From 738678e87be60a60d8fa4528b3004ae644e6586f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 8 Jan 2026 10:20:37 +1000 Subject: [PATCH 0001/2030] [image] Add define and core data (#13058) --- esphome/components/image/__init__.py | 51 ++++++++-- tests/component_tests/image/test_init.py | 117 ++++++++++++++++++++++- 2 files changed, 161 insertions(+), 7 deletions(-) diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index a7b788bf91..3f8d909824 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -1,6 +1,7 @@ from __future__ import annotations import contextlib +from dataclasses import dataclass import hashlib import io import logging @@ -37,11 +38,21 @@ image_ns = cg.esphome_ns.namespace("image") ImageType = image_ns.enum("ImageType") + +@dataclass(frozen=True) +class ImageMetaData: + width: int + height: int + image_type: str + transparency: str + + CONF_OPAQUE = "opaque" CONF_CHROMA_KEY = "chroma_key" CONF_ALPHA_CHANNEL = "alpha_channel" CONF_INVERT_ALPHA = "invert_alpha" CONF_IMAGES = "images" +KEY_METADATA = "metadata" TRANSPARENCY_TYPES = ( CONF_OPAQUE, @@ -723,10 +734,38 @@ async def write_image(config, all_frames=False): return prog_arr, width, height, image_type, trans_value, frame_count +async def _image_to_code(entry): + """ + Convert a single image entry to code and return its metadata. + :param entry: The config entry for the image. + :return: An ImageMetaData object + """ + prog_arr, width, height, image_type, trans_value, _ = await write_image(entry) + cg.new_Pvariable(entry[CONF_ID], prog_arr, width, height, image_type, trans_value) + return ImageMetaData( + width, + height, + entry[CONF_TYPE], + entry[CONF_TRANSPARENCY], + ) + + async def to_code(config): - # By now the config should be a simple list. - for entry in config: - prog_arr, width, height, image_type, trans_value, _ = await write_image(entry) - cg.new_Pvariable( - entry[CONF_ID], prog_arr, width, height, image_type, trans_value - ) + cg.add_define("USE_IMAGE") + # By now the config will be a simple list. + # Use a subkey to allow for other data in the future + CORE.data[DOMAIN] = { + KEY_METADATA: { + entry[CONF_ID].id: await _image_to_code(entry) for entry in config + } + } + + +def get_all_image_metadata() -> dict[str, ImageMetaData]: + """Get all image metadata.""" + return CORE.data.get(DOMAIN, {}).get(KEY_METADATA, {}) + + +def get_image_metadata(image_id: str) -> ImageMetaData | None: + """Get image metadata by ID for use by other components.""" + return get_all_image_metadata().get(image_id) diff --git a/tests/component_tests/image/test_init.py b/tests/component_tests/image/test_init.py index f0b132cef8..930bbac8d1 100644 --- a/tests/component_tests/image/test_init.py +++ b/tests/component_tests/image/test_init.py @@ -9,8 +9,14 @@ from typing import Any import pytest from esphome import config_validation as cv -from esphome.components.image import CONF_TRANSPARENCY, CONFIG_SCHEMA +from esphome.components.image import ( + CONF_TRANSPARENCY, + CONFIG_SCHEMA, + get_all_image_metadata, + get_image_metadata, +) from esphome.const import CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE +from esphome.core import CORE @pytest.mark.parametrize( @@ -235,3 +241,112 @@ def test_image_generation( "cat_img = new image::Image(uint8_t_id, 32, 24, image::IMAGE_TYPE_RGB565, image::TRANSPARENCY_OPAQUE);" in main_cpp ) + + +def test_image_to_code_defines_and_core_data( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that to_code() sets USE_IMAGE define and stores image metadata.""" + # Generate the main cpp which will call to_code + generate_main(component_config_path("image_test.yaml")) + + # Verify USE_IMAGE define was added + assert any(d.name == "USE_IMAGE" for d in CORE.defines), ( + "USE_IMAGE define should be set when images are configured" + ) + + # Use the public API to get image metadata + # The test config has an image with id 'cat_img' + cat_img_metadata = get_image_metadata("cat_img") + + assert cat_img_metadata is not None, ( + "Image metadata should be retrievable via get_image_metadata()" + ) + + # Verify the metadata has the expected attributes + assert hasattr(cat_img_metadata, "width"), "Metadata should have width attribute" + assert hasattr(cat_img_metadata, "height"), "Metadata should have height attribute" + assert hasattr(cat_img_metadata, "image_type"), ( + "Metadata should have image_type attribute" + ) + assert hasattr(cat_img_metadata, "transparency"), ( + "Metadata should have transparency attribute" + ) + + # Verify the values are correct (from the test image) + assert cat_img_metadata.width == 32, "Width should be 32" + assert cat_img_metadata.height == 24, "Height should be 24" + assert cat_img_metadata.image_type == "RGB565", "Type should be RGB565" + assert cat_img_metadata.transparency == "opaque", "Transparency should be opaque" + + +def test_image_to_code_multiple_images( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that to_code() stores metadata for multiple images.""" + generate_main(component_config_path("image_test.yaml")) + + # Use the public API to get all image metadata + all_metadata = get_all_image_metadata() + + assert isinstance(all_metadata, dict), ( + "get_all_image_metadata() should return a dictionary" + ) + + # Verify that at least one image is present + assert len(all_metadata) > 0, "Should have at least one image metadata entry" + + # Each image ID should map to an ImageMetaData object + for image_id, metadata in all_metadata.items(): + assert isinstance(image_id, str), "Image IDs should be strings" + + # Verify it's an ImageMetaData object with all required attributes + assert hasattr(metadata, "width"), ( + f"Metadata for '{image_id}' should have width" + ) + assert hasattr(metadata, "height"), ( + f"Metadata for '{image_id}' should have height" + ) + assert hasattr(metadata, "image_type"), ( + f"Metadata for '{image_id}' should have image_type" + ) + assert hasattr(metadata, "transparency"), ( + f"Metadata for '{image_id}' should have transparency" + ) + + # Verify values are valid + assert isinstance(metadata.width, int), ( + f"Width for '{image_id}' should be an integer" + ) + assert isinstance(metadata.height, int), ( + f"Height for '{image_id}' should be an integer" + ) + assert isinstance(metadata.image_type, str), ( + f"Type for '{image_id}' should be a string" + ) + assert isinstance(metadata.transparency, str), ( + f"Transparency for '{image_id}' should be a string" + ) + assert metadata.width > 0, f"Width for '{image_id}' should be positive" + assert metadata.height > 0, f"Height for '{image_id}' should be positive" + + +def test_get_image_metadata_nonexistent() -> None: + """Test that get_image_metadata returns None for non-existent image IDs.""" + # This should return None when no images are configured or ID doesn't exist + metadata = get_image_metadata("nonexistent_image_id") + assert metadata is None, ( + "get_image_metadata should return None for non-existent IDs" + ) + + +def test_get_all_image_metadata_empty() -> None: + """Test that get_all_image_metadata returns empty dict when no images configured.""" + # When CORE hasn't been initialized with images, should return empty dict + all_metadata = get_all_image_metadata() + assert isinstance(all_metadata, dict), ( + "get_all_image_metadata should always return a dict" + ) + # Length could be 0 or more depending on what's in CORE at test time From e301b8d0e0af68502adb73952c79abae36b20522 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 7 Jan 2026 21:44:10 -0600 Subject: [PATCH 0002/2030] [thermostat] Allow `heat_cool_mode` without an automation (#13069) Co-authored-by: J. Nick Koston --- esphome/components/thermostat/climate.py | 25 ++++++++++++++++++------ tests/components/thermostat/common.yaml | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index a3c155aac0..f7c1298d68 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -153,6 +153,19 @@ def generate_comparable_preset(config, name): return comparable_preset +def validate_heat_cool_mode(value) -> list: + """Validate heat_cool_mode - accepts either True or an automation.""" + if value is True: + # Convert True to empty automation list + return [] + if value is False: + raise cv.Invalid( + "heat_cool_mode cannot be 'false'. Specify 'true' to enable the mode or provide an automation" + ) + # Otherwise validate as automation + return automation.validate_automation(single=True)(value) + + def validate_thermostat(config): # verify corresponding action(s) exist(s) for any defined climate mode or action requirements = { @@ -554,9 +567,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_FAN_ONLY_MODE): automation.validate_automation( single=True ), - cv.Optional(CONF_HEAT_COOL_MODE): automation.validate_automation( - single=True - ), + cv.Optional(CONF_HEAT_COOL_MODE): validate_heat_cool_mode, cv.Optional(CONF_HEAT_MODE): automation.validate_automation(single=True), cv.Optional(CONF_OFF_MODE): automation.validate_automation(single=True), cv.Optional(CONF_FAN_MODE_ON_ACTION): automation.validate_automation( @@ -828,9 +839,11 @@ async def to_code(config): ) cg.add(var.set_supports_heat(True)) if CONF_HEAT_COOL_MODE in config: - await automation.build_automation( - var.get_heat_cool_mode_trigger(), [], config[CONF_HEAT_COOL_MODE] - ) + # Build automation only if user provided actions (not just `true`) + if config[CONF_HEAT_COOL_MODE]: + await automation.build_automation( + var.get_heat_cool_mode_trigger(), [], config[CONF_HEAT_COOL_MODE] + ) cg.add(var.set_supports_heat_cool(True)) if CONF_OFF_MODE in config: await automation.build_automation( diff --git a/tests/components/thermostat/common.yaml b/tests/components/thermostat/common.yaml index 4aa87c0ac3..63bd174e14 100644 --- a/tests/components/thermostat/common.yaml +++ b/tests/components/thermostat/common.yaml @@ -41,6 +41,7 @@ climate: - logger.log: dry_mode fan_only_mode: - logger.log: fan_only_mode + heat_cool_mode: true fan_mode_auto_action: - logger.log: fan_mode_auto_action fan_mode_on_action: From da0b01f4d01a81db99fbed91d5fb9e0c5ac31a13 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 10:51:18 -1000 Subject: [PATCH 0003/2030] [logger] Enable loop disable optimization for LibreTiny task log buffer (#13078) --- esphome/components/logger/logger.cpp | 6 +++--- esphome/components/logger/logger.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index bb00a230ee..1b41bc3d47 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -197,8 +197,8 @@ void Logger::init_log_buffer(size_t total_buffer_size) { this->log_buffer_ = esphome::make_unique(total_buffer_size); #endif -#ifdef USE_ESP32 - // Start with loop disabled when using task buffer (unless using USB CDC) +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Start with loop disabled when using task buffer (unless using USB CDC on ESP32) // The loop will be enabled automatically when messages arrive this->disable_loop_when_buffer_empty_(); #endif @@ -247,7 +247,7 @@ void Logger::process_messages_() { } #endif } -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_LIBRETINY) else { // No messages to process, disable loop if appropriate // This reduces overhead when there's no async logging activity diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 79299c2b1c..c58ca8ddce 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -609,8 +609,8 @@ class Logger : public Component { this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size); } -#ifdef USE_ESP32 - // Disable loop when task buffer is empty (with USB CDC check) +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Disable loop when task buffer is empty (with USB CDC check on ESP32) inline void disable_loop_when_buffer_empty_() { // Thread safety note: This is safe even if another task calls enable_loop_soon_any_context() // concurrently. If that happens between our check and disable_loop(), the enable request From c9ab4ca0181df99681fbea08e74bbf8fa88ec884 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 10:51:35 -1000 Subject: [PATCH 0004/2030] [libretiny] Bump to 1.9.2 (#13077) --- .clang-tidy.hash | 2 +- esphome/components/libretiny/__init__.py | 6 +++--- platformio.ini | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 0a71b6859f..9661c2ca02 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -191a0e6ab5842d153dd77a2023bc5742f9d4333c334de8d81b57f2b8d4d4b65e +d272a88e8ca28ae9340a9a03295a566432a52cb696501908f57764475bf7ca65 diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 93b66888da..4c8a1999f9 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -174,9 +174,9 @@ def _notify_old_style(config): # The dev and latest branches will be at *least* this version, which is what matters. ARDUINO_VERSIONS = { - "dev": (cv.Version(1, 9, 1), "https://github.com/libretiny-eu/libretiny.git"), - "latest": (cv.Version(1, 9, 1), "libretiny"), - "recommended": (cv.Version(1, 9, 1), None), + "dev": (cv.Version(1, 9, 2), "https://github.com/libretiny-eu/libretiny.git"), + "latest": (cv.Version(1, 9, 2), "libretiny"), + "recommended": (cv.Version(1, 9, 2), None), } diff --git a/platformio.ini b/platformio.ini index d96e9ad2cc..4180971b54 100644 --- a/platformio.ini +++ b/platformio.ini @@ -212,7 +212,7 @@ build_unflags = ; This are common settings for the LibreTiny (all variants) using Arduino. [common:libretiny-arduino] extends = common:arduino -platform = libretiny@1.9.1 +platform = libretiny@1.9.2 framework = arduino lib_compat_mode = soft lib_deps = From eb5c4f34e2199fe3de3bab7f875be57a4653d29d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 10:51:58 -1000 Subject: [PATCH 0005/2030] [wifi] Disable SoftAP support on Arduino ESP32 when ap: not configured (#13076) --- esphome/components/wifi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 824944d4a2..7ba1b5e417 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -466,7 +466,7 @@ async def to_code(config): ) cg.add(var.set_ap_timeout(conf[CONF_AP_TIMEOUT])) cg.add_define("USE_WIFI_AP") - elif CORE.is_esp32 and not CORE.using_arduino: + elif CORE.is_esp32: add_idf_sdkconfig_option("CONFIG_ESP_WIFI_SOFTAP_SUPPORT", False) add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False) From 423a617b156e5d03716d8cb3ba5e616645c1767c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 10:52:27 -1000 Subject: [PATCH 0006/2030] [core] Improve minimum_chip_revision warning for PSRAM users (#13074) --- esphome/core/application.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index f8fa3b333e..55eb25ce09 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -215,8 +215,13 @@ void Application::loop() { #if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET) // Suggest optimization for chips that don't need the PSRAM cache workaround if (chip_info.revision >= 300) { +#ifdef USE_PSRAM + ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to save ~10KB IRAM", chip_info.revision / 100, + chip_info.revision % 100); +#else ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to reduce binary size", chip_info.revision / 100, chip_info.revision % 100); +#endif } #endif #endif From 325c9380749d1a7344cf52ce606ef7454a1dd2e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:57:30 +0000 Subject: [PATCH 0007/2030] Bump ruff from 0.14.10 to 0.14.11 (#13082) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index de7d30cfa2..3295cf070a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.14.10 + rev: v0.14.11 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index f00bcd0a0d..092a06fd66 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.10 # also change in .pre-commit-config.yaml when updating +ruff==0.14.11 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From 52459d1bc7144d10a1bd63fdd6820d7b00ae7614 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 11:42:06 -1000 Subject: [PATCH 0008/2030] [wifi] Fix infinite roaming when best-signal AP is crashed/broken (#13071) --- esphome/components/wifi/wifi_component.cpp | 146 ++++++++++++--------- esphome/components/wifi/wifi_component.h | 15 ++- 2 files changed, 96 insertions(+), 65 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 6654474329..afdaa0b6e8 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -151,48 +151,51 @@ static const char *const TAG = "wifi"; /// │ Purpose: Handle AP reboot or power loss scenarios where device │ /// │ connects to suboptimal AP and never switches back │ /// │ │ -/// │ Loop call site: roaming enabled && attempts < 3 && 5 min elapsed │ -/// │ ↓ │ -/// │ ┌─────────────────┐ Hidden? ┌──────────────────────────┐ │ -/// │ │ check_roaming_ ├───────────→│ attempts = MAX, stop │ │ -/// │ └────────┬────────┘ └──────────────────────────┘ │ -/// │ ↓ │ -/// │ attempts++, update last_check │ -/// │ ↓ │ -/// │ RSSI > -49 dBm? ────Yes────→ Skip scan (excellent signal)─┐ │ -/// │ ↓ No │ │ -/// │ ┌─────────────────┐ │ │ -/// │ │ Start scan │ │ │ -/// │ └────────┬────────┘ │ │ -/// │ ↓ │ │ -/// │ ┌────────────────────────┐ │ │ -/// │ │ process_roaming_scan_ │ │ │ -/// │ └────────┬───────────────┘ │ │ -/// │ ↓ │ │ -/// │ ┌─────────────────┐ No ┌───────────────┐ │ │ -/// │ │ +10 dB better AP├────────→│ Stay connected│───────────────┤ │ -/// │ └────────┬────────┘ └───────────────┘ │ │ -/// │ │ Yes │ │ -/// │ ↓ │ │ -/// │ ┌─────────────────┐ │ │ -/// │ │ start_connecting│ (roaming_connect_active_ = true) │ │ -/// │ └────────┬────────┘ │ │ -/// │ ↓ │ │ -/// │ ┌────┴────┐ │ │ -/// │ ↓ ↓ │ │ -/// │ ┌───────┐ ┌───────┐ │ │ -/// │ │SUCCESS│ │FAILED │ │ │ -/// │ └───┬───┘ └───┬───┘ │ │ -/// │ ↓ ↓ │ │ -/// │ Keep counter retry_connect() → normal reconnect flow │ │ -/// │ (no reset) (keeps counter, handles retries) │ │ -/// │ │ │ │ │ -/// │ └──────────────┴────────────────────────────────────────┘ │ +/// │ State Machine (RoamingState): │ /// │ │ -/// │ After 3 checks: attempts >= 3, stop checking │ -/// │ Non-roaming disconnect: clear_roaming_state_() resets counter │ -/// │ Roaming success: counter preserved (prevents ping-pong) │ -/// │ Roaming fail: normal flow handles reconnection, counter preserved │ +/// │ ┌─────────────────────────────────────────────────────────────┐ │ +/// │ │ IDLE │ │ +/// │ │ (waiting for 5 min timer, attempts < 3) │ │ +/// │ └─────────────────────────┬───────────────────────────────────┘ │ +/// │ │ 5 min elapsed, RSSI < -49 dBm │ +/// │ ↓ │ +/// │ ┌─────────────────────────────────────────────────────────────┐ │ +/// │ │ SCANNING │ │ +/// │ │ (attempts++ in check_roaming_ before entering this state) │ │ +/// │ └─────────────────────────┬───────────────────────────────────┘ │ +/// │ │ │ +/// │ ┌──────────────┼──────────────┐ │ +/// │ ↓ ↓ ↓ │ +/// │ scan error no better AP +10 dB better AP │ +/// │ │ │ │ │ +/// │ ↓ ↓ ↓ │ +/// │ ┌──────────────────────────────┐ ┌──────────────────────────┐ │ +/// │ │ → IDLE │ │ CONNECTING │ │ +/// │ │ (counter preserved) │ │ (process_roaming_scan_) │ │ +/// │ └──────────────────────────────┘ └────────────┬─────────────┘ │ +/// │ │ │ +/// │ ┌───────────────────┴───────────────┐ │ +/// │ ↓ ↓ │ +/// │ SUCCESS FAILED │ +/// │ │ │ │ +/// │ ↓ ↓ │ +/// │ ┌──────────────────────────────────┐ ┌─────────────────────────┐ +/// │ │ → IDLE │ │ RECONNECTING │ +/// │ │ (counter reset to 0) │ │ (retry_connect called) │ +/// │ └──────────────────────────────────┘ └───────────┬─────────────┘ +/// │ │ │ +/// │ ↓ │ +/// │ ┌───────────────────────┐ │ +/// │ │ → IDLE │ │ +/// │ │ (counter preserved!) │ │ +/// │ └───────────────────────┘ │ +/// │ │ +/// │ Key behaviors: │ +/// │ - After 3 checks: attempts >= 3, stop checking │ +/// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │ +/// │ - Scan error (SCANNING→IDLE): counter preserved │ +/// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │ +/// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ /// └──────────────────────────────────────────────────────────────────────┘ static const LogString *retry_phase_to_log_string(WiFiRetryPhase phase) { @@ -574,12 +577,12 @@ void WiFiComponent::loop() { // Post-connect roaming: check for better AP if (this->post_connect_roaming_) { - if (this->roaming_scan_active_) { + if (this->roaming_state_ == RoamingState::SCANNING) { if (this->scan_done_) { this->process_roaming_scan_(); } // else: scan in progress, wait - } else if (this->roaming_attempts_ < ROAMING_MAX_ATTEMPTS && + } else if (this->roaming_state_ == RoamingState::IDLE && this->roaming_attempts_ < ROAMING_MAX_ATTEMPTS && now - this->roaming_last_check_ >= ROAMING_CHECK_INTERVAL) { this->check_roaming_(now); } @@ -1302,12 +1305,20 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { // Reset roaming state on successful connection this->roaming_last_check_ = now; - // Only reset attempts if this wasn't a roaming-triggered connection - // (prevents ping-pong between APs) - if (!this->roaming_connect_active_) { + // Only preserve attempts if reconnecting after a failed roam attempt + // This prevents ping-pong between APs when a roam target is unreachable + if (this->roaming_state_ == RoamingState::CONNECTING) { + // Successful roam to better AP - reset attempts so we can roam again later + ESP_LOGD(TAG, "Roam successful"); + this->roaming_attempts_ = 0; + } else if (this->roaming_state_ == RoamingState::RECONNECTING) { + // Failed roam, reconnected via normal recovery - keep attempts to prevent ping-pong + ESP_LOGD(TAG, "Reconnected after failed roam (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + } else { + // Normal connection (boot, credentials changed, etc.) this->roaming_attempts_ = 0; } - this->roaming_connect_active_ = false; + this->roaming_state_ = RoamingState::IDLE; // Clear all priority penalties - the next reconnect will happen when an AP disconnects, // which means the landscape has likely changed and previous tracked failures are stale @@ -1733,16 +1744,21 @@ void WiFiComponent::advance_to_next_target_or_increment_retry_() { } void WiFiComponent::retry_connect() { - // If this was a roaming attempt, preserve roaming_attempts_ count - // (so we stop roaming after ROAMING_MAX_ATTEMPTS failures) - // Otherwise reset all roaming state - if (this->roaming_connect_active_) { - this->roaming_connect_active_ = false; - this->roaming_scan_active_ = false; - // Keep roaming_attempts_ - will prevent further roaming after max failures - } else { + // Handle roaming state transitions - preserve attempts counter to prevent ping-pong + // to unreachable APs after ROAMING_MAX_ATTEMPTS failures + if (this->roaming_state_ == RoamingState::CONNECTING) { + // Roam connection failed - transition to reconnecting + ESP_LOGD(TAG, "Roam failed, reconnecting (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::RECONNECTING; + } else if (this->roaming_state_ == RoamingState::SCANNING) { + // Roam scan failed (e.g., scan error on ESP8266) - go back to idle, keep counter + ESP_LOGD(TAG, "Roam scan failed (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::IDLE; + } else if (this->roaming_state_ == RoamingState::IDLE) { + // Not a roaming-triggered reconnect, reset state this->clear_roaming_state_(); } + // RECONNECTING: keep state and counter, still trying to reconnect this->log_and_adjust_priority_for_failed_connect_(); @@ -1989,8 +2005,7 @@ bool WiFiScanResult::operator==(const WiFiScanResult &rhs) const { return this-> void WiFiComponent::clear_roaming_state_() { this->roaming_attempts_ = 0; this->roaming_last_check_ = 0; - this->roaming_scan_active_ = false; - this->roaming_connect_active_ = false; + this->roaming_state_ = RoamingState::IDLE; } void WiFiComponent::release_scan_results_() { @@ -2018,17 +2033,21 @@ void WiFiComponent::check_roaming_(uint32_t now) { // Guard: skip scan if signal is already good (no meaningful improvement possible) int8_t rssi = this->wifi_rssi(); - if (rssi > ROAMING_GOOD_RSSI) + if (rssi > ROAMING_GOOD_RSSI) { + ESP_LOGV(TAG, "Roam check skipped, signal good (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, + ROAMING_MAX_ATTEMPTS); return; + } - ESP_LOGD(TAG, "Roam scan (%d dBm)", rssi); - this->roaming_scan_active_ = true; + ESP_LOGD(TAG, "Roam scan (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::SCANNING; this->wifi_scan_start_(this->passive_scan_); } void WiFiComponent::process_roaming_scan_() { this->scan_done_ = false; - this->roaming_scan_active_ = false; + // Default to IDLE - will be set to CONNECTING if we find a better AP + this->roaming_state_ = RoamingState::IDLE; // Get current connection info int8_t current_rssi = this->wifi_rssi(); @@ -2066,7 +2085,8 @@ void WiFiComponent::process_roaming_scan_() { const WiFiAP *selected = this->get_selected_sta_(); int8_t improvement = (best == nullptr) ? 0 : best->get_rssi() - current_rssi; if (selected == nullptr || improvement < ROAMING_MIN_IMPROVEMENT) { - ESP_LOGV(TAG, "Roam best %+d dB (need +%d)", improvement, ROAMING_MIN_IMPROVEMENT); + ESP_LOGV(TAG, "Roam best %+d dB (need +%d), attempt %u/%u", improvement, ROAMING_MIN_IMPROVEMENT, + this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); this->release_scan_results_(); return; } @@ -2079,7 +2099,7 @@ void WiFiComponent::process_roaming_scan_() { this->release_scan_results_(); // Mark as roaming attempt - affects retry behavior if connection fails - this->roaming_connect_active_ = true; + this->roaming_state_ = RoamingState::CONNECTING; // Connect directly - wifi_sta_connect_ handles disconnect internally this->error_from_callback_ = false; diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 09af384725..9b606bd692 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -112,6 +112,18 @@ enum class WiFiRetryPhase : uint8_t { RESTARTING_ADAPTER, }; +/// Tracks post-connect roaming state machine +enum class RoamingState : uint8_t { + /// Not roaming, waiting for next check interval + IDLE, + /// Scanning for better AP + SCANNING, + /// Attempting to connect to better AP found in scan + CONNECTING, + /// Roam connection failed, reconnecting to any available AP + RECONNECTING, +}; + /// Struct for setting static IPs in WiFiComponent. struct ManualIP { network::IPAddress static_ip; @@ -667,8 +679,7 @@ class WiFiComponent : public Component { bool did_scan_this_cycle_{false}; bool skip_cooldown_next_cycle_{false}; bool post_connect_roaming_{true}; // Enabled by default - bool roaming_scan_active_{false}; - bool roaming_connect_active_{false}; // True during roaming connection attempt (preserves roaming_attempts_) + RoamingState roaming_state_{RoamingState::IDLE}; #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) WiFiPowerSaveMode configured_power_save_{WIFI_POWER_SAVE_NONE}; bool is_high_performance_mode_{false}; From 40f108116b0b4dd28f0bc701acb7138eb38145a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 11:42:18 -1000 Subject: [PATCH 0009/2030] [mqtt] Reduce heap allocations in topic string building (#13072) --- esphome/components/mqtt/__init__.py | 17 +++- .../mqtt/mqtt_alarm_control_panel.cpp | 2 +- .../mqtt/mqtt_alarm_control_panel.h | 2 +- .../components/mqtt/mqtt_binary_sensor.cpp | 2 +- esphome/components/mqtt/mqtt_binary_sensor.h | 2 +- esphome/components/mqtt/mqtt_button.cpp | 2 +- esphome/components/mqtt/mqtt_button.h | 2 +- esphome/components/mqtt/mqtt_climate.cpp | 2 +- esphome/components/mqtt/mqtt_climate.h | 2 +- esphome/components/mqtt/mqtt_component.cpp | 77 ++++++++++++++++--- esphome/components/mqtt/mqtt_component.h | 21 ++++- esphome/components/mqtt/mqtt_cover.cpp | 2 +- esphome/components/mqtt/mqtt_cover.h | 2 +- esphome/components/mqtt/mqtt_date.cpp | 2 +- esphome/components/mqtt/mqtt_date.h | 2 +- esphome/components/mqtt/mqtt_datetime.cpp | 2 +- esphome/components/mqtt/mqtt_datetime.h | 2 +- esphome/components/mqtt/mqtt_event.cpp | 2 +- esphome/components/mqtt/mqtt_event.h | 2 +- esphome/components/mqtt/mqtt_fan.cpp | 2 +- esphome/components/mqtt/mqtt_fan.h | 2 +- esphome/components/mqtt/mqtt_light.cpp | 2 +- esphome/components/mqtt/mqtt_light.h | 2 +- esphome/components/mqtt/mqtt_lock.cpp | 2 +- esphome/components/mqtt/mqtt_lock.h | 2 +- esphome/components/mqtt/mqtt_number.cpp | 2 +- esphome/components/mqtt/mqtt_number.h | 2 +- esphome/components/mqtt/mqtt_select.cpp | 2 +- esphome/components/mqtt/mqtt_select.h | 2 +- esphome/components/mqtt/mqtt_sensor.cpp | 2 +- esphome/components/mqtt/mqtt_sensor.h | 2 +- esphome/components/mqtt/mqtt_switch.cpp | 2 +- esphome/components/mqtt/mqtt_switch.h | 2 +- esphome/components/mqtt/mqtt_text.cpp | 2 +- esphome/components/mqtt/mqtt_text.h | 2 +- esphome/components/mqtt/mqtt_text_sensor.cpp | 2 +- esphome/components/mqtt/mqtt_text_sensor.h | 2 +- esphome/components/mqtt/mqtt_time.cpp | 2 +- esphome/components/mqtt/mqtt_time.h | 2 +- esphome/components/mqtt/mqtt_update.cpp | 2 +- esphome/components/mqtt/mqtt_update.h | 2 +- esphome/components/mqtt/mqtt_valve.cpp | 2 +- esphome/components/mqtt/mqtt_valve.h | 2 +- esphome/core/config.py | 2 + esphome/core/entity_base.h | 5 +- 45 files changed, 145 insertions(+), 57 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index e73de49fef..f01c928b30 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -77,6 +77,13 @@ CONF_DISCOVER_IP = "discover_ip" CONF_IDF_SEND_ASYNC = "idf_send_async" CONF_WAIT_FOR_CONNECTION = "wait_for_connection" +# Max lengths for stack-based topic building. +# These values are used in cv.Length() validators below to ensure the C++ code +# in mqtt_component.cpp can safely use fixed-size stack buffers without overflow. +# If you change these, update the corresponding constants in mqtt_component.cpp. +TOPIC_PREFIX_MAX_LEN = 64 # Default is device name, typically short +DISCOVERY_PREFIX_MAX_LEN = 64 # Default is "homeassistant" (13 chars) + def validate_message_just_topic(value): value = cv.publish_topic(value) @@ -253,9 +260,9 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_DISCOVERY_RETAIN, default=True): cv.boolean, cv.Optional(CONF_DISCOVER_IP, default=True): cv.boolean, - cv.Optional( - CONF_DISCOVERY_PREFIX, default="homeassistant" - ): cv.publish_topic, + cv.Optional(CONF_DISCOVERY_PREFIX, default="homeassistant"): cv.All( + cv.publish_topic, cv.Length(max=DISCOVERY_PREFIX_MAX_LEN) + ), cv.Optional(CONF_DISCOVERY_UNIQUE_ID_GENERATOR, default="legacy"): cv.enum( MQTT_DISCOVERY_UNIQUE_ID_GENERATOR_OPTIONS ), @@ -266,7 +273,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, - cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.publish_topic, + cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.All( + cv.publish_topic, cv.Length(max=TOPIC_PREFIX_MAX_LEN) + ), cv.Optional(CONF_LOG_TOPIC): cv.Any( None, MQTT_MESSAGE_BASE.extend( diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index eb46c3b10c..6245d10882 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -79,7 +79,7 @@ void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendD root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm(); } -std::string MQTTAlarmControlPanelComponent::component_type() const { return "alarm_control_panel"; } +MQTT_COMPONENT_TYPE(MQTTAlarmControlPanelComponent, "alarm_control_panel") const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return this->alarm_control_panel_; } bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.h b/esphome/components/mqtt/mqtt_alarm_control_panel.h index cf4fac1511..89a0ff1be8 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.h +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.h @@ -25,7 +25,7 @@ class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent { void dump_config() override; protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; alarm_control_panel::AlarmControlPanel *alarm_control_panel_; diff --git a/esphome/components/mqtt/mqtt_binary_sensor.cpp b/esphome/components/mqtt/mqtt_binary_sensor.cpp index 146ca46f68..a37043406b 100644 --- a/esphome/components/mqtt/mqtt_binary_sensor.cpp +++ b/esphome/components/mqtt/mqtt_binary_sensor.cpp @@ -10,7 +10,7 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt.binary_sensor"; -std::string MQTTBinarySensorComponent::component_type() const { return "binary_sensor"; } +MQTT_COMPONENT_TYPE(MQTTBinarySensorComponent, "binary_sensor") const EntityBase *MQTTBinarySensorComponent::get_entity() const { return this->binary_sensor_; } void MQTTBinarySensorComponent::setup() { diff --git a/esphome/components/mqtt/mqtt_binary_sensor.h b/esphome/components/mqtt/mqtt_binary_sensor.h index 82176ec97b..5917a9966c 100644 --- a/esphome/components/mqtt/mqtt_binary_sensor.h +++ b/esphome/components/mqtt/mqtt_binary_sensor.h @@ -29,7 +29,7 @@ class MQTTBinarySensorComponent : public mqtt::MQTTComponent { bool publish_state(bool state); protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; binary_sensor::BinarySensor *binary_sensor_; diff --git a/esphome/components/mqtt/mqtt_button.cpp b/esphome/components/mqtt/mqtt_button.cpp index 2b700a4962..718fe93016 100644 --- a/esphome/components/mqtt/mqtt_button.cpp +++ b/esphome/components/mqtt/mqtt_button.cpp @@ -39,7 +39,7 @@ void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) } -std::string MQTTButtonComponent::component_type() const { return "button"; } +MQTT_COMPONENT_TYPE(MQTTButtonComponent, "button") const EntityBase *MQTTButtonComponent::get_entity() const { return this->button_; } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_button.h b/esphome/components/mqtt/mqtt_button.h index ec802664df..a2db64d39d 100644 --- a/esphome/components/mqtt/mqtt_button.h +++ b/esphome/components/mqtt/mqtt_button.h @@ -26,7 +26,7 @@ class MQTTButtonComponent : public mqtt::MQTTComponent { protected: /// "button" component type. - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; button::Button *button_; diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index d402fff6e6..77aabb2461 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -254,7 +254,7 @@ void MQTTClimateComponent::setup() { } MQTTClimateComponent::MQTTClimateComponent(Climate *device) : device_(device) {} bool MQTTClimateComponent::send_initial_state() { return this->publish_state_(); } -std::string MQTTClimateComponent::component_type() const { return "climate"; } +MQTT_COMPONENT_TYPE(MQTTClimateComponent, "climate") const EntityBase *MQTTClimateComponent::get_entity() const { return this->device_; } bool MQTTClimateComponent::publish_state_() { diff --git a/esphome/components/mqtt/mqtt_climate.h b/esphome/components/mqtt/mqtt_climate.h index f561627ac9..f0715929d4 100644 --- a/esphome/components/mqtt/mqtt_climate.h +++ b/esphome/components/mqtt/mqtt_climate.h @@ -15,7 +15,7 @@ class MQTTClimateComponent : public mqtt::MQTTComponent { MQTTClimateComponent(climate::Climate *device); void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; bool send_initial_state() override; - std::string component_type() const override; + const char *component_type() const override; void setup() override; MQTT_COMPONENT_CUSTOM_TOPIC(current_temperature, state) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index ccbdb2ea91..d838d1789f 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -13,6 +13,34 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt.component"; +// Helper functions for building topic strings on stack +inline char *append_str(char *p, const char *s, size_t len) { + memcpy(p, s, len); + return p + len; +} + +inline char *append_char(char *p, char c) { + *p = c; + return p + 1; +} + +// Max lengths for stack-based topic building. +// These limits are enforced at Python config validation time in mqtt/__init__.py +// using cv.Length() validators for topic_prefix and discovery_prefix. +// MQTT_COMPONENT_TYPE_MAX_LEN and MQTT_SUFFIX_MAX_LEN are defined in mqtt_component.h. +// ESPHOME_DEVICE_NAME_MAX_LEN and OBJECT_ID_MAX_LEN are defined in entity_base.h. +// This ensures the stack buffers below are always large enough. +static constexpr size_t TOPIC_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) +static constexpr size_t DISCOVERY_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) + +// Stack buffer sizes - safe because all inputs are length-validated at config time +// Format: prefix + "/" + type + "/" + object_id + "/" + suffix + null +static constexpr size_t DEFAULT_TOPIC_MAX_LEN = + TOPIC_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1 + MQTT_SUFFIX_MAX_LEN + 1; +// Format: prefix + "/" + type + "/" + name + "/" + object_id + "/config" + null +static constexpr size_t DISCOVERY_TOPIC_MAX_LEN = DISCOVERY_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 7 + 1; + void MQTTComponent::set_qos(uint8_t qos) { this->qos_ = qos; } void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; } @@ -21,8 +49,23 @@ void MQTTComponent::set_retain(bool retain) { this->retain_ = retain; } std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const { std::string sanitized_name = str_sanitize(App.get_name()); - return discovery_info.prefix + "/" + this->component_type() + "/" + sanitized_name + "/" + - this->get_default_object_id_() + "/config"; + const char *comp_type = this->component_type(); + char object_id_buf[OBJECT_ID_MAX_LEN]; + StringRef object_id = this->get_default_object_id_to_(object_id_buf); + + char buf[DISCOVERY_TOPIC_MAX_LEN]; + char *p = buf; + + p = append_str(p, discovery_info.prefix.data(), discovery_info.prefix.size()); + p = append_char(p, '/'); + p = append_str(p, comp_type, strlen(comp_type)); + p = append_char(p, '/'); + p = append_str(p, sanitized_name.data(), sanitized_name.size()); + p = append_char(p, '/'); + p = append_str(p, object_id.c_str(), object_id.size()); + p = append_str(p, "/config", 7); + + return std::string(buf, p - buf); } std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) const { @@ -32,7 +75,22 @@ std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) con return ""; } - return topic_prefix + "/" + this->component_type() + "/" + this->get_default_object_id_() + "/" + suffix; + const char *comp_type = this->component_type(); + char object_id_buf[OBJECT_ID_MAX_LEN]; + StringRef object_id = this->get_default_object_id_to_(object_id_buf); + + char buf[DEFAULT_TOPIC_MAX_LEN]; + char *p = buf; + + p = append_str(p, topic_prefix.data(), topic_prefix.size()); + p = append_char(p, '/'); + p = append_str(p, comp_type, strlen(comp_type)); + p = append_char(p, '/'); + p = append_str(p, object_id.c_str(), object_id.size()); + p = append_char(p, '/'); + p = append_str(p, suffix.data(), suffix.size()); + + return std::string(buf, p - buf); } std::string MQTTComponent::get_state_topic_() const { @@ -123,6 +181,8 @@ bool MQTTComponent::send_discovery_() { } const MQTTDiscoveryInfo &discovery_info = global_mqtt_client->get_discovery_info(); + char object_id_buf[OBJECT_ID_MAX_LEN]; + StringRef object_id = this->get_default_object_id_to_(object_id_buf); if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) { char friendly_name_hash[9]; sprintf(friendly_name_hash, "%08" PRIx32, fnv1_hash(this->friendly_name_())); @@ -131,12 +191,12 @@ bool MQTTComponent::send_discovery_() { } else { // default to almost-unique ID. It's a hack but the only way to get that // gorgeous device registry view. - root[MQTT_UNIQUE_ID] = "ESP" + this->component_type() + this->get_default_object_id_(); + root[MQTT_UNIQUE_ID] = "ESP" + std::string(this->component_type()) + object_id.c_str(); } const std::string &node_name = App.get_name(); if (discovery_info.object_id_generator == MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR) - root[MQTT_OBJECT_ID] = node_name + "_" + this->get_default_object_id_(); + root[MQTT_OBJECT_ID] = node_name + "_" + object_id.c_str(); const std::string &friendly_name_ref = App.get_friendly_name(); const std::string &node_friendly_name = friendly_name_ref.empty() ? node_name : friendly_name_ref; @@ -194,10 +254,6 @@ bool MQTTComponent::is_discovery_enabled() const { return this->discovery_enabled_ && global_mqtt_client->is_discovery_enabled(); } -std::string MQTTComponent::get_default_object_id_() const { - return str_sanitize(str_snake_case(this->friendly_name_())); -} - void MQTTComponent::subscribe(const std::string &topic, mqtt_callback_t callback, uint8_t qos) { global_mqtt_client->subscribe(topic, std::move(callback), qos); } @@ -280,6 +336,9 @@ bool MQTTComponent::is_connected_() const { return global_mqtt_client->is_connec // Pull these properties from EntityBase if not overridden std::string MQTTComponent::friendly_name_() const { return this->get_entity()->get_name(); } +StringRef MQTTComponent::get_default_object_id_to_(std::span buf) const { + return this->get_entity()->get_object_id_to(buf); +} StringRef MQTTComponent::get_icon_ref_() const { return this->get_entity()->get_icon_ref(); } bool MQTTComponent::is_disabled_by_default_() const { return this->get_entity()->is_disabled_by_default(); } bool MQTTComponent::is_internal() { diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index e5f9664f77..e0b751f05f 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -19,6 +19,10 @@ struct SendDiscoveryConfig { bool command_topic{true}; ///< If the command topic should be included. Default to true. }; +// Max lengths for stack-based topic building (must match mqtt_component.cpp) +static constexpr size_t MQTT_COMPONENT_TYPE_MAX_LEN = 20; +static constexpr size_t MQTT_SUFFIX_MAX_LEN = 32; + #define LOG_MQTT_COMPONENT(state_topic, command_topic) \ if (state_topic) { \ ESP_LOGCONFIG(TAG, " State Topic: '%s'", this->get_state_topic_().c_str()); \ @@ -27,7 +31,18 @@ struct SendDiscoveryConfig { ESP_LOGCONFIG(TAG, " Command Topic: '%s'", this->get_command_topic_().c_str()); \ } +// Macro to define component_type() with compile-time length verification +// Usage: MQTT_COMPONENT_TYPE(MQTTSensorComponent, "sensor") +#define MQTT_COMPONENT_TYPE(class_name, type_str) \ + const char *class_name::component_type() const { return type_str; } \ + static_assert(sizeof(type_str) - 1 <= MQTT_COMPONENT_TYPE_MAX_LEN, \ + #class_name "::component_type() exceeds MQTT_COMPONENT_TYPE_MAX_LEN"); + +// Macro to define custom topic getter/setter with compile-time suffix length verification #define MQTT_COMPONENT_CUSTOM_TOPIC_(name, type) \ + static_assert(sizeof(#name "/" #type) - 1 <= MQTT_SUFFIX_MAX_LEN, \ + "topic suffix " #name "/" #type " exceeds MQTT_SUFFIX_MAX_LEN"); \ +\ protected: \ std::string custom_##name##_##type##_topic_{}; \ \ @@ -92,7 +107,7 @@ class MQTTComponent : public Component { void set_subscribe_qos(uint8_t qos); /// Override this method to return the component type (e.g. "light", "sensor", ...) - virtual std::string component_type() const = 0; + virtual const char *component_type() const = 0; /// Set a custom state topic. Set to "" for default behavior. void set_custom_state_topic(const char *custom_state_topic); @@ -185,8 +200,8 @@ class MQTTComponent : public Component { // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) - /// Generate the Home Assistant MQTT discovery object id by automatically transforming the friendly name. - std::string get_default_object_id_() const; + /// Get the object ID for this MQTT component, writing to the provided buffer. + StringRef get_default_object_id_to_(std::span buf) const; StringRef custom_state_topic_{}; StringRef custom_command_topic_{}; diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index e628ac37a9..4505027485 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -90,7 +90,7 @@ void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf } } -std::string MQTTCoverComponent::component_type() const { return "cover"; } +MQTT_COMPONENT_TYPE(MQTTCoverComponent, "cover") const EntityBase *MQTTCoverComponent::get_entity() const { return this->cover_; } bool MQTTCoverComponent::send_initial_state() { return this->publish_state(); } diff --git a/esphome/components/mqtt/mqtt_cover.h b/esphome/components/mqtt/mqtt_cover.h index 6b874af16a..13582d14d1 100644 --- a/esphome/components/mqtt/mqtt_cover.h +++ b/esphome/components/mqtt/mqtt_cover.h @@ -29,7 +29,7 @@ class MQTTCoverComponent : public mqtt::MQTTComponent { void dump_config() override; protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; cover::Cover *cover_; diff --git a/esphome/components/mqtt/mqtt_date.cpp b/esphome/components/mqtt/mqtt_date.cpp index 1715384c5f..dba7c1a671 100644 --- a/esphome/components/mqtt/mqtt_date.cpp +++ b/esphome/components/mqtt/mqtt_date.cpp @@ -39,7 +39,7 @@ void MQTTDateComponent::dump_config() { LOG_MQTT_COMPONENT(true, true) } -std::string MQTTDateComponent::component_type() const { return "date"; } +MQTT_COMPONENT_TYPE(MQTTDateComponent, "date") const EntityBase *MQTTDateComponent::get_entity() const { return this->date_; } void MQTTDateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_date.h b/esphome/components/mqtt/mqtt_date.h index 380bb69e0e..4a626becb2 100644 --- a/esphome/components/mqtt/mqtt_date.h +++ b/esphome/components/mqtt/mqtt_date.h @@ -31,7 +31,7 @@ class MQTTDateComponent : public mqtt::MQTTComponent { bool publish_state(uint16_t year, uint8_t month, uint8_t day); protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; datetime::DateEntity *date_; diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp index 79a2c82180..5f1cf19b97 100644 --- a/esphome/components/mqtt/mqtt_datetime.cpp +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -50,7 +50,7 @@ void MQTTDateTimeComponent::dump_config() { LOG_MQTT_COMPONENT(true, true) } -std::string MQTTDateTimeComponent::component_type() const { return "datetime"; } +MQTT_COMPONENT_TYPE(MQTTDateTimeComponent, "datetime") const EntityBase *MQTTDateTimeComponent::get_entity() const { return this->datetime_; } void MQTTDateTimeComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_datetime.h b/esphome/components/mqtt/mqtt_datetime.h index 8706bfcf75..d02d6f579c 100644 --- a/esphome/components/mqtt/mqtt_datetime.h +++ b/esphome/components/mqtt/mqtt_datetime.h @@ -31,7 +31,7 @@ class MQTTDateTimeComponent : public mqtt::MQTTComponent { bool publish_state(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; datetime::DateTimeEntity *datetime_; diff --git a/esphome/components/mqtt/mqtt_event.cpp b/esphome/components/mqtt/mqtt_event.cpp index 67a7aab5bd..42fbc1eabd 100644 --- a/esphome/components/mqtt/mqtt_event.cpp +++ b/esphome/components/mqtt/mqtt_event.cpp @@ -50,7 +50,7 @@ bool MQTTEventComponent::publish_event_(const std::string &event_type) { }); } -std::string MQTTEventComponent::component_type() const { return "event"; } +MQTT_COMPONENT_TYPE(MQTTEventComponent, "event") const EntityBase *MQTTEventComponent::get_entity() const { return this->event_; } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_event.h b/esphome/components/mqtt/mqtt_event.h index fc6e778d44..e6d5b6f278 100644 --- a/esphome/components/mqtt/mqtt_event.h +++ b/esphome/components/mqtt/mqtt_event.h @@ -25,7 +25,7 @@ class MQTTEventComponent : public mqtt::MQTTComponent { protected: bool publish_event_(const std::string &event_type); - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; event::Event *event_; diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index ffecd9c663..bd6c98b679 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -15,7 +15,7 @@ using namespace esphome::fan; MQTTFanComponent::MQTTFanComponent(Fan *state) : state_(state) {} Fan *MQTTFanComponent::get_state() const { return this->state_; } -std::string MQTTFanComponent::component_type() const { return "fan"; } +MQTT_COMPONENT_TYPE(MQTTFanComponent, "fan") const EntityBase *MQTTFanComponent::get_entity() const { return this->state_; } void MQTTFanComponent::setup() { diff --git a/esphome/components/mqtt/mqtt_fan.h b/esphome/components/mqtt/mqtt_fan.h index 16ce246853..43ef67e733 100644 --- a/esphome/components/mqtt/mqtt_fan.h +++ b/esphome/components/mqtt/mqtt_fan.h @@ -36,7 +36,7 @@ class MQTTFanComponent : public mqtt::MQTTComponent { bool send_initial_state() override; bool publish_state(); /// 'fan' component type for discovery. - std::string component_type() const override; + const char *component_type() const override; fan::Fan *get_state() const; diff --git a/esphome/components/mqtt/mqtt_light.cpp b/esphome/components/mqtt/mqtt_light.cpp index 0dafe487ff..2d588ed10b 100644 --- a/esphome/components/mqtt/mqtt_light.cpp +++ b/esphome/components/mqtt/mqtt_light.cpp @@ -14,7 +14,7 @@ static const char *const TAG = "mqtt.light"; using namespace esphome::light; -std::string MQTTJSONLightComponent::component_type() const { return "light"; } +MQTT_COMPONENT_TYPE(MQTTJSONLightComponent, "light") const EntityBase *MQTTJSONLightComponent::get_entity() const { return this->state_; } void MQTTJSONLightComponent::setup() { diff --git a/esphome/components/mqtt/mqtt_light.h b/esphome/components/mqtt/mqtt_light.h index 2cc631c901..41981655ef 100644 --- a/esphome/components/mqtt/mqtt_light.h +++ b/esphome/components/mqtt/mqtt_light.h @@ -28,7 +28,7 @@ class MQTTJSONLightComponent : public mqtt::MQTTComponent, public light::LightRe void on_light_remote_values_update() override; protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; bool publish_state_(); diff --git a/esphome/components/mqtt/mqtt_lock.cpp b/esphome/components/mqtt/mqtt_lock.cpp index 58fa675eb7..43ef60bdf4 100644 --- a/esphome/components/mqtt/mqtt_lock.cpp +++ b/esphome/components/mqtt/mqtt_lock.cpp @@ -34,7 +34,7 @@ void MQTTLockComponent::dump_config() { LOG_MQTT_COMPONENT(true, true); } -std::string MQTTLockComponent::component_type() const { return "lock"; } +MQTT_COMPONENT_TYPE(MQTTLockComponent, "lock") const EntityBase *MQTTLockComponent::get_entity() const { return this->lock_; } void MQTTLockComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson diff --git a/esphome/components/mqtt/mqtt_lock.h b/esphome/components/mqtt/mqtt_lock.h index 6fb4998b25..666882c73d 100644 --- a/esphome/components/mqtt/mqtt_lock.h +++ b/esphome/components/mqtt/mqtt_lock.h @@ -27,7 +27,7 @@ class MQTTLockComponent : public mqtt::MQTTComponent { protected: /// "lock" component type. - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; lock::Lock *lock_; diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index 381574ae56..8342210ee4 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -33,7 +33,7 @@ void MQTTNumberComponent::dump_config() { LOG_MQTT_COMPONENT(true, false) } -std::string MQTTNumberComponent::component_type() const { return "number"; } +MQTT_COMPONENT_TYPE(MQTTNumberComponent, "number") const EntityBase *MQTTNumberComponent::get_entity() const { return this->number_; } void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_number.h b/esphome/components/mqtt/mqtt_number.h index b89e78a454..021a539988 100644 --- a/esphome/components/mqtt/mqtt_number.h +++ b/esphome/components/mqtt/mqtt_number.h @@ -32,7 +32,7 @@ class MQTTNumberComponent : public mqtt::MQTTComponent { protected: /// Override for MQTTComponent, returns "number". - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; number::Number *number_; diff --git a/esphome/components/mqtt/mqtt_select.cpp b/esphome/components/mqtt/mqtt_select.cpp index 5edc5c50dc..09d90ed46e 100644 --- a/esphome/components/mqtt/mqtt_select.cpp +++ b/esphome/components/mqtt/mqtt_select.cpp @@ -28,7 +28,7 @@ void MQTTSelectComponent::dump_config() { LOG_MQTT_COMPONENT(true, false) } -std::string MQTTSelectComponent::component_type() const { return "select"; } +MQTT_COMPONENT_TYPE(MQTTSelectComponent, "select") const EntityBase *MQTTSelectComponent::get_entity() const { return this->select_; } void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_select.h b/esphome/components/mqtt/mqtt_select.h index 19aad662e5..aaf174ff72 100644 --- a/esphome/components/mqtt/mqtt_select.h +++ b/esphome/components/mqtt/mqtt_select.h @@ -32,7 +32,7 @@ class MQTTSelectComponent : public mqtt::MQTTComponent { protected: /// Override for MQTTComponent, returns "select". - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; select::Select *select_; diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index bd79ae40fe..14eb160e72 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -31,7 +31,7 @@ void MQTTSensorComponent::dump_config() { LOG_MQTT_COMPONENT(true, false) } -std::string MQTTSensorComponent::component_type() const { return "sensor"; } +MQTT_COMPONENT_TYPE(MQTTSensorComponent, "sensor") const EntityBase *MQTTSensorComponent::get_entity() const { return this->sensor_; } uint32_t MQTTSensorComponent::get_expire_after() const { diff --git a/esphome/components/mqtt/mqtt_sensor.h b/esphome/components/mqtt/mqtt_sensor.h index 8c60199e1b..e8202aa8e2 100644 --- a/esphome/components/mqtt/mqtt_sensor.h +++ b/esphome/components/mqtt/mqtt_sensor.h @@ -43,7 +43,7 @@ class MQTTSensorComponent : public mqtt::MQTTComponent { protected: /// Override for MQTTComponent, returns "sensor". - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; sensor::Sensor *sensor_; diff --git a/esphome/components/mqtt/mqtt_switch.cpp b/esphome/components/mqtt/mqtt_switch.cpp index a35ae8f9b6..a985ec66be 100644 --- a/esphome/components/mqtt/mqtt_switch.cpp +++ b/esphome/components/mqtt/mqtt_switch.cpp @@ -41,7 +41,7 @@ void MQTTSwitchComponent::dump_config() { LOG_MQTT_COMPONENT(true, true); } -std::string MQTTSwitchComponent::component_type() const { return "switch"; } +MQTT_COMPONENT_TYPE(MQTTSwitchComponent, "switch") const EntityBase *MQTTSwitchComponent::get_entity() const { return this->switch_; } void MQTTSwitchComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson diff --git a/esphome/components/mqtt/mqtt_switch.h b/esphome/components/mqtt/mqtt_switch.h index fb6a13f172..5f6cb841fd 100644 --- a/esphome/components/mqtt/mqtt_switch.h +++ b/esphome/components/mqtt/mqtt_switch.h @@ -27,7 +27,7 @@ class MQTTSwitchComponent : public mqtt::MQTTComponent { protected: /// "switch" component type. - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; switch_::Switch *switch_; diff --git a/esphome/components/mqtt/mqtt_text.cpp b/esphome/components/mqtt/mqtt_text.cpp index 3cb851fd38..cee94965c6 100644 --- a/esphome/components/mqtt/mqtt_text.cpp +++ b/esphome/components/mqtt/mqtt_text.cpp @@ -29,7 +29,7 @@ void MQTTTextComponent::dump_config() { LOG_MQTT_COMPONENT(true, true) } -std::string MQTTTextComponent::component_type() const { return "text"; } +MQTT_COMPONENT_TYPE(MQTTTextComponent, "text") const EntityBase *MQTTTextComponent::get_entity() const { return this->text_; } void MQTTTextComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_text.h b/esphome/components/mqtt/mqtt_text.h index 0480b89395..8ae0b9e29a 100644 --- a/esphome/components/mqtt/mqtt_text.h +++ b/esphome/components/mqtt/mqtt_text.h @@ -32,7 +32,7 @@ class MQTTTextComponent : public mqtt::MQTTComponent { protected: /// Override for MQTTComponent, returns "text". - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; text::Text *text_; diff --git a/esphome/components/mqtt/mqtt_text_sensor.cpp b/esphome/components/mqtt/mqtt_text_sensor.cpp index c87f22fb8e..5346923b41 100644 --- a/esphome/components/mqtt/mqtt_text_sensor.cpp +++ b/esphome/components/mqtt/mqtt_text_sensor.cpp @@ -39,7 +39,7 @@ bool MQTTTextSensor::send_initial_state() { return true; } } -std::string MQTTTextSensor::component_type() const { return "sensor"; } +MQTT_COMPONENT_TYPE(MQTTTextSensor, "sensor") const EntityBase *MQTTTextSensor::get_entity() const { return this->sensor_; } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_text_sensor.h b/esphome/components/mqtt/mqtt_text_sensor.h index d4d38d7eb2..d8f9315c1e 100644 --- a/esphome/components/mqtt/mqtt_text_sensor.h +++ b/esphome/components/mqtt/mqtt_text_sensor.h @@ -25,7 +25,7 @@ class MQTTTextSensor : public mqtt::MQTTComponent { bool send_initial_state() override; protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; text_sensor::TextSensor *sensor_; diff --git a/esphome/components/mqtt/mqtt_time.cpp b/esphome/components/mqtt/mqtt_time.cpp index 01b8dd3483..b75325022a 100644 --- a/esphome/components/mqtt/mqtt_time.cpp +++ b/esphome/components/mqtt/mqtt_time.cpp @@ -39,7 +39,7 @@ void MQTTTimeComponent::dump_config() { LOG_MQTT_COMPONENT(true, true) } -std::string MQTTTimeComponent::component_type() const { return "time"; } +MQTT_COMPONENT_TYPE(MQTTTimeComponent, "time") const EntityBase *MQTTTimeComponent::get_entity() const { return this->time_; } void MQTTTimeComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_time.h b/esphome/components/mqtt/mqtt_time.h index 60345c37ae..cf5780da2d 100644 --- a/esphome/components/mqtt/mqtt_time.h +++ b/esphome/components/mqtt/mqtt_time.h @@ -31,7 +31,7 @@ class MQTTTimeComponent : public mqtt::MQTTComponent { bool publish_state(uint8_t hour, uint8_t minute, uint8_t second); protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; datetime::TimeEntity *time_; diff --git a/esphome/components/mqtt/mqtt_update.cpp b/esphome/components/mqtt/mqtt_update.cpp index aedf2414c1..99e0c85509 100644 --- a/esphome/components/mqtt/mqtt_update.cpp +++ b/esphome/components/mqtt/mqtt_update.cpp @@ -52,7 +52,7 @@ void MQTTUpdateComponent::dump_config() { LOG_MQTT_COMPONENT(true, true); } -std::string MQTTUpdateComponent::component_type() const { return "update"; } +MQTT_COMPONENT_TYPE(MQTTUpdateComponent, "update") const EntityBase *MQTTUpdateComponent::get_entity() const { return this->update_; } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_update.h b/esphome/components/mqtt/mqtt_update.h index d04d22d25f..ec1adb1fcd 100644 --- a/esphome/components/mqtt/mqtt_update.h +++ b/esphome/components/mqtt/mqtt_update.h @@ -27,7 +27,7 @@ class MQTTUpdateComponent : public mqtt::MQTTComponent { protected: /// "update" component type. - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; update::UpdateEntity *update_; diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 8ee693121b..a4c893f84b 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -65,7 +65,7 @@ void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf } } -std::string MQTTValveComponent::component_type() const { return "valve"; } +MQTT_COMPONENT_TYPE(MQTTValveComponent, "valve") const EntityBase *MQTTValveComponent::get_entity() const { return this->valve_; } bool MQTTValveComponent::send_initial_state() { return this->publish_state(); } diff --git a/esphome/components/mqtt/mqtt_valve.h b/esphome/components/mqtt/mqtt_valve.h index 9e5221e495..d3b724a8ba 100644 --- a/esphome/components/mqtt/mqtt_valve.h +++ b/esphome/components/mqtt/mqtt_valve.h @@ -27,7 +27,7 @@ class MQTTValveComponent : public mqtt::MQTTComponent { void dump_config() override; protected: - std::string component_type() const override; + const char *component_type() const override; const EntityBase *get_entity() const override; valve::Valve *valve_; diff --git a/esphome/core/config.py b/esphome/core/config.py index f9c3011507..b7e6ab9bee 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -76,6 +76,7 @@ VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"} def validate_hostname(config): + # Keep in sync with ESPHOME_DEVICE_NAME_MAX_LEN in esphome/core/entity_base.h max_length = 31 if config[CONF_NAME_ADD_MAC_SUFFIX]: max_length -= 7 # "-AABBCC" is appended when add mac suffix option is used @@ -207,6 +208,7 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.Required(CONF_NAME): cv.valid_name, + # Keep max=120 in sync with OBJECT_ID_MAX_LEN in esphome/core/entity_base.h cv.Optional(CONF_FRIENDLY_NAME, ""): cv.All( cv.string_no_slash, cv.Length(max=120) ), diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index a45c7795bf..1649077dd0 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -13,7 +13,10 @@ namespace esphome { -// Maximum size for object_id buffer (friendly_name max ~120 + margin) +// Maximum device name length - keep in sync with validate_hostname() in esphome/core/config.py +static constexpr size_t ESPHOME_DEVICE_NAME_MAX_LEN = 31; + +// Maximum size for object_id buffer - keep in sync with friendly_name cv.Length(max=120) in esphome/core/config.py static constexpr size_t OBJECT_ID_MAX_LEN = 128; enum EntityCategory : uint8_t { From d4969f581aaafc27200da114078918886e3a1f88 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 11:42:30 -1000 Subject: [PATCH 0010/2030] [wifi] Limit ignored disconnect events on LibreTiny to speed up AP failover (#13070) --- .../wifi/wifi_component_libretiny.cpp | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 68fcc3577d..c5b6a8ad96 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -86,6 +86,14 @@ enum class LTWiFiSTAState : uint8_t { static LTWiFiSTAState s_sta_state = LTWiFiSTAState::IDLE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +// Count of ignored disconnect events during connection - too many indicates real failure +static uint8_t s_ignored_disconnect_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +// Threshold for ignored disconnect events before treating as connection failure +// LibreTiny sends spurious "Association Leave" events, but more than this many +// indicates the connection is failing repeatedly. Value of 3 balances fast failure +// detection with tolerance for occasional spurious events on successful connections. +static constexpr uint8_t IGNORED_DISCONNECT_THRESHOLD = 3; + bool WiFiComponent::wifi_mode_(optional sta, optional ap) { uint8_t current_mode = WiFi.getMode(); bool current_sta = current_mode & 0b01; @@ -201,8 +209,9 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { this->wifi_apply_hostname_(); - // Reset state machine before connecting + // Reset state machine and disconnect counter before connecting s_sta_state = LTWiFiSTAState::CONNECTING; + s_ignored_disconnect_count = 0; WiFiStatus status = WiFi.begin(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), ap.get_channel(), // 0 = auto @@ -474,10 +483,22 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // causing wifi_sta_connect_status_() to return an error. The main loop would then // call retry_connect(), aborting a connection that may succeed moments later. // Only ignore benign reasons - real failures like NO_AP_FOUND should still be processed. + // However, if we get too many of these events (IGNORED_DISCONNECT_THRESHOLD), treat it + // as a real connection failure to avoid waiting the full timeout for a failing connection. if (it.ssid_len == 0 && s_sta_state == LTWiFiSTAState::CONNECTING && it.reason != WIFI_REASON_NO_AP_FOUND) { - ESP_LOGV(TAG, "Ignoring disconnect event with empty ssid while connecting (reason=%s)", - get_disconnect_reason_str(it.reason)); - break; + s_ignored_disconnect_count++; + if (s_ignored_disconnect_count >= IGNORED_DISCONNECT_THRESHOLD) { + ESP_LOGW(TAG, "Too many disconnect events (%u) while connecting, treating as failure (reason=%s)", + s_ignored_disconnect_count, get_disconnect_reason_str(it.reason)); + s_sta_state = LTWiFiSTAState::ERROR_FAILED; + WiFi.disconnect(); + this->error_from_callback_ = true; + // Don't break - fall through to notify listeners + } else { + ESP_LOGV(TAG, "Ignoring disconnect event with empty ssid while connecting (reason=%s, count=%u)", + get_disconnect_reason_str(it.reason), s_ignored_disconnect_count); + break; + } } if (it.reason == WIFI_REASON_NO_AP_FOUND) { From 012a1e2afd2c1c532f6d1c0cdd3a247fdc845179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= Date: Thu, 8 Jan 2026 23:05:53 +0100 Subject: [PATCH 0011/2030] [mqtt] Include session_present and reason parameters in connection callbacks (#12413) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/mqtt/__init__.py | 15 +++++++++++---- esphome/components/mqtt/mqtt_client.h | 8 ++++---- tests/components/mqtt/common.yaml | 4 ++++ 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index f01c928b30..d57cedd144 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -113,6 +113,7 @@ MQTT_MESSAGE_SCHEMA = cv.Any( mqtt_ns = cg.esphome_ns.namespace("mqtt") MQTTMessage = mqtt_ns.struct("MQTTMessage") +MQTTClientDisconnectReason = mqtt_ns.enum("MQTTClientDisconnectReason") MQTTClientComponent = mqtt_ns.class_("MQTTClientComponent", cg.Component) MQTTPublishAction = mqtt_ns.class_("MQTTPublishAction", automation.Action) MQTTPublishJsonAction = mqtt_ns.class_("MQTTPublishJsonAction", automation.Action) @@ -124,9 +125,11 @@ MQTTMessageTrigger = mqtt_ns.class_( MQTTJsonMessageTrigger = mqtt_ns.class_( "MQTTJsonMessageTrigger", automation.Trigger.template(cg.JsonObjectConst) ) -MQTTConnectTrigger = mqtt_ns.class_("MQTTConnectTrigger", automation.Trigger.template()) +MQTTConnectTrigger = mqtt_ns.class_( + "MQTTConnectTrigger", automation.Trigger.template(cg.bool_) +) MQTTDisconnectTrigger = mqtt_ns.class_( - "MQTTDisconnectTrigger", automation.Trigger.template() + "MQTTDisconnectTrigger", automation.Trigger.template(MQTTClientDisconnectReason) ) MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) @@ -475,11 +478,15 @@ async def to_code(config): for conf in config.get(CONF_ON_CONNECT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_automation( + trigger, [(cg.bool_, "session_present")], conf + ) for conf in config.get(CONF_ON_DISCONNECT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_automation( + trigger, [(MQTTClientDisconnectReason, "reason")], conf + ) cg.add(var.set_publish_nan_as_none(config[CONF_PUBLISH_NAN_AS_NONE])) diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 4189e7ae77..9e9db03b19 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -378,17 +378,17 @@ class MQTTJsonMessageTrigger : public Trigger { } }; -class MQTTConnectTrigger : public Trigger<> { +class MQTTConnectTrigger : public Trigger { public: explicit MQTTConnectTrigger(MQTTClientComponent *&client) { - client->set_on_connect([this](bool session_present) { this->trigger(); }); + client->set_on_connect([this](bool session_present) { this->trigger(session_present); }); } }; -class MQTTDisconnectTrigger : public Trigger<> { +class MQTTDisconnectTrigger : public Trigger { public: explicit MQTTDisconnectTrigger(MQTTClientComponent *&client) { - client->set_on_disconnect([this](MQTTClientDisconnectReason reason) { this->trigger(); }); + client->set_on_disconnect([this](MQTTClientDisconnectReason reason) { this->trigger(reason); }); } }; diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index 284ac30337..33988cebb4 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -57,10 +57,14 @@ mqtt: - mqtt.publish: topic: some/topic payload: Hello + - lambda: |- + ESP_LOGD("MQTT", "Session present %d", session_present); on_disconnect: - mqtt.publish: topic: some/topic payload: Good-bye + - lambda: |- + ESP_LOGD("MQTT", "Disconnect reason %d", reason); publish_nan_as_none: false binary_sensor: From dcb8c994cc09d6aa31b88d8aca47573cec708a2b Mon Sep 17 00:00:00 2001 From: Anton Viktorov Date: Fri, 9 Jan 2026 02:24:01 +0100 Subject: [PATCH 0012/2030] [ac_dimmer] Added support for ESP-IDF (5+) (#7072) Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ac_dimmer/ac_dimmer.cpp | 35 ++-- esphome/components/ac_dimmer/ac_dimmer.h | 10 +- .../components/ac_dimmer/hw_timer_esp_idf.cpp | 152 ++++++++++++++++++ .../components/ac_dimmer/hw_timer_esp_idf.h | 17 ++ esphome/components/ac_dimmer/output.py | 1 - .../components/ac_dimmer/test.esp32-ard.yaml | 5 - .../components/ac_dimmer/test.esp32-idf.yaml | 5 + 7 files changed, 195 insertions(+), 30 deletions(-) create mode 100644 esphome/components/ac_dimmer/hw_timer_esp_idf.cpp create mode 100644 esphome/components/ac_dimmer/hw_timer_esp_idf.h delete mode 100644 tests/components/ac_dimmer/test.esp32-ard.yaml create mode 100644 tests/components/ac_dimmer/test.esp32-idf.yaml diff --git a/esphome/components/ac_dimmer/ac_dimmer.cpp b/esphome/components/ac_dimmer/ac_dimmer.cpp index 04c01948c8..1e850a18fe 100644 --- a/esphome/components/ac_dimmer/ac_dimmer.cpp +++ b/esphome/components/ac_dimmer/ac_dimmer.cpp @@ -1,5 +1,3 @@ -#ifdef USE_ARDUINO - #include "ac_dimmer.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -9,12 +7,12 @@ #ifdef USE_ESP8266 #include #endif -#ifdef USE_ESP32_FRAMEWORK_ARDUINO -#include + +#ifdef USE_ESP32 +#include "hw_timer_esp_idf.h" #endif -namespace esphome { -namespace ac_dimmer { +namespace esphome::ac_dimmer { static const char *const TAG = "ac_dimmer"; @@ -27,7 +25,14 @@ static AcDimmerDataStore *all_dimmers[32]; // NOLINT(cppcoreguidelines-avoid-no /// However other factors like gate driver propagation time /// are also considered and a really low value is not important /// See also: https://github.com/esphome/issues/issues/1632 -static const uint32_t GATE_ENABLE_TIME = 50; +static constexpr uint32_t GATE_ENABLE_TIME = 50; + +#ifdef USE_ESP32 +/// Timer frequency in Hz (1 MHz = 1µs resolution) +static constexpr uint32_t TIMER_FREQUENCY_HZ = 1000000; +/// Timer interrupt interval in microseconds +static constexpr uint64_t TIMER_INTERVAL_US = 50; +#endif /// Function called from timer interrupt /// Input is current time in microseconds (micros()) @@ -154,7 +159,7 @@ void IRAM_ATTR HOT AcDimmerDataStore::s_gpio_intr(AcDimmerDataStore *store) { #ifdef USE_ESP32 // ESP32 implementation, uses basically the same code but needs to wrap // timer_interrupt() function to auto-reschedule -static hw_timer_t *dimmer_timer = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static HWTimer *dimmer_timer = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) void IRAM_ATTR HOT AcDimmerDataStore::s_timer_intr() { timer_interrupt(); } #endif @@ -194,15 +199,15 @@ void AcDimmer::setup() { setTimer1Callback(&timer_interrupt); #endif #ifdef USE_ESP32 - // timer frequency of 1mhz - dimmer_timer = timerBegin(1000000); - timerAttachInterrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr); + dimmer_timer = timer_begin(TIMER_FREQUENCY_HZ); + timer_attach_interrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr); // For ESP32, we can't use dynamic interval calculation because the timerX functions // are not callable from ISR (placed in flash storage). // Here we just use an interrupt firing every 50 µs. - timerAlarm(dimmer_timer, 50, true, 0); + timer_alarm(dimmer_timer, TIMER_INTERVAL_US, true, 0); #endif } + void AcDimmer::write_state(float state) { state = std::acos(1 - (2 * state)) / std::numbers::pi; // RMS power compensation auto new_value = static_cast(roundf(state * 65535)); @@ -210,6 +215,7 @@ void AcDimmer::write_state(float state) { this->store_.init_cycle = this->init_with_half_cycle_; this->store_.value = new_value; } + void AcDimmer::dump_config() { ESP_LOGCONFIG(TAG, "AcDimmer:\n" @@ -230,7 +236,4 @@ void AcDimmer::dump_config() { ESP_LOGV(TAG, " Estimated Frequency: %.3fHz", 1e6f / this->store_.cycle_time_us / 2); } -} // namespace ac_dimmer -} // namespace esphome - -#endif // USE_ARDUINO +} // namespace esphome::ac_dimmer diff --git a/esphome/components/ac_dimmer/ac_dimmer.h b/esphome/components/ac_dimmer/ac_dimmer.h index fd1bbc28db..ca2a19210a 100644 --- a/esphome/components/ac_dimmer/ac_dimmer.h +++ b/esphome/components/ac_dimmer/ac_dimmer.h @@ -1,13 +1,10 @@ #pragma once -#ifdef USE_ARDUINO - #include "esphome/core/component.h" #include "esphome/core/hal.h" #include "esphome/components/output/float_output.h" -namespace esphome { -namespace ac_dimmer { +namespace esphome::ac_dimmer { enum DimMethod { DIM_METHOD_LEADING_PULSE = 0, DIM_METHOD_LEADING, DIM_METHOD_TRAILING }; @@ -64,7 +61,4 @@ class AcDimmer : public output::FloatOutput, public Component { DimMethod method_; }; -} // namespace ac_dimmer -} // namespace esphome - -#endif // USE_ARDUINO +} // namespace esphome::ac_dimmer diff --git a/esphome/components/ac_dimmer/hw_timer_esp_idf.cpp b/esphome/components/ac_dimmer/hw_timer_esp_idf.cpp new file mode 100644 index 0000000000..543b476085 --- /dev/null +++ b/esphome/components/ac_dimmer/hw_timer_esp_idf.cpp @@ -0,0 +1,152 @@ +#ifdef USE_ESP32 + +#include "hw_timer_esp_idf.h" + +#include "freertos/FreeRTOS.h" +#include "esphome/core/log.h" + +#include "driver/gptimer.h" +#include "esp_clk_tree.h" +#include "soc/clk_tree_defs.h" + +static const char *const TAG = "hw_timer_esp_idf"; + +namespace esphome::ac_dimmer { + +// GPTimer divider constraints from ESP-IDF documentation +static constexpr uint32_t GPTIMER_DIVIDER_MIN = 2; +static constexpr uint32_t GPTIMER_DIVIDER_MAX = 65536; + +using voidFuncPtr = void (*)(); +using voidFuncPtrArg = void (*)(void *); + +struct InterruptConfigT { + voidFuncPtr fn{nullptr}; + void *arg{nullptr}; +}; + +struct HWTimer { + gptimer_handle_t timer_handle{nullptr}; + InterruptConfigT interrupt_handle{}; + bool timer_started{false}; +}; + +HWTimer *timer_begin(uint32_t frequency) { + esp_err_t err = ESP_OK; + uint32_t counter_src_hz = 0; + uint32_t divider = 0; + soc_module_clk_t clk; + for (auto clk_candidate : SOC_GPTIMER_CLKS) { + clk = clk_candidate; + esp_clk_tree_src_get_freq_hz(clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz); + divider = counter_src_hz / frequency; + if ((divider >= GPTIMER_DIVIDER_MIN) && (divider <= GPTIMER_DIVIDER_MAX)) { + break; + } else { + divider = 0; + } + } + + if (divider == 0) { + ESP_LOGE(TAG, "Resolution not possible; aborting"); + return nullptr; + } + + gptimer_config_t config = { + .clk_src = static_cast(clk), + .direction = GPTIMER_COUNT_UP, + .resolution_hz = frequency, + .flags = {.intr_shared = true}, + }; + + HWTimer *timer = new HWTimer(); + + err = gptimer_new_timer(&config, &timer->timer_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "GPTimer creation failed; error %d", err); + delete timer; + return nullptr; + } + + err = gptimer_enable(timer->timer_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "GPTimer enable failed; error %d", err); + gptimer_del_timer(timer->timer_handle); + delete timer; + return nullptr; + } + + err = gptimer_start(timer->timer_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "GPTimer start failed; error %d", err); + gptimer_disable(timer->timer_handle); + gptimer_del_timer(timer->timer_handle); + delete timer; + return nullptr; + } + + timer->timer_started = true; + return timer; +} + +bool IRAM_ATTR timer_fn_wrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *args) { + auto *isr = static_cast(args); + if (isr->fn) { + if (isr->arg) { + reinterpret_cast(isr->fn)(isr->arg); + } else { + isr->fn(); + } + } + // Return false to indicate that no higher-priority task was woken and no context switch is requested. + return false; +} + +static void timer_attach_interrupt_functional_arg(HWTimer *timer, void (*user_func)(void *), void *arg) { + if (timer == nullptr) { + ESP_LOGE(TAG, "Timer handle is nullptr"); + return; + } + gptimer_event_callbacks_t cbs = { + .on_alarm = timer_fn_wrapper, + }; + + timer->interrupt_handle.fn = reinterpret_cast(user_func); + timer->interrupt_handle.arg = arg; + + if (timer->timer_started) { + gptimer_stop(timer->timer_handle); + } + gptimer_disable(timer->timer_handle); + esp_err_t err = gptimer_register_event_callbacks(timer->timer_handle, &cbs, &timer->interrupt_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Timer Attach Interrupt failed; error %d", err); + } + gptimer_enable(timer->timer_handle); + if (timer->timer_started) { + gptimer_start(timer->timer_handle); + } +} + +void timer_attach_interrupt(HWTimer *timer, voidFuncPtr user_func) { + timer_attach_interrupt_functional_arg(timer, reinterpret_cast(user_func), nullptr); +} + +void timer_alarm(HWTimer *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count) { + if (timer == nullptr) { + ESP_LOGE(TAG, "Timer handle is nullptr"); + return; + } + gptimer_alarm_config_t alarm_cfg = { + .alarm_count = alarm_value, + .reload_count = reload_count, + .flags = {.auto_reload_on_alarm = autoreload}, + }; + esp_err_t err = gptimer_set_alarm_action(timer->timer_handle, &alarm_cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Timer Alarm Write failed; error %d", err); + } +} + +} // namespace esphome::ac_dimmer +#endif diff --git a/esphome/components/ac_dimmer/hw_timer_esp_idf.h b/esphome/components/ac_dimmer/hw_timer_esp_idf.h new file mode 100644 index 0000000000..1b2401ebda --- /dev/null +++ b/esphome/components/ac_dimmer/hw_timer_esp_idf.h @@ -0,0 +1,17 @@ +#pragma once +#ifdef USE_ESP32 + +#include "driver/gptimer_types.h" + +namespace esphome::ac_dimmer { + +struct HWTimer; + +HWTimer *timer_begin(uint32_t frequency); + +void timer_attach_interrupt(HWTimer *timer, void (*user_func)()); +void timer_alarm(HWTimer *timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count); + +} // namespace esphome::ac_dimmer + +#endif diff --git a/esphome/components/ac_dimmer/output.py b/esphome/components/ac_dimmer/output.py index 9f9afb6d80..efc24b65e7 100644 --- a/esphome/components/ac_dimmer/output.py +++ b/esphome/components/ac_dimmer/output.py @@ -32,7 +32,6 @@ CONFIG_SCHEMA = cv.All( ), } ).extend(cv.COMPONENT_SCHEMA), - cv.only_with_arduino, ) diff --git a/tests/components/ac_dimmer/test.esp32-ard.yaml b/tests/components/ac_dimmer/test.esp32-ard.yaml deleted file mode 100644 index eaa4901f03..0000000000 --- a/tests/components/ac_dimmer/test.esp32-ard.yaml +++ /dev/null @@ -1,5 +0,0 @@ -substitutions: - gate_pin: GPIO4 - zero_cross_pin: GPIO5 - -<<: !include common.yaml diff --git a/tests/components/ac_dimmer/test.esp32-idf.yaml b/tests/components/ac_dimmer/test.esp32-idf.yaml new file mode 100644 index 0000000000..3ec069f430 --- /dev/null +++ b/tests/components/ac_dimmer/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + gate_pin: GPIO18 + zero_cross_pin: GPIO19 + +<<: !include common.yaml From 5afe4b7b12db3811f4a3d5128ddaec12b2897dad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 16:41:34 -1000 Subject: [PATCH 0013/2030] [wifi] Warn when AP is configured without captive_portal or web_server (#13087) --- esphome/components/wifi/__init__.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 7ba1b5e417..e8bc2edd8f 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -238,12 +238,21 @@ def _apply_min_auth_mode_default(config): def final_validate(config): has_sta = bool(config.get(CONF_NETWORKS, True)) has_ap = CONF_AP in config - has_improv = "esp32_improv" in fv.full_config.get() - has_improv_serial = "improv_serial" in fv.full_config.get() + full_config = fv.full_config.get() + has_improv = "esp32_improv" in full_config + has_improv_serial = "improv_serial" in full_config + has_captive_portal = "captive_portal" in full_config + has_web_server = "web_server" in full_config if not (has_sta or has_ap or has_improv or has_improv_serial): raise cv.Invalid( "Please specify at least an SSID or an Access Point to create." ) + if has_ap and not has_captive_portal and not has_web_server: + _LOGGER.warning( + "WiFi AP is configured but neither captive_portal nor web_server is enabled. " + "The AP will not be usable for configuration or monitoring. " + "Add 'captive_portal:' or 'web_server:' to your configuration." + ) FINAL_VALIDATE_SCHEMA = cv.All( From 2c165e4817054f60cf50d7eecb492a57d24d7c2a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 20:36:08 -1000 Subject: [PATCH 0014/2030] [web_server] Use centralized length constants for buffer sizing (#13073) --- esphome/components/web_server/web_server.cpp | 12 +++++++----- esphome/core/config.py | 13 ++++++++++--- esphome/core/entity_base.h | 9 ++++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e5705d7b47..cab177c182 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -498,14 +498,16 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J // Build id into stack buffer - ArduinoJson copies the string // Format: {prefix}/{device?}/{name} - // Buffer size guaranteed by schema validation (NAME_MAX_LENGTH=120): - // With devices: domain(20) + "/" + device(120) + "/" + name(120) + null = 263, rounded up to 280 for safety margin - // Without devices: domain(20) + "/" + name(120) + null = 142, rounded up to 150 for safety margin + // Buffer sizes use constants from entity_base.h validated in core/config.py + // Note: Device name uses ESPHOME_FRIENDLY_NAME_MAX_LEN (sub-device max 120), not ESPHOME_DEVICE_NAME_MAX_LEN + // (hostname) #ifdef USE_DEVICES - char id_buf[280]; + static constexpr size_t ID_BUF_SIZE = + ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1; #else - char id_buf[150]; + static constexpr size_t ID_BUF_SIZE = ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1; #endif + char id_buf[ID_BUF_SIZE]; char *p = id_buf; memcpy(p, prefix, prefix_len); p += prefix_len; diff --git a/esphome/core/config.py b/esphome/core/config.py index b7e6ab9bee..21ed8ced1a 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -184,17 +184,24 @@ if "ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT" in os.environ: else: _compile_process_limit_default = cv.UNDEFINED +# Keep in sync with ESPHOME_FRIENDLY_NAME_MAX_LEN in esphome/core/entity_base.h +FRIENDLY_NAME_MAX_LEN = 120 + AREA_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Area), - cv.Required(CONF_NAME): cv.All(cv.string_no_slash, cv.Length(max=120)), + cv.Required(CONF_NAME): cv.All( + cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) + ), } ) DEVICE_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Device), - cv.Required(CONF_NAME): cv.All(cv.string_no_slash, cv.Length(max=120)), + cv.Required(CONF_NAME): cv.All( + cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) + ), cv.Optional(CONF_AREA_ID): cv.use_id(Area), } ) @@ -210,7 +217,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_NAME): cv.valid_name, # Keep max=120 in sync with OBJECT_ID_MAX_LEN in esphome/core/entity_base.h cv.Optional(CONF_FRIENDLY_NAME, ""): cv.All( - cv.string_no_slash, cv.Length(max=120) + cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) ), cv.Optional(CONF_AREA): validate_area_config, cv.Optional(CONF_COMMENT): cv.All(cv.string, cv.Length(max=255)), diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 1649077dd0..5f75872a0f 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -16,7 +16,14 @@ namespace esphome { // Maximum device name length - keep in sync with validate_hostname() in esphome/core/config.py static constexpr size_t ESPHOME_DEVICE_NAME_MAX_LEN = 31; -// Maximum size for object_id buffer - keep in sync with friendly_name cv.Length(max=120) in esphome/core/config.py +// Maximum friendly name length for entities and sub-devices - keep in sync with FRIENDLY_NAME_MAX_LEN in +// esphome/core/config.py +static constexpr size_t ESPHOME_FRIENDLY_NAME_MAX_LEN = 120; + +// Maximum domain length (longest: "alarm_control_panel" = 19) +static constexpr size_t ESPHOME_DOMAIN_MAX_LEN = 20; + +// Maximum size for object_id buffer (friendly_name + null + margin) static constexpr size_t OBJECT_ID_MAX_LEN = 128; enum EntityCategory : uint8_t { From cd43b4114e2c650e61d0b3a86a3f56389646defb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Jan 2026 20:36:24 -1000 Subject: [PATCH 0015/2030] [api] Fire on_client_disconnected trigger after removing client from list (#13088) --- esphome/components/api/api_server.cpp | 14 +++++++++++--- .../fixtures/api_conditional_memory.yaml | 8 ++++++++ tests/integration/test_api_conditional_memory.py | 8 ++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 4ececfec94..336672f50b 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -186,14 +186,17 @@ void APIServer::loop() { } // Rare case: handle disconnection -#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - this->client_disconnected_trigger_->trigger(std::string(client->get_name()), std::string(client->get_peername())); -#endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES this->unregister_active_action_calls_for_connection(client.get()); #endif ESP_LOGV(TAG, "Remove connection %s", client->get_name()); +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Save client info before removal for the trigger + std::string client_name(client->get_name()); + std::string client_peername(client->get_peername()); +#endif + // Swap with the last element and pop (avoids expensive vector shifts) if (client_index < this->clients_.size() - 1) { std::swap(this->clients_[client_index], this->clients_.back()); @@ -205,6 +208,11 @@ void APIServer::loop() { this->status_set_warning(); this->last_connected_ = App.get_loop_component_start_time(); } + +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Fire trigger after client is removed so api.connected reflects the true state + this->client_disconnected_trigger_->trigger(client_name, client_peername); +#endif // Don't increment client_index since we need to process the swapped element } } diff --git a/tests/integration/fixtures/api_conditional_memory.yaml b/tests/integration/fixtures/api_conditional_memory.yaml index 22e8ed79d6..4a0923b93f 100644 --- a/tests/integration/fixtures/api_conditional_memory.yaml +++ b/tests/integration/fixtures/api_conditional_memory.yaml @@ -24,6 +24,14 @@ api: - logger.log: format: "Client %s disconnected from %s" args: [client_info.c_str(), client_address.c_str()] + # Verify fix for issue #11131: api.connected should reflect true state in trigger + - if: + condition: + api.connected: + then: + - logger.log: "Other clients still connected" + else: + - logger.log: "No clients remaining" logger: level: DEBUG diff --git a/tests/integration/test_api_conditional_memory.py b/tests/integration/test_api_conditional_memory.py index 349b572859..91625770d9 100644 --- a/tests/integration/test_api_conditional_memory.py +++ b/tests/integration/test_api_conditional_memory.py @@ -23,12 +23,14 @@ async def test_api_conditional_memory( # Track log messages connected_future = loop.create_future() disconnected_future = loop.create_future() + no_clients_future = loop.create_future() service_simple_future = loop.create_future() service_args_future = loop.create_future() # Patterns to match in logs connected_pattern = re.compile(r"Client .* connected from") disconnected_pattern = re.compile(r"Client .* disconnected from") + no_clients_pattern = re.compile(r"No clients remaining") service_simple_pattern = re.compile(r"Simple service called") service_args_pattern = re.compile( r"Service called with: test_string, 123, 1, 42\.50" @@ -40,6 +42,8 @@ async def test_api_conditional_memory( connected_future.set_result(True) elif not disconnected_future.done() and disconnected_pattern.search(line): disconnected_future.set_result(True) + elif not no_clients_future.done() and no_clients_pattern.search(line): + no_clients_future.set_result(True) elif not service_simple_future.done() and service_simple_pattern.search(line): service_simple_future.set_result(True) elif not service_args_future.done() and service_args_pattern.search(line): @@ -109,3 +113,7 @@ async def test_api_conditional_memory( # Client disconnected here, wait for disconnect log await asyncio.wait_for(disconnected_future, timeout=5.0) + + # Verify fix for issue #11131: api.connected should be false in trigger + # when the last client disconnects + await asyncio.wait_for(no_clients_future, timeout=5.0) From 7576e032f8ef79375f82d24a9d105f98a78206cd Mon Sep 17 00:00:00 2001 From: Stuart Parmenter Date: Thu, 8 Jan 2026 23:56:51 -0800 Subject: [PATCH 0016/2030] [hub75] Fix depth and gamma mode defines (#13091) --- esphome/components/hub75/display.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 40202e52ca..7a3df333c9 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -550,12 +550,12 @@ async def to_code(config: ConfigType) -> None: ref="0.2.2", ) - # Set compile-time configuration via defines + # Set compile-time configuration via build flags (so external library sees them) if CONF_BIT_DEPTH in config: - cg.add_define("HUB75_BIT_DEPTH", config[CONF_BIT_DEPTH]) + cg.add_build_flag(f"-DHUB75_BIT_DEPTH={config[CONF_BIT_DEPTH]}") if CONF_GAMMA_CORRECT in config: - cg.add_define("HUB75_GAMMA_MODE", config[CONF_GAMMA_CORRECT]) + cg.add_build_flag(f"-DHUB75_GAMMA_MODE={config[CONF_GAMMA_CORRECT]}") # Await all pin expressions pin_expressions = { From 62cb08c3dce9d2579c70dcad157c6634f471f29e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 9 Jan 2026 04:05:47 -0600 Subject: [PATCH 0017/2030] [api] Add methods supporting efficient packed repeated sint32 field encoding for #12985 (#13094) --- esphome/components/api/proto.h | 63 +++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 2d93adbb47..a336a9493d 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -39,6 +39,24 @@ inline constexpr int64_t decode_zigzag64(uint64_t value) { return (value & 1) ? static_cast(~(value >> 1)) : static_cast(value >> 1); } +/// Count number of varints in a packed buffer +inline uint16_t count_packed_varints(const uint8_t *data, size_t len) { + uint16_t count = 0; + while (len > 0) { + // Skip varint bytes until we find one without continuation bit + while (len > 0 && (*data & 0x80)) { + data++; + len--; + } + if (len > 0) { + data++; + len--; + count++; + } + } + return count; +} + /* * StringRef Ownership Model for API Protocol Messages * =================================================== @@ -180,9 +198,10 @@ class ProtoVarInt { uint64_t value_; }; -// Forward declaration for decode_to_message and encode_to_writer -class ProtoMessage; +// Forward declarations for decode_to_message, encode_message and encode_packed_sint32 class ProtoDecodableMessage; +class ProtoMessage; +class ProtoSize; class ProtoLengthDelimited { public: @@ -334,6 +353,8 @@ class ProtoWriteBuffer { void encode_sint64(uint32_t field_id, int64_t value, bool force = false) { this->encode_uint64(field_id, encode_zigzag64(value), force); } + /// Encode a packed repeated sint32 field (zero-copy from vector) + void encode_packed_sint32(uint32_t field_id, const std::vector &values); void encode_message(uint32_t field_id, const ProtoMessage &value); std::vector *get_buffer() const { return buffer_; } @@ -341,9 +362,6 @@ class ProtoWriteBuffer { std::vector *buffer_; }; -// Forward declaration -class ProtoSize; - class ProtoMessage { public: virtual ~ProtoMessage() = default; @@ -792,8 +810,43 @@ class ProtoSize { } } } + + /** + * @brief Calculate size of a packed repeated sint32 field + */ + inline void add_packed_sint32(uint32_t field_id_size, const std::vector &values) { + if (values.empty()) + return; + + size_t packed_size = 0; + for (int value : values) { + packed_size += varint(encode_zigzag32(value)); + } + + // field_id + length varint + packed data + total_size_ += field_id_size + varint(static_cast(packed_size)) + static_cast(packed_size); + } }; +// Implementation of encode_packed_sint32 - must be after ProtoSize is defined +inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector &values) { + if (values.empty()) + return; + + // Calculate packed size + size_t packed_size = 0; + for (int value : values) { + packed_size += ProtoSize::varint(encode_zigzag32(value)); + } + + // Write tag (LENGTH_DELIMITED) + length + all zigzag-encoded values + this->encode_field_raw(field_id, WIRE_TYPE_LENGTH_DELIMITED); + this->encode_varint_raw(packed_size); + for (int value : values) { + this->encode_varint_raw(encode_zigzag32(value)); + } +} + // Implementation of encode_message - must be after ProtoMessage is defined inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value) { this->encode_field_raw(field_id, 2); // type 2: Length-delimited message From c40f44f4bdd4fe559925407d22712b93636dc4b8 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 9 Jan 2026 04:06:03 -0600 Subject: [PATCH 0018/2030] [remote_base] Add zero-copy packed sint32 decoder for #12985 (#13093) --- .../components/remote_base/remote_base.cpp | 33 +++++++++++++++++++ esphome/components/remote_base/remote_base.h | 5 +++ 2 files changed, 38 insertions(+) diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 34aba236b3..2f1c107bf4 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -128,6 +128,39 @@ void RemoteReceiverBase::call_dumpers_() { void RemoteReceiverBinarySensorBase::dump_config() { LOG_BINARY_SENSOR("", "Remote Receiver Binary Sensor", this); } +/* RemoteTransmitData */ + +void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count) { + this->data_.clear(); + this->data_.reserve(count); + + while (len > 0) { + // Parse varint (inline, no dependency on api component) + uint32_t raw = 0; + uint32_t shift = 0; + uint32_t consumed = 0; + for (; consumed < len && consumed < 5; consumed++) { + uint8_t byte = data[consumed]; + raw |= (byte & 0x7F) << shift; + if ((byte & 0x80) == 0) { + consumed++; + break; + } + shift += 7; + } + if (consumed == 0) + break; // Parse error + + // Zigzag decode: (n >> 1) ^ -(n & 1) + int32_t decoded = static_cast((raw >> 1) ^ (~(raw & 1) + 1)); + this->data_.push_back(decoded); + data += consumed; + len -= consumed; + } +} + +/* RemoteTransmitterBase */ + void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE const auto &vec = this->temp_.get_data(); diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 2cb79bf571..a11e0271af 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -31,6 +31,11 @@ class RemoteTransmitData { uint32_t get_carrier_frequency() const { return this->carrier_frequency_; } const RawTimings &get_data() const { return this->data_; } void set_data(const RawTimings &data) { this->data_ = data; } + /// Set data from packed protobuf sint32 buffer (zigzag + varint encoded) + /// @param data Pointer to packed zigzag-varint-encoded sint32 values + /// @param len Length of the buffer in bytes + /// @param count Number of values (for reserve optimization) + void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count); void reset() { this->data_.clear(); this->carrier_frequency_ = 0; From 3d54ccac65b7d8d02e2f59e17c8b88d3617faa53 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 9 Jan 2026 04:35:19 -1000 Subject: [PATCH 0019/2030] Revert "[wifi] Disable SoftAP support on Arduino ESP32 when ap: not configured" (#13099) --- esphome/components/wifi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index e8bc2edd8f..26aec29b6d 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -475,7 +475,7 @@ async def to_code(config): ) cg.add(var.set_ap_timeout(conf[CONF_AP_TIMEOUT])) cg.add_define("USE_WIFI_AP") - elif CORE.is_esp32: + elif CORE.is_esp32 and not CORE.using_arduino: add_idf_sdkconfig_option("CONFIG_ESP_WIFI_SOFTAP_SUPPORT", False) add_idf_sdkconfig_option("CONFIG_LWIP_DHCPS", False) From ab32b939287ddeaccf009ebfb5b5282930f3089f Mon Sep 17 00:00:00 2001 From: Stuart Parmenter Date: Fri, 9 Jan 2026 11:34:04 -0800 Subject: [PATCH 0020/2030] [hub75] Fix gamma_correct to use enum value instead of key string (#13102) Co-authored-by: Claude --- esphome/components/hub75/display.py | 2 +- tests/components/hub75/test.esp32-s3-idf-board.yaml | 1 + tests/components/hub75/test.esp32-s3-idf.yaml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 7a3df333c9..20c731e730 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -555,7 +555,7 @@ async def to_code(config: ConfigType) -> None: cg.add_build_flag(f"-DHUB75_BIT_DEPTH={config[CONF_BIT_DEPTH]}") if CONF_GAMMA_CORRECT in config: - cg.add_build_flag(f"-DHUB75_GAMMA_MODE={config[CONF_GAMMA_CORRECT]}") + cg.add_build_flag(f"-DHUB75_GAMMA_MODE={config[CONF_GAMMA_CORRECT].enum_value}") # Await all pin expressions pin_expressions = { diff --git a/tests/components/hub75/test.esp32-s3-idf-board.yaml b/tests/components/hub75/test.esp32-s3-idf-board.yaml index 3723a80006..8c73a0fd44 100644 --- a/tests/components/hub75/test.esp32-s3-idf-board.yaml +++ b/tests/components/hub75/test.esp32-s3-idf-board.yaml @@ -6,6 +6,7 @@ display: panel_height: 32 double_buffer: true brightness: 128 + gamma_correct: gamma_2_2 pages: - id: page1 lambda: |- diff --git a/tests/components/hub75/test.esp32-s3-idf.yaml b/tests/components/hub75/test.esp32-s3-idf.yaml index f8ee26e73d..0adb4f991b 100644 --- a/tests/components/hub75/test.esp32-s3-idf.yaml +++ b/tests/components/hub75/test.esp32-s3-idf.yaml @@ -5,6 +5,7 @@ display: panel_height: 32 double_buffer: true brightness: 128 + gamma_correct: cie1931 r1_pin: GPIO42 g1_pin: GPIO41 b1_pin: GPIO40 From 7935fba4b10b87468d1caacaf9a2326d9b3c80ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 14:37:53 -0500 Subject: [PATCH 0021/2030] Bump esphome-dashboard from 20251013.0 to 20260110.0 (#13109) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 56df559cd7..00f81f793f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ pyserial==3.5 platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 -esphome-dashboard==20251013.0 +esphome-dashboard==20260110.0 aioesphomeapi==43.10.1 zeroconf==0.148.0 puremagic==1.30 From 2fb7c0d453c37e6c12030d6269a77c74714afa69 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 9 Jan 2026 09:39:53 -1000 Subject: [PATCH 0022/2030] [mapping] Fix test SPI data rate for RP2040 (#13108) --- tests/components/mapping/test.rp2040-ard.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/components/mapping/test.rp2040-ard.yaml b/tests/components/mapping/test.rp2040-ard.yaml index acc305a701..fdfed5f6ab 100644 --- a/tests/components/mapping/test.rp2040-ard.yaml +++ b/tests/components/mapping/test.rp2040-ard.yaml @@ -7,6 +7,7 @@ display: platform: ili9xxx id: main_lcd model: ili9342 + data_rate: 31.25MHz cs_pin: 20 dc_pin: 21 reset_pin: 22 From 32f90b2855c00f2f723751fd5bc896d57fd66233 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 9 Jan 2026 09:40:24 -1000 Subject: [PATCH 0023/2030] [mdns] Remove deprecated api password from test configuration (#13107) --- tests/components/mdns/test-comprehensive.esp8266-ard.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/components/mdns/test-comprehensive.esp8266-ard.yaml b/tests/components/mdns/test-comprehensive.esp8266-ard.yaml index 3129ca3143..7d3f61cf08 100644 --- a/tests/components/mdns/test-comprehensive.esp8266-ard.yaml +++ b/tests/components/mdns/test-comprehensive.esp8266-ard.yaml @@ -42,4 +42,3 @@ status_led: # Include API at priority 40 api: - password: "apipassword" From 3c9b300c462e86316c5b154c485fff53bec1a7be Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Fri, 9 Jan 2026 23:13:37 +0100 Subject: [PATCH 0024/2030] [CI] skip endpoint check due to test grouping (#13111) --- esphome/components/zigbee/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 1a017f2ab2..cf37e890c4 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -69,7 +69,7 @@ def validate_number_of_ep(config: ConfigType) -> None: raise cv.Invalid( "Single endpoint is not supported https://github.com/Koenkk/zigbee2mqtt/issues/29888" ) - if count > CONF_MAX_EP_NUMBER: + if count > CONF_MAX_EP_NUMBER and not CORE.testing_mode: raise cv.Invalid(f"Maximum number of end points is {CONF_MAX_EP_NUMBER}") From e0ff7fdaa1b4b5e2c26023f0f6671d621b29c8c8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 9 Jan 2026 17:36:56 -0500 Subject: [PATCH 0025/2030] [esp32_hosted] Add HTTP-based coprocessor firmware update support (#13090) Co-authored-by: Claude --- .../esp32_hosted/update/__init__.py | 68 +++- .../update/esp32_hosted_update.cpp | 353 ++++++++++++++++-- .../esp32_hosted/update/esp32_hosted_update.h | 35 +- ...f.yaml => test-embedded.esp32-p4-idf.yaml} | 1 + .../esp32_hosted/test-http.esp32-p4-idf.yaml | 10 + 5 files changed, 410 insertions(+), 57 deletions(-) rename tests/components/esp32_hosted/{test.esp32-p4-idf.yaml => test-embedded.esp32-p4-idf.yaml} (92%) create mode 100644 tests/components/esp32_hosted/test-http.esp32-p4-idf.yaml diff --git a/esphome/components/esp32_hosted/update/__init__.py b/esphome/components/esp32_hosted/update/__init__.py index fff0d3623a..b258a26b08 100644 --- a/esphome/components/esp32_hosted/update/__init__.py +++ b/esphome/components/esp32_hosted/update/__init__.py @@ -4,18 +4,24 @@ from typing import Any import esphome.codegen as cg from esphome.components import esp32, update import esphome.config_validation as cv -from esphome.const import CONF_PATH, CONF_RAW_DATA_ID -from esphome.core import CORE, HexInt +from esphome.const import CONF_ID, CONF_PATH, CONF_SOURCE, CONF_TYPE +from esphome.core import CORE, ID, HexInt CODEOWNERS = ["@swoboda1337"] -AUTO_LOAD = ["sha256", "watchdog"] +AUTO_LOAD = ["sha256", "watchdog", "json"] DEPENDENCIES = ["esp32_hosted"] CONF_SHA256 = "sha256" +CONF_HTTP_REQUEST_ID = "http_request_id" + +TYPE_EMBEDDED = "embedded" +TYPE_HTTP = "http" esp32_hosted_ns = cg.esphome_ns.namespace("esp32_hosted") +http_request_ns = cg.esphome_ns.namespace("http_request") +HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) Esp32HostedUpdate = esp32_hosted_ns.class_( - "Esp32HostedUpdate", update.UpdateEntity, cg.Component + "Esp32HostedUpdate", update.UpdateEntity, cg.PollingComponent ) @@ -30,12 +36,29 @@ def _validate_sha256(value: Any) -> str: return value +BASE_SCHEMA = update.update_schema(Esp32HostedUpdate, device_class="firmware").extend( + cv.polling_component_schema("6h") +) + +EMBEDDED_SCHEMA = BASE_SCHEMA.extend( + { + cv.Required(CONF_PATH): cv.file_, + cv.Required(CONF_SHA256): _validate_sha256, + } +) + +HTTP_SCHEMA = BASE_SCHEMA.extend( + { + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), + cv.Required(CONF_SOURCE): cv.url, + } +) + CONFIG_SCHEMA = cv.All( - update.update_schema(Esp32HostedUpdate, device_class="firmware").extend( + cv.typed_schema( { - cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), - cv.Required(CONF_PATH): cv.file_, - cv.Required(CONF_SHA256): _validate_sha256, + TYPE_EMBEDDED: EMBEDDED_SCHEMA, + TYPE_HTTP: HTTP_SCHEMA, } ), esp32.only_on_variant( @@ -48,6 +71,9 @@ CONFIG_SCHEMA = cv.All( def _validate_firmware(config: dict[str, Any]) -> None: + if config[CONF_TYPE] != TYPE_EMBEDDED: + return + path = CORE.relative_config_path(config[CONF_PATH]) with open(path, "rb") as f: firmware_data = f.read() @@ -65,14 +91,22 @@ FINAL_VALIDATE_SCHEMA = _validate_firmware async def to_code(config: dict[str, Any]) -> None: var = await update.new_update(config) - path = config[CONF_PATH] - with open(CORE.relative_config_path(path), "rb") as f: - firmware_data = f.read() - rhs = [HexInt(x) for x in firmware_data] - prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) + if config[CONF_TYPE] == TYPE_EMBEDDED: + path = config[CONF_PATH] + with open(CORE.relative_config_path(path), "rb") as f: + firmware_data = f.read() + rhs = [HexInt(x) for x in firmware_data] + arr_id = ID(f"{config[CONF_ID]}_data", is_declaration=True, type=cg.uint8) + prog_arr = cg.progmem_array(arr_id, rhs) + + sha256_bytes = bytes.fromhex(config[CONF_SHA256]) + cg.add(var.set_firmware_sha256([HexInt(b) for b in sha256_bytes])) + cg.add(var.set_firmware_data(prog_arr)) + cg.add(var.set_firmware_size(len(firmware_data))) + else: + http_request_var = await cg.get_variable(config[CONF_HTTP_REQUEST_ID]) + cg.add(var.set_http_request_parent(http_request_var)) + cg.add(var.set_source_url(config[CONF_SOURCE])) + cg.add_define("USE_ESP32_HOSTED_HTTP_UPDATE") - sha256_bytes = bytes.fromhex(config[CONF_SHA256]) - cg.add(var.set_firmware_sha256([HexInt(b) for b in sha256_bytes])) - cg.add(var.set_firmware_data(prog_arr)) - cg.add(var.set_firmware_size(len(firmware_data))) await cg.register_component(var, config) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index 3598a2e69c..fcec1a5f20 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -7,6 +7,12 @@ #include #include #include +#include + +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE +#include "esphome/components/json/json_util.h" +#include "esphome/components/network/util.h" +#endif extern "C" { #include @@ -16,18 +22,50 @@ namespace esphome::esp32_hosted { static const char *const TAG = "esp32_hosted.update"; -// older coprocessor firmware versions have a 1500-byte limit per RPC call +// Older coprocessor firmware versions have a 1500-byte limit per RPC call constexpr size_t CHUNK_SIZE = 1500; +// Compile-time version string from esp_hosted_host_fw_ver.h macros +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) +static const char *const ESP_HOSTED_VERSION_STR = STRINGIFY(ESP_HOSTED_VERSION_MAJOR_1) "." STRINGIFY( + ESP_HOSTED_VERSION_MINOR_1) "." STRINGIFY(ESP_HOSTED_VERSION_PATCH_1); + +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE +// Parse version string "major.minor.patch" into components +// Returns true if parsing succeeded +static bool parse_version(const std::string &version_str, int &major, int &minor, int &patch) { + major = minor = patch = 0; + if (sscanf(version_str.c_str(), "%d.%d.%d", &major, &minor, &patch) >= 2) { + return true; + } + return false; +} + +// Compare two versions, returns: +// -1 if v1 < v2 +// 0 if v1 == v2 +// 1 if v1 > v2 +static int compare_versions(int major1, int minor1, int patch1, int major2, int minor2, int patch2) { + if (major1 != major2) + return major1 < major2 ? -1 : 1; + if (minor1 != minor2) + return minor1 < minor2 ? -1 : 1; + if (patch1 != patch2) + return patch1 < patch2 ? -1 : 1; + return 0; +} +#endif + void Esp32HostedUpdate::setup() { this->update_info_.title = "ESP32 Hosted Coprocessor"; - // if wifi is not present, connect to the coprocessor #ifndef USE_WIFI + // If WiFi is not present, connect to the coprocessor esp_hosted_connect_to_slave(); // NOLINT #endif - // get coprocessor version + // Get coprocessor version esp_hosted_coprocessor_fwver_t ver_info; if (esp_hosted_get_coprocessor_fwversion(&ver_info) == ESP_OK) { this->update_info_.current_version = str_sprintf("%d.%d.%d", ver_info.major1, ver_info.minor1, ver_info.patch1); @@ -36,7 +74,8 @@ void Esp32HostedUpdate::setup() { } ESP_LOGD(TAG, "Coprocessor version: %s", this->update_info_.current_version.c_str()); - // get image version +#ifndef USE_ESP32_HOSTED_HTTP_UPDATE + // Embedded mode: get image version from embedded firmware const int app_desc_offset = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t); if (this->firmware_size_ >= app_desc_offset + sizeof(esp_app_desc_t)) { esp_app_desc_t *app_desc = (esp_app_desc_t *) (this->firmware_data_ + app_desc_offset); @@ -64,58 +103,272 @@ void Esp32HostedUpdate::setup() { this->state_ = update::UPDATE_STATE_NO_UPDATE; } - // publish state + // Publish state this->status_clear_error(); this->publish_state(); +#else + // HTTP mode: retry initial check every 10s until network is ready (max 6 attempts) + // Only if update interval is > 1 minute to avoid redundant checks + if (this->get_update_interval() > 60000) { + this->set_retry("initial_check", 10000, 6, [this](uint8_t) { + if (!network::is_connected()) { + return RetryResult::RETRY; + } + this->check(); + return RetryResult::DONE; + }); + } +#endif } void Esp32HostedUpdate::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 Hosted Update:\n" - " Current Version: %s\n" - " Latest Version: %s\n" - " Latest Size: %zu bytes", - this->update_info_.current_version.c_str(), this->update_info_.latest_version.c_str(), + " Host Library Version: %s\n" + " Coprocessor Version: %s\n" + " Latest Version: %s", + ESP_HOSTED_VERSION_STR, this->update_info_.current_version.c_str(), + this->update_info_.latest_version.c_str()); +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + ESP_LOGCONFIG(TAG, + " Mode: HTTP\n" + " Source URL: %s", + this->source_url_.c_str()); +#else + ESP_LOGCONFIG(TAG, + " Mode: Embedded\n" + " Firmware Size: %zu bytes", this->firmware_size_); +#endif } -void Esp32HostedUpdate::perform(bool force) { - if (this->state_ != update::UPDATE_STATE_AVAILABLE && !force) { - ESP_LOGW(TAG, "Update not available"); +void Esp32HostedUpdate::check() { +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + if (!network::is_connected()) { + ESP_LOGD(TAG, "Network not connected, skipping update check"); return; } + if (!this->fetch_manifest_()) { + return; + } + + // Compare versions + if (this->update_info_.latest_version.empty() || + this->update_info_.latest_version == this->update_info_.current_version) { + this->state_ = update::UPDATE_STATE_NO_UPDATE; + } else { + this->state_ = update::UPDATE_STATE_AVAILABLE; + } + + this->update_info_.has_progress = false; + this->update_info_.progress = 0.0f; + this->status_clear_error(); + this->publish_state(); +#endif +} + +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE +bool Esp32HostedUpdate::fetch_manifest_() { + ESP_LOGD(TAG, "Fetching manifest"); + + auto container = this->http_request_parent_->get(this->source_url_); + if (container == nullptr || container->status_code != 200) { + ESP_LOGE(TAG, "Failed to fetch manifest from %s", this->source_url_.c_str()); + this->status_set_error(LOG_STR("Failed to fetch manifest")); + return false; + } + + // Read manifest JSON into string (manifest is small, ~1KB max) + std::string json_str; + json_str.reserve(container->content_length); + uint8_t buf[256]; + while (container->get_bytes_read() < container->content_length) { + int read = container->read(buf, sizeof(buf)); + if (read > 0) { + json_str.append(reinterpret_cast(buf), read); + } + yield(); + } + container->end(); + + // Parse JSON manifest + // Format: {"versions": [{"version": "2.7.0", "url": "...", "sha256": "..."}]} + // Only consider versions <= host library version to avoid compatibility issues + bool valid = json::parse_json(json_str, [this](JsonObject root) -> bool { + if (!root["versions"].is()) { + ESP_LOGE(TAG, "Manifest does not contain 'versions' array"); + return false; + } + + JsonArray versions = root["versions"].as(); + if (versions.size() == 0) { + ESP_LOGE(TAG, "Manifest 'versions' array is empty"); + return false; + } + + // Find the highest version that is compatible with the host library + // (version <= host version to avoid upgrading coprocessor ahead of host) + int best_major = -1, best_minor = -1, best_patch = -1; + std::string best_version, best_url, best_sha256; + + for (JsonObject entry : versions) { + if (!entry["version"].is() || !entry["url"].is() || + !entry["sha256"].is()) { + continue; // Skip malformed entries + } + + std::string ver_str = entry["version"].as(); + int major, minor, patch; + if (!parse_version(ver_str, major, minor, patch)) { + ESP_LOGW(TAG, "Failed to parse version: %s", ver_str.c_str()); + continue; + } + + // Check if this version is compatible (not newer than host) + if (compare_versions(major, minor, patch, ESP_HOSTED_VERSION_MAJOR_1, ESP_HOSTED_VERSION_MINOR_1, + ESP_HOSTED_VERSION_PATCH_1) > 0) { + continue; + } + + // Check if this is better than our current best + if (best_major < 0 || compare_versions(major, minor, patch, best_major, best_minor, best_patch) > 0) { + best_major = major; + best_minor = minor; + best_patch = patch; + best_version = ver_str; + best_url = entry["url"].as(); + best_sha256 = entry["sha256"].as(); + } + } + + if (best_major < 0) { + ESP_LOGW(TAG, "No compatible firmware version found (host is %s)", ESP_HOSTED_VERSION_STR); + return false; + } + + this->update_info_.latest_version = best_version; + this->firmware_url_ = best_url; + + // Parse SHA256 hex string to bytes + if (!parse_hex(best_sha256, this->firmware_sha256_.data(), 32)) { + ESP_LOGE(TAG, "Invalid SHA256: %s", best_sha256.c_str()); + return false; + } + + ESP_LOGD(TAG, "Best compatible version: %s", this->update_info_.latest_version.c_str()); + + return true; + }); + + if (!valid) { + ESP_LOGE(TAG, "Failed to parse manifest JSON"); + this->status_set_error(LOG_STR("Failed to parse manifest")); + return false; + } + + return true; +} + +bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { + ESP_LOGI(TAG, "Downloading firmware"); + + auto container = this->http_request_parent_->get(this->firmware_url_); + if (container == nullptr || container->status_code != 200) { + ESP_LOGE(TAG, "Failed to fetch firmware"); + this->status_set_error(LOG_STR("Failed to fetch firmware")); + return false; + } + + size_t total_size = container->content_length; + ESP_LOGI(TAG, "Firmware size: %zu bytes", total_size); + + // Begin OTA on coprocessor + esp_err_t err = esp_hosted_slave_ota_begin(); // NOLINT + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to begin OTA: %s", esp_err_to_name(err)); + container->end(); + this->status_set_error(LOG_STR("Failed to begin OTA")); + return false; + } + + // Stream firmware to coprocessor while computing SHA256 + // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) + alignas(32) sha256::SHA256 hasher; + hasher.init(); + + uint8_t buffer[CHUNK_SIZE]; + while (container->get_bytes_read() < total_size) { + int read = container->read(buffer, sizeof(buffer)); + + // Feed watchdog and give other tasks a chance to run + App.feed_wdt(); + yield(); + + // Exit loop if no data available (stream closed or end of data) + if (read <= 0) { + if (read < 0) { + ESP_LOGE(TAG, "Stream closed with error"); + esp_hosted_slave_ota_end(); // NOLINT + container->end(); + this->status_set_error(LOG_STR("Download failed")); + return false; + } + // read == 0: no more data available, exit loop + break; + } + + hasher.add(buffer, read); + err = esp_hosted_slave_ota_write(buffer, read); // NOLINT + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err)); + esp_hosted_slave_ota_end(); // NOLINT + container->end(); + this->status_set_error(LOG_STR("Failed to write OTA data")); + return false; + } + } + container->end(); + + // Verify SHA256 + hasher.calculate(); + if (!hasher.equals_bytes(this->firmware_sha256_.data())) { + ESP_LOGE(TAG, "SHA256 mismatch"); + esp_hosted_slave_ota_end(); // NOLINT + this->status_set_error(LOG_STR("SHA256 verification failed")); + return false; + } + + ESP_LOGI(TAG, "SHA256 verified successfully"); + return true; +} +#else +bool Esp32HostedUpdate::write_embedded_firmware_to_coprocessor_() { if (this->firmware_data_ == nullptr || this->firmware_size_ == 0) { ESP_LOGE(TAG, "No firmware data available"); - return; + this->status_set_error(LOG_STR("No firmware data available")); + return false; } - // ESP32-S3 hardware SHA acceleration requires 32-byte DMA alignment (IDF 5.5.x+) + // Verify SHA256 before writing + // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) alignas(32) sha256::SHA256 hasher; hasher.init(); hasher.add(this->firmware_data_, this->firmware_size_); hasher.calculate(); if (!hasher.equals_bytes(this->firmware_sha256_.data())) { + ESP_LOGE(TAG, "SHA256 mismatch"); this->status_set_error(LOG_STR("SHA256 verification failed")); - this->publish_state(); - return; + return false; } ESP_LOGI(TAG, "Starting OTA update (%zu bytes)", this->firmware_size_); - watchdog::WatchdogManager watchdog(20000); - update::UpdateState prev_state = this->state_; - this->state_ = update::UPDATE_STATE_INSTALLING; - this->update_info_.has_progress = false; - this->publish_state(); - esp_err_t err = esp_hosted_slave_ota_begin(); // NOLINT if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to begin OTA: %s", esp_err_to_name(err)); - this->state_ = prev_state; this->status_set_error(LOG_STR("Failed to begin OTA")); - this->publish_state(); - return; + return false; } uint8_t chunk[CHUNK_SIZE]; @@ -128,42 +381,68 @@ void Esp32HostedUpdate::perform(bool force) { if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err)); esp_hosted_slave_ota_end(); // NOLINT - this->state_ = prev_state; this->status_set_error(LOG_STR("Failed to write OTA data")); - this->publish_state(); - return; + return false; } data_ptr += chunk_size; remaining -= chunk_size; App.feed_wdt(); } - err = esp_hosted_slave_ota_end(); // NOLINT - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to end OTA: %s", esp_err_to_name(err)); + return true; +} +#endif + +void Esp32HostedUpdate::perform(bool force) { + if (this->state_ != update::UPDATE_STATE_AVAILABLE && !force) { + ESP_LOGW(TAG, "Update not available"); + return; + } + + update::UpdateState prev_state = this->state_; + this->state_ = update::UPDATE_STATE_INSTALLING; + this->update_info_.has_progress = false; + this->publish_state(); + + watchdog::WatchdogManager watchdog(60000); + +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + if (!this->stream_firmware_to_coprocessor_()) +#else + if (!this->write_embedded_firmware_to_coprocessor_()) +#endif + { + this->state_ = prev_state; + this->publish_state(); + return; + } + + // End OTA and activate new firmware + esp_err_t end_err = esp_hosted_slave_ota_end(); // NOLINT + if (end_err != ESP_OK) { + ESP_LOGE(TAG, "Failed to end OTA: %s", esp_err_to_name(end_err)); this->state_ = prev_state; this->status_set_error(LOG_STR("Failed to end OTA")); this->publish_state(); return; } - // activate new firmware - err = esp_hosted_slave_ota_activate(); // NOLINT - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to activate OTA: %s", esp_err_to_name(err)); + esp_err_t activate_err = esp_hosted_slave_ota_activate(); // NOLINT + if (activate_err != ESP_OK) { + ESP_LOGE(TAG, "Failed to activate OTA: %s", esp_err_to_name(activate_err)); this->state_ = prev_state; this->status_set_error(LOG_STR("Failed to activate OTA")); this->publish_state(); return; } - // update state + // Update state ESP_LOGI(TAG, "OTA update successful"); this->state_ = update::UPDATE_STATE_NO_UPDATE; this->status_clear_error(); this->publish_state(); - // schedule a restart to ensure everything is in sync + // Schedule a restart to ensure everything is in sync ESP_LOGI(TAG, "Restarting in 1 second"); this->set_timeout(1000, []() { App.safe_reboot(); }); } diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.h b/esphome/components/esp32_hosted/update/esp32_hosted_update.h index 9c087bf72a..7c9645c12a 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.h +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.h @@ -5,26 +5,55 @@ #include "esphome/core/component.h" #include "esphome/components/update/update_entity.h" #include +#include + +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE +#include "esphome/components/http_request/http_request.h" +#endif namespace esphome::esp32_hosted { -class Esp32HostedUpdate : public update::UpdateEntity, public Component { +class Esp32HostedUpdate : public update::UpdateEntity, public PollingComponent { public: void setup() override; void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } + void update() override { this->check(); } // PollingComponent - delegates to check() void perform(bool force) override; - void check() override {} + void check() override; +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + // HTTP mode setters + void set_source_url(const std::string &url) { this->source_url_ = url; } + void set_http_request_parent(http_request::HttpRequestComponent *parent) { this->http_request_parent_ = parent; } +#else + // Embedded mode setters void set_firmware_data(const uint8_t *data) { this->firmware_data_ = data; } void set_firmware_size(size_t size) { this->firmware_size_ = size; } void set_firmware_sha256(const std::array &sha256) { this->firmware_sha256_ = sha256; } +#endif protected: +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + // HTTP mode members + http_request::HttpRequestComponent *http_request_parent_{nullptr}; + std::string source_url_; + std::string firmware_url_; + + // HTTP mode helpers + bool fetch_manifest_(); + bool stream_firmware_to_coprocessor_(); +#else + // Embedded mode members const uint8_t *firmware_data_{nullptr}; size_t firmware_size_{0}; - std::array firmware_sha256_; + + // Embedded mode helper + bool write_embedded_firmware_to_coprocessor_(); +#endif + + std::array firmware_sha256_{}; }; } // namespace esphome::esp32_hosted diff --git a/tests/components/esp32_hosted/test.esp32-p4-idf.yaml b/tests/components/esp32_hosted/test-embedded.esp32-p4-idf.yaml similarity index 92% rename from tests/components/esp32_hosted/test.esp32-p4-idf.yaml rename to tests/components/esp32_hosted/test-embedded.esp32-p4-idf.yaml index 2a76f17e2f..9640032b34 100644 --- a/tests/components/esp32_hosted/test.esp32-p4-idf.yaml +++ b/tests/components/esp32_hosted/test-embedded.esp32-p4-idf.yaml @@ -3,5 +3,6 @@ update: - platform: esp32_hosted name: "Coprocessor Firmware Update" + type: embedded path: $component_dir/test_firmware.bin sha256: de2f256064a0af797747c2b97505dc0b9f3df0de4f489eac731c23ae9ca9cc31 diff --git a/tests/components/esp32_hosted/test-http.esp32-p4-idf.yaml b/tests/components/esp32_hosted/test-http.esp32-p4-idf.yaml new file mode 100644 index 0000000000..17cde0f35d --- /dev/null +++ b/tests/components/esp32_hosted/test-http.esp32-p4-idf.yaml @@ -0,0 +1,10 @@ +<<: !include common.yaml + +http_request: + +update: + - platform: esp32_hosted + name: "Coprocessor Firmware Update" + type: http + source: https://esphome.github.io/esp-hosted-firmware/manifest/esp32c6.json + update_interval: 6h From cea2878b55630159b791ab1a477afe6b286dca6f Mon Sep 17 00:00:00 2001 From: Douwe <61123717+dhoeben@users.noreply.github.com> Date: Sat, 10 Jan 2026 02:25:42 +0100 Subject: [PATCH 0026/2030] [water_heater] (3/4) Implement web_server for new water_heater component (#12511) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- .../components/web_server/list_entities.cpp | 2 +- esphome/components/web_server/web_server.cpp | 194 ++++++++++++++---- esphome/components/web_server/web_server.h | 52 ++++- .../components/web_server/web_server_v1.cpp | 7 + 4 files changed, 214 insertions(+), 41 deletions(-) diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 55beed812f..1e852f6a96 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -136,7 +136,7 @@ bool ListEntitiesIterator::on_alarm_control_panel(alarm_control_panel::AlarmCont #ifdef USE_WATER_HEATER bool ListEntitiesIterator::on_water_heater(water_heater::WaterHeater *obj) { - // Water heater web_server support not yet implemented - this stub acknowledges the entity + this->events_->deferrable_send_state(obj, "state_detail_all", WebServer::water_heater_all_json_generator); return true; } #endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index cab177c182..12115083f6 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -28,6 +28,10 @@ #include "esphome/components/climate/climate.h" #endif +#ifdef USE_WATER_HEATER +#include "esphome/components/water_heater/water_heater.h" +#endif + #ifdef USE_WEBSERVER_LOCAL #if USE_WEBSERVER_VERSION == 2 #include "server_index_v2.h" @@ -558,7 +562,7 @@ static void set_json_icon_state_value(JsonObject &root, EntityBase *obj, const c // Helper to get request detail parameter static JsonDetail get_request_detail(AsyncWebServerRequest *request) { - auto *param = request->getParam("detail"); + auto *param = request->getParam(ESPHOME_F("detail")); return (param && param->value() == "all") ? DETAIL_ALL : DETAIL_STATE; } @@ -837,10 +841,10 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc } auto call = is_on ? obj->turn_on() : obj->turn_off(); - parse_int_param_(request, "speed_level", call, &decltype(call)::set_speed); + parse_int_param_(request, ESPHOME_F("speed_level"), call, &decltype(call)::set_speed); - if (request->hasParam("oscillation")) { - auto speed = request->getParam("oscillation")->value(); + if (request->hasParam(ESPHOME_F("oscillation"))) { + auto speed = request->getParam(ESPHOME_F("oscillation"))->value(); auto val = parse_on_off(speed.c_str()); switch (val) { case PARSE_ON: @@ -920,20 +924,20 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa if (is_on) { // Parse color parameters - parse_light_param_(request, "brightness", call, &decltype(call)::set_brightness, 255.0f); - parse_light_param_(request, "r", call, &decltype(call)::set_red, 255.0f); - parse_light_param_(request, "g", call, &decltype(call)::set_green, 255.0f); - parse_light_param_(request, "b", call, &decltype(call)::set_blue, 255.0f); - parse_light_param_(request, "white_value", call, &decltype(call)::set_white, 255.0f); - parse_light_param_(request, "color_temp", call, &decltype(call)::set_color_temperature); + parse_light_param_(request, ESPHOME_F("brightness"), call, &decltype(call)::set_brightness, 255.0f); + parse_light_param_(request, ESPHOME_F("r"), call, &decltype(call)::set_red, 255.0f); + parse_light_param_(request, ESPHOME_F("g"), call, &decltype(call)::set_green, 255.0f); + parse_light_param_(request, ESPHOME_F("b"), call, &decltype(call)::set_blue, 255.0f); + parse_light_param_(request, ESPHOME_F("white_value"), call, &decltype(call)::set_white, 255.0f); + parse_light_param_(request, ESPHOME_F("color_temp"), call, &decltype(call)::set_color_temperature); // Parse timing parameters - parse_light_param_uint_(request, "flash", call, &decltype(call)::set_flash_length, 1000); + parse_light_param_uint_(request, ESPHOME_F("flash"), call, &decltype(call)::set_flash_length, 1000); } - parse_light_param_uint_(request, "transition", call, &decltype(call)::set_transition_length, 1000); + parse_light_param_uint_(request, ESPHOME_F("transition"), call, &decltype(call)::set_transition_length, 1000); if (is_on) { - parse_string_param_(request, "effect", call, &decltype(call)::set_effect); + parse_string_param_(request, ESPHOME_F("effect"), call, &decltype(call)::set_effect); } this->defer([call]() mutable { call.perform(); }); @@ -1016,14 +1020,14 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa } auto traits = obj->get_traits(); - if ((request->hasParam("position") && !traits.get_supports_position()) || - (request->hasParam("tilt") && !traits.get_supports_tilt())) { + if ((request->hasParam(ESPHOME_F("position")) && !traits.get_supports_position()) || + (request->hasParam(ESPHOME_F("tilt")) && !traits.get_supports_tilt())) { request->send(409); return; } - parse_float_param_(request, "position", call, &decltype(call)::set_position); - parse_float_param_(request, "tilt", call, &decltype(call)::set_tilt); + parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); + parse_float_param_(request, ESPHOME_F("tilt"), call, &decltype(call)::set_tilt); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1082,7 +1086,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM } auto call = obj->make_call(); - parse_float_param_(request, "value", call, &decltype(call)::set_value); + parse_float_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1150,12 +1154,12 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat auto call = obj->make_call(); - if (!request->hasParam("value")) { + if (!request->hasParam(ESPHOME_F("value"))) { request->send(409); return; } - parse_string_param_(request, "value", call, &decltype(call)::set_date); + parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_date); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1214,12 +1218,12 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat auto call = obj->make_call(); - if (!request->hasParam("value")) { + if (!request->hasParam(ESPHOME_F("value"))) { request->send(409); return; } - parse_string_param_(request, "value", call, &decltype(call)::set_time); + parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_time); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1277,12 +1281,12 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur auto call = obj->make_call(); - if (!request->hasParam("value")) { + if (!request->hasParam(ESPHOME_F("value"))) { request->send(409); return; } - parse_string_param_(request, "value", call, &decltype(call)::set_datetime); + parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_datetime); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1342,7 +1346,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat } auto call = obj->make_call(); - parse_string_param_(request, "value", call, &decltype(call)::set_value); + parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1400,7 +1404,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM } auto call = obj->make_call(); - parse_string_param_(request, "option", call, &decltype(call)::set_option); + parse_string_param_(request, ESPHOME_F("option"), call, &decltype(call)::set_option); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1460,14 +1464,15 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url auto call = obj->make_call(); // Parse string mode parameters - parse_string_param_(request, "mode", call, &decltype(call)::set_mode); - parse_string_param_(request, "fan_mode", call, &decltype(call)::set_fan_mode); - parse_string_param_(request, "swing_mode", call, &decltype(call)::set_swing_mode); + parse_string_param_(request, ESPHOME_F("mode"), call, &decltype(call)::set_mode); + parse_string_param_(request, ESPHOME_F("fan_mode"), call, &decltype(call)::set_fan_mode); + parse_string_param_(request, ESPHOME_F("swing_mode"), call, &decltype(call)::set_swing_mode); // Parse temperature parameters - parse_float_param_(request, "target_temperature_high", call, &decltype(call)::set_target_temperature_high); - parse_float_param_(request, "target_temperature_low", call, &decltype(call)::set_target_temperature_low); - parse_float_param_(request, "target_temperature", call, &decltype(call)::set_target_temperature); + parse_float_param_(request, ESPHOME_F("target_temperature_high"), call, + &decltype(call)::set_target_temperature_high); + parse_float_param_(request, ESPHOME_F("target_temperature_low"), call, &decltype(call)::set_target_temperature_low); + parse_float_param_(request, ESPHOME_F("target_temperature"), call, &decltype(call)::set_target_temperature); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1706,12 +1711,12 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa } auto traits = obj->get_traits(); - if (request->hasParam("position") && !traits.get_supports_position()) { + if (request->hasParam(ESPHOME_F("position")) && !traits.get_supports_position()) { request->send(409); return; } - parse_float_param_(request, "position", call, &decltype(call)::set_position); + parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); this->defer([call]() mutable { call.perform(); }); request->send(200); @@ -1764,7 +1769,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques } auto call = obj->make_call(); - parse_string_param_(request, "code", call, &decltype(call)::set_code); + parse_string_param_(request, ESPHOME_F("code"), call, &decltype(call)::set_code); // Lookup table for alarm control panel methods static const struct { @@ -1825,6 +1830,117 @@ std::string WebServer::alarm_control_panel_json_(alarm_control_panel::AlarmContr } #endif +#ifdef USE_WATER_HEATER +void WebServer::on_water_heater_update(water_heater::WaterHeater *obj) { + if (!this->include_internal_ && obj->is_internal()) + return; + this->events_.deferrable_send_state(obj, "state", water_heater_state_json_generator); +} +void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (water_heater::WaterHeater *obj : App.get_water_heaters()) { + auto entity_match = match.match_entity(obj); + if (!entity_match.matched) + continue; + + if (request->method() == HTTP_GET && entity_match.action_is_empty) { + auto detail = get_request_detail(request); + std::string data = this->water_heater_json_(obj, detail); + request->send(200, "application/json", data.c_str()); + return; + } + if (!match.method_equals("set")) { + request->send(404); + return; + } + auto call = obj->make_call(); + // Use base class reference for template deduction (make_call returns WaterHeaterCallInternal) + water_heater::WaterHeaterCall &base_call = call; + + // Parse mode parameter + parse_string_param_(request, ESPHOME_F("mode"), base_call, &water_heater::WaterHeaterCall::set_mode); + + // Parse temperature parameters + parse_float_param_(request, ESPHOME_F("target_temperature"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature); + parse_float_param_(request, ESPHOME_F("target_temperature_low"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature_low); + parse_float_param_(request, ESPHOME_F("target_temperature_high"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature_high); + + // Parse away mode parameter + parse_bool_param_(request, ESPHOME_F("away"), base_call, &water_heater::WaterHeaterCall::set_away); + + // Parse on/off parameter + parse_bool_param_(request, ESPHOME_F("is_on"), base_call, &water_heater::WaterHeaterCall::set_on); + + this->defer([call]() mutable { call.perform(); }); + request->send(200); + return; + } + request->send(404); +} + +std::string WebServer::water_heater_state_json_generator(WebServer *web_server, void *source) { + return web_server->water_heater_json_(static_cast(source), DETAIL_STATE); +} +std::string WebServer::water_heater_all_json_generator(WebServer *web_server, void *source) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + return web_server->water_heater_json_(static_cast(source), DETAIL_ALL); +} +std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config) { + json::JsonBuilder builder; + JsonObject root = builder.root(); + char buf[PSTR_LOCAL_SIZE]; + + const auto mode = obj->get_mode(); + const char *mode_s = PSTR_LOCAL(water_heater::water_heater_mode_to_string(mode)); + + set_json_icon_state_value(root, obj, "water_heater", mode_s, mode, start_config); + + auto traits = obj->get_traits(); + + if (start_config == DETAIL_ALL) { + JsonArray modes = root[ESPHOME_F("modes")].to(); + for (auto m : traits.get_supported_modes()) + modes.add(PSTR_LOCAL(water_heater::water_heater_mode_to_string(m))); + this->add_sorting_info_(root, obj); + } + + if (traits.get_supports_current_temperature()) { + float current = obj->get_current_temperature(); + if (!std::isnan(current)) + root[ESPHOME_F("current_temperature")] = current; + } + + if (traits.get_supports_two_point_target_temperature()) { + float low = obj->get_target_temperature_low(); + float high = obj->get_target_temperature_high(); + if (!std::isnan(low)) + root[ESPHOME_F("target_temperature_low")] = low; + if (!std::isnan(high)) + root[ESPHOME_F("target_temperature_high")] = high; + } else { + float target = obj->get_target_temperature(); + if (!std::isnan(target)) + root[ESPHOME_F("target_temperature")] = target; + } + + root[ESPHOME_F("min_temperature")] = traits.get_min_temperature(); + root[ESPHOME_F("max_temperature")] = traits.get_max_temperature(); + root[ESPHOME_F("step")] = traits.get_target_temperature_step(); + + if (traits.get_supports_away_mode()) { + root[ESPHOME_F("away")] = obj->is_away(); + } + + if (traits.has_feature_flags(water_heater::WATER_HEATER_SUPPORTS_ON_OFF)) { + root[ESPHOME_F("is_on")] = obj->is_on(); + } + + return builder.serialize(); +} +#endif + #ifdef USE_EVENT void WebServer::on_event(event::Event *obj) { if (!this->include_internal_ && obj->is_internal()) @@ -2060,6 +2176,9 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const { #endif #ifdef USE_UPDATE "update", +#endif +#ifdef USE_WATER_HEATER + "water_heater", #endif }; @@ -2220,6 +2339,11 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { else if (match.domain_equals("update")) { this->handle_update_request(request, match); } +#endif +#ifdef USE_WATER_HEATER + else if (match.domain_equals("water_heater")) { + this->handle_water_heater_request(request, match); + } #endif else { // No matching handler found - send 404 diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 3e1dd867c6..c52cf981e0 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -35,6 +35,13 @@ extern const size_t ESPHOME_WEBSERVER_JS_INCLUDE_SIZE; namespace esphome::web_server { +// Type for parameter names that can be stored in flash on ESP8266 +#ifdef USE_ESP8266 +using ParamNameType = const __FlashStringHelper *; +#else +using ParamNameType = const char *; +#endif + /// Result of matching a URL against an entity struct EntityMatchResult { bool matched; ///< True if entity matched the URL @@ -429,6 +436,16 @@ class WebServer : public Controller, static std::string alarm_control_panel_all_json_generator(WebServer *web_server, void *source); #endif +#ifdef USE_WATER_HEATER + void on_water_heater_update(water_heater::WaterHeater *obj) override; + + /// Handle a water_heater request under '/water_heater//'. + void handle_water_heater_request(AsyncWebServerRequest *request, const UrlMatch &match); + + static std::string water_heater_state_json_generator(WebServer *web_server, void *source); + static std::string water_heater_all_json_generator(WebServer *web_server, void *source); +#endif + #ifdef USE_EVENT void on_event(event::Event *obj) override; @@ -472,7 +489,7 @@ class WebServer : public Controller, #ifdef USE_LIGHT // Helper to parse and apply a float parameter with optional scaling template - void parse_light_param_(AsyncWebServerRequest *request, const char *param_name, T &call, Ret (T::*setter)(float), + void parse_light_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(float), float scale = 1.0f) { if (request->hasParam(param_name)) { auto value = parse_number(request->getParam(param_name)->value().c_str()); @@ -484,7 +501,7 @@ class WebServer : public Controller, // Helper to parse and apply a uint32_t parameter with optional scaling template - void parse_light_param_uint_(AsyncWebServerRequest *request, const char *param_name, T &call, + void parse_light_param_uint_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(uint32_t), uint32_t scale = 1) { if (request->hasParam(param_name)) { auto value = parse_number(request->getParam(param_name)->value().c_str()); @@ -497,7 +514,7 @@ class WebServer : public Controller, // Generic helper to parse and apply a float parameter template - void parse_float_param_(AsyncWebServerRequest *request, const char *param_name, T &call, Ret (T::*setter)(float)) { + void parse_float_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(float)) { if (request->hasParam(param_name)) { auto value = parse_number(request->getParam(param_name)->value().c_str()); if (value.has_value()) { @@ -508,7 +525,7 @@ class WebServer : public Controller, // Generic helper to parse and apply an int parameter template - void parse_int_param_(AsyncWebServerRequest *request, const char *param_name, T &call, Ret (T::*setter)(int)) { + void parse_int_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(int)) { if (request->hasParam(param_name)) { auto value = parse_number(request->getParam(param_name)->value().c_str()); if (value.has_value()) { @@ -519,7 +536,7 @@ class WebServer : public Controller, // Generic helper to parse and apply a string parameter template - void parse_string_param_(AsyncWebServerRequest *request, const char *param_name, T &call, + void parse_string_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(const std::string &)) { if (request->hasParam(param_name)) { // .c_str() is required for Arduino framework where value() returns Arduino String instead of std::string @@ -528,6 +545,28 @@ class WebServer : public Controller, } } + // Generic helper to parse and apply a bool parameter + // Accepts: "on", "true", "1" (case-insensitive) as true + // Accepts: "off", "false", "0" (case-insensitive) as false + // Invalid values are ignored (setter not called) + template + void parse_bool_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(bool)) { + if (request->hasParam(param_name)) { + auto param_value = request->getParam(param_name)->value(); + // First check on/off (default), then true/false (custom) + auto val = parse_on_off(param_value.c_str()); + if (val == PARSE_NONE) { + val = parse_on_off(param_value.c_str(), "true", "false"); + } + if (val == PARSE_ON || param_value == "1") { + (call.*setter)(true); + } else if (val == PARSE_OFF || param_value == "0") { + (call.*setter)(false); + } + // PARSE_NONE/PARSE_TOGGLE: ignore invalid values + } + } + web_server_base::WebServerBase *base_; #ifdef USE_ESP32 AsyncEventSource events_{"/events", this}; @@ -606,6 +645,9 @@ class WebServer : public Controller, #ifdef USE_EVENT std::string event_json_(event::Event *obj, const std::string &event_type, JsonDetail start_config); #endif +#ifdef USE_WATER_HEATER + std::string water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config); +#endif #ifdef USE_UPDATE std::string update_json_(update::UpdateEntity *obj, JsonDetail start_config); #endif diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp index a21e9cb9ff..c3fe6f6780 100644 --- a/esphome/components/web_server/web_server_v1.cpp +++ b/esphome/components/web_server/web_server_v1.cpp @@ -232,6 +232,13 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { } #endif +#ifdef USE_WATER_HEATER + for (auto *obj : App.get_water_heaters()) { + if (this->include_internal_ || !obj->is_internal()) + write_row(stream, obj, "water_heater", ""); + } +#endif + stream->print(ESPHOME_F("

See ESPHome Web API for " "REST API documentation.

")); #if defined(USE_WEBSERVER_OTA) && !defined(USE_WEBSERVER_OTA_DISABLED) From da7680f7d996431362755ec1296d3dfd0469dfdb Mon Sep 17 00:00:00 2001 From: esphomebot Date: Sat, 10 Jan 2026 15:38:01 +1300 Subject: [PATCH 0027/2030] Update webserver local assets to 20260110-013228 (#13113) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/captive_portal/captive_index.h | 154 +- .../components/web_server/server_index_v2.h | 2434 +-- .../components/web_server/server_index_v3.h | 15165 ++++++++-------- 3 files changed, 8906 insertions(+), 8847 deletions(-) diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index ad74c395f3..645ebb7a2f 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -7,83 +7,83 @@ namespace esphome::captive_portal { #ifdef USE_CAPTIVE_PORTAL_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x95, 0x56, 0xeb, 0x6f, 0xd4, 0x38, 0x10, 0xff, 0xce, - 0x5f, 0xe1, 0x33, 0x8f, 0x26, 0xd0, 0x3c, 0xb7, 0xdb, 0x96, 0x6c, 0x12, 0x04, 0xdc, 0x21, 0x90, 0x28, 0x20, 0xb5, - 0x70, 0x1f, 0x10, 0x52, 0xbd, 0xc9, 0x64, 0x63, 0x9a, 0x38, 0x39, 0xdb, 0xfb, 0x62, 0xb5, 0xf7, 0xb7, 0xdf, 0x38, - 0xc9, 0x6e, 0xb7, 0x15, 0x9c, 0xee, 0x5a, 0x35, 0x1d, 0xdb, 0xf3, 0xf8, 0xcd, 0x78, 0x1e, 0x8e, 0x7f, 0xcb, 0x9b, - 0x4c, 0xaf, 0x5b, 0x20, 0xa5, 0xae, 0xab, 0x34, 0x36, 0x5f, 0x52, 0x31, 0x31, 0x4b, 0x40, 0xe0, 0x0a, 0x58, 0x9e, - 0xc6, 0x35, 0x68, 0x46, 0xb2, 0x92, 0x49, 0x05, 0x3a, 0xf9, 0x7c, 0xf5, 0xc6, 0x39, 0x4f, 0xe3, 0x8a, 0x8b, 0x1b, - 0x22, 0xa1, 0x4a, 0x78, 0xd6, 0x08, 0x52, 0x4a, 0x28, 0x92, 0x9c, 0x69, 0x16, 0xf1, 0x9a, 0xcd, 0x60, 0x10, 0x11, - 0xac, 0x86, 0x64, 0xc1, 0x61, 0xd9, 0x36, 0x52, 0x13, 0xe4, 0xd3, 0x20, 0x74, 0x42, 0x97, 0x3c, 0xd7, 0x65, 0x92, - 0xc3, 0x82, 0x67, 0xe0, 0x74, 0x8b, 0x63, 0x2e, 0xb8, 0xe6, 0xac, 0x72, 0x54, 0xc6, 0x2a, 0x48, 0x82, 0xe3, 0xb9, - 0x02, 0xd9, 0x2d, 0xd8, 0x14, 0xd7, 0xa2, 0xa1, 0x69, 0xac, 0x32, 0xc9, 0x5b, 0x4d, 0x0c, 0xd4, 0xa4, 0x6e, 0xf2, - 0x79, 0x05, 0xa9, 0xe7, 0x31, 0x85, 0x90, 0x94, 0xc7, 0x45, 0x0e, 0x2b, 0x77, 0xea, 0x67, 0x99, 0x0f, 0xe7, 0xe7, - 0xee, 0x77, 0xf5, 0x00, 0x9d, 0x9a, 0xd7, 0x68, 0xcd, 0xad, 0x9a, 0x8c, 0x69, 0xde, 0x08, 0x57, 0x01, 0x93, 0x59, - 0x99, 0x24, 0x09, 0x7d, 0xa1, 0xd8, 0x02, 0xe8, 0x93, 0x27, 0xd6, 0x9e, 0x69, 0x06, 0xfa, 0x8f, 0x0a, 0x0c, 0xa9, - 0x5e, 0xad, 0xaf, 0xd8, 0xec, 0x03, 0x02, 0xb7, 0x28, 0x53, 0x3c, 0x07, 0x6a, 0x7f, 0xf5, 0xbf, 0xb9, 0x4a, 0xaf, - 0x2b, 0x70, 0x73, 0xae, 0xda, 0x8a, 0xad, 0x13, 0x3a, 0x45, 0xad, 0x37, 0xd4, 0x9e, 0x14, 0x73, 0x91, 0x19, 0xe5, - 0x44, 0x59, 0x60, 0x6f, 0x2a, 0x40, 0x78, 0xc9, 0x05, 0xd3, 0xa5, 0x5b, 0xb3, 0x95, 0xd5, 0x13, 0x5c, 0x58, 0xe1, - 0x53, 0x0b, 0x9e, 0x05, 0xbe, 0x6f, 0x1f, 0x77, 0x1f, 0xdf, 0xf6, 0xf0, 0xff, 0x44, 0x82, 0x9e, 0x4b, 0x41, 0x98, - 0x75, 0x1d, 0xb7, 0xc8, 0x49, 0xf2, 0x84, 0x5e, 0x04, 0x21, 0x09, 0x9e, 0xbb, 0xe1, 0xf8, 0xbd, 0x7b, 0x46, 0x4e, - 0xf0, 0x7f, 0x76, 0xe6, 0x8c, 0x49, 0x70, 0x82, 0x9f, 0x30, 0x74, 0xc7, 0xc4, 0xff, 0x41, 0x49, 0xc1, 0xab, 0x2a, - 0xa1, 0xa2, 0x11, 0x40, 0x89, 0xd2, 0xb2, 0xb9, 0x81, 0x84, 0x66, 0x73, 0x29, 0x11, 0xfb, 0xeb, 0xa6, 0x6a, 0x24, - 0xf5, 0xd2, 0x07, 0xff, 0x4b, 0xa1, 0x96, 0x4c, 0xa8, 0xa2, 0x91, 0x75, 0x42, 0xbb, 0xe8, 0x5b, 0x8f, 0x36, 0x7a, - 0x4b, 0xcc, 0xc7, 0x3e, 0x38, 0x74, 0x1a, 0xc9, 0x67, 0x5c, 0x24, 0xd4, 0x68, 0x3c, 0x47, 0x23, 0xd7, 0xf6, 0x76, - 0xef, 0x3d, 0x33, 0xde, 0x0f, 0xfe, 0x34, 0xd6, 0xd7, 0xeb, 0x58, 0x2d, 0x66, 0x64, 0x55, 0x57, 0x42, 0x25, 0xb4, - 0xd4, 0xba, 0x8d, 0x3c, 0x6f, 0xb9, 0x5c, 0xba, 0xcb, 0x91, 0xdb, 0xc8, 0x99, 0x17, 0xfa, 0xbe, 0xef, 0x21, 0x07, - 0x25, 0x7d, 0x22, 0xd0, 0xf0, 0x84, 0x92, 0x12, 0xf8, 0xac, 0xd4, 0x1d, 0x9d, 0x3e, 0xda, 0xc0, 0x36, 0x36, 0x1c, - 0xe9, 0xf5, 0xb7, 0x03, 0x2b, 0xfc, 0xc0, 0x0a, 0xbc, 0x60, 0x16, 0xdd, 0xb9, 0x79, 0xd4, 0xb9, 0x79, 0xc6, 0x42, - 0x12, 0x12, 0xbf, 0xfb, 0x0d, 0x1d, 0x43, 0x0f, 0x2b, 0xe7, 0xde, 0x8a, 0x1c, 0xac, 0x0c, 0x55, 0x9f, 0x3a, 0xcf, - 0xf7, 0xb2, 0x81, 0xd9, 0x59, 0x04, 0xfe, 0xed, 0x86, 0x11, 0x78, 0x7b, 0x7a, 0xb8, 0x76, 0xc2, 0x2f, 0x87, 0x0c, - 0xc6, 0x5a, 0x19, 0x7c, 0x39, 0x65, 0x63, 0x32, 0x1e, 0x76, 0xc6, 0x8e, 0xa1, 0xf7, 0x2b, 0x32, 0x5e, 0x20, 0x47, - 0xed, 0x9c, 0x3a, 0x63, 0x36, 0x22, 0xa3, 0x01, 0x08, 0x52, 0xb8, 0x7d, 0x8a, 0x82, 0x07, 0x7b, 0xce, 0xe8, 0xc7, - 0x91, 0x97, 0x52, 0x3b, 0xa2, 0xf4, 0xd6, 0xf3, 0xe6, 0xd0, 0x73, 0xf7, 0x7b, 0x83, 0x39, 0x45, 0x29, 0x46, 0x06, - 0x74, 0x56, 0x5a, 0xd4, 0xc3, 0xc2, 0x2a, 0xf8, 0x0c, 0xb3, 0xbe, 0x11, 0xd4, 0x76, 0x75, 0x09, 0xc2, 0xda, 0x89, - 0x1a, 0x41, 0xe8, 0x4e, 0xac, 0xfb, 0x27, 0xda, 0xde, 0xec, 0xf3, 0x5f, 0x73, 0x8d, 0x65, 0xa6, 0x5d, 0x53, 0xb0, - 0xc7, 0xfb, 0xdd, 0x69, 0x93, 0xaf, 0x7f, 0x51, 0x1a, 0x65, 0xd0, 0xd7, 0x05, 0x17, 0x02, 0xe4, 0x15, 0xac, 0xf0, - 0xe6, 0x2e, 0x5e, 0xbe, 0x26, 0x2f, 0xf3, 0x5c, 0x82, 0x52, 0x11, 0xa1, 0xcf, 0x34, 0xd6, 0x40, 0xf6, 0xdf, 0x75, - 0x05, 0x77, 0x74, 0xfd, 0xc9, 0xdf, 0x70, 0xf2, 0x01, 0xf4, 0xb2, 0x91, 0x37, 0x83, 0x36, 0x03, 0x6d, 0x62, 0x2a, - 0x4c, 0x22, 0x4e, 0xd6, 0x2a, 0x57, 0x55, 0xd8, 0x3e, 0xac, 0xc0, 0x46, 0x3b, 0xed, 0xad, 0x57, 0x62, 0x17, 0xa8, - 0xeb, 0x38, 0xe7, 0x0b, 0x92, 0x55, 0xd8, 0x21, 0xb0, 0x5c, 0x7a, 0x55, 0x94, 0x3c, 0x20, 0xdd, 0x4f, 0x23, 0x32, - 0x94, 0xbe, 0x49, 0xe8, 0x4f, 0x3a, 0xc0, 0xab, 0xf5, 0xbb, 0xdc, 0x3a, 0x52, 0x58, 0xfb, 0x47, 0xb6, 0xbb, 0x60, - 0xd5, 0x1c, 0x48, 0x42, 0x74, 0xc9, 0xd5, 0x2d, 0xc0, 0xc9, 0x2f, 0xc5, 0x5a, 0x75, 0x83, 0x52, 0x05, 0x1e, 0x2b, - 0xcb, 0xa6, 0xe9, 0x60, 0x2e, 0x66, 0x7d, 0x83, 0xa4, 0x0f, 0xe9, 0x3d, 0x44, 0x4e, 0x05, 0x85, 0xde, 0xf3, 0x11, - 0x2c, 0x3b, 0x65, 0x09, 0x57, 0xa2, 0x75, 0x7b, 0xbb, 0xdf, 0x8c, 0x55, 0xcb, 0xc4, 0x7d, 0x41, 0x03, 0xd0, 0x94, - 0x0a, 0x36, 0x36, 0xa4, 0x4c, 0xbd, 0x20, 0xd3, 0xde, 0xa0, 0xc7, 0x76, 0xe4, 0xa3, 0x0d, 0x47, 0x8d, 0xa6, 0x5f, - 0xed, 0x35, 0xc6, 0x1e, 0x86, 0x26, 0xbd, 0xde, 0xda, 0xb7, 0x7e, 0xfc, 0x35, 0x07, 0xb9, 0xbe, 0x84, 0x0a, 0x32, - 0xdd, 0x48, 0x8b, 0x3e, 0x44, 0x2b, 0x98, 0x4a, 0x9d, 0xc3, 0x6f, 0xaf, 0x2e, 0xde, 0x27, 0x8d, 0x25, 0xed, 0xe3, - 0x5f, 0x71, 0x9b, 0x51, 0xf0, 0x15, 0x47, 0xc1, 0xdf, 0xc9, 0x91, 0x19, 0x06, 0x47, 0xdf, 0x50, 0xb4, 0xf3, 0xf7, - 0xfa, 0x76, 0x22, 0x98, 0x72, 0x7e, 0x86, 0x2d, 0xe1, 0xd8, 0x78, 0xe8, 0x9c, 0x8e, 0xed, 0x2d, 0xda, 0x47, 0x04, - 0x88, 0xbb, 0xeb, 0xeb, 0xd8, 0xdf, 0x4d, 0x8b, 0x4d, 0x9f, 0x6e, 0xa6, 0xcd, 0xca, 0x51, 0xfc, 0x07, 0x17, 0xb3, - 0x88, 0x8b, 0x12, 0x24, 0xd7, 0x5b, 0x84, 0x8b, 0x13, 0xa2, 0x9d, 0xeb, 0x4d, 0xcb, 0xf2, 0xdc, 0x9c, 0x8c, 0xdb, - 0xd5, 0xa4, 0xc0, 0x79, 0x62, 0x38, 0x21, 0x0a, 0xa0, 0xde, 0xf6, 0xe7, 0x5d, 0x47, 0x89, 0x9e, 0x8f, 0x1f, 0x6f, - 0x4d, 0xc2, 0x6d, 0x34, 0x5e, 0x96, 0xc3, 0x2a, 0x3e, 0x13, 0x51, 0x86, 0xc0, 0x41, 0xf6, 0x42, 0x05, 0xab, 0x79, - 0xb5, 0x8e, 0x14, 0xf6, 0x36, 0x07, 0x07, 0x0d, 0x2f, 0xb6, 0xd3, 0xb9, 0xd6, 0x8d, 0x40, 0xdb, 0x32, 0x07, 0x19, - 0xf9, 0x93, 0x9e, 0x70, 0x24, 0xcb, 0xf9, 0x5c, 0x45, 0xee, 0x48, 0x42, 0x3d, 0x99, 0xb2, 0xec, 0x66, 0x26, 0x9b, - 0xb9, 0xc8, 0x9d, 0xcc, 0x74, 0xda, 0xe8, 0x61, 0x50, 0xb0, 0x11, 0x64, 0x93, 0x61, 0x55, 0x14, 0xc5, 0x04, 0x43, - 0x01, 0x4e, 0xdf, 0xcb, 0xa2, 0xd0, 0x3d, 0x31, 0x62, 0x07, 0x30, 0xdd, 0xd0, 0x6c, 0xf4, 0x18, 0x71, 0x04, 0x3c, - 0x9e, 0xec, 0xdc, 0xf1, 0x27, 0xd8, 0xc2, 0x15, 0x2a, 0x69, 0xb1, 0xb6, 0x11, 0xe6, 0xb6, 0x66, 0x5c, 0x1c, 0xa2, - 0x37, 0x69, 0x32, 0x19, 0xc6, 0x0f, 0x86, 0xa5, 0x33, 0xd3, 0x0d, 0xa1, 0x09, 0x0e, 0x98, 0x7e, 0x86, 0x46, 0xe1, - 0xa9, 0xdf, 0xae, 0xb6, 0xee, 0x90, 0x20, 0x9b, 0x1d, 0x77, 0x51, 0xc1, 0x6a, 0xf2, 0x7d, 0xae, 0x34, 0x2f, 0xd6, - 0xce, 0x30, 0x83, 0x23, 0x4c, 0x16, 0x9c, 0xbd, 0x53, 0x64, 0x05, 0x10, 0x93, 0xce, 0x86, 0xc3, 0x35, 0xd4, 0x6a, - 0x88, 0xd3, 0x5e, 0x4d, 0x97, 0xa0, 0x77, 0x75, 0xfd, 0x1b, 0xb7, 0xc9, 0xc5, 0x4d, 0xcd, 0x24, 0x8e, 0x0a, 0x67, - 0xda, 0x60, 0x4c, 0xeb, 0xc8, 0x39, 0xc3, 0xbb, 0x1a, 0xb6, 0x8c, 0x32, 0xf4, 0x1c, 0x61, 0x76, 0xb3, 0x75, 0x17, - 0xef, 0xa0, 0x5d, 0x11, 0xd5, 0x54, 0x3c, 0x1f, 0xf8, 0x3a, 0x16, 0xe2, 0xef, 0xc3, 0x13, 0xe0, 0x75, 0x13, 0xb3, - 0xb7, 0x0b, 0xf5, 0x49, 0x71, 0xce, 0x02, 0xff, 0x27, 0x37, 0x92, 0x17, 0x45, 0x38, 0x2d, 0xf6, 0x91, 0x32, 0x63, - 0xd2, 0x94, 0x46, 0x97, 0x5a, 0xb1, 0xd7, 0xbf, 0x66, 0x4c, 0x66, 0xe0, 0x03, 0x05, 0x23, 0x8c, 0xef, 0x9b, 0x80, - 0xf0, 0x3c, 0xc1, 0x4e, 0x95, 0x1e, 0xb4, 0x2f, 0x64, 0x0c, 0x76, 0x47, 0x48, 0xdd, 0x69, 0x46, 0xfd, 0x59, 0x87, - 0x3e, 0x7d, 0xdd, 0x60, 0x7d, 0x60, 0xdb, 0x11, 0x33, 0xa2, 0x1b, 0x32, 0x84, 0xc0, 0x75, 0xdd, 0x78, 0x2a, 0xd3, - 0x4f, 0x15, 0x30, 0x05, 0x64, 0xc9, 0xb8, 0x76, 0xb1, 0x1a, 0x3b, 0xfe, 0xbe, 0x8e, 0x51, 0x29, 0xb2, 0xa6, 0x43, - 0xc1, 0xc6, 0xe5, 0xa8, 0x37, 0x70, 0x09, 0xda, 0x68, 0x32, 0x06, 0x46, 0x69, 0x6c, 0x46, 0x2e, 0x61, 0x5d, 0x4b, - 0x4b, 0xbc, 0x25, 0x2f, 0xb8, 0x79, 0xb2, 0xa4, 0x71, 0x97, 0xe4, 0x46, 0x83, 0x89, 0x73, 0xff, 0xbc, 0xea, 0xa8, - 0x0a, 0xc4, 0x0c, 0x27, 0xe9, 0x28, 0x24, 0xe8, 0x76, 0x06, 0x65, 0x53, 0x61, 0x58, 0x93, 0xcb, 0xcb, 0x77, 0xbf, - 0xa7, 0x06, 0xcc, 0xad, 0x1c, 0xf6, 0xa7, 0x5e, 0xcc, 0x10, 0x83, 0xd4, 0xe9, 0x49, 0xff, 0xa8, 0x6a, 0xb1, 0xbf, - 0xa0, 0x07, 0xf9, 0x1d, 0x1d, 0x9f, 0x86, 0xcd, 0x5e, 0x4f, 0xf7, 0xd7, 0x95, 0x4a, 0x7a, 0x89, 0x80, 0x62, 0x6f, - 0x58, 0xc4, 0x9e, 0x01, 0xdc, 0x9f, 0x97, 0x03, 0x1f, 0xc6, 0xe9, 0xe3, 0xd5, 0x4b, 0xf2, 0xb9, 0xc5, 0x26, 0x00, - 0x7d, 0xd8, 0x3a, 0xaf, 0xf0, 0x65, 0x58, 0x36, 0x79, 0xf2, 0xe9, 0xe3, 0xe5, 0xd5, 0xde, 0xc3, 0x79, 0xc7, 0x44, - 0x40, 0x64, 0xfd, 0xf3, 0x6e, 0x5e, 0x69, 0xde, 0x32, 0xa9, 0x3b, 0xb5, 0x8e, 0xe9, 0x22, 0x3b, 0x1f, 0xba, 0x73, - 0x7c, 0x03, 0x41, 0xef, 0x46, 0x2f, 0x98, 0x92, 0x1d, 0xaa, 0x9d, 0xb5, 0x7b, 0xb8, 0xbc, 0xfe, 0xb6, 0xbd, 0xfe, - 0xea, 0xbd, 0xee, 0xa5, 0xfb, 0x0f, 0x53, 0x58, 0x46, 0xb2, 0xf9, 0x0a, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x95, 0x16, 0x6b, 0x8f, 0xdb, 0x36, 0xf2, 0x7b, 0x7e, + 0x05, 0x8f, 0x49, 0xbb, 0x52, 0xb3, 0x7a, 0x7a, 0xed, 0x6c, 0x24, 0x51, 0x45, 0x9a, 0xbb, 0xa2, 0x05, 0x9a, 0x36, + 0xc0, 0x6e, 0x73, 0x1f, 0x82, 0x00, 0x4b, 0x53, 0x23, 0x8b, 0x31, 0x45, 0xea, 0x48, 0xca, 0x8f, 0x18, 0xbe, 0xdf, + 0x7e, 0xa0, 0x24, 0x7b, 0x9d, 0x45, 0x73, 0xb8, 0xb3, 0x60, 0x61, 0x38, 0xef, 0x19, 0xcd, 0x83, 0xc5, 0xdf, 0x2a, + 0xc5, 0xec, 0xbe, 0x03, 0xd4, 0xd8, 0x56, 0x94, 0x85, 0x7b, 0x23, 0x41, 0xe5, 0x8a, 0x80, 0x2c, 0x8b, 0x06, 0x68, + 0x55, 0x16, 0x2d, 0x58, 0x8a, 0x58, 0x43, 0xb5, 0x01, 0x4b, 0xfe, 0xbc, 0xff, 0x39, 0xb8, 0x2d, 0x0b, 0xc1, 0xe5, + 0x1a, 0x69, 0x10, 0x84, 0x33, 0x25, 0x51, 0xa3, 0xa1, 0x26, 0x15, 0xb5, 0x34, 0xe3, 0x2d, 0x5d, 0xc1, 0x24, 0x22, + 0x69, 0x0b, 0x64, 0xc3, 0x61, 0xdb, 0x29, 0x6d, 0x11, 0x53, 0xd2, 0x82, 0xb4, 0x04, 0x6f, 0x79, 0x65, 0x1b, 0x52, + 0xc1, 0x86, 0x33, 0x08, 0x86, 0xc3, 0x35, 0x97, 0xdc, 0x72, 0x2a, 0x02, 0xc3, 0xa8, 0x00, 0x92, 0x5c, 0xf7, 0x06, + 0xf4, 0x70, 0xa0, 0x4b, 0x01, 0x44, 0x2a, 0x5c, 0x16, 0x86, 0x69, 0xde, 0x59, 0xe4, 0x5c, 0x25, 0xad, 0xaa, 0x7a, + 0x01, 0x65, 0x14, 0x51, 0x63, 0xc0, 0x9a, 0x88, 0xcb, 0x0a, 0x76, 0xe1, 0x32, 0x66, 0x2c, 0x86, 0xdb, 0xdb, 0xf0, + 0xb3, 0x79, 0x56, 0x29, 0xd6, 0xb7, 0x20, 0x6d, 0x28, 0x14, 0xa3, 0x96, 0x2b, 0x19, 0x1a, 0xa0, 0x9a, 0x35, 0x84, + 0x10, 0xfc, 0xa3, 0xa1, 0x1b, 0xc0, 0xdf, 0x7f, 0xef, 0x9d, 0x99, 0x56, 0x60, 0xff, 0x21, 0xc0, 0x81, 0xe6, 0xa7, + 0xfd, 0x3d, 0x5d, 0xfd, 0x4e, 0x5b, 0xf0, 0x30, 0x35, 0xbc, 0x02, 0xec, 0x7f, 0x8c, 0x3f, 0x85, 0xc6, 0xee, 0x05, + 0x84, 0x15, 0x37, 0x9d, 0xa0, 0x7b, 0x82, 0x97, 0x42, 0xb1, 0x35, 0xf6, 0xf3, 0xba, 0x97, 0xcc, 0x29, 0x47, 0xc6, + 0x03, 0xff, 0x20, 0xc0, 0x22, 0x4b, 0xde, 0x51, 0xdb, 0x84, 0x2d, 0xdd, 0x79, 0x23, 0xc0, 0xa5, 0x97, 0xfe, 0xe0, + 0xc1, 0xcb, 0x24, 0x8e, 0xfd, 0xeb, 0xe1, 0x15, 0xfb, 0x51, 0x12, 0xc7, 0xb9, 0x06, 0xdb, 0x6b, 0x89, 0xa8, 0xf7, + 0x50, 0x74, 0xd4, 0x36, 0xa8, 0x22, 0xf8, 0x5d, 0x92, 0xa2, 0xe4, 0x75, 0x98, 0xce, 0x7f, 0x0b, 0x5f, 0xa1, 0x9b, + 0x30, 0x9d, 0xb3, 0x57, 0xc1, 0x1c, 0x25, 0x37, 0xc1, 0x1c, 0xa5, 0x69, 0x38, 0x47, 0xf1, 0x17, 0x8c, 0x6a, 0x2e, + 0x04, 0xc1, 0x52, 0x49, 0xc0, 0xc8, 0x58, 0xad, 0xd6, 0x40, 0x30, 0xeb, 0xb5, 0x06, 0x69, 0xdf, 0x2a, 0xa1, 0x34, + 0x8e, 0xca, 0x67, 0xff, 0x97, 0x42, 0xab, 0xa9, 0x34, 0xb5, 0xd2, 0x2d, 0xc1, 0x43, 0xf6, 0xbd, 0x17, 0x07, 0x7b, + 0x44, 0xee, 0xe5, 0x5f, 0x10, 0x03, 0xa5, 0xf9, 0x8a, 0x4b, 0x82, 0x9d, 0xc6, 0x5b, 0x1c, 0x95, 0x0f, 0xfe, 0xf1, + 0x1c, 0x3d, 0x75, 0xd1, 0x4f, 0xf1, 0x28, 0xef, 0xe3, 0x43, 0x61, 0x36, 0x2b, 0xb4, 0x6b, 0x85, 0x34, 0x04, 0x37, + 0xd6, 0x76, 0x59, 0x14, 0x6d, 0xb7, 0xdb, 0x70, 0x3b, 0x0b, 0x95, 0x5e, 0x45, 0x69, 0x1c, 0xc7, 0x91, 0xd9, 0xac, + 0x30, 0x1a, 0x0b, 0x01, 0xa7, 0x37, 0x18, 0x35, 0xc0, 0x57, 0x8d, 0x1d, 0xe0, 0xf2, 0xc5, 0x01, 0x8e, 0x85, 0xe3, + 0x28, 0x1f, 0x3e, 0x5d, 0x58, 0xe1, 0x17, 0x56, 0xe0, 0x47, 0xea, 0xe1, 0x53, 0x98, 0x57, 0x43, 0x98, 0xaf, 0x68, + 0x8a, 0x52, 0x14, 0x0f, 0x4f, 0x1a, 0x38, 0x78, 0x3a, 0x05, 0x4f, 0x4e, 0xe8, 0xe2, 0xe4, 0xa0, 0x76, 0x11, 0xbc, + 0x3e, 0xcb, 0x26, 0x0e, 0xb3, 0x49, 0xe2, 0x47, 0x84, 0x13, 0xf8, 0x65, 0x71, 0x79, 0x0e, 0xd2, 0x0f, 0x97, 0x0c, + 0xce, 0x5a, 0x93, 0x7c, 0x58, 0xd0, 0x39, 0x9a, 0x4f, 0x98, 0x79, 0xe0, 0xe0, 0xf3, 0x09, 0xcd, 0x37, 0x69, 0x93, + 0xb4, 0xc1, 0x22, 0x98, 0xd3, 0x19, 0x9a, 0x4d, 0x8e, 0xcc, 0xd0, 0x6c, 0x93, 0x36, 0x8b, 0x0f, 0x8b, 0x4b, 0x5c, + 0x30, 0xfb, 0x72, 0x15, 0x95, 0xd8, 0xcf, 0x30, 0x7e, 0x8c, 0x5c, 0x5d, 0x46, 0x1e, 0x7e, 0x56, 0x5c, 0x7a, 0x18, + 0xfb, 0xc7, 0x1a, 0x2c, 0x6b, 0x3c, 0x1c, 0x31, 0x25, 0x6b, 0xbe, 0x0a, 0x3f, 0x1b, 0x25, 0xb1, 0x1f, 0xda, 0x06, + 0xa4, 0x77, 0x12, 0x75, 0x82, 0x30, 0x50, 0xbc, 0xa7, 0x14, 0xeb, 0x1f, 0xce, 0xf5, 0x6f, 0xb9, 0x15, 0x40, 0x6c, + 0xe8, 0x1a, 0xf6, 0xfa, 0x8c, 0x5d, 0xaa, 0x6a, 0xff, 0x8d, 0xd6, 0x68, 0x92, 0xb1, 0x2f, 0xb8, 0x94, 0xa0, 0xef, + 0x61, 0x67, 0x09, 0x7e, 0xf7, 0xe6, 0x2d, 0x7a, 0x53, 0x55, 0x1a, 0x8c, 0xc9, 0x10, 0x7e, 0x69, 0xc3, 0x96, 0xb2, + 0xff, 0x5d, 0x57, 0xf2, 0x95, 0xae, 0x7f, 0xf2, 0x9f, 0x39, 0xfa, 0x1d, 0xec, 0x56, 0xe9, 0xf5, 0xa4, 0xcd, 0xb9, + 0x96, 0xbb, 0x0e, 0xd3, 0xc4, 0x86, 0xb4, 0x33, 0xa1, 0x11, 0x9c, 0x81, 0x97, 0xf8, 0x61, 0x4b, 0xbb, 0xc7, 0xa8, + 0xe4, 0x29, 0x51, 0x0f, 0x45, 0xc5, 0x37, 0x88, 0x09, 0x6a, 0x0c, 0xc1, 0x72, 0x54, 0x85, 0xd1, 0x33, 0x34, 0xfc, + 0x94, 0x64, 0x82, 0xb3, 0x35, 0xc1, 0x7f, 0x31, 0x01, 0x7e, 0xda, 0xff, 0x5a, 0x79, 0x57, 0xc6, 0xf0, 0xea, 0xca, + 0x0f, 0x37, 0x54, 0xf4, 0x80, 0x08, 0xb2, 0x0d, 0x37, 0x8f, 0x0e, 0xe6, 0xdf, 0x14, 0xeb, 0xcc, 0xfa, 0xca, 0x0f, + 0x6b, 0xc5, 0x7a, 0xe3, 0xf9, 0xb8, 0x9c, 0xcc, 0x15, 0x74, 0x1c, 0x90, 0xf8, 0x39, 0x7e, 0xe2, 0x51, 0x20, 0xa0, + 0xb6, 0x67, 0x3e, 0x84, 0x5e, 0x1c, 0x8c, 0x27, 0x43, 0x6d, 0x0c, 0xf7, 0x8f, 0x67, 0x64, 0x61, 0x3a, 0x2a, 0x9f, + 0x0a, 0x3a, 0x07, 0x5d, 0xab, 0xc8, 0xd0, 0x41, 0xae, 0x5f, 0x3a, 0x2a, 0xcf, 0x06, 0x23, 0x7a, 0x02, 0x5f, 0x1c, + 0xb8, 0x27, 0xdd, 0x14, 0x5c, 0x9f, 0x35, 0x16, 0x51, 0xc5, 0x37, 0xe5, 0xc3, 0xd1, 0x7f, 0x8c, 0xe3, 0x5f, 0x3d, + 0xe8, 0xfd, 0x1d, 0x08, 0x60, 0x56, 0x69, 0x0f, 0x3f, 0x97, 0x60, 0xb1, 0x3f, 0x06, 0xfc, 0xcb, 0xfd, 0xbb, 0xdf, + 0x88, 0xf2, 0xb4, 0x7f, 0xfd, 0x2d, 0x6e, 0xb7, 0x0a, 0x3e, 0x6a, 0x10, 0xff, 0x26, 0x57, 0x6e, 0x19, 0x5c, 0x7d, + 0xc2, 0x7e, 0x38, 0xc4, 0xfb, 0xf0, 0xb8, 0x11, 0x5c, 0x3b, 0xbf, 0xdc, 0xb5, 0xe2, 0xda, 0x45, 0x18, 0x2c, 0xe6, + 0xfe, 0xf1, 0xe1, 0xe8, 0x1f, 0xfd, 0xbc, 0x88, 0xc6, 0xb9, 0x5e, 0x16, 0xc3, 0x88, 0x2d, 0x7f, 0x38, 0x2c, 0xd5, + 0x2e, 0x30, 0xfc, 0x0b, 0x97, 0xab, 0x8c, 0xcb, 0x06, 0x34, 0xb7, 0xc7, 0x8a, 0x6f, 0xae, 0xb9, 0xec, 0x7a, 0x7b, + 0xe8, 0x68, 0x55, 0x39, 0xca, 0xbc, 0xdb, 0xe5, 0xb5, 0x92, 0xd6, 0x71, 0x42, 0x96, 0x40, 0x7b, 0x1c, 0xe9, 0xc3, + 0x44, 0xc9, 0x5e, 0xcf, 0xbf, 0x3b, 0xba, 0x82, 0x3b, 0x58, 0xd8, 0xd9, 0x80, 0x0a, 0xbe, 0x92, 0x19, 0x03, 0x69, + 0x41, 0x8f, 0x42, 0x35, 0x6d, 0xb9, 0xd8, 0x67, 0x86, 0x4a, 0x13, 0x18, 0xd0, 0xbc, 0x3e, 0x2e, 0x7b, 0x6b, 0x95, + 0x3c, 0x2c, 0x95, 0xae, 0x40, 0x67, 0x71, 0x3e, 0x02, 0x81, 0xa6, 0x15, 0xef, 0x4d, 0x16, 0xce, 0x34, 0xb4, 0xf9, + 0x92, 0xb2, 0xf5, 0x4a, 0xab, 0x5e, 0x56, 0x01, 0x73, 0x93, 0x36, 0x7b, 0x9e, 0xd4, 0x74, 0x06, 0x2c, 0x9f, 0x4e, + 0x75, 0x5d, 0xe7, 0x82, 0x4b, 0x08, 0xc6, 0x59, 0x96, 0xa5, 0xe1, 0x8d, 0x13, 0xbb, 0x70, 0x33, 0x4c, 0x1d, 0x62, + 0xf4, 0x31, 0x89, 0xe3, 0xef, 0xf2, 0x53, 0x38, 0x71, 0xce, 0x7a, 0x6d, 0x94, 0xce, 0x3a, 0xc5, 0x9d, 0x9b, 0xc7, + 0x96, 0x72, 0x79, 0xe9, 0xbd, 0x2b, 0x93, 0x7c, 0x5a, 0x3f, 0x19, 0x97, 0x83, 0x99, 0x61, 0x09, 0xe5, 0x2d, 0x97, + 0xe3, 0x0e, 0xcd, 0xd2, 0x45, 0xdc, 0xed, 0x8e, 0xe1, 0x54, 0x20, 0x87, 0x13, 0x77, 0x2d, 0x60, 0x97, 0x7f, 0xee, + 0x8d, 0xe5, 0xf5, 0x3e, 0x98, 0x76, 0x70, 0x66, 0x3a, 0xca, 0x20, 0x58, 0x82, 0xdd, 0x02, 0xc8, 0x7c, 0xb0, 0x11, + 0x70, 0x0b, 0xad, 0x99, 0xf2, 0x74, 0x56, 0x33, 0x14, 0xe8, 0xd7, 0xba, 0xfe, 0x1b, 0xb7, 0xab, 0xc5, 0x43, 0x4b, + 0xf5, 0x8a, 0xcb, 0x60, 0xa9, 0xac, 0x55, 0x6d, 0x16, 0xbc, 0xea, 0x76, 0xf9, 0x84, 0x72, 0xca, 0xb2, 0xc4, 0xb9, + 0x39, 0xec, 0xd6, 0x53, 0xbe, 0x93, 0x6e, 0x87, 0x8c, 0x12, 0xbc, 0x9a, 0xf8, 0x06, 0x16, 0x14, 0x9f, 0xd3, 0x93, + 0xcc, 0xbb, 0x1d, 0x72, 0xb8, 0x53, 0xaa, 0x6f, 0xea, 0x5b, 0x9a, 0xc4, 0x7f, 0xf1, 0x45, 0xaa, 0xba, 0x4e, 0x97, + 0xf5, 0x39, 0x53, 0x6e, 0x4d, 0xba, 0xd6, 0x18, 0x4a, 0xab, 0x88, 0xc6, 0xdb, 0x8c, 0xab, 0x8c, 0xb2, 0x70, 0x19, + 0x2e, 0x8b, 0x26, 0x41, 0xbc, 0x22, 0x2d, 0x65, 0xe5, 0xc5, 0xf8, 0x2a, 0xa2, 0x26, 0x39, 0x91, 0x9a, 0xa4, 0xfc, + 0x6a, 0x18, 0x8d, 0xb4, 0xc1, 0xfb, 0xf2, 0xad, 0x92, 0x12, 0x98, 0xe5, 0x72, 0x85, 0xac, 0x42, 0x53, 0x0a, 0xc2, + 0x30, 0x2c, 0x96, 0xba, 0x7c, 0x2f, 0x80, 0x1a, 0x40, 0x5b, 0xca, 0x6d, 0x58, 0x44, 0x23, 0xff, 0xd8, 0xc7, 0xbc, + 0x22, 0x12, 0x6c, 0x39, 0x35, 0x6c, 0xd1, 0xcc, 0x46, 0x03, 0x77, 0x60, 0x9d, 0x26, 0x67, 0x60, 0x56, 0x16, 0x6e, + 0xe5, 0x22, 0x3a, 0x8c, 0x34, 0x12, 0x6d, 0x79, 0xcd, 0xdd, 0x95, 0xa5, 0x2c, 0x86, 0x22, 0x77, 0x1a, 0x5c, 0x9e, + 0xc7, 0xeb, 0xd5, 0x00, 0x09, 0x90, 0x2b, 0xdb, 0x90, 0x59, 0x8a, 0x3a, 0x41, 0x19, 0x34, 0x4a, 0x54, 0xa0, 0xc9, + 0xdd, 0xdd, 0xaf, 0x7f, 0x2f, 0x9d, 0x33, 0x8f, 0x72, 0x9d, 0x59, 0x8f, 0x62, 0x0e, 0x98, 0xa4, 0x16, 0x37, 0xe3, + 0xa5, 0xaa, 0xa3, 0xc6, 0x6c, 0x95, 0xae, 0xbe, 0xd2, 0xf1, 0x7e, 0x42, 0x8e, 0x7a, 0x86, 0xff, 0xd0, 0x2a, 0xe5, + 0x1d, 0xdd, 0x40, 0x11, 0x4d, 0x87, 0x22, 0x72, 0x0e, 0x8f, 0xf4, 0x66, 0xe2, 0x6b, 0x92, 0xf2, 0x8f, 0xfb, 0x37, + 0xe8, 0xcf, 0xae, 0xa2, 0x16, 0xc6, 0xb4, 0x0d, 0x51, 0xb5, 0x60, 0x1b, 0x55, 0x91, 0xf7, 0x7f, 0xdc, 0xdd, 0x9f, + 0x23, 0xec, 0x07, 0x26, 0x04, 0x92, 0x8d, 0xd7, 0xbb, 0x5e, 0x58, 0xde, 0x51, 0x6d, 0x07, 0xb5, 0x81, 0x9b, 0x22, + 0xa7, 0x18, 0x06, 0x7a, 0xcd, 0x05, 0x8c, 0x61, 0x8c, 0x82, 0x25, 0x3a, 0x79, 0x75, 0xb2, 0xf6, 0xc4, 0xaf, 0x68, + 0xfc, 0xda, 0xd1, 0xf8, 0xe9, 0xa3, 0xe1, 0xa6, 0xfb, 0x1f, 0x53, 0x58, 0x46, 0xb2, 0xf9, 0x0a, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 5f6d11865b..b224354a6b 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,1213 +10,1239 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xcd, 0x7d, 0xdb, 0x76, 0xdb, 0xc6, 0xb2, 0xe0, 0xf3, - 0xe4, 0x2b, 0x20, 0x44, 0xc7, 0x06, 0xb6, 0x9a, 0x10, 0x49, 0x49, 0xb6, 0x0c, 0x0a, 0xe4, 0xb6, 0x65, 0x3b, 0x76, - 0xe2, 0x5b, 0x2c, 0x3b, 0xd9, 0x89, 0xa2, 0x6d, 0x41, 0x64, 0x93, 0x84, 0x0d, 0x02, 0x0c, 0xd0, 0xd4, 0x25, 0x14, - 0xce, 0x9a, 0x0f, 0x98, 0xb5, 0x66, 0xad, 0x79, 0x9a, 0x97, 0x59, 0x73, 0x1e, 0xe6, 0x23, 0xe6, 0xf9, 0x7c, 0xca, - 0xf9, 0x81, 0x99, 0x4f, 0x98, 0xaa, 0xea, 0x6e, 0xa0, 0xc1, 0x8b, 0x2c, 0x27, 0xd9, 0xe7, 0xcc, 0x4a, 0x2c, 0x12, - 0x7d, 0xad, 0xae, 0xae, 0xae, 0x7b, 0x83, 0x07, 0x1b, 0x83, 0xb4, 0x2f, 0xae, 0xa6, 0xdc, 0x1a, 0x8b, 0x49, 0xdc, - 0x3d, 0x50, 0x7f, 0x79, 0x38, 0xe8, 0x1e, 0xc4, 0x51, 0xf2, 0xc9, 0xca, 0x78, 0x1c, 0x44, 0xfd, 0x34, 0xb1, 0xc6, - 0x19, 0x1f, 0x06, 0x83, 0x50, 0x84, 0x7e, 0x34, 0x09, 0x47, 0xdc, 0xda, 0xee, 0x1e, 0x4c, 0xb8, 0x08, 0xad, 0xfe, - 0x38, 0xcc, 0x72, 0x2e, 0x82, 0xf7, 0xef, 0x9e, 0x36, 0xf6, 0xbb, 0x07, 0x79, 0x3f, 0x8b, 0xa6, 0xc2, 0xc2, 0x21, - 0x83, 0x49, 0x3a, 0x98, 0xc5, 0xbc, 0xbb, 0xbd, 0x7d, 0x71, 0x71, 0xe1, 0x7d, 0xcc, 0xbf, 0x82, 0x61, 0x72, 0x61, - 0xbd, 0x08, 0x2e, 0xa2, 0x64, 0x90, 0x5e, 0xb0, 0x48, 0x04, 0x2f, 0xbc, 0xa3, 0x71, 0x08, 0xdf, 0xdf, 0xa6, 0xa9, - 0xb8, 0x73, 0xc7, 0x91, 0x8f, 0x57, 0x87, 0x47, 0x47, 0x41, 0x10, 0x9c, 0xa7, 0xd1, 0xc0, 0x6a, 0x5e, 0x5f, 0x57, - 0x85, 0x5e, 0x12, 0x8a, 0xe8, 0x9c, 0xcb, 0x2e, 0xee, 0x9d, 0x3b, 0x36, 0x7c, 0x4e, 0x05, 0x1f, 0x1c, 0x89, 0xab, - 0x18, 0x4a, 0x39, 0x17, 0xb9, 0x1d, 0x25, 0xd6, 0xe3, 0xb4, 0x3f, 0x9b, 0xf0, 0x44, 0x78, 0xd3, 0x2c, 0x15, 0x29, - 0x42, 0x02, 0x4d, 0x33, 0x3e, 0x8d, 0xc3, 0x3e, 0xc7, 0x7a, 0x18, 0xa9, 0xea, 0x51, 0x35, 0x62, 0xb9, 0x08, 0x8e, - 0xae, 0x26, 0x67, 0x69, 0xec, 0xb8, 0x2c, 0x14, 0x41, 0xc2, 0x2f, 0xac, 0x1f, 0x79, 0xf8, 0xe9, 0x65, 0x38, 0xed, - 0xf4, 0xe3, 0x30, 0xcf, 0xad, 0x4b, 0x31, 0xa7, 0x25, 0x64, 0xb3, 0xbe, 0x48, 0x33, 0x47, 0x30, 0xce, 0x22, 0x77, - 0x1e, 0x0d, 0x1d, 0x31, 0x8e, 0x72, 0xef, 0xc3, 0x66, 0x3f, 0xcf, 0xdf, 0xf2, 0x7c, 0x16, 0x8b, 0xcd, 0x60, 0xa3, - 0xc9, 0xa2, 0x8d, 0x20, 0xc8, 0x85, 0x2b, 0xc6, 0x59, 0x7a, 0x61, 0x3d, 0xc9, 0x32, 0xe8, 0x61, 0xc3, 0xd4, 0xb2, - 0x85, 0x15, 0xe5, 0x56, 0x92, 0x0a, 0xab, 0x1c, 0x2f, 0x3c, 0x8b, 0xb9, 0x67, 0xbd, 0xcf, 0xb9, 0x75, 0x3a, 0x4b, - 0xf2, 0x70, 0xc8, 0xa1, 0xe9, 0xa9, 0x95, 0x66, 0xd6, 0x29, 0x8c, 0x7a, 0x6a, 0x45, 0xd0, 0x0c, 0x36, 0xc5, 0xb3, - 0xdd, 0x0e, 0x4d, 0x06, 0x85, 0xef, 0xf8, 0xa5, 0x08, 0x04, 0xa3, 0x47, 0x11, 0xf0, 0x62, 0xc4, 0x85, 0x95, 0x97, - 0xeb, 0x72, 0xdc, 0x79, 0x0c, 0x05, 0xd0, 0x02, 0xeb, 0xd3, 0x8e, 0xc4, 0x3d, 0x97, 0x8f, 0xa2, 0x03, 0x40, 0x47, - 0x80, 0x71, 0x51, 0xe2, 0xd9, 0x95, 0x4b, 0xb3, 0xa2, 0x80, 0x6f, 0xe8, 0xb2, 0x3b, 0x77, 0xb8, 0x17, 0xf3, 0x64, - 0x24, 0xc6, 0xd0, 0xac, 0xd5, 0x89, 0x60, 0x87, 0x44, 0x10, 0x0a, 0x0f, 0x66, 0x72, 0xb8, 0xeb, 0xb2, 0xaa, 0x37, - 0xd4, 0x48, 0x24, 0xa4, 0x81, 0x44, 0x5c, 0x0d, 0xc7, 0xae, 0xa7, 0xb0, 0x7f, 0x74, 0x95, 0xf4, 0x1d, 0x13, 0x7e, - 0x97, 0xc1, 0xa0, 0x30, 0x62, 0x8e, 0x23, 0x32, 0xe1, 0xba, 0x45, 0xc6, 0xc5, 0x2c, 0x4b, 0x2c, 0x51, 0x88, 0xf4, - 0x48, 0x64, 0x51, 0x32, 0x82, 0x85, 0xe8, 0x32, 0xa3, 0x63, 0x51, 0x48, 0x70, 0x5f, 0xc1, 0x74, 0x41, 0x17, 0x67, - 0xbc, 0x14, 0x0e, 0xee, 0x62, 0x3a, 0xb4, 0x92, 0x20, 0xb0, 0x73, 0xea, 0x6b, 0xf7, 0x12, 0x3f, 0xd9, 0xb2, 0x6d, - 0x26, 0xa1, 0x84, 0x1d, 0x76, 0xd9, 0xeb, 0xc0, 0x49, 0x98, 0xe7, 0x79, 0xc2, 0x0d, 0xba, 0x73, 0x8d, 0x95, 0xc4, - 0x58, 0x67, 0x2f, 0x39, 0x6e, 0x9e, 0xf8, 0x02, 0x60, 0x1e, 0xcc, 0xfa, 0xdc, 0x71, 0x22, 0x96, 0xb3, 0x0c, 0x1a, - 0x47, 0x5b, 0x4e, 0x0a, 0x5d, 0x00, 0x73, 0x69, 0x7d, 0xaf, 0x03, 0xd8, 0x6d, 0x57, 0xc1, 0x98, 0x6a, 0x00, 0x11, - 0xc3, 0x0a, 0x9e, 0x14, 0xe0, 0x49, 0x66, 0x93, 0x33, 0x9e, 0xd9, 0x65, 0xb3, 0x4e, 0x8d, 0x2c, 0x66, 0xb0, 0xed, - 0xd0, 0xcf, 0x1a, 0xce, 0x92, 0xbe, 0x88, 0xe0, 0xb0, 0xd9, 0x5b, 0xe9, 0x96, 0x2d, 0xc9, 0xa1, 0xa4, 0x06, 0xdb, - 0x2d, 0x5c, 0x27, 0x77, 0xb7, 0x92, 0xe3, 0x6c, 0xab, 0x75, 0xc2, 0x10, 0x4a, 0xb7, 0xa3, 0xc6, 0x53, 0x08, 0xe0, - 0x2c, 0xc1, 0x35, 0x16, 0xec, 0xad, 0xc0, 0x55, 0xd2, 0x12, 0x23, 0xd1, 0x4b, 0xbc, 0xe5, 0x83, 0x12, 0x08, 0x6f, - 0x12, 0x4e, 0x1d, 0x1e, 0x74, 0x39, 0x11, 0x57, 0x98, 0xf4, 0x11, 0xd6, 0xda, 0xbe, 0xf5, 0xb8, 0xcf, 0xbd, 0x8a, - 0xa4, 0x5c, 0x40, 0xca, 0x30, 0xcd, 0x9e, 0x84, 0xfd, 0x31, 0xf6, 0x2b, 0x09, 0x66, 0xa0, 0xcf, 0x5b, 0x3f, 0xe3, - 0xa1, 0xe0, 0x4f, 0x62, 0x8e, 0x4f, 0x8e, 0x4d, 0x3d, 0x6d, 0x97, 0xe5, 0x70, 0xcc, 0xe3, 0x48, 0xbc, 0x4a, 0x61, - 0x8a, 0x4e, 0x6e, 0x50, 0x57, 0x84, 0xfb, 0xfe, 0x50, 0xc0, 0x56, 0x9d, 0xcd, 0x04, 0x77, 0xec, 0x04, 0x5b, 0xd8, - 0x2c, 0x07, 0xaa, 0xf0, 0x04, 0xe0, 0xf0, 0x30, 0x4d, 0x04, 0x8c, 0x14, 0x70, 0x8d, 0x54, 0x06, 0x2b, 0x99, 0x4e, - 0x79, 0x32, 0x38, 0x1c, 0x47, 0xf1, 0xc0, 0x89, 0x00, 0x23, 0x05, 0x1b, 0x8b, 0x00, 0xd7, 0x08, 0x54, 0xe0, 0xe3, - 0x9f, 0xf5, 0xab, 0x01, 0xe2, 0xed, 0xd2, 0xa1, 0xe0, 0x81, 0x6d, 0x77, 0x60, 0x25, 0x8e, 0x5a, 0x81, 0x05, 0x4d, - 0x05, 0xce, 0xf1, 0x16, 0xd8, 0x55, 0xee, 0xf2, 0xad, 0x20, 0x2a, 0xb7, 0x51, 0x21, 0xf8, 0x15, 0x52, 0x3c, 0xe0, - 0x3f, 0x71, 0xfd, 0xa4, 0x73, 0x1e, 0x66, 0xd6, 0x8f, 0xea, 0x44, 0x3d, 0xd6, 0xdc, 0xac, 0x2f, 0x82, 0xc7, 0x1e, - 0x1c, 0x65, 0x38, 0xa7, 0x83, 0x77, 0xb0, 0xf1, 0x39, 0x7b, 0x26, 0x82, 0xbe, 0xe8, 0xf5, 0x85, 0xc7, 0x27, 0x53, - 0x71, 0x75, 0x44, 0x8c, 0xd1, 0x07, 0x62, 0x1c, 0x60, 0x4b, 0x40, 0x55, 0x1f, 0x99, 0x99, 0xc2, 0xd6, 0x9b, 0x34, - 0xbe, 0x1a, 0x46, 0x71, 0x7c, 0x34, 0x9b, 0x4e, 0xd3, 0x4c, 0xb0, 0xbf, 0x05, 0x73, 0x91, 0x56, 0xa8, 0xc1, 0xbd, - 0x9c, 0xe7, 0x17, 0x91, 0x00, 0xd4, 0xc3, 0xb7, 0x7e, 0x08, 0x84, 0xf1, 0x28, 0x4d, 0x63, 0x1e, 0xe2, 0xa2, 0x93, - 0xde, 0x33, 0xe1, 0x27, 0xb3, 0x38, 0xee, 0x9c, 0xc1, 0xb0, 0x9f, 0x3a, 0x54, 0xfd, 0xfa, 0xec, 0x23, 0xef, 0x0b, - 0x9f, 0xbe, 0x3f, 0xcc, 0xb2, 0xf0, 0x0a, 0x1b, 0x06, 0x01, 0x36, 0x83, 0x53, 0xf1, 0xed, 0xd1, 0xeb, 0x57, 0x9e, - 0x3c, 0x24, 0xd1, 0xf0, 0x0a, 0x96, 0xa5, 0x0f, 0x5e, 0x52, 0xb0, 0x61, 0x96, 0x4e, 0x16, 0xa6, 0x96, 0x58, 0x4b, - 0x3a, 0x6b, 0x40, 0x80, 0xaa, 0x0d, 0x39, 0xb4, 0x09, 0xc1, 0x2b, 0xa2, 0x79, 0xac, 0x0c, 0xf4, 0xbc, 0xf0, 0xc7, - 0x97, 0xc5, 0x30, 0xe5, 0xcd, 0xd0, 0x8a, 0xec, 0x6a, 0xce, 0x03, 0x82, 0x73, 0x8a, 0x12, 0x06, 0x61, 0xec, 0x87, - 0x30, 0x3b, 0x94, 0xe2, 0x38, 0x85, 0x86, 0x98, 0x17, 0x05, 0x7b, 0x58, 0xd2, 0xbb, 0x40, 0x40, 0x88, 0x51, 0x05, - 0xe2, 0xfa, 0x1a, 0x17, 0xec, 0xb2, 0x9f, 0x83, 0x79, 0xa8, 0xd7, 0xe3, 0x03, 0x67, 0xc6, 0x73, 0xe9, 0x4b, 0xee, - 0xc2, 0x60, 0x17, 0xcf, 0x79, 0x26, 0x00, 0xce, 0xbf, 0x31, 0x90, 0x70, 0x31, 0x42, 0xb1, 0xd1, 0x62, 0xe3, 0x30, - 0x3f, 0x1c, 0x87, 0xc9, 0x88, 0x0f, 0xfc, 0x87, 0xa2, 0x60, 0x42, 0x04, 0xf6, 0x30, 0x4a, 0xc2, 0x38, 0xfa, 0x8d, - 0x0f, 0x6c, 0x25, 0x0e, 0x9e, 0x58, 0x40, 0x20, 0x40, 0x8c, 0xb9, 0xf5, 0xec, 0xdd, 0xcb, 0x17, 0x6a, 0x23, 0x6b, - 0x12, 0x02, 0xf6, 0x6c, 0x36, 0x85, 0xb5, 0xba, 0x4c, 0x49, 0x88, 0x27, 0x11, 0x71, 0x47, 0x10, 0x29, 0xb2, 0x24, - 0xca, 0xdf, 0x4f, 0x41, 0xa6, 0xf2, 0x37, 0x30, 0x0c, 0x40, 0x13, 0xc0, 0xcc, 0x54, 0x0e, 0xd3, 0xcb, 0x8a, 0x41, - 0x59, 0x04, 0x9d, 0x63, 0x5a, 0x78, 0xf9, 0x38, 0x73, 0xdc, 0x02, 0x48, 0x5d, 0x44, 0x7d, 0x2b, 0x1c, 0x0c, 0x9e, - 0x27, 0x91, 0x88, 0x08, 0xc0, 0x0c, 0xf7, 0x07, 0x69, 0x94, 0x4b, 0x59, 0xa1, 0x01, 0x07, 0x30, 0x1c, 0x47, 0x49, - 0x80, 0xb1, 0xab, 0x36, 0x0c, 0x78, 0x7c, 0x79, 0x22, 0xe1, 0xbc, 0xcb, 0xca, 0xe0, 0xf8, 0xc4, 0xf5, 0xa6, 0xb3, - 0x1c, 0x77, 0x5a, 0x4f, 0x81, 0xe2, 0x25, 0x3d, 0xcb, 0x79, 0x76, 0xce, 0x07, 0x25, 0x75, 0xe4, 0xb0, 0xc4, 0x85, - 0x39, 0xd4, 0xb9, 0x10, 0x30, 0x46, 0xc7, 0x64, 0xdc, 0x5c, 0x11, 0x7a, 0x96, 0x02, 0x46, 0x44, 0xc4, 0xf3, 0x92, - 0x97, 0x38, 0x28, 0x46, 0x4b, 0x7e, 0x92, 0x07, 0x7a, 0x7d, 0x53, 0x60, 0xbd, 0xdc, 0xad, 0x71, 0x0c, 0x2d, 0x69, - 0x9f, 0x9c, 0x93, 0xc8, 0xc8, 0xa1, 0x23, 0x13, 0x12, 0xd2, 0x1c, 0x84, 0x07, 0x3c, 0x68, 0x70, 0x25, 0x2f, 0x52, - 0xb3, 0x5d, 0xa1, 0xac, 0x0e, 0x7e, 0x26, 0x59, 0x8d, 0x1c, 0x0d, 0x6a, 0x60, 0x2c, 0xee, 0x95, 0x54, 0x01, 0x58, - 0x56, 0x7b, 0x64, 0x20, 0x6b, 0x0d, 0xd8, 0x38, 0x31, 0x0c, 0xe7, 0xb2, 0x0d, 0xee, 0x25, 0xe9, 0xc3, 0x7e, 0x9f, - 0xe7, 0x79, 0x9a, 0xdd, 0xb9, 0xb3, 0x41, 0xed, 0x4b, 0x75, 0x02, 0xf7, 0xf0, 0xf5, 0x45, 0x52, 0x41, 0xe0, 0x56, - 0x22, 0x56, 0x09, 0x06, 0x81, 0x82, 0x8a, 0x34, 0x0e, 0xbb, 0xa7, 0x35, 0x0f, 0xdf, 0xfe, 0xf0, 0xc1, 0xde, 0x12, - 0x4c, 0xa1, 0x01, 0xb0, 0xae, 0x47, 0x78, 0xcc, 0xa5, 0x6e, 0x45, 0x9a, 0xc7, 0x12, 0x66, 0xe4, 0x01, 0xf2, 0x06, - 0x1c, 0x16, 0x60, 0x2c, 0xbb, 0x06, 0x12, 0x83, 0x61, 0xdd, 0xc2, 0xd8, 0xd0, 0x95, 0x43, 0x93, 0x52, 0x23, 0x77, - 0x6e, 0x3e, 0x22, 0x45, 0xc2, 0xd8, 0xc6, 0x63, 0x7e, 0x52, 0x30, 0x42, 0xbd, 0x5e, 0x4d, 0x46, 0x80, 0x1e, 0x8b, - 0x93, 0x8e, 0xaa, 0x0f, 0x72, 0x89, 0xb9, 0x8c, 0xff, 0x3a, 0xe3, 0xb9, 0x90, 0x74, 0x0c, 0xe3, 0x66, 0x30, 0x6e, - 0x81, 0xe7, 0x6d, 0x18, 0x8d, 0x66, 0x19, 0xea, 0x3b, 0x78, 0x16, 0x39, 0x48, 0x46, 0xae, 0x9f, 0x56, 0xc1, 0xf6, - 0x7a, 0x8a, 0x12, 0x31, 0x47, 0x9a, 0xbe, 0x99, 0x9c, 0x10, 0x56, 0xe1, 0x5e, 0x5f, 0xff, 0xac, 0x07, 0xa9, 0xb6, - 0xb2, 0xd4, 0xd1, 0x16, 0xf7, 0x04, 0x36, 0x45, 0x0e, 0xba, 0xd1, 0x92, 0xe0, 0x0b, 0x71, 0x02, 0xd2, 0xbc, 0xa4, - 0x61, 0x85, 0x55, 0x09, 0x8e, 0x44, 0xe2, 0x6b, 0x39, 0x94, 0x4b, 0x02, 0xbe, 0x46, 0x2e, 0xde, 0x78, 0x89, 0x52, - 0xe1, 0x24, 0xa1, 0xaa, 0xe1, 0x8d, 0x4f, 0xd6, 0x91, 0x93, 0xe6, 0x07, 0x30, 0xd6, 0x52, 0x5d, 0xc5, 0x36, 0xce, - 0xeb, 0x6c, 0x63, 0x61, 0x19, 0xf6, 0xb4, 0xec, 0x62, 0x97, 0x54, 0xa6, 0x0e, 0x7a, 0x55, 0xc5, 0x22, 0x02, 0xa6, - 0x5a, 0x92, 0x31, 0xc4, 0xab, 0x70, 0x02, 0x67, 0x19, 0x68, 0x7a, 0x5d, 0x03, 0x49, 0x9e, 0xd8, 0xe4, 0xc4, 0x90, - 0x9c, 0x39, 0x4a, 0xce, 0xc8, 0x95, 0x8a, 0x59, 0xfd, 0xc0, 0xe5, 0x8c, 0x1f, 0xe7, 0x27, 0x95, 0x3e, 0x67, 0x2c, - 0x9e, 0x44, 0xb2, 0xa2, 0x6f, 0x8d, 0x3f, 0x59, 0x26, 0x91, 0x46, 0x7a, 0x03, 0x2c, 0x1e, 0xe8, 0x61, 0x61, 0x27, - 0x75, 0xab, 0x6a, 0x8d, 0xc0, 0x64, 0x60, 0x1f, 0x48, 0x62, 0x00, 0x33, 0xa5, 0xcf, 0xda, 0x49, 0x43, 0xb4, 0x1d, - 0x21, 0x61, 0x78, 0xc3, 0x38, 0x14, 0x4e, 0x6b, 0xbb, 0x89, 0xca, 0x28, 0x70, 0x7c, 0x10, 0x28, 0xae, 0xbb, 0xbc, - 0x14, 0xee, 0x81, 0xbe, 0x35, 0x8e, 0x86, 0xc2, 0x19, 0x0b, 0x62, 0x29, 0x3c, 0x06, 0x89, 0x24, 0x6a, 0x2a, 0x31, - 0xb1, 0x9b, 0x31, 0x12, 0x5b, 0xa9, 0x7f, 0x71, 0x0d, 0x29, 0xb1, 0x2d, 0xe4, 0x0e, 0x95, 0x3a, 0x5d, 0x71, 0x19, - 0xdd, 0x3a, 0x42, 0x95, 0xb1, 0xd5, 0x93, 0x23, 0xfa, 0x8a, 0x19, 0x44, 0x86, 0xd6, 0x1a, 0xf9, 0x26, 0x87, 0x50, - 0x85, 0xc2, 0x13, 0xe9, 0x8b, 0xf4, 0x82, 0x67, 0x87, 0x21, 0x02, 0xef, 0xcb, 0xee, 0x85, 0x14, 0x04, 0xc4, 0xef, - 0x45, 0x47, 0xd3, 0xcb, 0x07, 0x5a, 0x38, 0x6c, 0xc6, 0x24, 0x82, 0xb6, 0xa0, 0xac, 0x49, 0xfc, 0x27, 0x78, 0xce, - 0xe8, 0x40, 0xa2, 0xb0, 0xe1, 0x25, 0x7d, 0x3d, 0x7c, 0x51, 0xa7, 0x2f, 0x18, 0x61, 0xa4, 0x19, 0x60, 0xfd, 0x18, - 0x83, 0x08, 0x51, 0x26, 0x85, 0x21, 0xe7, 0x40, 0x9a, 0x28, 0x09, 0x7f, 0x7d, 0x2d, 0x0c, 0xcb, 0xad, 0xa6, 0x2e, - 0x72, 0x79, 0x6c, 0xdc, 0x02, 0x64, 0x15, 0x2a, 0x76, 0x59, 0x1a, 0xc7, 0x86, 0xa8, 0x62, 0x51, 0xa7, 0x14, 0x4e, - 0x30, 0xfd, 0xd1, 0x4d, 0xf2, 0x09, 0xeb, 0x4d, 0x11, 0xa5, 0x01, 0x4d, 0x06, 0x3c, 0x43, 0x4b, 0xd2, 0xd8, 0x2d, - 0x25, 0x65, 0x61, 0xc2, 0x04, 0x88, 0x9a, 0x0f, 0xd0, 0x50, 0x01, 0xfe, 0xeb, 0x8d, 0xd3, 0x5c, 0x94, 0x85, 0x15, - 0xf4, 0x91, 0x01, 0x3d, 0xe8, 0x80, 0x61, 0x1c, 0x3b, 0xd2, 0x28, 0x99, 0xa4, 0xe7, 0x7c, 0x05, 0xd4, 0x9d, 0x1a, - 0xc8, 0xe5, 0x30, 0xdc, 0x18, 0x06, 0xe4, 0xcd, 0x34, 0x8e, 0xfa, 0xbc, 0x14, 0x5d, 0x47, 0x1e, 0x28, 0x8c, 0xfc, - 0x12, 0xf9, 0x88, 0xdb, 0xed, 0x76, 0x9b, 0xac, 0xe5, 0x16, 0x12, 0xe1, 0xf3, 0x25, 0xc4, 0xde, 0x20, 0x34, 0x91, - 0xc8, 0x40, 0x68, 0xae, 0xe2, 0x07, 0xdc, 0x35, 0x24, 0x65, 0xa4, 0x8d, 0x2b, 0xc9, 0x9d, 0x5d, 0x36, 0x80, 0x41, - 0x05, 0xd7, 0xdc, 0x1c, 0x55, 0x68, 0x79, 0x74, 0xdf, 0x96, 0xf8, 0x2b, 0xc9, 0x49, 0x9f, 0x32, 0xbd, 0xe7, 0x79, - 0x69, 0xac, 0x57, 0xdb, 0x53, 0x61, 0xbb, 0x27, 0xe4, 0xf6, 0x00, 0xbd, 0x03, 0x84, 0xd2, 0x4a, 0x77, 0x96, 0x96, - 0x54, 0x8d, 0xa1, 0x38, 0x7b, 0x79, 0x88, 0xde, 0x6a, 0x30, 0x57, 0xa1, 0xe0, 0x48, 0x31, 0x05, 0x8e, 0x86, 0x9f, - 0xdc, 0xb6, 0x43, 0xd8, 0x9e, 0xb3, 0xb0, 0xff, 0xa9, 0x4e, 0xfd, 0x15, 0x19, 0x04, 0x8b, 0xdc, 0xd8, 0xa8, 0x32, - 0x58, 0x96, 0xb9, 0x6e, 0xcd, 0xa5, 0x6b, 0x07, 0xc5, 0x01, 0xf3, 0xae, 0x24, 0xfb, 0xfa, 0x46, 0xaf, 0xa5, 0x76, - 0x82, 0x28, 0x52, 0x2b, 0x73, 0x90, 0x0b, 0x7c, 0x96, 0xe2, 0x34, 0x3f, 0x50, 0x74, 0x87, 0xe6, 0x46, 0xb1, 0x00, - 0x08, 0x90, 0x5d, 0x31, 0x88, 0xf2, 0xf5, 0x18, 0xf8, 0x53, 0xa0, 0x7c, 0x6c, 0xcc, 0x70, 0x5b, 0x40, 0x4b, 0x1e, - 0xa7, 0xb4, 0xe6, 0x12, 0x32, 0xa5, 0x4f, 0x68, 0x46, 0xf3, 0x1d, 0xea, 0x2e, 0x44, 0xef, 0xaf, 0x65, 0x15, 0x6a, - 0x65, 0x08, 0x45, 0xde, 0x31, 0xd5, 0x89, 0x1a, 0x05, 0x28, 0x9e, 0x1a, 0x91, 0xc8, 0xcd, 0x6a, 0xf6, 0xa3, 0xd2, - 0xd8, 0xa5, 0x09, 0xae, 0x58, 0x6e, 0x1a, 0x38, 0x8e, 0x93, 0xa3, 0x09, 0xa7, 0x55, 0xfb, 0x6a, 0x11, 0xf9, 0xd2, - 0x22, 0x72, 0xcf, 0xb0, 0xb3, 0xdc, 0x8a, 0x96, 0x8d, 0xee, 0xfe, 0xdf, 0x5c, 0xb3, 0x11, 0xaa, 0xab, 0x1e, 0xf2, - 0x67, 0xb7, 0x64, 0xb7, 0x71, 0x20, 0x58, 0xaa, 0x6c, 0x1c, 0x45, 0x69, 0xc8, 0x30, 0xaa, 0x2e, 0x99, 0x2b, 0x8f, - 0x46, 0xcd, 0xde, 0xcd, 0x58, 0xea, 0x2e, 0xe8, 0xf6, 0x45, 0xa1, 0x70, 0xc4, 0x5d, 0xb5, 0x37, 0x35, 0xa5, 0xd8, - 0xc0, 0x0a, 0xcb, 0x02, 0xa5, 0x08, 0x4b, 0xbd, 0x67, 0x11, 0x37, 0xe5, 0xb8, 0x50, 0x96, 0x55, 0xa8, 0xa9, 0x69, - 0x94, 0x5a, 0xb5, 0xca, 0x5c, 0x36, 0xd6, 0x3a, 0x69, 0x5a, 0xad, 0x1b, 0x64, 0x8f, 0x76, 0x48, 0xd8, 0xbd, 0x79, - 0xcd, 0x2a, 0xf4, 0x8d, 0x66, 0x85, 0x8f, 0x2c, 0x35, 0x5d, 0x85, 0xee, 0x55, 0x34, 0x53, 0x1b, 0xc7, 0x40, 0x78, - 0x6a, 0x22, 0xdc, 0xc0, 0x6c, 0x26, 0x39, 0x57, 0x76, 0x12, 0x8c, 0xeb, 0x7d, 0x61, 0x1f, 0x52, 0xb9, 0x0f, 0x4b, - 0x48, 0x5c, 0x54, 0x3d, 0x89, 0x04, 0xd1, 0x86, 0xcd, 0x51, 0xb9, 0x33, 0xe5, 0x83, 0x83, 0xb0, 0x47, 0x70, 0x2c, - 0x16, 0x89, 0x6e, 0xa5, 0x06, 0xea, 0x7a, 0x95, 0x5d, 0x78, 0x7d, 0xfd, 0x50, 0xb8, 0x8e, 0xd2, 0x7d, 0x61, 0xbf, - 0x7a, 0x9a, 0xe3, 0x3e, 0x7c, 0x81, 0xad, 0x48, 0x15, 0xad, 0x4a, 0x4a, 0xa3, 0xa1, 0x4e, 0xb3, 0xf5, 0x7d, 0x12, - 0x06, 0xdb, 0x3e, 0x5c, 0xe2, 0x5e, 0x54, 0xa8, 0xc4, 0x74, 0xb5, 0xe4, 0x43, 0x35, 0x74, 0xe4, 0xba, 0xae, 0x9f, - 0x93, 0x1d, 0xb3, 0xb1, 0xca, 0xb4, 0xbc, 0x73, 0x27, 0x37, 0x06, 0xfa, 0x50, 0xb2, 0x89, 0x8f, 0x0e, 0x8a, 0xe4, - 0xfc, 0x2a, 0x21, 0xdd, 0xe5, 0xa3, 0x16, 0x42, 0x4b, 0x86, 0x29, 0xa0, 0x0d, 0x0c, 0xf2, 0xf0, 0x22, 0x8c, 0x84, - 0x55, 0x8e, 0x22, 0x0d, 0x72, 0xe0, 0x00, 0x73, 0xa5, 0x6a, 0xc0, 0xe2, 0x50, 0x79, 0x44, 0x9e, 0xa0, 0x55, 0x68, - 0x49, 0xf7, 0xfd, 0x31, 0x47, 0x5f, 0xb0, 0xd6, 0x22, 0x4a, 0xcb, 0x70, 0x43, 0x49, 0x11, 0x35, 0xf0, 0x6a, 0xd8, - 0x8b, 0xc5, 0xee, 0x35, 0x4b, 0x00, 0xf6, 0x08, 0x58, 0xda, 0x44, 0xd7, 0x15, 0x0b, 0xcf, 0x8a, 0x33, 0xc2, 0xf1, - 0x58, 0x39, 0xb6, 0xd2, 0xff, 0x3b, 0x0b, 0x66, 0x77, 0x65, 0xb0, 0xd7, 0x44, 0x69, 0x29, 0x7d, 0xa5, 0x4b, 0x50, - 0x53, 0x66, 0x6e, 0x1a, 0xf8, 0xca, 0x9f, 0xda, 0x91, 0x3e, 0x13, 0x30, 0x2c, 0x4a, 0xab, 0x4f, 0x53, 0x43, 0x47, - 0xfa, 0x36, 0x94, 0x48, 0x4d, 0x67, 0xf1, 0x40, 0x01, 0x0b, 0xd6, 0x2c, 0x57, 0x74, 0x74, 0x11, 0xc5, 0x71, 0x55, - 0xfa, 0x25, 0x7c, 0x3d, 0x57, 0x7c, 0x3d, 0xd3, 0x7c, 0x1d, 0x39, 0x05, 0xf2, 0x75, 0x39, 0x5c, 0xd5, 0x3d, 0x5b, - 0x3a, 0x9d, 0x99, 0xe4, 0xe8, 0x39, 0x59, 0xd2, 0x38, 0xdf, 0x4c, 0x43, 0xe0, 0x96, 0x9a, 0x17, 0x08, 0x1b, 0xb5, - 0xed, 0x39, 0xd2, 0x0a, 0x7a, 0x31, 0xb9, 0xe9, 0xa4, 0x80, 0x7a, 0x96, 0x17, 0xbc, 0xa4, 0xec, 0x87, 0x4f, 0xd0, - 0x4f, 0x67, 0x2c, 0x07, 0x85, 0x18, 0x15, 0x7f, 0x91, 0x12, 0xa5, 0x57, 0x17, 0xa9, 0xd5, 0xe5, 0x7a, 0x75, 0xc8, - 0xe9, 0xab, 0xd5, 0x0d, 0x6e, 0xe6, 0xf5, 0xb4, 0xbc, 0xa8, 0x5c, 0x5e, 0xb5, 0xdf, 0xd7, 0xd7, 0xce, 0x42, 0x09, - 0xba, 0xf0, 0x95, 0x89, 0x92, 0x95, 0xa3, 0x23, 0x0f, 0x30, 0x31, 0x83, 0x05, 0x85, 0x5c, 0x74, 0x29, 0xe2, 0x5e, - 0x7c, 0xce, 0xc5, 0x43, 0x9e, 0x7a, 0xd9, 0xff, 0x30, 0x9d, 0x4c, 0x51, 0x1b, 0x5b, 0x20, 0x69, 0x68, 0xf0, 0x7e, - 0xa1, 0xbe, 0x58, 0x51, 0x56, 0xeb, 0x43, 0xe7, 0xb1, 0x46, 0x4d, 0xa5, 0xc5, 0x0c, 0x86, 0xd4, 0xac, 0x2c, 0x2a, - 0x19, 0xc7, 0x2a, 0xb7, 0xca, 0xe1, 0xa2, 0x53, 0x46, 0x57, 0xbc, 0x76, 0x22, 0xc9, 0x87, 0x23, 0xe4, 0x75, 0x06, - 0xfb, 0xd1, 0xe4, 0x6e, 0xee, 0x7f, 0x51, 0x21, 0x67, 0x5e, 0x2c, 0xa0, 0x6f, 0x5e, 0x14, 0x4f, 0x94, 0x95, 0xcd, - 0x9e, 0xac, 0x37, 0x87, 0xab, 0x3a, 0x65, 0x2d, 0x1e, 0x9f, 0x40, 0xd1, 0x92, 0xee, 0x18, 0xcc, 0x27, 0xe9, 0x80, - 0xfb, 0x36, 0x74, 0x4f, 0xec, 0x02, 0x3d, 0xab, 0x6a, 0xf3, 0x07, 0xc2, 0x99, 0xbf, 0xad, 0xbb, 0x58, 0xfd, 0x27, - 0x05, 0x3a, 0xc0, 0x7e, 0x5c, 0x76, 0xbe, 0xfe, 0x00, 0xe6, 0x20, 0x69, 0xa2, 0xa5, 0x52, 0xfb, 0x63, 0x25, 0x97, - 0x7e, 0xf4, 0xd7, 0xb6, 0xaf, 0x6c, 0x10, 0xbb, 0xe5, 0xdd, 0xf3, 0x76, 0x6c, 0x97, 0x5c, 0xc3, 0xdf, 0xaa, 0x13, - 0xff, 0x51, 0xbb, 0x86, 0x8f, 0x82, 0x8f, 0x75, 0xcf, 0xf0, 0x4c, 0x04, 0x47, 0xbd, 0x23, 0x6d, 0x32, 0xa7, 0x60, - 0x1e, 0x80, 0x11, 0x1f, 0x47, 0xa2, 0x81, 0xe1, 0x37, 0x9b, 0xcd, 0x65, 0x05, 0x7a, 0x15, 0xc9, 0xa5, 0x5d, 0x68, - 0x63, 0x8f, 0x71, 0x11, 0xd8, 0x9b, 0xd0, 0x70, 0xd3, 0x66, 0x93, 0xe0, 0x14, 0xbf, 0x6c, 0xce, 0x9d, 0x97, 0xa1, - 0x18, 0x7b, 0x59, 0x08, 0x53, 0x4d, 0x1c, 0x77, 0xcb, 0xb6, 0x5d, 0x2f, 0x27, 0x83, 0xe3, 0x81, 0x5b, 0x6c, 0x9e, - 0xb2, 0x27, 0xd0, 0xa5, 0x67, 0x6f, 0x4d, 0xd8, 0x23, 0x11, 0x9c, 0x1e, 0x6c, 0xce, 0x9f, 0x88, 0xa2, 0x7b, 0xca, - 0x2e, 0x4b, 0xaf, 0x3d, 0x7b, 0x1f, 0x38, 0xb0, 0xd1, 0x97, 0x0a, 0x1a, 0xa0, 0x2e, 0xe9, 0xbd, 0xb7, 0x5d, 0xf6, - 0x8e, 0x62, 0x2b, 0x15, 0xbb, 0x51, 0xe1, 0x95, 0x8d, 0xc0, 0x4e, 0xc9, 0x47, 0x60, 0xc3, 0x21, 0xaf, 0xca, 0x4a, - 0x5d, 0x81, 0x1d, 0x89, 0xa0, 0x66, 0x91, 0xb3, 0x97, 0x14, 0xa5, 0x39, 0x12, 0x4e, 0xe2, 0xea, 0x61, 0x1c, 0xed, - 0x8b, 0x56, 0x67, 0x33, 0x39, 0x96, 0x2e, 0x06, 0x2f, 0x02, 0x05, 0x20, 0x04, 0x09, 0x7c, 0xe2, 0x9a, 0xfa, 0x07, - 0xfb, 0x2e, 0x38, 0x3d, 0xb6, 0xfe, 0xd3, 0x57, 0xbf, 0x0c, 0x7f, 0xc9, 0x4e, 0x4e, 0xd9, 0x9b, 0x60, 0xfb, 0xc0, - 0xe9, 0xf9, 0xce, 0x46, 0xa3, 0x71, 0xfd, 0xcb, 0xf6, 0xf1, 0xdf, 0xc3, 0xc6, 0x6f, 0x0f, 0x1b, 0x3f, 0x9f, 0xb8, - 0xd7, 0xce, 0x2f, 0xdb, 0xbd, 0x63, 0xf5, 0x74, 0xfc, 0xf7, 0xee, 0x2f, 0xf9, 0xc9, 0x5f, 0x64, 0xe1, 0xa6, 0xeb, - 0x6e, 0x8f, 0xd8, 0x54, 0x04, 0xdb, 0x8d, 0x46, 0x17, 0xbe, 0x8d, 0xe0, 0x1b, 0x7e, 0x9e, 0x05, 0x6f, 0xf9, 0xe8, - 0xc9, 0xe5, 0xd4, 0x39, 0xed, 0x5e, 0x6f, 0xce, 0xbf, 0x2b, 0x70, 0xd4, 0xe3, 0xbf, 0xff, 0xf2, 0x4b, 0x6e, 0xdf, - 0xed, 0x06, 0xdb, 0x27, 0x5b, 0xae, 0x83, 0xa5, 0x7f, 0x09, 0xe8, 0x2f, 0x54, 0x1e, 0xff, 0x5d, 0x41, 0x61, 0xdf, - 0xfd, 0xe5, 0xf4, 0xa0, 0x1b, 0x9c, 0x5c, 0x3b, 0xf6, 0xf5, 0x5d, 0xf7, 0xda, 0x75, 0xaf, 0x37, 0xdd, 0x53, 0x66, - 0x8f, 0x00, 0x6f, 0xe7, 0x30, 0xf6, 0x5d, 0x18, 0x7b, 0x08, 0x9f, 0x36, 0x7c, 0x1e, 0xc2, 0xe7, 0xdf, 0xa1, 0xaf, - 0x74, 0xb2, 0x5d, 0x93, 0x7f, 0xe3, 0x1a, 0x03, 0x1c, 0x21, 0xa0, 0xfc, 0x5a, 0x44, 0x22, 0xe6, 0xee, 0xe6, 0x76, - 0xc4, 0x3e, 0x11, 0x9a, 0x40, 0x98, 0x7b, 0x9e, 0x87, 0xc6, 0x9d, 0x33, 0xff, 0x80, 0x9b, 0x8d, 0x34, 0xb3, 0xe9, - 0x63, 0x64, 0x07, 0x1d, 0x01, 0xb9, 0x2f, 0xd8, 0x79, 0x18, 0x83, 0x7e, 0xe3, 0x73, 0x20, 0xe8, 0x7e, 0xf0, 0x49, - 0x38, 0x20, 0xf4, 0x5f, 0x08, 0xfc, 0xd2, 0x76, 0xd9, 0xa1, 0x0a, 0x62, 0xe2, 0x49, 0x96, 0x44, 0x95, 0xa4, 0x52, - 0x65, 0x01, 0xc8, 0xa6, 0x2b, 0x2a, 0xe1, 0xe0, 0x26, 0x08, 0xf5, 0x66, 0x2d, 0xe4, 0xc9, 0x2e, 0x02, 0x4d, 0x12, - 0xef, 0x32, 0xce, 0x7f, 0x0c, 0xe3, 0x4f, 0x60, 0xf7, 0x5e, 0xb2, 0x56, 0xfb, 0x01, 0x23, 0x2f, 0x34, 0x68, 0x1a, - 0x9d, 0x32, 0x5e, 0xf5, 0x5a, 0xc8, 0x38, 0x01, 0x4a, 0xd9, 0xba, 0x33, 0x06, 0x77, 0x7c, 0x23, 0x59, 0xf2, 0x58, - 0x65, 0xe1, 0x85, 0xed, 0xd6, 0x63, 0xa3, 0x51, 0x02, 0xcb, 0x02, 0x5a, 0x10, 0x1c, 0xf8, 0x1b, 0x4c, 0x6b, 0xa9, - 0xf5, 0x5a, 0x21, 0x0e, 0x64, 0x97, 0x3a, 0xc3, 0xcc, 0xb0, 0x38, 0x67, 0x3a, 0xe8, 0x84, 0x67, 0xc5, 0xc1, 0x08, - 0x95, 0xd2, 0x3b, 0x1e, 0x57, 0x01, 0xb0, 0xc5, 0x18, 0x5f, 0xa3, 0x85, 0x9e, 0xb0, 0x13, 0x92, 0xcf, 0x20, 0xc6, - 0x03, 0x94, 0xa2, 0xed, 0x9e, 0x7d, 0x90, 0x9f, 0x8f, 0xba, 0x36, 0xc6, 0x67, 0xd2, 0xe0, 0x0d, 0x39, 0x86, 0xb0, - 0xc1, 0x38, 0x68, 0x76, 0xc6, 0x07, 0xbc, 0x33, 0xde, 0xda, 0xd2, 0x4a, 0x34, 0x28, 0x99, 0xc7, 0x63, 0xd9, 0x3d, - 0x64, 0x03, 0x36, 0x0b, 0x60, 0xc0, 0x11, 0x34, 0xc3, 0x2e, 0x9d, 0xd1, 0x41, 0xac, 0xa6, 0x01, 0xae, 0x9a, 0x7a, - 0x71, 0x98, 0x8b, 0xe7, 0x68, 0xed, 0x07, 0x23, 0x36, 0x00, 0x1d, 0x99, 0x5f, 0xf2, 0xbe, 0x13, 0x83, 0x0d, 0xae, - 0x38, 0x8d, 0xdb, 0x71, 0x47, 0x81, 0xd1, 0x0c, 0xad, 0x88, 0xe0, 0x4d, 0x6f, 0x70, 0xdc, 0x3a, 0x81, 0x2f, 0x36, - 0x90, 0xb7, 0xdd, 0x4b, 0x83, 0xa9, 0xf0, 0xb1, 0xc4, 0xd0, 0x95, 0x83, 0x11, 0x16, 0xb5, 0x8d, 0x22, 0xe7, 0x50, - 0x78, 0x02, 0x74, 0x5e, 0x07, 0x8b, 0xd1, 0xfe, 0xcf, 0x35, 0x61, 0xdb, 0x07, 0xdb, 0xf6, 0x16, 0x96, 0x12, 0x71, - 0xba, 0x30, 0xc5, 0x99, 0x0b, 0x9d, 0x77, 0x4e, 0x4c, 0x01, 0x40, 0x85, 0x38, 0xf9, 0x19, 0x4c, 0xde, 0xa4, 0xc9, - 0xbb, 0x76, 0x0f, 0x8a, 0x73, 0xa9, 0xa1, 0xf5, 0x72, 0xff, 0x0d, 0x2d, 0xd5, 0xf5, 0x15, 0x70, 0x7a, 0x07, 0x82, - 0x46, 0xdb, 0x77, 0x66, 0xe6, 0x22, 0x1a, 0x38, 0x99, 0xc2, 0x02, 0x0b, 0x03, 0x6c, 0x0f, 0x93, 0xe2, 0x8c, 0x55, - 0xb7, 0x33, 0x5f, 0x3d, 0xdf, 0xb5, 0xef, 0xf6, 0x86, 0xc2, 0x3f, 0x17, 0x72, 0xfa, 0xa1, 0xb8, 0xbe, 0xc6, 0xcf, - 0x73, 0x01, 0x8b, 0x3c, 0xa3, 0xa2, 0xa9, 0x2a, 0x1a, 0x61, 0xd1, 0x1b, 0x1f, 0x41, 0x65, 0x79, 0xa9, 0x65, 0xc9, - 0x3d, 0x39, 0x0f, 0x08, 0xf6, 0x3b, 0x77, 0x60, 0x6b, 0xb6, 0x5a, 0x27, 0xe8, 0xe2, 0xcf, 0x44, 0xfe, 0x63, 0x24, - 0x80, 0x35, 0x6f, 0x77, 0x6d, 0xb7, 0x67, 0x5b, 0xb8, 0xb5, 0x9d, 0x6c, 0x2b, 0x90, 0x18, 0x8e, 0xb7, 0x1e, 0x09, - 0x7f, 0xd6, 0x0d, 0x00, 0x71, 0x91, 0x64, 0xe1, 0xa1, 0xcb, 0x62, 0xc5, 0x38, 0x9b, 0x6c, 0xe6, 0x6e, 0x71, 0xb1, - 0xa5, 0x9f, 0xe1, 0x69, 0xb2, 0x75, 0xee, 0xfa, 0x31, 0x7c, 0xc0, 0x52, 0x03, 0x58, 0x72, 0xd9, 0x4d, 0x8b, 0xbf, - 0x31, 0xf0, 0x68, 0xed, 0xed, 0x3c, 0xa6, 0xe3, 0x90, 0x6d, 0x39, 0xc9, 0x31, 0x3f, 0xb9, 0xbe, 0xb6, 0x0f, 0x7a, - 0x00, 0xc2, 0x96, 0xa3, 0x09, 0x6d, 0x5b, 0x53, 0x1a, 0x6c, 0x46, 0x74, 0x52, 0xa8, 0x68, 0xd2, 0xab, 0x5a, 0xe4, - 0x68, 0x5e, 0x1d, 0x76, 0x83, 0x07, 0xf0, 0xa2, 0x34, 0x64, 0xa4, 0xc2, 0x3a, 0xc5, 0x65, 0x6a, 0x62, 0xce, 0x82, - 0x26, 0xe0, 0x59, 0x3b, 0xaf, 0xc1, 0xa2, 0xab, 0x08, 0x3e, 0x0e, 0xaa, 0xe6, 0xec, 0x18, 0xc8, 0xf6, 0x24, 0x78, - 0x2c, 0x0d, 0x92, 0x8e, 0x76, 0x8d, 0xf3, 0x38, 0x78, 0xb5, 0x10, 0xc1, 0x0d, 0x31, 0xbc, 0x72, 0xe1, 0xf5, 0x67, - 0x59, 0x06, 0x8f, 0xaf, 0x40, 0xd2, 0x06, 0xaa, 0x29, 0x9a, 0x4a, 0x18, 0x9a, 0x65, 0xa8, 0xa4, 0xb5, 0xf5, 0xc9, - 0x98, 0x2d, 0x55, 0x8f, 0x82, 0x99, 0xd4, 0x9f, 0x28, 0x60, 0xdb, 0x19, 0x29, 0xc3, 0x18, 0x54, 0xc4, 0x99, 0x8a, - 0xe4, 0x3a, 0xc0, 0xeb, 0x46, 0x5e, 0x1f, 0xab, 0x71, 0x02, 0x50, 0x3d, 0xe9, 0x1c, 0x01, 0xf9, 0x5e, 0x78, 0x09, - 0xb0, 0x48, 0x2c, 0x04, 0x13, 0xa5, 0x94, 0xcc, 0xfa, 0x78, 0x1d, 0x8c, 0x3b, 0xc4, 0x6e, 0x72, 0x2f, 0x81, 0x16, - 0x88, 0x1e, 0x8c, 0xdd, 0xab, 0x22, 0xe0, 0x36, 0x66, 0x88, 0xaa, 0x82, 0xef, 0xd8, 0xf4, 0x5e, 0x8f, 0xd0, 0xe5, - 0x4b, 0xca, 0x56, 0xd9, 0x58, 0xfa, 0xc1, 0x5d, 0x17, 0x46, 0x19, 0x79, 0x18, 0xda, 0x23, 0x12, 0xe2, 0x68, 0xcb, - 0x8d, 0x4c, 0xa2, 0x9a, 0x94, 0x63, 0x9e, 0x03, 0x61, 0xa7, 0x5b, 0x5b, 0xe4, 0x86, 0x9e, 0x49, 0x92, 0x18, 0x81, - 0x04, 0x28, 0xcf, 0x96, 0x6e, 0xf7, 0x34, 0xa8, 0xcf, 0xe4, 0x9c, 0xd7, 0xdd, 0xb9, 0x5b, 0x98, 0x26, 0x81, 0x9e, - 0x42, 0x01, 0x83, 0xb3, 0x87, 0xc1, 0xb6, 0x73, 0xec, 0xf5, 0xfe, 0x7a, 0x02, 0x66, 0xa5, 0xf7, 0x17, 0x77, 0x5b, - 0x32, 0x8e, 0x73, 0x30, 0x2a, 0xe4, 0x14, 0x73, 0x0a, 0x61, 0x02, 0x23, 0xc3, 0xf3, 0xe6, 0x67, 0x2c, 0x01, 0xb8, - 0xfd, 0x87, 0x78, 0xc6, 0x35, 0xdd, 0x3c, 0x65, 0x48, 0x47, 0x50, 0x26, 0x39, 0x89, 0x67, 0xf7, 0x9e, 0x8b, 0xf2, - 0xa9, 0x67, 0xf7, 0x7e, 0xab, 0x9e, 0xfe, 0x6a, 0xf7, 0x7e, 0x10, 0xfe, 0x6f, 0x85, 0x72, 0x76, 0xd7, 0xa6, 0xb8, - 0xa7, 0xa7, 0x28, 0xe4, 0xc6, 0x18, 0x98, 0x9b, 0xb9, 0xcb, 0x7e, 0x8e, 0x91, 0x5b, 0x00, 0x1e, 0x34, 0x2b, 0xca, - 0x3d, 0x11, 0x8e, 0x10, 0xa5, 0xc6, 0x0e, 0xe4, 0x66, 0x64, 0xbf, 0x5a, 0x30, 0x12, 0x8a, 0xa6, 0x56, 0x44, 0xe5, - 0xa8, 0x0b, 0x98, 0xab, 0xb5, 0x25, 0x8d, 0xa9, 0x1e, 0x49, 0x2f, 0xb9, 0xf4, 0x39, 0x50, 0xfd, 0xf9, 0xc1, 0xa8, - 0x73, 0x0e, 0x5c, 0x3a, 0xd7, 0x84, 0x35, 0x3b, 0x3e, 0x3f, 0x61, 0xef, 0xd1, 0xa7, 0x67, 0x52, 0x12, 0xab, 0x2d, - 0xaf, 0xad, 0x96, 0xb7, 0xb5, 0x05, 0x0b, 0xec, 0x18, 0x5d, 0x47, 0xb2, 0x6b, 0x51, 0x48, 0x9c, 0x2c, 0x12, 0xda, - 0xbe, 0x4b, 0x25, 0x98, 0x0e, 0x05, 0x4f, 0x4f, 0x84, 0xbb, 0x72, 0x54, 0x1c, 0x13, 0xbb, 0xd3, 0x89, 0x45, 0xe6, - 0x29, 0x65, 0x84, 0x83, 0x58, 0xc0, 0xae, 0xa5, 0x23, 0x78, 0xc2, 0x66, 0x5b, 0x2d, 0x22, 0x72, 0x68, 0x53, 0x1f, - 0xeb, 0x7e, 0x35, 0x16, 0x34, 0x0a, 0x26, 0x25, 0x96, 0x8a, 0x6c, 0x6b, 0xab, 0xa8, 0x47, 0x3b, 0xf5, 0xb9, 0xad, - 0xc5, 0x1f, 0x2e, 0x17, 0xd3, 0x32, 0xb4, 0x7c, 0xad, 0x24, 0x6a, 0x04, 0x80, 0x24, 0x3c, 0x43, 0x19, 0x1a, 0x08, - 0x16, 0x15, 0x45, 0x29, 0xd7, 0x3f, 0xa1, 0x10, 0x85, 0x43, 0x9e, 0x20, 0xdf, 0x21, 0xb3, 0x8b, 0x65, 0x2c, 0x65, - 0x63, 0xe2, 0x1a, 0xb0, 0xf2, 0x43, 0x9d, 0xd0, 0x22, 0x88, 0x03, 0xc5, 0x41, 0x64, 0x48, 0xa4, 0x3c, 0xe0, 0x60, - 0x10, 0x1c, 0xa6, 0x37, 0x9a, 0x64, 0x60, 0x50, 0xf8, 0xd4, 0x2c, 0x56, 0x7c, 0x2b, 0x0c, 0xde, 0x81, 0x20, 0x2f, - 0x83, 0x23, 0x1e, 0xb1, 0xbf, 0xc7, 0x51, 0xc6, 0x49, 0x03, 0xdf, 0xd4, 0x66, 0x5f, 0x5c, 0x57, 0x1f, 0x63, 0xd3, - 0x79, 0x83, 0x88, 0x0c, 0xd1, 0xb7, 0x93, 0x05, 0x4b, 0xcd, 0xc0, 0x40, 0x7b, 0xbd, 0xca, 0x04, 0x86, 0xef, 0xd2, - 0x3a, 0x24, 0xcd, 0x86, 0x85, 0x15, 0xa4, 0xb1, 0xfa, 0xe2, 0xc3, 0x9c, 0xa8, 0x20, 0x85, 0xa0, 0xd3, 0x30, 0x1a, - 0xe8, 0x1d, 0x60, 0x07, 0xcd, 0x24, 0x97, 0x99, 0xcb, 0x06, 0x01, 0xe5, 0x8c, 0x03, 0xee, 0xca, 0xb5, 0x97, 0x8c, - 0x2b, 0x35, 0xc4, 0xb7, 0x3f, 0xa6, 0x4a, 0xb4, 0x1f, 0x60, 0xfd, 0x41, 0xac, 0x30, 0x10, 0x80, 0x66, 0x10, 0xd7, - 0xcc, 0xb2, 0x00, 0x37, 0x80, 0xe6, 0x3a, 0xc2, 0x9d, 0xf0, 0xa4, 0xe2, 0x07, 0xad, 0x68, 0x56, 0x50, 0x76, 0x48, - 0x74, 0x7c, 0x5c, 0xca, 0x4b, 0xab, 0xac, 0xd1, 0x1f, 0xd0, 0x72, 0xd2, 0x0f, 0xaf, 0xd4, 0xd0, 0x65, 0xc1, 0x63, - 0x9d, 0x40, 0x06, 0xdf, 0x5f, 0xaa, 0x1c, 0x32, 0x10, 0x12, 0x8a, 0xdb, 0x2f, 0x59, 0x98, 0x0f, 0x5f, 0x7a, 0x55, - 0x2d, 0x35, 0x86, 0xb2, 0xf7, 0xab, 0x9a, 0x61, 0x79, 0x31, 0xab, 0x4c, 0x7c, 0x82, 0x6f, 0xce, 0x63, 0x7f, 0xae, - 0x44, 0x83, 0x1f, 0x15, 0x8c, 0xc4, 0x91, 0x9f, 0x17, 0xa5, 0x67, 0xe4, 0x31, 0xa8, 0x63, 0x14, 0x05, 0xaa, 0xef, - 0x9a, 0x52, 0xf2, 0x80, 0x20, 0x8f, 0xfa, 0xa0, 0x40, 0xae, 0x09, 0x0d, 0x5d, 0xba, 0x5e, 0x34, 0xc1, 0xe4, 0x19, - 0x02, 0x3d, 0x62, 0x1b, 0xa0, 0x1d, 0xd4, 0x85, 0x57, 0x46, 0x44, 0x9a, 0xd6, 0x24, 0x0b, 0x03, 0x0d, 0x0f, 0xc4, - 0x63, 0x13, 0x76, 0x3c, 0x07, 0xc5, 0x47, 0x9e, 0xd0, 0xb0, 0x1c, 0x57, 0x0a, 0x19, 0xcc, 0x0b, 0x53, 0xa7, 0x55, - 0x8a, 0xdf, 0x41, 0x27, 0x24, 0xd7, 0x23, 0x49, 0xf4, 0x01, 0x91, 0xc5, 0x33, 0x27, 0x65, 0x29, 0x0d, 0x7c, 0x14, - 0x9d, 0xc5, 0x98, 0x5a, 0x82, 0xab, 0x02, 0x15, 0xd4, 0x2f, 0x9b, 0xb6, 0x54, 0xd3, 0xd0, 0xa3, 0x7d, 0x4a, 0x59, - 0xe8, 0x21, 0xe3, 0x86, 0x0f, 0xc5, 0xb5, 0x97, 0xbb, 0xdc, 0x03, 0x2a, 0x90, 0x9d, 0x9e, 0x0a, 0xe8, 0xa0, 0xea, - 0xab, 0xc0, 0xdd, 0x0f, 0x92, 0x57, 0x0c, 0x5c, 0x82, 0x7f, 0x6b, 0x2b, 0x3e, 0x29, 0x30, 0x0a, 0xed, 0x84, 0x75, - 0x0c, 0x6a, 0xe0, 0x49, 0xd3, 0xab, 0x2f, 0x1f, 0x58, 0xa6, 0x0e, 0xd2, 0xd6, 0xb1, 0x75, 0xc9, 0xb2, 0xe2, 0xdc, - 0x29, 0x93, 0x7f, 0x9a, 0x4b, 0x19, 0x53, 0x1a, 0x04, 0x37, 0x32, 0x69, 0x36, 0xd2, 0x8b, 0x31, 0x8e, 0x44, 0x84, - 0xed, 0x9e, 0xab, 0xb4, 0x05, 0x46, 0xf9, 0x55, 0xaa, 0x91, 0x66, 0x67, 0x6d, 0xd7, 0xd7, 0x8d, 0x30, 0x28, 0x85, - 0x8d, 0x80, 0xbb, 0x49, 0xf2, 0x7e, 0xb6, 0x9c, 0x75, 0xc9, 0x72, 0x57, 0xf9, 0xb8, 0x08, 0x0a, 0x42, 0x56, 0xbb, - 0x44, 0xca, 0xb3, 0x60, 0xba, 0x9e, 0xe4, 0x1f, 0x1a, 0x24, 0xff, 0x28, 0xe0, 0x06, 0xf9, 0x4b, 0x0f, 0x87, 0x97, - 0x2a, 0xd7, 0x42, 0xae, 0xab, 0x0e, 0xa7, 0x01, 0xfa, 0xd0, 0xea, 0x18, 0xad, 0x45, 0x15, 0xd7, 0x30, 0x14, 0xf3, - 0x84, 0x90, 0x17, 0x92, 0xe9, 0x10, 0xb0, 0x53, 0xc5, 0xd4, 0x70, 0xea, 0x55, 0x2e, 0x3d, 0x93, 0x03, 0x3e, 0x7c, - 0x7f, 0x73, 0x38, 0xf4, 0x70, 0xba, 0x7c, 0x72, 0x8d, 0xec, 0x4f, 0x5c, 0xb5, 0x71, 0x70, 0xeb, 0xb9, 0xa0, 0x38, - 0x7f, 0x19, 0xc6, 0xae, 0x33, 0x9f, 0x85, 0x43, 0xa8, 0xe5, 0x1f, 0x42, 0xdb, 0x6a, 0x51, 0x0b, 0x6e, 0x0c, 0x8b, - 0xfc, 0x48, 0xe6, 0xa0, 0x86, 0xd9, 0x1a, 0xf6, 0xf1, 0x90, 0x1a, 0x80, 0x84, 0x5d, 0x5d, 0xfd, 0xa8, 0x50, 0x64, - 0x22, 0x41, 0x03, 0x26, 0x06, 0xfc, 0x4f, 0x92, 0x3c, 0xd2, 0x0d, 0xc9, 0x05, 0x44, 0xd0, 0x94, 0xf0, 0x54, 0x21, - 0xcc, 0xb6, 0x2b, 0xe7, 0xfb, 0x33, 0x58, 0xc2, 0xb4, 0x72, 0x3e, 0xbe, 0xad, 0x72, 0xaf, 0x90, 0x2c, 0xc0, 0x40, - 0x44, 0x3f, 0xbb, 0x2e, 0x90, 0xd1, 0xcb, 0x43, 0xdd, 0x9c, 0x0c, 0x48, 0xaf, 0xd2, 0xb7, 0x8d, 0xc8, 0x26, 0x79, - 0xe5, 0x64, 0xbd, 0x46, 0xc3, 0x42, 0xed, 0x26, 0xd6, 0xbe, 0x14, 0x04, 0x23, 0x3e, 0xbf, 0xa3, 0xd6, 0x7a, 0xdc, - 0xe2, 0xd3, 0x62, 0x02, 0xcb, 0xc2, 0xa6, 0xc0, 0x01, 0xcd, 0xc1, 0x34, 0x7e, 0xc4, 0xe1, 0x94, 0x61, 0xc8, 0xa2, - 0xc4, 0x89, 0x5b, 0x6c, 0x1a, 0x6e, 0x3b, 0x5a, 0x9f, 0x11, 0x27, 0x58, 0x58, 0x20, 0x7d, 0xfb, 0x44, 0x31, 0xeb, - 0x0f, 0x8b, 0xbd, 0x00, 0x2b, 0xef, 0x2a, 0x34, 0x29, 0x28, 0x09, 0x0a, 0x83, 0x69, 0x49, 0x95, 0x46, 0x05, 0x72, - 0x37, 0x9d, 0xd2, 0x05, 0xa0, 0x19, 0x86, 0xc9, 0x7b, 0x60, 0xba, 0x62, 0xb4, 0xc8, 0xe2, 0x95, 0x6b, 0x22, 0x32, - 0xcd, 0x16, 0xe4, 0xf0, 0x68, 0x68, 0x4b, 0x5f, 0x51, 0x5e, 0xa5, 0xc3, 0x96, 0x30, 0x1c, 0x22, 0xb2, 0x1c, 0x32, - 0x42, 0x0c, 0x0a, 0x5c, 0x69, 0x94, 0xbc, 0x46, 0xbd, 0x72, 0xcc, 0xe0, 0x1f, 0x26, 0xc0, 0xd6, 0x8e, 0x2c, 0xc0, - 0x26, 0xf3, 0x72, 0x8c, 0x4c, 0x02, 0x58, 0xe9, 0x0a, 0x8f, 0xb2, 0x26, 0x6a, 0x4e, 0x52, 0x07, 0x5b, 0x64, 0x6e, - 0xd9, 0xc1, 0x3b, 0x77, 0x22, 0xa5, 0xb8, 0xe9, 0xb0, 0x19, 0x32, 0xe0, 0x8f, 0xc2, 0x91, 0xb1, 0x28, 0x94, 0x19, - 0xa9, 0x37, 0x73, 0x6a, 0x53, 0x77, 0x52, 0xea, 0xc6, 0x14, 0xe2, 0xc6, 0x26, 0x9a, 0x52, 0x0a, 0xeb, 0x1d, 0x56, - 0xbc, 0x74, 0x53, 0xe6, 0x50, 0x0b, 0xcd, 0x05, 0xab, 0x3c, 0x12, 0x63, 0xf9, 0x9b, 0x32, 0x2d, 0xba, 0x6c, 0x84, - 0x6a, 0x18, 0x80, 0xf1, 0x8a, 0xf6, 0x80, 0x17, 0x48, 0x5f, 0xf3, 0x23, 0x61, 0xec, 0xa8, 0xf6, 0x61, 0xd3, 0x9c, - 0x86, 0xd4, 0x7f, 0x8b, 0x99, 0x2e, 0x8b, 0x67, 0xfe, 0x19, 0xc9, 0x42, 0x60, 0xa4, 0x35, 0xc6, 0x9e, 0x11, 0x63, - 0x77, 0x51, 0x4f, 0xd3, 0xa9, 0xdf, 0x3d, 0x95, 0xf0, 0x12, 0x29, 0x29, 0xa7, 0x48, 0xec, 0x7d, 0x19, 0x2c, 0x37, - 0xbe, 0x2f, 0xec, 0x86, 0x1f, 0x05, 0x98, 0x04, 0xc4, 0x14, 0x67, 0xcf, 0x60, 0x7b, 0xb6, 0xb6, 0x3a, 0xf9, 0x01, - 0xaf, 0x5c, 0x24, 0x15, 0x8c, 0x11, 0xc6, 0x73, 0x91, 0xe0, 0x6b, 0x32, 0x14, 0x23, 0xfe, 0x3a, 0x37, 0x3b, 0x47, - 0x57, 0x3b, 0xb4, 0x34, 0xb9, 0x9a, 0xd9, 0xb6, 0x8c, 0x99, 0xe2, 0x7a, 0x9c, 0x2a, 0xde, 0xf2, 0xe6, 0xe6, 0xfc, - 0x0e, 0x84, 0x7b, 0xa3, 0xc5, 0x30, 0x17, 0xcd, 0xed, 0x08, 0xc9, 0x12, 0xca, 0xd3, 0xd7, 0xd1, 0x8a, 0x34, 0x26, - 0x4c, 0x1b, 0x93, 0x75, 0x44, 0x65, 0xca, 0x8a, 0x20, 0x07, 0x45, 0x9c, 0x57, 0xd1, 0xfd, 0x85, 0xfc, 0x4b, 0x12, - 0x2e, 0xcb, 0xce, 0x76, 0x10, 0x2b, 0x82, 0x19, 0x84, 0xfa, 0x66, 0x5d, 0xe8, 0xa3, 0x02, 0x13, 0xcf, 0xb5, 0x12, - 0x8a, 0xbf, 0xad, 0x12, 0x8a, 0x2c, 0x53, 0x47, 0x9e, 0x04, 0x62, 0xeb, 0x16, 0x02, 0x51, 0x39, 0xd9, 0xb5, 0x4c, - 0x44, 0x75, 0xa4, 0x26, 0x13, 0xeb, 0x5b, 0x1a, 0x64, 0xb0, 0x97, 0x72, 0x37, 0xba, 0x6d, 0xc0, 0x20, 0x9c, 0xc0, - 0x0d, 0x64, 0xbf, 0xf8, 0xb5, 0x25, 0xbf, 0x1a, 0x9c, 0x58, 0x3a, 0x81, 0x9d, 0xa8, 0x34, 0x59, 0x5c, 0x0f, 0x53, - 0x9c, 0x1d, 0xca, 0xc9, 0x22, 0x9a, 0x56, 0x14, 0xa4, 0x08, 0x3c, 0x88, 0xca, 0x28, 0x13, 0x42, 0x4c, 0xb2, 0x42, - 0x19, 0x90, 0xce, 0xca, 0xe4, 0x3f, 0x6d, 0x5e, 0x7e, 0x5e, 0x13, 0xad, 0xc9, 0x15, 0xa9, 0x3e, 0xd4, 0xd2, 0x0d, - 0x14, 0x04, 0x4a, 0x3f, 0xdc, 0x20, 0x13, 0xb4, 0x12, 0xe5, 0xae, 0x29, 0x87, 0x58, 0x13, 0x5d, 0x68, 0x1b, 0xef, - 0x64, 0x80, 0x77, 0x85, 0x34, 0x61, 0xa9, 0x41, 0xd7, 0xc0, 0x23, 0x6b, 0xac, 0x64, 0x1c, 0x28, 0x4b, 0x89, 0x85, - 0x44, 0xa6, 0x22, 0xc8, 0x00, 0x89, 0xa8, 0x80, 0x76, 0xe2, 0x83, 0xac, 0x32, 0x81, 0x63, 0x50, 0xcb, 0x42, 0x3d, - 0xeb, 0xf8, 0x38, 0x02, 0xc5, 0x0e, 0xa6, 0x8e, 0xa5, 0x61, 0x02, 0x02, 0x0b, 0x14, 0xbc, 0x72, 0x8a, 0xe3, 0x18, - 0xf8, 0x60, 0x0a, 0xa7, 0x9f, 0xc0, 0x0a, 0x01, 0xac, 0xd0, 0x04, 0x8b, 0xaa, 0xb1, 0xdb, 0x14, 0x84, 0xe7, 0x94, - 0x04, 0xe0, 0x14, 0x21, 0xdc, 0x02, 0x2d, 0x51, 0x39, 0xf7, 0x42, 0x74, 0x46, 0x6d, 0x65, 0xc7, 0xf1, 0x56, 0xeb, - 0xc4, 0x60, 0x5c, 0xd0, 0x33, 0x08, 0x0b, 0x58, 0xce, 0x46, 0xae, 0x44, 0xe4, 0x47, 0x14, 0x65, 0x1f, 0x49, 0xb2, - 0xc8, 0x01, 0xcd, 0xdd, 0x58, 0x74, 0x06, 0x94, 0x14, 0xa5, 0xb6, 0x55, 0xb7, 0xab, 0x25, 0x41, 0x94, 0x8d, 0x98, - 0x8a, 0x05, 0xf7, 0xd0, 0xb2, 0x2f, 0xc9, 0xfc, 0xb9, 0x28, 0x93, 0xac, 0xeb, 0x14, 0xaf, 0x53, 0xab, 0x3d, 0xcf, - 0x0b, 0xb3, 0x11, 0x45, 0x32, 0x74, 0x14, 0x96, 0x88, 0x7f, 0x47, 0x81, 0x69, 0x4c, 0x7c, 0x5c, 0xce, 0x75, 0x12, - 0x48, 0xf0, 0xb5, 0x6a, 0xa3, 0x6f, 0x93, 0xfc, 0xba, 0xd2, 0xcb, 0xa0, 0x0e, 0xdc, 0xef, 0x85, 0x64, 0x57, 0x41, - 0x22, 0xc9, 0x63, 0x01, 0x67, 0x6b, 0x70, 0xf1, 0xab, 0x58, 0xc0, 0xd9, 0x7a, 0xdc, 0x6a, 0x4c, 0xfd, 0xb0, 0x0e, - 0x3e, 0x83, 0x37, 0x48, 0x40, 0xab, 0x02, 0x03, 0xca, 0xbd, 0x45, 0xdd, 0x4b, 0xb2, 0x52, 0x14, 0xa6, 0x22, 0x00, - 0x66, 0x5a, 0x3b, 0x00, 0x95, 0x36, 0x6a, 0x18, 0xbe, 0x91, 0x3f, 0x75, 0x0d, 0x97, 0x40, 0x3d, 0x73, 0x05, 0xc9, - 0x49, 0xf9, 0xda, 0x81, 0xf8, 0xd0, 0x36, 0x40, 0x25, 0x0e, 0x58, 0xdb, 0x14, 0xda, 0xa2, 0x2a, 0x95, 0xeb, 0xef, - 0x58, 0x8c, 0xf7, 0x40, 0xa8, 0x0c, 0xbf, 0x60, 0xc1, 0x14, 0x56, 0x08, 0xd6, 0x3f, 0x95, 0xa9, 0xef, 0x70, 0x08, - 0x35, 0x29, 0xe7, 0x52, 0x27, 0xcc, 0x40, 0x8c, 0x2a, 0x3a, 0xad, 0xa3, 0xed, 0xc9, 0x39, 0x7c, 0x7f, 0x11, 0xe5, - 0x80, 0x1d, 0x5c, 0x7e, 0x45, 0x71, 0xb8, 0x22, 0xd8, 0xab, 0x74, 0xa1, 0x57, 0x38, 0x18, 0xdc, 0xd8, 0x45, 0xd4, - 0x75, 0xa0, 0x71, 0x98, 0x0c, 0x62, 0x39, 0x89, 0x99, 0xce, 0xa8, 0x53, 0x38, 0xcb, 0x96, 0x66, 0x3a, 0x4d, 0xa5, - 0x6c, 0x10, 0x77, 0x07, 0x04, 0x6b, 0x49, 0xa0, 0xa5, 0xe7, 0x8d, 0x5a, 0x0b, 0x06, 0xbc, 0xd7, 0x6c, 0x82, 0xb9, - 0x12, 0x26, 0x0c, 0x8e, 0xea, 0xd5, 0xe1, 0xd4, 0x74, 0xf3, 0x74, 0xe5, 0xa5, 0xb6, 0x55, 0xc2, 0x81, 0xe8, 0xe4, - 0xde, 0x7a, 0xcb, 0xea, 0xa5, 0x96, 0x1c, 0x5a, 0x5a, 0x44, 0xb7, 0x65, 0xcc, 0xee, 0x5c, 0x93, 0x97, 0xab, 0x8f, - 0xe2, 0x07, 0x11, 0x7c, 0xc4, 0x5b, 0x43, 0xcf, 0xc4, 0x24, 0x5e, 0xb8, 0x1c, 0xd3, 0xf9, 0x50, 0x6a, 0xff, 0x1f, - 0x84, 0xf3, 0x8a, 0x3d, 0xc3, 0xb0, 0xee, 0xb7, 0x55, 0xf3, 0xe5, 0x70, 0xee, 0xb7, 0x15, 0x82, 0xbe, 0xf5, 0x97, - 0xda, 0x19, 0x61, 0xdc, 0xb6, 0xb7, 0xef, 0x35, 0x6d, 0xad, 0x2d, 0xfd, 0x28, 0x83, 0x48, 0x32, 0xd1, 0x92, 0xce, - 0x03, 0xab, 0xd2, 0xd4, 0x30, 0x5d, 0xae, 0x6e, 0x21, 0x71, 0x95, 0x60, 0x28, 0x75, 0xf8, 0x75, 0xdb, 0xa3, 0x64, - 0x4c, 0x26, 0xed, 0x8c, 0x37, 0x60, 0x2b, 0x6d, 0xe2, 0x29, 0x4b, 0x97, 0x6e, 0xe2, 0x8d, 0x03, 0xf4, 0xa0, 0xdd, - 0x6e, 0x0a, 0xc3, 0xd8, 0xce, 0xe5, 0x4d, 0x20, 0x73, 0xfc, 0x20, 0xd5, 0xba, 0x5b, 0xdd, 0xca, 0x78, 0x8f, 0xf6, - 0x3f, 0xfc, 0xaf, 0xaf, 0xc7, 0x71, 0xc5, 0x81, 0xb9, 0x3f, 0x2f, 0x4a, 0xa7, 0x40, 0x2a, 0x95, 0xb7, 0x04, 0x8e, - 0x49, 0x41, 0xe1, 0xed, 0xef, 0xd9, 0x4f, 0x8a, 0x25, 0x0e, 0x4b, 0x8e, 0xf3, 0xe4, 0xb6, 0x1c, 0x51, 0x82, 0x5f, - 0x46, 0xef, 0x91, 0x8e, 0x89, 0x42, 0x0b, 0x4d, 0x45, 0x8f, 0x53, 0xb5, 0x90, 0xb5, 0x59, 0xa9, 0x4c, 0x1b, 0xb0, - 0x51, 0x40, 0xd3, 0xac, 0x48, 0xe3, 0xd4, 0x56, 0xb6, 0x28, 0x4f, 0x55, 0x6d, 0x5e, 0x77, 0x0d, 0x16, 0xab, 0xc0, - 0x22, 0x08, 0xd3, 0x3a, 0xaa, 0x83, 0xc8, 0x88, 0x63, 0xb8, 0x2c, 0x32, 0x12, 0x2a, 0x6a, 0x9a, 0xb5, 0xec, 0xe3, - 0xb8, 0x8b, 0xf9, 0x44, 0x5a, 0x37, 0xaf, 0xc1, 0x61, 0xba, 0x10, 0x64, 0x77, 0xd3, 0xa7, 0xc0, 0xe4, 0xea, 0xca, - 0x89, 0x0c, 0x0c, 0xfd, 0x58, 0x66, 0xca, 0x56, 0x29, 0xad, 0x2b, 0xf0, 0xeb, 0xde, 0x90, 0x2b, 0xab, 0x50, 0xb7, - 0x5c, 0x6f, 0xe4, 0x1a, 0x3d, 0x4e, 0xd7, 0xe5, 0x1a, 0xd5, 0xb4, 0xdd, 0x8d, 0xa6, 0x7b, 0x73, 0x56, 0xaa, 0x9c, - 0x6b, 0x75, 0x93, 0xdf, 0x31, 0x5d, 0x0b, 0x69, 0x53, 0xa2, 0x59, 0x73, 0x95, 0xc3, 0xa2, 0x18, 0x96, 0x77, 0x09, - 0x28, 0x75, 0x67, 0x28, 0xe9, 0x5f, 0x59, 0x8d, 0x74, 0x21, 0xd7, 0xf9, 0x3e, 0x18, 0xc5, 0xe9, 0x59, 0x18, 0xbf, - 0xc3, 0xf9, 0xaa, 0xca, 0x67, 0x57, 0x83, 0x0c, 0x50, 0xac, 0xb8, 0x4b, 0x05, 0xc3, 0xf7, 0x06, 0x0c, 0xdf, 0x4b, - 0x3e, 0x5d, 0xf5, 0x67, 0xf3, 0x17, 0xe5, 0x00, 0xfe, 0xb0, 0xd0, 0x2c, 0x63, 0x22, 0x56, 0xcf, 0xb1, 0xc8, 0xc2, - 0x26, 0x25, 0x0b, 0x9b, 0x08, 0x67, 0x71, 0x28, 0xc7, 0xf9, 0x69, 0xf5, 0x28, 0xcb, 0x9c, 0xed, 0xa7, 0xea, 0xe0, - 0xff, 0xe4, 0xdf, 0xd8, 0xc7, 0xe0, 0x72, 0x3b, 0xde, 0x0e, 0x25, 0xab, 0x48, 0x90, 0x1f, 0x61, 0xd2, 0x81, 0x80, - 0xff, 0xab, 0x2b, 0x07, 0x95, 0x9c, 0xd2, 0x79, 0x40, 0x4e, 0x7f, 0x96, 0x8b, 0x74, 0xa2, 0xc6, 0xcc, 0xd5, 0x3d, - 0x23, 0xaa, 0x44, 0x57, 0x34, 0xc5, 0xda, 0xfd, 0xfa, 0x4d, 0xae, 0xf9, 0xa7, 0x28, 0x19, 0xf8, 0x60, 0xb6, 0xaa, - 0x3e, 0x7e, 0x56, 0x04, 0x3a, 0xd7, 0x78, 0xb9, 0x8e, 0xc1, 0x78, 0x51, 0x3e, 0x86, 0x4d, 0x4d, 0xe1, 0x48, 0xad, - 0x99, 0x2c, 0xc5, 0x80, 0x8c, 0x9c, 0x8c, 0xfd, 0x5c, 0x5d, 0xf9, 0xf3, 0x70, 0x34, 0xf4, 0x03, 0x4d, 0xb8, 0x18, - 0xa7, 0x03, 0x4c, 0x4b, 0x81, 0x3e, 0xfa, 0x4a, 0x13, 0xa8, 0xaf, 0x8e, 0x4d, 0x6e, 0x09, 0xbc, 0xfc, 0x6d, 0xd6, - 0xb8, 0xbd, 0x39, 0xde, 0xce, 0xa9, 0xa6, 0x06, 0x0b, 0x92, 0x2f, 0x5e, 0x64, 0x81, 0xd1, 0xf9, 0x15, 0x4b, 0x60, - 0x66, 0x5f, 0x42, 0x6d, 0x0f, 0x23, 0x1e, 0x0f, 0x6c, 0x06, 0xc5, 0x7e, 0x79, 0x5f, 0x9c, 0xae, 0x37, 0xd3, 0x06, - 0xda, 0xe9, 0x45, 0x62, 0xb3, 0x6a, 0x12, 0xe0, 0xa5, 0x2c, 0xcd, 0xa2, 0x11, 0x12, 0xe7, 0x77, 0xd0, 0x45, 0x8e, - 0x17, 0x19, 0xb7, 0xf5, 0xdc, 0xb9, 0x46, 0xbd, 0x67, 0x14, 0x9b, 0xdb, 0xa0, 0x0c, 0x8a, 0x63, 0xea, 0x0b, 0xca, - 0xab, 0xd9, 0xae, 0x32, 0x0f, 0xc1, 0x38, 0xbc, 0xed, 0x52, 0xd8, 0xb7, 0xa6, 0x68, 0x13, 0xb5, 0xcc, 0xd7, 0x85, - 0x4e, 0x1c, 0x3b, 0x54, 0x99, 0x1e, 0x1f, 0x40, 0x12, 0xcc, 0x35, 0x7b, 0xa5, 0xee, 0x86, 0x23, 0xec, 0x5b, 0xa1, - 0x06, 0xf5, 0x7f, 0x96, 0x09, 0x21, 0x55, 0x24, 0xe9, 0x65, 0xd5, 0x0f, 0xc6, 0x40, 0xbc, 0x63, 0x42, 0x4b, 0x48, - 0x17, 0x32, 0x0b, 0x9d, 0x2d, 0xfa, 0x1d, 0x40, 0x35, 0xd7, 0x4b, 0xf0, 0x13, 0x13, 0x8b, 0xa2, 0x40, 0x2a, 0x54, - 0xf4, 0x25, 0x13, 0x00, 0xf1, 0x0e, 0xfb, 0x92, 0xd4, 0xcc, 0x48, 0x6a, 0x7a, 0x06, 0xc6, 0xd7, 0x48, 0x49, 0x4e, - 0xc8, 0x20, 0x25, 0x92, 0x84, 0x9e, 0xda, 0x5c, 0x45, 0x42, 0xe6, 0x86, 0x96, 0xf7, 0xe7, 0xe4, 0x9e, 0x67, 0x35, - 0xb0, 0x1c, 0x1a, 0xc7, 0x05, 0xe2, 0xc0, 0xa4, 0x1d, 0xd9, 0xa0, 0x28, 0xaf, 0x65, 0xeb, 0xf4, 0x56, 0x27, 0xf5, - 0xf4, 0xb2, 0x02, 0x8d, 0x12, 0x67, 0xec, 0xce, 0xe1, 0x0f, 0xa8, 0xe1, 0x05, 0xca, 0xd6, 0x12, 0x7e, 0x6e, 0xee, - 0x46, 0x2d, 0x59, 0x79, 0xf5, 0x1d, 0x3f, 0x54, 0xe6, 0x05, 0xa6, 0x68, 0xb2, 0x44, 0xf3, 0x94, 0xc4, 0xa1, 0xcb, - 0x76, 0xc6, 0xb6, 0x7d, 0xaf, 0x12, 0x74, 0x14, 0x60, 0xdf, 0x01, 0xd3, 0x31, 0x56, 0x61, 0xde, 0xe6, 0x56, 0x77, - 0xfe, 0x54, 0xb0, 0xaf, 0xca, 0x21, 0x75, 0xf2, 0x60, 0x41, 0xe2, 0xdc, 0x9c, 0x6a, 0xf9, 0xeb, 0x8c, 0x67, 0x57, - 0x47, 0x1c, 0x53, 0x9d, 0x53, 0xbc, 0xed, 0x5b, 0x6d, 0x43, 0x95, 0xa6, 0xde, 0xcb, 0x48, 0x59, 0x29, 0xea, 0xb7, - 0x00, 0x17, 0xef, 0x08, 0x16, 0x14, 0x6d, 0x34, 0x1c, 0x31, 0xf2, 0xb4, 0xf0, 0xb5, 0xb7, 0x27, 0x79, 0x27, 0x42, - 0xff, 0x5a, 0x85, 0x69, 0x15, 0x2c, 0x60, 0xa9, 0x79, 0x23, 0xf5, 0x38, 0x3f, 0x59, 0xf4, 0xca, 0x60, 0x11, 0x86, - 0xef, 0xb2, 0xf5, 0x4b, 0x5d, 0x95, 0x34, 0xbb, 0x7e, 0xa9, 0xb5, 0xa0, 0x1f, 0x25, 0xfc, 0x30, 0x35, 0x4f, 0x79, - 0x7d, 0x39, 0x02, 0x8e, 0x56, 0x20, 0x78, 0xdf, 0x00, 0xdf, 0xff, 0x46, 0xa5, 0x0c, 0x7a, 0x18, 0x8b, 0x3d, 0x8a, - 0x53, 0xcd, 0xc4, 0xab, 0xf9, 0xbf, 0x59, 0x9a, 0xff, 0x1b, 0xe3, 0xce, 0x29, 0x9a, 0x46, 0xa3, 0x84, 0x0f, 0x34, - 0xeb, 0x74, 0x25, 0x01, 0x92, 0xde, 0x06, 0x8a, 0xfc, 0xeb, 0x53, 0x1f, 0x35, 0xae, 0xf9, 0x30, 0x4d, 0x44, 0x63, - 0x18, 0x4e, 0xa2, 0xf8, 0xca, 0x9f, 0x45, 0x8d, 0x49, 0x9a, 0xa4, 0xf9, 0x14, 0xe8, 0x9d, 0xe5, 0x57, 0x60, 0xf1, - 0x4c, 0x1a, 0xb3, 0x88, 0x3d, 0xe3, 0xf1, 0x39, 0x17, 0x51, 0x3f, 0x64, 0xf6, 0xc3, 0x0c, 0x58, 0x8d, 0xf5, 0x2a, - 0xcc, 0xb2, 0xf4, 0xc2, 0x66, 0x6f, 0xd3, 0x33, 0x98, 0x8d, 0xbd, 0xbe, 0xbc, 0x1a, 0xf1, 0x84, 0xbd, 0x3f, 0x9b, - 0x25, 0x62, 0xc6, 0xf2, 0x30, 0xc9, 0x1b, 0xa0, 0x59, 0x46, 0x43, 0x10, 0x2a, 0x71, 0x9a, 0x35, 0x30, 0x63, 0x7b, - 0xc2, 0xfd, 0x38, 0x1a, 0x8d, 0x85, 0x35, 0x08, 0xb3, 0x4f, 0x9d, 0x46, 0x63, 0x9a, 0x45, 0x93, 0x30, 0xbb, 0x6a, - 0x50, 0x0b, 0xff, 0xeb, 0xe6, 0x4e, 0xf8, 0x60, 0xb8, 0xdb, 0x11, 0x19, 0xf4, 0x8d, 0x70, 0x9b, 0x7c, 0x60, 0x64, - 0xd6, 0xce, 0x5e, 0x73, 0x92, 0x6f, 0xc8, 0x40, 0x5e, 0x98, 0x88, 0xe2, 0x94, 0xbd, 0x41, 0xb8, 0xbd, 0x33, 0x91, - 0x30, 0xb0, 0x7c, 0x45, 0x9a, 0x80, 0x74, 0xc8, 0x72, 0x18, 0x60, 0x9a, 0x46, 0x89, 0xe0, 0x59, 0xe7, 0x2c, 0xcd, - 0x60, 0x97, 0x1a, 0x59, 0x38, 0x88, 0x66, 0xb9, 0xbf, 0x3b, 0xbd, 0xec, 0xa0, 0x66, 0x31, 0xca, 0xd2, 0x59, 0x32, - 0x50, 0x73, 0x45, 0x09, 0x1c, 0xbc, 0x48, 0x98, 0x15, 0xf4, 0x12, 0x13, 0x80, 0x2f, 0xe1, 0x61, 0xd6, 0x18, 0x61, - 0x67, 0x34, 0x8b, 0x9a, 0x03, 0x3e, 0x62, 0xd9, 0xe8, 0x2c, 0x74, 0x5a, 0xed, 0xfb, 0x4c, 0xff, 0xf3, 0xf6, 0x5c, - 0xd0, 0x8e, 0x57, 0x16, 0xb7, 0x9a, 0xcd, 0x7f, 0x72, 0x3b, 0x0b, 0xb3, 0x10, 0x40, 0x7e, 0x6b, 0x7a, 0x69, 0xe5, - 0x29, 0x66, 0xb4, 0xad, 0xea, 0xd9, 0x99, 0x82, 0x95, 0x19, 0x25, 0x23, 0xbf, 0x3d, 0xbd, 0x2c, 0x70, 0x75, 0xbe, - 0x4c, 0x31, 0x55, 0x8b, 0x54, 0x4f, 0xf3, 0xdf, 0x0b, 0xf1, 0xfe, 0x6a, 0x88, 0xdb, 0x1a, 0xe2, 0x0a, 0xeb, 0x8d, - 0x01, 0x1c, 0x34, 0x42, 0x7f, 0x2b, 0x97, 0x80, 0x8c, 0xc1, 0x64, 0xce, 0x34, 0x1c, 0xf4, 0xf0, 0xbb, 0xc1, 0x68, - 0xaf, 0x06, 0x63, 0xff, 0x73, 0x60, 0x64, 0xc9, 0x60, 0x5e, 0xdf, 0xd7, 0x16, 0x98, 0xf2, 0x9d, 0x31, 0x47, 0x7a, - 0xf2, 0xdb, 0xf8, 0xfd, 0x22, 0x1a, 0x88, 0xb1, 0xfc, 0x4a, 0xe4, 0x7c, 0x21, 0xeb, 0xf6, 0x9a, 0x4d, 0xf9, 0x9c, - 0x83, 0x70, 0xf4, 0x5b, 0x1e, 0x36, 0x00, 0x22, 0xfa, 0xa9, 0xbc, 0xcb, 0x5b, 0xe7, 0x9e, 0xec, 0x1b, 0xf3, 0x92, - 0xaf, 0x91, 0xa2, 0x58, 0x5d, 0x89, 0x66, 0x99, 0x96, 0x95, 0x52, 0xf8, 0xa0, 0xdb, 0x8e, 0xb8, 0x63, 0x10, 0x75, - 0xcb, 0x4b, 0x9c, 0x51, 0xef, 0x1b, 0x99, 0x77, 0xe1, 0x63, 0xa4, 0xc3, 0x48, 0x35, 0x04, 0x96, 0xd3, 0x0d, 0x9a, - 0x9d, 0xac, 0xd1, 0x70, 0x81, 0xb3, 0x24, 0xc7, 0x99, 0x4a, 0xce, 0x73, 0xa2, 0x5e, 0x4a, 0xc6, 0x76, 0xee, 0xfa, - 0x29, 0xde, 0x34, 0x05, 0x2e, 0x5a, 0x25, 0x64, 0xd0, 0x6d, 0x8d, 0x9f, 0x84, 0x6a, 0xc0, 0x72, 0x83, 0x93, 0xa7, - 0xfa, 0xd5, 0x2e, 0x89, 0xe6, 0x15, 0x71, 0xda, 0x27, 0xcc, 0x79, 0xd3, 0x50, 0x8c, 0xd1, 0x4b, 0x51, 0x8a, 0x9f, - 0x2a, 0x85, 0xc9, 0xde, 0xb6, 0xdd, 0x5e, 0x52, 0xe6, 0xb7, 0x61, 0x1e, 0x5f, 0x52, 0xe0, 0x28, 0x57, 0x22, 0x20, - 0x8b, 0xa9, 0x1c, 0xff, 0xbd, 0x30, 0x24, 0x75, 0x02, 0x9a, 0x46, 0x3f, 0x9e, 0x81, 0xa8, 0xa0, 0x11, 0x2a, 0x71, - 0xfe, 0x37, 0xb3, 0x15, 0x75, 0xc1, 0xd1, 0x29, 0x9b, 0x07, 0x1b, 0xe2, 0x1b, 0x54, 0xca, 0xe7, 0x06, 0x3d, 0x57, - 0x7d, 0xf5, 0x4b, 0x25, 0x80, 0xab, 0x63, 0x4f, 0x6f, 0x96, 0x44, 0xc0, 0x41, 0x3f, 0x44, 0x03, 0xe3, 0xde, 0x2e, - 0x4f, 0xfa, 0xe9, 0x80, 0xbf, 0x7f, 0xfb, 0x1c, 0xb3, 0xdd, 0xd3, 0x04, 0x49, 0x2c, 0x91, 0xfe, 0x2e, 0x96, 0x03, - 0x7a, 0x07, 0xfc, 0x1c, 0x16, 0xd2, 0x3b, 0xdd, 0x9c, 0xaf, 0x6c, 0x28, 0xab, 0xdd, 0x62, 0xfb, 0x94, 0x92, 0xfe, - 0x08, 0x4a, 0x68, 0x7b, 0x25, 0x8a, 0xed, 0xcd, 0x39, 0x54, 0xa7, 0x93, 0x30, 0x4a, 0xf0, 0x7b, 0x5e, 0x6c, 0xce, - 0x23, 0xfc, 0x02, 0x8c, 0xa6, 0xa8, 0x12, 0x45, 0x4b, 0x88, 0x8c, 0x25, 0x28, 0xdc, 0xb5, 0x5c, 0xef, 0x23, 0x30, - 0x1e, 0x2a, 0xba, 0x69, 0x64, 0xae, 0x47, 0x45, 0x24, 0x3f, 0x0f, 0xa4, 0xc1, 0xac, 0xcd, 0xe5, 0xe1, 0x6d, 0xcd, - 0x65, 0xf8, 0x1a, 0x51, 0x5a, 0xbc, 0x0e, 0xe7, 0x80, 0x45, 0xf9, 0xa1, 0x2f, 0xef, 0xa1, 0xe6, 0xd5, 0xad, 0x8b, - 0x90, 0x10, 0x2b, 0x2d, 0x60, 0xd0, 0x30, 0xd0, 0xd8, 0xe7, 0xeb, 0x2f, 0x4a, 0x26, 0x37, 0x19, 0x7f, 0x25, 0x55, - 0xe5, 0xe9, 0x2c, 0xeb, 0x63, 0xac, 0x57, 0xa9, 0x14, 0xcb, 0x5e, 0x31, 0x9b, 0xf4, 0x37, 0x9b, 0x09, 0x23, 0xc9, - 0x56, 0xb0, 0xc8, 0x7c, 0x67, 0x07, 0xa7, 0x78, 0xa2, 0xbc, 0x0b, 0xa3, 0xf4, 0x07, 0xbd, 0x24, 0x54, 0x88, 0x06, - 0x94, 0x2f, 0x0a, 0xe2, 0xb6, 0x9b, 0x55, 0x38, 0x07, 0x01, 0x17, 0x79, 0x40, 0x0c, 0x28, 0xf5, 0x51, 0xb1, 0x68, - 0xb4, 0x30, 0x32, 0x04, 0x05, 0xa5, 0x86, 0x14, 0x29, 0x3c, 0x5f, 0x5f, 0x03, 0x19, 0xca, 0xb6, 0xd2, 0xa9, 0x82, - 0x3a, 0x58, 0xc4, 0x64, 0x25, 0xe8, 0x69, 0xe5, 0x90, 0x3e, 0x36, 0x2a, 0x3a, 0x29, 0xa1, 0x4f, 0x22, 0x2b, 0xd0, - 0xe8, 0x7c, 0x28, 0x55, 0x84, 0x14, 0x74, 0x30, 0xa3, 0xba, 0xbc, 0xc0, 0x5f, 0xc3, 0x77, 0x73, 0x61, 0x5b, 0xa4, - 0x3d, 0x95, 0x2e, 0x96, 0x82, 0x74, 0x12, 0x0e, 0x68, 0x76, 0x31, 0xb0, 0x8b, 0x31, 0x51, 0xed, 0x41, 0x4c, 0x1f, - 0xbd, 0x46, 0xcb, 0x6f, 0x95, 0x9e, 0x90, 0xda, 0xbd, 0x6a, 0x99, 0x67, 0xa6, 0xee, 0xe6, 0x22, 0xb8, 0xac, 0xfc, - 0x2e, 0xd7, 0x53, 0x3d, 0x97, 0xcb, 0x62, 0x8a, 0x73, 0x49, 0xa9, 0xef, 0xd4, 0x80, 0xa0, 0xb8, 0xdb, 0x9a, 0xa9, - 0xdc, 0xa2, 0x5a, 0x77, 0x79, 0x8a, 0x4f, 0xa5, 0xb6, 0xf3, 0xc1, 0x20, 0xe3, 0xd3, 0x48, 0xfb, 0xeb, 0xea, 0x04, - 0x56, 0x28, 0x8c, 0x18, 0x2c, 0x60, 0x55, 0x33, 0x09, 0xcb, 0x55, 0x90, 0xac, 0xa4, 0x52, 0x4f, 0x3e, 0x72, 0xa9, - 0x6b, 0xad, 0x6e, 0x42, 0x59, 0x8f, 0xab, 0x00, 0x43, 0x0f, 0x40, 0x2e, 0xf4, 0x12, 0x90, 0x99, 0x0c, 0x39, 0xbd, - 0x98, 0x46, 0xb2, 0x16, 0x36, 0x97, 0x6a, 0xbc, 0x6f, 0xbf, 0x79, 0x7d, 0xf4, 0xce, 0x66, 0xf8, 0x3e, 0x33, 0x30, - 0x83, 0xfd, 0xb9, 0xad, 0x92, 0x09, 0x1b, 0x18, 0x98, 0xb6, 0x7d, 0x3b, 0x9c, 0xe2, 0xdd, 0x6c, 0xe2, 0x9e, 0xdb, - 0x97, 0x8d, 0x8b, 0x8b, 0x8b, 0x06, 0x5e, 0x1d, 0x6b, 0xcc, 0xb2, 0x58, 0xf2, 0x95, 0x81, 0x0d, 0xda, 0x99, 0x27, - 0xc6, 0x3c, 0x29, 0xdf, 0x78, 0x94, 0xc6, 0x1c, 0x38, 0xee, 0x48, 0x5e, 0x7b, 0x5d, 0xf4, 0x43, 0xf4, 0x4f, 0x0f, - 0xe8, 0x4d, 0x5e, 0xdd, 0x03, 0x21, 0xdf, 0xa1, 0x26, 0x32, 0xfc, 0xda, 0xc5, 0x28, 0xd5, 0xc1, 0x36, 0x7c, 0xc1, - 0x87, 0x23, 0x3c, 0x36, 0xf4, 0xb4, 0x39, 0x5f, 0x22, 0xb2, 0x1e, 0x0e, 0x31, 0xee, 0xca, 0xa5, 0xe5, 0xd4, 0xea, - 0xd4, 0xef, 0x9f, 0x9e, 0x16, 0xf0, 0x15, 0xc6, 0xda, 0xd6, 0xe3, 0x9e, 0xa5, 0x83, 0x2b, 0xdd, 0xbf, 0x24, 0x3c, - 0x7c, 0xa3, 0x13, 0x18, 0xf3, 0x38, 0x04, 0xce, 0x3b, 0xe8, 0x12, 0xce, 0x14, 0xaf, 0x3c, 0xae, 0x1e, 0x8a, 0x13, - 0x0b, 0x39, 0x63, 0x81, 0x25, 0x48, 0x97, 0x38, 0xf8, 0xa0, 0xec, 0x40, 0xc7, 0x5a, 0x16, 0xad, 0x03, 0x50, 0x36, - 0xac, 0x8e, 0x8b, 0xf4, 0x67, 0x57, 0x64, 0xa1, 0x21, 0x1e, 0x98, 0xc0, 0xc3, 0xae, 0xc1, 0x27, 0x01, 0x0e, 0x9f, - 0x84, 0xa6, 0x53, 0xf3, 0xed, 0x32, 0xf2, 0xbd, 0x0f, 0x25, 0x32, 0x8f, 0x13, 0x01, 0xba, 0x1f, 0x7b, 0x7d, 0x4a, - 0x4d, 0xb5, 0x3a, 0x80, 0x7a, 0x2a, 0xaa, 0x4d, 0x4d, 0xad, 0xf7, 0x81, 0xee, 0x15, 0x87, 0xd3, 0x9c, 0xfb, 0xfa, - 0x8b, 0xd2, 0x0c, 0x50, 0xc1, 0x58, 0x56, 0xc5, 0x54, 0x82, 0xd3, 0x21, 0x2a, 0x6c, 0xcb, 0x7a, 0x22, 0x70, 0x47, - 0xa7, 0xd1, 0xe8, 0x37, 0xce, 0x46, 0x6e, 0x21, 0xc6, 0x73, 0x53, 0xaf, 0xb8, 0x07, 0x7a, 0x05, 0x66, 0xa3, 0x36, - 0xc0, 0xea, 0x1e, 0x25, 0x7e, 0xcc, 0x87, 0xa2, 0x10, 0x78, 0x4d, 0x70, 0xae, 0x15, 0x39, 0xaf, 0xbd, 0x07, 0xba, - 0x86, 0xe5, 0xe1, 0xdf, 0x9b, 0x27, 0x86, 0x8e, 0x7e, 0x02, 0xda, 0x01, 0x65, 0x3d, 0xe3, 0x9d, 0x0d, 0x00, 0xd7, - 0x7c, 0x9e, 0x1b, 0x13, 0xf5, 0x39, 0x2a, 0xb9, 0x85, 0xc8, 0xe0, 0x88, 0x31, 0x91, 0x99, 0xed, 0xe0, 0xf4, 0x2d, - 0xad, 0x60, 0x59, 0xd7, 0xda, 0x71, 0x8b, 0x9c, 0x4c, 0x93, 0xe5, 0xc6, 0x5a, 0x61, 0xad, 0x3f, 0x2d, 0xa1, 0xcf, - 0x50, 0xad, 0x0b, 0xe9, 0xda, 0x9f, 0xcb, 0x1e, 0xb7, 0x41, 0x66, 0x4d, 0xe9, 0x67, 0x66, 0x0f, 0xb7, 0x88, 0x92, - 0xe9, 0x4c, 0x1c, 0x53, 0x58, 0x21, 0xc3, 0x0b, 0x2a, 0xc0, 0xb1, 0xaa, 0x12, 0xc4, 0xc1, 0xc9, 0x5c, 0x02, 0xd3, - 0x0f, 0xe3, 0xbe, 0x83, 0x10, 0x59, 0x0d, 0x6b, 0x1f, 0xd0, 0xeb, 0x76, 0x26, 0x51, 0xd2, 0x90, 0x75, 0x7b, 0x86, - 0x62, 0xe8, 0xdd, 0xc7, 0xa7, 0xc2, 0xa3, 0xd1, 0x18, 0x65, 0x0f, 0xaf, 0xc0, 0xe5, 0x29, 0x18, 0x5f, 0x1d, 0xe0, - 0xd0, 0xc7, 0x2f, 0x1d, 0xf7, 0x84, 0x3d, 0x37, 0xde, 0x8f, 0x63, 0xeb, 0x93, 0x64, 0xb3, 0xb6, 0xbb, 0xa6, 0x89, - 0x79, 0x16, 0xa8, 0xd9, 0xf3, 0x00, 0x1b, 0x3e, 0x72, 0x6c, 0x9e, 0x4f, 0x1b, 0x92, 0xe5, 0x35, 0x88, 0x64, 0x6d, - 0xec, 0xea, 0x2a, 0x5f, 0x39, 0xe7, 0x73, 0xe2, 0x66, 0xea, 0x92, 0x8c, 0x74, 0xe7, 0x9c, 0x94, 0x97, 0xaa, 0xd4, - 0xb3, 0x79, 0x8d, 0xca, 0xad, 0xb1, 0x9b, 0xd3, 0x87, 0x75, 0xd6, 0x88, 0xca, 0x45, 0xf9, 0x12, 0x41, 0x90, 0xdf, - 0x38, 0xe1, 0xa9, 0xd6, 0x48, 0xcc, 0xb7, 0xae, 0xc0, 0xa8, 0xc0, 0xf2, 0xd5, 0x39, 0x7d, 0x44, 0x4a, 0xbd, 0xf1, - 0xe6, 0xc2, 0x0d, 0xa1, 0xc3, 0x75, 0x52, 0x44, 0x47, 0x98, 0x70, 0x50, 0x4b, 0x4c, 0xef, 0x54, 0xac, 0x4d, 0x9a, - 0x04, 0x16, 0x2d, 0x28, 0xb0, 0x41, 0x47, 0xb7, 0xad, 0xbf, 0xf6, 0x81, 0x7f, 0x7e, 0x0a, 0xec, 0xcd, 0xb9, 0xe3, - 0x2e, 0xdf, 0x3b, 0x25, 0xae, 0xa0, 0xf9, 0xbc, 0x5b, 0x0f, 0x65, 0x64, 0x9e, 0xc1, 0xc2, 0xe5, 0x8b, 0x89, 0xec, - 0x2e, 0xea, 0x4d, 0x07, 0xdb, 0x72, 0x1e, 0x60, 0x0e, 0x1f, 0xaa, 0xf7, 0x8d, 0x55, 0x50, 0x20, 0x9a, 0x65, 0xb9, - 0x45, 0x44, 0x15, 0xd8, 0x9f, 0xa5, 0x34, 0xdb, 0x92, 0x4c, 0x0d, 0xe1, 0x14, 0x8a, 0xbf, 0x01, 0xec, 0x65, 0x19, - 0x2f, 0x7d, 0x4a, 0x94, 0x14, 0x13, 0xd8, 0x38, 0x17, 0x3a, 0x12, 0x80, 0x5f, 0x8a, 0x30, 0x8a, 0x65, 0x97, 0x8e, - 0x76, 0x81, 0x2c, 0xac, 0x08, 0x34, 0xf7, 0xfa, 0x5a, 0xa2, 0x3a, 0x06, 0x69, 0x65, 0x07, 0xdb, 0x15, 0xdc, 0xb4, - 0x32, 0x3a, 0x93, 0x66, 0x70, 0xb6, 0x5a, 0xa1, 0xac, 0x03, 0xdc, 0xd2, 0xb5, 0x2d, 0x04, 0x30, 0x55, 0x00, 0x62, - 0xda, 0x80, 0xbc, 0x96, 0xe4, 0xc4, 0x41, 0xea, 0x09, 0xd0, 0x17, 0xb9, 0x58, 0x40, 0x6c, 0x2c, 0xb3, 0x84, 0x3b, - 0x3a, 0x45, 0x60, 0x09, 0xda, 0xb0, 0x0e, 0x2d, 0x2a, 0xd1, 0x45, 0x0f, 0xf5, 0xe0, 0x60, 0xa5, 0x3a, 0x3d, 0x76, - 0x51, 0xde, 0xd2, 0xe6, 0x48, 0x09, 0x93, 0x92, 0x84, 0x91, 0x9c, 0xc0, 0xa2, 0xb9, 0x08, 0x44, 0xc0, 0x68, 0x4f, - 0x42, 0xce, 0x07, 0x12, 0xe6, 0x20, 0xa3, 0x5e, 0x29, 0x6c, 0xa9, 0x6c, 0x2d, 0x45, 0x80, 0x6c, 0x84, 0x48, 0xa0, - 0x73, 0x5a, 0xe1, 0x00, 0x33, 0xcb, 0x4d, 0x3c, 0x0c, 0xa2, 0xf3, 0x92, 0xd8, 0xe8, 0x02, 0x5b, 0xf7, 0x00, 0xe8, - 0x9c, 0xc7, 0x30, 0x66, 0x76, 0x7d, 0xdd, 0x84, 0xa1, 0xe4, 0xa3, 0x75, 0x40, 0x7c, 0x43, 0xbe, 0x74, 0x94, 0xb6, - 0x18, 0x6f, 0x85, 0x62, 0xbe, 0xad, 0x4e, 0x34, 0xf3, 0xd5, 0x00, 0x00, 0x23, 0xa5, 0xb8, 0x50, 0xa3, 0x52, 0x8f, - 0x82, 0xd2, 0x68, 0xb0, 0x5c, 0x06, 0x6a, 0xee, 0x14, 0x4b, 0xc7, 0xd7, 0xd7, 0x2d, 0x78, 0x04, 0x96, 0x83, 0x4f, - 0x30, 0x33, 0x5d, 0xb8, 0x84, 0x47, 0x30, 0xa4, 0x80, 0x6c, 0xa1, 0x26, 0xbc, 0xa4, 0x05, 0xeb, 0x9a, 0xf0, 0x12, - 0x98, 0x95, 0xac, 0xf2, 0x4a, 0xfc, 0xe4, 0x48, 0x71, 0xd5, 0x8e, 0xc6, 0x6a, 0x47, 0x07, 0x6c, 0x26, 0xaf, 0x92, - 0x05, 0xce, 0x20, 0x88, 0x57, 0xef, 0xe8, 0x40, 0xef, 0xe8, 0x6c, 0xcd, 0x8e, 0xce, 0x6e, 0xd8, 0xd1, 0x50, 0xed, - 0x9e, 0x55, 0xe2, 0x0e, 0xe0, 0x04, 0x5e, 0x5a, 0x62, 0xef, 0x60, 0x1b, 0xf0, 0x8c, 0xbb, 0x81, 0xda, 0xa1, 0x88, - 0x26, 0x7c, 0x35, 0x51, 0xd6, 0x51, 0xcc, 0xbf, 0x08, 0x93, 0x15, 0x16, 0xb2, 0x3a, 0x16, 0x4c, 0xba, 0x2e, 0xa3, - 0x9e, 0x7f, 0x26, 0x65, 0x47, 0x88, 0x87, 0x1c, 0xf1, 0x30, 0xd6, 0x2f, 0x21, 0x75, 0x6c, 0xd0, 0x08, 0x6d, 0xcb, - 0xd6, 0x64, 0x0d, 0x2b, 0x47, 0x19, 0x41, 0xeb, 0xbb, 0x15, 0x2d, 0x62, 0x6b, 0x20, 0xc5, 0xb5, 0x34, 0x87, 0x09, - 0x0a, 0x17, 0x20, 0x39, 0x81, 0xea, 0xa8, 0xe9, 0x17, 0xa1, 0x0a, 0xc8, 0x4a, 0xa5, 0xbb, 0xad, 0xa5, 0xb5, 0xaa, - 0xde, 0xa4, 0xb8, 0xf6, 0xde, 0x9e, 0x6c, 0x31, 0x0d, 0x05, 0x48, 0xb9, 0x44, 0x51, 0xae, 0x6d, 0xff, 0x7f, 0x41, - 0x85, 0x2b, 0xf8, 0x4a, 0xa8, 0x37, 0x40, 0x13, 0xa0, 0xd2, 0xf3, 0x15, 0xcf, 0x97, 0xe2, 0x69, 0xa3, 0x52, 0x70, - 0xaf, 0x5c, 0xd3, 0xd6, 0x90, 0x45, 0x68, 0xfa, 0x80, 0xc1, 0x3c, 0xf8, 0x40, 0x0c, 0x1a, 0x54, 0x53, 0xa5, 0xb0, - 0x2e, 0x88, 0xbb, 0xaa, 0x03, 0xb3, 0x7f, 0x99, 0xb5, 0xef, 0xef, 0x1e, 0x02, 0x05, 0x10, 0x8f, 0x4f, 0x87, 0x43, - 0x20, 0x04, 0xeb, 0x76, 0xdd, 0x5a, 0xbb, 0xbf, 0xcc, 0x9e, 0x3e, 0x69, 0x3e, 0x2d, 0x3b, 0x27, 0x48, 0x44, 0x2a, - 0xc3, 0x42, 0x8b, 0x2a, 0x03, 0x5e, 0xbd, 0xa2, 0x61, 0x98, 0xac, 0x5f, 0xce, 0xb1, 0xb9, 0x9c, 0x7c, 0xca, 0xf9, - 0x00, 0x89, 0x93, 0x2d, 0x95, 0x7e, 0x88, 0xf9, 0x39, 0xd7, 0x2f, 0x7f, 0x5c, 0x31, 0xd9, 0x8a, 0x1e, 0x7d, 0xd0, - 0xc6, 0x84, 0x4a, 0x35, 0x51, 0xac, 0xd6, 0x58, 0xd2, 0x29, 0xad, 0xc1, 0x34, 0x21, 0xae, 0xa4, 0x9c, 0xab, 0x4b, - 0xaf, 0xe2, 0x94, 0xd9, 0x06, 0x00, 0x6b, 0x21, 0xeb, 0xad, 0x29, 0xf7, 0x9b, 0xac, 0xb9, 0x0e, 0x36, 0xd6, 0x72, - 0xc1, 0x0c, 0x39, 0xd1, 0x78, 0x22, 0x6f, 0x71, 0xed, 0x8d, 0x1d, 0x6b, 0xf1, 0xf5, 0x59, 0x0c, 0x9c, 0x65, 0x38, - 0x58, 0xc2, 0xf3, 0x7c, 0x2d, 0x02, 0xca, 0x4d, 0x64, 0x76, 0xd5, 0xda, 0x5e, 0x33, 0x0a, 0x2c, 0x02, 0x4f, 0x18, - 0x01, 0x5c, 0xc6, 0xac, 0x55, 0x2b, 0x3e, 0x1c, 0x82, 0x40, 0xd3, 0xce, 0x76, 0x8c, 0x3e, 0x0e, 0xa3, 0x58, 0x60, - 0x10, 0x8e, 0xa2, 0x63, 0xf6, 0x2b, 0x20, 0x78, 0xdb, 0xd5, 0xf9, 0xb4, 0x0a, 0x7e, 0x25, 0xff, 0x57, 0xc3, 0x23, - 0x47, 0xac, 0xc3, 0xa2, 0x66, 0xb9, 0xbe, 0xd6, 0xbe, 0xa0, 0x5a, 0x79, 0x1d, 0x91, 0x29, 0x39, 0x7b, 0xd6, 0x1d, - 0xa0, 0xdb, 0x1d, 0x93, 0x79, 0xeb, 0xe9, 0x5e, 0xab, 0x59, 0x00, 0x34, 0x38, 0xdc, 0x6d, 0x4f, 0x09, 0xf5, 0xda, - 0xc1, 0x5e, 0xb3, 0xe4, 0x4b, 0xfa, 0xb5, 0x5b, 0x0f, 0x5a, 0xd0, 0x89, 0x5e, 0xe4, 0x00, 0x34, 0xa7, 0x57, 0xd2, - 0x47, 0xf7, 0xf3, 0x1f, 0x5e, 0x4a, 0x7d, 0xf0, 0xdb, 0xc1, 0x73, 0xaf, 0xd5, 0x84, 0x2e, 0xb9, 0x48, 0xa7, 0x5f, - 0xb0, 0x84, 0x1d, 0xe8, 0xd2, 0x8f, 0xd3, 0x9c, 0x9b, 0x6b, 0x90, 0xea, 0xec, 0x1f, 0x5f, 0x84, 0x84, 0x68, 0x0a, - 0x4c, 0x36, 0xb7, 0xcc, 0xf1, 0x15, 0x29, 0x7d, 0x86, 0x61, 0xae, 0xa4, 0xb8, 0x9c, 0x0b, 0xc2, 0x8b, 0x7c, 0xc7, - 0x82, 0x49, 0x55, 0xb2, 0x6c, 0x89, 0xd8, 0x48, 0x04, 0x94, 0x8c, 0x4d, 0x6a, 0x57, 0x9f, 0x9d, 0x79, 0xc5, 0xd1, - 0x93, 0x13, 0xcb, 0xa8, 0xfc, 0xf2, 0x04, 0xb5, 0x12, 0x10, 0x7e, 0x1f, 0x56, 0x94, 0x86, 0x97, 0x2b, 0x4a, 0x51, - 0x65, 0x2b, 0xa1, 0x53, 0xef, 0xff, 0xf9, 0x3c, 0xd6, 0x2b, 0xc5, 0xc7, 0x04, 0x71, 0x40, 0xce, 0xcd, 0xcf, 0x40, - 0x6a, 0x6c, 0x03, 0x8d, 0xf0, 0xfb, 0xa7, 0xc3, 0x92, 0x2f, 0x99, 0xae, 0x1c, 0xe5, 0x8f, 0xad, 0x10, 0x4b, 0x1b, - 0x18, 0x41, 0x88, 0xbf, 0x68, 0xad, 0xa0, 0xd7, 0x7c, 0x76, 0xdb, 0x0d, 0xad, 0xea, 0x0f, 0x6c, 0xbd, 0x7a, 0x8f, - 0xc0, 0xe2, 0xde, 0xaf, 0x28, 0x56, 0x8a, 0x4f, 0xb9, 0xff, 0x60, 0x9a, 0x4e, 0x2a, 0x12, 0x58, 0x06, 0x93, 0x34, - 0x1e, 0x4c, 0x27, 0x33, 0x07, 0x91, 0xaa, 0xcf, 0x07, 0xbc, 0x24, 0x8b, 0xef, 0x21, 0x99, 0x65, 0x1c, 0xb8, 0xe9, - 0xc5, 0xe2, 0x8b, 0xd5, 0xd6, 0x37, 0x1e, 0x83, 0xc0, 0x30, 0x6e, 0xbe, 0xf1, 0xa0, 0xdc, 0x84, 0x1b, 0x27, 0x28, - 0xfe, 0xf5, 0x5f, 0x3c, 0xef, 0x5f, 0xff, 0xe5, 0xb3, 0x4d, 0x71, 0x78, 0x90, 0xc8, 0xa2, 0x1a, 0x76, 0xfd, 0xe9, - 0x5a, 0x3d, 0x53, 0x1d, 0xe7, 0xab, 0xdb, 0x2c, 0x6d, 0x02, 0xd6, 0x2f, 0x6d, 0xc1, 0x52, 0xa1, 0x3c, 0x7d, 0xd6, - 0xef, 0x01, 0x0c, 0xd7, 0xf5, 0x59, 0xc8, 0xb0, 0xd1, 0x1f, 0x02, 0xed, 0xd4, 0xf5, 0x6f, 0xb5, 0x23, 0xbf, 0x1f, - 0xc3, 0x9f, 0x5b, 0xc3, 0x1f, 0x04, 0x5f, 0xf9, 0x27, 0xfa, 0xa7, 0xa7, 0x65, 0x8a, 0xa3, 0xd9, 0x15, 0x5f, 0xa0, - 0xd0, 0x5b, 0x2a, 0x51, 0x8a, 0x87, 0xdf, 0x74, 0xbb, 0x74, 0x41, 0x13, 0xba, 0xbf, 0xc4, 0xb7, 0x26, 0x1d, 0x9c, - 0x65, 0xda, 0xc1, 0x7b, 0x83, 0x70, 0xc0, 0x21, 0xea, 0xab, 0xa2, 0x41, 0x97, 0x24, 0x03, 0x96, 0xa2, 0xb9, 0x81, - 0x60, 0x32, 0x30, 0x98, 0xa4, 0x71, 0x79, 0x28, 0xdd, 0x30, 0xfe, 0x22, 0x69, 0x2b, 0xf7, 0x4c, 0x0d, 0xe9, 0xcc, - 0x7a, 0x47, 0xf8, 0xa2, 0xc6, 0xbc, 0xb2, 0xee, 0xc9, 0xd5, 0x85, 0x76, 0x44, 0xc9, 0x7e, 0x80, 0x53, 0x9c, 0xdf, - 0x8e, 0xf1, 0xad, 0x17, 0xa8, 0xd7, 0xd6, 0xf5, 0x3f, 0x5a, 0x25, 0xb8, 0x6e, 0x5c, 0xd7, 0xf4, 0x01, 0x4a, 0xf3, - 0x88, 0xf8, 0x9a, 0x48, 0x74, 0xce, 0x3f, 0x1b, 0x89, 0x8e, 0x6f, 0x15, 0x89, 0xce, 0xf9, 0x9f, 0x1d, 0x89, 0x8e, - 0xb8, 0x11, 0x89, 0x46, 0x12, 0xfc, 0xf5, 0x56, 0x01, 0x4d, 0x1d, 0x7e, 0x4a, 0x2f, 0xf2, 0xa0, 0xa5, 0x8c, 0x80, - 0x38, 0x1d, 0x61, 0x34, 0xf3, 0x1f, 0x1f, 0x9c, 0x84, 0x89, 0xcc, 0xd0, 0x24, 0xbe, 0xf4, 0x17, 0x63, 0x91, 0x80, - 0x93, 0xb9, 0xfd, 0xcb, 0x65, 0xeb, 0xd1, 0x71, 0xab, 0xb3, 0xd3, 0x9a, 0x80, 0x8d, 0x8e, 0x52, 0x97, 0x0a, 0x9a, - 0x9d, 0x9d, 0x1d, 0x2c, 0xb8, 0x30, 0x0a, 0xda, 0x58, 0x10, 0x19, 0x05, 0x7b, 0x58, 0xd0, 0x37, 0x0a, 0xee, 0x61, - 0xc1, 0xc0, 0x28, 0xb8, 0x8f, 0x05, 0xe7, 0x76, 0x71, 0x1c, 0x95, 0xe1, 0xf6, 0xfb, 0x2e, 0xbd, 0x1f, 0x64, 0x23, - 0xab, 0xdf, 0x8d, 0x18, 0x07, 0xba, 0xc9, 0xfd, 0xf2, 0x5e, 0x55, 0x63, 0x57, 0xbf, 0x06, 0xe4, 0xf4, 0x2b, 0x38, - 0x48, 0x71, 0x80, 0xd7, 0x1c, 0x19, 0x1a, 0xe5, 0xb2, 0xe5, 0x8e, 0xae, 0x86, 0x49, 0xdc, 0x72, 0x82, 0xb6, 0x8e, - 0x4a, 0x43, 0x21, 0x9b, 0x95, 0x8d, 0xf7, 0xb6, 0x06, 0x6a, 0x58, 0x7c, 0xc3, 0x46, 0xf5, 0x7a, 0x9b, 0x1d, 0x97, - 0xc9, 0x37, 0x8a, 0x3f, 0x26, 0xf9, 0x08, 0x06, 0xdf, 0x3b, 0x50, 0x03, 0xf4, 0xef, 0xad, 0xe8, 0x09, 0x2c, 0x8a, - 0xdb, 0x77, 0xc6, 0xd5, 0x3b, 0xe1, 0x9e, 0xb2, 0x87, 0xd5, 0x1b, 0x95, 0xde, 0x89, 0x40, 0xbe, 0xa2, 0x02, 0xe8, - 0x92, 0x0c, 0xbd, 0x11, 0x13, 0xe1, 0xc8, 0xc7, 0xc0, 0x25, 0xfa, 0x4c, 0xfd, 0x87, 0x41, 0x10, 0x34, 0x7b, 0x33, - 0xff, 0x29, 0xbb, 0x18, 0xf3, 0xc4, 0x3f, 0x2f, 0x3a, 0x25, 0x01, 0xc8, 0xb8, 0xe9, 0x3b, 0x51, 0xbe, 0x88, 0x8f, - 0xa8, 0xa2, 0xaa, 0x96, 0x70, 0x36, 0x4a, 0xea, 0x59, 0x13, 0x6a, 0x33, 0x7c, 0x32, 0x43, 0x90, 0x5a, 0x8d, 0x4b, - 0xbb, 0xbb, 0x3a, 0xfc, 0x86, 0xab, 0x2b, 0xc3, 0x6f, 0x2f, 0x10, 0xd8, 0xf2, 0xe9, 0x5d, 0x38, 0x2a, 0xbf, 0xbf, - 0x04, 0xcd, 0x3a, 0x1c, 0xa9, 0x96, 0xeb, 0xc3, 0x6d, 0x04, 0xa2, 0x19, 0x6a, 0xd3, 0x40, 0x60, 0x4c, 0x0c, 0x31, - 0x82, 0x3e, 0x0d, 0x15, 0x22, 0xc3, 0xa5, 0xd7, 0xa3, 0x6b, 0x84, 0xab, 0x7a, 0x11, 0xa0, 0xad, 0x2a, 0x38, 0x00, - 0x05, 0x5f, 0xc5, 0xed, 0x10, 0x8d, 0x50, 0x81, 0x05, 0xb2, 0x7a, 0x4d, 0x14, 0x4d, 0x3b, 0x50, 0xd6, 0xc7, 0xd2, - 0x2c, 0x1d, 0x45, 0x33, 0x33, 0xbf, 0xca, 0xb4, 0xaf, 0xe5, 0xd8, 0xcd, 0xd7, 0xad, 0x3e, 0xfe, 0xa7, 0x22, 0x43, - 0x5f, 0x0f, 0x87, 0xc3, 0x1b, 0xa3, 0x6a, 0x5f, 0x0f, 0x86, 0xbc, 0xcd, 0xf7, 0x3a, 0x98, 0x15, 0xd4, 0x50, 0xb1, - 0x98, 0x56, 0x41, 0xb8, 0x9b, 0xdf, 0xae, 0x31, 0x86, 0x6d, 0xc4, 0x78, 0x7e, 0xfb, 0x08, 0x5b, 0x01, 0x58, 0x99, - 0x4f, 0x40, 0x5e, 0x44, 0x89, 0xdf, 0x2c, 0xbc, 0x73, 0x15, 0x92, 0xfa, 0x7a, 0x7f, 0x7f, 0xbf, 0xf0, 0x06, 0xfa, - 0xa9, 0x39, 0x18, 0x14, 0x5e, 0x7f, 0x5e, 0x2e, 0xa3, 0xd9, 0x1c, 0x0e, 0x0b, 0x2f, 0xd2, 0x05, 0x3b, 0xed, 0xfe, - 0x60, 0xa7, 0x5d, 0x78, 0x17, 0x46, 0x8b, 0xc2, 0xe3, 0xea, 0x29, 0xe3, 0x83, 0x5a, 0x6a, 0xd1, 0xfd, 0x26, 0x54, - 0x4a, 0x42, 0x9b, 0xa3, 0x59, 0x2a, 0xbf, 0xfa, 0xe1, 0x4c, 0xa4, 0xc8, 0xdc, 0x3b, 0xb1, 0x70, 0x8e, 0x3f, 0xa8, - 0xd7, 0xb6, 0xc8, 0x1f, 0x39, 0x29, 0xdc, 0x13, 0xf6, 0xab, 0x19, 0x3c, 0x42, 0x62, 0xa6, 0xa0, 0x51, 0xac, 0x63, - 0x4b, 0xb5, 0x6a, 0xa4, 0x2c, 0xaa, 0xfe, 0x35, 0x88, 0xab, 0x98, 0x12, 0x72, 0x32, 0x6c, 0x29, 0xdf, 0x2e, 0x98, - 0xac, 0x93, 0x1f, 0xd9, 0xe7, 0xe5, 0xc7, 0xd5, 0x6d, 0xc4, 0x47, 0xf6, 0xa7, 0x8b, 0x8f, 0xc4, 0x14, 0x1f, 0x92, - 0x79, 0x9c, 0x89, 0xc0, 0xee, 0x8f, 0x79, 0xff, 0xd3, 0x59, 0x7a, 0xd9, 0xc0, 0x23, 0x91, 0xd9, 0x24, 0x58, 0x36, - 0x7f, 0x6f, 0xa6, 0x8c, 0x1e, 0xcc, 0xf8, 0x89, 0x14, 0x52, 0x1f, 0x5e, 0x27, 0x81, 0xfd, 0x5a, 0xdb, 0xb6, 0xb2, - 0x64, 0x38, 0x84, 0xa2, 0xe1, 0xd0, 0xd6, 0x97, 0x4f, 0x81, 0x07, 0x52, 0xab, 0x57, 0xb5, 0x12, 0x6a, 0xf5, 0xf4, - 0xa9, 0x59, 0x66, 0x16, 0xa8, 0xd0, 0x93, 0x19, 0x66, 0x52, 0x35, 0x83, 0x28, 0xc7, 0xa3, 0x86, 0xbf, 0xdc, 0x52, - 0x7f, 0xf9, 0x65, 0x52, 0x7b, 0x4f, 0x79, 0x09, 0xf0, 0x8a, 0x97, 0xab, 0x2f, 0xbe, 0x79, 0x01, 0x36, 0x54, 0x65, - 0x74, 0x3e, 0xba, 0x7a, 0x3e, 0x70, 0xce, 0x80, 0x71, 0x46, 0xf9, 0xeb, 0x64, 0xe1, 0x56, 0x95, 0x84, 0x31, 0x08, - 0xcc, 0x65, 0x15, 0x22, 0x1d, 0x8d, 0x62, 0xfc, 0xf1, 0x9c, 0x79, 0xed, 0x85, 0xbc, 0xb2, 0x7b, 0xaf, 0xb6, 0x5e, - 0xdf, 0xec, 0xa8, 0x5e, 0x5f, 0x4b, 0xbf, 0xe5, 0x25, 0xb3, 0xf1, 0xe9, 0xde, 0x98, 0xce, 0xf9, 0x99, 0x2b, 0x26, - 0x3f, 0x97, 0x39, 0xdc, 0x82, 0x45, 0x03, 0xd9, 0x3d, 0x1a, 0x14, 0x85, 0xba, 0xfd, 0x02, 0x88, 0x98, 0xe2, 0x8b, - 0x62, 0x65, 0x4f, 0xfe, 0x39, 0x16, 0x9e, 0x5f, 0x18, 0xf1, 0x9d, 0xda, 0x76, 0x15, 0x3a, 0xc0, 0x23, 0x1d, 0xe6, - 0x67, 0xa2, 0xb0, 0x95, 0xdf, 0x5d, 0x23, 0xd1, 0xb6, 0x24, 0x3e, 0x65, 0xe4, 0xc9, 0x58, 0x21, 0x3a, 0xbf, 0xcb, - 0x0d, 0xd1, 0x55, 0xba, 0xa0, 0x30, 0xe3, 0x97, 0x54, 0x23, 0xb1, 0x45, 0xd1, 0x12, 0x80, 0x3d, 0x91, 0x6c, 0x14, - 0xa6, 0x21, 0x7e, 0xb0, 0x39, 0xaf, 0x76, 0x1e, 0xba, 0x2a, 0xb0, 0x25, 0xf1, 0x02, 0x0f, 0xc6, 0x0e, 0x5d, 0xab, - 0x06, 0x7a, 0xb2, 0x14, 0x64, 0xb9, 0x39, 0xdd, 0xe1, 0xf5, 0xa9, 0x97, 0x5f, 0x30, 0xf8, 0x67, 0xfd, 0x65, 0x0e, - 0x5c, 0xe7, 0xec, 0x53, 0x24, 0x1a, 0x22, 0x9c, 0x36, 0xd0, 0xf0, 0x21, 0xe7, 0xa8, 0x62, 0xcf, 0x94, 0x36, 0x29, - 0xdf, 0x1d, 0xd1, 0x99, 0xe5, 0x98, 0x15, 0x41, 0xea, 0xbb, 0x9f, 0xa4, 0x09, 0xef, 0xd4, 0xd3, 0x63, 0xcd, 0x20, - 0xbb, 0xc6, 0xd6, 0xc9, 0x3c, 0xc5, 0x2c, 0x0a, 0x71, 0xe5, 0x37, 0x15, 0x5b, 0x6f, 0xea, 0x08, 0x7a, 0x73, 0x65, - 0x7b, 0x5f, 0x21, 0x77, 0x8b, 0xa4, 0x57, 0xb6, 0x9c, 0x49, 0xb0, 0x2e, 0x13, 0xe0, 0x73, 0xc9, 0xa2, 0xe8, 0x52, - 0xd5, 0xff, 0x8c, 0x2c, 0xdb, 0xc5, 0x62, 0x4a, 0x16, 0xbd, 0x0d, 0x64, 0x7e, 0x38, 0x84, 0x35, 0xb3, 0xdb, 0xb4, - 0x3c, 0xa3, 0x7b, 0x5d, 0x73, 0x14, 0x33, 0x7e, 0x6b, 0x7f, 0x7a, 0x79, 0xfb, 0xe1, 0x6f, 0x5e, 0x7e, 0xa1, 0x70, - 0xa4, 0xdf, 0x73, 0x64, 0xdb, 0x1d, 0x3c, 0x08, 0x71, 0x78, 0xe5, 0x47, 0x09, 0xc9, 0xbc, 0x33, 0xf4, 0x8b, 0x76, - 0xa6, 0xa9, 0xca, 0x7a, 0xce, 0x78, 0x4c, 0x3f, 0x6b, 0xa8, 0xb6, 0x62, 0xe7, 0xde, 0xf4, 0x52, 0xef, 0x46, 0x6b, - 0x21, 0x9b, 0xf9, 0x4f, 0x4d, 0x5a, 0x5e, 0x9f, 0x25, 0x5d, 0x4f, 0xbc, 0xdd, 0x03, 0x18, 0xa4, 0xa0, 0x6d, 0x64, - 0x12, 0xaa, 0x26, 0x94, 0x18, 0x69, 0xdb, 0xd5, 0x40, 0x96, 0xb7, 0x03, 0xac, 0x3b, 0xcc, 0x79, 0x07, 0x5f, 0xe4, - 0x1e, 0xf5, 0xc3, 0x58, 0x09, 0xf3, 0x49, 0x34, 0x18, 0xc4, 0xbc, 0xa3, 0xe5, 0xb5, 0xd5, 0xba, 0x87, 0x59, 0xcf, - 0xe6, 0x96, 0xd5, 0x77, 0xc5, 0x40, 0x5e, 0x89, 0xa7, 0xf0, 0x0c, 0xf4, 0x07, 0xfc, 0x15, 0x95, 0x95, 0xe8, 0x54, - 0xe9, 0xc0, 0xcd, 0x0a, 0x79, 0xf4, 0xbd, 0xbe, 0x96, 0x3d, 0x50, 0x5e, 0x68, 0xc3, 0x9b, 0x1d, 0x30, 0xe2, 0xfc, - 0xc6, 0x4e, 0x7d, 0x21, 0x58, 0x55, 0x2e, 0x81, 0xad, 0x58, 0x16, 0x43, 0x69, 0x25, 0xf9, 0xb4, 0xe5, 0xb5, 0x54, - 0x19, 0x0d, 0x80, 0x69, 0x63, 0x65, 0x51, 0x51, 0x5f, 0xcc, 0x3f, 0xe6, 0xb4, 0x3c, 0x58, 0x7d, 0x5a, 0x1e, 0xe8, - 0xd3, 0x72, 0x33, 0xc5, 0x7e, 0x3d, 0x6c, 0xe1, 0x7f, 0x9d, 0x6a, 0x41, 0xb0, 0x2b, 0x80, 0x0e, 0x0b, 0xf5, 0xb4, - 0x46, 0x1b, 0xfe, 0xd0, 0xd0, 0x18, 0xbb, 0x69, 0x62, 0x1a, 0x37, 0x6b, 0x5a, 0x58, 0x88, 0xff, 0x9a, 0xb5, 0xaa, - 0xd6, 0x2e, 0xd6, 0x61, 0xaf, 0xbd, 0xe5, 0xba, 0xf6, 0xcd, 0x87, 0x16, 0xf8, 0x95, 0x70, 0x7c, 0xcd, 0x8d, 0xc1, - 0x0c, 0x09, 0xcf, 0xce, 0xa0, 0x74, 0x98, 0xf6, 0x67, 0xf9, 0x3f, 0x2b, 0xf8, 0x15, 0x12, 0x6f, 0x3c, 0xd2, 0x0b, - 0xe3, 0xe8, 0xae, 0x32, 0x85, 0x5e, 0x8f, 0x30, 0x2f, 0xf7, 0xc9, 0xcf, 0x81, 0x30, 0xb9, 0xd3, 0xf6, 0x76, 0x57, - 0x1c, 0x82, 0x7f, 0x97, 0xbd, 0x59, 0xb9, 0x98, 0x3f, 0x8a, 0x8c, 0x1b, 0x91, 0xf0, 0x45, 0x38, 0x30, 0xf7, 0xb0, - 0xb9, 0xbf, 0x1a, 0xdc, 0x63, 0x3d, 0xd3, 0x89, 0x16, 0x0a, 0x4a, 0xee, 0x80, 0x56, 0x1a, 0xce, 0x62, 0x71, 0xf3, - 0xa8, 0xeb, 0x28, 0x63, 0x69, 0xd4, 0x1b, 0x18, 0x7a, 0xd5, 0xf6, 0x96, 0x5c, 0xfa, 0xeb, 0x07, 0xbb, 0xf8, 0x9f, - 0xcc, 0xff, 0xba, 0xaa, 0x74, 0x75, 0x69, 0xf7, 0xa2, 0xae, 0xbe, 0x59, 0x53, 0xc6, 0xa5, 0x08, 0x27, 0x7d, 0xfc, - 0xb6, 0xad, 0x51, 0xab, 0xbc, 0x55, 0x73, 0xa5, 0x65, 0x7d, 0x51, 0xeb, 0x2f, 0x1b, 0xfc, 0x96, 0x6d, 0xfb, 0x52, - 0x73, 0xad, 0xb7, 0x55, 0xbf, 0xeb, 0xb8, 0xd4, 0x58, 0x63, 0x9c, 0xda, 0x6f, 0x06, 0x57, 0xa5, 0x89, 0x22, 0xa3, - 0xb1, 0x68, 0xa5, 0x6c, 0x4a, 0x2b, 0x25, 0xe5, 0xc1, 0xe9, 0x41, 0xef, 0x72, 0x12, 0x5b, 0xe7, 0xf2, 0xfe, 0x69, - 0x60, 0xb7, 0xbc, 0xa6, 0x6d, 0x51, 0x1e, 0x00, 0xbe, 0x06, 0xdf, 0xa6, 0xdf, 0x0b, 0xb6, 0x7b, 0xa8, 0x69, 0x9d, - 0x8f, 0x48, 0xb3, 0x7b, 0x11, 0x5e, 0xf1, 0xec, 0x43, 0xdb, 0xb6, 0xd0, 0x4f, 0xd3, 0x90, 0x29, 0x13, 0x54, 0x66, - 0x41, 0x19, 0x0c, 0x95, 0x80, 0xb6, 0x35, 0x16, 0x62, 0xea, 0xcb, 0x1f, 0x14, 0xbe, 0xd8, 0xf1, 0xd2, 0x6c, 0xb4, - 0xdd, 0x6e, 0x36, 0x9b, 0xf8, 0x46, 0x5d, 0xdb, 0x3a, 0x8f, 0xf8, 0xc5, 0x23, 0x50, 0xa8, 0xed, 0x26, 0xf0, 0xa1, - 0x56, 0x7b, 0x1f, 0xfe, 0xed, 0x7a, 0xf7, 0xf6, 0xed, 0xee, 0x57, 0x96, 0x75, 0x00, 0x64, 0x99, 0xe3, 0x17, 0xf8, - 0x4a, 0x8a, 0x97, 0xfc, 0x6e, 0x81, 0xde, 0x18, 0xe7, 0x8d, 0x96, 0x35, 0x57, 0x8f, 0x96, 0x85, 0xb7, 0x74, 0x7d, - 0xeb, 0xeb, 0x61, 0x7b, 0xb8, 0x3b, 0x7c, 0xd0, 0x51, 0xc5, 0xc5, 0x57, 0xb5, 0xe6, 0x4c, 0x7e, 0xb6, 0x8d, 0x6e, - 0x60, 0xa3, 0xa4, 0x9f, 0xb8, 0xca, 0x49, 0xb4, 0x50, 0xf4, 0xac, 0xec, 0xda, 0x5e, 0x9e, 0xa9, 0xb5, 0x7f, 0xd6, - 0x1f, 0xb6, 0xab, 0xe6, 0x04, 0xe3, 0x76, 0x09, 0x24, 0x68, 0x8e, 0x0a, 0xf4, 0x03, 0x13, 0x4d, 0xad, 0xc6, 0x2a, - 0x44, 0xb5, 0x6c, 0xb5, 0xc6, 0x91, 0x5e, 0xdf, 0x01, 0x5e, 0x0a, 0xd1, 0xba, 0x2a, 0x41, 0x00, 0xdd, 0x02, 0xfb, - 0x25, 0xe0, 0x87, 0xb5, 0x5a, 0xf7, 0x00, 0x3f, 0xfd, 0x26, 0xdb, 0xf5, 0x76, 0x1b, 0x3b, 0xde, 0x3d, 0xb6, 0xdf, - 0xd8, 0x67, 0xfb, 0xcf, 0xf6, 0xfb, 0x0d, 0x28, 0x60, 0xcd, 0xc6, 0x3e, 0x16, 0xc2, 0xdf, 0xfd, 0xf3, 0xc6, 0x2e, - 0x34, 0xa3, 0xd2, 0xb6, 0xb7, 0xb7, 0xd7, 0x68, 0x35, 0xe1, 0x2f, 0xdb, 0xf3, 0xee, 0xdd, 0x6b, 0xb4, 0xa0, 0xc9, - 0xbd, 0x17, 0x7b, 0xfb, 0xde, 0x0e, 0xd6, 0xed, 0xec, 0xf4, 0x77, 0xbc, 0x56, 0xab, 0x81, 0x7f, 0xd8, 0xbe, 0xd7, - 0x96, 0x5f, 0x5a, 0x2d, 0x6f, 0xa7, 0xc5, 0x9a, 0xf1, 0x5e, 0xdb, 0xbb, 0xf7, 0x80, 0xd1, 0x5f, 0x6a, 0xc6, 0xe8, - 0x0f, 0x0e, 0xc3, 0x1e, 0x78, 0xed, 0x7b, 0xf2, 0x1b, 0x0d, 0x78, 0xbe, 0xbb, 0xff, 0xb3, 0xbd, 0xbd, 0x76, 0x0d, - 0x2d, 0xb9, 0x86, 0xfd, 0x3d, 0x98, 0x90, 0xed, 0xb6, 0xbc, 0xfd, 0x9d, 0x71, 0x63, 0x17, 0x86, 0xbd, 0xdf, 0x6f, - 0xb4, 0xbc, 0xfb, 0xf7, 0x01, 0xf4, 0x1d, 0xaf, 0xcd, 0x5a, 0xde, 0xee, 0x0e, 0x7d, 0x81, 0x7f, 0xe7, 0xf7, 0x1f, - 0x78, 0xf7, 0xf6, 0xc6, 0xf7, 0xbc, 0xdd, 0x1f, 0x76, 0x01, 0xae, 0x9d, 0xf1, 0xce, 0x3d, 0xaf, 0x7d, 0xff, 0x1c, - 0x9e, 0xc7, 0x8d, 0xf6, 0xbd, 0x1b, 0x7b, 0xb6, 0xda, 0x1e, 0xe2, 0x88, 0xaa, 0xb1, 0x82, 0xa9, 0x0a, 0xfc, 0x37, - 0xa6, 0xbe, 0xff, 0x8e, 0xc3, 0xe4, 0xcb, 0x5d, 0x1f, 0x78, 0xfb, 0xf7, 0xfb, 0xb2, 0x39, 0x16, 0x34, 0x74, 0x0b, - 0xec, 0x72, 0xde, 0x90, 0xd3, 0xd2, 0x70, 0x0d, 0x3d, 0x90, 0xfe, 0xa7, 0x26, 0x3b, 0x6f, 0xe0, 0xc4, 0x72, 0xde, - 0xff, 0xd0, 0x71, 0xca, 0x2d, 0x3f, 0xd8, 0x1e, 0x49, 0xd2, 0x87, 0x0f, 0xf9, 0xba, 0xec, 0xaf, 0x4e, 0x59, 0xbc, - 0xce, 0xf1, 0x11, 0x7e, 0xde, 0xf1, 0x31, 0xe6, 0xb7, 0xf1, 0x7c, 0x84, 0x7f, 0xba, 0xe7, 0x23, 0x5e, 0x74, 0x9c, - 0x5f, 0x88, 0x25, 0x07, 0xc7, 0xa2, 0x55, 0xfc, 0x42, 0x38, 0xc7, 0x29, 0xfe, 0x30, 0x5b, 0xd1, 0x81, 0xd6, 0x63, - 0x6e, 0xfa, 0x81, 0x52, 0x64, 0xb1, 0x17, 0x42, 0xf2, 0xd8, 0xfe, 0x3a, 0x84, 0x0c, 0x3e, 0x8f, 0x90, 0x1f, 0x6e, - 0x83, 0x8f, 0xc1, 0x9f, 0x8e, 0x8f, 0xbe, 0x89, 0x8f, 0x9a, 0x2f, 0x9f, 0x3c, 0x0d, 0xe4, 0x29, 0x38, 0xa2, 0x67, - 0x07, 0x6f, 0xa5, 0x6d, 0xd9, 0xdb, 0x1c, 0x8b, 0x72, 0x5b, 0x46, 0xbe, 0xde, 0x7e, 0x49, 0xd8, 0x41, 0x5e, 0x41, - 0x0d, 0x6c, 0xe5, 0x96, 0x99, 0x92, 0xd4, 0x51, 0x0f, 0xa5, 0x50, 0x6a, 0x7b, 0x4d, 0x10, 0x4b, 0xda, 0xa5, 0x83, - 0xd7, 0x8e, 0x83, 0x79, 0x2a, 0x42, 0xfc, 0x09, 0x60, 0x40, 0x37, 0xfd, 0x58, 0x30, 0xfe, 0x3c, 0x03, 0x26, 0xfd, - 0xf4, 0xe5, 0x2f, 0x63, 0xe0, 0xbd, 0x09, 0xe5, 0xe8, 0x09, 0xb3, 0x4f, 0xdf, 0xe3, 0xd5, 0x5f, 0x1d, 0x95, 0x98, - 0xa0, 0xb7, 0xe3, 0x25, 0x1f, 0x44, 0xa1, 0x63, 0x3b, 0xd3, 0x8c, 0x0f, 0x61, 0x96, 0x46, 0xed, 0x3e, 0x2c, 0x5d, - 0x85, 0x75, 0x6d, 0xfd, 0x5b, 0xb3, 0x19, 0xbe, 0x6e, 0x3c, 0x38, 0x56, 0xfe, 0x46, 0x5b, 0x19, 0x60, 0x30, 0xbe, - 0x2e, 0xc9, 0x50, 0xd6, 0x56, 0x4a, 0x9b, 0x2d, 0xb5, 0xb6, 0x96, 0xd7, 0x06, 0x2b, 0x8e, 0x8a, 0xf1, 0x45, 0xce, - 0x3f, 0x39, 0x8d, 0x1d, 0xd0, 0x2a, 0x8d, 0x6e, 0xe5, 0x40, 0x27, 0xca, 0xdd, 0x96, 0x54, 0x3f, 0xd2, 0x5d, 0xbf, - 0xac, 0x6c, 0x4b, 0x8a, 0xf8, 0x5a, 0xae, 0x1d, 0xd0, 0x9c, 0xa8, 0x08, 0xb7, 0x7c, 0xe5, 0x06, 0x94, 0x39, 0xe6, - 0x4f, 0x30, 0xcb, 0x17, 0x45, 0xd3, 0x2f, 0xb7, 0xbb, 0x45, 0xd5, 0x24, 0x71, 0xe7, 0x14, 0x6f, 0x89, 0x12, 0x2b, - 0xb9, 0xbe, 0x86, 0x66, 0xf0, 0x10, 0x18, 0x38, 0xc5, 0x67, 0xb7, 0x86, 0xe4, 0x84, 0x95, 0x00, 0x11, 0x82, 0x81, - 0xbe, 0xe8, 0xb3, 0x2a, 0xd6, 0x5f, 0x94, 0xe3, 0xcb, 0x8b, 0x43, 0xd8, 0xbf, 0x84, 0x3e, 0x96, 0xdc, 0x6a, 0x32, - 0x64, 0xb4, 0x50, 0x5a, 0x0d, 0x55, 0xb9, 0xcf, 0xf2, 0x47, 0x57, 0xef, 0xd4, 0x1b, 0xe5, 0x6c, 0xf4, 0x4e, 0x53, - 0x84, 0xa3, 0x7a, 0xfb, 0xf5, 0x56, 0x70, 0xf7, 0x60, 0xc2, 0x45, 0x28, 0xf3, 0x35, 0x51, 0x9f, 0xc0, 0x6b, 0xc8, - 0x96, 0xb2, 0x46, 0x03, 0x9b, 0xa4, 0x7b, 0x20, 0xef, 0xd0, 0x48, 0x51, 0xcf, 0x2c, 0xf5, 0x2a, 0x86, 0x06, 0x6d, - 0x4d, 0xd0, 0x62, 0xd2, 0x1f, 0x03, 0x0f, 0xa8, 0x29, 0x05, 0x49, 0x6a, 0x77, 0xef, 0x96, 0x3f, 0x27, 0xbb, 0x6e, - 0x13, 0xc0, 0xac, 0xf8, 0x74, 0x9c, 0xf1, 0xf8, 0x9f, 0x83, 0xbb, 0x11, 0xb4, 0xbd, 0x7b, 0x02, 0x1b, 0x21, 0xbc, - 0x31, 0x50, 0x50, 0x70, 0x17, 0x65, 0xbc, 0x4f, 0xd6, 0x07, 0x32, 0xc2, 0x2d, 0xd0, 0x83, 0x18, 0x69, 0x4c, 0xb7, - 0x50, 0x88, 0x24, 0xb8, 0x76, 0x7b, 0xcf, 0xb6, 0xa4, 0x4d, 0x4c, 0xdf, 0xbb, 0x52, 0x9c, 0x92, 0x12, 0x00, 0x2a, - 0x92, 0xb7, 0x37, 0x6e, 0x7b, 0x0f, 0xce, 0xef, 0x7b, 0xfb, 0xe3, 0x16, 0xb0, 0x70, 0xfc, 0x84, 0xe7, 0xb8, 0x01, - 0x7f, 0xf0, 0xdf, 0x0f, 0xbb, 0xd0, 0x00, 0x38, 0xf5, 0xfe, 0xf9, 0x8e, 0xb7, 0xf3, 0x02, 0x9a, 0xef, 0x58, 0x2d, - 0x4b, 0xf6, 0x43, 0x76, 0x2d, 0xb9, 0xf3, 0xdd, 0x85, 0x03, 0xb1, 0x22, 0x1c, 0x27, 0x73, 0x4e, 0x6d, 0xe6, 0x94, - 0x3f, 0x5a, 0xa9, 0xce, 0xa7, 0x72, 0xd6, 0x3d, 0x86, 0xbe, 0x4e, 0x19, 0x0f, 0x5a, 0x55, 0xc7, 0x6a, 0xfc, 0x62, - 0xc5, 0x14, 0x78, 0xc2, 0x6d, 0x66, 0xbe, 0xcb, 0x00, 0x5f, 0x04, 0x40, 0x2f, 0x5a, 0xd7, 0xef, 0x9b, 0x5c, 0x4f, - 0xda, 0xb2, 0xa1, 0x7e, 0xa7, 0x25, 0x31, 0x8b, 0x88, 0x7e, 0xd2, 0x82, 0x26, 0x79, 0x3e, 0x28, 0x16, 0xe7, 0xc7, - 0xd4, 0xd7, 0x2c, 0x35, 0x5e, 0xe7, 0xc0, 0xab, 0x0b, 0x1b, 0x83, 0x08, 0x5f, 0xc0, 0x51, 0x14, 0x1a, 0xf4, 0x9a, - 0x9b, 0xb6, 0xc2, 0x12, 0xf1, 0x0b, 0x9e, 0xf7, 0x6c, 0x2c, 0xb2, 0x7d, 0x9b, 0x5c, 0x7c, 0x76, 0xf9, 0xeb, 0x49, - 0x25, 0x61, 0x57, 0x05, 0x8c, 0x2e, 0x5d, 0xe1, 0xa9, 0x45, 0xfc, 0xd8, 0xc0, 0x77, 0xd7, 0x9e, 0x17, 0x52, 0x20, - 0x71, 0xad, 0xd5, 0x8f, 0xae, 0x98, 0xac, 0xc8, 0x36, 0x11, 0x5d, 0x8e, 0x4b, 0x28, 0x74, 0x15, 0x9e, 0xce, 0x78, - 0x28, 0xbc, 0x30, 0x91, 0x49, 0x34, 0x06, 0xc3, 0x62, 0x2d, 0xbe, 0xe3, 0x16, 0xc0, 0x25, 0x8d, 0x1f, 0x56, 0x56, - 0xe7, 0x1c, 0x0a, 0xf5, 0xe5, 0x64, 0xe3, 0x3d, 0x4c, 0xe8, 0xe8, 0x1d, 0xb7, 0xbb, 0xaf, 0xdf, 0x3d, 0xb4, 0xe4, - 0xf1, 0x3c, 0xd8, 0x86, 0xc7, 0x03, 0xf2, 0x99, 0xc8, 0x8b, 0x7a, 0x81, 0xbc, 0xa8, 0x67, 0xa9, 0xbb, 0x99, 0x18, - 0x49, 0x2b, 0xb6, 0xe5, 0xb2, 0xc9, 0x66, 0x90, 0xde, 0xde, 0x09, 0xd8, 0x95, 0x11, 0xbe, 0x34, 0x7c, 0x9b, 0x6e, - 0xe9, 0xe1, 0x86, 0x95, 0x79, 0xd8, 0x4a, 0x3b, 0x3c, 0x13, 0x89, 0xf6, 0x0d, 0x83, 0x7a, 0xcd, 0x75, 0xe6, 0xb5, - 0x1a, 0xaa, 0xbc, 0x29, 0xb0, 0xdc, 0x3a, 0x9f, 0x9d, 0x4d, 0x80, 0x63, 0xea, 0xfb, 0x0c, 0xef, 0x55, 0x87, 0x03, - 0x9a, 0xaa, 0x7b, 0x5a, 0x28, 0xe7, 0xb5, 0xfe, 0x79, 0xa4, 0xfa, 0x96, 0xaa, 0xd5, 0x2b, 0x09, 0x81, 0x37, 0xe4, - 0xc6, 0x3b, 0xdd, 0xd2, 0x5d, 0x6c, 0xd6, 0x15, 0xb0, 0xf4, 0x9d, 0xee, 0xa9, 0x3f, 0x55, 0xe3, 0xbd, 0x48, 0x47, - 0xab, 0xc7, 0x02, 0x8e, 0xd9, 0xa3, 0xab, 0x20, 0xf2, 0xce, 0xb4, 0x56, 0x7e, 0xd3, 0x18, 0x60, 0x52, 0xca, 0x80, - 0x45, 0x81, 0x75, 0x7b, 0xaf, 0xa9, 0x6f, 0x97, 0x40, 0x19, 0x1e, 0x48, 0xd9, 0xc5, 0x98, 0xa4, 0xe6, 0x71, 0x1f, - 0xb7, 0xba, 0x07, 0xa1, 0x45, 0xbc, 0x85, 0x98, 0x47, 0x0e, 0xdc, 0x03, 0x3a, 0x8f, 0xd3, 0x09, 0xf7, 0xa2, 0x74, - 0xfb, 0x82, 0x9f, 0x35, 0xc2, 0x69, 0x54, 0xb9, 0xb7, 0x51, 0xe9, 0x28, 0xa7, 0x4c, 0xb5, 0x47, 0x5c, 0xdd, 0xbd, - 0x6a, 0x57, 0xee, 0xb6, 0x5d, 0xb4, 0x79, 0xb4, 0x6b, 0x8e, 0x7c, 0x72, 0x06, 0x58, 0x29, 0x7c, 0x0d, 0x17, 0x30, - 0x42, 0xfc, 0xbe, 0x50, 0x8e, 0x76, 0x34, 0x6c, 0x90, 0xde, 0x60, 0x3b, 0x48, 0x1c, 0x68, 0x87, 0xbc, 0x12, 0xd4, - 0x85, 0xdd, 0xfd, 0xb7, 0xff, 0xf1, 0xbf, 0x94, 0x8f, 0x1d, 0x50, 0xd8, 0xd2, 0x63, 0x2d, 0xec, 0x4a, 0x71, 0x80, - 0xf7, 0x43, 0xab, 0xa0, 0x30, 0xbf, 0x6c, 0x8c, 0xb2, 0x68, 0xd0, 0x18, 0x87, 0xf1, 0x10, 0xc0, 0x59, 0x8b, 0x4d, - 0x6e, 0x5c, 0xdb, 0x52, 0x50, 0xd7, 0x8b, 0x90, 0x5e, 0x7f, 0xd7, 0xc5, 0x23, 0x7d, 0x7f, 0x85, 0x8e, 0xb6, 0x79, - 0x0d, 0xa9, 0x3a, 0x7d, 0xb5, 0xab, 0x48, 0x89, 0xfa, 0xcd, 0x35, 0xc5, 0x01, 0x93, 0xda, 0x0d, 0x24, 0x68, 0x59, - 0x06, 0xb5, 0xfe, 0xef, 0xff, 0xfc, 0x2f, 0xff, 0x4d, 0x3f, 0x62, 0xac, 0xea, 0xdf, 0xfe, 0xfb, 0x7f, 0xfe, 0x3f, - 0xff, 0xfb, 0xbf, 0xe2, 0xad, 0x15, 0x15, 0xcf, 0x22, 0xa6, 0x62, 0x55, 0xc1, 0x2c, 0xc9, 0x5d, 0x2c, 0x4c, 0xec, - 0x9c, 0x00, 0xcf, 0x8c, 0xfa, 0xf5, 0x3b, 0x49, 0x47, 0x34, 0x21, 0x9d, 0x4c, 0x05, 0x1d, 0x9d, 0xf0, 0xa2, 0x22, - 0xa8, 0x1a, 0xca, 0x89, 0x70, 0xa1, 0x12, 0xf1, 0x7d, 0xbb, 0x6b, 0x9c, 0x5e, 0xb9, 0x1d, 0x73, 0x4d, 0x26, 0x58, - 0x52, 0x54, 0xe5, 0x16, 0xc6, 0x56, 0xe6, 0xf8, 0xe8, 0xb7, 0x8d, 0x62, 0xda, 0xbd, 0x5a, 0x9f, 0xce, 0xc7, 0x19, - 0x2c, 0x60, 0x88, 0x28, 0x97, 0x7e, 0x62, 0x0a, 0x63, 0x37, 0x50, 0x57, 0x8c, 0xaf, 0x0a, 0x1a, 0x45, 0x12, 0xe8, - 0xee, 0xfe, 0x3f, 0x15, 0x7f, 0x9d, 0xa0, 0x46, 0x66, 0x39, 0x93, 0xf0, 0x52, 0x99, 0xe7, 0xf7, 0x9a, 0x40, 0xab, - 0xee, 0xbc, 0x9a, 0x81, 0xad, 0x9b, 0x8c, 0xe8, 0xd8, 0x1c, 0x90, 0xe2, 0xdf, 0xa5, 0x1b, 0xbb, 0x69, 0xa1, 0x2f, - 0xdc, 0x6a, 0x16, 0xc5, 0x5f, 0xe6, 0xe4, 0x49, 0x8d, 0x7e, 0xc3, 0x38, 0xb5, 0x72, 0x3a, 0x43, 0x89, 0xb1, 0x8a, - 0xb9, 0xd1, 0xab, 0x2d, 0x7b, 0x8d, 0x5b, 0xcb, 0xb7, 0x13, 0xcd, 0x38, 0xbb, 0x19, 0x21, 0xdf, 0xc5, 0x98, 0xf7, - 0xb8, 0xc5, 0xc6, 0xed, 0x79, 0x39, 0xbc, 0x10, 0xe9, 0xc4, 0x0c, 0xac, 0xf3, 0x90, 0xf7, 0xf9, 0x50, 0x3b, 0xeb, - 0x55, 0xbd, 0x0c, 0x9a, 0x17, 0xe3, 0x9d, 0x15, 0x73, 0x29, 0x90, 0x28, 0xa0, 0x0e, 0xf0, 0x7c, 0x8d, 0x27, 0x10, - 0xf0, 0x9f, 0x86, 0xc2, 0x27, 0x82, 0xed, 0x98, 0xe1, 0xf9, 0x10, 0x79, 0x52, 0x3a, 0x37, 0xe0, 0xe9, 0xc8, 0xa6, - 0xe8, 0x36, 0xaf, 0xdf, 0x21, 0x2d, 0x3c, 0xea, 0x6e, 0x0e, 0x25, 0xbd, 0x6e, 0x3f, 0xa8, 0xa8, 0xf7, 0xdb, 0x9a, - 0xbb, 0x4a, 0x09, 0xa4, 0xb6, 0xbb, 0xba, 0x5e, 0xca, 0x75, 0x59, 0xfb, 0xbd, 0x70, 0x6c, 0x02, 0xd3, 0x5e, 0x6c, - 0x45, 0x85, 0xd8, 0xea, 0x6d, 0xf0, 0x43, 0x69, 0x32, 0x85, 0xd3, 0x29, 0x35, 0x74, 0x3b, 0x40, 0xc6, 0xa4, 0xe9, - 0x22, 0xf7, 0xa0, 0x94, 0x0e, 0x99, 0x41, 0xa1, 0x1a, 0xa9, 0xa3, 0x20, 0xbf, 0xa9, 0xdc, 0x0a, 0xfc, 0x2d, 0xbe, - 0xee, 0xff, 0x03, 0x85, 0xa3, 0x0b, 0x12, 0x20, 0x8b, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xdb, 0x72, 0xe3, 0x46, 0x96, 0xe0, 0xf3, + 0xfa, 0x2b, 0x20, 0x58, 0x2d, 0x23, 0x9b, 0x49, 0xf0, 0x22, 0xa9, 0x4a, 0x05, 0x32, 0xc9, 0x56, 0xa9, 0xca, 0x5d, + 0x76, 0xd7, 0xcd, 0xa5, 0xb2, 0xdd, 0x6e, 0x5a, 0x2d, 0x42, 0x40, 0x92, 0x48, 0x17, 0x08, 0xd0, 0x40, 0x52, 0x17, + 0x93, 0x98, 0xd8, 0x0f, 0xd8, 0x88, 0x8d, 0xd8, 0xa7, 0x7d, 0xd9, 0xd8, 0x79, 0xd8, 0x8f, 0xd8, 0xe7, 0xf9, 0x94, + 0xf9, 0x81, 0xdd, 0x4f, 0xd8, 0x38, 0x79, 0x01, 0x12, 0xbc, 0xa8, 0x54, 0xb6, 0x7b, 0x66, 0x1e, 0x36, 0x1c, 0x56, + 0x11, 0x89, 0xbc, 0x9c, 0x3c, 0x79, 0xf2, 0xdc, 0x33, 0xd1, 0xdf, 0x0b, 0xd3, 0x80, 0xdf, 0xcd, 0xa9, 0x15, 0xf1, + 0x59, 0x3c, 0xe8, 0xab, 0xbf, 0xd4, 0x0f, 0x07, 0xfd, 0x98, 0x25, 0x1f, 0xac, 0x8c, 0xc6, 0x84, 0x05, 0x69, 0x62, + 0x45, 0x19, 0x9d, 0x90, 0xd0, 0xe7, 0xbe, 0xc7, 0x66, 0xfe, 0x94, 0x5a, 0xad, 0x41, 0x7f, 0x46, 0xb9, 0x6f, 0x05, + 0x91, 0x9f, 0xe5, 0x94, 0x93, 0x6f, 0xdf, 0x7f, 0xd9, 0x3c, 0x19, 0xf4, 0xf3, 0x20, 0x63, 0x73, 0x6e, 0x41, 0x97, + 0x64, 0x96, 0x86, 0x8b, 0x98, 0x0e, 0x5a, 0xad, 0x9b, 0x9b, 0x1b, 0xf7, 0xa7, 0xfc, 0xb3, 0x20, 0x4d, 0x72, 0x6e, + 0xbd, 0x24, 0x37, 0x2c, 0x09, 0xd3, 0x1b, 0xcc, 0x38, 0x79, 0xe9, 0x9e, 0x47, 0x7e, 0x98, 0xde, 0xbc, 0x4b, 0x53, + 0x7e, 0x70, 0xe0, 0xc8, 0xc7, 0xbb, 0xb3, 0xf3, 0x73, 0x42, 0xc8, 0x75, 0xca, 0x42, 0xab, 0xbd, 0x5a, 0x55, 0x85, + 0x6e, 0xe2, 0x73, 0x76, 0x4d, 0x65, 0x13, 0x74, 0x70, 0x60, 0xfb, 0x61, 0x3a, 0xe7, 0x34, 0x3c, 0xe7, 0x77, 0x31, + 0x3d, 0x8f, 0x28, 0xe5, 0xb9, 0xcd, 0x12, 0xeb, 0x59, 0x1a, 0x2c, 0x66, 0x34, 0xe1, 0xee, 0x3c, 0x4b, 0x79, 0x0a, + 0x90, 0x1c, 0x1c, 0xd8, 0x19, 0x9d, 0xc7, 0x7e, 0x40, 0xe1, 0xfd, 0xd9, 0xf9, 0x79, 0xd5, 0xa2, 0xaa, 0x84, 0x73, + 0x4e, 0xce, 0xef, 0x66, 0x57, 0x69, 0xec, 0x20, 0x1c, 0x73, 0x92, 0xd0, 0x1b, 0xeb, 0x7b, 0xea, 0x7f, 0x78, 0xe5, + 0xcf, 0x7b, 0x41, 0xec, 0xe7, 0xb9, 0x75, 0xcb, 0x97, 0x62, 0x0a, 0xd9, 0x22, 0xe0, 0x69, 0xe6, 0x70, 0x4c, 0x31, + 0x43, 0x4b, 0x36, 0x71, 0x78, 0xc4, 0x72, 0xf7, 0x72, 0x3f, 0xc8, 0xf3, 0x77, 0x34, 0x5f, 0xc4, 0x7c, 0x9f, 0xec, + 0xb5, 0x31, 0xdb, 0x23, 0x24, 0xe7, 0x88, 0x47, 0x59, 0x7a, 0x63, 0x3d, 0xcf, 0xb2, 0x34, 0x73, 0xec, 0xb3, 0xf3, + 0x73, 0x59, 0xc3, 0x62, 0xb9, 0x95, 0xa4, 0xdc, 0x2a, 0xfb, 0xf3, 0xaf, 0x62, 0xea, 0x5a, 0xdf, 0xe6, 0xd4, 0x1a, + 0x2f, 0x92, 0xdc, 0x9f, 0xd0, 0xb3, 0xf3, 0xf3, 0xb1, 0x95, 0x66, 0xd6, 0x38, 0xc8, 0xf3, 0xb1, 0xc5, 0x92, 0x9c, + 0x53, 0x3f, 0x74, 0x6d, 0xd4, 0x13, 0x83, 0x05, 0x79, 0xfe, 0x9e, 0xde, 0x72, 0xc2, 0xb1, 0x78, 0xe4, 0x84, 0x16, + 0x53, 0xca, 0xad, 0xbc, 0x9c, 0x97, 0x83, 0x96, 0x31, 0xe5, 0x16, 0x27, 0xe2, 0x7d, 0xda, 0x93, 0xb8, 0xa7, 0xf2, + 0x91, 0xf7, 0xd8, 0xc4, 0x61, 0xfc, 0xe0, 0x80, 0x97, 0x78, 0x46, 0x72, 0x6a, 0x16, 0x23, 0x74, 0x4f, 0x97, 0x1d, + 0x1c, 0x50, 0x37, 0xa6, 0xc9, 0x94, 0x47, 0x84, 0x90, 0x4e, 0x8f, 0x1d, 0x1c, 0x38, 0x9c, 0xc4, 0xdc, 0x9d, 0x52, + 0xee, 0x50, 0x84, 0x70, 0xd5, 0xfa, 0xe0, 0xc0, 0x91, 0x48, 0x48, 0x89, 0x44, 0x5c, 0x0d, 0xc7, 0xc8, 0x55, 0xd8, + 0x3f, 0xbf, 0x4b, 0x02, 0xc7, 0x84, 0x1f, 0x61, 0x76, 0x70, 0x10, 0x73, 0x37, 0x87, 0x1e, 0x31, 0x47, 0xa8, 0xc8, + 0x28, 0x5f, 0x64, 0x89, 0xc5, 0x0b, 0x9e, 0x9e, 0xf3, 0x8c, 0x25, 0x53, 0x07, 0x2d, 0x75, 0x99, 0xd1, 0xb0, 0x28, + 0x24, 0xb8, 0xaf, 0x39, 0x49, 0xc8, 0x00, 0x46, 0xbc, 0xe5, 0x0e, 0xac, 0x62, 0x3a, 0xb1, 0x12, 0x42, 0xec, 0x5c, + 0xb4, 0xb5, 0x87, 0x89, 0x97, 0x34, 0x6c, 0x1b, 0x4b, 0x28, 0x71, 0xce, 0x11, 0xfe, 0x40, 0x9c, 0x04, 0xbb, 0xae, + 0xcb, 0x11, 0x19, 0x2c, 0x35, 0x56, 0x12, 0x63, 0x9e, 0xc3, 0x64, 0xd4, 0xbe, 0xf0, 0xb8, 0x9b, 0xd1, 0x70, 0x11, + 0x50, 0xc7, 0x61, 0x38, 0xc7, 0x19, 0x22, 0x03, 0xd6, 0x70, 0x52, 0x32, 0x80, 0xe5, 0x4e, 0xeb, 0x6b, 0x4d, 0xc8, + 0x5e, 0x1b, 0x29, 0x18, 0x53, 0x0d, 0x20, 0x60, 0x58, 0xc1, 0x93, 0x12, 0x62, 0x27, 0x8b, 0xd9, 0x15, 0xcd, 0xec, + 0xb2, 0x5a, 0xaf, 0x46, 0x16, 0x8b, 0x9c, 0x5a, 0x41, 0x9e, 0x5b, 0x93, 0x45, 0x12, 0x70, 0x96, 0x26, 0x96, 0xdd, + 0x48, 0x1b, 0xb6, 0x24, 0x87, 0x92, 0x1a, 0x6c, 0x54, 0x20, 0x27, 0x47, 0x8d, 0x64, 0x94, 0x35, 0x3a, 0x17, 0x18, + 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0xef, 0x38, 0xcc, 0x52, 0x4c, 0x91, 0xf1, + 0x61, 0xe2, 0x6e, 0x6e, 0x14, 0xc2, 0xdd, 0x99, 0x3f, 0x77, 0x28, 0x19, 0x50, 0x41, 0x5c, 0x7e, 0x12, 0x00, 0xac, + 0xb5, 0x75, 0x1b, 0x52, 0x8f, 0xba, 0x15, 0x49, 0x21, 0x8f, 0xbb, 0x93, 0x34, 0x7b, 0xee, 0x07, 0x11, 0xb4, 0x2b, + 0x09, 0x26, 0xd4, 0xfb, 0x2d, 0xc8, 0xa8, 0xcf, 0xe9, 0xf3, 0x98, 0xc2, 0x93, 0x63, 0x8b, 0x96, 0x36, 0xc2, 0x39, + 0x79, 0xe9, 0xc6, 0x8c, 0xbf, 0x4e, 0x93, 0x80, 0xf6, 0x72, 0x83, 0xba, 0x18, 0xac, 0xfb, 0x29, 0xe7, 0x19, 0xbb, + 0x5a, 0x70, 0xea, 0xd8, 0x09, 0xd4, 0xb0, 0x71, 0x8e, 0x30, 0x73, 0x39, 0xbd, 0xe5, 0x67, 0x69, 0xc2, 0x69, 0xc2, + 0x09, 0xd5, 0x48, 0xc5, 0x89, 0xeb, 0xcf, 0xe7, 0x34, 0x09, 0xcf, 0x22, 0x16, 0x87, 0x0e, 0x43, 0x05, 0x2a, 0x70, + 0xc4, 0x09, 0xcc, 0x91, 0x0c, 0x12, 0x0f, 0xfe, 0xec, 0x9e, 0x8d, 0xc3, 0xc9, 0x40, 0x6c, 0x0a, 0x4a, 0x6c, 0xbb, + 0x37, 0x49, 0x33, 0x47, 0xcd, 0xc0, 0x4a, 0x27, 0x16, 0x87, 0x31, 0xde, 0x2d, 0x62, 0x9a, 0x23, 0xda, 0x20, 0xac, + 0x5c, 0x46, 0x85, 0xe0, 0xd7, 0x40, 0xf1, 0x05, 0x72, 0x12, 0xe4, 0x25, 0xbd, 0x6b, 0x3f, 0xb3, 0xbe, 0x57, 0x3b, + 0xea, 0x99, 0xe6, 0x66, 0x01, 0x27, 0xcf, 0x5c, 0x9e, 0x2d, 0x72, 0x4e, 0xc3, 0xf7, 0x77, 0x73, 0x9a, 0xe3, 0xa7, + 0x9c, 0x04, 0x7c, 0x18, 0x70, 0x97, 0xce, 0xe6, 0xfc, 0xee, 0x5c, 0x30, 0x46, 0xcf, 0xb6, 0x71, 0x08, 0x35, 0x33, + 0xea, 0x07, 0xc0, 0xcc, 0x14, 0xb6, 0xde, 0xa6, 0xf1, 0xdd, 0x84, 0xc5, 0xf1, 0xf9, 0x62, 0x3e, 0x4f, 0x33, 0x8e, + 0xff, 0x4a, 0x96, 0x3c, 0xad, 0x50, 0x03, 0x6b, 0xb9, 0xcc, 0x6f, 0x18, 0x0f, 0x22, 0x87, 0xa3, 0x65, 0xe0, 0xe7, + 0xd4, 0x7a, 0x9a, 0xa6, 0x31, 0xf5, 0x61, 0xd2, 0xc9, 0xf0, 0x29, 0xf7, 0x92, 0x45, 0x1c, 0xf7, 0xae, 0x32, 0xea, + 0x7f, 0xe8, 0x89, 0xd7, 0x6f, 0xae, 0x7e, 0xa2, 0x01, 0xf7, 0xc4, 0xef, 0xd3, 0x2c, 0xf3, 0xef, 0xa0, 0x22, 0x21, + 0x50, 0x6d, 0x98, 0x78, 0x5f, 0x9f, 0xbf, 0x79, 0xed, 0xca, 0x4d, 0xc2, 0x26, 0x77, 0x4e, 0x52, 0x6e, 0xbc, 0xa4, + 0xc0, 0x93, 0x2c, 0x9d, 0xad, 0x0d, 0x2d, 0xb1, 0x96, 0xf4, 0x76, 0x80, 0x40, 0x49, 0xb2, 0x27, 0xbb, 0x36, 0x21, + 0x78, 0x2d, 0x68, 0x1e, 0x5e, 0x12, 0x3d, 0xee, 0x22, 0x8e, 0x3d, 0x59, 0xec, 0x24, 0xe8, 0x7e, 0x68, 0x79, 0x76, + 0xb7, 0xa4, 0x44, 0xc0, 0x39, 0x07, 0x09, 0x03, 0x30, 0x06, 0x3e, 0x0f, 0xa2, 0x25, 0x15, 0x9d, 0x15, 0x1a, 0x62, + 0x5a, 0x14, 0xf8, 0xb4, 0xa4, 0x77, 0x0e, 0x80, 0x08, 0x46, 0x45, 0xf8, 0x6a, 0x05, 0x13, 0x46, 0xf8, 0x6f, 0x64, + 0xe9, 0xeb, 0xf9, 0x78, 0x7b, 0x6d, 0x0c, 0xfb, 0xd2, 0x93, 0xdc, 0x05, 0x07, 0x69, 0x72, 0x4d, 0x33, 0x4e, 0x33, + 0xef, 0xaf, 0x38, 0xa3, 0x93, 0x18, 0xa0, 0xd8, 0xeb, 0xe0, 0xc8, 0xcf, 0xcf, 0x22, 0x3f, 0x99, 0xd2, 0xd0, 0x3b, + 0xe5, 0x05, 0xe6, 0x9c, 0xd8, 0x13, 0x96, 0xf8, 0x31, 0xfb, 0x85, 0x86, 0xb6, 0x12, 0x07, 0xcf, 0x2d, 0x7a, 0xcb, + 0x69, 0x12, 0xe6, 0xd6, 0x8b, 0xf7, 0xaf, 0x5e, 0xaa, 0x85, 0xac, 0x49, 0x08, 0xb4, 0xcc, 0x17, 0x73, 0x9a, 0x39, + 0x08, 0x2b, 0x09, 0xf1, 0x9c, 0x09, 0xee, 0xf8, 0xca, 0x9f, 0xcb, 0x12, 0x96, 0x7f, 0x3b, 0x0f, 0x7d, 0x4e, 0xdf, + 0xd2, 0x24, 0x64, 0xc9, 0x94, 0xec, 0x75, 0x64, 0x79, 0xe4, 0xab, 0x17, 0x61, 0x59, 0x74, 0xb9, 0xff, 0x3c, 0x16, + 0x13, 0x2f, 0x1f, 0x17, 0x0e, 0x2a, 0x72, 0xee, 0x73, 0x16, 0x58, 0x7e, 0x18, 0x7e, 0x95, 0x30, 0xce, 0x04, 0x80, + 0x19, 0xac, 0x0f, 0xd0, 0x28, 0x95, 0xb2, 0x42, 0x03, 0xee, 0x20, 0xec, 0x38, 0x4a, 0x02, 0x44, 0x48, 0x2d, 0xd8, + 0xc1, 0x41, 0xc5, 0xef, 0x87, 0xd4, 0x93, 0x2f, 0xc9, 0xe8, 0x02, 0xb9, 0xf3, 0x45, 0x0e, 0x2b, 0xad, 0x87, 0x00, + 0xf1, 0x92, 0x5e, 0xe5, 0x34, 0xbb, 0xa6, 0x61, 0x49, 0x1d, 0xb9, 0x83, 0x96, 0x6b, 0x63, 0xa8, 0x7d, 0xc1, 0xc9, + 0xe8, 0xa2, 0x67, 0x32, 0x6e, 0xaa, 0x08, 0x3d, 0x4b, 0xe7, 0x34, 0xe3, 0x8c, 0xe6, 0x25, 0x2f, 0x71, 0x40, 0x8c, + 0x96, 0xfc, 0x24, 0x27, 0x7a, 0x7e, 0x73, 0x87, 0x61, 0x8a, 0x6a, 0x1c, 0x43, 0x4b, 0xda, 0xe7, 0xd7, 0x42, 0x64, + 0xe4, 0x98, 0x21, 0xcc, 0x25, 0xa4, 0x39, 0x42, 0x05, 0xc2, 0x5c, 0x83, 0x2b, 0x79, 0x91, 0x1a, 0xed, 0x0e, 0x64, + 0x35, 0xf9, 0x9b, 0x90, 0xd5, 0xc0, 0xd1, 0x7c, 0x4e, 0x0f, 0x0e, 0x1c, 0xea, 0x96, 0x54, 0x41, 0xf6, 0x3a, 0x6a, + 0x8d, 0x0c, 0x64, 0xed, 0x00, 0x1b, 0x06, 0xe6, 0x98, 0x22, 0xbc, 0x47, 0xdd, 0x24, 0x3d, 0x0d, 0x02, 0x9a, 0xe7, + 0x69, 0x76, 0x70, 0xb0, 0x27, 0xea, 0x97, 0xea, 0x04, 0xac, 0xe1, 0x9b, 0x9b, 0xa4, 0x82, 0x00, 0x55, 0x22, 0x56, + 0x09, 0x06, 0x0e, 0x82, 0x4a, 0x68, 0x1c, 0xf6, 0x50, 0x6b, 0x1e, 0x9e, 0x7d, 0x79, 0x69, 0x37, 0x38, 0x56, 0x68, + 0x98, 0x52, 0x3d, 0xf4, 0xdd, 0x33, 0x2a, 0x75, 0x2b, 0xa1, 0x79, 0x6c, 0x60, 0x46, 0x6e, 0x20, 0x37, 0xa4, 0x13, + 0x96, 0x18, 0xd3, 0xae, 0x81, 0x84, 0x39, 0xce, 0x51, 0x61, 0x2c, 0xe8, 0xd6, 0xae, 0x85, 0x52, 0x23, 0x57, 0x6e, + 0x39, 0x15, 0x8a, 0x84, 0xb1, 0x8c, 0x23, 0x7a, 0x51, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x4c, 0x00, 0x3a, 0xe2, 0x17, + 0x3d, 0xf5, 0x9e, 0xe4, 0x12, 0x73, 0x19, 0xfd, 0x79, 0x41, 0x73, 0x2e, 0xe9, 0xd8, 0xe1, 0x38, 0xc3, 0x0c, 0x15, + 0xb0, 0xdf, 0x26, 0x6c, 0xba, 0xc8, 0x40, 0xdf, 0x81, 0xbd, 0x48, 0x93, 0xc5, 0x8c, 0xea, 0xa7, 0x6d, 0xb0, 0xbd, + 0x99, 0x83, 0x44, 0xcc, 0x81, 0xa6, 0xef, 0x27, 0x27, 0x80, 0x95, 0xa3, 0xd5, 0xea, 0x6f, 0xba, 0x93, 0x6a, 0x29, + 0x4b, 0x1d, 0x6d, 0x7d, 0x4d, 0x38, 0x52, 0x12, 0x79, 0xaf, 0x23, 0xc1, 0xe7, 0xfc, 0x82, 0xec, 0xb5, 0x4b, 0x1a, + 0x56, 0x58, 0x95, 0xe0, 0x48, 0x24, 0xbe, 0x91, 0x5d, 0x21, 0x21, 0xe0, 0x6b, 0xe4, 0xe2, 0x46, 0x1b, 0x94, 0x1a, + 0x91, 0x11, 0xa8, 0x1a, 0x6e, 0x74, 0xb1, 0x8b, 0x9c, 0x34, 0x3f, 0x70, 0xf8, 0xe6, 0xbb, 0x8a, 0x6d, 0x5c, 0xd7, + 0xd9, 0xc6, 0xda, 0x34, 0xec, 0x79, 0xd9, 0xc4, 0x2e, 0xa9, 0x4c, 0x6d, 0xf4, 0xea, 0x15, 0x66, 0x02, 0x98, 0x6a, + 0x4a, 0x46, 0x17, 0xaf, 0xfd, 0x19, 0xcd, 0x1d, 0x8a, 0xf0, 0xae, 0x0a, 0x92, 0x3c, 0xa1, 0xca, 0x85, 0x21, 0x39, + 0x73, 0x90, 0x9c, 0x0c, 0x49, 0xc5, 0xac, 0xbe, 0xe1, 0x72, 0x4c, 0x47, 0xf9, 0x45, 0xa5, 0xcf, 0x19, 0x93, 0x17, + 0x22, 0x59, 0xd1, 0xb7, 0xc6, 0x9f, 0x2c, 0x93, 0x48, 0x13, 0x7a, 0x43, 0x8e, 0xf0, 0x5e, 0x7b, 0x7d, 0x25, 0x75, + 0xad, 0x6a, 0x8e, 0xa3, 0x0b, 0x58, 0x07, 0x21, 0x31, 0x5c, 0x96, 0x8b, 0x7f, 0x6b, 0x3b, 0x0d, 0xd0, 0x76, 0x0e, + 0x84, 0xe1, 0x4e, 0x62, 0x9f, 0x3b, 0x9d, 0x56, 0x1b, 0x94, 0xd1, 0x6b, 0x0a, 0x02, 0x05, 0xa1, 0xcd, 0xa9, 0x50, + 0x77, 0x91, 0xe4, 0x11, 0x9b, 0x70, 0x27, 0xe2, 0x82, 0xa5, 0xd0, 0x38, 0xa7, 0x16, 0xaf, 0xa9, 0xc4, 0x82, 0xdd, + 0x44, 0x40, 0x6c, 0xa5, 0xfe, 0x45, 0x35, 0xa4, 0x82, 0x6d, 0x01, 0x77, 0xa8, 0xd4, 0xe9, 0x8a, 0xcb, 0xe8, 0xda, + 0x0c, 0x54, 0xc6, 0xce, 0x50, 0xf6, 0xe8, 0x29, 0x66, 0xc0, 0x0c, 0xad, 0x95, 0x79, 0x26, 0x87, 0x50, 0x85, 0xdc, + 0xe5, 0xe9, 0xcb, 0xf4, 0x86, 0x66, 0x67, 0x3e, 0x00, 0xef, 0xc9, 0xe6, 0x85, 0x14, 0x04, 0x82, 0xdf, 0xf3, 0x9e, + 0xa6, 0x97, 0x4b, 0x31, 0xf1, 0xb7, 0x59, 0x3a, 0x63, 0x39, 0x05, 0x65, 0x4d, 0xe2, 0x3f, 0x81, 0x7d, 0x26, 0x36, + 0x24, 0x08, 0x1b, 0x5a, 0xd2, 0xd7, 0xe9, 0xcb, 0x3a, 0x7d, 0x5d, 0xee, 0x3f, 0x9f, 0x6a, 0x06, 0x58, 0xdf, 0xc6, + 0x08, 0x3b, 0xca, 0xa4, 0x30, 0xe4, 0x9c, 0x1b, 0x21, 0x25, 0xe1, 0x57, 0x2b, 0x6e, 0x58, 0x6e, 0x35, 0x75, 0x91, + 0xca, 0x6d, 0x83, 0x0a, 0x3f, 0x0c, 0x41, 0xb1, 0xcb, 0xd2, 0x38, 0x36, 0x44, 0x15, 0x66, 0xbd, 0x52, 0x38, 0x5d, + 0xee, 0x3f, 0x3f, 0xbf, 0x4f, 0x3e, 0xc1, 0x7b, 0x53, 0x44, 0x69, 0x40, 0x93, 0x90, 0x66, 0x60, 0x49, 0x1a, 0xab, + 0xa5, 0xa4, 0xec, 0x59, 0x9a, 0x24, 0x34, 0xe0, 0x34, 0x04, 0x43, 0x85, 0x11, 0xee, 0x46, 0x69, 0xce, 0xcb, 0xc2, + 0x0a, 0x7a, 0x66, 0x40, 0xcf, 0xdc, 0xc0, 0x8f, 0x63, 0x47, 0x1a, 0x25, 0xb3, 0xf4, 0x9a, 0x6e, 0x81, 0xba, 0x57, + 0x03, 0xb9, 0xec, 0x86, 0x1a, 0xdd, 0x50, 0x37, 0x9f, 0xc7, 0x2c, 0xa0, 0xa5, 0xe8, 0x3a, 0x77, 0x59, 0x12, 0xd2, + 0x5b, 0xe0, 0x23, 0x68, 0x30, 0x18, 0xb4, 0x71, 0x07, 0x15, 0x12, 0xe1, 0xcb, 0x0d, 0xc4, 0xde, 0x23, 0x34, 0x81, + 0xc8, 0xc8, 0x60, 0xb9, 0x8d, 0x1f, 0x50, 0x64, 0x48, 0x4a, 0xa6, 0x8d, 0x2b, 0xc9, 0x9d, 0x11, 0x0e, 0x69, 0x4c, + 0x39, 0xd5, 0xdc, 0x1c, 0x54, 0x68, 0xb9, 0x75, 0xdf, 0x95, 0xf8, 0x2b, 0xc9, 0x49, 0xef, 0x32, 0xbd, 0xe6, 0x79, + 0x69, 0xac, 0x57, 0xcb, 0x53, 0x61, 0x7b, 0xc8, 0xe5, 0xf2, 0xf8, 0x9c, 0xfb, 0x41, 0x24, 0xad, 0x74, 0x67, 0x63, + 0x4a, 0x55, 0x1f, 0x8a, 0xb3, 0x97, 0x9b, 0xe8, 0x9d, 0x06, 0x73, 0x1b, 0x0a, 0xce, 0x15, 0x53, 0xa0, 0x60, 0xf8, + 0xc9, 0x65, 0x3b, 0xf3, 0xe3, 0xf8, 0xca, 0x0f, 0x3e, 0xd4, 0xa9, 0xbf, 0x22, 0x03, 0xb2, 0xce, 0x8d, 0x8d, 0x57, + 0x06, 0xcb, 0x32, 0xe7, 0xad, 0xb9, 0x74, 0x6d, 0xa3, 0x38, 0x7b, 0xed, 0x8a, 0xec, 0xeb, 0x0b, 0xbd, 0x93, 0xda, + 0x05, 0x44, 0x4c, 0xcd, 0xcc, 0x01, 0x2e, 0xf0, 0x51, 0x8a, 0xd3, 0xfc, 0x40, 0xd1, 0x1d, 0x98, 0x1b, 0xc5, 0x1a, + 0x20, 0x1c, 0x2d, 0x8b, 0x90, 0xe5, 0xbb, 0x31, 0xf0, 0xbb, 0x40, 0xf9, 0xcc, 0x18, 0xe1, 0xa1, 0x80, 0x96, 0x3c, + 0x4e, 0x69, 0xcd, 0x25, 0x64, 0x4a, 0x9f, 0xd0, 0x8c, 0xe6, 0x2f, 0xa0, 0xbb, 0x08, 0x7a, 0x7f, 0x23, 0x5f, 0x81, + 0x56, 0x06, 0x50, 0xe4, 0x3d, 0x53, 0x9d, 0xa8, 0x51, 0x80, 0xe2, 0xa9, 0x4c, 0x88, 0xdc, 0xac, 0x66, 0x3f, 0x2a, + 0x8d, 0x5d, 0x9a, 0xe0, 0x8a, 0xe5, 0xa6, 0xc4, 0x71, 0x9c, 0x1c, 0x4c, 0x38, 0xad, 0xda, 0x57, 0x93, 0xc8, 0x37, + 0x26, 0x91, 0xbb, 0x86, 0x9d, 0x85, 0x2a, 0x5a, 0x36, 0x9a, 0x7b, 0x7f, 0x45, 0x66, 0x25, 0x50, 0x57, 0x5d, 0xe0, + 0xcf, 0xa8, 0x64, 0xb7, 0x31, 0xe1, 0x38, 0x55, 0x36, 0x8e, 0xa2, 0x34, 0x60, 0x18, 0x55, 0x93, 0x0c, 0xc9, 0xad, + 0x51, 0xb3, 0x77, 0x33, 0x9c, 0xa2, 0x35, 0xdd, 0xbe, 0x28, 0x14, 0x8e, 0x28, 0x52, 0x6b, 0x53, 0x53, 0x8a, 0x0d, + 0xac, 0xe0, 0x8c, 0x28, 0x45, 0x58, 0xea, 0x3d, 0xeb, 0xb8, 0x29, 0xfb, 0xdd, 0x23, 0x24, 0xab, 0x50, 0x53, 0xd3, + 0x28, 0xb5, 0x6a, 0x95, 0x21, 0x1c, 0x69, 0x9d, 0x34, 0xad, 0xe6, 0x4d, 0x88, 0xad, 0x1d, 0x12, 0xf6, 0x70, 0x59, + 0xb3, 0x0a, 0x3d, 0xa3, 0x5a, 0xe1, 0x01, 0x4b, 0x4d, 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xfa, 0x31, 0x10, 0x9e, + 0x9a, 0x08, 0x37, 0x30, 0x9b, 0x49, 0xce, 0x95, 0x5d, 0x90, 0xa8, 0xde, 0xd6, 0xa1, 0x38, 0x95, 0xeb, 0xb0, 0x81, + 0xc4, 0x75, 0xd5, 0x53, 0x90, 0x20, 0xd8, 0xb0, 0x39, 0x28, 0x77, 0xa6, 0x7c, 0x70, 0x00, 0x76, 0xb6, 0x5a, 0x6d, + 0x10, 0xdd, 0x56, 0x0d, 0x14, 0xb9, 0x95, 0x5d, 0xb8, 0x5a, 0x9d, 0x72, 0xe4, 0x28, 0xdd, 0x17, 0x53, 0x34, 0xd4, + 0x1c, 0xf7, 0xf4, 0x25, 0xd4, 0x12, 0xaa, 0x68, 0x55, 0x52, 0x1a, 0x0d, 0x75, 0x9a, 0xad, 0xaf, 0x13, 0x37, 0xd8, + 0xf6, 0xd9, 0x06, 0xf7, 0x12, 0x85, 0x4a, 0x4c, 0x57, 0x53, 0x3e, 0x53, 0x5d, 0x33, 0x84, 0x90, 0x97, 0x0b, 0x3b, + 0x66, 0x6f, 0x9b, 0x69, 0x79, 0x70, 0x90, 0x1b, 0x1d, 0x5d, 0x96, 0x6c, 0xe2, 0x27, 0x07, 0x44, 0x72, 0x7e, 0x97, + 0x08, 0xdd, 0xe5, 0x27, 0x2d, 0x84, 0x36, 0x0c, 0xd3, 0x76, 0x0f, 0x0c, 0x72, 0xff, 0xc6, 0x67, 0xdc, 0x2a, 0x7b, + 0x91, 0x06, 0xb9, 0x43, 0xd1, 0x52, 0xa9, 0x1a, 0x6e, 0x46, 0x41, 0x79, 0x04, 0x9e, 0xa0, 0x55, 0x68, 0x49, 0xf7, + 0x41, 0x44, 0xc1, 0x17, 0xac, 0xb5, 0x88, 0xd2, 0x32, 0xdc, 0x53, 0x52, 0x44, 0x75, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, + 0x79, 0xcd, 0x12, 0x98, 0xd3, 0x6c, 0x92, 0x66, 0x33, 0xfd, 0xae, 0x58, 0x7b, 0x56, 0x9c, 0x91, 0x4d, 0x9c, 0xad, + 0x7d, 0x2b, 0xfd, 0xbf, 0xb7, 0x66, 0x76, 0x57, 0x06, 0x7b, 0x4d, 0x94, 0x96, 0xd2, 0x57, 0xba, 0x04, 0x35, 0x65, + 0xe6, 0xa6, 0x81, 0xaf, 0xfc, 0xa9, 0x3d, 0xe9, 0x33, 0xd9, 0xeb, 0xf4, 0x4a, 0xab, 0x4f, 0x53, 0x43, 0x4f, 0xfa, + 0x36, 0x94, 0x48, 0x4d, 0x17, 0x71, 0xa8, 0x80, 0x65, 0x08, 0x53, 0x45, 0x47, 0x37, 0x2c, 0x8e, 0xab, 0xd2, 0x4f, + 0xe1, 0xeb, 0xb9, 0xe2, 0xeb, 0x99, 0xe6, 0xeb, 0xc0, 0x29, 0x80, 0xaf, 0xcb, 0xee, 0xaa, 0xe6, 0xd9, 0xc6, 0xee, + 0xcc, 0x24, 0x47, 0xcf, 0x85, 0x25, 0x0d, 0xe3, 0x2d, 0x34, 0x04, 0xa8, 0xd4, 0xbc, 0x3e, 0x38, 0xca, 0x0f, 0x03, + 0x26, 0xa0, 0xf4, 0x62, 0x52, 0xd3, 0x49, 0xf1, 0xc1, 0x41, 0x38, 0x2f, 0x68, 0x49, 0xd9, 0xa7, 0xcf, 0xc1, 0x4f, + 0x67, 0x4c, 0x07, 0x84, 0x98, 0x28, 0xfe, 0x24, 0x25, 0x4a, 0xcf, 0x8e, 0xa9, 0xd9, 0xe5, 0x7a, 0x76, 0xc0, 0xe9, + 0xab, 0xd9, 0x85, 0xf7, 0xf3, 0x7a, 0x31, 0x3d, 0x56, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0xca, 0x59, 0x2b, 0x01, 0x17, + 0xbe, 0x32, 0x51, 0xb2, 0xb2, 0x77, 0xe0, 0x01, 0x26, 0x66, 0xa0, 0xa0, 0x90, 0x93, 0x2e, 0x45, 0xdc, 0xcb, 0x8f, + 0xb9, 0x78, 0x84, 0xa7, 0x5e, 0xb6, 0x3f, 0x4b, 0x67, 0x73, 0xd0, 0xc6, 0xd6, 0x48, 0x7a, 0x4a, 0xd5, 0x80, 0xd5, + 0xfb, 0x62, 0x4b, 0x59, 0xad, 0x8d, 0xd8, 0x8f, 0x35, 0x6a, 0x2a, 0x2d, 0xe6, 0xbd, 0x76, 0xb1, 0x28, 0x8b, 0x4a, + 0xc6, 0xb1, 0xcd, 0xad, 0x72, 0xb6, 0xee, 0x94, 0xd1, 0x2f, 0xde, 0x38, 0x4c, 0xf2, 0x61, 0x06, 0xbc, 0xce, 0x60, + 0x3f, 0x9a, 0xdc, 0xcd, 0xf5, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0xb9, 0xb2, 0xb2, 0xf1, + 0xf3, 0xdd, 0xe6, 0x70, 0xf5, 0x4e, 0x59, 0x8b, 0xa3, 0x0b, 0xfc, 0x7c, 0x53, 0x77, 0x24, 0xcb, 0x59, 0x1a, 0x52, + 0xcf, 0x4e, 0xe7, 0x34, 0xb1, 0x0b, 0xf0, 0xac, 0xaa, 0xc5, 0x0f, 0xb9, 0xb3, 0x7c, 0x57, 0x77, 0xb1, 0x7a, 0xcf, + 0x0b, 0x70, 0x80, 0x7d, 0xbf, 0xe9, 0x7c, 0xfd, 0x8e, 0x66, 0xb9, 0xd0, 0x44, 0x4b, 0xa5, 0xf6, 0xfb, 0x4a, 0x2e, + 0x7d, 0xef, 0xed, 0xac, 0x5f, 0xd9, 0x20, 0x76, 0xc7, 0x7d, 0xe4, 0x1e, 0xda, 0x48, 0xb8, 0x86, 0xbf, 0x56, 0x3b, + 0xfe, 0x27, 0xed, 0x1a, 0x3e, 0x27, 0x3f, 0xd5, 0x3d, 0xc3, 0x0b, 0x4e, 0xce, 0x87, 0xe7, 0xda, 0x64, 0x4e, 0x63, + 0x16, 0xdc, 0x39, 0x76, 0xcc, 0x78, 0x13, 0xc2, 0x6f, 0x36, 0x5e, 0xca, 0x17, 0xe0, 0x55, 0x14, 0x2e, 0xed, 0x42, + 0x1b, 0x7b, 0x98, 0x72, 0x62, 0xef, 0xc7, 0x8c, 0xef, 0xdb, 0x78, 0x42, 0xc6, 0xf0, 0x63, 0x7f, 0xe9, 0xbc, 0xf2, + 0x79, 0xe4, 0x66, 0x7e, 0x12, 0xa6, 0x33, 0x07, 0x35, 0x6c, 0x1b, 0xb9, 0xb9, 0x30, 0x38, 0x9e, 0xa0, 0x62, 0x7f, + 0x8c, 0x9f, 0x73, 0x62, 0x0f, 0xed, 0xc6, 0x04, 0xbf, 0xe0, 0x64, 0xdc, 0xdf, 0x5f, 0x3e, 0xe7, 0xc5, 0x60, 0x8c, + 0x6f, 0x4b, 0xaf, 0x3d, 0xfe, 0x96, 0x38, 0x88, 0x0c, 0x6e, 0x15, 0x34, 0x67, 0xe9, 0x4c, 0x7a, 0xef, 0x6d, 0x84, + 0xdf, 0x8b, 0xd8, 0x4a, 0xc5, 0x6e, 0x54, 0x78, 0x65, 0x8f, 0xd8, 0xa9, 0xf0, 0x11, 0xd8, 0x07, 0x07, 0x46, 0x59, + 0xa9, 0x2b, 0xe0, 0x73, 0x4e, 0x6a, 0x16, 0x39, 0x7e, 0x25, 0xa2, 0x34, 0xe7, 0xdc, 0x49, 0x90, 0xee, 0xc6, 0xd1, + 0xbe, 0x68, 0xb5, 0x37, 0x93, 0x91, 0x74, 0x31, 0xb8, 0x8c, 0xd3, 0xcc, 0xe7, 0x69, 0x76, 0x81, 0x4c, 0xfd, 0x03, + 0xff, 0x85, 0x8c, 0x47, 0xd6, 0x7f, 0xfa, 0xec, 0xc7, 0xc9, 0x8f, 0xd9, 0xc5, 0x18, 0xbf, 0x25, 0xad, 0xbe, 0x33, + 0xf4, 0x9c, 0xbd, 0x66, 0x73, 0xf5, 0x63, 0x6b, 0xf4, 0x77, 0xbf, 0xf9, 0xcb, 0x69, 0xf3, 0x6f, 0x17, 0x68, 0xe5, + 0xfc, 0xd8, 0x1a, 0x8e, 0xd4, 0xd3, 0xe8, 0xef, 0x83, 0x1f, 0xf3, 0x8b, 0x3f, 0xca, 0xc2, 0x7d, 0x84, 0x5a, 0x53, + 0x3c, 0xe7, 0xa4, 0xd5, 0x6c, 0x0e, 0x5a, 0x53, 0x3c, 0xe5, 0xa4, 0x05, 0xff, 0x5e, 0x91, 0x77, 0x74, 0xfa, 0xfc, + 0x76, 0xee, 0x8c, 0x07, 0xab, 0xfd, 0xe5, 0x5f, 0x0a, 0xe8, 0x75, 0xf4, 0xf7, 0x1f, 0x7f, 0xcc, 0xed, 0x2f, 0x06, + 0xa4, 0x75, 0xd1, 0x40, 0x0e, 0x94, 0xfe, 0x91, 0x88, 0xbf, 0xce, 0xd0, 0x1b, 0xfd, 0x5d, 0x41, 0x61, 0x7f, 0xf1, + 0xe3, 0xb8, 0x3f, 0x20, 0x17, 0x2b, 0xc7, 0x5e, 0x7d, 0x81, 0x56, 0x08, 0xad, 0xf6, 0xd1, 0x18, 0xdb, 0x53, 0x1b, + 0xe1, 0x4b, 0x4e, 0x5a, 0x5f, 0xb4, 0xa6, 0xf8, 0x9a, 0x93, 0x96, 0xdd, 0x9a, 0xe2, 0x33, 0x4e, 0x5a, 0x7f, 0x77, + 0x86, 0x9e, 0x74, 0xb2, 0xad, 0x84, 0x7f, 0x63, 0x05, 0x01, 0x0e, 0x3f, 0xa3, 0xfe, 0x8a, 0x33, 0x1e, 0x53, 0xb4, + 0xdf, 0x62, 0xf8, 0x8d, 0x40, 0x93, 0xc3, 0xc1, 0x0b, 0x03, 0xc6, 0x9d, 0xb3, 0xbc, 0x84, 0xc5, 0x06, 0x9a, 0xd9, + 0xf7, 0x20, 0xb2, 0x03, 0x8e, 0x80, 0xdc, 0xe3, 0xf8, 0xda, 0x8f, 0x17, 0x34, 0xf7, 0x68, 0x81, 0x70, 0x4c, 0xde, + 0x70, 0xa7, 0x83, 0xf0, 0x4b, 0x0e, 0x3f, 0xba, 0x08, 0x9f, 0xa9, 0x20, 0x26, 0xec, 0x64, 0x49, 0x54, 0x49, 0x2a, + 0x55, 0x16, 0x1b, 0xe1, 0xf9, 0x96, 0x97, 0x3c, 0x02, 0xf7, 0x02, 0xc2, 0xfb, 0xb5, 0x90, 0x27, 0xbe, 0x21, 0x9a, + 0x24, 0xde, 0x67, 0x94, 0x7e, 0xef, 0xc7, 0x1f, 0x68, 0xe6, 0xdc, 0xe2, 0x4e, 0xf7, 0x09, 0x16, 0x5e, 0xe8, 0xbd, + 0x0e, 0xea, 0x95, 0xf1, 0xaa, 0x0f, 0x5c, 0xc6, 0x09, 0x40, 0xca, 0xd6, 0x9d, 0x31, 0xb0, 0xe2, 0x7b, 0xc9, 0x86, + 0xc7, 0x2a, 0xf3, 0x6f, 0x6c, 0x54, 0x8f, 0x8d, 0xb2, 0xe4, 0xda, 0x8f, 0x59, 0x68, 0x71, 0x3a, 0x9b, 0xc7, 0x3e, + 0xa7, 0x96, 0x9a, 0xaf, 0xe5, 0x43, 0x47, 0x76, 0xa9, 0x33, 0x2c, 0x0c, 0x8b, 0x73, 0xa1, 0x83, 0x4e, 0xb0, 0x57, + 0x1c, 0x88, 0x50, 0x29, 0xbd, 0xe3, 0x59, 0x15, 0x00, 0x5b, 0x8f, 0xf1, 0x35, 0x3b, 0xe0, 0x09, 0xbb, 0x10, 0xf2, + 0x39, 0xc7, 0x19, 0x01, 0x29, 0xda, 0x1d, 0xda, 0xfd, 0xfc, 0x7a, 0x3a, 0xb0, 0x21, 0x3e, 0x93, 0x92, 0xb7, 0xc2, + 0x31, 0x04, 0x15, 0x22, 0xd2, 0xee, 0x45, 0x7d, 0xda, 0x8b, 0x1a, 0x0d, 0xad, 0x44, 0xfb, 0x24, 0x19, 0x45, 0xb2, + 0x79, 0x80, 0x43, 0xbc, 0x20, 0xcd, 0x0e, 0x9e, 0x92, 0xb6, 0x68, 0xd2, 0x9b, 0xf6, 0x7d, 0x35, 0xcc, 0xc1, 0x81, + 0x93, 0xba, 0xb1, 0x9f, 0xf3, 0xaf, 0xc0, 0xda, 0x27, 0x53, 0x1c, 0x92, 0xd4, 0xa5, 0xb7, 0x34, 0x70, 0x7c, 0x84, + 0x43, 0xc5, 0x69, 0x50, 0x0f, 0x4d, 0x89, 0x51, 0x0d, 0xac, 0x08, 0xf2, 0x76, 0x18, 0x8e, 0x3a, 0x17, 0x84, 0x10, + 0x7b, 0xaf, 0xd9, 0xb4, 0x87, 0x29, 0x99, 0x73, 0x0f, 0x4a, 0x0c, 0x5d, 0x99, 0x4c, 0xa1, 0xa8, 0x6b, 0x14, 0x39, + 0x67, 0xdc, 0xe5, 0x34, 0xe7, 0x0e, 0x14, 0x83, 0xfd, 0x9f, 0x6b, 0xc2, 0xb6, 0xfb, 0x2d, 0xbb, 0x01, 0xa5, 0x82, + 0x38, 0x11, 0x4e, 0xc9, 0x15, 0xf2, 0xc2, 0xd1, 0xe1, 0x85, 0x29, 0x00, 0x44, 0x21, 0x0c, 0x7e, 0x35, 0x0c, 0x47, + 0x6d, 0x31, 0xf8, 0xc0, 0x1e, 0x3a, 0x29, 0xc9, 0xa5, 0x86, 0x36, 0xcc, 0xbd, 0xb7, 0x62, 0xaa, 0xc8, 0x53, 0xc0, + 0xe9, 0x15, 0x20, 0xcd, 0xae, 0xe7, 0x2c, 0xcc, 0x49, 0x34, 0x61, 0x30, 0x85, 0x05, 0x1c, 0x10, 0xa8, 0x8f, 0x53, + 0x02, 0x23, 0x56, 0xcd, 0xae, 0x3c, 0xf5, 0xfc, 0x85, 0xfd, 0xc5, 0xf0, 0x9a, 0x7b, 0x97, 0x5c, 0x0e, 0x7f, 0xcd, + 0x57, 0x2b, 0xf8, 0xf7, 0x92, 0x0f, 0x53, 0x72, 0x25, 0x8a, 0xe6, 0xaa, 0x68, 0x0a, 0x45, 0x6f, 0x3d, 0x00, 0x15, + 0xe7, 0xa5, 0x96, 0x25, 0xd7, 0xe4, 0x92, 0x08, 0xd8, 0x0f, 0x0e, 0x92, 0x51, 0xd4, 0xe8, 0x5c, 0x80, 0x8b, 0x3f, + 0xe3, 0xf9, 0xf7, 0x8c, 0x47, 0x8e, 0xdd, 0x1a, 0xd8, 0x68, 0x68, 0x5b, 0xb0, 0xb4, 0xbd, 0xac, 0x41, 0x24, 0x86, + 0xfd, 0xc6, 0x0b, 0xee, 0x2d, 0x06, 0xa4, 0x3d, 0x74, 0x98, 0x64, 0xe1, 0x01, 0xc2, 0xbe, 0x62, 0x9c, 0x6d, 0xbc, + 0x40, 0x0d, 0xca, 0x1b, 0xfa, 0x79, 0x81, 0x1a, 0x93, 0xc6, 0x25, 0xf2, 0xfc, 0xc6, 0xa4, 0xe1, 0x2c, 0x08, 0x21, + 0xcd, 0x6e, 0xd9, 0x4c, 0x8b, 0xbf, 0x08, 0x79, 0x97, 0xda, 0xdb, 0x39, 0x12, 0xdb, 0x21, 0x6b, 0x38, 0xc9, 0x88, + 0x5e, 0xac, 0x56, 0x76, 0x7f, 0x38, 0xb0, 0x51, 0xc3, 0xd1, 0x84, 0xd6, 0xd2, 0x94, 0x86, 0x10, 0x66, 0x17, 0x85, + 0x8a, 0x26, 0xbd, 0xae, 0x45, 0x8e, 0x96, 0xd5, 0x66, 0x37, 0x78, 0x00, 0x2d, 0x4a, 0x43, 0x46, 0x2a, 0xac, 0x73, + 0x98, 0xa6, 0x26, 0xe6, 0x8c, 0xb4, 0x71, 0x4a, 0xb4, 0xf3, 0x3a, 0x22, 0xbc, 0x22, 0x78, 0x9f, 0x54, 0xd5, 0xf1, + 0x28, 0xc0, 0xe1, 0x05, 0x79, 0x26, 0x0d, 0x92, 0x9e, 0x76, 0x8d, 0xd3, 0x98, 0xbc, 0x5e, 0x8b, 0xe0, 0x06, 0x10, + 0x5e, 0xb9, 0x71, 0x83, 0x45, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcd, + 0x62, 0x50, 0xd2, 0xba, 0x7a, 0x67, 0x2c, 0x36, 0x5e, 0x4f, 0xc9, 0x42, 0xea, 0x4f, 0x22, 0x60, 0xdb, 0x9b, 0x2a, + 0xc3, 0xd8, 0x41, 0x78, 0xa1, 0x22, 0xb9, 0x8e, 0xeb, 0xba, 0x53, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, + 0x8f, 0x9c, 0x9c, 0xdc, 0xb8, 0x09, 0xbd, 0x15, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0xf5, 0xa3, 0x9e, 0x60, + 0x37, 0xb9, 0x9b, 0xa4, 0x21, 0x05, 0xf4, 0x40, 0xec, 0x5e, 0x15, 0x45, 0x7e, 0x6e, 0x86, 0xa8, 0x2a, 0xf8, 0x46, + 0xa6, 0xf7, 0x7a, 0x0a, 0x2e, 0x5f, 0xa1, 0x6c, 0x95, 0x95, 0xa5, 0x1f, 0x1c, 0x21, 0x36, 0x71, 0xa6, 0x2e, 0x84, + 0xf6, 0x04, 0x09, 0x51, 0xb0, 0xe5, 0xa6, 0x26, 0x51, 0x4d, 0xca, 0x3e, 0x2f, 0x49, 0x38, 0x4a, 0x1b, 0x0d, 0xe1, + 0x86, 0x5e, 0x48, 0x92, 0x98, 0x22, 0x7c, 0x59, 0xee, 0x2d, 0x5d, 0xef, 0x3b, 0x52, 0x1f, 0xc9, 0xb9, 0xac, 0xbb, + 0x73, 0x1b, 0x90, 0x26, 0x01, 0x9e, 0x42, 0xee, 0x4c, 0x10, 0x3e, 0x25, 0x2d, 0x67, 0xe4, 0x0e, 0xff, 0x74, 0x81, + 0x86, 0x8e, 0xfb, 0x47, 0xd4, 0x92, 0x8c, 0xe3, 0x12, 0xf5, 0x7c, 0x39, 0xc4, 0x52, 0x84, 0x30, 0x3b, 0x58, 0x78, + 0x12, 0xbd, 0x0c, 0x27, 0xfe, 0x8c, 0x7a, 0xa7, 0xb0, 0xc7, 0x35, 0xdd, 0x7c, 0x87, 0x81, 0x8e, 0xbc, 0x53, 0xc5, + 0x49, 0x5c, 0x7b, 0xf8, 0x15, 0x2f, 0x9f, 0x86, 0xf6, 0xf0, 0x97, 0xea, 0xe9, 0x4f, 0xf6, 0xf0, 0x4b, 0xee, 0xfd, + 0x52, 0x28, 0x67, 0x77, 0x6d, 0x88, 0x47, 0x7a, 0x88, 0x42, 0x2e, 0x8c, 0x81, 0xb9, 0x05, 0xda, 0xf4, 0x73, 0x4c, + 0x51, 0xc1, 0x26, 0x25, 0x2b, 0xca, 0x5d, 0xee, 0x4f, 0x01, 0xa5, 0xc6, 0x0a, 0xe4, 0x66, 0x64, 0xbf, 0x9a, 0x30, + 0x10, 0x8a, 0xa6, 0x56, 0x40, 0xe5, 0x74, 0xd0, 0x46, 0xcb, 0x5a, 0x5d, 0xa1, 0x31, 0xd5, 0x23, 0xe9, 0x25, 0x97, + 0xbe, 0x24, 0xed, 0xde, 0x65, 0x7f, 0xda, 0xbb, 0x6c, 0x34, 0x50, 0xae, 0x09, 0x6b, 0x31, 0xba, 0xbc, 0xc0, 0xdf, + 0x82, 0x4f, 0xcf, 0xa4, 0x24, 0x5c, 0x9b, 0x5e, 0x57, 0x4d, 0xaf, 0xd1, 0xc8, 0x0a, 0xd4, 0x33, 0x9a, 0x4e, 0x65, + 0xd3, 0xa2, 0x90, 0x38, 0x59, 0x27, 0xb4, 0x13, 0x24, 0x4a, 0x20, 0x1d, 0x8a, 0x10, 0xf2, 0x9c, 0xa3, 0xad, 0xbd, + 0x42, 0x9f, 0xd0, 0x5c, 0xec, 0x58, 0x60, 0x9e, 0x52, 0x46, 0x38, 0x80, 0x05, 0x68, 0x5a, 0x3a, 0x82, 0x27, 0x78, + 0xd1, 0xe8, 0x08, 0x22, 0x6f, 0x76, 0x7a, 0xf5, 0xbe, 0x1e, 0x57, 0x7d, 0xe1, 0x45, 0x83, 0x4c, 0x4a, 0x2c, 0x15, + 0x59, 0xa3, 0x51, 0xd4, 0xa3, 0x9d, 0x7a, 0xdf, 0xd6, 0xe2, 0x0f, 0xb7, 0xeb, 0x69, 0x19, 0x5a, 0xbe, 0x56, 0x12, + 0x95, 0xb9, 0x2c, 0x49, 0x68, 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, + 0x12, 0xe0, 0x3b, 0xc2, 0xec, 0xc2, 0x19, 0x4e, 0x71, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x4c, 0x27, 0xb4, 0x70, 0xc1, + 0x81, 0x7c, 0xc2, 0x0c, 0x89, 0x94, 0x13, 0xea, 0x5e, 0xee, 0x9f, 0xa5, 0xf7, 0x9a, 0x64, 0x23, 0x76, 0xe1, 0x89, + 0x6a, 0xb1, 0xe2, 0x5b, 0x01, 0x79, 0xef, 0x70, 0x54, 0x06, 0x47, 0x5c, 0xc1, 0xfe, 0x9e, 0xb1, 0x8c, 0x0a, 0x0d, + 0x7c, 0x5f, 0x9b, 0x7d, 0x7e, 0x5d, 0x7d, 0xf4, 0x4d, 0xe7, 0x0d, 0x20, 0x32, 0x00, 0xdf, 0x4e, 0x46, 0x36, 0xaa, + 0x5d, 0xee, 0x9f, 0xbe, 0xd9, 0x66, 0x02, 0xaf, 0x56, 0xca, 0xf8, 0xf5, 0x41, 0xb3, 0xc1, 0x41, 0x05, 0xa9, 0xaf, + 0x7e, 0x78, 0x8e, 0x2f, 0x14, 0xa4, 0xc0, 0x49, 0x80, 0x8a, 0x2e, 0xf7, 0x4f, 0xdf, 0x3b, 0x89, 0x70, 0x2d, 0x21, + 0x6c, 0x4e, 0xdb, 0x49, 0x89, 0x13, 0x11, 0x8a, 0xe4, 0xdc, 0x4b, 0xc6, 0x95, 0x1a, 0xe2, 0xdb, 0x8b, 0xc4, 0x4b, + 0xb0, 0x1f, 0x46, 0xec, 0x82, 0xf8, 0x0a, 0x03, 0xc4, 0x47, 0xd8, 0xaf, 0x99, 0x65, 0x04, 0x16, 0x40, 0x8c, 0x75, + 0x0e, 0x2b, 0xe1, 0x4a, 0xc5, 0x0f, 0x61, 0x5f, 0x8c, 0xca, 0x0b, 0x29, 0x3a, 0x7e, 0xda, 0xc8, 0x4b, 0xab, 0xac, + 0xd1, 0xef, 0xc0, 0x72, 0xd2, 0x0f, 0xaf, 0x55, 0xd7, 0x65, 0xc1, 0x33, 0x9d, 0x40, 0x76, 0xb9, 0x7f, 0xfa, 0x4a, + 0xe5, 0x90, 0xcd, 0x7d, 0xcd, 0xed, 0x37, 0x2c, 0xcc, 0xd3, 0x57, 0x6e, 0xf5, 0x56, 0x54, 0xbe, 0xdc, 0x3f, 0xfd, + 0x76, 0x5b, 0x35, 0x28, 0x2f, 0x16, 0x95, 0x89, 0x2f, 0xe0, 0x5b, 0xd2, 0xd8, 0x5b, 0x2a, 0xd1, 0xe0, 0xb1, 0x02, + 0x0b, 0x71, 0xe4, 0xe5, 0x45, 0xe9, 0x19, 0x79, 0x86, 0x33, 0x22, 0xa2, 0x40, 0xf5, 0x55, 0x53, 0x4a, 0x1e, 0x4b, + 0x93, 0xf3, 0x20, 0x9d, 0xd3, 0x1d, 0xa1, 0xa1, 0x5b, 0xe4, 0xb2, 0x19, 0x24, 0xcf, 0x08, 0xd0, 0x19, 0xde, 0x6b, + 0xa3, 0x5e, 0x5d, 0x78, 0x65, 0x82, 0x48, 0xd3, 0x9a, 0x64, 0xc1, 0x11, 0x69, 0x63, 0x9f, 0xb4, 0x71, 0x40, 0xf2, + 0x51, 0x5b, 0x8a, 0x87, 0x5e, 0x50, 0xf6, 0x2b, 0x85, 0x0c, 0xe4, 0x85, 0x05, 0x72, 0xb7, 0x4a, 0xf1, 0x1b, 0xf6, + 0x02, 0xe1, 0x7a, 0x14, 0x12, 0x3d, 0x14, 0x64, 0xf1, 0xd4, 0x49, 0x71, 0x2a, 0x3a, 0x3e, 0x67, 0x57, 0x31, 0xa4, + 0x96, 0xc0, 0xac, 0x30, 0x47, 0x5e, 0x59, 0xb5, 0xa3, 0xaa, 0x06, 0xae, 0x58, 0xa7, 0x14, 0x07, 0x2e, 0x30, 0x6e, + 0x1c, 0xa8, 0x4c, 0x9c, 0x7c, 0xb3, 0xc9, 0xa3, 0x83, 0x03, 0x47, 0x36, 0xfa, 0x8e, 0x3b, 0xa9, 0x7e, 0x5f, 0x05, + 0xee, 0xbe, 0x93, 0xbc, 0x22, 0x44, 0x02, 0xfe, 0x46, 0xc3, 0xbf, 0x28, 0x20, 0x0a, 0xed, 0x04, 0x75, 0x0c, 0x6a, + 0xe0, 0x85, 0xa6, 0x57, 0x9f, 0x7e, 0xa3, 0x51, 0x06, 0x69, 0xeb, 0xd8, 0xba, 0xc5, 0x59, 0x71, 0xed, 0x94, 0xc9, + 0x3f, 0xed, 0x8d, 0x8c, 0x29, 0x0d, 0x02, 0x62, 0x26, 0xcd, 0x32, 0x3d, 0x19, 0x63, 0x4b, 0x30, 0xa8, 0xf7, 0x95, + 0x4a, 0x5b, 0xc0, 0x22, 0xbf, 0x4a, 0x55, 0xd2, 0xec, 0xac, 0x8b, 0x3c, 0x5d, 0x09, 0x82, 0x52, 0x50, 0xa9, 0x51, + 0x28, 0xf2, 0x7e, 0xba, 0x99, 0x75, 0x89, 0x73, 0xa4, 0x7c, 0x5c, 0x02, 0x0a, 0x81, 0xac, 0x6e, 0x89, 0x94, 0x17, + 0x64, 0xbe, 0x9b, 0xe4, 0x4f, 0x0d, 0x92, 0x7f, 0x4a, 0xa8, 0x41, 0xfe, 0xd2, 0xc3, 0xe1, 0xa6, 0xca, 0xb5, 0x90, + 0xeb, 0x57, 0x67, 0x73, 0x02, 0x3e, 0xb4, 0x3a, 0x46, 0x6b, 0x51, 0xc5, 0x1d, 0x0c, 0xc5, 0xdc, 0x21, 0xc2, 0x0b, + 0x89, 0x75, 0x08, 0xd8, 0xa9, 0x62, 0x6a, 0x30, 0xf4, 0x36, 0x97, 0x9e, 0xc9, 0x01, 0x4f, 0xbf, 0xbd, 0x3f, 0x1c, + 0x7a, 0x36, 0xdf, 0xdc, 0xb9, 0x46, 0xf6, 0x27, 0xcc, 0xda, 0xd8, 0xb8, 0xf5, 0x5c, 0x50, 0x18, 0xbf, 0x0c, 0x63, + 0xd7, 0x99, 0xcf, 0xda, 0x26, 0xd4, 0xf2, 0x0f, 0xa0, 0xed, 0x74, 0x44, 0x0d, 0x6a, 0x74, 0x0b, 0xfc, 0x48, 0xe6, + 0xa0, 0xfa, 0xd9, 0x0e, 0xf6, 0x71, 0x2a, 0x2a, 0xd0, 0x24, 0xdc, 0xfe, 0xfa, 0x69, 0xa1, 0xc8, 0x44, 0x82, 0x86, + 0x96, 0xc0, 0xff, 0x24, 0xc9, 0x03, 0xdd, 0x08, 0xb9, 0x00, 0x08, 0x9a, 0x0b, 0x3c, 0x55, 0x08, 0xb3, 0xed, 0xca, + 0xf9, 0xfe, 0x62, 0x8f, 0x90, 0x79, 0xe5, 0x7c, 0x7c, 0x57, 0xe5, 0x5e, 0x01, 0x59, 0x20, 0x0f, 0x8c, 0xc7, 0xb2, + 0x40, 0x46, 0x2f, 0xcf, 0x74, 0x75, 0x61, 0x40, 0xba, 0x95, 0xbe, 0x6d, 0x44, 0x36, 0x85, 0x57, 0x4e, 0xbe, 0xd7, + 0x68, 0x58, 0x7b, 0xbb, 0x0f, 0x6f, 0x5f, 0x71, 0x01, 0x23, 0x3c, 0xbf, 0x17, 0xb5, 0x75, 0xbf, 0xc5, 0x87, 0xf5, + 0x04, 0x96, 0xb5, 0x45, 0x71, 0x59, 0x92, 0xd3, 0x8c, 0x3f, 0xa5, 0x93, 0x34, 0x83, 0x90, 0x45, 0x89, 0x13, 0x54, + 0xec, 0x1b, 0x6e, 0x3b, 0x31, 0x3f, 0x23, 0x4e, 0xb0, 0x36, 0x41, 0xf1, 0xeb, 0x83, 0x88, 0x59, 0x5f, 0xae, 0xb7, + 0x9a, 0x1f, 0x1c, 0xbc, 0xaf, 0xd0, 0xa4, 0xa0, 0x14, 0x50, 0x18, 0x4c, 0x4b, 0xaa, 0x34, 0x2a, 0x90, 0xbb, 0xef, + 0x94, 0x2e, 0x00, 0xcd, 0x30, 0x4c, 0xde, 0xf3, 0x82, 0xf0, 0x62, 0xba, 0xce, 0xe2, 0x95, 0x6b, 0x82, 0x99, 0x66, + 0x0b, 0x70, 0x78, 0x30, 0xb4, 0xa5, 0xaf, 0x28, 0xaf, 0xd2, 0x61, 0x4b, 0x18, 0xce, 0x00, 0x59, 0x8e, 0x30, 0x42, + 0x0c, 0x0a, 0xdc, 0x6a, 0x94, 0x7c, 0x00, 0xbd, 0x32, 0xc2, 0xb9, 0x1b, 0x41, 0x02, 0x6c, 0x6d, 0xcb, 0x22, 0x84, + 0x65, 0x5e, 0x8e, 0x91, 0x49, 0x70, 0xfa, 0x62, 0x9b, 0x47, 0x59, 0x13, 0x35, 0x15, 0x52, 0x07, 0x6a, 0x64, 0xa8, + 0x6c, 0xe0, 0x5e, 0x3b, 0x4c, 0x29, 0x6e, 0x3a, 0x6c, 0x06, 0x0c, 0xf8, 0x27, 0xee, 0xc8, 0x58, 0x14, 0xc8, 0x8c, + 0xd4, 0x5d, 0x38, 0xb5, 0xa1, 0x7b, 0xa9, 0x68, 0x86, 0x15, 0xe2, 0x22, 0x13, 0x4d, 0xa9, 0x08, 0xeb, 0x9d, 0x55, + 0xbc, 0x74, 0x5f, 0xe6, 0x50, 0x73, 0xcd, 0x05, 0xab, 0x3c, 0x12, 0x63, 0xfa, 0xfb, 0x32, 0x2d, 0xba, 0xac, 0x04, + 0x6a, 0x18, 0xbd, 0xb1, 0x5e, 0x8b, 0x35, 0xa0, 0x05, 0xd0, 0xd7, 0xf2, 0x9c, 0x1b, 0x2b, 0xaa, 0x7d, 0xd8, 0x62, + 0x4c, 0x43, 0xea, 0xbf, 0x83, 0x4c, 0x97, 0xf5, 0x3d, 0xff, 0x42, 0xc8, 0x42, 0x86, 0xf3, 0x1a, 0x63, 0xcf, 0x04, + 0x63, 0x47, 0xa0, 0xa7, 0xe9, 0xd4, 0xef, 0xa1, 0x4a, 0x78, 0x61, 0x4a, 0xca, 0x29, 0x12, 0xfb, 0xb6, 0x0c, 0x96, + 0x1b, 0xbf, 0xd7, 0x56, 0xc3, 0x63, 0x04, 0x92, 0x80, 0xb0, 0xe2, 0xec, 0x19, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xfb, + 0xb4, 0x72, 0x91, 0x54, 0x30, 0x32, 0x88, 0xe7, 0x02, 0xc1, 0xd7, 0x64, 0x28, 0x44, 0xfc, 0x75, 0x6e, 0x76, 0x0e, + 0xae, 0xf6, 0xd3, 0x77, 0x8e, 0xc9, 0xd5, 0xcc, 0xba, 0x65, 0xcc, 0x14, 0xe6, 0xe3, 0x54, 0xf1, 0x96, 0xb7, 0xf7, + 0xe7, 0x77, 0x00, 0xdc, 0x7b, 0x1d, 0x0c, 0xb9, 0x68, 0xa8, 0xc7, 0x25, 0x4b, 0x28, 0x77, 0x5f, 0x0f, 0x55, 0x69, + 0x89, 0xe6, 0x60, 0x3d, 0x5e, 0x99, 0xb2, 0x9c, 0xe4, 0x45, 0x91, 0xd3, 0x2a, 0xba, 0xbf, 0x96, 0x7f, 0x29, 0x84, + 0xcb, 0xa6, 0xb3, 0xfd, 0x6c, 0x4e, 0x38, 0x36, 0x08, 0xf5, 0xed, 0xae, 0xd0, 0x47, 0x05, 0x26, 0xec, 0x6b, 0x25, + 0x14, 0x7f, 0xd9, 0x26, 0x14, 0x71, 0xa6, 0xb6, 0xbc, 0x10, 0x88, 0x9d, 0x07, 0x08, 0x44, 0xe5, 0x64, 0xd7, 0x32, + 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x2f, 0x29, 0xc9, 0x30, 0x53, 0xab, 0x31, 0xe8, 0xae, 0x56, 0x6c, 0xd4, 0x06, + 0x27, 0x92, 0x6d, 0xc3, 0xcf, 0x8e, 0xfc, 0x69, 0x70, 0x62, 0xe9, 0x04, 0x76, 0x58, 0x69, 0xb2, 0x20, 0x17, 0x52, + 0x9c, 0x1d, 0x91, 0x93, 0x25, 0x68, 0x5a, 0x51, 0x90, 0x22, 0x70, 0xc2, 0xca, 0x28, 0x13, 0x40, 0x2c, 0x64, 0x85, + 0x32, 0x20, 0x9d, 0xad, 0xc9, 0x7f, 0xda, 0xbc, 0xfc, 0xb8, 0x26, 0x5a, 0x93, 0x2b, 0x52, 0x7d, 0xa8, 0xa5, 0x1b, + 0x28, 0x08, 0x94, 0x7e, 0xb8, 0x27, 0x4c, 0xd0, 0x4a, 0x94, 0x23, 0x53, 0x0e, 0xe1, 0x36, 0xb8, 0xd0, 0xf6, 0xde, + 0xcb, 0x00, 0xef, 0x16, 0x69, 0x82, 0x53, 0x83, 0xae, 0x5f, 0x10, 0x5e, 0x63, 0x25, 0x11, 0x51, 0x96, 0x12, 0x0e, + 0x04, 0x99, 0x72, 0x92, 0x8d, 0xda, 0x17, 0xa0, 0x80, 0xf6, 0xfc, 0x7e, 0x56, 0x99, 0xc0, 0x7e, 0xa3, 0x81, 0x02, + 0x3d, 0x6a, 0x34, 0x62, 0x0d, 0xff, 0x02, 0x53, 0xec, 0x4b, 0xc3, 0xe4, 0xec, 0xe0, 0xc0, 0x09, 0xaa, 0x71, 0x47, + 0xfe, 0x05, 0xc2, 0xe9, 0x6a, 0xe5, 0x08, 0xb0, 0x02, 0xb4, 0x5a, 0x05, 0x26, 0x58, 0xe2, 0x35, 0x34, 0x9b, 0x0f, + 0x39, 0x99, 0x0b, 0x01, 0x38, 0x07, 0x08, 0x1b, 0xc4, 0x09, 0x94, 0x73, 0x2f, 0x00, 0x67, 0x54, 0x23, 0x1b, 0xf9, + 0x8d, 0xce, 0x85, 0xc1, 0xb8, 0x46, 0xfe, 0x05, 0x09, 0x8a, 0xf4, 0xe0, 0x60, 0x2f, 0x57, 0x22, 0xf2, 0x27, 0x10, + 0x65, 0x3f, 0x09, 0xc9, 0x22, 0x3b, 0x34, 0x57, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0x5a, 0x56, 0x5d, 0xaf, 0x96, + 0x04, 0x51, 0x56, 0xc2, 0x2a, 0x16, 0x3c, 0x04, 0xcb, 0xbe, 0x24, 0xf3, 0xaf, 0x78, 0x99, 0x64, 0xfd, 0xcb, 0xd6, + 0xd4, 0x6a, 0xd7, 0x75, 0xfd, 0x6c, 0x2a, 0x22, 0x19, 0x3a, 0x0a, 0x2b, 0x88, 0xff, 0x50, 0x81, 0x69, 0x0c, 0x3c, + 0x2a, 0xc7, 0xba, 0x20, 0x12, 0x7c, 0xad, 0xda, 0xe8, 0xd3, 0x24, 0x3f, 0x6f, 0xf5, 0x32, 0xa8, 0x0d, 0xf7, 0x6b, + 0x21, 0x39, 0x52, 0x90, 0x48, 0xf2, 0x58, 0xc3, 0xd9, 0x0e, 0x5c, 0xfc, 0xcc, 0xd7, 0x70, 0xb6, 0x1b, 0xb7, 0x1a, + 0x53, 0x5f, 0xee, 0x82, 0xcf, 0xe0, 0x0d, 0x12, 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x78, 0x5d, 0xf7, 0x92, 0xac, 0x14, + 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0xcd, 0x91, 0xe1, 0x12, 0xa8, 0x67, + 0xae, 0x00, 0x39, 0x29, 0x5f, 0xfb, 0xfc, 0xe0, 0x00, 0x6c, 0x03, 0x50, 0xe2, 0xdc, 0xc0, 0x9f, 0xf3, 0x45, 0x06, + 0xaa, 0x54, 0xae, 0x7f, 0x43, 0x31, 0x9c, 0x03, 0x11, 0x65, 0xf0, 0x03, 0x0a, 0xe6, 0x7e, 0x9e, 0xb3, 0x6b, 0x59, + 0xa6, 0x7e, 0xe3, 0x94, 0x68, 0x52, 0xce, 0xa5, 0x4e, 0x98, 0xa1, 0x5e, 0xa6, 0xe8, 0xb4, 0x8e, 0xb6, 0xe7, 0xd7, + 0x34, 0xe1, 0x2f, 0x59, 0xce, 0x69, 0x02, 0xd3, 0xaf, 0x28, 0x0e, 0x66, 0x94, 0x23, 0xd8, 0xb0, 0xb5, 0x56, 0x7e, + 0x18, 0xde, 0xdb, 0x84, 0xd7, 0x75, 0xa0, 0xc8, 0x4f, 0xc2, 0x58, 0x0e, 0x62, 0xa6, 0x33, 0xea, 0x14, 0xce, 0xb2, + 0xa6, 0x99, 0x4e, 0x53, 0x29, 0x1b, 0x82, 0xbb, 0x3b, 0x8c, 0x68, 0x49, 0xa0, 0xa5, 0xe7, 0xbd, 0x5a, 0x0b, 0x04, + 0xbc, 0x77, 0x2c, 0x82, 0x39, 0x13, 0xcc, 0x0d, 0x8e, 0xea, 0xd6, 0xe1, 0xd4, 0x74, 0xf3, 0xdd, 0xd6, 0x43, 0x6d, + 0xdb, 0x84, 0x83, 0xa0, 0x93, 0x47, 0xbb, 0x2d, 0xab, 0x57, 0x5a, 0x72, 0x68, 0x69, 0xc1, 0x1e, 0xca, 0x98, 0xd1, + 0x52, 0x93, 0x17, 0xd2, 0x5b, 0x71, 0xc6, 0xc9, 0x4f, 0x70, 0x6a, 0xe8, 0x05, 0x9f, 0xc5, 0x6b, 0x87, 0x63, 0x7a, + 0xb3, 0x52, 0xfb, 0x9f, 0x71, 0xe7, 0x35, 0x7e, 0x0a, 0x61, 0xdd, 0xaf, 0xab, 0xea, 0x9b, 0xe1, 0xdc, 0xaf, 0x2b, + 0x04, 0x7d, 0xed, 0x6d, 0xd4, 0x33, 0xc2, 0xb8, 0x5d, 0xf7, 0xc4, 0x6d, 0xdb, 0x5a, 0x5b, 0xfa, 0x5e, 0x06, 0x91, + 0x64, 0xa2, 0xa5, 0xd8, 0x0f, 0xb8, 0x4a, 0x53, 0x83, 0x74, 0xb9, 0xba, 0x85, 0x44, 0x55, 0x82, 0xa1, 0xd4, 0xe1, + 0x77, 0x2d, 0x8f, 0x92, 0x31, 0x99, 0xb4, 0x33, 0xde, 0xfa, 0x19, 0xdf, 0x87, 0x5d, 0x96, 0x6e, 0x9c, 0xc4, 0x8b, + 0x08, 0x78, 0xd0, 0x1e, 0x36, 0x84, 0x61, 0x6c, 0xe7, 0xf2, 0x24, 0x90, 0xd9, 0x3f, 0x49, 0xb5, 0xee, 0x56, 0xb7, + 0x32, 0xbe, 0x05, 0xfb, 0x1f, 0xe1, 0x48, 0x1f, 0x8f, 0xa3, 0x8a, 0x03, 0x53, 0x6f, 0x59, 0x94, 0x4e, 0x81, 0x54, + 0x2a, 0x6f, 0x09, 0xc2, 0x69, 0x21, 0xc2, 0xdb, 0xdf, 0xe0, 0x1f, 0x14, 0x4b, 0xbc, 0x2e, 0x39, 0xce, 0xf3, 0x87, + 0x72, 0x44, 0x09, 0x7e, 0x19, 0xbd, 0x07, 0x3a, 0x16, 0x14, 0x5a, 0x68, 0x2a, 0x7a, 0x96, 0xaa, 0x89, 0xec, 0xcc, + 0x4a, 0xc5, 0xb4, 0xcc, 0xa8, 0x11, 0xc3, 0x6c, 0x49, 0xe3, 0xd4, 0x56, 0x36, 0x2f, 0x77, 0x55, 0x6d, 0x5c, 0xb4, + 0x03, 0x8b, 0x55, 0x60, 0x71, 0xb5, 0x72, 0xea, 0xa8, 0x26, 0xcc, 0x88, 0x63, 0x20, 0xcc, 0x8c, 0x84, 0x8a, 0x9a, + 0x66, 0x2d, 0xdb, 0x38, 0x68, 0x3d, 0x9f, 0x48, 0xeb, 0xe6, 0x35, 0x38, 0x4c, 0x17, 0x82, 0x6c, 0x6e, 0xfa, 0x14, + 0xb0, 0x9c, 0x5d, 0x39, 0x90, 0x81, 0xa1, 0xef, 0xcb, 0x4c, 0xd9, 0x2a, 0xa5, 0x75, 0x0b, 0x7e, 0xd1, 0x3d, 0xb9, + 0xb2, 0x0a, 0x75, 0x9b, 0xef, 0x8d, 0x5c, 0xa3, 0x67, 0xe9, 0xae, 0x5c, 0xa3, 0x9a, 0xb6, 0xbb, 0xd7, 0x46, 0xf7, + 0x67, 0xa5, 0xca, 0xb1, 0xb6, 0x57, 0xf9, 0x15, 0xc3, 0x75, 0x80, 0x36, 0x25, 0x9a, 0x35, 0x57, 0x39, 0x2b, 0x8a, + 0xeb, 0xf2, 0x2c, 0x81, 0x48, 0xdd, 0xb9, 0x96, 0xf4, 0xaf, 0xac, 0x46, 0x71, 0x20, 0xd7, 0xf9, 0x86, 0x4c, 0xe3, + 0xf4, 0xca, 0x8f, 0xdf, 0xc3, 0x78, 0xd5, 0xcb, 0x17, 0x77, 0x61, 0xe6, 0x73, 0xaa, 0xb8, 0x4b, 0x05, 0xc3, 0x37, + 0x06, 0x0c, 0xdf, 0x48, 0x3e, 0x5d, 0xb5, 0xc7, 0xcb, 0x97, 0x65, 0x07, 0xde, 0x75, 0xa1, 0x59, 0xc6, 0x84, 0x6f, + 0x1f, 0x63, 0x9d, 0x85, 0x4d, 0x4a, 0x16, 0x36, 0xe1, 0xce, 0x7a, 0x57, 0x8e, 0xf3, 0xc3, 0xf6, 0x5e, 0x36, 0x39, + 0xdb, 0x0f, 0xd5, 0xc6, 0xff, 0xc1, 0xbb, 0xb7, 0x8d, 0xc1, 0xe5, 0x0e, 0xdd, 0x43, 0x91, 0xac, 0x22, 0x41, 0x7e, + 0x01, 0x49, 0x07, 0x9c, 0x0c, 0x8c, 0x23, 0x07, 0x95, 0x9c, 0xd2, 0x79, 0x40, 0x4e, 0xb0, 0xc8, 0x79, 0x3a, 0x53, + 0x7d, 0xe6, 0xea, 0x9c, 0x91, 0x78, 0x09, 0xae, 0x68, 0x11, 0x6b, 0xf7, 0xea, 0x27, 0xb9, 0x96, 0x1f, 0x58, 0x12, + 0x7a, 0x39, 0x56, 0x52, 0x24, 0xf7, 0xb2, 0x82, 0xe8, 0x5c, 0xe3, 0xcd, 0x77, 0x78, 0xc2, 0x12, 0x96, 0x47, 0x34, + 0x73, 0x52, 0xb4, 0xdc, 0x35, 0x58, 0x0a, 0x01, 0x19, 0x39, 0x18, 0xfe, 0x5b, 0x75, 0xe4, 0xcf, 0x85, 0xde, 0xc0, + 0x0f, 0x34, 0xa3, 0x3c, 0x4a, 0x43, 0x48, 0x4b, 0x71, 0xc3, 0xf2, 0x48, 0xd3, 0xc1, 0xc1, 0x9e, 0x63, 0x0b, 0xb7, + 0x04, 0x1c, 0xfe, 0x36, 0xdf, 0xa0, 0xe1, 0x12, 0x4e, 0xe7, 0x54, 0x43, 0x53, 0xb4, 0xa4, 0xeb, 0x07, 0x59, 0xb8, + 0xfb, 0x81, 0xde, 0xe1, 0x04, 0x15, 0x85, 0x27, 0xa1, 0xb6, 0x27, 0x8c, 0xc6, 0xa1, 0x8d, 0x3f, 0xd0, 0x3b, 0xaf, + 0x3c, 0x2f, 0x2e, 0x8e, 0x37, 0x8b, 0x05, 0xb4, 0xd3, 0x9b, 0xc4, 0xc6, 0xd5, 0x20, 0xde, 0xb2, 0xc0, 0x69, 0xc6, + 0xa6, 0x40, 0x9c, 0x7f, 0xa1, 0x77, 0x9e, 0xec, 0x8f, 0x19, 0xa7, 0xf5, 0xd0, 0x52, 0xa3, 0xde, 0x35, 0x8a, 0xcd, + 0x65, 0x50, 0x06, 0xc5, 0x48, 0xb4, 0xbd, 0x20, 0xb5, 0x7a, 0x95, 0x79, 0x88, 0x50, 0xf1, 0xd0, 0xa9, 0xe0, 0xaf, + 0x4d, 0xd1, 0xc6, 0x6b, 0x99, 0xaf, 0x6b, 0x8d, 0x28, 0x34, 0xa8, 0x32, 0x3d, 0x66, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, + 0x82, 0x60, 0x38, 0xc2, 0xbe, 0xe6, 0xaa, 0x53, 0xef, 0x6f, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xaa, 0xda, 0x59, + 0x33, 0x07, 0xf0, 0x0e, 0x09, 0x2d, 0xbe, 0x38, 0x90, 0x59, 0xe8, 0x6c, 0xd1, 0xbf, 0x70, 0xe2, 0x2c, 0xf5, 0x14, + 0xbc, 0xc4, 0xc4, 0x22, 0x2f, 0x80, 0x0a, 0x15, 0x7d, 0xc9, 0x04, 0x40, 0x38, 0xc3, 0xbe, 0x21, 0x35, 0x33, 0x21, + 0x35, 0x5d, 0x03, 0xe3, 0x3b, 0xa4, 0x24, 0x15, 0xc8, 0x10, 0x4a, 0xa4, 0x10, 0x7a, 0x6a, 0x71, 0x15, 0x09, 0x99, + 0x0b, 0x5a, 0x9e, 0x9f, 0x93, 0x6b, 0x9e, 0xd5, 0xc0, 0x72, 0x44, 0x3f, 0xa8, 0xf0, 0x60, 0x4a, 0x54, 0x56, 0x28, + 0xca, 0x63, 0xd9, 0x3a, 0xbd, 0xd5, 0x49, 0x5d, 0x3d, 0x2d, 0xa2, 0x51, 0xe2, 0x44, 0x68, 0x99, 0x38, 0x11, 0xce, + 0x20, 0x1d, 0x31, 0x2d, 0x4a, 0xf8, 0xa9, 0xb9, 0x1a, 0xb5, 0x64, 0xe5, 0xed, 0x67, 0xfc, 0x40, 0x99, 0xe7, 0x90, + 0xa2, 0x89, 0x13, 0xcd, 0x53, 0x12, 0x47, 0x1c, 0xb6, 0x33, 0x96, 0xed, 0x1b, 0x95, 0xa0, 0xa3, 0x00, 0xfb, 0x0b, + 0x77, 0x96, 0xc6, 0x2c, 0xcc, 0xd3, 0xdc, 0xea, 0xcc, 0x9f, 0x0a, 0xf6, 0x55, 0x39, 0xa4, 0x4e, 0x4e, 0xd6, 0x24, + 0xce, 0xfd, 0xa9, 0x96, 0x3f, 0x2f, 0x68, 0x76, 0x77, 0x4e, 0x21, 0xd5, 0x39, 0x85, 0xd3, 0xbe, 0xd5, 0x32, 0x54, + 0x69, 0xea, 0xc3, 0x4c, 0x28, 0x2b, 0x45, 0xfd, 0x14, 0xe0, 0xfa, 0x19, 0xc1, 0x42, 0x44, 0x1b, 0x0d, 0x47, 0x8c, + 0xdc, 0x2d, 0x74, 0xe7, 0xe9, 0x49, 0xda, 0x63, 0xe0, 0x5f, 0xab, 0x30, 0xad, 0x82, 0x05, 0x38, 0x35, 0x4f, 0xa4, + 0x8e, 0xf2, 0x8b, 0x75, 0xaf, 0x0c, 0x14, 0x41, 0xf8, 0x2e, 0xdb, 0x3d, 0xd5, 0x6d, 0x49, 0xb3, 0xbb, 0xa7, 0x5a, + 0x0b, 0xfa, 0x89, 0x84, 0x1f, 0xac, 0xc6, 0x29, 0x8f, 0x2f, 0xb3, 0xa2, 0x40, 0x05, 0x80, 0xf7, 0xe7, 0x9e, 0xe3, + 0xfc, 0x59, 0xa5, 0x0c, 0xba, 0x10, 0x8b, 0x3d, 0x8f, 0x53, 0xcd, 0xc4, 0xab, 0xf1, 0xff, 0xbc, 0x31, 0xfe, 0x9f, + 0x8d, 0x33, 0xa7, 0x60, 0x1a, 0x4d, 0x13, 0x1a, 0x6a, 0xd6, 0x89, 0x24, 0x01, 0x0a, 0xbd, 0x2d, 0xe1, 0xe4, 0xc3, + 0xd8, 0x03, 0x8d, 0x6b, 0x39, 0x49, 0x13, 0xde, 0x9c, 0xf8, 0x33, 0x16, 0xdf, 0x79, 0x0b, 0xd6, 0x9c, 0xa5, 0x49, + 0x9a, 0xcf, 0xfd, 0x80, 0xe2, 0xfc, 0x2e, 0xe7, 0x74, 0xd6, 0x5c, 0x30, 0xfc, 0x82, 0xc6, 0xd7, 0x94, 0xb3, 0xc0, + 0xc7, 0xf6, 0x69, 0xc6, 0xfc, 0xd8, 0x7a, 0xed, 0x67, 0x59, 0x7a, 0x63, 0xe3, 0x77, 0xe9, 0x55, 0xca, 0x53, 0xfc, + 0xe6, 0xf6, 0x6e, 0x4a, 0x13, 0xfc, 0xed, 0xd5, 0x22, 0xe1, 0x0b, 0x9c, 0xfb, 0x49, 0xde, 0xcc, 0x69, 0xc6, 0x26, + 0xbd, 0x20, 0x8d, 0xd3, 0xac, 0x09, 0x19, 0xdb, 0x33, 0xea, 0xc5, 0x6c, 0x1a, 0x71, 0x2b, 0xf4, 0xb3, 0x0f, 0xbd, + 0x66, 0x73, 0x9e, 0xb1, 0x99, 0x9f, 0xdd, 0x35, 0x45, 0x0d, 0xef, 0xf3, 0xf6, 0xa1, 0xff, 0x64, 0x72, 0xd4, 0xe3, + 0x99, 0x9f, 0xe4, 0x0c, 0x96, 0xc9, 0xf3, 0xe3, 0xd8, 0x3a, 0x3c, 0x6e, 0xcf, 0xf2, 0x3d, 0x19, 0xc8, 0xf3, 0x13, + 0x5e, 0x8c, 0xf1, 0x5b, 0x80, 0xdb, 0xbd, 0xe2, 0x09, 0xbe, 0x5a, 0x70, 0x9e, 0x26, 0xcb, 0x60, 0x91, 0xe5, 0x69, + 0xe6, 0xcd, 0x53, 0x96, 0x70, 0x9a, 0xf5, 0xae, 0xd2, 0x2c, 0xa4, 0x59, 0x33, 0xf3, 0x43, 0xb6, 0xc8, 0xbd, 0xa3, + 0xf9, 0x6d, 0x0f, 0x34, 0x8b, 0x69, 0x96, 0x2e, 0x92, 0x50, 0x8d, 0xc5, 0x92, 0x88, 0x66, 0x8c, 0x9b, 0x2f, 0xc4, + 0x25, 0x26, 0x5e, 0xcc, 0x12, 0xea, 0x67, 0xcd, 0x29, 0x34, 0x06, 0xb3, 0xa8, 0x1d, 0xd2, 0x29, 0xce, 0xa6, 0x57, + 0xbe, 0xd3, 0xe9, 0x3e, 0xc6, 0xfa, 0x7f, 0xf7, 0x18, 0x59, 0xed, 0xed, 0xc5, 0x9d, 0x76, 0xfb, 0x0f, 0xa8, 0xb7, + 0x36, 0x8a, 0x00, 0xc8, 0xeb, 0xcc, 0x6f, 0xad, 0x3c, 0x85, 0x8c, 0xb6, 0x6d, 0x2d, 0x7b, 0x73, 0x3f, 0x84, 0x7c, + 0x60, 0xaf, 0x3b, 0xbf, 0x2d, 0x60, 0x76, 0x9e, 0x4c, 0x31, 0x55, 0x93, 0x54, 0x4f, 0xcb, 0x5f, 0x0b, 0xf1, 0xc9, + 0x76, 0x88, 0xbb, 0x1a, 0xe2, 0x0a, 0xeb, 0xcd, 0x70, 0x91, 0x89, 0xd8, 0xaa, 0xd7, 0xc9, 0x25, 0x20, 0x51, 0x7a, + 0x4d, 0x33, 0x0d, 0x87, 0x78, 0xf8, 0xd5, 0x60, 0x74, 0xb7, 0x83, 0x71, 0xf2, 0x31, 0x30, 0xb2, 0x24, 0x5c, 0xd6, + 0xd7, 0xb5, 0x93, 0xd1, 0x59, 0x2f, 0xa2, 0x40, 0x4f, 0x5e, 0x17, 0x7e, 0xdf, 0xb0, 0x90, 0x47, 0xf2, 0xa7, 0x20, + 0xe7, 0x1b, 0xf9, 0xee, 0xb8, 0xdd, 0x96, 0xcf, 0x39, 0xfb, 0x85, 0x7a, 0x1d, 0x17, 0x2a, 0x14, 0x63, 0xfc, 0x43, + 0x79, 0x96, 0xb7, 0xce, 0x3d, 0xf1, 0x9f, 0xcd, 0x43, 0xbe, 0x46, 0x8a, 0x62, 0x75, 0x24, 0x1a, 0x67, 0x5a, 0x56, + 0x4a, 0xe1, 0x03, 0x6e, 0x3b, 0xc1, 0x1d, 0x09, 0x1b, 0x94, 0x87, 0x38, 0xd9, 0xf0, 0xcf, 0x32, 0xef, 0xc2, 0x83, + 0x48, 0x87, 0x91, 0x6a, 0x98, 0xf6, 0xb2, 0x01, 0x69, 0xf7, 0xb2, 0x66, 0x13, 0x39, 0x29, 0x49, 0x46, 0x99, 0x4a, + 0xce, 0x73, 0xd8, 0x30, 0x15, 0xc6, 0x76, 0x8e, 0xbc, 0x14, 0x4e, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0x89, 0xd3, + 0x1a, 0x3f, 0x70, 0x55, 0x01, 0xe7, 0x06, 0x27, 0x4f, 0xf5, 0xd5, 0x2e, 0x89, 0xe6, 0x15, 0x71, 0x1a, 0x08, 0xcc, + 0xb9, 0x73, 0x9f, 0x47, 0xe0, 0xa5, 0x28, 0xc5, 0x4f, 0x95, 0xc2, 0x64, 0xb7, 0x6c, 0x34, 0x4c, 0xca, 0xfc, 0x36, + 0xc8, 0xe3, 0x4b, 0x0a, 0xe8, 0xe5, 0x8e, 0x13, 0x61, 0x31, 0x95, 0xfd, 0x7f, 0xcb, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, + 0x09, 0xe2, 0x45, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xff, 0x6a, 0xd6, 0x12, 0x4d, 0xa0, 0x77, 0x91, 0xcd, 0x03, + 0x15, 0xe1, 0x06, 0x95, 0xf2, 0xb9, 0x29, 0x9e, 0xab, 0xb6, 0xfa, 0x52, 0x09, 0x36, 0x71, 0xa0, 0xa5, 0xbb, 0x48, + 0xd8, 0xcf, 0x0b, 0x7a, 0xc9, 0x42, 0xe3, 0xdc, 0x2e, 0x4d, 0x82, 0x34, 0xa4, 0xdf, 0xbe, 0xfb, 0x0a, 0xb2, 0xdd, + 0xd3, 0x04, 0x48, 0x2c, 0x91, 0xfe, 0x2e, 0x9c, 0x93, 0xc4, 0x0d, 0xe9, 0x35, 0x0b, 0xe8, 0x70, 0xbc, 0xbf, 0xdc, + 0x5a, 0x51, 0xbe, 0x46, 0x45, 0x6b, 0x2c, 0x92, 0xfe, 0x04, 0x94, 0xe3, 0xfd, 0xe5, 0x1d, 0x2f, 0x5a, 0xfb, 0xcb, + 0xc4, 0x0d, 0xd3, 0x99, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xfb, 0x4b, 0x06, 0x3f, 0x78, 0x31, 0x2e, 0xaa, 0x44, 0xd1, + 0x12, 0x22, 0x63, 0x0a, 0x0a, 0x77, 0x1d, 0xe4, 0xfe, 0x94, 0xb2, 0x44, 0x14, 0xdd, 0xd7, 0x33, 0xd5, 0xbd, 0x02, + 0x92, 0xbf, 0x22, 0xd2, 0x60, 0xd6, 0xe6, 0xf2, 0xf5, 0x43, 0xcd, 0x65, 0x9a, 0x70, 0x26, 0xd2, 0xe2, 0x75, 0x38, + 0x27, 0xf2, 0xf3, 0xcb, 0x40, 0x9e, 0x43, 0xcd, 0xab, 0x53, 0x17, 0xbe, 0x40, 0xac, 0xb4, 0x80, 0x69, 0x26, 0x8c, + 0x7d, 0xba, 0xfb, 0xa0, 0x64, 0x72, 0x9f, 0xf1, 0x57, 0x52, 0x55, 0x9e, 0x2e, 0xb2, 0x00, 0x62, 0xbd, 0x4a, 0xa5, + 0xd8, 0xf4, 0x8a, 0xd9, 0x42, 0x7f, 0xb3, 0x31, 0x37, 0x92, 0x6c, 0x39, 0x66, 0xe6, 0x9d, 0x1d, 0x54, 0xc4, 0x13, + 0xe5, 0x59, 0x18, 0xa5, 0x3f, 0xe8, 0x29, 0x81, 0x42, 0x14, 0x8a, 0x7c, 0x51, 0x27, 0x23, 0x83, 0xac, 0xc2, 0x39, + 0x21, 0x84, 0xb9, 0x2c, 0x14, 0x81, 0x3c, 0x50, 0x2c, 0x9a, 0x1d, 0x88, 0x0c, 0xb1, 0xb0, 0xd2, 0xf0, 0x98, 0xc2, + 0xf3, 0x6a, 0xf5, 0x57, 0xee, 0xc8, 0xba, 0xd2, 0xa9, 0x02, 0x3a, 0x18, 0xc3, 0xf2, 0xa5, 0x97, 0xe1, 0xb2, 0x4b, + 0x0f, 0x2a, 0x15, 0xbd, 0x54, 0xa0, 0x4f, 0x22, 0x8b, 0x68, 0x74, 0x9e, 0x4a, 0x15, 0x21, 0x45, 0xd8, 0x7c, 0x5d, + 0x1e, 0xe0, 0xaf, 0xe1, 0xbb, 0xbd, 0xb6, 0x2c, 0xd2, 0x9e, 0x4a, 0xd7, 0x4b, 0xf3, 0x34, 0xe3, 0x8e, 0x13, 0x61, + 0x1f, 0x91, 0x41, 0x24, 0xa8, 0xb6, 0xef, 0x8b, 0x7f, 0x86, 0xcd, 0x8e, 0xd7, 0x29, 0x3d, 0x21, 0xb5, 0x73, 0xd5, + 0x32, 0xcf, 0x4c, 0x9d, 0xcd, 0x05, 0x70, 0x71, 0xf9, 0x5b, 0xce, 0xa7, 0x7a, 0x2e, 0xa7, 0x85, 0x15, 0xe7, 0x92, + 0x52, 0xdf, 0xa9, 0x01, 0x21, 0xe2, 0x6e, 0x3b, 0x86, 0x42, 0x45, 0x35, 0xef, 0x72, 0x17, 0x8f, 0xa5, 0xb6, 0x73, + 0x69, 0x90, 0xf1, 0x98, 0x69, 0x7f, 0x5d, 0x9d, 0xc0, 0x0a, 0x85, 0x11, 0x83, 0x05, 0x6c, 0xab, 0x26, 0x61, 0xb9, + 0x23, 0xc9, 0x56, 0x2a, 0x75, 0xe5, 0x23, 0x95, 0xba, 0xd6, 0xf6, 0x2a, 0x22, 0xeb, 0x71, 0x1b, 0x60, 0xe0, 0x01, + 0xc8, 0xb9, 0x9e, 0x02, 0x30, 0x93, 0x09, 0x15, 0x17, 0xd3, 0x48, 0xd6, 0x82, 0x97, 0x52, 0x8d, 0xf7, 0xec, 0xb7, + 0x6f, 0xce, 0xdf, 0xdb, 0x18, 0xee, 0x33, 0xa3, 0x59, 0xee, 0x2d, 0x6d, 0x95, 0x4c, 0xd8, 0x84, 0xc0, 0xb4, 0xed, + 0xd9, 0xfe, 0x1c, 0xce, 0x66, 0x0b, 0xee, 0xd9, 0xba, 0x6d, 0xde, 0xdc, 0xdc, 0x34, 0xe1, 0xe8, 0x58, 0x73, 0x91, + 0xc5, 0x92, 0xaf, 0x84, 0x76, 0x51, 0x20, 0x97, 0x47, 0x34, 0x29, 0x6f, 0x3c, 0x4a, 0x63, 0xea, 0xc6, 0xe9, 0x54, + 0x1e, 0x7b, 0x5d, 0xf7, 0x43, 0xc4, 0xe3, 0xbe, 0xb8, 0xc9, 0x6b, 0xd0, 0xe7, 0xf2, 0x0e, 0x35, 0x9e, 0xc1, 0xcf, + 0x01, 0x44, 0xa9, 0xfa, 0x2d, 0x1e, 0x89, 0x87, 0x73, 0xd8, 0x36, 0xe2, 0x69, 0x7f, 0xb9, 0x41, 0x64, 0x43, 0xe8, + 0x22, 0x1a, 0xc8, 0xa9, 0xe5, 0xa2, 0xd6, 0xd8, 0x8b, 0xc7, 0xe3, 0xa2, 0xdf, 0x82, 0xbe, 0x5a, 0xba, 0xdf, 0xab, + 0x34, 0xbc, 0xd3, 0xed, 0x4b, 0xc2, 0x83, 0x1b, 0x9d, 0x12, 0x32, 0x80, 0x2e, 0x60, 0xdc, 0x70, 0x20, 0x70, 0xa6, + 0x78, 0xe5, 0xa8, 0x7a, 0x28, 0x2e, 0x2c, 0xe0, 0x8c, 0x05, 0x94, 0x00, 0x5d, 0x42, 0xe7, 0x61, 0xd9, 0x40, 0x6c, + 0x6b, 0x59, 0xb4, 0x0b, 0x40, 0x59, 0xb1, 0xda, 0x2e, 0xd2, 0x9f, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, 0x1f, + 0x23, 0xf8, 0x57, 0x00, 0xde, 0x6f, 0x49, 0x34, 0x8d, 0xcd, 0xdb, 0x65, 0xe4, 0xbd, 0x0f, 0x25, 0x32, 0x47, 0x09, + 0xc7, 0x6f, 0x39, 0xfe, 0x30, 0x16, 0x55, 0xb5, 0x3a, 0x00, 0x7a, 0x2a, 0xa8, 0x4d, 0x6d, 0xad, 0xf7, 0x05, 0x69, + 0x1c, 0xfb, 0xf3, 0x9c, 0x7a, 0xfa, 0x87, 0xd2, 0x0c, 0x40, 0xc1, 0xd8, 0x54, 0xc5, 0x54, 0x82, 0xd3, 0x19, 0x28, + 0x6c, 0x9b, 0x7a, 0xe2, 0xb5, 0x9f, 0x39, 0xcd, 0x66, 0xd0, 0xbc, 0x9a, 0xa2, 0x82, 0x47, 0x4b, 0x53, 0xaf, 0x78, + 0xd4, 0x6e, 0xf7, 0x20, 0x1b, 0xb5, 0xe9, 0xc7, 0x6c, 0x9a, 0x78, 0x31, 0x9d, 0xf0, 0x82, 0xc3, 0x31, 0xc1, 0xa5, + 0x56, 0xe4, 0xdc, 0xee, 0x71, 0x46, 0x67, 0x96, 0x0b, 0x7f, 0xef, 0x1f, 0xb8, 0xe0, 0xa1, 0x97, 0xf0, 0xa8, 0x29, + 0xb2, 0x9e, 0xe1, 0xcc, 0x06, 0x8f, 0x6a, 0xcf, 0x4b, 0x63, 0xa0, 0x80, 0x82, 0x92, 0x5b, 0xf0, 0xcc, 0xe2, 0x11, + 0xe6, 0x99, 0x59, 0x2f, 0x41, 0xcb, 0x8d, 0x19, 0x6c, 0xea, 0x5a, 0x87, 0xa8, 0xc8, 0x85, 0x69, 0xb2, 0x59, 0x59, + 0x2b, 0xac, 0xf5, 0xa7, 0x0d, 0xf4, 0x19, 0xaa, 0x75, 0x21, 0x5d, 0xfb, 0x4b, 0xd9, 0xe2, 0x21, 0xc8, 0xac, 0x29, + 0xfd, 0xd8, 0x6c, 0x81, 0x0a, 0x96, 0xcc, 0x17, 0x7c, 0x24, 0xc2, 0x0a, 0x19, 0x1c, 0x50, 0xb9, 0xc0, 0x46, 0x09, + 0xe0, 0xe0, 0x62, 0x29, 0x81, 0x09, 0xfc, 0x38, 0x70, 0x00, 0x22, 0xab, 0x69, 0x9d, 0x64, 0x74, 0x86, 0x7a, 0x33, + 0x96, 0x34, 0xe5, 0xbb, 0x63, 0x43, 0x31, 0x74, 0x1f, 0xc3, 0x53, 0xe1, 0x8a, 0xde, 0xb0, 0xc8, 0x1e, 0xde, 0x82, + 0xcb, 0xf1, 0x45, 0x51, 0xf4, 0x32, 0xee, 0x8c, 0x5e, 0x39, 0xe8, 0x02, 0x7f, 0x65, 0xdc, 0x8f, 0x63, 0xeb, 0x9d, + 0x64, 0xe3, 0x2e, 0xda, 0x51, 0xc5, 0xdc, 0x0b, 0xa2, 0xda, 0x57, 0x04, 0x2a, 0xbe, 0x70, 0x6c, 0x9a, 0xcf, 0x9b, + 0x92, 0xe5, 0x35, 0x05, 0xc9, 0xda, 0xd0, 0x14, 0x29, 0x5f, 0x39, 0xa5, 0x4b, 0xc1, 0xcd, 0xd4, 0x21, 0x19, 0xe9, + 0xce, 0xb9, 0x28, 0x0f, 0x55, 0xa9, 0x67, 0xf3, 0x18, 0x15, 0xaa, 0xb1, 0x9b, 0xf1, 0x69, 0x9d, 0x35, 0x82, 0x72, + 0x51, 0x5e, 0x22, 0xe8, 0xc7, 0x31, 0x0c, 0x38, 0xd6, 0x1a, 0x89, 0x79, 0xeb, 0xca, 0x88, 0x5f, 0x38, 0xa8, 0x50, + 0xfb, 0xf4, 0xa9, 0x50, 0xea, 0x8d, 0x9b, 0x0b, 0xf7, 0xb8, 0x0e, 0xd7, 0x49, 0x11, 0xcd, 0x20, 0xe1, 0xa0, 0x96, + 0x98, 0xde, 0xab, 0x58, 0x9b, 0x34, 0x09, 0x2c, 0x31, 0x21, 0x62, 0x67, 0x49, 0x68, 0x5b, 0x7f, 0x0a, 0x62, 0x16, + 0x7c, 0x20, 0xf6, 0xfe, 0xd2, 0x41, 0x9b, 0xe7, 0x4e, 0x05, 0x57, 0xd0, 0x7c, 0x1e, 0xd5, 0x43, 0x19, 0x99, 0x6b, + 0xb0, 0x70, 0x79, 0x31, 0x91, 0x3d, 0x00, 0xbd, 0xa9, 0xdf, 0x92, 0xe3, 0x0c, 0xc6, 0xc5, 0x65, 0x75, 0xdf, 0x58, + 0x05, 0x05, 0xa0, 0x59, 0x96, 0x5b, 0x82, 0xa8, 0x88, 0xfd, 0x51, 0x4a, 0xb3, 0x2d, 0xc9, 0xd4, 0x00, 0x4e, 0xae, + 0xf8, 0x9b, 0x6d, 0xfd, 0xa9, 0x2c, 0xa3, 0xa5, 0x4f, 0x49, 0x24, 0xc5, 0x10, 0x1b, 0xc6, 0x02, 0x47, 0x82, 0x1b, + 0x52, 0xee, 0xb3, 0x58, 0x36, 0xe9, 0x69, 0x17, 0xc8, 0xda, 0x8c, 0x56, 0xab, 0xbc, 0x3e, 0x17, 0x56, 0xc7, 0xa0, + 0x98, 0x59, 0xbf, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0xa4, 0x19, 0x9c, 0xad, 0x66, 0x28, 0xdf, 0x59, 0x7f, 0x0a, + 0xc4, 0xb1, 0x2d, 0x00, 0x30, 0x55, 0x00, 0x42, 0xda, 0x80, 0x3c, 0x96, 0xe4, 0xf8, 0x24, 0x75, 0xb9, 0x9f, 0x4d, + 0x29, 0x5f, 0x43, 0xac, 0x2f, 0xb3, 0x84, 0x7b, 0x3a, 0x45, 0x60, 0x03, 0xda, 0xa0, 0x0e, 0x2d, 0x28, 0xd1, 0xc5, + 0x10, 0xf4, 0x60, 0xb2, 0x55, 0x9d, 0x8e, 0x10, 0xc8, 0x5b, 0xb1, 0x38, 0x52, 0xc2, 0xa4, 0x42, 0xc2, 0x48, 0x4e, + 0x60, 0x89, 0xb1, 0x04, 0x88, 0x85, 0x6d, 0x0d, 0x25, 0xe4, 0x34, 0x94, 0x30, 0x93, 0x4c, 0xb4, 0x4a, 0x8b, 0x7e, + 0x4b, 0xd6, 0x96, 0x22, 0x40, 0x56, 0x02, 0x24, 0x88, 0x7d, 0x5a, 0xe1, 0x00, 0x32, 0xcb, 0x4d, 0x3c, 0x84, 0xec, + 0xba, 0x24, 0x36, 0x71, 0x80, 0x6d, 0xd0, 0x8f, 0xfd, 0x2b, 0x1a, 0x0f, 0xf6, 0x97, 0xd9, 0x6a, 0xd5, 0x2e, 0xfa, + 0x2d, 0xf9, 0x68, 0xf5, 0x05, 0xdf, 0x90, 0x97, 0x8e, 0x8a, 0x25, 0x86, 0x53, 0xa1, 0x90, 0x6f, 0xab, 0x13, 0xcd, + 0x3c, 0xd5, 0x41, 0x61, 0x5b, 0x22, 0xc5, 0x45, 0x54, 0x2a, 0xf5, 0xa8, 0xc2, 0xb6, 0x58, 0xb8, 0x59, 0x96, 0x73, + 0x3a, 0x87, 0xd2, 0x68, 0xb5, 0xea, 0x14, 0xb6, 0x35, 0x63, 0x09, 0x3c, 0x65, 0xab, 0x95, 0x38, 0x70, 0x39, 0x63, + 0x89, 0xd3, 0x06, 0xb2, 0xb5, 0xad, 0x99, 0x7f, 0x2b, 0x26, 0xac, 0xdf, 0xf8, 0xb7, 0x4e, 0x47, 0xbd, 0x72, 0x4b, + 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8a, 0xfa, 0x6a, 0x45, 0x43, 0xbc, 0x90, 0x47, 0xc9, 0x88, 0x13, 0x12, 0x7f, 0xfb, + 0x8a, 0x86, 0x7a, 0x45, 0x17, 0x3b, 0x56, 0x74, 0x71, 0xcf, 0x8a, 0x06, 0x6a, 0xf5, 0xac, 0x12, 0x77, 0xe9, 0x6a, + 0xd5, 0x69, 0x57, 0xd8, 0xeb, 0xb7, 0x42, 0x76, 0x0d, 0xab, 0x01, 0xda, 0x21, 0x67, 0x33, 0xba, 0x9d, 0x28, 0xeb, + 0x28, 0xa6, 0x9f, 0x84, 0xc9, 0x0a, 0x0b, 0x59, 0x1d, 0x0b, 0x26, 0x5d, 0x97, 0x51, 0xcf, 0xdf, 0x93, 0xb2, 0x19, + 0xe0, 0x21, 0x07, 0x3c, 0x44, 0xfa, 0x12, 0x52, 0xc7, 0x7e, 0x6f, 0x63, 0xdb, 0xb2, 0x35, 0x59, 0x8f, 0x8b, 0x4b, + 0x90, 0x11, 0x62, 0x7e, 0x0f, 0xa2, 0x45, 0xa8, 0x6d, 0x0f, 0x76, 0xd3, 0x1c, 0x24, 0x28, 0xdc, 0xa4, 0x59, 0x68, + 0x7b, 0xb2, 0xea, 0x27, 0xa1, 0x6a, 0xc6, 0x12, 0x95, 0xee, 0xb6, 0x93, 0xd6, 0xaa, 0xf7, 0x26, 0xc5, 0x75, 0x8f, + 0x8f, 0x65, 0x8d, 0xb9, 0xcf, 0x39, 0xcd, 0x12, 0x45, 0xb9, 0xb6, 0xfd, 0x1f, 0x82, 0x0a, 0xb7, 0xf0, 0x95, 0x40, + 0x2f, 0x80, 0x26, 0x40, 0xa5, 0xe7, 0x2b, 0x9e, 0x2f, 0xc5, 0xd3, 0x5e, 0xa5, 0xe0, 0xde, 0x21, 0xd3, 0xd6, 0x90, + 0x45, 0x60, 0xfa, 0x2c, 0x66, 0x34, 0xbc, 0x14, 0x0c, 0x7a, 0x18, 0x8f, 0x95, 0xc2, 0xba, 0x26, 0xee, 0xaa, 0x06, + 0xd8, 0xfe, 0x71, 0xd1, 0x7d, 0x7c, 0x74, 0x66, 0x63, 0xc9, 0xe3, 0xd3, 0xc9, 0xc4, 0x46, 0x85, 0xf5, 0xb0, 0x66, + 0x9d, 0xa3, 0x1f, 0x17, 0x5f, 0x3e, 0x6f, 0x7f, 0x59, 0x36, 0x4e, 0x80, 0x88, 0x54, 0x86, 0x85, 0x16, 0x55, 0x06, + 0xbc, 0x7a, 0x46, 0x13, 0x3f, 0xd9, 0x3d, 0x9d, 0x91, 0x39, 0x9d, 0x7c, 0x4e, 0x69, 0x08, 0xc4, 0x89, 0x37, 0x4a, + 0x2f, 0x63, 0x7a, 0x4d, 0xf5, 0xe5, 0x8f, 0x5b, 0x06, 0xdb, 0xd2, 0x22, 0x48, 0x17, 0x09, 0x57, 0xa9, 0x26, 0x8a, + 0xd5, 0x1a, 0x53, 0x1a, 0x8b, 0x39, 0x98, 0x26, 0xc4, 0x9d, 0x94, 0x73, 0x75, 0xe9, 0x55, 0x8c, 0xb1, 0x6d, 0x00, + 0xb0, 0x13, 0xb2, 0xe1, 0x8e, 0x72, 0xaf, 0x8d, 0xdb, 0xbb, 0x60, 0xc3, 0x1d, 0xe4, 0xd9, 0xf6, 0x85, 0xc6, 0x93, + 0xf0, 0x16, 0xd7, 0x6e, 0xec, 0xd8, 0x89, 0xaf, 0x8f, 0x62, 0xe0, 0x2a, 0x83, 0xce, 0x12, 0x9a, 0xe7, 0x3b, 0x11, + 0x50, 0x2e, 0x22, 0xb6, 0xab, 0xda, 0xf6, 0x8e, 0x5e, 0x70, 0x1b, 0xc3, 0x0e, 0x13, 0x00, 0x97, 0x31, 0x6b, 0x55, + 0x8b, 0x4e, 0x26, 0x34, 0x28, 0x9d, 0xed, 0x10, 0x7d, 0x9c, 0xb0, 0x98, 0x43, 0x10, 0x4e, 0x44, 0xc7, 0xec, 0xd7, + 0x69, 0x42, 0x6d, 0xa4, 0xf3, 0x69, 0x15, 0xfc, 0x4a, 0xfe, 0x6f, 0x87, 0x47, 0xf6, 0x58, 0x87, 0x45, 0x8d, 0xb2, + 0x5a, 0x69, 0x5f, 0x50, 0xad, 0xbc, 0x8e, 0xc8, 0x54, 0x38, 0x7b, 0x76, 0x6d, 0xa0, 0x87, 0x6d, 0x93, 0x65, 0xe7, + 0xcb, 0xe3, 0x4e, 0xbb, 0xb0, 0xb1, 0x0d, 0xdd, 0x3d, 0x74, 0x97, 0x88, 0x56, 0x87, 0xd0, 0x6a, 0x91, 0x7c, 0x4a, + 0xbb, 0x6e, 0xe7, 0x49, 0xc7, 0xc6, 0xf2, 0x22, 0x07, 0x54, 0x94, 0xcc, 0x20, 0x00, 0xf7, 0xf3, 0x6f, 0x9e, 0x4a, + 0xbd, 0xf3, 0x87, 0xc1, 0xf3, 0xa8, 0xd3, 0xb6, 0xb1, 0x9d, 0xf3, 0x74, 0xfe, 0x09, 0x53, 0x38, 0xb4, 0xb1, 0x1d, + 0xc4, 0x69, 0x4e, 0xcd, 0x39, 0x48, 0x75, 0xf6, 0xb7, 0x4f, 0x42, 0x42, 0x34, 0xcf, 0x68, 0x9e, 0x5b, 0x66, 0xff, + 0x8a, 0x94, 0x3e, 0xc2, 0x30, 0xb7, 0x52, 0x5c, 0x4e, 0xb9, 0xc0, 0x8b, 0xbc, 0x63, 0xc1, 0xa4, 0x2a, 0x59, 0xb6, + 0x41, 0x6c, 0x42, 0x04, 0x94, 0x8c, 0x4d, 0x6a, 0x57, 0x1f, 0x1d, 0x79, 0xcb, 0xd6, 0x93, 0x03, 0xcb, 0xa8, 0xfc, + 0xe6, 0x00, 0xb5, 0x92, 0x19, 0x4b, 0x2e, 0xb7, 0x94, 0xfa, 0xb7, 0x5b, 0x4a, 0x41, 0x65, 0x2b, 0xa1, 0x53, 0xf7, + 0xff, 0x7c, 0x1c, 0xeb, 0x95, 0xe2, 0x63, 0x82, 0x18, 0x0a, 0xe7, 0xe6, 0x47, 0x20, 0x35, 0x96, 0x41, 0xf4, 0xf0, + 0xeb, 0x87, 0x83, 0x92, 0x4f, 0x19, 0xae, 0xec, 0xe5, 0xb7, 0xcd, 0x10, 0x4a, 0x9b, 0x10, 0x41, 0x88, 0x3f, 0x69, + 0xae, 0xf4, 0xf6, 0xe3, 0x04, 0x67, 0x68, 0x55, 0xbf, 0x61, 0xe9, 0xd5, 0x3d, 0x02, 0xeb, 0x6b, 0xbf, 0xa5, 0x58, + 0x29, 0x3e, 0xe5, 0xfa, 0x07, 0x31, 0x9b, 0x55, 0x24, 0xb0, 0x09, 0xa6, 0xd0, 0x78, 0x20, 0x9d, 0xcc, 0xec, 0x44, + 0xaa, 0x3e, 0x97, 0x70, 0x48, 0x16, 0xee, 0x21, 0x59, 0x64, 0xf4, 0x32, 0x4e, 0x6f, 0xd6, 0x2f, 0x56, 0xdb, 0x5d, + 0x39, 0x62, 0xd3, 0xc8, 0x38, 0xf9, 0x46, 0x49, 0xb9, 0x08, 0xf7, 0x0e, 0x50, 0xfc, 0xcb, 0x3f, 0xbb, 0xee, 0xbf, + 0xfc, 0xf3, 0x47, 0xab, 0x42, 0xf7, 0xc5, 0x18, 0xf3, 0xaa, 0xdb, 0xdd, 0xbb, 0x6b, 0xfb, 0x48, 0x75, 0x9c, 0x6f, + 0xaf, 0xb3, 0xb1, 0x08, 0xf0, 0x7e, 0x63, 0x09, 0x36, 0x0a, 0xe5, 0xee, 0xb3, 0x7e, 0x0d, 0x60, 0x30, 0xaf, 0x8f, + 0x42, 0x06, 0x95, 0x7e, 0x13, 0x68, 0x63, 0xe4, 0x3d, 0x68, 0x45, 0x7e, 0x3d, 0x86, 0x3f, 0x36, 0x87, 0xdf, 0x08, + 0xbe, 0xf2, 0x4f, 0xc4, 0xe3, 0x71, 0x99, 0xe2, 0x68, 0x36, 0x85, 0x0b, 0x14, 0x86, 0x1b, 0x25, 0x4a, 0xf1, 0xf0, + 0xda, 0x68, 0x20, 0x0e, 0x68, 0x92, 0x78, 0xfc, 0x0a, 0x6e, 0x4d, 0xea, 0x5f, 0x65, 0xda, 0xc1, 0x7b, 0x8f, 0x70, + 0x80, 0x2e, 0xea, 0xb3, 0x12, 0x9d, 0x6e, 0x48, 0x06, 0x28, 0x05, 0x73, 0x03, 0xc0, 0xc4, 0xf1, 0x58, 0x59, 0x9b, + 0x67, 0xd2, 0x0d, 0xe3, 0xad, 0x93, 0xb6, 0x72, 0xcf, 0xd4, 0x90, 0x8e, 0xad, 0xf7, 0x02, 0x5f, 0xa2, 0x32, 0xad, + 0xac, 0x7b, 0xe1, 0xea, 0x02, 0x3b, 0xa2, 0x64, 0x3f, 0xd7, 0x7e, 0x7c, 0xfd, 0x30, 0xc6, 0xb7, 0x5b, 0xa0, 0xae, + 0xac, 0xd5, 0x3f, 0x5a, 0x25, 0x58, 0x35, 0x57, 0xdb, 0xf4, 0x81, 0x1b, 0x9f, 0xd3, 0xec, 0x32, 0x82, 0x2c, 0xab, + 0xec, 0x23, 0xcc, 0x09, 0x56, 0x1a, 0x53, 0xf1, 0x97, 0x11, 0x75, 0x47, 0xf5, 0x3f, 0x88, 0x53, 0x31, 0x48, 0x91, + 0x84, 0xa1, 0x8c, 0x45, 0xf8, 0xff, 0x7c, 0xeb, 0x3f, 0x0c, 0xdf, 0xba, 0x7f, 0x88, 0xda, 0x01, 0xec, 0x4f, 0x5e, + 0xc8, 0xff, 0xd8, 0xec, 0x2e, 0x17, 0xec, 0xee, 0x57, 0x30, 0xba, 0xfc, 0x1f, 0xc3, 0xe8, 0x84, 0x8d, 0xac, 0x39, + 0x9d, 0xba, 0x78, 0xc7, 0x7c, 0xef, 0xdf, 0xf8, 0x77, 0xd5, 0xbe, 0x8a, 0xc7, 0xa7, 0x37, 0xfe, 0x5d, 0xb5, 0x08, + 0xbb, 0xd9, 0xc5, 0x7a, 0x1f, 0x43, 0xfb, 0xcd, 0x6b, 0xdb, 0xb3, 0xdf, 0x7c, 0xf9, 0xa5, 0x8d, 0xc7, 0x39, 0xe5, + 0x43, 0x28, 0x24, 0xfb, 0xcb, 0xbd, 0xf5, 0x8a, 0xe0, 0x46, 0x81, 0x29, 0x8a, 0x50, 0x1b, 0x64, 0x34, 0x1a, 0xef, + 0x59, 0x7e, 0x99, 0x26, 0x26, 0x34, 0x6f, 0xc1, 0xb2, 0xff, 0x54, 0x70, 0x44, 0x2f, 0x1b, 0xf0, 0x88, 0xd2, 0x75, + 0x80, 0x44, 0x61, 0x0d, 0xa2, 0xea, 0x3e, 0xa2, 0xfb, 0xf9, 0x7f, 0x75, 0xe7, 0x82, 0xbc, 0x4a, 0x24, 0x1a, 0xc6, + 0xe3, 0x4f, 0x11, 0x1f, 0x72, 0xb0, 0xca, 0x63, 0xa7, 0xdd, 0x9d, 0x7e, 0xb1, 0xbf, 0x8c, 0x0e, 0x0e, 0xd8, 0xd0, + 0xc6, 0xe2, 0x12, 0xa8, 0x62, 0x9b, 0x70, 0xc9, 0xe1, 0x4f, 0x06, 0x7f, 0xd2, 0x62, 0x5c, 0x88, 0x7c, 0x3c, 0x46, + 0x77, 0xa4, 0x0c, 0xe5, 0xf4, 0xa3, 0x29, 0x43, 0xfe, 0x83, 0x52, 0x86, 0x72, 0xfa, 0x7b, 0xa7, 0x0c, 0x31, 0x6a, + 0xa4, 0x0c, 0x01, 0x1a, 0x7f, 0x7e, 0x50, 0xe6, 0x89, 0xce, 0x13, 0x48, 0x6f, 0x72, 0xd2, 0x51, 0xde, 0x9a, 0x38, + 0x9d, 0x42, 0xda, 0xc9, 0x3f, 0x3e, 0x8b, 0x24, 0x4e, 0xa7, 0x66, 0x0e, 0x09, 0xdc, 0xce, 0x0e, 0x49, 0x23, 0x38, + 0x23, 0x4b, 0xfb, 0xc7, 0xdb, 0xce, 0xd3, 0x51, 0xa7, 0x77, 0xd8, 0x99, 0xd9, 0x9e, 0x0d, 0xe6, 0x91, 0x28, 0x68, + 0xf7, 0x0e, 0x0f, 0xa1, 0xe0, 0xc6, 0x28, 0xe8, 0x42, 0x01, 0x33, 0x0a, 0x8e, 0xa1, 0x20, 0x30, 0x0a, 0x1e, 0x41, + 0x41, 0x68, 0x14, 0x3c, 0x86, 0x82, 0x6b, 0xbb, 0x18, 0xb1, 0x32, 0x2f, 0xea, 0x31, 0x12, 0x17, 0x39, 0xed, 0x65, + 0xf5, 0x43, 0x6c, 0x11, 0xd1, 0x55, 0x1e, 0x97, 0x07, 0x60, 0x9b, 0x47, 0xfa, 0xbe, 0xa6, 0xf1, 0x67, 0x63, 0x84, + 0x7d, 0x02, 0xe7, 0xd1, 0x31, 0x78, 0x4f, 0x65, 0xcd, 0x43, 0xfd, 0xda, 0xf6, 0xca, 0xe4, 0xa1, 0x36, 0xee, 0xea, + 0xf4, 0x21, 0xcf, 0x46, 0x78, 0x51, 0x56, 0x3e, 0x6e, 0x84, 0xaa, 0x5b, 0xb8, 0x0a, 0xa9, 0xba, 0x87, 0xec, 0x10, + 0x61, 0x79, 0x95, 0xff, 0x33, 0x61, 0xc8, 0xb8, 0x3c, 0x7d, 0xcf, 0x66, 0x54, 0x7f, 0x18, 0x4b, 0x0f, 0x60, 0x89, + 0x04, 0xab, 0x5e, 0x54, 0x5d, 0xde, 0xf9, 0x1d, 0x3e, 0xad, 0xae, 0xbe, 0x7b, 0xcf, 0x89, 0xbc, 0x4b, 0x28, 0xc3, + 0xd2, 0x23, 0x37, 0xc5, 0xdc, 0x9f, 0x7a, 0x90, 0x61, 0x02, 0xc1, 0x2d, 0xef, 0x94, 0x10, 0xd2, 0x1e, 0x2e, 0xbc, + 0xef, 0xf0, 0x4d, 0x44, 0x13, 0xef, 0xb2, 0xe8, 0x95, 0x04, 0x20, 0x13, 0x5c, 0xde, 0xf3, 0xf2, 0xc6, 0x54, 0x41, + 0x15, 0xd5, 0x6b, 0x09, 0x67, 0xb3, 0xa4, 0x9e, 0x1d, 0x39, 0x11, 0x86, 0xf3, 0x7c, 0x12, 0xa7, 0x37, 0xcd, 0x5b, + 0x7b, 0xb0, 0x3d, 0x4f, 0x02, 0x66, 0x57, 0xe6, 0x49, 0xbc, 0x04, 0x60, 0xcb, 0xa7, 0xf7, 0xfe, 0xb4, 0xfc, 0xfd, + 0x8a, 0xe6, 0xb9, 0x3f, 0x55, 0x35, 0x77, 0xe7, 0x45, 0x08, 0x10, 0xcd, 0x9c, 0x08, 0x0d, 0x04, 0x24, 0x2f, 0x00, + 0x46, 0xc0, 0xf9, 0xac, 0x72, 0x19, 0x60, 0xea, 0xf5, 0x34, 0x08, 0x81, 0xab, 0x7a, 0x11, 0xf7, 0xa7, 0x55, 0x41, + 0x7f, 0x9e, 0x51, 0x95, 0x60, 0x01, 0x68, 0x2c, 0xfa, 0x2d, 0x28, 0x90, 0xaf, 0x77, 0xa4, 0x3b, 0x68, 0x4f, 0xf7, + 0xee, 0xa4, 0x07, 0x4b, 0xa7, 0x3b, 0x98, 0x29, 0xba, 0x65, 0x7e, 0xee, 0x66, 0x90, 0xfd, 0xf3, 0x4e, 0x00, 0xff, + 0xa9, 0x10, 0xfe, 0xe7, 0x93, 0xc9, 0xe4, 0xde, 0xf4, 0x87, 0xcf, 0xc3, 0x09, 0xed, 0xd2, 0xe3, 0x1e, 0xa4, 0x6f, + 0x36, 0x55, 0xd0, 0xbc, 0x53, 0x08, 0xdc, 0x2d, 0x1f, 0x56, 0x19, 0xe2, 0xeb, 0x3c, 0x5a, 0x3e, 0x3c, 0x15, 0xa2, + 0x98, 0x67, 0x74, 0x39, 0xf3, 0xb3, 0x29, 0x4b, 0xbc, 0x76, 0xe1, 0x5e, 0xab, 0xdc, 0x81, 0xcf, 0x4f, 0x4e, 0x4e, + 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x59, 0x4e, 0xa3, 0xdd, 0x9e, 0x4c, 0x0a, 0x97, 0xe9, 0x82, + 0xc3, 0x6e, 0x10, 0x1e, 0x76, 0x0b, 0xf7, 0xc6, 0xa8, 0x51, 0xb8, 0x54, 0x3d, 0x65, 0x34, 0xac, 0xe5, 0x80, 0x3e, + 0x6e, 0xb7, 0x0b, 0x57, 0x12, 0xda, 0x12, 0xfc, 0x87, 0xf2, 0xa7, 0xe7, 0x2f, 0xb8, 0x60, 0xee, 0x3d, 0x9f, 0x3b, + 0xa3, 0x99, 0xba, 0x5f, 0x4b, 0x7e, 0x8d, 0xaa, 0x40, 0x17, 0xf8, 0x67, 0x33, 0xca, 0x0f, 0xc4, 0x2c, 0xa2, 0xfb, + 0xbe, 0x4e, 0x02, 0xa8, 0xbd, 0x06, 0xca, 0x12, 0xaf, 0x7f, 0x26, 0x7e, 0x15, 0xfc, 0x07, 0x4e, 0x06, 0x35, 0xe5, + 0x35, 0xb0, 0xc9, 0x2e, 0xf9, 0x91, 0x7d, 0x5c, 0x7e, 0xdc, 0x3d, 0x44, 0x7c, 0x64, 0xbf, 0xbb, 0xf8, 0x48, 0x4c, + 0xf1, 0x21, 0x99, 0xc7, 0x15, 0x27, 0x76, 0x10, 0xd1, 0xe0, 0xc3, 0x55, 0x7a, 0xdb, 0x84, 0x2d, 0x91, 0xd9, 0x42, + 0xb0, 0xec, 0xff, 0xda, 0x94, 0x46, 0xdd, 0x99, 0xf1, 0x2d, 0x2b, 0x21, 0x8a, 0xdf, 0x24, 0xc4, 0x7e, 0xa3, 0x9d, + 0x90, 0xb2, 0x64, 0x32, 0x21, 0xf6, 0x9b, 0xc9, 0xc4, 0xd6, 0xb7, 0x04, 0xf8, 0x9c, 0x8a, 0x5a, 0xaf, 0x6b, 0x25, + 0xa2, 0x16, 0x28, 0x25, 0x55, 0x99, 0x59, 0xa0, 0x72, 0x04, 0xcc, 0x7c, 0x00, 0xf5, 0x26, 0x64, 0x39, 0x6c, 0x35, + 0xf8, 0xc4, 0x56, 0xfd, 0x96, 0xe2, 0xa4, 0xf6, 0x41, 0x89, 0x12, 0xe0, 0x2d, 0x5f, 0xc1, 0x58, 0xbf, 0x22, 0x67, + 0x4a, 0x75, 0xc6, 0xfe, 0xd3, 0xbb, 0xaf, 0x42, 0xe7, 0x8a, 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0xb5, 0xe3, 0xaf, 0x12, + 0x46, 0x42, 0xcc, 0x69, 0x15, 0x3c, 0x9d, 0x4e, 0x63, 0xf8, 0xca, 0xd9, 0xb2, 0x76, 0x73, 0xba, 0x6c, 0x3e, 0xac, + 0xcd, 0xd7, 0x33, 0x1b, 0xaa, 0x7b, 0xc6, 0xc5, 0x47, 0x17, 0xe5, 0xb1, 0xa9, 0x6b, 0xf5, 0xf5, 0x3d, 0xe1, 0xbf, + 0x5c, 0x2a, 0x26, 0xbf, 0x94, 0x87, 0x6d, 0x38, 0x66, 0xa1, 0x6c, 0xce, 0xc2, 0xa2, 0x50, 0xc7, 0x14, 0x43, 0x96, + 0xcf, 0xe1, 0x46, 0x6f, 0xd9, 0x92, 0x7e, 0x8c, 0x85, 0xe7, 0x37, 0x46, 0x20, 0xbe, 0xb6, 0x5c, 0x85, 0x8e, 0xc4, + 0xcb, 0xc8, 0xe6, 0x15, 0x2f, 0x6c, 0x15, 0x20, 0xd5, 0x48, 0xb4, 0x2d, 0x89, 0x4f, 0x99, 0x22, 0x60, 0xcc, 0x10, + 0xa2, 0x94, 0xe5, 0x82, 0xe8, 0x57, 0xba, 0xa0, 0x30, 0x13, 0x4d, 0xc4, 0x1b, 0x89, 0x2d, 0x11, 0xd6, 0xce, 0xe7, + 0x7e, 0x22, 0xd9, 0x28, 0xb1, 0x25, 0x3f, 0xd8, 0x5f, 0x56, 0x2b, 0x5f, 0xd8, 0x1a, 0x6c, 0x49, 0xbc, 0x83, 0x7e, + 0x0b, 0x1a, 0x0c, 0xac, 0x1a, 0xe8, 0xc9, 0x46, 0x34, 0xfc, 0xfe, 0xbc, 0xb4, 0x0f, 0x63, 0x37, 0xbf, 0xc1, 0x6e, + 0x7e, 0x63, 0xfd, 0x71, 0xd9, 0xbc, 0xa1, 0x57, 0x1f, 0x18, 0x6f, 0x72, 0x7f, 0xde, 0x04, 0x4b, 0x4f, 0x44, 0xb1, + 0x14, 0x7b, 0x16, 0xf9, 0xed, 0xf2, 0x92, 0x9f, 0xde, 0x22, 0x87, 0xf4, 0x35, 0x61, 0x7e, 0x78, 0x49, 0x9a, 0xd0, + 0x5e, 0xfd, 0x1c, 0x83, 0x99, 0x0d, 0xa5, 0xb1, 0x75, 0xb1, 0x4c, 0x21, 0xdd, 0x8d, 0xdf, 0x79, 0x6d, 0xc5, 0xd6, + 0xdb, 0x3a, 0xd5, 0xa9, 0xbd, 0xb5, 0xbe, 0xa7, 0x90, 0xdb, 0x10, 0xd2, 0x2b, 0xdb, 0x4c, 0xf9, 0xda, 0x95, 0xb2, + 0xf5, 0xb1, 0xac, 0x7e, 0x88, 0x7d, 0xe9, 0xff, 0x8d, 0xe3, 0x10, 0xeb, 0xc5, 0x22, 0xab, 0xff, 0x21, 0x90, 0x79, + 0xfe, 0x84, 0xd3, 0x0c, 0x3f, 0xa4, 0xe6, 0x95, 0x38, 0x80, 0xbb, 0x04, 0x31, 0xe3, 0x75, 0x4e, 0xe6, 0xb7, 0x0f, + 0xef, 0xfe, 0xfe, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x42, 0x3a, 0xdb, 0xee, 0xc1, 0x46, 0x88, 0xfd, 0x3b, 0x8f, 0x25, + 0x42, 0xe6, 0x5d, 0x41, 0x00, 0xab, 0x37, 0x4f, 0xd5, 0xf1, 0x94, 0x8c, 0xc6, 0xe2, 0xfb, 0xb3, 0x6a, 0x29, 0x0e, + 0x1f, 0xcd, 0x6f, 0xf5, 0x6a, 0x74, 0xd6, 0x8e, 0x9d, 0xfc, 0xae, 0xa7, 0x4b, 0x76, 0x1f, 0x67, 0xa9, 0x9f, 0x90, + 0x38, 0x9e, 0xdf, 0xf6, 0xa4, 0xa0, 0x6d, 0x66, 0x12, 0xaa, 0xf6, 0xfc, 0xd6, 0x3c, 0x5f, 0x53, 0x75, 0x64, 0xb9, + 0x87, 0xb9, 0x45, 0xfd, 0x9c, 0xf6, 0xe0, 0x8b, 0x1b, 0x2c, 0xf0, 0x63, 0x25, 0xcc, 0x67, 0x2c, 0x0c, 0x63, 0xda, + 0xd3, 0xf2, 0xda, 0xea, 0x3c, 0x82, 0xe3, 0x29, 0xe6, 0x92, 0xd5, 0x57, 0xc5, 0x40, 0x5e, 0x89, 0x27, 0xff, 0x2a, + 0x4f, 0x63, 0xf8, 0xdc, 0xd5, 0x56, 0x74, 0xaa, 0x73, 0x1b, 0xed, 0x0a, 0x79, 0xe2, 0x77, 0x7d, 0x2e, 0xc7, 0xed, + 0x3f, 0xf4, 0xc4, 0x82, 0xb7, 0x7b, 0x3c, 0x9d, 0x7b, 0xcd, 0xc3, 0xfa, 0x44, 0xe0, 0x55, 0x39, 0x05, 0xbc, 0x65, + 0x5a, 0x18, 0xa4, 0x95, 0xe4, 0xd3, 0x96, 0xdb, 0x51, 0x65, 0xa2, 0x03, 0xc8, 0xef, 0x2d, 0x8b, 0x8a, 0xfa, 0x64, + 0xfe, 0x31, 0xbb, 0xe5, 0xc9, 0xf6, 0xdd, 0xf2, 0x44, 0xef, 0x96, 0xfb, 0x29, 0xf6, 0xf3, 0x49, 0x07, 0xfe, 0xeb, + 0x55, 0x13, 0xf2, 0xda, 0xd6, 0xe1, 0xfc, 0xd6, 0x02, 0x3d, 0xad, 0xd9, 0x9d, 0xdf, 0xca, 0xd3, 0x45, 0x10, 0x64, + 0x6f, 0xc3, 0x79, 0x1b, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, 0x75, 0x8e, 0xe0, 0x1d, 0xb4, 0x3a, 0xde, + 0x7c, 0xd7, 0xbd, 0x7f, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, 0xe4, 0x72, 0xff, 0xea, 0x8a, 0x86, 0xde, + 0x24, 0x0d, 0x16, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdd, 0xd2, 0x6b, 0xfd, 0xe8, 0xa6, 0xf2, 0xac, 0x93, + 0xee, 0x61, 0x59, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, 0xb4, 0x65, 0x13, 0xfc, 0x9b, 0xac, 0xcd, + 0xd6, 0xc9, 0xfc, 0x56, 0x64, 0xdc, 0x8b, 0x84, 0x4f, 0xc2, 0x81, 0xb9, 0x86, 0xed, 0x93, 0xed, 0xe0, 0x8e, 0xf4, + 0x48, 0x17, 0x5a, 0x28, 0x28, 0xb9, 0x13, 0xd2, 0x89, 0xbf, 0x88, 0xf9, 0xfd, 0xbd, 0xee, 0xa2, 0x8c, 0x8d, 0x5e, + 0xef, 0x61, 0xe8, 0x55, 0xdd, 0x07, 0x72, 0xe9, 0xcf, 0x9f, 0x1c, 0xc1, 0x7f, 0x32, 0x51, 0xf7, 0xae, 0xd2, 0xd5, + 0xa5, 0xdd, 0x0b, 0xba, 0xfa, 0x7e, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, 0x83, + 0xaa, 0x2b, 0x2d, 0xeb, 0x93, 0x6a, 0x7f, 0x5a, 0xe7, 0x0f, 0xac, 0x1b, 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x80, + 0x77, 0xa3, 0xb2, 0xc6, 0xb8, 0xa8, 0xbf, 0x4f, 0xee, 0x4a, 0x13, 0x45, 0xa6, 0xcd, 0x80, 0x95, 0xb2, 0x2f, 0xad, + 0x94, 0x94, 0x92, 0x71, 0x7f, 0x78, 0x3b, 0x8b, 0xad, 0x6b, 0x79, 0x51, 0x00, 0xb1, 0x3b, 0x6e, 0xdb, 0xb6, 0x44, + 0xc2, 0x16, 0x7c, 0xaf, 0xc4, 0x16, 0x1f, 0x76, 0xb7, 0x87, 0xa0, 0x69, 0x5d, 0x4f, 0x85, 0x66, 0xf7, 0xd2, 0xbf, + 0xa3, 0xd9, 0x65, 0xd7, 0xb6, 0xc0, 0x4f, 0xd3, 0x94, 0xb9, 0x6d, 0xa2, 0xcc, 0xea, 0xda, 0xd6, 0xed, 0x2c, 0x4e, + 0x72, 0x62, 0x47, 0x9c, 0xcf, 0x3d, 0xf9, 0xe5, 0xf7, 0x9b, 0x43, 0x37, 0xcd, 0xa6, 0xad, 0x6e, 0xbb, 0xdd, 0x86, + 0xab, 0xcf, 0x6d, 0xeb, 0x9a, 0xd1, 0x9b, 0xa7, 0xe9, 0x2d, 0xb1, 0xdb, 0x56, 0xdb, 0xea, 0x74, 0x4f, 0xac, 0x4e, + 0xf7, 0xc8, 0x7d, 0x74, 0x62, 0x0f, 0x3e, 0xb3, 0xac, 0x7e, 0x48, 0x27, 0x39, 0xfc, 0xb0, 0xac, 0xbe, 0x50, 0xbc, + 0xe4, 0x6f, 0xcb, 0x72, 0x83, 0x38, 0x6f, 0x76, 0xac, 0xa5, 0x7a, 0xb4, 0x2c, 0xb8, 0x4e, 0xc1, 0xb3, 0x3e, 0x9f, + 0x74, 0x27, 0x47, 0x93, 0x27, 0x3d, 0x55, 0x5c, 0x7c, 0x56, 0xab, 0x8e, 0xe5, 0xbf, 0x5d, 0xa3, 0x59, 0xce, 0xb3, + 0xf4, 0x03, 0x55, 0xc9, 0xe3, 0x16, 0x88, 0x9e, 0xad, 0x4d, 0xbb, 0x9b, 0x23, 0x75, 0x4e, 0xae, 0x82, 0x49, 0xb7, + 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0xf6, 0x5b, 0x1a, 0xf4, 0xbe, 0x89, 0xa6, 0x4e, 0x73, 0x1b, 0xa2, 0x3a, 0xb6, + 0x9a, 0xe3, 0x54, 0xcf, 0xaf, 0x0f, 0xa7, 0xf7, 0xb4, 0xae, 0x2a, 0x20, 0xb0, 0xad, 0x90, 0xd8, 0xaf, 0x3a, 0xdd, + 0x13, 0xdc, 0xe9, 0x3c, 0x72, 0x1f, 0x9d, 0x04, 0x6d, 0x7c, 0xe4, 0x1e, 0x35, 0x0f, 0xdd, 0x47, 0xf8, 0xa4, 0x79, + 0x82, 0x4f, 0x5e, 0x9c, 0x04, 0xcd, 0x23, 0xf7, 0x08, 0xb7, 0x9b, 0x27, 0x50, 0xd8, 0x3c, 0x69, 0x9e, 0x5c, 0x37, + 0x8f, 0x4e, 0x82, 0xb6, 0x28, 0xed, 0xba, 0xc7, 0xc7, 0xcd, 0x4e, 0xdb, 0x3d, 0x3e, 0xc6, 0xc7, 0xee, 0xa3, 0x47, + 0xcd, 0xce, 0xa1, 0xfb, 0xe8, 0xd1, 0xcb, 0xe3, 0x13, 0xf7, 0x10, 0xde, 0x1d, 0x1e, 0x06, 0x87, 0x6e, 0xa7, 0xd3, + 0x84, 0x3f, 0xf8, 0xc4, 0xed, 0xca, 0x1f, 0x9d, 0x8e, 0x7b, 0xd8, 0xc1, 0xed, 0xf8, 0xb8, 0xeb, 0x3e, 0x7a, 0x82, + 0xc5, 0x5f, 0x51, 0x0d, 0x8b, 0x3f, 0xd0, 0x0d, 0x7e, 0xe2, 0x76, 0x1f, 0xc9, 0x5f, 0xa2, 0xc3, 0xeb, 0xa3, 0x93, + 0xbf, 0xd9, 0xad, 0x9d, 0x73, 0xe8, 0xc8, 0x39, 0x9c, 0x1c, 0xbb, 0x87, 0x87, 0xf8, 0xa8, 0xe3, 0x9e, 0x1c, 0x46, + 0xcd, 0xa3, 0xae, 0xfb, 0xe8, 0x71, 0xd0, 0xec, 0xb8, 0x8f, 0x1f, 0xe3, 0x76, 0xf3, 0xd0, 0xed, 0xe2, 0x8e, 0x7b, + 0x74, 0x28, 0x7e, 0x1c, 0xba, 0xdd, 0xeb, 0xc7, 0x4f, 0xdc, 0x47, 0xc7, 0xd1, 0x23, 0xf7, 0xe8, 0xbb, 0xa3, 0x13, + 0xb7, 0x7b, 0x18, 0x1d, 0x3e, 0x72, 0xbb, 0x8f, 0xaf, 0x1f, 0xb9, 0x47, 0x51, 0xb3, 0xfb, 0xe8, 0xde, 0x96, 0x9d, + 0xae, 0x0b, 0x38, 0x12, 0xaf, 0xe1, 0x05, 0x56, 0x2f, 0xe0, 0xff, 0x48, 0xb4, 0xfd, 0x37, 0xec, 0x26, 0xdf, 0x6c, + 0xfa, 0xc4, 0x3d, 0x79, 0x1c, 0xc8, 0xea, 0x50, 0xd0, 0xd4, 0x35, 0xa0, 0xc9, 0x75, 0x53, 0x0e, 0x2b, 0xba, 0x6b, + 0xea, 0x8e, 0xf4, 0xff, 0x6a, 0xb0, 0xeb, 0x26, 0x0c, 0x2c, 0xc7, 0xfd, 0x77, 0xed, 0xa7, 0x5c, 0xf2, 0x7e, 0x6b, + 0x2a, 0x49, 0x7f, 0x3a, 0xf8, 0x4c, 0x7e, 0xd7, 0xe0, 0xb3, 0x31, 0xf6, 0x77, 0x39, 0x3e, 0xe2, 0x8f, 0x3b, 0x3e, + 0x22, 0xfa, 0x10, 0xcf, 0x47, 0xfc, 0xbb, 0x7b, 0x3e, 0xfc, 0x75, 0xc7, 0xf9, 0x0d, 0xdf, 0x70, 0x70, 0xac, 0x5b, + 0xc5, 0x2f, 0xb9, 0x33, 0x4a, 0xe1, 0x0b, 0x9a, 0x45, 0xef, 0x86, 0x93, 0x88, 0x9a, 0x7e, 0xa0, 0x14, 0x58, 0xec, + 0x0d, 0x97, 0x3c, 0x36, 0xd8, 0x85, 0x90, 0xf0, 0xe3, 0x08, 0xf9, 0xf2, 0x21, 0xf8, 0x08, 0x7f, 0x77, 0x7c, 0x04, + 0x26, 0x3e, 0x6a, 0xbe, 0x7c, 0xe1, 0x69, 0x10, 0x9e, 0x82, 0x73, 0xf1, 0xec, 0xc0, 0xf1, 0xe1, 0x86, 0xdd, 0xa2, + 0x50, 0x94, 0xdb, 0x32, 0x22, 0xf6, 0xee, 0x53, 0xc2, 0x0e, 0xf2, 0xae, 0x00, 0x62, 0x2b, 0xb7, 0xcc, 0x5c, 0x48, + 0x1d, 0xf5, 0x50, 0x0a, 0xa5, 0xae, 0xdb, 0x76, 0xdb, 0xa5, 0x4b, 0x07, 0xee, 0x87, 0x20, 0xcb, 0x94, 0xfb, 0xf0, + 0xad, 0xf6, 0x38, 0x9d, 0x8a, 0xaf, 0xba, 0xc3, 0x77, 0x74, 0x20, 0x3b, 0x33, 0x90, 0x9f, 0x30, 0x82, 0x50, 0x8f, + 0x72, 0xf4, 0xf8, 0xd9, 0x87, 0x6f, 0xe0, 0x8e, 0x06, 0x1d, 0x95, 0x98, 0x81, 0xb7, 0xe3, 0x15, 0x0d, 0x99, 0xef, + 0xd8, 0xce, 0x3c, 0xa3, 0x13, 0x9a, 0xe5, 0xcd, 0xda, 0xc5, 0x05, 0xe2, 0xce, 0x02, 0x64, 0xeb, 0x8f, 0x82, 0x67, + 0xf0, 0x5d, 0x08, 0x32, 0x52, 0xfe, 0x46, 0x5b, 0x19, 0x60, 0x76, 0x81, 0x75, 0x49, 0x06, 0xb2, 0xb6, 0x52, 0xda, + 0x6c, 0xa9, 0xb5, 0x75, 0xdc, 0xee, 0x31, 0xb2, 0x44, 0x31, 0xdc, 0xb8, 0xff, 0x83, 0xd3, 0x3c, 0x6c, 0xff, 0x01, + 0x19, 0xcd, 0xca, 0x8e, 0x2e, 0x94, 0xbb, 0x2d, 0x29, 0xbf, 0xcb, 0xb4, 0x76, 0xab, 0x84, 0x2d, 0x29, 0xe2, 0x73, + 0x39, 0x77, 0x1b, 0xf5, 0x12, 0x15, 0xe0, 0x97, 0x77, 0x23, 0x4d, 0xd8, 0xd4, 0x31, 0xce, 0xdd, 0x26, 0xf2, 0x46, + 0x7f, 0xb8, 0xb6, 0x17, 0xa1, 0xa2, 0xaa, 0x92, 0xa0, 0xa5, 0x88, 0xb7, 0xb0, 0xc4, 0x4a, 0x56, 0x2b, 0x27, 0x01, + 0x17, 0x39, 0x31, 0x70, 0x0a, 0xcf, 0xa8, 0x86, 0xe4, 0x04, 0x97, 0x00, 0x09, 0x04, 0x93, 0x44, 0xfe, 0x5b, 0x15, + 0xeb, 0x1f, 0xca, 0xf1, 0xe5, 0xc6, 0x7e, 0x32, 0x05, 0x2a, 0xf4, 0x93, 0xe9, 0x86, 0x5b, 0x4d, 0x86, 0x8c, 0xd6, + 0x4a, 0xab, 0xae, 0x2a, 0xf7, 0x59, 0xfe, 0xf4, 0xee, 0xbd, 0xba, 0xfa, 0xd3, 0x06, 0xef, 0xb4, 0x88, 0x70, 0x54, + 0x9f, 0x29, 0x68, 0x90, 0x2f, 0xfa, 0x33, 0xca, 0x7d, 0x99, 0x58, 0x0f, 0xfa, 0x04, 0xdc, 0x17, 0x61, 0x29, 0x6b, + 0x94, 0xd8, 0x42, 0xba, 0x13, 0x79, 0xd8, 0x51, 0x8a, 0x7a, 0x6c, 0xa9, 0x3b, 0x73, 0x9a, 0x62, 0x69, 0x48, 0x07, + 0x4b, 0x7f, 0x4c, 0xe0, 0x8b, 0xa3, 0x53, 0x24, 0x49, 0xed, 0xc1, 0x17, 0xe5, 0x77, 0xbf, 0x77, 0x2d, 0x42, 0xcc, + 0x92, 0x0f, 0xa3, 0x8c, 0xc6, 0xff, 0x44, 0xbe, 0x60, 0x41, 0x9a, 0x7c, 0x71, 0x61, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, + 0x4e, 0xc8, 0x17, 0x20, 0xe3, 0x3d, 0x61, 0x7d, 0x00, 0x23, 0x6c, 0xdc, 0xce, 0x62, 0x2c, 0x34, 0xa6, 0x07, 0x28, + 0x44, 0x12, 0x5c, 0xbb, 0x7b, 0x6c, 0x5b, 0xd2, 0x26, 0x16, 0xbf, 0x07, 0x52, 0x9c, 0x0a, 0x25, 0xc0, 0xea, 0x74, + 0xdd, 0xe3, 0xa8, 0xeb, 0x3e, 0xb9, 0x7e, 0xec, 0x9e, 0x44, 0x9d, 0xc7, 0xd7, 0x4d, 0xf8, 0xb7, 0xeb, 0x3e, 0x89, + 0x9b, 0x5d, 0xf7, 0x09, 0xfc, 0xff, 0xdd, 0x91, 0x7b, 0x1c, 0x35, 0x3b, 0xee, 0xc9, 0xf5, 0xa1, 0x7b, 0xf8, 0xb2, + 0xd3, 0x75, 0x0f, 0xad, 0x8e, 0x25, 0xdb, 0x01, 0xbb, 0x96, 0xdc, 0xf9, 0x8b, 0xb5, 0x0d, 0xb1, 0x25, 0x1c, 0x27, + 0x0f, 0x07, 0xd8, 0xd8, 0x29, 0xbf, 0x2e, 0xac, 0xf6, 0xa7, 0x72, 0xd6, 0x3d, 0xf3, 0x33, 0xf8, 0xc4, 0x5b, 0x7d, + 0xef, 0xd6, 0xde, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x04, 0xec, 0x70, 0x1b, 0x9b, 0x97, 0xce, 0xc0, 0x8d, 0x2d, 0xe2, + 0x8b, 0x18, 0xfa, 0x62, 0xe0, 0xdd, 0xa4, 0x2d, 0x2b, 0xea, 0xcb, 0x87, 0x05, 0xb3, 0x60, 0xe2, 0xdb, 0x43, 0x62, + 0x90, 0xaf, 0xc2, 0x62, 0x7d, 0x7c, 0x38, 0xa3, 0x90, 0xa5, 0xc6, 0xbd, 0x3b, 0xb4, 0x3a, 0x59, 0x17, 0x32, 0xb8, + 0x29, 0xa9, 0x28, 0x34, 0xe8, 0x35, 0x37, 0x6d, 0x85, 0x25, 0xc1, 0x2f, 0x68, 0x3e, 0xb4, 0xa1, 0xc8, 0xf6, 0x6c, + 0xe1, 0xe2, 0xb3, 0xcb, 0xcf, 0xdc, 0x95, 0x84, 0x5d, 0x15, 0x60, 0x71, 0x3a, 0x16, 0x76, 0x2d, 0xe0, 0xc7, 0x46, + 0x07, 0x07, 0x3b, 0xf7, 0x8b, 0x50, 0x20, 0x61, 0xae, 0xd5, 0xd7, 0xb1, 0x4c, 0x56, 0x64, 0x9b, 0x88, 0x2e, 0xfb, + 0x15, 0x28, 0x44, 0x0a, 0x4f, 0x57, 0xd4, 0xe7, 0xae, 0x9f, 0xc8, 0x6c, 0x47, 0x83, 0x61, 0xe1, 0x0e, 0x3d, 0x44, + 0x45, 0xca, 0x7d, 0x99, 0x65, 0x64, 0xee, 0xf3, 0x94, 0xfb, 0xfa, 0x16, 0x09, 0xe3, 0xc2, 0x3c, 0x70, 0xf4, 0x46, + 0xdd, 0xc1, 0x9b, 0xf7, 0xa7, 0x96, 0xdc, 0x9e, 0xfd, 0x56, 0xd4, 0x1d, 0xf4, 0x85, 0xcf, 0x44, 0x9e, 0xa8, 0x26, + 0xf2, 0x44, 0xb5, 0xa5, 0x0e, 0xd1, 0x43, 0x24, 0xad, 0x68, 0xc9, 0x69, 0x0b, 0x9b, 0x41, 0x7a, 0x7b, 0x67, 0x8b, + 0x98, 0x33, 0xf8, 0xba, 0x43, 0x4b, 0x1c, 0xa7, 0x86, 0x05, 0x2b, 0x0f, 0xcc, 0x28, 0xed, 0xf0, 0x8a, 0x27, 0xda, + 0x37, 0x3c, 0x61, 0x31, 0xd5, 0x47, 0x64, 0x54, 0x57, 0xe5, 0x91, 0xae, 0xcd, 0xda, 0xf9, 0xe2, 0x6a, 0xc6, 0xb8, + 0xad, 0x0f, 0x9e, 0x7d, 0xab, 0x1a, 0xf4, 0xc5, 0x50, 0x83, 0x71, 0xa1, 0x9c, 0xd7, 0xfa, 0x3b, 0x76, 0xf5, 0x25, + 0x55, 0xb3, 0x57, 0x12, 0x02, 0x8e, 0x32, 0x47, 0x87, 0x83, 0xd2, 0x5d, 0x6c, 0xbe, 0x2b, 0xfa, 0xad, 0xe8, 0x70, + 0x30, 0xf6, 0xe6, 0xaa, 0xbf, 0x97, 0xe9, 0x74, 0x7b, 0x5f, 0x71, 0x3a, 0x1d, 0x8a, 0x33, 0x7b, 0xf2, 0x72, 0x0b, + 0xad, 0xfc, 0xa6, 0xb1, 0x3d, 0xe8, 0x2b, 0x65, 0xc0, 0x12, 0x81, 0x75, 0xfb, 0xb8, 0xad, 0x8f, 0x01, 0xc6, 0xe9, + 0x14, 0x36, 0xa4, 0x6c, 0x62, 0x0c, 0x52, 0xf3, 0xb8, 0x47, 0x9d, 0x41, 0xdf, 0xb7, 0x04, 0x6f, 0x11, 0xcc, 0x23, + 0xf7, 0x5a, 0xd0, 0x38, 0x4a, 0x67, 0xd4, 0x65, 0x69, 0xeb, 0x86, 0x5e, 0x35, 0xfd, 0x39, 0xab, 0xdc, 0xdb, 0xa0, + 0x74, 0x94, 0x43, 0xa6, 0xda, 0x23, 0xae, 0x0e, 0xc9, 0x76, 0x2b, 0x77, 0xdb, 0x11, 0xd8, 0x3c, 0xda, 0x35, 0x27, + 0x7c, 0x72, 0x06, 0x58, 0xe9, 0xa0, 0xdf, 0xf2, 0xd7, 0x30, 0x22, 0xf8, 0x7d, 0xa1, 0x1c, 0xed, 0x60, 0xd8, 0x00, + 0xbd, 0xd9, 0x96, 0x14, 0x07, 0xda, 0x21, 0xaf, 0x04, 0x75, 0x61, 0x0f, 0xfe, 0xf5, 0x7f, 0xfc, 0x2f, 0xe5, 0x63, + 0xef, 0xb7, 0xa2, 0x8e, 0xee, 0x6b, 0x6d, 0x55, 0x8a, 0x3e, 0x1c, 0xe4, 0xaf, 0x82, 0xc2, 0xf4, 0xb6, 0x39, 0xcd, + 0x58, 0xd8, 0x8c, 0xfc, 0x78, 0x62, 0x0f, 0x76, 0x63, 0xd3, 0x3c, 0x5f, 0xab, 0xa0, 0xae, 0x17, 0x01, 0xbd, 0xfe, + 0xaa, 0x13, 0xa2, 0xfa, 0xa0, 0xa1, 0xd8, 0xda, 0xe6, 0x79, 0xd1, 0x6a, 0xf7, 0xd5, 0xce, 0x8c, 0x26, 0xea, 0xe3, + 0x98, 0x8a, 0x03, 0x26, 0xb5, 0xa3, 0xa2, 0x85, 0x6d, 0x95, 0x41, 0xad, 0xff, 0xfb, 0x3f, 0xff, 0xcb, 0x7f, 0xd3, + 0x8f, 0x10, 0xab, 0xfa, 0xd7, 0xff, 0xfe, 0x9f, 0xff, 0xcf, 0xff, 0xfe, 0xaf, 0x70, 0xbc, 0x50, 0xc5, 0xb3, 0x04, + 0x53, 0xb1, 0xaa, 0x60, 0x96, 0xe4, 0x2e, 0x16, 0x64, 0xe0, 0xcf, 0x58, 0xce, 0x59, 0x50, 0x3f, 0x3c, 0x7a, 0x2e, + 0x06, 0x14, 0x3b, 0x53, 0x41, 0x27, 0x76, 0x78, 0x51, 0x11, 0x54, 0x0d, 0xe5, 0x82, 0x70, 0x8b, 0x7e, 0x0b, 0xf0, + 0xfd, 0xb0, 0xf3, 0xf6, 0x6e, 0xb9, 0x1c, 0x4b, 0x4d, 0x26, 0x50, 0x52, 0x54, 0xe5, 0x16, 0xc4, 0x56, 0x96, 0xf0, + 0xe8, 0x75, 0x8d, 0x62, 0xb1, 0x7a, 0xb5, 0x36, 0xbd, 0x9f, 0x16, 0x39, 0x67, 0x13, 0x40, 0xb9, 0xf4, 0x13, 0x8b, + 0x30, 0x76, 0x13, 0x74, 0xc5, 0xf8, 0xae, 0x10, 0xbd, 0x48, 0x02, 0x3d, 0x3a, 0xf9, 0x43, 0xf1, 0xa7, 0x19, 0x68, + 0x64, 0x96, 0x33, 0xf3, 0x6f, 0x95, 0x79, 0xfe, 0xa8, 0xdd, 0x9e, 0xdf, 0xa2, 0x65, 0x35, 0x02, 0xde, 0x35, 0x98, + 0xa0, 0x63, 0xb3, 0x43, 0x11, 0xff, 0x2e, 0xdd, 0xd8, 0x6d, 0x0b, 0x7c, 0xe1, 0x56, 0xbb, 0x28, 0xfe, 0xb8, 0x14, + 0x9e, 0x54, 0xf6, 0x0b, 0xc4, 0xa9, 0x95, 0xd3, 0xf9, 0x2a, 0x35, 0x27, 0xb7, 0x34, 0x5a, 0x75, 0x65, 0xab, 0xa8, + 0xb3, 0x79, 0x8c, 0xdc, 0x8c, 0xb3, 0x9b, 0x11, 0xf2, 0x23, 0x88, 0x79, 0x47, 0x1d, 0x1c, 0x75, 0x97, 0x65, 0xf7, + 0x9c, 0xa7, 0x33, 0x33, 0xb0, 0x4e, 0x7d, 0x1a, 0xd0, 0x89, 0x76, 0xd6, 0xab, 0xf7, 0x32, 0x68, 0x5e, 0x44, 0x87, + 0x5b, 0xc6, 0x52, 0x20, 0x89, 0x80, 0xba, 0xd5, 0x2e, 0x3e, 0x87, 0x1d, 0xb8, 0x9c, 0xc4, 0xa9, 0xcf, 0x3d, 0x41, + 0xb0, 0x3d, 0x33, 0x3c, 0xef, 0x03, 0x4f, 0x4a, 0x97, 0x06, 0x3c, 0x3d, 0x59, 0x15, 0xdc, 0xe6, 0xf5, 0xc3, 0xfe, + 0x85, 0x2b, 0x9a, 0x9b, 0x5d, 0x49, 0xaf, 0xdb, 0x97, 0x2a, 0xea, 0xfd, 0xae, 0xe6, 0xae, 0x52, 0x02, 0xa9, 0x8b, + 0xb6, 0xbf, 0x97, 0x72, 0x5d, 0xbe, 0xfd, 0x86, 0x3b, 0xb6, 0x00, 0xd3, 0x5e, 0xaf, 0x25, 0x0a, 0xa1, 0xd6, 0x3b, + 0xf2, 0x65, 0x69, 0x32, 0xf9, 0xf3, 0xb9, 0xa8, 0x88, 0x7a, 0xfd, 0x96, 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, + 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, 0x68, 0xea, 0xe0, 0xff, 0x01, 0x0b, 0x95, + 0x29, 0x52, 0xc9, 0x90, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0x1f, 0x8b, 0x11, 0x15, 0xb5, 0x07, 0x2e, 0x8a, 0x32, 0xd1, 0x4a, 0x00, 0x3d, 0x0c, 0xf0, 0x64, 0x64, 0xfe, - 0xca, 0x03, 0x1e, 0x15, 0x6c, 0xb2, 0x3d, 0x4d, 0x23, 0x3c, 0x36, 0x77, 0xaa, 0xd8, 0x7a, 0xb4, 0xd1, 0x42, 0x40, - 0x11, 0xba, 0x7d, 0xa8, 0xfe, 0xef, 0x5a, 0xfe, 0xb4, 0x58, 0x8c, 0x03, 0x96, 0xaa, 0x9a, 0x1e, 0xa8, 0x33, 0x7d, - 0x5d, 0x84, 0x65, 0xb5, 0x47, 0x68, 0xec, 0x93, 0x5c, 0xff, 0x2b, 0x9b, 0x76, 0xcf, 0xe5, 0xd4, 0x74, 0x28, 0xfc, - 0x7f, 0x78, 0x92, 0x3d, 0xcb, 0xf6, 0x9b, 0x2f, 0xcd, 0xba, 0xe3, 0x39, 0x31, 0x14, 0x22, 0xa6, 0x8d, 0x55, 0x43, - 0x59, 0x29, 0x8b, 0x2c, 0x54, 0xeb, 0xe5, 0x7e, 0x18, 0xa7, 0x9c, 0x80, 0x44, 0x51, 0xd2, 0x0a, 0x12, 0xb8, 0xda, - 0xff, 0xd4, 0x66, 0x5f, 0x6f, 0x9a, 0x0a, 0xde, 0x78, 0x8c, 0xb4, 0xd8, 0xc1, 0x22, 0x7b, 0x1a, 0x9e, 0xc9, 0x71, - 0xdc, 0x84, 0x1f, 0x2e, 0xe1, 0x68, 0x57, 0xc8, 0x1e, 0xe9, 0x11, 0x48, 0x6c, 0x17, 0x5d, 0xb3, 0x45, 0xf5, 0xfd, - 0xde, 0x57, 0xf7, 0x7d, 0xfd, 0x6e, 0xb4, 0x4d, 0xde, 0x92, 0xd8, 0xe1, 0xd5, 0x46, 0x69, 0x45, 0xc4, 0x13, 0x6b, - 0x40, 0xd1, 0xc0, 0xcc, 0xb5, 0x29, 0x3e, 0x58, 0xaa, 0xf9, 0x6f, 0x55, 0xdb, 0xb9, 0x34, 0xe0, 0xbc, 0xcd, 0x51, - 0x52, 0x9e, 0xe7, 0xdc, 0x45, 0x93, 0x52, 0x21, 0x60, 0x02, 0xa2, 0xbf, 0x95, 0x43, 0x0c, 0xe4, 0xc9, 0x6d, 0x9a, - 0xa6, 0xea, 0xb4, 0xba, 0x26, 0x39, 0xe4, 0xf0, 0x22, 0x5f, 0xea, 0x44, 0x64, 0xf7, 0x65, 0x2b, 0x7d, 0x2b, 0x6d, - 0x8b, 0xe9, 0x9b, 0xfe, 0x74, 0x5a, 0x9d, 0xa4, 0x65, 0xe9, 0x9d, 0x25, 0x63, 0x79, 0xc5, 0x19, 0xb7, 0x0f, 0x54, - 0x02, 0x27, 0xa5, 0x02, 0x7c, 0xd4, 0xb8, 0x51, 0xea, 0x44, 0xe9, 0xf6, 0x99, 0xe8, 0xff, 0x37, 0xd5, 0xb7, 0x76, - 0x00, 0x06, 0xa7, 0x58, 0x34, 0xf6, 0xc6, 0x36, 0xc4, 0x0e, 0xa2, 0xa9, 0x4d, 0xb9, 0x29, 0xb6, 0x28, 0x39, 0xf7, - 0xde, 0xf7, 0xae, 0x35, 0x09, 0x5f, 0x98, 0x01, 0x61, 0x23, 0xd1, 0x02, 0x09, 0x72, 0x99, 0x8f, 0x98, 0x14, 0xd2, - 0x7b, 0x33, 0x03, 0x70, 0x66, 0x40, 0xc9, 0x03, 0x52, 0x32, 0xc3, 0xa7, 0xcf, 0xa1, 0x82, 0x43, 0xca, 0xb2, 0x37, - 0xa4, 0x54, 0x35, 0x21, 0x77, 0x7b, 0xfa, 0x58, 0x95, 0xdf, 0x45, 0xb9, 0xdd, 0x16, 0xed, 0xea, 0x1c, 0xdb, 0x4c, - 0x25, 0x33, 0x2b, 0xe1, 0xfc, 0x2d, 0x43, 0x5b, 0xf3, 0xbc, 0x73, 0xff, 0x5b, 0xd8, 0x81, 0x02, 0x25, 0x64, 0x58, - 0x5d, 0xc6, 0xb4, 0x7e, 0xdc, 0xda, 0x45, 0xc4, 0x10, 0x92, 0x4d, 0xad, 0xed, 0x7f, 0xd8, 0x86, 0xbd, 0xba, 0x8a, - 0x6a, 0x12, 0x8a, 0x71, 0x80, 0x76, 0x0a, 0xca, 0xd0, 0x72, 0x9f, 0x76, 0xdc, 0xe2, 0xdc, 0xc7, 0xa8, 0x39, 0x08, - 0x26, 0x69, 0x0f, 0x5e, 0x4b, 0xc3, 0x81, 0x08, 0x34, 0x8a, 0x3c, 0x95, 0xfc, 0xf4, 0x81, 0xed, 0x9b, 0xe7, 0x33, - 0x36, 0xe8, 0xd5, 0xb0, 0xd6, 0x03, 0x6e, 0x01, 0xdb, 0x4f, 0x83, 0xb3, 0x11, 0x2c, 0xcd, 0x6a, 0x2e, 0x7c, 0xf6, - 0xb8, 0xf1, 0xf2, 0xcd, 0xcd, 0xda, 0x11, 0x1b, 0xfd, 0x23, 0xe5, 0xa7, 0xb4, 0x70, 0xea, 0xaa, 0x4b, 0xde, 0xba, - 0xba, 0xf0, 0xa1, 0xe6, 0x61, 0xe1, 0xe1, 0x12, 0xbc, 0x85, 0x31, 0xf6, 0xbb, 0x8c, 0x67, 0x86, 0x8c, 0x49, 0x17, - 0xad, 0x1e, 0xb8, 0x99, 0xf9, 0x79, 0xb3, 0xf6, 0xa5, 0x3a, 0x9c, 0x0b, 0xcc, 0xce, 0xb4, 0xe9, 0x7a, 0x29, 0x10, - 0xec, 0xa6, 0x2d, 0x45, 0x4a, 0xcf, 0xfe, 0x36, 0xca, 0x53, 0xc3, 0x3d, 0xf3, 0xe8, 0xb2, 0x1f, 0x7e, 0xc5, 0xc1, - 0x0a, 0x48, 0x64, 0x14, 0xbe, 0x73, 0xa4, 0x5c, 0xb9, 0xf4, 0x26, 0xcf, 0x91, 0xcb, 0xd2, 0xaf, 0x3c, 0xc7, 0x7a, - 0x44, 0x3e, 0x21, 0x3a, 0xeb, 0xf9, 0xf1, 0x34, 0x2c, 0x85, 0x31, 0xaf, 0x88, 0xdb, 0xf9, 0x69, 0x7d, 0xbb, 0x32, - 0xf0, 0x18, 0x72, 0x27, 0xb4, 0x1e, 0x88, 0x6e, 0xdf, 0x78, 0xe7, 0x72, 0xed, 0xea, 0xf5, 0x5e, 0x6d, 0x4d, 0xfa, - 0x57, 0xe9, 0x6a, 0xd9, 0x53, 0xb8, 0xba, 0x7b, 0x8e, 0x1d, 0xc1, 0xcd, 0x6c, 0xed, 0x78, 0x8a, 0xd0, 0xec, 0xb0, - 0x9e, 0xab, 0xe1, 0x44, 0xa3, 0x3b, 0x21, 0x39, 0x8e, 0x8d, 0x82, 0xe5, 0xed, 0x92, 0x14, 0x25, 0x2d, 0x1f, 0x72, - 0x13, 0xc8, 0x0c, 0xff, 0x80, 0xdc, 0xcb, 0x9d, 0x33, 0xdf, 0x85, 0xbd, 0xf0, 0x09, 0xd6, 0x01, 0x8a, 0xab, 0x79, - 0x76, 0x79, 0x7a, 0x6c, 0x7d, 0xf9, 0xb2, 0x83, 0xfc, 0x77, 0x73, 0x44, 0x61, 0xfc, 0xa9, 0xcf, 0xa0, 0x91, 0xeb, - 0xa6, 0x91, 0x10, 0x14, 0x90, 0xeb, 0x80, 0xf9, 0xc8, 0x1c, 0x01, 0x4f, 0x87, 0x73, 0x55, 0xeb, 0x12, 0x78, 0x97, - 0x9b, 0x8f, 0xc7, 0x3b, 0xc9, 0xc3, 0xf5, 0x0a, 0xfe, 0xd4, 0x1f, 0xb9, 0xb6, 0x50, 0xd7, 0x09, 0x28, 0x89, 0x9d, - 0xbc, 0x31, 0xd5, 0x32, 0xc9, 0x13, 0xcd, 0xae, 0xad, 0x1c, 0x90, 0x20, 0x6f, 0xd8, 0x20, 0x37, 0x4a, 0xb6, 0x5a, - 0x7d, 0xb4, 0xfb, 0x3b, 0x97, 0x85, 0xc0, 0xf1, 0x37, 0xc7, 0xd6, 0xe4, 0x9c, 0x00, 0x02, 0x48, 0x7f, 0x1f, 0x34, - 0x2b, 0x36, 0x91, 0x65, 0x0e, 0x81, 0x4f, 0x78, 0x52, 0x30, 0x93, 0x34, 0x7d, 0xbd, 0x65, 0x64, 0x96, 0x72, 0x65, - 0x88, 0xcb, 0xf0, 0xf8, 0x65, 0x99, 0x67, 0x1a, 0x15, 0x9e, 0xf4, 0x89, 0x89, 0x92, 0x21, 0xcf, 0x90, 0xa7, 0x0b, - 0x68, 0x2e, 0xe0, 0x74, 0xe5, 0x09, 0xb1, 0x2c, 0x60, 0x2a, 0x08, 0x1d, 0x7b, 0x1b, 0x57, 0x4d, 0x27, 0xd2, 0x10, - 0x07, 0x93, 0x3f, 0x3d, 0x79, 0xe6, 0xf8, 0x57, 0x5c, 0xca, 0x12, 0x90, 0x04, 0xdf, 0xfd, 0x72, 0x11, 0x54, 0x31, - 0x2c, 0xcd, 0xa2, 0x49, 0xac, 0x00, 0x29, 0x4b, 0x20, 0x81, 0x84, 0x3a, 0x31, 0xf7, 0xb3, 0x43, 0xec, 0xf8, 0x11, - 0x9f, 0xde, 0x03, 0xbb, 0x35, 0xc1, 0x2c, 0x5f, 0xcb, 0x29, 0x66, 0x35, 0x17, 0x52, 0x92, 0x73, 0xaa, 0xfb, 0x64, - 0xb3, 0xb1, 0xbb, 0xa2, 0x95, 0x99, 0xc2, 0xde, 0x37, 0xaa, 0x21, 0xa6, 0xdd, 0xce, 0x2f, 0x84, 0x75, 0x25, 0xd1, - 0xc4, 0x52, 0x55, 0xf8, 0xfe, 0xaf, 0x07, 0x85, 0xe9, 0x34, 0xf4, 0x46, 0xbf, 0x67, 0xe6, 0x2e, 0x77, 0x8c, 0xc2, - 0x32, 0xd4, 0xbc, 0x54, 0xcb, 0xd4, 0xda, 0x08, 0x30, 0x80, 0x43, 0x5a, 0x09, 0xf1, 0x37, 0xed, 0x12, 0xb1, 0xc3, - 0xc8, 0xf2, 0xeb, 0x7a, 0x06, 0x95, 0x88, 0xf6, 0x7e, 0x76, 0x94, 0x3c, 0xe6, 0x1f, 0x62, 0xf6, 0x68, 0x96, 0x41, - 0x09, 0x63, 0x7c, 0x67, 0x72, 0x80, 0xce, 0xb4, 0x5b, 0xb9, 0xc8, 0x81, 0x6e, 0x61, 0x3b, 0x38, 0xaf, 0x72, 0x4d, - 0x73, 0x42, 0xb5, 0x55, 0x89, 0xe4, 0xce, 0x06, 0x09, 0x8d, 0xc1, 0x52, 0x86, 0xe5, 0x59, 0x47, 0xb8, 0x87, 0x5c, - 0xe5, 0xfd, 0x92, 0x68, 0xc6, 0x64, 0x76, 0x37, 0xe8, 0xb0, 0x5b, 0x70, 0xc6, 0xe7, 0x8d, 0x58, 0xb2, 0x4f, 0xdc, - 0x4e, 0x7c, 0x2c, 0x19, 0xa4, 0x57, 0x96, 0xcc, 0x41, 0x50, 0xd7, 0x0e, 0x6c, 0x13, 0xd1, 0x02, 0x63, 0x9d, 0x3f, - 0x33, 0x7d, 0x51, 0x74, 0x42, 0xa5, 0x5d, 0x81, 0x23, 0x15, 0xe8, 0xe8, 0xc1, 0xf1, 0x74, 0x8a, 0x34, 0xef, 0x08, - 0x50, 0xec, 0xbd, 0x0d, 0x3f, 0xb2, 0x4c, 0xe7, 0x51, 0xc7, 0x97, 0xcc, 0xf5, 0xd0, 0xa6, 0xba, 0xed, 0xa4, 0x50, - 0xec, 0x54, 0x85, 0xb4, 0x86, 0x6d, 0xa7, 0x71, 0x56, 0x2b, 0x54, 0xae, 0x08, 0x1f, 0xea, 0xad, 0xc9, 0xbb, 0xd8, - 0x25, 0x46, 0x59, 0xef, 0x67, 0x17, 0xc9, 0xcc, 0x57, 0xcf, 0x03, 0x2a, 0x24, 0x6c, 0xf3, 0x84, 0xb9, 0xfb, 0x31, - 0x33, 0x18, 0x06, 0x9d, 0x78, 0x42, 0xbc, 0x23, 0x4d, 0x09, 0x15, 0x46, 0x65, 0xb5, 0x3f, 0x38, 0xb6, 0xe8, 0xad, - 0x90, 0x0c, 0x88, 0x37, 0xe1, 0xb8, 0x14, 0x12, 0xac, 0x68, 0xac, 0x00, 0x9c, 0x68, 0x81, 0xf8, 0x85, 0x1a, 0xf4, - 0x08, 0xf5, 0x3a, 0x91, 0xf8, 0x4e, 0xf3, 0xd6, 0x19, 0x18, 0x14, 0x56, 0x1d, 0xa4, 0x57, 0xd9, 0xe9, 0x1d, 0xc0, - 0x89, 0x8a, 0xd0, 0xa7, 0x4e, 0x3c, 0x88, 0xc8, 0x9b, 0x4e, 0x2c, 0x61, 0xca, 0x38, 0x9f, 0x66, 0xd7, 0xda, 0x11, - 0x8d, 0xdd, 0xed, 0x36, 0x10, 0x8c, 0xd5, 0xed, 0xa0, 0xef, 0x46, 0xfb, 0x4e, 0x04, 0xec, 0x60, 0x34, 0xac, 0xf6, - 0x9f, 0x79, 0x1a, 0x55, 0x82, 0x3b, 0x9f, 0x73, 0x03, 0x65, 0x2f, 0x06, 0x53, 0xd7, 0x12, 0x7e, 0x51, 0xae, 0x0a, - 0xec, 0x4b, 0x0a, 0xf8, 0x7b, 0x4a, 0x42, 0x36, 0xd7, 0x47, 0x79, 0x69, 0xc0, 0xcf, 0x1d, 0xf2, 0x39, 0x97, 0xba, - 0xbe, 0xe9, 0x75, 0xb1, 0xac, 0x1a, 0xeb, 0xbd, 0x33, 0x2d, 0xa6, 0x06, 0x6c, 0xdd, 0x79, 0x2e, 0x9a, 0x5b, 0xb0, - 0x82, 0xb1, 0x83, 0x23, 0xe1, 0x70, 0x98, 0x39, 0xdd, 0xb4, 0x02, 0xc3, 0xc6, 0x21, 0x7d, 0x21, 0x81, 0xdf, 0xca, - 0x0a, 0x78, 0x4f, 0xda, 0x88, 0x8b, 0x41, 0xcb, 0x2d, 0x7c, 0x99, 0xdf, 0x1c, 0xc9, 0x5c, 0x61, 0x4e, 0xfd, 0x73, - 0xb5, 0x8f, 0xca, 0xd8, 0x0c, 0xa8, 0x18, 0x69, 0xcd, 0x28, 0xb7, 0xab, 0xe0, 0x7e, 0x45, 0x79, 0x15, 0xbc, 0xe1, - 0xe2, 0xba, 0x7e, 0x68, 0xc2, 0x5b, 0x98, 0x2e, 0xca, 0x3c, 0x65, 0x96, 0x27, 0x67, 0x3c, 0x91, 0x05, 0xf2, 0xb4, - 0xa9, 0x8f, 0x1f, 0x32, 0x17, 0x26, 0x41, 0x6a, 0x78, 0x6c, 0xb9, 0xfd, 0xae, 0x36, 0xb6, 0x18, 0x19, 0x00, 0xb4, - 0x3b, 0x0d, 0x4a, 0x05, 0x40, 0x26, 0x79, 0x24, 0xe7, 0x46, 0x83, 0xbe, 0x7e, 0x91, 0x9e, 0x6d, 0x3a, 0x1e, 0x92, - 0x75, 0xdf, 0x67, 0x14, 0x94, 0xf1, 0x6e, 0xb1, 0x2e, 0x00, 0x84, 0xc5, 0x00, 0x1d, 0x37, 0xfe, 0x72, 0x90, 0x56, - 0x06, 0x32, 0x72, 0x37, 0x6f, 0x97, 0x07, 0xbb, 0xf0, 0xeb, 0xaf, 0x6c, 0x52, 0xc0, 0x38, 0x1e, 0xf9, 0x63, 0xf9, - 0x08, 0x45, 0x02, 0x6a, 0x56, 0x28, 0x87, 0x02, 0xe8, 0x30, 0x11, 0xbd, 0xd6, 0xfa, 0xb8, 0xc5, 0xdc, 0xeb, 0x2b, - 0x34, 0x89, 0xa8, 0x68, 0x37, 0x8d, 0x5a, 0x51, 0x2f, 0x21, 0x06, 0xff, 0x84, 0x63, 0x87, 0x0e, 0x12, 0x95, 0xac, - 0x52, 0x65, 0xc3, 0x3a, 0x58, 0x1f, 0x34, 0x00, 0x0d, 0x1c, 0xd4, 0xe8, 0xe6, 0xdb, 0x44, 0x56, 0xbb, 0x8f, 0x28, - 0x4d, 0x23, 0x1d, 0xbc, 0xbc, 0xa1, 0x42, 0xa0, 0x5f, 0xf6, 0xc8, 0x57, 0x2d, 0x6b, 0xa1, 0xa4, 0x3a, 0x81, 0x3b, - 0xec, 0x09, 0x0b, 0x94, 0x68, 0xf9, 0x53, 0x33, 0x50, 0xc9, 0x20, 0xf6, 0x3c, 0xef, 0x8f, 0x4f, 0xfc, 0xe8, 0xd2, - 0x65, 0x1e, 0x52, 0x49, 0x24, 0x7c, 0xc2, 0x93, 0x03, 0xba, 0xee, 0x81, 0xa4, 0x00, 0xde, 0x35, 0x60, 0x2a, 0x9f, - 0x1b, 0xe2, 0xe1, 0x64, 0x3b, 0x2d, 0x7c, 0x5c, 0xcc, 0x46, 0x0d, 0x07, 0x33, 0xd1, 0x85, 0x2b, 0xe0, 0xad, 0xd7, - 0x23, 0x3a, 0x16, 0x98, 0x25, 0x90, 0x08, 0x91, 0xce, 0x45, 0x73, 0xb6, 0x2a, 0x79, 0x9d, 0x64, 0x86, 0x22, 0x52, - 0xab, 0xe4, 0x26, 0x30, 0x37, 0x4e, 0x15, 0xb1, 0x90, 0x94, 0x94, 0x09, 0x07, 0x08, 0x96, 0x2b, 0xa2, 0xa3, 0xe4, - 0x3d, 0xaa, 0x2b, 0x09, 0xb7, 0xf3, 0x5f, 0xa6, 0x34, 0xc1, 0xec, 0xca, 0x62, 0x1f, 0x0c, 0x90, 0xd2, 0x2d, 0xb5, - 0x19, 0xbc, 0x15, 0x11, 0x4f, 0x45, 0x40, 0x25, 0x22, 0x51, 0x78, 0x4f, 0x6e, 0xb5, 0x67, 0xd1, 0x7c, 0xd6, 0x8d, - 0x85, 0x31, 0x9d, 0x61, 0xef, 0x69, 0xb1, 0xa2, 0x1c, 0x37, 0xda, 0x89, 0x6a, 0xda, 0xdf, 0xa8, 0x7c, 0x44, 0x6c, - 0x3b, 0xfd, 0x28, 0xc5, 0x20, 0x1a, 0x4d, 0xae, 0xa9, 0xf4, 0xb3, 0xd2, 0x3f, 0x1f, 0x0b, 0xd4, 0x1a, 0xf5, 0x9a, - 0x9f, 0x3f, 0xeb, 0xdc, 0x86, 0xa8, 0xb3, 0x76, 0x89, 0x03, 0x6e, 0xae, 0x9a, 0x6e, 0x95, 0x44, 0xf8, 0xaf, 0x65, - 0x72, 0x40, 0xa1, 0xdd, 0x99, 0xcd, 0xd1, 0xee, 0xd7, 0x21, 0xd9, 0x8f, 0x16, 0x2b, 0x10, 0x00, 0x4a, 0xc1, 0x2c, - 0x46, 0x91, 0x03, 0x55, 0x0c, 0x48, 0x29, 0xe7, 0x11, 0xb4, 0x28, 0xba, 0x0a, 0x60, 0x28, 0x54, 0x49, 0x23, 0xd7, - 0xb0, 0xd8, 0x6c, 0x0c, 0xc4, 0xa8, 0x55, 0xb7, 0x11, 0x08, 0x49, 0xb6, 0x5c, 0x3d, 0xb5, 0xa0, 0x14, 0x69, 0xf2, - 0xee, 0x82, 0xc2, 0x9a, 0x70, 0x5c, 0x19, 0xa0, 0xcc, 0x1f, 0x85, 0x89, 0xda, 0xaf, 0x9d, 0x17, 0xbb, 0xe2, 0x05, - 0x83, 0x0d, 0x17, 0x92, 0x5f, 0x89, 0x4c, 0x09, 0x0a, 0xa7, 0x2c, 0x69, 0xec, 0x65, 0x5b, 0xa7, 0xf2, 0xe5, 0x59, - 0x52, 0x29, 0x58, 0x19, 0xd5, 0x88, 0x83, 0x3b, 0x55, 0xd7, 0xb5, 0xea, 0x08, 0x2d, 0x7f, 0x74, 0x2a, 0xc9, 0x7b, - 0xd3, 0x4d, 0x46, 0x27, 0xb3, 0xce, 0xaa, 0x72, 0xbf, 0x1e, 0x9c, 0xe9, 0xe4, 0x49, 0x5d, 0x35, 0xc1, 0xb3, 0x82, - 0x22, 0x10, 0xf6, 0x78, 0xf3, 0x49, 0x75, 0xb4, 0x4f, 0x02, 0x96, 0x7c, 0x63, 0xf0, 0x26, 0xd5, 0x11, 0x13, 0x9a, - 0x96, 0xcf, 0x7d, 0x04, 0xce, 0x4a, 0x9d, 0x45, 0x07, 0xe0, 0xc3, 0x0b, 0x94, 0x1e, 0x94, 0x2a, 0x4b, 0xdd, 0xe4, - 0x36, 0xe4, 0x98, 0x80, 0x83, 0x1e, 0x05, 0x79, 0x3a, 0x3d, 0x71, 0x53, 0xa5, 0xd2, 0x93, 0x17, 0x4b, 0x36, 0x33, - 0xc9, 0xac, 0xae, 0x72, 0x8e, 0xfd, 0xa7, 0x00, 0x4d, 0xd3, 0xdc, 0xb0, 0x02, 0x91, 0x9e, 0x59, 0x90, 0x1b, 0x5b, - 0x71, 0xbe, 0x12, 0xa4, 0x48, 0x99, 0x90, 0x27, 0x68, 0xcb, 0x11, 0x55, 0x25, 0x4a, 0xe8, 0x40, 0x91, 0xc9, 0x90, - 0x65, 0x4d, 0x2a, 0xd9, 0xb7, 0x7c, 0x8d, 0x43, 0x26, 0x29, 0xc9, 0x69, 0x72, 0xdc, 0xcb, 0xe6, 0xb0, 0x2b, 0x43, - 0x54, 0x42, 0xa3, 0x14, 0xb6, 0x0b, 0x43, 0xf2, 0xd4, 0x33, 0xa5, 0x5b, 0x6a, 0x3b, 0x42, 0xba, 0x33, 0x23, 0x79, - 0x3b, 0xa0, 0xea, 0xeb, 0xe8, 0x82, 0x63, 0x41, 0x41, 0x23, 0x92, 0x24, 0xcf, 0x25, 0xc5, 0x20, 0x87, 0x91, 0x42, - 0x89, 0x67, 0xb2, 0xc5, 0x58, 0x16, 0xd1, 0xf7, 0x83, 0x14, 0xcc, 0xd2, 0x96, 0x41, 0x44, 0xfa, 0x34, 0x88, 0xbd, - 0x52, 0x3c, 0x42, 0xe5, 0x72, 0xef, 0xde, 0x46, 0x61, 0x49, 0xaa, 0x93, 0x32, 0x41, 0xd0, 0x9e, 0x45, 0xa3, 0x13, - 0x06, 0xcc, 0x47, 0x13, 0x28, 0x2f, 0x87, 0xcd, 0x61, 0x61, 0xf7, 0x21, 0xc5, 0xf3, 0x65, 0xf6, 0xf3, 0x99, 0xe5, - 0x1c, 0x59, 0xce, 0x0c, 0x9d, 0xb4, 0x29, 0xa4, 0xb0, 0x59, 0x3e, 0x11, 0x22, 0xd3, 0xbc, 0x73, 0xb1, 0x38, 0xd0, - 0x33, 0xfc, 0xae, 0x11, 0xdc, 0x00, 0x95, 0x30, 0x42, 0xae, 0xda, 0xac, 0x76, 0xd3, 0xea, 0x43, 0x0a, 0xab, 0x1d, - 0xdd, 0x70, 0x29, 0x76, 0xef, 0x14, 0x67, 0xde, 0x9b, 0x54, 0x98, 0xf7, 0x4a, 0x47, 0x26, 0x76, 0x79, 0x0b, 0x5f, - 0x2b, 0xc1, 0xe9, 0x39, 0xaf, 0xc2, 0x3b, 0x48, 0xa1, 0x22, 0x98, 0xac, 0x70, 0xc0, 0x50, 0x39, 0x9e, 0x8c, 0xf3, - 0x16, 0x51, 0xfc, 0x1c, 0x2c, 0x27, 0xa1, 0xa1, 0xac, 0x16, 0x28, 0xd8, 0x43, 0xf7, 0x79, 0x1f, 0xa5, 0x14, 0xd8, - 0xf7, 0x55, 0x12, 0x4f, 0x0e, 0x61, 0x66, 0x8c, 0x27, 0xb6, 0x16, 0x54, 0xc6, 0x70, 0xa1, 0xc9, 0x06, 0x7e, 0xb8, - 0xed, 0x33, 0x33, 0x44, 0xfb, 0x72, 0x90, 0x0b, 0xf3, 0x6a, 0x4d, 0x81, 0xa8, 0x80, 0x85, 0xd2, 0xf7, 0xb6, 0x23, - 0x5c, 0xec, 0xc0, 0x70, 0x5b, 0x78, 0x86, 0xc9, 0xb8, 0x6a, 0x85, 0x26, 0x56, 0xd5, 0xc2, 0x1e, 0xe8, 0x46, 0x6d, - 0x4b, 0x47, 0xfa, 0x39, 0x99, 0x8a, 0x5d, 0xc7, 0x4a, 0xaf, 0x05, 0x2d, 0xfe, 0xb6, 0xbe, 0x1c, 0x8b, 0x51, 0x09, - 0x47, 0x64, 0xa8, 0xf9, 0x69, 0x10, 0xf9, 0xb1, 0x96, 0x19, 0x78, 0x9a, 0x8e, 0xb0, 0x18, 0xfc, 0x27, 0xab, 0x57, - 0x49, 0x78, 0xd1, 0x56, 0x68, 0x4e, 0x6b, 0xdf, 0x70, 0xdb, 0x54, 0x6e, 0x91, 0x8a, 0xfd, 0xbb, 0x0e, 0x42, 0xcb, - 0x14, 0x2a, 0xd4, 0x44, 0x73, 0x94, 0x4b, 0x15, 0xc7, 0x41, 0xa7, 0xdb, 0xb0, 0xb1, 0x4a, 0x92, 0xe8, 0x2e, 0xef, - 0xa0, 0x4f, 0x5b, 0x20, 0x55, 0x75, 0x4d, 0x51, 0x2c, 0x9a, 0xdf, 0xc4, 0x50, 0x35, 0xf3, 0x65, 0x06, 0x0e, 0xdc, - 0xcb, 0xa9, 0x92, 0x74, 0xcf, 0xe5, 0x57, 0x51, 0xb1, 0xfc, 0x47, 0x0a, 0x65, 0x7e, 0x8c, 0x4a, 0x06, 0x96, 0x16, - 0x10, 0x75, 0x9d, 0xe3, 0x52, 0x42, 0xe6, 0x8c, 0x5b, 0xf2, 0xaa, 0x58, 0xbb, 0x5b, 0xcc, 0x0d, 0x77, 0xfd, 0x52, - 0xc3, 0x41, 0x2e, 0x48, 0x33, 0x1a, 0x57, 0x90, 0xe1, 0x77, 0x31, 0x2a, 0x2c, 0xf6, 0xab, 0x38, 0x69, 0x12, 0xd1, - 0x78, 0x0c, 0xf8, 0x33, 0xd9, 0x84, 0xee, 0x0d, 0x88, 0xbc, 0x85, 0x5c, 0x9e, 0x66, 0x99, 0x94, 0x8e, 0xc0, 0x22, - 0xd1, 0xed, 0xbb, 0x9a, 0xa2, 0x0a, 0x73, 0xbd, 0xf9, 0x29, 0xad, 0xd4, 0x29, 0x6b, 0x60, 0x0a, 0x0b, 0x4a, 0xea, - 0xcc, 0x39, 0xac, 0x23, 0x63, 0xaa, 0x4e, 0x8a, 0x9b, 0xb4, 0xeb, 0xc2, 0xac, 0x41, 0xa6, 0x08, 0x44, 0xa7, 0x43, - 0x65, 0x94, 0x7d, 0x10, 0x00, 0x77, 0x19, 0x20, 0x5a, 0x82, 0x44, 0x00, 0x2f, 0xe9, 0x9f, 0x06, 0x1a, 0xb3, 0x71, - 0x7d, 0x95, 0xca, 0x51, 0x93, 0xca, 0xc7, 0xc4, 0x76, 0x54, 0x0d, 0x13, 0x9d, 0xf2, 0x5a, 0x28, 0xa6, 0xd5, 0x1e, - 0x5a, 0x7f, 0xa5, 0x18, 0x7a, 0xd7, 0xb2, 0xc2, 0xd8, 0xd3, 0x24, 0xeb, 0x2c, 0xc0, 0x46, 0xa6, 0xee, 0x0f, 0xb2, - 0xb5, 0x27, 0x0a, 0xec, 0x12, 0x2a, 0x32, 0x5c, 0xd4, 0x37, 0x43, 0x8a, 0x7b, 0x38, 0xc6, 0xe3, 0xf6, 0x93, 0x4d, - 0x6a, 0xef, 0x53, 0x79, 0x4f, 0xaf, 0x63, 0xac, 0x8d, 0xf9, 0xc9, 0x53, 0xc9, 0x82, 0x2f, 0xa3, 0x11, 0xe6, 0x49, - 0xc4, 0x82, 0xb6, 0x00, 0xd8, 0xe1, 0x42, 0x87, 0x1d, 0x2f, 0x97, 0x21, 0xee, 0x29, 0xcc, 0x83, 0xd1, 0x7a, 0x6a, - 0x43, 0xe6, 0xf5, 0xc2, 0xc8, 0xda, 0x24, 0x65, 0xfd, 0x73, 0xe7, 0xb1, 0x3c, 0x72, 0x3d, 0xe6, 0x49, 0x9d, 0xa2, - 0x3c, 0x54, 0x5a, 0x98, 0x45, 0xfe, 0xba, 0x98, 0x85, 0xc7, 0xc0, 0x99, 0x90, 0x09, 0x0d, 0xcc, 0xc8, 0x85, 0xcd, - 0x0b, 0x51, 0xb2, 0xd8, 0x62, 0x79, 0xa7, 0x90, 0xfc, 0xf8, 0x4e, 0x0a, 0x34, 0xa2, 0x20, 0xa8, 0x56, 0x5e, 0x50, - 0x28, 0x0b, 0xab, 0xfc, 0xce, 0xd3, 0xbe, 0x4f, 0xce, 0xbb, 0xc4, 0x72, 0x39, 0x7b, 0x8c, 0x8f, 0xe9, 0x9f, 0x63, - 0xde, 0x7e, 0xac, 0x78, 0x71, 0x2d, 0x3c, 0x2d, 0x77, 0xb1, 0x36, 0xf3, 0x44, 0x6d, 0x02, 0x78, 0x37, 0x53, 0x4b, - 0xbf, 0x13, 0x66, 0xfd, 0x0c, 0x6c, 0xbe, 0x52, 0x78, 0x7f, 0x18, 0x80, 0x95, 0xbb, 0x27, 0x50, 0x0c, 0xdb, 0x92, - 0x87, 0xfb, 0x7b, 0xc8, 0xeb, 0x28, 0x7e, 0xc8, 0x56, 0x27, 0xc2, 0x8f, 0xb0, 0xd1, 0xcb, 0x92, 0xba, 0x2b, 0x5c, - 0xef, 0xdd, 0x84, 0x87, 0x4f, 0xd8, 0xd5, 0x9f, 0x3b, 0xa3, 0x6d, 0xdd, 0x5c, 0x6f, 0x6c, 0x50, 0xfa, 0xcf, 0xbb, - 0xb8, 0xe4, 0xf4, 0x46, 0xd5, 0xe5, 0x2e, 0x05, 0xe8, 0x17, 0x42, 0x64, 0x11, 0xc3, 0xda, 0xde, 0x70, 0xf8, 0x7e, - 0x39, 0x92, 0x1d, 0x3c, 0xbd, 0xd1, 0x1c, 0x82, 0x99, 0x86, 0x27, 0xf6, 0xf1, 0x8a, 0x2c, 0xe6, 0xec, 0x12, 0x80, - 0xdf, 0xfe, 0x54, 0x7f, 0xb1, 0xf7, 0xe0, 0x7c, 0x18, 0xcc, 0x93, 0x43, 0x0f, 0x9a, 0x73, 0xfe, 0xb0, 0x0f, 0xbb, - 0x7f, 0x14, 0xf3, 0xc4, 0xa6, 0x0b, 0x1e, 0x23, 0xf7, 0xb7, 0x60, 0x1f, 0x59, 0xe1, 0xc9, 0x3b, 0x88, 0x44, 0x16, - 0x7e, 0xa3, 0x38, 0xe0, 0xd8, 0x13, 0x04, 0xcc, 0x54, 0x32, 0xc5, 0x62, 0x9c, 0xe8, 0x18, 0xa7, 0xf3, 0x0b, 0xbf, - 0x9c, 0xed, 0x85, 0x87, 0xb1, 0x6b, 0xf7, 0xca, 0xeb, 0x58, 0x77, 0x6b, 0x6b, 0x6b, 0x4b, 0xc6, 0x53, 0x20, 0xb9, - 0x69, 0xc9, 0x9f, 0x41, 0x5e, 0xc2, 0x0c, 0xdf, 0xba, 0x66, 0x67, 0xbb, 0xa7, 0x63, 0x5b, 0xf5, 0x76, 0xff, 0xd2, - 0x56, 0x35, 0xec, 0xff, 0xf6, 0x65, 0xed, 0xe5, 0xfe, 0x67, 0x5b, 0xba, 0x60, 0x4b, 0xad, 0xae, 0xff, 0x1a, 0xfb, - 0x41, 0x18, 0x96, 0x2f, 0xad, 0xfe, 0xc5, 0xe8, 0xed, 0xf3, 0x9b, 0xf0, 0xb9, 0xe8, 0xc4, 0x90, 0x97, 0xf4, 0xfa, - 0x53, 0xa9, 0x95, 0xe4, 0x5f, 0x57, 0x5e, 0x3c, 0x7c, 0x69, 0x8f, 0xeb, 0x75, 0xca, 0x3b, 0x7b, 0x2b, 0x0c, 0x93, - 0xa8, 0xd0, 0xc0, 0x43, 0x70, 0xad, 0xff, 0x69, 0x8f, 0x1b, 0xaf, 0x92, 0xc9, 0x2b, 0x56, 0x47, 0xcb, 0x53, 0x62, - 0xe3, 0xe5, 0xfa, 0xf3, 0x55, 0xe2, 0xad, 0xc1, 0x92, 0xcb, 0x12, 0xff, 0x05, 0xfe, 0x64, 0x12, 0xa6, 0xaa, 0x80, - 0xe4, 0xaf, 0xe4, 0x7c, 0xf5, 0x32, 0xec, 0x7e, 0xf1, 0xc1, 0xc4, 0x5c, 0xd9, 0xe0, 0x13, 0xd7, 0xc9, 0xe3, 0x5d, - 0xe0, 0xd2, 0xb3, 0xa2, 0xb3, 0xb7, 0x1a, 0xad, 0x94, 0x53, 0xbf, 0x00, 0x85, 0x9f, 0x17, 0xfe, 0xd3, 0x53, 0xa0, - 0xcd, 0x9e, 0x62, 0x1c, 0x5e, 0x99, 0x24, 0xb6, 0xcb, 0x64, 0xed, 0x26, 0x3e, 0x6f, 0x29, 0xde, 0xa2, 0xaa, 0x22, - 0x88, 0xc4, 0x6c, 0xec, 0xe0, 0x89, 0xf4, 0x97, 0x03, 0x0e, 0x74, 0xd3, 0xf5, 0xe2, 0xcc, 0x7f, 0x1a, 0xbb, 0x00, - 0x4c, 0x08, 0xff, 0x72, 0x46, 0x43, 0x31, 0xd1, 0x5f, 0x4b, 0x05, 0xac, 0xf9, 0x84, 0x31, 0x76, 0x7f, 0x26, 0x32, - 0x81, 0x9b, 0x89, 0xb0, 0x02, 0xd3, 0x8f, 0x7e, 0x7b, 0x8a, 0x30, 0xf1, 0x9d, 0xc8, 0x59, 0x9b, 0x35, 0xfd, 0x47, - 0xda, 0xb3, 0x8d, 0x07, 0x91, 0x05, 0xec, 0x33, 0x04, 0x76, 0x9e, 0x71, 0x63, 0xb6, 0xf2, 0xc8, 0x2a, 0xd6, 0x8c, - 0x44, 0x2f, 0x0c, 0x04, 0x52, 0xce, 0x2a, 0xd8, 0xa4, 0x5c, 0x01, 0x68, 0x5a, 0x7d, 0xf8, 0x71, 0xd4, 0xf7, 0xaf, - 0x9b, 0xa8, 0xd5, 0xbb, 0xb1, 0x75, 0x19, 0x35, 0x3f, 0xea, 0xab, 0x3d, 0x05, 0x2f, 0x67, 0xa9, 0x89, 0x3e, 0xe3, - 0x59, 0xf2, 0xca, 0xd1, 0x6e, 0x48, 0xb6, 0x5e, 0xe7, 0x91, 0x85, 0x6b, 0x7e, 0xd9, 0x26, 0x04, 0xc3, 0x48, 0xcd, - 0x50, 0x52, 0x20, 0x32, 0xcf, 0xd7, 0xa9, 0x04, 0x39, 0x76, 0x84, 0x36, 0xe1, 0xef, 0x94, 0x2a, 0x12, 0x62, 0x7b, - 0x04, 0x5d, 0xfb, 0xeb, 0xd8, 0xc4, 0xd8, 0x41, 0x20, 0xba, 0x0c, 0x0e, 0x41, 0xa5, 0xaf, 0x1a, 0x15, 0x59, 0xbc, - 0xd0, 0x1c, 0x53, 0x93, 0xb7, 0x66, 0xa4, 0x60, 0x89, 0x4d, 0x7c, 0xc5, 0x80, 0x9a, 0xad, 0x42, 0xc1, 0x46, 0xd1, - 0x6a, 0xdd, 0x8f, 0xcd, 0x25, 0x6d, 0xea, 0x9d, 0x17, 0x3e, 0x93, 0x38, 0x4e, 0x9e, 0x5f, 0xd3, 0x53, 0xd6, 0xca, - 0x82, 0xfe, 0xc9, 0x13, 0x49, 0x40, 0x2d, 0x6d, 0xde, 0x59, 0x53, 0x71, 0x54, 0xd5, 0xdf, 0x3e, 0x44, 0x88, 0x97, - 0xd7, 0xe9, 0x52, 0xad, 0x1c, 0x11, 0xea, 0x61, 0x08, 0xbd, 0x4c, 0xb9, 0xad, 0x94, 0xbb, 0x6e, 0xce, 0x62, 0x5a, - 0x3a, 0x6e, 0xb2, 0x9f, 0x9e, 0xbb, 0x01, 0x8b, 0x20, 0x06, 0xe0, 0x19, 0x71, 0x2f, 0xb9, 0xee, 0x08, 0x9a, 0x4b, - 0x90, 0x40, 0x9f, 0x51, 0xfc, 0xe0, 0x05, 0x63, 0x94, 0xcc, 0x99, 0x0a, 0x5c, 0x00, 0x00, 0x14, 0xc6, 0x23, 0xe5, - 0x1b, 0x93, 0xd8, 0x5b, 0x81, 0x3b, 0xb1, 0x6a, 0xc3, 0xe5, 0xad, 0xee, 0xda, 0x00, 0xe7, 0x79, 0x6e, 0xe2, 0x0f, - 0xb5, 0x1b, 0xdf, 0x76, 0xc4, 0xaa, 0x36, 0x28, 0x30, 0x51, 0x47, 0xd0, 0x3a, 0x75, 0x88, 0xb6, 0xaa, 0xac, 0x5a, - 0x1d, 0xe7, 0xb2, 0x9b, 0x1b, 0xd0, 0xe8, 0xcd, 0x6c, 0x9d, 0x41, 0x58, 0x9a, 0x79, 0x2a, 0xb3, 0xaa, 0xcb, 0x6e, - 0x33, 0x8d, 0x8b, 0xc7, 0xf2, 0x62, 0x5a, 0xb9, 0xcc, 0xe0, 0x56, 0x69, 0x7f, 0x65, 0xc6, 0xc1, 0xef, 0x04, 0xff, - 0x4d, 0x9f, 0xfa, 0x66, 0x89, 0x49, 0xac, 0x6e, 0x07, 0x22, 0xb8, 0xa9, 0x64, 0xaf, 0x73, 0xad, 0x24, 0xf2, 0x16, - 0x6a, 0xc3, 0x3b, 0xd7, 0xd1, 0x84, 0x58, 0x7e, 0xaa, 0x4e, 0xdb, 0xb6, 0xf6, 0xdd, 0xa3, 0x11, 0x63, 0x31, 0xde, - 0x0d, 0x40, 0x12, 0x9e, 0xb7, 0x95, 0x6c, 0xb1, 0x94, 0x5e, 0x96, 0x99, 0xfd, 0xb2, 0x79, 0x7a, 0x87, 0x25, 0xf7, - 0x4a, 0xd6, 0x0a, 0x31, 0x6c, 0xaf, 0x2a, 0x55, 0xe0, 0x7c, 0x84, 0x75, 0x11, 0x4f, 0x7b, 0xc3, 0x12, 0xbf, 0xbe, - 0x26, 0x96, 0x17, 0x2a, 0x53, 0x09, 0xdd, 0xaf, 0x49, 0xe4, 0x4b, 0x46, 0x6c, 0xde, 0xe8, 0x7e, 0x1b, 0x57, 0x70, - 0x61, 0x46, 0x29, 0xbd, 0x91, 0x3d, 0x4a, 0xf4, 0x0c, 0xaf, 0xca, 0x81, 0x1a, 0x0d, 0x67, 0x86, 0x8c, 0x56, 0x9c, - 0x71, 0x22, 0x09, 0x7a, 0x87, 0x2a, 0xa2, 0x28, 0x80, 0x7d, 0x24, 0x8a, 0x88, 0x3e, 0x97, 0xb4, 0xca, 0x4d, 0x38, - 0x0d, 0xac, 0x8b, 0xef, 0x3a, 0x25, 0x5e, 0x0a, 0x8f, 0x3f, 0x8a, 0x7e, 0xf3, 0xf3, 0x2c, 0xee, 0xb6, 0x40, 0x06, - 0x1e, 0x6e, 0x60, 0x22, 0xd8, 0x2f, 0x90, 0x8b, 0xd5, 0xc5, 0x0d, 0x48, 0x54, 0x01, 0xf5, 0x4b, 0x72, 0x47, 0x76, - 0x5b, 0xa5, 0xd9, 0x68, 0x61, 0x43, 0x61, 0xd2, 0xb6, 0x9a, 0x1a, 0xe7, 0xb8, 0xcb, 0x0a, 0xb4, 0xd9, 0xdc, 0x65, - 0x19, 0x02, 0xc3, 0x61, 0x34, 0xc2, 0x46, 0x1a, 0x4e, 0xc9, 0x4b, 0x1d, 0x6f, 0x5a, 0x1e, 0xd4, 0x22, 0x2c, 0xc8, - 0xb1, 0x42, 0x3b, 0x4b, 0x16, 0x6b, 0xac, 0xe2, 0x2c, 0x72, 0x2c, 0x3b, 0x5c, 0x49, 0x40, 0xd1, 0x1c, 0x22, 0x8a, - 0x62, 0x90, 0x38, 0x5a, 0x9a, 0x4a, 0x81, 0x31, 0xd5, 0x8f, 0x60, 0x17, 0x9b, 0x94, 0x1d, 0x47, 0x23, 0xc5, 0xc2, - 0x37, 0x14, 0xda, 0xdf, 0xa5, 0x39, 0xce, 0x46, 0x24, 0x23, 0x8b, 0xfc, 0xb9, 0x54, 0x4a, 0x58, 0xe5, 0x59, 0xbb, - 0x9b, 0x3b, 0x4d, 0x17, 0x49, 0xcd, 0x50, 0xb4, 0xd3, 0x92, 0xc5, 0x42, 0x03, 0x74, 0xfc, 0x25, 0xeb, 0xee, 0xb3, - 0x80, 0x5b, 0x1b, 0x66, 0x5d, 0x48, 0x17, 0x68, 0xce, 0xd5, 0x39, 0x85, 0xbf, 0x9b, 0x19, 0xf0, 0x1d, 0x5b, 0xec, - 0x74, 0x78, 0xb2, 0x39, 0xd0, 0x96, 0x0d, 0x77, 0xf8, 0xb5, 0xf0, 0xe8, 0x76, 0x48, 0x69, 0x9e, 0x26, 0xa6, 0x31, - 0xfd, 0x8a, 0xd7, 0x07, 0xb8, 0xa2, 0xbc, 0x22, 0xc0, 0xd6, 0x77, 0x3e, 0x97, 0xb4, 0x53, 0x59, 0x20, 0x2d, 0x99, - 0x38, 0x49, 0x93, 0xf5, 0xf5, 0x79, 0xef, 0x88, 0x4a, 0x8c, 0x5e, 0xc9, 0xa7, 0xb1, 0x69, 0xdc, 0x57, 0x9f, 0x47, - 0xc0, 0x5b, 0xdf, 0xcc, 0xf8, 0x1b, 0x93, 0x11, 0x86, 0xbd, 0x03, 0x5a, 0x8d, 0x75, 0xac, 0x37, 0x60, 0x7f, 0x17, - 0x47, 0x4b, 0x16, 0xa8, 0x29, 0x5a, 0xd5, 0x51, 0x48, 0xb9, 0xec, 0x3e, 0x77, 0x1a, 0x89, 0x45, 0x52, 0x2c, 0xa0, - 0xf3, 0x5d, 0x9a, 0xf7, 0x1b, 0x94, 0xfa, 0x64, 0x35, 0x85, 0x64, 0xd3, 0x59, 0x52, 0x17, 0xba, 0xd7, 0x74, 0x97, - 0x66, 0xee, 0xbc, 0x91, 0xb8, 0xfe, 0x0e, 0xed, 0xd2, 0x15, 0xec, 0x33, 0xae, 0xa0, 0xa6, 0x34, 0xba, 0x38, 0x36, - 0xbe, 0xf8, 0x6f, 0xd3, 0x92, 0x69, 0xf5, 0xd1, 0x26, 0x20, 0xf1, 0x12, 0x4a, 0x6c, 0xfe, 0x2f, 0xdc, 0xc1, 0x94, - 0xa8, 0x8f, 0x18, 0x11, 0xf7, 0x48, 0x5b, 0x86, 0x07, 0x68, 0x02, 0xb9, 0x16, 0x04, 0x28, 0xe9, 0x89, 0xa6, 0x6f, - 0xb5, 0x3a, 0x07, 0x83, 0x97, 0x66, 0x6c, 0x93, 0x20, 0x74, 0xa8, 0x17, 0xd2, 0x5e, 0xc9, 0x5b, 0x73, 0xd6, 0x70, - 0x8e, 0xa9, 0x05, 0x7f, 0x4a, 0xcd, 0x9c, 0x99, 0xce, 0xbb, 0x21, 0x39, 0x88, 0xcc, 0xd5, 0xd4, 0x0c, 0xa9, 0x63, - 0x15, 0xad, 0x9a, 0xe4, 0x7d, 0xf0, 0x5e, 0xe1, 0x44, 0x1e, 0xd4, 0xed, 0xd6, 0xed, 0xdd, 0x36, 0x92, 0x0c, 0x39, - 0x54, 0xb7, 0x89, 0x4a, 0x61, 0x94, 0x1c, 0x6b, 0x42, 0xdc, 0x81, 0x1b, 0x82, 0x52, 0xe8, 0x68, 0x92, 0xd2, 0x4a, - 0x9f, 0x65, 0x93, 0x8c, 0x4b, 0x6f, 0xa7, 0xbb, 0x65, 0xe0, 0x54, 0xd8, 0x56, 0xd5, 0xfd, 0x4d, 0x76, 0xed, 0x08, - 0x7e, 0x3b, 0x11, 0xea, 0xf8, 0x08, 0x11, 0x48, 0x97, 0xf0, 0x37, 0xdf, 0xbf, 0x67, 0xcf, 0xf5, 0xcb, 0x48, 0x26, - 0x64, 0x2a, 0x05, 0x70, 0x00, 0x99, 0xd6, 0x28, 0xbe, 0xb3, 0xaf, 0xaa, 0x2a, 0x38, 0x69, 0x03, 0x2f, 0xdc, 0x60, - 0x33, 0x26, 0x0f, 0x11, 0xad, 0x9b, 0x1c, 0x02, 0xb4, 0x55, 0xad, 0x47, 0xdf, 0x27, 0x23, 0x69, 0x39, 0x48, 0x06, - 0x1a, 0x6b, 0xdc, 0x8a, 0x09, 0x2f, 0x0d, 0x29, 0xba, 0x7e, 0x93, 0x17, 0xb1, 0x28, 0x89, 0xfe, 0xb3, 0xf0, 0x4a, - 0x66, 0x2a, 0xdc, 0xcf, 0xb1, 0x02, 0xf8, 0x10, 0xab, 0x1b, 0x2e, 0xae, 0xb1, 0xf0, 0xae, 0xae, 0x81, 0xe4, 0x9a, - 0x59, 0x1a, 0x04, 0xdc, 0x5e, 0xe1, 0x26, 0x40, 0x18, 0x7f, 0x26, 0x13, 0xb7, 0x1c, 0x60, 0xa8, 0x8f, 0xec, 0x9b, - 0xb9, 0x69, 0x8a, 0x47, 0x6a, 0xdd, 0x7b, 0x4f, 0xb2, 0xc0, 0x3d, 0x6f, 0x9e, 0x0b, 0x67, 0x76, 0x9d, 0x4e, 0xbb, - 0x67, 0xf3, 0xc8, 0xaa, 0x77, 0x55, 0xe2, 0xab, 0x5e, 0x26, 0xd7, 0x2b, 0xd7, 0x35, 0x68, 0x05, 0x13, 0x1f, 0x78, - 0x57, 0x15, 0x96, 0xe5, 0xf8, 0xda, 0xcd, 0x47, 0x18, 0x57, 0x0b, 0xfd, 0x66, 0xbd, 0x7a, 0x98, 0x35, 0x1e, 0x50, - 0x49, 0x0b, 0x66, 0xc3, 0x41, 0x6a, 0x40, 0x95, 0x09, 0x0a, 0x19, 0x39, 0x0f, 0x47, 0x7c, 0x8a, 0x3b, 0x66, 0x8b, - 0x93, 0x1e, 0x0a, 0x1e, 0x71, 0x8b, 0x50, 0x21, 0xf8, 0x1f, 0x06, 0x73, 0x10, 0x21, 0x29, 0x30, 0xdb, 0x12, 0xea, - 0xb0, 0xb8, 0x4c, 0x78, 0x7a, 0x54, 0xc4, 0xa4, 0x88, 0x41, 0x6e, 0x29, 0x55, 0x44, 0xed, 0x63, 0x68, 0x9b, 0x14, - 0x4d, 0x37, 0x0a, 0x91, 0x63, 0x49, 0x05, 0x37, 0xea, 0x39, 0x84, 0x1f, 0x51, 0xab, 0xdb, 0x53, 0xd2, 0x58, 0x5e, - 0x62, 0x19, 0xa5, 0xf1, 0xcd, 0x6b, 0x35, 0x3e, 0xf5, 0xe6, 0x88, 0xdc, 0x05, 0x00, 0x56, 0x7d, 0x4c, 0xf8, 0xa1, - 0x1e, 0xab, 0x8e, 0x30, 0x84, 0xf0, 0x36, 0x5d, 0xf1, 0x11, 0xb1, 0xda, 0xdc, 0x8f, 0x2f, 0x9f, 0x3d, 0xce, 0x2f, - 0x90, 0x48, 0x9d, 0x9a, 0x62, 0x88, 0x49, 0x5e, 0xf8, 0x35, 0xfa, 0x70, 0xd9, 0xbf, 0x4d, 0x5d, 0xf8, 0x70, 0xee, - 0xc3, 0x02, 0x16, 0xe5, 0x6f, 0xb4, 0xf6, 0x42, 0x50, 0x50, 0x4b, 0xcd, 0x44, 0x6d, 0x08, 0xc6, 0xae, 0x58, 0x51, - 0xc7, 0x9b, 0x69, 0x02, 0x50, 0x66, 0x34, 0x6b, 0x8a, 0xc1, 0x18, 0xd2, 0x9e, 0x6e, 0x3d, 0xee, 0x90, 0xca, 0x16, - 0x16, 0xd7, 0x75, 0x8f, 0xa6, 0x2e, 0x2c, 0x80, 0x12, 0x7e, 0x48, 0x91, 0xd6, 0x6e, 0xc3, 0x7e, 0x43, 0x62, 0x0a, - 0x7e, 0x57, 0x9b, 0x15, 0x89, 0x67, 0x2e, 0xdd, 0xad, 0x92, 0x69, 0x88, 0x73, 0xe1, 0x07, 0x22, 0xac, 0xdc, 0x46, - 0xcc, 0x29, 0x0f, 0x3d, 0x27, 0xfb, 0xd2, 0x2d, 0x63, 0x5b, 0x65, 0x01, 0x47, 0x9d, 0x76, 0x25, 0xbc, 0xe0, 0xb9, - 0xc5, 0xf5, 0x9d, 0x3f, 0x3c, 0x8e, 0x16, 0x82, 0x55, 0x3d, 0xb3, 0x18, 0x47, 0xa8, 0x28, 0x5c, 0x42, 0x10, 0xb7, - 0x41, 0x12, 0x61, 0x98, 0x57, 0xe3, 0xcd, 0x47, 0x86, 0xf5, 0x14, 0x06, 0x80, 0x56, 0xe2, 0xd0, 0x3d, 0x43, 0x19, - 0xc1, 0xbd, 0x34, 0x03, 0x94, 0x7b, 0xae, 0x32, 0x2f, 0xa7, 0xf6, 0x18, 0x06, 0x4e, 0x65, 0x6b, 0x83, 0x19, 0xca, - 0x88, 0xac, 0x03, 0x01, 0x62, 0x5f, 0x68, 0xad, 0xa4, 0x6c, 0xba, 0xc1, 0x01, 0x48, 0xd0, 0x54, 0x8a, 0x21, 0x42, - 0xec, 0xad, 0x4a, 0xa7, 0xa0, 0xc7, 0xc3, 0x43, 0x75, 0x9b, 0xa4, 0x42, 0xe0, 0x55, 0xb4, 0xc8, 0x40, 0x22, 0x7b, - 0xa0, 0x1d, 0xd4, 0x0d, 0x80, 0x24, 0x3b, 0xc7, 0x95, 0x82, 0xb4, 0x05, 0x80, 0x1e, 0x1b, 0xff, 0x33, 0x33, 0xc4, - 0x3c, 0x00, 0x79, 0xec, 0x5a, 0x38, 0x69, 0xbc, 0x11, 0x06, 0x0e, 0x17, 0x52, 0x06, 0xd3, 0xdb, 0x59, 0x05, 0x9d, - 0xc8, 0x44, 0xd8, 0xdc, 0x0a, 0xb6, 0xf1, 0xc1, 0x69, 0xea, 0x48, 0x54, 0x84, 0xbd, 0x15, 0xff, 0x58, 0x59, 0xb7, - 0x00, 0x65, 0xc5, 0x3d, 0x6e, 0xfb, 0x31, 0xfc, 0x6f, 0x02, 0x4a, 0xe2, 0x9c, 0xd9, 0x4b, 0x25, 0xd3, 0x29, 0x79, - 0x71, 0xae, 0xf5, 0xd1, 0xa0, 0x3d, 0xb0, 0x7b, 0x3c, 0x05, 0x9b, 0x3b, 0x51, 0xb9, 0x5b, 0xd3, 0xc8, 0x13, 0xb7, - 0xa8, 0xaa, 0x69, 0x0b, 0x89, 0x26, 0xb8, 0xc8, 0xac, 0xa9, 0x52, 0xee, 0x16, 0x87, 0x01, 0xa4, 0xd0, 0x18, 0x06, - 0x36, 0xb9, 0xef, 0x38, 0x8a, 0x79, 0x11, 0x9e, 0x48, 0xb2, 0xeb, 0x82, 0x52, 0x7e, 0x9a, 0x9a, 0x65, 0x4a, 0xd8, - 0x94, 0x58, 0x86, 0xc3, 0xda, 0x41, 0x98, 0xed, 0x1d, 0x11, 0x95, 0x0a, 0xa3, 0x1d, 0x93, 0xca, 0x26, 0x19, 0xf9, - 0x1d, 0x5a, 0xc4, 0x49, 0xb0, 0x3a, 0xdb, 0x36, 0x55, 0x31, 0x37, 0x07, 0xf5, 0x08, 0xf7, 0x96, 0x19, 0x6c, 0x62, - 0x59, 0x24, 0x6b, 0xb7, 0x56, 0xcd, 0x62, 0xa5, 0x6e, 0xfd, 0x3e, 0xb1, 0xf1, 0x26, 0x52, 0x67, 0x28, 0x84, 0x8d, - 0x9b, 0x11, 0x05, 0xbd, 0xf1, 0x70, 0x16, 0xed, 0xb4, 0x79, 0x3f, 0xc9, 0xaa, 0x2e, 0x90, 0x97, 0x8a, 0xa8, 0x6a, - 0x66, 0x83, 0xfd, 0x94, 0xf2, 0x34, 0xf0, 0x28, 0x73, 0x27, 0x25, 0xa1, 0x32, 0x97, 0x44, 0x45, 0x81, 0x49, 0x3c, - 0xc7, 0x7c, 0x10, 0x28, 0xf6, 0xc6, 0x38, 0xd4, 0x69, 0xdc, 0x36, 0x99, 0xdf, 0xf5, 0xa8, 0xe6, 0xa6, 0xb2, 0x80, - 0x34, 0x3f, 0x93, 0x49, 0xb6, 0xf2, 0xbd, 0x7d, 0xa8, 0x0f, 0x8f, 0x33, 0x4c, 0xb8, 0x8f, 0xe8, 0x1a, 0x46, 0x21, - 0x4e, 0xff, 0x76, 0xdb, 0x49, 0x2f, 0x2e, 0x6b, 0x3a, 0x41, 0x66, 0x68, 0x5c, 0x87, 0x9e, 0x0e, 0x1b, 0x91, 0xba, - 0xb1, 0x26, 0x02, 0xb9, 0x90, 0xee, 0xb7, 0x5b, 0xc0, 0x52, 0xb3, 0x63, 0x97, 0xe6, 0x75, 0x52, 0x9e, 0x55, 0x9f, - 0xfa, 0x8a, 0xe8, 0x75, 0x3d, 0xda, 0x36, 0x60, 0x8d, 0x59, 0x77, 0xe0, 0x9f, 0x83, 0x49, 0xe4, 0xcb, 0x79, 0x53, - 0xec, 0x53, 0xcd, 0x73, 0xcd, 0xbd, 0x5f, 0xce, 0xf1, 0x40, 0xd8, 0x9f, 0x32, 0x10, 0x1c, 0x44, 0x24, 0x24, 0x88, - 0x05, 0xe6, 0xc0, 0x5c, 0x2a, 0xa6, 0x26, 0x6a, 0x1b, 0xcc, 0x25, 0xb8, 0xb3, 0x1f, 0x0c, 0x72, 0x83, 0x63, 0xcb, - 0xf0, 0x2b, 0x7c, 0xc1, 0x52, 0x56, 0x23, 0x6d, 0x45, 0xb5, 0x3c, 0x96, 0xe8, 0x09, 0xd4, 0x52, 0x59, 0x2a, 0xdb, - 0x80, 0x2a, 0xc6, 0xd7, 0xf9, 0x7c, 0x86, 0x8a, 0xa2, 0x14, 0xcf, 0x53, 0xc8, 0x40, 0xbb, 0xfc, 0xc4, 0xb3, 0x2f, - 0x7d, 0x9f, 0x09, 0x5c, 0xcb, 0x92, 0x47, 0xe4, 0x99, 0xe6, 0xc3, 0x72, 0xbd, 0x5a, 0xca, 0xd5, 0x0c, 0x11, 0xe0, - 0x64, 0xb1, 0xd2, 0xa5, 0x31, 0x05, 0x82, 0x6b, 0xc2, 0x6e, 0x8b, 0x85, 0x9b, 0xf2, 0x0f, 0xe7, 0x65, 0x21, 0x5d, - 0x13, 0xe5, 0x48, 0x22, 0x3f, 0xe3, 0x0a, 0xd6, 0x00, 0xa9, 0x35, 0xe1, 0x44, 0x0e, 0x66, 0x13, 0x00, 0x9d, 0xba, - 0x46, 0xaf, 0xd6, 0xa8, 0xae, 0x5b, 0x00, 0x5b, 0xfa, 0x0c, 0x46, 0x86, 0x42, 0xd8, 0x88, 0x7e, 0x5d, 0x64, 0xd4, - 0xc7, 0x95, 0x82, 0x2e, 0xba, 0xc4, 0x12, 0xa0, 0x39, 0xb7, 0x49, 0xde, 0x28, 0x8d, 0xe2, 0x53, 0xc6, 0x99, 0xe5, - 0xa4, 0x2e, 0x4e, 0xaa, 0x51, 0xde, 0x92, 0xcf, 0x40, 0xaa, 0x1b, 0x20, 0xbb, 0x94, 0x2b, 0x23, 0xf4, 0x8c, 0xa5, - 0x8b, 0xba, 0xc1, 0x6b, 0x29, 0x35, 0xf9, 0x7e, 0xcb, 0xbf, 0x42, 0x5c, 0x38, 0xe9, 0x02, 0x62, 0x02, 0x82, 0x94, - 0x56, 0x8e, 0x85, 0xf7, 0x1b, 0x37, 0xba, 0x28, 0xe4, 0x55, 0x32, 0xd0, 0x0a, 0x23, 0x63, 0xa4, 0x57, 0xa1, 0x55, - 0xb7, 0xe6, 0x57, 0x52, 0x9e, 0xa1, 0x0e, 0xb6, 0x31, 0x24, 0x64, 0x21, 0xc0, 0x67, 0x8d, 0x02, 0x52, 0x9f, 0x6a, - 0x69, 0x97, 0x94, 0xc4, 0x4a, 0xb1, 0xf6, 0x2d, 0x3e, 0x1a, 0xc3, 0xa7, 0x7e, 0xdd, 0xa9, 0xc9, 0xc2, 0x8d, 0xc5, - 0x1f, 0xfc, 0x82, 0x46, 0xb5, 0x11, 0x09, 0x0f, 0x08, 0x30, 0x55, 0x0d, 0x73, 0xab, 0xfb, 0x6c, 0xd6, 0xe8, 0xa9, - 0x1a, 0x00, 0xa0, 0x02, 0x31, 0xa9, 0xd7, 0x96, 0x69, 0xa2, 0xf5, 0xe0, 0xe7, 0xe9, 0xd5, 0xb5, 0x21, 0x8e, 0x75, - 0x3a, 0xa7, 0x60, 0x00, 0x67, 0x03, 0x54, 0x6d, 0xe3, 0xe5, 0xcd, 0xf6, 0xfc, 0x81, 0x77, 0x41, 0x6a, 0x02, 0x3e, - 0x47, 0xc9, 0xe0, 0xfb, 0x48, 0x03, 0x41, 0xf3, 0x03, 0xf2, 0x3c, 0xf6, 0x8d, 0x48, 0xe4, 0x81, 0xf3, 0x2b, 0x3e, - 0xde, 0x0e, 0xf7, 0x56, 0xc3, 0x2f, 0x63, 0x6b, 0x52, 0x07, 0x2c, 0x1f, 0x24, 0xb0, 0x5c, 0xa8, 0x7d, 0x64, 0x7c, - 0xe7, 0x13, 0x21, 0x4e, 0x51, 0xa1, 0x3e, 0x02, 0x62, 0xcc, 0x04, 0x8a, 0x45, 0x5a, 0xa2, 0xce, 0xaa, 0x7c, 0x87, - 0xb0, 0x80, 0xd0, 0x3a, 0x25, 0x86, 0xf1, 0x76, 0x24, 0xc0, 0xc0, 0x9d, 0x0c, 0x39, 0x71, 0xa3, 0xb9, 0x19, 0x75, - 0xcf, 0x99, 0xb0, 0x6d, 0xb0, 0x6a, 0xca, 0x7e, 0x77, 0x83, 0x0d, 0xf8, 0x14, 0x34, 0xe3, 0xf8, 0x20, 0xb6, 0xdb, - 0x81, 0xa8, 0x3a, 0xfb, 0xa6, 0x20, 0xdf, 0x64, 0x91, 0x14, 0x89, 0x02, 0x1d, 0x92, 0x0f, 0x92, 0x6e, 0x01, 0xf9, - 0x6c, 0x21, 0x8d, 0xb9, 0x7a, 0x94, 0x01, 0xe2, 0xf3, 0xf4, 0x61, 0x3d, 0xdc, 0x32, 0x30, 0x0e, 0x22, 0x3a, 0x44, - 0x7c, 0xd5, 0x96, 0x34, 0x8a, 0x21, 0x0f, 0xbb, 0xd6, 0x97, 0xd4, 0xb0, 0x0d, 0xb5, 0xf0, 0x1f, 0xc2, 0xb3, 0x18, - 0xa9, 0xb9, 0x8d, 0x3f, 0x72, 0x41, 0xa4, 0x77, 0x9c, 0x82, 0xd0, 0x72, 0x93, 0x07, 0x5a, 0xd5, 0x74, 0x9d, 0x56, - 0xae, 0x3b, 0x83, 0x17, 0x08, 0xdb, 0xa2, 0x3a, 0x08, 0xaa, 0x2b, 0x83, 0x7e, 0x74, 0x26, 0xdc, 0x63, 0x4c, 0x20, - 0xef, 0x89, 0x6a, 0x9c, 0xa7, 0x51, 0xaa, 0x98, 0x87, 0xdd, 0xd1, 0xb8, 0x5c, 0xfa, 0x13, 0x69, 0x23, 0x4e, 0xf4, - 0x61, 0x04, 0x32, 0xb5, 0x74, 0x79, 0x04, 0xf0, 0xb7, 0x79, 0xa5, 0x69, 0x83, 0x4b, 0x80, 0xf7, 0x2b, 0x5e, 0x22, - 0x50, 0xba, 0x25, 0xc7, 0xb5, 0xe3, 0xec, 0x36, 0x0a, 0x95, 0xfb, 0x9a, 0x76, 0xf8, 0x15, 0x22, 0x4a, 0x87, 0x71, - 0x48, 0x73, 0x60, 0x1e, 0x96, 0xcb, 0x25, 0xb0, 0x54, 0xed, 0x11, 0x8c, 0x25, 0x8f, 0x92, 0x5c, 0x5a, 0x64, 0x48, - 0xe3, 0xf8, 0x58, 0x45, 0x24, 0xfa, 0x19, 0xc7, 0x1e, 0x6b, 0x00, 0x73, 0x77, 0x6b, 0xbe, 0xa7, 0x65, 0x0b, 0x35, - 0xde, 0xdb, 0x25, 0x8a, 0x59, 0x34, 0x25, 0xce, 0x71, 0xd4, 0x40, 0xda, 0xe7, 0x34, 0x66, 0xe3, 0x37, 0xfd, 0x48, - 0x03, 0xc6, 0x6e, 0x3b, 0x10, 0x81, 0x48, 0x0c, 0xb3, 0x68, 0x85, 0x17, 0x64, 0xee, 0x5f, 0x26, 0x06, 0x1c, 0x19, - 0xc0, 0x19, 0xc6, 0x97, 0x81, 0xe2, 0x6e, 0x6d, 0x07, 0xc7, 0xcd, 0x62, 0x79, 0xfa, 0xf4, 0xfd, 0x32, 0x4f, 0x59, - 0x60, 0x0c, 0x3e, 0xd4, 0x65, 0xac, 0xa5, 0x1e, 0x6b, 0x52, 0x75, 0xb7, 0x67, 0x26, 0xde, 0xca, 0xd4, 0x2a, 0xe9, - 0xea, 0xb3, 0x47, 0x35, 0xa0, 0x76, 0x2c, 0x8f, 0xb4, 0x0d, 0x18, 0x14, 0x1e, 0xf7, 0x5e, 0x14, 0x92, 0xcf, 0xa3, - 0x13, 0x3e, 0x25, 0x03, 0x77, 0x1e, 0x15, 0x2e, 0xe3, 0xa8, 0x82, 0x17, 0x55, 0x50, 0x82, 0xf4, 0xb8, 0x4e, 0x21, - 0x45, 0x5a, 0x63, 0xa2, 0xa7, 0x45, 0x9f, 0x46, 0xa0, 0x20, 0x54, 0xc3, 0x40, 0x91, 0x43, 0x8e, 0x4c, 0x85, 0xd2, - 0x23, 0x1f, 0x2c, 0xb4, 0xf0, 0x79, 0x10, 0xf2, 0x1a, 0x77, 0xbd, 0x2c, 0x45, 0x10, 0xe1, 0x46, 0x5b, 0x6f, 0xf4, - 0xa3, 0xda, 0xed, 0xfa, 0x88, 0xf7, 0xb4, 0x83, 0x08, 0x2b, 0x53, 0x39, 0x3e, 0x72, 0xb6, 0xdb, 0x5f, 0x86, 0x10, - 0xa0, 0xe6, 0x96, 0x65, 0xe1, 0x67, 0xc5, 0x7b, 0x7a, 0x02, 0x5c, 0xbe, 0xe3, 0x4c, 0xf7, 0x01, 0x3a, 0x72, 0x24, - 0xa2, 0xdc, 0xa6, 0xdf, 0x16, 0xfd, 0x33, 0x8a, 0xc6, 0x50, 0x1c, 0x6c, 0xff, 0xf1, 0xe3, 0xf0, 0xb4, 0xa7, 0xdc, - 0xc2, 0x28, 0xe9, 0x28, 0xbd, 0x72, 0xae, 0xda, 0x6a, 0x25, 0x8c, 0x19, 0xf4, 0x6b, 0x97, 0xb6, 0x4d, 0x47, 0xb3, - 0x61, 0xcc, 0xa2, 0xe3, 0x09, 0x6d, 0xc6, 0x9e, 0x37, 0x33, 0xe6, 0xa1, 0xc1, 0x9d, 0xc2, 0xfb, 0xe3, 0x90, 0x22, - 0x5a, 0xb7, 0x92, 0xa7, 0xfb, 0x7d, 0xca, 0xfe, 0xf4, 0x96, 0xee, 0xe2, 0x46, 0xf8, 0xf2, 0xbd, 0xf5, 0x63, 0xe1, - 0x41, 0xfb, 0xac, 0xa4, 0xcf, 0xd2, 0xfb, 0x2a, 0xb9, 0x16, 0xc8, 0x11, 0xa2, 0x73, 0x11, 0xae, 0x3b, 0xd2, 0x1a, - 0xa1, 0x03, 0x73, 0xd8, 0x8a, 0x6f, 0xcf, 0x30, 0x6a, 0x2e, 0xab, 0x9c, 0x77, 0x8b, 0x96, 0x91, 0xfc, 0xcd, 0x9b, - 0x0e, 0x5f, 0x6f, 0x1c, 0x61, 0xef, 0x51, 0x2c, 0xde, 0x7b, 0x65, 0x45, 0x50, 0x22, 0xfc, 0x46, 0x01, 0xc9, 0x1c, - 0x4e, 0xc8, 0xfe, 0xac, 0xf8, 0x9c, 0x73, 0x44, 0x20, 0x91, 0x87, 0xa5, 0x29, 0xc9, 0xd0, 0x81, 0x0d, 0xa9, 0xb3, - 0x7c, 0xe6, 0x94, 0x5f, 0x39, 0xd6, 0xef, 0xc1, 0xf6, 0x83, 0x69, 0x5b, 0x0c, 0x81, 0xcf, 0xe8, 0x0d, 0xca, 0x24, - 0x62, 0x96, 0xa7, 0x21, 0x6e, 0xdb, 0x07, 0x32, 0x48, 0x4b, 0xb9, 0xed, 0xb4, 0x68, 0xb9, 0x80, 0x54, 0xd9, 0x68, - 0xc6, 0x91, 0xc4, 0x19, 0x0b, 0xf1, 0x83, 0xb8, 0xec, 0xef, 0xc7, 0x88, 0x88, 0xe6, 0xad, 0x7f, 0x01, 0x97, 0x81, - 0x0b, 0xbf, 0xc8, 0x28, 0x4c, 0x45, 0xce, 0x21, 0xd6, 0x64, 0x09, 0xfe, 0x64, 0x58, 0x69, 0x45, 0x21, 0x0e, 0x2a, - 0xec, 0x8d, 0xff, 0xe1, 0xad, 0xbb, 0x55, 0x0e, 0x11, 0xcd, 0xde, 0x97, 0xec, 0x0c, 0x61, 0xa5, 0x7b, 0x4b, 0x01, - 0x81, 0x12, 0xea, 0xd1, 0x22, 0x4f, 0xca, 0x6a, 0x8f, 0xf6, 0xa5, 0xe4, 0x3d, 0xcf, 0x91, 0x20, 0x92, 0xb9, 0x83, - 0x75, 0x1d, 0xb0, 0x6f, 0x27, 0x5b, 0x35, 0xd0, 0xef, 0xf3, 0xd6, 0x21, 0x1c, 0x80, 0xfd, 0xa6, 0x67, 0x9a, 0xf7, - 0x44, 0xfa, 0x25, 0x57, 0x8c, 0xae, 0xad, 0x92, 0xb3, 0x3e, 0x1b, 0x43, 0x96, 0x21, 0xb9, 0x8a, 0xa1, 0x9e, 0xd4, - 0x31, 0xc2, 0x46, 0x41, 0xcf, 0x39, 0x31, 0x8f, 0x68, 0x32, 0xa0, 0x1e, 0xa7, 0xa7, 0xb4, 0x09, 0x20, 0xd3, 0xa2, - 0x43, 0x0f, 0x2a, 0x60, 0x59, 0x8d, 0xb4, 0x42, 0x65, 0x1a, 0x3a, 0x2a, 0xf7, 0xb4, 0x26, 0xcd, 0x9e, 0xc2, 0xaa, - 0x2b, 0x2d, 0x5b, 0x4e, 0xe7, 0xa8, 0x3c, 0x48, 0xb3, 0x29, 0x7c, 0x5c, 0x0e, 0x22, 0xb3, 0xa6, 0xe9, 0x6e, 0xfb, - 0x1b, 0x44, 0x94, 0x3c, 0x45, 0x2a, 0xa8, 0x90, 0x91, 0x87, 0x94, 0x2c, 0x91, 0x07, 0x4b, 0xa0, 0xf3, 0x83, 0x01, - 0xfd, 0x4e, 0x4c, 0x0c, 0x45, 0x6e, 0x57, 0x7c, 0x33, 0x11, 0xdc, 0xa9, 0x45, 0xe7, 0x6c, 0x97, 0x89, 0x2c, 0x85, - 0xb3, 0xab, 0x24, 0x7d, 0x4e, 0x34, 0x8a, 0x6e, 0xa4, 0xfb, 0x63, 0x84, 0x9f, 0xec, 0x4d, 0x11, 0xb4, 0x61, 0xbd, - 0x4e, 0x0f, 0xcb, 0x2d, 0x91, 0xff, 0x46, 0x79, 0xad, 0xb8, 0x70, 0x5e, 0xf2, 0x71, 0x43, 0x89, 0xad, 0xd8, 0x6c, - 0x9c, 0x41, 0x4a, 0xc0, 0x50, 0x3a, 0x41, 0xdb, 0x31, 0x8e, 0xea, 0x64, 0x0c, 0xed, 0x31, 0x7b, 0x23, 0x0a, 0xca, - 0xba, 0x9c, 0x79, 0x8e, 0x2d, 0xcb, 0x79, 0x6e, 0x3c, 0xa4, 0x94, 0x99, 0x9c, 0x71, 0xc8, 0xca, 0xcc, 0x8c, 0x34, - 0x06, 0x14, 0xde, 0x1e, 0x35, 0xbb, 0x13, 0xdb, 0xc9, 0x6a, 0x49, 0x36, 0x92, 0x55, 0x15, 0x71, 0x31, 0x09, 0xb3, - 0xc1, 0x15, 0x65, 0x12, 0x57, 0x17, 0x3b, 0xde, 0x2f, 0xfe, 0x74, 0xa8, 0x80, 0x8f, 0x6d, 0xaf, 0x4f, 0x43, 0x43, - 0xae, 0xa4, 0x61, 0xe2, 0x83, 0xe4, 0x22, 0xdd, 0xa9, 0xe4, 0xfd, 0x22, 0xbc, 0xbe, 0x6a, 0xd4, 0x19, 0x8e, 0xdd, - 0x36, 0x64, 0xfb, 0xc5, 0x30, 0x1e, 0x75, 0xa5, 0x0a, 0xef, 0x8f, 0xcd, 0xed, 0x16, 0xce, 0xbb, 0x19, 0xce, 0x1d, - 0x3a, 0x71, 0x06, 0xf9, 0x9f, 0x5f, 0x2d, 0xb6, 0x60, 0xa9, 0xe9, 0x37, 0x99, 0xfa, 0xc9, 0x3e, 0x70, 0x5b, 0xb6, - 0x1f, 0xe9, 0xb0, 0x31, 0xb2, 0x4f, 0xc3, 0x32, 0x62, 0xa7, 0x8f, 0x07, 0x1a, 0x82, 0xcd, 0xd5, 0xe5, 0x98, 0x0d, - 0xf6, 0xc7, 0xaf, 0xcd, 0xf9, 0x35, 0x2b, 0x17, 0xa9, 0x5f, 0xb2, 0x53, 0xfd, 0xca, 0x76, 0x91, 0xcb, 0x08, 0x70, - 0x46, 0x6f, 0xa5, 0xff, 0x43, 0x9e, 0x26, 0x89, 0x4a, 0xff, 0xe4, 0x0f, 0x92, 0xee, 0x7e, 0x9f, 0x3f, 0xb6, 0xb3, - 0x13, 0xf2, 0xc9, 0xc3, 0x6f, 0xa7, 0x30, 0x97, 0xcb, 0x65, 0x94, 0xb2, 0xda, 0x61, 0x17, 0x6c, 0xa5, 0x7d, 0x65, - 0xbd, 0xf6, 0x23, 0xb8, 0xa2, 0x64, 0x15, 0xc6, 0x25, 0xa1, 0x82, 0x4d, 0x3e, 0xa5, 0xad, 0xd3, 0x7e, 0xe1, 0xec, - 0x15, 0x03, 0x14, 0x11, 0x1f, 0x2b, 0x63, 0xbc, 0x87, 0xc4, 0xe1, 0x54, 0xa8, 0x61, 0x5a, 0xa9, 0xd2, 0x00, 0xe0, - 0xd0, 0xe8, 0xd7, 0x29, 0x8f, 0x39, 0x85, 0x7e, 0x78, 0xb9, 0x67, 0x55, 0x2c, 0xf9, 0xff, 0x7b, 0x1e, 0x06, 0x84, - 0xc8, 0x0a, 0x58, 0xba, 0x0f, 0x6b, 0x8a, 0x49, 0x24, 0x2a, 0x69, 0x12, 0x56, 0x23, 0x7d, 0x7b, 0x89, 0x57, 0x4d, - 0x67, 0x7c, 0x7f, 0xc7, 0x1c, 0x3a, 0xb6, 0xcc, 0x94, 0x32, 0x2a, 0x4d, 0xde, 0x2c, 0x45, 0xaa, 0x27, 0x91, 0xc7, - 0x54, 0x85, 0xfc, 0x72, 0x35, 0xfd, 0xd3, 0xee, 0x8b, 0xc0, 0xaf, 0x5e, 0x89, 0x21, 0xd6, 0x43, 0xf2, 0x09, 0x0d, - 0x76, 0xe7, 0x75, 0x12, 0x7a, 0x5e, 0xf9, 0x11, 0xef, 0xfb, 0xa1, 0x94, 0xed, 0x5a, 0xf5, 0xcc, 0xf3, 0xc4, 0x42, - 0x09, 0xb6, 0x91, 0x67, 0x0e, 0x3d, 0x69, 0x9c, 0x8e, 0x8e, 0xbd, 0x16, 0xd1, 0xa1, 0x0b, 0x1c, 0x7d, 0xc4, 0xec, - 0x82, 0x63, 0x7b, 0x0b, 0xfa, 0x18, 0x2c, 0xda, 0x89, 0x5e, 0x75, 0xb2, 0xe8, 0x2a, 0xb4, 0xbf, 0x14, 0x1d, 0x90, - 0x64, 0xd3, 0xb3, 0x60, 0x52, 0xef, 0x84, 0x9c, 0xcb, 0x7c, 0x3d, 0xb0, 0xf4, 0x7e, 0xc7, 0x40, 0x5d, 0x6e, 0xf8, - 0x6b, 0xcb, 0xac, 0xef, 0x1e, 0x99, 0xbe, 0x85, 0x5c, 0x44, 0x66, 0xd1, 0x05, 0x7a, 0x1d, 0xc6, 0xd7, 0xcc, 0xd3, - 0xdf, 0x86, 0x06, 0x93, 0xc9, 0xa0, 0x53, 0x89, 0x0a, 0xb0, 0x99, 0x62, 0xa3, 0xfa, 0x64, 0x47, 0x79, 0x58, 0x6b, - 0xee, 0x09, 0x7b, 0x97, 0xfd, 0xb2, 0xd8, 0x78, 0x03, 0x93, 0x20, 0x98, 0xa9, 0xe0, 0x2e, 0x48, 0x59, 0xc6, 0x74, - 0x85, 0x6b, 0x01, 0x6f, 0xcd, 0x1a, 0x37, 0x58, 0xcb, 0x57, 0xc9, 0x23, 0xa4, 0xfa, 0x93, 0x3d, 0x54, 0x25, 0x8e, - 0xfc, 0x3e, 0xf5, 0xd6, 0x5e, 0xfe, 0xe1, 0x44, 0x30, 0x14, 0xa5, 0x4b, 0x4f, 0x1e, 0xb9, 0x24, 0x6f, 0x41, 0x6b, - 0x56, 0xf4, 0xa0, 0x63, 0xe0, 0xa2, 0xc2, 0x66, 0x23, 0xa1, 0xe2, 0xbf, 0x86, 0xb6, 0x60, 0x14, 0xde, 0xe9, 0x34, - 0x46, 0x1e, 0x7d, 0x55, 0x2b, 0xed, 0x6e, 0x14, 0xb7, 0x22, 0x27, 0xcf, 0x79, 0xcd, 0xc1, 0x64, 0x4e, 0x98, 0xe4, - 0xe3, 0x7b, 0x43, 0xaf, 0x70, 0x4c, 0x4e, 0xb6, 0x73, 0x5e, 0x0f, 0x63, 0x07, 0x10, 0x31, 0xf9, 0x5b, 0x9f, 0xcc, - 0x6b, 0xaf, 0xc8, 0x67, 0x3e, 0x12, 0xb6, 0x97, 0x6c, 0xcc, 0x0b, 0xbe, 0xcd, 0x63, 0x74, 0xd5, 0xc1, 0x9c, 0x9a, - 0x2a, 0x35, 0x1b, 0x02, 0x7e, 0x95, 0x0a, 0x3f, 0x90, 0x09, 0x1a, 0xc7, 0x0e, 0xdd, 0xa5, 0x90, 0x11, 0xd0, 0xfe, - 0x32, 0x1e, 0x34, 0xf3, 0xf3, 0xf7, 0xcb, 0xd4, 0x0c, 0x9b, 0x3d, 0xf5, 0x4b, 0xe0, 0xe5, 0x51, 0xa5, 0xb7, 0xe3, - 0x4f, 0xa5, 0x50, 0x5e, 0x10, 0x47, 0x27, 0x3a, 0x0a, 0xf6, 0xb3, 0x3d, 0xe0, 0xdf, 0x23, 0x11, 0x4b, 0xee, 0x39, - 0x1f, 0x00, 0x72, 0xcd, 0x22, 0xb6, 0x51, 0x1e, 0xff, 0x1a, 0x60, 0x66, 0xc6, 0x6c, 0xa7, 0x59, 0x56, 0x1e, 0x58, - 0x68, 0x7b, 0x8c, 0xc8, 0x7c, 0x3b, 0x6c, 0xc2, 0x29, 0x3a, 0x7c, 0xbd, 0x6d, 0x5a, 0xd9, 0x82, 0x1f, 0x50, 0x05, - 0x7f, 0x9f, 0x05, 0x67, 0x54, 0xc9, 0x13, 0xdc, 0x37, 0x3b, 0xa2, 0x0a, 0x5e, 0x91, 0x79, 0x37, 0x98, 0x10, 0x43, - 0xf1, 0xe5, 0x1b, 0xf2, 0x28, 0xc9, 0x55, 0xb0, 0x5e, 0x99, 0xca, 0x47, 0x8b, 0x7b, 0x9a, 0x58, 0x81, 0x71, 0x58, - 0x30, 0xd1, 0xc1, 0x8c, 0x29, 0x83, 0xb5, 0xec, 0xb9, 0xc1, 0x24, 0x20, 0x24, 0x80, 0x79, 0x0e, 0x52, 0xfa, 0x6b, - 0xd8, 0x3d, 0x26, 0x80, 0x13, 0x1a, 0x14, 0x84, 0xc2, 0x3c, 0x2b, 0x2a, 0x1a, 0x3a, 0xa6, 0xca, 0x12, 0x1b, 0x38, - 0xbd, 0xb2, 0x37, 0xf8, 0xc8, 0x04, 0x4f, 0x1e, 0x6a, 0xae, 0xdf, 0x4d, 0xdf, 0xbe, 0xe7, 0x5e, 0x28, 0x9a, 0x8a, - 0xb6, 0x5a, 0xac, 0xbf, 0x13, 0xf4, 0xb9, 0x90, 0x64, 0x17, 0xdb, 0x32, 0xc3, 0x8a, 0x19, 0x67, 0xcd, 0x45, 0xeb, - 0x45, 0x3d, 0x7f, 0x5a, 0x12, 0x82, 0xb8, 0xb7, 0x38, 0xd1, 0xe5, 0x94, 0x79, 0xe7, 0x3d, 0xd9, 0xe9, 0x46, 0x3c, - 0xc9, 0x5d, 0x55, 0x7e, 0x6c, 0xa7, 0xf6, 0x50, 0xc9, 0x5c, 0x42, 0x45, 0x09, 0x20, 0xda, 0x29, 0xa5, 0xe7, 0xf1, - 0x17, 0x37, 0x74, 0x41, 0x46, 0x4e, 0x1e, 0x6f, 0x45, 0x3b, 0xa3, 0x95, 0x8f, 0x91, 0x89, 0x83, 0x59, 0x80, 0xc0, - 0x9d, 0xb3, 0x41, 0x0d, 0x8a, 0x3f, 0x6d, 0xcc, 0x69, 0xa8, 0x79, 0x09, 0xd0, 0x0f, 0xe5, 0x7d, 0x73, 0xe7, 0xaa, - 0x9f, 0xb8, 0xd3, 0x75, 0x47, 0xeb, 0xdd, 0x82, 0x42, 0xbb, 0x3a, 0xad, 0x37, 0x29, 0xc7, 0x16, 0x6d, 0xc3, 0xea, - 0x6d, 0xf9, 0xf7, 0xdb, 0x8a, 0x7c, 0xac, 0x5b, 0x2d, 0x8e, 0xd3, 0x0f, 0xa4, 0x5a, 0x27, 0xf5, 0xdc, 0xcf, 0xca, - 0x71, 0xf2, 0x3f, 0xc4, 0xa0, 0xf3, 0x7a, 0xea, 0xa9, 0x10, 0x38, 0x17, 0x51, 0x9d, 0xdc, 0x54, 0x68, 0xae, 0x27, - 0x2b, 0xc4, 0x2b, 0x65, 0xc4, 0xd7, 0x1f, 0xcd, 0xef, 0xf5, 0xa0, 0x31, 0xa2, 0x87, 0x01, 0x0a, 0x64, 0xc4, 0xcb, - 0xfe, 0xf3, 0xa2, 0xa2, 0xd5, 0xdb, 0xc9, 0xcd, 0x1d, 0x65, 0xcf, 0x1e, 0x3f, 0x36, 0x75, 0xf1, 0xe4, 0x36, 0xac, - 0x18, 0xf3, 0x81, 0x19, 0x85, 0x0d, 0x0c, 0xdd, 0x44, 0x18, 0x5c, 0xee, 0xc8, 0xd5, 0xc9, 0xc8, 0x10, 0x0c, 0xc4, - 0x7d, 0x61, 0x25, 0x29, 0xed, 0x65, 0xa2, 0x6f, 0x50, 0xaf, 0xb6, 0xa1, 0x75, 0xb4, 0x2a, 0x53, 0xa8, 0x9b, 0x10, - 0x41, 0x79, 0xf5, 0x84, 0xbb, 0x36, 0x19, 0xc7, 0x49, 0x24, 0x39, 0x56, 0x77, 0x19, 0xbb, 0x7d, 0x56, 0xaa, 0x86, - 0x4c, 0x75, 0x6a, 0xcd, 0x40, 0xbb, 0xe3, 0xe4, 0x62, 0x28, 0xf9, 0xfd, 0xa5, 0x3a, 0x0e, 0x33, 0xc4, 0xfb, 0x81, - 0x01, 0x7a, 0xe3, 0x26, 0x1b, 0x5b, 0xc6, 0xe6, 0xd0, 0xb9, 0x1c, 0x12, 0x88, 0xdf, 0x30, 0xf6, 0xbe, 0xa5, 0x31, - 0xb4, 0x93, 0x1b, 0x2a, 0x0f, 0xbe, 0x88, 0xe1, 0x98, 0x58, 0xe4, 0x84, 0x92, 0x33, 0x23, 0xc6, 0x8a, 0xff, 0x96, - 0xae, 0x5a, 0xf9, 0x3f, 0x9c, 0xbc, 0x8d, 0x3f, 0x28, 0xcf, 0x8f, 0x32, 0xb6, 0x28, 0xbc, 0x09, 0xe5, 0xa9, 0x5a, - 0xe1, 0x99, 0x54, 0x90, 0x35, 0x2c, 0xdc, 0xa8, 0xf9, 0x33, 0xcf, 0xc3, 0xf0, 0xbb, 0x1e, 0x22, 0x37, 0xc5, 0xcb, - 0x96, 0xfd, 0x50, 0x9d, 0x3d, 0xb4, 0x77, 0x1d, 0x03, 0x78, 0x98, 0x0d, 0x28, 0xdc, 0xb9, 0x3f, 0x15, 0xcf, 0x47, - 0xc0, 0x03, 0x38, 0x5e, 0x4f, 0xbe, 0x6a, 0xc9, 0x45, 0xc4, 0x78, 0xab, 0xe9, 0x40, 0xf6, 0x84, 0x7b, 0x2b, 0x43, - 0x63, 0xdd, 0x44, 0x03, 0x61, 0xf8, 0xf0, 0xda, 0xe1, 0xf4, 0xbe, 0x53, 0x7c, 0xf5, 0x0c, 0x50, 0x7d, 0xe0, 0x9f, - 0xc2, 0x83, 0xaf, 0xe4, 0x51, 0x68, 0x6f, 0x50, 0x0b, 0xa8, 0xe8, 0x70, 0x12, 0xa6, 0x00, 0x87, 0x60, 0x5b, 0x12, - 0xb4, 0x34, 0xa9, 0xfa, 0x4e, 0x52, 0xf5, 0xf4, 0x10, 0x86, 0x5f, 0xcf, 0x3c, 0xd7, 0x34, 0xdb, 0x4c, 0x65, 0x9f, - 0x7c, 0x3d, 0x38, 0xac, 0x0c, 0x93, 0x89, 0xcf, 0x3a, 0xc4, 0x4a, 0x30, 0x0c, 0x26, 0x0a, 0x9e, 0xff, 0xda, 0x6e, - 0x40, 0x26, 0xb5, 0x9c, 0xae, 0x4f, 0x7c, 0x8b, 0x65, 0x1e, 0x39, 0x9e, 0xdb, 0x9b, 0x9e, 0x24, 0x62, 0x0c, 0x67, - 0xea, 0xfe, 0x40, 0x4e, 0x2b, 0xcb, 0x78, 0xdd, 0xfa, 0x63, 0x02, 0xf9, 0x7c, 0x55, 0x35, 0x7b, 0x76, 0x55, 0x6d, - 0x2d, 0xf0, 0x5e, 0xe5, 0xa9, 0xfb, 0xf7, 0x73, 0xd1, 0xa2, 0x09, 0x42, 0x19, 0x41, 0x3b, 0xcc, 0x84, 0x55, 0xc2, - 0x4c, 0x23, 0xa5, 0x4a, 0x6b, 0x93, 0xb3, 0xcf, 0xd5, 0x56, 0xf3, 0x08, 0x03, 0x0c, 0x66, 0x24, 0x58, 0xaf, 0xfa, - 0x14, 0xa9, 0x37, 0x1c, 0x95, 0x38, 0xfc, 0x56, 0x86, 0xdc, 0x92, 0x82, 0xfb, 0x2a, 0xb1, 0xbf, 0x94, 0x88, 0x1e, - 0x4c, 0x8c, 0x03, 0xf7, 0xa2, 0x9b, 0x7e, 0x84, 0x7a, 0x95, 0x72, 0x71, 0x7a, 0x22, 0x35, 0x6f, 0x74, 0x58, 0x20, - 0x14, 0xf0, 0xd8, 0x64, 0xf7, 0x43, 0x0c, 0x9b, 0xe7, 0xc3, 0xfa, 0x31, 0x5e, 0xe1, 0x0b, 0xda, 0x53, 0x48, 0x03, - 0xb7, 0xf5, 0x8e, 0x3e, 0x28, 0x87, 0xce, 0x6a, 0x33, 0x4e, 0xcc, 0x89, 0x2a, 0x31, 0x19, 0x3b, 0x31, 0x9b, 0xd1, - 0x23, 0x5d, 0xb5, 0xe3, 0x39, 0xa6, 0xa4, 0x04, 0x40, 0x4d, 0x76, 0xf8, 0xfb, 0x6f, 0xe9, 0xad, 0xb6, 0x05, 0xb1, - 0xd6, 0xb0, 0x41, 0x5a, 0x5d, 0xb4, 0x71, 0x53, 0xf8, 0xf3, 0x36, 0x3d, 0x9a, 0x57, 0x42, 0x48, 0xd4, 0xd9, 0x21, - 0x3e, 0x98, 0x4c, 0xa0, 0x53, 0x72, 0x4a, 0xde, 0x4e, 0xea, 0x78, 0xcb, 0x15, 0xcf, 0x81, 0x84, 0xe4, 0x27, 0x83, - 0xa1, 0x88, 0xb9, 0xcb, 0xad, 0x46, 0x69, 0xc7, 0x7b, 0xdc, 0x2f, 0x15, 0x7c, 0xac, 0x96, 0x4b, 0xb2, 0x0f, 0xc2, - 0x37, 0x8e, 0x9d, 0x90, 0xc8, 0x31, 0x69, 0x24, 0x86, 0xeb, 0x96, 0x28, 0x96, 0x94, 0x9d, 0xda, 0xd3, 0x30, 0xe0, - 0x3a, 0x69, 0xa5, 0xf0, 0x69, 0x3a, 0x3e, 0xa4, 0x78, 0x82, 0x91, 0x75, 0x05, 0x78, 0xab, 0x1d, 0x0b, 0x0f, 0xf6, - 0x21, 0x75, 0x37, 0x82, 0x5d, 0x01, 0x51, 0x2f, 0x53, 0x94, 0x30, 0x39, 0x5a, 0x94, 0xcc, 0xf9, 0x11, 0x6b, 0x3d, - 0x9e, 0xa4, 0x94, 0x6e, 0x1f, 0xad, 0xcf, 0x9a, 0x0c, 0x3e, 0xa6, 0xd8, 0x0d, 0x90, 0x43, 0x00, 0x04, 0xee, 0xab, - 0xfc, 0x8a, 0xab, 0xcb, 0x55, 0x58, 0x68, 0xcc, 0x4a, 0x51, 0x11, 0x52, 0xed, 0x04, 0xa6, 0xdd, 0xd6, 0xcc, 0x0b, - 0x7d, 0x95, 0x91, 0xf3, 0x70, 0x8d, 0x94, 0x49, 0x49, 0xc5, 0x0c, 0x94, 0xa1, 0xf3, 0x88, 0x62, 0xb4, 0xd8, 0xcc, - 0xb5, 0x40, 0x3c, 0xb2, 0x7f, 0x05, 0x87, 0x3c, 0x96, 0x32, 0x33, 0x07, 0xa8, 0xc3, 0x73, 0xc7, 0x39, 0xe7, 0xf7, - 0x97, 0xe2, 0xab, 0x14, 0x50, 0x7d, 0xbe, 0x99, 0x27, 0x43, 0x91, 0xe8, 0xd2, 0x2c, 0x4b, 0x52, 0xd2, 0x60, 0xfb, - 0xc2, 0xba, 0x1a, 0x97, 0x6e, 0x5d, 0x49, 0x75, 0x29, 0xaf, 0xc3, 0xc8, 0x30, 0xad, 0x54, 0xc7, 0xd2, 0xab, 0x6a, - 0xb6, 0x46, 0xf8, 0x59, 0xd4, 0xd2, 0xe3, 0xf5, 0x64, 0xda, 0xc9, 0x2e, 0xdc, 0x50, 0x82, 0xe5, 0x00, 0x3f, 0x43, - 0x6a, 0x42, 0xae, 0xca, 0x69, 0x10, 0x80, 0x12, 0x81, 0x11, 0xe2, 0xe3, 0xa9, 0x9f, 0xe7, 0x8a, 0x19, 0x06, 0xe6, - 0x7b, 0x44, 0xd0, 0xd4, 0x21, 0x61, 0x68, 0xac, 0xba, 0x0d, 0x2d, 0xde, 0x73, 0xeb, 0xa3, 0xc8, 0x45, 0x2b, 0x47, - 0x3d, 0x20, 0xb7, 0xdd, 0x9e, 0xe9, 0x6a, 0x70, 0x83, 0xdc, 0x43, 0x3f, 0x81, 0x79, 0xec, 0xbd, 0x3e, 0x12, 0xab, - 0xe2, 0x98, 0xf5, 0x4e, 0xd1, 0xd9, 0xc3, 0x31, 0xe7, 0x7d, 0x7a, 0xa3, 0x9a, 0x46, 0xf3, 0x07, 0x31, 0xeb, 0x1b, - 0xbb, 0xd1, 0x6b, 0x5d, 0x73, 0x9c, 0xe7, 0x17, 0xc1, 0x74, 0x58, 0xd4, 0xde, 0xff, 0xed, 0x00, 0x35, 0x31, 0xba, - 0x6d, 0x19, 0x0b, 0x5c, 0x09, 0x69, 0x40, 0x2d, 0xdb, 0x7d, 0xea, 0xa2, 0x12, 0xf5, 0x41, 0x6e, 0xf5, 0xa2, 0x25, - 0xa2, 0x1a, 0x8b, 0x13, 0x5f, 0x6b, 0xef, 0x1a, 0xe9, 0x56, 0x6f, 0x72, 0x1b, 0xb4, 0x86, 0x74, 0x79, 0xaa, 0xa7, - 0xa7, 0xc0, 0xbd, 0x2c, 0xbe, 0x2a, 0xb3, 0x59, 0x64, 0x3b, 0xff, 0xf1, 0x90, 0xdd, 0xef, 0xa3, 0x32, 0x78, 0x7d, - 0x46, 0x33, 0x6f, 0xe1, 0xc7, 0xbd, 0x9b, 0x65, 0x00, 0xd6, 0x5e, 0x91, 0x9c, 0xf8, 0x5d, 0x24, 0x5d, 0x4b, 0xb3, - 0xcc, 0xd5, 0x29, 0x67, 0xd5, 0xdc, 0xce, 0xd9, 0x20, 0x9f, 0x67, 0xa8, 0xa0, 0xd9, 0xb4, 0xb1, 0x77, 0xbf, 0xc0, - 0x89, 0x78, 0x11, 0x46, 0xf8, 0x22, 0x76, 0xde, 0xa3, 0x2d, 0x35, 0xb7, 0x5a, 0xb6, 0xec, 0xab, 0x7c, 0x60, 0xee, - 0xd9, 0x2f, 0x82, 0x32, 0xa4, 0x07, 0x3b, 0xcb, 0x2e, 0x70, 0x89, 0x88, 0x97, 0xba, 0xbd, 0xb4, 0x76, 0x4f, 0x64, - 0x25, 0xcb, 0x8f, 0x9d, 0xa8, 0x60, 0x0e, 0x06, 0xb0, 0xc2, 0x19, 0x63, 0xc6, 0x1c, 0xc7, 0x83, 0x59, 0xef, 0x50, - 0xa8, 0x5c, 0x1f, 0x01, 0x3e, 0xd9, 0x63, 0x76, 0xe3, 0x2b, 0x17, 0x64, 0x0e, 0xce, 0xc7, 0x5e, 0x62, 0x48, 0x75, - 0x94, 0xdc, 0xcb, 0x30, 0xd1, 0x02, 0x6f, 0xcd, 0x2e, 0x05, 0xab, 0x70, 0x4f, 0x31, 0x3e, 0x0e, 0xfd, 0xa1, 0xcd, - 0xd9, 0x84, 0x21, 0xb3, 0xe0, 0x84, 0x25, 0xbb, 0x3a, 0x2f, 0x28, 0x92, 0x44, 0x1d, 0x61, 0xac, 0x37, 0x0a, 0xf5, - 0xa0, 0x88, 0x98, 0x50, 0xf5, 0x9a, 0x28, 0x3b, 0x1d, 0x98, 0xc0, 0xe7, 0x3c, 0xee, 0x4e, 0xd4, 0x87, 0x5d, 0xe5, - 0xf2, 0xff, 0xab, 0xe5, 0x27, 0x2a, 0x3e, 0x20, 0xc8, 0x9e, 0xf7, 0x14, 0xf6, 0x59, 0x4c, 0xdf, 0x62, 0x8b, 0xfd, - 0xba, 0xe5, 0x2b, 0xad, 0xb5, 0x47, 0x66, 0x0e, 0x35, 0x65, 0x83, 0x80, 0x8c, 0xd6, 0x77, 0x33, 0x3b, 0x7a, 0x04, - 0xfd, 0x49, 0xd3, 0x2b, 0x0a, 0x15, 0x60, 0xff, 0xde, 0xaf, 0x6c, 0x14, 0x52, 0xe4, 0xae, 0xae, 0x5d, 0x68, 0x48, - 0xbb, 0xcb, 0x6f, 0x94, 0x2a, 0x94, 0x03, 0xa1, 0xc5, 0x41, 0xd5, 0x29, 0xee, 0x7d, 0xcc, 0x5a, 0xd7, 0x70, 0x8d, - 0x60, 0x03, 0x31, 0x87, 0xd4, 0x38, 0x32, 0x0f, 0x7d, 0xa5, 0x6e, 0x80, 0x1b, 0x37, 0x1a, 0x61, 0xc5, 0x8f, 0x9d, - 0x77, 0xbf, 0xc8, 0x57, 0xc2, 0xcc, 0x47, 0x44, 0xa2, 0x9b, 0x3e, 0x6e, 0xb6, 0x99, 0x9d, 0xcd, 0x8f, 0x54, 0x57, - 0x30, 0x6c, 0x93, 0x29, 0xc4, 0x31, 0x4d, 0xef, 0x90, 0xe7, 0xc1, 0x8f, 0x9e, 0x4c, 0xb0, 0xb9, 0x2b, 0x48, 0xad, - 0x5a, 0x14, 0x18, 0xca, 0x2e, 0x45, 0x09, 0x9f, 0xfd, 0xba, 0xa7, 0x90, 0x76, 0x31, 0x5a, 0xf9, 0x69, 0x87, 0x22, - 0x03, 0xfa, 0x97, 0xdf, 0x07, 0x6c, 0xab, 0x4a, 0xc7, 0x23, 0xab, 0xdd, 0x2b, 0x7e, 0x6a, 0x39, 0x43, 0xdf, 0x22, - 0xad, 0xc4, 0xe0, 0x87, 0xeb, 0x80, 0x90, 0x0a, 0x21, 0x5e, 0xf4, 0x27, 0x3e, 0xec, 0xc5, 0x25, 0x65, 0xaa, 0xb5, - 0x18, 0xfe, 0x24, 0x77, 0xe2, 0x12, 0xce, 0xbe, 0xea, 0xbe, 0x44, 0xc4, 0xf7, 0xe2, 0x01, 0x84, 0x30, 0xa8, 0xd4, - 0x6f, 0x35, 0x52, 0x41, 0xc4, 0x8f, 0xe4, 0xe7, 0xf9, 0x7f, 0xeb, 0xd8, 0x1f, 0x74, 0x5e, 0xde, 0xbb, 0xec, 0x02, - 0x04, 0x1d, 0x7f, 0x0f, 0x8b, 0x11, 0xdb, 0x03, 0x46, 0xa4, 0x28, 0xb4, 0x20, 0xd0, 0x4d, 0xf8, 0x7b, 0xb8, 0x05, - 0xed, 0x81, 0xf7, 0x38, 0x24, 0x8e, 0xf2, 0x16, 0xfb, 0x8d, 0x1d, 0xee, 0xde, 0xdb, 0x5b, 0xdf, 0x71, 0x2b, 0x95, - 0x5d, 0x82, 0x72, 0x4f, 0xf9, 0xd8, 0xcd, 0x2c, 0xd0, 0x1c, 0x85, 0xf9, 0x7a, 0xc3, 0x89, 0x16, 0xdd, 0x3b, 0x30, - 0x51, 0xc8, 0x6e, 0x4d, 0xc5, 0xe0, 0xa3, 0x63, 0x25, 0x9a, 0xc5, 0x0e, 0x10, 0x04, 0xe8, 0x2e, 0x62, 0xc5, 0x42, - 0x5d, 0x1e, 0x68, 0x5e, 0x74, 0x10, 0x10, 0x8c, 0xfe, 0x4e, 0x01, 0x6b, 0xaf, 0x6c, 0x03, 0x87, 0x1c, 0x90, 0xd4, - 0x16, 0x26, 0xb7, 0x23, 0x4e, 0xf1, 0x8b, 0xd4, 0x0f, 0xad, 0xde, 0xce, 0xc4, 0x4e, 0x07, 0xbc, 0x83, 0x53, 0x95, - 0x8a, 0x1e, 0x12, 0x74, 0x84, 0x6f, 0xaa, 0xa1, 0x62, 0x25, 0xb8, 0x09, 0xfa, 0x40, 0xbe, 0x57, 0xfd, 0x26, 0x77, - 0xaa, 0xff, 0xa7, 0xcb, 0x5a, 0x39, 0x2c, 0x38, 0x5e, 0x86, 0xe5, 0x0d, 0x97, 0x7a, 0xdc, 0x0f, 0x67, 0x6c, 0xf4, - 0x8f, 0xcd, 0xda, 0xf9, 0xa7, 0x9f, 0x68, 0xd7, 0xbe, 0xef, 0x0f, 0x52, 0x0d, 0xab, 0xe1, 0xdd, 0xdf, 0x23, 0x35, - 0x25, 0x0a, 0x6a, 0x4b, 0x5f, 0x8e, 0x2e, 0xe4, 0xad, 0x9e, 0x7a, 0x8a, 0xd1, 0x7c, 0x8e, 0x23, 0x28, 0x8f, 0xe9, - 0x9e, 0x3e, 0x1b, 0x8c, 0xf8, 0xc8, 0xdf, 0x5d, 0xa0, 0x2a, 0xdc, 0xcb, 0xea, 0xcb, 0xe9, 0x46, 0xd8, 0x9c, 0x5e, - 0xa2, 0x39, 0x79, 0x86, 0xa1, 0x11, 0x15, 0xd3, 0xd2, 0x65, 0x31, 0x96, 0xaa, 0x62, 0x5e, 0x3a, 0x29, 0x16, 0xa5, - 0xd3, 0x62, 0xb9, 0xfe, 0x7e, 0xe6, 0x86, 0x51, 0xee, 0x8d, 0xb7, 0xd8, 0x1e, 0xd2, 0x64, 0x58, 0xfa, 0x88, 0xe9, - 0x28, 0x67, 0xed, 0xb7, 0xe4, 0xc2, 0xf2, 0xbe, 0xb1, 0x02, 0xd9, 0x78, 0xb5, 0xd6, 0x29, 0x92, 0x48, 0x1d, 0xbb, - 0xa8, 0xa5, 0x5d, 0x4f, 0xcf, 0x01, 0x2f, 0xfd, 0xbc, 0xb8, 0x5d, 0x72, 0x7c, 0x35, 0xe2, 0x1a, 0x5a, 0x0f, 0xad, - 0xd7, 0xbf, 0xd3, 0xa0, 0xd7, 0x15, 0x8d, 0xf4, 0xc7, 0x7b, 0x9c, 0x03, 0x3a, 0xa9, 0x01, 0x52, 0xf9, 0xec, 0xe2, - 0x89, 0x84, 0xcc, 0x15, 0x8e, 0x04, 0x15, 0x5f, 0xc8, 0xa5, 0xc8, 0x17, 0x6e, 0x61, 0x81, 0xdf, 0x39, 0x54, 0x9b, - 0x7b, 0xe4, 0x6c, 0x2a, 0x02, 0xe5, 0xc1, 0xde, 0x4d, 0x0d, 0x51, 0x53, 0xab, 0x39, 0x6f, 0xfa, 0x07, 0xb1, 0xef, - 0x88, 0x18, 0x8d, 0x16, 0x79, 0x81, 0x0f, 0x8f, 0x6c, 0xac, 0x1b, 0xa9, 0x12, 0x10, 0xee, 0xf4, 0x9d, 0xf7, 0xac, - 0xd4, 0x9a, 0xc1, 0x5b, 0x22, 0xad, 0xe5, 0xff, 0x6b, 0x90, 0x8e, 0x6e, 0x8b, 0x9e, 0x97, 0x01, 0x69, 0x4f, 0x17, - 0xab, 0x95, 0x45, 0xa3, 0xe0, 0x7e, 0xf0, 0xed, 0x86, 0x8a, 0xd0, 0xb0, 0xc9, 0xcc, 0x6d, 0x4d, 0x9f, 0x85, 0xcc, - 0x28, 0xfa, 0x88, 0x46, 0xb9, 0x71, 0x32, 0x75, 0x74, 0x9b, 0x4c, 0x08, 0x7c, 0x01, 0x54, 0x6a, 0x55, 0xc4, 0xa7, - 0x41, 0xf6, 0x43, 0x30, 0x6c, 0x08, 0xaf, 0x10, 0xe3, 0x23, 0xa8, 0xe9, 0xf3, 0xec, 0xea, 0xee, 0xc8, 0x8f, 0x08, - 0x4a, 0x70, 0x0d, 0x8f, 0xe4, 0x24, 0x06, 0x26, 0x8d, 0x26, 0x51, 0xe2, 0xe3, 0xd3, 0xbc, 0xf0, 0xa0, 0xad, 0xfe, - 0xe2, 0x5b, 0x04, 0xfe, 0xa6, 0xfe, 0xbb, 0x38, 0xfc, 0x1b, 0xa2, 0x6a, 0x59, 0x7c, 0xcc, 0xda, 0xa7, 0xf8, 0xfd, - 0x70, 0xcf, 0xed, 0xd3, 0x77, 0x13, 0x29, 0xe5, 0x57, 0x0e, 0xbf, 0x7b, 0x50, 0x3c, 0x00, 0xea, 0xe6, 0xed, 0x73, - 0x7e, 0x14, 0x60, 0xd9, 0xd6, 0xf8, 0xea, 0xc8, 0x85, 0x58, 0xb2, 0xae, 0xd7, 0xe5, 0xff, 0xe4, 0xbe, 0xfe, 0xd7, - 0x67, 0x0a, 0x19, 0x6f, 0x5f, 0x1e, 0x1d, 0x0f, 0x46, 0x23, 0xb3, 0xf2, 0xa6, 0x1b, 0x39, 0xdf, 0xbf, 0xe3, 0xd3, - 0xb7, 0xda, 0x88, 0x87, 0xc3, 0x47, 0x31, 0xb9, 0x74, 0x35, 0x75, 0x8c, 0x75, 0xc7, 0xb5, 0x4d, 0x97, 0x17, 0x19, - 0x6f, 0x03, 0xaf, 0x2b, 0x9b, 0xf5, 0xff, 0xa1, 0x29, 0x6d, 0x2e, 0xe5, 0xf0, 0x27, 0x0d, 0x0d, 0xfc, 0xb6, 0x94, - 0x2c, 0xa7, 0x97, 0xac, 0x5b, 0x48, 0xd0, 0xc9, 0xbb, 0x50, 0xb7, 0xb8, 0x47, 0x20, 0x41, 0x85, 0x46, 0xc4, 0x91, - 0x97, 0xf0, 0x4b, 0xba, 0x93, 0x57, 0xeb, 0x9e, 0x1e, 0xb9, 0x97, 0xc6, 0x2b, 0x41, 0x6b, 0x06, 0xae, 0x1d, 0x2c, - 0xe5, 0x8b, 0xd5, 0x87, 0x9c, 0xa7, 0xde, 0xf5, 0xd3, 0xd3, 0x0f, 0xb8, 0xfd, 0xbe, 0xa5, 0x46, 0x34, 0x7f, 0xf3, - 0xd7, 0x76, 0x10, 0x7b, 0x57, 0xa9, 0xb4, 0x12, 0xe5, 0xd8, 0xb9, 0xbc, 0x59, 0xfe, 0x58, 0x2d, 0x23, 0x03, 0x54, - 0xc5, 0xa4, 0xe0, 0x10, 0xe2, 0x43, 0xfd, 0x61, 0x1c, 0x2e, 0x4c, 0x34, 0xbd, 0x34, 0xbb, 0x77, 0x70, 0xe8, 0x83, - 0xa6, 0xbd, 0xd0, 0x65, 0xea, 0xdc, 0x94, 0xee, 0x7f, 0xc8, 0xfe, 0xf7, 0xda, 0xab, 0x40, 0x3f, 0x69, 0xa8, 0x26, - 0x61, 0x2b, 0xc5, 0xaf, 0x9d, 0xe0, 0x75, 0xc1, 0x00, 0xd3, 0xcb, 0xb3, 0x5b, 0x7a, 0xa2, 0x23, 0x19, 0xac, 0x87, - 0x71, 0x5f, 0x88, 0x12, 0xb2, 0xfc, 0x49, 0xae, 0xad, 0xec, 0x9f, 0x7f, 0x98, 0x5d, 0x5c, 0x4d, 0xe7, 0x10, 0x62, - 0xd6, 0x1c, 0x4a, 0x96, 0x83, 0xf8, 0x75, 0xa6, 0xbc, 0x14, 0x44, 0xba, 0xcd, 0x73, 0xca, 0x3c, 0x63, 0x89, 0x10, - 0xd5, 0x39, 0xc9, 0x13, 0xc4, 0x2e, 0x96, 0xd7, 0xfd, 0xb8, 0x7d, 0x43, 0x6f, 0xf7, 0x66, 0x2b, 0x31, 0xc8, 0x6b, - 0x10, 0x3b, 0x78, 0x25, 0x35, 0x01, 0x03, 0x45, 0x1e, 0x92, 0xef, 0xbb, 0xa2, 0x66, 0x3c, 0xef, 0xfe, 0xc6, 0xf1, - 0xe8, 0x45, 0xe6, 0xf1, 0x8d, 0x26, 0xcd, 0xbb, 0xd7, 0x66, 0x9c, 0x7b, 0x57, 0xf4, 0xdb, 0xc7, 0x4d, 0x3b, 0x3b, - 0x52, 0x73, 0x69, 0xb2, 0x65, 0xa1, 0xb0, 0x35, 0x1b, 0x7a, 0xc4, 0x61, 0xb2, 0x2d, 0x42, 0x0c, 0xda, 0x70, 0x5d, - 0x4a, 0x37, 0xb5, 0x09, 0xc2, 0x1d, 0x1a, 0x4c, 0x33, 0x26, 0x9d, 0x2a, 0xb0, 0xd7, 0xc8, 0x73, 0xd4, 0x93, 0x9f, - 0x69, 0x10, 0x2d, 0xf1, 0x97, 0x3c, 0xc0, 0xed, 0x92, 0x18, 0xe1, 0xb5, 0xc4, 0xde, 0x0a, 0x5f, 0x0b, 0x01, 0x8a, - 0xeb, 0xd5, 0x67, 0x95, 0x57, 0x02, 0xfb, 0x44, 0x13, 0xad, 0x8a, 0xef, 0xdb, 0x92, 0xbe, 0x5c, 0xb6, 0xd5, 0x10, - 0x5e, 0x3d, 0x4b, 0xdc, 0x21, 0x4b, 0x64, 0x35, 0x44, 0xbb, 0x84, 0x58, 0x73, 0x5b, 0xb2, 0xbf, 0xdc, 0x04, 0xd7, - 0x36, 0xed, 0x9e, 0xc5, 0xa2, 0x0f, 0xb6, 0x7e, 0x5c, 0x03, 0xb0, 0xbf, 0x44, 0x8e, 0x23, 0x56, 0x13, 0x68, 0xbb, - 0x42, 0xbf, 0x56, 0xda, 0x22, 0xe2, 0x42, 0xfe, 0x4f, 0x0f, 0x91, 0x56, 0x74, 0xdf, 0x73, 0xea, 0x6c, 0xfb, 0xdd, - 0x08, 0xf5, 0xec, 0x9a, 0xc4, 0x33, 0xda, 0x85, 0xf0, 0x47, 0x10, 0x2d, 0xd9, 0x97, 0x28, 0x7a, 0x02, 0x81, 0xc3, - 0x37, 0xe6, 0x75, 0xf4, 0xec, 0x73, 0xe8, 0xc8, 0x5a, 0x8c, 0x10, 0xc0, 0x48, 0xc5, 0x91, 0x73, 0x51, 0xd2, 0x24, - 0x0a, 0x16, 0x7d, 0x2e, 0x2e, 0x5c, 0x8e, 0xbb, 0x52, 0x5a, 0x5f, 0xf9, 0x81, 0xc2, 0x37, 0x75, 0x01, 0x92, 0x28, - 0x53, 0x53, 0x5d, 0xba, 0xad, 0x04, 0xd6, 0x09, 0xeb, 0xe9, 0x87, 0xe6, 0x2f, 0x59, 0x1d, 0x11, 0x93, 0x24, 0x15, - 0xd3, 0xeb, 0x88, 0x11, 0x7e, 0x57, 0x2d, 0x5e, 0x57, 0x2c, 0x36, 0xbd, 0x64, 0x34, 0x00, 0x46, 0x88, 0xa9, 0x8c, - 0x06, 0x29, 0xdd, 0xbf, 0x4c, 0x2d, 0x6d, 0x87, 0xe4, 0x67, 0x36, 0xd8, 0x75, 0x2b, 0xf4, 0x4f, 0xc3, 0x1e, 0x7c, - 0xbe, 0xe4, 0xc6, 0x1b, 0x9f, 0x60, 0xcd, 0xd9, 0x18, 0x14, 0x64, 0xcd, 0x0a, 0x7a, 0x2c, 0x6a, 0xab, 0xa7, 0xf0, - 0x31, 0x65, 0x21, 0x9c, 0xfc, 0x94, 0xae, 0x32, 0xf4, 0x5c, 0xdc, 0x63, 0x26, 0x51, 0x8f, 0xd7, 0x3d, 0xd4, 0xda, - 0xfa, 0x62, 0x26, 0xff, 0x26, 0x0e, 0x32, 0xb5, 0xd1, 0xac, 0x49, 0xef, 0xab, 0x30, 0x56, 0xbb, 0x18, 0xb6, 0x1d, - 0x0c, 0xbe, 0x12, 0xd1, 0xe7, 0x06, 0xc4, 0x6d, 0x44, 0xc6, 0x02, 0x3e, 0xd2, 0x91, 0x75, 0x45, 0xfd, 0xa5, 0xa0, - 0xaf, 0xe3, 0xfb, 0x5d, 0xe8, 0x8e, 0xbb, 0xc3, 0x9e, 0x5f, 0x48, 0xe2, 0x16, 0xf9, 0x0d, 0x5a, 0xbf, 0x7d, 0xe3, - 0xa5, 0x6d, 0x72, 0x4c, 0xdd, 0xf7, 0x79, 0x10, 0x80, 0xbc, 0x57, 0x41, 0x58, 0xd2, 0x3b, 0x2d, 0xa3, 0x97, 0xa1, - 0x94, 0x8b, 0xb2, 0xb2, 0xed, 0x74, 0xce, 0xfe, 0x3f, 0x6c, 0x43, 0xdb, 0xa9, 0x7c, 0x22, 0x33, 0xb4, 0xab, 0x00, - 0x89, 0x0f, 0x88, 0x3e, 0x3e, 0x69, 0xe5, 0xf8, 0xa3, 0x90, 0xec, 0x6d, 0x62, 0xf3, 0xb6, 0x1d, 0x83, 0xe8, 0x7b, - 0x84, 0x60, 0xd9, 0x1e, 0x42, 0xfe, 0xb1, 0xab, 0x72, 0x0b, 0x11, 0xdf, 0x7d, 0x5f, 0x5a, 0xea, 0xfa, 0xe2, 0xb7, - 0xff, 0x97, 0xd6, 0x80, 0x25, 0x3e, 0xc6, 0xeb, 0x74, 0xec, 0x0b, 0xf7, 0xe7, 0x78, 0xa2, 0x1b, 0xc7, 0xaf, 0xbe, - 0xf8, 0x78, 0x4b, 0x9c, 0xfb, 0x8b, 0x18, 0x69, 0xf5, 0xed, 0xa1, 0x9f, 0x11, 0xf4, 0xe3, 0x19, 0xc1, 0x13, 0xfa, - 0x29, 0x64, 0x3b, 0x86, 0xbf, 0x49, 0xa8, 0xe3, 0xd7, 0x8c, 0x87, 0x1f, 0x87, 0x29, 0x84, 0x91, 0x85, 0xaf, 0x51, - 0xcf, 0xc8, 0xaa, 0xc3, 0xae, 0x80, 0x6c, 0x21, 0x05, 0x1c, 0xe4, 0xa8, 0x47, 0xe9, 0x24, 0x46, 0xd2, 0xa1, 0xad, - 0xd1, 0x68, 0xcb, 0x2f, 0xc7, 0xd1, 0x1d, 0xaa, 0x47, 0x57, 0xdd, 0xa9, 0x8c, 0x66, 0x5c, 0x36, 0x41, 0xe6, 0x46, - 0x50, 0xcf, 0x64, 0x7b, 0xd5, 0x41, 0x7a, 0x3c, 0x08, 0x15, 0xf6, 0x97, 0x4e, 0x04, 0x34, 0x48, 0x01, 0x07, 0xae, - 0xba, 0x56, 0x54, 0x78, 0xe8, 0x8f, 0xf7, 0x75, 0x5f, 0x39, 0x44, 0x46, 0x3a, 0x1a, 0xb3, 0xd1, 0xe8, 0x91, 0x3c, - 0x6f, 0xd7, 0x42, 0x58, 0x1d, 0xbb, 0xd9, 0xb8, 0x61, 0x1a, 0x0e, 0xbe, 0xe0, 0x0d, 0xae, 0xd7, 0xd5, 0x87, 0xc7, - 0xb1, 0x12, 0xf3, 0x7f, 0xc1, 0x2b, 0x9c, 0x6e, 0xc6, 0x5b, 0xcd, 0x9e, 0x69, 0xef, 0xfb, 0xbd, 0x03, 0xab, 0x61, - 0xae, 0x79, 0x71, 0xe8, 0xfb, 0xa4, 0x7a, 0xdd, 0x36, 0xfa, 0x69, 0xf8, 0x9b, 0xb5, 0x7d, 0x80, 0xee, 0x27, 0xda, - 0xfb, 0x00, 0x8d, 0xed, 0xe7, 0x10, 0xb9, 0x6e, 0xee, 0x3f, 0xc4, 0x74, 0xba, 0xc9, 0x05, 0x36, 0x65, 0xf2, 0x53, - 0x2b, 0x50, 0x1d, 0x28, 0x7c, 0xb5, 0x45, 0x86, 0xc1, 0x39, 0xbc, 0xe2, 0x15, 0x08, 0x43, 0xe4, 0x78, 0x15, 0x1e, - 0xc1, 0xeb, 0x1f, 0x5d, 0x70, 0x26, 0x34, 0x93, 0x48, 0x44, 0x72, 0x63, 0xc9, 0x43, 0x9c, 0x22, 0x94, 0xb9, 0xa2, - 0x7c, 0xda, 0x86, 0xc1, 0x0e, 0x59, 0xae, 0x2c, 0x0a, 0xfc, 0xf2, 0xc2, 0xde, 0xb6, 0x97, 0xcb, 0x15, 0x0e, 0xac, - 0xd6, 0xfb, 0x36, 0x14, 0x90, 0xc8, 0xea, 0x96, 0x2e, 0x9d, 0x41, 0xfb, 0xeb, 0xe8, 0x1a, 0x87, 0x11, 0x7e, 0x9d, - 0xa3, 0x0c, 0x6c, 0xfc, 0x0a, 0x22, 0xa0, 0x90, 0x7d, 0x0c, 0x8a, 0xec, 0xd1, 0x23, 0x3a, 0x2d, 0x12, 0x06, 0xb5, - 0x42, 0x7b, 0x40, 0xdc, 0xc2, 0x40, 0x3f, 0x6a, 0xc5, 0xe7, 0xbb, 0x95, 0xe4, 0x63, 0x54, 0xfe, 0x26, 0x7e, 0x05, - 0xd0, 0x91, 0x17, 0xd4, 0x8d, 0xec, 0x15, 0x49, 0x0d, 0x0b, 0x6e, 0x22, 0xcb, 0x29, 0x40, 0x02, 0xb9, 0x0d, 0x73, - 0xff, 0x0f, 0xbe, 0xa4, 0x3d, 0x24, 0x8c, 0x11, 0xba, 0x52, 0x06, 0xdc, 0xe8, 0x22, 0x90, 0x4a, 0x84, 0x46, 0xd6, - 0xe8, 0xbb, 0x2e, 0x0a, 0x38, 0x81, 0x13, 0xb4, 0x2c, 0x92, 0x78, 0xb7, 0x47, 0xff, 0x5f, 0x2f, 0x41, 0x0d, 0xf8, - 0x78, 0x7d, 0xc3, 0x1e, 0xaa, 0xa1, 0xa7, 0x02, 0x15, 0x19, 0x37, 0x20, 0x66, 0x87, 0x2f, 0x45, 0xf6, 0x38, 0x30, - 0xf9, 0xbf, 0x88, 0xb0, 0x52, 0x38, 0x72, 0x7a, 0xfa, 0xfa, 0x0d, 0x8b, 0x8b, 0xdd, 0x5f, 0x25, 0x75, 0x18, 0xbf, - 0x25, 0x96, 0xd9, 0x4f, 0xf4, 0xac, 0x0b, 0xf4, 0xe4, 0xc7, 0x79, 0x56, 0x0f, 0x3c, 0x76, 0x97, 0x1f, 0xf0, 0xea, - 0xfb, 0x66, 0xea, 0xc9, 0xf3, 0xfd, 0x97, 0xbe, 0x84, 0x1e, 0x19, 0x6f, 0x3c, 0xf5, 0x56, 0x3f, 0x93, 0x03, 0x12, - 0x5e, 0x53, 0x31, 0xf4, 0xd6, 0xcd, 0x05, 0x59, 0xc3, 0x25, 0x58, 0x7e, 0x5e, 0x26, 0x35, 0x39, 0xcf, 0xf6, 0xbc, - 0xaf, 0x7e, 0xc0, 0xdb, 0xef, 0x7b, 0xce, 0x44, 0x9b, 0xcf, 0xa7, 0xd9, 0x06, 0x9c, 0x2d, 0xa0, 0xbf, 0xd8, 0xa3, - 0xad, 0x19, 0x09, 0x6f, 0x42, 0xeb, 0x4c, 0xb5, 0x10, 0xf6, 0xeb, 0x9e, 0x5d, 0xa3, 0x1e, 0xe8, 0xaf, 0x06, 0xd6, - 0x81, 0xeb, 0x42, 0x3e, 0x99, 0xa3, 0x01, 0x77, 0x4c, 0x46, 0xdb, 0x34, 0xb2, 0x20, 0xd2, 0xe3, 0x25, 0x2f, 0x32, - 0xda, 0x8b, 0x01, 0x6e, 0x3c, 0xbe, 0xa4, 0x02, 0x83, 0x6f, 0x99, 0xe8, 0x94, 0xe3, 0x39, 0x04, 0xe2, 0xfe, 0xcd, - 0xd0, 0xa9, 0xfc, 0x00, 0x69, 0x2b, 0x6a, 0x19, 0x29, 0x31, 0x13, 0x28, 0xf2, 0x1f, 0x7f, 0xb5, 0x6e, 0x35, 0x60, - 0x3f, 0xcb, 0xdb, 0xf0, 0x58, 0xd1, 0xc4, 0x5a, 0xc6, 0x5f, 0x55, 0x63, 0x2a, 0x51, 0xa1, 0x80, 0x96, 0xf3, 0xfe, - 0x9c, 0xa3, 0x3b, 0x3f, 0x08, 0x6b, 0x47, 0x06, 0xa6, 0x96, 0xed, 0x6f, 0x95, 0x81, 0x9b, 0x33, 0xbf, 0x7c, 0x10, - 0x01, 0x84, 0xed, 0xa0, 0xe4, 0xef, 0x07, 0x7f, 0x9a, 0xc2, 0x0d, 0xbb, 0x0e, 0xaf, 0x1c, 0x98, 0x3b, 0x98, 0x72, - 0x2b, 0x1b, 0x91, 0x1f, 0x61, 0x04, 0xcb, 0x0e, 0xd4, 0x0a, 0xe7, 0x79, 0xfe, 0xe7, 0xa2, 0x76, 0x0c, 0x96, 0x1b, - 0xd9, 0x6e, 0xa0, 0x79, 0x4a, 0xc4, 0x30, 0x13, 0xb3, 0x68, 0x94, 0xde, 0x9e, 0xd3, 0xca, 0x59, 0xc3, 0x6c, 0x17, - 0x9c, 0xcb, 0x65, 0xbd, 0x09, 0xe6, 0xf5, 0x47, 0x35, 0x81, 0xa4, 0xc3, 0x15, 0xbe, 0xd2, 0x0a, 0xe8, 0x9a, 0xa1, - 0x44, 0x21, 0x90, 0x03, 0x34, 0xdf, 0x2b, 0x56, 0xe2, 0x4d, 0x4e, 0x7e, 0xc1, 0x79, 0x1b, 0xf0, 0xdd, 0xbc, 0x87, - 0x4f, 0xad, 0x11, 0xda, 0x28, 0xcc, 0x86, 0x83, 0x8b, 0xa1, 0xaa, 0x05, 0xcc, 0x50, 0x23, 0x96, 0x43, 0xe1, 0x80, - 0x7d, 0xec, 0xfc, 0x35, 0x74, 0x36, 0x96, 0x6a, 0x6f, 0xb0, 0x1e, 0x11, 0xd8, 0xc3, 0xa7, 0x5c, 0x87, 0x72, 0xc1, - 0x8e, 0x81, 0x34, 0x55, 0xa8, 0xa3, 0xa0, 0x39, 0x19, 0x34, 0xa8, 0xec, 0xc7, 0x59, 0xeb, 0xbe, 0x40, 0xd3, 0x28, - 0x88, 0xc9, 0x11, 0x68, 0x5b, 0x50, 0xd8, 0xd4, 0xdf, 0x1f, 0x35, 0xae, 0x9b, 0xaf, 0xb6, 0xc0, 0x3b, 0x04, 0xad, - 0x0b, 0x12, 0x8d, 0x0b, 0x34, 0x86, 0xcb, 0xcb, 0xd5, 0xd3, 0x09, 0xa3, 0xa6, 0x1e, 0x07, 0x45, 0x52, 0xd1, 0xb8, - 0x44, 0x50, 0x37, 0x19, 0xb6, 0x9d, 0xb6, 0x4b, 0xc5, 0x81, 0xc0, 0xeb, 0x8d, 0xfd, 0x72, 0xf0, 0xa8, 0x78, 0x25, - 0xa1, 0xa3, 0xa4, 0xc2, 0xdf, 0x9b, 0xd8, 0xc5, 0x47, 0x7e, 0xe0, 0xe9, 0xe2, 0x95, 0x48, 0xbf, 0x04, 0x0b, 0x5a, - 0x1c, 0x78, 0x39, 0x0a, 0x1a, 0x25, 0x5e, 0xa1, 0xc9, 0xa6, 0x16, 0x3a, 0xeb, 0x6a, 0xa7, 0x88, 0x42, 0xc9, 0xd1, - 0xd9, 0xa7, 0xb1, 0x41, 0x2a, 0xa0, 0xee, 0xa3, 0x72, 0x4a, 0x12, 0x7e, 0x7d, 0x76, 0x8c, 0x13, 0x8a, 0xb4, 0x4f, - 0x07, 0x6d, 0x46, 0x54, 0x34, 0xb0, 0x97, 0x0f, 0x45, 0xf0, 0x33, 0x68, 0xc8, 0xce, 0x84, 0xf8, 0x13, 0xed, 0x57, - 0xec, 0xea, 0x4d, 0x8e, 0xf3, 0x5c, 0x1b, 0x0c, 0x5b, 0x89, 0xb5, 0xc0, 0x88, 0x4e, 0xfc, 0xe9, 0xf8, 0x9f, 0x06, - 0xa1, 0x20, 0x87, 0xc2, 0x68, 0x20, 0x21, 0x89, 0x36, 0x6e, 0x99, 0x4e, 0x56, 0x24, 0x67, 0x95, 0x7c, 0x6e, 0xde, - 0xc3, 0x20, 0x25, 0x14, 0xd9, 0xa8, 0xb4, 0x73, 0xe3, 0x46, 0x34, 0xf8, 0x99, 0x7c, 0xf6, 0xe5, 0xa2, 0x72, 0x2b, - 0x86, 0x36, 0x08, 0xaf, 0x02, 0x01, 0x18, 0x3d, 0x19, 0xa8, 0xef, 0xef, 0x33, 0x38, 0x88, 0x84, 0xfc, 0x2a, 0x82, - 0x57, 0xb4, 0xe6, 0x28, 0x05, 0xc0, 0xe6, 0xb0, 0x11, 0x8c, 0xae, 0xc2, 0xaa, 0x3b, 0xee, 0x46, 0xf4, 0x27, 0xd2, - 0xa9, 0x36, 0x5a, 0x37, 0x43, 0xba, 0x8d, 0x6d, 0x66, 0xb4, 0xc7, 0xc2, 0x6b, 0xfb, 0xba, 0x99, 0x90, 0x04, 0xca, - 0xc3, 0x19, 0xd1, 0x8f, 0x6c, 0x7d, 0xd3, 0xe3, 0x3f, 0x6e, 0x7f, 0xd8, 0x45, 0x51, 0x09, 0x8c, 0x10, 0x85, 0x24, - 0x50, 0xa9, 0x14, 0xc2, 0xa7, 0x23, 0x36, 0x2d, 0xf8, 0xbf, 0xce, 0x3a, 0x1e, 0x37, 0xd0, 0x8c, 0x2f, 0xff, 0xdc, - 0x86, 0x9d, 0xbd, 0x3d, 0x5f, 0x7b, 0xb7, 0xaa, 0x42, 0x93, 0x6b, 0xb1, 0x55, 0xf5, 0x3d, 0xe4, 0xfc, 0x30, 0xa8, - 0x64, 0x21, 0x57, 0x5f, 0x8b, 0xe0, 0xee, 0xaf, 0xa9, 0xf9, 0x08, 0xd3, 0x90, 0xc2, 0xbd, 0x7b, 0x11, 0x1a, 0x61, - 0x54, 0xbb, 0x6a, 0x02, 0x5b, 0x8a, 0x48, 0xe2, 0x62, 0xd5, 0x20, 0x20, 0x7a, 0x09, 0xa0, 0x92, 0x7b, 0xc1, 0x9b, - 0x8b, 0xb2, 0xb7, 0xa9, 0xb4, 0x46, 0xab, 0x8b, 0xf3, 0x30, 0x4f, 0xfc, 0xb5, 0xa7, 0xe1, 0x71, 0xab, 0x09, 0x61, - 0x09, 0xa5, 0x30, 0x78, 0x00, 0xbc, 0xfa, 0xa2, 0x63, 0xd3, 0x1d, 0x10, 0x08, 0xc5, 0x56, 0x2a, 0xdf, 0x6d, 0x52, - 0x85, 0xb9, 0x19, 0x09, 0x6f, 0x6a, 0x44, 0x78, 0xe3, 0xc2, 0xd8, 0x5f, 0x8e, 0x15, 0x82, 0x81, 0x00, 0x50, 0xe3, - 0x8f, 0xaf, 0xa5, 0xb2, 0xd6, 0xb2, 0x1b, 0x57, 0x55, 0xde, 0x43, 0xac, 0x38, 0xf0, 0xe0, 0xb7, 0x8c, 0x41, 0x73, - 0x8d, 0x5c, 0xd0, 0x29, 0xb7, 0xa2, 0xd7, 0xf5, 0x3d, 0xe6, 0xa4, 0x5d, 0x18, 0x5a, 0xc6, 0x08, 0x2a, 0xd4, 0xe6, - 0x27, 0x2a, 0x1d, 0xf9, 0xa0, 0xce, 0xb1, 0xd6, 0x1a, 0xe8, 0x9e, 0x3b, 0xeb, 0x0f, 0x93, 0x31, 0xf9, 0xe7, 0xe9, - 0xad, 0x37, 0xfd, 0x26, 0xe1, 0x85, 0x95, 0x4c, 0xa5, 0xea, 0xd2, 0x88, 0x2a, 0x88, 0xe1, 0x7a, 0x5e, 0x55, 0xfa, - 0x88, 0x58, 0xd5, 0x8f, 0xdd, 0x16, 0x0f, 0xa2, 0x3a, 0xe9, 0x96, 0x78, 0xd5, 0x8d, 0xa1, 0x0a, 0xf7, 0x9f, 0xf8, - 0x48, 0x46, 0x87, 0xb3, 0xa7, 0x1a, 0x29, 0x92, 0xba, 0x07, 0xea, 0xe4, 0x48, 0x86, 0xd1, 0x5a, 0x41, 0x89, 0x0a, - 0x66, 0xc2, 0x25, 0x46, 0x6c, 0x75, 0xff, 0x0f, 0x68, 0x84, 0x9f, 0x77, 0xfc, 0x93, 0xbf, 0x10, 0x9e, 0xb1, 0x61, - 0x49, 0x84, 0x4f, 0x47, 0x27, 0x03, 0x16, 0x77, 0x7e, 0x18, 0xf3, 0xde, 0x9d, 0xfb, 0x09, 0x5d, 0x92, 0xbd, 0x8e, - 0x14, 0xf7, 0x4e, 0x91, 0x42, 0xdc, 0xcb, 0xcb, 0x55, 0xa5, 0x92, 0x56, 0x5c, 0x79, 0xd1, 0x01, 0xc0, 0xbc, 0x0f, - 0xa4, 0x9c, 0xe5, 0x50, 0x24, 0x5e, 0xa9, 0x2a, 0x60, 0x9a, 0xa0, 0x9d, 0x15, 0xf0, 0x2b, 0x56, 0xf9, 0xac, 0x9a, - 0x5e, 0xb9, 0x04, 0x75, 0x7f, 0x6e, 0x52, 0xf2, 0xc5, 0xab, 0xe6, 0x8a, 0x11, 0x95, 0x6d, 0x85, 0xe3, 0xc5, 0xc6, - 0xe9, 0xc2, 0x90, 0xa8, 0x92, 0x2e, 0xfb, 0xbc, 0xee, 0x9b, 0xca, 0xce, 0xac, 0xb0, 0x4b, 0xb5, 0xaa, 0x6c, 0xac, - 0xa8, 0xff, 0x4b, 0x4e, 0x4b, 0x2c, 0x03, 0x11, 0x21, 0xd7, 0x65, 0x19, 0x28, 0xe3, 0xc0, 0x79, 0x2a, 0xdb, 0x11, - 0x1d, 0xd9, 0x67, 0x9d, 0x5f, 0x8b, 0xd9, 0xd4, 0xca, 0xf4, 0x89, 0xab, 0x0e, 0x39, 0xcf, 0x0e, 0x5a, 0x06, 0x93, - 0xc5, 0xe7, 0x68, 0x3c, 0xe0, 0x41, 0x28, 0x14, 0x55, 0x5c, 0xbb, 0x8e, 0x25, 0x2f, 0xfa, 0x0f, 0xe3, 0x41, 0x68, - 0xd4, 0x5f, 0x35, 0x0e, 0x35, 0xe4, 0xfa, 0x36, 0x39, 0x92, 0x93, 0x3c, 0x4b, 0xa2, 0x74, 0x43, 0x88, 0xf3, 0x67, - 0xe3, 0x83, 0x8b, 0x4f, 0x24, 0x0b, 0x91, 0xea, 0xe6, 0x63, 0x3d, 0xdf, 0x0b, 0x53, 0x45, 0xf7, 0x14, 0x0d, 0x45, - 0x5f, 0xd9, 0xaf, 0xef, 0xcc, 0xc9, 0xe2, 0x31, 0x99, 0xd4, 0x4d, 0xd1, 0xd1, 0x08, 0x3e, 0xeb, 0x20, 0xb4, 0xe0, - 0x68, 0xe6, 0xcd, 0xbd, 0xc7, 0x7c, 0x97, 0x5e, 0x8b, 0x0e, 0x0d, 0x3f, 0xa2, 0xdd, 0x50, 0xdf, 0x4e, 0xef, 0xb3, - 0x57, 0xb4, 0x05, 0x49, 0xcd, 0x8c, 0x2e, 0xc1, 0x02, 0xef, 0x67, 0xae, 0xf1, 0xfe, 0xb0, 0xa9, 0x51, 0xe5, 0xaf, - 0xbe, 0x34, 0x1d, 0x5a, 0x54, 0x15, 0x59, 0xaa, 0xcd, 0xca, 0xa1, 0x99, 0xe1, 0x2d, 0x5d, 0x71, 0x19}; + 0x1b, 0xc8, 0x90, 0x11, 0x55, 0xb5, 0x2b, 0x2a, 0x8a, 0xaa, 0x55, 0x0f, 0xd0, 0x7a, 0xc0, 0x36, 0x66, 0x21, 0xff, + 0x0b, 0x0b, 0xa3, 0x01, 0x85, 0xcd, 0xc9, 0x64, 0x39, 0xe4, 0x0c, 0x83, 0xa7, 0x5a, 0x3d, 0x8d, 0x21, 0xe6, 0xfa, + 0x1a, 0xa7, 0xef, 0x35, 0x45, 0xd8, 0xd0, 0xc6, 0x30, 0x0a, 0x7e, 0xe2, 0x70, 0x81, 0x7e, 0xd3, 0x30, 0x8a, 0xf7, + 0x08, 0x8d, 0x7d, 0x92, 0xbb, 0x98, 0x33, 0xdf, 0xfb, 0xfc, 0x16, 0x8f, 0x9c, 0x41, 0x68, 0x88, 0x3d, 0x00, 0xca, + 0xb9, 0x8e, 0x1a, 0xab, 0x60, 0xf5, 0x24, 0xe5, 0x28, 0x3b, 0xbf, 0xca, 0x5f, 0xd9, 0x7d, 0x2e, 0xa7, 0xea, 0x32, + 0x41, 0xe7, 0x1b, 0x9e, 0x44, 0xdb, 0xde, 0x6f, 0x16, 0xa9, 0xda, 0xef, 0xbf, 0xbd, 0x27, 0x46, 0x81, 0x70, 0x53, + 0x66, 0x14, 0x4b, 0xb4, 0x26, 0x10, 0xf3, 0x21, 0x4a, 0xe9, 0xc3, 0xed, 0xb0, 0xff, 0xab, 0x2d, 0xff, 0xfb, 0x34, + 0xd5, 0x70, 0xe3, 0xc3, 0xc8, 0x07, 0x19, 0x24, 0xc3, 0x64, 0x31, 0x73, 0x3d, 0x59, 0x96, 0x9d, 0xcc, 0xc3, 0xc2, + 0x08, 0xa3, 0xc4, 0xc8, 0x7e, 0xd2, 0x65, 0x49, 0x64, 0xf7, 0xcd, 0xab, 0xca, 0x5f, 0x54, 0xdf, 0x32, 0x4d, 0xad, + 0xda, 0xc8, 0xf9, 0x38, 0xb8, 0xd1, 0xa2, 0x3f, 0x6a, 0x2c, 0xa4, 0xa8, 0x53, 0x5e, 0x0e, 0x10, 0x01, 0xd2, 0x16, + 0xf3, 0x90, 0x7e, 0x26, 0xbf, 0xd6, 0x2f, 0xfd, 0xb1, 0xaa, 0x36, 0xe0, 0x19, 0x76, 0xdf, 0xac, 0xc4, 0x3e, 0xea, + 0xb5, 0xdc, 0x95, 0xb8, 0x04, 0x4e, 0xbe, 0x4e, 0xce, 0xe4, 0x7c, 0x20, 0x3a, 0x9d, 0x2e, 0xad, 0x20, 0x81, 0xd4, + 0x2a, 0xc0, 0x47, 0xd8, 0x60, 0x9b, 0x3b, 0x34, 0xb2, 0xff, 0xdf, 0x54, 0x3f, 0xdb, 0x01, 0x18, 0x36, 0xa5, 0xa2, + 0xb2, 0x73, 0x1b, 0x92, 0x3a, 0x88, 0x4b, 0x39, 0xe5, 0xa6, 0x70, 0x51, 0x72, 0xee, 0xbd, 0xef, 0xdd, 0xd5, 0x24, + 0x7c, 0x61, 0x06, 0xc4, 0x7e, 0x24, 0x7d, 0x01, 0x04, 0x69, 0xe6, 0x23, 0x26, 0x85, 0xf4, 0xde, 0x9b, 0x01, 0x38, + 0x03, 0x50, 0x5a, 0x80, 0x94, 0x56, 0x71, 0xcf, 0xa1, 0x48, 0xf9, 0x6f, 0x48, 0x49, 0x5e, 0x87, 0x94, 0xaa, 0x26, + 0xe4, 0xce, 0xa7, 0x8f, 0x55, 0xb9, 0xa9, 0x68, 0xdc, 0xb9, 0x74, 0x6b, 0xa7, 0x43, 0x13, 0xe7, 0xec, 0xce, 0x93, + 0x52, 0xd8, 0x63, 0xa8, 0xb5, 0x3a, 0x6f, 0xfe, 0xb7, 0xba, 0x71, 0x46, 0x11, 0x68, 0x7a, 0xdb, 0x50, 0xad, 0xbf, + 0x56, 0x7a, 0xd7, 0x60, 0x86, 0x10, 0x42, 0x13, 0x1c, 0x37, 0x5f, 0xd3, 0x1d, 0x77, 0x77, 0x16, 0xd9, 0xc4, 0x38, + 0xe3, 0x00, 0xf5, 0x14, 0xa4, 0xa1, 0x63, 0x36, 0xdd, 0xac, 0xc6, 0xb9, 0x8d, 0x3c, 0xdf, 0x08, 0x26, 0x6e, 0x0f, + 0x41, 0xb7, 0x86, 0x03, 0x27, 0xd0, 0xc8, 0xf3, 0x4c, 0xfe, 0xe8, 0x03, 0x9b, 0xe3, 0xd7, 0x37, 0x64, 0xd0, 0xcb, + 0x61, 0xad, 0x05, 0xdc, 0x42, 0xb4, 0xbd, 0x0a, 0xca, 0x46, 0x80, 0x9a, 0x55, 0x5f, 0x0f, 0xd9, 0xfb, 0xc6, 0xfb, + 0x6f, 0x77, 0x9f, 0x0d, 0xb1, 0xd2, 0xbf, 0xa7, 0x58, 0xfe, 0x6b, 0x78, 0x6d, 0xd6, 0x25, 0x6b, 0x1d, 0xac, 0x87, + 0x90, 0xf3, 0x30, 0xf1, 0x10, 0x05, 0x6f, 0x61, 0x8e, 0xe3, 0xc6, 0xe3, 0x99, 0x21, 0x63, 0xcb, 0x45, 0xad, 0x07, + 0x66, 0xce, 0xfe, 0xfd, 0xf8, 0x6c, 0x4b, 0x35, 0x38, 0xc7, 0xc5, 0x46, 0xb4, 0xe9, 0x72, 0x49, 0x39, 0xb5, 0xd9, + 0xe5, 0xc8, 0x52, 0xba, 0xfd, 0x77, 0xd7, 0xa6, 0x8a, 0xfb, 0xec, 0xad, 0x6b, 0x39, 0xfc, 0xbc, 0x93, 0x13, 0x25, + 0x10, 0x51, 0xf1, 0x81, 0x22, 0xe5, 0x4a, 0x1d, 0x95, 0xaf, 0x33, 0x95, 0xa5, 0x5f, 0x7e, 0x85, 0x03, 0x41, 0x3c, + 0x20, 0x7a, 0xe3, 0x76, 0xbd, 0x4e, 0x47, 0x66, 0xcc, 0x2b, 0x62, 0x7e, 0xfb, 0xf9, 0xf9, 0x72, 0x61, 0xc0, 0xd7, + 0x10, 0x77, 0x9a, 0xd6, 0x03, 0xd6, 0xed, 0x1b, 0xf7, 0x5f, 0xcb, 0xd9, 0xe5, 0x7e, 0xcb, 0xb6, 0xb6, 0xfc, 0xb9, + 0xe1, 0x31, 0xbd, 0x50, 0x9d, 0xf2, 0x75, 0x1e, 0x16, 0xdc, 0xb4, 0x5b, 0x83, 0xe4, 0xa1, 0x3d, 0x00, 0x9f, 0xab, + 0x66, 0xc4, 0xb7, 0x1b, 0x55, 0x3a, 0xcf, 0x0b, 0x05, 0x89, 0xdb, 0x39, 0x49, 0xeb, 0xf4, 0x0e, 0x55, 0x66, 0x22, + 0x1a, 0xe1, 0x1f, 0x81, 0xac, 0xdc, 0x38, 0xe2, 0x83, 0xa0, 0xd7, 0x43, 0x82, 0x75, 0x84, 0x6a, 0x6a, 0x1e, 0xa5, + 0x0f, 0xef, 0x8d, 0xf5, 0x73, 0xdd, 0x40, 0xfe, 0x9b, 0x19, 0xa2, 0x4c, 0xf8, 0x61, 0xc8, 0x54, 0xb5, 0xdb, 0x76, + 0x21, 0x01, 0x80, 0x2a, 0xd3, 0x11, 0xb3, 0x9e, 0x79, 0x02, 0x9e, 0x0e, 0xe7, 0x32, 0xda, 0x14, 0x78, 0xab, 0x8f, + 0x77, 0xaf, 0x2f, 0x12, 0x87, 0xcb, 0x41, 0xfc, 0x30, 0xac, 0xdd, 0x8a, 0xab, 0xeb, 0x54, 0xc0, 0x17, 0x3b, 0x05, + 0x59, 0x27, 0x05, 0xd2, 0xb2, 0x6b, 0x96, 0x23, 0xf7, 0x20, 0x6f, 0xd8, 0x20, 0xb3, 0xca, 0x7d, 0x2d, 0xdf, 0x7a, + 0xf3, 0x77, 0x2e, 0x0a, 0xa1, 0xc4, 0x5f, 0x1d, 0xb3, 0xad, 0xb1, 0x40, 0x64, 0x48, 0x7f, 0x0f, 0x14, 0x83, 0x13, + 0xb1, 0xc8, 0x2c, 0xcb, 0x14, 0x96, 0x57, 0xc8, 0xa4, 0x6d, 0x5c, 0xaf, 0xc9, 0xb1, 0x15, 0xbd, 0x6a, 0xf0, 0xf0, + 0xf8, 0x25, 0x99, 0x45, 0x0a, 0x19, 0x96, 0x8f, 0x85, 0x91, 0xf2, 0x24, 0xef, 0x43, 0x97, 0xd3, 0x18, 0x3e, 0xc2, + 0xe9, 0xd3, 0x05, 0xa1, 0x2c, 0xc2, 0x94, 0x23, 0x92, 0xbd, 0x8d, 0x8d, 0x66, 0xc7, 0xac, 0x21, 0x84, 0xc9, 0x9f, + 0xf5, 0xaf, 0x73, 0xfc, 0x2b, 0xa6, 0x34, 0x05, 0xb2, 0x04, 0x1f, 0x7e, 0xa9, 0x08, 0x87, 0x08, 0x36, 0xb6, 0x71, + 0x91, 0x3d, 0x43, 0xca, 0x35, 0x90, 0x00, 0x42, 0x15, 0x18, 0xe3, 0xd9, 0x72, 0xee, 0xf8, 0x8c, 0x97, 0xb7, 0x83, + 0xce, 0x36, 0x0a, 0xcb, 0x17, 0x32, 0x8a, 0xd9, 0xd4, 0x0a, 0x28, 0x2f, 0x73, 0xaa, 0xfb, 0x34, 0x9b, 0xb4, 0xbb, + 0x20, 0xeb, 0x0a, 0x21, 0xdf, 0x1b, 0xa1, 0x1a, 0xa3, 0xdd, 0xe1, 0x17, 0x82, 0x5d, 0x99, 0x69, 0x12, 0x35, 0x55, + 0xf8, 0xfd, 0x2f, 0x07, 0x50, 0xf4, 0x2a, 0x1e, 0x57, 0xfa, 0x07, 0xd9, 0x97, 0x32, 0x97, 0x1c, 0xd6, 0xc7, 0xe0, + 0xa5, 0x3a, 0xaf, 0xa6, 0x36, 0x02, 0x05, 0xc4, 0xa8, 0xad, 0x44, 0xf5, 0x37, 0x6b, 0x1a, 0xb0, 0xa3, 0x8c, 0xf5, + 0xd7, 0xe5, 0x08, 0x87, 0x33, 0xd8, 0xe2, 0xd9, 0x52, 0xfe, 0x5a, 0x6f, 0x24, 0x8c, 0x51, 0x9b, 0xa9, 0xf2, 0x82, + 0xf1, 0xed, 0x41, 0x10, 0xd3, 0x68, 0x77, 0x72, 0x06, 0xdf, 0xc8, 0x1d, 0xf5, 0x07, 0xf1, 0x2a, 0xd7, 0x50, 0x0a, + 0x1a, 0x5f, 0x25, 0x90, 0x5b, 0x1b, 0x24, 0x90, 0x06, 0x4b, 0x11, 0x1a, 0xc7, 0x36, 0xc2, 0x3f, 0x2c, 0x55, 0xc1, + 0xbf, 0x1a, 0xcd, 0xf2, 0xed, 0x47, 0xf1, 0xf9, 0xd2, 0x6f, 0x41, 0x8c, 0xcf, 0x2b, 0xf9, 0xc7, 0x56, 0x3a, 0x97, + 0x96, 0x25, 0x83, 0xda, 0x95, 0x25, 0x35, 0x91, 0x8d, 0xe9, 0xe8, 0x7d, 0xa9, 0xa2, 0x05, 0xc4, 0x5a, 0xff, 0xa2, + 0xfa, 0xde, 0xd0, 0x89, 0x26, 0xed, 0x02, 0x1e, 0x29, 0xe8, 0x0e, 0x1e, 0x4c, 0x4f, 0xaf, 0xd6, 0xe6, 0x2d, 0x51, + 0xd4, 0xfe, 0xde, 0x86, 0x3f, 0x4d, 0x53, 0x17, 0x15, 0xf1, 0x25, 0x7b, 0x7e, 0x60, 0x6d, 0xba, 0xdd, 0xd4, 0xa0, + 0xb8, 0xc9, 0x08, 0xb5, 0x1a, 0xae, 0xde, 0x47, 0xac, 0x56, 0x30, 0x5c, 0x12, 0x9e, 0xaa, 0xd9, 0x56, 0x12, 0xbb, + 0x54, 0x50, 0xd6, 0xc7, 0xcd, 0x5d, 0x62, 0xe1, 0xab, 0xc6, 0x64, 0x13, 0x62, 0xf2, 0x9e, 0x20, 0x77, 0x3b, 0x76, + 0x0c, 0x86, 0x05, 0x0f, 0x3c, 0x20, 0x1e, 0xa8, 0xa5, 0x04, 0x03, 0xe3, 0x72, 0xf2, 0x3f, 0xbc, 0xe1, 0xe9, 0xa1, + 0x37, 0x41, 0x22, 0x20, 0xde, 0xa4, 0x2f, 0xf7, 0x0a, 0x82, 0x15, 0x95, 0x15, 0x80, 0x13, 0x35, 0x90, 0xb0, 0x42, + 0x85, 0x81, 0x43, 0xbd, 0x0e, 0xe9, 0xfc, 0x4d, 0xf3, 0xce, 0x0d, 0x18, 0x64, 0x56, 0x2d, 0xa4, 0x5b, 0xd7, 0xe9, + 0x1d, 0xe0, 0x89, 0x82, 0xeb, 0x53, 0x2b, 0x4b, 0x04, 0xe7, 0xa6, 0x97, 0x71, 0x98, 0x22, 0xf7, 0x69, 0x76, 0x9c, + 0x1e, 0x51, 0xd9, 0xdd, 0xae, 0x89, 0x64, 0x98, 0xfc, 0x09, 0xfa, 0xae, 0xd4, 0xdf, 0xe4, 0x54, 0x1b, 0x28, 0x0d, + 0xab, 0xe3, 0xdf, 0xb2, 0x8e, 0x22, 0xc1, 0x1f, 0xc4, 0xdc, 0x40, 0xd8, 0x8b, 0xc1, 0xd4, 0xa5, 0x44, 0x98, 0xd6, + 0x77, 0x05, 0xf6, 0x65, 0x29, 0xc3, 0xc7, 0x86, 0x43, 0xd6, 0xd7, 0x55, 0x9b, 0x1a, 0xe1, 0xeb, 0x09, 0xf9, 0xbc, + 0x77, 0xb2, 0xbe, 0x6e, 0x03, 0x79, 0xac, 0x1c, 0xa6, 0x6f, 0xde, 0x3a, 0x99, 0x2a, 0x70, 0xeb, 0xce, 0x73, 0xd2, + 0xdc, 0x9e, 0xa5, 0xee, 0x3b, 0xb8, 0xc7, 0xcd, 0xa7, 0x95, 0xd3, 0x75, 0x27, 0xaa, 0xd8, 0x78, 0x20, 0x2f, 0x24, + 0xf0, 0x5b, 0x59, 0x4a, 0x6b, 0x41, 0x8d, 0xf8, 0x18, 0xb4, 0xa1, 0xf5, 0x90, 0xe7, 0xd7, 0x33, 0xd4, 0x0c, 0x73, + 0x5a, 0x9c, 0x43, 0x3f, 0x2a, 0x6a, 0x33, 0x20, 0x62, 0xa4, 0x36, 0xa3, 0x3c, 0xaf, 0x82, 0xfb, 0xa5, 0xf5, 0x8f, + 0x98, 0x1b, 0xbe, 0xbe, 0xaf, 0x1f, 0x1a, 0xf3, 0x16, 0xaa, 0x8b, 0xb2, 0x4e, 0x99, 0xf9, 0xc9, 0x21, 0x0b, 0x44, + 0x86, 0x3c, 0x2b, 0xea, 0xe3, 0x7b, 0x6d, 0x05, 0x09, 0xe0, 0x1a, 0x01, 0x3b, 0xee, 0x1e, 0xc4, 0xc6, 0x16, 0x21, + 0x82, 0x0a, 0xed, 0x4e, 0x01, 0x1c, 0x54, 0x90, 0x89, 0x1f, 0xc9, 0xb5, 0xd1, 0x20, 0xaf, 0x5f, 0xa2, 0x1f, 0x2e, + 0x5c, 0x0f, 0xc9, 0xfa, 0x70, 0xc8, 0x20, 0x28, 0xe3, 0x6d, 0xe2, 0x40, 0x82, 0x08, 0x4b, 0x00, 0x3a, 0x36, 0xfe, + 0x4a, 0x25, 0xac, 0x24, 0x3a, 0xe2, 0xae, 0xde, 0x2e, 0x4f, 0x6e, 0x3d, 0x1c, 0xfc, 0x61, 0x95, 0x02, 0xc6, 0xf1, + 0x9e, 0x7f, 0x7e, 0xbf, 0x42, 0x91, 0x82, 0x98, 0x15, 0xc2, 0x21, 0xa7, 0x74, 0x99, 0x88, 0x41, 0xd6, 0x3e, 0xae, + 0x51, 0x73, 0x58, 0xc2, 0x86, 0x88, 0x8a, 0x66, 0xbb, 0x50, 0x2d, 0xea, 0x23, 0xc4, 0xe0, 0x67, 0x33, 0x76, 0xe8, + 0x22, 0x51, 0x49, 0x2b, 0x55, 0x1a, 0xd6, 0xc1, 0x7a, 0x8f, 0x5c, 0x29, 0xf0, 0x41, 0x8d, 0xaf, 0xbe, 0x09, 0x44, + 0xb1, 0x7b, 0x44, 0x6d, 0x17, 0x92, 0xc1, 0xcb, 0x7b, 0xe8, 0x4e, 0xf4, 0xcb, 0x1e, 0x85, 0xac, 0x63, 0x0d, 0xed, + 0x29, 0x4f, 0x64, 0x1e, 0x7b, 0x42, 0x03, 0x25, 0x5a, 0xfe, 0xe8, 0x4c, 0xc9, 0x44, 0x38, 0xcf, 0x3c, 0x1f, 0xae, + 0x2e, 0xf3, 0xd1, 0x87, 0xc7, 0x3c, 0xa4, 0x94, 0x58, 0xf8, 0x84, 0x25, 0x07, 0x74, 0xdd, 0x05, 0x49, 0x01, 0xbc, + 0x6b, 0x8a, 0xa5, 0xfb, 0x51, 0x11, 0x0f, 0x27, 0xeb, 0x69, 0xe6, 0x71, 0xb1, 0x57, 0xaa, 0x38, 0x7a, 0x90, 0x5d, + 0xb8, 0x40, 0xdd, 0xdb, 0x40, 0xd0, 0xb1, 0xc0, 0x2c, 0x81, 0x44, 0x88, 0xf4, 0xde, 0x56, 0xe7, 0x42, 0xc8, 0xeb, + 0x24, 0x33, 0x12, 0x81, 0x5a, 0xe5, 0x6c, 0x02, 0x75, 0xe3, 0x91, 0x22, 0x74, 0x92, 0x92, 0x3c, 0xe1, 0x00, 0xd1, + 0xe3, 0x0a, 0xeb, 0x28, 0x38, 0xc4, 0x75, 0x25, 0x65, 0x4e, 0xfe, 0xcb, 0x94, 0x26, 0x26, 0xbb, 0x72, 0x38, 0x24, + 0x02, 0xa4, 0x74, 0x4b, 0xad, 0x06, 0x9f, 0x45, 0xc4, 0x47, 0x02, 0x30, 0x13, 0x91, 0x28, 0xfc, 0x4b, 0xf7, 0xd2, + 0x33, 0x2f, 0x21, 0xa2, 0x31, 0xd3, 0xa4, 0xb3, 0xe4, 0xed, 0x35, 0xe9, 0xf0, 0x71, 0xa3, 0x93, 0xa8, 0x66, 0xed, + 0x2f, 0xa5, 0x8f, 0x89, 0x2b, 0xf7, 0x8f, 0x02, 0x13, 0x31, 0x9a, 0x9c, 0x53, 0xe9, 0x67, 0x69, 0x71, 0x3e, 0x16, + 0x28, 0x35, 0xaa, 0x2d, 0xbe, 0xbe, 0xad, 0xcf, 0x36, 0x44, 0x9d, 0xb3, 0x4b, 0x1c, 0xf0, 0x74, 0xd5, 0x74, 0xca, + 0x6d, 0x81, 0x0f, 0x2d, 0x93, 0x03, 0x52, 0x74, 0xa7, 0x5d, 0xa2, 0xdb, 0xde, 0x87, 0xe4, 0x30, 0x98, 0xad, 0x80, + 0x03, 0x28, 0xa3, 0x6a, 0x31, 0xb2, 0x1c, 0xc8, 0x62, 0xa9, 0xe4, 0x72, 0x01, 0x40, 0x8b, 0xac, 0x2b, 0xa7, 0x0c, + 0x85, 0xca, 0x69, 0x64, 0x09, 0x07, 0xd5, 0xc6, 0x48, 0xe6, 0x5a, 0x7d, 0x65, 0x08, 0x69, 0xd4, 0x5c, 0x03, 0x73, + 0xa0, 0x50, 0xb3, 0x64, 0xdd, 0x45, 0xa9, 0x56, 0xe1, 0xb9, 0x30, 0x40, 0x9e, 0x3f, 0xae, 0x36, 0xeb, 0x2e, 0x3b, + 0x2f, 0x4e, 0xc5, 0x0b, 0x0a, 0x1b, 0x1e, 0x24, 0xbb, 0x12, 0x27, 0x25, 0x08, 0x9c, 0xa2, 0xa6, 0xb1, 0x57, 0xdc, + 0x7f, 0x25, 0x7f, 0x3f, 0xa4, 0x92, 0x74, 0x2a, 0xa3, 0x18, 0xf1, 0xf4, 0xab, 0x2a, 0xeb, 0x1a, 0x6d, 0x80, 0x94, + 0xbf, 0x77, 0xe9, 0xc8, 0x7a, 0xd3, 0x55, 0x46, 0xaf, 0x4c, 0x9d, 0x55, 0xf8, 0x71, 0x3e, 0x19, 0xd3, 0xe9, 0x8b, + 0xb8, 0xaa, 0x13, 0x47, 0x01, 0x45, 0x20, 0xec, 0xf1, 0xe3, 0x2b, 0xe5, 0xd1, 0x5e, 0x09, 0x58, 0xb2, 0x8d, 0xc1, + 0x9a, 0x54, 0x47, 0x4c, 0x48, 0x5a, 0xde, 0x7d, 0x04, 0xc6, 0x4a, 0x15, 0x45, 0x17, 0xe0, 0xc3, 0x07, 0x94, 0x1e, + 0x14, 0x1a, 0xc7, 0x3c, 0xe5, 0x36, 0x64, 0x98, 0x80, 0x81, 0x1e, 0x07, 0x79, 0x76, 0xfc, 0xc9, 0x55, 0x15, 0xea, + 0x40, 0x3f, 0x2c, 0xd9, 0xd9, 0xb2, 0xb0, 0xbc, 0xca, 0x8e, 0xfd, 0xa7, 0x28, 0xba, 0xae, 0x7b, 0x62, 0x09, 0x47, + 0x7a, 0xdf, 0x8a, 0xdc, 0xc4, 0x82, 0xf3, 0xd5, 0x4a, 0x88, 0xe5, 0x09, 0xc3, 0x00, 0x69, 0x39, 0x66, 0xca, 0x40, + 0x0e, 0x1d, 0x81, 0x91, 0x0c, 0x99, 0x56, 0x77, 0xf8, 0xf4, 0x2d, 0x7e, 0xc0, 0x21, 0x93, 0x94, 0x9c, 0x69, 0x72, + 0xdc, 0x8b, 0x62, 0xb0, 0x2b, 0x43, 0x54, 0x40, 0xe3, 0x6a, 0x3a, 0x85, 0x21, 0x59, 0xea, 0x7d, 0xa5, 0x5b, 0x6a, + 0x3d, 0x82, 0xbb, 0xf3, 0x44, 0x0a, 0x76, 0x40, 0xd5, 0xcb, 0xe8, 0x8c, 0x63, 0x01, 0x84, 0xf4, 0x24, 0xc9, 0x5d, + 0x52, 0x0c, 0xb2, 0x89, 0x14, 0x0a, 0xac, 0x2f, 0x3b, 0x8c, 0x69, 0x31, 0x7d, 0x3f, 0x08, 0x9c, 0x2c, 0x75, 0x49, + 0x04, 0xe9, 0xf3, 0x60, 0x77, 0x49, 0xf1, 0x08, 0x95, 0x8f, 0xbd, 0xfb, 0x59, 0x0a, 0x4a, 0x53, 0x9d, 0xe4, 0x09, + 0x82, 0xf6, 0x1c, 0x18, 0x1d, 0x13, 0x30, 0x1f, 0x48, 0x45, 0x7d, 0x38, 0xad, 0x1e, 0x0b, 0xbb, 0x0f, 0x29, 0xee, + 0xcb, 0xec, 0xe5, 0x2f, 0xe6, 0x73, 0xa4, 0x39, 0x33, 0x74, 0x52, 0xa7, 0x90, 0xcc, 0x66, 0xf9, 0xa5, 0x28, 0x91, + 0xe6, 0xbd, 0xb7, 0x87, 0x23, 0xfd, 0x80, 0xdf, 0x17, 0x82, 0x1b, 0xc0, 0x1c, 0x46, 0xf0, 0x55, 0x17, 0xc5, 0x6e, + 0x96, 0x6d, 0x48, 0xa1, 0xb5, 0xa3, 0x19, 0x2e, 0xd9, 0xee, 0x8d, 0x24, 0x66, 0xad, 0xc8, 0x84, 0x7a, 0xaf, 0x74, + 0x64, 0x6a, 0x3f, 0x2c, 0x61, 0x6b, 0xa5, 0x62, 0x7a, 0x1e, 0xc6, 0xb0, 0x0e, 0x32, 0xc8, 0x08, 0x2a, 0x2b, 0x5c, + 0x30, 0xd4, 0x50, 0x9c, 0x94, 0xf3, 0x06, 0x91, 0xec, 0x1c, 0x4c, 0x27, 0xa6, 0xa1, 0x14, 0x8b, 0x18, 0xd3, 0x43, + 0xb7, 0x79, 0x8f, 0x62, 0x12, 0xf4, 0xfb, 0xb2, 0x3b, 0x9e, 0x3c, 0xc0, 0xcc, 0x04, 0x4e, 0x2d, 0x0d, 0xb2, 0x94, + 0xe1, 0x5c, 0xdb, 0x5f, 0xf1, 0xc3, 0x75, 0x1f, 0x7a, 0x40, 0x74, 0xbf, 0x0f, 0xf2, 0xa1, 0x5e, 0xad, 0x31, 0x18, + 0xe4, 0xb0, 0x50, 0xfa, 0xde, 0x34, 0x84, 0x87, 0x1d, 0x18, 0xcd, 0xc1, 0x32, 0x4c, 0x67, 0x59, 0x4b, 0xae, 0x6c, + 0x55, 0x4d, 0xec, 0x82, 0x6e, 0xd4, 0xba, 0x74, 0xa4, 0x9f, 0x44, 0x2a, 0x76, 0x3d, 0xc7, 0xbd, 0x16, 0xb8, 0xdb, + 0xb6, 0xbc, 0x1c, 0x8b, 0x71, 0x32, 0x23, 0xd2, 0xa8, 0x7e, 0x5a, 0x40, 0x76, 0xac, 0x23, 0x0a, 0x9e, 0x26, 0x23, + 0x1c, 0x06, 0xff, 0x83, 0xcd, 0xad, 0x23, 0xbc, 0x78, 0x2d, 0x74, 0x08, 0xad, 0x6d, 0xb8, 0x6d, 0xe9, 0xee, 0x13, + 0x44, 0xff, 0x5d, 0x27, 0x20, 0x33, 0x81, 0x0a, 0x39, 0x51, 0x1d, 0xe5, 0x54, 0xc5, 0x70, 0xd0, 0xe9, 0xd6, 0x34, + 0x56, 0x69, 0x62, 0xdd, 0xc5, 0x87, 0xe8, 0xd3, 0x0e, 0x48, 0x51, 0x5d, 0x01, 0x93, 0x45, 0xf5, 0x9b, 0x10, 0x80, + 0x8a, 0x2d, 0x33, 0x30, 0x31, 0x2f, 0x67, 0x5a, 0xda, 0xff, 0x2a, 0x2e, 0x59, 0xc5, 0xf2, 0x2f, 0x49, 0xe1, 0xf1, + 0x31, 0x4a, 0x19, 0x58, 0x6b, 0x40, 0xd4, 0xb5, 0x5e, 0xee, 0xd5, 0x45, 0xce, 0xb8, 0xa6, 0xe0, 0xc1, 0xd7, 0xee, + 0x57, 0x75, 0xc3, 0x1f, 0x3f, 0x6a, 0x38, 0xf0, 0x05, 0xa9, 0x46, 0x63, 0x01, 0xe9, 0x7e, 0x17, 0xa3, 0xc2, 0x6c, + 0xbf, 0xac, 0x07, 0x49, 0x22, 0x2a, 0x4f, 0x00, 0x7f, 0x5f, 0xaf, 0x42, 0xb7, 0x06, 0x44, 0xdc, 0x42, 0x1e, 0xcf, + 0x7a, 0x9a, 0xe4, 0x8e, 0x30, 0x45, 0xe2, 0xeb, 0xf7, 0x11, 0xa2, 0x32, 0x99, 0xde, 0xfc, 0x33, 0x6b, 0xc4, 0x29, + 0x4b, 0x60, 0x72, 0x0b, 0x4a, 0xea, 0x1c, 0xf2, 0x28, 0x23, 0x7d, 0xaa, 0x5e, 0xf2, 0x9b, 0x34, 0x07, 0x32, 0x69, + 0x83, 0x4c, 0x11, 0x88, 0x4e, 0x0f, 0xd2, 0x28, 0xfa, 0x20, 0x00, 0xee, 0x20, 0x08, 0xb4, 0x04, 0x81, 0x00, 0x3e, + 0xd2, 0x3b, 0x09, 0x34, 0x21, 0x93, 0xfc, 0x1a, 0x96, 0xa7, 0x2a, 0x95, 0xdb, 0xd4, 0x6e, 0x9c, 0x2d, 0x11, 0x9d, + 0x0a, 0x3a, 0x28, 0x66, 0xa1, 0xdf, 0x1b, 0xbf, 0x25, 0x1d, 0x7a, 0x5f, 0xa2, 0xc2, 0xd8, 0xd3, 0x34, 0xf3, 0x2c, + 0x50, 0xb2, 0x50, 0xf7, 0x7b, 0xb8, 0xff, 0x58, 0x10, 0xde, 0x25, 0x14, 0x64, 0x78, 0xa8, 0x67, 0x8a, 0x14, 0xf7, + 0x70, 0x02, 0x27, 0xe5, 0xc7, 0x8a, 0xcc, 0xde, 0xd7, 0xfc, 0x9e, 0xfe, 0x4c, 0xa0, 0x36, 0xe6, 0x0f, 0x5e, 0x3a, + 0xe6, 0x7c, 0x19, 0x17, 0x18, 0x27, 0x11, 0x07, 0x9a, 0xa2, 0xc0, 0x0e, 0x27, 0x7a, 0xde, 0xf1, 0x62, 0x1d, 0xe2, + 0xae, 0xdc, 0x3c, 0xe8, 0xad, 0xa7, 0x3a, 0x64, 0x5c, 0xcf, 0x44, 0xd6, 0xb6, 0xa8, 0xdf, 0x7f, 0xbf, 0xfa, 0x9e, + 0x1e, 0x5f, 0x8e, 0xe7, 0xa4, 0x4e, 0x51, 0x81, 0x66, 0x5a, 0x78, 0x10, 0xfe, 0x31, 0x99, 0x99, 0xc7, 0xc0, 0x07, + 0x26, 0x63, 0x74, 0xcc, 0xc8, 0x83, 0xf5, 0xb7, 0x82, 0xbc, 0xd8, 0x41, 0x7e, 0xa7, 0x90, 0xfc, 0xe4, 0xc3, 0x0c, + 0x69, 0x44, 0x41, 0x50, 0xa5, 0x3e, 0xa0, 0x50, 0x26, 0x96, 0xfd, 0xf7, 0x96, 0xf6, 0x6d, 0x72, 0x60, 0x12, 0xcb, + 0xe3, 0x6c, 0x31, 0x1e, 0xb3, 0x38, 0xe7, 0x40, 0x7f, 0x2c, 0x59, 0x78, 0x2f, 0x3c, 0x1d, 0xf3, 0xb0, 0x36, 0xf3, + 0xce, 0xc6, 0x04, 0xf0, 0x36, 0xd6, 0x96, 0x7e, 0xc7, 0xcd, 0xfa, 0x71, 0xe8, 0xa0, 0x07, 0xad, 0x3d, 0x74, 0xc0, + 0xca, 0xd3, 0x13, 0x28, 0x8a, 0x6d, 0xc1, 0xd7, 0xdb, 0x3b, 0xac, 0x65, 0x14, 0x3b, 0x64, 0xab, 0xf9, 0xba, 0x2d, + 0xad, 0xc7, 0x28, 0xa9, 0xbf, 0x32, 0xeb, 0x83, 0xb1, 0x7b, 0xf8, 0x01, 0xbb, 0xfa, 0xf5, 0xd5, 0xea, 0x1a, 0x1f, + 0xcf, 0xbb, 0x3a, 0x28, 0x7d, 0xf0, 0x2e, 0x2e, 0x99, 0xcb, 0x4a, 0xcd, 0xe3, 0x2e, 0x45, 0xec, 0x0f, 0x82, 0x67, + 0x11, 0xdd, 0xda, 0x41, 0x1a, 0x7c, 0xbf, 0x14, 0xc1, 0x06, 0xab, 0x7a, 0xa5, 0x15, 0x70, 0xa4, 0xe2, 0xce, 0x3e, + 0x51, 0x88, 0x62, 0xb6, 0x37, 0x10, 0xf1, 0xfc, 0x53, 0xfd, 0xf9, 0x3e, 0xc3, 0x57, 0x05, 0x1f, 0x90, 0x41, 0x86, + 0xcd, 0x86, 0x4b, 0xb6, 0xe2, 0xf2, 0x69, 0x18, 0x90, 0x77, 0x03, 0xbf, 0xf5, 0xdc, 0x5f, 0xc3, 0x7d, 0x64, 0xa9, + 0xe5, 0x5f, 0x20, 0x12, 0x51, 0xf8, 0x8d, 0x62, 0x22, 0xb8, 0x27, 0x08, 0x78, 0x52, 0xc9, 0x10, 0x8b, 0x75, 0xa0, + 0x6b, 0x9c, 0x1e, 0x5e, 0x0f, 0xd3, 0x59, 0x5f, 0x78, 0x9c, 0xbb, 0x36, 0xab, 0xbc, 0xca, 0x75, 0xd7, 0xb6, 0xf6, + 0x6c, 0x89, 0xf8, 0x19, 0x49, 0xac, 0x5a, 0xce, 0xcf, 0x28, 0xb6, 0x0f, 0x98, 0xca, 0xbf, 0x0d, 0xba, 0xb8, 0x23, + 0x4d, 0xae, 0x87, 0xdd, 0xfe, 0xc2, 0x56, 0x55, 0x2c, 0x1e, 0x3f, 0x7a, 0xf3, 0x6e, 0xf3, 0xc5, 0xf5, 0x81, 0x6f, + 0x69, 0x72, 0x69, 0x7f, 0x66, 0x36, 0x49, 0x92, 0xee, 0xe7, 0x64, 0x71, 0xa1, 0x8e, 0x7f, 0x3f, 0xf1, 0x49, 0xc7, + 0xc2, 0x98, 0x97, 0x5d, 0x2d, 0x66, 0x4a, 0x2b, 0xf9, 0x3b, 0xdf, 0xdf, 0x7e, 0xff, 0xec, 0x51, 0x8c, 0x6d, 0xc5, + 0xb9, 0x6d, 0x92, 0x24, 0x79, 0x96, 0x6b, 0xe1, 0x7b, 0x34, 0xd4, 0x47, 0xda, 0xe3, 0xc6, 0xcb, 0x7c, 0x89, 0xc2, + 0x6a, 0xd6, 0x3c, 0x63, 0xb6, 0x7e, 0x5e, 0x7e, 0xf7, 0xd8, 0xd9, 0xe4, 0x7a, 0x13, 0xcb, 0x91, 0xf0, 0x2d, 0xbe, + 0x65, 0x0b, 0x66, 0xba, 0x80, 0xe4, 0x2f, 0xe5, 0xee, 0xf1, 0x5d, 0x71, 0xf9, 0xc3, 0xae, 0x17, 0x66, 0x96, 0x73, + 0x2c, 0x31, 0x96, 0x28, 0x1e, 0xb8, 0x39, 0xdf, 0x81, 0x35, 0x69, 0x72, 0xbe, 0xad, 0x78, 0x8d, 0x73, 0x90, 0xfb, + 0x7b, 0xfa, 0x1f, 0x3f, 0x39, 0xda, 0xdc, 0xc5, 0xc7, 0x11, 0x74, 0x41, 0x62, 0xb7, 0x0b, 0xd6, 0x6e, 0x8a, 0x57, + 0x13, 0xc3, 0x4d, 0x54, 0x95, 0x44, 0x3d, 0x31, 0x1b, 0x01, 0x96, 0x4b, 0x5f, 0x0f, 0x38, 0xd0, 0x4d, 0x27, 0xca, + 0x22, 0xff, 0x6b, 0xec, 0x22, 0x65, 0x40, 0xf8, 0x97, 0x52, 0x48, 0x70, 0xaa, 0xb7, 0x24, 0x25, 0xb8, 0xe6, 0x3b, + 0x56, 0xe5, 0xff, 0x0d, 0x64, 0xc2, 0x6c, 0x26, 0xc2, 0x8a, 0xec, 0x7e, 0xf5, 0xdb, 0x33, 0x82, 0xa9, 0xe7, 0x22, + 0x66, 0x6d, 0xf7, 0xec, 0xd3, 0xb0, 0x67, 0x93, 0x37, 0x22, 0x0b, 0x38, 0x67, 0x08, 0x9c, 0x3c, 0xe3, 0xca, 0xe2, + 0xe4, 0x96, 0xe5, 0x37, 0x77, 0xb9, 0x27, 0x7a, 0x21, 0x91, 0x48, 0x31, 0xab, 0x68, 0xe2, 0x58, 0x01, 0x48, 0x5a, + 0x7d, 0xf8, 0x71, 0xd4, 0xf7, 0x1f, 0x58, 0xaf, 0xd5, 0xdb, 0xb8, 0x4e, 0xc7, 0x88, 0xf8, 0x68, 0x38, 0x6e, 0x21, + 0x78, 0xb9, 0x4a, 0x4d, 0xf4, 0x19, 0xb7, 0xe4, 0x15, 0xa3, 0xde, 0x90, 0xee, 0xac, 0xce, 0x7b, 0x3a, 0xb7, 0xf3, + 0x65, 0x9b, 0x28, 0x54, 0x33, 0x34, 0x83, 0x41, 0x81, 0xf8, 0x38, 0x5f, 0xab, 0x91, 0x44, 0xdf, 0x11, 0xea, 0x84, + 0xbf, 0x5d, 0xb2, 0x48, 0x88, 0x69, 0x36, 0x3b, 0xf9, 0x75, 0xee, 0xa2, 0x9a, 0x48, 0xd2, 0x3b, 0xe7, 0x10, 0x64, + 0xfa, 0x39, 0x83, 0x44, 0x0a, 0x27, 0x18, 0x43, 0x19, 0xc5, 0xb5, 0x59, 0x2e, 0x6a, 0xa1, 0x8a, 0xcf, 0xeb, 0xd9, + 0xb0, 0x53, 0x22, 0xd9, 0x4a, 0x14, 0xeb, 0x7c, 0x6d, 0x4f, 0xae, 0xa9, 0xb7, 0x5c, 0x0f, 0x19, 0xc5, 0x75, 0xf2, + 0xfc, 0xaa, 0x56, 0xb1, 0x51, 0x13, 0xf0, 0xa7, 0x94, 0xe2, 0xc0, 0x86, 0xdb, 0xbc, 0x25, 0x52, 0x7a, 0x56, 0xd6, + 0xdf, 0x3a, 0x49, 0x88, 0xef, 0xce, 0x4d, 0x2b, 0x7b, 0x43, 0x84, 0x87, 0x24, 0x81, 0xdc, 0xa8, 0xb5, 0xa6, 0x72, + 0xd7, 0xed, 0x33, 0x5f, 0x15, 0x56, 0x75, 0xfb, 0xd7, 0x6b, 0x37, 0xe0, 0x10, 0xf8, 0x00, 0x02, 0x21, 0xee, 0x25, + 0xb3, 0xcb, 0x61, 0x73, 0x04, 0x09, 0xf4, 0x19, 0xf0, 0x07, 0x2f, 0x5a, 0xa1, 0xe0, 0xad, 0xed, 0xc0, 0x03, 0x00, + 0x40, 0x6e, 0x35, 0x56, 0x3c, 0xdb, 0xc5, 0x7c, 0x47, 0xfe, 0x30, 0x55, 0x6b, 0xbe, 0x6e, 0x75, 0xd7, 0x05, 0x38, + 0x2f, 0x30, 0x9b, 0x7f, 0x2c, 0x55, 0xdb, 0x75, 0xc4, 0x69, 0x1a, 0x14, 0x98, 0xa8, 0xd2, 0xab, 0x4c, 0x95, 0xa4, + 0x56, 0x95, 0xa2, 0xe5, 0x61, 0x4d, 0xbb, 0xfa, 0x3c, 0x3e, 0xe6, 0x83, 0xb5, 0x26, 0x10, 0x5a, 0x07, 0x2f, 0xdd, + 0xdb, 0x9b, 0x96, 0x74, 0x6e, 0xb4, 0x4a, 0x9e, 0x68, 0xf3, 0x55, 0xe9, 0x5d, 0x05, 0xb7, 0x4c, 0xf9, 0x22, 0x23, + 0x0e, 0x61, 0x8d, 0xf0, 0x5f, 0xf5, 0x61, 0x68, 0x5b, 0x28, 0xb2, 0x7f, 0x1e, 0x88, 0xe0, 0xa9, 0x92, 0xbd, 0xcc, + 0x6c, 0xf3, 0x88, 0x0c, 0x61, 0x78, 0xe7, 0x12, 0x17, 0xc4, 0xf2, 0x53, 0x5d, 0x79, 0x66, 0xed, 0xee, 0x4d, 0x64, + 0x8b, 0x6c, 0xbc, 0xe3, 0x41, 0xc7, 0x3c, 0xaf, 0x2b, 0xd8, 0x61, 0xa3, 0xbd, 0x49, 0xb3, 0xc7, 0x79, 0x9b, 0xb2, + 0x8c, 0xd5, 0xc1, 0x0b, 0x59, 0x27, 0xc4, 0x24, 0x2d, 0x2a, 0x45, 0xe0, 0x7c, 0x80, 0xd6, 0x1e, 0x4f, 0x77, 0x3f, + 0x25, 0x7e, 0x6d, 0x2e, 0x2c, 0x36, 0xe8, 0x4b, 0x07, 0xbb, 0x9f, 0x79, 0xc4, 0x86, 0x11, 0x5b, 0x90, 0x7f, 0xdb, + 0x06, 0x10, 0xbb, 0x47, 0x94, 0xb2, 0x1b, 0xd1, 0xa3, 0x54, 0x3f, 0xe1, 0x55, 0x3e, 0x50, 0x81, 0x34, 0x66, 0x48, + 0x69, 0xc5, 0x15, 0x27, 0x92, 0xa0, 0x77, 0xb0, 0x04, 0x49, 0x0e, 0xec, 0x7b, 0x82, 0x88, 0xe8, 0x87, 0x9c, 0x8a, + 0x5c, 0xc5, 0x53, 0xcf, 0xa6, 0xdb, 0x23, 0xa3, 0x24, 0x48, 0xee, 0xf1, 0xa3, 0xe0, 0xbb, 0xbd, 0x89, 0xe2, 0x6e, + 0xf3, 0x44, 0xf0, 0xe6, 0x09, 0x26, 0x82, 0xf3, 0x02, 0xf9, 0x98, 0x5d, 0x3c, 0x81, 0x44, 0x25, 0x42, 0xbf, 0xe4, + 0xec, 0xe8, 0xdf, 0x65, 0xa9, 0xb7, 0xda, 0xeb, 0x50, 0x18, 0xb4, 0x2d, 0xa7, 0xd6, 0x38, 0xee, 0xb0, 0x94, 0x5d, + 0x34, 0x77, 0x59, 0xb2, 0x2c, 0x6b, 0x2f, 0xa3, 0x11, 0x1a, 0xa9, 0x79, 0xf8, 0x5c, 0x6a, 0x59, 0xd1, 0xf1, 0xa2, + 0x16, 0xe1, 0xc0, 0x10, 0x4b, 0xa5, 0xb3, 0x9c, 0x62, 0xb5, 0x5d, 0x18, 0x59, 0x8e, 0x23, 0x97, 0x2b, 0x09, 0x28, + 0x9a, 0x43, 0x44, 0x99, 0x0c, 0x1c, 0x47, 0x0b, 0x53, 0x29, 0x30, 0x66, 0x16, 0x1e, 0xec, 0x7c, 0x9b, 0x91, 0xeb, + 0x68, 0x24, 0x5f, 0xf8, 0x86, 0x14, 0xe3, 0x83, 0xb4, 0xd7, 0xd9, 0x88, 0x64, 0xe4, 0x80, 0x3d, 0x97, 0xa9, 0x08, + 0xab, 0x38, 0xaa, 0x77, 0x73, 0x8d, 0xeb, 0x46, 0x65, 0xe4, 0x8a, 0xf6, 0x3a, 0xb2, 0x58, 0x68, 0xc1, 0x7a, 0x7e, + 0xc9, 0xbc, 0xfb, 0x1c, 0x60, 0x6b, 0xa3, 0xac, 0x76, 0xe9, 0x02, 0xcd, 0xf9, 0x58, 0x53, 0xf8, 0x3b, 0x19, 0x81, + 0xbf, 0x71, 0xc2, 0x4e, 0xb3, 0x9f, 0xf7, 0xae, 0x91, 0x59, 0xf6, 0x32, 0xde, 0x32, 0x8f, 0x4e, 0x1d, 0x27, 0xb7, + 0x4e, 0x13, 0xc3, 0x98, 0x61, 0xc9, 0xf7, 0x07, 0xb8, 0xc4, 0x7c, 0x47, 0x80, 0x9d, 0xdf, 0xf3, 0x5c, 0xd2, 0x4e, + 0xe9, 0x80, 0xb4, 0x64, 0xf3, 0xc4, 0x4d, 0xd6, 0x5b, 0x93, 0x9f, 0x53, 0x8a, 0x95, 0x0b, 0xfe, 0x5a, 0xbf, 0xb2, + 0x9e, 0x94, 0xef, 0xd3, 0xe1, 0xad, 0x37, 0x33, 0xf9, 0xc1, 0x56, 0x98, 0xb0, 0x77, 0x40, 0x07, 0x5f, 0xc7, 0x7a, + 0x0b, 0x1f, 0x1f, 0xd8, 0xd1, 0x92, 0x84, 0x4e, 0x15, 0x5a, 0xd5, 0x51, 0xc8, 0xf8, 0xe8, 0x3e, 0x77, 0x1a, 0x89, + 0x45, 0x52, 0x2c, 0xa0, 0xf3, 0xad, 0xda, 0xfb, 0x27, 0xd4, 0xfc, 0xa8, 0x35, 0x99, 0xa2, 0xe9, 0xcc, 0xa9, 0x73, + 0xf5, 0xd7, 0xd4, 0x97, 0xed, 0x58, 0x07, 0x33, 0x71, 0xfd, 0x2d, 0xba, 0x56, 0x5f, 0x73, 0x9f, 0xa5, 0x20, 0x35, + 0x65, 0xd9, 0xc5, 0x89, 0xea, 0xcc, 0xab, 0x51, 0xa4, 0x53, 0xf1, 0xf1, 0x36, 0x72, 0xc7, 0x8b, 0x91, 0xd8, 0xc2, + 0x3b, 0xf8, 0x0a, 0x4b, 0xa2, 0xde, 0x6f, 0x44, 0x7c, 0x4c, 0xa8, 0x19, 0xbe, 0x43, 0x15, 0x38, 0x6b, 0x81, 0x81, + 0x92, 0x9c, 0xa8, 0xdb, 0x4e, 0xc5, 0xd9, 0x19, 0xbc, 0x34, 0x62, 0x57, 0x24, 0xa1, 0x43, 0x3e, 0x43, 0x7d, 0x05, + 0x1f, 0xed, 0xb3, 0x82, 0x1b, 0x4c, 0x2d, 0xf8, 0xb5, 0x8c, 0x62, 0x66, 0xfa, 0xdc, 0x35, 0xc4, 0x20, 0xfa, 0x9e, + 0x96, 0x66, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, 0x9e, 0x83, 0xf7, 0x02, 0x23, 0x62, 0xba, 0x6c, 0x77, 0x36, 0xbf, + 0x6e, 0x23, 0xc8, 0x12, 0x5d, 0x75, 0x9b, 0xc8, 0x24, 0x06, 0xce, 0xb1, 0x26, 0xc4, 0x87, 0x30, 0x43, 0x90, 0x0b, + 0xdd, 0xeb, 0x64, 0xa4, 0xd2, 0x27, 0x5c, 0xa4, 0xa3, 0x8e, 0x1e, 0xee, 0x66, 0x59, 0xbb, 0x61, 0xd7, 0xac, 0xfe, + 0x77, 0xde, 0xb5, 0xc3, 0xeb, 0xd3, 0xa0, 0xc8, 0x13, 0x6a, 0xb0, 0x40, 0x7a, 0x84, 0xbf, 0xf9, 0xf1, 0x50, 0x22, + 0xd3, 0xaf, 0x8f, 0x53, 0x21, 0x33, 0xce, 0x81, 0x03, 0xc8, 0x74, 0x4a, 0xff, 0xce, 0xbe, 0xac, 0xac, 0x60, 0xa4, + 0x0d, 0x7c, 0x6b, 0x06, 0xdb, 0x39, 0x59, 0x88, 0x8e, 0xd3, 0x6e, 0x86, 0xe8, 0xa1, 0x2d, 0x3b, 0xfd, 0x08, 0xad, + 0x53, 0x92, 0x96, 0xfd, 0x10, 0xc1, 0xca, 0x6a, 0x9f, 0x24, 0xba, 0x97, 0x46, 0xc0, 0xae, 0x5f, 0x65, 0x49, 0x2c, + 0x48, 0xa3, 0xff, 0xcc, 0xbc, 0xd2, 0x8d, 0x08, 0x0f, 0x6b, 0xc8, 0x00, 0x36, 0xc4, 0xea, 0x1e, 0xbb, 0x29, 0x2c, + 0xbc, 0xb5, 0x29, 0xd0, 0x99, 0x66, 0x8e, 0x06, 0x01, 0xdb, 0xcb, 0x7d, 0x8c, 0x34, 0x94, 0x3f, 0x5b, 0x89, 0x2d, + 0x47, 0x9a, 0xe2, 0xa3, 0xff, 0x78, 0x6d, 0x9a, 0x62, 0x91, 0x3a, 0x5f, 0xac, 0x27, 0x99, 0xe0, 0xbf, 0xa9, 0x9e, + 0x13, 0xcf, 0x3e, 0x32, 0xba, 0xef, 0xbf, 0x5e, 0x47, 0x56, 0x9e, 0x4f, 0x1c, 0x5f, 0xb5, 0x32, 0x39, 0x5f, 0xb1, + 0xcd, 0x41, 0x05, 0x6c, 0x7e, 0xe0, 0xe7, 0xac, 0x70, 0x6c, 0xc8, 0x3f, 0x9a, 0xf9, 0x08, 0xe3, 0x6a, 0x85, 0xef, + 0xda, 0x8b, 0x87, 0xb6, 0x62, 0x52, 0x24, 0x2d, 0xa8, 0xa4, 0x81, 0x54, 0x23, 0x2b, 0x12, 0x64, 0x18, 0xb9, 0x40, + 0xaf, 0xf8, 0x14, 0x4f, 0xcc, 0x96, 0x24, 0x3c, 0x14, 0xdd, 0xe2, 0x19, 0xa1, 0x42, 0xf0, 0xdf, 0x07, 0x64, 0x22, + 0x90, 0x04, 0x98, 0xeb, 0x08, 0x75, 0x94, 0xc4, 0x13, 0x9e, 0x1e, 0x24, 0xe8, 0x24, 0xe8, 0xe5, 0x5b, 0x21, 0x22, + 0x2a, 0x5f, 0x7d, 0xdd, 0x24, 0x68, 0x56, 0x82, 0x10, 0xcb, 0x19, 0x4b, 0x22, 0xb8, 0xd6, 0x8c, 0xde, 0xfd, 0x88, + 0x52, 0xdd, 0x6d, 0x48, 0x63, 0xf9, 0x0f, 0x23, 0x52, 0xe5, 0x9b, 0x9f, 0x71, 0x75, 0x19, 0xed, 0x19, 0xb9, 0x0b, + 0x54, 0x68, 0xf6, 0x09, 0x19, 0xfa, 0x18, 0xab, 0x16, 0xd1, 0x07, 0xf3, 0xb6, 0xa1, 0xb8, 0xc5, 0x14, 0x9b, 0xbb, + 0xb5, 0x7e, 0xce, 0x7e, 0xcc, 0x1f, 0x90, 0x50, 0x9e, 0x0a, 0x38, 0xc4, 0xc4, 0x2f, 0xc2, 0x06, 0x7d, 0x38, 0xef, + 0xd5, 0x48, 0x75, 0x7f, 0xbf, 0xed, 0xc3, 0x3c, 0x16, 0xe5, 0x27, 0xd4, 0xf6, 0x0c, 0x28, 0xa8, 0x94, 0x51, 0xa0, + 0xd6, 0x80, 0xb1, 0x0b, 0x4e, 0xe4, 0xfc, 0x34, 0x2c, 0x00, 0xea, 0x2b, 0x56, 0x4d, 0x31, 0x18, 0x23, 0x18, 0xe9, + 0x36, 0xc0, 0x0e, 0xa9, 0xd3, 0xc2, 0xc1, 0xbc, 0xfe, 0xf3, 0xa5, 0x0b, 0x0b, 0x84, 0x82, 0x37, 0xc9, 0xd2, 0x9a, + 0x29, 0xf4, 0x13, 0x04, 0xa6, 0xe0, 0x53, 0x79, 0xd4, 0x93, 0x78, 0xdf, 0x3f, 0x5f, 0x57, 0x89, 0x14, 0xf8, 0xb9, + 0xf0, 0x86, 0x08, 0x2b, 0xa6, 0x88, 0x79, 0xc4, 0x67, 0xd6, 0x92, 0x7d, 0xe1, 0x7d, 0xeb, 0x81, 0x3a, 0x05, 0x3c, + 0x73, 0xdf, 0x27, 0xf7, 0x42, 0xe0, 0x0f, 0x57, 0x1f, 0x3e, 0x99, 0x1f, 0xcd, 0x80, 0x55, 0x3d, 0xb2, 0x98, 0x84, + 0xa9, 0x28, 0xb3, 0x84, 0x20, 0x6e, 0x2a, 0x81, 0x85, 0x61, 0x5c, 0x8d, 0x9b, 0x8f, 0x75, 0xeb, 0x29, 0x13, 0x00, + 0x6a, 0x49, 0x42, 0xf7, 0x0c, 0x65, 0xcc, 0xec, 0xa5, 0x15, 0xa0, 0xdc, 0x73, 0x75, 0xf2, 0x72, 0x68, 0x8f, 0x61, + 0xe0, 0x50, 0xb6, 0x36, 0x98, 0xc6, 0x89, 0xc8, 0x32, 0x10, 0x20, 0x0e, 0xe5, 0xd7, 0xb9, 0xd2, 0xba, 0xea, 0x46, + 0x4c, 0x5d, 0x87, 0x7a, 0x3b, 0x47, 0xc7, 0x42, 0xdc, 0xfb, 0x99, 0x1e, 0x01, 0xb6, 0xd3, 0xf7, 0xf2, 0x03, 0x27, + 0x15, 0x02, 0xaf, 0x84, 0xca, 0x03, 0x89, 0xec, 0x81, 0x76, 0x50, 0x36, 0x00, 0x92, 0xdc, 0x16, 0x57, 0x0a, 0xd2, + 0x16, 0x20, 0x66, 0x36, 0xfe, 0xa7, 0x1f, 0x34, 0x8a, 0x03, 0xf2, 0xbe, 0x0f, 0x92, 0x92, 0xc6, 0xb3, 0x50, 0x6d, + 0x9c, 0x48, 0x11, 0xcc, 0xe0, 0x61, 0x11, 0x34, 0x22, 0x53, 0xa1, 0x73, 0x2b, 0xd8, 0xc6, 0xef, 0x5e, 0x9b, 0x47, + 0xa2, 0xc2, 0xf4, 0x37, 0xff, 0x74, 0x65, 0xdd, 0xa2, 0x48, 0xcb, 0xef, 0x71, 0xdd, 0xc7, 0xf8, 0xff, 0x06, 0x45, + 0x49, 0x92, 0xcd, 0x5e, 0x2a, 0x99, 0xce, 0xd8, 0xf3, 0x2b, 0xad, 0x8f, 0x16, 0xed, 0x81, 0x7d, 0xc3, 0x7b, 0xd0, + 0xdc, 0x03, 0xe1, 0x87, 0x92, 0x56, 0x9b, 0xfa, 0x84, 0xaa, 0x0a, 0x32, 0x24, 0x1a, 0xe3, 0x22, 0xb5, 0xa6, 0x4c, + 0xb5, 0x5b, 0xec, 0x06, 0x90, 0x4c, 0x63, 0x54, 0xd1, 0xe4, 0xbe, 0x79, 0x66, 0xf3, 0xc2, 0x3d, 0x91, 0x46, 0xd3, + 0x05, 0xb9, 0xfc, 0x2c, 0x39, 0xca, 0x94, 0x92, 0x25, 0xb1, 0x0c, 0x87, 0xf3, 0x10, 0x61, 0xae, 0x35, 0x44, 0x54, + 0x2a, 0x8c, 0x37, 0x4c, 0x4a, 0x13, 0x2b, 0xf9, 0x2d, 0x4a, 0x84, 0x45, 0xb0, 0xfa, 0xb4, 0xad, 0x03, 0x5c, 0x9b, + 0x83, 0x72, 0x84, 0x7b, 0xcb, 0x13, 0x6c, 0x6a, 0x9d, 0x07, 0xe7, 0x51, 0xae, 0x8a, 0x43, 0xa1, 0x4e, 0xdb, 0x07, + 0x54, 0xde, 0x44, 0xe8, 0x0c, 0x99, 0xb0, 0x35, 0x1e, 0x63, 0x90, 0x1b, 0x8f, 0x37, 0xd1, 0x0d, 0xcd, 0x87, 0x89, + 0x8a, 0xfa, 0x44, 0x5e, 0x26, 0xa0, 0xaa, 0xde, 0xa4, 0xf7, 0x53, 0xf2, 0xd3, 0x28, 0xa2, 0xc8, 0x9d, 0xe4, 0x84, + 0xca, 0x5a, 0x12, 0x15, 0x05, 0xb6, 0xf0, 0x24, 0x09, 0x09, 0xa0, 0xb8, 0x1b, 0xe3, 0x50, 0x85, 0xfc, 0xae, 0xca, + 0xe1, 0x5d, 0x8f, 0xea, 0xd0, 0xd2, 0x25, 0x90, 0xe4, 0x67, 0x32, 0xe9, 0x8f, 0x79, 0xef, 0x3e, 0x93, 0x87, 0xf7, + 0x23, 0x85, 0xb9, 0x8f, 0xf1, 0x1a, 0x66, 0x21, 0x2e, 0xff, 0xf6, 0xf3, 0xa2, 0x17, 0x1f, 0x25, 0x9d, 0x20, 0x33, + 0x54, 0xae, 0x8d, 0xf7, 0x4d, 0x23, 0x52, 0x55, 0xd4, 0x42, 0x20, 0x9f, 0xdc, 0xfd, 0x7a, 0x06, 0xa5, 0x8c, 0xe6, + 0x72, 0xaa, 0x5e, 0x27, 0xe5, 0x36, 0x7e, 0x18, 0x1a, 0xa2, 0xd7, 0xe5, 0x68, 0x53, 0xc0, 0x12, 0x6d, 0xf3, 0xf0, + 0xcf, 0x07, 0xab, 0xc8, 0x97, 0xe3, 0xa6, 0xd8, 0xa7, 0x8a, 0xc5, 0x9c, 0x7b, 0x7f, 0xb7, 0xc6, 0x03, 0x61, 0x7f, + 0x4a, 0x22, 0x99, 0x08, 0x02, 0x92, 0xb2, 0x05, 0x9e, 0x81, 0x43, 0x29, 0x5d, 0x9a, 0xa8, 0x35, 0x38, 0x94, 0xd4, + 0x9c, 0x7d, 0x4f, 0x2a, 0x9f, 0x3e, 0x2f, 0x11, 0x7e, 0x65, 0x5e, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xc7, + 0x12, 0x2d, 0x80, 0x5a, 0xa8, 0x0b, 0x75, 0x53, 0x01, 0xc1, 0xf8, 0x5a, 0xef, 0x0f, 0x91, 0x51, 0x85, 0xe2, 0x29, + 0x4a, 0xe9, 0x68, 0x97, 0xaf, 0xb8, 0x7d, 0xe9, 0x84, 0x29, 0x7c, 0xc3, 0x11, 0x47, 0xe4, 0x99, 0xee, 0x9b, 0x76, + 0xb9, 0x69, 0x45, 0xff, 0x80, 0x08, 0xf1, 0x6e, 0xbe, 0xd4, 0xb9, 0x31, 0x39, 0x82, 0x2b, 0x82, 0x66, 0x8b, 0x83, + 0xa7, 0xf2, 0x0f, 0xd7, 0x65, 0x21, 0x5d, 0x13, 0xe5, 0x48, 0x22, 0x3f, 0x64, 0x06, 0x5a, 0x01, 0x89, 0x35, 0x61, + 0x44, 0x0e, 0x66, 0x0b, 0x00, 0xbd, 0x36, 0x47, 0xb7, 0xda, 0xa8, 0x2e, 0x5b, 0x00, 0x5b, 0xfa, 0x0a, 0x46, 0x86, + 0x42, 0xe8, 0x88, 0xe1, 0x40, 0x46, 0xd4, 0x27, 0x95, 0x81, 0x2c, 0x3a, 0xc7, 0x02, 0x94, 0x79, 0x9f, 0x82, 0xbc, + 0x71, 0x12, 0x25, 0x24, 0x8d, 0x33, 0xf3, 0x49, 0x9d, 0x9d, 0x94, 0x83, 0xac, 0xa5, 0x90, 0x9e, 0x54, 0x37, 0xa8, + 0x5c, 0x2b, 0x7a, 0x25, 0xf4, 0x50, 0x72, 0x27, 0x36, 0x83, 0xd7, 0x5c, 0x19, 0xc5, 0x2f, 0x2d, 0xff, 0x32, 0xa1, + 0x61, 0x51, 0x9d, 0x40, 0x07, 0x7a, 0x09, 0xad, 0x21, 0xe6, 0xff, 0x5d, 0xb9, 0x77, 0x1d, 0xa4, 0x5b, 0xc7, 0x40, + 0xcb, 0x79, 0xab, 0xd4, 0xb3, 0x50, 0xd1, 0xad, 0xed, 0x99, 0xd4, 0x56, 0x15, 0x07, 0xdb, 0x98, 0x16, 0x64, 0xde, + 0xc1, 0xe7, 0x94, 0x0e, 0xa9, 0x8f, 0xb6, 0x71, 0xcd, 0x15, 0xd9, 0x83, 0xa5, 0xaf, 0xb1, 0x32, 0xa7, 0x0f, 0xc3, + 0x81, 0x17, 0x93, 0xb9, 0xb1, 0xe3, 0x6f, 0x84, 0x55, 0x2b, 0xd5, 0x46, 0xc4, 0xec, 0x10, 0x60, 0xaa, 0x1a, 0x8d, + 0x35, 0xef, 0xc3, 0x64, 0xa1, 0x9f, 0x65, 0xae, 0x00, 0xe5, 0x88, 0x49, 0xbd, 0xb2, 0xec, 0x85, 0xd6, 0x83, 0xef, + 0x97, 0x57, 0x57, 0xb2, 0xec, 0x5a, 0xa7, 0x87, 0xc0, 0x09, 0xe0, 0x4d, 0x41, 0xd5, 0x1a, 0x2f, 0xee, 0xdb, 0x0b, + 0xaf, 0xad, 0x0b, 0x52, 0x12, 0xf0, 0x8e, 0x92, 0xc1, 0x57, 0x9e, 0x06, 0x82, 0xe6, 0x7b, 0xe5, 0x7e, 0x62, 0x46, + 0x24, 0x72, 0xc7, 0xed, 0x19, 0x1f, 0xcf, 0xc3, 0x95, 0xa1, 0xf8, 0x65, 0x6c, 0x4d, 0x6b, 0x81, 0xf9, 0x83, 0x04, + 0x96, 0x13, 0xb5, 0x5b, 0x9f, 0x8b, 0x79, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x23, 0x54, 0x0c, 0x27, 0x81, 0xa2, 0x91, + 0x16, 0x98, 0xc3, 0x58, 0xe7, 0x70, 0x0b, 0x08, 0xa9, 0x53, 0x20, 0xe8, 0x6f, 0x47, 0x02, 0x8c, 0xfc, 0x41, 0x91, + 0x13, 0x4f, 0x9a, 0x9b, 0x35, 0x08, 0xfc, 0x7d, 0x38, 0x54, 0xa7, 0xed, 0xe5, 0x27, 0xdc, 0x81, 0x9b, 0xd8, 0x33, + 0x8e, 0x9f, 0xc5, 0xfd, 0x26, 0x27, 0x91, 0x73, 0x28, 0xaa, 0xf2, 0x39, 0x87, 0xc4, 0x4c, 0x1c, 0xea, 0x70, 0xfb, + 0x20, 0x5d, 0x5b, 0xc0, 0x70, 0x71, 0x98, 0xc6, 0x5e, 0x1d, 0x25, 0x20, 0x95, 0x7c, 0x74, 0x37, 0x9f, 0x7e, 0xf6, + 0x51, 0x3d, 0x88, 0xf6, 0x21, 0xe2, 0x6f, 0x6d, 0x49, 0xa3, 0x50, 0x79, 0x38, 0xb7, 0xbe, 0xa4, 0x86, 0x8f, 0x10, + 0x87, 0x7f, 0x2f, 0x16, 0xc5, 0x40, 0xec, 0x36, 0xb9, 0xe6, 0x82, 0x41, 0xef, 0x24, 0x03, 0xa1, 0xf5, 0x66, 0x98, + 0xca, 0x55, 0xb3, 0x2d, 0xac, 0x4c, 0x3b, 0x83, 0x0f, 0x36, 0xb6, 0xc5, 0x09, 0x08, 0xa2, 0x95, 0x41, 0xb7, 0x84, + 0x09, 0x4b, 0x8c, 0x29, 0xf4, 0x2d, 0x31, 0xcc, 0x79, 0x16, 0x95, 0xc4, 0x02, 0x4c, 0x47, 0x6b, 0xb6, 0xf4, 0x2b, + 0xa6, 0x2b, 0x9d, 0x89, 0xde, 0xb4, 0x41, 0xa6, 0x92, 0x66, 0x16, 0xc0, 0xdf, 0x64, 0x67, 0xd9, 0xe0, 0x1f, 0xd0, + 0xda, 0x95, 0x22, 0x31, 0x21, 0xdd, 0x82, 0x17, 0x95, 0x95, 0x9a, 0x37, 0x2e, 0x94, 0xfb, 0x35, 0xdf, 0xb4, 0xad, + 0x15, 0x82, 0xc3, 0x3a, 0x24, 0x1f, 0x58, 0x80, 0xe5, 0x72, 0x29, 0x2e, 0x55, 0x3b, 0x82, 0xa1, 0xb4, 0x95, 0xe4, + 0xc3, 0x22, 0x43, 0xd2, 0xe3, 0x13, 0x0d, 0x91, 0x90, 0x33, 0x9e, 0xb3, 0x35, 0xe0, 0xe4, 0xee, 0xce, 0x6a, 0xa6, + 0xf5, 0xa7, 0xdd, 0x78, 0xcf, 0x4b, 0x10, 0x93, 0x66, 0x0a, 0xbc, 0x27, 0xbb, 0x81, 0xb4, 0xdb, 0x2c, 0x36, 0xfa, + 0x9b, 0x6e, 0x69, 0x80, 0xee, 0xb6, 0x83, 0x01, 0x0c, 0x8c, 0x30, 0x0b, 0x2e, 0xbc, 0xa0, 0x6b, 0xff, 0xe0, 0x18, + 0xf0, 0x48, 0x81, 0xb3, 0x62, 0x48, 0x19, 0xe2, 0x6e, 0x6c, 0xf3, 0x63, 0xb6, 0x58, 0xbc, 0xfe, 0xfa, 0x3d, 0x32, + 0xa0, 0x2e, 0x70, 0x04, 0x1f, 0x68, 0x19, 0xa9, 0x34, 0x70, 0x4a, 0x2a, 0x3f, 0xda, 0x3b, 0x93, 0x6c, 0x65, 0x6a, + 0x85, 0xb0, 0xaa, 0x06, 0x9b, 0x1a, 0xd0, 0x66, 0x96, 0x96, 0xb6, 0xa5, 0x16, 0x98, 0xdb, 0xde, 0x0b, 0x30, 0xf9, + 0x02, 0x7a, 0xc0, 0xf2, 0x9f, 0xa1, 0x7b, 0x18, 0x4d, 0x2c, 0xe3, 0x5e, 0x10, 0x17, 0x55, 0x10, 0x40, 0x7a, 0x5b, + 0x8f, 0x20, 0x69, 0x5a, 0x63, 0xa2, 0xc3, 0xa2, 0xbb, 0x11, 0xb0, 0x0a, 0x2d, 0x31, 0x02, 0x7b, 0xc8, 0x8d, 0xa9, + 0x58, 0x3a, 0xf2, 0xab, 0x05, 0x16, 0x3e, 0x0f, 0x62, 0x5f, 0x93, 0xae, 0x97, 0xa5, 0x06, 0x62, 0xf2, 0x68, 0xeb, + 0x8d, 0x7e, 0x48, 0x8f, 0x76, 0x5d, 0xe3, 0x7d, 0xd4, 0x44, 0x60, 0x65, 0x2a, 0xb7, 0x87, 0xd9, 0x76, 0xfd, 0xd5, + 0x92, 0x02, 0xd5, 0xcc, 0x59, 0x16, 0xfe, 0xf6, 0xfe, 0x69, 0x3f, 0x01, 0x2e, 0xdf, 0xf1, 0xae, 0xe7, 0x80, 0xb0, + 0x1c, 0x9d, 0x55, 0x72, 0xdd, 0x6e, 0x6b, 0xff, 0x33, 0x3e, 0x34, 0x86, 0x92, 0x61, 0xfb, 0x9f, 0xee, 0x4e, 0xd7, + 0x23, 0x15, 0x0e, 0xa3, 0xc0, 0x51, 0xf8, 0xde, 0x7b, 0xcf, 0xab, 0x95, 0x3a, 0xce, 0xb2, 0x5f, 0xfb, 0xd6, 0xd4, + 0xeb, 0x64, 0x1b, 0xd6, 0x28, 0xbe, 0x1d, 0x23, 0x1b, 0x7b, 0xc1, 0xc8, 0xda, 0x18, 0xab, 0x7b, 0x04, 0x6b, 0x8f, + 0x6b, 0x8a, 0xe1, 0x6e, 0x05, 0xdf, 0x6f, 0xf7, 0xb8, 0x96, 0xd3, 0x39, 0xdd, 0x99, 0x6f, 0xdb, 0x2f, 0x7f, 0x72, + 0x96, 0x16, 0x1e, 0x34, 0x6f, 0xca, 0x65, 0x96, 0x2e, 0xab, 0xe4, 0x5a, 0x20, 0x4f, 0x36, 0x9d, 0x8b, 0x7a, 0xfd, + 0x79, 0xaf, 0x11, 0x66, 0xb0, 0x77, 0x17, 0xf1, 0xf6, 0x3e, 0xba, 0x9b, 0xcb, 0xa9, 0xcf, 0xbb, 0x45, 0x43, 0x08, + 0xe5, 0xe6, 0x95, 0xd3, 0xd6, 0x1b, 0xc7, 0x1c, 0x0f, 0xf8, 0xb0, 0x78, 0xef, 0x90, 0x13, 0x42, 0x6d, 0xf0, 0xeb, + 0x09, 0xee, 0x3e, 0xc4, 0x93, 0x6d, 0x7f, 0x4e, 0xdc, 0xe6, 0x0c, 0x11, 0xb6, 0xc8, 0xc3, 0xd2, 0x94, 0x74, 0x5c, + 0x03, 0x1b, 0xee, 0xce, 0x0a, 0x99, 0xb9, 0xf8, 0x95, 0xfb, 0xc6, 0x2d, 0x1c, 0x7d, 0x4f, 0xc8, 0x21, 0xcb, 0x32, + 0x6d, 0xde, 0x82, 0xbe, 0xb0, 0x99, 0xe5, 0x69, 0x1a, 0x93, 0xe5, 0x0f, 0x23, 0xdc, 0x15, 0x72, 0xd7, 0x5c, 0x45, + 0xcb, 0x69, 0x96, 0x8a, 0xba, 0x67, 0x1c, 0xb7, 0x38, 0xe3, 0x20, 0xbe, 0x07, 0x33, 0xfd, 0x7e, 0x8d, 0x6c, 0x68, + 0x5e, 0xfb, 0x07, 0x9e, 0x65, 0xe0, 0xf4, 0x5f, 0x6d, 0x54, 0xa7, 0x72, 0x9e, 0x03, 0xa0, 0x64, 0x89, 0xfe, 0x74, + 0x1c, 0xd2, 0x86, 0x42, 0x18, 0x15, 0xee, 0xbe, 0xfc, 0x68, 0x6f, 0x79, 0x15, 0x13, 0xd1, 0x1e, 0x3d, 0xe9, 0xce, + 0x08, 0x57, 0xc4, 0x5b, 0x46, 0x03, 0x28, 0xc6, 0x82, 0x0e, 0x14, 0x52, 0x56, 0x7b, 0x34, 0x67, 0x43, 0x9c, 0x79, + 0x9e, 0x54, 0x91, 0x2e, 0x02, 0xd6, 0x77, 0xc5, 0xa1, 0x9e, 0xdc, 0xab, 0xc0, 0xcb, 0xbe, 0x60, 0x1d, 0xea, 0x01, + 0xdc, 0x6f, 0x8a, 0x14, 0x1f, 0x69, 0xeb, 0x97, 0x5c, 0x31, 0xba, 0xb6, 0x4a, 0xc6, 0xfa, 0x6e, 0x8c, 0x68, 0xc4, + 0xe4, 0xaa, 0x26, 0x2c, 0xa7, 0x31, 0x8a, 0x46, 0x81, 0xe4, 0x9c, 0x1a, 0xc7, 0x38, 0x1d, 0x58, 0x4f, 0x22, 0x29, + 0x5d, 0x40, 0xc8, 0x2c, 0xc9, 0xf4, 0xa0, 0x01, 0x96, 0x64, 0xa4, 0x0d, 0x2a, 0xef, 0xa1, 0xa3, 0x71, 0xcf, 0x32, + 0x68, 0xee, 0x50, 0x57, 0x15, 0xae, 0xdd, 0xf2, 0x20, 0x53, 0x31, 0xb7, 0x66, 0x53, 0xfd, 0xb8, 0x1c, 0x44, 0x76, + 0x4d, 0xbb, 0x76, 0xdb, 0x67, 0x03, 0x2a, 0xb8, 0x81, 0x0c, 0x07, 0x29, 0xfb, 0x90, 0xd1, 0x23, 0x72, 0x67, 0x49, + 0xf7, 0xf9, 0x81, 0x42, 0xbf, 0x53, 0x07, 0x04, 0x18, 0xf9, 0x4a, 0x68, 0x87, 0x0d, 0x77, 0xea, 0xd0, 0x79, 0xdb, + 0x63, 0x22, 0x47, 0xe1, 0xf0, 0x2a, 0x49, 0xdf, 0x13, 0x6d, 0x47, 0x37, 0xee, 0xfb, 0xe3, 0x80, 0x9f, 0x94, 0xa6, + 0x88, 0x5a, 0x93, 0xd4, 0xe9, 0x62, 0xb9, 0x25, 0x9a, 0x0c, 0xfd, 0x8d, 0xe2, 0xb3, 0xe0, 0xc2, 0xc3, 0x12, 0xb7, + 0x1b, 0x0a, 0x5c, 0x89, 0xab, 0x72, 0x1f, 0x5f, 0x09, 0x68, 0x5c, 0x27, 0xe8, 0xfa, 0x8c, 0xa3, 0x3a, 0x18, 0x43, + 0x25, 0x66, 0x6f, 0xb0, 0x82, 0xb2, 0xaa, 0x47, 0x1c, 0x63, 0xeb, 0x67, 0x34, 0x37, 0x1e, 0x63, 0xd2, 0xb8, 0x9c, + 0x71, 0x44, 0xfa, 0xc8, 0x8c, 0x54, 0x86, 0x29, 0xbc, 0x3d, 0x72, 0x74, 0xa7, 0x76, 0xd3, 0xe5, 0x82, 0x66, 0x8c, + 0xca, 0xa0, 0x5f, 0xbc, 0x84, 0xd9, 0xc2, 0x12, 0x3c, 0x88, 0xab, 0x8b, 0x73, 0x6b, 0x17, 0x1f, 0x1d, 0x2a, 0xcc, + 0xc7, 0x36, 0x9f, 0x2f, 0x53, 0x45, 0xae, 0x84, 0x61, 0xea, 0xa7, 0xe9, 0xc5, 0x75, 0xa7, 0x92, 0xf6, 0x8b, 0xb0, + 0xfa, 0x9a, 0x19, 0x0f, 0xd8, 0x77, 0xdb, 0x10, 0x6d, 0xbf, 0x2f, 0x59, 0xaf, 0x2b, 0x53, 0x69, 0x7f, 0x6c, 0xee, + 0xd6, 0x64, 0xb7, 0xdb, 0x69, 0xdf, 0xa1, 0x13, 0x65, 0x90, 0xff, 0xfe, 0xcd, 0x7e, 0xe5, 0x4b, 0x4b, 0xfd, 0xa9, + 0xd0, 0x58, 0x1e, 0xb9, 0xf9, 0xb5, 0x1b, 0x55, 0x1d, 0x36, 0x94, 0xbb, 0x4e, 0xc7, 0xc8, 0x9d, 0x7d, 0x35, 0xd1, + 0xc4, 0x37, 0x4f, 0xf7, 0x73, 0xb1, 0xdc, 0x5f, 0x7d, 0xb4, 0xb7, 0x8f, 0xa4, 0x5c, 0xa4, 0x7c, 0xc9, 0x5e, 0xf3, + 0x94, 0xed, 0x22, 0x95, 0x11, 0xa0, 0x8c, 0xde, 0x48, 0x6f, 0x12, 0x9a, 0x26, 0xa9, 0x46, 0xfe, 0xe4, 0xf7, 0xf0, + 0xad, 0xba, 0x7b, 0xfd, 0x93, 0xa5, 0xbd, 0x13, 0x22, 0x1e, 0x00, 0xfe, 0x5b, 0xbe, 0xfd, 0xa9, 0xd8, 0xcd, 0x5c, + 0x56, 0x5b, 0x3e, 0xf0, 0xad, 0xb0, 0xaf, 0x8c, 0x87, 0x7e, 0x25, 0x55, 0x94, 0x7e, 0x95, 0x70, 0x89, 0x91, 0xb1, + 0xc9, 0x47, 0x75, 0xd3, 0x7a, 0xdc, 0x7b, 0x7d, 0x47, 0x00, 0x45, 0xf8, 0xc7, 0xc2, 0x18, 0xef, 0x21, 0x51, 0x38, + 0x15, 0x62, 0x98, 0x96, 0x9a, 0xca, 0x01, 0xd8, 0x34, 0xfa, 0x35, 0x8a, 0x53, 0xa9, 0xc8, 0x8f, 0xdf, 0x1f, 0x59, + 0xf9, 0xcd, 0x6d, 0xfe, 0xff, 0xdb, 0xcf, 0xde, 0x23, 0x14, 0x5a, 0x40, 0xd2, 0x7d, 0x14, 0xc9, 0x27, 0x11, 0xa8, + 0xb4, 0x72, 0x58, 0x8d, 0xb5, 0x1d, 0x24, 0x5a, 0x35, 0xad, 0xea, 0xc3, 0x17, 0x8f, 0xa1, 0xa7, 0x68, 0xa6, 0x14, + 0x51, 0xa9, 0xf2, 0x06, 0x09, 0xa1, 0x9e, 0xc6, 0xa7, 0x89, 0x4a, 0x85, 0xfc, 0x72, 0xb3, 0xfe, 0xe9, 0x8e, 0x49, + 0x10, 0x96, 0x73, 0x60, 0x88, 0xf4, 0x90, 0x3c, 0xa0, 0xc2, 0xee, 0x7c, 0x4c, 0xa3, 0x3a, 0xa5, 0x4f, 0x47, 0xf0, + 0x76, 0xaa, 0x69, 0xbb, 0x56, 0x5e, 0xcb, 0x2e, 0x91, 0x50, 0x82, 0xfb, 0x48, 0x33, 0x87, 0x0e, 0x1a, 0xa5, 0xa3, + 0xfb, 0xde, 0x3f, 0x09, 0x19, 0xba, 0xc0, 0xd0, 0xfb, 0xed, 0x03, 0x3f, 0xb6, 0xd5, 0xa0, 0xc7, 0x70, 0xd1, 0xb6, + 0xe8, 0x55, 0x5f, 0x16, 0x5d, 0x26, 0xb7, 0x97, 0xa2, 0x01, 0x92, 0x64, 0x7a, 0x16, 0x44, 0xe6, 0x7e, 0x21, 0x67, + 0x1d, 0xcf, 0x4f, 0x71, 0x2f, 0x1e, 0x53, 0x25, 0xa3, 0x1b, 0xfe, 0xea, 0x34, 0xf2, 0xbd, 0x89, 0xc4, 0xc7, 0x24, + 0x16, 0x92, 0x6d, 0x8c, 0xa0, 0xd7, 0x62, 0x78, 0x6e, 0x2c, 0xfd, 0x8d, 0x28, 0x50, 0x1a, 0x04, 0x58, 0x3a, 0x8f, + 0x94, 0x81, 0x2b, 0x36, 0xca, 0xdf, 0x6d, 0x68, 0x98, 0x52, 0x9b, 0x07, 0x44, 0xde, 0x65, 0xbf, 0x28, 0x32, 0xde, + 0x40, 0x24, 0x08, 0x46, 0x2a, 0xb8, 0x09, 0x52, 0xd0, 0x98, 0x2e, 0x30, 0x5b, 0x40, 0xb6, 0x38, 0x6e, 0x80, 0xcb, + 0x57, 0x8a, 0xe9, 0x52, 0xf5, 0xce, 0xe6, 0xaa, 0xe2, 0xc7, 0xf0, 0xbe, 0x5b, 0xeb, 0x20, 0x3e, 0x38, 0x11, 0x74, + 0x45, 0x69, 0xd2, 0xd3, 0x47, 0x26, 0xc9, 0x5a, 0x94, 0x2d, 0x46, 0x0f, 0x1a, 0x06, 0x2a, 0x2a, 0xac, 0x36, 0xd6, + 0x28, 0xf6, 0x2b, 0xba, 0x20, 0x8c, 0xc2, 0x17, 0xed, 0xc6, 0xc8, 0x7b, 0x97, 0x66, 0x5e, 0xbb, 0x1b, 0x47, 0xad, + 0xc8, 0x8b, 0x63, 0x5e, 0x73, 0x14, 0xd9, 0x1d, 0x26, 0x79, 0xfc, 0x55, 0x11, 0x05, 0xc3, 0x64, 0x64, 0x7b, 0xec, + 0xdb, 0x22, 0x33, 0x11, 0x22, 0xb6, 0x7e, 0xeb, 0x9d, 0x7d, 0x1b, 0x85, 0xb8, 0xe7, 0x23, 0xe1, 0xfe, 0x92, 0xe4, + 0x2a, 0xe0, 0x65, 0x5e, 0x73, 0xe8, 0x37, 0xe6, 0xd4, 0x50, 0xa9, 0xd1, 0x10, 0xf0, 0x2b, 0x95, 0x78, 0x40, 0x26, + 0xa8, 0x9c, 0xd8, 0x75, 0x1f, 0x5c, 0x46, 0x40, 0x87, 0xcb, 0xda, 0x68, 0xe6, 0xd3, 0xf7, 0xc8, 0xb5, 0x9d, 0xd6, + 0x47, 0x1a, 0x51, 0xe0, 0xe5, 0x56, 0x65, 0x70, 0xa0, 0x4f, 0xa5, 0xac, 0xbc, 0x20, 0x8a, 0x4e, 0xb4, 0x15, 0x1c, + 0x16, 0xb7, 0xc1, 0xbf, 0x47, 0x58, 0x2c, 0xb9, 0xe7, 0xb8, 0x01, 0xc8, 0x39, 0x8b, 0xc8, 0x46, 0x05, 0xf1, 0xef, + 0x00, 0x3b, 0x32, 0xe6, 0x1a, 0xc9, 0xb2, 0x86, 0xa9, 0x88, 0xb6, 0xf7, 0x11, 0x91, 0x6e, 0x87, 0x0b, 0x73, 0x8a, + 0x5e, 0x8c, 0x6f, 0x9b, 0x55, 0xb4, 0xe0, 0x01, 0xaa, 0xe0, 0xf3, 0x59, 0x70, 0x88, 0x95, 0x5f, 0xe1, 0xbe, 0xd9, + 0x10, 0x4d, 0xe0, 0x3c, 0x99, 0x07, 0x9d, 0x8b, 0x76, 0x22, 0xd7, 0xcf, 0x15, 0xb9, 0x97, 0xe4, 0x1b, 0x58, 0xaf, + 0x2c, 0xdd, 0x37, 0x8b, 0x79, 0x1a, 0x58, 0x81, 0x7e, 0x58, 0x84, 0x34, 0x70, 0x56, 0x99, 0xce, 0x3a, 0x7a, 0xaa, + 0x79, 0x22, 0x10, 0x12, 0xc0, 0x02, 0x03, 0x29, 0xfd, 0x35, 0xec, 0xde, 0x47, 0xa0, 0x11, 0xec, 0x14, 0x98, 0x61, + 0xde, 0x4f, 0x24, 0x0d, 0x6d, 0x53, 0xf5, 0x23, 0x1d, 0xd8, 0xbd, 0xb2, 0x57, 0xd8, 0x40, 0x07, 0xcb, 0xdf, 0xe7, + 0xdc, 0xf0, 0xd2, 0xdd, 0x7c, 0xfb, 0x57, 0x89, 0xd4, 0x72, 0x6d, 0xb5, 0xc0, 0xbf, 0x13, 0xeb, 0x73, 0x21, 0xc8, + 0x3e, 0xef, 0xcb, 0x08, 0x2b, 0x6a, 0x1c, 0x35, 0x9f, 0xb5, 0x17, 0xb5, 0xfc, 0x59, 0x09, 0x08, 0xce, 0xbd, 0x25, + 0xf1, 0x6e, 0x08, 0x1e, 0x77, 0x2e, 0xc9, 0xde, 0xd0, 0xe3, 0x49, 0x1f, 0xb2, 0xf2, 0xb1, 0x83, 0xd9, 0x42, 0x26, + 0xf3, 0x1d, 0x2a, 0x8a, 0x03, 0xf1, 0x46, 0x29, 0x3c, 0xc7, 0xdf, 0xcd, 0xd2, 0x04, 0x29, 0x79, 0xa5, 0xbf, 0x15, + 0x6f, 0x8c, 0x30, 0x1f, 0x63, 0x03, 0x07, 0xa3, 0x00, 0x91, 0xbf, 0x45, 0x83, 0x2a, 0x94, 0x70, 0xb4, 0x10, 0xa7, + 0xa1, 0xea, 0x25, 0x62, 0xdf, 0x95, 0x0f, 0xd5, 0xec, 0xab, 0x7e, 0xa2, 0x4e, 0xd7, 0x99, 0xb5, 0x37, 0x08, 0x85, + 0x6e, 0xb3, 0x5b, 0x6f, 0x32, 0x86, 0x2c, 0xda, 0x86, 0xd3, 0xf1, 0xf8, 0xfb, 0x73, 0xb3, 0x7c, 0xac, 0xd3, 0xec, + 0x5f, 0x2e, 0x0f, 0x48, 0xb5, 0xea, 0x8e, 0x7d, 0x3f, 0x2b, 0xfb, 0xc9, 0x7f, 0x1f, 0x53, 0x5d, 0xc6, 0xd3, 0xbd, + 0x12, 0x80, 0x8f, 0x45, 0x94, 0xa7, 0x17, 0x11, 0x9a, 0xab, 0xf9, 0x4e, 0xfd, 0x95, 0x3c, 0xe2, 0xab, 0xd7, 0xee, + 0x1f, 0xf9, 0xa0, 0x96, 0xd3, 0x55, 0x01, 0x19, 0x32, 0xe2, 0x71, 0xff, 0x55, 0xc8, 0x68, 0xd5, 0x5c, 0x5f, 0xcc, + 0x51, 0xf4, 0xdc, 0xf9, 0x7b, 0xd3, 0x90, 0x4d, 0x2f, 0x45, 0x4f, 0x98, 0x0f, 0xd4, 0xc8, 0x6d, 0x20, 0xe8, 0x26, + 0xdc, 0xe0, 0x74, 0x47, 0xaa, 0x4e, 0x56, 0x8c, 0x2e, 0x17, 0xbf, 0x4f, 0xcf, 0x22, 0xa5, 0xbe, 0x4c, 0x2d, 0x14, + 0xaa, 0x7d, 0x1f, 0x6a, 0x47, 0xc7, 0x55, 0x21, 0x6f, 0x82, 0x07, 0xc5, 0xd9, 0x12, 0x16, 0x6d, 0x54, 0x4e, 0x14, + 0x48, 0x32, 0xac, 0x16, 0x19, 0x37, 0x9f, 0x94, 0xac, 0x21, 0x43, 0x9d, 0x99, 0x23, 0xd0, 0x1c, 0x62, 0xa7, 0x62, + 0x28, 0xe9, 0xfd, 0x65, 0x06, 0x0a, 0x33, 0x44, 0xfb, 0x81, 0x01, 0x7a, 0xe5, 0x3e, 0x9a, 0x5b, 0xe6, 0xe4, 0x62, + 0x5c, 0x76, 0x09, 0xc4, 0x33, 0x8c, 0xbd, 0x6f, 0x91, 0x08, 0xda, 0xc9, 0x3b, 0x2a, 0x0d, 0xbe, 0x98, 0xee, 0x98, + 0x40, 0x72, 0x42, 0xce, 0x99, 0x31, 0x7d, 0xc5, 0x7f, 0xcd, 0xf5, 0xe4, 0xe4, 0x4d, 0x52, 0x1e, 0x57, 0x8f, 0xf0, + 0xdb, 0xb5, 0xf6, 0x2d, 0x72, 0x1f, 0x8c, 0x34, 0x55, 0x4b, 0x7e, 0x5b, 0x2a, 0xc8, 0x12, 0x16, 0x6e, 0xac, 0x7e, + 0xea, 0xca, 0x2e, 0x64, 0xb7, 0xba, 0xf0, 0xdc, 0x36, 0x2f, 0x6b, 0xf4, 0xfb, 0x66, 0xef, 0xa1, 0xbd, 0x75, 0x05, + 0xea, 0x55, 0x6d, 0x40, 0xa5, 0xce, 0xfd, 0xd1, 0xfc, 0xf6, 0x12, 0xf4, 0x4a, 0x7d, 0xf9, 0x78, 0xf0, 0x2b, 0x6a, + 0x2c, 0x62, 0xfa, 0x5b, 0xf5, 0xb7, 0x70, 0xf2, 0x84, 0x7b, 0xab, 0x5d, 0x63, 0x5d, 0x45, 0x03, 0xa1, 0xb9, 0x7b, + 0xed, 0xf9, 0xf0, 0xbe, 0x57, 0x6d, 0x75, 0x0d, 0x50, 0xbd, 0xe3, 0x9f, 0xe1, 0x5b, 0x08, 0xa7, 0x51, 0xe8, 0xee, + 0xa7, 0x16, 0x50, 0xd0, 0xe1, 0x34, 0x55, 0x01, 0x0e, 0x51, 0x5f, 0x03, 0xb4, 0xe4, 0xa7, 0xfa, 0x45, 0x42, 0xf5, + 0xf4, 0xf0, 0xe6, 0xec, 0xd3, 0xb5, 0xec, 0x90, 0x66, 0xab, 0x6d, 0xf4, 0xd3, 0xef, 0x3b, 0x87, 0xa5, 0xec, 0xa3, + 0x4a, 0xe8, 0xad, 0x8b, 0x25, 0x9e, 0x39, 0x13, 0x07, 0xcf, 0x7f, 0xe9, 0x70, 0xed, 0x9e, 0xd8, 0x72, 0xba, 0x3e, + 0xa4, 0x3d, 0x97, 0x69, 0xe4, 0x04, 0xa6, 0x34, 0x3d, 0x49, 0x64, 0x05, 0x63, 0x6a, 0x79, 0x20, 0xa3, 0xa5, 0x65, + 0x3c, 0x6f, 0x5d, 0x1a, 0x4c, 0x79, 0xfd, 0xd0, 0x54, 0x7b, 0x6e, 0x93, 0x6d, 0x1d, 0xb0, 0x5e, 0x8e, 0x53, 0xf3, + 0x1f, 0x2e, 0xa1, 0x46, 0x13, 0x0b, 0x65, 0xc4, 0xda, 0x61, 0x5e, 0x58, 0x25, 0xd4, 0xb4, 0xa5, 0x54, 0x59, 0x54, + 0x39, 0xfb, 0x5c, 0xde, 0xaf, 0x1e, 0xa1, 0x83, 0xc1, 0x84, 0x04, 0xab, 0x53, 0x7d, 0xf1, 0x34, 0x28, 0x7a, 0x25, + 0x9e, 0xdf, 0x94, 0x2e, 0x37, 0x24, 0xf5, 0xb2, 0x4a, 0xe4, 0x2f, 0x55, 0xea, 0x85, 0xf5, 0x84, 0x60, 0x5e, 0x34, + 0xd3, 0x47, 0x98, 0x5b, 0xa7, 0x91, 0xd3, 0x53, 0xa9, 0x7a, 0xa3, 0xcd, 0x02, 0x21, 0x80, 0xc7, 0xa6, 0xeb, 0x76, + 0x8a, 0xe1, 0xd7, 0xfe, 0xb0, 0x3e, 0x66, 0x15, 0x6c, 0xba, 0xf6, 0x14, 0xc2, 0xc0, 0x75, 0xbd, 0x87, 0x37, 0x65, + 0xd3, 0x59, 0xad, 0xc6, 0x89, 0x38, 0x51, 0x29, 0x76, 0x7d, 0x27, 0x26, 0x33, 0x7a, 0xcf, 0xd0, 0x1f, 0x68, 0x8e, + 0x29, 0x21, 0x01, 0x50, 0x93, 0x1e, 0x3e, 0xff, 0x2d, 0xdd, 0xe5, 0xb6, 0x28, 0x86, 0x8a, 0x0d, 0xc2, 0xea, 0x6b, + 0x1d, 0x37, 0xc3, 0xbf, 0xe0, 0x97, 0x0f, 0xc1, 0x27, 0x24, 0x80, 0x2a, 0x0a, 0xfc, 0x83, 0xc1, 0x04, 0xda, 0x25, + 0xa7, 0x64, 0xed, 0x41, 0x73, 0x2b, 0xb1, 0xe2, 0x31, 0x10, 0x43, 0x7c, 0xfa, 0x20, 0x14, 0x31, 0x76, 0x43, 0xbb, + 0x3c, 0xec, 0xf8, 0x8a, 0xe5, 0x52, 0x99, 0x8f, 0xd5, 0x62, 0x49, 0xfa, 0x51, 0xf8, 0x45, 0xb1, 0x13, 0x02, 0x39, + 0x41, 0x35, 0x47, 0x7f, 0xde, 0x12, 0xc4, 0x9c, 0x9a, 0x5d, 0x7b, 0x6a, 0x02, 0xae, 0xe7, 0x30, 0x85, 0x1f, 0x65, + 0x6e, 0x7d, 0x88, 0xa7, 0x28, 0x9d, 0x4b, 0xc0, 0x3b, 0xb9, 0x2f, 0x3c, 0xd8, 0xba, 0xd4, 0x9d, 0x00, 0x1f, 0x12, + 0x88, 0x5a, 0x99, 0x3c, 0x99, 0xf8, 0x68, 0x51, 0x30, 0xe7, 0x33, 0x86, 0x9f, 0x34, 0x49, 0x29, 0xdc, 0x21, 0x3a, + 0x9b, 0x15, 0x4a, 0x3a, 0xa6, 0xd8, 0x0c, 0x90, 0x41, 0x00, 0x04, 0x96, 0x55, 0xfe, 0x40, 0xec, 0x72, 0x15, 0x16, + 0x1a, 0xb1, 0x52, 0x14, 0x84, 0x54, 0xdb, 0x81, 0x69, 0xd7, 0x75, 0xab, 0xc0, 0xb7, 0x4e, 0x38, 0x0d, 0xd7, 0x58, + 0x9e, 0x94, 0x94, 0xcc, 0xb0, 0x32, 0x14, 0x70, 0x6e, 0x25, 0xb2, 0x99, 0xaf, 0x8e, 0x04, 0x4e, 0xfe, 0x15, 0x0c, + 0x72, 0x5f, 0xca, 0xae, 0x1c, 0x80, 0xf3, 0xa9, 0x25, 0x2e, 0xed, 0xeb, 0xb9, 0x70, 0xeb, 0x24, 0x55, 0x9d, 0xad, + 0xf6, 0x60, 0x31, 0x2e, 0xba, 0xb4, 0xdb, 0x92, 0x14, 0x14, 0xe8, 0xbe, 0x78, 0x3a, 0x4d, 0x52, 0x67, 0x3a, 0x49, + 0x79, 0x2c, 0x66, 0x30, 0xb2, 0x44, 0x4b, 0xd5, 0x09, 0xf7, 0x9a, 0x86, 0x9d, 0xe5, 0x7f, 0x0a, 0x8d, 0xd4, 0x64, + 0x33, 0x9d, 0x6e, 0xba, 0x7b, 0xdf, 0xa7, 0x60, 0x31, 0xc0, 0xcf, 0xa2, 0x8a, 0x7c, 0x3a, 0x2b, 0xbb, 0x41, 0x00, + 0x52, 0x04, 0x7a, 0x88, 0xc7, 0xd3, 0xb8, 0x2b, 0x19, 0xd3, 0x04, 0xe6, 0x5b, 0x04, 0xd0, 0xd4, 0x21, 0x51, 0xc0, + 0xc6, 0xbc, 0x0d, 0x35, 0xde, 0x17, 0xd7, 0x77, 0x1e, 0xf3, 0x52, 0x0c, 0x72, 0x40, 0x6e, 0xfb, 0xce, 0x15, 0x40, + 0x38, 0x83, 0x0b, 0xc4, 0x1e, 0xda, 0x09, 0x8c, 0x63, 0xf7, 0xf9, 0x91, 0x48, 0x15, 0x27, 0xcc, 0x77, 0x8a, 0xcc, + 0x1e, 0x9e, 0x1a, 0xef, 0xd1, 0x27, 0xe5, 0x34, 0x1a, 0x3f, 0x48, 0x98, 0xdf, 0xd8, 0x8c, 0x9e, 0xeb, 0xea, 0x69, + 0xce, 0x47, 0x41, 0x74, 0x58, 0xe4, 0xde, 0xff, 0xe9, 0x00, 0x39, 0x31, 0xbe, 0x6e, 0x99, 0x28, 0x39, 0x13, 0x52, + 0x87, 0x5a, 0xd6, 0xfb, 0xd4, 0x44, 0xa5, 0x06, 0x9d, 0xdc, 0xf2, 0x1d, 0x29, 0xa2, 0x2a, 0x8b, 0x1d, 0x5f, 0xeb, + 0x1e, 0x2a, 0xe9, 0xc6, 0x55, 0x5d, 0x74, 0x5a, 0x0d, 0x4d, 0x9e, 0x6a, 0xe9, 0x29, 0x84, 0x9f, 0xfb, 0xb4, 0xa6, + 0x2d, 0x60, 0x3d, 0xff, 0xa1, 0xd0, 0x6c, 0x7e, 0x88, 0xf0, 0x60, 0xf5, 0x19, 0x4d, 0x68, 0xe1, 0xc9, 0x40, 0x76, + 0x1d, 0x70, 0x6c, 0x46, 0xf2, 0xb2, 0x2f, 0x11, 0x74, 0x2d, 0xcc, 0x32, 0x56, 0x8f, 0xb8, 0x51, 0xf6, 0x72, 0xd2, + 0x1e, 0xe9, 0x3c, 0x43, 0x06, 0xed, 0x4f, 0x1d, 0xf7, 0xf0, 0x04, 0x4e, 0x24, 0xf3, 0x30, 0xc6, 0x16, 0x91, 0xf3, + 0x1e, 0xcf, 0x58, 0x07, 0xea, 0xd1, 0x72, 0x8b, 0x78, 0x60, 0xec, 0xd9, 0x2e, 0x82, 0xd2, 0xd0, 0x82, 0x1d, 0xf6, + 0x81, 0x43, 0x20, 0x92, 0x85, 0x6e, 0x2f, 0x59, 0xef, 0x89, 0x54, 0x90, 0x7c, 0xef, 0xa4, 0x8c, 0x0a, 0x70, 0x0d, + 0x2b, 0x1c, 0x31, 0xe6, 0x99, 0xe3, 0x64, 0x30, 0xeb, 0x1e, 0x0a, 0xa5, 0xa1, 0x73, 0xf0, 0xc9, 0x5e, 0x8b, 0x9f, + 0x3f, 0x38, 0x21, 0x87, 0x08, 0x36, 0xf6, 0x12, 0x5d, 0xaa, 0x52, 0x50, 0x29, 0xc3, 0x40, 0xf3, 0xbc, 0xb5, 0x30, + 0x29, 0x48, 0x85, 0x07, 0x98, 0xf1, 0xf1, 0xe8, 0x0f, 0x6d, 0xce, 0xd5, 0x33, 0x64, 0x0e, 0xec, 0xb0, 0x64, 0x1f, + 0xe3, 0x82, 0x22, 0x48, 0xd4, 0x10, 0x26, 0xfa, 0x24, 0x57, 0x0f, 0x8a, 0xf4, 0x09, 0x45, 0xaf, 0x89, 0xd3, 0xd3, + 0x81, 0x09, 0x74, 0xce, 0x93, 0x16, 0xa2, 0x1e, 0x14, 0x95, 0xf3, 0x83, 0xdc, 0xbd, 0x50, 0x19, 0x77, 0x70, 0x92, + 0x4b, 0x4a, 0xd7, 0x36, 0xf3, 0xfe, 0x46, 0xdb, 0xdb, 0xf3, 0x96, 0x54, 0x07, 0x9d, 0x24, 0x31, 0x87, 0x0a, 0xbc, + 0x42, 0x40, 0x42, 0xeb, 0xbb, 0x19, 0x1d, 0xdd, 0x83, 0xde, 0x84, 0xe9, 0x55, 0x45, 0x05, 0xc8, 0xbf, 0xf7, 0x2a, + 0x1a, 0x39, 0x47, 0xea, 0xea, 0xda, 0x91, 0xba, 0xb4, 0xbb, 0xfc, 0x49, 0xa1, 0x42, 0x3e, 0x10, 0x9a, 0x1f, 0x94, + 0x9d, 0x92, 0xbe, 0x26, 0xcc, 0x75, 0x35, 0xaf, 0x09, 0x36, 0xe0, 0xb3, 0x21, 0xc7, 0x91, 0xba, 0xf1, 0x83, 0x9a, + 0x01, 0xae, 0xdc, 0xa8, 0x87, 0x95, 0xdc, 0x77, 0x2e, 0x7e, 0xb1, 0x1f, 0x34, 0x33, 0x1f, 0xe3, 0x89, 0xae, 0x7a, + 0xdc, 0xcc, 0xd8, 0x83, 0xce, 0x0f, 0xa6, 0x4e, 0xd0, 0x6d, 0x93, 0x21, 0xc4, 0x3e, 0x4d, 0xf7, 0x90, 0xe7, 0xce, + 0x8f, 0x1e, 0x4c, 0xd0, 0xb9, 0x29, 0x08, 0xad, 0x9a, 0x14, 0xe8, 0xca, 0x2e, 0x79, 0x09, 0x3f, 0xbd, 0x7a, 0x45, + 0x97, 0x76, 0xd3, 0x5b, 0xf9, 0xe3, 0x26, 0x2c, 0x03, 0x7a, 0x17, 0xdf, 0x3b, 0xd4, 0xa7, 0x4c, 0xc7, 0x3d, 0xab, + 0xdd, 0x4b, 0x7e, 0xaa, 0x39, 0x8d, 0x9f, 0xb1, 0x5a, 0xa2, 0xf3, 0xc3, 0x79, 0x40, 0x70, 0x85, 0x10, 0x57, 0xfd, + 0xc0, 0x9b, 0xbd, 0x88, 0x52, 0xa6, 0x6a, 0x8b, 0xee, 0x4f, 0xfa, 0xc0, 0x2e, 0xe1, 0xf0, 0xb2, 0x6e, 0x8e, 0x13, + 0xf1, 0xdd, 0x58, 0x00, 0x26, 0x0c, 0xea, 0xea, 0xb7, 0x10, 0x30, 0x21, 0xba, 0xf3, 0xe4, 0x67, 0xfc, 0xbf, 0x21, + 0xe6, 0x3b, 0x45, 0xf8, 0xea, 0x78, 0xc1, 0xc9, 0xe9, 0xe4, 0x25, 0x2c, 0x81, 0x6f, 0x77, 0x18, 0x19, 0x22, 0x63, + 0x42, 0xa0, 0x19, 0xf3, 0x17, 0x69, 0x98, 0x4b, 0xe0, 0x2d, 0x0e, 0x81, 0xa3, 0xb8, 0x25, 0xfe, 0x64, 0x83, 0xbb, + 0xf7, 0xf9, 0xa6, 0x0f, 0xb1, 0xa6, 0xca, 0x2e, 0x41, 0xb9, 0xab, 0x78, 0xec, 0x66, 0x14, 0x68, 0x8c, 0xc2, 0x7e, + 0x83, 0x62, 0xa0, 0x45, 0xb7, 0x0e, 0x44, 0x14, 0xfa, 0x67, 0x55, 0xd1, 0xf9, 0x68, 0xa9, 0x88, 0x1d, 0xb2, 0x03, + 0x38, 0x01, 0xb2, 0x8b, 0x38, 0x19, 0x53, 0x97, 0x3b, 0x8a, 0x42, 0x03, 0x01, 0xce, 0xf0, 0x17, 0x3b, 0x9c, 0xf1, + 0x1f, 0xac, 0x03, 0x9b, 0x1c, 0x10, 0xd4, 0x06, 0xeb, 0x62, 0x8b, 0x53, 0x3c, 0x91, 0xfa, 0xc6, 0xec, 0xed, 0x79, + 0x3d, 0x1d, 0xf0, 0x1e, 0xdf, 0x55, 0xa9, 0x68, 0x21, 0x05, 0x5b, 0xf8, 0xb6, 0x1b, 0x32, 0x56, 0x0a, 0xab, 0xa0, + 0x77, 0xe7, 0x41, 0xd5, 0x9f, 0x4a, 0xa3, 0xfa, 0xbf, 0xba, 0x3b, 0xeb, 0xba, 0x05, 0x0f, 0xed, 0x92, 0xee, 0x82, + 0x2c, 0x59, 0xaa, 0x87, 0xad, 0xbe, 0xd9, 0x4d, 0x05, 0x05, 0xa9, 0x1d, 0x72, 0x7d, 0xeb, 0xff, 0xac, 0xc1, 0x81, + 0xac, 0xad, 0xda, 0x88, 0x03, 0xe1, 0x1d, 0x27, 0xc4, 0x57, 0x8f, 0xea, 0xae, 0x2e, 0x12, 0x54, 0x4d, 0xf9, 0xb8, + 0xc4, 0xfc, 0x32, 0x5e, 0xe5, 0x8d, 0x49, 0xaf, 0x2b, 0xbb, 0xef, 0x75, 0x39, 0x91, 0xb7, 0x93, 0xf9, 0x53, 0x10, + 0xdf, 0xd1, 0xcc, 0x00, 0x27, 0x27, 0xa5, 0x6c, 0x3d, 0xfb, 0x58, 0xdc, 0xe7, 0x38, 0x21, 0x92, 0x56, 0x19, 0x46, + 0x77, 0x7e, 0xe9, 0x0c, 0x6f, 0xdf, 0x80, 0xc2, 0xdb, 0x27, 0x4f, 0x80, 0x85, 0xd7, 0x94, 0x35, 0x8e, 0xb4, 0x28, + 0x24, 0x86, 0x61, 0x28, 0x05, 0xa2, 0x89, 0xd3, 0x6d, 0xa3, 0xbc, 0x09, 0xd0, 0x5b, 0xa1, 0x3f, 0x34, 0xf6, 0x88, + 0x9c, 0xb3, 0x7a, 0x79, 0x24, 0x97, 0xcc, 0x9f, 0xa8, 0x63, 0xfc, 0xc4, 0x0f, 0xfd, 0x93, 0x07, 0xf7, 0xba, 0x69, + 0x03, 0x38, 0xa4, 0x82, 0x9c, 0xc8, 0xf3, 0xb6, 0xbd, 0xaa, 0x8b, 0x26, 0x84, 0x3c, 0xe4, 0x56, 0x80, 0x87, 0x3c, + 0x3f, 0x9f, 0xeb, 0xa3, 0x10, 0x86, 0x43, 0x73, 0x05, 0x9c, 0x10, 0xd4, 0xc0, 0xbe, 0x81, 0x71, 0xe4, 0x46, 0x9e, + 0xdb, 0xd4, 0x17, 0x3d, 0x4e, 0xde, 0xed, 0x20, 0xa0, 0x0d, 0xfd, 0xf0, 0xbc, 0x3e, 0x75, 0xf5, 0xa3, 0xed, 0xf5, + 0x89, 0xdf, 0xc7, 0x68, 0x04, 0xe5, 0xcd, 0x5f, 0x61, 0x9f, 0x48, 0x5c, 0x81, 0x2d, 0xcd, 0x71, 0x36, 0x29, 0x9f, + 0xd5, 0x69, 0x53, 0xa1, 0x9e, 0x7c, 0x91, 0x63, 0x92, 0xdc, 0x57, 0x37, 0xd5, 0xc9, 0x42, 0x44, 0x1c, 0xf9, 0x9d, + 0x71, 0x87, 0xc1, 0xfc, 0x3c, 0xc9, 0xcd, 0x85, 0x2e, 0xb9, 0x3e, 0x4d, 0x2a, 0x68, 0xa0, 0xa2, 0x25, 0x79, 0x2f, + 0x3c, 0xe6, 0xad, 0xd0, 0xe4, 0x73, 0x61, 0x99, 0x2f, 0x85, 0xeb, 0x7c, 0x5d, 0x3f, 0x80, 0xef, 0x11, 0x37, 0xaa, + 0x56, 0x63, 0x3f, 0xf6, 0xe4, 0xbb, 0x96, 0x98, 0xf3, 0xaf, 0x34, 0xd6, 0xbc, 0x4d, 0x77, 0x89, 0x15, 0xcc, 0x68, + 0x36, 0x6d, 0x2c, 0x6e, 0x0c, 0x31, 0x15, 0xae, 0x49, 0xef, 0x70, 0x8d, 0xca, 0xf4, 0xec, 0x34, 0x22, 0x10, 0xbd, + 0x20, 0x6b, 0x0a, 0xb2, 0xb3, 0x95, 0x55, 0xb8, 0xb7, 0xd0, 0xb8, 0x58, 0xb8, 0x74, 0x7a, 0x1d, 0xbc, 0x42, 0xf5, + 0xfd, 0x76, 0x3d, 0x72, 0x89, 0xf2, 0xda, 0x94, 0xb4, 0xe1, 0x23, 0x27, 0x98, 0x63, 0xb1, 0x27, 0x28, 0xa1, 0xc8, + 0x50, 0xda, 0x12, 0xf0, 0x5c, 0x38, 0xe0, 0x1b, 0x31, 0x54, 0xeb, 0x7b, 0x5e, 0xa1, 0x27, 0x14, 0x39, 0x3e, 0x2a, + 0x77, 0x55, 0xc5, 0x49, 0x55, 0xba, 0xe6, 0x13, 0x5c, 0xbf, 0x1f, 0xbd, 0x8f, 0x88, 0x62, 0xed, 0x2b, 0xfb, 0xc2, + 0xbf, 0xb7, 0xc5, 0xea, 0xb2, 0x4f, 0x99, 0x80, 0x90, 0x5c, 0xde, 0xf2, 0x13, 0xc5, 0x1e, 0x39, 0x83, 0xef, 0x89, + 0xb0, 0x16, 0x93, 0x1c, 0xa4, 0xe3, 0x45, 0xc4, 0x0f, 0xa0, 0x03, 0x5b, 0xbe, 0x33, 0xcd, 0x29, 0xe2, 0x71, 0x25, + 0xbe, 0xef, 0x27, 0x83, 0x12, 0x2b, 0xb1, 0xca, 0xd9, 0x4f, 0xaa, 0x3a, 0x09, 0xe6, 0x7e, 0xf4, 0x1d, 0x8f, 0x1b, + 0xc1, 0xc1, 0xd4, 0xf1, 0x22, 0x64, 0x40, 0xe0, 0x17, 0xa0, 0x52, 0xe9, 0x01, 0xf1, 0x01, 0xa2, 0x6f, 0x40, 0x85, + 0x40, 0x78, 0x19, 0x94, 0xef, 0x51, 0x55, 0x9d, 0xda, 0x97, 0x73, 0x57, 0xde, 0x11, 0x94, 0x60, 0x1a, 0xde, 0xd1, + 0x48, 0x12, 0x94, 0x07, 0x1a, 0xed, 0x4e, 0x8e, 0xf8, 0xe0, 0x87, 0x37, 0x1d, 0x4d, 0x97, 0x2f, 0x31, 0x13, 0xed, + 0xd5, 0x9b, 0xf2, 0xe2, 0x5f, 0x83, 0x4c, 0x7c, 0xc9, 0x51, 0x20, 0x3e, 0xca, 0x93, 0xf5, 0xa6, 0xa4, 0x57, 0x17, + 0x4b, 0xbc, 0xff, 0x42, 0x39, 0xc2, 0xef, 0x16, 0x54, 0x0b, 0x30, 0xc7, 0xfe, 0xfc, 0xd0, 0xb6, 0x12, 0x3a, 0xc4, + 0x9a, 0xb7, 0xae, 0x04, 0xfe, 0x91, 0x9d, 0xb1, 0xbd, 0x0e, 0xc1, 0x7d, 0xdd, 0x9d, 0xcf, 0x0c, 0x33, 0xd9, 0xbc, + 0x52, 0x5c, 0x5e, 0x5a, 0x5e, 0x46, 0xe5, 0xb9, 0x27, 0xb9, 0xbe, 0x7e, 0x27, 0xf1, 0x9b, 0x4d, 0xed, 0xe2, 0xf2, + 0x5b, 0x4b, 0xdf, 0x98, 0x9a, 0x59, 0x26, 0xe0, 0x7e, 0xa7, 0xd7, 0x78, 0xa0, 0xd6, 0xed, 0x68, 0x6c, 0x33, 0x9b, + 0x13, 0xc6, 0x10, 0xe9, 0x6e, 0x3b, 0x53, 0x7b, 0xaa, 0xe0, 0xb7, 0x25, 0x45, 0xb2, 0x98, 0xd1, 0xd8, 0x22, 0x8e, + 0x54, 0x6f, 0xe5, 0x71, 0xcf, 0x7f, 0x67, 0xfa, 0x21, 0x43, 0xe3, 0x0c, 0x7f, 0xa0, 0x10, 0x01, 0x74, 0x23, 0x90, + 0xbb, 0xf0, 0xf5, 0x9e, 0x7f, 0x51, 0x21, 0x00, 0x40, 0x6d, 0x06, 0xa6, 0xbd, 0x18, 0xe7, 0x3a, 0x51, 0x1b, 0x72, + 0x8a, 0xee, 0xa6, 0xff, 0x1c, 0xbe, 0xd7, 0xdd, 0x89, 0x85, 0x56, 0x54, 0x7f, 0xf3, 0x43, 0x1b, 0xf0, 0x27, 0x75, + 0x9a, 0x62, 0x11, 0xba, 0xd8, 0xb8, 0xbc, 0x41, 0x9e, 0xa2, 0x35, 0x4a, 0x07, 0x55, 0x7e, 0x56, 0xd8, 0x1c, 0xbf, + 0xb7, 0x7f, 0xc6, 0x15, 0x78, 0x6b, 0x27, 0x55, 0xcf, 0x8d, 0xae, 0x0d, 0x00, 0x7d, 0x53, 0xdf, 0x0b, 0x4d, 0x66, + 0xde, 0xa8, 0xd2, 0xeb, 0xf7, 0x7b, 0xf2, 0x44, 0xfb, 0x10, 0x78, 0x02, 0x1a, 0x4e, 0x80, 0xd0, 0x95, 0x7c, 0x32, + 0x1f, 0x60, 0x03, 0x49, 0xa9, 0x38, 0xb0, 0xd3, 0x10, 0x7a, 0xa0, 0x63, 0x39, 0x61, 0x98, 0xc8, 0xe4, 0xc4, 0x71, + 0xc3, 0xff, 0x08, 0x2b, 0x42, 0x3f, 0xfa, 0x7f, 0xc6, 0x22, 0xae, 0x86, 0x73, 0x04, 0x31, 0x6a, 0xde, 0xc8, 0x02, + 0x14, 0xfc, 0xd7, 0xa9, 0xa7, 0x93, 0x13, 0xd9, 0x1c, 0xe7, 0x8c, 0x5a, 0xc6, 0x14, 0x21, 0xf2, 0x20, 0xc4, 0xf8, + 0x15, 0x9b, 0x58, 0x46, 0xd0, 0xf4, 0x43, 0x45, 0xef, 0x06, 0xb5, 0x95, 0x8c, 0xb8, 0x59, 0x3b, 0xb1, 0x03, 0xd7, + 0xde, 0x23, 0x01, 0x03, 0x79, 0xd3, 0x92, 0xed, 0x9b, 0xd2, 0xd5, 0xf8, 0xb0, 0x3f, 0x4e, 0xc6, 0xeb, 0x49, 0x16, + 0xf8, 0x27, 0xcd, 0x6e, 0x76, 0x86, 0xe4, 0x30, 0x49, 0xaa, 0x3c, 0x10, 0x09, 0xbc, 0xeb, 0x16, 0x43, 0x6a, 0x2c, + 0x6d, 0xb5, 0x4c, 0x14, 0xd6, 0x66, 0xc5, 0xc0, 0x91, 0x4d, 0x58, 0x17, 0x21, 0x06, 0x75, 0xb8, 0x2e, 0x4e, 0x01, + 0xd5, 0x09, 0xc2, 0x1c, 0x2a, 0xcc, 0x3a, 0x04, 0x9d, 0x32, 0x70, 0xd0, 0x31, 0xde, 0xd5, 0x83, 0xdf, 0x37, 0xce, + 0x88, 0x27, 0xc7, 0x4d, 0x83, 0xcb, 0xb9, 0xb1, 0x1c, 0x39, 0x37, 0xc2, 0xcb, 0xc0, 0xe9, 0x76, 0xbd, 0x21, 0xd5, + 0x36, 0x9c, 0x55, 0x45, 0x15, 0xad, 0xf2, 0x59, 0x75, 0x12, 0xd3, 0x56, 0xaf, 0xd9, 0x04, 0x51, 0x77, 0xe7, 0xb9, + 0x61, 0x2d, 0x83, 0x86, 0x11, 0x25, 0x21, 0x56, 0xef, 0x03, 0xfd, 0x89, 0x3d, 0xf8, 0xa2, 0x6a, 0x0f, 0x04, 0xba, + 0xd3, 0x60, 0x61, 0xc7, 0xcf, 0x00, 0x1c, 0x6e, 0xc6, 0x31, 0x8e, 0x41, 0xfb, 0xd2, 0x8a, 0x42, 0xaf, 0x96, 0x44, + 0xe0, 0x0c, 0xb3, 0xfc, 0x1f, 0xdf, 0xe2, 0xb5, 0xe8, 0xb5, 0xeb, 0xd0, 0xb9, 0xfa, 0x24, 0x36, 0x75, 0x6d, 0x9a, + 0xf8, 0xe8, 0xba, 0x81, 0x4b, 0x2f, 0xf0, 0x00, 0xee, 0x89, 0x17, 0x5d, 0x81, 0xc0, 0xf3, 0x4f, 0x26, 0x4a, 0xf7, + 0x70, 0x80, 0x39, 0x53, 0xdc, 0x18, 0x4e, 0xb9, 0x94, 0x1c, 0x43, 0xd3, 0xc2, 0x12, 0x18, 0x39, 0x40, 0x7f, 0x31, + 0xae, 0x30, 0x49, 0xba, 0xa4, 0x45, 0x47, 0xd1, 0x43, 0x2e, 0xc9, 0x3a, 0xa7, 0x5f, 0x64, 0x7e, 0xac, 0xae, 0xb1, + 0x51, 0x1c, 0x6b, 0x85, 0xcc, 0x3f, 0x44, 0x34, 0xea, 0x37, 0xe7, 0x05, 0x4c, 0xec, 0x8b, 0x83, 0x39, 0xbf, 0xf7, + 0xb7, 0xd6, 0xf2, 0xfa, 0xe3, 0xc9, 0xa6, 0xa7, 0x8c, 0x06, 0xc0, 0x18, 0x7e, 0xc2, 0xf1, 0x20, 0xa5, 0xd7, 0x57, + 0xa4, 0x82, 0xf7, 0x4d, 0xf1, 0x69, 0x5f, 0xc8, 0x4c, 0x4a, 0xf4, 0x8f, 0x41, 0x2c, 0x7d, 0x36, 0xad, 0x26, 0xd3, + 0x1f, 0xd0, 0xe6, 0x68, 0x0c, 0xe2, 0x51, 0x73, 0x78, 0x8b, 0x45, 0x75, 0xf5, 0x0c, 0x3f, 0xa1, 0xcc, 0x2d, 0x99, + 0x0f, 0xd9, 0x3e, 0x42, 0x5f, 0x8c, 0x25, 0x66, 0x1a, 0x9f, 0x27, 0x3f, 0x77, 0x91, 0x6b, 0xab, 0x37, 0x37, 0xf2, + 0xdf, 0xd4, 0x52, 0xa4, 0x36, 0xaa, 0x08, 0xfe, 0xfa, 0x13, 0xfa, 0x6a, 0x67, 0xde, 0xa4, 0x00, 0x9d, 0x2f, 0x09, + 0xfa, 0xd9, 0x80, 0x2a, 0x52, 0x04, 0x0d, 0xf8, 0xce, 0x16, 0xda, 0xa5, 0x32, 0x1d, 0x73, 0xfa, 0x5a, 0xde, 0xdf, + 0x84, 0x15, 0xdc, 0x1d, 0x6a, 0x1b, 0x92, 0xac, 0x46, 0x7e, 0x3d, 0xc6, 0x8a, 0xad, 0xef, 0x5d, 0x65, 0x38, 0xed, + 0xff, 0x18, 0x07, 0x01, 0xc8, 0x5b, 0xc5, 0xdd, 0x92, 0xd6, 0x69, 0xbd, 0x93, 0x74, 0xa5, 0x18, 0xd2, 0xca, 0xd5, + 0xfd, 0xee, 0xfb, 0xff, 0x30, 0x45, 0x63, 0x4a, 0x9f, 0xd8, 0x08, 0xed, 0x2a, 0x40, 0x92, 0x03, 0xa2, 0x87, 0x07, + 0x2d, 0x1d, 0x7f, 0x08, 0x45, 0x0b, 0x16, 0xbe, 0x05, 0x7d, 0xc3, 0x20, 0xda, 0x1e, 0xc1, 0x01, 0xbc, 0x0b, 0x97, + 0x7f, 0xf8, 0xa5, 0x71, 0x0d, 0x91, 0xdc, 0x7c, 0x4f, 0x6a, 0xea, 0xea, 0xcd, 0xbb, 0xe9, 0x5f, 0x42, 0xd6, 0x4d, + 0xfd, 0xe9, 0xaf, 0xd3, 0xb6, 0x2f, 0xbc, 0x9e, 0x14, 0x89, 0x66, 0x1c, 0x7f, 0x7b, 0x62, 0xe3, 0x8d, 0x31, 0xba, + 0x3e, 0x8a, 0x9e, 0x56, 0xcf, 0xde, 0x7a, 0xe9, 0x41, 0x2f, 0x4e, 0x08, 0x1e, 0xe3, 0x8f, 0x60, 0xc2, 0x6b, 0xfe, + 0x94, 0x50, 0xc7, 0xdf, 0x7a, 0x84, 0x7f, 0x36, 0x53, 0x18, 0x09, 0x15, 0x7e, 0xc7, 0x23, 0x8b, 0xca, 0xc5, 0xa5, + 0x24, 0x03, 0x42, 0x5c, 0x03, 0x60, 0x78, 0x2f, 0x9f, 0x02, 0x44, 0x62, 0xe3, 0xef, 0xe4, 0xde, 0x56, 0x78, 0x38, + 0xf7, 0xee, 0x50, 0x8e, 0xc5, 0xf2, 0x21, 0x65, 0xa6, 0x8f, 0xf8, 0x6d, 0xa4, 0x6e, 0x05, 0x75, 0x97, 0xe3, 0x97, + 0x0d, 0xc4, 0x7c, 0x00, 0xee, 0xef, 0xe1, 0xcd, 0x94, 0x57, 0x3f, 0x88, 0x6b, 0x00, 0xe4, 0xcf, 0x9d, 0x28, 0x99, + 0xd6, 0x1f, 0xed, 0x37, 0x74, 0x32, 0x10, 0x41, 0x82, 0x5a, 0x0b, 0x6a, 0x09, 0xb6, 0xc9, 0xee, 0x4d, 0x08, 0xbb, + 0xb5, 0xde, 0xcc, 0x77, 0xec, 0xc0, 0xce, 0x17, 0x7c, 0xc2, 0xf9, 0xb2, 0xf6, 0xa2, 0x9e, 0x1b, 0x19, 0xfe, 0x1d, + 0xf1, 0x0c, 0xfb, 0x05, 0xf3, 0xda, 0xb3, 0x9b, 0x9b, 0xf4, 0x3a, 0x5d, 0x0f, 0x4b, 0x5a, 0xa3, 0x7e, 0xc3, 0x8a, + 0x47, 0xb7, 0xd3, 0xa9, 0xd5, 0x6d, 0xb3, 0xaf, 0xd3, 0xef, 0x22, 0x96, 0x09, 0x34, 0x3f, 0xf1, 0xd6, 0x07, 0xa4, + 0xbe, 0xfd, 0x34, 0xb2, 0x9d, 0x5f, 0xfc, 0xf0, 0x0d, 0x86, 0xd3, 0x9f, 0x1c, 0xe1, 0xae, 0x0c, 0x7e, 0x66, 0x07, + 0xaa, 0x03, 0x25, 0x9f, 0xdd, 0x32, 0xc2, 0x60, 0x1c, 0x3e, 0xf0, 0x0c, 0x2b, 0xf8, 0x64, 0x7f, 0x15, 0xde, 0xc1, + 0xea, 0x1f, 0x5e, 0xf0, 0x5a, 0x5a, 0x23, 0xd5, 0x02, 0xdb, 0x85, 0x50, 0x42, 0xd9, 0x21, 0x35, 0x6e, 0xd4, 0xf6, + 0xef, 0x5c, 0x30, 0xd9, 0x22, 0xe1, 0xa6, 0x91, 0xe3, 0x57, 0x76, 0x9e, 0xb9, 0x72, 0x3c, 0xdf, 0x70, 0x33, 0xab, + 0xa0, 0x6f, 0x41, 0x19, 0x16, 0x56, 0x5f, 0x3a, 0xbe, 0x68, 0x88, 0xfe, 0x65, 0xf1, 0x0b, 0xc7, 0x51, 0xfe, 0x98, + 0xa3, 0x06, 0xee, 0xfc, 0x32, 0xaa, 0x88, 0x92, 0x3c, 0x66, 0x83, 0x03, 0xbd, 0xa3, 0xd1, 0x3c, 0xa1, 0x53, 0x2b, + 0x34, 0x80, 0x72, 0x0f, 0x1d, 0xfd, 0x80, 0xf5, 0xd4, 0x7e, 0xc3, 0x36, 0x1e, 0xe3, 0xf2, 0xaf, 0xe3, 0x4e, 0x46, + 0x9c, 0x92, 0x62, 0x7e, 0xcb, 0x33, 0x83, 0xf5, 0x82, 0x25, 0x5e, 0x25, 0x61, 0x07, 0xa4, 0xa8, 0xdf, 0xb1, 0xe7, + 0x7f, 0xe7, 0x7b, 0x1d, 0x60, 0xbe, 0x2d, 0xe8, 0xc9, 0xac, 0x01, 0xbf, 0xf5, 0x02, 0x6a, 0x2f, 0xe8, 0x2d, 0xa7, + 0xc5, 0x76, 0x55, 0x0d, 0x70, 0x02, 0x23, 0xa8, 0x99, 0x27, 0xf1, 0xe5, 0xde, 0xda, 0xff, 0x52, 0x71, 0x6a, 0xc0, + 0xc7, 0xc7, 0xeb, 0x07, 0xcc, 0x43, 0x87, 0x1c, 0xe5, 0x19, 0xef, 0x80, 0xcf, 0x1e, 0x1f, 0xf3, 0x1c, 0xb0, 0x63, + 0xf2, 0x7f, 0xe1, 0x61, 0xa9, 0xb3, 0xe7, 0x78, 0xf8, 0x12, 0x76, 0x8b, 0x93, 0x3d, 0xdc, 0x4d, 0xf2, 0x30, 0xde, + 0x24, 0xde, 0x06, 0x4f, 0x74, 0x63, 0xe0, 0x6a, 0xf0, 0xe3, 0x14, 0xeb, 0x3b, 0xde, 0xea, 0xe3, 0xf7, 0x7a, 0x7d, + 0x62, 0x5f, 0x35, 0x78, 0xbe, 0xff, 0x8d, 0x8f, 0xc6, 0x2d, 0xe3, 0x7f, 0xd5, 0x9a, 0xe7, 0x17, 0xa4, 0xaf, 0x63, + 0xf7, 0x74, 0x24, 0xdb, 0xea, 0xb1, 0x20, 0x67, 0x3a, 0x46, 0x47, 0x3a, 0x4e, 0xcb, 0x9f, 0xe2, 0xfa, 0x94, 0x9f, + 0x7c, 0xaf, 0xaf, 0x4f, 0x3c, 0xa9, 0xd4, 0xc6, 0xf3, 0x69, 0xb4, 0x01, 0x47, 0x0b, 0xe8, 0x4f, 0xab, 0x69, 0x6b, + 0x43, 0x12, 0x6f, 0x60, 0xb2, 0x4b, 0x71, 0x68, 0x56, 0xec, 0x96, 0xed, 0x4c, 0x3d, 0xd0, 0x9f, 0x77, 0xad, 0x07, + 0xe7, 0x85, 0xb9, 0xb1, 0x67, 0x05, 0x6e, 0x98, 0xac, 0xd4, 0x0e, 0xd2, 0x20, 0x1a, 0x11, 0x4b, 0x16, 0x88, 0x8e, + 0xfc, 0xda, 0x6b, 0x8f, 0x4d, 0xc5, 0xd9, 0xfd, 0x1a, 0x43, 0x97, 0x92, 0x01, 0x70, 0xb9, 0x2c, 0xec, 0xd4, 0xeb, + 0xed, 0x00, 0x0d, 0x02, 0x14, 0x07, 0x55, 0xce, 0x4c, 0xa0, 0x6c, 0x16, 0xf8, 0x1c, 0xe8, 0x55, 0x80, 0x3d, 0xe8, + 0xc2, 0xd1, 0xb9, 0x21, 0x5e, 0xe0, 0x9c, 0xd9, 0x2b, 0x03, 0x42, 0x89, 0x92, 0x5f, 0x34, 0xbc, 0x2d, 0xc6, 0x1c, + 0x7d, 0xd8, 0x08, 0x6b, 0x46, 0xa7, 0xaa, 0xe3, 0xda, 0x5b, 0xa5, 0xe3, 0xe6, 0xc1, 0xf1, 0x3d, 0x48, 0x90, 0x63, + 0x90, 0xc6, 0xfa, 0x3d, 0x7f, 0xb7, 0x3c, 0x95, 0x19, 0x58, 0x65, 0xc7, 0xfc, 0x7e, 0xc8, 0xad, 0x18, 0x79, 0x33, + 0x99, 0x28, 0x4b, 0x78, 0x90, 0x2b, 0xbc, 0xaf, 0xe2, 0x3f, 0x17, 0x91, 0xec, 0x24, 0x3f, 0xd2, 0x47, 0x42, 0xf5, + 0x8c, 0xf0, 0xcb, 0x27, 0xaa, 0xfe, 0x28, 0x66, 0xc3, 0x50, 0xec, 0xc6, 0x6a, 0x36, 0x0e, 0x73, 0x2e, 0xe7, 0x8d, + 0x36, 0xc4, 0x5b, 0x27, 0xb5, 0x89, 0xb4, 0xc1, 0x15, 0x7e, 0xb3, 0x00, 0x74, 0xc5, 0xf2, 0x40, 0x21, 0x90, 0x23, + 0xb4, 0xb7, 0x15, 0x2d, 0xf1, 0x29, 0x07, 0xbf, 0x60, 0x07, 0x3b, 0x84, 0x66, 0xbf, 0xcc, 0x43, 0x6b, 0x34, 0x6d, + 0x64, 0xd2, 0x61, 0xe7, 0x12, 0xc8, 0xd4, 0x02, 0x23, 0xd4, 0x38, 0xcb, 0xa1, 0xb0, 0x2a, 0xb8, 0x6f, 0xb4, 0x72, + 0x2e, 0x5c, 0xb7, 0x94, 0x4f, 0x86, 0x05, 0x3e, 0xc1, 0x16, 0x3e, 0x63, 0xc2, 0xee, 0x0b, 0xba, 0x39, 0x24, 0x52, + 0x48, 0x15, 0x25, 0x8d, 0xc9, 0xa0, 0x42, 0xe9, 0xb8, 0x8a, 0x5a, 0xa7, 0x81, 0xee, 0x31, 0x21, 0xa6, 0xa7, 0x20, + 0x16, 0x47, 0x6e, 0x5f, 0xfd, 0x11, 0xcf, 0xcf, 0x9b, 0x1f, 0xfb, 0x18, 0x27, 0x1a, 0x8b, 0xc7, 0x91, 0x3a, 0x3f, + 0x42, 0x65, 0xb8, 0xbc, 0x39, 0xed, 0x2e, 0xec, 0x35, 0x75, 0xd9, 0x29, 0x92, 0x12, 0x21, 0xa6, 0xb2, 0x5c, 0xe0, + 0x70, 0xdf, 0xeb, 0x9a, 0x54, 0xec, 0x08, 0xbc, 0x2e, 0xc4, 0x2f, 0x85, 0x7b, 0x6b, 0xf8, 0xbd, 0x62, 0xb7, 0x5a, + 0x3b, 0xdf, 0xb6, 0xb9, 0x33, 0x8f, 0xfc, 0xc0, 0xe1, 0xcc, 0xc9, 0x4c, 0xf4, 0x8b, 0xb0, 0xc4, 0xba, 0x23, 0xc7, + 0xd2, 0x90, 0xe0, 0xc4, 0x33, 0x54, 0xd9, 0x54, 0x43, 0xf7, 0x3b, 0x2f, 0x14, 0x71, 0x53, 0x72, 0xb4, 0x9b, 0x80, + 0x5c, 0xae, 0xe9, 0x52, 0xcb, 0xa8, 0x1c, 0x92, 0x84, 0xe7, 0x39, 0x90, 0xe7, 0x84, 0x62, 0xf5, 0xb3, 0xac, 0x33, + 0xe2, 0xbc, 0x81, 0x52, 0x3e, 0x12, 0x49, 0x78, 0xa6, 0xa6, 0xe7, 0x66, 0xe2, 0x4f, 0xd4, 0x5f, 0x89, 0xb3, 0x37, + 0x19, 0x1e, 0x8e, 0xe3, 0x0a, 0xc3, 0x35, 0xfc, 0x87, 0xd0, 0xa3, 0x07, 0xfe, 0xb9, 0x19, 0xc3, 0x20, 0x24, 0x99, + 0x51, 0x28, 0xc2, 0xa4, 0xf4, 0xea, 0xba, 0x6b, 0x1a, 0xe3, 0x44, 0xc7, 0xbd, 0x07, 0x9f, 0xab, 0x77, 0x13, 0xa4, + 0x84, 0xc4, 0x31, 0xa5, 0x0c, 0xca, 0xb5, 0xa8, 0xf0, 0xe0, 0xa9, 0xf6, 0xf5, 0x8f, 0x99, 0x5b, 0x51, 0x74, 0xf9, + 0x0a, 0xd9, 0x48, 0x00, 0x46, 0x4f, 0x06, 0x58, 0x0f, 0xcb, 0x0c, 0x76, 0x22, 0x21, 0xbe, 0x0a, 0x87, 0x2c, 0xad, + 0x3a, 0xca, 0x00, 0xb0, 0xd9, 0x6d, 0x04, 0xa3, 0x0f, 0x58, 0x75, 0x86, 0x5a, 0xd1, 0xdf, 0xb2, 0xa8, 0x5a, 0x69, + 0xdd, 0x48, 0x79, 0x35, 0x8d, 0x3e, 0xd1, 0x91, 0x0b, 0x3e, 0x97, 0x75, 0xbb, 0x20, 0x29, 0x49, 0x8c, 0x36, 0xb4, + 0xd0, 0x6f, 0x6b, 0x48, 0x57, 0xff, 0xf9, 0xe9, 0x7e, 0x28, 0xa2, 0x28, 0xad, 0x8b, 0x41, 0x72, 0x14, 0x94, 0xfe, + 0x87, 0x50, 0x07, 0x70, 0x36, 0x2d, 0xea, 0x27, 0x51, 0xc7, 0xed, 0x06, 0x1a, 0xf1, 0xe5, 0x07, 0xd8, 0xd9, 0x3a, + 0xba, 0xdb, 0xd6, 0xba, 0xd3, 0x24, 0x9a, 0x5c, 0x34, 0xa3, 0xca, 0x59, 0x23, 0xc7, 0x87, 0x41, 0x76, 0x16, 0xb9, + 0x4c, 0x46, 0x38, 0x77, 0x7b, 0x5d, 0xb0, 0x61, 0x12, 0x65, 0xc5, 0xff, 0x7c, 0x15, 0xa2, 0xbb, 0x94, 0x8b, 0x7e, + 0x00, 0x5b, 0xf2, 0xb2, 0xe3, 0x64, 0xd5, 0x20, 0x20, 0x5a, 0x09, 0x58, 0xce, 0xfc, 0xa2, 0x30, 0x8d, 0xd3, 0x77, + 0x5d, 0xba, 0x98, 0xc6, 0x90, 0xb5, 0x6e, 0x3e, 0xf0, 0x6f, 0x54, 0xb9, 0xc7, 0xb5, 0x26, 0xb8, 0x25, 0xa4, 0x77, + 0xe1, 0x0e, 0xf0, 0x6a, 0x53, 0xc7, 0x6e, 0xd7, 0x21, 0x10, 0x12, 0x08, 0x95, 0x2e, 0x24, 0xa8, 0x42, 0xdd, 0xce, + 0x84, 0x35, 0xd5, 0x23, 0xbc, 0x70, 0x62, 0xec, 0x2f, 0x57, 0x25, 0x37, 0x02, 0x07, 0x50, 0x34, 0x9b, 0x2f, 0x84, + 0xcd, 0xe4, 0xa8, 0x57, 0x8d, 0x6a, 0x47, 0xf0, 0x15, 0x3b, 0x1e, 0xfc, 0xd9, 0x67, 0x12, 0x31, 0x66, 0xe8, 0xc2, + 0x86, 0xdc, 0xf2, 0x33, 0x5d, 0x30, 0x6f, 0x0e, 0xda, 0xe9, 0x69, 0xed, 0xa3, 0xa0, 0x42, 0x75, 0x7e, 0xaa, 0x17, + 0x66, 0x12, 0xf2, 0x1c, 0x8b, 0x17, 0x83, 0xe6, 0xb9, 0xb1, 0x7e, 0x1f, 0x1d, 0xf2, 0xff, 0xd7, 0x0a, 0x18, 0x39, + 0xbb, 0x95, 0xee, 0x99, 0x52, 0xa6, 0xe4, 0xbb, 0xc5, 0xfc, 0xca, 0xc4, 0x70, 0xb5, 0x9c, 0x1a, 0xc1, 0x71, 0x9c, + 0xe6, 0xf1, 0x11, 0x26, 0x83, 0xa8, 0xbe, 0xc6, 0x56, 0x7c, 0xe8, 0xca, 0x90, 0x85, 0x7b, 0xbf, 0x4a, 0x54, 0x7a, + 0x87, 0xa3, 0xa7, 0xda, 0x9a, 0x51, 0xb5, 0x04, 0xea, 0xeb, 0x46, 0xad, 0xa8, 0xd5, 0x82, 0x72, 0x2a, 0x98, 0x57, + 0x98, 0xf2, 0xc4, 0x56, 0xe7, 0xff, 0x2d, 0x2b, 0xe1, 0xcf, 0x0d, 0xff, 0x8b, 0xbf, 0x10, 0x4e, 0x58, 0xb1, 0xa4, + 0xc2, 0x8f, 0x57, 0x07, 0x03, 0xb0, 0xf0, 0xdf, 0x87, 0xdd, 0xe8, 0x6f, 0x63, 0xb9, 0x80, 0xd4, 0xfd, 0xe8, 0x29, + 0x96, 0x4e, 0x11, 0x42, 0x2c, 0xe5, 0x45, 0xcf, 0x54, 0x52, 0x8b, 0x33, 0x2f, 0x1a, 0x00, 0x98, 0xf7, 0x60, 0xcd, + 0x7d, 0x71, 0x9c, 0x24, 0x41, 0xcd, 0x2a, 0xa0, 0x9a, 0x72, 0x3d, 0x27, 0xcc, 0xaf, 0x38, 0xf5, 0xa7, 0xac, 0xe9, + 0x99, 0x53, 0x50, 0xb7, 0xe7, 0x27, 0x69, 0x8c, 0x82, 0x66, 0xac, 0x18, 0xa7, 0xb2, 0x9d, 0xa4, 0xbf, 0x58, 0xbb, + 0xdc, 0xdd, 0x25, 0xca, 0xa4, 0xcb, 0xb3, 0x36, 0xe3, 0xbf, 0x92, 0x4a, 0x69, 0xc5, 0xee, 0xd4, 0xa9, 0xd1, 0x71, + 0x6e, 0x09, 0x6a, 0x34, 0x84, 0xe0, 0xcb, 0x40, 0x7a, 0xc8, 0x79, 0x59, 0x3a, 0xca, 0x73, 0xe0, 0x3c, 0x94, 0xed, + 0xc9, 0x83, 0x19, 0x68, 0x8f, 0xfe, 0x36, 0x8c, 0xa6, 0x96, 0xcc, 0xdf, 0xb9, 0x6a, 0xc3, 0x0e, 0xd1, 0xd0, 0x22, + 0x98, 0xae, 0x36, 0xc7, 0xed, 0x80, 0xf7, 0x72, 0x29, 0xb9, 0x3a, 0xd7, 0xae, 0xcf, 0x92, 0xe7, 0x67, 0xef, 0xc3, + 0x56, 0xd2, 0x6d, 0xfa, 0x4f, 0xde, 0x4e, 0x6d, 0x72, 0x7d, 0x9b, 0x56, 0xba, 0x2c, 0x9b, 0x20, 0x4a, 0x33, 0x34, + 0x71, 0xfe, 0x30, 0xdf, 0x4e, 0xfd, 0x13, 0xc1, 0x72, 0xc6, 0xa6, 0xec, 0xc7, 0xf9, 0xaa, 0x14, 0x66, 0xaa, 0x90, + 0x40, 0xda, 0x14, 0x7d, 0x49, 0x8d, 0x0b, 0x73, 0x3a, 0xbc, 0xa7, 0x93, 0x5c, 0x40, 0xfa, 0x34, 0x42, 0xe8, 0x63, + 0x27, 0x34, 0xe7, 0x68, 0xe4, 0xcd, 0x7f, 0x32, 0xf3, 0x5d, 0xf8, 0x41, 0x34, 0x68, 0xf8, 0x1d, 0x6f, 0x86, 0xda, + 0x76, 0xfa, 0x6a, 0x6f, 0xd3, 0x3c, 0x04, 0xb5, 0x6f, 0x34, 0x09, 0x1a, 0xf8, 0x7a, 0xf6, 0x03, 0x3e, 0xd9, 0x6c, + 0xaa, 0xa9, 0xf6, 0xc3, 0xaf, 0x26, 0xec, 0x90, 0x2a, 0xcb, 0xd0, 0x0c, 0x12, 0x06, 0xed, 0x0a, 0xdf, 0xd3, 0x25, + 0x4c, 0x02}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 3a8d466208..7bf86f6e8b 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,7575 +10,7608 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xcc, 0x7d, 0xf9, 0x7f, 0xdb, 0xb6, 0xf2, 0xe0, 0xcf, - 0xbb, 0x7f, 0x85, 0xcd, 0x6f, 0xe2, 0x92, 0x16, 0x44, 0x4b, 0xf2, 0x11, 0x87, 0x32, 0xad, 0xcd, 0xd9, 0xa4, 0xcd, - 0xd5, 0x38, 0x49, 0x0f, 0x57, 0xcf, 0xa1, 0x28, 0x48, 0x62, 0x42, 0x91, 0x2a, 0x49, 0xc5, 0x56, 0x65, 0xfd, 0xef, - 0x3b, 0x33, 0x38, 0x29, 0xc9, 0x79, 0x7d, 0x7b, 0x7d, 0xf6, 0xe5, 0xd5, 0x22, 0x01, 0x10, 0xc7, 0x60, 0x30, 0x17, - 0x06, 0x83, 0xb3, 0xdd, 0x61, 0x1e, 0x57, 0x8b, 0x19, 0xdf, 0x99, 0x54, 0xd3, 0xf4, 0xfc, 0x4c, 0xfe, 0xe5, 0xd1, - 0xf0, 0xfc, 0x2c, 0x4d, 0xb2, 0xaf, 0x3b, 0x05, 0x4f, 0xc3, 0x24, 0xce, 0xb3, 0x9d, 0x49, 0xc1, 0x47, 0xe1, 0x30, - 0xaa, 0xa2, 0x20, 0x99, 0x46, 0x63, 0xbe, 0x73, 0x70, 0x7e, 0x36, 0xe5, 0x55, 0xb4, 0x13, 0x4f, 0xa2, 0xa2, 0xe4, - 0x55, 0xf8, 0xf1, 0xc3, 0xf3, 0xe6, 0xe9, 0xf9, 0x59, 0x19, 0x17, 0xc9, 0xac, 0xda, 0xc1, 0x2a, 0xc3, 0x69, 0x3e, - 0x9c, 0xa7, 0xfc, 0xfc, 0xe0, 0xe0, 0xfa, 0xfa, 0xda, 0xff, 0x52, 0xfe, 0xf7, 0x6f, 0x51, 0xb1, 0xf3, 0x63, 0x11, - 0xbe, 0x1d, 0x7c, 0xe1, 0x71, 0xe5, 0x0f, 0xf9, 0x28, 0xc9, 0xf8, 0xbb, 0x22, 0x9f, 0xf1, 0xa2, 0x5a, 0x74, 0x31, - 0xf3, 0x97, 0x22, 0x74, 0x13, 0x56, 0x31, 0xee, 0x85, 0xe7, 0xd5, 0x4e, 0x92, 0xed, 0x24, 0xbd, 0x1f, 0x0b, 0x4a, - 0x59, 0xf2, 0x6c, 0x3e, 0xe5, 0x45, 0x34, 0x48, 0x79, 0xb0, 0xdb, 0x62, 0xd0, 0xa1, 0x51, 0x32, 0x9e, 0xeb, 0xf7, - 0xeb, 0x22, 0xa9, 0xd4, 0xf3, 0xb7, 0x28, 0x9d, 0xf3, 0x80, 0xaf, 0xbc, 0x20, 0xb9, 0xac, 0xfa, 0x21, 0xa7, 0x9a, - 0xbf, 0x9a, 0x8a, 0xdd, 0x5f, 0xa8, 0x4a, 0xe8, 0x60, 0x3e, 0xda, 0xa9, 0x76, 0x43, 0xa7, 0x5c, 0x4c, 0x07, 0x79, - 0xea, 0xf4, 0xaa, 0x86, 0xe3, 0x04, 0x58, 0x06, 0xfe, 0xdf, 0x85, 0x16, 0xca, 0x6a, 0x27, 0x4b, 0xc2, 0xeb, 0x24, - 0x1b, 0xe6, 0xd7, 0xec, 0x3a, 0x0b, 0xb3, 0xc4, 0xbf, 0x98, 0x44, 0xf0, 0xf2, 0x3e, 0xcf, 0xab, 0xbd, 0x3d, 0x57, - 0xbe, 0x2f, 0x9e, 0x5c, 0x5c, 0x84, 0x61, 0xf8, 0x2d, 0x4f, 0x86, 0x3b, 0xad, 0xdb, 0x5b, 0x2b, 0xd5, 0xcf, 0xa2, - 0x2a, 0xf9, 0xc6, 0xc5, 0x47, 0xde, 0xde, 0x9e, 0x03, 0xbf, 0xb3, 0x8a, 0x0f, 0x2f, 0xaa, 0x45, 0x0a, 0xa9, 0x9c, - 0x57, 0xa5, 0x03, 0x83, 0x7c, 0x9a, 0xc7, 0x30, 0xb6, 0xac, 0xf2, 0x67, 0x45, 0x5e, 0xe5, 0xd8, 0x31, 0x28, 0x5a, - 0xf0, 0x59, 0x1a, 0xc5, 0x1c, 0xf3, 0xa1, 0x26, 0xf3, 0x85, 0x29, 0xc4, 0xbe, 0x66, 0xe1, 0x05, 0x75, 0xdd, 0xf5, - 0xd8, 0xaf, 0xd0, 0x3d, 0x7e, 0xbd, 0xf3, 0x2b, 0x8f, 0xbe, 0xbe, 0x8e, 0x66, 0xdd, 0x38, 0x8d, 0xca, 0x72, 0xe7, - 0x4d, 0xbe, 0xa4, 0x61, 0x14, 0xf3, 0xb8, 0xca, 0x0b, 0x17, 0x86, 0xc6, 0x32, 0x6f, 0x99, 0x8c, 0xdc, 0x6a, 0x92, - 0x94, 0xfe, 0xd5, 0xbd, 0xb8, 0x2c, 0xdf, 0xf3, 0x72, 0x9e, 0x56, 0xf7, 0x42, 0x80, 0x5b, 0xb6, 0x1b, 0x86, 0x5f, - 0x33, 0xaf, 0x9a, 0x14, 0xf9, 0xf5, 0xce, 0xb3, 0xa2, 0x80, 0x2f, 0x1c, 0x68, 0x5a, 0x94, 0xd8, 0x49, 0xca, 0x9d, - 0x2c, 0xaf, 0x76, 0x74, 0x7d, 0x08, 0x6d, 0x7f, 0xe7, 0x63, 0xc9, 0x77, 0x3e, 0xcf, 0xb3, 0x32, 0x1a, 0x71, 0x28, - 0xfa, 0x79, 0x27, 0x2f, 0x76, 0x3e, 0x43, 0xad, 0x9f, 0x61, 0xee, 0xca, 0x0a, 0x90, 0xc8, 0x77, 0xbc, 0x2e, 0x35, - 0x06, 0x89, 0x1f, 0xf8, 0x4d, 0x15, 0x56, 0x8c, 0x5e, 0xab, 0x90, 0xaf, 0xc6, 0xbc, 0xda, 0x29, 0xf5, 0xb8, 0x5c, - 0x6f, 0x99, 0x42, 0x02, 0x94, 0xc0, 0xfc, 0x5c, 0xc2, 0x9f, 0x8b, 0xd7, 0xaa, 0x0b, 0x9d, 0xbe, 0xce, 0xf6, 0xf6, - 0x2a, 0x0d, 0x68, 0x6f, 0x29, 0x67, 0x28, 0xe4, 0xbb, 0x2a, 0x6d, 0x6f, 0x8f, 0xfb, 0x29, 0xcf, 0xc6, 0xd5, 0x04, - 0x8a, 0xb5, 0xbb, 0x50, 0xde, 0xad, 0xc2, 0x5f, 0x33, 0x1f, 0x5a, 0x72, 0xb9, 0xe7, 0x31, 0xf3, 0x35, 0xe4, 0x08, - 0x20, 0xe4, 0x61, 0x45, 0x80, 0xab, 0xc1, 0xd8, 0xf3, 0x25, 0xf4, 0x2f, 0x16, 0x59, 0xec, 0xda, 0xfd, 0xf7, 0x18, - 0x54, 0x0a, 0x35, 0x96, 0x58, 0x23, 0xab, 0x3c, 0x6f, 0x55, 0xf0, 0x6a, 0x5e, 0x64, 0x3b, 0xd5, 0xaa, 0xca, 0x2f, - 0xaa, 0x22, 0xc9, 0xc6, 0x30, 0x10, 0x95, 0x66, 0x7d, 0xb8, 0x5a, 0x89, 0xee, 0xfe, 0x51, 0x84, 0x49, 0x78, 0x8e, - 0x2d, 0xbe, 0xc9, 0x5d, 0x89, 0x83, 0x49, 0x08, 0x38, 0x48, 0xdf, 0x3a, 0xbd, 0x24, 0x48, 0x00, 0x0b, 0x99, 0xe8, - 0x25, 0xcc, 0x30, 0x34, 0x58, 0x21, 0xea, 0xfa, 0xbe, 0x5f, 0x01, 0xee, 0x2e, 0x15, 0x58, 0x12, 0x6b, 0xa0, 0xbd, - 0xe4, 0xb2, 0xd5, 0x0f, 0x2a, 0xe8, 0xf4, 0x70, 0x1e, 0x73, 0xd7, 0xcd, 0x58, 0xc9, 0x72, 0x28, 0x9c, 0x35, 0xdc, - 0x02, 0x3e, 0x01, 0xd0, 0x15, 0xf5, 0xc9, 0x0e, 0x61, 0xba, 0x3d, 0xd9, 0xc9, 0x42, 0xf5, 0x10, 0x41, 0x2c, 0x3b, - 0x54, 0x40, 0x87, 0x60, 0xb9, 0x0d, 0x78, 0xe1, 0xe8, 0x62, 0xdd, 0x1a, 0x5e, 0xcc, 0x61, 0xde, 0xe1, 0xbb, 0x9d, - 0xd1, 0x3c, 0x8b, 0xab, 0x04, 0xa8, 0x83, 0xd3, 0x28, 0x1a, 0x8e, 0xc0, 0x07, 0x8d, 0x0e, 0x8e, 0xb7, 0xf2, 0xdc, - 0xd2, 0x6b, 0x24, 0x97, 0x79, 0xa3, 0xdd, 0x67, 0xd8, 0x4b, 0xaf, 0x2b, 0xeb, 0x93, 0x10, 0xe0, 0x2c, 0xc1, 0x41, - 0xae, 0xd8, 0x4f, 0x62, 0xe5, 0xe3, 0x10, 0xaf, 0xb3, 0x5e, 0xe2, 0x6f, 0xae, 0x94, 0xb0, 0xf2, 0xa7, 0xd1, 0xcc, - 0xe5, 0xe1, 0x39, 0x27, 0xec, 0x8a, 0xb2, 0x18, 0xfb, 0x5a, 0x9b, 0xb8, 0x1e, 0xac, 0x7b, 0xdf, 0xe0, 0x94, 0x07, - 0x40, 0x19, 0xe5, 0xc5, 0xb3, 0x28, 0x9e, 0xe0, 0x77, 0x1a, 0x63, 0x86, 0x6a, 0xc1, 0xc5, 0x05, 0x8f, 0x2a, 0xfe, - 0x2c, 0xe5, 0xf8, 0xe6, 0x3a, 0xf4, 0xa5, 0xe3, 0xb1, 0x12, 0x97, 0x7a, 0x9a, 0x54, 0x6f, 0x72, 0x68, 0xa3, 0x5b, - 0x5a, 0xf8, 0x45, 0x33, 0xff, 0xa8, 0x82, 0xc9, 0x1a, 0xcc, 0x2b, 0xee, 0x3a, 0x19, 0x96, 0x70, 0x58, 0x09, 0xd3, - 0xe4, 0x57, 0x00, 0xc4, 0x27, 0x79, 0x56, 0x41, 0x55, 0x21, 0x57, 0x50, 0x65, 0x30, 0x94, 0xd9, 0x8c, 0x67, 0xc3, - 0x27, 0x93, 0x24, 0x1d, 0xba, 0x30, 0x54, 0x18, 0xec, 0xef, 0x59, 0x88, 0x83, 0x0c, 0xcf, 0x61, 0xb6, 0xe1, 0xcf, - 0xdd, 0xc3, 0x01, 0xf4, 0x3d, 0xa7, 0x65, 0xc1, 0x43, 0xc7, 0xe9, 0xc2, 0x50, 0x5c, 0x39, 0x84, 0x1d, 0x24, 0x5d, - 0xd8, 0xc6, 0x7b, 0x20, 0xb0, 0xa5, 0xc7, 0x1b, 0x61, 0xa6, 0xe7, 0x51, 0x42, 0xf8, 0x8f, 0x02, 0x70, 0x1e, 0x26, - 0x20, 0x01, 0x3a, 0x48, 0x24, 0xf0, 0x55, 0x22, 0x17, 0xd5, 0x50, 0x13, 0xb5, 0xbf, 0x00, 0x16, 0x89, 0x0f, 0xeb, - 0x19, 0x16, 0xeb, 0xf0, 0x03, 0x4c, 0x7e, 0xc9, 0xaa, 0x28, 0xfc, 0x2b, 0xeb, 0xfd, 0x95, 0xf9, 0x7c, 0x3a, 0xab, - 0x16, 0x17, 0x44, 0xcd, 0x03, 0xc0, 0xc8, 0xdf, 0xa8, 0x28, 0xc0, 0x2b, 0x46, 0x92, 0x26, 0x41, 0xf6, 0x2e, 0x4f, - 0x17, 0xa3, 0x24, 0x4d, 0x2f, 0xe6, 0xb3, 0x59, 0x5e, 0xc0, 0xda, 0xce, 0xc2, 0x65, 0x95, 0x1b, 0xf8, 0xe0, 0x8c, - 0x2e, 0xcb, 0xeb, 0xa4, 0x82, 0x09, 0x80, 0xa7, 0x38, 0x02, 0xf4, 0x78, 0x9c, 0xe7, 0x29, 0x8f, 0x32, 0x18, 0x79, - 0xd2, 0x03, 0x66, 0x92, 0xcd, 0xd3, 0xb4, 0x3b, 0x80, 0x7a, 0xbf, 0x76, 0x29, 0x5b, 0x30, 0x87, 0x80, 0x9e, 0x1f, - 0x15, 0x45, 0xb4, 0xc0, 0x82, 0x61, 0x88, 0xc5, 0x60, 0x71, 0xfc, 0x74, 0xf1, 0xf6, 0x8d, 0x2f, 0xd6, 0x4a, 0x32, - 0x5a, 0xc0, 0xd8, 0xd4, 0xfa, 0x4b, 0x56, 0x6c, 0x54, 0xe4, 0xd3, 0xb5, 0xa6, 0x05, 0xe8, 0x92, 0xee, 0x1d, 0x5d, - 0x80, 0xac, 0x5d, 0x51, 0xb5, 0xdd, 0x83, 0x37, 0x84, 0xf9, 0x98, 0x19, 0xca, 0x76, 0xf1, 0x4f, 0x20, 0x92, 0xa1, - 0xc9, 0xef, 0xf7, 0xb6, 0x2a, 0x16, 0x4b, 0x1e, 0x52, 0x3f, 0x67, 0xc8, 0x18, 0xb1, 0x8f, 0x71, 0x04, 0xad, 0x43, - 0x2a, 0xd6, 0xb3, 0x52, 0x3d, 0xe6, 0xab, 0x15, 0xfb, 0x3b, 0x57, 0x58, 0x0f, 0x7c, 0x28, 0x4c, 0x88, 0x5e, 0x85, - 0xd5, 0xed, 0x2d, 0xb4, 0x9c, 0x78, 0xec, 0x7d, 0x12, 0x2e, 0x23, 0x35, 0x20, 0xe4, 0x6c, 0xb8, 0x3c, 0x03, 0x41, - 0x65, 0x90, 0x03, 0x7e, 0x03, 0xbe, 0x09, 0x1d, 0xad, 0x32, 0x06, 0xac, 0x39, 0xc5, 0x7e, 0xec, 0xb6, 0xd9, 0x24, - 0x2a, 0x9f, 0x4c, 0xa2, 0x6c, 0xcc, 0x87, 0xc1, 0xdf, 0xf9, 0x8a, 0xf1, 0x2c, 0x74, 0x80, 0xcd, 0x46, 0x69, 0xf2, - 0x37, 0x1f, 0x3a, 0x92, 0x2f, 0x7c, 0x02, 0xa8, 0xdc, 0x00, 0x9e, 0x0e, 0xcb, 0x9d, 0x17, 0x1f, 0x5e, 0xbf, 0x92, - 0x93, 0x59, 0xe3, 0x15, 0x30, 0x6d, 0x73, 0xe0, 0xcb, 0xc0, 0x59, 0x24, 0xaf, 0x78, 0x96, 0x10, 0x9d, 0x04, 0xe6, - 0x22, 0x52, 0x92, 0xf2, 0xe3, 0x0c, 0xa4, 0x01, 0xfe, 0x0e, 0xaa, 0x81, 0xfe, 0x84, 0xd0, 0x34, 0xa5, 0x43, 0xfb, - 0x22, 0x63, 0xa8, 0x93, 0xe0, 0xe3, 0x94, 0xc6, 0xae, 0x5f, 0xe7, 0xae, 0xb7, 0x02, 0x94, 0xaf, 0x92, 0x78, 0x27, - 0x1a, 0x0e, 0x5f, 0x66, 0x49, 0x95, 0x50, 0x0f, 0x0b, 0x9c, 0x22, 0xc4, 0x55, 0x2e, 0xb8, 0x86, 0xea, 0x39, 0x74, - 0xc3, 0x75, 0x25, 0x2f, 0x98, 0x78, 0x72, 0xce, 0x80, 0xda, 0xeb, 0x95, 0x09, 0x0b, 0x5f, 0x64, 0x86, 0x97, 0x7d, - 0xcf, 0x9f, 0xcd, 0x4b, 0x9c, 0x6c, 0xd5, 0x04, 0x32, 0x9a, 0x7c, 0x50, 0xf2, 0xe2, 0x1b, 0x1f, 0x6a, 0x04, 0x29, - 0x61, 0x88, 0x6b, 0x6d, 0xc8, 0xe5, 0x51, 0x41, 0x1d, 0x5d, 0x9b, 0x84, 0x73, 0x89, 0xec, 0x42, 0x52, 0x49, 0x78, - 0xa9, 0x89, 0x8a, 0x8b, 0x0c, 0x55, 0x13, 0x96, 0x32, 0x54, 0xe3, 0x9b, 0x01, 0x0d, 0x06, 0x19, 0xc2, 0xa6, 0x1c, - 0x8a, 0xe7, 0x3e, 0xfb, 0x46, 0xcc, 0xa3, 0x84, 0x0f, 0x59, 0x25, 0x7a, 0x5a, 0x02, 0x1b, 0x81, 0x17, 0xd5, 0x5d, - 0x41, 0x94, 0x94, 0x5c, 0x84, 0x5c, 0x3b, 0x7c, 0x9f, 0x10, 0xdb, 0x46, 0xda, 0x06, 0x59, 0x50, 0x19, 0xf7, 0x35, - 0x62, 0x00, 0x98, 0xe5, 0x24, 0x59, 0xd0, 0xba, 0xa3, 0xdf, 0xd8, 0x32, 0x09, 0x38, 0xbb, 0xdc, 0xcf, 0xf2, 0x47, - 0x71, 0xcc, 0xcb, 0x32, 0x2f, 0xf6, 0xf6, 0x76, 0xa9, 0xbc, 0x96, 0x2c, 0x70, 0x12, 0xdf, 0x5e, 0x67, 0xa6, 0x0b, - 0x9e, 0xe1, 0xb6, 0x4a, 0x6e, 0x0a, 0x8d, 0xdc, 0xa4, 0x84, 0x90, 0xc0, 0xb9, 0xba, 0x72, 0x1a, 0x15, 0x93, 0x70, - 0x00, 0xb0, 0xab, 0x1a, 0x9e, 0x72, 0x21, 0x16, 0x92, 0x10, 0xb2, 0x01, 0x9a, 0xad, 0xf2, 0xa0, 0x5b, 0xef, 0x12, - 0xc8, 0x6e, 0xa5, 0xb7, 0xb2, 0x66, 0x74, 0x6b, 0xd5, 0x24, 0xdf, 0x88, 0xa9, 0x5b, 0x8e, 0x49, 0xa6, 0xb0, 0xe6, - 0xf1, 0x92, 0xf7, 0x57, 0x8c, 0x60, 0xaf, 0x46, 0x93, 0x53, 0x47, 0x41, 0x48, 0xec, 0xca, 0xfc, 0xb0, 0x14, 0x90, - 0x2b, 0xf8, 0x5f, 0x73, 0x5e, 0x56, 0x02, 0x91, 0xa1, 0xde, 0x9c, 0x21, 0x8f, 0x5a, 0x17, 0x3a, 0x6b, 0x22, 0xe9, - 0xb6, 0xbe, 0xbd, 0x9d, 0x21, 0x6f, 0x2c, 0x11, 0xa9, 0xbf, 0x8f, 0x4f, 0xd8, 0xd7, 0xca, 0xbb, 0xbd, 0x7d, 0x9f, - 0xa8, 0x5a, 0xcc, 0x5c, 0x6a, 0x79, 0x6d, 0x6d, 0x52, 0x78, 0xe6, 0x49, 0xe6, 0xbc, 0xdb, 0x96, 0xfd, 0xcf, 0xfa, - 0xc0, 0xd8, 0x35, 0x16, 0x4b, 0xb0, 0x8a, 0xfe, 0x08, 0x28, 0xbe, 0x15, 0x55, 0x79, 0xc4, 0xeb, 0x6b, 0xf8, 0xe2, - 0x4f, 0x36, 0x70, 0x15, 0xd6, 0x12, 0x4a, 0x1d, 0xfe, 0xa4, 0x7f, 0x17, 0x3e, 0x29, 0x8a, 0x00, 0x75, 0x6d, 0xe4, - 0x19, 0xc2, 0xf1, 0xad, 0x4e, 0x38, 0xd6, 0x86, 0xe1, 0xcc, 0xf4, 0x27, 0x8e, 0x46, 0x33, 0xb9, 0xd4, 0x4d, 0x16, - 0xcb, 0xa8, 0x33, 0x66, 0x48, 0x56, 0x15, 0x6f, 0xa2, 0x29, 0xac, 0x66, 0x40, 0xea, 0xbb, 0x0a, 0x08, 0xfc, 0xc4, - 0x22, 0x7d, 0x8b, 0x87, 0x96, 0xc8, 0x43, 0x51, 0xdc, 0x45, 0x21, 0xad, 0xbe, 0xe4, 0x4a, 0xc6, 0x2f, 0xcb, 0xbe, - 0x91, 0xed, 0xac, 0xc1, 0x13, 0x73, 0x96, 0x08, 0xae, 0xe0, 0x27, 0xd2, 0x04, 0xd0, 0x48, 0x84, 0x80, 0xc1, 0x03, - 0x42, 0xac, 0xcd, 0xa4, 0x2a, 0x65, 0xc6, 0x08, 0x64, 0x06, 0xe6, 0x81, 0xd8, 0x06, 0x90, 0x53, 0xfa, 0xad, 0x2d, - 0x35, 0x04, 0xdb, 0x05, 0x62, 0x86, 0x3f, 0x4a, 0xa3, 0xca, 0x6d, 0x1f, 0xb4, 0x50, 0x30, 0x05, 0xaa, 0x0f, 0x5c, - 0xc5, 0xf3, 0x36, 0x87, 0xc2, 0x7d, 0x10, 0xbd, 0x26, 0xc9, 0xa8, 0x72, 0x7f, 0xcf, 0x88, 0xa8, 0xf0, 0x14, 0xd8, - 0x52, 0x55, 0x13, 0x8f, 0x89, 0xe0, 0x40, 0x36, 0xb4, 0xd3, 0xd5, 0x8c, 0x48, 0xf6, 0x94, 0x08, 0x17, 0x92, 0x07, - 0x23, 0x5a, 0x1b, 0x32, 0xa3, 0x05, 0x37, 0x94, 0x1e, 0xdb, 0x3d, 0x51, 0x63, 0x20, 0xa9, 0x41, 0x66, 0x49, 0xb0, - 0x59, 0x60, 0x93, 0x08, 0x99, 0x58, 0xf9, 0x55, 0xfe, 0x2a, 0xbf, 0xe6, 0xc5, 0x93, 0x08, 0x3b, 0x1f, 0x88, 0xcf, - 0x57, 0x82, 0x15, 0x10, 0xc5, 0xaf, 0xba, 0x0a, 0x5f, 0xae, 0x68, 0xe0, 0x30, 0x19, 0xd3, 0x04, 0xca, 0x82, 0xdc, - 0x26, 0xe0, 0x9f, 0xe1, 0x42, 0xa3, 0x15, 0x89, 0xec, 0x86, 0x6b, 0xfc, 0x7a, 0xf4, 0xaa, 0x8e, 0x5f, 0x50, 0xc3, - 0x58, 0x51, 0xc0, 0xfa, 0x3a, 0x06, 0x26, 0x22, 0xd5, 0x0b, 0x8b, 0xd3, 0x01, 0x3f, 0x91, 0x6c, 0xfe, 0xf6, 0xb6, - 0xb2, 0xd4, 0xb8, 0x9a, 0xe4, 0xc8, 0xc5, 0xb2, 0xf1, 0x56, 0xc0, 0xad, 0x50, 0xc4, 0x2b, 0xf2, 0x34, 0xb5, 0x98, - 0x15, 0xcb, 0xba, 0x9a, 0x3d, 0x41, 0xf3, 0x17, 0xdf, 0xe3, 0x50, 0x98, 0x6f, 0x33, 0x29, 0xd5, 0xd1, 0x6c, 0xc8, - 0x0b, 0xd4, 0x2b, 0xad, 0xd9, 0x92, 0x7c, 0x16, 0x1a, 0xcc, 0x00, 0xa9, 0xf9, 0x10, 0x95, 0x16, 0x20, 0xc0, 0xfe, - 0x24, 0x2f, 0x2b, 0x9d, 0x68, 0x7a, 0x9f, 0xd9, 0x4a, 0xa8, 0x1f, 0x47, 0x69, 0xea, 0x0a, 0x05, 0x65, 0x9a, 0x7f, - 0xe3, 0x5b, 0x7a, 0xdd, 0xad, 0x75, 0x59, 0x57, 0xc3, 0xad, 0x6a, 0x80, 0xe1, 0xcc, 0xd2, 0x24, 0xe6, 0x9a, 0x79, - 0x5d, 0xf8, 0x20, 0x38, 0xf2, 0x1b, 0xa4, 0x23, 0xde, 0xf9, 0xf9, 0x79, 0x8b, 0xb5, 0xbd, 0x95, 0x00, 0xf8, 0x72, - 0x03, 0xb0, 0xdf, 0x61, 0x9b, 0x42, 0x11, 0x5f, 0x6e, 0x25, 0x6b, 0x9e, 0xc5, 0x2b, 0x13, 0xa5, 0x68, 0x09, 0xf2, - 0xec, 0xb1, 0x21, 0x54, 0x5a, 0x71, 0x45, 0xce, 0x51, 0x98, 0x16, 0x4b, 0xf7, 0xbd, 0x86, 0x9f, 0x46, 0x27, 0xb5, - 0xca, 0xd4, 0x9c, 0x97, 0x5a, 0x75, 0x37, 0xd3, 0x63, 0xa0, 0xdd, 0xab, 0xc4, 0xf4, 0x00, 0xbe, 0x43, 0x0f, 0x85, - 0xc6, 0xee, 0x6e, 0x0c, 0xc9, 0xd4, 0x21, 0x49, 0xbb, 0x5e, 0x44, 0x3f, 0x15, 0xb2, 0x9b, 0xdb, 0x40, 0x70, 0x21, - 0x89, 0x02, 0x47, 0x25, 0x50, 0x4c, 0xdb, 0x13, 0x98, 0x9e, 0x41, 0x14, 0x7f, 0xad, 0x63, 0xbf, 0x41, 0x83, 0x70, - 0x9d, 0x1a, 0x5b, 0x59, 0x16, 0xc9, 0xb2, 0xc7, 0xad, 0xa8, 0x74, 0x6d, 0xa1, 0xb8, 0xa0, 0xe9, 0x69, 0xb4, 0xaf, - 0x4f, 0xf4, 0x9d, 0xd8, 0x4e, 0x3d, 0xca, 0xe4, 0xc8, 0x5c, 0xa4, 0x02, 0xff, 0x16, 0xe3, 0x14, 0x3d, 0x90, 0x78, - 0x87, 0x8a, 0xc7, 0x6a, 0xad, 0x23, 0x80, 0x76, 0xab, 0x61, 0x52, 0xde, 0x0d, 0x81, 0xff, 0x23, 0xbd, 0x7c, 0x6a, - 0xb5, 0xf0, 0x4f, 0x3b, 0xaa, 0x69, 0x9c, 0x14, 0x9c, 0x75, 0xcf, 0xa4, 0x40, 0xa1, 0x08, 0xcd, 0xcf, 0x28, 0xbc, - 0x10, 0xbe, 0xbf, 0x15, 0x59, 0x24, 0x97, 0x61, 0x37, 0xca, 0xae, 0x2d, 0x50, 0xd4, 0x50, 0x40, 0x12, 0xd5, 0x8c, - 0x78, 0x6e, 0x5e, 0x53, 0x25, 0xa5, 0xd4, 0x2e, 0xd4, 0x71, 0x49, 0x73, 0x41, 0x0d, 0x76, 0xdd, 0x12, 0xb5, 0x39, - 0x25, 0xdf, 0x9b, 0x51, 0x94, 0x1b, 0xa3, 0x28, 0x7d, 0x4b, 0xdb, 0xf2, 0x0c, 0x32, 0x5b, 0x9f, 0x83, 0x7a, 0xe0, - 0xd9, 0xa5, 0x50, 0x64, 0xf5, 0x91, 0x42, 0x7b, 0x9a, 0xe0, 0xa6, 0x61, 0xc5, 0x0a, 0xa9, 0xea, 0x48, 0x5c, 0x43, - 0x92, 0x61, 0x3e, 0xc9, 0x3d, 0xb1, 0x38, 0x6a, 0xba, 0x6f, 0xce, 0x0a, 0x6f, 0x4d, 0xbe, 0x5f, 0xad, 0x24, 0x94, - 0xb8, 0x27, 0x67, 0xa7, 0x26, 0x18, 0x5b, 0x60, 0x61, 0x79, 0x28, 0x85, 0x61, 0x21, 0xfa, 0xac, 0x03, 0x47, 0xd7, - 0x0b, 0x69, 0xb9, 0x81, 0x4d, 0x4d, 0xa8, 0x54, 0xd2, 0x55, 0xee, 0xb1, 0x48, 0x89, 0xa5, 0x85, 0x19, 0x38, 0x70, - 0x1f, 0x65, 0x9d, 0x70, 0x7a, 0xcb, 0x9a, 0x72, 0x18, 0x58, 0xc5, 0x56, 0x01, 0x12, 0xd5, 0x62, 0x1b, 0xbc, 0xb7, - 0x61, 0x4d, 0xad, 0x1e, 0x0b, 0xe2, 0x45, 0x0d, 0xe2, 0x16, 0x68, 0x73, 0x41, 0xbc, 0xf2, 0x7e, 0x18, 0xd5, 0x3f, - 0x86, 0x89, 0x28, 0xc4, 0x44, 0x6c, 0x40, 0x71, 0x5d, 0xfc, 0x24, 0x2c, 0x44, 0x5d, 0xb6, 0x44, 0xf9, 0xce, 0x66, - 0x11, 0x2e, 0x76, 0x3e, 0x83, 0x95, 0xb1, 0x8e, 0x76, 0x5b, 0xa5, 0x50, 0xcf, 0x37, 0xda, 0xe1, 0xed, 0xed, 0xdf, - 0xb9, 0xe7, 0x4a, 0xf9, 0x17, 0x26, 0xac, 0xa7, 0x88, 0xee, 0xa3, 0x57, 0x58, 0x8a, 0xc4, 0x51, 0x93, 0xa2, 0x15, - 0x87, 0x3a, 0xd6, 0xd6, 0x27, 0xaa, 0xb2, 0x28, 0xf7, 0x93, 0x0d, 0x02, 0x46, 0x89, 0x92, 0x53, 0x9b, 0x21, 0x3f, - 0x91, 0x55, 0x83, 0x30, 0xeb, 0x05, 0x25, 0xe9, 0x32, 0xbb, 0xdb, 0xf4, 0xcb, 0xbd, 0xbd, 0xd2, 0xaa, 0xe8, 0x4a, - 0x53, 0x8a, 0x2f, 0x2e, 0x72, 0xe5, 0x72, 0x91, 0x91, 0xf8, 0xf2, 0x45, 0xf1, 0xa1, 0x0d, 0xed, 0x14, 0xc0, 0x06, - 0x8a, 0x79, 0x74, 0x1d, 0x25, 0xd5, 0x8e, 0xae, 0x45, 0x28, 0xe6, 0x40, 0x04, 0x96, 0x52, 0xda, 0x80, 0xc1, 0xa1, - 0xfc, 0x88, 0x64, 0x41, 0x49, 0xd1, 0x02, 0xf1, 0xe3, 0x09, 0x47, 0x53, 0xb6, 0x12, 0x24, 0xb4, 0x7a, 0xb8, 0x2b, - 0x19, 0x89, 0xac, 0x78, 0x7b, 0xdf, 0x57, 0xeb, 0x9f, 0xd7, 0xb4, 0x01, 0x98, 0x23, 0xa0, 0x6a, 0x53, 0x95, 0xb7, - 0x5a, 0x7b, 0x97, 0xc4, 0x11, 0xd6, 0xc7, 0xd6, 0xba, 0xa5, 0x0a, 0xd0, 0x5d, 0xd3, 0xbd, 0x8d, 0xd6, 0x5e, 0xe3, - 0xa6, 0x9a, 0x01, 0x0b, 0x03, 0xa1, 0xc2, 0xcc, 0xd2, 0xd6, 0xf2, 0xa5, 0x79, 0xb5, 0x2b, 0x6c, 0x27, 0xa0, 0x5b, - 0x68, 0xcd, 0x4f, 0x61, 0x43, 0x57, 0xd8, 0x38, 0x24, 0x57, 0xcd, 0xe7, 0xe9, 0x50, 0x76, 0x16, 0x54, 0x5a, 0x2e, - 0xf1, 0xe8, 0x3a, 0x49, 0x53, 0x93, 0xfa, 0x9f, 0x90, 0xf6, 0x52, 0x92, 0xf6, 0x5c, 0x91, 0x76, 0x24, 0x15, 0x48, - 0xda, 0x45, 0x75, 0xe6, 0xf3, 0x7c, 0x63, 0x79, 0xe6, 0x82, 0xa8, 0x97, 0xa4, 0x4e, 0x63, 0x7b, 0x73, 0xd5, 0x03, - 0x4f, 0x0b, 0x5f, 0xc0, 0x6f, 0xe4, 0xb4, 0x97, 0x88, 0x2b, 0x68, 0xd3, 0xe4, 0xb6, 0xa5, 0x02, 0xf2, 0x59, 0xb9, - 0xe2, 0x1a, 0xb3, 0x1f, 0x3d, 0x43, 0xa3, 0x9d, 0x35, 0x1c, 0xe4, 0x63, 0x94, 0xfc, 0x1f, 0xc9, 0x51, 0x6a, 0x74, - 0x99, 0x1c, 0x5d, 0xa9, 0x46, 0x87, 0xb4, 0xde, 0x8c, 0x6e, 0xf8, 0x7d, 0x6a, 0x4f, 0xc3, 0xcb, 0xf4, 0xf0, 0xcc, - 0x7c, 0xdf, 0xde, 0xba, 0x6b, 0x29, 0x68, 0xd1, 0x97, 0x5a, 0x4a, 0xa1, 0x6b, 0x47, 0x1a, 0x60, 0x43, 0x06, 0x13, - 0x56, 0x62, 0xd0, 0x9a, 0xcb, 0xbd, 0xfa, 0x77, 0x76, 0x1e, 0x32, 0xdc, 0x8b, 0xef, 0x9f, 0xe4, 0xd3, 0x19, 0x0a, - 0x64, 0x6b, 0x28, 0x0d, 0x05, 0x3e, 0xae, 0xe5, 0xaf, 0xb6, 0xa4, 0xd5, 0xbe, 0xa1, 0xf5, 0x58, 0xc3, 0x26, 0xad, - 0x35, 0x83, 0x2e, 0x35, 0xd7, 0x49, 0x9a, 0x70, 0x6c, 0xb3, 0xad, 0x3c, 0x59, 0xb7, 0xcc, 0xa8, 0x8c, 0xb7, 0x6e, - 0x26, 0xe8, 0x70, 0x86, 0xb4, 0xce, 0x22, 0x3f, 0x0a, 0xdd, 0xed, 0xf9, 0x5f, 0x19, 0xe0, 0x2c, 0x57, 0x6b, 0xe0, - 0x5b, 0xae, 0x56, 0x9f, 0x2a, 0xa9, 0x69, 0xb3, 0x4f, 0x5b, 0xf4, 0x5e, 0x0d, 0x3d, 0x93, 0x29, 0x75, 0xc6, 0xcb, - 0x3e, 0xa6, 0x6d, 0x88, 0x90, 0xe1, 0x72, 0x9a, 0x0f, 0x79, 0xe0, 0x40, 0x05, 0x99, 0xb3, 0x42, 0x3b, 0xab, 0x44, - 0x80, 0xdf, 0x32, 0x77, 0xf9, 0xbe, 0x6e, 0x6f, 0x0d, 0x3e, 0x55, 0x2b, 0x34, 0x85, 0xbd, 0x4a, 0xb6, 0x18, 0x63, - 0x3f, 0x81, 0x62, 0x48, 0x32, 0xa9, 0x16, 0x6f, 0x5f, 0x25, 0x86, 0x41, 0xbd, 0x4a, 0x82, 0xbb, 0x3f, 0x31, 0x0a, - 0x89, 0xd3, 0xf6, 0x4f, 0xfc, 0x43, 0xc7, 0x23, 0x8b, 0xf1, 0x73, 0x65, 0x31, 0x9e, 0x6b, 0x8b, 0xf1, 0x8b, 0x2a, - 0x9c, 0xaf, 0x59, 0x8c, 0x7f, 0xce, 0xc2, 0x17, 0x55, 0xef, 0x85, 0xb2, 0xa6, 0xbf, 0xcb, 0x41, 0x63, 0x00, 0xbd, - 0x3e, 0x4d, 0xaa, 0x26, 0xee, 0x26, 0x3a, 0x6c, 0x29, 0x32, 0xd0, 0xd4, 0x48, 0xf6, 0xee, 0x95, 0xd2, 0xff, 0x58, - 0x96, 0x85, 0xce, 0x3d, 0x28, 0x78, 0xcf, 0x61, 0x93, 0x2a, 0xfc, 0x8c, 0x4f, 0xf7, 0x96, 0xee, 0xeb, 0xa8, 0x9a, - 0xf8, 0x45, 0x04, 0xed, 0x4d, 0x5d, 0xaf, 0xe1, 0x38, 0x9e, 0x5f, 0x92, 0x12, 0xf2, 0xd0, 0x5b, 0xdd, 0xfb, 0xcc, - 0xbe, 0xe4, 0xa1, 0xd3, 0x73, 0x1a, 0x13, 0x60, 0x47, 0x51, 0xf8, 0xf9, 0xec, 0xde, 0xf2, 0x4b, 0xbe, 0x3a, 0xff, - 0xcc, 0x9e, 0x55, 0xda, 0xac, 0xcf, 0x6e, 0x40, 0xea, 0x87, 0xc9, 0x7f, 0xa6, 0xba, 0x04, 0x28, 0x27, 0x0c, 0xfc, - 0x8e, 0xc7, 0xbe, 0xa1, 0x5d, 0xf7, 0x3c, 0x31, 0x44, 0x48, 0xee, 0xc1, 0xec, 0x86, 0x4e, 0x4e, 0xc6, 0x03, 0x07, - 0x96, 0xbe, 0x49, 0xd3, 0x22, 0x04, 0x7b, 0x9c, 0x87, 0x35, 0x55, 0x9d, 0x25, 0x11, 0xd6, 0xf4, 0x38, 0x77, 0x13, - 0x4f, 0x55, 0xe3, 0x2a, 0x4b, 0xb5, 0x5c, 0xb1, 0xc9, 0xa5, 0xb0, 0x3d, 0xf8, 0x09, 0xc8, 0x05, 0x11, 0xf0, 0xe5, - 0xbe, 0x67, 0x8b, 0x25, 0xec, 0x4d, 0x12, 0x7e, 0xbe, 0xdc, 0xf9, 0x6f, 0xff, 0xfd, 0xcf, 0xd1, 0x9f, 0x45, 0xff, - 0x33, 0xcb, 0x78, 0x78, 0x70, 0xe6, 0xf6, 0x02, 0x77, 0xb7, 0xd9, 0xbc, 0xfd, 0xf3, 0xe0, 0xf2, 0x5f, 0x51, 0xf3, - 0xef, 0x47, 0xcd, 0x3f, 0xfa, 0xde, 0xad, 0xfb, 0xe7, 0x41, 0xef, 0x52, 0xbe, 0x5d, 0xfe, 0xeb, 0xfc, 0xcf, 0xb2, - 0xbf, 0x2f, 0x12, 0xef, 0x79, 0xde, 0xc1, 0x98, 0xfd, 0x98, 0x85, 0x07, 0xcd, 0xe6, 0x39, 0x3c, 0xfd, 0x02, 0x4f, - 0xf8, 0xbb, 0xa8, 0xc2, 0xf7, 0x7c, 0xfc, 0xec, 0x66, 0xe6, 0x7e, 0x3e, 0xbf, 0xbd, 0xb7, 0x7c, 0x93, 0xac, 0xb0, - 0xde, 0xcb, 0x7f, 0xfd, 0xf9, 0x67, 0xe9, 0xfc, 0x70, 0x1e, 0x1e, 0xf4, 0x1b, 0x9e, 0x4b, 0xc9, 0xfb, 0xa1, 0xf8, - 0x81, 0xec, 0xcb, 0x7f, 0xc9, 0xae, 0x38, 0x3f, 0xfc, 0xf9, 0xf9, 0xec, 0x3c, 0xec, 0xdf, 0xba, 0xce, 0xed, 0x0f, - 0xde, 0xad, 0xe7, 0xdd, 0xde, 0xf3, 0x3e, 0x33, 0x67, 0x0c, 0xe0, 0xfb, 0x03, 0xea, 0xff, 0x01, 0xea, 0xff, 0x09, - 0x7e, 0x1d, 0xf8, 0xfd, 0x94, 0x87, 0x07, 0xff, 0x82, 0x6f, 0x85, 0x11, 0xee, 0x96, 0xcc, 0x1f, 0xb7, 0xb8, 0x13, - 0x12, 0x01, 0xe4, 0x6f, 0xab, 0xa4, 0x4a, 0xb9, 0x77, 0xef, 0x20, 0x61, 0x2f, 0x72, 0x04, 0x16, 0x30, 0x7a, 0xdf, - 0xf7, 0x69, 0x13, 0x76, 0x79, 0x85, 0x13, 0x8f, 0x18, 0x74, 0x2f, 0x48, 0x98, 0xb0, 0x13, 0x94, 0x41, 0x25, 0x76, - 0x6f, 0x4b, 0xdc, 0xbe, 0x65, 0x4f, 0xc2, 0x17, 0xb9, 0x0b, 0x02, 0x41, 0x16, 0xe1, 0x43, 0xc7, 0x63, 0x1f, 0x2b, - 0xb9, 0xe1, 0x89, 0xcb, 0x5c, 0x60, 0x58, 0x96, 0x0b, 0x79, 0x06, 0xba, 0xf6, 0x6a, 0x4b, 0x26, 0xac, 0xea, 0x0c, - 0xbb, 0x5d, 0x95, 0xf6, 0xf6, 0x28, 0x7b, 0x52, 0x85, 0x1a, 0x39, 0x3e, 0x14, 0x9c, 0xff, 0x1a, 0xa5, 0x5f, 0x41, - 0x33, 0x7e, 0x56, 0xb1, 0x76, 0xe7, 0x21, 0x23, 0x53, 0x35, 0x48, 0x22, 0x5d, 0xbd, 0xbb, 0xf5, 0x31, 0x17, 0xfb, - 0x09, 0xc8, 0x85, 0xeb, 0xf6, 0x1a, 0x9c, 0xfb, 0xdd, 0x64, 0xc3, 0xa8, 0x55, 0x44, 0xd7, 0x8e, 0x57, 0xdf, 0x4a, - 0x4d, 0x32, 0x18, 0x1a, 0x60, 0x45, 0xc5, 0x81, 0xfe, 0x41, 0xbb, 0x3b, 0x72, 0xcc, 0x3b, 0x11, 0x56, 0xe4, 0x68, - 0x99, 0xe2, 0xe7, 0xcc, 0x2c, 0xda, 0x9f, 0x33, 0xdf, 0xac, 0x1d, 0x17, 0xf7, 0xb3, 0xa4, 0x5c, 0x52, 0x46, 0x7a, - 0xbb, 0x6c, 0x7d, 0x47, 0xb0, 0xd9, 0x46, 0x63, 0x59, 0x9f, 0xf8, 0x37, 0xb0, 0xf9, 0x10, 0xb9, 0x6c, 0xa7, 0xe7, - 0x9c, 0x95, 0xdf, 0xc6, 0xe7, 0x0e, 0xee, 0xe4, 0x14, 0x00, 0x0a, 0x32, 0x1e, 0x61, 0x89, 0x28, 0x6c, 0x75, 0xa3, - 0x33, 0xde, 0x8d, 0x1a, 0x0d, 0x25, 0x66, 0xc7, 0x61, 0x72, 0x19, 0x89, 0xef, 0x53, 0x36, 0x61, 0xc3, 0x10, 0x6a, - 0x9c, 0x43, 0x31, 0xfc, 0xa4, 0x3b, 0x3f, 0x8b, 0x65, 0x3b, 0x40, 0x76, 0x0b, 0x3f, 0x8d, 0xca, 0xea, 0x25, 0x5a, - 0x04, 0xc2, 0x39, 0x9b, 0x80, 0x14, 0xcd, 0x6f, 0x78, 0xec, 0xc6, 0x1e, 0x9b, 0x48, 0x1a, 0xe4, 0x75, 0xbd, 0x79, - 0x68, 0x15, 0x43, 0x3d, 0x03, 0x9a, 0xef, 0x4d, 0x2e, 0xdb, 0x7d, 0x78, 0x72, 0x00, 0xd1, 0x9d, 0x5e, 0x11, 0xfe, - 0x98, 0x05, 0x98, 0x62, 0x89, 0xd3, 0xe1, 0x2f, 0x98, 0xd4, 0xb1, 0x92, 0xdc, 0x4f, 0xb9, 0x5f, 0x81, 0x54, 0xec, - 0x62, 0x32, 0x1a, 0x09, 0x4a, 0x85, 0xe1, 0xce, 0xd9, 0x01, 0xd0, 0x03, 0x48, 0x25, 0x14, 0xf5, 0xa0, 0x8d, 0x05, - 0x80, 0x6a, 0x72, 0x79, 0xd8, 0xb7, 0x79, 0x84, 0x48, 0xc5, 0xf6, 0x17, 0x15, 0xb4, 0xdf, 0xa2, 0xf6, 0xcf, 0x9d, - 0x1e, 0x64, 0x94, 0x42, 0x8c, 0xeb, 0x95, 0x41, 0xc6, 0x69, 0xbc, 0x5e, 0x20, 0x3b, 0x28, 0xdb, 0x86, 0xb4, 0x4e, - 0xe0, 0x0e, 0xed, 0x91, 0x34, 0xb1, 0x41, 0x09, 0x0a, 0x96, 0x86, 0x58, 0x1e, 0x1a, 0xc6, 0x46, 0xcd, 0x67, 0x8b, - 0x2a, 0x90, 0x09, 0x3f, 0x38, 0x3f, 0xf4, 0x7e, 0xca, 0x82, 0x3f, 0x32, 0xd1, 0x83, 0x9f, 0x40, 0x64, 0xc7, 0xdf, - 0x3f, 0xb2, 0x1e, 0x76, 0x8b, 0xd2, 0x7e, 0x94, 0x69, 0xbf, 0x60, 0x5a, 0xc6, 0x03, 0xea, 0x30, 0x2b, 0xb5, 0x3c, - 0x26, 0x26, 0x67, 0x14, 0x8a, 0x11, 0xec, 0xed, 0xc1, 0x24, 0x35, 0xda, 0x7d, 0xdc, 0x11, 0x28, 0xaa, 0xf2, 0xd7, - 0xa4, 0x02, 0xda, 0x7d, 0x70, 0xee, 0x78, 0x3d, 0x67, 0x07, 0x67, 0xb9, 0x9b, 0x37, 0x42, 0x09, 0xeb, 0xb8, 0xc1, - 0xa3, 0x60, 0x78, 0x1e, 0x02, 0x08, 0x33, 0x41, 0xe4, 0x53, 0x8f, 0xc5, 0x92, 0xa6, 0xb6, 0xd8, 0xd0, 0x6b, 0x64, - 0x59, 0x43, 0xbd, 0xc3, 0xdb, 0xa4, 0x6a, 0x8c, 0xbc, 0x20, 0xc6, 0x5f, 0x18, 0x72, 0x08, 0x43, 0xd7, 0x1f, 0x2a, - 0x66, 0x19, 0x79, 0xc1, 0x48, 0x99, 0x47, 0x2f, 0x69, 0x71, 0xe4, 0x0d, 0x37, 0xb9, 0xe4, 0xfd, 0xdb, 0x5b, 0xe7, - 0xac, 0x07, 0xbd, 0x68, 0xb8, 0x0a, 0xed, 0x0e, 0x14, 0xde, 0xc1, 0xc4, 0x64, 0xfd, 0x95, 0xdc, 0x81, 0xba, 0xe6, - 0xb5, 0xdd, 0xa6, 0xa5, 0x59, 0xff, 0x16, 0x59, 0xe0, 0x2b, 0xad, 0xf7, 0x08, 0xf9, 0x76, 0x86, 0x43, 0x55, 0xb8, - 0x9d, 0x87, 0x2d, 0x00, 0xb8, 0x32, 0x77, 0x83, 0x06, 0x68, 0xf0, 0x3f, 0x0e, 0x4d, 0x71, 0x76, 0x09, 0x48, 0x0c, - 0x22, 0x6e, 0x44, 0xfa, 0x4b, 0x57, 0x19, 0xd3, 0x79, 0x1a, 0x5e, 0xf3, 0xb5, 0xfd, 0xdf, 0x14, 0xf7, 0x64, 0x9e, - 0x00, 0x5d, 0x98, 0x17, 0x05, 0xbc, 0xbf, 0x01, 0xb6, 0x1c, 0xca, 0xc2, 0xa8, 0x5b, 0xe1, 0xc6, 0x2e, 0x43, 0xa9, - 0xae, 0xa3, 0x56, 0xca, 0x70, 0x23, 0x7b, 0x1e, 0x0e, 0x85, 0xc0, 0x45, 0xdb, 0xbd, 0xdd, 0xb9, 0x54, 0xa5, 0x41, - 0xa6, 0x1c, 0xca, 0x7d, 0x60, 0x17, 0x08, 0xe0, 0xdc, 0x8f, 0x31, 0x1b, 0x1b, 0x00, 0x59, 0x95, 0xd6, 0x15, 0x60, - 0x33, 0xb4, 0x9c, 0x01, 0xe1, 0xc4, 0x54, 0x50, 0x6a, 0x34, 0x13, 0x57, 0xeb, 0xed, 0x2c, 0xea, 0x12, 0x01, 0x2a, - 0xfd, 0x0c, 0x4a, 0x20, 0x84, 0x70, 0xef, 0x5f, 0x26, 0x01, 0xfd, 0xb1, 0x77, 0xb6, 0x4c, 0x07, 0x2f, 0x6d, 0x93, - 0xf7, 0x1c, 0xed, 0xc4, 0x24, 0x9e, 0xe9, 0xc2, 0xc2, 0x78, 0xee, 0x79, 0x50, 0xcb, 0xdc, 0xc7, 0x1d, 0x41, 0xc2, - 0xa4, 0x2c, 0x03, 0xb2, 0x36, 0xb7, 0x71, 0x6b, 0x62, 0x0c, 0xd3, 0x23, 0xc0, 0xf2, 0xa2, 0xd1, 0x20, 0xe3, 0xf5, - 0x50, 0xe0, 0xc5, 0xdc, 0x63, 0x23, 0xbd, 0xd6, 0x54, 0xb9, 0x59, 0x58, 0x6f, 0xca, 0x1d, 0xd5, 0x8d, 0xc0, 0x80, - 0x76, 0x1e, 0xd9, 0x17, 0x2b, 0xac, 0x9d, 0x8d, 0xc3, 0x03, 0xf7, 0xd2, 0xef, 0xfd, 0x8f, 0x3e, 0xa8, 0xa2, 0xfe, - 0xbe, 0x77, 0x20, 0x68, 0xc9, 0x08, 0x10, 0x5f, 0xb4, 0xb1, 0xa4, 0xdd, 0xcf, 0x36, 0x23, 0x03, 0x64, 0x90, 0x03, - 0x57, 0x98, 0xf2, 0x60, 0x8c, 0xab, 0x5e, 0x21, 0xcf, 0x8c, 0x21, 0x32, 0x41, 0x9a, 0xa0, 0x2d, 0x3e, 0x50, 0x96, - 0x48, 0xbf, 0xf5, 0x9c, 0x5e, 0x6c, 0xde, 0xfe, 0x87, 0xd3, 0x4b, 0xa3, 0xe0, 0x49, 0xb2, 0x92, 0x46, 0xf2, 0x5a, - 0x1b, 0x27, 0xaa, 0x8d, 0x95, 0x98, 0x1c, 0x0b, 0x78, 0x43, 0x6f, 0xd3, 0x3a, 0x32, 0xf7, 0x56, 0x00, 0x09, 0x45, - 0x9d, 0x4a, 0xbf, 0x8a, 0xc6, 0x08, 0x55, 0x6b, 0x12, 0x4a, 0xdb, 0x37, 0xc0, 0x1a, 0x32, 0x62, 0x8b, 0x42, 0x5a, - 0x84, 0xe6, 0xfc, 0x1c, 0x80, 0x57, 0x2b, 0x2c, 0x25, 0xab, 0xfa, 0x5e, 0xbc, 0x26, 0xde, 0x23, 0xa4, 0xca, 0x67, - 0xf3, 0xee, 0x08, 0x88, 0x77, 0xa9, 0xf0, 0x6b, 0x78, 0x39, 0xea, 0x83, 0x04, 0x84, 0xf6, 0xc0, 0x1a, 0x46, 0xb1, - 0xda, 0x18, 0x3b, 0x72, 0x8c, 0x8d, 0x06, 0x8c, 0xb2, 0x6b, 0x7d, 0x3c, 0x97, 0x1f, 0xaf, 0x56, 0x02, 0x32, 0xeb, - 0x18, 0x77, 0xea, 0x51, 0x0a, 0x3a, 0x82, 0xc1, 0xdb, 0x97, 0xdc, 0xdb, 0x5a, 0x2d, 0x56, 0x8a, 0x9f, 0xd3, 0xea, - 0x45, 0x8a, 0x2a, 0xb8, 0x87, 0x8b, 0xb0, 0xc0, 0x4f, 0xb5, 0x19, 0x19, 0xc4, 0xb8, 0x61, 0xa3, 0x4d, 0xe8, 0x0e, - 0x85, 0xea, 0x95, 0x3d, 0x30, 0x95, 0x41, 0xa1, 0x70, 0x62, 0x56, 0xf8, 0x2a, 0x6f, 0x34, 0x56, 0xf5, 0xfd, 0x52, - 0xb5, 0x88, 0x6b, 0xfb, 0x17, 0xcf, 0x36, 0x5c, 0x3c, 0x14, 0xf7, 0x35, 0xfc, 0x36, 0x83, 0xbe, 0x64, 0xbc, 0x40, - 0x0e, 0x1b, 0x56, 0x2c, 0x5b, 0xad, 0x34, 0xd7, 0xff, 0xb5, 0x12, 0x3e, 0x63, 0x61, 0x82, 0x74, 0x88, 0xb4, 0x36, - 0x96, 0xb3, 0x82, 0x45, 0x44, 0x45, 0x60, 0xf4, 0x1f, 0x2b, 0xe5, 0x1e, 0x53, 0x11, 0x49, 0x8a, 0x43, 0x8b, 0x77, - 0xc3, 0x8a, 0xe6, 0xa0, 0x50, 0x3c, 0xc9, 0xbf, 0xab, 0xd2, 0x81, 0x42, 0x12, 0x50, 0xb1, 0x54, 0x12, 0xb2, 0x34, - 0xfc, 0x86, 0x7a, 0x8e, 0xde, 0x60, 0xf1, 0x89, 0x20, 0x3e, 0x4d, 0x0a, 0x4e, 0x82, 0xfb, 0x3d, 0xa5, 0x37, 0xc6, - 0x75, 0x49, 0x33, 0xb6, 0xad, 0x3f, 0x08, 0xcd, 0x14, 0x8d, 0x43, 0x79, 0xb8, 0x51, 0x0c, 0x34, 0xbc, 0xb7, 0xdb, - 0x74, 0x68, 0x78, 0x16, 0xea, 0x65, 0x8c, 0xa2, 0x0f, 0x70, 0x34, 0xdd, 0xd5, 0x58, 0x3e, 0x04, 0xd0, 0x26, 0x0a, - 0x51, 0x29, 0x08, 0x3d, 0x8c, 0x2a, 0xfa, 0x00, 0xf0, 0x41, 0x3d, 0xcb, 0x63, 0xf6, 0xb8, 0x81, 0x71, 0xb9, 0x51, - 0xc8, 0x3d, 0x31, 0x78, 0x4d, 0xc7, 0x0a, 0x8b, 0xbb, 0x07, 0x11, 0x65, 0xa2, 0xda, 0x01, 0x00, 0x08, 0x63, 0x09, - 0x82, 0x10, 0x24, 0x87, 0xb8, 0xa6, 0xd7, 0x85, 0x34, 0x07, 0xd4, 0xd8, 0x05, 0x4e, 0x86, 0x2f, 0xc4, 0x43, 0x28, - 0x46, 0xcd, 0x82, 0x38, 0x44, 0xec, 0x24, 0x8f, 0xd6, 0x1d, 0xdd, 0x8c, 0x3e, 0xfb, 0x09, 0x15, 0x2f, 0xf5, 0xf2, - 0x46, 0xd6, 0xad, 0x13, 0x9e, 0x2a, 0x8f, 0x34, 0x78, 0x7e, 0x2d, 0x9d, 0xd2, 0x80, 0x6f, 0x48, 0xf2, 0xbf, 0xa1, - 0xa3, 0x3e, 0x7a, 0xed, 0x9b, 0x5c, 0x2a, 0x0c, 0x69, 0x1f, 0xb7, 0x15, 0xc3, 0xf4, 0xd5, 0xdc, 0x18, 0x09, 0xa8, - 0x7f, 0x4b, 0x9e, 0x06, 0x4b, 0xc9, 0x2b, 0x82, 0x6c, 0xc5, 0x88, 0x43, 0x05, 0xe5, 0x4a, 0xdb, 0x56, 0x9e, 0x82, - 0xc0, 0x46, 0x5b, 0x49, 0xf5, 0x69, 0x93, 0x68, 0x0c, 0x48, 0x79, 0x11, 0x83, 0x88, 0x79, 0xc7, 0xfe, 0xd2, 0xb3, - 0xca, 0xf3, 0x93, 0x29, 0x3a, 0xe2, 0x50, 0xdf, 0x33, 0xb6, 0x0b, 0x62, 0xc3, 0x1a, 0x3f, 0xcb, 0x09, 0x51, 0x8b, - 0x3a, 0xb3, 0x61, 0x20, 0x05, 0x02, 0xd3, 0x6c, 0xc1, 0xac, 0x97, 0x20, 0x18, 0x89, 0xb5, 0x9a, 0xea, 0xaa, 0x05, - 0xdf, 0xc1, 0xe5, 0x9e, 0x8a, 0x75, 0x2b, 0x98, 0xf2, 0xa4, 0x9b, 0x92, 0xfd, 0x92, 0x18, 0xfd, 0x84, 0x50, 0xe3, - 0x25, 0x77, 0x0b, 0x56, 0x50, 0xcd, 0x17, 0xc9, 0x20, 0x45, 0x3f, 0x15, 0x1c, 0x19, 0x08, 0xaa, 0x81, 0x2e, 0xdb, - 0x96, 0x65, 0x81, 0x69, 0xe2, 0x5c, 0x15, 0x2c, 0xf5, 0x91, 0x94, 0xc3, 0x8f, 0xa4, 0xe3, 0x9b, 0x9f, 0x9c, 0x00, - 0x2a, 0x88, 0x8f, 0x26, 0x11, 0x7c, 0x20, 0xf3, 0xcd, 0x0e, 0xe0, 0x27, 0x41, 0x35, 0x26, 0x1e, 0x0d, 0xa0, 0xd1, - 0x88, 0xfb, 0xab, 0x08, 0x7a, 0xef, 0xa6, 0x75, 0x28, 0xaa, 0xde, 0x93, 0x30, 0xb8, 0x06, 0x00, 0xa0, 0xa0, 0x6a, - 0xbb, 0x77, 0x0d, 0x62, 0xa0, 0x14, 0xe4, 0xab, 0x6f, 0xae, 0xf6, 0x26, 0x6a, 0x6d, 0xf8, 0x61, 0xa9, 0x5e, 0x78, - 0x99, 0x8d, 0xbb, 0x99, 0x1a, 0x8f, 0xb5, 0x34, 0x32, 0x2c, 0xf7, 0x52, 0xfa, 0x40, 0x30, 0xf2, 0xda, 0x92, 0x85, - 0x14, 0x69, 0xeb, 0x78, 0x81, 0x2a, 0x84, 0x1b, 0x5c, 0x58, 0x08, 0x28, 0x9d, 0xc0, 0xf2, 0x97, 0x7c, 0x1d, 0xcb, - 0xa1, 0x9e, 0xd2, 0x93, 0xd6, 0x32, 0xea, 0x06, 0x01, 0xac, 0xa3, 0x01, 0xf3, 0x22, 0x7c, 0x75, 0x37, 0xea, 0x3f, - 0xb2, 0x50, 0xff, 0x71, 0xc8, 0xad, 0x65, 0x20, 0x6c, 0x25, 0x7e, 0x2e, 0x0d, 0x14, 0xa5, 0xca, 0x7a, 0x32, 0x0b, - 0xd1, 0x1a, 0x57, 0x87, 0x6a, 0x6d, 0x8b, 0xf2, 0x0e, 0xca, 0x62, 0xaf, 0x14, 0xb2, 0x67, 0x32, 0xb5, 0x9f, 0xec, - 0x9a, 0x0d, 0x3a, 0x6c, 0x7a, 0x9b, 0x71, 0xd0, 0x26, 0x85, 0x8f, 0x3e, 0x7e, 0x7f, 0x6f, 0xf5, 0xc9, 0x6c, 0x73, - 0x05, 0x5b, 0x6e, 0xa5, 0x38, 0x6a, 0x6b, 0x01, 0xd7, 0x9d, 0x4c, 0xb1, 0x7d, 0xbd, 0x27, 0x5e, 0xa7, 0x42, 0x6b, - 0x8b, 0x51, 0xb1, 0x43, 0xec, 0x6d, 0xbb, 0x4d, 0x25, 0xb8, 0x55, 0x2d, 0xd2, 0x25, 0xe1, 0xdc, 0x1a, 0x15, 0x77, - 0x90, 0x91, 0x47, 0x54, 0x00, 0x38, 0xee, 0xf6, 0xec, 0xc7, 0x2b, 0x89, 0x27, 0xa2, 0x6b, 0x40, 0xcc, 0x90, 0x10, - 0x0a, 0xbc, 0x47, 0xcc, 0x11, 0x2c, 0x02, 0x41, 0xf4, 0x8a, 0x20, 0x65, 0x40, 0xe6, 0x38, 0xc6, 0x90, 0xff, 0x02, - 0x06, 0xf1, 0xca, 0x18, 0x32, 0xdf, 0x1b, 0x67, 0x2e, 0x44, 0x0c, 0x50, 0x26, 0xd1, 0x66, 0xaf, 0x12, 0xc4, 0x66, - 0xe8, 0xc7, 0x4a, 0x95, 0x27, 0x6d, 0xd3, 0x37, 0xd2, 0xb8, 0xb5, 0x53, 0x4a, 0x26, 0x3e, 0x91, 0xaf, 0x20, 0xb1, - 0x96, 0x7b, 0x0f, 0x73, 0x93, 0x88, 0x3a, 0x89, 0xef, 0x1f, 0xa8, 0xb4, 0xaa, 0x77, 0xf5, 0x75, 0xdd, 0x23, 0x66, - 0x6d, 0x5e, 0x60, 0x9d, 0x96, 0xa0, 0x47, 0x3f, 0xe6, 0xb0, 0xd2, 0x70, 0xff, 0x43, 0x83, 0xc5, 0x5b, 0xdd, 0xb3, - 0x6c, 0x80, 0x34, 0x40, 0x6b, 0xd3, 0x61, 0x6d, 0x84, 0xf4, 0xf4, 0x95, 0xf6, 0xc0, 0xaf, 0xd6, 0xbf, 0x02, 0xb0, - 0x7c, 0xe3, 0x06, 0x50, 0xb2, 0x9b, 0xd4, 0x0d, 0x8b, 0x78, 0x09, 0x29, 0x47, 0xee, 0x0c, 0xdf, 0x73, 0x8d, 0xc9, - 0x40, 0x11, 0x0e, 0x9b, 0x08, 0x41, 0x83, 0xab, 0xf1, 0x3a, 0xbd, 0x97, 0xd6, 0x8c, 0xcc, 0x56, 0x6b, 0x90, 0xdc, - 0xa3, 0x5e, 0x2e, 0x8c, 0x4c, 0xa5, 0xf1, 0xb5, 0xd5, 0x9d, 0x78, 0x82, 0xe0, 0x72, 0x49, 0x49, 0xb1, 0xd0, 0x70, - 0xbb, 0xd2, 0x02, 0xda, 0x17, 0x88, 0xff, 0x0c, 0xfe, 0x43, 0xf7, 0xda, 0xda, 0xc2, 0x85, 0xce, 0x09, 0x57, 0x1f, - 0xcb, 0x39, 0x01, 0xc6, 0xba, 0xc5, 0x42, 0xad, 0x50, 0x9b, 0x13, 0x0f, 0xc2, 0x12, 0xb9, 0xa7, 0x3f, 0xf0, 0xbf, - 0xb9, 0x99, 0x94, 0xe6, 0xd4, 0x3e, 0x1c, 0x92, 0xe2, 0x3c, 0x72, 0xc5, 0xde, 0x16, 0xb2, 0x8f, 0xc2, 0x9f, 0xbb, - 0xb5, 0xa6, 0xbb, 0x05, 0x7d, 0xc6, 0x24, 0xe8, 0x22, 0x1b, 0x4e, 0x05, 0xed, 0x13, 0x3e, 0x31, 0x24, 0xb5, 0x92, - 0x1e, 0x50, 0x8a, 0x18, 0x1a, 0xd7, 0x14, 0x6b, 0xfc, 0x95, 0x74, 0x5f, 0xd3, 0x6c, 0x82, 0x53, 0x37, 0xae, 0xc5, - 0x2c, 0xf0, 0x15, 0xe2, 0xd8, 0xf2, 0x71, 0x6e, 0x4d, 0xaa, 0x32, 0x8a, 0x53, 0xa3, 0x96, 0x10, 0xf0, 0x1e, 0xbd, - 0x67, 0xd6, 0x97, 0xfe, 0x0b, 0x62, 0x8c, 0x40, 0x4f, 0x6b, 0x04, 0x3e, 0x27, 0x02, 0xef, 0xa1, 0xe0, 0xa6, 0x5c, - 0xcb, 0x7b, 0xd2, 0x89, 0x26, 0x53, 0x1c, 0x4f, 0xe2, 0x99, 0x10, 0xb9, 0x37, 0x5e, 0xd6, 0x66, 0x24, 0xc8, 0x42, - 0xf4, 0x2d, 0x62, 0x92, 0xc8, 0xe7, 0x30, 0x45, 0x8d, 0x46, 0xb7, 0x3c, 0xe3, 0xc6, 0xaa, 0x62, 0xba, 0x99, 0xe1, - 0x2e, 0x31, 0xe2, 0x7d, 0x8d, 0xa3, 0xa2, 0x23, 0x81, 0xf2, 0xfe, 0x2e, 0xd1, 0x7c, 0x0f, 0x25, 0x6d, 0xfa, 0x66, - 0x97, 0xd5, 0x1b, 0xb1, 0x38, 0x24, 0xd7, 0xec, 0xe1, 0xbc, 0xfb, 0xbe, 0xdb, 0x08, 0xf6, 0x7b, 0xb7, 0xcd, 0xd0, - 0xc7, 0xcd, 0xeb, 0x56, 0x82, 0x34, 0xe8, 0x45, 0xd8, 0x55, 0xf2, 0x35, 0xba, 0x64, 0x5b, 0x8d, 0x75, 0x2b, 0xa3, - 0xed, 0x56, 0x61, 0x09, 0xf2, 0x39, 0x37, 0x4e, 0x03, 0x6b, 0x8e, 0x9d, 0xc4, 0x66, 0x36, 0x0d, 0xf8, 0xc0, 0x60, - 0x2a, 0x66, 0x21, 0xeb, 0xbb, 0xbb, 0xb6, 0x53, 0x4c, 0x37, 0x71, 0x79, 0x4b, 0xfe, 0xf8, 0x24, 0xd9, 0xc6, 0x1f, - 0x59, 0x2e, 0x97, 0x3e, 0xf1, 0xc6, 0xf6, 0x3f, 0xe0, 0x8d, 0xd2, 0x6c, 0xaf, 0xd8, 0x23, 0x4a, 0x27, 0x35, 0xf6, - 0x58, 0x9f, 0xd3, 0x10, 0x54, 0x51, 0x39, 0x1d, 0xe7, 0x1d, 0x00, 0x21, 0x2c, 0xc3, 0x5d, 0xa4, 0xc3, 0xf8, 0xd8, - 0x16, 0x8f, 0x16, 0x49, 0x16, 0x36, 0x64, 0x37, 0xd3, 0xaa, 0x8c, 0xe7, 0xa3, 0x03, 0xb5, 0x4b, 0xbe, 0x5e, 0x84, - 0xd8, 0x12, 0x87, 0x24, 0x96, 0x87, 0x99, 0xde, 0xba, 0xc2, 0x1e, 0x13, 0xdb, 0x90, 0x0a, 0xa6, 0xbb, 0xd5, 0xab, - 0x50, 0xa9, 0x9f, 0xff, 0x5e, 0x38, 0xad, 0xb1, 0x18, 0x21, 0x49, 0xd4, 0xbc, 0x18, 0x64, 0x0f, 0xa4, 0xc0, 0xb8, - 0x4b, 0x1a, 0xaa, 0xe1, 0xea, 0x5e, 0x8d, 0x25, 0xb1, 0x16, 0x9a, 0xdd, 0x76, 0x89, 0x2f, 0x01, 0x23, 0xda, 0xc6, - 0x58, 0x58, 0x61, 0xe1, 0x36, 0x10, 0xcb, 0x1a, 0x49, 0x01, 0x2a, 0x2b, 0x34, 0x28, 0x96, 0x12, 0xaa, 0x56, 0x61, - 0x0e, 0x70, 0x44, 0x99, 0xb4, 0x1b, 0x9f, 0xe5, 0x46, 0x49, 0x8e, 0x41, 0x4e, 0x4b, 0x75, 0xc3, 0xd1, 0x65, 0x06, - 0xb2, 0x1e, 0xb4, 0x1e, 0x0b, 0x85, 0x05, 0xb9, 0x17, 0x08, 0x7d, 0xba, 0x91, 0xcb, 0x18, 0x28, 0x62, 0x01, 0x64, - 0x40, 0x74, 0x2d, 0x85, 0xae, 0xa5, 0x76, 0xd7, 0x28, 0x1f, 0x3f, 0x7c, 0x05, 0xbc, 0xf4, 0x15, 0xf1, 0xc3, 0x57, - 0xd8, 0xc9, 0x06, 0x88, 0x8e, 0xd2, 0x24, 0x98, 0xa2, 0xe5, 0xaa, 0x91, 0x5f, 0xc6, 0x8d, 0x76, 0xdf, 0xa2, 0x61, - 0xf0, 0x65, 0x98, 0xae, 0xd0, 0x73, 0xb6, 0x94, 0x0c, 0xf3, 0x0b, 0x32, 0xb6, 0x2f, 0xc4, 0x67, 0x44, 0x85, 0xf6, - 0x9c, 0xac, 0x9b, 0x0c, 0x34, 0x5e, 0xc9, 0xc9, 0x55, 0xe5, 0x6a, 0x0e, 0x16, 0xba, 0x10, 0x93, 0xdb, 0xcc, 0x3d, - 0x54, 0xfe, 0x35, 0xb6, 0x17, 0x91, 0x76, 0xe2, 0x5e, 0x43, 0x7c, 0xe5, 0xbb, 0xed, 0xfb, 0x7e, 0x54, 0x8c, 0x69, - 0x4b, 0x44, 0xed, 0xf0, 0xd2, 0x1a, 0x38, 0x94, 0xfd, 0xb4, 0x5a, 0xbe, 0xd4, 0x8d, 0xf5, 0x43, 0xd1, 0x7f, 0x25, - 0xec, 0xa8, 0x83, 0x2b, 0x51, 0xb4, 0xdd, 0x16, 0x21, 0x3a, 0x13, 0xff, 0x2f, 0x77, 0xe6, 0x48, 0x76, 0x46, 0xa0, - 0xc9, 0x1a, 0xdc, 0xee, 0x80, 0x47, 0x14, 0xad, 0xc1, 0xed, 0x6e, 0xf8, 0x2a, 0x68, 0xa5, 0x77, 0x76, 0xd0, 0x22, - 0x13, 0xa2, 0xa7, 0x26, 0xc1, 0xea, 0xe6, 0xf1, 0xba, 0x44, 0x26, 0xc8, 0x2a, 0x32, 0xd7, 0x2a, 0x04, 0xc2, 0x5a, - 0x5f, 0x0b, 0x46, 0x48, 0xb5, 0x14, 0xe3, 0x2c, 0x78, 0xe5, 0xd9, 0x46, 0x83, 0xba, 0x73, 0x0c, 0x62, 0x95, 0xb4, - 0xd6, 0x03, 0x0e, 0xa2, 0xd2, 0x80, 0xa2, 0x1d, 0x10, 0xba, 0x19, 0x94, 0x45, 0xf9, 0xaa, 0x54, 0xcf, 0x98, 0x8c, - 0xc7, 0x4e, 0x28, 0x0d, 0x1f, 0x30, 0x61, 0x06, 0x83, 0x4c, 0xbe, 0x89, 0x34, 0xf9, 0x0c, 0x0b, 0x52, 0x61, 0x74, - 0x29, 0x24, 0xc5, 0xdc, 0xeb, 0xe6, 0x12, 0x5d, 0xeb, 0x90, 0x7b, 0xf6, 0x0d, 0x9e, 0x5f, 0x25, 0x25, 0x00, 0x08, - 0x01, 0x60, 0x10, 0x0f, 0x87, 0x04, 0xd3, 0x55, 0xac, 0x7d, 0x15, 0x0d, 0x87, 0xdf, 0xfd, 0xa4, 0xaa, 0x8b, 0x45, - 0x93, 0x28, 0x1b, 0xa6, 0xa2, 0x11, 0xdb, 0x67, 0x52, 0xf9, 0x89, 0xea, 0x92, 0xb6, 0xc7, 0x8e, 0x11, 0x3f, 0x88, - 0xd6, 0x03, 0x88, 0x15, 0x5f, 0x50, 0xbc, 0xf4, 0xbb, 0x72, 0x0c, 0x6e, 0xa9, 0xdf, 0x31, 0x0b, 0xf6, 0x48, 0x58, - 0x65, 0x91, 0x57, 0xbf, 0xde, 0x4f, 0x85, 0x3a, 0x93, 0x0d, 0xe3, 0x82, 0x76, 0x0a, 0x5b, 0xe3, 0x14, 0x84, 0x29, - 0x27, 0x77, 0x6b, 0x5c, 0xaf, 0x15, 0x1b, 0x51, 0xac, 0x23, 0xfb, 0xa7, 0x54, 0xda, 0x5b, 0x6a, 0x04, 0xf3, 0xd4, - 0x8a, 0xe4, 0x25, 0x6e, 0xc5, 0x82, 0x58, 0xf9, 0xa2, 0x9a, 0xa6, 0x6b, 0x27, 0x71, 0xba, 0xbc, 0xd4, 0xd0, 0x29, - 0xdd, 0x6b, 0xce, 0x5e, 0x72, 0xdc, 0x37, 0x7e, 0x9e, 0x58, 0x9f, 0x6c, 0xee, 0x17, 0x3f, 0xb7, 0xf6, 0x8b, 0x9f, - 0x27, 0xc1, 0x66, 0x51, 0x6b, 0x9f, 0xb8, 0xe3, 0x9f, 0xfa, 0x2d, 0x47, 0xc9, 0x51, 0xc3, 0xc8, 0x9c, 0xaf, 0x14, - 0x4b, 0x83, 0x19, 0x9f, 0x38, 0x74, 0xce, 0xab, 0xab, 0x50, 0x5c, 0xba, 0x33, 0x0a, 0x09, 0xff, 0xae, 0x79, 0x92, - 0x9c, 0x27, 0x17, 0x5a, 0xc8, 0x3b, 0x50, 0xa6, 0xee, 0xe1, 0x82, 0x2b, 0x36, 0xce, 0x00, 0x42, 0xe3, 0xe5, 0x3f, - 0x6d, 0xc2, 0x52, 0xc7, 0x4b, 0x71, 0xf8, 0xc8, 0xae, 0x3f, 0x2c, 0xb4, 0x54, 0x57, 0x57, 0x42, 0x6e, 0xc8, 0x4a, - 0x00, 0xff, 0x57, 0x47, 0xf3, 0xb8, 0xa4, 0xc9, 0x3c, 0x58, 0xae, 0xb4, 0xe9, 0xa0, 0x10, 0x52, 0x5d, 0x02, 0x2b, - 0x66, 0x45, 0x3b, 0xe8, 0x7f, 0x27, 0xec, 0x4b, 0x22, 0x69, 0xe4, 0x4f, 0x9a, 0x02, 0x7d, 0xda, 0x7e, 0xd6, 0x66, - 0x0b, 0x89, 0x14, 0x63, 0xd0, 0x9e, 0x02, 0x88, 0xd5, 0x84, 0xaf, 0x2b, 0x85, 0x53, 0x4f, 0x73, 0x39, 0x9a, 0x3b, - 0x1d, 0x61, 0x99, 0x52, 0x73, 0xb3, 0x90, 0x9a, 0xd9, 0xe2, 0x39, 0xaa, 0x74, 0xf1, 0x4a, 0xaf, 0xb1, 0x5a, 0xbb, - 0xde, 0x1d, 0xa0, 0x34, 0x8e, 0x68, 0xc0, 0x62, 0xeb, 0xf0, 0x0e, 0x33, 0x6b, 0x1b, 0xc4, 0x63, 0x99, 0xe5, 0xc0, - 0x51, 0x13, 0xbc, 0xc5, 0x37, 0xae, 0xb7, 0xee, 0xbf, 0xa4, 0x44, 0xf7, 0x5a, 0x3f, 0x6c, 0x43, 0x83, 0xf8, 0xdc, - 0xb6, 0x3c, 0x30, 0x31, 0x3a, 0xdd, 0x90, 0x05, 0xa1, 0x61, 0xa4, 0x9c, 0x73, 0x8d, 0x17, 0xed, 0x16, 0xf8, 0x7a, - 0xdf, 0x71, 0xcf, 0x95, 0xa0, 0xdb, 0xcc, 0xb7, 0x7c, 0x9b, 0x9e, 0xe6, 0x77, 0xf9, 0x36, 0xd5, 0x24, 0xe1, 0xdd, - 0x96, 0xf7, 0x7d, 0x47, 0x58, 0xd1, 0xd6, 0xf6, 0x22, 0xff, 0x0b, 0xcd, 0xb5, 0x11, 0x3d, 0x05, 0x98, 0x15, 0x8d, - 0xf9, 0x08, 0x6c, 0xfd, 0x27, 0x7d, 0x7e, 0x81, 0x7c, 0x85, 0x7e, 0x12, 0xab, 0x40, 0xaa, 0x95, 0x74, 0x20, 0xd8, - 0xfd, 0x3b, 0x09, 0xc7, 0x69, 0x3e, 0x88, 0xd2, 0x0f, 0xd8, 0xa2, 0xc9, 0x7d, 0xb1, 0x18, 0x16, 0x00, 0x64, 0x49, - 0x6b, 0x4c, 0x2f, 0xfe, 0x4e, 0xac, 0x6e, 0xfc, 0x9d, 0x08, 0xca, 0x6d, 0x6a, 0x60, 0xcb, 0x57, 0xba, 0x8a, 0xe0, - 0xa7, 0x95, 0xa2, 0x1d, 0x49, 0xb9, 0xbd, 0x95, 0x75, 0x92, 0x96, 0x68, 0x92, 0x96, 0x94, 0xee, 0x7a, 0x55, 0xae, - 0xfb, 0xe5, 0x8e, 0xce, 0x6e, 0x92, 0xb9, 0x2f, 0x16, 0x99, 0xfb, 0x92, 0x04, 0xdf, 0xfd, 0xca, 0xa2, 0x78, 0x87, - 0xfe, 0x21, 0x79, 0xc6, 0x88, 0x5e, 0xbf, 0xaf, 0xd0, 0xa1, 0xa1, 0x82, 0xff, 0x9b, 0xd3, 0x0e, 0x86, 0x7b, 0x29, - 0xff, 0x23, 0x37, 0x9e, 0x97, 0x55, 0x3e, 0x95, 0x95, 0x96, 0xf2, 0x8c, 0x13, 0x65, 0xa2, 0x01, 0x9b, 0xf6, 0xf0, - 0x83, 0xfa, 0x31, 0xb2, 0xe5, 0xd7, 0x24, 0x1b, 0x06, 0xa0, 0xde, 0xca, 0x6f, 0x82, 0x7c, 0x15, 0x2a, 0x37, 0xe7, - 0xcd, 0x3c, 0x06, 0xf5, 0x25, 0xe5, 0x04, 0x26, 0xb7, 0x80, 0xa5, 0x75, 0x47, 0x63, 0x05, 0xee, 0xe6, 0x88, 0xc6, - 0xd8, 0x5c, 0x7b, 0x0e, 0x54, 0x3e, 0xd6, 0x86, 0x36, 0xa3, 0x29, 0xaf, 0x26, 0xf9, 0x10, 0x1d, 0x5f, 0xe0, 0x1b, - 0x75, 0x9c, 0x0a, 0x64, 0x5b, 0xd7, 0x21, 0xfb, 0x05, 0x9e, 0x41, 0xb7, 0x73, 0xbc, 0xde, 0x12, 0x0f, 0x06, 0x99, - 0xa6, 0x41, 0xcb, 0xe4, 0xeb, 0x67, 0x68, 0xa0, 0x76, 0xbe, 0x60, 0x09, 0xb4, 0x1c, 0x88, 0x5e, 0x3b, 0xa3, 0x84, - 0xa7, 0x43, 0x87, 0x41, 0x72, 0xa0, 0x8f, 0xad, 0xd3, 0x29, 0x6b, 0x9a, 0x44, 0x27, 0xbf, 0xce, 0x1c, 0x66, 0x1a, - 0x01, 0xb2, 0xca, 0xf2, 0x22, 0x19, 0x23, 0x8e, 0xfe, 0x0c, 0x9f, 0xc8, 0xfa, 0xac, 0xa3, 0x82, 0xde, 0x52, 0x81, - 0xde, 0xb7, 0x92, 0xed, 0x69, 0x90, 0x0a, 0xc7, 0x25, 0x7d, 0x0b, 0x82, 0xad, 0x5d, 0xce, 0xa8, 0x90, 0xa0, 0x40, - 0xfe, 0xd3, 0xa1, 0xb0, 0x91, 0xcd, 0xe7, 0xaa, 0x9a, 0xc7, 0xed, 0xda, 0x47, 0x1c, 0x3f, 0x30, 0x1e, 0x24, 0xbf, - 0x03, 0x53, 0x58, 0x2a, 0x32, 0x4b, 0x9f, 0x5b, 0x36, 0xb3, 0x51, 0x24, 0x2b, 0x0d, 0xe6, 0xf4, 0xe4, 0x99, 0x3d, - 0xa8, 0x69, 0x65, 0x3e, 0x84, 0x4a, 0x10, 0xf0, 0xe8, 0x2d, 0x13, 0xd1, 0x81, 0xd0, 0x95, 0x72, 0x53, 0x9d, 0x41, - 0xb7, 0x96, 0x6a, 0x0c, 0x41, 0x62, 0x83, 0xb1, 0x5a, 0x21, 0x1a, 0x4a, 0x04, 0x13, 0x9e, 0x87, 0xc0, 0x43, 0xb3, - 0x0d, 0x1e, 0x9a, 0x13, 0x0f, 0xf5, 0x2d, 0x90, 0xdf, 0xc1, 0x33, 0x39, 0x41, 0x83, 0x64, 0x4b, 0x62, 0x80, 0x72, - 0x76, 0x25, 0x0e, 0xd9, 0x33, 0xaa, 0x0f, 0xef, 0x89, 0x49, 0xcf, 0x6b, 0xdd, 0x72, 0xa9, 0x1e, 0x0f, 0xb0, 0x03, - 0x3d, 0x82, 0x44, 0x81, 0x95, 0xb2, 0xfb, 0x24, 0xca, 0xaf, 0xd6, 0x2d, 0x7c, 0x35, 0xac, 0x50, 0xc1, 0xc4, 0x8d, - 0xbc, 0x65, 0xe2, 0x46, 0x20, 0x9f, 0xaf, 0x90, 0xcf, 0xea, 0xfe, 0x73, 0x7b, 0x3a, 0x6a, 0x5e, 0xd2, 0xdb, 0x0f, - 0x18, 0xa2, 0x94, 0x5f, 0xa1, 0x6f, 0x28, 0x4b, 0x34, 0x61, 0x71, 0xe9, 0xa4, 0x9f, 0x35, 0x6f, 0x63, 0x31, 0x21, - 0x6a, 0x06, 0x66, 0x91, 0xbb, 0xb4, 0x46, 0x61, 0x1f, 0x2a, 0x97, 0x07, 0x0e, 0xe5, 0x36, 0xa1, 0x71, 0x5e, 0x75, - 0xcb, 0x70, 0x8d, 0xf5, 0x7c, 0xdf, 0xc7, 0xf3, 0xaf, 0x39, 0x2f, 0x16, 0x17, 0x1c, 0x7d, 0xac, 0x73, 0x3c, 0x6e, - 0x6c, 0xa6, 0xc1, 0x38, 0xc8, 0xf7, 0x72, 0x12, 0x5d, 0x56, 0xec, 0xbb, 0x51, 0x31, 0x56, 0xb4, 0x4f, 0x69, 0x59, - 0x6b, 0xc4, 0x72, 0xe1, 0x77, 0x1e, 0xdd, 0xe4, 0x5d, 0x8a, 0x95, 0x60, 0x20, 0x2d, 0xf7, 0x16, 0x58, 0x61, 0x9f, - 0x87, 0xbd, 0x2c, 0xfb, 0xeb, 0xa6, 0x1b, 0x4c, 0xc2, 0x6d, 0xbf, 0xfc, 0xee, 0xa1, 0x6e, 0xf3, 0xd6, 0xbd, 0x7b, - 0xa8, 0xb5, 0xcd, 0x42, 0x72, 0x24, 0x62, 0xb2, 0x1d, 0x7d, 0x7e, 0x3a, 0x03, 0x92, 0xb6, 0xc2, 0xee, 0x3d, 0x4e, - 0x80, 0xfa, 0x3f, 0x56, 0x1e, 0x8a, 0x3e, 0x6e, 0xe4, 0x5e, 0xa4, 0xb9, 0x22, 0xe4, 0xa6, 0x07, 0x8f, 0x93, 0x8d, - 0x2e, 0x3c, 0x4e, 0xac, 0x43, 0xaf, 0xa8, 0x35, 0x8d, 0x33, 0x3e, 0x54, 0xf4, 0xd3, 0x13, 0x48, 0x48, 0x72, 0xdc, - 0xdb, 0x24, 0xcc, 0xaa, 0xcf, 0x01, 0xca, 0x5f, 0x0c, 0x34, 0xcc, 0x2a, 0xcf, 0x80, 0x14, 0xcd, 0xe6, 0x15, 0x2b, - 0xa9, 0xf7, 0xcb, 0x51, 0x9e, 0x55, 0xcd, 0x51, 0x34, 0x4d, 0xd2, 0x05, 0x88, 0xcd, 0xcd, 0x69, 0x9e, 0xe5, 0xe5, - 0x0c, 0x16, 0x02, 0x2b, 0x17, 0xa0, 0x21, 0x4d, 0x9b, 0xf3, 0x84, 0xbd, 0xe0, 0xe9, 0x37, 0x5e, 0x25, 0x71, 0xc4, - 0xde, 0xe7, 0x03, 0x68, 0x93, 0xbd, 0xbd, 0x59, 0x8c, 0x79, 0xc6, 0x3e, 0x0e, 0xe6, 0x59, 0x35, 0x67, 0x65, 0x94, - 0x95, 0x4d, 0x10, 0x38, 0x93, 0x51, 0xb7, 0xd9, 0x9c, 0x15, 0xc9, 0x34, 0x2a, 0x16, 0xcd, 0x38, 0x4f, 0x01, 0xcb, - 0xfe, 0xab, 0x75, 0x18, 0x3d, 0x1c, 0x1d, 0x75, 0xab, 0x02, 0xca, 0x24, 0x38, 0x31, 0x01, 0xd0, 0xae, 0x9d, 0xc3, - 0xe3, 0xd6, 0xb4, 0xdc, 0x15, 0x1b, 0x7e, 0x51, 0x56, 0xad, 0x3e, 0xb3, 0x5f, 0x73, 0xec, 0xa5, 0x3f, 0xa8, 0x32, - 0xd9, 0x49, 0xe0, 0x08, 0x45, 0x09, 0x35, 0xcc, 0xf2, 0x24, 0xab, 0x78, 0xd1, 0x1d, 0xe4, 0x05, 0x4c, 0x4c, 0xb3, - 0x88, 0x86, 0xc9, 0xbc, 0x0c, 0x8e, 0x66, 0x37, 0xdd, 0x7a, 0x0b, 0x22, 0x3f, 0xc8, 0xf2, 0x8c, 0x77, 0x51, 0xde, - 0x18, 0x17, 0xf9, 0x3c, 0x1b, 0xca, 0x6e, 0xcc, 0x41, 0x1e, 0xae, 0xba, 0x33, 0xd0, 0xfd, 0x92, 0x6c, 0x1c, 0x9c, - 0xc2, 0xc7, 0x34, 0xea, 0x6b, 0x9e, 0x8c, 0x27, 0x55, 0x70, 0xdc, 0x6a, 0x89, 0xf7, 0x12, 0xa8, 0x6b, 0xd0, 0xee, - 0xf8, 0x9d, 0x63, 0x28, 0x01, 0x12, 0x3c, 0xb4, 0xdb, 0x44, 0x58, 0xe0, 0x47, 0x6d, 0xbf, 0xf5, 0xf0, 0xf0, 0x01, - 0x66, 0xa0, 0x8f, 0x43, 0x93, 0x06, 0x84, 0xce, 0xee, 0x01, 0xb0, 0x78, 0x5e, 0xe0, 0x29, 0xfa, 0x2e, 0x8c, 0x1b, - 0x08, 0x50, 0xb3, 0xa0, 0x4a, 0x9b, 0xd0, 0xca, 0x0a, 0xc7, 0x13, 0x08, 0xb7, 0x55, 0x39, 0x2c, 0xf9, 0xb6, 0xb4, - 0xba, 0x48, 0x31, 0x69, 0x82, 0x62, 0x3c, 0x88, 0xdc, 0x76, 0xe7, 0x01, 0x53, 0xff, 0xf9, 0x1d, 0xcf, 0x02, 0x5b, - 0x73, 0x08, 0x6b, 0x83, 0xe0, 0xd7, 0x2e, 0x45, 0xb5, 0x13, 0x50, 0x7e, 0x0b, 0x55, 0x2b, 0xbd, 0x2c, 0x37, 0xc6, - 0xfd, 0x1f, 0x55, 0x1a, 0x89, 0xba, 0x5e, 0x96, 0x17, 0x48, 0xa3, 0x37, 0x2b, 0xfb, 0xaf, 0xce, 0x69, 0xf4, 0xe0, - 0xe8, 0x58, 0xc1, 0x7d, 0x34, 0x1a, 0xd5, 0x80, 0xae, 0xa0, 0xdb, 0x6e, 0xcd, 0x6e, 0x76, 0x3a, 0x2d, 0x05, 0x63, - 0x01, 0xd3, 0x13, 0x78, 0xdd, 0x9c, 0x41, 0x0b, 0x2b, 0xd6, 0x5b, 0xdb, 0xf1, 0x0f, 0xcb, 0x1d, 0x0e, 0x50, 0x05, - 0xdc, 0x98, 0x46, 0x88, 0x1b, 0x84, 0xb4, 0x97, 0xa4, 0xa7, 0xe2, 0x0c, 0xf4, 0x97, 0xd7, 0xc9, 0xb0, 0x9a, 0x40, - 0x73, 0xad, 0xfb, 0x06, 0x93, 0xba, 0x13, 0x31, 0xa5, 0xed, 0x82, 0x4f, 0x6b, 0xf8, 0x35, 0x88, 0xf4, 0x2a, 0x58, - 0xce, 0x72, 0xd9, 0x68, 0xc1, 0x53, 0x8a, 0x72, 0xb3, 0x92, 0x4b, 0x61, 0x63, 0xc8, 0x49, 0x06, 0xd4, 0x3b, 0xa9, - 0xba, 0xf5, 0x37, 0xd3, 0xf0, 0xe6, 0x98, 0x56, 0x42, 0x3f, 0x5e, 0x8a, 0x2f, 0xe4, 0x66, 0xec, 0x13, 0x7c, 0xd9, - 0xc4, 0x4a, 0x58, 0x9d, 0xee, 0xda, 0x82, 0x61, 0xf6, 0x17, 0xde, 0xca, 0x1a, 0x73, 0x81, 0xae, 0xa2, 0x7d, 0x76, - 0x07, 0x14, 0x40, 0x22, 0x88, 0x5d, 0xec, 0xd1, 0x4e, 0x73, 0xe7, 0x10, 0xc6, 0xee, 0x29, 0x40, 0xf8, 0x0f, 0x8e, - 0xe1, 0x75, 0xe5, 0xd3, 0xe7, 0x4b, 0x42, 0x5d, 0x10, 0x22, 0xc6, 0x59, 0x10, 0x73, 0x5c, 0x56, 0x2b, 0x1f, 0x7e, - 0x92, 0x6a, 0xd1, 0x2c, 0xf2, 0xeb, 0x25, 0x88, 0xed, 0xc0, 0x02, 0x17, 0xc1, 0x28, 0xe5, 0x37, 0x5d, 0x2a, 0xd5, - 0x4c, 0x80, 0x02, 0x94, 0xb2, 0x6c, 0x17, 0xd3, 0x9b, 0x43, 0xe1, 0xce, 0x81, 0xd0, 0xcb, 0xaf, 0xd7, 0xd7, 0xb5, - 0x9a, 0xb4, 0x66, 0x3e, 0xaf, 0x76, 0x5a, 0x65, 0x77, 0x0a, 0xcb, 0x41, 0x76, 0xe4, 0x08, 0x31, 0x62, 0x13, 0xf2, - 0x56, 0xfb, 0x3e, 0xbf, 0x99, 0x45, 0x40, 0x7d, 0x87, 0x4b, 0xeb, 0xb3, 0x0e, 0x7e, 0x67, 0x97, 0x0a, 0xb2, 0x6a, - 0xd2, 0x24, 0x1f, 0x34, 0xb7, 0x93, 0x79, 0x77, 0xa0, 0xfc, 0xc3, 0x16, 0x13, 0xff, 0xf7, 0x41, 0x83, 0xb0, 0x3e, - 0xde, 0xc1, 0x70, 0x50, 0xc9, 0x68, 0xd1, 0xc4, 0xdf, 0x25, 0x9e, 0x79, 0x02, 0xa2, 0x96, 0x4a, 0x88, 0x4c, 0x93, - 0xe1, 0x30, 0xad, 0xf5, 0xe8, 0xdc, 0x6a, 0xac, 0xed, 0x2d, 0x71, 0xfc, 0x41, 0x6b, 0xa7, 0xb5, 0x43, 0x63, 0x91, - 0xcb, 0xe0, 0xe8, 0xe8, 0xc1, 0xe1, 0x43, 0xde, 0x4d, 0x81, 0x3d, 0xd7, 0x86, 0xfa, 0x5d, 0x50, 0xdb, 0x15, 0x77, - 0x64, 0xc5, 0xed, 0x9d, 0x36, 0x54, 0x7c, 0x5f, 0x51, 0x91, 0x94, 0x8f, 0x2a, 0xb1, 0x6e, 0x6a, 0x64, 0xe5, 0x54, - 0x55, 0x7d, 0x5d, 0x44, 0x33, 0x58, 0x78, 0xf8, 0xd3, 0xc5, 0xc5, 0x3f, 0x4a, 0x01, 0x36, 0x13, 0x18, 0x02, 0xcf, - 0x44, 0x01, 0x9d, 0xc8, 0xd3, 0x34, 0x99, 0x95, 0x89, 0x98, 0x0d, 0x89, 0xbb, 0xc7, 0x6b, 0x50, 0xb5, 0x3b, 0x74, - 0x68, 0x75, 0xe8, 0xd8, 0x74, 0xc8, 0xb4, 0x6f, 0xf7, 0xb0, 0xb3, 0x36, 0x56, 0x2a, 0xd5, 0xad, 0x61, 0xd2, 0x17, - 0x10, 0xed, 0x11, 0xe6, 0xca, 0x79, 0x84, 0xb8, 0x4b, 0x73, 0xc0, 0xab, 0x6b, 0xce, 0xb3, 0xbb, 0x3b, 0x71, 0x1e, - 0xe4, 0x59, 0xba, 0x10, 0xaf, 0x4b, 0xbb, 0xc9, 0x68, 0x5e, 0xe5, 0x40, 0x02, 0x41, 0xd4, 0x2b, 0x16, 0x57, 0x25, - 0xcf, 0x80, 0x4b, 0x5c, 0xe5, 0xa3, 0xd1, 0xf2, 0x2e, 0x92, 0xf7, 0x00, 0x50, 0xa0, 0x04, 0xca, 0x94, 0x72, 0x41, - 0xe0, 0x08, 0x11, 0x24, 0x93, 0x11, 0xf5, 0x52, 0x95, 0xb5, 0x4e, 0xaf, 0xfc, 0x38, 0x85, 0x65, 0x59, 0x71, 0x82, - 0xb3, 0x45, 0x6a, 0xe4, 0xe0, 0x05, 0x95, 0x6b, 0xed, 0x88, 0x1f, 0x53, 0x1a, 0x97, 0x91, 0x55, 0x58, 0x55, 0x99, - 0x64, 0x84, 0x1f, 0x04, 0x0e, 0x5a, 0x45, 0x34, 0x7b, 0x34, 0x77, 0x16, 0xec, 0x70, 0x74, 0xb5, 0xaa, 0xce, 0x25, - 0x5d, 0x12, 0x35, 0xc2, 0x5c, 0xd4, 0x73, 0xd3, 0x68, 0xc0, 0xd3, 0xa5, 0x58, 0xa8, 0x0a, 0xb8, 0x72, 0xa9, 0xda, - 0xd3, 0x6c, 0x91, 0x0c, 0x02, 0x51, 0x3f, 0x08, 0x80, 0xf3, 0x0d, 0xbe, 0x26, 0x95, 0x58, 0x32, 0xcd, 0xf2, 0x1a, - 0x0f, 0x15, 0x51, 0x9f, 0x80, 0x95, 0x2d, 0x15, 0x21, 0x6f, 0xd5, 0x08, 0xe8, 0x45, 0x46, 0x0c, 0xba, 0x8a, 0x06, - 0x4d, 0x0c, 0xb1, 0x06, 0xe5, 0xb6, 0x0d, 0x6e, 0x1a, 0xdd, 0x48, 0x14, 0x7b, 0x08, 0xc3, 0xb7, 0x99, 0xec, 0x11, - 0x30, 0x59, 0x59, 0x73, 0x53, 0x7c, 0x01, 0x2c, 0xf5, 0x98, 0x4f, 0x75, 0x62, 0x95, 0xcf, 0x82, 0x5a, 0x02, 0x48, - 0x1a, 0xa0, 0x12, 0x8a, 0xb4, 0x2d, 0xd4, 0xa8, 0x4e, 0x7a, 0xdb, 0x1d, 0x98, 0x08, 0xfa, 0x03, 0x0b, 0x74, 0x93, - 0xd4, 0x6e, 0x62, 0xc5, 0xa1, 0xa7, 0xf0, 0x18, 0x1b, 0x6e, 0x43, 0x1b, 0xf3, 0x12, 0xd9, 0x3d, 0x41, 0x9c, 0x38, - 0xda, 0x8a, 0x06, 0x8b, 0x80, 0x8d, 0xa0, 0xb7, 0xc0, 0x5d, 0x05, 0xb3, 0xc3, 0x36, 0xca, 0x1c, 0xdd, 0xe1, 0xb7, - 0x56, 0x5a, 0xef, 0x56, 0x6b, 0xc7, 0x74, 0x0c, 0xff, 0xac, 0x3e, 0x1b, 0xf9, 0xfc, 0x29, 0xb7, 0xf4, 0xa3, 0xa4, - 0xe1, 0x1f, 0xdf, 0xb6, 0xa4, 0x4e, 0x34, 0xac, 0x8c, 0xaa, 0x46, 0x27, 0x4a, 0x00, 0xac, 0xe2, 0x68, 0x09, 0x2c, - 0x61, 0x74, 0x5c, 0x03, 0x91, 0xd2, 0x72, 0xf1, 0x9f, 0xd8, 0x15, 0x0d, 0x2b, 0x17, 0x2b, 0xde, 0xef, 0xf8, 0xc7, - 0xc7, 0x1e, 0x6b, 0xb1, 0x0e, 0xfc, 0x18, 0x9d, 0x6c, 0x54, 0x6d, 0x2b, 0xba, 0xad, 0x64, 0xbe, 0xa5, 0xe4, 0x01, - 0x55, 0x7a, 0x00, 0xa8, 0xcd, 0xe8, 0xf8, 0xbc, 0x2e, 0x9c, 0x95, 0x5b, 0xaa, 0x85, 0x62, 0x58, 0x2d, 0xfe, 0xc8, - 0x71, 0xfd, 0x1c, 0x2e, 0x5b, 0x01, 0xa4, 0x04, 0x6d, 0xd6, 0x09, 0x3a, 0xec, 0x30, 0x38, 0x64, 0x47, 0xc1, 0x11, - 0x3b, 0x0e, 0x8e, 0xd9, 0x49, 0x70, 0xc2, 0x1e, 0x04, 0x0f, 0xd8, 0x69, 0x70, 0xca, 0x1e, 0x06, 0x0f, 0xd9, 0x23, - 0x58, 0x40, 0xec, 0x71, 0xd0, 0x6e, 0xb3, 0x27, 0x30, 0xb7, 0xec, 0x69, 0xd0, 0x3e, 0x64, 0xcf, 0x82, 0xf6, 0x11, - 0x7b, 0x0e, 0x58, 0xcd, 0x22, 0xcc, 0x1d, 0x60, 0x6e, 0x8c, 0xb9, 0x43, 0xcc, 0xe5, 0x98, 0x3b, 0x82, 0xdc, 0x15, - 0x2b, 0x45, 0xc8, 0x0d, 0xa7, 0xd5, 0xee, 0x1c, 0x1e, 0x1d, 0x9f, 0x3c, 0x38, 0x7d, 0xf8, 0xe8, 0xf1, 0x93, 0xa7, - 0xcf, 0x9e, 0x3b, 0x7d, 0x76, 0x45, 0x27, 0x5f, 0xca, 0xec, 0x32, 0xd9, 0x6b, 0x1f, 0xf7, 0xd9, 0x42, 0xbd, 0xba, - 0xc9, 0x1e, 0xb0, 0x1a, 0xef, 0xfc, 0xfc, 0xa8, 0xdf, 0xd0, 0xb9, 0x8f, 0xe9, 0xc0, 0x8d, 0xc9, 0x02, 0x21, 0xdc, - 0xc5, 0x1c, 0x8f, 0xdd, 0x88, 0x03, 0x34, 0x30, 0x4c, 0xbf, 0xf0, 0xf6, 0xf6, 0xe8, 0x61, 0xac, 0x1e, 0x06, 0xea, - 0x21, 0xb2, 0x26, 0xe9, 0x5b, 0xe4, 0xca, 0x13, 0xd7, 0x95, 0x3e, 0xef, 0xa0, 0x5d, 0x89, 0x76, 0x12, 0xe9, 0xd4, - 0xff, 0x5f, 0x8e, 0x70, 0xda, 0x09, 0x8f, 0x84, 0x61, 0xec, 0xb8, 0xc7, 0xc3, 0x25, 0xe0, 0xdc, 0xf1, 0xf1, 0xde, - 0xcf, 0x97, 0xc9, 0x65, 0xbb, 0xdf, 0xdf, 0x6f, 0x3f, 0x60, 0x63, 0x9d, 0xd0, 0x11, 0x09, 0x03, 0x9d, 0x70, 0x28, - 0x12, 0xa2, 0x40, 0x7c, 0x8d, 0x49, 0x47, 0x94, 0x84, 0x25, 0x56, 0x01, 0xd5, 0xfd, 0x40, 0xd4, 0xfd, 0x10, 0xbd, - 0xc9, 0xa8, 0x7a, 0x59, 0xf5, 0xd9, 0xd9, 0xd1, 0xad, 0xac, 0x14, 0x9a, 0x90, 0xb5, 0xa9, 0x44, 0xa8, 0x05, 0x9a, - 0xc1, 0xa7, 0x63, 0x93, 0x78, 0x02, 0x89, 0xa2, 0xa9, 0x87, 0xd4, 0xd4, 0x03, 0x93, 0x75, 0xda, 0xef, 0x53, 0x93, - 0x9e, 0x8c, 0x1d, 0x00, 0xd3, 0x7f, 0xad, 0xed, 0x37, 0xc9, 0x19, 0x64, 0xf5, 0x10, 0xc3, 0xc8, 0x27, 0x58, 0xc1, - 0xe8, 0xab, 0x05, 0xa3, 0x1b, 0x7c, 0xee, 0x5d, 0x45, 0xc1, 0x22, 0xd2, 0x40, 0xea, 0x01, 0x7c, 0x1a, 0x15, 0xc1, - 0x9c, 0x7e, 0xc6, 0xe2, 0x67, 0xe0, 0x35, 0xae, 0x23, 0x04, 0x37, 0x5a, 0xa4, 0x94, 0x49, 0x99, 0x5a, 0xbc, 0x88, - 0xf0, 0x88, 0xcf, 0xa4, 0x4c, 0xa3, 0xde, 0xed, 0xe4, 0x7a, 0x70, 0x3b, 0x29, 0xbf, 0x79, 0x7f, 0xba, 0x7f, 0x96, - 0xfb, 0xee, 0x65, 0xb3, 0xe1, 0xf3, 0x3f, 0x87, 0x78, 0x96, 0xa8, 0x17, 0x0c, 0xf9, 0xd8, 0xeb, 0x5d, 0xfe, 0x59, - 0xb2, 0x7e, 0xc3, 0xca, 0xb8, 0xbf, 0x99, 0x82, 0x27, 0x8d, 0xd6, 0x13, 0xdd, 0xfb, 0x5e, 0xcf, 0xeb, 0x41, 0x9d, - 0x7f, 0x7a, 0xf7, 0x0e, 0x2c, 0xab, 0x49, 0x2e, 0x97, 0xb0, 0x09, 0x3f, 0xb4, 0xaf, 0x97, 0x30, 0x67, 0xed, 0x26, - 0xc7, 0x60, 0x6d, 0x78, 0x14, 0x1d, 0xfe, 0x34, 0x92, 0x83, 0xc3, 0x96, 0x77, 0xbf, 0xdd, 0x41, 0xe3, 0x4a, 0x33, - 0xdb, 0xdf, 0x5c, 0xf4, 0x45, 0xf3, 0x90, 0x3d, 0x6c, 0x16, 0xb0, 0xea, 0x58, 0xb3, 0xad, 0xac, 0xde, 0x97, 0xa5, - 0x0b, 0x4b, 0xac, 0x74, 0x4f, 0xf1, 0xcf, 0x91, 0xd7, 0x37, 0x0b, 0xf2, 0x75, 0xb4, 0xde, 0x3a, 0x9e, 0x9b, 0x85, - 0x3f, 0xd0, 0xd2, 0x09, 0xb4, 0x74, 0x42, 0x0d, 0xf1, 0xfd, 0x6a, 0x4b, 0x53, 0x39, 0x3b, 0x6a, 0xe6, 0xd8, 0x50, - 0x4b, 0xb7, 0x93, 0xb9, 0x80, 0xf3, 0x19, 0x30, 0x65, 0xf8, 0xd3, 0xb6, 0xdb, 0x79, 0xb2, 0xd1, 0x0e, 0x8d, 0xbb, - 0xcd, 0xfc, 0x63, 0x71, 0x0c, 0xb7, 0x14, 0x7b, 0xe2, 0x0d, 0x7e, 0xde, 0xa6, 0xcd, 0xbc, 0xf6, 0x01, 0xbe, 0x00, - 0xfd, 0xda, 0x0f, 0x4b, 0xc6, 0xf7, 0xf1, 0xfc, 0x2e, 0xba, 0xad, 0x94, 0x67, 0x87, 0xdd, 0xb2, 0xd1, 0xf0, 0x60, - 0x48, 0xfd, 0xfd, 0xb0, 0xdd, 0xac, 0x9a, 0x9c, 0xe1, 0x73, 0x23, 0xd4, 0x41, 0xe1, 0x32, 0xd3, 0xea, 0x5b, 0xd9, - 0xaa, 0xd8, 0xf9, 0x57, 0xd8, 0x01, 0x58, 0x58, 0xf6, 0x5c, 0xf8, 0xd2, 0x3b, 0xc8, 0x1a, 0x6e, 0x75, 0xc6, 0x7b, - 0x27, 0x41, 0xcb, 0x23, 0xec, 0x84, 0x74, 0xde, 0x4c, 0x30, 0xbd, 0x13, 0xb8, 0x49, 0xb3, 0xc2, 0xa7, 0x23, 0x0b, - 0x5a, 0x19, 0xe2, 0x9d, 0x39, 0x8d, 0x54, 0x1c, 0x00, 0x7a, 0xb2, 0x0c, 0x9e, 0xc6, 0xf4, 0x54, 0xc2, 0xd3, 0x80, - 0x9e, 0xf2, 0x50, 0xc3, 0x4b, 0xb4, 0x0e, 0xd3, 0x67, 0xcd, 0x2a, 0xa5, 0x44, 0x38, 0xa1, 0x85, 0x77, 0xd0, 0x51, - 0x6e, 0x01, 0x6c, 0xa2, 0xc6, 0x80, 0x66, 0x90, 0x82, 0x3c, 0x42, 0x73, 0x98, 0xcb, 0x34, 0x8c, 0xce, 0xfd, 0xe3, - 0xde, 0xe4, 0xc0, 0xed, 0x34, 0xe1, 0xdd, 0x0b, 0xe0, 0x09, 0xbf, 0x64, 0x71, 0xf8, 0x36, 0x12, 0xb5, 0xb1, 0x09, - 0xee, 0xe5, 0xc6, 0x61, 0xbc, 0x7f, 0xd2, 0x02, 0x0e, 0xe1, 0xb1, 0xcb, 0xf8, 0xb6, 0xc5, 0xd2, 0x5b, 0xf8, 0x13, - 0xd9, 0xd3, 0x90, 0x29, 0x80, 0x68, 0x4b, 0xdd, 0x7a, 0x6c, 0x9e, 0x5e, 0xe2, 0x56, 0xe8, 0x97, 0x50, 0xe1, 0x69, - 0x9f, 0x0a, 0xcf, 0x21, 0x05, 0x89, 0xdc, 0x10, 0xf4, 0x28, 0x3a, 0xe1, 0xc8, 0xb6, 0xdd, 0xbd, 0xcd, 0xd4, 0xbc, - 0x2a, 0xcf, 0xd2, 0xcc, 0xfd, 0x3d, 0x67, 0x22, 0xcd, 0x14, 0x7b, 0x17, 0x6d, 0x16, 0x7b, 0x12, 0x6d, 0x14, 0xbb, - 0xb7, 0xa5, 0xd8, 0xeb, 0xcd, 0x62, 0x7f, 0xe5, 0x96, 0xa5, 0x31, 0xb9, 0x7f, 0x08, 0x43, 0x3e, 0x44, 0x64, 0x85, - 0x3f, 0xa6, 0xd0, 0xa3, 0xc8, 0xcc, 0x55, 0x15, 0x5e, 0x44, 0xe2, 0xac, 0x45, 0xa2, 0x0e, 0x7d, 0xd3, 0xc4, 0x89, - 0x23, 0xe7, 0xfa, 0x7c, 0x39, 0x50, 0x2c, 0xb4, 0xce, 0x10, 0xb5, 0xab, 0x80, 0x66, 0xf5, 0x80, 0x61, 0x36, 0x30, - 0xd5, 0x0b, 0x80, 0x1f, 0x8a, 0x27, 0x4f, 0x6f, 0x69, 0x43, 0x2f, 0x1a, 0x04, 0x1f, 0x98, 0x6c, 0x78, 0x38, 0xec, - 0x13, 0xbf, 0x2b, 0xf0, 0xf9, 0x88, 0x9e, 0xb5, 0x41, 0x49, 0x1e, 0xc8, 0x00, 0xc2, 0xe2, 0xf4, 0xb2, 0x10, 0x60, - 0x41, 0x3e, 0xf6, 0x80, 0x71, 0x2a, 0xa3, 0xfc, 0x86, 0x19, 0xf7, 0x74, 0x46, 0x16, 0x02, 0x5c, 0xc5, 0x33, 0x03, - 0xb2, 0x8b, 0xfe, 0x36, 0x40, 0x68, 0xd1, 0xd7, 0x06, 0x48, 0x6b, 0x86, 0xe7, 0x41, 0xa2, 0x80, 0x5b, 0x5e, 0xfc, - 0xcf, 0xa4, 0x05, 0x8f, 0x76, 0x9d, 0x43, 0xc2, 0xd2, 0x2e, 0x47, 0x4e, 0x01, 0x7d, 0xc4, 0xdf, 0x46, 0x05, 0xc4, - 0x15, 0xeb, 0x84, 0x05, 0x05, 0x58, 0x1b, 0x62, 0x1a, 0x3c, 0x8c, 0xe1, 0x01, 0x83, 0x56, 0xfa, 0x03, 0x78, 0xe8, - 0x58, 0x68, 0xf2, 0x92, 0x60, 0x87, 0xc0, 0x49, 0xea, 0x1b, 0xf9, 0x95, 0xa8, 0x1c, 0x3d, 0x04, 0xb0, 0x0a, 0x10, - 0xf5, 0x4a, 0x17, 0x47, 0x41, 0xf1, 0x24, 0xf1, 0xb1, 0x63, 0xc2, 0x5f, 0x02, 0x9d, 0x25, 0xea, 0xfd, 0x19, 0xc9, - 0xaa, 0x7b, 0x6f, 0xc9, 0x57, 0x6c, 0xe7, 0xde, 0x32, 0x5b, 0xdd, 0xc7, 0x9f, 0x52, 0xfc, 0xa0, 0xf0, 0x00, 0xdc, - 0x6f, 0xe5, 0x7d, 0x0e, 0xb0, 0xd8, 0x96, 0x52, 0xde, 0x67, 0x75, 0x1c, 0xb0, 0x0c, 0x97, 0x37, 0x81, 0x33, 0x8c, - 0x8a, 0xaf, 0x0e, 0xfb, 0x23, 0x70, 0x52, 0x94, 0x16, 0x1d, 0xf6, 0x7b, 0xe0, 0x14, 0xdc, 0x61, 0xbf, 0x05, 0xce, - 0x20, 0x9d, 0x3b, 0xec, 0xd7, 0xc0, 0x19, 0x17, 0x0e, 0xfb, 0x84, 0xc6, 0x5a, 0x10, 0xac, 0xa6, 0x0e, 0xfb, 0x18, - 0x38, 0x25, 0x9d, 0x86, 0x00, 0x51, 0xc1, 0xe1, 0xf0, 0xf3, 0x21, 0x70, 0xf2, 0xd4, 0x61, 0x17, 0xf0, 0x03, 0x25, - 0x1f, 0xc3, 0xf7, 0x91, 0x03, 0xc2, 0x83, 0x83, 0x85, 0xc6, 0x0e, 0x48, 0x10, 0x0e, 0xd6, 0x5c, 0x3a, 0xec, 0x3d, - 0x3c, 0x65, 0x0e, 0xfb, 0x25, 0x70, 0x60, 0x3c, 0x7f, 0xcd, 0xf3, 0x04, 0xd2, 0x9e, 0x05, 0xce, 0x24, 0x71, 0xd8, - 0x3b, 0xf8, 0x2a, 0x77, 0xd8, 0xdb, 0xc0, 0x89, 0xa0, 0xaa, 0x37, 0xf0, 0x31, 0x54, 0xfc, 0x1a, 0x7a, 0x07, 0x3f, - 0xaf, 0x02, 0x67, 0x01, 0xaa, 0x14, 0x64, 0x3f, 0x87, 0x06, 0xa1, 0x82, 0x9f, 0x03, 0x27, 0x9e, 0x38, 0xec, 0x47, - 0x28, 0x5c, 0x7c, 0x85, 0x3a, 0x5e, 0x40, 0x32, 0x34, 0xf9, 0x52, 0x34, 0x04, 0x4d, 0xfe, 0x14, 0x38, 0xd7, 0x13, - 0x67, 0xc5, 0x72, 0x18, 0xe2, 0xdb, 0x24, 0xe6, 0xbf, 0xf1, 0xc0, 0x19, 0xb5, 0x46, 0xa7, 0xa3, 0x91, 0xc3, 0x40, - 0xa8, 0x4e, 0xfe, 0x9a, 0xf3, 0xeb, 0x67, 0x15, 0x26, 0x46, 0x7c, 0x30, 0x7c, 0x00, 0x89, 0x7f, 0xcd, 0x23, 0x78, - 0x1b, 0x51, 0x01, 0x78, 0x06, 0x01, 0xf5, 0x3d, 0x64, 0x3f, 0x80, 0x84, 0xe1, 0x11, 0x24, 0xfd, 0x3d, 0xff, 0x9d, - 0x6a, 0xa0, 0x02, 0x03, 0x90, 0xab, 0xf1, 0xdb, 0xe3, 0xd1, 0xf1, 0x30, 0x86, 0xd7, 0xa4, 0x84, 0xfa, 0xf0, 0x6b, - 0x7e, 0x14, 0x43, 0xe1, 0x41, 0x0a, 0x32, 0x70, 0xe0, 0xb4, 0xe8, 0x29, 0xfb, 0x99, 0x0f, 0xdf, 0x4e, 0x73, 0xda, - 0xca, 0x18, 0xf1, 0x41, 0x3c, 0x04, 0xc8, 0x52, 0x59, 0xfc, 0xfd, 0x96, 0x7c, 0xe0, 0x55, 0xe0, 0x9c, 0x46, 0x9d, - 0x01, 0xef, 0x40, 0xf1, 0x77, 0xd7, 0x19, 0x0c, 0xe9, 0xb8, 0x13, 0x75, 0x60, 0x34, 0x83, 0x79, 0x91, 0x2e, 0xae, - 0xf3, 0x7c, 0x88, 0x40, 0x18, 0x9c, 0x9e, 0x42, 0x2f, 0xe3, 0xe8, 0x75, 0x85, 0x5f, 0x1f, 0x8f, 0x1e, 0xf2, 0x08, - 0xea, 0xff, 0x39, 0x2a, 0xaa, 0xdf, 0x41, 0x78, 0x16, 0x1d, 0x6d, 0x61, 0x4a, 0x1e, 0x7f, 0x40, 0x33, 0xbf, 0x33, - 0xec, 0x9c, 0x3c, 0x6c, 0x03, 0xec, 0xe2, 0x8b, 0xb7, 0xd8, 0xda, 0x83, 0xd1, 0x71, 0x0b, 0x5f, 0x32, 0xd4, 0x4b, - 0x79, 0x81, 0x95, 0x9c, 0x1c, 0x3d, 0x3c, 0xe6, 0x43, 0x4a, 0x2c, 0x93, 0xf4, 0x2b, 0x8d, 0xfe, 0x14, 0xc7, 0x13, - 0x17, 0xc9, 0xb4, 0xcc, 0xa1, 0x27, 0xc3, 0xb8, 0x7d, 0x74, 0x88, 0x09, 0x8b, 0x28, 0x53, 0xc0, 0xb9, 0xc1, 0x4f, - 0x4f, 0x07, 0xf0, 0x20, 0x52, 0x4f, 0x07, 0xf4, 0x32, 0xfe, 0xf0, 0x3a, 0x7b, 0x07, 0x3d, 0x85, 0x7e, 0x9e, 0xb4, - 0x30, 0xe1, 0x57, 0x50, 0x4f, 0x9c, 0xe8, 0x21, 0xfe, 0xc3, 0xec, 0xdf, 0x9f, 0x63, 0x83, 0xd8, 0x43, 0x78, 0xb6, - 0x73, 0xbe, 0x4e, 0xa2, 0xaf, 0x09, 0x7c, 0x37, 0x1c, 0x3c, 0x38, 0xc1, 0xef, 0xa6, 0xd1, 0xf8, 0x79, 0x15, 0x61, - 0xbd, 0xad, 0x16, 0xd5, 0xfc, 0x21, 0xf9, 0xc6, 0xe9, 0xf3, 0xe3, 0xe3, 0x93, 0x41, 0x07, 0x7b, 0x70, 0x81, 0x06, - 0x15, 0xec, 0xcf, 0x69, 0x4c, 0x15, 0x5e, 0xc4, 0xcf, 0xa0, 0xe5, 0x87, 0x0f, 0x0f, 0x3b, 0x31, 0x74, 0xf6, 0xe6, - 0xf7, 0xa1, 0xf8, 0x9a, 0xf2, 0x4a, 0x84, 0x3d, 0x60, 0xc7, 0xc3, 0x87, 0x27, 0x0f, 0x22, 0x7c, 0x7f, 0x41, 0x75, - 0x9d, 0x8e, 0x06, 0xf1, 0x29, 0xd6, 0xf5, 0x11, 0x87, 0x73, 0x74, 0x7a, 0x38, 0xa4, 0xb6, 0x3e, 0x52, 0xaf, 0x3b, - 0xa3, 0x23, 0xf8, 0x87, 0xaf, 0xd4, 0x55, 0xfd, 0xfa, 0x0b, 0x14, 0x8d, 0xf9, 0xb0, 0x0d, 0x8f, 0x72, 0xe2, 0x1e, - 0xc2, 0x88, 0x86, 0x87, 0x0e, 0x1b, 0x3e, 0x9a, 0xcd, 0xde, 0x13, 0x04, 0xdb, 0x47, 0x0f, 0xc5, 0x7b, 0xf9, 0x75, - 0x81, 0x55, 0x0f, 0x08, 0x68, 0xc3, 0x64, 0x4a, 0x35, 0x9f, 0x3c, 0xc4, 0x7f, 0xf4, 0x4e, 0x55, 0xeb, 0xf7, 0x7c, - 0x38, 0x16, 0x93, 0xd2, 0xe6, 0x0f, 0x5b, 0xf8, 0xc5, 0x28, 0xf9, 0x7d, 0x50, 0x24, 0x88, 0x46, 0x83, 0x0e, 0xfe, - 0x0f, 0x52, 0xd2, 0x8b, 0xb7, 0x12, 0x67, 0x47, 0xa3, 0x68, 0x04, 0x83, 0x1b, 0xe5, 0xbf, 0x97, 0xd5, 0xaf, 0x8f, - 0x60, 0x78, 0x9d, 0xce, 0xe9, 0x80, 0xca, 0xcc, 0x7f, 0x2e, 0x13, 0xc2, 0xe3, 0x16, 0xd5, 0x32, 0x8e, 0xde, 0x97, - 0x83, 0x8b, 0x1c, 0x67, 0x12, 0xff, 0x41, 0x02, 0x5a, 0xe1, 0x64, 0x2d, 0xa7, 0x62, 0x39, 0x8c, 0x3f, 0x10, 0x6a, - 0x0e, 0x1f, 0x20, 0xbc, 0xd4, 0x34, 0x0e, 0x23, 0xc0, 0x42, 0x78, 0xa7, 0x5e, 0x9f, 0xb6, 0xf0, 0x1f, 0x64, 0x12, - 0xe4, 0x08, 0xae, 0xf0, 0xf8, 0xea, 0x1a, 0x66, 0x71, 0x38, 0x1a, 0xe1, 0x94, 0xd0, 0x60, 0x54, 0xb1, 0x09, 0x28, - 0x70, 0x8b, 0xd7, 0xd7, 0x72, 0xb9, 0x50, 0x42, 0x25, 0xa1, 0x73, 0xf2, 0x70, 0x00, 0xeb, 0xe3, 0xfd, 0x30, 0x89, - 0x32, 0x9c, 0xa5, 0x78, 0x78, 0x1c, 0x1f, 0xc7, 0x94, 0x30, 0x86, 0x4e, 0x1e, 0xe1, 0x94, 0xc3, 0x28, 0x92, 0x6f, - 0x17, 0x0b, 0x81, 0x6e, 0xf8, 0xb5, 0x44, 0x90, 0x51, 0x8b, 0x9f, 0x9c, 0x42, 0xd9, 0x34, 0xfa, 0xf6, 0xfc, 0x75, - 0x01, 0x33, 0x7a, 0xc2, 0x4f, 0x46, 0x91, 0x7a, 0xff, 0xad, 0x9c, 0xd0, 0x17, 0xad, 0xd1, 0x31, 0x26, 0x5d, 0x67, - 0xd4, 0xd7, 0x07, 0xf1, 0x88, 0x30, 0xe4, 0x0d, 0xe0, 0x40, 0xfc, 0x6c, 0x34, 0xca, 0x05, 0x16, 0x47, 0xb8, 0x08, - 0xff, 0x40, 0x68, 0x83, 0xba, 0x7b, 0xca, 0x4f, 0xe0, 0x45, 0xac, 0x12, 0x39, 0x80, 0x3f, 0x04, 0x66, 0x73, 0xb9, - 0xda, 0xff, 0x10, 0x40, 0xc1, 0xf1, 0x02, 0xdc, 0xa3, 0x21, 0xf4, 0xf0, 0x0f, 0x82, 0xcb, 0xf0, 0x10, 0xff, 0x61, - 0x01, 0x6c, 0xec, 0x61, 0x8b, 0xc3, 0xdc, 0xd1, 0x9b, 0x9d, 0x27, 0x47, 0x3e, 0x38, 0x89, 0x01, 0x6f, 0xfe, 0x90, - 0xe8, 0x08, 0x7d, 0x68, 0x21, 0x3a, 0xfe, 0x21, 0xd1, 0xb1, 0xd3, 0x1a, 0x74, 0x22, 0x7a, 0x17, 0x58, 0x73, 0xfa, - 0x20, 0xe6, 0x38, 0xb8, 0x3f, 0x04, 0x42, 0x3e, 0x78, 0x70, 0x7a, 0xfa, 0xf0, 0x21, 0xbe, 0x52, 0xdd, 0xfa, 0xb5, - 0xac, 0x1e, 0xa5, 0x84, 0x64, 0xad, 0xf8, 0x08, 0xe9, 0xe4, 0x1f, 0xd4, 0x47, 0xf8, 0x1f, 0x87, 0x7e, 0xa4, 0xc9, - 0x94, 0x0b, 0x4c, 0x10, 0xcf, 0xd4, 0x10, 0x2c, 0x91, 0xe1, 0x21, 0x0c, 0x20, 0x7d, 0xff, 0x9c, 0x46, 0xd3, 0xc2, - 0xd1, 0xab, 0x25, 0xa7, 0xb0, 0x66, 0x1a, 0xbd, 0xc3, 0x4e, 0xe2, 0x4c, 0xe3, 0xc7, 0x9f, 0x2c, 0x7a, 0x78, 0x72, - 0x12, 0x0f, 0xb1, 0xa3, 0x9f, 0xb0, 0x59, 0x04, 0xe3, 0x27, 0xb1, 0xf8, 0x06, 0xd1, 0xf1, 0x31, 0x0e, 0xf7, 0xd3, - 0x6c, 0x5e, 0xcc, 0x80, 0x78, 0x3f, 0x3c, 0x7c, 0xd0, 0x1a, 0xc2, 0x8a, 0xfa, 0x24, 0x07, 0x78, 0x18, 0x0f, 0x0e, - 0x1f, 0x00, 0x00, 0x3e, 0xd1, 0x7a, 0x7b, 0x30, 0x38, 0x39, 0x45, 0xbe, 0xf1, 0xa9, 0x9c, 0x15, 0xef, 0xc7, 0x54, - 0x60, 0x04, 0xe4, 0x00, 0x12, 0x7e, 0xa1, 0xd5, 0x38, 0x6c, 0xe3, 0x42, 0xfe, 0x44, 0x8b, 0x8c, 0xf0, 0xe4, 0x41, - 0xfb, 0xf8, 0x14, 0x26, 0x76, 0x9a, 0x0c, 0x33, 0x24, 0xf0, 0xb4, 0x50, 0x1e, 0xb6, 0x1f, 0x3e, 0x80, 0xde, 0x4d, - 0xdf, 0x57, 0xf1, 0xef, 0xd1, 0x94, 0xa8, 0xf1, 0x08, 0x61, 0x36, 0x4d, 0xca, 0x6a, 0xf1, 0xae, 0x94, 0xf4, 0x98, - 0x43, 0xa3, 0xd3, 0x3c, 0x8e, 0xa3, 0xf2, 0xbd, 0x48, 0x18, 0x40, 0x3d, 0x59, 0xf4, 0x2d, 0xfa, 0x92, 0xab, 0xc5, - 0x34, 0xe4, 0xd1, 0x90, 0xd2, 0x08, 0x87, 0x81, 0x9b, 0x0d, 0x71, 0x33, 0x12, 0x72, 0x86, 0xa3, 0x63, 0x04, 0x0f, - 0x12, 0x20, 0x81, 0xdd, 0x08, 0x0d, 0x7c, 0x1b, 0x3e, 0x1e, 0x00, 0x28, 0x06, 0xa7, 0xbc, 0x03, 0x43, 0xd6, 0xd4, - 0x28, 0x3a, 0xc6, 0x7c, 0x7a, 0xfd, 0x9d, 0x96, 0xd4, 0x91, 0x48, 0x20, 0x00, 0x0d, 0x23, 0x00, 0x08, 0x54, 0x36, - 0x7b, 0xcb, 0xd5, 0x1a, 0xe3, 0x9c, 0x9f, 0x22, 0x2c, 0x31, 0x89, 0x10, 0x08, 0x88, 0xd2, 0xc3, 0x53, 0x7a, 0x47, - 0x30, 0x44, 0x23, 0x28, 0xc0, 0xe9, 0x55, 0x03, 0x02, 0x88, 0x64, 0x0b, 0xe9, 0xcb, 0x2c, 0x9a, 0x45, 0x8b, 0xe8, - 0xfa, 0xd9, 0x8c, 0xc6, 0x34, 0x1a, 0xc2, 0x98, 0x66, 0x2f, 0x7e, 0x9e, 0xcd, 0x47, 0x23, 0x1a, 0x50, 0x34, 0x00, - 0xec, 0x98, 0xf1, 0x62, 0x8e, 0x73, 0x74, 0x7a, 0x7c, 0x08, 0x73, 0x2a, 0xd1, 0x30, 0x6e, 0xc5, 0x03, 0xdc, 0x6d, - 0x9d, 0x03, 0xc0, 0x86, 0xc3, 0xa8, 0x35, 0xc4, 0xbd, 0xd7, 0xfc, 0xfa, 0x75, 0x21, 0xd0, 0x88, 0x13, 0x3e, 0xc8, - 0x39, 0xc4, 0xf1, 0x22, 0x3c, 0x7e, 0x1f, 0x70, 0x80, 0x9f, 0x4c, 0x3c, 0x39, 0x39, 0x3c, 0x44, 0xdc, 0x13, 0x23, - 0x14, 0x08, 0xf2, 0xae, 0x5c, 0x0c, 0x8a, 0x1c, 0x59, 0x17, 0x12, 0x55, 0x24, 0xab, 0xef, 0x16, 0x6f, 0x89, 0xae, - 0xb6, 0x4f, 0x1e, 0xe2, 0x04, 0x94, 0xb0, 0xce, 0xde, 0x08, 0xe6, 0x76, 0x3a, 0x38, 0x3a, 0x6e, 0xc3, 0x08, 0xd4, - 0x42, 0x88, 0x4e, 0x5b, 0x0f, 0x3a, 0x58, 0x22, 0x1b, 0x2e, 0x44, 0x89, 0xd1, 0x51, 0x74, 0x74, 0x02, 0xb5, 0xaa, - 0xa5, 0xc1, 0x4f, 0x07, 0xc7, 0x0f, 0xf0, 0xb5, 0x9c, 0x80, 0x0c, 0x40, 0xf8, 0x7d, 0x8c, 0x70, 0x29, 0x93, 0xe7, - 0x19, 0x20, 0x6d, 0xd4, 0x3a, 0xee, 0x74, 0x86, 0xf8, 0x9a, 0x7e, 0xe3, 0x40, 0x17, 0x60, 0x84, 0xf0, 0x0f, 0xde, - 0xcd, 0x4a, 0xe2, 0x30, 0x64, 0xc2, 0xbb, 0x93, 0xe8, 0x98, 0xd6, 0xbe, 0x5c, 0x55, 0x30, 0x3a, 0x5c, 0xb0, 0x72, - 0x51, 0xc9, 0xb7, 0x32, 0xcb, 0xaf, 0x25, 0x89, 0x85, 0xb9, 0xb1, 0x10, 0x14, 0x58, 0x28, 0xbc, 0xcb, 0x15, 0x77, - 0x74, 0x72, 0xda, 0x41, 0x52, 0x56, 0x21, 0xa1, 0x18, 0xc2, 0x23, 0x92, 0xa6, 0x8a, 0xbf, 0x15, 0x78, 0x02, 0x8f, - 0xcf, 0xca, 0x0a, 0xa0, 0x05, 0x5c, 0x65, 0x34, 0x84, 0x29, 0xad, 0xf2, 0x69, 0x54, 0xe5, 0x44, 0x01, 0x0f, 0x8f, - 0x60, 0x30, 0x84, 0xe6, 0x00, 0xed, 0x21, 0x14, 0x95, 0xac, 0x04, 0x90, 0xa1, 0x83, 0xc3, 0xfa, 0xe9, 0x45, 0x85, - 0xb8, 0x0c, 0x1c, 0x1f, 0xa0, 0xa4, 0xe9, 0x3d, 0x11, 0x22, 0x7c, 0x2b, 0xa7, 0xf9, 0x57, 0x29, 0x7a, 0x20, 0xa9, - 0x53, 0x0b, 0x1e, 0xa7, 0xe1, 0xd5, 0xb5, 0x40, 0xa3, 0x88, 0x96, 0xb8, 0xb5, 0x1b, 0xfd, 0x34, 0x72, 0x95, 0xd8, - 0x9e, 0x84, 0xcb, 0x15, 0xd3, 0x41, 0x5e, 0xbf, 0xf2, 0x45, 0xe9, 0xe6, 0x25, 0x49, 0xb2, 0x56, 0x4a, 0x59, 0x7a, - 0xea, 0x58, 0x83, 0x3c, 0xb9, 0x8a, 0x8a, 0x64, 0x06, 0xba, 0x62, 0x76, 0xa6, 0x4e, 0xd3, 0x76, 0x33, 0x0c, 0xfd, - 0x80, 0xe9, 0x45, 0x18, 0x81, 0xe8, 0x9a, 0xf5, 0xa5, 0x32, 0xa9, 0x0e, 0x19, 0x90, 0x4e, 0x99, 0x8b, 0x63, 0x0b, - 0x51, 0x18, 0xa9, 0xd8, 0xf8, 0xa0, 0xe2, 0x96, 0x18, 0x3d, 0xca, 0xeb, 0xe6, 0x21, 0x45, 0xba, 0x7e, 0x99, 0x55, - 0xd0, 0x85, 0xcb, 0xa2, 0xcf, 0xda, 0x27, 0x20, 0x4a, 0x5f, 0x46, 0xfd, 0xf0, 0x32, 0x3f, 0x3f, 0x6f, 0x9f, 0xec, - 0x91, 0xd2, 0x77, 0x7e, 0x7e, 0x2a, 0x1e, 0xf0, 0x6f, 0xdf, 0xc4, 0xed, 0xc6, 0xfe, 0x7d, 0xe2, 0x66, 0x8c, 0x1f, - 0x48, 0xbe, 0xfe, 0xc4, 0x6f, 0x6f, 0xdd, 0x4f, 0x3c, 0xc4, 0x11, 0xb3, 0x4f, 0xdc, 0xa7, 0x3d, 0x12, 0x71, 0x42, - 0x28, 0xbc, 0x44, 0xcb, 0x19, 0xfc, 0xeb, 0x9b, 0x88, 0xcd, 0x9f, 0xf8, 0x65, 0x52, 0x3f, 0x5d, 0x6e, 0x42, 0x38, - 0xef, 0xed, 0x81, 0x9a, 0x50, 0x09, 0x35, 0xa1, 0x12, 0x6a, 0x42, 0x25, 0xd4, 0x84, 0xca, 0x04, 0xd1, 0x3f, 0xea, - 0xa1, 0x96, 0x42, 0xc6, 0x16, 0x29, 0x53, 0xbf, 0x42, 0xb3, 0x07, 0x5a, 0x27, 0x7b, 0xc6, 0xd8, 0xa1, 0x6d, 0x15, - 0x5b, 0x0d, 0x18, 0x5b, 0x13, 0xa5, 0xb5, 0xe3, 0xe0, 0x9f, 0x98, 0x3b, 0xde, 0xd7, 0xd4, 0xb2, 0x57, 0x5b, 0xd5, - 0x32, 0x9c, 0x49, 0x52, 0xcd, 0x76, 0x45, 0x3c, 0x92, 0xea, 0xf2, 0x01, 0x29, 0x66, 0x26, 0x48, 0x5e, 0x03, 0x93, - 0xba, 0xa8, 0x85, 0x9c, 0x92, 0x96, 0x06, 0x3a, 0xd3, 0xb0, 0x72, 0x0b, 0xb4, 0x50, 0x2a, 0x03, 0xa5, 0x8e, 0xe5, - 0xda, 0x20, 0x80, 0x94, 0x42, 0x47, 0x13, 0xba, 0xda, 0x31, 0xaa, 0x2e, 0x68, 0x09, 0x23, 0x8d, 0x05, 0x2b, 0xc8, - 0xa8, 0x82, 0x4c, 0x7e, 0x8c, 0xea, 0x8c, 0xcc, 0x3e, 0xa2, 0xec, 0x92, 0xb2, 0x4b, 0x9d, 0x9d, 0xab, 0x6c, 0xa1, - 0x24, 0xe6, 0x94, 0x9d, 0xeb, 0x6c, 0xd4, 0xd9, 0x60, 0x26, 0x4a, 0x98, 0x86, 0x5c, 0xa8, 0x6a, 0x46, 0xb7, 0x7a, - 0x1e, 0xd9, 0xd6, 0x5c, 0xd0, 0x35, 0xb5, 0x9e, 0x44, 0x66, 0xe2, 0x7b, 0x4b, 0x50, 0xd0, 0x48, 0x07, 0x02, 0xfd, - 0x4c, 0xfe, 0x0e, 0x56, 0xeb, 0xba, 0x12, 0x14, 0xbd, 0xa3, 0xa4, 0xf7, 0x59, 0x19, 0x51, 0x3f, 0x25, 0x14, 0x05, - 0xe8, 0x2c, 0xf4, 0x5b, 0xad, 0xc3, 0xf6, 0x61, 0xeb, 0xb4, 0x97, 0xec, 0xb7, 0x3b, 0xfe, 0xc3, 0x4e, 0x40, 0x86, - 0x08, 0x20, 0xa4, 0x68, 0x80, 0x39, 0xe8, 0xf8, 0x47, 0xde, 0x7e, 0xdb, 0x6f, 0x1d, 0x1f, 0x37, 0xf1, 0x0f, 0x7b, - 0x5c, 0xe9, 0xcf, 0x8e, 0x5a, 0x47, 0xc7, 0xbd, 0xe4, 0x60, 0xed, 0x23, 0x37, 0x69, 0x60, 0x41, 0xef, 0x80, 0x3e, - 0x62, 0xf8, 0xbd, 0x99, 0xde, 0x37, 0x1b, 0x76, 0x9e, 0xc7, 0x00, 0x18, 0x61, 0x8a, 0x43, 0xa8, 0xaa, 0xb7, 0x31, - 0x01, 0x51, 0xbd, 0x0d, 0x74, 0xa4, 0x5e, 0x80, 0x1c, 0xa8, 0xda, 0x9f, 0x12, 0x37, 0x6b, 0xf0, 0x7d, 0x57, 0xe4, - 0x57, 0xf8, 0x6d, 0x13, 0xa3, 0xe7, 0x01, 0x4c, 0x45, 0x6e, 0x69, 0xe7, 0x42, 0x5d, 0xcd, 0x12, 0x73, 0x07, 0x32, - 0x37, 0xb7, 0x73, 0xa1, 0xee, 0x66, 0x8e, 0xb9, 0x51, 0x00, 0xe0, 0xc3, 0x9c, 0xca, 0x8f, 0x9a, 0x04, 0x49, 0x33, - 0x29, 0x2f, 0xb8, 0xea, 0x36, 0xa0, 0x5b, 0x22, 0xce, 0x6c, 0x65, 0x52, 0x91, 0xce, 0xf0, 0x86, 0x15, 0x6d, 0xcd, - 0x69, 0x31, 0x6d, 0xc6, 0xc1, 0x8c, 0x06, 0xfe, 0xd9, 0xe7, 0x74, 0xed, 0x46, 0xab, 0x77, 0x78, 0xd2, 0x0a, 0xda, - 0x78, 0x54, 0x1c, 0x75, 0xed, 0x4c, 0xe8, 0xda, 0x99, 0xd2, 0xb5, 0x33, 0xa5, 0x6b, 0xa3, 0x02, 0x6f, 0xb5, 0xfd, - 0x5b, 0x5e, 0x73, 0xbf, 0x49, 0xb4, 0x2f, 0x8f, 0x70, 0xd6, 0x70, 0xab, 0xdb, 0x5b, 0x20, 0x83, 0x89, 0x65, 0xff, - 0x28, 0x4a, 0x63, 0xfe, 0x04, 0x80, 0xb5, 0x00, 0x2c, 0x68, 0xe5, 0x6e, 0xc1, 0x10, 0x71, 0x71, 0x2b, 0xaa, 0xb0, - 0x1e, 0xc5, 0xa7, 0xa7, 0xcc, 0xc9, 0xe7, 0xe1, 0x21, 0x59, 0x8f, 0xe1, 0xdb, 0x44, 0xd0, 0x8c, 0x44, 0xd0, 0x8c, - 0x44, 0xd0, 0x0c, 0xac, 0x84, 0xe9, 0xc2, 0x54, 0xd6, 0x8f, 0x42, 0xdc, 0x12, 0x80, 0x15, 0x84, 0x41, 0x0c, 0xe1, - 0x5b, 0xea, 0xf5, 0x5a, 0xe3, 0x6d, 0x0c, 0xda, 0x26, 0x4a, 0xc2, 0x0f, 0x9d, 0x5d, 0xd7, 0x7d, 0xfe, 0xbb, 0x86, - 0xf6, 0x3e, 0xde, 0xa8, 0xf3, 0xa8, 0x72, 0x5b, 0xe8, 0xba, 0xe2, 0x14, 0x4e, 0x8f, 0xc8, 0x42, 0x40, 0x36, 0x1b, - 0xe9, 0x92, 0xfe, 0x75, 0xed, 0x24, 0xb0, 0xa0, 0x04, 0xf6, 0x3d, 0x12, 0x5f, 0xb9, 0x09, 0x4d, 0xa0, 0x3d, 0x6e, - 0xa5, 0xbb, 0x9c, 0x60, 0x09, 0x5d, 0x74, 0x9b, 0x57, 0x31, 0xaf, 0x7a, 0x59, 0x58, 0x60, 0xcc, 0xc7, 0x80, 0x12, - 0x65, 0xd4, 0x66, 0x3c, 0xc4, 0x1c, 0x7e, 0x8b, 0xe8, 0x48, 0xcf, 0x07, 0xf1, 0xf3, 0x77, 0x64, 0x9d, 0x79, 0x84, - 0x85, 0xa6, 0x8e, 0x0a, 0x5f, 0x51, 0x6c, 0xa3, 0x70, 0x77, 0x57, 0x78, 0xb4, 0xd3, 0xdb, 0xba, 0x4b, 0x3b, 0x25, - 0x52, 0x36, 0xae, 0x50, 0x35, 0x47, 0xbf, 0xa9, 0x13, 0x7b, 0x90, 0xe8, 0x59, 0x34, 0x9b, 0xc0, 0x9a, 0x1b, 0x60, - 0x95, 0xf2, 0x3b, 0x7d, 0x90, 0x13, 0x5b, 0xa7, 0x3e, 0xaf, 0xe0, 0x69, 0xeb, 0xd5, 0x2b, 0xa2, 0xc5, 0x1e, 0x10, - 0x15, 0xd3, 0x82, 0x32, 0x6d, 0x4f, 0xf8, 0xcd, 0xf7, 0xbe, 0xf9, 0xba, 0xf5, 0x9b, 0x32, 0xfd, 0xde, 0x37, 0x2f, - 0xb7, 0x7d, 0x33, 0x4d, 0x6e, 0x5c, 0xb5, 0x76, 0x2a, 0xcb, 0x8c, 0x4d, 0x6e, 0x52, 0xe3, 0x01, 0xc6, 0xca, 0xc7, - 0x5f, 0x11, 0xd1, 0xa6, 0xab, 0x48, 0x38, 0xce, 0x42, 0xde, 0xf3, 0x8f, 0x03, 0x0e, 0x1c, 0xb7, 0xb3, 0x5f, 0x50, - 0x4c, 0x9b, 0x0c, 0x96, 0x66, 0xe9, 0x47, 0x2c, 0x0d, 0x5d, 0x37, 0xda, 0x8f, 0x31, 0x32, 0x4f, 0xbb, 0x17, 0x05, - 0x6e, 0xd4, 0x88, 0xbd, 0x03, 0xb7, 0xdd, 0x80, 0x34, 0xcf, 0x6b, 0xb4, 0xd1, 0x66, 0x9a, 0x87, 0xed, 0x66, 0x8a, - 0xb1, 0x3a, 0x89, 0x14, 0xa7, 0xfb, 0xf0, 0xd4, 0xc8, 0xf7, 0xa1, 0xc5, 0x86, 0x0f, 0x2c, 0x04, 0xd6, 0x9b, 0x4a, - 0x1e, 0x53, 0xf2, 0x58, 0x24, 0x0f, 0x74, 0xf2, 0x80, 0x92, 0x07, 0x22, 0x39, 0x0a, 0x0b, 0x48, 0x8a, 0x1a, 0x6e, - 0xbb, 0x59, 0x78, 0xfb, 0xd8, 0x03, 0xd5, 0xfb, 0x30, 0xb3, 0x43, 0xa4, 0xaf, 0xc8, 0xc7, 0x68, 0x96, 0xa7, 0x32, - 0x68, 0xa9, 0x01, 0x92, 0x3e, 0xf8, 0x85, 0xdf, 0xbc, 0xb1, 0xc0, 0x04, 0x2b, 0x82, 0x7e, 0x54, 0x48, 0x3e, 0x40, - 0x6f, 0x50, 0x39, 0x0d, 0x78, 0xd1, 0x17, 0xff, 0xab, 0x3c, 0xce, 0x83, 0x50, 0x5d, 0x45, 0xe9, 0x6c, 0x12, 0x6d, - 0x9c, 0x1e, 0x86, 0x2c, 0xb9, 0xb2, 0x74, 0x35, 0x1c, 0x44, 0x85, 0x62, 0xc3, 0xdd, 0x1c, 0x4b, 0xea, 0xb3, 0xa5, - 0x7e, 0x44, 0x46, 0x72, 0xf1, 0xc5, 0xb8, 0x00, 0x79, 0x29, 0x8e, 0x52, 0xee, 0x1a, 0x06, 0x6c, 0xba, 0x09, 0x72, - 0x08, 0x9e, 0x08, 0x28, 0xf6, 0xfd, 0xc3, 0x06, 0xd0, 0xd4, 0x7d, 0xff, 0xf8, 0x21, 0xfc, 0x0e, 0xf6, 0xfd, 0x76, - 0xdb, 0xe0, 0x2c, 0x40, 0x1b, 0xf2, 0xe0, 0xbf, 0x81, 0x3c, 0xe6, 0xb1, 0xca, 0x67, 0x11, 0xba, 0xb8, 0xfd, 0x83, - 0x6e, 0x34, 0x64, 0x37, 0x32, 0x3e, 0x16, 0x51, 0x3f, 0x37, 0xfa, 0x60, 0x37, 0x03, 0xd3, 0xd4, 0x84, 0x5f, 0x56, - 0x89, 0x99, 0x84, 0xe7, 0x31, 0xab, 0xc4, 0xf4, 0xc1, 0xf3, 0x40, 0x54, 0x45, 0x36, 0x40, 0x9e, 0x59, 0xc0, 0x7a, - 0xc1, 0x2d, 0xc8, 0x77, 0xd4, 0x21, 0x9d, 0x15, 0x5a, 0x0d, 0xbf, 0x57, 0xae, 0xa9, 0x0a, 0x96, 0x51, 0x85, 0xae, - 0x4e, 0xfc, 0xae, 0xa2, 0x6d, 0x53, 0x25, 0xff, 0xf7, 0x65, 0x75, 0xb5, 0x45, 0x5e, 0xd5, 0x0b, 0x3e, 0xab, 0x61, - 0x88, 0x2c, 0x25, 0x19, 0xf7, 0x97, 0x08, 0xb0, 0xdf, 0x93, 0xb7, 0xe2, 0x24, 0xa1, 0xb2, 0x23, 0x63, 0x52, 0xd2, - 0x68, 0xac, 0x3c, 0xd7, 0xe2, 0xb7, 0xcf, 0x6c, 0xaa, 0xba, 0x11, 0xf0, 0x0f, 0xe8, 0xdc, 0x3c, 0x13, 0x2e, 0xa1, - 0x43, 0xc7, 0xd0, 0xe2, 0xf7, 0xd2, 0xba, 0x5b, 0x63, 0x10, 0x7b, 0x7b, 0xeb, 0xfc, 0x42, 0x5d, 0xbd, 0xb0, 0x71, - 0xdd, 0x82, 0xf1, 0x27, 0x54, 0x17, 0x42, 0x09, 0x4f, 0xe3, 0xc4, 0x42, 0x14, 0x15, 0x7a, 0xeb, 0x01, 0x51, 0xf8, - 0x4b, 0x13, 0x77, 0x50, 0xe6, 0x34, 0x4f, 0x28, 0x83, 0xda, 0xea, 0x5b, 0x7d, 0x7b, 0x67, 0x0f, 0x48, 0xfb, 0x4a, - 0xfe, 0xdb, 0x86, 0xad, 0x46, 0xe4, 0x85, 0x35, 0x76, 0xa5, 0x5f, 0x6c, 0xcf, 0x64, 0x03, 0x1b, 0x79, 0x26, 0xfd, - 0xf6, 0xb6, 0x76, 0x3d, 0x91, 0xb8, 0x04, 0xc7, 0xdb, 0xdb, 0x4b, 0xca, 0xe7, 0xe8, 0x4c, 0xcd, 0xdd, 0x86, 0xcd, - 0x7c, 0xff, 0xaa, 0x71, 0xeb, 0x2f, 0xc4, 0x57, 0x03, 0x8b, 0xd1, 0x3d, 0xaa, 0xe5, 0x6f, 0x9d, 0x89, 0x5e, 0x15, - 0x24, 0x72, 0xae, 0x1f, 0x1b, 0x57, 0xf5, 0x8d, 0x8b, 0xb2, 0xa0, 0x07, 0x26, 0x5c, 0x95, 0x73, 0xdf, 0xf1, 0x7a, - 0xa4, 0x83, 0x3c, 0x4f, 0xf3, 0x08, 0x77, 0x44, 0x71, 0x8b, 0x21, 0x68, 0x24, 0x07, 0x15, 0xfb, 0x39, 0xff, 0xdf, - 0xaa, 0x64, 0xbf, 0x82, 0x6a, 0x0c, 0x4a, 0xbd, 0xb4, 0x45, 0x21, 0x13, 0x28, 0x92, 0x20, 0x6d, 0x7b, 0x9e, 0x7b, - 0x9a, 0x99, 0x47, 0xb3, 0x59, 0xba, 0xa0, 0xbb, 0xc2, 0x2c, 0x89, 0xca, 0x6c, 0x34, 0xc9, 0x28, 0x7d, 0xac, 0x40, - 0x99, 0x1e, 0x71, 0xcf, 0xa3, 0x53, 0xb6, 0x7a, 0x73, 0x3b, 0xf3, 0x50, 0x33, 0x2b, 0xc3, 0xbc, 0xd9, 0xee, 0x96, - 0xe7, 0xa8, 0x97, 0x35, 0x9b, 0x5e, 0x25, 0x83, 0x97, 0x83, 0x92, 0x05, 0x3a, 0x59, 0x29, 0x4e, 0xd2, 0xee, 0x88, - 0x82, 0xa8, 0xb9, 0xe5, 0xa4, 0xb2, 0x6d, 0x2f, 0x05, 0xd5, 0x23, 0x1a, 0x79, 0x42, 0xe1, 0xb3, 0x95, 0xc5, 0x04, - 0xa5, 0xce, 0x42, 0x35, 0x7c, 0x47, 0x4d, 0x05, 0xd4, 0xd5, 0x67, 0x05, 0x5d, 0x8f, 0xa1, 0xc7, 0x13, 0x95, 0xd6, - 0x75, 0x4b, 0x96, 0x8a, 0x92, 0xdc, 0xde, 0xee, 0xe2, 0x6d, 0x46, 0xb2, 0x4e, 0x3c, 0x7a, 0x2b, 0x1f, 0xcd, 0xcd, - 0x25, 0xd8, 0x0f, 0x1e, 0xb6, 0x68, 0xa3, 0x50, 0xea, 0x9b, 0xfc, 0x2c, 0xeb, 0x36, 0x1a, 0x9c, 0x02, 0x4d, 0x85, - 0x18, 0x55, 0x0e, 0xcf, 0x45, 0xe2, 0x8f, 0x88, 0x1d, 0x05, 0x92, 0x00, 0x45, 0xe0, 0xc3, 0xd0, 0xe0, 0xb5, 0x84, - 0xdb, 0xdb, 0x52, 0x44, 0x78, 0xa1, 0x1c, 0x11, 0xeb, 0x45, 0xb7, 0xa3, 0x43, 0xc9, 0x1a, 0x37, 0x8e, 0x44, 0x2e, - 0xf5, 0xf7, 0x66, 0x3d, 0xc3, 0x84, 0xd1, 0x36, 0x5e, 0x42, 0x71, 0x13, 0x08, 0x50, 0xcb, 0xb5, 0x05, 0x2e, 0xfc, - 0xfc, 0x5d, 0xe1, 0x94, 0xcc, 0xd7, 0x21, 0x98, 0xe9, 0x38, 0x01, 0x62, 0xe7, 0x56, 0xc5, 0x4d, 0x2c, 0x69, 0x4c, - 0xa5, 0x07, 0xe3, 0x40, 0x08, 0x86, 0xd8, 0xb8, 0x78, 0x34, 0x74, 0xc1, 0xe8, 0xc4, 0xba, 0x8f, 0x3f, 0x5a, 0xbb, - 0x79, 0x97, 0xce, 0xd5, 0x15, 0x2d, 0xf2, 0xab, 0x2b, 0x87, 0xd9, 0xce, 0xf5, 0x8e, 0x25, 0x0b, 0x3a, 0x7d, 0x1d, - 0x5a, 0x8b, 0x16, 0x7e, 0xb3, 0x6d, 0x2a, 0xfb, 0x14, 0x19, 0xbc, 0xc3, 0xe9, 0xa1, 0xca, 0x37, 0x0e, 0xa3, 0x5e, - 0x26, 0x08, 0x6f, 0xd0, 0xa7, 0xfb, 0xdd, 0x77, 0xa0, 0xdb, 0xed, 0xed, 0xbd, 0x03, 0x15, 0xae, 0x77, 0xc1, 0x69, - 0xcf, 0x0d, 0x4f, 0xa3, 0x43, 0x0e, 0x76, 0x3f, 0xb7, 0x10, 0xe0, 0x82, 0xaf, 0x6b, 0x36, 0xef, 0x29, 0xf6, 0x47, - 0x80, 0xb1, 0xc5, 0x31, 0xc2, 0xb1, 0x04, 0x09, 0xb6, 0xfa, 0xce, 0x86, 0x36, 0x08, 0xa1, 0x1c, 0x45, 0x78, 0x7d, - 0x56, 0x90, 0xfb, 0x53, 0x5e, 0x8c, 0x79, 0x71, 0x7b, 0xfb, 0x29, 0x12, 0xe7, 0xff, 0xd6, 0x42, 0x55, 0x96, 0x00, - 0xc6, 0x88, 0xfa, 0x8f, 0xea, 0x43, 0xd4, 0x67, 0x50, 0x21, 0xa8, 0x40, 0xe8, 0x61, 0x94, 0x64, 0x73, 0x75, 0xd6, - 0x2d, 0xae, 0xcd, 0x4b, 0xe1, 0xe9, 0x4a, 0x52, 0x40, 0xb5, 0x49, 0x18, 0xeb, 0x39, 0x3a, 0x9b, 0x40, 0x7d, 0xa9, - 0x97, 0xbb, 0xf1, 0x65, 0x0a, 0x1a, 0x08, 0x2b, 0x70, 0x33, 0x75, 0x73, 0x1e, 0x66, 0xbc, 0x46, 0xb9, 0xe4, 0x78, - 0x97, 0xa2, 0xaf, 0xc1, 0x8b, 0x68, 0x65, 0xaf, 0xee, 0xc8, 0x22, 0x12, 0xdb, 0x80, 0x9c, 0x09, 0x20, 0x97, 0x0a, - 0xc8, 0x19, 0x01, 0xb9, 0x04, 0xea, 0x83, 0x41, 0x9b, 0x40, 0x9d, 0xde, 0xa0, 0xe8, 0xf5, 0xf0, 0xa2, 0xf2, 0xe8, - 0x0a, 0x4b, 0x28, 0xc2, 0x85, 0x9c, 0x0e, 0x3c, 0xc6, 0x22, 0xc7, 0x5e, 0x86, 0x4b, 0xc7, 0xa1, 0x48, 0xbb, 0xec, - 0x86, 0x7e, 0xfc, 0x1b, 0xb6, 0x10, 0x0f, 0x0b, 0xcb, 0x98, 0xf4, 0xb1, 0x66, 0x6d, 0x48, 0x64, 0x5c, 0x3a, 0xc7, - 0x77, 0x10, 0xad, 0x65, 0x90, 0xc5, 0xac, 0x7e, 0xef, 0x5c, 0x29, 0xc2, 0x61, 0x64, 0x8d, 0xb0, 0x04, 0xc1, 0xd0, - 0x90, 0xce, 0x3f, 0xff, 0x04, 0xda, 0x99, 0x61, 0x34, 0x23, 0xc9, 0xd9, 0x9a, 0x6d, 0xaf, 0x01, 0x35, 0x05, 0xae, - 0x0a, 0x96, 0x81, 0x2b, 0xc3, 0x71, 0xac, 0x3b, 0x67, 0x4c, 0x94, 0xb5, 0x5a, 0x37, 0xa8, 0x53, 0x26, 0xfc, 0xc7, - 0xf9, 0x72, 0x3d, 0xd8, 0x12, 0x41, 0x35, 0xa3, 0x48, 0x37, 0x9e, 0xb8, 0x88, 0x0d, 0x50, 0x68, 0x6f, 0x8f, 0x5f, - 0x66, 0x7d, 0xeb, 0x66, 0x35, 0xe3, 0x41, 0x52, 0xd9, 0x13, 0xe7, 0xc6, 0x18, 0xed, 0x1e, 0xa0, 0x46, 0xbf, 0xe1, - 0xaf, 0xa4, 0xcd, 0xe0, 0x15, 0x79, 0x16, 0x8f, 0xcd, 0xb6, 0xeb, 0x62, 0xc0, 0x55, 0x3f, 0xa2, 0x67, 0x9f, 0x8c, - 0x5d, 0x98, 0xc8, 0xa1, 0xb6, 0xf5, 0x11, 0x1c, 0xb2, 0x28, 0x58, 0x91, 0x83, 0x0d, 0x4b, 0x63, 0xb3, 0xca, 0xce, - 0xab, 0x45, 0x00, 0x4e, 0x4b, 0x1d, 0xc8, 0x15, 0x59, 0x8a, 0x8f, 0x9e, 0xde, 0x44, 0x27, 0xf1, 0xa1, 0x4e, 0x25, - 0xa5, 0x08, 0x89, 0x50, 0x48, 0x3c, 0xda, 0x9c, 0xa7, 0x40, 0xfd, 0xdc, 0xdb, 0x42, 0xe4, 0x2c, 0x17, 0x9a, 0xba, - 0x6e, 0x29, 0x23, 0x6a, 0x39, 0xd3, 0x7c, 0x5e, 0xf2, 0xf9, 0x0c, 0xf9, 0xbb, 0x4e, 0x8b, 0x61, 0x44, 0x5f, 0xeb, - 0x29, 0xe8, 0x10, 0x79, 0x53, 0x4d, 0x79, 0x36, 0x77, 0xe4, 0x38, 0xdf, 0x08, 0x75, 0xff, 0xdd, 0x4b, 0xf6, 0x09, - 0x34, 0x93, 0x37, 0xec, 0xaf, 0x28, 0xfc, 0xd4, 0x78, 0xc3, 0xc6, 0x49, 0x28, 0x64, 0x03, 0xff, 0xdd, 0xdb, 0x8b, - 0x97, 0x1f, 0x5e, 0x7e, 0x7a, 0x76, 0xf5, 0xf2, 0xcd, 0xf3, 0x97, 0x6f, 0x5e, 0x7e, 0xf8, 0x9d, 0xfd, 0x16, 0x85, - 0x6f, 0x0e, 0xda, 0xa7, 0x2d, 0xf6, 0x11, 0x7e, 0x3b, 0xec, 0xa6, 0x82, 0x9f, 0x23, 0x36, 0x29, 0xc3, 0x37, 0xfb, - 0x9d, 0x83, 0x43, 0x36, 0xaf, 0x44, 0x95, 0x69, 0x3e, 0x6e, 0xb7, 0xd8, 0x5f, 0xf2, 0x0d, 0xd5, 0x7b, 0xeb, 0x18, - 0x0e, 0x5f, 0x73, 0x7e, 0xa0, 0x32, 0xd1, 0xa0, 0x24, 0x47, 0x94, 0x33, 0x0b, 0x9d, 0x86, 0xa5, 0x8d, 0x4e, 0x22, - 0x94, 0x34, 0xfa, 0x30, 0x22, 0x5a, 0x25, 0xa1, 0xac, 0x27, 0x39, 0x68, 0xf3, 0x43, 0xa4, 0x4f, 0x89, 0x56, 0x8e, - 0xb5, 0x09, 0xa7, 0x2d, 0xad, 0x18, 0xa3, 0x34, 0x07, 0xa0, 0xcf, 0x51, 0x10, 0x20, 0xab, 0x45, 0x72, 0xa0, 0x63, - 0x56, 0x65, 0x67, 0x61, 0xbb, 0xd7, 0x0e, 0xe0, 0xa7, 0xd3, 0xeb, 0xe0, 0xcf, 0x71, 0xef, 0x38, 0x68, 0xb7, 0xbc, - 0x7d, 0xab, 0x1f, 0x3f, 0xd7, 0xd0, 0xfa, 0xb2, 0xcf, 0x64, 0x13, 0xe5, 0x5f, 0x45, 0xa5, 0x4c, 0x7a, 0x99, 0x34, - 0xc7, 0xb6, 0xbb, 0xd9, 0x19, 0x27, 0x3b, 0x6c, 0x72, 0x1f, 0x51, 0x9b, 0x8e, 0xd5, 0xe8, 0x85, 0x23, 0x9f, 0x92, - 0x83, 0xcc, 0xab, 0x05, 0xc6, 0x71, 0xf9, 0x6d, 0xcb, 0x43, 0xa1, 0x91, 0xb2, 0xd1, 0x1d, 0xc8, 0x2f, 0x73, 0xa8, - 0x5c, 0x06, 0xf7, 0x2f, 0x9b, 0xb9, 0x07, 0x03, 0x9a, 0xb9, 0x35, 0x53, 0xc3, 0x6b, 0xcb, 0xcd, 0x71, 0x37, 0x29, - 0xdf, 0x44, 0x6f, 0xdc, 0x9a, 0xcc, 0x63, 0x8b, 0x76, 0xf6, 0xb2, 0xf8, 0x51, 0x7a, 0x51, 0xd4, 0xc0, 0xa5, 0x01, - 0xab, 0x7a, 0xd5, 0xac, 0xce, 0xf0, 0x16, 0x43, 0xde, 0xa8, 0xce, 0x43, 0x8b, 0x7a, 0xfe, 0xa2, 0xdd, 0xb8, 0xb4, - 0x31, 0x5a, 0x19, 0xa2, 0xc9, 0x2d, 0x48, 0x19, 0xa2, 0x81, 0xb8, 0x67, 0x64, 0x6b, 0x4e, 0x60, 0x35, 0x23, 0xc3, - 0x17, 0x1d, 0xcc, 0x89, 0xce, 0xa1, 0x59, 0xc9, 0xb8, 0x09, 0xd1, 0x2b, 0x85, 0x68, 0x40, 0xcb, 0x93, 0x31, 0x41, - 0xd1, 0x2b, 0xa4, 0x5b, 0x5d, 0xff, 0xc3, 0x5e, 0x00, 0xfb, 0x2e, 0xa1, 0xa2, 0xed, 0x57, 0x93, 0xd5, 0xf3, 0x21, - 0xf7, 0xe0, 0x8d, 0x95, 0x3f, 0x2f, 0x95, 0xbf, 0xc7, 0x17, 0x8b, 0x92, 0x8b, 0xa0, 0x62, 0x6d, 0xa6, 0xe2, 0xc1, - 0x75, 0x6d, 0x80, 0xec, 0x57, 0xde, 0x01, 0x5d, 0xe8, 0xd8, 0xf5, 0x2a, 0x50, 0xee, 0x5a, 0x18, 0xc4, 0x6d, 0x0b, - 0xe5, 0xfb, 0x65, 0x0d, 0xa6, 0x95, 0x7f, 0xd3, 0x44, 0x5a, 0x8d, 0x77, 0x3c, 0x2d, 0xe0, 0x69, 0x01, 0xc0, 0x31, - 0x38, 0xc3, 0xf7, 0x79, 0x23, 0xdb, 0xcf, 0x3c, 0x19, 0xfc, 0x56, 0x2c, 0x00, 0x90, 0xcb, 0x3b, 0xe2, 0xae, 0x41, - 0xe5, 0x1c, 0x75, 0xd6, 0xf4, 0x8f, 0xf7, 0xdf, 0x00, 0x02, 0xe5, 0x8d, 0xf0, 0x93, 0xc7, 0x96, 0x11, 0xfa, 0x6c, - 0xe3, 0xd9, 0xbb, 0x44, 0x08, 0xf1, 0x41, 0x69, 0x51, 0xc7, 0x51, 0x59, 0x63, 0x6b, 0xa6, 0x31, 0xbd, 0x1a, 0x54, - 0x9f, 0x3a, 0x5e, 0xc3, 0x4a, 0x13, 0xbd, 0xeb, 0xd4, 0xa0, 0x5c, 0x3b, 0x28, 0x87, 0xcb, 0xb2, 0xf1, 0x57, 0xe4, - 0xdd, 0xff, 0xd4, 0x7c, 0x63, 0x0d, 0xb8, 0xe6, 0x9a, 0xf4, 0xa9, 0xf1, 0x09, 0xf2, 0xad, 0xa3, 0x8e, 0x89, 0x11, - 0x4f, 0x94, 0x34, 0xf2, 0x8b, 0x90, 0x4a, 0x7f, 0x41, 0xcd, 0xbe, 0x80, 0x1f, 0x8e, 0x9e, 0x61, 0xbf, 0xb8, 0x79, - 0x13, 0x43, 0x40, 0xc2, 0x43, 0x81, 0x0f, 0x29, 0x3c, 0x20, 0xb6, 0x03, 0x63, 0xc7, 0x87, 0x42, 0x03, 0x03, 0x8f, - 0xd7, 0xe5, 0xe2, 0x94, 0x1d, 0x08, 0x14, 0xd9, 0xde, 0x5e, 0x2e, 0x9e, 0xa2, 0xf3, 0x78, 0x6f, 0x0f, 0x58, 0xbf, - 0x69, 0x3b, 0xa9, 0xb6, 0xd1, 0x17, 0x42, 0x28, 0x66, 0xb9, 0xa6, 0x25, 0xf6, 0x88, 0x7f, 0xaa, 0x51, 0x56, 0xac, - 0xa0, 0x79, 0xd8, 0x79, 0x70, 0x72, 0xca, 0xf0, 0xef, 0x03, 0xab, 0x60, 0x15, 0xab, 0x81, 0x85, 0x6d, 0x0e, 0xba, - 0x9d, 0xfe, 0xe6, 0xdc, 0xc2, 0x67, 0x68, 0xbb, 0x09, 0x3d, 0x4c, 0xce, 0x2c, 0x5c, 0x86, 0xb4, 0x86, 0xe5, 0xb1, - 0xf7, 0x48, 0xfb, 0x93, 0x91, 0xd4, 0x84, 0x97, 0xfb, 0x82, 0x40, 0xde, 0x3f, 0xab, 0x24, 0x35, 0xb1, 0x43, 0x80, - 0x83, 0xe0, 0x29, 0x17, 0x59, 0x37, 0x6b, 0x96, 0xe7, 0xed, 0x2e, 0xac, 0xaa, 0xb2, 0x91, 0x9d, 0x9f, 0x03, 0xca, - 0xa2, 0x3c, 0x07, 0x1a, 0x45, 0x90, 0x85, 0xea, 0x98, 0xe2, 0x32, 0xcd, 0x83, 0x92, 0x4d, 0x92, 0x20, 0x53, 0x7a, - 0xf6, 0x5b, 0xe5, 0x3d, 0x4d, 0x07, 0x47, 0xa9, 0x65, 0x78, 0xec, 0x95, 0xfa, 0xc0, 0x23, 0x2e, 0xd2, 0xb2, 0x8f, - 0x77, 0x27, 0x6a, 0xcc, 0xe3, 0xe2, 0x94, 0x1f, 0xc7, 0xd8, 0xd4, 0x65, 0xa3, 0x8d, 0x99, 0xf8, 0xba, 0x0a, 0x4a, - 0xec, 0x28, 0x15, 0x3e, 0xc3, 0xb0, 0x87, 0xb1, 0x71, 0xcc, 0x56, 0x15, 0x63, 0x81, 0x0c, 0x0b, 0x9c, 0x87, 0xdc, - 0xd2, 0xe0, 0x93, 0xb8, 0x46, 0x38, 0xea, 0xe4, 0x42, 0x0c, 0xee, 0xac, 0xc4, 0xe6, 0x32, 0x80, 0x42, 0x17, 0xe4, - 0x92, 0x86, 0x94, 0xb6, 0xcf, 0x33, 0xea, 0x44, 0xb3, 0xdd, 0x3f, 0xe7, 0x5d, 0x0f, 0x74, 0x26, 0xed, 0x00, 0x79, - 0xde, 0x02, 0x84, 0x38, 0x53, 0x95, 0xf4, 0x14, 0x1f, 0x27, 0xb9, 0x4b, 0x29, 0x9e, 0x7f, 0xe4, 0xe1, 0xa5, 0x83, - 0x54, 0x15, 0xe5, 0xec, 0x7c, 0x06, 0x7f, 0xe9, 0x5a, 0x3d, 0xfc, 0xa5, 0xeb, 0xd0, 0xe0, 0x41, 0xde, 0xb4, 0xe7, - 0xf4, 0x4d, 0x67, 0xb3, 0x58, 0x07, 0x89, 0x4f, 0xfc, 0x2b, 0x14, 0x1c, 0xaa, 0x2f, 0x25, 0xbc, 0xea, 0x67, 0x3f, - 0x95, 0xe1, 0x52, 0x4a, 0x75, 0xf9, 0x9b, 0xec, 0xd5, 0x6a, 0xfb, 0x01, 0xd5, 0x84, 0x39, 0xea, 0x53, 0xbc, 0x44, - 0xe1, 0x3b, 0xb7, 0x4f, 0xb6, 0xe5, 0xa5, 0xe7, 0x4b, 0xdd, 0x02, 0x4a, 0xde, 0xab, 0x95, 0xc7, 0xfe, 0xc8, 0xb7, - 0xde, 0x80, 0xec, 0x5c, 0xe5, 0xd9, 0x53, 0xa0, 0x1e, 0x4e, 0xe3, 0x1d, 0x39, 0xbe, 0x09, 0x3d, 0xab, 0x7b, 0x57, - 0x3f, 0xf8, 0x3f, 0x6a, 0x1e, 0x03, 0x58, 0xd4, 0x2e, 0x6b, 0x12, 0xba, 0x2f, 0x85, 0x2d, 0xc9, 0x2d, 0xd7, 0xb7, - 0x2d, 0xf0, 0x50, 0x7d, 0x8c, 0xf0, 0x58, 0xb5, 0x90, 0x93, 0x22, 0x8c, 0x0c, 0x5b, 0x3b, 0xcc, 0x8d, 0x29, 0xa2, - 0x0d, 0x3a, 0xf8, 0xbb, 0xf2, 0x6c, 0xa9, 0x7b, 0x56, 0xd6, 0x89, 0xa9, 0x69, 0x86, 0xb4, 0x0e, 0xbe, 0x2e, 0x82, - 0x73, 0xd3, 0x3a, 0x69, 0x28, 0xe6, 0x5e, 0x3b, 0xba, 0x9b, 0xb4, 0xd9, 0xa6, 0xcb, 0x9e, 0xc5, 0xed, 0x77, 0x25, - 0x3a, 0xf2, 0xee, 0xea, 0xa0, 0x5d, 0xe7, 0xc8, 0x76, 0x5d, 0x0b, 0xb2, 0x39, 0xf4, 0x5a, 0xde, 0x4c, 0x97, 0x5c, - 0xe6, 0xfd, 0x95, 0xbe, 0xa7, 0xce, 0xc2, 0x03, 0xd3, 0xd3, 0x32, 0xb6, 0x25, 0x03, 0x75, 0xc9, 0x63, 0xcd, 0x3e, - 0x04, 0xb2, 0x1f, 0xac, 0x1c, 0x83, 0xa4, 0x81, 0x30, 0x3f, 0xe1, 0xfd, 0x51, 0x68, 0xf0, 0x16, 0xdf, 0xfe, 0x94, - 0xdb, 0x07, 0x75, 0xeb, 0x36, 0x15, 0x71, 0x16, 0xb6, 0x6e, 0x58, 0xd1, 0x85, 0x2d, 0xaa, 0xe5, 0x7a, 0xab, 0x40, - 0x9e, 0x9b, 0x95, 0x97, 0x4e, 0x3d, 0xca, 0xf0, 0x6c, 0x0c, 0x14, 0x7b, 0x5e, 0x60, 0x14, 0x31, 0xdb, 0x9e, 0x56, - 0x15, 0xf6, 0xad, 0xca, 0x97, 0xb8, 0x4f, 0xa8, 0x65, 0x4e, 0x7d, 0x13, 0x38, 0x4e, 0x50, 0x89, 0x14, 0x0a, 0x34, - 0x04, 0xa0, 0x51, 0x19, 0xc5, 0x96, 0x90, 0xa1, 0x85, 0xe5, 0x1d, 0x22, 0x64, 0xbf, 0xc3, 0x6f, 0x99, 0x32, 0x8f, - 0x90, 0x0b, 0xab, 0x67, 0x6f, 0x3a, 0xe5, 0xb1, 0xd5, 0xd6, 0xb6, 0x36, 0x32, 0x33, 0xe4, 0x9e, 0x4b, 0xf6, 0xde, - 0x0f, 0xc9, 0x94, 0xe7, 0x73, 0xbc, 0xbc, 0x09, 0xb8, 0x72, 0xc9, 0x2b, 0xf5, 0x8e, 0x14, 0x04, 0x6f, 0x00, 0x4a, - 0x6c, 0x7c, 0x44, 0xb9, 0x4a, 0xd1, 0xba, 0x22, 0x56, 0x57, 0x82, 0x38, 0x14, 0xb2, 0xd3, 0xe9, 0x39, 0x78, 0x8a, - 0x08, 0x55, 0x28, 0x48, 0x02, 0x2d, 0x07, 0x12, 0xe8, 0x48, 0x96, 0x83, 0x5e, 0x63, 0x68, 0xe4, 0x76, 0xd8, 0xb8, - 0x34, 0x44, 0xcc, 0xfe, 0xb2, 0xb2, 0x3e, 0xe2, 0x01, 0xb9, 0x69, 0x1f, 0x74, 0x0c, 0x08, 0xa3, 0x78, 0x5d, 0x51, - 0xae, 0xd6, 0xcc, 0x05, 0xc0, 0xed, 0xc8, 0xf5, 0x16, 0x50, 0x07, 0xa5, 0x39, 0x3e, 0x94, 0x45, 0x97, 0xc9, 0x05, - 0x9a, 0xa7, 0x83, 0x82, 0x5d, 0x91, 0xc0, 0x36, 0x0c, 0xa2, 0x55, 0x98, 0x00, 0x13, 0x2c, 0xfc, 0xe8, 0x06, 0x63, - 0x6b, 0x00, 0x17, 0x09, 0x52, 0x06, 0x7c, 0x23, 0x98, 0x30, 0x78, 0x7e, 0x2a, 0xa6, 0x3d, 0x18, 0x62, 0x92, 0x7a, - 0x99, 0xaf, 0x42, 0xba, 0x1a, 0xec, 0x63, 0xc9, 0x8b, 0xc7, 0x28, 0xab, 0x94, 0x30, 0xbf, 0x43, 0xf2, 0x29, 0x4f, - 0x2a, 0xe3, 0xbc, 0xfe, 0xb6, 0x72, 0x23, 0x16, 0xb3, 0xd4, 0x03, 0x99, 0x9c, 0xf1, 0x5e, 0x16, 0xbc, 0xc5, 0xb8, - 0xda, 0x31, 0x13, 0xd7, 0x8a, 0x25, 0x37, 0x3c, 0x7d, 0x9e, 0x17, 0x9f, 0x68, 0xc9, 0xa7, 0x1e, 0x16, 0xc2, 0x23, - 0x2a, 0x59, 0x13, 0x77, 0xf7, 0xe6, 0xbd, 0xdc, 0x54, 0x05, 0x3c, 0x8c, 0xaa, 0x92, 0x5d, 0x9c, 0x60, 0x40, 0x62, - 0x7f, 0x92, 0x34, 0x80, 0x07, 0xf5, 0x5a, 0xdf, 0xa9, 0x74, 0xe2, 0xe9, 0x92, 0x40, 0x9a, 0x60, 0xae, 0x9a, 0x65, - 0x00, 0x60, 0x69, 0x96, 0x52, 0xc3, 0x5b, 0x12, 0xb0, 0x81, 0x63, 0xc5, 0x30, 0x86, 0x2a, 0xc8, 0x2d, 0xbc, 0x89, - 0xcd, 0xe2, 0x5a, 0xde, 0x08, 0x88, 0x55, 0x6c, 0x21, 0x1e, 0x38, 0xbb, 0x22, 0x13, 0xff, 0x7b, 0x74, 0xec, 0x29, - 0x81, 0xd7, 0x01, 0xfc, 0xd0, 0x71, 0x16, 0x21, 0x27, 0xe4, 0xc9, 0x1b, 0x04, 0x9f, 0x10, 0x21, 0x17, 0x98, 0xca, - 0x29, 0x75, 0x81, 0xa9, 0x1c, 0x53, 0xe9, 0x44, 0xfd, 0x6e, 0x66, 0x8c, 0x45, 0x76, 0x85, 0x80, 0xf1, 0xda, 0x1c, - 0x0c, 0xbd, 0xf5, 0xb1, 0x5e, 0x52, 0xe5, 0xe0, 0x17, 0x43, 0x2b, 0x62, 0xe5, 0xe2, 0x3d, 0xba, 0xc1, 0xf7, 0x85, - 0xc8, 0xe7, 0x2a, 0x7f, 0x21, 0xf2, 0xa9, 0x21, 0x85, 0xf1, 0xf5, 0xdd, 0x4e, 0xf2, 0x8c, 0xcf, 0x25, 0xd6, 0x7e, - 0xd4, 0x17, 0xd9, 0xb4, 0xe8, 0xc2, 0x70, 0x10, 0x46, 0xa7, 0x16, 0x52, 0x36, 0x8d, 0x0c, 0xd7, 0x61, 0xed, 0xd6, - 0x3e, 0x48, 0x64, 0x21, 0x4c, 0xd0, 0xbe, 0x54, 0xae, 0x32, 0x97, 0x34, 0xa7, 0xfd, 0x4f, 0x07, 0xb8, 0xf7, 0x32, - 0x28, 0xd7, 0xce, 0x4a, 0x89, 0xcf, 0x9a, 0xf0, 0x5d, 0xb2, 0xf5, 0x13, 0x98, 0xc2, 0x29, 0x0f, 0x97, 0x78, 0x02, - 0x2d, 0x2a, 0x84, 0xa9, 0x01, 0x8f, 0xac, 0xbe, 0xcc, 0x7e, 0x99, 0x47, 0x43, 0x7a, 0xdf, 0x17, 0x29, 0x6f, 0xe7, - 0x95, 0x4a, 0x6a, 0x26, 0xd8, 0x89, 0x8e, 0x27, 0x4b, 0x5a, 0x39, 0xa0, 0xdb, 0x84, 0xfe, 0xb1, 0x77, 0xd6, 0xee, - 0x81, 0xec, 0x0a, 0x5f, 0x06, 0x28, 0xc3, 0xba, 0x4d, 0xf5, 0x01, 0x20, 0x96, 0xfc, 0xe6, 0xc9, 0x7c, 0x90, 0xc4, - 0xb2, 0x7a, 0xd3, 0x80, 0x4e, 0x15, 0x63, 0xc4, 0x2c, 0x44, 0x31, 0xd5, 0x8a, 0x95, 0x5d, 0x6f, 0x06, 0x1a, 0xc2, - 0x76, 0xf0, 0xab, 0x8e, 0xf8, 0x4a, 0x77, 0x0e, 0x7a, 0x56, 0x54, 0xba, 0xa1, 0xda, 0x58, 0x44, 0x7a, 0xd3, 0x35, - 0x8d, 0xed, 0x27, 0xa6, 0x87, 0x76, 0x99, 0xcd, 0xf6, 0xd4, 0xd0, 0x4c, 0x93, 0xfb, 0x16, 0x44, 0x7e, 0x99, 0x27, - 0x99, 0xdd, 0xa8, 0xdd, 0xac, 0xcc, 0xb1, 0x1b, 0xad, 0x8f, 0xd2, 0x2a, 0xb2, 0xd9, 0xea, 0xc6, 0x48, 0xeb, 0xa3, - 0xbd, 0xc0, 0x83, 0x84, 0x38, 0x28, 0x9a, 0xe9, 0x38, 0x07, 0x56, 0xba, 0xff, 0xd1, 0x93, 0xb5, 0x43, 0xdd, 0x2a, - 0x5f, 0x23, 0x02, 0x66, 0x9b, 0xa6, 0xf5, 0xe7, 0xd8, 0x86, 0xae, 0xe2, 0x0d, 0xa0, 0x8e, 0x81, 0xcb, 0xb3, 0x9b, - 0x59, 0x1e, 0x28, 0x7c, 0x85, 0xc5, 0xbf, 0x81, 0x9c, 0x48, 0x3c, 0x64, 0x73, 0x76, 0x59, 0xd4, 0xb3, 0x9b, 0x1b, - 0x28, 0x69, 0x0f, 0x5c, 0x95, 0xfe, 0xc8, 0xc5, 0x76, 0x43, 0x72, 0xe6, 0x1f, 0xe3, 0xd0, 0xd7, 0x5b, 0xd8, 0xef, - 0x60, 0x1b, 0x04, 0x87, 0xf5, 0x0a, 0x55, 0xa6, 0x81, 0xc8, 0x93, 0xa4, 0x10, 0x78, 0x76, 0x0e, 0x3d, 0x80, 0x49, - 0x73, 0x8d, 0x6a, 0xd4, 0x06, 0xb4, 0x34, 0x23, 0x43, 0xfc, 0x92, 0x65, 0xed, 0x22, 0x6a, 0x9e, 0x2c, 0x28, 0xa9, - 0x62, 0x66, 0x7e, 0x0c, 0xbc, 0xea, 0x15, 0x07, 0xeb, 0xe9, 0x6a, 0xde, 0x70, 0x77, 0x57, 0xc1, 0x13, 0x2f, 0xa2, - 0x11, 0x68, 0xad, 0x06, 0x3e, 0x45, 0x09, 0xc8, 0x6f, 0x3d, 0x38, 0xc6, 0x23, 0x94, 0x1a, 0x96, 0x9b, 0xe5, 0x06, - 0x1b, 0xe5, 0x04, 0x1c, 0x45, 0x49, 0x4b, 0x3a, 0x58, 0x87, 0x28, 0x36, 0xb0, 0xdf, 0x61, 0x7e, 0xbb, 0xdd, 0x81, - 0x6f, 0x8f, 0x8e, 0xb1, 0xa3, 0x0d, 0x48, 0x1f, 0x94, 0x02, 0x80, 0x56, 0xce, 0x4a, 0xd6, 0xfb, 0x18, 0x83, 0x56, - 0xd9, 0xea, 0x35, 0x2c, 0x69, 0xb7, 0xed, 0x3f, 0x68, 0xb5, 0x8f, 0x4f, 0x1b, 0x08, 0xa0, 0xa6, 0x7c, 0x91, 0x5f, - 0x40, 0x3f, 0xea, 0x9f, 0x68, 0x84, 0xaf, 0x7f, 0xd6, 0x50, 0x9f, 0x35, 0xda, 0x2b, 0x33, 0x04, 0xf5, 0xa9, 0x54, - 0xce, 0x45, 0x11, 0x65, 0xb4, 0xb1, 0x97, 0x85, 0x2b, 0x3a, 0xe2, 0xa2, 0x76, 0xee, 0x1f, 0x77, 0x8e, 0x3d, 0xd1, - 0x97, 0x4a, 0xe2, 0x87, 0x5e, 0x27, 0x1b, 0x45, 0x1a, 0x15, 0x22, 0x89, 0x1e, 0x1d, 0xb0, 0x9f, 0x98, 0x50, 0xbf, - 0xdd, 0x9c, 0x72, 0x5f, 0x0d, 0x80, 0x52, 0x71, 0x3a, 0xf5, 0x2c, 0xc8, 0x24, 0x0b, 0x10, 0x67, 0xe8, 0x5c, 0xf4, - 0xe0, 0xb8, 0xf7, 0xc0, 0x3f, 0x3e, 0xe9, 0x08, 0xa2, 0x97, 0x9c, 0x75, 0x6a, 0x69, 0x34, 0x74, 0xff, 0x98, 0xd2, - 0xb0, 0x69, 0xf8, 0xc1, 0x32, 0x32, 0xc5, 0x2e, 0x85, 0xc1, 0x36, 0x4c, 0x31, 0x8c, 0xb0, 0x11, 0xd4, 0x72, 0x4f, - 0x6a, 0xd9, 0xa7, 0x47, 0x50, 0xc0, 0x86, 0x9a, 0x1e, 0x05, 0x4d, 0xb4, 0x1c, 0x88, 0x1a, 0x1d, 0x4e, 0xad, 0xb7, - 0xef, 0x1f, 0x07, 0x1b, 0x03, 0x14, 0x8b, 0x66, 0x9f, 0x70, 0xc0, 0x32, 0x38, 0x3e, 0xcb, 0xa4, 0xbd, 0xc4, 0xda, - 0x1f, 0x33, 0x8e, 0x26, 0xb6, 0xc1, 0x59, 0xed, 0x53, 0x5a, 0xf7, 0x69, 0xda, 0x5b, 0x95, 0x4f, 0xa2, 0xec, 0x5b, - 0x54, 0xbe, 0x8b, 0x30, 0x82, 0x48, 0xd6, 0x77, 0x64, 0x7c, 0xf3, 0x7a, 0xee, 0x8f, 0x78, 0x44, 0x18, 0x44, 0xb2, - 0xbe, 0xb3, 0x52, 0x46, 0x50, 0x23, 0x0b, 0x5c, 0xd9, 0x07, 0x6a, 0xa9, 0x5b, 0x80, 0xcc, 0xd2, 0xa5, 0xc0, 0xb6, - 0x6d, 0xbd, 0x48, 0xbe, 0x57, 0xce, 0xd7, 0x5b, 0xd9, 0x80, 0x3e, 0xbe, 0xdc, 0x2c, 0xf7, 0xdb, 0x20, 0x9e, 0x18, - 0x17, 0x12, 0xc9, 0x92, 0xd3, 0x18, 0xf4, 0xc6, 0x1b, 0xd0, 0x0e, 0x17, 0xf0, 0x9f, 0x38, 0xc3, 0xfc, 0x2b, 0x9e, - 0xe3, 0x86, 0x37, 0x71, 0x94, 0x19, 0x1e, 0x40, 0xe5, 0xc0, 0xc0, 0x62, 0x4e, 0x9f, 0x4d, 0xb0, 0x34, 0x9d, 0xac, - 0xd6, 0xa5, 0x9f, 0xa8, 0x37, 0x7d, 0xf4, 0x5a, 0xa4, 0x58, 0x5a, 0xe6, 0x90, 0x56, 0xa8, 0xb8, 0x18, 0xdb, 0x89, - 0x94, 0xb0, 0x0e, 0xfa, 0x21, 0xa8, 0x1c, 0xd1, 0x42, 0x5d, 0xac, 0x67, 0x62, 0x92, 0xf0, 0x43, 0x9c, 0x69, 0x3c, - 0x8a, 0xee, 0xd8, 0x3c, 0xcc, 0x61, 0xa3, 0x4c, 0x15, 0x46, 0xb5, 0x42, 0x3d, 0xa7, 0x79, 0x3e, 0x53, 0xcf, 0x55, - 0xae, 0x9f, 0xf0, 0x3a, 0x16, 0xe9, 0xd1, 0x82, 0x9e, 0x5b, 0x22, 0x04, 0xd2, 0x80, 0xd7, 0x7b, 0x70, 0x35, 0x92, - 0x61, 0xea, 0x50, 0x23, 0xbc, 0x22, 0x85, 0x4a, 0xe9, 0x87, 0x57, 0x22, 0x64, 0x12, 0xbd, 0x62, 0xcc, 0x34, 0x0c, - 0x8b, 0x9c, 0xe3, 0x86, 0xc6, 0xb8, 0xe0, 0x65, 0xe9, 0x88, 0x58, 0x82, 0x90, 0xa2, 0x2e, 0x87, 0x54, 0x29, 0xa3, - 0xcc, 0xa1, 0x06, 0xeb, 0xa3, 0x15, 0xea, 0x30, 0x00, 0xa6, 0x0c, 0xc4, 0x4d, 0x31, 0x0a, 0x8c, 0x33, 0x7d, 0x0d, - 0x63, 0x30, 0x89, 0x57, 0x4c, 0xec, 0x61, 0xeb, 0x42, 0x72, 0x4b, 0xdb, 0x2e, 0x95, 0xc6, 0xab, 0xbb, 0x06, 0x54, - 0xd6, 0x46, 0x64, 0x0d, 0xd4, 0x74, 0xc8, 0x04, 0xee, 0xc0, 0xc2, 0x22, 0x28, 0x4d, 0xb0, 0xd4, 0x25, 0x83, 0xa5, - 0x9e, 0x86, 0xa3, 0x56, 0x6b, 0xb5, 0x62, 0x30, 0x56, 0x0c, 0xe4, 0xb2, 0xb5, 0x04, 0xe6, 0x97, 0x93, 0xfc, 0xda, - 0xca, 0x2d, 0x03, 0x3d, 0x4a, 0x9a, 0x22, 0xc7, 0x72, 0x82, 0x75, 0x56, 0xec, 0x5b, 0x52, 0x26, 0x08, 0x4f, 0x39, - 0xba, 0x41, 0x9e, 0x83, 0x16, 0x84, 0x31, 0xd4, 0xac, 0x2a, 0x57, 0x6c, 0x92, 0x0c, 0xf9, 0xf6, 0x3a, 0xd1, 0x8d, - 0xf9, 0x9f, 0xd5, 0xa8, 0x10, 0x48, 0x88, 0x7b, 0x84, 0x3a, 0x38, 0x89, 0xb7, 0xd8, 0x80, 0xad, 0x83, 0xcf, 0x6d, - 0xdc, 0x04, 0x6c, 0x04, 0xed, 0x0b, 0xe1, 0x32, 0xaf, 0xf2, 0x77, 0x32, 0x1c, 0x02, 0x28, 0x83, 0x2a, 0x32, 0xc2, - 0x12, 0x43, 0x06, 0xb4, 0x98, 0x88, 0x88, 0xd1, 0x62, 0x32, 0x50, 0x01, 0x60, 0x20, 0x86, 0xa7, 0x68, 0xad, 0x74, - 0x6c, 0xb3, 0x85, 0xbe, 0x52, 0xd3, 0x2c, 0x82, 0x91, 0xd4, 0x0e, 0xab, 0xb0, 0xb2, 0x76, 0x0f, 0x41, 0x20, 0x6e, - 0xfc, 0x74, 0xf1, 0xf6, 0x8d, 0x8c, 0x5c, 0x9d, 0x8c, 0xf0, 0xc8, 0xa6, 0x34, 0x8d, 0x2d, 0x44, 0x88, 0x79, 0x63, - 0x28, 0x15, 0xca, 0x29, 0x05, 0xfb, 0xcc, 0xaa, 0xd4, 0x17, 0x9b, 0x17, 0xa0, 0x81, 0x4c, 0x23, 0xb1, 0x63, 0xc4, - 0x16, 0xa5, 0xbc, 0x7c, 0x9e, 0xee, 0xb7, 0x31, 0x83, 0xfc, 0xb0, 0xbe, 0x15, 0x01, 0x9d, 0xc1, 0x57, 0xb4, 0x06, - 0xd0, 0xc7, 0xaa, 0xe3, 0xbc, 0x08, 0x65, 0xfc, 0x7f, 0x8b, 0xbc, 0xbc, 0x17, 0xd4, 0xc5, 0x71, 0x1a, 0x09, 0xe1, - 0x27, 0x2f, 0x8c, 0x8d, 0x2b, 0xa1, 0xfb, 0x23, 0xc3, 0x96, 0x54, 0x2f, 0x9c, 0x96, 0x53, 0xbf, 0x7b, 0x97, 0x4c, - 0x09, 0x2a, 0x76, 0x2c, 0x68, 0x5d, 0xa8, 0x7a, 0xe8, 0x6b, 0xfe, 0x12, 0x54, 0x4d, 0xd4, 0xde, 0xf3, 0x79, 0x5b, - 0xd1, 0xd9, 0xd4, 0x98, 0x13, 0xf5, 0x96, 0x09, 0x9e, 0x70, 0x14, 0x17, 0xe9, 0x78, 0xcc, 0x4a, 0xe4, 0xda, 0x7a, - 0xa8, 0x72, 0xbd, 0xae, 0x9b, 0x9e, 0xb5, 0x79, 0xf3, 0xe8, 0xf6, 0x36, 0x3d, 0x6f, 0xf3, 0xf6, 0xb1, 0xb8, 0x76, - 0xcf, 0x29, 0x63, 0xa4, 0xb9, 0xc9, 0x28, 0x89, 0x1d, 0xb4, 0xce, 0xce, 0x62, 0x0a, 0xa7, 0xa0, 0xb4, 0xe9, 0x70, - 0x5e, 0x99, 0xb6, 0x72, 0x74, 0x2e, 0x0d, 0x85, 0x1d, 0xbf, 0xf0, 0x40, 0x98, 0xdb, 0x3c, 0x2a, 0xdd, 0x6c, 0xef, - 0x5b, 0x1b, 0x2e, 0x85, 0xc7, 0x3a, 0x18, 0xf2, 0x00, 0xed, 0xbb, 0xcb, 0x0c, 0x5d, 0x83, 0x10, 0x95, 0x4b, 0x54, - 0x69, 0x93, 0xe9, 0x7c, 0xfa, 0xbc, 0x88, 0x68, 0x1a, 0x9e, 0x26, 0xe3, 0xa4, 0x2a, 0x83, 0x08, 0xb5, 0xdb, 0x6d, - 0xe9, 0xab, 0xed, 0x1a, 0x54, 0x5c, 0x8b, 0xbf, 0xeb, 0x83, 0xbc, 0xf3, 0xb5, 0x94, 0x13, 0xe7, 0x31, 0x9a, 0xd9, - 0x8c, 0xc5, 0xc0, 0xdf, 0xd3, 0x7c, 0x1c, 0x15, 0x49, 0x35, 0x99, 0xfe, 0xa3, 0xd9, 0xe1, 0x97, 0x55, 0x9f, 0x36, - 0xac, 0x10, 0x24, 0x51, 0x36, 0x04, 0x7d, 0xec, 0xe0, 0xfb, 0xfb, 0x49, 0xea, 0x4c, 0x78, 0x9b, 0x75, 0xd8, 0x21, - 0x3b, 0x06, 0x09, 0x95, 0xb5, 0x8f, 0x71, 0xeb, 0x3e, 0x4e, 0xe7, 0x40, 0x8b, 0x5c, 0xbc, 0x7f, 0xad, 0x3a, 0xf7, - 0x4f, 0xf7, 0xcd, 0xad, 0x03, 0x85, 0x2f, 0xd1, 0xc5, 0x0a, 0x7e, 0x2f, 0xa3, 0x06, 0x3a, 0x8e, 0x1d, 0xb2, 0x6e, - 0x66, 0x9b, 0x4e, 0xb4, 0x7d, 0xe1, 0xfc, 0xb0, 0x87, 0xfe, 0xdc, 0x62, 0x66, 0x9b, 0xe8, 0xf6, 0x2d, 0x1e, 0x03, - 0xf3, 0xd8, 0xac, 0x34, 0x62, 0x28, 0xe8, 0x19, 0xf4, 0xf0, 0x40, 0x12, 0xde, 0xdb, 0x43, 0xaf, 0x23, 0x6b, 0x34, - 0x89, 0x88, 0x7e, 0x90, 0x34, 0x6b, 0x69, 0x18, 0xac, 0x00, 0x9d, 0x3b, 0xdf, 0x25, 0xe1, 0x52, 0xc0, 0xb6, 0x42, - 0x2a, 0xcc, 0x0b, 0x3b, 0xae, 0x9e, 0x4d, 0x2a, 0x48, 0x89, 0x46, 0x16, 0x26, 0x83, 0xa1, 0x00, 0x95, 0xc8, 0x47, - 0x23, 0xc8, 0x42, 0xd6, 0x51, 0xf0, 0x6f, 0xf0, 0x35, 0x71, 0x91, 0x01, 0x1f, 0x27, 0xd9, 0xa3, 0xea, 0x0f, 0x5e, - 0xe4, 0xf4, 0x4a, 0x16, 0x0c, 0x20, 0x62, 0x38, 0x8b, 0x0e, 0x8b, 0xd3, 0x64, 0x86, 0x9f, 0x8e, 0x0b, 0x3c, 0xf4, - 0x83, 0xbf, 0xc9, 0x30, 0xb0, 0xeb, 0x44, 0xf2, 0xf5, 0xab, 0x88, 0xe9, 0xc2, 0x86, 0x45, 0x74, 0xfd, 0x36, 0x7b, - 0x82, 0x2b, 0xea, 0x51, 0xc1, 0x23, 0xcc, 0xc6, 0xa4, 0x0f, 0x58, 0x15, 0xbe, 0x60, 0x9d, 0xaf, 0x08, 0x70, 0xc1, - 0x29, 0xbd, 0x88, 0x0f, 0x55, 0xec, 0x46, 0x5f, 0xd7, 0x45, 0x99, 0xc4, 0xa5, 0x4d, 0xa6, 0x88, 0x42, 0xa5, 0x87, - 0xb0, 0x62, 0x32, 0xea, 0x89, 0xdd, 0x99, 0x61, 0x54, 0x4e, 0x82, 0xcb, 0x3e, 0xfd, 0xbe, 0x15, 0x25, 0x5b, 0x4c, - 0x46, 0x9c, 0x59, 0x31, 0xba, 0x38, 0xd5, 0x2a, 0xdf, 0x66, 0xb8, 0x0f, 0x8b, 0xb7, 0x77, 0xd6, 0xc8, 0xe7, 0x91, - 0x22, 0x9b, 0x47, 0xab, 0x15, 0x75, 0x04, 0xc8, 0x3a, 0x2c, 0x94, 0xf7, 0x6a, 0xd9, 0xb4, 0x70, 0x79, 0xe8, 0xb7, - 0x63, 0x78, 0x4d, 0xf0, 0x32, 0x52, 0x55, 0x1f, 0x88, 0x2f, 0xf9, 0x57, 0x09, 0x92, 0x96, 0x95, 0x22, 0x86, 0x63, - 0x35, 0x76, 0xc8, 0xac, 0x9e, 0x23, 0x3d, 0xbf, 0xf8, 0x2a, 0x60, 0xad, 0x9e, 0xdf, 0xe9, 0x82, 0x14, 0x4f, 0x47, - 0x0f, 0x28, 0x56, 0xfc, 0xf3, 0x5d, 0xe2, 0x1b, 0x54, 0x90, 0xb7, 0x78, 0xe1, 0x9a, 0x16, 0x81, 0x3e, 0xa7, 0xd1, - 0x17, 0xf1, 0x20, 0x62, 0xf8, 0x68, 0x2b, 0x5b, 0x5c, 0xe4, 0x65, 0xf9, 0x48, 0xa4, 0x09, 0xd6, 0x83, 0x2c, 0xf2, - 0x15, 0x36, 0x81, 0xb2, 0xfe, 0x10, 0x18, 0x39, 0x21, 0x82, 0x7c, 0x96, 0xfd, 0xa6, 0xb3, 0x02, 0x78, 0xda, 0x61, - 0xc7, 0xfc, 0x69, 0xa1, 0xf8, 0xeb, 0xe8, 0x92, 0xaa, 0xbf, 0x1d, 0xc1, 0xfe, 0x41, 0xd4, 0x02, 0xf9, 0x4e, 0xe0, - 0xa1, 0x2f, 0xd1, 0x49, 0x8b, 0x66, 0xfa, 0x71, 0xa3, 0x24, 0x62, 0x58, 0xbd, 0xa0, 0x2d, 0xc6, 0x6d, 0x14, 0x17, - 0x99, 0xff, 0xc1, 0x07, 0x84, 0x05, 0x77, 0xf5, 0xc4, 0x88, 0x2c, 0x6a, 0xf9, 0xd4, 0xe5, 0xaf, 0xba, 0xc4, 0xb5, - 0x8b, 0xf7, 0xa6, 0x98, 0x9b, 0x42, 0x07, 0x14, 0xa5, 0xd9, 0x81, 0xe5, 0xbb, 0x96, 0x11, 0x8d, 0x10, 0xf0, 0x9e, - 0x14, 0xbf, 0xd4, 0xf4, 0x29, 0x71, 0x8c, 0x2c, 0x8f, 0xd0, 0x13, 0x4b, 0xb8, 0x53, 0xd2, 0x9c, 0x18, 0xc8, 0x53, - 0xc0, 0x66, 0x55, 0x18, 0xe1, 0xf8, 0x78, 0x23, 0x15, 0xf1, 0xdd, 0x59, 0x6d, 0x19, 0xc0, 0x9a, 0xbc, 0x25, 0x06, - 0xb5, 0xad, 0xa0, 0x9a, 0xa0, 0xe5, 0x36, 0xa1, 0x72, 0x6d, 0x82, 0x9d, 0xf5, 0x81, 0x6c, 0xed, 0xfa, 0xda, 0x37, - 0x5a, 0xf4, 0x78, 0xb9, 0xdd, 0xe9, 0x2b, 0xcf, 0xb6, 0x25, 0x1b, 0xda, 0x36, 0xe0, 0xe6, 0xb6, 0xe0, 0xca, 0xb8, - 0x3a, 0x99, 0x6d, 0x5e, 0xe3, 0x69, 0xa3, 0xfd, 0x92, 0xc4, 0xde, 0x16, 0xb7, 0xb7, 0xc2, 0x1b, 0x0d, 0xbd, 0x11, - 0x8a, 0xfe, 0x58, 0x59, 0xbf, 0x9b, 0x84, 0xb8, 0xbd, 0x00, 0x82, 0x0b, 0xfe, 0x6c, 0xeb, 0xc3, 0x36, 0xd7, 0xa5, - 0x8f, 0xc9, 0x9a, 0xbc, 0x62, 0x05, 0x2c, 0x96, 0x7e, 0x90, 0xe8, 0xdd, 0x25, 0x3b, 0x8d, 0xec, 0x44, 0xbd, 0xe1, - 0x75, 0xd9, 0x95, 0x3a, 0x72, 0x30, 0x8d, 0xef, 0xb8, 0x62, 0x4f, 0x8b, 0x96, 0xb5, 0x68, 0xf7, 0x6b, 0x1a, 0x4c, - 0x28, 0x16, 0xa5, 0x3c, 0xb8, 0x05, 0xda, 0x93, 0x23, 0x8b, 0x19, 0xf4, 0xbf, 0xab, 0x48, 0x2c, 0x32, 0xff, 0xeb, - 0xe4, 0xe4, 0x44, 0xa6, 0x48, 0x9f, 0xbf, 0x92, 0x4e, 0xc0, 0x51, 0x02, 0xff, 0x96, 0xc4, 0x9c, 0x6c, 0xc8, 0xef, - 0xb1, 0x2b, 0x61, 0x16, 0x9e, 0x67, 0x52, 0x5c, 0xc2, 0xdb, 0x1e, 0x91, 0xf2, 0xa0, 0xf8, 0xf7, 0x74, 0xad, 0x9c, - 0xba, 0x2e, 0x4a, 0x85, 0x53, 0xd6, 0x15, 0xf2, 0x6f, 0xf4, 0x7a, 0x29, 0xdc, 0x64, 0xf0, 0x86, 0x04, 0x58, 0x7a, - 0xf4, 0x4c, 0x22, 0xad, 0xf4, 0x94, 0x01, 0x65, 0x2e, 0x9f, 0xc7, 0x13, 0x61, 0xf9, 0x97, 0x2f, 0x54, 0x56, 0x5e, - 0x35, 0x84, 0x91, 0xbb, 0x80, 0x03, 0x8a, 0xa8, 0xa0, 0xce, 0x0f, 0x3a, 0x00, 0xe8, 0xce, 0x1b, 0x3e, 0xe7, 0x3f, - 0xb0, 0x1d, 0x93, 0x82, 0x2f, 0x8f, 0x8a, 0x24, 0x4a, 0xe1, 0xc1, 0x04, 0x02, 0xc5, 0xa3, 0x90, 0x14, 0x4b, 0x93, - 0xd1, 0xb5, 0xda, 0x40, 0x02, 0x91, 0x82, 0xa6, 0x0e, 0x31, 0xb2, 0x17, 0x32, 0x46, 0xa3, 0xdf, 0x61, 0x32, 0x38, - 0x98, 0x88, 0x08, 0x2b, 0x02, 0xa9, 0x63, 0xdc, 0x3a, 0x3d, 0x1a, 0x7a, 0x7b, 0xbc, 0x36, 0x21, 0x64, 0x4c, 0x0e, - 0xcf, 0x41, 0xf7, 0xdd, 0x98, 0x2c, 0xcf, 0xfe, 0xcc, 0x9a, 0xa0, 0xda, 0x27, 0x26, 0xdd, 0x2e, 0xbe, 0x59, 0x30, - 0xb6, 0x8a, 0xd0, 0xd2, 0x7b, 0x74, 0x93, 0x80, 0x08, 0x79, 0xe3, 0xa8, 0x24, 0xbc, 0x19, 0x9d, 0x30, 0x35, 0x5c, - 0x4e, 0xf3, 0x21, 0x17, 0x84, 0x9e, 0x97, 0x00, 0x51, 0xca, 0x2b, 0x31, 0x92, 0x18, 0x70, 0x1a, 0x29, 0x1a, 0xbd, - 0xcc, 0x94, 0x92, 0x82, 0x7c, 0x95, 0xaa, 0x98, 0x46, 0x09, 0x45, 0x17, 0x7b, 0x54, 0xce, 0xa0, 0xac, 0x40, 0x80, - 0x5d, 0x89, 0x86, 0x79, 0xf6, 0x82, 0x40, 0x41, 0x57, 0x7a, 0xcb, 0x94, 0x27, 0x38, 0x79, 0x56, 0x0a, 0x12, 0x35, - 0x58, 0x05, 0xfa, 0x9b, 0x59, 0x3a, 0x07, 0x31, 0xc3, 0x20, 0x03, 0x74, 0x66, 0x06, 0x98, 0x0f, 0xba, 0x9d, 0x2e, - 0x42, 0x74, 0xa8, 0x86, 0xef, 0x82, 0x84, 0xe9, 0x6f, 0x88, 0x4d, 0xc1, 0x2c, 0xe9, 0x2f, 0x50, 0xb8, 0x78, 0x44, - 0x0a, 0xa2, 0x0a, 0x2f, 0xfb, 0x36, 0xfb, 0x90, 0xcf, 0x4c, 0xbe, 0xa2, 0x71, 0x2a, 0x70, 0xbd, 0xf4, 0x1b, 0xf6, - 0x56, 0x74, 0xe9, 0x95, 0xb5, 0x7c, 0x61, 0x3d, 0xab, 0x9b, 0x46, 0xbc, 0x15, 0x5d, 0x9b, 0xa5, 0xb3, 0x06, 0x5c, - 0xdf, 0x11, 0x61, 0xea, 0xab, 0x7f, 0x9a, 0x67, 0xe2, 0x43, 0x84, 0x0a, 0x70, 0xaf, 0x8d, 0xfc, 0x97, 0x95, 0xc8, - 0x17, 0x7c, 0x48, 0x87, 0x07, 0x52, 0x64, 0xc8, 0xb4, 0xc0, 0x0a, 0xfd, 0x92, 0xa1, 0x88, 0xef, 0x50, 0xfc, 0xe0, - 0x6d, 0x1b, 0xc8, 0xa0, 0x67, 0xbb, 0x39, 0x5b, 0x5e, 0x46, 0xfd, 0x40, 0xe8, 0x43, 0x41, 0x8e, 0xbe, 0x3d, 0xd7, - 0x20, 0x5f, 0xab, 0x40, 0xc5, 0x0c, 0x12, 0x82, 0x65, 0x3d, 0x98, 0xb1, 0x08, 0xa7, 0xac, 0xdc, 0x39, 0x29, 0xfa, - 0x6f, 0xd4, 0x67, 0x69, 0x88, 0xbe, 0xc7, 0x4a, 0x3c, 0x7d, 0xe7, 0xc6, 0x5e, 0xaf, 0x2e, 0xe1, 0xc3, 0x0c, 0xa4, - 0x20, 0xc2, 0x07, 0x8f, 0x5c, 0xdc, 0xc0, 0x02, 0x9d, 0x1a, 0xaa, 0x89, 0x05, 0xa9, 0xc2, 0x13, 0xa9, 0x31, 0x69, - 0xac, 0x72, 0x23, 0x10, 0x92, 0xed, 0xdd, 0x71, 0xae, 0xc2, 0x81, 0x93, 0xf4, 0xfa, 0x9c, 0x94, 0xc3, 0x69, 0xec, - 0xd6, 0xf8, 0x4c, 0x02, 0xac, 0x34, 0xa9, 0x71, 0x4c, 0xf4, 0xf6, 0xb6, 0xb9, 0x0a, 0xda, 0xd1, 0x90, 0xab, 0x08, - 0x1a, 0x82, 0x31, 0x13, 0xf0, 0x34, 0xb3, 0xcd, 0xda, 0x2c, 0x9c, 0x07, 0xa5, 0xdb, 0x7a, 0x0b, 0x6a, 0x4d, 0xad, - 0x1b, 0x51, 0x40, 0xc4, 0xbb, 0x1c, 0xc6, 0x6c, 0x1e, 0xb3, 0x71, 0xdc, 0xb7, 0xd9, 0x8d, 0x65, 0xb3, 0x45, 0x97, - 0xeb, 0x67, 0xd2, 0x8d, 0xd0, 0x13, 0x8f, 0x82, 0xfe, 0x78, 0x3d, 0x44, 0xf8, 0x00, 0xb3, 0x90, 0x96, 0xf4, 0xe4, - 0x6f, 0x43, 0xdc, 0x16, 0xee, 0x35, 0x20, 0x43, 0x90, 0x91, 0x9e, 0x7a, 0xd0, 0x59, 0xa2, 0xb6, 0x86, 0x33, 0xbb, - 0xd9, 0x01, 0xad, 0x55, 0xd6, 0x67, 0xf8, 0xcb, 0x40, 0xbb, 0xed, 0x20, 0xa2, 0x08, 0xe7, 0xa4, 0xca, 0x9a, 0xa3, - 0x1c, 0xf8, 0x95, 0x48, 0x09, 0x13, 0x7f, 0xca, 0xa3, 0x72, 0x5e, 0xd0, 0x05, 0x7a, 0x6e, 0xe9, 0xf9, 0x24, 0xef, - 0x32, 0xe9, 0x23, 0x8a, 0xf7, 0xd5, 0xe5, 0xe8, 0xb8, 0x01, 0x7a, 0x79, 0x5e, 0x53, 0xb9, 0xaf, 0xb4, 0x03, 0x8d, - 0xb7, 0x04, 0x9d, 0x9d, 0x54, 0x7e, 0xb1, 0x5d, 0x9a, 0x89, 0x2b, 0xfa, 0xc4, 0x0f, 0x9d, 0x05, 0xc4, 0x9d, 0x37, - 0xd0, 0xdd, 0x06, 0xd1, 0x18, 0xc5, 0x58, 0x8c, 0x43, 0xb8, 0x91, 0x70, 0x7b, 0x7b, 0xd9, 0xef, 0x66, 0x44, 0x9e, - 0xe5, 0x05, 0x82, 0xba, 0xa2, 0xed, 0x15, 0xe0, 0x56, 0xb7, 0xa0, 0xe6, 0x15, 0xd9, 0x7e, 0x22, 0xba, 0xe3, 0x2c, - 0x91, 0x49, 0xf2, 0x9a, 0x12, 0x73, 0x13, 0x79, 0xcd, 0x03, 0x9c, 0x42, 0x57, 0xb1, 0x21, 0x9b, 0x0b, 0x1f, 0x4e, - 0xba, 0xd0, 0x2a, 0xa2, 0x7b, 0xac, 0xf0, 0xfa, 0x6c, 0xe0, 0xeb, 0x31, 0xe8, 0x00, 0x2a, 0xdc, 0xf9, 0xee, 0x7b, - 0x77, 0xe8, 0x79, 0xb0, 0xb2, 0x10, 0xa6, 0xe2, 0xc8, 0xf6, 0xd0, 0xf8, 0xed, 0x53, 0x26, 0x09, 0x0c, 0xe4, 0xc4, - 0x3c, 0xb4, 0x9d, 0x98, 0x53, 0xa8, 0x70, 0x1e, 0x0e, 0xd1, 0x89, 0x79, 0x6e, 0xd5, 0x36, 0x17, 0x97, 0x9d, 0x5a, - 0xf5, 0xcd, 0x41, 0xf9, 0x4c, 0x90, 0xa6, 0x55, 0x78, 0xad, 0x89, 0xb9, 0x56, 0x5e, 0x5d, 0xb2, 0x75, 0xd0, 0x41, - 0x43, 0xc2, 0xe8, 0x5c, 0x0d, 0x42, 0x1c, 0x0d, 0x17, 0xfd, 0x1e, 0x51, 0xbf, 0xa5, 0x6f, 0x43, 0x79, 0x99, 0x43, - 0xdf, 0xfb, 0xdd, 0x5c, 0x79, 0x49, 0xb4, 0xd8, 0xc8, 0x5c, 0x84, 0x62, 0x26, 0xef, 0x5b, 0xb5, 0xbe, 0xe5, 0x9d, - 0xa8, 0xfb, 0x55, 0xd7, 0xf9, 0x31, 0x4a, 0x40, 0xbb, 0xb8, 0x3f, 0x64, 0xe2, 0x83, 0x1d, 0x74, 0x30, 0x0a, 0x5a, - 0xd0, 0xaa, 0x29, 0xa4, 0xc2, 0xcd, 0xce, 0xad, 0x9a, 0xa5, 0xb7, 0x9f, 0x61, 0x18, 0xb2, 0xd2, 0x34, 0x77, 0x53, - 0x5a, 0xa6, 0xa1, 0x04, 0xb9, 0xfe, 0x13, 0xe1, 0xc4, 0xea, 0x3a, 0x9d, 0xa1, 0x43, 0x4e, 0x92, 0x62, 0xfa, 0xf0, - 0xee, 0x23, 0xf4, 0x12, 0x50, 0x31, 0xa8, 0x29, 0x89, 0x1c, 0x09, 0xde, 0xc3, 0x9c, 0x93, 0x1c, 0x92, 0x48, 0x04, - 0x4d, 0x7c, 0x11, 0x94, 0x56, 0x7e, 0x24, 0x20, 0x67, 0x9a, 0x5c, 0x58, 0xe8, 0x79, 0xa3, 0x9f, 0x19, 0x49, 0x64, - 0x56, 0xc7, 0xe2, 0x8d, 0x75, 0x82, 0x27, 0xf2, 0x99, 0x41, 0x10, 0x35, 0x15, 0x20, 0xb4, 0x60, 0xbc, 0xee, 0x0b, - 0x5c, 0xa0, 0x6c, 0x86, 0x07, 0x04, 0xa5, 0x06, 0xc7, 0xf0, 0x74, 0x99, 0xb0, 0x24, 0x13, 0x6e, 0x4d, 0x43, 0x77, - 0x76, 0x7b, 0xdb, 0xf2, 0xf6, 0x7f, 0xa3, 0x2b, 0xa9, 0x47, 0xda, 0xe0, 0x3e, 0x32, 0x06, 0x77, 0xf4, 0x04, 0x0c, - 0x47, 0x96, 0xad, 0x9d, 0xe5, 0xb6, 0x19, 0x1d, 0xa3, 0xa5, 0xbf, 0xc4, 0xd8, 0xd9, 0x92, 0x2d, 0xa1, 0x9d, 0x7d, - 0xa3, 0x80, 0xb0, 0xb5, 0xeb, 0x12, 0x1e, 0x29, 0xee, 0x6a, 0x11, 0x90, 0x09, 0x91, 0xce, 0xfc, 0xd1, 0xad, 0x16, - 0x89, 0x2f, 0xcf, 0x73, 0x4d, 0x49, 0x74, 0x07, 0xb6, 0x47, 0xd5, 0xbb, 0x23, 0xd6, 0x1c, 0x09, 0x70, 0xc2, 0x94, - 0xc2, 0xa3, 0x80, 0x28, 0x3c, 0xcb, 0x54, 0x36, 0xd2, 0x40, 0xb6, 0xd1, 0x53, 0x3a, 0x48, 0xa1, 0x28, 0xed, 0x0a, - 0x2b, 0xd2, 0x18, 0xe8, 0xda, 0xf8, 0x2c, 0x6c, 0x41, 0x2f, 0xca, 0xeb, 0xa4, 0x02, 0xd2, 0x9d, 0xf8, 0x64, 0x18, - 0x78, 0x07, 0xa8, 0x01, 0x3d, 0x1a, 0x79, 0x4b, 0x60, 0x3f, 0xd1, 0x3c, 0xad, 0x82, 0x12, 0x88, 0x99, 0x08, 0xdc, - 0xcb, 0x45, 0x24, 0x38, 0x68, 0x6e, 0x4c, 0xf2, 0xe5, 0x27, 0x72, 0x07, 0x29, 0x62, 0x4a, 0x1e, 0x53, 0x02, 0x34, - 0x1b, 0xa7, 0x79, 0xc9, 0x45, 0x35, 0x5d, 0xe1, 0x5b, 0x8e, 0x21, 0xc9, 0x1d, 0x00, 0x1c, 0x79, 0x51, 0x3a, 0xc1, - 0x24, 0x2c, 0x7b, 0x50, 0x49, 0x30, 0x86, 0xc2, 0x28, 0xe9, 0x7d, 0xc8, 0x5d, 0xde, 0xd0, 0xbb, 0xa2, 0x53, 0x6f, - 0x7f, 0xc2, 0x32, 0xb3, 0x89, 0x0a, 0xef, 0x63, 0x8f, 0x4d, 0x1b, 0xe1, 0xa4, 0xc4, 0x13, 0xc3, 0xc0, 0x11, 0xff, - 0x6f, 0x94, 0xbf, 0xb3, 0xdb, 0x18, 0x62, 0xfa, 0x3d, 0xae, 0x14, 0x3e, 0x74, 0x82, 0x34, 0xc4, 0x53, 0x8b, 0xed, - 0x13, 0x16, 0x87, 0xe3, 0x66, 0xaa, 0x02, 0xee, 0x51, 0x2d, 0x8d, 0x9b, 0xca, 0xdb, 0x8f, 0xd9, 0x70, 0x3d, 0xc9, - 0xa5, 0xb1, 0x36, 0xd3, 0x20, 0x46, 0xfe, 0x6e, 0x7a, 0x21, 0xcb, 0xcf, 0xd7, 0x93, 0xec, 0xf2, 0x12, 0xb8, 0xcd, - 0x21, 0xf4, 0x37, 0x02, 0x04, 0x9f, 0x36, 0xdf, 0xc0, 0x7f, 0x1f, 0x75, 0x46, 0x63, 0x0e, 0x19, 0x05, 0x65, 0x7c, - 0x64, 0x53, 0x93, 0x0c, 0xe5, 0x1b, 0x54, 0x1e, 0xc0, 0x60, 0x4a, 0x37, 0xa1, 0x74, 0x83, 0x4a, 0x37, 0xa0, 0x74, - 0xe3, 0xcd, 0xbf, 0x19, 0xb4, 0x13, 0x20, 0xba, 0xcc, 0x80, 0xe0, 0x88, 0x2e, 0x5e, 0xfc, 0xf2, 0xfe, 0x43, 0xfb, - 0xaa, 0xb3, 0x3f, 0x66, 0x6a, 0xfe, 0x62, 0xc2, 0x31, 0x58, 0xe5, 0xbc, 0x89, 0x10, 0x8d, 0x59, 0x07, 0x20, 0xdb, - 0xd9, 0x8f, 0x65, 0x55, 0x2b, 0x98, 0x83, 0x9b, 0xca, 0x86, 0x22, 0xd4, 0x69, 0xc3, 0x47, 0x0d, 0x36, 0x18, 0x7b, - 0x35, 0x50, 0xc2, 0x84, 0xd4, 0x40, 0x85, 0xef, 0xf3, 0xda, 0xbb, 0xf9, 0xce, 0x60, 0x90, 0x80, 0x92, 0x67, 0xcf, - 0x39, 0x81, 0xa7, 0x96, 0x42, 0x90, 0xb1, 0x53, 0x04, 0x50, 0xbe, 0x03, 0x0a, 0x32, 0x9e, 0x50, 0xd7, 0xad, 0xe1, - 0x50, 0xe2, 0xff, 0xe3, 0xc1, 0xe8, 0xae, 0xeb, 0x25, 0xb3, 0x31, 0x3c, 0x39, 0x18, 0xbb, 0xfb, 0x28, 0x63, 0xfd, - 0x7f, 0xdb, 0x51, 0x46, 0x20, 0x65, 0xff, 0x9f, 0xf6, 0xce, 0x06, 0x23, 0x66, 0x39, 0x41, 0x21, 0x11, 0xff, 0xfb, - 0xdd, 0xb2, 0x9a, 0x2f, 0x36, 0x9a, 0x2f, 0xa8, 0x79, 0xbb, 0x6a, 0x32, 0xe5, 0x04, 0xe6, 0x23, 0x41, 0xfe, 0xeb, - 0x74, 0x6b, 0x03, 0x34, 0x59, 0x8d, 0x9e, 0x8d, 0xed, 0x0a, 0x77, 0xdb, 0xc1, 0x16, 0x64, 0x5e, 0x25, 0xe2, 0x86, - 0x54, 0x64, 0xbe, 0xd6, 0x9e, 0xea, 0x79, 0x0b, 0x4f, 0x6f, 0x96, 0x64, 0xaf, 0x74, 0x6d, 0xcf, 0xc1, 0x68, 0xdd, - 0x95, 0x9b, 0x9c, 0xa5, 0xfd, 0x63, 0x46, 0x47, 0x11, 0xf1, 0xa3, 0x9b, 0x73, 0x34, 0x8a, 0x8f, 0xaa, 0x26, 0xa7, - 0xb7, 0x33, 0xe0, 0xa9, 0x24, 0xf0, 0xd2, 0xeb, 0x02, 0x32, 0xab, 0x7c, 0x26, 0xf2, 0x16, 0x67, 0xd8, 0x26, 0x5a, - 0x58, 0x1b, 0x96, 0xdf, 0x7e, 0x22, 0xfd, 0x20, 0x2d, 0x26, 0x68, 0x33, 0x20, 0x49, 0x5a, 0x44, 0x1b, 0x8c, 0x6a, - 0x63, 0xb2, 0x89, 0xa6, 0x4e, 0x14, 0xb5, 0x36, 0x29, 0x57, 0xac, 0xe1, 0x64, 0x66, 0xcb, 0x14, 0x59, 0x21, 0xec, - 0xe3, 0x5b, 0xc4, 0x8d, 0x6f, 0x35, 0x41, 0xa2, 0x6e, 0x64, 0xd2, 0xd0, 0xf7, 0x6f, 0x40, 0xac, 0x5e, 0xd0, 0x29, - 0xc6, 0x92, 0xce, 0xfb, 0x50, 0x5c, 0x7e, 0xc7, 0x68, 0x72, 0xe8, 0xd9, 0xdf, 0x80, 0x62, 0xe8, 0x9e, 0xa8, 0x3f, - 0xcb, 0xa1, 0x67, 0x0b, 0x6b, 0x12, 0x73, 0xaa, 0x64, 0x45, 0x02, 0x28, 0x55, 0x23, 0xcc, 0x83, 0xbb, 0x18, 0xe8, - 0xa1, 0xa7, 0x4b, 0x55, 0xb2, 0xb1, 0xa0, 0xd6, 0x7c, 0x45, 0xcd, 0xaf, 0x77, 0xc8, 0x0c, 0xe3, 0xda, 0x92, 0x9a, - 0xfe, 0xdd, 0x20, 0x00, 0xbe, 0x7f, 0x27, 0xbc, 0x78, 0x32, 0x2f, 0x08, 0xd3, 0xb2, 0x1e, 0x48, 0x6a, 0xb3, 0x36, - 0xba, 0xea, 0xc5, 0xb3, 0xce, 0x0d, 0x93, 0xef, 0x0b, 0xf1, 0xbe, 0x80, 0x77, 0x4e, 0x19, 0x01, 0xa7, 0x62, 0xea, - 0x7d, 0x21, 0xde, 0x17, 0x6c, 0xb3, 0x33, 0x5f, 0xd5, 0x86, 0xa2, 0x16, 0x67, 0x20, 0x15, 0x31, 0xc0, 0x48, 0x37, - 0xb5, 0x2c, 0x0a, 0x02, 0x5b, 0x4b, 0xc0, 0x38, 0x9f, 0xcf, 0x5c, 0x23, 0xab, 0x79, 0x28, 0x7d, 0xaa, 0xa3, 0xed, - 0x26, 0x15, 0x65, 0x4c, 0xb4, 0x88, 0x50, 0x6c, 0x1b, 0xba, 0xdd, 0x0c, 0xa5, 0xbc, 0xb0, 0xd2, 0x76, 0x12, 0x1f, - 0x65, 0x55, 0x32, 0x79, 0x53, 0x11, 0xfd, 0x16, 0x5a, 0x39, 0xaa, 0xd8, 0x63, 0x58, 0x34, 0x08, 0x2b, 0x5d, 0x52, - 0x25, 0x84, 0xf5, 0x7c, 0xfb, 0xa4, 0xe6, 0x3a, 0xf2, 0x88, 0x7b, 0x7e, 0xbf, 0xf2, 0x6a, 0x02, 0x52, 0xf5, 0x78, - 0x82, 0x67, 0x68, 0x51, 0x64, 0x28, 0xe8, 0x3b, 0xe3, 0xeb, 0x5f, 0xd3, 0xdc, 0x32, 0xa4, 0x70, 0x55, 0x33, 0xf7, - 0x41, 0x6d, 0x9d, 0x47, 0x29, 0x79, 0x92, 0x82, 0x6c, 0xf9, 0x38, 0xbf, 0x79, 0x85, 0xd8, 0x1d, 0x85, 0x55, 0x63, - 0x4b, 0xde, 0x7b, 0x5c, 0x01, 0x20, 0x7f, 0xf0, 0x6d, 0x1f, 0x3e, 0x2a, 0xd1, 0xe6, 0x0f, 0xea, 0x3d, 0xdf, 0xf6, - 0xe9, 0x53, 0x2e, 0xb2, 0x81, 0x7f, 0xd7, 0xbb, 0xdb, 0x73, 0xe3, 0x46, 0x0a, 0x28, 0x1c, 0xa4, 0x5d, 0x45, 0x0c, - 0x04, 0x40, 0x2d, 0xe0, 0x6e, 0x2c, 0x4f, 0xbd, 0x77, 0x13, 0xa2, 0xdd, 0x25, 0xce, 0xc5, 0x76, 0x39, 0xa5, 0xdc, - 0xde, 0x76, 0x0c, 0x15, 0x2c, 0xd8, 0xc4, 0x5a, 0x0b, 0x91, 0x78, 0xdb, 0x42, 0x71, 0x5e, 0xc7, 0xeb, 0xae, 0xe7, - 0xba, 0xed, 0xee, 0x96, 0x49, 0x66, 0x22, 0xed, 0xfd, 0x16, 0x22, 0x21, 0x24, 0xe1, 0xca, 0x92, 0x84, 0xcd, 0xd7, - 0x16, 0x01, 0xba, 0xb2, 0x54, 0x6e, 0x10, 0xe7, 0x97, 0x2b, 0xe3, 0x74, 0x6f, 0x9d, 0xbb, 0x8d, 0x40, 0xa7, 0x2b, - 0xcd, 0x0e, 0x0f, 0x12, 0x4c, 0x95, 0x40, 0x66, 0x3a, 0xba, 0x9a, 0xba, 0x76, 0xeb, 0xf2, 0xba, 0x6a, 0xab, 0xee, - 0x80, 0x66, 0xb4, 0x3c, 0x28, 0x86, 0x32, 0xaa, 0x81, 0xea, 0x8c, 0x78, 0xb7, 0xd1, 0x88, 0x3d, 0x34, 0xc8, 0x80, - 0x0a, 0x9b, 0xfb, 0xca, 0x8a, 0xbe, 0xb7, 0x47, 0xf0, 0x30, 0x09, 0x20, 0x3d, 0xa2, 0x12, 0x62, 0x37, 0x4d, 0x08, - 0x6b, 0x4f, 0x57, 0x2d, 0x17, 0x17, 0x52, 0xad, 0xeb, 0x78, 0xfe, 0xcb, 0x9e, 0xb6, 0x7a, 0xa6, 0x9e, 0x14, 0xc2, - 0xcd, 0x94, 0xc0, 0x92, 0xa3, 0xf6, 0x28, 0xb2, 0x15, 0x14, 0xb7, 0xe7, 0x32, 0x5a, 0x10, 0x98, 0x98, 0xe2, 0x00, - 0xb3, 0x86, 0x3c, 0xc6, 0xe8, 0x96, 0xbe, 0xb1, 0xb2, 0xd6, 0x34, 0x66, 0x2b, 0x60, 0xb4, 0x3d, 0xef, 0x4b, 0xa0, - 0x36, 0x6c, 0x11, 0x64, 0xec, 0x1a, 0x4f, 0xd2, 0x04, 0xa0, 0xdb, 0x89, 0xcb, 0x0b, 0x8a, 0x55, 0x58, 0x75, 0x95, - 0x78, 0x5b, 0xe0, 0x3c, 0xd3, 0x1a, 0xc9, 0xac, 0x67, 0xf3, 0xd4, 0xc6, 0xb3, 0x5b, 0xec, 0x0d, 0x7a, 0x3f, 0x5b, - 0x9c, 0x14, 0x0a, 0xe7, 0xcd, 0x42, 0xb2, 0x0c, 0x2c, 0x67, 0xe4, 0x65, 0x3b, 0x75, 0xa3, 0x18, 0xab, 0xbd, 0xbc, - 0x61, 0x1f, 0xd7, 0xea, 0x6d, 0x94, 0xba, 0xb8, 0x58, 0x9b, 0x50, 0x81, 0xa9, 0x7a, 0x4b, 0xe6, 0x5a, 0x4a, 0xfd, - 0xed, 0x23, 0x68, 0x51, 0xeb, 0xf5, 0xab, 0x61, 0xbe, 0x57, 0xe8, 0x6c, 0xaa, 0x56, 0xa9, 0xb5, 0x22, 0xcc, 0x7a, - 0x6c, 0xb1, 0xe6, 0x46, 0x87, 0x2d, 0xf8, 0xa9, 0x3d, 0x9a, 0xb7, 0x31, 0x46, 0xa7, 0x17, 0x96, 0xf1, 0x5b, 0xf7, - 0xcf, 0x61, 0xc3, 0xed, 0x05, 0x7f, 0xfa, 0xf0, 0xeb, 0xf5, 0x3c, 0x77, 0x76, 0x73, 0xcb, 0xa7, 0xb7, 0x18, 0x6c, - 0xed, 0xde, 0x01, 0x7b, 0x67, 0x97, 0x4c, 0xaa, 0x28, 0x4d, 0xe2, 0x5b, 0x79, 0x21, 0xe0, 0xad, 0xbc, 0x95, 0xe8, - 0x96, 0xee, 0xb8, 0xba, 0x75, 0xf3, 0x41, 0x8a, 0x81, 0x85, 0xdd, 0x9d, 0x66, 0xef, 0xb2, 0xd5, 0x7c, 0xd8, 0x17, - 0x7f, 0x29, 0xc2, 0xbd, 0x57, 0x8b, 0xd8, 0x76, 0x6f, 0x6d, 0xe9, 0xbb, 0xe8, 0xd8, 0x81, 0xa1, 0xc0, 0x51, 0x2f, - 0x7d, 0x1b, 0x7b, 0xe2, 0xec, 0xc9, 0xed, 0x2d, 0x97, 0xd1, 0xac, 0xa5, 0x05, 0x5f, 0xc7, 0x66, 0xda, 0x6f, 0xfb, - 0x9d, 0xae, 0x52, 0x63, 0xc3, 0x06, 0x46, 0x9a, 0x66, 0x1c, 0x03, 0x49, 0x2d, 0x49, 0xc2, 0x9a, 0xdd, 0x80, 0xe8, - 0xa6, 0xf7, 0x8f, 0x30, 0xe5, 0x3e, 0x08, 0x5c, 0x07, 0x21, 0x06, 0xd0, 0x16, 0xc2, 0x91, 0xae, 0x48, 0x9d, 0x5d, - 0x7a, 0x44, 0x87, 0x19, 0x1a, 0xc9, 0xed, 0x6d, 0xcb, 0x74, 0xb3, 0x2c, 0xea, 0xdd, 0x5c, 0xae, 0x58, 0x16, 0xbe, - 0x43, 0x5b, 0x73, 0x19, 0x66, 0x3d, 0xfb, 0xa8, 0x3c, 0xde, 0x87, 0x0c, 0x24, 0x05, 0x0f, 0xe9, 0xf7, 0xb2, 0x5e, - 0x11, 0x9e, 0x3f, 0x72, 0xf1, 0x8c, 0x19, 0x4b, 0x2e, 0x2b, 0xf8, 0xe9, 0x7b, 0x81, 0x3c, 0x74, 0x16, 0x50, 0xc4, - 0x15, 0xeb, 0x5c, 0x72, 0x81, 0xe7, 0x92, 0x4b, 0x8f, 0x43, 0x5e, 0xf8, 0x28, 0x76, 0x73, 0x3c, 0x94, 0xbf, 0xe5, - 0xcc, 0xe3, 0x33, 0xdb, 0xc1, 0x94, 0xba, 0x45, 0x1b, 0xd9, 0xe8, 0x31, 0x27, 0x3c, 0x81, 0x70, 0x67, 0x40, 0x6e, - 0x6a, 0x63, 0x22, 0x79, 0x03, 0x41, 0x9a, 0xed, 0x66, 0xf4, 0x72, 0xa3, 0x8e, 0x4b, 0x47, 0xe2, 0x05, 0x6d, 0xc3, - 0x08, 0x04, 0xa2, 0xcd, 0x55, 0x85, 0xfd, 0xfa, 0x45, 0x64, 0xd9, 0xc1, 0x2b, 0xe2, 0xca, 0x3e, 0x8e, 0x43, 0xfd, - 0x33, 0x27, 0x71, 0x88, 0x20, 0x87, 0x82, 0x4a, 0x37, 0xa4, 0x10, 0xa7, 0xe9, 0x73, 0x48, 0x64, 0xbb, 0xa1, 0x84, - 0x39, 0xfb, 0x98, 0xed, 0x6f, 0xf2, 0xd8, 0x79, 0x12, 0x26, 0x64, 0x95, 0x24, 0x6b, 0xd4, 0x73, 0xa2, 0xaa, 0x32, - 0x98, 0xdf, 0x23, 0x69, 0xa5, 0x65, 0xf2, 0xa8, 0x77, 0xd7, 0xbe, 0x9d, 0x4f, 0xc7, 0xdf, 0xe2, 0x26, 0xb4, 0x22, - 0x67, 0xed, 0x96, 0xa7, 0xdc, 0x99, 0x1e, 0x29, 0x43, 0x2e, 0x7e, 0x8e, 0xbf, 0x5e, 0x37, 0xa3, 0x0b, 0x3b, 0x9d, - 0x46, 0xa6, 0xd0, 0xef, 0x5d, 0x8c, 0xc6, 0x3f, 0x1c, 0x58, 0x9e, 0x72, 0xff, 0x3a, 0x2a, 0x32, 0xf7, 0x87, 0x97, - 0x19, 0xc5, 0xaa, 0xda, 0xc1, 0x8e, 0xec, 0xd0, 0x87, 0x3b, 0xb8, 0x6b, 0x92, 0x8c, 0x12, 0x3e, 0x0c, 0x76, 0x9c, - 0x1f, 0x1a, 0x59, 0xe3, 0x07, 0xe7, 0x07, 0x3c, 0xee, 0x2c, 0x6f, 0x87, 0xd4, 0x71, 0x21, 0xd4, 0x3e, 0xd6, 0x23, - 0x6d, 0x52, 0x86, 0xa6, 0xa5, 0x6d, 0xd9, 0xde, 0x90, 0x82, 0x15, 0xf1, 0x48, 0x12, 0x6b, 0x91, 0x02, 0xc5, 0x2c, - 0x4a, 0x8a, 0xd7, 0xae, 0xd0, 0xae, 0x16, 0x97, 0x9b, 0x5a, 0x99, 0xda, 0xbe, 0x7a, 0xa4, 0x4d, 0xd0, 0xc8, 0x08, - 0x65, 0x69, 0x01, 0x09, 0x74, 0x70, 0xd1, 0x67, 0x3a, 0x25, 0x4f, 0x0a, 0x07, 0xb1, 0x8b, 0xf7, 0x1e, 0x58, 0x81, - 0x04, 0xf8, 0x5a, 0x58, 0x15, 0xdc, 0x5c, 0x31, 0x51, 0x2f, 0xf3, 0x10, 0x03, 0xd0, 0xeb, 0xd3, 0x83, 0xf9, 0x59, - 0x01, 0xfc, 0x2b, 0x47, 0x2b, 0x6c, 0x44, 0xdb, 0xaa, 0x2c, 0xda, 0xb5, 0x6f, 0x35, 0xb4, 0x5e, 0xd4, 0x81, 0xb4, - 0xb5, 0xab, 0x45, 0xa3, 0x30, 0x12, 0x2b, 0x68, 0x17, 0xbd, 0xb2, 0xad, 0xf2, 0xef, 0xdd, 0xc8, 0x13, 0xf9, 0x97, - 0xfc, 0x7e, 0x24, 0x1b, 0xec, 0xcb, 0x82, 0xa6, 0x15, 0x1d, 0x05, 0x03, 0x67, 0xae, 0x44, 0xb3, 0xb7, 0x1f, 0x47, - 0xf1, 0x84, 0xa3, 0xb9, 0x5f, 0x14, 0x35, 0x63, 0x7b, 0x5a, 0x3f, 0x37, 0x44, 0x87, 0x7d, 0x32, 0x3a, 0xec, 0x53, - 0xe2, 0x29, 0x96, 0x3c, 0xfc, 0x19, 0xc4, 0x70, 0xe6, 0x96, 0xcd, 0x0c, 0x84, 0x21, 0x94, 0xce, 0xf0, 0x00, 0x0f, - 0xfa, 0xa2, 0xec, 0xed, 0x45, 0xd2, 0xe3, 0x3e, 0x6a, 0xc4, 0xea, 0xb4, 0x27, 0x7e, 0x5d, 0xb8, 0x19, 0x6b, 0xd6, - 0xdc, 0xb4, 0xb0, 0xb6, 0x82, 0x0e, 0x8f, 0xdb, 0x11, 0x19, 0x6b, 0xf1, 0x13, 0xd6, 0xbc, 0xa9, 0xea, 0x3b, 0xd0, - 0x89, 0x57, 0x0b, 0x72, 0xf3, 0x92, 0x4e, 0xab, 0x86, 0x97, 0x8e, 0xd3, 0x17, 0x92, 0x4a, 0x48, 0x24, 0x03, 0x24, - 0x67, 0x6b, 0x57, 0x1b, 0x84, 0x64, 0x85, 0xf8, 0x59, 0xed, 0xb4, 0x1a, 0xed, 0x02, 0xc4, 0x85, 0xeb, 0xe8, 0x7d, - 0x13, 0x07, 0x4f, 0xdf, 0xea, 0x08, 0x69, 0xcb, 0x4b, 0x71, 0x75, 0xa5, 0x36, 0x6c, 0x7e, 0x88, 0xc6, 0xfd, 0xc0, - 0x11, 0x3d, 0x72, 0xd8, 0x95, 0x86, 0x24, 0x6e, 0x25, 0x5d, 0x95, 0x71, 0x3e, 0xe3, 0x65, 0x90, 0xb0, 0xab, 0x22, - 0xcf, 0xab, 0x0b, 0xf1, 0x96, 0x33, 0xb3, 0x27, 0x93, 0xb1, 0xab, 0x31, 0xaf, 0x3e, 0x44, 0x05, 0xfc, 0x05, 0xfe, - 0xad, 0x76, 0xc7, 0x82, 0x28, 0x3c, 0x87, 0x71, 0x5c, 0x46, 0x0c, 0xef, 0x5d, 0x05, 0x91, 0x9f, 0x42, 0xa0, 0x68, - 0x5c, 0xc4, 0x0d, 0xa2, 0x77, 0x45, 0x7e, 0xb3, 0x00, 0x51, 0x51, 0x1e, 0x00, 0xd4, 0x87, 0x26, 0x11, 0xfe, 0xfa, - 0x32, 0x1f, 0x61, 0x31, 0x8f, 0xc8, 0xd6, 0x2f, 0x9f, 0xfd, 0x2b, 0xa4, 0xb7, 0xfa, 0xa0, 0x20, 0x80, 0x05, 0x73, - 0x71, 0x2f, 0x0c, 0x37, 0xbe, 0xec, 0xaf, 0x8b, 0x82, 0x4e, 0x63, 0x21, 0xf4, 0x1e, 0xc7, 0xe8, 0xc1, 0xc6, 0x12, - 0x16, 0xe1, 0xa5, 0xb5, 0x50, 0xd0, 0x8a, 0x0a, 0xf2, 0x54, 0x5f, 0x4b, 0x5a, 0xfb, 0xfa, 0x3d, 0x1f, 0xe1, 0x1e, - 0x86, 0x7f, 0x77, 0x61, 0x5f, 0x82, 0x07, 0x75, 0x9a, 0x58, 0x54, 0xfb, 0x4e, 0x45, 0x1e, 0x79, 0x3b, 0x72, 0xb7, - 0xd5, 0x64, 0xe7, 0xd3, 0x8c, 0xae, 0x18, 0x86, 0xa2, 0xb0, 0xdb, 0xbd, 0x86, 0x57, 0xcf, 0x38, 0xb4, 0x61, 0xc5, - 0xf9, 0x75, 0xf6, 0x33, 0xf2, 0x98, 0xa8, 0x5e, 0x48, 0xec, 0xd1, 0x89, 0x03, 0x67, 0x12, 0x33, 0x26, 0x21, 0xf6, - 0x0a, 0x7a, 0x17, 0x8d, 0xf1, 0xa0, 0xb3, 0x79, 0x09, 0x4b, 0xd7, 0xb0, 0x15, 0x84, 0x67, 0x38, 0xc1, 0x3f, 0xe9, - 0x3a, 0x58, 0x77, 0x5b, 0x35, 0xc7, 0xd4, 0x9f, 0xab, 0xcd, 0xa3, 0xe5, 0x4b, 0x1b, 0x47, 0xda, 0x0c, 0x43, 0xeb, - 0xdc, 0x2c, 0x10, 0x45, 0x64, 0xd0, 0x0b, 0xe0, 0x83, 0x57, 0xe5, 0x7c, 0x40, 0xf3, 0x4b, 0x47, 0xc7, 0x2a, 0x42, - 0x14, 0x71, 0x5c, 0x93, 0x5d, 0x99, 0x5b, 0x60, 0x01, 0x93, 0x90, 0x07, 0x81, 0x52, 0x54, 0xea, 0xcd, 0x86, 0x20, - 0x0f, 0xcf, 0xa9, 0xd1, 0x9c, 0x1a, 0x35, 0x08, 0x25, 0xd3, 0x7d, 0xbd, 0xff, 0x8a, 0x21, 0x0c, 0xa8, 0xcc, 0x16, - 0xac, 0x2a, 0x37, 0xb0, 0x0a, 0x6f, 0xbd, 0x58, 0xc3, 0xaa, 0x1c, 0xd9, 0xb3, 0x46, 0xa3, 0xc2, 0xe0, 0x10, 0x91, - 0x3e, 0x1b, 0x8b, 0x30, 0x01, 0xb1, 0xe8, 0x55, 0x2c, 0xf3, 0xbe, 0x87, 0x43, 0x76, 0x4b, 0xb9, 0x6f, 0x0f, 0xd7, - 0x87, 0x45, 0x83, 0xf3, 0xd8, 0x53, 0x08, 0x31, 0xa1, 0xf8, 0x4f, 0x78, 0x2d, 0xf4, 0xf7, 0xaf, 0xa3, 0x95, 0x1e, - 0xe4, 0xc1, 0xbf, 0x45, 0x49, 0xac, 0xec, 0x3f, 0xc7, 0x43, 0x89, 0x84, 0x76, 0xc7, 0xd7, 0x7b, 0x68, 0x70, 0x70, - 0xa3, 0x88, 0xca, 0x48, 0x24, 0x3e, 0xd6, 0xa1, 0x87, 0x80, 0x0d, 0x23, 0x66, 0x83, 0x7c, 0x0d, 0xc5, 0xa8, 0xdb, - 0x55, 0xb8, 0xb4, 0x37, 0x70, 0xd1, 0x6b, 0x41, 0xef, 0xdf, 0xb6, 0x94, 0x96, 0x56, 0xdb, 0xe4, 0x25, 0x77, 0x20, - 0xfd, 0x6a, 0x6f, 0xf8, 0x66, 0x74, 0x5f, 0xb5, 0x7c, 0x63, 0x57, 0x12, 0xe8, 0x01, 0x06, 0x8c, 0x94, 0xcf, 0x40, - 0xf9, 0x15, 0x45, 0xd7, 0xb9, 0xcc, 0xae, 0xdb, 0x6a, 0x3e, 0x63, 0x49, 0x79, 0x61, 0xb2, 0x66, 0xe8, 0x0a, 0x8d, - 0x07, 0x54, 0x91, 0x47, 0x40, 0xd6, 0x4b, 0x5d, 0x70, 0x86, 0xea, 0x7d, 0x2f, 0xa3, 0x1c, 0x1d, 0x0d, 0xe0, 0x43, - 0xac, 0x2f, 0x9d, 0xea, 0x25, 0x78, 0x64, 0x9c, 0xc4, 0xc4, 0xa7, 0x99, 0x4a, 0x45, 0x51, 0x52, 0x38, 0x87, 0x3a, - 0xd1, 0x30, 0x9a, 0xa1, 0xdb, 0x06, 0x52, 0x70, 0xc9, 0x1f, 0xd6, 0x26, 0xca, 0xba, 0x92, 0xb7, 0x76, 0x83, 0x36, - 0xa4, 0x8a, 0x0f, 0xac, 0xbd, 0xed, 0xa2, 0xb0, 0xdc, 0x6f, 0xff, 0x51, 0x58, 0x24, 0xec, 0x90, 0xb6, 0x24, 0x61, - 0x78, 0x02, 0xed, 0xa4, 0x6b, 0x8e, 0x99, 0x60, 0x7a, 0x98, 0xd9, 0x3b, 0xcc, 0xaf, 0xd6, 0xf8, 0xab, 0xa4, 0x06, - 0x99, 0xa1, 0x06, 0xa5, 0x45, 0x0d, 0xf2, 0xfa, 0xf2, 0x2f, 0x70, 0x22, 0x44, 0x84, 0xaa, 0xcc, 0x0a, 0x88, 0x00, - 0x90, 0x44, 0x39, 0xa0, 0xf0, 0x6d, 0xc8, 0x13, 0xa0, 0x40, 0x34, 0x78, 0x8f, 0x4e, 0xe3, 0x78, 0x7b, 0x0f, 0x1e, - 0xbf, 0x14, 0x02, 0x83, 0x92, 0x14, 0x28, 0xff, 0xb9, 0xca, 0xc7, 0xcf, 0xf5, 0xec, 0x40, 0xd9, 0xa7, 0x18, 0x2b, - 0x42, 0xca, 0x17, 0x3f, 0x23, 0xd9, 0x04, 0x6e, 0x05, 0x8a, 0x3d, 0x2a, 0xfc, 0x18, 0x45, 0xd8, 0x92, 0x19, 0xde, - 0xc7, 0x6b, 0x44, 0x4f, 0x8d, 0xaa, 0x34, 0xa3, 0xca, 0xad, 0x51, 0x15, 0x8a, 0xc6, 0x45, 0xab, 0x90, 0xa3, 0xe2, - 0x12, 0x89, 0x75, 0xe3, 0x79, 0x68, 0x6c, 0xb9, 0x26, 0xba, 0xf4, 0x0c, 0xdd, 0x47, 0x5d, 0xe7, 0x3d, 0xc7, 0x8b, - 0x85, 0xe9, 0x38, 0x0a, 0xac, 0x87, 0xb8, 0x22, 0xe1, 0xb1, 0x61, 0x1d, 0x52, 0x07, 0xd2, 0xff, 0x25, 0x4f, 0x32, - 0xd7, 0x69, 0x9e, 0x3b, 0x5e, 0x03, 0xff, 0x82, 0x5a, 0xd4, 0x8d, 0xfc, 0x68, 0x38, 0x54, 0xc1, 0x6f, 0xe2, 0x90, - 0x16, 0xd9, 0xed, 0x6d, 0x66, 0x08, 0xba, 0x2f, 0x16, 0x18, 0x8a, 0x12, 0x4f, 0x51, 0x7c, 0x10, 0x12, 0x6c, 0xf8, - 0x21, 0x03, 0x75, 0x5c, 0x72, 0x29, 0x86, 0x5e, 0xcf, 0x31, 0x8c, 0x34, 0xb6, 0x84, 0x94, 0xff, 0x7c, 0xa4, 0xf6, - 0xfc, 0xa9, 0xf1, 0x4a, 0x41, 0x24, 0x57, 0x41, 0xe4, 0x6a, 0xe2, 0x48, 0x66, 0x85, 0x2d, 0xab, 0x2e, 0x65, 0x99, - 0xfb, 0xca, 0xbb, 0xba, 0x2f, 0xc2, 0xc5, 0xa1, 0x03, 0xb5, 0x67, 0x39, 0xad, 0xb0, 0x34, 0xd4, 0x1d, 0x47, 0x23, - 0x04, 0x2c, 0x0c, 0x77, 0x12, 0x9e, 0x63, 0x24, 0x3c, 0xd0, 0x0d, 0xd1, 0xb1, 0xc0, 0xd2, 0xa0, 0x26, 0xa8, 0x41, - 0xc5, 0xea, 0xeb, 0x21, 0x8e, 0x3a, 0xa5, 0xd1, 0x4e, 0xa0, 0xa8, 0x70, 0x91, 0x80, 0x09, 0x1f, 0xa2, 0x48, 0x0b, - 0x58, 0x85, 0x11, 0xc4, 0x90, 0x82, 0x6b, 0x0d, 0xd0, 0xb2, 0x80, 0xeb, 0x45, 0x63, 0x30, 0x31, 0xa1, 0xbb, 0xab, - 0xd0, 0xbb, 0x4f, 0x29, 0x8a, 0x6f, 0xcc, 0x9a, 0x86, 0x95, 0xb7, 0xdb, 0xea, 0x01, 0xc7, 0xdb, 0x88, 0x90, 0xd8, - 0xfb, 0xbd, 0xa2, 0x40, 0x63, 0x92, 0x74, 0x9b, 0x85, 0xf9, 0x77, 0xcd, 0x8e, 0x68, 0x06, 0x91, 0xcb, 0x20, 0x5d, - 0x4a, 0x4e, 0x7b, 0x83, 0x5b, 0xac, 0x39, 0xe9, 0xc1, 0x05, 0xda, 0xb3, 0x11, 0x01, 0x0a, 0x4f, 0xbb, 0x4a, 0x40, - 0x57, 0x0b, 0x5f, 0x8b, 0x61, 0x50, 0x5d, 0xe9, 0x59, 0x33, 0x11, 0xad, 0xcd, 0x01, 0xca, 0xce, 0x5c, 0xfc, 0xe8, - 0x33, 0xd8, 0xd1, 0x4a, 0xb9, 0x47, 0x20, 0x01, 0xd9, 0x6d, 0x6b, 0x71, 0x3d, 0x5b, 0xfb, 0x98, 0xdb, 0x5f, 0x91, - 0xaf, 0xdc, 0xe6, 0x89, 0xb1, 0x0f, 0xd9, 0xa6, 0x9c, 0x80, 0x21, 0x6a, 0xb5, 0xd0, 0x08, 0x92, 0x36, 0x74, 0xb9, - 0xaa, 0x75, 0x99, 0xac, 0xa1, 0x78, 0x55, 0x62, 0x82, 0x52, 0x22, 0x05, 0xc9, 0x97, 0x52, 0x82, 0x44, 0xf8, 0x4c, - 0x21, 0xfc, 0x37, 0x14, 0x91, 0x0a, 0xf8, 0x24, 0xbf, 0xbd, 0xc5, 0xef, 0x14, 0xde, 0xc7, 0xeb, 0xc1, 0x49, 0xf3, - 0xb5, 0xbe, 0xe7, 0x62, 0xe0, 0xae, 0xae, 0x22, 0x07, 0x69, 0x29, 0x43, 0x7b, 0x9c, 0xf8, 0xd0, 0xeb, 0xed, 0xb6, - 0x83, 0x97, 0xea, 0xbe, 0x32, 0xb9, 0x02, 0x19, 0x89, 0xde, 0xe8, 0xf5, 0x81, 0xb4, 0xfc, 0x4b, 0xac, 0x2e, 0x2a, - 0xb3, 0x76, 0x12, 0xca, 0xf5, 0x49, 0xec, 0xf2, 0xae, 0xc7, 0xc3, 0xda, 0xe4, 0x6e, 0x51, 0xe2, 0xbf, 0x6c, 0x44, - 0x31, 0x48, 0x7c, 0x23, 0x3f, 0x03, 0x9d, 0xc5, 0x50, 0xd4, 0xe2, 0x84, 0x0d, 0x52, 0xda, 0xe5, 0xca, 0xa8, 0x91, - 0x36, 0x81, 0x7c, 0x2f, 0xc3, 0x0b, 0x12, 0x27, 0x2a, 0x51, 0x4f, 0x36, 0x4d, 0x3c, 0x8e, 0xd7, 0x94, 0xb9, 0xee, - 0x06, 0x8e, 0xd1, 0xd6, 0x06, 0xa8, 0x08, 0x1f, 0x50, 0x9c, 0x49, 0x48, 0xb3, 0x94, 0xe0, 0x2b, 0x6b, 0xe0, 0x53, - 0x73, 0x4e, 0x14, 0xa5, 0xf4, 0x7a, 0x1f, 0xc4, 0x25, 0x73, 0xf8, 0x1c, 0x58, 0xea, 0x63, 0x2c, 0x6d, 0x24, 0x6b, - 0xa1, 0xd6, 0xa4, 0x1f, 0x2f, 0x5f, 0x8f, 0x30, 0x98, 0x89, 0xe8, 0x7d, 0x06, 0x59, 0xb3, 0xad, 0x8d, 0x66, 0xd6, - 0x98, 0xae, 0x4b, 0x73, 0x38, 0x35, 0x11, 0x82, 0xaa, 0xb6, 0x34, 0x60, 0x84, 0x2b, 0x95, 0x18, 0x7e, 0x8a, 0x29, - 0xfc, 0x03, 0x61, 0x5c, 0x3d, 0x52, 0xf8, 0xa7, 0x6d, 0xb1, 0x43, 0x36, 0xa3, 0xc3, 0xad, 0x05, 0xcd, 0xb3, 0x0d, - 0x3c, 0x78, 0x50, 0x49, 0x10, 0xa2, 0x32, 0x3c, 0xdf, 0x2d, 0x6b, 0xae, 0x6c, 0x57, 0x8e, 0x07, 0xc4, 0x5e, 0xe1, - 0xac, 0xec, 0x5a, 0x3d, 0xf4, 0x88, 0x39, 0x34, 0xb9, 0x41, 0x73, 0x65, 0x80, 0x0a, 0x52, 0x48, 0x97, 0xd0, 0x16, - 0xc8, 0xba, 0x4e, 0xe1, 0xac, 0x64, 0x08, 0x63, 0xe9, 0x65, 0x09, 0x4b, 0x05, 0x7b, 0x2d, 0xc2, 0xe8, 0xca, 0x85, - 0x21, 0x7d, 0x60, 0x68, 0x18, 0x11, 0x68, 0xe9, 0x71, 0x98, 0x75, 0xa3, 0xb3, 0x98, 0x02, 0x3d, 0xa6, 0x61, 0xd4, - 0xe0, 0x6c, 0x12, 0x56, 0xe8, 0xd9, 0x54, 0xa0, 0x07, 0xdf, 0xb2, 0x08, 0x84, 0xcf, 0x26, 0x77, 0x81, 0x38, 0xd1, - 0xd5, 0x7e, 0xa9, 0x11, 0x9e, 0x0b, 0x15, 0x1d, 0x21, 0x56, 0xf1, 0xe8, 0x9e, 0xbd, 0xbb, 0x78, 0xf9, 0xea, 0xed, - 0x9b, 0xdb, 0xdb, 0x36, 0x6f, 0xb6, 0x8f, 0xd8, 0x8f, 0x95, 0x8e, 0x07, 0xab, 0xa3, 0x00, 0x81, 0xfe, 0x9d, 0xd0, - 0x11, 0x9e, 0xaf, 0xc9, 0x0c, 0xe3, 0x06, 0x01, 0x2f, 0x4d, 0x0b, 0x1d, 0x13, 0xe4, 0xc6, 0xe9, 0x39, 0x0b, 0x07, - 0x8d, 0x50, 0x86, 0xfc, 0xfd, 0xba, 0x3e, 0xfa, 0x1d, 0x0c, 0x4c, 0x84, 0xdf, 0x63, 0x04, 0x10, 0x8c, 0x57, 0x0a, - 0x03, 0xe5, 0x2a, 0x01, 0xa3, 0x78, 0x8f, 0x50, 0x32, 0xa5, 0xa8, 0x55, 0xf0, 0x54, 0x20, 0x49, 0x14, 0xe1, 0x28, - 0xa3, 0x03, 0x0a, 0xe0, 0x8d, 0x41, 0x29, 0xc5, 0x53, 0x37, 0x95, 0xc7, 0xa5, 0x60, 0x55, 0xb7, 0x02, 0x80, 0x8b, - 0x7c, 0x9d, 0xe0, 0xeb, 0xa4, 0xab, 0xb8, 0x43, 0xb6, 0x9f, 0xb2, 0x39, 0xfc, 0x55, 0xd7, 0x22, 0x2e, 0x67, 0x05, - 0xff, 0x96, 0xe4, 0xf3, 0x32, 0x58, 0xde, 0x04, 0xb9, 0x7f, 0xd3, 0x1c, 0xee, 0x03, 0x69, 0xbd, 0x69, 0x96, 0xfe, - 0x8d, 0xc7, 0x60, 0x2e, 0xfc, 0x85, 0x48, 0x59, 0x40, 0xca, 0x02, 0x64, 0xdc, 0x0c, 0x99, 0xa2, 0x28, 0xda, 0x98, - 0xaf, 0x17, 0x15, 0x29, 0xb2, 0xa8, 0x1d, 0x4d, 0x71, 0xcb, 0xc2, 0xb7, 0xc3, 0x97, 0x30, 0xed, 0xd2, 0x14, 0xfe, - 0x88, 0xda, 0x4f, 0xcb, 0x38, 0xb8, 0x4f, 0xc2, 0x56, 0x77, 0x72, 0x96, 0x35, 0xdb, 0x30, 0xad, 0x13, 0x5c, 0xbb, - 0x31, 0x68, 0x6d, 0xb2, 0xd8, 0xa4, 0x41, 0xf1, 0x75, 0x76, 0xe3, 0xdb, 0xdb, 0xdd, 0xd4, 0xa3, 0x05, 0x37, 0x06, - 0x49, 0xe9, 0x72, 0xd2, 0x67, 0x2d, 0xf6, 0x11, 0x98, 0xfd, 0x92, 0xc3, 0x33, 0x2c, 0x38, 0x28, 0xd8, 0x17, 0x8e, - 0x76, 0xb4, 0x14, 0x57, 0x18, 0x42, 0x73, 0xd2, 0x3f, 0xa0, 0x92, 0xb9, 0xcc, 0x17, 0x6f, 0x91, 0x09, 0xe8, 0x57, - 0xd6, 0x82, 0x97, 0xe5, 0xf0, 0x06, 0x6d, 0x45, 0x67, 0xe2, 0xea, 0xd6, 0x22, 0x3c, 0x3c, 0x30, 0x47, 0xed, 0x81, - 0x68, 0x52, 0x4b, 0xe5, 0x7e, 0xb1, 0x4f, 0xd5, 0xc8, 0x26, 0x73, 0xf9, 0x6e, 0x5b, 0x46, 0xfe, 0x92, 0xb0, 0x40, - 0x04, 0x31, 0xf0, 0x48, 0x0b, 0x19, 0x4e, 0xc9, 0x86, 0x8b, 0x84, 0xca, 0x06, 0x4c, 0x52, 0x18, 0x4b, 0x4a, 0x9e, - 0xfe, 0xa9, 0x8c, 0x68, 0x1a, 0x41, 0xc7, 0x63, 0x55, 0x32, 0x25, 0xb0, 0x44, 0xeb, 0x94, 0x67, 0x82, 0x76, 0x25, - 0x50, 0xf9, 0x42, 0x8c, 0x87, 0xd4, 0x2d, 0xc8, 0xc1, 0xcb, 0x9d, 0x34, 0x0b, 0x48, 0xf4, 0x0e, 0x0e, 0x59, 0x74, - 0xf9, 0x39, 0x9e, 0xb5, 0xf1, 0xb2, 0xc0, 0xcf, 0xa0, 0x1d, 0x37, 0x73, 0x9d, 0x90, 0x61, 0xc2, 0xb0, 0x99, 0xef, - 0xe3, 0x5a, 0x02, 0x44, 0x14, 0x1f, 0xc6, 0xf0, 0x59, 0x73, 0xa2, 0x3f, 0xec, 0xa8, 0x0f, 0x1b, 0xb9, 0x4e, 0x10, - 0x1f, 0x36, 0xe4, 0x87, 0xf6, 0xed, 0x0c, 0x04, 0x02, 0x1b, 0x00, 0x1c, 0x01, 0x50, 0x79, 0x56, 0x34, 0x5f, 0x80, - 0x85, 0x5a, 0xec, 0x62, 0x1f, 0xbf, 0x85, 0x1e, 0x68, 0xb5, 0xf5, 0xbf, 0x0d, 0x65, 0xd0, 0x9f, 0xb2, 0xa0, 0x98, - 0xb9, 0x85, 0x30, 0xd1, 0x21, 0x54, 0x34, 0xc2, 0x14, 0x04, 0x99, 0xdd, 0x98, 0xa0, 0x66, 0x59, 0x0d, 0x52, 0x58, - 0xba, 0xcd, 0x18, 0x59, 0x0c, 0xde, 0x43, 0x13, 0x4e, 0xc8, 0x99, 0xd0, 0x4d, 0x71, 0x88, 0x31, 0x81, 0x67, 0x12, - 0xb4, 0x56, 0x39, 0xe9, 0x72, 0xbd, 0xb4, 0xf7, 0x57, 0xe5, 0x42, 0xb1, 0x66, 0xbb, 0xef, 0x41, 0x39, 0xf1, 0xd2, - 0xc7, 0x45, 0x26, 0x53, 0x1b, 0xf4, 0x7e, 0xd0, 0x09, 0xc4, 0x2b, 0xfe, 0xf4, 0x57, 0xb4, 0x02, 0xd0, 0x46, 0xc6, - 0x68, 0xfe, 0xf3, 0x9a, 0xc9, 0xeb, 0xf7, 0xad, 0x51, 0x2a, 0xb7, 0xdd, 0x3b, 0x6d, 0x99, 0x26, 0xec, 0xd3, 0x7a, - 0x4c, 0x5f, 0xd4, 0x13, 0xa2, 0x1b, 0x03, 0xed, 0x32, 0x7b, 0xdf, 0x0b, 0x91, 0x5c, 0x84, 0x39, 0x8a, 0x24, 0x50, - 0x9e, 0xe3, 0xda, 0x02, 0xd9, 0x08, 0x3f, 0xe3, 0x0d, 0xbc, 0x9e, 0xd4, 0x43, 0xc5, 0x40, 0x45, 0x50, 0x46, 0x34, - 0x29, 0x69, 0x37, 0x3c, 0x84, 0x5e, 0x8a, 0x27, 0xa6, 0x77, 0x1f, 0x0b, 0x69, 0x6d, 0xa5, 0xed, 0x71, 0x5d, 0x60, - 0xa1, 0xf7, 0x25, 0x85, 0x81, 0xdb, 0x13, 0x3b, 0x79, 0x25, 0xed, 0xad, 0xab, 0x52, 0x9d, 0xed, 0xd5, 0x74, 0x74, - 0x35, 0x9d, 0xcd, 0x6a, 0xec, 0xb8, 0x92, 0x77, 0x79, 0x45, 0x12, 0x67, 0xf5, 0xcb, 0x59, 0x94, 0xfd, 0x18, 0xcd, - 0xd0, 0x3a, 0x9a, 0x88, 0x7d, 0x55, 0xe4, 0x5c, 0x29, 0x70, 0xae, 0x94, 0x88, 0xab, 0x47, 0x1b, 0xea, 0x18, 0xe0, - 0xe5, 0xa5, 0xbe, 0x7c, 0x00, 0xaa, 0x7d, 0x9d, 0x0f, 0x65, 0x94, 0xd3, 0x0c, 0x74, 0xc5, 0x8c, 0x3b, 0x1e, 0xa1, - 0xaa, 0x8c, 0x81, 0xbd, 0x14, 0x6b, 0x2f, 0xeb, 0x25, 0x97, 0x26, 0x62, 0x5e, 0x9f, 0xae, 0xfb, 0xf8, 0x9e, 0xa5, - 0x58, 0x9a, 0x89, 0xe3, 0x10, 0x88, 0x7f, 0x8a, 0xba, 0xd9, 0xa5, 0xb9, 0xed, 0xb7, 0xd1, 0x66, 0x45, 0xd3, 0xcd, - 0x7a, 0x74, 0xc5, 0xc9, 0xfd, 0x82, 0x9c, 0x03, 0xc4, 0x41, 0x7f, 0x80, 0x99, 0x00, 0x7b, 0xec, 0x2b, 0x0a, 0xed, - 0xdf, 0x88, 0xb4, 0x85, 0x9d, 0xb6, 0xa0, 0xb4, 0x0e, 0x96, 0x43, 0xd2, 0x2c, 0xcb, 0x74, 0x16, 0xea, 0x7d, 0x81, - 0x37, 0xdd, 0xae, 0x30, 0x12, 0xf7, 0xec, 0x31, 0x39, 0x43, 0xbc, 0x43, 0x1f, 0x51, 0x00, 0xcc, 0xcf, 0xf2, 0xf4, - 0xad, 0xd1, 0x65, 0xef, 0x0a, 0x07, 0xb6, 0x26, 0x54, 0xca, 0xbc, 0x61, 0x1e, 0xcf, 0xd1, 0xaf, 0x73, 0xf7, 0x8e, - 0x78, 0xf8, 0x99, 0x2d, 0xb4, 0x88, 0xa3, 0xe2, 0x6f, 0x00, 0xbc, 0xd6, 0x55, 0x1d, 0x95, 0xe5, 0x5d, 0x6a, 0xbb, - 0x8e, 0x5e, 0x4c, 0x22, 0x68, 0xf5, 0x3d, 0x08, 0xcf, 0x7d, 0x71, 0x23, 0x77, 0xe5, 0xe3, 0xa5, 0x85, 0x35, 0x81, - 0x66, 0xa1, 0x4f, 0x27, 0x89, 0x80, 0xa8, 0xf5, 0x7e, 0xdb, 0x9a, 0x88, 0x9b, 0x99, 0xbd, 0x90, 0x04, 0xf7, 0x42, - 0x58, 0xa2, 0x83, 0xb6, 0x61, 0xec, 0x76, 0x19, 0xb4, 0x0d, 0x0f, 0x75, 0x8b, 0xc0, 0xed, 0x56, 0x67, 0x71, 0xed, - 0xe3, 0xcd, 0xb1, 0x09, 0xe8, 0xfc, 0x82, 0x56, 0xdc, 0x13, 0x17, 0x00, 0xa1, 0xd9, 0x87, 0x17, 0x4f, 0x25, 0x08, - 0x7c, 0xe9, 0x38, 0xfa, 0x29, 0xe1, 0xd7, 0xc2, 0x73, 0x78, 0x3a, 0x9b, 0x83, 0x72, 0x4b, 0x7b, 0xd4, 0x68, 0xe2, - 0xab, 0x9f, 0xf3, 0xfa, 0x25, 0xae, 0xd9, 0xc6, 0xef, 0x61, 0x18, 0x09, 0x69, 0xec, 0x20, 0x83, 0x84, 0x08, 0x66, - 0xa5, 0xe3, 0xb5, 0xfd, 0x81, 0xf1, 0x1e, 0x2a, 0x0a, 0x27, 0x58, 0xd4, 0x36, 0xa8, 0xe0, 0x81, 0xe2, 0x8d, 0x59, - 0x51, 0x1e, 0xde, 0x6d, 0x38, 0x4d, 0x2f, 0x57, 0x18, 0xe8, 0xb8, 0xe7, 0x34, 0x9d, 0x06, 0x0f, 0x64, 0x50, 0x66, - 0x15, 0x61, 0xbc, 0x3c, 0x3b, 0xa2, 0x38, 0xed, 0xda, 0xae, 0xfe, 0x47, 0x8c, 0x0e, 0xf8, 0x19, 0x9e, 0x12, 0xb3, - 0xa3, 0xbb, 0x5e, 0x56, 0x0d, 0xfc, 0x3e, 0x6f, 0x00, 0x38, 0x6e, 0x6f, 0x5b, 0xfa, 0x1a, 0x28, 0xb9, 0xcd, 0x95, - 0x89, 0x6d, 0xae, 0x4c, 0x6e, 0x73, 0x65, 0x6a, 0x9b, 0x2b, 0xa3, 0x6d, 0xae, 0x4c, 0x6d, 0x73, 0x29, 0x10, 0xfe, - 0x64, 0xc5, 0x71, 0x74, 0x13, 0x8c, 0xab, 0x58, 0x89, 0xc8, 0x78, 0xb8, 0xe1, 0xb9, 0x0b, 0xc2, 0x8f, 0x9e, 0x7e, - 0x3b, 0x86, 0x5c, 0xba, 0xee, 0x2b, 0x41, 0xc7, 0xa6, 0x40, 0xb3, 0xca, 0x28, 0x8c, 0xb3, 0x3e, 0xee, 0x0c, 0x8b, - 0x11, 0x04, 0xa9, 0xa5, 0x38, 0x44, 0xfb, 0x1b, 0xda, 0xe4, 0xe9, 0xe9, 0xf7, 0x20, 0x5f, 0x85, 0x99, 0x74, 0xb9, - 0xdf, 0x6d, 0x2b, 0x4a, 0xf1, 0x53, 0x4c, 0xe1, 0xc9, 0xa1, 0x36, 0x52, 0x41, 0x3c, 0x58, 0xac, 0x25, 0xac, 0xd4, - 0x5c, 0xac, 0x77, 0x75, 0x14, 0x9e, 0x4c, 0x51, 0xca, 0xad, 0xe4, 0x49, 0x8a, 0x87, 0xd8, 0xc9, 0x0b, 0xc3, 0xeb, - 0xe2, 0x11, 0x82, 0x98, 0x12, 0x7e, 0x6b, 0xa6, 0x82, 0x9c, 0xc5, 0x3a, 0xe9, 0xf7, 0x66, 0x4a, 0x04, 0x0c, 0x1a, - 0x54, 0x30, 0x03, 0xc1, 0x29, 0x02, 0x51, 0x29, 0x66, 0x83, 0xfc, 0x26, 0x28, 0x2c, 0x96, 0x78, 0xa1, 0x36, 0xfe, - 0x00, 0x29, 0xb3, 0x08, 0xcf, 0xfb, 0x38, 0xa0, 0x0a, 0x25, 0x6b, 0xa7, 0x00, 0x97, 0x31, 0x79, 0x54, 0x83, 0x60, - 0x78, 0x87, 0x27, 0x3c, 0x06, 0x27, 0xab, 0x80, 0x75, 0x02, 0x4e, 0x71, 0xe4, 0x97, 0x78, 0xe0, 0xea, 0xe6, 0x22, - 0xf9, 0x1b, 0x37, 0xbe, 0xf4, 0x61, 0xcb, 0x26, 0xa4, 0x39, 0xd0, 0xab, 0x77, 0x78, 0xfb, 0x96, 0x23, 0xcf, 0xea, - 0x3a, 0xe8, 0xac, 0x2b, 0x52, 0xf4, 0x79, 0x53, 0x9a, 0x5e, 0xc8, 0x80, 0x5e, 0xc7, 0xd0, 0xeb, 0x94, 0x7a, 0x3d, - 0x81, 0x16, 0x52, 0xc1, 0x8f, 0x86, 0x14, 0xf6, 0x1f, 0xa6, 0xde, 0x9d, 0x08, 0x33, 0x14, 0xba, 0x18, 0xcc, 0x43, - 0xda, 0x6d, 0x97, 0x69, 0xe8, 0xa6, 0x86, 0x50, 0x5f, 0x8a, 0x23, 0xca, 0x23, 0x26, 0x70, 0x23, 0x98, 0xad, 0xcc, - 0xe5, 0xe2, 0xc8, 0x6e, 0x46, 0x4d, 0xf8, 0x8c, 0xca, 0x34, 0x22, 0xe9, 0xce, 0x32, 0xc3, 0x24, 0x51, 0x1c, 0xd2, - 0x94, 0x6b, 0x0b, 0xf4, 0xc5, 0xf6, 0xe5, 0x8f, 0x9b, 0x43, 0xef, 0x60, 0xb4, 0xcf, 0xa5, 0x8b, 0x78, 0x86, 0x82, - 0xa8, 0x9d, 0x9f, 0x36, 0xe7, 0xde, 0xc1, 0x0c, 0xf2, 0xa5, 0xdf, 0x78, 0x66, 0xcb, 0x21, 0x3c, 0x5d, 0x8b, 0x2f, - 0x4c, 0xcc, 0x23, 0x54, 0x1b, 0x6d, 0xa0, 0x6c, 0xeb, 0x67, 0xb3, 0x46, 0x88, 0xb0, 0xd1, 0xfe, 0x7c, 0xee, 0x21, - 0x69, 0x13, 0x73, 0x2d, 0xce, 0x74, 0x73, 0xfd, 0x2e, 0xb6, 0x2d, 0x6d, 0x34, 0x02, 0x96, 0x7b, 0x17, 0x1a, 0x01, - 0xe4, 0xef, 0x61, 0x60, 0x7c, 0xc0, 0x9d, 0x77, 0x68, 0x9a, 0xdb, 0x9c, 0x81, 0x54, 0x66, 0xe8, 0xc9, 0xea, 0x56, - 0x0a, 0x5e, 0x80, 0x64, 0xe2, 0x37, 0x56, 0xc7, 0x62, 0x34, 0xd8, 0x20, 0x4b, 0x3e, 0xc4, 0xf2, 0x01, 0x56, 0x0b, - 0x50, 0xce, 0x48, 0xfb, 0xb1, 0x00, 0xee, 0x3b, 0xd6, 0x00, 0x1c, 0x14, 0x41, 0x55, 0x01, 0xb9, 0x0d, 0xab, 0x4b, - 0x88, 0x77, 0x47, 0x9b, 0x8e, 0xe4, 0x94, 0x56, 0x6a, 0x4a, 0x39, 0x53, 0xb5, 0x06, 0xa0, 0xc2, 0x8f, 0x13, 0xa6, - 0xeb, 0x40, 0x25, 0x7d, 0x9c, 0x28, 0xa3, 0xf0, 0x5f, 0x14, 0x80, 0xae, 0x16, 0xf7, 0x18, 0xa8, 0x32, 0xd0, 0x5e, - 0x2b, 0x7e, 0x6b, 0xba, 0xa9, 0x26, 0x11, 0x99, 0x44, 0x17, 0x03, 0xc2, 0xd1, 0x29, 0xac, 0xd7, 0x04, 0x4f, 0x50, - 0x15, 0xd8, 0xdf, 0xd2, 0x0c, 0x28, 0x59, 0x1b, 0x10, 0xf5, 0x24, 0xd2, 0x85, 0xe4, 0xa0, 0x92, 0xf5, 0x41, 0x51, - 0xb1, 0x38, 0xd4, 0x18, 0x61, 0xe1, 0x6c, 0xaa, 0x06, 0x08, 0x98, 0x4f, 0x44, 0x63, 0x6d, 0x51, 0x91, 0xa5, 0x30, - 0xab, 0x68, 0x55, 0xa9, 0xee, 0xce, 0xef, 0x5a, 0x4a, 0xa3, 0xf5, 0x55, 0xd7, 0x4d, 0x9b, 0xa1, 0x3c, 0xca, 0xd0, - 0x98, 0xcb, 0x19, 0x9c, 0x60, 0x92, 0xc4, 0xfc, 0xb9, 0x7c, 0x50, 0x44, 0xd7, 0x0a, 0xcc, 0xd1, 0x62, 0x69, 0x33, - 0x17, 0x9f, 0xa0, 0x1e, 0x68, 0xa5, 0x67, 0xbd, 0xf4, 0x20, 0x0b, 0x40, 0x88, 0xd7, 0xcb, 0x26, 0x0d, 0xff, 0xe2, - 0x46, 0x9a, 0x4c, 0x41, 0x56, 0x8a, 0x6d, 0x57, 0xa7, 0x49, 0x2d, 0x7b, 0x82, 0xe4, 0xd1, 0x40, 0x0b, 0xf2, 0xf1, - 0x54, 0x10, 0x1a, 0x98, 0xa9, 0x5c, 0x7a, 0xd0, 0x81, 0x24, 0x6b, 0xab, 0x1b, 0x16, 0x8a, 0xd9, 0x9d, 0xde, 0xdb, - 0xcb, 0xf6, 0xf6, 0x14, 0xbe, 0xed, 0xed, 0x4d, 0xce, 0xcd, 0xb3, 0x8b, 0x37, 0x28, 0x48, 0x44, 0x34, 0x1d, 0x12, - 0xe1, 0x1f, 0x26, 0xfb, 0x74, 0x19, 0xdd, 0x26, 0xcc, 0x2d, 0x67, 0xcb, 0x72, 0x23, 0x08, 0x26, 0x68, 0xe7, 0x2a, - 0xd8, 0xb5, 0x8c, 0x22, 0x21, 0xeb, 0xdf, 0xc7, 0xcd, 0xb3, 0x7a, 0x06, 0xd5, 0x8c, 0x81, 0xb0, 0x55, 0x99, 0x6d, - 0xdf, 0x79, 0xea, 0xf0, 0xce, 0x96, 0x6f, 0xcd, 0x2e, 0x32, 0x5e, 0xdc, 0x82, 0x84, 0x58, 0x5b, 0x0f, 0x84, 0x33, - 0x05, 0x3a, 0x5e, 0x00, 0x0b, 0x93, 0x6f, 0x7a, 0xd8, 0x3a, 0x41, 0xd4, 0x82, 0xda, 0x63, 0xad, 0x44, 0xf8, 0x19, - 0xaf, 0x19, 0x94, 0xd3, 0x3c, 0xbb, 0xf9, 0xcc, 0x6a, 0xe5, 0x45, 0x2e, 0x3d, 0x62, 0x26, 0x39, 0xfd, 0x6e, 0x27, - 0xfe, 0x68, 0xa8, 0xbc, 0xbd, 0x55, 0x8b, 0x1f, 0xde, 0x4a, 0x7c, 0xa3, 0x2f, 0xf1, 0x66, 0x93, 0x9e, 0x7b, 0xe7, - 0x97, 0x61, 0xc6, 0xd4, 0x67, 0xc0, 0xff, 0xe4, 0x37, 0x21, 0xf2, 0xc5, 0xb8, 0xba, 0xf1, 0x6b, 0xa7, 0x9d, 0x32, - 0x3a, 0x07, 0x43, 0x7f, 0x29, 0xda, 0x26, 0x1e, 0x30, 0x94, 0xd3, 0x91, 0xda, 0x71, 0x65, 0xc5, 0x3d, 0x4b, 0xbb, - 0xed, 0x6e, 0x55, 0x2c, 0xb4, 0xe1, 0x69, 0x89, 0xb7, 0xb8, 0xcd, 0xd0, 0x0b, 0xe0, 0x9b, 0x75, 0x5b, 0x57, 0x82, - 0x0e, 0x17, 0x78, 0x4e, 0xb1, 0x8b, 0x22, 0x28, 0x80, 0x47, 0x46, 0x96, 0x85, 0x25, 0xf2, 0x0c, 0x0f, 0x43, 0xbe, - 0x92, 0x01, 0x77, 0x5d, 0xa7, 0xa2, 0xf3, 0xbd, 0xe2, 0x08, 0xae, 0xc7, 0x74, 0x00, 0x5a, 0xf4, 0xbb, 0xfc, 0x5e, - 0x49, 0x90, 0xa4, 0xd0, 0xb3, 0x65, 0x69, 0x4e, 0xb9, 0xdb, 0xe1, 0x69, 0x2f, 0xd6, 0x22, 0x00, 0x4b, 0xf1, 0x4c, - 0x09, 0x16, 0xc2, 0x29, 0xe6, 0xe0, 0x5f, 0xe8, 0x23, 0xe6, 0xb9, 0xd2, 0x45, 0x6c, 0x76, 0x73, 0xef, 0xc0, 0x84, - 0x04, 0xea, 0x35, 0xd0, 0x8f, 0x57, 0x05, 0xba, 0x32, 0xfe, 0x9d, 0xd6, 0xee, 0xb1, 0x66, 0xff, 0x09, 0xba, 0x4f, - 0xef, 0xab, 0xf8, 0xe8, 0xc8, 0xae, 0x12, 0x7f, 0x21, 0x52, 0x28, 0x3a, 0xba, 0xcd, 0x9f, 0xca, 0xf4, 0x1f, 0x55, - 0x90, 0x59, 0x8e, 0xda, 0x3d, 0x8e, 0xb1, 0xd8, 0xa0, 0x9e, 0x00, 0xea, 0x13, 0x39, 0xc2, 0xf7, 0x1a, 0x32, 0xda, - 0x3a, 0x9d, 0x9f, 0xb7, 0x7a, 0xf8, 0x8b, 0x17, 0x7b, 0x58, 0x5b, 0x91, 0x5b, 0xa8, 0x2e, 0x35, 0x48, 0xda, 0xda, - 0x42, 0x3c, 0x2c, 0xf0, 0xa4, 0xe3, 0x52, 0xb8, 0x50, 0xb7, 0x31, 0x55, 0xb8, 0x50, 0xaf, 0xf0, 0xec, 0x42, 0x45, - 0x3a, 0x2e, 0xc5, 0x5a, 0x7f, 0x5d, 0x91, 0x60, 0xc5, 0x91, 0xa7, 0xbd, 0xc6, 0x0d, 0x1b, 0x5c, 0xb7, 0xb0, 0xe8, - 0xe1, 0x19, 0xd5, 0x34, 0x4e, 0x04, 0x4b, 0xec, 0xde, 0x9b, 0xd8, 0x4a, 0xaf, 0xd1, 0xd1, 0x72, 0x52, 0x53, 0x4a, - 0x26, 0xc5, 0xda, 0x65, 0x5c, 0x8e, 0x38, 0x52, 0xd5, 0x5b, 0x0e, 0x78, 0x75, 0xcd, 0x79, 0x16, 0x4c, 0x81, 0x6e, - 0x83, 0xbc, 0x0d, 0x32, 0x7b, 0xf0, 0x47, 0xc4, 0x84, 0xa3, 0x1c, 0x3a, 0x0a, 0xfd, 0xb2, 0x0a, 0x74, 0x99, 0x2a, - 0xd6, 0x65, 0x64, 0xb0, 0x95, 0xaa, 0xc9, 0xad, 0xb2, 0x18, 0xd1, 0xc1, 0x76, 0xcc, 0x2d, 0x5d, 0x19, 0x2a, 0x16, - 0xc4, 0x9c, 0x6c, 0x08, 0x2c, 0x4e, 0x04, 0x8c, 0xe5, 0x22, 0xcc, 0x59, 0x26, 0x5d, 0x90, 0xca, 0x95, 0x9e, 0x16, - 0x59, 0xfa, 0x3e, 0x17, 0xe5, 0xef, 0xab, 0x92, 0xa8, 0xbe, 0x34, 0x31, 0x1c, 0xed, 0x7d, 0x14, 0x25, 0x5a, 0xfa, - 0x43, 0xeb, 0xde, 0xc9, 0xb4, 0x46, 0xd4, 0x96, 0x32, 0xc8, 0xd8, 0x82, 0x5a, 0x11, 0xd1, 0x6a, 0xb1, 0x4a, 0x90, - 0x5e, 0x39, 0xd3, 0xe3, 0x29, 0xac, 0xbe, 0x47, 0xab, 0x10, 0x80, 0x44, 0x46, 0x7d, 0x3b, 0x26, 0xb0, 0xec, 0x52, - 0x4a, 0x5f, 0x4f, 0x44, 0x77, 0x86, 0x68, 0x62, 0x9d, 0xb3, 0x11, 0x32, 0xb1, 0xa1, 0xb0, 0x58, 0xa7, 0x8d, 0x30, - 0x66, 0x13, 0xfc, 0x33, 0x87, 0xee, 0x8d, 0x80, 0xc1, 0xcd, 0xcf, 0x46, 0x7b, 0x7b, 0x85, 0x1b, 0xb9, 0xd5, 0x65, - 0x7a, 0x3f, 0xee, 0x5f, 0x66, 0x7d, 0x8f, 0x0c, 0x17, 0xa0, 0xcb, 0xce, 0xbd, 0xb4, 0xd9, 0x04, 0xee, 0xd4, 0xec, - 0xa6, 0xf7, 0xf1, 0x33, 0xf8, 0xa3, 0x96, 0xd4, 0xe4, 0x2c, 0x45, 0xfa, 0x0e, 0x15, 0x01, 0x0d, 0xdf, 0xd6, 0xb4, - 0x1c, 0xba, 0x74, 0x3f, 0xb3, 0xcf, 0x5d, 0x68, 0x00, 0xd8, 0xf1, 0xb6, 0xd1, 0x46, 0xfe, 0xef, 0x01, 0x52, 0xe8, - 0x21, 0x63, 0x60, 0x37, 0x31, 0xc1, 0x11, 0x53, 0x50, 0x8a, 0x2d, 0x28, 0xa5, 0x0a, 0x4a, 0xb2, 0x73, 0x13, 0xaa, - 0x64, 0x28, 0x3a, 0x37, 0x97, 0x9d, 0x1b, 0xad, 0x42, 0x3d, 0x1d, 0x6c, 0xa6, 0xee, 0xb2, 0x19, 0xa3, 0xbe, 0x30, - 0x15, 0x07, 0xff, 0x07, 0xec, 0x8a, 0x7d, 0x93, 0x6c, 0xe0, 0x35, 0x39, 0x26, 0xa1, 0x02, 0xf1, 0x8d, 0x0d, 0x70, - 0x1f, 0x16, 0x9f, 0x50, 0x9d, 0x6c, 0xb1, 0x05, 0x65, 0x45, 0x80, 0xf6, 0x03, 0x4f, 0x04, 0xda, 0xc5, 0xbd, 0x06, - 0x2c, 0xc6, 0x6e, 0x28, 0x6b, 0x7c, 0x7b, 0xfb, 0x1a, 0xe4, 0xbe, 0x6b, 0x7a, 0xd9, 0x85, 0xb7, 0x85, 0x6b, 0xcc, - 0x7b, 0x17, 0xe1, 0x84, 0xbd, 0x0d, 0x27, 0xdd, 0x8b, 0xb3, 0x70, 0x08, 0x50, 0xbf, 0xf0, 0xae, 0xc2, 0xea, 0xf2, - 0x02, 0xad, 0x03, 0xbb, 0x57, 0xd2, 0xd6, 0xec, 0x0e, 0xc2, 0xd4, 0xbd, 0xa2, 0xb9, 0x19, 0x20, 0xeb, 0x85, 0x94, - 0x71, 0x18, 0xbb, 0x03, 0x61, 0x62, 0x9a, 0x86, 0xea, 0x8e, 0xb7, 0x1b, 0xa2, 0xa7, 0xd3, 0x30, 0xc2, 0x2c, 0xea, - 0x4a, 0xef, 0x22, 0x78, 0x0b, 0x25, 0xf4, 0x2d, 0x70, 0xd7, 0x54, 0x62, 0x26, 0xf6, 0x09, 0x0d, 0xe2, 0x4f, 0x09, - 0x3e, 0x17, 0x0a, 0x3e, 0x02, 0xff, 0x0b, 0x0d, 0x27, 0x74, 0xfb, 0x12, 0x3b, 0x48, 0xd0, 0xd3, 0x0b, 0xf6, 0x2d, - 0x34, 0xb7, 0xcd, 0xee, 0x98, 0xba, 0xef, 0xa8, 0x75, 0xf8, 0x9d, 0x5a, 0x67, 0xd6, 0xc6, 0xca, 0x9a, 0xca, 0x47, - 0x81, 0xc3, 0x31, 0xf2, 0xd3, 0x98, 0xe2, 0x20, 0xac, 0x69, 0xb2, 0xfa, 0xae, 0xa8, 0x9a, 0x42, 0x0b, 0xc8, 0x95, - 0xe1, 0x2d, 0x66, 0x89, 0x38, 0x1a, 0x8b, 0x01, 0x08, 0xba, 0xb9, 0xb6, 0xde, 0xcb, 0x03, 0xe4, 0x22, 0x34, 0xfc, - 0xe6, 0x76, 0x55, 0x6a, 0xd1, 0x43, 0x13, 0x65, 0xbb, 0x6a, 0xb6, 0x29, 0x64, 0x1a, 0xf0, 0x75, 0x71, 0xc9, 0x1a, - 0x34, 0x5e, 0xd1, 0x4e, 0x40, 0x29, 0x76, 0x02, 0xba, 0x5e, 0xa9, 0xef, 0x13, 0xc0, 0x9c, 0x2d, 0x19, 0xe5, 0x7d, - 0xd0, 0xd2, 0xb8, 0xb8, 0x6c, 0xa3, 0x84, 0x1e, 0x9d, 0xd3, 0x65, 0x04, 0xf9, 0xfd, 0x4a, 0x15, 0xcc, 0xcd, 0xcd, - 0x03, 0x39, 0x96, 0x5d, 0xd6, 0x51, 0xdf, 0xa2, 0x8f, 0x5b, 0x68, 0xb6, 0x36, 0xa1, 0xe6, 0x0a, 0x85, 0x61, 0x9d, - 0x60, 0x34, 0x35, 0xdc, 0xa0, 0x88, 0xe5, 0x79, 0xf2, 0xaa, 0xd1, 0xee, 0xc6, 0x67, 0x21, 0x27, 0x67, 0x7c, 0xad, - 0xe9, 0x26, 0x97, 0xf1, 0xfd, 0x12, 0xbe, 0xa1, 0x6e, 0xdc, 0xde, 0xc2, 0x2f, 0x28, 0x70, 0xbd, 0x48, 0xbe, 0xba, - 0x14, 0x7c, 0x3d, 0x17, 0x50, 0x93, 0x5d, 0xaa, 0xee, 0x8b, 0x4e, 0x81, 0x26, 0x06, 0x54, 0xae, 0x94, 0x74, 0x0f, - 0x2f, 0xad, 0x0d, 0x8b, 0x50, 0x7e, 0x1f, 0x53, 0x8c, 0x11, 0x2f, 0x70, 0x0b, 0xa0, 0x1a, 0x91, 0x42, 0xe1, 0x2a, - 0x8c, 0x29, 0xc8, 0x5b, 0xaa, 0x0f, 0x7f, 0x6b, 0xc4, 0xd9, 0xde, 0x44, 0x61, 0x57, 0x9f, 0x5b, 0x57, 0xf7, 0x6c, - 0xd8, 0x06, 0xe4, 0x64, 0x23, 0xba, 0xa8, 0x90, 0x6d, 0xca, 0x22, 0x68, 0x47, 0xcb, 0x41, 0x82, 0x53, 0x2a, 0x82, - 0xa3, 0x3c, 0x3e, 0xf2, 0x70, 0x77, 0x37, 0xf1, 0xaf, 0xb0, 0x21, 0x05, 0xf6, 0x82, 0x9a, 0x07, 0x42, 0x4b, 0x97, - 0xd9, 0x89, 0xfb, 0xcc, 0xba, 0xf2, 0x3a, 0xa9, 0x5d, 0x15, 0xd8, 0x6d, 0xe7, 0x09, 0xca, 0x11, 0x97, 0xf5, 0x4f, - 0x44, 0x7f, 0xf3, 0x15, 0xba, 0x32, 0x56, 0x4a, 0x7e, 0x8c, 0xc3, 0xe8, 0xac, 0xe8, 0x45, 0x0d, 0x0c, 0x43, 0x97, - 0x8a, 0xd6, 0x46, 0x30, 0xec, 0x57, 0x39, 0x1e, 0x82, 0x28, 0xc4, 0x3d, 0x3e, 0xe8, 0x7d, 0x59, 0x36, 0x75, 0x94, - 0x7c, 0xaa, 0x7b, 0x82, 0xad, 0x17, 0xe4, 0xef, 0xc6, 0xea, 0x17, 0x03, 0x3e, 0x29, 0xd7, 0x05, 0x85, 0x5d, 0x90, - 0x04, 0x77, 0x33, 0xdf, 0x78, 0x96, 0xa1, 0x69, 0xa5, 0x57, 0x05, 0x73, 0x83, 0x2f, 0x56, 0xfc, 0xc5, 0xad, 0x48, - 0x24, 0xae, 0x20, 0xb0, 0x4f, 0xc2, 0xa3, 0x48, 0xfd, 0xb6, 0x74, 0x35, 0x50, 0x81, 0x9a, 0x5e, 0xd9, 0x17, 0xe9, - 0xc1, 0xa8, 0x65, 0x4e, 0xb0, 0x54, 0xf0, 0x06, 0xb0, 0x89, 0x78, 0xf3, 0x0a, 0xea, 0x30, 0x64, 0x89, 0x95, 0x28, - 0x61, 0x0e, 0x43, 0x0a, 0x1e, 0x47, 0x40, 0x03, 0x16, 0x34, 0xb4, 0x62, 0x35, 0xba, 0x33, 0x36, 0x66, 0x53, 0xa0, - 0x99, 0xb2, 0x4f, 0x57, 0x61, 0xd4, 0x6b, 0xb6, 0x03, 0x5a, 0x7d, 0x33, 0x40, 0x95, 0xb1, 0xe0, 0x60, 0x33, 0xe0, - 0x39, 0x5d, 0x7e, 0x39, 0x03, 0x5e, 0x25, 0x17, 0xcf, 0xac, 0x19, 0x5e, 0x89, 0xf5, 0xc7, 0x2f, 0xc7, 0x26, 0x79, - 0xdc, 0x80, 0x64, 0x28, 0x86, 0x9f, 0xde, 0xc7, 0x5d, 0x8c, 0xb4, 0x86, 0x65, 0x90, 0x43, 0x73, 0x06, 0x79, 0x62, - 0xd6, 0xa6, 0x92, 0x2e, 0x0d, 0x56, 0x28, 0xac, 0x0c, 0xa0, 0xab, 0x90, 0x85, 0xe2, 0x99, 0xde, 0x24, 0x9d, 0xc9, - 0x8d, 0xde, 0x21, 0xf4, 0x6c, 0x18, 0xcc, 0xc4, 0x28, 0x24, 0xcf, 0xe0, 0x97, 0x43, 0x68, 0x9a, 0x4d, 0xa9, 0x23, - 0x30, 0x30, 0x58, 0x6e, 0xf3, 0xb3, 0x70, 0x86, 0x97, 0x9f, 0x75, 0xe7, 0x86, 0x44, 0x0d, 0xa0, 0xe0, 0x1c, 0x0a, - 0x76, 0xa7, 0x08, 0x59, 0x7b, 0xc2, 0xdc, 0xe7, 0x28, 0x42, 0xc9, 0x90, 0x9a, 0x92, 0xe8, 0x39, 0x6c, 0xd6, 0x0a, - 0xc6, 0x6c, 0xd6, 0x0e, 0x06, 0xf0, 0x84, 0x17, 0x71, 0x08, 0xb8, 0xbb, 0x73, 0x5c, 0x7c, 0x31, 0x64, 0x98, 0x34, - 0xa8, 0x95, 0xd5, 0x27, 0x67, 0x85, 0x0a, 0xd6, 0x28, 0x75, 0xa7, 0x0c, 0x95, 0x10, 0x10, 0x01, 0x18, 0x7c, 0xc6, - 0x66, 0x3e, 0xa1, 0x3a, 0xa8, 0x90, 0x63, 0x18, 0xe4, 0x24, 0x9c, 0xae, 0x86, 0x67, 0x73, 0xb4, 0x88, 0x6e, 0x14, - 0xd0, 0x2a, 0xa8, 0xc1, 0x9c, 0xb7, 0x56, 0x8c, 0xca, 0xe5, 0x5a, 0x38, 0x20, 0xe0, 0xf5, 0x6b, 0x29, 0x32, 0x9e, - 0xdd, 0x93, 0x68, 0x76, 0x21, 0x85, 0x81, 0x7a, 0x02, 0x33, 0xc1, 0xc0, 0x74, 0x1e, 0xbe, 0x58, 0xe9, 0x32, 0x42, - 0x9c, 0x9d, 0x2b, 0x92, 0x64, 0x99, 0x9f, 0x60, 0xe5, 0xd7, 0x2b, 0xd7, 0x29, 0xcc, 0x3a, 0x05, 0xaa, 0x73, 0x85, - 0xd1, 0xc0, 0x8a, 0x4a, 0x64, 0x3a, 0x85, 0x6f, 0xf6, 0x9d, 0x47, 0xe9, 0x66, 0x74, 0x2e, 0x50, 0x6f, 0x6a, 0xdc, - 0x49, 0xeb, 0x3f, 0xc8, 0x86, 0xad, 0xc8, 0xc0, 0xb9, 0xd7, 0x73, 0xb9, 0x71, 0x6a, 0xc5, 0x8b, 0xa9, 0x24, 0xef, - 0x01, 0x6e, 0xcd, 0xb5, 0x39, 0x3a, 0xf7, 0x3c, 0xa0, 0x15, 0x6a, 0xcd, 0xaf, 0x85, 0x24, 0x45, 0x4f, 0x51, 0x40, - 0xdd, 0xf5, 0x40, 0xa5, 0x74, 0xa2, 0x85, 0x22, 0x6d, 0xcd, 0xd2, 0x5a, 0xa4, 0x2d, 0x7d, 0xdf, 0xb5, 0xb8, 0x9f, - 0xc3, 0x0a, 0x5c, 0x24, 0x16, 0xb6, 0x0e, 0x8f, 0xaa, 0x6e, 0xe5, 0x9e, 0x67, 0x19, 0x85, 0x33, 0x6a, 0xcb, 0x04, - 0x8c, 0xeb, 0x0d, 0xe8, 0xa4, 0xe2, 0x15, 0xad, 0xae, 0xb2, 0xbc, 0x12, 0x4d, 0xae, 0x05, 0xf7, 0xb1, 0xae, 0x44, - 0x41, 0x5e, 0x8b, 0x1b, 0xd8, 0x2a, 0x96, 0x6c, 0x37, 0xb7, 0xaf, 0x68, 0x89, 0xdc, 0x25, 0x35, 0x0d, 0x02, 0xb5, - 0x3c, 0x40, 0x13, 0xe0, 0xe0, 0xe9, 0x09, 0x83, 0x9a, 0x5e, 0x54, 0x1c, 0x08, 0x46, 0xa1, 0x8c, 0x9b, 0xf8, 0x1a, - 0x98, 0x9b, 0xe1, 0x9b, 0x5c, 0x92, 0x89, 0x82, 0xee, 0xfc, 0x80, 0x81, 0x8d, 0x0a, 0x0e, 0x20, 0x5c, 0x1b, 0x28, - 0x7a, 0x44, 0xd4, 0x07, 0xd4, 0x62, 0x75, 0x48, 0x6c, 0xbb, 0x56, 0x44, 0x94, 0x98, 0xcf, 0x86, 0x74, 0x8d, 0x32, - 0xbb, 0x13, 0x74, 0xb2, 0xd2, 0xbd, 0x3d, 0x55, 0x42, 0xf6, 0x81, 0x7a, 0x24, 0x3f, 0xaf, 0x42, 0x04, 0x9b, 0x9f, - 0xe5, 0x20, 0x5b, 0xa9, 0x70, 0x9a, 0xad, 0xae, 0x0d, 0x7a, 0x0d, 0x14, 0x19, 0xf1, 0x8a, 0x90, 0x2a, 0xf3, 0x65, - 0xe5, 0x44, 0xb9, 0x93, 0x8a, 0x4f, 0xcb, 0xfa, 0xad, 0xa7, 0xd6, 0x1d, 0x11, 0x94, 0x2b, 0x59, 0x7b, 0xae, 0xf7, - 0xa2, 0x80, 0x99, 0xc2, 0xec, 0x09, 0x0e, 0xdf, 0x2d, 0xf0, 0xd6, 0xd7, 0x66, 0xb3, 0xf0, 0xe2, 0x90, 0xfc, 0x4e, - 0x63, 0xff, 0x4a, 0x44, 0x1a, 0xee, 0xb9, 0xf0, 0x58, 0xe5, 0x55, 0x94, 0x9e, 0x67, 0x7a, 0xa2, 0xe8, 0x18, 0x81, - 0x7a, 0x09, 0x55, 0x01, 0x50, 0x2a, 0x28, 0x6a, 0x1e, 0x6e, 0xcd, 0x46, 0xc8, 0xea, 0x02, 0x97, 0x76, 0x41, 0xf3, - 0x4b, 0xd3, 0x28, 0x9e, 0xe1, 0xa3, 0xeb, 0xe2, 0xbc, 0xae, 0xd8, 0xe5, 0xc3, 0xd8, 0x1d, 0x1a, 0x84, 0x12, 0x67, - 0x80, 0x17, 0x03, 0x83, 0xc1, 0xcb, 0x47, 0x45, 0xe0, 0x66, 0x0c, 0xd9, 0x23, 0x6b, 0x40, 0xb1, 0xc2, 0xdf, 0x40, - 0xbe, 0xfa, 0x77, 0xb1, 0x0a, 0xef, 0x0c, 0x5a, 0xb9, 0x42, 0x18, 0x71, 0x7c, 0xa2, 0xa1, 0x87, 0xbf, 0xf2, 0xd6, - 0xf1, 0x16, 0x37, 0xd9, 0xe5, 0xa5, 0x78, 0x6b, 0x18, 0x0e, 0x73, 0x05, 0x6c, 0x0d, 0xaf, 0xac, 0x29, 0x37, 0x2f, - 0xd9, 0x16, 0x53, 0x24, 0x0f, 0xcc, 0x70, 0x5f, 0x84, 0xca, 0xaa, 0x87, 0xff, 0x5d, 0xca, 0xaa, 0xd0, 0x01, 0x5c, - 0x61, 0x32, 0x7a, 0xed, 0xe2, 0xac, 0x60, 0x70, 0x4e, 0x73, 0x9d, 0xd2, 0x52, 0x75, 0x1d, 0x93, 0xd5, 0xf0, 0xe1, - 0x79, 0xb5, 0x82, 0x75, 0x2f, 0x42, 0x74, 0x89, 0x38, 0xc1, 0xe2, 0x13, 0xe9, 0x6b, 0x25, 0xd1, 0xd1, 0xea, 0xa3, - 0xb5, 0xc4, 0x78, 0x5f, 0x5d, 0xf1, 0xb7, 0x42, 0x8f, 0x1b, 0x52, 0x9d, 0xe4, 0xd6, 0x89, 0x82, 0xe8, 0xe6, 0xe7, - 0x02, 0x9d, 0x94, 0xb8, 0x0b, 0x1a, 0x36, 0xba, 0x68, 0xae, 0xdf, 0x87, 0xbe, 0xf9, 0x81, 0xba, 0xb8, 0x68, 0x45, - 0x2b, 0xef, 0x2e, 0x58, 0x29, 0x18, 0x61, 0x2f, 0x80, 0xce, 0x59, 0x0b, 0x4f, 0x2e, 0x59, 0x6b, 0x41, 0x30, 0x43, - 0x1c, 0x00, 0xb8, 0xa2, 0x95, 0x82, 0x0f, 0xe7, 0x31, 0x57, 0x8b, 0x41, 0xdb, 0x31, 0xe1, 0xd5, 0xbf, 0x52, 0x85, - 0x29, 0xb4, 0xef, 0xda, 0xa2, 0x03, 0x8e, 0x24, 0x9a, 0x72, 0x15, 0x5d, 0xb6, 0xe7, 0x79, 0x93, 0x46, 0x6f, 0xeb, - 0xb3, 0x2c, 0xa4, 0x36, 0x9f, 0xcc, 0x12, 0xe4, 0xf5, 0x25, 0xb8, 0x42, 0x49, 0xf6, 0xdf, 0x01, 0x40, 0x9e, 0xda, - 0x5b, 0xff, 0xb6, 0xb6, 0x7c, 0xf5, 0xb0, 0x75, 0x28, 0x2a, 0xb5, 0x92, 0xd4, 0x1d, 0x64, 0xb4, 0x6e, 0x4b, 0x0f, - 0x15, 0x17, 0xb4, 0x33, 0xc6, 0x3c, 0x05, 0xe5, 0x50, 0x7e, 0x84, 0x7c, 0xa6, 0xb6, 0x42, 0x10, 0x61, 0x2c, 0xe8, - 0x5a, 0x4b, 0x65, 0x25, 0x0c, 0x63, 0x1b, 0xb3, 0x2c, 0xbb, 0x2c, 0x5d, 0x66, 0x2b, 0x19, 0xb6, 0xac, 0x14, 0x6e, - 0x61, 0xb3, 0x54, 0x76, 0xf3, 0x5d, 0x19, 0xd6, 0xa2, 0x7c, 0xb3, 0x71, 0x1a, 0x2e, 0x65, 0x64, 0xef, 0xf5, 0x40, - 0x09, 0xe7, 0xfe, 0x31, 0x5d, 0xbf, 0xcd, 0xe8, 0x9c, 0xf2, 0xba, 0x91, 0x16, 0xc3, 0xe9, 0xdf, 0xde, 0xbe, 0x2b, - 0xe9, 0xd0, 0xa0, 0x4f, 0xe7, 0xc8, 0xf6, 0xf6, 0x20, 0xb1, 0xa2, 0x44, 0x7d, 0x3e, 0x6b, 0x6f, 0xaf, 0x14, 0x99, - 0xbd, 0x12, 0xe8, 0xfd, 0x0d, 0xdd, 0x4e, 0x68, 0xc7, 0xca, 0x0f, 0x2a, 0x15, 0x98, 0x7d, 0xad, 0xf9, 0xa4, 0x81, - 0x36, 0x16, 0xbc, 0x44, 0x73, 0xd5, 0x95, 0x31, 0x27, 0xeb, 0x9c, 0x70, 0x93, 0x61, 0xa1, 0x03, 0x4c, 0x19, 0xfe, - 0xca, 0xdd, 0x4b, 0xdc, 0x83, 0x26, 0x89, 0xbe, 0x22, 0x57, 0xb5, 0xbe, 0xb1, 0xf1, 0x8a, 0x5c, 0x4c, 0x84, 0xdc, - 0x12, 0x32, 0x04, 0xf4, 0x04, 0x0d, 0x35, 0x4c, 0x65, 0x84, 0xfe, 0xf6, 0x23, 0xdc, 0xf0, 0x48, 0xb1, 0x32, 0x90, - 0xd6, 0xb4, 0x37, 0x66, 0xa1, 0xa6, 0x4a, 0xc4, 0x41, 0x0f, 0xa7, 0x1c, 0x4a, 0x88, 0xe7, 0xfe, 0xed, 0xed, 0x54, - 0x04, 0x03, 0x8e, 0x0a, 0x59, 0x48, 0x2c, 0x14, 0xcb, 0xea, 0x6c, 0x66, 0x15, 0x06, 0xe8, 0x53, 0x98, 0x7e, 0x0c, - 0xda, 0xa4, 0x56, 0x81, 0x5e, 0x45, 0xe2, 0x95, 0xe8, 0xb5, 0xfd, 0x79, 0xe5, 0x9b, 0xa5, 0x23, 0x09, 0x63, 0x8e, - 0x81, 0x03, 0x77, 0x2b, 0x21, 0xcf, 0xc9, 0xcf, 0x68, 0xdf, 0x33, 0xe4, 0xf2, 0x15, 0x8d, 0x2d, 0x61, 0xa6, 0x86, - 0x06, 0x63, 0x0f, 0x55, 0xf7, 0xaa, 0x3c, 0x2c, 0x4d, 0xa1, 0x69, 0x52, 0xf2, 0x52, 0x09, 0x06, 0x02, 0x24, 0xee, - 0x1a, 0x9a, 0x89, 0xd4, 0x95, 0xe2, 0x89, 0x3a, 0x60, 0x83, 0x9d, 0xab, 0x08, 0x9d, 0xc4, 0x65, 0x20, 0xcc, 0xe6, - 0x3e, 0x69, 0xab, 0x7b, 0x97, 0xa6, 0x73, 0xe8, 0xaf, 0x95, 0x35, 0x2d, 0x88, 0xa1, 0x0d, 0xa8, 0x06, 0x8f, 0x66, - 0xde, 0xb5, 0x01, 0x9a, 0xad, 0x83, 0xcb, 0x02, 0x91, 0xa6, 0x34, 0x30, 0x48, 0x03, 0x2d, 0x8f, 0x59, 0x10, 0x05, - 0xfe, 0xf2, 0x3d, 0xe8, 0xe5, 0x06, 0x89, 0x50, 0x31, 0x54, 0x48, 0x64, 0x03, 0xd0, 0xc2, 0x23, 0x50, 0x63, 0xd1, - 0x0f, 0x4a, 0xad, 0xe9, 0xa5, 0x0d, 0x0a, 0xc5, 0xa5, 0x88, 0xdd, 0x5a, 0xf2, 0x03, 0xab, 0xa3, 0xdd, 0x1a, 0x7f, - 0x04, 0x88, 0x79, 0x2b, 0xc9, 0xa1, 0x0d, 0x65, 0xaa, 0xc1, 0x27, 0x5b, 0x83, 0x0f, 0x53, 0xb0, 0x45, 0x70, 0xa2, - 0x3d, 0x43, 0x77, 0x55, 0x83, 0x92, 0x46, 0x18, 0x69, 0xc4, 0x12, 0x5e, 0xc8, 0xdd, 0xb5, 0xb9, 0x0b, 0x71, 0xbf, - 0x01, 0x39, 0x7e, 0x01, 0xc2, 0xec, 0x19, 0x20, 0xd9, 0xee, 0xb6, 0x99, 0x95, 0x13, 0x58, 0xe2, 0x29, 0x98, 0x7a, - 0xcf, 0x5b, 0x76, 0x90, 0x2e, 0x7e, 0xd6, 0xda, 0xfc, 0x42, 0xdd, 0x32, 0xb9, 0x02, 0xe5, 0xf1, 0x20, 0xbb, 0xdf, - 0xc1, 0x4b, 0xcb, 0xf6, 0xf6, 0xe2, 0xf3, 0x76, 0xaf, 0xd3, 0x8c, 0x03, 0x74, 0xec, 0xb2, 0x97, 0x97, 0xd9, 0xbe, - 0x6a, 0x33, 0x6b, 0x2b, 0x2c, 0xf6, 0xcc, 0x84, 0xea, 0x9a, 0xd5, 0xd2, 0x75, 0x73, 0xdc, 0xe9, 0xf2, 0x56, 0xd7, - 0x51, 0x62, 0x82, 0x46, 0x56, 0x61, 0x1d, 0xcd, 0xb5, 0x40, 0xa9, 0xf1, 0xfe, 0xd2, 0x5c, 0xbe, 0x2e, 0x0f, 0x5d, - 0x61, 0xba, 0xeb, 0x8a, 0x4b, 0x2f, 0x97, 0xd2, 0xe9, 0x1e, 0x96, 0x03, 0xee, 0xd4, 0x17, 0xfc, 0x0b, 0x1a, 0x2c, - 0xe0, 0x9f, 0x26, 0xd9, 0xd6, 0x54, 0xf5, 0x1c, 0x28, 0xe5, 0x04, 0xf0, 0xf7, 0x8b, 0xa3, 0xa7, 0xca, 0xb4, 0x2c, - 0x1d, 0xfd, 0xef, 0x30, 0x73, 0x21, 0x87, 0x00, 0x71, 0x00, 0x83, 0x4a, 0x08, 0xc2, 0x37, 0xd8, 0x20, 0x7c, 0x0a, - 0xaa, 0x44, 0xf4, 0x41, 0x22, 0x32, 0x53, 0x2f, 0x22, 0x6c, 0xd6, 0x95, 0x00, 0x75, 0xf2, 0x8a, 0xbb, 0x22, 0x2c, - 0xbf, 0x7c, 0x91, 0xdc, 0x15, 0x4f, 0xeb, 0xd4, 0x79, 0x59, 0xfd, 0x1a, 0xfb, 0xe7, 0x26, 0xa6, 0xaf, 0x67, 0x8f, - 0x45, 0x36, 0xf5, 0x3f, 0xd9, 0x7b, 0xf7, 0xe6, 0xb6, 0x8d, 0x64, 0x6f, 0xf8, 0xab, 0x48, 0x2c, 0x1f, 0x05, 0x30, - 0x41, 0x5a, 0xf2, 0x5e, 0x9e, 0xe7, 0x80, 0x82, 0x59, 0xbe, 0xc4, 0x6b, 0xef, 0xc6, 0xb1, 0xd7, 0x76, 0xb2, 0xc9, - 0xaa, 0x54, 0x0a, 0x04, 0x82, 0x22, 0x12, 0x08, 0x60, 0x00, 0x50, 0x16, 0x4d, 0xe1, 0xbb, 0x3f, 0x7d, 0x9b, 0x1b, - 0x00, 0xca, 0xce, 0xb9, 0xfc, 0xf5, 0xbe, 0xa9, 0x8a, 0x45, 0x0c, 0x66, 0x06, 0x73, 0xed, 0xe9, 0xee, 0xe9, 0xfe, - 0xf5, 0xcc, 0xb8, 0xf5, 0x58, 0xde, 0x37, 0xdf, 0xc7, 0xd7, 0x29, 0x31, 0x1c, 0x8a, 0x25, 0xb6, 0x43, 0x85, 0x12, - 0x1e, 0x24, 0x7f, 0xba, 0xec, 0x7c, 0x1a, 0x61, 0x6a, 0x2d, 0x03, 0xe6, 0x18, 0x45, 0xf1, 0xd4, 0x27, 0x4b, 0xdf, - 0x12, 0xfe, 0x99, 0x79, 0xef, 0xbd, 0x72, 0x6a, 0x3e, 0xee, 0x93, 0x52, 0x49, 0x3f, 0xc2, 0xc8, 0x02, 0x49, 0x77, - 0xc2, 0x47, 0x7a, 0xa4, 0x72, 0x21, 0xde, 0x9b, 0x7c, 0x12, 0x31, 0xa4, 0x31, 0xc9, 0xe3, 0x68, 0x38, 0xef, 0xf3, - 0x04, 0x72, 0xff, 0xd2, 0xb7, 0xac, 0xe4, 0xf0, 0x9c, 0x63, 0x2e, 0x55, 0x5a, 0x11, 0xbc, 0x42, 0xcf, 0x89, 0xaf, - 0xdb, 0xa7, 0x60, 0x92, 0x29, 0x21, 0xf7, 0x57, 0x1d, 0x37, 0xb1, 0x46, 0x66, 0xd7, 0xac, 0xab, 0xe9, 0x83, 0x1a, - 0xa6, 0x2c, 0xc5, 0xa3, 0x12, 0x2a, 0xd3, 0x6a, 0xac, 0x07, 0x26, 0x22, 0x07, 0xe4, 0x9e, 0x36, 0x2b, 0xe0, 0x19, - 0x59, 0x80, 0x51, 0x59, 0xa2, 0xa2, 0x65, 0x91, 0x86, 0x94, 0x64, 0xfd, 0xaf, 0xb8, 0x17, 0xa8, 0x9d, 0x39, 0x0a, - 0x88, 0xc1, 0x80, 0x16, 0xda, 0x1f, 0xa2, 0x28, 0xca, 0xd6, 0x33, 0x1a, 0xe6, 0x03, 0xad, 0x70, 0xad, 0xc3, 0x81, - 0x5e, 0x18, 0xaa, 0x25, 0x14, 0x83, 0x35, 0x8d, 0x95, 0x61, 0x70, 0x12, 0xe6, 0x6d, 0x2c, 0x85, 0x23, 0x82, 0x80, - 0xe0, 0x30, 0xe5, 0x26, 0x62, 0x3a, 0x5e, 0xf2, 0x3c, 0x18, 0x19, 0xeb, 0x55, 0x7c, 0x8b, 0x69, 0xd2, 0xbf, 0x91, - 0xbf, 0x33, 0x8c, 0xac, 0x90, 0x9c, 0xfe, 0xb4, 0xf8, 0xc6, 0xd8, 0x57, 0x19, 0x79, 0xa6, 0x67, 0x39, 0xeb, 0x9d, - 0x16, 0xb0, 0x42, 0x72, 0x35, 0x1b, 0x1b, 0x84, 0xed, 0x84, 0x49, 0xce, 0x7d, 0xbe, 0x15, 0x81, 0x7f, 0x36, 0x47, - 0x47, 0x8b, 0xa9, 0x3a, 0xd4, 0xfc, 0xdd, 0x62, 0x2a, 0x67, 0xd8, 0x26, 0x58, 0x05, 0xb1, 0x55, 0x31, 0x39, 0x90, - 0x2c, 0x0c, 0x8b, 0x86, 0xb3, 0xbd, 0x81, 0x05, 0xb4, 0x31, 0x67, 0xc9, 0x0e, 0x4d, 0x5f, 0xa3, 0x95, 0x29, 0x83, - 0x5f, 0x8e, 0x16, 0x0c, 0x11, 0x9b, 0x43, 0x8d, 0x0d, 0x5a, 0xb0, 0xa3, 0xe9, 0x23, 0xf5, 0x68, 0xa1, 0x75, 0x2c, - 0xb5, 0x75, 0x70, 0x5a, 0xc7, 0xa6, 0x99, 0x29, 0x15, 0xec, 0x13, 0xe8, 0xa6, 0xeb, 0x5c, 0xdd, 0x98, 0x0b, 0xb5, - 0xd6, 0x9d, 0xe6, 0xc1, 0xa5, 0x40, 0x7a, 0x4c, 0x97, 0x51, 0x05, 0x5e, 0x90, 0x6c, 0xf9, 0x2d, 0xca, 0x81, 0x4e, - 0x23, 0xe8, 0xb8, 0x68, 0xa0, 0x64, 0x86, 0x94, 0xf3, 0x2e, 0x20, 0xc4, 0x57, 0x29, 0xe8, 0xb3, 0x33, 0x24, 0x62, - 0xe7, 0x33, 0xf4, 0x45, 0xd3, 0x63, 0xae, 0x35, 0xf3, 0xe5, 0x94, 0x29, 0xb3, 0x1e, 0x16, 0x21, 0xb5, 0xe8, 0xc9, - 0xe8, 0xd9, 0xd7, 0x84, 0xdb, 0x01, 0xe5, 0x8c, 0x00, 0x26, 0x68, 0x6d, 0xa5, 0xc4, 0x73, 0xdd, 0xe9, 0x04, 0x6d, - 0x81, 0xa4, 0x75, 0xff, 0x66, 0xd3, 0x19, 0x25, 0x67, 0xa4, 0x89, 0x9c, 0x41, 0x0a, 0x4e, 0x83, 0x9d, 0xe4, 0x44, - 0x09, 0xf0, 0x81, 0x1d, 0x25, 0xa7, 0x6d, 0x29, 0x8e, 0x85, 0x41, 0xfa, 0xe8, 0xc6, 0x97, 0x45, 0x74, 0x28, 0xa9, - 0x9a, 0x20, 0x1e, 0x90, 0x72, 0x48, 0xac, 0x0a, 0xd2, 0x4d, 0x63, 0xb8, 0x72, 0x65, 0x4c, 0x31, 0xc7, 0x58, 0x08, - 0x25, 0x87, 0x76, 0x74, 0x12, 0x95, 0xf1, 0x3e, 0xab, 0x2e, 0x8b, 0x79, 0x29, 0x57, 0x03, 0xc5, 0xbc, 0x76, 0xae, - 0x07, 0x6e, 0xed, 0xcb, 0xb5, 0x94, 0x1c, 0x9d, 0xba, 0x62, 0x51, 0x11, 0x51, 0x13, 0xc9, 0xfa, 0xfc, 0x41, 0x6d, - 0x2f, 0x1f, 0x42, 0xd8, 0xa8, 0x51, 0x63, 0x29, 0x18, 0x1b, 0x05, 0xfd, 0x16, 0x94, 0x0d, 0x71, 0x01, 0x61, 0xa4, - 0x8d, 0x82, 0x1f, 0xac, 0x2f, 0xdf, 0xe4, 0xda, 0xfe, 0x93, 0xd9, 0x6f, 0x83, 0xbd, 0x9c, 0xf9, 0x73, 0x8f, 0xe3, - 0x78, 0xad, 0xc9, 0x62, 0x4a, 0xcc, 0x06, 0xa3, 0x4c, 0x59, 0x0a, 0xf2, 0x15, 0xc6, 0x12, 0x9d, 0x45, 0x61, 0xf4, - 0x8b, 0xa8, 0x8e, 0x04, 0xee, 0xa3, 0x91, 0x86, 0xa4, 0xaa, 0x11, 0x05, 0x7f, 0xbe, 0xc6, 0x38, 0x13, 0xe8, 0xe8, - 0xb8, 0xa0, 0x30, 0xaa, 0x68, 0x4b, 0x60, 0x6e, 0x07, 0xaa, 0xc1, 0x6b, 0x24, 0x14, 0x76, 0x3f, 0x50, 0xa0, 0xd4, - 0x17, 0xac, 0x24, 0x7d, 0x93, 0x36, 0x24, 0x12, 0x2b, 0x8f, 0x04, 0xbe, 0xa8, 0xe1, 0xc0, 0xaa, 0x7a, 0xe9, 0x9e, - 0x96, 0xb3, 0xf1, 0xb8, 0xf6, 0x65, 0x79, 0x92, 0x84, 0x46, 0xca, 0xbb, 0x21, 0x6f, 0xa7, 0xa7, 0x5a, 0x29, 0x6f, - 0x21, 0x2d, 0x61, 0xd7, 0xc8, 0xd3, 0x1c, 0x6b, 0xbd, 0x16, 0x73, 0x63, 0x64, 0x5f, 0xf2, 0x74, 0x64, 0x1b, 0xb5, - 0x13, 0xb7, 0x25, 0xf7, 0x21, 0xac, 0xe7, 0xae, 0xa0, 0x29, 0x71, 0xa4, 0x64, 0xca, 0x59, 0x75, 0x1a, 0x93, 0x91, - 0xfb, 0x8e, 0x5c, 0x22, 0xc8, 0xe6, 0x9c, 0xdc, 0xba, 0x78, 0xaa, 0x0b, 0xdc, 0x21, 0x86, 0x84, 0x32, 0xe6, 0x4b, - 0x0e, 0xdf, 0xe6, 0x08, 0x1a, 0x08, 0x19, 0xf0, 0x2b, 0x90, 0x3c, 0xbc, 0x81, 0xe2, 0xf8, 0x68, 0xc7, 0x77, 0x77, - 0xbf, 0x37, 0xec, 0x62, 0xfb, 0x3b, 0x12, 0x43, 0x7c, 0xd5, 0x8c, 0xa3, 0xdc, 0x37, 0x7e, 0x82, 0x96, 0x43, 0x52, - 0x6e, 0x7b, 0x13, 0xd9, 0xbb, 0x1e, 0xdd, 0xa9, 0x2c, 0x47, 0x1d, 0x75, 0x3b, 0x2b, 0xf0, 0x23, 0x81, 0x1a, 0x56, - 0x8e, 0x5a, 0xa0, 0xaf, 0xab, 0x55, 0xd4, 0x02, 0x3c, 0xf0, 0x0b, 0x74, 0x9e, 0x28, 0xce, 0xd1, 0xc4, 0xa0, 0x44, - 0x9b, 0x03, 0x8c, 0x8b, 0x3c, 0x84, 0x07, 0x73, 0xcf, 0xb6, 0x9a, 0x92, 0x3b, 0x6a, 0xba, 0xd0, 0xc5, 0x6c, 0x43, - 0x3e, 0x34, 0x3b, 0xa6, 0xf7, 0xda, 0x62, 0xc9, 0x32, 0x30, 0xca, 0x5d, 0xd1, 0x92, 0x2c, 0x6f, 0xb2, 0x45, 0x3b, - 0x7d, 0x00, 0xc7, 0x2b, 0xff, 0x4d, 0xb9, 0x30, 0xea, 0x6f, 0x51, 0xca, 0x6b, 0x7f, 0xb1, 0x4c, 0x38, 0xcd, 0xa8, - 0x10, 0x52, 0x46, 0x43, 0xc8, 0x18, 0xa9, 0x1d, 0x54, 0xb7, 0xb0, 0x83, 0xea, 0xa2, 0xc3, 0x53, 0x2f, 0xa8, 0xae, - 0x85, 0xb4, 0x51, 0xc0, 0x46, 0x17, 0x5f, 0xa4, 0xef, 0xbf, 0xfd, 0xdb, 0xd3, 0x8f, 0xaf, 0x7f, 0xfc, 0xf6, 0xe2, - 0xf5, 0xf7, 0x2f, 0x5f, 0x7f, 0xff, 0xfa, 0xe3, 0xcf, 0x0c, 0xe1, 0x31, 0x4f, 0x55, 0x86, 0x77, 0x6f, 0x3f, 0xbc, - 0x76, 0x32, 0xd8, 0xd6, 0x0c, 0x79, 0x57, 0x22, 0xc7, 0x8b, 0x40, 0x8a, 0x06, 0x21, 0x4e, 0x76, 0x8a, 0xe7, 0x00, - 0x5e, 0x92, 0x7c, 0xef, 0x52, 0x4a, 0xb6, 0x20, 0x39, 0xac, 0xeb, 0x25, 0xc3, 0x72, 0xd5, 0x74, 0xfb, 0x81, 0x3d, - 0x78, 0x83, 0x26, 0x32, 0xb0, 0x86, 0x7f, 0x64, 0x88, 0x7d, 0xde, 0x49, 0xc0, 0x9d, 0x08, 0x59, 0xf3, 0x7c, 0x9b, - 0xde, 0x0b, 0x9c, 0xff, 0xb9, 0x5c, 0xa2, 0x96, 0x68, 0x00, 0x7c, 0x88, 0x3f, 0x4e, 0xf5, 0x4d, 0x9a, 0x64, 0xd1, - 0x76, 0xc6, 0xe8, 0x74, 0x69, 0x20, 0x4d, 0xec, 0x99, 0x17, 0x7d, 0x72, 0x2a, 0xc0, 0x1d, 0x0b, 0xfc, 0xb4, 0x0a, - 0xd0, 0x9b, 0x4e, 0xd9, 0x2f, 0xb9, 0x26, 0xa5, 0x94, 0xfc, 0x26, 0xde, 0x45, 0xb9, 0x9c, 0x95, 0xc1, 0x8d, 0x0a, - 0x8e, 0x4c, 0x1f, 0xc4, 0x2b, 0xbe, 0x02, 0xcd, 0x7f, 0x39, 0xee, 0x70, 0xae, 0x62, 0x24, 0xaf, 0x22, 0x58, 0x19, - 0xe8, 0x5f, 0x50, 0xa0, 0xcd, 0xab, 0x13, 0x79, 0x79, 0xa3, 0x4f, 0xb9, 0x25, 0x9c, 0x72, 0xcb, 0x53, 0xbc, 0xb0, - 0x5f, 0xaa, 0xee, 0xae, 0x61, 0x3d, 0x2f, 0xcf, 0x83, 0x1d, 0x6c, 0xb7, 0xf0, 0x2a, 0x80, 0x93, 0x3f, 0xbc, 0x6e, - 0xa3, 0x75, 0x70, 0x19, 0xad, 0xad, 0xa6, 0xad, 0xed, 0xa6, 0xcd, 0x36, 0xd1, 0x25, 0x72, 0x08, 0x30, 0x67, 0x18, - 0xf7, 0xf8, 0xca, 0x0f, 0x36, 0xc8, 0xd1, 0x5e, 0x07, 0x1b, 0x14, 0xc4, 0xd6, 0x11, 0xcc, 0xc4, 0x06, 0xda, 0x71, - 0x78, 0x1c, 0x14, 0xb4, 0xfe, 0x7c, 0x7c, 0xc1, 0xb4, 0x50, 0xbf, 0x3b, 0x51, 0xef, 0x66, 0xea, 0xde, 0x0c, 0xf2, - 0xdc, 0x64, 0xf5, 0x26, 0xce, 0xc9, 0xb2, 0x1c, 0x3f, 0xda, 0x49, 0xa1, 0x4f, 0x5f, 0xd0, 0x97, 0xac, 0x85, 0xf3, - 0xaf, 0xac, 0x7b, 0xaf, 0xca, 0xd1, 0x0a, 0x3a, 0x21, 0xb2, 0x3a, 0xee, 0x81, 0x45, 0xf4, 0x04, 0x37, 0x30, 0x8d, - 0x1c, 0xec, 0x3a, 0xe0, 0xec, 0x29, 0xe2, 0xbd, 0x03, 0x80, 0x96, 0x3b, 0x06, 0xf0, 0x84, 0x15, 0xa3, 0xc2, 0xe0, - 0x41, 0xf3, 0xe5, 0xd6, 0x4a, 0xc7, 0x24, 0xb4, 0x2f, 0xb1, 0x1a, 0x99, 0x29, 0xd8, 0x5c, 0x14, 0xf4, 0x41, 0x2c, - 0xef, 0x47, 0x1c, 0x6a, 0x70, 0x24, 0x79, 0x1d, 0xd8, 0xa7, 0xb7, 0x9d, 0x5d, 0x3d, 0xf8, 0x3d, 0x55, 0xbb, 0xc4, - 0xc8, 0x96, 0x4f, 0x57, 0xf1, 0x27, 0xf5, 0x53, 0x62, 0x7d, 0x28, 0x70, 0x84, 0xfb, 0x1a, 0xe0, 0x7c, 0xbd, 0x4e, - 0xbb, 0x83, 0x88, 0x54, 0xb9, 0x42, 0x84, 0xf8, 0x8a, 0x97, 0x39, 0x1d, 0x47, 0xbc, 0x10, 0x91, 0x88, 0xf1, 0x2f, - 0x1a, 0x3e, 0xe2, 0x58, 0x0e, 0x0b, 0x0d, 0x4a, 0x2e, 0x11, 0xbc, 0x67, 0xdd, 0x3d, 0x68, 0xb6, 0x57, 0xad, 0x16, - 0x13, 0x1b, 0x28, 0xdf, 0xdd, 0x95, 0x48, 0x4b, 0x8d, 0x9d, 0x26, 0x3e, 0xe2, 0xf6, 0xd6, 0xd6, 0x9a, 0xc2, 0x2a, - 0x69, 0x80, 0x0a, 0x7a, 0x1d, 0xe0, 0x5f, 0x77, 0x85, 0x58, 0x30, 0x45, 0xfd, 0x97, 0x50, 0xc4, 0x7a, 0x6f, 0xd5, - 0xd5, 0xcb, 0xd6, 0x2a, 0x23, 0xe0, 0x9f, 0x33, 0xed, 0x27, 0x49, 0x70, 0xea, 0x23, 0x8e, 0x45, 0x3d, 0x2a, 0xd0, - 0xeb, 0x26, 0xf8, 0x58, 0x6b, 0x67, 0xcb, 0x79, 0x16, 0xf6, 0xd8, 0x2f, 0x38, 0x65, 0xde, 0xe5, 0x56, 0x1c, 0x75, - 0x8a, 0x46, 0xb4, 0xca, 0x16, 0x8b, 0xb4, 0x40, 0xf2, 0x7e, 0x21, 0xf4, 0xff, 0xe8, 0x08, 0xdd, 0x49, 0xeb, 0x10, - 0x38, 0x80, 0x94, 0x10, 0xe1, 0xf8, 0xf0, 0xe3, 0x80, 0x27, 0xa2, 0x2a, 0x7c, 0xd0, 0xec, 0x91, 0x98, 0x5d, 0x81, - 0x39, 0x69, 0x6e, 0x11, 0x86, 0xb1, 0xb9, 0xb5, 0x02, 0x92, 0x68, 0xa5, 0x19, 0x93, 0x1e, 0x64, 0x23, 0x40, 0x02, - 0x31, 0xb1, 0x3c, 0x2c, 0x92, 0xc4, 0x0c, 0xf8, 0x15, 0x33, 0x19, 0xfa, 0x6e, 0x04, 0x57, 0x4c, 0xd4, 0xcd, 0x4a, - 0x5b, 0xd7, 0x89, 0x36, 0xe7, 0xc4, 0x0b, 0xb9, 0xd0, 0x51, 0x47, 0x94, 0x26, 0x88, 0xe2, 0x0f, 0x38, 0x59, 0xd8, - 0x8d, 0xe6, 0x45, 0x2f, 0x9d, 0x39, 0xd6, 0xb7, 0x43, 0xb5, 0xe2, 0x9d, 0xcd, 0x07, 0xd2, 0x97, 0xf5, 0x92, 0x9f, - 0xa3, 0x91, 0x8e, 0x93, 0x9c, 0x16, 0xc8, 0x6a, 0x71, 0x3d, 0x1f, 0xa0, 0x4e, 0xbb, 0x39, 0xf5, 0x66, 0xbd, 0x06, - 0xae, 0xaa, 0x7e, 0x91, 0x26, 0x2a, 0xbc, 0x8f, 0x7a, 0xf5, 0x40, 0x20, 0x15, 0x3a, 0x8d, 0xda, 0x16, 0x09, 0x9a, - 0x6d, 0x6a, 0xc5, 0xb6, 0x6c, 0x61, 0x41, 0x8d, 0xff, 0x88, 0x63, 0x04, 0x0c, 0x85, 0x38, 0x68, 0x0c, 0xbc, 0x35, - 0xa5, 0xee, 0x29, 0xd2, 0xcb, 0x2f, 0xb7, 0x36, 0x20, 0x43, 0x01, 0x61, 0xb2, 0x1f, 0x3a, 0x4a, 0x20, 0x33, 0x31, - 0xb3, 0x8e, 0x86, 0x44, 0x66, 0x31, 0xcf, 0x8a, 0xdf, 0x68, 0xc7, 0xd6, 0x84, 0x34, 0xac, 0xd6, 0x5e, 0x04, 0x0c, - 0x4a, 0x23, 0x7b, 0x39, 0xd0, 0xb1, 0x59, 0x16, 0x0b, 0x15, 0xc5, 0x45, 0x15, 0x57, 0x2c, 0x0b, 0xba, 0x38, 0xe2, - 0x32, 0xd6, 0x4b, 0x6f, 0x9a, 0xd5, 0xef, 0x28, 0xa0, 0xcc, 0xb7, 0x34, 0xda, 0x0b, 0x6f, 0x84, 0x59, 0x38, 0xc6, - 0x16, 0x36, 0x51, 0x63, 0xb3, 0x8d, 0x3e, 0x56, 0x59, 0xba, 0x38, 0x68, 0xca, 0x83, 0x0d, 0x88, 0xa3, 0xcd, 0x2a, - 0x3d, 0xf8, 0x06, 0x73, 0x7e, 0x73, 0xc0, 0x55, 0x1f, 0x7c, 0xca, 0x9a, 0x55, 0xb9, 0x69, 0xf8, 0xcd, 0x4b, 0xaa, - 0xe3, 0x9b, 0x03, 0x8e, 0x55, 0x73, 0xc0, 0x33, 0xb9, 0x98, 0x1e, 0xbc, 0xcb, 0x31, 0xc8, 0xeb, 0x41, 0x76, 0x8d, - 0x93, 0x77, 0x10, 0x17, 0x8b, 0x83, 0x2a, 0xbd, 0xc2, 0x1b, 0xa7, 0x6a, 0xb0, 0x1c, 0x66, 0xb8, 0x8e, 0x7f, 0x4b, - 0x0f, 0x10, 0xda, 0xf5, 0x20, 0x6b, 0x0e, 0xb2, 0xfa, 0xa0, 0x28, 0x41, 0xb2, 0x16, 0x2e, 0x1c, 0xdd, 0xf8, 0xb1, - 0x9c, 0x16, 0xd9, 0x45, 0x9a, 0x25, 0x2a, 0x4b, 0xf1, 0x53, 0xf4, 0x2e, 0xe2, 0x48, 0x1a, 0x75, 0xea, 0x75, 0xc7, - 0xdb, 0xb7, 0xb7, 0x5a, 0xd3, 0xda, 0xe3, 0xec, 0xce, 0x11, 0x0b, 0xa8, 0xfd, 0x9d, 0xa4, 0x54, 0x50, 0x18, 0xc0, - 0x89, 0x57, 0x8d, 0x87, 0x32, 0x0e, 0x5a, 0x35, 0x04, 0xcb, 0x60, 0x0d, 0x84, 0x63, 0x21, 0x6e, 0xda, 0x9b, 0x90, - 0x7e, 0x55, 0xa3, 0xf9, 0x3a, 0x5c, 0x92, 0xbc, 0x45, 0xd1, 0x86, 0x5e, 0xbf, 0x88, 0x9e, 0x02, 0x27, 0x2d, 0xbf, - 0x83, 0x7f, 0x21, 0x10, 0x06, 0xfa, 0xac, 0xfa, 0x74, 0xc5, 0xbd, 0xb5, 0xb2, 0x6c, 0x9d, 0x2c, 0xdb, 0x11, 0xd9, - 0x35, 0x81, 0x58, 0x67, 0x65, 0xa9, 0x9c, 0x2c, 0x15, 0x66, 0x41, 0x9b, 0x18, 0x1d, 0xda, 0x08, 0x21, 0x6c, 0xa7, - 0x99, 0x14, 0xa8, 0xbd, 0x84, 0xdd, 0x39, 0xd1, 0xf2, 0x24, 0x9d, 0xde, 0x58, 0xc9, 0x88, 0xe1, 0x10, 0xe3, 0x75, - 0xd0, 0x2d, 0x8d, 0x86, 0xee, 0x22, 0x3d, 0xbd, 0x2c, 0xab, 0xd7, 0x0b, 0xb6, 0x29, 0xd8, 0xee, 0x7d, 0x5d, 0xe1, - 0xeb, 0x6a, 0xef, 0xeb, 0x98, 0x2c, 0x12, 0xf6, 0xbe, 0x46, 0xdb, 0x23, 0x59, 0xd7, 0x43, 0xaf, 0x57, 0x14, 0x5b, - 0x48, 0x8f, 0xb7, 0x73, 0x25, 0xc0, 0xeb, 0x1a, 0xb7, 0xa3, 0x0e, 0xc5, 0x75, 0x66, 0xe6, 0xf8, 0xbc, 0xd5, 0xf4, - 0x71, 0xa0, 0x94, 0xa9, 0x94, 0xb2, 0x98, 0x62, 0xf4, 0x3d, 0xab, 0x01, 0xcd, 0x50, 0x69, 0xe6, 0x5b, 0x80, 0xdd, - 0xa5, 0x7b, 0xdf, 0xb7, 0xb0, 0x34, 0xb9, 0xff, 0x03, 0xf7, 0x79, 0x66, 0xbf, 0xab, 0x6a, 0x50, 0xa8, 0x92, 0x01, - 0x99, 0xab, 0xae, 0x87, 0x2a, 0xa5, 0xa5, 0xd3, 0x4b, 0xeb, 0xf2, 0x45, 0x69, 0x23, 0x67, 0x9a, 0xdf, 0x22, 0x5e, - 0x0c, 0x1c, 0xf6, 0xdb, 0x2f, 0xd2, 0x15, 0x22, 0xe3, 0x47, 0x47, 0xeb, 0xda, 0x33, 0x8f, 0xb4, 0x01, 0x6c, 0xa2, - 0xc2, 0xfb, 0x04, 0x6b, 0x85, 0xb7, 0xcf, 0x57, 0x69, 0xf2, 0x5b, 0xb7, 0x5e, 0x67, 0xad, 0x23, 0x46, 0x14, 0xc7, - 0xb7, 0xf1, 0xf8, 0x07, 0x2a, 0xae, 0xcd, 0x7d, 0x00, 0x24, 0x30, 0xfa, 0x4c, 0x8a, 0x48, 0x3d, 0xfa, 0x28, 0xf9, - 0x84, 0x9a, 0x15, 0x1d, 0x3b, 0xa6, 0x38, 0xd4, 0x22, 0xa5, 0xbf, 0x83, 0xd6, 0xf1, 0x75, 0x4a, 0xf7, 0x9a, 0xc6, - 0xea, 0x0d, 0xb4, 0x10, 0x6f, 0xfa, 0x14, 0xaf, 0x02, 0x9f, 0x6c, 0x81, 0xad, 0x91, 0x23, 0x3c, 0xab, 0xbf, 0xbd, - 0x25, 0xff, 0x56, 0x44, 0x34, 0x4a, 0x51, 0xc1, 0x8a, 0x30, 0x2f, 0xd2, 0xcd, 0xe1, 0xe3, 0x80, 0x1b, 0x95, 0xb6, - 0xad, 0x43, 0x3c, 0xbf, 0x66, 0x34, 0x65, 0x80, 0xf6, 0x9d, 0x2a, 0x28, 0xe0, 0xaa, 0x64, 0x12, 0x59, 0xf7, 0xe4, - 0xf3, 0xdb, 0xcb, 0x4d, 0x96, 0x2f, 0xde, 0x56, 0x3f, 0xd0, 0xdc, 0xea, 0x36, 0xdc, 0xb3, 0x74, 0x86, 0x28, 0x8f, - 0xdc, 0xf6, 0xa2, 0x43, 0x44, 0xb7, 0x85, 0x5a, 0x2f, 0x9c, 0xea, 0x99, 0x9e, 0xa5, 0xce, 0x49, 0xa2, 0x96, 0x1d, - 0x6a, 0x69, 0x52, 0x2d, 0xbe, 0x16, 0xfc, 0x8b, 0x9c, 0xb5, 0x41, 0x22, 0xc0, 0x60, 0x25, 0xfa, 0xb5, 0x7a, 0x69, - 0xee, 0xcc, 0x71, 0x64, 0xad, 0xc6, 0x07, 0x1e, 0xc8, 0x01, 0x84, 0x0f, 0xa3, 0xbf, 0x04, 0xf3, 0xf1, 0x82, 0xd7, - 0x1f, 0xd4, 0x22, 0xf3, 0x67, 0x5f, 0x03, 0x0c, 0xd1, 0x5d, 0x39, 0x10, 0xf5, 0x5a, 0xab, 0x53, 0x46, 0xbc, 0x21, - 0x4c, 0x34, 0xc3, 0xe6, 0xd0, 0xb2, 0x23, 0xcd, 0x3f, 0x73, 0x0d, 0x04, 0x51, 0xe2, 0x0d, 0x2c, 0x59, 0xe4, 0xd3, - 0x66, 0x0e, 0xf7, 0xa3, 0x70, 0x22, 0xdf, 0xa7, 0x70, 0xe6, 0xdd, 0xa0, 0x80, 0x11, 0xa8, 0x72, 0xda, 0x2e, 0xd1, - 0xef, 0x30, 0x47, 0xce, 0xd1, 0xaa, 0x10, 0x44, 0xf6, 0x30, 0x6b, 0x2d, 0x63, 0x82, 0xd8, 0x20, 0x5e, 0xb6, 0x2c, - 0x19, 0xd0, 0x4c, 0xa1, 0xb0, 0x4e, 0x03, 0x63, 0x44, 0x47, 0x35, 0x6a, 0x08, 0xe3, 0x55, 0x10, 0x68, 0x36, 0xb1, - 0xec, 0x02, 0x51, 0xc5, 0x86, 0x27, 0xa8, 0x76, 0x50, 0x1a, 0x9b, 0xf9, 0xe1, 0x71, 0x58, 0xc0, 0x58, 0x93, 0xce, - 0x09, 0xa8, 0x7d, 0x83, 0xc0, 0xda, 0x85, 0x1a, 0xe7, 0xb3, 0x06, 0x2d, 0x69, 0x38, 0x9e, 0x8f, 0xd1, 0xf6, 0x4a, - 0x77, 0x48, 0x6d, 0xa7, 0xb3, 0x46, 0x75, 0xa0, 0xeb, 0xc1, 0x79, 0xdf, 0x44, 0x35, 0xfb, 0x19, 0xbe, 0xf7, 0x90, - 0xc4, 0xf9, 0xf3, 0x0d, 0xf7, 0x9f, 0x72, 0x93, 0x1e, 0x06, 0x7b, 0x8b, 0xd6, 0x14, 0x1c, 0xf5, 0xf7, 0xdd, 0x40, - 0xb6, 0xb7, 0x9a, 0x65, 0x34, 0xf9, 0xec, 0xf7, 0xef, 0xaa, 0xec, 0x3a, 0x43, 0x79, 0xc9, 0xc9, 0xa2, 0x23, 0x0f, - 0xe1, 0x7d, 0xc3, 0x02, 0xc5, 0x47, 0x85, 0x47, 0x04, 0xbc, 0x0c, 0x3e, 0x9f, 0xe6, 0x78, 0x15, 0x83, 0xe2, 0x0a, - 0xc3, 0x78, 0xa4, 0x04, 0xe2, 0x61, 0x3a, 0xbd, 0x1a, 0x37, 0xa8, 0x0d, 0xdf, 0x20, 0x64, 0x06, 0x5a, 0x64, 0x2e, - 0x3d, 0x06, 0xee, 0x42, 0xd3, 0x9e, 0x3c, 0x5a, 0xf8, 0x33, 0xd3, 0xd1, 0xa4, 0xad, 0xcc, 0xf2, 0xdc, 0xf8, 0xed, - 0x40, 0xb3, 0xdc, 0x7b, 0xfe, 0xbe, 0x90, 0xdf, 0x92, 0x15, 0xb4, 0x08, 0xf7, 0x89, 0x12, 0xee, 0x73, 0xf6, 0xcb, - 0xa4, 0xe0, 0xb0, 0xc8, 0x96, 0xad, 0x22, 0x8c, 0x63, 0x54, 0x05, 0x0b, 0x4b, 0x8f, 0x55, 0xf3, 0xf6, 0x25, 0xbe, - 0x41, 0x0c, 0x3a, 0xd1, 0x59, 0xa2, 0x46, 0x67, 0x09, 0xf2, 0x8b, 0x58, 0x47, 0x9b, 0x71, 0x11, 0x2c, 0xce, 0x36, - 0xe7, 0x11, 0x05, 0xac, 0x5b, 0xc1, 0xde, 0x12, 0xb0, 0x99, 0xfc, 0x6c, 0x7d, 0x0e, 0xdc, 0x46, 0x80, 0x4a, 0x80, - 0x4a, 0xd2, 0x52, 0x4e, 0xd3, 0x8a, 0xad, 0x45, 0xdb, 0x99, 0xac, 0x4e, 0x57, 0x6e, 0x55, 0x57, 0xb6, 0x4e, 0x57, - 0x7a, 0x0d, 0x94, 0x98, 0x50, 0x2a, 0x64, 0x18, 0xc2, 0x88, 0xcd, 0x92, 0xd3, 0x9c, 0x6c, 0xbc, 0x57, 0x51, 0x82, - 0x4d, 0x24, 0xe4, 0x93, 0x80, 0x20, 0x30, 0x09, 0xc5, 0x85, 0x1b, 0xb4, 0x40, 0xc8, 0x88, 0x15, 0x3a, 0x13, 0x55, - 0x3a, 0x05, 0xd7, 0xa3, 0x69, 0x62, 0xdc, 0x76, 0x17, 0xca, 0xd7, 0xb4, 0x71, 0x47, 0xbc, 0x0d, 0x10, 0x83, 0x30, - 0xa6, 0xd8, 0x8d, 0x5b, 0xf5, 0x98, 0x44, 0xc0, 0x26, 0x75, 0x31, 0x7e, 0xf2, 0x7e, 0x8f, 0x68, 0x47, 0x04, 0x4b, - 0xb5, 0x86, 0xa0, 0xfd, 0x35, 0xac, 0xa3, 0x05, 0xad, 0xa3, 0x4d, 0xb4, 0x82, 0x1e, 0x2d, 0xd1, 0x82, 0xf6, 0x3c, - 0xc8, 0x11, 0x7f, 0xc5, 0xea, 0xd1, 0xcf, 0x8d, 0xb7, 0x44, 0xfe, 0x69, 0x63, 0x77, 0x8a, 0x12, 0x13, 0x4c, 0xd4, - 0xfd, 0xca, 0x91, 0x7f, 0x78, 0x47, 0xcb, 0xb1, 0x6f, 0x29, 0x63, 0xa4, 0x32, 0xbd, 0x4d, 0xcf, 0x15, 0x7f, 0x23, - 0xb4, 0xf4, 0xbe, 0x42, 0x48, 0x39, 0xb0, 0x04, 0x85, 0x0d, 0xfc, 0x80, 0xe4, 0x42, 0xd9, 0x41, 0x38, 0xc7, 0x27, - 0x33, 0xb0, 0x65, 0xff, 0x18, 0xa9, 0x30, 0x42, 0x38, 0xad, 0x52, 0x04, 0xa6, 0xd1, 0xc2, 0x6c, 0x6d, 0x0b, 0xb3, - 0x5a, 0xb3, 0xa5, 0x72, 0xba, 0x32, 0xb7, 0xee, 0xe7, 0x53, 0x01, 0x00, 0x13, 0x9d, 0x03, 0xc7, 0xcc, 0xc4, 0x7b, - 0x69, 0x66, 0x59, 0xde, 0xc7, 0xc5, 0x55, 0xfa, 0xb2, 0x2a, 0xaf, 0xd5, 0x50, 0x74, 0x6d, 0x66, 0x8a, 0x33, 0xd6, - 0x49, 0x28, 0x87, 0x82, 0x52, 0xf6, 0xfa, 0xfc, 0xfb, 0xf8, 0xfb, 0xb0, 0xd4, 0xc0, 0x6c, 0x35, 0xd1, 0x34, 0x69, - 0x91, 0x2a, 0x01, 0x89, 0x6c, 0x1a, 0xc8, 0x6d, 0x8e, 0xb0, 0x67, 0x4f, 0x6b, 0x72, 0x10, 0xeb, 0x8d, 0x19, 0x33, - 0x75, 0xc8, 0xf5, 0xe0, 0x45, 0x88, 0xbe, 0xd3, 0xa7, 0xc7, 0x80, 0x02, 0x5d, 0xe0, 0x5d, 0x88, 0xbe, 0xe0, 0xa7, - 0x47, 0xbc, 0x9f, 0x45, 0xe6, 0x31, 0x2b, 0xde, 0x60, 0x52, 0xff, 0x82, 0xd3, 0x1a, 0x53, 0xb4, 0x41, 0x92, 0xc9, - 0x24, 0x1d, 0xbc, 0xd0, 0x97, 0xa3, 0x23, 0x24, 0xd9, 0x85, 0x70, 0x75, 0xd0, 0x3e, 0x45, 0xb6, 0xb5, 0x1d, 0x44, - 0x97, 0x71, 0x44, 0x67, 0xed, 0x9c, 0x10, 0xc1, 0xcc, 0x24, 0x22, 0xd5, 0x22, 0xdd, 0xed, 0x3e, 0xb5, 0x2c, 0xe9, - 0x6d, 0xf7, 0x29, 0x75, 0xdb, 0x80, 0xca, 0xae, 0x28, 0xd3, 0xa2, 0x8d, 0x3e, 0xe4, 0xc0, 0x8c, 0x2b, 0xc2, 0x63, - 0xc5, 0x69, 0x87, 0x83, 0x18, 0x68, 0x0f, 0x2c, 0x7a, 0x19, 0xf5, 0xab, 0x68, 0x79, 0x16, 0xcb, 0x50, 0xcb, 0xe5, - 0xce, 0xaf, 0xde, 0x52, 0xad, 0x07, 0xff, 0xee, 0x6e, 0x85, 0xfe, 0x46, 0x8b, 0xd3, 0xab, 0x56, 0x48, 0x17, 0x90, - 0xad, 0x0a, 0x51, 0xbf, 0x0f, 0xd7, 0x44, 0x6f, 0xa9, 0xfd, 0xc3, 0xcb, 0x20, 0x07, 0x3a, 0x4f, 0x3b, 0xa6, 0xf4, - 0xd9, 0x01, 0x0c, 0x0f, 0xa7, 0x92, 0xb5, 0xc0, 0x9b, 0xa8, 0x9a, 0x9c, 0xcc, 0x36, 0x7c, 0xa5, 0xbb, 0xf1, 0x29, - 0x76, 0x16, 0xaa, 0x7a, 0xbf, 0xa2, 0x3a, 0xb9, 0x90, 0x68, 0xed, 0x3d, 0xf8, 0x34, 0xcf, 0x39, 0x17, 0x2f, 0xdc, - 0xfb, 0xf8, 0x2b, 0x3d, 0x81, 0x85, 0x72, 0x25, 0x20, 0xf4, 0x1b, 0xeb, 0xc6, 0x26, 0xed, 0xde, 0xd8, 0xe0, 0x56, - 0xaa, 0xcf, 0xf5, 0x6e, 0xfa, 0x15, 0xa4, 0x20, 0x5c, 0xa9, 0x74, 0x8d, 0x53, 0x19, 0x0d, 0x38, 0x2d, 0xa3, 0xf8, - 0xf6, 0x2d, 0xf0, 0x19, 0xcb, 0x1c, 0x6f, 0xb2, 0x95, 0x3b, 0xc5, 0x49, 0xab, 0xce, 0x88, 0xa7, 0xc5, 0x42, 0x01, - 0x74, 0xdc, 0xc7, 0x00, 0x2a, 0x01, 0x81, 0x14, 0xd1, 0xc2, 0xbd, 0x95, 0x9a, 0x2d, 0xd4, 0x04, 0x47, 0x29, 0xfc, - 0x29, 0xfc, 0x79, 0x58, 0xcc, 0x11, 0x88, 0x5d, 0x1f, 0x47, 0x20, 0xd1, 0xf0, 0xa7, 0xca, 0xb3, 0x42, 0x26, 0x13, - 0xa3, 0xab, 0x73, 0x30, 0xd4, 0x1a, 0xf3, 0xd6, 0x43, 0x79, 0x6b, 0x93, 0xb7, 0x35, 0x46, 0xc9, 0xf7, 0x48, 0x3a, - 0xd6, 0x8c, 0xa1, 0x55, 0x9e, 0xd6, 0x69, 0x22, 0x37, 0x79, 0x81, 0x11, 0x86, 0xa2, 0x9b, 0xdc, 0x7b, 0xea, 0x39, - 0x5c, 0x15, 0x26, 0x07, 0xb7, 0xb9, 0xa7, 0x04, 0x51, 0x2d, 0x72, 0x6a, 0xee, 0xcc, 0x19, 0x47, 0x04, 0xef, 0x31, - 0x2d, 0x69, 0xd9, 0x46, 0xb8, 0xcb, 0xc5, 0x37, 0xb7, 0x4a, 0x8c, 0x97, 0x4b, 0xe7, 0xe1, 0xed, 0xcb, 0x32, 0x0d, - 0xd9, 0x29, 0xa4, 0x9c, 0xf3, 0x29, 0x2c, 0x27, 0x04, 0x53, 0x3c, 0xd7, 0xbb, 0x55, 0x2b, 0xb4, 0xee, 0xee, 0x8e, - 0xb5, 0xa1, 0x90, 0x56, 0x67, 0x61, 0xb4, 0x1a, 0x31, 0x4a, 0x40, 0x17, 0x1c, 0xa7, 0x63, 0x7b, 0x22, 0xee, 0xf2, - 0x69, 0xc4, 0xb7, 0x57, 0x8a, 0xd3, 0xc5, 0x15, 0x24, 0x3f, 0xd9, 0xea, 0x19, 0xd1, 0x12, 0xd0, 0xa0, 0x08, 0x98, - 0x88, 0x18, 0x8e, 0x29, 0x84, 0x4e, 0xc7, 0x83, 0x4a, 0x43, 0x73, 0xd6, 0x70, 0x48, 0xcd, 0x16, 0xa2, 0xaa, 0x04, - 0xb1, 0x4c, 0x99, 0x19, 0x1c, 0x1d, 0xe5, 0xf3, 0x4a, 0x99, 0x00, 0x84, 0x0b, 0x5d, 0x19, 0x22, 0x1e, 0x69, 0xe6, - 0xc9, 0x0a, 0x9f, 0xb2, 0xf2, 0x2b, 0xa8, 0xc9, 0x64, 0x23, 0x19, 0x98, 0xc0, 0x66, 0x5c, 0x93, 0x94, 0xf9, 0x88, - 0xeb, 0x1f, 0x19, 0x3d, 0xb5, 0x2d, 0xd6, 0xea, 0x1b, 0xb1, 0xa1, 0x83, 0x0b, 0x3a, 0x35, 0xa7, 0x17, 0x15, 0x33, - 0xde, 0x2f, 0x1c, 0xc9, 0x48, 0xd9, 0x5a, 0x14, 0x7e, 0xd8, 0xcd, 0xd4, 0xc9, 0x41, 0x33, 0x50, 0x50, 0x13, 0x15, - 0xbf, 0x3e, 0x74, 0x08, 0xf6, 0x64, 0xa5, 0x92, 0xf8, 0xe0, 0x27, 0xc8, 0x46, 0x37, 0xa7, 0x83, 0x2d, 0xd4, 0x91, - 0x46, 0x95, 0x45, 0xd0, 0xbe, 0x03, 0x78, 0x56, 0x02, 0xb3, 0xa7, 0xd4, 0x8f, 0x30, 0xec, 0xe6, 0x21, 0x7a, 0x9b, - 0x6b, 0x29, 0xc4, 0x78, 0x39, 0x35, 0x04, 0x89, 0x2b, 0x9c, 0xc4, 0xa2, 0xbf, 0x69, 0xe1, 0x15, 0x8c, 0x7c, 0x54, - 0xab, 0xfa, 0xd5, 0xa9, 0x0a, 0x9c, 0xa4, 0xbe, 0x4b, 0x88, 0x1a, 0xb6, 0x0f, 0x91, 0x3d, 0x6f, 0x7d, 0xdd, 0x55, - 0x86, 0x3e, 0x97, 0x06, 0x0c, 0x38, 0x5b, 0x59, 0x4a, 0x0e, 0xfc, 0xa4, 0x92, 0x55, 0xeb, 0xce, 0xe7, 0xd4, 0xdd, - 0x48, 0x64, 0xf2, 0x6b, 0xdf, 0xc1, 0xa9, 0xb2, 0x1b, 0x3c, 0x4c, 0x31, 0x7a, 0x0d, 0xde, 0x37, 0x17, 0x41, 0xd9, - 0xde, 0x3b, 0xa5, 0x5d, 0x86, 0x46, 0x32, 0x77, 0x73, 0x0d, 0x4b, 0xcb, 0xd3, 0x6c, 0x81, 0x9e, 0x69, 0xf7, 0x2c, - 0x07, 0x3b, 0xa2, 0xfc, 0xd7, 0xd4, 0xdf, 0xa9, 0x9c, 0x1c, 0xdf, 0xf6, 0x95, 0x41, 0x54, 0x3d, 0x7d, 0x21, 0x63, - 0xad, 0x30, 0xba, 0x65, 0x97, 0xad, 0xd0, 0x61, 0xb4, 0x94, 0x24, 0x88, 0xc6, 0x8f, 0x84, 0x72, 0x84, 0xa0, 0x8b, - 0xec, 0x30, 0x11, 0xed, 0xd3, 0x76, 0x1f, 0x1d, 0xad, 0x33, 0x8f, 0xcd, 0xbb, 0x62, 0x75, 0x67, 0xf9, 0x91, 0x61, - 0xec, 0x67, 0xca, 0xb0, 0xa9, 0x2f, 0x22, 0xaf, 0xa2, 0xbc, 0x33, 0x60, 0x43, 0x92, 0x32, 0x2a, 0x8b, 0x81, 0x50, - 0xcc, 0xcf, 0x7e, 0x79, 0xb0, 0x6b, 0x5a, 0x8a, 0x42, 0xfe, 0x4b, 0x30, 0xa2, 0x60, 0xd0, 0x23, 0x74, 0x85, 0x18, - 0x9d, 0x87, 0x67, 0xf4, 0x07, 0xe4, 0xbe, 0xfc, 0x2b, 0x24, 0xea, 0x15, 0x62, 0x8e, 0xb8, 0x56, 0x7a, 0x2a, 0x6c, - 0x3d, 0x4a, 0x81, 0xc1, 0x9a, 0x84, 0xb7, 0xee, 0x1e, 0x28, 0xd8, 0x8f, 0xff, 0x0a, 0x3e, 0x21, 0x43, 0x8d, 0x76, - 0x7a, 0xea, 0xee, 0xc0, 0x23, 0x41, 0x08, 0x43, 0x0c, 0x4b, 0xe7, 0xaf, 0x2c, 0xc3, 0x19, 0xfd, 0x3b, 0x4a, 0x02, - 0x72, 0x16, 0x91, 0x8f, 0x2f, 0xab, 0x34, 0xfd, 0x9c, 0x7a, 0x30, 0x4e, 0x57, 0x6c, 0x94, 0x79, 0xa5, 0xa7, 0xd1, - 0x35, 0x49, 0xfa, 0x2a, 0xfe, 0xd8, 0x9a, 0xb6, 0x5f, 0xb4, 0xf9, 0xcd, 0x84, 0x40, 0x08, 0x65, 0xfe, 0x9c, 0xd9, - 0x89, 0x8d, 0x0d, 0xab, 0xa1, 0xf4, 0xba, 0xdc, 0x21, 0x09, 0xd8, 0x1a, 0x0d, 0xb0, 0x3f, 0x75, 0x8b, 0x68, 0xa5, - 0xa6, 0x4e, 0xb7, 0x75, 0x70, 0xf2, 0xf0, 0x42, 0x16, 0xf2, 0x7e, 0x79, 0x5a, 0x60, 0xec, 0x12, 0xc8, 0xd8, 0x51, - 0x6d, 0x6c, 0x7a, 0xaa, 0x0d, 0x38, 0x04, 0xd1, 0x9a, 0xad, 0x55, 0xcb, 0x0a, 0x05, 0xa4, 0x4b, 0xbc, 0x1c, 0x4e, - 0x10, 0x64, 0xc5, 0x18, 0x1e, 0x19, 0x4c, 0x60, 0x4c, 0x37, 0x21, 0x0a, 0xd0, 0xc2, 0xa3, 0x3f, 0x09, 0x39, 0x42, - 0xba, 0xd0, 0xa1, 0x61, 0x5f, 0x09, 0x29, 0x3b, 0xcf, 0xc3, 0x46, 0x4d, 0xa1, 0xef, 0x6c, 0x54, 0xe7, 0xfe, 0x48, - 0x5b, 0xc5, 0xba, 0xb7, 0x4a, 0xbd, 0xbb, 0x3a, 0x44, 0xdf, 0x10, 0xc7, 0xb7, 0x01, 0x12, 0x80, 0xde, 0x12, 0x3f, - 0x67, 0xf0, 0x61, 0xf1, 0x59, 0xe1, 0x51, 0xbf, 0x30, 0xfd, 0x7a, 0x21, 0x37, 0x0a, 0xa4, 0xb8, 0xed, 0xb4, 0xb6, - 0xc7, 0xe7, 0xdf, 0x4f, 0x75, 0xb4, 0xe1, 0xb3, 0xd3, 0x62, 0x8b, 0x29, 0x73, 0xab, 0xe7, 0x60, 0x75, 0x4c, 0x52, - 0x9d, 0xe6, 0x23, 0x2e, 0x35, 0xab, 0xce, 0x0c, 0x0c, 0xaf, 0x61, 0xa0, 0xdc, 0x4a, 0x24, 0x8c, 0xc3, 0xce, 0xf9, - 0x24, 0xc8, 0xc8, 0x6e, 0x95, 0x88, 0x04, 0xb6, 0xb1, 0xb5, 0x8b, 0x46, 0xfc, 0x82, 0xc1, 0xa9, 0xbb, 0xa1, 0xea, - 0xd1, 0x1a, 0x2f, 0x74, 0x68, 0xa7, 0xb5, 0x81, 0x10, 0x0a, 0x5b, 0xf3, 0x72, 0x78, 0xee, 0x0e, 0x35, 0x4b, 0x79, - 0x19, 0x81, 0x10, 0xf0, 0x73, 0x46, 0x8a, 0xd8, 0x7d, 0xd5, 0xa9, 0xdb, 0x6f, 0xb7, 0xce, 0x8b, 0xda, 0xe2, 0x37, - 0xb8, 0xa1, 0x8d, 0x3a, 0x6a, 0x6a, 0xd7, 0xcc, 0x55, 0x73, 0x26, 0x84, 0xd1, 0xbd, 0xbf, 0xd5, 0x85, 0xd3, 0xee, - 0x9d, 0xf2, 0x23, 0xc6, 0x00, 0x37, 0xc3, 0xf3, 0x43, 0x93, 0xd0, 0x2a, 0x2f, 0x17, 0x22, 0x94, 0x56, 0x93, 0x94, - 0x42, 0xde, 0x6a, 0x68, 0x11, 0xe8, 0x23, 0x00, 0x3d, 0xc0, 0xe0, 0xcd, 0x1f, 0x2c, 0x74, 0x4c, 0x07, 0x0f, 0x7e, - 0x4d, 0xf6, 0xb1, 0x55, 0x7e, 0xbf, 0x46, 0x5a, 0x11, 0x8e, 0x59, 0xa3, 0x46, 0xd9, 0xaa, 0x5e, 0x86, 0xd7, 0x69, - 0x18, 0xbe, 0xff, 0xdf, 0xfb, 0x00, 0x77, 0xa2, 0xa3, 0x0c, 0xee, 0x88, 0x06, 0x74, 0xf9, 0xd0, 0x67, 0xbe, 0xe9, - 0x43, 0xc6, 0xf8, 0xe0, 0x8c, 0x0c, 0xd5, 0xce, 0xd1, 0x00, 0xc1, 0x51, 0xdd, 0xd3, 0x65, 0xc2, 0x59, 0x7c, 0xee, - 0xa1, 0xa3, 0xfa, 0xcc, 0x7d, 0x17, 0x69, 0x2b, 0x68, 0xe3, 0xf8, 0x64, 0x89, 0x6b, 0x2a, 0x00, 0x2e, 0x61, 0x63, - 0x12, 0x86, 0xb8, 0x74, 0x89, 0xd5, 0x37, 0xc7, 0xa8, 0x00, 0x28, 0x9f, 0xd4, 0xcc, 0x97, 0x5e, 0x64, 0x45, 0x9d, - 0x56, 0x8d, 0xee, 0x06, 0x6c, 0xe5, 0x09, 0x02, 0x3c, 0x84, 0xe5, 0x69, 0x6d, 0x16, 0x34, 0x61, 0x03, 0xa9, 0x2c, - 0x50, 0xe7, 0x04, 0xb8, 0xe5, 0x6e, 0x49, 0x36, 0xd2, 0x3b, 0x3c, 0xee, 0x9c, 0x3b, 0xb6, 0xdc, 0x51, 0x0a, 0xb7, - 0x47, 0x6c, 0x42, 0xca, 0xf0, 0xd3, 0xda, 0x9d, 0x3f, 0x8f, 0x9e, 0x30, 0x98, 0x8a, 0x74, 0x63, 0x1c, 0x21, 0x13, - 0x91, 0x1b, 0xbb, 0xe7, 0xf8, 0x49, 0x54, 0xcd, 0xe2, 0xc9, 0xc4, 0x47, 0x7d, 0x68, 0x04, 0xff, 0x4c, 0xd2, 0x73, - 0xb1, 0x5e, 0xc7, 0xdb, 0x3a, 0x10, 0x5a, 0x66, 0x31, 0xa1, 0x85, 0xc6, 0x3e, 0x1a, 0xaf, 0xbb, 0xd7, 0x11, 0x16, - 0x03, 0x34, 0x73, 0xf4, 0x65, 0x40, 0xe9, 0x3d, 0x7d, 0xd1, 0x22, 0xec, 0xa2, 0x51, 0x66, 0x07, 0x85, 0x0c, 0xc2, - 0xc6, 0xbd, 0xb7, 0x20, 0x28, 0x9e, 0x40, 0xdf, 0x50, 0x75, 0xde, 0xea, 0xfd, 0xdc, 0x76, 0xc7, 0xee, 0x5e, 0xb5, - 0x4a, 0x4f, 0x67, 0x6d, 0x86, 0x52, 0xab, 0x5b, 0xa6, 0xf5, 0x3a, 0xcf, 0x12, 0x6e, 0xdc, 0xac, 0x70, 0x2f, 0xb5, - 0xf0, 0x93, 0x2d, 0x0b, 0x53, 0x76, 0xb6, 0x96, 0x16, 0x8e, 0x9c, 0x4b, 0x6e, 0xfd, 0xee, 0xba, 0x62, 0xd9, 0xa9, - 0xf1, 0x2d, 0xc0, 0xbd, 0x33, 0xea, 0xc8, 0x39, 0x0c, 0x2d, 0xad, 0xc7, 0xf4, 0x9c, 0x3f, 0x62, 0x1f, 0x33, 0x7c, - 0x07, 0x83, 0x3a, 0x0a, 0xb1, 0xbf, 0xb6, 0xae, 0x23, 0x11, 0x93, 0x1f, 0xf8, 0xa3, 0xf6, 0xa2, 0x2c, 0x70, 0x33, - 0xbe, 0xdb, 0x90, 0xa7, 0xb1, 0xda, 0x83, 0x71, 0x75, 0x45, 0xc8, 0x9f, 0xda, 0x1c, 0xd3, 0x34, 0xc7, 0x3b, 0x1b, - 0x75, 0xd6, 0xd7, 0x48, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, 0xe5, 0x97, 0x49, 0x13, 0xd8, 0x1f, 0x42, 0x57, 0xda, 0x9d, - 0x5b, 0x9d, 0x3b, 0x13, 0xa3, 0xbe, 0xd2, 0xcc, 0xae, 0xed, 0x24, 0x38, 0x31, 0xb5, 0x7d, 0x60, 0xd3, 0xab, 0x2f, - 0xd4, 0x77, 0xec, 0x14, 0x31, 0xc3, 0xbf, 0x4b, 0x35, 0x45, 0xd9, 0xd7, 0x12, 0xf4, 0x68, 0xd2, 0x86, 0xc4, 0xdd, - 0x51, 0x99, 0x3c, 0x9e, 0x15, 0xdd, 0x1a, 0x7a, 0x43, 0x13, 0x14, 0xe6, 0xdb, 0x3f, 0x14, 0xf5, 0x60, 0x83, 0xbb, - 0x85, 0x8e, 0x83, 0xee, 0xa7, 0xd0, 0xaf, 0xea, 0x37, 0xef, 0x01, 0x70, 0xc6, 0xc2, 0xff, 0x43, 0x2e, 0x34, 0xf5, - 0x93, 0xb4, 0x9e, 0x9c, 0xc2, 0xd8, 0x60, 0xf6, 0xfb, 0xfe, 0x4b, 0x2b, 0x5c, 0xa3, 0x0b, 0x14, 0x19, 0x21, 0xe8, - 0xdc, 0x49, 0xc0, 0x78, 0xbf, 0xc7, 0xb4, 0xf6, 0x4f, 0x7f, 0x54, 0x8b, 0x23, 0x26, 0xb4, 0x8b, 0x78, 0x8c, 0x10, - 0x77, 0x3a, 0x94, 0x75, 0xac, 0x01, 0xfa, 0x30, 0x80, 0x75, 0xec, 0xdb, 0x11, 0xc0, 0x51, 0x1f, 0x6d, 0xde, 0x25, - 0xc8, 0xaf, 0x7b, 0x37, 0xc1, 0x9b, 0x60, 0x0b, 0x7c, 0xf9, 0x75, 0x06, 0x3f, 0x91, 0xce, 0x02, 0x71, 0x9a, 0x9f, - 0x84, 0x06, 0x17, 0x3a, 0x78, 0xf3, 0x30, 0x0d, 0xb6, 0xc1, 0xf6, 0x21, 0x21, 0x15, 0x0d, 0xe7, 0x9f, 0x9c, 0x18, - 0xef, 0x79, 0xa7, 0xc0, 0x55, 0xb4, 0x44, 0xf0, 0x40, 0x60, 0x42, 0x83, 0x6b, 0xf8, 0xf9, 0x43, 0xb0, 0x42, 0x35, - 0xf9, 0x65, 0xb4, 0xf6, 0xbe, 0xe7, 0xd4, 0x0b, 0xfc, 0x39, 0xe6, 0xf4, 0x59, 0x11, 0x79, 0x57, 0x93, 0x4b, 0xff, - 0xd1, 0x63, 0x34, 0x9e, 0xb8, 0x9e, 0x5c, 0xe0, 0xaf, 0x32, 0x9a, 0x78, 0x57, 0x63, 0x4a, 0xac, 0xe0, 0xe7, 0xf5, - 0x18, 0x53, 0x15, 0x2e, 0x24, 0xf9, 0x3e, 0xfc, 0x14, 0x16, 0x01, 0xfd, 0xf8, 0x59, 0x63, 0xb0, 0xfe, 0x04, 0x8c, - 0x8f, 0x42, 0x63, 0xad, 0x94, 0xcb, 0xd2, 0x22, 0x3d, 0x48, 0xf1, 0x4e, 0x78, 0x31, 0x6c, 0x8b, 0x55, 0x6f, 0xd6, - 0x29, 0xff, 0xbc, 0xc7, 0xf6, 0xe8, 0x58, 0x89, 0xca, 0x45, 0x5a, 0xbd, 0xa7, 0xf0, 0xa9, 0x8e, 0x8d, 0x51, 0xb9, - 0x69, 0x86, 0xd3, 0xb9, 0x55, 0x03, 0x69, 0x3f, 0x2b, 0xd3, 0x60, 0xc7, 0xea, 0xa4, 0x77, 0x53, 0x78, 0x30, 0x70, - 0xcf, 0xcb, 0xa7, 0xc4, 0xc0, 0xc5, 0xf8, 0xf0, 0xad, 0x9e, 0xb9, 0x28, 0x2f, 0x0c, 0xc6, 0x74, 0x19, 0x25, 0xd1, - 0x93, 0x71, 0x21, 0xae, 0x31, 0xef, 0x28, 0x1a, 0x86, 0xb2, 0xa1, 0xa5, 0x08, 0x09, 0x49, 0x34, 0x22, 0x25, 0x60, - 0xf7, 0x06, 0x65, 0x56, 0xe2, 0x59, 0x34, 0xfe, 0x19, 0x04, 0x38, 0x8c, 0x7b, 0x90, 0xf8, 0xad, 0x98, 0x94, 0x0b, - 0x36, 0x3a, 0xc7, 0x58, 0x4e, 0xb5, 0xf1, 0xb8, 0xfe, 0x3a, 0x39, 0xf5, 0x7b, 0x15, 0x6c, 0x22, 0xe4, 0xb3, 0xdf, - 0x4b, 0xd4, 0x69, 0x63, 0x89, 0xf1, 0x6f, 0x57, 0xf9, 0xa7, 0xc2, 0x52, 0x4f, 0xfe, 0xf3, 0x98, 0x5d, 0xe9, 0x9f, - 0x67, 0x55, 0xb2, 0xb9, 0x5e, 0xa6, 0x55, 0x5a, 0x24, 0xe9, 0xde, 0x62, 0x89, 0x9d, 0xcb, 0x77, 0x3e, 0x45, 0x76, - 0x01, 0x74, 0xb3, 0xcf, 0x90, 0xd1, 0x3f, 0x82, 0x28, 0x3f, 0xf9, 0x51, 0x1b, 0xd7, 0x16, 0xb0, 0xcd, 0x8a, 0x53, - 0x8b, 0x76, 0x3b, 0x56, 0x24, 0x46, 0x31, 0x56, 0xf8, 0x6a, 0x98, 0x95, 0x11, 0x95, 0x4c, 0x8c, 0x98, 0x26, 0x03, - 0x57, 0x2f, 0x04, 0x69, 0xd0, 0xac, 0x04, 0x3d, 0xaa, 0xd0, 0x7a, 0x2c, 0x52, 0xbe, 0x8f, 0x78, 0x75, 0x3d, 0x20, - 0x8c, 0x0e, 0x94, 0x33, 0x56, 0x9d, 0xc4, 0x2b, 0xb8, 0xc3, 0x48, 0xf7, 0x09, 0x03, 0xe3, 0x34, 0x6b, 0xac, 0x1b, - 0x0e, 0x44, 0xee, 0x4a, 0xcd, 0xcd, 0x06, 0x88, 0x19, 0x30, 0x43, 0x7a, 0x4f, 0x49, 0x5d, 0x88, 0x45, 0x67, 0xd7, - 0x11, 0xa6, 0x93, 0xa6, 0x6d, 0xf7, 0xe8, 0x78, 0x59, 0x70, 0xde, 0x69, 0x15, 0x29, 0x5a, 0x46, 0xa7, 0x03, 0x6b, - 0xd3, 0xe1, 0x6e, 0x8c, 0xf6, 0xf6, 0x99, 0x41, 0x48, 0xf1, 0xfc, 0xb1, 0xad, 0xd6, 0xa5, 0x4d, 0x02, 0x9c, 0xcb, - 0xd8, 0x99, 0xde, 0x7a, 0x1d, 0x27, 0x78, 0x8d, 0x17, 0x9b, 0x4e, 0x18, 0xa7, 0x4c, 0x01, 0x8b, 0xd6, 0xe8, 0xd0, - 0xfe, 0xa4, 0x42, 0xea, 0x71, 0x4c, 0x00, 0x81, 0x2a, 0xd3, 0xb3, 0xb8, 0xb3, 0x60, 0x36, 0x0d, 0x6c, 0x5e, 0xbc, - 0xc6, 0xa3, 0x0b, 0x61, 0x7d, 0x11, 0xf3, 0x1e, 0x3e, 0xf3, 0x2f, 0xaa, 0xc6, 0xb6, 0x04, 0x82, 0x9e, 0x3a, 0x43, - 0x03, 0xec, 0xa4, 0x1a, 0xb5, 0x45, 0x6b, 0x15, 0xee, 0x2e, 0xb9, 0x40, 0x51, 0xac, 0x8d, 0xa2, 0x58, 0x4b, 0x4d, - 0xb1, 0xd6, 0x9a, 0x62, 0x5d, 0xb5, 0x11, 0x1c, 0x03, 0x0b, 0xa0, 0x89, 0x09, 0x92, 0x4d, 0xd5, 0x21, 0xec, 0xc6, - 0x06, 0x68, 0xa7, 0xa7, 0x3a, 0x86, 0x09, 0x4b, 0xa0, 0xa0, 0x7d, 0x0c, 0x7f, 0xc4, 0x32, 0xe2, 0x2e, 0xdf, 0x50, - 0xdc, 0x4d, 0x67, 0x47, 0x11, 0x79, 0x0a, 0x2e, 0xfc, 0xe0, 0x8d, 0x29, 0x79, 0xf3, 0x30, 0xc1, 0xdc, 0x5b, 0xa0, - 0xef, 0x93, 0x37, 0xfe, 0x23, 0xdd, 0x03, 0x59, 0xcc, 0xb2, 0x02, 0x79, 0x20, 0x3e, 0xa2, 0xb7, 0xb2, 0xa7, 0x6c, - 0x27, 0x84, 0xb2, 0xad, 0x1f, 0xde, 0xb8, 0x64, 0xed, 0x0a, 0x12, 0xea, 0x29, 0xfb, 0x8a, 0xf3, 0x12, 0x89, 0xf3, - 0x64, 0x83, 0x71, 0xea, 0xa5, 0xfc, 0x00, 0xc5, 0x9c, 0x6c, 0x1f, 0x0e, 0x0c, 0xbc, 0xac, 0x01, 0x7b, 0xf8, 0x7b, - 0x44, 0xd8, 0xdc, 0xd2, 0x75, 0x2a, 0x85, 0x2a, 0x73, 0x8d, 0xe7, 0xd0, 0xe3, 0x4f, 0x8f, 0x35, 0x36, 0x08, 0xe9, - 0xfa, 0x9c, 0x49, 0x1d, 0xa0, 0xbe, 0xc6, 0xed, 0x72, 0x60, 0x5d, 0xeb, 0x96, 0x77, 0x77, 0x9e, 0xf2, 0x0d, 0x41, - 0x1d, 0xbe, 0x56, 0x37, 0xc8, 0xaf, 0x94, 0x96, 0x08, 0x02, 0x39, 0xf4, 0xb7, 0x3c, 0x8d, 0x7d, 0x96, 0x67, 0xcd, - 0x96, 0xb4, 0x16, 0xb5, 0x75, 0x33, 0xac, 0xad, 0x1f, 0xb4, 0x62, 0x58, 0x34, 0xfd, 0xf3, 0xe3, 0xd0, 0x1d, 0x6c, - 0xb7, 0x31, 0x76, 0x1d, 0x0f, 0xcb, 0x47, 0x3f, 0xee, 0x67, 0xca, 0xb5, 0x99, 0xb7, 0xb1, 0x9b, 0x56, 0x5b, 0x96, - 0xf7, 0x7a, 0x1c, 0x55, 0xd6, 0x8d, 0x08, 0x3a, 0x30, 0xf4, 0x94, 0x5d, 0xc0, 0x88, 0x78, 0x8c, 0xd5, 0x3d, 0x8e, - 0x25, 0xf2, 0x02, 0x2c, 0xca, 0x05, 0x26, 0x22, 0x6c, 0x77, 0xac, 0xa2, 0x2d, 0x40, 0xe2, 0x26, 0x2a, 0x8f, 0x8e, - 0x72, 0x35, 0x28, 0x7c, 0xbb, 0xb3, 0x8c, 0x36, 0xaa, 0x3b, 0xd6, 0x54, 0x03, 0x0f, 0xa2, 0x93, 0xad, 0x79, 0xee, - 0x2a, 0x3e, 0xae, 0xba, 0x8a, 0x8f, 0x6b, 0x6b, 0x5f, 0xba, 0xe2, 0x3d, 0xa9, 0x0b, 0x90, 0xf4, 0x5f, 0xf6, 0x77, - 0x2e, 0x2c, 0x53, 0x06, 0xf8, 0xba, 0x80, 0x63, 0xe1, 0x82, 0xac, 0x4a, 0x2e, 0xfc, 0xcb, 0xb1, 0x9a, 0x7f, 0x67, - 0x70, 0x2f, 0x10, 0xba, 0x92, 0xf3, 0xa6, 0x98, 0x77, 0x5c, 0x50, 0x6e, 0x19, 0xca, 0x9b, 0xbd, 0x65, 0x60, 0x1f, - 0x36, 0x67, 0x17, 0xe7, 0xb0, 0xf9, 0x76, 0xb7, 0xe1, 0x6a, 0x6c, 0x6f, 0xab, 0x60, 0x1b, 0x2e, 0xec, 0x84, 0x9f, - 0x19, 0x98, 0xf2, 0x29, 0x3a, 0x71, 0x85, 0x97, 0xe8, 0x87, 0x27, 0x3f, 0xc7, 0x37, 0x1d, 0x62, 0x7d, 0x13, 0x58, - 0x83, 0x03, 0xb4, 0xc5, 0x1a, 0xc1, 0x70, 0xd9, 0xce, 0xae, 0x8f, 0x8e, 0xbc, 0xad, 0x36, 0x7c, 0xba, 0x12, 0x9d, - 0xd8, 0x7e, 0xad, 0xd6, 0x45, 0xf0, 0x46, 0xb4, 0x2e, 0xe6, 0xa2, 0x07, 0x03, 0x3f, 0xc1, 0x50, 0xdc, 0x0c, 0xec, - 0x2d, 0x60, 0x02, 0x2f, 0x80, 0x05, 0xac, 0x09, 0x82, 0xc0, 0xdd, 0xf6, 0x7b, 0x95, 0x0b, 0xda, 0xb0, 0x4b, 0xf0, - 0x70, 0x8e, 0x83, 0x5a, 0x5d, 0xb3, 0xce, 0xea, 0xd3, 0x74, 0xd0, 0xa7, 0xb3, 0xd1, 0xeb, 0xb9, 0x3e, 0x9f, 0x95, - 0x1a, 0xd4, 0xef, 0x90, 0xe3, 0x11, 0x95, 0x83, 0x27, 0xb0, 0xb5, 0xad, 0xd0, 0x57, 0xfb, 0x10, 0x6f, 0x6b, 0xb5, - 0x49, 0xbf, 0x57, 0x8c, 0x23, 0x3b, 0xe4, 0xb0, 0x76, 0x0c, 0x6a, 0xf7, 0xec, 0xa8, 0xfb, 0xee, 0x8e, 0x89, 0xf8, - 0xe9, 0xed, 0x8f, 0x46, 0x58, 0xd2, 0xb0, 0xc6, 0x9f, 0xff, 0xf8, 0xd0, 0xd3, 0xdf, 0x81, 0x6d, 0x91, 0xfa, 0xe1, - 0xf1, 0x1f, 0xbd, 0xf7, 0xb5, 0x36, 0xa3, 0xba, 0xab, 0x9c, 0xd2, 0xe5, 0x6e, 0x2d, 0x57, 0x96, 0x1f, 0x53, 0x2f, - 0xb5, 0x36, 0x3c, 0x1c, 0x88, 0x6a, 0x8b, 0xe6, 0x25, 0xee, 0xb0, 0xce, 0x95, 0x70, 0x4d, 0xbe, 0x5a, 0xfa, 0xd6, - 0xb7, 0x6c, 0xdb, 0xfe, 0xe1, 0xdc, 0x18, 0x94, 0x29, 0x87, 0x32, 0x52, 0x33, 0xdc, 0x08, 0x4b, 0x33, 0xf6, 0x90, - 0xdd, 0xd9, 0xce, 0x8d, 0x83, 0xbc, 0x94, 0xba, 0x38, 0x27, 0x67, 0xc2, 0x1e, 0x1b, 0x05, 0xab, 0x6c, 0x57, 0xb1, - 0xe7, 0xb4, 0xcd, 0x07, 0xd5, 0x04, 0xfb, 0xc8, 0xac, 0x04, 0x91, 0x22, 0xcd, 0x14, 0xa9, 0x1b, 0x7f, 0xdb, 0x41, - 0x17, 0xe3, 0x02, 0xea, 0x66, 0x34, 0xdd, 0x0f, 0x83, 0x0c, 0x75, 0xcf, 0xd2, 0xc7, 0x88, 0x58, 0x02, 0xd4, 0xf6, - 0x34, 0xcf, 0xae, 0x50, 0x85, 0x3f, 0xa2, 0xdd, 0xc4, 0xd1, 0xcf, 0x2d, 0x2e, 0x2a, 0xb1, 0x91, 0xde, 0xe8, 0x36, - 0x78, 0x4a, 0xb7, 0x29, 0xcf, 0x9c, 0x54, 0x3b, 0xe8, 0xbc, 0xc3, 0xe4, 0x58, 0x63, 0x6b, 0x31, 0xa3, 0x43, 0xde, - 0x8b, 0x3b, 0x47, 0xef, 0xb9, 0xbf, 0xe9, 0x85, 0x3f, 0x73, 0xd9, 0x3c, 0x21, 0x23, 0xd8, 0xb6, 0x92, 0xdb, 0xf6, - 0x56, 0x25, 0x58, 0xb0, 0xa4, 0xc3, 0xc7, 0xef, 0x60, 0xeb, 0x90, 0x55, 0xa6, 0x26, 0x7d, 0x89, 0x13, 0xf6, 0xd2, - 0xf1, 0x20, 0x53, 0x55, 0xd8, 0xc3, 0xd1, 0x65, 0xb8, 0xfa, 0x51, 0x8a, 0x9e, 0xda, 0x2c, 0x77, 0xc7, 0xbe, 0xfb, - 0x5c, 0x05, 0x67, 0x3f, 0x41, 0x04, 0xa7, 0xf6, 0x0b, 0xec, 0x4b, 0x0f, 0x8f, 0x6a, 0x98, 0xe1, 0xd8, 0x2f, 0x03, - 0xc0, 0x91, 0x7c, 0x82, 0x9a, 0x80, 0x45, 0x1a, 0x8c, 0xb2, 0xc5, 0x08, 0x44, 0xfb, 0x72, 0x73, 0xb5, 0x2a, 0x36, - 0x68, 0xcc, 0xc0, 0xa9, 0x96, 0x7e, 0xa0, 0xaf, 0x16, 0x50, 0xee, 0x60, 0x76, 0xd2, 0x28, 0xae, 0x92, 0x51, 0xa0, - 0xcf, 0xcf, 0x70, 0xe7, 0x30, 0x09, 0x88, 0xfb, 0x65, 0x1f, 0x90, 0x88, 0x87, 0x1e, 0xd8, 0x0e, 0xe1, 0x8c, 0x59, - 0x04, 0x3f, 0xd8, 0x41, 0x8c, 0x1f, 0x47, 0x81, 0xf1, 0xe4, 0x0f, 0xcf, 0x46, 0xce, 0x29, 0x01, 0x8d, 0x56, 0x47, - 0x08, 0xfc, 0xb4, 0x8e, 0x08, 0x78, 0xb2, 0x8e, 0x0f, 0x78, 0x32, 0xc7, 0xce, 0x08, 0x1d, 0x13, 0xd0, 0xf3, 0x00, - 0xb2, 0xd0, 0x38, 0x8d, 0x54, 0xec, 0x01, 0x0e, 0x83, 0x00, 0x79, 0x99, 0x39, 0x1f, 0x21, 0xf2, 0x18, 0xb3, 0xd5, - 0xe1, 0xe8, 0x2f, 0xc7, 0xff, 0x31, 0x32, 0x3c, 0xf2, 0x71, 0xe7, 0xb0, 0xfa, 0xd3, 0x5f, 0xd1, 0x01, 0x8e, 0xce, - 0xa6, 0xd1, 0xc9, 0x31, 0x66, 0x95, 0x3a, 0x42, 0x89, 0x4f, 0x8c, 0xb6, 0x7c, 0x21, 0x86, 0xea, 0x33, 0x43, 0xab, - 0x83, 0xa3, 0xc2, 0xe8, 0xda, 0xe1, 0x8a, 0x11, 0x60, 0x1b, 0xb7, 0xa8, 0x6a, 0x85, 0x1d, 0xb0, 0xb8, 0xfb, 0x8e, - 0xbc, 0xb9, 0xec, 0xf0, 0x82, 0x06, 0xea, 0x11, 0x9d, 0x5f, 0x3a, 0x2f, 0xad, 0xbd, 0xcc, 0x39, 0x74, 0x6b, 0x54, - 0xa8, 0x6c, 0x6c, 0x4b, 0x5c, 0xaf, 0xd3, 0xa4, 0xe1, 0x10, 0x29, 0x27, 0x01, 0x7b, 0xb1, 0xc0, 0x94, 0xe4, 0xe9, - 0x15, 0x7a, 0xcd, 0x33, 0xa9, 0x85, 0xe7, 0x2b, 0x44, 0x58, 0x83, 0x99, 0x14, 0x63, 0x50, 0x9b, 0xd2, 0x4f, 0x95, - 0xbd, 0x7c, 0x2a, 0xe4, 0xdc, 0x42, 0x11, 0xee, 0xae, 0x41, 0x91, 0xd4, 0x55, 0xad, 0x84, 0x46, 0xcb, 0xa0, 0x94, - 0x05, 0x43, 0x64, 0x21, 0x02, 0x38, 0x11, 0x10, 0xfc, 0xbc, 0xc6, 0x27, 0xd0, 0x28, 0x04, 0xf2, 0x81, 0xeb, 0x78, - 0xed, 0x51, 0x58, 0x6a, 0x8d, 0x88, 0x92, 0x44, 0x3d, 0xd1, 0xf3, 0xd8, 0x16, 0x3d, 0xcd, 0x6d, 0x4b, 0x65, 0x9c, - 0xf8, 0x39, 0x8a, 0x2d, 0xfa, 0x04, 0x71, 0x1b, 0x92, 0x1e, 0x2c, 0x27, 0xba, 0x28, 0xfc, 0x96, 0xea, 0xb7, 0x06, - 0xfe, 0x32, 0x58, 0x42, 0xd5, 0x0c, 0x8b, 0x59, 0x07, 0x88, 0x56, 0xc5, 0xe0, 0x99, 0x0e, 0x49, 0x0d, 0x9c, 0xee, - 0xf1, 0x91, 0x1d, 0x1e, 0x0e, 0x1d, 0xec, 0x95, 0x2f, 0xbe, 0x93, 0x55, 0xdb, 0x2a, 0xc2, 0x46, 0x48, 0x78, 0x65, - 0xf1, 0x3c, 0xcf, 0x8c, 0x71, 0x64, 0x21, 0xfb, 0xbb, 0x29, 0xaf, 0xae, 0x98, 0x4c, 0x58, 0x95, 0xa4, 0x4a, 0xda, - 0x50, 0xb9, 0x14, 0x66, 0x63, 0x0b, 0xff, 0xf9, 0xe2, 0xd5, 0x57, 0x67, 0xb6, 0x52, 0xc9, 0x71, 0xef, 0xfa, 0xa2, - 0x16, 0x69, 0xc8, 0x83, 0x0d, 0xe8, 0x3d, 0xea, 0xa1, 0x5c, 0xaf, 0xb1, 0x2f, 0x1b, 0x56, 0x69, 0x0a, 0x03, 0x03, - 0xc3, 0x56, 0xe4, 0x68, 0xa2, 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, 0xbd, 0x17, 0x9f, 0x16, 0x96, 0x7b, 0x2c, 0x80, - 0xd9, 0x49, 0x1b, 0xc5, 0x09, 0x01, 0x11, 0x57, 0xea, 0x7e, 0xc5, 0xf8, 0xef, 0x29, 0x98, 0x25, 0xe3, 0xba, 0x97, - 0x04, 0x49, 0x42, 0x77, 0x7c, 0x12, 0x24, 0x53, 0x2f, 0x53, 0x34, 0x23, 0x17, 0x37, 0x47, 0xc3, 0xb4, 0x14, 0x53, - 0x07, 0xd2, 0xd7, 0x32, 0x2a, 0xa1, 0x57, 0x3c, 0x28, 0x68, 0x78, 0x7e, 0x58, 0x5a, 0x8f, 0xf0, 0x8e, 0x31, 0x97, - 0xf5, 0xf5, 0x5f, 0xde, 0x3b, 0x06, 0x87, 0x2c, 0x4d, 0x1c, 0x53, 0xff, 0x69, 0xbd, 0x2a, 0x3f, 0x7d, 0x07, 0xab, - 0xec, 0xee, 0xce, 0xcb, 0xed, 0x25, 0x16, 0x81, 0xa8, 0x98, 0x2b, 0xe0, 0x6f, 0xd7, 0x5a, 0x4b, 0x12, 0x87, 0xb8, - 0xdd, 0x42, 0x5d, 0x7e, 0x29, 0x82, 0xbd, 0x08, 0x0f, 0x0d, 0x40, 0x71, 0xde, 0x6a, 0xb7, 0xbc, 0x8e, 0xb4, 0x55, - 0x93, 0x02, 0xb5, 0xf9, 0x63, 0x52, 0x98, 0xb2, 0x36, 0xaf, 0x94, 0xb5, 0x79, 0x6c, 0x1c, 0x04, 0x12, 0x33, 0xe5, - 0x79, 0x3b, 0xb0, 0x48, 0x5c, 0x19, 0x69, 0xd5, 0x95, 0x91, 0x16, 0xf7, 0xca, 0x48, 0x14, 0x6f, 0x89, 0x0c, 0xd9, - 0x97, 0x11, 0x1b, 0x81, 0x06, 0x06, 0x7b, 0x79, 0x1d, 0xc8, 0xf8, 0xa0, 0xf6, 0xc2, 0x11, 0x96, 0xaf, 0xa3, 0x37, - 0xa9, 0xb7, 0xf6, 0xe7, 0xeb, 0xfd, 0xa6, 0xaa, 0x97, 0x5f, 0x58, 0x99, 0x77, 0x77, 0x25, 0x88, 0xba, 0xc6, 0x69, - 0x17, 0x04, 0xac, 0x31, 0x8c, 0xb9, 0xeb, 0x1f, 0xff, 0x26, 0x22, 0x16, 0x5b, 0x29, 0x8f, 0xc4, 0x84, 0x2a, 0x9d, - 0x9c, 0x18, 0x78, 0x98, 0x2d, 0x30, 0x2c, 0xdb, 0xd3, 0x1b, 0x60, 0x58, 0xb6, 0x6a, 0x6c, 0x61, 0xd9, 0x9d, 0x6d, - 0xcf, 0x83, 0x4f, 0xd1, 0xe5, 0xfc, 0x36, 0xdc, 0xb5, 0x48, 0x76, 0xb7, 0xa7, 0xb0, 0x2c, 0xb6, 0x4f, 0x22, 0x10, - 0xdd, 0x3e, 0x11, 0xa0, 0x33, 0xec, 0xca, 0x2e, 0xc6, 0xcf, 0x87, 0xae, 0xa9, 0xd6, 0x16, 0xe1, 0xe9, 0xbf, 0xf5, - 0x3e, 0x9c, 0x2d, 0xcf, 0xfd, 0xe0, 0x41, 0xf4, 0x09, 0xed, 0xf3, 0x89, 0x48, 0x52, 0xe8, 0x13, 0x6d, 0x32, 0xf9, - 0x01, 0x0d, 0xc8, 0x21, 0xef, 0x0b, 0xc8, 0xb1, 0x3c, 0x8f, 0xa0, 0x5b, 0x6f, 0xe7, 0x31, 0x05, 0x6b, 0x82, 0x49, - 0xa3, 0xac, 0x9e, 0x1f, 0xc6, 0xfd, 0x72, 0x09, 0x5f, 0x44, 0x5a, 0xe6, 0xdd, 0x71, 0xf0, 0x21, 0x48, 0xfc, 0x10, - 0x3f, 0x08, 0x15, 0xce, 0xa4, 0xa5, 0x2c, 0x5f, 0x3c, 0x00, 0xde, 0x84, 0x7f, 0xbd, 0x80, 0x5f, 0x6f, 0x03, 0x78, - 0x89, 0x2e, 0xfd, 0x5b, 0x1c, 0x1f, 0x2d, 0x75, 0x60, 0x53, 0x26, 0x6f, 0xe0, 0x1f, 0xff, 0xc9, 0x75, 0x70, 0x85, - 0xb1, 0x50, 0x94, 0x15, 0xda, 0x07, 0x28, 0x80, 0x56, 0x67, 0x6c, 0x44, 0x04, 0xc3, 0xe3, 0x07, 0x0b, 0x7a, 0xaf, - 0xe4, 0xc5, 0xd5, 0x17, 0xe5, 0xc5, 0x6d, 0x70, 0x3b, 0x2c, 0x2f, 0x4a, 0x49, 0x77, 0xff, 0xdc, 0x82, 0xac, 0xf8, - 0x09, 0x57, 0xd8, 0x9b, 0xe8, 0x43, 0xdb, 0x37, 0x8c, 0xfd, 0xa2, 0xc4, 0x88, 0xa0, 0xcc, 0x16, 0x2c, 0x16, 0x1e, - 0x94, 0x6a, 0xd7, 0x76, 0x38, 0xf2, 0x5a, 0x3b, 0xaa, 0x9d, 0x31, 0xdc, 0x57, 0x07, 0x39, 0xf3, 0xc0, 0x40, 0xdf, - 0xd6, 0x84, 0x16, 0x8e, 0x04, 0xf8, 0x0b, 0x7d, 0x3d, 0x26, 0x37, 0xcd, 0xfa, 0x4c, 0xdf, 0x45, 0x9d, 0x7c, 0x5d, - 0x39, 0x93, 0xdf, 0xf0, 0xc0, 0x16, 0x22, 0x29, 0x1e, 0xc7, 0x8f, 0x1e, 0xef, 0xb1, 0x5f, 0xb5, 0x2c, 0x6a, 0xb5, - 0x5d, 0x28, 0x8f, 0xe9, 0x73, 0x3e, 0xa2, 0x39, 0xf6, 0xa2, 0xcd, 0xc3, 0x1a, 0x65, 0x4d, 0x23, 0x06, 0xc3, 0xb4, - 0x87, 0x7d, 0x39, 0x70, 0xf8, 0x3b, 0xc8, 0xd0, 0xd6, 0x99, 0x30, 0xb4, 0x78, 0x0c, 0x13, 0x33, 0x8b, 0x29, 0xf7, - 0x33, 0xb3, 0x9c, 0xb7, 0xcf, 0xd0, 0x12, 0xa9, 0x06, 0x76, 0x4e, 0xc8, 0x2d, 0xb2, 0xb0, 0x9a, 0x64, 0x00, 0xfb, - 0xaa, 0x2a, 0xb7, 0x19, 0x28, 0xf6, 0xa0, 0x0c, 0x77, 0xcc, 0xb7, 0x5d, 0x28, 0x6e, 0x36, 0x81, 0xbe, 0x5d, 0x95, - 0xd5, 0x76, 0xd4, 0x06, 0x17, 0x24, 0xa0, 0xea, 0x37, 0x8c, 0x6d, 0x39, 0xb2, 0x0e, 0xe5, 0x32, 0xfb, 0x43, 0x37, - 0x3d, 0x5f, 0x7f, 0x9b, 0xf3, 0xbf, 0x2d, 0xa2, 0x4f, 0xab, 0x3f, 0x2e, 0xa4, 0xef, 0x75, 0x96, 0x91, 0x25, 0xf5, - 0x0a, 0x78, 0x28, 0x18, 0x4a, 0x5a, 0x0a, 0xbe, 0x7e, 0xfb, 0x15, 0x3c, 0x05, 0xf3, 0xa1, 0x9c, 0xaa, 0x8c, 0xec, - 0x71, 0x2c, 0xbc, 0xe1, 0xc3, 0x2c, 0x0d, 0x10, 0x84, 0xd7, 0x68, 0x53, 0x8d, 0x9b, 0xc4, 0xbd, 0x3b, 0xf8, 0xbf, - 0xe1, 0xc4, 0xa0, 0x6d, 0xa2, 0x78, 0x60, 0xbb, 0x48, 0xd7, 0x5d, 0xe3, 0x20, 0xa1, 0xd4, 0xb5, 0x3f, 0xad, 0x66, - 0x7f, 0x44, 0x43, 0xe4, 0x95, 0xa7, 0x84, 0x95, 0x85, 0x42, 0x2c, 0xb9, 0x8a, 0x94, 0x68, 0x1a, 0x42, 0x48, 0x59, - 0x9c, 0x14, 0xdf, 0x46, 0xa8, 0x2a, 0x42, 0x30, 0xae, 0xce, 0x40, 0xed, 0x71, 0x1f, 0xb7, 0xf6, 0x22, 0x3a, 0x2b, - 0x1a, 0xb5, 0xb2, 0x56, 0xe0, 0xa7, 0xac, 0x2f, 0x9d, 0xa4, 0x1c, 0xe9, 0x31, 0x15, 0x55, 0x29, 0x3c, 0x63, 0x98, - 0x43, 0x15, 0x6f, 0x0c, 0x09, 0x45, 0xcd, 0x7a, 0xfe, 0xca, 0xa4, 0x14, 0x72, 0x99, 0xf1, 0x2e, 0xad, 0x12, 0x98, - 0x99, 0xf8, 0x2a, 0x9d, 0x97, 0x14, 0x6f, 0xb4, 0xff, 0x02, 0x24, 0x94, 0x63, 0x34, 0x0a, 0xf1, 0x4a, 0xbc, 0x4b, - 0xa0, 0x01, 0x70, 0x45, 0x66, 0xe2, 0xeb, 0xb4, 0xae, 0xdf, 0xda, 0x0f, 0xe5, 0x24, 0x7e, 0x68, 0x31, 0x6c, 0xbd, - 0x7d, 0xd4, 0xd3, 0xc3, 0xc7, 0xff, 0x75, 0x55, 0x73, 0x32, 0xa8, 0x5c, 0xce, 0xfb, 0x0b, 0x96, 0x3d, 0x66, 0xc8, - 0xfc, 0xf5, 0xf6, 0x79, 0x8a, 0xe1, 0x76, 0x83, 0x05, 0xfc, 0xde, 0xca, 0x6f, 0x31, 0x63, 0x25, 0x6e, 0x93, 0x64, - 0x59, 0x20, 0xdd, 0x93, 0xe9, 0x5f, 0x1e, 0x7e, 0x3f, 0x63, 0x54, 0x9d, 0x4d, 0xb0, 0xd6, 0x7e, 0x2e, 0x20, 0x92, - 0xf2, 0x2d, 0x08, 0x31, 0xc2, 0x32, 0x28, 0xc6, 0x2b, 0x98, 0x58, 0x8a, 0x35, 0xb0, 0x13, 0x6b, 0xd2, 0x09, 0xaf, - 0xfd, 0xa5, 0xd6, 0x09, 0x73, 0x44, 0x56, 0xae, 0x1f, 0xb8, 0xa2, 0xe0, 0x4a, 0x65, 0x4e, 0x31, 0xf3, 0xb8, 0x98, - 0xad, 0x8d, 0x06, 0xf3, 0x1a, 0xb8, 0x8f, 0xf5, 0xb9, 0x28, 0x9f, 0xf1, 0x2a, 0x67, 0x39, 0xde, 0x5b, 0x0b, 0xf0, - 0x3b, 0xd5, 0xc0, 0x0a, 0x05, 0xce, 0x8a, 0x7a, 0x05, 0xbc, 0x52, 0x83, 0xf0, 0x80, 0xe8, 0x03, 0xc3, 0xfd, 0xd5, - 0xcc, 0x43, 0x67, 0x03, 0xac, 0x61, 0x03, 0xf8, 0xe1, 0xf1, 0x6c, 0x19, 0x5d, 0x50, 0xfc, 0xe5, 0xc4, 0x51, 0xbb, - 0x43, 0xc2, 0x0d, 0x72, 0xc1, 0x89, 0x7b, 0x43, 0x41, 0x81, 0x80, 0x2e, 0xa2, 0x8d, 0xaf, 0x6c, 0x30, 0xde, 0x90, - 0xb6, 0x1a, 0x15, 0xd4, 0x8e, 0x6e, 0xf9, 0xd8, 0xd1, 0x3b, 0xdf, 0xec, 0xd1, 0x57, 0x5f, 0x68, 0xe6, 0xf8, 0x0b, - 0x67, 0xe4, 0x3a, 0xb8, 0x1e, 0xe0, 0x23, 0xda, 0xd9, 0x00, 0x13, 0x71, 0x1d, 0xac, 0x83, 0x37, 0xac, 0x72, 0x1e, - 0x9c, 0xb2, 0xfd, 0x47, 0xa8, 0xd2, 0x6b, 0xdd, 0x4f, 0x4e, 0x94, 0xee, 0xb6, 0x4f, 0x4d, 0xbe, 0x86, 0x88, 0xa4, - 0xe3, 0x31, 0x13, 0x08, 0x67, 0x66, 0x9d, 0x40, 0x2a, 0x03, 0x20, 0x04, 0xce, 0x15, 0xd0, 0xfc, 0xdf, 0x5f, 0xe2, - 0x28, 0xf0, 0x48, 0x9b, 0x52, 0xd4, 0xb2, 0xbb, 0xbb, 0x02, 0x35, 0xca, 0x70, 0x9a, 0x97, 0xea, 0x34, 0xc7, 0xc8, - 0xd3, 0x15, 0xd2, 0x1c, 0x3a, 0xd2, 0xcb, 0xfe, 0x91, 0xfe, 0xdf, 0xd1, 0x44, 0x1d, 0xff, 0x71, 0x4d, 0x94, 0xd2, - 0x22, 0x39, 0xaa, 0xa5, 0xaf, 0x52, 0x47, 0xa1, 0x20, 0xef, 0xa8, 0x85, 0xec, 0x55, 0x76, 0xdc, 0xaa, 0xee, 0xfd, - 0xff, 0x5a, 0x99, 0xff, 0xaf, 0x69, 0x65, 0x02, 0xc5, 0x3b, 0x56, 0x6a, 0xe5, 0xa1, 0x56, 0x31, 0xce, 0xbf, 0x63, - 0x0e, 0x31, 0xa0, 0xad, 0x81, 0x0f, 0x90, 0x65, 0x91, 0xd5, 0xeb, 0x3c, 0xde, 0x92, 0x12, 0xf5, 0x32, 0x85, 0xe5, - 0xf0, 0xb4, 0xf9, 0x77, 0x5a, 0x95, 0xb8, 0xb4, 0xaf, 0x60, 0xd5, 0x84, 0x7c, 0xc3, 0x0f, 0x5b, 0x86, 0x16, 0x37, - 0xf5, 0xf1, 0x3b, 0x99, 0x4f, 0xbb, 0xa8, 0xb3, 0xf2, 0x90, 0x03, 0x35, 0xd0, 0x85, 0x6c, 0x5c, 0x56, 0x95, 0x9f, - 0x08, 0xba, 0xf9, 0xdb, 0xaa, 0x82, 0x53, 0x60, 0xf4, 0x11, 0x76, 0xf0, 0xc1, 0x75, 0xda, 0xac, 0xca, 0x85, 0x82, - 0xb2, 0xc9, 0x10, 0x46, 0x1f, 0x77, 0x1e, 0x08, 0xf0, 0x07, 0x04, 0xd4, 0x00, 0x94, 0x20, 0x46, 0xa0, 0x61, 0x85, - 0xb0, 0x7f, 0x80, 0x3d, 0x3c, 0x88, 0x17, 0xf1, 0x1a, 0x61, 0x72, 0xa0, 0x18, 0x6c, 0xa4, 0x1b, 0x58, 0xd9, 0x8b, - 0xe9, 0x48, 0x85, 0x64, 0x79, 0x59, 0xb8, 0x7c, 0xae, 0xbf, 0xfb, 0x8d, 0x1d, 0xd8, 0x0d, 0x98, 0x6d, 0x07, 0xec, - 0x00, 0x21, 0x41, 0x31, 0xd8, 0x42, 0x93, 0x25, 0x07, 0x6a, 0xab, 0x60, 0x39, 0xd7, 0x02, 0xfc, 0x65, 0x81, 0x58, - 0xc6, 0x4d, 0x29, 0x0e, 0x23, 0x04, 0x60, 0x84, 0x06, 0x4a, 0x18, 0xa1, 0x33, 0x26, 0xb2, 0x2a, 0xab, 0x16, 0xbb, - 0x2b, 0x66, 0x4b, 0x6e, 0x1a, 0xe7, 0xec, 0x24, 0x22, 0xe8, 0xab, 0x9b, 0xb2, 0xc8, 0x96, 0xcb, 0x4e, 0x12, 0x8d, - 0xed, 0xdb, 0x6e, 0x2a, 0xec, 0x98, 0x5e, 0x1a, 0xc5, 0x15, 0x78, 0x9a, 0x47, 0x14, 0x24, 0x2a, 0x0d, 0x5f, 0x16, - 0xad, 0x99, 0x87, 0x6f, 0xbb, 0x21, 0xa7, 0x76, 0x66, 0xbf, 0x20, 0x9c, 0x27, 0x6a, 0xcb, 0x10, 0x63, 0x81, 0x9c, - 0x73, 0xd1, 0x97, 0x3c, 0x23, 0xf0, 0x4b, 0xc7, 0x53, 0x98, 0xa8, 0x1c, 0xb9, 0x79, 0xb0, 0xf7, 0x2e, 0xab, 0x3f, - 0xe0, 0xf7, 0x21, 0x81, 0xf9, 0x1c, 0x1d, 0x55, 0x08, 0x2a, 0xeb, 0x3a, 0x89, 0xe1, 0xad, 0xd2, 0x85, 0xe0, 0x12, - 0x92, 0x30, 0x5f, 0xcf, 0xd3, 0x24, 0x7c, 0xdb, 0xcc, 0x18, 0xe1, 0x84, 0xfc, 0x43, 0x5c, 0x07, 0x01, 0x83, 0x55, - 0x5c, 0x92, 0x93, 0x7c, 0x24, 0xe8, 0xfe, 0x74, 0xbe, 0x93, 0x83, 0x2b, 0x7c, 0x4d, 0xf5, 0x6b, 0x84, 0xf7, 0xe5, - 0x2a, 0x5d, 0x22, 0x42, 0x58, 0xfe, 0x7f, 0x09, 0x5b, 0xdf, 0x4e, 0x56, 0xa8, 0xb6, 0x91, 0x87, 0xf1, 0xca, 0x08, - 0x13, 0x65, 0xb8, 0x00, 0x01, 0x03, 0xb6, 0x6b, 0xb8, 0x99, 0xae, 0x32, 0xd4, 0x68, 0x92, 0x0f, 0x99, 0x72, 0xed, - 0x90, 0x30, 0x9a, 0xad, 0xc9, 0x7e, 0x8c, 0x79, 0x4d, 0x2c, 0x16, 0x0b, 0xbc, 0xef, 0xbb, 0x54, 0x0d, 0xb0, 0xcd, - 0xcd, 0x11, 0xe0, 0x24, 0xc3, 0x9e, 0xba, 0x2c, 0x25, 0x63, 0x36, 0xfa, 0xec, 0x72, 0x6e, 0x40, 0xc7, 0x59, 0x63, - 0xa8, 0x3e, 0x30, 0x8b, 0x4f, 0x13, 0x32, 0x52, 0x56, 0x08, 0x0b, 0x44, 0x37, 0x72, 0x9e, 0xad, 0x55, 0x4b, 0xc0, - 0xdb, 0x01, 0xf5, 0x82, 0xba, 0xd0, 0x46, 0x30, 0xcb, 0x94, 0xd6, 0x04, 0x15, 0x5e, 0xe7, 0x1b, 0xa8, 0xc4, 0xc5, - 0x6c, 0x79, 0x1a, 0x6d, 0x5c, 0xac, 0xc4, 0xd5, 0xd9, 0xf2, 0x7c, 0xb6, 0x96, 0x50, 0x73, 0x05, 0x30, 0x19, 0x79, - 0xb0, 0x44, 0xfa, 0x61, 0x60, 0x28, 0x1d, 0xd8, 0xd1, 0x4c, 0x87, 0x4d, 0x42, 0x4c, 0x26, 0x98, 0xf2, 0xc9, 0x09, - 0xa1, 0xc9, 0xea, 0xd4, 0xad, 0xa4, 0x2a, 0x0a, 0xae, 0x83, 0x33, 0x39, 0x23, 0xd2, 0xcc, 0xb5, 0xee, 0xa5, 0x98, - 0xde, 0x4e, 0xea, 0xe9, 0x2d, 0x1c, 0xd1, 0x38, 0x0c, 0x76, 0xfa, 0x16, 0xd2, 0xb7, 0xbe, 0x86, 0xdd, 0x65, 0x85, - 0x40, 0xfd, 0x7b, 0xd5, 0xf0, 0x75, 0xf1, 0xba, 0xfc, 0x04, 0x53, 0xf3, 0xd8, 0x1f, 0xeb, 0xa7, 0x0a, 0x9e, 0xec, - 0x48, 0xae, 0xbf, 0x67, 0x43, 0xb3, 0x71, 0xa6, 0xfd, 0xb5, 0x6b, 0xbc, 0x85, 0x46, 0xc8, 0x2f, 0xa4, 0x68, 0xaf, - 0x0b, 0x64, 0x08, 0xc8, 0xbc, 0x84, 0x66, 0x31, 0x45, 0xaf, 0x69, 0xd5, 0x78, 0x32, 0xba, 0xf7, 0x77, 0x54, 0x22, - 0x46, 0x6c, 0xf2, 0xcc, 0x92, 0x5b, 0x8e, 0xa1, 0x08, 0xba, 0xd0, 0xcb, 0xf2, 0x9b, 0x82, 0x08, 0x30, 0xdd, 0x06, - 0x85, 0x6f, 0x22, 0xea, 0x29, 0x18, 0xc3, 0xd8, 0x85, 0x55, 0x4c, 0xe4, 0x0c, 0xc8, 0xe1, 0x08, 0x20, 0x74, 0x01, - 0x2b, 0xbc, 0xde, 0x8b, 0x5e, 0x18, 0x44, 0x44, 0xa5, 0xd7, 0x41, 0x63, 0x29, 0x9e, 0xab, 0x42, 0xf4, 0xde, 0x59, - 0x94, 0x37, 0x37, 0x9c, 0x25, 0xac, 0x0d, 0x56, 0xbb, 0x01, 0xab, 0x51, 0x7b, 0x67, 0x7b, 0xb8, 0x8b, 0x73, 0x72, - 0x95, 0xa1, 0xe3, 0x00, 0x95, 0x9e, 0xff, 0x8c, 0xa1, 0x6a, 0x8a, 0x34, 0xcb, 0x61, 0x66, 0xb7, 0x40, 0xc7, 0xaf, - 0x33, 0x6f, 0x41, 0x88, 0xd9, 0x18, 0x2d, 0xc4, 0xed, 0x51, 0xe5, 0xf6, 0x28, 0x96, 0x1e, 0x25, 0xfa, 0x50, 0x3b, - 0xd0, 0x83, 0x09, 0xa2, 0x62, 0x6d, 0xfa, 0xf7, 0x31, 0x37, 0x73, 0x83, 0x61, 0xbb, 0x18, 0xdf, 0x40, 0x3b, 0x2a, - 0xc4, 0xd1, 0x6b, 0x42, 0x44, 0x62, 0x60, 0x97, 0x7d, 0x32, 0xb1, 0x19, 0x90, 0xdc, 0x23, 0xcc, 0x0a, 0x35, 0xcb, - 0xcb, 0x68, 0xd5, 0x9b, 0x90, 0x9a, 0x51, 0xb7, 0x61, 0x06, 0x97, 0x2e, 0xa8, 0xfd, 0x9a, 0x7d, 0xc7, 0x58, 0x52, - 0xa0, 0xb5, 0xe0, 0x71, 0xde, 0x43, 0xef, 0x10, 0xd1, 0x1c, 0xbb, 0x4b, 0x64, 0x8d, 0x38, 0xbd, 0xdd, 0x4a, 0x30, - 0xda, 0x67, 0x13, 0xac, 0x61, 0xb0, 0x4e, 0x93, 0xb9, 0x07, 0x3d, 0xd1, 0x43, 0xb4, 0x72, 0x87, 0x68, 0x21, 0x43, - 0xb4, 0x69, 0xd1, 0xd9, 0xf1, 0xda, 0x0f, 0x31, 0x6e, 0x68, 0x02, 0x64, 0xb3, 0x33, 0xb2, 0x7b, 0x8b, 0xf5, 0x47, - 0x36, 0x07, 0x0a, 0x62, 0x46, 0xf6, 0xa7, 0xcc, 0x1d, 0x59, 0x59, 0xec, 0xe5, 0xe0, 0x62, 0x9f, 0x9f, 0x9d, 0x87, - 0x69, 0x24, 0x94, 0xfb, 0xb0, 0x98, 0xeb, 0x65, 0x57, 0xfb, 0x61, 0x67, 0x8a, 0x2c, 0x2a, 0x57, 0x0f, 0xef, 0x2b, - 0xdc, 0xc0, 0x02, 0xee, 0x06, 0x2c, 0xeb, 0x4f, 0x34, 0xfc, 0xa3, 0x10, 0x7e, 0xfe, 0xcc, 0x3f, 0xd9, 0x81, 0x03, - 0xd1, 0x98, 0xba, 0x3d, 0xf0, 0x08, 0x43, 0x85, 0x98, 0xbb, 0xb3, 0xea, 0xdc, 0x6b, 0x10, 0x0e, 0x93, 0xf5, 0x0d, - 0x9d, 0x51, 0xe9, 0x44, 0xd7, 0xcb, 0x65, 0x54, 0x30, 0x0e, 0x55, 0x1c, 0xc5, 0x77, 0x77, 0xc9, 0xc0, 0xb4, 0xa3, - 0x3a, 0x02, 0xa7, 0x3d, 0xc6, 0xce, 0x96, 0x74, 0x3e, 0x7e, 0x07, 0xe7, 0x63, 0x8a, 0x6a, 0x23, 0x82, 0xc7, 0x83, - 0x69, 0x8f, 0xa9, 0x67, 0xaf, 0x29, 0x94, 0xd4, 0x77, 0x29, 0xa1, 0x8c, 0x02, 0x77, 0x43, 0x95, 0xf7, 0xa3, 0x34, - 0x7e, 0x40, 0x57, 0xb1, 0xcc, 0x27, 0x17, 0x1a, 0x3c, 0xfc, 0xee, 0xee, 0x90, 0x83, 0xaf, 0x22, 0x1d, 0x6c, 0xee, - 0x75, 0x71, 0xc3, 0x74, 0xfe, 0xee, 0xee, 0xf0, 0x84, 0x40, 0xe9, 0x32, 0xfc, 0x48, 0x0d, 0xcc, 0xc4, 0x9c, 0x88, - 0x12, 0x45, 0xb3, 0x04, 0x6e, 0x36, 0xfc, 0x49, 0x3d, 0x21, 0x80, 0x2c, 0x3a, 0xda, 0x24, 0x86, 0x3e, 0x1d, 0x28, - 0xef, 0x02, 0x8c, 0x21, 0x7e, 0xff, 0x09, 0xa2, 0x25, 0xb4, 0x5c, 0xf3, 0xc7, 0xab, 0x28, 0x46, 0xad, 0x2d, 0xeb, - 0x24, 0x16, 0x4a, 0x81, 0x8d, 0x9e, 0xf0, 0x30, 0x14, 0x0b, 0x09, 0x07, 0x9a, 0x74, 0x86, 0x77, 0xd1, 0x19, 0x5e, - 0x29, 0xae, 0x07, 0x19, 0x46, 0x32, 0xf1, 0x31, 0x90, 0x96, 0xca, 0xf7, 0x75, 0x83, 0xb3, 0xdd, 0x3f, 0x3a, 0xb2, - 0x26, 0xbe, 0x7e, 0x84, 0x88, 0xf5, 0xd0, 0x21, 0xb2, 0x2c, 0x0e, 0x03, 0x7b, 0x6b, 0xb7, 0x3e, 0xc8, 0xf9, 0xe0, - 0xb5, 0x25, 0x84, 0x84, 0x2d, 0xc5, 0x67, 0x71, 0x64, 0xc5, 0xf8, 0x60, 0x47, 0xff, 0xdc, 0xd8, 0x33, 0xaf, 0xfc, - 0xb8, 0x33, 0x2e, 0x88, 0x73, 0x33, 0x4c, 0xbb, 0x57, 0x66, 0x3f, 0xc6, 0xc2, 0x1b, 0xff, 0xf7, 0xc7, 0x44, 0x2a, - 0x74, 0x06, 0xa2, 0x0d, 0x90, 0x71, 0x4f, 0xeb, 0xff, 0xb9, 0xea, 0xf5, 0xc8, 0x5a, 0x83, 0x2f, 0x9f, 0xda, 0xbf, - 0xe8, 0xf5, 0xd6, 0xad, 0xa9, 0x30, 0x2e, 0x7c, 0xa7, 0x38, 0x14, 0xde, 0x7e, 0x75, 0xe1, 0x6d, 0xaf, 0x30, 0x46, - 0x93, 0xa2, 0x32, 0x1b, 0x20, 0xa1, 0x23, 0x54, 0xf8, 0xc1, 0x59, 0xd5, 0x94, 0x6b, 0xf8, 0x97, 0xb4, 0x80, 0x64, - 0x61, 0x81, 0xea, 0xbf, 0x91, 0x7d, 0x1a, 0xa6, 0x0e, 0xb2, 0x71, 0xa6, 0x40, 0x91, 0xd3, 0xe8, 0x49, 0x0a, 0x8c, - 0x01, 0x03, 0x22, 0x1b, 0xf2, 0xf5, 0xbe, 0xde, 0x9b, 0x7d, 0x53, 0x69, 0x4e, 0x86, 0x4a, 0x22, 0x32, 0x3b, 0x46, - 0xe5, 0x44, 0xa5, 0xe3, 0xad, 0x01, 0x57, 0xb6, 0x02, 0x89, 0x77, 0x3f, 0x8d, 0xbc, 0xb3, 0x8e, 0x49, 0xa3, 0x6d, - 0xd8, 0xe7, 0x45, 0x48, 0x40, 0x24, 0x73, 0x90, 0x0b, 0x75, 0xec, 0x2d, 0xb1, 0xd1, 0x81, 0x1a, 0x4b, 0xf9, 0x39, - 0x17, 0x1d, 0xe2, 0x44, 0xb0, 0x06, 0x42, 0x95, 0x67, 0xa2, 0x72, 0xd8, 0x20, 0xc7, 0xef, 0x1d, 0xce, 0x4c, 0x30, - 0x59, 0x84, 0x5a, 0x07, 0xca, 0xfd, 0x20, 0x05, 0x5e, 0xb2, 0x88, 0x30, 0x16, 0xd8, 0xd9, 0xb9, 0xaf, 0x96, 0x78, - 0x7a, 0x8a, 0xf6, 0x98, 0xa9, 0x5f, 0x47, 0x19, 0x52, 0x5a, 0x90, 0xca, 0xeb, 0x8c, 0x74, 0x1b, 0xa5, 0x15, 0x4a, - 0x16, 0xaf, 0xd6, 0x28, 0x4c, 0x34, 0xfc, 0x65, 0x63, 0xa0, 0x30, 0x8e, 0x80, 0xd9, 0xc5, 0x88, 0x54, 0xb2, 0x3d, - 0xb8, 0x91, 0x18, 0x17, 0x00, 0x9a, 0x0a, 0x8b, 0x1f, 0x9d, 0x6c, 0x57, 0x65, 0x95, 0x7d, 0x06, 0xa9, 0x22, 0xce, - 0xa1, 0xf5, 0x59, 0xfd, 0x4a, 0x3f, 0x62, 0xe4, 0x6d, 0xae, 0x46, 0xf5, 0x2a, 0x90, 0x6f, 0x00, 0xa3, 0x34, 0xee, - 0x7c, 0xc8, 0xe0, 0xa3, 0x37, 0xa6, 0xc3, 0x2f, 0x9d, 0x0e, 0x3b, 0x91, 0x68, 0x52, 0x84, 0x64, 0xce, 0x2c, 0x7e, - 0x08, 0xea, 0x2d, 0xa8, 0x45, 0xb5, 0x53, 0x31, 0xde, 0xfe, 0xd3, 0xd1, 0x8e, 0x91, 0x7a, 0x69, 0xb6, 0x25, 0x3a, - 0x28, 0x1c, 0x13, 0xea, 0x5e, 0x73, 0xa6, 0x91, 0x2d, 0xce, 0x0a, 0x84, 0x66, 0x6f, 0x08, 0x19, 0x9f, 0xad, 0x00, - 0x8e, 0x03, 0x10, 0x77, 0x13, 0x10, 0x8e, 0x8e, 0x55, 0x67, 0x8e, 0x03, 0xbc, 0xe0, 0x42, 0x5d, 0xcb, 0xac, 0x62, - 0x0d, 0xe9, 0x78, 0x1c, 0x54, 0xd2, 0xc3, 0x71, 0x54, 0xb6, 0xfd, 0x7e, 0x7c, 0xdf, 0x09, 0xe3, 0x41, 0xfd, 0x0a, - 0x76, 0x37, 0xcf, 0xca, 0xdb, 0x37, 0xf1, 0x2d, 0xeb, 0x15, 0x8a, 0x60, 0xc5, 0x8f, 0xaf, 0x64, 0xcc, 0xda, 0x88, - 0x8d, 0x0a, 0xcd, 0xd4, 0xb2, 0x27, 0x94, 0x8a, 0x3b, 0x3d, 0x2b, 0xc9, 0x97, 0x11, 0x0e, 0x7c, 0x8c, 0x39, 0x5d, - 0xaa, 0x40, 0xee, 0x18, 0xe3, 0xf8, 0x03, 0x36, 0x10, 0xed, 0x17, 0x70, 0x15, 0x23, 0xe4, 0xe9, 0x59, 0xcc, 0x38, - 0x85, 0x28, 0x58, 0xe5, 0x47, 0x47, 0xf2, 0xc4, 0x43, 0xf4, 0x28, 0x97, 0xb6, 0xcf, 0xe2, 0xa9, 0x99, 0xcb, 0x39, - 0xd0, 0x5c, 0xb2, 0xbc, 0x8f, 0x56, 0xf3, 0xd5, 0xc3, 0x22, 0x4c, 0x10, 0xf2, 0x39, 0xbe, 0x89, 0xb3, 0x1c, 0x6f, - 0xa5, 0x59, 0xf9, 0x11, 0x8b, 0x2d, 0x7e, 0x04, 0xbc, 0x83, 0xce, 0x5e, 0x98, 0x64, 0x2c, 0x59, 0x77, 0x4a, 0x72, - 0xef, 0x86, 0xe2, 0x80, 0x7f, 0x76, 0x26, 0x9b, 0xd6, 0x3a, 0x48, 0x1a, 0x18, 0x17, 0x49, 0xed, 0x57, 0x38, 0xeb, - 0x72, 0xda, 0x97, 0xaa, 0x8f, 0x3e, 0x31, 0xd1, 0x05, 0x66, 0x2a, 0x51, 0xa1, 0xc8, 0xf4, 0x83, 0x53, 0x6b, 0x93, - 0xca, 0x84, 0x04, 0xd1, 0x3d, 0x4c, 0x1a, 0x92, 0x18, 0xce, 0x58, 0x99, 0x44, 0xa1, 0x34, 0x84, 0x2b, 0xfb, 0xbe, - 0x16, 0x1c, 0x5a, 0x38, 0xa1, 0xf9, 0x37, 0x48, 0x3a, 0x4a, 0x84, 0xd4, 0x83, 0x9c, 0x52, 0x64, 0x8c, 0xa7, 0xc5, - 0xe2, 0x23, 0x06, 0xcc, 0x46, 0x6d, 0x54, 0x12, 0xa3, 0xcb, 0x06, 0x47, 0xd0, 0x80, 0xf4, 0x67, 0x2a, 0x8c, 0x87, - 0xbc, 0x4a, 0x7c, 0xf5, 0xab, 0xd2, 0xbf, 0x62, 0xf8, 0x86, 0x76, 0x1e, 0xe1, 0x96, 0xe8, 0x67, 0xf8, 0xfe, 0x0d, - 0xaa, 0x0d, 0x41, 0x08, 0x37, 0xf5, 0xd7, 0xbe, 0xa9, 0xce, 0xde, 0x7f, 0xe5, 0x50, 0xdd, 0x96, 0x7c, 0xf4, 0xb2, - 0x17, 0xc0, 0xda, 0x5c, 0xba, 0x12, 0x61, 0x40, 0x3e, 0x4c, 0xe4, 0x2b, 0x4e, 0x2b, 0x30, 0x0d, 0x5d, 0x07, 0x4d, - 0x80, 0x5e, 0x09, 0xf4, 0x41, 0x81, 0x45, 0xcc, 0xc5, 0x0b, 0xc7, 0x19, 0x69, 0xf8, 0x8a, 0x86, 0xe3, 0x8a, 0xd8, - 0x2f, 0xe9, 0x26, 0xa7, 0xe1, 0x70, 0x23, 0x81, 0x8a, 0x40, 0x62, 0x67, 0x90, 0x98, 0x24, 0x8d, 0xb2, 0x8b, 0x0f, - 0x24, 0x60, 0x89, 0x9d, 0x87, 0x23, 0x98, 0x34, 0x62, 0x4e, 0x6f, 0x9a, 0xf4, 0x6b, 0x4f, 0xcb, 0xc1, 0x74, 0x00, - 0xa9, 0x94, 0x58, 0xff, 0x64, 0x58, 0xc5, 0xbb, 0x78, 0xb1, 0x40, 0xf7, 0x2d, 0x0e, 0x75, 0x85, 0xc6, 0xb5, 0x29, - 0x5d, 0x56, 0x63, 0x1c, 0x9a, 0xb3, 0xfa, 0x7c, 0x12, 0xf1, 0xa3, 0xd2, 0xf2, 0x2f, 0x08, 0x8d, 0x8d, 0xf7, 0xcd, - 0xdd, 0xdd, 0x8e, 0x77, 0xbd, 0x18, 0x07, 0x9d, 0xb4, 0xb3, 0x05, 0xc7, 0x06, 0xd2, 0xed, 0xe3, 0x67, 0x38, 0xdf, - 0xac, 0x4d, 0x54, 0xca, 0x56, 0x80, 0x99, 0xa1, 0xdd, 0x41, 0xc0, 0xa1, 0x58, 0x8a, 0x33, 0x3f, 0x5a, 0x30, 0x01, - 0x09, 0xf0, 0xf3, 0x63, 0xf9, 0x7c, 0x5b, 0xb2, 0x8a, 0x9d, 0xda, 0x7a, 0x74, 0x04, 0xe3, 0x8d, 0x78, 0x72, 0x26, - 0xc9, 0xd3, 0xd7, 0x10, 0x96, 0x07, 0xd0, 0x31, 0x0c, 0x0b, 0xa9, 0x89, 0x69, 0x67, 0x4e, 0x60, 0xa2, 0xab, 0x20, - 0x0b, 0xd4, 0x79, 0xaa, 0x37, 0x40, 0x32, 0x50, 0x82, 0x77, 0xa4, 0x2e, 0xc2, 0x67, 0xaf, 0xd9, 0x09, 0x79, 0x14, - 0x83, 0x7c, 0x9f, 0x4d, 0x3f, 0x01, 0xe9, 0x48, 0xe8, 0xd7, 0x6a, 0xa6, 0x0f, 0xbf, 0x4f, 0x11, 0x4a, 0xc6, 0xf0, - 0xc2, 0xed, 0xf6, 0xae, 0x8e, 0xaf, 0x51, 0x32, 0x2d, 0x11, 0xc9, 0x0d, 0x38, 0xa6, 0x90, 0x13, 0x56, 0x92, 0x90, - 0x5b, 0x4b, 0xf2, 0x59, 0x47, 0xdb, 0x60, 0x4d, 0x93, 0xce, 0x83, 0x56, 0xb4, 0xfa, 0x68, 0x35, 0xde, 0x2e, 0xb0, - 0x2e, 0x27, 0xb4, 0x42, 0x75, 0x8c, 0xbb, 0x03, 0x7c, 0x1c, 0xc3, 0x79, 0x55, 0xb7, 0xd9, 0x74, 0x0b, 0x03, 0xea, - 0xc9, 0x3e, 0xcf, 0xa6, 0xb7, 0xf4, 0x24, 0xf4, 0x01, 0xa1, 0x83, 0x79, 0x48, 0xf0, 0xa7, 0xea, 0xab, 0x69, 0xd4, - 0x8f, 0x1d, 0x7a, 0xdd, 0x0c, 0x36, 0xab, 0xf0, 0x2c, 0x61, 0x68, 0x47, 0x11, 0x72, 0x60, 0x50, 0x81, 0x0e, 0x1c, - 0x4b, 0xfc, 0x9c, 0x63, 0x15, 0x3f, 0xe7, 0xb8, 0x35, 0x3c, 0x80, 0x62, 0xdc, 0x2b, 0x60, 0x17, 0x08, 0x33, 0xc4, - 0xea, 0x50, 0x85, 0x51, 0x59, 0xaa, 0x73, 0x9f, 0x62, 0x8a, 0x29, 0xa3, 0x0c, 0x2f, 0x9b, 0x9f, 0xb9, 0x13, 0x79, - 0x1e, 0x9e, 0xb9, 0xd3, 0x64, 0xef, 0xcf, 0x4d, 0xda, 0xe7, 0xc6, 0x84, 0x55, 0x10, 0xe3, 0x74, 0x94, 0xbc, 0x06, - 0xce, 0x13, 0x98, 0xe9, 0xe3, 0xee, 0x99, 0x82, 0x2e, 0xb6, 0x74, 0x86, 0x24, 0x4a, 0xd5, 0x2c, 0x64, 0xfe, 0xee, - 0xae, 0x81, 0x15, 0xa1, 0x28, 0x3d, 0x3e, 0xad, 0x02, 0x18, 0x35, 0xfb, 0x04, 0x41, 0x4c, 0x12, 0x39, 0x93, 0x68, - 0xf6, 0x17, 0x32, 0xfb, 0x9b, 0x36, 0xfa, 0x35, 0x27, 0x75, 0x77, 0x8c, 0x91, 0xd8, 0xf2, 0xbb, 0x08, 0x9d, 0xd3, - 0x55, 0x23, 0x56, 0x68, 0x60, 0xb3, 0x81, 0xef, 0x29, 0x12, 0x8b, 0x7e, 0x3e, 0xc4, 0x7c, 0xc4, 0x26, 0x32, 0xfa, - 0xd1, 0x11, 0xf4, 0xb2, 0x96, 0x5e, 0xde, 0xdd, 0xad, 0x2c, 0x59, 0xd8, 0xd1, 0xc7, 0x31, 0x8d, 0x4a, 0x15, 0x3d, - 0x6a, 0x34, 0x51, 0x69, 0xc6, 0x85, 0xa1, 0x42, 0xe9, 0xb8, 0x86, 0x07, 0x75, 0x7a, 0x65, 0xfa, 0x50, 0xb3, 0xce, - 0xef, 0xba, 0x3f, 0xa6, 0xc0, 0x2e, 0xca, 0x82, 0x40, 0xd3, 0x41, 0x0e, 0xa3, 0x83, 0x60, 0x9c, 0xdd, 0x68, 0x79, - 0x99, 0xad, 0x13, 0xe5, 0xe3, 0xb8, 0xd0, 0xc7, 0x31, 0x90, 0x15, 0xa1, 0x27, 0x3d, 0x36, 0xe3, 0xa4, 0x45, 0x78, - 0xb3, 0xc1, 0x83, 0xfa, 0xee, 0xee, 0x84, 0x85, 0x22, 0x33, 0xd8, 0x46, 0xf9, 0x09, 0xf3, 0xf2, 0x70, 0x45, 0xd7, - 0xbd, 0x35, 0x8d, 0x5e, 0x22, 0xfd, 0x99, 0xad, 0x33, 0x2f, 0x67, 0x9b, 0x5e, 0x94, 0xb3, 0xab, 0x48, 0x3d, 0x58, - 0x63, 0x3d, 0x87, 0xe1, 0x4b, 0x82, 0x9a, 0xa9, 0x75, 0x05, 0x7b, 0xda, 0x22, 0x29, 0xb5, 0xdc, 0xca, 0xcb, 0xdb, - 0x0d, 0x08, 0x6a, 0x98, 0x99, 0x69, 0xfa, 0x38, 0x9f, 0x72, 0xfb, 0xa1, 0x14, 0x6a, 0x65, 0x02, 0xa9, 0x3c, 0xaa, - 0x02, 0xf5, 0x66, 0x1c, 0xc1, 0xcb, 0x28, 0x91, 0x41, 0x6f, 0x0d, 0x82, 0x00, 0xb5, 0x79, 0xd5, 0x69, 0x33, 0xcd, - 0x46, 0xa7, 0xc9, 0xe5, 0xfe, 0x26, 0x97, 0xe4, 0x6e, 0xb7, 0x0e, 0x36, 0xaa, 0xcd, 0x42, 0xd4, 0x6a, 0x65, 0x3b, - 0x40, 0xaf, 0xa5, 0xc9, 0x25, 0x1f, 0x53, 0xa6, 0xcd, 0x1b, 0x74, 0xc6, 0x56, 0x2d, 0x2e, 0x9d, 0x16, 0x97, 0xd0, - 0x62, 0xea, 0x77, 0xdb, 0x36, 0xd3, 0x5b, 0x8c, 0x52, 0x3a, 0xdd, 0x46, 0x15, 0xa9, 0x14, 0xfe, 0x91, 0x46, 0x3b, - 0x58, 0x01, 0xc0, 0xb4, 0xa9, 0x03, 0x11, 0x66, 0x97, 0xc2, 0xbe, 0xc8, 0x2f, 0xc2, 0x01, 0x6f, 0x74, 0x4b, 0xa3, - 0xc6, 0x5a, 0xd3, 0x18, 0xad, 0x61, 0xaa, 0xb8, 0xf0, 0xc8, 0xfc, 0x04, 0x49, 0x8e, 0x76, 0x76, 0xa3, 0x64, 0x85, - 0x46, 0xcf, 0x39, 0x12, 0xec, 0x8b, 0x3c, 0xde, 0x82, 0xec, 0x14, 0xe9, 0x5f, 0x77, 0x77, 0x5a, 0x65, 0xa9, 0x8e, - 0xf4, 0xb3, 0xdd, 0x67, 0x58, 0x45, 0x64, 0xd2, 0x84, 0x51, 0x36, 0xa6, 0xf2, 0xab, 0x6d, 0x41, 0x88, 0x97, 0x96, - 0x29, 0x1c, 0x87, 0x36, 0x60, 0xa4, 0x01, 0xdd, 0x07, 0x45, 0xf0, 0x24, 0xdf, 0x5c, 0xe5, 0x57, 0x32, 0x52, 0xe3, - 0x87, 0x93, 0x93, 0x59, 0x7a, 0xc8, 0x42, 0x92, 0x7a, 0x2b, 0x50, 0x12, 0x69, 0x70, 0xe2, 0x63, 0x70, 0x62, 0x05, - 0x64, 0x2d, 0xbe, 0xfc, 0xd6, 0x08, 0xa4, 0xfa, 0xa7, 0xdd, 0xfb, 0x54, 0xff, 0x34, 0xdd, 0x4e, 0x95, 0xf8, 0x13, - 0x08, 0xdd, 0xd1, 0xfb, 0x0f, 0x0f, 0xef, 0xcc, 0x55, 0xc5, 0xd5, 0x51, 0xd2, 0x98, 0x48, 0x72, 0x53, 0x18, 0x19, - 0x58, 0x03, 0x6a, 0x7b, 0x3a, 0x06, 0x23, 0xb8, 0x22, 0xd8, 0x41, 0xd6, 0x35, 0x1b, 0x49, 0x21, 0x9d, 0xb7, 0x09, - 0xdb, 0x84, 0x20, 0x2f, 0xca, 0x9d, 0xf3, 0x89, 0x04, 0x2a, 0x16, 0x0c, 0x4f, 0x43, 0x6b, 0xd7, 0xcd, 0x5e, 0xa9, - 0x6c, 0xc1, 0x15, 0x06, 0x87, 0xe4, 0x2b, 0x8b, 0xab, 0xe9, 0x65, 0x0a, 0x44, 0x20, 0xfd, 0x8e, 0xda, 0xe1, 0x5e, - 0x5b, 0xb8, 0xef, 0x30, 0xa0, 0xfd, 0x4c, 0x69, 0x6f, 0x12, 0x1d, 0xa0, 0xfb, 0x2a, 0xb8, 0x46, 0x90, 0x01, 0x62, - 0x75, 0xb5, 0x59, 0x9f, 0xf3, 0x38, 0x95, 0x6b, 0x38, 0xf2, 0x6e, 0x9f, 0x5f, 0x85, 0x57, 0xe3, 0x13, 0xd2, 0x4a, - 0x9f, 0x04, 0x8b, 0x0e, 0x06, 0xd5, 0xce, 0x6c, 0xe1, 0xb0, 0x09, 0xac, 0xbd, 0x01, 0xac, 0xab, 0x8c, 0x10, 0x70, - 0x4a, 0x2e, 0x63, 0x0f, 0xb4, 0xac, 0xc3, 0xaf, 0xa3, 0xc1, 0xad, 0x2d, 0xac, 0x94, 0x8f, 0x1e, 0x3f, 0x5a, 0x75, - 0x04, 0x96, 0xea, 0xd1, 0xe3, 0x16, 0x2f, 0x5c, 0x7a, 0xd8, 0x54, 0x78, 0x25, 0x81, 0xa0, 0x5b, 0x09, 0x7b, 0xbc, - 0x28, 0x85, 0x6d, 0x27, 0x9f, 0x39, 0x61, 0xc3, 0x4d, 0xf0, 0x09, 0xe5, 0x4a, 0xf8, 0x28, 0x0a, 0xc4, 0x44, 0x6e, - 0xb6, 0x21, 0xed, 0x60, 0xac, 0x2c, 0x58, 0x47, 0x20, 0x4f, 0x25, 0x8a, 0xc1, 0xcd, 0x09, 0xe5, 0x6b, 0x83, 0x27, - 0x93, 0x5e, 0x5c, 0x4b, 0x20, 0x42, 0xc0, 0x86, 0xa2, 0xed, 0xa8, 0xf5, 0x3b, 0x97, 0xdf, 0x74, 0x7a, 0xe8, 0x17, - 0xc0, 0x80, 0x2c, 0xfd, 0x00, 0x28, 0x3c, 0x7b, 0x6b, 0x32, 0x2b, 0xaf, 0x5e, 0x2e, 0x91, 0x6f, 0x58, 0xc2, 0x49, - 0xb7, 0x44, 0x76, 0x62, 0x09, 0x87, 0x1c, 0x65, 0x74, 0x99, 0x7b, 0x95, 0xd9, 0xba, 0x22, 0x10, 0x76, 0x60, 0x29, - 0x7c, 0x2f, 0xf0, 0x04, 0x4b, 0xa2, 0x4f, 0xcc, 0x17, 0x70, 0xf2, 0x18, 0xeb, 0x15, 0x06, 0x81, 0xde, 0x8e, 0xb1, - 0x7e, 0xe1, 0x17, 0xf1, 0x27, 0x2d, 0x54, 0xf8, 0xf5, 0xa9, 0x0d, 0x5e, 0xc1, 0x47, 0xcd, 0xfd, 0xc3, 0x95, 0xd6, - 0x34, 0x5c, 0x47, 0x57, 0xb8, 0x2c, 0x66, 0xee, 0x58, 0x5e, 0xdb, 0x4d, 0xf1, 0x83, 0x6b, 0x75, 0x76, 0x73, 0x47, - 0x56, 0xc1, 0x17, 0x78, 0x15, 0x8c, 0xc1, 0xaa, 0x02, 0xf7, 0xac, 0xab, 0x5d, 0x9c, 0xfc, 0xbe, 0xc9, 0xaa, 0xd4, - 0x40, 0xa5, 0xc1, 0x9e, 0x86, 0x93, 0x98, 0x42, 0x99, 0xe8, 0x44, 0x0b, 0xc1, 0x15, 0x23, 0x08, 0xdc, 0xa4, 0x45, - 0x83, 0x80, 0x31, 0x68, 0x52, 0xa0, 0x6e, 0xb6, 0x05, 0x42, 0x6a, 0xf8, 0x1d, 0xaa, 0xed, 0xd2, 0x1b, 0xa0, 0x22, - 0x74, 0x5b, 0x48, 0xb6, 0x0a, 0xe6, 0x9a, 0xf3, 0x44, 0xcc, 0x62, 0xb3, 0xeb, 0xcd, 0xf5, 0x07, 0x32, 0x2e, 0xed, - 0x98, 0xf9, 0xa5, 0x36, 0x5b, 0x9b, 0x12, 0x6f, 0xc2, 0xdc, 0x76, 0x11, 0x15, 0xc4, 0x9b, 0xf0, 0xd6, 0xde, 0xf1, - 0x88, 0xa6, 0x6a, 0x90, 0xad, 0x42, 0xf5, 0xdc, 0x0a, 0x58, 0x9d, 0x3e, 0x02, 0x81, 0x16, 0x75, 0x53, 0x59, 0xfd, - 0xb4, 0x69, 0xe8, 0x2a, 0xd4, 0xea, 0xe1, 0x71, 0xab, 0x8d, 0x4d, 0x81, 0xd0, 0x11, 0xce, 0xaa, 0xdc, 0x43, 0xbf, - 0xca, 0xb5, 0xe9, 0xe5, 0xc0, 0xb8, 0x19, 0x53, 0x17, 0x14, 0x88, 0x0d, 0xf8, 0x9c, 0xfb, 0xe4, 0x8d, 0x1e, 0x2f, - 0x46, 0xb0, 0x93, 0x29, 0x7a, 0x52, 0xf7, 0x43, 0x4d, 0xdf, 0x14, 0x8c, 0xa2, 0x30, 0x8a, 0xfe, 0x22, 0x8b, 0x46, - 0x0f, 0x68, 0xde, 0x7f, 0xad, 0x47, 0xc1, 0x0f, 0x79, 0xb4, 0x6b, 0xca, 0x4d, 0xb2, 0x62, 0xaf, 0x86, 0xd1, 0x75, - 0xb9, 0xa9, 0xd3, 0x45, 0xf9, 0xa9, 0x80, 0xc3, 0x05, 0x93, 0x71, 0x2e, 0x24, 0x15, 0x7f, 0x4a, 0x2a, 0x5a, 0x84, - 0x70, 0xe2, 0x06, 0x4e, 0x21, 0xd2, 0x6e, 0xa2, 0x9f, 0x12, 0xfc, 0x23, 0xc9, 0xf4, 0x5b, 0xbf, 0xc1, 0xfa, 0x9c, - 0xaa, 0x25, 0xbd, 0x57, 0xb9, 0xa4, 0x6f, 0xd6, 0xfd, 0xda, 0x61, 0x21, 0xe9, 0xcc, 0x40, 0x9f, 0x74, 0x3a, 0xf9, - 0x4e, 0xe9, 0xd4, 0x36, 0xf8, 0x5c, 0xab, 0x58, 0x56, 0xec, 0xfe, 0x4d, 0x81, 0xac, 0x46, 0x86, 0x1d, 0xff, 0x57, - 0xde, 0x3d, 0xc3, 0x6a, 0xb4, 0xcb, 0xa0, 0xb8, 0x5f, 0x08, 0x7c, 0xdc, 0x34, 0x55, 0x76, 0xb9, 0xc1, 0xb0, 0x21, - 0x3c, 0xfd, 0x23, 0x9f, 0x22, 0x60, 0xba, 0xaf, 0x68, 0x85, 0x8c, 0x48, 0xe7, 0x9c, 0x9d, 0x55, 0xd9, 0x79, 0xa4, - 0xdc, 0x5a, 0xc2, 0x9d, 0x2c, 0x9a, 0x42, 0xf6, 0x25, 0xaa, 0x99, 0xd0, 0xec, 0x43, 0x5b, 0x44, 0xa4, 0x8a, 0x28, - 0xab, 0xe5, 0x95, 0xaa, 0x75, 0x27, 0xcb, 0x8e, 0x17, 0x25, 0x9a, 0x6a, 0xe8, 0xac, 0x91, 0xfe, 0x05, 0x07, 0xff, - 0x65, 0x5e, 0x26, 0xbf, 0x8d, 0xc8, 0xde, 0xf1, 0x16, 0x96, 0x39, 0x7a, 0xcb, 0x58, 0xbf, 0x31, 0x03, 0x19, 0x9e, - 0x4c, 0x20, 0x69, 0x04, 0xa3, 0x41, 0x02, 0xac, 0x12, 0x3f, 0x3e, 0x20, 0x87, 0xaa, 0x5b, 0x5f, 0x5a, 0x71, 0xc2, - 0x3c, 0xc5, 0xda, 0x96, 0x3e, 0xba, 0x85, 0x7e, 0x46, 0xcf, 0x48, 0x74, 0x37, 0x95, 0xe1, 0x51, 0xdc, 0x2e, 0x8e, - 0xa5, 0xaf, 0x79, 0x5f, 0x29, 0xf3, 0x08, 0x61, 0x65, 0x1f, 0xdb, 0x70, 0x4f, 0xfa, 0x53, 0x6a, 0x0c, 0xbb, 0xdf, - 0x92, 0x0a, 0x4a, 0xcd, 0xac, 0x67, 0xb2, 0x3a, 0xaf, 0xaa, 0xa8, 0x00, 0xc9, 0x70, 0x8d, 0x34, 0xea, 0x86, 0xac, - 0xa6, 0xc2, 0xc3, 0x13, 0x33, 0x7b, 0x3f, 0x9b, 0x10, 0xaa, 0xd3, 0x41, 0x0a, 0x72, 0x55, 0x59, 0x42, 0xce, 0xef, - 0x56, 0xee, 0x24, 0x2e, 0x6e, 0x62, 0xb4, 0x0c, 0x1b, 0xa6, 0x2e, 0x4e, 0xb9, 0x9f, 0x3a, 0x6b, 0xe4, 0x87, 0xfc, - 0x2c, 0x23, 0x2c, 0x92, 0x73, 0xbc, 0xf5, 0x23, 0x3b, 0x0f, 0x60, 0xe5, 0x0b, 0x3c, 0x6e, 0x5a, 0xd4, 0x61, 0x63, - 0x66, 0x6d, 0x4b, 0x84, 0x46, 0x35, 0x29, 0x6b, 0x6a, 0xe0, 0x28, 0x2d, 0x62, 0x0a, 0x6c, 0x97, 0xc1, 0x19, 0x55, - 0xe8, 0x21, 0x98, 0x17, 0x14, 0xf6, 0x0c, 0xcb, 0x9b, 0x34, 0x09, 0x85, 0x66, 0x85, 0x8b, 0x95, 0x88, 0x7f, 0x3d, - 0x6d, 0xa6, 0x44, 0x8f, 0x6d, 0x30, 0xee, 0x25, 0x2a, 0x27, 0xe3, 0x8c, 0xdc, 0x77, 0x7c, 0x4d, 0x79, 0x74, 0x15, - 0xff, 0xe8, 0x47, 0x9b, 0x94, 0x81, 0x08, 0x24, 0xd8, 0xf8, 0x86, 0xfd, 0x0d, 0xdf, 0x5e, 0xd6, 0x69, 0x85, 0xa0, - 0x97, 0x25, 0x1c, 0x1a, 0x7c, 0xe7, 0x8a, 0xc3, 0xee, 0xca, 0x28, 0xa5, 0x5f, 0x45, 0xd5, 0xdd, 0x1d, 0xb4, 0x2b, - 0xc6, 0xc1, 0x4f, 0x17, 0xdf, 0xe3, 0x75, 0x58, 0x40, 0xd8, 0x8c, 0x08, 0x61, 0x4e, 0x2f, 0x78, 0x80, 0xf5, 0x2b, - 0x04, 0x8d, 0x4b, 0x89, 0x81, 0xd1, 0xa2, 0x6d, 0xc9, 0xdf, 0xf2, 0x16, 0x65, 0x42, 0xa8, 0x51, 0x88, 0x89, 0x92, - 0xe5, 0x0b, 0x9c, 0x0e, 0x32, 0x7e, 0xdf, 0x5c, 0x36, 0xc0, 0x94, 0xe0, 0xd4, 0x3b, 0x37, 0xc3, 0x7f, 0xfb, 0x5f, - 0xeb, 0x4b, 0xa7, 0xc9, 0x76, 0x6f, 0x9c, 0x6e, 0xfe, 0xb7, 0xfb, 0xc2, 0xdf, 0x7f, 0x9e, 0xaa, 0x38, 0xef, 0x24, - 0x6e, 0xff, 0x8a, 0xde, 0xfb, 0xba, 0x97, 0xd7, 0x95, 0x36, 0xc3, 0xcc, 0xa2, 0x4f, 0xc0, 0x50, 0x97, 0x9f, 0xa6, - 0x8b, 0xce, 0x91, 0x37, 0xcb, 0x60, 0xd5, 0xfc, 0x0a, 0xcc, 0x9e, 0xf7, 0x2b, 0x06, 0xe3, 0x7d, 0x9e, 0x1a, 0x43, - 0x4c, 0x8e, 0xc1, 0xb7, 0x83, 0x75, 0xb1, 0xa9, 0x90, 0x20, 0x77, 0x4f, 0x4b, 0xd4, 0xcc, 0xc0, 0x49, 0x82, 0x9d, - 0xb0, 0xd6, 0xfb, 0x3f, 0x65, 0xbd, 0x3f, 0x4f, 0x45, 0xb2, 0x92, 0x0f, 0xf7, 0x76, 0x18, 0xda, 0x1e, 0x43, 0x86, - 0x51, 0x70, 0x5d, 0xf9, 0xf8, 0x5d, 0xb9, 0xe9, 0xb3, 0xaa, 0xfa, 0x37, 0x29, 0x6a, 0xe0, 0x15, 0x07, 0x1e, 0x44, - 0xed, 0x6c, 0xb7, 0xd6, 0xa1, 0x2d, 0x68, 0x57, 0x6c, 0x2a, 0xfb, 0xfb, 0xbd, 0x53, 0x7e, 0x74, 0xf4, 0xbe, 0xf0, - 0x3a, 0x71, 0xdd, 0x0d, 0xdc, 0x65, 0xe5, 0x11, 0x04, 0xb0, 0xe6, 0x81, 0xf2, 0x88, 0x60, 0xd2, 0xe1, 0xa3, 0xc4, - 0x9b, 0xce, 0x52, 0x7a, 0x1d, 0xe4, 0xa7, 0x4e, 0x32, 0x4f, 0x70, 0xc0, 0x2d, 0xc5, 0x95, 0x80, 0x33, 0xf5, 0x9e, - 0xda, 0xa6, 0x97, 0x55, 0x6c, 0xd9, 0x1a, 0xe2, 0xed, 0x22, 0x70, 0xfb, 0xc4, 0x66, 0x22, 0x80, 0xcd, 0x7b, 0xe4, - 0xaf, 0x58, 0x74, 0x58, 0x75, 0x52, 0x45, 0xbe, 0xce, 0x39, 0x18, 0xcd, 0x8a, 0xc3, 0xfc, 0x96, 0x1e, 0xde, 0x6f, - 0x9b, 0x15, 0x55, 0xe9, 0x15, 0x05, 0x1c, 0x2c, 0x4d, 0x4b, 0xe9, 0x5c, 0xe2, 0xff, 0x23, 0x53, 0x23, 0x92, 0x92, - 0x55, 0x65, 0x56, 0xc3, 0x27, 0x0a, 0xa8, 0x1e, 0x3d, 0x0e, 0xc4, 0x38, 0x1c, 0xc7, 0xf1, 0xe8, 0x88, 0x26, 0xc2, - 0x14, 0x6c, 0x56, 0xf7, 0x0c, 0x65, 0xc3, 0x7b, 0x25, 0xc3, 0x98, 0x8a, 0x1a, 0x21, 0x22, 0xf5, 0x7e, 0xc2, 0x38, - 0xab, 0x19, 0x2c, 0x14, 0xeb, 0x8a, 0x0e, 0x08, 0x30, 0xc8, 0x5f, 0xc8, 0x5f, 0xd7, 0xc2, 0xce, 0xa4, 0xab, 0xfb, - 0xd8, 0x19, 0x07, 0x20, 0xe6, 0xcb, 0x1c, 0x8d, 0xc6, 0xfe, 0x47, 0x24, 0x18, 0x6e, 0x1f, 0x52, 0xba, 0xb9, 0xf7, - 0xaf, 0x5c, 0x70, 0x14, 0x7d, 0x26, 0x93, 0x7d, 0xce, 0xd2, 0x68, 0xe1, 0xb8, 0x1c, 0x47, 0x18, 0xc7, 0xd3, 0xb9, - 0x1f, 0x64, 0x9b, 0x92, 0x95, 0x03, 0xe9, 0xec, 0x4c, 0x1d, 0x53, 0xea, 0x68, 0x3c, 0xd7, 0x1b, 0xaa, 0xd4, 0x73, - 0x0d, 0x4b, 0x01, 0x6f, 0x4f, 0xbe, 0xf5, 0x2a, 0x7f, 0x9e, 0xca, 0x1a, 0x36, 0x1c, 0x41, 0xe9, 0x87, 0xb4, 0x1b, - 0xac, 0x14, 0xbc, 0x30, 0x35, 0xa1, 0xb9, 0x0a, 0x3e, 0x47, 0xd1, 0xa2, 0x70, 0x28, 0x62, 0x6b, 0xed, 0x3b, 0x9f, - 0x4c, 0x39, 0x37, 0x7c, 0x30, 0xaa, 0x31, 0xe6, 0x32, 0x2a, 0x84, 0xf9, 0x78, 0x96, 0xbf, 0x81, 0xc4, 0xf5, 0xa4, - 0x8e, 0x60, 0x30, 0xf8, 0x7d, 0xec, 0xb4, 0x98, 0x43, 0x0f, 0x1e, 0x7a, 0x56, 0xe0, 0xb0, 0xe9, 0x83, 0x75, 0x55, - 0xde, 0x66, 0xa4, 0x97, 0x30, 0x0f, 0x14, 0x9f, 0xb7, 0x8a, 0x76, 0x31, 0xb1, 0xb7, 0xe1, 0x3f, 0x72, 0xf8, 0x2c, - 0xfd, 0xfa, 0x5b, 0x1e, 0xf0, 0x42, 0x0b, 0xff, 0x9e, 0xb7, 0x14, 0xa8, 0x18, 0xb1, 0x22, 0x30, 0x96, 0xa9, 0xfa, - 0xf0, 0x3e, 0x36, 0xde, 0x5a, 0x0d, 0xf7, 0x7c, 0xb3, 0x46, 0x9d, 0xfa, 0xb9, 0xbb, 0xb3, 0x3d, 0xdd, 0x8c, 0x4c, - 0x35, 0x03, 0x7e, 0x49, 0x33, 0xfe, 0x91, 0x71, 0x33, 0x7e, 0xcf, 0xd9, 0x7f, 0x07, 0xd6, 0x27, 0x45, 0x4e, 0x36, - 0x3e, 0x49, 0xfb, 0xe5, 0x86, 0x3d, 0x54, 0xf6, 0x4b, 0xd2, 0x44, 0x96, 0x1b, 0x4f, 0x21, 0x57, 0x02, 0x50, 0x2b, - 0x11, 0xc8, 0x93, 0xe6, 0x0b, 0x0e, 0x0f, 0x3d, 0xda, 0xb1, 0x59, 0xfd, 0x9c, 0x37, 0x2c, 0x46, 0xf3, 0x32, 0xdb, - 0x33, 0x5b, 0x21, 0xd9, 0x94, 0xac, 0xdf, 0x15, 0x1e, 0x42, 0x30, 0xb3, 0x9a, 0x00, 0x91, 0x16, 0x12, 0x38, 0x43, - 0x8a, 0xe7, 0xb4, 0xaa, 0x0f, 0xa3, 0xd1, 0xa6, 0x58, 0x70, 0xd0, 0x6a, 0xd8, 0xe5, 0xd9, 0x01, 0x9c, 0xfd, 0xe4, - 0xd4, 0xd0, 0xcf, 0x3a, 0x7f, 0x95, 0x87, 0xe9, 0x4a, 0x76, 0xe9, 0x3f, 0x5d, 0x27, 0x2f, 0x63, 0xfb, 0x7a, 0x0b, - 0x9b, 0x4e, 0xfd, 0xde, 0x5a, 0xbf, 0x2d, 0x10, 0xdc, 0x59, 0xdf, 0x4e, 0x56, 0xa5, 0x3c, 0x30, 0x26, 0xed, 0x23, - 0xbf, 0x6d, 0xca, 0x32, 0x6f, 0xb2, 0xf5, 0x3b, 0xd1, 0xd3, 0xe8, 0xb1, 0xd8, 0xe1, 0x65, 0xf0, 0x16, 0x01, 0xcf, - 0xb4, 0x6b, 0x80, 0xd8, 0x9e, 0xb1, 0x85, 0xfb, 0xb9, 0xc5, 0x3f, 0xa9, 0xac, 0xed, 0x2a, 0xae, 0xd9, 0x37, 0xc3, - 0x5c, 0x42, 0x89, 0x9f, 0xc6, 0x2d, 0xc8, 0xe6, 0xea, 0xf7, 0x96, 0xbc, 0xa8, 0xb8, 0xba, 0x3e, 0x1a, 0x95, 0xd5, - 0x3c, 0x26, 0x07, 0x77, 0x77, 0x87, 0x85, 0x8d, 0xa3, 0xad, 0x77, 0xc0, 0xce, 0x72, 0x95, 0xb2, 0x77, 0x22, 0x6e, - 0x3f, 0xda, 0xf9, 0x40, 0x90, 0xe0, 0x5f, 0xf1, 0xb4, 0xf0, 0xfc, 0x39, 0x3d, 0x5d, 0x34, 0x25, 0xb9, 0x67, 0xf0, - 0x1e, 0xad, 0xd1, 0x99, 0xe0, 0x9f, 0x03, 0xa8, 0x97, 0x56, 0xda, 0x7b, 0xd4, 0xad, 0xe0, 0x08, 0x9a, 0xfb, 0x81, - 0x55, 0x57, 0x20, 0x51, 0xd2, 0x5b, 0x93, 0x25, 0xbf, 0x01, 0xdf, 0x11, 0xd5, 0xb8, 0x38, 0x5c, 0xd7, 0x27, 0x10, - 0x47, 0x3f, 0xe2, 0xdb, 0xef, 0x30, 0xe4, 0x16, 0x88, 0x81, 0xc8, 0xb6, 0xa0, 0x99, 0xc7, 0x75, 0xfc, 0x6b, 0x59, - 0x89, 0x47, 0xfd, 0x62, 0x5e, 0xa1, 0xf6, 0x2e, 0x24, 0x03, 0x2c, 0x0d, 0xe2, 0x15, 0xb3, 0xe5, 0x6c, 0x82, 0xb0, - 0xec, 0x18, 0xe5, 0x2c, 0x8f, 0xd8, 0xcd, 0xb3, 0x7a, 0x52, 0x6b, 0x7c, 0x76, 0x28, 0x16, 0xe4, 0x68, 0x2c, 0x00, - 0x12, 0x6e, 0x90, 0x6b, 0xd5, 0x53, 0xb9, 0x22, 0x9b, 0x57, 0x36, 0x82, 0xab, 0xd0, 0xc8, 0x06, 0xf9, 0x17, 0x0c, - 0x92, 0xa6, 0x94, 0x35, 0xd5, 0x93, 0x13, 0x96, 0x90, 0xc9, 0x72, 0xde, 0xf3, 0x92, 0x49, 0xec, 0x3f, 0xf2, 0x2a, - 0x74, 0xdf, 0x24, 0xb2, 0x4d, 0x5c, 0xd8, 0xdf, 0x52, 0xaa, 0x7e, 0x15, 0x7c, 0xeb, 0x2d, 0xfd, 0xf9, 0x71, 0x18, - 0x4f, 0x28, 0x36, 0xd4, 0x22, 0xc2, 0xe8, 0x69, 0x18, 0xc5, 0x66, 0x71, 0xba, 0x99, 0x2d, 0xc6, 0x63, 0x5f, 0x67, - 0x2c, 0xcf, 0x16, 0x18, 0x06, 0x79, 0x31, 0x3e, 0x39, 0xd7, 0x27, 0x84, 0x7e, 0x99, 0x70, 0x3d, 0xca, 0xd1, 0x39, - 0x4c, 0xc6, 0x4b, 0xc4, 0x53, 0xef, 0x64, 0xc3, 0x24, 0x13, 0x06, 0x7a, 0xe5, 0xde, 0x26, 0xa9, 0x01, 0x67, 0xb4, - 0x0e, 0x32, 0x5c, 0xbd, 0xc0, 0xc1, 0xa7, 0x7d, 0xef, 0x93, 0x68, 0x78, 0xc1, 0xb5, 0x3f, 0x4a, 0xc7, 0x5e, 0x03, - 0x6d, 0x3e, 0x61, 0xa9, 0xf0, 0x02, 0xe6, 0xe1, 0x3b, 0x79, 0xe1, 0x98, 0xa3, 0xb2, 0x86, 0xc0, 0xe0, 0xed, 0x91, - 0xb9, 0x99, 0x31, 0x4c, 0xe9, 0x1d, 0xc6, 0x89, 0x4c, 0xb1, 0xea, 0xc5, 0x23, 0xb1, 0x46, 0xf0, 0xed, 0x4a, 0xc9, - 0x97, 0x2d, 0x38, 0x31, 0x21, 0x0a, 0xff, 0x81, 0x60, 0x87, 0xda, 0x5e, 0xa9, 0x82, 0x01, 0x8c, 0x23, 0x63, 0x7f, - 0x4c, 0xc0, 0x92, 0x95, 0xf1, 0xa4, 0x4a, 0x34, 0x12, 0x7f, 0x62, 0xe6, 0x3a, 0x69, 0x87, 0xbe, 0x60, 0x19, 0xb2, - 0xac, 0x86, 0x8d, 0x49, 0x2c, 0x23, 0x92, 0xcc, 0x36, 0x1f, 0x49, 0xe1, 0x7b, 0x78, 0x47, 0xcc, 0x2b, 0x11, 0x8f, - 0x78, 0x52, 0x22, 0xa7, 0x43, 0x76, 0x1b, 0xf1, 0xaa, 0x6b, 0xcb, 0x4a, 0xd1, 0x82, 0x70, 0x79, 0x72, 0xf8, 0x20, - 0x09, 0x39, 0x95, 0xa4, 0x40, 0x6b, 0x89, 0x2f, 0x3f, 0x86, 0x3e, 0xe9, 0xcf, 0x61, 0xd7, 0x2a, 0xb4, 0x92, 0xa1, - 0xe0, 0x91, 0xf4, 0x99, 0x0c, 0xaf, 0xc5, 0x82, 0x7a, 0x3c, 0xa6, 0x7a, 0xea, 0x87, 0xce, 0x95, 0xf4, 0xdf, 0x06, - 0x8d, 0xb0, 0x9f, 0xc2, 0xe4, 0x58, 0x5a, 0x5e, 0x98, 0xac, 0xa7, 0x5e, 0x1d, 0xa8, 0x8f, 0xf8, 0xe6, 0xd7, 0x4c, - 0x9b, 0x60, 0xeb, 0x9b, 0xb1, 0xd4, 0x6a, 0x1f, 0x42, 0xda, 0x53, 0xb8, 0xbc, 0x7a, 0x52, 0xc0, 0x0a, 0x4a, 0x1e, - 0x59, 0xeb, 0x20, 0x79, 0x94, 0xfa, 0x14, 0xcb, 0x6e, 0xb6, 0x3a, 0x3d, 0x9e, 0xf9, 0x31, 0xb4, 0x4f, 0x00, 0x68, - 0x79, 0x9f, 0x94, 0xe3, 0xf8, 0x61, 0x2a, 0x13, 0x69, 0x74, 0x54, 0x25, 0xde, 0x58, 0xe6, 0xa7, 0xd5, 0x2c, 0x87, - 0x8e, 0x22, 0xdb, 0xb8, 0xb2, 0x3b, 0x9a, 0x43, 0x47, 0xf7, 0x54, 0x64, 0xf5, 0x39, 0xe9, 0xac, 0x74, 0x0b, 0x0c, - 0x00, 0x27, 0x91, 0xc0, 0x72, 0x1f, 0x1b, 0xfe, 0x88, 0x07, 0x3d, 0xc3, 0x19, 0x48, 0xa3, 0x13, 0x98, 0xd0, 0x86, - 0xec, 0x81, 0x48, 0xcd, 0x91, 0xe2, 0x35, 0x6a, 0x0a, 0x24, 0x03, 0x39, 0x44, 0x53, 0xc4, 0xa0, 0x7f, 0x31, 0x9b, - 0xbd, 0xd2, 0xa1, 0xc4, 0xe9, 0x32, 0x72, 0x2e, 0x97, 0x91, 0x21, 0x47, 0x17, 0xa7, 0xdf, 0x73, 0x7e, 0x05, 0x42, - 0xf1, 0xb3, 0xda, 0x04, 0x0e, 0x27, 0xf6, 0x15, 0x6f, 0x35, 0xe0, 0xe8, 0x33, 0xc5, 0xb3, 0xb3, 0xe6, 0x7c, 0x0c, - 0xf2, 0x33, 0xfc, 0x99, 0xa4, 0xc1, 0x8f, 0x3a, 0x14, 0xb9, 0x41, 0xea, 0x04, 0x91, 0x1c, 0xf9, 0x53, 0xdd, 0xe5, - 0x57, 0xb5, 0x4b, 0x4f, 0x81, 0xfc, 0x99, 0x35, 0xfa, 0xa8, 0xa1, 0x7d, 0x6b, 0x0d, 0x43, 0x29, 0x68, 0x4d, 0xb3, - 0xf2, 0xb4, 0x9e, 0x95, 0x63, 0xe8, 0x5a, 0xaa, 0x86, 0xd8, 0x9a, 0xc1, 0xd2, 0x3f, 0xb7, 0x40, 0x98, 0xf4, 0xb7, - 0x56, 0x03, 0x5c, 0x35, 0x51, 0x6d, 0x45, 0x6d, 0x6b, 0x1b, 0x52, 0xb4, 0x00, 0x3a, 0x18, 0xa0, 0xd9, 0xff, 0x05, - 0x29, 0xdb, 0x88, 0xd5, 0xa0, 0x9b, 0xd5, 0x0b, 0xe0, 0x9e, 0xf9, 0x29, 0x8e, 0x4e, 0xd2, 0xc9, 0x5f, 0xc5, 0xbc, - 0x39, 0xb3, 0x41, 0x0e, 0x90, 0xdc, 0x7b, 0x44, 0x8e, 0xc9, 0x02, 0x19, 0xad, 0x11, 0x0a, 0x18, 0xa6, 0x93, 0xb9, - 0xb5, 0x62, 0x92, 0x09, 0xd0, 0xec, 0x49, 0xe2, 0x87, 0x14, 0xf1, 0x72, 0x8e, 0x51, 0xd9, 0x7b, 0x55, 0x9c, 0xf8, - 0x90, 0xe1, 0xd1, 0xe3, 0x10, 0x5e, 0x26, 0x93, 0x81, 0x2f, 0x20, 0xad, 0x7e, 0xf4, 0x38, 0x48, 0xc6, 0x51, 0x7d, - 0xda, 0xcc, 0xf3, 0x70, 0x92, 0x07, 0xc9, 0x69, 0x39, 0x41, 0x1b, 0xda, 0x27, 0xd5, 0x38, 0xf6, 0x7d, 0x43, 0x39, - 0xf4, 0x30, 0x2c, 0xe4, 0x08, 0x7b, 0x85, 0x66, 0xbb, 0x9a, 0x63, 0xc6, 0x2b, 0x9b, 0xab, 0x24, 0x30, 0xd8, 0xf2, - 0x8f, 0x1e, 0x9b, 0x58, 0x42, 0xf5, 0x13, 0xd1, 0x6c, 0x94, 0x74, 0x9d, 0x5c, 0xd3, 0x75, 0xb2, 0x62, 0x6a, 0xd9, - 0x26, 0x15, 0x4f, 0xd8, 0xf3, 0x59, 0xa1, 0xee, 0x8d, 0x8e, 0xc9, 0x71, 0xd1, 0x5a, 0xdb, 0x71, 0x6a, 0x78, 0xa6, - 0x83, 0x8c, 0x2e, 0xb0, 0xe8, 0x4c, 0x9c, 0xf3, 0x1c, 0x30, 0x5d, 0x0e, 0x2d, 0x6d, 0xc8, 0x0f, 0xb2, 0x32, 0xe8, - 0x6e, 0x48, 0x69, 0xd4, 0x0c, 0xfc, 0x99, 0x5a, 0x30, 0x3f, 0xe1, 0x2d, 0x11, 0x7a, 0x75, 0x21, 0x26, 0x49, 0xc1, - 0x97, 0x46, 0xea, 0x96, 0x48, 0xd6, 0x80, 0xf7, 0x1e, 0x2d, 0x59, 0x40, 0xf0, 0xf0, 0xe7, 0xfc, 0x57, 0x1d, 0x3e, - 0x27, 0xfe, 0xc3, 0x14, 0xa3, 0x90, 0xcb, 0x85, 0xc8, 0x58, 0xe1, 0x90, 0x5a, 0x17, 0xef, 0x2b, 0xc7, 0x32, 0xf0, - 0x25, 0x0a, 0xd0, 0xec, 0xd0, 0x1f, 0xc2, 0x07, 0xc9, 0x23, 0x8b, 0x9e, 0x46, 0x76, 0x57, 0x97, 0x7a, 0x9d, 0x39, - 0xc5, 0xb0, 0x9b, 0xc0, 0x2e, 0xb1, 0xb9, 0x9d, 0x2a, 0x8d, 0x89, 0x4e, 0xe1, 0xb5, 0x2e, 0xcc, 0x88, 0x64, 0x55, - 0xe2, 0x69, 0x79, 0x0e, 0xd7, 0x11, 0x7b, 0xe8, 0xd0, 0xce, 0x04, 0xf6, 0x28, 0x65, 0xf7, 0x1d, 0x65, 0xf9, 0x40, - 0xcb, 0x2c, 0x5f, 0xa1, 0x36, 0x30, 0x28, 0x4c, 0x9d, 0x57, 0x16, 0xe9, 0x66, 0x16, 0x0f, 0x6f, 0x09, 0x6a, 0x32, - 0x73, 0x0a, 0x4b, 0x75, 0x49, 0x50, 0xc9, 0xad, 0x41, 0x2c, 0xea, 0xb0, 0x04, 0x3d, 0x87, 0x2c, 0x04, 0xdc, 0x5c, - 0x79, 0xa3, 0xad, 0xda, 0x28, 0xa1, 0xb5, 0x41, 0x4c, 0x00, 0x05, 0xf6, 0x14, 0x75, 0x20, 0x30, 0x04, 0x88, 0x8f, - 0x12, 0x4f, 0x68, 0xd5, 0x64, 0x1d, 0xcb, 0x41, 0x9a, 0xcb, 0x65, 0x74, 0x55, 0x13, 0x18, 0x04, 0x30, 0x11, 0x14, - 0x3f, 0x59, 0xd6, 0xdf, 0xa5, 0x13, 0x69, 0x27, 0xf5, 0x91, 0xaa, 0x5d, 0xc0, 0xb1, 0x70, 0x79, 0x3e, 0x43, 0xff, - 0x96, 0xcb, 0xf3, 0x3e, 0x86, 0xc8, 0x85, 0x3f, 0xbe, 0x9a, 0x48, 0xac, 0x28, 0x32, 0x59, 0x4f, 0x58, 0x91, 0x3d, - 0x5f, 0x47, 0x04, 0x82, 0x83, 0xbd, 0x1a, 0xe7, 0x74, 0x49, 0xfc, 0xe8, 0x31, 0x66, 0x0d, 0xd7, 0xd1, 0xb3, 0x9a, - 0x8d, 0xd5, 0xfd, 0xd9, 0x06, 0x9b, 0xc9, 0x57, 0xd6, 0x2a, 0x94, 0xf3, 0x97, 0x9b, 0xb2, 0xdc, 0xdb, 0x94, 0xc9, - 0xf5, 0x78, 0xa8, 0x29, 0xcb, 0x88, 0x42, 0x1b, 0xd0, 0x6d, 0xba, 0x42, 0x0c, 0xc5, 0xac, 0xe1, 0xd2, 0x6a, 0xca, - 0x9a, 0xc7, 0x04, 0x1d, 0x7d, 0x30, 0xca, 0xa8, 0xa1, 0xa7, 0x93, 0x1f, 0xc2, 0x1f, 0x94, 0xcb, 0x52, 0x93, 0x35, - 0x79, 0xfa, 0x53, 0xb8, 0x0c, 0xe8, 0xc7, 0xcf, 0xe1, 0x1a, 0xb1, 0x04, 0xf8, 0xe6, 0x6e, 0x63, 0xa3, 0xf5, 0x8a, - 0x08, 0xf1, 0x7d, 0xa3, 0x05, 0xfd, 0x8e, 0x34, 0xd1, 0x28, 0xc0, 0x08, 0x85, 0x16, 0x81, 0x77, 0xf5, 0x18, 0x7b, - 0x0a, 0x1f, 0x08, 0xc3, 0xb9, 0x61, 0xad, 0xa9, 0xe3, 0x5e, 0x67, 0xe3, 0x48, 0x24, 0xcd, 0x2d, 0x0a, 0xee, 0xcd, - 0xad, 0x15, 0xbf, 0x51, 0x81, 0x00, 0x48, 0x35, 0xe5, 0xda, 0x29, 0x21, 0x56, 0x19, 0x76, 0x12, 0x59, 0x6f, 0xd8, - 0x09, 0x6c, 0xc5, 0x61, 0xa7, 0xb0, 0x10, 0x6d, 0xa7, 0x88, 0x26, 0xda, 0x4e, 0x02, 0xae, 0xae, 0x42, 0xe7, 0x57, - 0x6d, 0xad, 0xa3, 0xee, 0xbe, 0xf8, 0x26, 0x4c, 0xdf, 0x80, 0x71, 0x6e, 0x35, 0x66, 0x4e, 0x15, 0xd7, 0xea, 0xbe, - 0xd3, 0x49, 0x15, 0x2a, 0xf2, 0xb1, 0xd3, 0x15, 0x49, 0x7e, 0xd6, 0xef, 0x91, 0xbc, 0xf9, 0xae, 0xdb, 0x31, 0x49, - 0x7f, 0xdf, 0xfb, 0x02, 0x99, 0x22, 0x3b, 0x63, 0x82, 0x0e, 0x99, 0x0a, 0xaa, 0xd5, 0x6d, 0x62, 0x56, 0x74, 0x9b, - 0xec, 0x8e, 0x42, 0x45, 0xee, 0x74, 0x76, 0x12, 0x1d, 0x6d, 0x26, 0x18, 0x38, 0x3a, 0x81, 0xa2, 0xab, 0x28, 0xb9, - 0x47, 0x90, 0xd6, 0x48, 0x5e, 0xd0, 0x47, 0x87, 0x53, 0x91, 0xa5, 0x76, 0x53, 0x89, 0x70, 0x46, 0x66, 0xe8, 0x85, - 0xa1, 0xd6, 0x29, 0x79, 0x89, 0x21, 0x21, 0x9a, 0x8f, 0xb0, 0xf6, 0x9e, 0xa3, 0x88, 0x1d, 0xed, 0x5a, 0x15, 0x9e, - 0x5c, 0x9f, 0xa2, 0x6e, 0xc3, 0xd5, 0x69, 0xda, 0xe9, 0x8e, 0xed, 0x67, 0x18, 0xa1, 0x65, 0x05, 0xc3, 0x76, 0xd4, - 0x69, 0xf5, 0xa6, 0xdb, 0x75, 0x4a, 0xec, 0x8c, 0xcf, 0x45, 0xbd, 0xb9, 0xc2, 0x86, 0xa4, 0x8b, 0x5e, 0x76, 0xf3, - 0xa6, 0x5b, 0x86, 0x46, 0xac, 0xd3, 0x21, 0xbe, 0x9f, 0xa1, 0x5d, 0xae, 0xd3, 0x12, 0xb7, 0x67, 0x78, 0xfe, 0x91, - 0x68, 0x57, 0x53, 0x97, 0x17, 0xba, 0xb9, 0x3a, 0x52, 0x9d, 0x28, 0x36, 0xc8, 0xd7, 0xb4, 0x11, 0x35, 0x8f, 0x09, - 0xd2, 0x5d, 0x5b, 0x31, 0xab, 0x44, 0xe2, 0x56, 0xcf, 0x2a, 0x3c, 0x37, 0xad, 0x14, 0x8e, 0xc0, 0xd9, 0xe9, 0xb4, - 0xac, 0x30, 0x42, 0xd7, 0xc7, 0x55, 0xe2, 0x77, 0x46, 0xca, 0x7d, 0x1f, 0x2b, 0xac, 0x69, 0x77, 0x14, 0x9c, 0x4c, - 0xf6, 0x9b, 0x7e, 0xee, 0x6e, 0x95, 0xf6, 0x1b, 0xdf, 0x86, 0xf9, 0xd7, 0x12, 0x04, 0x74, 0xe7, 0x87, 0x1a, 0x81, - 0x06, 0x81, 0xe7, 0x15, 0x94, 0xfa, 0x9d, 0x6a, 0x3e, 0x9c, 0x83, 0xaa, 0xa5, 0x70, 0x34, 0x3a, 0x8d, 0xc2, 0xf8, - 0xe1, 0x76, 0xe5, 0x2a, 0x8e, 0xb8, 0x89, 0xc2, 0xf8, 0x3b, 0x7c, 0x68, 0x9f, 0x53, 0x19, 0x9a, 0x19, 0xff, 0xee, - 0xa5, 0xc1, 0x3e, 0xac, 0x15, 0xe4, 0x15, 0x7e, 0x07, 0x9a, 0xbb, 0xbf, 0x7c, 0x0d, 0xef, 0xeb, 0x7b, 0xca, 0x13, - 0xce, 0xcb, 0xef, 0x14, 0xd4, 0x89, 0x50, 0x5d, 0x7e, 0x67, 0x4c, 0x31, 0x48, 0x7d, 0xc1, 0x0a, 0x9f, 0xf0, 0x57, - 0x8c, 0x77, 0x08, 0xaf, 0xcc, 0x33, 0x5a, 0xec, 0x58, 0xd1, 0x76, 0x79, 0x2c, 0xb0, 0x9e, 0x94, 0xaa, 0x28, 0xec, - 0xd2, 0xb5, 0x5d, 0xb4, 0x34, 0xca, 0x18, 0x7b, 0x2c, 0x41, 0xf2, 0x42, 0xee, 0xec, 0xe8, 0xa8, 0x14, 0xc6, 0xc8, - 0xae, 0x4c, 0x39, 0x61, 0xc4, 0x16, 0x30, 0x7d, 0x93, 0xac, 0x80, 0x12, 0x89, 0xf7, 0x91, 0xb8, 0x1d, 0x69, 0x91, - 0x94, 0xc3, 0x5e, 0x2b, 0xb7, 0x1c, 0x1d, 0xfd, 0xba, 0x8a, 0x30, 0xe4, 0x75, 0xc7, 0x29, 0x5f, 0x75, 0x01, 0xf5, - 0x4a, 0xd0, 0x4b, 0xd4, 0x0a, 0xa6, 0x96, 0xca, 0x23, 0xa8, 0x68, 0x2d, 0x02, 0x03, 0x0d, 0x2f, 0x0a, 0x0b, 0xca, - 0x05, 0x5f, 0xc0, 0x42, 0x31, 0xec, 0x39, 0x0a, 0x84, 0xe9, 0x93, 0x82, 0x7c, 0x2b, 0x0a, 0x8c, 0x81, 0x8c, 0x0f, - 0xe8, 0x78, 0x2f, 0xe3, 0x9b, 0x06, 0x38, 0x4d, 0x28, 0x91, 0xf1, 0x20, 0x17, 0xc1, 0xef, 0xe4, 0x98, 0xc1, 0x23, - 0xa9, 0xcd, 0x67, 0x77, 0xca, 0xb1, 0x17, 0xcf, 0x80, 0x2e, 0x35, 0x26, 0x3b, 0x2b, 0x38, 0x0d, 0x3a, 0x64, 0x1d, - 0x93, 0xf9, 0xb0, 0xe8, 0x91, 0x69, 0x7c, 0x25, 0x27, 0x47, 0x9f, 0xe8, 0xc3, 0x4b, 0xfa, 0x38, 0xf1, 0xaf, 0x1d, - 0xe0, 0x55, 0x22, 0x21, 0x1a, 0x55, 0x69, 0x18, 0x31, 0x87, 0xbd, 0x97, 0xec, 0x52, 0xc6, 0xca, 0x89, 0xa1, 0x94, - 0x04, 0x1b, 0xde, 0xe1, 0x9e, 0xe6, 0xcd, 0xf4, 0x56, 0x1c, 0xf6, 0x9b, 0xe9, 0x96, 0x7f, 0xa1, 0xe2, 0xd1, 0xc2, - 0x5f, 0xd2, 0xdf, 0x25, 0x6a, 0xee, 0x39, 0xdf, 0x34, 0xb6, 0x23, 0x2e, 0x50, 0xac, 0xa1, 0xfe, 0x3a, 0x2c, 0x9d, - 0x75, 0x20, 0x38, 0xe0, 0x2d, 0x76, 0xd5, 0x30, 0xfe, 0xae, 0xd1, 0xd3, 0xee, 0x6b, 0x49, 0xa3, 0x94, 0xfb, 0x41, - 0x50, 0x0e, 0x76, 0xaf, 0x5d, 0x34, 0x7f, 0xfb, 0x6d, 0x40, 0x41, 0x85, 0xce, 0x0d, 0xb6, 0x93, 0xcd, 0xc2, 0xda, - 0x18, 0x07, 0x75, 0x70, 0x55, 0xc5, 0x09, 0x46, 0x50, 0xa7, 0xf1, 0x27, 0x9b, 0x4d, 0xab, 0x52, 0x02, 0x54, 0xae, - 0x63, 0xc4, 0x1e, 0xc0, 0x13, 0x8d, 0x71, 0x03, 0xdc, 0x66, 0x74, 0xb8, 0x83, 0xa6, 0xcb, 0x18, 0xa4, 0x1d, 0x66, - 0xa3, 0xe8, 0x9a, 0x3a, 0x7d, 0x81, 0xf9, 0x50, 0x94, 0x94, 0x0f, 0xe5, 0x2f, 0x9e, 0xb3, 0x7f, 0xec, 0xb0, 0xe6, - 0xae, 0x7c, 0x40, 0xcc, 0x9c, 0xeb, 0xb4, 0xa8, 0x09, 0x3a, 0x45, 0xbe, 0x57, 0x0f, 0x25, 0xc6, 0x4b, 0xe0, 0x4d, - 0x07, 0xb3, 0x5b, 0x27, 0xfa, 0xe0, 0x12, 0xd4, 0x5c, 0xd9, 0xb8, 0x60, 0xae, 0xb6, 0x98, 0x5a, 0x3b, 0x68, 0xa5, - 0xc4, 0x28, 0x34, 0x7c, 0x2a, 0xb4, 0xf9, 0xff, 0xe0, 0x4a, 0x50, 0xab, 0x8d, 0xdb, 0xfe, 0x42, 0xbf, 0x55, 0x2d, - 0x59, 0xa4, 0x68, 0x72, 0x02, 0x43, 0xd0, 0x7f, 0x45, 0xcd, 0xef, 0x27, 0x0b, 0x0b, 0xf4, 0x22, 0x61, 0xaa, 0x84, - 0x41, 0xd0, 0xf6, 0xae, 0x42, 0x15, 0x40, 0x81, 0xbf, 0xfe, 0x6c, 0x93, 0xe5, 0x0b, 0xd9, 0xcd, 0xf6, 0x34, 0x71, - 0x16, 0xeb, 0x25, 0x81, 0x9c, 0x99, 0x36, 0xd8, 0xe5, 0x66, 0xfa, 0x92, 0xf1, 0xd4, 0xd4, 0xe0, 0x86, 0xb8, 0x82, - 0x1c, 0x68, 0x73, 0x48, 0x05, 0x3e, 0x96, 0x42, 0x20, 0x92, 0xf9, 0x2b, 0x41, 0xb5, 0x63, 0x05, 0x72, 0x2c, 0xf1, - 0x09, 0xe9, 0x49, 0x5a, 0x63, 0xcc, 0x2f, 0x9d, 0x66, 0x3f, 0x57, 0x08, 0xee, 0xdf, 0xd9, 0x6c, 0xa3, 0xca, 0x93, - 0xdc, 0xfb, 0x96, 0xda, 0xbf, 0xb7, 0x82, 0x4a, 0xc9, 0xdb, 0x68, 0x54, 0x3c, 0x8d, 0x37, 0x4d, 0xf9, 0x81, 0xa0, - 0x05, 0x60, 0x17, 0x95, 0x9b, 0x2a, 0xe1, 0x98, 0xb0, 0x90, 0x3a, 0xd2, 0x31, 0xd0, 0x65, 0x5d, 0xaf, 0xe4, 0x44, - 0xe8, 0xf6, 0x60, 0x78, 0x99, 0x53, 0x23, 0x9e, 0x4a, 0xed, 0xc8, 0xeb, 0x24, 0x3a, 0xa0, 0xf2, 0xd0, 0x50, 0xf5, - 0x6a, 0xe5, 0x61, 0x78, 0x99, 0xe9, 0x88, 0xbf, 0x4b, 0xf3, 0x93, 0xea, 0x7e, 0xd9, 0x79, 0x56, 0xbb, 0xbd, 0xb5, - 0x46, 0x54, 0xa2, 0xe6, 0x38, 0x44, 0x48, 0xb8, 0x4f, 0x24, 0x37, 0xb3, 0xa1, 0x7d, 0xe0, 0x09, 0xb8, 0x1c, 0x59, - 0x02, 0xaa, 0x08, 0x9a, 0x24, 0xdd, 0x85, 0xea, 0x15, 0x5a, 0x06, 0xca, 0x1b, 0xb5, 0x0f, 0xa2, 0xc3, 0x46, 0xf3, - 0x53, 0x86, 0x19, 0x56, 0x94, 0x45, 0xf3, 0xc1, 0xc5, 0x20, 0x0b, 0xdc, 0xb8, 0x1c, 0x78, 0x31, 0x51, 0xe5, 0x62, - 0xc4, 0x70, 0xff, 0x58, 0xaa, 0x6c, 0x76, 0x37, 0x9c, 0x57, 0xad, 0x33, 0x02, 0x5d, 0xb2, 0x6b, 0xbd, 0xd4, 0x54, - 0x77, 0x90, 0xac, 0x0c, 0xd3, 0x6b, 0x27, 0x93, 0xae, 0xa0, 0x43, 0x7c, 0x76, 0x83, 0x43, 0x69, 0x49, 0x7a, 0x0e, - 0x0d, 0xb6, 0xa4, 0x44, 0x47, 0x40, 0x34, 0xf9, 0x61, 0xb0, 0x2d, 0xb2, 0xa3, 0x4b, 0x33, 0xc5, 0x36, 0x72, 0xa8, - 0x2b, 0x82, 0x5a, 0x25, 0x74, 0xdc, 0x3f, 0x23, 0xb6, 0xf5, 0x45, 0xbf, 0x21, 0x19, 0x6e, 0x50, 0x12, 0x3c, 0x6e, - 0x87, 0xc8, 0xea, 0xe0, 0x38, 0x0f, 0x8f, 0x16, 0x9c, 0x9d, 0x79, 0xfe, 0xaa, 0x2c, 0x7f, 0xab, 0xb5, 0x8c, 0xc0, - 0x47, 0x77, 0x51, 0x36, 0xd9, 0x72, 0xfb, 0x8e, 0x31, 0x9e, 0xbc, 0xa6, 0x17, 0xe8, 0x16, 0x36, 0x8e, 0xfb, 0x15, - 0x8c, 0x8d, 0xe0, 0x4e, 0xa2, 0x4d, 0x2d, 0xf5, 0x49, 0xad, 0xbe, 0x36, 0xea, 0xe6, 0x19, 0xf9, 0xed, 0x20, 0xf9, - 0xdd, 0xb5, 0x3d, 0xd2, 0xdb, 0xaf, 0xac, 0x93, 0x65, 0xa4, 0x9a, 0x60, 0x13, 0xcb, 0x7d, 0x4d, 0x30, 0x79, 0xb0, - 0x98, 0x5d, 0x40, 0x83, 0x2b, 0xf5, 0x08, 0xef, 0x9e, 0x16, 0xb8, 0x55, 0x51, 0xed, 0xf8, 0x24, 0xc4, 0xe4, 0x39, - 0xd1, 0x97, 0x9a, 0x4d, 0xec, 0x07, 0x57, 0xf4, 0x60, 0x66, 0x3d, 0xaa, 0x0a, 0x57, 0x0b, 0x73, 0x0d, 0x60, 0x6b, - 0xd9, 0xd5, 0x11, 0xc1, 0xe2, 0x10, 0x20, 0xe8, 0xd3, 0x2b, 0x5a, 0xfb, 0x5e, 0x18, 0x84, 0x62, 0x3c, 0xf6, 0x4b, - 0x72, 0x56, 0xc5, 0x10, 0x3e, 0x58, 0x65, 0xf4, 0xda, 0x4b, 0x91, 0x8a, 0xe7, 0x88, 0x6e, 0x15, 0x9c, 0x95, 0x53, - 0x42, 0xc8, 0x0c, 0x80, 0x3c, 0xf0, 0x19, 0xe4, 0xf3, 0x58, 0x7c, 0x65, 0xaf, 0xf6, 0xe7, 0xed, 0x2c, 0x95, 0x7d, - 0x87, 0xc2, 0xf0, 0x30, 0x0d, 0xe7, 0xd6, 0x55, 0xee, 0x3b, 0x84, 0x5c, 0xae, 0x58, 0xb1, 0x69, 0xa4, 0x79, 0x92, - 0x6b, 0xd4, 0x1f, 0x6d, 0x7a, 0xaf, 0x51, 0x38, 0xe5, 0xd1, 0xb9, 0x50, 0x45, 0x51, 0x8d, 0x70, 0x2c, 0x55, 0xf5, - 0x14, 0x0d, 0x82, 0xae, 0x57, 0x6f, 0x55, 0xd2, 0x8c, 0xaf, 0xdc, 0x18, 0x9f, 0x9a, 0x95, 0xf2, 0xbc, 0x6c, 0xb2, - 0x5a, 0x05, 0x75, 0xf0, 0x51, 0x9d, 0x6a, 0x2c, 0x37, 0xeb, 0x27, 0x08, 0x66, 0x5c, 0x9c, 0x46, 0x27, 0x2a, 0x96, - 0x51, 0x57, 0x99, 0xc9, 0xf4, 0xc9, 0xd1, 0xd8, 0x28, 0xe1, 0xb4, 0x55, 0x97, 0xb0, 0xc2, 0xcd, 0x09, 0x5b, 0x4e, - 0xe7, 0x1f, 0x46, 0xb0, 0x8e, 0x56, 0x48, 0xc1, 0x40, 0xb2, 0x15, 0xfb, 0x10, 0x0c, 0x7c, 0xbd, 0x02, 0xd2, 0x82, - 0x29, 0x62, 0x5f, 0xba, 0x8c, 0x32, 0x27, 0x62, 0x03, 0x47, 0xcc, 0x5a, 0x04, 0x46, 0xff, 0x43, 0x54, 0xd2, 0x9f, - 0xc5, 0x08, 0xb8, 0x49, 0x57, 0xa1, 0x73, 0xe7, 0xcd, 0xa3, 0x22, 0x5c, 0x3e, 0xf2, 0xe8, 0x16, 0x63, 0x31, 0xfe, - 0xeb, 0x93, 0x98, 0x40, 0xcc, 0x29, 0xc5, 0xd3, 0x05, 0xa6, 0x7f, 0x09, 0x4f, 0xc8, 0x83, 0xd0, 0xa5, 0x9d, 0x93, - 0x18, 0x25, 0x7b, 0xe4, 0x41, 0xfd, 0x89, 0x76, 0x89, 0x9a, 0xfc, 0x00, 0x33, 0x32, 0x25, 0xe5, 0xa3, 0xa5, 0xf6, - 0xd3, 0xcb, 0x01, 0x55, 0xf0, 0xbe, 0x8a, 0xdb, 0x48, 0xf8, 0x3e, 0x8b, 0x87, 0x8b, 0xf1, 0xe6, 0xe1, 0x06, 0x6f, - 0xeb, 0x1e, 0x14, 0xe6, 0x76, 0x95, 0xb1, 0x81, 0x30, 0x5e, 0x23, 0x74, 0xd0, 0xeb, 0xf6, 0x7b, 0xfc, 0x57, 0xff, - 0x51, 0x1c, 0x60, 0x24, 0x4e, 0x68, 0x97, 0x93, 0x35, 0x79, 0x94, 0x4b, 0xfa, 0xc4, 0x49, 0xdf, 0xe8, 0x74, 0xdf, - 0x71, 0xff, 0xa8, 0x03, 0x2b, 0x1e, 0x6e, 0xe5, 0x2b, 0x4d, 0x8a, 0x3b, 0x61, 0x55, 0x7b, 0x2f, 0x23, 0x34, 0xb8, - 0x89, 0xbe, 0xb0, 0xe4, 0x3b, 0x4c, 0xcd, 0xae, 0xb5, 0xb8, 0x94, 0xe1, 0x3d, 0x04, 0xaf, 0x74, 0x69, 0xe2, 0x60, - 0x8c, 0x77, 0x3c, 0x5b, 0x19, 0x1f, 0x2b, 0xeb, 0x63, 0x10, 0x24, 0x58, 0x21, 0x8f, 0x40, 0x04, 0xca, 0xc7, 0x9f, - 0x45, 0x9e, 0x82, 0xf5, 0xc2, 0x24, 0x0a, 0x65, 0xa8, 0x30, 0x60, 0x11, 0x48, 0x01, 0x8f, 0xda, 0x0b, 0x3d, 0x88, - 0x87, 0x98, 0x7b, 0x32, 0x13, 0x30, 0xb7, 0xcf, 0x3f, 0x20, 0x9a, 0x7b, 0xea, 0x4e, 0x2f, 0x39, 0xa8, 0xc1, 0x89, - 0x3d, 0x7c, 0x5c, 0xab, 0x73, 0x38, 0x46, 0x03, 0xab, 0x71, 0x82, 0xa7, 0xf3, 0xbe, 0xa3, 0x59, 0x2a, 0x50, 0x39, - 0x83, 0xc2, 0xf0, 0x9b, 0xbd, 0x4d, 0xaf, 0xe4, 0xbd, 0x65, 0x56, 0xd5, 0x4d, 0x98, 0x07, 0x79, 0x5c, 0x23, 0xae, - 0x0e, 0xef, 0x1f, 0x82, 0xcb, 0xa2, 0xf5, 0x83, 0x2e, 0x88, 0xc3, 0xbb, 0x6d, 0x19, 0x15, 0x6a, 0x0d, 0x3f, 0x7c, - 0x1c, 0xac, 0x23, 0x41, 0x9d, 0x74, 0x16, 0x02, 0x06, 0xf6, 0xd4, 0x51, 0x45, 0xd7, 0x18, 0xa4, 0x4e, 0x47, 0x15, - 0x5d, 0x73, 0xb7, 0xcd, 0xe5, 0x40, 0x01, 0x6b, 0x0a, 0xb1, 0xef, 0xe6, 0xc7, 0xe1, 0xf5, 0xc3, 0x85, 0x88, 0x43, - 0x57, 0x0f, 0x37, 0xca, 0x66, 0x50, 0xf7, 0xda, 0x5c, 0x26, 0x76, 0xbb, 0x2f, 0x6b, 0xfd, 0x72, 0xbc, 0xf4, 0x6d, - 0xa7, 0x39, 0xa7, 0xee, 0x2b, 0x5d, 0xf7, 0xb5, 0x5d, 0x37, 0x8f, 0x5c, 0xaf, 0x6a, 0x35, 0x07, 0x5c, 0x82, 0x2a, - 0xd6, 0xe7, 0x22, 0xaf, 0x56, 0xa5, 0x2a, 0x41, 0x2b, 0x8c, 0xeb, 0xe0, 0xca, 0x6f, 0x25, 0xc3, 0x2a, 0x2e, 0x16, - 0x79, 0xfa, 0x86, 0xe5, 0x5a, 0x5c, 0x1c, 0x7d, 0x96, 0x4c, 0x31, 0x9d, 0x62, 0xce, 0x36, 0x71, 0x44, 0x61, 0x62, - 0xd1, 0x3a, 0x49, 0x95, 0xe1, 0xc0, 0xd4, 0x0a, 0x50, 0x3c, 0x57, 0xe8, 0xd4, 0x2e, 0xf4, 0xaf, 0xc7, 0xc6, 0x99, - 0x2f, 0x4a, 0x64, 0x40, 0xb7, 0x7e, 0x60, 0xeb, 0x3a, 0x29, 0xe2, 0x61, 0xde, 0xf6, 0xfb, 0xeb, 0xda, 0x10, 0xc8, - 0x6e, 0xd9, 0x11, 0x6b, 0x1c, 0x96, 0xda, 0x5d, 0xaa, 0x42, 0xd8, 0x17, 0xc1, 0xcf, 0x88, 0x3b, 0xda, 0x03, 0x21, - 0x8f, 0xce, 0x82, 0x39, 0x8c, 0x58, 0x59, 0x76, 0x28, 0xd7, 0xe0, 0xb2, 0x70, 0x05, 0x5c, 0x64, 0x74, 0x3b, 0xd2, - 0x41, 0x4b, 0xbb, 0xc7, 0x86, 0x73, 0x34, 0x74, 0x2f, 0x74, 0x8f, 0xfd, 0x89, 0x11, 0x2c, 0x16, 0x96, 0x60, 0x31, - 0x19, 0xcc, 0xde, 0xdb, 0x2c, 0x18, 0x1c, 0x00, 0x8f, 0xba, 0x0d, 0xb4, 0x6e, 0x89, 0x31, 0xad, 0xe6, 0xf9, 0xdc, - 0xdb, 0x44, 0xf5, 0x43, 0x35, 0xd2, 0xb0, 0x19, 0x1e, 0xa6, 0x66, 0x2e, 0x36, 0xf0, 0x68, 0x1d, 0x39, 0xf5, 0xc3, - 0x54, 0xb1, 0xd6, 0x25, 0x76, 0x83, 0xc4, 0x14, 0xbc, 0xc4, 0x92, 0x64, 0x4e, 0x05, 0x49, 0x65, 0x34, 0xdf, 0xa8, - 0xc9, 0x0b, 0x4b, 0x27, 0x80, 0x94, 0x4e, 0x7f, 0xf4, 0x38, 0xd0, 0xe5, 0x1e, 0x3d, 0x1e, 0xe0, 0xb5, 0x4d, 0xa4, - 0xcb, 0xcd, 0x64, 0x35, 0xae, 0xfc, 0x87, 0x66, 0x61, 0x3c, 0xb2, 0x16, 0x09, 0x22, 0xfe, 0x1d, 0xfb, 0x03, 0x5c, - 0xb8, 0x29, 0xbf, 0x9c, 0x2c, 0xee, 0x29, 0xbf, 0xa0, 0xe8, 0x49, 0x3a, 0x42, 0xac, 0x59, 0x54, 0x14, 0xbb, 0xaf, - 0xd1, 0x0f, 0x33, 0xbb, 0xcb, 0x1e, 0xde, 0x00, 0x2c, 0xac, 0x65, 0xab, 0x7b, 0x0e, 0x7d, 0x34, 0x55, 0xa0, 0x1d, - 0x94, 0xdf, 0x93, 0x19, 0xa0, 0x37, 0x43, 0x12, 0x02, 0x34, 0xb2, 0x6d, 0xbb, 0xfb, 0x6d, 0xe7, 0xac, 0x63, 0x25, - 0x4e, 0x3b, 0x9b, 0xab, 0x13, 0x0c, 0xd2, 0x1a, 0xc3, 0xa0, 0x9f, 0xd9, 0x0f, 0x7a, 0x5b, 0x65, 0xb8, 0x3c, 0x7a, - 0xc4, 0xf5, 0xb2, 0x76, 0x4b, 0x77, 0xe0, 0x1a, 0x7a, 0x93, 0x30, 0x94, 0xbd, 0x5b, 0x47, 0x17, 0x17, 0xa2, 0x3f, - 0x32, 0x83, 0x05, 0x7c, 0x39, 0x4a, 0x07, 0x0f, 0x4e, 0xf5, 0x46, 0x9f, 0x9b, 0xee, 0x2e, 0x93, 0xbd, 0x8e, 0xbb, - 0x31, 0x6c, 0xcc, 0xc6, 0x4e, 0xdd, 0x8d, 0x6d, 0x74, 0xd0, 0xda, 0x96, 0x85, 0x7e, 0x8a, 0x03, 0xbe, 0x58, 0xb6, - 0xdc, 0x8e, 0xa0, 0xf2, 0x97, 0xe2, 0x85, 0xd8, 0xd1, 0xf6, 0xea, 0xd3, 0x51, 0x5e, 0xb7, 0x7b, 0x14, 0x17, 0x32, - 0xcb, 0xf7, 0x8a, 0x21, 0x4a, 0xac, 0x1b, 0x10, 0x2c, 0x06, 0xcc, 0xb8, 0x9a, 0xae, 0x19, 0xd7, 0xb7, 0x84, 0xb7, - 0xc6, 0x44, 0x8a, 0xb4, 0x32, 0xb6, 0x07, 0x6f, 0x50, 0x4c, 0x26, 0x41, 0x3a, 0x99, 0x08, 0x64, 0xea, 0x7d, 0x72, - 0x43, 0xdb, 0x3d, 0x3f, 0x6d, 0xfd, 0x88, 0xa5, 0xc6, 0x51, 0xd1, 0xf0, 0xf6, 0xcb, 0x3c, 0xb6, 0xc6, 0x95, 0x6d, - 0x19, 0x0c, 0xb9, 0xc2, 0x66, 0x6b, 0xbc, 0x61, 0x10, 0x87, 0x5e, 0xd5, 0xa2, 0xe4, 0xef, 0x7e, 0x26, 0xd2, 0xf0, - 0xd6, 0x96, 0x0e, 0x9a, 0x5b, 0x56, 0x04, 0x85, 0x96, 0x0b, 0xfa, 0x1f, 0x77, 0x45, 0x04, 0x83, 0xdf, 0x33, 0x50, - 0x91, 0x8b, 0xa5, 0xda, 0x20, 0x0a, 0x52, 0xef, 0x1e, 0x53, 0xdd, 0xc0, 0x04, 0x08, 0x6f, 0x18, 0x20, 0xf2, 0x98, - 0xc2, 0xdd, 0x50, 0xee, 0x85, 0x3f, 0xd6, 0x7c, 0x2f, 0x41, 0x7d, 0xcd, 0x61, 0x92, 0x88, 0x82, 0xb0, 0x7d, 0x44, - 0x70, 0x05, 0x47, 0xee, 0x65, 0x70, 0x11, 0x50, 0xb0, 0x71, 0x9a, 0x46, 0x20, 0x1c, 0xb3, 0xc5, 0x69, 0x3a, 0x5b, - 0x8c, 0xa3, 0x84, 0x0c, 0x23, 0xd6, 0x20, 0xfc, 0x2d, 0x64, 0x02, 0x81, 0x1b, 0x51, 0x3a, 0x20, 0x82, 0xc6, 0xc6, - 0x9e, 0xbc, 0x2c, 0x0d, 0x2e, 0x36, 0x90, 0x34, 0x66, 0xc9, 0x22, 0x74, 0x16, 0xad, 0x1b, 0x8c, 0xc2, 0x14, 0x5c, - 0x46, 0xe5, 0xd9, 0xf5, 0x39, 0xfd, 0x73, 0x77, 0x47, 0x00, 0xd8, 0xe1, 0xae, 0x0d, 0xae, 0x12, 0x42, 0x7a, 0xbb, - 0x80, 0x7c, 0xc6, 0xd2, 0x25, 0xb8, 0x89, 0xde, 0x40, 0xeb, 0x0e, 0xbf, 0xf5, 0xd0, 0x73, 0xf6, 0xf0, 0x3d, 0xa2, - 0x21, 0xde, 0x44, 0x97, 0x19, 0xb0, 0x7c, 0x97, 0x1c, 0x82, 0xf0, 0x12, 0x8d, 0x81, 0x6e, 0xd0, 0x03, 0xf6, 0x4d, - 0x74, 0x41, 0xbe, 0x62, 0x07, 0xd0, 0x46, 0xca, 0x88, 0xad, 0xe7, 0xf3, 0x65, 0xad, 0x16, 0xe1, 0xe6, 0x74, 0x39, - 0x1b, 0x8f, 0x37, 0xfe, 0x36, 0x5a, 0x63, 0x3c, 0x18, 0xa8, 0x77, 0xcb, 0xf5, 0xe2, 0x1f, 0x6f, 0xb0, 0xe6, 0x2d, - 0xd4, 0x3c, 0x8e, 0x2e, 0x10, 0x6f, 0x89, 0x0c, 0xb8, 0x6e, 0x80, 0xf3, 0xe0, 0x5f, 0x6f, 0xb4, 0x18, 0x41, 0x81, - 0x7c, 0x11, 0x18, 0x71, 0x65, 0x9e, 0xdf, 0xa0, 0x07, 0xc6, 0x02, 0x6d, 0x5b, 0xb5, 0x45, 0xfc, 0x6d, 0x64, 0x00, - 0xbf, 0x20, 0xf3, 0xa7, 0x28, 0xd6, 0x8f, 0x70, 0x76, 0x7c, 0x88, 0xde, 0x46, 0x4f, 0x3c, 0xe1, 0xa4, 0xab, 0xb3, - 0xb7, 0xe7, 0x28, 0x1e, 0x0a, 0x3f, 0x1d, 0xf3, 0x63, 0x6b, 0x30, 0x80, 0x88, 0xc9, 0xfc, 0xe0, 0x61, 0xd4, 0xa4, - 0x98, 0x7e, 0x61, 0xbc, 0x1d, 0xc5, 0x6c, 0x7e, 0xf0, 0x6e, 0x7d, 0xcd, 0x6f, 0x7e, 0xf0, 0x3e, 0xf9, 0xec, 0x05, - 0x58, 0x87, 0x95, 0x54, 0x58, 0x03, 0xef, 0xa0, 0x2f, 0x61, 0x0c, 0x5c, 0xbd, 0x7b, 0x19, 0xea, 0x5a, 0x8e, 0xd8, - 0x77, 0xa5, 0xdf, 0xc7, 0xdf, 0x63, 0x06, 0x7a, 0x01, 0x19, 0x38, 0x7c, 0x4e, 0xc3, 0x9e, 0xb4, 0xee, 0xb9, 0xdf, - 0xd9, 0x77, 0xbc, 0xa7, 0xd4, 0x47, 0x4e, 0x8f, 0x81, 0x74, 0x3d, 0x49, 0x35, 0x4b, 0x30, 0x47, 0x8d, 0x6b, 0xd8, - 0x65, 0x20, 0xf8, 0xf3, 0x08, 0x59, 0xcb, 0x8a, 0x05, 0xdf, 0xfe, 0x0a, 0x47, 0xf0, 0xca, 0x35, 0xe5, 0x72, 0x95, - 0x91, 0x48, 0x5e, 0xa2, 0x93, 0x49, 0xe3, 0xcf, 0x9c, 0x56, 0x58, 0x5a, 0xcd, 0x71, 0xf3, 0xd0, 0xe6, 0xe3, 0x54, - 0xd3, 0xfe, 0x2e, 0x41, 0xaa, 0x5d, 0xa5, 0xe5, 0xfc, 0xc6, 0x96, 0x74, 0x61, 0x33, 0x1e, 0xfb, 0x21, 0x37, 0x47, - 0x9a, 0x61, 0x8f, 0x85, 0xfa, 0xa2, 0xa7, 0x78, 0x42, 0xf3, 0x51, 0x15, 0xe6, 0xd9, 0xfd, 0xe6, 0x40, 0xfb, 0xe7, - 0x27, 0x93, 0x34, 0xa4, 0x60, 0x95, 0x56, 0x94, 0x22, 0x87, 0xb0, 0xf7, 0xa7, 0x49, 0x52, 0xb1, 0x80, 0x18, 0xba, - 0xfb, 0xad, 0xfb, 0x2c, 0x04, 0xe4, 0x9a, 0x6e, 0xb5, 0xf1, 0xb2, 0x32, 0xed, 0x5c, 0x58, 0x9f, 0x1e, 0x1f, 0x1d, - 0xa5, 0xa7, 0xc7, 0xf3, 0x34, 0x6c, 0x30, 0x70, 0x51, 0xfa, 0xe4, 0x78, 0xde, 0x70, 0x94, 0xd4, 0x21, 0xc7, 0x18, - 0x3d, 0xaf, 0x2a, 0xb4, 0x4f, 0xf3, 0x04, 0x5d, 0x91, 0x1a, 0x1d, 0x39, 0xd6, 0x98, 0x31, 0x12, 0xee, 0xb0, 0x32, - 0xed, 0xd4, 0x56, 0x07, 0x78, 0xf3, 0x6a, 0x4c, 0x10, 0x96, 0xab, 0xbe, 0x71, 0x41, 0xd0, 0xd0, 0x45, 0xaa, 0xdd, - 0x71, 0xab, 0xb0, 0xf3, 0x1c, 0x6d, 0x56, 0xb6, 0x36, 0xc2, 0xad, 0x05, 0x95, 0x51, 0x70, 0x70, 0x18, 0x23, 0xec, - 0x41, 0xf5, 0x8e, 0xa8, 0x76, 0xd2, 0x3d, 0x02, 0x58, 0x61, 0xe2, 0xd4, 0x6a, 0x49, 0x0c, 0x4f, 0x84, 0xba, 0x93, - 0x8e, 0x32, 0x59, 0x4a, 0xb8, 0x5f, 0xc3, 0xe2, 0x5e, 0x85, 0x76, 0x12, 0x22, 0x7e, 0x8b, 0x0c, 0x80, 0x3b, 0x3e, - 0x8e, 0xca, 0x79, 0xe9, 0x68, 0x5d, 0xc6, 0x55, 0x48, 0x08, 0xcd, 0x08, 0xe8, 0xe4, 0xea, 0x20, 0x2a, 0x03, 0x57, - 0x3c, 0xc0, 0xc2, 0xcf, 0x93, 0x87, 0xc5, 0x93, 0xf8, 0x61, 0x3d, 0x8f, 0x1f, 0x15, 0x61, 0xf2, 0xa8, 0x0e, 0x93, - 0x87, 0xf5, 0x69, 0xfc, 0xb0, 0x98, 0x27, 0xf0, 0x1c, 0x3f, 0xaa, 0x5b, 0x5b, 0xd6, 0x1e, 0x1e, 0x09, 0x91, 0x76, - 0xf5, 0x47, 0x0e, 0xd5, 0x7d, 0xca, 0xfc, 0xf0, 0xb0, 0xd1, 0x3b, 0x75, 0xf8, 0xba, 0x5e, 0xa3, 0x66, 0xea, 0xa3, - 0xec, 0x6f, 0xf6, 0x65, 0x61, 0x6f, 0x0d, 0x91, 0xcd, 0x48, 0x27, 0x72, 0x8f, 0x23, 0xde, 0xec, 0x58, 0x61, 0x60, - 0xd8, 0xa4, 0x2a, 0x60, 0xa3, 0x17, 0x14, 0x84, 0x6a, 0xc2, 0xb0, 0x16, 0x53, 0xfb, 0x7c, 0x48, 0x6f, 0xa0, 0xc4, - 0x14, 0x5b, 0x0c, 0x19, 0x7b, 0xc9, 0xfc, 0x24, 0x3c, 0x46, 0xe4, 0x08, 0x92, 0xf1, 0xe1, 0xac, 0x80, 0x03, 0x73, - 0x8d, 0xd0, 0x37, 0xf7, 0xda, 0xba, 0x5c, 0xc1, 0x91, 0x22, 0x63, 0x33, 0x5f, 0x4f, 0x95, 0xf2, 0x03, 0xce, 0x38, - 0x60, 0xd5, 0x2f, 0x23, 0x8d, 0x8a, 0xf2, 0x4c, 0x6f, 0xd6, 0x1b, 0x8c, 0x55, 0xf7, 0x0c, 0xa5, 0x59, 0x3a, 0x76, - 0xe5, 0x80, 0x0d, 0x6e, 0x83, 0x4f, 0xc1, 0x87, 0xe0, 0x6d, 0xf0, 0x20, 0x78, 0x11, 0x7c, 0x0e, 0x1a, 0x82, 0x28, - 0xaf, 0x14, 0x97, 0xe7, 0x5f, 0x44, 0x97, 0x72, 0xf7, 0x28, 0xb0, 0x64, 0x9f, 0xec, 0x7b, 0x9a, 0xc9, 0x26, 0x78, - 0x1b, 0x5d, 0x4c, 0xae, 0x83, 0x17, 0x98, 0x8d, 0x98, 0xe2, 0x31, 0x70, 0xa8, 0x28, 0xc2, 0x72, 0x06, 0x7d, 0x1a, - 0x56, 0x16, 0xb3, 0x68, 0x2a, 0x25, 0x2e, 0xfa, 0x45, 0xd4, 0x30, 0x76, 0x5a, 0x43, 0x95, 0xc8, 0x87, 0xa0, 0xd2, - 0x4f, 0xd1, 0x05, 0xd4, 0xf6, 0x56, 0xdf, 0x11, 0x8d, 0x37, 0x6e, 0x75, 0x0c, 0x66, 0xa5, 0x2b, 0x13, 0x86, 0xfa, - 0xd6, 0x96, 0x04, 0x37, 0x70, 0xa4, 0x61, 0xfb, 0x1e, 0x50, 0xd5, 0xc4, 0xf3, 0x43, 0x95, 0x9f, 0x23, 0xc1, 0x50, - 0x73, 0xeb, 0x13, 0xc3, 0x50, 0x5d, 0x21, 0x8b, 0x08, 0x0f, 0x22, 0x2e, 0x08, 0xa5, 0xb0, 0x0e, 0xfe, 0x0a, 0x54, - 0x79, 0x4b, 0xad, 0xfb, 0x60, 0x2e, 0xb7, 0xac, 0xe6, 0x09, 0x28, 0x30, 0xf1, 0x2a, 0x95, 0x65, 0xe2, 0x48, 0x75, - 0xf3, 0x40, 0x8d, 0x75, 0x4f, 0x1f, 0x3d, 0x1e, 0x4f, 0xff, 0xe2, 0xeb, 0xb2, 0xef, 0xbc, 0x4a, 0x4b, 0xbe, 0xcf, - 0x1c, 0xeb, 0xca, 0x8a, 0xac, 0x2b, 0x7f, 0x8a, 0xaa, 0xb3, 0x67, 0xe7, 0x33, 0xdd, 0x4a, 0x26, 0x32, 0x6c, 0x6e, - 0x0a, 0x2f, 0xfa, 0xe4, 0xf8, 0x27, 0xa0, 0x37, 0xd6, 0x18, 0xab, 0xef, 0xea, 0xe1, 0xfd, 0x34, 0xde, 0xb4, 0x4e, - 0xc3, 0xb7, 0xfb, 0x1b, 0x4e, 0xfd, 0x6c, 0xb4, 0x75, 0xe6, 0xff, 0x72, 0xab, 0x6f, 0x69, 0xee, 0x3e, 0x44, 0xb7, - 0x30, 0x8f, 0xd6, 0x34, 0xc8, 0xf7, 0x95, 0x5d, 0x7e, 0x13, 0x3d, 0xf5, 0x06, 0x39, 0x59, 0x44, 0x35, 0xfa, 0x68, - 0xb8, 0xa1, 0x93, 0xc0, 0xf8, 0x34, 0x2c, 0x1e, 0xe5, 0x88, 0xce, 0x85, 0xec, 0xd9, 0x0d, 0x30, 0x97, 0x37, 0xa7, - 0x8b, 0xd9, 0xcd, 0x38, 0xfa, 0x68, 0x7a, 0xd0, 0xdd, 0x70, 0xc0, 0x72, 0xfd, 0x04, 0x9b, 0xdb, 0xda, 0x92, 0xcf, - 0xfc, 0xe0, 0xfb, 0xd4, 0xdd, 0xa5, 0x90, 0xf4, 0x39, 0x8d, 0x7e, 0x9a, 0xea, 0x60, 0x19, 0xc1, 0xe7, 0x06, 0x1e, - 0x29, 0xea, 0x47, 0xf0, 0x6b, 0x1a, 0x7d, 0x8f, 0xf6, 0xdf, 0xf5, 0x8a, 0x6e, 0xc6, 0x7f, 0x6d, 0xd4, 0xe3, 0x5b, - 0xf1, 0xcd, 0xc1, 0x92, 0xd8, 0x0b, 0x2e, 0x79, 0xd9, 0xc8, 0x23, 0xc7, 0xe2, 0xc8, 0xd4, 0x5b, 0x13, 0x83, 0x96, - 0xaa, 0xb9, 0x68, 0x7a, 0xe9, 0x5c, 0xdf, 0xec, 0x4d, 0xb4, 0x92, 0x1b, 0xe6, 0x1b, 0x74, 0x07, 0x7e, 0x63, 0xc3, - 0x14, 0x6c, 0x23, 0x22, 0x06, 0x6f, 0x02, 0x84, 0x90, 0xcc, 0xe7, 0xb7, 0xd1, 0x87, 0xe8, 0x41, 0xf4, 0x39, 0xda, - 0x86, 0x9f, 0x80, 0x01, 0x84, 0xb5, 0xd2, 0x44, 0xdb, 0x60, 0x29, 0x90, 0xa7, 0xcd, 0xed, 0x49, 0x78, 0x1b, 0x34, - 0xdb, 0x93, 0xf0, 0x53, 0xd0, 0xdc, 0x3e, 0x0e, 0x3f, 0xc0, 0xef, 0xc7, 0xe1, 0xdb, 0x00, 0x92, 0x1f, 0x04, 0x90, - 0xfa, 0x22, 0x80, 0xc4, 0xcf, 0x01, 0xa4, 0x35, 0x0a, 0xe9, 0xe1, 0x73, 0x2a, 0x91, 0x4e, 0x3e, 0x37, 0x81, 0x89, - 0xaa, 0x1b, 0xfe, 0x9a, 0x5a, 0x4f, 0xdc, 0xca, 0xf0, 0xd7, 0x26, 0xd0, 0x7d, 0x0e, 0xd3, 0x34, 0xd0, 0x3d, 0x0e, - 0x2f, 0xf9, 0x8d, 0xe9, 0x57, 0x98, 0xa5, 0xc1, 0x50, 0x4f, 0xc3, 0x8b, 0xa6, 0xed, 0x9c, 0xcc, 0x8e, 0x75, 0xe2, - 0x62, 0xc0, 0x3a, 0xf1, 0x22, 0x58, 0xb6, 0x83, 0xa6, 0x3a, 0xfb, 0xcf, 0x03, 0x7d, 0x04, 0x68, 0xda, 0x5f, 0x8b, - 0x05, 0x0d, 0x88, 0x3b, 0x85, 0xd2, 0x1d, 0x77, 0xe8, 0x7d, 0x6c, 0xd1, 0xfb, 0x40, 0x14, 0x69, 0x49, 0x90, 0x54, - 0x65, 0x5d, 0x53, 0x3c, 0xf1, 0x30, 0xd7, 0x5a, 0xb5, 0x55, 0xc0, 0xea, 0x4c, 0xc4, 0xa4, 0x2f, 0xf9, 0x30, 0x28, - 0xf8, 0x5e, 0x01, 0x4e, 0x84, 0xcd, 0x78, 0x05, 0x47, 0xc2, 0x62, 0x3e, 0x59, 0x85, 0x4b, 0xa0, 0xfc, 0x93, 0x61, - 0xb6, 0xe0, 0x5a, 0xb9, 0x31, 0x69, 0xf1, 0xa9, 0x47, 0xdd, 0xa3, 0xd1, 0x75, 0xb6, 0x58, 0xe4, 0x29, 0xe9, 0xdc, - 0x6a, 0x4d, 0xe6, 0x6f, 0x1d, 0xaa, 0xbe, 0x56, 0x54, 0x1e, 0x19, 0x86, 0x9f, 0x30, 0xd0, 0x0e, 0xc7, 0xbd, 0xc3, - 0x16, 0x53, 0xb8, 0x25, 0xb3, 0xef, 0x6b, 0x9b, 0xae, 0xdf, 0x1a, 0x52, 0xfd, 0x47, 0xab, 0x60, 0x5a, 0x2e, 0xa3, - 0xff, 0xd1, 0x14, 0xfd, 0x79, 0xa0, 0xe8, 0xc6, 0x9f, 0x7d, 0x8a, 0x3e, 0x92, 0x77, 0x02, 0x25, 0x06, 0x5b, 0x78, - 0xba, 0x6d, 0x9d, 0xfa, 0x84, 0x96, 0xff, 0x8f, 0x54, 0x68, 0x53, 0xf3, 0xda, 0x26, 0x8a, 0xb7, 0xd1, 0x00, 0x2d, - 0x5f, 0x5a, 0x34, 0xd1, 0x20, 0x94, 0x7c, 0x8c, 0x5c, 0xa7, 0x68, 0xa4, 0x89, 0xcf, 0xa2, 0xfa, 0xec, 0xe3, 0xf9, - 0xec, 0x36, 0xea, 0x53, 0xc4, 0x8f, 0x03, 0x14, 0xf1, 0x99, 0x3f, 0x5e, 0xb6, 0x5f, 0x1a, 0xd5, 0x41, 0x4a, 0xee, - 0x34, 0x7a, 0x1b, 0xf5, 0xe9, 0xf8, 0xe4, 0x0f, 0x37, 0x7a, 0xfb, 0xd5, 0x8d, 0xb6, 0x9b, 0x3c, 0x3c, 0xf8, 0x66, - 0xe0, 0x5b, 0x69, 0x35, 0xb9, 0x9b, 0x19, 0x05, 0x23, 0x2e, 0x5b, 0x5c, 0xa6, 0x61, 0x62, 0x29, 0x16, 0x31, 0x51, - 0xa3, 0x74, 0xce, 0xf4, 0x59, 0x30, 0xc8, 0xe8, 0x12, 0xa1, 0xbf, 0x04, 0x39, 0xfc, 0xc2, 0x98, 0x6c, 0x5e, 0x9e, - 0x5e, 0x80, 0x1c, 0x7e, 0xe9, 0xef, 0x6e, 0xa2, 0xf8, 0xec, 0xf2, 0x1c, 0x64, 0xf7, 0x1b, 0xde, 0x4f, 0x33, 0xd5, - 0xf9, 0xf2, 0x3e, 0x0e, 0xec, 0x12, 0x3e, 0x6a, 0x05, 0x82, 0xb5, 0x25, 0xce, 0x4b, 0x7f, 0x2c, 0xd7, 0xd2, 0x42, - 0xda, 0xdf, 0xde, 0xaf, 0xa1, 0xb8, 0x44, 0x26, 0xe3, 0xad, 0xad, 0x72, 0x78, 0x11, 0xbd, 0x07, 0xd1, 0x7e, 0xfe, - 0x46, 0x3b, 0xdf, 0xcc, 0xd4, 0xb9, 0xf4, 0x02, 0xb8, 0xbb, 0x9f, 0x60, 0x75, 0xf2, 0x99, 0x02, 0x07, 0x10, 0x2f, - 0xdb, 0x0f, 0x14, 0xc4, 0x89, 0x8f, 0x8a, 0xcf, 0x6e, 0x22, 0x83, 0x42, 0x20, 0x55, 0x80, 0xc3, 0xe8, 0xd3, 0xac, - 0x9a, 0x03, 0xf5, 0xff, 0x00, 0xbb, 0xd3, 0x56, 0x44, 0x5f, 0xc2, 0xd3, 0x05, 0x08, 0xbf, 0x9f, 0x87, 0x6d, 0x7b, - 0x94, 0x5b, 0x9b, 0xf2, 0x78, 0xbb, 0x24, 0x27, 0xac, 0xbd, 0x99, 0x25, 0x97, 0x14, 0x82, 0x6c, 0x7a, 0xed, 0x05, - 0x9a, 0xe2, 0xcc, 0x73, 0x8a, 0xe8, 0x8b, 0x91, 0x99, 0xee, 0xee, 0xae, 0x0e, 0xa9, 0xbe, 0x68, 0xf2, 0xe2, 0xe1, - 0x83, 0xf1, 0x03, 0x72, 0xe1, 0xb2, 0xdc, 0x42, 0x20, 0x3d, 0x6f, 0x3a, 0x62, 0x07, 0x2c, 0xd9, 0x67, 0x98, 0x37, - 0x1c, 0x7a, 0x69, 0xaa, 0xe8, 0xd4, 0x3f, 0x50, 0xf5, 0x9e, 0x9a, 0xc3, 0x81, 0x37, 0xd8, 0x3a, 0x8a, 0x85, 0xfb, - 0xf9, 0x61, 0x84, 0x8a, 0x0e, 0xaa, 0xf5, 0xe8, 0xe8, 0xf0, 0x23, 0x07, 0x94, 0xc6, 0xf9, 0x7e, 0x16, 0x27, 0xbf, - 0x2d, 0xaa, 0x72, 0x8d, 0x47, 0xec, 0x18, 0x3f, 0xf7, 0x50, 0x8b, 0x61, 0x57, 0xbe, 0xef, 0x87, 0x1e, 0x9c, 0xb4, - 0xc0, 0xc0, 0x78, 0x27, 0x93, 0x17, 0xfe, 0xc3, 0x07, 0xc8, 0x3f, 0x11, 0x4e, 0x0a, 0xb9, 0xc4, 0x0e, 0x54, 0xa3, - 0xf6, 0x21, 0xf0, 0x0a, 0x49, 0x03, 0x19, 0x2e, 0x25, 0xfd, 0x9d, 0x42, 0xf6, 0x03, 0x9e, 0x21, 0x57, 0xcd, 0xab, - 0x71, 0x11, 0x03, 0xd7, 0x90, 0x8b, 0xc8, 0x86, 0xcf, 0x54, 0x3d, 0xb0, 0x0e, 0x9f, 0x27, 0xbf, 0x32, 0xff, 0x07, - 0xec, 0xc2, 0x31, 0xfe, 0xc6, 0xa9, 0x99, 0xd5, 0x9f, 0x32, 0x10, 0x9a, 0x60, 0x23, 0xc1, 0x77, 0x40, 0x34, 0x57, - 0x27, 0x03, 0x9c, 0xb3, 0x93, 0x28, 0x4d, 0x1f, 0x3d, 0x9e, 0x5d, 0x56, 0x69, 0xfc, 0xdb, 0x8c, 0xde, 0xc9, 0x4e, - 0x93, 0x77, 0xfc, 0xa6, 0x95, 0x0a, 0x3e, 0x49, 0x79, 0x19, 0x55, 0x38, 0x8f, 0x27, 0xd1, 0x65, 0xe3, 0x96, 0x97, - 0x35, 0xc1, 0xaf, 0xec, 0x17, 0xbc, 0x06, 0x43, 0xb5, 0x02, 0x39, 0x43, 0x78, 0x89, 0x42, 0xbf, 0xa7, 0x2a, 0xf2, - 0xe5, 0x7b, 0xc0, 0x42, 0xb1, 0xed, 0xe8, 0x05, 0x63, 0xca, 0x01, 0x43, 0xc0, 0x0c, 0xc7, 0x65, 0x33, 0xfe, 0x55, - 0xa3, 0x93, 0x08, 0xf8, 0x54, 0x8a, 0x49, 0x72, 0xf3, 0xc0, 0xdc, 0x88, 0x19, 0x40, 0xda, 0x28, 0x6d, 0x7b, 0x2d, - 0x2c, 0x0e, 0x47, 0x57, 0x7d, 0x43, 0x01, 0xcf, 0x80, 0xb3, 0xc1, 0xbd, 0x23, 0xac, 0xc5, 0x67, 0x73, 0x75, 0xac, - 0xdd, 0x86, 0xae, 0xa4, 0xba, 0x9f, 0x24, 0x74, 0x1a, 0xb3, 0x2b, 0xdf, 0xa7, 0xf2, 0xf8, 0x2f, 0xc5, 0x02, 0x69, - 0xaa, 0x86, 0x6c, 0x10, 0x3e, 0xa0, 0xfe, 0x03, 0x37, 0x39, 0x32, 0x4a, 0x4d, 0x15, 0x17, 0x75, 0xce, 0x15, 0x9e, - 0xc1, 0x31, 0x0d, 0x53, 0x27, 0x6d, 0x03, 0x36, 0xc9, 0x44, 0x48, 0x3b, 0xb8, 0x6e, 0xf7, 0x92, 0x7a, 0x03, 0xf5, - 0xcc, 0xec, 0x48, 0x23, 0xec, 0x48, 0x57, 0x73, 0x0f, 0x6b, 0x6b, 0x98, 0x5f, 0xd0, 0x70, 0x01, 0x7a, 0x53, 0xba, - 0xfb, 0x7c, 0xc6, 0xae, 0xcb, 0x6a, 0x5e, 0x4d, 0x88, 0x3a, 0xe2, 0x63, 0x2c, 0xfa, 0x5c, 0xcb, 0xf9, 0x1d, 0x5a, - 0xaf, 0xe8, 0xe2, 0xab, 0x56, 0x07, 0xb1, 0xfd, 0x46, 0x53, 0x9d, 0x5a, 0xfd, 0x46, 0x80, 0x81, 0x7d, 0xc7, 0x43, - 0xd3, 0xeb, 0x67, 0x2a, 0xfd, 0xdc, 0x59, 0x6c, 0x54, 0xa1, 0x98, 0xa7, 0x5a, 0xf3, 0x53, 0xea, 0x56, 0x5f, 0x33, - 0x6e, 0xd5, 0xf0, 0xd9, 0x80, 0x3c, 0xda, 0xb8, 0xa4, 0x38, 0xa3, 0xb6, 0xc6, 0x83, 0x55, 0xd3, 0xc1, 0xca, 0xb9, - 0xf8, 0x60, 0x4f, 0xb3, 0x1a, 0x6f, 0xbc, 0x8c, 0x90, 0x09, 0x85, 0x0b, 0x4d, 0x6c, 0x80, 0xae, 0xc9, 0x58, 0x14, - 0x36, 0xa1, 0xf1, 0x72, 0xfd, 0x3b, 0x58, 0x8d, 0xa3, 0x04, 0xd6, 0x74, 0x88, 0x69, 0x12, 0xe2, 0x01, 0x93, 0x90, - 0x3c, 0xd8, 0xd5, 0x4e, 0xe2, 0x4e, 0xb5, 0x32, 0x92, 0xfb, 0xeb, 0x9d, 0x98, 0x7a, 0x19, 0x2e, 0x79, 0x65, 0x84, - 0x53, 0xa8, 0x3d, 0xb5, 0xfc, 0x94, 0x4d, 0x17, 0x88, 0x13, 0xe8, 0xf6, 0xe0, 0xbf, 0xf0, 0xa9, 0x89, 0xd3, 0x03, - 0xaa, 0xb5, 0xdb, 0x81, 0xff, 0xc2, 0xb8, 0xd8, 0xe6, 0xa2, 0x7e, 0x68, 0x5e, 0xec, 0xcc, 0xe6, 0xca, 0x03, 0x8c, - 0x49, 0xe2, 0x72, 0xf3, 0x14, 0xeb, 0x87, 0x58, 0x9f, 0xa1, 0xdb, 0x0e, 0x5a, 0x29, 0x2e, 0xac, 0x52, 0x37, 0x48, - 0xaf, 0x5d, 0x4a, 0x2d, 0xbc, 0x99, 0xe2, 0xaa, 0xa8, 0x1f, 0x72, 0xff, 0x25, 0x7c, 0xa6, 0xf2, 0x3b, 0x24, 0x4b, - 0x76, 0xe3, 0x57, 0x41, 0x02, 0xab, 0xf2, 0x8d, 0x50, 0xc4, 0xc8, 0x32, 0x02, 0x67, 0x39, 0x56, 0x57, 0xdc, 0xbf, - 0x57, 0xb3, 0x2b, 0x56, 0xbc, 0x75, 0x20, 0xe6, 0xf3, 0xb6, 0xcf, 0x85, 0x88, 0xf4, 0x52, 0xb5, 0x02, 0xda, 0x43, - 0xc7, 0xe1, 0x67, 0x3a, 0xdc, 0xa3, 0x67, 0x5f, 0xdb, 0x34, 0x86, 0xb0, 0x75, 0x02, 0x42, 0x02, 0xfd, 0xe0, 0x2f, - 0x14, 0x01, 0x7b, 0xbe, 0xca, 0xcd, 0xb5, 0x22, 0xac, 0xe2, 0x2f, 0x30, 0x4b, 0xf9, 0xe2, 0x2c, 0xbe, 0x21, 0x4b, - 0xeb, 0xa9, 0x0e, 0x31, 0x89, 0x46, 0xba, 0xf4, 0x84, 0xd8, 0x50, 0x9e, 0xc4, 0xe6, 0xc0, 0x1c, 0x18, 0xca, 0xa5, - 0xac, 0x94, 0x32, 0xf8, 0x3b, 0x25, 0x23, 0xdb, 0xaa, 0xff, 0xc1, 0x0b, 0x32, 0x94, 0x81, 0xbe, 0x6c, 0x85, 0xd6, - 0xf5, 0x76, 0xae, 0x6d, 0x4d, 0xdb, 0x32, 0x2b, 0x16, 0x14, 0xc5, 0x06, 0x91, 0x4f, 0xc4, 0x38, 0x90, 0xe2, 0x9a, - 0x68, 0xbc, 0xb3, 0x27, 0xc0, 0x20, 0xa4, 0xf7, 0xf1, 0x7b, 0xc0, 0x15, 0x1b, 0xb9, 0x3e, 0x3c, 0xa6, 0xb1, 0x45, - 0x65, 0xe2, 0xbd, 0xcd, 0xd6, 0xba, 0xc4, 0xe6, 0x56, 0x69, 0x12, 0x5d, 0x77, 0x05, 0xed, 0x47, 0xe2, 0x3a, 0x31, - 0x38, 0xd7, 0x78, 0x5d, 0x95, 0xa5, 0xaf, 0xb0, 0xcc, 0xb5, 0xcf, 0x92, 0x09, 0x26, 0x75, 0xb8, 0x52, 0xf0, 0xe4, - 0x87, 0x2b, 0xe6, 0x11, 0x49, 0xb3, 0x2d, 0xb3, 0x54, 0x98, 0x1e, 0x44, 0x92, 0x31, 0x40, 0xf8, 0x26, 0x1d, 0x00, - 0x34, 0x92, 0x42, 0x98, 0xca, 0x53, 0x84, 0x62, 0xb6, 0xb7, 0x9a, 0x5e, 0x3a, 0x5a, 0x07, 0x55, 0x93, 0x91, 0xc1, - 0x23, 0x3b, 0x8b, 0x70, 0xbd, 0xc5, 0x94, 0xdc, 0x4e, 0xde, 0x01, 0x07, 0x44, 0xdf, 0x46, 0xd4, 0xa4, 0x8f, 0xa5, - 0x97, 0x4c, 0x11, 0x4d, 0x7d, 0xab, 0xea, 0x80, 0x94, 0x1c, 0x52, 0x72, 0x4e, 0xe1, 0xb6, 0x50, 0x76, 0x6b, 0xb9, - 0x70, 0xe4, 0x55, 0x35, 0xd1, 0x06, 0xb9, 0x5d, 0xfb, 0x0c, 0x68, 0xd4, 0x76, 0x65, 0x91, 0x85, 0xb8, 0x35, 0xb3, - 0x94, 0x3c, 0xe7, 0xdf, 0x16, 0xcf, 0x95, 0x3b, 0xcf, 0xd1, 0x51, 0xec, 0xed, 0x6e, 0x43, 0x68, 0xc1, 0x49, 0xb0, - 0x85, 0x3f, 0xdb, 0x93, 0x36, 0xe0, 0xe7, 0xc7, 0xfc, 0xfc, 0xb8, 0x45, 0x55, 0x49, 0x6a, 0x3c, 0xee, 0x75, 0x89, - 0x46, 0x8a, 0x34, 0xba, 0x4c, 0x23, 0x85, 0x1a, 0x2c, 0xb5, 0x63, 0x96, 0x20, 0xb1, 0x34, 0x36, 0x9f, 0x24, 0x5a, - 0xaa, 0xa5, 0xd2, 0x31, 0xaa, 0x8c, 0xa4, 0xa3, 0xb3, 0xe9, 0x2b, 0x46, 0xba, 0x39, 0x38, 0x19, 0x91, 0x69, 0x69, - 0x57, 0x53, 0xba, 0xd9, 0xd1, 0x82, 0xc9, 0x88, 0x3b, 0xdb, 0xb2, 0x76, 0x13, 0xd5, 0x74, 0xc1, 0x66, 0x6e, 0xb5, - 0x32, 0x73, 0x2b, 0xa3, 0xe2, 0x0b, 0xba, 0xe5, 0x2a, 0xd2, 0x56, 0x66, 0xf3, 0x52, 0xe9, 0x96, 0x69, 0x0f, 0x76, - 0xe8, 0x26, 0x06, 0xcb, 0xbc, 0xa7, 0xaa, 0x63, 0x7b, 0xd3, 0x28, 0xdb, 0x20, 0x5b, 0x11, 0xa3, 0x4e, 0x59, 0xbc, - 0xfc, 0x1d, 0xf6, 0x1e, 0xc8, 0x51, 0x55, 0xd5, 0x18, 0x03, 0x77, 0xa0, 0x25, 0x93, 0x0a, 0x84, 0xa0, 0x95, 0x95, - 0xce, 0x26, 0x54, 0xb1, 0x3f, 0x8e, 0xc9, 0x4c, 0x65, 0x13, 0xa1, 0x41, 0xdd, 0xc2, 0xca, 0x40, 0xd0, 0xc3, 0x5c, - 0x6e, 0x63, 0x25, 0x0b, 0xd5, 0x94, 0x82, 0x79, 0xb4, 0x8a, 0x68, 0xf6, 0x65, 0xb7, 0xa4, 0xd6, 0x6e, 0x91, 0x41, - 0xc0, 0x97, 0xd6, 0x6e, 0x29, 0x65, 0xb7, 0xa4, 0xce, 0x4a, 0x4f, 0xd5, 0x4a, 0xcf, 0x51, 0x01, 0x99, 0xaa, 0x55, - 0xbe, 0x42, 0x58, 0xf8, 0xd4, 0xac, 0xf0, 0xd4, 0xac, 0x70, 0x9a, 0x52, 0x63, 0xff, 0xa0, 0x69, 0x9d, 0x7b, 0x6e, - 0xb9, 0x84, 0x4e, 0x23, 0xbe, 0xf5, 0x08, 0x4c, 0xff, 0x20, 0x9c, 0xc1, 0x3a, 0xce, 0x2a, 0xc2, 0xea, 0x31, 0x30, - 0x82, 0x32, 0x55, 0x8e, 0xf6, 0xcb, 0xc2, 0x92, 0xac, 0x18, 0x4b, 0x72, 0xa7, 0xe6, 0xb9, 0xb2, 0x4c, 0xbc, 0x2a, - 0x06, 0x91, 0xc8, 0xe1, 0x07, 0x5f, 0xc1, 0xaf, 0xe0, 0x97, 0xe1, 0x9a, 0x67, 0x17, 0x19, 0x7c, 0x2b, 0x0f, 0x8e, - 0x09, 0xc3, 0x28, 0xf6, 0x5b, 0xf8, 0x7c, 0x01, 0x9f, 0xe7, 0x7e, 0x7e, 0x44, 0xd3, 0xcb, 0x7d, 0x67, 0x91, 0xc3, - 0xe4, 0x35, 0x14, 0x54, 0x58, 0xc4, 0x4a, 0xbd, 0x7c, 0x19, 0x3e, 0x68, 0x78, 0x34, 0x4a, 0x84, 0xb8, 0x28, 0xc4, - 0xbe, 0xb6, 0x42, 0xa1, 0xa9, 0x30, 0x30, 0xe8, 0x31, 0x2c, 0x6a, 0x62, 0x42, 0x05, 0x84, 0xa4, 0xb4, 0x24, 0x6e, - 0x10, 0x56, 0x5c, 0x73, 0x16, 0x1b, 0x98, 0xe0, 0xee, 0x0e, 0x11, 0x0f, 0xe6, 0x5e, 0x32, 0x86, 0x6e, 0xca, 0x9a, - 0x79, 0x0f, 0x35, 0x13, 0x4c, 0x06, 0xaa, 0x2a, 0xc6, 0x4e, 0x5d, 0x0f, 0xe5, 0x95, 0x31, 0x33, 0x03, 0xd6, 0x85, - 0xca, 0xc2, 0x32, 0x9c, 0x29, 0xcb, 0x3a, 0x02, 0x28, 0xc8, 0x15, 0x40, 0xc1, 0xca, 0x00, 0x14, 0x2c, 0x0c, 0x40, - 0xc1, 0xa6, 0x8d, 0xae, 0x44, 0x87, 0x9b, 0x60, 0xb8, 0x08, 0x1f, 0x47, 0x16, 0x09, 0x2b, 0x56, 0x0f, 0xc3, 0x7b, - 0x0c, 0x47, 0xab, 0x50, 0x9e, 0x42, 0x96, 0xe2, 0x60, 0x35, 0x96, 0x28, 0xb2, 0x5e, 0x79, 0x31, 0xa3, 0xc8, 0x39, - 0x12, 0x89, 0x92, 0xfd, 0x5c, 0xb9, 0x04, 0x26, 0xf6, 0xbc, 0xe5, 0x59, 0xc3, 0x75, 0x39, 0x74, 0x00, 0xf3, 0x96, - 0xef, 0x32, 0x1a, 0x81, 0x4e, 0x95, 0x23, 0xd2, 0x24, 0x28, 0xca, 0x65, 0x52, 0x64, 0x41, 0x98, 0x04, 0xbd, 0x13, - 0xfc, 0x56, 0x50, 0xfe, 0xbf, 0x68, 0x04, 0x8f, 0x70, 0x4c, 0xbc, 0x4b, 0x3e, 0xe3, 0x05, 0x66, 0x11, 0x3d, 0x15, - 0xa3, 0x6c, 0x82, 0x62, 0x84, 0xbf, 0xd3, 0xcf, 0xc1, 0x84, 0xa0, 0xad, 0x9e, 0xd2, 0x15, 0x13, 0xb6, 0x01, 0x5f, - 0xf1, 0x2f, 0x78, 0xa9, 0x43, 0xa8, 0x0c, 0x75, 0x52, 0xb7, 0x0c, 0x24, 0xfe, 0xef, 0x1b, 0x13, 0x13, 0x99, 0xd2, - 0xe6, 0x18, 0x6f, 0x20, 0xa5, 0x78, 0x03, 0x21, 0xe2, 0xaa, 0xe9, 0xcc, 0x5e, 0x89, 0x31, 0x07, 0x42, 0x7c, 0x5d, - 0x0c, 0xbc, 0xbe, 0x67, 0xbc, 0xca, 0xfe, 0xe8, 0xb4, 0x70, 0xc6, 0x7c, 0xc6, 0x88, 0xc5, 0x58, 0x8f, 0xe7, 0x3b, - 0x15, 0xc9, 0x88, 0x72, 0x96, 0xa1, 0x96, 0xc8, 0x80, 0x52, 0x7b, 0xda, 0x7d, 0x97, 0xa5, 0x5d, 0x3e, 0x46, 0x5f, - 0x5e, 0xdf, 0x17, 0xc7, 0xb7, 0x30, 0x7a, 0xf2, 0xf1, 0x08, 0xa5, 0xb7, 0xd7, 0x2f, 0x46, 0x81, 0x1d, 0x6f, 0xc5, - 0x8a, 0xb3, 0x92, 0xee, 0x39, 0xad, 0xe3, 0x08, 0xe1, 0x20, 0x67, 0x31, 0x06, 0x1d, 0x8b, 0x44, 0x8b, 0x8e, 0x6a, - 0x96, 0xc3, 0x06, 0xa3, 0xcc, 0x12, 0xc8, 0x06, 0xb2, 0x6a, 0x3a, 0x14, 0xab, 0x89, 0x83, 0x02, 0x52, 0xe3, 0x1e, - 0x95, 0xda, 0x17, 0x8c, 0xad, 0xf6, 0x9f, 0x58, 0x8d, 0x71, 0xb7, 0x06, 0x52, 0x92, 0x32, 0x29, 0x69, 0xd1, 0xd5, - 0xf3, 0x45, 0x76, 0xc5, 0x5e, 0x3c, 0xce, 0x4a, 0xdc, 0xd7, 0x80, 0x63, 0xdf, 0xa2, 0x08, 0x0a, 0x92, 0x66, 0xe8, - 0x80, 0xa3, 0x34, 0x3e, 0x61, 0xe9, 0xa7, 0xd8, 0x50, 0x3e, 0x6a, 0x14, 0x38, 0xc9, 0x3f, 0x53, 0x17, 0x91, 0xc4, - 0x42, 0xbf, 0x64, 0x00, 0x12, 0x71, 0x5e, 0x4d, 0xca, 0x75, 0xaa, 0x1c, 0xe4, 0x54, 0x48, 0x6f, 0xe5, 0x1f, 0x97, - 0x11, 0x57, 0x29, 0xca, 0xdc, 0x04, 0xce, 0x84, 0x26, 0xf5, 0xd0, 0xd0, 0x05, 0x6d, 0x01, 0x51, 0x6b, 0x09, 0xf5, - 0x58, 0x96, 0x37, 0x92, 0xcf, 0x2c, 0xf3, 0xac, 0x7e, 0xa7, 0x7e, 0xbf, 0x5d, 0x92, 0x9b, 0x8d, 0xa7, 0xbf, 0x6f, - 0x47, 0x08, 0x37, 0xbf, 0x71, 0x8a, 0xae, 0x10, 0x1c, 0xb3, 0xb2, 0xa7, 0x42, 0x2a, 0x66, 0x58, 0x43, 0x55, 0x9f, - 0xb2, 0xd9, 0x2b, 0x66, 0x17, 0x88, 0xa6, 0x46, 0x26, 0x6e, 0x7c, 0xaa, 0xab, 0x1a, 0x52, 0xdf, 0x77, 0x99, 0x7a, - 0xea, 0x0e, 0x1a, 0x35, 0x20, 0x14, 0x8b, 0x88, 0xf5, 0xd4, 0xff, 0xf1, 0x68, 0x3a, 0x1a, 0x13, 0x9e, 0xce, 0x61, - 0xe9, 0xf7, 0xc2, 0xaf, 0xf3, 0x78, 0x2e, 0xca, 0x94, 0x43, 0xaf, 0xaf, 0xe0, 0x98, 0x3f, 0x00, 0xbe, 0xe8, 0x60, - 0x34, 0x36, 0x82, 0x40, 0x79, 0x90, 0xc1, 0xba, 0x02, 0xba, 0x46, 0xf0, 0x88, 0x4d, 0x70, 0x8d, 0x88, 0x81, 0x95, - 0x76, 0x49, 0x56, 0x03, 0x7b, 0x74, 0xf4, 0x72, 0x6a, 0xe2, 0xa6, 0x13, 0x22, 0x8c, 0x7e, 0xae, 0x91, 0x81, 0xc2, - 0x6d, 0x66, 0x1b, 0x33, 0xe9, 0x66, 0x9f, 0x35, 0xe7, 0xed, 0xa6, 0x18, 0x1a, 0x1d, 0xab, 0x6b, 0x05, 0x77, 0xad, - 0xb6, 0xba, 0x36, 0x2b, 0xb0, 0x65, 0xf0, 0x61, 0x8d, 0x8f, 0x5a, 0x9c, 0x23, 0x2e, 0x1b, 0x25, 0xbf, 0x3c, 0xab, - 0xcf, 0x61, 0xe0, 0xe4, 0x15, 0x3e, 0x51, 0xe0, 0x32, 0xb7, 0xc5, 0xf2, 0xf6, 0x35, 0xc7, 0x33, 0x33, 0x88, 0x47, - 0xd7, 0x3d, 0xa8, 0xaf, 0x0f, 0xa9, 0x37, 0xb0, 0x56, 0x82, 0xb3, 0x74, 0xfe, 0x12, 0x27, 0x0f, 0x26, 0x04, 0xad, - 0xe5, 0xf8, 0x37, 0x85, 0x33, 0x53, 0xb0, 0x90, 0xe7, 0xfe, 0xec, 0x25, 0x41, 0x27, 0x13, 0xd2, 0x83, 0x4e, 0x67, - 0x68, 0xc8, 0xa3, 0xa3, 0x4b, 0x1c, 0xcc, 0x4e, 0x2a, 0x67, 0xab, 0x93, 0x2a, 0x5b, 0xc3, 0xf2, 0xae, 0x71, 0x60, - 0xf9, 0xf1, 0x32, 0x95, 0xcc, 0xfa, 0x9d, 0x85, 0xfc, 0x74, 0x29, 0x58, 0x53, 0xf6, 0xfd, 0x44, 0x63, 0x90, 0x66, - 0x5d, 0xa8, 0x2e, 0x34, 0xee, 0x6c, 0x3c, 0x58, 0x1a, 0x04, 0xbf, 0x0a, 0xf2, 0xfc, 0xda, 0x43, 0x93, 0x98, 0xb3, - 0xec, 0x5c, 0xc5, 0xd0, 0x28, 0xfc, 0xe9, 0xaf, 0x65, 0x56, 0x70, 0x1e, 0x0c, 0x83, 0x98, 0x9e, 0xdb, 0xa5, 0x90, - 0xfb, 0xe1, 0x52, 0xc8, 0xfb, 0xe8, 0x9c, 0xd0, 0x57, 0x04, 0xe9, 0x47, 0x44, 0xdc, 0x9a, 0x19, 0x1d, 0xab, 0x85, - 0x17, 0x16, 0xee, 0xe9, 0x28, 0x5b, 0x8c, 0x60, 0x96, 0xb2, 0xa3, 0x23, 0x03, 0xa0, 0x99, 0x11, 0x32, 0x3c, 0xad, - 0xc8, 0xed, 0xaa, 0x83, 0x60, 0xca, 0xf4, 0x57, 0x63, 0x48, 0x30, 0x08, 0xf8, 0x3f, 0x53, 0xef, 0x01, 0xa2, 0x6d, - 0x32, 0x01, 0xae, 0x47, 0x81, 0x76, 0xcc, 0x96, 0x98, 0xad, 0x3a, 0x1b, 0x82, 0x72, 0xaa, 0xb4, 0x91, 0xb2, 0xb8, - 0x66, 0x8f, 0x48, 0x95, 0x85, 0xc7, 0x2d, 0x18, 0x49, 0xb2, 0xca, 0xc5, 0x17, 0x39, 0x2a, 0xd3, 0xf7, 0x90, 0x81, - 0x53, 0xd4, 0xfb, 0x0b, 0xdc, 0xb2, 0x8b, 0xf7, 0xb4, 0x78, 0x2b, 0x84, 0xb4, 0x3d, 0xeb, 0x36, 0xd5, 0xae, 0xc7, - 0x6d, 0xdd, 0x39, 0x22, 0xf9, 0x7a, 0xd3, 0xe9, 0x54, 0xdb, 0xc9, 0xa5, 0x38, 0x55, 0x23, 0xb5, 0x15, 0x46, 0x41, - 0xa3, 0xb0, 0x75, 0x07, 0x72, 0x99, 0x2d, 0x43, 0xf9, 0xa0, 0xaa, 0xe7, 0xe6, 0xa3, 0xf7, 0xd7, 0x1a, 0x74, 0xdb, - 0x48, 0xc5, 0xbf, 0x95, 0x66, 0x7d, 0x4d, 0x59, 0xd5, 0x05, 0x2a, 0xa8, 0x7c, 0x4b, 0xbf, 0xa2, 0x9c, 0x8c, 0x2e, - 0x15, 0xfb, 0x40, 0x43, 0xf2, 0x35, 0xa5, 0x78, 0xf0, 0x7c, 0x65, 0xeb, 0xc6, 0x8d, 0xee, 0xd2, 0x92, 0x0b, 0xda, - 0x7b, 0xbd, 0xae, 0x05, 0x23, 0xf3, 0x30, 0xa2, 0x2a, 0xa4, 0x9f, 0xf7, 0x95, 0x57, 0xdd, 0xd3, 0xab, 0x86, 0x4b, - 0x72, 0x47, 0xef, 0x2b, 0x28, 0xfd, 0x53, 0xcb, 0x88, 0x8b, 0x51, 0x47, 0xef, 0x2b, 0x25, 0x8b, 0x43, 0xc0, 0xe0, - 0xd4, 0x9c, 0xdf, 0x3f, 0x9d, 0xce, 0xf4, 0x0f, 0x4c, 0xa8, 0x60, 0x32, 0xef, 0x9f, 0xd3, 0x81, 0x0a, 0xcc, 0xac, - 0x72, 0xe9, 0xfd, 0x13, 0x3b, 0x50, 0x58, 0x4f, 0x2d, 0x97, 0xdd, 0x3b, 0xbb, 0x03, 0x45, 0xd5, 0xfc, 0x72, 0x0e, - 0x39, 0xcf, 0xcf, 0xa0, 0x68, 0x6a, 0xd0, 0xb9, 0x6b, 0x4d, 0xc0, 0x4a, 0x8a, 0xe0, 0xa2, 0xc6, 0x50, 0xb6, 0xde, - 0x56, 0x1d, 0xda, 0x20, 0xd0, 0xc1, 0xeb, 0x72, 0x6a, 0x8e, 0x71, 0xc4, 0x39, 0x29, 0x15, 0x1f, 0x25, 0xad, 0x44, - 0xd6, 0x29, 0x5b, 0xcc, 0xa5, 0x5d, 0xb7, 0x69, 0x02, 0x5f, 0x45, 0xc8, 0x87, 0xf0, 0x95, 0x87, 0x6a, 0xf1, 0x27, - 0x9a, 0x11, 0xbb, 0xef, 0x53, 0x95, 0x18, 0xc4, 0xab, 0x0a, 0x62, 0x82, 0x01, 0x6f, 0xb1, 0x1f, 0x9c, 0xe0, 0x44, - 0x87, 0x7b, 0x47, 0x08, 0xd1, 0xaf, 0xbd, 0xe2, 0x4c, 0xdc, 0x95, 0x47, 0xe3, 0xfa, 0x3c, 0x40, 0xc4, 0x4a, 0x90, - 0x7c, 0xe1, 0x0c, 0x44, 0xd4, 0x53, 0x7a, 0x4b, 0xf6, 0xf5, 0xe6, 0x65, 0x3b, 0xf4, 0x69, 0x01, 0x54, 0x24, 0xcb, - 0xfe, 0xe8, 0x18, 0xc1, 0x3b, 0x87, 0x88, 0x91, 0xb6, 0xf2, 0x37, 0xc0, 0xb0, 0xc2, 0x49, 0x74, 0x73, 0x0a, 0x02, - 0x77, 0x31, 0xb5, 0xb9, 0x1f, 0xa5, 0x40, 0x2c, 0x1c, 0x4b, 0x12, 0x19, 0xc1, 0x56, 0x16, 0x70, 0x27, 0x02, 0x1e, - 0x1f, 0x80, 0xca, 0x94, 0x82, 0xcd, 0x6b, 0x7a, 0x7c, 0xc7, 0x37, 0xa3, 0x6f, 0xc6, 0xcd, 0xf8, 0x9b, 0xd1, 0x41, - 0xc6, 0x7c, 0x47, 0x7c, 0xa0, 0x96, 0x44, 0xba, 0x38, 0xf8, 0x66, 0x5c, 0x8c, 0xe9, 0x2c, 0xd1, 0x2c, 0x2d, 0xc5, - 0x56, 0x4b, 0x1b, 0x22, 0xc2, 0xdb, 0x95, 0x84, 0x21, 0xba, 0x1d, 0x3c, 0x22, 0x2e, 0x10, 0x24, 0x0b, 0x98, 0xed, - 0x96, 0xbd, 0xde, 0x8d, 0xfb, 0x16, 0xcb, 0xb2, 0x34, 0xee, 0xaf, 0x21, 0xcb, 0x48, 0xbb, 0xca, 0x50, 0x01, 0x51, - 0x13, 0xd0, 0xd1, 0xfe, 0xc2, 0x1c, 0xaf, 0x50, 0x5c, 0x1f, 0x29, 0x17, 0xaa, 0x46, 0x5d, 0x0a, 0x56, 0xef, 0x88, - 0x10, 0xb9, 0xf3, 0xdc, 0xdc, 0xb7, 0x97, 0x51, 0x2d, 0xab, 0x6a, 0x61, 0xd7, 0xe3, 0xab, 0x80, 0xb5, 0xb5, 0x00, - 0x74, 0x74, 0x5e, 0xeb, 0xab, 0x18, 0xf9, 0x4a, 0x29, 0x80, 0x8b, 0xce, 0x5d, 0x0b, 0xfb, 0xc6, 0xa7, 0xa8, 0x2f, - 0xd9, 0x9a, 0x0e, 0x58, 0x25, 0x46, 0x35, 0xc7, 0xb6, 0xbc, 0xa7, 0xc1, 0x9b, 0xc2, 0x34, 0x19, 0x78, 0xb2, 0x8b, - 0xee, 0x38, 0xd5, 0x51, 0x4d, 0xb8, 0xf5, 0x46, 0xed, 0x51, 0xa2, 0xda, 0x43, 0x33, 0x65, 0x88, 0x2e, 0xcd, 0x2b, - 0x00, 0x79, 0x00, 0xe4, 0xa9, 0x92, 0xe8, 0x2c, 0x45, 0x95, 0xb6, 0x92, 0x28, 0x68, 0x21, 0xbd, 0xc6, 0x88, 0x0b, - 0xb0, 0x1d, 0x28, 0x1a, 0x19, 0x6e, 0xb6, 0x04, 0x71, 0xcb, 0x29, 0x7c, 0x98, 0x86, 0x93, 0x6d, 0x75, 0x0c, 0x93, - 0xac, 0xb8, 0x89, 0xf3, 0x4c, 0xa0, 0x25, 0xbe, 0x95, 0x16, 0x13, 0x16, 0x90, 0x96, 0xa7, 0x2f, 0xca, 0x7c, 0xc1, - 0x90, 0x70, 0xd6, 0x5b, 0x07, 0x50, 0x4d, 0xd6, 0x5a, 0xdb, 0x19, 0x59, 0x7d, 0xe5, 0x21, 0x15, 0x3a, 0x34, 0x98, - 0x92, 0x3a, 0x66, 0xe8, 0x89, 0xfd, 0x95, 0xfe, 0x8a, 0xf0, 0x5d, 0xcb, 0x70, 0x1e, 0xbf, 0x0f, 0x0d, 0x06, 0x65, - 0x5a, 0x21, 0x82, 0x0c, 0xcd, 0x26, 0xba, 0xf2, 0x0c, 0x2c, 0xa6, 0x6e, 0x7c, 0x04, 0xc6, 0x11, 0x21, 0x11, 0xbc, - 0x30, 0x61, 0xdd, 0x0a, 0x73, 0xcf, 0x22, 0xa7, 0x09, 0x22, 0x8b, 0x97, 0xd1, 0x0d, 0x22, 0x73, 0xea, 0x5d, 0x21, - 0x23, 0x7b, 0x98, 0xce, 0xcf, 0xce, 0xc3, 0xdf, 0x56, 0x4c, 0xbf, 0xe0, 0x0b, 0xed, 0x70, 0x93, 0x5c, 0x9e, 0x5a, - 0x8f, 0x26, 0x59, 0xcc, 0x15, 0xce, 0x98, 0xd6, 0x11, 0x79, 0x3c, 0xe3, 0xad, 0x80, 0xac, 0xd9, 0x38, 0x7a, 0x72, - 0x88, 0xd8, 0x2d, 0xd7, 0xa9, 0x97, 0x44, 0x4f, 0x62, 0x69, 0x16, 0x22, 0x3f, 0x46, 0x51, 0x62, 0x9e, 0x7c, 0x45, - 0x0e, 0x65, 0x4d, 0xb1, 0x47, 0xcb, 0xbe, 0x65, 0xc9, 0x2e, 0x3b, 0xfc, 0x16, 0xaf, 0x4c, 0x6d, 0xfe, 0xfb, 0x66, - 0xe5, 0x06, 0xf9, 0x0e, 0x04, 0xd9, 0xd7, 0x01, 0xd6, 0x6c, 0xd4, 0xf0, 0xb0, 0x84, 0x60, 0x80, 0xc8, 0x18, 0x65, - 0xb6, 0xd0, 0xb2, 0x35, 0x10, 0x3f, 0x81, 0xf9, 0x4d, 0x59, 0xd2, 0xe2, 0x53, 0x1c, 0x21, 0x67, 0x2d, 0x31, 0x2a, - 0x53, 0xd5, 0x91, 0xc1, 0xbc, 0x5b, 0x57, 0x6d, 0xd7, 0xa5, 0x37, 0x82, 0x68, 0xd4, 0x95, 0xb3, 0x48, 0xa5, 0x02, - 0xc5, 0x7b, 0xf2, 0x35, 0xbc, 0xe2, 0x39, 0xab, 0x60, 0x60, 0xce, 0x11, 0x31, 0x48, 0x01, 0x71, 0xca, 0x57, 0x30, - 0x4c, 0x74, 0x09, 0xc7, 0xde, 0xeb, 0x45, 0x1d, 0x36, 0x56, 0xd7, 0x3f, 0x39, 0x90, 0xb1, 0x87, 0xb0, 0x4c, 0x32, - 0x8e, 0xe8, 0x47, 0x5e, 0x18, 0xf4, 0xfb, 0x78, 0xbe, 0x6b, 0xc3, 0xcc, 0x14, 0xf9, 0x0d, 0x8b, 0xe8, 0x7a, 0x1b, - 0x53, 0x6f, 0xda, 0xba, 0xf0, 0xd7, 0x04, 0x0e, 0x9f, 0x39, 0x8a, 0xed, 0x6e, 0xa8, 0x9c, 0xc6, 0x5c, 0x18, 0xc4, - 0x28, 0x6f, 0xe5, 0x11, 0x34, 0xa8, 0x38, 0x4b, 0xce, 0x51, 0x51, 0x9a, 0xeb, 0x78, 0x21, 0xa5, 0x98, 0x09, 0xf0, - 0x47, 0xc3, 0x58, 0xab, 0x2b, 0x3f, 0x40, 0x5b, 0xd4, 0xb2, 0x36, 0x6f, 0xa9, 0x45, 0x61, 0x0a, 0xd5, 0xb4, 0x41, - 0xce, 0x87, 0xa4, 0x12, 0x2e, 0x4d, 0x37, 0x3e, 0x58, 0xdd, 0x50, 0xbd, 0xe8, 0x75, 0x41, 0xcd, 0xd2, 0x07, 0x14, - 0x00, 0xff, 0xc1, 0x32, 0x8e, 0xea, 0x14, 0x2b, 0x1a, 0xe8, 0x0d, 0x61, 0xc4, 0x1a, 0xe2, 0x89, 0x7b, 0x4d, 0x89, - 0x19, 0x47, 0x47, 0xe2, 0x32, 0x64, 0x92, 0x28, 0x4e, 0x1f, 0x6d, 0xd7, 0xf7, 0xac, 0xba, 0xc0, 0xf8, 0xca, 0x75, - 0x70, 0x36, 0x1a, 0x9d, 0x23, 0x5c, 0x2f, 0xee, 0x5f, 0x24, 0x5c, 0xe1, 0xe1, 0x09, 0xc3, 0xef, 0xaa, 0x07, 0xa0, - 0xa2, 0xd8, 0x04, 0x8a, 0xf8, 0x63, 0xa1, 0xa8, 0x17, 0x9d, 0xc8, 0xee, 0x53, 0x25, 0xa0, 0x80, 0x78, 0x65, 0xc5, - 0x04, 0x41, 0xe3, 0x61, 0xf5, 0x06, 0x93, 0x7d, 0x79, 0xed, 0xf3, 0x8a, 0x42, 0xd5, 0x11, 0xe2, 0xb3, 0x59, 0x0f, - 0xa9, 0xfd, 0x80, 0x9e, 0x85, 0xfa, 0x9b, 0x6f, 0x64, 0xd5, 0x30, 0x3f, 0x90, 0xe9, 0xd8, 0xc7, 0x78, 0x6a, 0x5c, - 0x50, 0xa1, 0x8b, 0xd1, 0x1c, 0xf6, 0x3e, 0x23, 0x73, 0x5f, 0xd0, 0x6d, 0xdf, 0x05, 0x1e, 0x21, 0x90, 0xc6, 0xa6, - 0x7c, 0xf3, 0xd1, 0x76, 0x14, 0x52, 0x6c, 0x73, 0x0b, 0xf2, 0xfa, 0xb9, 0x8b, 0x5f, 0x9c, 0x51, 0x78, 0x16, 0x5d, - 0x61, 0xa8, 0x2b, 0x32, 0x25, 0xfe, 0x55, 0xe3, 0xce, 0x45, 0xf4, 0x5e, 0xae, 0x56, 0x62, 0xb2, 0x6d, 0xd5, 0x8f, - 0x4a, 0xdd, 0xdf, 0x1e, 0x58, 0x0b, 0xf8, 0xed, 0xca, 0x2e, 0xc4, 0x57, 0xbe, 0x59, 0xff, 0xca, 0x57, 0xdc, 0xa2, - 0x33, 0xeb, 0xc2, 0x39, 0xeb, 0x5d, 0x38, 0xc3, 0xa7, 0x2c, 0xd4, 0x68, 0x9c, 0x0a, 0xe6, 0x40, 0xa1, 0x20, 0xb5, - 0x4d, 0x7f, 0xde, 0x5a, 0xf9, 0xa9, 0xb3, 0xf2, 0x51, 0x3e, 0x8e, 0x69, 0x88, 0xa1, 0x5d, 0x26, 0x10, 0xa9, 0x8f, - 0xe1, 0xc0, 0xc4, 0x79, 0x02, 0x36, 0x39, 0x56, 0x76, 0x76, 0x7c, 0x3e, 0x6d, 0xca, 0xef, 0xca, 0x4f, 0x88, 0xea, - 0x50, 0xe3, 0xbd, 0x1c, 0xf1, 0x50, 0x86, 0x6d, 0xea, 0xf2, 0x3d, 0xbf, 0x3c, 0x8f, 0x0b, 0xe4, 0x77, 0x34, 0x3c, - 0xce, 0x01, 0xb2, 0x61, 0xf8, 0xf5, 0x6f, 0x1e, 0xec, 0xb2, 0xf6, 0x9b, 0x03, 0xfc, 0xee, 0xf4, 0xe0, 0x1d, 0x85, - 0xbb, 0x39, 0x58, 0x57, 0xe5, 0x4d, 0xb6, 0x48, 0x0f, 0xbe, 0xc1, 0xd4, 0x6f, 0x0e, 0xca, 0xea, 0xe0, 0x1b, 0xd5, - 0x18, 0x78, 0xa2, 0xc5, 0x3e, 0xfd, 0xc5, 0x5a, 0x78, 0x3f, 0xd7, 0x3a, 0x02, 0xda, 0x12, 0x3d, 0xb3, 0xb4, 0xfa, - 0x11, 0x95, 0x88, 0x2a, 0x3e, 0xaa, 0x78, 0xb5, 0x5a, 0x14, 0xe7, 0xdd, 0x4a, 0x23, 0x65, 0xf3, 0x82, 0xa4, 0xdd, - 0x02, 0x7f, 0xf5, 0xea, 0xb4, 0xe3, 0xed, 0x38, 0x2f, 0xd4, 0x01, 0x51, 0x44, 0x4f, 0x8a, 0xe9, 0x2d, 0x7f, 0x0d, - 0xbf, 0x75, 0x77, 0x57, 0x4c, 0xb7, 0xe6, 0xd1, 0xe7, 0xdb, 0x4a, 0xf1, 0x3b, 0x52, 0xc1, 0x85, 0x28, 0x66, 0xdc, - 0xed, 0x28, 0xc0, 0x18, 0x00, 0x30, 0xb8, 0xfc, 0xbc, 0x95, 0x67, 0x45, 0x2d, 0xad, 0x76, 0x3e, 0xe8, 0xc4, 0xce, - 0x78, 0xdd, 0x98, 0x40, 0x6d, 0x3b, 0xc1, 0x96, 0x86, 0xfc, 0xa4, 0x29, 0xe2, 0x47, 0xdc, 0x4d, 0x70, 0x9c, 0xe1, - 0x86, 0x14, 0x48, 0x62, 0x3c, 0x46, 0x07, 0xf4, 0x38, 0x43, 0x51, 0x7a, 0x0a, 0xdf, 0x89, 0xcb, 0xad, 0xe5, 0x01, - 0x09, 0xab, 0x70, 0xf8, 0xce, 0x8b, 0x0d, 0x3c, 0x3a, 0xbc, 0x2c, 0xf3, 0x74, 0x9a, 0xf2, 0x2c, 0xbf, 0x66, 0x76, - 0xe6, 0x80, 0x5a, 0x71, 0x90, 0x08, 0x58, 0x58, 0xcc, 0xe8, 0xde, 0x30, 0x8d, 0x8c, 0x00, 0x7e, 0xf0, 0x60, 0x57, - 0xb5, 0xbf, 0x30, 0x3c, 0xc4, 0xf4, 0x02, 0x23, 0xe2, 0x6c, 0xbb, 0xf5, 0x7d, 0x8a, 0xa1, 0xed, 0xbf, 0xbc, 0xbe, - 0x2a, 0x4a, 0x74, 0xd1, 0x3c, 0x10, 0xc5, 0x6a, 0x75, 0x80, 0x11, 0xf3, 0x80, 0x53, 0x8e, 0x6b, 0x59, 0x06, 0xf5, - 0x40, 0xb5, 0x9a, 0x8c, 0x17, 0x1e, 0x86, 0xf8, 0x86, 0x59, 0xae, 0x82, 0xcc, 0x0f, 0x5e, 0x2a, 0xd3, 0x54, 0xd6, - 0x23, 0x9f, 0xa3, 0xb7, 0x24, 0x6c, 0xf3, 0x04, 0xef, 0x3f, 0xd0, 0x31, 0xdd, 0x8c, 0xdc, 0x8c, 0x42, 0x91, 0xaf, - 0xf7, 0x28, 0xbe, 0x78, 0x1d, 0x25, 0x2d, 0x54, 0xbd, 0xc2, 0xe3, 0x61, 0x75, 0x96, 0x9f, 0x53, 0x94, 0xf2, 0xac, - 0xbb, 0x44, 0x06, 0x06, 0xb1, 0xa2, 0x6f, 0xeb, 0xf8, 0x7a, 0x89, 0xf2, 0xc0, 0x64, 0xca, 0x06, 0x7d, 0x8e, 0x71, - 0xaa, 0x56, 0x91, 0x07, 0x73, 0x1c, 0x0b, 0x51, 0xb4, 0x1a, 0x66, 0x4f, 0xd3, 0xca, 0x4c, 0xd3, 0x42, 0x7f, 0x61, - 0x13, 0x01, 0x41, 0x5c, 0xe0, 0xc5, 0xf5, 0x12, 0x78, 0xd4, 0x8d, 0xd9, 0x08, 0x77, 0x77, 0x1b, 0xe8, 0xd6, 0x12, - 0xdd, 0x5c, 0x97, 0xf0, 0x30, 0xd4, 0x33, 0xe8, 0x30, 0xbe, 0x54, 0x3d, 0xdc, 0xc0, 0x82, 0xc2, 0xc7, 0xd5, 0xd9, - 0x82, 0xfa, 0x07, 0x3d, 0xb4, 0x3f, 0x5f, 0x0e, 0xaf, 0x12, 0x0a, 0xbe, 0xb1, 0xc6, 0xb0, 0x63, 0x67, 0xdd, 0x01, - 0x57, 0x33, 0x20, 0x21, 0xdd, 0x8d, 0xfe, 0xae, 0x1a, 0x8c, 0x53, 0x42, 0xb1, 0xa3, 0x15, 0xd8, 0x2f, 0x8c, 0xc3, - 0x4c, 0xb3, 0x3d, 0x74, 0x6f, 0x63, 0x73, 0x88, 0x6a, 0xd9, 0x47, 0xb2, 0x53, 0x2c, 0xcd, 0x5b, 0x65, 0xa3, 0xe7, - 0xe3, 0xfe, 0xdc, 0xb5, 0x32, 0x51, 0x38, 0x47, 0x51, 0x66, 0x1d, 0x44, 0xc0, 0x24, 0x64, 0x02, 0x0a, 0x1a, 0x65, - 0x16, 0x3a, 0x68, 0x60, 0x11, 0xec, 0xa7, 0xab, 0xbd, 0xf5, 0x45, 0xf8, 0x2d, 0xfa, 0xe5, 0x07, 0xd4, 0xa5, 0x40, - 0x45, 0x7b, 0xfc, 0xbd, 0x56, 0xa1, 0xf0, 0x82, 0x2d, 0xc7, 0x5a, 0xfb, 0x90, 0x36, 0x26, 0x94, 0xc3, 0xbf, 0x53, - 0xfb, 0x08, 0xfb, 0x9d, 0xae, 0x20, 0x0c, 0x76, 0xfd, 0x41, 0x4a, 0x10, 0xb1, 0xe8, 0x2f, 0xf8, 0x7b, 0x2d, 0xa1, - 0xe8, 0x80, 0x7b, 0xdc, 0x56, 0x18, 0xb7, 0x8e, 0x1c, 0xfa, 0x52, 0xf9, 0x4c, 0x92, 0x9a, 0x30, 0x13, 0x9a, 0xa2, - 0xff, 0xcc, 0xd1, 0xc9, 0x66, 0x85, 0xe5, 0xf2, 0x41, 0x41, 0x25, 0xf1, 0x0a, 0x56, 0x04, 0xca, 0x6f, 0x5d, 0x81, - 0x52, 0x6b, 0x2d, 0x78, 0xff, 0x46, 0x4f, 0x57, 0x9e, 0xc1, 0xdf, 0x43, 0x1e, 0x83, 0xa5, 0x11, 0xd5, 0x25, 0xe7, - 0xea, 0xa3, 0x72, 0xde, 0xa1, 0x0a, 0xe8, 0x60, 0x9d, 0xc7, 0x0d, 0xac, 0x94, 0xeb, 0x8e, 0xa7, 0xa8, 0xd4, 0x3e, - 0x55, 0xaf, 0x29, 0x2f, 0xae, 0x93, 0x3d, 0xf9, 0xf0, 0x15, 0x02, 0xe3, 0x71, 0x9e, 0x4e, 0x1b, 0xe5, 0xf6, 0x83, - 0xea, 0xc0, 0x19, 0xd8, 0x53, 0x07, 0xbe, 0xa2, 0x3a, 0x28, 0x4f, 0xb7, 0x0e, 0x35, 0x89, 0x0d, 0xa9, 0xae, 0x14, - 0x81, 0xd9, 0x53, 0x95, 0xbc, 0xa5, 0xda, 0x4a, 0x73, 0xd1, 0x34, 0x94, 0x47, 0xda, 0x25, 0x0b, 0x76, 0xef, 0x30, - 0xb0, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0xdd, 0x9b, 0x25, 0xce, 0xc5, 0x52, 0x46, 0x02, 0x87, 0x24, 0x8f, 0xb3, 0x47, - 0x2b, 0x0d, 0xda, 0x6b, 0x27, 0xed, 0xba, 0x33, 0xc5, 0x05, 0x0c, 0xda, 0xa7, 0x3d, 0x53, 0xea, 0x5d, 0x2b, 0xdb, - 0xc0, 0xe6, 0x2e, 0x55, 0x3b, 0xff, 0x8d, 0xca, 0x77, 0xbc, 0x66, 0x3c, 0x3b, 0xfb, 0x45, 0x13, 0xb7, 0x07, 0xbb, - 0xa6, 0xfd, 0x25, 0x00, 0x3e, 0xf1, 0x5c, 0x97, 0x7d, 0xaa, 0xa2, 0x50, 0x59, 0x95, 0x58, 0x4e, 0xda, 0x50, 0xcd, - 0x2f, 0x58, 0x6a, 0x4a, 0xd7, 0xca, 0x74, 0x98, 0x43, 0x2d, 0x29, 0xd4, 0x32, 0x54, 0xb7, 0x95, 0xab, 0x96, 0x6c, - 0xbf, 0xf4, 0x92, 0x80, 0x56, 0xdd, 0xdb, 0x22, 0xd1, 0x01, 0xde, 0xdf, 0x9e, 0xc9, 0x3d, 0x8d, 0x50, 0x6a, 0x41, - 0xd5, 0x82, 0xce, 0xc7, 0x7e, 0xe9, 0xbc, 0xe7, 0x8f, 0xf7, 0xf9, 0x74, 0x8b, 0x8b, 0x30, 0x76, 0x60, 0xb8, 0x64, - 0x67, 0x4e, 0x5b, 0x8a, 0x76, 0xc2, 0x65, 0xdd, 0x26, 0x29, 0x61, 0x8f, 0x13, 0x91, 0xa9, 0xc3, 0xfd, 0x4b, 0xe3, - 0x10, 0xe7, 0x36, 0xeb, 0x8f, 0xc4, 0xea, 0x9c, 0x01, 0x11, 0x11, 0xad, 0x55, 0xe4, 0x81, 0x7e, 0xbc, 0x30, 0x6b, - 0x6d, 0x88, 0x59, 0x6f, 0xa1, 0xb4, 0x57, 0xc2, 0xa0, 0x1f, 0x22, 0xcf, 0xed, 0x93, 0x59, 0xae, 0xda, 0xe6, 0x85, - 0xdc, 0xe5, 0xe0, 0x8d, 0x16, 0x01, 0x35, 0x3b, 0x42, 0x87, 0x03, 0x05, 0xa1, 0x44, 0xa2, 0x9a, 0x63, 0x75, 0x94, - 0x1d, 0x44, 0xad, 0x4e, 0xeb, 0x0a, 0xbe, 0x53, 0xe1, 0xbb, 0x24, 0x86, 0x8c, 0x52, 0x11, 0xba, 0xf4, 0x51, 0xae, - 0x68, 0xa6, 0x89, 0x01, 0xba, 0xc2, 0x3b, 0x6d, 0xb4, 0xb7, 0x20, 0x5a, 0x86, 0x67, 0xa6, 0x7d, 0x1a, 0x26, 0x18, - 0xd3, 0x1c, 0x7d, 0xfe, 0xfc, 0xa1, 0x17, 0x35, 0xbe, 0x18, 0x48, 0x87, 0x33, 0xb7, 0xa4, 0x33, 0x77, 0xcf, 0xfb, - 0x97, 0x7b, 0xd2, 0xcb, 0x02, 0x5f, 0xe8, 0x30, 0x88, 0x79, 0xf4, 0xb4, 0xaa, 0xe2, 0xed, 0x74, 0x59, 0x95, 0xd7, - 0x5e, 0xa2, 0xe9, 0x78, 0x2e, 0x6c, 0x20, 0x47, 0xc6, 0xcc, 0x59, 0x14, 0x1b, 0x38, 0x87, 0x89, 0xb6, 0xaf, 0xe2, - 0x9a, 0xee, 0x3f, 0x2b, 0x1a, 0xf5, 0x14, 0xb1, 0x1c, 0xf2, 0x96, 0x6e, 0xe1, 0x9d, 0x61, 0xef, 0x8e, 0xb8, 0x44, - 0x47, 0x71, 0x1d, 0xe8, 0xcf, 0x1a, 0xec, 0x59, 0xca, 0x3d, 0xb3, 0x64, 0x32, 0x49, 0x91, 0x58, 0xbe, 0xf0, 0x0a, - 0x3a, 0x72, 0xde, 0x0a, 0x79, 0xf8, 0x3e, 0xbe, 0x4e, 0x17, 0xfa, 0x06, 0x9d, 0x75, 0x64, 0x11, 0xca, 0x85, 0x46, - 0x22, 0xdd, 0x3d, 0xa8, 0xa1, 0x41, 0xe9, 0x02, 0xa5, 0xc0, 0x60, 0xa7, 0xc8, 0x4a, 0x58, 0x61, 0x3c, 0xd8, 0x77, - 0x55, 0xba, 0xcc, 0x6e, 0x53, 0xc4, 0x75, 0x88, 0x7e, 0x12, 0x44, 0x42, 0x97, 0xf2, 0x70, 0x88, 0x35, 0xb6, 0xbe, - 0x21, 0x34, 0xf6, 0x17, 0xc8, 0xa7, 0x61, 0x30, 0x91, 0x72, 0x2a, 0x15, 0x63, 0x3c, 0x80, 0x22, 0x5a, 0xe3, 0x95, - 0xdc, 0xbc, 0xf0, 0xfc, 0xb0, 0xd0, 0x03, 0xcc, 0x74, 0xd0, 0x15, 0x5c, 0x61, 0x25, 0xa1, 0x55, 0x4c, 0x12, 0xfd, - 0xa3, 0x81, 0x8a, 0x0a, 0x18, 0xb2, 0xd6, 0x08, 0x3a, 0x39, 0x8a, 0x1a, 0xa9, 0x5f, 0x02, 0xaf, 0x16, 0x25, 0xf0, - 0x8f, 0xbe, 0xe2, 0x6d, 0x7b, 0xb5, 0x20, 0x9c, 0x3a, 0x09, 0xc0, 0x1a, 0xfa, 0x4a, 0x77, 0xad, 0xbc, 0xa7, 0x33, - 0x46, 0x41, 0x45, 0x06, 0x42, 0xd0, 0x88, 0x12, 0xaa, 0x92, 0x30, 0x09, 0xb5, 0x8f, 0x26, 0xe8, 0x26, 0xf2, 0x72, - 0xed, 0xc6, 0xaa, 0xc9, 0xd4, 0xf6, 0x2b, 0x08, 0xf5, 0x5d, 0x6d, 0xb9, 0x4c, 0x5f, 0x9f, 0x1a, 0x65, 0x4d, 0xca, - 0x57, 0x8e, 0x62, 0xf7, 0x29, 0x1b, 0xb7, 0x36, 0x57, 0xd6, 0x50, 0x01, 0xcc, 0x8c, 0x6e, 0xf1, 0xeb, 0x82, 0x03, - 0x8a, 0xda, 0x53, 0x92, 0xda, 0xda, 0xad, 0xd8, 0x95, 0xe3, 0x80, 0x1b, 0x4d, 0xf2, 0xcd, 0x02, 0x96, 0xd6, 0x68, - 0x85, 0xb7, 0xc5, 0x23, 0x8c, 0x8b, 0xca, 0x5b, 0xbf, 0x0e, 0x4a, 0x44, 0x0f, 0x10, 0x66, 0xe3, 0x35, 0x45, 0xc0, - 0x7a, 0x07, 0x7c, 0xca, 0xd1, 0x91, 0xb9, 0xca, 0x7f, 0xfb, 0xa9, 0xc0, 0x20, 0x85, 0x69, 0xd5, 0x6c, 0x71, 0x01, - 0xa1, 0xd8, 0xc9, 0xda, 0xb3, 0x26, 0x7a, 0x02, 0xf3, 0x88, 0xf1, 0xad, 0x7c, 0x2b, 0x88, 0xd5, 0x0b, 0x5b, 0xb0, - 0xd9, 0x65, 0xf5, 0x07, 0xa3, 0x71, 0x48, 0x03, 0xe0, 0x5b, 0xb5, 0xca, 0xa1, 0x68, 0xa3, 0x12, 0x59, 0x2a, 0x4b, - 0x74, 0xad, 0x1d, 0xd1, 0xb5, 0x8c, 0x28, 0x96, 0x2c, 0x70, 0x57, 0xf8, 0x27, 0x8e, 0xbc, 0xea, 0xee, 0xae, 0x84, - 0xa6, 0x65, 0x67, 0xac, 0x95, 0xc5, 0xe8, 0x69, 0xd0, 0x80, 0x18, 0xc4, 0xad, 0xd7, 0x68, 0x35, 0x02, 0x7f, 0xab, - 0xa3, 0xa3, 0xf7, 0x46, 0x92, 0x81, 0x35, 0xac, 0xb5, 0xb3, 0xa8, 0x74, 0xff, 0xb8, 0x8a, 0x46, 0x7f, 0x9e, 0xfe, - 0x79, 0x7a, 0x32, 0x92, 0xa1, 0xff, 0x6e, 0x05, 0xab, 0x02, 0x25, 0xf4, 0x40, 0x09, 0xe7, 0x81, 0x98, 0xbb, 0x2b, - 0x3b, 0xf4, 0x91, 0x86, 0x8a, 0x1f, 0x9d, 0x9b, 0x3e, 0xfe, 0xa3, 0xee, 0x69, 0x12, 0x06, 0x04, 0xfd, 0xbb, 0xbb, - 0xef, 0x56, 0x5a, 0x9f, 0x96, 0x29, 0x7d, 0x9a, 0xc2, 0x51, 0x32, 0xc1, 0xdd, 0xdc, 0xca, 0xb4, 0x63, 0x3f, 0x11, - 0x5f, 0xc5, 0x2f, 0x9e, 0x65, 0x28, 0xf6, 0x16, 0xf0, 0x67, 0x8e, 0xb7, 0x2b, 0x13, 0x20, 0x00, 0xe7, 0x21, 0xa6, - 0x4e, 0x30, 0xcd, 0x5a, 0x86, 0xff, 0xac, 0x5d, 0xc6, 0x5b, 0x5b, 0xbc, 0x1b, 0xb8, 0x28, 0x75, 0xa4, 0xcf, 0xba, - 0x68, 0xba, 0xac, 0x92, 0x7f, 0x9f, 0x42, 0x93, 0xd1, 0x67, 0xe3, 0x35, 0xc7, 0xfd, 0x2c, 0x8b, 0xe7, 0x25, 0x62, - 0x17, 0x21, 0x18, 0x72, 0x76, 0xee, 0x70, 0xe2, 0xef, 0x57, 0x5f, 0xff, 0x31, 0x5d, 0x1b, 0x2c, 0xa6, 0x2b, 0x58, - 0xcb, 0x75, 0xaf, 0xb6, 0x5b, 0x9b, 0xaf, 0xc7, 0x48, 0xa2, 0x30, 0x58, 0x1c, 0x49, 0x34, 0x23, 0x57, 0x14, 0x94, - 0x1a, 0x47, 0xf3, 0x2c, 0x52, 0x11, 0xab, 0xa7, 0xe6, 0xf6, 0xf3, 0xd9, 0xf6, 0xf5, 0x02, 0x0a, 0x87, 0x19, 0x32, - 0xc2, 0x1a, 0x4a, 0x29, 0xa3, 0x78, 0x70, 0xc0, 0xb3, 0x63, 0x2a, 0x87, 0xd6, 0xe5, 0x54, 0x79, 0x30, 0xdc, 0x7c, - 0x9c, 0xa1, 0x5e, 0xf6, 0xdf, 0x35, 0xae, 0x7f, 0xdd, 0x1f, 0x6a, 0x4f, 0x47, 0x98, 0x26, 0x15, 0x51, 0xed, 0xc5, - 0x99, 0xbe, 0x02, 0x49, 0xa3, 0x27, 0xa9, 0x15, 0xef, 0xd7, 0x67, 0x43, 0x82, 0xd6, 0x2c, 0x96, 0x97, 0x3d, 0xf3, - 0x0b, 0x5b, 0xe4, 0xea, 0xaf, 0xff, 0xc2, 0xac, 0xff, 0x31, 0x19, 0x43, 0x96, 0x4f, 0x22, 0xeb, 0xc2, 0x82, 0x56, - 0xbf, 0x98, 0x7a, 0xe0, 0xef, 0xc0, 0x4b, 0x9f, 0x60, 0x38, 0xe6, 0x27, 0x64, 0xaa, 0x98, 0x9d, 0x95, 0x63, 0x8c, - 0x65, 0xeb, 0xb7, 0xd6, 0x9a, 0xf8, 0xde, 0x0a, 0x79, 0x25, 0x1b, 0x42, 0x8b, 0xab, 0xb8, 0x1a, 0xaf, 0xcb, 0x4d, - 0x9d, 0x96, 0x9b, 0x66, 0xc4, 0x6a, 0xd9, 0x62, 0xde, 0xd8, 0x0a, 0xd9, 0xbf, 0xa7, 0x9d, 0x08, 0x5e, 0x26, 0xea, - 0x64, 0x92, 0x67, 0xeb, 0x39, 0xc6, 0xd7, 0x0b, 0xf1, 0x2c, 0x32, 0x45, 0x3e, 0x3b, 0x34, 0xe0, 0x96, 0x2e, 0x4f, - 0x31, 0x38, 0x2a, 0xff, 0x80, 0x8d, 0xaf, 0x75, 0x7a, 0xb0, 0x26, 0x8a, 0x39, 0xfb, 0x7c, 0xfd, 0x1d, 0xe1, 0xb9, - 0x1a, 0xd9, 0x80, 0xbe, 0xb8, 0x3a, 0xa8, 0x44, 0xd1, 0x8a, 0x91, 0xc7, 0x02, 0xa4, 0x61, 0x20, 0x67, 0x76, 0x6c, - 0x56, 0x5e, 0x12, 0x2a, 0x51, 0x29, 0xd9, 0xda, 0xb0, 0x11, 0xeb, 0x8b, 0xaa, 0xd9, 0xd5, 0x68, 0x28, 0x99, 0xe8, - 0x6b, 0x39, 0xb9, 0xc6, 0x4d, 0x89, 0xe7, 0xe2, 0x87, 0xe0, 0xef, 0x70, 0xf0, 0xb6, 0x92, 0xcf, 0x32, 0xdf, 0xd1, - 0x39, 0x6d, 0xc3, 0x05, 0xce, 0xdc, 0x31, 0xda, 0xea, 0xf0, 0x63, 0x22, 0x67, 0x91, 0xb6, 0x6c, 0x45, 0x21, 0x16, - 0x71, 0x3d, 0x91, 0xca, 0xe6, 0xdf, 0xe8, 0x6a, 0x4b, 0x13, 0xdb, 0x37, 0x61, 0xe2, 0xf8, 0xb7, 0x78, 0x93, 0x18, - 0xe7, 0x40, 0x74, 0x16, 0x5b, 0xb4, 0xfe, 0x81, 0xd9, 0x99, 0x1e, 0x90, 0x91, 0xfb, 0xc1, 0xa7, 0xac, 0x59, 0x1d, - 0xbc, 0x7e, 0x71, 0xf0, 0xcd, 0x68, 0x5c, 0x02, 0xdf, 0x39, 0x1e, 0x7d, 0x73, 0x70, 0xbd, 0x41, 0xb4, 0xcc, 0xf4, - 0x60, 0xc1, 0x57, 0x69, 0xe9, 0xe2, 0x80, 0x2f, 0x06, 0x41, 0x16, 0x49, 0x0f, 0x78, 0x61, 0xba, 0xc5, 0x38, 0x4d, - 0x4a, 0xc3, 0x03, 0x16, 0xae, 0x52, 0xf8, 0xc8, 0x02, 0xef, 0x29, 0xd5, 0x3a, 0x2b, 0xba, 0x67, 0x71, 0x31, 0x1d, - 0xe0, 0x55, 0x06, 0xf0, 0xb7, 0x67, 0x72, 0xaf, 0xca, 0x22, 0x20, 0x8e, 0x00, 0x1a, 0xe9, 0xca, 0x23, 0x2c, 0xbb, - 0x15, 0xba, 0x5a, 0x04, 0x4e, 0xa6, 0x29, 0x4b, 0x48, 0xcf, 0x69, 0xcc, 0xf0, 0x5a, 0x48, 0x69, 0x1e, 0xdc, 0x5c, - 0x9d, 0x08, 0xdd, 0xc0, 0x7d, 0x4e, 0xe3, 0x7a, 0x0d, 0x5b, 0x89, 0xa2, 0x1e, 0xa3, 0xf1, 0x0e, 0x7a, 0x00, 0xa8, - 0xe0, 0xe0, 0x79, 0x94, 0x1c, 0x1d, 0x25, 0xca, 0x29, 0x67, 0xc5, 0x4f, 0xec, 0xfa, 0xa5, 0xe1, 0x28, 0x17, 0xd1, - 0xaf, 0xb1, 0x8e, 0x11, 0xd0, 0xdc, 0x46, 0xb1, 0x0a, 0x17, 0x40, 0xdb, 0x39, 0x09, 0x8c, 0xf1, 0x5e, 0xe4, 0x02, - 0x73, 0xaa, 0x10, 0x14, 0x4a, 0x1c, 0xac, 0x14, 0x00, 0xbd, 0x69, 0x8f, 0x58, 0x4e, 0x9a, 0x04, 0x8d, 0xe7, 0x86, - 0x16, 0xaf, 0x26, 0x16, 0xd5, 0x75, 0x2a, 0x7a, 0x0b, 0x9d, 0x02, 0xcb, 0x10, 0x03, 0x08, 0xb8, 0x31, 0xc3, 0x6e, - 0x53, 0x93, 0x23, 0xd9, 0x54, 0x15, 0x50, 0xbd, 0x6e, 0x60, 0x68, 0x37, 0x2e, 0x99, 0x3a, 0xb8, 0xdc, 0xb0, 0x4e, - 0x1c, 0x05, 0xd8, 0x7c, 0x0b, 0x91, 0xbd, 0x28, 0xd4, 0xb5, 0x9b, 0x2d, 0x97, 0xc0, 0xd7, 0xb5, 0x09, 0x5f, 0x02, - 0x34, 0x7b, 0x0d, 0x5d, 0x85, 0xd2, 0xdf, 0xe9, 0x97, 0x6e, 0x2c, 0x29, 0xb2, 0x23, 0x7d, 0xd3, 0xed, 0x8e, 0xa8, - 0x71, 0x74, 0x3d, 0xb6, 0xa5, 0xd2, 0xad, 0x8c, 0xaa, 0x15, 0x42, 0x5b, 0x72, 0xad, 0xb2, 0xc5, 0x22, 0x2d, 0x80, - 0x5b, 0x80, 0x1e, 0x9a, 0xe4, 0x58, 0x62, 0x55, 0x9b, 0x20, 0x58, 0x26, 0x4c, 0xf2, 0x8b, 0xac, 0xa6, 0xd8, 0xc1, - 0x4e, 0xa3, 0x3a, 0x51, 0xa7, 0x54, 0x0c, 0x8c, 0xf2, 0x3d, 0x05, 0xdf, 0x8e, 0xca, 0x04, 0x19, 0x7e, 0x4a, 0x14, - 0x21, 0x7d, 0x81, 0x01, 0x1f, 0x38, 0x34, 0xf7, 0x8b, 0x94, 0xc0, 0xaf, 0xf5, 0x95, 0x39, 0x32, 0xd9, 0x72, 0x05, - 0x49, 0xb8, 0x77, 0xd9, 0x99, 0x2c, 0xa2, 0x73, 0x96, 0x85, 0x0e, 0xe3, 0xbb, 0xbb, 0xc3, 0x84, 0xe9, 0x80, 0xd1, - 0x9f, 0x8e, 0x5e, 0xc6, 0x19, 0xb4, 0xea, 0xa0, 0x29, 0x0f, 0x78, 0x43, 0x1d, 0xb0, 0x33, 0x07, 0xee, 0xbc, 0x6f, - 0x60, 0x8d, 0xf3, 0x9a, 0x3e, 0x90, 0x76, 0x1e, 0xa0, 0x80, 0x41, 0x3b, 0xf7, 0x0a, 0x06, 0x1a, 0x68, 0x6d, 0x93, - 0x5e, 0x6b, 0xe3, 0x01, 0xa0, 0x4f, 0x53, 0x9e, 0x18, 0x89, 0x61, 0x9d, 0xc8, 0xc1, 0x3c, 0x0a, 0xfe, 0x89, 0x61, - 0xed, 0x3b, 0x6f, 0xd7, 0x72, 0xd0, 0x8e, 0x82, 0xf7, 0x2b, 0xd5, 0x07, 0x09, 0x1c, 0xcf, 0xd1, 0x81, 0x9d, 0x21, - 0x15, 0xd0, 0x56, 0xa5, 0xab, 0x20, 0xf5, 0x86, 0xb5, 0x78, 0x7b, 0x62, 0xc9, 0xce, 0x7a, 0x49, 0x18, 0x5f, 0x59, - 0xd1, 0xc0, 0xff, 0x4f, 0xad, 0x54, 0x90, 0x3f, 0xd8, 0xf0, 0xb5, 0x50, 0xbe, 0x65, 0x75, 0x60, 0xef, 0x10, 0x25, - 0x45, 0xaa, 0xc3, 0xe0, 0x5b, 0xa0, 0x8f, 0x73, 0x38, 0x11, 0xca, 0x79, 0x19, 0xd6, 0xf3, 0xe2, 0x51, 0x1d, 0x32, - 0x58, 0xdb, 0x3e, 0x15, 0xd0, 0xbd, 0x1a, 0x20, 0x5b, 0x01, 0xd4, 0xdc, 0xa7, 0xfc, 0xb9, 0x4f, 0xeb, 0x33, 0xa8, - 0xf4, 0xa9, 0xc4, 0x7a, 0xc5, 0x54, 0x94, 0x36, 0xad, 0x33, 0xb2, 0xce, 0x07, 0x3a, 0x3c, 0x96, 0x65, 0xb5, 0xa1, - 0x6c, 0x4e, 0xb5, 0x7f, 0xbd, 0xda, 0x60, 0x6c, 0x73, 0xc1, 0xab, 0x10, 0x64, 0xa4, 0xdf, 0x6a, 0x2b, 0x92, 0x88, - 0x86, 0xcd, 0xea, 0x6c, 0x7e, 0x15, 0x06, 0x04, 0x18, 0x4e, 0xda, 0xcf, 0x9a, 0x38, 0x0f, 0xf1, 0x78, 0xd6, 0xe7, - 0x5b, 0xd1, 0x16, 0xa9, 0x36, 0xdf, 0x8a, 0x30, 0x24, 0x54, 0x54, 0x91, 0x46, 0xc9, 0x8c, 0x77, 0xdf, 0x26, 0x2f, - 0xac, 0x38, 0x4a, 0xc0, 0x57, 0x92, 0x41, 0x1a, 0x4d, 0x07, 0x22, 0xbc, 0xae, 0x36, 0x45, 0x41, 0xc0, 0xc3, 0x98, - 0x63, 0xae, 0x09, 0x09, 0x64, 0x79, 0xc6, 0x71, 0x16, 0xaa, 0xf8, 0x93, 0x42, 0xf6, 0x6e, 0xb4, 0x6b, 0x77, 0x1b, - 0xda, 0x39, 0xa9, 0xb2, 0xd6, 0x7e, 0x70, 0x8f, 0x5a, 0xe5, 0x2c, 0x20, 0xd6, 0xb4, 0xd2, 0x70, 0x94, 0xa3, 0x06, - 0x16, 0xa5, 0xc2, 0x26, 0xb6, 0xc8, 0x72, 0xd5, 0x39, 0x66, 0xc8, 0x80, 0xfe, 0x36, 0xbb, 0xde, 0x5c, 0x13, 0x80, - 0x5b, 0x4d, 0xac, 0x53, 0xc9, 0xfe, 0x25, 0xdd, 0x51, 0x17, 0x7b, 0x2a, 0xbb, 0x6c, 0x97, 0x2a, 0x7b, 0x1a, 0x53, - 0x9e, 0xba, 0x39, 0x1f, 0x71, 0x47, 0x46, 0xe1, 0x88, 0xb7, 0xde, 0x68, 0x66, 0x9d, 0x32, 0xd5, 0x00, 0x08, 0x74, - 0xa5, 0xce, 0xb0, 0xaf, 0x38, 0x62, 0xd4, 0x52, 0x89, 0xd1, 0xd4, 0x47, 0x19, 0xd5, 0x74, 0x56, 0x80, 0x7c, 0x3f, - 0xd8, 0xe1, 0x9f, 0xb0, 0x6a, 0xc9, 0x50, 0x0b, 0x18, 0x73, 0xa6, 0x89, 0x8c, 0x22, 0x1b, 0x54, 0x12, 0x57, 0x61, - 0x90, 0x48, 0x68, 0x02, 0xea, 0x25, 0xbe, 0x24, 0x55, 0x24, 0x35, 0xa0, 0x33, 0x5f, 0x5a, 0xd4, 0x9b, 0x4a, 0x0c, - 0xe6, 0x5e, 0xc5, 0x37, 0xe9, 0xeb, 0x17, 0xc6, 0xa8, 0xbe, 0x63, 0xad, 0x6f, 0xdd, 0x82, 0xbc, 0x02, 0x3e, 0x8f, - 0x1c, 0x98, 0x80, 0x01, 0x27, 0x63, 0x8c, 0xba, 0x95, 0xa8, 0x17, 0x6f, 0x25, 0x14, 0x8b, 0x98, 0xe0, 0xdd, 0xe3, - 0x29, 0x22, 0x86, 0x87, 0x85, 0xb2, 0xaa, 0xa6, 0xa7, 0x3a, 0xea, 0xdc, 0x83, 0x55, 0xe9, 0x62, 0x93, 0xa4, 0x1e, - 0xde, 0x23, 0xc1, 0xc7, 0xbc, 0xea, 0x2c, 0x3e, 0xc7, 0xe3, 0xa4, 0xf2, 0xf1, 0xda, 0x41, 0x44, 0xf0, 0xb3, 0x73, - 0x72, 0x7f, 0x2d, 0xc9, 0x03, 0x8c, 0x2c, 0x88, 0xdd, 0x28, 0xa8, 0xb0, 0xb2, 0xd6, 0xce, 0x15, 0x49, 0x7a, 0x56, - 0xa1, 0xed, 0x10, 0x5f, 0x4f, 0xe1, 0x2d, 0x54, 0xc2, 0xf7, 0xc3, 0xc8, 0x77, 0x08, 0x06, 0xb6, 0xdc, 0x01, 0x2a, - 0xfa, 0x19, 0x07, 0x0b, 0xed, 0x0c, 0x95, 0xcf, 0x2d, 0x39, 0x33, 0x84, 0x25, 0xa2, 0xd0, 0x18, 0x44, 0x1a, 0x5d, - 0x90, 0x3a, 0x07, 0x72, 0x55, 0xf1, 0x02, 0x68, 0x0c, 0xfa, 0x6d, 0xc6, 0x15, 0x65, 0x84, 0xa6, 0xa5, 0x57, 0x65, - 0x85, 0xb7, 0xdd, 0x39, 0xa7, 0xb6, 0x2d, 0x2a, 0xc8, 0x5e, 0xa1, 0xd5, 0x8b, 0x73, 0x47, 0x65, 0xbc, 0xbb, 0xc4, - 0x14, 0x02, 0xda, 0x8a, 0x36, 0xcd, 0xd0, 0xc2, 0xa7, 0x1e, 0xdf, 0xe6, 0x60, 0xa8, 0x23, 0x32, 0xee, 0x9f, 0x41, - 0x82, 0x6a, 0x9c, 0xb6, 0x7b, 0xbb, 0xbb, 0x03, 0xb1, 0xd7, 0xa4, 0x07, 0xb9, 0x7f, 0x18, 0x45, 0x90, 0x04, 0x85, - 0xf4, 0xad, 0x32, 0x2e, 0x39, 0xab, 0xa8, 0xfd, 0x2a, 0xa8, 0xcf, 0x12, 0x34, 0x1d, 0x91, 0x60, 0xb9, 0x48, 0xd9, - 0x29, 0xa0, 0x3b, 0x32, 0xb8, 0x05, 0x48, 0x01, 0x18, 0x56, 0x4f, 0x04, 0x92, 0x95, 0x0f, 0xef, 0xe1, 0x79, 0x66, - 0xc1, 0xc1, 0x6f, 0x22, 0x36, 0x77, 0x61, 0xeb, 0xd3, 0x95, 0x3f, 0x5b, 0x10, 0x03, 0xb1, 0xf1, 0x76, 0xd9, 0x22, - 0x4c, 0x58, 0x45, 0xb6, 0x22, 0xff, 0x48, 0x45, 0xb1, 0x24, 0x72, 0x2f, 0x51, 0x25, 0x3f, 0x28, 0xce, 0x16, 0x74, - 0x52, 0x2f, 0x5a, 0xf8, 0x8b, 0xa1, 0x27, 0xf1, 0x52, 0xae, 0xc5, 0x81, 0xaa, 0x03, 0x59, 0x0a, 0xbb, 0xea, 0xee, - 0x4e, 0x04, 0xab, 0x02, 0x16, 0x05, 0xbd, 0x2c, 0x68, 0x14, 0xff, 0x91, 0x5a, 0x61, 0xa7, 0x78, 0x7b, 0x04, 0x7a, - 0x44, 0xfd, 0x00, 0x5e, 0x83, 0x20, 0xf1, 0xac, 0x94, 0x10, 0x80, 0x64, 0x11, 0x72, 0xc1, 0x07, 0xa9, 0xe2, 0x86, - 0x7a, 0xca, 0x7f, 0xc5, 0xf5, 0x29, 0x67, 0x74, 0xf7, 0x9a, 0x51, 0xa0, 0x7c, 0x2d, 0x68, 0x63, 0xba, 0xcf, 0x46, - 0x0e, 0xcb, 0x23, 0xa5, 0x4d, 0xf4, 0xa4, 0x66, 0xd5, 0xc2, 0xa4, 0xe4, 0xbf, 0xd0, 0xc3, 0x27, 0xa9, 0x31, 0xa3, - 0xac, 0xa3, 0x74, 0x56, 0x9f, 0x16, 0xb3, 0xf1, 0xb8, 0xf6, 0x65, 0xcb, 0xb2, 0x78, 0x60, 0xf9, 0xf7, 0xa0, 0x14, - 0x62, 0x21, 0x23, 0x17, 0x93, 0x54, 0xe1, 0xe4, 0x77, 0x38, 0x39, 0xc8, 0xc4, 0x71, 0xac, 0x7d, 0x6e, 0xc1, 0xdf, - 0x80, 0x88, 0x90, 0x4f, 0xd2, 0x08, 0x4d, 0x06, 0xe1, 0xe3, 0xa8, 0x51, 0xba, 0x60, 0x09, 0xe9, 0x07, 0x90, 0x9d, - 0x96, 0x29, 0x50, 0x83, 0xc4, 0x54, 0xa0, 0x79, 0x07, 0xdd, 0x6b, 0xa0, 0xf5, 0x8c, 0xc9, 0xab, 0x7a, 0x0c, 0x34, - 0x5f, 0x78, 0x01, 0xd5, 0x63, 0x8d, 0xd9, 0xaa, 0x1d, 0x1b, 0x6c, 0xe6, 0x18, 0x5d, 0xd0, 0x45, 0x63, 0xab, 0xa8, - 0x86, 0x56, 0x81, 0xa1, 0x0b, 0x38, 0x2a, 0x4b, 0x98, 0x63, 0x83, 0xda, 0x7d, 0x47, 0x4b, 0x7b, 0xcf, 0x70, 0x74, - 0x49, 0x8e, 0x6d, 0xb3, 0x6c, 0x26, 0xf0, 0xec, 0x7c, 0x70, 0xd2, 0x54, 0x58, 0x1b, 0x92, 0xe7, 0xd5, 0xf9, 0xb5, - 0x7f, 0x48, 0x02, 0x8e, 0x7b, 0xa3, 0x9d, 0xa6, 0x54, 0xdc, 0x1b, 0xa3, 0xfc, 0x3a, 0x2b, 0xce, 0x25, 0x54, 0x8b, - 0x12, 0xb2, 0xec, 0xd6, 0x5a, 0x52, 0x52, 0x29, 0x17, 0xd0, 0x36, 0xcb, 0x42, 0x37, 0x11, 0x08, 0xf2, 0x47, 0xbf, - 0x50, 0xe9, 0x8c, 0x7f, 0x61, 0xc7, 0xc6, 0xda, 0xd4, 0x72, 0x60, 0x08, 0x0a, 0x6d, 0xba, 0xd9, 0xfb, 0x1a, 0xf2, - 0xc5, 0xb4, 0x3f, 0xe3, 0xc0, 0xba, 0xdf, 0x8e, 0xca, 0xfe, 0x5d, 0xb7, 0x45, 0x96, 0xb1, 0x10, 0xad, 0x14, 0xc4, - 0xcd, 0xc4, 0xbf, 0x14, 0x66, 0x92, 0x8b, 0x20, 0xa6, 0x9a, 0x04, 0xf7, 0x19, 0x8d, 0x14, 0xa0, 0x12, 0x24, 0xdd, - 0xb0, 0x23, 0x9a, 0x82, 0x5b, 0x93, 0x56, 0x28, 0x6f, 0x3d, 0x6c, 0xa1, 0x65, 0x1a, 0xee, 0xdb, 0x0f, 0xc2, 0xbc, - 0x32, 0x10, 0x40, 0x27, 0x23, 0x7a, 0x6b, 0xfd, 0xa6, 0x8e, 0x10, 0x9b, 0xb0, 0x24, 0x42, 0x58, 0x2c, 0x53, 0x7c, - 0x20, 0x8a, 0x3b, 0xf7, 0xb6, 0xe9, 0x23, 0xd1, 0x5f, 0x5a, 0xb3, 0x76, 0xca, 0xaa, 0xb5, 0xed, 0xa1, 0xe2, 0xf3, - 0x99, 0x1b, 0x07, 0x31, 0xe1, 0x6a, 0xec, 0x12, 0xa9, 0xad, 0xb5, 0x42, 0x44, 0xe6, 0xa1, 0xef, 0x1c, 0x1d, 0xb9, - 0xd9, 0x72, 0x24, 0x54, 0x76, 0x67, 0x88, 0xf4, 0x49, 0x68, 0x3f, 0xb4, 0x49, 0x14, 0x0b, 0x3d, 0x7b, 0x5c, 0x5a, - 0x17, 0x2f, 0xaf, 0x4b, 0x8d, 0x82, 0x86, 0x18, 0x2a, 0xfd, 0x0d, 0x5c, 0xdf, 0xaf, 0xbc, 0xfe, 0xa2, 0x0e, 0x3c, - 0xb9, 0x7b, 0x1e, 0x5a, 0x14, 0x70, 0x0e, 0x5a, 0x03, 0x4c, 0xd5, 0x81, 0xe0, 0x20, 0xf1, 0x98, 0xe4, 0x51, 0x43, - 0x26, 0x3b, 0xdf, 0x1a, 0xe4, 0x4c, 0x29, 0xcf, 0xc8, 0x04, 0xb8, 0xec, 0xfa, 0x2b, 0xf2, 0x75, 0x69, 0xaa, 0x45, - 0x14, 0xd7, 0x43, 0x5a, 0x8b, 0xe2, 0x69, 0x57, 0x71, 0x91, 0x7e, 0xa5, 0xe2, 0x42, 0x3b, 0x58, 0x0f, 0xc8, 0x94, - 0x87, 0x85, 0xa5, 0xca, 0xd4, 0x36, 0xb8, 0x1b, 0x87, 0x31, 0x51, 0xf6, 0xbb, 0xab, 0x34, 0xf9, 0x8d, 0x58, 0xf0, - 0x67, 0xb0, 0xce, 0x81, 0xf9, 0x35, 0xaf, 0x38, 0xff, 0x2b, 0x5b, 0xb4, 0xd5, 0xef, 0xb4, 0xf9, 0xa7, 0x65, 0x3d, - 0x3c, 0x38, 0x4c, 0x76, 0xac, 0x4e, 0x60, 0xe2, 0xae, 0xcb, 0x45, 0x8a, 0xc8, 0x00, 0xda, 0x22, 0x99, 0x0c, 0xf8, - 0xc8, 0xca, 0xb2, 0xeb, 0x3b, 0xcd, 0x02, 0xc2, 0x5e, 0x02, 0x37, 0xdb, 0xff, 0x35, 0x35, 0x73, 0xf2, 0x55, 0x5f, - 0xe8, 0xd2, 0xb1, 0xb6, 0x2c, 0x65, 0x8c, 0xf7, 0xbd, 0x27, 0xd9, 0x2c, 0x3f, 0x85, 0xff, 0x35, 0x75, 0xdb, 0x99, - 0x65, 0x83, 0x68, 0x88, 0x43, 0x6b, 0x2b, 0x47, 0xbc, 0xdc, 0x43, 0x8c, 0xe6, 0xab, 0x55, 0xe8, 0x0b, 0x56, 0xa1, - 0xcf, 0x16, 0x6e, 0x1f, 0xf4, 0xaa, 0xda, 0x38, 0x21, 0x8f, 0xc6, 0x0b, 0x61, 0xe4, 0xdf, 0xc2, 0x1a, 0x58, 0xe6, - 0xe5, 0x27, 0x84, 0x43, 0x86, 0x65, 0xa9, 0xce, 0x5f, 0x74, 0xe7, 0x27, 0xc7, 0x71, 0x38, 0x28, 0x72, 0x8a, 0xdb, - 0x4a, 0x48, 0xc9, 0x92, 0x38, 0x47, 0x3c, 0x64, 0x7b, 0xd2, 0x24, 0xb4, 0x6b, 0x45, 0xe1, 0x7d, 0x91, 0xbb, 0xca, - 0x61, 0x53, 0xe4, 0x7a, 0xd1, 0xbb, 0x33, 0x2c, 0x1d, 0xa9, 0xb5, 0x8d, 0xc5, 0x90, 0x0c, 0xd6, 0x99, 0x41, 0x5d, - 0x05, 0xeb, 0x87, 0xcc, 0x49, 0xfb, 0x19, 0x4e, 0xd9, 0x8b, 0x6c, 0x71, 0xab, 0xad, 0xf2, 0x77, 0xa2, 0xc4, 0x01, - 0x16, 0xd2, 0xa8, 0x6f, 0xc2, 0x44, 0xce, 0xcf, 0x44, 0xb9, 0x81, 0x60, 0xea, 0x2b, 0x8a, 0xaf, 0x51, 0x01, 0x25, - 0x02, 0x71, 0x20, 0x8c, 0xf5, 0x89, 0xea, 0x2c, 0x47, 0xbc, 0x13, 0x22, 0xbc, 0x03, 0x60, 0xef, 0x58, 0x70, 0x08, - 0x1c, 0x96, 0xbe, 0xed, 0xac, 0x73, 0x45, 0x28, 0x94, 0x13, 0x18, 0x33, 0x48, 0x7c, 0xd6, 0x69, 0x26, 0xa8, 0xd1, - 0x63, 0x32, 0x28, 0x0f, 0x04, 0xfd, 0xb5, 0xa8, 0xaa, 0x6f, 0x07, 0x77, 0xd0, 0x3e, 0xae, 0x5f, 0x6e, 0x91, 0x1d, - 0xfe, 0xbc, 0xa3, 0xc2, 0xf2, 0xf1, 0xac, 0x55, 0xf9, 0x9a, 0x29, 0x0d, 0x0c, 0xb0, 0x3e, 0xde, 0x61, 0xce, 0x36, - 0xdd, 0x77, 0x77, 0x87, 0x87, 0x7b, 0x55, 0x5c, 0x70, 0x62, 0x36, 0x96, 0x64, 0xae, 0x65, 0xaa, 0x4d, 0xd1, 0x97, - 0xb4, 0xed, 0x14, 0x3d, 0x6a, 0x9d, 0xdd, 0xae, 0x38, 0x21, 0x47, 0xbf, 0x05, 0xb3, 0xcf, 0x2a, 0x24, 0x65, 0xd0, - 0x8e, 0xa1, 0xad, 0x8b, 0x0c, 0x25, 0xca, 0x17, 0x46, 0xe9, 0xc4, 0x21, 0x57, 0xcd, 0x75, 0xc1, 0x0e, 0xb8, 0xa9, - 0x55, 0xb9, 0x08, 0x81, 0xe7, 0x40, 0x9b, 0xf3, 0x10, 0x78, 0xfb, 0x72, 0x03, 0x2b, 0xa1, 0x6c, 0xe9, 0x5e, 0x54, - 0xdf, 0x18, 0x10, 0x20, 0xd3, 0x85, 0xeb, 0x41, 0x35, 0x9a, 0x4f, 0xca, 0xb0, 0x9c, 0xbd, 0x44, 0x4b, 0x7b, 0xe2, - 0x58, 0xdb, 0x7d, 0xdf, 0xec, 0xf0, 0xad, 0x96, 0x12, 0x8c, 0x31, 0x7b, 0x30, 0x22, 0x9c, 0x6b, 0x0c, 0x39, 0x1b, - 0x52, 0x97, 0xb9, 0x6e, 0x09, 0x7b, 0xb8, 0x5d, 0xe0, 0xdc, 0xcc, 0x3c, 0x09, 0x37, 0x07, 0xfc, 0x77, 0x75, 0x76, - 0x8c, 0xb7, 0x5f, 0x25, 0x8b, 0x5d, 0xc2, 0xad, 0xc7, 0x63, 0xd8, 0x17, 0xe3, 0x4a, 0xf1, 0xaf, 0x27, 0xca, 0xc3, - 0x33, 0x18, 0xf9, 0x44, 0xca, 0x0b, 0x60, 0x57, 0x2d, 0xc3, 0xf7, 0x93, 0x59, 0x79, 0x9a, 0x92, 0xc5, 0x3b, 0xb6, - 0x3a, 0xc7, 0x80, 0x5e, 0x85, 0x57, 0xfa, 0xea, 0xaa, 0x50, 0xa9, 0xa0, 0xac, 0x5b, 0xfe, 0x9a, 0x3f, 0x47, 0x80, - 0x42, 0xe2, 0x2b, 0x8a, 0x75, 0xab, 0x44, 0x4f, 0x0d, 0x7f, 0x79, 0x76, 0x72, 0x2e, 0x33, 0x30, 0x2e, 0xcf, 0x1e, - 0x9f, 0xcb, 0x2c, 0xc0, 0xef, 0x3f, 0x9d, 0xb7, 0x66, 0x1d, 0x08, 0x01, 0xb1, 0x5c, 0x38, 0x06, 0x29, 0x2d, 0x67, - 0x03, 0xaa, 0x70, 0x1f, 0x41, 0xff, 0x87, 0x3e, 0x04, 0x8d, 0x5e, 0xa8, 0xa7, 0x37, 0x08, 0xba, 0x21, 0x09, 0xb4, - 0x88, 0x19, 0x14, 0x2a, 0x16, 0xd1, 0x69, 0x74, 0x8c, 0x86, 0xd8, 0x5c, 0x00, 0x1e, 0x66, 0x36, 0x09, 0x42, 0x46, - 0xf7, 0x95, 0x02, 0x07, 0xbf, 0x25, 0x51, 0x1a, 0x64, 0x73, 0x72, 0xd3, 0x37, 0xb2, 0xa1, 0x25, 0xb8, 0xa2, 0x53, - 0xb5, 0x91, 0x93, 0xc8, 0x4d, 0xa6, 0x1b, 0xab, 0x57, 0x11, 0x37, 0xe2, 0x57, 0xa6, 0xd3, 0xa9, 0x4e, 0x81, 0x0d, - 0xa3, 0x38, 0x07, 0x37, 0xa7, 0xe6, 0xf2, 0x59, 0xea, 0xd9, 0xa1, 0x0e, 0x73, 0x71, 0x1b, 0x95, 0xed, 0x3d, 0x94, - 0x55, 0xc6, 0x50, 0x0f, 0xbd, 0x45, 0x8e, 0xef, 0x1f, 0x7c, 0x95, 0xf1, 0x0b, 0x87, 0xeb, 0x21, 0xcd, 0x85, 0xed, - 0xb2, 0xa6, 0x74, 0x0e, 0x83, 0x67, 0x5f, 0x4a, 0x72, 0x58, 0xea, 0x7f, 0x99, 0x85, 0xb2, 0xc6, 0x6b, 0xf6, 0x5f, - 0xaa, 0xdd, 0xed, 0x30, 0x50, 0xb7, 0x35, 0xae, 0xb8, 0x79, 0xe3, 0x29, 0x7e, 0x96, 0x78, 0x63, 0x10, 0xb6, 0xfc, - 0xb0, 0x19, 0x3e, 0xef, 0x75, 0xc4, 0xd2, 0x81, 0x71, 0x40, 0x70, 0xa2, 0xce, 0x17, 0xfa, 0xda, 0xb8, 0x4e, 0x07, - 0x29, 0x22, 0x25, 0x6e, 0x95, 0x18, 0xe8, 0x14, 0x9d, 0xe4, 0xa8, 0x2c, 0xc6, 0xea, 0xd2, 0xce, 0xb0, 0xde, 0xc3, - 0x7e, 0x48, 0x85, 0xaa, 0x39, 0x35, 0xcf, 0x00, 0x22, 0x09, 0xd8, 0xa3, 0x27, 0x4d, 0xa3, 0xcb, 0x36, 0xcb, 0x43, - 0x4b, 0xdf, 0x15, 0xdc, 0xd3, 0x53, 0x53, 0x33, 0x32, 0xae, 0x7c, 0xec, 0xed, 0xf6, 0xb7, 0x47, 0xae, 0xc8, 0x7b, - 0x9b, 0x54, 0x35, 0x0b, 0x21, 0x45, 0xe3, 0xda, 0x56, 0x7a, 0x1a, 0x05, 0xda, 0x61, 0x57, 0x2b, 0x0a, 0x1b, 0x05, - 0xd5, 0xa8, 0xb0, 0x8b, 0xf8, 0x39, 0x34, 0x90, 0x2b, 0xb0, 0x6d, 0xfe, 0x59, 0x7b, 0x3b, 0x5b, 0x91, 0xe1, 0x0b, - 0x5c, 0x8b, 0x84, 0x22, 0x32, 0xbc, 0x68, 0x57, 0xab, 0xaa, 0x4e, 0x9a, 0xae, 0x06, 0x5e, 0x45, 0x06, 0xec, 0xe6, - 0x9f, 0x39, 0x2a, 0xd7, 0xc2, 0x04, 0x0c, 0xef, 0xa9, 0x6b, 0x51, 0x75, 0xd3, 0xaa, 0xef, 0x3a, 0x76, 0x88, 0x86, - 0xa6, 0x58, 0x74, 0xc8, 0x3c, 0x0f, 0xcf, 0x2d, 0x54, 0xf9, 0x05, 0x72, 0xe7, 0x3a, 0x7b, 0x31, 0x61, 0x60, 0x29, - 0x1b, 0x29, 0xd6, 0xa9, 0x51, 0x14, 0x50, 0x00, 0x97, 0xcf, 0x48, 0xc7, 0xc6, 0xe3, 0xc6, 0xa7, 0x27, 0xc6, 0xb6, - 0x71, 0xc8, 0x9f, 0x6f, 0x49, 0xe8, 0xf8, 0x5a, 0x93, 0x07, 0xdf, 0xaa, 0xec, 0x0b, 0x35, 0xec, 0x5f, 0x50, 0xd8, - 0x1d, 0xf6, 0x72, 0x65, 0x5c, 0x15, 0x07, 0x50, 0xa5, 0xe7, 0xb9, 0xe6, 0x6a, 0x5a, 0xd0, 0x4a, 0x89, 0x65, 0x7e, - 0x15, 0x1c, 0xb7, 0x8e, 0x38, 0x7c, 0xab, 0x34, 0xaa, 0x3e, 0x2d, 0x49, 0xa5, 0xa3, 0xcf, 0xf6, 0x14, 0xad, 0x01, - 0xe8, 0x14, 0xd6, 0x82, 0xb3, 0x8f, 0x3e, 0x77, 0xe2, 0xb2, 0xa5, 0x84, 0xc0, 0xa2, 0xbd, 0x1f, 0xe7, 0xa5, 0xe7, - 0xcb, 0x3d, 0xd0, 0xf6, 0x43, 0xf2, 0x46, 0x74, 0xc6, 0xeb, 0xeb, 0xa8, 0xe9, 0x57, 0xcf, 0x70, 0xa3, 0x29, 0xc8, - 0x3d, 0x4d, 0xb5, 0x08, 0xa3, 0x41, 0x60, 0x9a, 0xa5, 0x4f, 0x60, 0xd2, 0x27, 0x13, 0x45, 0x06, 0xad, 0x66, 0x52, - 0x28, 0xb0, 0xaf, 0xa0, 0x75, 0x6a, 0xe2, 0x9c, 0xa2, 0x5d, 0x11, 0xb4, 0xb9, 0x25, 0x9d, 0xdc, 0x05, 0x1a, 0x3e, - 0x00, 0x5d, 0x63, 0x98, 0x2a, 0x92, 0x10, 0x61, 0x96, 0x3e, 0xaf, 0xb4, 0xc3, 0xbe, 0x5e, 0x28, 0x20, 0x91, 0x30, - 0xf1, 0x6b, 0x14, 0xf1, 0x63, 0x71, 0xe6, 0x0f, 0xd3, 0x3e, 0x1e, 0xc4, 0xca, 0x90, 0x18, 0x42, 0xfc, 0x4a, 0x03, - 0xb6, 0x9d, 0x28, 0x38, 0x36, 0x1e, 0xb9, 0xd6, 0x1d, 0x87, 0x25, 0x87, 0xa1, 0x2c, 0x04, 0x4f, 0x8d, 0xf6, 0x7d, - 0x21, 0xe1, 0xeb, 0x28, 0x8b, 0xd9, 0xac, 0x90, 0x97, 0x31, 0x4e, 0x0b, 0x15, 0xa7, 0xb2, 0x5c, 0x43, 0x5e, 0x0c, - 0x94, 0xa7, 0x2b, 0xc3, 0x00, 0x93, 0x94, 0xa4, 0x6c, 0x2d, 0x0a, 0x15, 0xc6, 0xce, 0x54, 0x26, 0xd4, 0xa5, 0x94, - 0x37, 0x63, 0x95, 0x85, 0x0c, 0xf9, 0x2d, 0x1a, 0x2d, 0x54, 0x8d, 0x01, 0xc3, 0x52, 0xd2, 0x6a, 0xfc, 0x21, 0x42, - 0xad, 0x86, 0x01, 0x81, 0x6d, 0xde, 0x01, 0xbf, 0x07, 0x07, 0x1a, 0x41, 0xa0, 0x19, 0xfb, 0xa9, 0xb8, 0xe9, 0xcd, - 0x82, 0xba, 0x68, 0xd7, 0x22, 0x9f, 0x0d, 0x9c, 0x50, 0x3f, 0x65, 0x01, 0xea, 0x65, 0x59, 0xbd, 0x29, 0x17, 0x69, - 0x27, 0x44, 0x26, 0x70, 0x8e, 0xdf, 0xe5, 0x53, 0x3c, 0xaf, 0xc8, 0xa9, 0x5c, 0x6d, 0x13, 0x36, 0x4b, 0x2a, 0x81, - 0xfd, 0x51, 0x36, 0x2f, 0xa3, 0x79, 0x29, 0xcc, 0x18, 0x95, 0xc6, 0x38, 0x63, 0xbd, 0x93, 0x70, 0xb7, 0x9f, 0x07, - 0xc6, 0x28, 0xe5, 0x45, 0x47, 0x35, 0xac, 0xed, 0x78, 0x2d, 0xbd, 0x26, 0xca, 0xc3, 0x4a, 0xad, 0x09, 0xc3, 0x9f, - 0x8a, 0xb9, 0x91, 0xf6, 0xa3, 0x45, 0x1e, 0x2c, 0x62, 0xeb, 0x4f, 0x24, 0xd3, 0xac, 0x65, 0x05, 0x3e, 0x4e, 0x8a, - 0x70, 0xa2, 0x25, 0x7d, 0xd3, 0x33, 0xcb, 0x22, 0xfc, 0x5b, 0xfc, 0x9e, 0xf8, 0x61, 0x6b, 0x3f, 0x30, 0xd6, 0x20, - 0x1b, 0x71, 0x29, 0x55, 0x9e, 0x3a, 0xd0, 0x55, 0x93, 0xe0, 0x50, 0xbf, 0x58, 0xc7, 0x55, 0x9d, 0x2e, 0xf0, 0xa3, - 0x42, 0xdd, 0xc2, 0xc3, 0x13, 0xb4, 0x37, 0x24, 0x92, 0xa4, 0x2d, 0x8d, 0xb5, 0xda, 0xc5, 0x21, 0x3d, 0x7b, 0x23, - 0x2e, 0xbd, 0x6c, 0xc8, 0x90, 0x36, 0xb0, 0xce, 0x42, 0xd6, 0xf9, 0x33, 0xff, 0x39, 0x6a, 0x19, 0x74, 0xd4, 0xa5, - 0x18, 0xcf, 0x91, 0x11, 0xef, 0x07, 0xb3, 0xba, 0x87, 0xb8, 0x08, 0x41, 0x69, 0x7b, 0x6a, 0xc7, 0x2f, 0x4d, 0x1e, - 0xc9, 0x42, 0xc6, 0x19, 0x7c, 0x76, 0x3f, 0x4b, 0xd4, 0x59, 0x47, 0xc5, 0x94, 0x67, 0x80, 0x4c, 0x07, 0x4b, 0x38, - 0x50, 0x61, 0x35, 0x1d, 0xaa, 0xc4, 0xf0, 0x30, 0x95, 0x5f, 0x78, 0x43, 0x6d, 0x37, 0x2b, 0x03, 0x99, 0x64, 0xfb, - 0x35, 0x1c, 0xd8, 0x4c, 0x7f, 0xe0, 0x30, 0x6d, 0x9b, 0xf2, 0xea, 0x8a, 0xbb, 0x6d, 0x57, 0xa2, 0xf4, 0x74, 0x8e, - 0x58, 0x0a, 0xfd, 0x8a, 0x0e, 0x87, 0xd3, 0xd5, 0xe2, 0x76, 0xeb, 0x70, 0x10, 0xd6, 0x7a, 0x45, 0x84, 0x3f, 0x73, - 0xdb, 0x6e, 0xe3, 0x2d, 0x14, 0xf3, 0x11, 0x42, 0xa4, 0x8f, 0xc2, 0x11, 0x94, 0x05, 0x6e, 0xac, 0xdc, 0xc7, 0x51, - 0x56, 0x7c, 0x2f, 0xa7, 0x19, 0x3f, 0x31, 0x8d, 0xd5, 0xce, 0x0a, 0xb5, 0xa7, 0x6d, 0x74, 0x67, 0xeb, 0x8c, 0xb0, - 0xfd, 0x4a, 0x9a, 0x2d, 0xc4, 0xfd, 0x51, 0x43, 0x21, 0xd0, 0x59, 0x4a, 0x9b, 0xa8, 0xf8, 0xae, 0x3d, 0x83, 0x4c, - 0xea, 0x64, 0xc9, 0x5b, 0x06, 0x3b, 0x39, 0x6b, 0xc3, 0x42, 0xc9, 0x21, 0xf2, 0x2a, 0x46, 0x8f, 0x72, 0x9b, 0xd7, - 0x26, 0x27, 0xd3, 0x3a, 0x14, 0x77, 0x7e, 0xbf, 0x5d, 0x65, 0x0b, 0xb9, 0xc3, 0xb6, 0x19, 0xf6, 0xce, 0x98, 0xc0, - 0xc1, 0xd8, 0xe2, 0x48, 0x7c, 0x39, 0xa3, 0x20, 0x04, 0x74, 0xf5, 0xf8, 0x3d, 0x3e, 0x43, 0xd1, 0x14, 0x5c, 0xaa, - 0xb4, 0x85, 0xcd, 0xf0, 0xb9, 0x4f, 0xfa, 0x5a, 0x00, 0x83, 0x59, 0xd9, 0xf7, 0x2e, 0x56, 0x0d, 0xed, 0x85, 0x98, - 0x01, 0x10, 0x0b, 0x1a, 0xa4, 0x86, 0x9f, 0xe2, 0x74, 0xb4, 0x44, 0x11, 0x7b, 0x39, 0x91, 0xe8, 0x80, 0x8b, 0xb9, - 0x47, 0xf2, 0x47, 0xb6, 0x8b, 0xf8, 0xad, 0xbd, 0xf7, 0x12, 0x0d, 0x70, 0xbd, 0xaa, 0x59, 0xf7, 0xf0, 0xe5, 0x0a, - 0x4d, 0x42, 0x29, 0xca, 0xd8, 0x14, 0x40, 0xe1, 0xa6, 0xaa, 0x0b, 0x26, 0x66, 0xbc, 0xb8, 0xa5, 0x96, 0x66, 0xd9, - 0xf5, 0xc1, 0x69, 0xf6, 0x28, 0x7a, 0x6e, 0xd9, 0xf9, 0xa2, 0x63, 0xbf, 0x56, 0xa5, 0xe4, 0xe4, 0xaa, 0x88, 0x9a, - 0x7a, 0x2f, 0x76, 0x64, 0x44, 0xb9, 0x14, 0x03, 0x11, 0xb1, 0x63, 0x9e, 0x8c, 0xad, 0x65, 0x44, 0x74, 0xcf, 0xd9, - 0xa7, 0xba, 0x05, 0x9b, 0x17, 0x11, 0x1d, 0xff, 0xfa, 0xe7, 0xd7, 0xd7, 0xf1, 0x95, 0x42, 0x51, 0x72, 0x2c, 0x62, - 0xd8, 0xb4, 0xaf, 0x29, 0x71, 0xf0, 0x7e, 0x78, 0xff, 0x1d, 0x67, 0x69, 0xed, 0x1e, 0xec, 0xb4, 0xaa, 0xea, 0x87, - 0x3a, 0xad, 0x5c, 0x05, 0xd6, 0x3e, 0x4b, 0x14, 0xcc, 0xfd, 0x5e, 0xa7, 0xa9, 0x32, 0xa1, 0x23, 0xd9, 0x44, 0xc0, - 0xc6, 0x74, 0x6b, 0xed, 0xe8, 0x8e, 0xb4, 0x46, 0x4e, 0x2d, 0x06, 0x35, 0x7e, 0x70, 0xf4, 0x09, 0x4a, 0xc3, 0x8e, - 0xae, 0x52, 0xa9, 0xbc, 0x52, 0xc1, 0xf1, 0xb1, 0xca, 0x18, 0xd3, 0x88, 0xd9, 0x56, 0xb5, 0x02, 0xea, 0xc0, 0x97, - 0xb6, 0x2a, 0x20, 0xdb, 0x4f, 0x51, 0x15, 0xa8, 0xdf, 0x3f, 0x2b, 0x43, 0x3e, 0x57, 0x0b, 0x5a, 0xfa, 0x68, 0x67, - 0xe0, 0xf4, 0x94, 0x95, 0x81, 0x01, 0x2a, 0x9e, 0x10, 0xe5, 0xcb, 0xe7, 0xb1, 0xea, 0xf7, 0xd5, 0x5c, 0x63, 0x74, - 0x15, 0x84, 0x1a, 0xd2, 0x63, 0xc8, 0x3e, 0x6e, 0xa7, 0x1d, 0x48, 0x2c, 0x38, 0xc1, 0x6e, 0xae, 0xa1, 0xd1, 0x48, - 0x82, 0xfc, 0xbe, 0xd1, 0xc0, 0xd7, 0x30, 0x1a, 0xc9, 0x79, 0x94, 0xd3, 0x68, 0x48, 0x76, 0x4c, 0x21, 0xc4, 0x06, - 0x51, 0xf6, 0xed, 0x29, 0xa8, 0xf6, 0x35, 0xe4, 0xf6, 0x5b, 0xe8, 0xbb, 0x2e, 0x6e, 0x96, 0x90, 0xb6, 0xea, 0x60, - 0x2b, 0x0f, 0x74, 0xbc, 0x60, 0x9d, 0xbf, 0xc1, 0xa4, 0x26, 0x6d, 0x8c, 0xa7, 0x8c, 0x58, 0xd0, 0x92, 0xa0, 0xbb, - 0x1e, 0x02, 0xbb, 0x0e, 0x3f, 0x28, 0x8c, 0xe9, 0x49, 0x49, 0x4f, 0x8b, 0x94, 0x8b, 0x82, 0x9c, 0x32, 0xab, 0x22, - 0x03, 0x7a, 0x69, 0x5b, 0xf9, 0xd5, 0x4e, 0xa1, 0xfe, 0xde, 0x55, 0x02, 0xeb, 0x31, 0xc6, 0xc5, 0x2e, 0xec, 0xe6, - 0xb4, 0x01, 0x02, 0x1b, 0x3e, 0x95, 0xba, 0x6c, 0xa3, 0x26, 0x7f, 0x1e, 0xc3, 0xea, 0x45, 0xcd, 0xb6, 0xbb, 0xb9, - 0x95, 0x62, 0xdb, 0x5a, 0xa8, 0xce, 0xf5, 0x97, 0xb5, 0xdd, 0xf7, 0x0c, 0x6f, 0x6a, 0xe9, 0xbd, 0x5d, 0x1b, 0xca, - 0x57, 0xfb, 0x57, 0xc9, 0x7f, 0xeb, 0x23, 0xfb, 0xad, 0x32, 0xdb, 0xae, 0x7a, 0x7f, 0xe8, 0xb8, 0x4d, 0x29, 0x1a, - 0x04, 0x7d, 0x69, 0xa4, 0x20, 0x3d, 0x83, 0x38, 0x48, 0x24, 0xba, 0x32, 0x70, 0x24, 0x42, 0xab, 0x47, 0x64, 0x0e, - 0x33, 0x78, 0x1e, 0x23, 0x70, 0x80, 0x7d, 0xe4, 0xf9, 0x81, 0x7d, 0x3a, 0x9f, 0x8d, 0x2e, 0x46, 0xe3, 0x7a, 0x3c, - 0x92, 0x22, 0xa6, 0x39, 0xa3, 0x73, 0xbc, 0x73, 0x8b, 0x23, 0x8c, 0x3b, 0xa9, 0xcd, 0x1c, 0xe2, 0xd3, 0x04, 0x4e, - 0x82, 0x18, 0xa8, 0x5a, 0x84, 0xce, 0xd2, 0xda, 0x39, 0xa8, 0x92, 0x05, 0xd9, 0xf9, 0x76, 0xe5, 0x7e, 0xd8, 0xfa, - 0xec, 0x2c, 0x3f, 0x3a, 0xca, 0xcf, 0xe0, 0xbb, 0xce, 0x07, 0x2b, 0xe5, 0xfd, 0x17, 0xb8, 0x25, 0xd5, 0x9d, 0xb4, - 0x4f, 0x11, 0x6b, 0x9f, 0xd2, 0xf5, 0x8a, 0x75, 0x33, 0xea, 0x48, 0xc7, 0x7c, 0xf9, 0x82, 0xaa, 0x78, 0x64, 0xc8, - 0x3a, 0x79, 0x7b, 0x07, 0xaf, 0xc9, 0x4d, 0x92, 0x23, 0x29, 0xb0, 0x5d, 0x65, 0x5c, 0x29, 0x5c, 0x74, 0xd5, 0xfa, - 0x96, 0xc1, 0xce, 0x50, 0x6f, 0x4b, 0xb2, 0x1a, 0x3f, 0x8c, 0xfb, 0x66, 0xe3, 0xdf, 0x97, 0x07, 0x52, 0xe7, 0xc1, - 0x12, 0x11, 0x67, 0x41, 0x0a, 0x3a, 0xa0, 0x5a, 0x0f, 0x46, 0x63, 0x8d, 0x1c, 0xd2, 0xfd, 0xac, 0x0c, 0x45, 0xc8, - 0xe7, 0x31, 0x1a, 0x30, 0xa9, 0x86, 0x00, 0xd5, 0x3a, 0x8c, 0x19, 0xd2, 0x46, 0x5b, 0x0b, 0x88, 0xe1, 0x70, 0xd1, - 0xb3, 0x1b, 0x36, 0xa7, 0xdb, 0xc0, 0x85, 0x12, 0x05, 0xb2, 0x6e, 0xdd, 0x43, 0xcd, 0xf1, 0x44, 0x90, 0x41, 0x55, - 0xb7, 0x9f, 0x16, 0xca, 0x93, 0x78, 0x2c, 0xa0, 0xa0, 0x47, 0x2f, 0xbf, 0x2d, 0x48, 0xd0, 0xee, 0x21, 0xcf, 0xa9, - 0xa2, 0xec, 0x83, 0xe8, 0xb8, 0x65, 0xd8, 0xd0, 0x3e, 0xb6, 0x15, 0xc8, 0x49, 0x3b, 0xd0, 0xd4, 0xce, 0xee, 0x70, - 0x8e, 0x09, 0xf2, 0x9b, 0x32, 0x94, 0x32, 0x51, 0x5f, 0x59, 0x45, 0x4f, 0x0e, 0x73, 0xf6, 0x86, 0x5a, 0x44, 0x4f, - 0x56, 0x5d, 0xce, 0x6f, 0xe1, 0x24, 0x1c, 0x1d, 0x89, 0x3b, 0x10, 0xbd, 0xe1, 0xf5, 0x46, 0xbc, 0xac, 0x47, 0x58, - 0x0e, 0x71, 0x84, 0x8e, 0x17, 0x25, 0xbb, 0x76, 0x57, 0xee, 0x55, 0x5d, 0x6f, 0x2b, 0x57, 0x41, 0x4d, 0x52, 0x29, - 0xb2, 0x8a, 0x81, 0xb9, 0xd7, 0xe3, 0xc4, 0x7d, 0x85, 0x62, 0x5d, 0x08, 0xd9, 0x46, 0xe7, 0x68, 0x74, 0xa4, 0x88, - 0x1d, 0xbd, 0x02, 0xb6, 0xa9, 0x4a, 0x11, 0x82, 0xbb, 0xab, 0xa9, 0x85, 0x65, 0xa2, 0x11, 0xf7, 0x99, 0x07, 0xe8, - 0xca, 0xe2, 0x84, 0x53, 0x81, 0xb6, 0x75, 0x9d, 0x73, 0x56, 0xf4, 0x80, 0x6e, 0xa2, 0xe5, 0x9f, 0xd6, 0x4c, 0x8b, - 0x18, 0x57, 0xd9, 0x94, 0xad, 0xd0, 0xee, 0xd5, 0x2e, 0xd1, 0xe2, 0x1b, 0x91, 0xb0, 0xbd, 0xff, 0xb2, 0xfb, 0x62, - 0x45, 0xfd, 0xa3, 0xbc, 0x3c, 0xc1, 0x53, 0xab, 0xf1, 0x5a, 0x0e, 0x2b, 0xbe, 0x56, 0x0b, 0x61, 0x7d, 0x34, 0xf0, - 0x4a, 0x04, 0x06, 0x49, 0xe8, 0x86, 0x6b, 0xd1, 0x35, 0x83, 0x64, 0x63, 0xd8, 0xfe, 0xe7, 0xf5, 0xfd, 0x9f, 0x5c, - 0xe1, 0xd2, 0x25, 0x8b, 0x32, 0x09, 0x34, 0x4e, 0xb5, 0xa9, 0x0a, 0x2c, 0x78, 0xd1, 0x27, 0x47, 0x78, 0x61, 0x57, - 0x20, 0x37, 0x94, 0x44, 0x3f, 0x93, 0x34, 0x94, 0x47, 0xdf, 0x6b, 0xcd, 0x93, 0xd9, 0x97, 0x90, 0x27, 0x01, 0xc9, - 0x4f, 0xef, 0xdf, 0xce, 0x86, 0x7d, 0x0d, 0x12, 0x51, 0x59, 0xd0, 0xe2, 0x08, 0xce, 0x10, 0xec, 0x0f, 0x73, 0x29, - 0x9b, 0xcf, 0xe4, 0xe8, 0x88, 0xdf, 0x3f, 0xcf, 0xb3, 0xe4, 0xb7, 0xde, 0x7b, 0xc5, 0xd3, 0xac, 0x22, 0xa4, 0x12, - 0x71, 0xa0, 0x5d, 0x15, 0xbd, 0x95, 0xb8, 0x18, 0x3b, 0x24, 0x23, 0xde, 0x4b, 0x1d, 0x62, 0xc2, 0xf8, 0xf2, 0x7b, - 0x24, 0x25, 0x0f, 0x56, 0xed, 0x60, 0xcf, 0x45, 0x35, 0x43, 0xc6, 0x70, 0x3d, 0xef, 0x25, 0x59, 0x01, 0x1c, 0x20, - 0xfa, 0x50, 0x03, 0xd7, 0xa4, 0xee, 0x92, 0x70, 0xb6, 0xf4, 0xac, 0xa3, 0x1a, 0xd8, 0xab, 0x13, 0x2a, 0x79, 0xe3, - 0x20, 0x8b, 0xd8, 0xb6, 0xbf, 0x79, 0x15, 0x02, 0xb5, 0x2a, 0xa4, 0xd7, 0xe0, 0xa5, 0x1f, 0x70, 0x12, 0x81, 0xd1, - 0xc1, 0x42, 0x82, 0xb4, 0x38, 0x53, 0x89, 0x1a, 0x36, 0x78, 0x14, 0xbc, 0x6e, 0x54, 0xa2, 0xb2, 0x21, 0x1f, 0x05, - 0xa9, 0x4e, 0x43, 0x18, 0x7c, 0xd4, 0x24, 0x05, 0x1f, 0x57, 0x2a, 0x09, 0x15, 0x25, 0xa4, 0xdf, 0x08, 0xfe, 0x5d, - 0x5b, 0x3e, 0x96, 0x7f, 0xb7, 0x0e, 0xa5, 0x57, 0x90, 0x71, 0xaa, 0x3f, 0x1c, 0x64, 0xd1, 0x93, 0x6c, 0xd8, 0x98, - 0xc4, 0xf2, 0xb4, 0xbb, 0xa9, 0xd8, 0xa5, 0x0b, 0xfd, 0xca, 0x32, 0xc2, 0xb1, 0x7e, 0x1e, 0xaf, 0xa3, 0xa7, 0xc0, - 0x38, 0x32, 0x5e, 0x3a, 0x3c, 0xd1, 0x0c, 0x05, 0x4d, 0x27, 0xc1, 0x67, 0xff, 0x55, 0x1d, 0x38, 0xc4, 0x14, 0xa1, - 0x20, 0x17, 0x8d, 0xf5, 0xe0, 0x63, 0xde, 0x4e, 0x10, 0x11, 0x37, 0xbb, 0x84, 0x11, 0x69, 0x7a, 0x49, 0xaa, 0xe4, - 0xdf, 0x81, 0xa8, 0x58, 0x65, 0xf0, 0xd1, 0x6d, 0x96, 0x4e, 0x51, 0x25, 0x38, 0x98, 0x83, 0x29, 0xc2, 0x71, 0x29, - 0x1a, 0xfb, 0x89, 0xba, 0x60, 0xc5, 0x78, 0xb0, 0x7a, 0x4d, 0x00, 0xfb, 0x8d, 0xfd, 0x64, 0x8d, 0xd9, 0xaf, 0xda, - 0x8d, 0x2f, 0x53, 0x11, 0x1f, 0xd2, 0xe9, 0x2d, 0xf0, 0x98, 0x5b, 0x2b, 0xd3, 0x33, 0x07, 0x4a, 0x04, 0xbe, 0x93, - 0xae, 0xd7, 0xe9, 0x62, 0x7e, 0x93, 0x84, 0xd9, 0x14, 0x98, 0x33, 0x9c, 0x5e, 0x74, 0xbc, 0x4b, 0x36, 0x97, 0x59, - 0xf2, 0x1a, 0x63, 0x0f, 0xac, 0x4b, 0xc6, 0xe2, 0xc7, 0x65, 0xc6, 0x8b, 0x19, 0xc8, 0x4e, 0x59, 0xa4, 0xa3, 0xf9, - 0xa7, 0x24, 0xfc, 0x75, 0x65, 0x21, 0xa9, 0xa9, 0x29, 0x03, 0x91, 0x42, 0x13, 0x6a, 0xe5, 0xeb, 0x18, 0xec, 0xc4, - 0x02, 0x00, 0xe5, 0xec, 0x62, 0x11, 0x96, 0x51, 0x31, 0x39, 0x69, 0x81, 0x8a, 0x48, 0x7a, 0x45, 0xa9, 0x31, 0x90, - 0x17, 0x20, 0x1a, 0xda, 0x42, 0x06, 0xef, 0xfd, 0x81, 0x78, 0xf0, 0x73, 0x86, 0xf2, 0x0f, 0x59, 0x03, 0xd7, 0xa7, - 0xc0, 0x6c, 0x95, 0xa7, 0xd5, 0xdd, 0x5d, 0xfd, 0x24, 0x86, 0x5f, 0x4f, 0x62, 0xc5, 0x3f, 0xf0, 0xc5, 0xb6, 0x32, - 0x37, 0x80, 0xa3, 0xb0, 0xc4, 0xa8, 0x45, 0x53, 0xfc, 0x13, 0x64, 0xd0, 0x92, 0x30, 0x3f, 0x05, 0xca, 0x71, 0xb8, - 0x9a, 0x17, 0xe3, 0x7c, 0x92, 0x84, 0xf0, 0xbf, 0xe5, 0x84, 0xf8, 0xa3, 0xe5, 0x84, 0xc8, 0x34, 0x70, 0x8d, 0x67, - 0x06, 0x22, 0x0a, 0xd8, 0xf4, 0x2f, 0x90, 0xaf, 0x54, 0xf2, 0x95, 0x98, 0xbf, 0x92, 0xc8, 0x07, 0xda, 0x08, 0x06, - 0xa2, 0xa6, 0x5a, 0xa0, 0xa9, 0x30, 0xdc, 0x25, 0xd9, 0x22, 0xed, 0x90, 0x81, 0x0d, 0x49, 0xe6, 0x50, 0xe1, 0x24, - 0x36, 0x2d, 0xa2, 0x9d, 0x02, 0xe7, 0xbd, 0x0c, 0xd6, 0xc1, 0x15, 0xf1, 0xb3, 0x4b, 0x34, 0x58, 0x3a, 0x8d, 0x72, - 0xe0, 0x30, 0x97, 0xfe, 0x3a, 0xaa, 0xcf, 0xbc, 0x78, 0xec, 0x6d, 0xe6, 0xf9, 0x64, 0x19, 0x2e, 0x7d, 0xff, 0x3f, - 0x80, 0x01, 0x3a, 0x5c, 0x4f, 0xeb, 0xdf, 0x32, 0x0c, 0xef, 0xb7, 0x98, 0x7b, 0x99, 0x8a, 0xf3, 0xb1, 0x86, 0x79, - 0x5e, 0x63, 0xfc, 0x1a, 0x94, 0x48, 0xfc, 0x10, 0x3b, 0x72, 0x05, 0x95, 0x6e, 0x80, 0x2a, 0xc8, 0x0c, 0x53, 0xb4, - 0x6e, 0x7d, 0x9c, 0x24, 0xe8, 0x98, 0x6c, 0xaa, 0x0f, 0x8f, 0xb9, 0xf2, 0xa1, 0x72, 0x7e, 0x70, 0x78, 0x98, 0x98, - 0x41, 0x7a, 0xd5, 0x1d, 0x24, 0x64, 0x44, 0xa6, 0x3c, 0x50, 0x6a, 0x64, 0xca, 0x40, 0x4d, 0x2a, 0x0d, 0x49, 0x6c, - 0x0f, 0x09, 0x8f, 0x43, 0x62, 0x8f, 0x43, 0x2e, 0xe3, 0x40, 0xdc, 0xfd, 0x0a, 0x16, 0xc8, 0x02, 0xfe, 0xdf, 0xf0, - 0xa8, 0x04, 0xd7, 0xc1, 0xa5, 0x50, 0xc7, 0x8b, 0xe8, 0x0d, 0x1e, 0xd8, 0x63, 0x2f, 0x9f, 0xc7, 0x93, 0x37, 0xe1, - 0x1b, 0x68, 0x72, 0x19, 0xdc, 0xb0, 0x50, 0x86, 0x81, 0x10, 0xaf, 0xd1, 0xb9, 0xd4, 0x84, 0x3a, 0xb9, 0x56, 0x3b, - 0x8e, 0x9e, 0xae, 0x9c, 0xa7, 0x4b, 0x8c, 0xe8, 0x43, 0x56, 0x2a, 0x50, 0x66, 0x09, 0xe3, 0x70, 0xe1, 0x1d, 0xfb, - 0x88, 0xc3, 0x23, 0xc3, 0xb9, 0x84, 0xe1, 0x5c, 0xc2, 0x70, 0xa2, 0x85, 0xd7, 0xf1, 0x6c, 0x73, 0x1a, 0xc5, 0x30, - 0x21, 0x1b, 0xa2, 0xea, 0x9c, 0x7b, 0x03, 0xb9, 0x97, 0x34, 0x11, 0x3e, 0x32, 0xf4, 0x59, 0xb1, 0x51, 0x34, 0xfc, - 0x4d, 0x84, 0x85, 0xb7, 0xf0, 0xef, 0x36, 0xb8, 0x8d, 0xde, 0xdc, 0x1d, 0xcf, 0x90, 0x99, 0x5a, 0xcf, 0xbd, 0xed, - 0xe9, 0xd5, 0xfc, 0x2a, 0xda, 0x86, 0xdb, 0x27, 0xd8, 0xd0, 0xeb, 0x68, 0x4b, 0x80, 0x4b, 0x8b, 0x87, 0xab, 0xf1, - 0x1b, 0xff, 0xd1, 0x78, 0xbc, 0xf0, 0x43, 0xef, 0xc6, 0xb3, 0x5a, 0xf9, 0x26, 0x80, 0x1c, 0xeb, 0xe8, 0x96, 0x46, - 0xe3, 0x2a, 0xa2, 0x02, 0x97, 0xd1, 0xb6, 0x85, 0x4c, 0x66, 0x36, 0x92, 0x62, 0x10, 0xc4, 0x88, 0x7c, 0x0d, 0x0c, - 0xcd, 0x32, 0x61, 0x26, 0xf0, 0x49, 0x09, 0x32, 0xa2, 0x0a, 0xcd, 0x50, 0x9d, 0x95, 0xa0, 0x5a, 0x92, 0xee, 0x7e, - 0xe1, 0x11, 0x97, 0x33, 0xfc, 0x6a, 0x14, 0x3d, 0x20, 0xe4, 0xcc, 0x41, 0x7a, 0x70, 0x68, 0xd3, 0x03, 0x2a, 0x22, - 0xab, 0x86, 0x70, 0x32, 0x5f, 0xad, 0xc2, 0x1f, 0x2d, 0xfa, 0xf0, 0xc3, 0x30, 0xe5, 0xa9, 0xf3, 0x3f, 0x4e, 0x79, - 0xca, 0x3c, 0x7c, 0xd3, 0x58, 0x20, 0x78, 0xd6, 0x9a, 0xe4, 0x1b, 0x89, 0x06, 0x0e, 0x98, 0x18, 0x6f, 0x23, 0xe9, - 0xb6, 0x41, 0x9e, 0xc8, 0xc2, 0x0a, 0x23, 0xe4, 0x3c, 0x7e, 0x81, 0x06, 0xa9, 0x18, 0x2a, 0x87, 0x17, 0x25, 0x19, - 0x82, 0xe4, 0x65, 0x9d, 0x72, 0xf8, 0x1c, 0x3f, 0xe0, 0xd3, 0xc7, 0x98, 0x08, 0x2b, 0x7a, 0xec, 0xd9, 0x00, 0xf0, - 0x3f, 0xf7, 0xc8, 0x45, 0x9d, 0x5e, 0xd1, 0xd9, 0xdc, 0x25, 0x18, 0x55, 0x94, 0x14, 0x6e, 0x68, 0x1b, 0xc2, 0x7e, - 0xac, 0x7d, 0xfa, 0x0e, 0x10, 0x35, 0xa8, 0x5e, 0x8e, 0x08, 0x3b, 0x8a, 0x0f, 0xd3, 0xd3, 0x58, 0x91, 0xc8, 0x94, - 0x48, 0x64, 0x3a, 0x46, 0xc2, 0xe9, 0x93, 0xbf, 0xb8, 0x69, 0xb2, 0x69, 0xa1, 0xaf, 0xd0, 0x9f, 0x56, 0x91, 0xe8, - 0xee, 0xb9, 0xc7, 0xf6, 0x45, 0x90, 0x39, 0xa6, 0x7f, 0xb2, 0xfa, 0xf0, 0xfb, 0x8a, 0x66, 0x50, 0x7b, 0xbe, 0x70, - 0x67, 0xe6, 0xd6, 0xe0, 0x86, 0x56, 0x97, 0xc5, 0x75, 0x79, 0x99, 0x1e, 0xa4, 0xb7, 0x30, 0x7b, 0x8b, 0xfa, 0xe0, - 0x9f, 0x4d, 0x17, 0xcf, 0xa9, 0xde, 0xac, 0x4d, 0x9c, 0x15, 0x36, 0x4e, 0xb5, 0xb4, 0x2e, 0xca, 0x1a, 0xd6, 0xf1, - 0x7b, 0xa4, 0xbb, 0x92, 0x8e, 0xa3, 0x27, 0x2c, 0x47, 0x37, 0x65, 0x09, 0xec, 0xe1, 0x77, 0xbd, 0x54, 0x9a, 0x62, - 0x37, 0x85, 0xa8, 0x52, 0xc7, 0x05, 0x54, 0xe6, 0xa8, 0xe3, 0x6e, 0xa9, 0x76, 0x80, 0x71, 0xdb, 0xe4, 0xc2, 0x6c, - 0x76, 0x61, 0x25, 0x3b, 0xf2, 0x93, 0xaa, 0x43, 0x83, 0x51, 0x88, 0x59, 0x35, 0x0b, 0x87, 0xca, 0x4e, 0x58, 0x4c, - 0x58, 0x49, 0x00, 0x19, 0x02, 0xc6, 0xb1, 0xa2, 0x64, 0x52, 0xdc, 0x1e, 0xd9, 0x0a, 0xc5, 0xd7, 0x6c, 0x05, 0x58, - 0x08, 0x87, 0x85, 0xb5, 0xeb, 0x06, 0xda, 0x6e, 0xa9, 0x53, 0xa6, 0xf5, 0x3a, 0x2e, 0xfe, 0x16, 0xaf, 0x15, 0x64, - 0x32, 0x1f, 0x8f, 0xce, 0x98, 0xce, 0xfe, 0x96, 0x78, 0x76, 0x25, 0x01, 0xfa, 0xac, 0xd7, 0x5a, 0x9f, 0xdc, 0x1d, - 0x96, 0xe3, 0x96, 0xbc, 0x12, 0xd7, 0xd2, 0x37, 0xa5, 0x85, 0x94, 0x91, 0x6f, 0x5c, 0x05, 0xbd, 0x1a, 0x7b, 0x37, - 0x15, 0xe7, 0x6d, 0xcf, 0x98, 0x33, 0x82, 0x15, 0xd7, 0xdd, 0x95, 0xa9, 0x29, 0x95, 0x32, 0xa8, 0x6a, 0xbb, 0x59, - 0x54, 0xba, 0xd6, 0x7f, 0xea, 0xb9, 0x5f, 0xe4, 0x03, 0xee, 0x8a, 0xf2, 0x16, 0xb9, 0xd0, 0xac, 0xaa, 0x9b, 0xae, - 0x6e, 0x58, 0x37, 0x5e, 0xe9, 0x42, 0xa9, 0x01, 0x9a, 0x3d, 0xb7, 0x2d, 0x3c, 0x50, 0xdd, 0x44, 0x7b, 0xf6, 0xbc, - 0x45, 0x89, 0xe1, 0xeb, 0x6a, 0xb2, 0x5d, 0x69, 0x94, 0xd0, 0xc7, 0xb5, 0xc1, 0x86, 0x3f, 0x9f, 0xc2, 0x16, 0x3b, - 0x6f, 0x33, 0xbd, 0x16, 0xbe, 0xe0, 0x65, 0x78, 0x96, 0x9e, 0xab, 0xbb, 0x29, 0xa9, 0x1d, 0x68, 0x90, 0x74, 0x7a, - 0xb7, 0x16, 0xac, 0x94, 0x30, 0xd5, 0x66, 0x99, 0x48, 0x59, 0xea, 0x96, 0x95, 0x37, 0x55, 0xc7, 0x56, 0x52, 0xe9, - 0x7b, 0xce, 0xd0, 0x7d, 0xec, 0x07, 0xc2, 0x44, 0x56, 0x81, 0x49, 0xc9, 0xd0, 0x81, 0xec, 0xaa, 0x2b, 0xdb, 0x8c, - 0x7a, 0x3c, 0xce, 0x35, 0x49, 0xa4, 0x0f, 0x2c, 0xe8, 0x03, 0xc0, 0xef, 0x54, 0x67, 0x39, 0x1c, 0x9c, 0x51, 0x79, - 0xb6, 0x38, 0x87, 0xb3, 0xad, 0x3c, 0xdb, 0x90, 0x24, 0xb4, 0xc4, 0x13, 0xd2, 0xdf, 0xc5, 0x7c, 0x01, 0xbb, 0x24, - 0xe1, 0x8d, 0xce, 0x54, 0xa1, 0x65, 0x57, 0xcc, 0x01, 0xc6, 0x97, 0xb5, 0xe7, 0xd5, 0x93, 0x25, 0x5a, 0x4b, 0x3c, - 0xf2, 0xd6, 0xf0, 0x87, 0x7f, 0x63, 0xd4, 0xf9, 0xc4, 0x63, 0x76, 0x41, 0xef, 0x05, 0x7f, 0x76, 0x0d, 0xef, 0x78, - 0x24, 0xa4, 0xe2, 0x6b, 0x6d, 0x6c, 0x12, 0x5b, 0x8a, 0x96, 0x79, 0x0c, 0xd3, 0x05, 0x3c, 0x0a, 0x2e, 0xc3, 0x0f, - 0x3c, 0x33, 0x1d, 0xfd, 0x4f, 0xc2, 0x1b, 0xda, 0x17, 0x09, 0x96, 0xc9, 0x1f, 0x1d, 0x1f, 0x43, 0x0a, 0x19, 0x3d, - 0xbb, 0x65, 0xa4, 0x0a, 0xda, 0x3e, 0x32, 0xb4, 0xe7, 0x66, 0x69, 0x94, 0x72, 0x90, 0x28, 0x05, 0x77, 0xcf, 0xb3, - 0xa4, 0xac, 0x45, 0xd2, 0xfe, 0x51, 0x51, 0x1d, 0x45, 0xa5, 0x6a, 0xc0, 0xf0, 0x91, 0xa0, 0x0e, 0xf4, 0xc3, 0x4a, - 0xc2, 0x65, 0x75, 0xcd, 0x04, 0xec, 0x45, 0x42, 0xfc, 0x96, 0x67, 0x7d, 0x9a, 0x82, 0x2a, 0xea, 0x45, 0x5c, 0xda, - 0xf2, 0x88, 0x1d, 0x65, 0xf3, 0x27, 0x25, 0xc7, 0xb3, 0x86, 0xc1, 0x0e, 0xa9, 0xe9, 0x92, 0x79, 0x2d, 0x62, 0xef, - 0xa1, 0xa3, 0x16, 0xb5, 0x26, 0x79, 0x75, 0x99, 0x06, 0x18, 0xa3, 0x24, 0x20, 0x27, 0xc1, 0x11, 0x4a, 0x97, 0x98, - 0x62, 0x24, 0xd8, 0x9d, 0x2b, 0xe6, 0x85, 0xa3, 0xcb, 0x4d, 0x03, 0x42, 0xa7, 0x15, 0xd0, 0x10, 0xd6, 0x67, 0x2f, - 0x84, 0xe1, 0x71, 0xd0, 0x11, 0xc3, 0x30, 0xcc, 0x18, 0x45, 0x42, 0xb0, 0xfa, 0x17, 0xfe, 0x29, 0x48, 0xe2, 0xf5, - 0xb3, 0xf4, 0x73, 0x96, 0x56, 0x4c, 0xa4, 0x51, 0x85, 0x34, 0x4c, 0x7c, 0x43, 0xd5, 0xa4, 0x51, 0x80, 0x01, 0x46, - 0x11, 0x95, 0x58, 0xd1, 0x54, 0xfa, 0xcd, 0x8b, 0x0f, 0x7f, 0x0a, 0x1d, 0x0f, 0x8f, 0xdb, 0x4e, 0x67, 0x38, 0xe8, - 0x0c, 0xf6, 0xa8, 0x13, 0xf5, 0x74, 0xd4, 0x49, 0x50, 0x8d, 0x54, 0x6f, 0xcd, 0xc3, 0xc8, 0xaa, 0x53, 0xe3, 0x9d, - 0x43, 0x8d, 0x17, 0x36, 0x78, 0xf2, 0x71, 0x70, 0x61, 0xd0, 0x93, 0x9b, 0xe8, 0x49, 0x73, 0x48, 0xb7, 0xf7, 0x6a, - 0x84, 0x80, 0x5f, 0xa3, 0x14, 0xec, 0x06, 0xd4, 0x67, 0x78, 0x82, 0xa6, 0xec, 0x73, 0xf8, 0x86, 0xb3, 0xdc, 0x21, - 0x96, 0x0a, 0x70, 0x35, 0x99, 0xc4, 0x50, 0x5a, 0xd7, 0x1e, 0x6e, 0x31, 0x83, 0x43, 0xa5, 0xb7, 0x6a, 0x33, 0x29, - 0xfd, 0xd3, 0x7a, 0x8a, 0x0e, 0xa1, 0x9b, 0x7a, 0x5c, 0x4f, 0x57, 0x59, 0xf3, 0x9e, 0x7e, 0x0b, 0xeb, 0x90, 0x64, - 0xfb, 0x58, 0x87, 0x54, 0xb3, 0x0e, 0xb3, 0xdf, 0x14, 0x52, 0x00, 0x99, 0x6c, 0x8c, 0x4c, 0x02, 0xf2, 0xde, 0xf6, - 0x23, 0x41, 0xad, 0xcc, 0xf6, 0x32, 0x16, 0x5c, 0xde, 0x49, 0xc2, 0x1a, 0xdc, 0x84, 0xc6, 0xb0, 0x14, 0xe9, 0xe0, - 0x91, 0x9e, 0xfa, 0x40, 0x82, 0xdf, 0xa3, 0x3a, 0xcd, 0xbb, 0x67, 0x6f, 0x61, 0x70, 0xce, 0x2a, 0xd8, 0x92, 0x34, - 0x2b, 0x5a, 0x1b, 0x19, 0x28, 0x84, 0xdf, 0x1d, 0x6d, 0x09, 0xe4, 0xcb, 0x19, 0xae, 0x75, 0xf9, 0xc9, 0x4b, 0x27, - 0x55, 0xf0, 0xd8, 0x1f, 0xeb, 0xe7, 0x62, 0x12, 0xc3, 0xf3, 0xa9, 0x7e, 0x2e, 0xcd, 0x00, 0x8e, 0x4b, 0x19, 0x55, - 0xc8, 0x00, 0x0d, 0xfa, 0x49, 0xb7, 0xc8, 0x1c, 0x80, 0xa5, 0xba, 0x88, 0xc1, 0x4f, 0xa2, 0x8a, 0xba, 0xf8, 0xf9, - 0xde, 0x5c, 0x5b, 0xca, 0x85, 0xca, 0x1c, 0x0a, 0x38, 0x48, 0xdb, 0xc0, 0x53, 0x07, 0x0c, 0xf4, 0xa7, 0x80, 0xfe, - 0xd4, 0xfb, 0xfb, 0x93, 0x6a, 0x0d, 0xbe, 0xca, 0xda, 0xd2, 0x9d, 0x57, 0x8a, 0x81, 0x20, 0x52, 0x57, 0xa9, 0xaa, - 0x45, 0x3d, 0xb4, 0xf1, 0xe6, 0x7e, 0x00, 0x2d, 0x9c, 0x15, 0x46, 0xec, 0x2f, 0x02, 0x3c, 0xf9, 0x58, 0xff, 0xf5, - 0x5e, 0x65, 0x30, 0x60, 0x64, 0xf4, 0xd2, 0xda, 0xbf, 0x58, 0x5a, 0xb4, 0x7b, 0xc5, 0xb8, 0xf6, 0x1f, 0x3e, 0x66, - 0xfa, 0xb7, 0x57, 0x57, 0x3e, 0xd3, 0xd3, 0x7f, 0x77, 0xa7, 0xd6, 0xe7, 0xe9, 0xf4, 0xe4, 0xee, 0xee, 0x30, 0x6e, - 0xc4, 0x63, 0x4d, 0x16, 0x04, 0x39, 0xd7, 0xfb, 0x8f, 0x1e, 0x63, 0x54, 0x04, 0x37, 0xee, 0x66, 0xed, 0x68, 0x64, - 0xec, 0x38, 0x9d, 0xb5, 0xa3, 0xd8, 0x49, 0xad, 0xa8, 0xc4, 0xf5, 0xb4, 0xb3, 0xc1, 0x83, 0x6d, 0xe2, 0x61, 0x28, - 0x07, 0xfa, 0xd8, 0x2d, 0xff, 0xd9, 0xb2, 0x99, 0x10, 0x4f, 0xd6, 0xb0, 0x53, 0xba, 0x85, 0x69, 0x7e, 0xa0, 0x46, - 0x70, 0x9c, 0x5a, 0xfb, 0x0b, 0xc8, 0x69, 0x92, 0x09, 0x39, 0x25, 0xf2, 0x4b, 0xf4, 0x14, 0x93, 0x7a, 0xf4, 0x94, - 0x09, 0xe0, 0x49, 0xa0, 0x0b, 0xe3, 0x6f, 0x1c, 0xf7, 0x67, 0xee, 0x6b, 0x33, 0x15, 0xe1, 0x9f, 0x03, 0xaa, 0x53, - 0xc8, 0x69, 0x92, 0x55, 0x09, 0x46, 0x6d, 0xe4, 0x66, 0x00, 0x29, 0xd5, 0x31, 0x1f, 0x99, 0xf0, 0x59, 0x5f, 0xfd, - 0x9f, 0x21, 0x7c, 0xea, 0xc2, 0x0d, 0xe1, 0xf2, 0xaa, 0xab, 0x4b, 0xef, 0x2f, 0x7f, 0x0e, 0x0e, 0x4e, 0xfe, 0xfa, - 0x38, 0x38, 0x78, 0xfc, 0xa7, 0xbf, 0xf8, 0x08, 0x8b, 0x06, 0x69, 0x8f, 0xff, 0xf2, 0x97, 0xe0, 0xe0, 0x3f, 0xff, - 0x13, 0x5e, 0xfc, 0xe9, 0xb1, 0x93, 0x76, 0xf2, 0x17, 0x48, 0xfc, 0xeb, 0x9f, 0x9d, 0xb4, 0xc7, 0xc7, 0xf0, 0xcf, - 0xff, 0xfd, 0xab, 0x4a, 0xfb, 0x3f, 0x98, 0xed, 0x3f, 0x1f, 0xd3, 0x3f, 0x2a, 0xed, 0xe4, 0x2f, 0x7f, 0x82, 0xe7, - 0x63, 0xfc, 0xc8, 0x5f, 0xcc, 0x47, 0x8e, 0x4f, 0xb0, 0xf0, 0x9f, 0xf0, 0x9f, 0xff, 0xe3, 0xe3, 0x26, 0x28, 0xa3, - 0xbc, 0xa0, 0xfb, 0x33, 0x52, 0x71, 0xd2, 0xd5, 0x44, 0x92, 0x7a, 0x94, 0x99, 0xcb, 0xc4, 0xde, 0xc8, 0x37, 0xe9, - 0x58, 0x51, 0x70, 0x70, 0x3c, 0x85, 0x1a, 0x6d, 0x78, 0xba, 0xdf, 0x6c, 0x90, 0xb1, 0xbc, 0x38, 0xcb, 0xfe, 0x23, - 0x57, 0xb1, 0x15, 0x2c, 0x00, 0xab, 0xff, 0xd7, 0xdc, 0x97, 0x26, 0xb6, 0x6d, 0xa4, 0x89, 0xfe, 0x9f, 0x53, 0x50, - 0x88, 0xe3, 0x00, 0x26, 0x48, 0x91, 0x5a, 0x6c, 0x07, 0x14, 0xc4, 0x71, 0xbc, 0x24, 0x4e, 0x7b, 0x8b, 0xe5, 0x24, - 0xdd, 0x51, 0x6b, 0x24, 0x88, 0x00, 0x45, 0xc4, 0x14, 0xc0, 0x06, 0x40, 0x2d, 0xa1, 0x30, 0x67, 0x79, 0x47, 0x78, - 0x67, 0x98, 0x93, 0xbd, 0x6f, 0xa9, 0x0d, 0x0b, 0x25, 0xa5, 0x93, 0xee, 0x79, 0xd3, 0x13, 0x0b, 0x2c, 0x14, 0x6a, - 0xaf, 0x6f, 0x5f, 0x0e, 0xcc, 0x5a, 0x51, 0x0a, 0xb5, 0xa2, 0xb4, 0x59, 0xeb, 0x2f, 0xb5, 0x80, 0xf2, 0xe6, 0xa9, - 0xf5, 0x3f, 0x67, 0x9c, 0x3a, 0xad, 0xb6, 0xfa, 0xfe, 0x01, 0x95, 0x77, 0xbb, 0x06, 0x87, 0xfd, 0x6d, 0xa3, 0x9d, - 0xda, 0x37, 0x22, 0x0a, 0x35, 0x29, 0x0f, 0x1d, 0x7f, 0x1f, 0x9b, 0xee, 0x76, 0x91, 0x26, 0x30, 0xe2, 0xbe, 0xfd, - 0xce, 0x36, 0x0e, 0x5a, 0xda, 0xf8, 0x85, 0x64, 0x08, 0x64, 0xd4, 0xe3, 0xab, 0x4b, 0x8f, 0x17, 0x5d, 0xe9, 0x25, - 0x73, 0xc6, 0x4c, 0xa6, 0x52, 0x32, 0xa9, 0x68, 0x5d, 0xf3, 0x8e, 0x14, 0x45, 0x03, 0x5d, 0x15, 0x46, 0xe3, 0xc2, - 0x87, 0xc9, 0xa1, 0x7a, 0xcb, 0xab, 0xbc, 0x49, 0x63, 0x78, 0xf3, 0x83, 0x7c, 0x83, 0xd4, 0x8c, 0xff, 0x17, 0xfe, - 0x65, 0x26, 0xce, 0x88, 0x53, 0x35, 0x1e, 0x36, 0x31, 0xc2, 0x58, 0x01, 0x31, 0x3a, 0xf0, 0x60, 0xd0, 0x41, 0x73, - 0xb5, 0x6f, 0x6e, 0xb8, 0xa4, 0x3a, 0x67, 0x15, 0x06, 0x50, 0x12, 0x6f, 0x43, 0x23, 0xaa, 0x59, 0x45, 0x5e, 0x42, - 0xc2, 0xad, 0x6a, 0x7b, 0x8d, 0xc6, 0x28, 0x84, 0x60, 0x11, 0xfa, 0x18, 0x70, 0xc0, 0xa2, 0x64, 0xac, 0x70, 0xdb, - 0xe4, 0x95, 0xf7, 0x56, 0x11, 0xab, 0x27, 0x91, 0x32, 0x80, 0xb1, 0x4e, 0xa2, 0xf7, 0x42, 0xec, 0x4f, 0xd6, 0x8f, - 0xa6, 0x6f, 0x8f, 0x11, 0xd6, 0x7e, 0x23, 0xea, 0x8b, 0xcf, 0x2a, 0xec, 0x00, 0x29, 0x6a, 0x0d, 0xdf, 0xf8, 0xa4, - 0x54, 0x12, 0x8f, 0x1c, 0x69, 0x83, 0x89, 0xc8, 0x48, 0x21, 0x23, 0xd5, 0x22, 0xc5, 0xc0, 0xde, 0x58, 0x14, 0x4b, - 0x55, 0xf7, 0x8d, 0xd3, 0x4a, 0x6d, 0xf4, 0x70, 0xfb, 0x7e, 0xc6, 0x89, 0xa3, 0x1e, 0x3e, 0x84, 0x02, 0xc3, 0xed, - 0x49, 0xda, 0x91, 0xd3, 0xd6, 0x8f, 0x12, 0x1d, 0xfe, 0x1b, 0xf6, 0x41, 0xda, 0xdd, 0x87, 0xbe, 0x22, 0x59, 0xfc, - 0x7d, 0x5b, 0xc8, 0x3d, 0x0a, 0x23, 0x24, 0x9f, 0x1d, 0x61, 0x26, 0x0b, 0xca, 0x42, 0xe1, 0xf4, 0x86, 0xc0, 0x25, - 0x2c, 0x93, 0x7c, 0x16, 0x4f, 0x0b, 0x7b, 0xc5, 0x0a, 0xe5, 0xc8, 0x25, 0xdf, 0x6e, 0x74, 0x20, 0x71, 0xbc, 0x38, - 0x7f, 0x17, 0xbc, 0xb3, 0x29, 0x58, 0x5d, 0x24, 0x6c, 0xa1, 0x22, 0xe3, 0x7e, 0xc6, 0x61, 0x1b, 0x7d, 0x24, 0x5d, - 0x40, 0x75, 0x2e, 0xa6, 0xde, 0x50, 0xe9, 0x77, 0xf4, 0x17, 0x4a, 0xd3, 0x83, 0xa1, 0xbe, 0x73, 0x16, 0x23, 0xf0, - 0x57, 0xd2, 0x3e, 0x16, 0x68, 0xb2, 0x74, 0x8c, 0xb9, 0x86, 0x05, 0x6f, 0xc7, 0x73, 0x83, 0x79, 0x61, 0xe0, 0x46, - 0x1c, 0x8d, 0xc8, 0x4c, 0x52, 0xd8, 0x84, 0x2f, 0x39, 0x7d, 0x6b, 0xec, 0xb8, 0x03, 0xf4, 0xa6, 0x52, 0x83, 0x4c, - 0x52, 0x53, 0x30, 0x28, 0xd1, 0xb6, 0xc8, 0xc2, 0xaa, 0x3a, 0x8b, 0xf7, 0x31, 0xdc, 0x40, 0xbc, 0x27, 0x19, 0xcf, - 0x71, 0x71, 0x18, 0x1f, 0x79, 0x32, 0x29, 0xe0, 0x2c, 0x51, 0x04, 0xda, 0xbb, 0x35, 0xb2, 0x1d, 0x1d, 0xa1, 0x1b, - 0xf9, 0x11, 0xca, 0xa7, 0x5d, 0x15, 0xac, 0x50, 0x34, 0x42, 0x42, 0x66, 0xbe, 0x8a, 0xef, 0x15, 0x86, 0x51, 0xc8, - 0x23, 0xc1, 0xc4, 0x51, 0x14, 0xea, 0xa2, 0x69, 0x94, 0xa0, 0x2b, 0x55, 0x92, 0x19, 0x34, 0xec, 0x48, 0xd5, 0x94, - 0xb4, 0xd3, 0x21, 0x6f, 0x69, 0x2e, 0xb6, 0x54, 0xf8, 0x1a, 0x26, 0x87, 0x39, 0x79, 0xe8, 0xa1, 0xeb, 0x81, 0x70, - 0xc8, 0xcb, 0xdd, 0xa1, 0xcc, 0xa0, 0x53, 0x1b, 0x13, 0x4d, 0xae, 0x2f, 0x46, 0x56, 0x12, 0xed, 0x68, 0xcb, 0x1b, - 0xf1, 0xd2, 0x4c, 0xd4, 0x85, 0x21, 0x42, 0xd6, 0x8e, 0x48, 0xa5, 0x92, 0x8a, 0xf3, 0x57, 0xd8, 0x56, 0x44, 0xb1, - 0x75, 0x13, 0x64, 0x4b, 0xd1, 0xe4, 0x32, 0xf2, 0xe0, 0x24, 0xa1, 0x74, 0xe5, 0x19, 0x6b, 0xd7, 0x1b, 0x23, 0x71, - 0x5c, 0xd8, 0x59, 0x54, 0x08, 0xab, 0x2c, 0xce, 0xa5, 0x4a, 0x64, 0x81, 0xf0, 0xed, 0x4d, 0x7c, 0x6e, 0xa4, 0x83, - 0x5d, 0x41, 0xf1, 0x8b, 0x68, 0x0a, 0xef, 0x42, 0x0a, 0x76, 0x75, 0x25, 0x7f, 0x44, 0x9a, 0x6c, 0x43, 0xcb, 0xb7, - 0x6f, 0xf0, 0xc0, 0xe4, 0xb6, 0x50, 0x4a, 0xc4, 0x09, 0xd0, 0x6b, 0x50, 0xd9, 0x24, 0xee, 0xde, 0xc6, 0xc9, 0x5b, - 0xa0, 0xc2, 0x36, 0x06, 0x55, 0x7a, 0x1a, 0xa0, 0x0f, 0x7e, 0x49, 0x91, 0x44, 0x31, 0x87, 0x2d, 0x65, 0xc4, 0xa2, - 0xc8, 0xb1, 0x03, 0xb8, 0x20, 0x2c, 0x68, 0xad, 0x2d, 0x81, 0x91, 0x7f, 0x9a, 0xa7, 0x07, 0xfd, 0x49, 0xfb, 0x0c, - 0xe8, 0xd4, 0xcf, 0x39, 0x98, 0x05, 0xe5, 0xb9, 0xaf, 0x4b, 0x49, 0xa0, 0xaa, 0x14, 0x90, 0x40, 0x55, 0xb7, 0x2a, - 0xe3, 0x10, 0x56, 0x74, 0x46, 0x9e, 0xdf, 0xe6, 0xf2, 0xa7, 0x94, 0x6a, 0x05, 0xce, 0x37, 0x4a, 0xcc, 0x52, 0x35, - 0x94, 0x71, 0xea, 0xa5, 0x22, 0x5a, 0x08, 0x6c, 0x69, 0x77, 0xe8, 0x34, 0x4f, 0xaa, 0x22, 0x44, 0xd5, 0x57, 0x76, - 0x32, 0x1e, 0x78, 0x50, 0x75, 0xd8, 0x72, 0xde, 0xe5, 0x68, 0xb1, 0x52, 0x7f, 0xd7, 0x33, 0x7c, 0x3a, 0x81, 0xe5, - 0x1f, 0x65, 0x7b, 0x7e, 0x34, 0xca, 0x00, 0x8f, 0x09, 0x97, 0xc2, 0x15, 0xf5, 0x83, 0xa6, 0x34, 0x3a, 0xdf, 0x9a, - 0x1c, 0xf5, 0xab, 0x94, 0x53, 0xd2, 0x1b, 0x06, 0x24, 0x49, 0xaa, 0x93, 0xdd, 0xa2, 0x44, 0xd1, 0xf0, 0xbf, 0xe3, - 0x2b, 0xd8, 0xf4, 0x60, 0xac, 0x66, 0xf7, 0x35, 0x8c, 0xff, 0x48, 0xdb, 0x42, 0x51, 0x9f, 0x72, 0x7f, 0xa3, 0xa5, - 0x90, 0x53, 0x2e, 0xe2, 0x63, 0xcb, 0x40, 0x24, 0x50, 0xdd, 0xf0, 0xad, 0x64, 0x79, 0x7e, 0x0a, 0x2c, 0x34, 0xe1, - 0x44, 0xcd, 0x5c, 0xe1, 0xb5, 0x70, 0x0b, 0x09, 0xa3, 0x00, 0x82, 0x7a, 0x8a, 0x59, 0x10, 0x4d, 0xbe, 0x20, 0x21, - 0xeb, 0xdc, 0x06, 0xce, 0xb0, 0xbe, 0x88, 0xce, 0x66, 0x7d, 0x13, 0x2a, 0x83, 0xc1, 0x03, 0xd2, 0x80, 0x11, 0x74, - 0x08, 0x95, 0xfc, 0x6d, 0x0f, 0x5d, 0xb8, 0x54, 0x44, 0x96, 0x9e, 0xc8, 0xdf, 0x54, 0x1f, 0x02, 0xcf, 0x8a, 0x9c, - 0xa6, 0xa8, 0x2b, 0x36, 0xc9, 0xc7, 0x27, 0x78, 0x49, 0x95, 0x8c, 0x29, 0x1b, 0xf0, 0xb5, 0x3e, 0xde, 0xae, 0x6c, - 0x58, 0xcc, 0xc9, 0xf8, 0xfa, 0x51, 0xeb, 0x4c, 0xd0, 0x28, 0x96, 0x6b, 0x54, 0x85, 0x94, 0xc2, 0x07, 0x05, 0x28, - 0xf6, 0x59, 0x22, 0x28, 0x76, 0x15, 0x30, 0x09, 0xc9, 0x67, 0x2c, 0x35, 0x88, 0x76, 0x9a, 0xb3, 0xb7, 0xc2, 0x23, - 0x81, 0xc8, 0xdf, 0x4b, 0xd2, 0xd2, 0x64, 0xdd, 0xf3, 0xb0, 0x9a, 0xb2, 0xe5, 0xf0, 0x08, 0xe9, 0x7c, 0xbc, 0xb5, - 0x00, 0x0e, 0x51, 0x36, 0xe1, 0xa5, 0x2e, 0x5e, 0x79, 0x4a, 0xd2, 0xee, 0x05, 0xee, 0x22, 0x83, 0xe1, 0x93, 0x94, - 0x62, 0x22, 0x7c, 0x82, 0xe7, 0xf8, 0x86, 0xee, 0x23, 0x27, 0x84, 0xe7, 0x94, 0xd3, 0x5e, 0xe8, 0x0a, 0x0b, 0x18, - 0x86, 0x1e, 0x28, 0xca, 0x8b, 0x51, 0x8e, 0x77, 0x73, 0x33, 0x74, 0x17, 0x3e, 0x2c, 0xb7, 0x4b, 0xa0, 0xe4, 0x8c, - 0xda, 0x3d, 0x47, 0x9d, 0xc7, 0xa9, 0xbf, 0xf1, 0x12, 0x63, 0x11, 0x1c, 0xe3, 0xdf, 0xc0, 0x71, 0x2f, 0xf0, 0x2f, - 0x60, 0xd2, 0xb7, 0xbe, 0x7d, 0xde, 0x3b, 0x73, 0x36, 0xed, 0x10, 0xae, 0x1e, 0x5d, 0xdd, 0x6b, 0x1f, 0xc0, 0x11, - 0x17, 0x2e, 0x36, 0xa7, 0xce, 0xa3, 0xa9, 0x7b, 0xe5, 0x5e, 0xba, 0x07, 0xee, 0x7b, 0x04, 0xfc, 0xd7, 0x7b, 0xc3, - 0xa8, 0x37, 0xdc, 0x79, 0xf8, 0x70, 0xe3, 0x14, 0xfe, 0x3b, 0x96, 0x06, 0x14, 0xe2, 0x16, 0x9d, 0x95, 0xae, 0x78, - 0x3a, 0x2f, 0x8f, 0x46, 0xef, 0xf9, 0xe2, 0x4e, 0xa2, 0x78, 0x6e, 0x9f, 0x6f, 0x5e, 0x3b, 0x3d, 0xfa, 0x39, 0x9d, - 0xa7, 0x70, 0x1d, 0xcf, 0xe0, 0xb7, 0xfb, 0x7e, 0x1f, 0xf5, 0xa6, 0xd4, 0xdf, 0xfb, 0x47, 0xd7, 0xa2, 0x37, 0xc7, - 0x7d, 0x69, 0x4f, 0xf0, 0x9a, 0x5c, 0xf9, 0x8a, 0xd7, 0x1e, 0x0e, 0x30, 0x97, 0xc9, 0xb5, 0xd1, 0xde, 0xf5, 0xa3, - 0x2b, 0x67, 0xf3, 0x0a, 0x3d, 0x45, 0x15, 0xf8, 0x1b, 0xdb, 0x97, 0x7e, 0xad, 0x87, 0x47, 0xd7, 0xee, 0x41, 0x6d, - 0x10, 0x8f, 0xae, 0x1d, 0x0f, 0x2a, 0x9e, 0xc1, 0x8b, 0x73, 0xc7, 0x85, 0x49, 0x1c, 0x3f, 0x7c, 0x08, 0x48, 0xe8, - 0xdb, 0xc0, 0xb6, 0x83, 0x5e, 0xe6, 0x6c, 0xa6, 0xee, 0xf5, 0xe6, 0x30, 0xda, 0x76, 0xc6, 0xb6, 0x18, 0x3e, 0x1f, - 0x38, 0xa5, 0xf2, 0xe6, 0x5a, 0xd7, 0x2e, 0x5a, 0x2b, 0x5c, 0xfb, 0xfc, 0xeb, 0xbd, 0x7b, 0xe9, 0x67, 0xd0, 0x60, - 0xe0, 0x78, 0x17, 0x38, 0x8a, 0xd3, 0x71, 0xe6, 0xc1, 0x8a, 0xf9, 0xc7, 0xe3, 0xc0, 0x83, 0x75, 0xf3, 0xe7, 0xb0, - 0x1f, 0x50, 0xf7, 0xa0, 0x77, 0x09, 0x75, 0xa1, 0xfb, 0xf7, 0xe2, 0xf9, 0xda, 0x05, 0x9e, 0xf2, 0xbd, 0x6b, 0x74, - 0xf3, 0xde, 0x91, 0xdd, 0x57, 0x7a, 0x87, 0x8f, 0xcc, 0xc5, 0x7c, 0xaf, 0xec, 0x69, 0x1e, 0x68, 0xd8, 0xb8, 0xcc, - 0x6d, 0x58, 0x52, 0xf8, 0xf7, 0x12, 0xde, 0x56, 0xd7, 0x0e, 0x17, 0x74, 0xfc, 0xc0, 0x83, 0x25, 0xbc, 0x34, 0x5b, - 0xbd, 0xa4, 0x35, 0x94, 0x2b, 0xc4, 0x65, 0x07, 0x54, 0x46, 0xe7, 0xe0, 0x85, 0x08, 0xd6, 0x01, 0x6b, 0x64, 0x2f, - 0x1f, 0x3e, 0xc4, 0x4c, 0xf7, 0xd9, 0x58, 0xe6, 0x76, 0xd3, 0x60, 0xd3, 0xbd, 0x44, 0xed, 0xff, 0x8b, 0x6e, 0x17, - 0x27, 0x63, 0xb4, 0x64, 0x5f, 0x76, 0x5f, 0xc0, 0x62, 0x73, 0x1f, 0x99, 0x9b, 0xa7, 0x76, 0xe6, 0xbe, 0x75, 0x63, - 0x0c, 0xf8, 0x05, 0x95, 0x1d, 0x4f, 0x7e, 0xe6, 0x8c, 0x5e, 0xec, 0xbd, 0x1f, 0x75, 0xbb, 0x2f, 0xe4, 0x35, 0xf9, - 0xcd, 0x5f, 0xd3, 0x0a, 0x9e, 0x3f, 0xd8, 0xad, 0xdf, 0xf6, 0x03, 0xe7, 0x34, 0x8b, 0x82, 0xcf, 0xa3, 0xea, 0x58, - 0x7e, 0xd3, 0x59, 0xd5, 0xa0, 0x16, 0x8c, 0xf8, 0x00, 0x63, 0x17, 0x8d, 0xb5, 0xaf, 0x27, 0x4a, 0x5b, 0x0e, 0x35, - 0x44, 0x12, 0x20, 0xc7, 0x0d, 0x70, 0x6c, 0x01, 0x8f, 0x6d, 0xdc, 0x52, 0xc1, 0x0f, 0xbc, 0x6a, 0x47, 0x41, 0x09, - 0x7b, 0xb8, 0x71, 0x7c, 0x73, 0x73, 0x00, 0x87, 0x2f, 0x70, 0x50, 0xfa, 0x61, 0xbe, 0x3e, 0x28, 0x2b, 0x39, 0xc4, - 0x72, 0x16, 0xdf, 0xad, 0x66, 0x0a, 0x09, 0x00, 0x75, 0x0b, 0x27, 0xe9, 0xa3, 0xe4, 0xcb, 0x93, 0x52, 0xd3, 0xad, - 0xbf, 0x60, 0x10, 0xa2, 0xd4, 0xb7, 0xa3, 0x31, 0xad, 0x41, 0x1e, 0x63, 0x20, 0x73, 0x8f, 0x77, 0x3e, 0xc5, 0x20, - 0xc0, 0x70, 0x31, 0xfa, 0x03, 0x60, 0x74, 0x33, 0xbf, 0xff, 0x64, 0xf7, 0x51, 0xf1, 0xc8, 0xb6, 0xac, 0x6e, 0xec, - 0xd4, 0xf4, 0x14, 0xea, 0xb0, 0x16, 0x9b, 0x68, 0x04, 0x2f, 0xc8, 0xc7, 0x8b, 0xf8, 0xde, 0xe4, 0x23, 0x01, 0xd6, - 0x0a, 0xe1, 0x08, 0x9f, 0xd5, 0xf4, 0x76, 0x6b, 0x08, 0x4c, 0xa8, 0x78, 0x07, 0xd9, 0x69, 0xd2, 0x6f, 0x46, 0x18, - 0x4f, 0x44, 0x8c, 0x9a, 0x51, 0x10, 0x38, 0x0d, 0x70, 0x88, 0xc9, 0x04, 0xbe, 0xa3, 0x52, 0xd4, 0xb1, 0x29, 0x12, - 0xae, 0x5b, 0x38, 0x8c, 0x5a, 0x80, 0x3d, 0x66, 0xdb, 0x39, 0x84, 0x96, 0xd4, 0x95, 0xcc, 0x5b, 0x20, 0x09, 0x32, - 0xd2, 0xe5, 0x3e, 0x2b, 0x7e, 0x89, 0xb2, 0x54, 0x86, 0xcf, 0xd0, 0x22, 0x42, 0x83, 0x5a, 0x8b, 0x4c, 0x6a, 0x2d, - 0xb9, 0x83, 0x5a, 0xcb, 0x09, 0xc4, 0xca, 0xb0, 0xa4, 0x92, 0x39, 0x9a, 0xf8, 0xfb, 0xb9, 0x1f, 0x8d, 0x73, 0x80, - 0xe3, 0x01, 0xfe, 0x48, 0xfd, 0x04, 0xe8, 0x9c, 0x09, 0xd9, 0x27, 0xea, 0x0c, 0x83, 0xff, 0xc0, 0x98, 0xfd, 0xee, - 0x1c, 0xff, 0xa6, 0x70, 0xa3, 0xf7, 0x30, 0x21, 0xc4, 0xde, 0x60, 0x1c, 0xd8, 0x03, 0xc7, 0x9b, 0xec, 0xe3, 0x2f, - 0xfc, 0x27, 0x83, 0x9f, 0xa5, 0xe0, 0x61, 0x52, 0x66, 0x6e, 0x27, 0x3e, 0x86, 0x2b, 0x1b, 0x8c, 0x87, 0x9e, 0x92, - 0xee, 0xa6, 0x8f, 0xfa, 0x83, 0x5d, 0x67, 0x14, 0xd8, 0x69, 0x17, 0xee, 0x39, 0x7a, 0xf7, 0xda, 0x79, 0x6f, 0x22, - 0xc2, 0xb3, 0x21, 0x99, 0x97, 0x6b, 0x32, 0x2f, 0x45, 0x0c, 0x88, 0xcb, 0x44, 0x14, 0xeb, 0x9a, 0x48, 0x29, 0x02, - 0x9f, 0xd3, 0x3c, 0x05, 0x0a, 0xa2, 0xea, 0xa4, 0xa5, 0x8a, 0x16, 0x18, 0xe8, 0x92, 0x16, 0xc7, 0x55, 0x38, 0x3f, - 0x19, 0xc3, 0x18, 0x35, 0x94, 0x92, 0xdd, 0x6d, 0x26, 0x15, 0xc8, 0x2f, 0x07, 0x04, 0xc5, 0xdd, 0xa1, 0x9b, 0xef, - 0x03, 0xb4, 0xc3, 0x04, 0x1e, 0xa9, 0x99, 0xf1, 0x8b, 0xe3, 0xc4, 0x60, 0x7a, 0x15, 0x22, 0xa0, 0xc2, 0x92, 0x07, - 0xd3, 0x57, 0x1d, 0x77, 0x30, 0x4d, 0x4a, 0xe7, 0x32, 0x5d, 0xce, 0x43, 0xcc, 0x0a, 0x06, 0xd8, 0xb8, 0x73, 0x86, - 0x96, 0xec, 0x70, 0xa3, 0x92, 0xb3, 0xce, 0x72, 0x81, 0xb1, 0x73, 0x1f, 0xac, 0xf2, 0xb2, 0xc3, 0xdf, 0x75, 0x68, - 0xe4, 0xf8, 0x0a, 0xca, 0x87, 0x83, 0xc1, 0xa0, 0x7f, 0x82, 0xa8, 0x03, 0x01, 0x2d, 0x5c, 0x65, 0x19, 0x05, 0x34, - 0x3d, 0x5f, 0x2c, 0x8b, 0xc8, 0x58, 0x17, 0x97, 0x64, 0xa5, 0x43, 0x20, 0x32, 0x23, 0x4a, 0x82, 0xa2, 0xee, 0x55, - 0x24, 0xf2, 0x9f, 0x34, 0x3f, 0x91, 0x27, 0x9a, 0x4f, 0x6a, 0xff, 0xc3, 0xfb, 0x83, 0xd7, 0x9f, 0x5e, 0xff, 0xf4, - 0xf2, 0xf8, 0xf5, 0xbb, 0x57, 0xaf, 0xdf, 0xbd, 0xfe, 0xf4, 0xb7, 0x5b, 0x08, 0x6c, 0xd3, 0x56, 0x44, 0xad, 0xbd, - 0xc1, 0xc7, 0x18, 0xbd, 0x98, 0xc2, 0xd9, 0x2d, 0xcd, 0xc5, 0x62, 0xd8, 0x04, 0x49, 0x2d, 0x24, 0xae, 0x20, 0x34, - 0x0a, 0xc1, 0x27, 0x10, 0xa1, 0x51, 0x10, 0x19, 0x8f, 0x27, 0xb6, 0x20, 0x2a, 0x5e, 0x13, 0x1c, 0x00, 0xc3, 0xe4, - 0x33, 0x53, 0x26, 0x91, 0x5a, 0x6d, 0x41, 0x8a, 0xa0, 0xcf, 0x17, 0xfc, 0x35, 0xa8, 0x10, 0xbe, 0xdb, 0xea, 0x37, - 0x2c, 0x98, 0x01, 0xe4, 0x5a, 0x68, 0xdf, 0x0a, 0xd8, 0x8b, 0xfa, 0xc6, 0x2f, 0xf6, 0x0c, 0x35, 0x29, 0x9a, 0xa8, - 0x5f, 0xf9, 0x4d, 0x4e, 0xcc, 0xa5, 0xd4, 0xa1, 0x1e, 0x67, 0x78, 0xbf, 0x59, 0x8c, 0x0d, 0xa0, 0x10, 0xc8, 0xac, - 0xdc, 0x48, 0x77, 0x59, 0xb4, 0x70, 0x46, 0x3f, 0x20, 0xfa, 0x61, 0xd5, 0x04, 0xc1, 0x22, 0x8b, 0x75, 0x65, 0x44, - 0x6d, 0x8f, 0xed, 0x4c, 0x3e, 0xda, 0x15, 0x00, 0xa8, 0x98, 0x1d, 0x05, 0x02, 0xe5, 0xe1, 0x55, 0xae, 0x7f, 0x46, - 0xbd, 0x38, 0xa9, 0xd7, 0x0b, 0xae, 0x30, 0xc5, 0xb0, 0xc9, 0x22, 0x54, 0x36, 0x5c, 0x6f, 0xb2, 0x66, 0x5a, 0x24, - 0x5f, 0x05, 0xdf, 0x92, 0xdc, 0xa2, 0x9d, 0xa5, 0xa8, 0x72, 0x5d, 0x68, 0x0f, 0x54, 0x65, 0xc7, 0x73, 0xdf, 0xc6, - 0xd8, 0x8c, 0x9b, 0xea, 0x90, 0x68, 0xbf, 0x77, 0x60, 0x99, 0x36, 0xb7, 0x46, 0x51, 0x0f, 0xe0, 0x41, 0xd2, 0x05, - 0x86, 0xaf, 0x01, 0xcd, 0xa3, 0x3a, 0x20, 0x4f, 0x9a, 0x30, 0x1c, 0x1a, 0xbf, 0x8d, 0x49, 0xfa, 0x14, 0x55, 0x1c, - 0xaa, 0xd5, 0x70, 0x29, 0xa5, 0x69, 0xe4, 0x36, 0xa1, 0x0c, 0x0a, 0x91, 0xce, 0x03, 0x60, 0xa7, 0x04, 0xaa, 0x0a, - 0xb5, 0xa4, 0xe3, 0x22, 0x5e, 0xdd, 0xc1, 0x64, 0x33, 0x77, 0x6d, 0xb2, 0xd5, 0x75, 0x86, 0x19, 0xc1, 0xdf, 0xaf, - 0x14, 0xd5, 0x44, 0x86, 0xe8, 0x42, 0x28, 0xf8, 0x2b, 0x7a, 0x79, 0x46, 0x9e, 0x50, 0x80, 0xae, 0xc3, 0x1d, 0x6d, - 0x77, 0xbc, 0xb2, 0x8b, 0xb5, 0x23, 0x0e, 0x5b, 0x69, 0x3a, 0xcb, 0x73, 0xdb, 0x1c, 0x5d, 0x27, 0x01, 0xf4, 0xde, - 0x32, 0x77, 0xe3, 0x1a, 0x20, 0x50, 0xb2, 0x0b, 0x8d, 0xfb, 0x13, 0x03, 0xf7, 0x27, 0x0a, 0xf7, 0xab, 0x4b, 0xc0, - 0x3e, 0xac, 0x38, 0xb2, 0x57, 0xd0, 0xbd, 0x1c, 0xf2, 0xa0, 0xaa, 0xcb, 0x22, 0x58, 0x1c, 0x6d, 0x2a, 0xd8, 0xb5, - 0x33, 0x70, 0x53, 0x52, 0x8f, 0x7c, 0x47, 0xa3, 0xda, 0xcc, 0x9d, 0xdb, 0xf9, 0xcc, 0x3f, 0x97, 0x83, 0x5c, 0xc7, - 0xdb, 0xfd, 0x11, 0x86, 0x0e, 0xb9, 0xb5, 0x30, 0x31, 0xd4, 0xd5, 0x41, 0x46, 0xbc, 0x5a, 0x78, 0x3b, 0xaf, 0xf6, - 0x21, 0x16, 0xc7, 0xae, 0xc0, 0xa8, 0x41, 0x40, 0x70, 0x44, 0x59, 0x3c, 0x29, 0x95, 0x42, 0xe3, 0x7d, 0x84, 0xa9, - 0x3d, 0x0c, 0xc4, 0x85, 0x72, 0x58, 0x80, 0xfa, 0x9f, 0x0b, 0x29, 0x00, 0x34, 0x49, 0xec, 0xf7, 0x11, 0xbc, 0xec, - 0x9a, 0x12, 0xbf, 0x34, 0x35, 0xc5, 0xc5, 0x9b, 0x8d, 0xca, 0x0e, 0x79, 0x95, 0xe8, 0xac, 0xb9, 0x69, 0x3d, 0xe7, - 0x87, 0xf9, 0x05, 0x65, 0x83, 0x30, 0xc6, 0x12, 0x6f, 0x26, 0x2d, 0xbb, 0x5c, 0x20, 0xaa, 0xcd, 0x75, 0x9b, 0x69, - 0x8d, 0xfd, 0x2c, 0x7a, 0xb1, 0xc0, 0x29, 0xef, 0x51, 0xf6, 0x45, 0xd4, 0xfd, 0x48, 0x74, 0x9c, 0x38, 0xfb, 0xc3, - 0xc1, 0xc8, 0x49, 0xba, 0xdd, 0x5a, 0xf1, 0x1e, 0x15, 0xf7, 0x7a, 0x0d, 0xe2, 0x32, 0x11, 0xf3, 0x30, 0xe6, 0x80, - 0xfd, 0x55, 0xae, 0xa4, 0xb3, 0x2a, 0xfc, 0x7f, 0xa0, 0x59, 0x2c, 0x02, 0x47, 0x1d, 0x7e, 0x11, 0xf8, 0xe0, 0x1c, - 0xc7, 0x50, 0xc8, 0xe8, 0xc9, 0x30, 0x52, 0xf2, 0x91, 0xcd, 0xfc, 0x14, 0x08, 0x20, 0x73, 0xe6, 0x9a, 0xc0, 0x01, - 0x54, 0x2d, 0xbd, 0xe4, 0x83, 0xca, 0xe2, 0x50, 0x1e, 0x87, 0x7c, 0x3f, 0xad, 0x7c, 0x07, 0x64, 0xf3, 0x40, 0x9a, - 0x2a, 0x0b, 0x56, 0xa2, 0x00, 0x7a, 0xe8, 0x11, 0xb0, 0x6b, 0x99, 0x3b, 0x33, 0xd7, 0x92, 0xca, 0x37, 0x83, 0xcd, - 0xe1, 0xc0, 0x79, 0x14, 0x3c, 0x1a, 0xca, 0x70, 0xc3, 0x66, 0x8d, 0x79, 0x6f, 0xe6, 0x6c, 0x56, 0xbb, 0x44, 0x53, - 0x54, 0x39, 0x33, 0xb3, 0x93, 0x49, 0x77, 0xd6, 0x0d, 0x1f, 0xd5, 0xea, 0x52, 0xaf, 0x62, 0xbd, 0x97, 0x7b, 0x11, - 0xac, 0x67, 0x85, 0x63, 0x58, 0xc2, 0x6a, 0xfd, 0x9a, 0x66, 0x1e, 0x1c, 0x99, 0x25, 0x6c, 0x74, 0x7c, 0x96, 0xc4, - 0xd3, 0x78, 0x02, 0x00, 0xc9, 0x0b, 0x81, 0x97, 0x08, 0xf7, 0xfd, 0xe1, 0x60, 0x1c, 0xfa, 0xe1, 0xde, 0x70, 0x77, - 0x3c, 0xdc, 0xf5, 0xb6, 0x06, 0x5e, 0x08, 0xdc, 0x16, 0x14, 0x6f, 0x0d, 0xd0, 0xc5, 0x0e, 0x9f, 0xfd, 0x2d, 0x5c, - 0xba, 0x7d, 0x22, 0x09, 0x33, 0x1c, 0xda, 0xfd, 0x86, 0x24, 0x96, 0x73, 0xca, 0x33, 0x01, 0x44, 0xb7, 0x34, 0x1c, - 0x5c, 0xcc, 0x11, 0x4e, 0xf5, 0x08, 0xa7, 0xcd, 0x11, 0x26, 0x02, 0x6c, 0x07, 0xe9, 0xbf, 0x83, 0xc3, 0x58, 0xc7, - 0x4b, 0xc8, 0xc3, 0x75, 0x11, 0x03, 0x29, 0x93, 0x16, 0x29, 0x72, 0x13, 0x2c, 0x0a, 0xeb, 0x07, 0x8b, 0xc5, 0x5c, - 0xb8, 0x88, 0x1d, 0x42, 0xdd, 0x23, 0xce, 0x53, 0x8c, 0x24, 0xb4, 0x34, 0x90, 0xfb, 0x0d, 0x98, 0x02, 0x5f, 0xa9, - 0x7d, 0x24, 0x1f, 0xf9, 0xab, 0x8d, 0xc6, 0xa8, 0xc9, 0xfe, 0x60, 0xcc, 0xb1, 0x2e, 0xee, 0x92, 0xf7, 0xfe, 0x0e, - 0x54, 0xa4, 0x50, 0x33, 0xea, 0x09, 0x3c, 0xed, 0x11, 0xa7, 0x30, 0x93, 0x51, 0x21, 0x32, 0x2b, 0x28, 0xe9, 0xaf, - 0xe6, 0x66, 0x94, 0x6d, 0x8f, 0x98, 0x85, 0x14, 0x8a, 0xfe, 0x46, 0xef, 0x64, 0xbf, 0x18, 0x97, 0x90, 0x17, 0x76, - 0x79, 0x76, 0x16, 0xe5, 0x18, 0x44, 0x28, 0x4e, 0x80, 0x95, 0xfa, 0x55, 0x86, 0x26, 0x05, 0xf6, 0x06, 0x4a, 0x94, - 0x33, 0x0e, 0x0e, 0x15, 0xa1, 0xff, 0xe7, 0x42, 0xfd, 0x76, 0x07, 0xce, 0xd8, 0xfc, 0xd9, 0x1b, 0x3a, 0x5e, 0xf5, - 0xb5, 0x73, 0x07, 0x36, 0xbd, 0x83, 0x45, 0xfb, 0x27, 0x64, 0xe6, 0x92, 0x42, 0xc6, 0xfe, 0x73, 0x4d, 0x3c, 0x49, - 0xbd, 0x4e, 0xe0, 0xef, 0x43, 0x85, 0x31, 0x66, 0x61, 0xcf, 0xf0, 0x07, 0xb3, 0x65, 0xc1, 0x08, 0x77, 0x1f, 0xd5, - 0x88, 0xc9, 0x1e, 0x5c, 0x1a, 0x3b, 0xb5, 0x87, 0x68, 0xdf, 0x0b, 0x20, 0x00, 0x28, 0xbb, 0xd4, 0x86, 0x39, 0xd1, - 0xe4, 0xb0, 0xec, 0x73, 0x41, 0x8a, 0x09, 0x0c, 0x11, 0x88, 0x75, 0x1f, 0x3e, 0x4c, 0xb9, 0x88, 0x5e, 0xe7, 0x54, - 0x92, 0xf1, 0x07, 0xff, 0x8c, 0x54, 0x5d, 0x13, 0xfd, 0x7c, 0x7e, 0xcc, 0x9d, 0x60, 0x3a, 0x5d, 0x97, 0x04, 0x57, - 0x98, 0xdc, 0x39, 0x43, 0x1d, 0x04, 0x96, 0xde, 0x45, 0xef, 0x26, 0xeb, 0xe9, 0xdd, 0xe4, 0x5f, 0x47, 0xef, 0x26, - 0xb7, 0x11, 0x86, 0x85, 0x0a, 0x0d, 0x3f, 0xb6, 0x06, 0x96, 0xf7, 0xcf, 0xd3, 0x89, 0x6b, 0x69, 0x6a, 0x18, 0xd5, - 0x68, 0x0d, 0xd1, 0x6c, 0x02, 0x14, 0x0a, 0xab, 0xd8, 0x84, 0x27, 0xcb, 0x42, 0x71, 0xad, 0x4e, 0x8f, 0xea, 0xdc, - 0x42, 0x1a, 0xd9, 0x7a, 0x36, 0xc0, 0x89, 0x10, 0x30, 0xd1, 0x22, 0x78, 0x5c, 0x33, 0x25, 0x7d, 0xbf, 0xb9, 0x91, - 0x2a, 0xcc, 0x5b, 0xa9, 0x28, 0xac, 0x2e, 0x3f, 0x1e, 0x0f, 0x3c, 0x9b, 0x06, 0xf0, 0x4f, 0x13, 0x56, 0x15, 0xd9, - 0x7c, 0x2b, 0x21, 0xd5, 0x30, 0x79, 0x1a, 0x36, 0x41, 0x6f, 0x37, 0x6a, 0x91, 0x9f, 0x03, 0xbd, 0x15, 0xa4, 0x92, - 0xde, 0x4a, 0xcf, 0x82, 0x2c, 0x2e, 0x66, 0xe7, 0xf1, 0x84, 0x88, 0x2e, 0x7c, 0x71, 0x6f, 0xa2, 0xcb, 0xf8, 0x58, - 0x20, 0x18, 0x43, 0x29, 0x5e, 0x56, 0x44, 0xe9, 0xcb, 0x9a, 0x67, 0x05, 0x33, 0x4f, 0x9c, 0xb3, 0x3d, 0xce, 0xd1, - 0xe9, 0x14, 0x4d, 0xf0, 0xc5, 0xa3, 0x9e, 0xfd, 0x04, 0xe3, 0x82, 0x62, 0xcf, 0x61, 0x96, 0x2e, 0x64, 0x2c, 0x27, - 0x15, 0xba, 0x13, 0x63, 0x86, 0x02, 0xe5, 0x8c, 0x0c, 0x14, 0xfe, 0x25, 0x03, 0x23, 0xf7, 0x95, 0x7e, 0x76, 0xba, - 0x32, 0xd2, 0xa5, 0xc4, 0x08, 0x03, 0x4d, 0xed, 0x04, 0x61, 0x2d, 0xcb, 0x59, 0xe4, 0x7f, 0x64, 0x96, 0x02, 0x0d, - 0xf0, 0x56, 0x97, 0xde, 0xf1, 0x84, 0xbc, 0x16, 0x58, 0xe7, 0x8d, 0xd4, 0xcd, 0xcc, 0x93, 0xc2, 0xc5, 0x47, 0x85, - 0x41, 0x82, 0x1b, 0xf6, 0x0b, 0x13, 0x65, 0xeb, 0x87, 0xc6, 0x6c, 0x46, 0xb2, 0xc0, 0x84, 0x13, 0x05, 0xe6, 0x63, - 0x61, 0x69, 0x5a, 0xf4, 0xa2, 0xcd, 0x2d, 0xb2, 0x36, 0x2d, 0xba, 0xf0, 0x54, 0x7a, 0xf1, 0x1e, 0x56, 0xd9, 0x37, - 0x2b, 0xf0, 0xeb, 0xd2, 0x93, 0x25, 0xb2, 0xba, 0xd9, 0x5f, 0x68, 0xae, 0xea, 0x0a, 0x5d, 0x3f, 0x30, 0x02, 0x58, - 0x17, 0x1d, 0x02, 0x79, 0xb1, 0x44, 0x44, 0x30, 0x78, 0x41, 0xd1, 0xbe, 0x7a, 0xc6, 0x1b, 0x11, 0xfe, 0x0b, 0xdd, - 0x45, 0xd2, 0x85, 0xf9, 0x09, 0x05, 0xfe, 0xf2, 0x62, 0xa1, 0x4c, 0x31, 0x3f, 0x11, 0xea, 0x15, 0x00, 0x77, 0x55, - 0x6b, 0x3e, 0xcc, 0xd6, 0xe4, 0xb8, 0x82, 0x30, 0x44, 0xff, 0x56, 0x3f, 0x16, 0x96, 0xaa, 0xac, 0x3e, 0x94, 0x5e, - 0x6b, 0x99, 0xb6, 0x7c, 0xec, 0x1b, 0xaf, 0x29, 0x75, 0xec, 0x44, 0x5b, 0xca, 0x71, 0xe9, 0xf8, 0xdd, 0x66, 0xea, - 0xe9, 0x80, 0xd3, 0x13, 0x7f, 0x30, 0x9a, 0xec, 0xa5, 0xa3, 0x89, 0x0e, 0x99, 0x3f, 0xf7, 0x29, 0xb3, 0xaa, 0x0c, - 0xc2, 0xc2, 0x36, 0x94, 0xaa, 0x01, 0x59, 0x3c, 0x71, 0x9c, 0x11, 0xa5, 0xa2, 0x98, 0xf7, 0xc5, 0x3c, 0x94, 0x37, - 0xab, 0xfe, 0xe2, 0x83, 0x08, 0x70, 0x6a, 0x4f, 0x30, 0x11, 0x78, 0x16, 0x5c, 0x42, 0x35, 0xf4, 0x18, 0xee, 0xe2, - 0x97, 0xe8, 0x26, 0x17, 0xfa, 0x7f, 0x2d, 0xec, 0x39, 0x9d, 0x2d, 0x24, 0xd0, 0xf0, 0xf4, 0x50, 0x74, 0xb8, 0xd0, - 0xad, 0x4e, 0x15, 0x43, 0x6c, 0x8c, 0x30, 0x97, 0x85, 0xbf, 0x54, 0xe4, 0xd9, 0x0f, 0x3c, 0x34, 0xb2, 0x4e, 0x78, - 0x96, 0x9c, 0xcd, 0x31, 0x8b, 0x4a, 0x37, 0x40, 0x77, 0x24, 0x83, 0xce, 0x7b, 0x90, 0x00, 0x6d, 0x86, 0x6e, 0x65, - 0x70, 0x88, 0x16, 0xee, 0xac, 0x0f, 0xd4, 0x5c, 0xff, 0xd2, 0x1d, 0xb8, 0xc3, 0xa7, 0x03, 0xb2, 0xc8, 0xe6, 0xd2, - 0x6b, 0x28, 0x9d, 0xb9, 0x5f, 0x0f, 0xdc, 0xad, 0x27, 0x40, 0x93, 0xcc, 0x09, 0x99, 0xb8, 0x53, 0x74, 0xec, 0x72, - 0x4a, 0xf2, 0xd4, 0x34, 0x0d, 0x0e, 0xe1, 0x94, 0xf6, 0xe0, 0xc8, 0xba, 0x51, 0x3f, 0xeb, 0x01, 0xfa, 0x80, 0xc3, - 0x0c, 0xc7, 0xaa, 0x0f, 0x07, 0xa9, 0x7f, 0x0a, 0xbf, 0x4f, 0x9d, 0xea, 0xd0, 0x5f, 0x17, 0xd1, 0x79, 0xee, 0x2f, - 0xf1, 0x5a, 0xe0, 0xf1, 0xd5, 0xa7, 0x6c, 0x1e, 0x9a, 0xa7, 0x5a, 0x62, 0x66, 0x45, 0xd9, 0x2b, 0x76, 0x37, 0x72, - 0x54, 0x3c, 0x6e, 0x55, 0x8e, 0xac, 0x2f, 0x94, 0x13, 0xa6, 0xe7, 0xc8, 0x0f, 0x83, 0x51, 0xc2, 0x78, 0x08, 0xcd, - 0x24, 0xc6, 0x76, 0xe0, 0xd3, 0x30, 0x45, 0x19, 0x2a, 0x70, 0xe0, 0x0c, 0x6b, 0x51, 0x1d, 0xfc, 0x70, 0xf1, 0x7d, - 0x00, 0x98, 0x3d, 0x41, 0x5c, 0xb5, 0x0f, 0x13, 0xc1, 0x9c, 0x23, 0xbe, 0x4d, 0x3f, 0x71, 0x5e, 0xfc, 0x91, 0x11, - 0x09, 0x3c, 0xa6, 0xb9, 0x66, 0xb0, 0xc4, 0x18, 0x18, 0x54, 0x76, 0x56, 0x8c, 0xed, 0x09, 0x76, 0x56, 0xf4, 0x72, - 0xd9, 0x59, 0x06, 0xdf, 0x15, 0x66, 0x67, 0x05, 0xad, 0x11, 0x9c, 0x18, 0x2f, 0x17, 0x9d, 0xa1, 0xfa, 0x04, 0x3e, - 0xcb, 0x45, 0x67, 0xa7, 0xfc, 0xd1, 0xa9, 0xd9, 0xd9, 0x29, 0xba, 0x90, 0x76, 0x27, 0x26, 0x2b, 0x35, 0x0b, 0xeb, - 0xec, 0x60, 0xe5, 0x54, 0xb9, 0x2b, 0x38, 0x98, 0x59, 0xe0, 0xc1, 0xc9, 0x57, 0x39, 0xa0, 0xe9, 0x60, 0x78, 0xa9, - 0x2b, 0xce, 0x28, 0xfa, 0x43, 0xa2, 0xa8, 0x34, 0x40, 0xaf, 0xce, 0x49, 0xdb, 0x49, 0x05, 0xee, 0xae, 0x9b, 0x77, - 0x33, 0xe4, 0x9f, 0xe6, 0xb5, 0x83, 0xf4, 0x03, 0x66, 0x54, 0xc6, 0xf6, 0xba, 0x3f, 0x52, 0xf2, 0x64, 0xff, 0x2c, - 0x84, 0x92, 0x6b, 0x37, 0x80, 0xb3, 0x83, 0xe1, 0x60, 0xfc, 0x69, 0xc8, 0xf1, 0xd6, 0x17, 0x58, 0x7e, 0x05, 0xe5, - 0x97, 0x6e, 0xa8, 0x6c, 0x4e, 0x65, 0xa8, 0xab, 0x8d, 0x81, 0x7b, 0xe5, 0xe1, 0xeb, 0x6b, 0x6f, 0xe6, 0xe2, 0x55, - 0x7a, 0x36, 0x87, 0xcb, 0xee, 0x85, 0x2e, 0x45, 0x20, 0x5c, 0x52, 0xe4, 0xc0, 0x99, 0x88, 0x36, 0xb8, 0xec, 0x62, - 0x1b, 0x22, 0x5c, 0xe0, 0x0c, 0x7e, 0xcc, 0x0c, 0x30, 0x15, 0x0a, 0x46, 0x96, 0xc2, 0x47, 0x6b, 0x1b, 0x2d, 0xa6, - 0x19, 0xa9, 0xb1, 0x88, 0xc3, 0x10, 0x8a, 0xc6, 0x72, 0xd9, 0x50, 0xaa, 0x13, 0x47, 0x6e, 0xd8, 0x41, 0x61, 0xaf, - 0xd0, 0xb4, 0xe8, 0x1a, 0xcd, 0xa3, 0x50, 0xe1, 0xa0, 0x0b, 0x52, 0xb3, 0x20, 0xaf, 0xd7, 0xc8, 0x65, 0x0d, 0x63, - 0x83, 0x96, 0x8d, 0x0d, 0x22, 0xd8, 0xd5, 0x0e, 0xb6, 0x52, 0xd3, 0x60, 0xbb, 0x01, 0xa7, 0x60, 0xa7, 0x04, 0xde, - 0xc2, 0xcd, 0x4a, 0x2b, 0x80, 0x6d, 0xe2, 0x8b, 0x9d, 0x5e, 0x62, 0xec, 0x69, 0x00, 0xf9, 0xf5, 0xfd, 0xce, 0x00, - 0xca, 0xe5, 0xde, 0x80, 0x2d, 0x78, 0xe7, 0x0a, 0xd8, 0xcd, 0xe0, 0x9a, 0xcc, 0xf6, 0xf2, 0xd1, 0x8c, 0x80, 0x9d, - 0x84, 0x5b, 0x7e, 0x74, 0x38, 0x3b, 0x72, 0x27, 0x84, 0xdb, 0xfc, 0x02, 0x9e, 0x05, 0x84, 0x09, 0x7d, 0x3a, 0x6f, - 0x33, 0xf2, 0xff, 0x67, 0xc6, 0x2f, 0xc4, 0xf0, 0x12, 0x40, 0x50, 0x62, 0x84, 0x7b, 0x34, 0x2d, 0x08, 0x55, 0x96, - 0x0d, 0xd8, 0x8c, 0x90, 0x0e, 0x81, 0x2c, 0x81, 0xb7, 0x73, 0x3f, 0x74, 0x8c, 0xd0, 0xa1, 0x6a, 0x95, 0xa6, 0xa1, - 0x29, 0x04, 0x41, 0x1a, 0x89, 0xf1, 0x18, 0xc0, 0xa4, 0xb1, 0xc5, 0x0b, 0x61, 0x01, 0xea, 0xa2, 0x9f, 0x94, 0xb8, - 0xc8, 0x13, 0x79, 0x3b, 0x75, 0x13, 0x8b, 0x26, 0x9a, 0xc5, 0x3c, 0x49, 0x54, 0x6b, 0x1c, 0xf7, 0x7c, 0xd8, 0x7b, - 0x0a, 0x2a, 0xcd, 0x8d, 0xa1, 0xfd, 0x1a, 0x94, 0x6d, 0x6e, 0x61, 0xa6, 0x56, 0xd5, 0xc6, 0x59, 0x5b, 0x1b, 0x5f, - 0x63, 0x20, 0x6b, 0xf8, 0x0b, 0x80, 0x70, 0xcc, 0xdf, 0x78, 0x76, 0xb4, 0x0f, 0xbf, 0xa0, 0x78, 0xef, 0x6b, 0x22, - 0xe6, 0xb0, 0xb8, 0xd2, 0xd0, 0x79, 0x75, 0xd7, 0x45, 0x28, 0x4d, 0x3a, 0x7b, 0xb9, 0x38, 0x7b, 0xa9, 0x3c, 0x7b, - 0x19, 0xb9, 0x53, 0x4b, 0xda, 0x83, 0x6d, 0x67, 0xd1, 0x04, 0x9d, 0xcc, 0xee, 0x50, 0x07, 0xaf, 0x15, 0x41, 0xaf, - 0x27, 0xb6, 0xf4, 0x08, 0x65, 0xa3, 0x5e, 0xca, 0x07, 0xd5, 0x4a, 0xba, 0xc4, 0x86, 0x01, 0x73, 0xa0, 0xf0, 0x50, - 0xd2, 0x9b, 0x33, 0xa2, 0x0e, 0xfd, 0x1c, 0x1e, 0x11, 0x01, 0x2f, 0xfd, 0xb4, 0x97, 0x74, 0xe7, 0x22, 0xca, 0xf7, - 0xd4, 0xcf, 0x7a, 0x39, 0xfc, 0x62, 0x6a, 0x66, 0x54, 0xcd, 0x4d, 0x3b, 0x11, 0xe9, 0x99, 0x17, 0xfe, 0xfe, 0x62, - 0x03, 0xe9, 0x58, 0xf4, 0x64, 0x36, 0x3d, 0x1f, 0x9f, 0x23, 0x25, 0x03, 0x17, 0x61, 0x06, 0x17, 0x21, 0x74, 0x2f, - 0xe1, 0xea, 0xce, 0xbc, 0xa9, 0x34, 0x31, 0x9e, 0x94, 0x88, 0x07, 0x70, 0x54, 0x18, 0x12, 0x8f, 0x9f, 0x3e, 0x42, - 0xeb, 0xf6, 0x0c, 0x70, 0xdb, 0xd2, 0x9d, 0x9a, 0xf6, 0x99, 0xa7, 0xa6, 0x44, 0x6a, 0x45, 0x31, 0xd6, 0x94, 0xa1, - 0xe2, 0xca, 0x38, 0xf7, 0x70, 0xff, 0xf0, 0xe6, 0xea, 0xdc, 0x44, 0x45, 0x6f, 0x38, 0xca, 0x31, 0x62, 0x6b, 0xde, - 0xeb, 0x69, 0x14, 0xd2, 0x44, 0x3f, 0x22, 0xd1, 0xf3, 0x46, 0xaa, 0x62, 0xdb, 0xd6, 0xfc, 0x81, 0x31, 0x4d, 0xe9, - 0xdd, 0x28, 0x1f, 0x23, 0x56, 0x9c, 0x23, 0x6e, 0x44, 0xe8, 0xa8, 0x84, 0x4e, 0x80, 0xc0, 0x33, 0x81, 0xc0, 0x61, - 0x31, 0x26, 0xb0, 0x18, 0x73, 0x03, 0xac, 0xcd, 0xe0, 0xee, 0x8e, 0x8e, 0x63, 0xf8, 0xa8, 0x86, 0xd0, 0xf3, 0x23, - 0x0c, 0xa2, 0x05, 0x20, 0xcd, 0x90, 0xba, 0x6e, 0xa1, 0xd3, 0x10, 0x99, 0x84, 0x7a, 0xc8, 0xaa, 0x50, 0x18, 0x01, - 0xdd, 0x12, 0x3d, 0xa3, 0x89, 0x0a, 0x7e, 0x81, 0x2e, 0x32, 0x21, 0x30, 0xcd, 0x56, 0x69, 0xae, 0xe4, 0xdb, 0xac, - 0xee, 0xed, 0x8a, 0xab, 0x89, 0xc6, 0x9e, 0x64, 0x9f, 0xe7, 0xe4, 0xfd, 0x20, 0x83, 0x5d, 0xeb, 0x5f, 0x31, 0x3e, - 0x87, 0x31, 0x5d, 0x8b, 0xa7, 0x02, 0x68, 0x82, 0x9f, 0x44, 0x42, 0x1b, 0x96, 0xbe, 0xb5, 0xe0, 0x06, 0xb2, 0x5e, - 0xcc, 0xa5, 0xff, 0x75, 0x0a, 0x30, 0x3c, 0xed, 0x5f, 0x9b, 0x96, 0x54, 0xc3, 0x51, 0xb6, 0x97, 0x90, 0x21, 0x55, - 0xeb, 0xf7, 0x19, 0xd2, 0x73, 0xb9, 0xf4, 0x9d, 0x96, 0xdf, 0x1b, 0xe3, 0x3f, 0x6e, 0xa5, 0x09, 0x98, 0x24, 0xca, - 0xfc, 0xa2, 0x8f, 0x76, 0xec, 0xcb, 0x79, 0x90, 0xc9, 0x55, 0x0a, 0x5c, 0x65, 0xd2, 0x4f, 0x89, 0x2b, 0x46, 0x1b, - 0x19, 0xba, 0x5a, 0xa2, 0x93, 0x00, 0xe6, 0xd0, 0xc4, 0x3b, 0x3b, 0xc0, 0xac, 0xe7, 0xd2, 0x31, 0x2a, 0xad, 0xb8, - 0x07, 0x04, 0x42, 0xe6, 0xcd, 0x2e, 0x01, 0x13, 0x7c, 0x6b, 0xc4, 0xa4, 0xc0, 0x18, 0x83, 0xf9, 0xcc, 0x11, 0x75, - 0x8c, 0xe8, 0x13, 0xfc, 0x42, 0x44, 0x9d, 0x48, 0x2b, 0x57, 0x82, 0xd6, 0x1f, 0xcf, 0x47, 0x42, 0xc1, 0xab, 0x0c, - 0xd7, 0x5f, 0xd9, 0x33, 0x3d, 0x6a, 0x77, 0x2c, 0x3d, 0xf5, 0xeb, 0x3a, 0x34, 0x7a, 0x85, 0x16, 0xbe, 0x2b, 0x36, - 0x8f, 0x8c, 0x54, 0x84, 0x54, 0x0e, 0x56, 0xaa, 0x0f, 0x12, 0xee, 0x3f, 0xcb, 0xd9, 0x8a, 0xd8, 0x54, 0x8f, 0xdc, - 0x2a, 0x67, 0x13, 0xdb, 0x5f, 0x91, 0xa0, 0x5d, 0xb7, 0x94, 0x19, 0xb4, 0x45, 0x8b, 0xcf, 0xae, 0xb2, 0xc4, 0x6c, - 0x14, 0x32, 0xcd, 0xc7, 0x81, 0xad, 0x5e, 0xc4, 0xe7, 0xec, 0x63, 0xd5, 0x8c, 0xe3, 0x27, 0xf1, 0x0f, 0x40, 0x85, - 0x65, 0x52, 0x51, 0x82, 0xa0, 0x37, 0x87, 0xb4, 0x2b, 0xe4, 0x84, 0x86, 0x92, 0x03, 0xa7, 0xbd, 0x02, 0x8a, 0x89, - 0x01, 0x98, 0x90, 0xf2, 0x88, 0x04, 0x87, 0xb2, 0x0e, 0xdf, 0x26, 0xa8, 0x24, 0xe0, 0x5a, 0x65, 0xce, 0x75, 0xa5, - 0x33, 0x71, 0x36, 0xc0, 0x2c, 0x75, 0x0b, 0x7a, 0x74, 0xaa, 0xab, 0x51, 0xaf, 0x8d, 0x3c, 0x4d, 0x42, 0x95, 0xe1, - 0xc9, 0x69, 0xae, 0x92, 0x51, 0xdf, 0xd0, 0x0b, 0x27, 0x38, 0x9f, 0x7f, 0x5e, 0x4c, 0x38, 0xac, 0x89, 0x09, 0xc9, - 0xd2, 0x41, 0x88, 0x0e, 0x1a, 0xca, 0x2b, 0xf5, 0x92, 0x98, 0xce, 0xc1, 0xef, 0xd7, 0x63, 0x35, 0x15, 0x08, 0xb5, - 0x49, 0x6e, 0xd6, 0x37, 0x0b, 0x45, 0x0d, 0xa4, 0x66, 0xe7, 0x76, 0xd8, 0xb4, 0x13, 0x0e, 0x5d, 0x45, 0xe6, 0xda, - 0xac, 0x52, 0xb1, 0x99, 0x6c, 0x39, 0x58, 0x72, 0x19, 0x94, 0x9d, 0x2a, 0xf9, 0x1c, 0xd4, 0xfc, 0x08, 0x5e, 0x57, - 0x95, 0x67, 0x26, 0x99, 0x25, 0xc5, 0x0b, 0xee, 0x21, 0x7c, 0x73, 0x54, 0x95, 0x8e, 0xe5, 0x37, 0x37, 0x39, 0x19, - 0x4b, 0xe4, 0x9e, 0x05, 0x57, 0x48, 0xc6, 0xe1, 0x12, 0xad, 0x1b, 0xd2, 0xa7, 0x66, 0x7c, 0xda, 0x84, 0x7c, 0x8f, - 0xd7, 0x19, 0x48, 0x8c, 0x0c, 0xc9, 0x43, 0x51, 0x19, 0x8e, 0x28, 0x1e, 0x4f, 0x42, 0x11, 0x9f, 0x9f, 0x65, 0x67, - 0x55, 0xde, 0x6a, 0xe0, 0xd2, 0xff, 0x9c, 0xb2, 0xce, 0x73, 0x49, 0x98, 0x68, 0x9e, 0xe5, 0x6e, 0x4d, 0x61, 0x11, - 0xd1, 0xb5, 0x31, 0xcf, 0x6f, 0xb5, 0x46, 0xd2, 0xcb, 0x75, 0x0d, 0x63, 0x43, 0x7b, 0x9a, 0x57, 0x69, 0xec, 0xf5, - 0x96, 0xab, 0xd5, 0xc5, 0x62, 0x0c, 0x24, 0x59, 0x32, 0xb8, 0x4e, 0x43, 0xac, 0xf4, 0xd3, 0xa6, 0xdd, 0xd8, 0x47, - 0x41, 0xee, 0xde, 0xdc, 0x0c, 0x9d, 0xba, 0x7d, 0x30, 0xf1, 0x4b, 0xd4, 0x88, 0xf6, 0x0e, 0xeb, 0xfc, 0x60, 0x17, - 0x8f, 0xa2, 0xee, 0x2f, 0xb4, 0xce, 0xb8, 0xfa, 0x31, 0x1b, 0xfa, 0xbc, 0xca, 0xd2, 0x73, 0x9e, 0x94, 0x29, 0x74, - 0xab, 0x99, 0x7a, 0xc3, 0xb9, 0xaf, 0x46, 0xf9, 0x37, 0xa7, 0xa2, 0xa4, 0x78, 0x3d, 0x25, 0x8c, 0xab, 0xc4, 0x6d, - 0xd2, 0x51, 0x4b, 0x85, 0x40, 0x54, 0xd7, 0x77, 0x1e, 0x45, 0x9e, 0x54, 0x67, 0xe2, 0x77, 0x8f, 0x22, 0x53, 0xba, - 0xd6, 0x1c, 0xe2, 0x5d, 0x43, 0xdb, 0x6c, 0x2e, 0x74, 0xcb, 0xe8, 0x6e, 0x1f, 0x9e, 0xaa, 0x1f, 0x79, 0xf2, 0x8b, - 0x2e, 0x0d, 0xab, 0x49, 0xb8, 0x34, 0x0c, 0xf7, 0x8d, 0xed, 0xa1, 0x5c, 0x40, 0x28, 0x31, 0x23, 0x2f, 0x03, 0x9d, - 0xb8, 0x40, 0xb3, 0x30, 0x68, 0x88, 0x2b, 0x47, 0x72, 0x2d, 0xac, 0x6c, 0xcd, 0xc8, 0xdb, 0xa4, 0x10, 0x2c, 0xcb, - 0x16, 0x4e, 0x32, 0xc2, 0xe4, 0x84, 0x35, 0xf7, 0xbe, 0xfa, 0xd9, 0xe9, 0xfd, 0xd8, 0x95, 0x59, 0x73, 0x80, 0x7c, - 0x32, 0x8c, 0xda, 0x1e, 0x09, 0x75, 0xaf, 0xa4, 0x55, 0xae, 0x3d, 0xc3, 0xfa, 0x4d, 0xbe, 0x94, 0xe4, 0x0b, 0xb1, - 0xa5, 0xe8, 0xd0, 0x58, 0x1f, 0x85, 0x3e, 0x2c, 0x06, 0x6a, 0x55, 0xb2, 0xd6, 0xda, 0x78, 0x95, 0x54, 0x74, 0xfd, - 0x99, 0x8b, 0x1c, 0x6d, 0x29, 0xac, 0x3e, 0xbc, 0xbd, 0x61, 0x3d, 0x04, 0x34, 0x68, 0x91, 0x55, 0xb0, 0x05, 0x2e, - 0x16, 0xaa, 0x76, 0xb5, 0x25, 0x66, 0xbb, 0xf7, 0x62, 0x66, 0x5b, 0xd1, 0xaf, 0xde, 0xb4, 0x3b, 0x3e, 0x27, 0x3f, - 0xcc, 0x6f, 0x94, 0x93, 0x92, 0x36, 0x8c, 0xab, 0xf9, 0xff, 0x15, 0xee, 0x59, 0x16, 0x87, 0xde, 0x4a, 0xd2, 0x60, - 0x2a, 0xd5, 0xa6, 0x19, 0x1a, 0xa3, 0xd0, 0xc7, 0x86, 0x81, 0x68, 0x71, 0x85, 0x82, 0x19, 0xa6, 0xbe, 0x92, 0x3a, - 0xad, 0xc4, 0xb0, 0xff, 0xee, 0x45, 0xe7, 0x09, 0x4a, 0xdb, 0x13, 0xc7, 0x8d, 0x9a, 0xd8, 0x42, 0x9e, 0x5a, 0xe8, - 0xc4, 0x24, 0xbb, 0x12, 0x83, 0x31, 0x2a, 0xc4, 0x2f, 0x2a, 0x56, 0x24, 0x18, 0xcf, 0xff, 0x5b, 0x98, 0x5a, 0x1d, - 0xa2, 0x23, 0xd1, 0x59, 0xf5, 0xe9, 0x74, 0x57, 0x74, 0xce, 0x90, 0x44, 0x44, 0x5b, 0x2a, 0x5a, 0x8f, 0x5c, 0xb8, - 0x41, 0xe2, 0x46, 0x44, 0x32, 0xeb, 0x65, 0xcb, 0xc8, 0x58, 0x56, 0x85, 0x34, 0x3f, 0xbb, 0xca, 0xb4, 0xa0, 0x86, - 0x87, 0x0f, 0x4f, 0x43, 0x99, 0xfa, 0xd5, 0x35, 0x4a, 0x99, 0xf2, 0x90, 0xaa, 0x0e, 0x4e, 0x63, 0x04, 0x6c, 0x14, - 0xa2, 0x41, 0x68, 0x2a, 0x24, 0xe6, 0x6c, 0x35, 0xf1, 0xef, 0xb1, 0x90, 0x33, 0x61, 0x50, 0x2f, 0x20, 0xd1, 0xd2, - 0xaf, 0x5f, 0x66, 0x60, 0xf0, 0xa7, 0x7e, 0x6e, 0xf2, 0x42, 0x4b, 0x14, 0x28, 0xa6, 0xd5, 0x92, 0xd1, 0xb1, 0x18, - 0xe7, 0x14, 0xe6, 0x93, 0xb9, 0x0b, 0x58, 0x44, 0x5c, 0x53, 0x25, 0x67, 0x27, 0x27, 0x3b, 0xb9, 0xeb, 0x01, 0x30, - 0x99, 0xc3, 0x51, 0x80, 0x6c, 0x5a, 0xa0, 0xd9, 0xb4, 0x59, 0x95, 0xe3, 0xaa, 0x5c, 0x9c, 0x0a, 0xec, 0x42, 0x69, - 0x9b, 0xa0, 0xf6, 0x43, 0x83, 0xda, 0x5f, 0x96, 0xfe, 0x6c, 0xb4, 0xb1, 0x04, 0x2a, 0x3f, 0x44, 0x1b, 0x51, 0x83, - 0x8e, 0x5f, 0xb2, 0x74, 0x5d, 0x51, 0xf9, 0x21, 0xfe, 0x36, 0xe8, 0xfa, 0x99, 0x19, 0x5c, 0xce, 0x2d, 0xea, 0xd4, - 0xfd, 0xac, 0x19, 0x59, 0xee, 0x5e, 0x4b, 0x1b, 0x89, 0x1d, 0xaa, 0x82, 0x67, 0xa9, 0xbd, 0x23, 0x2d, 0xd8, 0xdc, - 0x6f, 0x07, 0x3c, 0x01, 0xda, 0xb1, 0x17, 0x95, 0xcb, 0x51, 0x48, 0x26, 0xab, 0x02, 0x02, 0x4d, 0x90, 0x27, 0x87, - 0x0e, 0x75, 0xe6, 0xc0, 0x48, 0xcd, 0x31, 0xae, 0x58, 0xa1, 0x98, 0x0c, 0xa7, 0x2c, 0xea, 0x47, 0x9c, 0x7d, 0x85, - 0xe1, 0x90, 0xd3, 0x2f, 0x49, 0x54, 0xdd, 0x79, 0xe4, 0xd1, 0xff, 0x5b, 0xa9, 0x55, 0x36, 0xf4, 0x26, 0x57, 0x1c, - 0xff, 0x5a, 0x61, 0xfb, 0xc0, 0x91, 0x91, 0x80, 0x47, 0xea, 0x30, 0x00, 0xdd, 0x9c, 0x05, 0x49, 0x3e, 0x97, 0x39, - 0xc7, 0xd6, 0x4e, 0x8d, 0x1c, 0x94, 0xd1, 0xaf, 0x1b, 0x3f, 0x91, 0x3c, 0xb0, 0x12, 0xe8, 0x88, 0x42, 0xc9, 0x0c, - 0xfb, 0x92, 0x19, 0x76, 0xdb, 0xae, 0x0a, 0x2e, 0x2f, 0x5f, 0x95, 0x09, 0xbb, 0x1a, 0x6d, 0x44, 0x72, 0x97, 0xaa, - 0xb3, 0x98, 0xb7, 0x9f, 0x49, 0x43, 0xe2, 0xef, 0xce, 0x0c, 0x79, 0x3d, 0x2e, 0x48, 0x7a, 0x9f, 0xa3, 0xa1, 0x07, - 0x85, 0xc9, 0xa9, 0xf9, 0x06, 0xc2, 0x86, 0x61, 0x64, 0x7e, 0xda, 0x86, 0x6f, 0x84, 0x38, 0x07, 0xa8, 0x3b, 0x6a, - 0x19, 0xce, 0xa0, 0x50, 0x0f, 0x21, 0xcf, 0x7b, 0x1e, 0x05, 0x98, 0xf8, 0xf0, 0x13, 0x5d, 0x06, 0xce, 0x6e, 0xeb, - 0xc8, 0x2c, 0x6d, 0x06, 0x74, 0x9b, 0xf7, 0x2b, 0x42, 0x25, 0x25, 0xc3, 0x9b, 0xe0, 0x78, 0x1b, 0x02, 0xa3, 0x42, - 0x0b, 0x64, 0x7a, 0xd9, 0xe6, 0x56, 0x2f, 0x64, 0x41, 0x51, 0x2f, 0xed, 0xcd, 0x48, 0x0e, 0x48, 0x45, 0x28, 0x30, - 0xca, 0xba, 0xa1, 0xe8, 0x8c, 0x5f, 0xc0, 0x4f, 0xe6, 0xaa, 0x9c, 0xf2, 0x38, 0x06, 0x94, 0x29, 0x46, 0x04, 0x44, - 0x6b, 0x2f, 0x75, 0x67, 0xf2, 0xa6, 0xce, 0x85, 0xf4, 0x82, 0x8f, 0xe3, 0x73, 0x51, 0x86, 0xab, 0x78, 0xa0, 0x4b, - 0xc4, 0x5b, 0xbe, 0xcf, 0xe6, 0x5b, 0x2a, 0x29, 0x29, 0x36, 0xb5, 0x71, 0x88, 0xf1, 0xd4, 0x7e, 0x8a, 0x8b, 0x39, - 0x6a, 0x77, 0x51, 0xd9, 0x58, 0x48, 0xe7, 0xf9, 0x4a, 0x32, 0x73, 0xd4, 0x36, 0x16, 0x55, 0x1f, 0x7a, 0x29, 0x46, - 0xdd, 0x18, 0xb8, 0x22, 0xee, 0x09, 0x3e, 0xaa, 0xa4, 0xe9, 0x46, 0xe6, 0x39, 0xd7, 0x00, 0xef, 0xe6, 0x67, 0x1a, - 0xec, 0x0c, 0xef, 0x8c, 0x65, 0x52, 0xd6, 0xd1, 0x24, 0x5a, 0xa8, 0x6a, 0x42, 0x17, 0x39, 0x32, 0xd6, 0x7e, 0x36, - 0xb6, 0x9f, 0xe2, 0x99, 0xdc, 0x6e, 0x87, 0xe6, 0x9a, 0xd2, 0xb0, 0x9a, 0x14, 0x51, 0x30, 0xe8, 0xb5, 0xad, 0xf6, - 0xb6, 0x5c, 0x63, 0x22, 0x78, 0xba, 0xa0, 0x67, 0xd4, 0x00, 0x0c, 0x61, 0xa4, 0xb2, 0x37, 0x93, 0x82, 0x29, 0x95, - 0xaa, 0x60, 0xd7, 0x6d, 0x0a, 0xa5, 0x61, 0x32, 0x65, 0x6d, 0x89, 0x55, 0xc0, 0x00, 0x4b, 0xaf, 0x1e, 0x6f, 0xbf, - 0x55, 0x8d, 0x0a, 0xe0, 0x5a, 0x15, 0xee, 0x4c, 0xd4, 0x98, 0x88, 0x77, 0x7c, 0x69, 0xab, 0xa5, 0x46, 0x57, 0x66, - 0x00, 0x15, 0x73, 0x97, 0x8e, 0xa7, 0x72, 0xc5, 0x2c, 0x5c, 0x77, 0x4b, 0x9b, 0xea, 0x3d, 0x8b, 0xd1, 0x7a, 0x62, - 0x3e, 0x8f, 0xf3, 0x08, 0x0a, 0x70, 0x47, 0xd2, 0xf3, 0x73, 0xd8, 0x6f, 0x58, 0x06, 0x5e, 0x00, 0xb2, 0x68, 0xce, - 0xbd, 0x61, 0xb4, 0x0d, 0x1b, 0xb4, 0xa6, 0x4e, 0xb4, 0x2d, 0x6a, 0x3d, 0x86, 0xe5, 0x02, 0x68, 0x0e, 0x53, 0x6d, - 0x54, 0x7a, 0x1c, 0xed, 0x18, 0x95, 0x66, 0xe9, 0x32, 0x6b, 0x54, 0xd9, 0x7e, 0x1c, 0xed, 0x8a, 0x3a, 0x5b, 0x3b, - 0xa5, 0x1b, 0xc2, 0x6e, 0xd4, 0xab, 0x3c, 0x7d, 0xbc, 0xa3, 0xea, 0x6c, 0x43, 0x3b, 0x97, 0x51, 0xf4, 0x59, 0x57, - 0x1a, 0x8a, 0xae, 0x06, 0x3b, 0x4f, 0x55, 0x2d, 0x68, 0x08, 0xde, 0xc1, 0xa1, 0xac, 0x37, 0xb5, 0xf5, 0x78, 0xeb, - 0x69, 0xf4, 0x58, 0x4e, 0x6f, 0xab, 0x74, 0xff, 0xb1, 0x84, 0xe3, 0x17, 0x65, 0x8d, 0xe6, 0x9e, 0x3c, 0x7d, 0xba, - 0xa3, 0x2a, 0x42, 0x73, 0xd7, 0x70, 0x83, 0x9a, 0x63, 0x1f, 0xee, 0xee, 0x44, 0x4f, 0xca, 0xd2, 0xfd, 0xd9, 0x37, - 0x93, 0xa3, 0x3e, 0x8b, 0x0d, 0x3d, 0xfc, 0x3c, 0xad, 0x46, 0x0d, 0xe8, 0x19, 0xd1, 0x00, 0x66, 0xa9, 0x52, 0xd3, - 0xac, 0xf1, 0xca, 0x45, 0xb7, 0xef, 0xe3, 0x20, 0x0c, 0x16, 0x88, 0x08, 0x56, 0x64, 0x9c, 0x95, 0x21, 0xa5, 0x8a, - 0xb4, 0x27, 0xd0, 0x57, 0x71, 0x9e, 0xfe, 0x0c, 0x8b, 0x81, 0x8b, 0x46, 0x21, 0x6d, 0x38, 0x33, 0xd0, 0xfb, 0x85, - 0xc8, 0x6c, 0x44, 0xfe, 0x9b, 0xd5, 0x3c, 0x38, 0x66, 0x18, 0xbd, 0x87, 0x0f, 0xed, 0xcc, 0x4f, 0xec, 0x0c, 0x80, - 0xf7, 0xaf, 0xf0, 0x2f, 0x10, 0x0b, 0x99, 0x6f, 0xd4, 0x93, 0xbe, 0xe7, 0xc2, 0x28, 0xcc, 0x46, 0xd1, 0x9d, 0xa7, - 0x7e, 0x90, 0xea, 0xd1, 0x74, 0xe8, 0xc6, 0x7c, 0x59, 0xd0, 0x00, 0x59, 0xd5, 0xe0, 0x0e, 0x61, 0xf3, 0x6f, 0x23, - 0x3b, 0x45, 0x9f, 0x78, 0x0c, 0x1f, 0x3d, 0x70, 0xc6, 0x11, 0xb3, 0xb5, 0xef, 0xa7, 0xd0, 0x96, 0x25, 0xc6, 0x8e, - 0x49, 0x07, 0x3c, 0xf3, 0x05, 0x7a, 0x0a, 0x74, 0xcd, 0xb0, 0xb0, 0xcb, 0x96, 0x78, 0x3e, 0x3f, 0x4b, 0xd2, 0x51, - 0xa7, 0x1f, 0xfd, 0x59, 0xb9, 0xb0, 0xc3, 0xf2, 0xa7, 0x7b, 0x39, 0x50, 0x56, 0xdd, 0x6e, 0xaa, 0xf3, 0xb8, 0x3d, - 0x8b, 0x0f, 0x7f, 0x3e, 0x4c, 0x8f, 0x8e, 0x48, 0xf7, 0x4d, 0xfb, 0x3a, 0x16, 0x7f, 0x3d, 0xe1, 0x7c, 0xf0, 0xf6, - 0xd9, 0x5f, 0x8f, 0x0f, 0x9e, 0xbd, 0x42, 0xe7, 0x83, 0x4f, 0x2f, 0xbf, 0x7d, 0xf9, 0x91, 0x93, 0xbb, 0xf3, 0x9e, - 0x3f, 0x7c, 0xa8, 0xa5, 0x3e, 0x76, 0x04, 0x6c, 0xef, 0xa6, 0x1d, 0x3c, 0xca, 0xd8, 0xe8, 0xc1, 0xd9, 0xf3, 0x55, - 0x28, 0x64, 0xec, 0xa2, 0x54, 0xcf, 0x30, 0x08, 0x23, 0x98, 0xc5, 0x55, 0x45, 0x84, 0x6b, 0x8e, 0x5c, 0x25, 0x59, - 0x4b, 0xf7, 0x8d, 0x79, 0x00, 0x31, 0x9a, 0x6a, 0xb2, 0x30, 0xf3, 0xb1, 0x6d, 0x1c, 0x13, 0xcc, 0x24, 0x3b, 0x52, - 0xe3, 0xd2, 0x07, 0x04, 0x08, 0x90, 0xe9, 0xd4, 0xe6, 0xd0, 0xd5, 0xfb, 0xa8, 0x01, 0x90, 0x83, 0xca, 0xf4, 0x88, - 0xa2, 0xb1, 0xd9, 0xbe, 0x37, 0x30, 0x86, 0x77, 0x41, 0xba, 0x27, 0x39, 0xac, 0xa2, 0xb2, 0xa0, 0xdd, 0x21, 0x10, - 0x3f, 0x6a, 0xd1, 0x65, 0x32, 0x19, 0x1e, 0xcb, 0xcf, 0xc0, 0x4f, 0xc9, 0xe1, 0xe8, 0x65, 0x28, 0x8c, 0x96, 0xa7, - 0xca, 0x56, 0x97, 0x73, 0x38, 0xc5, 0x94, 0xf6, 0x68, 0x40, 0x22, 0xf5, 0x4e, 0xd3, 0x3b, 0x7e, 0x35, 0x4f, 0x31, - 0x9b, 0x62, 0x8c, 0xd2, 0xf9, 0x67, 0x09, 0x3b, 0x97, 0xa7, 0xc0, 0x6b, 0x27, 0x47, 0xfb, 0xe8, 0x76, 0x0e, 0x7f, - 0x3d, 0x4a, 0xca, 0x17, 0x63, 0xae, 0x12, 0xb4, 0x7b, 0xd1, 0x21, 0x7c, 0x5b, 0x43, 0x1b, 0xa8, 0x0b, 0x94, 0xfa, - 0xdd, 0x5c, 0x9d, 0x34, 0x8a, 0x72, 0xc7, 0x1e, 0x6d, 0x98, 0x79, 0xc8, 0x2f, 0x0e, 0x8b, 0xba, 0x27, 0x9b, 0x64, - 0x4c, 0xe8, 0x94, 0x05, 0x7e, 0x3a, 0x0a, 0xf6, 0xfc, 0x6c, 0x14, 0x60, 0x2b, 0x80, 0x08, 0x80, 0x7a, 0x1a, 0xc2, - 0xa7, 0xce, 0x04, 0x86, 0x16, 0x1c, 0xb9, 0x13, 0x92, 0x12, 0xd8, 0x98, 0xf2, 0xa3, 0x4f, 0xb6, 0x39, 0x78, 0xe4, - 0xd5, 0xf5, 0x33, 0xf4, 0x73, 0x0d, 0xc3, 0x65, 0x52, 0x84, 0xae, 0xc8, 0x59, 0xc3, 0xe4, 0x88, 0x80, 0x75, 0xa7, - 0x8e, 0x31, 0x09, 0x78, 0x46, 0x59, 0x09, 0x33, 0x27, 0x80, 0x61, 0x66, 0x50, 0x1d, 0x3a, 0xf4, 0x33, 0xb7, 0x6a, - 0x73, 0x1a, 0x08, 0x93, 0xa0, 0x0d, 0x1d, 0x4b, 0xad, 0x93, 0xb2, 0x0a, 0x71, 0x23, 0x1a, 0x27, 0xde, 0xa5, 0x30, - 0x34, 0xc0, 0x28, 0x50, 0x2c, 0x17, 0xbf, 0xbc, 0xbf, 0x87, 0x1b, 0x87, 0xfe, 0xf7, 0x57, 0x32, 0xdb, 0xd9, 0x9c, - 0x91, 0x1e, 0x3c, 0x01, 0x92, 0xc1, 0x54, 0x6c, 0x32, 0x02, 0x79, 0x12, 0x17, 0x98, 0xd1, 0xe2, 0xda, 0x92, 0x29, - 0xe1, 0x70, 0x4c, 0x3f, 0x62, 0x69, 0x45, 0x4c, 0xce, 0x9e, 0x18, 0x34, 0x6d, 0x2e, 0x48, 0x10, 0xa5, 0xcf, 0xe1, - 0x3a, 0x55, 0x62, 0xac, 0x09, 0x68, 0x26, 0xf3, 0x6d, 0x70, 0x44, 0x83, 0x5a, 0x88, 0x66, 0xf4, 0xfe, 0x39, 0x8f, - 0x88, 0xd5, 0xc1, 0x07, 0x7c, 0xa7, 0xf3, 0xcc, 0xf3, 0xce, 0x53, 0xe4, 0xd4, 0x67, 0x73, 0x8a, 0x7e, 0x09, 0x44, - 0x67, 0x5f, 0x14, 0x53, 0xae, 0xa4, 0x08, 0xf5, 0x36, 0xd4, 0x30, 0x90, 0x9e, 0x8b, 0xc8, 0x56, 0x74, 0xfc, 0x2b, - 0x22, 0x32, 0x72, 0x57, 0x5a, 0xd1, 0xe5, 0x2a, 0x46, 0x9c, 0x31, 0x30, 0x05, 0x93, 0x19, 0x2e, 0x66, 0x02, 0x34, - 0x27, 0x6c, 0x1a, 0x60, 0x02, 0xe8, 0xa4, 0xaf, 0x7f, 0x00, 0x56, 0x35, 0x23, 0x34, 0x34, 0x97, 0x20, 0xea, 0xeb, - 0x1f, 0x2d, 0xfe, 0x7f, 0x86, 0x5d, 0x20, 0xc1, 0xde, 0x99, 0xcc, 0x8c, 0xe7, 0x94, 0x95, 0x38, 0x28, 0xd2, 0xc7, - 0xbe, 0x5a, 0x78, 0xcf, 0x1d, 0xbd, 0x4d, 0x2a, 0xdf, 0xe2, 0x83, 0x65, 0xae, 0xb7, 0x2b, 0x77, 0xa5, 0x8f, 0xe7, - 0xe1, 0xe6, 0x86, 0x0e, 0x44, 0xdd, 0x05, 0xd0, 0x35, 0x8c, 0x57, 0x33, 0xd3, 0x78, 0x35, 0x58, 0x63, 0xbc, 0xaa, - 0xad, 0xb0, 0xec, 0xb9, 0xb3, 0x22, 0x7d, 0x16, 0xcb, 0xf3, 0xe7, 0x24, 0x13, 0xac, 0xba, 0x9c, 0xe5, 0x2e, 0x97, - 0x3a, 0xee, 0x46, 0x60, 0x56, 0x04, 0x6e, 0x93, 0xf2, 0xac, 0xe8, 0x18, 0x09, 0x2e, 0x97, 0x3a, 0xa5, 0xbd, 0x91, - 0xa1, 0x7a, 0x0c, 0xdf, 0xcb, 0x18, 0xa2, 0x52, 0xc6, 0x2e, 0xc7, 0xe0, 0xb8, 0xb6, 0xb4, 0x1e, 0xdd, 0x50, 0xd6, - 0xa3, 0x37, 0x37, 0x85, 0xf4, 0xb7, 0x03, 0x0a, 0x67, 0x42, 0x51, 0x85, 0x79, 0x35, 0x31, 0xbc, 0xe9, 0x44, 0x71, - 0x4b, 0x5a, 0x69, 0x41, 0xe9, 0xb3, 0x7f, 0xb5, 0x73, 0xad, 0x92, 0xc8, 0x9d, 0x71, 0xee, 0x75, 0x35, 0x1e, 0x84, - 0x25, 0xc7, 0x33, 0x80, 0x99, 0x1c, 0xc9, 0xc3, 0xf5, 0x57, 0x40, 0xa4, 0xaa, 0x72, 0xea, 0x8c, 0x53, 0xac, 0x0c, - 0x37, 0xb7, 0x5e, 0xb5, 0x3b, 0xd4, 0x26, 0xb5, 0xc6, 0x5a, 0xa4, 0x3d, 0x19, 0xf9, 0x01, 0x95, 0x21, 0x3a, 0x3e, - 0x39, 0x54, 0x4f, 0x39, 0x95, 0x6a, 0x65, 0x9a, 0xed, 0x81, 0x57, 0x3e, 0xc1, 0x86, 0xc2, 0xf8, 0xce, 0x17, 0xd2, - 0x92, 0x38, 0xf2, 0xd7, 0xb9, 0xed, 0xc1, 0x01, 0x10, 0xaf, 0xde, 0xbd, 0xfc, 0xf6, 0x59, 0xe5, 0x55, 0x33, 0xe2, - 0xa8, 0x8d, 0xb6, 0x15, 0x03, 0xca, 0xde, 0x62, 0xc2, 0x60, 0x87, 0x5d, 0x23, 0xc8, 0xbb, 0x14, 0xf5, 0xdb, 0xf7, - 0xf5, 0x04, 0x3c, 0x8f, 0xc4, 0xf1, 0x83, 0x9a, 0x2e, 0x05, 0x8d, 0xa5, 0x5d, 0xf1, 0xf5, 0xae, 0x8c, 0xd7, 0x4e, - 0xcb, 0x93, 0xdb, 0xce, 0x1a, 0x19, 0xcc, 0x57, 0xdb, 0x62, 0x2c, 0x9c, 0xeb, 0xa1, 0xab, 0xc5, 0x16, 0xe0, 0x8f, - 0x2d, 0x91, 0x6f, 0x6e, 0x72, 0x9c, 0x90, 0x5a, 0x70, 0xe3, 0x65, 0x70, 0x85, 0x2f, 0x73, 0x63, 0x9a, 0xca, 0xf4, - 0x5a, 0xb6, 0x25, 0x45, 0x65, 0x68, 0x59, 0x1c, 0xf8, 0xf1, 0xc4, 0xe6, 0xdc, 0x5c, 0x15, 0x91, 0x37, 0x03, 0x5a, - 0x79, 0xbf, 0x00, 0x68, 0xa1, 0xdd, 0xc9, 0xc1, 0xe7, 0x78, 0x31, 0x5e, 0x62, 0xd4, 0x7c, 0x68, 0x05, 0x61, 0xae, - 0x3a, 0x0b, 0x6a, 0x28, 0x6e, 0xf5, 0x5c, 0x3f, 0x0f, 0x16, 0xc1, 0x04, 0x55, 0x37, 0xe8, 0x2d, 0x72, 0x25, 0x44, - 0x57, 0x32, 0xba, 0xa8, 0x7b, 0x4b, 0x3b, 0x0a, 0x14, 0x6a, 0xf8, 0xbe, 0x91, 0x30, 0xde, 0x93, 0x01, 0x97, 0x44, - 0xd4, 0x3c, 0x1e, 0x29, 0xac, 0x1e, 0x92, 0xd0, 0xd6, 0x98, 0xc1, 0x96, 0x77, 0x21, 0x63, 0x52, 0xe0, 0x5b, 0x19, - 0xf8, 0x03, 0x1e, 0x99, 0x57, 0xcc, 0xed, 0xdc, 0xb0, 0xbf, 0x7e, 0xf8, 0x30, 0x30, 0xec, 0xaf, 0x17, 0x02, 0xd6, - 0x05, 0xf5, 0x01, 0x38, 0x25, 0x25, 0x10, 0x79, 0x26, 0x16, 0x42, 0x66, 0x14, 0xab, 0xfa, 0xfe, 0x3d, 0x93, 0x55, - 0x38, 0x08, 0x7d, 0xa3, 0x5f, 0x43, 0x4a, 0x82, 0x3a, 0xb5, 0xc2, 0xdf, 0xef, 0x0a, 0xb3, 0x0f, 0x4c, 0x88, 0x6a, - 0x56, 0x04, 0xb4, 0xcd, 0xce, 0xc5, 0x9c, 0x3e, 0x1c, 0x58, 0x02, 0x37, 0x1d, 0xb5, 0xf4, 0xa8, 0xbd, 0x0d, 0x09, - 0x40, 0x29, 0xa1, 0x88, 0x32, 0x2f, 0x16, 0x92, 0x10, 0x38, 0x30, 0x24, 0xb8, 0xd2, 0x81, 0x5d, 0x23, 0x7f, 0xd8, - 0xcb, 0xbd, 0xc8, 0xb7, 0xd7, 0x7f, 0x03, 0xc7, 0x87, 0x34, 0x57, 0x66, 0x22, 0xc7, 0x46, 0xa5, 0xca, 0x9d, 0xaa, - 0xf4, 0x90, 0xf8, 0x40, 0x69, 0xf9, 0x76, 0xda, 0xbb, 0xc7, 0xc7, 0x5b, 0x47, 0x0e, 0xaa, 0xc8, 0x94, 0x59, 0x88, - 0x7c, 0xb1, 0xb7, 0x8d, 0x51, 0x63, 0xfa, 0x5b, 0xbb, 0x23, 0x60, 0x56, 0x30, 0x21, 0xfa, 0x00, 0x65, 0xb4, 0x09, - 0x3e, 0x27, 0xfc, 0x5c, 0xc3, 0xf8, 0x66, 0xe8, 0xd7, 0xc4, 0x9d, 0x06, 0x48, 0x70, 0x78, 0xc3, 0x4d, 0x3b, 0xea, - 0x0e, 0xbb, 0xa8, 0x2d, 0x31, 0x6e, 0x5f, 0x4d, 0x2b, 0x2e, 0xb1, 0x4b, 0xab, 0xfb, 0xa7, 0x5b, 0x0d, 0x92, 0x08, - 0x2b, 0x92, 0x33, 0x30, 0xc0, 0x54, 0x96, 0x7c, 0x4d, 0x96, 0x68, 0x59, 0x21, 0x8f, 0x74, 0x24, 0xa3, 0x24, 0x36, - 0x2f, 0x43, 0x44, 0x59, 0xb3, 0x9e, 0xd9, 0x79, 0xcd, 0x8d, 0x1a, 0xc3, 0xe7, 0x4c, 0xfc, 0x4c, 0x71, 0x38, 0xe3, - 0xd4, 0xc0, 0xe9, 0xc8, 0x3a, 0xce, 0xfd, 0xb7, 0x11, 0x05, 0xe3, 0x98, 0x10, 0xc7, 0xe3, 0xce, 0x7c, 0x11, 0x2a, - 0x12, 0x30, 0x3a, 0x9a, 0xf6, 0x20, 0xf5, 0x3e, 0x47, 0xe3, 0x30, 0xbf, 0x5b, 0x28, 0x50, 0x1f, 0x1a, 0xbc, 0x10, - 0x0a, 0xd2, 0x6a, 0x2f, 0xe7, 0x63, 0xc2, 0x9e, 0x1e, 0xc9, 0xfe, 0x88, 0xc2, 0x4f, 0xd0, 0x8e, 0xc2, 0xd9, 0x1f, - 0x46, 0xbb, 0x8f, 0x9a, 0x89, 0xaa, 0xa2, 0xae, 0xd5, 0x09, 0x92, 0xb0, 0x63, 0x75, 0x13, 0x7c, 0xca, 0xa2, 0x4e, - 0x91, 0xa6, 0x9d, 0x69, 0x90, 0x75, 0x60, 0x76, 0x59, 0x01, 0x34, 0x5f, 0x31, 0xeb, 0xc8, 0x09, 0x61, 0x68, 0x5e, - 0xab, 0x1b, 0x40, 0x45, 0x0b, 0x88, 0x4b, 0xb1, 0xb5, 0x0b, 0x3f, 0xaf, 0xa0, 0x33, 0x99, 0xa2, 0xcc, 0xaa, 0x26, - 0x08, 0xab, 0x60, 0x03, 0xa4, 0x53, 0x97, 0x7e, 0xe8, 0x4e, 0x29, 0xdd, 0x40, 0x32, 0x5a, 0xe2, 0x1c, 0x90, 0x46, - 0x5e, 0xc2, 0x3d, 0x85, 0x91, 0x4f, 0xbb, 0x5d, 0x67, 0x8a, 0x99, 0x0b, 0x96, 0xae, 0x4a, 0xe2, 0x00, 0x1f, 0x90, - 0x9d, 0x76, 0x33, 0x30, 0xd3, 0xcd, 0x0d, 0x46, 0x54, 0x1e, 0x02, 0xc2, 0x53, 0xdf, 0xb8, 0x26, 0x83, 0x3d, 0x43, - 0xfb, 0xab, 0xac, 0xb0, 0xe7, 0x29, 0x6b, 0xbe, 0xcf, 0xe0, 0x96, 0x72, 0xc6, 0xe1, 0x86, 0x23, 0x45, 0x3d, 0x2a, - 0x97, 0x22, 0x4f, 0xcc, 0x8b, 0x8a, 0xc7, 0x44, 0xfb, 0x71, 0xc1, 0x7a, 0xcd, 0x8b, 0x78, 0xc1, 0xe4, 0xdf, 0x38, - 0x12, 0xd4, 0x1f, 0x5a, 0x7f, 0x56, 0x5f, 0x21, 0xdb, 0x6a, 0xbc, 0xab, 0x52, 0x8d, 0x44, 0x59, 0x62, 0xbb, 0xc0, - 0xc8, 0xca, 0x3a, 0x51, 0x4d, 0xdf, 0x67, 0x76, 0x5f, 0x27, 0x3a, 0xa5, 0xcf, 0x2a, 0x1e, 0x5c, 0xcc, 0x56, 0x84, - 0x48, 0x23, 0x3d, 0xaa, 0xa2, 0x00, 0xc9, 0xf6, 0xa9, 0x0e, 0x80, 0x6b, 0x3e, 0x2e, 0xc8, 0xbb, 0x15, 0x0b, 0x5e, - 0x09, 0x72, 0xe9, 0xf6, 0x40, 0xca, 0x74, 0x3d, 0x84, 0x84, 0x49, 0xc8, 0x8b, 0x88, 0xef, 0x95, 0x9c, 0xdc, 0x6b, - 0x9b, 0xb2, 0x17, 0x19, 0x76, 0x02, 0xd2, 0xba, 0x2b, 0x6d, 0x1d, 0xf8, 0xc4, 0x1c, 0xf8, 0xdc, 0xaf, 0xc1, 0x68, - 0xb8, 0x11, 0x13, 0x00, 0xe7, 0x68, 0xe2, 0x1d, 0xfa, 0x73, 0x7c, 0x9a, 0x1f, 0xb9, 0x4b, 0x1f, 0x63, 0x8a, 0xc1, - 0xd9, 0x81, 0x82, 0x90, 0x22, 0x91, 0x2c, 0x19, 0x93, 0xdc, 0x31, 0x5d, 0x0c, 0x8c, 0x3e, 0x1d, 0x87, 0xde, 0x6c, - 0xad, 0x99, 0x05, 0x81, 0x67, 0x9c, 0xbb, 0x48, 0xb6, 0x37, 0x30, 0x83, 0x94, 0x47, 0x70, 0x4e, 0xbb, 0xdd, 0xc8, - 0x11, 0xe1, 0xc6, 0x73, 0x16, 0xd7, 0x8a, 0x11, 0xb7, 0x2c, 0x63, 0x2e, 0xb8, 0x45, 0x4a, 0x0e, 0xd8, 0x06, 0x2b, - 0xdb, 0x7d, 0x80, 0x4d, 0xe5, 0x78, 0x9b, 0x2a, 0xbb, 0xd5, 0x63, 0xa6, 0x7a, 0x6c, 0x05, 0xe8, 0x74, 0x93, 0xf5, - 0x40, 0xbe, 0x4a, 0x1d, 0xb4, 0xb9, 0x1c, 0x0b, 0xda, 0xb2, 0x8b, 0x2a, 0xfa, 0x3e, 0x43, 0xdd, 0x7b, 0x38, 0xc2, - 0xdc, 0xda, 0xb7, 0xfc, 0x64, 0x53, 0x36, 0xd8, 0x23, 0x9a, 0xb4, 0x32, 0x14, 0xd4, 0xbd, 0x27, 0x8f, 0xda, 0xe6, - 0xad, 0xe0, 0x2e, 0x42, 0xa2, 0x46, 0xc7, 0x15, 0x3f, 0x26, 0x57, 0xeb, 0x4c, 0x2b, 0x42, 0xff, 0x42, 0x8a, 0xfb, - 0x73, 0xe9, 0x2a, 0x5e, 0xf5, 0x2e, 0x87, 0xdb, 0x0b, 0x7d, 0xb6, 0x87, 0x50, 0x40, 0xaa, 0xda, 0xd0, 0xa9, 0x4b, - 0x43, 0x7a, 0x56, 0xa2, 0xab, 0xe4, 0x60, 0x6b, 0x7d, 0xc6, 0x49, 0xf4, 0x23, 0xd5, 0xc8, 0x97, 0x5e, 0xf2, 0x28, - 0xed, 0x06, 0x8f, 0x32, 0x77, 0x06, 0x4f, 0x19, 0x3c, 0xa5, 0x65, 0xd9, 0xc4, 0x2b, 0xeb, 0xe7, 0x48, 0x34, 0x6b, - 0xe3, 0x2e, 0xe5, 0x78, 0x31, 0x08, 0x77, 0x1d, 0x61, 0x3a, 0x05, 0x43, 0x64, 0xab, 0xe0, 0x43, 0xeb, 0x75, 0x1f, - 0x28, 0x22, 0x09, 0x93, 0x9e, 0xd7, 0xc9, 0x24, 0x97, 0x26, 0x5b, 0x45, 0x7d, 0xb4, 0x05, 0x29, 0x4e, 0xbb, 0x6e, - 0xd6, 0x55, 0x5b, 0x50, 0x2a, 0xa3, 0x35, 0xdf, 0xcc, 0xfa, 0x97, 0xa6, 0xbb, 0x3e, 0xfc, 0x9e, 0x39, 0xbd, 0xa1, - 0xdc, 0xfc, 0x60, 0x7f, 0x30, 0x0e, 0xbc, 0x61, 0xd9, 0x82, 0x2d, 0x44, 0xfc, 0x53, 0x83, 0x0b, 0xa5, 0xc0, 0xa9, - 0x94, 0xc1, 0x11, 0xd6, 0x81, 0x9d, 0x94, 0x2a, 0x31, 0xfc, 0x3b, 0x45, 0x43, 0x9b, 0x06, 0xe3, 0x9c, 0xcc, 0xe2, - 0xe4, 0x4c, 0xa4, 0x0f, 0x17, 0xd9, 0xc5, 0x55, 0x42, 0x3b, 0x83, 0x99, 0xd6, 0xf4, 0xba, 0x53, 0x81, 0x27, 0xba, - 0x67, 0x1f, 0xa9, 0x75, 0x33, 0x43, 0x33, 0x26, 0x46, 0x9b, 0xcf, 0x3f, 0x50, 0xcc, 0xed, 0x9f, 0xd8, 0xe6, 0x97, - 0x61, 0x9f, 0x06, 0x23, 0x79, 0x1d, 0x8c, 0x14, 0x68, 0x84, 0x99, 0x26, 0x13, 0x00, 0x4d, 0x98, 0xc8, 0xfe, 0x3e, - 0xcd, 0xd5, 0x48, 0x7a, 0x63, 0x40, 0x54, 0xa0, 0xa6, 0x20, 0xfc, 0xea, 0x1a, 0xdc, 0x4a, 0x8d, 0x3c, 0xe2, 0xef, - 0xe7, 0xda, 0x76, 0x45, 0x80, 0xbf, 0xfb, 0x2d, 0x68, 0x25, 0x10, 0xe5, 0xba, 0x39, 0xb2, 0xc0, 0x49, 0x8a, 0x1b, - 0x72, 0xca, 0x5e, 0xd0, 0x36, 0x89, 0xb9, 0x61, 0xa7, 0x66, 0x6c, 0xc5, 0x98, 0xf3, 0xca, 0x57, 0x67, 0x66, 0xfe, - 0x90, 0x10, 0x34, 0x47, 0x03, 0x6f, 0x89, 0xe3, 0xc9, 0x81, 0xee, 0x52, 0xea, 0xb4, 0xf0, 0xb2, 0x90, 0x2e, 0xeb, - 0xb2, 0x1e, 0x0f, 0x9a, 0xe2, 0xa0, 0x30, 0xa9, 0xe2, 0x4a, 0x09, 0x8f, 0x87, 0x02, 0x26, 0xf8, 0xc2, 0x93, 0x82, - 0x1a, 0xa0, 0xd2, 0xf0, 0x42, 0xe1, 0x5f, 0x16, 0xd5, 0xc0, 0x43, 0x95, 0x88, 0x13, 0x04, 0x22, 0x9a, 0x11, 0xab, - 0xfb, 0x66, 0xb9, 0xd5, 0xab, 0x09, 0xcd, 0x96, 0x4a, 0x5b, 0x45, 0x54, 0x92, 0xc7, 0x96, 0xff, 0x5a, 0x4d, 0x85, - 0x2d, 0xd5, 0x5c, 0xf4, 0x86, 0x55, 0x17, 0xbd, 0x28, 0x96, 0x92, 0x40, 0x76, 0xcb, 0x1d, 0x90, 0x3f, 0x84, 0x0a, - 0x3c, 0x22, 0xf3, 0xc4, 0xa2, 0xb9, 0xd5, 0xbe, 0x1f, 0x1f, 0x26, 0x47, 0xfd, 0x45, 0x8a, 0x69, 0x83, 0xf7, 0xe0, - 0x47, 0x2e, 0x7e, 0xd8, 0xa6, 0xb0, 0xf4, 0x3d, 0xda, 0xc5, 0x5a, 0x50, 0x6e, 0xa1, 0xef, 0x85, 0xbb, 0x82, 0x27, - 0x2f, 0xe5, 0xe9, 0x07, 0x25, 0xb5, 0xc0, 0x65, 0x19, 0x97, 0x4d, 0x4a, 0x6a, 0x08, 0x7d, 0x55, 0x45, 0xfb, 0x58, - 0xac, 0x3b, 0xe0, 0x5f, 0x2d, 0x3d, 0xd0, 0x16, 0x70, 0x17, 0xd4, 0x50, 0x8a, 0x2a, 0x43, 0xdd, 0x05, 0x95, 0x65, - 0x54, 0x26, 0xbb, 0x50, 0x6a, 0xe4, 0xac, 0x97, 0xca, 0xf3, 0x32, 0x1f, 0x07, 0x5d, 0x7b, 0xd2, 0x0b, 0x9c, 0x47, - 0x14, 0x6a, 0x7f, 0x73, 0x0e, 0x2d, 0xb0, 0x5c, 0xf2, 0x4c, 0xfb, 0xc5, 0x5f, 0xde, 0x61, 0xaf, 0x7b, 0x4c, 0xc9, - 0x02, 0xb4, 0xa5, 0x2d, 0x6c, 0xde, 0x87, 0xb4, 0x96, 0x1c, 0x87, 0xaa, 0xb0, 0xc3, 0xaa, 0x21, 0x47, 0x94, 0x8c, - 0x5c, 0xfd, 0x16, 0x51, 0xe4, 0x20, 0x79, 0xc7, 0x30, 0x76, 0x23, 0x7e, 0x6d, 0x2b, 0x9b, 0x5b, 0xd1, 0x21, 0x3d, - 0x93, 0x44, 0xe2, 0x4d, 0x9a, 0x7e, 0x5e, 0x2e, 0xb8, 0x56, 0x21, 0xe3, 0xb1, 0x8a, 0x61, 0x44, 0xb1, 0xf0, 0x3d, - 0x16, 0xfe, 0xad, 0xf5, 0xe1, 0x18, 0xef, 0xd1, 0x83, 0xd6, 0xfc, 0xd6, 0x90, 0x10, 0x2a, 0x96, 0xd3, 0x29, 0x5b, - 0x7a, 0x34, 0xcc, 0x64, 0xa5, 0xa8, 0xc4, 0xe7, 0xdb, 0xc9, 0x8e, 0x81, 0x02, 0x0e, 0xd0, 0x59, 0x72, 0x65, 0xd2, - 0x93, 0x0c, 0x0e, 0x5b, 0x60, 0xe4, 0x6b, 0xd9, 0x0b, 0x48, 0xbc, 0x3c, 0x67, 0xf1, 0xf2, 0x7c, 0xdf, 0x8f, 0x30, - 0xb4, 0x16, 0x46, 0xaa, 0x17, 0x61, 0x3f, 0xe7, 0x1c, 0x16, 0x58, 0xf2, 0x7c, 0x5b, 0x2a, 0x90, 0x21, 0x6d, 0x76, - 0x44, 0x9b, 0x3d, 0x28, 0xc5, 0xde, 0x27, 0xf4, 0x73, 0x58, 0x1e, 0x19, 0x7d, 0xe5, 0xf5, 0xbe, 0x66, 0x00, 0x75, - 0xb3, 0xee, 0x10, 0x93, 0xb2, 0xc0, 0x03, 0xf0, 0xa6, 0x40, 0x2d, 0xe6, 0xd8, 0xbb, 0x19, 0x8a, 0x61, 0xd6, 0x9d, - 0x20, 0xd3, 0xb9, 0xe1, 0x23, 0x6d, 0x98, 0x0a, 0x71, 0x37, 0xf5, 0x31, 0xa7, 0x3e, 0xb2, 0x4d, 0x3b, 0xc0, 0xb8, - 0xb2, 0x5a, 0xe0, 0xbd, 0x9e, 0x7d, 0xac, 0x06, 0x64, 0x15, 0xae, 0xf0, 0xbc, 0xca, 0x6d, 0x2c, 0x8d, 0x60, 0x52, - 0x36, 0x12, 0x23, 0x79, 0x2a, 0x70, 0x76, 0x1b, 0x32, 0x9c, 0xad, 0x63, 0x44, 0xe2, 0x1d, 0x50, 0xf4, 0x62, 0xb7, - 0x52, 0x39, 0x72, 0x10, 0x67, 0x6b, 0x66, 0x9b, 0xea, 0xd3, 0x04, 0x22, 0xb4, 0x08, 0x22, 0xe0, 0x46, 0x61, 0x98, - 0xfc, 0xfd, 0xbc, 0x27, 0x84, 0x70, 0x6d, 0x07, 0xaf, 0x05, 0x5b, 0x06, 0xe8, 0x22, 0x2d, 0x6c, 0x13, 0xd7, 0xc0, - 0x75, 0xc3, 0x8f, 0xb9, 0x36, 0x31, 0xb7, 0x16, 0xe9, 0xb7, 0x65, 0xd2, 0x1d, 0x1d, 0x03, 0x50, 0xce, 0x60, 0x5c, - 0xd4, 0x71, 0x52, 0x24, 0xb1, 0x5d, 0xe2, 0x38, 0x1e, 0x8a, 0xa2, 0x44, 0x45, 0xdc, 0xfe, 0xc6, 0x70, 0xfd, 0xc2, - 0x2d, 0x6e, 0xa5, 0x99, 0x6d, 0xb8, 0x0a, 0xc6, 0xf5, 0x70, 0x8b, 0xea, 0x6d, 0x90, 0x4e, 0xdc, 0xfa, 0xee, 0xfc, - 0x6b, 0x49, 0xd7, 0xda, 0x68, 0x92, 0x47, 0xf5, 0xee, 0xbb, 0x95, 0xbb, 0xba, 0xc1, 0x39, 0x60, 0xce, 0x52, 0x03, - 0x47, 0x01, 0xb2, 0x89, 0xa3, 0x9c, 0x30, 0xd5, 0x59, 0xc5, 0xc7, 0xfb, 0x32, 0xee, 0xcb, 0x1f, 0xce, 0x08, 0x23, - 0x9e, 0x7f, 0x0e, 0xa5, 0xfa, 0x38, 0x24, 0x09, 0xf8, 0x07, 0x91, 0xdf, 0xc8, 0x3d, 0x50, 0x2f, 0x60, 0xec, 0xef, - 0x2f, 0x13, 0xf9, 0xe2, 0x85, 0xd2, 0xf9, 0xbb, 0xcf, 0x33, 0x33, 0x74, 0x38, 0x69, 0xef, 0xb0, 0x49, 0xa0, 0x1c, - 0xf7, 0x87, 0x52, 0xd6, 0x96, 0x8c, 0x0f, 0x38, 0x5c, 0x8c, 0x57, 0x90, 0x67, 0x9d, 0xc2, 0x30, 0x19, 0xea, 0x1b, - 0x07, 0xa4, 0x64, 0x84, 0x5b, 0x8a, 0xea, 0x34, 0x16, 0xa2, 0xdb, 0xc9, 0x98, 0xf2, 0x15, 0x63, 0x50, 0x98, 0x8c, - 0x83, 0x28, 0x6a, 0xfb, 0x70, 0x84, 0x09, 0x0f, 0x1f, 0x7e, 0x0e, 0x45, 0x05, 0x37, 0x2f, 0x47, 0x19, 0x8a, 0xea, - 0x30, 0xdb, 0x2a, 0x02, 0xe6, 0xd0, 0xcd, 0x63, 0x77, 0x96, 0xb8, 0x61, 0xe2, 0x4e, 0x62, 0x77, 0x1a, 0xb1, 0xa8, - 0x78, 0x9a, 0xf8, 0x0c, 0xdb, 0x25, 0x60, 0xff, 0xbe, 0x02, 0xd7, 0x6b, 0xb9, 0xd6, 0xc8, 0xee, 0x84, 0x08, 0xa1, - 0xc3, 0x23, 0x91, 0x84, 0x8c, 0x94, 0x93, 0x14, 0x1f, 0x5e, 0xc4, 0x2b, 0xd0, 0xc5, 0x6e, 0xdc, 0x9f, 0x01, 0xf1, - 0x67, 0xa9, 0xaf, 0x2c, 0x15, 0x93, 0x83, 0x8a, 0x0e, 0x96, 0xa7, 0xcf, 0xd3, 0xf3, 0x45, 0x9a, 0x44, 0x49, 0xc1, - 0x21, 0xfa, 0x65, 0xdc, 0x77, 0x99, 0x57, 0xdd, 0xaf, 0xf6, 0xea, 0xde, 0xf6, 0xad, 0x49, 0xda, 0xe8, 0x2f, 0x64, - 0x1c, 0x83, 0xc6, 0x47, 0x8e, 0x0c, 0x69, 0x50, 0x88, 0x11, 0xdb, 0x32, 0x41, 0x97, 0x48, 0x29, 0xa4, 0xc0, 0x54, - 0xcc, 0x2d, 0x70, 0x7e, 0xe3, 0x8f, 0x69, 0x5a, 0xf4, 0xff, 0xb1, 0x8c, 0xb2, 0xeb, 0x83, 0x68, 0x1e, 0xd1, 0x1a, - 0x59, 0x93, 0x20, 0xb9, 0x08, 0xe0, 0x44, 0x99, 0x96, 0x57, 0xd6, 0x56, 0x28, 0xd3, 0xc6, 0x34, 0xba, 0x26, 0xad, - 0x57, 0x46, 0xbe, 0x32, 0xec, 0x1b, 0x43, 0xa9, 0x89, 0x5c, 0x0e, 0x7d, 0x2f, 0xd4, 0x3d, 0xb5, 0x69, 0xa8, 0x80, - 0xf8, 0x87, 0xac, 0x17, 0xaa, 0xbd, 0xae, 0xe6, 0xdc, 0x90, 0x19, 0x82, 0xfa, 0xdb, 0xe5, 0x91, 0x8e, 0x9f, 0xbf, - 0x62, 0x4b, 0x22, 0x7c, 0xb1, 0x0a, 0x97, 0x99, 0xcc, 0xa5, 0xe1, 0x8a, 0x84, 0xb9, 0xd0, 0x73, 0x74, 0x86, 0xa2, - 0x3f, 0x6d, 0x45, 0x04, 0x64, 0x91, 0xcb, 0x11, 0x0c, 0xbd, 0xd5, 0x55, 0xa5, 0xdc, 0xbd, 0x46, 0x2f, 0x37, 0x69, - 0x8d, 0x24, 0x3c, 0x1d, 0x4b, 0x17, 0x98, 0x32, 0x98, 0x61, 0x8e, 0xd9, 0x9d, 0x37, 0x06, 0x80, 0xf3, 0x62, 0x60, - 0x4e, 0xe2, 0xe4, 0x59, 0xbe, 0x80, 0x85, 0xfa, 0x88, 0x1d, 0x0a, 0x63, 0x1c, 0x1a, 0x3d, 0xaf, 0x3a, 0xa7, 0x43, - 0x7e, 0x3d, 0x7d, 0x79, 0xb5, 0x08, 0x60, 0x7d, 0x61, 0xd5, 0xcb, 0x75, 0x2f, 0xaa, 0xdb, 0x01, 0x64, 0x23, 0x2c, - 0xa5, 0xc8, 0x5a, 0x0c, 0x80, 0xcd, 0x8a, 0x44, 0x45, 0x0b, 0x90, 0x09, 0xe5, 0xee, 0x8c, 0x39, 0x97, 0x21, 0x1c, - 0xee, 0x37, 0x70, 0x05, 0x88, 0xee, 0x0f, 0x28, 0x09, 0xbb, 0x33, 0x96, 0x41, 0x40, 0xa0, 0x0b, 0xe9, 0x89, 0x63, - 0x6d, 0xed, 0x0c, 0x16, 0x57, 0x96, 0x6b, 0xbc, 0x49, 0x99, 0x3d, 0xf4, 0xad, 0x41, 0x7f, 0xd7, 0xd2, 0x91, 0x43, - 0xcc, 0x8f, 0x76, 0xb6, 0xd6, 0x7f, 0x33, 0xb4, 0x9c, 0x72, 0x84, 0xaa, 0x0a, 0xa9, 0x10, 0xc5, 0x6d, 0x7f, 0xbb, - 0x64, 0x2e, 0xf7, 0xfd, 0x29, 0xc0, 0xa1, 0x0b, 0xcc, 0xd6, 0x0e, 0x08, 0x1c, 0xc1, 0x79, 0xca, 0x05, 0x78, 0x28, - 0x82, 0xa2, 0xc8, 0xe2, 0x53, 0x34, 0x51, 0x22, 0x03, 0x30, 0xf9, 0xeb, 0x15, 0x39, 0x7c, 0x78, 0x87, 0x16, 0xcd, - 0xc9, 0x3a, 0x2a, 0x9d, 0x32, 0xc7, 0xc6, 0x26, 0x1d, 0x4a, 0x56, 0xc7, 0x79, 0xa5, 0x75, 0x80, 0xef, 0xe2, 0xc4, - 0x9b, 0xa5, 0x94, 0x6b, 0x56, 0xec, 0x53, 0x70, 0x0a, 0x2c, 0x33, 0xb4, 0x33, 0x22, 0xe3, 0xea, 0xad, 0x9d, 0xc5, - 0xd5, 0x88, 0xa7, 0xe1, 0xe1, 0x2c, 0x46, 0x1c, 0xe7, 0x0d, 0xb6, 0x7b, 0x62, 0x0f, 0x07, 0x83, 0x2f, 0x3b, 0xbd, - 0x0e, 0x16, 0x3b, 0xa3, 0xdf, 0x7a, 0xec, 0xc8, 0xd5, 0x83, 0xd2, 0xf2, 0xa4, 0x94, 0x69, 0xbe, 0x65, 0x3f, 0xcf, - 0x4f, 0xf6, 0xf8, 0xfc, 0xef, 0xef, 0x6d, 0x8a, 0x87, 0x93, 0xb2, 0x1c, 0x3d, 0xcf, 0xec, 0xc3, 0xbf, 0xd9, 0x7c, - 0xbe, 0x9f, 0x65, 0x59, 0x70, 0x5d, 0x62, 0x66, 0xd3, 0x44, 0x7b, 0xd7, 0xb8, 0x06, 0x58, 0x70, 0xb7, 0x80, 0xfa, - 0x4e, 0x7c, 0xfc, 0xe6, 0x23, 0x5c, 0x1d, 0x38, 0x45, 0x3d, 0xd8, 0x54, 0x58, 0xc6, 0x1e, 0xd5, 0xb1, 0xe8, 0x53, - 0x15, 0xcf, 0x2c, 0x93, 0xc0, 0x77, 0x9a, 0x45, 0x11, 0x20, 0x3c, 0x36, 0x16, 0x1f, 0x90, 0xb1, 0xf8, 0xc0, 0xe5, - 0x69, 0x0c, 0x1f, 0xbb, 0x62, 0x6e, 0xc3, 0xc7, 0x68, 0x92, 0x15, 0xd7, 0xbf, 0x61, 0x63, 0x4d, 0xa8, 0x7f, 0xf1, - 0x6a, 0x1e, 0x2f, 0x90, 0x29, 0x98, 0x89, 0x07, 0xa8, 0xfe, 0x31, 0xaa, 0x57, 0xef, 0xf7, 0xfb, 0xef, 0x33, 0x17, - 0xfe, 0xfd, 0x1c, 0xc3, 0xfb, 0x45, 0xd2, 0xf2, 0xfe, 0x63, 0x04, 0xd7, 0x30, 0xbc, 0xf6, 0x2c, 0x0b, 0x68, 0xf2, - 0x30, 0x8c, 0x12, 0x6e, 0xeb, 0x6d, 0x58, 0xaf, 0xcb, 0x23, 0xa4, 0x40, 0x48, 0x62, 0x8c, 0x14, 0x92, 0xc9, 0x71, - 0x3f, 0x34, 0x66, 0x06, 0xcd, 0xbe, 0x0d, 0x65, 0xb7, 0x9a, 0x41, 0x79, 0x4e, 0xe6, 0x14, 0xda, 0x4f, 0x01, 0xad, - 0x91, 0x64, 0xf6, 0x97, 0xcd, 0xff, 0xea, 0x8d, 0x0f, 0x07, 0xbd, 0xaf, 0xfb, 0x47, 0x8f, 0x36, 0x5d, 0xcb, 0x32, - 0x53, 0x37, 0xd8, 0xc2, 0xba, 0x65, 0x94, 0xef, 0x0d, 0x46, 0x4e, 0xde, 0xf5, 0x77, 0x94, 0x6f, 0xd1, 0x97, 0x3b, - 0x18, 0x99, 0x95, 0x44, 0xca, 0x96, 0x96, 0x86, 0x12, 0x6b, 0xf6, 0x3a, 0xc1, 0x78, 0x71, 0x2a, 0xb3, 0x83, 0xd4, - 0x8a, 0x02, 0xfa, 0xc2, 0xac, 0xa5, 0xca, 0x54, 0x04, 0x48, 0xc1, 0x58, 0x66, 0x49, 0x1d, 0x8c, 0xf2, 0xcb, 0xb8, - 0x98, 0xcc, 0x28, 0xd1, 0x13, 0xc0, 0x2d, 0xeb, 0x4b, 0xcb, 0xcb, 0xfd, 0xad, 0xdd, 0x11, 0x87, 0x3b, 0xa6, 0xa2, - 0x30, 0x3a, 0xc3, 0xc2, 0xaf, 0x07, 0x14, 0x12, 0xd6, 0x11, 0x1e, 0x9c, 0xd4, 0xe3, 0xab, 0x79, 0x1a, 0xa0, 0x47, - 0x6b, 0x2e, 0x68, 0x38, 0x85, 0x19, 0x95, 0x3d, 0x4a, 0x6d, 0x38, 0x29, 0x0e, 0xc7, 0x4e, 0xfd, 0x74, 0x13, 0xe8, - 0xb6, 0x2f, 0x87, 0xe4, 0x25, 0x85, 0x6e, 0xe6, 0x1e, 0xa2, 0x7f, 0x65, 0xe9, 0x21, 0x8e, 0x4f, 0xe8, 0x6f, 0x1e, - 0xfe, 0x3d, 0x77, 0x8f, 0xba, 0x9b, 0x7a, 0x69, 0x3e, 0x08, 0x77, 0xde, 0x82, 0x08, 0xc7, 0xc2, 0x7e, 0x1f, 0x3a, - 0xca, 0x18, 0x37, 0x02, 0x50, 0x22, 0xa7, 0xd3, 0x87, 0xab, 0x78, 0x6e, 0x3b, 0x62, 0x56, 0x3a, 0x48, 0xa8, 0xe5, - 0x01, 0xaa, 0xc3, 0xf3, 0x83, 0xd6, 0x33, 0xc6, 0x24, 0xe1, 0x82, 0xc3, 0xfd, 0xe4, 0xf7, 0x17, 0x95, 0xf7, 0x65, - 0x29, 0x13, 0xaa, 0x3e, 0xc8, 0x7c, 0xdc, 0xe7, 0x0f, 0x19, 0x06, 0x31, 0x25, 0x18, 0x60, 0x02, 0x4c, 0xcb, 0x2a, - 0xf5, 0x30, 0xcf, 0x2b, 0xc9, 0x37, 0xf0, 0xab, 0x07, 0x19, 0xc6, 0x20, 0xb1, 0x51, 0x8a, 0x8c, 0xa9, 0x81, 0x50, - 0xa0, 0x21, 0xc1, 0x05, 0x25, 0x3f, 0x31, 0xf2, 0x48, 0xb2, 0x53, 0x62, 0x64, 0x5b, 0xf4, 0x60, 0xb9, 0x9c, 0x80, - 0x44, 0x7a, 0x1c, 0xe2, 0x0b, 0x7e, 0xd2, 0x6f, 0xf8, 0x8e, 0xf8, 0x70, 0xda, 0x30, 0xd9, 0x10, 0xfd, 0xb0, 0xf0, - 0x48, 0xc1, 0x49, 0x25, 0x2a, 0xc3, 0xb6, 0xa6, 0x30, 0x25, 0x51, 0x54, 0xf4, 0x5b, 0x86, 0x8f, 0xad, 0xb6, 0x14, - 0x5b, 0xae, 0x51, 0x1e, 0x50, 0x79, 0xc6, 0xe5, 0xdc, 0x94, 0x36, 0xca, 0x79, 0x20, 0x36, 0x46, 0xa7, 0x2d, 0x8c, - 0x30, 0x13, 0xce, 0x83, 0x8c, 0x53, 0xe1, 0x44, 0x47, 0x18, 0x0c, 0x0c, 0xa5, 0x1d, 0xcd, 0x7c, 0x37, 0x5c, 0xfd, - 0x38, 0xf2, 0x37, 0xff, 0xeb, 0x30, 0xe8, 0xfd, 0x06, 0x57, 0xe2, 0xa8, 0x6b, 0xf7, 0xd4, 0xa3, 0xf3, 0xe8, 0xc1, - 0xa6, 0xfb, 0x2a, 0x52, 0x54, 0x1a, 0x1e, 0xfc, 0x4a, 0xb2, 0x1f, 0x3e, 0x09, 0x96, 0x67, 0x11, 0x87, 0xa5, 0x4f, - 0xe3, 0x10, 0x03, 0x1e, 0x5a, 0xff, 0x69, 0x91, 0xd1, 0x94, 0x66, 0xbc, 0x50, 0x5f, 0xc2, 0xcf, 0xfb, 0xdb, 0x15, - 0x83, 0x41, 0x14, 0xd7, 0x70, 0x4e, 0x18, 0x47, 0xb4, 0x31, 0xe4, 0x30, 0xc8, 0xaa, 0x3a, 0x30, 0x2f, 0x75, 0x49, - 0x18, 0x7d, 0x69, 0x56, 0x1a, 0xca, 0x7d, 0x47, 0x8e, 0x6d, 0x91, 0x2e, 0x6c, 0x8a, 0x15, 0x28, 0x9e, 0xe6, 0x3e, - 0xe6, 0xde, 0xbc, 0x88, 0xd1, 0xa7, 0x43, 0x7d, 0x31, 0x18, 0x23, 0x19, 0x85, 0x3c, 0x5f, 0x06, 0xd4, 0x2b, 0xba, - 0x79, 0x27, 0x01, 0x09, 0x1c, 0xd4, 0x91, 0x78, 0xf8, 0x70, 0x63, 0x1e, 0x03, 0x07, 0xc9, 0xb6, 0x2a, 0xf3, 0x52, - 0xaa, 0x21, 0x48, 0x47, 0x8e, 0xea, 0x07, 0xb1, 0x04, 0x3d, 0x5e, 0x82, 0xac, 0x65, 0x2c, 0xba, 0x5f, 0xd5, 0x4f, - 0x26, 0x67, 0xcb, 0xfd, 0x65, 0xfd, 0x5f, 0xd3, 0x38, 0xa1, 0x46, 0xea, 0x3d, 0x07, 0xa2, 0xe7, 0x80, 0x60, 0x0f, - 0x20, 0xc1, 0x0a, 0xf8, 0x69, 0x6d, 0x1c, 0x80, 0x2b, 0xb5, 0x9a, 0x36, 0xda, 0x02, 0x32, 0x5a, 0xb6, 0x66, 0xac, - 0x61, 0xe9, 0xce, 0x63, 0x95, 0xe7, 0x66, 0xbc, 0xb1, 0x61, 0xdb, 0xe4, 0xe0, 0x49, 0xad, 0x52, 0x6f, 0x98, 0xee, - 0x48, 0x16, 0x00, 0xfb, 0x89, 0xb7, 0xfc, 0x38, 0x72, 0x88, 0x4e, 0x45, 0xf2, 0x81, 0xbb, 0x35, 0x6a, 0xe2, 0xcf, - 0x4a, 0xbd, 0xb8, 0x8f, 0x03, 0x32, 0x8a, 0x00, 0xec, 0xeb, 0x1b, 0xfb, 0xac, 0x16, 0xb9, 0x72, 0x55, 0x8e, 0x36, - 0x04, 0xa8, 0xd8, 0xf0, 0x37, 0x0a, 0x7e, 0x42, 0x4b, 0x0b, 0x05, 0x3e, 0x1c, 0x77, 0x43, 0xc0, 0x0a, 0xaa, 0x70, - 0xa1, 0x2a, 0x48, 0xf8, 0xa1, 0xe9, 0x09, 0x9c, 0x0c, 0x5f, 0x4b, 0x4c, 0x63, 0xd7, 0xb5, 0x0b, 0xe3, 0x97, 0xf3, - 0xe5, 0x8e, 0xc1, 0x18, 0xc0, 0xe7, 0xe2, 0x32, 0x27, 0x95, 0x98, 0xee, 0xa7, 0x69, 0x75, 0x78, 0x62, 0xb8, 0x46, - 0x96, 0xd0, 0x04, 0xaf, 0xdb, 0x22, 0x71, 0xe8, 0xef, 0xe7, 0x78, 0x4c, 0x7f, 0x81, 0x60, 0xd9, 0xb0, 0xe9, 0x29, - 0xa2, 0x64, 0x46, 0x87, 0xc9, 0x91, 0xff, 0x19, 0x65, 0x4c, 0x8e, 0x47, 0xa5, 0x6c, 0x0c, 0x08, 0x17, 0x33, 0x39, - 0xf2, 0xe4, 0x07, 0x5c, 0x8b, 0x2a, 0x29, 0x66, 0x4e, 0x0f, 0xe4, 0x65, 0x6d, 0x9d, 0xe2, 0x7e, 0x3c, 0x61, 0x57, - 0x8e, 0x18, 0xd8, 0xd4, 0x18, 0x60, 0x69, 0x7e, 0x73, 0x23, 0x90, 0xe3, 0x04, 0xe0, 0x27, 0x82, 0x37, 0x82, 0x52, - 0xb9, 0xdf, 0x52, 0x6a, 0x04, 0x2f, 0xb5, 0x33, 0xba, 0xa7, 0xd1, 0x61, 0x26, 0x61, 0x44, 0x07, 0x85, 0x19, 0x3e, - 0x73, 0xe9, 0x1b, 0x76, 0x86, 0xc3, 0x03, 0x4e, 0x6a, 0x45, 0xa5, 0x86, 0x85, 0x6f, 0xe0, 0x27, 0x50, 0x82, 0x69, - 0x75, 0xb2, 0x23, 0x41, 0x6c, 0xc2, 0x8d, 0x0b, 0x30, 0x6c, 0x5e, 0x00, 0x5b, 0x80, 0xfc, 0x18, 0xb5, 0x13, 0x1c, - 0x49, 0x7e, 0x7b, 0xa2, 0x23, 0x87, 0xe0, 0xab, 0x52, 0x46, 0x57, 0x53, 0x03, 0x27, 0x1d, 0x69, 0xe4, 0xc8, 0xfa, - 0x66, 0x29, 0xf0, 0xea, 0x1a, 0xe3, 0xa4, 0xc8, 0xbc, 0xa9, 0x29, 0xbc, 0x6e, 0x89, 0xa0, 0xc3, 0x8b, 0x93, 0xdf, - 0xb1, 0x38, 0x22, 0x26, 0xe9, 0xca, 0xc0, 0x20, 0x19, 0x0c, 0x7e, 0x95, 0xfa, 0xb0, 0xef, 0x09, 0x8c, 0x1c, 0x95, - 0x97, 0xc1, 0x11, 0x5a, 0x1a, 0x49, 0x83, 0x54, 0x94, 0xdf, 0x45, 0x46, 0x2a, 0x2c, 0x97, 0x4e, 0x48, 0x6a, 0x58, - 0xfd, 0x3e, 0xcb, 0xea, 0xa9, 0x40, 0x48, 0xdc, 0xc1, 0xe6, 0xc9, 0xf1, 0x86, 0x6f, 0xa5, 0x34, 0x10, 0x34, 0xbe, - 0x12, 0x65, 0x3c, 0x5a, 0xfd, 0x46, 0x65, 0xaf, 0x1a, 0xc1, 0xdd, 0x49, 0x8b, 0xe3, 0x29, 0x8a, 0x94, 0xcc, 0xe8, - 0xf8, 0x44, 0x2f, 0xd2, 0xcd, 0x92, 0x6f, 0xd5, 0x88, 0x72, 0x00, 0xd1, 0x18, 0xb4, 0x50, 0x64, 0xcf, 0x62, 0xb9, - 0x4d, 0xee, 0x94, 0xfa, 0x52, 0xe0, 0x49, 0x32, 0x0f, 0x30, 0x26, 0x5f, 0xeb, 0x24, 0x5a, 0xc7, 0x8a, 0xf9, 0x9a, - 0x46, 0x14, 0x69, 0x12, 0x9a, 0xa1, 0xb5, 0xcd, 0x29, 0x0a, 0xaa, 0x6a, 0x4b, 0x2d, 0x86, 0xcc, 0x12, 0xfc, 0x22, - 0x34, 0x20, 0x11, 0x00, 0x20, 0xb1, 0xe4, 0x28, 0xc1, 0x56, 0x03, 0xc4, 0x1f, 0x44, 0x23, 0x1a, 0x6b, 0xfd, 0x6d, - 0xdc, 0x8a, 0xbb, 0xc8, 0x3c, 0x37, 0x12, 0xb7, 0x42, 0xae, 0x11, 0x61, 0x32, 0x99, 0x36, 0xc0, 0xc0, 0x67, 0x52, - 0x6d, 0xb3, 0x61, 0xc4, 0x6b, 0x7b, 0x49, 0x19, 0xfa, 0xd6, 0x2c, 0xba, 0x4c, 0xe6, 0xd5, 0x62, 0xb3, 0x5e, 0x70, - 0x48, 0x0d, 0xd9, 0x8b, 0x00, 0x66, 0x1b, 0xca, 0xa0, 0x1c, 0xd0, 0x90, 0xd8, 0xab, 0xf5, 0x7b, 0x07, 0x75, 0x68, - 0x5a, 0x2f, 0xc2, 0x76, 0xab, 0xf8, 0x82, 0x3f, 0xa8, 0xaf, 0x7f, 0xa4, 0xd7, 0x3f, 0x92, 0x91, 0x4d, 0x72, 0x0d, - 0x33, 0x55, 0x7f, 0x98, 0x1e, 0x38, 0xbc, 0xae, 0x0c, 0x09, 0xba, 0x4b, 0x81, 0xe0, 0xae, 0x74, 0x27, 0x53, 0x98, - 0x41, 0x77, 0xb7, 0x9e, 0xff, 0xdb, 0x4f, 0x01, 0xa1, 0x38, 0xbe, 0xd9, 0x6b, 0x07, 0x94, 0x55, 0xc6, 0x12, 0x11, - 0x44, 0xd8, 0x40, 0x90, 0xb0, 0x6e, 0x64, 0x35, 0x6a, 0xf3, 0x20, 0xbe, 0x1d, 0x3e, 0x7d, 0x0a, 0x4d, 0x2f, 0x04, - 0x7d, 0xcc, 0x62, 0x89, 0xf0, 0x0a, 0x97, 0x16, 0xd4, 0x6b, 0x83, 0x7d, 0xe7, 0x71, 0x9e, 0xa3, 0xd7, 0x0b, 0xf2, - 0x95, 0x07, 0x91, 0x19, 0x7e, 0xef, 0xac, 0xa8, 0x5e, 0xd2, 0x83, 0xf8, 0x30, 0x86, 0x21, 0xdb, 0xf4, 0xb7, 0x6d, - 0x44, 0x1a, 0x26, 0x1f, 0xa2, 0x4e, 0x93, 0x32, 0x19, 0xf9, 0x62, 0x70, 0xc6, 0xe5, 0x7f, 0x97, 0x54, 0x9c, 0x26, - 0x5e, 0x22, 0xbc, 0x18, 0x3f, 0x43, 0x99, 0x94, 0x0c, 0x72, 0x90, 0x8c, 0xc5, 0x99, 0xc1, 0x6c, 0x64, 0x89, 0x87, - 0x71, 0x85, 0x69, 0x90, 0x64, 0x74, 0x12, 0xc1, 0x45, 0x45, 0x0b, 0x56, 0xd5, 0xde, 0x1b, 0x05, 0xdb, 0x8a, 0xec, - 0xda, 0x38, 0xd2, 0x11, 0x9d, 0x03, 0xed, 0xeb, 0x20, 0x97, 0x58, 0xb6, 0x0d, 0x83, 0x43, 0xea, 0x37, 0x2a, 0x5d, - 0xb8, 0x18, 0x13, 0xdc, 0xb5, 0x55, 0xa9, 0x08, 0x3f, 0xd5, 0xfa, 0x47, 0xb1, 0xb8, 0x6c, 0x0c, 0x76, 0x28, 0xad, - 0x34, 0xd4, 0xbd, 0x31, 0x7c, 0x29, 0x30, 0x3d, 0x9d, 0x09, 0x8f, 0x0f, 0x62, 0x03, 0x1e, 0x23, 0xd0, 0x91, 0x1f, - 0xe5, 0xfa, 0x23, 0x75, 0x7b, 0xcd, 0x84, 0x80, 0x30, 0xb4, 0x5a, 0x43, 0x70, 0xd2, 0x30, 0xb1, 0xaa, 0xd1, 0x5e, - 0xa6, 0xe8, 0xcc, 0xc0, 0x3f, 0x43, 0x30, 0x94, 0x39, 0x98, 0xb8, 0xbb, 0x0d, 0x2f, 0x04, 0x3c, 0x61, 0x36, 0xa7, - 0x99, 0xf8, 0xfb, 0x36, 0x99, 0xb7, 0x5a, 0x63, 0xa0, 0x3f, 0xbb, 0x79, 0x17, 0x88, 0x53, 0x00, 0x48, 0x4e, 0x37, - 0xc3, 0x27, 0x8a, 0xbb, 0xe6, 0x50, 0xce, 0x16, 0x9c, 0xf0, 0x87, 0xc8, 0x37, 0x09, 0x91, 0xd7, 0x66, 0x5a, 0x4f, - 0x63, 0x01, 0x4e, 0xd3, 0x74, 0x1e, 0x05, 0xe4, 0x73, 0x02, 0x5f, 0xc4, 0x40, 0xda, 0x1b, 0x58, 0xf9, 0x41, 0x54, - 0x49, 0xf6, 0xd7, 0x5c, 0xb6, 0x57, 0x28, 0xaf, 0xd8, 0x18, 0xc0, 0x47, 0x8e, 0x17, 0x57, 0x9c, 0xa9, 0x23, 0x9c, - 0x59, 0xa1, 0x48, 0x2b, 0x57, 0x82, 0x1b, 0x12, 0x73, 0x13, 0xc9, 0xa4, 0x65, 0xda, 0xbc, 0xa7, 0x09, 0x9d, 0x3b, - 0x75, 0x5e, 0x50, 0x72, 0x98, 0x08, 0x92, 0x4e, 0xa5, 0xf3, 0x56, 0x23, 0x7b, 0x51, 0xc3, 0x42, 0xc6, 0x40, 0x38, - 0x1b, 0xa4, 0x06, 0xa0, 0x12, 0x56, 0xc0, 0x78, 0x22, 0x3d, 0x9e, 0x48, 0x8e, 0x47, 0x0e, 0xe3, 0x0d, 0xe6, 0xcc, - 0x8b, 0x68, 0x64, 0x68, 0x47, 0xa2, 0xe3, 0xfb, 0x68, 0x5f, 0xa0, 0x26, 0xbc, 0xd5, 0xbd, 0x18, 0x80, 0x75, 0xc3, - 0x38, 0x21, 0x36, 0x86, 0xf8, 0x94, 0x9d, 0xde, 0xdc, 0xc0, 0x66, 0xc1, 0x10, 0x01, 0x84, 0x20, 0xd5, 0x2a, 0xc9, - 0x49, 0xc9, 0x35, 0x2b, 0x60, 0xcf, 0x10, 0x9e, 0x12, 0x73, 0x0a, 0xfa, 0x13, 0xb0, 0x0e, 0xe1, 0x5d, 0x1b, 0xed, - 0x4d, 0xe1, 0xf4, 0x60, 0xc6, 0xa1, 0x8c, 0x7e, 0x90, 0x5c, 0x18, 0xc5, 0xdc, 0x22, 0x8f, 0x87, 0x24, 0x9f, 0xf8, - 0x43, 0x5a, 0x0b, 0xa0, 0x8e, 0x35, 0x60, 0x29, 0x24, 0x60, 0x89, 0x98, 0x90, 0xb6, 0x02, 0xab, 0x74, 0x5a, 0x17, - 0xab, 0xd0, 0xc9, 0x97, 0x37, 0x36, 0xde, 0x61, 0x98, 0xf4, 0xd8, 0x58, 0x96, 0x57, 0x46, 0x40, 0xb4, 0x8d, 0x0d, - 0x3a, 0x28, 0x06, 0x98, 0xa8, 0x44, 0xe3, 0xa4, 0x97, 0x8a, 0x5c, 0x1f, 0x0b, 0x59, 0x09, 0xfc, 0x5b, 0x94, 0x2c, - 0xf9, 0x50, 0xdf, 0xfd, 0x56, 0x8b, 0xe2, 0x99, 0x06, 0x61, 0x14, 0xa2, 0xe5, 0xbb, 0x84, 0x74, 0xf0, 0xb8, 0x88, - 0x92, 0x90, 0x1f, 0x8d, 0xe8, 0x9b, 0x15, 0xe0, 0x1a, 0x57, 0x75, 0x38, 0x6a, 0xf9, 0x31, 0x01, 0xa6, 0xfa, 0x31, - 0xd6, 0xe5, 0x22, 0x4c, 0x2f, 0x8a, 0x67, 0x01, 0x19, 0xd8, 0xba, 0x0e, 0xc6, 0x3e, 0x94, 0x48, 0x92, 0x3e, 0xc5, - 0xc7, 0xb1, 0x2c, 0x6b, 0xf9, 0x8c, 0x76, 0x13, 0x3e, 0x22, 0x8e, 0xa0, 0xfe, 0x1a, 0x0b, 0x1d, 0x19, 0xe9, 0xb9, - 0x42, 0x50, 0xd4, 0x78, 0x1b, 0x64, 0xf9, 0x15, 0xbc, 0x33, 0x61, 0x10, 0xc6, 0xfa, 0xa6, 0x66, 0x30, 0x80, 0x2a, - 0x3d, 0x90, 0xea, 0x4a, 0xb2, 0x28, 0x72, 0x60, 0x5c, 0xa8, 0x78, 0x1c, 0x3d, 0x51, 0xe9, 0x3a, 0x0c, 0x1c, 0xa9, - 0xb2, 0x6d, 0xd6, 0x6f, 0x31, 0xff, 0x88, 0x68, 0x81, 0xd4, 0x82, 0x74, 0x13, 0xd0, 0x87, 0x26, 0x65, 0x84, 0x90, - 0xb6, 0x23, 0x0e, 0x0c, 0xf0, 0x46, 0xf8, 0xd0, 0xc6, 0x3f, 0x78, 0x70, 0xf0, 0x58, 0xf2, 0x3c, 0x67, 0xa3, 0x00, - 0xf1, 0xee, 0x9c, 0x6f, 0xf8, 0x78, 0x86, 0x8a, 0x4d, 0xde, 0x53, 0xc9, 0x7c, 0xcd, 0x2b, 0xf7, 0x1d, 0x18, 0x42, - 0xac, 0x23, 0x77, 0x1b, 0x9f, 0xc5, 0x76, 0x2b, 0xdf, 0x60, 0xbd, 0x70, 0xa9, 0x62, 0x38, 0x15, 0x63, 0x3b, 0x93, - 0x21, 0xff, 0xca, 0x8a, 0x10, 0xe1, 0x93, 0x00, 0x16, 0x71, 0x45, 0xa6, 0x23, 0x8f, 0x7a, 0xc4, 0x63, 0xca, 0x9e, - 0x0b, 0x03, 0x81, 0x7c, 0xc4, 0x0c, 0x53, 0xad, 0xd4, 0x4f, 0x64, 0xc4, 0x9d, 0x1c, 0x0f, 0x55, 0x8c, 0x31, 0x0c, - 0x0a, 0x82, 0xb8, 0xaa, 0x9f, 0x5f, 0xe9, 0xf8, 0xc6, 0x72, 0xcc, 0xea, 0xd3, 0x57, 0xf3, 0xe0, 0x0c, 0xd6, 0xa7, - 0xfd, 0x05, 0x9a, 0xa3, 0xe6, 0xac, 0x61, 0x44, 0x27, 0x10, 0x96, 0x5c, 0xaf, 0xa9, 0x39, 0xd4, 0x94, 0x5c, 0x7d, - 0x78, 0xe3, 0x46, 0x89, 0x14, 0x58, 0x20, 0xc6, 0x25, 0x38, 0x50, 0x53, 0x49, 0x0a, 0x4f, 0x01, 0xe3, 0xd2, 0x6b, - 0x48, 0x45, 0xac, 0x85, 0x00, 0x21, 0x85, 0xe6, 0x4b, 0xd4, 0xaa, 0x21, 0xe5, 0xc4, 0x3c, 0x08, 0x3a, 0xed, 0x89, - 0xc1, 0x2a, 0x45, 0xb2, 0x2c, 0x30, 0x5e, 0x89, 0xa5, 0x9b, 0x08, 0xa7, 0x76, 0x7d, 0xad, 0xf2, 0x5a, 0x14, 0xcc, - 0x0e, 0x1c, 0x27, 0x46, 0x0f, 0x24, 0x74, 0x61, 0xd4, 0x30, 0x07, 0x7a, 0x58, 0x9c, 0x1c, 0xa1, 0x6a, 0x6e, 0x4a, - 0x06, 0x72, 0x3e, 0x05, 0xf3, 0xd2, 0x51, 0xee, 0x6b, 0x71, 0xe5, 0x70, 0xc1, 0x59, 0xcd, 0x54, 0xc1, 0x7d, 0x5b, - 0x51, 0x61, 0x16, 0x61, 0x97, 0x4c, 0xe1, 0x92, 0xe3, 0xd6, 0xa7, 0x8d, 0x39, 0xda, 0xf0, 0xdc, 0xdc, 0xdc, 0xc0, - 0x71, 0x03, 0x72, 0xc2, 0x85, 0x15, 0x0a, 0x29, 0xa4, 0x9a, 0xf4, 0x58, 0x56, 0x53, 0x90, 0x1b, 0xe3, 0xea, 0xf1, - 0x18, 0x45, 0xb2, 0x59, 0x55, 0x94, 0xf6, 0x83, 0x53, 0x00, 0x68, 0x8c, 0xdd, 0x1d, 0x42, 0xee, 0xdf, 0x84, 0x98, - 0xd3, 0x4e, 0x9e, 0xbb, 0x9f, 0x1a, 0x1c, 0xe2, 0x37, 0x98, 0x58, 0x21, 0xf7, 0x3f, 0x65, 0xfd, 0xd3, 0x38, 0x09, - 0xe9, 0xa6, 0x72, 0x96, 0x60, 0x3e, 0x07, 0xd5, 0x91, 0x2b, 0xbe, 0x58, 0x01, 0x05, 0xcc, 0xf3, 0x9c, 0x08, 0xc2, - 0xb3, 0xd0, 0x96, 0x33, 0xb1, 0x4b, 0x03, 0xf1, 0x72, 0x23, 0x4b, 0xbc, 0x49, 0xd3, 0xc8, 0x19, 0xea, 0x33, 0x88, - 0xae, 0xab, 0x8d, 0x8b, 0x74, 0x78, 0x04, 0xb4, 0x10, 0x6d, 0x40, 0x8a, 0x17, 0x55, 0x62, 0xad, 0xb3, 0xe4, 0x76, - 0x52, 0xf9, 0x5a, 0x20, 0xe2, 0xb3, 0x04, 0x69, 0x58, 0xe3, 0x7a, 0x9f, 0x27, 0x06, 0x69, 0x43, 0x6f, 0x6f, 0x6e, - 0xe0, 0x8f, 0x65, 0x19, 0x84, 0xe6, 0x77, 0x2c, 0x31, 0x87, 0x5d, 0xc4, 0x13, 0x6f, 0xba, 0xf8, 0xb5, 0x83, 0x5a, - 0x65, 0x91, 0xdb, 0xa0, 0xfa, 0x90, 0xe6, 0xc9, 0x69, 0xb5, 0xbd, 0x7c, 0x94, 0x2a, 0xdb, 0x01, 0x9a, 0x4a, 0x42, - 0x89, 0xb2, 0x7f, 0x04, 0x28, 0x85, 0xe6, 0x89, 0x68, 0x7d, 0x44, 0x7e, 0x5b, 0xac, 0x3f, 0x19, 0x90, 0x71, 0x0f, - 0xdc, 0x71, 0x6f, 0x2b, 0x12, 0xd9, 0xec, 0x23, 0xef, 0xc9, 0xee, 0xc0, 0xcd, 0x82, 0x24, 0x4c, 0xcf, 0x51, 0x05, - 0x81, 0xca, 0x10, 0x72, 0x84, 0x10, 0xd0, 0x00, 0x35, 0x08, 0x7a, 0x01, 0x7e, 0x6e, 0x75, 0xa2, 0x54, 0x3d, 0x99, - 0x31, 0x5a, 0xb9, 0xc9, 0x71, 0x3d, 0xb4, 0x1b, 0x17, 0xdb, 0xce, 0xa3, 0x1c, 0xe3, 0x5b, 0xd2, 0xb0, 0xd8, 0x06, - 0x85, 0x2f, 0x1b, 0xbf, 0x66, 0x72, 0xe4, 0xaa, 0xd2, 0xb4, 0x3c, 0x8b, 0xc2, 0x6e, 0x04, 0x56, 0xed, 0x4a, 0x09, - 0x03, 0x47, 0x72, 0x34, 0x97, 0x8d, 0x50, 0x72, 0xaa, 0x3f, 0x59, 0xdb, 0x41, 0xe0, 0x80, 0xcb, 0x75, 0x75, 0x78, - 0x79, 0xe4, 0xb8, 0x57, 0xfe, 0x95, 0x12, 0xab, 0x5e, 0x2a, 0xb9, 0x88, 0x2c, 0xbb, 0xec, 0x0e, 0x91, 0x19, 0xf7, - 0x33, 0xf5, 0x42, 0xa8, 0x1b, 0xb2, 0x96, 0xb1, 0xa5, 0xea, 0xf3, 0x96, 0x71, 0x23, 0x83, 0xaf, 0xc4, 0x3a, 0xda, - 0x2d, 0x6b, 0xc4, 0xd1, 0xb4, 0x2d, 0x71, 0x1d, 0x2c, 0x40, 0x65, 0x03, 0x77, 0xe6, 0x86, 0xc4, 0x40, 0xbb, 0x4b, - 0x34, 0xd3, 0x99, 0xe2, 0x5c, 0xdb, 0x7d, 0xb4, 0xa7, 0x3c, 0x93, 0xc4, 0x38, 0xa2, 0xe8, 0xdb, 0x12, 0xa2, 0x97, - 0x1a, 0x90, 0xd4, 0x72, 0x0f, 0x31, 0x3e, 0x0d, 0xb7, 0x68, 0x60, 0x8a, 0x33, 0xd4, 0x66, 0x22, 0x0a, 0x94, 0x5d, - 0x53, 0x6c, 0x65, 0x8b, 0xae, 0x57, 0x14, 0x02, 0x91, 0x88, 0x52, 0xdd, 0xa5, 0x3a, 0x91, 0x57, 0x70, 0x22, 0xaf, - 0xd0, 0x4c, 0xb8, 0x58, 0xe6, 0xb5, 0xaf, 0x54, 0xb1, 0xfe, 0xb8, 0x74, 0x68, 0xec, 0xc6, 0x05, 0xb1, 0xaf, 0x60, - 0x79, 0x57, 0x97, 0x50, 0x1d, 0xe7, 0xe3, 0xb8, 0x62, 0x42, 0x57, 0xad, 0x13, 0xba, 0x32, 0xc6, 0x79, 0xaa, 0xf4, - 0x7c, 0xec, 0x1d, 0xf2, 0x89, 0x4c, 0xd6, 0xdc, 0x45, 0x70, 0x8d, 0x97, 0x1a, 0x60, 0x03, 0x77, 0xee, 0x4d, 0x5c, - 0x54, 0x89, 0xc7, 0x51, 0x7e, 0x10, 0x51, 0xae, 0x57, 0xf1, 0xeb, 0x83, 0xa0, 0xd5, 0x96, 0xf2, 0x6c, 0xe6, 0xcb, - 0x53, 0xb4, 0x90, 0x38, 0x8d, 0xbc, 0x73, 0x01, 0x4b, 0xce, 0xcc, 0x50, 0x9a, 0xb4, 0x2a, 0xd6, 0x34, 0x88, 0xe7, - 0xa8, 0xc6, 0x9d, 0x56, 0xe7, 0x6f, 0x0b, 0xdb, 0xb1, 0x59, 0x05, 0xe7, 0x5e, 0xc0, 0x37, 0x7f, 0xda, 0x42, 0xbd, - 0xb5, 0x29, 0x43, 0xac, 0x3c, 0xd0, 0xef, 0x7d, 0xcc, 0x15, 0x6a, 0xe5, 0xcb, 0x09, 0x9c, 0xa5, 0xdc, 0x92, 0x4a, - 0xad, 0xa5, 0xbf, 0x94, 0xf8, 0xec, 0x81, 0xbf, 0xff, 0x00, 0xaa, 0x00, 0x57, 0x33, 0x11, 0x3a, 0x21, 0xd9, 0xa3, - 0x67, 0x68, 0x81, 0xc4, 0x84, 0x3c, 0xb8, 0x64, 0xef, 0x49, 0xc8, 0x52, 0xbf, 0xe7, 0x12, 0x23, 0xf3, 0x37, 0xc2, - 0x08, 0xc5, 0xe3, 0x42, 0x94, 0x8d, 0x5f, 0x52, 0x00, 0x63, 0x1c, 0xb6, 0xe5, 0xac, 0x66, 0xfe, 0x81, 0x7b, 0xac, - 0x4c, 0x82, 0xf0, 0xf5, 0x7b, 0x2e, 0x94, 0xab, 0xcc, 0x40, 0x97, 0x8d, 0x7e, 0xae, 0x6d, 0xc7, 0x83, 0xca, 0x66, - 0x6d, 0x3c, 0x5a, 0xb0, 0x6a, 0x28, 0x66, 0x96, 0x17, 0x5e, 0x28, 0xa2, 0x2a, 0xd7, 0x4a, 0xfa, 0x98, 0x5f, 0xa9, - 0x32, 0x67, 0x84, 0x73, 0xed, 0x0d, 0x1f, 0x3e, 0xc4, 0xbf, 0x02, 0x7e, 0x10, 0x97, 0x42, 0x4f, 0xfe, 0x03, 0xa7, - 0x84, 0xdd, 0xc3, 0xf0, 0x8c, 0x70, 0xaf, 0xaa, 0x1b, 0x08, 0xeb, 0xb4, 0x7a, 0x60, 0x1f, 0x54, 0x76, 0x0e, 0x86, - 0x46, 0xb4, 0xc0, 0x86, 0xb1, 0x4f, 0x72, 0x21, 0x16, 0x4a, 0x6b, 0x7e, 0xe5, 0x2b, 0x7d, 0x02, 0x02, 0xa9, 0x2b, - 0xe5, 0x60, 0x4b, 0x1f, 0xcb, 0x29, 0xc3, 0xb5, 0xf3, 0xeb, 0x44, 0x14, 0xab, 0x48, 0xaa, 0x87, 0x00, 0xe7, 0x8d, - 0xcb, 0x51, 0x62, 0xb8, 0x73, 0xb1, 0xf6, 0x72, 0x69, 0x8c, 0x35, 0x95, 0xf0, 0x6c, 0x25, 0x8e, 0xb7, 0x86, 0x10, - 0x72, 0x2d, 0xbc, 0x2b, 0x8d, 0x16, 0xed, 0x03, 0xf7, 0x3d, 0x76, 0xf8, 0xd6, 0xa6, 0xec, 0xc2, 0xc0, 0xa6, 0x8e, - 0x96, 0x7c, 0x95, 0x2e, 0x81, 0x3a, 0xa6, 0xac, 0x46, 0xc6, 0xd8, 0xae, 0x5d, 0x29, 0xb4, 0x07, 0x4e, 0x1d, 0xce, - 0x5b, 0xe1, 0x5e, 0x2a, 0x12, 0x41, 0xcb, 0x8f, 0x8d, 0xfa, 0x8e, 0x7b, 0x6a, 0x08, 0x4c, 0xb2, 0xba, 0x06, 0xf0, - 0x47, 0xd2, 0x0f, 0xc7, 0xe5, 0x48, 0x49, 0x39, 0x0c, 0x85, 0xaf, 0xb3, 0x42, 0xb9, 0x82, 0x38, 0xac, 0x81, 0xbf, - 0x1f, 0xa0, 0x0e, 0xaa, 0x71, 0x3b, 0x8c, 0x4d, 0xc9, 0x6d, 0xb2, 0x46, 0xd4, 0x21, 0xaf, 0x7e, 0x46, 0x4d, 0x1f, - 0x96, 0xd9, 0xa1, 0xbb, 0x24, 0x01, 0x0f, 0xea, 0x9b, 0x1e, 0x3e, 0x9c, 0xd3, 0xef, 0xd2, 0xb0, 0x4c, 0x63, 0x0b, - 0x64, 0xc7, 0x9d, 0x19, 0x79, 0xbb, 0x50, 0xda, 0xac, 0x49, 0x05, 0x24, 0x45, 0x26, 0x38, 0x88, 0x09, 0x5a, 0x2e, - 0x19, 0xe2, 0xb2, 0x15, 0x19, 0xd4, 0x00, 0xf1, 0x85, 0x55, 0x80, 0xb0, 0xcf, 0x45, 0x50, 0x26, 0x2f, 0x40, 0x71, - 0xaf, 0x38, 0x5e, 0x41, 0xe9, 0xca, 0x60, 0x4d, 0x1e, 0x6e, 0xb0, 0x28, 0x77, 0x11, 0xd8, 0x26, 0xcb, 0x05, 0x7a, - 0xa2, 0x6a, 0x46, 0x92, 0x48, 0x02, 0x32, 0xd0, 0x33, 0xa5, 0xd3, 0xfa, 0x78, 0x1b, 0xa2, 0xa5, 0xc2, 0x3f, 0x34, - 0x5e, 0x1c, 0x29, 0xea, 0xb1, 0x30, 0xaf, 0x83, 0xbb, 0x61, 0x17, 0x0d, 0x11, 0x35, 0x5a, 0x1d, 0xd6, 0xed, 0xfc, - 0x48, 0x1a, 0x2a, 0x66, 0xa5, 0x89, 0x00, 0xe0, 0xba, 0x01, 0x1f, 0x02, 0xce, 0xc5, 0x3f, 0x37, 0x37, 0xd6, 0xa6, - 0x85, 0x16, 0xa1, 0x3f, 0x7e, 0x7c, 0xe3, 0x51, 0xba, 0x2a, 0x78, 0xb8, 0xb9, 0xd9, 0x1d, 0x0c, 0x24, 0x55, 0xa0, - 0xd5, 0x3a, 0x48, 0x1f, 0x48, 0xb2, 0x41, 0x1d, 0x59, 0xa8, 0x8b, 0x14, 0x04, 0x93, 0x0d, 0xf2, 0x16, 0xb3, 0x63, - 0x1b, 0x93, 0x1a, 0xe2, 0x46, 0x62, 0xec, 0xbe, 0x06, 0x49, 0xd1, 0x84, 0x3e, 0x9c, 0x92, 0x52, 0x1c, 0xfa, 0x97, - 0xad, 0x02, 0x4b, 0x17, 0x4d, 0x79, 0xad, 0x59, 0x51, 0x2c, 0x72, 0x6f, 0x73, 0x33, 0x58, 0x00, 0x8b, 0x1d, 0xe3, - 0x35, 0xcf, 0x2f, 0xce, 0x30, 0xc0, 0x84, 0xe5, 0x56, 0xde, 0x2d, 0x93, 0x58, 0xbe, 0x38, 0x72, 0x67, 0x31, 0x9d, - 0x49, 0x34, 0x3b, 0x98, 0x47, 0x4a, 0x37, 0x39, 0x72, 0xd4, 0x0f, 0xb4, 0xc1, 0xbc, 0xb9, 0xa9, 0xd0, 0x0b, 0xfb, - 0xfd, 0xdd, 0xf1, 0x2c, 0x16, 0x06, 0xae, 0x91, 0xbc, 0xff, 0x8e, 0x67, 0x94, 0x91, 0xe2, 0xd3, 0x19, 0xbd, 0x8c, - 0x91, 0xce, 0xf3, 0x61, 0xbf, 0x4d, 0x92, 0xab, 0x32, 0x1a, 0x24, 0x63, 0xe3, 0xe9, 0x75, 0x3f, 0x8c, 0x30, 0x43, - 0x87, 0xa5, 0xd4, 0x35, 0xb3, 0xd8, 0x31, 0x6d, 0x2a, 0xae, 0x6a, 0xaa, 0xb0, 0xdf, 0x12, 0xc3, 0x79, 0x27, 0x92, - 0x8e, 0x43, 0x1b, 0x43, 0xcf, 0x7e, 0x49, 0x42, 0xd4, 0x88, 0x8c, 0x0b, 0xb5, 0x7c, 0x2d, 0x36, 0x88, 0x50, 0xaa, - 0xa1, 0xdf, 0xfd, 0x2d, 0xd4, 0xe6, 0x32, 0xa6, 0x70, 0xef, 0xa5, 0x29, 0x33, 0xb9, 0x48, 0x31, 0x48, 0x14, 0xf7, - 0xfe, 0xc3, 0x1d, 0x52, 0xe3, 0x7f, 0x84, 0x42, 0x03, 0xb0, 0xf1, 0x03, 0xf6, 0xa4, 0x01, 0x02, 0x8d, 0x62, 0x64, - 0x66, 0x17, 0x50, 0x92, 0xf9, 0x37, 0xa4, 0xdb, 0x49, 0x7c, 0xac, 0x3b, 0x8d, 0xcf, 0xe0, 0x48, 0x66, 0x51, 0xb8, - 0x4c, 0x42, 0x38, 0xd0, 0xd7, 0x5e, 0x54, 0x8e, 0xa8, 0x25, 0x5f, 0x65, 0x0c, 0xfb, 0xa1, 0x3a, 0x85, 0x8f, 0x59, - 0xc5, 0x24, 0xde, 0xcd, 0xcd, 0x6b, 0x65, 0x5c, 0x26, 0x45, 0x38, 0x13, 0x51, 0xce, 0x11, 0xcc, 0x95, 0xbe, 0x47, - 0x62, 0xf0, 0x9d, 0xad, 0x1d, 0x40, 0x41, 0xe9, 0x28, 0xa7, 0x20, 0x7d, 0x49, 0xa8, 0x5c, 0x57, 0x69, 0x5e, 0x23, - 0xcc, 0x6a, 0x91, 0xf8, 0x98, 0xca, 0x54, 0x8e, 0x8f, 0xe9, 0x3e, 0xd5, 0xf6, 0x6f, 0xb2, 0xed, 0xd4, 0x59, 0x25, - 0x38, 0xb1, 0x54, 0x7b, 0xbf, 0x1a, 0x77, 0x76, 0x6c, 0x3c, 0xa3, 0x26, 0x1c, 0x55, 0x37, 0x38, 0xae, 0xcc, 0x19, - 0x05, 0x24, 0x36, 0x0b, 0xa8, 0x77, 0x65, 0x22, 0x42, 0x41, 0xb8, 0xf3, 0xb1, 0x5d, 0x1f, 0x27, 0xe6, 0xdb, 0x20, - 0x00, 0x85, 0xae, 0x6d, 0xb0, 0x04, 0x00, 0x43, 0x09, 0x17, 0x4b, 0x34, 0x91, 0xfa, 0x96, 0x38, 0x63, 0x5b, 0x96, - 0xfb, 0x2c, 0x52, 0xbf, 0x2c, 0xf7, 0x55, 0xe6, 0x3f, 0x8b, 0xba, 0x56, 0x8f, 0xf2, 0xcd, 0x5a, 0xee, 0xe7, 0x94, - 0x7f, 0xa2, 0xc7, 0x34, 0x92, 0x5c, 0xee, 0xbb, 0xcc, 0xa7, 0x30, 0x4b, 0x7f, 0x0d, 0xfd, 0xe1, 0xe3, 0xa7, 0x7a, - 0x7f, 0x4f, 0x85, 0x98, 0x1d, 0x85, 0xe2, 0x8a, 0x3d, 0x41, 0xe0, 0x57, 0x44, 0xe7, 0x68, 0x6d, 0x2e, 0x24, 0xde, - 0x86, 0xe4, 0x21, 0x31, 0xe5, 0xe8, 0xea, 0x93, 0x5c, 0x7e, 0x82, 0x49, 0x7b, 0xb4, 0xa4, 0x5c, 0x7f, 0x77, 0x90, - 0xea, 0x8e, 0x70, 0xb5, 0x30, 0x82, 0xdf, 0xda, 0x4e, 0x8e, 0xab, 0xc2, 0x7f, 0xea, 0xf3, 0x15, 0xe5, 0x52, 0x49, - 0x0f, 0x68, 0xfb, 0xab, 0xc1, 0xc1, 0x4d, 0xae, 0x4c, 0x19, 0x12, 0x9d, 0xf2, 0x47, 0x08, 0xff, 0x07, 0x62, 0xfd, - 0x9e, 0x91, 0xa4, 0x0f, 0x50, 0x20, 0x85, 0x6f, 0x02, 0x42, 0x2b, 0xa6, 0x48, 0x4e, 0xa5, 0xfb, 0x5b, 0x26, 0x5f, - 0x08, 0x05, 0x87, 0x7a, 0x2b, 0x15, 0x1e, 0x84, 0xf3, 0xbe, 0x49, 0x2a, 0x82, 0xee, 0xbf, 0xd0, 0xdd, 0x80, 0xc2, - 0x98, 0x38, 0xe5, 0x38, 0x96, 0x3c, 0xdc, 0x25, 0xc0, 0xc4, 0x14, 0x28, 0x29, 0x0b, 0x0e, 0x15, 0x07, 0xb4, 0xb0, - 0xc6, 0xab, 0xd2, 0xe3, 0x62, 0xfd, 0xfd, 0xaf, 0x15, 0x0c, 0x1b, 0x77, 0xad, 0x83, 0x22, 0xcd, 0x82, 0xb3, 0xc8, - 0x1a, 0x09, 0x15, 0x45, 0x8c, 0x76, 0x85, 0x18, 0x29, 0x47, 0x6b, 0xef, 0xf0, 0x97, 0x82, 0x66, 0x32, 0xe5, 0xb7, - 0xd2, 0x59, 0xe0, 0x5b, 0xb9, 0x9a, 0xcf, 0x0a, 0xbc, 0x65, 0xa6, 0x92, 0xe2, 0x9b, 0x9a, 0x24, 0x9b, 0xfa, 0xaf, - 0xc8, 0xb0, 0x95, 0x7c, 0xe6, 0x14, 0x63, 0xee, 0x7c, 0x4e, 0x39, 0xe9, 0x1f, 0x40, 0xed, 0xcb, 0x94, 0x80, 0x40, - 0xa2, 0x2d, 0x26, 0xae, 0x13, 0x99, 0x0e, 0x53, 0x27, 0x0a, 0x0a, 0x28, 0x51, 0x10, 0xec, 0x74, 0x04, 0x87, 0xb3, - 0x3b, 0xa9, 0xec, 0xd6, 0xaf, 0xdc, 0xa2, 0x0b, 0x2d, 0xb9, 0xc7, 0xf8, 0x3c, 0xa8, 0xd1, 0x40, 0x95, 0x64, 0x9d, - 0x9a, 0x73, 0xda, 0x7c, 0x97, 0x39, 0xbd, 0xbf, 0xa2, 0xb7, 0x5b, 0xa0, 0x98, 0xe5, 0x09, 0x1e, 0xee, 0xc0, 0x68, - 0x1e, 0xd8, 0x29, 0x1a, 0xf1, 0xc4, 0x31, 0x80, 0xc5, 0xdc, 0x04, 0x16, 0xb8, 0xa2, 0x92, 0xd0, 0xf8, 0xfe, 0xe0, - 0xfd, 0x3b, 0x11, 0xc3, 0x6a, 0x6e, 0x7e, 0x80, 0x2b, 0x2a, 0xa4, 0xed, 0x6a, 0xc1, 0x67, 0x7d, 0x32, 0x60, 0x0f, - 0xf5, 0x62, 0x3f, 0x7c, 0x28, 0xcb, 0xf6, 0x73, 0xa3, 0x9a, 0x16, 0x83, 0x36, 0x94, 0x36, 0x33, 0x36, 0x30, 0x6e, - 0x6b, 0x9c, 0xcc, 0x89, 0xa5, 0x58, 0xd5, 0xf8, 0xd0, 0x9e, 0xb9, 0x81, 0x92, 0x95, 0xab, 0xdb, 0x44, 0x2b, 0x3b, - 0x41, 0xaa, 0x8f, 0x43, 0x7b, 0x55, 0xf7, 0xa0, 0x16, 0x4a, 0x14, 0x29, 0x22, 0xa0, 0xcf, 0x31, 0x23, 0x09, 0x94, - 0x8f, 0xed, 0xac, 0xd7, 0xe3, 0x85, 0x87, 0x2b, 0xe1, 0xfd, 0x96, 0xc1, 0xe1, 0xe0, 0x08, 0x46, 0xe6, 0x4d, 0xfa, - 0x29, 0x63, 0x4a, 0x79, 0xe3, 0x1b, 0xd8, 0x69, 0x38, 0xde, 0x1b, 0x03, 0x53, 0xb3, 0x19, 0xa3, 0x84, 0xf5, 0x59, - 0xe1, 0xf0, 0x39, 0x52, 0xbb, 0x81, 0xaa, 0x58, 0x32, 0x0d, 0x46, 0x75, 0x8b, 0x21, 0xd6, 0x93, 0x7a, 0x0f, 0xd8, - 0xba, 0xb3, 0x82, 0xec, 0xc6, 0xe8, 0xac, 0xbd, 0x4b, 0xec, 0x14, 0x80, 0x44, 0x95, 0x98, 0x51, 0xa2, 0xc1, 0x0c, - 0x85, 0xa4, 0x41, 0x5e, 0xbc, 0x4d, 0xc3, 0x78, 0x1a, 0x63, 0x04, 0x09, 0xed, 0x4f, 0x98, 0x56, 0xde, 0x3c, 0xe7, - 0x7d, 0x69, 0x2b, 0x1c, 0xab, 0xb0, 0x27, 0x6d, 0x6f, 0x61, 0x01, 0xbc, 0x0c, 0x61, 0x94, 0xa9, 0xe5, 0xf9, 0xb6, - 0x61, 0x15, 0xd2, 0xfc, 0x70, 0xc4, 0xb6, 0x43, 0xd1, 0xbe, 0x5f, 0x38, 0x06, 0xb6, 0x2e, 0x58, 0xa4, 0xd1, 0x32, - 0x36, 0x04, 0x86, 0x35, 0xfb, 0x16, 0x5e, 0x3e, 0x4c, 0xbb, 0xa8, 0x25, 0x3f, 0xe4, 0x29, 0x1e, 0x28, 0x03, 0x49, - 0x53, 0x8b, 0x60, 0x6a, 0x74, 0x52, 0x2d, 0xca, 0x94, 0x12, 0x53, 0x2c, 0x34, 0xfb, 0xc5, 0xd1, 0x28, 0x42, 0xd9, - 0x54, 0xe4, 0xff, 0x20, 0xa6, 0xf7, 0x0d, 0x20, 0x1e, 0xdc, 0x64, 0xc3, 0x03, 0x0d, 0x2f, 0x35, 0x69, 0x85, 0x68, - 0x77, 0x9e, 0x15, 0xa4, 0x1d, 0xdb, 0x00, 0x9c, 0x05, 0xe0, 0x01, 0x6d, 0x45, 0x2a, 0x90, 0x01, 0x30, 0x62, 0x06, - 0x15, 0xb4, 0x28, 0x27, 0xe5, 0xf8, 0x67, 0x29, 0xd0, 0x3c, 0xc8, 0x8a, 0xd9, 0x80, 0x86, 0x90, 0x5e, 0xed, 0x4f, - 0x33, 0xa0, 0xae, 0x52, 0x47, 0x11, 0x54, 0x8a, 0xd6, 0xa5, 0x53, 0x9b, 0x03, 0x8e, 0x38, 0xc6, 0xa0, 0x34, 0x19, - 0x0a, 0x5e, 0x2a, 0x3d, 0x04, 0x40, 0x36, 0xd0, 0xea, 0x79, 0x6b, 0xc1, 0x81, 0xab, 0x75, 0xd7, 0xfa, 0xbc, 0xb1, - 0xad, 0xba, 0x12, 0x17, 0xfe, 0x8a, 0xad, 0x03, 0x94, 0xc8, 0x4c, 0x28, 0x41, 0x17, 0x9f, 0x2f, 0x19, 0x20, 0x4d, - 0x3a, 0xfa, 0x45, 0x65, 0xfd, 0x1e, 0x3e, 0xdc, 0xe0, 0x83, 0x50, 0x29, 0x45, 0xe2, 0xdb, 0x24, 0xa6, 0x0a, 0xa9, - 0x29, 0x55, 0x4c, 0x70, 0xa1, 0xed, 0x47, 0x48, 0x11, 0xd7, 0x96, 0xa9, 0x8d, 0x17, 0xa8, 0x63, 0x54, 0x45, 0xae, - 0xcc, 0x22, 0xb4, 0x63, 0x41, 0x17, 0xf0, 0x2c, 0x90, 0x8e, 0x65, 0x5e, 0xc9, 0xb7, 0x44, 0xac, 0xa9, 0x9f, 0xbf, - 0x08, 0xc1, 0x3f, 0x8d, 0xe0, 0x0d, 0x89, 0x3b, 0x95, 0xcc, 0xbf, 0x56, 0xd6, 0x2e, 0xee, 0x6f, 0x54, 0x1a, 0xba, - 0xa4, 0x4c, 0x28, 0xcd, 0x4e, 0xbf, 0x97, 0xc9, 0xa3, 0xb8, 0xfa, 0xa7, 0x14, 0x3f, 0x18, 0x57, 0x7e, 0xf9, 0x95, - 0x5f, 0x92, 0xd2, 0x2d, 0x44, 0x58, 0x06, 0x12, 0xfa, 0x19, 0x95, 0x0b, 0x57, 0xfc, 0xfe, 0x61, 0x19, 0x2d, 0xa3, - 0xea, 0x88, 0x55, 0xd1, 0x2d, 0x03, 0x36, 0xea, 0x08, 0x48, 0xa1, 0x25, 0xea, 0x91, 0x94, 0xa8, 0x27, 0xa5, 0x1f, - 0x93, 0x3a, 0xc1, 0xe8, 0x79, 0x24, 0x96, 0xbd, 0x5a, 0x48, 0xd6, 0x4a, 0x6c, 0x89, 0x81, 0x67, 0x9d, 0x68, 0xc8, - 0x48, 0x9f, 0x75, 0xba, 0x69, 0xa4, 0x4b, 0xe3, 0xa8, 0x09, 0x4a, 0xb8, 0x80, 0x28, 0x08, 0xe8, 0xd3, 0x08, 0xd9, - 0x54, 0xd6, 0x2f, 0x08, 0x48, 0x3e, 0x31, 0x14, 0xb5, 0x42, 0x91, 0xae, 0x3e, 0x9a, 0xd3, 0x34, 0x4c, 0xe3, 0x84, - 0xb9, 0x23, 0x85, 0xfe, 0x1a, 0x2d, 0xcd, 0x7d, 0xb2, 0x78, 0x60, 0x0c, 0xb6, 0x31, 0xaf, 0x29, 0x50, 0x24, 0xea, - 0x52, 0xea, 0x9a, 0xd7, 0x64, 0xfb, 0x32, 0x03, 0xee, 0x58, 0xf5, 0x13, 0x42, 0x3f, 0x33, 0x79, 0x0f, 0x49, 0x31, - 0x45, 0xb7, 0x7e, 0x22, 0xe8, 0x2b, 0x5b, 0xb0, 0xda, 0x29, 0xb0, 0x34, 0x11, 0xc5, 0x09, 0x81, 0x61, 0xfc, 0xc2, - 0x5b, 0xcf, 0xe2, 0x7e, 0xee, 0xe4, 0xa7, 0x44, 0x5a, 0x31, 0x2a, 0x60, 0x48, 0x22, 0x6d, 0xd8, 0x9c, 0xd7, 0x19, - 0x86, 0xbf, 0x4a, 0xfc, 0xdf, 0x42, 0x5b, 0x28, 0xbf, 0x93, 0xba, 0x80, 0x7f, 0xc5, 0xd4, 0x80, 0x52, 0x60, 0xa0, - 0xd1, 0x64, 0x7d, 0x4f, 0x27, 0x88, 0xe0, 0x12, 0xa1, 0xa2, 0x70, 0x13, 0xb9, 0x34, 0xae, 0x6a, 0xcc, 0x7d, 0x4b, - 0x32, 0x6e, 0xae, 0x6c, 0x70, 0x8c, 0xad, 0x16, 0x78, 0x15, 0xff, 0x46, 0x23, 0x15, 0xb3, 0x54, 0x07, 0x89, 0xd5, - 0x99, 0xc8, 0xf9, 0xe8, 0x83, 0x33, 0x97, 0x07, 0x67, 0x56, 0xfa, 0x13, 0x9c, 0x0e, 0x32, 0x88, 0x40, 0xaf, 0xcf, - 0x11, 0x65, 0xca, 0x95, 0xcf, 0xfc, 0x39, 0xd0, 0xf2, 0x33, 0x57, 0x78, 0x1e, 0x02, 0x26, 0x9b, 0xbb, 0x33, 0x25, - 0xe3, 0x0d, 0x7d, 0x54, 0x19, 0xc1, 0x59, 0xc6, 0x3f, 0xed, 0xd6, 0x2e, 0xe1, 0xe1, 0x0c, 0x2b, 0xe0, 0x1f, 0x94, - 0x88, 0x52, 0x2c, 0xf0, 0xdf, 0x35, 0x38, 0xd6, 0x13, 0x85, 0x30, 0x46, 0x77, 0xe9, 0x8b, 0xfe, 0xdd, 0xa9, 0xbf, - 0xac, 0x1c, 0x05, 0xe8, 0xa1, 0x5a, 0xe0, 0x0b, 0xca, 0x15, 0x40, 0x3d, 0xe9, 0xa4, 0x10, 0x8a, 0xd9, 0x53, 0x3a, - 0x7e, 0x00, 0x78, 0x70, 0xb8, 0x30, 0x20, 0xa9, 0xc4, 0xc4, 0x51, 0xa5, 0xf7, 0x5f, 0x2a, 0xf9, 0xb5, 0xf4, 0x10, - 0x04, 0x70, 0x31, 0x91, 0x4d, 0x92, 0x42, 0x74, 0xfc, 0x13, 0xca, 0x72, 0x12, 0x8c, 0xeb, 0xf9, 0x16, 0xb3, 0xc0, - 0x2d, 0x31, 0x2f, 0x3c, 0x0e, 0xe8, 0x03, 0xa0, 0x85, 0x18, 0xe8, 0x2e, 0xe2, 0x13, 0x0c, 0xcd, 0xe8, 0x7a, 0x83, - 0x0f, 0x61, 0xed, 0xb1, 0x01, 0x58, 0xca, 0x50, 0xee, 0x97, 0x3f, 0x25, 0xf6, 0x21, 0x66, 0xef, 0x3c, 0x72, 0x85, - 0xba, 0x5a, 0x07, 0xe4, 0x32, 0x6c, 0xaf, 0x1e, 0x20, 0x76, 0x13, 0xec, 0x5b, 0x61, 0x6b, 0x73, 0x80, 0x54, 0x21, - 0xc9, 0xb2, 0x8c, 0xc4, 0x0d, 0x30, 0x50, 0xe2, 0x12, 0x61, 0xac, 0xbe, 0x9a, 0xad, 0xf6, 0x28, 0x06, 0x11, 0x19, - 0x4b, 0x8b, 0x14, 0x69, 0xee, 0xd6, 0x6a, 0x51, 0xb4, 0x22, 0x33, 0x84, 0x26, 0xaf, 0x13, 0x2f, 0x6b, 0x19, 0xe7, - 0xd7, 0xdb, 0xbe, 0xe0, 0x6a, 0x48, 0x73, 0xed, 0x0d, 0xd3, 0xd0, 0x6d, 0xa9, 0x57, 0x46, 0x44, 0x82, 0x8c, 0x19, - 0x21, 0xa6, 0xa5, 0x32, 0x60, 0x7b, 0x10, 0x89, 0x4b, 0x8b, 0xf4, 0xbc, 0xcc, 0xc1, 0xbb, 0xa1, 0x8c, 0x53, 0x6a, - 0x5f, 0xd3, 0x99, 0x8b, 0xb8, 0x91, 0xa4, 0x54, 0x91, 0x02, 0x70, 0xd9, 0xa3, 0x23, 0xba, 0x99, 0x05, 0x25, 0x73, - 0xa2, 0x56, 0x9d, 0x46, 0xe7, 0xe2, 0x73, 0xbc, 0xe2, 0x28, 0x95, 0xcf, 0x8d, 0xf9, 0xfe, 0x62, 0x8a, 0x2f, 0xc8, - 0x6d, 0x4f, 0xfb, 0x11, 0x58, 0x71, 0x42, 0x0e, 0x6a, 0xac, 0x7a, 0xfc, 0x2e, 0x43, 0x68, 0x8f, 0xfb, 0x00, 0x4f, - 0x49, 0x70, 0x11, 0x9f, 0x05, 0xc0, 0x20, 0xf5, 0x2f, 0xe0, 0x94, 0xa7, 0x99, 0x92, 0x1a, 0x5b, 0xcf, 0x16, 0x8b, - 0x39, 0x7c, 0x82, 0xae, 0x18, 0x72, 0x75, 0xb5, 0x5c, 0x52, 0x2c, 0xae, 0x90, 0xa7, 0x17, 0x42, 0x74, 0x9e, 0x5f, - 0x9c, 0x59, 0x1e, 0x3d, 0x9d, 0xca, 0x87, 0xf3, 0x20, 0xff, 0x6c, 0x79, 0xca, 0xa6, 0x4e, 0x3e, 0x90, 0x54, 0x1e, - 0xfd, 0x9d, 0x50, 0xa6, 0xfb, 0x5d, 0x86, 0x96, 0xd9, 0xaa, 0xe3, 0xbd, 0x80, 0x7a, 0xed, 0x0d, 0x9d, 0x31, 0xb7, - 0x68, 0xbc, 0x9b, 0x2c, 0x33, 0xb4, 0xf6, 0xe3, 0xd8, 0xce, 0x5c, 0x6b, 0x4c, 0x9d, 0x71, 0x47, 0x12, 0xa0, 0x2d, - 0xfd, 0x4d, 0x5b, 0x39, 0xd1, 0x1c, 0x92, 0xb7, 0x80, 0xf8, 0xe1, 0x6c, 0x9e, 0xb9, 0x29, 0xbc, 0xfe, 0xaf, 0xf6, - 0xd7, 0x0f, 0x36, 0xcf, 0x0c, 0x81, 0x92, 0xe2, 0xc9, 0x49, 0x98, 0x88, 0x9e, 0xc6, 0x72, 0x7d, 0x89, 0x66, 0xc5, - 0xd8, 0x41, 0xc3, 0xc1, 0xc0, 0x35, 0x8e, 0x56, 0x8d, 0x73, 0xd4, 0x91, 0x6d, 0xe3, 0x47, 0xc5, 0xa3, 0xc8, 0xd9, - 0x8c, 0x6a, 0xa6, 0xb6, 0x75, 0xeb, 0x38, 0x43, 0x93, 0xcf, 0xa6, 0xfb, 0xf9, 0x52, 0x65, 0x88, 0x67, 0x67, 0x47, - 0xed, 0x25, 0x5d, 0xfb, 0x26, 0x97, 0xf0, 0x3a, 0xc5, 0xc0, 0x7c, 0xc2, 0x80, 0x3f, 0xf3, 0xd3, 0x65, 0xbf, 0x88, - 0xf2, 0x02, 0x25, 0x2c, 0x24, 0xc2, 0x1b, 0xd1, 0x6c, 0x32, 0xcd, 0x71, 0x1a, 0x0e, 0x3b, 0xc8, 0x98, 0x92, 0x3b, - 0x4e, 0xe0, 0x8c, 0x73, 0xa9, 0x15, 0xf5, 0xc4, 0x93, 0x9e, 0x4b, 0x20, 0xe6, 0x22, 0x94, 0x79, 0xaa, 0x26, 0xc7, - 0xa6, 0xd7, 0x9d, 0xa7, 0x5a, 0xd4, 0xaf, 0x88, 0x70, 0x76, 0x25, 0xb0, 0xe0, 0x64, 0xfb, 0x1b, 0x99, 0xbc, 0x45, - 0x19, 0x01, 0x32, 0x34, 0x7c, 0x05, 0xd6, 0x1e, 0xd0, 0x9a, 0xb0, 0x82, 0x35, 0xf8, 0x7c, 0x51, 0x90, 0xa4, 0x70, - 0x8a, 0xf5, 0x06, 0xfd, 0x58, 0xe3, 0xbc, 0x35, 0x24, 0x8a, 0x31, 0x3f, 0xb9, 0x70, 0xca, 0x21, 0x00, 0x81, 0x71, - 0x60, 0x39, 0x25, 0x09, 0x07, 0x9d, 0x47, 0x57, 0xb3, 0x88, 0x82, 0xcd, 0xb3, 0x33, 0x57, 0x24, 0x03, 0xce, 0xb3, - 0x3f, 0x97, 0x4a, 0xb6, 0x2c, 0x56, 0x94, 0xcd, 0x19, 0x47, 0x94, 0xd4, 0x49, 0x01, 0xf4, 0x85, 0x82, 0xb4, 0x67, - 0xa8, 0x69, 0x3c, 0xf7, 0x17, 0xec, 0x03, 0xe0, 0x9e, 0xc2, 0x13, 0x19, 0xfb, 0xd3, 0xd7, 0xc7, 0xf0, 0x8b, 0xa5, - 0xc1, 0xa3, 0xf3, 0xf1, 0xe9, 0xf8, 0xb8, 0xeb, 0x6f, 0x79, 0xb6, 0x30, 0x60, 0xb0, 0x74, 0x66, 0x02, 0xab, 0x6b, - 0x8b, 0xf8, 0x2f, 0x5d, 0x4e, 0x10, 0xe6, 0x18, 0x34, 0x36, 0xc5, 0x11, 0xb3, 0x07, 0x3d, 0x4a, 0x06, 0x56, 0x7d, - 0xe1, 0x58, 0x8e, 0x2b, 0x5b, 0x23, 0x5f, 0x4f, 0xbb, 0x37, 0xec, 0x0c, 0xb1, 0x94, 0x2a, 0xfb, 0xdc, 0x98, 0x0f, - 0x30, 0x0e, 0xf3, 0xbf, 0xb6, 0xf6, 0x8b, 0xed, 0xb6, 0xf7, 0x28, 0x43, 0xd0, 0x74, 0xef, 0xd5, 0xf1, 0xb0, 0xd3, - 0x6b, 0xeb, 0x98, 0x56, 0xe1, 0x42, 0x2a, 0xdf, 0x8e, 0xf7, 0x30, 0x98, 0xef, 0x71, 0xcf, 0x94, 0x4b, 0x1c, 0x6f, - 0xee, 0x38, 0x8f, 0x76, 0x1c, 0xf7, 0xd8, 0x3f, 0xfe, 0x72, 0xc7, 0x3d, 0x66, 0x70, 0xd2, 0x19, 0x7a, 0x17, 0xbe, - 0x8a, 0x81, 0xb3, 0xc5, 0x43, 0x80, 0x1e, 0xe1, 0x88, 0xd0, 0x01, 0x13, 0x0e, 0x4d, 0xf6, 0xd7, 0x03, 0x18, 0xe9, - 0x45, 0x7d, 0xe8, 0x17, 0xf5, 0xb1, 0x1a, 0x5e, 0x5d, 0x9d, 0x2d, 0xaf, 0xd9, 0xcc, 0xf0, 0xe9, 0xa0, 0xa3, 0xf7, - 0x80, 0xfa, 0xbb, 0x7d, 0x4d, 0xe4, 0x90, 0x1a, 0xab, 0x62, 0xf6, 0xb4, 0x4d, 0x73, 0xa8, 0x36, 0xd9, 0x32, 0x87, - 0xde, 0xef, 0x9a, 0x44, 0x79, 0xfc, 0xe5, 0x16, 0x82, 0x23, 0x94, 0x81, 0x52, 0x8b, 0x68, 0x86, 0x83, 0x43, 0x41, - 0x05, 0x99, 0x58, 0x77, 0x57, 0x2c, 0x3f, 0xaf, 0x1a, 0xef, 0xc8, 0x05, 0x6e, 0x0d, 0x8d, 0x85, 0x3e, 0xe0, 0x69, - 0x88, 0x6f, 0x44, 0xb4, 0x27, 0xe1, 0x64, 0x26, 0x5f, 0xba, 0x2a, 0xcf, 0xdd, 0x05, 0x26, 0x74, 0xd6, 0xe1, 0x16, - 0x53, 0xff, 0xab, 0xbd, 0xb3, 0x0e, 0x9d, 0x22, 0x8c, 0x1a, 0xe6, 0x5b, 0x5f, 0x75, 0xcf, 0xc4, 0xe5, 0xee, 0x58, - 0x4e, 0xf7, 0x2b, 0x6b, 0xff, 0xab, 0x6e, 0xda, 0xb5, 0xf6, 0x36, 0xcf, 0xf6, 0x2d, 0x6d, 0xdc, 0x8f, 0x29, 0x2f, - 0xb9, 0xa3, 0x00, 0x9e, 0x44, 0x17, 0x13, 0xd5, 0xfb, 0x5c, 0xf5, 0xcb, 0xc6, 0x67, 0x6e, 0x38, 0x52, 0x91, 0xd0, - 0x81, 0x0e, 0x0f, 0xe4, 0xb3, 0x35, 0x8c, 0xce, 0x2d, 0x4f, 0x27, 0x85, 0x1d, 0xcf, 0xbd, 0xc0, 0x9d, 0xf9, 0x00, - 0xaf, 0x43, 0x77, 0xb2, 0x09, 0xd4, 0xa1, 0x07, 0x34, 0x67, 0xa6, 0x5f, 0x4f, 0x30, 0xaf, 0xad, 0xfe, 0x1c, 0xea, - 0x41, 0x5f, 0x9b, 0x13, 0xa7, 0xd6, 0x84, 0xce, 0x50, 0x03, 0xac, 0xe5, 0xd4, 0xb7, 0xe1, 0xb0, 0x91, 0xa9, 0xe6, - 0xd2, 0x3e, 0x43, 0x2a, 0x6f, 0x79, 0xb8, 0x38, 0xf2, 0xcf, 0x2a, 0xd2, 0x37, 0x49, 0x17, 0x4f, 0x95, 0x4f, 0x1e, - 0xd2, 0x90, 0xda, 0x0f, 0x2f, 0x44, 0x1b, 0x80, 0x8b, 0x38, 0xba, 0xfc, 0x26, 0xbd, 0x12, 0xfb, 0x52, 0xdf, 0x62, - 0xda, 0x99, 0x7a, 0xe1, 0xa4, 0x5e, 0x30, 0x37, 0xf9, 0x6d, 0xd3, 0xbd, 0x78, 0xc9, 0x2e, 0xab, 0x8a, 0x20, 0x09, - 0x96, 0xec, 0x3a, 0x4d, 0x92, 0x53, 0x25, 0xf0, 0xf4, 0xa7, 0x11, 0x5c, 0x3d, 0x13, 0x51, 0x29, 0xab, 0x01, 0x85, - 0x46, 0x14, 0x09, 0x45, 0x6b, 0xff, 0x36, 0xf6, 0x83, 0x65, 0x25, 0x32, 0x30, 0x51, 0x6f, 0x50, 0x6c, 0xe4, 0xa0, - 0x9d, 0x2f, 0x8d, 0xd4, 0x7d, 0x46, 0xf9, 0xac, 0x46, 0x7b, 0x69, 0xa5, 0x86, 0x94, 0x88, 0x76, 0x06, 0x6c, 0x46, - 0xc9, 0x85, 0x42, 0x83, 0xe6, 0x24, 0xfe, 0x40, 0x27, 0x03, 0x45, 0x27, 0xd4, 0xc8, 0x50, 0x67, 0x9b, 0x76, 0x4a, - 0xb9, 0x11, 0x68, 0xd7, 0x95, 0xaa, 0x72, 0x7d, 0xcc, 0x52, 0xbf, 0xe8, 0x5a, 0xfd, 0x5f, 0xf3, 0x34, 0x19, 0x13, - 0xcf, 0xe8, 0x5b, 0x23, 0xb4, 0x12, 0xe4, 0x5e, 0x7a, 0x79, 0x2f, 0x22, 0x2d, 0x9e, 0xf4, 0x49, 0x4d, 0xc5, 0x43, - 0x4b, 0xd2, 0xe0, 0x70, 0x59, 0x4b, 0x1a, 0xbc, 0x33, 0xd8, 0x11, 0x0b, 0xbd, 0x5c, 0x0a, 0xc7, 0x43, 0x93, 0xde, - 0xa6, 0x78, 0xe3, 0x62, 0xf6, 0xae, 0xd0, 0x2a, 0xe4, 0x96, 0x10, 0x2b, 0xb2, 0x2b, 0x75, 0xea, 0xae, 0x77, 0x11, - 0x40, 0x8b, 0xd8, 0xc0, 0x1f, 0x68, 0x8d, 0xac, 0x4a, 0x27, 0x83, 0x1a, 0x5d, 0xe8, 0x27, 0xe8, 0xfa, 0x13, 0x31, - 0xda, 0xee, 0xd0, 0x0d, 0xf6, 0xfd, 0x1c, 0xd8, 0xaa, 0x7d, 0x84, 0xa7, 0xc2, 0x88, 0x29, 0x43, 0x94, 0x7f, 0xdf, - 0x8e, 0x64, 0x53, 0x68, 0xb3, 0xc6, 0xbc, 0x35, 0xb5, 0x31, 0x11, 0xcc, 0x94, 0x68, 0x2f, 0x31, 0x0c, 0x98, 0xa6, - 0xcb, 0x9a, 0xe3, 0x4a, 0x53, 0x71, 0x64, 0xa8, 0xb0, 0x94, 0x38, 0xaf, 0xa0, 0xf5, 0x16, 0xeb, 0x6b, 0x6d, 0x4a, - 0x32, 0x6d, 0x61, 0x2e, 0x21, 0x1e, 0x84, 0xb7, 0x31, 0x72, 0x23, 0xc2, 0x4e, 0x82, 0x94, 0x37, 0x92, 0x9d, 0x60, - 0x9b, 0x5b, 0xe8, 0x5e, 0x8b, 0x42, 0x1d, 0x89, 0x50, 0xe0, 0x4a, 0xc1, 0x68, 0x04, 0x09, 0xca, 0x2b, 0xee, 0x69, - 0xf3, 0x2f, 0x6d, 0x10, 0x2b, 0xe4, 0x4b, 0x02, 0x4a, 0xb9, 0x16, 0x1a, 0x17, 0x20, 0xf3, 0x04, 0x67, 0xe2, 0x20, - 0x0a, 0xb2, 0xc9, 0xec, 0x43, 0x90, 0x05, 0xe7, 0xb9, 0xbd, 0xe2, 0x35, 0x0a, 0xe0, 0x38, 0x25, 0x5d, 0x3f, 0x95, - 0x27, 0xa9, 0x7a, 0x2b, 0x05, 0x20, 0xa6, 0x3e, 0x27, 0xcb, 0xbc, 0x48, 0xcf, 0x2b, 0x9d, 0x2e, 0xb3, 0x98, 0x3e, - 0xae, 0xf9, 0x9c, 0x6e, 0x62, 0x60, 0x53, 0xe9, 0x42, 0xea, 0xa5, 0xa2, 0x11, 0x69, 0x2e, 0x62, 0x4c, 0x7d, 0x30, - 0xa8, 0x4c, 0x3d, 0xf7, 0x77, 0x07, 0xdb, 0xa3, 0xb7, 0xb0, 0xb0, 0xdd, 0x04, 0xd0, 0xcd, 0x2c, 0x4a, 0x6a, 0xa6, - 0x9c, 0x6c, 0x12, 0x40, 0x3e, 0x9e, 0x00, 0xda, 0xb7, 0xe0, 0xf3, 0x55, 0x5d, 0x3c, 0x10, 0xd9, 0x70, 0x9a, 0x33, - 0xa0, 0xa9, 0xb9, 0x0f, 0xcf, 0x4a, 0xa2, 0x2b, 0xe8, 0x2a, 0xd3, 0x26, 0x00, 0xca, 0x76, 0x01, 0x7a, 0x1b, 0x02, - 0xe3, 0x8a, 0xd3, 0xb6, 0xe1, 0xb5, 0xee, 0x50, 0xef, 0x7c, 0x6a, 0x7a, 0x14, 0xa5, 0xd2, 0x65, 0xa9, 0xd1, 0x69, - 0xca, 0x77, 0x66, 0xac, 0xa7, 0x86, 0x39, 0x29, 0x6c, 0xd1, 0x77, 0x6e, 0xf4, 0xdd, 0x1c, 0xae, 0x32, 0xdb, 0x41, - 0xef, 0x35, 0x1c, 0x06, 0xcb, 0x5b, 0xe4, 0x5b, 0xdd, 0x44, 0xe9, 0x9e, 0x2d, 0xd1, 0xac, 0x98, 0x64, 0x4b, 0xde, - 0x72, 0xe9, 0xa2, 0x52, 0xd0, 0x5b, 0x2c, 0x8d, 0x83, 0xfb, 0x3c, 0xad, 0x30, 0x2c, 0xb1, 0x38, 0x2d, 0x2c, 0x25, - 0x64, 0x4e, 0x45, 0x4a, 0x09, 0x3d, 0xd6, 0xf0, 0x14, 0xa6, 0x17, 0x78, 0x30, 0x87, 0x5a, 0x35, 0x2f, 0xb0, 0x67, - 0x85, 0xf3, 0x0c, 0x1d, 0xbd, 0x64, 0x4d, 0x09, 0x81, 0xbf, 0x8f, 0x39, 0xa8, 0x6b, 0x8f, 0xf9, 0x1b, 0xba, 0xfc, - 0x3f, 0x67, 0xbe, 0x65, 0xd0, 0xad, 0xe7, 0x74, 0x8d, 0xa0, 0xd0, 0x80, 0x99, 0xef, 0x53, 0xd3, 0xd5, 0xc5, 0x90, - 0xf6, 0xc6, 0xfd, 0xc9, 0x2c, 0x9e, 0x87, 0xef, 0xd2, 0x30, 0x42, 0x91, 0x19, 0x59, 0x83, 0x02, 0xd7, 0x5f, 0xe1, - 0xf0, 0xd0, 0x88, 0xb1, 0xc2, 0xf1, 0x7d, 0x1f, 0xa3, 0x6c, 0x18, 0xad, 0xbe, 0xfd, 0x30, 0x9d, 0x2c, 0x31, 0xc2, - 0x86, 0x90, 0x9f, 0x88, 0x78, 0x1b, 0xb6, 0x60, 0xbf, 0xd0, 0x6d, 0x2e, 0x37, 0x7d, 0xce, 0xbf, 0x8f, 0xdd, 0xef, - 0x29, 0xf0, 0x4b, 0xb0, 0x40, 0xb9, 0xc7, 0x73, 0xec, 0x9b, 0xc2, 0xf6, 0x46, 0x94, 0x2c, 0xe9, 0x39, 0x46, 0x47, - 0x49, 0x0a, 0xdf, 0xe2, 0xd0, 0x14, 0x32, 0xa2, 0x08, 0x33, 0x98, 0xbd, 0x53, 0x58, 0xd0, 0xcf, 0x23, 0xe9, 0x33, - 0xdf, 0x0b, 0x28, 0x87, 0x34, 0x90, 0x4c, 0xc5, 0xd8, 0xea, 0x0d, 0xfa, 0xc3, 0xad, 0x5d, 0xc4, 0xdb, 0xd6, 0x00, - 0x08, 0x04, 0xab, 0xcc, 0x17, 0x41, 0xe2, 0x02, 0x7f, 0xa7, 0xda, 0xa0, 0x8f, 0x4b, 0xab, 0xfb, 0x73, 0x66, 0x28, - 0xde, 0x51, 0x73, 0x72, 0x9d, 0x02, 0xc7, 0x00, 0x7b, 0xec, 0xa0, 0xa4, 0x6c, 0x43, 0xd0, 0x93, 0x02, 0xb9, 0xf9, - 0xac, 0xfd, 0x93, 0xc8, 0x0b, 0x91, 0x1d, 0x01, 0x28, 0x94, 0xc6, 0xc3, 0x24, 0x5e, 0xb3, 0x22, 0xf7, 0x43, 0x16, - 0x21, 0xcf, 0xbc, 0xa1, 0x4d, 0x8f, 0xb4, 0x42, 0xa2, 0x5a, 0x05, 0xdd, 0xc8, 0x5f, 0x27, 0xc0, 0x6f, 0x43, 0xb5, - 0xea, 0x9b, 0x4e, 0x7e, 0x9d, 0x14, 0xc1, 0x55, 0xdf, 0x92, 0xd6, 0x84, 0x91, 0xa9, 0x7a, 0xc2, 0xe8, 0x09, 0x78, - 0x05, 0xd0, 0x80, 0xb8, 0x61, 0x66, 0x32, 0x8e, 0x3c, 0xf4, 0x08, 0xac, 0xfa, 0x40, 0xc2, 0xe8, 0x95, 0x4b, 0x92, - 0x79, 0x99, 0x72, 0xc5, 0xea, 0xe5, 0x8d, 0x86, 0x94, 0x57, 0x5b, 0xde, 0x74, 0xeb, 0x53, 0x6f, 0x5a, 0xbc, 0x02, - 0x8f, 0x53, 0x74, 0x8b, 0x7c, 0xf8, 0xb0, 0x2a, 0xa8, 0x4c, 0xa4, 0x8a, 0xb8, 0x51, 0x5c, 0x92, 0x7f, 0xbb, 0xb1, - 0x36, 0x0c, 0x72, 0xf3, 0xdb, 0x17, 0x50, 0x54, 0x32, 0x58, 0xdc, 0xd6, 0x25, 0xaa, 0xeb, 0x6e, 0x8c, 0xe0, 0xbd, - 0x56, 0xbd, 0xad, 0x43, 0x0a, 0xb6, 0x7c, 0xd4, 0x89, 0x71, 0x2d, 0x68, 0x57, 0xfa, 0xac, 0xc6, 0x55, 0x32, 0x1a, - 0x54, 0x9b, 0xac, 0x01, 0x4b, 0x1b, 0x29, 0x2a, 0x72, 0x0c, 0x8b, 0x21, 0x39, 0xf8, 0x89, 0x4c, 0xc4, 0x7e, 0x95, - 0xda, 0x28, 0x4d, 0xbb, 0xb9, 0xa9, 0xae, 0x40, 0xde, 0xbe, 0x30, 0x50, 0x5c, 0x4a, 0x53, 0x03, 0x11, 0x7a, 0x90, - 0x34, 0x52, 0x5e, 0xe4, 0xef, 0x3f, 0x47, 0x1d, 0x22, 0xfa, 0x7e, 0xc3, 0x69, 0x6e, 0x79, 0x31, 0x74, 0x08, 0xf3, - 0xbe, 0xbc, 0x8a, 0xf3, 0x22, 0xf7, 0x5e, 0x85, 0x64, 0x08, 0x05, 0x05, 0xde, 0x3b, 0xcc, 0x2f, 0x98, 0xd3, 0x73, - 0xee, 0x7d, 0x0c, 0xdd, 0x20, 0x0c, 0xa9, 0xfc, 0x45, 0x86, 0x8f, 0xcf, 0x31, 0xca, 0x25, 0xdd, 0x04, 0xef, 0x38, - 0x45, 0x7b, 0x35, 0xcc, 0xee, 0x55, 0x44, 0x18, 0x53, 0xd4, 0xbb, 0x4a, 0x5c, 0x8a, 0x59, 0x47, 0xd5, 0x7f, 0xcc, - 0x48, 0x28, 0xc4, 0xcd, 0xfc, 0x94, 0xa8, 0x1f, 0x5e, 0xb1, 0xc4, 0x76, 0x9e, 0x7d, 0x78, 0x2d, 0x97, 0xd4, 0xbb, - 0x4a, 0x5d, 0x71, 0xb5, 0x09, 0x6d, 0x51, 0x94, 0x1e, 0xef, 0x7c, 0xe9, 0x1e, 0x07, 0x8b, 0xd8, 0x5b, 0x61, 0xfc, - 0x89, 0x0f, 0xaf, 0x9f, 0xb3, 0x85, 0xc9, 0xeb, 0x18, 0x15, 0x07, 0xf0, 0xfb, 0x6d, 0x1a, 0x2e, 0xa1, 0xd6, 0x75, - 0x4a, 0xa0, 0x15, 0x0a, 0x7e, 0x20, 0x73, 0xaf, 0x8f, 0x19, 0xbe, 0x7f, 0x85, 0xb4, 0xa5, 0x37, 0x59, 0xe2, 0x9c, - 0xf8, 0x79, 0xbe, 0xa4, 0x49, 0x19, 0xbd, 0xe6, 0xde, 0xdf, 0xc2, 0xd2, 0x90, 0x56, 0xfd, 0x23, 0x33, 0xa1, 0x9d, - 0x21, 0xe0, 0xb9, 0x02, 0x38, 0xf2, 0xd9, 0x53, 0xa2, 0x1d, 0xcb, 0xfb, 0xaa, 0x73, 0x75, 0x3e, 0x87, 0x49, 0xd1, - 0x0b, 0x9f, 0xec, 0x82, 0xbc, 0xcd, 0xcd, 0xcb, 0xcb, 0xcb, 0xfe, 0xe5, 0x76, 0x3f, 0xcd, 0xce, 0x36, 0x87, 0x5f, - 0x7f, 0xfd, 0xf5, 0x26, 0xbd, 0xb5, 0xbe, 0xaa, 0xbb, 0xbd, 0x17, 0x4e, 0xd4, 0xf5, 0x2d, 0x8a, 0xd8, 0xfd, 0x15, - 0xb2, 0x28, 0xa8, 0x85, 0x03, 0xde, 0xe4, 0x2b, 0x81, 0x74, 0xbe, 0xda, 0x03, 0xf8, 0xc3, 0xed, 0xb7, 0xb5, 0x0c, - 0x68, 0x74, 0xb0, 0x89, 0x12, 0xa8, 0xaf, 0xba, 0x51, 0xd7, 0xda, 0xb7, 0xba, 0x31, 0x32, 0x34, 0x50, 0xb0, 0x6f, - 0x19, 0x06, 0xb6, 0x15, 0x12, 0x51, 0x07, 0x71, 0xb1, 0x36, 0xcf, 0x5c, 0xeb, 0x2b, 0xcb, 0xd1, 0x25, 0x5f, 0x62, - 0xc9, 0x97, 0x5b, 0xbb, 0x66, 0xd9, 0x17, 0x5c, 0xb6, 0x6d, 0x96, 0xed, 0x51, 0xd9, 0xf6, 0x73, 0xb3, 0x6c, 0x9f, - 0xcb, 0x5e, 0x9a, 0x65, 0x7f, 0xcf, 0xbb, 0x58, 0xda, 0x31, 0xad, 0xff, 0x8e, 0x8d, 0xd1, 0x10, 0x16, 0xf2, 0xe2, - 0xf3, 0xe0, 0x2c, 0xc2, 0x41, 0x77, 0x61, 0x9e, 0xae, 0xd5, 0xa5, 0xf1, 0x1a, 0x46, 0x1e, 0xc6, 0x07, 0x5f, 0x2d, - 0xb3, 0xb9, 0x0d, 0x93, 0xa5, 0x46, 0x60, 0x99, 0x9c, 0xaf, 0x04, 0x4a, 0xbb, 0x48, 0xfc, 0x95, 0xa5, 0x53, 0xb3, - 0xf6, 0x54, 0xc2, 0x34, 0x53, 0x1a, 0x57, 0xba, 0x7f, 0xcd, 0xda, 0xab, 0x11, 0x97, 0xc8, 0x6e, 0xba, 0x50, 0xeb, - 0x03, 0x7a, 0x27, 0xe0, 0xa0, 0x3c, 0xeb, 0x22, 0xc8, 0xec, 0x5e, 0x0f, 0xc6, 0xe6, 0xa0, 0x5d, 0xe6, 0x02, 0xd0, - 0x13, 0x50, 0x25, 0x69, 0x8f, 0x1f, 0x2d, 0xce, 0x04, 0x66, 0x51, 0x28, 0x23, 0xfc, 0x07, 0xbe, 0x7d, 0x00, 0xdf, - 0x5a, 0xbd, 0xcb, 0xe8, 0xf4, 0x73, 0x5c, 0xf4, 0x58, 0xb4, 0x78, 0x91, 0xb8, 0xf8, 0x80, 0x7f, 0x75, 0xd7, 0xde, - 0x5f, 0xd1, 0x8d, 0xbb, 0xaa, 0x61, 0x7f, 0x90, 0x6a, 0x12, 0xf5, 0x41, 0x0a, 0x28, 0x7e, 0x54, 0x43, 0xe8, 0x1f, - 0x52, 0x07, 0x30, 0x7f, 0xd7, 0xea, 0x59, 0x5d, 0xc0, 0xea, 0x1f, 0x52, 0x00, 0xd9, 0x86, 0xd3, 0x7c, 0x6a, 0x6e, - 0xf3, 0x38, 0xee, 0xa2, 0x6f, 0x0a, 0xd1, 0x23, 0x9b, 0xff, 0x75, 0xd8, 0x23, 0xe1, 0x61, 0xf7, 0xc1, 0x26, 0x50, - 0x57, 0x8b, 0x2b, 0xf2, 0xe8, 0xf4, 0xac, 0x38, 0x99, 0x45, 0x59, 0x5c, 0x18, 0x47, 0xe5, 0x6a, 0x59, 0xf7, 0xf2, - 0x58, 0x8b, 0x9b, 0x01, 0x37, 0x5a, 0x8c, 0xe7, 0x50, 0xf1, 0x46, 0xb2, 0xa7, 0xbc, 0x2a, 0x21, 0x15, 0x86, 0xbc, - 0x76, 0x0e, 0x07, 0x7c, 0x6f, 0xa3, 0xd7, 0x83, 0x43, 0xae, 0xd5, 0xb9, 0xc0, 0x33, 0xf6, 0x7a, 0xc0, 0x78, 0x2b, - 0x7e, 0x08, 0xd0, 0xb9, 0xe2, 0x19, 0x81, 0x43, 0x80, 0xeb, 0x97, 0xbb, 0x28, 0x1e, 0x4b, 0x85, 0xf8, 0x4b, 0x04, - 0x97, 0xe9, 0x62, 0xe8, 0x23, 0x96, 0x80, 0xc9, 0xb0, 0x32, 0x5d, 0x4c, 0x55, 0x0e, 0xd4, 0xf3, 0x35, 0x12, 0x8f, - 0x48, 0x31, 0xf7, 0x89, 0x70, 0xc0, 0x88, 0x25, 0x16, 0xed, 0x1d, 0x30, 0xe2, 0xa2, 0x91, 0x67, 0x98, 0x04, 0x80, - 0x1e, 0x1d, 0xd9, 0x0a, 0x15, 0x89, 0xdc, 0x8d, 0x28, 0x88, 0x8b, 0xc6, 0x17, 0x49, 0x6d, 0x73, 0x66, 0xe4, 0x60, - 0xe6, 0x4c, 0x90, 0x0c, 0x91, 0x61, 0xf8, 0x90, 0x3f, 0x47, 0xa5, 0x87, 0xd2, 0x3b, 0x11, 0x15, 0x7c, 0x1d, 0x69, - 0x12, 0xea, 0x02, 0x59, 0x4f, 0x44, 0x04, 0xd7, 0x91, 0x20, 0x01, 0xfa, 0x45, 0x06, 0x00, 0x2d, 0x0a, 0x3f, 0x01, - 0x26, 0xc8, 0xc5, 0x82, 0x7e, 0x48, 0x81, 0xd6, 0xbe, 0xb6, 0xb5, 0x3d, 0xd7, 0x8a, 0xcb, 0xbf, 0xfb, 0xf4, 0xf6, - 0x8d, 0x87, 0x22, 0xc7, 0x52, 0x42, 0x7a, 0x68, 0x86, 0xcc, 0x59, 0x8d, 0x8c, 0x57, 0xe6, 0xc5, 0xbe, 0x8e, 0x14, - 0xf6, 0x78, 0xf8, 0x10, 0xfb, 0x76, 0xaf, 0xa3, 0xf1, 0x75, 0xd4, 0xd7, 0xcd, 0x91, 0xba, 0x42, 0x7f, 0xfd, 0x79, - 0x69, 0x1a, 0x21, 0xdd, 0xbe, 0xcf, 0x6e, 0x54, 0xd9, 0x1f, 0xe1, 0x60, 0x08, 0x04, 0xa3, 0x10, 0x4a, 0x62, 0x16, - 0x12, 0x9f, 0x05, 0x0c, 0x5e, 0x47, 0x1c, 0xab, 0x11, 0x51, 0x6e, 0xbc, 0xb2, 0xf8, 0x1e, 0x4e, 0x81, 0x58, 0x72, - 0xb3, 0x06, 0xfb, 0xc1, 0xd1, 0x86, 0xf9, 0x2a, 0xfc, 0x56, 0x8e, 0xdb, 0xcf, 0x87, 0x4a, 0x3b, 0x88, 0x76, 0xd0, - 0x18, 0x37, 0x89, 0x32, 0x9c, 0x8a, 0x0f, 0x53, 0xa7, 0x2c, 0x21, 0x14, 0x4c, 0x8f, 0x28, 0x40, 0x23, 0x76, 0x41, - 0xcd, 0xca, 0x92, 0xb9, 0x2a, 0x6d, 0xa9, 0xc2, 0xcc, 0x10, 0x20, 0x41, 0x8e, 0x81, 0x9f, 0xfb, 0x3f, 0x66, 0xe4, - 0x59, 0x3e, 0x4a, 0xda, 0xc2, 0x0b, 0x91, 0x04, 0x4b, 0x4f, 0xbd, 0x35, 0x02, 0x51, 0xeb, 0x87, 0x06, 0xab, 0x2f, - 0xe2, 0xfa, 0x45, 0x21, 0x60, 0xa9, 0x48, 0x98, 0x50, 0x08, 0x3a, 0x3f, 0x35, 0x15, 0x13, 0x99, 0xff, 0x19, 0xe7, - 0x55, 0xb7, 0xd1, 0xf7, 0xe1, 0x5a, 0xf2, 0x65, 0x60, 0xd1, 0x71, 0x54, 0x92, 0xe0, 0x9a, 0x15, 0x0a, 0x52, 0x7b, - 0x1b, 0xdc, 0x41, 0x91, 0x2b, 0xdd, 0x1e, 0x79, 0xbf, 0x15, 0xc1, 0xd9, 0x3b, 0xf2, 0xed, 0x54, 0x8f, 0xc0, 0x39, - 0xfe, 0x08, 0x48, 0x37, 0x7b, 0x1e, 0x60, 0xa6, 0x15, 0x15, 0xa7, 0x17, 0xfb, 0x39, 0xf8, 0xf0, 0xec, 0x1d, 0xfa, - 0x51, 0xd2, 0xf3, 0x4f, 0xdf, 0xc2, 0x6d, 0x1b, 0x05, 0xe3, 0x4c, 0x7e, 0xa8, 0x6a, 0x60, 0xaa, 0x16, 0x5d, 0xa6, - 0xde, 0x8f, 0x83, 0x2a, 0xf9, 0x2e, 0xc8, 0x7a, 0x37, 0xab, 0x46, 0x92, 0x92, 0xd4, 0x3e, 0x1a, 0x10, 0x08, 0x04, - 0xc2, 0x94, 0x3d, 0x90, 0x19, 0x58, 0x66, 0x12, 0xfb, 0x66, 0x86, 0xc0, 0xd7, 0x8d, 0x94, 0x6a, 0x11, 0xc7, 0xa2, - 0x11, 0x4b, 0x0e, 0x94, 0x2d, 0x1b, 0x16, 0x7d, 0xa4, 0x02, 0xa5, 0xb0, 0x92, 0xef, 0x29, 0x06, 0x34, 0xf1, 0x06, - 0x42, 0xf6, 0xe0, 0xc5, 0xae, 0xae, 0x5e, 0xb1, 0xf8, 0x3e, 0x80, 0x1b, 0xa3, 0x2c, 0x2f, 0x7b, 0xf8, 0xd7, 0x12, - 0x06, 0xe0, 0x6e, 0x44, 0x24, 0x5f, 0x21, 0x2f, 0x3a, 0x1f, 0x31, 0x71, 0x89, 0x30, 0x37, 0x91, 0x28, 0xc7, 0xb3, - 0x2b, 0x4a, 0xc5, 0xad, 0xd6, 0x3e, 0x13, 0x1b, 0x05, 0x6a, 0xe5, 0xea, 0xf6, 0x78, 0x14, 0xfe, 0x53, 0x48, 0x2b, - 0x54, 0x86, 0x3d, 0x9d, 0x5f, 0xf8, 0x90, 0x86, 0x63, 0xb9, 0xd6, 0x39, 0x6c, 0x35, 0xfc, 0x11, 0x6a, 0x34, 0x57, - 0x0a, 0xfb, 0x94, 0x9c, 0x4f, 0xc7, 0xd6, 0xa2, 0x78, 0x5a, 0x18, 0x1c, 0xb8, 0x1a, 0x93, 0x33, 0x6a, 0x8f, 0xc9, - 0x39, 0xfa, 0xcc, 0xe1, 0xbe, 0xad, 0xe3, 0x7c, 0x16, 0xc0, 0x14, 0x30, 0x36, 0xa5, 0x65, 0x96, 0x52, 0xab, 0x46, - 0x01, 0x10, 0x95, 0x93, 0xcf, 0x64, 0xb5, 0x11, 0x5a, 0x48, 0x55, 0x8e, 0xa4, 0xe5, 0x1e, 0x07, 0x4d, 0xd5, 0xad, - 0x70, 0x01, 0xdc, 0x2c, 0xa0, 0x43, 0x0f, 0xa8, 0xd4, 0x5e, 0xe1, 0x2c, 0x3c, 0x0b, 0x20, 0x6c, 0x82, 0x20, 0x7d, - 0xee, 0xff, 0x12, 0x8b, 0xd8, 0xeb, 0xc0, 0x7b, 0xa2, 0x80, 0x49, 0x44, 0x51, 0xa6, 0x4e, 0x7d, 0xd8, 0x79, 0xa1, - 0x76, 0x04, 0x04, 0xa0, 0x5f, 0xfe, 0x03, 0xfb, 0x7e, 0x8e, 0xa3, 0xb0, 0x2b, 0xc1, 0x0b, 0x45, 0xf0, 0xc3, 0x50, - 0x1d, 0x39, 0x23, 0x90, 0xa1, 0xf6, 0x3e, 0x2b, 0xd5, 0x55, 0x7f, 0x3e, 0xc3, 0x58, 0xaf, 0xa1, 0xf4, 0x29, 0xb4, - 0x27, 0x8e, 0xcc, 0x95, 0xac, 0x94, 0x95, 0xea, 0x42, 0xc9, 0x71, 0xba, 0x33, 0xdf, 0x18, 0xe1, 0x68, 0x0e, 0x28, - 0x70, 0xd6, 0xe7, 0xda, 0x70, 0x28, 0xe5, 0xa3, 0x3f, 0x77, 0xdf, 0x8b, 0x14, 0xd6, 0xc6, 0x7a, 0xc0, 0x0c, 0x84, - 0xba, 0xaa, 0x65, 0x1e, 0x38, 0x01, 0xdc, 0x69, 0x15, 0xa1, 0x52, 0x27, 0xdf, 0x36, 0x95, 0xa8, 0x74, 0x24, 0xf1, - 0xa8, 0x4c, 0xf0, 0x66, 0x57, 0x25, 0x3b, 0x2b, 0xcb, 0x31, 0x0c, 0x77, 0x0d, 0x2d, 0xf6, 0xc4, 0xa9, 0x86, 0xb7, - 0xe8, 0x4c, 0x50, 0xd4, 0xc1, 0xdd, 0xc1, 0xa4, 0xa5, 0xa1, 0x8b, 0xc9, 0x28, 0xc1, 0x32, 0xd4, 0x4c, 0xaa, 0x26, - 0x32, 0x29, 0x54, 0xde, 0x1c, 0x11, 0x5a, 0xa2, 0xd0, 0x04, 0x68, 0xf6, 0x7a, 0xd5, 0xe5, 0xaa, 0x71, 0x77, 0xfc, - 0x12, 0x7d, 0x9c, 0xc6, 0x6d, 0x0d, 0xc9, 0x83, 0x0d, 0x27, 0x14, 0x56, 0xde, 0x13, 0xe1, 0x52, 0xd1, 0x98, 0xb8, - 0x4d, 0x8b, 0x8c, 0xf9, 0x91, 0x29, 0xb7, 0xb0, 0x08, 0x47, 0x5a, 0x5f, 0x37, 0xb1, 0x41, 0xe4, 0x27, 0x2c, 0x21, - 0x81, 0xde, 0xce, 0xfa, 0xd6, 0x54, 0xeb, 0x21, 0x10, 0xc7, 0x05, 0x45, 0x90, 0x4d, 0x4b, 0x3a, 0x27, 0xf8, 0x42, - 0xa0, 0x89, 0x12, 0x65, 0x33, 0xcd, 0x89, 0xb2, 0x22, 0xdb, 0xb0, 0x75, 0xe5, 0x25, 0x06, 0xe4, 0x34, 0x27, 0x4b, - 0x4e, 0x8e, 0xa7, 0x89, 0x32, 0xb1, 0x35, 0x63, 0x93, 0x9b, 0xa1, 0x21, 0x99, 0x25, 0x9f, 0x2c, 0x6f, 0xa2, 0x71, - 0x9a, 0x52, 0x39, 0x48, 0x17, 0x30, 0x4b, 0x28, 0xdf, 0xad, 0xb2, 0x72, 0x86, 0x56, 0x22, 0x2c, 0xb3, 0xbe, 0x9f, - 0x68, 0xbf, 0x56, 0x2f, 0x6b, 0x33, 0xc5, 0x32, 0x2a, 0xd9, 0x64, 0x2f, 0x24, 0x9f, 0x49, 0x24, 0xda, 0x68, 0x42, - 0x82, 0xb0, 0x96, 0xb6, 0x87, 0x75, 0x68, 0x80, 0x33, 0x35, 0x12, 0xc0, 0xb7, 0x9e, 0x65, 0xbc, 0x45, 0x62, 0xbe, - 0x9c, 0x8c, 0x4b, 0x0c, 0x08, 0x4b, 0xc4, 0x25, 0x45, 0x73, 0x5e, 0x03, 0x92, 0x1a, 0x7b, 0x5a, 0x33, 0xa3, 0x6a, - 0xe9, 0x88, 0x20, 0x27, 0xfa, 0x4f, 0x9e, 0xa7, 0x02, 0xd8, 0xc0, 0x5e, 0x23, 0x14, 0xc0, 0x7d, 0xc6, 0x0b, 0x7c, - 0x73, 0xf3, 0x00, 0xd0, 0x67, 0x9d, 0x6c, 0x08, 0x51, 0x5a, 0x21, 0xf3, 0x84, 0x60, 0x67, 0xaf, 0xe9, 0xbe, 0xd0, - 0x38, 0xdd, 0x10, 0x3d, 0x08, 0x2b, 0x03, 0x9c, 0xe8, 0xd3, 0x15, 0x2f, 0x01, 0x96, 0x01, 0xfd, 0x28, 0x9c, 0x9d, - 0xb8, 0x78, 0x5a, 0x3f, 0x97, 0x53, 0x35, 0x07, 0x91, 0x4b, 0xad, 0x6d, 0x79, 0x70, 0x78, 0xd5, 0x29, 0x2e, 0x7c, - 0x01, 0x13, 0xa5, 0xf5, 0x10, 0x5b, 0x72, 0x2c, 0xcb, 0xd1, 0x82, 0x4e, 0xcb, 0x58, 0x04, 0xba, 0x4f, 0x89, 0xa1, - 0xc7, 0xf8, 0xe0, 0xf6, 0xc2, 0xf1, 0xa6, 0x34, 0x6c, 0x7f, 0x01, 0x98, 0x7d, 0xbe, 0xae, 0xda, 0x5c, 0x26, 0xc8, - 0x53, 0xd0, 0x77, 0x6e, 0x82, 0x63, 0x01, 0xdb, 0xcc, 0x22, 0x8c, 0x6b, 0x6e, 0x34, 0x30, 0x69, 0x39, 0x82, 0x3a, - 0xdf, 0xa7, 0xb9, 0x88, 0xae, 0xdc, 0x0a, 0x77, 0xed, 0x7e, 0x41, 0xdb, 0x95, 0x2f, 0xd0, 0x36, 0x6a, 0x25, 0x4d, - 0xb3, 0x12, 0x58, 0x61, 0xb6, 0xb0, 0x26, 0x12, 0x72, 0x86, 0x3e, 0x98, 0xcd, 0xa1, 0x8e, 0x5e, 0xb6, 0x00, 0x61, - 0x73, 0x8a, 0x06, 0x8d, 0x30, 0x60, 0xd2, 0x60, 0x22, 0x49, 0x85, 0xa5, 0x5b, 0x3d, 0x0e, 0xde, 0xdc, 0x95, 0x47, - 0x06, 0x56, 0xde, 0x84, 0x14, 0x5e, 0x88, 0xe6, 0xc6, 0xa3, 0xbc, 0x62, 0x4a, 0x48, 0x21, 0x2b, 0x52, 0x1d, 0xa8, - 0x56, 0x85, 0x96, 0xaa, 0x06, 0x01, 0xb7, 0x8d, 0x2a, 0x6e, 0xe0, 0xa2, 0xe8, 0xc3, 0x93, 0xd4, 0x88, 0x06, 0xa3, - 0xcd, 0x35, 0x0a, 0x1c, 0x4c, 0xdd, 0x6d, 0xd4, 0xc5, 0xd3, 0x27, 0x64, 0x5b, 0x2d, 0xc0, 0x35, 0x00, 0x80, 0xd4, - 0x0e, 0x50, 0x03, 0x12, 0xb4, 0x69, 0xdd, 0xe8, 0xdf, 0x32, 0xdb, 0xb4, 0x0b, 0xa7, 0x69, 0x64, 0x4e, 0x8a, 0x19, - 0x69, 0x8d, 0xa1, 0x52, 0x82, 0x5a, 0xf8, 0x47, 0x13, 0xee, 0x3c, 0x2d, 0x8a, 0xf2, 0xe6, 0xa6, 0x25, 0xd0, 0x51, - 0xce, 0xcd, 0x0d, 0xb5, 0x85, 0xbe, 0xec, 0x6f, 0x97, 0x6b, 0x42, 0xa0, 0x3f, 0x5f, 0xde, 0x19, 0x02, 0xfd, 0x45, - 0x7c, 0x9f, 0x10, 0xe8, 0xcf, 0x97, 0x7f, 0x76, 0x08, 0xf4, 0xb7, 0x4b, 0x23, 0x04, 0x3a, 0x2f, 0xc6, 0x5f, 0x32, - 0xdf, 0x7a, 0xff, 0xce, 0x72, 0x5f, 0xa4, 0xf0, 0xf7, 0xd5, 0x2b, 0x43, 0x98, 0xfe, 0x5d, 0x22, 0x22, 0xf9, 0x4b, - 0x59, 0x30, 0xc5, 0x6d, 0xc1, 0x57, 0xa4, 0x75, 0x32, 0x03, 0x15, 0xc5, 0x18, 0x88, 0x3e, 0xff, 0x39, 0x2e, 0x66, - 0xb6, 0xb5, 0x69, 0x39, 0x63, 0x1d, 0x12, 0xb4, 0x37, 0xac, 0x70, 0x6f, 0x3f, 0x26, 0x15, 0xa1, 0x8e, 0xca, 0x3c, - 0x80, 0x5f, 0x19, 0x22, 0x7b, 0x93, 0x43, 0xa4, 0x4f, 0xc6, 0x2a, 0xe8, 0x28, 0x54, 0x44, 0x8f, 0xa5, 0xd8, 0x88, - 0xc0, 0x79, 0x68, 0xa6, 0x84, 0xfe, 0xb0, 0x34, 0x6c, 0x8b, 0xe0, 0xdb, 0x02, 0x7d, 0xee, 0x00, 0xa1, 0x1c, 0xc7, - 0xa1, 0xa3, 0xe5, 0xa1, 0x51, 0x32, 0x81, 0x43, 0xfe, 0xe3, 0xc7, 0xd7, 0x2a, 0xf2, 0xb8, 0xcd, 0xa1, 0x97, 0x1c, - 0x4a, 0x69, 0x1c, 0x46, 0x17, 0x30, 0xfc, 0xf1, 0xc9, 0x83, 0x55, 0x6b, 0x45, 0x7e, 0xed, 0x94, 0x9b, 0x27, 0x40, - 0xc3, 0x89, 0x35, 0x80, 0xba, 0x71, 0xb9, 0xf9, 0x60, 0x05, 0x6f, 0x53, 0x0c, 0xef, 0x8d, 0xcf, 0x69, 0xf9, 0x60, - 0x95, 0xe3, 0x43, 0x54, 0x9e, 0x18, 0x81, 0xd9, 0xd4, 0x80, 0x8c, 0x39, 0x28, 0xe5, 0x95, 0x8e, 0x09, 0x7a, 0x4b, - 0xc3, 0x89, 0x6c, 0x54, 0xc7, 0xa3, 0x5a, 0x1a, 0x72, 0xbf, 0x91, 0x98, 0xba, 0xe3, 0x20, 0x1b, 0xa9, 0x17, 0x8e, - 0x42, 0x65, 0x25, 0xfe, 0x7e, 0xcb, 0xa4, 0x12, 0x47, 0xf6, 0x0c, 0xf5, 0x46, 0x86, 0x4f, 0x59, 0xa2, 0x5b, 0xe8, - 0xa1, 0x05, 0x8a, 0x9f, 0x60, 0x08, 0x54, 0xb2, 0x46, 0x6a, 0x8e, 0x38, 0xf2, 0x4f, 0xe4, 0x8c, 0x9b, 0x5d, 0xa4, - 0x0e, 0xc5, 0xc8, 0x36, 0xe7, 0x14, 0x95, 0xe3, 0x30, 0x2a, 0x80, 0x00, 0xf0, 0x81, 0x5c, 0x3d, 0x21, 0x59, 0xc4, - 0xb7, 0xf7, 0x0a, 0xba, 0x0f, 0xec, 0x64, 0x90, 0x9d, 0x11, 0xeb, 0x2f, 0xc1, 0x2d, 0x85, 0xc5, 0x8e, 0xa3, 0x5c, - 0x25, 0x56, 0x99, 0x05, 0xf9, 0xf1, 0x84, 0x33, 0x1a, 0xe5, 0x0a, 0x60, 0xe7, 0xb3, 0xf4, 0xf2, 0x18, 0xb3, 0x3b, - 0x28, 0x08, 0x1e, 0xd0, 0x02, 0x32, 0xdf, 0x24, 0xd3, 0x2e, 0x2f, 0xc5, 0xbb, 0x53, 0xe0, 0x2a, 0x3f, 0xc0, 0x59, - 0xf7, 0xf1, 0x2e, 0x08, 0xa8, 0x9e, 0xa5, 0xcb, 0x85, 0xee, 0xe4, 0x78, 0x99, 0x7c, 0x4e, 0xd2, 0xcb, 0x84, 0x61, - 0xef, 0x71, 0x74, 0x81, 0x23, 0xf2, 0x57, 0xa4, 0xb3, 0x4a, 0x00, 0x06, 0x18, 0x94, 0x38, 0xe7, 0x02, 0x80, 0x5d, - 0x12, 0xd9, 0x00, 0x5a, 0x6a, 0xb8, 0xb6, 0xba, 0x6b, 0xc2, 0xb1, 0x5c, 0xaa, 0x2c, 0x62, 0xb4, 0x84, 0x7d, 0x89, - 0xad, 0x63, 0xc4, 0x76, 0x4c, 0x17, 0x82, 0xac, 0x27, 0xb1, 0x46, 0x95, 0x88, 0x3d, 0xb0, 0x41, 0x06, 0x8d, 0xcc, - 0xa4, 0x96, 0x8c, 0x76, 0x59, 0x59, 0x26, 0x62, 0xaf, 0xc9, 0x65, 0x18, 0x15, 0xff, 0x99, 0x3e, 0x94, 0x14, 0x17, - 0x09, 0x2e, 0x0b, 0x19, 0x9d, 0x6d, 0x90, 0x2c, 0x8c, 0x7e, 0x1b, 0x3a, 0x4a, 0x91, 0x56, 0xce, 0x30, 0xcb, 0x5b, - 0xb1, 0x26, 0xfe, 0x10, 0x4d, 0xc2, 0xcc, 0x5e, 0x00, 0x38, 0x71, 0xdd, 0x63, 0xa8, 0x19, 0x65, 0xf1, 0xe4, 0x18, - 0xde, 0xc2, 0x46, 0x5e, 0x1f, 0xc9, 0x70, 0x17, 0xa2, 0xad, 0xda, 0x26, 0xae, 0xfd, 0x0e, 0x7d, 0xde, 0x39, 0x81, - 0x49, 0x6f, 0x17, 0xd8, 0x1e, 0x61, 0x2d, 0x8f, 0x03, 0x74, 0xd5, 0x33, 0xdf, 0x13, 0xfd, 0x5b, 0x4d, 0xcd, 0xad, - 0xfa, 0x39, 0xd4, 0x7b, 0x74, 0xe5, 0x51, 0xca, 0x22, 0xa8, 0x2f, 0xb3, 0x1d, 0xd8, 0x3a, 0x92, 0x37, 0x00, 0x59, - 0x46, 0x46, 0x02, 0x44, 0x73, 0x24, 0x28, 0x86, 0xbe, 0xb5, 0x17, 0x3c, 0x06, 0xc7, 0x61, 0x6e, 0x11, 0xb6, 0x8e, - 0x82, 0xb6, 0xa3, 0x94, 0x84, 0xee, 0x96, 0xca, 0xf9, 0xd5, 0x76, 0x7c, 0x0e, 0x71, 0x3a, 0x47, 0xe3, 0xbb, 0x2a, - 0x74, 0xbb, 0xde, 0x5d, 0x55, 0xfc, 0xe1, 0x2d, 0xa7, 0x94, 0xab, 0xec, 0x49, 0xdb, 0xcb, 0x11, 0x99, 0xb2, 0xd8, - 0x00, 0x48, 0xaa, 0x67, 0xdf, 0xa5, 0xdd, 0x77, 0x57, 0xe7, 0x51, 0x31, 0x4b, 0x43, 0xcf, 0xfa, 0xf6, 0xe5, 0x27, - 0x4b, 0xaa, 0xae, 0x33, 0x11, 0xb4, 0x48, 0x68, 0x73, 0xe6, 0xe9, 0x19, 0xca, 0x32, 0x37, 0xb2, 0x7e, 0xfa, 0xb9, - 0x91, 0xe5, 0xf3, 0xe4, 0xbb, 0x4f, 0x9f, 0x3e, 0x74, 0x48, 0xe1, 0xb3, 0xd1, 0x39, 0xe0, 0xe8, 0x01, 0x9d, 0x07, - 0xab, 0x4c, 0xa8, 0xd8, 0xcb, 0x13, 0x85, 0xab, 0xb2, 0x9a, 0x82, 0x5c, 0x06, 0x05, 0x34, 0xba, 0xa8, 0x2d, 0x6b, - 0xa6, 0xb5, 0xd8, 0x66, 0x65, 0xd6, 0x2e, 0x59, 0xa4, 0x3b, 0xe1, 0x9e, 0x3d, 0xd6, 0xcb, 0x63, 0xa6, 0x05, 0xbb, - 0x58, 0x73, 0xd5, 0x8a, 0xb6, 0xab, 0x96, 0x66, 0x05, 0xf0, 0x26, 0xc7, 0x74, 0xfb, 0xef, 0x75, 0xe5, 0xe4, 0x0e, - 0x33, 0xbc, 0xa8, 0xdf, 0xb6, 0x4a, 0xa8, 0x32, 0x61, 0x94, 0x2b, 0xee, 0x10, 0x0a, 0xcc, 0x00, 0x3b, 0x9b, 0x1f, - 0x4b, 0x8b, 0x11, 0xb3, 0x8c, 0x03, 0xb9, 0x21, 0x0d, 0xe4, 0xef, 0x07, 0x7d, 0x39, 0xbe, 0x4b, 0x92, 0x9b, 0xec, - 0x4d, 0x6a, 0x05, 0xe3, 0xde, 0xd0, 0x1b, 0x3a, 0x2a, 0xbf, 0x84, 0x80, 0x61, 0xdf, 0xf6, 0x5f, 0xbe, 0xfb, 0xf4, - 0xfa, 0xd3, 0xdf, 0x8e, 0x9f, 0x3f, 0xfb, 0xf4, 0xf2, 0xdb, 0xf7, 0x1f, 0x5f, 0xbf, 0x3c, 0x20, 0x0c, 0x21, 0x02, - 0x56, 0xda, 0x2b, 0x61, 0x15, 0x5d, 0x6d, 0xcb, 0x4b, 0x4a, 0xa7, 0x3a, 0x14, 0x8e, 0x18, 0x45, 0x95, 0x55, 0x93, - 0x3f, 0xbe, 0x7b, 0xf1, 0xf2, 0xd5, 0xeb, 0x77, 0x2f, 0x5f, 0xd4, 0xbf, 0xee, 0x0d, 0x61, 0xf9, 0xf5, 0xce, 0x89, - 0x0c, 0x29, 0x91, 0x5a, 0xaf, 0x16, 0xf8, 0x44, 0x5a, 0x79, 0x13, 0x3e, 0xc5, 0x78, 0x22, 0x7d, 0x96, 0xd3, 0xd3, - 0xb3, 0x11, 0xff, 0x97, 0x2f, 0x1e, 0x50, 0xa6, 0x4b, 0x9b, 0x5e, 0x09, 0x59, 0x3f, 0xae, 0x6a, 0xec, 0xf2, 0x4b, - 0x2f, 0x71, 0x55, 0x6b, 0x68, 0x03, 0x1d, 0xba, 0x9c, 0x52, 0xe1, 0x18, 0x4e, 0x50, 0x74, 0x06, 0x40, 0xc6, 0x8b, - 0xfb, 0xb5, 0x12, 0xb7, 0x72, 0x00, 0x3c, 0x1b, 0x05, 0xcb, 0x95, 0x22, 0xe0, 0x69, 0x08, 0x00, 0x18, 0x4b, 0xa0, - 0x57, 0xf5, 0x50, 0x67, 0x0b, 0xa8, 0x37, 0xec, 0x1c, 0xdd, 0xdc, 0xb4, 0x2c, 0x5a, 0x2b, 0xec, 0xf3, 0x0e, 0x63, - 0x06, 0x8a, 0x47, 0x48, 0x98, 0x23, 0x7a, 0x63, 0xdc, 0xe5, 0x4b, 0x74, 0xf7, 0x4c, 0x64, 0xfd, 0x44, 0x6b, 0x44, - 0xfd, 0x5a, 0x26, 0x96, 0xa9, 0xe2, 0xc3, 0x41, 0x0d, 0xe2, 0xca, 0x18, 0xbf, 0xb5, 0x52, 0x3e, 0x66, 0x22, 0xb6, - 0x22, 0xee, 0x14, 0xa6, 0xe3, 0x92, 0xa2, 0x5b, 0x7b, 0x8e, 0x16, 0x32, 0x95, 0xfd, 0x95, 0xeb, 0x30, 0xf7, 0x52, - 0x19, 0x26, 0x0f, 0x4d, 0x06, 0xd7, 0xd4, 0x9a, 0x79, 0x59, 0x25, 0xe0, 0x65, 0x5a, 0x5d, 0xd4, 0xbd, 0xac, 0xfa, - 0x1b, 0x8f, 0x71, 0xad, 0x0a, 0x89, 0x6c, 0xab, 0x95, 0x50, 0xb4, 0x30, 0x19, 0x73, 0xf7, 0xfd, 0x22, 0x7d, 0x93, - 0x5e, 0x4a, 0xf1, 0xf0, 0x5e, 0xd6, 0x52, 0x48, 0x77, 0xc3, 0x0b, 0xf6, 0x26, 0xfc, 0x30, 0x2c, 0xd7, 0x20, 0x81, - 0x52, 0x2f, 0xb0, 0x22, 0x4e, 0x4f, 0x98, 0x65, 0x3a, 0x06, 0x72, 0x46, 0x52, 0x67, 0x27, 0xb1, 0x4a, 0xfe, 0x5a, - 0x21, 0x2c, 0x4a, 0xb1, 0xf4, 0x66, 0xac, 0xd1, 0x96, 0x6a, 0xe2, 0x7c, 0xf8, 0x71, 0x2b, 0x75, 0xd2, 0xe7, 0x9f, - 0x11, 0xe7, 0xc2, 0x6c, 0xaf, 0x12, 0x5d, 0x45, 0x13, 0xbb, 0x6d, 0x60, 0x2c, 0x5e, 0x92, 0x53, 0xa0, 0xf0, 0xcb, - 0x04, 0xf1, 0x3f, 0x34, 0x20, 0x3e, 0x59, 0xd9, 0x29, 0x80, 0xff, 0xe1, 0xfd, 0xc1, 0x27, 0xd4, 0x5e, 0x05, 0xa4, - 0x6e, 0x5e, 0x59, 0xc2, 0x52, 0xa5, 0x87, 0xfa, 0x20, 0xcb, 0xb3, 0x82, 0x05, 0xe2, 0x63, 0xe2, 0x0b, 0x36, 0xaf, - 0x7a, 0x97, 0x97, 0x97, 0x3d, 0xb4, 0x5b, 0xed, 0x2d, 0xb3, 0x39, 0xd3, 0x80, 0xa1, 0x55, 0x4a, 0x40, 0x1e, 0xd5, - 0x00, 0x39, 0x06, 0xbd, 0x15, 0x59, 0x53, 0x0e, 0x80, 0x2e, 0x7b, 0x36, 0x9f, 0x9b, 0xc2, 0x19, 0x49, 0xaa, 0x09, - 0x79, 0x45, 0x05, 0x30, 0xd8, 0xa8, 0x63, 0xea, 0xc7, 0xf9, 0xb1, 0xb0, 0x0a, 0x08, 0x8f, 0x4f, 0xaf, 0x8f, 0x85, - 0xe6, 0x41, 0x45, 0x1d, 0x7e, 0x7e, 0xb2, 0x17, 0xc6, 0x17, 0x1d, 0xa2, 0x27, 0x7d, 0x0b, 0x5d, 0xb6, 0xe6, 0x11, - 0xf0, 0x87, 0x45, 0x9a, 0xf4, 0x00, 0x35, 0x59, 0xfb, 0x7b, 0xfc, 0x43, 0x56, 0x08, 0xf8, 0xa7, 0xd5, 0xf9, 0xcf, - 0x09, 0x4c, 0xe8, 0xb3, 0x6f, 0xc1, 0xe2, 0xf9, 0xfb, 0x35, 0xaa, 0x71, 0x50, 0x5a, 0xfb, 0x38, 0xd6, 0x0e, 0x0c, - 0x76, 0x6f, 0x93, 0xbf, 0xd8, 0xdf, 0xdb, 0x84, 0x7e, 0xf6, 0x8d, 0x04, 0x30, 0x42, 0x3b, 0xea, 0x8b, 0x40, 0x9b, - 0xca, 0x9e, 0x2c, 0xa7, 0xc8, 0x0d, 0x40, 0xbc, 0x68, 0x16, 0x17, 0x23, 0xca, 0xf0, 0x78, 0x81, 0xf9, 0x47, 0xa1, - 0xf9, 0x1c, 0x19, 0xba, 0x9b, 0x1b, 0x5b, 0x59, 0x9b, 0xce, 0x8c, 0x50, 0x6c, 0xa4, 0xcc, 0xa3, 0x2a, 0x2e, 0xc5, - 0x93, 0x71, 0x6c, 0x19, 0x30, 0x6e, 0xee, 0xb8, 0x93, 0xd2, 0xa5, 0x3c, 0x3a, 0xc1, 0x02, 0xf5, 0x8a, 0xe2, 0xd1, - 0xe0, 0x7b, 0x27, 0x98, 0x3b, 0xdb, 0x00, 0xdc, 0x8e, 0xa1, 0x59, 0xe1, 0x5b, 0x28, 0xa2, 0x01, 0xa2, 0x4a, 0x84, - 0xfa, 0x61, 0x6d, 0x07, 0x94, 0x60, 0xee, 0x36, 0x15, 0x82, 0x27, 0x28, 0x65, 0xb6, 0x34, 0xb9, 0x2e, 0xe3, 0xca, - 0x0e, 0x79, 0xf5, 0xfd, 0x92, 0xb1, 0x21, 0x37, 0xf2, 0x75, 0x5b, 0x86, 0x9a, 0x3a, 0x60, 0x4d, 0x6b, 0x78, 0x16, - 0x7d, 0xf7, 0x0c, 0xf5, 0x50, 0xe4, 0xda, 0x87, 0xb0, 0xa0, 0x47, 0x1a, 0x37, 0xe5, 0x0c, 0x28, 0xbd, 0xb4, 0xd4, - 0x61, 0x9a, 0x79, 0xd7, 0xf7, 0x81, 0x49, 0x22, 0x64, 0x06, 0xdd, 0x56, 0xcf, 0x41, 0x11, 0x9c, 0xf6, 0xf8, 0x30, - 0xc3, 0x4e, 0x87, 0xa7, 0x73, 0xb5, 0xd9, 0x7c, 0x09, 0x66, 0x41, 0x12, 0xce, 0xa3, 0x4f, 0xc1, 0xe9, 0x77, 0x54, - 0xe7, 0xc5, 0xe9, 0xfc, 0x39, 0x56, 0x80, 0x6d, 0x07, 0xce, 0x86, 0x96, 0xa9, 0x0d, 0x60, 0x97, 0x7c, 0x04, 0xea, - 0xfd, 0x4c, 0x38, 0xb1, 0x12, 0x74, 0x45, 0x5f, 0xd3, 0x60, 0x19, 0xc5, 0x32, 0x44, 0xad, 0x8e, 0x4c, 0x24, 0xf6, - 0xc1, 0xb3, 0xd9, 0x11, 0xb7, 0x16, 0xc7, 0x95, 0xca, 0x1b, 0x6c, 0x9e, 0x4c, 0x73, 0xb0, 0x8c, 0x4a, 0x3f, 0xa6, - 0x97, 0x72, 0xa4, 0x62, 0x01, 0x38, 0x10, 0xe5, 0x18, 0x3a, 0x31, 0x95, 0x3f, 0x24, 0x21, 0xe7, 0x76, 0xf1, 0x09, - 0x5a, 0xd5, 0x69, 0x9e, 0x16, 0x57, 0xf0, 0xf1, 0xa6, 0x59, 0x7b, 0xff, 0xc4, 0x7b, 0x63, 0x4c, 0x8e, 0x5a, 0x95, - 0xdc, 0xf1, 0xa1, 0xfe, 0x51, 0x1e, 0x75, 0x90, 0x17, 0x2e, 0xb1, 0x04, 0xd7, 0xa8, 0xfa, 0x49, 0x03, 0xfd, 0x60, - 0x62, 0x44, 0x8d, 0xa0, 0xf8, 0xf4, 0x48, 0xf8, 0x98, 0x3a, 0x9e, 0xda, 0x42, 0xb6, 0xbf, 0x94, 0xad, 0x9d, 0x88, - 0xbf, 0x7a, 0x49, 0x48, 0x9e, 0x1d, 0x01, 0x40, 0xc9, 0x2c, 0x9c, 0x66, 0x3d, 0x3b, 0x52, 0xc7, 0xc8, 0xca, 0x46, - 0x13, 0x6e, 0x45, 0xab, 0xb8, 0x60, 0x9b, 0xf5, 0x4f, 0x8d, 0x79, 0x03, 0xe0, 0x54, 0x0f, 0x1d, 0x31, 0x99, 0x1a, - 0xd0, 0x52, 0x03, 0x5c, 0x9f, 0x75, 0xea, 0xf0, 0x7d, 0xec, 0xfe, 0x9c, 0xba, 0xe7, 0x81, 0x7b, 0x1a, 0xb8, 0x07, - 0xc9, 0x51, 0xd9, 0xba, 0x79, 0x2a, 0x63, 0x9c, 0x1b, 0x8d, 0x6c, 0x8c, 0xb3, 0x54, 0xe5, 0x2b, 0xe2, 0xbe, 0xb0, - 0x0c, 0xf9, 0x04, 0xdc, 0x6f, 0x24, 0x13, 0xb5, 0xc9, 0xb7, 0x52, 0x42, 0xe0, 0x18, 0xcb, 0x82, 0x41, 0xc8, 0x36, - 0x84, 0x01, 0x1d, 0x7c, 0x5d, 0x64, 0xf3, 0xbf, 0x44, 0xd7, 0xc8, 0x4e, 0xc2, 0xd4, 0x17, 0x28, 0x99, 0x0a, 0xce, - 0x84, 0xa6, 0xc1, 0x45, 0xa2, 0xe6, 0x3e, 0xdd, 0xdd, 0xdc, 0x44, 0x46, 0xee, 0xb0, 0x22, 0x3d, 0x03, 0xb0, 0x6a, - 0x1b, 0x39, 0xc6, 0x54, 0x37, 0xe3, 0x8d, 0x81, 0x8c, 0x4f, 0xed, 0x94, 0xeb, 0x2e, 0x96, 0xa6, 0x00, 0xa5, 0x4e, - 0x1f, 0x01, 0x17, 0x9b, 0x50, 0x11, 0x11, 0x6e, 0xcb, 0x7b, 0xa1, 0x2f, 0x6e, 0x2f, 0x4c, 0x97, 0x00, 0x41, 0x7a, - 0x74, 0x1b, 0xb0, 0xcb, 0xd5, 0xe9, 0xf2, 0xf4, 0x74, 0xce, 0x49, 0xc1, 0x30, 0xca, 0x5a, 0x9a, 0x93, 0xf4, 0xb3, - 0x74, 0x46, 0x44, 0xa9, 0x15, 0xf5, 0xe1, 0xa3, 0x65, 0x24, 0x72, 0x0b, 0xdc, 0x41, 0x81, 0x92, 0xce, 0xe6, 0x9d, - 0xf6, 0x2d, 0xe4, 0x52, 0xa2, 0xdc, 0x1a, 0xb5, 0x90, 0x74, 0xfe, 0xa1, 0x75, 0x40, 0x2b, 0xdc, 0x81, 0x69, 0x75, - 0x9e, 0xf3, 0xd9, 0xb5, 0x5c, 0x8b, 0x0d, 0xbc, 0x44, 0x0e, 0x39, 0xf8, 0xfd, 0x22, 0x0e, 0xce, 0x92, 0x34, 0x87, - 0x43, 0x61, 0x1d, 0x8d, 0x5e, 0xc4, 0xf6, 0xe1, 0x79, 0x61, 0x3b, 0x47, 0xee, 0xb7, 0x66, 0xb6, 0x2f, 0x09, 0x29, - 0x29, 0xd9, 0xd7, 0x9a, 0x3a, 0xe6, 0xed, 0xb9, 0xad, 0x9e, 0x84, 0xc8, 0x54, 0xe7, 0x5b, 0x1f, 0x6b, 0xd5, 0xf2, - 0x86, 0x51, 0x42, 0x48, 0xcc, 0x1b, 0xf6, 0xad, 0x33, 0x62, 0x51, 0xcb, 0xb3, 0xe5, 0x8a, 0x88, 0x86, 0x42, 0x23, - 0x5f, 0x0a, 0x75, 0x2f, 0xfd, 0x43, 0xf9, 0xf7, 0x86, 0xe9, 0xdb, 0x50, 0x41, 0xe3, 0x27, 0xcf, 0xaa, 0x14, 0x08, - 0xdc, 0x91, 0x12, 0x0d, 0x0b, 0x93, 0x14, 0x70, 0x0e, 0x8c, 0x05, 0x3b, 0x3c, 0xa9, 0xdb, 0x42, 0x8b, 0x56, 0xe1, - 0xee, 0x08, 0x28, 0xf0, 0x0d, 0xe1, 0x52, 0x92, 0x4f, 0x62, 0xb8, 0x09, 0x0c, 0x45, 0x5a, 0x89, 0xd6, 0x24, 0x3c, - 0xf0, 0x70, 0xfb, 0x2a, 0xf4, 0x9b, 0x01, 0xf7, 0xab, 0xf8, 0x1c, 0x20, 0xee, 0x58, 0x22, 0xf5, 0xd7, 0x39, 0xed, - 0x25, 0x92, 0x2b, 0x02, 0xcb, 0x03, 0xdc, 0x1b, 0x4b, 0x4c, 0x44, 0x75, 0x2b, 0xe0, 0xd5, 0x96, 0xe4, 0x6e, 0x26, - 0x23, 0xe3, 0x8b, 0xf4, 0xe3, 0x92, 0x00, 0xab, 0x5d, 0x3d, 0x0c, 0xc9, 0xa4, 0x68, 0xab, 0x02, 0xed, 0xaa, 0x09, - 0x61, 0x20, 0xe4, 0x12, 0x34, 0xc2, 0x49, 0x79, 0x8c, 0x84, 0x24, 0xc6, 0x29, 0x93, 0x73, 0x84, 0x6a, 0x46, 0xaa, - 0xb8, 0x38, 0x59, 0x2c, 0x0b, 0x8a, 0x3f, 0x8f, 0x03, 0x88, 0x60, 0x38, 0xc4, 0x24, 0x22, 0xac, 0xd7, 0xcc, 0x0f, - 0x94, 0xc6, 0x61, 0xb3, 0x4c, 0xc8, 0x63, 0x10, 0xc6, 0xd1, 0x34, 0x48, 0x7b, 0x83, 0x3f, 0x33, 0x31, 0x0d, 0x20, - 0x33, 0x34, 0xd5, 0x3e, 0x21, 0x2b, 0x87, 0x16, 0x00, 0x32, 0xe1, 0x76, 0x46, 0xf6, 0xbc, 0x75, 0xb2, 0x18, 0x93, - 0xba, 0x32, 0xcd, 0x13, 0x94, 0x44, 0x8e, 0x71, 0xed, 0xfc, 0x07, 0xab, 0x40, 0x19, 0xd0, 0x59, 0x40, 0x2e, 0x92, - 0xf5, 0xdc, 0x09, 0x2d, 0x03, 0xcc, 0x5c, 0xbb, 0xb3, 0xea, 0xf9, 0xe2, 0x91, 0xe4, 0xf2, 0x0e, 0xd9, 0xb3, 0xf9, - 0xc2, 0x6a, 0x6d, 0x91, 0xc5, 0xe7, 0x41, 0x76, 0xcd, 0x46, 0x6e, 0xae, 0x69, 0x09, 0xe7, 0xc0, 0x44, 0x59, 0xc5, - 0x41, 0x0b, 0xc0, 0xa8, 0x01, 0xa6, 0xab, 0xca, 0x22, 0x31, 0x5b, 0x65, 0xe9, 0x83, 0x7d, 0x1d, 0x5b, 0x5d, 0xb8, - 0xf0, 0x24, 0x65, 0xe4, 0x4f, 0x46, 0x76, 0xbe, 0x66, 0x7a, 0x79, 0x75, 0x7a, 0x49, 0xf5, 0xa0, 0xd1, 0x64, 0x18, - 0x53, 0xf0, 0xb8, 0x69, 0x66, 0x94, 0xea, 0xb2, 0x7d, 0x47, 0xf9, 0xdd, 0xbf, 0x75, 0x3b, 0x22, 0xdc, 0x8e, 0x04, - 0xb7, 0xa3, 0x45, 0x00, 0x1b, 0xc8, 0x1d, 0x41, 0x5a, 0x04, 0xa9, 0x90, 0x8c, 0x28, 0x10, 0xce, 0x82, 0xd9, 0x51, - 0x47, 0x28, 0xc3, 0xab, 0xc1, 0x63, 0xe7, 0xab, 0x91, 0xf9, 0x7e, 0x4a, 0x5f, 0x65, 0x70, 0x9c, 0xb9, 0x36, 0x23, - 0x45, 0xae, 0x84, 0xcb, 0x90, 0xe1, 0x0c, 0xf5, 0x2a, 0x60, 0x1a, 0x70, 0x7f, 0xa8, 0x19, 0x9d, 0xfe, 0x39, 0x29, - 0x9f, 0x87, 0xe3, 0x2a, 0xc1, 0x43, 0x5f, 0xc1, 0x9a, 0x52, 0x62, 0x4f, 0x44, 0xeb, 0x18, 0xfa, 0x6a, 0x6f, 0x93, - 0x7f, 0x76, 0x6a, 0x37, 0x42, 0x37, 0x22, 0xa5, 0x8e, 0x9e, 0x68, 0xe0, 0x77, 0x5d, 0x95, 0xbc, 0x88, 0x16, 0x58, - 0x1a, 0xc0, 0xf3, 0xb9, 0x20, 0xb0, 0x44, 0x8c, 0x3d, 0x0c, 0xc0, 0x33, 0x40, 0xc7, 0x07, 0x78, 0x13, 0x5c, 0xd1, - 0xcc, 0xe5, 0x9b, 0xe0, 0xca, 0x1e, 0x8a, 0x57, 0xfa, 0xae, 0xe5, 0xd5, 0xbb, 0x36, 0x11, 0x9b, 0x8b, 0xde, 0x75, - 0x92, 0xb0, 0x06, 0xde, 0x77, 0xd2, 0xbe, 0xb9, 0x33, 0xb9, 0xb9, 0xe1, 0x9a, 0xcd, 0x0d, 0x6f, 0xd9, 0xdc, 0xb9, - 0xd8, 0xc8, 0x8e, 0x5a, 0xba, 0x8c, 0x3c, 0xa6, 0xd5, 0xe2, 0x09, 0x7a, 0xc4, 0x13, 0xf7, 0x8c, 0xd6, 0xa9, 0x97, - 0xcf, 0xd1, 0x62, 0x78, 0xcd, 0x5a, 0xb5, 0xad, 0x8b, 0xb1, 0x10, 0xcd, 0x89, 0xab, 0x5b, 0x37, 0x31, 0x24, 0x03, - 0xf6, 0xbc, 0x3e, 0x5f, 0x3c, 0xa5, 0xf4, 0xa1, 0x6b, 0xcf, 0xd6, 0xcc, 0x74, 0x76, 0xcb, 0x4c, 0x27, 0x95, 0xab, - 0x2b, 0xa6, 0xcd, 0x97, 0xd0, 0x9c, 0x14, 0x9e, 0x41, 0xf4, 0xa2, 0xa0, 0x23, 0x53, 0x3d, 0x87, 0xeb, 0x61, 0xac, - 0x71, 0xa2, 0x16, 0x70, 0x1e, 0x2f, 0xd3, 0x0c, 0xcd, 0x10, 0xb0, 0x99, 0xdf, 0x77, 0xa4, 0x60, 0xb9, 0x44, 0x84, - 0xb3, 0xb5, 0x87, 0x49, 0xbf, 0x37, 0x8f, 0xd4, 0xd6, 0xee, 0x2e, 0xd7, 0x00, 0x62, 0x04, 0x58, 0x24, 0x5a, 0xf4, - 0x00, 0x53, 0x61, 0xfc, 0x7f, 0x72, 0xcc, 0x5a, 0x60, 0xc8, 0xdc, 0x80, 0xea, 0x04, 0xa1, 0x17, 0x48, 0x82, 0xb1, - 0xde, 0x31, 0x71, 0x56, 0x46, 0xb4, 0xd4, 0x4c, 0x2d, 0xfc, 0x3b, 0xba, 0xae, 0x50, 0xa0, 0xdd, 0xbc, 0x86, 0x8f, - 0x81, 0x6d, 0x0d, 0xc2, 0x03, 0xb4, 0x76, 0xb1, 0xb7, 0x5c, 0xf4, 0x5c, 0x31, 0x63, 0xa3, 0x66, 0x4c, 0x13, 0x4e, - 0x34, 0x90, 0x24, 0x28, 0x29, 0xec, 0x82, 0x31, 0xa4, 0x40, 0xd0, 0x9b, 0x1e, 0xad, 0xb6, 0xca, 0xcd, 0xb3, 0xd8, - 0x69, 0x40, 0x4d, 0x04, 0x6d, 0x73, 0x7f, 0x5f, 0x09, 0xdd, 0xe6, 0x2e, 0x74, 0x87, 0xea, 0xd0, 0x43, 0x4c, 0x7a, - 0x3e, 0x90, 0xcc, 0xf4, 0x49, 0x86, 0x58, 0x0b, 0x95, 0x87, 0x0f, 0xcf, 0xe8, 0x69, 0x08, 0x4f, 0xa7, 0xf4, 0xb4, - 0x75, 0xa4, 0x54, 0x55, 0x35, 0x29, 0x82, 0x31, 0x67, 0x38, 0x87, 0xe6, 0x79, 0x62, 0xa3, 0xec, 0xdf, 0x71, 0x6c, - 0xc4, 0x06, 0x7f, 0x01, 0x3b, 0x8c, 0x61, 0x08, 0xcc, 0x39, 0x24, 0xfd, 0xcc, 0x29, 0x5b, 0xcb, 0xcf, 0xd6, 0x94, - 0x9f, 0x3a, 0xff, 0x66, 0xc4, 0x4f, 0xa7, 0x24, 0xd5, 0x38, 0xa5, 0x2a, 0x03, 0x39, 0x3e, 0x8d, 0x13, 0x40, 0xe2, - 0xc7, 0xcc, 0x85, 0xd8, 0x86, 0x90, 0x77, 0x43, 0x0b, 0x07, 0xae, 0xab, 0x36, 0x20, 0x85, 0xa1, 0xa0, 0xba, 0x16, - 0x88, 0xde, 0xff, 0x4b, 0x66, 0xd0, 0x77, 0x15, 0x36, 0x56, 0x6c, 0x48, 0xa5, 0xa3, 0x63, 0xa0, 0xdc, 0xa2, 0x66, - 0x33, 0xb5, 0xd9, 0xd6, 0x08, 0x48, 0xdc, 0x1e, 0x62, 0x89, 0xcf, 0xc3, 0xd8, 0x23, 0x23, 0x8f, 0xd3, 0xf4, 0xaa, - 0x07, 0xbb, 0x35, 0xb6, 0x80, 0x10, 0x01, 0xfe, 0xa2, 0x37, 0x89, 0xb3, 0xc9, 0x1c, 0x89, 0xc7, 0xd3, 0x79, 0x90, - 0x7c, 0x16, 0x3f, 0x7b, 0xe9, 0xb2, 0x20, 0xb3, 0xad, 0x3b, 0x39, 0x68, 0xb9, 0x26, 0x2c, 0x48, 0x24, 0xaa, 0xb6, - 0x65, 0x15, 0x60, 0x82, 0x92, 0xad, 0xd7, 0x84, 0xa2, 0xae, 0xe5, 0xa2, 0xd7, 0x01, 0x5a, 0x92, 0x61, 0x18, 0x07, - 0xd7, 0xa2, 0xfd, 0xb2, 0x5c, 0x73, 0xaa, 0xac, 0x47, 0x53, 0x79, 0x88, 0x8f, 0xa9, 0x85, 0x7f, 0xbe, 0x3b, 0x2c, - 0xf9, 0x3d, 0xdd, 0xa9, 0x56, 0xfe, 0xd8, 0x0c, 0xb1, 0xb4, 0xc7, 0xee, 0x83, 0xbf, 0xa3, 0x73, 0x41, 0x60, 0xae, - 0xef, 0xda, 0xfc, 0x18, 0xce, 0xcd, 0xf2, 0x3c, 0x0a, 0x59, 0x19, 0x36, 0xd6, 0x83, 0xaa, 0xf2, 0x21, 0xe6, 0xc0, - 0xfe, 0xbe, 0xdc, 0x7a, 0xb2, 0xf3, 0x1c, 0xcd, 0xf8, 0x90, 0xa0, 0x4c, 0xa7, 0x53, 0x4b, 0x8b, 0x02, 0xee, 0xf8, - 0x6c, 0xb8, 0xf3, 0xf7, 0xe5, 0xab, 0x97, 0x83, 0x57, 0xea, 0xe3, 0x04, 0x09, 0x63, 0x69, 0x93, 0x24, 0xe8, 0x62, - 0x63, 0xbc, 0x72, 0x46, 0xd3, 0x20, 0x59, 0x3f, 0x9d, 0xc3, 0xca, 0x11, 0x5f, 0x44, 0x51, 0x88, 0x04, 0xb7, 0xdb, - 0x28, 0x3d, 0x9e, 0x47, 0x17, 0x91, 0xb2, 0x77, 0x6a, 0x76, 0xd6, 0xf2, 0x05, 0x05, 0x64, 0x15, 0xba, 0x47, 0x41, - 0xd5, 0x19, 0x53, 0x3a, 0xa1, 0x39, 0x88, 0x99, 0x9b, 0x57, 0xac, 0x76, 0xa5, 0x4e, 0x60, 0xef, 0xf4, 0x00, 0xd6, - 0x8e, 0x6c, 0xbc, 0xa6, 0xdc, 0x43, 0x40, 0xbd, 0x66, 0x6c, 0xee, 0xd0, 0xf1, 0x30, 0x81, 0x85, 0x58, 0xa7, 0x39, - 0xde, 0x3c, 0x5b, 0x4b, 0x4d, 0xd6, 0xad, 0x58, 0x9b, 0xa8, 0xcd, 0x62, 0x21, 0x8d, 0x74, 0x01, 0x20, 0x5f, 0x18, - 0x29, 0xae, 0x6a, 0xdd, 0x9b, 0x4e, 0x75, 0xe6, 0xa7, 0x94, 0xde, 0x3d, 0x89, 0xf2, 0x7c, 0xed, 0x82, 0xa9, 0x4d, - 0x77, 0x2d, 0x5d, 0xbb, 0xba, 0x1e, 0xba, 0x1c, 0x26, 0x8d, 0x24, 0x01, 0x4d, 0xb0, 0xde, 0x17, 0xa1, 0x97, 0xe3, - 0x73, 0x61, 0xc4, 0x99, 0x9d, 0x9d, 0x5a, 0xc2, 0xc0, 0x6e, 0xdd, 0xfb, 0x4b, 0x4b, 0x0c, 0xaa, 0x82, 0xa6, 0x5b, - 0x87, 0x66, 0x57, 0x40, 0x6f, 0x43, 0xaa, 0x44, 0x0d, 0xc8, 0x31, 0xd5, 0xe0, 0x6b, 0x34, 0x9d, 0x02, 0x0b, 0x90, - 0x3b, 0x52, 0xc6, 0xa4, 0x42, 0xaa, 0xa3, 0xd2, 0x6e, 0xc3, 0xb7, 0xde, 0x61, 0x60, 0x19, 0x19, 0x79, 0x50, 0x0c, - 0x48, 0xf2, 0x4c, 0xed, 0xcb, 0xc4, 0x2d, 0x56, 0x97, 0x48, 0xf4, 0x82, 0x52, 0xe8, 0x96, 0x72, 0x1a, 0x9a, 0xc0, - 0x3f, 0xfa, 0x5c, 0xa4, 0xca, 0xd4, 0xf3, 0x76, 0x50, 0x74, 0xdb, 0xf5, 0x5d, 0x0d, 0x5f, 0xed, 0x0e, 0x07, 0x25, - 0x8c, 0x0a, 0x9b, 0xab, 0x1d, 0x63, 0x46, 0x50, 0xbe, 0xf5, 0xe6, 0xfd, 0xf3, 0xbf, 0xbc, 0x7c, 0x71, 0x5f, 0x88, - 0x40, 0x4d, 0x6e, 0x63, 0x93, 0xcb, 0xe4, 0x96, 0x46, 0x7f, 0x7c, 0xf7, 0xfb, 0x9a, 0xdd, 0x1a, 0x7e, 0x3d, 0x84, - 0x36, 0xc9, 0x06, 0xdd, 0x80, 0x8b, 0x93, 0xf4, 0x22, 0xca, 0xfe, 0xf0, 0x32, 0x98, 0x8d, 0xb7, 0x0f, 0xf7, 0xfd, - 0x87, 0x97, 0xef, 0xee, 0x3d, 0xd4, 0xc7, 0xc3, 0x01, 0xc2, 0xf6, 0x22, 0x5d, 0xfc, 0x8e, 0xd9, 0x6d, 0xc3, 0x27, - 0x93, 0x79, 0x9a, 0x47, 0x6b, 0x46, 0xf0, 0xfc, 0xcd, 0xfb, 0x03, 0x5a, 0x2e, 0x4d, 0x82, 0x70, 0x53, 0x7f, 0x6c, - 0xf2, 0x1f, 0x3e, 0xbe, 0x3c, 0x38, 0x80, 0xae, 0xd1, 0x53, 0x26, 0x37, 0x5b, 0x17, 0x87, 0xf8, 0x0e, 0x8c, 0xd3, - 0x7a, 0xd6, 0x19, 0xab, 0x31, 0x23, 0x5d, 0x9d, 0x0d, 0x97, 0x35, 0x8e, 0xb9, 0xc0, 0x76, 0xa2, 0x67, 0xe6, 0x7e, - 0xef, 0x35, 0xaf, 0x16, 0x78, 0x74, 0x3b, 0x4a, 0xad, 0x94, 0x00, 0x0b, 0x73, 0xdc, 0x52, 0x1a, 0x5c, 0xb5, 0x94, - 0x22, 0xfb, 0xd8, 0x80, 0x8f, 0xcb, 0xf4, 0xdc, 0x20, 0x47, 0x80, 0xaf, 0xba, 0x73, 0xb9, 0x0c, 0x1e, 0xee, 0x0f, - 0x0c, 0x5a, 0xa4, 0x54, 0xa9, 0x8f, 0xba, 0xa5, 0x58, 0x30, 0x5e, 0x6a, 0x6d, 0x27, 0x73, 0xb4, 0xbc, 0x8f, 0x4c, - 0x35, 0x64, 0x95, 0x54, 0x15, 0x7e, 0x33, 0x7e, 0x8d, 0x2b, 0xe0, 0xcf, 0x58, 0x75, 0x23, 0x70, 0x0a, 0xb0, 0x37, - 0x68, 0xce, 0xde, 0x3b, 0x4d, 0xe1, 0x54, 0x9d, 0x03, 0x72, 0x01, 0xd2, 0xb0, 0x33, 0x92, 0xc2, 0x0e, 0x61, 0x6d, - 0xef, 0xfd, 0xcf, 0xff, 0xa9, 0x81, 0x79, 0x2e, 0x87, 0x85, 0x38, 0x5f, 0x44, 0x59, 0x00, 0x7d, 0x46, 0x65, 0xe7, - 0x7f, 0xfe, 0xef, 0xf3, 0x1a, 0x63, 0x3f, 0x32, 0xbf, 0x61, 0x92, 0xde, 0xfc, 0x04, 0xa0, 0xdf, 0xe5, 0x86, 0xf6, - 0xab, 0xbb, 0xa3, 0xf2, 0x0c, 0xf0, 0x8f, 0xaa, 0x3d, 0x2e, 0x6e, 0x99, 0x9b, 0x1c, 0x3d, 0xeb, 0x03, 0x3a, 0x80, - 0xf1, 0x61, 0x02, 0x4a, 0x60, 0x73, 0xe7, 0xa9, 0x6b, 0x1f, 0x68, 0x75, 0x47, 0xdb, 0xeb, 0x34, 0xb6, 0x18, 0xdf, - 0x37, 0x36, 0xb8, 0x51, 0xc8, 0xa7, 0xb2, 0xa9, 0x9b, 0xbb, 0x65, 0x4e, 0xdf, 0xc1, 0x62, 0xfc, 0xd1, 0x49, 0xe1, - 0x82, 0xde, 0x39, 0x2b, 0xac, 0xf4, 0x27, 0x4c, 0x0b, 0x48, 0xc9, 0x7b, 0x6f, 0xd8, 0x1f, 0x9c, 0xd7, 0x5d, 0x53, - 0xfa, 0x33, 0x66, 0x23, 0x24, 0xb7, 0xcf, 0x4f, 0x4e, 0x54, 0x4a, 0x5a, 0xf3, 0x7b, 0xf4, 0x0c, 0x1c, 0x37, 0x4a, - 0x04, 0x79, 0xe1, 0x0d, 0x1c, 0x0e, 0xd9, 0x73, 0x8f, 0x05, 0x21, 0x1b, 0xf7, 0x96, 0xe5, 0x58, 0x0f, 0xaf, 0xd9, - 0x55, 0xad, 0xd1, 0x77, 0x03, 0x58, 0x63, 0x29, 0xa5, 0x33, 0x55, 0x5a, 0x43, 0xb7, 0x7d, 0x38, 0x97, 0x59, 0xb0, - 0x60, 0x25, 0x41, 0x87, 0x34, 0x26, 0x28, 0x74, 0xa9, 0x71, 0xd1, 0x00, 0xde, 0x2e, 0xee, 0xc7, 0x50, 0xad, 0xc7, - 0x60, 0x84, 0x9a, 0xff, 0xf7, 0x90, 0x37, 0xe1, 0xe5, 0xfb, 0xe3, 0x6e, 0x4a, 0x13, 0xf7, 0x72, 0x9d, 0x69, 0xfd, - 0xeb, 0xbb, 0x4d, 0xeb, 0x3f, 0xdd, 0xcb, 0xb4, 0xfe, 0xf5, 0x9f, 0x6e, 0x5a, 0xff, 0xd2, 0x34, 0xad, 0xc7, 0x43, - 0xfc, 0x32, 0xba, 0x97, 0x25, 0xb3, 0xb4, 0x36, 0x4a, 0x2f, 0x73, 0x7f, 0x28, 0x98, 0x9e, 0x7c, 0x32, 0x8b, 0x50, - 0x8a, 0x24, 0x96, 0x6b, 0x9e, 0x9e, 0xa1, 0xc1, 0xf1, 0x7a, 0x93, 0xe2, 0x3f, 0xcb, 0xa0, 0x18, 0x3a, 0xb2, 0x8c, - 0x40, 0xf9, 0x89, 0x0c, 0x94, 0x8f, 0xc1, 0x01, 0xfe, 0x7e, 0x35, 0xfc, 0xe6, 0x70, 0x38, 0xda, 0x1e, 0x62, 0xa0, - 0x19, 0x14, 0x0c, 0x50, 0xc1, 0x60, 0xb4, 0xbd, 0x8d, 0x05, 0x97, 0x46, 0xc1, 0x16, 0x16, 0xc4, 0x46, 0xc1, 0x2e, - 0x16, 0x4c, 0x8c, 0x82, 0xc7, 0x58, 0x10, 0x1a, 0x05, 0x4f, 0xb0, 0xe0, 0xc2, 0x2a, 0x0f, 0x13, 0xe5, 0x38, 0xf0, - 0xc4, 0x39, 0xaa, 0xe4, 0x48, 0x51, 0x52, 0x2c, 0x59, 0xe5, 0x89, 0x2b, 0x03, 0x76, 0xf6, 0x76, 0x1c, 0x61, 0xa2, - 0x7e, 0xf2, 0x1f, 0x27, 0xe8, 0x4a, 0x8f, 0x42, 0x3d, 0x17, 0x45, 0xa2, 0x5c, 0x73, 0x5b, 0xbe, 0x86, 0x4e, 0x1c, - 0xd5, 0xc1, 0x96, 0x34, 0x5c, 0xf7, 0xc8, 0x8d, 0x4a, 0x56, 0xde, 0xed, 0xce, 0x54, 0xf4, 0xae, 0xa5, 0xaf, 0xbd, - 0x11, 0xb7, 0x31, 0x86, 0x31, 0xaa, 0xa6, 0x5f, 0x10, 0x7d, 0x00, 0xfc, 0x2e, 0x3a, 0x9b, 0xc9, 0xa8, 0x55, 0xb2, - 0x83, 0x0e, 0x79, 0x23, 0x8c, 0x02, 0x1d, 0x60, 0x4c, 0xc4, 0xba, 0xe3, 0xd1, 0x9f, 0xab, 0x10, 0x62, 0xcc, 0xe6, - 0x2e, 0xdd, 0x22, 0x38, 0xf3, 0x66, 0x2e, 0xcb, 0xb8, 0xbd, 0x33, 0x8c, 0x09, 0x3b, 0x0e, 0xbd, 0x85, 0x7b, 0x39, - 0x8b, 0x12, 0x6f, 0x2a, 0xac, 0x40, 0x71, 0xff, 0xd9, 0xc8, 0xe7, 0xdc, 0x91, 0xd6, 0x69, 0x74, 0x26, 0xf4, 0x5b, - 0x1e, 0x65, 0x4f, 0x1d, 0x25, 0x6d, 0x58, 0x65, 0x9b, 0xf2, 0xef, 0x3f, 0xc3, 0x0c, 0xe6, 0x45, 0x74, 0xba, 0x3c, - 0x03, 0xd4, 0x7f, 0x76, 0xa7, 0xc9, 0x8b, 0xf9, 0x0a, 0x47, 0x69, 0xb1, 0xa2, 0xaf, 0x27, 0x8f, 0xb7, 0xe8, 0x8b, - 0x7f, 0x96, 0xd5, 0xfa, 0x05, 0x8e, 0xad, 0x53, 0x30, 0xc8, 0xc6, 0x7e, 0x70, 0xb5, 0x0d, 0xa3, 0x92, 0x37, 0xb8, - 0x7e, 0xc6, 0xef, 0x4f, 0x81, 0x31, 0x9e, 0xfd, 0xb7, 0x40, 0xac, 0x07, 0x67, 0xb2, 0x7e, 0x73, 0x9c, 0xe8, 0x5f, - 0xa5, 0x38, 0x7d, 0x5a, 0x40, 0x94, 0x19, 0xc7, 0x0d, 0x53, 0x21, 0xb4, 0x60, 0x46, 0x13, 0x3a, 0xdc, 0x34, 0x6d, - 0x57, 0x13, 0xf7, 0x71, 0x7b, 0xaa, 0x26, 0x2e, 0x08, 0x44, 0x60, 0x44, 0xf5, 0x42, 0xd8, 0xde, 0x7a, 0x11, 0xef, - 0x75, 0x69, 0x8e, 0x4d, 0x59, 0x98, 0x54, 0x0a, 0xff, 0x88, 0xc9, 0x04, 0xcc, 0xe9, 0x5f, 0x6a, 0x2f, 0x71, 0x8b, - 0x9d, 0xcb, 0x41, 0xe2, 0x26, 0xc5, 0x49, 0x9f, 0xd6, 0xb8, 0xd3, 0xc7, 0x25, 0xf4, 0x12, 0xb8, 0xa3, 0xe4, 0xd9, - 0x6f, 0x6f, 0x25, 0x8e, 0xdb, 0xa7, 0xbd, 0x5d, 0xd5, 0xe3, 0x99, 0x78, 0xd9, 0xd9, 0x69, 0x60, 0x0f, 0xb7, 0x9e, - 0xb8, 0xf2, 0xbf, 0xfe, 0x60, 0xd7, 0x29, 0xa9, 0x85, 0x0e, 0x2c, 0x08, 0x80, 0xf2, 0xa4, 0xe8, 0x4d, 0x83, 0xf3, - 0x78, 0x7e, 0xed, 0x9d, 0xa7, 0x49, 0x0a, 0x43, 0x9a, 0x44, 0x23, 0x2d, 0xba, 0x19, 0x51, 0xa4, 0x2c, 0x11, 0xac, - 0x61, 0xd8, 0xdf, 0xca, 0xa2, 0x73, 0xfe, 0x5a, 0x05, 0xc2, 0x9a, 0xce, 0xa3, 0xab, 0x52, 0x74, 0x5f, 0xa9, 0xcc, - 0x55, 0xe9, 0xc8, 0xf1, 0x17, 0xc8, 0x87, 0x88, 0x28, 0x5b, 0x18, 0x5b, 0x72, 0x24, 0x88, 0x79, 0xaf, 0xbf, 0xb5, - 0x0b, 0x75, 0x3b, 0xfd, 0xdd, 0xb5, 0x8d, 0x43, 0xd1, 0x3e, 0x8e, 0x96, 0x3e, 0xee, 0x01, 0x39, 0x31, 0xa5, 0x37, - 0x3d, 0x72, 0xec, 0x95, 0xed, 0xf4, 0x48, 0xe4, 0x83, 0xad, 0x45, 0xe7, 0x23, 0x7c, 0xed, 0x6d, 0x75, 0x06, 0x23, - 0x20, 0x99, 0x7a, 0x3c, 0x9d, 0x27, 0xc0, 0x2c, 0xe8, 0xb6, 0xcc, 0xf5, 0x73, 0x56, 0x54, 0x7d, 0x08, 0xd5, 0x91, - 0xb5, 0x9f, 0x02, 0x6d, 0xec, 0xcd, 0xe2, 0x30, 0x8c, 0x92, 0x11, 0x8d, 0x59, 0x15, 0x46, 0xf3, 0x79, 0xbc, 0xc8, - 0xe3, 0x7c, 0x04, 0x34, 0x97, 0x68, 0x75, 0x67, 0x5d, 0xab, 0xdb, 0xa2, 0xd5, 0xed, 0x7b, 0xb7, 0x6a, 0x34, 0x83, - 0x4e, 0xc4, 0xdc, 0x8e, 0x18, 0xda, 0x2e, 0xb4, 0x52, 0x9d, 0xe7, 0xbd, 0x5b, 0x05, 0x2e, 0x7b, 0x75, 0x0e, 0x87, - 0x2f, 0x4e, 0xbc, 0x41, 0xd9, 0xbf, 0x58, 0xf1, 0xc1, 0xf8, 0xe2, 0xe9, 0xd3, 0xa7, 0x65, 0x3f, 0x94, 0xbf, 0x06, - 0x61, 0x58, 0xf6, 0x27, 0xf2, 0xd7, 0x74, 0x3a, 0x18, 0x4c, 0xa7, 0x65, 0x3f, 0x96, 0x05, 0xdb, 0x5b, 0x93, 0x70, - 0x7b, 0xab, 0xec, 0x5f, 0x1a, 0x35, 0xca, 0x7e, 0x24, 0x7e, 0x65, 0x51, 0x38, 0xa2, 0x83, 0x24, 0xcc, 0xd1, 0x9f, - 0x0c, 0xe0, 0x25, 0x42, 0x80, 0xc3, 0x0a, 0x6c, 0x22, 0xa9, 0xe2, 0xd1, 0xea, 0xde, 0x35, 0x3b, 0xba, 0xbb, 0xc9, - 0xa4, 0xb5, 0x5e, 0x18, 0x64, 0x9f, 0xa1, 0x9a, 0x9e, 0x45, 0x10, 0x70, 0xb5, 0x95, 0x5c, 0x86, 0xde, 0x95, 0x87, - 0x11, 0x53, 0x47, 0xa7, 0x69, 0x86, 0x77, 0x36, 0x0b, 0xc2, 0x78, 0x99, 0x7b, 0xc3, 0xad, 0xc5, 0x95, 0x2c, 0x12, - 0x67, 0x5d, 0x17, 0xd0, 0xdd, 0xf3, 0xf2, 0x74, 0x1e, 0x87, 0xb2, 0x68, 0xdd, 0x5d, 0x1a, 0x6e, 0x39, 0x23, 0x8a, - 0x17, 0x14, 0x53, 0xd4, 0x2b, 0xa0, 0x10, 0x3a, 0xfd, 0x6d, 0x20, 0x4e, 0x82, 0x9c, 0x34, 0x19, 0x9d, 0x41, 0xce, - 0xeb, 0x42, 0xb1, 0x81, 0x86, 0x3b, 0xd0, 0x87, 0x3c, 0xf3, 0xc3, 0xc7, 0x70, 0x6c, 0xfe, 0xf3, 0x3c, 0x0a, 0xe3, - 0xa0, 0x63, 0xeb, 0xd3, 0x34, 0x1c, 0xa0, 0xb6, 0xc3, 0x59, 0xad, 0x39, 0xa6, 0xf2, 0x5a, 0x60, 0x64, 0xe9, 0x8d, - 0x18, 0x40, 0x4c, 0x56, 0x04, 0x49, 0x51, 0x96, 0x27, 0x47, 0x65, 0x39, 0xfa, 0x14, 0xdb, 0x87, 0x7f, 0xb3, 0x19, - 0x17, 0xb2, 0x76, 0xb0, 0x74, 0x8e, 0xdc, 0x97, 0x91, 0x69, 0xc9, 0x84, 0x68, 0x8c, 0xac, 0x98, 0xcc, 0xca, 0x8c, - 0x6f, 0x9b, 0x95, 0x79, 0x91, 0x55, 0x75, 0x36, 0x8c, 0xaa, 0x56, 0x21, 0x0c, 0x84, 0x15, 0x80, 0x30, 0xfb, 0x64, - 0x98, 0x45, 0x21, 0xd1, 0x43, 0x95, 0xd9, 0xad, 0xf3, 0xc5, 0x3a, 0xda, 0xf3, 0xd3, 0xdd, 0xb4, 0xe7, 0x2f, 0xc5, - 0x7d, 0x68, 0xcf, 0x4f, 0x7f, 0x3a, 0xed, 0xf9, 0xa2, 0xe9, 0xd6, 0xf9, 0x29, 0x05, 0x46, 0x43, 0xea, 0xb2, 0x10, - 0x35, 0x65, 0x1c, 0x30, 0xf1, 0x45, 0xf1, 0xcf, 0xfa, 0xd7, 0xc9, 0xd6, 0x38, 0x05, 0x30, 0x63, 0x6e, 0x24, 0xe0, - 0xdf, 0x27, 0xfe, 0x5f, 0x32, 0xf3, 0xf7, 0x74, 0xea, 0xbf, 0x48, 0x8d, 0x02, 0xf5, 0x4b, 0x98, 0xf9, 0x54, 0x82, - 0x5b, 0xf1, 0x1b, 0x65, 0x88, 0x85, 0xe9, 0xbf, 0x30, 0x36, 0x0e, 0x5b, 0xdd, 0x87, 0xca, 0x1c, 0x72, 0x54, 0x1d, - 0x82, 0xad, 0xec, 0x8f, 0xa5, 0x07, 0x74, 0x43, 0x68, 0x0d, 0x9b, 0x24, 0x42, 0x96, 0x7c, 0x73, 0xfd, 0x3a, 0xb4, - 0x3f, 0xa5, 0x4e, 0x19, 0xe7, 0xef, 0xeb, 0xfe, 0xc7, 0x92, 0x05, 0x31, 0xa7, 0x53, 0x0a, 0x93, 0x46, 0x23, 0xcc, - 0x10, 0xbd, 0xe6, 0xcf, 0xc7, 0x95, 0x99, 0x7a, 0xe6, 0x87, 0x22, 0xcf, 0x68, 0x03, 0x19, 0x0b, 0x3f, 0xbd, 0x95, - 0xa0, 0xf2, 0x28, 0x75, 0x2a, 0x85, 0x6d, 0x09, 0xf9, 0xf3, 0x38, 0x2c, 0x01, 0xf3, 0xca, 0x85, 0x30, 0x10, 0x6d, - 0x74, 0x17, 0x11, 0x97, 0x6b, 0x86, 0x56, 0xe8, 0xa2, 0x59, 0xd1, 0xfc, 0x09, 0x4d, 0x37, 0x84, 0x5a, 0x5a, 0xac, - 0x99, 0xd5, 0xe1, 0xe5, 0x63, 0x93, 0x1e, 0x63, 0x42, 0x68, 0x6b, 0x60, 0x1a, 0xc2, 0x55, 0x36, 0xa4, 0x69, 0x73, - 0xcc, 0x8b, 0x43, 0xb6, 0x27, 0x18, 0x64, 0x49, 0x4a, 0xbb, 0x18, 0xec, 0x88, 0x3a, 0xf4, 0x03, 0x3e, 0x95, 0xb4, - 0x1f, 0x1d, 0x3f, 0x20, 0x6b, 0xf0, 0x83, 0xfd, 0x9a, 0x24, 0xeb, 0x0e, 0x93, 0x59, 0x24, 0x25, 0xf2, 0x4b, 0x17, - 0xfe, 0xeb, 0x3c, 0x5a, 0xc9, 0x00, 0x65, 0x45, 0xb0, 0xe8, 0xa1, 0xf8, 0x84, 0x60, 0xaf, 0x80, 0x78, 0x46, 0x2c, - 0xb4, 0xd1, 0x32, 0x47, 0xd8, 0x48, 0x9c, 0x3c, 0xc1, 0x9f, 0x11, 0x1c, 0xb9, 0x1c, 0xea, 0x2c, 0x80, 0xde, 0x2f, - 0x00, 0xd6, 0xd0, 0x52, 0x1d, 0xd2, 0xfa, 0xc8, 0xe5, 0x39, 0x5a, 0xa5, 0x40, 0x4e, 0x00, 0x57, 0x0a, 0xc8, 0x8a, - 0xe1, 0xdb, 0x60, 0x24, 0xa8, 0x83, 0x41, 0x6b, 0x7d, 0x4f, 0xac, 0x66, 0x97, 0x08, 0xbf, 0xac, 0x49, 0xce, 0x98, - 0xc7, 0x7c, 0x64, 0xbc, 0xe5, 0x10, 0x6d, 0x48, 0x7e, 0x04, 0x59, 0xef, 0x0c, 0xa1, 0x3c, 0x6e, 0xf5, 0x20, 0x8c, - 0xce, 0x5c, 0x82, 0xda, 0xa8, 0x01, 0x92, 0xff, 0xf5, 0x77, 0x9d, 0xce, 0xa0, 0xbd, 0x18, 0x29, 0x1e, 0xe7, 0x3e, - 0x23, 0xf3, 0x02, 0x4c, 0x68, 0xea, 0xde, 0xa7, 0xe6, 0x69, 0x04, 0x20, 0x2b, 0xe2, 0x70, 0xfe, 0xc3, 0xa7, 0x00, - 0xf5, 0xef, 0xdd, 0xfc, 0xed, 0xd3, 0x6f, 0x6f, 0x27, 0x49, 0x0b, 0x5b, 0x36, 0xe6, 0xdc, 0xd1, 0x5a, 0x13, 0x9f, - 0x21, 0x69, 0xc8, 0x2b, 0x3f, 0x61, 0x7f, 0x14, 0x74, 0xc5, 0x6e, 0x8d, 0x9a, 0x0a, 0xd4, 0x2d, 0xe3, 0xbc, 0x2c, - 0x9a, 0xc3, 0x51, 0xbb, 0x90, 0x34, 0xe3, 0x36, 0xe0, 0x35, 0xb9, 0xc7, 0x84, 0xf0, 0x7e, 0xc7, 0x26, 0xd5, 0x86, - 0x22, 0x37, 0xa9, 0x5e, 0x4c, 0x9b, 0x34, 0x6a, 0xcc, 0x46, 0x06, 0x12, 0xab, 0x61, 0xfa, 0x5d, 0x18, 0x83, 0x81, - 0xa2, 0xf5, 0x67, 0x0a, 0x53, 0xd7, 0x23, 0xc0, 0x9e, 0x03, 0x35, 0x05, 0x97, 0xb1, 0xb2, 0xd1, 0xd5, 0xbd, 0x34, - 0x16, 0x47, 0xad, 0x43, 0x70, 0x0a, 0x14, 0xc3, 0xb2, 0x88, 0xda, 0x97, 0x8b, 0x17, 0x67, 0x6b, 0xa0, 0x17, 0x87, - 0x9e, 0xab, 0x63, 0xdd, 0x45, 0x72, 0x1b, 0x8f, 0xc9, 0x60, 0x84, 0x09, 0x1f, 0x7a, 0xdb, 0xd5, 0xa1, 0xe3, 0x2b, - 0x35, 0x68, 0xb7, 0x65, 0x22, 0x2e, 0xa2, 0x25, 0x86, 0xde, 0x9d, 0xfe, 0x50, 0x94, 0xa9, 0xa0, 0xf7, 0xaa, 0xa8, - 0xac, 0x4e, 0xe6, 0x5f, 0x73, 0xc7, 0xbe, 0x6e, 0xbf, 0x63, 0x5f, 0xcb, 0x3b, 0x76, 0xfb, 0xc9, 0xfc, 0x62, 0x3a, - 0xc4, 0xff, 0x8d, 0xf4, 0x84, 0xbc, 0x41, 0x07, 0x96, 0xa3, 0x03, 0x64, 0x5a, 0xa7, 0x07, 0xc4, 0x5b, 0x87, 0x9a, - 0x26, 0xcb, 0x23, 0xb7, 0xbf, 0xe5, 0xb8, 0x83, 0x0e, 0x16, 0xe2, 0x7f, 0x83, 0xca, 0xab, 0xe1, 0x0e, 0xbe, 0xc3, - 0xaf, 0x76, 0x9b, 0xef, 0xb6, 0x6e, 0xbf, 0xea, 0x7c, 0x97, 0x24, 0xd0, 0x76, 0x80, 0x81, 0x3b, 0x3d, 0x85, 0xd2, - 0x69, 0x3a, 0x59, 0xe6, 0xff, 0x2d, 0xc6, 0x2f, 0x16, 0xf1, 0x56, 0x40, 0x50, 0x6b, 0x47, 0x7e, 0x8a, 0xd2, 0xbd, - 0x8b, 0x48, 0xb6, 0xb0, 0x52, 0xfb, 0xe4, 0x71, 0x76, 0x8a, 0xad, 0xfe, 0x4e, 0xcb, 0x21, 0x6f, 0x5f, 0xe8, 0x7f, - 0xd9, 0x2e, 0xad, 0x07, 0x31, 0x7f, 0x60, 0x59, 0x6e, 0x5d, 0x8e, 0xdf, 0xbf, 0x1a, 0x62, 0x37, 0x07, 0x4f, 0xdb, - 0x87, 0x7b, 0x28, 0x7b, 0x3a, 0x92, 0x48, 0x45, 0xe0, 0x2d, 0xe1, 0x25, 0x75, 0x7b, 0xab, 0xeb, 0xce, 0x48, 0xa3, - 0xd5, 0x5b, 0x10, 0x82, 0xae, 0x7b, 0x4f, 0x28, 0xff, 0xc5, 0xd7, 0x3b, 0xf8, 0x3f, 0xa6, 0xea, 0x7f, 0x29, 0xda, - 0x08, 0xf5, 0x17, 0x45, 0x85, 0x50, 0x67, 0x52, 0x89, 0x08, 0xf1, 0xfb, 0xd7, 0x9f, 0x4e, 0x7f, 0xdf, 0x07, 0xf7, - 0xae, 0xcd, 0x46, 0x7b, 0xf5, 0xda, 0xdf, 0xa4, 0x29, 0x66, 0x4e, 0x6f, 0x56, 0x97, 0xcb, 0xc3, 0x1e, 0x18, 0x85, - 0x8f, 0x1f, 0x49, 0x3e, 0x82, 0xed, 0x45, 0x2c, 0xfa, 0x86, 0x59, 0x89, 0x37, 0xeb, 0x58, 0x89, 0x8f, 0x77, 0xb3, - 0x12, 0xdf, 0xdf, 0x8b, 0x95, 0xf8, 0xf8, 0xa7, 0xb3, 0x12, 0x6f, 0x9a, 0xac, 0xc4, 0x9b, 0x54, 0x5a, 0x6a, 0xbb, - 0xaf, 0x96, 0xe2, 0xf1, 0x27, 0x56, 0xc5, 0x7e, 0x4c, 0xfd, 0xdd, 0x01, 0x67, 0x9c, 0xf8, 0xf4, 0x4f, 0x33, 0x16, - 0x74, 0x10, 0x3f, 0x92, 0xe1, 0xa2, 0x66, 0x2d, 0x04, 0x64, 0xa7, 0x7e, 0x8c, 0xe2, 0x79, 0x9a, 0x9c, 0x7d, 0x40, - 0x55, 0x3c, 0x8a, 0x03, 0x33, 0xe3, 0x45, 0x9c, 0x7f, 0x48, 0x17, 0xcb, 0xc5, 0x6b, 0x6c, 0xeb, 0xa7, 0x38, 0x8f, - 0x61, 0x97, 0x54, 0x88, 0x0f, 0x36, 0xb4, 0x14, 0xb2, 0x75, 0xb4, 0x6d, 0x96, 0x8f, 0xc1, 0x95, 0x7c, 0x24, 0xeb, - 0x67, 0xf1, 0xcc, 0x16, 0x9c, 0x56, 0x3b, 0x23, 0x82, 0x21, 0x13, 0x6b, 0x83, 0xfe, 0xfd, 0xcc, 0xc8, 0x9b, 0xd4, - 0x69, 0x99, 0xa5, 0xb4, 0xac, 0x59, 0xdb, 0x4e, 0x54, 0x6f, 0xe7, 0xd5, 0xd2, 0x71, 0x55, 0x04, 0xd4, 0xa6, 0x38, - 0xff, 0x3c, 0x05, 0x42, 0x18, 0x9a, 0x82, 0xdb, 0x96, 0x08, 0x73, 0x50, 0x4e, 0x22, 0xa9, 0xbe, 0xa1, 0xdc, 0xdd, - 0x07, 0x44, 0x28, 0x63, 0xa0, 0x04, 0x4c, 0x1d, 0xbf, 0x5c, 0xf4, 0xd8, 0xc0, 0xa0, 0x47, 0x53, 0xb4, 0x54, 0x92, - 0xc9, 0x0d, 0xdb, 0x4e, 0xfd, 0xdf, 0xf7, 0xa5, 0x34, 0x0a, 0x4a, 0xfb, 0x42, 0x2a, 0x9c, 0xdb, 0x89, 0x14, 0x2e, - 0xca, 0x30, 0x64, 0x2d, 0x1b, 0x27, 0xde, 0x70, 0xfc, 0x0e, 0xfd, 0x16, 0x03, 0x42, 0x94, 0x4b, 0xb1, 0x1f, 0x22, - 0x28, 0x17, 0xff, 0x7c, 0x6e, 0x2c, 0xe3, 0x7b, 0x80, 0x56, 0x40, 0xd3, 0x40, 0xe5, 0x34, 0x79, 0x8b, 0x0b, 0xf0, - 0x02, 0x16, 0xc0, 0xac, 0x40, 0xb9, 0xf2, 0x5a, 0xce, 0x52, 0x6b, 0xf8, 0x38, 0x74, 0xa7, 0x32, 0x46, 0x10, 0xf7, - 0x17, 0x80, 0xb2, 0xfe, 0xea, 0xf2, 0xdf, 0xbf, 0x39, 0x25, 0xdc, 0x00, 0xd5, 0xd1, 0x8f, 0x8b, 0x7b, 0x74, 0xf3, - 0xf0, 0xe1, 0xc6, 0xfa, 0x69, 0xdb, 0x13, 0x00, 0x3b, 0x99, 0x1c, 0x45, 0xcb, 0xd7, 0xce, 0xda, 0x5b, 0x80, 0xa3, - 0xf8, 0x94, 0x2e, 0x27, 0x33, 0x32, 0xa9, 0xfe, 0xf3, 0xe6, 0x5b, 0x60, 0x9b, 0x94, 0x24, 0x5e, 0x4d, 0xbd, 0x56, - 0xa4, 0x57, 0x81, 0xfa, 0x7f, 0x89, 0xf1, 0xcf, 0xff, 0x17, 0x97, 0xa1, 0x79, 0x6a, 0x94, 0x37, 0xf6, 0xef, 0x3a, - 0xbc, 0x23, 0xcc, 0x65, 0x2e, 0x22, 0x8b, 0x49, 0x25, 0x5d, 0x3b, 0x90, 0x29, 0xeb, 0x8b, 0x66, 0x46, 0xf1, 0x5d, - 0x17, 0xa0, 0x58, 0xf6, 0x12, 0xf5, 0x99, 0x4d, 0x17, 0x2e, 0x2d, 0x6e, 0x24, 0xa0, 0x55, 0x0d, 0xc8, 0x08, 0x43, - 0x97, 0x88, 0xc0, 0x57, 0xfd, 0x1d, 0x94, 0xb9, 0x94, 0x84, 0xa7, 0xf9, 0x26, 0xb8, 0xc2, 0x34, 0x14, 0x08, 0xdc, - 0xea, 0xaf, 0xb0, 0xd0, 0x35, 0x1d, 0x39, 0x31, 0xd3, 0xa6, 0xd5, 0xba, 0x12, 0x52, 0x1b, 0x78, 0xf2, 0x1f, 0x1d, - 0xf8, 0x3f, 0xc5, 0x46, 0x74, 0x14, 0x1f, 0x41, 0xe5, 0xc4, 0x0e, 0xa0, 0xb6, 0xa4, 0x04, 0x5e, 0x80, 0x4a, 0x90, - 0x33, 0x20, 0xd5, 0xb6, 0x2c, 0x10, 0x91, 0x96, 0x77, 0x07, 0xb2, 0x40, 0x32, 0xf4, 0x18, 0x25, 0x37, 0xc8, 0x30, - 0x21, 0x83, 0xd7, 0x21, 0x86, 0x9d, 0xde, 0x0a, 0x49, 0x30, 0x10, 0x8d, 0xf4, 0xf3, 0x64, 0x14, 0xb5, 0x87, 0xe4, - 0x4d, 0x0c, 0x28, 0x88, 0x5a, 0x87, 0x5a, 0x86, 0x0d, 0x98, 0x65, 0x13, 0x36, 0x12, 0x5f, 0x74, 0x55, 0xc0, 0x37, - 0x4b, 0x8b, 0x52, 0x72, 0x52, 0x88, 0x64, 0xac, 0xf3, 0x82, 0x89, 0x2d, 0x84, 0x36, 0xed, 0x5f, 0xce, 0x18, 0x17, - 0xe6, 0x02, 0xa4, 0x06, 0xee, 0x44, 0xf8, 0x26, 0xe6, 0x02, 0xb6, 0xd5, 0x31, 0x84, 0xd8, 0xd2, 0xb4, 0x0a, 0xcd, - 0x85, 0x37, 0x32, 0x51, 0x0a, 0x1c, 0x76, 0x4a, 0x88, 0x8b, 0xe4, 0xb2, 0xdb, 0x41, 0x7d, 0xd3, 0x94, 0x46, 0x26, - 0xa8, 0x09, 0x8a, 0x32, 0xa7, 0xd9, 0x8c, 0x18, 0x27, 0xc6, 0x85, 0x5c, 0xdb, 0xce, 0xa4, 0xd1, 0xce, 0x9a, 0x49, - 0x7f, 0x8e, 0xae, 0x19, 0x91, 0xf0, 0x52, 0xc1, 0x4f, 0xd4, 0xdb, 0xbf, 0x44, 0x69, 0x8a, 0x75, 0x0b, 0xb8, 0x76, - 0x31, 0xd3, 0xd2, 0x04, 0x63, 0x85, 0xde, 0x72, 0x81, 0x06, 0xe5, 0x2d, 0x50, 0x9c, 0x96, 0x38, 0x71, 0xf3, 0x91, - 0xbc, 0xc4, 0xc2, 0x99, 0xc4, 0x6e, 0x5d, 0xe3, 0x5e, 0xcb, 0xd5, 0x70, 0x1e, 0x01, 0x83, 0xb0, 0xd9, 0xa8, 0x8f, - 0x82, 0xec, 0xb6, 0xda, 0x30, 0x52, 0x7f, 0x38, 0xe8, 0xc5, 0x8f, 0xfa, 0x5b, 0xa3, 0x06, 0x8e, 0x36, 0x42, 0x79, - 0x9f, 0x90, 0xf8, 0x6b, 0xff, 0xc1, 0xca, 0x6e, 0x5c, 0x48, 0xa7, 0xee, 0x9c, 0x41, 0x63, 0x2b, 0x85, 0xfc, 0xeb, - 0xa4, 0x89, 0xfa, 0x39, 0x90, 0x38, 0xa7, 0x95, 0x3b, 0xc1, 0x64, 0x14, 0x36, 0x5e, 0xa3, 0x2f, 0x3b, 0xdd, 0x8e, - 0xcd, 0xd7, 0xc7, 0x71, 0x4e, 0x46, 0x12, 0xa2, 0x48, 0xef, 0x45, 0xb3, 0x81, 0x5a, 0x8f, 0x79, 0x1d, 0xc2, 0x89, - 0xb0, 0xf7, 0x91, 0xd6, 0xe8, 0xdd, 0x4a, 0x2d, 0x50, 0xfb, 0x6b, 0xd0, 0x67, 0xff, 0x14, 0xc3, 0x6f, 0x60, 0x0d, - 0x4c, 0x5d, 0x73, 0x67, 0x83, 0x18, 0x2d, 0xc9, 0x6c, 0xae, 0x8a, 0x24, 0xef, 0xdf, 0x18, 0x21, 0x1d, 0xd2, 0xa1, - 0xa9, 0xf6, 0xda, 0xd1, 0xdd, 0xef, 0x6c, 0x12, 0xe0, 0x44, 0xb5, 0xc1, 0x1a, 0xfe, 0xba, 0x7f, 0x73, 0x15, 0x88, - 0x82, 0x39, 0x9d, 0xd2, 0x16, 0x88, 0x02, 0x58, 0x92, 0x0e, 0x3f, 0x5f, 0xb7, 0xf8, 0x5e, 0x54, 0x0c, 0x7d, 0xc0, - 0x01, 0x59, 0xd5, 0x67, 0x86, 0x50, 0x1c, 0x13, 0x87, 0x90, 0x73, 0xb3, 0x2d, 0x09, 0xd1, 0xb5, 0x27, 0xb1, 0x90, - 0x96, 0xa4, 0xfa, 0x9b, 0x58, 0x84, 0x02, 0xbf, 0xaf, 0xd4, 0x3a, 0xbe, 0x5b, 0x6a, 0x5d, 0xdc, 0x25, 0xb5, 0x66, - 0xc7, 0x3d, 0x36, 0x7f, 0x52, 0x0e, 0x8c, 0x92, 0x38, 0x37, 0x5d, 0x40, 0x2b, 0xa2, 0x6e, 0xf2, 0xf3, 0x93, 0x5f, - 0x35, 0x5a, 0x63, 0xdb, 0x50, 0x12, 0x7f, 0x1b, 0x0c, 0x8a, 0x54, 0xa8, 0x9b, 0xb2, 0xf1, 0x37, 0x5a, 0x36, 0xce, - 0x5c, 0x8d, 0x76, 0xd9, 0x92, 0xd4, 0xbf, 0xe1, 0x0e, 0xa9, 0xb8, 0x03, 0xed, 0x16, 0xa9, 0x47, 0x6a, 0x38, 0xfa, - 0x69, 0x46, 0xc3, 0x70, 0x1f, 0x95, 0x5c, 0x46, 0xd5, 0x8b, 0xb4, 0x5a, 0x55, 0xfb, 0xf9, 0xe9, 0x72, 0x94, 0xba, - 0xd3, 0x90, 0x55, 0xb1, 0x79, 0x6c, 0xaa, 0x8e, 0x5e, 0xe6, 0x6b, 0xe3, 0x90, 0x28, 0x8f, 0x2c, 0x5e, 0x60, 0x29, - 0xa6, 0xaf, 0xe9, 0xb5, 0x95, 0x0d, 0x04, 0x0d, 0xb2, 0xc5, 0x81, 0xf4, 0x6e, 0xe9, 0x3c, 0xa7, 0xab, 0xd2, 0xaa, - 0xeb, 0x21, 0x61, 0x77, 0xd6, 0x04, 0x9b, 0xf2, 0x08, 0x5a, 0xeb, 0x23, 0x43, 0x82, 0xe0, 0x0d, 0x00, 0xb1, 0xb7, - 0x10, 0x00, 0x84, 0xff, 0xeb, 0xbf, 0x05, 0x29, 0x80, 0x92, 0xc8, 0xce, 0xc0, 0xd4, 0xf9, 0xd3, 0x25, 0xee, 0xb1, - 0xf9, 0x19, 0x55, 0x6d, 0xf6, 0xc9, 0xf2, 0x9e, 0x95, 0x70, 0xd7, 0xaa, 0x8a, 0xf3, 0x45, 0x0d, 0x4f, 0x8e, 0x43, - 0x9c, 0xb2, 0x6c, 0x99, 0x50, 0x16, 0xa2, 0x5e, 0x91, 0xc1, 0x78, 0x57, 0x46, 0x7f, 0x42, 0x24, 0x8a, 0xe2, 0xe2, - 0xaa, 0x52, 0x61, 0x14, 0x50, 0xd0, 0xee, 0xc8, 0xeb, 0x6f, 0xe5, 0x86, 0xa0, 0xc6, 0xfb, 0x62, 0xb0, 0x1d, 0x7c, - 0x3d, 0xdd, 0xa9, 0xc9, 0x4f, 0xb7, 0x76, 0xab, 0xd2, 0x75, 0x35, 0x8e, 0xf3, 0xf4, 0x37, 0xe1, 0xd8, 0xfa, 0xef, - 0xef, 0x3a, 0x17, 0x7d, 0xd6, 0xf6, 0xe8, 0x8f, 0x0c, 0x01, 0xbf, 0xaf, 0x28, 0xa6, 0x4d, 0x35, 0x4d, 0xa3, 0x64, - 0xdd, 0xb0, 0xa6, 0xf1, 0x7c, 0xde, 0x9b, 0xa3, 0x7b, 0xd1, 0xea, 0x0f, 0x4d, 0x8f, 0xda, 0x59, 0x62, 0xba, 0x88, - 0x3f, 0xd0, 0x4e, 0xf5, 0xa4, 0x14, 0x33, 0xa0, 0x47, 0x56, 0xa6, 0xa0, 0xdc, 0x90, 0x9f, 0x37, 0x65, 0xe6, 0x66, - 0xb7, 0xd3, 0xe9, 0xb4, 0x2a, 0x35, 0x1e, 0x74, 0x76, 0x48, 0xf2, 0xfb, 0xc5, 0x60, 0x30, 0xa8, 0xaf, 0xef, 0xba, - 0x8b, 0xc2, 0x17, 0xa3, 0x47, 0x42, 0xf8, 0xa7, 0x77, 0x9f, 0xa9, 0x7f, 0xd3, 0x68, 0xb9, 0xa9, 0x75, 0xf7, 0x91, - 0x8f, 0xda, 0xff, 0x17, 0x43, 0x21, 0xd0, 0x70, 0xd7, 0xf5, 0x6f, 0x9e, 0x95, 0x5b, 0x5a, 0xaa, 0x5f, 0xe0, 0xdf, - 0xf7, 0xf1, 0x1d, 0x67, 0xfd, 0x1e, 0x9f, 0xae, 0x3b, 0xde, 0x65, 0x5f, 0xa3, 0xdd, 0x8a, 0xcd, 0xd2, 0x88, 0x2d, - 0x95, 0xe2, 0x22, 0x3a, 0xcf, 0xbd, 0x49, 0x44, 0x0a, 0xd2, 0xbe, 0x81, 0x6d, 0xc9, 0xaa, 0xa7, 0x77, 0x86, 0x76, - 0x5c, 0x43, 0x09, 0x87, 0x07, 0x1d, 0x52, 0x56, 0x35, 0x34, 0x6b, 0xb2, 0x13, 0xc2, 0x62, 0xab, 0xa6, 0xc2, 0x89, - 0x8e, 0x29, 0x6c, 0x67, 0xa5, 0x5e, 0x07, 0xa9, 0xd3, 0x95, 0xb4, 0x36, 0x61, 0xe5, 0x09, 0xfd, 0xab, 0x94, 0x73, - 0x5f, 0xc3, 0x73, 0xc5, 0x5e, 0xeb, 0x29, 0xaa, 0x9b, 0x34, 0x2a, 0xe3, 0x51, 0xb7, 0x81, 0x3e, 0x65, 0x02, 0x34, - 0x35, 0xad, 0x5b, 0xd0, 0x82, 0xa6, 0x92, 0x1c, 0xb1, 0x45, 0x37, 0x46, 0xec, 0x2c, 0x9e, 0x3c, 0x2d, 0xdf, 0xd7, - 0xa9, 0xbd, 0x71, 0x0e, 0x6e, 0xf7, 0x29, 0x29, 0xf7, 0x2a, 0x47, 0x95, 0x4c, 0x65, 0xe8, 0x0c, 0x48, 0x8e, 0xb4, - 0xb3, 0xcc, 0xe6, 0x3d, 0xce, 0x1c, 0x08, 0xa8, 0xb3, 0x39, 0xef, 0xf5, 0xcd, 0x03, 0x26, 0xfd, 0xd2, 0x29, 0x9b, - 0x4b, 0x75, 0x2f, 0xd5, 0x5e, 0x5d, 0x87, 0x2d, 0xc7, 0x89, 0x3b, 0x80, 0xae, 0x28, 0x1d, 0x32, 0x1a, 0xea, 0xd4, - 0x60, 0x1f, 0x4f, 0x5a, 0xbd, 0x35, 0x81, 0xb5, 0x9c, 0x27, 0x35, 0xd7, 0x5e, 0x85, 0xdb, 0x96, 0x9a, 0x41, 0x5c, - 0x3b, 0x01, 0x9d, 0xe8, 0x77, 0x0f, 0x4f, 0x8c, 0x09, 0xae, 0x86, 0x74, 0x82, 0xe8, 0x96, 0xf6, 0x38, 0x22, 0x2d, - 0xdf, 0x52, 0xd2, 0x25, 0x7c, 0xdf, 0x2a, 0xbc, 0xff, 0x54, 0x91, 0xc6, 0x0b, 0x7f, 0xa0, 0x2d, 0xe7, 0x5e, 0xb5, - 0x81, 0x44, 0xb9, 0x7f, 0xdd, 0xe0, 0xea, 0xde, 0x75, 0x91, 0x38, 0xbc, 0x77, 0x65, 0xa4, 0x2e, 0xd9, 0x4a, 0xa9, - 0xf0, 0xbf, 0x37, 0x94, 0x07, 0x66, 0x2c, 0x0b, 0x8b, 0xbe, 0x62, 0x8e, 0xfe, 0xdd, 0x12, 0x18, 0xcd, 0xf1, 0xd5, - 0xf9, 0xbc, 0x03, 0x0c, 0x01, 0x66, 0x51, 0xf5, 0xad, 0x61, 0x7f, 0x60, 0x75, 0x28, 0x32, 0x03, 0xf4, 0xe0, 0x5b, - 0x3f, 0x7e, 0x7a, 0xd5, 0x7b, 0x6a, 0x8d, 0xd1, 0x1c, 0xe3, 0xe2, 0x8c, 0x48, 0xdc, 0x37, 0xc1, 0x75, 0x94, 0x1d, - 0x6f, 0x59, 0x1d, 0x4a, 0x96, 0xca, 0xc4, 0x2d, 0x95, 0x75, 0xa0, 0xec, 0xee, 0x9c, 0x7c, 0x1d, 0x99, 0x56, 0xdb, - 0x42, 0xc0, 0x3a, 0xdc, 0x7a, 0x0a, 0xff, 0xed, 0xf4, 0x1f, 0x3f, 0xb5, 0xf6, 0xff, 0xa3, 0xd3, 0xd9, 0x0b, 0xa3, - 0x69, 0xbe, 0x4f, 0xe2, 0x98, 0x3d, 0xa2, 0x07, 0xf9, 0xb9, 0xd3, 0xe9, 0x4f, 0xe6, 0x79, 0x6f, 0xd8, 0x59, 0x89, - 0x9f, 0x9d, 0x0e, 0x02, 0x23, 0xaf, 0xf3, 0xc5, 0x74, 0x6b, 0xba, 0x33, 0xfd, 0x7a, 0x24, 0x8a, 0xcb, 0xff, 0xa8, - 0x54, 0x77, 0xf9, 0xef, 0x96, 0xf1, 0x59, 0x5e, 0x64, 0xe9, 0xe7, 0x48, 0xd0, 0x92, 0x1d, 0x25, 0x28, 0xaa, 0x7f, - 0xba, 0xd5, 0xec, 0x69, 0xf8, 0xf4, 0x74, 0x32, 0xdd, 0xd2, 0xd5, 0x69, 0x8c, 0x9b, 0x6a, 0x90, 0x40, 0xd0, 0x8a, - 0xa1, 0xef, 0x99, 0xcb, 0x34, 0xec, 0xb5, 0x2d, 0xd4, 0xd0, 0x12, 0x73, 0x3c, 0x93, 0xf3, 0xdb, 0xc3, 0x90, 0xf7, - 0xda, 0x83, 0x23, 0xa7, 0xcf, 0x7c, 0xeb, 0x2d, 0xac, 0x8f, 0x3b, 0x1c, 0x3e, 0x86, 0xf5, 0x99, 0x0c, 0xdc, 0x9d, - 0xfe, 0x4e, 0x6f, 0xbb, 0xff, 0xd8, 0x7d, 0xda, 0x7b, 0xea, 0x3e, 0xfd, 0xee, 0xe9, 0xa4, 0x07, 0x05, 0xee, 0xa0, - 0xf7, 0x14, 0x0b, 0xe1, 0xdf, 0xa7, 0x17, 0xbd, 0x1d, 0xa8, 0x46, 0xa5, 0x5b, 0xfd, 0xdd, 0xdd, 0xde, 0x70, 0x00, - 0xff, 0xba, 0xbb, 0xfd, 0xc7, 0x8f, 0x7b, 0x43, 0xa8, 0xf2, 0xf8, 0xcd, 0xee, 0xd3, 0xfe, 0x36, 0xbe, 0xdb, 0xde, - 0x9e, 0x6c, 0xf7, 0x87, 0xc3, 0x1e, 0xfe, 0xe3, 0x3e, 0xed, 0x6f, 0xf1, 0xc3, 0x70, 0xd8, 0xdf, 0x1e, 0xba, 0x83, - 0xf9, 0xee, 0x56, 0xff, 0xf1, 0xd7, 0x2e, 0xfd, 0x4b, 0xd5, 0x5c, 0xfa, 0x07, 0x9b, 0x71, 0xbf, 0xee, 0x6f, 0x3d, - 0xe6, 0x27, 0x6a, 0xf0, 0x62, 0xe7, 0xe9, 0x2f, 0xd6, 0xe6, 0xda, 0x39, 0x0c, 0x79, 0x0e, 0x4f, 0x77, 0xa1, 0x43, - 0x77, 0x67, 0xd8, 0x7f, 0xba, 0x3d, 0xeb, 0xed, 0x40, 0xb3, 0x4f, 0x26, 0xbd, 0x61, 0xff, 0xc9, 0x13, 0x18, 0xfa, - 0x76, 0x7f, 0xcb, 0x1d, 0xf6, 0x77, 0xb6, 0xe9, 0x01, 0xfe, 0xbb, 0x78, 0xf2, 0x75, 0xff, 0xf1, 0xee, 0xec, 0x71, - 0x7f, 0xe7, 0xa7, 0x1d, 0x18, 0xd7, 0xf6, 0x6c, 0xfb, 0x71, 0x7f, 0xeb, 0xc9, 0x05, 0xfc, 0x9e, 0xf5, 0xb6, 0x1e, - 0xdf, 0xfa, 0xe5, 0x70, 0xab, 0x8f, 0x6b, 0x44, 0xaf, 0xf1, 0x85, 0x2b, 0x5e, 0xe0, 0x7f, 0x33, 0xfa, 0xf6, 0xdf, - 0xd8, 0x4c, 0xde, 0xfc, 0xf4, 0xeb, 0xfe, 0xd3, 0x27, 0x13, 0xae, 0x8e, 0x05, 0x3d, 0x59, 0x03, 0x3f, 0xb9, 0xe8, - 0x71, 0xb7, 0xd4, 0x5c, 0x4f, 0x36, 0x24, 0xff, 0x13, 0x9d, 0x5d, 0xf4, 0xb0, 0x63, 0xee, 0xf7, 0x7f, 0xb5, 0x1d, - 0xb5, 0xe5, 0x7b, 0x9b, 0x67, 0x7c, 0xf4, 0xe1, 0x0f, 0xe7, 0xd7, 0x3c, 0x71, 0x7f, 0x5b, 0xa7, 0x94, 0xfc, 0xf5, - 0x6e, 0xa5, 0xe4, 0x37, 0xcb, 0xfb, 0x28, 0x25, 0x7f, 0xfd, 0xd3, 0x95, 0x92, 0xbf, 0xd5, 0x7d, 0x6b, 0x5e, 0xd5, - 0xd3, 0x80, 0x7d, 0xbf, 0xaa, 0x8b, 0x1c, 0x92, 0xc0, 0x3e, 0x7c, 0xb7, 0x3c, 0xc2, 0xd0, 0x7e, 0x50, 0xfb, 0x9b, - 0x65, 0xc5, 0xe0, 0x33, 0x45, 0x18, 0xfb, 0x2a, 0x65, 0x18, 0xfb, 0xd3, 0xd2, 0x47, 0x2b, 0x33, 0x41, 0xe6, 0xc4, - 0x61, 0x6f, 0x16, 0xcc, 0xa7, 0x8a, 0x44, 0xc2, 0x92, 0x11, 0x15, 0xa3, 0xe3, 0x1a, 0xa2, 0x67, 0xe4, 0x64, 0x96, - 0xe7, 0x49, 0x8e, 0x16, 0xc1, 0x68, 0xc9, 0x31, 0x05, 0x7a, 0xa9, 0xfa, 0x71, 0x5f, 0x06, 0x43, 0x3c, 0x16, 0x5e, - 0x50, 0x6b, 0xdf, 0x93, 0x01, 0x70, 0x7b, 0xeb, 0xc3, 0x66, 0xbb, 0x1d, 0xb4, 0xac, 0x93, 0x06, 0xd2, 0x48, 0xed, - 0xb7, 0xbd, 0xaf, 0x9a, 0xe1, 0xd6, 0x0c, 0xaf, 0xd7, 0x8f, 0x14, 0x47, 0x52, 0xff, 0x7e, 0x58, 0x35, 0xe3, 0xbd, - 0x6b, 0x9a, 0x2d, 0xdd, 0x57, 0x3e, 0xbf, 0xc5, 0x86, 0x58, 0x35, 0x5c, 0x5f, 0xaa, 0x5a, 0x12, 0xeb, 0xd6, 0x05, - 0xd1, 0x0c, 0xaa, 0x36, 0x34, 0xd6, 0x94, 0x2a, 0xe0, 0x30, 0x92, 0x1a, 0x18, 0xef, 0x2a, 0x6d, 0x9a, 0xc6, 0xc9, - 0x8f, 0x56, 0xc4, 0x57, 0xc4, 0xbf, 0x21, 0x25, 0x2a, 0x28, 0x1e, 0x28, 0x31, 0xba, 0x5d, 0x19, 0xed, 0xb2, 0x34, - 0xa2, 0x9c, 0x0d, 0x57, 0x4d, 0x5a, 0x74, 0xad, 0x5b, 0xc2, 0x30, 0x3a, 0x97, 0x54, 0x10, 0x75, 0xcf, 0x4e, 0x00, - 0x25, 0x3b, 0x6a, 0x90, 0x9f, 0xc3, 0x6d, 0x8d, 0xc9, 0x7a, 0x5f, 0xe0, 0x21, 0x16, 0x31, 0x99, 0x3b, 0x66, 0xb4, - 0x19, 0xa0, 0xd6, 0xd3, 0xa0, 0xf0, 0x88, 0x4c, 0x33, 0x48, 0xde, 0x2d, 0xf2, 0x58, 0x18, 0xdd, 0x62, 0x4c, 0x67, - 0x36, 0x2c, 0x1a, 0x21, 0xcf, 0x87, 0xdb, 0xec, 0xef, 0x94, 0xc3, 0xd9, 0xaa, 0x62, 0x8e, 0x32, 0xdc, 0x85, 0x3a, - 0x8f, 0xdd, 0xfe, 0x13, 0xa8, 0x23, 0x2f, 0x9c, 0xd9, 0x64, 0x65, 0x41, 0xd0, 0x01, 0x42, 0x0d, 0x33, 0x4e, 0x80, - 0x8c, 0x0d, 0xe6, 0x25, 0xd2, 0xc3, 0x55, 0x26, 0xe5, 0xd7, 0x65, 0x5e, 0xe0, 0x1c, 0x25, 0xd1, 0x4b, 0xce, 0x1f, - 0xbd, 0xd3, 0xa8, 0xb8, 0x8c, 0xa2, 0x64, 0x8d, 0x61, 0x4c, 0xdd, 0x97, 0xe4, 0x5f, 0x67, 0x59, 0x5f, 0xb2, 0xd5, - 0xda, 0x69, 0x91, 0x88, 0xf3, 0x21, 0x1d, 0x1f, 0xca, 0x13, 0xf7, 0xbb, 0x75, 0x00, 0xf7, 0xc7, 0xbb, 0x01, 0x6e, - 0x11, 0xdd, 0x07, 0xe0, 0xfe, 0xf8, 0xa7, 0x03, 0xdc, 0xef, 0x4c, 0x80, 0x5b, 0xf1, 0x1f, 0xd4, 0x1a, 0xa6, 0x03, - 0xfa, 0x6d, 0x63, 0x66, 0x94, 0xae, 0xb5, 0xc9, 0x04, 0xbc, 0xe5, 0xe8, 0xf4, 0x41, 0x3f, 0x57, 0x12, 0xb5, 0x92, - 0x00, 0x94, 0xb2, 0x6e, 0x70, 0x52, 0xc8, 0x18, 0x5d, 0xdd, 0x54, 0x62, 0x48, 0x68, 0xf3, 0x75, 0x52, 0xcc, 0xfb, - 0x1f, 0x05, 0x1f, 0x89, 0x0a, 0xdd, 0x57, 0xb0, 0xa4, 0x01, 0x45, 0x7f, 0xb5, 0x28, 0xc1, 0x3b, 0xfe, 0x18, 0xa0, - 0x33, 0x2e, 0x34, 0x19, 0x2a, 0xad, 0x64, 0xe4, 0x1f, 0x32, 0xc5, 0x6d, 0x5d, 0x47, 0x41, 0x66, 0xb9, 0xfc, 0x1a, - 0x37, 0xf7, 0xd1, 0xf6, 0xe0, 0xd1, 0xd6, 0xce, 0xa3, 0xc7, 0x03, 0xfc, 0xff, 0x61, 0xb4, 0x5d, 0xba, 0xa2, 0xe2, - 0x39, 0x1c, 0xa1, 0x99, 0xae, 0xb9, 0xae, 0x1a, 0x1c, 0xac, 0xcf, 0xba, 0xd6, 0x93, 0xf6, 0x4a, 0x61, 0x70, 0xad, - 0xeb, 0xb4, 0xd6, 0x98, 0xc1, 0x32, 0xe9, 0x2a, 0x2d, 0xa3, 0x89, 0x93, 0x25, 0xca, 0xd9, 0x8d, 0x1a, 0xe6, 0x6b, - 0x31, 0x5d, 0x3d, 0x2f, 0x78, 0x77, 0xa4, 0x13, 0xd9, 0xca, 0x7c, 0x46, 0x77, 0xae, 0xa0, 0x50, 0x51, 0x0e, 0x28, - 0x1c, 0x38, 0x25, 0x9a, 0xc0, 0x60, 0xe0, 0x2a, 0xfd, 0x68, 0xc0, 0x1b, 0x54, 0x64, 0xb0, 0x7b, 0x36, 0x3d, 0x02, - 0x27, 0x69, 0xc7, 0x9b, 0x59, 0x5f, 0x74, 0xec, 0xd0, 0xae, 0x05, 0xfb, 0x03, 0x9d, 0xf5, 0x2f, 0x97, 0xbb, 0x12, - 0x3c, 0x2a, 0xdc, 0x8c, 0xf4, 0xd8, 0xbc, 0xb5, 0x3d, 0x3f, 0x78, 0xa4, 0x3e, 0x84, 0x77, 0x49, 0x17, 0x75, 0x9f, - 0xfe, 0xe0, 0xe1, 0x43, 0xae, 0xb5, 0xe1, 0xcb, 0x69, 0x8d, 0x27, 0x3a, 0x68, 0x68, 0x27, 0x00, 0xb4, 0x4c, 0x71, - 0x43, 0xbd, 0x89, 0x9b, 0x76, 0xbb, 0xfb, 0xfe, 0xd0, 0xa1, 0x8c, 0xb2, 0x32, 0x33, 0xbc, 0x48, 0x56, 0xfc, 0xe6, - 0x7e, 0x86, 0x46, 0x32, 0xaf, 0x63, 0xd5, 0x95, 0x76, 0x81, 0x3c, 0xd3, 0x40, 0xba, 0x23, 0x08, 0xe8, 0x85, 0xc9, - 0x03, 0xd9, 0xa0, 0x20, 0x90, 0x06, 0x3f, 0xb2, 0x8e, 0xe2, 0xba, 0xb6, 0xfb, 0x03, 0xe0, 0xbb, 0xd4, 0x87, 0xd3, - 0xf8, 0xcc, 0x5f, 0xa5, 0x45, 0x80, 0x69, 0x58, 0x01, 0xbc, 0xa1, 0x1f, 0x1d, 0x60, 0xc0, 0x39, 0xe6, 0xf4, 0x44, - 0x87, 0xba, 0x73, 0xe6, 0xcb, 0x4b, 0xe1, 0xdd, 0x10, 0x64, 0x9f, 0x29, 0xaf, 0xbb, 0x74, 0xc5, 0xa5, 0x38, 0x76, - 0x6f, 0x11, 0x19, 0xda, 0x96, 0x8d, 0xb2, 0x01, 0xe8, 0xa5, 0x67, 0x7a, 0x0b, 0x79, 0x1d, 0xfc, 0xc6, 0xb1, 0xc4, - 0x24, 0xa6, 0x19, 0xf0, 0x26, 0x39, 0x9c, 0x74, 0x38, 0x16, 0x0c, 0x85, 0x2c, 0x01, 0x6a, 0x3b, 0xc3, 0xaf, 0x1f, - 0xbb, 0x9d, 0x2d, 0xe0, 0xa4, 0x06, 0x08, 0x6e, 0xa1, 0xc7, 0x15, 0x1c, 0x8f, 0xbb, 0x0c, 0x1e, 0x18, 0xbe, 0x7c, - 0xc1, 0xf3, 0x60, 0x53, 0x07, 0xa1, 0x4a, 0x2a, 0x38, 0x7e, 0xb1, 0x6d, 0x24, 0x34, 0x89, 0x59, 0xe9, 0xf9, 0x09, - 0x96, 0xdb, 0xa1, 0x9c, 0x97, 0xa2, 0x0a, 0x5c, 0x6e, 0x72, 0x18, 0x8e, 0x93, 0x4e, 0x7c, 0x73, 0x03, 0xd5, 0xe0, - 0x87, 0x6f, 0xac, 0x0f, 0xfe, 0x76, 0x2a, 0x0b, 0x16, 0x6b, 0x35, 0x3d, 0x2d, 0x16, 0x7a, 0x1a, 0xe2, 0x5f, 0x5d, - 0x2c, 0x1f, 0x84, 0x99, 0x04, 0x6c, 0x08, 0x6c, 0x57, 0x4c, 0x7f, 0x1a, 0xe6, 0x58, 0xec, 0xf3, 0x5c, 0x2b, 0xd5, - 0x4d, 0x69, 0x53, 0xa9, 0xfc, 0x9b, 0xeb, 0x4f, 0x9c, 0xd3, 0xd7, 0xb6, 0x10, 0xcb, 0x91, 0x8b, 0xae, 0xd6, 0xe4, - 0x76, 0xfd, 0xaf, 0xf6, 0xce, 0xa3, 0x22, 0x60, 0x35, 0x10, 0x32, 0xbf, 0x48, 0x0e, 0x74, 0x04, 0xa2, 0x11, 0xb1, - 0xa1, 0x7c, 0x0e, 0x73, 0xce, 0x78, 0xc2, 0xed, 0x08, 0x3c, 0xd5, 0x23, 0x8b, 0x4f, 0x7f, 0xe8, 0xb2, 0xc3, 0x01, - 0xfc, 0x40, 0xa9, 0xa1, 0x9f, 0xa4, 0xd6, 0xfe, 0x57, 0xca, 0x37, 0x73, 0xdd, 0x26, 0x00, 0x16, 0xfc, 0x7c, 0x98, - 0x45, 0xf3, 0xff, 0xf6, 0xbf, 0x42, 0xc4, 0xfd, 0xd5, 0x11, 0x6c, 0x44, 0xd1, 0x9f, 0xc1, 0x69, 0xf0, 0xbf, 0x6a, - 0x49, 0x30, 0x4f, 0xec, 0x3d, 0x8f, 0xc5, 0xda, 0xde, 0xd2, 0x21, 0xe7, 0xb6, 0xef, 0xc5, 0xd4, 0xef, 0x0b, 0x6e, - 0x1d, 0x39, 0xc0, 0x55, 0x85, 0xc7, 0x1e, 0x8e, 0x88, 0x7f, 0x3e, 0x85, 0x4b, 0xf8, 0x79, 0xc4, 0x6f, 0x2a, 0x3f, - 0x7a, 0x88, 0xad, 0x27, 0xc1, 0xc2, 0x23, 0xf4, 0x6a, 0x16, 0xa2, 0xf7, 0x34, 0x97, 0x2a, 0xca, 0xae, 0xf5, 0x2c, - 0xd3, 0x51, 0x5e, 0x51, 0xcf, 0xd4, 0xd5, 0xe5, 0x2c, 0x2e, 0x22, 0xd9, 0x15, 0xfd, 0x28, 0x4b, 0xc9, 0xa8, 0x33, - 0x8b, 0x4a, 0x8c, 0x75, 0x7f, 0xbb, 0x33, 0x7c, 0xfa, 0xdd, 0xee, 0xc5, 0x70, 0x30, 0xdb, 0x02, 0xd6, 0xf4, 0xa7, - 0xe1, 0xd3, 0xd9, 0x76, 0xff, 0xc9, 0x1c, 0x18, 0x9c, 0x27, 0xf8, 0xdf, 0x4f, 0x4f, 0xfa, 0x4f, 0x81, 0x61, 0x02, - 0x46, 0x74, 0xb8, 0x35, 0xef, 0x3d, 0x85, 0x42, 0xf8, 0xef, 0x0d, 0x7f, 0x85, 0x0c, 0x10, 0xf3, 0x3b, 0x5f, 0x55, - 0xa0, 0x80, 0xf1, 0xac, 0x74, 0xb2, 0x6e, 0x05, 0xbd, 0xb5, 0xe8, 0x75, 0x11, 0x64, 0x70, 0xc6, 0x1f, 0x32, 0x45, - 0x18, 0xd9, 0x89, 0x1f, 0x71, 0x8e, 0x1f, 0x69, 0xde, 0x26, 0xfd, 0xd0, 0x65, 0xa2, 0x95, 0xd6, 0x6b, 0x24, 0xbe, - 0x69, 0x4f, 0x2e, 0x22, 0x93, 0x00, 0xb3, 0x22, 0xf8, 0xc7, 0x05, 0x85, 0xc6, 0x93, 0x39, 0xb1, 0x0c, 0xa8, 0xa4, - 0x13, 0xd1, 0x97, 0x77, 0x0f, 0x9c, 0xbc, 0xf9, 0x23, 0x95, 0x08, 0xf5, 0x4f, 0x6d, 0xdb, 0x48, 0x3d, 0xf6, 0x87, - 0xda, 0xa1, 0xa4, 0x4c, 0x3a, 0x9f, 0x12, 0x46, 0x14, 0x0f, 0xe3, 0x4c, 0x0d, 0xcf, 0x00, 0xd1, 0xc3, 0xf6, 0xac, - 0x2c, 0x0e, 0x66, 0x8c, 0x7c, 0x8d, 0x54, 0xf2, 0x45, 0x30, 0x37, 0x0c, 0xd9, 0x8c, 0x2f, 0x37, 0x14, 0xe4, 0x7f, - 0xf8, 0x50, 0x0f, 0xae, 0x57, 0x1b, 0xf7, 0xde, 0x70, 0x17, 0xd1, 0x2e, 0xfc, 0x73, 0xab, 0x4d, 0x65, 0x74, 0x67, - 0x2c, 0x7a, 0x1d, 0x84, 0x5a, 0xda, 0x4d, 0x49, 0x8b, 0x8d, 0xb5, 0x86, 0x9d, 0x0d, 0x7b, 0x0d, 0x8c, 0xe2, 0x5f, - 0x63, 0x75, 0x00, 0x3a, 0x24, 0xd2, 0xfc, 0x20, 0xb9, 0x25, 0xfe, 0xbe, 0xe0, 0xc5, 0x2c, 0x5c, 0x9a, 0x5b, 0xe6, - 0x71, 0x87, 0x83, 0xf8, 0xff, 0xf6, 0x24, 0xc8, 0x59, 0x13, 0xed, 0x25, 0x6a, 0xb7, 0xb5, 0xe2, 0xbc, 0xa7, 0xf0, - 0x2a, 0x23, 0xd4, 0x28, 0x1f, 0x5b, 0x58, 0x84, 0xa9, 0x84, 0x29, 0x7b, 0xb8, 0x32, 0x16, 0x55, 0xd8, 0x42, 0x17, - 0xb8, 0x31, 0xe5, 0x3a, 0x91, 0x8e, 0xa3, 0x40, 0x19, 0xaf, 0x45, 0x42, 0x6c, 0x9c, 0x03, 0xc7, 0x4c, 0xe5, 0x37, - 0xb5, 0x4c, 0xf8, 0x66, 0x99, 0x20, 0x46, 0xb5, 0x4b, 0x50, 0x43, 0xda, 0xb8, 0xf2, 0xd9, 0xa3, 0xc7, 0xd3, 0x28, - 0x80, 0xed, 0x60, 0x65, 0xa9, 0x6d, 0x20, 0x77, 0x17, 0x08, 0x3b, 0xb4, 0x6e, 0x15, 0x11, 0x34, 0x55, 0x9a, 0x44, - 0xa0, 0xa2, 0x7b, 0xaa, 0x8d, 0x9b, 0x81, 0x0e, 0x40, 0xf6, 0xbe, 0x08, 0x38, 0x30, 0x8c, 0x89, 0x72, 0x81, 0x22, - 0x91, 0x29, 0x3b, 0x91, 0x2e, 0x1f, 0xdd, 0x15, 0xf9, 0x61, 0xff, 0xfd, 0xa7, 0x67, 0x1d, 0x71, 0xfe, 0xd9, 0x5a, - 0x80, 0x18, 0x19, 0xce, 0xfc, 0xe3, 0x73, 0xe6, 0x9f, 0x8e, 0x48, 0x32, 0x65, 0x51, 0xce, 0x46, 0x5e, 0x41, 0x12, - 0x40, 0xb3, 0x0d, 0xc5, 0x39, 0xec, 0x4b, 0x0c, 0x20, 0xae, 0xd8, 0xa4, 0xb4, 0x3f, 0x08, 0xe4, 0xac, 0x75, 0xf1, - 0x20, 0xd8, 0x0c, 0x43, 0x06, 0x6e, 0x2d, 0x12, 0x69, 0x87, 0x01, 0x68, 0x41, 0x99, 0x61, 0xc8, 0x0e, 0x82, 0xc9, - 0x24, 0x5a, 0x00, 0x7e, 0x33, 0xd3, 0x0b, 0xa5, 0x70, 0xa1, 0x81, 0x53, 0x2c, 0x80, 0x2a, 0x3c, 0xb7, 0x54, 0x80, - 0xf0, 0x66, 0x7b, 0xf9, 0xf2, 0xf4, 0x3c, 0x2e, 0x54, 0x84, 0x5d, 0x9e, 0x20, 0x1a, 0x44, 0xe0, 0x10, 0xf7, 0x4f, - 0x4a, 0xb1, 0x84, 0x6f, 0xd2, 0xb3, 0xda, 0x89, 0xd2, 0x94, 0xcb, 0x98, 0xe2, 0xb7, 0x33, 0x27, 0x83, 0xd2, 0x62, - 0xd8, 0xf1, 0x63, 0x11, 0xc3, 0x42, 0x05, 0x02, 0x86, 0x16, 0x05, 0x7b, 0xdb, 0xa1, 0xf0, 0x2d, 0xd6, 0xee, 0x00, - 0x23, 0xd4, 0xaf, 0x8b, 0x6e, 0xb1, 0x29, 0x2a, 0x23, 0x6a, 0xe2, 0x96, 0x29, 0xc9, 0x08, 0x8f, 0xe5, 0x13, 0x12, - 0x42, 0x15, 0x83, 0x99, 0xd9, 0x70, 0x5f, 0xb9, 0x53, 0xd2, 0xa8, 0x88, 0x56, 0xba, 0xb9, 0x79, 0x7e, 0xf2, 0x3f, - 0xff, 0x07, 0x33, 0xa1, 0xc0, 0x7b, 0x11, 0x53, 0xe2, 0xd0, 0xac, 0x25, 0xa8, 0x4f, 0xf7, 0x84, 0x8c, 0xa5, 0xa2, - 0x50, 0x86, 0xe8, 0x91, 0x47, 0xab, 0x3c, 0x39, 0x92, 0x21, 0x1a, 0x31, 0x87, 0x92, 0x23, 0x23, 0x5f, 0x50, 0x4a, - 0xce, 0x13, 0x19, 0x13, 0xa5, 0xf3, 0xf7, 0xab, 0x6f, 0x9e, 0x74, 0x74, 0x0c, 0xa3, 0x36, 0x8b, 0x1e, 0x3e, 0x43, - 0xfb, 0x7b, 0x41, 0x87, 0x88, 0x16, 0x22, 0x3f, 0x72, 0xa0, 0x3f, 0x60, 0x9a, 0xb3, 0xf4, 0x3c, 0xea, 0xc7, 0xe9, - 0xe6, 0x65, 0x74, 0xda, 0x0b, 0x16, 0x31, 0xdb, 0xe5, 0x90, 0xdc, 0xad, 0xc3, 0x94, 0x9f, 0x32, 0x77, 0x61, 0xfa, - 0xba, 0xd4, 0x4b, 0x99, 0x56, 0x63, 0x72, 0xee, 0x6e, 0x69, 0x3d, 0x20, 0xc6, 0x2f, 0x30, 0xd6, 0x31, 0x85, 0xc7, - 0x60, 0xbf, 0x1a, 0x14, 0xb8, 0x2f, 0x93, 0xdb, 0x54, 0x91, 0xc0, 0x98, 0x63, 0xfb, 0xca, 0x30, 0xbe, 0xfa, 0x47, - 0x2f, 0x9d, 0x4e, 0xcd, 0x40, 0xbe, 0xfd, 0xea, 0xf0, 0xd4, 0xa2, 0xe9, 0x23, 0x9d, 0x2e, 0xb8, 0xa7, 0x66, 0x17, - 0xea, 0xd1, 0xf2, 0x28, 0x82, 0x37, 0xce, 0x19, 0xaf, 0x7b, 0x23, 0x20, 0xb0, 0x5a, 0xb1, 0x2f, 0xb8, 0x92, 0x80, - 0x23, 0xf5, 0xf4, 0x13, 0x6b, 0x28, 0x97, 0x0d, 0xdf, 0x67, 0x30, 0x57, 0x87, 0x76, 0xb8, 0x88, 0x2d, 0x89, 0x7e, - 0x70, 0xb2, 0x05, 0x7e, 0xd8, 0x63, 0x77, 0x59, 0xfa, 0xa8, 0x3e, 0x9d, 0xe6, 0x18, 0x61, 0x69, 0x2b, 0xb9, 0x6e, - 0xc4, 0x01, 0xc5, 0x83, 0x27, 0xf6, 0x1d, 0xe1, 0xbb, 0x6c, 0xa7, 0x06, 0xe6, 0x3b, 0xff, 0xc9, 0x10, 0xbd, 0x37, - 0x0f, 0xae, 0x53, 0xc3, 0x8c, 0x49, 0x44, 0x34, 0x79, 0x43, 0xa5, 0x9f, 0xa4, 0x27, 0x71, 0xe3, 0xa2, 0x45, 0x32, - 0x21, 0x4a, 0xf3, 0xb2, 0x69, 0xfc, 0x3b, 0x8f, 0xee, 0xba, 0x6b, 0x66, 0xdd, 0xea, 0x64, 0x08, 0x78, 0x96, 0xfa, - 0x1e, 0x56, 0x5e, 0x12, 0x58, 0x80, 0x97, 0x38, 0x3f, 0x8c, 0xc2, 0x52, 0x21, 0x9c, 0x00, 0x95, 0xc4, 0x44, 0x35, - 0x10, 0x3e, 0x7d, 0x1d, 0x4a, 0x9a, 0x8f, 0x18, 0x4b, 0x23, 0xcd, 0x9f, 0x51, 0xa5, 0x49, 0xcb, 0x0c, 0xda, 0x89, - 0xc0, 0xbb, 0xb3, 0x07, 0xfd, 0xb4, 0xa4, 0xd4, 0x41, 0xe5, 0x08, 0xea, 0x8b, 0x20, 0x07, 0x6f, 0x8a, 0x35, 0x71, - 0x10, 0xd6, 0x55, 0x61, 0x7a, 0xf6, 0x96, 0x0a, 0xfa, 0x1c, 0xdf, 0x56, 0x4b, 0x53, 0x4e, 0xaa, 0xda, 0x19, 0xb0, - 0xb3, 0x5f, 0xd0, 0x89, 0x6f, 0xd4, 0xa6, 0x52, 0xac, 0x07, 0xdc, 0x3b, 0x56, 0x95, 0xb2, 0x78, 0x80, 0xee, 0x5c, - 0xd9, 0x19, 0xc1, 0x6e, 0x10, 0x5b, 0xba, 0xcf, 0x27, 0x6c, 0x7f, 0x0f, 0x4d, 0xb9, 0x79, 0xd3, 0xa1, 0x96, 0xd8, - 0x52, 0x7e, 0xe2, 0x37, 0x9b, 0xb3, 0xe2, 0x7c, 0xbe, 0xff, 0xff, 0x00, 0x04, 0xdf, 0xdf, 0xf4, 0x2c, 0x6c, 0x03, - 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x69, 0x7b, 0x1b, 0x37, 0xb2, 0x30, 0xfa, + 0xf9, 0xde, 0x5f, 0x21, 0xf5, 0x71, 0x34, 0x0d, 0x11, 0x6c, 0x91, 0xd4, 0x62, 0xb9, 0x29, 0x88, 0xd7, 0xeb, 0xd8, + 0x59, 0x6c, 0xc7, 0xb2, 0x9d, 0x49, 0x18, 0x1e, 0x07, 0xec, 0x06, 0x49, 0xc4, 0x4d, 0x80, 0x69, 0x80, 0x96, 0x14, + 0x92, 0xff, 0xfd, 0x3e, 0x85, 0xa5, 0x1b, 0x4d, 0xd2, 0x9e, 0x39, 0xef, 0x5d, 0x9e, 0xf7, 0xe4, 0x8c, 0xc5, 0xc6, + 0x8e, 0x42, 0xa1, 0x50, 0x55, 0xa8, 0x2a, 0x5c, 0x1d, 0xe6, 0x32, 0xd3, 0xf7, 0x0b, 0x76, 0x30, 0xd3, 0xf3, 0xe2, + 0xfa, 0xca, 0xfd, 0xcb, 0x68, 0x7e, 0x7d, 0x55, 0x70, 0xf1, 0xf9, 0xa0, 0x64, 0x05, 0xe1, 0x99, 0x14, 0x07, 0xb3, + 0x92, 0x4d, 0x48, 0x4e, 0x35, 0x4d, 0xf9, 0x9c, 0x4e, 0xd9, 0xc1, 0xc9, 0xf5, 0xd5, 0x9c, 0x69, 0x7a, 0x90, 0xcd, + 0x68, 0xa9, 0x98, 0x26, 0x1f, 0xde, 0xbf, 0x68, 0x5f, 0x5e, 0x5f, 0xa9, 0xac, 0xe4, 0x0b, 0x7d, 0x00, 0x4d, 0x92, + 0xb9, 0xcc, 0x97, 0x05, 0xbb, 0x3e, 0x39, 0xb9, 0xbd, 0xbd, 0x4d, 0xfe, 0x54, 0xff, 0xe7, 0x17, 0x5a, 0x1e, 0xfc, + 0xb3, 0x24, 0x6f, 0xc6, 0x7f, 0xb2, 0x4c, 0x27, 0x39, 0x9b, 0x70, 0xc1, 0xde, 0x96, 0x72, 0xc1, 0x4a, 0x7d, 0xdf, + 0x87, 0xcc, 0x9f, 0x4b, 0x12, 0x73, 0xac, 0x31, 0x43, 0xe4, 0x5a, 0x1f, 0x70, 0x71, 0xc0, 0x07, 0xff, 0x2c, 0x4d, + 0xca, 0x8a, 0x89, 0xe5, 0x9c, 0x95, 0x74, 0x5c, 0xb0, 0xf4, 0xb0, 0x83, 0x33, 0x29, 0x26, 0x7c, 0xba, 0xac, 0xbe, + 0x6f, 0x4b, 0xae, 0xfd, 0xef, 0x2f, 0xb4, 0x58, 0xb2, 0x94, 0x6d, 0x50, 0xca, 0x87, 0x7a, 0x44, 0x98, 0x69, 0xf9, + 0x73, 0xdd, 0x70, 0xfc, 0xb3, 0x69, 0xf2, 0x7e, 0xc1, 0xe4, 0xe4, 0x40, 0x1f, 0x92, 0x48, 0xdd, 0xcf, 0xc7, 0xb2, + 0x88, 0x06, 0xba, 0x15, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0xf5, 0x33, 0x29, 0x94, 0x3e, 0x10, 0x9c, 0xdc, 0x72, 0x91, + 0xcb, 0x5b, 0x7c, 0x2b, 0x88, 0xe0, 0xc9, 0xcd, 0x8c, 0xe6, 0xf2, 0xf6, 0x9d, 0x94, 0xfa, 0xe8, 0x28, 0x76, 0xdf, + 0xf7, 0x4f, 0x6f, 0x6e, 0x08, 0x21, 0x5f, 0x24, 0xcf, 0x0f, 0x3a, 0xeb, 0x75, 0x90, 0x9a, 0x08, 0xaa, 0xf9, 0x17, + 0x66, 0x2b, 0xa1, 0xa3, 0xa3, 0x88, 0xe6, 0x72, 0xa1, 0x59, 0x7e, 0xa3, 0xef, 0x0b, 0x76, 0x33, 0x63, 0x4c, 0xab, + 0x88, 0x8b, 0x83, 0x67, 0x32, 0x5b, 0xce, 0x99, 0xd0, 0xc9, 0xa2, 0x94, 0x5a, 0xc2, 0xc0, 0x8e, 0x8e, 0xa2, 0x92, + 0x2d, 0x0a, 0x9a, 0x31, 0xc8, 0x7f, 0x7a, 0x73, 0x53, 0xd7, 0xa8, 0x0b, 0xe1, 0xcf, 0x82, 0xdc, 0x98, 0xa1, 0xc7, + 0x08, 0xff, 0x22, 0x88, 0x60, 0xb7, 0x07, 0xbf, 0x30, 0xfa, 0xf9, 0x27, 0xba, 0xe8, 0x67, 0x05, 0x55, 0xea, 0xe0, + 0xb5, 0x5c, 0x99, 0x69, 0x94, 0xcb, 0x4c, 0xcb, 0x32, 0xd6, 0x98, 0x61, 0x81, 0x56, 0x7c, 0x12, 0xeb, 0x19, 0x57, + 0xc9, 0xa7, 0x07, 0x99, 0x52, 0xef, 0x98, 0x5a, 0x16, 0xfa, 0x01, 0x39, 0xec, 0x60, 0x71, 0x48, 0xc8, 0x67, 0x81, + 0xf4, 0xac, 0x94, 0xb7, 0x07, 0xcf, 0xcb, 0x52, 0x96, 0x71, 0xf4, 0xf4, 0xe6, 0xc6, 0x96, 0x38, 0xe0, 0xea, 0x40, + 0x48, 0x7d, 0x50, 0xb5, 0x07, 0xd0, 0x4e, 0x0e, 0x3e, 0x28, 0x76, 0xf0, 0xc7, 0x52, 0x28, 0x3a, 0x61, 0x4f, 0x6f, + 0x6e, 0xfe, 0x38, 0x90, 0xe5, 0xc1, 0x1f, 0x99, 0x52, 0x7f, 0x1c, 0x70, 0xa1, 0x34, 0xa3, 0x79, 0x12, 0xa1, 0xbe, + 0xe9, 0x2c, 0x53, 0xea, 0x3d, 0xbb, 0xd3, 0x44, 0x63, 0xf3, 0xa9, 0x09, 0xdb, 0x4c, 0x99, 0x3e, 0x50, 0xd5, 0xbc, + 0x62, 0xb4, 0x2a, 0x98, 0x3e, 0xd0, 0xc4, 0xe4, 0x4b, 0x07, 0x7f, 0x66, 0x3f, 0x75, 0x9f, 0x4f, 0xe2, 0x5b, 0x71, + 0x74, 0xa4, 0x2b, 0x40, 0xa3, 0x95, 0x5b, 0x21, 0xc2, 0x0e, 0x7d, 0xda, 0xd1, 0x11, 0x4b, 0x0a, 0x26, 0xa6, 0x7a, + 0x46, 0x08, 0xe9, 0xf6, 0xc5, 0xd1, 0x51, 0xac, 0xc9, 0x2f, 0x22, 0x99, 0x32, 0x1d, 0x33, 0x84, 0x70, 0x5d, 0xfb, + 0xe8, 0x28, 0xb6, 0x40, 0x90, 0x44, 0x1b, 0xc0, 0x35, 0x60, 0x8c, 0x12, 0x07, 0xfd, 0x9b, 0x7b, 0x91, 0xc5, 0xe1, + 0xf8, 0x11, 0x16, 0x47, 0x47, 0xbf, 0x88, 0x44, 0x41, 0x8b, 0x58, 0x23, 0xb4, 0x29, 0x99, 0x5e, 0x96, 0xe2, 0x40, + 0x6f, 0xb4, 0xbc, 0xd1, 0x25, 0x17, 0xd3, 0x18, 0xad, 0x7c, 0x5a, 0x50, 0x71, 0xb3, 0xb1, 0xc3, 0xfd, 0xad, 0x24, + 0x9c, 0x5c, 0x43, 0x8f, 0xaf, 0x65, 0xec, 0x70, 0x90, 0x13, 0x12, 0x29, 0x53, 0x37, 0x1a, 0xf0, 0x94, 0xb7, 0xa2, + 0x08, 0xdb, 0x51, 0xe2, 0xcf, 0x02, 0x61, 0xa1, 0x01, 0x75, 0x93, 0x24, 0xd1, 0x88, 0x5c, 0xaf, 0x3c, 0x58, 0x78, + 0x30, 0xd1, 0x01, 0x1f, 0x76, 0x46, 0xa9, 0x4e, 0x4a, 0x96, 0x2f, 0x33, 0x16, 0xc7, 0x02, 0x2b, 0x2c, 0x11, 0xb9, + 0x16, 0xad, 0xb8, 0x24, 0xd7, 0xb0, 0xde, 0x65, 0x73, 0xb1, 0x09, 0x39, 0xec, 0x20, 0x37, 0xc8, 0xd2, 0x8f, 0x10, + 0x40, 0xec, 0x06, 0x54, 0x12, 0x12, 0x89, 0xe5, 0x7c, 0xcc, 0xca, 0xa8, 0x2a, 0xd6, 0x6f, 0xe0, 0xc5, 0x52, 0xb1, + 0x83, 0x4c, 0xa9, 0x83, 0xc9, 0x52, 0x64, 0x9a, 0x4b, 0x71, 0x10, 0xb5, 0xca, 0x56, 0x64, 0xf1, 0xa1, 0x42, 0x87, + 0x08, 0x6d, 0x50, 0xac, 0x50, 0x8b, 0x0f, 0x65, 0xab, 0x3b, 0xc2, 0x30, 0x4a, 0xd4, 0x77, 0xed, 0x39, 0x08, 0x30, + 0xcc, 0x61, 0x92, 0x1b, 0xfc, 0xbd, 0xdd, 0xf9, 0x30, 0xc5, 0x5b, 0x31, 0xe0, 0xc9, 0xee, 0x4e, 0x21, 0x3a, 0x99, + 0xd3, 0x45, 0xcc, 0xc8, 0x35, 0x33, 0xd8, 0x45, 0x45, 0x06, 0x63, 0x6d, 0x2c, 0xdc, 0x80, 0xa5, 0x2c, 0xa9, 0x71, + 0x0a, 0xa5, 0x3a, 0x99, 0xc8, 0xf2, 0x39, 0xcd, 0x66, 0x50, 0xaf, 0xc2, 0x98, 0xdc, 0x6f, 0xb8, 0xac, 0x64, 0x54, + 0xb3, 0xe7, 0x05, 0x83, 0xaf, 0x38, 0x32, 0x35, 0x23, 0x84, 0x15, 0x6c, 0xf5, 0x82, 0xeb, 0xd7, 0x52, 0x64, 0xac, + 0xaf, 0x02, 0xfc, 0x32, 0x2b, 0xff, 0x58, 0xeb, 0x92, 0x8f, 0x97, 0x9a, 0xc5, 0x91, 0x80, 0x12, 0x11, 0x56, 0x08, + 0x8b, 0x44, 0xb3, 0x3b, 0xfd, 0x54, 0x0a, 0xcd, 0x84, 0x26, 0xcc, 0x43, 0x15, 0xf3, 0x84, 0x2e, 0x16, 0x4c, 0xe4, + 0x4f, 0x67, 0xbc, 0xc8, 0x63, 0x81, 0x36, 0x68, 0x83, 0x7f, 0x15, 0x04, 0x26, 0x49, 0xae, 0x79, 0x0a, 0xff, 0x7c, + 0x7d, 0x3a, 0xb1, 0x26, 0xd7, 0x66, 0x5b, 0x30, 0x12, 0x45, 0xfd, 0x89, 0x2c, 0x63, 0x37, 0x85, 0x03, 0x20, 0x5d, + 0xd0, 0xc7, 0xbb, 0x65, 0xc1, 0x14, 0x62, 0x2d, 0x22, 0xaa, 0x75, 0x74, 0x10, 0xfe, 0xad, 0x8c, 0x19, 0x2c, 0x00, + 0x47, 0x29, 0x37, 0x24, 0xf0, 0x47, 0xee, 0x36, 0x55, 0x5e, 0x11, 0xb5, 0xbf, 0x04, 0xc9, 0x79, 0xa2, 0xcb, 0xa5, + 0xd2, 0x2c, 0x7f, 0x7f, 0xbf, 0x60, 0x0a, 0x6b, 0x4a, 0xfe, 0x12, 0x83, 0xbf, 0x44, 0xc2, 0xe6, 0x0b, 0x7d, 0x7f, + 0x63, 0xa8, 0x79, 0x1a, 0x45, 0xf8, 0x5f, 0xa6, 0x68, 0xc9, 0x68, 0x06, 0x24, 0xcd, 0x81, 0xec, 0xad, 0x2c, 0xee, + 0x27, 0xbc, 0x28, 0x6e, 0x96, 0x8b, 0x85, 0x2c, 0x35, 0xd6, 0x82, 0xac, 0xb4, 0xac, 0xe1, 0x03, 0x2b, 0xba, 0x52, + 0xb7, 0x5c, 0x67, 0xb3, 0x58, 0xa3, 0x55, 0x46, 0x15, 0x3b, 0x78, 0x22, 0x65, 0xc1, 0xa8, 0x48, 0x39, 0xe1, 0x03, + 0x4d, 0x53, 0xb1, 0x2c, 0x8a, 0xfe, 0xb8, 0x64, 0xf4, 0x73, 0xdf, 0x64, 0xdb, 0xc3, 0x21, 0x35, 0xbf, 0x1f, 0x97, + 0x25, 0xbd, 0x87, 0x82, 0x84, 0x40, 0xb1, 0x01, 0x4f, 0xbf, 0xbf, 0x79, 0xf3, 0x3a, 0xb1, 0x7b, 0x85, 0x4f, 0xee, + 0x63, 0x5e, 0xed, 0x3f, 0xbe, 0xc1, 0x93, 0x52, 0xce, 0xb7, 0xba, 0xb6, 0xa0, 0xe3, 0xfd, 0xaf, 0x0c, 0x81, 0x11, + 0x7e, 0x68, 0x9b, 0x0e, 0x47, 0xf0, 0xda, 0x60, 0x3e, 0x64, 0x12, 0xd7, 0x2f, 0xfc, 0x93, 0xda, 0xe4, 0x98, 0xa3, + 0x6f, 0x8f, 0x56, 0x97, 0xf7, 0x2b, 0x46, 0xcc, 0x38, 0x17, 0x70, 0x30, 0xc2, 0x18, 0x33, 0xaa, 0xb3, 0xd9, 0x8a, + 0x99, 0xc6, 0x36, 0x7e, 0xc4, 0x6c, 0xb3, 0xc1, 0x7f, 0x4b, 0x8f, 0xf5, 0xfa, 0x90, 0x10, 0x6e, 0xe8, 0x15, 0xd1, + 0xeb, 0x35, 0x27, 0x84, 0x23, 0xfc, 0x8e, 0x93, 0x15, 0xf5, 0x13, 0x82, 0x93, 0x0d, 0xb6, 0x67, 0x6a, 0xa9, 0x0c, + 0x9c, 0x80, 0x5f, 0x58, 0xa9, 0x59, 0x99, 0x6a, 0x81, 0x4b, 0x36, 0x29, 0x60, 0x1c, 0x87, 0x5d, 0x3c, 0xa3, 0xea, + 0xe9, 0x8c, 0x8a, 0x29, 0xcb, 0xd3, 0xbf, 0xe5, 0x06, 0x33, 0x41, 0xa2, 0x09, 0x17, 0xb4, 0xe0, 0x7f, 0xb3, 0x3c, + 0x72, 0xe7, 0xc2, 0x47, 0x7d, 0xc0, 0xee, 0x34, 0x13, 0xb9, 0x3a, 0x78, 0xf9, 0xfe, 0xa7, 0x1f, 0xdd, 0x62, 0x36, + 0xce, 0x0a, 0xb4, 0x52, 0xcb, 0x05, 0x2b, 0x63, 0x84, 0xdd, 0x59, 0xf1, 0x9c, 0x1b, 0x3a, 0xf9, 0x13, 0x5d, 0xd8, + 0x14, 0xae, 0x3e, 0x2c, 0x72, 0xaa, 0xd9, 0x5b, 0x26, 0x72, 0x2e, 0xa6, 0xe4, 0xb0, 0x6b, 0xd3, 0x67, 0xd4, 0x65, + 0xe4, 0x55, 0xd2, 0xa7, 0x07, 0xcf, 0x0b, 0x33, 0xf7, 0xea, 0x73, 0x19, 0xa3, 0x8d, 0xd2, 0x54, 0xf3, 0xec, 0x80, + 0xe6, 0xf9, 0x2b, 0xc1, 0x35, 0x37, 0x23, 0x2c, 0x61, 0x89, 0x00, 0x57, 0x99, 0x3d, 0x35, 0xfc, 0xc8, 0x63, 0x84, + 0xe3, 0xd8, 0x9d, 0x05, 0x33, 0xe4, 0xd6, 0xec, 0xe8, 0xa8, 0xa6, 0xfc, 0x03, 0x96, 0xda, 0x4c, 0x32, 0x1c, 0xa1, + 0x64, 0xb1, 0x54, 0xb0, 0xd8, 0xbe, 0x0b, 0x38, 0x68, 0xe4, 0x58, 0xb1, 0xf2, 0x0b, 0xcb, 0x2b, 0x04, 0x51, 0x31, + 0x5a, 0x6d, 0xf5, 0xe1, 0xb6, 0x87, 0x26, 0xc3, 0x51, 0x3f, 0x24, 0xe1, 0xcc, 0x21, 0xbb, 0xe5, 0x54, 0x38, 0x53, + 0x15, 0x51, 0x89, 0xe1, 0x40, 0xad, 0x08, 0x8b, 0x22, 0x7e, 0x7e, 0x8b, 0x58, 0x00, 0x0f, 0x11, 0x52, 0x0e, 0x7f, + 0xe6, 0x3e, 0xff, 0x62, 0x0e, 0x0f, 0x85, 0x05, 0xc2, 0xda, 0x8e, 0x54, 0x21, 0xb4, 0x41, 0x58, 0xfb, 0xe1, 0x5a, + 0xa2, 0xe4, 0xf9, 0x22, 0x38, 0xb5, 0xc9, 0x3b, 0x6e, 0x8e, 0x6d, 0xa0, 0x6d, 0x54, 0xb3, 0xa3, 0xa3, 0x98, 0x25, + 0x15, 0x62, 0x90, 0xc3, 0xae, 0x5b, 0xa4, 0x00, 0x5a, 0x5f, 0x19, 0x37, 0xf4, 0x6c, 0x18, 0x9c, 0x43, 0x96, 0x08, + 0xf9, 0x38, 0xcb, 0x98, 0x52, 0xb2, 0x3c, 0x3a, 0x3a, 0x34, 0xe5, 0x2b, 0xce, 0x02, 0x16, 0xf1, 0xcd, 0xad, 0xa8, + 0x87, 0x80, 0xea, 0xd3, 0xd6, 0xf3, 0x4d, 0xa4, 0xe6, 0x9b, 0x3c, 0x13, 0x92, 0x46, 0x9f, 0x3e, 0x45, 0x2d, 0x8d, + 0x1d, 0x1c, 0xa6, 0xcc, 0x77, 0x7d, 0xff, 0x8c, 0x59, 0xb6, 0xd0, 0x30, 0x21, 0x3b, 0xa0, 0xd9, 0xcb, 0x0f, 0xc6, + 0xcd, 0x21, 0x61, 0x8d, 0x15, 0xda, 0x04, 0x2b, 0xba, 0xb7, 0x69, 0xc3, 0xdf, 0xd8, 0xa5, 0x5b, 0x4d, 0x0d, 0x4f, + 0x11, 0xac, 0xe3, 0x90, 0x8d, 0x36, 0xd8, 0xc0, 0xde, 0xcf, 0x46, 0x9a, 0x81, 0x0e, 0xf5, 0xa8, 0xef, 0xf2, 0x89, + 0xb2, 0x90, 0x2b, 0xd9, 0x5f, 0x4b, 0xa6, 0xb4, 0x45, 0xe4, 0x58, 0x63, 0x89, 0xe1, 0x8c, 0xda, 0x66, 0x3a, 0x1b, + 0x2c, 0xe9, 0xbe, 0xb1, 0xbd, 0x59, 0xc0, 0xd9, 0xa8, 0x00, 0xa9, 0xbf, 0x8d, 0x4f, 0x30, 0x56, 0x8d, 0xd6, 0xeb, + 0x77, 0xdc, 0xb7, 0x52, 0xaf, 0x65, 0xc5, 0xaf, 0x6d, 0x2d, 0x0a, 0x13, 0xc8, 0x1d, 0xce, 0x87, 0x5d, 0x37, 0x7e, + 0x31, 0x22, 0x87, 0x9d, 0x0a, 0x8b, 0x1d, 0x58, 0xed, 0x78, 0x2c, 0x14, 0xdf, 0xd8, 0xa6, 0x90, 0x39, 0xeb, 0x1b, + 0xf8, 0x92, 0xcc, 0x76, 0x70, 0x75, 0x46, 0x86, 0xc0, 0x75, 0x24, 0xb3, 0xd1, 0xd7, 0xf0, 0xc9, 0x53, 0x84, 0x58, + 0xef, 0xe6, 0xd5, 0x84, 0xe3, 0x4b, 0x93, 0x70, 0x6c, 0x4d, 0x23, 0x5a, 0x54, 0x55, 0xa2, 0x0a, 0xcd, 0xdc, 0x56, + 0xaf, 0xb3, 0xb0, 0x30, 0x83, 0xa9, 0xa7, 0x14, 0x34, 0xf1, 0x9a, 0xce, 0x99, 0x8a, 0x19, 0xc2, 0x5f, 0x2b, 0x60, + 0xf1, 0x13, 0x8a, 0x8c, 0x82, 0x33, 0x54, 0xc1, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, 0xcd, 0x2d, 0xa7, 0x30, 0x1b, + 0xaa, 0x51, 0xcd, 0xdb, 0x05, 0x93, 0x37, 0x87, 0xb3, 0x43, 0x70, 0x0f, 0x3f, 0x9b, 0x66, 0x81, 0x66, 0x58, 0x08, + 0x85, 0xf0, 0x61, 0x67, 0x7b, 0x25, 0x7d, 0xa9, 0x7a, 0x8e, 0xc3, 0x11, 0xac, 0x83, 0x39, 0x36, 0x12, 0xae, 0xcc, + 0xdf, 0xc6, 0x56, 0x03, 0xb0, 0xdd, 0x00, 0x66, 0x24, 0x93, 0x82, 0xea, 0xb8, 0x7b, 0xd2, 0x01, 0xc6, 0xf4, 0x0b, + 0x83, 0x53, 0x05, 0xa1, 0xdd, 0xa9, 0xb0, 0x64, 0x29, 0xd4, 0x8c, 0x4f, 0x74, 0xfc, 0xab, 0x30, 0x44, 0x85, 0x15, + 0x8a, 0x81, 0x84, 0x13, 0xb0, 0xc7, 0x86, 0xe0, 0xfc, 0x2a, 0xa0, 0x9f, 0x7e, 0x75, 0x10, 0xb9, 0x91, 0x1a, 0xc2, + 0x05, 0xe4, 0xa1, 0x66, 0xad, 0x6b, 0x32, 0x53, 0x31, 0x6e, 0xc0, 0x3d, 0x76, 0x07, 0xb6, 0xc5, 0xd4, 0x51, 0x03, + 0x11, 0x70, 0xb0, 0x22, 0x0d, 0x49, 0x84, 0x4b, 0xd4, 0x89, 0x96, 0x3f, 0xca, 0x5b, 0x56, 0x3e, 0xa5, 0x30, 0xf8, + 0xd4, 0x56, 0xdf, 0xd8, 0xa3, 0xc0, 0x50, 0x7c, 0xdd, 0xf7, 0xf8, 0xf2, 0xc9, 0x4c, 0xfc, 0x6d, 0x29, 0xe7, 0x5c, + 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x15, 0x7e, 0x3d, 0xfe, 0xb1, 0x89, + 0x5f, 0x9f, 0x1e, 0x3c, 0x9f, 0x7a, 0x0a, 0xd8, 0xdc, 0xc7, 0x08, 0xc7, 0x4e, 0xbc, 0x08, 0x4e, 0xba, 0x64, 0x86, + 0xdc, 0x31, 0xbf, 0x5e, 0xeb, 0x40, 0x8c, 0x6b, 0x70, 0x8e, 0xcc, 0x6e, 0x1b, 0xb4, 0xa1, 0x79, 0x0e, 0x2c, 0x5e, + 0x29, 0x8b, 0x22, 0x38, 0xac, 0xb0, 0xe8, 0x57, 0xc7, 0xd3, 0xa7, 0x07, 0xcf, 0x6f, 0xbe, 0x75, 0x42, 0x41, 0x7e, + 0x78, 0x48, 0xf9, 0x81, 0x8a, 0x9c, 0x95, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xa7, 0x52, 0x08, 0x96, 0x69, + 0x96, 0x83, 0xd0, 0x22, 0x88, 0x4e, 0x66, 0x52, 0xe9, 0x2a, 0xb1, 0x1e, 0xbd, 0x08, 0x85, 0xd0, 0x24, 0xa3, 0x45, + 0x11, 0x5b, 0x01, 0x65, 0x2e, 0xbf, 0xb0, 0x3d, 0xa3, 0xee, 0x37, 0x86, 0x5c, 0x35, 0xc3, 0x82, 0x66, 0x58, 0xa2, + 0x16, 0x05, 0xcf, 0x58, 0x75, 0x78, 0xdd, 0x24, 0x5c, 0xe4, 0xec, 0x0e, 0xe8, 0x08, 0xba, 0xbe, 0xbe, 0xee, 0xe0, + 0x2e, 0xda, 0x58, 0x80, 0xaf, 0x76, 0x00, 0xfb, 0x8d, 0x63, 0xd3, 0x0a, 0xe2, 0xab, 0xbd, 0x64, 0x0d, 0x05, 0x67, + 0x25, 0xf7, 0x82, 0x96, 0x25, 0xcf, 0x08, 0xe7, 0xac, 0x60, 0x9a, 0x79, 0x72, 0x0e, 0xcc, 0xb4, 0xdd, 0xba, 0xef, + 0x2a, 0xf8, 0x55, 0xe8, 0xe4, 0x77, 0x99, 0x5f, 0x73, 0x55, 0x89, 0xee, 0xf5, 0xf2, 0xd4, 0xd0, 0x1e, 0x68, 0xbb, + 0x3c, 0x54, 0x6b, 0x9a, 0xcd, 0xac, 0xc4, 0x1e, 0xef, 0x4c, 0xa9, 0x6e, 0xc3, 0x91, 0xf6, 0x6a, 0x13, 0x7d, 0x5f, + 0xba, 0x61, 0xee, 0x03, 0xc1, 0x8d, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x4f, 0x69, 0x51, 0x8c, 0x69, 0xf6, + 0xb9, 0x89, 0xfd, 0x35, 0x1a, 0x90, 0x6d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, 0xd2, 0x8d, 0x8d, + 0x12, 0x1f, 0x76, 0x6a, 0xb4, 0x6f, 0x2e, 0xf4, 0x57, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, 0x40, 0x05, 0xfe, + 0x2d, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xcd, 0xd6, 0x40, 0x34, 0x5a, 0x6d, 0x72, 0xae, 0xbe, 0x0e, + 0x81, 0xff, 0x57, 0x46, 0xf9, 0x2c, 0xe8, 0xe1, 0x3f, 0x1d, 0x68, 0x45, 0xe3, 0x1c, 0xe3, 0x5c, 0x8d, 0xcc, 0x31, + 0x14, 0x9e, 0xd0, 0xfc, 0x00, 0xcc, 0x8b, 0xc1, 0xf7, 0x37, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, 0xd5, 0x0f, 0x19, + 0x8a, 0x06, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x1b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, 0xee, 0x68, 0x6e, + 0x49, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9e, 0x85, 0xda, 0x99, 0x85, 0x4a, 0x02, 0x69, 0x0b, 0xd5, + 0xc8, 0x1c, 0x54, 0x4f, 0xb5, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x22, 0xb8, 0x05, 0xd1, 0xb8, + 0x74, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x75, 0x15, 0x89, 0xec, 0xe6, 0x68, 0xc8, 0xbe, 0x12, 0x97, 0x68, 0x8b, + 0xbf, 0xdf, 0x6c, 0x1c, 0x94, 0x18, 0x72, 0xab, 0xd3, 0x60, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, 0x33, 0x6c, 0x59, + 0x9f, 0x6d, 0xe0, 0x54, 0xed, 0x1e, 0x12, 0x22, 0x6b, 0xd8, 0x34, 0x98, 0x4a, 0xcf, 0x5d, 0x49, 0x84, 0xa9, 0x67, + 0x4b, 0xcb, 0x7a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0x0d, 0x56, 0x0d, 0xe1, 0x30, 0x0d, 0x8a, 0x6d, 0x52, 0x20, + 0xaa, 0xe5, 0x3e, 0x78, 0xef, 0xc3, 0x9a, 0x46, 0x3b, 0x01, 0xc4, 0xcb, 0x06, 0xc4, 0x03, 0xd0, 0x4a, 0x4b, 0xbc, + 0xe4, 0x88, 0xd0, 0x66, 0xe5, 0x98, 0xe1, 0xd2, 0x2e, 0xc4, 0x0e, 0x14, 0xb7, 0xd9, 0x4f, 0x83, 0x85, 0x20, 0xcb, + 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xf5, 0x7a, 0x07, 0xed, 0xf6, 0x72, 0xa1, 0x28, 0xa9, 0xa5, + 0xc3, 0xf5, 0xfa, 0x6f, 0x89, 0x62, 0xc7, 0xff, 0x62, 0x86, 0x06, 0x9e, 0xe8, 0x3e, 0xfe, 0x11, 0x4a, 0x19, 0x76, + 0xb4, 0x4e, 0xa9, 0x04, 0x87, 0x26, 0xd6, 0x36, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xe9, 0x0e, 0x01, 0x33, 0x89, 0xee, + 0xa4, 0xae, 0xa7, 0xfc, 0xd4, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xe1, 0x3e, 0xf9, 0xf2, 0xe8, 0x48, + 0x05, 0x0d, 0x7d, 0xaa, 0x28, 0xc5, 0x9f, 0x31, 0x9c, 0xca, 0xea, 0x5e, 0x18, 0xf6, 0xe5, 0x4f, 0x7f, 0x0e, 0xed, + 0x48, 0xa7, 0x9d, 0x3e, 0x08, 0xe6, 0xf4, 0x96, 0x72, 0x7d, 0x50, 0xb5, 0x62, 0x05, 0xf3, 0x98, 0xa1, 0x95, 0xe3, + 0x36, 0x92, 0x92, 0x01, 0xff, 0x08, 0x64, 0xc1, 0x73, 0xd1, 0x16, 0xf1, 0xb3, 0x19, 0x03, 0x55, 0xb6, 0x67, 0x24, + 0x2a, 0xf1, 0xf0, 0xd0, 0x1d, 0x24, 0xae, 0xe1, 0xfd, 0x63, 0xdf, 0x6c, 0x57, 0x6f, 0x48, 0x03, 0x0b, 0x56, 0x4e, + 0x64, 0x39, 0xf7, 0x79, 0x9b, 0xad, 0x6f, 0x47, 0x1c, 0xf9, 0x24, 0xde, 0xdb, 0xb6, 0x13, 0x01, 0xfa, 0x5b, 0xb2, + 0x77, 0x2d, 0xb5, 0x37, 0x4e, 0xd3, 0xea, 0x00, 0xb6, 0x0a, 0x42, 0x8f, 0x99, 0x2a, 0x94, 0xf2, 0x9d, 0x7a, 0xb5, + 0x6f, 0x75, 0x27, 0x87, 0xdd, 0x7e, 0x25, 0xf9, 0x79, 0x6c, 0xe8, 0x5b, 0x1d, 0x87, 0x3b, 0x55, 0xe5, 0xb2, 0xc8, + 0xdd, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x2d, 0x2f, 0x8a, 0x3a, 0xf5, 0x7f, 0x42, 0xda, 0x95, 0x23, 0xed, 0xd2, + 0x93, 0x76, 0x20, 0x15, 0x40, 0xda, 0x6d, 0x73, 0x75, 0x75, 0xb9, 0xb3, 0x3d, 0xa5, 0x25, 0xea, 0xca, 0x88, 0xd3, + 0xd0, 0xdf, 0xd2, 0x8f, 0x00, 0x55, 0xcc, 0xd7, 0xe7, 0xd8, 0xe9, 0x63, 0x40, 0x0c, 0xb4, 0x3a, 0x4d, 0x16, 0x6a, + 0x2a, 0x3e, 0xc7, 0x08, 0xab, 0x0d, 0xab, 0x30, 0xfb, 0xf1, 0x73, 0x50, 0xda, 0x05, 0xd3, 0x81, 0x73, 0xcc, 0x24, + 0xff, 0x8f, 0xf8, 0x28, 0x3f, 0x3b, 0xe1, 0x66, 0xa7, 0xfc, 0xec, 0x80, 0xd6, 0xd7, 0xb3, 0xcb, 0xbf, 0x4d, 0xed, + 0xcd, 0xf4, 0x44, 0x35, 0xbd, 0x7a, 0xbd, 0xd7, 0xeb, 0x78, 0x2b, 0x05, 0x34, 0xfa, 0x4e, 0x4a, 0x29, 0xab, 0xd6, + 0x81, 0x06, 0x84, 0x90, 0x81, 0x84, 0x8d, 0x9d, 0x74, 0x75, 0xca, 0xfd, 0xf8, 0xef, 0xf4, 0x3c, 0x46, 0x71, 0x6f, + 0xeb, 0x3f, 0x95, 0xf3, 0x05, 0x30, 0x64, 0x5b, 0x28, 0x3d, 0x65, 0xae, 0xc3, 0x3a, 0x7f, 0xb3, 0x27, 0xad, 0x51, + 0xc7, 0xec, 0xc7, 0x06, 0x36, 0x55, 0x52, 0xf3, 0x61, 0x67, 0xb3, 0xac, 0x92, 0x2a, 0xc2, 0xb1, 0x4f, 0xb7, 0xf2, + 0x74, 0x5b, 0x33, 0xe3, 0x33, 0xde, 0xc4, 0xc2, 0xd2, 0x61, 0x01, 0xb4, 0x2e, 0x20, 0x3f, 0x1e, 0xdd, 0xc3, 0xf5, + 0xdf, 0xd4, 0xc0, 0x59, 0x6d, 0xb6, 0xc0, 0xb7, 0xda, 0x6c, 0x3e, 0x6a, 0x27, 0x69, 0xe3, 0x8f, 0x7b, 0xe4, 0xde, + 0x0a, 0x7a, 0x75, 0xa6, 0x93, 0x19, 0x87, 0x23, 0x48, 0xdb, 0x61, 0x21, 0xc9, 0x6a, 0x2e, 0x73, 0x96, 0x46, 0x72, + 0xc1, 0x44, 0xb4, 0x01, 0x3d, 0xab, 0x43, 0x80, 0x7f, 0x89, 0x78, 0xf5, 0xae, 0xa9, 0x6f, 0x4d, 0x3f, 0xea, 0x0d, + 0xa8, 0xc2, 0x7e, 0xe4, 0x7b, 0x94, 0xb1, 0x1f, 0x59, 0xa9, 0x0c, 0x4f, 0x5a, 0xb1, 0xb7, 0x3f, 0xf2, 0xfa, 0x80, + 0xfa, 0x91, 0xa7, 0x5f, 0xaf, 0x52, 0x0b, 0x24, 0x51, 0x37, 0xb9, 0x48, 0x4e, 0x23, 0x64, 0x34, 0xc6, 0x2f, 0xbc, + 0xc6, 0x78, 0x59, 0x69, 0x8c, 0x5f, 0x6a, 0xb2, 0xdc, 0xd2, 0x18, 0xff, 0x20, 0xc8, 0x4b, 0x3d, 0x78, 0xe9, 0xb5, + 0xe9, 0x6f, 0x65, 0xc1, 0xb3, 0xfb, 0x38, 0x2a, 0xb8, 0x6e, 0xc3, 0x6d, 0x62, 0x84, 0x57, 0x36, 0x03, 0x54, 0x8d, + 0x46, 0xdf, 0xbd, 0xf1, 0xf2, 0x1f, 0x16, 0x82, 0x44, 0x0f, 0x0a, 0xae, 0x1f, 0x44, 0x78, 0xa6, 0xc9, 0x1f, 0xf0, + 0xeb, 0xc1, 0x2a, 0xfe, 0x89, 0xea, 0x59, 0x52, 0x52, 0x91, 0xcb, 0x79, 0x8c, 0x5a, 0x51, 0x84, 0x12, 0x65, 0x84, + 0x90, 0x47, 0x68, 0xf3, 0xe0, 0x0f, 0xfc, 0xa7, 0x24, 0xd1, 0x20, 0x6a, 0xcd, 0x34, 0x66, 0x94, 0xfc, 0x71, 0xf5, + 0x60, 0xf5, 0xa7, 0xdc, 0x5c, 0xff, 0x81, 0x9f, 0xeb, 0x4a, 0xad, 0x8f, 0xef, 0x18, 0x89, 0x11, 0xb9, 0x7e, 0xee, + 0x87, 0xf4, 0x54, 0xce, 0xad, 0x82, 0x3f, 0x42, 0xf8, 0x0b, 0xe8, 0x75, 0xaf, 0x79, 0x4d, 0x84, 0xdc, 0x1d, 0xcc, + 0x21, 0x89, 0xa4, 0x51, 0x1e, 0x44, 0x47, 0x47, 0x41, 0x5a, 0xc5, 0x42, 0xe0, 0x27, 0x92, 0x34, 0x44, 0x75, 0xcc, + 0x29, 0xb4, 0xf4, 0x44, 0xc6, 0x1c, 0xf9, 0x66, 0x62, 0xaf, 0xa9, 0x76, 0x3b, 0x96, 0x0f, 0xad, 0xee, 0x21, 0xe1, + 0x9a, 0x95, 0x54, 0xcb, 0x72, 0x84, 0x42, 0xb6, 0x04, 0xbf, 0xe6, 0xe4, 0x8f, 0xe1, 0xc1, 0xff, 0xf1, 0x7f, 0xfe, + 0x3e, 0xf9, 0xbd, 0x1c, 0xfd, 0x81, 0x05, 0x23, 0x27, 0x57, 0xf1, 0x20, 0x8d, 0x0f, 0xdb, 0xed, 0xf5, 0xef, 0x27, + 0xc3, 0xff, 0xa6, 0xed, 0xbf, 0x1f, 0xb7, 0x7f, 0x1b, 0xa1, 0x75, 0xfc, 0xfb, 0xc9, 0x60, 0xe8, 0xbe, 0x86, 0xff, + 0x7d, 0xfd, 0xbb, 0x1a, 0x1d, 0xdb, 0xc4, 0x07, 0x08, 0x9d, 0x4c, 0xf1, 0x3f, 0x05, 0x39, 0x69, 0xb7, 0xaf, 0x4f, + 0xa6, 0xf8, 0x67, 0x41, 0x4e, 0xe0, 0xef, 0xbd, 0x26, 0xef, 0xd8, 0xf4, 0xf9, 0xdd, 0x22, 0xfe, 0xe3, 0x7a, 0xfd, + 0x60, 0xf5, 0x9a, 0x6f, 0xa0, 0xdd, 0xe1, 0x7f, 0xff, 0xfe, 0xbb, 0x8a, 0xfe, 0x71, 0x4d, 0x4e, 0x46, 0x2d, 0x14, + 0x9b, 0xe4, 0x63, 0x62, 0xff, 0xc4, 0x83, 0x74, 0xf8, 0xdf, 0x6e, 0x28, 0xd1, 0x3f, 0x7e, 0xff, 0xe3, 0xea, 0x9a, + 0x8c, 0xd6, 0x71, 0xb4, 0xfe, 0x07, 0x5a, 0x23, 0xb4, 0x7e, 0x80, 0xfe, 0xc0, 0xd1, 0x34, 0x42, 0xf8, 0x37, 0x41, + 0x4e, 0xfe, 0x71, 0x32, 0xc5, 0xdf, 0x0b, 0x72, 0x12, 0x9d, 0x4c, 0xf1, 0x47, 0x49, 0x4e, 0xfe, 0x3b, 0x1e, 0xa4, + 0x56, 0x09, 0xb7, 0x36, 0xea, 0x8f, 0x35, 0xdc, 0x84, 0xd0, 0x92, 0xd1, 0xb5, 0xe6, 0xba, 0x60, 0xe8, 0xc1, 0x09, + 0xc7, 0x2f, 0x25, 0x00, 0x2b, 0xd6, 0xa0, 0xa4, 0x31, 0x97, 0xb0, 0xab, 0x4f, 0xb0, 0xf0, 0x80, 0x41, 0x0f, 0x52, + 0x8e, 0xad, 0x9e, 0x40, 0xa5, 0xda, 0xde, 0xde, 0x2a, 0xb8, 0xbe, 0xc5, 0x37, 0xe4, 0xa5, 0x8c, 0xbb, 0x08, 0x0b, + 0x0a, 0x3f, 0x7a, 0x08, 0x7f, 0xd0, 0xee, 0xc2, 0x13, 0xb6, 0xb9, 0xc5, 0x30, 0x21, 0x2d, 0x3f, 0x13, 0x21, 0xfc, + 0x7c, 0x4f, 0xa6, 0x9e, 0x81, 0xfa, 0x01, 0x61, 0xad, 0xc2, 0xeb, 0x51, 0xfc, 0x54, 0x93, 0x0a, 0x39, 0xde, 0x97, + 0x8c, 0xfd, 0x42, 0x8b, 0xcf, 0xac, 0x8c, 0x9f, 0x6b, 0xdc, 0xed, 0x3d, 0xc2, 0x46, 0x55, 0x7d, 0xd8, 0x45, 0xfd, + 0xea, 0x76, 0xeb, 0x83, 0xb4, 0xf7, 0x09, 0x70, 0x0a, 0x37, 0xf5, 0x35, 0xb0, 0xf6, 0x87, 0x7c, 0x47, 0xa9, 0x55, + 0xd2, 0xdb, 0x08, 0x35, 0xaf, 0x52, 0xb9, 0xf8, 0x42, 0x0b, 0x9e, 0x1f, 0x68, 0x36, 0x5f, 0x14, 0x54, 0xb3, 0x03, + 0x37, 0xe7, 0x03, 0x0a, 0x0d, 0x45, 0x15, 0x4f, 0xf1, 0x83, 0xa8, 0x37, 0xed, 0x0f, 0x22, 0xa9, 0xf7, 0x4e, 0x0c, + 0xf7, 0x59, 0x8e, 0x2f, 0x51, 0xb4, 0xba, 0x2e, 0xdb, 0xbe, 0x11, 0x6c, 0x77, 0x41, 0x59, 0x36, 0x32, 0xe7, 0xb7, + 0xc2, 0x70, 0xbf, 0x49, 0x48, 0x6f, 0x10, 0x5d, 0xa9, 0x2f, 0xd3, 0xeb, 0x08, 0x6e, 0x72, 0x4a, 0x22, 0x98, 0x51, + 0x1e, 0x41, 0x09, 0x4a, 0x3a, 0x7d, 0x7a, 0xc5, 0xfa, 0xb4, 0xd5, 0xf2, 0x6c, 0x76, 0x46, 0xf8, 0x90, 0xda, 0xfa, + 0x05, 0x9e, 0xe1, 0x9c, 0xb4, 0xbb, 0x78, 0x49, 0x3a, 0xa6, 0x4a, 0x7f, 0x79, 0x95, 0xb9, 0x7e, 0x8e, 0x8e, 0xe2, + 0x32, 0x29, 0xa8, 0xd2, 0xaf, 0x40, 0x23, 0x40, 0x96, 0x78, 0x46, 0xca, 0x84, 0xdd, 0xb1, 0x2c, 0xce, 0x10, 0x9e, + 0x39, 0x1a, 0x84, 0xfa, 0x68, 0x49, 0x82, 0x62, 0x20, 0x67, 0x10, 0xc1, 0x06, 0xb3, 0x61, 0x77, 0x44, 0x08, 0x89, + 0x0e, 0xdb, 0xed, 0x68, 0x50, 0x92, 0x7f, 0x8a, 0x14, 0x52, 0x02, 0x76, 0x9a, 0xfc, 0x0c, 0x49, 0xbd, 0x20, 0x29, + 0xfe, 0x28, 0x13, 0xcd, 0x94, 0x8e, 0x21, 0x19, 0x94, 0x04, 0xca, 0x63, 0x78, 0x74, 0x75, 0x12, 0xb5, 0x20, 0xd5, + 0xa0, 0x28, 0xc2, 0x25, 0xb9, 0xd7, 0x28, 0x9d, 0x0d, 0x4f, 0x47, 0xe1, 0x19, 0x61, 0x53, 0xa1, 0xff, 0x7b, 0x3d, + 0x98, 0x0d, 0x3b, 0xa6, 0xff, 0xeb, 0x68, 0x10, 0x97, 0x44, 0x59, 0x36, 0x6e, 0xa0, 0x52, 0xc1, 0xcc, 0x7c, 0x51, + 0xea, 0x06, 0xe8, 0xfa, 0xce, 0x49, 0xbb, 0x97, 0xc6, 0x79, 0x38, 0x93, 0x36, 0x74, 0xe8, 0x40, 0x81, 0x0b, 0x02, + 0xe5, 0x71, 0x49, 0xa0, 0xd3, 0xba, 0xda, 0xbd, 0x4e, 0x5d, 0xc2, 0x3f, 0xa2, 0x7f, 0x0c, 0xbe, 0x17, 0xe9, 0x6f, + 0xc2, 0x8e, 0xe0, 0x7b, 0xb1, 0x5e, 0xc3, 0xdf, 0xdf, 0xc4, 0x00, 0x86, 0x65, 0xd2, 0xfe, 0xe9, 0xd2, 0x7e, 0x86, + 0x34, 0xc1, 0x52, 0x33, 0x60, 0xac, 0x2a, 0x7e, 0xcc, 0x2e, 0xce, 0x84, 0xd8, 0x19, 0x1c, 0x1d, 0xf1, 0x21, 0x6d, + 0x75, 0x47, 0x70, 0x23, 0x50, 0x6a, 0xf5, 0x0b, 0xd7, 0xb3, 0x38, 0x3a, 0xb9, 0x8e, 0xd0, 0x20, 0x3a, 0x80, 0x55, + 0xee, 0xcb, 0x16, 0x71, 0xb0, 0xce, 0x5a, 0x8c, 0xa6, 0xf9, 0x35, 0xe9, 0x0c, 0x62, 0x61, 0x89, 0x7c, 0x81, 0x70, + 0xe6, 0x68, 0x6a, 0x07, 0xe7, 0xa8, 0x25, 0x44, 0xcb, 0x7f, 0xe7, 0xa8, 0x35, 0xd3, 0xad, 0x09, 0x4a, 0x33, 0xf8, + 0x1b, 0xe7, 0x84, 0x90, 0x76, 0xaf, 0xaa, 0xe8, 0x0f, 0x4b, 0x8a, 0xd2, 0x89, 0x57, 0x8f, 0x0e, 0xcd, 0xe6, 0x90, + 0xad, 0x98, 0x0f, 0xd9, 0x68, 0xbd, 0x8e, 0xae, 0x06, 0xd7, 0x11, 0x6a, 0xc5, 0x1e, 0xed, 0x4e, 0x3c, 0xde, 0x21, + 0x84, 0xc5, 0x68, 0xe3, 0x6e, 0xa0, 0x6e, 0x59, 0xe3, 0xb6, 0x69, 0x55, 0xef, 0xff, 0x80, 0x2c, 0xb0, 0x4d, 0x25, + 0xf7, 0x58, 0xfe, 0x76, 0x01, 0x53, 0xf5, 0xb8, 0x2d, 0x49, 0x07, 0x97, 0xc4, 0xab, 0xbb, 0x29, 0xd1, 0x35, 0xfe, + 0x67, 0xa4, 0x2e, 0x8e, 0x87, 0x05, 0x9e, 0x8d, 0x88, 0xa2, 0x46, 0x7e, 0xe9, 0x7b, 0x65, 0x3a, 0x2b, 0xc8, 0x2d, + 0xdb, 0xba, 0xff, 0x2d, 0xe0, 0x4e, 0xe6, 0xa9, 0x4e, 0xb2, 0x65, 0x59, 0x32, 0xa1, 0x5f, 0xcb, 0xdc, 0x31, 0x76, + 0xac, 0x00, 0xd9, 0x0a, 0x2e, 0x76, 0x31, 0x70, 0x75, 0x3d, 0xbf, 0x53, 0xf2, 0x9d, 0xec, 0x25, 0xc9, 0x2d, 0xc3, + 0x65, 0xae, 0x7b, 0xfb, 0x4b, 0x27, 0x4a, 0xc7, 0x08, 0xe7, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x99, 0x64, 0x90, + 0x0d, 0x1d, 0x28, 0xb4, 0x31, 0xfb, 0x2a, 0x56, 0xe4, 0xa9, 0x4e, 0x04, 0xbb, 0x33, 0xdd, 0xc6, 0xa8, 0x3e, 0xc4, + 0xfd, 0x7e, 0xbb, 0xa2, 0x7d, 0x43, 0x80, 0x54, 0x22, 0x64, 0xce, 0x00, 0x42, 0x70, 0xf7, 0xef, 0x92, 0x66, 0x54, + 0x85, 0x37, 0x5b, 0xf5, 0x00, 0x87, 0xa1, 0xca, 0x7b, 0x09, 0x7a, 0x62, 0xc3, 0x9e, 0x55, 0x85, 0xad, 0xf2, 0x1c, + 0x21, 0x3e, 0x89, 0x97, 0x09, 0xdc, 0x08, 0x1a, 0x4c, 0x12, 0x02, 0xad, 0xd7, 0xcb, 0x10, 0xb7, 0x66, 0xb5, 0x62, + 0x7a, 0x42, 0x66, 0xc3, 0xb2, 0xd5, 0x32, 0xca, 0xeb, 0xdc, 0xe2, 0xc5, 0x12, 0xe1, 0x49, 0xb5, 0xd7, 0x7c, 0xb9, + 0x05, 0x69, 0x76, 0x15, 0x4f, 0x9a, 0x4a, 0xe0, 0x96, 0x10, 0xc8, 0xe8, 0x17, 0x35, 0xb4, 0x8e, 0xa7, 0xe4, 0x24, + 0x1e, 0x26, 0x83, 0xff, 0x6b, 0x84, 0x06, 0x71, 0x72, 0x8c, 0x4e, 0x2c, 0x2d, 0x99, 0xa0, 0x7e, 0x66, 0xfb, 0x58, + 0x99, 0xdb, 0xcf, 0x2e, 0x36, 0x0a, 0xc8, 0x54, 0x62, 0x41, 0xe7, 0x2c, 0x9d, 0xc2, 0xae, 0xf7, 0xc8, 0xb3, 0xc0, + 0x80, 0x4c, 0xe9, 0xd4, 0xd1, 0x96, 0x24, 0x1a, 0x94, 0xb4, 0xfa, 0x1a, 0x44, 0x83, 0xac, 0xfe, 0xfa, 0xbf, 0xa2, + 0x41, 0x41, 0xd3, 0xa7, 0x7c, 0xe3, 0x94, 0xe4, 0x8d, 0x3e, 0x2e, 0x7c, 0x1f, 0x1b, 0xbb, 0x38, 0x01, 0xf0, 0x72, + 0xb4, 0xab, 0x1d, 0x59, 0xa2, 0x0d, 0x9f, 0x54, 0xd4, 0x49, 0x25, 0x9a, 0x4e, 0x01, 0xaa, 0xc1, 0x22, 0xa8, 0xd0, + 0x36, 0x20, 0x98, 0x32, 0x60, 0x8b, 0x47, 0x5a, 0x80, 0xe6, 0xf2, 0xba, 0x83, 0x56, 0x8d, 0xc2, 0x8e, 0xb3, 0x6a, + 0xde, 0xc5, 0x57, 0xc4, 0x7b, 0x02, 0x54, 0xf9, 0x6a, 0xd9, 0x9f, 0xb4, 0x5a, 0x48, 0x79, 0xfc, 0xca, 0x87, 0x93, + 0x11, 0xbe, 0x03, 0x14, 0xc2, 0x0d, 0x8c, 0xc2, 0x8d, 0x39, 0xf6, 0xdc, 0x1c, 0x5b, 0x2d, 0xb9, 0x41, 0xfd, 0xa0, + 0xf2, 0xd2, 0x55, 0xde, 0x6c, 0x2c, 0x64, 0xb6, 0x31, 0xee, 0x12, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, 0xfc, 0x29, + 0xd1, 0xde, 0x66, 0xa1, 0x51, 0xa8, 0x6e, 0x76, 0x2f, 0x50, 0x54, 0x7b, 0x7a, 0xc4, 0x00, 0x0b, 0xa8, 0x5a, 0xa9, + 0x91, 0x67, 0x1a, 0xe7, 0xad, 0xae, 0x41, 0xf7, 0x76, 0xb7, 0xdf, 0x6c, 0xec, 0x61, 0xdd, 0x18, 0xce, 0x5b, 0x64, + 0x56, 0xef, 0xf0, 0x8d, 0x6c, 0xb5, 0x36, 0xcd, 0xfb, 0x52, 0xbf, 0x89, 0x1b, 0xf7, 0x17, 0xcf, 0x77, 0x4c, 0x3c, + 0xfc, 0xe9, 0x5b, 0x9f, 0xb7, 0x22, 0xe1, 0x42, 0xb0, 0x12, 0x4e, 0x58, 0xa2, 0xb1, 0xd8, 0x6c, 0xaa, 0x53, 0xff, + 0x17, 0x6d, 0x6d, 0xc6, 0x08, 0x07, 0x3a, 0x64, 0xa4, 0x36, 0x2c, 0x71, 0x89, 0xa9, 0xa1, 0x22, 0x84, 0x90, 0x0f, + 0xda, 0x9b, 0xc7, 0x68, 0x43, 0x92, 0x32, 0x12, 0x9c, 0xdd, 0xb1, 0x22, 0x2c, 0xf9, 0xf4, 0xe0, 0xa9, 0xfc, 0xa6, + 0x48, 0x37, 0x14, 0xa3, 0xd4, 0x14, 0x2b, 0x1c, 0x21, 0x2b, 0xc8, 0x17, 0x90, 0x73, 0xaa, 0x0b, 0x96, 0xc4, 0x10, + 0xc4, 0x67, 0xbc, 0x64, 0x86, 0x71, 0x7f, 0xe0, 0xe5, 0xc6, 0xac, 0xc9, 0x69, 0x66, 0xa1, 0xf6, 0x07, 0xa0, 0x59, + 0x80, 0x72, 0x48, 0x92, 0x9d, 0x62, 0x9f, 0x1e, 0x3c, 0x7e, 0xb3, 0x4f, 0x86, 0x5e, 0xaf, 0x9d, 0xf4, 0x9c, 0x01, + 0xeb, 0x83, 0x8b, 0x7a, 0xa8, 0x99, 0xfb, 0x91, 0xc6, 0x99, 0x61, 0xa2, 0x8a, 0x98, 0x03, 0x32, 0x7d, 0x7a, 0xf0, + 0xf8, 0x7d, 0xcc, 0x8d, 0x6e, 0x0a, 0xe1, 0x70, 0xde, 0x71, 0x49, 0x62, 0x4a, 0x18, 0xb2, 0x93, 0xaf, 0xe8, 0x58, + 0x19, 0x9c, 0xee, 0x29, 0x35, 0x99, 0x20, 0x76, 0x0c, 0xc5, 0x88, 0x64, 0x0e, 0x04, 0x24, 0x43, 0x38, 0x6b, 0xc8, + 0x75, 0xc4, 0xac, 0x81, 0xe9, 0xec, 0x06, 0x16, 0x23, 0xb1, 0xec, 0x21, 0xc2, 0x99, 0xe9, 0x56, 0x6f, 0xec, 0x71, + 0x22, 0xe9, 0xb6, 0xa1, 0x5b, 0x2d, 0xcf, 0x7e, 0x04, 0xc1, 0xcb, 0x7f, 0xbc, 0x76, 0x6d, 0x57, 0x09, 0xcf, 0xbc, + 0x45, 0xda, 0xa7, 0x07, 0x8f, 0x7f, 0x72, 0x46, 0x69, 0x0b, 0xea, 0xc9, 0xff, 0x8e, 0x8c, 0xfa, 0xf8, 0xa7, 0xa4, + 0xce, 0x35, 0x85, 0x3f, 0x3d, 0x78, 0xfc, 0x61, 0x5f, 0x31, 0x48, 0xdf, 0x2c, 0x6b, 0x25, 0x81, 0x19, 0xdf, 0x8a, + 0x15, 0xe9, 0xca, 0x9d, 0x15, 0xa9, 0xd8, 0x60, 0x73, 0x42, 0xa5, 0x6a, 0x53, 0xe9, 0x56, 0x9e, 0x61, 0x49, 0xcc, + 0x55, 0x52, 0x73, 0xd9, 0x1c, 0x1a, 0x73, 0x29, 0x6e, 0x32, 0xb9, 0x60, 0x5f, 0xb9, 0x5f, 0x7a, 0xae, 0x51, 0xc2, + 0xe7, 0x60, 0x88, 0x63, 0xc6, 0x2e, 0xf0, 0x61, 0x07, 0xf5, 0xb7, 0xce, 0x33, 0x69, 0x10, 0xb5, 0x6c, 0x1e, 0x36, + 0x98, 0x92, 0x0e, 0xce, 0x48, 0x07, 0x17, 0x44, 0x0d, 0x3b, 0xf6, 0xc4, 0xe8, 0x17, 0x55, 0xd3, 0xf6, 0xdc, 0x81, + 0xed, 0x5e, 0xd8, 0x7d, 0x6b, 0x0f, 0xe5, 0x59, 0xbf, 0x30, 0xfa, 0x4b, 0x73, 0xd0, 0xcf, 0x0c, 0x6a, 0xbc, 0x62, + 0x71, 0x89, 0x4b, 0xd3, 0xf2, 0x0d, 0x1f, 0x17, 0x60, 0xa7, 0x02, 0x33, 0xc3, 0x1a, 0xa5, 0x55, 0xd9, 0xae, 0x2b, + 0x5b, 0x24, 0x66, 0xad, 0x4a, 0x5c, 0x24, 0x40, 0xca, 0x71, 0xe1, 0xec, 0x7a, 0xd4, 0x6e, 0x95, 0x8b, 0xa3, 0xa3, + 0xd8, 0x56, 0x9a, 0xd1, 0xb8, 0xf4, 0xf9, 0xf5, 0x0d, 0xe0, 0x47, 0x4b, 0x35, 0x66, 0xc8, 0x4c, 0xa0, 0xd5, 0xca, + 0x46, 0x1b, 0x7a, 0x48, 0x48, 0x5c, 0x34, 0xa1, 0xe8, 0x47, 0x6f, 0x98, 0xc1, 0x2d, 0x00, 0xb4, 0x5a, 0xd5, 0x75, + 0xef, 0x16, 0xc4, 0x9e, 0x6b, 0x2c, 0x37, 0x5f, 0xe2, 0xca, 0x9a, 0xa8, 0xb3, 0x63, 0x87, 0xe5, 0x47, 0x81, 0x44, + 0x88, 0xbb, 0xc2, 0xcf, 0x27, 0xd8, 0x1a, 0x02, 0xca, 0xbd, 0x72, 0x36, 0x10, 0xd8, 0x58, 0x6d, 0xb9, 0x42, 0x9e, + 0xb4, 0xf5, 0x50, 0xea, 0x0b, 0xc1, 0x05, 0x17, 0x14, 0x6a, 0x6d, 0x1c, 0x96, 0xbf, 0x62, 0xbb, 0xe6, 0x9c, 0x58, + 0x21, 0xa7, 0x2d, 0x33, 0xc3, 0x30, 0x00, 0xeb, 0x55, 0x80, 0x79, 0x49, 0x9e, 0x7f, 0x1d, 0xf5, 0x1f, 0x07, 0xa8, + 0xff, 0x84, 0xb0, 0x60, 0x1b, 0x58, 0x5d, 0x49, 0x22, 0x9d, 0x82, 0x42, 0xf9, 0xac, 0xa7, 0x0b, 0x02, 0xda, 0xb8, + 0x26, 0x54, 0x1b, 0x57, 0x94, 0x5f, 0xa1, 0x2c, 0xe1, 0x4e, 0x31, 0xfa, 0x4c, 0xec, 0xef, 0x93, 0xe3, 0xfa, 0x82, + 0x0e, 0xba, 0xde, 0xa7, 0x1c, 0x0c, 0x49, 0xe1, 0xe3, 0x0f, 0xdf, 0xbe, 0x5b, 0x7d, 0xba, 0xd8, 0xdd, 0xc1, 0x81, + 0x59, 0x29, 0xcc, 0x3a, 0xd8, 0xc0, 0x4d, 0x23, 0x53, 0xe8, 0xbf, 0xba, 0x13, 0x6f, 0x52, 0xa1, 0xad, 0xcd, 0xe8, + 0x8f, 0x43, 0x18, 0x6d, 0xb7, 0x6b, 0x4a, 0xb0, 0xa0, 0x59, 0xa0, 0x4b, 0xd6, 0xb8, 0x95, 0x96, 0x5f, 0x21, 0x23, + 0x8f, 0x4d, 0x01, 0x26, 0xf2, 0xfd, 0xd9, 0x4f, 0x36, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xca, 0x10, 0x42, 0x8b, 0xf7, + 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0x3d, 0x37, 0x90, 0xaa, 0x41, 0x16, 0x45, 0xb5, 0x22, 0xff, 0xe5, 0x21, 0x21, + 0xcf, 0x6b, 0x45, 0xe6, 0xbb, 0xda, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x25, 0xd8, 0xcb, 0xd0, 0x0f, + 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x73, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0xad, 0xdc, + 0x07, 0x90, 0xcb, 0xa9, 0x19, 0x24, 0x7c, 0xbf, 0x37, 0xa5, 0x7d, 0xbb, 0x9b, 0xcf, 0xdb, 0x16, 0x31, 0x5b, 0xeb, + 0x92, 0x70, 0xa1, 0x58, 0xa9, 0x9f, 0xb0, 0x89, 0x2c, 0xe1, 0xfe, 0xa3, 0x02, 0x0b, 0xda, 0x3c, 0x08, 0x74, 0x80, + 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xd6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0xd3, 0x76, 0xad, 0xe7, 0x47, 0x47, + 0x5f, 0x58, 0x0d, 0x28, 0x37, 0x4c, 0x33, 0x8c, 0x80, 0x78, 0x59, 0x2e, 0xc7, 0xdd, 0x0c, 0x3f, 0x88, 0x6b, 0x95, + 0x81, 0x27, 0x1c, 0x21, 0x11, 0x7a, 0x49, 0xf4, 0x66, 0xba, 0x4d, 0xef, 0x9d, 0x36, 0x43, 0x84, 0x62, 0x0d, 0x90, + 0x7b, 0x90, 0xcb, 0xad, 0x92, 0x49, 0xd5, 0xb6, 0xb6, 0xd5, 0x20, 0x9e, 0x02, 0xb8, 0x62, 0x23, 0xa4, 0x04, 0x68, + 0xb8, 0x5f, 0x68, 0xf9, 0x20, 0x81, 0xfd, 0xc7, 0x2a, 0x01, 0x91, 0x16, 0x35, 0x36, 0x2e, 0x42, 0xd8, 0x9a, 0xfa, + 0x04, 0xc6, 0x09, 0x8f, 0x5f, 0xee, 0xd3, 0x50, 0x7b, 0xd4, 0x66, 0xe6, 0x0c, 0x82, 0x12, 0x12, 0x55, 0x15, 0x92, + 0x2f, 0xb1, 0x70, 0xdc, 0x9c, 0xbf, 0x87, 0x03, 0x52, 0x2c, 0x69, 0x6c, 0xef, 0xb6, 0xe0, 0xf8, 0x28, 0x93, 0x65, + 0xdc, 0xe8, 0xba, 0x5f, 0x9a, 0x6a, 0xd8, 0x81, 0x8e, 0x86, 0x70, 0x2a, 0xcd, 0x3d, 0xe1, 0xd3, 0x9a, 0xa4, 0x6a, + 0x67, 0x01, 0xe5, 0x89, 0x61, 0x6d, 0x9a, 0x12, 0xcc, 0x5f, 0x3b, 0xf3, 0xb5, 0xea, 0x98, 0x60, 0x66, 0x18, 0xb7, + 0x76, 0x15, 0xd8, 0x06, 0x70, 0x6c, 0xf5, 0x44, 0x06, 0x8b, 0xea, 0x95, 0xe2, 0xa6, 0xd3, 0x80, 0x09, 0x78, 0x07, + 0xd6, 0x33, 0xdb, 0x5b, 0xff, 0xa5, 0x39, 0x18, 0x05, 0x56, 0x0d, 0x02, 0x2f, 0x0d, 0x81, 0x47, 0xc0, 0xb8, 0x79, + 0xd3, 0xf2, 0x81, 0x33, 0xa2, 0x11, 0xfe, 0xc4, 0x73, 0x78, 0x66, 0x59, 0xee, 0x9d, 0x8f, 0xad, 0x15, 0x49, 0x05, + 0x01, 0xdb, 0x22, 0xec, 0x88, 0xbc, 0x44, 0x58, 0xb5, 0x5a, 0x7d, 0x75, 0xc5, 0x6a, 0xad, 0x4a, 0x3d, 0x4c, 0x01, + 0xb7, 0xc4, 0x80, 0xf7, 0x8d, 0x13, 0x15, 0x0c, 0x09, 0xbc, 0xf5, 0xb7, 0x02, 0xf5, 0xfd, 0xe3, 0x77, 0x71, 0x48, + 0xdf, 0xc2, 0xb2, 0xd5, 0x45, 0x2c, 0x4c, 0x29, 0xae, 0xef, 0x70, 0xde, 0x7e, 0xdb, 0x6c, 0x04, 0xc6, 0x7d, 0xd8, + 0xc5, 0x60, 0xe3, 0x86, 0xfa, 0xda, 0x92, 0x86, 0x6a, 0x13, 0xf6, 0x51, 0x6d, 0xef, 0x18, 0x76, 0xd6, 0xd7, 0xb5, + 0xb4, 0xab, 0x89, 0xda, 0x6c, 0x14, 0xab, 0x8d, 0x06, 0xb6, 0x0c, 0x3b, 0xcd, 0x31, 0xb3, 0xab, 0xc0, 0x7f, 0xba, + 0x20, 0x1a, 0x07, 0xc8, 0xfa, 0xf6, 0x6b, 0xd7, 0x29, 0xf5, 0x30, 0x61, 0x7b, 0xbb, 0xf3, 0xf1, 0x29, 0xdf, 0x77, + 0x3e, 0x62, 0xe9, 0xb6, 0xbe, 0x39, 0x1b, 0xbb, 0xff, 0xc1, 0xd9, 0xe8, 0xd4, 0xf6, 0xfe, 0x78, 0x04, 0xee, 0xa4, + 0x71, 0x3c, 0x36, 0xd7, 0x94, 0x48, 0x2c, 0xdc, 0x72, 0x5c, 0xf7, 0xd6, 0x6b, 0x31, 0xec, 0x80, 0xda, 0x29, 0x8a, + 0xe0, 0x67, 0xd7, 0xfe, 0x0c, 0x48, 0xb2, 0xd5, 0x21, 0xc7, 0xa2, 0x12, 0x65, 0x50, 0x02, 0x06, 0xd4, 0xb1, 0xb1, + 0xf5, 0x32, 0x88, 0xed, 0x70, 0xc8, 0x61, 0x39, 0x11, 0xd5, 0xd5, 0x15, 0x8c, 0xd8, 0x1c, 0x1b, 0x4e, 0xc0, 0x8c, + 0xf7, 0x5a, 0x15, 0x7a, 0xf1, 0xf3, 0xdf, 0x33, 0xa7, 0x8d, 0x23, 0xc6, 0x72, 0x12, 0x0d, 0x2b, 0x06, 0x37, 0x02, + 0xc7, 0x30, 0x1e, 0x1a, 0x09, 0xb5, 0x3e, 0xd5, 0x51, 0xe3, 0x48, 0xc2, 0x1d, 0x50, 0xbb, 0x1d, 0x9a, 0x73, 0x69, + 0xbd, 0xde, 0x7b, 0xb0, 0xe0, 0x32, 0xc0, 0xed, 0x97, 0x44, 0x37, 0x48, 0x0a, 0x25, 0x4e, 0x82, 0xc2, 0x85, 0x41, + 0x55, 0x4d, 0xe4, 0xb0, 0x33, 0x02, 0x9e, 0xb4, 0x9f, 0x5d, 0xc9, 0x5a, 0x48, 0xce, 0x5a, 0x2d, 0x54, 0x54, 0x1d, + 0xd3, 0xa1, 0x68, 0x65, 0x23, 0xcc, 0x70, 0x66, 0x05, 0x16, 0x38, 0xbd, 0xe2, 0xa2, 0xee, 0x7a, 0x98, 0x8d, 0x10, + 0x2e, 0xd7, 0xeb, 0xd8, 0x0e, 0xad, 0x40, 0xeb, 0x75, 0x11, 0x0e, 0xcd, 0xe4, 0x43, 0xc5, 0xe7, 0x03, 0x4d, 0x9e, + 0x9b, 0xf3, 0xf0, 0x39, 0x0c, 0xb2, 0x45, 0xe2, 0xc2, 0xa9, 0x04, 0x0b, 0xd0, 0x5c, 0xb5, 0xe4, 0x30, 0x6b, 0x75, + 0x47, 0x01, 0x0d, 0x1b, 0x66, 0x23, 0x52, 0x6c, 0xc0, 0x72, 0x56, 0xb9, 0x03, 0xf3, 0x4f, 0x38, 0xd8, 0xfe, 0x34, + 0xe7, 0x8c, 0x6d, 0x30, 0x5c, 0x93, 0x6d, 0x95, 0x41, 0x85, 0x57, 0x6e, 0x71, 0x7d, 0xb9, 0x86, 0x81, 0x45, 0x55, + 0x08, 0xbb, 0x6b, 0xe6, 0x01, 0x08, 0xff, 0x15, 0xb6, 0x97, 0xb4, 0x32, 0xe2, 0xde, 0x42, 0x7c, 0x6f, 0xbb, 0x9d, + 0x24, 0x09, 0x2d, 0xa7, 0xe6, 0x4a, 0xc4, 0xdf, 0xf0, 0x9a, 0x3d, 0x70, 0xea, 0xc6, 0x19, 0xf4, 0x3c, 0xac, 0x3a, + 0x1b, 0x11, 0x3b, 0x7e, 0xcf, 0xec, 0x78, 0xc7, 0x15, 0x4a, 0xf7, 0xeb, 0x22, 0xec, 0x60, 0xb2, 0xff, 0xe5, 0xc1, + 0x9c, 0xb9, 0xc1, 0x58, 0x34, 0xd9, 0x82, 0xdb, 0x57, 0xe0, 0x41, 0xe9, 0x16, 0xdc, 0xbe, 0x0e, 0x5f, 0x0f, 0xad, + 0xe2, 0xab, 0x03, 0x0c, 0xc8, 0x84, 0x1d, 0x69, 0x9d, 0x10, 0x0c, 0xf3, 0x7c, 0x9b, 0x23, 0xb3, 0x64, 0x15, 0x0e, + 0x57, 0x4d, 0x62, 0xb1, 0xb5, 0x17, 0x6a, 0x26, 0x35, 0x10, 0x8c, 0x45, 0xfa, 0x1c, 0x85, 0x4a, 0x83, 0xa6, 0x71, + 0x0c, 0x60, 0x95, 0xd3, 0xd6, 0x3f, 0x3f, 0x3a, 0x02, 0xa1, 0x01, 0x58, 0xbb, 0x24, 0xa3, 0x0b, 0xbd, 0x2c, 0x81, + 0xbf, 0x52, 0xfe, 0x37, 0x24, 0x83, 0xdb, 0x89, 0x49, 0x83, 0x1f, 0x90, 0xb0, 0xa0, 0x4a, 0xf1, 0x2f, 0x36, 0xcd, + 0xfd, 0xc6, 0x25, 0xf1, 0x18, 0xad, 0x2c, 0xa7, 0x28, 0x51, 0x5f, 0x3a, 0x74, 0x6d, 0x42, 0xee, 0xf9, 0x17, 0x26, + 0xf4, 0x8f, 0x5c, 0x69, 0x26, 0x00, 0x00, 0x35, 0xe2, 0xc1, 0x94, 0x14, 0x82, 0xad, 0xdb, 0xa8, 0x45, 0xf3, 0xfc, + 0x9b, 0x55, 0x74, 0x93, 0x2d, 0x9a, 0x51, 0x91, 0x17, 0xb6, 0x93, 0xd0, 0x66, 0xd2, 0xdb, 0x89, 0x56, 0x25, 0x43, + 0x8b, 0x9d, 0x9a, 0xfd, 0x30, 0xb4, 0x3e, 0x16, 0xc4, 0x9f, 0x0b, 0xfe, 0x2c, 0xfd, 0x26, 0x1f, 0x03, 0x57, 0xea, + 0x5f, 0x59, 0x85, 0x70, 0x26, 0x58, 0x07, 0xe4, 0x35, 0x69, 0x8e, 0xd3, 0xa3, 0xce, 0x6c, 0x47, 0xb9, 0x50, 0x19, + 0x85, 0x6d, 0x9d, 0x14, 0x06, 0x53, 0x2e, 0xbe, 0x2e, 0x71, 0xfd, 0xe4, 0x8f, 0x11, 0x7f, 0x74, 0x88, 0xff, 0x94, + 0x4a, 0xa3, 0x55, 0x85, 0x60, 0xc8, 0xef, 0x48, 0xa6, 0xe0, 0x2a, 0xb6, 0xe0, 0xfa, 0xa5, 0x9e, 0x17, 0x5b, 0x9e, + 0x38, 0x7d, 0xa6, 0x2a, 0xe8, 0xa8, 0xf8, 0x96, 0xe1, 0x57, 0x0c, 0xee, 0x8d, 0x5f, 0xf0, 0xa0, 0xca, 0xee, 0x7d, + 0xf1, 0x8b, 0xe0, 0xbe, 0xf8, 0x05, 0x4f, 0x77, 0x8b, 0x06, 0xf7, 0xc4, 0xbd, 0xe4, 0x32, 0xe9, 0x44, 0x9e, 0x8f, + 0xca, 0x69, 0xed, 0x5f, 0x69, 0xb7, 0x06, 0xae, 0x6d, 0xe2, 0xc0, 0x38, 0xaf, 0x29, 0x42, 0x31, 0x67, 0xce, 0x68, + 0x39, 0xfc, 0xaf, 0xad, 0x93, 0x3b, 0x79, 0xa4, 0x95, 0x42, 0xde, 0xd2, 0x52, 0x3f, 0x80, 0x0d, 0x57, 0xee, 0xf8, + 0x00, 0x52, 0x02, 0xca, 0xb6, 0xff, 0xac, 0x8b, 0x40, 0x1c, 0x57, 0xd6, 0xf9, 0x28, 0x6c, 0x9f, 0x94, 0x15, 0x57, + 0xd7, 0x14, 0x42, 0xee, 0x8c, 0x96, 0x00, 0x61, 0xea, 0x5d, 0xf3, 0x98, 0xa3, 0xc9, 0x2c, 0x5d, 0x6d, 0x2a, 0xd5, + 0x41, 0x69, 0xb9, 0x3a, 0x8e, 0x70, 0xb9, 0x31, 0x37, 0xe8, 0x7f, 0x73, 0xfc, 0x27, 0x77, 0x34, 0xf2, 0xfb, 0x8a, + 0x02, 0x7d, 0xdc, 0xef, 0x6b, 0xb3, 0x87, 0x44, 0xda, 0x39, 0x54, 0x96, 0x02, 0x80, 0xd5, 0x06, 0x5f, 0x37, 0x1e, + 0xa7, 0x9e, 0x49, 0x37, 0x9b, 0xaf, 0x1a, 0xc2, 0x62, 0x56, 0x59, 0xf0, 0x98, 0x6e, 0xf6, 0x58, 0x8e, 0x7a, 0x59, + 0x5c, 0x57, 0x7b, 0xac, 0xd1, 0x2f, 0xfa, 0x0a, 0x28, 0x6b, 0x43, 0xb4, 0xf5, 0x3a, 0x6e, 0xc2, 0x9b, 0x88, 0xe0, + 0x1a, 0x04, 0x61, 0x11, 0x18, 0x70, 0x34, 0x18, 0x6f, 0x5b, 0x27, 0x46, 0xdb, 0xf6, 0x4b, 0x9e, 0x75, 0x6f, 0x8c, + 0x23, 0x54, 0x34, 0xd8, 0xea, 0xa1, 0xe6, 0x01, 0xdb, 0xd9, 0x55, 0x1d, 0x05, 0x10, 0xca, 0xa9, 0x37, 0xce, 0xad, + 0xad, 0x68, 0xf7, 0xc0, 0x17, 0x7d, 0xc3, 0x3c, 0xd7, 0x81, 0x6e, 0x37, 0x3f, 0xb0, 0x6d, 0x7a, 0x26, 0xbf, 0x66, + 0xdb, 0xd4, 0xe0, 0x84, 0x0f, 0x3b, 0xe8, 0xdb, 0x86, 0xb0, 0xb6, 0xaf, 0xfd, 0x45, 0xfe, 0x17, 0xba, 0xeb, 0x02, + 0x7a, 0x5a, 0x30, 0x7b, 0x1a, 0xf3, 0x41, 0x6f, 0x36, 0xdf, 0x57, 0xfe, 0x0b, 0xc6, 0x56, 0xe8, 0x7b, 0xbb, 0x0b, + 0x9c, 0x58, 0x69, 0x1c, 0x82, 0xe3, 0xbf, 0x39, 0x99, 0x16, 0x72, 0x4c, 0x8b, 0xf7, 0xd0, 0x63, 0x9d, 0xfb, 0xf2, + 0x3e, 0x2f, 0xa9, 0x66, 0x8e, 0xd6, 0xd4, 0xa3, 0xf8, 0x9b, 0x07, 0xc3, 0xf8, 0x9b, 0x5b, 0xca, 0x5d, 0xb7, 0x80, + 0x57, 0x3f, 0x56, 0x4d, 0xa4, 0xdf, 0x6f, 0x3c, 0xed, 0xe0, 0x6a, 0x7f, 0x2f, 0xdb, 0x24, 0x8d, 0x57, 0x24, 0x8d, + 0xab, 0x78, 0xbb, 0xa9, 0x38, 0xfe, 0xf3, 0x2b, 0x83, 0xdd, 0x25, 0x73, 0x7f, 0x06, 0x64, 0xee, 0x4f, 0x9e, 0x7e, + 0xb3, 0x56, 0x40, 0xf1, 0x4e, 0x93, 0x53, 0x63, 0x19, 0x63, 0x47, 0xfd, 0x4e, 0x83, 0x41, 0x83, 0x26, 0xd7, 0x81, + 0xb7, 0x43, 0x7d, 0x7a, 0x79, 0xfb, 0xa3, 0x38, 0x5b, 0x2a, 0x2d, 0xe7, 0xae, 0x51, 0xe5, 0x7c, 0x9c, 0x4c, 0x26, + 0x28, 0xb0, 0xcd, 0x1d, 0x7e, 0xda, 0x74, 0x23, 0x5b, 0x7d, 0xe6, 0x22, 0x4f, 0x15, 0x76, 0x67, 0x8b, 0x4a, 0xe5, + 0x86, 0x78, 0x33, 0xe7, 0xdd, 0x3c, 0x3c, 0xe1, 0x82, 0xab, 0x19, 0x2b, 0xe3, 0x12, 0xad, 0xbe, 0xd6, 0x59, 0x09, + 0xb7, 0x39, 0xb6, 0x33, 0xbc, 0xac, 0x2c, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xce, 0xf4, 0x4c, 0xe6, 0x60, + 0xf8, 0x92, 0xe4, 0x95, 0x3b, 0xd5, 0xd1, 0xd1, 0x61, 0x1c, 0x19, 0xfd, 0x05, 0xf8, 0xa0, 0x87, 0x39, 0x68, 0xb0, + 0x02, 0xc7, 0xa0, 0xba, 0x6b, 0x86, 0x56, 0x6c, 0xdb, 0x87, 0x46, 0x27, 0x9f, 0xd9, 0x3d, 0xe6, 0x68, 0xb3, 0x49, + 0xed, 0xa8, 0xa3, 0x09, 0x67, 0x45, 0x1e, 0xe1, 0xcf, 0xec, 0x3e, 0xad, 0xdc, 0xd6, 0x8d, 0x97, 0xb5, 0x59, 0xc4, + 0x48, 0xde, 0x8a, 0x08, 0xd7, 0x9d, 0xa4, 0xab, 0x0d, 0x96, 0x25, 0x9f, 0x02, 0x8e, 0xfe, 0xc0, 0xee, 0x53, 0xd7, + 0x5e, 0xe0, 0x2a, 0x88, 0x56, 0x1e, 0xf4, 0x49, 0x90, 0x1c, 0x2e, 0x83, 0x13, 0x38, 0x86, 0xa6, 0xee, 0x88, 0x34, + 0xca, 0xd5, 0x22, 0x24, 0x42, 0x9b, 0xff, 0x74, 0x2a, 0x78, 0x12, 0x9e, 0x73, 0xba, 0x61, 0x71, 0xbb, 0x55, 0x89, + 0x41, 0x85, 0xda, 0x82, 0xe4, 0xd7, 0x98, 0xfb, 0xdd, 0xe7, 0xbc, 0x1f, 0x02, 0x9d, 0xd9, 0x84, 0xba, 0x46, 0xd3, + 0xa5, 0xf9, 0x85, 0xea, 0x3b, 0xa8, 0xb9, 0xae, 0x2b, 0x1e, 0xfc, 0x1a, 0x03, 0xe0, 0xc1, 0x5a, 0x86, 0x1a, 0x87, + 0xd0, 0x8d, 0x37, 0x53, 0x5d, 0x50, 0x12, 0xaf, 0xfc, 0x1c, 0x52, 0x1e, 0x82, 0x51, 0x6f, 0x00, 0x0d, 0x1d, 0x82, + 0x59, 0xcb, 0x43, 0x3e, 0x89, 0xc5, 0xce, 0x19, 0x2a, 0xcd, 0x19, 0x9a, 0x04, 0x20, 0xff, 0xca, 0x99, 0xc9, 0x0c, + 0x34, 0x0c, 0x6f, 0x69, 0x0e, 0x40, 0xb7, 0xba, 0x0e, 0x87, 0xc2, 0x15, 0xad, 0x9c, 0xf7, 0xec, 0xa2, 0xcb, 0xc6, + 0xb0, 0x62, 0xd3, 0x0e, 0xda, 0xa4, 0x30, 0x25, 0x66, 0x0b, 0x6c, 0xbc, 0xde, 0x87, 0x7b, 0xbb, 0xda, 0xb8, 0x4c, + 0xfc, 0xb4, 0x88, 0x87, 0x49, 0x4c, 0xd1, 0x8a, 0xc7, 0x14, 0x4b, 0xb0, 0x83, 0x2c, 0x37, 0xd5, 0xf8, 0x59, 0xb8, + 0x1c, 0x0d, 0x2b, 0xe9, 0xfd, 0x0e, 0x86, 0xc0, 0xe5, 0x6b, 0xb0, 0x0d, 0xc5, 0xbc, 0x22, 0x2c, 0xb1, 0xf1, 0xf4, + 0x0b, 0xd6, 0x6d, 0x6a, 0x17, 0xc4, 0xaf, 0xc0, 0x82, 0xc6, 0xab, 0x60, 0x16, 0xa1, 0x53, 0xb9, 0x73, 0x38, 0x74, + 0xd7, 0x84, 0xb5, 0xf1, 0x6a, 0xac, 0xc8, 0xd6, 0xd1, 0xf3, 0x6d, 0x1b, 0xcf, 0xbf, 0x96, 0xac, 0xbc, 0xbf, 0x61, + 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5e, 0x86, 0xda, 0x40, 0x7e, 0x20, 0x0d, 0xeb, 0xb2, 0xc1, 0xdf, 0x8c, 0x8a, + 0xb1, 0x31, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x55, 0xd7, 0x4d, 0xd6, 0x37, 0xb1, 0x12, 0x6a, 0x48, + 0xbb, 0xbb, 0x05, 0x5c, 0x86, 0xfe, 0xb0, 0x43, 0x35, 0xda, 0x56, 0xdd, 0x40, 0x12, 0x5c, 0xfb, 0xc9, 0xaf, 0x4f, + 0x75, 0x9f, 0xb5, 0xee, 0xd7, 0xa7, 0xda, 0xb8, 0x2c, 0x34, 0x86, 0x44, 0xd8, 0xf5, 0x53, 0xf9, 0x4f, 0x8b, 0xcd, + 0x06, 0x6d, 0x60, 0x78, 0x4f, 0x78, 0x3f, 0x8e, 0x9f, 0x78, 0x0b, 0xc5, 0x04, 0x2e, 0x72, 0x6f, 0x0a, 0xe9, 0x09, + 0x79, 0x3d, 0x82, 0x27, 0x7c, 0x67, 0x08, 0x4f, 0x78, 0xe0, 0xf4, 0x0a, 0x52, 0xd3, 0x54, 0xb0, 0xdc, 0xd3, 0x4f, + 0x64, 0x91, 0xd0, 0xf0, 0x71, 0x6f, 0x38, 0x11, 0xfa, 0x8f, 0x14, 0xf8, 0x2f, 0x3c, 0x5e, 0x6a, 0x2d, 0x05, 0xe6, + 0x62, 0xb1, 0xd4, 0x58, 0x99, 0xd1, 0xaf, 0x26, 0x52, 0xe8, 0xf6, 0x84, 0xce, 0x79, 0x71, 0x9f, 0x2e, 0x79, 0x7b, + 0x2e, 0x85, 0x54, 0x0b, 0x9a, 0x31, 0xac, 0xee, 0x95, 0x66, 0xf3, 0xf6, 0x92, 0xe3, 0x97, 0xac, 0xf8, 0xc2, 0x34, + 0xcf, 0x28, 0x7e, 0x27, 0xc7, 0x52, 0x4b, 0xfc, 0xe6, 0xee, 0x7e, 0xca, 0x04, 0xfe, 0x30, 0x5e, 0x0a, 0xbd, 0xc4, + 0x8a, 0x0a, 0xd5, 0x56, 0xac, 0xe4, 0x93, 0x7e, 0xbb, 0xbd, 0x28, 0xf9, 0x9c, 0x96, 0xf7, 0xed, 0x4c, 0x16, 0xb2, + 0x4c, 0xff, 0xab, 0x73, 0x4a, 0x1f, 0x4d, 0xce, 0xfa, 0xba, 0xa4, 0x42, 0x71, 0x58, 0x98, 0x94, 0x16, 0xc5, 0xc1, + 0xe9, 0x79, 0x67, 0xae, 0x0e, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xf3, 0x07, 0xfe, 0x45, 0xc2, 0x28, 0x93, 0xb1, 0x16, + 0x6e, 0x90, 0xab, 0x6c, 0x59, 0x2a, 0x59, 0xa6, 0x0b, 0xc9, 0x85, 0x66, 0x65, 0x7f, 0x2c, 0xcb, 0x9c, 0x95, 0xed, + 0x92, 0xe6, 0x7c, 0xa9, 0xd2, 0xb3, 0xc5, 0x5d, 0xbf, 0xd9, 0x83, 0xcd, 0x4f, 0x85, 0x14, 0xac, 0x0f, 0xfc, 0xc6, + 0xb4, 0x94, 0x4b, 0x91, 0xbb, 0x61, 0x2c, 0x85, 0x62, 0xba, 0xbf, 0xa0, 0x39, 0xd8, 0x01, 0xa7, 0x97, 0x8b, 0xbb, + 0xbe, 0x99, 0xf5, 0x2d, 0xe3, 0xd3, 0x99, 0x4e, 0xcf, 0x3b, 0x1d, 0xfb, 0xad, 0xf8, 0xdf, 0x2c, 0xed, 0xf6, 0x92, + 0xde, 0xf9, 0xe2, 0x0e, 0x38, 0x78, 0xcd, 0xca, 0x36, 0xc0, 0x02, 0x2a, 0x75, 0x93, 0xce, 0xa3, 0xd3, 0x87, 0x90, + 0x01, 0x36, 0x0e, 0x6d, 0x33, 0x21, 0x30, 0x76, 0x4f, 0x97, 0x8b, 0x05, 0x2b, 0xc1, 0x8b, 0xbe, 0x3f, 0xa7, 0xe5, + 0x94, 0x8b, 0x76, 0x69, 0x1a, 0x6d, 0x5f, 0x2e, 0xee, 0x36, 0x30, 0x9f, 0xd4, 0x9a, 0xad, 0xba, 0x69, 0xb9, 0xaf, + 0x55, 0x30, 0x44, 0x13, 0x93, 0x26, 0x2d, 0xa7, 0x63, 0x1a, 0x77, 0x7b, 0x0f, 0xb1, 0xff, 0x5f, 0xd2, 0x43, 0x01, + 0xd8, 0xda, 0xf9, 0xb2, 0x34, 0xb7, 0xa8, 0x69, 0x57, 0xd9, 0x66, 0x67, 0xf2, 0x0b, 0x2b, 0x7d, 0xab, 0xe6, 0x63, + 0xb5, 0x33, 0xef, 0xff, 0x51, 0xa3, 0xd4, 0xb6, 0xf5, 0x4a, 0xdd, 0x00, 0x8d, 0xde, 0x6d, 0xec, 0xbf, 0x7a, 0x97, + 0xf4, 0xe1, 0xd9, 0xb9, 0x87, 0xfb, 0x64, 0x32, 0x69, 0x00, 0xdd, 0x43, 0xb7, 0xdb, 0x59, 0xdc, 0x1d, 0xf4, 0x3a, + 0x1e, 0xc6, 0x16, 0xa6, 0x17, 0x8b, 0xbb, 0x3d, 0x2b, 0x18, 0x60, 0xc5, 0x76, 0x6f, 0x07, 0xc9, 0xa9, 0x3a, 0x60, + 0x54, 0xb1, 0xcd, 0x1f, 0x78, 0x4e, 0x01, 0x37, 0x0c, 0xd2, 0x0e, 0x8d, 0x9c, 0x0a, 0x2b, 0x30, 0x5a, 0xdd, 0xf2, + 0x5c, 0xcf, 0xd2, 0x6e, 0xa7, 0xf3, 0x5d, 0x8d, 0x49, 0xfd, 0x99, 0x5d, 0xd2, 0x6e, 0xc9, 0xe6, 0x0d, 0xfc, 0x1a, + 0xd3, 0x6a, 0x17, 0xac, 0x16, 0xd2, 0x75, 0x5a, 0xb2, 0xc2, 0x44, 0xb9, 0xd9, 0xb8, 0xad, 0xb0, 0x33, 0x65, 0x2e, + 0x66, 0xac, 0xe4, 0xba, 0xdf, 0xfc, 0xaa, 0x3b, 0xde, 0x9d, 0xd3, 0xc6, 0xca, 0xc7, 0x2b, 0x5b, 0xc3, 0x5d, 0xc6, + 0x3e, 0x85, 0x8f, 0x5d, 0xac, 0xfc, 0x42, 0xcb, 0x78, 0x6b, 0xc3, 0xe0, 0xb0, 0x06, 0xda, 0x04, 0x73, 0x2e, 0xc1, + 0x54, 0x74, 0x84, 0xbf, 0x02, 0x85, 0x8c, 0x16, 0x59, 0x0c, 0x23, 0x3a, 0x68, 0x1f, 0x9c, 0x96, 0x6c, 0x8e, 0x3c, + 0x20, 0x92, 0x87, 0xe7, 0x25, 0x9b, 0x6f, 0x12, 0x53, 0x7d, 0x65, 0x50, 0x97, 0x16, 0x7c, 0x2a, 0xd2, 0x8c, 0xc1, + 0xb6, 0xda, 0x24, 0x4c, 0x68, 0xae, 0xef, 0xdb, 0xa5, 0xbc, 0x5d, 0xe5, 0x5c, 0x2d, 0x0a, 0x7a, 0x9f, 0x4e, 0x0a, + 0x76, 0xd7, 0x37, 0xa5, 0xda, 0x5c, 0xb3, 0xb9, 0x72, 0x65, 0xfb, 0x90, 0xde, 0xce, 0xad, 0x39, 0x07, 0x40, 0x4f, + 0xde, 0x6e, 0xef, 0x6b, 0xbf, 0x68, 0x6d, 0xb9, 0xd4, 0x07, 0x1d, 0xd5, 0x9f, 0x73, 0xd1, 0x76, 0x03, 0x39, 0x03, + 0x8c, 0xd8, 0x85, 0x7c, 0xd0, 0x7f, 0xc2, 0xee, 0x16, 0x54, 0xe4, 0x2c, 0x5f, 0x05, 0xd5, 0x7a, 0x50, 0x2f, 0x2c, + 0x95, 0x0a, 0x3d, 0x6b, 0x1b, 0x1b, 0xb4, 0xb8, 0x27, 0xd0, 0x57, 0x50, 0xfe, 0x51, 0x07, 0xdb, 0xff, 0x4f, 0xba, + 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xbe, 0x0d, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, 0x5a, 0x38, 0x88, + 0xcc, 0x79, 0x9e, 0x17, 0x8d, 0x11, 0x5d, 0x07, 0x9d, 0x75, 0xd1, 0x0a, 0xe6, 0x9f, 0x76, 0x0e, 0x3a, 0x07, 0x66, + 0x2e, 0x6e, 0x1b, 0x9c, 0x9d, 0x3d, 0x3c, 0x7d, 0xc4, 0xfa, 0x05, 0x17, 0xac, 0x31, 0xd5, 0x6f, 0x82, 0x3a, 0x6c, + 0xb8, 0xe7, 0x1a, 0xee, 0x1e, 0x74, 0x0f, 0xce, 0x3a, 0xdf, 0x79, 0x2a, 0x52, 0xb0, 0x89, 0xb6, 0xfb, 0xa6, 0x41, + 0x56, 0x2e, 0x7d, 0xd3, 0xb7, 0x25, 0x5d, 0xa4, 0x42, 0xc2, 0x9f, 0x3e, 0x6c, 0xfe, 0x49, 0x21, 0x6f, 0xd3, 0x19, + 0xcf, 0x73, 0x26, 0x6c, 0x81, 0x2a, 0x91, 0x15, 0x05, 0x5f, 0x28, 0x6e, 0x57, 0xc3, 0xe1, 0xee, 0xf9, 0x16, 0x54, + 0xc3, 0x01, 0x9d, 0x06, 0x03, 0x3a, 0xaf, 0x07, 0x54, 0xf7, 0x1f, 0x8e, 0xb0, 0xb7, 0x35, 0x57, 0x53, 0xaa, 0xdf, + 0xc0, 0xa4, 0x3f, 0x97, 0x4a, 0x03, 0xcc, 0xbd, 0xf1, 0x88, 0x39, 0x5d, 0xda, 0x63, 0xa6, 0x6f, 0x19, 0x13, 0x5f, + 0x1f, 0xc4, 0x75, 0x2a, 0x45, 0x71, 0x6f, 0x3f, 0x57, 0x61, 0x97, 0x74, 0xa9, 0xe5, 0x26, 0x19, 0x73, 0x41, 0xcb, + 0xfb, 0x4f, 0x8a, 0x09, 0x25, 0xcb, 0x4f, 0x72, 0x32, 0x59, 0x7d, 0x8d, 0xe4, 0x3d, 0x44, 0x9b, 0x44, 0x71, 0x31, + 0x2d, 0x98, 0x25, 0x70, 0x06, 0x11, 0xdc, 0x21, 0x63, 0xdb, 0x35, 0x4d, 0x36, 0x06, 0xbd, 0x49, 0xb2, 0x82, 0xcf, + 0xa9, 0x66, 0x06, 0xce, 0x01, 0xa9, 0x71, 0x93, 0xb7, 0x54, 0xae, 0x73, 0x60, 0xff, 0xd4, 0xa5, 0x61, 0x1b, 0x05, + 0x85, 0x7d, 0x93, 0x5c, 0x18, 0xfc, 0x30, 0xe0, 0x30, 0xbb, 0xc8, 0xac, 0x9e, 0x59, 0xbb, 0x00, 0x76, 0x30, 0xbb, + 0x46, 0x53, 0xd7, 0x8e, 0x2e, 0xd9, 0x16, 0xcf, 0x3b, 0xdf, 0x35, 0x73, 0x0b, 0x3a, 0x66, 0xc5, 0xca, 0x6e, 0x54, + 0x0f, 0x5c, 0xb7, 0x55, 0xc3, 0x65, 0x0e, 0x48, 0x86, 0x01, 0xd1, 0x28, 0x4d, 0xdb, 0xb7, 0x6c, 0xfc, 0x99, 0x6b, + 0xbb, 0x65, 0xda, 0xea, 0x16, 0x9c, 0x8a, 0xcc, 0x98, 0x16, 0xac, 0x5c, 0x79, 0x42, 0xde, 0x69, 0x10, 0xd0, 0x1b, + 0x61, 0x0e, 0x68, 0x4d, 0xc7, 0x6d, 0x08, 0xb1, 0xc6, 0xca, 0xd5, 0xbe, 0xc9, 0xcd, 0xe9, 0x9d, 0x43, 0xb1, 0x47, + 0x9d, 0xef, 0x1a, 0x87, 0xec, 0x59, 0xa7, 0xe3, 0x8f, 0x88, 0xb6, 0xad, 0x91, 0x76, 0x93, 0x73, 0x36, 0xaf, 0x12, + 0xb5, 0x5c, 0xa4, 0x8d, 0x84, 0xb1, 0xd4, 0x5a, 0xce, 0x6d, 0xda, 0x1e, 0x6a, 0xd4, 0x24, 0xbd, 0xdd, 0xde, 0xe2, + 0xee, 0xc0, 0xfc, 0xd3, 0x39, 0xe8, 0xec, 0x92, 0xda, 0x5d, 0xac, 0x38, 0x45, 0x1e, 0x8f, 0xa1, 0xe3, 0x2e, 0x9b, + 0xf7, 0x97, 0x0a, 0x8e, 0x7b, 0x03, 0x71, 0x73, 0xa2, 0x6d, 0xcc, 0x64, 0x01, 0xb0, 0x94, 0x0b, 0x38, 0x5d, 0xed, + 0x61, 0x07, 0x7d, 0x28, 0x09, 0xe6, 0xf0, 0x7b, 0x1b, 0x6d, 0x0e, 0xab, 0x73, 0x50, 0x0f, 0x0c, 0xfe, 0xd9, 0xfc, + 0x51, 0xf3, 0xe7, 0xcf, 0x58, 0x20, 0x1f, 0xf1, 0x56, 0x72, 0xbe, 0xee, 0x38, 0x99, 0x28, 0xd7, 0xb5, 0xa8, 0x66, + 0x3c, 0x4a, 0xe6, 0xf4, 0xce, 0xba, 0x96, 0xcc, 0xb9, 0x00, 0xc3, 0x35, 0x84, 0x75, 0x60, 0xe2, 0x3f, 0x0b, 0x1b, + 0xca, 0x75, 0x0c, 0x0d, 0x1f, 0xf7, 0x92, 0xf3, 0x73, 0x84, 0x3b, 0xb8, 0x77, 0x7e, 0x1e, 0xc8, 0x64, 0x13, 0xbd, + 0xaf, 0xe8, 0xbe, 0x92, 0x72, 0x4f, 0xc9, 0x13, 0xd3, 0xe8, 0x49, 0xb7, 0xd3, 0xc1, 0xc6, 0x7d, 0xbe, 0x2a, 0x2c, + 0xd4, 0x9e, 0x66, 0xbb, 0x9d, 0x0e, 0x34, 0x0b, 0x7f, 0xdc, 0xbc, 0x7e, 0x20, 0xab, 0x4e, 0xda, 0xc1, 0xdd, 0xb4, + 0x8b, 0x7b, 0x69, 0x0f, 0x9f, 0xa6, 0xa7, 0xf8, 0x2c, 0x3d, 0xc3, 0xe7, 0xe9, 0x39, 0xbe, 0x48, 0x2f, 0xf0, 0xc3, + 0xf4, 0x21, 0xbe, 0x4c, 0x2f, 0xf1, 0xa3, 0xf4, 0x11, 0x7e, 0x9c, 0x76, 0x3b, 0xf8, 0x49, 0xda, 0xed, 0xe2, 0xa7, + 0x69, 0xb7, 0x87, 0x9f, 0xa5, 0xdd, 0x53, 0xfc, 0x3c, 0xed, 0x9e, 0xe1, 0x17, 0x69, 0xf7, 0x1c, 0x53, 0xc8, 0x1d, + 0x43, 0x6e, 0x06, 0xb9, 0x39, 0xe4, 0x32, 0xc8, 0x9d, 0xa4, 0xdd, 0xf3, 0x0d, 0x56, 0x36, 0xe4, 0x46, 0xd4, 0xe9, + 0xf6, 0x4e, 0xcf, 0xce, 0x2f, 0x1e, 0x5e, 0x3e, 0x7a, 0xfc, 0xe4, 0xe9, 0xb3, 0xe7, 0x2f, 0xa2, 0x11, 0xfe, 0x64, + 0x3c, 0x5f, 0x94, 0x18, 0xf2, 0xa3, 0xee, 0xf9, 0x08, 0xdf, 0xfb, 0xcf, 0x98, 0x1f, 0xf5, 0xce, 0x3a, 0xe8, 0xfa, + 0xfa, 0x6c, 0xd4, 0xaa, 0x72, 0x9f, 0x18, 0x87, 0x9b, 0x3a, 0x8b, 0x10, 0x12, 0x43, 0x0e, 0xc2, 0x77, 0xd6, 0x81, + 0x86, 0xc5, 0x3c, 0x29, 0xd1, 0xd1, 0x91, 0xf9, 0x31, 0xf5, 0x3f, 0xc6, 0xfe, 0x07, 0x0d, 0x16, 0xe9, 0x0b, 0x8d, + 0x9d, 0xc7, 0xb5, 0xae, 0xfc, 0x1d, 0x2a, 0x53, 0xa2, 0x03, 0xee, 0x8c, 0xfa, 0xff, 0x2b, 0xb2, 0x46, 0x3b, 0xe4, + 0xcc, 0x2a, 0xc6, 0xce, 0x07, 0x8c, 0xac, 0xca, 0xb4, 0x77, 0x7e, 0x7e, 0xf4, 0xc3, 0x90, 0x0f, 0xbb, 0xa3, 0xd1, + 0x71, 0xf7, 0x21, 0x9e, 0x56, 0x09, 0x3d, 0x9b, 0x30, 0xae, 0x12, 0x4e, 0x6d, 0x02, 0x4d, 0x6d, 0x6d, 0x48, 0x3a, + 0x33, 0x49, 0x50, 0x62, 0x93, 0x9a, 0xb6, 0x1f, 0xda, 0xb6, 0x1f, 0x81, 0x35, 0x99, 0x69, 0xde, 0x35, 0x7d, 0x75, + 0x75, 0xb6, 0x76, 0x8d, 0xe2, 0x69, 0xea, 0x5a, 0xf3, 0x89, 0x67, 0xa3, 0x11, 0x1e, 0x9b, 0xc4, 0xf3, 0x3a, 0xf1, + 0x62, 0x34, 0x72, 0x5d, 0x3d, 0x32, 0x5d, 0x3d, 0xac, 0xb3, 0x2e, 0x47, 0x23, 0xd3, 0x25, 0x72, 0xb1, 0x03, 0x94, + 0x3e, 0xb8, 0xad, 0xf4, 0x37, 0xfc, 0xaa, 0x77, 0x7e, 0x3e, 0x00, 0x0c, 0x33, 0x36, 0xc1, 0x1e, 0x46, 0x9f, 0x03, + 0x18, 0xdd, 0xc1, 0xef, 0xc1, 0x27, 0x9a, 0xde, 0xd3, 0x0a, 0x48, 0x83, 0xe8, 0xbf, 0xa2, 0x96, 0x36, 0x30, 0x37, + 0x7f, 0xa6, 0xf6, 0xcf, 0x18, 0xb5, 0x6e, 0x29, 0x80, 0x1b, 0x34, 0x52, 0x5e, 0xa5, 0x6c, 0x7a, 0xbc, 0xa1, 0xe0, + 0xe2, 0x33, 0x53, 0x05, 0x1d, 0xac, 0x67, 0xb7, 0xe3, 0xf5, 0x4c, 0x7d, 0x41, 0xbf, 0xc7, 0xbf, 0xab, 0xe3, 0x78, + 0xd8, 0x6e, 0x25, 0xec, 0xf7, 0x1c, 0x7c, 0x89, 0x06, 0x69, 0xce, 0xa6, 0x68, 0x30, 0xfc, 0x5d, 0xe1, 0x51, 0x2b, + 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0xd0, 0x00, 0x0d, 0x7e, 0x57, 0xc7, 0xbf, 0xa3, + 0x07, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x87, 0x1f, 0x3a, 0xae, 0xb6, 0x30, 0xc3, 0xdd, 0x36, 0x83, 0x60, + 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe2, 0x27, 0xa7, 0x1d, 0xf4, 0x5d, 0xb7, 0x07, 0xca, 0x95, 0xb6, 0x38, 0xde, + 0xdd, 0xf4, 0x65, 0xfb, 0x14, 0x3f, 0x6a, 0x97, 0xb8, 0x8b, 0x70, 0xbb, 0xeb, 0xb5, 0xde, 0x43, 0x15, 0x77, 0x10, + 0x56, 0xf1, 0x25, 0xfc, 0x73, 0x86, 0x46, 0xf5, 0x86, 0xfc, 0x89, 0x6e, 0xf7, 0x0e, 0x7e, 0xb3, 0x24, 0x56, 0x2d, + 0x7e, 0x72, 0xd1, 0x41, 0xdf, 0x5d, 0x98, 0x8e, 0xd8, 0xb1, 0xde, 0xd3, 0x95, 0xc4, 0x67, 0x6d, 0x09, 0x1d, 0x75, + 0xaa, 0x7e, 0x44, 0x7c, 0x8e, 0xb0, 0x88, 0x4f, 0xe1, 0x9f, 0x6e, 0xd8, 0xcf, 0xd3, 0x9d, 0x7e, 0xcc, 0xbc, 0xbb, + 0x38, 0x39, 0xb7, 0x6e, 0xb8, 0xca, 0xde, 0x89, 0xb7, 0xd8, 0x75, 0xd7, 0x5c, 0xe6, 0x75, 0x4f, 0xe0, 0x03, 0x61, + 0x7d, 0x4c, 0x14, 0x66, 0xc7, 0xe0, 0xbf, 0x0b, 0x66, 0x2b, 0xea, 0xea, 0xb4, 0xaf, 0x5a, 0x2d, 0x24, 0x86, 0x6a, + 0x74, 0x4c, 0xba, 0x6d, 0xdd, 0x66, 0x18, 0x7e, 0xb7, 0x48, 0x15, 0x14, 0x4e, 0xd4, 0xbd, 0xbe, 0x71, 0xbd, 0xda, + 0x9b, 0x7f, 0x8f, 0x1d, 0x84, 0x10, 0x35, 0x88, 0x75, 0x9b, 0xa1, 0x13, 0xd1, 0x8a, 0xf5, 0x15, 0x1b, 0x5c, 0xa4, + 0x1d, 0x64, 0xb0, 0x53, 0x0d, 0x62, 0xd6, 0xe6, 0x90, 0xde, 0x4b, 0x63, 0xde, 0xd6, 0xf0, 0xeb, 0x2c, 0x80, 0x96, + 0x00, 0xbc, 0xab, 0xbd, 0x91, 0xca, 0x93, 0xde, 0xf9, 0x39, 0x16, 0x84, 0x27, 0x53, 0xf3, 0x4b, 0x11, 0x9e, 0x8c, + 0xcd, 0x2f, 0x49, 0x2a, 0x78, 0xd9, 0xde, 0x71, 0x49, 0x82, 0x55, 0x35, 0x29, 0x14, 0x16, 0xb4, 0x44, 0x27, 0x3d, + 0x6f, 0x16, 0x80, 0x67, 0x7e, 0x0e, 0xa0, 0x06, 0x29, 0x8d, 0x45, 0xa8, 0x6c, 0x97, 0xb8, 0x20, 0xf4, 0x3a, 0x39, + 0x1f, 0xcc, 0x4e, 0xe2, 0x5e, 0x5b, 0xb6, 0x4b, 0x94, 0xce, 0x4e, 0x4c, 0x4d, 0x9c, 0x91, 0x37, 0xd4, 0xb6, 0x86, + 0x67, 0x70, 0x97, 0x9b, 0x91, 0xec, 0xf8, 0xa2, 0xd3, 0x4a, 0xce, 0x11, 0x1e, 0x66, 0xeb, 0x0e, 0x2e, 0xd6, 0xeb, + 0x0e, 0xa6, 0xe1, 0x32, 0x08, 0x0f, 0x90, 0x4a, 0x53, 0xb7, 0x1d, 0x9b, 0x67, 0xc0, 0x63, 0x0d, 0x76, 0x09, 0x1a, + 0xbc, 0x7d, 0x34, 0xf8, 0x21, 0xa5, 0xdc, 0x5d, 0x08, 0x22, 0x13, 0x9d, 0x70, 0x12, 0xea, 0xee, 0xde, 0x08, 0xbf, + 0xae, 0xde, 0xb2, 0x54, 0xc4, 0xbf, 0x4a, 0x6c, 0xd3, 0xea, 0x62, 0x0f, 0xe8, 0x6e, 0xb1, 0xa7, 0x74, 0xa7, 0xd8, + 0xdb, 0x3d, 0xc5, 0x7e, 0xda, 0x2d, 0xf6, 0x97, 0x0c, 0x34, 0x8d, 0xfc, 0xbb, 0xd3, 0x8b, 0x4e, 0xeb, 0x14, 0x90, + 0xf5, 0xf4, 0xa2, 0x53, 0x17, 0x7a, 0x4c, 0xeb, 0xb5, 0xd2, 0xe4, 0x86, 0x5a, 0x5f, 0x0b, 0xee, 0x9d, 0xbe, 0xcd, + 0xc2, 0x59, 0x97, 0xf3, 0xca, 0xbf, 0x7c, 0x78, 0x0e, 0xb6, 0x2c, 0xc2, 0x50, 0x3b, 0x3d, 0xbc, 0x18, 0x0d, 0x66, + 0x2c, 0x6e, 0x41, 0x2a, 0x4a, 0x27, 0xda, 0xfd, 0x42, 0xd5, 0x95, 0xf6, 0x5f, 0x12, 0x92, 0x7a, 0x23, 0x84, 0x25, + 0x69, 0xe9, 0xe1, 0xe9, 0xc8, 0x9c, 0x77, 0x25, 0xfc, 0x3e, 0x33, 0xbf, 0x2b, 0x85, 0x92, 0x73, 0xc8, 0x98, 0xdd, + 0x8e, 0xa3, 0x81, 0x20, 0x0f, 0x68, 0x6c, 0x6c, 0xec, 0x51, 0x5a, 0x65, 0xa8, 0x2f, 0x90, 0xf1, 0xb6, 0xca, 0x10, + 0xe4, 0x8d, 0x70, 0xbf, 0xf1, 0xaa, 0x4c, 0xc1, 0xde, 0x06, 0x4f, 0x53, 0xb0, 0xb5, 0xc1, 0xe3, 0x54, 0x80, 0x3f, + 0x08, 0x4d, 0x59, 0x60, 0xc5, 0xff, 0xdc, 0x69, 0xf0, 0xcc, 0xad, 0x33, 0x31, 0x58, 0xda, 0x67, 0x70, 0x52, 0xfc, + 0x25, 0x63, 0xf8, 0xdb, 0xd2, 0x08, 0x33, 0x68, 0x93, 0x21, 0xcc, 0x93, 0x92, 0x40, 0x1a, 0xe6, 0xc9, 0x94, 0x30, + 0x68, 0x92, 0x27, 0x63, 0xc2, 0x86, 0xbd, 0x00, 0x4d, 0x5e, 0x19, 0xd8, 0x01, 0x70, 0x78, 0xf3, 0x22, 0x5f, 0xdb, + 0xc6, 0xc1, 0x42, 0x00, 0x9a, 0x10, 0x04, 0x62, 0x2e, 0x0c, 0xc1, 0x6c, 0x44, 0xd9, 0x9f, 0xbd, 0x3a, 0xfc, 0x25, + 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x00, 0x59, 0x8d, 0x1f, 0xac, 0xd8, 0x06, 0x1f, 0x3c, 0x58, 0x89, 0xcd, 0x77, 0xf0, + 0x47, 0xd9, 0x3f, 0xc0, 0x3c, 0x24, 0x14, 0x6d, 0xd0, 0x1f, 0x29, 0x14, 0xdb, 0x53, 0x0a, 0xfd, 0xe1, 0xdd, 0x01, + 0x15, 0x59, 0xdd, 0xa5, 0x51, 0x4e, 0xcb, 0xcf, 0x11, 0xfe, 0x2d, 0x8d, 0x0a, 0xe0, 0x16, 0x23, 0xfc, 0x6b, 0x1a, + 0x95, 0x2c, 0xc2, 0xff, 0x4a, 0xa3, 0x71, 0xb1, 0x8c, 0xf0, 0x2f, 0x69, 0x34, 0x2d, 0x23, 0xfc, 0x11, 0x94, 0xb5, + 0x39, 0x5f, 0xce, 0x23, 0xfc, 0x21, 0x8d, 0x94, 0xf1, 0x86, 0xc0, 0x8f, 0xd3, 0x88, 0xb1, 0x08, 0xbf, 0x4f, 0x23, + 0x59, 0x44, 0xf8, 0x26, 0x8d, 0x64, 0x19, 0xe1, 0x27, 0x69, 0x54, 0xd2, 0x08, 0x3f, 0x4d, 0x23, 0x28, 0x34, 0x8d, + 0xf0, 0xb3, 0x34, 0x82, 0x96, 0x55, 0x84, 0xdf, 0xa5, 0x11, 0x17, 0x11, 0xfe, 0x39, 0x8d, 0xf4, 0xb2, 0xfc, 0x6b, + 0x29, 0xb9, 0x8a, 0xf0, 0xf3, 0x34, 0x9a, 0xf1, 0x08, 0xbf, 0x4d, 0xa3, 0x52, 0x46, 0xf8, 0x4d, 0x1a, 0xd1, 0x22, + 0xc2, 0xaf, 0xd3, 0xa8, 0x60, 0x11, 0xfe, 0x29, 0x8d, 0x72, 0x16, 0xe1, 0x1f, 0xd3, 0xe8, 0x9e, 0x15, 0x85, 0x8c, + 0xf0, 0x8b, 0x34, 0x62, 0x22, 0xc2, 0x3f, 0xa4, 0x51, 0x36, 0x8b, 0xf0, 0x3f, 0xd3, 0x88, 0x96, 0x9f, 0x55, 0x84, + 0x5f, 0xa6, 0x11, 0xa3, 0x11, 0x7e, 0x65, 0x3b, 0x9a, 0x46, 0xf8, 0xfb, 0x34, 0xba, 0x9d, 0x45, 0x1b, 0x2c, 0x15, + 0x59, 0xbd, 0xe1, 0x19, 0xfb, 0x17, 0x4b, 0xa3, 0x49, 0x67, 0x72, 0x39, 0x99, 0x44, 0x98, 0x0a, 0xcd, 0xff, 0x5a, + 0xb2, 0xdb, 0xe7, 0x1a, 0x12, 0x29, 0x1b, 0xe7, 0x0f, 0x23, 0x4c, 0xff, 0x5a, 0xd2, 0x34, 0x9a, 0x4c, 0x4c, 0x81, + 0xbf, 0x96, 0x74, 0x4e, 0xcb, 0x77, 0x2c, 0x8d, 0x1e, 0x4e, 0x26, 0x93, 0xfc, 0x2c, 0xc2, 0xf4, 0xef, 0xe5, 0xaf, + 0xa6, 0x05, 0x53, 0x60, 0xcc, 0xf8, 0x14, 0xea, 0x9e, 0x4f, 0xce, 0xf3, 0x2c, 0xc2, 0x63, 0xae, 0xfe, 0x5a, 0xc2, + 0xf7, 0x84, 0x9d, 0x65, 0x67, 0x11, 0x1e, 0x17, 0x34, 0xfb, 0x9c, 0x46, 0x1d, 0xf3, 0x4b, 0xfc, 0xc0, 0xf2, 0x37, + 0x73, 0x69, 0xae, 0x32, 0x26, 0x6c, 0x9c, 0xe5, 0x11, 0x36, 0x83, 0x99, 0xc0, 0xdf, 0x2f, 0xfc, 0x3d, 0xd3, 0x69, + 0x74, 0x49, 0x7b, 0x63, 0xd6, 0x8b, 0xf0, 0xf8, 0xed, 0xad, 0x48, 0x23, 0x7a, 0xde, 0xa3, 0x3d, 0x1a, 0xe1, 0xf1, + 0xb2, 0x2c, 0xee, 0x6f, 0xa5, 0xcc, 0x01, 0x08, 0xe3, 0xcb, 0xcb, 0x87, 0x11, 0xce, 0xe8, 0x4f, 0x1a, 0x6a, 0x9f, + 0x4f, 0x1e, 0x31, 0xda, 0x89, 0xf0, 0x0f, 0xb4, 0xd4, 0xbf, 0x2e, 0x95, 0x1b, 0x68, 0x07, 0x52, 0x64, 0xf6, 0x1e, + 0xd4, 0xfc, 0x51, 0xde, 0xbb, 0x78, 0xd4, 0x65, 0x11, 0xce, 0x6e, 0xde, 0x40, 0x6f, 0x0f, 0x27, 0xe7, 0x1d, 0xf8, + 0x10, 0x20, 0x97, 0xb2, 0x12, 0x1a, 0xb9, 0x38, 0x7b, 0x74, 0xce, 0x72, 0x93, 0xa8, 0x78, 0xf1, 0xd9, 0xcc, 0xfe, + 0x12, 0xe6, 0x93, 0x95, 0x7c, 0xae, 0xa4, 0x48, 0xa3, 0x3c, 0xeb, 0x9e, 0x9d, 0x42, 0xc2, 0x3d, 0x15, 0x1e, 0x38, + 0x77, 0x50, 0xf5, 0x72, 0x1c, 0xe1, 0x3b, 0x9b, 0x7a, 0x39, 0x36, 0x1f, 0xd3, 0xf7, 0x3f, 0x89, 0xb7, 0x79, 0x1a, + 0x8d, 0x2f, 0x2f, 0x2f, 0x3a, 0x90, 0xf0, 0x0b, 0xbd, 0x4f, 0x23, 0xfa, 0x08, 0xfe, 0x83, 0xec, 0x5f, 0x5f, 0x40, + 0x87, 0x30, 0xc2, 0xbb, 0xe9, 0xaf, 0x61, 0xce, 0xe7, 0x19, 0xfd, 0xcc, 0xd3, 0x68, 0x9c, 0x8f, 0x1f, 0x5e, 0x40, + 0xbd, 0x39, 0x9d, 0xbe, 0xd0, 0x14, 0xda, 0xed, 0x74, 0x4c, 0xcb, 0xef, 0xf9, 0x17, 0x66, 0xaa, 0x9f, 0x9f, 0x5f, + 0x8c, 0x7b, 0x30, 0x82, 0x1b, 0x50, 0xa8, 0xc0, 0x78, 0x2e, 0x33, 0xd3, 0xe0, 0x4d, 0xf6, 0x3c, 0x4f, 0xa3, 0x47, + 0x8f, 0x4e, 0x7b, 0x59, 0x16, 0xe1, 0xbb, 0x5f, 0x73, 0x5b, 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x47, 0x8f, + 0x2e, 0x1e, 0x52, 0xf8, 0x7e, 0x69, 0xda, 0xba, 0x9c, 0x8c, 0xb3, 0x4b, 0x68, 0xeb, 0x03, 0x4c, 0xe7, 0xec, 0xf2, + 0x34, 0x37, 0x7d, 0x7d, 0x30, 0xa3, 0xee, 0x4d, 0xce, 0x26, 0x67, 0x26, 0xd3, 0x0c, 0xb5, 0xfa, 0xfc, 0x99, 0xa5, + 0x51, 0xc6, 0xf2, 0x6e, 0x84, 0xef, 0xdc, 0xc2, 0x3d, 0x3a, 0xeb, 0x74, 0xf2, 0xd3, 0x08, 0xe7, 0x8f, 0x17, 0x8b, + 0x77, 0x06, 0x82, 0xdd, 0xb3, 0x47, 0xf6, 0x5b, 0x7d, 0xbe, 0x87, 0xa6, 0xc7, 0x06, 0x68, 0x39, 0x9f, 0x9b, 0x96, + 0x2f, 0x1e, 0xc1, 0x7f, 0xe6, 0xdb, 0x34, 0x5d, 0x7d, 0xcb, 0x7c, 0x6a, 0x17, 0xa5, 0xcb, 0x1e, 0x75, 0xa0, 0xc6, + 0x84, 0xff, 0x3a, 0x2e, 0x39, 0xa0, 0xd1, 0xb8, 0x07, 0xff, 0x17, 0xe1, 0x49, 0x71, 0xf3, 0xc6, 0xe1, 0xec, 0x64, + 0x42, 0x27, 0x9d, 0x08, 0x4f, 0xe4, 0xaf, 0x4a, 0xff, 0xf2, 0x58, 0xa4, 0x51, 0xaf, 0x77, 0x39, 0x36, 0x65, 0x96, + 0x3f, 0x28, 0x6e, 0xf0, 0xb8, 0x63, 0x5a, 0x99, 0xd2, 0x77, 0x6a, 0x7c, 0x23, 0x61, 0x25, 0xe1, 0xbf, 0x08, 0x4f, + 0x41, 0x0b, 0xe7, 0x5a, 0xb9, 0xb4, 0xdb, 0x61, 0xfa, 0xde, 0xa0, 0x66, 0xfe, 0x10, 0xe0, 0xe5, 0x97, 0x31, 0xa7, + 0xf4, 0xbc, 0xd7, 0x89, 0xb0, 0x19, 0xf5, 0x65, 0x07, 0xfe, 0x8b, 0xb0, 0x85, 0x9c, 0x81, 0xeb, 0xf4, 0xd7, 0x17, + 0x3f, 0xde, 0xa6, 0x11, 0xcd, 0x27, 0x13, 0x58, 0x12, 0x33, 0x19, 0x5f, 0x6c, 0x26, 0x05, 0xbb, 0xff, 0xe9, 0xd6, + 0x6d, 0x17, 0x93, 0xa0, 0x1d, 0x74, 0x2e, 0x1e, 0x8d, 0xcf, 0x22, 0xfc, 0x2e, 0xe7, 0x54, 0xc0, 0x2a, 0x65, 0xf9, + 0x79, 0x76, 0x9e, 0x99, 0x84, 0xa9, 0x4c, 0xa3, 0x33, 0x58, 0xf2, 0x5e, 0x84, 0xf9, 0x97, 0x9b, 0x7b, 0x8b, 0x6e, + 0x50, 0xdb, 0x21, 0xc8, 0xa4, 0xc3, 0x2e, 0x2e, 0xb3, 0x08, 0x17, 0xf4, 0xcb, 0x8b, 0x9f, 0xca, 0x34, 0x62, 0x17, + 0xec, 0x62, 0x42, 0xfd, 0xf7, 0xbf, 0xd4, 0xcc, 0xd4, 0xe8, 0x4c, 0xce, 0x21, 0xe9, 0x56, 0x98, 0xb1, 0x3e, 0xcc, + 0x26, 0x06, 0x43, 0x5e, 0xcf, 0xa5, 0xc8, 0x9e, 0x4f, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, 0x1b, 0x40, 0x9b, + 0xe6, 0xf9, 0x25, 0xbb, 0x88, 0xf0, 0x6f, 0x76, 0x97, 0xb8, 0x09, 0xfc, 0x66, 0x31, 0x9b, 0xb9, 0xdd, 0xfe, 0x9b, + 0x05, 0x0a, 0xcc, 0x77, 0x42, 0x27, 0x34, 0xef, 0x45, 0xf8, 0x37, 0x03, 0x97, 0xfc, 0x14, 0xfe, 0x83, 0x02, 0xd0, + 0xd9, 0xa3, 0x0e, 0x63, 0x8f, 0x3a, 0xe6, 0x2b, 0xcc, 0x73, 0x33, 0x1f, 0x5f, 0x64, 0xdd, 0x08, 0xff, 0xe6, 0xd0, + 0x71, 0x32, 0xa1, 0x1d, 0x40, 0xc7, 0xdf, 0x1c, 0x3a, 0xf6, 0x3a, 0xe3, 0x1e, 0x35, 0xdf, 0x16, 0x6b, 0x2e, 0x1f, + 0x66, 0x0c, 0x26, 0xf7, 0x9b, 0x45, 0xc8, 0x87, 0x0f, 0x2f, 0x2f, 0x1f, 0x3d, 0x82, 0x4f, 0xd3, 0x76, 0xf5, 0xa9, + 0xf4, 0xe3, 0xc2, 0x20, 0x59, 0x27, 0x3b, 0x03, 0x3a, 0xf9, 0x9b, 0x19, 0xe3, 0x64, 0x32, 0x61, 0x9d, 0x08, 0x17, + 0x7c, 0xce, 0x2c, 0x26, 0xd8, 0xdf, 0xa6, 0xa3, 0xd3, 0x5e, 0x96, 0x9f, 0xf6, 0x22, 0x5c, 0xbc, 0x7b, 0x61, 0x66, + 0xd3, 0x81, 0xd9, 0xfb, 0x2d, 0xe7, 0xb1, 0x66, 0x4e, 0xdf, 0xc2, 0x20, 0x61, 0xa5, 0xa1, 0xf2, 0xc7, 0x80, 0x1e, + 0x5e, 0x5c, 0x64, 0x39, 0x0c, 0xf4, 0x23, 0x74, 0x0b, 0x60, 0xfc, 0x68, 0x37, 0xdf, 0x98, 0x9e, 0x9f, 0xc3, 0x74, + 0x3f, 0x2e, 0x96, 0xe5, 0xe2, 0x75, 0x1a, 0x3d, 0x3a, 0x7d, 0xd8, 0xc9, 0xc7, 0x11, 0xfe, 0xe8, 0x26, 0x78, 0x9a, + 0x8d, 0x4f, 0x1f, 0x76, 0x23, 0xfc, 0xd1, 0xec, 0xb7, 0x87, 0xe3, 0x8b, 0x4b, 0x38, 0x37, 0x3e, 0xaa, 0x45, 0xf9, + 0x6e, 0x6a, 0x0a, 0x4c, 0xe8, 0x23, 0x68, 0xf6, 0x67, 0xb3, 0x1b, 0xf3, 0x2e, 0x6c, 0xe4, 0x8f, 0x66, 0x93, 0x19, + 0x3c, 0x79, 0xd8, 0x3d, 0xbf, 0x3c, 0x8f, 0xf0, 0x9c, 0xe7, 0x02, 0x08, 0xbc, 0xd9, 0x28, 0x8f, 0xba, 0x8f, 0x1e, + 0x76, 0x22, 0x3c, 0x7f, 0xa7, 0xb3, 0x5f, 0xe9, 0xdc, 0x50, 0xe3, 0x09, 0xc0, 0x6c, 0xce, 0x95, 0xbe, 0x7f, 0xab, + 0x1c, 0x3d, 0x66, 0xdd, 0x08, 0xcf, 0x65, 0x96, 0x51, 0xf5, 0xce, 0x26, 0x8c, 0xcf, 0x23, 0x2c, 0xe8, 0x17, 0xfa, + 0xa7, 0xf4, 0x9b, 0x29, 0x67, 0x34, 0x37, 0x69, 0x06, 0x87, 0x23, 0xfc, 0x3e, 0x87, 0xcb, 0xc8, 0x34, 0x9a, 0xe4, + 0x93, 0x73, 0x00, 0x0f, 0x10, 0x20, 0x8b, 0xdd, 0x00, 0x0d, 0xf8, 0xca, 0x9f, 0x8c, 0xd3, 0xe8, 0x62, 0x7c, 0xc9, + 0x7a, 0xa7, 0x11, 0xae, 0xa8, 0x11, 0x3d, 0x87, 0x7c, 0xf3, 0xf9, 0xab, 0xd9, 0x52, 0x67, 0x36, 0xc1, 0x00, 0x28, + 0xa7, 0x0f, 0x3b, 0xf9, 0x45, 0x84, 0x17, 0x6f, 0x98, 0xdf, 0x63, 0x8c, 0xb1, 0x4b, 0x80, 0x25, 0x24, 0x19, 0x04, + 0xba, 0x9c, 0x8c, 0x1f, 0x5d, 0x9a, 0x6f, 0x00, 0x03, 0x9d, 0x30, 0x06, 0x40, 0x5a, 0xbc, 0x61, 0x15, 0x20, 0xf2, + 0xf1, 0xc3, 0x0e, 0xd0, 0x97, 0x05, 0x5d, 0xd0, 0x7b, 0x7a, 0xfb, 0x7c, 0x61, 0xe6, 0x34, 0xc9, 0xcf, 0x23, 0xbc, + 0x78, 0xf9, 0xc3, 0x62, 0x39, 0x99, 0x98, 0x09, 0xd1, 0xf1, 0xa3, 0x08, 0x2f, 0x58, 0xb9, 0x84, 0x35, 0xba, 0x3c, + 0x3f, 0x9d, 0x44, 0xd8, 0xa1, 0x61, 0xd6, 0xc9, 0xc6, 0x70, 0xdb, 0xba, 0x9c, 0xa7, 0x51, 0x9e, 0xd3, 0x4e, 0x0e, + 0x77, 0xaf, 0xf2, 0xf6, 0xa7, 0xd2, 0xa2, 0x11, 0x33, 0xf8, 0xe0, 0xd6, 0x10, 0xe6, 0x0b, 0xf0, 0xf8, 0x75, 0xcc, + 0xb2, 0x8c, 0xba, 0xc4, 0x8b, 0x8b, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd5, 0xfd, 0xb8, 0x94, + 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xf6, 0xfe, 0x8d, 0xa1, 0xab, 0xdd, 0x8b, 0x47, 0xb0, 0x00, 0x8a, 0xe6, + 0xf9, 0x6b, 0x7b, 0xb8, 0x5d, 0x8e, 0xcf, 0xce, 0xbb, 0xa7, 0x11, 0xf6, 0x1b, 0x81, 0x5e, 0x76, 0x1e, 0xf6, 0xa0, + 0x84, 0xc8, 0xef, 0x6d, 0x89, 0xc9, 0x19, 0x3d, 0xbb, 0xe8, 0x44, 0xd8, 0x6f, 0x0d, 0x76, 0x39, 0x3e, 0x7f, 0x08, + 0x9f, 0x6a, 0xc6, 0x8a, 0xc2, 0xe0, 0xf7, 0x39, 0xc0, 0x45, 0xf1, 0x17, 0x82, 0xa6, 0x11, 0xed, 0x9c, 0xf7, 0x7a, + 0x39, 0x7c, 0x16, 0x5f, 0x58, 0x99, 0x46, 0x59, 0x07, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, 0x38, 0xc2, 0x06, 0xef, + 0x2e, 0xe8, 0xb9, 0xd9, 0xfb, 0x6e, 0x57, 0x75, 0x2e, 0x3b, 0xb0, 0x61, 0xdd, 0xa6, 0x72, 0x5f, 0x4a, 0xc8, 0x5b, + 0x47, 0x62, 0x69, 0x84, 0x03, 0x04, 0x9d, 0x3c, 0x9c, 0x44, 0xd8, 0xef, 0xb8, 0xb3, 0x8b, 0xcb, 0x1e, 0x90, 0x32, + 0x0d, 0x84, 0x22, 0xef, 0x8d, 0xcf, 0x80, 0x34, 0x69, 0xf6, 0xc6, 0xe2, 0x49, 0x84, 0xf5, 0x73, 0xa5, 0x5f, 0xa7, + 0x51, 0x7e, 0x39, 0x9e, 0xe4, 0x97, 0x11, 0xd6, 0x72, 0x4e, 0xb5, 0x34, 0x14, 0xf0, 0xf4, 0xec, 0x61, 0x84, 0x0d, + 0x9a, 0x77, 0x58, 0x27, 0xef, 0x44, 0xd8, 0x1d, 0x25, 0x8c, 0x5d, 0xf6, 0x60, 0x5a, 0xdf, 0xbf, 0xd4, 0x80, 0xcb, + 0x39, 0x1b, 0x9f, 0x46, 0xb8, 0xa2, 0xf7, 0x86, 0x10, 0xc1, 0x97, 0x9a, 0xcb, 0xcf, 0x8e, 0xf5, 0x00, 0x52, 0xe7, + 0x37, 0x3c, 0x2c, 0xc3, 0x8f, 0xb7, 0x16, 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x6d, 0xf4, 0x33, 0x1a, 0x7b, 0xb6, 0x9d, + 0x93, 0xd5, 0x06, 0x57, 0x41, 0x5e, 0x3f, 0xb3, 0x7b, 0x15, 0x4b, 0x65, 0x38, 0xd9, 0x20, 0x45, 0x29, 0xe4, 0xdd, + 0x1a, 0x9c, 0xe7, 0x2a, 0x08, 0x92, 0x82, 0x74, 0xfa, 0xe2, 0xca, 0x7b, 0xd3, 0xf6, 0x05, 0x84, 0x7e, 0x80, 0xf4, + 0x92, 0x50, 0xa2, 0x21, 0x42, 0x8e, 0x15, 0x26, 0xbd, 0x93, 0x81, 0x91, 0x29, 0xa5, 0x75, 0x5b, 0xa0, 0x84, 0xfa, + 0xd8, 0xf8, 0xb1, 0xc4, 0x0a, 0xa2, 0x47, 0xa1, 0xbe, 0x24, 0x26, 0xd2, 0xf5, 0x2b, 0xa1, 0x63, 0xa9, 0x86, 0xe5, + 0x08, 0x77, 0x2f, 0x10, 0x86, 0x18, 0x12, 0x64, 0x28, 0xaf, 0xaf, 0xbb, 0x17, 0x47, 0x46, 0xe8, 0xbb, 0xbe, 0xbe, + 0xb4, 0x3f, 0xe0, 0xdf, 0x51, 0x1d, 0xb7, 0x1b, 0xc6, 0xf7, 0x91, 0xd5, 0x73, 0x7c, 0x6f, 0xf8, 0xeb, 0x8f, 0x6c, + 0xbd, 0x8e, 0x3f, 0x32, 0x02, 0x33, 0xc6, 0x1f, 0x59, 0x62, 0xee, 0x48, 0xac, 0x87, 0x10, 0x19, 0x82, 0xe6, 0xac, + 0x83, 0x21, 0x9a, 0xbc, 0xe7, 0xbc, 0x3f, 0xb2, 0x21, 0x6f, 0x7a, 0x97, 0xd7, 0x21, 0x9c, 0x8f, 0x8e, 0x56, 0x65, + 0xaa, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xeb, 0x20, 0xfa, 0x67, 0x03, 0x90, 0x52, 0x8c, 0xb2, + 0xc5, 0xf1, 0xd4, 0x3f, 0x82, 0xda, 0x03, 0xb4, 0x93, 0x83, 0x5a, 0xd9, 0x51, 0xe9, 0x2a, 0xf6, 0x2a, 0x30, 0xf6, + 0x26, 0x3a, 0x6d, 0xc7, 0xc9, 0x7f, 0xa2, 0xee, 0x78, 0xd7, 0x10, 0xcb, 0x7e, 0xdc, 0x2b, 0x96, 0xc1, 0x4a, 0x1a, + 0xd1, 0xec, 0xd0, 0xc6, 0x23, 0xd1, 0xc3, 0x87, 0x46, 0x30, 0xab, 0x83, 0xe4, 0xb5, 0x20, 0xa9, 0x0f, 0x52, 0xc8, + 0xa5, 0x91, 0xd2, 0x4a, 0x94, 0xe6, 0x3a, 0x2e, 0x41, 0x43, 0xe9, 0x15, 0x94, 0x55, 0x2c, 0xd7, 0x96, 0x01, 0x88, + 0xb2, 0x32, 0x9a, 0x95, 0xd5, 0xce, 0x41, 0x74, 0x01, 0x4d, 0x98, 0x91, 0x58, 0xa0, 0x01, 0x61, 0x1a, 0x10, 0xae, + 0x32, 0x88, 0x33, 0x2e, 0xfb, 0xcc, 0x64, 0x2b, 0x93, 0xad, 0xaa, 0x6c, 0xe9, 0xb3, 0xad, 0x90, 0x28, 0x4d, 0xb6, + 0xac, 0xb2, 0x41, 0x66, 0xc3, 0xd3, 0x54, 0xe1, 0x71, 0x2a, 0xad, 0xa8, 0x56, 0xcb, 0x56, 0x2f, 0x68, 0xa8, 0xcd, + 0x3d, 0x3a, 0x8a, 0x2b, 0x39, 0xc9, 0xa8, 0x89, 0x1f, 0xac, 0x78, 0x52, 0x1a, 0x19, 0x88, 0x27, 0x53, 0xf7, 0x77, + 0xbc, 0xd9, 0x96, 0x95, 0xca, 0xe9, 0xf8, 0x2b, 0x25, 0xd1, 0x1f, 0x5e, 0x89, 0xfa, 0x91, 0x9b, 0x28, 0x40, 0x57, + 0x24, 0xe9, 0x74, 0x4e, 0xbb, 0xa7, 0x9d, 0xcb, 0x01, 0x3f, 0xee, 0xf6, 0x92, 0x47, 0xbd, 0xd4, 0x28, 0x22, 0x16, + 0xf2, 0x16, 0x14, 0x30, 0x27, 0xbd, 0xe4, 0x0c, 0x1d, 0x77, 0x93, 0xce, 0xf9, 0x79, 0x1b, 0xfe, 0xc1, 0x4f, 0x74, + 0x55, 0xed, 0xac, 0x73, 0x76, 0x3e, 0xe0, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x82, 0x82, 0xe8, 0xc4, 0x54, 0xc2, 0x50, + 0xbf, 0x5e, 0xde, 0xd7, 0x3b, 0x7a, 0x9e, 0x27, 0x3a, 0x96, 0x56, 0x15, 0x07, 0x50, 0xf5, 0x5f, 0x53, 0x03, 0x44, + 0xff, 0x35, 0xae, 0x22, 0xf5, 0xae, 0x4a, 0x10, 0xb5, 0x3f, 0xf2, 0x58, 0xb4, 0xd8, 0x71, 0x6c, 0xf3, 0x35, 0xd4, + 0x6d, 0x43, 0xf4, 0x3c, 0x3c, 0x75, 0xb9, 0x2a, 0xcc, 0x9d, 0x22, 0xd4, 0x56, 0x90, 0x3b, 0x76, 0xb9, 0x32, 0xcc, + 0x1d, 0x23, 0xd4, 0x96, 0x90, 0x4b, 0x53, 0x9e, 0x50, 0xc8, 0xd1, 0x09, 0x6d, 0x1b, 0x48, 0xd6, 0x8b, 0xf2, 0x92, + 0xf9, 0x61, 0xf3, 0x09, 0x2c, 0x8f, 0x21, 0x28, 0x4e, 0x90, 0x16, 0xf0, 0xc2, 0x4a, 0xa5, 0xcd, 0xe9, 0xe0, 0x4a, + 0x8d, 0x03, 0x19, 0x2d, 0xf8, 0xe7, 0x98, 0x99, 0x67, 0x37, 0x3a, 0x83, 0xd3, 0x8b, 0x4e, 0xda, 0x05, 0x57, 0x71, + 0x90, 0xb5, 0x85, 0x95, 0xb5, 0x85, 0x97, 0xb5, 0x85, 0x97, 0xb5, 0x41, 0x80, 0x0f, 0xfa, 0xfe, 0x97, 0x6c, 0x98, + 0xdf, 0xf0, 0xca, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, 0xaa, 0x51, 0xaa, 0x5a, + 0xfd, 0xb9, 0x2a, 0xd3, 0x0e, 0x9e, 0xa6, 0xa0, 0xe5, 0xee, 0x60, 0x6a, 0x36, 0xb7, 0xa7, 0x0a, 0xdb, 0x51, 0x7c, + 0x06, 0x5e, 0x9d, 0x7c, 0x4d, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa6, 0xdc, 0xd2, 0x0c, 0x6e, 0x69, 0x06, 0xb7, 0x34, + 0x03, 0x1a, 0xc1, 0x55, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x86, 0xa7, 0x23, 0x08, 0x62, 0x18, 0x6b, 0x62, + 0x46, 0xbd, 0xd5, 0x79, 0x17, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1a, 0xf3, 0xdf, 0x0d, 0xb4, + 0x4f, 0xe0, 0x45, 0x9d, 0xc7, 0x3a, 0xee, 0x80, 0xe9, 0x4a, 0x54, 0x46, 0x03, 0x43, 0x16, 0x52, 0xa3, 0xb3, 0x71, + 0x26, 0xe9, 0x9f, 0xb7, 0x3c, 0x81, 0x2d, 0x25, 0x08, 0xdf, 0x91, 0xf8, 0xcc, 0xea, 0xd0, 0x04, 0x95, 0xc5, 0xad, + 0x33, 0x97, 0xb3, 0x47, 0x42, 0x1f, 0xcc, 0xe6, 0x7d, 0xcc, 0xab, 0x81, 0x20, 0x25, 0xc4, 0x7c, 0x4c, 0x4d, 0xa2, + 0x8b, 0xda, 0x0c, 0x4e, 0xcc, 0xe4, 0x0b, 0x35, 0x2e, 0x3d, 0xef, 0xed, 0x9f, 0xbf, 0x69, 0xe0, 0xf3, 0x58, 0x4e, + 0xc7, 0xde, 0x55, 0xf8, 0x93, 0x89, 0x6d, 0x44, 0x0e, 0x0f, 0xad, 0x45, 0xbb, 0xf9, 0xda, 0x36, 0x69, 0x37, 0x89, + 0x26, 0x1b, 0x76, 0xa8, 0x5f, 0xa3, 0x7f, 0x79, 0x8f, 0xbd, 0x72, 0x3a, 0x46, 0x01, 0xcd, 0x36, 0x60, 0x95, 0x35, + 0xb0, 0x94, 0xab, 0x57, 0x39, 0x72, 0x42, 0xef, 0x66, 0xcc, 0x9b, 0x72, 0x3a, 0xde, 0xfb, 0xf4, 0x8a, 0xed, 0x71, + 0xf0, 0x82, 0x06, 0x3d, 0x78, 0xd5, 0xf6, 0x8c, 0xdd, 0x7d, 0xab, 0xce, 0xe7, 0xbd, 0x75, 0x54, 0xf1, 0xad, 0x3a, + 0xaf, 0xf6, 0xd5, 0x99, 0xf3, 0xbb, 0xd8, 0xef, 0x1d, 0x1d, 0xa8, 0xb1, 0x8d, 0x99, 0xd4, 0x74, 0x0c, 0xb1, 0xf2, + 0xe1, 0xaf, 0x8d, 0x68, 0xd3, 0xf7, 0x24, 0x1c, 0x56, 0x41, 0x0e, 0x92, 0xf3, 0x94, 0x61, 0x4a, 0x7a, 0xc7, 0xa5, + 0x89, 0x69, 0x23, 0x12, 0xda, 0x56, 0x09, 0xc5, 0x05, 0x89, 0x63, 0x7a, 0x9c, 0x41, 0x64, 0x9e, 0xee, 0x80, 0xa6, + 0x31, 0x6d, 0x65, 0xe8, 0x24, 0xee, 0xb6, 0xe8, 0x71, 0x86, 0x50, 0xab, 0x0b, 0x3a, 0x53, 0x49, 0xba, 0xed, 0x02, + 0x62, 0x75, 0x1a, 0x52, 0x5c, 0x1c, 0x8b, 0xa4, 0x6c, 0xc9, 0x63, 0x95, 0x94, 0xad, 0xe4, 0x1c, 0x8b, 0x64, 0x5a, + 0x25, 0x4f, 0x4d, 0xf2, 0xd4, 0x26, 0x8f, 0xab, 0xe4, 0xb1, 0x49, 0x1e, 0xdb, 0x64, 0x4a, 0xca, 0x63, 0x91, 0xd0, + 0x56, 0xdc, 0x6d, 0x97, 0xe8, 0x18, 0x46, 0xe0, 0x47, 0x4f, 0x44, 0x18, 0x22, 0x7d, 0x63, 0x6c, 0x8c, 0x16, 0xb2, + 0x70, 0x41, 0x4b, 0x6b, 0x20, 0x55, 0x8e, 0x5f, 0x50, 0xe7, 0x75, 0x00, 0x26, 0xac, 0xed, 0x1f, 0x1f, 0x92, 0x6f, + 0x93, 0x15, 0x52, 0x04, 0x8e, 0x6d, 0x60, 0x8b, 0xff, 0xd9, 0xb9, 0xf3, 0x00, 0x54, 0x37, 0xb4, 0x58, 0xcc, 0xe8, + 0x8e, 0xf7, 0x70, 0x39, 0x1d, 0xbb, 0x9d, 0x55, 0x35, 0xc3, 0x68, 0x69, 0x43, 0x5d, 0x37, 0xfd, 0x3c, 0x01, 0xd4, + 0xde, 0xb7, 0x34, 0xa1, 0x46, 0x49, 0x6e, 0x6b, 0x4c, 0x4b, 0x76, 0xaf, 0x32, 0x5a, 0xb0, 0xb8, 0x3e, 0x80, 0xeb, + 0x61, 0x32, 0xf2, 0x0c, 0x3c, 0x02, 0xca, 0xe3, 0xe4, 0xb4, 0xa5, 0x93, 0xe9, 0x71, 0x72, 0xfe, 0xa8, 0xa5, 0x93, + 0xf1, 0x71, 0xd2, 0xed, 0xd6, 0x38, 0x9b, 0x94, 0x44, 0x27, 0x53, 0xa2, 0x41, 0x63, 0x68, 0x1b, 0x95, 0x0b, 0x0a, + 0x26, 0x6e, 0xff, 0xc1, 0x30, 0x5a, 0x6e, 0x18, 0x82, 0x4d, 0x6d, 0xd4, 0xcf, 0x9d, 0x31, 0x84, 0xdd, 0xf4, 0xce, + 0xcf, 0xdb, 0x3a, 0x29, 0xb1, 0xb6, 0x2b, 0xd9, 0xd6, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x6d, 0x9d, 0x8c, 0x6d, 0x53, + 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0x97, 0x2c, 0x80, 0x7c, 0xcf, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, 0xf8, 0xad, 0x72, + 0x6d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xbb, 0x75, 0x93, 0xec, 0xdf, 0x97, 0xad, 0x9a, 0x2d, + 0xa5, 0x6e, 0x16, 0x7c, 0xde, 0xc0, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x7f, 0x52, 0x12, 0x43, 0x6c, 0x3f, 0x73, 0x0a, + 0x71, 0xe2, 0xf5, 0xc8, 0x90, 0xc4, 0x5b, 0xad, 0x0d, 0x8a, 0x83, 0xf3, 0xf6, 0x55, 0x48, 0x55, 0x77, 0x02, 0xfe, + 0x11, 0x12, 0x2d, 0x85, 0x35, 0x09, 0xcd, 0xa3, 0x9a, 0x16, 0xbf, 0x73, 0xda, 0xdd, 0xc6, 0x01, 0x71, 0x74, 0xb4, + 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xed, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, 0x98, 0x07, 0x88, + 0xe2, 0x43, 0x6f, 0x3d, 0x34, 0x14, 0x7e, 0x58, 0xc7, 0x1d, 0x74, 0x39, 0xed, 0x0b, 0x93, 0x61, 0xfa, 0x1a, 0x05, + 0x63, 0x7b, 0x10, 0x4e, 0xa8, 0xb2, 0x95, 0xfc, 0xb7, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, 0x46, 0xff, 0x0c, + 0x2d, 0x93, 0x6b, 0xd8, 0x38, 0x9f, 0xf4, 0xf5, 0xba, 0xf1, 0x3c, 0x91, 0x7d, 0x04, 0x07, 0x1d, 0x1d, 0x71, 0xf5, + 0x02, 0x8c, 0xa9, 0x59, 0xdc, 0x0a, 0x0f, 0xdf, 0xbf, 0x1a, 0xa7, 0xf5, 0x9f, 0xe6, 0x5c, 0x4d, 0x83, 0x83, 0xee, + 0x71, 0x23, 0x7f, 0xef, 0x4a, 0x0c, 0x74, 0xca, 0xdd, 0x5a, 0x3f, 0xa9, 0x4d, 0xd5, 0x77, 0x1e, 0xca, 0x3a, 0x3a, + 0xe2, 0x75, 0xb8, 0xaa, 0xe8, 0xbb, 0x08, 0x0d, 0x8c, 0x0c, 0xf2, 0xa2, 0x90, 0x14, 0x6e, 0x44, 0xe1, 0x8a, 0x21, + 0x6d, 0xf1, 0x13, 0x8d, 0x7f, 0x90, 0xff, 0x8f, 0x1a, 0x39, 0xd6, 0x69, 0x8b, 0x07, 0x02, 0x58, 0xc8, 0x0a, 0xd5, + 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1d, 0xe6, 0x74, 0xb1, 0x28, 0xee, 0xcd, 0x5b, 0x61, 0x01, 0x47, + 0x55, 0x5f, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x04, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xea, 0x72, 0x5b, 0x20, + 0x90, 0xcc, 0x14, 0x91, 0xed, 0x6e, 0x5f, 0x5d, 0x83, 0x5c, 0xd6, 0x6e, 0x23, 0xed, 0x82, 0x97, 0x63, 0x0e, 0x32, + 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, 0x0c, 0x68, 0x84, + 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xd2, 0x77, 0xfc, 0x95, 0x96, 0xca, 0xa1, 0x1a, 0x8d, 0x70, 0x69, + 0x9e, 0xc7, 0xa8, 0xe6, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, 0x33, 0x72, 0x6d, + 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbf, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x63, 0x2e, 0x0a, 0x9d, 0xbc, 0xc9, 0xae, 0x44, + 0xbf, 0xd5, 0x62, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, 0xc5, 0x6c, 0x04, + 0x3e, 0x08, 0x0d, 0xde, 0x48, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xaa, 0x9f, 0x2a, 0x94, + 0x6c, 0x6d, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x57, 0xef, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, 0x9b, 0x60, 0x00, + 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8a, 0x13, 0x60, 0x6f, 0x6e, + 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x82, 0x1c, 0x3d, 0x22, 0xd0, 0xb9, 0xfd, 0x59, 0xd3, 0x85, 0x5a, + 0x26, 0xae, 0xc6, 0xf8, 0xcf, 0xe0, 0x36, 0x6f, 0x18, 0x7d, 0xfa, 0x64, 0x36, 0xf9, 0xa7, 0x4f, 0x11, 0x0e, 0x8d, + 0xeb, 0xa3, 0x80, 0x17, 0x8c, 0x46, 0x55, 0x68, 0x2d, 0xb3, 0xf1, 0xdb, 0xdd, 0xba, 0xb1, 0x8f, 0xb4, 0xc6, 0x3b, + 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x90, 0x03, 0xbc, 0xd9, 0x90, 0x8f, 0xfa, 0x0f, 0x62, 0x85, 0x8e, 0x8e, + 0x1e, 0xc4, 0x12, 0x0d, 0x6e, 0x98, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x21, 0x37, 0xc3, 0x97, 0x01, 0x02, 0xdc, 0xb0, + 0x6d, 0xc9, 0xe6, 0x9d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0x3e, 0x08, 0xa1, + 0xdd, 0x67, 0x84, 0x01, 0x0b, 0x5f, 0xf9, 0x0a, 0xb2, 0x64, 0xce, 0xca, 0x29, 0x2b, 0xd7, 0xeb, 0x8f, 0xd4, 0xfa, + 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xfd, 0x56, 0x8b, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x47, 0xf8, 0xf0, 0x41, 0x5c, 0x22, + 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0xd6, 0x58, 0x97, 0x12, 0x55, 0x8d, 0x14, 0xa4, 0x83, 0x67, 0x24, + 0xab, 0xd6, 0xe8, 0x6a, 0xd6, 0x6f, 0xb5, 0x0a, 0x24, 0xe3, 0x6c, 0x58, 0x8c, 0x30, 0xc7, 0x25, 0x5c, 0xa6, 0xee, + 0xae, 0xc3, 0x82, 0x35, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x49, 0x37, 0xe1, 0xee, 0xa6, 0x01, 0x91, + 0xd8, 0x07, 0x64, 0x61, 0x81, 0xac, 0x3c, 0x90, 0x85, 0x01, 0xb2, 0x42, 0x83, 0x05, 0x04, 0x6d, 0x52, 0x28, 0xdd, + 0xa1, 0xe8, 0xcd, 0xf0, 0xa2, 0xce, 0x75, 0x05, 0x73, 0x13, 0xe1, 0xc2, 0x2d, 0x07, 0xb8, 0xb1, 0xb8, 0xb9, 0x2b, + 0xb2, 0x8a, 0x22, 0x13, 0x69, 0x17, 0xdf, 0x99, 0x3f, 0xc9, 0x1d, 0xbe, 0xb7, 0x3f, 0xee, 0x03, 0x65, 0xd2, 0x87, + 0x86, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xf9, 0xee, 0x9c, 0xb2, 0xe1, + 0x30, 0x44, 0x8b, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xfb, 0xef, 0x11, 0x1a, 0x08, 0x88, 0x66, 0xe4, 0x4e, 0xb6, 0x76, + 0x17, 0xb5, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0xd4, 0x51, 0xd6, 0x1a, + 0xc3, 0x30, 0x83, 0xaa, 0xc3, 0x7f, 0x5c, 0xaf, 0xb6, 0x83, 0x2d, 0x19, 0xa8, 0x0a, 0x13, 0xe9, 0x06, 0xd9, 0x87, + 0xd8, 0x18, 0x61, 0x47, 0x47, 0x6c, 0x28, 0x46, 0xc1, 0xcb, 0x6a, 0xb5, 0x05, 0x89, 0x0e, 0x17, 0x2e, 0xce, 0x20, + 0xda, 0xfd, 0x7a, 0x6d, 0xff, 0x92, 0x5f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0x67, 0xac, 0xd8, 0x2f, 0x8b, 0x25, + 0x5a, 0x7e, 0x00, 0xcb, 0x3e, 0x17, 0xbb, 0x90, 0xbb, 0xa9, 0x76, 0x2b, 0x17, 0x1c, 0xa3, 0x51, 0x08, 0x22, 0x07, + 0xd7, 0x47, 0x1a, 0x5e, 0xe8, 0x30, 0xaf, 0x11, 0x01, 0xb8, 0x50, 0x55, 0x20, 0x57, 0x38, 0x52, 0x12, 0xb0, 0xf4, + 0x36, 0x74, 0x12, 0x7e, 0x34, 0xa9, 0xa4, 0x63, 0x21, 0x01, 0x0a, 0x1c, 0x99, 0xcb, 0x79, 0x13, 0xa8, 0x9f, 0xa1, + 0x3d, 0x44, 0x2e, 0x30, 0xa1, 0x69, 0xca, 0x96, 0x2e, 0xa2, 0x56, 0x34, 0x97, 0x4b, 0xc5, 0x96, 0x0b, 0x38, 0xdf, + 0xab, 0xb4, 0xac, 0xe0, 0xd9, 0xe7, 0x66, 0x0a, 0x18, 0x44, 0xde, 0xe9, 0x39, 0x13, 0xcb, 0xc8, 0xcd, 0xf3, 0xb5, + 0x15, 0xf7, 0xdf, 0xbe, 0xc2, 0x1f, 0x49, 0xef, 0xf8, 0x35, 0xfe, 0x8b, 0x92, 0x8f, 0xad, 0xd7, 0x78, 0xca, 0x89, + 0xe5, 0x0d, 0x92, 0xb7, 0x6f, 0x6e, 0x5e, 0xbd, 0x7f, 0xf5, 0xf1, 0xf9, 0xa7, 0x57, 0xaf, 0x5f, 0xbc, 0x7a, 0xfd, + 0xea, 0xfd, 0xaf, 0xf8, 0x5f, 0x94, 0xbc, 0x3e, 0xe9, 0x5e, 0x76, 0xf0, 0x07, 0xf2, 0xfa, 0xa4, 0x87, 0xef, 0x34, + 0x79, 0x7d, 0x72, 0x86, 0x67, 0x8a, 0xbc, 0x3e, 0xee, 0x9d, 0x9c, 0xe2, 0xa5, 0xb6, 0x4d, 0x16, 0x72, 0xda, 0xed, + 0xe0, 0xbf, 0xdc, 0x17, 0x88, 0xf7, 0x81, 0x1b, 0x0e, 0xdb, 0x32, 0x7e, 0x30, 0x65, 0xe8, 0x58, 0x19, 0x43, 0x94, + 0xab, 0x00, 0x9d, 0x72, 0x15, 0xa2, 0x93, 0x0d, 0x25, 0x0d, 0x36, 0x8c, 0x80, 0x56, 0x9c, 0xb8, 0x76, 0xf8, 0x49, + 0x97, 0x9d, 0x02, 0x7d, 0xe2, 0x95, 0x70, 0x5c, 0xa9, 0x70, 0xba, 0x4e, 0x8b, 0x31, 0x29, 0xa4, 0x2c, 0xe3, 0x25, + 0x30, 0x02, 0x46, 0x6b, 0xc1, 0x4f, 0xaa, 0x98, 0x55, 0xe2, 0x8a, 0x74, 0x07, 0xdd, 0x54, 0x5c, 0x91, 0xde, 0xa0, + 0x07, 0x7f, 0xce, 0x07, 0xe7, 0x69, 0xb7, 0x83, 0x8e, 0x83, 0x71, 0xfc, 0xd0, 0x40, 0xeb, 0xe1, 0x08, 0xbb, 0x2e, + 0xd4, 0x5f, 0xa5, 0xf6, 0x2a, 0x3d, 0xe1, 0xd4, 0xb1, 0xdd, 0xbe, 0xb8, 0x62, 0x46, 0x0f, 0xcb, 0xbf, 0x03, 0xd4, + 0x36, 0x6e, 0x35, 0xd5, 0xc6, 0x71, 0xbf, 0xf8, 0x89, 0x40, 0x8d, 0xc0, 0x38, 0x31, 0x5b, 0x77, 0x10, 0x30, 0x8d, + 0x26, 0x1b, 0xcc, 0x81, 0x12, 0x25, 0x4b, 0xed, 0x83, 0xfb, 0xab, 0xb6, 0x44, 0xc9, 0x42, 0x2e, 0xe2, 0x86, 0xaa, + 0xe1, 0xa7, 0xc0, 0xcc, 0xf1, 0x90, 0xab, 0xd7, 0xf4, 0x75, 0xdc, 0xe0, 0x79, 0x42, 0xd6, 0x2e, 0xdc, 0x16, 0xff, + 0x74, 0x56, 0x14, 0x0d, 0x70, 0x55, 0x80, 0xf5, 0xa3, 0x6a, 0xeb, 0x2b, 0x78, 0xc5, 0x90, 0xb5, 0xf4, 0x35, 0x09, + 0xa8, 0xe7, 0xcf, 0x95, 0x19, 0x57, 0xa5, 0x8c, 0xf6, 0x8a, 0x68, 0x63, 0x16, 0xe4, 0x15, 0xd1, 0x57, 0xca, 0x00, + 0x41, 0x12, 0x3e, 0x14, 0x23, 0x38, 0xf0, 0xed, 0x00, 0xa5, 0xa1, 0x73, 0xa0, 0x56, 0xaa, 0xcd, 0x84, 0xcc, 0xa7, + 0x09, 0xd1, 0x00, 0x9a, 0xa7, 0x5a, 0x05, 0x65, 0x3e, 0xb1, 0x44, 0xc1, 0xd0, 0x7f, 0x0b, 0x37, 0xc0, 0x71, 0x6c, + 0x50, 0x31, 0xb4, 0xab, 0x11, 0xcd, 0xfc, 0xee, 0x65, 0xe7, 0xe4, 0x75, 0x90, 0xbf, 0x54, 0xde, 0xde, 0xe3, 0xcf, + 0x80, 0x92, 0xdb, 0xa0, 0x62, 0x5d, 0xec, 0xe3, 0xc1, 0xf5, 0x43, 0x80, 0x1c, 0x6b, 0x74, 0x62, 0x1e, 0x74, 0xec, + 0x23, 0x7d, 0x4c, 0xba, 0x1d, 0x08, 0xe2, 0xb6, 0x87, 0xf2, 0xfd, 0xbc, 0x05, 0x53, 0x9d, 0xdc, 0xb5, 0x81, 0x56, + 0xc3, 0x1b, 0x4f, 0xf7, 0x6d, 0x9e, 0xdc, 0x63, 0x15, 0xe0, 0x0c, 0x3b, 0x66, 0x2d, 0x71, 0x2c, 0x90, 0x0b, 0x7e, + 0x6b, 0x37, 0x80, 0xa6, 0xa2, 0x67, 0xdf, 0x1a, 0xf4, 0xc6, 0x51, 0x57, 0xed, 0xe4, 0xfc, 0xf8, 0xf5, 0xd1, 0x51, + 0x2c, 0x5b, 0xe4, 0x23, 0xc2, 0x2b, 0x0a, 0x36, 0xdb, 0xe0, 0x7b, 0xc7, 0x2d, 0x13, 0x9f, 0xaa, 0x80, 0x3a, 0x4e, + 0x54, 0xe3, 0x58, 0xab, 0x3b, 0xab, 0x76, 0x83, 0x1f, 0x53, 0x0f, 0xb5, 0x82, 0x34, 0x3b, 0xba, 0x5e, 0x03, 0xca, + 0x0d, 0x47, 0x39, 0xd8, 0x96, 0xad, 0xbf, 0x28, 0xfa, 0xee, 0x63, 0xfb, 0x75, 0x30, 0xe1, 0x86, 0x69, 0xd2, 0xc7, + 0xd6, 0x47, 0xf4, 0xdd, 0xc7, 0xc0, 0xd5, 0x91, 0xd7, 0xec, 0x89, 0xe7, 0x46, 0x7e, 0xb6, 0x5c, 0xe9, 0xcf, 0x20, + 0xd9, 0x97, 0xe4, 0x67, 0xc0, 0x72, 0x4a, 0x7e, 0x8e, 0x65, 0x1b, 0x42, 0x40, 0x92, 0x9f, 0xe3, 0x12, 0x7e, 0x14, + 0xe4, 0xe7, 0x18, 0xb0, 0x1d, 0xcf, 0xcc, 0x8f, 0xb2, 0x02, 0x06, 0xb8, 0xd7, 0x49, 0xeb, 0x65, 0x57, 0xae, 0xd7, + 0xe2, 0xe8, 0x48, 0xda, 0x5f, 0xf4, 0x3a, 0x3b, 0x3a, 0x2a, 0xae, 0x66, 0x75, 0xdf, 0x5c, 0xef, 0xa3, 0x2f, 0x06, + 0xa1, 0x70, 0x60, 0x9a, 0xc6, 0xc3, 0x19, 0x7f, 0xdf, 0xa0, 0xac, 0xd0, 0x40, 0xfb, 0xb4, 0xf7, 0xf0, 0xe2, 0x12, + 0xc3, 0xbf, 0x0f, 0x83, 0x82, 0x3a, 0xf3, 0x13, 0x23, 0x5d, 0xd6, 0xbe, 0xa8, 0xeb, 0x5c, 0x07, 0xf8, 0x8c, 0x19, + 0x6a, 0x8b, 0xa3, 0x23, 0x7e, 0x15, 0xe0, 0x32, 0x66, 0xa8, 0x15, 0x58, 0xec, 0x3d, 0xae, 0xec, 0xc9, 0x0c, 0xd7, + 0x04, 0x8f, 0xfb, 0xf2, 0x61, 0x39, 0xba, 0xd2, 0x8e, 0x9a, 0x84, 0x21, 0xc0, 0x15, 0xe9, 0xb8, 0x4d, 0xd6, 0x17, + 0x6d, 0x75, 0xdd, 0xed, 0x23, 0x49, 0x54, 0x4b, 0x5c, 0x5f, 0x77, 0x31, 0xa8, 0xe4, 0x07, 0x8a, 0xc8, 0x54, 0x10, + 0xef, 0xa6, 0xb8, 0x2a, 0x64, 0xaa, 0xf0, 0x8c, 0xa7, 0xc2, 0xcb, 0xd9, 0x6f, 0xbc, 0xf5, 0xb4, 0x71, 0x1c, 0x35, + 0x3d, 0x33, 0x2c, 0x06, 0xaa, 0x72, 0x78, 0x84, 0x4d, 0xaa, 0x46, 0xf0, 0x76, 0x62, 0x85, 0x79, 0xcc, 0x7a, 0xf9, + 0x31, 0x88, 0x4d, 0xad, 0x5a, 0x5d, 0xc8, 0x84, 0xcf, 0x4d, 0xaa, 0x60, 0xa0, 0xa6, 0xf0, 0x15, 0x84, 0x3d, 0xcc, + 0x6a, 0xc3, 0x6c, 0xdf, 0x30, 0x14, 0x10, 0x50, 0xe0, 0x9a, 0xb0, 0x40, 0x82, 0xe7, 0x59, 0x83, 0x70, 0x34, 0xc9, + 0x85, 0x9d, 0xdc, 0x95, 0x82, 0xee, 0xc4, 0xe8, 0x4a, 0xf7, 0x91, 0x68, 0xb5, 0x1c, 0xb7, 0x7d, 0x2d, 0xcc, 0x20, + 0xda, 0xdd, 0xd1, 0x35, 0xeb, 0x23, 0xd5, 0x6e, 0x57, 0x06, 0x90, 0xd7, 0x9d, 0xf5, 0x5a, 0x5d, 0xf9, 0x46, 0x06, + 0xfe, 0x1c, 0x37, 0x7c, 0x97, 0x17, 0x3c, 0x7f, 0x93, 0x64, 0x18, 0x01, 0x55, 0x05, 0x3e, 0x5b, 0x2e, 0x22, 0x1c, + 0x99, 0x67, 0xf5, 0xe0, 0xaf, 0x79, 0x0e, 0x2d, 0xc2, 0x91, 0x7b, 0x69, 0x2f, 0x1a, 0xd5, 0x83, 0x15, 0x59, 0x15, + 0x24, 0x9e, 0x27, 0x9f, 0x80, 0x71, 0xd0, 0x7f, 0x2a, 0xb4, 0xaa, 0x7f, 0x27, 0x85, 0x0b, 0x97, 0xa2, 0xfc, 0xe3, + 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, 0x8d, 0xd7, 0x27, 0xbb, 0xee, + 0xd1, 0xf3, 0x55, 0xd5, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0xbf, 0xc9, 0xbd, 0x2f, 0x20, 0x47, 0x9f, 0xa4, 0x78, + 0x46, 0x35, 0x8d, 0x5a, 0x0f, 0x8c, 0xe1, 0x9b, 0x95, 0xb3, 0xfa, 0x5f, 0x1b, 0x07, 0xfb, 0x8f, 0xba, 0x87, 0x00, + 0x16, 0x8d, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, 0x3c, 0xfc, 0x18, 0x29, 0xb8, + 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x86, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, 0xe3, 0xef, 0x06, 0x85, 0x5c, + 0xf7, 0x42, 0x35, 0x89, 0x69, 0xdd, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xea, 0xde, 0x8d, 0x84, 0x52, 0xbf, + 0x6b, 0x67, 0xde, 0x26, 0x6d, 0x77, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, 0xbc, 0x87, 0x55, 0xd0, 0xae, + 0x6b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xaf, 0xdc, 0xcb, 0x74, 0x7c, 0x28, 0x47, 0x9b, 0xea, 0x9d, 0xba, + 0x00, 0x0f, 0xea, 0x91, 0xaa, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x0d, 0xfd, 0x10, 0xff, 0x1b, 0x0e, 0xf8, 0x1a, + 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0x7e, 0x2f, 0x43, 0x47, 0xdd, 0xa6, 0x4e, 0xc5, + 0xfa, 0xc2, 0x36, 0x15, 0x2b, 0x55, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, 0x59, 0xf7, 0xe8, 0xd4, 0x63, + 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x17, 0x25, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x0c, 0x5f, 0x55, 0x1e, 0xc2, 0x3d, + 0x61, 0xc5, 0x73, 0x56, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, 0x3a, 0x16, 0x26, 0xb6, 0x84, + 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, + 0x66, 0x41, 0x5f, 0xfb, 0xfa, 0x10, 0xf5, 0x94, 0x07, 0xb1, 0xd1, 0xf7, 0xbe, 0xe7, 0x73, 0x26, 0x97, 0xf0, 0x78, + 0x13, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, 0x0b, 0x40, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x2b, + 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0x83, 0x08, 0xbc, 0x88, 0x40, 0x84, 0x22, 0x24, 0x62, 0x22, 0x8f, + 0x06, 0x91, 0x71, 0xc9, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, 0xdc, 0x11, 0x9e, 0xaa, 0x9a, 0x88, 0x85, 0x35, 0x75, 0x50, + 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa4, 0x57, 0x83, 0x90, 0x66, 0xdb, 0x82, 0xb2, 0xde, 0x52, 0x17, 0x60, 0x49, 0x8c, + 0xe9, 0x2d, 0x4f, 0x3e, 0x01, 0x37, 0xc7, 0x72, 0x57, 0x74, 0xc5, 0x6f, 0x40, 0x3d, 0x9d, 0x96, 0xf8, 0x93, 0x61, + 0xd8, 0xf2, 0x94, 0x6e, 0x08, 0xc7, 0x19, 0x29, 0x13, 0x7a, 0x07, 0xb1, 0x35, 0xe6, 0x5c, 0xa4, 0x05, 0x9e, 0xd3, + 0xbb, 0x74, 0x86, 0xe7, 0x5c, 0x3c, 0xb3, 0xcb, 0x9e, 0xe6, 0x90, 0xe4, 0x3f, 0x96, 0x1b, 0x62, 0x9e, 0x06, 0xfb, + 0xa0, 0x58, 0xf9, 0x04, 0x78, 0x15, 0x15, 0xa3, 0x7e, 0x6e, 0x6c, 0xca, 0xb9, 0xae, 0x8d, 0xd7, 0xdf, 0xe8, 0x98, + 0xe2, 0x0c, 0x17, 0x28, 0x29, 0x24, 0x66, 0x03, 0x91, 0xbe, 0x81, 0xb8, 0xda, 0x19, 0xb6, 0xcf, 0x8a, 0xf1, 0x3b, + 0x56, 0xbc, 0x90, 0xe5, 0x47, 0xb3, 0xe5, 0x0b, 0x04, 0x85, 0xc0, 0x45, 0x45, 0xb4, 0xe1, 0x76, 0x6f, 0x39, 0x90, + 0x75, 0x53, 0xf4, 0xce, 0x36, 0xe5, 0x86, 0x38, 0x83, 0x80, 0xc4, 0xc9, 0x8c, 0xb7, 0xba, 0x98, 0x0d, 0x3a, 0xdf, + 0x68, 0x74, 0x86, 0xaa, 0x92, 0x08, 0xc3, 0x5a, 0xb5, 0x55, 0x2a, 0x89, 0x68, 0x2b, 0x27, 0xe1, 0xad, 0x0c, 0xb0, + 0x53, 0x85, 0x33, 0xb9, 0x14, 0x3a, 0x95, 0x01, 0xde, 0x64, 0xf5, 0xe6, 0x5a, 0xdd, 0x59, 0x88, 0x69, 0x7c, 0x6f, + 0x7f, 0x30, 0xfc, 0xc9, 0xa8, 0xf8, 0xdf, 0x81, 0x61, 0x8f, 0x4a, 0x05, 0xc0, 0x0f, 0x0c, 0x67, 0x01, 0x72, 0x96, + 0x9f, 0xbc, 0x03, 0xf0, 0x59, 0x16, 0xf2, 0x1e, 0x52, 0x99, 0x49, 0xbd, 0x87, 0x54, 0x06, 0xa9, 0xc6, 0xa3, 0xfe, + 0x50, 0xd4, 0xca, 0xa2, 0xb0, 0x41, 0xa2, 0x70, 0xa5, 0x0e, 0x96, 0x44, 0x24, 0xd0, 0xae, 0x11, 0xe5, 0xe6, 0x5c, + 0x40, 0x68, 0x45, 0x68, 0xdc, 0x7e, 0xd3, 0x3b, 0xf8, 0xbe, 0xb7, 0xf9, 0xcc, 0xe7, 0xdf, 0xdb, 0x7c, 0xd3, 0x91, + 0xc7, 0xf8, 0xe6, 0x6d, 0xa7, 0xb1, 0x8c, 0x97, 0x0e, 0x6b, 0x3f, 0x54, 0x0f, 0xd9, 0x74, 0xcc, 0x83, 0xe1, 0xa4, + 0x8b, 0xe7, 0x01, 0x52, 0xb6, 0x6b, 0x1e, 0xae, 0x87, 0xbb, 0x9d, 0xe3, 0x98, 0xb7, 0x49, 0x17, 0xa1, 0x63, 0x27, + 0x5c, 0x89, 0xd8, 0x48, 0x4e, 0xc7, 0x1f, 0x4f, 0xe0, 0xee, 0x65, 0xac, 0xb6, 0x7c, 0xa5, 0x6c, 0xb5, 0x76, 0xb7, + 0x73, 0xcc, 0xf7, 0x56, 0x69, 0x75, 0xf1, 0x9c, 0x91, 0x15, 0x78, 0xa0, 0xd1, 0xd2, 0xaa, 0x1a, 0xc0, 0x65, 0xf5, + 0x95, 0xf8, 0x79, 0x49, 0x73, 0xf3, 0x7d, 0x6c, 0x53, 0xde, 0x2c, 0xb5, 0x4f, 0x6a, 0x73, 0x18, 0x44, 0x0f, 0xb9, + 0x92, 0x41, 0x4e, 0xcc, 0x4f, 0x48, 0x72, 0x8e, 0xae, 0xba, 0x83, 0xe4, 0xfc, 0x98, 0x1f, 0xf3, 0x14, 0x78, 0xd8, + 0xb8, 0xed, 0x2b, 0xb4, 0xbb, 0xbe, 0xce, 0xd3, 0xe5, 0x98, 0x67, 0xae, 0xf9, 0xba, 0x83, 0x2a, 0xd5, 0xce, 0x11, + 0xb2, 0x00, 0xc5, 0x7c, 0x2f, 0x41, 0x76, 0xb3, 0x9b, 0x63, 0x9e, 0x42, 0x3f, 0x50, 0xab, 0x67, 0x6b, 0x55, 0x83, + 0xfb, 0x79, 0x09, 0x08, 0xe6, 0x3b, 0x6a, 0xcc, 0xc5, 0xa6, 0xb7, 0xe3, 0xba, 0xb3, 0x63, 0x5e, 0x8f, 0x30, 0x2c, + 0xb3, 0xdb, 0x9f, 0x9f, 0x5a, 0xdd, 0xe5, 0x71, 0x00, 0x91, 0x9f, 0x97, 0x5c, 0x84, 0x9d, 0x86, 0xdd, 0xba, 0x9c, + 0xb0, 0xd3, 0xe6, 0x2c, 0x83, 0x22, 0xbb, 0xbd, 0xee, 0xcc, 0xb4, 0x39, 0xdb, 0x1b, 0x70, 0x24, 0x84, 0x49, 0x99, + 0x95, 0xce, 0xa4, 0x8a, 0xf9, 0xf1, 0x07, 0xe4, 0x5a, 0x7f, 0xb3, 0xd4, 0x3e, 0xbf, 0x42, 0x04, 0xc8, 0xae, 0xbb, + 0xae, 0xaa, 0x43, 0x1f, 0x55, 0x13, 0xaf, 0x8f, 0x79, 0xb0, 0x72, 0xcf, 0xef, 0x16, 0x32, 0xf5, 0xf8, 0x3a, 0xe8, + 0xa4, 0x3b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, 0xbb, 0xbd, 0x83, 0x92, 0xe1, 0xc4, 0x7d, 0xe9, + 0x0f, 0xcc, 0x5e, 0x37, 0xf0, 0xab, 0xe4, 0x1c, 0xa6, 0xbe, 0xdd, 0xc3, 0x71, 0x0f, 0xfa, 0x30, 0x70, 0xd8, 0x6e, + 0xd0, 0x67, 0xd6, 0x10, 0x79, 0xca, 0x4b, 0x8b, 0x67, 0xd7, 0xa4, 0x3b, 0xe0, 0xa9, 0xdb, 0x4c, 0x46, 0x34, 0xea, + 0xb6, 0x79, 0x30, 0x33, 0xc0, 0x2f, 0x57, 0x36, 0x2c, 0xe2, 0xd7, 0x29, 0x80, 0x92, 0x2f, 0x56, 0xaf, 0x4f, 0x0d, + 0xaf, 0x66, 0xc3, 0xe9, 0x76, 0xba, 0x5f, 0x37, 0xb8, 0xdd, 0xf5, 0xf0, 0x84, 0x87, 0x68, 0x2c, 0x5a, 0xfb, 0x89, + 0xcf, 0x81, 0x03, 0x4a, 0x3a, 0x0f, 0xcf, 0xc1, 0x85, 0xb2, 0x82, 0xe5, 0x6e, 0xb9, 0xf1, 0x4e, 0x39, 0x0b, 0x47, + 0x5b, 0x32, 0xe0, 0x0e, 0xb6, 0x21, 0x0a, 0x1d, 0x1c, 0xf7, 0x70, 0xd2, 0xed, 0xf6, 0xce, 0x71, 0x72, 0x76, 0x0e, + 0x03, 0x6d, 0x25, 0xe7, 0xc7, 0x63, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x4f, 0x20, 0x68, 0x55, 0x28, 0x5e, + 0xf3, 0xe3, 0x38, 0xee, 0x26, 0x0f, 0x3b, 0xdd, 0xf3, 0xcb, 0x16, 0x00, 0xa8, 0xed, 0x3e, 0x5c, 0x8d, 0x37, 0x4b, + 0xdd, 0xac, 0x52, 0x21, 0x7c, 0xb3, 0x5a, 0xcb, 0x57, 0x6b, 0x75, 0x37, 0xf5, 0x14, 0x7c, 0x55, 0x27, 0x9c, 0xdb, + 0x22, 0x5e, 0x69, 0x13, 0x6e, 0x8b, 0xd8, 0x0e, 0x24, 0x06, 0xe9, 0x3c, 0x39, 0xef, 0x9d, 0x23, 0x3b, 0x16, 0xed, + 0xf0, 0xa3, 0xda, 0x27, 0x3b, 0x45, 0x5a, 0x1a, 0x90, 0xa4, 0x9a, 0x9d, 0x5c, 0x82, 0x44, 0xcd, 0xc9, 0x75, 0xb7, + 0x3d, 0x67, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0xac, 0x56, 0xc1, 0x25, 0x05, 0x80, 0xb8, 0x02, 0xe3, 0xa2, 0x87, + 0xe7, 0x83, 0x87, 0xc9, 0xf9, 0x45, 0xcf, 0x12, 0x3d, 0x7e, 0xd5, 0x6b, 0xa4, 0x99, 0xa9, 0x27, 0xe7, 0x26, 0x0d, + 0xba, 0x4e, 0x1e, 0x9e, 0x43, 0x19, 0x97, 0x12, 0x96, 0x82, 0x60, 0x1b, 0x75, 0x31, 0x88, 0xb0, 0x91, 0x36, 0x72, + 0x2f, 0x1a, 0xd9, 0x97, 0x67, 0xa7, 0x0f, 0xcf, 0x43, 0xa8, 0x55, 0xb3, 0x30, 0x0b, 0xed, 0x26, 0xe2, 0x67, 0x07, + 0x4b, 0x8b, 0x8e, 0x93, 0xf3, 0x74, 0x67, 0x82, 0x76, 0xd3, 0x1c, 0x1b, 0x1c, 0x08, 0x14, 0x8e, 0xcf, 0x85, 0xd3, + 0x97, 0x04, 0xf7, 0x63, 0xb5, 0xa1, 0x49, 0xa8, 0x70, 0xf6, 0xf7, 0x94, 0xc1, 0x7b, 0x9a, 0xe1, 0x55, 0xe5, 0x53, + 0x2a, 0xbe, 0x50, 0xf5, 0x96, 0x42, 0x04, 0x11, 0x31, 0x8a, 0x5c, 0x7c, 0xf3, 0x66, 0xee, 0x3f, 0xc1, 0x45, 0x98, + 0x09, 0xb8, 0xd0, 0xf4, 0x4a, 0xd0, 0x9a, 0x17, 0xf8, 0x14, 0x3a, 0xd4, 0x9a, 0x61, 0x0d, 0x78, 0xea, 0x4c, 0x0a, + 0x42, 0xdd, 0xd6, 0x4b, 0xfe, 0xad, 0x72, 0x49, 0x75, 0x95, 0x9d, 0x9c, 0xa3, 0xc4, 0x5d, 0x96, 0x27, 0x5d, 0x94, + 0x04, 0x26, 0x24, 0xee, 0x48, 0x2e, 0x32, 0x32, 0x8c, 0xee, 0x22, 0x1c, 0xdd, 0x47, 0x38, 0xb2, 0x3e, 0xcc, 0xbf, + 0x80, 0x1f, 0x77, 0x84, 0x23, 0xeb, 0xca, 0x1c, 0xe1, 0x48, 0x33, 0x01, 0x81, 0xc5, 0xa2, 0x11, 0x9e, 0x41, 0x69, + 0xe3, 0x59, 0x5d, 0x95, 0x7e, 0xea, 0xbf, 0x2a, 0xd7, 0x6b, 0x9b, 0x12, 0x48, 0x99, 0xb9, 0xd9, 0xa1, 0xf6, 0x61, + 0xec, 0x88, 0x7a, 0x66, 0x3d, 0xc2, 0x20, 0x80, 0xd0, 0x7b, 0xff, 0xb0, 0x5e, 0x1d, 0x93, 0x84, 0x9d, 0xc2, 0x4a, + 0x83, 0x2b, 0x7a, 0x14, 0x9e, 0x61, 0x11, 0x9e, 0x08, 0x5f, 0x18, 0xc4, 0x0a, 0xff, 0xbb, 0x90, 0x72, 0xe1, 0x7f, + 0x6b, 0x59, 0xfd, 0x82, 0xe7, 0x58, 0x9c, 0x45, 0x0b, 0x58, 0x6e, 0xd9, 0x10, 0x48, 0x63, 0xd6, 0x1c, 0xc1, 0xa7, + 0x89, 0x0b, 0x53, 0x07, 0x12, 0xe1, 0x27, 0x23, 0x50, 0x79, 0xf9, 0xf0, 0x93, 0x0d, 0x99, 0x64, 0x3e, 0x21, 0x66, + 0x1a, 0x84, 0x45, 0x96, 0x70, 0xa1, 0x31, 0x2d, 0x99, 0x52, 0x91, 0x8d, 0x25, 0x18, 0x49, 0xe1, 0x1f, 0x87, 0xf4, + 0x29, 0x13, 0x11, 0x99, 0x0e, 0x9b, 0xb3, 0xb5, 0xe2, 0x70, 0x21, 0x4b, 0x95, 0xda, 0x97, 0x62, 0x3c, 0x18, 0x17, + 0xd5, 0x33, 0x8c, 0xe9, 0x2c, 0xdb, 0x60, 0x7b, 0x87, 0x5d, 0x15, 0x72, 0x57, 0xda, 0x61, 0xa9, 0x22, 0xdb, 0x7c, + 0x6d, 0x42, 0xaa, 0x31, 0xa3, 0x60, 0xa2, 0xf5, 0x80, 0xea, 0xc0, 0x1d, 0x50, 0xd8, 0x06, 0xa5, 0x49, 0x57, 0x55, + 0xc9, 0x74, 0x55, 0x2d, 0xc3, 0x59, 0xa7, 0xb3, 0xd9, 0xe0, 0x92, 0x99, 0x40, 0x2e, 0x7b, 0x4b, 0x40, 0xbe, 0x9a, + 0xc9, 0xdb, 0x20, 0x57, 0xa5, 0xd5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, 0x5f, 0xb8, 0xe2, 0x00, + 0x4f, 0x37, 0xbb, 0xb1, 0x94, 0x05, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x3c, 0x67, 0xfb, 0xdb, 0x04, + 0x33, 0xe6, 0xff, 0xac, 0x45, 0x8f, 0x40, 0x96, 0xdd, 0x33, 0xa8, 0x03, 0x8b, 0xb8, 0x86, 0x0e, 0x42, 0x19, 0x7c, + 0x19, 0xe2, 0x66, 0x41, 0xef, 0xe5, 0x52, 0x03, 0x5c, 0x96, 0x5a, 0xbe, 0x75, 0xe1, 0x10, 0x0e, 0x3b, 0xd8, 0x47, + 0x46, 0x58, 0x41, 0xc8, 0x80, 0x0e, 0xb6, 0x11, 0x31, 0x3a, 0xd8, 0x05, 0x2a, 0xe8, 0x60, 0x13, 0x9e, 0xa2, 0xb3, + 0xa9, 0x62, 0x9b, 0xdd, 0x57, 0x4f, 0x6a, 0xd6, 0x9b, 0x60, 0xe2, 0xa4, 0x43, 0x4d, 0x74, 0x70, 0x7b, 0xc8, 0x08, + 0x6f, 0x7d, 0x7f, 0xf3, 0xe6, 0xb5, 0x8b, 0x5c, 0xcd, 0x27, 0xe0, 0xb2, 0xe9, 0x54, 0x63, 0xf7, 0x36, 0xc4, 0x7c, + 0xad, 0x28, 0xb5, 0xc2, 0xa9, 0x09, 0xf6, 0x29, 0x74, 0x91, 0xd8, 0xcb, 0x8b, 0x17, 0xb2, 0x9c, 0x53, 0x7b, 0x63, + 0x84, 0xef, 0x95, 0x7b, 0x7c, 0xde, 0xbc, 0x6f, 0x53, 0x4f, 0xf2, 0xfd, 0xf6, 0x55, 0xc4, 0x24, 0x33, 0xf2, 0x2b, + 0x68, 0x03, 0x4c, 0x65, 0x3f, 0x70, 0x56, 0x12, 0x17, 0xff, 0x3f, 0x20, 0x2f, 0xef, 0x2c, 0x75, 0x89, 0xa2, 0x16, + 0x37, 0xf8, 0xc9, 0xca, 0x5a, 0xc7, 0xc5, 0xcd, 0xfb, 0x91, 0xa4, 0xe3, 0xc4, 0x8b, 0xa8, 0x13, 0x35, 0xdf, 0xde, + 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0x29, 0x24, 0x88, 0x1e, 0xd5, 0x33, 0x7f, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, + 0xdd, 0xf5, 0x74, 0xb6, 0xa8, 0xd5, 0x89, 0xd5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, 0x0e, 0x12, 0x59, + 0xa5, 0x3d, 0xf4, 0xb9, 0xa8, 0x1f, 0x17, 0x57, 0x5d, 0xd6, 0x3e, 0x5b, 0xaf, 0x8b, 0xeb, 0x2e, 0xeb, 0x9e, 0xdb, + 0x67, 0xf7, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x13, 0x9e, 0x45, 0xa0, 0x9d, 0x5d, 0x64, 0x26, 0x9c, 0x82, 0x97, 0xa6, + 0xc9, 0x52, 0xd7, 0x7d, 0x49, 0x30, 0x2e, 0x25, 0x56, 0x8f, 0x5f, 0xa2, 0x41, 0x37, 0xdd, 0x75, 0x95, 0x6e, 0x77, + 0x8f, 0x83, 0x0b, 0x97, 0x12, 0xe1, 0x1e, 0x84, 0x3c, 0x00, 0xfd, 0xee, 0x4a, 0x80, 0x69, 0x10, 0xa0, 0xb2, 0x02, + 0x91, 0x96, 0xcf, 0x97, 0xf3, 0x17, 0x25, 0x35, 0xcb, 0xf0, 0x8c, 0x4f, 0xb9, 0x56, 0x29, 0x05, 0xe9, 0x76, 0x5f, + 0xfa, 0x66, 0xbf, 0x04, 0x95, 0x35, 0xe2, 0xef, 0x26, 0x9a, 0x67, 0x9f, 0x95, 0x5b, 0x38, 0x84, 0xcd, 0xca, 0x0a, + 0x9c, 0xa1, 0x0d, 0x2e, 0xe4, 0x94, 0x96, 0x5c, 0xcf, 0xe6, 0xff, 0xd1, 0xea, 0xb0, 0xa1, 0x1e, 0x99, 0x0b, 0x2b, + 0x00, 0x09, 0x15, 0xf9, 0x7a, 0xcd, 0x4f, 0xbe, 0x7d, 0x9f, 0xe4, 0x7d, 0xc2, 0xbb, 0xb8, 0x87, 0x4f, 0xf1, 0x39, + 0xee, 0x76, 0x70, 0xf7, 0x1c, 0xae, 0xee, 0xb3, 0x62, 0x99, 0x33, 0x15, 0xc3, 0xfb, 0x6b, 0xfa, 0x3a, 0xb9, 0x3c, + 0xae, 0x5f, 0x1d, 0x28, 0x13, 0x87, 0x2e, 0x41, 0xf0, 0x7b, 0x17, 0x35, 0x30, 0x8a, 0xc2, 0x90, 0x75, 0x8b, 0x50, + 0x75, 0x52, 0xe9, 0x17, 0xae, 0x4f, 0x07, 0x60, 0xcf, 0x6d, 0x57, 0xb6, 0x0d, 0x66, 0xdf, 0xf6, 0x67, 0x5a, 0xff, + 0x6c, 0xeb, 0x0a, 0x31, 0x3c, 0xf4, 0x6a, 0xf4, 0x40, 0xd7, 0xa4, 0x7b, 0x74, 0x04, 0x56, 0x47, 0xc1, 0x6c, 0xb8, + 0x8d, 0x7e, 0xc0, 0xdb, 0x8d, 0x34, 0x08, 0x56, 0x00, 0xc6, 0x9d, 0x0f, 0x38, 0x59, 0x59, 0xd8, 0x6a, 0xa0, 0xc2, + 0xac, 0x0c, 0xe3, 0xea, 0x85, 0xa4, 0xc2, 0x08, 0xd1, 0x70, 0x84, 0xb9, 0x60, 0x28, 0x87, 0x1d, 0x2c, 0x27, 0x13, + 0xc5, 0x34, 0x1c, 0x1d, 0x25, 0xfb, 0xc2, 0x4a, 0x65, 0x4e, 0x91, 0x31, 0x9b, 0x72, 0xf1, 0x58, 0xff, 0xc6, 0x4a, + 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, 0x2a, 0x46, 0x38, 0x2b, 0xf8, 0x02, 0xaa, 0x4e, 0x4b, 0x70, 0xfa, 0x81, + 0xbf, 0x3c, 0x4f, 0xc3, 0x36, 0x81, 0x7c, 0xfd, 0x62, 0x63, 0xba, 0xe0, 0xbc, 0xa4, 0xb7, 0x6f, 0xc4, 0x53, 0xd8, + 0x51, 0x8f, 0x4b, 0x46, 0x21, 0x1b, 0x92, 0xde, 0x43, 0x53, 0xf0, 0x01, 0x6d, 0xfe, 0x68, 0x00, 0x97, 0x5e, 0x9a, + 0x0f, 0x5b, 0xd1, 0xc7, 0x6e, 0x4c, 0xaa, 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xeb, 0x4c, 0x1b, 0x85, 0xaa, 0x9a, 0xc2, + 0x06, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x72, 0xaa, 0x66, 0xe9, 0x70, 0x64, 0xfe, 0xbe, 0xb1, 0x25, 0x3b, 0xd8, 0x45, + 0x9c, 0xd9, 0x60, 0xf3, 0x70, 0x6a, 0x50, 0xbe, 0x8b, 0xe1, 0x1e, 0x16, 0x5e, 0xef, 0x6c, 0x90, 0xcf, 0x33, 0x4f, + 0x36, 0xcf, 0x36, 0x1b, 0x33, 0x10, 0x95, 0x82, 0x1e, 0xe8, 0x9d, 0xdf, 0x36, 0x1d, 0xd8, 0x1e, 0xd5, 0xd7, 0x79, + 0x07, 0xcf, 0x39, 0x3c, 0x46, 0xea, 0xdb, 0xbb, 0xd1, 0xa5, 0xfc, 0xec, 0x40, 0xd2, 0x09, 0x52, 0xec, 0x74, 0x82, + 0xce, 0x4e, 0x71, 0x30, 0x72, 0xa0, 0xe7, 0x37, 0x9f, 0x2d, 0xac, 0xfd, 0xef, 0xb7, 0x55, 0x41, 0x13, 0x4f, 0xa7, + 0x9a, 0x50, 0xe6, 0xcf, 0xcf, 0x07, 0x3c, 0xa9, 0x51, 0xc1, 0xbd, 0xe2, 0x05, 0x7b, 0xda, 0x06, 0xfa, 0x9c, 0xd3, + 0x3f, 0xed, 0x0f, 0x1b, 0xc3, 0xa7, 0xd2, 0xb2, 0x65, 0xa5, 0x54, 0xea, 0xb1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, + 0x3f, 0x42, 0x17, 0xc0, 0xeb, 0xe7, 0xa5, 0x5c, 0x18, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, + 0x1c, 0xd4, 0xff, 0x74, 0x80, 0xfd, 0x8d, 0xaa, 0x92, 0x7e, 0xbc, 0x3d, 0x7b, 0xfc, 0x97, 0x12, 0xa2, 0xc6, 0x5b, + 0x3c, 0x4c, 0x1c, 0x3a, 0x55, 0xac, 0x59, 0xf5, 0x73, 0xa7, 0x24, 0x60, 0x58, 0xb3, 0x60, 0xc8, 0xc6, 0xed, 0x14, + 0xb7, 0x99, 0xff, 0x83, 0x0a, 0x06, 0x0b, 0xbe, 0x36, 0x92, 0x9a, 0x65, 0xf1, 0xdb, 0xa7, 0xc9, 0x7f, 0x35, 0x39, + 0xae, 0x43, 0xdd, 0x78, 0x29, 0x74, 0x6c, 0xa2, 0x34, 0x47, 0xe8, 0xe8, 0x68, 0x2b, 0x83, 0x4e, 0x00, 0xf0, 0xc8, + 0xb1, 0x5f, 0x7e, 0xf9, 0x3c, 0x3b, 0x66, 0x34, 0x8f, 0x65, 0x14, 0x32, 0x77, 0x9e, 0x9b, 0xb3, 0x13, 0x79, 0x46, + 0xd5, 0xcc, 0x17, 0x06, 0x38, 0x3e, 0xd9, 0x49, 0x05, 0x7c, 0x8f, 0x36, 0x7b, 0x26, 0xb0, 0xc5, 0x6f, 0xd9, 0x49, + 0xed, 0x2b, 0xe8, 0x17, 0x68, 0xb5, 0x8f, 0xa9, 0xdc, 0x5a, 0xe0, 0x68, 0x7b, 0x22, 0x7b, 0x87, 0xbe, 0x55, 0xa7, + 0x62, 0x3d, 0x5e, 0xed, 0x37, 0xfa, 0x92, 0x62, 0x5f, 0x72, 0x4d, 0xdb, 0xc6, 0xac, 0x7e, 0x2d, 0x58, 0xd7, 0xa6, + 0x4e, 0xf5, 0x35, 0x6f, 0x6d, 0x69, 0x53, 0xd9, 0x25, 0xd9, 0xbb, 0x2d, 0x16, 0x5e, 0x85, 0xb7, 0x5a, 0xd5, 0x45, + 0x28, 0xd8, 0x63, 0x89, 0x51, 0x9f, 0x13, 0xb8, 0x5e, 0x58, 0xaf, 0x63, 0xf8, 0xb3, 0x6f, 0x0c, 0xfb, 0x4c, 0x97, + 0x3e, 0xf0, 0x2d, 0x7e, 0x25, 0x08, 0x58, 0xec, 0xec, 0x20, 0xc1, 0xba, 0xcb, 0x0d, 0x1a, 0x8e, 0x13, 0xff, 0x05, + 0xcf, 0x65, 0x6b, 0xef, 0x72, 0x30, 0xcf, 0xbe, 0xf2, 0xc4, 0x5e, 0xc5, 0x5a, 0x36, 0xa2, 0xdd, 0x6f, 0x49, 0x30, + 0xc4, 0x6e, 0x4a, 0xe7, 0xb8, 0x95, 0x74, 0x51, 0xe4, 0x8a, 0xd5, 0xe8, 0xff, 0xb5, 0x22, 0x99, 0xcd, 0xfc, 0xaf, + 0x8b, 0x8b, 0x0b, 0x97, 0xe2, 0x6c, 0xfe, 0x94, 0xf1, 0x80, 0x33, 0x09, 0xec, 0x0b, 0xcf, 0x98, 0xd1, 0x21, 0xbf, + 0x83, 0xa1, 0x10, 0x41, 0xae, 0x85, 0x63, 0x97, 0xe0, 0xb5, 0x47, 0xa0, 0x3c, 0xc0, 0xfe, 0x3d, 0xdb, 0x2a, 0xe7, + 0x9f, 0x8b, 0xf2, 0xe1, 0x94, 0xab, 0x06, 0xd9, 0x17, 0xf3, 0x39, 0xb4, 0x66, 0x32, 0xf0, 0x42, 0x42, 0x84, 0xed, + 0x6f, 0xc3, 0xd2, 0x3a, 0x4b, 0x19, 0x1c, 0x69, 0xb9, 0xcc, 0x66, 0x56, 0xf3, 0xef, 0x3e, 0x4c, 0x59, 0xf7, 0xd4, + 0x10, 0x44, 0xee, 0x22, 0x2b, 0x17, 0x15, 0x34, 0xfa, 0x47, 0x15, 0x00, 0xf4, 0xe0, 0x35, 0x5b, 0xb2, 0x7f, 0xe0, + 0x83, 0x3a, 0x05, 0x3e, 0x1e, 0x97, 0x9c, 0x16, 0xff, 0xc0, 0x07, 0x75, 0x20, 0x50, 0x70, 0x85, 0x34, 0xb1, 0x34, + 0xb1, 0x79, 0x56, 0x3b, 0x8d, 0x04, 0x50, 0xd0, 0x22, 0x32, 0x07, 0xd9, 0x4b, 0x17, 0xa3, 0x31, 0xe9, 0x61, 0x17, + 0x1c, 0xcc, 0x46, 0x84, 0xb5, 0x81, 0xd4, 0x21, 0x6e, 0x5d, 0x35, 0x1b, 0xf3, 0xf5, 0x64, 0x6b, 0x41, 0x8c, 0x32, + 0x99, 0x5c, 0xbf, 0xe4, 0xf1, 0xce, 0x62, 0xa1, 0xb0, 0x5a, 0xb0, 0x40, 0x8d, 0x2a, 0x75, 0x7a, 0x58, 0x7c, 0xb7, + 0x60, 0x16, 0x14, 0x31, 0x5b, 0xef, 0xf1, 0x1d, 0x57, 0x04, 0xa4, 0x64, 0x97, 0x04, 0x2f, 0xa3, 0x1b, 0x4c, 0x25, + 0xab, 0xb9, 0xcc, 0x99, 0x25, 0xf4, 0x4c, 0xe9, 0x08, 0x9b, 0x3c, 0x05, 0x91, 0xc4, 0x0e, 0x3b, 0xd8, 0xb1, 0x46, + 0xaf, 0x84, 0x17, 0x52, 0xe0, 0x5c, 0x35, 0x4d, 0xcc, 0x29, 0x37, 0xd1, 0xc5, 0x1e, 0xab, 0x05, 0xcb, 0xb4, 0x45, + 0x80, 0x43, 0x87, 0x86, 0x52, 0xbc, 0x34, 0xa0, 0x30, 0x4f, 0x7a, 0xbb, 0x94, 0xa7, 0xb0, 0x78, 0x41, 0x0a, 0x10, + 0x35, 0x2e, 0xa6, 0x55, 0x9d, 0x45, 0xb1, 0x9c, 0x72, 0x51, 0x23, 0x43, 0xc9, 0xd4, 0x42, 0x0a, 0x78, 0x51, 0xa3, + 0x2a, 0x62, 0xe8, 0x50, 0x03, 0xdf, 0x2d, 0x09, 0xab, 0xea, 0x98, 0x63, 0x8a, 0x8b, 0xba, 0x06, 0x30, 0x17, 0x8f, + 0x8d, 0x80, 0xe8, 0xc3, 0xcb, 0xbe, 0x11, 0xef, 0xe5, 0xa2, 0xce, 0xf7, 0x34, 0xce, 0x07, 0xae, 0x77, 0x76, 0xc3, + 0x68, 0x63, 0x1e, 0xbd, 0x0a, 0xb6, 0xef, 0x07, 0x5e, 0x3f, 0x04, 0xb7, 0x31, 0xcf, 0x66, 0x55, 0x59, 0x63, 0x56, + 0xbd, 0x11, 0x51, 0xb7, 0xd7, 0xac, 0x2a, 0x85, 0xad, 0x08, 0x50, 0x29, 0x79, 0xbe, 0x93, 0xff, 0x4a, 0xdb, 0x7c, + 0x7b, 0x0e, 0x55, 0xe1, 0x81, 0x3c, 0x19, 0xaa, 0x7b, 0xc0, 0x65, 0xf5, 0x21, 0x80, 0xc5, 0x8f, 0x4c, 0xfc, 0xe0, + 0x7d, 0x17, 0xc8, 0x9c, 0xa9, 0x58, 0xe2, 0xd5, 0x90, 0x8e, 0x52, 0x2b, 0x0f, 0xa5, 0x12, 0x6c, 0x7b, 0x6e, 0x4b, + 0xae, 0x7d, 0xa0, 0x62, 0x3c, 0x64, 0xa3, 0x74, 0xd5, 0x0c, 0x66, 0x6c, 0xc3, 0x29, 0x7b, 0x73, 0x4e, 0x13, 0xfd, + 0x97, 0x8e, 0x70, 0x41, 0xc0, 0xf6, 0xd8, 0xb3, 0xa7, 0x0f, 0xe2, 0x0c, 0x0d, 0x9a, 0x1c, 0xfe, 0x6a, 0x83, 0x0b, + 0x9c, 0xa1, 0xf4, 0x71, 0x0c, 0x17, 0x58, 0x1b, 0x0c, 0xe0, 0xcb, 0x2c, 0xa9, 0x02, 0x8f, 0xd4, 0xcc, 0x48, 0xac, + 0xee, 0x22, 0x10, 0xad, 0x74, 0x78, 0x3b, 0xce, 0x7c, 0x38, 0x70, 0xc3, 0xbd, 0xbe, 0x30, 0xc2, 0xe1, 0x3c, 0x8b, + 0x1b, 0xe7, 0x0c, 0x27, 0xd7, 0x87, 0xbc, 0x71, 0x62, 0x82, 0xb5, 0x77, 0x78, 0xaa, 0x80, 0x1e, 0x0d, 0x4e, 0x15, + 0x4b, 0x43, 0x20, 0x66, 0x02, 0x78, 0x33, 0x87, 0x47, 0x5b, 0x80, 0xf3, 0xd1, 0x06, 0x07, 0x5f, 0x69, 0xa3, 0xab, + 0x6d, 0x25, 0xca, 0x66, 0x83, 0x87, 0x79, 0x86, 0x97, 0x19, 0x9e, 0x66, 0xa3, 0xf0, 0xb8, 0xc9, 0x42, 0x93, 0xae, + 0xf5, 0xfa, 0x95, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0x68, 0x00, 0x08, 0x9f, 0x42, 0x16, 0xd0, 0x92, 0x81, + 0xfb, 0xdb, 0xb2, 0xaf, 0x85, 0xa3, 0x56, 0xcc, 0x13, 0x4b, 0x46, 0x06, 0xfe, 0x47, 0x95, 0x65, 0x5b, 0x6b, 0x45, + 0x8b, 0xbb, 0x83, 0xa8, 0xe5, 0xdb, 0xab, 0xcf, 0x97, 0x71, 0x65, 0xb6, 0x03, 0x88, 0x62, 0x8d, 0x93, 0x74, 0xb0, + 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcd, 0x03, 0x7a, 0xb1, 0x42, 0x89, 0xe1, + 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x86, 0xc8, 0xfd, 0x29, 0xab, 0x2d, + 0x83, 0x04, 0x11, 0x46, 0xe4, 0xb7, 0xd7, 0xa5, 0xc2, 0x3e, 0xd1, 0x67, 0xff, 0x18, 0x5f, 0x40, 0xb8, 0x79, 0x9b, + 0xd2, 0x72, 0x4c, 0xa7, 0xc0, 0xc6, 0x42, 0x1c, 0xc2, 0x9d, 0x84, 0xf5, 0x7a, 0x38, 0xea, 0x0b, 0x43, 0x9e, 0xdd, + 0x03, 0x82, 0x55, 0x43, 0xfb, 0x1b, 0x80, 0xab, 0x6e, 0x4b, 0xcd, 0xb5, 0xd1, 0xfd, 0x50, 0xf3, 0xc6, 0x19, 0x77, + 0x49, 0xee, 0x99, 0x92, 0xfa, 0x25, 0xf2, 0x86, 0x05, 0xb8, 0x09, 0x5d, 0x85, 0x73, 0xbc, 0xb4, 0x36, 0x9c, 0xe6, + 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x66, 0x23, 0x9c, 0xfb, 0x70, 0xe7, 0x87, 0xef, 0xe2, + 0x1c, 0xa1, 0x92, 0x18, 0x98, 0x5a, 0x97, 0xed, 0xbc, 0xb6, 0xdb, 0x37, 0x99, 0x86, 0x61, 0x30, 0x46, 0xcc, 0x79, + 0x68, 0xc4, 0x5c, 0xb4, 0x5a, 0x68, 0x49, 0x72, 0x30, 0x62, 0x5e, 0x06, 0xad, 0x2d, 0xed, 0x63, 0xa7, 0x41, 0x7b, + 0x4b, 0x84, 0xfa, 0x1c, 0x68, 0x9a, 0x86, 0x67, 0x4d, 0xea, 0x67, 0xe5, 0xfd, 0x23, 0x5b, 0x27, 0x3d, 0x50, 0x24, + 0x4c, 0xae, 0xfd, 0x24, 0xac, 0x6b, 0xb8, 0x1d, 0xf7, 0xc4, 0x8c, 0xdb, 0xd9, 0x36, 0xa8, 0xa1, 0x1c, 0x66, 0xa3, + 0x51, 0x5f, 0x7a, 0x2b, 0x89, 0x0e, 0x9e, 0xd4, 0x0f, 0xa1, 0xd4, 0x8b, 0xf7, 0x45, 0x6f, 0x5f, 0x79, 0x73, 0xff, + 0xbe, 0xea, 0xf6, 0x79, 0x0c, 0x1c, 0xd0, 0x21, 0xdc, 0x0f, 0xd5, 0xf1, 0xc1, 0x4e, 0x7a, 0x10, 0x05, 0x2d, 0xed, + 0x34, 0x04, 0x52, 0x6b, 0x66, 0x17, 0xeb, 0xb6, 0x42, 0xc7, 0x02, 0xc2, 0x90, 0xa9, 0xba, 0xbb, 0x3b, 0x15, 0xa8, + 0x86, 0x38, 0x9c, 0xfa, 0x4f, 0xad, 0x11, 0x6b, 0x1c, 0xf5, 0xf2, 0xc8, 0x18, 0x49, 0xda, 0xe5, 0x83, 0xb7, 0x8f, + 0xc0, 0x4a, 0xc0, 0xc7, 0xa0, 0x36, 0x49, 0xc6, 0x90, 0xe0, 0x1d, 0xcb, 0xb4, 0xe1, 0x43, 0xb8, 0x43, 0x50, 0x9e, + 0xd8, 0xa0, 0xb4, 0xae, 0x92, 0x85, 0x5c, 0xdd, 0xe5, 0x7d, 0x80, 0x9e, 0x77, 0xd5, 0x6f, 0x6c, 0x38, 0xb2, 0x60, + 0x60, 0xd9, 0xce, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x23, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0x78, 0xdd, 0x37, 0xb0, 0x41, + 0xf1, 0x02, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, 0x49, 0xbc, 0x58, 0xaf, + 0x3b, 0xe8, 0xf8, 0x5f, 0xe6, 0x49, 0xea, 0x49, 0xa5, 0x70, 0x9f, 0xd4, 0x0a, 0x77, 0xb0, 0x04, 0x24, 0x93, 0x40, + 0xd7, 0x8e, 0x65, 0xa8, 0x46, 0x87, 0x68, 0xe9, 0xaf, 0x20, 0x76, 0xb6, 0x3b, 0x96, 0x40, 0xcf, 0xbe, 0x53, 0xc0, + 0xea, 0xda, 0xab, 0x12, 0xc8, 0x08, 0xee, 0x7e, 0x13, 0x18, 0x15, 0xa2, 0xf1, 0xf9, 0x33, 0xaf, 0x5a, 0xf0, 0xc4, + 0xf9, 0x73, 0xcd, 0x0d, 0xeb, 0x5e, 0xd2, 0x5b, 0xd3, 0x7c, 0x3c, 0xc1, 0xed, 0x89, 0x05, 0xe7, 0x49, 0x0f, 0x7e, + 0x5a, 0x88, 0x9e, 0xf4, 0xb0, 0x4b, 0xc5, 0x93, 0x0a, 0xc8, 0x21, 0x7a, 0x3a, 0x03, 0x29, 0x60, 0xa5, 0x63, 0xab, + 0x45, 0x9a, 0xa2, 0xf5, 0x7a, 0x7a, 0x45, 0x3a, 0x08, 0xad, 0xd4, 0x2d, 0xd7, 0xd9, 0x0c, 0x7c, 0xa4, 0x41, 0x31, + 0xf0, 0x96, 0xea, 0x59, 0x8c, 0xf0, 0x04, 0xad, 0x72, 0x36, 0xa1, 0xcb, 0x42, 0xa7, 0x6a, 0xc0, 0x13, 0x1b, 0xb8, + 0x97, 0xd9, 0x48, 0x70, 0x27, 0x3d, 0x3c, 0x35, 0xfc, 0xe5, 0x47, 0x63, 0x0e, 0x52, 0x66, 0x26, 0x79, 0x6a, 0x12, + 0x30, 0x4f, 0xb2, 0x42, 0x2a, 0x66, 0x9b, 0xe9, 0x5b, 0xdb, 0x72, 0x08, 0x49, 0x1e, 0xe9, 0x92, 0x1b, 0x2b, 0xca, + 0x28, 0x9d, 0x11, 0x35, 0x50, 0x27, 0xbd, 0x74, 0x8a, 0x79, 0x02, 0x9c, 0xde, 0x7b, 0x19, 0xb3, 0x56, 0x75, 0x2b, + 0x3a, 0x47, 0xc7, 0x33, 0x2c, 0xea, 0x4b, 0xd4, 0x39, 0x3a, 0x9e, 0x22, 0x3c, 0x6f, 0x91, 0x99, 0x02, 0x8f, 0x61, + 0x2e, 0xfe, 0x3f, 0x29, 0xff, 0xd5, 0x61, 0x43, 0x88, 0xe9, 0x77, 0xb0, 0x53, 0x58, 0x1e, 0xa5, 0x05, 0x01, 0xaf, + 0xc5, 0xee, 0x05, 0xce, 0xc8, 0xb4, 0x5d, 0xf8, 0x80, 0x7b, 0xa6, 0x95, 0xd6, 0x9d, 0x46, 0xc7, 0x19, 0xce, 0xb7, + 0x93, 0x62, 0x33, 0xd7, 0x76, 0x91, 0x66, 0x70, 0xbe, 0xd7, 0xa3, 0x70, 0xe5, 0x97, 0xdb, 0x49, 0x61, 0x79, 0x07, + 0xdc, 0x76, 0x8e, 0x45, 0x9b, 0xe2, 0x02, 0xcf, 0xdb, 0xaf, 0xf1, 0xbc, 0xfd, 0xa1, 0xca, 0x68, 0x2d, 0xb1, 0x80, + 0xe0, 0x7d, 0x90, 0x88, 0xe7, 0x75, 0x72, 0x8e, 0x45, 0xcb, 0x94, 0xc7, 0xf3, 0x56, 0x5d, 0xba, 0xbd, 0xc4, 0xa2, + 0x65, 0x4a, 0xb7, 0x3e, 0xe0, 0x79, 0xeb, 0xf5, 0xbf, 0x99, 0x74, 0x94, 0x02, 0xba, 0x2c, 0xd0, 0x2a, 0xb3, 0x43, + 0xbc, 0xf9, 0xf9, 0xdd, 0xfb, 0xee, 0xa7, 0xde, 0xf1, 0x14, 0xfb, 0xf5, 0xcb, 0x0c, 0x8e, 0x65, 0x3a, 0x66, 0x6d, + 0x80, 0x68, 0x86, 0x7b, 0xc7, 0x33, 0xdc, 0x3b, 0xce, 0x5c, 0x53, 0x9b, 0x79, 0x8b, 0xdc, 0xe9, 0x10, 0x8a, 0x3a, + 0x4a, 0x43, 0xf8, 0xf8, 0xc9, 0xa6, 0x53, 0xd4, 0x00, 0x25, 0x3a, 0x9e, 0x36, 0x40, 0x05, 0xdf, 0xcb, 0xc6, 0x77, + 0x5d, 0xaf, 0xc6, 0x20, 0x0b, 0x25, 0x14, 0xae, 0xb9, 0x01, 0x4f, 0x23, 0xc5, 0x40, 0x26, 0x4c, 0xb1, 0x40, 0xf9, + 0x06, 0x28, 0x8c, 0xf2, 0xc4, 0x0c, 0x3d, 0x98, 0x8e, 0x49, 0xfc, 0xff, 0x79, 0x32, 0xd5, 0xd0, 0xab, 0x2d, 0xb3, + 0x33, 0x3d, 0x37, 0x99, 0x70, 0xf8, 0xc0, 0x63, 0xfd, 0x6f, 0x3b, 0x50, 0x6c, 0x40, 0x8a, 0xff, 0x37, 0x1d, 0x5d, + 0x08, 0x46, 0xc8, 0x8a, 0xd2, 0xd2, 0x21, 0xfe, 0xb7, 0x87, 0x15, 0x74, 0x5f, 0xee, 0x74, 0x5f, 0x9a, 0xee, 0xc3, + 0xa6, 0x8d, 0x2a, 0x27, 0xad, 0x2b, 0x59, 0xf2, 0xdf, 0xa4, 0x5b, 0x3b, 0xa0, 0x11, 0x0d, 0x7a, 0x36, 0x0d, 0x1b, + 0x3c, 0xec, 0xa6, 0x7b, 0x90, 0x79, 0xc3, 0xed, 0x0b, 0xa9, 0x70, 0xf8, 0x06, 0x77, 0xaa, 0xd7, 0x1d, 0xf0, 0xde, + 0x54, 0x46, 0x5f, 0x19, 0x87, 0x96, 0x83, 0x74, 0xdb, 0x94, 0xdb, 0x18, 0x4b, 0x27, 0xe7, 0xd8, 0xb8, 0x22, 0x42, + 0xa5, 0xbb, 0x6b, 0x50, 0x8a, 0x4f, 0x74, 0x9b, 0x99, 0xaf, 0x2b, 0x9d, 0x98, 0x4b, 0xa8, 0x96, 0xf9, 0xbc, 0xbf, + 0xd6, 0x89, 0x96, 0x0b, 0x9b, 0x77, 0x7f, 0x05, 0x7d, 0x82, 0x86, 0xb5, 0x15, 0xd8, 0xed, 0x73, 0x67, 0x07, 0x19, + 0x1c, 0x82, 0xe1, 0x01, 0xe4, 0x48, 0x8b, 0xed, 0x03, 0x9b, 0xd6, 0xb0, 0xeb, 0xa2, 0x5d, 0x25, 0xda, 0x56, 0xdb, + 0x26, 0xd7, 0xee, 0x61, 0xbe, 0x08, 0x79, 0x0a, 0x51, 0x5a, 0xfd, 0xf8, 0x1e, 0x76, 0xe3, 0x4b, 0x83, 0x91, 0x68, + 0x2a, 0x99, 0x2a, 0xe8, 0x27, 0x77, 0x98, 0x25, 0xf7, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0x97, 0x3f, 0xaa, + 0x25, 0x39, 0xb0, 0xec, 0x6f, 0xb1, 0xe4, 0x0e, 0xcc, 0x13, 0xab, 0x6a, 0x12, 0xeb, 0xe4, 0x3e, 0x58, 0x44, 0x69, + 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0x61, 0x50, 0x95, 0xd2, 0xae, 0xb3, 0xb4, + 0xd1, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9e, 0xc6, 0x6d, 0xc0, 0x35, 0xfd, 0xbb, 0x49, 0x24, 0x63, 0xf6, 0x37, + 0x67, 0xe5, 0xd3, 0x65, 0x69, 0x30, 0x4d, 0x0c, 0x74, 0x92, 0x2d, 0xba, 0x60, 0xaa, 0x97, 0x2d, 0x7a, 0x77, 0xd8, + 0x7d, 0xdf, 0xdb, 0xef, 0x7b, 0x2c, 0x06, 0xcc, 0x64, 0xa4, 0xcc, 0x14, 0xf3, 0xdf, 0xf7, 0xf6, 0xfb, 0x1e, 0xef, + 0x0e, 0xe6, 0xb3, 0xbf, 0x50, 0xac, 0xd8, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x1a, 0x59, 0x26, 0x08, 0x6c, + 0x23, 0x01, 0xe2, 0x7c, 0xbe, 0x8a, 0x6b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xeb, 0x54, 0xe0, 0x31, 0x41, + 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd2, 0x93, 0x24, 0xc0, 0xab, 0x1a, 0x95, 0xb7, + 0x29, 0x52, 0x7d, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x42, 0x15, 0x03, 0x58, 0x55, 0x25, 0x7d, 0x02, 0x69, 0xe6, 0x87, + 0x9e, 0x9a, 0xdb, 0xc8, 0x63, 0xdf, 0xf9, 0xfd, 0xcc, 0xf4, 0xac, 0x94, 0xcb, 0xe9, 0x0c, 0x7c, 0x68, 0x81, 0x65, + 0x28, 0x4d, 0xbd, 0xda, 0xd6, 0xbf, 0x21, 0xb9, 0x09, 0xa0, 0x70, 0xba, 0x2d, 0x13, 0x9a, 0xe9, 0x25, 0x2d, 0x8c, + 0x25, 0x29, 0x17, 0xd3, 0x27, 0xf2, 0xee, 0x47, 0xc0, 0x6e, 0x4a, 0x74, 0x6b, 0x4f, 0xde, 0x3b, 0xd8, 0x01, 0x38, + 0x23, 0x6c, 0x5f, 0xc5, 0xc7, 0x0a, 0x74, 0xfe, 0xb8, 0x20, 0x6c, 0x5f, 0xd5, 0x67, 0xcc, 0x66, 0xcf, 0xc8, 0xd6, + 0x70, 0x07, 0x71, 0xd6, 0x2a, 0xd0, 0x49, 0x2f, 0x2d, 0xfa, 0x9e, 0x18, 0x58, 0x80, 0x06, 0xc0, 0xdd, 0xd9, 0x9e, + 0xd5, 0xdd, 0x0d, 0x01, 0xbd, 0x4b, 0x26, 0xed, 0x75, 0xb9, 0x49, 0x59, 0xaf, 0x7b, 0x35, 0x15, 0x2c, 0xf1, 0x2c, + 0xd8, 0x0b, 0xd4, 0x7e, 0xed, 0xa1, 0x38, 0x3f, 0x65, 0xdb, 0xa6, 0xe7, 0x55, 0xdf, 0xfd, 0x3d, 0x8b, 0x8c, 0x6d, + 0xda, 0xbb, 0x3d, 0x44, 0xc2, 0x72, 0xc2, 0x3a, 0xe0, 0x84, 0xeb, 0xda, 0x01, 0x01, 0xfa, 0x14, 0x88, 0xdc, 0x58, + 0x92, 0xd5, 0xa6, 0x36, 0xba, 0x0f, 0xfc, 0x6e, 0x29, 0x91, 0x6e, 0xb4, 0x15, 0xc1, 0xf4, 0x09, 0x46, 0x4d, 0x67, + 0x9e, 0xa6, 0x6e, 0xbc, 0xba, 0xbc, 0x2d, 0xda, 0xfa, 0x37, 0xa0, 0xb1, 0xd9, 0x1e, 0x26, 0x86, 0x32, 0x88, 0x81, + 0xde, 0x47, 0xbc, 0xdf, 0x6a, 0x65, 0x08, 0x14, 0x32, 0xd9, 0x08, 0xcb, 0xc4, 0x6b, 0xd1, 0x8f, 0x8e, 0x0c, 0x3c, + 0xea, 0x04, 0x84, 0x29, 0x08, 0x21, 0x61, 0xd7, 0x06, 0x61, 0xc3, 0xe5, 0x6a, 0xe4, 0xc2, 0x46, 0x6a, 0x0c, 0x1d, + 0xfc, 0xbf, 0xc2, 0x65, 0x6b, 0x66, 0x56, 0x8b, 0x62, 0x70, 0xb3, 0x30, 0x60, 0x91, 0x20, 0x3d, 0xda, 0x6c, 0x0f, + 0xc5, 0xfd, 0xb9, 0xd8, 0x6c, 0x08, 0x48, 0x2c, 0x60, 0x82, 0xa2, 0xe5, 0xdc, 0x18, 0x63, 0x95, 0xd4, 0x5a, 0xd6, + 0x86, 0xc4, 0x1c, 0x04, 0x8c, 0x0e, 0xd7, 0x7d, 0x75, 0x97, 0x32, 0x7c, 0x9f, 0x0a, 0x7c, 0x0b, 0x9e, 0x34, 0xa9, + 0xc4, 0xee, 0xf1, 0x82, 0x72, 0x43, 0x74, 0xdf, 0xb3, 0xb7, 0x25, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xff, + 0xea, 0x82, 0xef, 0x16, 0x7e, 0x0d, 0xd6, 0xcf, 0xc1, 0x49, 0x8a, 0x45, 0x4b, 0xb6, 0x4b, 0x77, 0x64, 0x40, 0xb9, + 0x9a, 0x5f, 0x0e, 0x53, 0x77, 0x8a, 0xe1, 0xc6, 0xc7, 0x6b, 0xfc, 0x61, 0xab, 0xdd, 0x96, 0xaa, 0x8a, 0xdb, 0xbd, + 0x29, 0x5a, 0xb2, 0x6e, 0x7a, 0x4f, 0xe6, 0x56, 0x4a, 0xf3, 0xeb, 0x03, 0xee, 0xec, 0xb4, 0xef, 0xa7, 0xf9, 0xce, + 0xa3, 0x73, 0xdd, 0xb4, 0x4f, 0x6d, 0x14, 0xc1, 0xc1, 0xcf, 0x0e, 0x6e, 0xef, 0x0c, 0x38, 0x80, 0x9f, 0xbf, 0xa3, + 0x79, 0x93, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc7, 0xbf, 0xe7, 0xad, 0x78, 0x90, 0xfe, 0x9e, 0xfc, 0x9e, 0xb7, + 0xd0, 0x00, 0xc5, 0x8b, 0xbb, 0x35, 0x9b, 0xaf, 0x21, 0xd8, 0xda, 0x83, 0x13, 0xfc, 0x20, 0x2c, 0xc9, 0x35, 0x2d, + 0x78, 0xb6, 0x76, 0x0f, 0x02, 0xae, 0xdd, 0xab, 0x44, 0x6b, 0xf3, 0xc6, 0xd5, 0x3a, 0x96, 0xe3, 0x02, 0x02, 0x0b, + 0xc7, 0x07, 0xed, 0xc1, 0xb0, 0xd3, 0x7e, 0x34, 0xb2, 0xff, 0x9a, 0x08, 0xf7, 0xa8, 0x11, 0xb1, 0xed, 0xed, 0xd6, + 0xd6, 0x8f, 0xc1, 0xb0, 0x03, 0x42, 0x81, 0x83, 0x5c, 0xfa, 0x26, 0x43, 0xd6, 0xf7, 0x64, 0xbd, 0x66, 0x2e, 0x9a, + 0xb5, 0xd3, 0xe0, 0x57, 0xb1, 0x99, 0x8e, 0xbb, 0x49, 0xaf, 0xef, 0xc5, 0x58, 0xd2, 0x82, 0x48, 0xd3, 0x98, 0x41, + 0x20, 0xa9, 0x95, 0xe1, 0xb0, 0x16, 0x77, 0x51, 0x5a, 0xdf, 0x1f, 0x41, 0xca, 0x77, 0x51, 0xca, 0x4f, 0x08, 0x04, + 0xd0, 0xb6, 0xcc, 0x51, 0xd5, 0x90, 0xf7, 0x5d, 0x7a, 0x6c, 0x9c, 0x19, 0x5a, 0x7c, 0xbd, 0xee, 0xd4, 0xc3, 0x54, + 0x65, 0x73, 0x98, 0xab, 0x0d, 0x16, 0xe4, 0x01, 0xe8, 0x9a, 0x15, 0x11, 0x83, 0xd0, 0x55, 0x1e, 0xde, 0x43, 0xc6, + 0x92, 0x80, 0x93, 0xfe, 0x40, 0x0c, 0x4a, 0x72, 0xfd, 0x38, 0x06, 0x1f, 0x33, 0xcc, 0x87, 0x7a, 0x58, 0x8e, 0x46, + 0x28, 0x75, 0x4e, 0x67, 0xa9, 0x89, 0xb8, 0x12, 0xf8, 0x25, 0x97, 0xe0, 0x97, 0xac, 0x10, 0x1b, 0x96, 0x23, 0xf2, + 0x38, 0x8b, 0x25, 0x38, 0xe5, 0xef, 0xf1, 0x79, 0x7c, 0x1e, 0x1a, 0x98, 0x9a, 0x61, 0x99, 0x8b, 0x6c, 0xb0, 0x98, + 0xb3, 0x96, 0x40, 0x70, 0x33, 0xe0, 0x2e, 0xb5, 0x21, 0xd1, 0x58, 0x03, 0x45, 0x77, 0x51, 0x68, 0x66, 0xf4, 0x6a, + 0xa7, 0x8d, 0x61, 0xe4, 0xf0, 0xc2, 0x5c, 0xc3, 0x58, 0x04, 0x32, 0x97, 0xab, 0x1e, 0xfb, 0xab, 0x0f, 0x9b, 0x15, + 0x06, 0xaf, 0xc8, 0x74, 0xe8, 0x8e, 0x63, 0xc6, 0x57, 0x7b, 0xe2, 0x18, 0x82, 0x4c, 0x2c, 0x95, 0x6e, 0x39, 0x26, + 0xae, 0xa2, 0xcf, 0xc4, 0x90, 0xed, 0x96, 0x67, 0xe6, 0x42, 0x37, 0xdb, 0x7f, 0x39, 0xb7, 0x73, 0x4e, 0xb8, 0xd1, + 0x4a, 0x1a, 0x6d, 0xd4, 0x0b, 0x43, 0x55, 0x5d, 0x30, 0xbf, 0xc7, 0x4e, 0x4b, 0x8b, 0x9d, 0xab, 0x77, 0x3f, 0x7c, + 0x9d, 0xaf, 0x8a, 0xbf, 0xc5, 0xea, 0xd0, 0x8a, 0x0c, 0x77, 0x3b, 0xc8, 0x9b, 0x33, 0x3d, 0xf6, 0x8a, 0x5c, 0xa8, + 0x0e, 0x7f, 0x51, 0x5f, 0x98, 0x07, 0x3b, 0xa3, 0x96, 0xf0, 0xe8, 0xf7, 0x20, 0x03, 0xe5, 0x1f, 0x4c, 0x4c, 0x16, + 0x2c, 0xb9, 0xa5, 0xa5, 0x88, 0xff, 0xf1, 0x4a, 0x98, 0x58, 0x55, 0x07, 0x30, 0x90, 0x03, 0x53, 0xf1, 0x00, 0x6e, + 0x4d, 0xf8, 0x84, 0xb3, 0x3c, 0x3d, 0x88, 0xfe, 0xd1, 0x12, 0xad, 0x7f, 0x44, 0xff, 0x00, 0x77, 0x67, 0xf7, 0x3a, + 0x64, 0x15, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0xae, 0x54, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x36, 0x8b, + 0x1f, 0x3b, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, + 0xfa, 0xea, 0x71, 0xa5, 0x82, 0x86, 0x83, 0xd0, 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xca, 0xa7, 0xd3, 0x9d, 0x49, + 0x64, 0x9c, 0xc5, 0xf0, 0xee, 0x41, 0x10, 0x48, 0x80, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, 0x3a, 0xea, 0xa5, 0x24, + 0x10, 0x80, 0xbe, 0xf2, 0x1e, 0x94, 0x57, 0x65, 0xbf, 0xd5, 0x92, 0xa0, 0x85, 0xa5, 0xe6, 0x5a, 0x15, 0xd3, 0xc3, + 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, 0x10, 0xac, 0xb2, 0x83, + 0xf2, 0xef, 0x62, 0x8a, 0x6c, 0xfe, 0x90, 0x7d, 0x47, 0x5d, 0x87, 0x23, 0x57, 0xb0, 0xee, 0xa5, 0x8a, 0x82, 0x01, + 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0xf5, 0xdc, 0x9e, 0x35, 0xfd, 0x86, + 0x8c, 0xb3, 0x8f, 0x30, 0xce, 0x3e, 0x0a, 0xbc, 0x58, 0x24, 0xf9, 0x41, 0xc6, 0x1a, 0xc7, 0xaa, 0x2d, 0xd0, 0x49, + 0x0f, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0xa3, 0x23, 0xea, 0x2c, 0xee, 0x69, 0x2b, 0xf3, 0xde, 0x9e, 0x50, + 0xbb, 0x8c, 0x05, 0x6e, 0x37, 0xcc, 0xb4, 0xa0, 0xb5, 0xd2, 0x38, 0x8f, 0x87, 0x11, 0x19, 0x1b, 0xf1, 0x13, 0xb6, + 0xac, 0xa9, 0x9a, 0x37, 0xd0, 0x1c, 0x35, 0x82, 0xdc, 0xbc, 0x32, 0xde, 0xaa, 0x64, 0x18, 0x45, 0x23, 0xcb, 0xa9, + 0x10, 0x43, 0x32, 0x86, 0x9d, 0x51, 0x70, 0xab, 0xbd, 0x5e, 0x73, 0x8f, 0xf8, 0xa2, 0xe1, 0xad, 0x66, 0x6e, 0x01, + 0xb2, 0x32, 0x8e, 0xaa, 0x7b, 0x93, 0x08, 0xbc, 0x6f, 0xab, 0x08, 0x69, 0xab, 0xa1, 0x7d, 0xba, 0xb2, 0x52, 0x6c, + 0xbe, 0xa7, 0xd3, 0x51, 0x1a, 0xd9, 0x11, 0x45, 0xf8, 0x53, 0x05, 0x49, 0xb8, 0x4a, 0xfa, 0xa4, 0x32, 0xb9, 0x60, + 0x2a, 0xe5, 0xf8, 0x53, 0x29, 0xa5, 0xbe, 0xb1, 0x5f, 0x12, 0xd7, 0x77, 0x32, 0x02, 0x7f, 0x9a, 0x32, 0xfd, 0x9e, + 0x96, 0x53, 0x06, 0x7e, 0x45, 0xfe, 0x76, 0x2c, 0xa5, 0xe4, 0xfa, 0x95, 0x88, 0x87, 0x14, 0xc3, 0xbb, 0xab, 0x23, + 0xac, 0x4d, 0x08, 0x94, 0x0a, 0x17, 0xe1, 0x82, 0xe8, 0x6d, 0x29, 0xef, 0xee, 0xe3, 0x12, 0x3b, 0x07, 0xc0, 0xca, + 0x69, 0x12, 0xe0, 0x5f, 0x3d, 0xe6, 0x63, 0x35, 0xe6, 0xd4, 0xe8, 0xfa, 0xdd, 0xef, 0xe4, 0x13, 0xd0, 0xdb, 0xca, + 0x51, 0x70, 0xd8, 0x19, 0x41, 0x2e, 0xdc, 0x85, 0xc1, 0xc5, 0x57, 0x58, 0xbb, 0x2c, 0x8d, 0x37, 0x16, 0x40, 0xef, + 0x49, 0x06, 0x16, 0x6c, 0x98, 0x63, 0x0a, 0x8f, 0xd6, 0x4e, 0x99, 0x0e, 0xa2, 0x82, 0x3c, 0xab, 0x9e, 0x25, 0x6d, + 0xd4, 0x7e, 0xc7, 0x26, 0x70, 0x87, 0x91, 0x7c, 0xbd, 0x70, 0xe2, 0xc0, 0x03, 0x32, 0x4d, 0x66, 0x9b, 0x7d, 0xeb, + 0x23, 0x8f, 0xbc, 0x99, 0xc4, 0xfb, 0x5a, 0x0a, 0xf3, 0xcd, 0x8a, 0x6e, 0x30, 0x84, 0xa2, 0x08, 0xfb, 0xbd, 0x55, + 0x31, 0x45, 0xb5, 0x41, 0x1b, 0x34, 0x2c, 0x6f, 0xc5, 0x0f, 0x70, 0xc6, 0xd0, 0x66, 0x21, 0x7b, 0x47, 0x67, 0x1d, + 0xce, 0x1c, 0x66, 0xcc, 0x08, 0x8c, 0x4a, 0xcb, 0x92, 0x4e, 0xc1, 0xd1, 0xb9, 0xfe, 0x20, 0x2a, 0xae, 0x8f, 0x15, + 0x80, 0x27, 0x99, 0xc1, 0x3f, 0xc5, 0x36, 0x58, 0x0f, 0x3b, 0x0d, 0xc3, 0xd4, 0x1f, 0xf4, 0xae, 0x6b, 0xf9, 0x2a, + 0xc4, 0x91, 0x2e, 0x86, 0xd0, 0x3a, 0x77, 0xf7, 0x80, 0x22, 0x2e, 0xe8, 0x45, 0xaa, 0xf1, 0x27, 0xb5, 0x1c, 0x9b, + 0xf5, 0x35, 0xae, 0x63, 0xda, 0x20, 0x8a, 0x75, 0xd7, 0xc4, 0x9f, 0xea, 0x57, 0x60, 0x55, 0x0a, 0xac, 0x33, 0x28, + 0x3f, 0x54, 0x75, 0xd9, 0x90, 0x4a, 0x72, 0x6d, 0x3a, 0x95, 0xa6, 0xd3, 0x1a, 0xa1, 0x5c, 0x7a, 0x52, 0xdd, 0xbf, + 0x42, 0x08, 0x03, 0x53, 0x66, 0x0f, 0x56, 0xa9, 0x1d, 0xac, 0x82, 0x57, 0x2f, 0xb6, 0xb0, 0x4a, 0xc2, 0xf1, 0x5c, + 0xa1, 0x51, 0x59, 0xe3, 0x90, 0x21, 0x7d, 0x21, 0x16, 0x41, 0x02, 0x60, 0xd1, 0x8f, 0x99, 0xcb, 0xfb, 0x16, 0x0e, + 0x85, 0x3d, 0xc9, 0x24, 0x9c, 0x6e, 0x42, 0x0b, 0x78, 0x1e, 0x58, 0x0d, 0x3c, 0x42, 0xcc, 0x4c, 0xfc, 0x27, 0x78, + 0x16, 0xfa, 0xdb, 0xcf, 0xd1, 0x3a, 0x0b, 0xf2, 0xf4, 0xdf, 0xa2, 0x24, 0x34, 0xf6, 0x3f, 0xc7, 0x43, 0x87, 0x84, + 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe3, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0x36, 0xa1, 0x07, 0x80, 0x25, 0x14, + 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x54, 0xf7, 0xb7, 0x1d, 0x2f, + 0xa5, 0x35, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf5, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, 0xfb, 0xc2, 0x9f, 0x1c, + 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xca, 0xc5, 0x61, 0xdb, 0x41, 0xf7, 0x02, 0x73, + 0x75, 0x53, 0x67, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0xaa, 0x0a, 0x2e, 0x40, 0xbc, + 0x1f, 0x08, 0x93, 0x53, 0x45, 0x03, 0x78, 0x9f, 0x55, 0x8f, 0x4e, 0x0d, 0x38, 0xb8, 0x8c, 0x1b, 0x36, 0xf1, 0x99, + 0xf0, 0xa9, 0xc0, 0x4a, 0x5a, 0xe3, 0xd0, 0x88, 0xe6, 0x74, 0x01, 0x66, 0x1b, 0x40, 0xc1, 0xdd, 0xf9, 0xb0, 0xb5, + 0x50, 0xc1, 0x93, 0xbc, 0x8d, 0x17, 0xb4, 0x09, 0x71, 0x26, 0x4d, 0xc1, 0xdd, 0x76, 0x59, 0x06, 0xe6, 0xb7, 0xff, + 0x51, 0x58, 0x24, 0x18, 0x50, 0xa5, 0x49, 0x82, 0xf0, 0x04, 0x95, 0x91, 0x6e, 0xed, 0x66, 0x02, 0xe9, 0x44, 0x84, + 0x37, 0xcc, 0x3f, 0x6e, 0x9d, 0xaf, 0x8e, 0x1a, 0x88, 0x9a, 0x1a, 0xa8, 0x80, 0x1a, 0xc8, 0xe6, 0xf6, 0x2f, 0x61, + 0x21, 0x6c, 0x84, 0x2a, 0x11, 0x04, 0x44, 0x58, 0x68, 0xc3, 0x07, 0x94, 0x49, 0x08, 0x79, 0x03, 0xa8, 0x98, 0x92, + 0x77, 0x60, 0x34, 0x0e, 0xaf, 0xf7, 0x80, 0xfb, 0xa5, 0x65, 0x18, 0x3c, 0xa7, 0x60, 0xf2, 0x5f, 0xf8, 0x7c, 0xa8, + 0x5e, 0xad, 0x0e, 0x42, 0xf8, 0x19, 0xc4, 0x8a, 0x70, 0xfc, 0xc5, 0x0f, 0x40, 0x36, 0x15, 0x96, 0x47, 0x47, 0x12, + 0x04, 0x7e, 0x88, 0x22, 0x1c, 0xf0, 0x0c, 0xef, 0xb2, 0x2d, 0xa2, 0xe7, 0x67, 0xa5, 0xea, 0x59, 0xc9, 0x60, 0x56, + 0xa5, 0xa7, 0x71, 0x74, 0x43, 0x18, 0x08, 0x2e, 0xd4, 0xee, 0x1b, 0x84, 0x40, 0xd9, 0x72, 0x6b, 0xe8, 0xd2, 0x73, + 0x30, 0x1f, 0x8d, 0xa3, 0x77, 0x0c, 0x1e, 0x16, 0x36, 0xee, 0x28, 0x4c, 0xb3, 0x4c, 0x1b, 0xe6, 0xb1, 0x15, 0x38, + 0xa9, 0x53, 0x94, 0xfc, 0x29, 0xb9, 0x88, 0xa3, 0xf6, 0x75, 0x84, 0x5a, 0xf0, 0x6f, 0x8b, 0xa3, 0x3e, 0x4d, 0x68, + 0x9e, 0xfb, 0xe0, 0x37, 0x19, 0x31, 0x9b, 0x6c, 0xbd, 0x16, 0x35, 0x41, 0x4f, 0xec, 0x06, 0x03, 0x56, 0xe2, 0x19, + 0xb0, 0x0f, 0x96, 0x83, 0x25, 0xef, 0x45, 0xac, 0xfc, 0x29, 0x85, 0xc1, 0xea, 0x39, 0x43, 0x08, 0x67, 0x01, 0x93, + 0xf2, 0x3f, 0x9f, 0x69, 0xb8, 0x7e, 0x7e, 0xbe, 0x8e, 0x11, 0x91, 0x3e, 0x88, 0x5c, 0x83, 0x1d, 0x11, 0x41, 0xd8, + 0x32, 0x3d, 0x74, 0x65, 0xbe, 0xf3, 0xd6, 0xd5, 0x23, 0x1b, 0x2e, 0x0e, 0x0c, 0xa8, 0x51, 0x60, 0xb4, 0x82, 0x0b, + 0x52, 0x0d, 0x1c, 0x94, 0x10, 0x9a, 0x95, 0xf1, 0x8c, 0x5c, 0x43, 0x24, 0xbc, 0x0c, 0xf5, 0xc1, 0xb0, 0x20, 0x90, + 0xa0, 0x66, 0x20, 0x41, 0x65, 0xbe, 0x76, 0x0e, 0xb3, 0x2e, 0xcc, 0x6c, 0x67, 0xa8, 0xef, 0x82, 0xfc, 0xfc, 0xa0, + 0xe3, 0x1c, 0x58, 0xda, 0xa3, 0xa3, 0x12, 0x22, 0x88, 0x01, 0x05, 0xaf, 0x24, 0xc0, 0x40, 0x03, 0x5e, 0x6e, 0x69, + 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x2a, 0xc8, 0xc5, 0xeb, 0x7a, 0x4f, 0x13, 0x42, 0x0e, 0x3b, 0x03, + 0x9d, 0xee, 0x46, 0x48, 0x1c, 0xfc, 0xaa, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xeb, 0x8d, 0xf9, 0x77, 0x43, 0x8f, 0x58, + 0x4f, 0x42, 0xba, 0x20, 0x5d, 0x9e, 0x4f, 0x7b, 0x0d, 0x57, 0xac, 0xd2, 0xc8, 0xc1, 0x25, 0xe8, 0xb3, 0x01, 0x01, + 0x4a, 0x54, 0x99, 0x4a, 0xd0, 0x32, 0x2e, 0x93, 0x8a, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, 0xd6, 0x2b, 0x41, 0xb7, 0xd6, + 0x00, 0x78, 0x67, 0x66, 0xff, 0x54, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, 0x1c, 0x76, 0x2b, 0x76, 0x5d, + 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0x5e, 0xec, 0xf2, 0x09, 0x10, 0xa2, 0xb6, 0x62, + 0x1a, 0xb1, 0x84, 0x21, 0xeb, 0xc6, 0x90, 0x8d, 0x36, 0x14, 0x9e, 0x4a, 0xe4, 0xc0, 0x25, 0x9a, 0x20, 0xf9, 0x8e, + 0x4b, 0x70, 0x08, 0x2f, 0x3c, 0xc2, 0x7f, 0x01, 0x16, 0xa9, 0xc4, 0x0c, 0xcb, 0xf5, 0x1a, 0xea, 0x79, 0xbc, 0xcf, + 0xb6, 0x83, 0x93, 0xca, 0xad, 0xb1, 0x4b, 0x3b, 0xf1, 0xb8, 0x6a, 0x42, 0xe2, 0x0c, 0xfa, 0xf5, 0x15, 0xd1, 0xe0, + 0xb0, 0x9b, 0xbe, 0xf2, 0xef, 0x95, 0xb9, 0x1d, 0x88, 0x0d, 0xeb, 0x0d, 0x56, 0x1f, 0x40, 0xcb, 0xff, 0xcc, 0xfc, + 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, 0x5e, 0xc4, 0x3e, 0xeb, 0x23, 0x46, 0x1a, 0x8b, 0xbb, 0x47, 0x88, 0xff, 0x73, + 0x27, 0x8a, 0x01, 0x4f, 0x6a, 0xfe, 0x39, 0x46, 0x7d, 0x08, 0x45, 0x6d, 0x3d, 0x6c, 0x80, 0xd2, 0xae, 0x36, 0xb5, + 0x18, 0x19, 0x12, 0xc8, 0x77, 0x2e, 0xbc, 0xa0, 0x39, 0x89, 0x14, 0xc8, 0xc9, 0x75, 0x17, 0x4f, 0xb2, 0x2d, 0x61, + 0xae, 0xbf, 0x83, 0x63, 0xe6, 0x6a, 0x23, 0x2b, 0xe3, 0xf7, 0xc0, 0xce, 0x70, 0x23, 0x59, 0x3a, 0xf0, 0xa9, 0x06, + 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0xd0, 0xe0, 0xbd, 0x7d, 0x64, 0x0e, 0x7e, 0xa7, 0x81, 0xf8, 0x98, 0x39, 0x1d, + 0xc9, 0x56, 0xa8, 0x35, 0x67, 0xc7, 0xcb, 0xb6, 0x23, 0x0c, 0x0a, 0x1b, 0xbd, 0xaf, 0x46, 0x56, 0xb1, 0xb7, 0x53, + 0x11, 0xcc, 0xe9, 0x56, 0xd5, 0xce, 0xa9, 0xdc, 0x32, 0xaa, 0x95, 0xa6, 0x01, 0x22, 0x5c, 0xf9, 0x44, 0xf2, 0x31, + 0x33, 0xe1, 0x1f, 0x0c, 0xc6, 0x35, 0x23, 0x85, 0x7f, 0xdc, 0x17, 0x3b, 0x64, 0x37, 0x3a, 0xdc, 0x56, 0xd0, 0xbc, + 0x50, 0xc1, 0x03, 0x8e, 0x4a, 0x96, 0x10, 0x29, 0x72, 0x7d, 0xa8, 0x1a, 0xa6, 0x6c, 0x9f, 0x22, 0x84, 0x90, 0xf6, + 0x38, 0xeb, 0x86, 0xd6, 0x0c, 0x3d, 0x52, 0x3b, 0x4d, 0xee, 0xd0, 0x5c, 0x17, 0xa0, 0xc2, 0x08, 0xa4, 0xab, 0xcf, + 0xec, 0x3e, 0x95, 0x10, 0xbd, 0x7c, 0xe3, 0x42, 0x18, 0x3b, 0x2b, 0x4b, 0x5c, 0x9a, 0x51, 0xdb, 0x30, 0xba, 0x6e, + 0x63, 0x38, 0x1b, 0x18, 0x33, 0x0d, 0x4a, 0x3a, 0x10, 0xea, 0xba, 0x4f, 0xaf, 0x32, 0x13, 0xe8, 0xb1, 0x20, 0xb4, + 0xc5, 0xf0, 0x8c, 0x68, 0xb0, 0x6c, 0x2a, 0xc1, 0x82, 0x6f, 0x55, 0xa6, 0xd6, 0x66, 0x93, 0xc5, 0xbf, 0xea, 0xd8, + 0x3c, 0xed, 0x57, 0xd4, 0xcc, 0x73, 0xe9, 0xa3, 0x23, 0x64, 0x3e, 0x1e, 0xdd, 0xf3, 0xb7, 0x37, 0xaf, 0x7e, 0x7c, + 0xf3, 0x7a, 0xbd, 0xee, 0xb2, 0x76, 0xf7, 0x0c, 0xff, 0x53, 0x57, 0xf1, 0x60, 0xab, 0x28, 0x40, 0x47, 0x47, 0x87, + 0xdc, 0xb8, 0xf0, 0x7c, 0xe6, 0x0b, 0x88, 0x1b, 0xa4, 0x47, 0xb8, 0x28, 0xab, 0x98, 0x20, 0x77, 0xd1, 0x20, 0xba, + 0x8f, 0x40, 0x09, 0x55, 0x93, 0xbf, 0x5f, 0xb6, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, + 0xa5, 0xb8, 0x24, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, 0x44, 0xc5, 0x25, 0x90, 0x44, + 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0x17, 0xce, 0x5d, 0xaa, 0x40, 0x83, 0x4e, + 0x5a, 0xe0, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xef, 0x4f, 0x07, 0x71, 0x5c, 0xe0, 0x25, 0x11, 0xc7, 0xfe, 0x59, + 0xc4, 0xd5, 0xa2, 0x64, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x97, 0xca, 0xe4, 0xae, 0x9d, 0x1f, 0xc7, 0x65, 0x72, + 0xd7, 0x56, 0xc9, 0x1d, 0xc2, 0xf7, 0xa9, 0x4c, 0xee, 0x6d, 0xca, 0x7d, 0x5b, 0xc1, 0xcd, 0x17, 0x16, 0x70, 0x28, + 0xda, 0xa2, 0xad, 0xe5, 0x76, 0x51, 0x9b, 0xe2, 0x8a, 0x86, 0xd1, 0x14, 0xf7, 0x6c, 0xfc, 0x30, 0x7c, 0x09, 0xae, + 0x4c, 0x9a, 0xc8, 0x3f, 0x41, 0xfa, 0xe9, 0xd4, 0x06, 0xee, 0x33, 0xd2, 0xe9, 0xcf, 0xae, 0x44, 0xbb, 0xdb, 0x6f, + 0xb5, 0x66, 0xb0, 0x77, 0x33, 0x52, 0xf8, 0x62, 0xb3, 0x96, 0x89, 0xaf, 0x73, 0x98, 0xad, 0xd7, 0x87, 0x05, 0x32, + 0x1b, 0x6e, 0xca, 0x62, 0x3d, 0x9c, 0x8d, 0x70, 0x07, 0x7f, 0xc8, 0x10, 0x5a, 0xb1, 0xe1, 0x6c, 0x44, 0xd8, 0x70, + 0xd6, 0xea, 0x8e, 0xac, 0xa1, 0x9d, 0xd9, 0x8a, 0x1b, 0x08, 0xa1, 0x39, 0x1b, 0x9d, 0x98, 0x92, 0xd2, 0xe5, 0xdb, + 0x2f, 0x5a, 0x07, 0xf4, 0x53, 0x8d, 0xe0, 0x65, 0x12, 0xf7, 0xa0, 0x2f, 0x7a, 0x65, 0x9f, 0x6e, 0x2d, 0xc9, 0xe9, + 0x49, 0xed, 0x6a, 0x4f, 0x11, 0x36, 0x3d, 0xa9, 0xe3, 0xf2, 0xd8, 0x34, 0xe3, 0xba, 0x94, 0xee, 0x3b, 0xd4, 0x8c, + 0xfc, 0xe5, 0x60, 0x01, 0x08, 0x52, 0xc3, 0xa3, 0x28, 0x5d, 0x38, 0xa5, 0x10, 0x2e, 0x0e, 0x2a, 0x3b, 0x30, 0x29, + 0x48, 0xa7, 0x5f, 0x18, 0x4b, 0xff, 0xc2, 0x45, 0x34, 0xa5, 0x98, 0x92, 0xcc, 0x97, 0x2c, 0x0c, 0x58, 0xe8, 0x36, + 0xe5, 0x99, 0x81, 0x5e, 0x69, 0x84, 0x73, 0x02, 0xf1, 0x90, 0xfa, 0xa5, 0x31, 0xf0, 0x8a, 0x67, 0xed, 0x72, 0xc8, + 0x46, 0xe8, 0xe4, 0x14, 0xd3, 0xe1, 0x1f, 0xd9, 0xa2, 0x0b, 0x8f, 0x05, 0xfe, 0x31, 0x22, 0xb3, 0xb6, 0xac, 0x12, + 0x04, 0x24, 0xe4, 0x6d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x86, 0x6c, 0xd4, 0x9e, 0x55, 0x15, 0x7b, + 0xbe, 0x62, 0x4b, 0x56, 0x09, 0xb6, 0x62, 0xcb, 0x55, 0x0c, 0x5f, 0x67, 0x30, 0x20, 0x08, 0x01, 0xc0, 0x00, 0x00, + 0x1a, 0x05, 0xd1, 0x7c, 0xb1, 0x22, 0x7e, 0xb3, 0xdb, 0x7b, 0xfc, 0x0e, 0x58, 0xa0, 0x35, 0xf6, 0xff, 0x3e, 0x94, + 0x01, 0x7b, 0xca, 0xd2, 0xc4, 0xcc, 0x2d, 0xad, 0x8a, 0x0e, 0xa0, 0x52, 0x21, 0x4c, 0x69, 0x20, 0x73, 0x98, 0x19, + 0xa8, 0x05, 0x5a, 0x83, 0x62, 0xa8, 0x47, 0xed, 0x0c, 0x8e, 0x18, 0x78, 0x87, 0x86, 0xcc, 0x8c, 0x31, 0x61, 0x5c, + 0xc0, 0x14, 0x33, 0x03, 0x9e, 0x59, 0xda, 0xd9, 0x48, 0x23, 0xcb, 0x0d, 0x8a, 0xc1, 0x5f, 0x3a, 0x56, 0xc3, 0xb2, + 0xdd, 0x1d, 0xa1, 0x43, 0x42, 0xec, 0xc7, 0x08, 0x36, 0x99, 0x4b, 0x6d, 0x99, 0xef, 0x93, 0x5e, 0x6a, 0x3f, 0xe1, + 0xcf, 0x68, 0x63, 0x76, 0x00, 0xe8, 0xc8, 0xb0, 0x59, 0x7f, 0xd9, 0x50, 0x79, 0xfd, 0xba, 0x37, 0x4a, 0xe5, 0xbe, + 0x77, 0xa7, 0x03, 0xd5, 0x44, 0xe8, 0xad, 0x87, 0xab, 0x87, 0x7a, 0x08, 0x98, 0x31, 0x98, 0x5b, 0x66, 0xf4, 0xad, + 0x10, 0xc9, 0x25, 0x91, 0xc0, 0x92, 0x60, 0x4a, 0x18, 0xec, 0xad, 0xa3, 0x23, 0x53, 0x8d, 0xb5, 0xe0, 0x79, 0x52, + 0x04, 0x82, 0x81, 0x8f, 0xa0, 0x0c, 0x68, 0xa2, 0xcc, 0x6d, 0x38, 0xf9, 0x95, 0xb9, 0x5f, 0xb8, 0xba, 0x7d, 0x2c, + 0x9d, 0xb6, 0xd5, 0x5c, 0x8f, 0x57, 0x05, 0xee, 0xab, 0x7b, 0x49, 0xab, 0xe0, 0x46, 0xf6, 0x26, 0x4f, 0x99, 0xbb, + 0x75, 0x5f, 0xaa, 0xb7, 0xbf, 0x99, 0x5e, 0xd5, 0x4c, 0x6f, 0xb7, 0x99, 0x30, 0xae, 0xe4, 0xd7, 0xac, 0x22, 0xcd, + 0xc9, 0x9a, 0xa8, 0x05, 0x15, 0xff, 0xa4, 0x0b, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x41, 0xae, 0x0f, + 0x0b, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, 0x00, 0x2f, 0xaf, 0xaa, 0xc7, 0x07, 0xb8, 0x14, 0x3f, 0xc9, 0xdc, 0x45, + 0x39, 0x15, 0x52, 0x4b, 0xc1, 0x22, 0x64, 0x50, 0xd5, 0xc5, 0xc0, 0x5e, 0xd9, 0xbd, 0x27, 0x06, 0x7c, 0x58, 0x47, + 0xcc, 0x1b, 0x99, 0xe7, 0x3e, 0xbe, 0xa5, 0x29, 0x76, 0x6a, 0xe2, 0x8c, 0xfc, 0x92, 0xc5, 0x05, 0xc8, 0x66, 0xc3, + 0xfa, 0xb5, 0xdf, 0x56, 0x17, 0x97, 0xed, 0x58, 0x0c, 0xcc, 0x13, 0x27, 0xdf, 0x95, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, + 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, 0xe8, 0xe4, 0xce, 0xa6, 0xdd, 0x87, 0x69, 0xf7, 0x26, 0xad, 0x07, 0xe5, + 0x80, 0x34, 0xbb, 0x32, 0xbd, 0x7b, 0xff, 0x7d, 0x0f, 0x2f, 0xdd, 0x6e, 0x20, 0x12, 0xf7, 0xe2, 0x89, 0x31, 0x86, + 0x78, 0x0b, 0x36, 0xa2, 0xea, 0xe8, 0xe8, 0x07, 0xe7, 0x7d, 0x5b, 0xcb, 0xb2, 0x5f, 0x0b, 0x07, 0xb6, 0xc5, 0x54, + 0xba, 0xbc, 0x5c, 0x66, 0x4b, 0xb0, 0xeb, 0x3c, 0xfc, 0x4a, 0x3c, 0x7c, 0x11, 0x32, 0x2d, 0xd6, 0x55, 0xfc, 0xb5, + 0xcc, 0x2b, 0x0f, 0x51, 0x0d, 0x11, 0x48, 0x6b, 0xeb, 0xd2, 0xd0, 0x74, 0xf4, 0x66, 0x46, 0x73, 0x79, 0xfb, 0x4e, + 0x4a, 0x3d, 0xb2, 0x2f, 0x72, 0xeb, 0x04, 0x1e, 0x2d, 0x6c, 0x30, 0x34, 0xf7, 0x95, 0x77, 0x92, 0x0d, 0x88, 0xda, + 0x1c, 0x77, 0x28, 0x89, 0xc4, 0xa2, 0xbe, 0x0b, 0xe1, 0x70, 0x17, 0x82, 0x79, 0x15, 0xb4, 0x0d, 0x62, 0xb7, 0xbb, + 0xa0, 0x6d, 0xe0, 0xd4, 0x6d, 0x03, 0xb7, 0x07, 0x83, 0x85, 0xbd, 0x0f, 0x2f, 0xc7, 0x72, 0x2c, 0x1c, 0x7f, 0xf0, + 0xd6, 0x3e, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3e, 0x73, 0x20, 0x48, 0x9c, 0xe1, 0xe8, 0x47, 0xce, 0x6e, 0xad, 0xe5, + 0xf0, 0x7c, 0xb1, 0xd4, 0x2c, 0x37, 0x77, 0xd4, 0xa0, 0xe2, 0x6b, 0xfa, 0x79, 0xfd, 0x9c, 0x35, 0x74, 0xe3, 0x6f, + 0x21, 0x8c, 0x84, 0x53, 0x76, 0x18, 0x85, 0x84, 0x0d, 0x66, 0x55, 0xc5, 0x6b, 0xfb, 0x0d, 0xe2, 0x3d, 0x68, 0x13, + 0x4e, 0xb0, 0x6c, 0x5c, 0x50, 0x45, 0xd8, 0xc6, 0x1b, 0x0b, 0xa2, 0x3c, 0x3c, 0xd8, 0x31, 0x9a, 0x5e, 0x6d, 0x20, + 0xd0, 0xf1, 0x20, 0x6a, 0x47, 0x2d, 0x96, 0xba, 0xa0, 0xcc, 0x3e, 0xc2, 0xb8, 0xba, 0x3a, 0x33, 0x71, 0xda, 0x2b, + 0xbd, 0xfa, 0x6f, 0x19, 0x18, 0xe0, 0x0b, 0xf0, 0x12, 0x0b, 0xa3, 0xbb, 0x0e, 0x75, 0x0b, 0xea, 0xcb, 0x16, 0x1b, + 0xa1, 0xf5, 0xba, 0x53, 0x3d, 0x03, 0xe5, 0xae, 0xb9, 0x84, 0xbd, 0xe6, 0x12, 0xee, 0x9a, 0x4b, 0xf8, 0x6b, 0x2e, + 0x61, 0xae, 0xb9, 0x84, 0xbf, 0xe6, 0xf2, 0x20, 0xfc, 0x3e, 0x88, 0xe3, 0x18, 0x73, 0x88, 0xab, 0xa8, 0x6d, 0x64, + 0x3c, 0xb8, 0xf0, 0x3c, 0x64, 0x89, 0xaa, 0x96, 0x3f, 0x8c, 0x21, 0x57, 0x6c, 0xdb, 0x4a, 0x18, 0xb7, 0x29, 0xa6, + 0x20, 0x72, 0xfa, 0xd1, 0x51, 0xed, 0xee, 0x3c, 0xec, 0x8c, 0x52, 0x8e, 0x57, 0xd6, 0x89, 0xf6, 0x5f, 0xa0, 0x93, + 0x37, 0xbf, 0x7e, 0x4d, 0xe5, 0x86, 0x08, 0x67, 0x72, 0x7f, 0xd8, 0xf5, 0x94, 0xe2, 0xfb, 0xcc, 0x84, 0x27, 0xe7, + 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0x7f, 0xb3, 0xf7, 0xae, 0xcb, 0x6d, 0x23, 0x59, 0xba, 0xe8, 0xab, + 0x48, 0x0c, 0x9b, 0x05, 0x98, 0x49, 0x8a, 0xf2, 0xde, 0x33, 0x11, 0x07, 0x54, 0x9a, 0x61, 0xcb, 0xe5, 0x2e, 0x77, + 0xf9, 0xd6, 0xb6, 0xab, 0xba, 0xaa, 0x19, 0x3c, 0x2a, 0x08, 0x48, 0x12, 0x70, 0x81, 0x00, 0x0b, 0x00, 0x25, 0xd2, + 0x24, 0xde, 0x7d, 0xc7, 0x5a, 0x2b, 0xaf, 0x20, 0x28, 0xbb, 0x67, 0xf6, 0xfc, 0x3a, 0xe7, 0x8f, 0x2d, 0x26, 0x12, + 0x89, 0xbc, 0xe7, 0xca, 0x75, 0xf9, 0xbe, 0x88, 0x17, 0xb4, 0xde, 0x55, 0x28, 0x3c, 0xaa, 0xa2, 0x94, 0x5b, 0xc9, + 0x75, 0x06, 0x41, 0xec, 0xe8, 0x85, 0xe1, 0x4f, 0x20, 0x84, 0x20, 0xc2, 0x84, 0xdf, 0x86, 0x19, 0x6d, 0x67, 0x91, + 0x4e, 0xfa, 0x7d, 0x98, 0xe1, 0x06, 0x56, 0xf2, 0x73, 0xd5, 0x67, 0xfb, 0x6d, 0x10, 0xb2, 0x5d, 0x10, 0xb1, 0xdb, + 0x62, 0x1b, 0x94, 0xd6, 0x91, 0xf8, 0x49, 0x19, 0xfe, 0x16, 0x5e, 0x2f, 0x0f, 0x21, 0xde, 0xa7, 0x97, 0xe6, 0x67, + 0x69, 0x2b, 0x0a, 0x70, 0x1f, 0xa1, 0x47, 0x75, 0x20, 0xd8, 0x09, 0x4f, 0x78, 0x00, 0x27, 0xab, 0x59, 0xc5, 0x3f, + 0xa4, 0x20, 0x4e, 0x14, 0x1c, 0x02, 0xae, 0xb6, 0x9f, 0xd2, 0xaf, 0x60, 0xf8, 0xd2, 0xc1, 0x96, 0xc3, 0xdb, 0x62, + 0xdb, 0x63, 0x25, 0x7f, 0x04, 0xec, 0x5b, 0x3d, 0x19, 0xab, 0xdb, 0x03, 0x67, 0x5d, 0x4a, 0xd1, 0xf1, 0xa6, 0x38, + 0xbc, 0x3d, 0x9f, 0xed, 0xb7, 0x41, 0xc4, 0x76, 0x41, 0x86, 0xb5, 0x4e, 0x1a, 0x8e, 0x83, 0x21, 0x7c, 0x16, 0x23, + 0xec, 0xff, 0xa2, 0x1e, 0x78, 0x09, 0xa9, 0xa1, 0xc0, 0xc5, 0x60, 0xc3, 0xd1, 0xda, 0x2e, 0xd3, 0xc0, 0x4d, 0x0d, + 0x7a, 0x7d, 0x4f, 0x21, 0xca, 0x0b, 0x46, 0x73, 0x23, 0x58, 0x37, 0x86, 0x5c, 0x1c, 0x8e, 0x9b, 0xc5, 0x90, 0x97, + 0x34, 0x9d, 0x06, 0xa1, 0x74, 0x67, 0x59, 0x43, 0x12, 0x65, 0x1f, 0x84, 0xda, 0xb5, 0x65, 0xbf, 0x0d, 0x6c, 0x5f, + 0xfe, 0x68, 0x18, 0xfb, 0x17, 0x8b, 0x27, 0x42, 0xba, 0x88, 0xe7, 0x20, 0x88, 0xda, 0xcf, 0xb3, 0xe1, 0xc6, 0xbf, + 0x58, 0x3f, 0x11, 0xca, 0x6f, 0x3c, 0xb7, 0xe5, 0x10, 0x91, 0xb5, 0xf0, 0x85, 0xf1, 0xf0, 0xe0, 0xca, 0xd0, 0x76, + 0x38, 0x08, 0xfd, 0xb7, 0x59, 0x23, 0xb8, 0xb1, 0xa1, 0x7d, 0xbe, 0xf0, 0x61, 0x6b, 0xa3, 0xb1, 0xa6, 0x98, 0x6e, + 0xa1, 0x7f, 0x93, 0xd9, 0xd2, 0x9e, 0x46, 0x25, 0x2f, 0x4e, 0x4d, 0x23, 0x16, 0xc2, 0x80, 0xa1, 0x9f, 0xcc, 0x23, + 0x50, 0xcd, 0x1d, 0x8f, 0x40, 0x26, 0x1f, 0xe8, 0xc1, 0x9a, 0xd4, 0xaa, 0xbf, 0x86, 0x99, 0xfc, 0x3f, 0x52, 0x61, + 0x31, 0xba, 0xdb, 0x86, 0x99, 0xfa, 0x23, 0x92, 0x7f, 0xb0, 0x9c, 0xef, 0x52, 0x2f, 0xd4, 0x7e, 0x2c, 0xac, 0xc0, + 0xa0, 0x44, 0xd5, 0x80, 0x1e, 0x88, 0xa0, 0x2a, 0x83, 0x34, 0xc3, 0xea, 0x1c, 0xf4, 0xbb, 0xa7, 0x55, 0x47, 0x72, + 0x48, 0x6b, 0x35, 0xa4, 0x82, 0xa9, 0x52, 0x83, 0xfc, 0x70, 0x58, 0xa6, 0x4c, 0x97, 0x01, 0x97, 0xf4, 0x65, 0xaa, + 0x94, 0xc2, 0x7f, 0x21, 0x00, 0x9d, 0x83, 0x7b, 0x7c, 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, + 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, 0xb9, 0x4c, 0x21, 0x82, 0xaa, 0x84, 0xfa, 0x56, 0xa6, 0x41, + 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, 0x11, 0xd7, 0x33, 0xc2, 0x9a, + 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, 0x8d, 0xab, 0x4a, 0x55, 0x77, + 0x73, 0x6a, 0x29, 0x2d, 0xda, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, 0xe4, 0x08, 0x26, 0x90, 0x24, + 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, + 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0xff, 0x25, 0x8c, 0x34, 0x99, 0xb1, 0x92, 0x45, + 0xb6, 0xab, 0x53, 0xe2, 0x3c, 0x4e, 0x60, 0x7b, 0x34, 0xbd, 0xe5, 0xfb, 0x0c, 0xa2, 0x82, 0x40, 0xc1, 0x8c, 0xf9, + 0xb2, 0x8b, 0xa7, 0xbe, 0xcf, 0x2c, 0x53, 0xf7, 0xe1, 0x60, 0xcc, 0xd8, 0x7e, 0xbf, 0x9f, 0xf7, 0xfb, 0x6a, 0xbe, + 0xf5, 0xfb, 0xc9, 0x33, 0xf3, 0xb7, 0x07, 0x0c, 0x0a, 0x72, 0x22, 0x9a, 0x0a, 0x11, 0xfc, 0x43, 0xf2, 0x04, 0xc9, + 0xe8, 0x8e, 0xfb, 0xdc, 0x72, 0xb6, 0xac, 0x8e, 0x40, 0x30, 0x0f, 0x87, 0x4b, 0x05, 0x76, 0x2d, 0x51, 0x24, 0x64, + 0xf9, 0x4f, 0xc0, 0x78, 0xe6, 0x3e, 0xc0, 0x92, 0x01, 0x08, 0x5b, 0xe5, 0xe9, 0x7a, 0xcf, 0x57, 0xc1, 0x3b, 0x1d, + 0xef, 0x1a, 0x2b, 0x32, 0x10, 0xb7, 0xc0, 0x46, 0xac, 0xb5, 0x07, 0xe4, 0x4c, 0x01, 0x8e, 0x17, 0x87, 0xc3, 0xb9, + 0xfc, 0xa5, 0x9b, 0xad, 0x13, 0xa8, 0x14, 0xb8, 0x3d, 0x3a, 0x39, 0xf8, 0x1f, 0x40, 0x33, 0x28, 0x87, 0x79, 0xbd, + 0xfd, 0x83, 0x39, 0xf9, 0xe9, 0x29, 0xfe, 0x09, 0x0f, 0xd1, 0xe9, 0xb7, 0x7b, 0xf3, 0x07, 0x45, 0xe5, 0xe1, 0xa0, + 0x16, 0xff, 0x39, 0xe7, 0x15, 0xfc, 0xc2, 0x37, 0x81, 0xd9, 0x64, 0xea, 0x9d, 0x7c, 0x93, 0xe7, 0x4c, 0xbd, 0xc6, + 0x2b, 0x26, 0xdf, 0xe1, 0x70, 0x2e, 0x46, 0xf5, 0x76, 0xe4, 0x44, 0x3b, 0xe5, 0x18, 0x07, 0x83, 0xff, 0x22, 0xda, + 0x26, 0x04, 0x18, 0xca, 0xe1, 0xc8, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, + 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, 0x88, 0x53, 0x9c, 0x80, 0x08, + 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x08, 0xc1, 0x90, 0x6f, 0x24, 0xe0, 0xae, 0xd7, 0xab, 0x31, 0xbe, + 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, 0x81, 0x67, 0xcb, 0xde, 0x44, + 0xb9, 0xdb, 0xf0, 0xb4, 0x9f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, + 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, + 0xc6, 0xbf, 0xd3, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0x27, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, + 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, + 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0xb3, 0xf1, 0x14, 0xfe, 0x07, + 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, 0xb6, 0xb6, 0xa3, 0x3f, 0x76, 0x10, 0xe9, 0xb8, 0x27, + 0x17, 0xea, 0x4b, 0x48, 0x25, 0x17, 0xea, 0x06, 0x62, 0x17, 0x6a, 0xbc, 0xe3, 0x22, 0xd6, 0xfa, 0xdb, 0x1a, 0x05, + 0x2b, 0x01, 0x67, 0xda, 0x5b, 0x30, 0xd8, 0xc0, 0xba, 0x65, 0x19, 0xfc, 0x0d, 0xd7, 0x34, 0x81, 0x1b, 0x16, 0x59, + 0xef, 0x0d, 0xb6, 0xd2, 0x5b, 0x70, 0xb4, 0x4c, 0x9c, 0x4b, 0x49, 0x52, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, + 0xdd, 0xdf, 0x8a, 0xfa, 0x5e, 0x88, 0x3c, 0x58, 0xa5, 0x2c, 0x2a, 0x56, 0x20, 0xb3, 0x07, 0xff, 0x0a, 0x19, 0x39, + 0xca, 0x81, 0xa3, 0xd0, 0x3f, 0x9a, 0x40, 0xe7, 0xa9, 0x23, 0x9d, 0x47, 0x82, 0xad, 0xd4, 0x43, 0x61, 0xe5, 0x05, + 0x44, 0x07, 0xdb, 0x31, 0xb7, 0xf2, 0x24, 0x54, 0x6c, 0xca, 0x44, 0x1e, 0x07, 0xb5, 0x04, 0x8c, 0x15, 0x04, 0x73, + 0x96, 0x4b, 0x17, 0xa4, 0xaa, 0xd1, 0xc3, 0x22, 0x73, 0x3f, 0x16, 0x94, 0xff, 0xb1, 0xca, 0x09, 0xd7, 0x97, 0x21, + 0xc0, 0xd1, 0x3e, 0x06, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x78, 0x27, 0x33, 0x67, 0x53, 0xdb, 0x4b, 0x90, 0xb1, 0x1d, + 0x7e, 0x85, 0xd0, 0x6a, 0xa1, 0xc8, 0xa2, 0xe1, 0x82, 0xe9, 0xf6, 0x94, 0x56, 0xdd, 0xc3, 0x86, 0x27, 0xa5, 0x87, + 0x4a, 0x7d, 0x1b, 0x13, 0x58, 0x56, 0x29, 0xc3, 0xb7, 0x13, 0xaa, 0x4e, 0x0c, 0x2a, 0xd6, 0x0d, 0x5b, 0xc0, 0x21, + 0x16, 0x93, 0xc6, 0x3a, 0x1b, 0xf0, 0x88, 0x25, 0xf0, 0xcf, 0x86, 0x8f, 0xd9, 0x82, 0x47, 0x93, 0xcd, 0xd5, 0xa2, + 0xdf, 0x2f, 0xbd, 0xd0, 0xab, 0x67, 0xd9, 0xe3, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, + 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x31, 0xbc, 0xf6, 0x98, 0x47, 0x6a, 0x49, 0x25, 0x57, 0x19, 0xec, + 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, + 0x83, 0x8e, 0xfc, 0xdb, 0x1d, 0x52, 0xea, 0x26, 0x03, 0xb0, 0x1b, 0x0d, 0x70, 0xc8, 0x54, 0x2f, 0x45, 0x56, 0x2f, + 0x65, 0xaa, 0x97, 0x64, 0xe5, 0x12, 0x2c, 0x24, 0xa6, 0xca, 0x6d, 0x64, 0xe5, 0x16, 0x0d, 0xd7, 0xc3, 0xc1, 0xd6, + 0x8a, 0xcb, 0x66, 0x09, 0xf7, 0x85, 0x15, 0x05, 0xfe, 0xdf, 0xb2, 0x1b, 0x76, 0x27, 0x8f, 0x81, 0x6b, 0x74, 0x4c, + 0x82, 0x0b, 0xc4, 0x1d, 0xbb, 0x05, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, + 0xad, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x96, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x7b, 0xfc, + 0x71, 0xbe, 0x3c, 0x1c, 0x76, 0x9e, 0x51, 0xef, 0xbd, 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xdb, 0x2b, 0x1e, 0x4f, + 0x06, 0x83, 0xb7, 0xfe, 0x0d, 0xaf, 0x67, 0x6f, 0x41, 0x3b, 0x70, 0x7e, 0x23, 0x75, 0xcd, 0xde, 0x2d, 0xcf, 0xbc, + 0x1b, 0x1c, 0x9b, 0x5b, 0x38, 0x7a, 0xfb, 0x7d, 0x6f, 0xc9, 0x23, 0xef, 0x96, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, + 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0xb7, 0xc1, 0x7b, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, + 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, + 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xbf, 0x65, 0x77, 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, + 0x50, 0xea, 0xda, 0x32, 0xac, 0xb4, 0xae, 0x7c, 0x08, 0x1c, 0x0e, 0xc8, 0x4f, 0x4b, 0xc4, 0x41, 0x68, 0xdd, 0x64, + 0x35, 0x57, 0x94, 0x73, 0xa1, 0x0d, 0x33, 0x2f, 0x07, 0x16, 0xb3, 0x94, 0x42, 0x63, 0x01, 0x80, 0x60, 0x52, 0x68, + 0xed, 0xbd, 0x0c, 0x20, 0x27, 0x68, 0xf8, 0x63, 0x73, 0x55, 0x96, 0xb5, 0x6c, 0x49, 0x88, 0xb2, 0x5d, 0x0f, 0x2f, + 0x11, 0x32, 0xad, 0xdf, 0x3f, 0x27, 0x92, 0xb5, 0x49, 0x75, 0x55, 0xa3, 0x25, 0xa0, 0x22, 0x4b, 0xc0, 0xc4, 0xaf, + 0x34, 0x9f, 0x00, 0x3c, 0xe9, 0x78, 0x50, 0x3d, 0xe6, 0x35, 0x13, 0x44, 0xb6, 0x51, 0xf9, 0x93, 0xe2, 0x19, 0x92, + 0x11, 0x14, 0x8f, 0x6b, 0x95, 0xb1, 0x30, 0xcc, 0x03, 0x05, 0xe4, 0xdd, 0xbb, 0x53, 0xdf, 0xda, 0x1f, 0x3b, 0xf6, + 0x6c, 0xad, 0x42, 0x2d, 0xd4, 0x14, 0x2e, 0x39, 0x44, 0x57, 0xa0, 0x81, 0x22, 0x92, 0xf1, 0xe4, 0xf5, 0xe0, 0x72, + 0x12, 0x5d, 0x71, 0x81, 0xce, 0xf8, 0xfa, 0xa6, 0x9b, 0xce, 0xa2, 0xc7, 0xd5, 0x7c, 0x42, 0x4a, 0xb2, 0xc3, 0x21, + 0x1b, 0x55, 0x75, 0xb1, 0x9e, 0x86, 0xf2, 0xa7, 0x87, 0xe0, 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x98, 0x2a, + 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x71, 0x25, 0xf7, 0x3d, 0x20, 0xad, 0xe5, 0x25, 0x97, 0xef, 0x47, 0x88, 0x31, 0xe2, + 0x07, 0x5e, 0xc9, 0x23, 0x16, 0xaa, 0x29, 0x5c, 0xf3, 0x08, 0x41, 0xde, 0x32, 0x1d, 0xfc, 0xad, 0x27, 0x4e, 0xf7, + 0x27, 0x4a, 0xbb, 0xf8, 0xc2, 0xa2, 0xee, 0x39, 0xd2, 0x0d, 0xc8, 0xc1, 0x86, 0xe9, 0xa2, 0x20, 0xdb, 0x94, 0x46, + 0xd0, 0x46, 0xcb, 0x81, 0x0d, 0xa7, 0x52, 0x1b, 0xce, 0x5c, 0x43, 0x70, 0x9f, 0x9f, 0xa7, 0xa3, 0x1b, 0xf8, 0x90, + 0xea, 0xf6, 0x12, 0x3f, 0x1f, 0x36, 0x1c, 0xc9, 0xec, 0x88, 0xcf, 0x6c, 0x22, 0xe9, 0xa4, 0xce, 0x15, 0xb0, 0xdb, + 0xd9, 0x35, 0xc8, 0x11, 0x33, 0xf7, 0x15, 0xaa, 0x6f, 0xd1, 0x80, 0x2b, 0x63, 0xed, 0x6b, 0x92, 0xb1, 0xf0, 0xaa, + 0x9c, 0x86, 0x03, 0x80, 0xa1, 0xcb, 0xe8, 0x6b, 0x8b, 0x4d, 0x96, 0xbd, 0x29, 0x20, 0x08, 0xa2, 0x24, 0x1e, 0x1f, + 0xf0, 0xbe, 0xac, 0x86, 0x1a, 0x25, 0x1f, 0xcb, 0x4e, 0xe0, 0xeb, 0x25, 0xfa, 0xbb, 0x31, 0x97, 0x18, 0xf0, 0xba, + 0x6a, 0x0b, 0x0a, 0xe7, 0xf9, 0xe1, 0x70, 0x9e, 0x8f, 0x8c, 0x67, 0x19, 0xa8, 0x56, 0xa6, 0x75, 0xb0, 0x31, 0xf3, + 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xbe, 0xf2, 0x74, 0xa7, 0xfa, + 0x6c, 0x7f, 0x63, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, + 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, 0x9d, 0xc6, 0x36, 0x3c, 0xb6, 0xb0, 0x1a, 0xbd, + 0x35, 0x5b, 0xb2, 0x15, 0xbb, 0x55, 0x75, 0xba, 0xe1, 0xe1, 0x74, 0x78, 0x19, 0xe0, 0xea, 0x5b, 0x9f, 0x73, 0xbe, + 0xa4, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, 0xd6, 0x8f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0x7e, 0x43, 0xeb, 0x4f, + 0xcc, 0x96, 0x26, 0x79, 0x39, 0xe0, 0x37, 0x93, 0xf5, 0xe3, 0x08, 0x5e, 0x7d, 0x0c, 0x56, 0x8c, 0xcc, 0x99, 0x65, + 0xeb, 0xc7, 0x11, 0x8e, 0xd9, 0xf2, 0x71, 0x44, 0xa3, 0xb6, 0x92, 0xfb, 0xd2, 0x6d, 0x03, 0xc2, 0xca, 0x2d, 0x8b, + 0xe1, 0x35, 0x10, 0xcf, 0xb4, 0x91, 0x74, 0x2d, 0x0d, 0xbd, 0x31, 0x0f, 0xa7, 0x71, 0xb0, 0xa6, 0x56, 0xc8, 0x33, + 0x43, 0xcc, 0xe2, 0xc7, 0xd1, 0x9c, 0xad, 0xb0, 0x22, 0x1b, 0x1e, 0x0f, 0x2e, 0x27, 0x9b, 0x2b, 0xbe, 0x06, 0xf2, + 0xb3, 0xc9, 0xc6, 0x6c, 0x51, 0xb7, 0x5c, 0xcc, 0x36, 0x8f, 0xa3, 0xf9, 0x64, 0x05, 0x3d, 0x6b, 0x0f, 0x98, 0xf7, + 0x0a, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x25, 0x5b, 0x5f, 0x06, 0xb7, 0x6c, 0x3d, + 0x06, 0x22, 0x0e, 0xea, 0x77, 0x6f, 0x03, 0x8b, 0x2f, 0x62, 0xeb, 0x4b, 0x93, 0xb6, 0x79, 0x1c, 0x31, 0x77, 0x70, + 0x1a, 0xb8, 0x60, 0x2d, 0x32, 0x6f, 0xc5, 0xe0, 0x12, 0xb2, 0xf0, 0x62, 0xb6, 0x19, 0x5e, 0xb2, 0xf5, 0x08, 0xa7, + 0x7a, 0xe2, 0xb3, 0x25, 0xbf, 0x65, 0x09, 0x5f, 0x35, 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, + 0xcc, 0x9c, 0xf7, 0x16, 0x46, 0xe5, 0xbe, 0x05, 0x07, 0x14, 0xa4, 0x6d, 0x80, 0x20, 0x89, 0x67, 0x77, 0x1d, 0xae, + 0x3f, 0x49, 0x61, 0xc0, 0x4d, 0x60, 0x06, 0x0c, 0x4c, 0x3f, 0x83, 0x1f, 0x56, 0xba, 0x44, 0x88, 0xb3, 0x9f, 0x52, + 0x92, 0xcc, 0xf3, 0xf7, 0x22, 0xcd, 0xdd, 0xc2, 0x75, 0x0a, 0xb3, 0xa2, 0x40, 0xf5, 0x53, 0x52, 0x1a, 0x58, 0xa8, + 0x44, 0xa6, 0x52, 0xf0, 0xcb, 0xe6, 0x3c, 0xca, 0x8e, 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, + 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, + 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, + 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xad, 0x33, 0x07, 0x69, 0x4b, 0xf3, 0x5d, 0x13, 0x3f, 0x87, 0x05, 0x5c, 0x44, 0x0b, + 0x5b, 0xc3, 0xa3, 0x2a, 0x56, 0xee, 0x4d, 0x9e, 0x23, 0x9c, 0xd1, 0xa5, 0x4c, 0x00, 0x5c, 0xef, 0x97, 0x61, 0xad, + 0xf0, 0x8a, 0x9a, 0x9b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, + 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, + 0x0b, 0x40, 0x4d, 0x3f, 0xd5, 0x62, 0x5d, 0x05, 0xa5, 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, + 0x26, 0x4a, 0xe4, 0xfc, 0xb8, 0x29, 0xc5, 0xa2, 0x14, 0x55, 0xd2, 0x6e, 0x28, 0x78, 0x44, 0xb8, 0x0d, 0x1a, 0x33, + 0xb7, 0x27, 0xba, 0x68, 0x45, 0x28, 0xc7, 0x66, 0x1d, 0x23, 0x8d, 0x32, 0x3b, 0xd9, 0x75, 0xb2, 0xd0, 0x7e, 0x5f, + 0xe5, 0x90, 0x75, 0xc0, 0x1a, 0xc9, 0xd7, 0x6b, 0x0e, 0xdd, 0x36, 0xca, 0x8b, 0x7b, 0xcf, 0x57, 0x70, 0x9a, 0xe3, + 0x89, 0xdd, 0xf5, 0xba, 0x53, 0x24, 0xe2, 0x15, 0x4e, 0xaa, 0x7c, 0x24, 0x0b, 0xc7, 0x9d, 0x3b, 0xad, 0xc5, 0xaa, + 0x72, 0x59, 0x4f, 0x2d, 0x8e, 0x08, 0x7c, 0x2a, 0x8f, 0xf6, 0x42, 0xdb, 0xa2, 0x58, 0x08, 0xa3, 0x47, 0x27, 0xfc, + 0xa4, 0x04, 0xd6, 0xd7, 0xe1, 0xb0, 0xf4, 0x23, 0x8e, 0x7e, 0xa7, 0xd1, 0xe8, 0x86, 0x90, 0x86, 0xa7, 0x5e, 0x34, + 0xba, 0xa9, 0x8b, 0x3a, 0xcc, 0x9e, 0xe5, 0x7a, 0xa0, 0x30, 0x8c, 0x40, 0xfd, 0xe0, 0x2a, 0x83, 0xcf, 0x22, 0x44, + 0xcd, 0x03, 0xd3, 0x6c, 0x08, 0x47, 0x5d, 0xe0, 0xa1, 0x15, 0xb4, 0x98, 0x99, 0x8f, 0x42, 0x0c, 0x1f, 0xd2, 0xc5, + 0xf9, 0x13, 0xb2, 0xf2, 0x01, 0x76, 0x87, 0xee, 0x42, 0x39, 0x67, 0x2a, 0x06, 0xf8, 0x51, 0x40, 0x3e, 0x4a, 0xc0, + 0xcd, 0x00, 0xd9, 0x23, 0x4b, 0x00, 0xb1, 0x62, 0x74, 0x34, 0xf9, 0xdc, 0xf7, 0x22, 0x05, 0xef, 0xec, 0xb3, 0x5c, + 0x4d, 0x18, 0x0a, 0x9f, 0x18, 0xe8, 0xe6, 0x37, 0x7e, 0x7b, 0xde, 0x82, 0x91, 0x5d, 0x92, 0xe2, 0xb5, 0x66, 0xb8, + 0xdf, 0x80, 0xdb, 0x11, 0x50, 0xd6, 0x54, 0xc7, 0x24, 0xdb, 0x34, 0x44, 0x32, 0x60, 0x46, 0x8c, 0x08, 0x2a, 0xcb, + 0x85, 0xff, 0xdd, 0xcb, 0xa2, 0xc0, 0x01, 0x5c, 0xcd, 0x64, 0xf0, 0xda, 0x85, 0x51, 0x01, 0x70, 0x4e, 0x43, 0xa7, + 0xb4, 0x57, 0x55, 0x87, 0x64, 0xd5, 0xfc, 0x60, 0x36, 0x6f, 0x1a, 0x26, 0x46, 0x04, 0xd1, 0x45, 0x38, 0xc1, 0xf4, + 0x8a, 0xf4, 0xb5, 0x92, 0xd3, 0xd1, 0xaa, 0xa3, 0xb5, 0xc4, 0xc4, 0x5c, 0x51, 0xfc, 0x35, 0xe0, 0x71, 0x83, 0x57, + 0x27, 0x69, 0x3a, 0x51, 0x3d, 0x7a, 0xfc, 0x3a, 0x4d, 0x27, 0x25, 0xee, 0x0a, 0xbf, 0x01, 0x17, 0xcd, 0x36, 0x1f, + 0xfa, 0xf1, 0x0b, 0x8a, 0xb8, 0xa8, 0xc1, 0x95, 0x77, 0xaa, 0xaf, 0x54, 0x1f, 0x41, 0x2d, 0x3c, 0x31, 0xb2, 0x16, + 0x9e, 0x5c, 0xb2, 0xd6, 0x82, 0x60, 0x66, 0x73, 0xe0, 0x42, 0x7e, 0xa5, 0x14, 0xf1, 0x26, 0x12, 0x6a, 0x31, 0x68, + 0x3d, 0x66, 0xce, 0xaa, 0xd1, 0x8d, 0xca, 0x8c, 0xd0, 0xbe, 0xad, 0x45, 0xe7, 0x37, 0xf2, 0x53, 0x9e, 0xda, 0x97, + 0xed, 0x71, 0x3e, 0xde, 0xa3, 0xbb, 0xea, 0x2c, 0x33, 0x29, 0xe3, 0x93, 0x59, 0x82, 0xc2, 0x5d, 0x82, 0x0d, 0x48, + 0xb2, 0xdf, 0xea, 0x00, 0x19, 0xb5, 0xd7, 0x7e, 0xd7, 0x59, 0xbe, 0xba, 0xd9, 0x1a, 0x8a, 0x4a, 0xad, 0x24, 0xc5, + 0x41, 0x86, 0xeb, 0xb6, 0xf2, 0xe1, 0xe2, 0x02, 0x7a, 0xc6, 0x48, 0x64, 0x9e, 0x3f, 0x91, 0x2f, 0xc1, 0x39, 0xe3, + 0xac, 0x10, 0x98, 0x30, 0x56, 0xef, 0x5a, 0x4b, 0xa5, 0x21, 0xc5, 0xd8, 0xd1, 0x28, 0xcb, 0x2a, 0x4b, 0x97, 0xd9, + 0x5a, 0xc2, 0x96, 0x55, 0xe4, 0x16, 0xb6, 0xce, 0x64, 0x35, 0x1f, 0x55, 0xdc, 0x41, 0xf9, 0x66, 0xcb, 0x8c, 0xef, + 0x25, 0xb2, 0x77, 0x1b, 0x28, 0xe1, 0xd9, 0xe8, 0x3f, 0x90, 0x7e, 0x9b, 0x61, 0x9c, 0x72, 0x5b, 0x49, 0x0b, 0x70, + 0xfa, 0x87, 0xc3, 0xa3, 0x0a, 0x83, 0x06, 0x47, 0x18, 0x47, 0xd6, 0xef, 0xdf, 0x54, 0x5e, 0x8d, 0x89, 0x3a, 0x3e, + 0xab, 0xdf, 0xaf, 0xe8, 0xe1, 0xb4, 0x1a, 0xad, 0xd2, 0x2d, 0xb2, 0x13, 0xda, 0x58, 0xf9, 0x41, 0xad, 0x80, 0xd9, + 0x5b, 0x9f, 0x4f, 0x07, 0xa0, 0x63, 0x01, 0x12, 0xcd, 0x66, 0x22, 0x31, 0x27, 0xdd, 0x93, 0xf0, 0xf8, 0xc0, 0x02, + 0x07, 0x98, 0x8a, 0xff, 0x53, 0x78, 0x33, 0xb0, 0x41, 0xa3, 0x44, 0x5f, 0xa3, 0xab, 0xda, 0xdc, 0xe8, 0x78, 0xe9, + 0x29, 0x24, 0xb2, 0x82, 0x55, 0x73, 0x5f, 0x6e, 0xe0, 0xb4, 0x87, 0x9a, 0x43, 0x65, 0x01, 0xfe, 0xf6, 0x0b, 0x30, + 0x78, 0x64, 0x50, 0xd8, 0x6e, 0x2d, 0xb4, 0x37, 0x66, 0xa9, 0x86, 0x8a, 0x70, 0xd0, 0xf9, 0x4a, 0xcc, 0xea, 0x11, + 0xfd, 0x3d, 0x3f, 0x1c, 0x56, 0x04, 0x06, 0x1c, 0x96, 0x32, 0x13, 0x2d, 0x14, 0x4b, 0xeb, 0x6c, 0x46, 0x75, 0xe0, + 0x81, 0x89, 0x39, 0x0b, 0x77, 0x00, 0xda, 0xa4, 0x56, 0x81, 0x5e, 0x45, 0xf4, 0x13, 0xf7, 0x6b, 0xfb, 0xf5, 0x7a, + 0x64, 0x96, 0x8e, 0xdc, 0x18, 0x0b, 0x00, 0x0e, 0x3c, 0xaf, 0x49, 0x9e, 0x93, 0xaf, 0xa1, 0xdd, 0x93, 0x0b, 0xf9, + 0x13, 0x94, 0x2d, 0x3c, 0x57, 0x4d, 0x2b, 0x8b, 0x15, 0x57, 0xd5, 0xab, 0x0b, 0x5e, 0x99, 0x4c, 0xab, 0xb4, 0x12, + 0x95, 0x12, 0x0c, 0xa8, 0x4b, 0xbc, 0xd6, 0x34, 0xa3, 0xd4, 0x46, 0x9d, 0x89, 0x1a, 0xb0, 0xc1, 0x7e, 0xaa, 0x36, + 0x3a, 0x39, 0x97, 0xcf, 0x2f, 0x8d, 0xc3, 0xa7, 0x5d, 0xbd, 0x99, 0xa9, 0x1c, 0xf8, 0x6b, 0xe5, 0x43, 0xab, 0xc7, + 0x40, 0x07, 0xe4, 0xf4, 0xc7, 0xb0, 0x98, 0xd8, 0x1d, 0x9a, 0xb7, 0xbb, 0xcb, 0xea, 0x22, 0xbd, 0xd3, 0x94, 0xcc, + 0xea, 0x2d, 0x9f, 0x59, 0x3d, 0x3a, 0xe0, 0xc5, 0x43, 0xbd, 0x57, 0x98, 0x49, 0x04, 0x17, 0x43, 0x35, 0x89, 0xec, + 0x0e, 0xb4, 0xe6, 0x51, 0xc5, 0x04, 0xf8, 0x41, 0xa9, 0x35, 0xbd, 0xb7, 0xbb, 0x42, 0x9d, 0x52, 0x78, 0xdc, 0x5a, + 0xf2, 0x03, 0x73, 0xa7, 0x5d, 0xeb, 0x7c, 0x3c, 0xbf, 0xf4, 0xfd, 0x46, 0x9e, 0xd0, 0x66, 0x67, 0x72, 0xfa, 0x27, + 0x6f, 0xf5, 0x0f, 0x53, 0x7d, 0x0b, 0xdd, 0x09, 0xfa, 0x0c, 0x5d, 0x55, 0xdd, 0x95, 0xd8, 0xc2, 0x50, 0x4f, 0x2c, + 0xf2, 0x42, 0x9e, 0xb4, 0xc6, 0x8e, 0x83, 0xbd, 0x01, 0x4e, 0xfc, 0xf2, 0x70, 0x10, 0x57, 0xb9, 0xcf, 0xce, 0xbb, + 0x46, 0x56, 0x0e, 0x60, 0x05, 0x51, 0x30, 0x6e, 0xcd, 0xc7, 0x36, 0x48, 0x97, 0xb8, 0x1a, 0x1f, 0xbf, 0xa1, 0x58, + 0x26, 0x9b, 0x88, 0x8b, 0x8b, 0xfc, 0xf1, 0x53, 0x20, 0x2d, 0xeb, 0xf7, 0xa3, 0x67, 0x97, 0xd3, 0xa7, 0xc3, 0x28, + 0x00, 0xc7, 0x2e, 0x7b, 0x79, 0x19, 0xf3, 0xd5, 0x25, 0xb3, 0x4c, 0x61, 0x91, 0x6f, 0x06, 0x54, 0x97, 0xac, 0x96, + 0xae, 0x57, 0x80, 0xa5, 0xcb, 0x6f, 0xee, 0xc3, 0xd4, 0x80, 0x46, 0xd6, 0xdc, 0x9d, 0xe6, 0x5a, 0xa0, 0xd4, 0xf3, + 0x7e, 0x66, 0xc8, 0xd7, 0x65, 0xd0, 0x15, 0xa4, 0x7b, 0x1e, 0x91, 0x5e, 0xee, 0xa5, 0xd3, 0xfd, 0xbe, 0x14, 0x60, + 0xa9, 0x2f, 0xc5, 0x17, 0x50, 0x58, 0x34, 0xbe, 0x11, 0xa0, 0xad, 0xa1, 0x9a, 0xf6, 0x4a, 0x51, 0xf5, 0x82, 0x5e, + 0x29, 0xbe, 0xf4, 0xf4, 0x50, 0x99, 0x2f, 0x4b, 0x47, 0xff, 0x13, 0x6a, 0x2e, 0x38, 0x21, 0x66, 0x62, 0x0e, 0xa0, + 0x12, 0xb4, 0xf1, 0xdd, 0x1e, 0x6d, 0x7c, 0xaa, 0x57, 0x71, 0xd3, 0xe7, 0xb5, 0xb5, 0xcc, 0x09, 0x61, 0xd3, 0xbd, + 0x04, 0xa8, 0xc8, 0x2b, 0xe1, 0x11, 0x2c, 0xbf, 0xfc, 0x21, 0x4f, 0x57, 0x88, 0xd6, 0x71, 0xcf, 0x32, 0x97, 0xc6, + 0xfe, 0x95, 0xc1, 0xf4, 0xf5, 0xed, 0xb6, 0xc8, 0x4f, 0x4d, 0x4c, 0x58, 0x8f, 0x15, 0x7d, 0xf3, 0x2e, 0x5c, 0x09, + 0x14, 0x38, 0x94, 0x48, 0x6c, 0x53, 0x85, 0x22, 0x1e, 0x24, 0x7d, 0xba, 0x68, 0x7d, 0x1a, 0x60, 0x6a, 0x2d, 0x07, + 0xe6, 0x10, 0xae, 0xe2, 0xc2, 0x47, 0x4f, 0xdf, 0x62, 0x16, 0xce, 0x27, 0xde, 0x47, 0xaf, 0x18, 0x99, 0x8f, 0xfb, + 0xa8, 0x54, 0xd2, 0x3f, 0x0f, 0x87, 0x59, 0x35, 0xf7, 0x1d, 0xfa, 0x48, 0x0f, 0x55, 0x2e, 0x28, 0x7b, 0x63, 0x4c, + 0x22, 0x50, 0x1a, 0xe3, 0x7d, 0x1c, 0x1c, 0xe7, 0x7d, 0x1a, 0x40, 0x6a, 0x9f, 0x78, 0x4f, 0x4a, 0x0e, 0xcf, 0x39, + 0xe6, 0x84, 0xd2, 0x8a, 0x80, 0x09, 0x3d, 0x43, 0xb9, 0xee, 0x94, 0x82, 0x49, 0x0e, 0x09, 0x86, 0xbf, 0x6a, 0xde, + 0xc4, 0x0a, 0x84, 0x5d, 0x33, 0xaf, 0x46, 0x8f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x1e, + 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, + 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, + 0xfd, 0x06, 0xc7, 0x7c, 0x56, 0x72, 0xd7, 0x3b, 0x9c, 0x85, 0x96, 0x90, 0x27, 0x77, 0x0c, 0xd2, 0x34, 0x96, 0x46, + 0xc0, 0x89, 0x48, 0xb6, 0xb1, 0x14, 0x8e, 0x00, 0x02, 0x02, 0xdd, 0x94, 0x19, 0xc6, 0x74, 0x30, 0xf2, 0x3c, 0xea, + 0x19, 0xef, 0x55, 0x78, 0x0a, 0x69, 0xb2, 0x7d, 0x3d, 0x7f, 0x6f, 0x04, 0x59, 0xb9, 0xe5, 0x1c, 0x0f, 0x8b, 0x6f, + 0x9c, 0x7d, 0x95, 0x93, 0xa7, 0x98, 0x65, 0xa4, 0x77, 0x8a, 0x79, 0x01, 0x7f, 0x2a, 0x4b, 0x7d, 0x8e, 0xd2, 0x5b, + 0xe6, 0x93, 0x55, 0x24, 0x5d, 0x78, 0x9b, 0x7e, 0x3f, 0x1e, 0xa9, 0x43, 0xcd, 0xdf, 0xc7, 0x23, 0x79, 0x86, 0x6d, + 0x58, 0xc2, 0x42, 0xab, 0x60, 0x0c, 0x20, 0x89, 0x8d, 0x88, 0x06, 0xa3, 0xbd, 0x39, 0x1c, 0xce, 0x37, 0xe6, 0x2c, + 0xd9, 0x83, 0xeb, 0x2b, 0x4f, 0xcc, 0x3b, 0xf0, 0x65, 0x1e, 0x13, 0x44, 0x6c, 0xe6, 0x6d, 0x58, 0x0d, 0x1e, 0xec, + 0xe0, 0xfa, 0x88, 0x2d, 0x8a, 0xb5, 0x8e, 0xa5, 0xb2, 0x0e, 0x4e, 0xeb, 0xd8, 0x34, 0x23, 0xa5, 0xc8, 0x3e, 0xc7, + 0xfe, 0xde, 0x0d, 0xae, 0xae, 0x8d, 0x41, 0xad, 0x71, 0x87, 0xb9, 0x73, 0x2a, 0xa0, 0x1e, 0xd3, 0x15, 0x54, 0xcf, + 0x2a, 0xf2, 0xe5, 0xb7, 0x76, 0x0e, 0x08, 0x1a, 0x81, 0xc0, 0x45, 0x03, 0x25, 0xd3, 0xa5, 0x9c, 0x77, 0x01, 0x21, + 0xbe, 0x4b, 0x41, 0x9f, 0xce, 0x60, 0x13, 0x9b, 0x4f, 0x20, 0x16, 0x4d, 0xf7, 0xb9, 0xd6, 0xcc, 0x17, 0x23, 0xda, + 0x99, 0x75, 0xb7, 0xc8, 0xad, 0x16, 0x22, 0x19, 0x3d, 0xdb, 0x4c, 0xb8, 0xeb, 0x50, 0xce, 0x48, 0xc0, 0x04, 0xad, + 0xad, 0x94, 0x7c, 0xae, 0x7b, 0x9d, 0xa0, 0x3d, 0x90, 0xb4, 0xee, 0xdf, 0x2c, 0x3a, 0xa3, 0xe4, 0xe4, 0x7a, 0x93, + 0x33, 0x48, 0xc1, 0x82, 0xed, 0x65, 0x4e, 0xb8, 0x01, 0x3e, 0xb2, 0x59, 0x72, 0x9a, 0x06, 0x79, 0x2c, 0x0c, 0xd2, + 0x47, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, + 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, + 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, 0x98, 0x07, 0xb6, 0xb6, 0x71, 0x4d, 0x60, 0xa0, 0x53, 0xfb, 0x5a, 0x94, 0x73, + 0xac, 0x22, 0x7a, 0x9f, 0x7f, 0xa8, 0xec, 0xe9, 0x83, 0x08, 0x1b, 0x15, 0x68, 0x2c, 0x25, 0xc6, 0x46, 0x8e, 0x7f, + 0x4b, 0x94, 0x0d, 0x19, 0x02, 0x42, 0x48, 0x1b, 0x39, 0xfd, 0xb0, 0xbe, 0x7c, 0x97, 0x69, 0xff, 0x4f, 0x12, 0xbf, + 0x0d, 0xf6, 0x72, 0xea, 0x4f, 0x3d, 0xe2, 0xf1, 0x5a, 0xa3, 0xc7, 0x94, 0x74, 0x1b, 0xe4, 0xa9, 0xf2, 0x14, 0x24, + 0x13, 0xc6, 0x02, 0x82, 0x45, 0xb9, 0xe0, 0x39, 0xaf, 0xb8, 0x84, 0xfb, 0xa8, 0x65, 0x45, 0x84, 0xaa, 0x44, 0x4e, + 0x9f, 0xaf, 0x80, 0x67, 0x02, 0x02, 0x1d, 0x63, 0xa4, 0x51, 0x05, 0x5f, 0x02, 0x63, 0x1d, 0x28, 0x3b, 0xcd, 0x48, + 0x70, 0xd9, 0xfd, 0x84, 0x44, 0xa9, 0x2f, 0x49, 0x49, 0xfa, 0x56, 0xd4, 0x78, 0x25, 0x56, 0x11, 0x09, 0x64, 0xa8, + 0x21, 0x62, 0x55, 0x3d, 0x75, 0xaf, 0x8a, 0xc9, 0x60, 0x50, 0xf9, 0x72, 0x7a, 0xe2, 0x0d, 0x0d, 0x95, 0x77, 0x5d, + 0xd1, 0x4e, 0xcf, 0xb5, 0x52, 0xde, 0x42, 0x5a, 0x82, 0xa6, 0x61, 0xa4, 0x39, 0x94, 0xba, 0x92, 0xee, 0xc6, 0x20, + 0xbe, 0x64, 0xa2, 0x67, 0x3b, 0xb5, 0xa3, 0xb4, 0x25, 0xed, 0x21, 0xa4, 0xe7, 0x2e, 0xf9, 0x98, 0x85, 0x5c, 0xdd, + 0x29, 0x27, 0xe5, 0x55, 0x88, 0x4e, 0xee, 0x7b, 0x0c, 0x89, 0x40, 0x9f, 0x73, 0x0c, 0xeb, 0xa2, 0xa1, 0xce, 0x61, + 0x85, 0x98, 0x2d, 0x94, 0x30, 0x5f, 0x32, 0x9e, 0x4a, 0x06, 0x0d, 0x80, 0x0c, 0xf8, 0xe2, 0x65, 0x60, 0xf9, 0x2b, + 0x88, 0x1f, 0x6d, 0x7c, 0x38, 0xfc, 0x55, 0x53, 0x88, 0xed, 0x5f, 0xb0, 0x19, 0xc2, 0xa3, 0x7a, 0xc0, 0x33, 0xdf, + 0xc4, 0x09, 0x5a, 0x01, 0x49, 0x99, 0x1d, 0x4d, 0x64, 0xaf, 0x7a, 0x08, 0xa7, 0xb2, 0x02, 0x75, 0x94, 0x75, 0x56, + 0xc2, 0x8f, 0x30, 0xd5, 0xad, 0xc4, 0x5a, 0xa0, 0xcd, 0xd5, 0x8a, 0xb5, 0x00, 0x0e, 0xfc, 0x1c, 0x82, 0x27, 0xf2, + 0x39, 0xb8, 0x18, 0x14, 0xe0, 0x73, 0x00, 0xbc, 0xc8, 0x5d, 0x78, 0x30, 0x0f, 0x2c, 0xab, 0x11, 0x86, 0xa3, 0x8a, + 0x58, 0xbf, 0x66, 0x3b, 0xf2, 0x81, 0xdb, 0x31, 0x3e, 0xd7, 0x1e, 0x4b, 0x96, 0x83, 0x51, 0xe6, 0x5e, 0x2d, 0xd1, + 0xf3, 0x26, 0x8d, 0x9b, 0xd1, 0xa3, 0x7d, 0x2d, 0xff, 0x17, 0xf4, 0x32, 0xe8, 0x6f, 0xe1, 0x96, 0xd7, 0xfc, 0x61, + 0xb9, 0x70, 0x9a, 0x5e, 0x41, 0xa4, 0x8c, 0x1a, 0x91, 0x31, 0x84, 0x4d, 0xaa, 0x9b, 0xdb, 0xa4, 0xba, 0x10, 0xf0, + 0x74, 0x44, 0xaa, 0x6b, 0x21, 0x6d, 0xe4, 0xd3, 0x3a, 0x90, 0xb1, 0x48, 0xef, 0x7e, 0xfc, 0xdb, 0xf3, 0xcf, 0xaf, + 0x7f, 0xfd, 0xf1, 0xe6, 0xf5, 0xbb, 0x57, 0xaf, 0xdf, 0xbd, 0xfe, 0xfc, 0x3b, 0x41, 0x78, 0x4c, 0x85, 0xca, 0xf0, + 0xe1, 0xfd, 0xa7, 0xd7, 0x4e, 0x06, 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, + 0x4e, 0xc9, 0x1c, 0x33, 0x31, 0xc7, 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x85, + 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, 0x91, 0x49, 0xf3, 0xe5, 0xaf, 0x04, 0xb1, 0x4f, 0x2b, 0x29, 0xf7, 0xd5, 0xb6, + 0xe6, 0xf9, 0xf6, 0x7e, 0x2f, 0xe1, 0xfc, 0xe7, 0xd2, 0x88, 0x5a, 0x80, 0x03, 0xf0, 0x39, 0xfc, 0x71, 0xa5, 0x2d, + 0x69, 0x32, 0x8b, 0xf6, 0x33, 0x86, 0xa0, 0x4b, 0x03, 0x69, 0x62, 0x8f, 0xbc, 0xd4, 0x27, 0x0b, 0x09, 0xdc, 0x11, + 0xc3, 0xa7, 0x15, 0x41, 0xaf, 0x18, 0x51, 0x5c, 0x72, 0x85, 0x4a, 0x29, 0xf9, 0x37, 0xca, 0x2e, 0x2a, 0xe4, 0xac, + 0x60, 0x77, 0x8a, 0x1c, 0x19, 0x3f, 0x08, 0x26, 0xbe, 0x1c, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, + 0xff, 0x33, 0xc3, 0xc0, 0xfe, 0x1c, 0x7c, 0x5e, 0x1d, 0xe6, 0xe5, 0x8d, 0x3e, 0xe5, 0x16, 0x7c, 0x3c, 0x59, 0x5c, + 0x81, 0xc1, 0x7e, 0xa1, 0x9a, 0xbb, 0xe6, 0xf5, 0x6c, 0x31, 0x67, 0xfb, 0x59, 0x34, 0x0f, 0x96, 0x6c, 0x96, 0xcd, + 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0xb7, + 0x99, 0x07, 0xbc, 0xc7, 0x4b, 0x9f, 0x6d, 0x40, 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x75, 0xe5, 0x6d, + 0x58, 0xc9, 0xce, 0xc7, 0x2c, 0xc7, 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x4b, 0xf5, 0x6c, 0xa2, 0xec, + 0x66, 0x9b, 0xd1, 0xcd, 0x5d, 0x5a, 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x0d, 0x7e, + 0xc9, 0x9a, 0x38, 0xff, 0x4c, 0xdb, 0x76, 0x55, 0x62, 0x2b, 0x68, 0x51, 0x64, 0xb5, 0xc2, 0x03, 0x73, 0xfe, 0x0c, + 0x16, 0x30, 0xf6, 0x1c, 0xe7, 0xbc, 0xf6, 0x47, 0xc8, 0x78, 0xef, 0x00, 0xa0, 0x65, 0x8e, 0x03, 0x3c, 0x62, 0xc5, + 0x28, 0x1a, 0xbc, 0xf3, 0x4b, 0x65, 0xb5, 0xd2, 0x9c, 0x84, 0xb6, 0x11, 0xab, 0x96, 0x23, 0x55, 0x33, 0x22, 0x7d, + 0x90, 0x9e, 0xf7, 0x3d, 0xa2, 0x1a, 0xec, 0xc9, 0xbc, 0x0e, 0xec, 0xd3, 0xfb, 0xd6, 0xaa, 0xee, 0xfc, 0x9e, 0x2a, + 0x5d, 0x72, 0x64, 0xcb, 0x4f, 0x97, 0xe1, 0xbd, 0xfa, 0x53, 0x72, 0x7d, 0x28, 0x70, 0x84, 0x87, 0x2a, 0xe0, 0x7c, + 0xbd, 0x12, 0xed, 0x4e, 0x84, 0x5d, 0xb9, 0x04, 0x84, 0xf8, 0x92, 0xa6, 0x39, 0x1e, 0x47, 0x34, 0x11, 0x61, 0x13, + 0xa3, 0xbf, 0xb0, 0xfb, 0x50, 0x62, 0x39, 0xcf, 0x35, 0x28, 0xb9, 0x64, 0xf0, 0x9e, 0xb4, 0xd7, 0xa0, 0x59, 0x5e, + 0x95, 0x9a, 0x4c, 0xe4, 0xa0, 0x7c, 0x38, 0x14, 0xb0, 0x97, 0x1a, 0x3f, 0x4d, 0xf8, 0x09, 0xcb, 0x5b, 0x7b, 0x6b, + 0x4a, 0x51, 0x49, 0x03, 0x54, 0xe0, 0x63, 0x06, 0xff, 0xbb, 0x33, 0xc4, 0x82, 0x29, 0x3a, 0x7e, 0x38, 0x13, 0x73, + 0xeb, 0xb9, 0x55, 0xd6, 0x51, 0xb6, 0x46, 0x39, 0x01, 0xff, 0x9e, 0xea, 0x38, 0x49, 0x84, 0x53, 0xef, 0x11, 0x17, + 0x75, 0x2f, 0x87, 0xa8, 0x1b, 0xf6, 0xb9, 0xd2, 0xc1, 0x96, 0xd3, 0x34, 0x38, 0x12, 0xbf, 0x52, 0x9f, 0x3d, 0xca, + 0x2c, 0x1e, 0x75, 0x64, 0x23, 0x4a, 0xd2, 0x38, 0x16, 0x39, 0x6c, 0xef, 0x37, 0x72, 0xff, 0xef, 0xf7, 0x21, 0x9c, + 0xb4, 0x0a, 0xe2, 0xd2, 0x13, 0x88, 0x08, 0x47, 0x87, 0x1f, 0x11, 0x9e, 0x48, 0x55, 0xe1, 0x87, 0xfa, 0xc4, 0x8d, + 0xd9, 0xbd, 0x30, 0x47, 0xf5, 0x16, 0x60, 0x18, 0xeb, 0xad, 0x45, 0x48, 0xa2, 0x95, 0x66, 0xb4, 0xf5, 0x80, 0x18, + 0xf1, 0x7e, 0x6d, 0x91, 0xc1, 0x58, 0x5b, 0x12, 0x09, 0xe0, 0x4b, 0x12, 0x32, 0xb4, 0x6d, 0x04, 0x66, 0x0c, 0x6f, + 0x67, 0xc5, 0xa5, 0xeb, 0xb0, 0xcd, 0x39, 0x7c, 0x21, 0x37, 0x9a, 0x75, 0x44, 0x69, 0x82, 0x90, 0x7f, 0xc0, 0xc9, + 0x42, 0x61, 0x34, 0x2f, 0x8f, 0xd2, 0x49, 0x62, 0x7d, 0xdf, 0x55, 0x2a, 0xd8, 0x6c, 0x3e, 0xa1, 0xbe, 0xec, 0x28, + 0xf9, 0x1a, 0x9c, 0x74, 0x9c, 0x64, 0x91, 0x83, 0xa8, 0x45, 0xe5, 0x7c, 0x4a, 0xc2, 0xd2, 0xae, 0x4e, 0xb5, 0x59, + 0xaf, 0x8b, 0xb2, 0xae, 0x5e, 0x8a, 0x48, 0xd1, 0xfb, 0xa8, 0x47, 0x8f, 0x24, 0xa4, 0x42, 0xab, 0x52, 0xbb, 0x3c, + 0x02, 0xb7, 0x4d, 0xad, 0xd8, 0x96, 0x4b, 0x58, 0xa2, 0xc6, 0x7f, 0x86, 0x3e, 0xca, 0xc5, 0xbd, 0x0c, 0xd0, 0xe8, + 0x78, 0x6a, 0xde, 0x7a, 0xe0, 0x95, 0xa3, 0xfc, 0xd2, 0x6a, 0x93, 0x7e, 0x05, 0x64, 0x46, 0xfb, 0x47, 0x4b, 0x09, + 0x64, 0x06, 0x66, 0xd2, 0xd2, 0x90, 0xc8, 0x51, 0xcc, 0xd2, 0xfc, 0x4f, 0x5c, 0xb1, 0x15, 0x22, 0x0d, 0xab, 0xb9, + 0xc7, 0x7f, 0xac, 0xbc, 0x5a, 0xae, 0x65, 0xa6, 0xb9, 0x59, 0xe2, 0x58, 0xb1, 0xb8, 0xa8, 0xd7, 0x95, 0xc8, 0x02, + 0x21, 0x8e, 0x30, 0x8d, 0xf5, 0xd4, 0x1b, 0xa5, 0xd5, 0x07, 0x24, 0x94, 0xf9, 0x11, 0x7b, 0x3b, 0xf6, 0x7a, 0x90, + 0x85, 0x38, 0xb6, 0x1c, 0x6c, 0xb6, 0xde, 0xe7, 0x32, 0x15, 0xf1, 0x59, 0x5d, 0x9c, 0x6d, 0x2a, 0x71, 0x56, 0x27, + 0xe2, 0xec, 0x07, 0xc8, 0xf9, 0xc3, 0x19, 0x15, 0x7d, 0x76, 0x9f, 0xd6, 0x49, 0xb1, 0xa9, 0xe9, 0xc9, 0x2b, 0x2c, + 0xe3, 0x87, 0x33, 0xe2, 0xaa, 0x39, 0xa3, 0x91, 0x8c, 0x47, 0x67, 0x1f, 0x32, 0x20, 0x79, 0x3d, 0x4b, 0x57, 0x30, + 0x78, 0x67, 0x61, 0x1e, 0x9f, 0x95, 0x62, 0x09, 0x16, 0xa7, 0xb2, 0xf3, 0x3d, 0xc8, 0xb0, 0x0a, 0xff, 0x14, 0x67, + 0x00, 0xed, 0x7a, 0x96, 0xd6, 0x67, 0x69, 0x75, 0x96, 0x17, 0xf5, 0x99, 0x92, 0xc2, 0x21, 0x8c, 0x1f, 0xde, 0xd3, + 0x57, 0x76, 0x79, 0x9b, 0xc5, 0x5d, 0x16, 0xf9, 0x53, 0xf4, 0x2a, 0x22, 0x26, 0x8d, 0x4a, 0x78, 0xed, 0xfe, 0xb6, + 0xb9, 0x7f, 0x78, 0xdd, 0xd8, 0xfd, 0xec, 0x8e, 0x11, 0x5d, 0x50, 0x8f, 0x57, 0x92, 0x52, 0x41, 0x01, 0x81, 0x13, + 0xcd, 0x1a, 0x0f, 0xee, 0x38, 0xe0, 0xd5, 0xc0, 0x16, 0x6c, 0xed, 0xf3, 0x67, 0xb1, 0x0c, 0xd3, 0xde, 0x04, 0xf8, + 0x57, 0xd9, 0x9b, 0xae, 0x83, 0x05, 0xde, 0xb7, 0x90, 0x6d, 0xe8, 0xf5, 0x4b, 0xfe, 0xdc, 0xcb, 0xd5, 0xdf, 0xec, + 0x9f, 0x00, 0x84, 0x01, 0x31, 0xab, 0x3e, 0x9a, 0xb8, 0x77, 0x56, 0x96, 0x9d, 0x93, 0x65, 0xd7, 0x43, 0xbf, 0x26, + 0x31, 0x2a, 0xad, 0x2c, 0xa5, 0x93, 0xa5, 0x84, 0x2c, 0xe0, 0x13, 0xa3, 0xa9, 0x8d, 0x00, 0xc2, 0x76, 0x94, 0xca, + 0x17, 0x2a, 0x2f, 0xa2, 0x70, 0x4e, 0xf0, 0x3c, 0x11, 0xa3, 0x3b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0x6d, + 0xb1, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xab, 0xa2, 0x7c, 0x1d, 0x93, 0x4f, 0xc1, 0xee, 0xe4, 0xe3, 0x12, 0x1e, 0x97, + 0x27, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf2, 0x31, 0xf8, 0x1e, 0xc9, 0x79, 0xdd, 0xf5, 0x38, 0x41, 0x6e, 0x21, 0xdd, + 0xdf, 0x8e, 0x49, 0x80, 0xe6, 0x35, 0x2c, 0x47, 0x4d, 0xc5, 0x35, 0x33, 0x63, 0x3c, 0x6f, 0xf4, 0xfe, 0xd8, 0xf1, + 0x96, 0x29, 0x14, 0xb3, 0x98, 0xd7, 0xf0, 0x7b, 0x56, 0x05, 0xea, 0xae, 0xb7, 0x49, 0x6e, 0x99, 0xd5, 0x73, 0xb4, + 0xfb, 0xbe, 0xaf, 0x13, 0x41, 0xed, 0xef, 0xb0, 0xe7, 0x99, 0xf5, 0xae, 0x8a, 0x81, 0x4b, 0x95, 0xec, 0x90, 0xa9, + 0x6a, 0x7a, 0xa0, 0x52, 0x1a, 0x3c, 0xbd, 0xb4, 0x2e, 0x5f, 0x2a, 0x6d, 0xe4, 0x99, 0xe6, 0x37, 0x80, 0x17, 0x53, + 0x97, 0xc5, 0xee, 0x9b, 0xfb, 0x0a, 0x6e, 0xe3, 0xfd, 0xfe, 0xba, 0xf2, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, + 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x3a, 0x11, 0xd1, 0x9f, 0xed, 0x72, 0x9d, 0xb9, 0x0e, 0x18, 0x51, 0xc4, 0x6f, + 0xe3, 0xd1, 0x1f, 0xa0, 0xb8, 0x36, 0xf6, 0x80, 0xb0, 0x0e, 0x09, 0x7d, 0x46, 0x00, 0x52, 0x8f, 0x3e, 0x4a, 0xee, + 0x41, 0xb3, 0xa2, 0xb9, 0x63, 0xf2, 0x73, 0x7d, 0xa5, 0xf4, 0xf7, 0xeb, 0xca, 0x23, 0x73, 0x4a, 0xdb, 0x4c, 0x63, + 0xb5, 0xa6, 0x12, 0x08, 0xaf, 0xa8, 0x64, 0x15, 0x3e, 0x9b, 0x37, 0xa2, 0xdf, 0x97, 0x47, 0x78, 0x5a, 0xfd, 0xb8, + 0xc5, 0xf8, 0x56, 0x40, 0x34, 0x12, 0xa0, 0x60, 0x05, 0x98, 0x17, 0xd9, 0xcc, 0xee, 0xe3, 0x80, 0x2a, 0x25, 0x9a, + 0xc6, 0xd9, 0x3c, 0xbf, 0xa7, 0x37, 0x65, 0x07, 0x9d, 0x3a, 0x55, 0xe0, 0x82, 0xab, 0x92, 0xf1, 0xca, 0x7a, 0x22, + 0x9f, 0xdf, 0xdc, 0x6e, 0xd2, 0x2c, 0x7e, 0x5f, 0xfe, 0x82, 0x63, 0xab, 0xeb, 0xf0, 0xc0, 0xd4, 0xe9, 0xda, 0x79, + 0xa4, 0xb5, 0x17, 0x02, 0x22, 0xda, 0x35, 0xd4, 0x7a, 0x61, 0xa1, 0x47, 0x7a, 0x22, 0x9c, 0x93, 0x44, 0x4d, 0x3b, + 0xd0, 0xd2, 0x08, 0x7d, 0x7d, 0xcd, 0xe9, 0x2f, 0x0c, 0xd6, 0x3e, 0x1f, 0x33, 0x20, 0x2b, 0xd1, 0x8f, 0xd5, 0x43, + 0x63, 0x33, 0x87, 0x9e, 0xb5, 0x2a, 0xcf, 0xbc, 0xea, 0x70, 0x40, 0x7c, 0x18, 0xfd, 0x25, 0xbf, 0xdf, 0x7f, 0x49, + 0xf3, 0x8f, 0x09, 0x35, 0x7e, 0xb6, 0x19, 0xa0, 0x6b, 0xdf, 0x95, 0x07, 0xa2, 0x9e, 0x6b, 0x95, 0x20, 0xc4, 0x1b, + 0xc4, 0x44, 0x33, 0x62, 0x0e, 0x4e, 0x3b, 0xd4, 0xfc, 0x93, 0xd4, 0x80, 0x10, 0x25, 0x5e, 0xc7, 0x94, 0x05, 0x39, + 0x6d, 0xe2, 0x48, 0x3f, 0x0a, 0x27, 0xf2, 0xa3, 0xa8, 0x8a, 0xec, 0x0e, 0x2e, 0x18, 0x4c, 0xbd, 0xa7, 0xfd, 0x12, + 0xfd, 0x96, 0x70, 0xe4, 0x1c, 0xad, 0x0a, 0x41, 0xe4, 0x84, 0xb0, 0xd6, 0x10, 0x26, 0x88, 0x0d, 0xe2, 0x65, 0xdf, + 0x25, 0x19, 0x8e, 0x14, 0x5c, 0xd6, 0xb1, 0x63, 0xcc, 0xd5, 0x51, 0xf5, 0x1a, 0xc0, 0x78, 0xe5, 0x08, 0x9a, 0x8d, + 0x22, 0xbb, 0x84, 0xa8, 0x22, 0xc7, 0x13, 0x50, 0x3b, 0x28, 0x8d, 0xcd, 0xf4, 0x7c, 0x1c, 0xe4, 0xa3, 0x9b, 0x0a, + 0x75, 0x4e, 0x2c, 0xe3, 0x35, 0x00, 0x6b, 0xe7, 0xaa, 0x9f, 0x67, 0x35, 0x78, 0xd2, 0x10, 0x9f, 0x8f, 0xd1, 0xf6, + 0xca, 0xe6, 0xa0, 0xda, 0x4e, 0x67, 0xe5, 0x15, 0xd3, 0xe5, 0xc0, 0xb8, 0x6f, 0x78, 0x45, 0x71, 0x86, 0x1f, 0x3d, + 0xd8, 0xe2, 0xfc, 0xe9, 0x86, 0xda, 0x8f, 0xb9, 0x51, 0x0f, 0x03, 0xad, 0x05, 0x6f, 0x0a, 0x62, 0xfd, 0x7d, 0xd4, + 0x91, 0xed, 0xbd, 0x16, 0x19, 0x4d, 0x3e, 0xfb, 0xf9, 0x87, 0x32, 0x5d, 0xa5, 0x70, 0x5f, 0x72, 0xb2, 0x68, 0xe6, + 0x21, 0xb0, 0x37, 0xc4, 0x70, 0x7d, 0x54, 0x78, 0x44, 0x59, 0xbf, 0x0f, 0xbf, 0xaf, 0x32, 0x30, 0xc5, 0xc0, 0x75, + 0x85, 0x60, 0x3c, 0x04, 0x82, 0x78, 0x98, 0x46, 0x27, 0x83, 0x1a, 0xb4, 0xe1, 0x1b, 0x80, 0xcc, 0x00, 0x8f, 0xcc, + 0x85, 0x47, 0xc0, 0x5d, 0xe0, 0xda, 0x93, 0xf1, 0xd8, 0x9f, 0x98, 0x86, 0x46, 0x4d, 0x69, 0xa6, 0xe7, 0xc6, 0x6f, + 0x3a, 0xaa, 0xe5, 0xda, 0xf9, 0x8f, 0x2f, 0xf9, 0x0d, 0x7a, 0x41, 0xcb, 0xcb, 0x7d, 0xa4, 0x2e, 0xf7, 0x19, 0xc5, + 0x65, 0x22, 0x39, 0x2c, 0x88, 0x65, 0x09, 0x07, 0x1e, 0xa3, 0x92, 0xc5, 0x96, 0x1e, 0xab, 0xa2, 0xe5, 0x8b, 0x72, + 0x83, 0x74, 0xe8, 0x84, 0x60, 0x89, 0x0a, 0x82, 0x25, 0x30, 0x2e, 0x62, 0xcd, 0x37, 0x83, 0x9c, 0xc5, 0xb3, 0xcd, + 0x9c, 0x23, 0x61, 0x5d, 0x72, 0x38, 0x14, 0x12, 0x6c, 0x26, 0x9b, 0xad, 0xe7, 0x6c, 0xed, 0x33, 0x50, 0x02, 0x94, + 0x32, 0x4d, 0x50, 0x9a, 0x56, 0x6c, 0xc5, 0x4d, 0x6b, 0xb0, 0x5a, 0x4d, 0xd9, 0xaa, 0xa6, 0xec, 0x9c, 0xa6, 0x1c, + 0x55, 0x50, 0x72, 0x42, 0x29, 0xca, 0x30, 0x80, 0x11, 0x9b, 0x44, 0x57, 0x19, 0xfa, 0x78, 0x27, 0x3c, 0x82, 0x2a, + 0x22, 0xf2, 0x09, 0x43, 0x08, 0x4c, 0x44, 0x71, 0xa1, 0x0a, 0xc5, 0x00, 0x19, 0x91, 0x40, 0x30, 0x51, 0xa9, 0x53, + 0x60, 0x3e, 0x9a, 0x2a, 0x86, 0x4d, 0x7b, 0xa2, 0x7c, 0x4f, 0x1d, 0xf7, 0x28, 0xdb, 0xfc, 0x2c, 0x76, 0x41, 0x88, + 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa1, 0xe6, + 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, 0x9e, 0x0c, 0x72, 0xb6, 0x00, 0x0f, 0xda, 0x39, 0xcb, + 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0xef, 0xb5, 0xb7, 0x00, 0xf9, 0x69, 0x63, 0x37, 0x0a, 0x13, 0x23, 0x48, 0xd4, 0xed, + 0xca, 0x40, 0x7e, 0xf8, 0x80, 0xd3, 0xf1, 0xd8, 0x53, 0xc6, 0xdc, 0xca, 0xf4, 0x32, 0x9d, 0x2b, 0xf9, 0x46, 0xee, + 0xa5, 0x0f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, 0x9f, 0x60, 0xbb, 0xf0, 0xda, 0x20, 0x61, 0x46, 0x80, + 0x2d, 0x8e, 0x8f, 0x91, 0x12, 0x18, 0xc2, 0x71, 0x96, 0x02, 0x30, 0x8d, 0xbe, 0xcc, 0x56, 0xf6, 0x65, 0x56, 0x6b, + 0xb6, 0x54, 0x4e, 0xf7, 0xce, 0xad, 0xdb, 0xf9, 0x5c, 0x02, 0x80, 0x49, 0x9d, 0x03, 0x71, 0x66, 0x82, 0x5d, 0x9a, + 0x44, 0x96, 0x8f, 0x61, 0xbe, 0x14, 0xaf, 0xca, 0x62, 0xa5, 0xba, 0xa2, 0xed, 0x33, 0x93, 0xcf, 0x48, 0x27, 0xa1, + 0x02, 0x0a, 0x0a, 0xb9, 0xd6, 0xa7, 0xef, 0xc2, 0x77, 0x41, 0xa1, 0x81, 0xd9, 0x2a, 0xdc, 0xd3, 0x64, 0x8d, 0xd4, + 0x1b, 0x55, 0xbf, 0x4f, 0xae, 0x81, 0x54, 0x67, 0x0e, 0x2d, 0x7b, 0x5e, 0x61, 0x80, 0xd8, 0x51, 0x9f, 0x91, 0x50, + 0x07, 0x52, 0x0f, 0x18, 0x42, 0xb4, 0x4d, 0x1f, 0x7f, 0x32, 0x24, 0xba, 0x00, 0x5b, 0x88, 0x36, 0xf0, 0xe3, 0x4f, + 0xb0, 0xcf, 0x82, 0xf0, 0x98, 0xe6, 0x6f, 0x21, 0xe9, 0xd8, 0xc0, 0x69, 0xf5, 0x29, 0xf8, 0x20, 0xc9, 0xc1, 0x44, + 0x1d, 0xbc, 0xdc, 0x5f, 0xfa, 0x7d, 0xd8, 0xb2, 0x73, 0x29, 0xd5, 0xb1, 0x52, 0x6f, 0xdb, 0xda, 0x0f, 0xa2, 0x2d, + 0x38, 0x42, 0xb0, 0x76, 0x86, 0x88, 0x60, 0x66, 0x10, 0x61, 0xd7, 0x42, 0xdd, 0xed, 0x29, 0xb5, 0x2c, 0xea, 0x6d, + 0x4f, 0x29, 0x75, 0x1b, 0x86, 0xef, 0x26, 0x98, 0x29, 0x6e, 0xf8, 0xa7, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0xf1, 0xb4, + 0x7b, 0xfe, 0x7e, 0xc1, 0xab, 0xd9, 0x46, 0x99, 0x30, 0x97, 0x7c, 0x31, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x17, + 0x6f, 0xa1, 0xe6, 0x83, 0x7f, 0x38, 0x24, 0x10, 0x6f, 0x14, 0x5f, 0x2d, 0x1b, 0xb9, 0x75, 0x4d, 0x36, 0x57, 0x25, + 0xa0, 0x7e, 0x9f, 0xaf, 0x71, 0xbf, 0xc5, 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, + 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0x37, 0xbc, 0x1c, 0x5e, 0x4e, 0x36, 0x64, 0xd2, 0xdd, 0xf8, 0xc8, 0x9d, 0x05, + 0xaa, 0xde, 0xef, 0x28, 0x4e, 0x1a, 0x24, 0x1a, 0x7b, 0x0d, 0x3e, 0xcf, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x21, 0xf9, + 0x4a, 0x0f, 0x60, 0xae, 0x42, 0x09, 0x10, 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x35, 0xd7, + 0xab, 0xe9, 0x8b, 0x57, 0xa2, 0x79, 0x1f, 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0xb7, 0xef, 0xef, 0x44, + 0xb9, 0xc8, 0xc0, 0x92, 0xad, 0xc2, 0x29, 0x2e, 0x1b, 0x75, 0x46, 0x3c, 0xcf, 0x63, 0x05, 0xd0, 0xf1, 0x90, 0x00, + 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, + 0xf9, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, 0xaa, 0x28, 0xe9, 0x53, 0xc5, 0x2c, 0x97, 0x83, 0x09, 0xec, 0xea, 0x44, + 0x86, 0x5a, 0x41, 0xde, 0xaa, 0x2b, 0x6f, 0x65, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x81, 0x9b, 0x8e, 0x35, 0x62, 0xe0, + 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0xde, 0x00, 0xc3, 0x10, 0xbf, 0xcb, 0xbc, 0xe7, 0x9e, 0x23, 0x55, 0x41, 0x32, + 0xdb, 0x66, 0x9e, 0xba, 0x88, 0xea, 0x2b, 0xa7, 0x96, 0xce, 0x9c, 0x7e, 0x04, 0xf0, 0x1e, 0x53, 0x93, 0x86, 0x7c, + 0x84, 0xdb, 0x52, 0x7c, 0xbd, 0x55, 0xd7, 0x78, 0x69, 0x74, 0xee, 0x5e, 0xbe, 0x74, 0xa7, 0x41, 0x3f, 0x05, 0x41, + 0x39, 0x9f, 0x97, 0x02, 0xf6, 0x94, 0xd9, 0x5c, 0xaf, 0x56, 0xad, 0xd0, 0x3a, 0x1c, 0xc6, 0xda, 0x51, 0x48, 0xab, + 0xb3, 0x80, 0xad, 0x46, 0x3a, 0x25, 0x40, 0x08, 0x8e, 0xd3, 0xb0, 0x13, 0x8c, 0xbb, 0x74, 0x1a, 0x91, 0xf5, 0x4a, + 0x49, 0xba, 0x30, 0x83, 0xe4, 0x9f, 0xe4, 0xf5, 0x0c, 0x68, 0x09, 0xe0, 0x50, 0xc4, 0x12, 0x1e, 0x4e, 0x92, 0x2b, + 0x80, 0x4e, 0x87, 0x83, 0x4a, 0x43, 0x73, 0x56, 0xb3, 0x64, 0x3e, 0x89, 0xa5, 0xaa, 0xf2, 0x70, 0xf0, 0x94, 0x9b, + 0x41, 0xbf, 0x9f, 0x4d, 0x4b, 0xe5, 0x02, 0x10, 0xc4, 0xba, 0x30, 0x40, 0x3c, 0xd2, 0xc2, 0x93, 0x45, 0x9f, 0x92, + 0xf8, 0xe5, 0x2c, 0x99, 0x9b, 0x6c, 0x78, 0x07, 0x46, 0xb0, 0x19, 0xd7, 0x25, 0x65, 0xda, 0xa3, 0xf2, 0x7b, 0x46, + 0x4f, 0x6d, 0x5f, 0x6b, 0xb5, 0x45, 0xac, 0xeb, 0xe0, 0xaa, 0x44, 0x3d, 0xc5, 0x07, 0x25, 0x09, 0xde, 0x2f, 0x9d, + 0x9b, 0x91, 0xf2, 0xb5, 0xc8, 0xfd, 0xa0, 0x9d, 0xa9, 0x95, 0x03, 0x47, 0x20, 0xc7, 0x2a, 0x2a, 0x79, 0xbd, 0xeb, + 0x10, 0x3c, 0xba, 0x2b, 0x15, 0x28, 0x07, 0x3f, 0x03, 0x31, 0xba, 0xbe, 0xea, 0xac, 0xa1, 0x66, 0x1a, 0x55, 0x1e, + 0x41, 0xa7, 0x0e, 0xe0, 0x49, 0xc1, 0x4b, 0xad, 0x7e, 0x3c, 0x1c, 0x3c, 0xf3, 0x83, 0xbf, 0xcf, 0xf4, 0x2d, 0xc4, + 0x44, 0x39, 0xd5, 0x08, 0x89, 0x2b, 0x25, 0x89, 0xf8, 0x78, 0xd1, 0xb2, 0x62, 0x54, 0x86, 0xf7, 0xbc, 0x52, 0xe5, + 0xab, 0x53, 0x95, 0x17, 0x23, 0x6d, 0x4b, 0xe0, 0x35, 0xf9, 0x87, 0xc8, 0x35, 0x6f, 0x7d, 0xdd, 0x55, 0x86, 0x5e, + 0xcb, 0x0a, 0x74, 0x04, 0x5b, 0x59, 0x4a, 0x0e, 0xf8, 0xa4, 0xba, 0xab, 0x56, 0xad, 0xcf, 0x29, 0xdb, 0x08, 0x37, + 0xf9, 0x75, 0xec, 0xe0, 0x48, 0xf9, 0x0d, 0x9e, 0x0b, 0x60, 0xaf, 0x01, 0x7b, 0x73, 0xce, 0x8a, 0xe6, 0xc1, 0x21, + 0x6d, 0x0b, 0x34, 0x32, 0x73, 0x3b, 0x57, 0xf7, 0x6d, 0x79, 0x94, 0xc6, 0x10, 0x99, 0xf6, 0xc0, 0x74, 0xb0, 0x19, + 0xe5, 0xbf, 0xa7, 0xfc, 0x56, 0xe1, 0x18, 0xf8, 0x76, 0xea, 0x1d, 0x40, 0xd5, 0xd3, 0x06, 0x19, 0x6b, 0x86, 0xa1, + 0x95, 0x5d, 0x2e, 0x85, 0x96, 0xa0, 0xa5, 0x6e, 0x82, 0xe0, 0xfc, 0x88, 0x28, 0x47, 0x00, 0xba, 0x48, 0x01, 0x13, + 0xfc, 0x94, 0xb6, 0xbb, 0xdf, 0x5f, 0xa7, 0x1e, 0xb9, 0x77, 0x85, 0xca, 0x66, 0xf9, 0x99, 0x60, 0xec, 0x27, 0x1a, + 0x33, 0xe8, 0xe8, 0x8a, 0x9c, 0xf0, 0xac, 0xd5, 0x61, 0x5d, 0x37, 0x65, 0x50, 0x16, 0xc7, 0xbc, 0x9a, 0xce, 0xfe, + 0x78, 0xb4, 0xaf, 0x1b, 0x64, 0x21, 0xff, 0x83, 0xf5, 0x90, 0x0c, 0xba, 0x07, 0xa1, 0x10, 0xbd, 0x79, 0x30, 0xc3, + 0xff, 0xd8, 0x86, 0x67, 0xdf, 0x71, 0xa3, 0x4e, 0x00, 0x73, 0xc4, 0xf5, 0xd2, 0x53, 0xb4, 0xf5, 0x70, 0x0b, 0x64, + 0x6b, 0xbc, 0xbc, 0xb5, 0xd7, 0x40, 0x4e, 0x71, 0xfc, 0x4b, 0x9e, 0xa9, 0x95, 0x0d, 0x7e, 0x7a, 0xca, 0x76, 0xe0, + 0xe1, 0x45, 0x08, 0x28, 0x86, 0x65, 0xe3, 0x97, 0x96, 0xe3, 0x8c, 0xfe, 0x9b, 0x47, 0x0c, 0x83, 0x45, 0xe4, 0xc7, + 0x17, 0xa5, 0x10, 0x5f, 0x85, 0xf7, 0xb9, 0xf2, 0x96, 0xe4, 0x94, 0xb9, 0xd4, 0xc3, 0xe8, 0xba, 0x24, 0x7d, 0x97, + 0x7c, 0x6c, 0x0d, 0xdb, 0x1f, 0xda, 0xfd, 0x66, 0x88, 0x20, 0x84, 0x72, 0xfc, 0x9c, 0xd1, 0x09, 0x8d, 0x0f, 0xab, + 0xd9, 0xe9, 0xf5, 0x7b, 0xe7, 0x78, 0xc1, 0xd6, 0x68, 0x80, 0xc7, 0x43, 0x17, 0xf3, 0x44, 0x0d, 0x9d, 0xae, 0x6b, + 0xe7, 0xe0, 0x81, 0x41, 0x96, 0x27, 0xdf, 0x31, 0x2c, 0xb1, 0x3f, 0x89, 0x78, 0xd2, 0x56, 0x6d, 0x6c, 0x8e, 0x54, + 0x1b, 0x35, 0x03, 0x3f, 0x78, 0x05, 0x05, 0x46, 0x17, 0xa4, 0x5b, 0x30, 0x0e, 0x47, 0x00, 0xb2, 0x62, 0x1c, 0x8f, + 0x0c, 0x26, 0x30, 0xa4, 0x1b, 0x8a, 0x02, 0xf0, 0xf0, 0x38, 0x1e, 0x84, 0x0c, 0x20, 0x5d, 0xf0, 0xd0, 0xb0, 0x4d, + 0x42, 0xca, 0xcf, 0xf3, 0xbc, 0x56, 0x43, 0xe8, 0x3b, 0x0b, 0xd5, 0xb1, 0x1f, 0x69, 0xaf, 0x58, 0xd7, 0xaa, 0x74, + 0x64, 0xab, 0x03, 0xf4, 0x0d, 0x19, 0xf8, 0xd6, 0xb1, 0x05, 0x40, 0xb4, 0xc4, 0xef, 0xa9, 0x57, 0xfb, 0x32, 0x66, + 0x85, 0x7a, 0xfd, 0xc6, 0xb4, 0xeb, 0xa5, 0xb4, 0x28, 0xa0, 0xe2, 0xb6, 0x55, 0xdb, 0x23, 0x39, 0xff, 0xe1, 0x5d, + 0x47, 0x3b, 0x3e, 0x3b, 0x35, 0xb6, 0x84, 0x32, 0xb7, 0x78, 0x22, 0xab, 0xa3, 0x2d, 0xd5, 0xa9, 0x3e, 0xe0, 0x52, + 0x93, 0xea, 0xcc, 0xc0, 0xf0, 0x1a, 0x01, 0xca, 0x2d, 0x44, 0xd2, 0x38, 0xec, 0x9d, 0x4f, 0x06, 0x05, 0x73, 0x8b, + 0x04, 0x24, 0xb0, 0x8d, 0xad, 0x5d, 0x34, 0xd7, 0xaf, 0xdf, 0x53, 0xaf, 0x6a, 0x53, 0xd5, 0x83, 0x37, 0x5e, 0xe0, + 0xec, 0x9d, 0xd6, 0x02, 0x02, 0x28, 0x6c, 0x2d, 0xcb, 0xc1, 0xb9, 0xdb, 0x55, 0x2d, 0x15, 0x65, 0xd4, 0xef, 0x9f, + 0xff, 0x9e, 0xa2, 0x22, 0xf6, 0x54, 0x71, 0xca, 0xfa, 0xed, 0x96, 0x79, 0x53, 0x59, 0xf2, 0x06, 0x55, 0xb4, 0x56, + 0x47, 0x4d, 0xe5, 0xba, 0xb9, 0x6a, 0xc9, 0x04, 0x31, 0xba, 0x4f, 0xd7, 0x3a, 0x77, 0xea, 0xbd, 0x57, 0x71, 0xc4, + 0x40, 0x70, 0xd3, 0x3d, 0x3e, 0x38, 0x08, 0x8d, 0x8a, 0x72, 0xc1, 0x8d, 0xd2, 0xaa, 0x92, 0x52, 0xc8, 0x5b, 0x15, + 0xcd, 0x99, 0x3e, 0x02, 0x20, 0x02, 0xac, 0x12, 0xf5, 0xbf, 0xf9, 0xd2, 0x18, 0x0f, 0x1e, 0xf8, 0x9a, 0x5c, 0xc7, + 0xd6, 0xfb, 0xa7, 0x35, 0xd2, 0x6a, 0xe3, 0x98, 0xd4, 0xaa, 0x97, 0xad, 0xe2, 0x65, 0xf7, 0x3a, 0x15, 0x83, 0xe7, + 0xff, 0x73, 0x1f, 0xa0, 0x46, 0xb4, 0x94, 0xc1, 0xad, 0xab, 0x01, 0x1a, 0x1f, 0x8e, 0x85, 0x6f, 0xfc, 0x90, 0x71, + 0x3e, 0x98, 0xa1, 0xa3, 0xda, 0x1c, 0x1c, 0x10, 0x1c, 0xd5, 0x3d, 0x1a, 0x13, 0x66, 0xe1, 0xdc, 0x83, 0x40, 0xf5, + 0x89, 0xfb, 0x8c, 0x6b, 0x2f, 0x68, 0x13, 0xf8, 0x64, 0x5d, 0xd7, 0x14, 0x01, 0x2e, 0x62, 0x63, 0x22, 0x86, 0xb8, + 0x6c, 0x12, 0xa9, 0x6f, 0xc6, 0xa0, 0x00, 0x28, 0x9e, 0x55, 0x24, 0x97, 0xde, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, + 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, + 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, + 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, 0x19, 0x7f, 0x46, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, + 0x9e, 0xc3, 0x67, 0xbc, 0x9c, 0x84, 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, + 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, + 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, + 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, + 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, + 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, + 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, + 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x9b, 0x22, 0x87, 0xc5, 0xf8, 0x61, 0x83, + 0x91, 0xc6, 0x6a, 0x0d, 0x86, 0xe5, 0x12, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, + 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, + 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x22, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, + 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, + 0x9d, 0xe4, 0xed, 0x12, 0x8e, 0xba, 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, + 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, 0xf7, 0xa1, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, + 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, + 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, + 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, + 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0x67, 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, + 0xf3, 0x9a, 0x5d, 0x3f, 0x11, 0x6c, 0xc7, 0x76, 0x4f, 0x10, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, + 0x2f, 0x2c, 0xf9, 0x02, 0xc0, 0x03, 0x59, 0x0c, 0x28, 0x3e, 0x0b, 0xef, 0x17, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, + 0xbd, 0x77, 0x94, 0x7a, 0x03, 0x7f, 0x0e, 0x28, 0x7d, 0x92, 0x73, 0x6f, 0x39, 0xbc, 0xf5, 0x2f, 0x9e, 0x82, 0xf3, + 0xc4, 0x6a, 0x78, 0x03, 0x7f, 0x15, 0x7c, 0xe8, 0x2d, 0x07, 0x98, 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, + 0x85, 0xc4, 0xd8, 0x87, 0xdf, 0x82, 0x9c, 0xe1, 0x1f, 0xbf, 0x6b, 0x0c, 0xd6, 0xdf, 0x82, 0x42, 0xa3, 0xb1, 0x96, + 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x01, 0xdf, + 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, + 0x1d, 0x69, 0xbf, 0x2b, 0xd7, 0x60, 0xc7, 0xeb, 0xe4, 0xc8, 0x52, 0x78, 0xd6, 0x61, 0xe7, 0xa5, 0x53, 0xa2, 0xc3, + 0x30, 0xde, 0x6d, 0xd5, 0x33, 0x86, 0xf2, 0xdc, 0x60, 0x4c, 0x17, 0x3c, 0xe2, 0xcf, 0x06, 0xb9, 0x0c, 0x8d, 0x79, + 0x84, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, + 0x1a, 0xfc, 0x5e, 0x7b, 0x39, 0xf0, 0x1e, 0x44, 0x7e, 0x23, 0x5d, 0xca, 0x25, 0x36, 0x3a, 0x71, 0x2c, 0x0b, 0xed, + 0x3c, 0xae, 0xbf, 0x8e, 0x41, 0xfd, 0x5e, 0xe9, 0x37, 0x28, 0x67, 0x7f, 0x94, 0xac, 0xd3, 0xc6, 0x13, 0xe3, 0x5f, + 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, 0x5f, 0xa7, 0x65, 0xb4, 0x59, 0x2d, 0x44, 0x29, + 0xf2, 0x48, 0x9c, 0x7c, 0x2d, 0xb2, 0x73, 0xf9, 0xce, 0xa7, 0xd0, 0x2f, 0x00, 0x2d, 0xfb, 0x04, 0x19, 0xfd, 0x2b, + 0x13, 0x7c, 0xf8, 0xab, 0x76, 0xae, 0xcd, 0xf9, 0x78, 0x92, 0x5f, 0x59, 0x7b, 0xb7, 0xe3, 0x45, 0x62, 0x14, 0x63, + 0xb9, 0xaf, 0xba, 0x59, 0x39, 0x51, 0xc9, 0x81, 0x91, 0xae, 0xc9, 0x5e, 0xae, 0x64, 0xdd, 0x4e, 0xb7, 0x12, 0x88, + 0xa8, 0x02, 0xef, 0x31, 0xae, 0x62, 0x1f, 0xc1, 0x74, 0xdd, 0x71, 0x19, 0xed, 0x78, 0xcf, 0x78, 0x75, 0xa2, 0xac, + 0xe0, 0x76, 0x23, 0xda, 0x13, 0x3a, 0xfa, 0x69, 0x52, 0x5b, 0x16, 0x0e, 0x40, 0xee, 0x12, 0xc6, 0xb2, 0x21, 0x58, + 0x31, 0x28, 0x7d, 0xbd, 0xa6, 0x64, 0x59, 0x80, 0x45, 0x67, 0x97, 0x11, 0x88, 0x61, 0xdd, 0x34, 0x27, 0x74, 0xbc, + 0x74, 0x71, 0xde, 0x6b, 0x15, 0x29, 0x78, 0x46, 0x8b, 0x8e, 0xb9, 0xe9, 0x48, 0x37, 0x46, 0x7b, 0xfb, 0xc2, 0x20, + 0xa4, 0x78, 0xfe, 0xc0, 0x56, 0xeb, 0xe2, 0x22, 0xf1, 0x0a, 0x99, 0x68, 0x41, 0x2c, 0x45, 0x60, 0xc6, 0x0b, 0x4d, + 0x23, 0x4c, 0x50, 0xa6, 0x04, 0x8b, 0xd6, 0xe8, 0xd0, 0xfe, 0xb0, 0x84, 0xdd, 0x63, 0x8c, 0x00, 0x81, 0x2a, 0xd3, + 0x8b, 0xb0, 0x35, 0x61, 0x36, 0x75, 0xb1, 0x01, 0xda, 0x2a, 0x86, 0x06, 0x61, 0x6d, 0x88, 0xf9, 0x98, 0xe6, 0xcb, + 0x7f, 0x62, 0x31, 0xb6, 0x27, 0x10, 0xdb, 0xbb, 0x5d, 0x93, 0x30, 0xdd, 0x6b, 0x71, 0x63, 0xbd, 0xdc, 0x9e, 0x72, + 0x4c, 0xed, 0x58, 0x1b, 0xb5, 0x63, 0x2d, 0xf4, 0x8e, 0xb5, 0xd6, 0x3b, 0xd6, 0xb2, 0xe1, 0x1f, 0x32, 0x2f, 0x66, + 0x09, 0xe8, 0x77, 0x57, 0x5c, 0x35, 0x08, 0x9a, 0xb1, 0x61, 0xb7, 0xf0, 0x5b, 0x62, 0xed, 0x96, 0xfe, 0xc5, 0x82, + 0xdd, 0x98, 0x3e, 0xd0, 0xad, 0x03, 0x2c, 0x23, 0x6a, 0xf2, 0x1d, 0xf2, 0x6e, 0x3a, 0x2b, 0x0a, 0xb7, 0x27, 0x76, + 0xe3, 0xb3, 0x6b, 0xf3, 0xe6, 0xdd, 0x93, 0x08, 0x72, 0xef, 0xb8, 0x77, 0x37, 0xbc, 0xf6, 0x2f, 0x74, 0x0b, 0xe4, + 0x64, 0x96, 0x33, 0x90, 0x3a, 0xe2, 0x33, 0x44, 0x2b, 0x7b, 0xca, 0x77, 0x42, 0xee, 0x6c, 0xeb, 0x27, 0x77, 0xee, + 0xb6, 0xb6, 0x7c, 0x72, 0xc7, 0xaa, 0x11, 0xc5, 0x8a, 0xd3, 0x14, 0x09, 0xb3, 0x68, 0x03, 0x3c, 0xf5, 0xf2, 0xfd, + 0x8e, 0x1d, 0x73, 0xb8, 0x7b, 0xd2, 0xd1, 0xf1, 0x72, 0x0e, 0xd8, 0xdd, 0x7f, 0xb4, 0x09, 0x1b, 0x2b, 0x5d, 0xab, + 0xd0, 0xe1, 0xee, 0x49, 0xa6, 0xf1, 0x1c, 0x8e, 0xe4, 0xd3, 0xb1, 0xc6, 0x06, 0x41, 0x5d, 0x9f, 0x33, 0xa8, 0x1d, + 0xbb, 0xaf, 0x09, 0xbb, 0xec, 0x98, 0xd7, 0xba, 0xe6, 0xed, 0x95, 0xa7, 0x62, 0x43, 0x40, 0x87, 0xaf, 0xd5, 0x0d, + 0xf2, 0x2f, 0x81, 0x53, 0x04, 0x80, 0x1c, 0x8e, 0x97, 0x3c, 0xf6, 0x7d, 0x9a, 0xa5, 0xf5, 0x0e, 0xb5, 0x16, 0x95, + 0x65, 0x19, 0xd6, 0xde, 0x0f, 0x5a, 0x31, 0x2c, 0x35, 0xfd, 0xd3, 0x71, 0xe0, 0x76, 0xb6, 0x5b, 0x19, 0xbb, 0x8c, + 0x27, 0xc5, 0xc5, 0xaf, 0xa7, 0x85, 0x72, 0xed, 0xe6, 0x6d, 0xfc, 0xa6, 0xd5, 0x92, 0xa5, 0xb5, 0x1e, 0xf2, 0xd2, + 0xb2, 0x88, 0x40, 0x00, 0xc3, 0x91, 0xb2, 0x8b, 0x25, 0xdc, 0x23, 0xac, 0xee, 0x41, 0x28, 0x99, 0x17, 0x2e, 0x9e, + 0xb2, 0x18, 0x12, 0x01, 0xb6, 0x3b, 0x54, 0x6c, 0x0b, 0x17, 0x4f, 0xd9, 0x86, 0x17, 0xfd, 0x7e, 0xa6, 0x3a, 0x85, + 0xac, 0x3b, 0x0b, 0xbe, 0x51, 0xcd, 0xb1, 0x86, 0x9a, 0xad, 0x4d, 0xb2, 0x35, 0xce, 0x6d, 0xc5, 0xc7, 0xb2, 0xad, + 0xf8, 0x58, 0x59, 0xeb, 0xd2, 0xbd, 0xde, 0xa3, 0xba, 0x00, 0xb6, 0xfe, 0xdb, 0xe3, 0x95, 0xeb, 0xf9, 0x8c, 0x00, + 0xbe, 0x6e, 0xf8, 0x78, 0x72, 0x83, 0x5e, 0x25, 0x37, 0xfe, 0xed, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x37, 0x00, 0x5d, + 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x37, 0x73, + 0xb6, 0x03, 0xa7, 0x82, 0x64, 0x60, 0x2f, 0x2b, 0xb6, 0x0b, 0x62, 0x3b, 0xe1, 0x77, 0x02, 0xa6, 0x7c, 0x0e, 0x41, + 0x5c, 0xc1, 0x2d, 0xc4, 0xe1, 0xc9, 0x3f, 0x07, 0x77, 0xad, 0xcd, 0xfa, 0x8e, 0x59, 0x9d, 0x13, 0xac, 0x99, 0xd5, + 0x83, 0xc1, 0xa2, 0x99, 0xac, 0xfa, 0x7d, 0x6f, 0xa7, 0x1d, 0x9f, 0x96, 0x52, 0x27, 0x76, 0x5a, 0xab, 0x75, 0xc3, + 0xae, 0xa5, 0xd6, 0xc5, 0x18, 0x7a, 0x80, 0xf8, 0xe9, 0x76, 0xc0, 0xef, 0x3a, 0xd6, 0x96, 0x77, 0xcd, 0x6e, 0xd8, + 0x0e, 0x2e, 0x41, 0x4d, 0x7b, 0xd9, 0x9f, 0x54, 0x2e, 0x68, 0xc7, 0x2e, 0x89, 0x87, 0x33, 0x66, 0x95, 0x32, 0xb3, + 0x4e, 0xaa, 0x2b, 0xd1, 0x19, 0xd3, 0x59, 0xeb, 0xf9, 0x5c, 0xcd, 0x27, 0x85, 0x06, 0xf5, 0x3b, 0x27, 0x3e, 0xa2, + 0xa2, 0xf3, 0x04, 0xb6, 0x96, 0x15, 0xc4, 0x6a, 0x9f, 0x83, 0xb5, 0x56, 0xbb, 0xf4, 0x7b, 0xf9, 0x80, 0xdb, 0x94, + 0xc3, 0x3a, 0x30, 0xa8, 0x39, 0xb1, 0xa2, 0x1e, 0xb2, 0x1d, 0xe3, 0xe6, 0xa7, 0x97, 0x3f, 0x38, 0x61, 0xc9, 0x8a, + 0xd5, 0xfe, 0xf4, 0xd7, 0x27, 0x9e, 0xfe, 0x4e, 0xed, 0x5f, 0x08, 0x3f, 0x18, 0xff, 0xbb, 0x76, 0x5f, 0x6b, 0x31, + 0x2a, 0x5b, 0xe5, 0x08, 0x8d, 0xbb, 0x95, 0x34, 0x59, 0x7e, 0x16, 0x9e, 0xb0, 0x16, 0x3c, 0xcb, 0xf5, 0x12, 0xcd, + 0x0a, 0x58, 0x61, 0x2d, 0x93, 0x70, 0x85, 0xb1, 0x5a, 0xda, 0xea, 0x5b, 0x34, 0xcd, 0xf1, 0xe1, 0x5c, 0x1b, 0x94, + 0x29, 0x67, 0x67, 0xc4, 0x6a, 0xb8, 0x0c, 0x4b, 0x13, 0x8a, 0x90, 0xdd, 0xdb, 0xc1, 0x8d, 0x9d, 0xb2, 0x94, 0x32, + 0x9c, 0x63, 0x30, 0xe1, 0x91, 0x18, 0x55, 0xf9, 0xfe, 0xbe, 0xa4, 0xc8, 0x69, 0x5b, 0x0e, 0xaa, 0x10, 0xf6, 0x91, + 0x44, 0x09, 0xdc, 0x8a, 0xb4, 0x50, 0xa4, 0x2c, 0xfe, 0x76, 0x80, 0x2e, 0xf0, 0x02, 0xea, 0x6a, 0xd4, 0xed, 0x0f, + 0x47, 0x3c, 0x7c, 0x60, 0xea, 0x03, 0x23, 0x96, 0x04, 0x6a, 0x7b, 0x9e, 0xa5, 0x4b, 0x50, 0xe1, 0xf7, 0x70, 0x35, + 0x11, 0xfb, 0xb9, 0x25, 0x45, 0x45, 0x36, 0xd2, 0x1b, 0x5a, 0x83, 0x47, 0x68, 0x4d, 0x79, 0xe1, 0xa4, 0xda, 0xa4, + 0xf3, 0x8e, 0x90, 0x63, 0xf5, 0xad, 0x25, 0x8c, 0x76, 0x45, 0x2f, 0xee, 0x1d, 0xbd, 0xe7, 0xe9, 0xaa, 0xe7, 0xfe, + 0xc4, 0x15, 0xf3, 0xe4, 0x36, 0x02, 0x75, 0x2b, 0xa8, 0x6e, 0xef, 0x55, 0x82, 0x05, 0x4b, 0xda, 0x7d, 0xfc, 0x76, + 0xd6, 0x0e, 0x44, 0x65, 0xac, 0xd2, 0xb7, 0x24, 0x61, 0x4f, 0x0c, 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, + 0x75, 0xcc, 0x52, 0xf4, 0xdc, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x37, + 0xc4, 0x97, 0x23, 0x3c, 0xaa, 0x6e, 0x81, 0xe3, 0xf4, 0x1d, 0xc0, 0x3f, 0x1c, 0x2e, 0x41, 0x13, 0x10, 0x0b, 0xd6, + 0x4b, 0xe3, 0x1e, 0xeb, 0xc5, 0xc5, 0x66, 0x99, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, + 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, + 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, + 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, + 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, + 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0xff, 0x31, 0x7e, 0xdc, 0x33, + 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, 0xaf, 0xff, 0x84, 0x00, 0x38, 0x3c, 0x9b, 0x7a, 0x97, 0x63, 0xc8, 0x2a, 0xcb, + 0x08, 0x24, 0x3f, 0x31, 0xf8, 0xf2, 0x05, 0x40, 0xd5, 0x67, 0xba, 0x56, 0x93, 0xa3, 0xf6, 0x98, 0x43, 0x57, 0x0c, + 0x00, 0xdb, 0xb0, 0x44, 0x55, 0x2d, 0x6c, 0xc2, 0xe2, 0xf6, 0x33, 0x8c, 0xe6, 0xb2, 0xe9, 0x05, 0x0d, 0xd4, 0x23, + 0x04, 0xbf, 0xb4, 0x1e, 0x5a, 0x6b, 0x99, 0x72, 0xe8, 0xda, 0x28, 0xaa, 0x6c, 0xa8, 0x4b, 0x58, 0xad, 0x45, 0x54, + 0x13, 0x45, 0xca, 0x25, 0xa3, 0x28, 0x96, 0x2a, 0xd8, 0x67, 0x62, 0x09, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0x7e, + 0x09, 0x08, 0x6b, 0x61, 0x2d, 0xa4, 0x33, 0xa8, 0xbd, 0xd3, 0x8f, 0x94, 0xbf, 0xbc, 0x90, 0xdb, 0xb9, 0x85, 0x22, + 0xdc, 0x9e, 0x83, 0xf2, 0xa6, 0xae, 0x4a, 0x45, 0x34, 0x5a, 0x02, 0xa5, 0xcc, 0x09, 0x22, 0x0b, 0x10, 0xc0, 0x71, + 0x03, 0x81, 0xcf, 0x6b, 0x7c, 0x02, 0x8d, 0x42, 0x20, 0x3f, 0xb0, 0x0a, 0xd7, 0x1e, 0xd2, 0x52, 0x6b, 0x44, 0x94, + 0x88, 0x1f, 0x5d, 0x3d, 0xc7, 0xf6, 0xd5, 0xd3, 0x58, 0x5b, 0x4a, 0x13, 0xc4, 0x4f, 0x2c, 0xb6, 0x10, 0x13, 0x44, + 0x75, 0x88, 0x8e, 0x60, 0x39, 0x21, 0x44, 0xe1, 0x4f, 0xa1, 0x9f, 0x1a, 0xf8, 0x4b, 0xb6, 0x28, 0xf2, 0x9a, 0x60, + 0x31, 0x2b, 0x06, 0x68, 0x55, 0x04, 0x9e, 0xe9, 0x6c, 0xa9, 0xcc, 0x69, 0x1e, 0x1d, 0xd9, 0xc1, 0x79, 0xd7, 0xc1, + 0x5e, 0xfa, 0x32, 0x76, 0xb2, 0x6c, 0x1a, 0xb5, 0xb1, 0x21, 0x12, 0x5e, 0x91, 0x5f, 0x67, 0xa9, 0x71, 0x8e, 0xcc, + 0xe5, 0xfa, 0xae, 0x8b, 0xe5, 0x92, 0xb6, 0x09, 0xab, 0x10, 0xa1, 0x6e, 0x1b, 0x2a, 0x97, 0xc2, 0x6c, 0x6c, 0x9a, + 0x06, 0xf8, 0x42, 0x51, 0xa9, 0x54, 0xa5, 0xb6, 0x52, 0xc9, 0x09, 0xef, 0xfa, 0xa6, 0x16, 0xa9, 0x2b, 0x82, 0x6d, + 0xcc, 0x50, 0x0f, 0xe5, 0x46, 0x8d, 0x7d, 0xdb, 0xb1, 0x4a, 0xef, 0x30, 0x41, 0xce, 0xc8, 0x8b, 0x1c, 0x5c, 0x94, + 0x14, 0x64, 0xae, 0x86, 0x30, 0x7f, 0xd0, 0xf0, 0x69, 0x61, 0xb9, 0x87, 0x12, 0x30, 0x3b, 0x6a, 0x78, 0x18, 0x21, + 0x10, 0x71, 0xa9, 0xec, 0x2b, 0x26, 0x7e, 0x4f, 0xc1, 0x2c, 0x99, 0xd0, 0xbd, 0x88, 0x45, 0x11, 0xda, 0xf8, 0x24, + 0x49, 0xa6, 0x9e, 0xa6, 0xe0, 0x46, 0x2e, 0xc3, 0x1c, 0x8d, 0xd0, 0x92, 0x8f, 0x1c, 0x48, 0x5f, 0xcb, 0xa9, 0x04, + 0x1f, 0x51, 0xa7, 0x80, 0xe3, 0xf9, 0x79, 0x61, 0xfd, 0x64, 0xb9, 0xc4, 0x5c, 0xd6, 0xe6, 0xbf, 0xec, 0xe8, 0x18, + 0xec, 0xf2, 0x34, 0x71, 0x5c, 0xfd, 0x47, 0x55, 0x52, 0xdc, 0xbf, 0x49, 0x73, 0x40, 0x11, 0xcc, 0xec, 0x29, 0xc6, + 0xc7, 0x3e, 0xcb, 0x14, 0xf0, 0xb7, 0xeb, 0xad, 0x25, 0x13, 0xbb, 0xa4, 0xdd, 0x5c, 0x19, 0xbf, 0xd4, 0x86, 0x1d, + 0x07, 0xe7, 0x06, 0xa0, 0x38, 0x6b, 0x74, 0x58, 0x5e, 0xeb, 0xb6, 0x55, 0xa1, 0x02, 0xb5, 0xfe, 0xf7, 0x6e, 0x61, + 0xca, 0xdb, 0xbc, 0x54, 0xde, 0xe6, 0xa1, 0x09, 0x10, 0x88, 0xcc, 0x90, 0x67, 0x4d, 0xc7, 0x24, 0x71, 0xef, 0x48, + 0x49, 0xfb, 0x8e, 0x14, 0x3f, 0x78, 0x47, 0x42, 0xbe, 0x25, 0x74, 0x64, 0x5f, 0x70, 0x72, 0x02, 0x65, 0x06, 0x7b, + 0x79, 0xcd, 0x64, 0xff, 0x80, 0xf6, 0xc2, 0xb9, 0x2c, 0xaf, 0xf8, 0x5b, 0xe1, 0xad, 0xfd, 0xe9, 0xfa, 0xb4, 0xab, + 0xea, 0xed, 0x37, 0x66, 0xe6, 0xe1, 0x50, 0x1c, 0x0e, 0x95, 0x09, 0xda, 0xbd, 0xe1, 0x62, 0x90, 0xb3, 0x3b, 0x37, + 0x3e, 0xfe, 0x9a, 0xa3, 0x88, 0xad, 0x94, 0x47, 0xd2, 0x85, 0x4a, 0x0c, 0x2f, 0x0d, 0x3c, 0xcc, 0x8e, 0x8f, 0x27, + 0xbb, 0xab, 0xbb, 0xc9, 0x60, 0xb0, 0x53, 0x7d, 0xbb, 0xe5, 0xf5, 0x6c, 0x37, 0x67, 0xf7, 0xfc, 0x76, 0xba, 0x0d, + 0xf6, 0x0d, 0x6c, 0xbb, 0xbb, 0x2b, 0x71, 0x38, 0xec, 0x9e, 0xf1, 0x1b, 0x7f, 0x7f, 0x8f, 0x80, 0xce, 0xfc, 0x7c, + 0xdc, 0xc6, 0xf8, 0x79, 0xdb, 0x76, 0xd5, 0xda, 0x01, 0x3c, 0xfd, 0x6b, 0xef, 0xed, 0x6c, 0x31, 0xf7, 0xd9, 0x07, + 0x7e, 0x0f, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, 0x7c, 0x0b, 0x0e, 0xe4, 0x3b, 0x9f, 0x7d, 0xe6, + 0xf7, 0xb3, 0xc5, 0x9c, 0x17, 0x87, 0xc3, 0xfb, 0x69, 0x88, 0x64, 0x4d, 0x61, 0x45, 0x2c, 0x29, 0x9e, 0x1f, 0x84, + 0xc7, 0xef, 0x45, 0x64, 0x88, 0xb4, 0xdc, 0xbb, 0x43, 0xf6, 0x96, 0x45, 0x7e, 0x00, 0x1f, 0x64, 0x3b, 0x7f, 0x22, + 0x6b, 0x4a, 0xf7, 0x8b, 0x0f, 0xfe, 0xe1, 0x40, 0x7f, 0x7d, 0xf6, 0x0f, 0x87, 0xf7, 0xec, 0x1e, 0xc1, 0xd1, 0xf9, + 0x0e, 0xfa, 0x47, 0xdf, 0x3a, 0xa0, 0x2a, 0xc3, 0xeb, 0xd9, 0x66, 0xee, 0x3f, 0x5b, 0xb1, 0x25, 0x70, 0xa1, 0x28, + 0x2f, 0xb4, 0xb7, 0xec, 0x1e, 0xbd, 0xce, 0xc8, 0x89, 0x68, 0xb6, 0x9b, 0xfb, 0x2c, 0xc6, 0xe7, 0xea, 0xbe, 0x98, + 0x7c, 0xf3, 0xbe, 0xb8, 0x63, 0xdb, 0xee, 0xfb, 0xa2, 0x7c, 0xd3, 0x5d, 0x3f, 0x5b, 0xb6, 0x63, 0xf7, 0x30, 0xc3, + 0xae, 0xf9, 0xdb, 0xe6, 0xd8, 0x31, 0xf6, 0x9b, 0x37, 0x46, 0x00, 0x65, 0xb6, 0x60, 0xb1, 0xe0, 0xa0, 0x54, 0xab, + 0xb6, 0x25, 0x91, 0x57, 0x3a, 0x50, 0x6d, 0x46, 0x70, 0x5f, 0x2d, 0xe4, 0xcc, 0x33, 0x03, 0x7d, 0x5b, 0x21, 0x5a, + 0x38, 0x6c, 0xc0, 0xdf, 0x68, 0xeb, 0x18, 0xc3, 0x34, 0xab, 0x99, 0xb6, 0x45, 0x5d, 0x7e, 0xdf, 0x7b, 0x26, 0xbf, + 0x91, 0x81, 0x2d, 0x44, 0x52, 0x38, 0x8e, 0x2f, 0x9e, 0x9e, 0xf0, 0x5f, 0xb5, 0x3c, 0x6a, 0xb5, 0x5f, 0x28, 0xf5, + 0xe9, 0x35, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, + 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0x56, 0xa9, 0x14, 0x68, 0xe1, 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x16, 0x66, 0x29, + 0xef, 0xb1, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, 0x44, 0x58, 0xbd, 0x65, 0x9c, 0x5f, 0x36, 0xaa, 0x70, + 0x5b, 0x80, 0xa2, 0x08, 0xca, 0x60, 0x4f, 0x72, 0xdb, 0x8d, 0x92, 0x66, 0xa3, 0xb0, 0x16, 0xcb, 0xa2, 0xdc, 0xf5, + 0x1a, 0x76, 0x83, 0x17, 0x54, 0xfd, 0x84, 0xb0, 0x2d, 0x7b, 0xd6, 0xa1, 0x5c, 0xa4, 0xff, 0x96, 0xa5, 0xe7, 0xfb, + 0xad, 0x39, 0xff, 0xd3, 0x57, 0xf4, 0x51, 0xf9, 0xef, 0x5f, 0xd2, 0x4f, 0x06, 0xcb, 0xc8, 0x29, 0xf5, 0x53, 0x34, + 0xba, 0x4d, 0x73, 0xc2, 0xd8, 0xf2, 0xf5, 0xd3, 0xef, 0x90, 0x29, 0x48, 0x0e, 0xa5, 0x54, 0xe5, 0x64, 0x0f, 0x7d, + 0xe1, 0x75, 0x1f, 0x66, 0x82, 0x01, 0x08, 0xaf, 0xd1, 0xa6, 0x9a, 0x30, 0x89, 0x07, 0x57, 0xf0, 0x7f, 0x23, 0x88, + 0x41, 0xfb, 0x44, 0x51, 0xc7, 0xb6, 0x91, 0xae, 0xdb, 0xce, 0x41, 0x72, 0xa7, 0xae, 0xfc, 0x51, 0x39, 0xf9, 0x77, + 0x34, 0x44, 0x5e, 0x71, 0x85, 0x58, 0x59, 0x70, 0x89, 0xc5, 0x50, 0x91, 0x02, 0x5c, 0x43, 0x10, 0x29, 0x8b, 0x92, + 0xc2, 0x2d, 0x07, 0x55, 0x11, 0x80, 0x71, 0xb5, 0x3a, 0xea, 0x44, 0xf8, 0xb8, 0xb5, 0x16, 0x21, 0x58, 0xd1, 0xa8, + 0x95, 0xb5, 0x02, 0x5f, 0x90, 0xbe, 0x74, 0x28, 0x88, 0xe9, 0x51, 0x48, 0x55, 0xe9, 0x50, 0x20, 0xcd, 0xa1, 0xe2, + 0x1b, 0x83, 0x8d, 0xa2, 0x22, 0x3d, 0x7f, 0x69, 0x52, 0x72, 0x69, 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, + 0x14, 0xd3, 0x02, 0xf9, 0x46, 0x8f, 0x1f, 0x04, 0x97, 0xf0, 0x6e, 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, + 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, 0x9f, 0x58, 0x02, 0xdb, 0xd1, 0x3a, 0x3a, 0xd2, + 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x8e, 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xf6, + 0x5a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, + 0xfe, 0x70, 0xf4, 0x1f, 0x4f, 0xde, 0x4d, 0x08, 0x55, 0x67, 0xc3, 0xd6, 0x3a, 0xce, 0xe5, 0x7f, 0xfd, 0xe7, 0x98, + 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, + 0x5f, 0x68, 0x9d, 0x30, 0x31, 0xb2, 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0xa5, 0xca, 0x2c, 0x20, 0xf3, 0x20, 0x9f, 0xac, + 0x8d, 0x06, 0x73, 0xc5, 0xeb, 0xd9, 0x7a, 0x2e, 0x95, 0xcf, 0x60, 0xca, 0x59, 0x0c, 0x4e, 0x96, 0xc2, 0xee, 0x48, + 0xa0, 0x68, 0xcd, 0xd0, 0xb5, 0x3f, 0xc5, 0x56, 0xbd, 0x4c, 0xab, 0x1a, 0xe0, 0x01, 0x21, 0x06, 0x86, 0xda, 0xab, + 0x85, 0x87, 0xd6, 0x02, 0x58, 0xfb, 0xa3, 0xd2, 0x0f, 0xc6, 0x93, 0x05, 0xbf, 0x41, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, + 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x1b, 0xbe, 0xf1, 0x95, 0x0f, 0xc6, 0x35, + 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, 0xee, 0x84, 0xbe, 0xfa, 0x46, 0x0b, 0xc7, 0xdf, + 0x38, 0x23, 0xd7, 0x6c, 0xd5, 0x21, 0x47, 0x34, 0x93, 0x0e, 0x21, 0x62, 0xc5, 0xd6, 0xec, 0x9a, 0x54, 0xce, 0x9d, + 0x43, 0x76, 0xfa, 0x08, 0x55, 0x7a, 0xad, 0x87, 0xb7, 0x13, 0xa5, 0xbb, 0x3d, 0xde, 0x4d, 0xbe, 0x67, 0x13, 0x11, + 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xaf, 0x6f, 0x49, + 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x70, 0xc8, 0x41, 0xa3, 0xdc, 0xfc, 0xe9, 0x15, 0xea, 0x34, 0x07, 0xe6, + 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xe3, 0x23, 0xfd, 0xbf, 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, + 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa5, 0x8e, 0x82, 0x8b, 0xbc, 0xa3, 0x16, 0xb2, 0x67, 0xd9, 0xb8, 0x51, 0xcd, 0xfb, + 0xff, 0xb5, 0x32, 0xff, 0x5f, 0xd3, 0xca, 0x30, 0x25, 0x3b, 0x96, 0x6a, 0xe6, 0x81, 0x56, 0x31, 0xcc, 0xde, 0x90, + 0x84, 0xc8, 0x70, 0x69, 0xc0, 0x8f, 0x2a, 0xd8, 0xc7, 0x69, 0xb5, 0xce, 0xc2, 0x1d, 0x2a, 0x51, 0x6f, 0xc5, 0x32, + 0xcd, 0x9f, 0xd7, 0xff, 0x12, 0x65, 0x01, 0x53, 0x7b, 0x59, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, + 0x63, 0x1b, 0xdf, 0xc8, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0xba, 0x90, 0x9c, 0xcb, 0xca, 0xe2, + 0x1e, 0xa1, 0x9b, 0x7f, 0x2c, 0xcb, 0xa2, 0xf4, 0x7a, 0x9f, 0x93, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, + 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, + 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, + 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x2a, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, + 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xab, 0x1c, + 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, + 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x58, 0xb4, 0x92, + 0xb0, 0x6f, 0xdf, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0xf3, 0x8c, 0x23, 0x49, 0x94, 0x08, 0x5e, + 0xe5, 0x8d, 0x19, 0x87, 0x1f, 0xdb, 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, + 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, + 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x37, 0x12, 0x97, + 0x10, 0x2f, 0xf3, 0xd5, 0x54, 0x44, 0xc1, 0xfb, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, + 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, + 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, + 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, + 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0x37, 0x42, 0x75, 0xb0, 0x2d, + 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, + 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, + 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, 0xf8, 0x8f, 0x99, 0x87, 0x69, 0x35, 0x2b, 0xc1, 0x9c, 0x6f, 0xa0, 0x12, 0xe3, + 0xc9, 0xe2, 0x8a, 0x6f, 0x5c, 0xac, 0xc4, 0x64, 0xb6, 0x98, 0x4f, 0xd6, 0x92, 0x6a, 0x2e, 0xf7, 0xd6, 0x2c, 0x63, + 0x0b, 0xd8, 0x3f, 0x0c, 0x0c, 0xa5, 0x03, 0x3b, 0x9a, 0x6a, 0xda, 0x24, 0xc0, 0x64, 0x3a, 0xe7, 0x7c, 0x78, 0x89, + 0x68, 0xb2, 0x3a, 0x75, 0x27, 0x53, 0xd5, 0x0e, 0xae, 0xc9, 0x99, 0x9c, 0x1e, 0xa9, 0xa7, 0x5a, 0xf7, 0x92, 0x8f, + 0xb6, 0xc3, 0x6a, 0xb4, 0xf5, 0x03, 0x70, 0xeb, 0x14, 0x76, 0xfa, 0x6e, 0x58, 0x8d, 0x76, 0xbe, 0x86, 0xdd, 0x25, + 0x85, 0x40, 0xf5, 0x57, 0x59, 0x93, 0xb9, 0x78, 0x5d, 0xdc, 0x7b, 0x05, 0x7b, 0xea, 0x0f, 0xf4, 0xaf, 0x92, 0x3d, + 0xf5, 0x6d, 0x26, 0xd7, 0xbf, 0xd2, 0xae, 0xd1, 0x98, 0xe9, 0x78, 0xed, 0x0a, 0xac, 0xd0, 0x00, 0xf9, 0x05, 0x3b, + 0xda, 0xeb, 0x1c, 0x04, 0x02, 0x74, 0x2f, 0xc1, 0x51, 0x14, 0x10, 0x35, 0xad, 0x2a, 0x8f, 0x4e, 0xf7, 0xfe, 0x1e, + 0xdf, 0x08, 0x01, 0x9b, 0x3c, 0xb5, 0xee, 0x2d, 0x63, 0xff, 0x70, 0x80, 0x10, 0x7a, 0x39, 0xfd, 0x46, 0x5b, 0x56, + 0x8f, 0x76, 0x2c, 0xf7, 0x0d, 0xa3, 0x9e, 0x82, 0x31, 0x0c, 0x5d, 0x58, 0xc5, 0x48, 0x9e, 0x01, 0x59, 0xe3, 0x37, + 0x88, 0x2e, 0x60, 0xd1, 0xeb, 0xbd, 0x3c, 0xa2, 0x41, 0x04, 0x54, 0x7a, 0x4d, 0x1a, 0x8b, 0x7c, 0xae, 0x0a, 0xd1, + 0x7b, 0x6f, 0xed, 0xbc, 0x99, 0x91, 0x2c, 0x93, 0x46, 0xaa, 0xdd, 0xca, 0x62, 0x5d, 0x79, 0xb3, 0x13, 0xd2, 0xc5, + 0x1c, 0x43, 0x65, 0xf0, 0x38, 0x00, 0xa5, 0xe7, 0x3f, 0x42, 0xaf, 0x64, 0xc8, 0x34, 0x4b, 0x34, 0xb3, 0xbb, 0xc6, + 0x9f, 0xac, 0x52, 0x2f, 0x46, 0xc4, 0x6c, 0x60, 0x0b, 0x71, 0x5b, 0x54, 0xba, 0x2d, 0x0a, 0x65, 0x8b, 0x22, 0x7d, + 0xa8, 0x9d, 0xe9, 0xce, 0x2c, 0x7c, 0x56, 0x99, 0xf6, 0x7d, 0xce, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, + 0x40, 0x85, 0x90, 0xbf, 0x46, 0x44, 0x24, 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, + 0x46, 0x79, 0xc1, 0x93, 0xa3, 0x01, 0xa9, 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xb8, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, + 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, + 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, + 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, + 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, 0xe9, 0xd9, 0xdf, 0x52, 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, + 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x59, 0xbb, 0x5c, + 0xd5, 0xbd, 0xae, 0x60, 0x01, 0x4b, 0x70, 0xb7, 0x5e, 0x9a, 0xff, 0x86, 0xdd, 0xdf, 0x0b, 0x7a, 0x69, 0xfe, 0x3b, + 0xfd, 0x49, 0x01, 0x1c, 0x80, 0xc6, 0xd4, 0x6e, 0x81, 0x87, 0x18, 0x2a, 0x28, 0xdc, 0xcd, 0xca, 0xb9, 0x57, 0x03, + 0x1c, 0x26, 0xe9, 0x1b, 0x5a, 0xbd, 0xd2, 0x62, 0xd7, 0xcb, 0x64, 0xaf, 0x00, 0x0f, 0x55, 0xc8, 0xc3, 0xc3, 0x21, + 0xea, 0x18, 0x76, 0x50, 0x47, 0xc0, 0xb0, 0x87, 0xd0, 0xd8, 0x02, 0xcf, 0xc7, 0x37, 0x19, 0xdf, 0x0b, 0x50, 0x1b, + 0x21, 0x3c, 0x5e, 0x2d, 0xca, 0x10, 0x5b, 0xf6, 0x1a, 0xa9, 0xa4, 0xde, 0x08, 0x44, 0x19, 0xad, 0x02, 0xda, 0x6a, + 0x8f, 0x59, 0x1a, 0x3f, 0x41, 0xa8, 0x58, 0xea, 0x63, 0x08, 0x0d, 0x1c, 0x7e, 0x87, 0x03, 0x48, 0xf0, 0x25, 0xd7, + 0x64, 0x73, 0xaf, 0xf3, 0x3b, 0xda, 0xe7, 0x0f, 0x87, 0xf3, 0x4b, 0x04, 0xa5, 0x4b, 0xe1, 0x23, 0x95, 0x88, 0xea, + 0x29, 0x6e, 0x4a, 0xc8, 0x66, 0xc9, 0x4a, 0x3f, 0xf8, 0x4d, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, + 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, + 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, + 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, + 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, + 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, + 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, + 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, + 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, + 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, + 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, + 0xe0, 0xcf, 0xc4, 0x68, 0x5d, 0x10, 0x20, 0xb2, 0xd9, 0xbe, 0x3e, 0x56, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, + 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0x48, 0xbc, 0xfd, 0x69, 0x90, 0x9d, + 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, + 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, + 0x47, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, + 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, + 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, + 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, + 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, 0x46, 0x69, 0xf5, 0x93, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, + 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xe5, 0x34, 0xd8, 0x61, 0xa2, + 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, + 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, + 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, + 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x5d, 0x8b, + 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0x2f, 0x8a, 0xed, 0xdb, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x27, + 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, + 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, 0x1c, 0xc7, 0x9f, 0xa0, 0x82, 0xe0, 0xbf, 0x00, 0xb3, 0x18, 0x20, 0x4f, + 0x67, 0x21, 0xe1, 0x14, 0xc2, 0xc5, 0x2a, 0xeb, 0xf7, 0xe5, 0x2f, 0xea, 0xa2, 0x8b, 0x4c, 0xd6, 0x7d, 0x12, 0x8e, + 0xcc, 0x58, 0x4e, 0xbd, 0x90, 0x3c, 0xef, 0x79, 0x32, 0x4d, 0x9e, 0xe4, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x5d, 0x98, + 0x66, 0x60, 0x95, 0x26, 0xe5, 0x47, 0x28, 0x7d, 0xf1, 0x79, 0xe5, 0x07, 0x3a, 0x7b, 0x6e, 0x92, 0xe1, 0xcd, 0xaa, + 0xf5, 0x26, 0xb5, 0xae, 0x8b, 0x07, 0xfc, 0xab, 0x33, 0xd8, 0x38, 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, + 0xc6, 0x9f, 0x65, 0xb8, 0x2e, 0x55, 0x1b, 0x7d, 0x14, 0xa2, 0x73, 0xc8, 0x54, 0x80, 0x42, 0x91, 0xf6, 0x0f, 0x4a, + 0xad, 0x4c, 0x2a, 0x6d, 0x24, 0x80, 0xee, 0x61, 0xd2, 0x60, 0x8b, 0xa1, 0x8c, 0xa5, 0x49, 0x94, 0x3b, 0x0d, 0xe2, + 0xca, 0x7e, 0xac, 0x24, 0x0e, 0x2d, 0x8b, 0xe4, 0xdf, 0xbb, 0x9e, 0xbe, 0x42, 0xea, 0x4e, 0x16, 0xc8, 0x8c, 0xf1, + 0x3c, 0x8f, 0x3f, 0x03, 0x61, 0x36, 0x68, 0xa3, 0xa2, 0x10, 0x42, 0x36, 0x88, 0x41, 0xe3, 0x79, 0x1e, 0xbf, 0x50, + 0x34, 0x1e, 0xf2, 0x51, 0xe4, 0xab, 0xbf, 0x4a, 0xfd, 0x57, 0xe8, 0x33, 0x13, 0x3c, 0x42, 0x35, 0xd1, 0xbf, 0x7b, + 0x3e, 0xbb, 0x03, 0xb5, 0x61, 0x14, 0x66, 0xa6, 0xfc, 0xca, 0x37, 0xc5, 0xd9, 0xeb, 0xaf, 0xe8, 0x2a, 0xdb, 0xba, + 0x1f, 0xbd, 0x3a, 0x22, 0xb0, 0x36, 0x46, 0x57, 0xdc, 0x18, 0x40, 0x0e, 0x93, 0xf7, 0x2b, 0x4a, 0xcb, 0x21, 0x0d, + 0x42, 0x07, 0x0d, 0x41, 0xaf, 0x24, 0xfa, 0x40, 0x62, 0x11, 0x63, 0x78, 0x21, 0x9e, 0x91, 0x9a, 0x4c, 0x34, 0xc4, + 0x2b, 0x62, 0x3f, 0x44, 0x4b, 0x4e, 0x4d, 0x74, 0x23, 0x4c, 0x31, 0x90, 0xd8, 0x19, 0x24, 0x27, 0x49, 0xad, 0xfc, + 0xe2, 0x99, 0x24, 0x2c, 0xb1, 0xf3, 0x10, 0x83, 0x49, 0x2d, 0xdd, 0xe9, 0x4d, 0x95, 0xbe, 0x1c, 0x69, 0x39, 0x68, + 0x1f, 0x80, 0x5d, 0x4a, 0x7a, 0xff, 0xa4, 0x50, 0xc4, 0x87, 0x30, 0x8e, 0x21, 0x7c, 0x8b, 0xa8, 0xae, 0xc0, 0xb9, + 0x56, 0xa0, 0xb1, 0x1a, 0x78, 0x68, 0x66, 0xd5, 0x7c, 0xc8, 0xe9, 0xa7, 0xd2, 0xf2, 0xc7, 0x88, 0xc6, 0x46, 0xeb, + 0xe6, 0x70, 0xd8, 0xd3, 0xaa, 0x97, 0xce, 0x41, 0x97, 0xcd, 0x24, 0x26, 0x6e, 0x20, 0x5d, 0x3f, 0xfa, 0xcd, 0x84, + 0xbd, 0x88, 0x0a, 0xb9, 0x14, 0x82, 0x82, 0x56, 0x07, 0x02, 0x87, 0xc2, 0x5b, 0x94, 0xf9, 0x22, 0xa6, 0x0d, 0x84, + 0xc1, 0xe7, 0x07, 0xf2, 0xf3, 0x4d, 0x41, 0x2a, 0x76, 0xac, 0x6b, 0xbf, 0xbf, 0x28, 0x3d, 0xc0, 0x93, 0x33, 0x49, + 0x9e, 0x36, 0x43, 0x58, 0x11, 0x40, 0x63, 0x56, 0x93, 0xc5, 0x09, 0x57, 0xe6, 0xf0, 0x55, 0xe5, 0x95, 0x2c, 0x65, + 0xea, 0x3c, 0xd5, 0x0b, 0x20, 0xea, 0x78, 0x83, 0x56, 0xa4, 0x7e, 0x85, 0xce, 0x5e, 0xb3, 0x12, 0x32, 0x1e, 0x9e, + 0x73, 0x9e, 0x8e, 0xee, 0x59, 0xc2, 0x23, 0xfc, 0x2b, 0x99, 0xe8, 0xc3, 0xef, 0x9e, 0xc3, 0xcd, 0x38, 0xe1, 0x91, + 0xdb, 0xec, 0x7d, 0x15, 0xae, 0xe0, 0x66, 0x5a, 0x00, 0x92, 0x5b, 0x90, 0x34, 0x01, 0x25, 0x24, 0x32, 0x21, 0xb3, + 0xa6, 0xe4, 0x8b, 0x96, 0xb6, 0xc1, 0x1a, 0x26, 0x9d, 0x07, 0xbc, 0x68, 0xf5, 0xd1, 0x6a, 0xa2, 0x5d, 0x66, 0xf9, + 0x7c, 0x88, 0x33, 0x54, 0x73, 0xdc, 0x9d, 0xc1, 0xcf, 0x01, 0xaf, 0x58, 0xd5, 0xa4, 0xa3, 0xdd, 0x80, 0x0b, 0x4f, + 0xae, 0xf3, 0x74, 0xb4, 0xc5, 0x5f, 0x72, 0x7f, 0x00, 0xe8, 0x60, 0xea, 0x12, 0xf8, 0x53, 0xb5, 0xd5, 0x54, 0xea, + 0xd7, 0xd6, 0x7e, 0x5d, 0x77, 0x56, 0x2b, 0xf7, 0xac, 0xcb, 0xd0, 0x1e, 0x19, 0x72, 0xc6, 0x0c, 0xf8, 0x73, 0xc6, + 0x92, 0x3f, 0x67, 0xac, 0xf8, 0x73, 0xc6, 0x8d, 0x91, 0x01, 0x94, 0xe0, 0x5e, 0xf2, 0x67, 0x7b, 0xc4, 0x0c, 0xb1, + 0x1a, 0x54, 0x02, 0x2b, 0x4b, 0x39, 0xf7, 0x91, 0x53, 0x4c, 0x39, 0x65, 0x78, 0xe9, 0x74, 0xe6, 0x0e, 0xe4, 0x3c, + 0x98, 0xb9, 0xc3, 0x64, 0xaf, 0xcf, 0x8d, 0x38, 0x96, 0xc6, 0xa4, 0xa8, 0x20, 0x9d, 0xd3, 0xe1, 0xe6, 0xd5, 0x71, + 0x9e, 0xb0, 0x8c, 0x8f, 0xdb, 0x67, 0x0a, 0x84, 0xd8, 0xe2, 0x19, 0x12, 0x29, 0x55, 0xb3, 0xdc, 0xe6, 0x0f, 0x87, + 0x7a, 0x74, 0xaf, 0x77, 0x7a, 0xf8, 0x95, 0xb0, 0x5f, 0x33, 0xcf, 0x3e, 0x41, 0x00, 0x93, 0x44, 0x9e, 0x49, 0x38, + 0xfa, 0xb1, 0x1c, 0xfd, 0x4d, 0xc3, 0xbf, 0x64, 0xa8, 0xee, 0x0e, 0x81, 0x89, 0x2d, 0x3b, 0x70, 0x08, 0x4e, 0x57, + 0x95, 0x48, 0xc0, 0xc1, 0x66, 0xc3, 0x22, 0xbd, 0xc7, 0x43, 0x9c, 0x0f, 0x0a, 0x1f, 0xa1, 0x61, 0x46, 0xef, 0xf7, + 0x37, 0xc2, 0xab, 0x64, 0x2b, 0x0f, 0x87, 0xc4, 0xba, 0x0b, 0x3b, 0xfa, 0x38, 0xda, 0xa3, 0x84, 0xda, 0x8f, 0x6a, + 0xbd, 0xa9, 0xd4, 0x83, 0xdc, 0xec, 0x42, 0x62, 0x50, 0xb1, 0x54, 0x9f, 0x5e, 0xa9, 0x3e, 0xd4, 0xac, 0xf3, 0xbb, + 0x3a, 0xee, 0x53, 0x31, 0x5a, 0xcb, 0x09, 0x01, 0xae, 0x83, 0x44, 0xa3, 0x03, 0x60, 0x9c, 0x6d, 0xb6, 0xbc, 0xd4, + 0xd6, 0x89, 0xd2, 0x71, 0x9c, 0xeb, 0xe3, 0xf8, 0x70, 0x90, 0x62, 0xc6, 0xe5, 0x91, 0x98, 0x71, 0xd9, 0x00, 0xbc, + 0x59, 0xe7, 0x41, 0x7d, 0x38, 0x5c, 0xd2, 0xa5, 0xc8, 0x74, 0xb6, 0x51, 0x7e, 0xd6, 0xa3, 0xfb, 0x27, 0x09, 0x9a, + 0x7b, 0x2b, 0xec, 0xbd, 0x48, 0xb6, 0x67, 0xb2, 0x4e, 0xbd, 0x8c, 0x7c, 0x7a, 0xe1, 0x9e, 0x5d, 0x72, 0xf5, 0xc3, + 0xea, 0xeb, 0xe9, 0x6f, 0xc2, 0x8b, 0x58, 0x45, 0xbb, 0x75, 0xc9, 0x84, 0xbd, 0xa5, 0x54, 0xd2, 0x2a, 0x2f, 0x9f, + 0x6e, 0xfc, 0x00, 0x33, 0xd3, 0x9e, 0x3e, 0xc8, 0x46, 0x54, 0x7f, 0x56, 0xa2, 0x56, 0x86, 0xc9, 0xc2, 0x79, 0xc9, + 0xd4, 0x93, 0x01, 0x8f, 0x59, 0xc9, 0x23, 0xd9, 0xe9, 0x8d, 0x41, 0x10, 0xc0, 0x3a, 0x27, 0xad, 0x3a, 0xe3, 0x68, + 0xb4, 0xaa, 0x5c, 0x9c, 0xae, 0x72, 0x81, 0xe1, 0x76, 0x6b, 0xb6, 0x51, 0x75, 0x96, 0x9b, 0x5a, 0xa5, 0x7c, 0x07, + 0xf0, 0xb1, 0xac, 0x72, 0x41, 0xc7, 0x94, 0xa9, 0xf3, 0x06, 0x82, 0xb1, 0x55, 0x8d, 0x0b, 0xa7, 0xc6, 0x05, 0x8f, + 0xa8, 0xdd, 0x4d, 0x53, 0x8f, 0xb6, 0xc0, 0x52, 0x3a, 0xda, 0xf1, 0x12, 0x55, 0x0a, 0x3f, 0x0b, 0xbe, 0x0f, 0xe3, + 0xf8, 0x45, 0xb1, 0x55, 0x07, 0xe2, 0x6d, 0xb1, 0x45, 0xda, 0x17, 0xf9, 0x17, 0xe2, 0x80, 0xd7, 0xba, 0xa6, 0xbc, + 0xb6, 0xe6, 0x34, 0xb0, 0x35, 0x8c, 0x94, 0x14, 0xce, 0xcd, 0x9f, 0x87, 0x03, 0xad, 0xec, 0x5a, 0xdd, 0x15, 0x6a, + 0x3d, 0xe6, 0xb0, 0x61, 0xdf, 0x64, 0xe1, 0x4e, 0x94, 0xe0, 0xc8, 0x25, 0xff, 0x3a, 0x1c, 0xb4, 0xca, 0x52, 0x1d, + 0xe9, 0xb3, 0xfd, 0xd7, 0x60, 0xcc, 0xd0, 0xa5, 0x09, 0x58, 0x36, 0x46, 0xf2, 0xaf, 0xa6, 0x99, 0x37, 0x4c, 0xd6, + 0x4c, 0xe1, 0x38, 0x34, 0x8c, 0x90, 0x06, 0x74, 0x1b, 0xd4, 0x86, 0x27, 0xf3, 0x4d, 0x55, 0x7e, 0x75, 0x47, 0xaa, + 0xfd, 0x60, 0x78, 0x39, 0x11, 0xe7, 0x74, 0x49, 0x52, 0x4f, 0x25, 0x94, 0x84, 0x60, 0x97, 0x3e, 0x90, 0x13, 0x2b, + 0x20, 0x6b, 0x19, 0xcb, 0x6f, 0xf5, 0x80, 0xd0, 0x7f, 0xda, 0xad, 0x17, 0xfa, 0x4f, 0xd3, 0x6c, 0xa1, 0xae, 0x3f, + 0x4c, 0xee, 0x3b, 0x7a, 0xfd, 0xc1, 0xe1, 0x9d, 0xba, 0xaa, 0xb8, 0x8a, 0x47, 0xb5, 0x61, 0x92, 0x1b, 0x65, 0xe1, + 0xae, 0xd8, 0xd4, 0x6a, 0x79, 0x3a, 0x0e, 0x23, 0x30, 0x23, 0x28, 0x40, 0xd6, 0x75, 0x1b, 0x11, 0xc3, 0x4a, 0x2e, + 0x13, 0xf2, 0x09, 0x01, 0x59, 0x94, 0x1a, 0xe7, 0xe3, 0x16, 0xa8, 0x44, 0x30, 0x38, 0x0d, 0xad, 0x55, 0x37, 0xf9, + 0x49, 0x65, 0x63, 0x4b, 0x20, 0x87, 0x24, 0x93, 0xc5, 0x72, 0x74, 0x2b, 0x16, 0x45, 0x29, 0xde, 0x60, 0x3d, 0x5c, + 0xb3, 0x85, 0xfb, 0x0c, 0x08, 0xed, 0x27, 0x4a, 0x7b, 0x13, 0x69, 0x82, 0xee, 0x25, 0x5b, 0x01, 0xc8, 0x00, 0x8a, + 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, 0x9f, 0x2e, 0x83, 0xe5, 0xe0, 0x12, 0xb5, 0xd2, + 0x97, 0x2c, 0x6e, 0x61, 0x50, 0xed, 0xcd, 0x12, 0x0e, 0x6a, 0x66, 0xad, 0x8d, 0x40, 0x30, 0xd9, 0x43, 0x41, 0xc5, + 0x5c, 0xc1, 0x3e, 0x28, 0x58, 0x4b, 0x5e, 0x07, 0x87, 0x5b, 0xfb, 0xb2, 0x52, 0x5c, 0x3c, 0xbd, 0x48, 0x5a, 0x17, + 0x96, 0xf2, 0xe2, 0x69, 0x03, 0x06, 0x97, 0x23, 0x6c, 0x2a, 0x30, 0x49, 0x00, 0xe8, 0x56, 0x44, 0x11, 0x2f, 0x4a, + 0x61, 0xdb, 0xca, 0x67, 0x4e, 0xd8, 0x60, 0xc3, 0xee, 0xe1, 0x5e, 0x19, 0x94, 0x0c, 0x2e, 0xc4, 0xb8, 0xdd, 0xec, + 0x02, 0x5c, 0xc1, 0x50, 0x18, 0x5b, 0xf3, 0x77, 0x99, 0x17, 0x29, 0x01, 0x37, 0x43, 0x94, 0xaf, 0x0d, 0x9c, 0x4c, + 0x7a, 0x72, 0x2d, 0x58, 0x0c, 0x58, 0xd0, 0xe0, 0x3b, 0x6a, 0xfd, 0x9d, 0xc9, 0xbf, 0xf1, 0xf4, 0xd0, 0x0f, 0x5e, + 0x64, 0xde, 0xc2, 0x67, 0xef, 0x2a, 0x19, 0xad, 0x49, 0xa2, 0xbc, 0x7a, 0xb8, 0x00, 0xb9, 0x61, 0x31, 0xba, 0x67, + 0x0b, 0x10, 0x27, 0x16, 0xa3, 0x84, 0x32, 0xba, 0xc2, 0xbd, 0xca, 0x6c, 0x99, 0x08, 0xa4, 0x38, 0xb0, 0x90, 0x72, + 0x6f, 0xb1, 0x0e, 0x16, 0xb8, 0x3f, 0x91, 0x5c, 0x40, 0xc9, 0x03, 0x28, 0x57, 0x0a, 0x08, 0xf8, 0x74, 0x00, 0xe5, + 0x4b, 0x79, 0x11, 0xfe, 0xc4, 0x89, 0x1a, 0x2c, 0x46, 0xf7, 0x0d, 0xfb, 0xc9, 0x0b, 0x2d, 0xfb, 0xc3, 0x52, 0x6b, + 0x1a, 0x56, 0x7c, 0x09, 0xd3, 0x62, 0xe2, 0xf6, 0xe5, 0xca, 0xae, 0x8a, 0xcf, 0x56, 0xea, 0xec, 0xa6, 0x86, 0x24, + 0xec, 0x1b, 0xb2, 0x0a, 0x70, 0xb0, 0x2a, 0xe2, 0x9e, 0x75, 0xb9, 0x0f, 0xa3, 0xbf, 0x36, 0x69, 0x29, 0x2c, 0x54, + 0x49, 0x7f, 0xdf, 0x94, 0x02, 0xa9, 0x4c, 0x74, 0xa2, 0x85, 0xe0, 0x0a, 0x0c, 0x02, 0x77, 0x22, 0xaf, 0x01, 0x30, + 0x06, 0x5c, 0x0a, 0x94, 0x65, 0x5b, 0x42, 0x48, 0x75, 0x3f, 0x03, 0xb5, 0x9d, 0xb8, 0x4b, 0x23, 0xb2, 0x16, 0xa2, + 0xaf, 0x82, 0x31, 0x73, 0x5e, 0x4a, 0xb7, 0xd8, 0x74, 0xb5, 0x59, 0x7d, 0x42, 0xe7, 0xd2, 0x96, 0x9b, 0x9f, 0xb0, + 0xc5, 0x5a, 0x81, 0xb2, 0x09, 0x49, 0xdb, 0x39, 0xcf, 0x51, 0x36, 0xa1, 0xa5, 0xbd, 0xa7, 0x1e, 0x15, 0xaa, 0x93, + 0xad, 0x97, 0xaa, 0xa9, 0x45, 0x58, 0x2d, 0x2e, 0x2a, 0x3f, 0x00, 0xdd, 0x54, 0x5a, 0x3d, 0xaf, 0x6b, 0x34, 0x85, + 0x5a, 0x2d, 0x1c, 0x37, 0xda, 0xd9, 0x74, 0x91, 0x2e, 0x11, 0x67, 0x55, 0xda, 0xa1, 0x7f, 0xca, 0xb4, 0xeb, 0x65, + 0x47, 0xbf, 0x19, 0x57, 0x17, 0xb8, 0x10, 0x1b, 0xf0, 0x39, 0xf7, 0x97, 0xd7, 0x7b, 0x1a, 0xf7, 0xfc, 0xc3, 0x01, + 0xd9, 0x93, 0xda, 0x1f, 0xaa, 0x8f, 0x5d, 0xc1, 0x90, 0x85, 0x51, 0xea, 0x2f, 0x52, 0xde, 0x7b, 0x84, 0xe3, 0xfe, + 0xa5, 0xea, 0xb1, 0x5f, 0x32, 0xbe, 0xaf, 0x8b, 0x4d, 0x94, 0x50, 0x54, 0x43, 0x6f, 0x55, 0x6c, 0x2a, 0x11, 0x17, + 0xf7, 0x79, 0x8f, 0x61, 0x32, 0x8c, 0x85, 0x4c, 0x85, 0x3f, 0x65, 0x2a, 0x78, 0x84, 0x50, 0xe2, 0x66, 0xdd, 0x23, + 0xed, 0x26, 0xc4, 0x29, 0xd5, 0xa2, 0x94, 0xc9, 0xf8, 0xb7, 0x7e, 0x02, 0xe5, 0x39, 0x45, 0xcb, 0xf4, 0xa3, 0xc2, + 0x65, 0xfa, 0x66, 0x7d, 0x5c, 0x7a, 0x26, 0x42, 0x9d, 0xb9, 0xd8, 0xd4, 0x3a, 0x1d, 0x63, 0xa7, 0x74, 0x6a, 0xc3, + 0xbe, 0x56, 0x8a, 0xcb, 0x8a, 0xc2, 0xbf, 0x91, 0xc8, 0xaa, 0x67, 0xc4, 0xf1, 0x7f, 0x66, 0xed, 0x33, 0xac, 0x02, + 0xbf, 0x0c, 0xe4, 0xfd, 0x02, 0xe0, 0xe3, 0xba, 0x2e, 0xd3, 0xdb, 0x0d, 0xd0, 0x86, 0xd0, 0xf0, 0xf7, 0x7c, 0x64, + 0xc0, 0x74, 0x1f, 0xe1, 0x0c, 0xe9, 0xa1, 0xce, 0x39, 0x9d, 0x95, 0xe9, 0x9c, 0xab, 0xb0, 0x96, 0x60, 0x2f, 0x27, + 0x4d, 0x2e, 0xd7, 0x25, 0xa8, 0x99, 0xc0, 0xed, 0x43, 0x7b, 0x44, 0x08, 0xb5, 0x29, 0xab, 0xe9, 0x25, 0xd4, 0xbc, + 0x93, 0xd3, 0x8e, 0x26, 0x25, 0xb8, 0x6a, 0xe8, 0xac, 0x5c, 0xff, 0x75, 0x38, 0xf4, 0x6e, 0xb3, 0x22, 0xfa, 0xb3, + 0x87, 0xfe, 0x8e, 0xdb, 0x4f, 0xe9, 0x57, 0x88, 0x96, 0xb1, 0xfe, 0x86, 0x0c, 0xe8, 0x78, 0x32, 0xbc, 0x2d, 0xb6, + 0x3d, 0xf6, 0x15, 0x35, 0x58, 0xfa, 0xfa, 0xf1, 0x09, 0x24, 0x54, 0x5d, 0xfb, 0xc2, 0xe2, 0x09, 0xf3, 0x94, 0x68, + 0x5b, 0xf8, 0x10, 0x16, 0xfa, 0x15, 0x22, 0x23, 0x21, 0xdc, 0x54, 0x76, 0x8f, 0x92, 0x76, 0xa1, 0x2f, 0x7d, 0x2d, + 0xfb, 0xca, 0x77, 0x2e, 0x00, 0x56, 0xf6, 0xa9, 0x0d, 0xf7, 0xa4, 0x3f, 0xa5, 0xfa, 0xb0, 0xfd, 0x2d, 0x59, 0x40, + 0xa1, 0x85, 0xf5, 0x54, 0xce, 0xce, 0x65, 0xc9, 0xf3, 0x6c, 0xba, 0x5f, 0xc3, 0x1e, 0x75, 0x87, 0x5e, 0x53, 0xc1, + 0xf9, 0xa5, 0x19, 0xbd, 0xdf, 0x0d, 0x85, 0xea, 0xa8, 0x73, 0x07, 0x59, 0x96, 0xd6, 0x25, 0xe7, 0x2f, 0x2b, 0x77, + 0x14, 0xe6, 0x77, 0x21, 0x78, 0x86, 0x75, 0xef, 0x2e, 0xce, 0x7b, 0xbf, 0xb5, 0xe6, 0xc8, 0x2f, 0xd9, 0x2c, 0x45, + 0x2c, 0x92, 0x39, 0x58, 0xfd, 0xd0, 0xcf, 0x63, 0xbf, 0x0d, 0x72, 0x38, 0x6e, 0x1a, 0xd0, 0x61, 0x43, 0x66, 0xed, + 0x4b, 0x04, 0x4e, 0x35, 0x82, 0x34, 0x35, 0x41, 0xcd, 0xf2, 0x10, 0x89, 0xed, 0x52, 0xb6, 0x0d, 0x72, 0xdd, 0x05, + 0xd3, 0x1c, 0x69, 0xcf, 0xe0, 0x7d, 0x93, 0x26, 0xa9, 0xd0, 0x2c, 0xba, 0x58, 0xc9, 0xf8, 0x77, 0xa4, 0xcd, 0x94, + 0xec, 0xb1, 0x35, 0xf0, 0x5e, 0x82, 0x72, 0x32, 0x4c, 0x31, 0x7c, 0xc7, 0xd7, 0x3b, 0x8f, 0x2e, 0xe2, 0xe7, 0x63, + 0xb6, 0x49, 0xd9, 0x11, 0x4c, 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xfd, 0x6d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, + 0x33, 0x69, 0x73, 0x85, 0x6e, 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, + 0xe2, 0x77, 0x60, 0x0e, 0x63, 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, + 0x02, 0x8c, 0xbe, 0xda, 0x16, 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, + 0xd0, 0xf9, 0x7d, 0x73, 0x5b, 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xed, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, + 0xad, 0x71, 0x9a, 0xf9, 0xdf, 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x5f, 0x20, 0x7a, 0x5f, + 0xb7, 0x72, 0x55, 0x6a, 0x37, 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, + 0x39, 0xff, 0x52, 0xf5, 0xfb, 0xde, 0x17, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, + 0x6d, 0x4a, 0xd8, 0x90, 0xdb, 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x0f, 0x39, 0xdf, + 0xaf, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, + 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x85, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, + 0x5a, 0x82, 0x76, 0xc1, 0xa6, 0xb0, 0xbf, 0x3f, 0x38, 0xe4, 0xfd, 0xfe, 0xc7, 0xdc, 0x6b, 0xf1, 0xba, 0x1b, 0xb8, + 0xcb, 0xd2, 0x43, 0x08, 0x60, 0x2d, 0x03, 0x65, 0x1c, 0x61, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, + 0x65, 0x57, 0x4e, 0x32, 0x0d, 0x30, 0xa3, 0x9a, 0xc2, 0x4c, 0x80, 0x91, 0xfa, 0x88, 0x75, 0xd3, 0xd3, 0x2a, 0xb4, + 0x7c, 0x0d, 0xc1, 0xba, 0xc8, 0x32, 0x8e, 0x62, 0x26, 0x00, 0xd8, 0x7c, 0x04, 0xf9, 0x8a, 0xae, 0x0e, 0x49, 0x2b, + 0x55, 0xde, 0xaf, 0x33, 0x22, 0xa3, 0x49, 0x88, 0xe6, 0xb7, 0xf0, 0xc0, 0xbe, 0x6d, 0x66, 0x54, 0xa9, 0x67, 0x54, + 0xe5, 0x33, 0x1c, 0x96, 0xc2, 0x31, 0xe2, 0xff, 0x9c, 0xaa, 0x1e, 0x11, 0xe8, 0x55, 0x99, 0x56, 0x51, 0x91, 0xe7, + 0x22, 0x42, 0x84, 0x6a, 0xe9, 0x1c, 0x0e, 0xfd, 0xd8, 0xef, 0xe3, 0x40, 0x98, 0x17, 0xeb, 0xe4, 0x81, 0xae, 0xac, + 0x69, 0xad, 0xa4, 0xc0, 0xa9, 0xa8, 0x11, 0x22, 0x84, 0xf7, 0x1b, 0xf0, 0xac, 0xa6, 0xbe, 0xdf, 0x58, 0x26, 0xba, + 0xdf, 0x33, 0xa0, 0xfc, 0x01, 0xf9, 0xba, 0x92, 0xe2, 0x8c, 0x48, 0x1e, 0x12, 0x67, 0x1c, 0x80, 0x98, 0x6f, 0x4b, + 0x34, 0x1a, 0xfb, 0x1f, 0x90, 0x60, 0xa8, 0x7e, 0xb0, 0xd3, 0x4d, 0xbd, 0x7f, 0x66, 0x12, 0x47, 0xd1, 0xa7, 0x6d, + 0xf2, 0x58, 0xb2, 0x34, 0x5a, 0x38, 0x7a, 0x8f, 0x18, 0xc6, 0xe1, 0x74, 0x3e, 0x26, 0xd9, 0xc6, 0x64, 0x15, 0x40, + 0x3a, 0x99, 0xa9, 0x63, 0x4a, 0x1d, 0x8d, 0x73, 0xbd, 0xa0, 0x0a, 0x3d, 0xd6, 0x25, 0xcf, 0xc1, 0x7a, 0xf2, 0xda, + 0x2b, 0xfd, 0xa9, 0x90, 0x73, 0xd8, 0x48, 0x04, 0x85, 0x1f, 0xe0, 0x6a, 0xb0, 0x52, 0xc0, 0x60, 0xea, 0x5b, 0xf8, + 0x9a, 0x78, 0x8e, 0x82, 0x47, 0x61, 0x17, 0x63, 0x6b, 0xe5, 0x3b, 0x9f, 0x14, 0x94, 0x7b, 0x56, 0xcc, 0x79, 0x05, + 0x9c, 0xcb, 0xa0, 0x10, 0xa6, 0xe3, 0x59, 0xfe, 0xcf, 0x24, 0xaf, 0x27, 0x36, 0x04, 0xc8, 0xe0, 0x4f, 0x89, 0xd3, + 0xd2, 0x1d, 0xba, 0xf3, 0xd0, 0xb3, 0x88, 0xc3, 0x46, 0x8f, 0xd6, 0x65, 0xb1, 0x4d, 0x51, 0x2f, 0x61, 0x7e, 0x20, + 0x3f, 0x6f, 0xc9, 0xf7, 0x21, 0x8a, 0xb7, 0xc1, 0xcf, 0x19, 0x8b, 0x05, 0xfe, 0xf5, 0xb7, 0x8c, 0xd1, 0x44, 0x0b, + 0xfe, 0x9e, 0x35, 0x48, 0x54, 0x0c, 0x58, 0x11, 0xc0, 0x65, 0xaa, 0x3e, 0x7c, 0x4a, 0x8c, 0xb7, 0x66, 0xc3, 0x03, + 0xdf, 0xac, 0x40, 0xa7, 0x3e, 0x77, 0x57, 0xb6, 0xa7, 0xab, 0x91, 0xaa, 0x6a, 0xfc, 0x9c, 0xaa, 0x6a, 0xfc, 0x9c, + 0x52, 0x35, 0xfe, 0xca, 0x28, 0x7e, 0xa7, 0xf2, 0x19, 0x32, 0x27, 0x9b, 0x98, 0xa4, 0xd3, 0xf7, 0x86, 0x13, 0xbb, + 0xec, 0xb7, 0x6e, 0x13, 0x69, 0x66, 0x22, 0x85, 0xdc, 0x1b, 0x80, 0x9a, 0x89, 0x1f, 0x73, 0xc3, 0x29, 0x71, 0x7e, + 0xee, 0xe1, 0x8a, 0x4d, 0xab, 0x6b, 0x5a, 0xb0, 0xc0, 0xe6, 0x65, 0x96, 0x67, 0x9a, 0xc0, 0xb6, 0x29, 0xb3, 0xbe, + 0xc9, 0x3d, 0x80, 0x60, 0x26, 0x35, 0x01, 0x20, 0x2d, 0x44, 0xa5, 0x10, 0xf9, 0x35, 0xce, 0xea, 0x73, 0xde, 0xdb, + 0xe4, 0x31, 0x91, 0x56, 0xf7, 0xfa, 0xfd, 0xf4, 0x2c, 0xcd, 0x29, 0xa8, 0xe1, 0x38, 0xeb, 0xf4, 0xa7, 0x2c, 0x10, + 0x89, 0x5c, 0xa5, 0xff, 0x70, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, 0x0b, + 0x04, 0x77, 0x72, 0xec, 0x27, 0xab, 0x52, 0x1e, 0x19, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, 0xfa, + 0x83, 0xd4, 0xd3, 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, 0x87, + 0xfb, 0xdc, 0x92, 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, 0xfb, + 0x7d, 0xf5, 0xf7, 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, 0xb9, + 0x8d, 0xa3, 0xad, 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, 0x2b, + 0x23, 0x2d, 0x3c, 0x7f, 0x8a, 0xbf, 0x6e, 0xea, 0x02, 0xc3, 0x33, 0x68, 0x8d, 0x56, 0x10, 0x4c, 0xf0, 0x8f, 0x0e, + 0xd4, 0x4b, 0x2b, 0xed, 0x23, 0xe8, 0x56, 0xa0, 0x07, 0x8d, 0x7d, 0x20, 0x69, 0x5f, 0x48, 0xd4, 0xed, 0xad, 0x4e, + 0xa3, 0x3f, 0x2b, 0x96, 0xf3, 0x0a, 0x26, 0x87, 0x1b, 0xfa, 0xb4, 0x0a, 0xb7, 0x9f, 0xe1, 0xe9, 0x1b, 0xa0, 0xdc, + 0x3a, 0x1c, 0x72, 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x29, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x4b, 0xd0, 0xde, + 0x05, 0xe8, 0x80, 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, 0x9e, + 0xe5, 0xb3, 0x4a, 0xe3, 0xb3, 0x27, 0x5e, 0xcd, 0x32, 0x70, 0x16, 0xb8, 0xa8, 0x7c, 0x96, 0x69, 0xd5, 0x53, 0x91, + 0xa0, 0xcf, 0x2b, 0x39, 0xc1, 0x95, 0xe0, 0x64, 0x03, 0xf2, 0x0b, 0x90, 0xa4, 0x29, 0x65, 0x4d, 0xf9, 0xec, 0x92, + 0x6e, 0xc8, 0xe8, 0x39, 0xef, 0x79, 0xd1, 0x30, 0xf4, 0x2f, 0xbc, 0x12, 0xc2, 0x37, 0x71, 0xdb, 0x46, 0x29, 0xec, + 0x6f, 0x02, 0x8b, 0x4f, 0xd8, 0x6b, 0x6f, 0xe1, 0x4f, 0xc7, 0x41, 0x38, 0x44, 0x6e, 0xa8, 0x98, 0x03, 0x7b, 0x1a, + 0xb0, 0xd8, 0xc4, 0x57, 0x9b, 0x49, 0x3c, 0x18, 0xf8, 0x3a, 0x63, 0x31, 0x8b, 0x81, 0x06, 0x39, 0x1e, 0x5c, 0xce, + 0xf5, 0x09, 0xa1, 0x1f, 0x46, 0x54, 0x8e, 0x0a, 0x74, 0x0e, 0xa2, 0xc1, 0x02, 0xf0, 0xd4, 0x5b, 0xd9, 0x20, 0xc9, + 0xd0, 0x40, 0x27, 0xae, 0x35, 0x49, 0x75, 0x38, 0xa1, 0x75, 0xa0, 0xe3, 0xea, 0x0d, 0x74, 0x3e, 0xae, 0x7b, 0x1f, + 0xaf, 0x86, 0x37, 0x54, 0xfa, 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0xf0, 0x66, 0x15, 0x6e, 0xdf, + 0xc8, 0x07, 0x8e, 0x3b, 0x2a, 0x69, 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0xc7, 0x94, 0xa3, 0xc3, 0x38, 0x92, + 0x43, 0xac, 0x5a, 0x71, 0x21, 0xbd, 0x11, 0x7c, 0xbb, 0x50, 0x8c, 0x65, 0x63, 0x97, 0x86, 0xa2, 0xf0, 0x67, 0x00, + 0x3b, 0xd4, 0xfe, 0x4a, 0x25, 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, + 0x89, 0x3f, 0x32, 0x63, 0x1d, 0x35, 0x5d, 0x5f, 0xb0, 0x1c, 0x59, 0x92, 0x6e, 0x67, 0x12, 0xcb, 0x89, 0x24, 0xb5, + 0xdd, 0x47, 0xc4, 0x60, 0xe0, 0x83, 0x8d, 0x98, 0x66, 0x22, 0x1c, 0xf1, 0xa8, 0x44, 0x16, 0x5d, 0x7e, 0x1b, 0x61, + 0xd2, 0xf6, 0x65, 0x45, 0xb6, 0x20, 0x98, 0x9e, 0x44, 0x1f, 0x24, 0x29, 0xa7, 0x22, 0x91, 0x66, 0x84, 0x00, 0x3f, + 0x9e, 0x94, 0x57, 0xfa, 0x73, 0xd0, 0xb4, 0x12, 0xbc, 0x64, 0x90, 0x3c, 0x12, 0x3f, 0x93, 0x82, 0x59, 0x8c, 0x55, + 0x83, 0x01, 0x96, 0x53, 0x3d, 0x71, 0x4c, 0xd2, 0x7f, 0xeb, 0x74, 0xc2, 0x7e, 0xee, 0xe5, 0xb6, 0x96, 0x37, 0xcd, + 0xbd, 0xe7, 0x5e, 0xc5, 0x52, 0x0d, 0xcb, 0xa0, 0xff, 0x9a, 0x68, 0x17, 0x6c, 0x6d, 0x19, 0x13, 0x56, 0xfd, 0x00, + 0xd2, 0x1e, 0xe9, 0xf2, 0xaa, 0x61, 0xce, 0x04, 0x8f, 0x2e, 0xac, 0x79, 0x10, 0x5d, 0x08, 0x1f, 0xb9, 0xec, 0x26, + 0xc9, 0xd5, 0x78, 0xe2, 0x87, 0x83, 0x81, 0x02, 0xa0, 0xa5, 0x75, 0x52, 0x0c, 0xc2, 0x27, 0x42, 0x0e, 0xa4, 0xd1, + 0x51, 0x15, 0x60, 0xb1, 0xcc, 0xae, 0xca, 0x49, 0x36, 0x18, 0xf8, 0x20, 0x36, 0x26, 0x76, 0x43, 0xb3, 0xb9, 0xcf, + 0x4e, 0x14, 0x64, 0xb5, 0x39, 0x6a, 0xcd, 0x74, 0x0b, 0x0c, 0x00, 0x06, 0x11, 0xc1, 0x72, 0x9f, 0x1a, 0xf9, 0x88, + 0x3a, 0x3d, 0x85, 0x11, 0x10, 0xfc, 0x72, 0x22, 0x10, 0xb9, 0x48, 0xa0, 0x1e, 0x60, 0x26, 0xc0, 0x8c, 0x2a, 0x86, + 0x97, 0xc0, 0x2e, 0x9e, 0x9b, 0x57, 0x0c, 0xfa, 0x17, 0x89, 0xd9, 0x89, 0xa6, 0x12, 0x47, 0x63, 0xe4, 0x54, 0x1a, + 0x23, 0x03, 0x62, 0x17, 0xc7, 0xbf, 0xa7, 0xf4, 0x28, 0x48, 0xd9, 0x8b, 0xca, 0x10, 0x87, 0xa3, 0xf8, 0x0a, 0x56, + 0x8d, 0xc3, 0xa1, 0x36, 0xaf, 0xa7, 0xb3, 0x7a, 0x3e, 0x10, 0x01, 0xfc, 0x37, 0x14, 0xec, 0x57, 0x4d, 0x45, 0x6e, + 0x90, 0x3a, 0x0f, 0x87, 0x14, 0xe4, 0x53, 0xdd, 0xe4, 0x9f, 0x2a, 0x77, 0x3f, 0x9d, 0xcd, 0xad, 0x39, 0x7a, 0x51, + 0xe3, 0xba, 0xb5, 0xba, 0xa1, 0x90, 0x68, 0x4d, 0x93, 0xe2, 0xaa, 0x9a, 0x14, 0x03, 0x9e, 0xfb, 0x42, 0x75, 0xb1, + 0x35, 0x82, 0x85, 0x3f, 0xb7, 0x40, 0x98, 0xf4, 0xb7, 0x92, 0x0e, 0xa9, 0x1a, 0x77, 0x6d, 0xb5, 0xdb, 0x56, 0x36, + 0xa4, 0x68, 0x3e, 0xbc, 0x84, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0x7a, 0x23, 0xf2, 0x98, + 0x7e, 0x85, 0xfc, 0x52, 0x0c, 0xff, 0x53, 0xba, 0x37, 0xa7, 0x36, 0xc8, 0x01, 0x6c, 0xf7, 0x1e, 0x6e, 0xc7, 0xe8, + 0x81, 0x0c, 0xde, 0x08, 0x39, 0xe7, 0xfc, 0x72, 0x6a, 0xcd, 0x98, 0x68, 0x58, 0xb0, 0x72, 0x18, 0xf9, 0x01, 0x32, + 0x5e, 0x4e, 0x81, 0x95, 0xfd, 0xa8, 0x88, 0x4b, 0x7f, 0x18, 0xf9, 0x17, 0x4f, 0x83, 0x8c, 0x7b, 0xd1, 0xb0, 0xe3, + 0x0b, 0xb0, 0x57, 0x5f, 0x3c, 0x65, 0xd1, 0x80, 0x57, 0x57, 0xf5, 0x34, 0x0b, 0x86, 0x19, 0x8b, 0xae, 0x8a, 0x21, + 0xf8, 0xd0, 0x3e, 0x2b, 0x07, 0xa1, 0xef, 0x9b, 0x9d, 0x43, 0x77, 0x43, 0x2c, 0x8f, 0xb0, 0x9f, 0xc0, 0x6d, 0x57, + 0x4b, 0xcc, 0x60, 0xb2, 0x59, 0x46, 0xcc, 0x60, 0xcb, 0x5f, 0x3c, 0x35, 0x5c, 0x42, 0xd5, 0x33, 0xa9, 0xd9, 0x28, + 0xd0, 0x9c, 0x5c, 0xa1, 0x39, 0x59, 0x09, 0xb5, 0xe4, 0x93, 0x0a, 0x27, 0xec, 0x7c, 0x92, 0x2b, 0xbb, 0xd1, 0x18, + 0x03, 0x17, 0xad, 0xb9, 0x1d, 0x0a, 0x23, 0x33, 0x9d, 0xa5, 0x68, 0xc0, 0xc2, 0x33, 0x71, 0x4a, 0x63, 0x40, 0xfb, + 0x72, 0x60, 0x69, 0x43, 0x7e, 0x91, 0x33, 0x03, 0x6d, 0x43, 0x4a, 0xa3, 0x66, 0xe0, 0xcf, 0xd4, 0x84, 0xf9, 0x0d, + 0xac, 0x44, 0x10, 0xd5, 0x05, 0x98, 0x24, 0x39, 0x19, 0x8d, 0x94, 0x95, 0x48, 0xce, 0x01, 0xef, 0x23, 0x78, 0xb2, + 0x88, 0x6d, 0xed, 0x4f, 0xe9, 0x7f, 0x75, 0xf8, 0x5c, 0xfa, 0x4f, 0x04, 0xb0, 0x90, 0x4b, 0x83, 0xc8, 0x40, 0xe1, + 0x90, 0x5a, 0x86, 0xf7, 0xc4, 0xf1, 0x0c, 0x7c, 0x05, 0x17, 0x68, 0x0a, 0xe8, 0x0f, 0x6a, 0x46, 0x11, 0x59, 0xf8, + 0xab, 0x67, 0x37, 0x75, 0xa1, 0xe7, 0x99, 0xf3, 0x1a, 0x34, 0x33, 0x10, 0xd2, 0xe3, 0x54, 0xbd, 0x0d, 0x89, 0xce, + 0xcb, 0x6b, 0xfd, 0x32, 0x21, 0x92, 0x95, 0x91, 0xa7, 0xef, 0x73, 0x30, 0x8f, 0x28, 0x42, 0x07, 0x57, 0xe6, 0xe1, + 0x70, 0x2e, 0x28, 0x7c, 0x47, 0x79, 0x3e, 0xe0, 0x34, 0xcb, 0x12, 0xd0, 0x06, 0xb2, 0xdc, 0x94, 0xb9, 0x4c, 0x5a, + 0xa6, 0xee, 0x3d, 0x58, 0x09, 0x2a, 0x74, 0x73, 0x0a, 0x0a, 0x65, 0x24, 0x28, 0xa5, 0xd5, 0x20, 0x94, 0xea, 0xb0, + 0x08, 0x22, 0x87, 0x2c, 0x04, 0xdc, 0x4c, 0x45, 0xa3, 0x25, 0x0d, 0x8f, 0x70, 0x6e, 0xa0, 0x10, 0x80, 0xc4, 0x9e, + 0x2a, 0xca, 0xb8, 0x1c, 0x02, 0x3e, 0x4a, 0x38, 0xc4, 0x59, 0x93, 0xb6, 0x3c, 0x07, 0x71, 0x2c, 0x17, 0x7c, 0x59, + 0x21, 0x18, 0x44, 0xe8, 0x33, 0xe4, 0x4f, 0x96, 0xf3, 0xef, 0xd6, 0x61, 0xda, 0x11, 0x3e, 0xec, 0x6a, 0x37, 0x5c, + 0xcc, 0x6e, 0xe7, 0x13, 0x88, 0x6f, 0xb9, 0x9d, 0x1f, 0x63, 0x88, 0xdc, 0xf8, 0x83, 0xe5, 0x50, 0x72, 0x45, 0xa1, + 0xcb, 0x7a, 0x44, 0x8a, 0xec, 0xe9, 0x9a, 0x23, 0x08, 0x0e, 0xb4, 0x6a, 0x90, 0xa1, 0x91, 0xf8, 0xe2, 0x29, 0x64, + 0x0d, 0xd6, 0xfc, 0x45, 0x45, 0xce, 0xea, 0xfe, 0x64, 0x03, 0xd5, 0x24, 0x93, 0xb5, 0xa2, 0x72, 0xfe, 0x76, 0x55, + 0x16, 0x27, 0xab, 0x32, 0x5c, 0x0d, 0xba, 0xaa, 0xb2, 0xe0, 0x48, 0x6d, 0x80, 0xd6, 0x74, 0x85, 0x18, 0x0a, 0x59, + 0x83, 0x85, 0x55, 0x95, 0x35, 0xf5, 0x09, 0x04, 0xfa, 0x00, 0xcb, 0xa8, 0xd9, 0x4f, 0x87, 0xbf, 0x04, 0xbf, 0xa8, + 0x90, 0xa5, 0x3a, 0xad, 0x33, 0xf1, 0x5b, 0xb0, 0x60, 0xf8, 0xc7, 0xef, 0xc1, 0x1a, 0xb0, 0x04, 0xc8, 0x72, 0xb7, + 0xb1, 0xd1, 0x7a, 0xe5, 0x15, 0xe2, 0x5d, 0xad, 0x2f, 0xfa, 0xad, 0xdb, 0x44, 0xad, 0x00, 0x23, 0x14, 0x5a, 0x04, + 0xd8, 0xea, 0x81, 0x7b, 0x0a, 0x7e, 0x20, 0x86, 0x73, 0x4d, 0x5a, 0x53, 0x27, 0xbc, 0xce, 0xc6, 0x91, 0x88, 0xea, + 0x2d, 0x5c, 0xdc, 0xeb, 0xad, 0xc5, 0xdf, 0xa8, 0x40, 0x00, 0x64, 0x31, 0xc5, 0xda, 0x79, 0x43, 0x7a, 0x65, 0xd8, + 0x49, 0xe8, 0xbd, 0x61, 0x27, 0x90, 0x17, 0x87, 0x9d, 0x42, 0x97, 0x68, 0x3b, 0x45, 0x6a, 0xa2, 0xed, 0xa4, 0x9b, + 0x55, 0x58, 0x42, 0xf0, 0xab, 0xf6, 0xd6, 0x51, 0xb6, 0x2f, 0xb2, 0x84, 0x69, 0x0b, 0x18, 0xe5, 0x56, 0x7d, 0xe6, + 0x14, 0xb1, 0x52, 0xf6, 0x4e, 0x27, 0x55, 0xee, 0x22, 0x9f, 0x5b, 0x4d, 0x91, 0xc9, 0x2f, 0x8e, 0x5b, 0x24, 0x9f, + 0xbc, 0x69, 0x37, 0x4c, 0xa6, 0x7f, 0x3c, 0xfa, 0x02, 0xba, 0x22, 0x3b, 0x7d, 0x02, 0x01, 0x99, 0x0a, 0xaa, 0xd5, + 0xad, 0x62, 0x9a, 0xb7, 0xab, 0xec, 0xf6, 0x42, 0x89, 0xe1, 0x74, 0x76, 0x12, 0x1e, 0x6d, 0x86, 0x0c, 0x1c, 0x82, + 0x40, 0x21, 0x54, 0x14, 0xc3, 0x23, 0x50, 0x6b, 0x24, 0x1f, 0xe0, 0x47, 0xbb, 0x53, 0x41, 0xa4, 0x76, 0x53, 0x71, + 0xe3, 0xe4, 0xa6, 0xeb, 0xa5, 0x40, 0xad, 0x53, 0xb2, 0x02, 0x28, 0x21, 0xea, 0xcf, 0x62, 0x5b, 0x5f, 0xc3, 0x15, + 0x9b, 0xef, 0x1b, 0x45, 0x4f, 0xae, 0x4f, 0x51, 0xb7, 0xe2, 0xea, 0x34, 0x6d, 0x35, 0xc7, 0x8e, 0x33, 0xe4, 0xe0, + 0x59, 0x41, 0xb0, 0x1d, 0x95, 0x28, 0xdf, 0xb6, 0x9b, 0x8e, 0x89, 0xad, 0xfe, 0xb9, 0xa9, 0x36, 0x4b, 0xa8, 0x88, + 0x88, 0x8f, 0xb2, 0x9b, 0x27, 0xed, 0x77, 0xb0, 0xc7, 0x5a, 0x0d, 0x22, 0xfb, 0x0c, 0xae, 0x72, 0x9d, 0x16, 0xb9, + 0x2d, 0x83, 0xf3, 0x0f, 0xaf, 0x76, 0x15, 0x36, 0x39, 0xd6, 0xd5, 0xd5, 0x4c, 0x75, 0x52, 0xb1, 0x81, 0xb1, 0xa6, + 0xb5, 0x54, 0xf3, 0x18, 0x92, 0xee, 0xca, 0xe2, 0xac, 0x4a, 0xba, 0xe9, 0xb9, 0x71, 0xa6, 0x10, 0x03, 0x67, 0xab, + 0xd1, 0x72, 0x86, 0x21, 0xba, 0x3e, 0xcc, 0x12, 0xbf, 0xd5, 0x53, 0xee, 0xf3, 0x70, 0xeb, 0x77, 0xf5, 0x82, 0x93, + 0xc9, 0x7e, 0x72, 0x9c, 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x29, 0xea, 0x5f, 0x2a, + 0x00, 0x1a, 0xdc, 0xe4, 0xb1, 0x44, 0xa9, 0xdf, 0xab, 0xea, 0x07, 0x35, 0x53, 0x35, 0x0d, 0x04, 0x73, 0x2a, 0x05, + 0xfc, 0xe1, 0x76, 0xe1, 0x8a, 0x47, 0xdc, 0xb0, 0x30, 0xfe, 0xe5, 0xd5, 0xec, 0x54, 0x50, 0x19, 0xb8, 0x19, 0xff, + 0xe5, 0x09, 0x76, 0x0a, 0x6b, 0x05, 0x64, 0x85, 0xbf, 0xbc, 0xfc, 0x81, 0xf7, 0x2b, 0xfe, 0x97, 0x57, 0x3d, 0xf0, + 0x3e, 0xe2, 0xbc, 0xfc, 0x85, 0xa4, 0x4e, 0x88, 0xea, 0xf2, 0x17, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x25, 0x29, 0x7c, + 0x82, 0x2f, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, + 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, + 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, 0xb7, 0x61, 0x1d, 0x25, 0x69, 0xbe, 0x94, 0xd1, 0x47, 0x32, + 0xec, 0x48, 0x5f, 0x49, 0x89, 0xf6, 0x5a, 0x85, 0xe5, 0x68, 0xf6, 0xeb, 0x92, 0x03, 0xe5, 0x75, 0x2b, 0x28, 0x5f, + 0x35, 0x01, 0xf4, 0x4a, 0xb5, 0xcf, 0x40, 0x2b, 0x28, 0x2c, 0x95, 0x07, 0x2b, 0x71, 0x2e, 0xfa, 0xac, 0x38, 0x1c, + 0xd4, 0xc5, 0x90, 0x50, 0xa0, 0x4a, 0x9c, 0x84, 0x46, 0x3c, 0x87, 0x0b, 0xa1, 0x78, 0x96, 0x63, 0x6c, 0x45, 0x0e, + 0x1c, 0xc8, 0xf0, 0x03, 0x02, 0xef, 0x65, 0xff, 0x0a, 0x06, 0xc3, 0x04, 0x37, 0x32, 0xea, 0xe4, 0x9c, 0xfd, 0x85, + 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, + 0x9d, 0xf4, 0xcf, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, + 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, + 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, + 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, + 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, + 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, 0x28, 0x07, 0xfb, 0x97, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, + 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, 0x71, 0x50, 0xb1, 0x65, 0x19, 0x46, 0xc0, 0xa0, 0x8e, 0xfd, + 0x8f, 0x3e, 0x9b, 0x36, 0x64, 0x1f, 0x00, 0x2a, 0x57, 0x21, 0x60, 0x0f, 0xc0, 0x89, 0x46, 0xb8, 0x01, 0x6e, 0x35, + 0x5a, 0xd2, 0x41, 0xdd, 0x16, 0x0c, 0x44, 0x4b, 0xd8, 0xc8, 0xdb, 0xae, 0x4e, 0xdf, 0x10, 0x3e, 0xd4, 0x4e, 0x4a, + 0x87, 0xf2, 0x37, 0xcf, 0xd9, 0x7f, 0xef, 0xb0, 0xa6, 0xa6, 0x7c, 0x02, 0xcc, 0x9c, 0x95, 0xc8, 0x2b, 0x84, 0x4e, + 0x91, 0xdf, 0xab, 0xba, 0x12, 0xc3, 0x45, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, + 0xc8, 0x49, 0xaa, 0xcd, 0x47, 0xd6, 0x0a, 0x4a, 0xd4, 0x35, 0x0a, 0x1c, 0x9f, 0x72, 0xed, 0xfe, 0xdf, 0x39, 0x13, + 0xd4, 0x6c, 0xa3, 0xba, 0xbf, 0xd4, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, + 0x9c, 0x2c, 0x45, 0xa0, 0x97, 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x72, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x8b, + 0x4d, 0x9a, 0xc5, 0x72, 0x35, 0xdb, 0xc3, 0x44, 0x59, 0xac, 0x87, 0x08, 0x72, 0x66, 0xea, 0x60, 0xbf, 0xa7, 0x19, + 0xcd, 0xc2, 0x2b, 0x53, 0x82, 0x4b, 0x71, 0x15, 0x15, 0x39, 0xf8, 0x1c, 0xe2, 0x0b, 0x9f, 0x0b, 0xb9, 0x41, 0x44, + 0xd3, 0x9f, 0x24, 0xaa, 0x1d, 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, + 0x6b, 0x85, 0xe0, 0xfe, 0xc6, 0x16, 0x1b, 0x55, 0x9e, 0xe8, 0xc1, 0xa7, 0x58, 0xff, 0x93, 0x05, 0x94, 0xea, 0xbe, + 0x0d, 0x4e, 0xc5, 0xa3, 0x70, 0x53, 0x17, 0x9f, 0x10, 0x5a, 0xa0, 0x1c, 0x55, 0xc5, 0xa6, 0x8c, 0x88, 0x13, 0x76, + 0x53, 0x17, 0x3d, 0xcd, 0x81, 0x2e, 0xe7, 0x75, 0x22, 0x4f, 0x84, 0x76, 0x0b, 0xba, 0xa7, 0x39, 0x56, 0xe2, 0xb9, + 0x2c, 0x1d, 0x64, 0x9d, 0x48, 0x13, 0x2a, 0x77, 0x75, 0xd5, 0x51, 0xa9, 0xd4, 0x0d, 0xaf, 0x52, 0xcd, 0xf8, 0xbb, + 0x30, 0x7f, 0x62, 0xd9, 0xaf, 0x5a, 0xbf, 0xd5, 0x6a, 0x6f, 0xac, 0x1e, 0x95, 0xac, 0x39, 0xce, 0x26, 0x24, 0xa5, + 0x4f, 0xd8, 0x6e, 0x26, 0x5d, 0xeb, 0xc0, 0x93, 0xe0, 0x72, 0xe8, 0x09, 0xa8, 0x18, 0x34, 0xf1, 0x76, 0x17, 0xa8, + 0x47, 0xe0, 0x19, 0x28, 0x9f, 0xa8, 0x75, 0xc0, 0xcf, 0x6b, 0x2d, 0x4f, 0x19, 0x61, 0x58, 0xed, 0x2c, 0x5a, 0x0e, + 0xce, 0x3b, 0x45, 0xe0, 0xda, 0x95, 0xc0, 0xf3, 0xa1, 0x7a, 0x2f, 0x04, 0x0c, 0xf7, 0xcf, 0x85, 0xca, 0x66, 0x37, + 0xc3, 0x79, 0xd4, 0x38, 0x3d, 0xd0, 0xde, 0x76, 0xad, 0x87, 0x7a, 0xd7, 0xed, 0xdc, 0x56, 0xba, 0xf7, 0x6b, 0x27, + 0x93, 0x2e, 0xa0, 0xb5, 0xf9, 0xec, 0x3b, 0xbb, 0xd2, 0xba, 0xe9, 0x39, 0x7b, 0xb0, 0x75, 0x4b, 0x74, 0x2e, 0x88, + 0x26, 0xbf, 0x1f, 0x78, 0xd6, 0xb6, 0xa3, 0xdf, 0xa6, 0x1d, 0xdb, 0xdc, 0x43, 0xdd, 0x2b, 0xa8, 0xf5, 0x86, 0xe6, + 0xfd, 0x33, 0xd7, 0xb6, 0xe3, 0xab, 0x5f, 0xd7, 0x1d, 0xae, 0xf3, 0x26, 0x38, 0x6e, 0xba, 0xb6, 0xd5, 0xce, 0x7e, + 0xee, 0xee, 0xad, 0x9b, 0x28, 0xcc, 0xb2, 0x9f, 0x8a, 0xe2, 0xcf, 0x4a, 0xdf, 0x11, 0xe8, 0xe8, 0xce, 0x8b, 0x3a, + 0x5d, 0xec, 0x3e, 0x10, 0xc6, 0x93, 0x57, 0x1f, 0x11, 0xdd, 0xfa, 0x3e, 0x73, 0xbf, 0x02, 0xdc, 0x08, 0xee, 0x20, + 0xda, 0xbb, 0xa5, 0x3e, 0xa9, 0xd5, 0xd7, 0x7a, 0xed, 0x3c, 0x3d, 0xbf, 0xe9, 0xdc, 0x7e, 0xf7, 0xcd, 0xd1, 0xd6, + 0x7b, 0x5c, 0x58, 0x2b, 0x4b, 0x4f, 0x55, 0xc1, 0xde, 0x2c, 0x4f, 0x55, 0xc1, 0xe4, 0x81, 0xd7, 0xec, 0x17, 0x34, + 0xb8, 0xd2, 0xd1, 0xc6, 0x7b, 0xa2, 0x06, 0x6e, 0x51, 0x58, 0x3a, 0xfc, 0x92, 0x9b, 0xc9, 0x35, 0xee, 0x2f, 0x15, + 0xb9, 0xd8, 0x77, 0xce, 0xe8, 0xce, 0xcc, 0xba, 0x57, 0x15, 0xae, 0x16, 0xe4, 0xea, 0xc0, 0xd6, 0xb2, 0x8b, 0xc3, + 0x0d, 0x8b, 0x28, 0x40, 0x20, 0xa6, 0x57, 0x6a, 0xed, 0x8f, 0x68, 0x10, 0xf2, 0xc1, 0xc0, 0x2f, 0x30, 0x58, 0x15, + 0x28, 0x7c, 0xa0, 0x48, 0xfe, 0xd2, 0x13, 0xb0, 0x8b, 0x67, 0x80, 0x6e, 0xc5, 0x66, 0xc5, 0x08, 0x11, 0x32, 0x59, + 0xce, 0x6a, 0x3a, 0x83, 0x7c, 0xea, 0x8b, 0xef, 0x6c, 0xd5, 0xe9, 0xbc, 0xad, 0xa9, 0x72, 0xea, 0x50, 0xe8, 0xee, + 0xa6, 0xee, 0xdc, 0xba, 0xc8, 0x53, 0x87, 0x90, 0x2b, 0x15, 0x2b, 0x31, 0x0d, 0x35, 0x4f, 0xd2, 0x8c, 0xfa, 0xab, + 0xbd, 0xdf, 0x6b, 0x14, 0x4e, 0xf9, 0xd3, 0x31, 0xa8, 0xc2, 0x55, 0x0d, 0x71, 0x2c, 0x55, 0xf1, 0xc8, 0x06, 0x81, + 0xe6, 0xd5, 0xad, 0x4a, 0x9a, 0x90, 0xc9, 0x8d, 0xf0, 0xa9, 0x49, 0x29, 0x4f, 0xd3, 0x26, 0xad, 0x14, 0xa9, 0x83, + 0x0f, 0xea, 0x54, 0xe3, 0xb9, 0x59, 0x3d, 0x03, 0x30, 0xe3, 0xfc, 0x8a, 0x5f, 0x2a, 0x2e, 0xa3, 0xb6, 0x32, 0x93, + 0xf6, 0x27, 0x47, 0x63, 0xa3, 0x2e, 0xa7, 0x8d, 0x32, 0xc2, 0x4a, 0x69, 0x4e, 0x8a, 0xe5, 0x78, 0xfe, 0x01, 0x83, + 0x35, 0x4f, 0x60, 0x07, 0x13, 0x95, 0xf2, 0x3e, 0x02, 0xe2, 0xeb, 0x24, 0x5d, 0x26, 0x90, 0x22, 0xfd, 0x4b, 0x17, + 0x3c, 0x75, 0x18, 0x1b, 0x88, 0x31, 0x2b, 0x66, 0x46, 0xff, 0x83, 0xbb, 0xa4, 0x3f, 0x09, 0x01, 0x70, 0x13, 0x4d, + 0xa1, 0x53, 0xe7, 0xc9, 0x45, 0x1e, 0x2c, 0x2e, 0x3c, 0xb4, 0x62, 0xc4, 0x83, 0xff, 0x7c, 0x16, 0x22, 0x88, 0x39, + 0xa6, 0x78, 0xfa, 0x85, 0xd1, 0x7f, 0x04, 0x97, 0x18, 0x41, 0xe8, 0xee, 0x9d, 0xc3, 0x10, 0x6e, 0xf6, 0x20, 0x83, + 0xfa, 0x43, 0x1d, 0x12, 0x35, 0xfc, 0xa5, 0xf2, 0xa0, 0xff, 0xeb, 0x4c, 0x58, 0x6a, 0x3f, 0x3d, 0x1d, 0x40, 0x05, + 0xef, 0x2b, 0xde, 0x46, 0xc4, 0xf7, 0x89, 0x9f, 0xc4, 0x83, 0xcd, 0x93, 0x0d, 0x58, 0xeb, 0x3e, 0xe4, 0xc6, 0xba, + 0x4a, 0xd8, 0x40, 0xc0, 0xd7, 0x98, 0xd6, 0x9e, 0xd7, 0x6e, 0xf7, 0xe0, 0x3f, 0xfd, 0x8b, 0x90, 0x01, 0x13, 0xa7, + 0xef, 0x33, 0x27, 0x6b, 0x74, 0x91, 0xc9, 0xf4, 0xa1, 0x93, 0xbe, 0xd1, 0xe9, 0xbe, 0x13, 0xfe, 0x51, 0x31, 0x8b, + 0x0f, 0xb7, 0xf4, 0x95, 0x26, 0xc5, 0x1d, 0xb0, 0xb2, 0x79, 0x50, 0x10, 0xea, 0x5c, 0x44, 0xdf, 0x98, 0xf2, 0x2d, + 0xa1, 0x66, 0xdf, 0x58, 0x52, 0x4a, 0xf7, 0x1a, 0x7a, 0x95, 0xd6, 0xfa, 0x6d, 0x94, 0x60, 0x4c, 0x74, 0x3c, 0x79, + 0x19, 0x8f, 0x95, 0xf7, 0xf1, 0xb8, 0x91, 0x0a, 0x79, 0x00, 0x22, 0x50, 0x31, 0xfe, 0x74, 0xe5, 0xc9, 0x49, 0x2f, + 0x8c, 0x57, 0xa1, 0x14, 0x14, 0x06, 0x74, 0x05, 0x52, 0xc0, 0xa3, 0xf6, 0x44, 0x67, 0x61, 0x97, 0x70, 0x8f, 0x6e, + 0x02, 0xc6, 0xfa, 0xfc, 0x0b, 0xa0, 0xb9, 0x0b, 0x77, 0x78, 0x31, 0x40, 0x6d, 0xea, 0xd5, 0xdd, 0xc7, 0xb5, 0x3a, + 0x87, 0x43, 0x70, 0xb0, 0x1a, 0x44, 0x70, 0x3a, 0x9f, 0x3a, 0x9a, 0x65, 0x01, 0x2a, 0x27, 0xcb, 0x8d, 0xbc, 0x79, + 0xb4, 0xe8, 0xd5, 0x7d, 0x6f, 0x91, 0x96, 0x55, 0x1d, 0x64, 0x2c, 0x0b, 0x2b, 0xc0, 0xd5, 0xa1, 0xf5, 0x83, 0x70, + 0x59, 0x38, 0x7f, 0x20, 0x04, 0xb1, 0x7b, 0xb5, 0x2d, 0x78, 0xae, 0xe6, 0xf0, 0x93, 0xa7, 0x6c, 0xcd, 0x25, 0xea, + 0xa4, 0x33, 0x11, 0x80, 0xd8, 0x53, 0xb3, 0x8a, 0xae, 0x81, 0xa4, 0x4e, 0xb3, 0x8a, 0xae, 0xa9, 0xd9, 0xc6, 0x38, + 0x90, 0x8f, 0x56, 0x29, 0x60, 0xdf, 0x4d, 0xc7, 0xc1, 0xea, 0x49, 0x2c, 0xaf, 0x43, 0xcb, 0x27, 0x1b, 0xe5, 0x33, + 0xa8, 0x5b, 0x6d, 0x8c, 0x89, 0xed, 0xe6, 0xcb, 0xb9, 0x7e, 0x3b, 0x58, 0xf8, 0x76, 0xd0, 0x9c, 0x53, 0xf6, 0x52, + 0x97, 0xbd, 0xb2, 0xcb, 0xa6, 0x9e, 0x3b, 0x2a, 0x5a, 0x8d, 0x01, 0xbd, 0x81, 0x05, 0xeb, 0x73, 0x91, 0x66, 0xab, + 0x52, 0x95, 0x80, 0x17, 0xc6, 0x8a, 0x2d, 0xfd, 0x46, 0x66, 0x48, 0xc2, 0x3c, 0xce, 0xc4, 0x5b, 0xba, 0xd7, 0xc2, + 0xe4, 0x38, 0x16, 0xc9, 0x94, 0xd0, 0x29, 0xdd, 0xd9, 0x86, 0xce, 0x55, 0x18, 0x45, 0xb4, 0x56, 0x52, 0x69, 0x24, + 0x30, 0x35, 0x03, 0x94, 0xcc, 0x15, 0x38, 0xa5, 0xcb, 0xfd, 0xef, 0x48, 0x8c, 0x33, 0x5f, 0x94, 0xcc, 0x80, 0x6e, + 0xf9, 0x75, 0xb1, 0x6e, 0xa5, 0xc8, 0x08, 0xf3, 0xe6, 0xb8, 0xbd, 0xae, 0x0f, 0x81, 0x5c, 0x2d, 0x7b, 0x14, 0x8d, + 0x83, 0x42, 0x87, 0x4b, 0x95, 0x00, 0xfb, 0x22, 0xf1, 0x33, 0xc2, 0x96, 0xf6, 0x40, 0x6e, 0x8f, 0xce, 0x84, 0x39, + 0xe7, 0xa4, 0x2c, 0x3b, 0x97, 0x66, 0x70, 0x39, 0x71, 0x25, 0xb8, 0x48, 0x6f, 0xdb, 0xd3, 0xa4, 0xa5, 0xed, 0x63, + 0xc3, 0x39, 0x1a, 0xda, 0x06, 0xdd, 0xb1, 0x3f, 0x34, 0x17, 0x8b, 0xd8, 0xba, 0x58, 0x0c, 0x3b, 0xb3, 0x1f, 0x2d, + 0x16, 0x20, 0x07, 0x80, 0xa3, 0x6e, 0xc3, 0xc7, 0x6c, 0x01, 0x9c, 0x56, 0xd3, 0x6c, 0xea, 0x6d, 0x78, 0xf5, 0x44, + 0xf5, 0xf4, 0x82, 0xe7, 0x4f, 0x84, 0x19, 0x8b, 0x0d, 0xcf, 0x9f, 0x58, 0x47, 0x4e, 0xf5, 0x44, 0x28, 0xd1, 0xba, + 0x80, 0x66, 0xe0, 0x35, 0x05, 0x8c, 0x58, 0x32, 0x99, 0x52, 0x45, 0x1e, 0xf7, 0xa6, 0x1b, 0x35, 0x78, 0x41, 0xe1, + 0x10, 0x48, 0xe9, 0xf4, 0x8b, 0xa7, 0x4c, 0xbf, 0x77, 0xf1, 0xb4, 0x43, 0xd6, 0x36, 0x4c, 0x97, 0x9b, 0x61, 0x32, + 0x28, 0xfd, 0x27, 0x66, 0x62, 0x5c, 0x58, 0x93, 0x04, 0x10, 0xff, 0xc6, 0x7e, 0x87, 0x14, 0x6e, 0xde, 0x5f, 0x0c, + 0xe3, 0x07, 0xde, 0x8f, 0x91, 0x3d, 0x49, 0x33, 0xc4, 0x9a, 0x49, 0x85, 0xdc, 0x7d, 0xb5, 0xfe, 0x31, 0xb1, 0x9b, + 0xec, 0x81, 0x05, 0x20, 0xb6, 0xa6, 0xad, 0x6e, 0x79, 0xbf, 0xef, 0x99, 0x22, 0xc0, 0x0f, 0xca, 0x3f, 0xba, 0x33, + 0x24, 0x83, 0xb2, 0xeb, 0x86, 0x10, 0x0f, 0xca, 0xa6, 0x69, 0xaf, 0xb7, 0xbd, 0x33, 0x8f, 0xd5, 0x75, 0xda, 0x59, + 0x5c, 0x2d, 0x32, 0x48, 0xab, 0x0f, 0xd9, 0x71, 0x66, 0x9f, 0x1d, 0x2d, 0x95, 0xee, 0xf7, 0x21, 0x22, 0xee, 0x28, + 0x6b, 0xfb, 0xed, 0x16, 0x5c, 0xc3, 0xd1, 0x20, 0x74, 0x65, 0x6f, 0x97, 0xd1, 0xc6, 0x85, 0x38, 0xee, 0x99, 0xce, + 0x17, 0x7c, 0x79, 0x94, 0x76, 0x1e, 0x9c, 0xea, 0x89, 0x3e, 0x37, 0xdd, 0x55, 0x26, 0xd7, 0x3a, 0xac, 0xc6, 0xa0, + 0x36, 0x0b, 0x5b, 0xb8, 0x0b, 0xdb, 0xe8, 0xa0, 0xb5, 0x2f, 0x0b, 0xfe, 0x29, 0x03, 0xf0, 0xa5, 0x67, 0xcb, 0xb6, + 0xd7, 0xa4, 0xd5, 0x2b, 0x19, 0x85, 0xd8, 0xd2, 0xf6, 0xea, 0xd3, 0x51, 0x3e, 0x6e, 0x4e, 0x28, 0x2e, 0xe4, 0x28, + 0x3f, 0x78, 0x0d, 0x51, 0xd7, 0xba, 0x8e, 0x8b, 0x45, 0x87, 0x1b, 0x57, 0xdd, 0x76, 0xe3, 0x7a, 0x8d, 0x78, 0x6b, + 0xb4, 0x49, 0xa1, 0x56, 0xc6, 0x8e, 0xe0, 0x65, 0xf9, 0x70, 0xc8, 0xc4, 0x70, 0x28, 0x21, 0x53, 0x1f, 0xba, 0x37, + 0x34, 0xed, 0xf3, 0xd3, 0xd6, 0x8f, 0x58, 0x6a, 0x1c, 0xc5, 0x86, 0x77, 0xfa, 0xce, 0x63, 0x6b, 0x5c, 0xc9, 0x97, + 0xc1, 0x6c, 0x57, 0x50, 0x6d, 0x8d, 0x37, 0xec, 0xe5, 0xfc, 0xa7, 0x4a, 0x2a, 0xf9, 0xdb, 0x9f, 0xe1, 0x1a, 0xde, + 0xda, 0xd2, 0x41, 0x53, 0xcd, 0x72, 0x96, 0xeb, 0x7b, 0xc1, 0xf1, 0xc7, 0xdd, 0x2b, 0x82, 0xc1, 0xef, 0xe9, 0x28, + 0xc8, 0xc5, 0x52, 0xad, 0x01, 0x05, 0xe9, 0xc8, 0x8e, 0xa9, 0x2c, 0x30, 0x0c, 0xe0, 0x0d, 0x19, 0x20, 0x8f, 0x29, + 0xdc, 0x0d, 0x15, 0x5e, 0xf8, 0x6b, 0x45, 0x76, 0x09, 0x6c, 0x6b, 0xc6, 0xc7, 0x0c, 0x77, 0x10, 0xf2, 0x8f, 0x60, + 0x4b, 0xb6, 0x62, 0xb7, 0xec, 0x86, 0x21, 0xd9, 0x38, 0x0e, 0x63, 0xcc, 0xc7, 0x93, 0xf8, 0x4a, 0x4c, 0xe2, 0x01, + 0x8f, 0xd0, 0x31, 0x62, 0xcd, 0xeb, 0x59, 0x2c, 0x07, 0x90, 0x2d, 0xb9, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, + 0x55, 0x61, 0x70, 0xb1, 0x63, 0x9f, 0x91, 0x48, 0xc6, 0x21, 0x58, 0xb4, 0xaa, 0x81, 0x85, 0x89, 0xdd, 0xf2, 0x62, + 0xb6, 0x9a, 0xe3, 0x3f, 0x87, 0x03, 0x02, 0x60, 0x07, 0xfb, 0x86, 0x2d, 0x23, 0x44, 0x7a, 0xbb, 0xe1, 0x4b, 0xcb, + 0xd3, 0x85, 0xdd, 0xf1, 0x6b, 0x3e, 0x66, 0xe7, 0xaf, 0x3d, 0x88, 0x9c, 0x3d, 0xff, 0x08, 0x68, 0x88, 0x77, 0xfc, + 0x36, 0xf5, 0x2a, 0x76, 0x4b, 0x14, 0x84, 0xb7, 0xe0, 0x0c, 0x74, 0x07, 0x11, 0xb0, 0xd7, 0xfc, 0x06, 0x63, 0xc5, + 0xce, 0xd2, 0x85, 0x87, 0x19, 0xa1, 0xf6, 0x74, 0xbe, 0xac, 0xd5, 0x24, 0xdc, 0x5c, 0x2d, 0x26, 0x83, 0xc1, 0xc6, + 0xdf, 0xf1, 0x35, 0xf0, 0xc1, 0x9c, 0xbf, 0xf6, 0x76, 0x54, 0x2e, 0xfc, 0xe7, 0x75, 0x96, 0xbc, 0xf3, 0xd9, 0xf5, + 0x80, 0xdf, 0x00, 0xde, 0x12, 0x3a, 0x70, 0xdd, 0xf9, 0x4c, 0xe2, 0xb5, 0x5d, 0xeb, 0x6b, 0x04, 0x12, 0xf9, 0x02, + 0x30, 0x62, 0x62, 0x7e, 0x5f, 0x43, 0x04, 0x46, 0x0c, 0xbe, 0xad, 0xda, 0x23, 0x7e, 0xcb, 0x0d, 0xe0, 0x57, 0xe6, + 0xb3, 0x7b, 0x1e, 0xea, 0x9f, 0x89, 0xcf, 0xde, 0xf2, 0xf7, 0xfc, 0x99, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, + 0xd7, 0x43, 0x29, 0x4f, 0x87, 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xbe, 0xf5, 0x80, 0x35, 0x29, 0xc4, 0xbf, + 0x80, 0x6f, 0x47, 0x09, 0x9b, 0x6f, 0xbd, 0xad, 0xaf, 0xe5, 0xcd, 0xb7, 0xde, 0xbd, 0x4f, 0x51, 0x80, 0x55, 0x50, + 0xca, 0x02, 0xab, 0x20, 0x6c, 0xb4, 0x11, 0xc6, 0xc0, 0xd5, 0xbb, 0xc6, 0x50, 0xd7, 0x73, 0xc4, 0xb6, 0x95, 0xbe, + 0x0b, 0xdf, 0x41, 0x06, 0x7c, 0xf0, 0xaa, 0x28, 0x89, 0x3e, 0xa7, 0xa6, 0x48, 0x5a, 0xf7, 0xdc, 0x6f, 0xad, 0x3b, + 0x5a, 0x53, 0xea, 0x23, 0x57, 0xe3, 0xc3, 0xa1, 0x7e, 0x26, 0xb4, 0x48, 0x30, 0x05, 0x8d, 0x6b, 0xd0, 0x16, 0x20, + 0xe8, 0xf3, 0x00, 0x59, 0x4b, 0x8a, 0x05, 0xdf, 0xfe, 0x0a, 0x31, 0x78, 0x65, 0x7a, 0xe7, 0x72, 0x95, 0x91, 0xb0, + 0xbd, 0xf0, 0xcb, 0x61, 0xed, 0x4f, 0x9c, 0x5a, 0x58, 0x5a, 0xcd, 0x41, 0xfd, 0xc4, 0x96, 0xe3, 0x54, 0xd5, 0xfe, + 0x2e, 0x49, 0xaa, 0x5d, 0xa5, 0xe5, 0xf4, 0xce, 0xbe, 0xe9, 0x32, 0xc1, 0xc6, 0x7e, 0x40, 0xd5, 0x91, 0xd5, 0xb0, + 0xfb, 0x42, 0x7d, 0xd1, 0x53, 0x32, 0xa1, 0xf9, 0xa8, 0xa2, 0x79, 0x76, 0xbf, 0xd9, 0x51, 0xff, 0xe9, 0xe5, 0x50, + 0x04, 0x48, 0x56, 0x69, 0xb1, 0x14, 0x39, 0x1b, 0xfb, 0xf1, 0x30, 0xc9, 0x54, 0x78, 0x41, 0x3a, 0xba, 0xfb, 0x8d, + 0xfb, 0x5b, 0x6e, 0x20, 0x2b, 0xb4, 0x6a, 0x83, 0xb1, 0x52, 0xb4, 0x0c, 0xd6, 0x57, 0xe3, 0x7e, 0x5f, 0x5c, 0x8d, + 0xa7, 0x22, 0xa8, 0x81, 0xb8, 0x48, 0x3c, 0x1b, 0x4f, 0x6b, 0x62, 0x49, 0xed, 0x0a, 0x8c, 0xd1, 0xe3, 0xaa, 0xa8, + 0x7d, 0xea, 0x67, 0x10, 0x8a, 0x54, 0x6b, 0xe6, 0x58, 0xe3, 0xc6, 0x88, 0xb8, 0xc3, 0xca, 0xb5, 0x53, 0x7b, 0x1d, + 0x80, 0xe5, 0xd5, 0xb8, 0x20, 0x2c, 0x92, 0x63, 0xe7, 0x02, 0x56, 0xa3, 0x21, 0xd5, 0x6e, 0xb8, 0xf5, 0xb2, 0xf3, + 0x9b, 0x6f, 0x12, 0x5b, 0x1b, 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, + 0x23, 0x4e, 0x5c, 0xc0, 0x72, 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0x54, 0xad, 0x74, 0xb8, 0x93, 0x09, 0xc4, + 0xfd, 0xea, 0xbe, 0xee, 0x95, 0xe0, 0x27, 0x21, 0xaf, 0xdf, 0xf2, 0x0e, 0x00, 0x2b, 0x3e, 0xe4, 0xc5, 0xb4, 0x70, + 0xb4, 0x2e, 0x83, 0x32, 0x40, 0x84, 0x66, 0x00, 0x74, 0x72, 0x75, 0x10, 0xa5, 0x81, 0x2b, 0xee, 0x10, 0xe1, 0xa7, + 0xd1, 0x93, 0xfc, 0x59, 0xf8, 0xa4, 0x9a, 0x86, 0x17, 0x79, 0x10, 0x5d, 0x54, 0x41, 0xf4, 0xa4, 0xba, 0x0a, 0x9f, + 0xe4, 0xd3, 0xe8, 0x22, 0x0f, 0xc2, 0x8b, 0xaa, 0xb1, 0xef, 0xda, 0xdd, 0x3d, 0x21, 0x6f, 0xbb, 0xfa, 0x23, 0xe7, + 0xca, 0x9e, 0x32, 0x3d, 0x3f, 0xaf, 0xf5, 0x4a, 0xed, 0x36, 0xd7, 0x6b, 0xd4, 0x4c, 0x7d, 0x94, 0xfd, 0xcd, 0x36, + 0x16, 0x1e, 0xcd, 0x21, 0xf4, 0x19, 0x69, 0x31, 0xf7, 0x38, 0xd7, 0x9b, 0x3d, 0x29, 0x0c, 0x8c, 0x98, 0x54, 0x32, + 0x72, 0x7a, 0x81, 0x8b, 0x50, 0x85, 0x18, 0xd6, 0xd2, 0xd5, 0x3e, 0xeb, 0xd2, 0x1b, 0xa8, 0x6b, 0x8a, 0x7d, 0x0d, + 0x19, 0x78, 0xd1, 0xf4, 0x32, 0x18, 0x03, 0x72, 0x04, 0xde, 0xf1, 0xd9, 0x02, 0x0e, 0xcc, 0x35, 0x40, 0xdf, 0x3c, + 0xe8, 0xeb, 0xb2, 0xe4, 0x6b, 0xd5, 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0x7c, 0x79, 0xf1, 0x94, 0xdd, 0x72, + 0x8d, 0x8a, 0xf2, 0x42, 0x2f, 0xd6, 0x3b, 0xe0, 0xaa, 0x7b, 0x01, 0xb7, 0x59, 0x3c, 0x76, 0xe5, 0x01, 0xcb, 0xb6, + 0xec, 0x9e, 0xbd, 0x65, 0xef, 0xd9, 0x07, 0xf6, 0x99, 0x7d, 0x65, 0x35, 0x42, 0x94, 0x97, 0x4a, 0xca, 0xf3, 0x6f, + 0xf8, 0xad, 0xb4, 0x3d, 0x4a, 0x58, 0xb2, 0x7b, 0xdb, 0x4e, 0x33, 0xdc, 0xb0, 0xf7, 0xfc, 0x66, 0xb8, 0x62, 0x9f, + 0x21, 0x1b, 0x0a, 0xc5, 0x83, 0x15, 0xab, 0xe1, 0x0a, 0x4b, 0x19, 0xf4, 0x69, 0x58, 0x5a, 0xc2, 0xa2, 0x29, 0x14, + 0xa5, 0xe8, 0xcf, 0xbc, 0x26, 0xec, 0xb4, 0x1a, 0x0b, 0x91, 0x1f, 0x1a, 0xae, 0xd8, 0x3d, 0xbf, 0x19, 0xac, 0xd8, + 0x7b, 0x6d, 0x23, 0x1a, 0x6c, 0xdc, 0xe2, 0x08, 0xcc, 0x4a, 0x17, 0x26, 0x05, 0xea, 0xad, 0x7d, 0x13, 0xdc, 0xb0, + 0xb7, 0x58, 0xbf, 0x0f, 0x58, 0x34, 0xca, 0xfc, 0x83, 0x15, 0xfb, 0xca, 0x25, 0x86, 0x9a, 0x5b, 0x9e, 0x74, 0x0c, + 0xd5, 0x05, 0xd2, 0x15, 0xe1, 0x03, 0xa7, 0x17, 0xd9, 0x57, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb1, 0x2d, 0xd6, 0xee, + 0xad, 0x31, 0x6e, 0x59, 0xd5, 0x93, 0xa0, 0xc0, 0x28, 0xab, 0x94, 0x96, 0x8b, 0x23, 0x96, 0x4d, 0x1d, 0x35, 0xa8, + 0x0d, 0x03, 0xfa, 0x60, 0xf4, 0x1f, 0xbe, 0x7e, 0xf7, 0x91, 0x57, 0xea, 0x9b, 0xef, 0x0b, 0xc7, 0xbb, 0xb2, 0x44, + 0xef, 0xca, 0xdf, 0x78, 0x39, 0x7b, 0x31, 0x9f, 0xe8, 0x5a, 0xd2, 0x26, 0x43, 0xee, 0xa6, 0xb3, 0x17, 0x1d, 0xfe, + 0x96, 0xbf, 0xf9, 0x7e, 0x63, 0xf5, 0xb1, 0xfa, 0xae, 0xee, 0xde, 0xfb, 0xc1, 0xa6, 0x71, 0x2a, 0xbe, 0x3b, 0x5d, + 0x71, 0x6c, 0x67, 0xad, 0xbd, 0x33, 0xff, 0x87, 0x6b, 0xbd, 0xc5, 0xb1, 0x7b, 0xcb, 0xb7, 0xc3, 0x8d, 0x3d, 0x0c, + 0xf2, 0xfb, 0xca, 0x2f, 0xbf, 0xe6, 0xcf, 0xbd, 0x4e, 0x49, 0x16, 0x50, 0x8d, 0xde, 0x18, 0x69, 0xe8, 0x92, 0x99, + 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, + 0x8d, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, 0xd8, 0x4b, 0xf2, 0x85, 0xcf, 0xde, 0x09, 0x77, 0x95, + 0xbe, 0xf0, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, + 0x11, 0xfc, 0x1d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0xbf, 0xd4, 0xea, 0xe7, 0x7b, 0x19, 0x9b, 0x03, 0x6f, 0x42, + 0x2b, 0xe8, 0xcd, 0xdb, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0x4d, 0x7d, 0x94, + 0x4e, 0xe5, 0x4d, 0xae, 0x79, 0x22, 0x2d, 0xcc, 0x77, 0x10, 0x0e, 0x7c, 0x6d, 0xc3, 0x14, 0xec, 0x38, 0x6e, 0x06, + 0xd7, 0x0c, 0x20, 0x24, 0xb3, 0xe9, 0x96, 0xbf, 0xe5, 0x1f, 0xf8, 0x57, 0xbe, 0x0b, 0xee, 0xf9, 0x7b, 0xfe, 0x99, + 0xd7, 0x35, 0xdf, 0xb1, 0x85, 0x84, 0x3c, 0xad, 0xb7, 0x97, 0xc1, 0x96, 0xd5, 0xbb, 0xcb, 0xe0, 0x9e, 0xd5, 0xdb, + 0xa7, 0xc1, 0x5b, 0x56, 0xef, 0x9e, 0x06, 0xef, 0xd9, 0xf6, 0x32, 0xf8, 0xc0, 0x76, 0x97, 0xc1, 0x67, 0xb6, 0x7d, + 0x1a, 0x7c, 0x65, 0xbb, 0xa7, 0x41, 0xad, 0x90, 0x1e, 0xbe, 0x0a, 0xc9, 0x74, 0xf2, 0xb5, 0x66, 0x86, 0x55, 0x37, + 0xf8, 0x22, 0xac, 0x5f, 0x54, 0xcb, 0xe0, 0x4b, 0xcd, 0x74, 0x9b, 0x03, 0x21, 0x98, 0x6e, 0x71, 0x70, 0x4b, 0x4f, + 0x4c, 0xbb, 0x82, 0x54, 0xb0, 0xae, 0x96, 0x06, 0x37, 0x75, 0xd3, 0x3a, 0x99, 0x1d, 0xef, 0xc4, 0xb8, 0xc3, 0x3b, + 0xf1, 0x86, 0x2d, 0x9a, 0x4e, 0x57, 0x9d, 0xd3, 0xe7, 0x81, 0x3e, 0x02, 0xf4, 0xde, 0x5f, 0x49, 0x0f, 0x9a, 0xa2, + 0xe1, 0xb9, 0xd2, 0x1d, 0xb7, 0xf6, 0xfb, 0xd0, 0xda, 0xef, 0x99, 0x54, 0xa4, 0x45, 0x2c, 0x2a, 0x8b, 0xaa, 0x42, + 0x3e, 0xf1, 0x20, 0xd3, 0x5a, 0xb5, 0x84, 0x91, 0x3a, 0x13, 0x30, 0xe9, 0x0b, 0x3a, 0x0c, 0x72, 0xb2, 0x2b, 0xb0, + 0x05, 0xdf, 0x0c, 0x12, 0xb6, 0xe6, 0xf1, 0x74, 0x98, 0x04, 0x0b, 0xb6, 0xe4, 0xc3, 0x6e, 0xb1, 0x60, 0xa5, 0xc2, + 0x98, 0xf4, 0xf5, 0xe9, 0x68, 0x77, 0xe7, 0xbd, 0x55, 0x1a, 0xc7, 0x99, 0x40, 0x9d, 0x5b, 0xa5, 0xb7, 0xf9, 0xad, + 0xb3, 0xab, 0xaf, 0xd5, 0x2e, 0x0f, 0x02, 0xc3, 0x6f, 0x40, 0xb4, 0x43, 0xbc, 0x77, 0x50, 0x63, 0xa4, 0x5b, 0x32, + 0xeb, 0xbe, 0xb2, 0xf7, 0xf5, 0xad, 0xd9, 0xaa, 0xff, 0xdd, 0x22, 0x68, 0x2f, 0x97, 0xbd, 0xff, 0xc6, 0xbc, 0xfa, + 0x7b, 0xc7, 0xab, 0x1b, 0x7f, 0x72, 0xcf, 0xdf, 0x60, 0x74, 0x02, 0x26, 0xb2, 0x1d, 0x7f, 0x33, 0xda, 0x36, 0x4e, + 0x79, 0x72, 0x2f, 0xff, 0xbf, 0x52, 0xa0, 0xbd, 0x9b, 0x57, 0xf6, 0xa6, 0xb8, 0xe5, 0x1d, 0x7b, 0xf9, 0xc2, 0xda, + 0x13, 0x0d, 0x42, 0xc9, 0x1b, 0xee, 0x06, 0x45, 0xc3, 0x9e, 0xf8, 0x82, 0x57, 0xb3, 0x37, 0xf3, 0xc9, 0x96, 0x1f, + 0xef, 0x88, 0x6f, 0x3a, 0x76, 0xc4, 0x17, 0xfe, 0x60, 0xd1, 0x7c, 0xab, 0x57, 0x3b, 0x77, 0x72, 0xa7, 0xd2, 0x3b, + 0x7e, 0xbc, 0x8f, 0x0f, 0xff, 0xed, 0x4a, 0xef, 0xbe, 0xbb, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, + 0x6b, 0x8d, 0xe1, 0x66, 0x46, 0xc1, 0x08, 0xd3, 0x16, 0xa6, 0x69, 0x10, 0x59, 0x8a, 0x45, 0x48, 0xd4, 0x28, 0x9d, + 0x13, 0x7d, 0x16, 0x74, 0x0a, 0xba, 0xb8, 0xd1, 0xdf, 0xf2, 0x31, 0xbb, 0x31, 0x2e, 0x9b, 0xb7, 0x57, 0x37, 0x93, + 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf1, 0x70, 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x8e, 0xd6, 0xd3, 0x44, 0x35, 0xbe, 0x78, + 0x48, 0x02, 0xbb, 0xf5, 0xfd, 0x89, 0x45, 0x04, 0x6b, 0xdf, 0x38, 0x6f, 0xfd, 0x81, 0x34, 0x4b, 0xcb, 0xad, 0xfd, + 0xfd, 0xc3, 0x1a, 0x8a, 0x5b, 0x10, 0x32, 0xde, 0xdb, 0x2a, 0x87, 0xcf, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, + 0xf0, 0xcd, 0x44, 0x9d, 0x4b, 0x9f, 0x2f, 0x9e, 0xb2, 0xdf, 0xf8, 0x1b, 0x79, 0xa6, 0xbc, 0x13, 0x72, 0xda, 0x7e, + 0x42, 0x12, 0x27, 0x3a, 0x2a, 0xbe, 0xba, 0x89, 0x04, 0x0a, 0x01, 0xbb, 0xc2, 0xd7, 0x9a, 0xdf, 0x4f, 0xca, 0xa9, + 0xb7, 0x03, 0x92, 0x57, 0x6e, 0x2b, 0xa2, 0x6f, 0x39, 0xe7, 0x37, 0xc3, 0xcb, 0xe9, 0xd7, 0x6e, 0xdf, 0x1e, 0x15, + 0xd6, 0xa6, 0x22, 0xde, 0x6e, 0x31, 0x08, 0xeb, 0x64, 0x66, 0x99, 0x4b, 0xbe, 0xf4, 0xb5, 0x36, 0x73, 0x8f, 0xe9, + 0x1d, 0x67, 0x9a, 0x21, 0xa3, 0x2f, 0x30, 0x33, 0x1d, 0x0e, 0xcb, 0x73, 0x2c, 0x8f, 0x0f, 0x3f, 0x3f, 0xf9, 0x30, + 0xf8, 0x80, 0x21, 0x5c, 0x56, 0x58, 0xc8, 0x57, 0x3e, 0xcc, 0xea, 0xd6, 0xb5, 0xe3, 0xe2, 0xe9, 0xf0, 0x05, 0xe4, + 0x0d, 0xba, 0x1e, 0x9a, 0x22, 0x5a, 0xe5, 0x77, 0x14, 0x7d, 0xa2, 0xe4, 0xa0, 0xe3, 0x09, 0xd4, 0x0e, 0xb9, 0x70, + 0xbf, 0x3e, 0xe1, 0xa0, 0xe8, 0xc0, 0x52, 0xfb, 0xfd, 0xf3, 0x37, 0x44, 0x28, 0x0d, 0xe3, 0xfd, 0x22, 0x8c, 0xfe, + 0x8c, 0xcb, 0x62, 0x0d, 0x47, 0xec, 0x00, 0x3e, 0xf7, 0x44, 0x5f, 0xc3, 0x96, 0xbe, 0xef, 0x07, 0xde, 0x96, 0xbf, + 0x65, 0x5f, 0xb9, 0x77, 0x39, 0xfc, 0xec, 0x3f, 0xf9, 0x00, 0xf2, 0x13, 0xe2, 0xa4, 0x60, 0x48, 0x6c, 0x47, 0x31, + 0x6a, 0x1d, 0x7e, 0xa9, 0x21, 0x56, 0xeb, 0x0d, 0x52, 0x77, 0x41, 0xfa, 0x07, 0x85, 0xec, 0x27, 0x04, 0x56, 0x93, + 0xf4, 0x29, 0x30, 0x89, 0x6f, 0x6b, 0x48, 0x20, 0x4d, 0x0b, 0xc4, 0xe0, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x87, 0x5f, + 0x48, 0xfe, 0xbb, 0xa9, 0xf9, 0x18, 0xfe, 0x86, 0xa1, 0x99, 0x54, 0xf7, 0x69, 0x1d, 0x25, 0x5e, 0x0d, 0xa7, 0x5e, + 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, 0x4e, 0x6e, 0x4b, 0x11, 0xfe, 0x39, 0xc1, 0x67, + 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, 0x65, 0xaf, 0x06, 0x37, 0xf5, 0x90, 0xdf, 0xd6, + 0xee, 0xfb, 0x72, 0x4e, 0xd0, 0x23, 0xfb, 0x01, 0xcd, 0xc1, 0x40, 0xcd, 0x40, 0xca, 0x10, 0xdc, 0xc2, 0xa5, 0xdf, + 0x53, 0x05, 0xf9, 0xf2, 0x7b, 0x5f, 0x84, 0x0c, 0x5c, 0xb9, 0x21, 0x4c, 0xb9, 0x54, 0x48, 0x81, 0xe3, 0xb6, 0x1e, + 0x7c, 0xd1, 0xe8, 0x24, 0x12, 0x7c, 0x4a, 0x40, 0x92, 0xb4, 0x3c, 0x90, 0x34, 0x62, 0x3a, 0x10, 0x17, 0x4a, 0xd3, + 0xac, 0xa4, 0x88, 0x43, 0xec, 0xaa, 0xd7, 0x48, 0x78, 0x16, 0xbc, 0x67, 0xb0, 0x76, 0xa4, 0x68, 0xf1, 0xd5, 0x98, + 0x8e, 0x75, 0xd8, 0xd0, 0x52, 0x16, 0xf7, 0x9b, 0xa4, 0x4e, 0x23, 0x71, 0xe5, 0x9d, 0x90, 0x3f, 0xff, 0xa9, 0x44, + 0x20, 0xbd, 0xab, 0x81, 0x18, 0x04, 0x3f, 0x40, 0xff, 0x01, 0x8b, 0x1c, 0x04, 0xa5, 0xba, 0x0c, 0xf3, 0x2a, 0xa3, + 0x02, 0x67, 0x3b, 0xb6, 0x9d, 0x33, 0x55, 0xb7, 0xe0, 0x8b, 0x30, 0x0c, 0x69, 0x67, 0xab, 0xe6, 0xe4, 0x56, 0x6f, + 0xa0, 0x9e, 0x49, 0x1c, 0xa9, 0xa5, 0x38, 0xd2, 0xd6, 0xdc, 0xa7, 0x0b, 0xaf, 0x5b, 0x5e, 0xd0, 0x70, 0x01, 0x7a, + 0x51, 0xba, 0xeb, 0x7c, 0x42, 0xa1, 0xcb, 0x6a, 0x5c, 0x0d, 0x45, 0x1d, 0xca, 0x31, 0xd6, 0xfe, 0x5c, 0xc9, 0xf3, + 0x3b, 0xb0, 0x1e, 0xa1, 0xe1, 0xab, 0x52, 0x07, 0xb1, 0xfd, 0x44, 0xef, 0x3a, 0x95, 0xfa, 0x1b, 0x00, 0x06, 0x4e, + 0x1d, 0x0f, 0xf5, 0x51, 0x3b, 0x85, 0x6c, 0xe7, 0xde, 0x12, 0xa3, 0x72, 0x25, 0x3c, 0x55, 0x5a, 0x9e, 0x52, 0x56, + 0x7d, 0x2d, 0xb8, 0x95, 0xdd, 0x67, 0x03, 0xc8, 0x68, 0x83, 0x02, 0x79, 0x46, 0x6d, 0x8d, 0x07, 0xa9, 0xa6, 0x59, + 0xe2, 0x18, 0x3e, 0x28, 0xd2, 0xac, 0x02, 0x8b, 0x97, 0xb9, 0x64, 0x0e, 0x0a, 0x96, 0xeb, 0xcd, 0x66, 0x9a, 0xa9, + 0xbe, 0xc8, 0xed, 0x8d, 0xc6, 0xcb, 0xf4, 0xdf, 0x2c, 0x19, 0xf0, 0xe8, 0xe2, 0xa9, 0x1f, 0x40, 0x9a, 0xa4, 0x78, + 0x80, 0x24, 0xd8, 0x1e, 0xec, 0x62, 0x87, 0x61, 0xab, 0x58, 0xd9, 0x93, 0xa7, 0xcb, 0x1d, 0x9a, 0x72, 0x09, 0x2e, + 0x39, 0x31, 0x97, 0x53, 0xdf, 0x97, 0xac, 0x37, 0x14, 0xa7, 0x6c, 0x9a, 0x80, 0x92, 0x40, 0xbb, 0x05, 0xff, 0x85, + 0x4f, 0x0d, 0x9d, 0x16, 0x60, 0xa9, 0xed, 0x06, 0xfc, 0x17, 0xfa, 0xc5, 0x76, 0x17, 0xf5, 0x03, 0xf3, 0x60, 0x6f, + 0x16, 0x57, 0xc6, 0x80, 0x93, 0xc4, 0x95, 0xe6, 0x91, 0xeb, 0x07, 0x45, 0x9f, 0x2e, 0x6b, 0x07, 0xce, 0x14, 0x17, + 0x56, 0xa9, 0x4d, 0xd2, 0x6b, 0xbf, 0xa5, 0x26, 0xde, 0x44, 0x49, 0x55, 0xd8, 0x0e, 0x69, 0xff, 0x92, 0x72, 0xa6, + 0x8a, 0x3b, 0x44, 0x4f, 0x76, 0x13, 0x57, 0x81, 0x17, 0x56, 0x15, 0x1b, 0xa1, 0x36, 0x23, 0xcb, 0x09, 0x9c, 0xee, + 0xb1, 0xba, 0xe0, 0x63, 0xbb, 0x9a, 0x5d, 0xb0, 0x92, 0xad, 0x99, 0x74, 0x9f, 0xb7, 0x63, 0x2e, 0xe4, 0x95, 0x5e, + 0x16, 0xad, 0x80, 0xf6, 0x20, 0x70, 0xf8, 0x85, 0xa6, 0x7b, 0xf4, 0x6c, 0xb3, 0x4d, 0x6d, 0x36, 0xb6, 0x16, 0x21, + 0x64, 0x20, 0x1a, 0xfa, 0x42, 0xce, 0x28, 0xf2, 0x55, 0x5a, 0xae, 0xd5, 0xc6, 0x2a, 0xe3, 0x05, 0x26, 0x82, 0x0c, + 0x67, 0xe1, 0x1d, 0x7a, 0x5a, 0x8f, 0x34, 0xc5, 0x24, 0x38, 0xe9, 0xe2, 0x2f, 0xc0, 0x86, 0xf2, 0x24, 0x37, 0x07, + 0xe4, 0x00, 0x2a, 0x97, 0xa2, 0x54, 0xca, 0xe0, 0x37, 0xea, 0x8e, 0x6c, 0xab, 0xfe, 0x3b, 0x0d, 0x64, 0x70, 0x07, + 0xfa, 0xb6, 0x17, 0x5a, 0x3b, 0xda, 0xb9, 0xb2, 0x35, 0x6d, 0x8b, 0x34, 0x8f, 0x91, 0xc5, 0x06, 0x90, 0x4f, 0xa4, + 0x73, 0x20, 0xf2, 0x9a, 0x68, 0xbc, 0xb3, 0x67, 0x7c, 0x3c, 0x15, 0x0f, 0xc9, 0x7b, 0x95, 0xef, 0x9b, 0x7b, 0x7d, + 0x30, 0xc6, 0xbe, 0x05, 0x65, 0xe2, 0x83, 0xd5, 0xd6, 0xba, 0xc4, 0x7a, 0xab, 0x34, 0x89, 0x6e, 0xb8, 0x82, 0x8e, + 0x23, 0x71, 0x83, 0x18, 0x1c, 0x33, 0x5e, 0x5b, 0x65, 0xe9, 0x2b, 0x2c, 0x73, 0x1d, 0xb3, 0x64, 0xc8, 0xa4, 0xce, + 0x13, 0x05, 0x4f, 0x7e, 0x9e, 0x90, 0x8c, 0x88, 0x9a, 0x6d, 0x39, 0x4a, 0xb9, 0x69, 0x01, 0x97, 0x19, 0x19, 0xc0, + 0x37, 0x69, 0x02, 0x50, 0x2e, 0x5f, 0x82, 0x54, 0x1a, 0x22, 0xb8, 0x66, 0x7b, 0xc9, 0xe8, 0xd6, 0xd1, 0x3a, 0xa8, + 0x92, 0xcc, 0x1d, 0x9c, 0xdb, 0x59, 0xa4, 0xd4, 0x9b, 0x8f, 0x30, 0xec, 0xe4, 0x43, 0x58, 0x27, 0xf8, 0x6d, 0x40, + 0x4d, 0xfa, 0x5c, 0x78, 0xd1, 0x08, 0xd0, 0xd4, 0x77, 0xaa, 0x8c, 0xcf, 0x85, 0x97, 0x8d, 0xb6, 0x2c, 0xa3, 0x14, + 0xaa, 0x0b, 0x66, 0xb7, 0xa6, 0x0b, 0x31, 0xaf, 0xaa, 0x81, 0x36, 0xc8, 0xed, 0x3a, 0x66, 0x40, 0xa3, 0xb6, 0x2b, + 0x8f, 0x2c, 0xc0, 0xad, 0x99, 0x08, 0x8c, 0x9c, 0x7f, 0x9f, 0x5f, 0xab, 0x70, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, + 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xa7, 0xf4, 0xfb, 0x69, 0x03, 0xaa, + 0x12, 0x61, 0x22, 0xee, 0xf5, 0x1b, 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x48, + 0x10, 0x59, 0x1a, 0x9b, 0x7b, 0xc9, 0x96, 0x6a, 0xa9, 0x74, 0x8c, 0x2a, 0x23, 0x6a, 0xe9, 0x6c, 0x8e, 0x15, 0x23, + 0xed, 0x1c, 0x94, 0x0c, 0xc8, 0xb4, 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x89, 0xc9, 0x08, 0x2b, 0xdb, 0xf2, 0x76, + 0x93, 0xaa, 0xe9, 0x9c, 0xdc, 0xdc, 0x2a, 0xe5, 0xe6, 0x56, 0xf0, 0xfc, 0x1b, 0xba, 0xe5, 0x92, 0x6b, 0x2f, 0xb3, + 0x69, 0xa1, 0x74, 0xcb, 0xb8, 0x06, 0x5b, 0xfb, 0x26, 0x90, 0x65, 0x3e, 0x50, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x37, + 0xc8, 0x56, 0xc4, 0xa8, 0x53, 0x16, 0x8c, 0xbf, 0xdd, 0xd1, 0x03, 0x19, 0xa8, 0xaa, 0x6a, 0xe3, 0xe0, 0xce, 0x4a, + 0x7f, 0x58, 0x5e, 0x3c, 0x65, 0x89, 0x95, 0x4e, 0x2e, 0x54, 0xa1, 0x3f, 0x08, 0xd1, 0x4d, 0x65, 0xc3, 0xc1, 0xa1, + 0x2e, 0xb6, 0x32, 0x20, 0xf4, 0x30, 0xbd, 0xb7, 0xb1, 0x92, 0xe5, 0xae, 0x29, 0x5f, 0xcc, 0x78, 0xc2, 0x71, 0xf4, + 0xe5, 0x6a, 0x11, 0xd6, 0x6a, 0x91, 0x9d, 0x00, 0x0f, 0xad, 0xd5, 0x52, 0xc8, 0xd5, 0x22, 0x9c, 0x99, 0x2e, 0xd4, + 0x4c, 0xcf, 0x40, 0x01, 0x29, 0xd4, 0x2c, 0x4f, 0x00, 0x16, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, + 0xfe, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, 0x2d, 0x77, 0xa3, 0xd3, 0x88, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0xa9, + 0xfa, 0xfd, 0xb4, 0x44, 0xac, 0x1e, 0x03, 0x23, 0x28, 0x87, 0xca, 0xd1, 0x7e, 0x59, 0x58, 0x92, 0x25, 0x61, 0x49, + 0xee, 0xd5, 0x38, 0x97, 0x96, 0x8b, 0x57, 0x49, 0x20, 0x12, 0x19, 0x2f, 0xa5, 0x09, 0x3e, 0xe1, 0xe5, 0xc8, 0x48, + 0xcd, 0x93, 0x9b, 0xd4, 0xcb, 0x59, 0xc6, 0xc6, 0x88, 0x61, 0x14, 0xfa, 0x4d, 0xd5, 0xef, 0xe7, 0xa5, 0x97, 0x53, + 0x3b, 0x3f, 0x83, 0xeb, 0xe5, 0xa9, 0xb3, 0xc8, 0x11, 0xf2, 0x6a, 0x24, 0x15, 0x96, 0xd7, 0x4a, 0x3d, 0x7d, 0x09, + 0x3e, 0xa8, 0xbb, 0x37, 0x0a, 0x80, 0xb8, 0xc8, 0xa5, 0x7f, 0x6d, 0x09, 0x97, 0xa6, 0xdc, 0xc0, 0xa0, 0x87, 0x3c, + 0x27, 0x21, 0x54, 0x82, 0x90, 0x14, 0xd6, 0x8d, 0xfb, 0xe2, 0xe9, 0xc4, 0x75, 0x67, 0xb1, 0x81, 0x09, 0x0e, 0x07, + 0x40, 0x3c, 0x98, 0x7a, 0xd1, 0x80, 0x97, 0x6a, 0xce, 0x7c, 0xf4, 0x72, 0x82, 0xc9, 0x00, 0x55, 0xc5, 0xc0, 0x29, + 0xeb, 0x89, 0x7c, 0x64, 0xdc, 0xcc, 0x7c, 0x3f, 0xc0, 0x77, 0xeb, 0x42, 0xa2, 0x3f, 0x28, 0x80, 0x82, 0x4c, 0x01, + 0x14, 0x24, 0x06, 0xa0, 0x20, 0x36, 0x00, 0x05, 0x9b, 0x86, 0x2f, 0xa5, 0x0e, 0x37, 0x02, 0xba, 0x08, 0x1f, 0x7a, + 0x16, 0x36, 0x56, 0x28, 0x9e, 0x8d, 0xd9, 0x98, 0x15, 0x6a, 0xe7, 0xc9, 0xe5, 0x54, 0xec, 0x2c, 0xc6, 0xba, 0x8a, + 0xac, 0x13, 0x2f, 0x24, 0x14, 0x39, 0xe7, 0x46, 0xa2, 0xee, 0x7e, 0xee, 0xbd, 0x24, 0x63, 0xc9, 0xbc, 0xa1, 0x51, + 0x83, 0x79, 0xd9, 0x75, 0x00, 0xd3, 0x92, 0x6f, 0x0b, 0x1a, 0x4c, 0xa7, 0xca, 0x23, 0xd2, 0x24, 0xa8, 0x9d, 0xcb, + 0xa4, 0xc8, 0x09, 0x61, 0x12, 0xf4, 0x4a, 0xf0, 0x1b, 0x89, 0xf2, 0xff, 0x4d, 0x27, 0x78, 0x80, 0x63, 0xa2, 0x55, + 0xf2, 0x15, 0x0c, 0x98, 0x39, 0x7f, 0x2e, 0x9d, 0xb2, 0x11, 0x8a, 0xb1, 0x4c, 0xe3, 0xd1, 0x57, 0x36, 0x44, 0x68, + 0xab, 0xe7, 0x68, 0x62, 0x82, 0x3a, 0xc0, 0x23, 0xfa, 0x6b, 0xf4, 0xd5, 0x50, 0xa8, 0x74, 0x35, 0x52, 0xd7, 0xec, + 0x9c, 0xf3, 0x77, 0xb5, 0xe1, 0x44, 0xc6, 0xb4, 0x29, 0xf0, 0x0d, 0x08, 0xe4, 0x1b, 0x08, 0x00, 0x57, 0x4d, 0x67, + 0xf6, 0x0a, 0xe0, 0x1c, 0x08, 0xe0, 0x71, 0xde, 0xf1, 0xf8, 0x81, 0xfe, 0x2a, 0x8e, 0x7b, 0xa7, 0x69, 0xd8, 0xfe, + 0x2b, 0x30, 0x16, 0x43, 0x39, 0x9e, 0xef, 0x14, 0x24, 0x7b, 0x94, 0xb2, 0x74, 0xd5, 0x44, 0x76, 0x28, 0xd6, 0xa7, + 0x39, 0x65, 0x2c, 0x6d, 0xcb, 0x31, 0xda, 0x78, 0xfd, 0x10, 0x8f, 0x6f, 0x6e, 0xf4, 0xe4, 0x83, 0x1e, 0xdc, 0xde, + 0x5e, 0xbf, 0xec, 0x31, 0x9b, 0x6f, 0xc5, 0xe2, 0x59, 0x11, 0x27, 0x4e, 0xeb, 0x90, 0x03, 0x1c, 0xe4, 0x24, 0x04, + 0xd2, 0x31, 0x2e, 0xb5, 0xe8, 0xa0, 0x66, 0x39, 0xaf, 0x81, 0x65, 0x16, 0x41, 0x36, 0x40, 0x54, 0xd3, 0x54, 0xac, + 0x86, 0x07, 0xa5, 0x6a, 0x4e, 0xa9, 0xd4, 0xbe, 0xe1, 0x6c, 0x75, 0xfa, 0xc4, 0xaa, 0x4d, 0xb8, 0xf5, 0x6f, 0xb5, + 0x27, 0x68, 0x2b, 0x69, 0x20, 0xd4, 0xf3, 0x65, 0xba, 0xa4, 0x28, 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, + 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, + 0xc9, 0x3f, 0x84, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, + 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, + 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, 0x9a, 0xa7, 0xd5, 0x07, 0xf5, 0xf7, 0xfb, 0x05, + 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, 0x68, 0x09, 0xe0, 0x98, 0xa5, 0x3d, 0x14, 0xb2, + 0x60, 0x82, 0x35, 0x54, 0xe5, 0x29, 0x9f, 0xbd, 0x7c, 0x72, 0x03, 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, + 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, + 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, + 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, + 0xb6, 0x02, 0xc4, 0xc0, 0x52, 0x87, 0x24, 0xab, 0x8e, 0xed, 0xf7, 0x5f, 0x8d, 0x0c, 0x6f, 0x3a, 0x22, 0xc2, 0xe8, + 0xdf, 0x15, 0x08, 0x50, 0xb0, 0xcc, 0x6c, 0x67, 0x26, 0x5d, 0xed, 0x59, 0x3d, 0x6f, 0x36, 0x79, 0x57, 0xef, 0x58, + 0x4d, 0xcb, 0xa9, 0x69, 0x95, 0xd5, 0xb4, 0x49, 0x0e, 0x35, 0x13, 0xfd, 0xbe, 0xc6, 0x47, 0xcd, 0xe7, 0x80, 0xcb, + 0x86, 0xc9, 0xaf, 0x66, 0xd5, 0xbc, 0xdf, 0xf7, 0xe4, 0x23, 0xf8, 0x85, 0xc4, 0x65, 0x6e, 0x8d, 0xe5, 0xd3, 0xd7, + 0xc4, 0x67, 0x66, 0x10, 0x8f, 0x56, 0x47, 0x50, 0x5f, 0x9f, 0x84, 0xd7, 0x31, 0x57, 0xd8, 0x4c, 0x4c, 0x5f, 0xc1, + 0xe0, 0x79, 0xc2, 0x07, 0x6f, 0x39, 0xfa, 0x1b, 0xe9, 0xcc, 0x14, 0x2c, 0xe4, 0xdc, 0x9f, 0xbc, 0x42, 0xe8, 0x64, + 0x44, 0x7a, 0xd0, 0xe9, 0x04, 0x0d, 0xd9, 0xef, 0xdf, 0x42, 0x67, 0xb6, 0x52, 0x29, 0x5b, 0x15, 0x95, 0xe9, 0xba, + 0x2e, 0xca, 0x0a, 0x3a, 0x96, 0x7e, 0xde, 0x0a, 0x99, 0x59, 0x3f, 0xb3, 0x90, 0x9f, 0x6e, 0x25, 0xd6, 0x94, 0x6d, + 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, + 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, 0xf4, 0xa5, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, + 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, 0x39, 0x79, 0x05, 0xe0, 0x74, 0x88, 0x88, 0x5b, + 0x91, 0xa0, 0x63, 0xd5, 0xf0, 0xc6, 0xc2, 0x3d, 0xed, 0xa5, 0x71, 0x2f, 0xcd, 0xcf, 0xd2, 0x7e, 0xdf, 0x00, 0x68, + 0xa6, 0x88, 0x0c, 0x8f, 0x33, 0x72, 0x97, 0xb4, 0x10, 0x4c, 0x69, 0xff, 0xd5, 0x18, 0x12, 0x04, 0x02, 0xfe, 0x0f, + 0xe1, 0x7d, 0x00, 0xb4, 0x4d, 0xda, 0x80, 0xab, 0x1e, 0xd3, 0x81, 0xd9, 0x92, 0xb3, 0x55, 0x67, 0x03, 0x50, 0x4e, + 0x95, 0xd6, 0x53, 0x1e, 0xd7, 0x14, 0x11, 0xa9, 0xb2, 0x50, 0xbf, 0xb1, 0x9e, 0x4c, 0x56, 0xb9, 0xc8, 0x90, 0xa3, + 0x32, 0xbd, 0xab, 0x19, 0x21, 0x76, 0xe9, 0xe7, 0x37, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0x80, 0xb4, 0x9d, + 0xb5, 0xab, 0x6a, 0x97, 0xe3, 0xd6, 0x6e, 0x0e, 0x48, 0xbe, 0xde, 0x68, 0x34, 0xd2, 0x7e, 0x72, 0x02, 0x86, 0xaa, + 0xa7, 0x96, 0x42, 0x8f, 0xd5, 0x0a, 0x5b, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x6b, 0xf3, 0xd1, + 0x87, 0x4b, 0x65, 0xed, 0x3a, 0xe2, 0xeb, 0x3f, 0xca, 0x6a, 0x7d, 0xcf, 0xbb, 0xaa, 0x09, 0xf8, 0xa2, 0x8a, 0x2d, + 0xfd, 0x8e, 0xf7, 0x64, 0xef, 0xe2, 0x6b, 0x9f, 0xb0, 0x4b, 0xbe, 0xe7, 0x2d, 0xea, 0x3c, 0x5f, 0xf9, 0xba, 0x51, + 0xa5, 0xdb, 0x7b, 0xc9, 0x0d, 0xae, 0xbd, 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7a, + 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, 0x1a, 0xfa, 0xd0, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, + 0x87, 0xde, 0x92, 0x93, 0x43, 0x82, 0xc1, 0xa9, 0x31, 0x7f, 0x78, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x89, 0xc9, + 0x7c, 0x7a, 0x4c, 0x3b, 0x0a, 0x30, 0xa3, 0x4a, 0x6f, 0x9f, 0x1e, 0xd8, 0x8e, 0x97, 0xf5, 0xd0, 0xd2, 0xbb, 0x27, + 0x47, 0xb7, 0xe3, 0x55, 0x35, 0xbe, 0x94, 0x43, 0x9e, 0xe7, 0xb3, 0xd1, 0x68, 0x24, 0x0c, 0x3a, 0x77, 0xa5, 0x37, + 0xb0, 0x02, 0x19, 0x5c, 0x54, 0x1f, 0xca, 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, + 0x63, 0x1c, 0x70, 0x4e, 0x0a, 0x25, 0x47, 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, + 0x1a, 0x21, 0x1f, 0x82, 0x9f, 0x3c, 0x50, 0x8b, 0x3f, 0xd3, 0x82, 0xd8, 0x43, 0x9f, 0x2a, 0xa5, 0x43, 0xbc, 0x2a, + 0x20, 0x44, 0x18, 0xf0, 0x06, 0xda, 0x41, 0x09, 0x0e, 0x3b, 0xdc, 0x23, 0x44, 0x88, 0x7e, 0xe9, 0xe5, 0x33, 0x19, + 0xae, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x88, 0x95, 0x3e, 0x03, 0x17, 0x4c, 0x40, 0x3d, 0xc5, 0xa7, 0xe8, 0x5f, 0x6f, + 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x80, 0x8a, 0xe8, 0xd9, 0xcf, 0xc7, 0x00, 0xde, 0xd9, 0xb5, 0x19, 0x69, 0x2f, 0x7f, + 0x03, 0x0c, 0x2b, 0x25, 0x89, 0x76, 0x4e, 0x89, 0xc0, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x93, + 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, 0x01, 0x8f, 0x0e, 0x40, 0xe5, 0x4a, 0x41, 0xee, 0x35, 0x47, 0x72, 0xc7, + 0x0f, 0xbd, 0x1f, 0x06, 0xf5, 0xe0, 0x87, 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0x7e, + 0x18, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, 0x8b, 0xdc, 0x6a, 0xa2, 0xc6, 0x4d, 0x78, 0x97, 0x48, 0x1a, 0xa2, 0x6d, + 0xe7, 0x11, 0x71, 0x03, 0x20, 0x59, 0x7c, 0x36, 0x6f, 0x28, 0xea, 0xdd, 0x84, 0x6f, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, + 0x75, 0x9e, 0xd6, 0x3d, 0x1d, 0x2a, 0x83, 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0x2f, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, + 0x48, 0xb9, 0x51, 0x25, 0xea, 0xb7, 0x58, 0xcd, 0x7a, 0x88, 0xc8, 0x9d, 0x65, 0xc6, 0xde, 0x5e, 0xf0, 0x4a, 0xce, + 0xaa, 0xd8, 0x2e, 0xc7, 0x57, 0x84, 0xb5, 0x95, 0x04, 0xe8, 0x68, 0x3d, 0xd6, 0xa6, 0x18, 0xf9, 0x95, 0x42, 0x02, + 0x2e, 0x3a, 0xb6, 0x16, 0x8a, 0x8d, 0x17, 0xa0, 0x2f, 0xd9, 0x99, 0x06, 0x58, 0x6f, 0xf4, 0x2a, 0xe2, 0xb6, 0x7c, + 0xa0, 0xc2, 0x9b, 0xdc, 0x54, 0x99, 0x95, 0xcd, 0x4d, 0xbb, 0x9f, 0x2a, 0x5e, 0x21, 0x6e, 0xbd, 0x51, 0x7b, 0x14, + 0xa0, 0xf6, 0xd0, 0x42, 0x19, 0xa0, 0x4b, 0xd3, 0x0c, 0x00, 0x19, 0x00, 0x64, 0xaa, 0x88, 0xcf, 0x04, 0xa8, 0xb4, + 0xd5, 0x8d, 0x02, 0x27, 0xd2, 0x4b, 0x60, 0x5c, 0x60, 0xa5, 0x8f, 0x6c, 0x64, 0xb0, 0xd8, 0x22, 0xc0, 0x2d, 0x47, + 0xfa, 0x30, 0x0d, 0x27, 0xdb, 0x68, 0x0e, 0x93, 0x34, 0xbf, 0x0b, 0xb3, 0x54, 0x42, 0x4b, 0xbc, 0x96, 0x35, 0x46, + 0x2c, 0x20, 0x7d, 0x9f, 0xbe, 0x29, 0xb2, 0x98, 0x20, 0xe1, 0xac, 0xa7, 0x0e, 0xa0, 0x9a, 0x9c, 0x6b, 0x4d, 0xab, + 0x67, 0xb5, 0xc9, 0x43, 0x16, 0xe8, 0xec, 0xc1, 0x98, 0xd4, 0x72, 0x43, 0x8f, 0xec, 0xaf, 0x1c, 0xcf, 0x08, 0xdf, + 0xf5, 0x0c, 0xa7, 0xfe, 0xfb, 0x54, 0x03, 0x29, 0x53, 0x02, 0x08, 0x32, 0x38, 0x9a, 0x10, 0xca, 0xd3, 0x31, 0x99, + 0xda, 0xfc, 0x08, 0x84, 0x23, 0x82, 0x57, 0xf0, 0xdc, 0xd0, 0xba, 0xe5, 0xc6, 0xce, 0x22, 0x4f, 0x13, 0x40, 0x16, + 0x2f, 0xf8, 0x1d, 0x20, 0x73, 0xea, 0x55, 0x21, 0x7b, 0xf6, 0x5c, 0x4c, 0x67, 0xf3, 0xe0, 0xcf, 0x84, 0xf6, 0x2f, + 0x26, 0xfc, 0xa6, 0xbb, 0x4a, 0xae, 0x4c, 0xad, 0x7b, 0x13, 0x3d, 0xe6, 0x72, 0xa7, 0x4f, 0x2b, 0x8e, 0x11, 0xcf, + 0x60, 0x15, 0x90, 0x73, 0x36, 0xe4, 0xcf, 0xce, 0x01, 0xbb, 0x65, 0x25, 0xbc, 0x88, 0x3f, 0x0b, 0x65, 0xb5, 0x00, + 0xf9, 0x91, 0xf3, 0xc8, 0xfc, 0xf2, 0xd5, 0x76, 0x28, 0xe7, 0x14, 0x45, 0xb4, 0x9c, 0x9a, 0x96, 0x14, 0xb2, 0x43, + 0x4f, 0xc1, 0x64, 0x6a, 0xcb, 0xdf, 0x77, 0x89, 0x4b, 0xf2, 0xcd, 0x24, 0xb2, 0xaf, 0x03, 0xac, 0x59, 0xab, 0xee, + 0xa1, 0x1b, 0x82, 0x01, 0x22, 0x23, 0x94, 0xd9, 0x5c, 0xdf, 0xad, 0x07, 0x03, 0x05, 0xf3, 0x2b, 0xe8, 0xa6, 0x45, + 0xa7, 0x38, 0x40, 0xce, 0x5a, 0xd7, 0xa8, 0x54, 0x15, 0x87, 0x0e, 0xf3, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, + 0x52, 0xa3, 0xae, 0x82, 0x45, 0x4a, 0x45, 0x14, 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, + 0x88, 0x41, 0x0a, 0x88, 0x53, 0x7e, 0x05, 0x68, 0xa2, 0x8b, 0x28, 0xcc, 0x5e, 0xc7, 0x55, 0x50, 0x5b, 0x4d, 0xbf, + 0x77, 0x20, 0x63, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, 0x46, 0x3f, 0x8c, 0xc2, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, + 0xe6, 0x95, 0x3f, 0xe1, 0x15, 0x5d, 0x6e, 0x6d, 0xca, 0x15, 0x8d, 0x0b, 0x7f, 0x8d, 0xe0, 0xf0, 0xa9, 0xa3, 0xd8, + 0x6e, 0x53, 0xe5, 0xd4, 0xc6, 0x60, 0x10, 0xc2, 0x7d, 0x2b, 0xe3, 0xf7, 0x89, 0x97, 0xcf, 0xa2, 0x39, 0x28, 0x4a, + 0x33, 0xcd, 0x17, 0x52, 0x48, 0x37, 0x01, 0xfa, 0x68, 0x10, 0x6a, 0x75, 0xe5, 0xa7, 0xc4, 0x4b, 0xd5, 0xb4, 0x36, + 0x4f, 0xb1, 0x46, 0x81, 0x98, 0x45, 0xf3, 0x86, 0x65, 0x74, 0x48, 0xaa, 0xcb, 0xa5, 0x69, 0xc6, 0x27, 0xab, 0x19, + 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0xf4, 0x09, 0x2e, 0x80, 0x3f, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, + 0x04, 0x31, 0x62, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x32, 0x64, 0x92, 0x90, 0xa7, 0x0f, + 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xbf, 0x72, 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0xe0, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, + 0x15, 0x9c, 0x5f, 0x12, 0xfc, 0xae, 0xfa, 0x11, 0x66, 0x19, 0x54, 0x01, 0x19, 0x7f, 0x2c, 0x14, 0xf5, 0xbc, 0xc5, + 0xec, 0x3e, 0x52, 0x17, 0x94, 0x59, 0x3a, 0xb7, 0x38, 0x41, 0xc0, 0x79, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, + 0x69, 0x46, 0x81, 0xea, 0x08, 0xf0, 0xd9, 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0x91, 0x85, 0xfa, 0x9b, 0x6f, 0xe5, 0xac, + 0x21, 0x79, 0x20, 0xd5, 0xdc, 0xc7, 0x70, 0x6a, 0xdc, 0xe0, 0x4b, 0x37, 0xbd, 0xa9, 0xe0, 0x35, 0x21, 0x73, 0xdf, + 0xa0, 0xb5, 0xef, 0x06, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, + 0x5f, 0xbb, 0xf8, 0xc5, 0x29, 0xd2, 0xb3, 0xe8, 0x02, 0x03, 0x5d, 0x90, 0x79, 0xe3, 0x9f, 0x15, 0xac, 0x5c, 0x40, + 0xef, 0xa5, 0x62, 0x25, 0x27, 0xdb, 0x4e, 0xfd, 0x51, 0x2a, 0xfb, 0xed, 0x99, 0x35, 0x81, 0xdf, 0x27, 0xf6, 0x4b, + 0x64, 0xf2, 0x4d, 0x8f, 0x4d, 0xbe, 0x32, 0x2c, 0x3a, 0xb5, 0x0c, 0xce, 0xe9, 0x91, 0xc1, 0xb9, 0xb7, 0xb3, 0x6a, + 0x13, 0xc2, 0x50, 0x90, 0x04, 0x9a, 0x2e, 0x3c, 0xac, 0x9b, 0xfe, 0xfc, 0xa4, 0x45, 0xb5, 0x55, 0xfb, 0xd6, 0xfd, + 0x38, 0xc4, 0x2e, 0x7e, 0x9f, 0x78, 0x86, 0x88, 0xd4, 0x07, 0x3a, 0x30, 0x19, 0x3c, 0x71, 0xd9, 0xef, 0x43, 0x61, + 0xb3, 0xf1, 0x7c, 0x54, 0x17, 0x6f, 0x8a, 0x7b, 0x40, 0x75, 0xa8, 0xc0, 0x2e, 0x87, 0x32, 0x94, 0x11, 0x9b, 0xda, + 0x72, 0xcf, 0x1f, 0xd7, 0x61, 0x0e, 0xf2, 0x8e, 0x86, 0xc7, 0x39, 0x03, 0x31, 0x0c, 0xbe, 0xfe, 0xc3, 0xa3, 0x7d, + 0xda, 0xfc, 0x70, 0x06, 0xdf, 0x1d, 0x9d, 0x7d, 0x40, 0xba, 0x9b, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x38, 0xfb, + 0x01, 0x52, 0x7f, 0x38, 0x2b, 0xca, 0xb3, 0x1f, 0x54, 0x65, 0x7e, 0x38, 0xa3, 0x05, 0x37, 0xfa, 0xc3, 0x9a, 0x78, + 0xbf, 0x57, 0x9a, 0x01, 0x6d, 0x01, 0x91, 0x59, 0x5a, 0xfd, 0x08, 0x4a, 0x44, 0xc5, 0x8f, 0x2a, 0xa3, 0x5a, 0xad, + 0x1d, 0xe7, 0x51, 0xa2, 0x91, 0xb2, 0x69, 0x42, 0xe2, 0x6a, 0x09, 0xeb, 0x50, 0xcf, 0x4e, 0x9b, 0x6f, 0xc7, 0x79, + 0xa0, 0x0e, 0x88, 0x9c, 0x3f, 0xcb, 0x47, 0x5b, 0xfa, 0x1a, 0x7c, 0xeb, 0x70, 0xc8, 0x47, 0x3b, 0xf3, 0xd3, 0x27, + 0x6b, 0xa5, 0x8c, 0x3b, 0x52, 0xe4, 0x42, 0xc8, 0x19, 0xb7, 0xed, 0x31, 0xe0, 0x00, 0xf0, 0x0f, 0x07, 0xfa, 0xbd, + 0x93, 0xbf, 0xd5, 0x6e, 0x69, 0xd5, 0xf3, 0x43, 0x8b, 0x3b, 0xe3, 0x75, 0x6d, 0x88, 0xda, 0xf6, 0x12, 0x5b, 0x7a, + 0xdf, 0x34, 0xa8, 0x29, 0xa2, 0x9f, 0xb0, 0x9a, 0x58, 0xc5, 0x61, 0x41, 0x4a, 0x48, 0x62, 0x38, 0x46, 0x3b, 0xf4, + 0x38, 0x5d, 0x2c, 0x3d, 0xb9, 0xef, 0xf0, 0x72, 0xeb, 0xfb, 0x80, 0xa4, 0x55, 0x38, 0x7f, 0xe4, 0x85, 0x06, 0x1e, + 0xbd, 0xc8, 0xab, 0x22, 0x13, 0x23, 0x41, 0xa3, 0xfc, 0x9a, 0xc4, 0x99, 0x33, 0xac, 0xc5, 0x99, 0x02, 0x0b, 0x0b, + 0x09, 0xdd, 0xbb, 0x28, 0x29, 0x3d, 0x38, 0x7b, 0xb4, 0x2f, 0x9b, 0x3f, 0x08, 0x1e, 0x62, 0x74, 0x03, 0x8c, 0x38, + 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0x5e, 0xe6, 0x05, 0x84, 0x68, 0x9e, 0x49, 0xc5, 0x6a, 0x79, + 0x06, 0x8c, 0x79, 0x22, 0x3e, 0x0b, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xf5, 0x36, 0x9e, 0x7b, 0x40, 0xf1, 0xfd, + 0x28, 0x01, 0x2e, 0x77, 0x9f, 0xbd, 0x52, 0xae, 0xa9, 0xa4, 0x47, 0x9e, 0x43, 0xb4, 0xe4, 0x75, 0x02, 0x14, 0xcf, + 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, + 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, + 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0xad, 0xcc, 0xbd, 0x10, 0x86, 0x2a, 0xe1, 0xde, 0xeb, 0x7a, 0x16, 0xca, 0x4d, 0xd1, + 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, 0xdf, 0x26, 0x5e, 0x0c, 0x86, 0xeb, 0x05, 0x2f, + 0x67, 0x1b, 0xb3, 0x10, 0x0e, 0x87, 0xcd, 0xa4, 0x98, 0x2d, 0x20, 0xcc, 0x75, 0x31, 0x3f, 0x1c, 0xba, 0x5a, 0xb6, + 0x16, 0x1e, 0x3c, 0x54, 0x2d, 0xdc, 0x34, 0x2c, 0x87, 0x9f, 0xc9, 0x2c, 0xc6, 0xf6, 0x35, 0x3e, 0xb3, 0x3f, 0x5f, + 0x74, 0xcf, 0x12, 0x24, 0xdf, 0x58, 0x03, 0xed, 0xd8, 0xac, 0xdd, 0xe1, 0x6a, 0x04, 0x24, 0xa5, 0xbb, 0xd1, 0xdf, + 0x95, 0x9d, 0x3c, 0x25, 0xc8, 0x1d, 0xad, 0xc0, 0x7e, 0xf7, 0x8d, 0x3f, 0xd1, 0x62, 0x0f, 0xda, 0x6d, 0x6c, 0x09, + 0x51, 0x4d, 0x7b, 0x2e, 0x57, 0x8a, 0xa5, 0x79, 0x2b, 0x6d, 0xf4, 0x7c, 0x58, 0x9f, 0xfb, 0x46, 0x0e, 0x14, 0x8c, + 0x11, 0x4f, 0xad, 0x83, 0x68, 0x36, 0x07, 0x1a, 0x0c, 0x34, 0x8f, 0xf0, 0xd4, 0x42, 0x07, 0x65, 0xd6, 0x86, 0xfd, + 0x3c, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, 0x31, 0xc5, 0xf6, 0xf8, 0x57, 0xa5, 0xa8, 0xf0, + 0xd8, 0x8e, 0xb8, 0xd6, 0x3e, 0x89, 0xda, 0x50, 0x39, 0xfc, 0x4b, 0xd8, 0x47, 0xd8, 0x5f, 0x68, 0x82, 0x30, 0xd8, + 0xf5, 0x67, 0x02, 0x21, 0x62, 0x21, 0x5e, 0xf0, 0xaf, 0x4a, 0x52, 0xd1, 0x09, 0x9f, 0xed, 0x4a, 0xe0, 0xad, 0xc3, + 0x80, 0x3e, 0x21, 0x3f, 0x13, 0x09, 0x43, 0x33, 0xa1, 0x77, 0xf4, 0xdf, 0x89, 0x9d, 0x6c, 0x92, 0x5b, 0x21, 0x1f, + 0x48, 0x2a, 0x09, 0x26, 0x58, 0x79, 0xa1, 0xfc, 0xd1, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x3c, 0xf1, + 0x0c, 0xfe, 0x1e, 0xc8, 0x18, 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x67, 0xeb, + 0x2c, 0xac, 0x17, 0x45, 0xb9, 0x6a, 0x45, 0x8a, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x22, 0x1f, + 0x3c, 0x02, 0x60, 0x3c, 0xca, 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x27, 0xca, 0x80, 0x47, 0x58, + 0x06, 0xe6, 0x69, 0x97, 0xa1, 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0x4e, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, + 0x31, 0x34, 0x75, 0xe5, 0x91, 0xf5, 0x92, 0x13, 0xf6, 0x64, 0x37, 0x90, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0x5d, 0xcb, + 0x12, 0xe5, 0xa2, 0x5b, 0x46, 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0xb4, 0x6f, 0x8f, + 0x14, 0xbd, 0x60, 0xd0, 0x3e, 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, + 0x7c, 0x07, 0x33, 0xe3, 0x6c, 0xf6, 0x87, 0xde, 0xdc, 0x1e, 0xed, 0xeb, 0xe6, 0x0f, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, + 0x13, 0x9f, 0x2b, 0x16, 0x2a, 0xab, 0x10, 0x2b, 0x48, 0xfb, 0x5f, 0xc2, 0xfb, 0x03, 0xde, 0x1a, 0xa1, 0x59, 0x19, + 0x0f, 0xf3, 0xd1, 0xa3, 0xbd, 0x68, 0xfe, 0xe8, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0x7f, 0x1c, 0x25, 0xcd, 0xd9, + 0xc3, 0x35, 0x92, 0x3a, 0xc0, 0x87, 0xeb, 0x33, 0x7c, 0xa0, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0x1f, + 0xad, 0xe7, 0xf4, 0xf1, 0x63, 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xbc, 0x19, + 0xd2, 0xbb, 0x6e, 0x95, 0xd4, 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, + 0x9b, 0xd5, 0x9c, 0x00, 0x11, 0x01, 0xad, 0x55, 0xde, 0x07, 0x8e, 0xf9, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x73, + 0xa5, 0xbd, 0x92, 0x02, 0xfa, 0x39, 0xc8, 0xdc, 0x3e, 0xba, 0xe5, 0xaa, 0x65, 0x9e, 0x4b, 0x5b, 0x0e, 0x58, 0xb4, + 0x10, 0xa8, 0xd9, 0xb9, 0x74, 0x38, 0x50, 0x10, 0xea, 0x4a, 0x54, 0x11, 0x57, 0x47, 0xd1, 0x42, 0xd4, 0x6a, 0xd5, + 0x2e, 0x27, 0x9b, 0x0a, 0xd9, 0x92, 0x08, 0x32, 0x4a, 0x31, 0x74, 0xe9, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0x03, 0x34, + 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0xc0, 0x69, 0x0e, 0x31, 0x7f, 0x7e, + 0xd7, 0x83, 0x0a, 0x1e, 0x74, 0xa4, 0xbf, 0xae, 0x67, 0x05, 0x9e, 0xb9, 0x27, 0x9e, 0xbf, 0x3a, 0x91, 0x5e, 0xe4, + 0xf0, 0x40, 0xd3, 0x20, 0x66, 0xfc, 0x79, 0x59, 0x86, 0xbb, 0xd1, 0xa2, 0x2c, 0x56, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, + 0x8a, 0x81, 0xc4, 0x8c, 0x99, 0xd1, 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, + 0xeb, 0x02, 0xb0, 0x1c, 0xb2, 0x06, 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0xb2, 0xa3, 0xb8, 0x01, 0xf4, 0xb3, + 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, 0x9d, 0x4c, 0xa6, 0x48, 0x2e, 0xdf, 0x86, 0xbd, 0x62, 0x45, 0x3e, 0x6f, 0xe4, + 0xf6, 0xf0, 0x2e, 0x5c, 0x89, 0x58, 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0xfb, 0x47, 0x55, + 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, 0xdb, 0xab, 0x6d, 0x25, 0x28, 0x81, 0x0f, 0xf6, 0x43, 0x29, 0x16, 0xe9, 0x56, + 0x00, 0xae, 0x03, 0xff, 0x4d, 0x22, 0x12, 0xba, 0x3b, 0x0f, 0x51, 0xac, 0x91, 0xf7, 0x0d, 0xa2, 0xb1, 0xbf, 0x04, + 0x39, 0x0d, 0xc8, 0x44, 0x8a, 0x91, 0x2c, 0x18, 0xf8, 0x00, 0x72, 0xbe, 0x06, 0x93, 0xdc, 0x34, 0xf7, 0xfc, 0x20, + 0xd7, 0x1d, 0x4c, 0xfb, 0xa0, 0x7b, 0x71, 0xad, 0x59, 0x0e, 0x5e, 0x31, 0x11, 0xff, 0xb9, 0xf6, 0x4a, 0x96, 0xb3, + 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, + 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, + 0x41, 0xe8, 0xe7, 0x1a, 0x90, 0x36, 0x98, 0xa4, 0x49, 0xa8, 0x7c, 0x70, 0x41, 0x37, 0xcc, 0xcb, 0x95, 0xcb, 0x55, + 0x93, 0xaa, 0xe5, 0x97, 0x23, 0xea, 0xbb, 0x5a, 0x72, 0xa9, 0x36, 0x9f, 0x1a, 0x65, 0x8d, 0x20, 0x93, 0xa3, 0xf4, + 0xfb, 0x94, 0x0b, 0xb7, 0x32, 0x26, 0xeb, 0xc3, 0xc1, 0x2b, 0xb8, 0xa9, 0xf1, 0xeb, 0x9c, 0x08, 0x45, 0xed, 0x21, + 0x11, 0xb6, 0x76, 0x2b, 0x74, 0xef, 0x71, 0xa3, 0x34, 0x8f, 0xb2, 0x4d, 0x2c, 0x2a, 0xaf, 0x97, 0x80, 0xb5, 0xb8, + 0x07, 0xbc, 0xa8, 0xb4, 0xf4, 0x2b, 0x56, 0x00, 0x7a, 0x80, 0x14, 0x36, 0x5e, 0x23, 0x03, 0xd6, 0x23, 0x2f, 0xf5, + 0xfb, 0x7d, 0x63, 0xca, 0x7f, 0x7f, 0x9f, 0x03, 0x49, 0xa1, 0x28, 0xeb, 0x1d, 0x4c, 0x20, 0xb8, 0x76, 0x92, 0xf6, + 0xac, 0xe6, 0xcf, 0xd6, 0xb5, 0x07, 0xfc, 0x56, 0xbe, 0x45, 0x62, 0xf5, 0xd2, 0xbe, 0xd8, 0xec, 0xd3, 0xea, 0x93, + 0xd1, 0x38, 0x08, 0x96, 0x56, 0xaf, 0xb5, 0xca, 0x21, 0x6f, 0x78, 0x01, 0x22, 0x95, 0x75, 0x75, 0xad, 0x9c, 0xab, + 0x6b, 0xc1, 0x91, 0x4b, 0xb6, 0xe4, 0x39, 0xfc, 0x17, 0x72, 0xaf, 0x3c, 0x1c, 0x0a, 0xbf, 0xdf, 0x4f, 0x67, 0xa4, + 0x95, 0x05, 0xf6, 0xb4, 0x75, 0xed, 0x85, 0xfe, 0xe1, 0xf0, 0x1a, 0xbc, 0x46, 0xfc, 0xc3, 0xa1, 0xec, 0xf7, 0x3f, + 0x9a, 0x9b, 0xcc, 0xf9, 0x58, 0x29, 0x65, 0x2f, 0x51, 0xe9, 0xfe, 0x39, 0xe1, 0xbd, 0xff, 0x3d, 0xfa, 0xdf, 0xa3, + 0xcb, 0x9e, 0x0a, 0x01, 0x4b, 0xf8, 0x0c, 0x6f, 0xe8, 0x4c, 0x5d, 0xce, 0x99, 0x74, 0x77, 0x57, 0x7e, 0xe8, 0x3d, + 0x0d, 0x15, 0xdf, 0x9b, 0x9b, 0x36, 0xfe, 0x5c, 0x1d, 0x69, 0x12, 0x3a, 0x2e, 0xfa, 0x87, 0xc3, 0x9b, 0x44, 0xeb, + 0xd3, 0x52, 0xa5, 0x4f, 0x53, 0x38, 0x4a, 0x86, 0xdc, 0xcd, 0x2d, 0x4c, 0x07, 0xf6, 0xe3, 0xe6, 0xab, 0xe4, 0xc5, + 0x59, 0x0a, 0xd7, 0xde, 0x7c, 0x96, 0xce, 0xa7, 0x60, 0x5d, 0x19, 0xe6, 0xb3, 0x7a, 0x1e, 0x40, 0xea, 0x10, 0xd2, + 0xac, 0x69, 0xf8, 0x8f, 0xca, 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0x81, 0x8b, 0x52, 0x47, 0xfa, 0xa4, 0x8d, 0xa6, 0x4b, + 0x2a, 0xf9, 0x8f, 0x22, 0x8f, 0x31, 0x66, 0xe3, 0x25, 0xf1, 0x7e, 0x16, 0xf9, 0x75, 0x01, 0xd8, 0x45, 0x00, 0x86, + 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0x63, 0xf2, 0xfd, 0x1f, 0xd3, 0xa5, 0x7d, 0x28, 0x8b, 0x65, 0x29, 0xaa, 0xea, 0xa8, + 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, + 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0x17, 0xbb, 0xd7, 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, + 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, + 0xaf, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, + 0xfe, 0x4c, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, 0xb2, 0xbc, 0x3a, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, + 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x33, 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, + 0x9b, 0x79, 0xe2, 0x19, 0xd0, 0x31, 0x3f, 0x43, 0x57, 0xc5, 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, + 0xf1, 0xce, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, + 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, + 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xab, 0xb3, 0x07, 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, + 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, + 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, + 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, + 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, + 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xa1, 0xb6, 0x2c, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, + 0x17, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, + 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xeb, 0x97, 0x67, 0x3f, 0xf4, + 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xce, 0x56, 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, + 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, + 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, + 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x69, 0x02, 0xa1, 0x16, 0xcc, + 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, + 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, + 0xfd, 0x48, 0x05, 0xe5, 0x24, 0xf4, 0x8b, 0x42, 0xbf, 0x34, 0x1c, 0x65, 0xcc, 0xbf, 0x84, 0x9a, 0x23, 0xa0, 0xde, + 0xf2, 0x50, 0xd1, 0x05, 0xe0, 0x72, 0x8e, 0x98, 0x71, 0xde, 0xe3, 0x2e, 0x30, 0xe7, 0xff, 0xe1, 0xed, 0x4b, 0xbc, + 0xdb, 0xb6, 0xb1, 0x7e, 0xff, 0x15, 0x8b, 0x2f, 0x55, 0x89, 0x08, 0x92, 0x25, 0x27, 0xe9, 0x4c, 0x29, 0xc3, 0xfa, + 0xdc, 0x2c, 0x6d, 0x3a, 0xcd, 0xd2, 0x24, 0x5d, 0x66, 0xf4, 0xf4, 0xb9, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, + 0x29, 0x2f, 0x91, 0xf8, 0xbf, 0xbf, 0x73, 0x2f, 0x56, 0x52, 0x94, 0x93, 0x99, 0xf7, 0xbd, 0x77, 0x72, 0x4e, 0x2c, + 0x82, 0x20, 0x76, 0x5c, 0x5c, 0xdc, 0xe5, 0x77, 0x4d, 0x08, 0x0a, 0x73, 0x1d, 0x2c, 0x0c, 0x00, 0xbd, 0x6b, 0x8f, + 0xb6, 0x9c, 0x74, 0x09, 0x16, 0xcf, 0x0d, 0x2c, 0x5e, 0x5d, 0x2c, 0xaa, 0x2b, 0xae, 0xe5, 0x16, 0x36, 0xa5, 0xac, + 0x62, 0x08, 0x20, 0xd0, 0x8c, 0x19, 0x76, 0xcb, 0x5d, 0x8e, 0x64, 0x5d, 0x14, 0x5c, 0xec, 0x04, 0x86, 0x6e, 0xc6, + 0x25, 0x33, 0x07, 0x57, 0x33, 0xac, 0x93, 0x8a, 0x02, 0xec, 0xea, 0x02, 0x64, 0x2f, 0x0c, 0x75, 0xdd, 0xcc, 0x96, + 0xeb, 0xc0, 0xd7, 0xa5, 0x0b, 0x5f, 0x52, 0xf0, 0x72, 0x25, 0x45, 0x99, 0x5d, 0xf3, 0x9f, 0xec, 0xcb, 0x66, 0x2c, + 0x29, 0xb4, 0x23, 0x7d, 0xd5, 0xee, 0x8e, 0x16, 0xe3, 0xd8, 0x72, 0x7c, 0x4b, 0xa5, 0x5b, 0x3d, 0xaa, 0x5e, 0x08, + 0x6d, 0x9d, 0x6b, 0x99, 0xa5, 0x29, 0x17, 0x2f, 0x45, 0x9a, 0x25, 0x5e, 0x72, 0xac, 0x63, 0x55, 0xbb, 0x20, 0x58, + 0x2e, 0x4c, 0xf2, 0xb3, 0xac, 0xc4, 0xd8, 0xc1, 0x8d, 0x46, 0xb5, 0xa2, 0x4e, 0x99, 0x18, 0x18, 0xf2, 0x1d, 0x06, + 0xdf, 0x66, 0x32, 0x01, 0x86, 0x1f, 0x13, 0xf5, 0x25, 0x3d, 0x85, 0x80, 0x0f, 0x2a, 0x34, 0xf7, 0x33, 0x8e, 0xe0, + 0xd7, 0x56, 0x65, 0x0e, 0x4c, 0xb6, 0x56, 0x41, 0x22, 0xee, 0x5d, 0x36, 0xd7, 0x8b, 0x68, 0xa1, 0xee, 0x42, 0xbd, + 0x78, 0xbb, 0xed, 0x25, 0x8a, 0x0e, 0x38, 0xf9, 0x69, 0xf0, 0x22, 0xce, 0x72, 0x9e, 0x1e, 0x54, 0xf2, 0x40, 0x6d, + 0xa8, 0x03, 0xe5, 0xcc, 0x01, 0x3b, 0xef, 0xeb, 0xea, 0x40, 0xaf, 0xe9, 0x03, 0xdd, 0xce, 0x03, 0xb8, 0x60, 0xe0, + 0xce, 0xbd, 0xcc, 0xae, 0xb9, 0x38, 0x00, 0x65, 0xa0, 0x35, 0x1e, 0xa8, 0xcb, 0x6a, 0xa4, 0x26, 0x46, 0xc7, 0xb0, + 0x4e, 0xf4, 0xc1, 0x1c, 0xd0, 0x9f, 0x21, 0xac, 0x7d, 0xeb, 0xed, 0x4a, 0x1f, 0xb4, 0x01, 0x7d, 0xb7, 0x34, 0x7d, + 0xd0, 0x81, 0xe3, 0x55, 0x74, 0xe0, 0xc6, 0x90, 0x6a, 0xd0, 0x56, 0x23, 0xab, 0x40, 0xf1, 0x86, 0xb7, 0x78, 0x77, + 0xae, 0x25, 0x1b, 0xef, 0x25, 0x62, 0x7c, 0x65, 0xa2, 0x8a, 0x33, 0x71, 0xea, 0xa5, 0xf2, 0x5a, 0x3b, 0xc9, 0x08, + 0xe3, 0x5b, 0x56, 0x52, 0x7f, 0x87, 0x98, 0x5b, 0xa4, 0x39, 0x0c, 0x5e, 0x86, 0x15, 0x99, 0xf1, 0x7e, 0x5f, 0xce, + 0x64, 0x54, 0xce, 0xc4, 0x61, 0x19, 0x29, 0xb0, 0xb6, 0x7d, 0x22, 0xa0, 0x7b, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0xba, + 0x4f, 0xf8, 0x73, 0x9f, 0xd4, 0xa7, 0x53, 0xe8, 0x53, 0x68, 0xeb, 0x15, 0x57, 0x10, 0xaf, 0xea, 0xc6, 0xc8, 0x36, + 0x2a, 0x68, 0xf1, 0x58, 0x9e, 0xd5, 0x86, 0xb1, 0x39, 0xb5, 0xfe, 0xf5, 0x66, 0x83, 0x29, 0x9b, 0x0b, 0xb5, 0x0a, + 0x43, 0x12, 0x7d, 0x2c, 0xbd, 0x48, 0x22, 0x16, 0x36, 0xab, 0xb5, 0xf9, 0x4d, 0x18, 0x90, 0x4c, 0xa4, 0xb8, 0x9f, + 0x2d, 0x71, 0xee, 0xe2, 0xf1, 0xbc, 0xea, 0x6b, 0x2d, 0x2d, 0x32, 0x6d, 0xbe, 0xd5, 0x97, 0x21, 0x4d, 0x45, 0x0d, + 0x69, 0xd4, 0x99, 0x41, 0xf7, 0xed, 0xf2, 0x96, 0xd5, 0x08, 0x13, 0xe0, 0x95, 0xce, 0xa0, 0x1b, 0x8d, 0x07, 0x62, + 0x59, 0x8d, 0x8a, 0xb5, 0x10, 0x08, 0x3c, 0x0c, 0x39, 0x66, 0x96, 0x90, 0x64, 0x9f, 0xf8, 0x77, 0x2a, 0xce, 0x42, + 0x11, 0xdf, 0x18, 0x64, 0xef, 0xca, 0xba, 0x76, 0xd7, 0x91, 0x9f, 0x13, 0x0b, 0xab, 0xfd, 0x87, 0xe6, 0x51, 0x6b, + 0x9c, 0x05, 0xb4, 0x35, 0xad, 0x6e, 0x38, 0xdc, 0xa3, 0x3a, 0x16, 0xa5, 0xc1, 0x26, 0xf6, 0xc8, 0x72, 0xd1, 0x3a, + 0x66, 0xd0, 0x80, 0xfe, 0x36, 0xbb, 0x5a, 0x5f, 0x21, 0x80, 0x5b, 0x89, 0xac, 0x93, 0x54, 0xfe, 0x25, 0xed, 0x51, + 0xd7, 0xf6, 0x54, 0xfe, 0xb7, 0x6d, 0xaa, 0x1c, 0x5a, 0x4c, 0x79, 0xec, 0xe6, 0x2c, 0x50, 0x1d, 0x09, 0xa2, 0x40, + 0x6d, 0xbd, 0x60, 0xea, 0x9d, 0x32, 0x45, 0x07, 0x08, 0x74, 0x61, 0xce, 0xb0, 0x2f, 0x38, 0x62, 0xcc, 0x52, 0x89, + 0xc1, 0xd4, 0xc7, 0x18, 0xd5, 0xb4, 0x56, 0x80, 0xae, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0xd4, 0x68, 0xa8, 0x35, 0x92, + 0x42, 0xd1, 0x44, 0x85, 0x22, 0x4b, 0x0b, 0x1d, 0x57, 0xa1, 0x93, 0x48, 0x58, 0x02, 0x1a, 0x26, 0x44, 0x27, 0x15, + 0x78, 0x6b, 0x00, 0x67, 0x3e, 0x2e, 0xca, 0x75, 0xa1, 0x0d, 0xe6, 0x7e, 0x88, 0xaf, 0xf9, 0xcb, 0x67, 0xce, 0xa8, + 0xbe, 0x65, 0xad, 0xef, 0x69, 0x41, 0x7e, 0x08, 0x39, 0x45, 0x07, 0x26, 0x76, 0xb2, 0x41, 0x63, 0x8c, 0xb2, 0xd6, + 0x51, 0x2f, 0xde, 0xe8, 0x50, 0x2c, 0xda, 0x04, 0xef, 0x1e, 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, + 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, 0x7a, 0x24, 0xc2, 0x4e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, + 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x8c, + 0x82, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, + 0x7e, 0x18, 0xf8, 0x0e, 0x8d, 0x81, 0xad, 0x75, 0x80, 0x86, 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, + 0x67, 0x46, 0xcb, 0x99, 0x45, 0x63, 0xd0, 0xb7, 0xd1, 0x14, 0xc5, 0x39, 0xf9, 0x2c, 0x28, 0xe2, 0x34, 0x8b, 0x73, + 0xf0, 0xdb, 0x8c, 0x0b, 0xcc, 0x98, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x68, 0xbb, 0x73, 0x95, 0x5a, 0xd7, 0x20, 0x20, + 0xfb, 0x01, 0xac, 0x5e, 0x1a, 0x3a, 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x62, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, + 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, + 0x8f, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, 0x31, 0xf6, 0x8f, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, + 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, + 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, + 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, 0x58, 0x87, 0x9b, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, + 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, + 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, 0x14, 0x36, 0xc5, 0x76, 0xab, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, + 0x51, 0xfc, 0x07, 0xf7, 0xc2, 0x4e, 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x0f, 0x0e, 0x17, 0x89, 0xef, 0xa4, + 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x8e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, + 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, + 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, + 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, + 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, 0x71, 0xac, 0x89, 0x6a, 0xc1, 0xf7, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, + 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, + 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, + 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, + 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, + 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0xfb, 0x87, 0x84, 0xaa, 0xb8, 0x37, 0xbc, + 0x1d, 0xf7, 0xc6, 0x09, 0xbf, 0xe6, 0x62, 0xa1, 0x43, 0xb5, 0x98, 0x4b, 0x96, 0xdf, 0x5a, 0xef, 0x96, 0x24, 0xb5, + 0x02, 0xda, 0x67, 0x59, 0x50, 0x13, 0x01, 0x20, 0x7f, 0xf8, 0x0b, 0x84, 0xce, 0xf0, 0xb7, 0xc7, 0xe0, 0x8a, 0x14, + 0xee, 0x1d, 0x02, 0x61, 0x4d, 0x37, 0x77, 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x3d, 0xfd, 0x36, 0x93, 0xbb, + 0xba, 0x6e, 0x8f, 0x2c, 0xc3, 0x47, 0xb8, 0x52, 0x00, 0x37, 0x13, 0xfe, 0x62, 0x98, 0x49, 0xf5, 0x09, 0x60, 0xaa, + 0xe9, 0xe0, 0x3e, 0x41, 0x60, 0x00, 0x95, 0x68, 0x31, 0xba, 0x56, 0x8e, 0x68, 0x06, 0x6e, 0x4d, 0xb7, 0xc2, 0x78, + 0xeb, 0x41, 0x0b, 0x3d, 0xd3, 0x70, 0xe2, 0x3f, 0x68, 0xe6, 0x55, 0x01, 0x01, 0xb4, 0x32, 0x82, 0xb7, 0xd6, 0x47, + 0x73, 0x84, 0xf8, 0x84, 0x25, 0xd1, 0x84, 0xc5, 0x33, 0xc5, 0x8f, 0x09, 0xdd, 0x34, 0xb5, 0x4d, 0x1f, 0x90, 0xfe, + 0xe2, 0x9a, 0xf5, 0x53, 0x96, 0xb5, 0x6f, 0x0f, 0x15, 0x2f, 0xa6, 0xcd, 0x38, 0x88, 0x89, 0x2a, 0xc6, 0xff, 0x82, + 0xfb, 0x52, 0x2b, 0x40, 0x64, 0xee, 0xaa, 0xa7, 0xdf, 0x6f, 0x66, 0xcb, 0x81, 0x50, 0xf9, 0x9d, 0x41, 0xd2, 0xa7, + 0x43, 0xfb, 0x81, 0x4d, 0xa2, 0xb6, 0xd0, 0xf3, 0xc7, 0xa5, 0x6e, 0xe2, 0xe5, 0xb5, 0xa9, 0x11, 0xad, 0x90, 0xa1, + 0xb2, 0x75, 0xc0, 0xfa, 0xfe, 0x21, 0xdc, 0x5d, 0xd4, 0x34, 0xd4, 0xba, 0xe7, 0xae, 0x45, 0xc1, 0x89, 0x3f, 0xc0, + 0x58, 0x5c, 0x48, 0x6a, 0x1d, 0x8f, 0x49, 0x3f, 0x5a, 0xc8, 0xe4, 0x46, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x5c, + 0x80, 0xcb, 0xb6, 0xbf, 0xa2, 0x52, 0x97, 0x72, 0x7b, 0x45, 0x69, 0x7a, 0x48, 0xdb, 0xab, 0x38, 0x6f, 0x0b, 0x2e, + 0xf8, 0x17, 0x0a, 0x2e, 0xac, 0x83, 0x75, 0xc7, 0x9d, 0xb2, 0x27, 0x3c, 0x51, 0xa6, 0xb5, 0xc1, 0x5d, 0x37, 0x18, + 0x13, 0x63, 0xbf, 0xbb, 0xe4, 0xc9, 0x47, 0x64, 0xc1, 0xbf, 0xcb, 0x04, 0x78, 0x26, 0xbb, 0x57, 0x2a, 0xff, 0x0f, + 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xb9, 0x92, + 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0xbd, 0x04, + 0x6e, 0xba, 0xbf, 0x36, 0x33, 0x73, 0xba, 0x56, 0xa2, 0xe9, 0xd2, 0xd8, 0x5a, 0x96, 0x2a, 0x8c, 0xf7, 0xbd, 0x27, + 0xd9, 0x34, 0x3f, 0x5e, 0x4e, 0x73, 0x4b, 0xdd, 0x36, 0x6e, 0xd9, 0x00, 0x1a, 0x62, 0xd7, 0xda, 0xca, 0x01, 0x2f, + 0xb7, 0x07, 0xd1, 0x7c, 0xad, 0x08, 0x3d, 0x55, 0x22, 0xf4, 0x69, 0xda, 0xec, 0x83, 0x5d, 0x55, 0xeb, 0x46, 0xc8, + 0xa3, 0x41, 0xaa, 0x19, 0xf9, 0x37, 0xd7, 0xbc, 0xb8, 0xc8, 0xe5, 0x0d, 0xc0, 0x21, 0x93, 0xda, 0x28, 0x2c, 0xaf, + 0xc0, 0x9d, 0x1f, 0x1d, 0xc7, 0x99, 0x18, 0xe5, 0x18, 0xb7, 0x15, 0x91, 0x92, 0x75, 0xe2, 0x0c, 0xf0, 0x90, 0xfd, + 0x49, 0xd3, 0xa1, 0x5d, 0x0b, 0x0c, 0xef, 0x0b, 0xdc, 0x55, 0xce, 0x4e, 0x36, 0xb9, 0x5d, 0xf4, 0xcd, 0x19, 0xd6, + 0x1d, 0x29, 0xad, 0x8d, 0x45, 0xd7, 0x1d, 0xac, 0x35, 0x83, 0xb6, 0x08, 0x25, 0x1f, 0x72, 0x27, 0xed, 0xa7, 0x80, + 0x06, 0x67, 0x59, 0x7a, 0x6b, 0xad, 0xf2, 0x37, 0x5a, 0x88, 0x13, 0xc5, 0xd4, 0x89, 0x6f, 0xa2, 0x44, 0x9f, 0x9f, + 0x89, 0x71, 0x03, 0x81, 0xd4, 0x1f, 0x30, 0xbe, 0x46, 0x11, 0x26, 0x70, 0x1d, 0x88, 0x62, 0x7b, 0xa2, 0x36, 0x96, + 0x23, 0xe8, 0x84, 0x10, 0xef, 0xa0, 0x0c, 0x63, 0x75, 0x71, 0xa0, 0x0d, 0x96, 0xbe, 0x6e, 0xad, 0x73, 0x43, 0x28, + 0x8c, 0x13, 0x98, 0x62, 0x90, 0xd4, 0x59, 0x67, 0x99, 0xa0, 0xca, 0x8e, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, + 0x53, 0x7c, 0xdd, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x5a, 0x8b, 0xdc, 0xe0, 0xcf, 0x5b, 0x22, 0x2c, 0x02, 0x67, 0xad, + 0xc9, 0x57, 0x8d, 0x70, 0x60, 0x4a, 0x32, 0x0d, 0x7b, 0xb9, 0xb2, 0xe9, 0xde, 0x6e, 0x7b, 0xbd, 0xbd, 0x22, 0xae, + 0x1e, 0x63, 0x95, 0x77, 0x33, 0xb7, 0x77, 0xaa, 0xb5, 0xd8, 0xbd, 0x69, 0xfb, 0x29, 0x76, 0xd4, 0x5a, 0xbb, 0xdd, + 0x70, 0x42, 0x0d, 0xf9, 0x56, 0x54, 0x69, 0x75, 0xba, 0x31, 0x68, 0x87, 0xd0, 0xd6, 0x22, 0x83, 0x1b, 0xe5, 0x33, + 0x27, 0x74, 0x52, 0x21, 0x57, 0x9d, 0xba, 0x60, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0x23, 0x41, 0xd1, 0xe6, 0x3c, 0x2a, + 0x69, 0x22, 0xd7, 0xa2, 0x8a, 0x64, 0x8d, 0x7a, 0x51, 0xab, 0x31, 0x40, 0x40, 0xa6, 0xb3, 0xa6, 0x07, 0x55, 0x30, + 0x1b, 0xca, 0x48, 0x4e, 0x5f, 0x80, 0xa5, 0x3d, 0x72, 0xac, 0xf5, 0xbe, 0x3a, 0x5b, 0x7c, 0xab, 0x27, 0x04, 0x53, + 0x98, 0x3d, 0x10, 0x11, 0xae, 0x69, 0x0c, 0x39, 0xed, 0x12, 0x97, 0x35, 0xdd, 0x12, 0xf6, 0x70, 0xbb, 0x92, 0x9d, + 0xb8, 0x79, 0xd2, 0xdc, 0x5c, 0xc1, 0x4e, 0x8a, 0xf9, 0x18, 0xb4, 0x5f, 0x52, 0x5d, 0xbb, 0x34, 0xb7, 0x1e, 0x0f, + 0x02, 0x1a, 0x0c, 0x0a, 0xc3, 0xbf, 0x4e, 0x8c, 0x87, 0x27, 0x0d, 0x08, 0x92, 0x72, 0x11, 0x8e, 0x7d, 0x23, 0xfa, + 0xc9, 0x54, 0x1e, 0x73, 0xb4, 0x78, 0x87, 0x56, 0xe7, 0x10, 0xd0, 0x4b, 0x84, 0x92, 0x18, 0x55, 0xa1, 0x11, 0x41, + 0x79, 0x5a, 0xfe, 0x52, 0x55, 0x87, 0x80, 0x42, 0xda, 0x57, 0x14, 0xca, 0x36, 0x89, 0xa1, 0x19, 0x7e, 0x39, 0x9f, + 0x2c, 0xf4, 0x0c, 0x0c, 0xe4, 0xfc, 0x68, 0xa1, 0x67, 0x61, 0x20, 0xe7, 0x8f, 0x16, 0xb5, 0x5b, 0x07, 0x9a, 0x80, + 0x78, 0x2e, 0x1c, 0x9d, 0x94, 0x56, 0x65, 0x0b, 0xe8, 0xe6, 0x3e, 0x82, 0xfe, 0x0f, 0x7b, 0x08, 0x3a, 0xb9, 0xd0, + 0x8e, 0xdc, 0x80, 0xb6, 0x43, 0x12, 0xd8, 0x2b, 0x26, 0x15, 0x26, 0x16, 0xd1, 0x31, 0x1b, 0x83, 0x21, 0xb6, 0xfa, + 0xe0, 0x98, 0x8d, 0xa7, 0x3e, 0x09, 0x02, 0x46, 0xf7, 0x07, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, 0x93, 0x8d, 0x40, + 0x37, 0x7d, 0x77, 0x37, 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, 0xd5, 0x6b, 0x88, + 0x1b, 0xf2, 0x2b, 0xa3, 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, 0xea, 0xd6, 0xb3, + 0x01, 0x19, 0x66, 0x7a, 0xcb, 0x64, 0x7d, 0x0f, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, 0xf7, 0x0f, 0xbe, + 0xc9, 0xf8, 0x99, 0xc3, 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, + 0xc9, 0xe7, 0x59, 0x28, 0x6f, 0xbc, 0xa6, 0xff, 0x51, 0xe9, 0xcd, 0x0e, 0x87, 0x9c, 0xae, 0x60, 0xc5, 0xcd, 0xaa, + 0xd0, 0xf0, 0xb3, 0xc8, 0x1b, 0x47, 0xbc, 0x26, 0x51, 0xd5, 0x7d, 0xde, 0xdb, 0x88, 0xa5, 0x1d, 0xe3, 0x00, 0xe0, + 0x44, 0xad, 0x1a, 0x76, 0xa5, 0x71, 0xad, 0x0e, 0x62, 0x44, 0x4a, 0xd8, 0x2a, 0x71, 0x24, 0x94, 0xbf, 0x01, 0x08, + 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x7b, 0xd8, 0x0f, 0x5d, 0xa0, 0x69, 0x4e, 0xa9, 0x66, 0x00, 0x90, 0x04, 0xfc, + 0xd1, 0xd3, 0x4d, 0x43, 0x65, 0x9b, 0xe7, 0xa1, 0x65, 0x75, 0x05, 0xf7, 0xf4, 0xd4, 0x95, 0x0c, 0x8c, 0xab, 0x3a, + 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x55, 0xe4, 0x3b, 0x9b, 0xd4, 0x34, 0x0b, 0x20, 0x45, 0xe3, 0xd2, 0x17, 0x7a, 0x3a, + 0x01, 0x5a, 0xaf, 0x2d, 0x15, 0xed, 0xf7, 0x51, 0x8c, 0x1a, 0x17, 0x0a, 0xac, 0xc2, 0x04, 0x85, 0x43, 0x84, 0x11, + 0x42, 0x7f, 0x2e, 0xc3, 0x8d, 0x2f, 0xc8, 0x20, 0x1a, 0xae, 0x45, 0x87, 0x22, 0x72, 0xbc, 0x68, 0x5b, 0xaa, 0x6a, + 0x4e, 0x9a, 0xb6, 0x04, 0xde, 0x44, 0x06, 0x6c, 0xe7, 0x9f, 0x36, 0x44, 0xae, 0xc2, 0x05, 0x0c, 0xdf, 0x11, 0xd7, + 0x82, 0xe8, 0xa6, 0x36, 0xf5, 0x36, 0xec, 0x10, 0x1d, 0x4d, 0xf1, 0xe8, 0x90, 0x7b, 0xee, 0x9e, 0xdb, 0x22, 0xbe, + 0xf9, 0x0c, 0xb9, 0x6b, 0x3a, 0x7b, 0x29, 0xc2, 0xa0, 0x6e, 0xd9, 0x40, 0xb1, 0x8e, 0x9d, 0xa0, 0x00, 0x03, 0xb8, + 0x7c, 0x02, 0x3a, 0x36, 0x18, 0x54, 0x04, 0x9f, 0x14, 0xb6, 0x4d, 0x83, 0xfc, 0x11, 0xef, 0x86, 0x0e, 0xaf, 0x2d, + 0x79, 0x20, 0x5e, 0x61, 0x9f, 0x29, 0x61, 0xff, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, + 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, + 0x51, 0xe5, 0xb1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, + 0xb4, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x1d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, + 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, + 0x94, 0x9f, 0xb0, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x02, 0x5a, 0x67, 0x26, 0xae, + 0xf1, 0x69, 0xfb, 0x0a, 0x5a, 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, + 0xa9, 0x64, 0x9f, 0x96, 0xd6, 0x61, 0xdf, 0x2e, 0x14, 0x5a, 0x68, 0xe2, 0x57, 0x19, 0xe2, 0xa7, 0xae, 0x33, 0xff, + 0x36, 0xed, 0x53, 0x83, 0x58, 0x38, 0x12, 0x83, 0x88, 0x5f, 0x9c, 0x2a, 0xdb, 0x09, 0xa1, 0x62, 0xe3, 0xa1, 0x6b, + 0xdd, 0x38, 0x92, 0x2a, 0x0c, 0xa5, 0xd0, 0x78, 0x6a, 0xb8, 0xef, 0x85, 0x0e, 0x5f, 0x87, 0x59, 0xdc, 0x66, 0x8d, + 0xa4, 0xc6, 0x38, 0x15, 0x26, 0x4e, 0xa5, 0x5c, 0x45, 0x02, 0x03, 0xe5, 0xd9, 0xc2, 0x20, 0xc0, 0x24, 0x26, 0x19, + 0x5b, 0x0b, 0x61, 0xc2, 0xd8, 0xb9, 0xc2, 0x34, 0x75, 0x91, 0xfa, 0xcd, 0xc0, 0x64, 0x41, 0x43, 0x7e, 0x8f, 0x46, + 0x6b, 0xaa, 0xa6, 0x00, 0xc3, 0x38, 0x4a, 0x35, 0xfe, 0x2d, 0x42, 0x6d, 0x86, 0x01, 0x80, 0x6d, 0xde, 0xca, 0x4c, + 0x54, 0x2f, 0x05, 0x42, 0xa0, 0x39, 0xfb, 0xa9, 0xb8, 0xda, 0x99, 0x05, 0xa3, 0x68, 0xb7, 0x57, 0x3e, 0x1f, 0x38, + 0xa1, 0x3c, 0x55, 0x17, 0xa8, 0x17, 0xb2, 0x78, 0x25, 0x53, 0xde, 0x0a, 0x91, 0x79, 0x20, 0xd9, 0x4f, 0xf9, 0x08, + 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, + 0xf0, 0x6b, 0x88, 0x33, 0xb6, 0x73, 0x12, 0x6e, 0xf6, 0xf3, 0xc0, 0x10, 0xa5, 0x5c, 0xb4, 0x44, 0xc3, 0xd6, 0x8e, + 0xd7, 0x93, 0x6b, 0xc2, 0x7d, 0xd8, 0x88, 0x35, 0x19, 0x63, 0x5c, 0x9b, 0x1b, 0x59, 0x3f, 0x5a, 0xe0, 0xc1, 0x98, + 0xb2, 0xfe, 0x04, 0x32, 0xad, 0xa4, 0xac, 0xf3, 0x85, 0x11, 0x33, 0xa9, 0x44, 0xef, 0xf6, 0x8d, 0xcf, 0xea, 0x2e, + 0xa2, 0x7e, 0x6b, 0xbf, 0x27, 0xf5, 0x70, 0xe7, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, + 0x37, 0x4d, 0x8a, 0x38, 0x3d, 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, + 0x24, 0x49, 0xd6, 0xd2, 0xd8, 0x8a, 0x5d, 0x1a, 0xa4, 0x67, 0x6f, 0xc4, 0xa5, 0x17, 0x15, 0x1a, 0xd2, 0x52, 0xef, + 0x2c, 0x54, 0x32, 0x7f, 0xc5, 0x7f, 0x06, 0xb5, 0x02, 0x1d, 0x6d, 0x52, 0x8c, 0xa7, 0xc0, 0x88, 0xef, 0x06, 0xb3, + 0xba, 0x87, 0xb8, 0x68, 0x82, 0x52, 0xef, 0x88, 0x1d, 0x3f, 0x37, 0x79, 0x78, 0x17, 0x72, 0xce, 0xe0, 0xd3, 0xfb, + 0x59, 0xa2, 0xd6, 0x3a, 0x12, 0x23, 0x35, 0x03, 0x68, 0x3a, 0x28, 0x73, 0x1e, 0x8b, 0x60, 0xd6, 0x33, 0x89, 0x51, + 0x8f, 0xeb, 0x5f, 0xa0, 0xa1, 0xf6, 0x9b, 0x95, 0xe5, 0x59, 0x75, 0xf7, 0x25, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, + 0x75, 0x25, 0x2f, 0x2f, 0x55, 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, + 0x37, 0x8b, 0xbb, 0x59, 0x46, 0x03, 0x61, 0x6d, 0xe7, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, + 0x00, 0x10, 0xe9, 0x41, 0x14, 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xee, 0xe3, 0x28, 0x0b, 0xa5, 0x97, 0xb3, 0x8c, 0x9f, + 0x36, 0x8d, 0xb5, 0xce, 0x0a, 0x65, 0x68, 0x6d, 0x74, 0xa7, 0xab, 0x0c, 0xb1, 0xfd, 0x24, 0xce, 0x16, 0xe0, 0xfe, + 0x98, 0xa1, 0xd0, 0xd0, 0x59, 0x46, 0x9a, 0x68, 0xf8, 0xae, 0x3d, 0x83, 0x8c, 0xe2, 0x64, 0x9d, 0x57, 0xd2, 0x8d, + 0x3e, 0x6b, 0x23, 0x61, 0xee, 0x21, 0xfa, 0x55, 0x0c, 0x1e, 0xe5, 0x3e, 0xaf, 0x8d, 0x4e, 0xa6, 0x65, 0xa4, 0xdd, + 0xf9, 0x49, 0xbd, 0xcc, 0x52, 0xad, 0xc3, 0xf6, 0x19, 0xf6, 0xd6, 0x98, 0xf4, 0x26, 0xa4, 0x86, 0x91, 0xf8, 0x7c, + 0x46, 0x8d, 0x10, 0xd0, 0x96, 0xe3, 0xef, 0xf0, 0x19, 0x86, 0xa6, 0xc0, 0x52, 0xc5, 0x2d, 0xec, 0x86, 0xaf, 0xf9, + 0x64, 0xd5, 0x02, 0x10, 0xcc, 0xca, 0xd7, 0xbb, 0x78, 0x25, 0xd4, 0x67, 0xda, 0x0c, 0x00, 0x59, 0x50, 0xca, 0x1d, + 0x3f, 0xa5, 0xd2, 0xc1, 0x12, 0x45, 0xdb, 0xcb, 0xe9, 0x1b, 0x1d, 0x1b, 0xdf, 0xa7, 0xe7, 0x02, 0xb6, 0x0b, 0xf9, + 0xad, 0xbd, 0x7a, 0x89, 0x8a, 0xd4, 0xb6, 0x59, 0xf7, 0xf0, 0xe5, 0x06, 0x4d, 0xc2, 0x08, 0xca, 0x94, 0x29, 0x80, + 0xc1, 0x4d, 0x35, 0x0a, 0x26, 0xad, 0x46, 0xc2, 0x96, 0x7a, 0x92, 0xe5, 0xa6, 0x0f, 0x4e, 0xb5, 0x47, 0xd0, 0x73, + 0xab, 0x9c, 0x2f, 0x5a, 0xf6, 0x6b, 0x05, 0x47, 0x27, 0x57, 0x43, 0xd4, 0xcc, 0x7b, 0x6d, 0x47, 0x86, 0x94, 0xcb, + 0x30, 0x10, 0x4c, 0x39, 0xe6, 0xe9, 0xb1, 0xf5, 0x8c, 0x88, 0xee, 0x39, 0xfb, 0x4c, 0xb7, 0xea, 0x4a, 0x02, 0xa2, + 0xe3, 0x37, 0x8f, 0x5f, 0x5e, 0xc5, 0x97, 0x06, 0x45, 0xa9, 0x61, 0x11, 0xa3, 0x4c, 0xfb, 0x2a, 0x09, 0x83, 0xf7, + 0xcb, 0xbb, 0x9f, 0x54, 0x96, 0xda, 0xef, 0xc1, 0xc6, 0x8a, 0xaa, 0x7e, 0x29, 0x79, 0xd1, 0x14, 0x60, 0xed, 0xb3, + 0x44, 0x81, 0xdc, 0xef, 0x6c, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, 0x6d, 0xc9, 0x8e, + 0xac, 0x44, 0xce, 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x0d, 0xaa, 0x52, 0xf1, 0x7b, 0x23, 0x82, 0x53, + 0xc7, 0xaa, 0xc2, 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, 0xfd, 0xce, 0x0a, + 0x6a, 0x7e, 0xff, 0xd3, 0x18, 0xf2, 0x35, 0xa5, 0xa0, 0x92, 0x80, 0x9d, 0x41, 0xa3, 0xa7, 0x4a, 0x18, 0x48, 0x41, + 0xf0, 0x04, 0x28, 0x5f, 0x44, 0x8d, 0xd5, 0x6e, 0x5f, 0x9d, 0x1a, 0xa3, 0x2d, 0x20, 0xb4, 0x90, 0x1e, 0x5d, 0xf6, + 0x71, 0x1b, 0xeb, 0x40, 0xe2, 0xc1, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, 0x42, 0xf3, 0xfb, 0x46, 0x03, 0x5e, 0xd3, + 0x0a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xce, 0x0e, 0x29, 0x88, 0xd8, 0xa0, 0x85, 0x7d, 0x7b, 0x3e, 0x34, 0xfb, 0x7a, + 0x9e, 0x2c, 0x48, 0x4d, 0xa5, 0xfb, 0xdc, 0x2d, 0x21, 0x6b, 0xd5, 0xa1, 0xac, 0x3c, 0xc0, 0xf1, 0x42, 0xc9, 0xfc, + 0x1d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x63, 0xc4, 0x02, 0x96, 0x04, 0xed, 0xf5, 0x40, 0xfd, 0x32, 0x08, 0x15, 0xce, + 0xf4, 0x44, 0xe2, 0x53, 0xca, 0xd5, 0xa7, 0x05, 0xa9, 0xa7, 0x05, 0x73, 0xa0, 0x97, 0xbe, 0x95, 0x5f, 0xd9, 0xf8, + 0x68, 0x77, 0xef, 0x9a, 0x0b, 0xeb, 0x18, 0xe2, 0x62, 0x0b, 0xbf, 0x39, 0x35, 0x05, 0x60, 0xc3, 0x53, 0x5d, 0x96, + 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, + 0xf2, 0xb6, 0xfb, 0x9e, 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xc3, 0xfe, 0x55, 0xf2, 0x7f, 0x55, 0xc9, + 0x7e, 0xab, 0xcc, 0xba, 0x2d, 0xde, 0xef, 0x3a, 0x6e, 0x39, 0x46, 0x83, 0xc0, 0x9a, 0x02, 0x03, 0xe9, 0x49, 0x63, + 0x9a, 0xe8, 0xe8, 0xca, 0x8c, 0x19, 0x3c, 0xba, 0x00, 0xcd, 0x61, 0x3a, 0xcf, 0x63, 0x00, 0x0e, 0xf0, 0x8f, 0x3c, + 0x42, 0xfd, 0xd3, 0x79, 0x1e, 0x9c, 0x05, 0x83, 0x72, 0x10, 0xe8, 0x4f, 0x5c, 0x73, 0x82, 0x05, 0xe8, 0xdc, 0x62, + 0x06, 0x71, 0x27, 0xad, 0x99, 0x43, 0x7c, 0x9c, 0x4c, 0x07, 0x83, 0x98, 0x6c, 0x00, 0xa4, 0x2f, 0x5e, 0x58, 0xe7, + 0xa0, 0x42, 0x2f, 0xc8, 0x56, 0xdd, 0x45, 0xb3, 0x62, 0xaf, 0xda, 0x69, 0xde, 0xef, 0xe7, 0xf3, 0x72, 0x10, 0x34, + 0x2a, 0x2c, 0x8c, 0xf7, 0x1f, 0x6d, 0x7e, 0x69, 0x74, 0xd2, 0x04, 0x23, 0xd6, 0x9e, 0xa2, 0x7a, 0xc5, 0xd3, 0x8c, + 0x36, 0x6e, 0xc7, 0x4a, 0xf9, 0x02, 0xa2, 0x78, 0x60, 0xc8, 0x5a, 0x79, 0x77, 0x0e, 0x5e, 0x97, 0x1b, 0x6f, 0x8e, + 0x28, 0xc0, 0x6e, 0x0a, 0xe3, 0xa4, 0xe6, 0xa2, 0x8b, 0x9a, 0x78, 0x06, 0x3b, 0x5d, 0xbd, 0x95, 0x68, 0x35, 0xde, + 0x8b, 0x77, 0xcd, 0xc6, 0x5f, 0xcb, 0x03, 0x5d, 0xe6, 0xc1, 0x05, 0x20, 0xce, 0x1e, 0xc4, 0xd5, 0x01, 0x96, 0x7a, + 0x10, 0x0c, 0x2c, 0x72, 0x48, 0xbb, 0x5a, 0x3d, 0x14, 0x91, 0x3a, 0x8f, 0xc1, 0x80, 0xc9, 0x34, 0xa4, 0x26, 0xd3, + 0x5e, 0xac, 0x20, 0x6d, 0xac, 0xb5, 0x80, 0x36, 0x1c, 0x16, 0x3b, 0x76, 0xc3, 0xee, 0x74, 0xeb, 0x50, 0x28, 0x61, + 0x20, 0xeb, 0xba, 0x79, 0xa8, 0x35, 0x3c, 0x11, 0xf4, 0xa0, 0x1a, 0xed, 0xa7, 0x87, 0xf2, 0xa4, 0x3d, 0x16, 0xe0, + 0xa2, 0x87, 0x2f, 0x9f, 0x0b, 0xbc, 0x68, 0xef, 0x20, 0xcf, 0x99, 0x4f, 0x95, 0x0f, 0x62, 0xc3, 0x2d, 0xc3, 0x87, + 0xf6, 0xf1, 0xad, 0x40, 0x26, 0x75, 0x47, 0x53, 0x5b, 0xbb, 0xa3, 0x71, 0x4c, 0xa0, 0xdf, 0x94, 0xa3, 0x94, 0x89, + 0xa9, 0x65, 0xc9, 0x4e, 0x7a, 0xb9, 0xf2, 0x86, 0x4a, 0xd9, 0xc9, 0xb2, 0xcd, 0xf9, 0xa5, 0x8d, 0x84, 0x7e, 0x5f, + 0xbb, 0x03, 0xe1, 0x1b, 0xb5, 0xde, 0x90, 0x97, 0x0d, 0x11, 0xcb, 0x21, 0x66, 0xe0, 0x78, 0x21, 0x95, 0x6b, 0x77, + 0xd1, 0x54, 0xd5, 0xed, 0x6c, 0xe5, 0x82, 0x96, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x3a, 0xbd, 0x9e, 0x4a, 0xdc, 0xf7, + 0x51, 0x6c, 0x3f, 0x02, 0xb6, 0xb1, 0x71, 0x34, 0x36, 0x6e, 0x11, 0x1b, 0x7c, 0x15, 0x55, 0xb4, 0xe0, 0x00, 0xc1, + 0xdd, 0x96, 0xd4, 0xd2, 0xcc, 0x21, 0xee, 0x2b, 0x1e, 0xa0, 0x7d, 0x17, 0x47, 0x9c, 0x0a, 0xb0, 0xad, 0x6b, 0x9d, + 0xb3, 0x5a, 0x0e, 0xd8, 0x4c, 0xf4, 0xfc, 0xd3, 0xaa, 0x91, 0x88, 0x61, 0x95, 0x8d, 0x94, 0x15, 0xda, 0xbd, 0xd2, + 0x25, 0x5c, 0x7c, 0x01, 0x5e, 0xb6, 0xf7, 0x2b, 0xbb, 0xcf, 0x96, 0xd8, 0x3f, 0xcc, 0xab, 0x26, 0x78, 0xe4, 0x35, + 0xde, 0xde, 0xc3, 0xc4, 0x97, 0x4a, 0x21, 0xbc, 0x4a, 0x69, 0x28, 0x01, 0x18, 0x24, 0x41, 0x0d, 0x57, 0xda, 0x36, + 0x83, 0x54, 0xc6, 0xb0, 0xbb, 0xd5, 0x5b, 0xfd, 0x9f, 0x56, 0xe1, 0xa2, 0x92, 0xc5, 0x98, 0x04, 0x3a, 0xa7, 0x5a, + 0x6e, 0x02, 0x0b, 0x9e, 0xed, 0x92, 0x23, 0x50, 0xd8, 0x09, 0xe0, 0x86, 0x12, 0xf6, 0x4f, 0xbc, 0x0d, 0xe5, 0xec, + 0xb5, 0x95, 0x3c, 0xb9, 0x7d, 0x49, 0x05, 0x4d, 0xc8, 0x54, 0xd8, 0xfd, 0xdb, 0xda, 0xb0, 0xcf, 0x42, 0x39, 0x92, + 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0x32, 0x36, 0x9f, 0x49, 0xbf, 0xaf, 0xde, 0x3f, 0xcd, 0xb3, 0xe4, + 0xe3, 0xce, 0x7b, 0xc3, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x5a, 0x57, 0xc5, 0x70, 0xa9, 0x5d, 0x8c, 0x1b, 0x24, + 0x23, 0xde, 0x4b, 0x1d, 0x62, 0xc4, 0xf8, 0x22, 0x3b, 0x24, 0x25, 0xa7, 0xcb, 0xba, 0xb3, 0xe7, 0x5a, 0x34, 0x83, + 0xc6, 0x70, 0x3b, 0xde, 0x4b, 0x7a, 0x05, 0xa8, 0x00, 0xd1, 0x3d, 0x0b, 0x5c, 0xc3, 0x9b, 0x4b, 0xa2, 0xb1, 0xa5, + 0xa7, 0x2d, 0xd1, 0xc0, 0x5e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x18, 0x16, 0x00, 0xd4, 0x6a, + 0x90, 0x5e, 0xe9, 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, + 0x03, 0xfa, 0xb2, 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x87, 0xa5, + 0x49, 0x02, 0x41, 0x09, 0xca, 0x37, 0xe8, 0xbf, 0x4a, 0xcf, 0xc7, 0xf2, 0x47, 0xef, 0x50, 0xfa, 0x21, 0x2c, 0x40, + 0xa6, 0xa8, 0x2b, 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, + 0x59, 0x86, 0x38, 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, + 0x4a, 0x20, 0xca, 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, + 0xa4, 0x99, 0x5d, 0x87, 0x11, 0xa9, 0x76, 0x92, 0xcc, 0x97, 0x3f, 0xca, 0x4c, 0x78, 0xdf, 0xc0, 0x63, 0xb3, 0x59, + 0x36, 0xc5, 0x7c, 0xa1, 0x82, 0x39, 0xb8, 0x4f, 0x54, 0x5c, 0x8a, 0xca, 0x7f, 0xc2, 0x2e, 0x78, 0x31, 0x1e, 0xbc, + 0x5e, 0x23, 0xc0, 0x7e, 0xe5, 0x3f, 0x79, 0x63, 0xf6, 0xa7, 0x75, 0xe3, 0xcb, 0x4c, 0xc4, 0x07, 0x3e, 0xba, 0xa5, + 0x7c, 0x74, 0xe7, 0x65, 0xfa, 0xae, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x9d, 0x44, 0xd9, + 0xa8, 0xe2, 0x02, 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x84, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, + 0x61, 0x99, 0xa9, 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x37, 0x49, 0xf4, 0xe7, 0xd2, 0x43, 0x52, 0x33, 0x53, + 0xb6, 0xa9, 0x1d, 0xa1, 0x36, 0xbe, 0x8e, 0x74, 0xa3, 0x2d, 0x00, 0xe0, 0x9e, 0x2d, 0xd2, 0x48, 0x32, 0x31, 0x9c, + 0xd4, 0x8c, 0x9b, 0xf4, 0x02, 0x53, 0xe3, 0x9a, 0x55, 0x34, 0x71, 0x16, 0x32, 0xa0, 0xf7, 0xa7, 0xb9, 0x7e, 0xce, + 0xe0, 0xfe, 0x83, 0xd6, 0xc0, 0xe5, 0x71, 0xd1, 0xef, 0xcb, 0xe3, 0x62, 0xbb, 0x2d, 0x4f, 0xe2, 0x7e, 0x5f, 0x9e, + 0xc4, 0x86, 0x7f, 0x50, 0x8a, 0x6d, 0x63, 0x6e, 0x90, 0xd0, 0x5c, 0x42, 0xd4, 0xa2, 0x11, 0xfc, 0xa1, 0x59, 0xce, + 0x45, 0x94, 0x1f, 0x27, 0xfd, 0x7e, 0x6f, 0x39, 0x13, 0x83, 0x7c, 0x98, 0x44, 0xf9, 0x30, 0xf1, 0x9c, 0x10, 0x7f, + 0xf5, 0x9c, 0x10, 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, + 0xab, 0x5a, 0x12, 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0x7d, 0xb7, 0x04, 0x9e, 0x28, 0xe7, + 0xd5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x4d, 0x4d, 0x2f, 0xe8, 0x8a, + 0x5e, 0x22, 0x3f, 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, + 0xc2, 0xf5, 0x2c, 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x55, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x66, 0x10, 0xde, + 0x2f, 0x9d, 0x85, 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, + 0x97, 0x74, 0x45, 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, + 0x55, 0xe1, 0x5d, 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x68, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, + 0x66, 0x64, 0x24, 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, + 0xdc, 0xfd, 0x92, 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, + 0x38, 0xb0, 0x07, 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x25, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, + 0xc4, 0x2b, 0x70, 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, + 0x2b, 0x95, 0x7e, 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, + 0x17, 0xa3, 0x3b, 0x02, 0x16, 0x5e, 0xe3, 0xe9, 0xfa, 0x98, 0xc5, 0xd3, 0xc1, 0x60, 0x8d, 0x54, 0x5d, 0xe5, 0x5e, + 0x93, 0x05, 0xbd, 0xc0, 0x89, 0x20, 0xc0, 0xd0, 0x67, 0x62, 0x6d, 0x68, 0xf8, 0x53, 0x06, 0x1f, 0xdf, 0xb1, 0x8b, + 0xd1, 0x1d, 0xbd, 0x65, 0x4f, 0xb7, 0xe3, 0x29, 0x30, 0x53, 0xab, 0x59, 0x78, 0x77, 0x7c, 0x39, 0xbb, 0x64, 0x77, + 0xd1, 0xdd, 0x09, 0x34, 0xf4, 0x8a, 0xdd, 0x21, 0xe0, 0x52, 0xfa, 0x70, 0x39, 0x78, 0x4a, 0x0e, 0x07, 0x83, 0x94, + 0x44, 0xe1, 0x75, 0xe8, 0xb5, 0xf2, 0x29, 0xbd, 0x23, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, + 0xee, 0xea, 0xeb, 0xd0, 0xdb, 0xcd, 0x89, 0xe8, 0x04, 0x31, 0x42, 0x5f, 0x03, 0x47, 0xb3, 0x5c, 0x98, 0x09, 0x78, + 0x32, 0x17, 0x19, 0x2d, 0x0a, 0xcd, 0x40, 0x9c, 0x95, 0x80, 0x58, 0x12, 0x75, 0xbf, 0xd9, 0xe8, 0x0c, 0x96, 0x73, + 0xbf, 0xdf, 0xab, 0x0c, 0x3d, 0x40, 0xe4, 0xcc, 0x4e, 0x7a, 0xd0, 0xf3, 0xe9, 0x01, 0x7e, 0xa2, 0x57, 0x0d, 0xe2, + 0x64, 0xfe, 0xb0, 0x8c, 0x7e, 0xf5, 0xe8, 0xc3, 0x2f, 0xdd, 0x94, 0xa7, 0xcc, 0xff, 0x7d, 0xca, 0x23, 0xf3, 0xe8, + 0x55, 0xe5, 0x81, 0xe0, 0x79, 0x6b, 0x52, 0x69, 0x24, 0xaa, 0xd1, 0xd9, 0x2a, 0x06, 0x6d, 0x24, 0x6a, 0x1b, 0xf4, + 0x13, 0x5a, 0x58, 0x41, 0x84, 0x9c, 0xa3, 0x67, 0x60, 0x90, 0x0a, 0xa1, 0x72, 0xd4, 0xa2, 0x44, 0x43, 0x90, 0x5c, + 0x96, 0x5c, 0x85, 0xcf, 0x21, 0x54, 0x9d, 0x3e, 0xce, 0x44, 0xd8, 0xd0, 0xe3, 0xd0, 0x07, 0x80, 0xff, 0xe7, 0x0e, + 0xb9, 0x28, 0xf9, 0x25, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb0, 0x44, 0x34, 0x43, 0xdb, 0x20, 0xf6, 0x63, 0x49, 0xb0, + 0x1e, 0x49, 0xe3, 0x51, 0x69, 0x8e, 0x08, 0x3f, 0x8a, 0x8f, 0xa2, 0xa7, 0xb1, 0x21, 0x91, 0x1c, 0x49, 0x24, 0x1f, + 0x00, 0xe1, 0x24, 0xe8, 0x2f, 0xee, 0x9a, 0xec, 0x5a, 0x48, 0x0c, 0xfa, 0xd3, 0x92, 0x69, 0xd9, 0xbd, 0xea, 0xb1, + 0xaf, 0x08, 0x72, 0xc7, 0xf4, 0xef, 0x5e, 0x1f, 0xfe, 0x5a, 0xe2, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0x99, 0x37, + 0xb8, 0x91, 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, 0xf1, + 0x9c, 0xca, 0xf5, 0xca, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, 0x57, + 0xd2, 0x72, 0xf4, 0x94, 0x72, 0xd5, 0x4c, 0xb9, 0x58, 0xe7, 0xf9, 0x4f, 0x3b, 0xa9, 0x38, 0xc5, 0xcd, 0x14, 0xa4, + 0x4a, 0x2d, 0x17, 0x50, 0x3d, 0x47, 0x2d, 0x77, 0x4b, 0xb3, 0x03, 0x9c, 0xdb, 0xa6, 0xfa, 0x58, 0x99, 0x5d, 0x78, + 0xc9, 0x8d, 0xfb, 0x93, 0x29, 0xc3, 0x82, 0x51, 0x68, 0xb3, 0xea, 0x4a, 0xdb, 0x17, 0x5a, 0xa7, 0x61, 0xb8, 0xf2, + 0xe3, 0x05, 0xa4, 0x0b, 0x18, 0xc7, 0x8b, 0x92, 0x89, 0x71, 0x7b, 0xf4, 0x56, 0x10, 0x5f, 0xb2, 0x15, 0x48, 0xbf, + 0xdf, 0x13, 0xde, 0xae, 0xeb, 0x68, 0xbb, 0x27, 0x4e, 0x19, 0x95, 0xab, 0x58, 0x7c, 0x1f, 0xaf, 0x0c, 0x64, 0xb2, + 0x3a, 0x1e, 0x1b, 0x63, 0x3a, 0xfd, 0x3e, 0x09, 0xfd, 0x42, 0x28, 0xf8, 0xac, 0x97, 0x56, 0x9e, 0xdc, 0x1e, 0x96, + 0x71, 0x8d, 0x5e, 0x89, 0x2b, 0xdd, 0x37, 0x23, 0x85, 0xd4, 0x23, 0x5f, 0x35, 0x05, 0xf4, 0x66, 0xec, 0x9b, 0xa9, + 0x30, 0x6f, 0x7b, 0xc6, 0x5c, 0x21, 0x58, 0xa9, 0xb2, 0xdb, 0x77, 0x6a, 0x4c, 0xc5, 0x0c, 0xa6, 0xd8, 0x76, 0x16, + 0x93, 0x6e, 0xe5, 0x9f, 0x76, 0xee, 0xd3, 0xbc, 0xc3, 0x5d, 0x51, 0xbf, 0x05, 0x2e, 0x34, 0x2b, 0xca, 0xaa, 0x2d, + 0x1b, 0xb6, 0x8d, 0x37, 0xb2, 0x50, 0x6c, 0x80, 0x65, 0xcf, 0x7d, 0x0b, 0x0f, 0x10, 0x37, 0xe1, 0x9e, 0x5d, 0xd4, + 0x70, 0x63, 0xf8, 0xb2, 0x92, 0x7c, 0x57, 0x1a, 0x73, 0xe9, 0x53, 0xa5, 0x89, 0xe1, 0x64, 0x31, 0xe2, 0x22, 0x5d, + 0xd4, 0x99, 0x5d, 0x0b, 0x9f, 0xf1, 0x32, 0x9c, 0xf3, 0x85, 0xd1, 0x4d, 0xe9, 0xd2, 0x0b, 0x96, 0xe8, 0x4e, 0x6f, + 0x56, 0x1a, 0x2b, 0x25, 0xe2, 0xd6, 0x2c, 0x13, 0x28, 0x4b, 0x59, 0x2b, 0xe1, 0x4d, 0xd1, 0xb2, 0x95, 0x34, 0xf2, + 0x9e, 0x39, 0xb8, 0x8f, 0xfd, 0x82, 0x98, 0xc8, 0x26, 0x30, 0x29, 0x1a, 0x3a, 0xa0, 0x5d, 0x75, 0xe1, 0x9b, 0x51, + 0x0f, 0x06, 0xb9, 0x25, 0x89, 0x58, 0x41, 0x8a, 0x15, 0xac, 0x6b, 0x56, 0xcc, 0xf3, 0x05, 0xbd, 0x60, 0x72, 0x9e, + 0x2e, 0xe8, 0x8a, 0xc9, 0xf9, 0x1a, 0x6f, 0x42, 0x17, 0x70, 0x42, 0x92, 0x4d, 0xac, 0x14, 0xb0, 0x17, 0x78, 0x79, + 0xc3, 0x33, 0x55, 0xd3, 0xb2, 0x4b, 0xc5, 0x01, 0xc6, 0xe7, 0x65, 0x18, 0x96, 0xc3, 0x0b, 0xb0, 0x96, 0x38, 0x0c, + 0x57, 0x73, 0xbe, 0x50, 0xbf, 0x21, 0xea, 0x7c, 0x12, 0x2a, 0x76, 0xc1, 0xee, 0x05, 0x32, 0xbd, 0x9a, 0xf3, 0x85, + 0x1a, 0x09, 0x5d, 0xf0, 0x95, 0x35, 0x36, 0x89, 0x3d, 0x41, 0xcb, 0x2c, 0x9e, 0x8f, 0x17, 0x51, 0x5c, 0xc3, 0x32, + 0x7c, 0xaf, 0x66, 0xa6, 0x25, 0xff, 0x49, 0xd4, 0x86, 0x26, 0xfa, 0x06, 0xab, 0xc8, 0x1f, 0x1e, 0x1f, 0x5d, 0x02, + 0x19, 0x3b, 0xbb, 0x92, 0x99, 0x0f, 0x7d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0a, 0x12, 0x65, 0xe0, 0xee, + 0xd5, 0x2c, 0x19, 0x6b, 0x11, 0xbe, 0x7b, 0x54, 0x14, 0x7d, 0x26, 0x4d, 0x03, 0xba, 0x8f, 0x04, 0x73, 0xa0, 0xf7, + 0x0a, 0x1d, 0x2e, 0xab, 0x6d, 0x26, 0xe0, 0x2f, 0x12, 0xe4, 0xb7, 0x42, 0xaf, 0x6a, 0x0c, 0xaa, 0x68, 0x17, 0xb1, + 0xf4, 0xef, 0x23, 0x7e, 0x94, 0xcd, 0xdf, 0xcd, 0x3d, 0x5e, 0x49, 0x18, 0xfc, 0x90, 0x9a, 0x4d, 0x32, 0x6f, 0xaf, + 0xd8, 0x7b, 0xe8, 0xa8, 0x47, 0xad, 0xf1, 0xbe, 0x7a, 0xc1, 0x29, 0xc4, 0x28, 0xa1, 0xe8, 0x24, 0x18, 0xc0, 0xed, + 0x12, 0x52, 0xdc, 0x0d, 0x76, 0xd3, 0xbc, 0xe6, 0x45, 0xc1, 0xf9, 0xba, 0xaa, 0x02, 0x3f, 0xa0, 0xe1, 0x7c, 0xb1, + 0x1b, 0xc2, 0x70, 0x4c, 0x5b, 0xd7, 0x30, 0x08, 0x33, 0x86, 0x91, 0x10, 0xbc, 0xfe, 0x45, 0x8f, 0x68, 0x12, 0xaf, + 0xbe, 0xe3, 0x9f, 0x32, 0x5e, 0x28, 0x22, 0x0d, 0x22, 0xa4, 0x6e, 0xe2, 0x1b, 0x99, 0x26, 0x05, 0x14, 0x02, 0x8c, + 0x02, 0x2a, 0xb1, 0xa1, 0xa9, 0xf8, 0x5b, 0x2d, 0x3e, 0xf8, 0xa9, 0xe9, 0x78, 0x34, 0xae, 0x5b, 0x9d, 0x51, 0x41, + 0x67, 0xa0, 0x47, 0xad, 0xa8, 0xa7, 0x41, 0x2b, 0xc1, 0x34, 0xd2, 0xbc, 0x75, 0x0f, 0x81, 0x57, 0xa6, 0xc5, 0x3b, + 0x0f, 0xe8, 0xe6, 0xcc, 0x07, 0x4f, 0x1e, 0xd3, 0x33, 0x87, 0x9e, 0x5c, 0xb1, 0x93, 0xaa, 0x87, 0xda, 0x7b, 0x33, + 0x42, 0x41, 0xbf, 0x8f, 0x29, 0xd0, 0x8d, 0xa0, 0xf6, 0xae, 0xee, 0x95, 0xdc, 0xe5, 0xf0, 0x1d, 0x67, 0xb9, 0x01, + 0x2c, 0x15, 0x59, 0x2b, 0xf0, 0x28, 0x40, 0x5d, 0x2a, 0x43, 0xd8, 0x62, 0x0e, 0x87, 0xca, 0x6e, 0xd5, 0x6a, 0x28, + 0xc9, 0x71, 0x39, 0x02, 0x87, 0xd0, 0x75, 0x39, 0x28, 0x47, 0xcb, 0xac, 0x7a, 0x87, 0xbf, 0x35, 0xeb, 0x90, 0x64, + 0xfb, 0x58, 0x07, 0x6e, 0x59, 0x87, 0xe9, 0x47, 0x83, 0x14, 0x80, 0x26, 0x1b, 0x81, 0x4b, 0x00, 0xde, 0xdb, 0x7f, + 0x44, 0xa8, 0x95, 0xe9, 0x5e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, + 0x91, 0xce, 0x49, 0x9d, 0x89, 0x77, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x77, 0x78, 0x9b, + 0xd5, 0x52, 0x1b, 0x3d, 0x50, 0x00, 0xbf, 0x1b, 0xdc, 0x21, 0xc8, 0x57, 0x63, 0xb8, 0x56, 0xf2, 0x26, 0xe4, 0xc3, + 0x82, 0x1e, 0x91, 0x81, 0x7d, 0x16, 0xc3, 0x98, 0x1e, 0x91, 0x63, 0xfb, 0x2c, 0xdd, 0x00, 0x0e, 0xa4, 0x1e, 0x55, + 0x7a, 0x04, 0x0d, 0xfa, 0xdd, 0xb6, 0xc8, 0x1d, 0x80, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0xde, + 0x9b, 0xeb, 0x0e, 0x73, 0x81, 0x30, 0x07, 0x03, 0x0e, 0xe2, 0x36, 0x08, 0xcd, 0x01, 0xb3, 0xb9, 0x8d, 0x04, 0xbd, + 0xb3, 0x86, 0x99, 0x1d, 0xfd, 0xe1, 0x56, 0x82, 0x6f, 0xb2, 0xd6, 0xa8, 0xf3, 0xe2, 0x10, 0x08, 0x82, 0x37, 0x85, + 0xaa, 0xf6, 0xaa, 0x07, 0x36, 0xde, 0xaa, 0x1f, 0xdb, 0xed, 0x78, 0x2a, 0xdc, 0xb5, 0x5f, 0x50, 0x38, 0xf9, 0x94, + 0xfc, 0xeb, 0x9d, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, + 0x3c, 0x52, 0xf4, 0x6f, 0xaf, 0xac, 0x7c, 0x6a, 0xa7, 0x7f, 0xbb, 0x35, 0xeb, 0xf3, 0x78, 0x34, 0xd9, 0x6e, 0x7b, + 0x71, 0xa5, 0x3d, 0xd6, 0xf4, 0x82, 0x40, 0xe7, 0x7a, 0x72, 0x78, 0x04, 0x51, 0x11, 0x9a, 0x71, 0x37, 0xcb, 0x86, + 0x44, 0xc6, 0x8f, 0xd3, 0x59, 0x36, 0x04, 0x3b, 0xdc, 0x8b, 0x4a, 0x5c, 0x8e, 0x5a, 0x1b, 0x9c, 0xde, 0x25, 0x21, + 0x84, 0x72, 0xc0, 0xca, 0x6e, 0xd5, 0x9f, 0x3b, 0x65, 0x26, 0xa4, 0x26, 0xab, 0xdb, 0x29, 0xdd, 0xc3, 0x34, 0x3f, + 0x30, 0x23, 0x38, 0xe0, 0xde, 0xfe, 0xaa, 0x3f, 0x86, 0x49, 0xa6, 0xc9, 0x29, 0x92, 0x5f, 0xa4, 0xa7, 0x90, 0xb4, + 0x43, 0x4f, 0x15, 0x01, 0x9c, 0x50, 0xfb, 0x31, 0xfc, 0x86, 0x71, 0xff, 0xae, 0xf9, 0xda, 0x4d, 0x45, 0xf4, 0x98, + 0x62, 0x99, 0x9a, 0x9c, 0x26, 0x59, 0x91, 0x40, 0xd4, 0x46, 0xd5, 0x8c, 0xe8, 0x91, 0x8b, 0xf9, 0xa8, 0x08, 0x9f, + 0x57, 0xeb, 0xff, 0x0c, 0xe1, 0x33, 0x0a, 0x37, 0x80, 0xcb, 0x2b, 0x2e, 0xcf, 0xc3, 0x27, 0x8f, 0xe9, 0xc1, 0xe4, + 0x9b, 0x23, 0x7a, 0x70, 0xf4, 0xe8, 0x09, 0x01, 0x58, 0xb4, 0xcb, 0xf3, 0xf0, 0xe8, 0xc9, 0x13, 0x7a, 0xf0, 0xed, + 0xb7, 0xf4, 0x60, 0xf2, 0xe8, 0xa8, 0x91, 0x36, 0x79, 0xf2, 0x2d, 0x3d, 0xf8, 0xe6, 0x71, 0x23, 0xed, 0x68, 0xfc, + 0x84, 0x1e, 0xfc, 0xfd, 0x1b, 0x93, 0xf6, 0x37, 0xc8, 0xf6, 0xed, 0x11, 0xfe, 0x67, 0xd2, 0x26, 0x4f, 0x1e, 0xd1, + 0x83, 0xc9, 0x18, 0x2a, 0x79, 0xe2, 0x2a, 0x19, 0x4f, 0xe0, 0xe3, 0x47, 0xf0, 0xdf, 0xdf, 0x08, 0x6c, 0x02, 0xc9, + 0x72, 0x81, 0xfa, 0x33, 0x14, 0x71, 0xa2, 0x6a, 0x22, 0xe1, 0x21, 0x66, 0x56, 0xdf, 0xc4, 0x61, 0x40, 0x5c, 0x3a, + 0x14, 0x44, 0x0f, 0xc6, 0xa3, 0x27, 0x24, 0xf0, 0xe1, 0xe9, 0x3e, 0xfa, 0x20, 0x63, 0xb9, 0x98, 0x67, 0x5f, 0xe5, + 0x26, 0xb6, 0x82, 0x07, 0x60, 0xf5, 0xde, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x8a, 0xcb, 0xdd, 0x5c, 0xff, 0x68, 0x01, + 0xca, 0xfb, 0xab, 0x96, 0x7d, 0x2c, 0x54, 0xe8, 0xb4, 0xd6, 0xe8, 0xb3, 0xf7, 0x98, 0x3e, 0x18, 0x78, 0x37, 0xec, + 0xef, 0x77, 0xca, 0x69, 0x7d, 0xa3, 0x51, 0xa8, 0x51, 0x79, 0x48, 0xd8, 0x09, 0x14, 0x3d, 0x18, 0x00, 0x4f, 0xe0, + 0xe1, 0xbe, 0xfd, 0x9b, 0x65, 0xbc, 0xef, 0x28, 0xe3, 0x5f, 0x28, 0x43, 0x40, 0xa3, 0x1e, 0x66, 0x37, 0x3d, 0x6c, + 0x74, 0xab, 0x97, 0x2c, 0xd5, 0xc9, 0xd4, 0xf4, 0x0c, 0xf6, 0xb5, 0xae, 0xe5, 0x81, 0x11, 0x45, 0xcb, 0x8b, 0x83, + 0x94, 0xcf, 0x2a, 0xf6, 0xfd, 0x12, 0xd5, 0x5b, 0x51, 0xe3, 0x8d, 0xcc, 0x66, 0x15, 0xfb, 0xd9, 0xbc, 0x01, 0x6e, + 0x86, 0xfd, 0x43, 0x3d, 0xf9, 0x81, 0x33, 0x32, 0x69, 0xdb, 0xa3, 0x4c, 0x8c, 0x00, 0x2b, 0x20, 0x03, 0x07, 0x1e, + 0x00, 0x1d, 0xf4, 0x47, 0x7b, 0xbb, 0x55, 0x29, 0xcd, 0x3e, 0x5b, 0x18, 0x40, 0xc3, 0xbc, 0x4d, 0x3c, 0x54, 0xb3, + 0x86, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0x76, 0x0a, 0x43, 0x08, 0xc1, 0x2a, 0x65, 0x00, 0x38, 0x10, 0x60, 0x30, + 0xd6, 0x32, 0xa0, 0x66, 0xcb, 0x47, 0x1b, 0xae, 0xd4, 0x93, 0xc0, 0x19, 0x5c, 0xc8, 0x22, 0xe1, 0x6f, 0xb4, 0xd8, + 0x1f, 0xad, 0x1f, 0x7d, 0xdf, 0x1e, 0x0f, 0xd6, 0xbe, 0xc7, 0x47, 0xfa, 0xb3, 0xc6, 0x75, 0x60, 0xd3, 0xf2, 0x8d, + 0x17, 0xb5, 0x95, 0x78, 0x94, 0xc0, 0x1b, 0x98, 0x88, 0x14, 0x06, 0xa9, 0x16, 0x38, 0x06, 0xe5, 0x8d, 0x85, 0x58, + 0xaa, 0xae, 0x6e, 0xe8, 0x96, 0x0c, 0xc1, 0xc3, 0xed, 0xc7, 0xa5, 0x0a, 0x1c, 0xd5, 0xef, 0x67, 0xd2, 0x77, 0x7b, + 0x32, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0xe1, 0xe0, 0xbf, 0x49, 0x5d, 0x1b, 0xbb, 0xfb, 0x94, 0x59, 0x96, 0x85, 0x9d, + 0x84, 0x5a, 0xee, 0x51, 0x79, 0x90, 0x7c, 0x21, 0x87, 0x48, 0x16, 0x18, 0x85, 0x82, 0x0c, 0x27, 0x54, 0x8c, 0xd6, + 0xa2, 0x5c, 0x66, 0x17, 0x55, 0xb8, 0x51, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, 0x48, 0x48, 0x94, 0x95, 0xaf, + 0xe3, 0xd7, 0x21, 0x82, 0xd5, 0x71, 0x6d, 0x0b, 0xc5, 0xbd, 0xfd, 0x99, 0xa5, 0x5d, 0xfc, 0x91, 0x71, 0x01, 0x75, + 0xb1, 0x98, 0x86, 0x13, 0xab, 0xdf, 0x71, 0x5f, 0x58, 0x4d, 0x0f, 0x40, 0x7d, 0x97, 0x4a, 0x8c, 0xa0, 0xbe, 0x32, + 0xf6, 0xb1, 0x3d, 0xc6, 0xe4, 0x0c, 0x62, 0x0d, 0xeb, 0xbb, 0x9d, 0xea, 0x1b, 0x61, 0x27, 0x00, 0xdc, 0x08, 0xad, + 0xd1, 0x91, 0x49, 0xaa, 0x10, 0xcf, 0x4b, 0x15, 0xbe, 0x35, 0x23, 0x74, 0x0c, 0xde, 0x54, 0xb6, 0x91, 0x42, 0xfa, + 0x82, 0x41, 0x73, 0x6c, 0xeb, 0x28, 0xac, 0xb6, 0xb2, 0xec, 0x04, 0xe0, 0x06, 0xb2, 0x63, 0x73, 0xf1, 0x9c, 0x55, + 0xf3, 0x6c, 0x11, 0x99, 0xa0, 0x80, 0x4b, 0x61, 0x19, 0xb4, 0xd7, 0x7b, 0x64, 0x3b, 0x0e, 0xa1, 0x1b, 0xee, 0x23, + 0x18, 0x4f, 0xbb, 0x29, 0x58, 0x41, 0x34, 0x42, 0x3c, 0xcc, 0x98, 0xc5, 0xf7, 0x4a, 0x53, 0x9e, 0xaa, 0x96, 0x40, + 0xe0, 0x28, 0x84, 0xba, 0xd8, 0x35, 0x4a, 0x70, 0x99, 0x1a, 0xc1, 0x0c, 0x76, 0xec, 0x48, 0x6d, 0x97, 0x9c, 0xd3, + 0xa1, 0x9a, 0xd2, 0x52, 0x4f, 0xa9, 0xf6, 0x35, 0x14, 0xf3, 0x12, 0x3d, 0xf4, 0xc0, 0xf5, 0x40, 0x3b, 0xe4, 0x95, + 0x74, 0x62, 0x22, 0xe8, 0xb4, 0xda, 0x84, 0x9d, 0x1b, 0xe9, 0x96, 0xd5, 0xc8, 0x3b, 0x86, 0x66, 0x47, 0xbc, 0xf4, + 0x03, 0x75, 0x01, 0x44, 0xc8, 0xde, 0x16, 0x99, 0xd9, 0x67, 0x59, 0xf9, 0x02, 0xca, 0xe2, 0x88, 0xad, 0x2b, 0xe0, + 0x5a, 0x0a, 0x26, 0x97, 0x3c, 0xca, 0x52, 0x44, 0x04, 0x3c, 0x55, 0xda, 0xf5, 0x9d, 0x96, 0x10, 0x2a, 0x52, 0x20, + 0x6e, 0x2e, 0x8a, 0x73, 0x6d, 0x03, 0x59, 0x00, 0x7d, 0xfb, 0x29, 0xbb, 0xf2, 0xc2, 0xc1, 0x6e, 0xae, 0x32, 0xf1, + 0x8c, 0x5f, 0x64, 0x82, 0xa7, 0x08, 0x76, 0x75, 0x6b, 0x1e, 0xb8, 0x63, 0xdb, 0xc0, 0xf2, 0xed, 0x3b, 0x58, 0x30, + 0x65, 0xa8, 0x95, 0x12, 0x99, 0x88, 0x04, 0x64, 0xf6, 0x99, 0xbb, 0x57, 0x99, 0x78, 0x15, 0xdf, 0x82, 0x37, 0x45, + 0x83, 0x9f, 0x1e, 0x9d, 0xe3, 0x97, 0x88, 0x24, 0x0a, 0x31, 0x6c, 0x31, 0x22, 0x16, 0x22, 0xc7, 0x8e, 0x09, 0xe5, + 0x4a, 0xd0, 0xda, 0x1a, 0x02, 0x2f, 0xfe, 0xb4, 0xea, 0xde, 0x55, 0x26, 0x8c, 0x7d, 0xc6, 0x55, 0x7c, 0xcb, 0x4a, + 0x05, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xab, 0x4c, 0x18, 0x01, 0xc9, 0x55, 0x7c, 0x4b, 0x9b, 0x32, 0x0e, + 0x6d, 0x45, 0xe7, 0xc5, 0xf9, 0xdd, 0x1d, 0x7e, 0x89, 0xa1, 0x56, 0xc6, 0xfd, 0x3e, 0x48, 0xcc, 0xa4, 0x6d, 0xca, + 0x4c, 0x46, 0x52, 0xa3, 0x85, 0x54, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x5a, 0x46, 0xd4, 0x7e, 0x15, 0x8a, 0xd9, + 0x38, 0x9a, 0x10, 0x3a, 0xe9, 0x58, 0xef, 0xa6, 0xb5, 0x90, 0x69, 0xf4, 0x24, 0xf2, 0x7c, 0x3a, 0x0b, 0x56, 0x4d, + 0x8b, 0x63, 0xc6, 0xa7, 0xc5, 0x60, 0x40, 0xb4, 0x4b, 0xe1, 0x06, 0xeb, 0x01, 0x53, 0x1a, 0x17, 0x6f, 0xcd, 0xb4, + 0xfa, 0x85, 0x54, 0x21, 0xe9, 0x3d, 0x03, 0x12, 0x21, 0x5d, 0xb0, 0x5b, 0x90, 0x28, 0x7a, 0xfe, 0x77, 0x6a, 0x0b, + 0xee, 0x7a, 0x30, 0x36, 0xa3, 0xfb, 0x7a, 0xc6, 0x7f, 0xa8, 0x6d, 0x41, 0xd4, 0xa7, 0x92, 0xf5, 0x3a, 0x12, 0x55, + 0xc8, 0x45, 0xf8, 0xd9, 0xd1, 0x10, 0x43, 0x54, 0x7b, 0x2c, 0x10, 0xeb, 0xab, 0x73, 0x5e, 0xe0, 0xf4, 0x33, 0x77, + 0xb9, 0x82, 0x6d, 0x41, 0x2b, 0x43, 0xa3, 0x5e, 0xc7, 0xaf, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0x3e, 0x43, 0x21, 0x6b, + 0x1e, 0x86, 0xd5, 0xb0, 0x3d, 0x88, 0xe4, 0xb0, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, + 0xad, 0xfc, 0xed, 0x18, 0x5c, 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, + 0xb0, 0x2a, 0x65, 0x92, 0x0f, 0xbf, 0x5e, 0xc8, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, + 0xb0, 0xee, 0x93, 0xf7, 0xf5, 0xc3, 0xce, 0x9e, 0x80, 0x51, 0xac, 0xca, 0xd1, 0x14, 0x52, 0x6a, 0x1f, 0x94, 0xfa, + 0x63, 0xb8, 0x14, 0x9a, 0x63, 0xb7, 0x80, 0x49, 0xc0, 0x3e, 0x43, 0xaa, 0xc7, 0xb4, 0x63, 0x9f, 0xa3, 0x0d, 0x2c, + 0x09, 0x38, 0xfc, 0x23, 0x21, 0x6b, 0xff, 0xea, 0x5e, 0xa6, 0xcd, 0x90, 0x2d, 0xf3, 0x05, 0xf0, 0xf9, 0xb0, 0x6b, + 0xa3, 0x12, 0x65, 0x13, 0x91, 0xa4, 0xb0, 0xe5, 0x31, 0x48, 0x7b, 0x14, 0xd3, 0x55, 0xc1, 0x93, 0x0c, 0xa5, 0x14, + 0x89, 0xf6, 0x09, 0xce, 0xe1, 0x0d, 0xee, 0x47, 0x15, 0x10, 0x5e, 0x85, 0x9c, 0x8e, 0x52, 0xaa, 0x2d, 0x60, 0x14, + 0xf5, 0x00, 0x51, 0x5e, 0x06, 0x72, 0xbc, 0xed, 0x76, 0x42, 0x57, 0x6c, 0x39, 0x9c, 0x50, 0x24, 0x25, 0x97, 0x58, + 0xee, 0x15, 0xe8, 0x3c, 0xce, 0x59, 0xef, 0x25, 0x60, 0x11, 0x9c, 0xc1, 0xdf, 0x98, 0xd0, 0x6b, 0xf8, 0x9b, 0x13, + 0xfa, 0x94, 0x85, 0x57, 0xc3, 0x4b, 0x72, 0x18, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0xb4, 0x0c, 0x55, 0xe2, + 0xea, 0xf0, 0x82, 0x3c, 0xbc, 0xa0, 0xb7, 0xf4, 0x86, 0xbe, 0xa2, 0x6f, 0x80, 0xf0, 0xdf, 0x1d, 0x4f, 0xf8, 0x70, + 0xf2, 0xb8, 0xdf, 0xef, 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, + 0x7a, 0x31, 0x7d, 0xa3, 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xbc, 0x23, 0x43, 0x7c, 0xbc, 0xc8, 0xa5, 0x2c, + 0xc2, 0xcb, 0xc3, 0x3b, 0x42, 0xdf, 0x9c, 0x80, 0xde, 0x14, 0xeb, 0x7b, 0xf3, 0xf0, 0x4e, 0xd7, 0x46, 0xe8, 0xcb, + 0x30, 0x81, 0x6d, 0x72, 0xcb, 0xec, 0x5d, 0x7b, 0x32, 0x86, 0x58, 0x26, 0x77, 0x5e, 0x79, 0x77, 0x0f, 0x6f, 0xc9, + 0xe1, 0x2d, 0x78, 0x8a, 0x5a, 0xf2, 0x37, 0x0b, 0x6f, 0x58, 0xab, 0x86, 0x87, 0x77, 0xf4, 0x55, 0xab, 0x11, 0x0f, + 0xef, 0x48, 0x14, 0xde, 0xb0, 0x4b, 0xfa, 0x8a, 0x5d, 0x11, 0x7a, 0xde, 0xef, 0x9f, 0xf5, 0xfb, 0xb2, 0xdf, 0xff, + 0x3e, 0x0e, 0xc3, 0x78, 0x58, 0x90, 0x43, 0x49, 0xef, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, + 0x59, 0x95, 0xb7, 0xca, 0x75, 0x47, 0xc1, 0x5a, 0xe1, 0x8e, 0xa9, 0xa7, 0x37, 0xf4, 0x86, 0x15, 0xf4, 0x15, 0x8b, + 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, 0x15, 0xd1, 0x0d, 0x7d, 0xc5, 0xce, 0x66, 0x71, 0xf4, 0x8a, 0xbe, 0x61, 0xf9, + 0x70, 0x02, 0x79, 0x5f, 0x0d, 0x6f, 0xc8, 0xe1, 0x1b, 0x12, 0x85, 0x6f, 0xf4, 0xef, 0x3b, 0x7a, 0xc9, 0xc3, 0x37, + 0xd4, 0xab, 0xe6, 0x0d, 0x31, 0xd5, 0x37, 0x6a, 0x7f, 0x43, 0x22, 0x7f, 0x30, 0xdf, 0x58, 0x7b, 0x9a, 0xb7, 0x8e, + 0x36, 0xae, 0xcb, 0xf0, 0x8e, 0xd0, 0x75, 0x19, 0xde, 0x10, 0x32, 0x6d, 0x8e, 0x1d, 0x0c, 0xe8, 0xec, 0x6d, 0x94, + 0x10, 0x7a, 0xe3, 0x97, 0x7a, 0x83, 0x63, 0x68, 0x46, 0x48, 0xf7, 0x13, 0xd3, 0x70, 0x1d, 0x7c, 0xd0, 0x60, 0x1d, + 0xe7, 0xfd, 0x7e, 0xb8, 0xee, 0xf7, 0x21, 0xd2, 0x7d, 0x31, 0x33, 0xb1, 0xdd, 0x1c, 0xd9, 0xa4, 0x37, 0xa0, 0xfd, + 0xff, 0x30, 0x18, 0x40, 0x67, 0xbc, 0x92, 0xc2, 0x9b, 0xc1, 0x87, 0x87, 0x77, 0x44, 0xd5, 0x51, 0xd0, 0x52, 0x86, + 0x05, 0x7d, 0x4a, 0x33, 0x00, 0xfc, 0xfa, 0x30, 0x18, 0x90, 0xc8, 0x7c, 0x46, 0xa6, 0x1f, 0x8e, 0xdf, 0x4c, 0x07, + 0x83, 0x0f, 0x66, 0x9b, 0x7c, 0x62, 0x7b, 0x4a, 0x81, 0xf5, 0x77, 0xd6, 0xef, 0x7f, 0x3a, 0x89, 0xc9, 0x79, 0xc1, + 0xe3, 0x8f, 0xd3, 0x66, 0x5b, 0x3e, 0xb9, 0xa8, 0x6a, 0x67, 0xfd, 0xfe, 0xba, 0xdf, 0x7f, 0x05, 0xd8, 0x45, 0x33, + 0xe7, 0xeb, 0x09, 0xd2, 0x96, 0xb9, 0xa3, 0x48, 0x9a, 0xe4, 0xd0, 0x18, 0xda, 0x16, 0xab, 0xb6, 0xcd, 0x3a, 0x32, + 0xb0, 0x38, 0x6a, 0x56, 0x14, 0xd7, 0x24, 0x0a, 0x7b, 0x67, 0xdb, 0xed, 0x2b, 0xc6, 0x58, 0x4c, 0x40, 0xfa, 0xe1, + 0xbf, 0x7e, 0x55, 0x37, 0x62, 0x88, 0x95, 0x4a, 0x7c, 0xb7, 0x59, 0xda, 0x43, 0x20, 0xe2, 0xb0, 0xe9, 0xdf, 0x99, + 0x7b, 0xb9, 0xa8, 0x1d, 0xdf, 0xfa, 0x2f, 0x00, 0x21, 0x92, 0x2c, 0xe4, 0x33, 0x1c, 0x83, 0x32, 0x03, 0x20, 0xf3, + 0x48, 0xcd, 0xbc, 0x04, 0x10, 0x60, 0xb2, 0xdd, 0x8e, 0xc6, 0xe3, 0x09, 0x2d, 0xd8, 0xe8, 0x6f, 0x4f, 0x1e, 0x56, + 0x0f, 0xc3, 0x20, 0x18, 0x64, 0xa4, 0xa5, 0xa7, 0xb0, 0x8b, 0xb5, 0x3a, 0x04, 0x23, 0x78, 0xcd, 0x3e, 0x5e, 0x67, + 0x5f, 0xcc, 0x3e, 0x22, 0x61, 0x6d, 0x30, 0x8e, 0x5c, 0xa4, 0x2d, 0xbd, 0xdd, 0x1e, 0x06, 0x93, 0x8b, 0xf4, 0x33, + 0x6c, 0xa7, 0xcf, 0xbf, 0x79, 0x30, 0x9e, 0x70, 0x30, 0xba, 0x8b, 0x82, 0x3e, 0xd3, 0xb6, 0xdb, 0xca, 0xbf, 0x04, + 0xbe, 0xc6, 0x54, 0xd0, 0xb1, 0x59, 0x16, 0x6e, 0x50, 0x11, 0x75, 0xb4, 0x0c, 0xaa, 0x5a, 0xd9, 0xce, 0x01, 0xb5, + 0xc4, 0xaa, 0x4c, 0xdc, 0x02, 0xc3, 0x90, 0xa1, 0x2e, 0xf7, 0xb4, 0xfa, 0x17, 0x2f, 0xa4, 0x81, 0xcf, 0x70, 0x22, + 0x42, 0x8f, 0x5b, 0xe3, 0x3e, 0xb7, 0x26, 0x3e, 0xc3, 0xad, 0x95, 0x48, 0x62, 0x0d, 0x2c, 0xa9, 0xb9, 0x1c, 0x25, + 0xec, 0xa4, 0x64, 0x7c, 0x56, 0x46, 0x09, 0x8d, 0xe1, 0x41, 0x32, 0x31, 0x93, 0x51, 0x82, 0xf6, 0x89, 0x2e, 0xc2, + 0xe0, 0x5f, 0x80, 0xd9, 0x4f, 0x73, 0xf8, 0x2b, 0xc9, 0x34, 0x39, 0x86, 0x80, 0x10, 0xc7, 0xe3, 0x59, 0x1c, 0x8e, + 0x49, 0x94, 0x9c, 0xc0, 0x13, 0xfc, 0x57, 0x84, 0x63, 0x52, 0xeb, 0x3b, 0x8c, 0x54, 0x97, 0xdb, 0x84, 0x01, 0x5c, + 0xd9, 0x78, 0x36, 0x89, 0xac, 0x74, 0x57, 0x3e, 0x1c, 0x8d, 0x9f, 0x90, 0x69, 0x1c, 0xca, 0x41, 0x42, 0x28, 0x78, + 0xf7, 0x86, 0xe5, 0x30, 0xd1, 0xf0, 0x6c, 0xc0, 0xe6, 0x95, 0x8e, 0xcd, 0x93, 0x70, 0x02, 0xc2, 0x30, 0x21, 0xc7, + 0xba, 0x07, 0x29, 0x45, 0x9f, 0xe7, 0xd8, 0x4f, 0x7d, 0x04, 0x61, 0x76, 0xd4, 0x52, 0xf1, 0x15, 0x00, 0x5d, 0xe2, + 0xe0, 0x50, 0x7b, 0xe6, 0x8b, 0x59, 0x58, 0x7a, 0x54, 0xca, 0x54, 0x77, 0x28, 0x1a, 0x94, 0xdf, 0x34, 0xe8, 0x50, + 0x90, 0xc1, 0x84, 0x96, 0x27, 0x13, 0xfe, 0x08, 0x02, 0x78, 0x34, 0x22, 0x7e, 0x29, 0x9c, 0x18, 0x08, 0xaf, 0x82, + 0x0c, 0x54, 0x5a, 0xab, 0xc6, 0x8c, 0x6c, 0xc5, 0x07, 0x10, 0x26, 0xe5, 0xe0, 0x46, 0xae, 0xf3, 0x14, 0xa2, 0x82, + 0xad, 0xf3, 0xea, 0xe0, 0x12, 0x2c, 0xd9, 0xe3, 0x0a, 0xe2, 0x84, 0xad, 0x57, 0x80, 0x9d, 0xfb, 0x60, 0x53, 0xd6, + 0x07, 0xea, 0xbb, 0x03, 0x6c, 0x39, 0xbc, 0xaa, 0xe4, 0xc1, 0x64, 0x3c, 0x1e, 0x8f, 0xfe, 0x80, 0xa3, 0x03, 0x08, + 0x2d, 0x89, 0x0c, 0x9f, 0x0c, 0xd0, 0xb8, 0xeb, 0x8a, 0x7b, 0xe3, 0x42, 0x51, 0x56, 0x3a, 0x99, 0x10, 0x10, 0x3f, + 0x9b, 0xbe, 0xc1, 0xbe, 0xe2, 0x3a, 0xfe, 0xc9, 0xee, 0x27, 0x66, 0x45, 0xab, 0x95, 0x3a, 0x7a, 0xfb, 0xe6, 0xfd, + 0xcb, 0x0f, 0x2f, 0x7f, 0x7d, 0x7e, 0xf6, 0xf2, 0xf5, 0x8b, 0x97, 0xaf, 0x5f, 0x7e, 0xf8, 0xe7, 0x3d, 0x0c, 0xb6, + 0x6f, 0x2b, 0x62, 0xc7, 0xde, 0xbb, 0xc7, 0x78, 0xb5, 0xf8, 0xc2, 0xd9, 0x23, 0x77, 0x8b, 0x05, 0xd8, 0x04, 0xc3, + 0x2d, 0x08, 0xaa, 0x19, 0x8d, 0x4a, 0xdf, 0x13, 0x90, 0xd1, 0xa8, 0x90, 0x8d, 0x87, 0x15, 0x5b, 0x21, 0x17, 0xef, + 0x18, 0x0e, 0x3e, 0xb2, 0xbf, 0x15, 0x67, 0xc2, 0xed, 0x68, 0x6b, 0x56, 0x04, 0x7c, 0xbe, 0xd6, 0xa2, 0xf2, 0xb8, + 0x10, 0xb5, 0xb7, 0xed, 0x73, 0x48, 0xa8, 0x47, 0xe4, 0x3a, 0x78, 0xdf, 0x06, 0xd9, 0xe3, 0x23, 0xef, 0x49, 0x79, + 0x86, 0xfa, 0x1c, 0x0d, 0x1f, 0x35, 0x9e, 0xd1, 0x89, 0xb9, 0x36, 0x3a, 0xd4, 0xb3, 0x02, 0xf6, 0xb7, 0x12, 0x63, + 0xd3, 0x82, 0x95, 0x29, 0x62, 0x7d, 0x38, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x67, 0x38, 0x7e, 0x94, 0x6a, 0x02, 0x69, + 0x51, 0xa0, 0x74, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0xc2, 0xfc, 0x0c, 0x1b, 0x04, 0xd0, 0x5e, 0x76, 0x2c, 0x09, 0x34, + 0x8b, 0xd7, 0xba, 0xfe, 0x79, 0xf9, 0x32, 0xd1, 0xce, 0x17, 0xdf, 0x42, 0x88, 0x61, 0xff, 0x8a, 0xd0, 0x98, 0x70, + 0x37, 0xc9, 0xee, 0xd2, 0x62, 0xee, 0x55, 0x57, 0x31, 0x1e, 0x77, 0x7b, 0xae, 0x14, 0xcd, 0x5b, 0x17, 0xd8, 0x03, + 0x35, 0xaf, 0xe3, 0x25, 0x0b, 0x01, 0x9b, 0xf1, 0xd0, 0x2e, 0x12, 0xe7, 0xf7, 0x4e, 0x27, 0xe4, 0xf0, 0x68, 0xca, + 0x87, 0xac, 0xa4, 0x62, 0xc0, 0xca, 0x7a, 0x87, 0x9a, 0xf3, 0x36, 0x21, 0x17, 0xbb, 0x34, 0x5c, 0x0c, 0xf9, 0x7d, + 0x97, 0xa4, 0x0f, 0xbc, 0xe1, 0x50, 0x6d, 0x9b, 0x8b, 0x21, 0x4d, 0x39, 0xdd, 0xa5, 0x32, 0x20, 0x44, 0xba, 0x8a, + 0x2b, 0x52, 0xeb, 0xa3, 0x2a, 0x75, 0x92, 0x8e, 0xeb, 0x6c, 0xf3, 0x99, 0x4b, 0xb6, 0xba, 0x5d, 0xfb, 0xd7, 0xea, + 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x9f, 0x88, 0x6a, 0x62, 0x20, 0xba, 0x80, 0x0a, 0xfe, 0x09, 0x5e, 0x9e, 0x3c, 0xd2, + 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0x6f, 0xcc, 0x62, 0x6b, 0x89, 0x73, 0x56, 0xf9, 0xce, 0xf2, 0xaa, 0x6c, + 0x85, 0xae, 0x23, 0xd8, 0xbf, 0xc2, 0x8e, 0xbe, 0x7b, 0xdb, 0x00, 0x88, 0x52, 0x58, 0xb9, 0xb3, 0x5f, 0x78, 0x67, + 0xbf, 0xb0, 0x67, 0xbf, 0xdd, 0x04, 0xca, 0x87, 0x15, 0x5a, 0xf6, 0x42, 0x8a, 0xca, 0x34, 0x79, 0xdc, 0xd4, 0x65, + 0x21, 0x2d, 0xe6, 0x87, 0x96, 0x76, 0x3d, 0x1e, 0x53, 0x89, 0xea, 0x91, 0x1f, 0xb0, 0x55, 0x87, 0x25, 0xb9, 0xff, + 0x9e, 0xf9, 0x3f, 0x7b, 0x83, 0xdc, 0x77, 0xb7, 0xfb, 0xbf, 0xb9, 0xd0, 0xc1, 0x6d, 0x2d, 0x15, 0x9e, 0xba, 0x3a, + 0x2e, 0xf0, 0xae, 0x96, 0xde, 0x7f, 0x57, 0x7b, 0x90, 0xe9, 0x65, 0x57, 0x01, 0x6a, 0x90, 0x58, 0x5f, 0xf1, 0x22, + 0x4b, 0x6a, 0xab, 0xd0, 0x78, 0xc3, 0x21, 0xb4, 0x87, 0x77, 0x70, 0x81, 0x1c, 0x96, 0x10, 0xfa, 0xb1, 0x32, 0x02, + 0x40, 0x9f, 0xc5, 0x7e, 0xc3, 0xc3, 0x8c, 0x0c, 0x7c, 0x89, 0x9f, 0x94, 0xbe, 0xb8, 0xf8, 0x70, 0x27, 0x33, 0x41, + 0xaf, 0x12, 0x17, 0x35, 0x57, 0xb6, 0x63, 0x7e, 0xf8, 0x5f, 0x60, 0x34, 0x08, 0xaf, 0x2d, 0xd9, 0xa1, 0xe8, 0x98, + 0xe5, 0x0a, 0x8e, 0xda, 0xd2, 0x95, 0x29, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x0d, 0xc8, 0xbe, 0x90, + 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0x77, + 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0xf5, 0x01, 0xea, 0x6b, 0x6c, 0x49, 0xb2, 0xa9, 0xd8, 0x5f, 0x60, 0x16, 0x0b, 0xc4, + 0xd1, 0xc1, 0x2f, 0xce, 0x17, 0x00, 0xb2, 0x0c, 0xcb, 0x4c, 0x0b, 0x8b, 0x64, 0xaa, 0x7c, 0x64, 0x0b, 0x26, 0x8f, + 0xc7, 0x33, 0xbf, 0xe7, 0x8e, 0xc1, 0x21, 0x24, 0x9a, 0x58, 0xe3, 0x17, 0x3f, 0x0b, 0xc6, 0x71, 0x28, 0x4f, 0x64, + 0xe3, 0xbb, 0x92, 0x44, 0x63, 0x63, 0xaa, 0xac, 0xaf, 0x12, 0xd5, 0x30, 0x21, 0x0f, 0x0b, 0x72, 0x58, 0xd0, 0xa5, + 0x3f, 0x96, 0x98, 0x7e, 0x18, 0x1f, 0x4e, 0xc6, 0xe4, 0x61, 0xfc, 0x70, 0x62, 0xe0, 0x86, 0xfd, 0x1c, 0xf9, 0x70, + 0x49, 0x0e, 0x9b, 0x55, 0x82, 0x29, 0xaa, 0xe9, 0x99, 0x5f, 0x49, 0x32, 0x58, 0x0e, 0xd2, 0x87, 0xad, 0xbc, 0x58, + 0xab, 0x1e, 0xef, 0xf5, 0x31, 0x9f, 0x12, 0xd1, 0xb8, 0x31, 0xac, 0xe9, 0x55, 0xfc, 0xa7, 0x2c, 0x22, 0x29, 0x01, + 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x84, 0x4d, 0xc6, 0xb3, 0x94, + 0xa5, 0xc7, 0x93, 0x27, 0xb3, 0xc9, 0x93, 0xe8, 0x68, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8d, 0xc1, 0xc5, 0x0e, + 0x7e, 0xb3, 0x23, 0x18, 0xba, 0x13, 0x64, 0x09, 0x0b, 0x68, 0xda, 0x97, 0x35, 0x49, 0x0f, 0xe7, 0x85, 0xea, 0x49, + 0x7c, 0x4b, 0xd7, 0x9e, 0x83, 0x8b, 0xdf, 0xc2, 0x0b, 0xd7, 0xc2, 0x8b, 0xdd, 0x16, 0x0a, 0x4d, 0xb6, 0x63, 0xf9, + 0xff, 0xe3, 0x86, 0xb1, 0xef, 0x2e, 0x61, 0x16, 0xd7, 0x75, 0x36, 0x5a, 0x15, 0xb2, 0x92, 0x70, 0x9b, 0x50, 0xa2, + 0xb0, 0x51, 0xbc, 0x5a, 0xe5, 0xda, 0x45, 0x6c, 0x5e, 0x51, 0x00, 0x77, 0x81, 0x38, 0xc5, 0xc0, 0x42, 0x1b, 0x03, + 0xb9, 0x4f, 0xbc, 0x90, 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0xcf, 0x10, 0x8c, 0x51, 0xc5, 0xc9, 0x78, 0xa6, 0xb0, + 0x2e, 0x3e, 0x27, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x7b, 0x34, 0x83, 0x9e, 0x20, 0x72, 0x1e, 0x71, 0xf6, 0x64, 0xf2, + 0x32, 0x70, 0x3f, 0x83, 0x95, 0xfe, 0xba, 0xdb, 0x8c, 0xb5, 0xed, 0xd1, 0xbd, 0x30, 0x42, 0xd1, 0x4f, 0xf8, 0xce, + 0xd4, 0x0b, 0xb8, 0x84, 0x6a, 0x60, 0xd7, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, 0xf4, 0xfb, 0xbd, 0x3f, 0x0d, + 0x34, 0x69, 0xc9, 0x8b, 0x57, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x1f, 0x2b, 0xfb, 0x4c, 0xc7, 0x64, + 0xe6, 0x3f, 0x0e, 0x27, 0x24, 0x6a, 0xbe, 0x26, 0x9f, 0x39, 0x4d, 0x3f, 0x73, 0x45, 0xfb, 0x0f, 0x64, 0xe6, 0x86, + 0x43, 0x86, 0xfa, 0x4b, 0xc7, 0x3c, 0x19, 0xbd, 0x4e, 0xcc, 0x4e, 0x04, 0xab, 0x66, 0x10, 0x85, 0xbd, 0x80, 0x07, + 0x75, 0x2d, 0x8b, 0xa7, 0x30, 0xfb, 0xa0, 0x46, 0x14, 0xc7, 0x6c, 0x3c, 0x0b, 0x65, 0x38, 0x01, 0xfb, 0xde, 0xc9, + 0x18, 0xee, 0x03, 0x32, 0xfc, 0x58, 0x85, 0xd8, 0x39, 0x48, 0xfb, 0x58, 0xa1, 0x62, 0x02, 0x20, 0x02, 0x21, 0x6f, + 0xbf, 0x2f, 0x55, 0x12, 0xbe, 0x2e, 0x31, 0xa5, 0x50, 0x1f, 0xfc, 0x27, 0x52, 0x75, 0xc7, 0xf4, 0xab, 0xf5, 0xe3, + 0xcf, 0x84, 0xe2, 0xd3, 0x5d, 0x4a, 0x7c, 0x0b, 0xc1, 0x9d, 0x0b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0x76, 0x3f, 0xbf, + 0x2b, 0xf6, 0xf3, 0xbb, 0xe2, 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, + 0xf4, 0x9f, 0xf3, 0x89, 0x7b, 0x79, 0xea, 0xab, 0x4c, 0x4c, 0xf7, 0x30, 0xcd, 0x3e, 0x41, 0x41, 0x58, 0xc5, 0x5d, + 0x7a, 0xb2, 0xae, 0xec, 0xad, 0x95, 0x0c, 0x31, 0xcf, 0x3d, 0xac, 0x51, 0x58, 0x79, 0x40, 0xf7, 0xa8, 0xda, 0x20, + 0x4e, 0x04, 0x0f, 0x63, 0x66, 0xa5, 0xef, 0xdb, 0xad, 0x51, 0x61, 0xde, 0xcb, 0x45, 0x41, 0x76, 0xf3, 0xf1, 0x6c, + 0x1c, 0x85, 0xd8, 0x80, 0xff, 0x98, 0xb1, 0x6a, 0xc8, 0xe6, 0x3b, 0x19, 0xa9, 0x1d, 0x93, 0xa7, 0xc9, 0x2e, 0xe9, + 0x1d, 0xf0, 0x0e, 0xf9, 0x79, 0xfd, 0x31, 0x8c, 0xa5, 0xe1, 0xb7, 0xe4, 0x65, 0x5c, 0x64, 0xd5, 0xf2, 0x2a, 0x4b, + 0x90, 0xe9, 0x82, 0x17, 0x5f, 0xcc, 0x74, 0x79, 0x1f, 0xeb, 0x03, 0xc6, 0x53, 0x8a, 0xd7, 0x0d, 0x51, 0xfa, 0xba, + 0xe5, 0x59, 0xa1, 0x2e, 0x4f, 0x2a, 0x66, 0x7b, 0x56, 0x82, 0xd3, 0x29, 0x98, 0xe0, 0xeb, 0x9f, 0xae, 0xf7, 0x09, + 0xe0, 0x82, 0x42, 0xcd, 0x69, 0x21, 0x57, 0x06, 0xcb, 0xc9, 0x42, 0x77, 0x02, 0x66, 0xa8, 0x14, 0x78, 0x81, 0x82, + 0xbf, 0x68, 0x60, 0x44, 0x5f, 0xb8, 0xdf, 0x64, 0x60, 0x90, 0x2e, 0xcd, 0x89, 0x30, 0x76, 0xdc, 0x4e, 0x9c, 0xb6, + 0xa2, 0x9c, 0x71, 0xf6, 0x4e, 0x5d, 0x29, 0xc0, 0x00, 0x6f, 0x73, 0x13, 0x9d, 0x25, 0xe8, 0xb5, 0xa0, 0x74, 0xde, + 0xc0, 0xdd, 0x2c, 0x23, 0x23, 0x5c, 0x7c, 0x58, 0x79, 0x2c, 0xb8, 0x67, 0xbf, 0x90, 0x58, 0x5b, 0x3f, 0x30, 0x66, + 0xf3, 0x82, 0x05, 0x0a, 0x15, 0x28, 0xb0, 0x9c, 0x69, 0x4b, 0xd3, 0x6a, 0xc8, 0x0f, 0x8f, 0xd0, 0xda, 0xb4, 0x1a, + 0xf0, 0xc3, 0xa3, 0x3a, 0xca, 0x8e, 0x21, 0xcb, 0x89, 0x9f, 0x41, 0xbd, 0xae, 0x23, 0x93, 0x62, 0xb2, 0xfb, 0xf5, + 0xa5, 0xfe, 0xa8, 0x6e, 0xc0, 0xf5, 0x03, 0x10, 0xc0, 0x06, 0xe0, 0x10, 0xa8, 0x06, 0x4b, 0x23, 0x82, 0x45, 0x99, + 0x42, 0xfb, 0x1a, 0x7a, 0x6f, 0x34, 0xfc, 0x17, 0xb8, 0x8b, 0xc8, 0x95, 0xff, 0x09, 0x02, 0x7f, 0x45, 0x99, 0x56, + 0xa6, 0xf8, 0x9f, 0x68, 0xf5, 0x0a, 0xe5, 0xac, 0x69, 0xcd, 0x07, 0xd1, 0x9a, 0x08, 0xd5, 0x8c, 0x21, 0xf8, 0xb7, + 0xb2, 0x4c, 0x5b, 0xaa, 0x2a, 0xf5, 0xa1, 0xf1, 0x5a, 0x2b, 0x9c, 0xe5, 0xe3, 0xc8, 0x7b, 0x8d, 0xa1, 0x63, 0x13, + 0x67, 0x29, 0xa7, 0x52, 0x67, 0xaf, 0x0f, 0x65, 0xe4, 0x00, 0xa7, 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x72, 0x9a, 0x38, + 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x03, 0xc2, 0xa2, 0x6c, 0x28, 0x6d, 0x01, 0x26, 0x39, 0x21, 0x64, 0x8a, 0xa1, + 0x28, 0xf2, 0x91, 0xee, 0x87, 0xf5, 0x66, 0x75, 0x5f, 0xbc, 0xd5, 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0x8b, 0xf8, + 0x26, 0x13, 0x97, 0xe0, 0x31, 0x3c, 0x80, 0x2f, 0xc1, 0x4d, 0x2e, 0x65, 0xbf, 0x57, 0x61, 0x8e, 0x6b, 0x0b, 0x18, + 0x34, 0x58, 0x3d, 0x88, 0x0e, 0x97, 0xd2, 0x66, 0x57, 0x01, 0x62, 0x63, 0x0a, 0xb1, 0x2c, 0xd8, 0xda, 0xb2, 0x67, + 0x3f, 0xab, 0xa6, 0xa1, 0x75, 0xc2, 0xa9, 0xb8, 0xcc, 0x21, 0x8a, 0xca, 0x20, 0x06, 0x77, 0x24, 0x8f, 0xcf, 0x7b, + 0x2b, 0xc2, 0x0b, 0x02, 0x6e, 0x65, 0x89, 0x0c, 0x57, 0x74, 0x39, 0xba, 0xa5, 0xeb, 0xd1, 0x0d, 0x1d, 0xd3, 0xc9, + 0xdf, 0xc7, 0x68, 0x91, 0xad, 0x52, 0xef, 0xe8, 0x7a, 0xb4, 0xa4, 0xdf, 0x8e, 0xe9, 0xd1, 0xdf, 0xc6, 0x64, 0x9a, + 0xe3, 0x61, 0x42, 0x2f, 0xc0, 0xb1, 0x8b, 0xd4, 0xe8, 0xa9, 0xe9, 0x1b, 0x1c, 0x56, 0xa3, 0x7c, 0xc8, 0x47, 0x39, + 0xe5, 0xa3, 0x62, 0x58, 0x8d, 0xc0, 0xd3, 0xb1, 0x1a, 0xf2, 0x51, 0x45, 0xf9, 0xe8, 0x7c, 0x58, 0x8d, 0xce, 0x49, + 0xb3, 0xe9, 0x2f, 0x2b, 0x7e, 0x55, 0xb2, 0x35, 0x6c, 0x0b, 0x58, 0xbe, 0x6e, 0x95, 0xe5, 0xa9, 0xbf, 0xaa, 0xcd, + 0xc9, 0x6c, 0x39, 0x7b, 0x7b, 0xdd, 0xe5, 0xc4, 0xe2, 0x71, 0xdb, 0x74, 0xb8, 0xfa, 0x72, 0xa2, 0x4e, 0x7a, 0x85, + 0xfc, 0x30, 0x9e, 0x0a, 0x75, 0x0e, 0x81, 0x99, 0xc4, 0x2c, 0x8c, 0x19, 0x36, 0x53, 0xa7, 0x81, 0x02, 0x27, 0x1b, + 0x79, 0x2e, 0x8a, 0xd9, 0x28, 0xa7, 0xf0, 0x3e, 0x26, 0x24, 0x12, 0x70, 0x56, 0x9d, 0x54, 0xa3, 0x02, 0x62, 0x8e, + 0xb0, 0x10, 0x1f, 0xa1, 0x5f, 0xea, 0x23, 0x0f, 0x09, 0x3c, 0xc3, 0xbe, 0x16, 0x83, 0x18, 0x8e, 0x78, 0x5b, 0x59, + 0x35, 0x0b, 0x13, 0xa8, 0xac, 0x1a, 0x96, 0xa6, 0xb2, 0x82, 0x66, 0xa3, 0xca, 0xaf, 0xac, 0xc2, 0x31, 0x4a, 0x08, + 0x89, 0x4a, 0x5d, 0x19, 0xa8, 0x4f, 0x12, 0x16, 0x96, 0xba, 0xb2, 0x73, 0xf5, 0xd1, 0xb9, 0x5f, 0xd9, 0x39, 0xb8, + 0x90, 0x0e, 0x12, 0xff, 0x2a, 0xb5, 0x4c, 0xdb, 0xd7, 0xc1, 0xc6, 0xaa, 0xa2, 0x1b, 0x7e, 0x5b, 0x15, 0x71, 0x54, + 0x52, 0x17, 0x03, 0x1a, 0x17, 0x46, 0x24, 0xa9, 0x5e, 0xa3, 0xe0, 0x0f, 0x09, 0xa2, 0xd2, 0x18, 0xbc, 0x3a, 0x93, + 0xae, 0x95, 0x5a, 0x51, 0x31, 0x28, 0x07, 0x05, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, 0x19, 0x22, 0x2a, 0x43, 0x79, + 0x83, 0x5f, 0x30, 0x78, 0x32, 0xbb, 0x4c, 0xc3, 0x64, 0x74, 0x47, 0xe3, 0xd1, 0x12, 0xe1, 0x60, 0xd8, 0x45, 0xaa, + 0xf0, 0xd6, 0x57, 0x90, 0x7e, 0x4b, 0xe3, 0xd1, 0x0d, 0x4d, 0xad, 0xcd, 0xa9, 0x81, 0xba, 0xea, 0x8d, 0xe9, 0x6d, + 0x04, 0xaf, 0xef, 0xa2, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x97, 0x22, 0x4a, 0x29, 0x22, 0x10, 0xae, 0x11, 0x39, + 0x70, 0xa9, 0xd1, 0x06, 0xd7, 0x03, 0x28, 0x43, 0xc3, 0x05, 0x2e, 0x07, 0xf1, 0x68, 0xe9, 0x91, 0xa9, 0x54, 0x5f, + 0x64, 0x11, 0x3e, 0xda, 0xd9, 0x68, 0x29, 0x9e, 0x11, 0x0b, 0xe3, 0x0a, 0x86, 0x50, 0x17, 0x56, 0x9a, 0x82, 0xa4, + 0x0b, 0x1c, 0xd9, 0x0b, 0xe3, 0x2a, 0xdc, 0x80, 0x69, 0xd1, 0x1d, 0x98, 0x47, 0x81, 0xc2, 0xc1, 0x25, 0x48, 0x3f, + 0xa1, 0x6c, 0xe7, 0x28, 0x4d, 0x0e, 0x6f, 0x82, 0xd6, 0x3b, 0x13, 0x84, 0xb4, 0xab, 0x9b, 0x6c, 0x49, 0xdf, 0x60, + 0x7b, 0x87, 0x4e, 0x45, 0x05, 0xd5, 0xe7, 0x16, 0x4c, 0x96, 0x6c, 0x10, 0xb6, 0x84, 0xe9, 0x99, 0x5e, 0x03, 0xf6, + 0xf4, 0xe1, 0xd1, 0xce, 0x7c, 0x17, 0xb3, 0xd7, 0x87, 0x65, 0x34, 0x56, 0x16, 0xbc, 0xb9, 0x25, 0x76, 0x4b, 0x36, + 0x9e, 0x2e, 0x8f, 0xcb, 0xe9, 0x12, 0x89, 0x9d, 0xa1, 0x5b, 0x8c, 0xcf, 0x97, 0x0b, 0x9a, 0xe0, 0xd9, 0xc6, 0xaa, + 0xf9, 0xd2, 0xa0, 0xa5, 0xa4, 0x0c, 0xd7, 0xdb, 0x12, 0xfd, 0xff, 0xd5, 0xc5, 0x2f, 0x05, 0x78, 0x09, 0xc6, 0x02, + 0x40, 0xb8, 0x07, 0xd3, 0x82, 0xd4, 0x46, 0xd9, 0x48, 0xd3, 0x30, 0xc5, 0x45, 0x60, 0x52, 0xfa, 0xfd, 0x30, 0x67, + 0x29, 0xf1, 0xa0, 0x43, 0xed, 0x28, 0x5d, 0xa4, 0xbe, 0x10, 0x04, 0x78, 0x24, 0x75, 0x8e, 0x4d, 0xfe, 0x3e, 0x9e, + 0x05, 0x6a, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xe9, 0xb8, 0x9d, 0xae, 0x88, 0xd5, 0xee, 0x31, + 0x0b, 0x71, 0x92, 0x30, 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, + 0x04, 0x91, 0x5a, 0x6d, 0x19, 0x97, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, + 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0x57, 0xcd, 0x59, + 0xd7, 0x50, 0x9a, 0xb8, 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, + 0x82, 0x09, 0x3a, 0x9a, 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x5e, 0x26, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, + 0x0f, 0xaa, 0x93, 0x75, 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, + 0xc7, 0x03, 0x78, 0xcd, 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, + 0x6d, 0xc6, 0xa6, 0x4d, 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, + 0x29, 0x70, 0x32, 0x9b, 0xdb, 0x68, 0x49, 0xef, 0xa2, 0x94, 0xde, 0x44, 0x6b, 0xba, 0x8c, 0x2e, 0x8c, 0x89, 0x71, + 0x52, 0xc3, 0x39, 0x00, 0xad, 0x02, 0x48, 0x3c, 0xf5, 0xeb, 0x1d, 0x4f, 0xaa, 0x70, 0x49, 0x53, 0x70, 0x1b, 0xf6, + 0xed, 0x33, 0xcf, 0x7d, 0x89, 0xd4, 0x06, 0x31, 0xd6, 0xac, 0xa1, 0xe2, 0xc6, 0x5b, 0xf7, 0x91, 0xa8, 0x61, 0xe7, + 0xba, 0xd8, 0x44, 0xd5, 0x70, 0x32, 0x2d, 0x01, 0xb1, 0xb5, 0x1c, 0x0e, 0xdd, 0x11, 0xb2, 0x7b, 0xfc, 0xe8, 0x40, + 0xcf, 0x3d, 0x69, 0xb1, 0x6d, 0x5b, 0xfe, 0xc0, 0x10, 0xa6, 0xf4, 0xf3, 0x47, 0x3e, 0x20, 0x56, 0x5c, 0xc1, 0xd9, + 0x08, 0xd4, 0xd1, 0x0a, 0x9d, 0x7e, 0xaf, 0xc2, 0x42, 0x1f, 0xe0, 0x9b, 0xdb, 0x28, 0xa1, 0x77, 0x51, 0xee, 0x91, + 0xb5, 0x65, 0xcd, 0xe4, 0xf4, 0x2c, 0x0b, 0x79, 0xfb, 0x40, 0x2f, 0x17, 0x00, 0xa2, 0x35, 0x88, 0x7d, 0xa9, 0xeb, + 0x11, 0x38, 0x0d, 0xa1, 0x49, 0x68, 0x04, 0x57, 0x15, 0x84, 0x11, 0x70, 0x25, 0xe1, 0x6f, 0x30, 0x51, 0x81, 0x2f, + 0xc0, 0x45, 0x26, 0x4d, 0x73, 0x1e, 0xd4, 0xfe, 0x48, 0xbe, 0x2a, 0xda, 0xde, 0xae, 0x30, 0x9a, 0x60, 0xec, 0x89, + 0xf6, 0x79, 0xa4, 0x1c, 0xc5, 0x45, 0x12, 0x66, 0xa3, 0x5b, 0x75, 0x9e, 0xd3, 0x6c, 0x74, 0xa7, 0x7f, 0x55, 0x74, + 0x4c, 0x7f, 0xd5, 0x01, 0x6d, 0x94, 0xf4, 0xad, 0xe3, 0x6c, 0x40, 0xeb, 0xc5, 0xd2, 0xf8, 0x5f, 0xcb, 0xd1, 0x2d, + 0x95, 0xa3, 0x3b, 0xdf, 0x92, 0x6a, 0x32, 0x2d, 0x8e, 0x05, 0x1a, 0x52, 0x75, 0x7e, 0x5f, 0x00, 0x3f, 0x57, 0x1a, + 0xdf, 0x69, 0xf3, 0xbd, 0xd7, 0xfe, 0xb3, 0x4e, 0x9e, 0x40, 0xb1, 0x44, 0x05, 0xab, 0x46, 0x60, 0xc7, 0xbe, 0xce, + 0xe3, 0xc2, 0x8c, 0x52, 0x4c, 0xad, 0x49, 0x3f, 0x06, 0xae, 0x98, 0xf6, 0x0a, 0x70, 0xb5, 0x04, 0x27, 0x01, 0x88, + 0xa1, 0x09, 0x7b, 0x76, 0x0c, 0x51, 0xcf, 0x8d, 0x63, 0x94, 0x6c, 0xb8, 0x07, 0xc4, 0x5a, 0xe6, 0xad, 0x5c, 0x02, + 0x12, 0x78, 0xeb, 0x61, 0x52, 0x00, 0xc6, 0x60, 0xb9, 0x24, 0x3a, 0x8f, 0x87, 0x3e, 0xa1, 0x5e, 0x68, 0xd4, 0x09, + 0xd9, 0xd8, 0x12, 0x38, 0xfe, 0xb0, 0x3e, 0x04, 0x82, 0x57, 0x79, 0xae, 0xbf, 0xd2, 0xba, 0xfe, 0x52, 0xe9, 0xb9, + 0x63, 0xb9, 0xae, 0xdf, 0xb5, 0xa9, 0xd1, 0x0b, 0xb0, 0xf0, 0xdd, 0x28, 0xf3, 0x48, 0x6e, 0x11, 0x52, 0x15, 0x58, + 0xa9, 0x5b, 0x48, 0x30, 0xff, 0x4a, 0xce, 0x56, 0x65, 0xbe, 0x7a, 0xe4, 0x5e, 0x39, 0x9b, 0x9e, 0xfe, 0x86, 0x04, + 0xed, 0xae, 0x23, 0xcd, 0xe3, 0x2d, 0x3a, 0x7c, 0x76, 0xad, 0x25, 0xe6, 0x4e, 0xa2, 0xe2, 0xf9, 0x14, 0xb0, 0xd5, + 0xb3, 0xec, 0x4a, 0xf9, 0x58, 0xed, 0xe2, 0xf8, 0x99, 0xf3, 0x27, 0xa9, 0xc2, 0xb5, 0x68, 0x28, 0x41, 0xc0, 0x9b, + 0xc3, 0xd8, 0x15, 0xaa, 0x80, 0x86, 0xe6, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x34, 0x01, 0xd3, 0x52, 0x1e, 0x1d, 0xe0, + 0xd0, 0xe4, 0x51, 0xbb, 0x69, 0x58, 0x19, 0xba, 0xd6, 0xe8, 0x73, 0x5b, 0xe9, 0x8c, 0x37, 0x1b, 0x7e, 0x78, 0x34, + 0xa8, 0xf0, 0x27, 0x69, 0x8e, 0x46, 0x3b, 0x37, 0xdc, 0x69, 0x04, 0x66, 0xae, 0xe4, 0x8a, 0xec, 0x8e, 0x92, 0x97, + 0xdf, 0xd3, 0x0b, 0x0b, 0xe8, 0xcf, 0x7f, 0x2e, 0x26, 0x9c, 0xb4, 0xc4, 0x84, 0x68, 0xe9, 0xa0, 0x45, 0x07, 0x3b, + 0xca, 0x2b, 0xfb, 0x12, 0x2f, 0x9d, 0xe3, 0x7f, 0x5f, 0x8f, 0xb5, 0xab, 0x40, 0x68, 0x75, 0xf2, 0xb0, 0x3d, 0x59, + 0x20, 0x6a, 0x40, 0x35, 0xbb, 0x2a, 0x47, 0x99, 0x76, 0x56, 0x64, 0xd3, 0x90, 0xb9, 0xee, 0x66, 0x69, 0xd8, 0x4c, + 0x76, 0x2c, 0x2c, 0x33, 0x0c, 0xd6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x9a, 0xca, 0x33, 0x9f, 0xcd, + 0x32, 0xe2, 0x05, 0x3a, 0xe7, 0x54, 0x2c, 0x9a, 0xd2, 0xb1, 0x72, 0xbb, 0x2d, 0xd1, 0x58, 0xa2, 0x8c, 0x82, 0xa0, + 0xb6, 0x41, 0xd8, 0x75, 0xe9, 0x9e, 0xf4, 0x69, 0x17, 0x9f, 0x56, 0xa0, 0xef, 0xf1, 0x3e, 0x03, 0x89, 0xa9, 0x27, + 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x24, 0xd5, 0xf8, 0xfc, 0x4a, 0x76, 0xd6, 0xbc, 0x5b, 0x8d, 0x29, 0xfe, + 0x23, 0x75, 0xfb, 0xce, 0x65, 0x68, 0xa2, 0xbf, 0x96, 0x07, 0x2d, 0x85, 0x05, 0xc7, 0x6d, 0xe3, 0xaf, 0xdf, 0x66, + 0x0e, 0x31, 0x2c, 0x5d, 0x0e, 0x6f, 0x42, 0x87, 0xee, 0xae, 0xb2, 0x33, 0xd7, 0x47, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, + 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0xaf, 0x87, 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, + 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0x76, 0xf0, 0x73, 0x58, 0x3d, 0xe4, 0x83, 0x7f, 0xe1, 0x38, + 0xc3, 0xe8, 0x67, 0xca, 0xd0, 0xe7, 0x45, 0x21, 0xaf, 0x54, 0xa7, 0x7c, 0xa1, 0x5b, 0xcb, 0xd4, 0xfb, 0x75, 0xfc, + 0xba, 0x15, 0x20, 0xc6, 0xeb, 0x8a, 0x95, 0xe2, 0x0d, 0xad, 0x30, 0xae, 0x81, 0xdb, 0xe4, 0x50, 0x4b, 0xb5, 0x40, + 0xd4, 0xe5, 0x27, 0x0f, 0x79, 0x64, 0xd4, 0x99, 0xf0, 0xdd, 0x43, 0xee, 0x4b, 0xd7, 0x76, 0x9b, 0xf8, 0xb9, 0xa6, + 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0xee, 0x6f, 0x9e, 0xcd, 0xcf, 0x23, 0xf3, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, 0xb8, + 0xec, 0x18, 0xee, 0x7b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x2e, 0x70, 0x81, 0xbb, 0xc2, 0x80, + 0x21, 0xae, 0x69, 0xc9, 0x9d, 0xb6, 0xb2, 0xf5, 0x91, 0xb7, 0x51, 0x21, 0x58, 0xd7, 0x1d, 0x37, 0x49, 0x0e, 0xc1, + 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0x65, 0x20, 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x50, 0xab, 0x7b, + 0x0d, 0xaf, 0x72, 0x17, 0x79, 0xd6, 0x6f, 0xe6, 0xa5, 0x61, 0x5f, 0xf0, 0x5a, 0x0a, 0x0e, 0x8d, 0xed, 0x56, 0xb8, + 0xc5, 0xe2, 0x1d, 0xad, 0x56, 0xd6, 0xda, 0x6a, 0xaf, 0x95, 0x8a, 0xee, 0x5f, 0x73, 0x9c, 0x38, 0x4b, 0x61, 0xfb, + 0xe1, 0xfd, 0x05, 0xbb, 0x26, 0x80, 0x41, 0x8b, 0xc9, 0x02, 0x25, 0xa8, 0x64, 0xad, 0x6a, 0xb7, 0x53, 0xe2, 0x97, + 0xfb, 0x45, 0x97, 0xd9, 0xce, 0xe3, 0xd7, 0x4d, 0xda, 0x67, 0x3e, 0x47, 0x3f, 0xcc, 0xef, 0xac, 0x93, 0x92, 0x33, + 0x8c, 0x6b, 0xf9, 0xff, 0x55, 0xf4, 0xb2, 0xc8, 0xd2, 0x68, 0x63, 0x78, 0x30, 0x1b, 0x6a, 0xd3, 0x87, 0xc6, 0xa8, + 0xdc, 0xb2, 0x51, 0x44, 0xb4, 0xba, 0x05, 0xc1, 0x8c, 0xe2, 0xbe, 0x44, 0x9b, 0x57, 0xaa, 0x2c, 0xbc, 0xc3, 0x67, + 0x36, 0x7a, 0xc3, 0xf6, 0x84, 0x50, 0xbe, 0x7b, 0x5a, 0x98, 0x55, 0x4b, 0x45, 0x83, 0xed, 0x12, 0xde, 0xc5, 0xa8, + 0xd2, 0x4f, 0x98, 0x6c, 0x59, 0x30, 0xd5, 0xff, 0xef, 0x8b, 0x2c, 0x6d, 0x53, 0x74, 0x60, 0x3a, 0x9b, 0x3e, 0x9d, + 0x74, 0x83, 0xeb, 0x0c, 0x58, 0x44, 0xb0, 0xa5, 0xc2, 0xf1, 0x28, 0xb5, 0x1b, 0x24, 0x4c, 0x04, 0x37, 0x51, 0x2f, + 0x3b, 0x5a, 0xa6, 0x64, 0x55, 0xc0, 0xf3, 0x2b, 0x57, 0x99, 0x8e, 0xa3, 0xa1, 0xdf, 0x3f, 0x4f, 0x4d, 0xe8, 0x57, + 0xea, 0xa5, 0x2a, 0xce, 0xc3, 0xa8, 0x3a, 0x54, 0x18, 0xa3, 0x25, 0x4d, 0xe1, 0x18, 0xcc, 0x2e, 0xc2, 0x14, 0x2f, + 0x67, 0x9b, 0x84, 0x7d, 0xc1, 0x40, 0x2e, 0xb5, 0x41, 0xbd, 0xa6, 0x44, 0x6b, 0xd6, 0xde, 0xcc, 0x29, 0xa1, 0x17, + 0xac, 0xf4, 0xef, 0x42, 0x6b, 0x10, 0x28, 0xca, 0x66, 0xca, 0xf4, 0x4c, 0xb7, 0xf3, 0x82, 0x26, 0xb4, 0xa0, 0x2b, + 0x52, 0x83, 0xbe, 0xd7, 0xc9, 0xd9, 0xd1, 0xc9, 0xce, 0xcc, 0x7a, 0xcc, 0x8a, 0xe1, 0x64, 0x1a, 0xc3, 0x35, 0x2d, + 0x76, 0xd7, 0xb4, 0x65, 0xf3, 0xc6, 0xd5, 0xd8, 0x38, 0x0d, 0xda, 0x05, 0xd2, 0x36, 0xcd, 0xed, 0xa7, 0x1e, 0xb7, + 0xbf, 0xae, 0xd9, 0x72, 0xda, 0x5b, 0x6f, 0xb7, 0xbd, 0x14, 0x6c, 0x44, 0x3d, 0x3e, 0x7e, 0xad, 0xa4, 0xeb, 0x96, + 0xcb, 0x4f, 0xe1, 0xd9, 0xe3, 0xeb, 0x97, 0x3e, 0xb8, 0x1c, 0xad, 0xda, 0xdc, 0xfd, 0x72, 0x17, 0x59, 0xee, 0x8b, + 0x86, 0x96, 0xeb, 0x19, 0x6a, 0x92, 0x67, 0xa3, 0xbd, 0x43, 0x2d, 0x58, 0xce, 0xba, 0x09, 0x4f, 0x0c, 0x76, 0xec, + 0x55, 0x63, 0x73, 0x54, 0xe6, 0x92, 0xd5, 0x20, 0x81, 0x3e, 0xc9, 0x33, 0x4d, 0xff, 0x20, 0xc3, 0x7c, 0x74, 0x4b, + 0x73, 0xc0, 0x15, 0xab, 0xec, 0x25, 0x83, 0xd4, 0x55, 0x7b, 0x89, 0x2b, 0x5f, 0xe1, 0x90, 0x6c, 0xf0, 0xc9, 0x30, + 0x55, 0x9f, 0x5d, 0xf2, 0xe0, 0xff, 0x6d, 0xd5, 0x2a, 0x3d, 0x37, 0xc9, 0x0d, 0xc7, 0xbf, 0x4e, 0xda, 0x3e, 0x26, + 0x06, 0x09, 0x78, 0x6a, 0x17, 0x43, 0x35, 0xaa, 0x8a, 0x58, 0x94, 0xb9, 0x89, 0x39, 0xb6, 0xb7, 0x6b, 0xe8, 0xa0, + 0x0c, 0x7e, 0xdd, 0xf0, 0x89, 0xb9, 0x03, 0x5b, 0x81, 0x8e, 0x4e, 0x34, 0x97, 0x61, 0x66, 0x2e, 0xc3, 0xb4, 0x6b, + 0xab, 0xc0, 0xf0, 0xaa, 0xad, 0x92, 0x28, 0x57, 0xa3, 0x1e, 0x37, 0xb3, 0xd4, 0xec, 0x45, 0xde, 0xbd, 0x26, 0x3d, + 0x89, 0x3f, 0x5d, 0x7a, 0xf2, 0x7a, 0x18, 0x10, 0xf9, 0x25, 0x4b, 0xc3, 0x35, 0x0a, 0x82, 0x53, 0xab, 0x1d, 0x48, + 0xf3, 0x11, 0x20, 0xf3, 0xe3, 0x34, 0x7c, 0xa7, 0xc5, 0x39, 0x64, 0xa3, 0x34, 0x4e, 0x6c, 0x69, 0xd4, 0x43, 0x70, + 0xe7, 0xbd, 0xe2, 0x31, 0x04, 0x3e, 0xfc, 0x80, 0x9b, 0x41, 0x45, 0xb7, 0x25, 0x26, 0x4a, 0x9b, 0x47, 0xdd, 0xf2, + 0x51, 0x43, 0xa8, 0x64, 0x65, 0x78, 0x09, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x39, 0x81, 0xcc, 0xb0, 0x38, 0x3c, 0x1a, + 0xa6, 0x4a, 0x50, 0x34, 0x94, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xc5, 0x20, 0xd5, 0x95, 0xa9, 0x17, + 0x83, 0x54, 0xdf, 0xaa, 0x48, 0x7d, 0x96, 0x85, 0x15, 0xd5, 0x2d, 0xa2, 0x63, 0x3a, 0x94, 0x74, 0x69, 0x76, 0x6a, + 0xae, 0xa5, 0x17, 0x6a, 0x39, 0x3e, 0xd5, 0x69, 0x30, 0x8a, 0xef, 0x5d, 0x8a, 0x7e, 0xab, 0xf6, 0xb3, 0xff, 0x16, + 0x53, 0x6a, 0xc4, 0xa6, 0xf6, 0x16, 0x31, 0xac, 0xda, 0x0f, 0x59, 0x95, 0x83, 0x76, 0x17, 0x94, 0x8d, 0x95, 0x71, + 0x9e, 0x6f, 0x04, 0x33, 0x07, 0x6d, 0x63, 0xd5, 0xf4, 0xa1, 0x37, 0x62, 0xd4, 0xde, 0x98, 0x6a, 0xdc, 0x13, 0xf8, + 0x69, 0x83, 0xa6, 0x7b, 0x91, 0xe7, 0xa8, 0x47, 0xde, 0xfd, 0xcf, 0x1c, 0xd9, 0x99, 0x7c, 0x16, 0xcb, 0xa4, 0x6e, + 0x1f, 0x93, 0x60, 0xa1, 0xea, 0x18, 0x5d, 0xb8, 0x91, 0x29, 0xed, 0xe7, 0xce, 0xf4, 0x23, 0x9e, 0xc9, 0xfd, 0x76, + 0x68, 0xd4, 0x97, 0x86, 0xb5, 0xa4, 0x88, 0xfa, 0x82, 0xde, 0x9a, 0xea, 0xe8, 0x88, 0x7a, 0x1d, 0x81, 0xd5, 0x15, + 0x6d, 0x50, 0x03, 0x30, 0x19, 0xd7, 0xb6, 0x36, 0x9f, 0x83, 0xa9, 0xad, 0xaa, 0xe0, 0x09, 0xdd, 0x15, 0x4a, 0xf7, + 0x26, 0x75, 0xdd, 0x1a, 0x62, 0x0b, 0x18, 0x10, 0xb8, 0xd1, 0x53, 0xd3, 0x1f, 0x34, 0x51, 0x01, 0x68, 0xd0, 0xb8, + 0x9d, 0xe9, 0x1c, 0x89, 0x7e, 0xa7, 0x36, 0x6d, 0x33, 0xd5, 0xab, 0xca, 0x07, 0x50, 0xf1, 0x67, 0xe9, 0xec, 0xc2, + 0x8c, 0x58, 0x00, 0xe3, 0x1e, 0x38, 0x53, 0xbd, 0xd3, 0x0c, 0xac, 0x27, 0xf2, 0x3c, 0x2b, 0x79, 0x22, 0x05, 0xcc, + 0x88, 0xbc, 0xba, 0x92, 0x02, 0x86, 0x41, 0x0d, 0x00, 0x5a, 0x34, 0x97, 0xd1, 0x84, 0x3f, 0xaa, 0xe9, 0xbe, 0x3c, + 0xfc, 0x91, 0xce, 0xf5, 0xcd, 0xb8, 0x06, 0x43, 0xe5, 0x75, 0xc5, 0x77, 0x32, 0x7d, 0xc3, 0x1f, 0x7b, 0x99, 0x96, + 0x72, 0x5d, 0xec, 0x64, 0x79, 0xf4, 0x0d, 0x7f, 0xa2, 0xf3, 0x1c, 0x3d, 0xae, 0x69, 0x1a, 0xdf, 0xed, 0x64, 0xf9, + 0xfb, 0x37, 0x8f, 0x6d, 0x9e, 0x47, 0xe3, 0x9a, 0xde, 0x70, 0xfe, 0xd1, 0x65, 0x9a, 0xe8, 0xaa, 0xc6, 0x8f, 0xff, + 0x6e, 0x73, 0x3d, 0xae, 0xe9, 0x95, 0x14, 0xd5, 0x72, 0xa7, 0xa8, 0xa3, 0x6f, 0x8e, 0xfe, 0xce, 0xbf, 0x31, 0xdd, + 0x3b, 0xaa, 0xe9, 0x5f, 0xeb, 0xb8, 0xa8, 0x78, 0xb1, 0x53, 0xdc, 0xdf, 0xfe, 0xfe, 0xf7, 0xc7, 0x36, 0xe3, 0xe3, + 0x9a, 0xde, 0xf1, 0xb8, 0xa3, 0xed, 0x93, 0x27, 0x8f, 0xf9, 0xdf, 0xea, 0x9a, 0xfe, 0xc6, 0xfc, 0xe0, 0xa8, 0xa7, + 0x99, 0xa7, 0x87, 0xcf, 0x65, 0x13, 0x35, 0x60, 0xe8, 0xa1, 0x01, 0x2c, 0xa5, 0x55, 0xd3, 0xec, 0xf1, 0xca, 0x05, + 0xb7, 0xef, 0xb3, 0x38, 0x8d, 0x57, 0x70, 0x10, 0x6c, 0xd0, 0x38, 0xab, 0x00, 0x4e, 0x15, 0x78, 0xcf, 0xa8, 0xa4, + 0x59, 0x29, 0x7f, 0xe3, 0xfc, 0x23, 0x0c, 0x1a, 0x42, 0xda, 0xa8, 0xc8, 0x40, 0x6f, 0x56, 0x3a, 0xb2, 0x11, 0xfa, + 0x6f, 0x36, 0xe3, 0xe0, 0xf8, 0x30, 0x7a, 0xfd, 0x7e, 0x58, 0x30, 0x11, 0x16, 0x84, 0xd0, 0x3f, 0xc3, 0x02, 0x1c, + 0x4a, 0x0a, 0xe6, 0xe5, 0x33, 0xbe, 0xe7, 0xda, 0x28, 0x2c, 0x04, 0xd1, 0x5d, 0x64, 0x1f, 0x50, 0xf5, 0xe8, 0x3b, + 0x74, 0x43, 0xbc, 0xac, 0xb0, 0x60, 0x68, 0x55, 0x03, 0x33, 0x04, 0xc5, 0xbf, 0xe2, 0xa1, 0x04, 0x9f, 0x78, 0x80, + 0x8f, 0x1e, 0x93, 0x19, 0x57, 0xd7, 0xda, 0x37, 0x17, 0x61, 0x41, 0x03, 0xdd, 0x76, 0x08, 0x3a, 0x10, 0xf9, 0x2f, + 0xc0, 0x53, 0x60, 0xe0, 0xc3, 0xc2, 0xae, 0x3b, 0xf0, 0x7c, 0x7e, 0x33, 0xac, 0xa3, 0x0b, 0x3f, 0xfa, 0x9b, 0x75, + 0x61, 0xcf, 0xc8, 0x54, 0x1e, 0x97, 0xc3, 0xc9, 0x74, 0x30, 0x90, 0x2e, 0x8e, 0xdb, 0x69, 0x36, 0xff, 0x6d, 0x2e, + 0x17, 0x0b, 0xd4, 0x7d, 0xe3, 0xbc, 0xce, 0xf4, 0xdf, 0x48, 0x3b, 0x1f, 0xbc, 0x3a, 0xfd, 0xfd, 0xec, 0xfd, 0xe9, + 0x0b, 0x70, 0x3e, 0xf8, 0xf0, 0xfc, 0xfb, 0xe7, 0xef, 0x54, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, 0x93, 0xfa, 0x84, + 0x7c, 0x58, 0x91, 0xc3, 0x30, 0x7e, 0x58, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, 0x51, 0xdb, 0xdf, + 0xe5, 0x70, 0xe2, 0x81, 0x59, 0xdc, 0x36, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x79, 0xe2, 0xf5, 0x83, 0x93, + 0xa9, 0x74, 0x6c, 0x61, 0xc1, 0xa0, 0x6c, 0x68, 0xd3, 0x69, 0x36, 0x2f, 0x16, 0xb6, 0x5d, 0x6e, 0x81, 0x8c, 0xd2, + 0xec, 0xe2, 0x22, 0x54, 0xd0, 0xd5, 0x27, 0xa0, 0x01, 0x30, 0x8d, 0x2a, 0x5c, 0x8b, 0xf8, 0xcc, 0x2f, 0x3f, 0x1a, + 0x7b, 0xcd, 0xbb, 0x46, 0xdd, 0x93, 0x69, 0x56, 0xd5, 0x18, 0xd0, 0xc1, 0x84, 0x72, 0x37, 0xe8, 0x26, 0x98, 0x8c, + 0x6a, 0xcb, 0x6f, 0xf3, 0x6a, 0x61, 0x9a, 0xe3, 0x86, 0xa1, 0xf2, 0x4a, 0xbe, 0x90, 0x0d, 0x44, 0x06, 0x92, 0x61, + 0xd8, 0xa3, 0x31, 0x8a, 0xd4, 0x0f, 0x76, 0xbd, 0xe3, 0x37, 0xb9, 0x84, 0x68, 0x8a, 0x19, 0x48, 0xe7, 0x4f, 0x85, + 0x72, 0x2e, 0x97, 0x8c, 0xcf, 0xc5, 0xe2, 0x04, 0xdc, 0xce, 0xe7, 0x62, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, 0x95, + 0x80, 0xdd, 0x8b, 0x83, 0xf0, 0xed, 0x84, 0x36, 0xb0, 0x1b, 0x48, 0xb2, 0x41, 0x69, 0x57, 0x1a, 0xa2, 0xdc, 0x29, + 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xaa, 0x79, 0xd5, 0xf6, 0x64, 0x33, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x93, 0xd3, 0xf8, + 0x98, 0x15, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x0a, 0x42, 0x12, 0xc6, 0xe7, 0xf1, 0x82, 0x26, + 0x28, 0x25, 0x08, 0x21, 0xe4, 0xc7, 0x08, 0x6d, 0x73, 0x60, 0xc9, 0xdb, 0xed, 0xe7, 0xe9, 0xe7, 0x76, 0x0c, 0x97, + 0x51, 0x11, 0xba, 0x41, 0x67, 0x0d, 0xff, 0x46, 0x54, 0xd0, 0x18, 0x2b, 0x86, 0x20, 0xe0, 0x05, 0x46, 0x25, 0x2c, + 0x48, 0xcc, 0x2a, 0x88, 0x22, 0x50, 0xce, 0xe3, 0x05, 0x2b, 0x68, 0xd3, 0xe6, 0x34, 0xd6, 0x26, 0x41, 0x3d, 0x87, + 0xa5, 0x76, 0x20, 0x95, 0x0a, 0xb1, 0xc7, 0x67, 0x22, 0xba, 0xd1, 0x86, 0x06, 0x80, 0x02, 0xa5, 0xe4, 0xe2, 0x37, + 0x5f, 0xee, 0xe1, 0xa6, 0xa0, 0xff, 0xd9, 0xc6, 0x44, 0x3b, 0xcb, 0xd5, 0xa1, 0x37, 0x5f, 0xd0, 0x38, 0xcf, 0x21, + 0x14, 0x9b, 0x41, 0x20, 0x17, 0x59, 0x05, 0x11, 0x2d, 0xee, 0x02, 0x13, 0x12, 0x0e, 0xda, 0xf4, 0x0b, 0xa4, 0x36, + 0xc4, 0xe4, 0xca, 0x13, 0x03, 0xbb, 0xad, 0x12, 0x04, 0x1c, 0xe9, 0x79, 0xf6, 0xa9, 0x89, 0xb1, 0xa6, 0xa9, 0x99, + 0x89, 0xb7, 0xa1, 0x10, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xc5, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, 0x9d, 0x8b, + 0x33, 0xaf, 0x66, 0x1e, 0x91, 0x53, 0x4f, 0x73, 0x44, 0xbf, 0xe4, 0x61, 0x35, 0xd2, 0xc9, 0x18, 0x2b, 0x89, 0x83, + 0xde, 0x06, 0x0b, 0xe6, 0x84, 0xae, 0x78, 0x68, 0xf9, 0xf8, 0x17, 0xc8, 0x64, 0x94, 0xd4, 0x58, 0xd1, 0x95, 0x16, + 0x23, 0xce, 0x6b, 0x98, 0xa5, 0xc9, 0x8a, 0x2e, 0x16, 0x9a, 0x34, 0x0b, 0x65, 0x1a, 0xe0, 0x13, 0x68, 0x31, 0x72, + 0x0f, 0x35, 0x6d, 0x20, 0x34, 0xec, 0x0e, 0x01, 0x1f, 0xb9, 0x87, 0x0e, 0xff, 0x3f, 0xcf, 0x2e, 0x10, 0x69, 0xef, + 0xd2, 0x44, 0xc6, 0x23, 0x75, 0x03, 0x07, 0xc5, 0xf8, 0xd8, 0x37, 0x13, 0xbf, 0x70, 0x46, 0xef, 0x93, 0xca, 0x77, + 0xf8, 0x60, 0xf9, 0xe3, 0x4d, 0xcd, 0xac, 0x8c, 0x60, 0x3d, 0x6c, 0xb7, 0xb8, 0x20, 0xda, 0x2e, 0x80, 0xd4, 0x33, + 0x5e, 0x2d, 0x7c, 0xe3, 0xd5, 0x78, 0x8f, 0xf1, 0xaa, 0xb3, 0xc2, 0x0a, 0x73, 0xb2, 0x41, 0x7d, 0x96, 0x92, 0xe7, + 0xe7, 0x28, 0x13, 0x6c, 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, + 0x0e, 0x23, 0x81, 0xaa, 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, + 0x03, 0xa1, 0xa1, 0xb1, 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xed, 0xb6, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, + 0xac, 0x46, 0x13, 0xe0, 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, + 0x49, 0x66, 0x65, 0x34, 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, + 0xba, 0xcc, 0x92, 0xcc, 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, + 0x90, 0x1f, 0x40, 0x19, 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, + 0x64, 0x57, 0xbc, 0xac, 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0x6c, 0x9f, 0xdb, 0x1e, 0x15, 0xe6, 0xd5, 0xeb, 0xe7, + 0xdf, 0x9f, 0x36, 0x5e, 0xed, 0x22, 0x8e, 0x86, 0x60, 0x5b, 0x31, 0xc6, 0xe8, 0x2d, 0x3e, 0x0d, 0x26, 0xca, 0x35, + 0x02, 0xbd, 0x4b, 0x41, 0xbf, 0xfd, 0xa5, 0x9e, 0x80, 0x57, 0x5c, 0x2f, 0xbf, 0xe4, 0x23, 0x60, 0x89, 0x0a, 0x3d, + 0x2b, 0xcc, 0xcd, 0xca, 0x6c, 0x6f, 0xb7, 0x22, 0x33, 0xed, 0x4a, 0x23, 0x03, 0xf1, 0x6a, 0x3b, 0x8c, 0x85, 0x4b, + 0xd7, 0x74, 0x3b, 0xd8, 0xd5, 0xd2, 0xb3, 0x44, 0xde, 0x6e, 0x4b, 0xe8, 0x90, 0x1d, 0x70, 0xef, 0x65, 0x7c, 0x0b, + 0x2f, 0x4b, 0xaf, 0x9b, 0xcd, 0xe0, 0x09, 0x60, 0x26, 0x5c, 0x38, 0xcb, 0xe2, 0x98, 0x65, 0x49, 0xa8, 0x62, 0x73, + 0x35, 0x44, 0xde, 0x8a, 0xd0, 0x9a, 0xfd, 0x15, 0x8a, 0x11, 0xd8, 0x9d, 0xbc, 0xff, 0x98, 0xad, 0x66, 0x6b, 0x40, + 0xcd, 0xbf, 0xca, 0x04, 0xd0, 0x5c, 0xbb, 0x16, 0x6c, 0x53, 0x68, 0x73, 0x5d, 0x3f, 0x8d, 0x57, 0x71, 0x02, 0xaa, + 0x1b, 0xf0, 0x16, 0xb9, 0xd5, 0xa2, 0x2b, 0x83, 0x2e, 0x4a, 0xef, 0x29, 0xc7, 0x92, 0x42, 0x47, 0xdf, 0x7b, 0x42, + 0x9d, 0x7b, 0x06, 0x70, 0x49, 0xa3, 0xe6, 0xa9, 0x96, 0x32, 0x16, 0x00, 0x0b, 0x1d, 0xcc, 0x14, 0xd9, 0x8a, 0xae, + 0x0d, 0x26, 0x05, 0xbc, 0x35, 0xc0, 0x1f, 0x22, 0xab, 0xd4, 0x5d, 0xb1, 0x0c, 0x4b, 0xcf, 0xfe, 0xba, 0xdf, 0x8f, + 0x3d, 0xfb, 0xeb, 0x95, 0xa6, 0x75, 0x71, 0xbb, 0x01, 0xa4, 0xc6, 0x00, 0x22, 0xa7, 0x7a, 0x20, 0x4c, 0x44, 0xb1, + 0xa6, 0xef, 0xdf, 0xa9, 0xc9, 0xa2, 0x40, 0xe8, 0x77, 0xea, 0xf5, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd8, 0xc9, 0x40, + 0x9b, 0x7d, 0x40, 0x40, 0x54, 0x3f, 0x23, 0x9b, 0x2f, 0x94, 0x73, 0xb1, 0x0a, 0x1f, 0x3e, 0xa6, 0x10, 0x50, 0xb8, + 0xa3, 0x46, 0xe7, 0x6d, 0x88, 0x04, 0xca, 0x0a, 0x45, 0xac, 0x79, 0xb1, 0x96, 0x84, 0xcc, 0xc7, 0x0b, 0x14, 0x5c, + 0x39, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x32, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, 0x07, 0x72, + 0xdc, 0xc9, 0xd4, 0xd8, 0x53, 0x8d, 0x1a, 0x04, 0x93, 0x11, 0x04, 0x86, 0x1b, 0x7e, 0xc1, 0xc7, 0x47, 0x0b, 0x02, + 0x2a, 0x32, 0x6b, 0x16, 0x62, 0x5e, 0x1c, 0x3f, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x93, 0x29, 0x67, 0x70, 0x88, 0xd2, + 0x31, 0xc8, 0x68, 0x05, 0xfc, 0x16, 0xea, 0x77, 0xeb, 0xc4, 0xf7, 0xa1, 0x5f, 0x05, 0xbd, 0x88, 0x81, 0xe1, 0x88, + 0x26, 0x87, 0x21, 0x1f, 0x4c, 0x06, 0xa0, 0x2d, 0xf1, 0x76, 0x5f, 0x4b, 0x2b, 0x6e, 0x4e, 0x97, 0x4e, 0xf7, 0x4f, + 0xda, 0x04, 0x49, 0xa4, 0x92, 0x95, 0x8a, 0x18, 0x40, 0x28, 0x4b, 0xb5, 0x4d, 0xd6, 0x60, 0x59, 0x61, 0x96, 0x34, + 0x37, 0x28, 0x89, 0xbb, 0x9b, 0x81, 0x63, 0xd4, 0xac, 0xd3, 0xb0, 0x6c, 0xb9, 0x51, 0x03, 0x7c, 0x4e, 0xc2, 0x0a, + 0x7b, 0xc3, 0x99, 0x49, 0xef, 0x4c, 0x87, 0xab, 0x63, 0xce, 0x5e, 0x71, 0x04, 0xe3, 0x48, 0xf0, 0xc6, 0x43, 0x97, + 0x4c, 0x43, 0x45, 0xa6, 0x8c, 0x83, 0x69, 0x0f, 0x70, 0xef, 0x39, 0x18, 0x87, 0xb1, 0x41, 0x65, 0x49, 0x7d, 0xea, + 0xdd, 0x85, 0x40, 0x90, 0xd6, 0x7a, 0x99, 0xcf, 0xf0, 0xf4, 0x8c, 0x50, 0xf6, 0x87, 0x1c, 0xbe, 0x00, 0x3b, 0x0a, + 0x72, 0x32, 0xe1, 0x4f, 0x1e, 0xee, 0x06, 0xaa, 0xe2, 0x83, 0xe0, 0x20, 0x16, 0xe9, 0x41, 0x30, 0x10, 0xf0, 0xab, + 0xe0, 0x07, 0x95, 0x94, 0x07, 0x17, 0x71, 0x71, 0x10, 0xaf, 0xe2, 0xa2, 0x3a, 0xb8, 0xc9, 0xaa, 0xe5, 0x81, 0xe9, + 0x10, 0x40, 0xf3, 0x06, 0x83, 0x78, 0x10, 0x1c, 0x04, 0x83, 0xc2, 0x4c, 0xed, 0x8a, 0x95, 0x8d, 0xe3, 0xcc, 0x84, + 0x28, 0x0b, 0x9a, 0x01, 0xc2, 0x1a, 0xa7, 0x01, 0xf0, 0xa9, 0x6b, 0x96, 0xd2, 0x0b, 0x0c, 0x37, 0x20, 0xa6, 0x6b, + 0xe8, 0x03, 0xf0, 0xc8, 0x6b, 0x1a, 0xc3, 0x12, 0xb8, 0x18, 0x0c, 0xc8, 0x05, 0x44, 0x2e, 0x58, 0x53, 0x1b, 0xc4, + 0x21, 0x5c, 0x2b, 0x3b, 0xed, 0x5d, 0x60, 0xa6, 0xed, 0x16, 0x10, 0x95, 0x27, 0xa4, 0xdf, 0xb7, 0xdf, 0x50, 0xff, + 0x82, 0xbd, 0x04, 0xfb, 0xab, 0xa2, 0x0a, 0x73, 0xa9, 0x34, 0xdf, 0x97, 0xec, 0x64, 0xa0, 0x22, 0x0e, 0xef, 0x38, + 0x52, 0xb4, 0x51, 0xb9, 0x2c, 0x7b, 0xb2, 0x6c, 0xf8, 0x4a, 0x5c, 0x71, 0xe7, 0xc7, 0x55, 0x49, 0x99, 0x57, 0xd9, + 0x4a, 0xb1, 0x7f, 0x33, 0xae, 0xb9, 0x3f, 0xb0, 0xfe, 0x6c, 0xbe, 0x82, 0x6b, 0xab, 0xf7, 0xae, 0xc9, 0x35, 0x22, + 0x67, 0x09, 0xe5, 0x92, 0xda, 0xe6, 0xe1, 0x2d, 0x7d, 0x9f, 0x5f, 0x7d, 0x9b, 0xe9, 0x34, 0x3e, 0xab, 0xb0, 0x70, + 0x21, 0x5a, 0x11, 0x1c, 0x1a, 0x72, 0xd1, 0x3c, 0x02, 0xcc, 0xb5, 0xcf, 0x56, 0x50, 0x90, 0xfa, 0xac, 0x42, 0xef, + 0x56, 0x48, 0x78, 0xa1, 0xd9, 0xa5, 0xfb, 0x81, 0x94, 0x71, 0x7b, 0x68, 0x09, 0x93, 0x96, 0x17, 0xe1, 0xbd, 0xd7, + 0xdc, 0xe4, 0x9e, 0x85, 0x18, 0xbd, 0xc8, 0xb3, 0x13, 0x30, 0xd6, 0x5d, 0xb2, 0xb3, 0xe1, 0x89, 0xdf, 0xf0, 0x9c, + 0xb5, 0x68, 0x34, 0x5d, 0xb2, 0xa4, 0xdf, 0x8f, 0xc1, 0xc4, 0x3b, 0x65, 0x39, 0xfc, 0xca, 0x17, 0x74, 0xcd, 0x00, + 0x53, 0x8c, 0x5e, 0x40, 0x42, 0x8a, 0x48, 0x24, 0x6b, 0x75, 0x92, 0x7c, 0xa6, 0xbb, 0x00, 0x8c, 0x7e, 0x31, 0x4b, + 0xa3, 0xe5, 0x5e, 0x33, 0x0b, 0x24, 0xcf, 0xd0, 0x77, 0x1d, 0x6c, 0x6f, 0xec, 0x83, 0x94, 0xf3, 0x63, 0x31, 0x1d, + 0x0c, 0x38, 0xd1, 0x70, 0xe3, 0xa5, 0x12, 0xd7, 0xea, 0x16, 0x77, 0x0c, 0x63, 0xa9, 0x6f, 0x8b, 0x18, 0x1c, 0xb0, + 0x8b, 0x56, 0x76, 0xfb, 0x00, 0xfb, 0xca, 0xf1, 0x2e, 0x55, 0x76, 0xa7, 0xc7, 0x4c, 0x73, 0xd9, 0x6a, 0xd2, 0x49, + 0xc5, 0x7e, 0x22, 0xdf, 0xe4, 0x0e, 0xba, 0x5c, 0x8e, 0x35, 0x6f, 0x39, 0x00, 0x15, 0xfd, 0x48, 0x51, 0xdd, 0x2f, + 0x70, 0x84, 0xb9, 0xb7, 0x6e, 0xf3, 0xc9, 0xa1, 0x29, 0x70, 0x88, 0x3c, 0x69, 0xa3, 0x29, 0xa0, 0x7b, 0x17, 0x0f, + 0xbb, 0xfa, 0x6d, 0xe9, 0x2e, 0x50, 0xa2, 0x9d, 0x8a, 0x1b, 0x7e, 0x4c, 0xd4, 0xe9, 0x4c, 0x1b, 0x42, 0xff, 0xca, + 0x88, 0xfb, 0x4b, 0xe3, 0x2a, 0xde, 0xf4, 0x2e, 0x9f, 0x71, 0xa8, 0xb3, 0x1b, 0x42, 0x01, 0xb8, 0x6a, 0x4f, 0xa7, + 0x6e, 0x0c, 0xe9, 0x95, 0x12, 0xdd, 0x06, 0x07, 0xdb, 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, + 0x43, 0x39, 0x88, 0x1f, 0x16, 0x74, 0x19, 0x89, 0x87, 0xc5, 0x20, 0x7e, 0x28, 0xeb, 0x7a, 0xf7, 0x5c, 0xd9, 0xdf, + 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x09, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0xf0, 0x44, 0xb6, 0x96, 0x3e, + 0x74, 0x6e, 0xf7, 0xb1, 0x65, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0xd9, 0xe6, 0xd1, 0x87, 0x53, 0x20, + 0xa1, 0xdb, 0x6d, 0xb3, 0xae, 0xd6, 0x80, 0x62, 0x1a, 0x8e, 0xf9, 0x61, 0x31, 0xba, 0xf1, 0xdd, 0xf5, 0x0f, 0x8b, + 0xd1, 0x92, 0x0c, 0x27, 0x66, 0xf2, 0xe3, 0x93, 0xf1, 0x2c, 0x8e, 0x26, 0x75, 0xc7, 0x69, 0xa1, 0xf1, 0x4f, 0xbd, + 0x5b, 0x28, 0x02, 0xa7, 0x62, 0x04, 0x47, 0x4e, 0x85, 0x72, 0x52, 0x6a, 0x60, 0xf8, 0x1f, 0x54, 0x3b, 0xda, 0xb4, + 0x57, 0x71, 0x95, 0x2c, 0x33, 0x71, 0xa9, 0xc3, 0x87, 0xeb, 0xe8, 0xe2, 0x36, 0xa0, 0x9d, 0x77, 0x99, 0x76, 0xfc, + 0x3a, 0x69, 0xd0, 0x13, 0x57, 0x33, 0x03, 0x6e, 0xdd, 0x8f, 0xd0, 0x0c, 0x81, 0xd1, 0xf2, 0xfc, 0x2d, 0x62, 0x6e, + 0xff, 0xaa, 0x6c, 0x7e, 0x15, 0xed, 0x73, 0x64, 0xa4, 0x6c, 0x93, 0x91, 0x0a, 0x8c, 0x30, 0xa5, 0x48, 0xe2, 0x2a, + 0x84, 0x40, 0xf6, 0x5f, 0x52, 0x5c, 0x8b, 0xa5, 0xf7, 0x1a, 0x84, 0x09, 0xb6, 0x0b, 0xda, 0xaf, 0x6e, 0xe7, 0xb6, + 0xd2, 0x62, 0x8f, 0xd4, 0xf7, 0xb9, 0xb3, 0x5d, 0xd1, 0xe4, 0xef, 0xcb, 0x06, 0xb4, 0x01, 0x44, 0xb9, 0xaf, 0x8f, + 0x4a, 0xe0, 0x64, 0xc4, 0x0d, 0x25, 0x46, 0x2f, 0xe8, 0xea, 0x44, 0xee, 0xd9, 0xa9, 0x79, 0x53, 0x31, 0x53, 0x71, + 0xe5, 0x9b, 0x3d, 0xf3, 0x1f, 0x0c, 0x05, 0x2d, 0xc1, 0xc0, 0xdb, 0x9c, 0xf1, 0xe8, 0x40, 0x77, 0x63, 0x74, 0x5a, + 0xb0, 0x59, 0x50, 0x97, 0x75, 0xd3, 0xc6, 0x83, 0x46, 0x1c, 0x14, 0xc5, 0xaa, 0x50, 0x23, 0xe1, 0x89, 0x40, 0xc0, + 0x94, 0x5d, 0xf1, 0xc8, 0x08, 0x6a, 0x7a, 0x13, 0x0a, 0x1b, 0x0a, 0xfe, 0x2a, 0x51, 0x4d, 0x6f, 0x42, 0x9b, 0x4c, + 0x9c, 0x66, 0x10, 0xc1, 0x8c, 0xd8, 0xee, 0xb7, 0x80, 0x36, 0xb7, 0x66, 0xb4, 0xa9, 0x6b, 0xab, 0xad, 0x42, 0x2e, + 0x29, 0x52, 0x96, 0xff, 0x4e, 0x4d, 0x05, 0x25, 0xb5, 0x5c, 0xf4, 0x26, 0x4d, 0x17, 0x3d, 0x9e, 0x19, 0x49, 0xa0, + 0x72, 0xcb, 0x1d, 0xa3, 0x3f, 0x84, 0x05, 0x1e, 0x31, 0x71, 0x62, 0xc1, 0xdc, 0xea, 0x84, 0x65, 0x73, 0xb1, 0x18, + 0xad, 0x24, 0x84, 0x0d, 0x3e, 0x66, 0xd9, 0xbc, 0xd4, 0x0f, 0xa1, 0x2f, 0x2c, 0x7d, 0x03, 0x76, 0xb1, 0xc1, 0x4a, + 0x96, 0x01, 0xf8, 0x5e, 0xd0, 0xcd, 0x4a, 0x96, 0x91, 0x54, 0xdd, 0x8f, 0x6b, 0x2c, 0x41, 0xa5, 0x15, 0x2a, 0x2d, + 0xa9, 0xb1, 0x20, 0xf0, 0x55, 0xd5, 0xe5, 0x43, 0xb2, 0xab, 0x40, 0x3d, 0x75, 0xd4, 0x80, 0x53, 0xa0, 0xaa, 0xc0, + 0x82, 0x24, 0xa8, 0x0c, 0x5d, 0x15, 0x98, 0x56, 0x60, 0x9a, 0xa9, 0xc2, 0x45, 0x99, 0x1d, 0x4a, 0xb3, 0x5e, 0xf2, + 0x59, 0x3c, 0x08, 0x93, 0x61, 0x4c, 0x1e, 0x22, 0xd4, 0xfe, 0x61, 0x1e, 0xc5, 0x5a, 0x2e, 0x79, 0xe9, 0xfc, 0xe2, + 0x6f, 0x3e, 0x63, 0xaf, 0x7b, 0x86, 0xc1, 0x02, 0x9c, 0xa5, 0xed, 0x55, 0x26, 0xde, 0xca, 0x56, 0x70, 0x1c, 0xcc, + 0xa2, 0x1c, 0x56, 0x3d, 0x39, 0xa2, 0xb9, 0xc8, 0xb5, 0x77, 0x11, 0x22, 0x07, 0x99, 0x3d, 0x06, 0xd8, 0x8d, 0xf0, + 0x75, 0x68, 0x6d, 0x6e, 0x75, 0x85, 0xf8, 0x1b, 0x25, 0x12, 0x3f, 0x49, 0xf9, 0x71, 0xbd, 0x52, 0xb9, 0x2a, 0x83, + 0xc7, 0xaa, 0x9b, 0xc1, 0x33, 0xed, 0x7b, 0xac, 0xfd, 0x5b, 0xdb, 0xcd, 0xf1, 0xde, 0x83, 0x07, 0xad, 0xff, 0xad, + 0x27, 0x21, 0xb4, 0x57, 0x4e, 0x52, 0x77, 0xd4, 0xe8, 0x99, 0xc9, 0x1a, 0x51, 0x09, 0x53, 0xbb, 0x53, 0x39, 0x06, + 0x6a, 0x3a, 0x80, 0x6b, 0x89, 0x9a, 0xa0, 0x27, 0x05, 0x1b, 0xc3, 0x11, 0x67, 0x71, 0xd0, 0x8e, 0x63, 0x14, 0x2f, + 0xe7, 0x4a, 0xbc, 0x9c, 0x9f, 0x30, 0x0e, 0xd0, 0x5a, 0x80, 0x54, 0xaf, 0x61, 0x3f, 0x73, 0x05, 0x0b, 0x6c, 0xee, + 0x7c, 0x47, 0x16, 0xc8, 0x10, 0x27, 0x9b, 0xe3, 0x64, 0x8f, 0x6b, 0x3d, 0xf7, 0x02, 0x1f, 0x27, 0xf5, 0xc2, 0xab, + 0xab, 0x6c, 0xd7, 0xb5, 0x64, 0xe5, 0xbc, 0x18, 0x4c, 0x20, 0x28, 0x4b, 0x39, 0x2f, 0x86, 0x93, 0x05, 0xcd, 0xe1, + 0xc7, 0xa2, 0x81, 0x0e, 0xb1, 0x1c, 0x24, 0x70, 0xe9, 0xec, 0x31, 0xe0, 0x0d, 0xa5, 0x16, 0x77, 0x63, 0x1d, 0x39, + 0xd6, 0x51, 0x1c, 0x86, 0x31, 0xe0, 0xca, 0x3a, 0x81, 0xf7, 0xfe, 0xeb, 0x63, 0x13, 0x90, 0x55, 0xbb, 0xc2, 0xab, + 0x51, 0xee, 0xba, 0xd2, 0xe8, 0x4b, 0x4a, 0x4f, 0x78, 0xc1, 0x53, 0xc9, 0x76, 0xdb, 0x33, 0x70, 0xb6, 0xc4, 0x43, + 0xe2, 0x1d, 0x23, 0x7a, 0x31, 0x6d, 0x64, 0xe6, 0x04, 0xce, 0x6c, 0x77, 0xd9, 0xc6, 0xfc, 0xd8, 0x01, 0x0e, 0x16, + 0x41, 0x48, 0xdc, 0x10, 0x86, 0x89, 0x9d, 0x94, 0x43, 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, + 0xd2, 0xda, 0x36, 0x71, 0x0f, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, + 0x0c, 0x40, 0xd3, 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, + 0xfe, 0x9d, 0xe6, 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, + 0x13, 0xb7, 0xdb, 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, + 0x18, 0x30, 0x97, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, + 0xcc, 0x03, 0x99, 0x02, 0xe2, 0xf9, 0xc7, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd5, 0xf1, 0x8d, 0xe8, 0x7b, + 0xfb, 0xe2, 0x92, 0x57, 0x6f, 0x6e, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, + 0x1d, 0x14, 0x59, 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xaf, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, + 0x09, 0x53, 0x80, 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, + 0x31, 0x80, 0xc2, 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa6, 0x3a, 0x03, 0x2d, 0xeb, + 0x69, 0x01, 0xa2, 0x3a, 0x88, 0xb6, 0x0a, 0x84, 0x39, 0xa5, 0x65, 0x46, 0x97, 0x82, 0xa6, 0x82, 0x26, 0x19, 0xbd, + 0xe0, 0x4a, 0x54, 0x7c, 0x21, 0x98, 0xa2, 0xed, 0x86, 0xb0, 0xff, 0xd8, 0xa0, 0xeb, 0xad, 0x58, 0x6b, 0x68, 0x77, + 0x82, 0x8c, 0xd0, 0x7c, 0xa1, 0x83, 0x90, 0xa1, 0x72, 0x12, 0xf1, 0xe1, 0x35, 0x5e, 0x81, 0x4b, 0xa6, 0xd9, 0x68, + 0x19, 0x97, 0x61, 0x60, 0xbf, 0x0a, 0x2c, 0x26, 0x07, 0x26, 0xbd, 0x5f, 0x9f, 0x3f, 0x95, 0x57, 0x2b, 0x29, 0xb8, + 0xa8, 0x14, 0x44, 0xbf, 0xc1, 0x7d, 0x37, 0x71, 0xd5, 0x59, 0xb3, 0x56, 0x7a, 0xdf, 0xb7, 0x3e, 0x6b, 0xe3, 0xbe, + 0x30, 0x38, 0x06, 0x3b, 0x1f, 0x11, 0x03, 0x69, 0x50, 0xe9, 0x16, 0x87, 0x26, 0x40, 0x97, 0x0e, 0x29, 0x64, 0xc9, + 0x54, 0xa6, 0x4a, 0x50, 0xf1, 0x8d, 0xdf, 0x49, 0x59, 0x8d, 0xfe, 0x5a, 0xf3, 0xe2, 0xee, 0x3d, 0xcf, 0x39, 0x8e, + 0x51, 0x90, 0xc4, 0xe2, 0x3a, 0x2e, 0x03, 0xe2, 0x5b, 0x5e, 0x05, 0x47, 0xa9, 0x09, 0x1b, 0xb3, 0x53, 0x35, 0x6a, + 0xbd, 0x0a, 0xf4, 0x95, 0x51, 0xbe, 0x31, 0x18, 0x9a, 0x88, 0x2a, 0xe8, 0x7b, 0xad, 0xee, 0x69, 0x75, 0xc3, 0x02, + 0xe2, 0xcf, 0x95, 0x5e, 0xa8, 0xf5, 0xba, 0x19, 0x73, 0xc3, 0x44, 0x08, 0x1a, 0x3d, 0xaa, 0x17, 0x0e, 0x3f, 0x7f, + 0xa3, 0x2c, 0x89, 0xe0, 0xc5, 0x26, 0x5d, 0x17, 0x26, 0x96, 0x06, 0xd5, 0x01, 0x73, 0xa3, 0x4d, 0xce, 0x2f, 0x41, + 0xf4, 0xe7, 0xac, 0x88, 0x26, 0x75, 0x4d, 0x15, 0x82, 0x61, 0xb4, 0xb9, 0x6d, 0xa4, 0xd3, 0x3b, 0xf0, 0x72, 0x33, + 0xd6, 0x48, 0xda, 0xd3, 0xb1, 0xa6, 0x05, 0x2f, 0x57, 0x52, 0x94, 0x10, 0xdd, 0xb9, 0x37, 0xa6, 0x57, 0x71, 0x26, + 0xaa, 0x38, 0x13, 0xa7, 0xe5, 0x8a, 0x27, 0xd5, 0x3b, 0xa8, 0x50, 0x1b, 0xe3, 0x60, 0xeb, 0xd5, 0xa8, 0xab, 0x70, + 0xc8, 0x2f, 0x2f, 0x9e, 0xdf, 0xae, 0x62, 0x91, 0xc2, 0xa8, 0xd7, 0xfb, 0x5e, 0x34, 0xa7, 0x63, 0x15, 0x17, 0x5c, + 0x98, 0xa8, 0xc5, 0xb4, 0x62, 0x01, 0xd7, 0x19, 0x03, 0xca, 0x55, 0xec, 0xce, 0x4c, 0xc5, 0x32, 0x8c, 0xcb, 0xf2, + 0xa7, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x06, 0x4e, 0x8b, 0x99, 0x01, 0x01, 0xb9, 0xcb, 0x0d, 0x2e, 0x02, 0x0b, 0x8e, + 0x1e, 0x8f, 0x57, 0xb7, 0x01, 0xf5, 0xde, 0x48, 0x75, 0x3d, 0x64, 0xc1, 0x78, 0xf4, 0x24, 0x70, 0xc8, 0x21, 0xfe, + 0x47, 0x8f, 0x8f, 0xf6, 0x7f, 0x33, 0x09, 0x48, 0x3d, 0x05, 0x55, 0x85, 0x51, 0x88, 0xc2, 0xb4, 0xbf, 0x5a, 0xab, + 0x5b, 0xee, 0x9b, 0xf3, 0x92, 0x17, 0xd7, 0x10, 0xad, 0x9d, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, + 0xab, 0xaa, 0xc8, 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, + 0x58, 0xd4, 0xa4, 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, + 0x4a, 0x8c, 0x35, 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, + 0xb7, 0x53, 0xd5, 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xea, 0x60, + 0x78, 0x00, 0xc9, 0x64, 0xfa, 0x69, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, + 0x3d, 0xef, 0xff, 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, + 0xcf, 0x50, 0xad, 0xef, 0xd3, 0xa2, 0x88, 0xef, 0x6a, 0x88, 0x6c, 0x2a, 0x9c, 0x77, 0x0d, 0xf5, 0xc8, 0x02, 0x3d, + 0x22, 0xd3, 0x0b, 0xc1, 0xe0, 0x9b, 0x77, 0x55, 0x18, 0xf0, 0x72, 0x35, 0xe4, 0xa2, 0xca, 0xaa, 0xbb, 0x21, 0xe6, + 0x09, 0xf0, 0x53, 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x89, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, + 0xe2, 0x63, 0xaa, 0xba, 0x31, 0xf9, 0x86, 0xea, 0xbe, 0x4d, 0xbe, 0x01, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, + 0x8c, 0xc6, 0xf4, 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf1, 0x76, 0xf6, 0xd1, + 0x68, 0xf4, 0xa6, 0xa0, 0xa3, 0xd1, 0xe8, 0x63, 0x56, 0x13, 0xba, 0x12, 0x1d, 0xef, 0xdf, 0x71, 0x7a, 0x2e, 0xd3, + 0xbb, 0x28, 0x08, 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0xaf, 0xd2, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, + 0x6d, 0x44, 0x48, 0x26, 0x42, 0x1f, 0xec, 0xf4, 0x6c, 0x34, 0x1a, 0xbd, 0x4a, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x14, + 0xcd, 0x29, 0x9c, 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, + 0x8b, 0x87, 0x87, 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, + 0xb1, 0xf5, 0x2d, 0xfa, 0xea, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x14, 0x80, + 0x17, 0x67, 0x23, 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, + 0xc7, 0xd3, 0xf2, 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x15, 0x44, 0x25, 0x3b, 0x7a, 0x32, + 0x55, 0x70, 0xc7, 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x76, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, + 0x72, 0x19, 0x83, 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, + 0x4c, 0x1e, 0x96, 0x54, 0x7e, 0x35, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0x7a, 0xf9, + 0xa4, 0xec, 0x70, 0xfe, 0xbf, 0x4b, 0xba, 0x18, 0x1c, 0xba, 0xa1, 0x79, 0xa0, 0xdd, 0x79, 0x2b, 0x64, 0x1c, 0xab, + 0xf0, 0x4d, 0x4a, 0xac, 0x31, 0x2e, 0x67, 0x27, 0x1b, 0xd3, 0x9d, 0x51, 0x55, 0x64, 0x57, 0x21, 0xd1, 0xbd, 0x72, + 0x20, 0xa1, 0x41, 0x94, 0x8d, 0x70, 0xfd, 0x80, 0xf5, 0x8c, 0xd7, 0xc9, 0x6b, 0x5e, 0x54, 0x59, 0xa2, 0xde, 0x5f, + 0x37, 0xde, 0xd7, 0xb5, 0x09, 0xa8, 0xfa, 0xb6, 0x60, 0x30, 0xcf, 0x0f, 0x0a, 0x00, 0x31, 0x45, 0x1a, 0xe0, 0x13, + 0xcc, 0x20, 0xa8, 0x5d, 0x33, 0xaf, 0x1a, 0xc1, 0x37, 0xe0, 0xab, 0xb7, 0x05, 0x60, 0x90, 0x84, 0x20, 0x45, 0x86, + 0xd0, 0x40, 0x20, 0xd0, 0x30, 0xe4, 0x02, 0x83, 0x9f, 0x78, 0x71, 0x24, 0x95, 0x53, 0x22, 0x0f, 0x03, 0xfc, 0x11, + 0x50, 0x15, 0x80, 0xc4, 0x78, 0x1c, 0xc2, 0x0b, 0xf5, 0xcb, 0xbd, 0x51, 0x7b, 0x84, 0x3d, 0x4d, 0x43, 0x08, 0x36, + 0x84, 0x0f, 0x01, 0x2c, 0x29, 0x42, 0x1f, 0x20, 0x97, 0x11, 0x06, 0x17, 0x79, 0xb6, 0xd2, 0x49, 0xd5, 0xa8, 0xa3, + 0xf9, 0x50, 0x6a, 0x47, 0x72, 0x40, 0xbd, 0xf4, 0x18, 0xd3, 0x0b, 0x95, 0xae, 0x8a, 0x72, 0x46, 0x39, 0x6f, 0xf5, + 0xc4, 0xb8, 0xb0, 0x85, 0x1c, 0x22, 0xe1, 0xbc, 0x2d, 0x54, 0x28, 0x1c, 0xbe, 0x00, 0x30, 0x30, 0x90, 0x76, 0xec, + 0xc6, 0xbb, 0x51, 0xd9, 0xcf, 0x38, 0x3b, 0xfc, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, + 0xfb, 0x93, 0x3c, 0x7c, 0x70, 0x48, 0x5f, 0x70, 0xcb, 0xa5, 0xc1, 0xc2, 0x6f, 0x04, 0xfb, 0x51, 0x2b, 0x21, 0x88, + 0x02, 0xbc, 0x61, 0xb9, 0xd5, 0x38, 0x01, 0xc0, 0xc3, 0xe0, 0xbf, 0x02, 0x34, 0x9a, 0x72, 0x17, 0x2f, 0xd0, 0x97, + 0xa8, 0xdf, 0x27, 0x8f, 0x1a, 0x06, 0x83, 0x20, 0xae, 0x51, 0x31, 0x61, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x90, 0x6d, + 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0x84, 0xe1, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xb1, 0xad, 0xe4, 0x2a, 0x44, + 0xac, 0x40, 0xfd, 0x2b, 0x67, 0x10, 0x7b, 0xf3, 0x3a, 0x03, 0x9f, 0x0e, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x14, 0xdc, + 0xf9, 0x0a, 0x7e, 0x91, 0x81, 0x9b, 0xb7, 0x88, 0x51, 0xe0, 0x60, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, 0xd7, + 0xb8, 0xd3, 0x79, 0x6d, 0xd4, 0x10, 0xa8, 0x23, 0x07, 0xf5, 0x83, 0x1e, 0x82, 0xa1, 0x1a, 0x82, 0xa2, 0xa3, 0x2d, + 0xae, 0x5e, 0x5b, 0x4f, 0x61, 0x7a, 0xab, 0xea, 0x2b, 0x46, 0x7f, 0xca, 0x4c, 0x60, 0x21, 0xed, 0x9a, 0x63, 0x5d, + 0x73, 0x8c, 0xb4, 0xa7, 0xdf, 0x17, 0x0d, 0xf2, 0xd3, 0x59, 0x78, 0x10, 0xa8, 0x52, 0xe5, 0x4e, 0x59, 0x94, 0xdb, + 0xd2, 0xbc, 0x31, 0xac, 0x69, 0x9e, 0xd9, 0x38, 0x37, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xc1, 0x13, 0x4b, 0xc5, 0xda, + 0x20, 0xdc, 0x91, 0x49, 0x18, 0x5d, 0x81, 0xec, 0x32, 0x3c, 0xe3, 0x04, 0xf9, 0x54, 0x60, 0x1f, 0x54, 0xb5, 0x5e, + 0x4e, 0x78, 0x6c, 0xe4, 0xcb, 0x46, 0xd0, 0x20, 0x2f, 0x29, 0xea, 0x4d, 0xdc, 0x8e, 0x3d, 0x6d, 0x21, 0x57, 0x6e, + 0xea, 0x69, 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, + 0xcc, 0x70, 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, + 0x13, 0xf9, 0xea, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, + 0xf5, 0xa2, 0x84, 0x0a, 0xd8, 0x6e, 0x2b, 0x41, 0xf0, 0xef, 0xc7, 0x6c, 0x86, 0x7f, 0xb3, 0x7e, 0xbf, 0x17, 0xe2, + 0x2f, 0x8e, 0xc1, 0x8c, 0xe6, 0x62, 0xc1, 0x3e, 0x82, 0x8c, 0x89, 0x44, 0x98, 0xaa, 0x8c, 0x01, 0x59, 0x05, 0x16, + 0x81, 0xe6, 0x03, 0x95, 0x0b, 0x33, 0xd9, 0xcb, 0x9c, 0x6b, 0xc8, 0xf3, 0xd6, 0x38, 0x65, 0xa3, 0x2c, 0x51, 0xae, + 0x1c, 0xd9, 0x28, 0xce, 0xb3, 0xb8, 0xe4, 0xe5, 0x76, 0xab, 0x0f, 0xc7, 0xa4, 0xe0, 0xc0, 0xae, 0x2b, 0x2a, 0x55, + 0xb2, 0x8e, 0x54, 0x0f, 0xbc, 0x34, 0x2c, 0x70, 0x9f, 0xf2, 0x79, 0x61, 0x68, 0xc4, 0x01, 0x08, 0x33, 0x98, 0xba, + 0xa5, 0xf7, 0xc2, 0x02, 0x9a, 0x57, 0x12, 0xb2, 0xc1, 0x54, 0xcf, 0xc2, 0x37, 0x66, 0x62, 0x5e, 0x2c, 0x20, 0xac, + 0x4e, 0xb1, 0xd0, 0xcc, 0x26, 0x4d, 0x58, 0x0c, 0xb0, 0x79, 0x31, 0x99, 0x42, 0x7c, 0x77, 0x55, 0x4e, 0xbc, 0x30, + 0xf7, 0xed, 0xc4, 0x21, 0x87, 0xc0, 0xab, 0xda, 0xa0, 0xab, 0xd9, 0x86, 0xa3, 0x8e, 0x94, 0x13, 0x93, 0xdf, 0x4f, + 0x15, 0x84, 0xb8, 0x13, 0x47, 0xc2, 0xe5, 0xcd, 0x76, 0xe1, 0x65, 0x07, 0x82, 0x8e, 0x1a, 0x9c, 0xf2, 0x33, 0x83, + 0xa3, 0x31, 0x49, 0x37, 0xde, 0x09, 0x52, 0x84, 0x31, 0xd9, 0x48, 0x76, 0x2e, 0x43, 0x31, 0x8f, 0x17, 0xa0, 0xbc, + 0x8c, 0x17, 0x60, 0x69, 0x64, 0x0c, 0x52, 0x41, 0x7e, 0xc7, 0xbd, 0x50, 0x58, 0x14, 0x57, 0x88, 0xf4, 0xac, 0x7e, + 0x4f, 0x8b, 0x76, 0x28, 0x10, 0x14, 0x77, 0x28, 0xf3, 0xe4, 0xac, 0xc7, 0x02, 0x89, 0x0d, 0x01, 0xe3, 0x2b, 0x9d, + 0xa6, 0x5a, 0xeb, 0xde, 0xd8, 0xe8, 0x55, 0xd3, 0x6c, 0x24, 0x64, 0x75, 0x76, 0x01, 0x22, 0x25, 0x1f, 0x1d, 0x1f, + 0xf9, 0x45, 0xdc, 0x59, 0xe6, 0xad, 0x6d, 0x51, 0xc9, 0x4e, 0x36, 0x00, 0x5a, 0xa8, 0xa3, 0x67, 0x29, 0xb9, 0x4d, + 0x49, 0x6a, 0xb7, 0x29, 0x60, 0x25, 0xf9, 0x0b, 0x18, 0x82, 0xaf, 0x1d, 0x08, 0xa7, 0x63, 0x85, 0x78, 0x4d, 0x53, + 0x44, 0x9a, 0x0c, 0x4b, 0x8a, 0x63, 0x5b, 0x22, 0x0a, 0xaa, 0x2d, 0xcb, 0x0e, 0x86, 0x89, 0x12, 0xfc, 0x2c, 0xf5, + 0x28, 0x51, 0x10, 0x50, 0x3d, 0xe4, 0x20, 0xc1, 0xb6, 0x0d, 0x84, 0x07, 0xe4, 0x11, 0xbd, 0xb1, 0xfe, 0x3e, 0xeb, + 0x3c, 0xbb, 0xd0, 0x3c, 0x97, 0xeb, 0x5d, 0x61, 0xc6, 0x08, 0x4f, 0x32, 0x13, 0x36, 0xc0, 0x3b, 0xcf, 0x8c, 0xda, + 0xa6, 0xe7, 0xe1, 0xb5, 0x3d, 0xc7, 0x08, 0x7d, 0x7b, 0x06, 0xdd, 0x04, 0xf3, 0xea, 0xb0, 0x59, 0xaf, 0x14, 0xa4, + 0x86, 0xa9, 0x45, 0x13, 0xb3, 0x9e, 0x35, 0x28, 0xdf, 0x6e, 0x7b, 0x7a, 0xae, 0xf6, 0xcf, 0xdd, 0x76, 0xdb, 0xc3, + 0x6e, 0x3d, 0x4b, 0xbb, 0xad, 0xe2, 0x2b, 0xf5, 0x41, 0x7b, 0xfc, 0xb9, 0x1b, 0x7f, 0x6e, 0x90, 0x4d, 0x4a, 0x47, + 0x33, 0x6d, 0x7d, 0x10, 0x1e, 0x38, 0xbd, 0x6b, 0x34, 0xe9, 0xfb, 0x2c, 0x94, 0x74, 0x25, 0x1a, 0xd5, 0x99, 0x10, + 0x66, 0xac, 0xba, 0x7f, 0xfd, 0xdf, 0xbf, 0x0a, 0xf0, 0x88, 0x53, 0x3b, 0x7b, 0x6f, 0x83, 0x8a, 0x46, 0x5b, 0x38, + 0x52, 0x84, 0x1e, 0x90, 0x84, 0x7d, 0x2d, 0x6b, 0x71, 0x9b, 0xef, 0xb3, 0xfb, 0xe9, 0xd3, 0x87, 0xd4, 0xf7, 0x42, + 0x70, 0xcb, 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, + 0xbd, 0xf2, 0x3d, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0x7d, 0x9f, 0xcd, 0xb3, 0xc5, 0x76, 0x1b, 0xe2, 0xdf, + 0xae, 0x16, 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0x7f, 0x2d, 0x1a, 0x4e, + 0x13, 0xcf, 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, + 0xc0, 0x15, 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x4f, 0x96, 0xb6, 0x55, 0xc5, + 0x9d, 0xb7, 0xa4, 0x39, 0xae, 0x03, 0xe7, 0xeb, 0x60, 0x86, 0xd8, 0x94, 0x5d, 0x2d, 0x90, 0xfb, 0xe5, 0x35, 0xed, + 0x8d, 0xeb, 0x04, 0x66, 0x6d, 0x53, 0x5b, 0xc6, 0xcf, 0x96, 0xfe, 0x4e, 0x0f, 0xae, 0x32, 0x06, 0x9b, 0x1b, 0x2b, + 0x0d, 0xbb, 0x6f, 0x3c, 0x5f, 0x0a, 0x08, 0x4f, 0xe7, 0xd3, 0xe3, 0xf7, 0x99, 0x47, 0x8f, 0x81, 0xe8, 0x98, 0x8f, + 0x4a, 0xf7, 0x91, 0xdd, 0xbd, 0x7e, 0x40, 0xc0, 0x79, 0xd5, 0x2e, 0x68, 0x5e, 0x2e, 0x20, 0xb0, 0xaa, 0x57, 0x5e, + 0x61, 0xf9, 0xcc, 0x98, 0x5d, 0x02, 0x19, 0x2a, 0x08, 0x04, 0xee, 0xee, 0x3a, 0x17, 0x62, 0xd5, 0x61, 0x65, 0x4e, + 0x93, 0xb0, 0x93, 0x10, 0xcd, 0x5b, 0x83, 0x59, 0xf0, 0x5f, 0xc1, 0xa0, 0x1c, 0x04, 0x51, 0x10, 0x05, 0x01, 0x19, + 0x14, 0xf0, 0x0b, 0x71, 0xd7, 0x08, 0xc6, 0x6c, 0x81, 0x0e, 0x3f, 0xe0, 0xcc, 0x67, 0x44, 0x5e, 0xfa, 0x61, 0x3d, + 0xbd, 0x01, 0x38, 0x97, 0x32, 0xe7, 0x31, 0xfa, 0x9c, 0x3c, 0xe0, 0x2c, 0x23, 0xf4, 0x81, 0x77, 0x2a, 0xbf, 0xe5, + 0x8d, 0x60, 0x7f, 0xbb, 0xc3, 0xf6, 0x02, 0xe4, 0x15, 0xbd, 0x31, 0x7d, 0xc0, 0x49, 0x94, 0x35, 0x9c, 0xa9, 0x39, + 0xf4, 0xac, 0xb2, 0xac, 0x15, 0x35, 0xe4, 0x06, 0xc5, 0xdc, 0xc8, 0x32, 0x39, 0x99, 0xb6, 0x9a, 0x53, 0x81, 0xeb, + 0xce, 0xae, 0x17, 0x90, 0x1c, 0x0a, 0xcd, 0xd2, 0xd9, 0x70, 0xde, 0xb6, 0x65, 0xcf, 0x5a, 0xa7, 0x90, 0xd7, 0x10, + 0x15, 0x0d, 0xd2, 0x11, 0x50, 0x43, 0x2b, 0x2e, 0x2b, 0x70, 0x61, 0x36, 0xed, 0xe1, 0xa6, 0x3d, 0xa6, 0x19, 0x3f, + 0x41, 0xcc, 0x3c, 0x8e, 0x2d, 0x03, 0x3b, 0x12, 0x87, 0xef, 0xe3, 0x7c, 0x81, 0x76, 0xe9, 0xad, 0xab, 0xc5, 0x23, + 0xac, 0x3d, 0x6f, 0x85, 0x84, 0x00, 0xf1, 0x69, 0x2a, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, + 0x6a, 0xd8, 0x49, 0x73, 0x6b, 0xb6, 0xc4, 0x5e, 0x51, 0x78, 0x0c, 0xcc, 0xa9, 0xf9, 0xcf, 0x20, 0xa0, 0x78, 0xee, + 0x86, 0x60, 0x6f, 0xca, 0x4e, 0x36, 0x45, 0xbf, 0xff, 0xac, 0xc0, 0x07, 0x94, 0x0b, 0x83, 0x98, 0x5b, 0xc7, 0xf1, + 0x30, 0xec, 0x93, 0xfa, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x47, 0x58, 0x2a, 0x43, 0x58, 0xb8, 0x62, 0xa4, 0x83, 0x38, + 0xa8, 0x49, 0xe7, 0x60, 0x55, 0x2e, 0xf8, 0x72, 0xaf, 0xf7, 0x1a, 0x60, 0xd2, 0x33, 0x6f, 0x58, 0x5e, 0x78, 0x80, + 0x68, 0xbd, 0x1e, 0x2e, 0x14, 0x8f, 0x4c, 0x34, 0xd0, 0x38, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, 0x56, 0x32, 0x1a, + 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0xec, 0x77, 0x9f, 0x5a, 0x28, 0x9e, 0x32, 0x4e, 0x79, 0x0a, 0x96, 0xef, 0x86, 0xd2, + 0xcd, 0x17, 0x74, 0xc5, 0x45, 0xaa, 0x7e, 0x7a, 0xe8, 0x9b, 0x0d, 0xe2, 0x9a, 0x35, 0x75, 0x38, 0x76, 0xf8, 0x21, + 0x00, 0xa6, 0x7d, 0x98, 0xb9, 0x74, 0x0d, 0xd3, 0x0b, 0xe2, 0xd9, 0xb8, 0xe0, 0xa1, 0xcb, 0x03, 0xd8, 0x87, 0xe6, + 0x90, 0xc4, 0x4f, 0xe1, 0xe7, 0xcc, 0xa4, 0x75, 0x7c, 0x86, 0xb3, 0x19, 0x95, 0xea, 0x46, 0xd0, 0x7e, 0x0d, 0x89, + 0xc4, 0x20, 0x3d, 0x37, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x96, 0xde, 0xf9, 0x34, 0x08, 0xb0, 0xbe, 0xb1, + 0x18, 0x00, 0x50, 0xc5, 0x1f, 0xa8, 0xba, 0x32, 0x57, 0x14, 0xd3, 0x30, 0x95, 0x68, 0xef, 0x38, 0xae, 0xa3, 0xc6, + 0x75, 0x58, 0xb0, 0xd2, 0xda, 0x36, 0xbb, 0xb7, 0x10, 0x7f, 0x44, 0x97, 0x80, 0x6a, 0x41, 0xdc, 0x09, 0xe0, 0x43, + 0x23, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x00, 0x78, 0xc3, 0xf3, 0x30, 0x84, 0x3f, 0xb0, 0x70, 0x60, 0x59, 0xaa, + 0x7e, 0x2e, 0xa7, 0x31, 0x9c, 0xbb, 0xb9, 0xda, 0xe1, 0xb3, 0x25, 0x28, 0x36, 0xd5, 0x9c, 0x9a, 0xcb, 0x57, 0xde, + 0xd8, 0xef, 0x31, 0xc1, 0x3c, 0x66, 0xb6, 0xe1, 0xb7, 0x9e, 0x6e, 0xeb, 0x1b, 0xec, 0x06, 0x4e, 0xda, 0x0b, 0xa7, + 0xbd, 0xd8, 0x2e, 0x0d, 0xe4, 0x5f, 0xdd, 0x10, 0x22, 0x7c, 0xd0, 0xc4, 0x22, 0x6b, 0xc8, 0x74, 0x2c, 0x56, 0x88, + 0x6a, 0x53, 0xf1, 0x54, 0x1b, 0x08, 0x94, 0x53, 0x75, 0x61, 0x6a, 0xa5, 0x32, 0x61, 0x10, 0x77, 0x4a, 0x58, 0x54, + 0x19, 0x60, 0x18, 0x54, 0x48, 0x71, 0x6d, 0x3d, 0x7f, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0x2f, 0xf2, 0xf8, + 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0x39, 0x6a, 0xa9, 0x34, 0x8c, 0xe0, 0x04, 0xa2, 0x24, 0xd7, 0x7b, 0x72, 0x4e, + 0x1c, 0x27, 0xd7, 0x6e, 0xde, 0x6c, 0x27, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0x49, 0x6a, 0x4f, + 0x01, 0x6f, 0xd3, 0x3b, 0x4a, 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, + 0x83, 0x80, 0xd3, 0x9e, 0x6e, 0xac, 0x55, 0x24, 0x9b, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0xb5, 0xbb, 0x6d, + 0x55, 0xb6, 0x50, 0x30, 0x0f, 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x17, 0xa4, 0xd0, 0x2b, + 0x47, 0xab, 0x9a, 0x77, 0x25, 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xfb, 0x5a, 0xd6, 0x58, 0x5c, 0x39, 0x21, + 0x85, 0x4d, 0xf8, 0xd2, 0x52, 0x2c, 0xcc, 0x62, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x8c, 0x36, + 0x58, 0x37, 0xdb, 0xed, 0x87, 0x22, 0x9c, 0x67, 0x0b, 0x2a, 0x47, 0x59, 0x8a, 0x90, 0x6a, 0xc6, 0x63, 0xd9, 0x76, + 0xc1, 0x4c, 0x0c, 0x75, 0xed, 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, + 0x1e, 0xee, 0xdf, 0xa5, 0x10, 0xd3, 0xce, 0xac, 0xbb, 0x5f, 0x77, 0x6e, 0x88, 0xdf, 0x41, 0x60, 0x85, 0x92, 0x7d, + 0x28, 0x46, 0xe7, 0x99, 0x48, 0x71, 0xa7, 0xaa, 0x28, 0xc1, 0x6a, 0x1d, 0x34, 0x5b, 0x6e, 0xef, 0xc5, 0x96, 0x28, + 0x40, 0x9c, 0x67, 0xa1, 0x19, 0xcf, 0xca, 0x59, 0xce, 0x64, 0x14, 0x1b, 0x12, 0x95, 0x5e, 0x94, 0x78, 0x9f, 0xa7, + 0x31, 0x3d, 0x74, 0x6b, 0x10, 0x5c, 0x57, 0x77, 0x36, 0xd2, 0x7c, 0x41, 0x88, 0x9a, 0x00, 0x09, 0x1b, 0xd5, 0x9c, + 0x5a, 0x97, 0xe2, 0x7e, 0x56, 0xf9, 0x4e, 0x1f, 0xc4, 0x97, 0x02, 0x78, 0x58, 0x6f, 0x7b, 0x5f, 0x09, 0x8f, 0xb5, + 0xc1, 0xb7, 0xdb, 0xed, 0xa5, 0x98, 0x07, 0x81, 0xc7, 0x68, 0xfe, 0xa0, 0x24, 0xe6, 0xbd, 0x31, 0x85, 0x15, 0xef, + 0xbb, 0xf8, 0x75, 0x93, 0x5a, 0x6b, 0x91, 0xbb, 0xc3, 0xf5, 0x01, 0xcf, 0x53, 0xe2, 0x68, 0x47, 0xe5, 0x54, 0x5a, + 0xdb, 0x01, 0xec, 0x8a, 0xc0, 0x40, 0xd9, 0xbf, 0xa4, 0x6c, 0x03, 0xe6, 0x89, 0x60, 0x7d, 0x84, 0x7e, 0x5b, 0x4a, + 0x7f, 0x32, 0x46, 0xe3, 0x1e, 0xb9, 0xae, 0xa2, 0x23, 0xae, 0xa3, 0xd9, 0xf3, 0xe8, 0x6f, 0x4f, 0xc6, 0xb4, 0x88, + 0x45, 0x2a, 0xaf, 0x40, 0x05, 0x01, 0xca, 0x10, 0x74, 0x84, 0xd0, 0xd4, 0x00, 0x34, 0x08, 0x6e, 0x00, 0x7e, 0xeb, + 0x74, 0xa2, 0xb4, 0x35, 0xf9, 0x18, 0xad, 0xaa, 0xc8, 0x59, 0x1b, 0xda, 0x4d, 0x25, 0x87, 0xe4, 0x61, 0x09, 0xf8, + 0x96, 0xd8, 0x2c, 0x65, 0x83, 0xa2, 0x36, 0x9b, 0x7a, 0xad, 0xd8, 0x91, 0xdb, 0x46, 0xd1, 0x66, 0x2d, 0x6a, 0xbb, + 0x91, 0xf9, 0x62, 0x7a, 0x6b, 0x85, 0x81, 0x53, 0xd3, 0x9a, 0x9b, 0x1d, 0x28, 0x39, 0x5b, 0x9f, 0xc9, 0x4d, 0x80, + 0x38, 0xc0, 0x70, 0xdd, 0xce, 0x6f, 0x16, 0x84, 0xde, 0xb2, 0x5b, 0x2b, 0x56, 0xbd, 0xb1, 0x72, 0x11, 0x93, 0x76, + 0x33, 0x98, 0xc0, 0x65, 0x9c, 0x15, 0xf6, 0x85, 0x56, 0x37, 0x14, 0x1d, 0x6d, 0x93, 0xf6, 0xf3, 0x8e, 0x76, 0xc3, + 0x05, 0xdf, 0x8a, 0x75, 0x9c, 0x5b, 0xd6, 0x54, 0xa1, 0x69, 0x07, 0x7a, 0x3b, 0x04, 0x34, 0x67, 0x63, 0xba, 0xa4, + 0x29, 0x5e, 0xa0, 0xe9, 0x1a, 0xcc, 0x74, 0x2e, 0xa0, 0xaf, 0xdd, 0x3e, 0xda, 0x17, 0xaa, 0x27, 0xc2, 0x5b, 0xa2, + 0xe0, 0xdb, 0x92, 0x82, 0x97, 0x5a, 0xce, 0x63, 0x33, 0x87, 0x80, 0x4f, 0xa3, 0x4a, 0xf4, 0x4e, 0x8a, 0x4b, 0xd0, + 0x66, 0xc2, 0x11, 0x68, 0xaa, 0x46, 0x6c, 0xe5, 0x00, 0xb7, 0x17, 0x4f, 0x03, 0x42, 0x41, 0xaa, 0xbb, 0xb6, 0x2b, + 0xf2, 0x96, 0x9d, 0x6c, 0x6e, 0xc1, 0x4c, 0xb8, 0x5a, 0x97, 0xad, 0xaf, 0x6c, 0xb2, 0xfb, 0xb8, 0x26, 0xd8, 0x76, + 0x6f, 0x83, 0x84, 0xb7, 0xf4, 0x86, 0x6c, 0x6e, 0xfa, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xee, 0xd0, 0x6d, 0x67, 0x87, + 0x6e, 0xbd, 0x76, 0x9e, 0x5b, 0x3d, 0x9f, 0xf2, 0x0e, 0xf9, 0x80, 0x26, 0x6b, 0x74, 0x15, 0xdf, 0xc1, 0xa6, 0x8e, + 0x2a, 0xaa, 0x2a, 0x8f, 0x12, 0x0a, 0x2a, 0xf1, 0x8c, 0x97, 0xef, 0x39, 0xc6, 0x7a, 0xd5, 0x4f, 0x6f, 0x35, 0xaf, + 0xb6, 0x36, 0x6b, 0xb3, 0x5c, 0x9f, 0x83, 0x85, 0xc4, 0x39, 0x8f, 0xae, 0x34, 0x2d, 0xb9, 0xf4, 0xa1, 0x34, 0x71, + 0x54, 0x82, 0x8b, 0x38, 0xcb, 0x41, 0x8d, 0x7b, 0xd1, 0xec, 0x7f, 0xa8, 0x6d, 0xc7, 0x96, 0x8d, 0x33, 0xf7, 0x3a, + 0x24, 0x9b, 0xff, 0xb1, 0x81, 0x7a, 0x1a, 0x62, 0x84, 0x58, 0xb3, 0xa0, 0xdf, 0x30, 0x88, 0x15, 0x1a, 0x94, 0xeb, + 0x24, 0xe1, 0x65, 0x19, 0x18, 0xa5, 0xd6, 0x9a, 0xad, 0xcd, 0x79, 0xf6, 0x96, 0x9d, 0xbc, 0xed, 0x31, 0x76, 0x4b, + 0x68, 0xa2, 0x75, 0x42, 0xa6, 0xc6, 0xc8, 0xd3, 0x02, 0xe9, 0x0e, 0x45, 0xd9, 0x45, 0xf8, 0x06, 0x85, 0x2c, 0xed, + 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0x42, 0x89, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xc0, 0x18, 0x9a, 0x1d, + 0x90, 0xcd, 0x92, 0xbd, 0xa2, 0x67, 0xd6, 0x24, 0x08, 0x5e, 0xbf, 0x51, 0x89, 0x66, 0x94, 0x15, 0xd1, 0x55, 0x46, + 0x3f, 0x77, 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, + 0x6a, 0x6c, 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, + 0xbc, 0xa5, 0xe0, 0x2f, 0xf6, 0x96, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb2, 0x93, + 0xcd, 0xdb, 0xf0, 0x55, 0x63, 0xe6, 0xee, 0x42, 0xbc, 0x54, 0x25, 0x3d, 0x6f, 0x9e, 0xcc, 0x40, 0xac, 0xac, 0xd6, + 0xfc, 0x96, 0x59, 0x7d, 0x02, 0x10, 0xa9, 0x5b, 0xeb, 0x60, 0x8b, 0x1f, 0x9b, 0x2e, 0x93, 0x4d, 0xca, 0xda, 0x4c, + 0x94, 0x52, 0x91, 0x34, 0x17, 0x01, 0xf4, 0x1b, 0x86, 0xa3, 0x06, 0xb8, 0x73, 0x3d, 0xf6, 0x66, 0x68, 0xbc, 0x31, + 0x35, 0xf4, 0x6c, 0xa3, 0x97, 0xb7, 0xa3, 0x10, 0x66, 0x2c, 0xa2, 0x5b, 0x77, 0x2c, 0x86, 0xaf, 0xe8, 0x1b, 0xa8, + 0xf0, 0x69, 0x88, 0xd1, 0x85, 0x49, 0x5d, 0x4f, 0xd7, 0x6a, 0x2b, 0xdd, 0x10, 0x9a, 0x63, 0x54, 0x23, 0xaf, 0x6d, + 0x77, 0xd4, 0x08, 0xed, 0x09, 0xe5, 0xe1, 0x2d, 0xad, 0xe8, 0x8d, 0x65, 0x11, 0x9c, 0xfc, 0xd8, 0xcb, 0x4f, 0xe8, + 0xb9, 0x27, 0x30, 0x29, 0xda, 0x1a, 0xc0, 0x5f, 0x50, 0x3f, 0x9c, 0xd5, 0x53, 0x2b, 0xe5, 0xf0, 0x14, 0xbe, 0x64, + 0x03, 0x72, 0x05, 0xbd, 0x58, 0x63, 0x76, 0x12, 0x83, 0x0e, 0x6a, 0x67, 0x77, 0x78, 0x93, 0x52, 0x86, 0x68, 0x8d, + 0xe8, 0x20, 0xaf, 0x7e, 0x03, 0x4d, 0x1f, 0xa4, 0x85, 0x29, 0x5d, 0xa3, 0x80, 0x07, 0xf4, 0x4d, 0xfd, 0x7e, 0x8e, + 0xcf, 0xb5, 0x67, 0x99, 0xa6, 0x2c, 0x90, 0x09, 0x5d, 0x7a, 0x71, 0xbb, 0x40, 0xda, 0xec, 0x58, 0x05, 0x60, 0x45, + 0x12, 0x68, 0x44, 0x02, 0x96, 0x4b, 0x9e, 0xb8, 0x6c, 0x83, 0x06, 0x35, 0x51, 0x49, 0x21, 0x4b, 0x24, 0x81, 0x1f, + 0x46, 0x50, 0xa6, 0x28, 0x06, 0x71, 0xaf, 0x5e, 0x5e, 0x71, 0x4d, 0x0d, 0x58, 0x53, 0x04, 0x13, 0xac, 0xd3, 0x29, + 0x10, 0x5b, 0xb1, 0x5e, 0x81, 0x27, 0xaa, 0xbb, 0x48, 0x22, 0x4b, 0x80, 0x06, 0x7a, 0xbe, 0x74, 0xda, 0x2d, 0x6f, + 0x4f, 0xb4, 0x54, 0xb1, 0xb9, 0xf7, 0x62, 0x61, 0xb9, 0xc7, 0xca, 0xdf, 0x0e, 0xb4, 0x17, 0x56, 0x3b, 0x22, 0x6a, + 0xb0, 0x3a, 0x6c, 0xdb, 0xf9, 0xa1, 0x34, 0x54, 0xf7, 0xca, 0x31, 0x01, 0x15, 0x5d, 0xc5, 0xd5, 0x32, 0xca, 0x46, + 0xf0, 0x67, 0xbb, 0x0d, 0x0e, 0x03, 0xb0, 0x08, 0xfd, 0xe5, 0xdd, 0x4f, 0x11, 0x86, 0xab, 0xfa, 0xe5, 0xdd, 0x4f, + 0xdb, 0xed, 0x93, 0xf1, 0xd8, 0x70, 0x05, 0x4e, 0xad, 0x03, 0xfc, 0x81, 0x61, 0x1b, 0xec, 0x92, 0xdd, 0x6e, 0x9f, + 0x00, 0x07, 0xa1, 0xd8, 0x06, 0xb3, 0x8b, 0x95, 0x63, 0x9b, 0x62, 0x35, 0xf4, 0x8e, 0x04, 0xec, 0xbe, 0x1d, 0x96, + 0x62, 0x97, 0xfa, 0xa8, 0x90, 0x94, 0x7a, 0xd1, 0x3f, 0xef, 0x14, 0x58, 0x52, 0x30, 0xe5, 0x0d, 0x96, 0x55, 0xb5, + 0x2a, 0xa3, 0xc3, 0xc3, 0x78, 0x95, 0x8d, 0xca, 0x0c, 0xb6, 0x79, 0x79, 0x7d, 0x09, 0x00, 0x13, 0x01, 0x6d, 0xbc, + 0x5b, 0x8b, 0xcc, 0xbc, 0x58, 0xd0, 0x65, 0x86, 0x6b, 0x12, 0xcc, 0x0e, 0x72, 0x6e, 0x75, 0x93, 0x53, 0x62, 0x1f, + 0xc0, 0x06, 0x73, 0xbb, 0x6d, 0xf0, 0x0b, 0x27, 0xa3, 0x27, 0xb3, 0x65, 0xa6, 0x0d, 0x5c, 0xb9, 0xd9, 0xff, 0x24, + 0xf2, 0xd2, 0x50, 0xf1, 0x49, 0xa6, 0xcf, 0x33, 0xe0, 0xf3, 0xd8, 0x27, 0x11, 0xfa, 0x2c, 0x57, 0xa3, 0x35, 0xc0, + 0xc6, 0x66, 0x17, 0x77, 0xa3, 0x94, 0x43, 0x84, 0x8e, 0xc0, 0xaa, 0x6b, 0x96, 0x19, 0xf1, 0x6d, 0x2a, 0x6e, 0x5b, + 0xaa, 0xb0, 0x4f, 0xc2, 0x73, 0xde, 0xe1, 0xc6, 0x71, 0xa8, 0x37, 0x89, 0xc2, 0xe7, 0x28, 0x44, 0xe5, 0x68, 0x5c, + 0xe8, 0xe4, 0x6b, 0x99, 0xc7, 0x84, 0x62, 0x0e, 0xf7, 0xee, 0x9f, 0xa9, 0x33, 0x97, 0xf1, 0x85, 0x7b, 0xcf, 0x7d, + 0x99, 0xc9, 0xb5, 0x04, 0x90, 0x28, 0x55, 0xfb, 0xcf, 0x9f, 0x91, 0x1a, 0xff, 0x95, 0x6a, 0x0d, 0x40, 0xef, 0x67, + 0xa8, 0xc9, 0x11, 0x04, 0x6c, 0xc5, 0xd4, 0x8f, 0x2e, 0x60, 0x25, 0xf3, 0x3f, 0xa1, 0x6e, 0x47, 0xb0, 0x8d, 0x8a, + 0x27, 0x14, 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0xee, 0x22, 0x5e, 0x4f, 0xb1, 0x24, 0x66, 0x23, 0x86, + 0xfd, 0xdc, 0xec, 0xc2, 0xbb, 0xa2, 0x61, 0x12, 0x4f, 0x4b, 0x7f, 0x5b, 0x79, 0x9b, 0xc9, 0x32, 0xce, 0xc8, 0x94, + 0x2b, 0x04, 0x73, 0xab, 0xef, 0x31, 0x27, 0xf8, 0xe3, 0xa3, 0xc7, 0x84, 0x5e, 0xcb, 0x69, 0x89, 0x20, 0x7d, 0x22, + 0xb5, 0xae, 0xab, 0xd8, 0xaf, 0x29, 0x44, 0xb5, 0x10, 0x0c, 0x42, 0x99, 0x9a, 0xf6, 0x29, 0xbe, 0xcf, 0x96, 0xfd, + 0xc9, 0x94, 0x2d, 0xc9, 0x46, 0x40, 0xc7, 0xa4, 0xf3, 0x7e, 0xf5, 0xf6, 0xec, 0xcc, 0xfb, 0x0d, 0x9a, 0x70, 0x50, + 0xdd, 0x40, 0xbb, 0x0a, 0x32, 0x8d, 0x51, 0x6c, 0x16, 0x63, 0xed, 0xd6, 0x44, 0x04, 0x41, 0xb8, 0xcb, 0x59, 0xd8, + 0x6e, 0x27, 0xc4, 0xdb, 0x40, 0x02, 0x05, 0xae, 0x6d, 0x94, 0x93, 0x90, 0xa8, 0x0b, 0x99, 0x39, 0x26, 0x24, 0x0b, + 0xf4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0xb7, 0x4f, 0x01, 0x7d, 0x51, 0xb0, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x6f, 0x36, + 0xa0, 0x1f, 0xa5, 0x7a, 0x04, 0x8f, 0x69, 0x60, 0xb9, 0xe8, 0xeb, 0x82, 0x21, 0xcc, 0xd2, 0xef, 0x29, 0x9b, 0x7c, + 0xf3, 0x77, 0x37, 0xbf, 0xe7, 0x5a, 0xcc, 0x0e, 0x42, 0x71, 0x7b, 0x3d, 0x01, 0xe2, 0x57, 0xf1, 0x2b, 0xb0, 0x36, + 0xd7, 0x12, 0x6f, 0x4f, 0xf2, 0x20, 0x7c, 0x39, 0xba, 0xfd, 0xa4, 0x34, 0x9f, 0x40, 0xd0, 0x1e, 0x27, 0x29, 0x77, + 0xdf, 0xbd, 0x97, 0xae, 0x22, 0x18, 0x2d, 0x40, 0xf0, 0xdb, 0x5b, 0xc9, 0x59, 0x53, 0xf8, 0x8f, 0x75, 0xbe, 0xc0, + 0x58, 0x2a, 0xf2, 0x3d, 0x4e, 0x7f, 0x13, 0x1c, 0xdc, 0xbf, 0x95, 0x59, 0x43, 0xa2, 0x73, 0xf5, 0x11, 0xd0, 0xff, + 0xb1, 0x1e, 0xbf, 0x53, 0x94, 0xf4, 0x25, 0x71, 0x8e, 0xf0, 0x4d, 0xbc, 0x44, 0xd3, 0xc5, 0xde, 0xb8, 0xa6, 0x9f, + 0x0a, 0xf3, 0x42, 0x2b, 0x38, 0xec, 0x5b, 0xa3, 0xf0, 0xc0, 0x33, 0xef, 0x3b, 0xd1, 0x10, 0x74, 0xff, 0x03, 0xf7, + 0xc6, 0x77, 0x82, 0x65, 0x78, 0x53, 0xce, 0x32, 0x73, 0x87, 0xbb, 0xc9, 0x44, 0x2a, 0x6f, 0x18, 0x0b, 0xd6, 0x42, + 0x99, 0xf3, 0xa6, 0xc1, 0x6c, 0x53, 0x47, 0x2a, 0xd9, 0x7d, 0xff, 0x67, 0xe3, 0x84, 0xcd, 0x06, 0xc1, 0xfb, 0x4a, + 0x16, 0xf1, 0x25, 0x0f, 0xa6, 0x5a, 0x45, 0x91, 0x81, 0x5d, 0x21, 0x20, 0xe5, 0x38, 0xed, 0x1d, 0x3c, 0x59, 0x6a, + 0x66, 0x42, 0x7e, 0x5b, 0x9d, 0x05, 0xbc, 0x35, 0xa3, 0x79, 0x5a, 0xc1, 0x2e, 0xf3, 0x95, 0x14, 0xdf, 0xb5, 0x24, + 0xd9, 0x58, 0x7f, 0x43, 0x86, 0x6d, 0xe5, 0x33, 0xe7, 0x80, 0xb9, 0xf3, 0x51, 0xaa, 0xa0, 0x7f, 0x3d, 0xc6, 0x6e, + 0x24, 0x12, 0x01, 0xe1, 0x2c, 0x26, 0xee, 0x84, 0x09, 0x87, 0xe9, 0x02, 0x05, 0xc5, 0x18, 0x28, 0xe8, 0xbd, 0x0c, + 0x39, 0x3d, 0xe5, 0x83, 0xa4, 0x31, 0x5b, 0x7f, 0xaa, 0x12, 0xe9, 0x8d, 0x24, 0xf4, 0x0c, 0x7e, 0x8f, 0x5b, 0x3c, + 0x50, 0x23, 0x58, 0xa7, 0xbb, 0x39, 0x1d, 0xbe, 0x2e, 0xc8, 0xf0, 0x77, 0xf0, 0x76, 0x8b, 0xed, 0x65, 0x39, 0x81, + 0xc5, 0x1d, 0x7b, 0xc5, 0xd3, 0x5c, 0xb5, 0x38, 0x21, 0x1e, 0xb1, 0xc8, 0x7d, 0x62, 0x01, 0x23, 0x6a, 0x18, 0x8d, + 0x1f, 0xdf, 0xbf, 0x79, 0xad, 0x31, 0xac, 0x72, 0xff, 0x03, 0x18, 0x51, 0x2d, 0x6d, 0xb7, 0x03, 0xbe, 0x1c, 0xa1, + 0x01, 0x7b, 0xea, 0x06, 0xbb, 0xdf, 0x37, 0x69, 0x27, 0xa5, 0x97, 0xcd, 0x89, 0x41, 0x77, 0x94, 0x36, 0x4b, 0x65, + 0x60, 0xdc, 0x55, 0x38, 0x9a, 0x13, 0x1b, 0xb1, 0xaa, 0xf7, 0x61, 0xb8, 0xa4, 0xb1, 0x95, 0x95, 0xdb, 0xdd, 0x84, + 0x23, 0x9b, 0x00, 0xd7, 0xa7, 0xa0, 0xbd, 0x9a, 0x73, 0xd0, 0x82, 0x12, 0x05, 0x8e, 0x68, 0xbb, 0x0d, 0x21, 0x22, + 0x49, 0x31, 0x9c, 0xcc, 0xc2, 0x62, 0x38, 0x54, 0x03, 0x5f, 0x10, 0x12, 0x7d, 0x2a, 0xe6, 0xd9, 0x42, 0x21, 0x18, + 0xf9, 0x3b, 0xe9, 0xd7, 0x42, 0x71, 0xca, 0xbd, 0xef, 0x04, 0xd9, 0xfc, 0x23, 0xc5, 0x18, 0x8c, 0x4e, 0xb3, 0x99, + 0x81, 0x84, 0xf5, 0xb4, 0x22, 0x6a, 0x1d, 0xd9, 0xd9, 0x00, 0x55, 0x2c, 0x9a, 0x06, 0x83, 0xba, 0xc5, 0x13, 0xeb, + 0x19, 0xbd, 0x07, 0x95, 0x20, 0xaa, 0x05, 0xbb, 0x31, 0x5c, 0x6b, 0xaf, 0x45, 0x28, 0x29, 0x27, 0x4d, 0x66, 0xc6, + 0x8a, 0x06, 0x0b, 0x10, 0x92, 0xc6, 0x65, 0xf5, 0x4a, 0xa6, 0xd9, 0x45, 0x06, 0x08, 0x12, 0xce, 0x9f, 0x50, 0x36, + 0xde, 0x3c, 0x55, 0xf3, 0xd2, 0x95, 0x38, 0xb3, 0xb0, 0x27, 0x5d, 0x6f, 0x69, 0x41, 0xa2, 0x02, 0x68, 0x94, 0xaf, + 0xe5, 0xf9, 0x7e, 0xc7, 0x2a, 0x64, 0xf7, 0xc3, 0xa9, 0xb2, 0x1d, 0xe2, 0x27, 0xac, 0x22, 0xde, 0x69, 0x5d, 0x29, + 0x91, 0x46, 0x47, 0xdb, 0x80, 0x18, 0xb6, 0xec, 0x5b, 0xd4, 0xf0, 0x41, 0xd8, 0x45, 0x27, 0xf9, 0x41, 0x4f, 0xf1, + 0xd8, 0x1a, 0x48, 0xfa, 0x5a, 0x04, 0x5f, 0xa3, 0x23, 0x9d, 0x28, 0xd3, 0x48, 0x4c, 0x21, 0xd1, 0xaf, 0x17, 0x5a, + 0x63, 0x19, 0x65, 0x5f, 0x91, 0xff, 0xb3, 0xee, 0xde, 0x77, 0x62, 0xbb, 0x85, 0x49, 0xf6, 0x3c, 0xd0, 0x60, 0x53, + 0xa3, 0x56, 0x08, 0x67, 0xe7, 0xb4, 0x42, 0xed, 0x58, 0x2f, 0x2c, 0x81, 0x3c, 0x80, 0xad, 0x48, 0x83, 0x32, 0x48, + 0xf6, 0xa9, 0x98, 0x8b, 0x85, 0x13, 0xe5, 0x48, 0x85, 0x7f, 0x26, 0x47, 0x29, 0x87, 0xab, 0x58, 0x58, 0x30, 0xe4, + 0x57, 0x47, 0x17, 0x85, 0xbc, 0x02, 0x49, 0x89, 0x61, 0xa8, 0x2c, 0xaf, 0x8b, 0xab, 0xb6, 0x24, 0xb4, 0x77, 0x06, + 0xa0, 0x34, 0x05, 0x08, 0x5e, 0x1a, 0x35, 0xc4, 0x6c, 0xa3, 0x76, 0x57, 0xb4, 0x97, 0x1c, 0x50, 0xa7, 0xbb, 0x76, + 0xeb, 0x4d, 0xd9, 0xaa, 0x5b, 0x71, 0xe1, 0x9f, 0x50, 0xfa, 0x29, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, + 0x59, 0x76, 0x71, 0x87, 0x4b, 0xbf, 0x6a, 0x8c, 0x5f, 0xbf, 0xdf, 0x53, 0x0b, 0xa1, 0x91, 0x0a, 0xcc, 0xb7, 0xcf, + 0x4c, 0x55, 0x46, 0x53, 0x6a, 0x2f, 0xc1, 0x95, 0xb3, 0x1f, 0x41, 0x45, 0x5c, 0x57, 0xa4, 0x36, 0x35, 0x40, 0x07, + 0x5e, 0x56, 0xb8, 0x95, 0x05, 0x78, 0xec, 0x04, 0x64, 0xbb, 0xe5, 0x61, 0xa0, 0x0f, 0x9d, 0xc0, 0xdf, 0x92, 0xaf, + 0x90, 0x59, 0xb3, 0x8f, 0xff, 0xd2, 0x82, 0x7f, 0x6c, 0xc1, 0x4f, 0x28, 0xee, 0xb4, 0x32, 0xff, 0x56, 0x5a, 0xb7, + 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0xd1, 0x04, 0x8f, 0x52, 0xd9, 0x3f, 0x48, 0xf8, + 0x60, 0xd6, 0x78, 0x62, 0x8d, 0x27, 0xc3, 0xe9, 0x56, 0x1a, 0x96, 0x01, 0x85, 0x7e, 0x5e, 0xe6, 0x8a, 0xea, 0xe7, + 0x9f, 0xd7, 0x7c, 0xcd, 0x9b, 0x2d, 0xb6, 0x49, 0xf7, 0x34, 0xd8, 0xcb, 0xa3, 0x29, 0x85, 0x93, 0xa8, 0x73, 0x23, + 0x51, 0x17, 0x35, 0xcb, 0x50, 0x9d, 0xe0, 0xd5, 0x3c, 0xd5, 0xc3, 0xde, 0x4c, 0x44, 0x6b, 0x25, 0x65, 0x89, 0x01, + 0x6b, 0x1d, 0x79, 0x48, 0xee, 0xd6, 0x3a, 0xee, 0x34, 0xd4, 0xa5, 0x29, 0xd4, 0x04, 0x2b, 0x5c, 0x80, 0x23, 0xe8, + 0x5d, 0x11, 0x72, 0xb8, 0xa6, 0x2a, 0xfd, 0x82, 0xa6, 0xe4, 0x89, 0xa7, 0xa8, 0xd5, 0x8a, 0x74, 0xfb, 0x51, 0x8e, + 0xdd, 0xf0, 0x8d, 0x13, 0x72, 0x62, 0x84, 0xfe, 0xee, 0x58, 0xca, 0x19, 0x5a, 0x3c, 0xa8, 0x13, 0xac, 0x97, 0xb7, + 0x14, 0x28, 0xe6, 0xe8, 0xb2, 0xea, 0x9a, 0x97, 0x68, 0xfb, 0xb2, 0xec, 0xf7, 0x73, 0x5b, 0x4f, 0xca, 0x4e, 0x36, + 0x4b, 0xb3, 0x0f, 0x51, 0x31, 0x85, 0xbb, 0x3e, 0xd1, 0xfc, 0x55, 0xa8, 0xaf, 0xda, 0x32, 0xe7, 0x23, 0x8e, 0x38, + 0x21, 0x39, 0xa9, 0xff, 0xa5, 0xa6, 0x5e, 0x89, 0xfb, 0x55, 0x25, 0xbf, 0x0a, 0x63, 0xc5, 0x68, 0x89, 0x21, 0x8a, + 0xb4, 0x7b, 0x63, 0xfa, 0xb2, 0x00, 0xf8, 0x2b, 0xc1, 0x3e, 0xa5, 0xa1, 0x56, 0x7e, 0x8b, 0xb6, 0x80, 0x7f, 0xa3, + 0xb8, 0x01, 0xab, 0xc0, 0x00, 0xa3, 0xc9, 0xf6, 0x9c, 0x26, 0x70, 0xc0, 0x09, 0xad, 0xa2, 0xa0, 0xc2, 0x0c, 0x0d, + 0xb5, 0x85, 0xd1, 0x57, 0x28, 0xe3, 0x56, 0x99, 0xbd, 0x1b, 0x63, 0xa7, 0x05, 0x5e, 0xc3, 0xbf, 0xd1, 0x0b, 0xc5, + 0x6c, 0xd4, 0x41, 0x7a, 0x74, 0x12, 0xd3, 0x1f, 0xb7, 0x70, 0x72, 0xb3, 0x70, 0x96, 0x35, 0x4b, 0xa0, 0x3b, 0x70, + 0x41, 0x8c, 0xfb, 0xfd, 0x1c, 0x8e, 0x4c, 0x33, 0xf2, 0x05, 0xcb, 0x69, 0xcc, 0x96, 0x54, 0x7b, 0x1e, 0x5e, 0x56, + 0x61, 0x4e, 0x97, 0x56, 0xc6, 0x9b, 0x32, 0x50, 0x19, 0x6d, 0xb7, 0x21, 0xfc, 0xe9, 0xb6, 0x76, 0x49, 0xe7, 0x4b, + 0xc8, 0x00, 0x7f, 0x40, 0x22, 0x8a, 0x58, 0xe0, 0xff, 0x56, 0xe3, 0x94, 0x9e, 0x28, 0xad, 0x59, 0x42, 0xd7, 0x4c, + 0xd7, 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0xb6, 0xdb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, + 0x02, 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0x2f, + 0x1f, 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xfc, 0x31, 0x0d, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0x47, + 0x00, 0xae, 0xe7, 0x2b, 0x88, 0x02, 0xb7, 0x86, 0xb8, 0xf0, 0xd0, 0xa0, 0xb7, 0x85, 0xbc, 0xca, 0x4a, 0x1e, 0xe2, + 0x3d, 0xc1, 0xd3, 0x8c, 0xee, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, 0xbf, 0xfe, 0x55, 0x84, + 0x73, 0x88, 0xde, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xb9, 0x3c, 0xdb, 0xab, 0xb7, 0x70, 0xba, 0xe9, 0xeb, 0x5b, + 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0x78, 0x47, 0xe2, 0x1a, 0x68, 0xac, 0xdb, 0x9a, + 0x9d, 0xf6, 0x28, 0x1e, 0x13, 0x99, 0x19, 0x8b, 0x14, 0x63, 0xee, 0xd6, 0x69, 0x51, 0xb4, 0x41, 0x33, 0x84, 0xdd, + 0xbb, 0x4e, 0xb6, 0x6e, 0x45, 0x9c, 0xdf, 0x6f, 0xfb, 0x02, 0xa3, 0x61, 0xcc, 0xb5, 0x7b, 0xbe, 0xa1, 0xdb, 0xda, + 0x8d, 0x8c, 0x46, 0x82, 0xcc, 0xd4, 0x81, 0x28, 0x6b, 0x6b, 0xc0, 0xf6, 0x96, 0xeb, 0x4d, 0x0b, 0xfc, 0xbc, 0x89, + 0xc1, 0xdb, 0xb3, 0xc6, 0x29, 0xad, 0xaf, 0x71, 0xcd, 0x71, 0x55, 0x88, 0xa8, 0x2d, 0x52, 0x00, 0x0c, 0x3b, 0x5f, + 0xe0, 0xce, 0xac, 0x30, 0x98, 0x13, 0x96, 0x4a, 0x76, 0x2a, 0xd7, 0x9f, 0xc3, 0x16, 0x07, 0xa9, 0x7c, 0xe9, 0xf5, + 0xf7, 0x5f, 0xbe, 0xf8, 0x02, 0xdd, 0xf6, 0x9c, 0x1f, 0x41, 0x90, 0x09, 0x74, 0x50, 0x53, 0xaa, 0xc7, 0x1f, 0x0a, + 0xa0, 0xf6, 0x30, 0x0f, 0x3f, 0x14, 0x4c, 0xc4, 0xd7, 0xd9, 0x65, 0x5c, 0xc9, 0x62, 0x74, 0xcd, 0x45, 0x2a, 0x0b, + 0x2b, 0x35, 0x0e, 0x4e, 0x57, 0xab, 0x9c, 0x07, 0x60, 0x2a, 0x6f, 0x19, 0x65, 0x27, 0x97, 0xd4, 0x83, 0xab, 0xe5, + 0xe9, 0x95, 0x16, 0x9d, 0x97, 0xd7, 0x97, 0x41, 0x84, 0xbf, 0xce, 0xcd, 0x8f, 0xab, 0xb8, 0xfc, 0x18, 0x44, 0xd6, + 0xa6, 0xce, 0xfc, 0x40, 0xa9, 0x3c, 0xf8, 0x3b, 0x81, 0x4c, 0xf7, 0x87, 0x02, 0x2c, 0xb3, 0x6d, 0xc5, 0xc7, 0x31, + 0xd6, 0x3a, 0x9c, 0x90, 0x99, 0x2a, 0xd1, 0x7b, 0x97, 0xac, 0x0b, 0xb0, 0xf6, 0x53, 0xd8, 0xce, 0x2a, 0xd7, 0x0c, + 0x2b, 0x53, 0x15, 0x19, 0x82, 0xb6, 0x66, 0x87, 0xa1, 0x75, 0xa2, 0x99, 0xa3, 0xb7, 0x80, 0x7e, 0x20, 0x87, 0x97, + 0x54, 0xae, 0x99, 0xe7, 0x63, 0xd3, 0x78, 0xfd, 0xe0, 0xf0, 0xd2, 0x13, 0x28, 0xd9, 0x3b, 0x39, 0x0a, 0x13, 0xc1, + 0xd3, 0xd8, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x1d, 0x34, 0x19, 0x8f, 0xa9, 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0x6c, + 0x9b, 0x3d, 0xac, 0x1e, 0x72, 0x72, 0xc8, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xcb, + 0xb5, 0x8d, 0x10, 0xaf, 0x9c, 0x1d, 0x9d, 0x97, 0x74, 0xeb, 0x9b, 0xd2, 0xd0, 0x6b, 0x09, 0xc0, 0x7c, 0xda, 0x80, + 0xbf, 0x60, 0x72, 0x3d, 0xaa, 0x78, 0x59, 0x81, 0x84, 0x05, 0x45, 0x78, 0x53, 0xec, 0x4d, 0xe1, 0x6e, 0x9c, 0x9e, + 0xc3, 0x0e, 0x5c, 0x4c, 0xd1, 0x1d, 0x27, 0x26, 0xb3, 0xd2, 0x68, 0x45, 0x23, 0xfd, 0xcb, 0xf5, 0x25, 0xd6, 0x7d, + 0xd1, 0xca, 0x3c, 0x9b, 0x53, 0x61, 0xd3, 0xbb, 0xca, 0xa5, 0x13, 0xf5, 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, + 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x51, 0x81, 0x84, 0x0c, 0x0c, 0x5f, 0x83, 0xb5, 0x28, 0xb9, 0xb1, 0x82, 0xf5, 0xee, + 0xf9, 0x3a, 0x41, 0x48, 0xc1, 0x03, 0x37, 0x41, 0xbf, 0xb4, 0x6e, 0xde, 0x8e, 0x12, 0x65, 0x10, 0x9f, 0x5c, 0x3b, + 0xe5, 0x20, 0x81, 0x00, 0x1c, 0x58, 0x15, 0x92, 0x44, 0x81, 0xce, 0x83, 0xab, 0x19, 0x47, 0xb0, 0x79, 0xe5, 0xcc, + 0xc5, 0x0d, 0xe0, 0xbc, 0xf2, 0xe7, 0xb2, 0xc1, 0x96, 0xf5, 0x88, 0x2a, 0x73, 0xc6, 0x29, 0x06, 0x75, 0xb2, 0x04, + 0x7d, 0x65, 0x29, 0xed, 0x25, 0x68, 0x1a, 0xaf, 0xd8, 0x4a, 0xf9, 0x00, 0xd0, 0x73, 0xb6, 0x52, 0xc6, 0xfe, 0xf8, + 0xf5, 0x19, 0x5b, 0x69, 0x69, 0xf0, 0xf4, 0x6a, 0x76, 0x3e, 0x3b, 0x1b, 0xb0, 0xa3, 0x28, 0xd4, 0x06, 0x0c, 0x81, + 0x8b, 0x4c, 0x10, 0x0c, 0x42, 0x8d, 0xff, 0x32, 0x50, 0x01, 0xc2, 0x88, 0xc7, 0x63, 0x23, 0x8e, 0x58, 0x38, 0x1e, + 0x62, 0x30, 0xb0, 0xe6, 0x0b, 0x12, 0x10, 0x6a, 0x4a, 0x43, 0x5f, 0xcf, 0x70, 0x38, 0x39, 0x98, 0x40, 0x2a, 0x66, + 0x66, 0xaa, 0x30, 0x36, 0x26, 0x11, 0xc4, 0x7f, 0xed, 0xac, 0x17, 0xca, 0xed, 0xae, 0xd1, 0x40, 0xd0, 0x0c, 0xbe, + 0xa8, 0xe2, 0xc9, 0xc1, 0xb0, 0xab, 0x62, 0x1c, 0x85, 0x6b, 0xa3, 0x7c, 0x3b, 0x3b, 0x06, 0x30, 0xdf, 0xb3, 0xa1, + 0x2f, 0x97, 0x38, 0x3b, 0x7c, 0x4c, 0x1e, 0x3e, 0x26, 0xf4, 0x8c, 0x9d, 0x7d, 0xf5, 0x98, 0x9e, 0x29, 0x72, 0x72, + 0x30, 0x89, 0xae, 0x99, 0xc5, 0xc0, 0x39, 0x52, 0x4d, 0xa0, 0x97, 0xa3, 0xb5, 0x50, 0x0b, 0x4c, 0x3b, 0x34, 0x85, + 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x75, 0xbb, 0xe9, 0xd7, 0xed, 0xb6, 0x7a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, 0x6e, 0x31, + 0x93, 0xbf, 0x8f, 0x0f, 0xdc, 0x1c, 0x60, 0x7d, 0xf7, 0x8f, 0x89, 0x69, 0xd2, 0xce, 0xa8, 0xf8, 0x35, 0x3d, 0xc2, + 0x3e, 0x34, 0x8b, 0xec, 0xe8, 0xc3, 0xf0, 0xdf, 0xea, 0x44, 0x7d, 0xf6, 0xd5, 0x11, 0x90, 0x23, 0x90, 0x81, 0x62, + 0x89, 0x60, 0x86, 0x03, 0x4d, 0x01, 0x05, 0x99, 0x1e, 0x77, 0xaa, 0x87, 0x5f, 0x8d, 0x9a, 0x9a, 0x91, 0x6b, 0x98, + 0x1a, 0x6c, 0x0b, 0x7e, 0xa0, 0xba, 0xa1, 0xbf, 0xd1, 0x68, 0x4f, 0xda, 0xc9, 0xcc, 0xbc, 0xa4, 0x36, 0xce, 0xdd, + 0x35, 0x04, 0x74, 0x76, 0x70, 0x8b, 0x92, 0x7d, 0x7d, 0x7c, 0x79, 0x80, 0xab, 0x08, 0x50, 0xc3, 0x58, 0xf0, 0xf5, + 0xe0, 0x52, 0x6f, 0xee, 0x83, 0x80, 0x0c, 0xbe, 0x0e, 0x4e, 0xbe, 0x1e, 0xc8, 0x41, 0x70, 0x7c, 0x78, 0x79, 0x12, + 0x38, 0xe3, 0x7e, 0x08, 0x79, 0xa9, 0x2a, 0x8a, 0x99, 0x30, 0x55, 0x24, 0xb6, 0xf6, 0xdc, 0xd6, 0xab, 0x8c, 0xcf, + 0x68, 0x3a, 0xb5, 0x48, 0xe8, 0x61, 0xca, 0x62, 0xf3, 0x3b, 0x98, 0xf0, 0xab, 0x20, 0x72, 0x41, 0x61, 0x67, 0x79, + 0x14, 0xd3, 0x25, 0xbb, 0x15, 0x61, 0x4a, 0x93, 0xc3, 0x9c, 0x90, 0x28, 0x5c, 0x2a, 0x30, 0x41, 0xf5, 0x3a, 0x81, + 0xb8, 0xb6, 0xee, 0xf3, 0x5b, 0x11, 0x2e, 0x69, 0x7e, 0x98, 0x90, 0x56, 0x11, 0x2e, 0x42, 0xcd, 0xa6, 0xa6, 0x17, + 0x2c, 0x5c, 0xd1, 0x4b, 0x34, 0xd5, 0x5c, 0x87, 0x97, 0xc0, 0xe5, 0xad, 0xe7, 0xab, 0x05, 0xbb, 0x6c, 0x48, 0xdf, + 0x0c, 0x5f, 0x7c, 0x61, 0x7d, 0xf2, 0x80, 0x87, 0x74, 0x7e, 0x78, 0x29, 0xd8, 0x00, 0x5c, 0x67, 0xfc, 0xe6, 0x3b, + 0x79, 0xab, 0xe7, 0xa5, 0x3d, 0xc5, 0x38, 0x33, 0xed, 0xc4, 0xa4, 0x9d, 0x90, 0xfb, 0xf7, 0x6d, 0xdf, 0xbd, 0x78, + 0xad, 0x5c, 0x56, 0x2d, 0x43, 0x12, 0xaf, 0x95, 0xeb, 0x34, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, + 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, 0x65, 0xa1, 0x70, 0xec, 0x5f, 0x65, 0x2c, 0x5e, 0x37, 0x90, 0x81, + 0x91, 0x7b, 0x7b, 0x95, 0x31, 0x2f, 0x06, 0x6d, 0xbe, 0xf6, 0x42, 0xf7, 0x79, 0xe9, 0xcb, 0x16, 0xef, 0xe5, 0x94, + 0x1a, 0x46, 0x22, 0x7a, 0x30, 0x56, 0x66, 0x94, 0x2a, 0x51, 0x6b, 0xd0, 0x88, 0x60, 0x63, 0x17, 0x0c, 0x14, 0x9c, + 0x50, 0xb9, 0xa7, 0xce, 0xf6, 0xed, 0x94, 0x4a, 0x0f, 0x68, 0x97, 0x1a, 0x55, 0xb9, 0x5b, 0x66, 0x92, 0x55, 0x83, + 0x60, 0xf4, 0x67, 0x29, 0xc5, 0x0c, 0xef, 0x8c, 0x2c, 0x98, 0x82, 0x95, 0xa0, 0xaa, 0x65, 0x58, 0x0e, 0x39, 0x6a, + 0xf1, 0x8c, 0x4f, 0xaa, 0xd4, 0x3f, 0x3a, 0x82, 0x06, 0xa7, 0xeb, 0x56, 0xd0, 0xe0, 0xc7, 0xe3, 0xc7, 0x7a, 0xa0, + 0xd7, 0x6b, 0xed, 0x78, 0xe8, 0xf3, 0xdb, 0x88, 0x37, 0xae, 0x7b, 0x4f, 0xb5, 0x56, 0xa1, 0x0c, 0xb4, 0x58, 0x51, + 0xb9, 0x52, 0x4b, 0xba, 0xdf, 0x45, 0x00, 0x2c, 0x62, 0x63, 0x36, 0xde, 0xb5, 0xcd, 0x0a, 0x41, 0xa3, 0xcb, 0x4e, + 0x36, 0xf1, 0x80, 0x25, 0xba, 0xb5, 0x83, 0x09, 0x8d, 0x4f, 0x58, 0xd9, 0xef, 0xe7, 0x27, 0x40, 0x4f, 0xb5, 0x11, + 0x53, 0x01, 0x47, 0xfe, 0x97, 0x56, 0x64, 0x8a, 0x02, 0x9b, 0x35, 0x75, 0xb7, 0xc6, 0x32, 0x12, 0x7d, 0x99, 0xd2, + 0xe5, 0x09, 0xcf, 0x80, 0xe9, 0x62, 0xdd, 0x72, 0x5c, 0xd9, 0x55, 0x1c, 0x79, 0x2a, 0x2c, 0x2b, 0xce, 0xab, 0x70, + 0xbc, 0xf5, 0xf8, 0x06, 0x87, 0x86, 0x4d, 0x5b, 0xf9, 0x43, 0x08, 0x0b, 0xe1, 0x55, 0x06, 0xb7, 0x11, 0x6d, 0x27, + 0x81, 0xca, 0x1b, 0x73, 0x9d, 0x50, 0x36, 0xb7, 0x17, 0x6b, 0xcf, 0x20, 0x9d, 0x98, 0x03, 0xa5, 0x1a, 0x41, 0x6b, + 0x34, 0x0b, 0xaa, 0x46, 0x3c, 0x72, 0xe6, 0x5f, 0xce, 0x20, 0x56, 0xcb, 0x97, 0x34, 0x95, 0xa2, 0x01, 0x18, 0x17, + 0xc0, 0xe5, 0xe9, 0x97, 0x77, 0x3f, 0xbd, 0xe7, 0x71, 0x91, 0x2c, 0xdf, 0xc6, 0x45, 0x7c, 0x55, 0x86, 0x1b, 0x35, + 0x46, 0x71, 0x4d, 0xa6, 0x62, 0xc0, 0xa4, 0x59, 0x49, 0xcd, 0x5d, 0xa9, 0x09, 0x31, 0xd6, 0x99, 0xac, 0xcb, 0x4a, + 0x5e, 0x35, 0x2a, 0x5d, 0x17, 0x19, 0x7e, 0xdc, 0xf2, 0x39, 0x3d, 0x04, 0x60, 0x53, 0xe3, 0x42, 0x1a, 0x49, 0x5d, + 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, 0xba, 0x5e, 0xb2, 0x27, 0xe3, 0x47, 0xd3, 0x57, 0x59, 0x98, 0x0d, + 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8d, 0xc7, 0x64, + 0xd3, 0x16, 0x0f, 0xf0, 0x30, 0x5d, 0x87, 0x05, 0x99, 0xe9, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, 0x2a, 0x00, 0x64, 0x4b, + 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0x93, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, 0x37, 0xf3, 0xd2, 0xf7, + 0x28, 0x92, 0xc6, 0x65, 0x69, 0xa7, 0x52, 0xa9, 0xf6, 0xcc, 0xcc, 0x75, 0x0d, 0x62, 0x52, 0x84, 0xba, 0xee, 0xd2, + 0xab, 0x7b, 0xb7, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, 0xba, 0x22, 0x6a, 0x7a, + 0xb9, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xeb, 0x35, 0x05, 0xa5, 0x60, 0xb4, 0x5a, 0x7b, 0x0b, 0xf7, 0xa9, 0x6c, + 0x5c, 0x58, 0x32, 0xbd, 0x5a, 0x94, 0x94, 0x50, 0xdd, 0x54, 0x8c, 0x94, 0x30, 0x52, 0x1a, 0x9e, 0xca, 0xf7, 0x02, + 0x8f, 0xf3, 0x3c, 0x88, 0x5a, 0x5e, 0x60, 0xa7, 0x15, 0x39, 0x05, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, + 0x05, 0xea, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, 0xbf, 0x15, 0x2c, 0xf0, 0xf8, 0xd6, 0x2b, 0xdc, 0x46, 0xbf, 0x15, + 0x3e, 0x2d, 0x7d, 0x23, 0x7d, 0x57, 0x17, 0x4f, 0xda, 0x9b, 0x8d, 0x92, 0x65, 0x96, 0xa7, 0xaf, 0x65, 0xca, 0x41, + 0x64, 0x86, 0xd6, 0xa0, 0xec, 0x44, 0x34, 0x6e, 0x78, 0x60, 0xc4, 0xd8, 0xb8, 0xf1, 0xfd, 0x98, 0x81, 0x6c, 0x18, + 0xac, 0xbe, 0x59, 0x2a, 0x93, 0x35, 0x20, 0x6c, 0x68, 0xf9, 0x89, 0xc6, 0xdb, 0x08, 0xf5, 0xf5, 0x0b, 0xdc, 0xe6, + 0x4a, 0xdf, 0xe7, 0xfc, 0xc7, 0x8c, 0xfe, 0x88, 0xc0, 0x2f, 0xf1, 0x0a, 0xe4, 0x1e, 0x4f, 0xa1, 0x6e, 0x84, 0xed, + 0xe5, 0x18, 0x2c, 0x09, 0xd1, 0x51, 0x44, 0xc5, 0x02, 0x05, 0x4d, 0x61, 0x10, 0x45, 0xd4, 0x05, 0x73, 0x78, 0x9e, + 0xcb, 0xe4, 0xe3, 0xd4, 0xf8, 0xcc, 0x0f, 0x63, 0x8c, 0x21, 0x1d, 0x0c, 0xc2, 0x6a, 0x16, 0x0c, 0xc7, 0xa3, 0xc9, + 0xd1, 0x13, 0x38, 0xb7, 0x83, 0x71, 0x40, 0x06, 0x41, 0x5d, 0xae, 0x62, 0x41, 0xcb, 0xeb, 0x4b, 0x5b, 0x06, 0x7e, + 0x5c, 0x07, 0x83, 0xdf, 0x0a, 0x4f, 0xf1, 0x0e, 0x9a, 0x93, 0x3b, 0x19, 0x06, 0x01, 0xbd, 0x5c, 0x13, 0x90, 0x94, + 0xf5, 0x34, 0x3f, 0xa9, 0x0f, 0x37, 0xa6, 0xb4, 0x7f, 0xe6, 0xf0, 0x82, 0xc3, 0x0e, 0x09, 0x14, 0x48, 0xe3, 0x69, + 0x36, 0x7a, 0xa9, 0x14, 0xb9, 0x6f, 0x0b, 0x0e, 0x77, 0xe6, 0x9e, 0x33, 0x3d, 0x72, 0x0a, 0x89, 0x66, 0x16, 0x70, + 0x23, 0x7f, 0x29, 0xae, 0xe3, 0x3c, 0x4b, 0x0f, 0x9a, 0x6f, 0x0e, 0xca, 0x3b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, 0x58, + 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xc7, 0xcc, 0x64, 0xc6, 0x23, 0xf0, 0x08, + 0x6c, 0xfa, 0x40, 0x16, 0x77, 0xce, 0x25, 0xc9, 0xdf, 0x4c, 0xa5, 0xbd, 0xea, 0x95, 0x3b, 0x05, 0x59, 0xaf, 0xb6, + 0x72, 0xd7, 0xad, 0xcf, 0xbe, 0xe9, 0xf0, 0x0a, 0x3c, 0x93, 0xe0, 0x16, 0xd9, 0xef, 0x37, 0x05, 0x95, 0xc2, 0xa8, + 0x88, 0x77, 0x92, 0x6b, 0xf4, 0x6f, 0xf7, 0xc6, 0x46, 0x91, 0xdc, 0xf2, 0xfe, 0x01, 0xd4, 0x99, 0xbc, 0x2b, 0x6e, + 0xe7, 0x10, 0xb5, 0x75, 0x37, 0x1e, 0x78, 0x6f, 0xd0, 0x2e, 0x6b, 0x8e, 0x60, 0xcb, 0x8b, 0x83, 0x0c, 0xc6, 0x02, + 0x67, 0x65, 0xa4, 0xd4, 0xb8, 0x56, 0x46, 0x03, 0x6a, 0x93, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, + 0x99, 0xc6, 0xdb, 0x40, 0xec, 0xb7, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, + 0xd7, 0xc6, 0xd4, 0x40, 0x43, 0x0f, 0xa2, 0x46, 0x2a, 0xe2, 0xec, 0xe4, 0x29, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, + 0xca, 0x8e, 0x17, 0x13, 0x82, 0x27, 0xef, 0xf3, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x45, 0x8a, 0x86, 0x50, 0x89, 0x14, + 0xd1, 0x6b, 0x88, 0x2f, 0x58, 0xe2, 0xef, 0x32, 0x7a, 0x97, 0xd2, 0x38, 0x4d, 0x31, 0xfd, 0x59, 0x01, 0x3f, 0x9f, + 0x02, 0xca, 0x25, 0xee, 0x84, 0xe8, 0x4c, 0x82, 0xbd, 0x1a, 0x44, 0xf7, 0xaa, 0x38, 0x60, 0x8a, 0x46, 0xb7, 0x82, + 0x22, 0x66, 0x1d, 0x66, 0xff, 0xa5, 0x40, 0xa1, 0x90, 0x2a, 0xe6, 0x57, 0x61, 0x1f, 0xa2, 0x6a, 0x0d, 0xe5, 0x9c, + 0xbe, 0x7d, 0x69, 0x86, 0x34, 0xba, 0x95, 0x54, 0x6f, 0x6d, 0x3c, 0xb6, 0x10, 0xa5, 0x27, 0xba, 0x5a, 0xd3, 0xb3, + 0x78, 0x95, 0x45, 0x1b, 0xc0, 0x9f, 0x78, 0xfb, 0xf2, 0xa9, 0xb2, 0x30, 0x79, 0x99, 0x81, 0xe2, 0xe0, 0xf4, 0xed, + 0xcb, 0x57, 0x32, 0x5d, 0xe7, 0x3c, 0xba, 0x93, 0x48, 0x5a, 0x4f, 0xdf, 0xbe, 0xfc, 0x19, 0xcd, 0xbd, 0xde, 0x15, + 0xf0, 0xfe, 0x05, 0xf0, 0x96, 0x51, 0xb2, 0x86, 0x3e, 0xa9, 0xdf, 0xf9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xff, + 0x4c, 0x6b, 0x4f, 0x5a, 0xf5, 0x57, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, + 0x41, 0xf4, 0xf5, 0xc1, 0xed, 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0x0e, 0x0f, 0x6f, 0x6e, 0x6e, + 0x46, 0x37, 0x8f, 0x46, 0xb2, 0xb8, 0x3c, 0x9c, 0x7c, 0xfb, 0xed, 0xb7, 0x87, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, + 0x5e, 0x11, 0x3e, 0x60, 0x01, 0x22, 0x76, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, + 0xce, 0xd7, 0xc7, 0xe5, 0xf5, 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0xa3, 0xf1, 0x78, 0x7c, 0x08, 0x12, 0xa8, 0xaf, 0x07, + 0x7c, 0x10, 0x9c, 0x04, 0x83, 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x49, 0xe0, 0x19, 0xd8, 0x36, 0x58, 0x44, 0x07, + 0xe2, 0x12, 0x1c, 0x5e, 0xd2, 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0xa3, 0x27, 0x7e, 0xda, 0xff, + 0x52, 0x69, 0x8f, 0xfc, 0xb4, 0x63, 0x4c, 0x7b, 0xf4, 0xd4, 0x4f, 0x3b, 0x51, 0x69, 0xcf, 0xfd, 0xb4, 0xff, 0x5d, + 0x0e, 0x20, 0xf5, 0xc0, 0xb7, 0xfe, 0x3b, 0xf3, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, + 0xb8, 0xbd, 0xca, 0x69, 0x30, 0xc0, 0xf6, 0x7a, 0x46, 0x1e, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, + 0x60, 0x21, 0x83, 0xaf, 0x03, 0xf2, 0xb5, 0x3e, 0xd2, 0xae, 0x05, 0xdb, 0x04, 0x2e, 0x34, 0xeb, 0xd0, 0x06, 0x4c, + 0xf3, 0xa5, 0x71, 0x35, 0xfd, 0xbd, 0xe8, 0xce, 0x86, 0xb7, 0x44, 0xe5, 0xa6, 0x1b, 0xd4, 0xf4, 0x01, 0x78, 0x27, + 0x40, 0xa3, 0xa2, 0xe0, 0x3a, 0x2e, 0xc2, 0xe1, 0xb0, 0xbc, 0xbe, 0x24, 0x60, 0x97, 0xb9, 0xe2, 0x71, 0x15, 0x05, + 0x42, 0x0e, 0xd5, 0xcf, 0x40, 0x45, 0x02, 0x0b, 0x10, 0xca, 0x08, 0xfe, 0x0b, 0x6a, 0xfa, 0x56, 0xb2, 0x4d, 0x30, + 0xbc, 0xe1, 0xe7, 0x1f, 0xb3, 0x6a, 0xa8, 0x44, 0x8b, 0xd7, 0x82, 0xc2, 0x0f, 0xf8, 0xeb, 0xaa, 0x8e, 0x7e, 0x07, + 0x37, 0xee, 0xa6, 0x86, 0xfd, 0xad, 0xf4, 0x1c, 0xda, 0xe4, 0x3c, 0x5b, 0x4c, 0x5b, 0x07, 0xfa, 0x03, 0x49, 0xaa, + 0x79, 0x36, 0x08, 0x86, 0xc1, 0x80, 0x2f, 0xd8, 0x03, 0x39, 0xe7, 0x9e, 0xf9, 0xd4, 0xa9, 0xf4, 0xa7, 0x79, 0x96, + 0x0d, 0xc0, 0x37, 0x05, 0xf9, 0x91, 0xc3, 0xff, 0x9e, 0x0f, 0x51, 0x78, 0x38, 0x78, 0x70, 0x48, 0x66, 0xc1, 0xea, + 0x16, 0x3d, 0x3a, 0xa3, 0x20, 0x13, 0x4b, 0x5e, 0x64, 0x95, 0xb7, 0x54, 0x6e, 0xd7, 0x6d, 0x2f, 0x8f, 0xbd, 0x67, + 0xf3, 0x2a, 0x16, 0x81, 0x3a, 0xe7, 0x40, 0xf1, 0x86, 0xb2, 0xa7, 0xb2, 0x29, 0x21, 0xd5, 0x86, 0xbc, 0x61, 0x39, + 0x60, 0xc1, 0x71, 0x6f, 0x38, 0x3c, 0x08, 0x06, 0x4e, 0x9d, 0x3b, 0x08, 0x0e, 0x86, 0xc3, 0x93, 0xc0, 0xdd, 0x87, + 0xb2, 0x91, 0xbb, 0x33, 0xd2, 0x82, 0xfd, 0x55, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, + 0x00, 0xe8, 0x23, 0x25, 0x01, 0x33, 0xb0, 0x32, 0x03, 0x08, 0x55, 0x4e, 0x63, 0x76, 0x07, 0xcc, 0x23, 0x70, 0xcc, + 0x0a, 0x26, 0x0b, 0x10, 0x4b, 0x02, 0x9c, 0xbb, 0x20, 0x8a, 0x75, 0x21, 0xa7, 0x10, 0x04, 0x00, 0x7f, 0x12, 0x53, + 0x0a, 0x26, 0xe9, 0xd8, 0x8d, 0x20, 0x88, 0xe3, 0xb3, 0x6b, 0xd1, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, + 0x10, 0x03, 0xc3, 0x07, 0xf7, 0x73, 0x50, 0x7a, 0x58, 0xbd, 0x13, 0x72, 0xc1, 0x77, 0xdc, 0xb1, 0x50, 0xd7, 0x70, + 0xf5, 0x84, 0x83, 0xe0, 0x8e, 0x6b, 0x16, 0x60, 0x54, 0x15, 0xeb, 0xb2, 0xe2, 0xe9, 0x87, 0xbb, 0x15, 0xc4, 0x02, + 0xc4, 0x01, 0x7d, 0x2b, 0xf3, 0x2c, 0xb9, 0x0b, 0x9d, 0x3d, 0xd7, 0x46, 0xa5, 0xff, 0xf0, 0xe1, 0xd5, 0x4f, 0x11, + 0x88, 0x1c, 0x6b, 0x43, 0xe9, 0xef, 0x38, 0x9e, 0x4d, 0x7e, 0xc4, 0x2b, 0x7f, 0x63, 0xdf, 0x71, 0x7b, 0x7a, 0xf4, + 0xfb, 0x50, 0x37, 0xbd, 0xe3, 0xb3, 0x3b, 0x3e, 0x72, 0xc5, 0xa1, 0xba, 0xc2, 0x7d, 0xfd, 0x71, 0xed, 0x1b, 0x21, + 0xdd, 0x3f, 0xcf, 0x94, 0x37, 0xe6, 0x47, 0x3b, 0x18, 0x06, 0xc1, 0x54, 0x0b, 0x25, 0x21, 0x0a, 0x09, 0x53, 0x02, + 0x86, 0xe8, 0x40, 0x2f, 0xab, 0x29, 0x72, 0x6e, 0x6a, 0x64, 0xe1, 0xfd, 0x80, 0x69, 0xa1, 0x43, 0x23, 0x87, 0xf2, + 0x83, 0xc3, 0x09, 0x63, 0x16, 0x7e, 0xab, 0x84, 0xe9, 0x57, 0x8b, 0xca, 0x39, 0x88, 0x1e, 0x80, 0x31, 0xae, 0xe0, + 0x05, 0x74, 0x85, 0xdd, 0xac, 0x55, 0x94, 0x10, 0x04, 0xd3, 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, 0xaa, + 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, 0x06, 0x7e, 0xc9, 0x7e, 0x29, 0xd0, 0xb3, 0x7c, 0x2a, + 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0xb8, 0x7e, 0x3c, + 0x7d, 0x25, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, 0xc5, 0x44, 0xc1, 0x3e, 0x42, 0xbf, 0xda, 0x36, 0xfa, + 0xec, 0x76, 0xad, 0x37, 0x83, 0x12, 0x1d, 0xf3, 0x1a, 0x05, 0xd7, 0x4a, 0xa1, 0x60, 0xb4, 0xb7, 0xf1, 0x67, 0x38, + 0x72, 0xab, 0xdb, 0x43, 0xef, 0xb7, 0x2a, 0xbe, 0x7c, 0x8d, 0xbe, 0x9d, 0xf6, 0xe7, 0xa8, 0x92, 0xbf, 0xac, 0x56, + 0xe0, 0x43, 0x05, 0x91, 0x56, 0x2c, 0x4e, 0x2f, 0xd4, 0xf3, 0xfe, 0xed, 0xe9, 0x6b, 0xf0, 0xa3, 0xc4, 0xdf, 0xbf, + 0x7e, 0x1f, 0xd4, 0x64, 0x1a, 0xcf, 0x0a, 0xf3, 0xa1, 0xcd, 0x01, 0xa1, 0x5a, 0x5c, 0x9a, 0x7d, 0x3f, 0x8b, 0x9b, + 0xec, 0xbb, 0x66, 0xeb, 0x69, 0xd1, 0x44, 0x92, 0x32, 0xdc, 0x3e, 0x18, 0x10, 0xe8, 0x03, 0x44, 0x71, 0xf6, 0x05, + 0x8d, 0x21, 0xcd, 0x67, 0xf6, 0xfd, 0x08, 0x81, 0x2f, 0x77, 0x42, 0xaa, 0x71, 0x85, 0x45, 0xa3, 0x87, 0x7c, 0xc6, + 0x23, 0x65, 0x58, 0xf4, 0x0e, 0x13, 0x88, 0x33, 0x9c, 0x56, 0xef, 0x11, 0x03, 0x1a, 0xef, 0x06, 0x5a, 0xf6, 0x10, + 0x65, 0xd4, 0x65, 0x6f, 0x58, 0x7c, 0xbf, 0x5f, 0x87, 0x99, 0xb5, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x1b, 0x80, 0x53, + 0x8e, 0x2c, 0x5f, 0x65, 0x36, 0xba, 0x5a, 0x62, 0x7a, 0x13, 0x41, 0x6c, 0x22, 0x9d, 0x0e, 0x6b, 0x57, 0xa7, 0xea, + 0x5d, 0xed, 0x7c, 0x26, 0x7a, 0x15, 0x68, 0xe5, 0xda, 0xf6, 0x78, 0x08, 0xff, 0xa9, 0xa5, 0x15, 0x36, 0xc2, 0x9e, + 0x8b, 0x2f, 0x3c, 0xc7, 0xe6, 0x04, 0x34, 0xb8, 0x92, 0x29, 0x00, 0x67, 0x69, 0x35, 0x1a, 0x35, 0xc2, 0x3e, 0x2b, + 0xe7, 0x73, 0xd8, 0x5a, 0x88, 0xa7, 0x05, 0xe0, 0xc0, 0x4d, 0x4c, 0x4e, 0xde, 0x8d, 0xc9, 0x39, 0xfd, 0xa8, 0xe0, + 0xbe, 0x83, 0xb3, 0x72, 0x19, 0xa7, 0xf2, 0x06, 0xb0, 0x29, 0x03, 0x3f, 0x15, 0x4b, 0xf5, 0x12, 0x92, 0x25, 0x4f, + 0x3e, 0xa2, 0xd5, 0x46, 0x1a, 0x00, 0x57, 0x39, 0x35, 0x96, 0x7b, 0x0a, 0x34, 0xd5, 0x95, 0xa2, 0x12, 0xe2, 0xaa, + 0x8a, 0x93, 0xe5, 0x7b, 0x4c, 0x0d, 0x37, 0xd0, 0x8b, 0x28, 0x90, 0x2b, 0x2e, 0x80, 0xa4, 0xe7, 0xec, 0x5f, 0x99, + 0xc6, 0x5e, 0x7f, 0x23, 0x51, 0xc0, 0xa4, 0x51, 0x94, 0xb1, 0x52, 0xf6, 0x52, 0x9a, 0xe8, 0x77, 0x41, 0x50, 0xbb, + 0x97, 0x7f, 0x41, 0xdd, 0x4f, 0xa1, 0x15, 0x61, 0x03, 0xbc, 0x50, 0x83, 0x1f, 0xa6, 0x76, 0xc9, 0x79, 0x40, 0x86, + 0xce, 0xfb, 0xac, 0xb6, 0x5b, 0xfd, 0xe9, 0x12, 0xb0, 0x5e, 0x53, 0xe3, 0x53, 0x18, 0x26, 0xc4, 0xc4, 0x4a, 0xb6, + 0xca, 0x4a, 0xbb, 0xa1, 0x4c, 0x3b, 0xe9, 0x92, 0x79, 0x2d, 0x9c, 0xe6, 0x3d, 0xc6, 0x96, 0x23, 0x95, 0xbb, 0xdf, + 0x0f, 0xcd, 0x4f, 0x96, 0xd3, 0x37, 0x3a, 0x84, 0xb5, 0x37, 0x1e, 0x34, 0x27, 0x5a, 0x5d, 0xd5, 0xd1, 0x0f, 0xe8, + 0x00, 0xcc, 0xb4, 0x45, 0xa8, 0x74, 0xc1, 0xb7, 0x7d, 0x25, 0x2a, 0x2e, 0x49, 0x58, 0x2a, 0x09, 0xec, 0xec, 0xa6, + 0x64, 0x67, 0x13, 0x10, 0xcf, 0x70, 0xd7, 0xd3, 0x62, 0x27, 0xa4, 0x09, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x55, + 0x97, 0x90, 0x8d, 0x31, 0x74, 0xf1, 0x2f, 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x09, 0x0a, 0x55, 0xee, 0xb6, + 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, 0x37, 0xea, 0x66, 0xd4, 0x54, 0x75, 0xea, 0x25, 0xf8, 0x38, 0xcd, 0xba, + 0x0a, 0x32, 0x0b, 0xbb, 0x2a, 0xd6, 0x3c, 0xd0, 0xb1, 0xba, 0x94, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x23, 0x63, + 0x6c, 0x61, 0x0d, 0x47, 0xda, 0x1e, 0x37, 0x3d, 0x41, 0xe8, 0x27, 0x6c, 0x28, 0x81, 0x9b, 0xce, 0xf6, 0xd4, 0x34, + 0xf3, 0x01, 0x11, 0x87, 0x01, 0x05, 0x92, 0x8d, 0x43, 0x9a, 0x23, 0x7d, 0x41, 0xd2, 0x84, 0x81, 0xb2, 0x15, 0xcf, + 0x09, 0xb2, 0xa2, 0xd0, 0xb3, 0x75, 0x55, 0x43, 0xfc, 0x5c, 0x86, 0x39, 0x5a, 0x72, 0x2a, 0x3c, 0x4d, 0x90, 0x89, + 0xed, 0x69, 0x9b, 0x99, 0x0c, 0x47, 0xc9, 0x02, 0xf3, 0x2b, 0x88, 0x12, 0x77, 0xa6, 0x59, 0x95, 0x83, 0x71, 0x01, + 0x0b, 0xb4, 0xf2, 0x3d, 0xa8, 0x1b, 0x6b, 0x68, 0xa3, 0x61, 0x99, 0xdd, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, + 0x29, 0x96, 0x97, 0x29, 0x44, 0x7b, 0x21, 0xf3, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x18, 0x12, 0xd6, 0x51, 0xf6, 0xa4, + 0x4d, 0x0d, 0xa0, 0xa7, 0x5e, 0x00, 0xf8, 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf7, 0x57, 0x05, 0xe3, 0xd2, 0x0d, 0x82, + 0x14, 0xbd, 0x49, 0xc1, 0x9c, 0xd7, 0xa3, 0xa4, 0xde, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, + 0x93, 0x57, 0x52, 0x13, 0x9b, 0x30, 0xc1, 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x36, 0x0d, 0x93, 0x36, + 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0x09, 0x81, 0xca, 0x5e, 0xe2, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0x1b, + 0x0d, 0x4c, 0xdc, 0xea, 0xca, 0xd6, 0x61, 0x42, 0xc3, 0x25, 0xd5, 0xce, 0x4e, 0x2a, 0xf9, 0xa2, 0xbd, 0x2e, 0x2f, + 0x6c, 0x1f, 0x74, 0x2c, 0xb5, 0xae, 0xe1, 0x81, 0xe6, 0x35, 0xbb, 0xb8, 0x62, 0x9a, 0x26, 0x1a, 0xeb, 0x21, 0x65, + 0xc9, 0xb1, 0xae, 0xa7, 0x2b, 0x5c, 0x2d, 0x33, 0x0d, 0x74, 0x2f, 0xf1, 0x42, 0x0f, 0xf8, 0xe0, 0xe1, 0x8a, 0x44, + 0x17, 0xd8, 0x6c, 0xb6, 0xaa, 0xc9, 0x34, 0xdf, 0x97, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, + 0x69, 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, + 0xe8, 0xde, 0xf9, 0x22, 0x75, 0xf3, 0x0b, 0xb0, 0x8d, 0xda, 0x18, 0xd3, 0x2c, 0xb1, 0x0e, 0x13, 0x65, 0x61, 0x8d, + 0x2c, 0xe4, 0x12, 0x7c, 0x30, 0x77, 0x9b, 0x3a, 0x7d, 0xde, 0x41, 0x84, 0xfd, 0x2e, 0x7a, 0x3c, 0xc2, 0x58, 0xb1, + 0x06, 0x89, 0x61, 0x15, 0xd6, 0xb4, 0xb9, 0x1c, 0xa2, 0x9c, 0x9a, 0x25, 0x13, 0x2d, 0xa9, 0x4f, 0x29, 0xa2, 0x14, + 0xcc, 0x8d, 0xa7, 0x65, 0xc3, 0x94, 0x10, 0x21, 0x2b, 0xa4, 0x03, 0xaa, 0xb5, 0xd0, 0x52, 0x4d, 0x10, 0xf0, 0xd0, + 0xcb, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0xc8, 0x70, 0x23, 0x8e, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x74, 0xb7, 0x97, + 0x17, 0x56, 0x9f, 0x96, 0x6d, 0x75, 0x10, 0xd7, 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, + 0x67, 0x11, 0xfa, 0x76, 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0x48, 0xeb, 0x35, 0x15, 0x03, 0xd4, 0xce, 0x63, 0x17, + 0xb1, 0x4a, 0x77, 0x0b, 0x51, 0xde, 0xa8, 0xac, 0xdf, 0xaf, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0xfe, 0x6a, + 0xbd, 0x07, 0x02, 0xfd, 0xe9, 0xfa, 0xb3, 0x10, 0xe8, 0xcf, 0xb2, 0x2f, 0x81, 0x40, 0x7f, 0xba, 0xfe, 0x9f, 0x86, + 0x40, 0x7f, 0xb5, 0xf6, 0x20, 0xd0, 0xd5, 0x60, 0xfc, 0xa3, 0x60, 0xc1, 0x9b, 0xd7, 0x01, 0x7d, 0x26, 0x59, 0xf0, + 0xe6, 0xc5, 0x0b, 0x4f, 0x98, 0xfe, 0x83, 0xd0, 0x48, 0xfe, 0x46, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, + 0x3e, 0x50, 0x51, 0x06, 0x40, 0xf4, 0xe5, 0x6f, 0x59, 0xb5, 0x0c, 0x83, 0xc3, 0x80, 0xcc, 0x1c, 0x24, 0xe8, 0x70, + 0xd2, 0xb8, 0xbd, 0xfd, 0x22, 0x1a, 0x42, 0x1d, 0x1b, 0x79, 0x00, 0xbe, 0xf2, 0x44, 0xf6, 0xfe, 0x0d, 0x11, 0x3f, + 0x99, 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x0f, 0xd6, 0x9e, + 0x6d, 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, + 0xe5, 0xbf, 0xbc, 0x7b, 0x69, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, + 0xfe, 0x78, 0xb0, 0xe9, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x93, + 0xd5, 0x87, 0x0f, 0x36, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x53, 0xc2, 0x0f, 0x5e, 0xff, + 0xe1, 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, + 0xa8, 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, + 0x9d, 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, + 0x2e, 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xbb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, + 0x79, 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0x7c, 0xff, 0x45, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, + 0x2e, 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, + 0x95, 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0xc9, 0x84, + 0x5d, 0x5e, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc6, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, + 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x0a, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x41, 0x9d, 0x95, + 0xe0, 0x49, 0xe5, 0x71, 0xe2, 0x2a, 0x16, 0x40, 0x46, 0x4d, 0x34, 0x80, 0x8e, 0x1c, 0x34, 0xb4, 0x7b, 0x4d, 0x3b, + 0x96, 0x1b, 0x95, 0x45, 0x06, 0x96, 0xb0, 0xcf, 0xa1, 0x74, 0x40, 0x6c, 0x87, 0x70, 0x21, 0x70, 0xf5, 0xc4, 0xab, + 0x51, 0x03, 0xb1, 0x87, 0x96, 0xbe, 0xbb, 0x90, 0x62, 0xb5, 0x0c, 0xda, 0x65, 0x63, 0x98, 0xf0, 0x7a, 0x8d, 0x2e, + 0xc3, 0xa0, 0xf8, 0x2f, 0xdc, 0xa2, 0x44, 0x5c, 0xa4, 0x2c, 0x55, 0x46, 0x67, 0x3d, 0x94, 0x85, 0xe1, 0xb3, 0xa7, + 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0x8d, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, + 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0xdd, 0xc2, 0xc0, 0x5d, 0xe8, 0xb2, + 0x5a, 0x93, 0xb8, 0xf7, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, + 0x6a, 0x7f, 0xab, 0x7d, 0xe2, 0x9e, 0x6d, 0xd7, 0x68, 0xd3, 0xcf, 0xa1, 0x5d, 0x23, 0x35, 0x4b, 0xa9, 0xe0, 0x7f, + 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0xd4, 0x87, 0x91, 0x26, 0xd1, 0x0a, 0x09, 0x4a, 0x51, 0xdf, + 0xd6, 0x0b, 0xd5, 0x06, 0x42, 0xd4, 0x6d, 0x31, 0x4d, 0x9f, 0x23, 0x68, 0x3b, 0x48, 0x49, 0x70, 0x6f, 0xd9, 0x98, + 0x5f, 0x5d, 0xcb, 0x67, 0x0e, 0xdd, 0x59, 0xcc, 0x3e, 0x97, 0x61, 0x30, 0x88, 0x3e, 0x97, 0x85, 0x4d, 0xee, 0x59, + 0xa5, 0x2a, 0xcb, 0xb1, 0xb1, 0xbd, 0x9c, 0xa2, 0x29, 0x4b, 0xf8, 0x76, 0x1d, 0x36, 0xd7, 0x3e, 0xc5, 0xd9, 0xa7, + 0x9b, 0x2b, 0x5e, 0x2d, 0x65, 0x1a, 0x05, 0xdf, 0x3f, 0xff, 0x10, 0x18, 0xd5, 0x75, 0xa1, 0x41, 0x8b, 0xb4, 0x36, + 0x27, 0x97, 0x97, 0x20, 0xcb, 0xec, 0x15, 0x23, 0xf9, 0x71, 0x27, 0xca, 0xe7, 0x1f, 0x3f, 0x7c, 0xf8, 0xf0, 0xf6, + 0x00, 0x15, 0x3e, 0xbd, 0x83, 0xf7, 0x0a, 0x3d, 0xe0, 0xe0, 0xc1, 0xa6, 0xd0, 0x2a, 0xf6, 0xfa, 0x0f, 0x7b, 0x56, + 0x15, 0x2d, 0x05, 0xb9, 0x01, 0x05, 0xf4, 0xaa, 0x68, 0x0d, 0x6b, 0xe1, 0xb4, 0xd8, 0x7e, 0x66, 0xa5, 0x5d, 0x0a, + 0x50, 0x77, 0xa2, 0x6a, 0x8e, 0x94, 0x5e, 0x1e, 0x22, 0x2d, 0x84, 0xd5, 0x9e, 0xad, 0x56, 0x75, 0x6d, 0x35, 0x59, + 0x54, 0x99, 0xb8, 0x3c, 0xc3, 0xdd, 0xff, 0x45, 0x5b, 0xce, 0xcc, 0xb0, 0xa2, 0x17, 0xed, 0xdd, 0xd6, 0x80, 0x2a, + 0xd3, 0x46, 0xb9, 0x7a, 0x0f, 0x81, 0xc0, 0xac, 0xac, 0xa7, 0xfe, 0xc7, 0xc6, 0x62, 0xc4, 0x4f, 0x53, 0x40, 0x6e, + 0xc0, 0x03, 0xb1, 0x93, 0x78, 0x64, 0xda, 0x77, 0x83, 0x72, 0x93, 0xe3, 0xa4, 0x95, 0x30, 0x1b, 0x4e, 0xa2, 0x09, + 0xb1, 0xf1, 0x25, 0x34, 0x0d, 0xfb, 0x7e, 0xf4, 0xfc, 0xf5, 0x87, 0x97, 0x1f, 0xfe, 0x79, 0xf6, 0xf4, 0xf4, 0xc3, + 0xf3, 0xef, 0xdf, 0xbc, 0x7b, 0xf9, 0xfc, 0x3d, 0x9e, 0x10, 0x1a, 0xb0, 0x32, 0xdc, 0x68, 0xab, 0xe8, 0x66, 0x59, + 0x91, 0xa8, 0x49, 0xb3, 0x29, 0x0a, 0x31, 0x0a, 0x33, 0xdb, 0x22, 0x7f, 0x79, 0xfd, 0xec, 0xf9, 0x8b, 0x97, 0xaf, + 0x9f, 0x3f, 0x6b, 0x7f, 0x3d, 0x9c, 0xd4, 0xa4, 0x76, 0x33, 0xa7, 0x23, 0xa4, 0x70, 0x3b, 0x5e, 0x1d, 0xf4, 0x09, + 0xb5, 0xf2, 0x3e, 0x7d, 0xca, 0x60, 0x45, 0x32, 0x25, 0xa7, 0xc7, 0xdf, 0x1e, 0xfe, 0xaf, 0xda, 0x78, 0xdb, 0x2d, + 0xf0, 0x10, 0x48, 0xc6, 0x94, 0xac, 0x1f, 0x46, 0x35, 0xa3, 0xea, 0x65, 0x24, 0xa8, 0x2d, 0x0d, 0x6c, 0xa0, 0x53, + 0xaa, 0x42, 0x2a, 0x9c, 0x25, 0x71, 0xc5, 0x2f, 0x65, 0x71, 0x17, 0x65, 0xa3, 0x56, 0x0a, 0x6d, 0x2c, 0x80, 0x28, + 0x04, 0xc1, 0x72, 0x23, 0x89, 0xf4, 0x14, 0x01, 0xf0, 0x86, 0xc0, 0x8d, 0xea, 0xdc, 0x45, 0x0b, 0x68, 0x17, 0x4c, + 0x16, 0xdb, 0x6d, 0xc7, 0xa0, 0x75, 0xd2, 0xbe, 0x68, 0x9e, 0x29, 0xa2, 0xb8, 0x00, 0xc6, 0x1c, 0x8e, 0x37, 0x75, + 0x76, 0x31, 0x73, 0xdc, 0x9d, 0xea, 0xa8, 0x9f, 0x60, 0x8d, 0xe8, 0x5e, 0x9b, 0xc0, 0x32, 0xcd, 0xf3, 0x70, 0xdc, + 0xa2, 0xb8, 0x06, 0xe3, 0xb7, 0x95, 0xaa, 0x96, 0x99, 0xc6, 0x56, 0x84, 0x99, 0x82, 0x70, 0x5c, 0x46, 0x74, 0x1b, + 0xe6, 0x60, 0x21, 0xd3, 0x98, 0x5f, 0x33, 0x0e, 0x79, 0x24, 0x0d, 0x4c, 0x1e, 0x98, 0x0c, 0xee, 0xc9, 0xb5, 0x8c, + 0x8a, 0x06, 0xe0, 0xa5, 0x6c, 0x0e, 0xea, 0xf1, 0xff, 0x69, 0xef, 0x69, 0xb7, 0xdb, 0xb6, 0x91, 0xfd, 0xdf, 0xa7, + 0x60, 0x98, 0x6c, 0x4a, 0x26, 0x24, 0x4d, 0x4a, 0x96, 0xad, 0x48, 0x96, 0xdc, 0xe6, 0x6b, 0x9b, 0xd6, 0x6d, 0x7a, + 0x62, 0x37, 0x7b, 0x77, 0x5d, 0x1f, 0x8b, 0x92, 0x20, 0x89, 0x1b, 0x8a, 0xd4, 0x25, 0x29, 0x4b, 0xae, 0xc2, 0x7d, + 0x96, 0x7d, 0x84, 0xfb, 0x0c, 0x7d, 0xb2, 0x7b, 0x66, 0x06, 0x20, 0xc1, 0x0f, 0xc9, 0x72, 0x93, 0xb6, 0x7b, 0xcf, + 0xb9, 0xa7, 0x4d, 0x22, 0x82, 0x00, 0x08, 0x0c, 0x80, 0x99, 0xc1, 0x7c, 0x46, 0xc5, 0x67, 0xd8, 0xc6, 0xa5, 0x2a, + 0x28, 0xb2, 0x2d, 0x56, 0x02, 0xd1, 0xc2, 0xe8, 0x94, 0x3e, 0x6f, 0x25, 0xe1, 0x59, 0xb8, 0x12, 0xe2, 0xe1, 0x93, + 0xa8, 0xa6, 0x10, 0xcf, 0x46, 0xc7, 0x3d, 0x19, 0xd1, 0x0f, 0x27, 0xdd, 0x42, 0x04, 0xd2, 0x1c, 0xc0, 0x19, 0x73, + 0x3a, 0xa0, 0x2b, 0xd3, 0xf5, 0xa3, 0x8d, 0xd8, 0x78, 0xe9, 0xc0, 0xcb, 0x92, 0xbf, 0x16, 0x18, 0x8b, 0x94, 0x83, + 0x5e, 0x8e, 0x35, 0x5a, 0x53, 0x8d, 0xef, 0x8f, 0x9e, 0x57, 0xcb, 0x9d, 0x58, 0xf4, 0xc8, 0x28, 0x17, 0x66, 0x7d, + 0x15, 0xb6, 0x66, 0x23, 0xad, 0x6e, 0x60, 0x24, 0x5e, 0x12, 0x53, 0xc0, 0xf0, 0xcb, 0x88, 0xf1, 0x1f, 0x55, 0x30, + 0x3e, 0x5a, 0xd9, 0x65, 0x08, 0xff, 0xc7, 0xb7, 0xe7, 0x17, 0xa0, 0xbd, 0x72, 0x51, 0xdd, 0xbc, 0x51, 0xb9, 0xa5, + 0x8a, 0x09, 0xfa, 0x20, 0xb5, 0xa3, 0xba, 0x0b, 0xa0, 0xc7, 0x78, 0x2f, 0x38, 0x58, 0x9b, 0xab, 0xd5, 0xca, 0x04, + 0xbb, 0x55, 0x73, 0x19, 0xf9, 0xc4, 0x03, 0x8e, 0xd5, 0x54, 0x20, 0x72, 0x56, 0x42, 0xe4, 0x10, 0xf4, 0x96, 0x67, + 0x4d, 0x39, 0x9f, 0x85, 0xab, 0xaf, 0x7d, 0x5f, 0x16, 0xce, 0x08, 0x56, 0x8d, 0xcb, 0x2b, 0x0a, 0x88, 0x41, 0x03, + 0x1d, 0x93, 0xe5, 0xc5, 0xd7, 0xdc, 0x2a, 0x60, 0x7c, 0x3d, 0xbc, 0xbd, 0xe6, 0x9a, 0x87, 0x2c, 0xea, 0xf0, 0xf9, + 0xe0, 0x64, 0xec, 0xdd, 0x28, 0xc8, 0x4f, 0xf6, 0x54, 0x70, 0xd9, 0xf2, 0xd9, 0x70, 0x99, 0x24, 0x61, 0x60, 0x46, + 0xe1, 0x4a, 0xed, 0x9f, 0xd0, 0x83, 0xa8, 0xe0, 0xd2, 0xa3, 0xaa, 0x7c, 0x35, 0xf2, 0xbd, 0xd1, 0x87, 0x9e, 0xfa, + 0x68, 0xe3, 0xf5, 0xfa, 0x25, 0xae, 0xd1, 0x4e, 0xd5, 0x3e, 0x8c, 0x55, 0xf9, 0xda, 0xf7, 0x4f, 0x0e, 0xa8, 0x45, + 0xff, 0xe4, 0x60, 0xec, 0xdd, 0xf4, 0xa5, 0x04, 0x30, 0x5c, 0x3b, 0xda, 0xe3, 0x81, 0x36, 0x33, 0x7b, 0xb2, 0x18, + 0x23, 0x37, 0x8c, 0x98, 0x96, 0x5f, 0x71, 0x21, 0xa2, 0x0c, 0x8d, 0x57, 0x1b, 0xa1, 0xd0, 0xdc, 0x87, 0x0b, 0xdd, + 0xc7, 0x8f, 0x5a, 0x66, 0x6d, 0x3a, 0x93, 0x42, 0xb1, 0xa1, 0x32, 0x0f, 0xab, 0x18, 0x18, 0x4f, 0x46, 0xd7, 0x44, + 0xc0, 0x38, 0x5f, 0x37, 0x46, 0xa9, 0x81, 0x79, 0x74, 0xdc, 0x05, 0xe8, 0x15, 0xf9, 0x4f, 0xe9, 0xde, 0x3b, 0x82, + 0xdc, 0xd9, 0x12, 0xe2, 0xd6, 0x25, 0xcd, 0x0a, 0x9d, 0x42, 0x1e, 0x0d, 0x10, 0x54, 0x22, 0xf8, 0x1d, 0xd2, 0x76, + 0x68, 0xbe, 0x0e, 0xb9, 0xdb, 0xb2, 0x10, 0x3c, 0x6e, 0x2a, 0xb2, 0xa5, 0x09, 0xb8, 0x9c, 0x16, 0x56, 0xa8, 0x53, + 0x5e, 0x2f, 0x11, 0x1b, 0xf2, 0x41, 0xbc, 0x6d, 0xc9, 0x40, 0x53, 0xa7, 0x25, 0x46, 0x89, 0xce, 0x82, 0xef, 0x9e, + 0xa4, 0x1e, 0x62, 0x86, 0x76, 0x19, 0x1b, 0xe1, 0x55, 0x4e, 0x9b, 0x62, 0x42, 0x94, 0x9d, 0x30, 0xcd, 0xc3, 0x34, + 0xd3, 0xaa, 0xf7, 0x1f, 0x6d, 0x02, 0x24, 0x66, 0x71, 0xaf, 0x5f, 0xdc, 0x07, 0x89, 0x3b, 0x34, 0x69, 0x33, 0xab, + 0xca, 0x57, 0xe3, 0xa1, 0x9f, 0x2d, 0x36, 0x1d, 0x82, 0x99, 0x1b, 0x8c, 0x7d, 0x76, 0xe1, 0x0e, 0xbf, 0xc1, 0x3a, + 0x2f, 0x87, 0xfe, 0x0b, 0xa8, 0x90, 0xaa, 0xfd, 0x47, 0x1b, 0x22, 0xd7, 0x75, 0x08, 0x3b, 0xa5, 0x2d, 0x50, 0xfe, + 0x0e, 0x4f, 0xac, 0xc4, 0x22, 0x6a, 0x8d, 0x83, 0x25, 0x12, 0x4b, 0x18, 0xb5, 0x38, 0x32, 0x9e, 0xd8, 0x07, 0xf6, + 0xa6, 0xc2, 0x4f, 0x2d, 0x8c, 0x2b, 0x14, 0x27, 0x58, 0xde, 0x99, 0xf2, 0x60, 0x89, 0x94, 0xbe, 0x0b, 0x57, 0x62, + 0xa4, 0x1c, 0x00, 0x14, 0x88, 0xf2, 0xf4, 0x7c, 0x70, 0x22, 0x2b, 0x7f, 0x50, 0x42, 0x4e, 0xfd, 0xc2, 0xaf, 0x54, + 0x55, 0xf2, 0x34, 0x4f, 0x8b, 0xb5, 0xda, 0x3f, 0x39, 0x90, 0x6b, 0xf7, 0x07, 0x9d, 0x57, 0xd2, 0xe4, 0xb0, 0x57, + 0x71, 0x3b, 0xbe, 0xcc, 0x1f, 0xd2, 0x2b, 0x05, 0xee, 0xc2, 0x29, 0x94, 0x00, 0x8c, 0x8a, 0x4d, 0x2a, 0xe4, 0x07, + 0x12, 0x23, 0xe6, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0xa1, 0xde, 0xc9, 0x96, 0x90, 0xec, 0x2f, 0x45, 0x6f, 0x03, + 0xfe, 0x6f, 0x0e, 0x12, 0x94, 0x67, 0xb3, 0x20, 0x0e, 0x23, 0x15, 0xa6, 0x59, 0xce, 0x8e, 0xa4, 0x48, 0x59, 0xd9, + 0x70, 0xc2, 0xb5, 0x64, 0x15, 0x00, 0x76, 0x50, 0x6e, 0x2a, 0xcd, 0x7b, 0xa0, 0xe7, 0x3f, 0x14, 0x3e, 0x99, 0x12, + 0xd2, 0xca, 0x06, 0xb8, 0x3d, 0xeb, 0xd4, 0xe5, 0x5b, 0xcf, 0xf8, 0x5b, 0x68, 0xcc, 0x5d, 0x63, 0xe8, 0x1a, 0xe7, + 0xc1, 0x55, 0x5a, 0xbb, 0x78, 0x59, 0xc6, 0x38, 0x83, 0x75, 0x35, 0x88, 0xb3, 0x54, 0xbc, 0x57, 0x78, 0x16, 0xb7, + 0x0c, 0xb9, 0x70, 0xa3, 0x29, 0x13, 0x89, 0xda, 0xc4, 0x5b, 0x21, 0x21, 0xd0, 0x25, 0xb0, 0x40, 0x10, 0xb2, 0x07, + 0xdc, 0x80, 0xce, 0xb3, 0x46, 0x49, 0xe4, 0x7f, 0xc7, 0x6e, 0xe1, 0x3a, 0x19, 0x27, 0xe1, 0x02, 0x24, 0x53, 0xee, + 0x94, 0x6b, 0x1a, 0x0c, 0x60, 0x6a, 0xf6, 0xf9, 0xdc, 0xc7, 0x8f, 0x4c, 0xca, 0x1d, 0x96, 0x84, 0xd3, 0xa9, 0xcf, + 0x34, 0x29, 0xc7, 0x58, 0xf6, 0x99, 0xd3, 0x07, 0xb6, 0x88, 0x4f, 0xad, 0xa7, 0xdb, 0x0e, 0x56, 0xce, 0x01, 0x0a, + 0x9d, 0x3e, 0x20, 0x2e, 0x32, 0xa1, 0x42, 0x26, 0x5c, 0x13, 0xe7, 0x22, 0x3f, 0xb8, 0xe6, 0x38, 0x5c, 0x0e, 0x7d, + 0x66, 0xe2, 0x69, 0x80, 0x4f, 0x6e, 0x86, 0xcb, 0xe1, 0xd0, 0xa7, 0xa4, 0x60, 0x10, 0x65, 0x2d, 0x8c, 0x51, 0xfa, + 0x99, 0xea, 0x5d, 0xe4, 0xd4, 0x92, 0xf2, 0xf0, 0xc1, 0x32, 0x12, 0x6e, 0x0b, 0xf4, 0x81, 0x04, 0x24, 0x9d, 0xd5, + 0x33, 0xdd, 0x53, 0xe1, 0x96, 0xc2, 0x62, 0xb5, 0x5b, 0xc3, 0xd2, 0xf5, 0x2e, 0xd5, 0x73, 0x84, 0xb0, 0xe2, 0x06, + 0x63, 0xe5, 0x05, 0xed, 0x5d, 0xd5, 0x50, 0xc9, 0xc0, 0x8b, 0xe7, 0x90, 0x53, 0x0d, 0xf5, 0xa5, 0xe7, 0x4e, 0x83, + 0x30, 0x4e, 0xbc, 0x91, 0x7a, 0xd5, 0x7d, 0xe9, 0x69, 0x97, 0xf3, 0x44, 0xd3, 0xaf, 0x8c, 0xbf, 0xca, 0xd9, 0xbe, + 0x04, 0xa6, 0xc4, 0x64, 0x5f, 0x5b, 0xea, 0xc8, 0xa7, 0x67, 0x57, 0x3d, 0x81, 0x91, 0xb1, 0xce, 0x5f, 0x7b, 0x50, + 0xab, 0x94, 0x37, 0x0c, 0x13, 0x42, 0x42, 0xde, 0xb0, 0xbf, 0xea, 0x5d, 0x12, 0xb5, 0x7c, 0xbd, 0xdc, 0x20, 0xd3, + 0x90, 0xe4, 0xc4, 0x17, 0x43, 0xdd, 0x0b, 0xff, 0x50, 0x7a, 0x7e, 0x20, 0xfb, 0x36, 0x14, 0xc8, 0xf8, 0xe0, 0xeb, + 0x22, 0x07, 0xf2, 0x68, 0x93, 0xa4, 0x60, 0x58, 0x18, 0x84, 0x89, 0x02, 0xf1, 0xdb, 0xe0, 0x83, 0x83, 0xb2, 0x2d, + 0x34, 0xef, 0x55, 0xd3, 0x53, 0x8e, 0x05, 0x9e, 0x23, 0x2d, 0x45, 0xf9, 0x24, 0x84, 0x9b, 0x80, 0x50, 0xa4, 0x85, + 0x68, 0x4d, 0xdc, 0x03, 0x0f, 0x96, 0xaf, 0xc0, 0xbf, 0x49, 0x78, 0xbf, 0x48, 0xcf, 0x1f, 0x6d, 0xe2, 0x53, 0x41, + 0xd4, 0xdf, 0xc4, 0xb8, 0x96, 0xc0, 0xae, 0x70, 0x2a, 0x9f, 0xaa, 0xca, 0xa9, 0xa0, 0x44, 0x58, 0xb7, 0x80, 0x5e, + 0x35, 0xc1, 0xee, 0x46, 0x22, 0x32, 0x3e, 0x4f, 0x3f, 0x2e, 0x18, 0xb0, 0xd2, 0xd1, 0x83, 0x90, 0x4c, 0x19, 0x6f, + 0x95, 0x80, 0x5d, 0x35, 0x12, 0x0c, 0xc0, 0x5c, 0x9c, 0x47, 0x18, 0xa4, 0xd7, 0xc0, 0x48, 0x42, 0x9c, 0x32, 0x31, + 0x47, 0x23, 0x94, 0x53, 0xc5, 0x79, 0xc1, 0x62, 0x99, 0x60, 0xfc, 0x79, 0x18, 0x00, 0x4b, 0x55, 0x05, 0x2f, 0x89, + 0x80, 0xeb, 0xf3, 0xcb, 0x4f, 0xaa, 0x2a, 0xde, 0xb8, 0x5a, 0xc6, 0xe5, 0x31, 0x80, 0xe3, 0x70, 0x1a, 0xa8, 0xbd, + 0x81, 0xc7, 0x88, 0x4f, 0x63, 0x64, 0xe4, 0xc9, 0x5b, 0xb4, 0x11, 0x5a, 0x39, 0xd4, 0x20, 0x90, 0x11, 0xf5, 0xd3, + 0xd5, 0xfc, 0xda, 0xc9, 0x42, 0x4c, 0xea, 0xc2, 0x34, 0x07, 0x20, 0x89, 0x3c, 0x05, 0xd8, 0xf5, 0x1e, 0x6d, 0xdc, + 0xcc, 0x80, 0x4e, 0xbd, 0x50, 0xc9, 0x7a, 0x6e, 0x80, 0x60, 0x18, 0xa4, 0xd7, 0xb9, 0x3b, 0x6b, 0x3e, 0x5f, 0xd8, + 0x92, 0x54, 0xae, 0xa0, 0x3d, 0x5b, 0x8f, 0x5b, 0xad, 0x2d, 0x22, 0x6f, 0xee, 0x46, 0xb7, 0x64, 0xe4, 0x66, 0xc8, + 0x96, 0x70, 0xba, 0xaa, 0x10, 0x3d, 0x20, 0x00, 0x10, 0x69, 0x50, 0x95, 0xaf, 0xb2, 0x32, 0xc6, 0x67, 0x9b, 0x59, + 0xfa, 0xc0, 0xb7, 0xae, 0xd5, 0xa7, 0xcc, 0x22, 0x29, 0x23, 0x35, 0xe9, 0x6a, 0xf1, 0x96, 0xe9, 0xc5, 0xc5, 0xe9, + 0x05, 0xc5, 0x8d, 0x86, 0x93, 0x21, 0x4a, 0x41, 0xe3, 0xc6, 0x99, 0x61, 0xaa, 0xcb, 0xfa, 0x15, 0xa5, 0x77, 0x7f, + 0xe8, 0x72, 0x30, 0x58, 0x8e, 0x00, 0x96, 0xa3, 0x46, 0x00, 0xeb, 0x8a, 0x15, 0x01, 0x5e, 0x04, 0xb8, 0x90, 0x08, + 0x39, 0x10, 0xca, 0x82, 0xa9, 0x64, 0x5b, 0x28, 0x82, 0xa3, 0x41, 0x63, 0xa7, 0xa3, 0x11, 0xf5, 0x7a, 0x21, 0xb6, + 0x8a, 0xd2, 0x93, 0x03, 0xaa, 0x4d, 0x44, 0x91, 0x2a, 0x01, 0x18, 0x22, 0x98, 0x61, 0x0e, 0x05, 0x48, 0x03, 0xde, + 0x73, 0xf2, 0x8b, 0x8e, 0x35, 0x47, 0xe5, 0xb3, 0x73, 0x5a, 0x64, 0x78, 0xb0, 0x95, 0xda, 0x3f, 0xc1, 0xc4, 0x9e, + 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xc9, 0x01, 0x3d, 0x2a, 0xa5, 0x13, 0x91, 0x77, 0x22, 0xa4, 0x8e, 0x1d, 0xde, 0xc1, + 0xbd, 0x8e, 0x4a, 0x9c, 0xb0, 0x05, 0x94, 0xba, 0xa9, 0xaa, 0xcc, 0x39, 0x83, 0xc5, 0x63, 0xec, 0x41, 0x00, 0x1e, + 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xee, 0xae, 0x71, 0xe6, 0xe2, 0x8d, 0xbb, 0xd6, 0x1c, 0xfe, 0x2a, 0x3f, 0x6b, 0x71, + 0xf1, 0xac, 0x8d, 0xf8, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x19, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, 0x4c, 0x2c, + 0xee, 0x78, 0xcb, 0xe2, 0x8e, 0x77, 0x2c, 0xae, 0xcf, 0x17, 0x52, 0xc9, 0x40, 0x17, 0xa1, 0xc7, 0x74, 0x06, 0x3c, + 0xce, 0x8f, 0x74, 0xf8, 0x39, 0x43, 0x38, 0x99, 0xb1, 0x0f, 0x16, 0xc3, 0x5b, 0x60, 0x55, 0x07, 0x17, 0x09, 0x10, + 0xd5, 0x89, 0x67, 0xa7, 0x6e, 0x24, 0x49, 0x06, 0x34, 0xbf, 0x3c, 0x5f, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x5b, + 0x66, 0x3a, 0xdb, 0x31, 0xd3, 0x51, 0xe1, 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x94, 0x27, 0x05, 0x7b, 0x10, 0xbc, 0x28, + 0x70, 0xcb, 0x14, 0xf7, 0xe1, 0x76, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x1b, 0xc7, 0xab, 0x30, 0x02, 0x33, 0x04, 0xe8, + 0xe6, 0x7e, 0x5b, 0x6a, 0xee, 0x05, 0x3c, 0xc2, 0xd9, 0xd6, 0xcd, 0x94, 0xbf, 0x97, 0xb7, 0x54, 0xa3, 0xd5, 0xa2, + 0x1a, 0x0b, 0x37, 0x49, 0x58, 0x84, 0x40, 0x77, 0x21, 0x15, 0xc6, 0x7f, 0xc8, 0x36, 0xab, 0xc1, 0x21, 0xbe, 0x84, + 0xd5, 0x11, 0x43, 0x2f, 0x80, 0x05, 0x23, 0xbd, 0x63, 0xa0, 0x6f, 0xa4, 0x68, 0xa9, 0x51, 0x06, 0xf8, 0x1f, 0xf0, + 0xb8, 0x6a, 0x91, 0xe4, 0xcf, 0xeb, 0x1c, 0xe9, 0xd6, 0xc2, 0x1d, 0x9f, 0x83, 0xb5, 0x8b, 0xd6, 0x30, 0xc0, 0x73, + 0x45, 0x8e, 0x8d, 0x1a, 0x11, 0x4f, 0x38, 0xca, 0x91, 0x24, 0x62, 0x49, 0x6e, 0x17, 0x0c, 0x21, 0x05, 0x5c, 0x73, + 0x72, 0xb5, 0x69, 0xa4, 0x07, 0x53, 0x4f, 0xaf, 0x60, 0x4d, 0x40, 0x6d, 0x7e, 0xaf, 0x9f, 0x09, 0xdd, 0x7c, 0xc3, + 0x39, 0xd2, 0x41, 0x1d, 0x7a, 0x09, 0x49, 0xcf, 0x6d, 0x71, 0x99, 0x1e, 0x44, 0x40, 0xb5, 0x40, 0x79, 0xf8, 0x78, + 0x8a, 0xbf, 0x9c, 0xab, 0xf4, 0xf1, 0x10, 0x7f, 0x35, 0xae, 0x32, 0x55, 0x55, 0x49, 0x8a, 0x20, 0xcd, 0x59, 0xed, + 0x17, 0xf6, 0x13, 0x19, 0x65, 0xdf, 0x63, 0xdb, 0xf0, 0x05, 0x7e, 0xf8, 0x68, 0x13, 0x43, 0x18, 0x02, 0x79, 0x0e, + 0x81, 0x15, 0xe9, 0x69, 0x6d, 0xf9, 0x74, 0x4b, 0xf9, 0x50, 0xff, 0x83, 0x09, 0x3f, 0xee, 0x92, 0x30, 0xa7, 0x29, + 0x45, 0x19, 0xc8, 0xf5, 0xd0, 0x0b, 0xdc, 0xe8, 0xf6, 0x9a, 0x6e, 0x21, 0x9a, 0x24, 0xe4, 0x7d, 0x90, 0x0b, 0x07, + 0x6e, 0x8b, 0x36, 0x20, 0x89, 0xa4, 0xa0, 0xba, 0xe5, 0x84, 0xbe, 0xf7, 0x5d, 0x24, 0xf1, 0x77, 0x85, 0x6b, 0x2c, + 0x5f, 0x90, 0xc2, 0x87, 0xae, 0x1f, 0x6d, 0x34, 0x56, 0xed, 0xa6, 0x34, 0xdb, 0x12, 0x03, 0x09, 0xcb, 0x83, 0x57, + 0xe2, 0xf9, 0xd8, 0xeb, 0xa0, 0x91, 0xc7, 0x30, 0x5c, 0x9b, 0x8f, 0x36, 0xc9, 0xa9, 0x3a, 0x77, 0xa3, 0x0f, 0x6c, + 0x6c, 0x8e, 0xbc, 0x68, 0xe4, 0x03, 0xf3, 0x38, 0xf4, 0xdd, 0xe0, 0x03, 0x7f, 0x34, 0xc3, 0x65, 0x82, 0x66, 0x5b, + 0x77, 0xde, 0xa0, 0x05, 0x4c, 0x48, 0x90, 0x88, 0x5c, 0x6d, 0x0d, 0x14, 0x94, 0xf3, 0x81, 0xb8, 0xd6, 0xe7, 0x8c, + 0x62, 0x5e, 0xcb, 0x00, 0xaf, 0x03, 0xb0, 0x24, 0x83, 0x30, 0x0e, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, 0xf2, 0x54, 0x49, + 0x8f, 0x96, 0xe5, 0x21, 0xbe, 0xc6, 0x1e, 0x7e, 0xfb, 0xe7, 0xa0, 0xe4, 0x3e, 0x9f, 0xcb, 0x7a, 0xf9, 0xb4, 0x19, + 0x42, 0xa9, 0x49, 0xee, 0x83, 0xf7, 0xf8, 0x38, 0x67, 0x30, 0xb7, 0x7f, 0x5a, 0x6e, 0xec, 0xc6, 0xf1, 0x72, 0xce, + 0xc6, 0xa4, 0x0c, 0x3b, 0xcd, 0x07, 0x55, 0xbc, 0x87, 0xc8, 0x03, 0xfb, 0x79, 0xd9, 0x38, 0x3e, 0x7c, 0x01, 0x66, + 0x7c, 0xc0, 0x50, 0x86, 0x93, 0x89, 0x9a, 0x8b, 0x02, 0xee, 0x68, 0xe6, 0x1c, 0xfe, 0xbc, 0x7c, 0xfd, 0xca, 0x7e, + 0x9d, 0x35, 0x0e, 0x80, 0x31, 0x16, 0x36, 0x49, 0x9c, 0x2f, 0x96, 0xc6, 0x2b, 0x66, 0x34, 0x71, 0x83, 0xed, 0xd3, + 0xb9, 0x2c, 0x6c, 0xf1, 0x05, 0x63, 0x63, 0x60, 0xb8, 0x8d, 0x4a, 0xe9, 0xb5, 0xcf, 0x6e, 0x58, 0x66, 0xef, 0x54, + 0xfd, 0x58, 0x4d, 0x0b, 0x0c, 0xc8, 0xca, 0x75, 0x8f, 0x9c, 0xab, 0x93, 0xa6, 0x34, 0xc0, 0x39, 0xf0, 0x99, 0xcb, + 0x47, 0xac, 0x74, 0xa4, 0x06, 0x86, 0x2a, 0x0d, 0x60, 0xeb, 0xc8, 0x4e, 0xb7, 0x94, 0x77, 0x00, 0x51, 0x6f, 0x19, + 0x9b, 0xe1, 0xe8, 0x1d, 0x48, 0x60, 0xc1, 0xe1, 0xe4, 0xc3, 0xc9, 0xd3, 0x72, 0xa9, 0xc9, 0x36, 0x88, 0xd5, 0x89, + 0xda, 0x54, 0x12, 0xd2, 0x08, 0x17, 0x00, 0xf4, 0x85, 0x11, 0xe2, 0xaa, 0xda, 0xb5, 0x51, 0x8a, 0x33, 0x1f, 0x62, + 0x7a, 0xf7, 0x80, 0xc5, 0xf1, 0x56, 0x80, 0x65, 0x8b, 0x6e, 0xa8, 0x79, 0xed, 0x22, 0x3c, 0xf2, 0x72, 0xc3, 0x36, + 0x80, 0x25, 0xc0, 0x09, 0x96, 0xbf, 0x85, 0xe4, 0xe5, 0x7a, 0xce, 0x8d, 0x38, 0xa3, 0xe9, 0x50, 0xe5, 0x06, 0x76, + 0xdb, 0xde, 0xaf, 0x54, 0x3e, 0xa8, 0x02, 0x99, 0xae, 0x1d, 0x9a, 0x56, 0x40, 0xbd, 0x15, 0xa9, 0x12, 0x76, 0x20, + 0xc6, 0x54, 0xc2, 0xaf, 0x6c, 0x32, 0x61, 0xa3, 0x24, 0xd6, 0x85, 0x8c, 0x29, 0x0b, 0xa9, 0x0e, 0x4a, 0xbb, 0x07, + 0x3d, 0xf5, 0x07, 0x08, 0x2c, 0x23, 0x22, 0x0f, 0xf2, 0x01, 0x89, 0x3b, 0x53, 0x3d, 0x98, 0xa8, 0xc7, 0x22, 0x88, + 0xf8, 0x57, 0x40, 0x0a, 0x5d, 0x53, 0x8e, 0x43, 0xe3, 0xf4, 0x27, 0xdf, 0x17, 0x61, 0x66, 0xea, 0xb9, 0x1b, 0x15, + 0xed, 0x3a, 0xbe, 0x1b, 0xe7, 0x75, 0xcb, 0xb1, 0x53, 0xd5, 0x00, 0x87, 0xe6, 0x0f, 0xa5, 0x6d, 0x4c, 0x04, 0xaa, + 0xa7, 0x9e, 0xbd, 0x7d, 0xf1, 0xdd, 0xab, 0x97, 0xfb, 0x62, 0x04, 0xec, 0xb2, 0x09, 0x5d, 0x2e, 0x83, 0x1d, 0x9d, + 0xfe, 0xf4, 0xc3, 0xfd, 0xba, 0x6d, 0x38, 0xcf, 0x1c, 0xd5, 0x20, 0x1b, 0x74, 0x09, 0x2f, 0x8e, 0xc2, 0x1b, 0x16, + 0x7d, 0x32, 0x18, 0xe4, 0xce, 0xeb, 0x87, 0xfb, 0xf6, 0xc7, 0x57, 0x3f, 0xec, 0x3d, 0xd4, 0x23, 0xc7, 0x06, 0xdc, + 0x9e, 0x84, 0x8b, 0x7b, 0xcc, 0xae, 0xa9, 0x1a, 0xea, 0xc8, 0x0f, 0x63, 0xb6, 0x65, 0x04, 0x2f, 0xce, 0xde, 0x9e, + 0x23, 0xb8, 0x72, 0x16, 0x84, 0xba, 0xfa, 0xb4, 0xc9, 0xff, 0xf8, 0xee, 0xd5, 0xf9, 0xb9, 0x6a, 0x60, 0x4a, 0xee, + 0x58, 0xee, 0x9d, 0x6f, 0xe2, 0x3b, 0x28, 0x4e, 0xed, 0x5e, 0x27, 0xaa, 0x46, 0x17, 0xe9, 0xe2, 0x6c, 0xa8, 0xac, + 0xb2, 0xcd, 0x39, 0xb5, 0xe3, 0x5f, 0xa6, 0xdb, 0xef, 0x5e, 0xf3, 0xaa, 0xc1, 0x47, 0xbb, 0x49, 0x6a, 0xa1, 0x64, + 0xee, 0x05, 0xd7, 0x35, 0xa5, 0xee, 0xba, 0xa6, 0x14, 0xae, 0x8f, 0x15, 0xfc, 0xb8, 0x0c, 0xe7, 0x12, 0x3b, 0xc2, + 0xd6, 0x77, 0x83, 0x4b, 0xba, 0xc3, 0x7d, 0xc2, 0xa0, 0x79, 0x4a, 0x95, 0xf2, 0xa8, 0x6b, 0x8a, 0xf9, 0xc5, 0x2b, + 0x83, 0xed, 0xc8, 0x07, 0xcb, 0x7b, 0x26, 0xab, 0x21, 0x8b, 0xac, 0x2a, 0xf7, 0x9b, 0xe9, 0x95, 0x6e, 0x05, 0xd4, + 0x8c, 0x54, 0x37, 0x9c, 0xa6, 0x2c, 0xdc, 0x31, 0x98, 0xb3, 0x9b, 0xc3, 0x30, 0x49, 0xc2, 0x79, 0xc7, 0xb1, 0x17, + 0x6b, 0x55, 0xe9, 0x0a, 0x61, 0x07, 0xb7, 0xb6, 0xef, 0xfc, 0xfa, 0xef, 0x12, 0x9a, 0xa7, 0xf2, 0xeb, 0x84, 0xcd, + 0x17, 0x2c, 0x72, 0x93, 0x65, 0xc4, 0x52, 0xe5, 0xd7, 0xff, 0x79, 0x51, 0xba, 0xd8, 0x77, 0xe5, 0x36, 0xc4, 0xd2, + 0xcb, 0x4d, 0xae, 0xfd, 0x70, 0xf5, 0x20, 0xf7, 0xab, 0xbb, 0xa3, 0xf2, 0xcc, 0x9b, 0xce, 0xb2, 0xda, 0xa7, 0xc9, + 0x8e, 0xb9, 0x89, 0xd1, 0x93, 0x3e, 0x40, 0x39, 0x0b, 0x57, 0x9d, 0x5f, 0xff, 0x9d, 0x09, 0x6c, 0xee, 0xdc, 0x75, + 0xf5, 0x03, 0x2d, 0xae, 0x68, 0x7d, 0x9d, 0xca, 0x12, 0xc3, 0xfb, 0xca, 0x02, 0x57, 0x0a, 0x69, 0x57, 0x56, 0x75, + 0x73, 0x3b, 0xe6, 0xf4, 0x8d, 0x37, 0x9d, 0x7d, 0xea, 0xa4, 0x00, 0xa0, 0x77, 0xce, 0x0a, 0x2a, 0x7d, 0x86, 0x69, + 0x0d, 0x3a, 0xfb, 0x2f, 0xd8, 0x27, 0xce, 0xeb, 0xae, 0x29, 0x7d, 0x8e, 0xd9, 0x70, 0xc9, 0xed, 0xf9, 0x60, 0x90, + 0xa5, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0x69, 0xa5, 0x84, 0xb3, 0x17, 0x1d, 0x5b, 0xa7, 0x90, 0x3d, 0x7b, 0x00, + 0x04, 0x6d, 0xdc, 0x6b, 0xc0, 0xb1, 0x1d, 0x5f, 0x93, 0xab, 0x5a, 0xe5, 0xdb, 0x15, 0x64, 0x0d, 0xa5, 0x98, 0xce, + 0x34, 0xd3, 0x1a, 0x1a, 0xf5, 0xc3, 0x59, 0x45, 0xee, 0x82, 0x94, 0x04, 0x0a, 0x6a, 0x4c, 0x40, 0xe8, 0x52, 0xba, + 0x45, 0xdf, 0xb8, 0xfe, 0xcd, 0x7e, 0x17, 0xaa, 0xed, 0x14, 0x0c, 0x49, 0xf3, 0x9f, 0x47, 0xbc, 0x91, 0x2e, 0xdf, + 0x9b, 0x76, 0xaf, 0xdc, 0x84, 0x45, 0xd7, 0x33, 0xf0, 0xe9, 0x15, 0xd2, 0x03, 0x88, 0x96, 0xbb, 0x0b, 0x29, 0x17, + 0xd8, 0xd2, 0x1a, 0x34, 0x9a, 0x63, 0xb8, 0xdf, 0x86, 0xbb, 0x3f, 0x13, 0xe6, 0xee, 0xbc, 0x02, 0xaf, 0xcb, 0xdf, + 0x0d, 0x7b, 0xef, 0xa2, 0x4c, 0xff, 0x8f, 0xbd, 0xff, 0x13, 0xb1, 0xf7, 0xce, 0xef, 0xfc, 0x96, 0x85, 0xfd, 0x3f, + 0x80, 0xe5, 0x3b, 0xac, 0xf7, 0x8a, 0x63, 0x7a, 0x4d, 0x73, 0x7b, 0x42, 0xb9, 0x2a, 0xe3, 0xd5, 0x8a, 0x82, 0x95, + 0x87, 0x54, 0xe3, 0x96, 0x83, 0x2e, 0x22, 0xfb, 0x1d, 0x47, 0xf9, 0xf7, 0x47, 0xf4, 0x31, 0xe5, 0xa1, 0x92, 0x30, + 0x7d, 0xe7, 0x95, 0x11, 0x17, 0x66, 0xe2, 0xae, 0xdc, 0xdb, 0x7d, 0xf0, 0x8e, 0x18, 0xec, 0xd7, 0x2b, 0xf7, 0xb6, + 0x6e, 0xb0, 0x5b, 0xd1, 0x6b, 0xf9, 0x63, 0xa7, 0xe0, 0xcb, 0xd3, 0x41, 0x47, 0x1e, 0x63, 0x10, 0xb3, 0xe4, 0x14, + 0x0a, 0x7b, 0x8f, 0x36, 0x0f, 0xca, 0x15, 0xd3, 0x01, 0x78, 0x39, 0x4b, 0x03, 0x0f, 0x0b, 0x03, 0xf7, 0xe2, 0xeb, + 0x30, 0xb8, 0xcf, 0xc8, 0x7f, 0x04, 0xe1, 0xcf, 0x6f, 0x1e, 0x3a, 0x7e, 0xae, 0x32, 0x76, 0x2c, 0x2d, 0x0f, 0x1e, + 0x0b, 0xcb, 0xa3, 0xef, 0xd6, 0xcb, 0xea, 0x4b, 0x84, 0x16, 0x69, 0x2c, 0x23, 0x42, 0xab, 0x80, 0x5e, 0x45, 0x01, + 0x1d, 0x97, 0x20, 0xb9, 0x98, 0xa0, 0xf4, 0xd5, 0x36, 0xa7, 0xae, 0x37, 0x77, 0x3b, 0x75, 0x5d, 0xec, 0xe5, 0xd4, + 0xf5, 0xe6, 0xb3, 0x3b, 0x75, 0xbd, 0x92, 0x9d, 0xba, 0xe0, 0x50, 0xbd, 0x62, 0x7b, 0xf9, 0xd0, 0x08, 0x3b, 0xd7, + 0x70, 0x15, 0xf7, 0x1c, 0x2e, 0x6e, 0x8b, 0x47, 0x33, 0x06, 0xfa, 0x0b, 0xbe, 0xff, 0xfd, 0x70, 0x0a, 0xae, 0x2e, + 0xdb, 0x9d, 0x59, 0x3e, 0x97, 0x2b, 0x8b, 0x1f, 0x4e, 0x55, 0x29, 0x45, 0x4b, 0x20, 0x52, 0xb4, 0x40, 0x58, 0x9a, + 0x9f, 0xd7, 0xce, 0xf3, 0x4b, 0xa7, 0xdb, 0x74, 0x20, 0xc4, 0x19, 0x88, 0xa4, 0xb1, 0xc0, 0xee, 0x36, 0x9b, 0x50, + 0xb0, 0x92, 0x0a, 0x1a, 0x50, 0xe0, 0x49, 0x05, 0x2d, 0x28, 0x18, 0x49, 0x05, 0x47, 0x50, 0x30, 0x96, 0x0a, 0x8e, + 0xa1, 0xe0, 0x46, 0x4d, 0x2f, 0x83, 0xcc, 0x65, 0xed, 0x58, 0xbf, 0x2a, 0x64, 0xe7, 0xca, 0xf4, 0x27, 0xa2, 0xca, + 0xb1, 0x21, 0x42, 0x45, 0x9b, 0x87, 0x3a, 0x77, 0x8e, 0x1a, 0x7c, 0x31, 0x80, 0x20, 0x2e, 0xa0, 0x4e, 0x32, 0x40, + 0x19, 0x47, 0x35, 0x9b, 0xe2, 0xb5, 0xda, 0xc9, 0x5c, 0xbc, 0x6c, 0xa3, 0x21, 0x5c, 0xa6, 0x3a, 0xe8, 0xc0, 0x2b, + 0x2a, 0xb7, 0x9e, 0xce, 0xb2, 0xb8, 0x91, 0xcb, 0x5e, 0xee, 0x07, 0xdf, 0x84, 0xe8, 0xf9, 0x60, 0x14, 0xf5, 0x12, + 0x6f, 0xa6, 0x56, 0x12, 0x82, 0x9b, 0xb3, 0x88, 0x97, 0x28, 0x3e, 0xa0, 0xa0, 0x1f, 0x5c, 0xd7, 0xcd, 0x43, 0x5b, + 0xf2, 0x28, 0xab, 0x34, 0xfa, 0x79, 0x16, 0xbc, 0x92, 0x04, 0xac, 0x4b, 0x23, 0x71, 0xa7, 0x9d, 0x99, 0x41, 0xda, + 0xd5, 0xce, 0x14, 0xa2, 0x91, 0x9f, 0x8e, 0x3b, 0x0b, 0x63, 0x35, 0x63, 0x41, 0x67, 0xc2, 0xfd, 0x0f, 0x60, 0xfd, + 0xc9, 0xbc, 0x74, 0xae, 0x0b, 0xbb, 0x68, 0xdc, 0x13, 0xf9, 0x5b, 0x1a, 0xa5, 0x99, 0x6d, 0xa5, 0xdc, 0xa4, 0x57, + 0x93, 0x35, 0xaf, 0x9f, 0xc3, 0x00, 0xf3, 0x25, 0x1b, 0x2e, 0xa7, 0xca, 0x59, 0x38, 0xbd, 0xd3, 0xd8, 0x52, 0x7e, + 0x05, 0xa3, 0x54, 0xc9, 0xc4, 0xc4, 0x14, 0xdb, 0x9b, 0x7f, 0x8b, 0x1e, 0xd3, 0x62, 0xfd, 0x04, 0xc6, 0xa6, 0x24, + 0x84, 0xdc, 0xe0, 0x3b, 0x00, 0x6d, 0xc9, 0x9c, 0xf1, 0x0c, 0xe0, 0x27, 0x3d, 0x5f, 0xb8, 0xd2, 0x78, 0xfa, 0xdf, + 0xb3, 0x38, 0x76, 0xa7, 0xa2, 0x7e, 0x75, 0x9c, 0xe0, 0xd9, 0x9b, 0xc9, 0x98, 0x11, 0x80, 0xa0, 0xad, 0xf4, 0x2a, + 0x46, 0xaa, 0xe0, 0x3b, 0x03, 0xc6, 0xdb, 0xb0, 0x68, 0xb9, 0x45, 0xa7, 0x67, 0xc1, 0xf2, 0x14, 0x8d, 0x2b, 0x01, + 0x89, 0xdc, 0x30, 0xbf, 0x5c, 0x98, 0xb8, 0xd3, 0x72, 0x11, 0xad, 0x75, 0x2a, 0x8f, 0x2d, 0xb3, 0x6d, 0x2c, 0x14, + 0x7e, 0x8a, 0xb1, 0x9e, 0x1f, 0x4e, 0x7f, 0x57, 0x4b, 0xbd, 0x1d, 0x16, 0x96, 0xe7, 0x81, 0x11, 0x24, 0x03, 0x0b, + 0x61, 0xac, 0x58, 0x00, 0xc2, 0x4e, 0x90, 0xcc, 0x4c, 0x8c, 0x29, 0xa3, 0x35, 0x02, 0xdd, 0xb0, 0x70, 0x6d, 0x37, + 0xe5, 0x48, 0x5a, 0x9d, 0x68, 0x3a, 0x74, 0x35, 0xa7, 0x71, 0x6c, 0x88, 0x3f, 0x96, 0xdd, 0xd2, 0x53, 0xec, 0x41, + 0x19, 0x7b, 0x37, 0x9b, 0x49, 0x18, 0x24, 0xe6, 0xc4, 0x9d, 0x7b, 0xfe, 0x6d, 0x67, 0x1e, 0x06, 0x61, 0xbc, 0x70, + 0x47, 0xac, 0x9b, 0x2b, 0x0d, 0xba, 0x18, 0xa3, 0x91, 0x87, 0x09, 0x72, 0xac, 0x46, 0xc4, 0xe6, 0xd4, 0x3a, 0x0b, + 0xc1, 0x38, 0xf1, 0xd9, 0x3a, 0xe5, 0x9f, 0x2f, 0x54, 0xa6, 0xaa, 0xb8, 0xe5, 0xa8, 0x05, 0x48, 0xc0, 0x78, 0x7c, + 0x47, 0x88, 0x6a, 0xdc, 0xe5, 0x57, 0x91, 0x8e, 0xd5, 0x68, 0x45, 0x6c, 0xae, 0x58, 0xad, 0xad, 0x9d, 0x47, 0xe1, + 0xaa, 0x0f, 0xa3, 0xc5, 0xc6, 0x66, 0xcc, 0xfc, 0x09, 0xbe, 0x31, 0x31, 0xa4, 0x84, 0xe8, 0xc7, 0x44, 0x65, 0x03, + 0xf4, 0xc6, 0xe6, 0x5d, 0x78, 0xdd, 0x69, 0x28, 0x76, 0x77, 0xee, 0x05, 0x26, 0x4d, 0xe7, 0xd8, 0x5e, 0x48, 0x7d, + 0xc9, 0xf0, 0xd3, 0x37, 0x58, 0xdd, 0x51, 0xec, 0x2e, 0x08, 0x95, 0x27, 0x7e, 0xb8, 0xea, 0xcc, 0xbc, 0xf1, 0x98, + 0x05, 0x5d, 0x1c, 0x73, 0x56, 0xc8, 0x7c, 0xdf, 0x5b, 0xc4, 0x5e, 0xdc, 0x9d, 0xbb, 0x6b, 0xde, 0xeb, 0xe1, 0xb6, + 0x5e, 0x9b, 0xbc, 0xd7, 0xe6, 0xde, 0xbd, 0x4a, 0xdd, 0x40, 0xf8, 0x0a, 0xea, 0x87, 0x0f, 0xad, 0xa5, 0xd8, 0xa5, + 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x62, 0x9b, 0xb9, 0x1b, 0x4d, 0xbd, 0xa0, 0x63, 0xa7, 0xd6, 0xcd, 0x86, 0x36, 0xc6, + 0xc3, 0x76, 0xbb, 0x9d, 0x5a, 0x63, 0xf1, 0x64, 0x8f, 0xc7, 0xa9, 0x35, 0x12, 0x4f, 0x93, 0x89, 0x6d, 0x4f, 0x26, + 0xa9, 0xe5, 0x89, 0x82, 0x66, 0x63, 0x34, 0x6e, 0x36, 0x52, 0x6b, 0x25, 0xd5, 0x48, 0x2d, 0xc6, 0x9f, 0x22, 0x36, + 0xee, 0xe2, 0x46, 0xe2, 0x8e, 0x50, 0xc7, 0xb6, 0x9d, 0x22, 0x06, 0xb8, 0x2c, 0xe0, 0x26, 0xd4, 0x67, 0x5d, 0x6d, + 0xf6, 0xae, 0xa9, 0xe4, 0x9f, 0x1b, 0x8d, 0x6a, 0xeb, 0x8d, 0xdd, 0xe8, 0xc3, 0x95, 0x22, 0xcd, 0xc2, 0x75, 0xa9, + 0xda, 0x46, 0x80, 0xc1, 0x5c, 0x77, 0x20, 0x56, 0x77, 0x77, 0x18, 0x46, 0x70, 0x66, 0x23, 0x77, 0xec, 0x2d, 0xe3, + 0x8e, 0xd3, 0x58, 0xac, 0x45, 0x11, 0xdf, 0xeb, 0x79, 0x01, 0x9e, 0xbd, 0x4e, 0x1c, 0xfa, 0xde, 0x58, 0x14, 0x6d, + 0x3b, 0x4b, 0x4e, 0x43, 0xef, 0x62, 0xa4, 0x3a, 0x0f, 0xe3, 0x2d, 0xba, 0xbe, 0xaf, 0x58, 0xcd, 0x58, 0x61, 0x6e, + 0x8c, 0x3a, 0x74, 0xc5, 0x8e, 0x09, 0x2e, 0x18, 0x95, 0xce, 0x39, 0x5c, 0xac, 0xb3, 0x3d, 0xef, 0x1c, 0x2d, 0xd6, + 0xe9, 0x57, 0x73, 0x36, 0xf6, 0x5c, 0x45, 0xcb, 0x77, 0x93, 0x63, 0x83, 0x9e, 0x5d, 0xdf, 0x6c, 0xd9, 0xa6, 0xe2, + 0x58, 0x40, 0x4e, 0x83, 0x07, 0xde, 0x7c, 0x11, 0x46, 0x89, 0x1b, 0x24, 0x69, 0x3a, 0xb8, 0x4a, 0xd3, 0xee, 0x85, + 0xa7, 0x5d, 0xfe, 0x5d, 0x23, 0x5a, 0x48, 0x76, 0x29, 0xa9, 0x7e, 0x65, 0xbc, 0x62, 0xb2, 0x0d, 0x2d, 0x90, 0x31, + 0xb4, 0x9f, 0x95, 0x2b, 0x13, 0xbd, 0xad, 0x56, 0x26, 0x20, 0x67, 0xd5, 0xc9, 0x24, 0xb7, 0x58, 0x05, 0x29, 0x10, + 0x54, 0x78, 0xc5, 0x7a, 0x17, 0x92, 0x41, 0x2e, 0x30, 0x3d, 0x58, 0x99, 0x02, 0x0a, 0xbc, 0xdc, 0xc6, 0x7b, 0x5e, + 0xdc, 0xcd, 0x7b, 0xfe, 0x23, 0xd9, 0x87, 0xf7, 0xbc, 0xf8, 0xec, 0xbc, 0xe7, 0xcb, 0x6a, 0x40, 0x81, 0x8b, 0xb0, + 0xa7, 0x66, 0x56, 0x14, 0x40, 0x9a, 0x22, 0x0a, 0xd5, 0xfb, 0x32, 0xf9, 0xad, 0x9e, 0xdd, 0xa2, 0x37, 0x4a, 0x3e, + 0x4f, 0x94, 0x1b, 0xee, 0x5e, 0x6f, 0x83, 0xde, 0x77, 0x91, 0xfc, 0x3c, 0x99, 0xf4, 0x5e, 0x86, 0x52, 0x41, 0xf6, + 0xc4, 0x0d, 0x4c, 0x0b, 0x61, 0x15, 0xe9, 0x4d, 0x66, 0x02, 0x0c, 0x89, 0x27, 0x21, 0x2a, 0x1b, 0xf9, 0x7b, 0x8d, + 0x33, 0x43, 0xfc, 0x6e, 0x71, 0x08, 0x5a, 0xe6, 0xf9, 0x22, 0x62, 0x6f, 0x54, 0xd4, 0xa5, 0x53, 0x96, 0xf0, 0x60, + 0x59, 0xcf, 0x6f, 0xdf, 0x8c, 0xb5, 0x8b, 0x50, 0x4f, 0xbd, 0xf8, 0x6d, 0x39, 0xf2, 0x85, 0x10, 0x7e, 0xc9, 0xd3, + 0x49, 0xb9, 0x31, 0xbd, 0x14, 0xe0, 0x0e, 0x5f, 0x53, 0xf3, 0xd3, 0xc2, 0x4c, 0x3b, 0x72, 0x43, 0x9e, 0xe1, 0xba, + 0x42, 0x8c, 0xb9, 0x87, 0xf8, 0x86, 0x73, 0x79, 0x98, 0xb4, 0x1b, 0x03, 0x86, 0x8d, 0xa9, 0xb9, 0x37, 0x4e, 0x53, + 0xbd, 0x2b, 0x00, 0x21, 0x11, 0x5a, 0x76, 0x17, 0x13, 0x17, 0xe7, 0x57, 0x3f, 0x6e, 0x05, 0x45, 0x26, 0x4e, 0x17, + 0x60, 0x34, 0xc8, 0x0d, 0xa2, 0x38, 0xcc, 0x54, 0x85, 0xc0, 0x47, 0xc6, 0xa4, 0xd2, 0x84, 0xc0, 0xca, 0x4d, 0x36, + 0xc1, 0x2e, 0x2c, 0x48, 0xd5, 0xdb, 0x85, 0x80, 0x83, 0x56, 0x8f, 0x10, 0xde, 0x4f, 0xc8, 0xea, 0x08, 0xed, 0xf0, + 0x3a, 0xf8, 0x90, 0xaa, 0x19, 0xef, 0x87, 0xdb, 0xaf, 0x7f, 0x72, 0x00, 0x0d, 0xfa, 0x25, 0x49, 0xdc, 0x1d, 0xce, + 0x1a, 0xc0, 0x4a, 0xc4, 0x2b, 0xc3, 0x8a, 0x57, 0xca, 0x93, 0x8d, 0x08, 0x8d, 0x99, 0xb8, 0x0b, 0x13, 0x44, 0x3f, + 0x88, 0x7b, 0x39, 0xc6, 0x93, 0xa2, 0x70, 0x76, 0x97, 0x31, 0xe0, 0x46, 0x14, 0x2d, 0x20, 0xfe, 0xe9, 0x8e, 0x96, + 0x51, 0x1c, 0x46, 0x9d, 0x45, 0xe8, 0x05, 0x09, 0x8b, 0x52, 0x04, 0xd5, 0x25, 0xc2, 0x47, 0x80, 0xe7, 0x6a, 0x13, + 0x2e, 0xdc, 0x91, 0x97, 0xdc, 0x76, 0x6c, 0xce, 0x52, 0xd8, 0x5d, 0xce, 0x1d, 0xd8, 0xb5, 0xf5, 0x3b, 0x1c, 0x9a, + 0x4f, 0x91, 0xf1, 0x8b, 0xaa, 0xec, 0x8c, 0xbc, 0xcd, 0xbb, 0xd2, 0x5b, 0x0a, 0x0e, 0x0a, 0xec, 0x87, 0x1b, 0x99, + 0x53, 0xc0, 0xf2, 0xb0, 0xd4, 0xf6, 0x98, 0x4d, 0x0d, 0xc4, 0xda, 0x60, 0x7b, 0x20, 0xfe, 0x58, 0x2d, 0x5d, 0xb1, + 0xeb, 0x8b, 0x81, 0xe3, 0xd1, 0xf7, 0x19, 0x59, 0xc7, 0x85, 0x54, 0xda, 0xc6, 0x3e, 0x35, 0x87, 0x6c, 0x12, 0x46, + 0x8c, 0x12, 0xc9, 0x38, 0xed, 0xc5, 0x7a, 0xff, 0xee, 0x77, 0x4f, 0xbf, 0xbe, 0x9f, 0x20, 0x4c, 0x34, 0xd1, 0x99, + 0x7e, 0x47, 0x6f, 0x55, 0x7a, 0x06, 0xac, 0x21, 0x41, 0x7e, 0x44, 0x9e, 0x90, 0x10, 0x04, 0xa4, 0x36, 0x5e, 0xf7, + 0x22, 0xe4, 0x34, 0x2f, 0x62, 0xbe, 0x9b, 0x78, 0x37, 0x82, 0x67, 0x6c, 0x1e, 0x2d, 0xd6, 0x62, 0x8d, 0x91, 0xe0, + 0xdd, 0x63, 0x91, 0x4a, 0x43, 0x11, 0x8b, 0x54, 0x2e, 0xc6, 0x45, 0xea, 0x56, 0x66, 0x23, 0x42, 0x58, 0x96, 0x28, + 0x7d, 0x6b, 0xb1, 0x96, 0x49, 0x74, 0xde, 0x2c, 0xa3, 0xd4, 0xe5, 0xd8, 0xe3, 0x73, 0x6f, 0x3c, 0xf6, 0x59, 0x5a, + 0x58, 0xe8, 0xe2, 0x5a, 0x4a, 0xc0, 0xc9, 0xe0, 0xe0, 0x0e, 0xe3, 0xd0, 0x5f, 0x26, 0xac, 0x1e, 0x5c, 0x04, 0x9c, + 0x86, 0x9d, 0x03, 0x07, 0x7f, 0x17, 0xc7, 0xda, 0x02, 0x76, 0x1b, 0xb6, 0x89, 0xdd, 0x85, 0x54, 0x43, 0x66, 0xb3, + 0x38, 0x74, 0x78, 0x95, 0x0d, 0xda, 0xa8, 0x99, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0x4b, + 0xb7, 0x92, 0x15, 0xa5, 0xc5, 0xc9, 0xfc, 0x3e, 0x67, 0xec, 0x59, 0xfd, 0x19, 0x7b, 0x26, 0xce, 0xd8, 0xee, 0x9d, + 0xf9, 0x70, 0xe2, 0xc0, 0x7f, 0xdd, 0x7c, 0x42, 0x1d, 0x5b, 0x69, 0x2e, 0xd6, 0x8a, 0xb3, 0x58, 0x2b, 0x66, 0x63, + 0xb1, 0x56, 0xb0, 0x6b, 0xb4, 0x79, 0x35, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf0, 0xca, 0x39, + 0x84, 0x77, 0xd0, 0xaa, 0x55, 0x7d, 0xd7, 0xd8, 0x7d, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0x89, 0x3b, 0x1c, + 0xb2, 0x71, 0x67, 0x12, 0x8e, 0x96, 0xf1, 0xbf, 0xf8, 0xf8, 0x39, 0x10, 0x77, 0x22, 0x82, 0x52, 0x3f, 0xa2, 0x29, + 0x48, 0x0f, 0x6f, 0x98, 0xe8, 0x61, 0x93, 0xad, 0x53, 0x87, 0xf2, 0x22, 0x35, 0xac, 0xc3, 0x9a, 0x4d, 0x5e, 0x0f, + 0xe8, 0xdf, 0x6d, 0x95, 0xb6, 0xa3, 0x98, 0x4f, 0x00, 0xcb, 0x4e, 0x70, 0xdc, 0x1f, 0x1a, 0x7c, 0x35, 0xed, 0x76, + 0xfd, 0x70, 0x2f, 0xc5, 0x97, 0xae, 0x04, 0x51, 0xe1, 0x74, 0x8b, 0xfb, 0xe7, 0xee, 0xee, 0x75, 0xdb, 0x1e, 0xa9, + 0xf4, 0xba, 0x83, 0x20, 0xe4, 0x75, 0xf7, 0xc4, 0xf2, 0x0f, 0x9f, 0x1d, 0xc2, 0x7f, 0xc4, 0xd5, 0xff, 0x23, 0xa9, + 0x63, 0xd4, 0x5f, 0x26, 0x05, 0x46, 0x9d, 0x58, 0x25, 0x64, 0xc4, 0xf7, 0xaf, 0x3f, 0x99, 0xdc, 0xaf, 0xc1, 0xde, + 0xb5, 0xc9, 0x5c, 0xbc, 0x5c, 0xfb, 0x79, 0x18, 0xfa, 0xcc, 0x0d, 0xaa, 0xd5, 0x05, 0x78, 0xc8, 0xf7, 0x2f, 0xe9, + 0x41, 0x23, 0x71, 0x8f, 0x20, 0x4b, 0x45, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x6c, 0xdb, 0x55, 0xe2, 0xdd, 0xdd, 0x57, + 0x89, 0x6f, 0xf7, 0xba, 0x4a, 0xbc, 0xfb, 0xec, 0x57, 0x89, 0xb3, 0xea, 0x55, 0xe2, 0x2c, 0x14, 0x3e, 0x42, 0xc6, + 0xeb, 0x25, 0xff, 0xf9, 0x9e, 0x8c, 0x80, 0xde, 0x85, 0xbd, 0x96, 0x4d, 0xb9, 0x8e, 0x2e, 0x7e, 0xf3, 0xc5, 0x02, + 0x37, 0xe2, 0x3b, 0x34, 0x99, 0xcf, 0xaf, 0x16, 0x1c, 0xb3, 0xe3, 0x77, 0xa4, 0x62, 0x3f, 0x0c, 0xa6, 0x3f, 0x82, + 0x11, 0x18, 0x88, 0x03, 0x23, 0xe9, 0x85, 0x17, 0xff, 0x18, 0x2e, 0x96, 0x8b, 0x37, 0xd0, 0xd7, 0x7b, 0x2f, 0xf6, + 0x86, 0x3e, 0xcb, 0x82, 0x4b, 0x91, 0x89, 0x3f, 0x97, 0xad, 0x83, 0x57, 0x8d, 0xf8, 0xe9, 0xae, 0xc5, 0x4f, 0xf4, + 0xbb, 0xe1, 0xbf, 0xc9, 0x77, 0x40, 0xad, 0xbf, 0x88, 0x08, 0xb5, 0xb1, 0x34, 0xe8, 0xfb, 0x5f, 0x46, 0xce, 0x42, + 0xbd, 0x66, 0x96, 0xc2, 0xa6, 0x73, 0x6b, 0x3f, 0xac, 0xdc, 0xcf, 0xeb, 0xa5, 0x6e, 0x64, 0xb1, 0xb7, 0xab, 0xe2, + 0xfc, 0x79, 0xb8, 0x8c, 0xd9, 0x38, 0x5c, 0x05, 0xaa, 0x11, 0x70, 0x47, 0x04, 0x4a, 0x5f, 0x9c, 0xb5, 0xf9, 0x6f, + 0xc8, 0x73, 0x70, 0x8e, 0x8c, 0x32, 0x84, 0xe8, 0xb1, 0x16, 0x00, 0x43, 0x93, 0x4c, 0xdb, 0x4c, 0x9c, 0xa2, 0x9a, + 0xa5, 0x37, 0x7e, 0xa0, 0x69, 0x61, 0xef, 0x7e, 0x2d, 0x85, 0x39, 0x6a, 0x68, 0x71, 0xa9, 0x70, 0xac, 0x05, 0x42, + 0xb8, 0x28, 0x02, 0x60, 0xd6, 0x2c, 0x1c, 0x7f, 0x43, 0x91, 0xa3, 0xf2, 0xb7, 0x10, 0x8a, 0x28, 0x5d, 0xf2, 0xf5, + 0xe0, 0xe1, 0x20, 0xe9, 0xf1, 0x85, 0x04, 0xc6, 0xb7, 0x37, 0x2c, 0xf2, 0xdd, 0x5b, 0x4d, 0x4f, 0xc3, 0xe0, 0x7b, + 0x00, 0xc0, 0xcb, 0x70, 0x15, 0xc8, 0x15, 0x30, 0x4b, 0x6b, 0xcd, 0x5e, 0xaa, 0x0d, 0x5c, 0x0a, 0x8e, 0xbc, 0xd2, + 0x08, 0x3c, 0x6b, 0xe1, 0x4e, 0xd9, 0x7f, 0x19, 0xf4, 0xef, 0xdf, 0xf5, 0xd4, 0x78, 0x17, 0x66, 0x1f, 0xfa, 0x69, + 0xb1, 0xc7, 0x67, 0x1e, 0x3f, 0x7e, 0xb0, 0x7d, 0xda, 0xda, 0xc8, 0x67, 0x6e, 0x24, 0x46, 0x51, 0xd3, 0x5a, 0xdf, + 0x7a, 0x0a, 0x60, 0x14, 0x17, 0xe1, 0x72, 0x34, 0x43, 0x67, 0x9e, 0xcf, 0x37, 0xdf, 0x04, 0xfa, 0x64, 0xf1, 0xa5, + 0x7d, 0x95, 0x4d, 0xbd, 0x54, 0x94, 0x43, 0x01, 0xbf, 0xff, 0x0a, 0x32, 0x6f, 0xfc, 0x89, 0x60, 0xa8, 0xee, 0x9a, + 0x2c, 0x0e, 0xc8, 0xbd, 0x36, 0x6f, 0xd7, 0x03, 0x57, 0x7d, 0x8a, 0x69, 0x29, 0x94, 0x74, 0xf5, 0x48, 0x26, 0x2d, + 0x03, 0x4d, 0x8e, 0x1f, 0xbf, 0x2d, 0x34, 0xbe, 0xf8, 0x0a, 0xb3, 0xe8, 0x9a, 0xce, 0x9d, 0x29, 0x0d, 0xc6, 0xb1, + 0x55, 0x09, 0xc9, 0x70, 0x13, 0x4b, 0x86, 0xe8, 0xab, 0xfc, 0x6e, 0xee, 0x05, 0x06, 0xa6, 0x7f, 0xab, 0xbe, 0x71, + 0xd7, 0x90, 0x00, 0x09, 0x90, 0x5b, 0xf9, 0x15, 0x14, 0x1a, 0x72, 0x08, 0x01, 0xc8, 0xf1, 0xac, 0xd6, 0x42, 0x42, + 0x68, 0x03, 0x07, 0x5f, 0x28, 0x8a, 0xa2, 0x64, 0xd7, 0x08, 0x25, 0xbb, 0x47, 0x60, 0x39, 0x5e, 0x07, 0x40, 0x5b, + 0x92, 0x2e, 0xd6, 0x54, 0x02, 0x37, 0x03, 0x34, 0xaa, 0x12, 0x05, 0x3c, 0xc6, 0x7f, 0xcb, 0x16, 0x05, 0xe2, 0x42, + 0x0f, 0xf1, 0xd9, 0xdd, 0x08, 0x52, 0x01, 0x75, 0x14, 0xbc, 0xb0, 0xe3, 0x5b, 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, + 0x74, 0x59, 0x7d, 0x30, 0xf8, 0x40, 0xc2, 0x82, 0xa0, 0x75, 0x28, 0xe5, 0x76, 0x32, 0x58, 0x0d, 0x6e, 0xc4, 0x7b, + 0xd1, 0x3a, 0x99, 0xb3, 0x60, 0xa9, 0x62, 0x32, 0x68, 0x0c, 0xce, 0x0f, 0x75, 0x5e, 0x12, 0xb3, 0x05, 0xd8, 0xa6, + 0xbe, 0xe5, 0x8c, 0x68, 0x61, 0xcc, 0x51, 0xaa, 0x6b, 0x8c, 0xb8, 0x57, 0x7c, 0xcc, 0x71, 0x5b, 0x99, 0x42, 0xf0, + 0x25, 0x0d, 0x8b, 0xd8, 0x9c, 0xc7, 0xc1, 0x40, 0x4e, 0x81, 0x02, 0x1e, 0x72, 0x71, 0x91, 0x00, 0xbb, 0xe6, 0x96, + 0x17, 0x2d, 0xd3, 0xc8, 0xb8, 0x25, 0x41, 0x51, 0xa4, 0x57, 0xbb, 0xe1, 0xe3, 0x84, 0x88, 0xc4, 0x5b, 0xfb, 0x19, + 0x55, 0xfa, 0xd9, 0x32, 0xe9, 0x0f, 0xec, 0x96, 0x08, 0x09, 0x81, 0xea, 0x03, 0xbb, 0x05, 0x8b, 0xb1, 0x57, 0x20, + 0x4d, 0x51, 0x77, 0xa0, 0x6b, 0x03, 0x72, 0xfc, 0x8d, 0x20, 0x4a, 0xf5, 0x8e, 0x03, 0x64, 0xa7, 0x3b, 0xb0, 0x38, + 0x82, 0x38, 0x30, 0xe2, 0xae, 0x38, 0xc4, 0xdc, 0x8d, 0x51, 0xab, 0x85, 0xb1, 0x59, 0x73, 0x34, 0xf4, 0x27, 0x8e, + 0x6d, 0x1f, 0x54, 0xea, 0x83, 0x20, 0xbb, 0xae, 0xb6, 0x6e, 0x24, 0x3d, 0xc7, 0x36, 0xbd, 0x27, 0x56, 0xa3, 0x5b, + 0xa1, 0xd1, 0x52, 0x12, 0x89, 0x01, 0x8a, 0xbf, 0xfa, 0x8f, 0x36, 0x5a, 0xe5, 0x40, 0xea, 0x65, 0xb7, 0x40, 0x1c, + 0x5b, 0xca, 0xe5, 0x5f, 0x83, 0x2a, 0xe9, 0xa7, 0x14, 0x16, 0x94, 0xd0, 0x74, 0x00, 0x69, 0x90, 0x34, 0x38, 0x46, + 0x7f, 0x51, 0x9e, 0x2a, 0x1a, 0x1d, 0x1f, 0x5d, 0x1f, 0x74, 0x05, 0x46, 0x11, 0x7e, 0xf3, 0x72, 0x07, 0xa5, 0x2f, + 0xc6, 0x65, 0x0c, 0xc7, 0x13, 0xae, 0xb0, 0x5c, 0xa3, 0xb7, 0x93, 0x5b, 0xc0, 0xfe, 0xb7, 0x90, 0x4f, 0x6b, 0x08, + 0x81, 0x9f, 0xa0, 0x06, 0x24, 0x4d, 0xbb, 0xb3, 0x43, 0x88, 0xd3, 0x27, 0x77, 0x57, 0x24, 0x92, 0xfb, 0x77, 0x86, + 0x44, 0x07, 0x75, 0x68, 0x59, 0x7f, 0xf5, 0xe4, 0xee, 0x9e, 0x5d, 0xb2, 0x60, 0x5c, 0xec, 0xb0, 0x44, 0xbf, 0xf6, + 0xef, 0xae, 0x80, 0x51, 0x20, 0x9b, 0x60, 0x58, 0x83, 0x51, 0xd2, 0x30, 0xc0, 0xcd, 0x4f, 0xc7, 0xcd, 0xdb, 0x8b, + 0x8b, 0xc1, 0x06, 0x14, 0x0a, 0x3c, 0x6b, 0x26, 0x09, 0xc5, 0x21, 0x65, 0x15, 0x86, 0xd5, 0xd0, 0x04, 0x23, 0xba, + 0x75, 0x27, 0x26, 0xc2, 0x87, 0x21, 0x6f, 0xe3, 0xf1, 0x24, 0x14, 0xfb, 0x4a, 0xad, 0xbd, 0xbb, 0xa5, 0xd6, 0xc9, + 0x5d, 0x52, 0x6b, 0x72, 0x19, 0x27, 0x7b, 0xa0, 0xcc, 0x75, 0x5e, 0x30, 0xe7, 0x72, 0xf0, 0x81, 0x82, 0xa8, 0x1b, + 0x3d, 0xcc, 0x45, 0xab, 0x4a, 0x6f, 0xe4, 0x95, 0x80, 0xe2, 0x6f, 0xe9, 0x82, 0x22, 0x14, 0xea, 0xb2, 0x6c, 0xfc, + 0x2c, 0x97, 0x8d, 0xd3, 0xad, 0x26, 0x77, 0x16, 0x16, 0xdc, 0xbf, 0xe4, 0x88, 0x9f, 0xdd, 0x0e, 0x72, 0x87, 0xfc, + 0x7c, 0xa4, 0x92, 0x8b, 0x79, 0x7e, 0xd1, 0x90, 0x02, 0x17, 0x88, 0x5b, 0x46, 0x31, 0x7e, 0x41, 0xb1, 0x6a, 0xee, + 0x61, 0x9e, 0x97, 0x83, 0xd4, 0x1d, 0x87, 0x9c, 0x15, 0xcb, 0xdb, 0xa6, 0xe8, 0x62, 0x2c, 0xbf, 0x96, 0x36, 0x49, + 0xe6, 0x0b, 0x4c, 0x00, 0x16, 0x62, 0xfa, 0x92, 0x5e, 0x3b, 0xb3, 0x81, 0xc0, 0x41, 0xd6, 0x84, 0x2e, 0xb8, 0x5b, + 0x3a, 0x4f, 0x89, 0x12, 0x73, 0xd5, 0xb5, 0x83, 0xd4, 0x9d, 0x34, 0xc1, 0xb2, 0x3c, 0x02, 0x61, 0x7d, 0x25, 0x49, + 0x10, 0x3a, 0xb6, 0x62, 0x77, 0x6b, 0x18, 0x00, 0xa4, 0xff, 0xe5, 0x67, 0xce, 0x0a, 0x80, 0x24, 0x52, 0xb1, 0x65, + 0x9d, 0x3f, 0x1e, 0x62, 0x93, 0xcc, 0xdb, 0xb0, 0x6a, 0xf5, 0x9b, 0x24, 0xef, 0xd9, 0x70, 0x47, 0xe1, 0xa2, 0x38, + 0x9f, 0xd7, 0xe8, 0x88, 0x71, 0xf0, 0x5d, 0x16, 0x2d, 0x03, 0xcc, 0x7f, 0x67, 0x26, 0x91, 0x3b, 0xfa, 0xb0, 0x91, + 0xbe, 0xc7, 0x45, 0xa2, 0x20, 0x2e, 0x2e, 0x2a, 0x15, 0xba, 0x2e, 0xa6, 0x8b, 0x60, 0x1d, 0xab, 0x11, 0x4b, 0x82, + 0x9a, 0xce, 0x43, 0xbb, 0xe9, 0x3e, 0x9b, 0x1c, 0x96, 0xe4, 0xa7, 0x8d, 0x56, 0x51, 0xba, 0x9e, 0x8d, 0x63, 0x1e, + 0xfe, 0xc2, 0x43, 0x2a, 0xfc, 0xf1, 0x9f, 0x8e, 0xf9, 0x37, 0x4b, 0x6b, 0xf4, 0x29, 0x43, 0x80, 0xf6, 0x05, 0xc5, + 0xb4, 0xac, 0xa6, 0xa9, 0x94, 0x6c, 0x1b, 0xd6, 0xc4, 0xf3, 0x7d, 0xd3, 0x07, 0xdb, 0xc6, 0xcd, 0x27, 0x4d, 0x0f, + 0xfb, 0x59, 0x42, 0xa2, 0xa2, 0x4f, 0xe8, 0xa7, 0xb8, 0x53, 0x92, 0xd9, 0x72, 0x3e, 0xdc, 0xc8, 0x82, 0x72, 0x49, + 0x7e, 0x5e, 0x95, 0x99, 0xcb, 0x9f, 0x9d, 0x4c, 0x26, 0x45, 0xa9, 0xb1, 0xad, 0x1c, 0xa2, 0xe4, 0xf7, 0xa1, 0x6d, + 0xdb, 0x65, 0xf8, 0x6e, 0x3b, 0x28, 0x74, 0x30, 0x4c, 0x14, 0xc2, 0xb7, 0xef, 0xde, 0x53, 0x7f, 0xd0, 0x68, 0xa9, + 0xab, 0x6d, 0xe7, 0x91, 0xb6, 0xda, 0x7f, 0xc4, 0x50, 0x10, 0x35, 0xdc, 0x75, 0xfc, 0xab, 0x7b, 0x65, 0x47, 0x4f, + 0xe5, 0x03, 0x7c, 0xbf, 0xc6, 0x77, 0xec, 0xf5, 0x3d, 0x9a, 0x6e, 0xdb, 0xde, 0xa9, 0x95, 0x93, 0xdd, 0x82, 0xcd, + 0x52, 0x97, 0x2c, 0x95, 0xbc, 0x84, 0xcd, 0xe3, 0xce, 0x88, 0xa1, 0x82, 0xd4, 0x92, 0xa8, 0x2d, 0x5a, 0xf5, 0x98, + 0x53, 0xb0, 0xe3, 0x72, 0x04, 0x1e, 0xb6, 0x15, 0x54, 0x56, 0x55, 0x34, 0x6b, 0xe2, 0x23, 0x48, 0xc5, 0x36, 0x55, + 0x85, 0x13, 0x6e, 0xd3, 0x96, 0xfd, 0x97, 0x42, 0x3d, 0x05, 0xb8, 0xd3, 0x8d, 0xb0, 0x36, 0x21, 0xe5, 0x09, 0xfe, + 0x9d, 0x29, 0xe7, 0x9e, 0x2d, 0xd6, 0x45, 0xe3, 0xae, 0x36, 0xa8, 0x9b, 0x72, 0x52, 0x46, 0xa3, 0xae, 0x43, 0x7d, + 0x99, 0x09, 0xd0, 0x44, 0xb6, 0x6e, 0x01, 0x0b, 0x9a, 0x42, 0x5a, 0xde, 0x1a, 0xdd, 0x18, 0x5e, 0x67, 0x61, 0xe7, + 0xe5, 0xf2, 0x7d, 0xfc, 0x05, 0x09, 0x4a, 0x21, 0xea, 0xf9, 0x5f, 0x8c, 0xa7, 0x6d, 0x54, 0xee, 0x15, 0xb6, 0x2a, + 0x9a, 0xca, 0xe0, 0x1e, 0x10, 0x37, 0x52, 0x65, 0x19, 0xf9, 0x26, 0xe5, 0xac, 0xd5, 0xf4, 0x4d, 0x75, 0xde, 0xdb, + 0xbb, 0x77, 0x5a, 0xa0, 0xd7, 0xa8, 0x82, 0x6a, 0x2f, 0xd5, 0x5e, 0x59, 0x87, 0x2d, 0xc6, 0x09, 0x2b, 0x00, 0x8e, + 0x34, 0x0a, 0x1a, 0x0d, 0x29, 0x25, 0xdc, 0x47, 0x93, 0xce, 0xde, 0xca, 0xc8, 0x5a, 0xcc, 0x13, 0xbb, 0xab, 0xaf, + 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xc0, 0x8e, 0x63, 0x27, 0x7c, 0x36, 0x61, 0xc7, 0xc8, 0xe8, 0xca, 0xc1, 0x1d, 0x84, + 0xa7, 0xd4, 0xa4, 0x58, 0xe8, 0x74, 0x4a, 0x51, 0x97, 0xf0, 0x6d, 0xad, 0xf0, 0xfe, 0xa2, 0x20, 0x8d, 0xe7, 0x9e, + 0xa8, 0x0d, 0x7d, 0xaf, 0xda, 0x73, 0x2f, 0xd8, 0xbf, 0xae, 0xbb, 0xde, 0xbb, 0x2e, 0x30, 0x87, 0x7b, 0x57, 0x06, + 0xee, 0x92, 0xac, 0x94, 0x92, 0xde, 0xb7, 0x92, 0xf2, 0x40, 0x8e, 0xa2, 0xa4, 0x62, 0x2b, 0xba, 0xd1, 0xff, 0xb0, + 0xec, 0x0d, 0x4e, 0x4e, 0xd7, 0x73, 0x5f, 0xb9, 0x61, 0x11, 0xe4, 0xef, 0xee, 0xa9, 0x8e, 0x65, 0xab, 0x0a, 0xc6, + 0x04, 0xf2, 0x82, 0x69, 0x4f, 0xfd, 0xe9, 0xe2, 0xb5, 0xd9, 0x56, 0x4f, 0xc1, 0x1c, 0xe3, 0x66, 0x8a, 0x2c, 0xee, + 0x99, 0x7b, 0xcb, 0xa2, 0xeb, 0x86, 0xaa, 0x60, 0x9a, 0x6e, 0x62, 0x6e, 0xb1, 0x4c, 0x69, 0xa8, 0x7b, 0x64, 0x83, + 0x55, 0x6e, 0x3c, 0xb6, 0x7a, 0x1e, 0xae, 0x7b, 0x2a, 0x20, 0x56, 0xa7, 0xd1, 0x56, 0x9c, 0xc6, 0xa1, 0x75, 0xd4, + 0x56, 0xfb, 0x5f, 0x28, 0xca, 0xc9, 0x98, 0x4d, 0xe2, 0x3e, 0x8a, 0x63, 0x4e, 0x90, 0x1f, 0xa4, 0xdf, 0x8a, 0x62, + 0x8d, 0xfc, 0xd8, 0x74, 0x94, 0x0d, 0x7f, 0x54, 0x14, 0x40, 0x46, 0x1d, 0xe5, 0xe1, 0xa4, 0x31, 0x39, 0x9c, 0x3c, + 0xeb, 0xf2, 0xe2, 0xf4, 0x8b, 0x42, 0x75, 0x83, 0xfe, 0x6d, 0x48, 0xcd, 0xe2, 0x24, 0x0a, 0x3f, 0x30, 0xce, 0x4b, + 0x2a, 0x99, 0xa0, 0xa8, 0xdc, 0xb4, 0x51, 0xfd, 0x92, 0xd3, 0x1e, 0x8e, 0x26, 0x8d, 0xbc, 0x3a, 0x8e, 0xf1, 0x20, + 0x1b, 0xe4, 0xc9, 0x81, 0x18, 0xfa, 0x89, 0x0c, 0x26, 0xc7, 0xac, 0x03, 0x94, 0xa3, 0xf2, 0x39, 0x4e, 0xc5, 0xfc, + 0x4e, 0x20, 0xd9, 0x4a, 0xee, 0xd2, 0x10, 0x63, 0xb3, 0x9e, 0xfa, 0xbd, 0xd3, 0x68, 0x1b, 0x8e, 0x73, 0x64, 0x1d, + 0xb5, 0x47, 0xb6, 0x71, 0x68, 0x1d, 0x9a, 0x4d, 0xeb, 0xc8, 0x68, 0x9b, 0x6d, 0xa3, 0xfd, 0x4d, 0x7b, 0x64, 0x1e, + 0x5a, 0x87, 0x86, 0x6d, 0xb6, 0xa1, 0xd0, 0x6c, 0x9b, 0xed, 0x1b, 0xf3, 0xb0, 0x3d, 0xb2, 0xb1, 0xb4, 0x61, 0xb5, + 0x5a, 0xa6, 0x63, 0x5b, 0xad, 0x96, 0xd1, 0xb2, 0x8e, 0x8e, 0x4c, 0xa7, 0x69, 0x1d, 0x1d, 0x9d, 0xb5, 0xda, 0x56, + 0x13, 0xde, 0x35, 0x9b, 0xa3, 0xa6, 0xe5, 0x38, 0x26, 0xfc, 0x65, 0xb4, 0xad, 0x06, 0xfd, 0x70, 0x1c, 0xab, 0xe9, + 0x18, 0xb6, 0xdf, 0x6a, 0x58, 0x47, 0xcf, 0x0c, 0xfc, 0x1b, 0xab, 0x19, 0xf8, 0x17, 0x74, 0x63, 0x3c, 0xb3, 0x1a, + 0x47, 0xf4, 0x0b, 0x3b, 0xbc, 0x39, 0x6c, 0xff, 0x43, 0x3d, 0xd8, 0x3a, 0x07, 0x87, 0xe6, 0xd0, 0x6e, 0x59, 0xcd, + 0xa6, 0x71, 0xe8, 0x58, 0xed, 0xe6, 0xcc, 0x3c, 0x6c, 0x58, 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, + 0x6c, 0x5a, 0x0d, 0xc3, 0xb1, 0x0e, 0x9b, 0xf8, 0xa3, 0x69, 0x35, 0x6e, 0x8e, 0x9f, 0x59, 0x47, 0xad, 0xd9, 0x91, + 0x75, 0xf8, 0xfe, 0xb0, 0x6d, 0x35, 0x9a, 0xb3, 0xe6, 0x91, 0xd5, 0x38, 0xbe, 0x39, 0xb2, 0x0e, 0x67, 0x66, 0xe3, + 0x68, 0x67, 0x4b, 0xa7, 0x61, 0x01, 0x8c, 0xf0, 0x35, 0xbc, 0x30, 0xf8, 0x0b, 0xf8, 0x33, 0xc3, 0xb6, 0x7f, 0x60, + 0x37, 0x71, 0xb5, 0xe9, 0x33, 0xab, 0x7d, 0x3c, 0xa2, 0xea, 0x50, 0x60, 0x8a, 0x1a, 0xd0, 0xe4, 0xc6, 0xa4, 0xcf, + 0x62, 0x77, 0xa6, 0xe8, 0x48, 0xfc, 0xe1, 0x1f, 0xbb, 0x31, 0xe1, 0xc3, 0xf4, 0xdd, 0x3f, 0xb5, 0x9f, 0x6c, 0xc9, + 0x4f, 0x0e, 0xa6, 0xb4, 0xf5, 0xa7, 0xfd, 0x2f, 0x28, 0xb3, 0xf3, 0xc0, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x9f, 0x77, + 0x2b, 0x25, 0x9f, 0x2f, 0xf7, 0x51, 0x4a, 0xfe, 0xf3, 0xb3, 0x2b, 0x25, 0x7f, 0x29, 0xfb, 0xd6, 0xbc, 0x2e, 0x27, + 0xa0, 0xfc, 0x76, 0x53, 0x16, 0x39, 0x04, 0xae, 0x76, 0xf9, 0xc3, 0xf2, 0x0a, 0x82, 0xca, 0xbe, 0x0e, 0x7b, 0xcf, + 0x97, 0x05, 0x83, 0xcf, 0x10, 0x70, 0xec, 0xeb, 0x90, 0x70, 0xec, 0xfb, 0x65, 0x0f, 0xac, 0xcc, 0x38, 0x9b, 0xe3, + 0x8d, 0xcd, 0x99, 0xeb, 0x4f, 0x32, 0x16, 0x09, 0x4a, 0xba, 0x58, 0x0c, 0xce, 0x74, 0x40, 0x9e, 0xe1, 0x26, 0xb3, + 0x9c, 0x07, 0x31, 0x58, 0x04, 0x83, 0x25, 0xc7, 0x24, 0x4a, 0x4b, 0x8d, 0x2d, 0x11, 0x86, 0xf7, 0x9a, 0x7b, 0x59, + 0x6d, 0x7d, 0x8f, 0x06, 0xc0, 0xf5, 0xbd, 0x3b, 0xd5, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, + 0xbd, 0x2f, 0x9a, 0xe1, 0x96, 0x0c, 0xaf, 0xb7, 0x8f, 0x14, 0x46, 0x52, 0x6e, 0xef, 0x14, 0xcd, 0x78, 0xef, 0x9a, + 0x66, 0xcd, 0xe7, 0x0b, 0xcd, 0x77, 0xd8, 0x10, 0x67, 0x1d, 0x97, 0x41, 0xb5, 0x29, 0xf0, 0x69, 0xf5, 0x00, 0xc9, + 0x2f, 0xa8, 0xb9, 0xa1, 0x71, 0xce, 0xa9, 0xda, 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd0, 0xa7, 0x6c, 0x9c, 0xfc, + 0x64, 0x83, 0xf7, 0x0a, 0xef, 0x17, 0xe0, 0x44, 0x39, 0xc7, 0x33, 0x0c, 0x65, 0x38, 0x6f, 0xa4, 0x7e, 0x49, 0x1a, + 0x91, 0xce, 0x9c, 0x4d, 0x95, 0x17, 0xdd, 0xea, 0x96, 0xe0, 0xb0, 0xb9, 0xe0, 0x82, 0xf0, 0xf3, 0xe4, 0x04, 0x90, + 0x92, 0xa3, 0x06, 0xfa, 0x39, 0xec, 0xea, 0x4c, 0xd4, 0x7b, 0x08, 0x9b, 0x98, 0x67, 0x03, 0x50, 0xe4, 0x38, 0x67, + 0x9b, 0x89, 0x1f, 0xba, 0x49, 0x07, 0xd9, 0x34, 0x89, 0xe5, 0x6d, 0xa0, 0xc7, 0x42, 0x77, 0x87, 0x31, 0x9d, 0xdc, + 0x31, 0xef, 0x04, 0x3d, 0x1f, 0x76, 0xd9, 0xdf, 0x65, 0x0e, 0x67, 0x9b, 0x82, 0x39, 0x8a, 0xd3, 0x3a, 0x36, 0x9c, + 0x23, 0xc3, 0x3a, 0x6e, 0xe9, 0xa9, 0x38, 0x70, 0x72, 0x97, 0x05, 0x80, 0x80, 0x03, 0x44, 0x36, 0x4c, 0x2f, 0xf0, + 0x12, 0xcf, 0xf5, 0x53, 0xe0, 0x87, 0x8b, 0x97, 0x94, 0x7f, 0x2e, 0xe3, 0x04, 0xe6, 0x28, 0x98, 0x5e, 0x74, 0xfe, + 0x30, 0x87, 0x2c, 0x59, 0x31, 0x16, 0x6c, 0x31, 0x8c, 0x29, 0xfb, 0x92, 0xfc, 0x7e, 0x96, 0xf5, 0x29, 0x59, 0xad, + 0x0d, 0x93, 0x80, 0xef, 0x0f, 0xe1, 0xf8, 0x90, 0x0e, 0x8c, 0x6f, 0xb6, 0x21, 0xdc, 0x9f, 0xee, 0x46, 0xb8, 0x09, + 0xdb, 0x07, 0xe1, 0xfe, 0xf4, 0xd9, 0x11, 0xee, 0x37, 0x32, 0xc2, 0x2d, 0xf8, 0x0f, 0xe6, 0x1a, 0xa6, 0x73, 0x7c, + 0xd6, 0x20, 0x27, 0xd7, 0x53, 0xf5, 0x80, 0x18, 0x78, 0x55, 0xcf, 0x13, 0xd7, 0xfd, 0xad, 0x90, 0x22, 0x1c, 0x05, + 0xa0, 0x98, 0xef, 0x89, 0xd2, 0x11, 0x7b, 0xe0, 0xea, 0x96, 0xa5, 0x24, 0x66, 0x2b, 0xe5, 0x4d, 0x90, 0xf8, 0xd6, + 0x3b, 0x7e, 0x8f, 0x04, 0x85, 0xee, 0xeb, 0x30, 0x9a, 0xbb, 0x18, 0x77, 0x5c, 0xd5, 0xc1, 0x9d, 0x0e, 0x1e, 0x6c, + 0xf0, 0x0e, 0x1e, 0x85, 0xc1, 0x38, 0xd3, 0x4a, 0xb2, 0xde, 0x25, 0x71, 0xdc, 0xea, 0x2d, 0x73, 0x23, 0xd5, 0xa0, + 0xd7, 0xb0, 0xb8, 0x4f, 0x9a, 0xf6, 0x93, 0xc6, 0xe1, 0x93, 0x23, 0x1b, 0xfe, 0x77, 0x58, 0x33, 0x35, 0x78, 0xc5, + 0x79, 0x18, 0x40, 0x76, 0x63, 0x51, 0x73, 0x5b, 0xb5, 0x15, 0x63, 0x1f, 0xf2, 0x5a, 0xc7, 0xf5, 0x95, 0xc6, 0xee, + 0x6d, 0x5e, 0xa7, 0xb6, 0xc6, 0x2c, 0x5c, 0x4a, 0xc3, 0xaa, 0x19, 0x8d, 0x17, 0x2c, 0x41, 0xce, 0x2e, 0xd5, 0x90, + 0x5f, 0xf3, 0xe9, 0xe6, 0xf3, 0x62, 0xcd, 0xf4, 0x2a, 0x4f, 0xa1, 0x2e, 0x32, 0xe9, 0xdd, 0x09, 0x41, 0xae, 0xa2, + 0xb4, 0x31, 0x11, 0x05, 0xa6, 0x38, 0x82, 0x34, 0x14, 0x59, 0xe2, 0x6b, 0x97, 0x16, 0x28, 0x89, 0x96, 0xc1, 0x48, + 0xc3, 0x9f, 0xee, 0x30, 0xd6, 0xbc, 0x83, 0xc8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xdc, 0xbe, 0x9d, 0xe7, 0x9b, 0x8d, + 0xc5, 0xaa, 0xb8, 0x4f, 0x12, 0x23, 0x42, 0x3d, 0x36, 0x2d, 0xad, 0xd9, 0x73, 0x9f, 0x64, 0x0d, 0x9f, 0x24, 0x46, + 0xf0, 0x14, 0x74, 0x9f, 0x3d, 0xfb, 0xf1, 0x63, 0xaa, 0xf5, 0xa0, 0x27, 0xa6, 0x75, 0x3a, 0xca, 0xc3, 0x55, 0x2b, + 0xee, 0x34, 0xa4, 0x88, 0xd5, 0x9d, 0x91, 0x11, 0x3e, 0x7d, 0xda, 0xef, 0x39, 0x3a, 0xe6, 0x32, 0x4f, 0x45, 0x0c, + 0xd0, 0x00, 0x53, 0xd3, 0x9d, 0xed, 0x67, 0x68, 0xa4, 0xd7, 0xba, 0xd2, 0x2e, 0xe0, 0xce, 0x64, 0x0b, 0x77, 0x04, + 0x8e, 0xbd, 0x20, 0x6d, 0x2d, 0x19, 0x14, 0xb8, 0xc2, 0xe0, 0x47, 0xd4, 0xc9, 0x6e, 0x5d, 0x4d, 0xcb, 0xb6, 0x6c, + 0x35, 0x6b, 0x38, 0xf1, 0xa6, 0xbd, 0x4d, 0x98, 0xb8, 0x90, 0x00, 0xdc, 0x0f, 0xa7, 0xe0, 0x47, 0x97, 0x78, 0x89, + 0x0f, 0xd9, 0xa4, 0xc1, 0xa1, 0x6e, 0x4e, 0xf7, 0xf2, 0x94, 0x7b, 0x37, 0xb8, 0x11, 0x64, 0x2c, 0x8d, 0x6e, 0x85, + 0x2b, 0x2e, 0x46, 0x50, 0xfd, 0x1e, 0x88, 0xa1, 0xa6, 0x6a, 0x20, 0x1b, 0x60, 0x51, 0x6c, 0xca, 0xde, 0x42, 0x1d, + 0x05, 0xda, 0xe8, 0x2a, 0x9f, 0xc4, 0x24, 0x72, 0xe7, 0x90, 0x52, 0x6f, 0x93, 0x1a, 0x1c, 0xd3, 0xaa, 0x1c, 0xd5, + 0x2a, 0xce, 0xb3, 0x23, 0x43, 0x69, 0x38, 0x86, 0x62, 0x03, 0xba, 0x55, 0x53, 0x63, 0x93, 0x5e, 0x75, 0xef, 0x32, + 0x78, 0x20, 0xfc, 0xf2, 0x90, 0xe6, 0x41, 0xa6, 0x0e, 0x5c, 0x95, 0x94, 0x50, 0xe4, 0x7c, 0x4d, 0x4a, 0xa5, 0xe5, + 0x91, 0xd2, 0xf3, 0x82, 0xad, 0x13, 0x1d, 0xb3, 0x2d, 0xf3, 0x2a, 0x9e, 0xbe, 0x41, 0x87, 0x61, 0x2f, 0x50, 0xbc, + 0x8f, 0x1f, 0x35, 0x0f, 0x9c, 0x99, 0x7a, 0x12, 0x7c, 0xe0, 0x59, 0x2f, 0x00, 0xcc, 0xcb, 0xd5, 0xf4, 0x08, 0x2c, + 0xf0, 0x34, 0x84, 0x7f, 0xf3, 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0xbe, 0x1b, 0x4c, 0x01, 0xa5, 0xb9, 0xc1, 0xb4, + 0x62, 0x8e, 0x45, 0x3e, 0xcf, 0xa5, 0xd2, 0xbc, 0xab, 0xdc, 0x54, 0x2a, 0x7e, 0x7e, 0x7b, 0x41, 0xd9, 0xe4, 0x35, + 0x15, 0xa8, 0x1c, 0xba, 0xe8, 0xe6, 0x9a, 0xdc, 0xa7, 0xbd, 0x2f, 0x4f, 0xe6, 0x2c, 0x71, 0x49, 0x0d, 0x04, 0x97, + 0x5f, 0x60, 0x07, 0x14, 0x4e, 0x68, 0x78, 0x54, 0xc2, 0x1e, 0x25, 0xd8, 0x20, 0x3a, 0x61, 0x28, 0x9c, 0x4e, 0x99, + 0x68, 0xf1, 0xd9, 0x73, 0x0c, 0x72, 0x38, 0x18, 0xb9, 0x18, 0x64, 0xbf, 0x17, 0x84, 0x6a, 0xff, 0xcb, 0xcc, 0x37, + 0x73, 0xdb, 0x22, 0xf8, 0x5e, 0xf0, 0xe1, 0x32, 0x62, 0xfe, 0xbf, 0x7a, 0x5f, 0x02, 0xe1, 0xfe, 0xf2, 0x4a, 0xd5, + 0xbb, 0x89, 0x35, 0x8b, 0xd8, 0xa4, 0xf7, 0x25, 0xa6, 0xdd, 0x45, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xae, 0xe7, 0xbe, + 0x81, 0xd7, 0x7b, 0x1a, 0x8b, 0xda, 0x6c, 0xe4, 0xc1, 0x4e, 0x9b, 0x7b, 0x5d, 0xea, 0xfb, 0xfc, 0xb6, 0x0e, 0x37, + 0xc0, 0x4d, 0xe1, 0x8e, 0xed, 0x74, 0xf1, 0xfe, 0x3c, 0xf4, 0xdd, 0xd1, 0x87, 0x2e, 0xbd, 0x29, 0x3c, 0x98, 0x40, + 0xad, 0x47, 0xee, 0xa2, 0x83, 0xe4, 0x55, 0x2e, 0x04, 0xef, 0x69, 0x2a, 0xcd, 0x38, 0xbb, 0xda, 0xbd, 0x8c, 0x5b, + 0x79, 0x83, 0x5f, 0xc6, 0x4f, 0xad, 0x66, 0x5e, 0xc2, 0xc4, 0xa7, 0xf0, 0x21, 0x4d, 0xc5, 0x45, 0x9d, 0xae, 0xa8, + 0x78, 0xb1, 0xb6, 0x9a, 0x8a, 0xd3, 0xfe, 0xa6, 0x75, 0xe3, 0xd8, 0xb3, 0x86, 0x63, 0xb5, 0xdf, 0x3b, 0xed, 0x59, + 0xd3, 0x3a, 0xf6, 0xcd, 0xa6, 0x75, 0x0c, 0x7f, 0xde, 0x1f, 0x5b, 0xed, 0x99, 0xd9, 0xb0, 0x0e, 0xdf, 0x3b, 0x0d, + 0xdf, 0x6c, 0x5b, 0xc7, 0xf0, 0xe7, 0x8c, 0x5a, 0xc1, 0x05, 0x88, 0xee, 0x3b, 0x5f, 0x16, 0xb0, 0x80, 0xf4, 0x3b, + 0xd3, 0xc9, 0x1a, 0x05, 0xf2, 0x56, 0xa3, 0xd7, 0x05, 0x94, 0x41, 0xb9, 0xe6, 0xd0, 0x14, 0xa1, 0xab, 0x05, 0x3d, + 0x46, 0xd9, 0xe5, 0x84, 0x79, 0x9b, 0xf0, 0x43, 0x17, 0x29, 0xbe, 0x6a, 0x8f, 0x11, 0x6f, 0x53, 0x9f, 0xd6, 0x4a, + 0xa4, 0x9f, 0x27, 0x45, 0xf0, 0x4f, 0x0b, 0x0c, 0xca, 0x2a, 0xb2, 0x31, 0x4a, 0x58, 0x09, 0x7c, 0xcf, 0xad, 0x20, + 0x5c, 0xa1, 0x6d, 0xc5, 0x5d, 0x03, 0x47, 0x6f, 0x7e, 0x96, 0xa5, 0xe0, 0xfe, 0xac, 0x7d, 0x4b, 0x49, 0x2f, 0x3f, + 0xa9, 0x1f, 0x4c, 0x07, 0x98, 0x67, 0xf2, 0x83, 0x5c, 0x16, 0x63, 0x2f, 0xca, 0x86, 0x27, 0xa1, 0x68, 0xa7, 0x3e, + 0x1f, 0x98, 0x0e, 0xb9, 0x8a, 0xdf, 0x00, 0x97, 0x7c, 0xe3, 0xfa, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x41, 0x86, 0xf9, + 0x1f, 0x3f, 0xce, 0x07, 0x67, 0x96, 0xc6, 0x7d, 0xe2, 0xb4, 0x80, 0xec, 0xb6, 0x58, 0x73, 0xa7, 0x4d, 0x25, 0xdd, + 0x74, 0x76, 0xf9, 0x56, 0xe7, 0xe9, 0x0f, 0x84, 0xdd, 0x94, 0xb0, 0xd8, 0xd8, 0x6a, 0xd8, 0x59, 0xb1, 0xd7, 0x80, + 0xfc, 0x31, 0xa5, 0xab, 0x8e, 0xaa, 0x77, 0x03, 0x61, 0x7e, 0x10, 0xec, 0xc8, 0xfc, 0xc2, 0xef, 0x62, 0x2a, 0x80, + 0x66, 0xc7, 0x3c, 0xee, 0x70, 0x10, 0xff, 0xb3, 0x27, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x3a, 0xad, 0x05, 0xe7, + 0xbd, 0x8c, 0xae, 0x12, 0x41, 0x65, 0xf1, 0xa9, 0x0a, 0x45, 0x90, 0xc4, 0x1e, 0x70, 0xa3, 0x9a, 0x19, 0x8b, 0x66, + 0xd4, 0x22, 0x2f, 0x30, 0x3c, 0xcc, 0xb2, 0x25, 0x1c, 0x47, 0xf5, 0xc7, 0x8f, 0xb7, 0x12, 0x21, 0x32, 0xce, 0x89, + 0x59, 0x92, 0x65, 0xd6, 0x56, 0x65, 0xfc, 0xa6, 0xca, 0x28, 0x26, 0xeb, 0x17, 0xb1, 0x86, 0xb0, 0x71, 0xa5, 0xbd, + 0x87, 0x3f, 0x87, 0xcc, 0x4d, 0x2c, 0xae, 0x2c, 0xd5, 0x24, 0xe2, 0x6e, 0x38, 0xac, 0x09, 0xd6, 0xad, 0x3c, 0x76, + 0x73, 0x96, 0xa0, 0xf7, 0x6f, 0x4b, 0x1e, 0xd5, 0x01, 0xfa, 0xf8, 0x68, 0xe7, 0xc1, 0xb9, 0xde, 0x26, 0x2e, 0x85, + 0x24, 0x93, 0x49, 0x6e, 0x98, 0xb8, 0x22, 0x59, 0x34, 0xf0, 0xe5, 0xf5, 0x01, 0x59, 0xa4, 0xc8, 0x0f, 0xfd, 0xb7, + 0x17, 0x5f, 0x2b, 0x7c, 0xff, 0x93, 0xb5, 0x00, 0x5e, 0x64, 0x28, 0xe7, 0x5c, 0x8f, 0x72, 0xce, 0x29, 0x3c, 0xbd, + 0xa1, 0x8a, 0xd9, 0x82, 0x09, 0x82, 0x28, 0x80, 0x26, 0x1b, 0x8a, 0xf9, 0xd2, 0x4f, 0xbc, 0x85, 0x1b, 0x25, 0x07, + 0x98, 0x70, 0x0e, 0x90, 0x9c, 0xba, 0x2d, 0x1e, 0x04, 0x99, 0x61, 0x88, 0x90, 0xe1, 0x49, 0x20, 0xec, 0x30, 0x26, + 0x9e, 0x9f, 0x99, 0x61, 0x88, 0x0f, 0xb8, 0xa3, 0x11, 0x5b, 0x24, 0xbd, 0x42, 0x62, 0xbb, 0x70, 0x94, 0xb0, 0xc4, + 0x8c, 0x93, 0x88, 0xb9, 0x73, 0x35, 0x4b, 0x4d, 0x51, 0xed, 0x2f, 0x5e, 0x0e, 0xe7, 0x5e, 0x92, 0xc5, 0x76, 0xa7, + 0x09, 0x82, 0x41, 0x04, 0x0c, 0x11, 0x82, 0xcc, 0x10, 0x08, 0xcf, 0xc2, 0x69, 0x69, 0x47, 0xe5, 0x9c, 0xcb, 0x29, + 0x66, 0x0e, 0xa1, 0x9b, 0x0c, 0x48, 0x8b, 0x47, 0xa1, 0x7f, 0xcd, 0x63, 0x58, 0x64, 0x21, 0xe8, 0xd5, 0xfe, 0x09, + 0xbf, 0xde, 0x2a, 0x18, 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x1b, 0x65, 0x5b, 0x74, 0x8b, 0x03, 0x5e, 0x19, 0x48, 0x13, + 0xf5, 0x8c, 0xe9, 0xad, 0x68, 0x2c, 0x17, 0xc0, 0x08, 0x15, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x73, 0xa7, 0xc4, 0x51, + 0x21, 0xaf, 0xf4, 0xf1, 0xe3, 0xf9, 0xe0, 0xd7, 0x7f, 0x43, 0x0e, 0xae, 0x99, 0x23, 0x62, 0x4a, 0x5c, 0xca, 0xb5, + 0x38, 0xf7, 0x69, 0x0c, 0xd0, 0x58, 0x8a, 0x8d, 0x45, 0x08, 0x20, 0xb1, 0xb5, 0xd2, 0xc1, 0x95, 0x08, 0x0e, 0x0c, + 0xd9, 0xfb, 0x74, 0x11, 0xf9, 0x02, 0x93, 0x41, 0x0f, 0x44, 0x4c, 0x14, 0xe5, 0xe7, 0xf5, 0xf3, 0x63, 0x25, 0x8f, + 0xa9, 0x54, 0x67, 0xd1, 0x43, 0x7b, 0xa8, 0x7f, 0xe2, 0x2a, 0xc8, 0xb4, 0x20, 0xfb, 0x11, 0x77, 0x0e, 0x60, 0x9a, + 0xb3, 0x70, 0xce, 0x2c, 0x2f, 0x3c, 0x58, 0xb1, 0xa1, 0xe9, 0x2e, 0x3c, 0xb2, 0xcb, 0x41, 0xb9, 0x9b, 0x42, 0x9c, + 0x5f, 0x66, 0xee, 0x42, 0xfc, 0x75, 0x9a, 0x83, 0x32, 0x2c, 0x46, 0x83, 0x6e, 0x35, 0x72, 0x3d, 0xe0, 0x21, 0x05, + 0x80, 0x13, 0x70, 0x0c, 0xfb, 0x27, 0x07, 0x6e, 0xbf, 0x18, 0x8e, 0xde, 0x12, 0x69, 0xd5, 0x8a, 0x44, 0xe0, 0x94, + 0xa2, 0xca, 0x8b, 0x00, 0xf2, 0xf9, 0x83, 0x19, 0x4e, 0x26, 0x72, 0x08, 0x79, 0xab, 0x38, 0xbc, 0x0c, 0x68, 0xf9, + 0x96, 0x0e, 0x17, 0xf4, 0xa5, 0xea, 0x27, 0xb2, 0x9f, 0x6a, 0x07, 0x73, 0x47, 0xc0, 0x9c, 0xe1, 0xb8, 0x57, 0x42, + 0xd1, 0x67, 0x10, 0x7b, 0x48, 0x95, 0x38, 0x1e, 0x29, 0x27, 0x3e, 0xda, 0xc2, 0xb9, 0x3c, 0xe8, 0xf5, 0x08, 0xcd, + 0x95, 0xb1, 0x1d, 0x00, 0xb1, 0x26, 0xc5, 0x1c, 0x4c, 0x36, 0x81, 0x86, 0x26, 0xb9, 0xcb, 0x62, 0xa3, 0xf2, 0x74, + 0xaa, 0x63, 0x3c, 0x70, 0xc5, 0xf6, 0x2b, 0x6c, 0x50, 0xd8, 0x78, 0x7c, 0xdd, 0x01, 0xbf, 0x8b, 0x7e, 0x4a, 0x68, + 0x5e, 0xf9, 0x8a, 0x30, 0xba, 0xe9, 0xbb, 0xb7, 0xa1, 0x64, 0xc6, 0xc4, 0x23, 0x9a, 0x9c, 0x61, 0xe9, 0x85, 0xf0, + 0x24, 0xae, 0x1c, 0x34, 0x24, 0x61, 0x90, 0x8a, 0xab, 0x7a, 0xd8, 0x72, 0xfa, 0xeb, 0xb3, 0xbb, 0xce, 0x9a, 0x5c, + 0xb7, 0x38, 0x19, 0x44, 0x9e, 0x69, 0x7e, 0x0e, 0x0b, 0x2f, 0x11, 0x2d, 0xa4, 0x27, 0x07, 0x30, 0x3f, 0x88, 0xc2, + 0x52, 0x60, 0x9c, 0x3c, 0x1d, 0x42, 0xbd, 0xb8, 0x31, 0x99, 0x62, 0xbd, 0x19, 0x0b, 0x9e, 0x0f, 0x2f, 0x96, 0x52, + 0x82, 0x59, 0xa9, 0x4a, 0x95, 0x97, 0xb1, 0xeb, 0x99, 0xc0, 0xbb, 0xf3, 0xd6, 0xbd, 0x5f, 0x62, 0xd2, 0xba, 0xb4, + 0x9b, 0x30, 0x11, 0xe4, 0xe0, 0x2c, 0xd9, 0x12, 0x07, 0x61, 0x5b, 0x15, 0xe2, 0x67, 0x77, 0x54, 0xc8, 0xf7, 0xf1, + 0xae, 0x5a, 0x39, 0xe7, 0x94, 0x55, 0x9b, 0xba, 0x9a, 0xfa, 0x10, 0x77, 0x7c, 0xa5, 0x36, 0x96, 0x42, 0xbd, 0xb3, + 0xa4, 0x07, 0x55, 0x85, 0x2c, 0xde, 0x5d, 0x2c, 0xa8, 0xb2, 0xde, 0x3d, 0x39, 0xa0, 0x6b, 0x69, 0x9f, 0x76, 0x58, + 0xff, 0x04, 0x4c, 0xb9, 0x69, 0xd1, 0xdd, 0xc5, 0x82, 0x2f, 0x29, 0xfd, 0xa2, 0x37, 0x07, 0xb3, 0x64, 0xee, 0xf7, + 0xff, 0x17, 0x99, 0x05, 0x40, 0xf2, 0xa6, 0x72, 0x03, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0x2b, 0x6c, 0x53, 0x31, 0x36, 0x86, 0xd6, 0x0d, 0xad, 0x13, 0x60, 0xc6, 0xfb, 0x5a, 0xd7, 0x08, 0x1b, 0x45, - 0xb0, 0x71, 0x00, 0x41, 0x10, 0x63, 0x53, 0x09, 0xbb, 0x95, 0x19, 0x6a, 0x27, 0xa0, 0xa2, 0x2a, 0xf7, 0x9b, 0x74, - 0x02, 0xa8, 0x6a, 0xd6, 0x51, 0x19, 0x43, 0x13, 0x5d, 0x5a, 0x68, 0x01, 0x45, 0x70, 0xfb, 0xcf, 0xc8, 0xe0, 0xa5, - 0x52, 0x09, 0x12, 0x12, 0xc9, 0x8d, 0xc5, 0xd1, 0x07, 0x3a, 0x35, 0x6a, 0x31, 0x2e, 0x19, 0xec, 0x9e, 0x4f, 0xc0, - 0xac, 0x20, 0xb0, 0xb0, 0x9d, 0xf2, 0x9d, 0xd1, 0x1d, 0xaa, 0x76, 0x51, 0x95, 0x96, 0x2f, 0xc1, 0x38, 0x0d, 0x1b, - 0x75, 0xa3, 0xab, 0x38, 0x0f, 0xb4, 0x34, 0xb8, 0x3f, 0x94, 0x22, 0x9d, 0xf1, 0x6f, 0xec, 0xa0, 0x1d, 0x93, 0x72, - 0x4e, 0x24, 0x12, 0x9e, 0xe4, 0x8e, 0x1e, 0x9a, 0x78, 0x8b, 0x0a, 0x8d, 0xd0, 0x15, 0x7e, 0xbb, 0x75, 0xb4, 0xa8, - 0x6e, 0x1f, 0xe9, 0xbf, 0xc3, 0xbf, 0xe3, 0xf9, 0x7f, 0xaa, 0xf0, 0x1e, 0x15, 0xf5, 0xd2, 0x67, 0xac, 0x5f, 0x43, - 0x10, 0x36, 0x12, 0x0b, 0xc1, 0x9b, 0xc5, 0x6d, 0x91, 0x71, 0xe0, 0x3b, 0x38, 0x85, 0xbe, 0xcd, 0x60, 0x56, 0x0e, - 0x5f, 0x32, 0xe1, 0x5e, 0xc6, 0xbd, 0x18, 0x75, 0x38, 0xe9, 0x07, 0xa7, 0x15, 0xa6, 0xc3, 0x21, 0x3b, 0x6e, 0x86, - 0x4d, 0xad, 0x3f, 0x91, 0xcb, 0x00, 0xc7, 0x98, 0xb8, 0x1e, 0x16, 0xbd, 0x58, 0xe4, 0x90, 0x45, 0xfc, 0x71, 0xf4, - 0xab, 0xd7, 0xb4, 0xfa, 0xfa, 0x1d, 0xe0, 0x1c, 0x10, 0x94, 0x41, 0x6b, 0xf6, 0xce, 0x6b, 0xc6, 0xcb, 0x8f, 0xb3, - 0xbd, 0x0c, 0x2a, 0x55, 0xf5, 0xd0, 0x55, 0xa3, 0xe4, 0xcb, 0xbe, 0xcc, 0xc4, 0x92, 0x14, 0x82, 0xf7, 0xfe, 0xd2, - 0xea, 0xeb, 0x97, 0x54, 0x67, 0x9d, 0xd2, 0x52, 0x72, 0xba, 0x33, 0x77, 0xd1, 0x65, 0xfa, 0xba, 0xd3, 0xc7, 0x9d, - 0xf5, 0xf3, 0x60, 0x90, 0x09, 0x13, 0x22, 0x58, 0x49, 0x8e, 0x21, 0xa0, 0xb9, 0x6c, 0xed, 0xbf, 0xd3, 0x75, 0x8a, - 0xb1, 0xea, 0xf1, 0xd7, 0x75, 0x4e, 0xac, 0x8a, 0xec, 0x8a, 0xeb, 0x85, 0x89, 0xa1, 0x81, 0x68, 0xec, 0xf0, 0x93, - 0x06, 0x97, 0xbf, 0x98, 0xa6, 0xbe, 0xde, 0x52, 0x17, 0xb3, 0xc9, 0x8c, 0x0d, 0xd6, 0x63, 0x6c, 0x75, 0x31, 0x14, - 0xce, 0x82, 0xad, 0x00, 0x36, 0x80, 0xb3, 0x9b, 0xe8, 0xf2, 0x55, 0xed, 0xbf, 0x7e, 0x43, 0x3e, 0x0f, 0x66, 0xf9, - 0x28, 0x32, 0x58, 0xa8, 0xb8, 0x64, 0x98, 0x5a, 0x9c, 0x5a, 0x7c, 0x30, 0xb5, 0x14, 0x91, 0x83, 0x16, 0x0a, 0xb0, - 0x4c, 0xac, 0x08, 0x67, 0x69, 0x89, 0x7b, 0x7d, 0x89, 0x15, 0x26, 0x8b, 0x9c, 0xb6, 0xf7, 0xa3, 0xec, 0x97, 0x52, - 0xba, 0xf1, 0x6d, 0xb8, 0x43, 0x96, 0x2d, 0x6c, 0xd3, 0x07, 0x08, 0xd5, 0xb7, 0xfc, 0xaa, 0x75, 0xd4, 0x61, 0x7c, - 0xf3, 0x76, 0xe5, 0x90, 0x28, 0x60, 0x59, 0x55, 0x74, 0x8c, 0x3f, 0x05, 0xf1, 0x5a, 0xcb, 0x7a, 0xfd, 0x53, 0xf3, - 0x9e, 0x42, 0x22, 0x5e, 0xbf, 0x5c, 0x73, 0x1d, 0x26, 0x73, 0x98, 0x5f, 0x43, 0x37, 0x86, 0x8d, 0x80, 0x2b, 0xa8, - 0xeb, 0xc2, 0xff, 0xf7, 0x6f, 0xd3, 0xef, 0xeb, 0xd7, 0x50, 0x36, 0xd1, 0x46, 0x4b, 0xc8, 0x7e, 0x3d, 0x9f, 0xe3, - 0x6b, 0xf5, 0x30, 0xcc, 0x6e, 0x0a, 0xd1, 0x0e, 0x49, 0xc8, 0x00, 0x2e, 0x20, 0xd3, 0xbb, 0xda, 0xbe, 0xd9, 0xec, - 0xeb, 0x74, 0xa5, 0x98, 0x28, 0x78, 0x56, 0x4b, 0xb2, 0x65, 0x1b, 0x33, 0x53, 0x6c, 0x4a, 0xe7, 0xcd, 0xfc, 0xcc, - 0xdf, 0xde, 0x94, 0x26, 0xfb, 0x95, 0x93, 0xaa, 0xda, 0x58, 0xb5, 0x31, 0xf5, 0x1c, 0xec, 0x2b, 0x70, 0xc6, 0x01, - 0x74, 0xe1, 0xfd, 0xd7, 0x37, 0xb5, 0xff, 0xfa, 0x95, 0x88, 0x0e, 0x7b, 0x6e, 0x75, 0xa4, 0x20, 0xfe, 0xbc, 0xec, - 0x0d, 0xe1, 0x74, 0x5d, 0xec, 0x59, 0x05, 0x65, 0x41, 0xc4, 0xc9, 0xe8, 0xc1, 0xb0, 0x1f, 0x4a, 0x77, 0x09, 0x4c, - 0xc2, 0xe7, 0x7e, 0xa0, 0xce, 0xd6, 0x4c, 0x98, 0xc0, 0xec, 0x64, 0xc5, 0x36, 0xe6, 0x06, 0xfd, 0x90, 0x88, 0x33, - 0xff, 0xc1, 0x71, 0x11, 0xf5, 0x6b, 0xa6, 0xf5, 0x51, 0x7a, 0xd2, 0x39, 0x10, 0x2d, 0xb4, 0x26, 0x1b, 0xdd, 0xd3, - 0x7c, 0x9f, 0xbb, 0x6c, 0xbe, 0x82, 0xae, 0xa1, 0xb5, 0x43, 0x15, 0x4b, 0xab, 0x30, 0xe7, 0xb1, 0xd7, 0x46, 0xbd, - 0xff, 0xab, 0x6d, 0x66, 0xa4, 0x41, 0x2e, 0x4e, 0xf9, 0x90, 0xfb, 0x96, 0x86, 0xc2, 0xd2, 0xdb, 0x6c, 0xfd, 0x2c, - 0x85, 0x4c, 0x73, 0x33, 0xe8, 0x77, 0x20, 0xbf, 0xe1, 0x26, 0x89, 0x82, 0x0b, 0x14, 0xb6, 0x15, 0xb8, 0xf6, 0xfa, - 0x1a, 0x99, 0xae, 0x7a, 0xdf, 0x7e, 0x5e, 0xd0, 0x93, 0xa4, 0xc2, 0xc6, 0x92, 0x81, 0x99, 0xcc, 0xcc, 0x86, 0x10, - 0x4d, 0xd2, 0xc8, 0xc2, 0x68, 0x57, 0x48, 0x9c, 0x25, 0xd2, 0x0a, 0xfe, 0x9f, 0xd5, 0xb1, 0x61, 0xea, 0x86, 0x34, - 0x79, 0x42, 0x8b, 0xf2, 0x82, 0xe5, 0x6f, 0xaf, 0x96, 0x5f, 0xdf, 0xde, 0xf1, 0x87, 0x7c, 0x95, 0xf4, 0x2f, 0xa5, - 0x38, 0xbe, 0x74, 0x56, 0x93, 0xe0, 0xdd, 0xbb, 0x4e, 0xa0, 0xeb, 0x86, 0x36, 0xf0, 0x10, 0x20, 0xcf, 0x85, 0xc8, - 0xff, 0xdf, 0x5b, 0x69, 0xb9, 0xfd, 0x91, 0xae, 0x8a, 0x68, 0x07, 0x90, 0xe3, 0x0c, 0x47, 0xd6, 0xef, 0x3b, 0x2b, - 0x0b, 0xa0, 0x1a, 0x20, 0xd9, 0xe3, 0xcc, 0x4a, 0x5a, 0x6b, 0xb1, 0xa9, 0xb8, 0xf7, 0xbe, 0x77, 0x99, 0xdf, 0x45, - 0x67, 0xfc, 0x30, 0xac, 0x30, 0x99, 0x8d, 0x74, 0xd5, 0x2c, 0xdb, 0xc8, 0x72, 0x1a, 0x00, 0x04, 0xef, 0x7d, 0xff, - 0x47, 0xe1, 0xff, 0x1f, 0x59, 0xec, 0x1f, 0x91, 0x05, 0x9e, 0xc8, 0xac, 0xe2, 0x9c, 0xac, 0x02, 0x66, 0x54, 0x05, - 0x72, 0x46, 0x05, 0xb0, 0x8f, 0x0e, 0xc8, 0xb1, 0xf4, 0x9a, 0xa6, 0x3b, 0x1a, 0x52, 0xde, 0xef, 0xb4, 0x58, 0xa1, - 0x29, 0xef, 0x77, 0x3b, 0x50, 0xc6, 0xad, 0xa4, 0xa5, 0xb4, 0xd4, 0xbd, 0xba, 0xd7, 0xf5, 0xc2, 0x4e, 0x26, 0x2e, - 0x4d, 0x4e, 0x27, 0x65, 0x18, 0xb6, 0xfa, 0xee, 0x64, 0x90, 0x3e, 0xcb, 0x21, 0x39, 0x28, 0x17, 0xed, 0xa2, 0x5d, - 0xa6, 0x91, 0x78, 0x5b, 0x88, 0x87, 0x89, 0xc7, 0xbe, 0xda, 0x1a, 0xe3, 0xbf, 0xb1, 0x04, 0x4c, 0x2b, 0x5f, 0xb0, - 0x2c, 0xff, 0x6e, 0x7f, 0x54, 0xeb, 0x7b, 0x3d, 0x6a, 0xe9, 0xd7, 0x51, 0x77, 0xbb, 0xb8, 0x0a, 0xee, 0x10, 0x20, - 0x04, 0xba, 0xe7, 0x31, 0xd4, 0x9a, 0xfb, 0x6b, 0x1c, 0x88, 0xc8, 0x50, 0x4c, 0xda, 0xfe, 0xdd, 0x4b, 0xbf, 0xe5, - 0xb3, 0x07, 0x68, 0x01, 0xb5, 0x3d, 0xf2, 0xff, 0x6d, 0x92, 0x9d, 0xe1, 0x21, 0xd3, 0xea, 0xd0, 0xa6, 0xcb, 0xd7, - 0x37, 0x84, 0x10, 0x20, 0x90, 0x2e, 0xed, 0x6d, 0x93, 0xa1, 0x6b, 0x6c, 0xf5, 0x77, 0x81, 0x00, 0x29, 0x04, 0x78, - 0xe9, 0x31, 0xb4, 0xae, 0x92, 0x6a, 0x70, 0xdf, 0x19, 0x9f, 0xd4, 0x0d, 0x50, 0x6b, 0xac, 0xd3, 0x1a, 0x24, 0x25, - 0xd7, 0x75, 0x22, 0xb8, 0x7f, 0x36, 0x64, 0xe2, 0x9c, 0x71, 0x00, 0x7b, 0x3a, 0x8e, 0x68, 0x0b, 0x3a, 0x03, 0xe6, - 0x38, 0x77, 0xf0, 0x21, 0x1b, 0xc1, 0x74, 0xb4, 0x87, 0x92, 0xcb, 0x31, 0x0a, 0xb1, 0x07, 0x51, 0xe1, 0x85, 0xd5, - 0xa5, 0x0f, 0x4c, 0xfe, 0x4e, 0xaa, 0x18, 0xcc, 0xdd, 0xea, 0x13, 0x0e, 0x08, 0xb4, 0xde, 0x4b, 0x7e, 0x50, 0xe0, - 0x95, 0xdf, 0x47, 0xe8, 0x4c, 0x02, 0x25, 0x5f, 0x7e, 0x12, 0xb9, 0x11, 0xf3, 0x2d, 0x0f, 0xed, 0xec, 0xd8, 0x1d, - 0x3c, 0x38, 0xf0, 0x7e, 0x1e, 0xb4, 0xc7, 0x2f, 0xe4, 0x27, 0x5c, 0x96, 0x61, 0x4f, 0x63, 0x3d, 0xbf, 0x1a, 0xa3, - 0x29, 0x7a, 0xc9, 0x5a, 0x30, 0xf7, 0xdc, 0xe5, 0xa1, 0xd9, 0xfc, 0x60, 0xac, 0x91, 0x81, 0xdb, 0xb4, 0xb3, 0xb6, - 0xa5, 0x7e, 0x60, 0x97, 0x62, 0x01, 0x38, 0x09, 0x00, 0x64, 0x39, 0x6c, 0x3e, 0x36, 0x18, 0x05, 0xe1, 0xd7, 0xf2, - 0x66, 0x37, 0xde, 0x96, 0xfb, 0x61, 0x82, 0x8e, 0x64, 0x43, 0x0f, 0x08, 0xdb, 0xfb, 0xf0, 0xec, 0x67, 0x63, 0x00, - 0x65, 0xd4, 0xec, 0xc7, 0xcd, 0x2d, 0x74, 0x4d, 0x1b, 0x50, 0xc2, 0x1d, 0x59, 0xa8, 0xb2, 0xa7, 0x20, 0xb1, 0xa1, - 0xcb, 0xe0, 0xb9, 0xec, 0x3e, 0xef, 0xc7, 0xa4, 0xe6, 0x96, 0xac, 0xd3, 0x0d, 0x97, 0x06, 0x35, 0x1b, 0xde, 0x4f, - 0x9b, 0x54, 0x32, 0xe2, 0x36, 0xbd, 0xdf, 0xed, 0x8f, 0x4c, 0xee, 0x45, 0x33, 0xbf, 0xd1, 0x78, 0x3d, 0x4c, 0x81, - 0xbd, 0xf5, 0xe1, 0xf4, 0x41, 0xd0, 0x6c, 0x64, 0x36, 0xf1, 0x8d, 0xaf, 0x7a, 0x70, 0x48, 0x82, 0x44, 0xed, 0xdf, - 0xf7, 0xa0, 0x79, 0x11, 0x8e, 0xfa, 0x33, 0xef, 0x15, 0xea, 0x5b, 0x3f, 0xb2, 0x46, 0xcb, 0x37, 0x83, 0xdb, 0x5d, - 0x2e, 0x5f, 0xdf, 0x0e, 0x87, 0x83, 0x47, 0x5f, 0xc4, 0xf8, 0xf8, 0xa7, 0xcd, 0xcb, 0xcd, 0x8d, 0xa8, 0x0d, 0x6a, - 0x98, 0x86, 0x84, 0xa9, 0xe6, 0xf7, 0x7e, 0x89, 0x94, 0xfc, 0x3f, 0xdf, 0x93, 0x59, 0x9d, 0xfe, 0xf3, 0x37, 0x97, - 0xba, 0x02, 0xed, 0xd4, 0x33, 0xdf, 0xfc, 0x81, 0xf0, 0xf4, 0xaf, 0x54, 0x16, 0x58, 0x57, 0xe8, 0x7f, 0xd6, 0x37, - 0xe7, 0xdd, 0x4e, 0x08, 0xdb, 0x79, 0x98, 0x6f, 0x98, 0xba, 0x3d, 0x8f, 0xb9, 0xea, 0x93, 0x10, 0xe2, 0x44, 0x5b, - 0x1b, 0x84, 0x10, 0xd4, 0x8e, 0xf1, 0xa2, 0x19, 0x9c, 0xdb, 0x3d, 0x04, 0xd9, 0x6d, 0x6a, 0x2b, 0xad, 0x03, 0xdf, - 0xc2, 0x87, 0x03, 0x24, 0xd0, 0x5f, 0x60, 0x00, 0x69, 0xf1, 0x79, 0x77, 0xa9, 0x73, 0x0e, 0xbc, 0x06, 0x00, 0x22, - 0x87, 0x7a, 0x36, 0x9c, 0x0a, 0x4b, 0xe4, 0xc8, 0xd3, 0x78, 0x6e, 0xc8, 0x92, 0xa1, 0x47, 0x3e, 0xbd, 0xf7, 0x77, - 0xa8, 0xc3, 0x8b, 0x05, 0x76, 0xf8, 0xc8, 0xc1, 0x4d, 0xbd, 0xc2, 0x84, 0xbc, 0x38, 0x2b, 0x1e, 0x97, 0xa1, 0xd4, - 0x6a, 0x22, 0x2a, 0x71, 0xab, 0x1a, 0xe4, 0x3d, 0x47, 0x37, 0x52, 0xbe, 0x6a, 0x3b, 0x33, 0x73, 0x7d, 0x5b, 0x00, - 0xda, 0x73, 0x28, 0xf7, 0xb2, 0x74, 0xa9, 0x5b, 0x00, 0x82, 0xf4, 0xac, 0xef, 0xf7, 0xf9, 0x8d, 0x2f, 0x0b, 0x9d, - 0x8f, 0xda, 0x56, 0x50, 0x72, 0x45, 0x4d, 0x9e, 0x2a, 0xfb, 0x49, 0xb9, 0x97, 0xa5, 0x22, 0xfd, 0xa0, 0x23, 0x2f, - 0xc4, 0x89, 0x0c, 0x5a, 0xc1, 0x9e, 0x83, 0x89, 0x2b, 0x87, 0x79, 0x89, 0xbf, 0xac, 0x82, 0x45, 0x00, 0x1a, 0xe9, - 0x17, 0x44, 0xb3, 0x01, 0xaa, 0xa6, 0xe9, 0xcc, 0xc2, 0x71, 0xd4, 0xe2, 0x99, 0x36, 0xcc, 0xb9, 0xdf, 0xef, 0xf0, - 0xea, 0x94, 0x70, 0xd1, 0x8a, 0xd1, 0x02, 0x4d, 0xf0, 0xc3, 0xaf, 0xe4, 0xb0, 0x9a, 0x40, 0xeb, 0x8a, 0x99, 0x16, - 0x36, 0x65, 0x96, 0x69, 0xb0, 0xd0, 0x03, 0xbb, 0x43, 0x37, 0xcd, 0x2b, 0x7f, 0xc3, 0x97, 0xcf, 0x71, 0xb3, 0xc7, - 0xdd, 0x7b, 0xcb, 0x37, 0x32, 0xf7, 0x65, 0xe9, 0x01, 0xe5, 0xdd, 0x24, 0xf0, 0x94, 0x6e, 0xd7, 0x78, 0x37, 0x45, - 0x4f, 0x70, 0xff, 0xdc, 0x2b, 0x91, 0x3e, 0x1e, 0x6e, 0x43, 0xf4, 0x1a, 0x40, 0xe0, 0xbe, 0x50, 0xb6, 0x62, 0xea, - 0x4d, 0x80, 0x48, 0xee, 0xef, 0x72, 0xde, 0xc2, 0x47, 0xec, 0x5d, 0xca, 0x82, 0xc6, 0x4a, 0xd8, 0x93, 0xd6, 0xb7, - 0xaa, 0xf6, 0x80, 0x01, 0xc8, 0x5e, 0x85, 0x61, 0xd8, 0x1d, 0x43, 0xcc, 0x4e, 0xb2, 0x73, 0xdc, 0x17, 0x13, 0x96, - 0xf9, 0x83, 0xe6, 0xd0, 0x4d, 0xe5, 0x7d, 0xba, 0x93, 0xb1, 0x4a, 0x5b, 0x92, 0xca, 0x5d, 0xe3, 0xef, 0x08, 0x68, - 0x21, 0x5b, 0x0f, 0x87, 0x26, 0xbe, 0xc9, 0xbe, 0xe0, 0x3a, 0xe8, 0x09, 0x7a, 0x59, 0x76, 0x66, 0x5c, 0xaa, 0xc5, - 0xf2, 0xe6, 0xd1, 0x81, 0x40, 0xd8, 0xea, 0x88, 0xce, 0x06, 0xdb, 0x49, 0xef, 0x58, 0x8d, 0x86, 0xb1, 0xc5, 0xe0, - 0xff, 0xa1, 0x37, 0xf1, 0x52, 0xb6, 0xc8, 0x4d, 0xf5, 0x5c, 0xe6, 0x22, 0xf7, 0x7b, 0xfc, 0xbe, 0x9f, 0x01, 0x0e, - 0x16, 0x86, 0xa5, 0x8e, 0x40, 0xbf, 0x47, 0x4f, 0x6d, 0x15, 0x2c, 0x12, 0x6d, 0xee, 0x33, 0xed, 0x43, 0xf1, 0x2c, - 0x05, 0xf1, 0xa9, 0xcc, 0xdd, 0xa6, 0x3c, 0x70, 0x44, 0xad, 0xda, 0xa8, 0x42, 0x28, 0x41, 0x84, 0x60, 0xea, 0xa7, - 0x5c, 0xeb, 0xda, 0x54, 0x58, 0xed, 0xa2, 0x3c, 0x17, 0x86, 0x38, 0x74, 0x90, 0x83, 0x3a, 0x44, 0xe1, 0xff, 0xec, - 0x1e, 0xfa, 0x24, 0x67, 0x5c, 0x54, 0xdc, 0x13, 0x1c, 0x36, 0xee, 0x89, 0x32, 0x30, 0xf7, 0x97, 0x23, 0xcb, 0xee, - 0x01, 0xbd, 0x0f, 0x5a, 0x31, 0x28, 0xf9, 0xae, 0x56, 0x3c, 0xa3, 0xef, 0x41, 0x68, 0x04, 0x03, 0xf0, 0xcc, 0x37, - 0x83, 0x07, 0x16, 0xf0, 0xa8, 0x60, 0x50, 0x2a, 0xde, 0x69, 0xe8, 0xa6, 0x97, 0x40, 0x07, 0xc4, 0xb5, 0x7c, 0x3d, - 0x9c, 0x20, 0x58, 0x49, 0xc7, 0x42, 0x7b, 0x92, 0xe2, 0x64, 0x4e, 0xc8, 0xb0, 0x55, 0xa1, 0x3e, 0x09, 0x86, 0xf9, - 0x70, 0x50, 0x7e, 0x79, 0x79, 0x33, 0x20, 0x9e, 0xf5, 0x35, 0xf0, 0x9b, 0x4e, 0x40, 0xe0, 0xc7, 0x2e, 0x93, 0x54, - 0x8a, 0xa4, 0x1b, 0x2e, 0x53, 0x8a, 0x39, 0x4d, 0x9b, 0xeb, 0x4b, 0x0f, 0x39, 0xcd, 0x9d, 0x5a, 0xfa, 0x89, 0x3a, - 0xa0, 0x6d, 0xf1, 0x7b, 0x16, 0x3c, 0x57, 0x3f, 0x1c, 0x11, 0xec, 0xd6, 0x6a, 0x3b, 0xe6, 0xe6, 0xa5, 0xe5, 0x36, - 0x55, 0x4e, 0x36, 0xb4, 0xb7, 0x39, 0x5b, 0x08, 0x60, 0x8a, 0x69, 0x50, 0x2d, 0x2f, 0x92, 0xb9, 0x5e, 0x88, 0xd9, - 0x9f, 0x98, 0x49, 0x1e, 0x08, 0x5e, 0x39, 0x48, 0xa5, 0x0f, 0x6d, 0xe9, 0xb9, 0x2b, 0xc1, 0xf0, 0xbd, 0x96, 0x32, - 0xb0, 0x06, 0xb7, 0xb5, 0x65, 0x79, 0x0c, 0xab, 0x60, 0xca, 0x20, 0x90, 0xf5, 0xe7, 0xa0, 0xed, 0x11, 0x67, 0x8f, - 0x7a, 0xcc, 0xb0, 0x30, 0xfb, 0x7c, 0x0f, 0x1c, 0x52, 0x25, 0x0b, 0x41, 0x72, 0x58, 0xe8, 0xaf, 0xc5, 0x99, 0x69, - 0x82, 0x0a, 0x89, 0xd0, 0x6e, 0x15, 0x0f, 0xee, 0x3f, 0x48, 0x4f, 0x11, 0xb6, 0xd5, 0x5d, 0x4a, 0xb3, 0x6b, 0x64, - 0x31, 0x50, 0xd8, 0x58, 0x3d, 0x4c, 0x5c, 0x23, 0x84, 0xd3, 0xe6, 0xfa, 0x6e, 0xba, 0x48, 0x44, 0x97, 0x52, 0x44, - 0xb1, 0x71, 0xa3, 0x74, 0x09, 0x0f, 0x6b, 0x66, 0x2c, 0xc7, 0x26, 0x90, 0x9c, 0xb9, 0x63, 0x50, 0xc7, 0xb7, 0x1c, - 0x40, 0x02, 0xdc, 0x23, 0x86, 0xed, 0xc1, 0x24, 0x40, 0xae, 0x09, 0x12, 0x24, 0xb4, 0xcf, 0x07, 0x64, 0xc0, 0x82, - 0x8c, 0x8c, 0x89, 0x75, 0x23, 0x28, 0xb9, 0xfb, 0x3a, 0xea, 0x8f, 0x01, 0xce, 0xca, 0xc9, 0xda, 0x02, 0x11, 0x13, - 0xc7, 0x9b, 0x4a, 0x83, 0x80, 0xb1, 0x0c, 0xb0, 0x63, 0xe9, 0xa8, 0xe4, 0x5c, 0x1c, 0xc8, 0xd7, 0x43, 0x33, 0xbf, - 0x70, 0x70, 0x1e, 0x45, 0x1a, 0xd6, 0x2e, 0x20, 0x20, 0x67, 0x3e, 0xdd, 0xf6, 0x60, 0xe4, 0x20, 0x71, 0xad, 0xee, - 0xb4, 0x0c, 0x56, 0x11, 0xf9, 0xa4, 0x18, 0x37, 0x17, 0x65, 0x2a, 0xc4, 0xc5, 0x3a, 0xaf, 0x21, 0x17, 0x79, 0x70, - 0x1b, 0xbc, 0x73, 0xa3, 0x27, 0x5d, 0x27, 0x2c, 0x01, 0x58, 0x8f, 0xa5, 0x64, 0xc0, 0xad, 0x9a, 0x9e, 0xfd, 0x3a, - 0x48, 0x09, 0xbc, 0x7a, 0xe2, 0x39, 0xc4, 0xf1, 0x85, 0x11, 0xd5, 0xe0, 0xdf, 0xd6, 0x28, 0x51, 0xd8, 0x36, 0xcc, - 0x9a, 0x71, 0x5a, 0xc5, 0xb0, 0x67, 0x94, 0x67, 0x22, 0xe6, 0x2f, 0x19, 0x93, 0x46, 0xc2, 0x8a, 0xa7, 0x56, 0x4b, - 0x53, 0xe1, 0x33, 0x46, 0x28, 0x44, 0xec, 0x11, 0x68, 0x0a, 0xec, 0x7b, 0x43, 0x62, 0xca, 0x6f, 0x7a, 0x4e, 0xdc, - 0x9e, 0xac, 0xb3, 0x39, 0x1b, 0x66, 0x88, 0x5d, 0x04, 0x74, 0xbb, 0xd5, 0x3a, 0x5c, 0xd9, 0xa7, 0xd2, 0x68, 0x4a, - 0x36, 0xa8, 0x25, 0x98, 0x08, 0x93, 0xe1, 0x79, 0x76, 0x81, 0xc8, 0x7b, 0x4d, 0x33, 0x93, 0x2e, 0xf4, 0x6a, 0xfa, - 0x13, 0x40, 0x1e, 0xf7, 0xe4, 0x52, 0x69, 0xca, 0x72, 0x85, 0x03, 0x90, 0xdb, 0x05, 0xf3, 0x38, 0x31, 0xa5, 0x56, - 0x25, 0x37, 0xee, 0xb8, 0x98, 0x49, 0xcd, 0x74, 0x77, 0xb1, 0x39, 0x21, 0x01, 0x12, 0xd5, 0x92, 0xd9, 0xe0, 0x35, - 0xa0, 0x78, 0x4f, 0x00, 0x91, 0x88, 0x46, 0xe1, 0x3b, 0xbf, 0x96, 0xa3, 0x73, 0x26, 0x41, 0x5b, 0x98, 0xab, 0xdb, - 0x79, 0xf1, 0xb9, 0x4a, 0x54, 0xb9, 0xe1, 0x68, 0x07, 0xb0, 0x45, 0xfb, 0xa2, 0xf0, 0x79, 0x04, 0x7e, 0xfa, 0xb8, - 0x30, 0xe8, 0xd6, 0xd4, 0x31, 0x45, 0x3d, 0x9b, 0xdd, 0x65, 0x58, 0xe0, 0x35, 0x4e, 0x99, 0xe8, 0xf9, 0x6f, 0xd5, - 0xdd, 0x10, 0x75, 0xfe, 0x3a, 0x76, 0xc0, 0x56, 0xdb, 0xec, 0x1c, 0xce, 0xe7, 0xfc, 0x59, 0x9c, 0x1c, 0x30, 0xab, - 0x3a, 0x5b, 0x3b, 0x3f, 0xf6, 0xcb, 0xbf, 0x9c, 0xfc, 0x41, 0xc6, 0x02, 0xc8, 0xab, 0x02, 0xa9, 0xc8, 0xc8, 0x74, - 0x40, 0x89, 0x97, 0x96, 0xcf, 0xc5, 0x00, 0x2d, 0x32, 0xaf, 0x5a, 0x32, 0x14, 0x92, 0xd5, 0xb0, 0xf2, 0x06, 0x10, - 0x64, 0x0b, 0x33, 0xd7, 0x28, 0x38, 0x42, 0x1e, 0xb5, 0xd8, 0x98, 0x37, 0x2c, 0xa7, 0xa2, 0x58, 0xa6, 0xad, 0x39, - 0xb2, 0x08, 0x5a, 0x1c, 0x10, 0xd7, 0x5f, 0xa0, 0x3a, 0x1a, 0xd4, 0x95, 0x37, 0xbb, 0x11, 0x06, 0xd8, 0x0d, 0x37, - 0x92, 0x4d, 0x8c, 0xbd, 0x12, 0x8a, 0x9c, 0x06, 0xd2, 0xd8, 0x4f, 0xde, 0x49, 0xf8, 0xed, 0xae, 0x1d, 0xe6, 0xbe, - 0x3c, 0x9c, 0x99, 0x4c, 0x0c, 0x29, 0xed, 0x86, 0x83, 0x40, 0xd4, 0xcf, 0x16, 0x8a, 0x29, 0xa7, 0xb5, 0xc7, 0x70, - 0xd7, 0x75, 0x2e, 0xc9, 0xdb, 0xc7, 0x3c, 0x10, 0x90, 0xdf, 0x09, 0xac, 0x01, 0x71, 0x14, 0x51, 0x04, 0xc2, 0x7e, - 0xd6, 0xdf, 0x1c, 0x47, 0x7e, 0x1b, 0x60, 0xc9, 0xae, 0x87, 0xba, 0xa5, 0x6c, 0x31, 0x23, 0x6b, 0x79, 0xe5, 0x14, - 0x54, 0x5c, 0x7a, 0x94, 0x33, 0x0f, 0xc4, 0x1b, 0x44, 0x0d, 0x96, 0xb3, 0xcf, 0xdb, 0x85, 0x03, 0x95, 0x14, 0xb2, - 0xf7, 0xd3, 0x20, 0x2f, 0x9e, 0x5f, 0x38, 0xab, 0xe5, 0x14, 0xd3, 0x21, 0xd5, 0x36, 0xca, 0x84, 0x71, 0xc5, 0xde, - 0x06, 0x5e, 0x9c, 0x78, 0x78, 0x78, 0xb8, 0xf5, 0x40, 0x40, 0xd6, 0x3a, 0x27, 0x72, 0x33, 0x8b, 0xce, 0xf7, 0x27, - 0x91, 0xce, 0xda, 0xf2, 0x90, 0x97, 0xf3, 0xa2, 0x0d, 0xb2, 0xe8, 0x96, 0x98, 0x85, 0xb1, 0x61, 0x03, 0xcb, 0xdd, - 0xb7, 0xf1, 0x11, 0x87, 0x4c, 0x52, 0xb6, 0xa7, 0xd9, 0x76, 0x6f, 0xb8, 0xf9, 0x2e, 0x9a, 0x68, 0x99, 0x2c, 0x4c, - 0xd7, 0xee, 0x17, 0xc9, 0x6a, 0x2f, 0x45, 0xb5, 0x64, 0x3e, 0x86, 0xbd, 0x73, 0x47, 0x6a, 0x2f, 0x1d, 0x54, 0x9d, - 0x46, 0x33, 0x8e, 0x73, 0x02, 0xda, 0x28, 0x98, 0x5d, 0xe1, 0xc5, 0x20, 0xbb, 0x48, 0x61, 0x99, 0x95, 0xc2, 0x66, - 0x0c, 0x4b, 0xa9, 0xfb, 0x41, 0xa2, 0xb3, 0x0c, 0x31, 0x68, 0xd2, 0xe7, 0xc6, 0x1e, 0x8d, 0xe2, 0x11, 0xaa, 0x08, - 0x6b, 0xf7, 0xc7, 0x09, 0x0a, 0xa9, 0xce, 0xf2, 0x04, 0x43, 0x7b, 0x3e, 0x42, 0xc7, 0x05, 0xcc, 0x2f, 0x67, 0xa2, - 0xde, 0xbf, 0xdc, 0x3c, 0x16, 0x5e, 0x7d, 0x48, 0x71, 0x4d, 0xe9, 0xad, 0x7c, 0x65, 0x3e, 0x67, 0x94, 0x67, 0x86, - 0xce, 0x28, 0x15, 0x96, 0xd9, 0x5c, 0x88, 0x91, 0x24, 0xcd, 0x87, 0xf9, 0x66, 0x80, 0xcd, 0x10, 0x94, 0xc8, 0x50, - 0xdc, 0x18, 0xc5, 0x62, 0x0c, 0x63, 0x0d, 0x28, 0x77, 0x8b, 0x66, 0x4e, 0x1a, 0xcd, 0x9d, 0x4c, 0x72, 0xc3, 0x77, - 0x3f, 0x55, 0x23, 0x4c, 0x53, 0x88, 0x5d, 0xc7, 0x17, 0x35, 0x59, 0x39, 0x55, 0xc3, 0x2d, 0xae, 0x9c, 0x22, 0x68, - 0x99, 0xc5, 0x7d, 0x9a, 0xbb, 0xc4, 0x04, 0xb0, 0x15, 0xd8, 0x9d, 0xaa, 0xa8, 0x54, 0xd0, 0x87, 0x4e, 0x37, 0x77, - 0x30, 0x9c, 0xd8, 0x86, 0x48, 0xd6, 0x32, 0x74, 0x10, 0x6d, 0xff, 0x3e, 0xc8, 0xe8, 0xd0, 0xf1, 0xdb, 0xd5, 0x98, - 0x0a, 0x81, 0x9a, 0x45, 0x5c, 0xd9, 0x0c, 0x69, 0x52, 0x88, 0x6b, 0x5c, 0x9e, 0x08, 0xe2, 0xbc, 0x8f, 0xb5, 0x06, - 0xf2, 0x76, 0x90, 0xb9, 0x86, 0x75, 0xd9, 0x80, 0x68, 0xf4, 0x42, 0x54, 0x7e, 0xdd, 0xa0, 0x3d, 0x68, 0xc2, 0x64, - 0x1e, 0x0c, 0xc4, 0x3c, 0x47, 0x6d, 0xd6, 0xc8, 0x58, 0x65, 0xe0, 0x08, 0x94, 0x23, 0xf3, 0xd2, 0x58, 0x3f, 0xb5, - 0x4b, 0xf4, 0x86, 0xc2, 0xc0, 0x76, 0xad, 0x96, 0x92, 0x01, 0x37, 0xc6, 0x82, 0xbb, 0x31, 0xe9, 0x54, 0x41, 0x3d, - 0x90, 0x3d, 0xeb, 0x1b, 0x18, 0x4f, 0x89, 0x09, 0x1f, 0x1c, 0x70, 0x34, 0xdf, 0x24, 0xbd, 0x74, 0x4d, 0xb4, 0xa2, - 0x95, 0x85, 0xf8, 0x73, 0x85, 0xd2, 0x56, 0x8d, 0x0e, 0x7c, 0x05, 0x60, 0x00, 0x99, 0x0a, 0x2a, 0x51, 0x25, 0xe5, - 0x50, 0x61, 0x3c, 0x68, 0xca, 0x75, 0x35, 0x56, 0xde, 0xb9, 0x77, 0xc3, 0xc3, 0x9f, 0xde, 0x60, 0xa4, 0x75, 0x57, - 0xf8, 0x30, 0xd9, 0x5f, 0x45, 0x48, 0x11, 0xf6, 0xcc, 0xd8, 0xc1, 0xc6, 0x3c, 0x73, 0xe4, 0xd3, 0x6b, 0xa7, 0x36, - 0xdb, 0xbe, 0xba, 0x70, 0xc6, 0x2c, 0x57, 0xef, 0x11, 0xc9, 0xd8, 0x2a, 0x02, 0x1a, 0xdd, 0xe6, 0xeb, 0xe1, 0x24, - 0x0d, 0x7f, 0x2c, 0x52, 0xfc, 0xbf, 0xaa, 0x20, 0xaa, 0x40, 0x0b, 0x69, 0x0e, 0x7a, 0x0e, 0x59, 0x83, 0x4d, 0x49, - 0x23, 0x07, 0x5b, 0x7b, 0x60, 0x13, 0x13, 0x9c, 0x45, 0x8c, 0x76, 0x91, 0x89, 0x11, 0x3c, 0x83, 0xfa, 0x4b, 0xab, - 0x10, 0x3a, 0x47, 0x60, 0xaa, 0x5d, 0x2c, 0x7d, 0xd1, 0x64, 0x1c, 0x40, 0xde, 0xbd, 0x7f, 0x87, 0xf8, 0x91, 0xd4, - 0xb0, 0xb9, 0xf2, 0xdf, 0xfc, 0x55, 0x14, 0x31, 0x2a, 0x47, 0xc2, 0x54, 0x48, 0x68, 0x5d, 0x67, 0xc5, 0xc0, 0xc7, - 0x16, 0xb1, 0x86, 0x59, 0x7e, 0xb2, 0xde, 0xe0, 0x4a, 0x10, 0xb2, 0x8b, 0x40, 0xe3, 0x0c, 0x41, 0x46, 0x95, 0x27, - 0x46, 0xc1, 0x3b, 0x04, 0x70, 0x4b, 0xd0, 0x8e, 0xc1, 0x34, 0xb7, 0x2e, 0x12, 0x5a, 0x8c, 0x25, 0xf5, 0x01, 0x93, - 0x91, 0x90, 0xe2, 0x67, 0xe5, 0xb0, 0x60, 0x5e, 0x18, 0x4d, 0xc5, 0x87, 0x2a, 0x3a, 0x8a, 0xdb, 0xf0, 0x82, 0xd9, - 0xea, 0xa3, 0xa8, 0xd4, 0x46, 0x9d, 0xe6, 0x65, 0x73, 0x8e, 0x68, 0x3b, 0xd7, 0xdd, 0xbc, 0x13, 0x20, 0xee, 0x84, - 0x96, 0x30, 0x2e, 0x43, 0xaa, 0x5b, 0x96, 0x96, 0x62, 0x1d, 0x2e, 0x72, 0xc9, 0xfc, 0xae, 0x21, 0xde, 0x7f, 0x15, - 0xe2, 0xd3, 0x63, 0x81, 0xda, 0xce, 0x8f, 0x2e, 0x84, 0x12, 0x98, 0x05, 0x8d, 0xd5, 0x3c, 0x86, 0x62, 0x1d, 0x09, - 0xd3, 0x61, 0xc2, 0xd0, 0x1a, 0x6f, 0x54, 0x2b, 0x1e, 0xa9, 0xac, 0x07, 0x0b, 0xef, 0x49, 0x0c, 0x5b, 0x2d, 0xe9, - 0x72, 0xd6, 0x75, 0x52, 0xd9, 0xef, 0x97, 0xc8, 0xe4, 0xe9, 0xfc, 0xd8, 0x4f, 0x6a, 0x17, 0x15, 0x27, 0xa3, 0x73, - 0xed, 0x79, 0x7f, 0x24, 0xe6, 0xc0, 0x63, 0x6c, 0x1b, 0xc8, 0x38, 0x4b, 0x67, 0x2c, 0xe5, 0x20, 0x07, 0xc3, 0x62, - 0x9f, 0xf9, 0x9d, 0x70, 0xf2, 0x4b, 0x5e, 0x21, 0x26, 0x70, 0x23, 0xc2, 0x80, 0x3a, 0x75, 0x6f, 0x84, 0x4c, 0x38, - 0xf4, 0x3f, 0x93, 0xdb, 0xbe, 0x47, 0x7c, 0x4b, 0xbe, 0x98, 0x19, 0x70, 0xbe, 0xb1, 0x59, 0x0c, 0xc5, 0xdd, 0xc9, - 0xc8, 0xa6, 0xc4, 0x85, 0x84, 0xfa, 0x98, 0x99, 0x67, 0xb7, 0xd9, 0x5f, 0x47, 0xf0, 0x26, 0x3f, 0xae, 0x89, 0x9f, - 0xca, 0x5c, 0xff, 0x6d, 0xe2, 0x6f, 0x19, 0xc2, 0x26, 0x6f, 0x54, 0x20, 0x6b, 0x07, 0x59, 0x10, 0x49, 0xdc, 0xca, - 0x1b, 0x5d, 0xef, 0xf1, 0x8d, 0x26, 0x6e, 0x22, 0x53, 0x72, 0x2d, 0x38, 0x67, 0x8e, 0x63, 0x75, 0x6f, 0x1c, 0x96, - 0x1a, 0x9f, 0x18, 0xff, 0x48, 0x2f, 0x82, 0xe5, 0x8d, 0xaf, 0x2f, 0x5e, 0x64, 0x7e, 0x51, 0xa2, 0x4e, 0xb0, 0xc8, - 0x78, 0x1e, 0x26, 0x06, 0x3d, 0x8d, 0x54, 0xcb, 0xbf, 0x94, 0x80, 0x6e, 0xc4, 0x32, 0xef, 0x78, 0xe4, 0x01, 0x5f, - 0x00, 0x9b, 0x05, 0x87, 0xe4, 0xbd, 0xc7, 0x90, 0xf4, 0x4d, 0x26, 0x67, 0x53, 0x8e, 0x63, 0xad, 0xec, 0x56, 0x0b, - 0xd0, 0xfd, 0xb4, 0xfa, 0x67, 0x7b, 0x41, 0xbe, 0x9e, 0x24, 0x67, 0x15, 0xdc, 0xa2, 0x35, 0x6b, 0xa4, 0x58, 0x26, - 0xd7, 0x87, 0xf1, 0xb7, 0xc6, 0x87, 0x31, 0x09, 0x52, 0xb4, 0xff, 0x4a, 0xda, 0x88, 0x10, 0x5a, 0x56, 0xbf, 0x50, - 0x96, 0x39, 0xb3, 0xd0, 0x7b, 0x01, 0xca, 0x24, 0x62, 0x0f, 0xf6, 0x6a, 0xb6, 0x1e, 0xc6, 0xdb, 0xd1, 0xc4, 0xad, - 0xab, 0xe3, 0x98, 0x9c, 0x93, 0x11, 0xf7, 0xeb, 0x82, 0xec, 0x7a, 0x8f, 0x34, 0x9b, 0x76, 0xf9, 0xa7, 0x18, 0x6d, - 0xbf, 0x5a, 0xa8, 0x85, 0xb6, 0xbe, 0xb6, 0xa5, 0x17, 0x28, 0xb0, 0xfc, 0xd5, 0x68, 0x33, 0xae, 0x08, 0x9d, 0x5b, - 0xab, 0xfc, 0xfc, 0x73, 0x98, 0x09, 0x93, 0xa2, 0xf1, 0x9f, 0x76, 0xff, 0xbb, 0xeb, 0x98, 0xa0, 0x48, 0x76, 0x4d, - 0x6e, 0x2f, 0xed, 0x66, 0x9a, 0xee, 0x06, 0x59, 0x31, 0x12, 0xc7, 0xdb, 0x5f, 0xdf, 0xfd, 0xfa, 0xd7, 0x44, 0x90, - 0x9f, 0xb8, 0x2d, 0xce, 0xa4, 0x2e, 0xf6, 0xff, 0xe7, 0xaf, 0xcb, 0xdb, 0x97, 0x3f, 0xa4, 0xea, 0x2b, 0x7a, 0x7e, - 0x91, 0xa5, 0x69, 0x3f, 0xaa, 0x7d, 0x84, 0x63, 0xb0, 0x6d, 0x02, 0x41, 0x90, 0x2f, 0x9a, 0xf4, 0xa7, 0xc3, 0xf8, - 0x4e, 0xc3, 0xec, 0x33, 0xe5, 0xde, 0xe0, 0xa5, 0xfb, 0xab, 0x7e, 0x39, 0x1d, 0xb6, 0xb4, 0xa1, 0x6a, 0x2d, 0x6f, - 0xfe, 0x5a, 0xa7, 0x9c, 0xe9, 0x46, 0x39, 0xff, 0xbc, 0xec, 0xaf, 0x06, 0x93, 0xeb, 0x7e, 0x59, 0x4f, 0x04, 0xbb, - 0x13, 0x3a, 0x51, 0x4d, 0x87, 0x74, 0x4c, 0xac, 0x6a, 0x0f, 0xc7, 0x8b, 0xec, 0x24, 0xab, 0xe8, 0x95, 0x5f, 0xc3, - 0xc9, 0x6f, 0xac, 0x8e, 0xea, 0xa9, 0x20, 0x2e, 0x98, 0x8b, 0x40, 0xe2, 0xb9, 0xfe, 0x3b, 0x98, 0xeb, 0xa1, 0xf7, - 0xaa, 0xeb, 0x4c, 0xd3, 0x0b, 0x3c, 0xec, 0xaa, 0x26, 0x50, 0xfb, 0xf6, 0xb6, 0x22, 0xb6, 0x19, 0xc7, 0x81, 0x0f, - 0xb1, 0x68, 0xe7, 0x98, 0x85, 0x42, 0xc4, 0xb3, 0x7e, 0x17, 0x66, 0x0d, 0xae, 0xef, 0xdf, 0xbe, 0x12, 0x5f, 0x3e, - 0xdd, 0x30, 0x3c, 0x00, 0x97, 0x13, 0xef, 0x49, 0xfb, 0x17, 0xaa, 0xf4, 0x84, 0xa4, 0x4e, 0xae, 0xac, 0x55, 0x8f, - 0x99, 0x7d, 0x1f, 0x0d, 0x6f, 0x18, 0x98, 0xf9, 0x78, 0xdf, 0x07, 0x79, 0x56, 0x91, 0x9e, 0xe3, 0x97, 0x69, 0x0e, - 0x04, 0x28, 0xa2, 0x00, 0x69, 0x90, 0xaf, 0x92, 0x1c, 0xbe, 0x26, 0x1e, 0x1e, 0x3c, 0xb7, 0xb8, 0xfa, 0xdc, 0x80, - 0x64, 0x0d, 0x57, 0x6b, 0x63, 0x75, 0x0a, 0x50, 0x12, 0x6b, 0x87, 0x80, 0xf6, 0x3f, 0xbd, 0x70, 0x05, 0x5b, 0x6f, - 0xe2, 0x96, 0x83, 0xa3, 0x3a, 0x35, 0x69, 0xf6, 0x16, 0x46, 0xb6, 0x16, 0xde, 0x74, 0x74, 0xc2, 0x43, 0x8e, 0x71, - 0xba, 0xa2, 0x12, 0xd3, 0xe3, 0xce, 0xdc, 0xe3, 0xe0, 0x7f, 0x2e, 0x21, 0x11, 0x99, 0x36, 0xe9, 0x1b, 0x16, 0x55, - 0xa5, 0xd5, 0x0a, 0x6e, 0xf6, 0x2a, 0xd1, 0x4b, 0x98, 0x66, 0xfc, 0xbe, 0xc9, 0xe4, 0x02, 0x78, 0x9d, 0xe1, 0x7e, - 0xfc, 0x79, 0x7f, 0x31, 0xe7, 0x11, 0xc8, 0xc5, 0x6b, 0x01, 0x12, 0x68, 0xc0, 0xfa, 0xba, 0x0c, 0x71, 0xc9, 0x84, - 0x51, 0x2c, 0x56, 0xe4, 0x3c, 0xde, 0x2a, 0x42, 0xe3, 0xab, 0x4a, 0x6a, 0xac, 0x7a, 0x81, 0x6e, 0x8a, 0xd9, 0x76, - 0xfe, 0x77, 0x9b, 0x4a, 0x59, 0x0f, 0x7b, 0x80, 0xfb, 0xe7, 0x01, 0xf4, 0x1d, 0x6d, 0xce, 0x26, 0xf5, 0xe1, 0xef, - 0x54, 0xa2, 0x80, 0xd6, 0x0e, 0x3d, 0x2c, 0x39, 0x7f, 0x14, 0xea, 0x3f, 0x01, 0xba, 0x00, 0x78, 0xcd, 0xb7, 0x72, - 0xa8, 0x02, 0xd0, 0x1e, 0x35, 0x4d, 0x99, 0x47, 0xad, 0x53, 0xa1, 0x2c, 0x7c, 0x7d, 0xcd, 0x1d, 0x2e, 0x7f, 0x32, - 0x90, 0x5f, 0x6d, 0xe1, 0x14, 0x48, 0x82, 0x27, 0x0a, 0xe2, 0xb0, 0xf2, 0xf3, 0xe3, 0xfd, 0xc7, 0x65, 0x9a, 0x82, - 0x66, 0xfa, 0x42, 0xe1, 0xfa, 0x71, 0xc9, 0x5f, 0x58, 0xf6, 0x71, 0xbd, 0x84, 0xf6, 0xc0, 0xc3, 0xfb, 0x7e, 0x5c, - 0xf3, 0xcb, 0xd9, 0xd5, 0x3c, 0xdf, 0x2d, 0x7b, 0xf3, 0xdc, 0xad, 0x91, 0xb8, 0xca, 0x1c, 0xc0, 0xd2, 0x89, 0x52, - 0xc7, 0xef, 0x33, 0x31, 0x55, 0x69, 0xfc, 0xbe, 0x50, 0xa3, 0x8e, 0x1e, 0x55, 0x79, 0x7a, 0xb8, 0x0a, 0x16, 0x59, - 0x87, 0x7f, 0x2e, 0x05, 0xbe, 0xfc, 0x0f, 0x38, 0xc9, 0x9f, 0x52, 0xff, 0x24, 0x17, 0x67, 0xc2, 0x66, 0xe1, 0xb1, - 0x77, 0xc5, 0xc8, 0x1a, 0x76, 0xd1, 0x3a, 0x7c, 0xee, 0xb0, 0xcf, 0x2b, 0x33, 0xdd, 0x66, 0xd0, 0xb3, 0xe4, 0xaa, - 0xa0, 0x68, 0xb5, 0xd0, 0xc5, 0xcb, 0x3c, 0x5c, 0x11, 0xd3, 0xda, 0xf1, 0x22, 0xd8, 0x14, 0xda, 0x17, 0x8d, 0xa7, - 0x37, 0xe7, 0x6a, 0x28, 0x93, 0x90, 0xde, 0xc9, 0xcc, 0xcc, 0xbc, 0xbf, 0x66, 0x36, 0x5f, 0xb8, 0xce, 0x25, 0xa6, - 0x30, 0xa0, 0xdf, 0x51, 0x50, 0xc2, 0xd5, 0x57, 0x2c, 0x56, 0xb4, 0xbc, 0x77, 0x64, 0x75, 0xdd, 0x3b, 0x5e, 0xdd, - 0x05, 0xa2, 0xdc, 0xbf, 0x59, 0xaa, 0x00, 0x5e, 0x18, 0xce, 0x36, 0xc2, 0xdc, 0x15, 0xc4, 0x5a, 0x44, 0x1a, 0x8c, - 0x1e, 0xe4, 0xbb, 0x9b, 0x49, 0x2f, 0xa8, 0x53, 0x2e, 0xef, 0x7f, 0x7a, 0x73, 0xae, 0x5a, 0x70, 0x7a, 0xf1, 0xe3, - 0xeb, 0x75, 0x4a, 0xb0, 0xba, 0x16, 0x6a, 0xf2, 0x26, 0x35, 0x4e, 0xb9, 0x3d, 0x0c, 0x90, 0x41, 0x43, 0x17, 0x2d, - 0xef, 0x43, 0x69, 0x5c, 0x6c, 0x5f, 0x63, 0xdd, 0xf7, 0x0d, 0x0a, 0x51, 0x57, 0x91, 0xf7, 0x0c, 0x83, 0xfb, 0x81, - 0x4a, 0x11, 0x97, 0x97, 0xf2, 0xa8, 0x6c, 0xb5, 0xd8, 0x92, 0x87, 0x89, 0xb3, 0x40, 0xfd, 0xcd, 0x86, 0xa7, 0x3d, - 0xae, 0x75, 0xc0, 0xd7, 0x2b, 0x09, 0xbe, 0xcc, 0x0d, 0x35, 0x02, 0x3a, 0x48, 0x91, 0x70, 0x30, 0x1b, 0x66, 0xd4, - 0x24, 0x9c, 0x66, 0x7d, 0x4b, 0x79, 0xc3, 0x64, 0xb0, 0xa9, 0x4f, 0x74, 0x61, 0x95, 0x6f, 0x3b, 0x6c, 0xd9, 0xe9, - 0x1d, 0x9c, 0xa9, 0x67, 0xcd, 0x7b, 0xeb, 0x51, 0xdb, 0x4e, 0xd3, 0x86, 0x84, 0x8b, 0xf4, 0xbd, 0xd8, 0x6f, 0x9d, - 0x9f, 0x42, 0xcb, 0xc9, 0xc5, 0x23, 0xc8, 0x54, 0x70, 0x8e, 0xc8, 0xad, 0x9f, 0xeb, 0x3f, 0x95, 0x31, 0x10, 0xf2, - 0x83, 0x3f, 0x4b, 0xf0, 0xa5, 0x1d, 0x01, 0x48, 0xc4, 0x87, 0x64, 0xf1, 0xb5, 0x5b, 0x42, 0x91, 0x85, 0xae, 0xd8, - 0x7b, 0x6e, 0x2c, 0x98, 0x89, 0x43, 0x52, 0x01, 0xfa, 0x9e, 0x59, 0xfb, 0xef, 0xd8, 0x18, 0x8b, 0x44, 0xd7, 0xf4, - 0x16, 0xdc, 0x65, 0xca, 0x93, 0xfb, 0xea, 0xb6, 0x4b, 0xe0, 0xab, 0x5b, 0x0c, 0xc5, 0x2d, 0x16, 0x60, 0x87, 0xd5, - 0x6d, 0xbc, 0xe9, 0x06, 0xd6, 0xb7, 0xd6, 0x19, 0x53, 0x06, 0x48, 0x37, 0x89, 0x6b, 0x41, 0x30, 0x44, 0xbd, 0x48, - 0x5a, 0x51, 0xfe, 0x40, 0xed, 0x12, 0x4e, 0x7a, 0x05, 0xc7, 0x47, 0xb7, 0x6e, 0x7f, 0xd7, 0x00, 0x8f, 0xfe, 0x5f, - 0xf5, 0xe1, 0xc9, 0xce, 0x8a, 0x2c, 0x4d, 0x53, 0xb1, 0x06, 0x34, 0x39, 0xb8, 0x04, 0xe2, 0xa6, 0x71, 0xed, 0xc3, - 0xfe, 0x29, 0xe5, 0x5b, 0x07, 0xd4, 0x3c, 0x33, 0x42, 0xb5, 0xf5, 0x14, 0xbe, 0xac, 0x2e, 0xb5, 0xb1, 0x90, 0x78, - 0xf9, 0xb2, 0xde, 0x7b, 0xe0, 0xf9, 0xe1, 0x97, 0x3d, 0x16, 0x94, 0x6b, 0x79, 0x96, 0xfe, 0xa3, 0xce, 0x70, 0x19, - 0xe0, 0x01, 0x8d, 0x2d, 0x21, 0xb9, 0xb2, 0xc1, 0xfb, 0xef, 0x21, 0xd4, 0xf9, 0xf0, 0x58, 0x6a, 0x9f, 0x95, 0x16, - 0x51, 0xb0, 0xf6, 0x01, 0x42, 0xdb, 0x10, 0x63, 0xd8, 0xe1, 0x82, 0x8f, 0x3e, 0xba, 0xcd, 0xb7, 0x54, 0x0e, 0x94, - 0xba, 0x72, 0xd5, 0xc7, 0x73, 0x00, 0x5e, 0x6b, 0x7f, 0xc7, 0x3a, 0x6d, 0xe3, 0x1a, 0x9f, 0xdd, 0xd8, 0x9e, 0x5a, - 0xd6, 0xca, 0x6d, 0x34, 0x2a, 0xe2, 0xaa, 0x8a, 0xe8, 0x73, 0xf1, 0xc9, 0xda, 0x45, 0x6d, 0xf9, 0x14, 0x60, 0x71, - 0x6b, 0xd9, 0xa6, 0xe3, 0x74, 0x75, 0xc9, 0x47, 0x2e, 0xd0, 0x19, 0xec, 0x0b, 0x16, 0x80, 0x9b, 0x43, 0x09, 0x0d, - 0x07, 0x18, 0x81, 0x3e, 0x18, 0x72, 0x55, 0x8a, 0x41, 0x06, 0x53, 0x15, 0x77, 0x2e, 0x4a, 0xde, 0xd3, 0x2e, 0x56, - 0xd3, 0x28, 0x0f, 0x0a, 0x1d, 0x02, 0x2e, 0xfb, 0xcf, 0x7a, 0xab, 0xd8, 0xe0, 0xcb, 0xcf, 0xf5, 0xd1, 0x62, 0xa5, - 0x9b, 0xf6, 0xc8, 0x8e, 0x3a, 0x8c, 0xf2, 0xd5, 0x66, 0x1e, 0x36, 0xc2, 0x94, 0xc0, 0x42, 0xe6, 0xe6, 0x71, 0x07, - 0xc4, 0x37, 0x99, 0x93, 0xcd, 0x92, 0xff, 0x89, 0x5d, 0x5e, 0x47, 0x88, 0xc8, 0xb1, 0xbe, 0xab, 0xc8, 0xe8, 0x14, - 0x4e, 0x72, 0x83, 0x00, 0x4e, 0x49, 0xcc, 0x18, 0x64, 0x4b, 0x55, 0x0e, 0xf9, 0xfd, 0x67, 0x5e, 0x42, 0xe8, 0x70, - 0x74, 0xcf, 0xcc, 0xba, 0xad, 0xc2, 0x1a, 0x51, 0x23, 0x65, 0x66, 0x37, 0x4a, 0x3c, 0xac, 0x98, 0x88, 0x94, 0xa4, - 0x33, 0x45, 0x3a, 0xc2, 0xe1, 0xee, 0x72, 0x93, 0x8e, 0x6d, 0xc7, 0x92, 0xa2, 0x6d, 0x16, 0xca, 0x08, 0x10, 0xf8, - 0xa8, 0x3f, 0x22, 0x88, 0xa6, 0x9a, 0xa2, 0x42, 0x2d, 0x6f, 0x6c, 0x6e, 0x47, 0xb7, 0x37, 0x2d, 0x68, 0xbf, 0x80, - 0x3f, 0x15, 0x14, 0xdc, 0x76, 0xd6, 0x73, 0x32, 0x15, 0x45, 0xea, 0x82, 0x34, 0x1d, 0x64, 0xd6, 0xaf, 0xd0, 0xc7, - 0xa7, 0x26, 0x44, 0xdd, 0x5f, 0x36, 0xb9, 0x82, 0x08, 0x81, 0x00, 0xe6, 0x65, 0xf9, 0x28, 0xe1, 0x93, 0x24, 0x11, - 0xa0, 0xea, 0x71, 0xe9, 0x91, 0xb5, 0x54, 0x34, 0x3c, 0x6a, 0x15, 0x14, 0xdb, 0x2e, 0x50, 0x3b, 0x60, 0x81, 0xb5, - 0x75, 0x98, 0xd7, 0x84, 0x54, 0x9d, 0x8a, 0x45, 0xb7, 0xb2, 0x89, 0x94, 0x67, 0x2b, 0x9e, 0x49, 0xc2, 0xa6, 0xf5, - 0xb7, 0x95, 0x2f, 0x1b, 0x10, 0x65, 0xf9, 0x73, 0xe0, 0x86, 0x6f, 0x7e, 0x3a, 0x4a, 0x1d, 0xd3, 0x3a, 0x03, 0x8b, - 0x00, 0x61, 0xa7, 0x72, 0xbc, 0xc6, 0x10, 0x83, 0x12, 0xd4, 0xf1, 0xb1, 0x9b, 0xa8, 0x20, 0x57, 0xa9, 0x1f, 0x07, - 0x0a, 0x10, 0xc6, 0x4b, 0x27, 0x3c, 0x75, 0x97, 0x17, 0x5b, 0xca, 0xc6, 0x05, 0xc6, 0xde, 0x88, 0x56, 0x40, 0xea, - 0xd3, 0x34, 0x9d, 0xe4, 0x68, 0xba, 0x38, 0xcf, 0xf2, 0x2a, 0xee, 0x99, 0x2e, 0xcb, 0x1c, 0xd3, 0xe0, 0x6b, 0x92, - 0xeb, 0xc4, 0x0a, 0xe1, 0x7f, 0x5b, 0xe4, 0xa0, 0x49, 0x99, 0x16, 0x08, 0xb1, 0x96, 0x68, 0x81, 0xf3, 0xed, 0x10, - 0x45, 0x8b, 0xa2, 0x2a, 0x2b, 0x4b, 0xf5, 0xd7, 0x86, 0x66, 0x4f, 0xb2, 0x07, 0x92, 0x7c, 0x38, 0xf6, 0x5d, 0x12, - 0xcc, 0xfd, 0xfe, 0xac, 0x63, 0x98, 0x28, 0xec, 0x83, 0x8d, 0x3c, 0xae, 0x8a, 0x80, 0x4e, 0xcf, 0xfd, 0xea, 0x8d, - 0xb6, 0xbb, 0xc5, 0xde, 0x23, 0xf8, 0x1c, 0x13, 0x11, 0x7f, 0x31, 0x25, 0xd2, 0xb7, 0x57, 0xcf, 0xa9, 0x5c, 0xac, - 0xd6, 0x5d, 0xc3, 0xcb, 0x53, 0x92, 0x6d, 0xbf, 0x1f, 0x80, 0xe7, 0xdd, 0x9e, 0xd1, 0xe3, 0x74, 0x45, 0x33, 0x13, - 0xe7, 0x48, 0x1a, 0x2a, 0xf1, 0x82, 0x8b, 0xba, 0xaf, 0xde, 0x8e, 0x29, 0x41, 0x31, 0x69, 0x6f, 0x51, 0x21, 0x74, - 0x21, 0xa1, 0x6b, 0x71, 0xca, 0xd7, 0x85, 0xb5, 0x9b, 0x57, 0x89, 0xd6, 0x3e, 0x05, 0x8f, 0xa2, 0xd2, 0xe8, 0x8b, - 0xc5, 0x90, 0x4c, 0xc8, 0x81, 0x7e, 0x63, 0xd6, 0x49, 0x76, 0x0f, 0x9f, 0x6a, 0xa3, 0xc8, 0x0f, 0xe2, 0x1c, 0x30, - 0xfb, 0xb2, 0xec, 0x6d, 0x7d, 0x21, 0x6e, 0x7f, 0x53, 0x41, 0x55, 0x3b, 0xfe, 0x47, 0xe9, 0xcf, 0x19, 0xe1, 0x12, - 0xc9, 0xc0, 0x88, 0x19, 0x7e, 0x21, 0xd2, 0x1a, 0xaf, 0x91, 0x73, 0x8f, 0x0b, 0xdb, 0x21, 0xff, 0xe5, 0x8e, 0xe7, - 0xca, 0xae, 0x10, 0xf2, 0x69, 0xe3, 0x47, 0xdc, 0x31, 0xdb, 0xdc, 0xbb, 0x77, 0x36, 0x8c, 0x9c, 0x03, 0xb3, 0x7a, - 0x9a, 0x32, 0x0b, 0x77, 0xe1, 0xde, 0x62, 0xc7, 0x34, 0x3b, 0x04, 0x5e, 0x86, 0x93, 0x74, 0x5c, 0x7c, 0xea, 0x00, - 0xa1, 0xe8, 0x08, 0x60, 0x4a, 0x16, 0xfa, 0x67, 0x28, 0x5d, 0xbd, 0x98, 0x5d, 0x4b, 0xb9, 0xe6, 0xb2, 0x13, 0xf3, - 0x3c, 0x21, 0xc3, 0xc0, 0xf3, 0xe2, 0xaa, 0x35, 0x9d, 0x1d, 0x92, 0x45, 0xa2, 0xa7, 0xfa, 0x90, 0xee, 0xc7, 0xca, - 0x63, 0xd6, 0x43, 0x45, 0x3a, 0xb8, 0xde, 0xc9, 0xad, 0x63, 0x25, 0x81, 0x13, 0xe9, 0x1e, 0x20, 0xcf, 0x4f, 0x6d, - 0xb7, 0xd2, 0x0a, 0x81, 0x97, 0x48, 0x65, 0x86, 0x44, 0xfb, 0x10, 0x7b, 0x48, 0x4c, 0x80, 0x37, 0x05, 0x3b, 0xd8, - 0x12, 0x68, 0x3b, 0xd7, 0x42, 0x0e, 0x14, 0xb0, 0xda, 0x72, 0xc4, 0x60, 0xe6, 0xa1, 0x15, 0x66, 0xe2, 0x38, 0x3b, - 0x47, 0x1e, 0x1c, 0x48, 0x13, 0xa2, 0x9d, 0x53, 0x4a, 0x83, 0x16, 0x67, 0xce, 0x35, 0x72, 0x81, 0x70, 0x7c, 0x0a, - 0x38, 0x0e, 0x63, 0xc3, 0xf5, 0x31, 0x77, 0xb3, 0xd6, 0x17, 0x8f, 0xc2, 0xe6, 0x7e, 0x38, 0xef, 0xd7, 0xf1, 0xbb, - 0x90, 0x58, 0xc9, 0xb2, 0xf0, 0x4d, 0x52, 0xea, 0x99, 0xf2, 0xb9, 0x6b, 0x55, 0x49, 0xcf, 0xf7, 0x01, 0x8f, 0x78, - 0x0a, 0x2e, 0x37, 0x23, 0x6f, 0x52, 0x32, 0x6a, 0xc0, 0x1f, 0x6d, 0x68, 0x57, 0x06, 0x50, 0x14, 0x03, 0x23, 0x4d, - 0xa7, 0xed, 0xa9, 0x5e, 0x62, 0xd8, 0xc0, 0x32, 0x8f, 0xc9, 0x44, 0xa1, 0x53, 0xdb, 0x6b, 0x9e, 0x6f, 0x46, 0x34, - 0xf2, 0x34, 0x6d, 0x90, 0xe5, 0x77, 0x68, 0xb3, 0x56, 0x39, 0xe3, 0x6f, 0xcb, 0x80, 0xf8, 0x9e, 0x97, 0x05, 0x93, - 0xa1, 0x22, 0x49, 0x31, 0x83, 0xe1, 0xd2, 0xfc, 0x45, 0x55, 0x01, 0x7a, 0x0c, 0xaf, 0xd6, 0x16, 0xd5, 0x79, 0x07, - 0x22, 0xdc, 0x7d, 0x50, 0xaa, 0x70, 0x7d, 0xb9, 0x9b, 0xad, 0x4c, 0x73, 0xf0, 0x7d, 0x55, 0x5d, 0x41, 0xa2, 0x9d, - 0xe1, 0x45, 0xa0, 0x46, 0x67, 0xe6, 0xe2, 0x90, 0x1d, 0x7b, 0x6a, 0xde, 0xa0, 0x08, 0xb9, 0x5f, 0xfd, 0x08, 0xc5, - 0x27, 0xe9, 0x49, 0x23, 0xd0, 0x57, 0x10, 0x5c, 0xf5, 0xb5, 0xb9, 0xa2, 0xcc, 0x56, 0x23, 0xf7, 0x82, 0xb2, 0x0c, - 0x51, 0xb8, 0xa7, 0x48, 0x1c, 0x78, 0x52, 0xf0, 0x88, 0x09, 0x01, 0x4a, 0x78, 0x6b, 0x89, 0x1e, 0xda, 0xdf, 0xcd, - 0xac, 0x7e, 0x61, 0x0d, 0x5b, 0x99, 0x72, 0x00, 0x29, 0x02, 0x4c, 0x2a, 0xe5, 0xea, 0xfe, 0xc1, 0x42, 0x38, 0x1e, - 0x46, 0x0a, 0x26, 0x3f, 0xaf, 0x7c, 0x0b, 0xbc, 0x59, 0xf7, 0xf2, 0x28, 0x3a, 0xd2, 0xc4, 0x94, 0x7a, 0x86, 0xd6, - 0x48, 0xed, 0x76, 0x07, 0xb8, 0x5a, 0xa5, 0x17, 0x54, 0xff, 0xa2, 0x08, 0x46, 0xff, 0x4a, 0x03, 0x61, 0xf1, 0x46, - 0x4c, 0x25, 0x68, 0x8a, 0xde, 0x62, 0x07, 0xa6, 0x7d, 0x2d, 0x55, 0xd7, 0x03, 0xa4, 0xd8, 0x32, 0x83, 0xef, 0x0e, - 0x4e, 0x11, 0x31, 0x4f, 0xc6, 0x62, 0xb5, 0xba, 0x13, 0x63, 0xee, 0xbf, 0x70, 0x1d, 0x41, 0xd8, 0xbf, 0xc6, 0x80, - 0x0e, 0x5a, 0x20, 0x93, 0x3d, 0x70, 0x47, 0xac, 0x84, 0xd9, 0xe7, 0x51, 0x15, 0x58, 0x09, 0x69, 0xf1, 0x3e, 0x2e, - 0x65, 0xcd, 0xe7, 0xd5, 0x71, 0x40, 0x74, 0x0e, 0xe6, 0xb7, 0x8a, 0xbe, 0x85, 0x90, 0x79, 0x5d, 0xe7, 0x04, 0x50, - 0x97, 0xd3, 0x72, 0x5a, 0x4f, 0x48, 0x46, 0x7e, 0x58, 0xaf, 0x1f, 0xa3, 0xa1, 0xca, 0xc7, 0x67, 0x9a, 0xcc, 0xd0, - 0xbd, 0xf9, 0x46, 0x0d, 0x45, 0xdf, 0xae, 0x60, 0x43, 0x21, 0x9b, 0x64, 0xef, 0xc5, 0x37, 0x9b, 0x5c, 0x16, 0xd4, - 0x53, 0xb3, 0x85, 0x53, 0xef, 0xe0, 0x62, 0xcb, 0x34, 0x8e, 0xdc, 0x05, 0xcd, 0x19, 0x9f, 0xed, 0x0d, 0x44, 0x7f, - 0x2f, 0x24, 0x6e, 0x43, 0x47, 0x86, 0xd2, 0x8f, 0x1b, 0x23, 0xa0, 0x46, 0xd1, 0x61, 0x8c, 0x4c, 0x7d, 0xcb, 0x90, - 0x1b, 0x13, 0x74, 0x54, 0x05, 0x55, 0x8b, 0x99, 0x59, 0x92, 0xae, 0x91, 0x0a, 0x0a, 0xa3, 0x34, 0x06, 0x8d, 0x95, - 0x2a, 0x24, 0x7b, 0x11, 0xb1, 0xf4, 0x3c, 0x17, 0xe0, 0xa1, 0x6c, 0x3a, 0x78, 0xca, 0xc2, 0x25, 0xa1, 0xb7, 0x35, - 0x33, 0x4c, 0xcd, 0x56, 0xda, 0x0c, 0x56, 0x54, 0x42, 0x4a, 0xae, 0x2f, 0x4a, 0x49, 0x59, 0x8a, 0x82, 0xe3, 0xa9, - 0x4c, 0x66, 0x28, 0x5f, 0x29, 0x16, 0xab, 0xf7, 0x85, 0x7f, 0x1b, 0x29, 0xb4, 0x5c, 0x01, 0x0b, 0x50, 0x49, 0xb0, - 0x0a, 0xe8, 0xe7, 0xcb, 0xc7, 0x52, 0x85, 0xdf, 0x04, 0xf0, 0x6a, 0xea, 0x79, 0x1d, 0x87, 0x12, 0x5f, 0xbb, 0xf3, - 0xe9, 0xd4, 0xce, 0xff, 0xa4, 0x70, 0xb8, 0x0e, 0xd2, 0x2c, 0xe8, 0xb0, 0xa0, 0x5f, 0xb0, 0x57, 0x5f, 0xac, 0x0d, - 0xa5, 0x98, 0x96, 0x48, 0xdd, 0x2b, 0x63, 0xeb, 0x3d, 0x1b, 0x25, 0xa1, 0x59, 0xfb, 0xf3, 0x7d, 0x27, 0xa9, 0x99, - 0xa9, 0x6a, 0x17, 0xf7, 0xb0, 0x01, 0xd3, 0xd6, 0xa4, 0x8a, 0xb8, 0x77, 0xf3, 0x35, 0xbc, 0xb4, 0x29, 0x01, 0xaa, - 0x4d, 0xa6, 0xf8, 0xae, 0x66, 0x47, 0xee, 0x83, 0xbd, 0xee, 0xbf, 0xdd, 0x7d, 0xd4, 0x9e, 0x0d, 0xec, 0x8a, 0xd0, - 0x0f, 0xa2, 0x37, 0xb0, 0xca, 0xd2, 0x1b, 0x63, 0x81, 0xad, 0x75, 0xa9, 0x83, 0x91, 0x0a, 0xbc, 0x78, 0xe5, 0x0e, - 0x18, 0x8f, 0x47, 0x10, 0x40, 0x7f, 0xe7, 0xf0, 0xc5, 0xb7, 0x44, 0x2a, 0x8c, 0xbb, 0xec, 0x38, 0xa9, 0xca, 0x72, - 0x9b, 0x1d, 0xc7, 0x8c, 0xb1, 0x25, 0x99, 0x99, 0x55, 0x10, 0xb4, 0x1c, 0xa8, 0xbe, 0x4a, 0xde, 0x75, 0x19, 0xc3, - 0x5a, 0x51, 0xc0, 0x3e, 0x28, 0x15, 0xd8, 0x1f, 0x84, 0xa2, 0xba, 0x8c, 0xef, 0xab, 0xe9, 0xcd, 0x3c, 0x70, 0x60, - 0xc4, 0xd0, 0x32, 0x83, 0x23, 0xf6, 0x48, 0x87, 0xad, 0xf4, 0xa6, 0xde, 0x99, 0x6b, 0x15, 0xce, 0x3b, 0x8a, 0xed, - 0x34, 0x48, 0xf5, 0xb7, 0xfd, 0xee, 0x05, 0x4e, 0xf0, 0xcb, 0x2c, 0xaa, 0xc7, 0x3b, 0x73, 0x7a, 0x9d, 0x5c, 0x54, - 0x1d, 0x86, 0xb6, 0xf8, 0xf3, 0x01, 0x69, 0x48, 0x1a, 0xf6, 0x70, 0x7d, 0x25, 0x9d, 0xf9, 0x82, 0x6a, 0x72, 0xc8, - 0xc6, 0x6a, 0x3d, 0x28, 0x80, 0xa7, 0xbc, 0x77, 0x7c, 0xcc, 0x2f, 0x25, 0xa9, 0x1a, 0xd1, 0x42, 0x4d, 0x7c, 0x53, - 0x7e, 0x93, 0x46, 0x0b, 0xe2, 0xd8, 0xda, 0x6b, 0x87, 0xb7, 0x10, 0xbf, 0x7f, 0x8b, 0x89, 0x0a, 0x10, 0xef, 0xcd, - 0xae, 0xcb, 0xe0, 0xb4, 0x7a, 0x96, 0x96, 0x50, 0xb5, 0x81, 0xaa, 0xa6, 0x28, 0x4d, 0xc3, 0xca, 0xe4, 0x73, 0x60, - 0xcf, 0x2b, 0xe9, 0x9c, 0xd2, 0x82, 0xa9, 0x65, 0xdc, 0x7b, 0xc9, 0xc2, 0xe2, 0x63, 0x05, 0xfc, 0xb4, 0x30, 0xa7, - 0xee, 0xa2, 0x12, 0x59, 0x8c, 0x5e, 0xb9, 0x05, 0xd5, 0xe6, 0x4b, 0x95, 0x80, 0x58, 0xbf, 0x6b, 0x35, 0xce, 0x46, - 0xc0, 0x89, 0xa1, 0x77, 0x7f, 0xe2, 0x66, 0xa5, 0x97, 0xa0, 0x98, 0xa6, 0x67, 0x3d, 0x59, 0xca, 0x9c, 0xf1, 0xf2, - 0x87, 0xde, 0x4d, 0x15, 0xdd, 0x3d, 0x57, 0xfc, 0xc1, 0xb3, 0x53, 0x3d, 0x89, 0x5d, 0x56, 0x94, 0xe3, 0x35, 0x96, - 0xd4, 0x3d, 0x72, 0xe4, 0x17, 0xf7, 0x80, 0x40, 0xa1, 0x19, 0x15, 0xc1, 0xa5, 0x91, 0xb4, 0xfc, 0x4c, 0x6d, 0x65, - 0xa4, 0x4f, 0x28, 0x96, 0x08, 0x90, 0xc1, 0xf7, 0x1f, 0x25, 0xba, 0x72, 0x5f, 0x07, 0xf8, 0x27, 0x84, 0x21, 0x44, - 0x31, 0xcb, 0x52, 0x38, 0x16, 0x20, 0xa9, 0xaf, 0xae, 0xa9, 0x66, 0xa7, 0x0d, 0x11, 0x54, 0xea, 0xae, 0x43, 0x80, - 0xb0, 0x5d, 0x23, 0xf0, 0xe5, 0xdf, 0xe0, 0x69, 0xbf, 0xe7, 0x05, 0x75, 0xd8, 0x64, 0x17, 0x3a, 0xf0, 0x36, 0x8b, - 0x7e, 0xe9, 0x19, 0xe9, 0xaf, 0x8d, 0x4f, 0x36, 0x96, 0x0f, 0x3f, 0x2b, 0xdb, 0xa4, 0x7a, 0xb0, 0xb7, 0x00, 0xc4, - 0x6c, 0xa4, 0xd9, 0xb8, 0xd2, 0x55, 0xfb, 0xbe, 0xd5, 0x28, 0x9b, 0x33, 0x6c, 0x97, 0xe0, 0xc5, 0x83, 0x45, 0x8d, - 0x19, 0x22, 0x5b, 0x7b, 0xdc, 0x4b, 0x0f, 0xee, 0xb2, 0xf7, 0x23, 0xe8, 0x3c, 0x21, 0x47, 0x6c, 0x02, 0xce, 0xab, - 0xc2, 0x53, 0x21, 0xb3, 0x02, 0x9d, 0x38, 0x08, 0x20, 0x5d, 0xd6, 0x5d, 0x30, 0xa7, 0x4f, 0x8b, 0x1b, 0x16, 0x3d, - 0xd8, 0x40, 0x59, 0xc8, 0xc0, 0x96, 0x50, 0x43, 0x2e, 0x4c, 0x62, 0xe9, 0x81, 0xfd, 0x82, 0xf0, 0xb5, 0x1e, 0xc7, - 0xba, 0x66, 0x75, 0xd1, 0xa5, 0x02, 0xd2, 0xe2, 0x48, 0xff, 0xa6, 0x8f, 0xe8, 0xbe, 0x69, 0x6d, 0xf8, 0x5e, 0x07, - 0x8d, 0x33, 0x2c, 0x97, 0xc7, 0xd1, 0x5e, 0xd5, 0x6f, 0x0f, 0x0d, 0xaa, 0x99, 0xcf, 0x5c, 0xde, 0x64, 0xf5, 0x6f, - 0xd7, 0x30, 0x90, 0xbf, 0x50, 0xf8, 0xaa, 0x27, 0x90, 0x69, 0x49, 0x8b, 0x82, 0xb7, 0xa7, 0x0f, 0x9b, 0x2c, 0x18, - 0xf7, 0xb7, 0x9f, 0x22, 0xc6, 0xf5, 0xaf, 0xdf, 0xf3, 0xb7, 0xdb, 0x90, 0xf8, 0x8d, 0x80, 0xa4, 0xfb, 0x77, 0x7b, - 0x04, 0x01, 0xe2, 0xde, 0x22, 0x97, 0x0d, 0xee, 0x6f, 0x1e, 0xd7, 0xf5, 0xd5, 0x3d, 0xff, 0xb8, 0x03, 0x51, 0x4b, - 0x72, 0xb2, 0xb5, 0x13, 0xdd, 0x73, 0xce, 0xec, 0xee, 0x65, 0x9a, 0xfe, 0x02, 0x38, 0x85, 0xd5, 0x2d, 0xff, 0xe9, - 0x7d, 0xcb, 0x9e, 0x52, 0x72, 0xbd, 0xb5, 0x5f, 0x4e, 0xbf, 0x7c, 0xdb, 0x5c, 0x65, 0xa7, 0x86, 0xf5, 0x8b, 0xb2, - 0x24, 0xd3, 0x12, 0xcc, 0xfa, 0x20, 0x85, 0xcd, 0x5a, 0x7d, 0x93, 0x71, 0x94, 0xd7, 0x39, 0x61, 0x84, 0x2d, 0x08, - 0xcd, 0xe3, 0x97, 0xc4, 0x52, 0x32, 0xff, 0xb4, 0x5d, 0x19, 0xc3, 0x20, 0xd2, 0xed, 0xaa, 0xb5, 0xe2, 0xea, 0x9c, - 0xb2, 0x3d, 0xe6, 0xd1, 0x04, 0x3f, 0x2f, 0x07, 0x47, 0x2d, 0xf0, 0xaf, 0x70, 0xd8, 0xee, 0xb2, 0x79, 0x0f, 0x34, - 0x2f, 0xfe, 0x03, 0x78, 0x23, 0xba, 0x64, 0x61, 0xc7, 0x87, 0x12, 0x3f, 0xeb, 0x70, 0xb8, 0x32, 0x2c, 0x81, 0x71, - 0x0c, 0x03, 0xc6, 0xa1, 0xab, 0xad, 0x3d, 0x19, 0x0e, 0x83, 0x83, 0x44, 0xf1, 0x1e, 0x4a, 0xb1, 0x8e, 0xe6, 0x85, - 0xe9, 0xd3, 0x3a, 0xb2, 0xcf, 0x30, 0x20, 0x0f, 0xc6, 0x33, 0x1f, 0xb3, 0x6a, 0xaa, 0xa1, 0x4b, 0xd7, 0x71, 0xa5, - 0x35, 0x36, 0xe4, 0x63, 0xc6, 0xee, 0xaf, 0xbd, 0xb3, 0xa0, 0x5d, 0xdd, 0xef, 0xd9, 0x39, 0xc3, 0xea, 0xbb, 0x32, - 0x93, 0xa7, 0x5c, 0x2e, 0xd8, 0x99, 0x2b, 0xfa, 0xf3, 0x7e, 0x93, 0x6a, 0x0a, 0x63, 0x74, 0x04, 0x63, 0xfa, 0xc9, - 0xa9, 0xc4, 0x15, 0x66, 0x64, 0x5d, 0x6f, 0x49, 0x75, 0x26, 0x58, 0x65, 0x5d, 0x21, 0xe7, 0x5d, 0x9c, 0x09, 0x7d, - 0x68, 0x12, 0x5e, 0x24, 0xeb, 0x87, 0xa9, 0xf7, 0xc0, 0x10, 0x59, 0xc8, 0x71, 0xb3, 0xf6, 0xc5, 0x92, 0x71, 0x12, - 0xdb, 0xa9, 0x2e, 0x9c, 0xb6, 0x7b, 0x6d, 0x8f, 0x60, 0x10, 0x78, 0xfe, 0x55, 0x8e, 0x71, 0xdd, 0x86, 0x75, 0x67, - 0xd6, 0x55, 0xf5, 0xf2, 0xc0, 0x12, 0xf6, 0x7a, 0x4c, 0x68, 0x47, 0xe5, 0xa5, 0x6c, 0x2a, 0x99, 0xc8, 0x68, 0x1e, - 0x0b, 0xca, 0xd1, 0x95, 0x39, 0xaf, 0xf2, 0x8e, 0xf6, 0x2c, 0x72, 0x33, 0x00, 0x46, 0x3a, 0x2e, 0xc3, 0xc4, 0xb4, - 0xb0, 0xa1, 0x23, 0xd5, 0xaa, 0xbc, 0x80, 0x8f, 0x1a, 0xbe, 0x68, 0xa0, 0x05, 0x21, 0xaf, 0x9e, 0x38, 0x9c, 0x15, - 0x52, 0xa4, 0xb8, 0x8d, 0xfd, 0x84, 0x22, 0x7f, 0x74, 0x33, 0xb1, 0x55, 0x53, 0xe7, 0x79, 0xf7, 0x7b, 0x08, 0x6a, - 0x0f, 0x42, 0x83, 0x85, 0xb7, 0x3a, 0x14, 0xb0, 0x49, 0x5e, 0x5b, 0xc8, 0x45, 0x86, 0xdf, 0x0c, 0x24, 0x33, 0x10, - 0xa2, 0x33, 0x97, 0x20, 0xac, 0xf6, 0x93, 0x6d, 0x17, 0x74, 0x8d, 0xc2, 0xad, 0x70, 0x7c, 0x60, 0xdc, 0x6b, 0xa2, - 0x16, 0x96, 0xe3, 0xa2, 0x43, 0x9e, 0x2a, 0xb4, 0x62, 0x15, 0x51, 0xeb, 0x12, 0x3f, 0xd9, 0x27, 0x05, 0xf1, 0x62, - 0x4b, 0xd0, 0x4e, 0x4d, 0x8e, 0x1f, 0x1c, 0xba, 0x3d, 0xb1, 0x2c, 0x34, 0x5b, 0x12, 0xbe, 0xf3, 0xca, 0x9e, 0x31, - 0x82, 0x9e, 0xab, 0x94, 0x23, 0x36, 0xd4, 0x65, 0xf6, 0x07, 0xcb, 0x37, 0x13, 0x1a, 0xf7, 0x97, 0x50, 0x66, 0xfb, - 0x2a, 0xb9, 0x4f, 0x91, 0x8f, 0x6b, 0x29, 0x27, 0xa3, 0x0e, 0xdf, 0x98, 0xe0, 0xcf, 0x33, 0xb8, 0x82, 0x55, 0x77, - 0xe5, 0xf0, 0x74, 0x6d, 0x59, 0x9c, 0xef, 0x6d, 0xa1, 0x2c, 0x5e, 0x43, 0xed, 0x61, 0x53, 0xb6, 0xe2, 0x0d, 0x6e, - 0xcf, 0xa6, 0xe9, 0x0b, 0x2f, 0x45, 0x58, 0x77, 0xc5, 0x70, 0xb3, 0x3b, 0x30, 0x73, 0x09, 0xc5, 0xf4, 0xbb, 0xfd, - 0xf1, 0x0c, 0x2c, 0x17, 0xbe, 0xda, 0xfd, 0xe6, 0x98, 0xc4, 0x1f, 0xc8, 0x32, 0x43, 0x5d, 0x6e, 0x6f, 0xde, 0x85, - 0xaf, 0x05, 0xe8, 0xdf, 0x67, 0x30, 0x58, 0x48, 0x7f, 0x9b, 0xa5, 0xb8, 0x49, 0x13, 0xac, 0x1e, 0x24, 0x1f, 0x14, - 0x26, 0x30, 0x95, 0xab, 0xa7, 0x4d, 0x6f, 0x0f, 0xdb, 0x4d, 0xc6, 0x3a, 0x41, 0xad, 0x7c, 0x0b, 0x3d, 0x6d, 0xf4, - 0x58, 0xfc, 0x8d, 0x09, 0x4d, 0x59, 0x50, 0xdb, 0x56, 0xff, 0x81, 0x3b, 0x7a, 0x39, 0x8c, 0xb5, 0xb1, 0xf4, 0x7e, - 0xbb, 0xb7, 0x61, 0x4f, 0xf8, 0x2e, 0xed, 0xa6, 0x41, 0x7f, 0xc9, 0xe9, 0x9e, 0x3a, 0x3f, 0x26, 0x5e, 0x9f, 0xee, - 0x7e, 0xcd, 0xe6, 0x71, 0xc4, 0x0c, 0x95, 0xff, 0xe1, 0x2f, 0x2e, 0xbf, 0xfb, 0xf6, 0x68, 0xcf, 0xc7, 0x5f, 0x66, - 0xbf, 0xa9, 0x4b, 0x77, 0xda, 0x9b, 0xcb, 0x3e, 0x95, 0x4d, 0x18, 0x2f, 0xce, 0x36, 0x60, 0xf6, 0xc6, 0xa5, 0x6a, - 0xf6, 0x9e, 0x51, 0x72, 0x1c, 0xb6, 0x28, 0xb4, 0x9e, 0x14, 0x8c, 0xc8, 0x1b, 0xa6, 0xdd, 0x9b, 0x90, 0x41, 0xec, - 0x00, 0xc8, 0x8f, 0x42, 0x18, 0x3a, 0xb4, 0x14, 0xc1, 0xae, 0xf1, 0x6d, 0x50, 0x1f, 0x61, 0x06, 0x56, 0x13, 0xe9, - 0x8b, 0x05, 0x79, 0x0f, 0x32, 0x96, 0x58, 0x14, 0xd5, 0x54, 0x3a, 0xf0, 0xf4, 0x95, 0x20, 0x4c, 0x0e, 0x6c, 0x49, - 0xef, 0x00, 0xdb, 0x39, 0xdf, 0x9c, 0xfc, 0x35, 0x44, 0x3f, 0x85, 0x5c, 0x75, 0xd5, 0x78, 0xcd, 0x2c, 0xd9, 0xc7, - 0x04, 0x58, 0xfb, 0xca, 0xf8, 0xdb, 0xb6, 0x40, 0xb4, 0x82, 0x9f, 0xb3, 0xad, 0x11, 0xeb, 0x2e, 0xe8, 0xf5, 0x0f, - 0x57, 0xf0, 0x30, 0xc1, 0x7f, 0x49, 0x13, 0xca, 0x12, 0x3d, 0x99, 0x05, 0xa5, 0x93, 0xdf, 0x6f, 0x21, 0xe1, 0xf0, - 0x9a, 0x5e, 0xf2, 0xd2, 0x5b, 0xdd, 0x4a, 0x79, 0x7e, 0x3b, 0xff, 0x33, 0xf5, 0xfa, 0xf8, 0x57, 0x6f, 0xc3, 0x56, - 0x31, 0x9e, 0x39, 0x0c, 0x80, 0x68, 0x88, 0xb8, 0x24, 0xf9, 0x0a, 0xb0, 0x46, 0xee, 0xb5, 0xa8, 0x42, 0x86, 0xd3, - 0xc6, 0xcd, 0xe4, 0x3d, 0xff, 0xdb, 0x10, 0xc3, 0xf9, 0xf8, 0xcb, 0xec, 0x7a, 0x09, 0x1f, 0x18, 0x70, 0x83, 0x8b, - 0xb2, 0x2a, 0x74, 0x07, 0x34, 0xff, 0x6f, 0xa3, 0xd1, 0x22, 0x34, 0x59, 0xa8, 0xa4, 0xfb, 0xf1, 0x1f, 0x73, 0x1d, - 0xc6, 0xba, 0xef, 0x96, 0x98, 0x30, 0x66, 0xc2, 0x0f, 0x8d, 0x62, 0x74, 0x70, 0x7b, 0x9b, 0x7b, 0x42, 0x5d, 0x92, - 0x2d, 0x11, 0x96, 0xa7, 0xf8, 0x2b, 0x8c, 0x65, 0xe4, 0x70, 0x32, 0x65, 0xce, 0x90, 0xc5, 0xc6, 0xce, 0x52, 0x42, - 0xe6, 0x83, 0x7e, 0x2f, 0x0e, 0x23, 0x4d, 0x81, 0x1e, 0xab, 0xaa, 0xf9, 0x1b, 0xbb, 0x53, 0xba, 0x1f, 0x72, 0xe2, - 0x42, 0xbf, 0xb4, 0x25, 0xa2, 0x80, 0xdd, 0x18, 0x3e, 0x8a, 0xff, 0x98, 0x6b, 0xf5, 0x7e, 0xb6, 0x2d, 0x6e, 0x49, - 0x74, 0x12, 0x63, 0x26, 0xe8, 0xd4, 0x1f, 0x6e, 0xf4, 0x63, 0x0f, 0x4d, 0x18, 0x75, 0x3c, 0x0e, 0x53, 0x23, 0x38, - 0x76, 0x24, 0xcb, 0x41, 0xa6, 0x33, 0xd0, 0x90, 0x4e, 0x46, 0xbf, 0x9f, 0xa9, 0xe5, 0x34, 0xe0, 0x57, 0xbd, 0xcc, - 0x15, 0xb7, 0x79, 0xc5, 0x45, 0x7a, 0xf2, 0x0d, 0xae, 0xff, 0xf8, 0x6f, 0xb6, 0xdd, 0xac, 0x76, 0x8c, 0xbf, 0x08, - 0x15, 0x6e, 0xee, 0x2b, 0x37, 0xd0, 0x44, 0x50, 0xce, 0x9a, 0x6a, 0x32, 0xea, 0x9b, 0x67, 0xa5, 0xf3, 0x02, 0xf3, - 0x75, 0xa9, 0xe7, 0xae, 0xeb, 0x5e, 0xcc, 0x1f, 0x2a, 0xd8, 0x0f, 0x4e, 0x05, 0x3f, 0x0e, 0xb5, 0x4a, 0x04, 0xa0, - 0xd5, 0x8a, 0xcd, 0x66, 0x37, 0xea, 0xdf, 0xcb, 0x26, 0x2c, 0x29, 0x82, 0xbf, 0x52, 0x46, 0xf2, 0x2b, 0x0b, 0x7b, - 0x48, 0xff, 0xf2, 0x60, 0x93, 0xf5, 0x80, 0x06, 0x3c, 0x6c, 0x54, 0x78, 0xab, 0x45, 0x2a, 0x71, 0x39, 0x6e, 0x20, - 0x52, 0xa1, 0x96, 0xcc, 0xec, 0xd6, 0xc4, 0x17, 0xcd, 0x53, 0x38, 0xdc, 0x89, 0x47, 0x89, 0x7b, 0x85, 0x71, 0x47, - 0x8b, 0x96, 0xe8, 0x84, 0x3c, 0x8f, 0x10, 0x3a, 0x64, 0x88, 0x2f, 0x27, 0x6a, 0x16, 0x69, 0x62, 0x85, 0x6b, 0xe9, - 0xd9, 0x36, 0xbd, 0x6f, 0xd6, 0x88, 0x09, 0xbf, 0x00, 0x05, 0x97, 0xc9, 0x51, 0xcb, 0xe7, 0x9e, 0xba, 0xdd, 0xa0, - 0x5d, 0x59, 0x66, 0xfc, 0x8b, 0x3a, 0x8b, 0x59, 0x68, 0x32, 0xa8, 0x76, 0xb1, 0xae, 0x40, 0x82, 0x29, 0x4c, 0xa4, - 0xc1, 0xc8, 0x32, 0x3a, 0xa4, 0x39, 0x07, 0xda, 0x17, 0x2d, 0x2a, 0x4c, 0xd6, 0xfe, 0x37, 0x96, 0xfd, 0x11, 0xba, - 0xe8, 0x37, 0x9b, 0x2d, 0xdc, 0xb8, 0x49, 0xab, 0xf5, 0x9d, 0xdb, 0x84, 0xef, 0xbb, 0x49, 0xec, 0x0d, 0x0a, 0xb5, - 0x69, 0xd0, 0x24, 0x21, 0x87, 0x81, 0x81, 0xfe, 0x34, 0xb4, 0x91, 0xac, 0x76, 0x78, 0x14, 0xa7, 0x65, 0x13, 0x79, - 0x9d, 0x9f, 0x62, 0xbd, 0x31, 0x45, 0x08, 0xb3, 0xf4, 0x2b, 0x9b, 0x00, 0xf2, 0xea, 0x90, 0x8e, 0x54, 0x8d, 0x2c, - 0x81, 0x5f, 0x68, 0x0d, 0xe2, 0x8b, 0x13, 0xec, 0x52, 0x93, 0x8b, 0x56, 0xb2, 0x89, 0xa8, 0x7e, 0x6c, 0xd9, 0x1d, - 0x3a, 0x10, 0x54, 0x2d, 0x98, 0xcc, 0x33, 0x83, 0x4d, 0x74, 0x95, 0xab, 0x5a, 0x09, 0x12, 0x64, 0xd3, 0x70, 0x9d, - 0xfe, 0x07, 0xe1, 0x8e, 0xa2, 0x4d, 0xa2, 0x13, 0x20, 0x1b, 0xb7, 0x39, 0xcf, 0xb0, 0x7b, 0x45, 0x2d, 0x44, 0x9f, - 0xf8, 0x29, 0x9f, 0x6b, 0xff, 0x5b, 0xb6, 0x7d, 0x4e, 0x1f, 0x3b, 0x79, 0x70, 0xb8, 0x5d, 0x86, 0x60, 0x76, 0xf8, - 0x54, 0x1e, 0x25, 0xb4, 0xb5, 0x85, 0xa1, 0x1e, 0x6a, 0x53, 0x6f, 0xc5, 0xc8, 0x7a, 0x6c, 0x33, 0x28, 0x38, 0xbd, - 0x90, 0xf0, 0xed, 0xe8, 0x3d, 0x45, 0x22, 0xb9, 0xc4, 0x2f, 0xa0, 0x75, 0xe2, 0x2f, 0x1f, 0xfb, 0x38, 0x6e, 0x77, - 0x4d, 0x0c, 0xbd, 0xa8, 0xb0, 0x0b, 0x5f, 0x76, 0x6c, 0xb3, 0xe9, 0x34, 0x4e, 0x73, 0x1d, 0x53, 0xb5, 0x20, 0x7a, - 0x98, 0x51, 0xe7, 0xa2, 0x29, 0xc1, 0xcb, 0x99, 0x96, 0xf3, 0x53, 0x8b, 0x94, 0xb0, 0x8b, 0xb5, 0x50, 0x1f, 0x79, - 0xa6, 0x12, 0x7f, 0xb9, 0x8f, 0x7e, 0xd2, 0x07, 0x1f, 0xae, 0x17, 0xd6, 0xfa, 0x3b, 0xdd, 0x9f, 0x96, 0x5c, 0xd6, - 0x70, 0xad, 0x92, 0xed, 0x65, 0x19, 0x30, 0xb2, 0xb6, 0xd9, 0xec, 0x43, 0x04, 0x26, 0x88, 0x9d, 0xd2, 0xf7, 0x9a, - 0x86, 0xc4, 0xbf, 0x4c, 0x6f, 0x58, 0x9d, 0xb8, 0xc0, 0xb8, 0x8d, 0x86, 0xfe, 0x61, 0xdb, 0x96, 0xda, 0x9d, 0x4e, - 0x05, 0x03, 0xe1, 0x68, 0xf8, 0x96, 0x4c, 0x55, 0x81, 0xe1, 0xc3, 0x61, 0xad, 0x53, 0x61, 0x0b, 0xb3, 0x46, 0xb6, - 0x7f, 0x0b, 0xc5, 0x4f, 0x0f, 0x4b, 0xd3, 0xc0, 0x86, 0x30, 0xcd, 0x60, 0xde, 0xe6, 0x58, 0xb4, 0x05, 0x96, 0x6d, - 0x89, 0x55, 0x5b, 0xe1, 0xb8, 0x1d, 0xe3, 0xa4, 0x9d, 0xe0, 0xb4, 0x9d, 0xe2, 0x0e, 0xa3, 0xe0, 0xee, 0x84, 0x8a, - 0x7b, 0x13, 0x1a, 0xee, 0x4f, 0x18, 0xf1, 0x80, 0x31, 0xe1, 0xe1, 0x84, 0x0e, 0x8b, 0x31, 0x77, 0x39, 0xd7, 0xcf, - 0xad, 0xe7, 0xa8, 0x36, 0x0c, 0x3a, 0xe3, 0x6d, 0x37, 0xfe, 0x15, 0x19, 0xef, 0xaa, 0xc5, 0xe4, 0xb9, 0xd4, 0xe5, - 0x7d, 0xd7, 0xf3, 0x83, 0xd0, 0x2a, 0xae, 0xac, 0x48, 0xf9, 0xbc, 0x5f, 0xb8, 0x0e, 0x7d, 0xe7, 0x1d, 0xe8, 0x9b, - 0x42, 0xef, 0x4c, 0x12, 0x9a, 0x1f, 0xbe, 0xbb, 0xdb, 0xee, 0x89, 0x2f, 0x44, 0x1c, 0x37, 0x9f, 0x77, 0x10, 0xba, - 0x01, 0xf1, 0x76, 0x25, 0x1a, 0x4f, 0x2e, 0xb8, 0xa1, 0x53, 0x91, 0x25, 0x5e, 0xa2, 0x3c, 0x56, 0xd4, 0xc9, 0x89, - 0xcd, 0x33, 0x65, 0xbc, 0xce, 0x43, 0x97, 0xe8, 0x91, 0xa3, 0x59, 0xb0, 0xbf, 0x75, 0xa7, 0x5c, 0x70, 0xa7, 0x05, - 0x6f, 0x9f, 0x1c, 0xfb, 0x47, 0xfb, 0x6e, 0x23, 0x4d, 0x9e, 0x8c, 0xfb, 0xe3, 0x67, 0x4b, 0x2f, 0xb8, 0xd7, 0x25, - 0x16, 0x6c, 0x80, 0x0b, 0xe6, 0xc4, 0xe5, 0xc2, 0xbc, 0x65, 0x13, 0x05, 0x18, 0xe6, 0x17, 0x80, 0x95, 0xf4, 0x44, - 0x7f, 0xe1, 0x83, 0xff, 0x69, 0x89, 0x32, 0x1c, 0x0d, 0xf9, 0x9d, 0xfb, 0xff, 0xfb, 0xdb, 0x3b, 0xc2, 0x09, 0xa7, - 0x84, 0x65, 0xf3, 0xda, 0x62, 0xfe, 0xdd, 0xb2, 0xa5, 0xb7, 0x32, 0xc5, 0xcd, 0x7f, 0xca, 0x1d, 0x27, 0x7b, 0x27, - 0x58, 0xec, 0x0e, 0x04, 0x4c, 0xa0, 0x71, 0x7b, 0x0e, 0x67, 0x6d, 0x3f, 0x9d, 0xfe, 0x66, 0x65, 0x33, 0x69, 0x04, - 0x3d, 0x2d, 0xbf, 0xf8, 0xff, 0xc7, 0x6f, 0xca, 0x17, 0x36, 0xed, 0x97, 0xcb, 0x55, 0xb9, 0xbc, 0x53, 0xa6, 0xa2, - 0x77, 0x9c, 0x5d, 0x60, 0x8f, 0x9a, 0x7f, 0x16, 0x95, 0x77, 0x28, 0xab, 0x68, 0x99, 0x52, 0x9b, 0x6b, 0x59, 0xcd, - 0xe7, 0x9f, 0xab, 0x76, 0xb6, 0x45, 0x9e, 0xc7, 0xbf, 0xb6, 0xf3, 0x78, 0xde, 0xa8, 0xff, 0xc1, 0xdf, 0x53, 0x0f, - 0xc7, 0x87, 0x75, 0x7b, 0xfc, 0x6f, 0x5d, 0xad, 0x6a, 0x3e, 0x3d, 0xab, 0x6b, 0xad, 0xf2, 0xd7, 0xd4, 0x2c, 0xbf, - 0xb7, 0x61, 0xcc, 0x0d, 0xb4, 0xce, 0x77, 0x8f, 0xbf, 0xa8, 0xf9, 0x17, 0x1a, 0xaa, 0x41, 0x1e, 0xee, 0xbf, 0x55, - 0xd7, 0xd7, 0x9f, 0x39, 0x09, 0xcd, 0x8d, 0xe5, 0x5b, 0x10, 0x35, 0xfa, 0xed, 0xf3, 0x44, 0x0c, 0xf6, 0x5f, 0x9f, - 0x50, 0x30, 0x46, 0x05, 0x33, 0x37, 0xcc, 0x85, 0x3e, 0xd4, 0x48, 0x79, 0x17, 0xb9, 0x77, 0xfc, 0x6f, 0x1c, 0xe3, - 0x1c, 0xa7, 0x21, 0x12, 0x89, 0x0f, 0xf1, 0x99, 0xef, 0x17, 0x5f, 0xa4, 0xa0, 0x89, 0x11, 0x4e, 0x66, 0x66, 0x16, - 0x54, 0x9d, 0x72, 0x6a, 0x2a, 0x1c, 0x7c, 0xab, 0x10, 0x0c, 0x0a, 0x61, 0x6e, 0x58, 0x09, 0x7d, 0xe4, 0xc2, 0xee, - 0x46, 0xbd, 0x84, 0xf3, 0x81, 0x8b, 0x10, 0xb6, 0x8d, 0xa5, 0x7b, 0x92, 0xc3, 0xf2, 0x8c, 0x33, 0x37, 0x2f, 0xe0, - 0x76, 0x65, 0x0f, 0x65, 0xbf, 0x88, 0x68, 0x9d, 0x56, 0xe5, 0xa1, 0xd7, 0xc5, 0xb7, 0x8c, 0xe6, 0x6f, 0x2f, 0xe8, - 0x35, 0xd3, 0x09, 0xf0, 0x2f, 0x0c, 0x98, 0x7d, 0x67, 0xa4, 0xbe, 0x33, 0x30, 0x14, 0xd7, 0x34, 0xcd, 0xd7, 0x64, - 0x75, 0x75, 0x28, 0xa9, 0xf6, 0x5d, 0x0a, 0x12, 0x89, 0xdd, 0x86, 0x75, 0xbe, 0xc0, 0xb3, 0x28, 0x79, 0x2e, 0xe7, - 0xe5, 0x08, 0xad, 0x85, 0xfc, 0xc0, 0x02, 0xb0, 0x0c, 0x19, 0x09, 0x03, 0x1b, 0xe4, 0x44, 0x79, 0xd5, 0x34, 0xa5, - 0x4c, 0x7b, 0x3f, 0xa2, 0xdb, 0x63, 0x1a, 0xf4, 0x28, 0xb1, 0xfc, 0x42, 0x63, 0x1e, 0xf3, 0x58, 0x23, 0xe9, 0x85, - 0x36, 0x18, 0x77, 0xf0, 0x31, 0xcf, 0xb5, 0x34, 0x4f, 0xdd, 0x20, 0x9d, 0x11, 0x07, 0x6d, 0x3a, 0xf4, 0x27, 0x37, - 0xeb, 0x4b, 0xa5, 0xee, 0x46, 0x0c, 0x66, 0xd1, 0x80, 0x0e, 0x47, 0x39, 0xe0, 0xa9, 0x90, 0x40, 0x97, 0x0a, 0xfd, - 0x7e, 0x25, 0x46, 0x7a, 0x95, 0xd9, 0x7d, 0x1b, 0x07, 0x78, 0x12, 0x42, 0x8c, 0x48, 0x6d, 0xc8, 0x7d, 0x91, 0x45, - 0xfb, 0x05, 0xc5, 0x4d, 0x8e, 0x0c, 0xb0, 0xff, 0x52, 0x6a, 0xbf, 0x92, 0xb9, 0x75, 0xe2, 0xb1, 0xdc, 0x1a, 0xfe, - 0xce, 0x1a, 0xb6, 0x2a, 0x62, 0x2a, 0xc5, 0x1e, 0xdc, 0xef, 0xcf, 0xb3, 0x99, 0x5d, 0x90, 0x65, 0x13, 0xce, 0x38, - 0x73, 0x78, 0x8d, 0xd9, 0x11, 0x3d, 0x64, 0x0b, 0xf0, 0x0e, 0x85, 0xb3, 0xc3, 0xa5, 0xb4, 0xbc, 0x40, 0x43, 0x12, - 0x4b, 0xe9, 0x7f, 0xd6, 0xd9, 0x49, 0xa2, 0x7e, 0x98, 0x42, 0x9e, 0xfb, 0x1e, 0x9f, 0x6e, 0x76, 0x9a, 0x17, 0xd5, - 0x3f, 0xfa, 0x6c, 0xe3, 0x0b, 0xdc, 0xc7, 0x3a, 0xcb, 0xfc, 0xf5, 0x29, 0x22, 0x10, 0x2b, 0x8e, 0xd4, 0xd7, 0x36, - 0xe1, 0x98, 0xd7, 0xb7, 0x88, 0xdd, 0x8a, 0xdf, 0x58, 0x79, 0xb4, 0xda, 0x39, 0xaf, 0x63, 0xde, 0x2c, 0xcb, 0xe5, - 0x59, 0x02, 0x6e, 0xf1, 0x5e, 0xec, 0x65, 0xb5, 0xe7, 0x71, 0xc5, 0x3a, 0x65, 0x07, 0xb1, 0x5e, 0xb1, 0x86, 0x5e, - 0xd6, 0x6e, 0xde, 0x1f, 0xe0, 0x39, 0xc0, 0x04, 0x2d, 0x08, 0xcc, 0x7c, 0xbf, 0xcd, 0x53, 0x71, 0x1c, 0x58, 0x44, - 0x4f, 0x2a, 0xc9, 0x95, 0x32, 0xbe, 0x7f, 0xf9, 0xd7, 0x16, 0x92, 0x75, 0xc0, 0x90, 0x18, 0x18, 0x91, 0x12, 0xc7, - 0xce, 0x9b, 0x91, 0x5f, 0xf7, 0x50, 0xfb, 0x76, 0x5f, 0x70, 0xf7, 0xc4, 0x75, 0x62, 0x4f, 0x89, 0x43, 0xf2, 0xce, - 0x05, 0xf3, 0xa4, 0x24, 0x5a, 0x92, 0x7f, 0x2c, 0x10, 0xf9, 0xca, 0xb3, 0x96, 0xa5, 0x76, 0x47, 0x14, 0x22, 0x9f, - 0x38, 0x5f, 0x98, 0x80, 0xa0, 0x5b, 0x25, 0xb0, 0xbb, 0x09, 0x1e, 0x04, 0x7d, 0xdc, 0x8f, 0x7d, 0x74, 0xbb, 0x31, - 0x15, 0x1d, 0xe9, 0x0f, 0x15, 0x34, 0xec, 0xa4, 0x32, 0xb9, 0x80, 0x8c, 0x90, 0x9d, 0xf8, 0x14, 0x9f, 0x08, 0x98, - 0x12, 0x51, 0x30, 0x51, 0x4b, 0x6c, 0x1c, 0x5b, 0x70, 0xf5, 0x4f, 0xd3, 0x7a, 0x34, 0x1e, 0x1d, 0x30, 0xe3, 0x06, - 0xff, 0x78, 0xd6, 0x8e, 0x9b, 0x7e, 0xd0, 0x1b, 0xd7, 0x6e, 0x01, 0x9d, 0x35, 0x5e, 0xa2, 0x5e, 0xab, 0x5b, 0xa0, - 0x71, 0x95, 0xc0, 0x4a, 0x95, 0xb8, 0x99, 0xf0, 0x29, 0x48, 0xe6, 0x1e, 0x0b, 0x9f, 0xdc, 0xe3, 0x0f, 0x78, 0x28, - 0xd4, 0x02, 0xee, 0x0b, 0xf7, 0x69, 0x0f, 0xee, 0x0a, 0x55, 0x01, 0xb7, 0x85, 0xdf, 0x8a, 0xdf, 0x63, 0x37, 0x05, - 0x9f, 0x8a, 0x70, 0x83, 0x93, 0x28, 0x17, 0x2a, 0xcf, 0xa5, 0xbe, 0x35, 0x14, 0x70, 0xbd, 0x9a, 0xc1, 0xc3, 0x4b, - 0x5c, 0x0b, 0xf8, 0x48, 0x3d, 0xf6, 0x02, 0x2b, 0x4f, 0x67, 0x28, 0x8f, 0x0d, 0xdd, 0xfd, 0x7f, 0xdf, 0x35, 0x38, - 0x04, 0xde, 0x2c, 0x26, 0x45, 0x25, 0x28, 0xe4, 0xff, 0x53, 0x24, 0x30, 0x2b, 0x18, 0x01, 0xd3, 0x42, 0x29, 0x60, - 0x52, 0xd8, 0x4a, 0xdb, 0x76, 0x60, 0x58, 0x50, 0x19, 0x8c, 0x0b, 0x72, 0x03, 0xe7, 0x05, 0x51, 0xae, 0x3c, 0xb8, - 0x28, 0x28, 0x06, 0xa3, 0xc2, 0xa0, 0x86, 0xe5, 0xdf, 0x58, 0x6f, 0xd0, 0xa8, 0x2a, 0xf1, 0x01, 0x66, 0x91, 0xa2, - 0x5f, 0xaa, 0x96, 0x6d, 0xb1, 0x7a, 0x05, 0x2e, 0x9a, 0xbf, 0x23, 0xcd, 0x07, 0x48, 0x98, 0x05, 0x92, 0x98, 0xef, - 0x1a, 0x09, 0x20, 0xc1, 0x0f, 0x5f, 0x37, 0x2d, 0x0c, 0x35, 0x25, 0x79, 0x60, 0x17, 0xd3, 0x36, 0xf1, 0x7f, 0x6c, - 0x1a, 0x2c, 0x38, 0x49, 0xa6, 0xcd, 0xef, 0x8b, 0x15, 0xad, 0x96, 0xa4, 0x09, 0xd6, 0x4f, 0xcb, 0x94, 0x56, 0x01, - 0x7d, 0xa7, 0x94, 0x0c, 0x62, 0xe7, 0xba, 0x67, 0xc2, 0x77, 0xef, 0x1d, 0xe2, 0x8c, 0x4b, 0x85, 0xc4, 0x90, 0xd2, - 0xf3, 0xff, 0x64, 0x32, 0x27, 0x8a, 0x95, 0x7f, 0x9e, 0xc4, 0x8f, 0xfc, 0x98, 0x5d, 0xf5, 0x05, 0x7d, 0xfe, 0x57, - 0x72, 0x1c, 0xba, 0x65, 0xf6, 0x1e, 0xab, 0x26, 0x59, 0xf8, 0x3b, 0x0a, 0x5e, 0x23, 0x85, 0xaf, 0xe9, 0x96, 0x03, - 0xec, 0x3c, 0xc3, 0x10, 0x9b, 0x31, 0x30, 0xab, 0x18, 0xd4, 0x79, 0x75, 0x02, 0xe1, 0x84, 0xe6, 0x16, 0x77, 0xac, - 0x3a, 0xbe, 0x77, 0x2e, 0x5f, 0x01, 0x40, 0xd3, 0x7d, 0xd2, 0xf0, 0x48, 0xa8, 0x66, 0x12, 0x3a, 0x98, 0x90, 0x07, - 0xd3, 0x5d, 0x35, 0xa0, 0x0a, 0x99, 0xe8, 0x53, 0x69, 0x79, 0x45, 0xf0, 0xae, 0x6a, 0x95, 0x08, 0x03, 0xd7, 0x16, - 0x70, 0x0a, 0x52, 0xff, 0xb2, 0x77, 0x3d, 0x03, 0x4c, 0xc1, 0x81, 0xc2, 0x69, 0xed, 0xe9, 0x15, 0x3f, 0xb0, 0x12, - 0xeb, 0x86, 0x53, 0xf5, 0x07, 0x96, 0xea, 0x97, 0x53, 0x44, 0xe9, 0x35, 0x77, 0x85, 0x1a, 0x20, 0x7e, 0x45, 0xea, - 0x81, 0xeb, 0x05, 0xae, 0xa6, 0x76, 0x07, 0xca, 0xdc, 0x2a, 0x16, 0xda, 0xbb, 0x08, 0xb4, 0x0d, 0x43, 0xc8, 0x4f, - 0x66, 0x22, 0x12, 0x85, 0xaa, 0x25, 0xe7, 0x22, 0x3f, 0x82, 0x6b, 0xd5, 0x68, 0x8a, 0x22, 0xba, 0x71, 0x54, 0x07, - 0x29, 0x73, 0x22, 0x98, 0x4a, 0xa5, 0x0d, 0x52, 0xa0, 0x74, 0x15, 0xf4, 0xbf, 0x54, 0xcd, 0x63, 0xed, 0x7d, 0x98, - 0x7e, 0xa0, 0xb7, 0xd3, 0x57, 0xaa, 0x42, 0x7d, 0x89, 0x94, 0x8b, 0x73, 0x97, 0xa7, 0xbf, 0x38, 0x2f, 0x69, 0xd3, - 0x4d, 0x11, 0x88, 0xdd, 0x08, 0x94, 0x7c, 0xd2, 0x37, 0x8b, 0x30, 0x51, 0x59, 0x79, 0x42, 0x08, 0xd0, 0xeb, 0x12, - 0x37, 0xa9, 0xaf, 0xb5, 0xb8, 0x92, 0x48, 0xc0, 0x6c, 0xb8, 0x2e, 0xe4, 0x75, 0x2a, 0x2e, 0x43, 0x63, 0xcf, 0x3d, - 0x8b, 0x29, 0xc1, 0x88, 0x7c, 0xb4, 0x5d, 0xf1, 0xd8, 0x56, 0x8c, 0xbb, 0x53, 0x22, 0x57, 0x45, 0x9b, 0x46, 0x0e, - 0xc6, 0x94, 0x7a, 0xc9, 0x27, 0x01, 0xba, 0xda, 0x1d, 0xdf, 0xed, 0xd6, 0xd7, 0x1a, 0x34, 0xfb, 0x8c, 0xf6, 0x4d, - 0x88, 0x3f, 0x1b, 0x56, 0x44, 0x9e, 0x78, 0xc5, 0xf8, 0x1c, 0x0c, 0x1c, 0x34, 0xa3, 0x54, 0x6d, 0xa1, 0x0e, 0xf2, - 0xe8, 0x6b, 0x13, 0xa7, 0x01, 0xb8, 0xe7, 0xe2, 0x43, 0xdc, 0x37, 0x0a, 0x97, 0x30, 0xed, 0xc9, 0x3c, 0x7b, 0x98, - 0xeb, 0x2c, 0xac, 0x4a, 0xa1, 0x01, 0x04, 0x81, 0xba, 0x9e, 0x63, 0x9a, 0x1e, 0xed, 0xa5, 0x40, 0xb4, 0x9b, 0xdc, - 0xce, 0x02, 0xb5, 0xe6, 0x0b, 0xba, 0x1c, 0xf5, 0xc4, 0x8b, 0x77, 0xb4, 0xbc, 0xce, 0x2e, 0x43, 0xc0, 0x66, 0xd4, - 0xd0, 0xb6, 0x2c, 0x32, 0x2d, 0x6a, 0x34, 0xe0, 0x6a, 0xaa, 0x56, 0x28, 0x4a, 0xd4, 0xae, 0x68, 0x7d, 0x25, 0xd5, - 0x0e, 0xe4, 0xcc, 0x74, 0x5c, 0x72, 0x30, 0x05, 0x69, 0x24, 0xc2, 0xb2, 0xc9, 0xbc, 0xbe, 0xd1, 0xc1, 0x74, 0xf7, - 0xaa, 0xab, 0xc9, 0x26, 0x5b, 0x80, 0x65, 0xbf, 0xe1, 0x92, 0xcb, 0xb2, 0x15, 0xa3, 0x99, 0x1d, 0xbf, 0xd9, 0x2b, - 0x6d, 0x25, 0x1b, 0x6f, 0xd6, 0x3b, 0xdb, 0xad, 0xb5, 0x77, 0x0a, 0x44, 0x47, 0x54, 0xe7, 0xfe, 0x98, 0x8f, 0x58, - 0x4c, 0x06, 0xb0, 0xa7, 0x48, 0x21, 0x1a, 0x67, 0xeb, 0x6e, 0x8e, 0xc7, 0x37, 0xce, 0x03, 0xca, 0x2c, 0x2c, 0x68, - 0x40, 0xae, 0xcf, 0x43, 0xaf, 0xd7, 0x53, 0x44, 0xc2, 0x5d, 0x2d, 0x30, 0x54, 0x02, 0x72, 0x45, 0xba, 0x94, 0x7e, - 0x53, 0x66, 0x95, 0x34, 0x69, 0x92, 0x3b, 0x56, 0x03, 0x1b, 0x3a, 0x97, 0x84, 0xe4, 0x1f, 0xc6, 0x96, 0x53, 0xf8, - 0x2b, 0xd2, 0x5b, 0x36, 0x4a, 0xe1, 0x3d, 0xf7, 0x88, 0xc1, 0x73, 0x74, 0x76, 0x21, 0x6e, 0x5c, 0x96, 0x39, 0xc9, - 0x2a, 0x6d, 0x42, 0x3e, 0x91, 0xf1, 0x73, 0x88, 0x9d, 0xce, 0x58, 0xb2, 0x06, 0x19, 0xa7, 0xc2, 0x04, 0xa6, 0xc2, - 0x35, 0x75, 0xbb, 0x7a, 0xa1, 0x25, 0xa1, 0x06, 0xa4, 0xdb, 0x45, 0x96, 0x53, 0x5a, 0xf8, 0xf0, 0xae, 0xb6, 0x29, - 0xdc, 0xfe, 0xdd, 0x26, 0x3a, 0xb3, 0x42, 0x66, 0xd5, 0xf7, 0x11, 0x55, 0xd9, 0xf8, 0x76, 0x40, 0x97, 0x20, 0x54, - 0xe4, 0xaf, 0x7f, 0xf7, 0xe3, 0xd0, 0xbf, 0x55, 0xc1, 0x0f, 0x2d, 0x57, 0xdf, 0x42, 0x2e, 0x71, 0x49, 0x34, 0xb9, - 0x4a, 0x3e, 0x57, 0x79, 0x99, 0xf9, 0x10, 0x46, 0xde, 0x0f, 0x75, 0x7b, 0xb2, 0x0b, 0x25, 0x69, 0xfd, 0xe9, 0x91, - 0x9b, 0x9d, 0x94, 0x3a, 0xc9, 0xd1, 0xc8, 0x56, 0xfc, 0xfc, 0xaa, 0x6b, 0x66, 0x0d, 0xbe, 0x3d, 0x3d, 0x39, 0x8b, - 0x8a, 0x4f, 0xf3, 0xf6, 0x1c, 0x5b, 0x47, 0xd5, 0x80, 0x6d, 0x91, 0x95, 0xd6, 0xdb, 0x89, 0xd6, 0x84, 0xb8, 0x7c, - 0x84, 0xa1, 0x3b, 0x09, 0x7a, 0xe5, 0x97, 0x36, 0xd5, 0xa8, 0x3b, 0x2f, 0xc5, 0x49, 0x0e, 0x26, 0xf8, 0xe3, 0x1d, - 0x0a, 0xdf, 0xc2, 0x9f, 0x46, 0xb2, 0xe3, 0xea, 0x39, 0x61, 0x07, 0x2a, 0xd5, 0xa2, 0x16, 0x2a, 0xc2, 0x46, 0x88, - 0x2d, 0x1c, 0x40, 0x90, 0xf7, 0xe3, 0x56, 0x56, 0x96, 0xc5, 0x70, 0x3e, 0x2d, 0x92, 0x07, 0x42, 0x5e, 0x74, 0xe3, - 0x56, 0x3a, 0x1d, 0x58, 0x49, 0x42, 0x43, 0x8e, 0xce, 0xd6, 0xfa, 0x77, 0xe5, 0x67, 0xb5, 0x21, 0x2a, 0x3e, 0x80, - 0xd9, 0x88, 0x96, 0x7c, 0xe5, 0x97, 0x60, 0xa8, 0x8a, 0xee, 0xd7, 0x24, 0x4d, 0x07, 0x56, 0x06, 0x52, 0x02, 0x89, - 0x6d, 0xcc, 0xb9, 0x3d, 0xf4, 0xb0, 0xc0, 0x7c, 0x48, 0x72, 0x8d, 0x6a, 0xac, 0xf7, 0x0f, 0xcf, 0xc3, 0xa8, 0xf5, - 0x71, 0x1c, 0x64, 0xe9, 0x7a, 0x1a, 0xc6, 0x7a, 0x3a, 0xa1, 0x50, 0xde, 0x95, 0x29, 0x6e, 0x53, 0xac, 0xe4, 0x46, - 0xdf, 0x8d, 0xb6, 0x8d, 0x37, 0x02, 0xe0, 0xc1, 0xde, 0xcf, 0xaf, 0x83, 0x29, 0xe9, 0xb1, 0x09, 0x59, 0x8f, 0x28, - 0x33, 0xea, 0xe4, 0x84, 0x46, 0x92, 0x52, 0x90, 0xe0, 0xcc, 0x98, 0xed, 0x8f, 0xa5, 0x64, 0x23, 0xc9, 0x3e, 0xc2, - 0xf2, 0xed, 0xd1, 0x52, 0x0d, 0x2b, 0x86, 0xec, 0x63, 0x79, 0xef, 0xed, 0xb5, 0xa8, 0x84, 0x83, 0x01, 0x10, 0xdf, - 0x6e, 0xe0, 0x04, 0xcf, 0x54, 0x2f, 0x87, 0xce, 0xe0, 0x41, 0xa1, 0x08, 0x6b, 0xda, 0xe1, 0x22, 0x6c, 0xfa, 0x53, - 0x43, 0xe8, 0x1e, 0xc5, 0x14, 0x29, 0x1e, 0x48, 0x85, 0x8f, 0x15, 0x41, 0x36, 0x3e, 0x2e, 0x86, 0xbe, 0x14, 0xcc, - 0x9d, 0x83, 0xea, 0x33, 0x25, 0xea, 0xd5, 0xcf, 0x59, 0xde, 0x16, 0x9b, 0xde, 0x79, 0xbc, 0xc9, 0x23, 0x49, 0xb6, - 0x97, 0xd9, 0x17, 0xfe, 0x2f, 0x3d, 0xcb, 0xc2, 0xe1, 0xb4, 0x74, 0x8e, 0x20, 0xf8, 0x81, 0x36, 0x64, 0x33, 0x0b, - 0x10, 0x19, 0x29, 0xdd, 0x8c, 0x2e, 0xac, 0xbc, 0xce, 0x89, 0x39, 0x35, 0x67, 0xbd, 0x08, 0x37, 0x95, 0x41, 0x88, - 0xcd, 0xd3, 0x4a, 0xa4, 0x77, 0x5b, 0x09, 0x8e, 0xcd, 0x43, 0x89, 0x6f, 0xd9, 0xd9, 0x22, 0x35, 0x16, 0xa5, 0xb7, - 0x10, 0x7d, 0x2b, 0x38, 0xce, 0xf2, 0xc8, 0xd4, 0x7d, 0x0c, 0x6b, 0x26, 0x6f, 0x4e, 0xdc, 0x50, 0x41, 0xa2, 0x2d, - 0x3f, 0x3d, 0xd0, 0xbb, 0x5d, 0x34, 0xc9, 0xa8, 0xcd, 0xc7, 0x2b, 0x41, 0xf6, 0x04, 0xbb, 0xc1, 0xed, 0xae, 0xee, - 0x7e, 0x60, 0x73, 0xe7, 0xcd, 0x05, 0x00, 0xd6, 0xe9, 0xbd, 0xbb, 0xf5, 0x98, 0x4c, 0x29, 0xb8, 0x76, 0x73, 0xf9, - 0xef, 0x45, 0x8b, 0xb4, 0xe7, 0x5b, 0xd0, 0xfd, 0xb2, 0xd0, 0x74, 0x0f, 0xa1, 0x57, 0xd8, 0x61, 0xef, 0x47, 0xc3, - 0xa9, 0x08, 0x51, 0x2f, 0x99, 0xa1, 0x0d, 0x66, 0xf4, 0x2a, 0x56, 0x26, 0x6f, 0x66, 0xc5, 0x95, 0x27, 0xe1, 0x45, - 0xea, 0x3c, 0x5b, 0x5d, 0x55, 0xb9, 0x4f, 0x8a, 0x2a, 0xf2, 0xc2, 0xb5, 0x42, 0x19, 0x93, 0xa2, 0x5a, 0x0a, 0x8f, - 0x43, 0x17, 0x36, 0x44, 0x65, 0x3a, 0x8d, 0x5e, 0x60, 0xa2, 0x20, 0x75, 0x0e, 0x69, 0x9a, 0xcd, 0xe2, 0xfb, 0x0c, - 0xe7, 0x45, 0xac, 0x3c, 0x64, 0x62, 0x2f, 0xb6, 0xaa, 0xb3, 0x79, 0xbe, 0xcb, 0x8f, 0x2b, 0x7e, 0x67, 0xa2, 0xf0, - 0x87, 0xaf, 0xf0, 0x91, 0xdb, 0x69, 0x77, 0x83, 0x1d, 0x2b, 0x5b, 0xb8, 0x33, 0xa8, 0x60, 0xec, 0x17, 0xfd, 0x2a, - 0x39, 0xc3, 0xaf, 0xd2, 0xb9, 0x7a, 0x96, 0x5f, 0x65, 0xbd, 0x8a, 0x5b, 0xd2, 0x2d, 0xf8, 0xdf, 0xdc, 0x4e, 0xb5, - 0xf9, 0x01, 0x67, 0xf2, 0xd5, 0x8d, 0x30, 0x17, 0x64, 0x9c, 0xaf, 0xf9, 0xa0, 0x0e, 0x9e, 0xa4, 0xaa, 0xb0, 0x20, - 0x0b, 0x62, 0xbd, 0x01, 0xd0, 0x45, 0xfe, 0x56, 0x53, 0x41, 0x84, 0x8b, 0x81, 0xab, 0xfd, 0x04, 0xf5, 0x01, 0x18, - 0xca, 0x5c, 0x8e, 0xf0, 0x60, 0x7c, 0x85, 0x46, 0x62, 0x64, 0x97, 0x30, 0x18, 0x8f, 0xdb, 0xbe, 0xfe, 0x56, 0x5c, - 0x55, 0xcd, 0x4e, 0xbb, 0x83, 0xa1, 0x89, 0xd5, 0xb3, 0xb0, 0xa0, 0x49, 0x72, 0xe6, 0x9e, 0x3f, 0x16, 0x84, 0xf2, - 0xfc, 0x67, 0xc2, 0xfe, 0x58, 0x13, 0x09, 0x4e, 0x6a, 0x6a, 0x7b, 0x23, 0x52, 0xbd, 0x30, 0x62, 0x29, 0xed, 0x2b, - 0xd3, 0x73, 0x0d, 0x9e, 0x79, 0x4a, 0x18, 0xf5, 0x34, 0xaa, 0xaf, 0x6d, 0x2e, 0x77, 0xf2, 0x72, 0xfe, 0xe3, 0x5a, - 0x0b, 0x1a, 0x32, 0xcf, 0x11, 0x1b, 0xb0, 0x0e, 0x42, 0xc9, 0xfc, 0x62, 0x3e, 0x9d, 0x48, 0x4b, 0x36, 0xbf, 0x9a, - 0x0f, 0x8b, 0x81, 0xea, 0x6d, 0xf5, 0xb1, 0x9a, 0x46, 0x18, 0x3e, 0xc4, 0x9b, 0x17, 0x4a, 0x8c, 0xee, 0x46, 0xa7, - 0xa0, 0xae, 0xf4, 0xfe, 0xf8, 0xdb, 0xf6, 0x6c, 0x77, 0x33, 0xb8, 0xbf, 0xc8, 0x35, 0xd2, 0xdf, 0xa0, 0x3c, 0xcb, - 0x6b, 0x07, 0x23, 0x22, 0x35, 0xd9, 0x76, 0x4a, 0x40, 0xdf, 0xcf, 0xd4, 0xbd, 0x14, 0x89, 0x1a, 0xa5, 0x6e, 0xae, - 0x47, 0xe3, 0xb0, 0x86, 0x8c, 0xf8, 0x4b, 0xd9, 0x8f, 0x03, 0x3a, 0xe2, 0xc9, 0xb0, 0x50, 0x8f, 0x0c, 0xf7, 0x70, - 0x67, 0x03, 0x77, 0x9b, 0xd6, 0x9f, 0x4f, 0x92, 0x5c, 0x57, 0x1a, 0x7a, 0xd0, 0x4d, 0x71, 0x42, 0xc3, 0xcd, 0x87, - 0x19, 0x22, 0x88, 0xcb, 0x33, 0x5c, 0x4f, 0x7f, 0xa9, 0xa1, 0xed, 0x7d, 0xf3, 0x59, 0x16, 0xa9, 0xf1, 0x09, 0xf3, - 0xc8, 0xf6, 0x00, 0xf3, 0x63, 0x75, 0xfb, 0x65, 0x1f, 0x22, 0xb0, 0x51, 0x0f, 0x6a, 0x7c, 0xd1, 0x7f, 0x7d, 0xc7, - 0x80, 0x38, 0xfd, 0x3d, 0x25, 0xd5, 0x78, 0x2e, 0x2d, 0xbe, 0x3b, 0x25, 0xd4, 0x68, 0x2e, 0x9c, 0x97, 0xe4, 0x1c, - 0x65, 0xb7, 0xd2, 0x31, 0xfa, 0xa6, 0x08, 0x98, 0xce, 0x02, 0x56, 0x6f, 0xf6, 0xef, 0x41, 0x84, 0x99, 0x8a, 0xa9, - 0x4c, 0x3f, 0xc9, 0x22, 0x8c, 0xd1, 0xe9, 0x6a, 0xa0, 0x72, 0x40, 0xd2, 0xb7, 0x3b, 0xdf, 0xba, 0x27, 0x8a, 0x00, - 0xe2, 0x36, 0xcf, 0xd2, 0x90, 0x40, 0x1d, 0x3e, 0xe4, 0xfa, 0xf6, 0x12, 0x2f, 0xf1, 0x1c, 0x8b, 0xb7, 0xc9, 0xbd, - 0x75, 0xc1, 0x89, 0x45, 0x7f, 0x1e, 0xd3, 0x61, 0xa3, 0x8d, 0xb2, 0xe5, 0x46, 0x33, 0x74, 0xe8, 0xaa, 0xe8, 0x8a, - 0x02, 0x7d, 0xc1, 0xe4, 0x49, 0x63, 0xf3, 0xad, 0x5d, 0x06, 0x36, 0x81, 0xdb, 0x9c, 0xc1, 0x81, 0xdd, 0xa9, 0x39, - 0x3b, 0x8e, 0xe7, 0x82, 0xde, 0x3c, 0x56, 0xa0, 0x3f, 0x74, 0xf9, 0xc6, 0x82, 0xab, 0x39, 0x63, 0x50, 0x83, 0x1a, - 0xf0, 0x75, 0x8f, 0xa3, 0x66, 0x17, 0x22, 0x7b, 0xaf, 0x86, 0x14, 0x53, 0xca, 0xe6, 0x2e, 0x0b, 0x6c, 0x63, 0x07, - 0xaa, 0x41, 0xd3, 0x31, 0x80, 0xb4, 0x77, 0xf1, 0x19, 0xf5, 0xbf, 0xb5, 0xb7, 0xaf, 0xc2, 0x3d, 0x0c, 0xd4, 0x24, - 0x80, 0xd6, 0xbd, 0x67, 0xd6, 0x10, 0x24, 0xbc, 0x8d, 0xe9, 0x96, 0xfe, 0xec, 0x8b, 0x98, 0xdc, 0x40, 0xcd, 0x25, - 0x31, 0xbc, 0x88, 0x32, 0x93, 0xa9, 0xe1, 0x32, 0xf9, 0x76, 0x2a, 0x16, 0xce, 0x9d, 0x49, 0x40, 0xf7, 0xea, 0xdd, - 0x24, 0x4b, 0x4f, 0x14, 0x24, 0x88, 0x72, 0x33, 0x0c, 0x64, 0xee, 0xeb, 0x61, 0x19, 0xd6, 0x13, 0xbe, 0xbb, 0x5b, - 0xfb, 0xcb, 0xe3, 0x1e, 0x2f, 0xc5, 0xdf, 0xb6, 0xc2, 0xe7, 0x48, 0xdf, 0x68, 0x20, 0x4d, 0xd1, 0xab, 0x1d, 0x45, - 0xd4, 0x17, 0x2b, 0x43, 0x25, 0x90, 0x4a, 0x29, 0x9c, 0xd0, 0xbf, 0xd8, 0x44, 0x41, 0x5b, 0xd1, 0x78, 0x6d, 0x4e, - 0x3c, 0x2c, 0x3c, 0xf5, 0x82, 0x7b, 0x59, 0x0f, 0xd9, 0x7b, 0xb5, 0x45, 0x34, 0x7c, 0x2a, 0xfd, 0xaa, 0x33, 0xf9, - 0x43, 0xbe, 0x0a, 0xa3, 0xb7, 0xef, 0xf9, 0x6b, 0x1d, 0xf4, 0x9d, 0xfe, 0xdf, 0x8f, 0xf8, 0x6c, 0x4f, 0xfb, 0x64, - 0xf7, 0xf7, 0x6d, 0xc0, 0xf4, 0xe3, 0x89, 0xa6, 0xa7, 0x58, 0xe7, 0x6e, 0x52, 0x92, 0xdf, 0x27, 0xaa, 0x36, 0xf1, - 0x98, 0x8d, 0x7f, 0x4b, 0x14, 0x80, 0xe4, 0xd6, 0x1b, 0xd1, 0xea, 0xf5, 0x14, 0xbf, 0xff, 0x4d, 0x61, 0xc7, 0x98, - 0x1c, 0xe9, 0x15, 0x26, 0xe9, 0x7b, 0x01, 0xbc, 0xc0, 0xcd, 0x26, 0x10, 0xeb, 0x31, 0xc0, 0x61, 0xb6, 0x7d, 0x0f, - 0xb4, 0x48, 0x83, 0x59, 0x83, 0x52, 0xf0, 0x64, 0xb7, 0xec, 0x78, 0xcd, 0xf7, 0xd1, 0x1f, 0x6d, 0xa1, 0x4f, 0x6e, - 0xd6, 0x7a, 0xea, 0x04, 0xcf, 0xf3, 0x02, 0x9f, 0xa0, 0x79, 0x5a, 0xa0, 0xb3, 0x28, 0x85, 0x5f, 0x88, 0x06, 0x87, - 0x10, 0xd1, 0x3a, 0x48, 0x17, 0xcc, 0x0a, 0x37, 0xbf, 0x28, 0x8b, 0xfc, 0xaa, 0x5e, 0xec, 0xda, 0x22, 0x18, 0x77, - 0xab, 0x10, 0xe5, 0x70, 0xcb, 0xef, 0x79, 0x55, 0x42, 0x72, 0x97, 0xc9, 0xf2, 0x5d, 0x15, 0x3f, 0x9f, 0x9d, 0x35, - 0x5e, 0xcc, 0x33, 0xc5, 0xac, 0x5f, 0x04, 0xaf, 0x99, 0xa8, 0xb6, 0xd1, 0x9f, 0x22, 0x53, 0x60, 0xd3, 0x4c, 0xea, - 0xe2, 0x9f, 0x47, 0x4c, 0xe1, 0x8c, 0xeb, 0x72, 0xce, 0xaa, 0x79, 0x7c, 0x69, 0xe2, 0x88, 0x28, 0x27, 0x5d, 0x30, - 0x5b, 0x19, 0xee, 0xf2, 0xa7, 0x7d, 0x5b, 0x46, 0xe7, 0x89, 0xb4, 0x22, 0xd9, 0xed, 0x97, 0xeb, 0xdb, 0x38, 0x8b, - 0x73, 0xdf, 0xfa, 0xe2, 0x7b, 0x54, 0x51, 0x8d, 0xb7, 0x4f, 0x7a, 0xd3, 0x1a, 0x2b, 0x67, 0x86, 0x7a, 0x78, 0x11, - 0xb9, 0xe9, 0x1b, 0xd9, 0x2a, 0x8b, 0xb3, 0x5d, 0xea, 0x47, 0xfa, 0x07, 0x5f, 0x8a, 0x02, 0x76, 0x35, 0xf8, 0x3e, - 0x2f, 0x49, 0xe7, 0x35, 0x5e, 0xa4, 0x90, 0x8c, 0x33, 0x8b, 0x36, 0xca, 0x5b, 0x0f, 0xab, 0x2e, 0xe0, 0xfb, 0x1d, - 0x83, 0x1b, 0x60, 0x0e, 0x33, 0xab, 0x8d, 0x9b, 0x37, 0xbb, 0x8c, 0x93, 0x7b, 0x2a, 0x82, 0x79, 0xcf, 0xa1, 0xb1, - 0xb7, 0xb9, 0x7e, 0xb1, 0xd1, 0x47, 0xbc, 0x8e, 0x70, 0xfc, 0x8c, 0x40, 0xf8, 0xc5, 0x14, 0xde, 0xd7, 0x9d, 0x59, - 0xc2, 0x34, 0xcf, 0x8c, 0xd3, 0x11, 0xc2, 0x25, 0x83, 0x70, 0x7f, 0x6f, 0xf5, 0xb4, 0x78, 0x02, 0xfb, 0xab, 0x72, - 0x56, 0x37, 0xd1, 0x3f, 0x4f, 0x62, 0x5a, 0xbb, 0x5c, 0xc3, 0x61, 0xf0, 0xea, 0x24, 0xcd, 0x3f, 0x75, 0xa1, 0xca, - 0x0c, 0x93, 0xc3, 0xa6, 0x4c, 0xb9, 0x10, 0xef, 0x1f, 0x76, 0x4d, 0xbd, 0xd4, 0xdb, 0x38, 0xe7, 0x22, 0x0b, 0x93, - 0xdf, 0x0a, 0x8e, 0x73, 0xf9, 0xc6, 0x05, 0xed, 0x41, 0x2b, 0x9b, 0x34, 0xab, 0x57, 0xbc, 0x5e, 0x7e, 0x6d, 0xbf, - 0x42, 0xe1, 0x28, 0xee, 0x2f, 0x39, 0xda, 0xc5, 0xe5, 0x85, 0xc2, 0x44, 0x83, 0x32, 0x78, 0xd9, 0xb9, 0x81, 0xfe, - 0xc3, 0xe3, 0xd2, 0x27, 0x77, 0x9e, 0xa2, 0x88, 0x26, 0xc2, 0xf9, 0x0f, 0xa1, 0x3a, 0xe5, 0xce, 0x67, 0x9d, 0x9b, - 0x60, 0xb0, 0x76, 0x0d, 0x10, 0xb2, 0xc4, 0x26, 0xd3, 0x8f, 0x65, 0x97, 0x44, 0xcd, 0xa9, 0x4e, 0x7a, 0x68, 0xec, - 0xa4, 0x24, 0x17, 0xde, 0x0d, 0xb7, 0xb9, 0x93, 0x55, 0xcb, 0xf2, 0x29, 0xe7, 0x48, 0x56, 0x5d, 0x28, 0xff, 0x33, - 0xaa, 0xa1, 0x1e, 0x72, 0xf5, 0x33, 0xed, 0x8a, 0x80, 0xae, 0x89, 0xfd, 0xcf, 0xbb, 0x56, 0xbb, 0x41, 0xf8, 0x4c, - 0x0d, 0x5a, 0x9b, 0xc4, 0x44, 0xb4, 0x2a, 0x44, 0xe0, 0x90, 0x20, 0x16, 0x89, 0xbe, 0xad, 0x7a, 0x9f, 0xc7, 0x84, - 0x14, 0x6e, 0xfe, 0xfd, 0x71, 0xa2, 0x00, 0xaa, 0xa2, 0x57, 0xa6, 0x70, 0xb6, 0x49, 0x81, 0x11, 0xae, 0x87, 0xf8, - 0x57, 0x43, 0x2e, 0x34, 0x70, 0x37, 0x19, 0xb5, 0xb3, 0x17, 0x25, 0x49, 0xc4, 0x35, 0xcd, 0xc7, 0x76, 0x6c, 0x2a, - 0xb6, 0xba, 0x84, 0x6e, 0x0f, 0xec, 0xf5, 0xb2, 0x30, 0x46, 0xd3, 0x06, 0x89, 0x62, 0xac, 0xbd, 0x05, 0x56, 0x6d, - 0xcb, 0xa0, 0xb2, 0x27, 0x6e, 0x88, 0x4a, 0x68, 0x74, 0xd1, 0x2b, 0x8c, 0x37, 0x74, 0x60, 0xd2, 0x8b, 0x67, 0x31, - 0x6d, 0xd5, 0xad, 0xb9, 0xe6, 0x9e, 0x74, 0x53, 0x95, 0xd5, 0x29, 0x97, 0x64, 0x35, 0xe5, 0x46, 0x77, 0xb3, 0x90, - 0x9b, 0x0e, 0x82, 0xe1, 0xb7, 0xe6, 0x54, 0xcc, 0x5e, 0x02, 0x76, 0xb9, 0x02, 0x45, 0xe9, 0xee, 0x17, 0x05, 0x4c, - 0x1c, 0x2f, 0x6a, 0xf2, 0x0d, 0x2f, 0x9a, 0x05, 0x95, 0x13, 0xdf, 0xef, 0x12, 0xfd, 0xa8, 0x96, 0x4f, 0x54, 0xf8, - 0x80, 0x3c, 0xb8, 0x16, 0xbc, 0x5c, 0x98, 0x5c, 0x65, 0xe9, 0x4c, 0x5c, 0xcb, 0xa6, 0x59, 0xd9, 0x95, 0x63, 0x2e, - 0x1a, 0xaf, 0xe7, 0x40, 0xa3, 0xa6, 0xbc, 0xf5, 0x4d, 0xa5, 0x67, 0x95, 0xd4, 0x44, 0x4e, 0xcf, 0xb1, 0x44, 0xea, - 0x98, 0x5c, 0x0a, 0x5f, 0xfc, 0xb5, 0x14, 0x52, 0xeb, 0xad, 0xa5, 0x9d, 0x18, 0x84, 0xbb, 0xce, 0x27, 0x5c, 0x0a, - 0x5e, 0xfc, 0x62, 0x01, 0x3a, 0x15, 0x79, 0x03, 0xd7, 0x8b, 0x85, 0x3d, 0xf3, 0xf3, 0x16, 0xbd, 0xad, 0x71, 0xdc, - 0x5c, 0x24, 0xf4, 0xfb, 0x36, 0x9f, 0x4a, 0xea, 0x60, 0x9f, 0x1f, 0xe1, 0xc1, 0xae, 0x2b, 0xf2, 0x5a, 0x49, 0x07, - 0x98, 0x20, 0x0c, 0xac, 0x6c, 0x25, 0xee, 0x41, 0x10, 0xe1, 0x05, 0xdc, 0x03, 0x52, 0x9b, 0xa5, 0xfb, 0xf9, 0x2a, - 0xba, 0x7f, 0x89, 0xf9, 0xfd, 0x14, 0x58, 0xa8, 0x57, 0x93, 0x61, 0x78, 0x0b, 0x0c, 0x1a, 0x89, 0x50, 0x04, 0x4e, - 0xc8, 0x5b, 0x24, 0x98, 0xba, 0x46, 0xed, 0x26, 0x38, 0xa2, 0xff, 0xd1, 0x4b, 0xc7, 0xac, 0x61, 0x46, 0xfc, 0x82, - 0x11, 0xa3, 0xf0, 0xca, 0xc7, 0x77, 0xce, 0x10, 0xee, 0x9a, 0xa7, 0xe8, 0xc8, 0x2f, 0xb7, 0xf7, 0xf4, 0xa2, 0x2b, - 0xfc, 0x20, 0x63, 0x00, 0x5d, 0xe4, 0x2a, 0x2f, 0xc4, 0x78, 0x51, 0x5b, 0x37, 0x40, 0x15, 0xc2, 0x93, 0x1b, 0x86, - 0x57, 0x93, 0x43, 0x73, 0x73, 0x1a, 0xc3, 0x8a, 0x3c, 0x6c, 0xba, 0x0e, 0x83, 0x3c, 0x79, 0xce, 0xa6, 0x1a, 0x4e, - 0xff, 0xb5, 0x9a, 0xda, 0x78, 0x51, 0x7b, 0x1c, 0x43, 0x29, 0x5a, 0xe9, 0x74, 0x02, 0x61, 0x51, 0x1d, 0x24, 0xf7, - 0x62, 0x37, 0x87, 0xbb, 0x7d, 0xef, 0xd3, 0x17, 0x12, 0x53, 0xb8, 0xf1, 0xea, 0x6c, 0xc7, 0x02, 0x2e, 0xc5, 0x3c, - 0xbd, 0xf0, 0x76, 0x17, 0xc9, 0x40, 0xd8, 0x3f, 0xdb, 0x9c, 0x4c, 0x94, 0x22, 0xbd, 0x44, 0x2a, 0x17, 0x26, 0x48, - 0x76, 0x02, 0xb2, 0xfb, 0x2f, 0x54, 0x9b, 0x46, 0xa0, 0xb6, 0x9b, 0xf0, 0xf6, 0xee, 0xb6, 0x27, 0xef, 0xde, 0xab, - 0xd5, 0x08, 0x9b, 0x6a, 0x8c, 0x43, 0x4c, 0xab, 0xa7, 0xd8, 0x2d, 0x15, 0x20, 0xb4, 0x58, 0x82, 0x73, 0xcf, 0xcd, - 0x9b, 0xc7, 0xdb, 0x83, 0x99, 0x91, 0xd9, 0xe7, 0xda, 0xff, 0xbe, 0xc9, 0x06, 0x8b, 0x4b, 0xb7, 0x57, 0x3e, 0x44, - 0xda, 0x72, 0x59, 0xf2, 0x44, 0x30, 0xa3, 0x09, 0x8c, 0x93, 0xf3, 0xce, 0xb0, 0x55, 0x4e, 0xdd, 0xa1, 0xc5, 0x58, - 0xe5, 0x91, 0xc8, 0x95, 0xe0, 0x12, 0xfa, 0x6c, 0x8f, 0x02, 0x13, 0x69, 0x32, 0xb6, 0x6f, 0x02, 0x61, 0x07, 0x2a, - 0xac, 0xbe, 0x80, 0x78, 0x9b, 0x38, 0x64, 0xe0, 0x35, 0x51, 0x28, 0xde, 0xb7, 0xa6, 0x7c, 0x3f, 0x29, 0xe7, 0x35, - 0x9a, 0x43, 0x6a, 0x7a, 0x8b, 0xfc, 0x3e, 0x58, 0x1f, 0xeb, 0xaf, 0xe4, 0xe0, 0xe5, 0xcc, 0xd0, 0x2f, 0x8c, 0x9c, - 0x73, 0x1b, 0x87, 0x61, 0x38, 0x88, 0x55, 0x60, 0xea, 0xc1, 0xaa, 0x58, 0x3b, 0xe4, 0xf9, 0x92, 0xd7, 0x54, 0x80, - 0x3b, 0x7a, 0x16, 0x51, 0x58, 0xac, 0xc0, 0x9a, 0xae, 0x21, 0xaf, 0xc4, 0x13, 0xf9, 0x97, 0x7d, 0x62, 0x0e, 0x12, - 0x61, 0x1b, 0xe8, 0x91, 0x58, 0xff, 0x41, 0x40, 0x46, 0x27, 0xbb, 0xd1, 0xe8, 0xfa, 0xa5, 0xa5, 0xaa, 0x15, 0xb4, - 0x93, 0xfa, 0x36, 0xf7, 0x7d, 0x19, 0xcf, 0xe2, 0x38, 0xb5, 0xad, 0x3e, 0xcc, 0x2c, 0xb3, 0xb0, 0xfe, 0x04, 0xe3, - 0xd6, 0x30, 0xab, 0xf2, 0xff, 0x20, 0x1f, 0x2f, 0xe9, 0xd1, 0x3e, 0xc0, 0x4c, 0xe7, 0xf4, 0x6b, 0x91, 0x33, 0x77, - 0x4e, 0x9b, 0x4d, 0x36, 0xc6, 0xc5, 0xee, 0x80, 0xd3, 0x66, 0xfd, 0xe4, 0x5d, 0xb8, 0x79, 0x4f, 0x5f, 0xf6, 0xf0, - 0xf6, 0x13, 0x77, 0x7b, 0x27, 0xac, 0x82, 0xf7, 0xfe, 0xf3, 0x06, 0x57, 0x57, 0xff, 0x0d, 0x0b, 0x8c, 0xe7, 0xb5, - 0x07, 0x73, 0x9a, 0x63, 0xba, 0x8c, 0xfd, 0x85, 0xf9, 0xa8, 0xef, 0xdd, 0x1d, 0x46, 0x04, 0xaa, 0xf8, 0x72, 0x28, - 0x4e, 0x99, 0x74, 0x80, 0x40, 0x75, 0x7d, 0xfc, 0xd5, 0x77, 0x46, 0xa9, 0x4c, 0x38, 0x7e, 0x46, 0x53, 0x8d, 0x71, - 0xb8, 0x23, 0xb8, 0x90, 0xad, 0x47, 0xfa, 0x39, 0xef, 0x06, 0x3c, 0xe6, 0x79, 0x54, 0xc3, 0x55, 0x90, 0x19, 0x8d, - 0x33, 0x8b, 0x82, 0x39, 0x77, 0xfd, 0x09, 0x18, 0x40, 0xcc, 0x45, 0x97, 0x06, 0xba, 0x55, 0x2f, 0xe4, 0xa9, 0x4b, - 0x1b, 0x36, 0xf7, 0xfd, 0xaf, 0x37, 0xf3, 0x8e, 0xef, 0xb6, 0x65, 0x43, 0xa1, 0xde, 0x2e, 0xcf, 0x8a, 0x65, 0xd8, - 0x5d, 0x72, 0x99, 0x5d, 0xff, 0x7f, 0x17, 0xd0, 0x7a, 0x11, 0xa2, 0x64, 0x6b, 0x29, 0x20, 0x5c, 0x6c, 0x73, 0xff, - 0x11, 0xbd, 0x71, 0x68, 0x0d, 0x27, 0x1e, 0x73, 0x76, 0xbf, 0x1b, 0x18, 0xc4, 0x71, 0x7e, 0x21, 0xe0, 0xd6, 0xd4, - 0x8d, 0x12, 0x9f, 0x14, 0xef, 0xfa, 0xe1, 0x02, 0x81, 0xff, 0x2f, 0x7e, 0x8e, 0x01, 0xfe, 0xd7, 0xd1, 0x23, 0xba, - 0xe1, 0x67, 0xa4, 0x78, 0xeb, 0x23, 0x77, 0xbe, 0x93, 0xf3, 0x09, 0xee, 0x51, 0xe0, 0x9d, 0x7a, 0x6d, 0xcd, 0xe5, - 0xc6, 0x5e, 0xa6, 0x3c, 0x97, 0x6d, 0xd6, 0x8b, 0x32, 0xcd, 0x64, 0xf8, 0x30, 0x99, 0xcc, 0xca, 0x41, 0x1b, 0x65, - 0x57, 0x2e, 0x46, 0x48, 0x5b, 0x64, 0xf4, 0x6f, 0x47, 0x12, 0x25, 0x53, 0xba, 0x9d, 0x3d, 0x8a, 0x5e, 0x28, 0xf4, - 0xc9, 0x92, 0x81, 0xe5, 0x75, 0x80, 0x5a, 0xe2, 0xae, 0x42, 0x24, 0x84, 0x64, 0x1a, 0x00, 0xfb, 0x24, 0xd0, 0x50, - 0xf8, 0x52, 0xcf, 0x49, 0xeb, 0x17, 0x8e, 0x89, 0x20, 0xe9, 0x21, 0x3a, 0x4a, 0x25, 0x53, 0x66, 0x7c, 0xab, 0x6b, - 0xf5, 0x74, 0x7e, 0xeb, 0x8c, 0x67, 0x9f, 0x8f, 0xfc, 0xcf, 0xdc, 0x9c, 0x08, 0x8b, 0xad, 0x27, 0x50, 0x21, 0xaf, - 0x3c, 0x65, 0xab, 0x17, 0x0c, 0x93, 0x3a, 0x7e, 0xb3, 0xb1, 0xba, 0xf4, 0x5d, 0x12, 0x90, 0xd5, 0xfe, 0x24, 0xbd, - 0xc6, 0xe5, 0xaf, 0x9b, 0xee, 0x19, 0xf3, 0xeb, 0x55, 0x8e, 0x6a, 0x35, 0x5b, 0x4c, 0xf1, 0xe6, 0x5a, 0xea, 0xc9, - 0xb8, 0xe7, 0xd8, 0x13, 0x2a, 0xc9, 0x8b, 0x78, 0x15, 0xf6, 0x6c, 0xbe, 0x41, 0xdb, 0x41, 0xea, 0x05, 0x53, 0xd3, - 0xfa, 0x74, 0x6e, 0xdf, 0xcd, 0xac, 0x3b, 0xb3, 0xdc, 0x65, 0xaf, 0x5b, 0xc3, 0x81, 0xfb, 0xc5, 0x98, 0x4f, 0x39, - 0xe4, 0xb3, 0xda, 0x9a, 0x4b, 0x2e, 0xc8, 0x29, 0xc2, 0xda, 0x6b, 0xc3, 0x90, 0x89, 0x5b, 0x1b, 0x16, 0x8d, 0x4f, - 0x17, 0xc4, 0x38, 0x48, 0x9a, 0xef, 0x68, 0xbf, 0x16, 0xf5, 0xf1, 0xf5, 0xf1, 0xdc, 0xd1, 0xba, 0x7b, 0xd2, 0xd9, - 0x6f, 0xf7, 0x81, 0x23, 0x8e, 0xca, 0x35, 0x82, 0x28, 0x16, 0x22, 0x01, 0x5d, 0x6b, 0x34, 0xd7, 0xcb, 0x9a, 0x7b, - 0xa8, 0xc9, 0xc7, 0x2d, 0x26, 0xab, 0x95, 0x39, 0xaf, 0xe9, 0x93, 0x11, 0xc3, 0x7c, 0x6b, 0x44, 0x0f, 0xb9, 0x68, - 0x00, 0x20, 0x23, 0xed, 0xae, 0xd5, 0x3b, 0x73, 0xa7, 0xc2, 0xd9, 0x3b, 0xd8, 0xf9, 0xb3, 0x53, 0x7e, 0x1a, 0xaf, - 0x3f, 0x55, 0x5c, 0x79, 0x0c, 0x47, 0xaa, 0x3c, 0xbb, 0xa7, 0x15, 0x9c, 0xab, 0x6b, 0x4b, 0x73, 0x18, 0x43, 0xf6, - 0x36, 0x73, 0x2b, 0xb9, 0xe2, 0x5e, 0xbe, 0x28, 0xee, 0xd0, 0xea, 0xb8, 0x87, 0x94, 0x8e, 0x66, 0xa5, 0x2f, 0x37, - 0xc7, 0x69, 0xb8, 0xfe, 0xe3, 0x23, 0x77, 0xca, 0x4d, 0xdd, 0xeb, 0x71, 0x82, 0x71, 0x0d, 0x8a, 0xfb, 0x94, 0x21, - 0xe4, 0x04, 0x13, 0xfc, 0x5e, 0xb7, 0x2f, 0xb1, 0x4e, 0x99, 0xa3, 0x28, 0x32, 0xe0, 0xc3, 0xa4, 0x98, 0xd0, 0xfe, - 0x99, 0xdd, 0x60, 0x4c, 0xf3, 0xb7, 0xb5, 0x3a, 0xca, 0x8c, 0xe7, 0xf9, 0x0e, 0x14, 0x02, 0x72, 0x92, 0x24, 0x96, - 0x60, 0x97, 0x5f, 0xe9, 0x0f, 0x4e, 0x1c, 0x37, 0xe6, 0xba, 0xf6, 0x46, 0x9e, 0x12, 0x22, 0x4d, 0xe5, 0xab, 0xc3, - 0x69, 0x37, 0xa7, 0x41, 0x8f, 0x90, 0x50, 0xbd, 0x54, 0xc9, 0x1a, 0xfb, 0x42, 0x1a, 0xe9, 0xe7, 0x23, 0x7d, 0x6a, - 0x2f, 0x81, 0x02, 0x10, 0x5a, 0x6b, 0xa9, 0xd2, 0x68, 0xb8, 0x6e, 0x02, 0x88, 0x4f, 0xe3, 0xe5, 0x01, 0x8a, 0xe6, - 0x78, 0x76, 0x2e, 0x58, 0x8b, 0x9f, 0x14, 0x9f, 0x99, 0x87, 0xce, 0x32, 0x8c, 0x03, 0x37, 0xa7, 0xd4, 0xa9, 0xdb, - 0xb5, 0x53, 0x8e, 0xd5, 0xc1, 0x6a, 0x99, 0x7e, 0xcc, 0xbb, 0x45, 0xbc, 0x78, 0xe3, 0xbc, 0x1b, 0xab, 0x73, 0x6c, - 0x6c, 0xfa, 0x24, 0x5e, 0x7e, 0xee, 0xa4, 0xc9, 0xa0, 0xc8, 0xf2, 0x58, 0x96, 0x13, 0xec, 0x15, 0xf7, 0x89, 0x9a, - 0x37, 0x4d, 0xba, 0x31, 0x67, 0x05, 0x58, 0x7b, 0xed, 0xe8, 0x3d, 0x9c, 0x5a, 0x0f, 0xbe, 0xfd, 0x3f, 0x74, 0xd4, - 0x57, 0x6b, 0xbf, 0x0b, 0xe7, 0xca, 0xc2, 0xf3, 0x18, 0xa2, 0x2c, 0x0f, 0x60, 0xb6, 0xfc, 0xb5, 0xff, 0x65, 0x88, - 0x3f, 0x68, 0x77, 0xfb, 0xd7, 0x93, 0xcb, 0x13, 0xc0, 0x19, 0x9b, 0xed, 0xa3, 0x0e, 0x52, 0x5d, 0xef, 0x1c, 0xb5, - 0xdf, 0xb3, 0x73, 0x9f, 0x81, 0x32, 0xc2, 0x89, 0xcf, 0x1b, 0xfb, 0x55, 0x00, 0xfa, 0xfe, 0x82, 0x6d, 0xf1, 0xa7, - 0xcd, 0x82, 0xbc, 0xd9, 0x6e, 0xc2, 0xfe, 0x28, 0x30, 0x5c, 0x7b, 0xfd, 0x8a, 0x00, 0xa8, 0x6b, 0xed, 0x2b, 0xed, - 0x72, 0xfb, 0xb0, 0x02, 0x10, 0xb1, 0x50, 0x13, 0x36, 0x51, 0xfd, 0x97, 0x48, 0x97, 0x34, 0x2c, 0x61, 0xa6, 0xfa, - 0x09, 0xdb, 0xb3, 0x26, 0x06, 0x56, 0x7a, 0x00, 0x5b, 0x58, 0x07, 0x74, 0x83, 0x28, 0x5e, 0x87, 0x06, 0xff, 0x4e, - 0x58, 0x90, 0xf7, 0x94, 0xa1, 0x66, 0xa8, 0xe2, 0x52, 0x58, 0xf3, 0x28, 0x25, 0x30, 0x3c, 0x87, 0x36, 0xc0, 0x5a, - 0x8a, 0x98, 0xdb, 0x2e, 0xc9, 0x20, 0x48, 0xbc, 0x3e, 0xc0, 0x33, 0xe0, 0xdd, 0x1c, 0x3c, 0xc0, 0x00, 0xa4, 0xbe, - 0xa0, 0xe8, 0xcd, 0x83, 0xef, 0xd6, 0xcc, 0xcc, 0x4e, 0x77, 0xa3, 0x58, 0xac, 0x5a, 0x88, 0xb0, 0x45, 0xa4, 0x6d, - 0xab, 0x66, 0x85, 0x0e, 0x78, 0xa2, 0x47, 0x51, 0x92, 0x12, 0xfc, 0x37, 0x23, 0x00, 0x11, 0x35, 0x4c, 0x28, 0x28, - 0xd8, 0xdb, 0xe3, 0x76, 0xe2, 0xcb, 0x5b, 0x5a, 0x73, 0x4b, 0x81, 0x57, 0xa1, 0xf1, 0xb0, 0x0e, 0xe4, 0x0a, 0x6b, - 0x90, 0x39, 0xd7, 0xb6, 0x99, 0x1d, 0x9f, 0x76, 0xbe, 0xc4, 0xf3, 0x6b, 0x5c, 0xae, 0x6f, 0x95, 0x22, 0xff, 0x06, - 0x85, 0x88, 0x53, 0xab, 0x52, 0xa9, 0xea, 0x03, 0x58, 0xd3, 0xa5, 0xe0, 0xce, 0xb8, 0xf9, 0x80, 0x40, 0xf2, 0x53, - 0x2e, 0x75, 0xd6, 0x48, 0x0b, 0x48, 0x5f, 0xc2, 0x90, 0x17, 0xa6, 0xab, 0x05, 0xc4, 0xe1, 0x81, 0xfe, 0x58, 0x14, - 0xc9, 0x93, 0x49, 0x14, 0xd4, 0xf0, 0x54, 0x55, 0xeb, 0xf5, 0x52, 0xaf, 0x93, 0x63, 0x67, 0x4f, 0xcc, 0xb2, 0x4d, - 0xcd, 0x90, 0xcd, 0xe4, 0xc5, 0xfd, 0x70, 0x5d, 0xbd, 0xbc, 0x0f, 0x8a, 0x1e, 0x27, 0x37, 0x08, 0xc8, 0x5b, 0x75, - 0xf4, 0x3a, 0x2d, 0x48, 0xd0, 0x2e, 0x97, 0xa6, 0x99, 0xe5, 0xf2, 0x68, 0x82, 0x10, 0x3e, 0x6b, 0xf6, 0x59, 0x71, - 0xd1, 0x34, 0x9d, 0x18, 0x39, 0x5c, 0xde, 0xf0, 0x74, 0x66, 0x64, 0x5a, 0x77, 0x5e, 0x34, 0x26, 0x94, 0xba, 0x6a, - 0x57, 0x7a, 0xe3, 0x8d, 0xd3, 0xd9, 0xda, 0xa9, 0xdd, 0x85, 0x32, 0xb8, 0xa8, 0x89, 0xc7, 0x6c, 0x04, 0x20, 0xba, - 0x76, 0xaa, 0x94, 0x27, 0xa7, 0xce, 0x84, 0xe6, 0x16, 0x3b, 0xaf, 0x80, 0xb6, 0x7f, 0xda, 0x95, 0x4a, 0x2b, 0xc4, - 0x22, 0x75, 0xfc, 0x7b, 0xf1, 0xdc, 0xaf, 0x37, 0xab, 0xca, 0xeb, 0x65, 0xd0, 0xc6, 0xeb, 0xcd, 0xae, 0x66, 0xa5, - 0xa9, 0x55, 0xd8, 0x0a, 0x6c, 0x6d, 0xad, 0xe8, 0x0c, 0x3d, 0x7d, 0x93, 0x1c, 0x63, 0x9b, 0x17, 0x32, 0xe6, 0xac, - 0xfd, 0xca, 0x2b, 0x74, 0x75, 0x60, 0xff, 0x8b, 0x7f, 0x47, 0x10, 0x16, 0x2a, 0x56, 0xfe, 0x20, 0xe4, 0x9a, 0xc0, - 0x5a, 0xa2, 0x7e, 0x64, 0x1f, 0xb4, 0xff, 0x12, 0xb7, 0xbd, 0xcf, 0x4d, 0x85, 0xc2, 0x77, 0xa7, 0xc4, 0x8d, 0x0b, - 0x38, 0x22, 0x81, 0x2d, 0x07, 0xe3, 0x7e, 0x7c, 0x19, 0x8c, 0x35, 0xfd, 0x91, 0x28, 0xf1, 0x9f, 0x59, 0x3f, 0x6f, - 0x29, 0x82, 0xb2, 0x36, 0xb8, 0x3b, 0x42, 0x75, 0x93, 0x18, 0x5e, 0x9f, 0x1c, 0x53, 0x0a, 0xe2, 0x98, 0x5a, 0x91, - 0x85, 0x1e, 0x5e, 0xdf, 0xb8, 0x65, 0x9f, 0xf9, 0x10, 0x77, 0x6a, 0xdc, 0xfa, 0xda, 0xc2, 0xd5, 0x40, 0xb8, 0x3f, - 0xf9, 0x4d, 0xc4, 0x8b, 0x84, 0x4c, 0x75, 0xf6, 0x3c, 0xb3, 0x1f, 0x42, 0xe7, 0x59, 0xf0, 0x3d, 0x82, 0x29, 0xfd, - 0x2b, 0x2f, 0xc4, 0xef, 0x26, 0xed, 0x65, 0xe6, 0x69, 0x6e, 0x3f, 0x47, 0x41, 0xcc, 0x4f, 0x72, 0x8c, 0x30, 0x52, - 0x86, 0x6e, 0x88, 0x11, 0x25, 0xbc, 0xa9, 0xc4, 0x6e, 0x76, 0xff, 0xa8, 0x83, 0x77, 0x20, 0xaf, 0x08, 0xbf, 0x24, - 0xf6, 0xc4, 0x32, 0x84, 0xa5, 0x66, 0x09, 0x17, 0x6a, 0x0e, 0x6d, 0xac, 0xd7, 0x2d, 0x9e, 0x58, 0x50, 0xfd, 0x04, - 0xad, 0xb3, 0x41, 0xcc, 0xed, 0xc5, 0x77, 0xf9, 0xee, 0x6c, 0xc2, 0x36, 0x62, 0xe6, 0x3a, 0x38, 0xee, 0xeb, 0x1b, - 0xa0, 0x4c, 0xd0, 0x63, 0x97, 0x08, 0xcb, 0x0a, 0x56, 0x62, 0xb1, 0xf6, 0xf4, 0x8e, 0xfd, 0x87, 0x13, 0x01, 0xbc, - 0xd3, 0x2c, 0x8f, 0xd5, 0x46, 0xc6, 0x3b, 0x6d, 0xd7, 0x1b, 0x62, 0xbb, 0xca, 0xb4, 0x8a, 0x51, 0x42, 0x37, 0x34, - 0x69, 0xe9, 0x06, 0x02, 0xec, 0xa6, 0x22, 0x65, 0xb6, 0x61, 0x0f, 0x5d, 0x3f, 0x3f, 0xa4, 0x6f, 0x76, 0x8e, 0x91, - 0xb6, 0x21, 0x6c, 0x99, 0xfa, 0xe5, 0x9b, 0x3e, 0x74, 0x2f, 0x9d, 0xa6, 0xc3, 0xd6, 0xfa, 0x54, 0xed, 0xa7, 0xfb, - 0xb1, 0x1d, 0x78, 0x98, 0xa9, 0x13, 0xf1, 0x94, 0x7b, 0xfc, 0x0d, 0x7d, 0xa6, 0x22, 0x64, 0xe0, 0x14, 0x92, 0x13, - 0x92, 0x3b, 0x86, 0x25, 0x31, 0x8a, 0xf3, 0x82, 0x01, 0x3a, 0xc8, 0xb9, 0xf0, 0x9a, 0x19, 0xac, 0x8f, 0x8e, 0x0b, - 0x85, 0xc9, 0xc0, 0x69, 0x9d, 0x0e, 0x06, 0x08, 0x82, 0x4b, 0xc6, 0x4b, 0x2b, 0x93, 0xc5, 0xe3, 0x11, 0xf3, 0xcb, - 0xe1, 0x59, 0xce, 0x8a, 0xc0, 0xa9, 0x6a, 0xa7, 0x25, 0x65, 0x34, 0xf7, 0x36, 0x5d, 0x5a, 0x87, 0xc4, 0x5b, 0x9f, - 0x3a, 0x1b, 0xc1, 0xb0, 0xb6, 0xf7, 0xb6, 0xc3, 0xa3, 0xeb, 0xdf, 0xd7, 0xb3, 0x61, 0xc1, 0xe2, 0xb0, 0x31, 0xc0, - 0x99, 0x8b, 0xe7, 0x2d, 0x8a, 0xc7, 0x64, 0x66, 0xcf, 0x0f, 0xae, 0xf6, 0x2e, 0x3f, 0xcd, 0xbe, 0x63, 0x9b, 0x3d, - 0x7a, 0xd3, 0xcd, 0x40, 0xeb, 0xdd, 0x16, 0x29, 0xf1, 0xf1, 0xb1, 0x76, 0x79, 0x63, 0x96, 0x2c, 0xbc, 0xcc, 0xd1, - 0xfa, 0x87, 0x79, 0xc9, 0x61, 0xd3, 0x4d, 0xad, 0x8b, 0xef, 0x2c, 0xa5, 0xd9, 0x9b, 0x80, 0xba, 0xd0, 0x44, 0x25, - 0x82, 0xd0, 0xca, 0xe0, 0x71, 0x8f, 0xb6, 0xf6, 0x0e, 0xb3, 0xd2, 0xe6, 0x52, 0x03, 0x0f, 0x8f, 0xfa, 0x18, 0x9c, - 0x74, 0xcc, 0xb2, 0xc5, 0x57, 0x68, 0xb6, 0xae, 0x2c, 0x4d, 0x46, 0x55, 0x75, 0xc4, 0x3a, 0x73, 0x11, 0x2f, 0x4d, - 0x69, 0xb6, 0xee, 0x2a, 0x30, 0x9d, 0x9a, 0x6f, 0x76, 0x71, 0xa1, 0x14, 0xfe, 0x9b, 0x6e, 0x4f, 0x74, 0x6c, 0xa5, - 0x38, 0xda, 0xc8, 0x60, 0x1a, 0xee, 0xf2, 0x4b, 0x1e, 0x79, 0x90, 0xf7, 0x10, 0x9c, 0x5a, 0x85, 0x42, 0xbe, 0x62, - 0x6f, 0xd0, 0xaa, 0x9a, 0xa3, 0x4d, 0xce, 0xec, 0xea, 0x7c, 0xb5, 0x2e, 0x4f, 0x25, 0xca, 0xd4, 0xa8, 0xd1, 0x86, - 0xcf, 0x33, 0x56, 0x3f, 0xc4, 0xae, 0xdb, 0x8b, 0xa7, 0x03, 0x3f, 0x51, 0xaf, 0xb3, 0x92, 0xa2, 0x08, 0xe8, 0x50, - 0xe3, 0xda, 0x91, 0x8d, 0x94, 0xe9, 0xce, 0xba, 0x64, 0x1d, 0xc3, 0xe2, 0x64, 0x76, 0x7a, 0x80, 0x6e, 0xd0, 0x4c, - 0x73, 0xaa, 0x5d, 0x23, 0x04, 0x66, 0xfc, 0xe9, 0x11, 0xfa, 0x45, 0x56, 0x73, 0x1a, 0x67, 0x05, 0xf0, 0x95, 0x54, - 0x34, 0xcf, 0x2a, 0x66, 0x24, 0xdc, 0xb2, 0xc9, 0x96, 0xe6, 0x7f, 0xe9, 0x2e, 0x6c, 0xd7, 0xa5, 0x10, 0x94, 0x02, - 0x55, 0x3a, 0x09, 0xfe, 0x53, 0xca, 0xf0, 0xa7, 0x05, 0x8c, 0x5e, 0xf6, 0x7c, 0x3b, 0x66, 0xcd, 0xd6, 0xf0, 0x9d, - 0xc1, 0x4f, 0x35, 0x28, 0x7e, 0xc2, 0xba, 0x85, 0xe2, 0xeb, 0x2e, 0xe0, 0x11, 0x54, 0x0f, 0xb3, 0xaf, 0x99, 0x7a, - 0x78, 0x97, 0x8d, 0x62, 0xc3, 0x28, 0x5a, 0xbf, 0x56, 0x93, 0x29, 0xcd, 0xb1, 0x24, 0x58, 0xd9, 0x34, 0xb2, 0x84, - 0x50, 0xbd, 0x6f, 0x4e, 0x7d, 0xeb, 0x6d, 0x24, 0x4e, 0x42, 0x12, 0x4e, 0xd0, 0xc7, 0x03, 0x89, 0x74, 0x3c, 0x19, - 0xd0, 0xd9, 0x46, 0x26, 0x3a, 0x9b, 0x28, 0xa4, 0xb3, 0xe0, 0x9a, 0x63, 0x29, 0x55, 0x73, 0xe5, 0x75, 0x9e, 0xf0, - 0x4d, 0xe1, 0x97, 0xd0, 0xf4, 0x7a, 0xeb, 0xf7, 0x39, 0xab, 0xf0, 0x9f, 0x0f, 0x13, 0xbe, 0xc1, 0xd8, 0xb0, 0x7e, - 0x8f, 0x88, 0x50, 0x01, 0x0f, 0x74, 0xeb, 0xf0, 0x75, 0xb4, 0x1a, 0x46, 0x68, 0xd3, 0xad, 0xa0, 0xe0, 0x90, 0xf6, - 0xfb, 0xee, 0x6a, 0x1b, 0xde, 0x9c, 0xbd, 0xd3, 0x3a, 0x79, 0x83, 0xf9, 0xf1, 0x56, 0xc9, 0xbb, 0x91, 0x98, 0x62, - 0xf9, 0x6b, 0xcb, 0x55, 0xba, 0x71, 0x78, 0x77, 0x1c, 0xdf, 0x1d, 0xc7, 0x31, 0xe3, 0x23, 0x7b, 0xd2, 0x72, 0x1c, - 0xce, 0x5c, 0x0f, 0xcc, 0xde, 0x38, 0xf5, 0x8a, 0xa6, 0x03, 0x47, 0x57, 0xf3, 0x2d, 0x7e, 0x2c, 0xc2, 0xc3, 0xaf, - 0x49, 0x54, 0xd6, 0x34, 0x83, 0x26, 0x95, 0xd2, 0xe4, 0xd8, 0x9d, 0xb2, 0x00, 0xd8, 0xfb, 0xe0, 0xce, 0xb4, 0x8d, - 0x9d, 0x5c, 0x4f, 0xd0, 0x25, 0x69, 0x1e, 0xf3, 0xd0, 0x7e, 0xa4, 0xb1, 0x35, 0x97, 0xe5, 0xd8, 0x2e, 0xb8, 0xee, - 0x1a, 0xa0, 0x6a, 0x61, 0xcf, 0x7f, 0x9b, 0x3f, 0xba, 0xbe, 0x23, 0xc7, 0x01, 0x61, 0x69, 0xfe, 0x3c, 0xda, 0x41, - 0xf7, 0x7d, 0xac, 0x70, 0xd8, 0xa2, 0x7d, 0x35, 0x90, 0xaa, 0x83, 0x5a, 0x61, 0x70, 0x51, 0xa9, 0xb2, 0x75, 0xc4, - 0xf0, 0x82, 0x6c, 0x12, 0x0a, 0x85, 0xc2, 0xf1, 0xc4, 0x7a, 0xdb, 0xed, 0x8f, 0x58, 0x4a, 0x7b, 0xa8, 0x5f, 0x3b, - 0x41, 0xa4, 0xbd, 0xf5, 0x77, 0x3b, 0x5c, 0xd4, 0xe1, 0xe2, 0x55, 0x2f, 0xf4, 0x9c, 0x36, 0xa1, 0xd9, 0x62, 0xac, - 0x57, 0x8a, 0x4d, 0x90, 0xdd, 0x1e, 0x3f, 0x23, 0xdb, 0xb1, 0x59, 0x21, 0x09, 0xe9, 0x2f, 0xcf, 0x67, 0x72, 0x54, - 0xd1, 0xbf, 0xb1, 0x9c, 0xb2, 0x14, 0x13, 0xef, 0xc0, 0x2f, 0x7a, 0xca, 0x95, 0x34, 0x0e, 0xaa, 0x3b, 0x7c, 0x08, - 0x8a, 0xfa, 0xb9, 0x2d, 0xbd, 0xc1, 0x2c, 0x4f, 0x06, 0x55, 0x70, 0x00, 0x63, 0x36, 0xf2, 0xe8, 0x7a, 0x76, 0x29, - 0x06, 0x53, 0xbe, 0x5c, 0xb5, 0x59, 0xbb, 0x61, 0xea, 0xc6, 0xba, 0x30, 0xdc, 0x32, 0xb6, 0x31, 0x01, 0x1a, 0xdb, - 0x34, 0xdb, 0x4c, 0x9b, 0xfe, 0xf6, 0x99, 0xc8, 0xe3, 0xe0, 0x48, 0x44, 0x20, 0x1f, 0x44, 0x1f, 0x0c, 0x48, 0xff, - 0xbe, 0x48, 0xc1, 0xe8, 0x52, 0x15, 0x3f, 0x89, 0x15, 0x1d, 0xf0, 0x9b, 0xf5, 0x1f, 0xa1, 0x63, 0xcc, 0x79, 0xbb, - 0xd0, 0xd8, 0x9d, 0x82, 0x1d, 0xb6, 0x7b, 0xd6, 0xa0, 0x8a, 0xd1, 0xd6, 0x20, 0x56, 0xd0, 0xd4, 0xb8, 0x81, 0xf5, - 0x6d, 0xc2, 0x6a, 0x3c, 0xa6, 0xd5, 0xcc, 0x65, 0xb8, 0xcb, 0x85, 0x75, 0x36, 0xe5, 0x2d, 0x88, 0x0f, 0x02, 0x91, - 0x31, 0x09, 0xc2, 0xe8, 0xb1, 0xf0, 0x07, 0x99, 0x79, 0x81, 0x2c, 0x5d, 0xc7, 0x9f, 0x99, 0x8c, 0xfb, 0x80, 0xa1, - 0x7d, 0x50, 0x3f, 0x68, 0x21, 0x5d, 0x68, 0xfe, 0x2a, 0xab, 0x6a, 0x6e, 0xe6, 0xb8, 0x11, 0x0e, 0x2d, 0xa9, 0x9a, - 0x23, 0xd0, 0x42, 0x20, 0xd4, 0xf6, 0x7b, 0x03, 0xac, 0xe5, 0x87, 0xf0, 0x92, 0x39, 0x00, 0x64, 0x16, 0x13, 0xae, - 0x5e, 0xb7, 0x4a, 0x48, 0x5d, 0x1c, 0x3d, 0x6e, 0x5c, 0x53, 0x36, 0x19, 0x22, 0x88, 0x64, 0x3e, 0x8f, 0x80, 0x39, - 0xce, 0xbf, 0x8b, 0xe8, 0x04, 0x4b, 0x3f, 0x16, 0x77, 0xf9, 0xa3, 0x61, 0xa6, 0xfa, 0xf3, 0xa9, 0x7a, 0x12, 0x13, - 0x96, 0x22, 0xfe, 0x96, 0xd7, 0xe6, 0x24, 0x4a, 0x91, 0x9b, 0x4d, 0x60, 0x94, 0x23, 0x3d, 0xae, 0x24, 0x79, 0x4a, - 0x34, 0x08, 0x83, 0x68, 0x55, 0x7c, 0x7b, 0xe4, 0xa4, 0x13, 0x1e, 0xcd, 0xe2, 0x5d, 0xf6, 0xf3, 0xb7, 0x03, 0x7f, - 0x9b, 0x7a, 0x2f, 0xd7, 0xae, 0x53, 0xef, 0x3c, 0x98, 0xee, 0x5c, 0x11, 0x93, 0xd3, 0x8f, 0x69, 0xcc, 0xaf, 0xeb, - 0x5d, 0x13, 0x00, 0x44, 0xb8, 0xfc, 0xcf, 0xe1, 0xc8, 0xd8, 0x86, 0x4b, 0xcf, 0x36, 0x38, 0x35, 0xba, 0x7c, 0xdb, - 0x08, 0x3e, 0x11, 0xe2, 0x42, 0x2c, 0x9a, 0x78, 0x84, 0xe8, 0xdc, 0x4e, 0xe4, 0x05, 0xa9, 0xff, 0xcc, 0x8b, 0xa0, - 0x30, 0x7b, 0x2b, 0xdd, 0xf3, 0x6c, 0x6b, 0xb8, 0xa9, 0x72, 0xfb, 0x68, 0xb5, 0xa8, 0x62, 0x4f, 0x83, 0x17, 0x76, - 0xa6, 0x24, 0xf2, 0x81, 0x97, 0x28, 0x86, 0xee, 0x3b, 0x31, 0x7b, 0x34, 0xf4, 0xa8, 0x77, 0xc6, 0x6e, 0xf4, 0x10, - 0x7a, 0x14, 0x8b, 0x54, 0x5f, 0x42, 0xc0, 0xe7, 0x5f, 0xcd, 0xd9, 0x0d, 0x6d, 0x4a, 0x3c, 0x2e, 0xfc, 0xbb, 0x20, - 0x0c, 0xe6, 0x58, 0x02, 0x05, 0xe8, 0xfb, 0x23, 0xc1, 0x03, 0x73, 0xb0, 0x3d, 0x24, 0xb3, 0xd7, 0x69, 0xe6, 0x81, - 0xf6, 0x6b, 0x19, 0x65, 0x24, 0x01, 0x7c, 0xb2, 0xde, 0xa1, 0x34, 0x02, 0xd9, 0xba, 0xc2, 0x80, 0x3e, 0xe9, 0xca, - 0xbb, 0xab, 0xee, 0x6c, 0x52, 0x4c, 0xe8, 0xae, 0x6b, 0x29, 0x01, 0x1d, 0xf1, 0x29, 0xc9, 0x2c, 0x6a, 0xeb, 0x83, - 0x22, 0x8a, 0xbc, 0x4b, 0xcc, 0x25, 0x8d, 0xd4, 0xc7, 0xc7, 0x7a, 0x27, 0xe2, 0xa2, 0x50, 0x53, 0x40, 0x98, 0xd4, - 0x47, 0xf1, 0xbe, 0x00, 0xe2, 0x6c, 0xbd, 0x42, 0x68, 0xc2, 0x35, 0xcf, 0xee, 0x95, 0x09, 0x55, 0x68, 0xeb, 0xa9, - 0xec, 0x02, 0x97, 0xd7, 0x17, 0x4b, 0x10, 0x05, 0x72, 0x0a, 0x62, 0x72, 0x09, 0x8a, 0x0f, 0xc3, 0xf5, 0x04, 0x9c, - 0x22, 0xdf, 0x4b, 0xcd, 0x87, 0xc4, 0x01, 0x38, 0x0a, 0x21, 0x16, 0x23, 0x61, 0x84, 0x64, 0x13, 0xe4, 0xd2, 0x0a, - 0xb4, 0xfb, 0xd5, 0x5e, 0xfb, 0xc2, 0xfd, 0x43, 0x4d, 0xc5, 0xe6, 0x42, 0x16, 0x46, 0x2b, 0xa2, 0x7b, 0x09, 0x47, - 0x59, 0x8a, 0xc3, 0x39, 0xb2, 0x34, 0x0e, 0x0c, 0x73, 0x83, 0x12, 0x10, 0xf6, 0x3f, 0x1b, 0x07, 0x02, 0x60, 0x2e, - 0xad, 0xa4, 0x2d, 0xe1, 0xf3, 0x1b, 0x69, 0xb6, 0xf4, 0x1b, 0x1b, 0xde, 0x3c, 0x54, 0x80, 0x25, 0xb5, 0xb8, 0x61, - 0x2e, 0x2b, 0x9c, 0xd1, 0xea, 0x94, 0xf0, 0xda, 0x42, 0x57, 0x97, 0xec, 0x2f, 0xb9, 0x18, 0xde, 0x0f, 0xcf, 0x55, - 0xb7, 0x19, 0xa8, 0xce, 0x24, 0x9d, 0xc9, 0x53, 0xa5, 0x9e, 0x26, 0xc7, 0xee, 0xfd, 0x4e, 0x01, 0xb2, 0xd0, 0xb8, - 0x9b, 0x75, 0x36, 0xbb, 0x5d, 0x1f, 0xd8, 0x1f, 0x70, 0x41, 0xf1, 0xc7, 0xa4, 0xe3, 0xb3, 0x24, 0xc2, 0x22, 0xab, - 0x3d, 0xb9, 0x1c, 0x9d, 0xeb, 0x9c, 0x99, 0x97, 0x3e, 0x49, 0xe9, 0xae, 0xbc, 0x25, 0xcf, 0x44, 0xc9, 0x49, 0xf2, - 0x82, 0xd5, 0x0e, 0x6c, 0x0f, 0x79, 0x3a, 0x30, 0x81, 0xae, 0xce, 0x1b, 0xef, 0x15, 0x23, 0x4d, 0x1d, 0x76, 0x94, - 0xdd, 0xc8, 0xe0, 0x99, 0x0f, 0xf2, 0xd1, 0x81, 0xe2, 0x19, 0xa6, 0x6b, 0x22, 0xf6, 0x89, 0xcb, 0xae, 0xc0, 0x13, - 0xa2, 0xe3, 0xc3, 0x98, 0x36, 0xe4, 0xfd, 0x2a, 0x7c, 0x28, 0x8e, 0xc5, 0x0f, 0x16, 0x93, 0xc8, 0x07, 0x39, 0xc0, - 0xfb, 0xc0, 0x96, 0x15, 0x46, 0x06, 0x73, 0x6e, 0xec, 0x8e, 0xe3, 0x05, 0x60, 0xc4, 0x43, 0xae, 0x71, 0xc7, 0x67, - 0x20, 0x70, 0x3c, 0x57, 0xcd, 0x76, 0x0e, 0x73, 0x10, 0x00, 0x99, 0xc1, 0x32, 0x71, 0x31, 0x5a, 0x46, 0x29, 0x06, - 0xcf, 0xf8, 0xd4, 0xad, 0x1a, 0x62, 0x99, 0xfe, 0x64, 0x50, 0x2e, 0x5d, 0x0b, 0x29, 0xb8, 0x55, 0xdf, 0x18, 0x13, - 0xd2, 0x6d, 0x23, 0xc1, 0x16, 0xf3, 0xab, 0x20, 0x96, 0x34, 0xa8, 0x6b, 0x72, 0x16, 0x66, 0x0b, 0xa5, 0xbd, 0xe9, - 0x3a, 0x8a, 0xc5, 0xb1, 0x24, 0xae, 0x2d, 0x31, 0x02, 0x04, 0xb3, 0xeb, 0x50, 0x34, 0x62, 0x88, 0x7d, 0xac, 0x3a, - 0x00, 0xf0, 0x18, 0xa2, 0x23, 0xc7, 0xec, 0x3e, 0xb1, 0xf5, 0xf2, 0x06, 0x7e, 0x59, 0xfe, 0x48, 0xc6, 0x2f, 0xcf, - 0xc7, 0xb5, 0x23, 0x8a, 0xfe, 0x8d, 0xc4, 0x53, 0x15, 0x73, 0x20, 0x8d, 0xfd, 0x0b, 0x58, 0xba, 0x02, 0xb9, 0x0c, - 0x1c, 0xc3, 0xd6, 0xcf, 0xac, 0x8f, 0xc1, 0x8f, 0x7d, 0x44, 0x1d, 0xbf, 0x0e, 0x54, 0x59, 0x4a, 0xe4, 0x6f, 0x95, - 0x93, 0xcc, 0x18, 0x9c, 0x0b, 0xdd, 0x9d, 0xb8, 0xa9, 0x57, 0xf6, 0xb6, 0xa1, 0xbe, 0x49, 0xdc, 0xbe, 0xb5, 0xa4, - 0x02, 0xdb, 0xd7, 0x89, 0x1b, 0x43, 0xa1, 0x4f, 0x96, 0x67, 0x9b, 0x02, 0x4d, 0x0c, 0xbd, 0x69, 0x47, 0xee, 0xa6, - 0xda, 0x23, 0xb5, 0xfb, 0xd2, 0xb4, 0x8d, 0x60, 0x96, 0x34, 0x16, 0x4d, 0x86, 0x9f, 0xc7, 0x58, 0x1c, 0x8a, 0x14, - 0x2b, 0x72, 0x19, 0xa0, 0xd0, 0xb0, 0x83, 0x3b, 0xb9, 0xae, 0xd3, 0xec, 0x31, 0x78, 0xa9, 0x29, 0xde, 0xbb, 0x6a, - 0x31, 0xa1, 0x24, 0x4c, 0x33, 0x78, 0x6b, 0x87, 0x95, 0xe6, 0x4a, 0x39, 0x09, 0x64, 0x53, 0x16, 0x36, 0x05, 0x3f, - 0x77, 0x70, 0xfa, 0x83, 0xa2, 0xdc, 0x11, 0x70, 0xdb, 0x4b, 0xdc, 0x7f, 0x12, 0xff, 0x64, 0x88, 0x47, 0x46, 0x66, - 0xf8, 0x2f, 0x89, 0x45, 0xff, 0x00, 0x32, 0x31, 0x2f, 0x69, 0x0f, 0x62, 0x09, 0x4f, 0xd4, 0x3a, 0x98, 0xe5, 0x91, - 0x86, 0x26, 0xc3, 0x67, 0xa1, 0xb0, 0xe8, 0x2a, 0x03, 0x8b, 0xb3, 0x0c, 0xfd, 0xb9, 0xd4, 0xed, 0x03, 0xf8, 0x9b, - 0x68, 0xf1, 0x86, 0x86, 0x49, 0xc8, 0x0a, 0xa0, 0xfa, 0xb0, 0x4c, 0xba, 0x6e, 0x54, 0x1b, 0x24, 0x52, 0x06, 0xed, - 0xe2, 0x84, 0x08, 0xe8, 0xf9, 0x24, 0x9b, 0x6e, 0x78, 0x7a, 0xe3, 0x1f, 0x10, 0xf8, 0xc4, 0xda, 0xb1, 0x68, 0x03, - 0xb1, 0x46, 0xcf, 0x48, 0x7a, 0x9a, 0x01, 0xb6, 0x71, 0x39, 0xc4, 0x36, 0x8e, 0x61, 0x61, 0x66, 0x16, 0xc3, 0x78, - 0x91, 0xb3, 0x61, 0x7d, 0x0a, 0xb1, 0xc0, 0xb8, 0x01, 0xa9, 0x59, 0x4e, 0x48, 0x14, 0x29, 0x7b, 0x14, 0x28, 0x88, - 0x50, 0x7e, 0xf3, 0xb2, 0xfa, 0xb5, 0x4c, 0x80, 0x15, 0x94, 0x56, 0x19, 0x48, 0x5a, 0x1b, 0xcb, 0x49, 0x2d, 0xa9, - 0x8a, 0xf3, 0x4d, 0x19, 0x26, 0xbf, 0xeb, 0x1f, 0xde, 0xa3, 0x17, 0x6c, 0xc2, 0x53, 0x72, 0xcd, 0x46, 0x93, 0xe1, - 0x53, 0x66, 0x7f, 0xc1, 0xf8, 0x00, 0xca, 0x6f, 0x7a, 0x53, 0x86, 0xd2, 0xc6, 0x80, 0x47, 0x9d, 0x97, 0x58, 0x51, - 0x69, 0x37, 0xb9, 0x13, 0x2d, 0x63, 0x6f, 0xf9, 0x87, 0x3b, 0x81, 0x8f, 0x81, 0xcb, 0x0c, 0x10, 0xf4, 0xb7, 0xfc, - 0xc2, 0x3b, 0xc0, 0x7f, 0xac, 0x28, 0x72, 0xe0, 0xb6, 0x4c, 0x20, 0x63, 0xdb, 0x68, 0x6c, 0xad, 0xcf, 0x70, 0xad, - 0xc7, 0x5e, 0xe8, 0x64, 0x61, 0xbc, 0x7b, 0x63, 0x94, 0x61, 0x5e, 0xc4, 0x71, 0x9e, 0x45, 0x85, 0x3e, 0x2c, 0xaa, - 0x2a, 0x2e, 0xff, 0x05, 0x00, 0xa3, 0xf0, 0x70, 0xfa, 0xfd, 0x1b, 0xfc, 0x39, 0xfe, 0x17, 0xee, 0x6a, 0x38, 0x9f, - 0x63, 0xe2, 0xf5, 0xa6, 0xef, 0x70, 0xc7, 0x9a, 0xfd, 0x0a, 0xc6, 0xcc, 0xe5, 0x34, 0x19, 0x5c, 0xd3, 0xaf, 0x15, - 0xf0, 0xf1, 0x13, 0x27, 0xe9, 0x58, 0x9b, 0xe9, 0xd4, 0xde, 0x72, 0xf9, 0x00, 0x9f, 0x39, 0xc3, 0x59, 0xb9, 0xfa, - 0xf1, 0x97, 0x81, 0xb2, 0x08, 0x7f, 0x1c, 0x93, 0x03, 0x89, 0xab, 0x74, 0xd1, 0x02, 0x9e, 0xed, 0x33, 0x80, 0x86, - 0x70, 0x6a, 0x23, 0xf2, 0x07, 0x1b, 0xe3, 0xd1, 0x6d, 0x17, 0xe2, 0x1a, 0x75, 0xa2, 0x47, 0xd8, 0x2d, 0xea, 0xca, - 0xb6, 0xdb, 0x5a, 0x07, 0x2c, 0x0b, 0x36, 0xdf, 0xc0, 0x79, 0x62, 0x5a, 0x72, 0xf8, 0xa9, 0xef, 0x9b, 0x90, 0xa8, - 0x17, 0xdf, 0xef, 0xe0, 0x4d, 0x8a, 0x64, 0x65, 0x2a, 0xc8, 0x50, 0xfe, 0xb7, 0x39, 0xdc, 0xa3, 0xec, 0x91, 0x3e, - 0xc7, 0x42, 0x0f, 0xa6, 0x8f, 0xbc, 0xde, 0x98, 0x91, 0xa8, 0xd6, 0x5a, 0xc9, 0x83, 0xef, 0x41, 0xf0, 0x2f, 0xa7, - 0x37, 0x08, 0xc1, 0x06, 0x61, 0x05, 0xf1, 0xf0, 0x75, 0xc5, 0xb2, 0xc6, 0x73, 0x93, 0x33, 0x57, 0x6a, 0x42, 0x8f, - 0x6f, 0x55, 0xb2, 0x78, 0x6e, 0x6e, 0x4f, 0xf9, 0x48, 0x02, 0xa6, 0x8d, 0x02, 0x17, 0x6f, 0x32, 0xde, 0xcf, 0x42, - 0x23, 0x52, 0xe0, 0xcb, 0xb9, 0x11, 0x29, 0xbf, 0xba, 0xde, 0x38, 0xd6, 0x4f, 0x9a, 0x3e, 0x69, 0xf3, 0xb9, 0x2e, - 0x72, 0x0a, 0x6b, 0xb7, 0xae, 0xe1, 0x9d, 0x1f, 0x74, 0x25, 0x0c, 0xd5, 0x29, 0xe5, 0x41, 0xa1, 0x62, 0x64, 0x0b, - 0xa4, 0x21, 0x3f, 0x89, 0xf2, 0xfb, 0x61, 0x3a, 0x63, 0xf8, 0x9a, 0x6a, 0x93, 0x94, 0x95, 0xc4, 0xf9, 0x09, 0x4b, - 0x93, 0x89, 0x37, 0xa6, 0x65, 0xff, 0x77, 0x62, 0xd9, 0xbb, 0x28, 0x63, 0xe6, 0x4e, 0x1c, 0x59, 0xa8, 0x83, 0x52, - 0xde, 0xc3, 0x69, 0x5b, 0xdd, 0x19, 0x44, 0xdb, 0xa2, 0x87, 0xb7, 0x07, 0x1e, 0x8a, 0xd6, 0x24, 0x61, 0xdb, 0x7b, - 0xba, 0x44, 0xac, 0x50, 0x6d, 0x61, 0xf3, 0x3e, 0xf2, 0xac, 0x28, 0xd5, 0xee, 0x4a, 0x5d, 0x7a, 0x07, 0xf5, 0x29, - 0xae, 0xf6, 0x53, 0x93, 0x69, 0xc0, 0x05, 0x82, 0xb9, 0x0b, 0x72, 0x6b, 0x18, 0x70, 0x3d, 0x2f, 0x6e, 0x5b, 0xd4, - 0x66, 0xb5, 0xa1, 0x6e, 0x41, 0x64, 0x5e, 0x30, 0x60, 0x16, 0x6d, 0x26, 0x11, 0x64, 0xc3, 0x32, 0x18, 0x72, 0xa6, - 0x64, 0x81, 0xf3, 0xe2, 0x60, 0x7f, 0x74, 0xaf, 0xe0, 0x84, 0x84, 0xd1, 0x3a, 0x6a, 0x36, 0xf2, 0x45, 0x14, 0xe4, - 0xab, 0xb6, 0xb8, 0xe6, 0x54, 0xdc, 0xd3, 0xa4, 0x56, 0x81, 0x9d, 0xcb, 0x0a, 0xa6, 0xd0, 0xbe, 0x51, 0x58, 0xfa, - 0xca, 0x4a, 0xf2, 0xfc, 0x25, 0xc5, 0x1b, 0x53, 0x81, 0x93, 0xfc, 0x95, 0x86, 0x6d, 0xe7, 0xd6, 0x7d, 0xf7, 0x41, - 0x01, 0xde, 0xa8, 0x23, 0xf3, 0x29, 0xfd, 0x5f, 0xd7, 0x5b, 0x5d, 0x7d, 0x54, 0x9f, 0xdf, 0x4c, 0xf4, 0xb7, 0x4a, - 0x9a, 0xfe, 0xbe, 0x34, 0x01, 0xd9, 0x9f, 0x66, 0xb9, 0x62, 0x6a, 0xf9, 0x48, 0x5e, 0x9a, 0xa7, 0x06, 0x99, 0xd0, - 0x19, 0xe6, 0xf7, 0x8a, 0xfa, 0xd7, 0xee, 0xf3, 0x83, 0xe9, 0xdf, 0xf0, 0x4a, 0xb3, 0x84, 0xd2, 0xd7, 0x9a, 0xd6, - 0x53, 0x62, 0x43, 0x63, 0x80, 0x41, 0x96, 0xe9, 0xa9, 0x53, 0x6b, 0xf6, 0x8e, 0x68, 0x8e, 0x55, 0x77, 0x99, 0x9c, - 0x50, 0x62, 0xe8, 0xae, 0x12, 0x37, 0x1a, 0x61, 0x37, 0x0f, 0x06, 0xad, 0x53, 0xa2, 0x19, 0x25, 0xbb, 0xda, 0xed, - 0x85, 0x8c, 0x09, 0x3d, 0x93, 0x22, 0x5b, 0x96, 0xaa, 0xf7, 0x8a, 0x1e, 0xf2, 0x5d, 0xc9, 0x6f, 0xfe, 0xa9, 0x44, - 0xdc, 0x58, 0x9e, 0xdd, 0x01, 0x64, 0x10, 0x06, 0xb9, 0x43, 0x46, 0xbc, 0x84, 0x0a, 0x14, 0xc6, 0xce, 0x04, 0x5b, - 0x1f, 0xd1, 0x07, 0x58, 0x24, 0x72, 0x91, 0x34, 0x74, 0x8f, 0x2c, 0x11, 0xa8, 0x62, 0xdf, 0x13, 0x97, 0xcd, 0x3f, - 0xa2, 0x68, 0xe3, 0xf6, 0x3c, 0x20, 0x54, 0x26, 0x2d, 0x57, 0xbe, 0xa6, 0x95, 0x2b, 0x8c, 0xb4, 0x8c, 0x24, 0x1c, - 0x1c, 0x81, 0x6f, 0xd4, 0x10, 0x3e, 0x24, 0xa5, 0x97, 0x76, 0x72, 0xb7, 0x5a, 0x5c, 0x93, 0x36, 0x02, 0x88, 0x4d, - 0xc6, 0xf8, 0xf5, 0xd5, 0xae, 0x08, 0xe7, 0x3b, 0x6b, 0xea, 0x3f, 0x71, 0xc0, 0x31, 0xd2, 0x7d, 0x59, 0x0b, 0xbd, - 0x01, 0xab, 0x9a, 0xe1, 0xdb, 0x27, 0x30, 0x54, 0x3a, 0x50, 0x4c, 0x47, 0x0e, 0x15, 0xcd, 0x1b, 0xe0, 0xda, 0xdd, - 0x8a, 0x08, 0xdf, 0xce, 0x5f, 0xb3, 0x4a, 0x35, 0x21, 0x88, 0xb5, 0x26, 0xd1, 0xcc, 0x16, 0x61, 0xb7, 0x71, 0xcf, - 0xe0, 0xf6, 0x1c, 0x8a, 0x3e, 0xbc, 0xc4, 0x45, 0x1c, 0xd8, 0x0c, 0x5e, 0xda, 0x3c, 0x35, 0xa7, 0xf4, 0x5b, 0x5f, - 0xd1, 0xe0, 0xd1, 0x27, 0x86, 0x13, 0x9d, 0x3b, 0x49, 0xc1, 0x23, 0x06, 0x41, 0x98, 0xa4, 0x4f, 0x3d, 0xe1, 0xce, - 0x9b, 0xa9, 0x8b, 0xc4, 0x5d, 0x5c, 0xe0, 0xf6, 0xc3, 0x08, 0x1e, 0x22, 0xdb, 0x4b, 0x15, 0x2b, 0xfe, 0x7d, 0x6e, - 0xeb, 0x6c, 0xa7, 0xec, 0x9c, 0x78, 0x2f, 0x5a, 0xf0, 0x2a, 0xa6, 0xc1, 0x60, 0x03, 0x63, 0x06, 0x1f, 0xba, 0x84, - 0x24, 0xaf, 0x52, 0x2a, 0xd8, 0x08, 0x7a, 0x44, 0xbe, 0x18, 0xc9, 0x28, 0xc9, 0xe8, 0xdb, 0x5f, 0x0c, 0xfe, 0x78, - 0x35, 0x85, 0xad, 0x5b, 0x03, 0xd1, 0x64, 0xf9, 0xf6, 0x9a, 0xef, 0x76, 0xec, 0xe8, 0xca, 0x67, 0x03, 0xb2, 0x96, - 0xd1, 0x9b, 0xb6, 0xe8, 0x47, 0x72, 0x43, 0x2a, 0x88, 0x7d, 0x95, 0x0d, 0x78, 0x6d, 0xdd, 0x70, 0x92, 0xc3, 0x1a, - 0xbc, 0xc7, 0xf4, 0x64, 0xb5, 0xfa, 0xce, 0x6f, 0x6b, 0x19, 0x9e, 0xf1, 0xb7, 0xbd, 0x50, 0x8d, 0x5c, 0x7c, 0x37, - 0x9a, 0xd1, 0xeb, 0x3a, 0x7a, 0x46, 0x99, 0xf4, 0x25, 0xda, 0xd5, 0xa5, 0xfa, 0x9e, 0x6b, 0xe1, 0x00, 0xdc, 0xbb, - 0x19, 0x7c, 0xea, 0xcb, 0x78, 0x6b, 0x13, 0xd6, 0xd3, 0x98, 0x84, 0xd3, 0x6e, 0xc6, 0x83, 0xbf, 0x67, 0x5c, 0x93, - 0xa3, 0xa5, 0xe7, 0x36, 0x9e, 0xd3, 0x36, 0xbe, 0x97, 0x7c, 0x9f, 0x4d, 0xf3, 0xd1, 0x7b, 0x2f, 0x0e, 0x6f, 0x1d, - 0xd8, 0xcb, 0x0c, 0xb7, 0x76, 0xd4, 0xe2, 0xbc, 0xd5, 0xec, 0xb5, 0xd8, 0xb9, 0xc3, 0x9b, 0x10, 0x51, 0x66, 0x7b, - 0x87, 0x7f, 0x8b, 0x35, 0xbf, 0xc1, 0xf7, 0xdf, 0xab, 0xea, 0xd3, 0xa5, 0x99, 0x36, 0x0c, 0xc3, 0x5a, 0xff, 0xbc, - 0xad, 0x65, 0x98, 0xb5, 0xf1, 0x13, 0x3d, 0xcd, 0x34, 0x7e, 0xa3, 0xde, 0xb8, 0xb7, 0x88, 0xbf, 0x5b, 0xf7, 0xff, - 0xe5, 0x93, 0x87, 0x04, 0xc2, 0x8f, 0xec, 0xc7, 0xa3, 0x6d, 0x03, 0xba, 0x5c, 0x7e, 0xe3, 0x5d, 0x24, 0x26, 0x7f, - 0xb4, 0x5e, 0x8e, 0x45, 0xc6, 0xa7, 0x1a, 0x08, 0x77, 0xeb, 0x45, 0x52, 0xd4, 0xf8, 0x8e, 0xbc, 0x19, 0x8f, 0xc9, - 0xea, 0x1d, 0x88, 0x40, 0x41, 0xeb, 0x1b, 0x27, 0xb1, 0xc4, 0x8f, 0xd0, 0x5f, 0x7e, 0x61, 0x75, 0xd2, 0x89, 0xfa, - 0x45, 0x3b, 0xe1, 0xff, 0x9f, 0x7e, 0xbf, 0x0a, 0x67, 0xd9, 0x80, 0xde, 0xfa, 0x7f, 0x41, 0x64, 0x43, 0xed, 0x95, - 0x20, 0x3d, 0x84, 0xf0, 0xc8, 0x9f, 0xdd, 0x6a, 0xca, 0x0a, 0x2b, 0xc7, 0xb9, 0xa8, 0x8c, 0x27, 0x74, 0x4e, 0x2e, - 0x34, 0x4e, 0x92, 0x35, 0x65, 0xf0, 0x9e, 0x49, 0xda, 0x75, 0x95, 0xa1, 0x77, 0x3b, 0xc2, 0x16, 0xa1, 0x93, 0xb8, - 0xcd, 0x92, 0x8a, 0x45, 0xb4, 0x6c, 0x57, 0x6d, 0xae, 0x7e, 0x1e, 0xc1, 0x19, 0x38, 0xce, 0xb2, 0x80, 0xbd, 0x07, - 0x4b, 0x59, 0x77, 0x6e, 0xec, 0x30, 0xdd, 0x6f, 0x1d, 0xc3, 0x11, 0x41, 0x63, 0x2f, 0xe7, 0x6b, 0xfb, 0xa3, 0x12, - 0x4d, 0x22, 0xde, 0x14, 0x18, 0xd0, 0x8b, 0x5f, 0x27, 0x6b, 0x1e, 0xc4, 0xd1, 0xcb, 0xd7, 0x8a, 0xb0, 0xac, 0xd5, - 0x94, 0x3a, 0x8c, 0xcf, 0xbd, 0x54, 0x41, 0xa8, 0x0b, 0x21, 0x93, 0xbd, 0xd0, 0x75, 0x02, 0x32, 0x31, 0xa2, 0xcf, - 0x58, 0x4b, 0x18, 0x93, 0x03, 0xad, 0x82, 0xd2, 0xf1, 0xa1, 0xa6, 0x47, 0x82, 0xd0, 0x73, 0x65, 0x6c, 0x07, 0x39, - 0x4e, 0x4c, 0x53, 0x99, 0x10, 0x4d, 0x1c, 0x02, 0x57, 0x79, 0x92, 0xbc, 0x46, 0x32, 0x5e, 0x4e, 0x02, 0x68, 0xd7, - 0xdd, 0x26, 0x6a, 0x73, 0xd0, 0xbb, 0xff, 0xa4, 0x11, 0x74, 0x51, 0x64, 0xad, 0x67, 0x03, 0x45, 0xf3, 0x14, 0xf3, - 0xc8, 0xb0, 0x49, 0x81, 0x46, 0x11, 0x8a, 0xd0, 0xbf, 0x49, 0xec, 0xa1, 0x91, 0x55, 0x46, 0x72, 0xc1, 0x62, 0xb2, - 0xc2, 0x9c, 0x38, 0x2d, 0x25, 0x9d, 0x72, 0xe2, 0x36, 0xda, 0x01, 0x7e, 0x7c, 0xf5, 0x6d, 0x63, 0xdc, 0xe3, 0x2d, - 0xc6, 0xb6, 0x17, 0x73, 0x16, 0x6f, 0x7f, 0xdc, 0x1b, 0xf8, 0xee, 0xf0, 0x6c, 0x20, 0xb1, 0x85, 0xb1, 0x36, 0x06, - 0x24, 0x99, 0x30, 0x29, 0xb5, 0x7f, 0x16, 0xc6, 0x03, 0x46, 0xb2, 0x50, 0x7c, 0x69, 0x54, 0x94, 0xfb, 0x79, 0x35, - 0xd1, 0x4e, 0xe8, 0x01, 0xe1, 0x28, 0x69, 0xa4, 0x5d, 0xa2, 0x05, 0x91, 0xd6, 0x67, 0xe5, 0x6b, 0x1b, 0x5e, 0x5b, - 0x97, 0x29, 0x83, 0x43, 0x4a, 0xa6, 0x45, 0x62, 0x45, 0x06, 0x1e, 0x10, 0xb7, 0x11, 0xd2, 0x8b, 0xe4, 0x05, 0x94, - 0x00, 0xbc, 0x8a, 0x68, 0x6f, 0x54, 0xc6, 0x22, 0x79, 0x93, 0xb5, 0x4a, 0x61, 0x09, 0x40, 0xe0, 0x5f, 0xf6, 0x97, - 0x05, 0x4b, 0x44, 0x8d, 0x1a, 0xad, 0xe9, 0x8c, 0x40, 0xed, 0xf0, 0x1d, 0x10, 0x31, 0xbc, 0xc6, 0x6e, 0x14, 0xa6, - 0x0d, 0xcd, 0xe2, 0x18, 0xe3, 0xaa, 0xbd, 0xf9, 0xcc, 0xe5, 0x76, 0x3c, 0x36, 0xdf, 0x5a, 0x0f, 0xec, 0x4d, 0xba, - 0x67, 0xb1, 0xf7, 0x97, 0x0c, 0x4f, 0x2b, 0x9c, 0xd7, 0x13, 0xb9, 0xc9, 0xe3, 0xa3, 0xaf, 0x7b, 0xd7, 0x22, 0xd4, - 0xdc, 0x5c, 0x9b, 0x87, 0x9b, 0xf7, 0xae, 0x2a, 0x7c, 0x37, 0xff, 0x32, 0x8e, 0xa7, 0x35, 0x59, 0xf9, 0x1b, 0x45, - 0x29, 0x56, 0xd0, 0x9b, 0xd0, 0x31, 0x43, 0x20, 0x4f, 0x95, 0x1e, 0xec, 0x4e, 0xa2, 0xdc, 0x7e, 0x53, 0x31, 0xdb, - 0x76, 0x2e, 0x14, 0x9d, 0x29, 0x34, 0x39, 0xe1, 0x19, 0xcd, 0xb7, 0x23, 0x14, 0x91, 0xb4, 0x5c, 0x67, 0x6a, 0x5a, - 0xba, 0x9f, 0xf3, 0xf5, 0xc7, 0x65, 0x01, 0x1d, 0x52, 0x7c, 0xdc, 0xd7, 0x8c, 0x82, 0xa0, 0xe1, 0x13, 0xa9, 0x4c, - 0xc8, 0x63, 0x9d, 0x58, 0x56, 0xbb, 0x2f, 0xd3, 0x34, 0xdd, 0x5f, 0xbf, 0xa0, 0xc7, 0xde, 0x0e, 0x45, 0x62, 0x63, - 0xce, 0x34, 0x6b, 0x81, 0x1b, 0x79, 0x70, 0x7a, 0x6a, 0x3d, 0xf3, 0xb2, 0xb3, 0x7a, 0x6b, 0xe7, 0x81, 0x0e, 0x98, - 0x44, 0xda, 0x86, 0x39, 0x99, 0x17, 0xfd, 0xf9, 0x70, 0x51, 0xf7, 0xea, 0x6b, 0x35, 0xb6, 0x63, 0x8e, 0x49, 0x4f, - 0x3c, 0xfc, 0x44, 0x08, 0xbe, 0xa5, 0x20, 0x1d, 0xe0, 0xf2, 0xf5, 0xe9, 0x08, 0x32, 0xad, 0x02, 0x12, 0x93, 0xb6, - 0x7e, 0x7d, 0x17, 0x20, 0xe8, 0xb4, 0x02, 0x0e, 0x18, 0x8a, 0x9f, 0x81, 0x7a, 0x8d, 0x6f, 0x35, 0x48, 0x52, 0x62, - 0x7d, 0x32, 0xc3, 0xa7, 0x4f, 0xa2, 0xc0, 0xc3, 0x57, 0x47, 0xb6, 0x69, 0x43, 0x19, 0x67, 0x10, 0x8e, 0x69, 0x3d, - 0x58, 0x32, 0x33, 0x9e, 0xf7, 0xb8, 0xc7, 0xf1, 0x77, 0x4a, 0xe0, 0x5d, 0x22, 0x6f, 0x52, 0xb0, 0x25, 0xe3, 0x04, - 0x06, 0x97, 0xbd, 0x15, 0x1f, 0x41, 0x5c, 0xbf, 0x87, 0x35, 0xa6, 0x93, 0x3c, 0xcf, 0xc5, 0xe1, 0x1f, 0xc6, 0x6f, - 0x3d, 0xf2, 0xe0, 0xdb, 0x07, 0x83, 0x2e, 0x4d, 0xeb, 0x05, 0xc3, 0x16, 0x7b, 0xb1, 0x01, 0x6a, 0x05, 0xcc, 0xac, - 0x64, 0xdc, 0x4a, 0x8b, 0x14, 0x38, 0xea, 0xdb, 0x07, 0xbf, 0x98, 0xdd, 0xb5, 0x71, 0x40, 0xfa, 0x44, 0x43, 0xd8, - 0xf8, 0x54, 0x05, 0x2e, 0x51, 0xc7, 0xef, 0xd1, 0xbf, 0xbc, 0x5d, 0xae, 0x61, 0x9d, 0x8a, 0x9f, 0xda, 0x78, 0x96, - 0xd1, 0xca, 0xf2, 0xfc, 0x3e, 0x7a, 0xf1, 0xa1, 0xa5, 0xa5, 0x1f, 0xc6, 0x18, 0xac, 0xe4, 0x17, 0x0a, 0xf5, 0x84, - 0x1d, 0xff, 0x32, 0x45, 0xfe, 0xbe, 0x36, 0xf9, 0xf4, 0xec, 0xef, 0xad, 0xff, 0x5f, 0xc2, 0x95, 0xa1, 0x6a, 0xce, - 0x7f, 0x17, 0xff, 0xbd, 0x5c, 0x56, 0x43, 0x75, 0x7d, 0x7d, 0xf6, 0xbd, 0x6a, 0xbb, 0x31, 0x1f, 0xed, 0xb2, 0x4c, - 0x0a, 0x18, 0x95, 0x99, 0x89, 0x82, 0x32, 0xcf, 0xd5, 0xf9, 0x22, 0xf6, 0xeb, 0x8e, 0xb8, 0xf0, 0xcb, 0xf1, 0x23, - 0xfd, 0xe7, 0xd7, 0xe5, 0xb8, 0x5a, 0xf7, 0x90, 0xca, 0x7d, 0xb1, 0xa2, 0xda, 0x56, 0x36, 0x4b, 0xfe, 0x7e, 0xe8, - 0xdc, 0x11, 0x81, 0xf5, 0xe7, 0xc1, 0x77, 0x5c, 0xc6, 0x9f, 0x0c, 0x6f, 0x12, 0x45, 0x6b, 0x83, 0xc5, 0x67, 0xfa, - 0x4c, 0xab, 0x87, 0x3b, 0x5e, 0x55, 0xd9, 0xa6, 0x9e, 0x51, 0x9b, 0x6e, 0x02, 0x62, 0x52, 0x41, 0x85, 0xb2, 0xce, - 0xfd, 0xf2, 0xb7, 0x8b, 0x36, 0x24, 0x14, 0xfd, 0xe4, 0xbb, 0xc0, 0x7d, 0xb0, 0x34, 0x27, 0x80, 0xc4, 0x86, 0xd9, - 0xf1, 0x4b, 0x81, 0x33, 0xa0, 0xe1, 0xa1, 0xd6, 0xdd, 0xd4, 0x56, 0x7d, 0x0e, 0x53, 0xfe, 0x43, 0x4c, 0xf7, 0x50, - 0x07, 0x53, 0x82, 0x10, 0xe7, 0xe1, 0xf2, 0xff, 0xf4, 0x13, 0x91, 0x34, 0x1d, 0x4c, 0x1d, 0x03, 0xe7, 0xae, 0xfc, - 0x13, 0xbb, 0x17, 0xaf, 0xf4, 0x92, 0xc5, 0xeb, 0x5a, 0x31, 0xf0, 0x2c, 0x08, 0xaa, 0x2b, 0x72, 0x6c, 0xf2, 0x9c, - 0x3e, 0x6b, 0xec, 0x2e, 0xff, 0xa7, 0x59, 0x16, 0x39, 0x2c, 0x38, 0x46, 0x7c, 0xe7, 0x03, 0x84, 0x25, 0x59, 0x0d, - 0x1b, 0xb3, 0x87, 0xe3, 0xf8, 0xde, 0x1b, 0x68, 0x38, 0x0e, 0xef, 0xef, 0x20, 0x01, 0xdf, 0xf8, 0xa9, 0xba, 0x1a, - 0x95, 0x47, 0xe6, 0xb4, 0x8f, 0x63, 0xdc, 0x18, 0x3a, 0xc7, 0x48, 0x04, 0xa7, 0x9c, 0x02, 0xc4, 0x37, 0x49, 0x2b, - 0x02, 0x16, 0x13, 0xbc, 0x0d, 0xc9, 0x41, 0x3b, 0x2e, 0xa6, 0xc9, 0x94, 0x43, 0xcb, 0xa9, 0xa3, 0x0e, 0x90, 0xe3, - 0x3c, 0x3a, 0xb0, 0xac, 0xdb, 0xeb, 0xc8, 0xf8, 0x2a, 0x93, 0x76, 0xd9, 0x42, 0xf6, 0xbb, 0x08, 0x33, 0x89, 0x18, - 0xa9, 0xe0, 0x61, 0xce, 0x6a, 0x08, 0xfa, 0x45, 0x8b, 0x98, 0xda, 0x88, 0x86, 0x7b, 0xdb, 0x19, 0xb1, 0x8b, 0x40, - 0x83, 0x2b, 0x07, 0xf2, 0x8a, 0x57, 0x81, 0x87, 0x89, 0x4c, 0x58, 0x40, 0x2c, 0xe0, 0xc2, 0xbc, 0xef, 0x2b, 0x8e, - 0x87, 0xfd, 0x22, 0x0a, 0x2e, 0xb1, 0xf7, 0xfd, 0x70, 0xa1, 0x60, 0xe7, 0x55, 0xaf, 0xef, 0x8b, 0xdb, 0xe3, 0xdf, - 0x5e, 0x32, 0x22, 0x05, 0x96, 0x41, 0xde, 0xe0, 0xf9, 0x41, 0x18, 0xf8, 0xa1, 0x7d, 0x04, 0x47, 0x29, 0xdb, 0x11, - 0x9c, 0x28, 0xc8, 0x7a, 0x52, 0xc3, 0xb4, 0x65, 0xc1, 0xd5, 0xe9, 0xb4, 0xcd, 0x3c, 0x0a, 0xd2, 0x28, 0xd5, 0xfb, - 0xe7, 0x3e, 0x28, 0x13, 0xa2, 0x55, 0xa6, 0xc0, 0xb6, 0x00, 0xb4, 0x6c, 0x45, 0x78, 0x8d, 0xd9, 0x84, 0x05, 0x3a, - 0xe9, 0xb4, 0xcd, 0x3c, 0x5a, 0x82, 0x6f, 0x40, 0x27, 0x17, 0x1b, 0x2e, 0xb6, 0x5c, 0x3a, 0x69, 0xdf, 0x8e, 0x07, - 0x08, 0x62, 0x02, 0x1e, 0xca, 0xc8, 0x30, 0x9f, 0xa4, 0x7c, 0xe9, 0xd9, 0x6f, 0xd3, 0x45, 0x7b, 0x6d, 0xf2, 0xf1, - 0xa2, 0x0e, 0x98, 0xd8, 0x40, 0x9a, 0x56, 0x27, 0x11, 0xbe, 0x3f, 0xa4, 0x80, 0x1d, 0x94, 0xe6, 0xf8, 0xd8, 0x02, - 0x51, 0x49, 0x45, 0xc8, 0xb8, 0x5e, 0x1e, 0x7a, 0xb6, 0xdf, 0x4c, 0x02, 0x35, 0x3b, 0x05, 0x1f, 0x70, 0xd1, 0x68, - 0x52, 0x7c, 0x42, 0x98, 0x12, 0x46, 0x88, 0xac, 0x04, 0x24, 0xc0, 0x4d, 0x66, 0x03, 0x94, 0x3f, 0x29, 0x17, 0xee, - 0x2b, 0xf1, 0xc7, 0x0e, 0xe1, 0x80, 0x9f, 0x39, 0x02, 0x47, 0x19, 0x35, 0xfa, 0xa7, 0xb3, 0x6d, 0x98, 0x9c, 0x22, - 0x56, 0xf4, 0x06, 0x5c, 0x41, 0x58, 0x50, 0xf2, 0xae, 0x83, 0xed, 0x75, 0x3f, 0x14, 0xcb, 0xfe, 0x88, 0x26, 0x3c, - 0xe2, 0x81, 0x7c, 0xd8, 0x55, 0x0b, 0x4d, 0x0c, 0x7c, 0x00, 0xb9, 0xa2, 0xca, 0x68, 0x22, 0x73, 0x7a, 0x8f, 0x2a, - 0x47, 0x2b, 0xf4, 0x7d, 0x1d, 0x64, 0x4a, 0xf5, 0x78, 0x2d, 0x53, 0xdd, 0x08, 0x6b, 0x68, 0x25, 0x50, 0xb6, 0x31, - 0x5b, 0x96, 0x6a, 0xd9, 0x5e, 0xbf, 0xe9, 0x22, 0x7f, 0x11, 0x47, 0xac, 0x61, 0x4b, 0xc0, 0xb9, 0xfa, 0xc2, 0xd8, - 0x76, 0xb2, 0xeb, 0xec, 0x88, 0x92, 0x9e, 0x36, 0xdc, 0x95, 0x31, 0x72, 0xf3, 0x9a, 0xed, 0xa9, 0xa7, 0x18, 0x6d, - 0x35, 0x74, 0x5e, 0xf9, 0x26, 0x35, 0x27, 0x05, 0x57, 0xfc, 0x7c, 0x7f, 0x0d, 0xaf, 0x9d, 0x57, 0xf1, 0xe8, 0xc2, - 0x46, 0xc4, 0x33, 0x6b, 0xfe, 0xb5, 0x4a, 0x5e, 0x6d, 0xd6, 0xb0, 0x54, 0xfe, 0x75, 0x0d, 0xb6, 0x90, 0x7d, 0x47, - 0x16, 0xe5, 0xdf, 0x20, 0x8e, 0xc2, 0x47, 0x6d, 0xeb, 0x2a, 0xdc, 0xc0, 0xda, 0xf8, 0x68, 0x78, 0x15, 0xbd, 0x38, - 0x3c, 0xc0, 0x39, 0x08, 0x90, 0x07, 0x4e, 0x42, 0x18, 0xb0, 0xcf, 0x19, 0xac, 0xf9, 0x2a, 0xd3, 0x98, 0xf3, 0xa6, - 0x87, 0x3c, 0xd7, 0xfe, 0x82, 0xd7, 0x80, 0x0a, 0x68, 0x0f, 0x3b, 0x7c, 0x5a, 0x83, 0x09, 0x4d, 0x5d, 0x84, 0x7c, - 0xfa, 0xe0, 0x77, 0xf9, 0x69, 0x41, 0x61, 0xb2, 0x53, 0x20, 0xc3, 0xe9, 0xaa, 0x9b, 0x19, 0x5a, 0x69, 0x82, 0xf9, - 0xf7, 0xbb, 0x9b, 0x51, 0x43, 0xe4, 0x5e, 0x84, 0x4c, 0x37, 0x90, 0xd1, 0x8a, 0x69, 0xd8, 0x34, 0xd3, 0xb4, 0x1a, - 0x0c, 0xd5, 0x47, 0x4d, 0x5b, 0xfc, 0xb5, 0x57, 0x6f, 0x50, 0x0e, 0x9d, 0xda, 0xc0, 0xf0, 0x9e, 0xfd, 0xb5, 0x7f, - 0x28, 0xc8, 0x8b, 0xa2, 0xd0, 0xb4, 0xd3, 0x21, 0x32, 0xdc, 0xc6, 0x8e, 0xb5, 0x1e, 0xff, 0x33, 0xc3, 0x38, 0xf9, - 0xcc, 0x4c, 0x10, 0xd8, 0x10, 0x0b, 0x45, 0x0b, 0xfa, 0x69, 0xb3, 0x0c, 0x77, 0xca, 0x46, 0xaf, 0x05, 0xbf, 0x54, - 0xa5, 0xc6, 0x01, 0x71, 0x0e, 0x2f, 0x2f, 0x4c, 0xf1, 0xc4, 0x43, 0x7f, 0x17, 0x98, 0xf0, 0x69, 0x9e, 0x5a, 0x51, - 0x57, 0x27, 0xaf, 0xd2, 0x8f, 0xed, 0x67, 0x29, 0x0f, 0x49, 0xba, 0x22, 0x0b, 0x0d, 0xd9, 0xdc, 0xe0, 0xd5, 0xda, - 0x17, 0x9b, 0x59, 0xc1, 0xe7, 0x2b, 0x24, 0x88, 0x06, 0x87, 0x2d, 0x35, 0xe5, 0x0b, 0xcf, 0x1b, 0x47, 0x2a, 0x2b, - 0x17, 0xbb, 0xe0, 0x10, 0x0d, 0x96, 0x4b, 0x8b, 0x59, 0x2b, 0xc7, 0xef, 0xd1, 0xe8, 0x4f, 0xaa, 0xc5, 0x39, 0x2a, - 0xe5, 0xfc, 0x03, 0xb3, 0x3f, 0xf5, 0xfd, 0x01, 0xa3, 0x7b, 0xbf, 0x27, 0xf9, 0xac, 0x2f, 0xfa, 0x6a, 0x13, 0xca, - 0x3b, 0x79, 0x73, 0xc0, 0xe7, 0x2e, 0x2c, 0xe3, 0x18, 0x29, 0x20, 0xf8, 0x9b, 0x9d, 0x53, 0x43, 0x8f, 0x30, 0x25, - 0xad, 0xe9, 0x45, 0x7e, 0x5b, 0x11, 0x2d, 0xd1, 0xc0, 0x5b, 0x1c, 0x17, 0xe9, 0x43, 0x5b, 0xde, 0x65, 0x4b, 0x19, - 0x0f, 0xdd, 0xca, 0x8c, 0x24, 0x1a, 0x55, 0x1a, 0x3e, 0x88, 0x9e, 0x3b, 0x5b, 0x0a, 0xbd, 0xdd, 0x19, 0xcd, 0x9e, - 0x50, 0x65, 0x42, 0x53, 0x23, 0x6e, 0x55, 0xfb, 0x1a, 0xeb, 0x9a, 0x9a, 0x6e, 0xe8, 0x85, 0x9a, 0xa1, 0x10, 0x52, - 0x8d, 0xbe, 0x50, 0xeb, 0x47, 0x11, 0x92, 0x34, 0x1e, 0xbf, 0xa6, 0x71, 0x9b, 0xf3, 0xf5, 0x5a, 0x28, 0x57, 0x67, - 0x15, 0x05, 0x9a, 0x9f, 0xa7, 0x89, 0xc7, 0xd8, 0xcf, 0x8d, 0xf4, 0xd5, 0xe7, 0x0b, 0xc0, 0x40, 0x90, 0xdc, 0xea, - 0xae, 0x21, 0x0d, 0x2d, 0xfb, 0xe9, 0x71, 0x9e, 0x99, 0x22, 0x40, 0xb7, 0x2a, 0x13, 0x4f, 0x5d, 0xcc, 0xbb, 0x3d, - 0x26, 0xa8, 0xd8, 0xf9, 0x8a, 0x32, 0x00, 0x4e, 0x52, 0x07, 0xd1, 0xa8, 0xdd, 0xdb, 0x9d, 0xa6, 0xcb, 0xb9, 0x78, - 0x06, 0x2e, 0x84, 0xe5, 0xb4, 0xbc, 0x7a, 0x16, 0xed, 0x7a, 0x86, 0x34, 0xc9, 0xf6, 0xed, 0xaa, 0x2e, 0x5d, 0x70, - 0x47, 0x26, 0x8d, 0x84, 0x96, 0x6a, 0x28, 0xe4, 0x2a, 0x59, 0x3b, 0xea, 0xce, 0x86, 0x39, 0xe5, 0x26, 0x0a, 0xb7, - 0x32, 0x97, 0x25, 0x65, 0xac, 0xc9, 0x11, 0x96, 0x71, 0x79, 0x94, 0x58, 0x16, 0xe0, 0x7b, 0x60, 0x10, 0x95, 0xaa, - 0x3c, 0x13, 0x45, 0x48, 0x86, 0x06, 0x0b, 0x4c, 0x44, 0xf7, 0xfd, 0x16, 0x26, 0x78, 0xf0, 0xb5, 0x8f, 0x0a, 0x92, - 0xc2, 0x4e, 0x40, 0x00, 0x0d, 0x16, 0x5a, 0x40, 0x35, 0x4b, 0x6b, 0x55, 0xf7, 0x10, 0x3a, 0xaf, 0xc4, 0x57, 0x94, - 0x24, 0x83, 0xfe, 0xc3, 0x6f, 0x27, 0x84, 0x41, 0xeb, 0x10, 0x4a, 0x56, 0x1c, 0x70, 0xc3, 0xe2, 0x6a, 0x1a, 0xe9, - 0xb2, 0x65, 0xb1, 0xdc, 0x62, 0xcf, 0xe7, 0x36, 0xa5, 0x15, 0xac, 0xbc, 0x84, 0x92, 0x76, 0x2c, 0x2f, 0x7b, 0x5d, - 0x14, 0x7e, 0xf6, 0x9a, 0x1f, 0x31, 0xb9, 0x30, 0x0e, 0x49, 0xb9, 0x20, 0x21, 0x95, 0x47, 0x00, 0x32, 0x1f, 0x07, - 0xaa, 0x37, 0x05, 0x0f, 0x5b, 0x65, 0x73, 0xd4, 0x0c, 0xc1, 0xc1, 0xbd, 0xf3, 0xa9, 0x43, 0x0a, 0xf3, 0x18, 0x96, - 0x00, 0x4e, 0xc2, 0x91, 0xd0, 0x66, 0x6e, 0x72, 0xa6, 0x4e, 0x4f, 0xb2, 0xeb, 0xa0, 0xbb, 0xb5, 0xd5, 0x09, 0xc5, - 0x5e, 0xd6, 0x09, 0x11, 0x25, 0x55, 0x8f, 0x41, 0xb9, 0x19, 0x51, 0x5c, 0xfb, 0x21, 0x0e, 0x65, 0x18, 0xb2, 0x9b, - 0x0d, 0x30, 0x12, 0x2b, 0x42, 0x72, 0x1a, 0x24, 0xc9, 0x33, 0xe9, 0xb2, 0x36, 0x2d, 0xea, 0x3a, 0xbf, 0x45, 0x08, - 0x8f, 0x48, 0xc6, 0xf9, 0x59, 0x1e, 0xca, 0x8e, 0x2b, 0x1b, 0x54, 0x59, 0x9e, 0x9e, 0x7c, 0xd7, 0xbd, 0xa6, 0x4c, - 0x0d, 0xef, 0x01, 0x15, 0x99, 0x1c, 0xba, 0xcd, 0xf5, 0x31, 0x37, 0xc1, 0x6f, 0x5c, 0x1e, 0xa8, 0x8b, 0x87, 0x0d, - 0x49, 0xe8, 0xe7, 0x5b, 0xbc, 0x4e, 0x54, 0x1a, 0xbd, 0x43, 0x2c, 0xbd, 0xe6, 0xe2, 0x5c, 0x0b, 0x94, 0x58, 0xf0, - 0x95, 0x4a, 0x32, 0xb4, 0x91, 0x07, 0x7e, 0x10, 0x67, 0x42, 0x17, 0xb9, 0x2c, 0x5d, 0x23, 0x3f, 0xa7, 0x77, 0xcb, - 0x99, 0x78, 0x92, 0x5f, 0xfb, 0x9c, 0x95, 0x5e, 0xa7, 0x3f, 0x22, 0x71, 0x16, 0x9f, 0xb8, 0x44, 0x37, 0xd3, 0x3c, - 0x8c, 0x93, 0xba, 0x6a, 0xaf, 0x00, 0xb4, 0xba, 0xf0, 0x96, 0xa3, 0xf6, 0x48, 0xe0, 0xb9, 0xed, 0x2e, 0x71, 0xa5, - 0xbc, 0xe0, 0x0e, 0x8a, 0x3d, 0x4c, 0x30, 0x10, 0x1a, 0x65, 0x2c, 0x1c, 0x00, 0x7e, 0x0e, 0xf1, 0x6e, 0xcc, 0x5f, - 0x0d, 0xc6, 0xaa, 0x5a, 0xe0, 0xdc, 0x29, 0x33, 0xc8, 0x5e, 0x86, 0x06, 0x14, 0x48, 0x27, 0x64, 0x41, 0x69, 0xa3, - 0xc6, 0x0e, 0xa8, 0x08, 0x2b, 0x54, 0xdd, 0x01, 0xc7, 0x26, 0xcd, 0xda, 0xa7, 0x26, 0x62, 0x44, 0x83, 0x6e, 0x72, - 0xfe, 0xba, 0x83, 0x84, 0xf2, 0x0d, 0xa4, 0x60, 0x22, 0xfd, 0x12, 0xfd, 0x07, 0x30, 0xe9, 0x9d, 0x9c, 0xa0, 0xdd, - 0x24, 0xc6, 0xfd, 0x52, 0x4e, 0xa0, 0xb4, 0x4c, 0xd9, 0x3f, 0x0c, 0x8e, 0x6f, 0x80, 0x31, 0x3d, 0x63, 0xb9, 0xb6, - 0xd5, 0xfc, 0x45, 0x65, 0x28, 0x30, 0x5e, 0x22, 0x52, 0x61, 0x00, 0xf8, 0xbd, 0x19, 0x34, 0x1e, 0x83, 0xb7, 0x9f, - 0x70, 0x9c, 0x6a, 0x4d, 0x28, 0xad, 0x01, 0xf9, 0x16, 0xff, 0x8b, 0x71, 0xde, 0x29, 0x80, 0x53, 0x2b, 0xf2, 0xde, - 0xd9, 0xdd, 0xad, 0x43, 0xc0, 0xd0, 0xd7, 0x61, 0xce, 0xfc, 0x49, 0x8c, 0xb2, 0x81, 0xdc, 0xb6, 0x3b, 0xdd, 0x57, - 0x25, 0x75, 0x26, 0x19, 0xae, 0x48, 0x0c, 0x52, 0x69, 0xe4, 0x47, 0x5d, 0x59, 0x5c, 0x66, 0xd1, 0x15, 0x5c, 0x00, - 0xba, 0xe3, 0x19, 0x36, 0x6f, 0x6c, 0xd6, 0x17, 0x7e, 0x06, 0x69, 0xae, 0xeb, 0x00, 0xc0, 0x0b, 0x4f, 0x35, 0x36, - 0xdc, 0x31, 0x57, 0xd9, 0x0e, 0x0c, 0xef, 0x26, 0x9a, 0x83, 0xf3, 0x7c, 0x54, 0x21, 0x9f, 0xe0, 0x45, 0xc5, 0xe7, - 0x45, 0x40, 0x3c, 0x8e, 0x93, 0xca, 0x60, 0x88, 0x14, 0xfc, 0x44, 0x84, 0x1d, 0x8f, 0x17, 0xce, 0xa3, 0xbb, 0x2a, - 0xb7, 0x3a, 0x40, 0x35, 0x24, 0x60, 0x95, 0xb1, 0x0d, 0x1b, 0x3f, 0x09, 0x12, 0x97, 0xed, 0xac, 0xa0, 0x67, 0x1d, - 0x0e, 0x6a, 0xe1, 0x63, 0xb7, 0xf4, 0x43, 0x52, 0x28, 0xc4, 0xb9, 0x08, 0xe7, 0x29, 0x24, 0x4f, 0x07, 0xc8, 0x8c, - 0xbc, 0x98, 0x9c, 0xa5, 0xee, 0x6c, 0xd7, 0x6d, 0x4a, 0x25, 0x5d, 0xe2, 0xad, 0xb5, 0x9e, 0x8c, 0x57, 0x9a, 0x8e, - 0xa9, 0x08, 0x24, 0x4d, 0xa4, 0x82, 0x2a, 0xa5, 0xc1, 0xce, 0xd3, 0x01, 0x50, 0x30, 0xb7, 0xfc, 0xad, 0x99, 0x9e, - 0x96, 0x09, 0xdd, 0xe6, 0x68, 0xb0, 0x4d, 0x1c, 0xa6, 0x1f, 0x0c, 0x3a, 0x85, 0xb8, 0x51, 0xbb, 0xc0, 0xa3, 0x4c, - 0x85, 0xd8, 0xe3, 0x3f, 0xcc, 0xf7, 0x2a, 0xe6, 0x6c, 0xf2, 0xa2, 0x15, 0x2f, 0x52, 0xcb, 0xe4, 0x29, 0xd8, 0xab, - 0x7f, 0xa7, 0x3f, 0x12, 0x8d, 0x06, 0x14, 0x80, 0x8e, 0x35, 0x85, 0x84, 0xb8, 0xd0, 0xa4, 0x3b, 0x79, 0x5b, 0x7c, - 0xf3, 0xf7, 0x9f, 0x3e, 0x16, 0xe2, 0x7b, 0xad, 0x8f, 0x7c, 0x9e, 0x34, 0x61, 0xbb, 0x53, 0x2f, 0x75, 0xfd, 0x02, - 0x2c, 0x80, 0x9d, 0x6d, 0x3c, 0x13, 0xc3, 0xeb, 0x06, 0xfa, 0xa2, 0x0b, 0xf2, 0xc2, 0xe1, 0x3d, 0xcb, 0xf1, 0x3d, - 0x5e, 0x91, 0x05, 0x7a, 0x3b, 0x77, 0x66, 0x11, 0x90, 0x19, 0x40, 0x05, 0xe4, 0x15, 0x34, 0x39, 0x5d, 0x28, 0xf8, - 0x95, 0x41, 0xd1, 0xec, 0x84, 0x31, 0x40, 0x39, 0x1b, 0x38, 0xcd, 0xf9, 0x5b, 0x12, 0x65, 0x20, 0xe2, 0xbd, 0x4d, - 0x53, 0xfd, 0xd3, 0x4e, 0x1d, 0x32, 0xe5, 0xe9, 0x25, 0x1d, 0xca, 0x26, 0x34, 0xd7, 0x3a, 0x6d, 0x2c, 0x21, 0x3e, - 0xc1, 0x7d, 0xe1, 0xe6, 0xc5, 0x1b, 0x18, 0x68, 0x1f, 0x6c, 0x92, 0x2f, 0xb7, 0xdf, 0x26, 0xf3, 0x8c, 0x6b, 0x2f, - 0xbe, 0x5e, 0x30, 0x3c, 0xc1, 0x1d, 0xba, 0x50, 0xb5, 0xfa, 0xa4, 0x82, 0xe1, 0x3a, 0x1c, 0x95, 0x3f, 0xa7, 0xfd, - 0xa0, 0x9b, 0xb9, 0x29, 0x8a, 0x8a, 0x29, 0x89, 0x5f, 0x93, 0x30, 0x69, 0x50, 0xb7, 0xa6, 0xc7, 0x69, 0x3d, 0xd1, - 0xb9, 0x74, 0x72, 0xf7, 0xfa, 0xaf, 0xb0, 0xda, 0xc4, 0xa8, 0xeb, 0xa2, 0x1e, 0xd3, 0xef, 0x7a, 0xd1, 0xa8, 0x34, - 0x69, 0x46, 0x63, 0xe7, 0xea, 0xa1, 0xbf, 0x59, 0x78, 0x24, 0xba, 0xbf, 0xe8, 0x69, 0xc5, 0x2c, 0xad, 0xb2, 0xf8, - 0x0b, 0x17, 0x55, 0xc4, 0xf5, 0x56, 0x27, 0xef, 0x56, 0x89, 0x2b, 0x39, 0xf6, 0xe2, 0x59, 0x92, 0x41, 0xaf, 0x3a, - 0x34, 0x35, 0x46, 0x24, 0x27, 0x44, 0xfd, 0x8a, 0x41, 0xc0, 0xac, 0x67, 0x7c, 0x72, 0xbd, 0x96, 0x4c, 0xd3, 0xb7, - 0x1e, 0x73, 0xbd, 0x39, 0x0f, 0xb7, 0xef, 0x0b, 0xb8, 0xda, 0x96, 0xf5, 0xbd, 0x37, 0xca, 0x5c, 0x36, 0x12, 0x31, - 0x85, 0x1d, 0x89, 0xfe, 0xf8, 0x07, 0x44, 0x12, 0xe1, 0x27, 0xad, 0xf1, 0x45, 0x52, 0x49, 0xfb, 0x8d, 0x39, 0xdc, - 0x47, 0x4d, 0x06, 0xda, 0xdb, 0x3f, 0xf2, 0x54, 0x4d, 0x2f, 0x17, 0x8a, 0xaa, 0xea, 0x40, 0xbd, 0xa6, 0xd4, 0xe6, - 0x3e, 0xff, 0x6a, 0xf7, 0x28, 0x05, 0x95, 0xaa, 0x52, 0x58, 0xd3, 0x3b, 0x80, 0x29, 0xb4, 0xd8, 0x0b, 0xaa, 0xfa, - 0xb9, 0x52, 0xde, 0xf6, 0x7f, 0x9c, 0x1f, 0xff, 0x43, 0x1b, 0xbf, 0x97, 0x21, 0x36, 0xc1, 0x39, 0x7a, 0xbd, 0xdf, - 0xa7, 0xa7, 0x81, 0x28, 0x9a, 0x57, 0x8b, 0x76, 0xbb, 0xf1, 0xb6, 0xb4, 0x5a, 0xb4, 0xa5, 0xd5, 0xa2, 0x49, 0x6f, - 0x98, 0xdf, 0xab, 0x63, 0x0e, 0xbc, 0x3c, 0xc1, 0x75, 0x86, 0x12, 0x3c, 0xb5, 0xe5, 0x3f, 0xba, 0x80, 0x29, 0x0f, - 0x48, 0x8d, 0x36, 0xd0, 0xa7, 0x32, 0x70, 0xba, 0xb9, 0x61, 0x44, 0xd3, 0x55, 0x2b, 0x23, 0xcd, 0xbc, 0x27, 0x45, - 0xef, 0x73, 0x12, 0x73, 0xb0, 0x67, 0x2c, 0x59, 0xbb, 0xbe, 0x98, 0xf1, 0xa3, 0xd2, 0x16, 0x0c, 0x1d, 0x0a, 0x3f, - 0x26, 0x99, 0x1a, 0xd0, 0x8b, 0xce, 0x8f, 0x69, 0xe9, 0xa3, 0xf4, 0xb7, 0x2f, 0xb9, 0xe4, 0xef, 0x17, 0xa2, 0x78, - 0xd4, 0xd2, 0xac, 0x03, 0x01, 0xbf, 0x26, 0x34, 0x23, 0xe3, 0xb7, 0x62, 0xd0, 0xbe, 0x48, 0x9f, 0x73, 0x11, 0x38, - 0x15, 0x20, 0x7f, 0x48, 0x18, 0x07, 0x8a, 0x86, 0xf6, 0x1a, 0x7b, 0xa0, 0x54, 0x99, 0x3e, 0xf7, 0xb4, 0x44, 0x4f, - 0x94, 0x16, 0xfa, 0xc9, 0x18, 0x63, 0xd6, 0x54, 0x14, 0x5b, 0x9a, 0xf7, 0x0d, 0x32, 0xc9, 0x17, 0x4e, 0x12, 0x5a, - 0xcc, 0xa9, 0xa3, 0x40, 0xb7, 0x0a, 0xb5, 0xf6, 0x60, 0xfa, 0x0e, 0x95, 0x03, 0x4b, 0x45, 0xd9, 0xf7, 0x53, 0x6c, - 0x11, 0x1f, 0xda, 0x25, 0x3e, 0x43, 0xe2, 0xb6, 0x17, 0x99, 0x08, 0x52, 0x8d, 0x51, 0x51, 0x3c, 0xb6, 0x4d, 0x1a, - 0x24, 0x37, 0x54, 0x31, 0x8c, 0x51, 0x27, 0x56, 0x4f, 0x63, 0x75, 0x62, 0x75, 0x9a, 0x95, 0xa2, 0x2d, 0x99, 0xa9, - 0x67, 0x24, 0x96, 0xae, 0xb0, 0x8b, 0x97, 0xdf, 0xe0, 0xd5, 0xe9, 0xb3, 0x07, 0x74, 0x51, 0xe9, 0x55, 0xd3, 0xc0, - 0x67, 0xb0, 0x81, 0x34, 0xaa, 0x03, 0x91, 0x97, 0xf8, 0xcd, 0x04, 0x04, 0x60, 0xf4, 0xf0, 0x03, 0x15, 0xa5, 0xd3, - 0xa6, 0x3d, 0xec, 0xac, 0x4c, 0x40, 0x74, 0xcd, 0x07, 0x63, 0x92, 0x37, 0x48, 0x70, 0xde, 0x8b, 0xa7, 0x42, 0x18, - 0x83, 0x97, 0x67, 0xc6, 0x16, 0x9b, 0x8f, 0x6f, 0x56, 0x74, 0x5e, 0xa0, 0x14, 0xf6, 0x12, 0xb2, 0x2f, 0x35, 0x53, - 0x3d, 0x0a, 0xf3, 0x34, 0x27, 0x97, 0x6e, 0x5c, 0x25, 0x1f, 0x03, 0xcf, 0x81, 0x20, 0x5e, 0xdf, 0xa9, 0xbe, 0x1d, - 0x38, 0x61, 0x8a, 0x9f, 0x32, 0xce, 0x97, 0xbf, 0x52, 0x0b, 0xd9, 0xb3, 0x51, 0xe7, 0xad, 0x8c, 0xd8, 0x55, 0x45, - 0x55, 0x69, 0x4c, 0x41, 0x05, 0x97, 0x1d, 0x22, 0x68, 0xdb, 0x4f, 0x12, 0x8f, 0x48, 0x54, 0x05, 0xea, 0xb3, 0x99, - 0x48, 0x82, 0xb9, 0x00, 0x4b, 0x23, 0x6f, 0x39, 0xe7, 0xd5, 0xdf, 0xb2, 0x26, 0x99, 0x27, 0xe0, 0x22, 0xf9, 0xb4, - 0x93, 0xd3, 0x75, 0xe4, 0xa5, 0x87, 0xa9, 0x3a, 0xc4, 0x82, 0x59, 0xc2, 0x69, 0x56, 0x6e, 0x62, 0x5f, 0x5e, 0x03, - 0x35, 0x93, 0x8f, 0x48, 0xe5, 0x8f, 0x4d, 0x4e, 0xa9, 0x8d, 0x54, 0x80, 0xed, 0x21, 0x73, 0xbd, 0x43, 0x27, 0xdc, - 0x86, 0xf4, 0xdb, 0xcd, 0x6d, 0x1b, 0x28, 0xfe, 0x91, 0x16, 0x86, 0xf4, 0x7f, 0xbd, 0x82, 0x22, 0x12, 0x46, 0x08, - 0x67, 0x93, 0x00, 0xe1, 0x5e, 0x74, 0xf2, 0x22, 0x5c, 0x4c, 0xe7, 0x51, 0xd8, 0xef, 0x9d, 0x75, 0x5e, 0xc3, 0x82, - 0xf3, 0x83, 0xea, 0xe7, 0x28, 0xec, 0x1c, 0xeb, 0x35, 0x59, 0x16, 0xfc, 0xf8, 0x23, 0x33, 0x0a, 0x1d, 0xcc, 0x77, - 0x13, 0x41, 0xab, 0x4e, 0x82, 0xb2, 0x60, 0xad, 0x04, 0x81, 0xa4, 0x60, 0xd1, 0x35, 0x52, 0xd5, 0xdb, 0x94, 0x76, - 0xfd, 0x28, 0x2f, 0x3a, 0x4e, 0xff, 0xaa, 0xa6, 0xfb, 0x84, 0x30, 0x07, 0x5d, 0xa6, 0xc4, 0x07, 0x28, 0xd1, 0x6a, - 0x9f, 0xff, 0x1b, 0xe3, 0xd6, 0xd7, 0xae, 0xca, 0x6c, 0x26, 0x47, 0x8a, 0x29, 0x0a, 0xaf, 0xbd, 0x92, 0x66, 0xc6, - 0xa7, 0x04, 0xf3, 0xaa, 0x29, 0xeb, 0xa9, 0xa0, 0x4c, 0x53, 0xd7, 0x02, 0x2f, 0xd6, 0x25, 0xce, 0xf3, 0x62, 0x65, - 0x6f, 0xcc, 0x2f, 0x69, 0x39, 0x36, 0x9b, 0x4e, 0x5b, 0x31, 0x10, 0xea, 0x78, 0xd8, 0xe8, 0x39, 0x51, 0x10, 0xd3, - 0xf5, 0xc2, 0x71, 0x53, 0x29, 0xf5, 0x97, 0xc0, 0xa1, 0x53, 0x9b, 0xc9, 0x93, 0xb5, 0x1c, 0x31, 0xe4, 0x19, 0x96, - 0xb5, 0x32, 0xe8, 0xdc, 0x07, 0xd2, 0x6e, 0xff, 0x55, 0xc1, 0xb3, 0xe0, 0x6f, 0x96, 0x78, 0x98, 0x2f, 0x35, 0x9b, - 0x5b, 0x24, 0xaf, 0x0a, 0x89, 0xf2, 0xb0, 0x3f, 0xd8, 0x9d, 0x5f, 0x4c, 0xb4, 0x95, 0xb1, 0x48, 0xf8, 0x4c, 0xf3, - 0x24, 0x84, 0x90, 0xed, 0x5a, 0x42, 0x5b, 0xf6, 0x82, 0x3d, 0x31, 0xae, 0x9e, 0x53, 0xc4, 0xde, 0x04, 0x07, 0x7f, - 0x7d, 0x94, 0x2c, 0xad, 0x51, 0xbe, 0xbd, 0xbf, 0x31, 0x13, 0xdb, 0x75, 0x35, 0x9a, 0x0a, 0xd9, 0xbb, 0xbf, 0x4d, - 0xc2, 0xbb, 0x54, 0xf8, 0xee, 0x18, 0xd4, 0x8f, 0xee, 0x3a, 0xc7, 0xff, 0x85, 0xe3, 0x46, 0x4b, 0xaf, 0x7e, 0x16, - 0xd7, 0x48, 0xc0, 0xe4, 0x54, 0x7a, 0x55, 0xdf, 0x8b, 0x82, 0xbd, 0xe1, 0x81, 0x40, 0x59, 0xcd, 0xff, 0x51, 0xfd, - 0xea, 0x02, 0x80, 0xc9, 0x9c, 0x8e, 0x61, 0xa3, 0xdb, 0xc5, 0xde, 0xdb, 0x80, 0xcb, 0xd5, 0x1e, 0xff, 0x3a, 0x4e, - 0xd7, 0x41, 0x22, 0x38, 0x6e, 0xd7, 0xf5, 0x10, 0xe4, 0xe0, 0x31, 0xa7, 0x18, 0xc4, 0xf5, 0xe4, 0x4b, 0xf6, 0xdb, - 0x54, 0x78, 0x97, 0xd4, 0xe6, 0x17, 0x5b, 0x2b, 0xfe, 0x2c, 0x93, 0x06, 0x55, 0x1a, 0xfc, 0x17, 0xa4, 0x75, 0xb0, - 0xa7, 0x17, 0x84, 0x4d, 0xfa, 0x83, 0xe2, 0x70, 0x86, 0x05, 0xb6, 0x61, 0xa5, 0xa1, 0xb5, 0x32, 0x7e, 0xcc, 0xe8, - 0xb9, 0x4d, 0x30, 0x0e, 0x45, 0xce, 0xf6, 0x1a, 0x4d, 0xa3, 0x54, 0xab, 0x4b, 0xf7, 0x9b, 0x3c, 0x0b, 0x93, 0x96, - 0x76, 0x97, 0x4e, 0xd0, 0x3e, 0xaa, 0x3f, 0xff, 0x27, 0x95, 0xb8, 0xa2, 0x1f, 0x7a, 0xef, 0x26, 0x7e, 0x7f, 0x05, - 0x77, 0x6a, 0x9e, 0xd4, 0xf8, 0xc3, 0xdb, 0x99, 0xef, 0xfa, 0x92, 0x1e, 0x3f, 0x0d, 0x12, 0x8d, 0x61, 0x2c, 0x40, - 0x14, 0xd3, 0x78, 0x69, 0x2c, 0xef, 0x60, 0xe6, 0x86, 0x6d, 0xf4, 0xcd, 0x80, 0x6f, 0xf9, 0x9c, 0x21, 0x68, 0x40, - 0x8c, 0x9a, 0x2e, 0x55, 0x54, 0xfa, 0x7d, 0xd2, 0x90, 0x26, 0x12, 0x68, 0x9e, 0xf9, 0x25, 0x14, 0x4e, 0x27, 0x91, - 0x4a, 0x72, 0x80, 0x75, 0x32, 0xfd, 0xac, 0xdd, 0x97, 0xfb, 0x0b, 0xb9, 0x4b, 0x78, 0x5d, 0xa7, 0x2f, 0x5f, 0x8b, - 0xf9, 0x66, 0x52, 0x3f, 0x36, 0x94, 0xbe, 0x2c, 0x3b, 0x34, 0x8e, 0x8e, 0x30, 0x57, 0x6b, 0x84, 0x22, 0x72, 0x86, - 0xf8, 0x22, 0xb1, 0x86, 0x43, 0x1f, 0x99, 0x60, 0x5d, 0xca, 0x0e, 0x68, 0xf2, 0xcd, 0xca, 0x9b, 0x9b, 0x8d, 0xcc, - 0x69, 0x6a, 0x88, 0x59, 0xc4, 0x70, 0xf0, 0x87, 0x08, 0x9d, 0xa6, 0x7d, 0xdc, 0xd4, 0x39, 0x71, 0x86, 0xa4, 0xe1, - 0x3a, 0x26, 0x55, 0x95, 0x30, 0xab, 0x6c, 0x63, 0xf1, 0x94, 0x76, 0xd5, 0xba, 0x07, 0x6e, 0xe7, 0x5c, 0x38, 0x6a, - 0xa5, 0x8e, 0xb6, 0x89, 0x44, 0x21, 0x3b, 0x6c, 0xa5, 0x4e, 0xdf, 0x9d, 0xa2, 0x58, 0xa1, 0xe2, 0xed, 0x92, 0x7a, - 0x0d, 0x33, 0x0e, 0x57, 0xc2, 0x32, 0x1c, 0x60, 0xe0, 0x97, 0xb5, 0xf2, 0xbe, 0xc6, 0xe4, 0x54, 0xba, 0xa6, 0xbc, - 0x4b, 0xa9, 0xd1, 0x66, 0xb1, 0x7f, 0xf1, 0x87, 0xd7, 0x96, 0x66, 0x8b, 0x3f, 0x6c, 0xc6, 0x5b, 0x90, 0x53, 0xa7, - 0x0d, 0x34, 0x36, 0x6d, 0x87, 0x84, 0x26, 0xf7, 0xa9, 0xcc, 0x65, 0xa8, 0xa9, 0xc5, 0x96, 0x74, 0x8e, 0xa9, 0xee, - 0x57, 0x88, 0xf2, 0x11, 0xa5, 0xb3, 0x74, 0x77, 0x2a, 0x36, 0x25, 0x4f, 0x35, 0x0a, 0xfb, 0x58, 0x7d, 0xc1, 0xc8, - 0xa0, 0xd5, 0x71, 0xa0, 0xda, 0x77, 0xd6, 0x61, 0x41, 0x4c, 0x79, 0xc1, 0x7e, 0x4b, 0x2c, 0x27, 0xde, 0x2e, 0x2f, - 0x14, 0x77, 0x2a, 0xce, 0xed, 0x7a, 0x35, 0xce, 0xe7, 0x68, 0x84, 0xfd, 0xb2, 0x96, 0x62, 0x12, 0x10, 0x89, 0xed, - 0x27, 0xa4, 0x4b, 0xf1, 0x77, 0xd9, 0xe1, 0xb2, 0xbc, 0x12, 0xc2, 0x7c, 0xf4, 0xce, 0x68, 0xa1, 0x2e, 0x61, 0xae, - 0xf1, 0x26, 0x4f, 0x18, 0x44, 0x49, 0x34, 0xbd, 0x3e, 0xe3, 0x54, 0x97, 0xaa, 0xb7, 0x2d, 0x28, 0x4e, 0xd3, 0x2f, - 0x5a, 0x92, 0x5b, 0xab, 0x67, 0xc6, 0x8c, 0x41, 0xa0, 0x0e, 0x15, 0xbd, 0x85, 0x82, 0x62, 0xcc, 0x88, 0xb0, 0xd3, - 0xf9, 0x97, 0x4c, 0xaa, 0x33, 0x1d, 0xaa, 0x76, 0xed, 0xff, 0xa3, 0x83, 0x1d, 0x1e, 0xad, 0xcf, 0x7f, 0xdf, 0xcc, - 0xf4, 0xa0, 0x0a, 0x3a, 0x85, 0xcf, 0x3b, 0xab, 0x18, 0x0a, 0x05, 0xc8, 0xca, 0xce, 0x9d, 0x33, 0x80, 0x3a, 0x52, - 0x2b, 0xa4, 0xbb, 0x3e, 0xef, 0x2d, 0x66, 0xb8, 0xad, 0x4b, 0xe0, 0xc7, 0xd0, 0x0a, 0x3f, 0x9a, 0x16, 0x2f, 0x77, - 0xf8, 0xfa, 0x35, 0x8c, 0x78, 0x0a, 0xc2, 0x58, 0x18, 0xbc, 0x87, 0x14, 0x37, 0x61, 0x90, 0xa1, 0x09, 0x92, 0x7c, - 0xa2, 0x2d, 0x6b, 0xe6, 0x5a, 0x4a, 0x0e, 0xc8, 0xf8, 0x3d, 0x29, 0x0a, 0x80, 0xdf, 0x25, 0xb3, 0x8d, 0x1b, 0x0c, - 0x70, 0x82, 0xd2, 0xa6, 0x76, 0xac, 0xe2, 0x66, 0xfe, 0xb3, 0xc3, 0x8b, 0x08, 0xf4, 0x4c, 0xe1, 0x18, 0xcf, 0xbf, - 0xdb, 0x8f, 0x23, 0x04, 0xa9, 0xe0, 0xc7, 0x28, 0xd5, 0xec, 0xe8, 0xa5, 0xff, 0xda, 0xd5, 0xf4, 0xf0, 0x48, 0x77, - 0x4d, 0xa2, 0xb6, 0x8c, 0x50, 0x01, 0x36, 0x20, 0x9a, 0x01, 0x2e, 0x4c, 0xc7, 0x98, 0xe6, 0xcb, 0x1f, 0xfd, 0xc4, - 0xda, 0x55, 0xf3, 0x7a, 0x46, 0x2b, 0x8f, 0xae, 0x93, 0x05, 0x6a, 0xce, 0x75, 0x5f, 0x5e, 0x83, 0xef, 0x96, 0x7d, - 0x3c, 0x65, 0x0b, 0x32, 0x83, 0x00, 0x83, 0xd5, 0x73, 0xce, 0x44, 0x2f, 0x09, 0x77, 0x52, 0x5b, 0x3d, 0xaa, 0xc1, - 0xbc, 0xe3, 0xd7, 0xd7, 0x5e, 0x92, 0x21, 0xf9, 0xd0, 0x59, 0xbb, 0x99, 0x44, 0x8f, 0xad, 0xd9, 0x78, 0xbf, 0x66, - 0x92, 0xa5, 0xfe, 0xd7, 0xf0, 0xd9, 0xf8, 0xea, 0xf5, 0x2a, 0x35, 0xdf, 0x66, 0xf0, 0xcb, 0xcb, 0x4b, 0x8e, 0x8b, - 0x39, 0x2f, 0x7e, 0x63, 0x8d, 0x2d, 0x1c, 0x27, 0x9b, 0x0f, 0x95, 0x28, 0x53, 0x83, 0xb9, 0xf3, 0x1a, 0xd4, 0xce, - 0x93, 0x2c, 0x37, 0x7b, 0xa5, 0x07, 0xd8, 0xf9, 0xfb, 0x0b, 0xe3, 0x9c, 0x78, 0x7f, 0x24, 0xcc, 0xb9, 0xf7, 0x67, - 0xb2, 0x39, 0xfb, 0x24, 0xa3, 0x60, 0xcf, 0xac, 0x83, 0x87, 0x1d, 0x6d, 0xc5, 0x64, 0x9a, 0x2d, 0x13, 0x72, 0x85, - 0x77, 0xc3, 0xaa, 0xda, 0x79, 0x78, 0x42, 0xc5, 0x0d, 0xfd, 0x46, 0xcf, 0x07, 0xb9, 0xc1, 0xbb, 0x85, 0x3a, 0xcb, - 0x41, 0x67, 0xa1, 0x8d, 0x7f, 0x5b, 0xa8, 0xfb, 0x49, 0xf8, 0xb4, 0x04, 0x57, 0x66, 0x2f, 0x91, 0xd4, 0xaf, 0x02, - 0xa8, 0x3a, 0xe7, 0xb6, 0x0d, 0xe4, 0x62, 0xaf, 0x5f, 0xa9, 0xf6, 0x59, 0x81, 0x68, 0x6c, 0xa8, 0x48, 0x9d, 0x45, - 0xa1, 0x1b, 0x52, 0xa7, 0x34, 0xdb, 0x59, 0x1d, 0xad, 0x0f, 0x7c, 0x8f, 0x3f, 0x54, 0x43, 0x15, 0xe6, 0x9b, 0x45, - 0x67, 0xc8, 0x0d, 0x34, 0xcf, 0x48, 0xb3, 0xb8, 0xde, 0x94, 0x9c, 0x5a, 0x11, 0x0d, 0xa1, 0x31, 0xf8, 0x26, 0x83, - 0x83, 0x72, 0x5c, 0x89, 0xad, 0x28, 0xba, 0x29, 0x9f, 0xed, 0x7f, 0x15, 0x6b, 0xc5, 0xbe, 0x80, 0xd8, 0x57, 0x74, - 0x81, 0x8d, 0xb5, 0x02, 0x77, 0x84, 0xf6, 0x78, 0x89, 0x6c, 0x65, 0x65, 0xa5, 0xe6, 0xc2, 0x9a, 0xb0, 0xd6, 0x7b, - 0x9c, 0x75, 0x82, 0xf6, 0xce, 0xbf, 0xd0, 0x55, 0x48, 0x2d, 0x31, 0xd6, 0x49, 0x77, 0x2a, 0x06, 0x16, 0xa0, 0xb8, - 0x8f, 0x5a, 0x1f, 0x43, 0x15, 0x85, 0x11, 0xf9, 0xb4, 0x9e, 0xf0, 0x3e, 0x36, 0x33, 0x1b, 0x9b, 0x1b, 0xee, 0x43, - 0x6b, 0xbd, 0xd9, 0x64, 0xd5, 0xb4, 0x9f, 0x38, 0xef, 0x02, 0xc3, 0x0e, 0x06, 0x97, 0x37, 0xce, 0x37, 0x5d, 0xd0, - 0xa4, 0x27, 0x9c, 0x60, 0x8a, 0xe6, 0x36, 0xe0, 0xc9, 0x47, 0xf4, 0x94, 0x46, 0x76, 0x76, 0x87, 0xb7, 0x40, 0xee, - 0x30, 0xfa, 0xd4, 0x72, 0xb1, 0xe0, 0xd8, 0x82, 0xf3, 0x76, 0x41, 0x2e, 0xd6, 0x0d, 0xdd, 0x4a, 0x90, 0x74, 0x48, - 0xf3, 0xd9, 0xe0, 0x3a, 0x95, 0x42, 0x3f, 0xf8, 0xff, 0x12, 0x27, 0x9d, 0x6d, 0x45, 0x41, 0x80, 0x3b, 0x27, 0x41, - 0x25, 0x62, 0xef, 0x46, 0x8e, 0x85, 0xb2, 0x67, 0x50, 0xa5, 0xec, 0x23, 0x87, 0xf4, 0xd9, 0x6d, 0x88, 0x4a, 0xc4, - 0x76, 0xcf, 0x50, 0xe7, 0x63, 0x42, 0x7f, 0xf9, 0x85, 0xd7, 0x77, 0x7e, 0x11, 0x80, 0xf9, 0xb6, 0x3a, 0x13, 0x6f, - 0xcf, 0xd5, 0xb3, 0xbf, 0x44, 0x02, 0x96, 0x8b, 0xec, 0x48, 0xa6, 0x59, 0x8e, 0x4f, 0xeb, 0xb7, 0xd8, 0x74, 0x50, - 0x08, 0x86, 0xa0, 0x7d, 0xb8, 0xc0, 0x37, 0x5f, 0x05, 0x5c, 0x2e, 0xd0, 0xf0, 0xf1, 0x79, 0xf1, 0x5b, 0x47, 0x2f, - 0x1a, 0x89, 0xc0, 0xd1, 0x4c, 0x1d, 0xaf, 0x79, 0xde, 0x82, 0xab, 0x3c, 0xb5, 0xe7, 0xc5, 0xa4, 0xd1, 0x3a, 0xcf, - 0xe7, 0xa7, 0xb4, 0xb0, 0x96, 0xde, 0xe6, 0xff, 0x84, 0xa9, 0xad, 0x50, 0x44, 0xfe, 0x79, 0x1f, 0x11, 0x3f, 0x32, - 0x69, 0xa0, 0x91, 0xfd, 0xaa, 0x2d, 0xf9, 0xca, 0x3b, 0x09, 0x8b, 0x08, 0x37, 0xf1, 0x2e, 0x36, 0xc2, 0xfc, 0x2c, - 0x26, 0x3f, 0x5d, 0x99, 0x4f, 0x8d, 0x2b, 0xb2, 0xda, 0xc7, 0xc4, 0xc3, 0xa3, 0xf5, 0x61, 0xdc, 0x2d, 0xcb, 0xb5, - 0x59, 0x9e, 0x2f, 0x4a, 0x57, 0x6a, 0x9f, 0x67, 0x4f, 0x04, 0x6b, 0xb1, 0x3e, 0xd8, 0xb9, 0x97, 0x08, 0xc8, 0xa8, - 0x9a, 0x97, 0xb6, 0x43, 0xe4, 0xe1, 0xf9, 0x93, 0x6f, 0x79, 0x97, 0x27, 0x0a, 0x4a, 0xdb, 0x21, 0xf0, 0xdd, 0x7d, - 0x9d, 0xea, 0x54, 0xc1, 0x98, 0xa7, 0x2b, 0x80, 0xd6, 0x80, 0x85, 0xd2, 0x0c, 0x27, 0xf6, 0x5c, 0x85, 0x6c, 0xda, - 0xeb, 0x35, 0xe5, 0x03, 0x80, 0x6a, 0xc2, 0x8d, 0x3d, 0x05, 0x19, 0xe7, 0xb3, 0xd2, 0xf5, 0xf8, 0xe1, 0xef, 0xb9, - 0xe3, 0xec, 0x03, 0x7e, 0xfc, 0x2d, 0xb9, 0x45, 0x7f, 0x99, 0x47, 0xa6, 0xe5, 0xdb, 0x8c, 0x46, 0x8d, 0x63, 0x34, - 0xde, 0xcc, 0x00, 0xa2, 0xa2, 0x6a, 0x60, 0xc6, 0x94, 0x9f, 0x05, 0x43, 0x4b, 0x66, 0xd5, 0x21, 0x9f, 0x6b, 0xbb, - 0x9f, 0x58, 0x8b, 0xf8, 0xb0, 0x3a, 0xb4, 0xca, 0x5a, 0xc9, 0xfe, 0xa5, 0xeb, 0xd0, 0x47, 0x2b, 0x14, 0x00, 0x01, - 0xf6, 0x30, 0xfa, 0x9c, 0xb1, 0x56, 0x0b, 0x3e, 0xde, 0x7f, 0x61, 0x12, 0x11, 0x89, 0x4d, 0xde, 0x77, 0x7d, 0x13, - 0xa0, 0x2c, 0x33, 0xc2, 0x9e, 0x1d, 0xb3, 0x1b, 0x63, 0xca, 0x12, 0x64, 0xd1, 0xb8, 0x0f, 0x12, 0x84, 0xde, 0x1a, - 0x6e, 0x00, 0x38, 0x47, 0x9e, 0x0c, 0x97, 0x29, 0xe4, 0x4b, 0xe4, 0xe3, 0xf4, 0x3d, 0xae, 0xc8, 0xc2, 0x01, 0xbe, - 0x1e, 0xb4, 0x92, 0x6d, 0x63, 0xac, 0xa0, 0xa2, 0x98, 0x03, 0x99, 0xce, 0x52, 0xc2, 0x57, 0x8c, 0x38, 0xe7, 0x0f, - 0x85, 0x73, 0xb8, 0x98, 0xf5, 0xfa, 0xf9, 0xdc, 0x67, 0xad, 0x4c, 0x68, 0x47, 0x73, 0x9a, 0x81, 0x01, 0xc5, 0xb0, - 0x2a, 0x36, 0xff, 0x57, 0x58, 0xa2, 0xe4, 0xbd, 0x36, 0xb2, 0xf3, 0xa7, 0xc4, 0xb6, 0x46, 0x11, 0x30, 0xd1, 0xd8, - 0x5e, 0x36, 0xe5, 0x6c, 0x2d, 0xa9, 0xa1, 0x2b, 0xc2, 0xc2, 0xfb, 0x60, 0xc7, 0x16, 0xae, 0xf5, 0x2a, 0x6a, 0x9e, - 0x51, 0x0f, 0xcc, 0xfb, 0x4a, 0xc4, 0x65, 0xbe, 0x6f, 0x6d, 0x10, 0xe4, 0x3e, 0x6f, 0x45, 0x26, 0x07, 0x24, 0x25, - 0x1a, 0x58, 0x78, 0x5c, 0xcb, 0x77, 0x2e, 0xd8, 0x7b, 0x97, 0xd5, 0xa1, 0x2b, 0x94, 0x25, 0xd5, 0x38, 0xa3, 0x68, - 0x30, 0xa6, 0x44, 0x24, 0x9e, 0x0b, 0x41, 0x8d, 0x86, 0xbf, 0xf9, 0x44, 0xd4, 0x72, 0xc2, 0x63, 0xef, 0x13, 0x6e, - 0x74, 0x32, 0xbd, 0xa1, 0x66, 0xca, 0x76, 0xf4, 0xe6, 0xe7, 0x03, 0x65, 0x8d, 0xe6, 0x7c, 0xac, 0x62, 0xe6, 0x92, - 0x03, 0x28, 0x33, 0x91, 0x22, 0x20, 0x87, 0x1e, 0x77, 0x9c, 0x55, 0x92, 0x5e, 0xe3, 0x2b, 0x4c, 0xa2, 0xa1, 0x27, - 0xb7, 0xd7, 0xd5, 0x54, 0x2c, 0x37, 0x18, 0x29, 0xf0, 0x62, 0x7a, 0xeb, 0x66, 0x53, 0x8a, 0xd5, 0xd2, 0x0d, 0xa3, - 0x2a, 0xe9, 0xa3, 0x7e, 0x6d, 0x3d, 0xc7, 0x8e, 0xbe, 0xd5, 0x53, 0xcb, 0xcc, 0xfb, 0x5e, 0x5b, 0x9d, 0x0a, 0xda, - 0xfd, 0x8f, 0x96, 0x8c, 0xa2, 0x8b, 0x69, 0xf5, 0x2c, 0xde, 0xea, 0x0f, 0xdd, 0x22, 0x9f, 0x37, 0x79, 0x7c, 0x0f, - 0x56, 0x9c, 0x52, 0x6b, 0x15, 0x66, 0xef, 0x3d, 0x4a, 0x8d, 0xbd, 0xd7, 0x4a, 0xb1, 0xbc, 0x4e, 0xc9, 0x25, 0xa6, - 0xdc, 0x78, 0x89, 0x2a, 0xf2, 0xa3, 0x56, 0xbc, 0x65, 0xfe, 0x03, 0x55, 0x49, 0xc3, 0x55, 0xa7, 0x39, 0xf9, 0xb0, - 0xcf, 0xa1, 0x66, 0x53, 0xc0, 0x29, 0xca, 0x6a, 0x25, 0x37, 0xd3, 0xfb, 0xae, 0x0a, 0xb4, 0x26, 0x7e, 0x03, 0xa3, - 0x0c, 0x59, 0x4d, 0xb3, 0x79, 0xf5, 0xdf, 0xde, 0xf4, 0xb3, 0x1a, 0xa6, 0x6f, 0xca, 0x99, 0x7e, 0x7e, 0xbe, 0x84, - 0x5b, 0xbf, 0x6f, 0x4e, 0x35, 0x01, 0xae, 0x96, 0xa4, 0x10, 0x5f, 0xad, 0x98, 0x23, 0x80, 0xbe, 0xef, 0x26, 0x09, - 0xfd, 0x84, 0xa7, 0xc5, 0x42, 0x0d, 0x41, 0xb2, 0x46, 0x34, 0x79, 0x74, 0xff, 0x8f, 0xc5, 0x02, 0x23, 0x4e, 0x2b, - 0xdf, 0x5e, 0x4e, 0x35, 0xa2, 0x22, 0xce, 0x26, 0x97, 0x39, 0x88, 0x11, 0x0c, 0x08, 0xb9, 0x48, 0x02, 0x1d, 0xa5, - 0xab, 0x8b, 0x46, 0xa4, 0x00, 0x34, 0x2c, 0xfa, 0x0d, 0x40, 0xe0, 0x10, 0xcc, 0x11, 0x41, 0x30, 0x92, 0x37, 0x02, - 0x2c, 0xc7, 0x64, 0xef, 0x58, 0x05, 0x0b, 0x1b, 0x75, 0xb0, 0xeb, 0x0d, 0xe2, 0x02, 0x5a, 0x34, 0x4f, 0x23, 0x41, - 0x51, 0x05, 0x8b, 0x18, 0x59, 0xb6, 0xb9, 0xf8, 0xa3, 0xe6, 0x3d, 0x2a, 0x24, 0x0a, 0x5d, 0x3c, 0x7d, 0x9a, 0x2e, - 0xa1, 0xec, 0x2f, 0xc0, 0xbf, 0x8a, 0x3a, 0xb0, 0xa7, 0x0e, 0x5a, 0x17, 0xd0, 0xb1, 0x15, 0x27, 0xa7, 0x32, 0xe5, - 0xcf, 0x39, 0x03, 0x40, 0x49, 0xcf, 0x1a, 0xc4, 0xd0, 0xa0, 0x73, 0xdd, 0x72, 0x4d, 0x12, 0xc0, 0x70, 0xc9, 0x78, - 0x69, 0xa9, 0x6d, 0x3d, 0x7b, 0x48, 0xe6, 0x23, 0x82, 0x39, 0x3a, 0x24, 0xf1, 0x22, 0x4a, 0xdc, 0x65, 0x79, 0x09, - 0x54, 0x66, 0x9d, 0x8f, 0x62, 0x5d, 0x2b, 0xaf, 0xf4, 0x8b, 0x3f, 0x3e, 0x3f, 0x21, 0xc9, 0xc2, 0xab, 0x06, 0x7c, - 0x84, 0xcb, 0xba, 0x08, 0xfc, 0xc8, 0x69, 0x51, 0xa0, 0xbc, 0x5d, 0x75, 0xd0, 0xd2, 0x93, 0x9d, 0x08, 0x36, 0x4d, - 0x4b, 0x7f, 0x1b, 0xf6, 0xcb, 0x77, 0x34, 0x99, 0x72, 0x1c, 0x2a, 0xfc, 0x0c, 0x08, 0x9b, 0xe2, 0x6e, 0x50, 0x34, - 0x94, 0x17, 0x37, 0x10, 0xca, 0xe9, 0xec, 0xf0, 0xed, 0xe8, 0x59, 0x45, 0xe0, 0xf3, 0x7e, 0xf4, 0x37, 0x71, 0x5d, - 0x81, 0xa5, 0xd3, 0xb1, 0x47, 0x15, 0x82, 0xa3, 0x3c, 0xad, 0x7d, 0x23, 0x75, 0x6a, 0x11, 0x52, 0x15, 0x4f, 0x8b, - 0xbe, 0x4a, 0xf7, 0x3e, 0x69, 0xb0, 0xe1, 0x6d, 0x96, 0xed, 0x41, 0xb6, 0x32, 0x46, 0x34, 0x53, 0x5e, 0xf7, 0x98, - 0xe5, 0x7a, 0x1c, 0x30, 0x73, 0x80, 0xae, 0xbc, 0x9f, 0x3d, 0xc6, 0x50, 0xbd, 0xc2, 0x88, 0xd5, 0x66, 0xbf, 0x00, - 0xe6, 0xde, 0xb8, 0x9f, 0x6b, 0x7a, 0xe6, 0x53, 0x2e, 0xa4, 0x8c, 0x0a, 0xe6, 0x75, 0x95, 0x67, 0x70, 0xf2, 0x25, - 0x04, 0xc3, 0xf2, 0xe5, 0xfb, 0xcc, 0xaf, 0x57, 0x3d, 0x6c, 0x22, 0x9e, 0xd4, 0xf7, 0x74, 0x50, 0x1c, 0xa8, 0x0d, - 0xaf, 0xe5, 0x12, 0xe2, 0x8a, 0x30, 0xbb, 0x17, 0x87, 0xc0, 0x9a, 0xf1, 0x80, 0xef, 0xd8, 0x14, 0xf5, 0x84, 0xf2, - 0x28, 0x9c, 0x37, 0x13, 0xe6, 0x6f, 0x6a, 0x62, 0x32, 0x6f, 0xa6, 0x48, 0xb9, 0xf0, 0xa0, 0xb0, 0x29, 0xe3, 0x12, - 0x65, 0x4b, 0x1f, 0xd2, 0xef, 0x60, 0x6f, 0x34, 0xf1, 0x66, 0x35, 0x74, 0x3d, 0x39, 0x6e, 0x35, 0xd9, 0x3a, 0xc2, - 0x14, 0x00, 0x2d, 0x72, 0x1e, 0x01, 0xd3, 0xf5, 0xda, 0xad, 0x28, 0x5b, 0x07, 0x46, 0x1a, 0x1a, 0x42, 0xd1, 0x30, - 0x2f, 0x98, 0x5a, 0x15, 0x77, 0x87, 0x4e, 0x4c, 0x8c, 0xe7, 0x8c, 0xe5, 0x17, 0xf0, 0x66, 0xb3, 0x4e, 0x5b, 0xa3, - 0x17, 0x57, 0xa6, 0x82, 0xc9, 0x0c, 0x9a, 0x09, 0x90, 0x04, 0xf0, 0x4a, 0x19, 0x4d, 0xc6, 0x79, 0xca, 0xb1, 0xb9, - 0x3f, 0x68, 0x43, 0x06, 0x08, 0x74, 0x8a, 0x29, 0x95, 0xe2, 0xdd, 0xfa, 0x20, 0x65, 0xbc, 0x00, 0x94, 0x1d, 0xb3, - 0xc1, 0x32, 0x86, 0x06, 0xb0, 0x69, 0xd3, 0x9c, 0xe2, 0x2a, 0x7b, 0xca, 0x64, 0xd6, 0x46, 0x9d, 0xe6, 0x0f, 0x97, - 0x16, 0x46, 0xc4, 0xb8, 0xa8, 0xf9, 0x84, 0x7d, 0x35, 0xc5, 0x08, 0xb4, 0x1e, 0x83, 0xbc, 0x1e, 0x4d, 0x79, 0xb3, - 0xac, 0x31, 0x2e, 0x5d, 0x13, 0x4f, 0x5e, 0x14, 0x74, 0xea, 0xcb, 0xe4, 0x5f, 0xd6, 0x9f, 0xc0, 0x26, 0x1e, 0xc8, - 0xc4, 0x67, 0x92, 0xad, 0x4c, 0x14, 0x15, 0x10, 0xd5, 0x22, 0xbc, 0x92, 0x5c, 0x84, 0xa4, 0x64, 0xbc, 0x0c, 0x84, - 0x3a, 0x0e, 0x1a, 0x90, 0xbc, 0xaf, 0x2b, 0xe1, 0xb5, 0xe5, 0xcb, 0x45, 0xc8, 0x9b, 0x75, 0x58, 0xbb, 0xf3, 0xe9, - 0x74, 0x7b, 0x1b, 0x85, 0xa6, 0x01, 0x4a, 0x26, 0xc3, 0x15, 0xc8, 0x37, 0x34, 0x3b, 0x92, 0x27, 0x74, 0xfa, 0x77, - 0xb3, 0x32, 0x26, 0x61, 0x76, 0xba, 0x25, 0x47, 0xc5, 0x7f, 0x28, 0xed, 0x2e, 0x44, 0x2f, 0xe1, 0x50, 0x77, 0x50, - 0x0f, 0x44, 0xe5, 0x10, 0x73, 0x6a, 0x64, 0x9e, 0xc4, 0x55, 0x8e, 0x2c, 0x7d, 0x58, 0x26, 0x17, 0xb3, 0x8a, 0x33, - 0x19, 0xd2, 0xda, 0xda, 0xa6, 0xdb, 0x6c, 0x94, 0xa4, 0xcb, 0x12, 0xd3, 0xde, 0xda, 0x43, 0xb2, 0xea, 0xe1, 0x22, - 0x8c, 0xd2, 0xf7, 0x25, 0x4f, 0x4f, 0x9b, 0xa8, 0x7b, 0x3b, 0x89, 0x25, 0x7c, 0xec, 0x32, 0x70, 0x0a, 0xee, 0x80, - 0xb1, 0xca, 0x4e, 0x44, 0x2d, 0x90, 0xd4, 0x7f, 0xe9, 0xcd, 0x57, 0x21, 0x84, 0x78, 0xb7, 0xac, 0xd7, 0x3c, 0x12, - 0xf3, 0xc9, 0x63, 0xb4, 0x06, 0x1f, 0x90, 0x14, 0xf4, 0xe2, 0x70, 0x0e, 0x08, 0x3c, 0x6a, 0x7a, 0xf9, 0x9d, 0x48, - 0xe2, 0xec, 0x2e, 0x2b, 0x34, 0x85, 0xc3, 0xb3, 0xec, 0x62, 0x49, 0x6d, 0xa5, 0x20, 0xcf, 0xbe, 0x26, 0x2e, 0xb4, - 0x34, 0x61, 0xcc, 0x6f, 0x19, 0x3a, 0x07, 0x1e, 0xd3, 0xe3, 0xa0, 0xa0, 0x31, 0xbb, 0xab, 0x35, 0x26, 0x3c, 0x2f, - 0xaa, 0x20, 0x89, 0x7a, 0x1b, 0x46, 0x55, 0x26, 0x4e, 0xf9, 0xa8, 0x28, 0x58, 0xce, 0x0e, 0xbb, 0x31, 0xa1, 0xd1, - 0xa3, 0xff, 0x1c, 0x73, 0x12, 0x54, 0xee, 0x91, 0x19, 0xeb, 0xe0, 0x22, 0x5a, 0xe8, 0x67, 0xed, 0xfb, 0xca, 0xa2, - 0xf3, 0x6b, 0xa6, 0x29, 0x6f, 0xd7, 0x25, 0x6d, 0x74, 0xa3, 0x90, 0x12, 0x8b, 0xc4, 0x3c, 0x8b, 0x90, 0xed, 0xb7, - 0x90, 0x5b, 0xab, 0x0d, 0x84, 0x9b, 0x6c, 0x4a, 0xe0, 0x94, 0x84, 0x2f, 0x94, 0x67, 0x2b, 0x23, 0x1a, 0x99, 0xd6, - 0x48, 0x17, 0x55, 0x6b, 0xce, 0x5b, 0x53, 0x88, 0x9f, 0x18, 0x71, 0xb3, 0x46, 0xde, 0x08, 0x85, 0x00, 0xe1, 0xc2, - 0xfc, 0x39, 0x80, 0xfb, 0x3b, 0xa6, 0x8a, 0x87, 0x87, 0xd8, 0xa9, 0x59, 0xa9, 0x6d, 0xec, 0x81, 0x03, 0xf2, 0x16, - 0x27, 0x83, 0x0b, 0x24, 0xc3, 0x4c, 0xfc, 0x32, 0xd1, 0x06, 0xa5, 0x62, 0x52, 0xd5, 0xf8, 0x5c, 0x19, 0xb0, 0xd3, - 0xa7, 0xb2, 0x62, 0x6e, 0x3c, 0xa0, 0xcf, 0x56, 0x95, 0xa3, 0xaf, 0x1d, 0x41, 0x97, 0x9f, 0xcc, 0xf6, 0x6d, 0x54, - 0xf2, 0x7b, 0x30, 0xa6, 0xf2, 0x26, 0xce, 0x6d, 0xaa, 0x4e, 0x1f, 0xab, 0x0a, 0x5f, 0xbd, 0xe7, 0xce, 0xc4, 0x07, - 0x73, 0x47, 0x44, 0xfa, 0xf5, 0x60, 0xc8, 0x5f, 0xf5, 0xfb, 0x64, 0x10, 0x1d, 0x3b, 0x5d, 0x17, 0xaa, 0x77, 0x98, - 0x92, 0x8a, 0x8a, 0x5c, 0x09, 0x43, 0x14, 0x50, 0xc8, 0x65, 0xa4, 0xf4, 0xb5, 0x44, 0xd6, 0xa6, 0x72, 0x27, 0xed, - 0x47, 0x2b, 0x71, 0x86, 0x21, 0x2f, 0xad, 0x77, 0x61, 0x5d, 0xfe, 0x41, 0x57, 0x76, 0x44, 0xef, 0xd4, 0x13, 0xb9, - 0xec, 0x1c, 0x7e, 0xbe, 0xb4, 0x39, 0x40, 0xa9, 0xff, 0xa5, 0xfa, 0x4d, 0x9a, 0x08, 0x86, 0xd0, 0x95, 0x81, 0xf8, - 0xa0, 0xa8, 0xa5, 0xd8, 0xbe, 0xa0, 0x09, 0x75, 0xdd, 0x05, 0xd3, 0xa2, 0x2b, 0x16, 0x45, 0xff, 0xe5, 0x3d, 0x09, - 0x87, 0xfa, 0xc1, 0x2d, 0xd2, 0x0e, 0xfd, 0x7c, 0x97, 0xcb, 0x91, 0x53, 0x61, 0x51, 0x12, 0x13, 0x4d, 0x58, 0xd5, - 0x83, 0xcd, 0x61, 0x6b, 0x05, 0xcd, 0x69, 0xba, 0x4d, 0xbe, 0x3f, 0x54, 0x18, 0x85, 0x05, 0xfe, 0xbc, 0x34, 0x81, - 0x81, 0x06, 0x8e, 0xea, 0x0c, 0x54, 0x72, 0xdc, 0x2f, 0x74, 0x6b, 0x52, 0xe5, 0x65, 0x07, 0x32, 0x4b, 0xbe, 0x51, - 0xd6, 0x2d, 0xbf, 0x9b, 0xaf, 0x5e, 0x41, 0x5f, 0xff, 0x51, 0x36, 0x59, 0x40, 0xb4, 0x0e, 0xae, 0xb5, 0x1c, 0x98, - 0x4f, 0xb9, 0x18, 0x8f, 0x76, 0xf2, 0xea, 0x77, 0xfa, 0xf5, 0x12, 0xd5, 0x85, 0xa5, 0xc4, 0xb9, 0x47, 0xd4, 0x86, - 0xed, 0xec, 0xe7, 0x3c, 0x25, 0x3a, 0x28, 0xe3, 0xe7, 0xcf, 0x06, 0xcc, 0x66, 0xe1, 0xaa, 0x08, 0xd8, 0xd1, 0x57, - 0x57, 0x12, 0x02, 0x16, 0xb0, 0x25, 0x2c, 0x8c, 0xd8, 0x71, 0x94, 0x67, 0x8e, 0xa9, 0xec, 0x73, 0xcf, 0xe8, 0xfa, - 0xe6, 0xc4, 0x3d, 0x7c, 0xb9, 0xfd, 0x86, 0x95, 0x38, 0x4e, 0x26, 0xd6, 0xf2, 0x45, 0x57, 0x30, 0x34, 0x21, 0xe9, - 0xf2, 0x2b, 0x19, 0x90, 0xaa, 0x95, 0x9d, 0x98, 0xe7, 0x58, 0x02, 0xb6, 0xb7, 0xef, 0xaa, 0x38, 0x8f, 0xc9, 0xe9, - 0xc7, 0xc9, 0xdc, 0x02, 0x33, 0xb2, 0x50, 0x42, 0xe8, 0xbb, 0x95, 0xa8, 0xd7, 0xad, 0x49, 0x30, 0xa1, 0x5d, 0x10, - 0xfe, 0xc6, 0x71, 0x89, 0x6d, 0x68, 0xe9, 0xae, 0x17, 0x21, 0x74, 0x04, 0x22, 0xb9, 0x31, 0x4a, 0xbc, 0x3f, 0x3b, - 0xd7, 0xbd, 0x18, 0x6e, 0x52, 0xd0, 0x8c, 0x1e, 0x3c, 0x61, 0xbb, 0x4c, 0x48, 0x26, 0xf2, 0x1d, 0x1a, 0x02, 0xcb, - 0x73, 0x27, 0xfa, 0x19, 0xe0, 0x15, 0x71, 0x6b, 0xaf, 0xbf, 0x49, 0x5f, 0xb7, 0x2e, 0x15, 0x97, 0x9e, 0x67, 0x54, - 0x56, 0xe3, 0xc6, 0x9b, 0x41, 0x07, 0x3c, 0xba, 0xfc, 0x54, 0x89, 0x91, 0x0c, 0x82, 0x07, 0x88, 0x22, 0xa2, 0x4c, - 0x5f, 0xc9, 0x6d, 0x71, 0x77, 0x38, 0x05, 0x04, 0x32, 0x66, 0x4d, 0x7e, 0x31, 0x4c, 0x04, 0x4a, 0xcc, 0x37, 0xe3, - 0x8b, 0x1e, 0xfc, 0xd8, 0xee, 0x23, 0x72, 0x2e, 0xca, 0x35, 0x0c, 0xb6, 0x31, 0xaf, 0xac, 0xd8, 0x13, 0x7c, 0x23, - 0x91, 0x8e, 0x9e, 0x62, 0x28, 0x97, 0x28, 0x07, 0x2b, 0xdd, 0xe3, 0xb2, 0x07, 0x2b, 0xaa, 0x00, 0x71, 0xe3, 0xc6, - 0x19, 0x47, 0x05, 0x66, 0xc9, 0x0d, 0x69, 0x41, 0x93, 0x53, 0x87, 0x5f, 0xdb, 0xd1, 0x73, 0x80, 0x45, 0x71, 0x4f, - 0x5e, 0x03, 0xa7, 0xb6, 0xb5, 0x9e, 0xd6, 0xfa, 0x1b, 0x68, 0x88, 0x05, 0x75, 0x51, 0x3b, 0xbb, 0x1d, 0xd6, 0x5e, - 0xb0, 0xad, 0xab, 0x56, 0xfe, 0xb0, 0x1f, 0xda, 0xd8, 0x28, 0x86, 0xd3, 0x20, 0x92, 0xb8, 0x01, 0xd3, 0x28, 0xc4, - 0x1f, 0x9a, 0x6e, 0x16, 0x53, 0x79, 0xe2, 0xd7, 0xee, 0xaf, 0x95, 0x32, 0xe8, 0xf3, 0x8f, 0x62, 0x61, 0x4f, 0x26, - 0xf6, 0xeb, 0x25, 0x6c, 0x4c, 0x2a, 0x1b, 0x70, 0x55, 0xa3, 0xe2, 0x59, 0xf2, 0xa6, 0xf0, 0xe4, 0x43, 0x85, 0x96, - 0x9d, 0xf0, 0xf3, 0xa8, 0x48, 0x65, 0x6f, 0x46, 0x34, 0xaa, 0x15, 0x6b, 0x50, 0xa7, 0x47, 0x07, 0xc2, 0x65, 0x32, - 0xb0, 0x6a, 0x2c, 0x40, 0xfd, 0xf9, 0x65, 0xee, 0xd1, 0x27, 0x31, 0x78, 0x91, 0x8f, 0xb1, 0x35, 0x82, 0xde, 0x41, - 0x14, 0x62, 0x74, 0x24, 0x7d, 0x93, 0xca, 0xab, 0xbf, 0xe6, 0x31, 0xbe, 0x11, 0xfc, 0x9d, 0xb1, 0xf3, 0x2d, 0xf3, - 0xdc, 0x99, 0xbd, 0xc6, 0xae, 0xb9, 0x8e, 0xd6, 0x61, 0x28, 0xbb, 0x04, 0xa6, 0x21, 0x68, 0x0c, 0xd1, 0x04, 0xc6, - 0x58, 0x9a, 0x39, 0x5d, 0x1b, 0x55, 0x90, 0x7b, 0x21, 0x31, 0xfe, 0x5f, 0x24, 0xbc, 0x1c, 0xa8, 0x9c, 0x8e, 0xa2, - 0x16, 0x3c, 0x04, 0x77, 0xd5, 0x50, 0x0b, 0x94, 0xc9, 0xc3, 0x53, 0x68, 0xc9, 0x58, 0x86, 0xe7, 0x98, 0xd9, 0x06, - 0x75, 0x30, 0x1e, 0xc9, 0x3c, 0xac, 0x53, 0xb8, 0x42, 0xcf, 0x16, 0xc5, 0xcc, 0x8e, 0x79, 0x5b, 0x61, 0x64, 0x6f, - 0xd1, 0x24, 0x9e, 0xbd, 0x0c, 0xc5, 0xd5, 0xf6, 0x38, 0x64, 0x6e, 0xcd, 0x03, 0x87, 0x99, 0x47, 0x13, 0x41, 0xe1, - 0xde, 0xc0, 0x16, 0x60, 0xb0, 0x93, 0xb3, 0x6a, 0x94, 0x20, 0xac, 0xb9, 0x09, 0x10, 0x67, 0x32, 0x0a, 0x21, 0x95, - 0x0d, 0x3f, 0xb0, 0x96, 0xe6, 0x3b, 0xe0, 0xb9, 0xf9, 0x36, 0xc3, 0x40, 0x88, 0xda, 0x46, 0x48, 0x01, 0x79, 0xf5, - 0xda, 0x44, 0x08, 0x10, 0x03, 0x82, 0x0b, 0xfa, 0xcb, 0x5e, 0x0f, 0x61, 0x2e, 0xaf, 0xcb, 0x3d, 0x21, 0xea, 0x3a, - 0x58, 0x8f, 0xc8, 0x78, 0xd3, 0x15, 0xfe, 0xeb, 0xee, 0x8e, 0x12, 0x29, 0x14, 0xcb, 0x44, 0xf2, 0x23, 0xca, 0x23, - 0xc6, 0x11, 0xf2, 0xe8, 0x04, 0x1f, 0xbb, 0xc2, 0xa0, 0x3b, 0x54, 0x5a, 0x66, 0x7a, 0x53, 0x62, 0xab, 0x1d, 0x7b, - 0x14, 0x6c, 0x26, 0x4b, 0x0d, 0x9f, 0x23, 0x4a, 0xd7, 0x3e, 0x8c, 0x6b, 0x27, 0xff, 0xb1, 0xb3, 0xcd, 0x53, 0xb3, - 0x8f, 0x88, 0xbe, 0xc9, 0x64, 0x1c, 0x59, 0x98, 0x28, 0x0a, 0x7f, 0x08, 0x81, 0x97, 0x3a, 0xe2, 0xa9, 0xe1, 0x20, - 0xe6, 0x21, 0xd3, 0x64, 0xe4, 0x7a, 0x40, 0x5f, 0x68, 0x72, 0xb4, 0x74, 0x39, 0xa6, 0x07, 0x0a, 0x44, 0x75, 0x6c, - 0x47, 0x88, 0xcb, 0xb4, 0x89, 0x58, 0x4e, 0xab, 0x2e, 0x47, 0x45, 0x66, 0x9d, 0xa7, 0x7c, 0x92, 0x20, 0x06, 0x6e, - 0x52, 0xd4, 0xef, 0x1c, 0x87, 0x76, 0x51, 0x70, 0xfb, 0x4c, 0x25, 0x9c, 0x8d, 0x1a, 0xba, 0x2f, 0xc3, 0xf7, 0xa2, - 0x59, 0x34, 0x80, 0x6c, 0xc0, 0xd7, 0xfa, 0x2b, 0x28, 0x16, 0x0a, 0xec, 0xa6, 0x34, 0x53, 0xb6, 0x7e, 0x5d, 0xc3, - 0x6c, 0xeb, 0xfe, 0x40, 0xa1, 0x35, 0x2d, 0x34, 0xc6, 0xd4, 0xa7, 0xc2, 0xb7, 0x76, 0x63, 0x88, 0xc9, 0xc9, 0xcd, - 0x46, 0x1e, 0x83, 0x75, 0x98, 0x75, 0x8f, 0xb1, 0x39, 0x89, 0x7f, 0xa9, 0xcf, 0x5c, 0x10, 0x1e, 0x59, 0xc9, 0x82, - 0xbf, 0xd0, 0xcd, 0x60, 0xd3, 0x78, 0x97, 0xfe, 0x8e, 0x35, 0x4d, 0x98, 0xac, 0x49, 0x2b, 0x18, 0x86, 0xa4, 0x76, - 0x53, 0xa5, 0x75, 0xf2, 0x27, 0x17, 0x05, 0x42, 0x6a, 0xe2, 0x56, 0x54, 0x76, 0x32, 0x5a, 0x4a, 0xa4, 0x1b, 0x7b, - 0xdf, 0xfc, 0xbc, 0x3e, 0xea, 0xca, 0x5f, 0xcc, 0x10, 0x06, 0xf4, 0x0b, 0xa9, 0xbe, 0x57, 0x89, 0xe3, 0x57, 0x6d, - 0xad, 0x68, 0x6d, 0xcc, 0x67, 0x01, 0x13, 0xeb, 0x9e, 0x42, 0x2f, 0x56, 0x26, 0xf9, 0xbd, 0xc3, 0x3c, 0xd3, 0x78, - 0x24, 0xfb, 0x48, 0x4e, 0x31, 0x7f, 0x0c, 0x68, 0xfc, 0x1b, 0x8a, 0xec, 0x89, 0x81, 0x06, 0xd5, 0xa3, 0xa1, 0x5c, - 0x07, 0xe0, 0x10, 0x43, 0x13, 0x51, 0x1f, 0x68, 0xc7, 0x70, 0x47, 0x73, 0x81, 0xd4, 0x53, 0x2c, 0xd0, 0xc4, 0x73, - 0x64, 0x13, 0x93, 0x93, 0xb1, 0x0b, 0x70, 0x05, 0x6e, 0x59, 0xcf, 0x70, 0xb1, 0xf7, 0xdb, 0x45, 0x48, 0xa9, 0xa9, - 0xc0, 0x85, 0xc7, 0xaa, 0x09, 0xe0, 0x29, 0xd5, 0x44, 0x53, 0x43, 0xaa, 0x1f, 0x3a, 0x01, 0xfb, 0xc5, 0x49, 0x63, - 0x6a, 0x4d, 0x33, 0xca, 0xf2, 0x75, 0xe0, 0xa5, 0x24, 0x6b, 0xa2, 0x42, 0xdf, 0xe0, 0x94, 0x23, 0x10, 0xef, 0xf0, - 0xab, 0xcb, 0xdb, 0x49, 0x7a, 0x5b, 0xe8, 0x63, 0x93, 0x01, 0x86, 0xe1, 0x73, 0x84, 0x5f, 0xec, 0xb0, 0xb3, 0x75, - 0xe3, 0x3f, 0x26, 0x48, 0xc6, 0x8b, 0xc2, 0xdf, 0x1a, 0x2f, 0x48, 0x47, 0x35, 0x09, 0xf1, 0x0f, 0x45, 0xb7, 0x4f, - 0x18, 0x9d, 0x04, 0x75, 0xf6, 0xe5, 0xb2, 0x71, 0x61, 0x55, 0xd0, 0x68, 0x9f, 0x1b, 0x56, 0xb3, 0xe5, 0xfb, 0x9f, - 0xff, 0x22, 0xf7, 0x63, 0xa9, 0x71, 0xe2, 0x51, 0x6b, 0x5c, 0xb7, 0x72, 0xc7, 0x77, 0xba, 0xb3, 0xde, 0x29, 0xe7, - 0xcd, 0xdc, 0xf4, 0x0d, 0x4a, 0xf8, 0x67, 0xbe, 0xab, 0x08, 0x36, 0x9e, 0xc0, 0x56, 0xa4, 0x96, 0xef, 0xdc, 0x1c, - 0xe4, 0xe8, 0x6d, 0xd3, 0x60, 0xa3, 0x73, 0xd0, 0x0b, 0xf2, 0x04, 0x49, 0xca, 0x0f, 0xf9, 0x77, 0x09, 0xe3, 0x6c, - 0x3b, 0xab, 0xf3, 0x68, 0x15, 0xf1, 0xd8, 0xbb, 0x1c, 0x2e, 0xec, 0x10, 0xa5, 0xcb, 0x07, 0x57, 0x57, 0x53, 0x6b, - 0x99, 0x2a, 0xeb, 0xe9, 0xcc, 0xcc, 0x58, 0x60, 0xe2, 0x4c, 0x96, 0x21, 0x82, 0x1e, 0x21, 0x11, 0xa3, 0xef, 0x5d, - 0x30, 0x00, 0xc7, 0xd6, 0xea, 0x6b, 0x22, 0x68, 0x0b, 0x8a, 0x66, 0x11, 0xbd, 0x18, 0x9e, 0x0a, 0xaf, 0x33, 0x60, - 0xcb, 0x15, 0xcf, 0x4b, 0xa8, 0x1a, 0xb2, 0x86, 0xc9, 0x7e, 0x9f, 0x26, 0x7e, 0xb0, 0xcf, 0xe7, 0x16, 0x6a, 0x2b, - 0x33, 0xea, 0x27, 0x5c, 0xb3, 0xd4, 0xb9, 0xa0, 0xd9, 0xaf, 0x69, 0xaf, 0x60, 0xe6, 0xc9, 0x36, 0x97, 0x5f, 0xf7, - 0xe5, 0x70, 0x6a, 0x9e, 0x41, 0x95, 0xb7, 0x09, 0x4b, 0xe8, 0x8f, 0xa9, 0x46, 0x3c, 0xb2, 0xd1, 0x96, 0x55, 0x4b, - 0x51, 0x1d, 0x8b, 0x24, 0x8a, 0x8c, 0x9d, 0x05, 0xce, 0xd0, 0x0b, 0x89, 0x67, 0xb3, 0x06, 0x13, 0x26, 0x37, 0xb3, - 0x78, 0xa7, 0x30, 0x57, 0xc2, 0x49, 0x2c, 0xb2, 0x08, 0x45, 0xda, 0x37, 0xc3, 0xcd, 0x90, 0x9f, 0xda, 0xdc, 0x8e, - 0x84, 0x2a, 0x8f, 0xf8, 0xcf, 0x82, 0x4b, 0x4c, 0xa4, 0x02, 0x95, 0xf8, 0xdc, 0x77, 0xc4, 0x12, 0x49, 0xaa, 0x28, - 0x45, 0x41, 0xbd, 0x4c, 0xfe, 0xb2, 0x79, 0x69, 0x4a, 0x63, 0x77, 0x04, 0xee, 0x1e, 0xfa, 0x58, 0x49, 0xdc, 0x71, - 0xcc, 0x64, 0x67, 0x01, 0xd8, 0xa3, 0xcb, 0x0d, 0x7f, 0x8e, 0x01, 0x97, 0x47, 0xe7, 0x3d, 0x81, 0x60, 0x0f, 0x77, - 0xf0, 0xbd, 0xce, 0xa5, 0x8e, 0x33, 0x12, 0x11, 0x0b, 0xce, 0x90, 0xc5, 0x93, 0x37, 0x00, 0x24, 0xe7, 0x1f, 0xe2, - 0xe7, 0x05, 0xad, 0x2f, 0x80, 0x2a, 0x1c, 0x15, 0x80, 0xd8, 0x21, 0xc1, 0xa2, 0x0b, 0xef, 0x64, 0xe6, 0xb5, 0x66, - 0xc7, 0xeb, 0x0b, 0xfa, 0xeb, 0x97, 0xb9, 0x7b, 0x72, 0x52, 0x12, 0x46, 0x9c, 0x61, 0xf6, 0x83, 0xa0, 0x44, 0xf5, - 0x7c, 0x98, 0x10, 0x46, 0x66, 0x4b, 0xbc, 0xb8, 0x69, 0x10, 0xe0, 0xf6, 0x11, 0x62, 0x26, 0xdb, 0xa5, 0x1c, 0x93, - 0xaf, 0x9e, 0x71, 0x4e, 0xcd, 0x19, 0x42, 0xd1, 0x40, 0xb7, 0x96, 0x40, 0xac, 0x73, 0x28, 0xa3, 0xa1, 0x34, 0xe5, - 0xcf, 0xe5, 0x08, 0x6a, 0x1d, 0xfb, 0xc9, 0x64, 0x68, 0xb7, 0xc1, 0xdd, 0x0f, 0x48, 0x91, 0xc2, 0x3d, 0x1a, 0x38, - 0x61, 0xbc, 0x5a, 0x5c, 0x32, 0xcb, 0x6c, 0x79, 0x24, 0x5b, 0xc9, 0xee, 0x07, 0xc1, 0xf0, 0xf9, 0x94, 0x70, 0x31, - 0x4b, 0x47, 0x37, 0x64, 0x15, 0x5c, 0x16, 0xeb, 0xfd, 0xb3, 0xbf, 0xeb, 0xba, 0xc9, 0xc8, 0x6d, 0x93, 0x8c, 0x0d, - 0xe5, 0x78, 0x5c, 0x41, 0xda, 0x90, 0xd7, 0xc3, 0x20, 0x8d, 0x34, 0x15, 0x42, 0x67, 0xd6, 0x0f, 0xf7, 0x87, 0x78, - 0xbc, 0x98, 0xab, 0xb3, 0x05, 0x18, 0xb4, 0x71, 0x07, 0x4e, 0x59, 0x86, 0x25, 0x31, 0x21, 0x09, 0x1b, 0x1e, 0x80, - 0xa9, 0xd6, 0xf7, 0xa2, 0x1c, 0xff, 0x2e, 0xd9, 0xaa, 0x41, 0xa6, 0xe7, 0x06, 0xcd, 0xcf, 0xd2, 0x78, 0x30, 0x0a, - 0x3f, 0x89, 0x39, 0x9c, 0x71, 0x98, 0x23, 0x44, 0x65, 0x8e, 0x7e, 0x83, 0x41, 0xcf, 0xfd, 0xb4, 0x34, 0xff, 0x6c, - 0xe3, 0xfc, 0x51, 0x19, 0xcd, 0xb3, 0xa5, 0xe9, 0xb3, 0x05, 0xe3, 0xde, 0x96, 0xb4, 0x49, 0x77, 0x16, 0xc5, 0x7f, - 0x51, 0x1d, 0x3e, 0xde, 0x61, 0x12, 0xf5, 0xc0, 0x95, 0x04, 0x37, 0xcd, 0x09, 0x1f, 0xef, 0xd4, 0x89, 0x79, 0x48, - 0x88, 0xcc, 0x8e, 0x91, 0xd1, 0xd6, 0x98, 0xda, 0xad, 0x60, 0x71, 0xe9, 0x45, 0x45, 0xb0, 0x93, 0x0c, 0x1b, 0xa6, - 0xbb, 0x1d, 0xaf, 0xb4, 0x3b, 0x48, 0x08, 0x37, 0xae, 0xb6, 0x9b, 0x1a, 0x2d, 0xe6, 0xb4, 0x80, 0x52, 0x12, 0x29, - 0x89, 0x66, 0xd3, 0x38, 0x32, 0xad, 0xe8, 0xe7, 0x05, 0x95, 0xdc, 0x2a, 0xde, 0xfc, 0xda, 0x19, 0x4e, 0x54, 0x49, - 0x4d, 0x49, 0x4d, 0x5d, 0x62, 0xd2, 0x33, 0x60, 0xfe, 0x77, 0xc6, 0x4c, 0x28, 0x54, 0x6e, 0x5c, 0x79, 0x46, 0xc9, - 0x2f, 0x87, 0x6a, 0x27, 0x53, 0x3a, 0xf3, 0x5c, 0x7f, 0x97, 0xd6, 0x3a, 0x17, 0xce, 0x38, 0x74, 0xc3, 0x1b, 0xdf, - 0x16, 0x6d, 0x9e, 0xbf, 0x80, 0xbf, 0x75, 0x4c, 0x96, 0x24, 0xa8, 0x99, 0x3b, 0x5f, 0xca, 0x4e, 0xad, 0xb9, 0xb1, - 0x26, 0xcb, 0xed, 0x54, 0x9b, 0x73, 0xb5, 0xc2, 0xd3, 0x1b, 0x35, 0xa9, 0x22, 0x46, 0xd3, 0xc0, 0x42, 0x19, 0xd2, - 0x79, 0x16, 0xb4, 0xd4, 0xf2, 0xf3, 0x29, 0xa7, 0x0d, 0x12, 0xce, 0xa9, 0x00, 0x3b, 0x13, 0x45, 0x2e, 0x3e, 0xc3, - 0xbd, 0x69, 0xfa, 0x15, 0xec, 0xaf, 0x94, 0xcc, 0xf9, 0xd3, 0xb3, 0x39, 0x79, 0x7a, 0x3a, 0xa7, 0x4f, 0xef, 0x9c, - 0x6d, 0xb0, 0x9f, 0x73, 0xb1, 0xcb, 0x81, 0x45, 0x49, 0x92, 0xa7, 0xe3, 0xca, 0x8d, 0xe1, 0xdc, 0x99, 0x9c, 0x47, - 0xa6, 0xea, 0x64, 0x83, 0x49, 0x99, 0xd0, 0xea, 0x89, 0xb6, 0xc4, 0xd8, 0x34, 0x81, 0x60, 0x97, 0xfe, 0x98, 0xb5, - 0xed, 0x17, 0x77, 0x49, 0x0a, 0xb5, 0xa5, 0xb5, 0xe9, 0x71, 0x14, 0x52, 0xf3, 0x4b, 0x5b, 0x4f, 0x89, 0x73, 0xe7, - 0xc7, 0x2c, 0x3a, 0x88, 0xa7, 0xd5, 0xb1, 0xba, 0x13, 0x81, 0x29, 0xd7, 0x86, 0x78, 0xb3, 0x35, 0x10, 0xd9, 0xf3, - 0x16, 0xce, 0xca, 0x1f, 0x5a, 0x60, 0x77, 0x42, 0x08, 0x13, 0x81, 0xca, 0x58, 0x28, 0xad, 0x24, 0xb0, 0x0a, 0x7c, - 0x94, 0xaa, 0xd9, 0xec, 0xb4, 0xf8, 0x3e, 0x84, 0x7c, 0x8e, 0x9b, 0x10, 0x4e, 0x00, 0x79, 0x3d, 0x03, 0x75, 0x15, - 0xa2, 0x40, 0x33, 0x03, 0x48, 0xf8, 0x21, 0x79, 0x7c, 0x02, 0xf3, 0xc7, 0x74, 0xf9, 0x56, 0xad, 0xdc, 0x41, 0x3d, - 0x9f, 0x4b, 0x62, 0xe5, 0xa6, 0x9a, 0x14, 0x17, 0x25, 0xb1, 0x92, 0x58, 0xb4, 0xf0, 0xca, 0x15, 0xeb, 0x2e, 0xbd, - 0xe3, 0x37, 0x6c, 0x4b, 0xcf, 0x17, 0xf7, 0x31, 0xae, 0x40, 0xd5, 0xa8, 0x86, 0x6d, 0xfe, 0x04, 0x4c, 0x4d, 0x2f, - 0x12, 0xd8, 0x62, 0xb3, 0xd8, 0x9c, 0x81, 0x8e, 0xec, 0xa3, 0xec, 0x49, 0x99, 0x4a, 0x16, 0xa8, 0xe4, 0x5a, 0x29, - 0xac, 0xb6, 0x66, 0x51, 0x9b, 0x28, 0xef, 0xb9, 0x43, 0xeb, 0x93, 0x5e, 0x66, 0x0a, 0xdb, 0x43, 0x44, 0x9f, 0xd1, - 0x73, 0x1f, 0xd3, 0xe2, 0x7b, 0x40, 0x83, 0xb6, 0x14, 0x8c, 0x4c, 0x71, 0x68, 0x4f, 0x06, 0x94, 0x26, 0x4b, 0xf0, - 0xd0, 0x40, 0x15, 0x36, 0xe4, 0x33, 0x1c, 0xb0, 0xfd, 0x98, 0x46, 0x1b, 0x2b, 0x2a, 0xb1, 0x87, 0x68, 0x37, 0x07, - 0xdf, 0x95, 0x0e, 0x78, 0x47, 0xa6, 0xb8, 0x19, 0xde, 0xec, 0xc2, 0xdb, 0xb2, 0x50, 0xf7, 0xe3, 0x60, 0x87, 0x08, - 0x43, 0xd9, 0x14, 0x90, 0x9e, 0xf7, 0x9a, 0x42, 0x91, 0xe3, 0x5b, 0xcb, 0x27, 0xaa, 0x37, 0x48, 0x17, 0x4d, 0x80, - 0x3a, 0x18, 0xf5, 0xc0, 0x4f, 0x08, 0x72, 0x40, 0x65, 0xf4, 0xe1, 0x8a, 0xb6, 0xb8, 0xfe, 0x3c, 0x0d, 0x01, 0x59, - 0x5a, 0x91, 0x66, 0x07, 0x4c, 0x23, 0x17, 0x0d, 0x75, 0xdf, 0xc4, 0x32, 0x01, 0x48, 0xba, 0x78, 0x35, 0x12, 0x99, - 0x00, 0xb6, 0xc0, 0x8e, 0xcd, 0x63, 0x37, 0x7c, 0x5d, 0x9f, 0x0c, 0x18, 0x5a, 0x76, 0xbd, 0x7d, 0xb2, 0xfa, 0x68, - 0x7d, 0xae, 0xa9, 0x5e, 0x71, 0x5c, 0x14, 0x4b, 0xa6, 0x8a, 0x3a, 0x9f, 0x6c, 0x90, 0x00, 0x6b, 0x73, 0x39, 0x1e, - 0xe8, 0x20, 0x83, 0x1e, 0x9b, 0x54, 0x39, 0x71, 0xed, 0x98, 0xfd, 0xfa, 0xe2, 0x98, 0x51, 0x6b, 0x4e, 0x1f, 0x48, - 0x98, 0xda, 0x49, 0x84, 0xba, 0x63, 0xe5, 0x1b, 0x66, 0x34, 0x0b, 0xc2, 0x7e, 0xb0, 0xc9, 0xc6, 0x1a, 0x36, 0x7f, - 0x9c, 0xb2, 0xb9, 0x81, 0x86, 0xc9, 0x0f, 0x50, 0x07, 0xe2, 0x62, 0xc0, 0xc5, 0xdb, 0x48, 0xc6, 0xcc, 0xbf, 0xe3, - 0xbe, 0x57, 0x4a, 0x69, 0xd4, 0xf1, 0xa5, 0xd4, 0xf0, 0xf6, 0x7e, 0xe9, 0xff, 0x78, 0xf6, 0x21, 0x3f, 0x14, 0xa8, - 0x50, 0x85, 0xb4, 0x34, 0x89, 0x7a, 0xbe, 0x83, 0xd8, 0xf6, 0xbd, 0x16, 0x69, 0xc5, 0x22, 0x52, 0x1e, 0x01, 0x0e, - 0xe1, 0xf0, 0x5e, 0xb3, 0x89, 0x11, 0xdf, 0x9a, 0x97, 0x56, 0x69, 0x4b, 0xb4, 0xd6, 0x40, 0xbc, 0x8b, 0x56, 0x93, - 0x38, 0xd3, 0x23, 0x1d, 0x3b, 0x53, 0xdb, 0x29, 0x8a, 0xde, 0x65, 0x83, 0xad, 0xe6, 0x6a, 0xeb, 0x77, 0x56, 0xf4, - 0x21, 0xac, 0x4e, 0x78, 0x7d, 0x2d, 0x2a, 0x8d, 0xcd, 0xc4, 0x09, 0x62, 0xdf, 0x7d, 0xc6, 0x4c, 0x93, 0x08, 0x40, - 0x59, 0x71, 0x59, 0x86, 0x25, 0x52, 0x84, 0x1d, 0xd0, 0x49, 0x34, 0x60, 0x62, 0xce, 0x70, 0x6c, 0xc4, 0x9e, 0x67, - 0xcd, 0xad, 0x72, 0x25, 0x94, 0x41, 0x99, 0xb4, 0x6e, 0xbb, 0xdd, 0x0c, 0xbe, 0xf7, 0x1d, 0x50, 0xcb, 0xb9, 0x72, - 0x06, 0xc7, 0x52, 0xc3, 0xc5, 0x17, 0xc0, 0xc8, 0xad, 0x4a, 0x33, 0x02, 0x2c, 0xd5, 0x39, 0x4b, 0xb7, 0xa7, 0xde, - 0x69, 0x4b, 0xca, 0x89, 0xc3, 0xec, 0xf1, 0xbc, 0x2a, 0x7b, 0x02, 0xed, 0xe7, 0xbd, 0xe7, 0x8d, 0xaa, 0x55, 0xfe, - 0x7a, 0x6d, 0x20, 0xa5, 0xa0, 0xd9, 0x8c, 0xa5, 0x9e, 0xac, 0x65, 0xb9, 0xa9, 0x81, 0xbb, 0xe4, 0xa2, 0x73, 0x07, - 0xb6, 0x66, 0x8d, 0xe9, 0xc8, 0x32, 0xfa, 0x57, 0xb0, 0xc3, 0x37, 0xb0, 0x16, 0x97, 0x40, 0xe6, 0x6f, 0x8c, 0xef, - 0x84, 0xbc, 0x52, 0x3e, 0xd2, 0xf9, 0x19, 0xa3, 0xae, 0xc2, 0x54, 0x91, 0x70, 0xbd, 0xd5, 0x5a, 0xad, 0x06, 0x0d, - 0xd3, 0xf2, 0x89, 0x11, 0x1f, 0x35, 0xb4, 0xda, 0xea, 0x6d, 0xbf, 0x56, 0x4b, 0x63, 0x3a, 0x3f, 0x4f, 0xae, 0x94, - 0x78, 0xfb, 0x65, 0x89, 0xb9, 0xc2, 0xbf, 0x4d, 0x39, 0x46, 0xdf, 0xc3, 0xaf, 0x1b, 0x7e, 0x90, 0x79, 0x81, 0x48, - 0xaa, 0x71, 0x85, 0x71, 0x4c, 0x7e, 0x9a, 0x55, 0x23, 0x66, 0x8a, 0xf0, 0x83, 0x53, 0x07, 0x56, 0x37, 0x59, 0x1e, - 0x3a, 0x17, 0xa1, 0x02, 0x88, 0x3d, 0x8d, 0x9d, 0x77, 0x61, 0xc9, 0x98, 0x8a, 0x04, 0xc2, 0xb8, 0x42, 0x7b, 0x4a, - 0x30, 0x76, 0xcb, 0xa8, 0x76, 0xd5, 0xbb, 0x05, 0xf3, 0x9a, 0x86, 0x08, 0x98, 0xc1, 0x3b, 0xd0, 0xbc, 0x99, 0x6d, - 0x36, 0xe8, 0x9c, 0xd8, 0x51, 0x81, 0x3d, 0x20, 0x33, 0xde, 0xe1, 0xee, 0x37, 0x33, 0xe0, 0x82, 0x6b, 0xd8, 0x9e, - 0x87, 0x76, 0xa3, 0x1b, 0xae, 0x3c, 0x94, 0x77, 0x65, 0xc4, 0xd9, 0x02, 0xcb, 0xd7, 0xc8, 0x56, 0xac, 0xab, 0x9e, - 0xa0, 0xee, 0x81, 0x64, 0x6f, 0xdf, 0x5c, 0xf7, 0x76, 0x17, 0x0d, 0x82, 0x46, 0x77, 0x1b, 0xc0, 0xee, 0x60, 0xc1, - 0xbb, 0xd5, 0xd3, 0xf1, 0xc4, 0x01, 0x40, 0xf6, 0x64, 0x3f, 0x08, 0x2b, 0x74, 0xa7, 0xdb, 0x5f, 0xbb, 0xa1, 0x2c, - 0x68, 0x83, 0xa6, 0x3c, 0x86, 0xb6, 0x09, 0x23, 0x62, 0xc8, 0xae, 0x4b, 0x9e, 0x75, 0x73, 0x5f, 0x08, 0x17, 0xf0, - 0x88, 0x03, 0xb6, 0x43, 0x5d, 0x10, 0x0c, 0x07, 0x24, 0xe4, 0x5c, 0x88, 0xbf, 0x4d, 0x43, 0xcd, 0x32, 0xee, 0x36, - 0x1b, 0x62, 0x37, 0xa9, 0xe8, 0x0f, 0x9a, 0xc2, 0x9b, 0x6b, 0x2b, 0xc7, 0x0a, 0xc9, 0x7c, 0xe4, 0x5c, 0xed, 0x67, - 0xcd, 0x5c, 0x77, 0xa7, 0x6c, 0xcd, 0x98, 0x97, 0x3a, 0xcc, 0x8a, 0x78, 0xb7, 0x69, 0xe0, 0x59, 0xff, 0x16, 0xd6, - 0x38, 0xb1, 0xa9, 0x29, 0x8f, 0x63, 0x8e, 0x76, 0xd6, 0xd3, 0xa9, 0x65, 0x5f, 0xfd, 0xb5, 0x4d, 0x4b, 0xf5, 0xd9, - 0x18, 0x76, 0x61, 0xe5, 0xfc, 0x19, 0xa2, 0xc2, 0x96, 0x32, 0x99, 0x6a, 0x12, 0xc3, 0x20, 0x30, 0x5a, 0x74, 0x7b, - 0x0b, 0xd5, 0xb0, 0x8b, 0x1a, 0x75, 0x6d, 0xcd, 0xba, 0x5b, 0x13, 0xf6, 0xdf, 0xcd, 0x7c, 0xad, 0xaa, 0xaf, 0xa6, - 0x51, 0xa2, 0xe0, 0x74, 0x38, 0x58, 0xcb, 0xdd, 0x7f, 0x14, 0x79, 0x33, 0xc3, 0x58, 0x1c, 0x88, 0x6a, 0xd1, 0xc2, - 0x55, 0x7a, 0xab, 0xcd, 0x8a, 0x08, 0xc9, 0xa9, 0x1d, 0xf5, 0x3f, 0x68, 0x00, 0xa9, 0xb9, 0x59, 0xa1, 0x6e, 0xce, - 0xb1, 0xe0, 0x18, 0x95, 0x3a, 0x67, 0x78, 0xca, 0x29, 0xf1, 0x90, 0x8a, 0x8e, 0x76, 0x39, 0xd1, 0x5a, 0xa3, 0x2d, - 0x47, 0x00, 0x02, 0xb9, 0xda, 0xb0, 0x4e, 0xa1, 0x77, 0x9b, 0xcc, 0x55, 0xa6, 0xc3, 0xcc, 0x54, 0x81, 0xf1, 0x37, - 0x2b, 0x73, 0x80, 0x94, 0x8b, 0x24, 0x66, 0x6e, 0x67, 0x68, 0x85, 0x01, 0x3a, 0x8c, 0x11, 0xf8, 0x76, 0xf2, 0x43, - 0xfd, 0x69, 0xd3, 0xb2, 0x88, 0x63, 0xc7, 0xe4, 0xec, 0xb5, 0x1d, 0x14, 0xb4, 0x6a, 0xbb, 0x37, 0xf1, 0x9a, 0x67, - 0x01, 0xed, 0x8b, 0x3f, 0x97, 0xde, 0x1e, 0x9e, 0xf8, 0xdc, 0x86, 0xac, 0x40, 0xea, 0x24, 0x6f, 0x6d, 0x65, 0x94, - 0xab, 0x9d, 0x4b, 0xa4, 0xfd, 0xf2, 0x98, 0x24, 0xdb, 0xc6, 0xbf, 0x47, 0x2e, 0xa5, 0x40, 0xf2, 0xf7, 0x5d, 0xbf, - 0x88, 0x6c, 0x31, 0x4b, 0x12, 0xa6, 0x7a, 0x4d, 0xf2, 0xf5, 0x32, 0xac, 0xe3, 0x36, 0x1d, 0xff, 0x59, 0x72, 0xc1, - 0xd3, 0x44, 0x48, 0xad, 0xb7, 0x55, 0xa8, 0x2d, 0x3a, 0xba, 0x85, 0x8b, 0xe7, 0x3c, 0x94, 0xa8, 0x20, 0x63, 0xb6, - 0x59, 0x77, 0xa9, 0x44, 0xa2, 0x16, 0x2c, 0x0b, 0xed, 0x76, 0x3d, 0x4e, 0x51, 0xeb, 0x00, 0xc9, 0x4e, 0x45, 0x5f, - 0x85, 0xa6, 0x32, 0xb6, 0x49, 0x2c, 0x17, 0x56, 0x62, 0x51, 0xb7, 0x97, 0x4a, 0xab, 0x59, 0xd1, 0x95, 0x97, 0x0b, - 0xa1, 0x7a, 0x07, 0xb0, 0x75, 0x9f, 0x7b, 0x37, 0x80, 0x6e, 0x54, 0x03, 0x37, 0x20, 0x03, 0x50, 0x6a, 0x0a, 0x95, - 0x9b, 0x46, 0x9c, 0x4a, 0xab, 0x4a, 0x31, 0x07, 0x24, 0x82, 0x33, 0xfa, 0x73, 0x80, 0x39, 0x5c, 0x23, 0x07, 0xb8, - 0x6a, 0x59, 0xb5, 0x65, 0xac, 0xad, 0xd3, 0xa7, 0xad, 0xc3, 0xcc, 0xca, 0xfe, 0x09, 0xf8, 0x2e, 0x3e, 0xa9, 0x1d, - 0xd9, 0xfe, 0x16, 0x47, 0x12, 0xa1, 0xd0, 0xf5, 0x81, 0xa1, 0x30, 0x43, 0x18, 0x66, 0x77, 0x17, 0x84, 0xe9, 0xf5, - 0xa5, 0x40, 0xc1, 0xc2, 0xcd, 0xb9, 0xd8, 0x71, 0xfc, 0xf4, 0x6e, 0xfc, 0x44, 0x10, 0x0e, 0xcd, 0x54, 0x08, 0x9f, - 0x4b, 0x93, 0xa2, 0x20, 0x67, 0x0a, 0x41, 0xe0, 0xc1, 0xb6, 0x2f, 0x51, 0xa3, 0x48, 0x48, 0xb2, 0xb8, 0x06, 0x9a, - 0x28, 0xaf, 0x12, 0x2e, 0x48, 0x5f, 0xb6, 0xe5, 0x60, 0x76, 0x0d, 0x5b, 0xb2, 0x1a, 0xde, 0x22, 0xf1, 0xa3, 0x65, - 0xde, 0x47, 0xc4, 0xa4, 0x7b, 0x69, 0x03, 0x2d, 0xd6, 0xb6, 0xe5, 0x5f, 0xf7, 0x80, 0x2b, 0x85, 0x03, 0x43, 0x1b, - 0xd9, 0xfa, 0x6a, 0xc3, 0x2e, 0xc9, 0xe2, 0xe6, 0x97, 0xf5, 0xf0, 0xf8, 0xc1, 0xd8, 0xf7, 0x1d, 0xdc, 0x2e, 0x88, - 0xd6, 0xe6, 0xfc, 0x86, 0x99, 0xd6, 0x82, 0xd5, 0x0d, 0xd4, 0x18, 0x0d, 0x2e, 0x95, 0x59, 0x6a, 0xcc, 0xbf, 0xbc, - 0x4b, 0x7d, 0x30, 0xe1, 0x28, 0xf1, 0x19, 0x24, 0xae, 0xe1, 0xfa, 0xf0, 0xf1, 0x9e, 0x49, 0xdf, 0x06, 0xa1, 0xc8, - 0xae, 0x62, 0xd9, 0x2e, 0x0a, 0x20, 0x39, 0xdc, 0x55, 0x53, 0x6d, 0x70, 0x40, 0x17, 0xa5, 0xa3, 0x21, 0x51, 0x06, - 0x4d, 0xec, 0x4b, 0x18, 0xef, 0x8b, 0x1e, 0xbb, 0x0d, 0xbb, 0x78, 0x45, 0xf2, 0xda, 0x6a, 0x2a, 0x52, 0xf6, 0xbc, - 0x22, 0xdf, 0x94, 0x6a, 0xf2, 0x11, 0x4d, 0xa3, 0xa7, 0xa5, 0xd7, 0x96, 0x7b, 0x94, 0x00, 0x74, 0xaf, 0xce, 0xef, - 0xde, 0x1e, 0x1d, 0xb2, 0xcd, 0x44, 0xbe, 0x79, 0x73, 0x3c, 0x5e, 0xde, 0x7f, 0xa9, 0x33, 0x39, 0xc2, 0x3a, 0x8e, - 0xaf, 0x7f, 0xbc, 0x6c, 0x1a, 0x6b, 0xd5, 0x0f, 0x6a, 0x60, 0xed, 0xa9, 0x67, 0x9a, 0xb3, 0xb0, 0x26, 0x98, 0x70, - 0xae, 0xc0, 0x39, 0xd3, 0x41, 0xc8, 0xb1, 0xfc, 0xeb, 0x27, 0x8d, 0xa9, 0x1b, 0x37, 0x28, 0xcf, 0x7a, 0x36, 0x56, - 0x86, 0xba, 0xac, 0x65, 0x67, 0xbe, 0xeb, 0x3c, 0xc3, 0xe7, 0x3d, 0xab, 0xf4, 0x4b, 0x6b, 0x81, 0xaf, 0x35, 0xbe, - 0x92, 0xb9, 0x4d, 0xf8, 0x73, 0xe0, 0xd4, 0x31, 0x33, 0x3e, 0x05, 0xa5, 0xee, 0x96, 0x34, 0x3a, 0x8c, 0xac, 0x83, - 0xae, 0xf3, 0x9f, 0x35, 0x22, 0xe8, 0x09, 0x11, 0x9a, 0x30, 0xd4, 0x21, 0x94, 0x63, 0xfd, 0x58, 0x45, 0x6e, 0xcf, - 0x7a, 0x83, 0xb6, 0x92, 0xcd, 0x14, 0x01, 0x53, 0x82, 0xef, 0xd7, 0x55, 0x0d, 0x6c, 0xdf, 0xf4, 0x6f, 0x0f, 0x9f, - 0xe5, 0xa6, 0x21, 0x68, 0xc0, 0xff, 0x8e, 0x2c, 0x1a, 0xd0, 0x1b, 0x2b, 0x6f, 0xb4, 0xec, 0x5b, 0x4b, 0x0e, 0x8c, - 0x2a, 0x49, 0x9b, 0xa7, 0x84, 0xa8, 0x32, 0xe7, 0x7a, 0x57, 0x88, 0xbe, 0xf4, 0x28, 0xc7, 0xd3, 0x14, 0x00, 0xa6, - 0x2b, 0x2d, 0x20, 0x2e, 0x28, 0x84, 0x16, 0x1c, 0xaa, 0x59, 0xc8, 0xf6, 0xf5, 0xec, 0x14, 0x12, 0x8c, 0xd6, 0x0b, - 0xd3, 0xda, 0x90, 0x28, 0x33, 0x73, 0xca, 0xa4, 0x74, 0x97, 0xda, 0x49, 0xc8, 0x83, 0xdf, 0xd2, 0xb2, 0x01, 0x18, - 0x31, 0x91, 0x7c, 0xee, 0x6c, 0x22, 0x4b, 0x9f, 0xcf, 0x81, 0xdb, 0xec, 0x9e, 0xf4, 0x4d, 0xad, 0x1b, 0x1b, 0xa7, - 0xc1, 0xfa, 0x23, 0xe4, 0x3c, 0x77, 0x23, 0x64, 0x6b, 0x1b, 0xb7, 0xdc, 0x97, 0xe8, 0x10, 0x7d, 0xa2, 0x5d, 0x4e, - 0xd8, 0x06, 0x0d, 0xe8, 0x33, 0x6e, 0x0d, 0x97, 0x40, 0x94, 0xc3, 0x20, 0x33, 0x95, 0x43, 0x71, 0xbf, 0xec, 0x11, - 0x6a, 0x34, 0x16, 0xa8, 0x81, 0x15, 0x3e, 0x62, 0x18, 0x45, 0x15, 0xec, 0x81, 0x7f, 0x74, 0x8c, 0xe9, 0xea, 0x3b, - 0xc9, 0x92, 0x37, 0x2d, 0x11, 0xed, 0x80, 0x01, 0xeb, 0xa0, 0xe2, 0x31, 0xb6, 0x1a, 0xa7, 0x34, 0x18, 0xba, 0x9e, - 0x7c, 0xee, 0xc8, 0xd8, 0x4c, 0x46, 0xda, 0x16, 0x70, 0x87, 0xb9, 0x9d, 0x4d, 0x82, 0x39, 0xd8, 0xb2, 0x71, 0x16, - 0x37, 0xae, 0x7d, 0x8d, 0x60, 0xe8, 0x04, 0xe9, 0x74, 0x67, 0xb4, 0x79, 0x91, 0xef, 0xf1, 0x3e, 0x96, 0x98, 0xd7, - 0xca, 0xe9, 0x0e, 0x23, 0x0c, 0x88, 0xb8, 0x8d, 0x74, 0xc1, 0xcc, 0x52, 0x5a, 0xcb, 0x54, 0x45, 0x94, 0x65, 0xbb, - 0x64, 0x31, 0x00, 0xa3, 0xc0, 0xfe, 0x58, 0x9e, 0xd7, 0xa0, 0xd1, 0xd3, 0xe1, 0xe6, 0x8a, 0x26, 0x2d, 0x4b, 0x33, - 0x34, 0x3c, 0x9b, 0x0e, 0x50, 0xe1, 0x9a, 0x58, 0x9d, 0x97, 0x30, 0x5e, 0x2c, 0x2d, 0x47, 0x7f, 0xdf, 0xa3, 0x17, - 0xf1, 0x34, 0x23, 0x84, 0x53, 0xb1, 0xd9, 0xdc, 0x00, 0xb1, 0x0f, 0x5e, 0x4c, 0x74, 0x40, 0x08, 0xc6, 0xce, 0x6a, - 0x0f, 0xa8, 0xc7, 0xef, 0x0d, 0xfa, 0x3e, 0x12, 0xbe, 0x09, 0x90, 0x99, 0x82, 0xf2, 0x44, 0xed, 0x53, 0x14, 0x91, - 0x83, 0x9f, 0x64, 0x95, 0x4d, 0x2d, 0xea, 0x24, 0x30, 0x3a, 0xe2, 0xe4, 0x2c, 0x83, 0xc2, 0x79, 0xf9, 0xa2, 0x03, - 0x9b, 0xcf, 0xd9, 0x60, 0x5a, 0x6c, 0x23, 0x3b, 0x65, 0x2b, 0x68, 0x71, 0x0d, 0xd0, 0x1d, 0x9b, 0x22, 0x8e, 0x09, - 0x32, 0x56, 0xf6, 0x76, 0x8d, 0x11, 0x1b, 0xac, 0x9b, 0x3a, 0xea, 0xfd, 0x54, 0xa3, 0x53, 0xea, 0x1e, 0x1f, 0x30, - 0x19, 0x82, 0x0a, 0xa1, 0x93, 0xa0, 0xe6, 0x21, 0xfd, 0xd1, 0xc8, 0x73, 0x6a, 0xa4, 0x4e, 0x79, 0x5c, 0x67, 0x48, - 0xd1, 0xd8, 0xf7, 0xd9, 0x93, 0x3d, 0x3a, 0x4a, 0x3c, 0xa9, 0x70, 0xa2, 0xab, 0xc5, 0x19, 0x46, 0xaf, 0x3d, 0xd8, - 0xcd, 0x56, 0x54, 0x24, 0xa3, 0x50, 0x0c, 0xed, 0x59, 0x1c, 0x55, 0xe9, 0x26, 0x09, 0xf9, 0x51, 0xcc, 0x70, 0x66, - 0xe7, 0x3c, 0xfa, 0xd0, 0xd8, 0x62, 0x40, 0x46, 0x81, 0xd0, 0x6e, 0x43, 0x8f, 0xb0, 0xb9, 0x0b, 0x7f, 0xc2, 0x2f, - 0xb7, 0x52, 0xb9, 0x54, 0x70, 0x9a, 0x2e, 0xbd, 0xf7, 0xbf, 0xec, 0xa8, 0x15, 0x37, 0xde, 0xda, 0x2a, 0x97, 0x28, - 0x17, 0x3b, 0xe7, 0x3f, 0x62, 0x8f, 0x4b, 0xd8, 0xb0, 0x05, 0x97, 0x0d, 0x5d, 0xa1, 0x52, 0x4a, 0x03, 0x47, 0x1e, - 0x88, 0xa4, 0xee, 0x6b, 0x38, 0xe2, 0x16, 0xd5, 0x9f, 0xf4, 0xfa, 0x60, 0x83, 0xd1, 0x31, 0xeb, 0xb5, 0xf8, 0x46, - 0xad, 0xd0, 0x85, 0x54, 0x51, 0x03, 0x97, 0x34, 0x5b, 0x30, 0x4d, 0x86, 0xc8, 0x26, 0x49, 0xdc, 0x3d, 0x9d, 0x61, - 0x95, 0x99, 0x5e, 0xf4, 0xdf, 0x2b, 0x11, 0xe9, 0x90, 0xd7, 0x5c, 0x69, 0xc2, 0x59, 0x46, 0xf5, 0xa3, 0x70, 0x1c, - 0xe3, 0xd8, 0x74, 0x27, 0x0c, 0xa0, 0xea, 0x30, 0x87, 0xfa, 0xc9, 0x8b, 0xad, 0xd1, 0x77, 0x6d, 0x24, 0x87, 0x86, - 0xbc, 0xe9, 0x10, 0xd0, 0x9f, 0xbf, 0x8b, 0x7a, 0xc0, 0x6d, 0x6d, 0x1c, 0xed, 0xbd, 0xb8, 0x68, 0x13, 0x41, 0xf0, - 0xc7, 0x53, 0xd1, 0xc1, 0x36, 0x5d, 0x62, 0xd8, 0x5c, 0x39, 0xfa, 0xcc, 0xb0, 0x5f, 0x56, 0x44, 0xcc, 0xea, 0x3d, - 0x15, 0xf2, 0xfa, 0x77, 0xff, 0x82, 0xd9, 0xd2, 0xac, 0x91, 0x6f, 0xce, 0xcb, 0xc1, 0xd8, 0xaa, 0x4b, 0xef, 0xc2, - 0x3f, 0x0b, 0xeb, 0x00, 0xa0, 0x72, 0x67, 0xbf, 0x17, 0xe2, 0xee, 0xba, 0x0a, 0xd1, 0x07, 0x53, 0x6a, 0x52, 0x3e, - 0xe4, 0x94, 0x8d, 0x25, 0x23, 0x4f, 0x99, 0xb5, 0xd4, 0x4e, 0x42, 0xe0, 0x6e, 0x02, 0x60, 0xfc, 0xaf, 0x4c, 0x8f, - 0x0b, 0x0b, 0x7d, 0xa7, 0x95, 0x42, 0xcc, 0x84, 0x6e, 0x46, 0xef, 0x73, 0x0c, 0xd8, 0x03, 0x44, 0x72, 0x52, 0xde, - 0x13, 0xcb, 0xaa, 0x27, 0xfe, 0x2b, 0xa2, 0x35, 0x6d, 0xc4, 0x1c, 0x28, 0x3f, 0x7e, 0xd8, 0x70, 0x23, 0xa3, 0xe0, - 0x41, 0x33, 0xc2, 0xf4, 0xef, 0x1c, 0xe2, 0xde, 0x70, 0x70, 0xf4, 0x04, 0x92, 0x9e, 0xb8, 0x79, 0x7b, 0x8e, 0xcd, - 0xfe, 0x53, 0x31, 0xd2, 0x01, 0xe9, 0x28, 0x81, 0x97, 0x0e, 0x0f, 0xb4, 0xac, 0x80, 0x2b, 0x85, 0x7b, 0x19, 0x9f, - 0x9e, 0x86, 0xf6, 0xfd, 0x2b, 0x67, 0xd0, 0x64, 0xe2, 0x25, 0x7a, 0x63, 0xd1, 0xe4, 0xe3, 0xc5, 0xe7, 0xc7, 0xa3, - 0x9e, 0xbf, 0xf3, 0xf6, 0xf1, 0xac, 0xe7, 0x32, 0x67, 0x96, 0x36, 0x24, 0x8e, 0x7f, 0xd8, 0xfa, 0xce, 0x81, 0x27, - 0xbb, 0x3f, 0xb8, 0x90, 0x22, 0xeb, 0x89, 0x18, 0xe7, 0x61, 0x4b, 0x91, 0x7c, 0x00, 0xe2, 0x52, 0xfb, 0x63, 0xf1, - 0xf2, 0x6a, 0xf7, 0x8b, 0xfe, 0x47, 0xf3, 0x9a, 0xd6, 0x64, 0x1f, 0x7c, 0x9d, 0x42, 0x55, 0xf7, 0x33, 0xba, 0xfb, - 0xf6, 0x23, 0xc8, 0x19, 0x9b, 0xa5, 0x89, 0x2f, 0xfe, 0xed, 0xe8, 0x79, 0xc2, 0xad, 0x85, 0x2a, 0x33, 0x4c, 0x4f, - 0xdd, 0x63, 0xa8, 0x14, 0xc9, 0xd2, 0xb2, 0x77, 0xe2, 0x9c, 0x0b, 0x74, 0xa6, 0x3f, 0x39, 0x42, 0xe8, 0xc7, 0x96, - 0x8b, 0x98, 0x22, 0xe6, 0xd7, 0x87, 0x02, 0x38, 0x4b, 0x82, 0x27, 0x10, 0x11, 0xe8, 0x6c, 0x45, 0xf9, 0x58, 0xa8, - 0xae, 0xb9, 0xb5, 0xcf, 0x57, 0x59, 0xe0, 0x66, 0x66, 0x33, 0xdd, 0xca, 0x0d, 0x7d, 0x74, 0x9a, 0x67, 0xb9, 0x41, - 0x1d, 0xc8, 0xd9, 0x06, 0x38, 0xb0, 0x7f, 0x2b, 0x64, 0x18, 0xd6, 0xb6, 0xdc, 0x1f, 0x89, 0xde, 0x18, 0x25, 0xef, - 0x10, 0x80, 0x91, 0x29, 0xda, 0xec, 0x4f, 0x27, 0xba, 0x90, 0x51, 0xbd, 0x3f, 0x73, 0xdf, 0xaf, 0xff, 0x4d, 0x2e, - 0xd9, 0xbb, 0xa4, 0xb5, 0xd0, 0x54, 0x16, 0xd5, 0xe5, 0x68, 0xf3, 0xbc, 0x1b, 0x79, 0xe9, 0xe5, 0x37, 0x3d, 0x52, - 0xe9, 0xf9, 0x87, 0x0e, 0xb6, 0xb4, 0xfc, 0x88, 0x4c, 0x3d, 0x49, 0x04, 0x72, 0xac, 0xcd, 0xf0, 0x6a, 0xee, 0x48, - 0x65, 0x02, 0xc7, 0x74, 0x4f, 0x46, 0xbe, 0x99, 0x33, 0x76, 0x2d, 0xe9, 0x04, 0xb0, 0x31, 0x2c, 0x9b, 0xaf, 0xb9, - 0x34, 0xcb, 0xac, 0x57, 0xf6, 0xec, 0x44, 0x78, 0xc1, 0xe1, 0x95, 0xd8, 0xa6, 0x90, 0xe6, 0x57, 0x13, 0x09, 0xdc, - 0xbc, 0xde, 0x17, 0x81, 0x5a, 0xe6, 0xd2, 0xb9, 0x68, 0x11, 0xe9, 0xca, 0xbc, 0x1c, 0x56, 0xa0, 0x4f, 0x7e, 0x6e, - 0x56, 0x51, 0xda, 0x4a, 0x59, 0xb9, 0xf2, 0x1c, 0xdf, 0xd0, 0xa4, 0xd8, 0x3b, 0xda, 0x53, 0xd9, 0x21, 0x1c, 0x89, - 0xc1, 0xcd, 0x5d, 0x52, 0x49, 0x99, 0xc5, 0xa9, 0x95, 0xa4, 0x7f, 0x49, 0x98, 0x61, 0x94, 0xe0, 0x20, 0x36, 0xff, - 0x88, 0x1b, 0x73, 0xcc, 0x21, 0x8d, 0xc9, 0x89, 0x86, 0x60, 0x34, 0x53, 0x88, 0x6e, 0x4a, 0xb7, 0x52, 0x27, 0xe2, - 0xd9, 0x8b, 0x15, 0x4e, 0x3b, 0x2f, 0x91, 0xe6, 0xa5, 0x3f, 0xc2, 0x61, 0x1f, 0xc8, 0x40, 0xa3, 0x30, 0x37, 0xc6, - 0xc0, 0xce, 0x6e, 0xd2, 0x36, 0x86, 0xab, 0xde, 0x40, 0x53, 0xb8, 0x79, 0x4f, 0xd7, 0xd2, 0xe7, 0x22, 0x99, 0x58, - 0xd2, 0xa3, 0x5d, 0x4c, 0xae, 0xb5, 0x54, 0x4f, 0xe8, 0x13, 0xe9, 0xbb, 0x99, 0x56, 0x8e, 0x3e, 0x48, 0x5a, 0x0a, - 0xe0, 0xe5, 0x28, 0x70, 0xca, 0xe5, 0x89, 0x5c, 0x93, 0xe3, 0xe0, 0x75, 0x66, 0x20, 0xf5, 0x07, 0x7e, 0x1d, 0x7a, - 0x72, 0x67, 0x3f, 0x68, 0xd3, 0xdf, 0x47, 0xaa, 0xc2, 0x2c, 0xea, 0x21, 0xd2, 0x0a, 0xac, 0xbb, 0xb7, 0xf5, 0xbd, - 0x8e, 0x4f, 0x1a, 0x9a, 0xb6, 0xf8, 0x02, 0xbd, 0x2b, 0x38, 0x42, 0x9b, 0x58, 0x48, 0x9e, 0x81, 0x4f, 0xf1, 0xb0, - 0xc9, 0x53, 0xe6, 0x6e, 0x47, 0xa4, 0xfe, 0xf7, 0xc7, 0xaa, 0x01, 0x7b, 0xc5, 0x43, 0x3d, 0x79, 0x8a, 0xd8, 0xaf, - 0x5a, 0x63, 0x46, 0x5a, 0xae, 0x79, 0xb7, 0xb8, 0xef, 0x3d, 0x9f, 0xe2, 0x81, 0x0e, 0x02, 0x77, 0x46, 0xcc, 0x8e, - 0x71, 0x7e, 0x6f, 0xf6, 0xfb, 0xde, 0xbb, 0x2e, 0x03, 0x8c, 0xda, 0x40, 0xf4, 0x41, 0x10, 0xdf, 0xa7, 0x03, 0xd6, - 0x9d, 0x03, 0xb3, 0x37, 0xa6, 0xc7, 0x6d, 0x12, 0x4e, 0x4b, 0x7d, 0x3c, 0x3e, 0x64, 0xe3, 0x83, 0x62, 0x54, 0x8a, - 0x3d, 0x0b, 0x52, 0x34, 0x01, 0x62, 0x0e, 0x29, 0xc9, 0x5e, 0xec, 0x03, 0x28, 0x62, 0x2e, 0x44, 0x2e, 0x9a, 0x83, - 0x1e, 0x10, 0x8c, 0x1c, 0x36, 0xd8, 0xfe, 0x23, 0xa2, 0x0e, 0x0f, 0x77, 0x58, 0x48, 0x99, 0xf3, 0x06, 0x97, 0x61, - 0xf8, 0x00, 0x98, 0x73, 0x57, 0x6f, 0xd1, 0x77, 0x7a, 0xc2, 0x9c, 0xde, 0x67, 0x99, 0x72, 0xab, 0xc8, 0x5d, 0x9c, - 0x32, 0xc2, 0xeb, 0x22, 0xad, 0x26, 0x46, 0xba, 0x3b, 0xb4, 0xc3, 0xaf, 0x20, 0x62, 0xfa, 0x52, 0x02, 0x5e, 0x22, - 0x3b, 0x10, 0x0b, 0xfe, 0xdc, 0x50, 0x15, 0x3b, 0xe5, 0x3d, 0x86, 0x5a, 0x78, 0x86, 0x5a, 0xd5, 0x49, 0x2a, 0xb8, - 0x3b, 0x4c, 0x52, 0xfa, 0xc7, 0x89, 0xfc, 0x58, 0xd1, 0xc4, 0x3e, 0x6d, 0xba, 0xab, 0xf8, 0x6d, 0xc5, 0x5e, 0x00, - 0x31, 0x57, 0xa5, 0x33, 0x55, 0x22, 0xf2, 0x75, 0x81, 0x76, 0x68, 0xd1, 0x9e, 0x25, 0x3b, 0x17, 0xd5, 0xff, 0x4d, - 0xb1, 0x23, 0xce, 0xec, 0xd0, 0x59, 0xc4, 0xef, 0x9c, 0x4a, 0x8c, 0xdf, 0x8d, 0x77, 0xee, 0x6b, 0xd3, 0x07, 0x69, - 0xf1, 0x57, 0x05, 0x85, 0x7e, 0x67, 0xe8, 0xd6, 0x93, 0xb5, 0xa4, 0xf5, 0x77, 0xa3, 0x91, 0xa4, 0xf5, 0xa8, 0x5c, - 0xde, 0x8e, 0x5c, 0x33, 0x5f, 0xe2, 0x54, 0xfb, 0x7c, 0x3a, 0xcd, 0x7e, 0x67, 0xd8, 0xd5, 0x8d, 0x1e, 0x34, 0xab, - 0x89, 0xbe, 0xf8, 0xa9, 0xaa, 0x5b, 0xfa, 0x4e, 0xc1, 0xe8, 0xfc, 0xf4, 0xd9, 0x98, 0x3b, 0x63, 0xb6, 0x86, 0x74, - 0x86, 0x31, 0x2f, 0xa2, 0xb1, 0xe7, 0xfa, 0x02, 0xc1, 0xad, 0x4b, 0xfb, 0x0e, 0xcc, 0xd2, 0xef, 0xc0, 0xa4, 0xb3, - 0x31, 0xc5, 0xfe, 0xcc, 0x8a, 0x60, 0xe0, 0xce, 0x5d, 0x8d, 0x8c, 0xe3, 0x2c, 0xf4, 0xd1, 0xb4, 0xe5, 0xbe, 0x88, - 0x91, 0xdb, 0x1c, 0xa7, 0xcf, 0x95, 0x9a, 0x91, 0xb0, 0x5f, 0x5c, 0x70, 0x66, 0x7d, 0xe7, 0x0b, 0x95, 0xb4, 0xd6, - 0x0a, 0xf8, 0xab, 0x54, 0xcf, 0xdd, 0xfa, 0xef, 0x83, 0x60, 0xdd, 0xb4, 0xc3, 0x62, 0x39, 0xa7, 0xe9, 0xa9, 0x2a, - 0x7b, 0x83, 0x27, 0x65, 0x80, 0x9c, 0x05, 0x74, 0x2f, 0xb7, 0x96, 0xbb, 0x09, 0x30, 0x7c, 0xe8, 0xf1, 0x5a, 0xff, - 0x40, 0x05, 0xf4, 0x84, 0x40, 0x6d, 0xbf, 0xc2, 0x79, 0xdc, 0x5e, 0x89, 0x8f, 0xbf, 0x57, 0x94, 0x9b, 0x2d, 0x8f, - 0x5f, 0x57, 0x54, 0x89, 0x7e, 0x1a, 0x81, 0x3b, 0x3f, 0x57, 0xb3, 0x30, 0x31, 0x9f, 0xce, 0x2d, 0xbf, 0x47, 0xc7, - 0xe6, 0x02, 0x5a, 0xee, 0x33, 0x42, 0x1a, 0xf3, 0x7f, 0x8e, 0x59, 0x96, 0xcc, 0x0a, 0xcd, 0xf2, 0x75, 0x80, 0x63, - 0x3a, 0x3c, 0xc5, 0x8d, 0xe7, 0x38, 0xa0, 0xd0, 0x0d, 0x4a, 0xbd, 0xdd, 0x02, 0xd5, 0xac, 0x00, 0x0b, 0x05, 0x85, - 0xf4, 0x23, 0x9a, 0x47, 0xd9, 0x11, 0x03, 0x46, 0xb6, 0xd5, 0x5f, 0x73, 0x6d, 0x91, 0x47, 0xad, 0xf6, 0x2b, 0xc2, - 0xbd, 0x3e, 0x89, 0x45, 0xff, 0x9d, 0x02, 0x04, 0xb1, 0x36, 0x64, 0x6f, 0x02, 0xa6, 0x11, 0xc5, 0x14, 0x05, 0x3f, - 0x0a, 0x92, 0x42, 0xa5, 0xec, 0x5d, 0xd8, 0x22, 0xcc, 0x5c, 0x6a, 0x49, 0x19, 0x35, 0xf1, 0xbc, 0x02, 0x74, 0xa4, - 0xff, 0xba, 0xf8, 0x2e, 0x7b, 0x7a, 0x30, 0x4a, 0xca, 0x3d, 0x22, 0x20, 0x41, 0x3d, 0x93, 0x95, 0x80, 0xfd, 0x16, - 0x62, 0xfc, 0x49, 0x50, 0x92, 0x26, 0x75, 0x17, 0xc1, 0xe9, 0x36, 0x64, 0x70, 0x19, 0xad, 0x35, 0x12, 0x34, 0x7c, - 0x77, 0x50, 0x06, 0x58, 0x15, 0x82, 0x97, 0xb8, 0xe4, 0xc7, 0xc0, 0x4c, 0x45, 0x77, 0xf8, 0x4b, 0xe8, 0xe3, 0x1d, - 0xd5, 0x79, 0xd9, 0x69, 0x5d, 0x7b, 0xb7, 0x61, 0x10, 0x86, 0x8d, 0xcf, 0x0c, 0x74, 0x64, 0xaf, 0x07, 0x6c, 0xca, - 0x94, 0x11, 0x1b, 0x70, 0x52, 0xae, 0xc8, 0x68, 0x9d, 0x5f, 0xb1, 0x7c, 0xb1, 0x67, 0xff, 0x3d, 0xcc, 0x21, 0x00, - 0x19, 0x8d, 0x23, 0x70, 0xa3, 0x06, 0x78, 0x48, 0x98, 0x12, 0x7e, 0x2c, 0x44, 0x29, 0x41, 0xfe, 0x2b, 0x35, 0xa0, - 0x80, 0x1c, 0xed, 0x71, 0x21, 0x69, 0x78, 0x0c, 0x53, 0x83, 0xc2, 0x47, 0x64, 0x28, 0x73, 0xb2, 0x40, 0x49, 0xb1, - 0x0e, 0x5a, 0xc5, 0xc8, 0x2c, 0x68, 0xfd, 0xd4, 0x91, 0xdf, 0xd5, 0xf5, 0x20, 0x8a, 0x9e, 0x2e, 0xc8, 0x43, 0x28, - 0x45, 0x28, 0x37, 0x33, 0xa1, 0xe6, 0x11, 0x16, 0xdd, 0x2e, 0x1b, 0xd0, 0xfa, 0x31, 0x8c, 0x9e, 0x3c, 0xba, 0x05, - 0x27, 0x97, 0xb1, 0x02, 0xeb, 0x62, 0x27, 0x0b, 0xea, 0x8f, 0x1e, 0xb8, 0x28, 0x37, 0xe6, 0xd4, 0x27, 0x0f, 0x5d, - 0xf0, 0x79, 0xba, 0x3e, 0xf6, 0x5e, 0x9e, 0x20, 0x35, 0x0b, 0xab, 0x75, 0x6c, 0x13, 0x9e, 0xb4, 0x38, 0x4d, 0xde, - 0xcd, 0x5f, 0x9e, 0x64, 0x13, 0xaf, 0x1c, 0x05, 0x36, 0x3d, 0xb3, 0x2a, 0xb6, 0x91, 0x9d, 0x2e, 0x1b, 0xfe, 0xe6, - 0x04, 0x9f, 0x67, 0x43, 0xe6, 0x78, 0x7e, 0x41, 0x37, 0xe2, 0xc3, 0x2c, 0x12, 0x72, 0x76, 0x5b, 0xc7, 0xec, 0x4e, - 0xb5, 0xcd, 0xbf, 0xd1, 0xb9, 0x7d, 0xec, 0xfb, 0xcc, 0x47, 0x2a, 0x4b, 0x17, 0x94, 0x84, 0xdd, 0xf1, 0x90, 0x74, - 0xb2, 0xc9, 0x82, 0x33, 0xa7, 0x01, 0xf7, 0x1a, 0xb9, 0x2c, 0xce, 0x6b, 0xa2, 0xb9, 0xb8, 0x5b, 0xc1, 0x96, 0x01, - 0x9c, 0xea, 0xcc, 0x45, 0x70, 0x55, 0x11, 0x38, 0x35, 0x35, 0x53, 0x45, 0xf1, 0xb8, 0x33, 0xdb, 0x2d, 0x2c, 0xd5, - 0x4f, 0xd1, 0xe2, 0xd2, 0xf0, 0xa2, 0xc4, 0xcc, 0x64, 0xcb, 0x4c, 0x81, 0x4c, 0xe7, 0x42, 0x9a, 0x93, 0x58, 0xe1, - 0xa0, 0x9f, 0xc5, 0x42, 0xb2, 0x5b, 0xeb, 0x61, 0x8f, 0x67, 0x55, 0x0d, 0x56, 0x18, 0x75, 0xb6, 0x5a, 0xa4, 0x13, - 0xa9, 0xd8, 0x3e, 0x50, 0x87, 0xc2, 0x7d, 0xc7, 0x41, 0xa7, 0x46, 0xca, 0xcb, 0x5f, 0x47, 0x6a, 0x78, 0xc4, 0x5f, - 0x1b, 0x77, 0x90, 0xb4, 0x6c, 0xd8, 0xd1, 0xe6, 0xb6, 0xb9, 0x0c, 0x8a, 0x51, 0xe3, 0xb0, 0x2a, 0x2d, 0xdd, 0x46, - 0xe4, 0x2b, 0xd4, 0x8c, 0xec, 0x9b, 0x30, 0x11, 0xb1, 0xa4, 0x87, 0x78, 0x8d, 0x84, 0x49, 0x4a, 0x1f, 0xc5, 0x16, - 0xe9, 0x85, 0xa2, 0x2b, 0xd3, 0x6e, 0xd3, 0x9d, 0xab, 0x38, 0x97, 0xe9, 0x29, 0x79, 0x16, 0x30, 0x85, 0x95, 0xe8, - 0x4a, 0x82, 0xc9, 0x98, 0x67, 0x6f, 0xfc, 0x94, 0xf4, 0xdc, 0x23, 0x21, 0x9a, 0x7d, 0xa1, 0xb4, 0x52, 0x3e, 0x89, - 0x11, 0x1f, 0xe9, 0xc8, 0x31, 0x7c, 0xe5, 0x65, 0xf8, 0xde, 0x56, 0x65, 0xf9, 0x6c, 0xe7, 0x33, 0x13, 0x65, 0x72, - 0x54, 0xed, 0x42, 0xda, 0x40, 0x6c, 0x0d, 0x10, 0xcf, 0xd2, 0xb1, 0x04, 0xa5, 0xd1, 0x63, 0xb0, 0xf3, 0x79, 0xb5, - 0x08, 0x42, 0x6d, 0x92, 0xee, 0x32, 0x37, 0x01, 0x2e, 0xc8, 0x51, 0x7a, 0x9b, 0xe8, 0xee, 0xfe, 0xcc, 0x01, 0xdd, - 0x7d, 0x33, 0x41, 0xa3, 0xd9, 0x65, 0x8b, 0xa0, 0xc4, 0xbf, 0x8b, 0xa6, 0xcd, 0x48, 0xa4, 0x42, 0xbc, 0x31, 0x1b, - 0xc0, 0x6c, 0xa6, 0x3d, 0x53, 0xe9, 0x40, 0xa4, 0xf8, 0x0d, 0x68, 0x23, 0x2b, 0xa1, 0x41, 0x20, 0x51, 0x3f, 0x8d, - 0x59, 0x13, 0x33, 0x3d, 0xce, 0x7f, 0x92, 0x3d, 0x27, 0x83, 0x04, 0x72, 0x25, 0xd8, 0x3d, 0x75, 0x46, 0x14, 0x67, - 0x3d, 0x69, 0xc5, 0xf6, 0xf4, 0x6b, 0x87, 0xad, 0x33, 0xfb, 0xe0, 0x5c, 0x68, 0xb1, 0x13, 0x41, 0x7f, 0xb9, 0x9d, - 0xe8, 0x47, 0x80, 0xc1, 0xd0, 0x15, 0xe6, 0x3f, 0x93, 0x5e, 0x78, 0xc5, 0x84, 0x61, 0xd7, 0x5d, 0xf5, 0x76, 0x78, - 0xec, 0x4c, 0x4a, 0xe6, 0x93, 0x9f, 0x07, 0xee, 0xbe, 0x1d, 0xda, 0x29, 0x63, 0x6e, 0x63, 0xe4, 0x13, 0x0c, 0x60, - 0xb6, 0xab, 0x1b, 0xd5, 0x8c, 0x8a, 0x48, 0x22, 0xa6, 0x36, 0x6e, 0x1c, 0xd3, 0x36, 0x3e, 0xad, 0xf7, 0xfe, 0xfb, - 0x2d, 0x3a, 0xa0, 0x8c, 0x4a, 0x13, 0xcf, 0x57, 0xe9, 0xc6, 0x41, 0xf7, 0x57, 0x1d, 0x93, 0xba, 0xf3, 0x7e, 0x2e, - 0xb4, 0xaa, 0x8d, 0xa8, 0xf3, 0x91, 0x76, 0xd0, 0x74, 0x7e, 0xa6, 0x11, 0xb8, 0xd6, 0x7f, 0xad, 0x06, 0x58, 0xf4, - 0x2a, 0x90, 0xa2, 0xab, 0x38, 0x76, 0xad, 0xd4, 0x5a, 0x78, 0x07, 0x5f, 0x25, 0xb9, 0x55, 0xf8, 0xab, 0x17, 0x96, - 0xa7, 0xf7, 0xc4, 0x3b, 0xbf, 0xcc, 0x85, 0xd2, 0xad, 0xcb, 0xc2, 0x27, 0xe5, 0xaf, 0x83, 0x53, 0x30, 0xbd, 0xa1, - 0x68, 0x8c, 0x94, 0x5d, 0xbc, 0x5f, 0xc8, 0x48, 0x28, 0x10, 0xff, 0x28, 0x18, 0x1a, 0xa5, 0x6d, 0xa9, 0x8e, 0xb1, - 0x7d, 0xac, 0xa6, 0x7c, 0x56, 0xbb, 0xac, 0xbd, 0x24, 0xe1, 0xe4, 0x75, 0xf0, 0x87, 0x1f, 0x71, 0xcd, 0x03, 0xac, - 0xb3, 0xd6, 0xbd, 0x70, 0xce, 0xeb, 0xe1, 0x03, 0xcd, 0x7c, 0x28, 0xb6, 0x27, 0x5a, 0x9f, 0xb0, 0xf5, 0x3c, 0x5b, - 0x70, 0xe7, 0x47, 0x15, 0x52, 0x0d, 0xd7, 0x19, 0x9f, 0x99, 0xfd, 0x7d, 0x18, 0xec, 0x07, 0xdd, 0xf9, 0xf8, 0x1d, - 0x9d, 0x83, 0xed, 0xcd, 0xc0, 0x22, 0xad, 0x73, 0xec, 0xc8, 0xb5, 0xc6, 0xe3, 0x3e, 0x05, 0x92, 0xc6, 0xea, 0x7a, - 0x75, 0xea, 0x84, 0xca, 0x37, 0x8a, 0xa0, 0x63, 0x27, 0xd1, 0xcd, 0x72, 0x11, 0x25, 0x12, 0xe4, 0x6f, 0x83, 0x42, - 0x31, 0x1c, 0x32, 0xe1, 0x51, 0xdc, 0x9b, 0x20, 0x30, 0xaf, 0x95, 0x52, 0x88, 0xd5, 0x8e, 0xae, 0x57, 0xe8, 0x11, - 0x70, 0xb0, 0xa4, 0x4a, 0xda, 0x8c, 0x44, 0x5d, 0xca, 0x3e, 0xac, 0xe9, 0xfe, 0xd0, 0xc8, 0x0e, 0xe3, 0xaf, 0x66, - 0x2b, 0xb5, 0x68, 0xfe, 0x45, 0x09, 0xc7, 0x4a, 0x84, 0xcd, 0x0c, 0xb8, 0x8e, 0xfe, 0x8f, 0xa4, 0xd0, 0xa1, 0x6b, - 0x01, 0x50, 0xfb, 0x13, 0x65, 0x83, 0xa2, 0x18, 0x01, 0xda, 0x8f, 0xaa, 0x6c, 0xa4, 0x3e, 0xe5, 0x05, 0xb3, 0xeb, - 0xb6, 0x33, 0xcb, 0x45, 0x30, 0xd6, 0x66, 0x1b, 0x00, 0xc2, 0x9a, 0x0b, 0x68, 0x20, 0x8a, 0x46, 0x51, 0xb6, 0xf4, - 0x06, 0xbb, 0xc5, 0xd7, 0x10, 0xad, 0x7d, 0x4c, 0x28, 0xfa, 0x0d, 0xad, 0xa4, 0x1a, 0x59, 0xe6, 0xfb, 0x57, 0x16, - 0xcc, 0xb5, 0x38, 0x7a, 0x6b, 0xcf, 0xad, 0x6c, 0xd1, 0x79, 0x6f, 0x57, 0xd3, 0x3f, 0xb3, 0xab, 0xe1, 0x3d, 0xdb, - 0x80, 0x19, 0x5e, 0xd8, 0x92, 0x5f, 0x9f, 0xd6, 0x4d, 0x38, 0xfe, 0x91, 0x55, 0x8c, 0x0a, 0x57, 0x10, 0x2c, 0xaa, - 0x46, 0x9c, 0x92, 0x7f, 0xec, 0x03, 0x05, 0xda, 0xc3, 0x8a, 0x48, 0x85, 0x51, 0xe5, 0xa1, 0x12, 0xd9, 0x53, 0xf1, - 0xab, 0x36, 0x90, 0xc1, 0x26, 0x1c, 0x4a, 0x06, 0x6e, 0x6a, 0xd7, 0x26, 0x31, 0x3b, 0x73, 0xeb, 0x3f, 0x65, 0x05, - 0xab, 0x61, 0xc4, 0x12, 0xf5, 0x21, 0x4e, 0xf4, 0xb2, 0xea, 0x11, 0x1e, 0x4d, 0x8b, 0xdd, 0x43, 0x90, 0x5a, 0x16, - 0x09, 0xbf, 0x6f, 0x19, 0xa0, 0x46, 0x30, 0xa1, 0x9a, 0x67, 0x65, 0x1c, 0x42, 0x2e, 0xd3, 0xe3, 0x4c, 0x10, 0xa0, - 0x96, 0xe5, 0x3a, 0x63, 0x0d, 0x47, 0x5e, 0x0b, 0xb4, 0xa4, 0x16, 0x48, 0xae, 0x51, 0x36, 0x2c, 0xb8, 0xfe, 0x5c, - 0x16, 0x8d, 0x42, 0x83, 0x86, 0xd8, 0x91, 0xe7, 0x24, 0x0f, 0x73, 0x8e, 0xa6, 0x48, 0x6e, 0xf3, 0x57, 0xa2, 0xd5, - 0xcc, 0xd6, 0xe2, 0x74, 0xf1, 0x6a, 0x33, 0xc2, 0x76, 0x47, 0xe3, 0x94, 0x69, 0xe2, 0x78, 0x8c, 0xb6, 0x07, 0xda, - 0xdc, 0x69, 0xc9, 0x8d, 0x8b, 0xff, 0x25, 0xb2, 0xe8, 0xe6, 0xf1, 0x02, 0xc1, 0x5c, 0xee, 0x62, 0x94, 0x19, 0x6e, - 0x8e, 0x5d, 0x60, 0xc3, 0xfc, 0x27, 0x2e, 0xba, 0x2a, 0xe3, 0xc5, 0xaa, 0xd5, 0x88, 0x21, 0x4e, 0xac, 0xcf, 0xf6, - 0x11, 0xb1, 0x1e, 0x91, 0x70, 0xa4, 0xac, 0xb3, 0x51, 0x99, 0xc6, 0xba, 0x0c, 0xbe, 0x79, 0x32, 0x5b, 0x42, 0x10, - 0x18, 0x36, 0x5f, 0x6c, 0x7f, 0x02, 0x2b, 0x2e, 0x24, 0xa1, 0x95, 0xf0, 0xc2, 0xbf, 0x7e, 0x87, 0x57, 0x34, 0x2b, - 0x2b, 0x5d, 0xe3, 0x72, 0x62, 0xa1, 0xd1, 0x30, 0xa7, 0x8e, 0x19, 0x8f, 0x09, 0x8b, 0xe9, 0xf9, 0x61, 0x49, 0x15, - 0x01, 0x0d, 0xcd, 0x39, 0x77, 0xa4, 0xcd, 0x24, 0xb8, 0x8d, 0xc9, 0xb1, 0x14, 0xa0, 0x2b, 0x74, 0x99, 0xdd, 0x6d, - 0x67, 0x18, 0x07, 0x43, 0x6e, 0x66, 0x00, 0xc2, 0x95, 0x08, 0x6a, 0x09, 0x78, 0x56, 0xec, 0x6b, 0xd1, 0x39, 0x98, - 0x8b, 0x02, 0xf5, 0x5e, 0x07, 0xfd, 0x0d, 0x12, 0x2e, 0x11, 0xad, 0x14, 0x38, 0x19, 0xd0, 0x65, 0xda, 0x55, 0x68, - 0x5e, 0x22, 0xc4, 0x58, 0x03, 0x92, 0x5a, 0xe3, 0x97, 0x8b, 0x08, 0xf7, 0xbc, 0x9f, 0x0d, 0x67, 0xdd, 0xa0, 0x00, - 0xf2, 0x28, 0x7f, 0x7e, 0x6f, 0x89, 0xfe, 0x20, 0x27, 0x20, 0x71, 0xc1, 0x33, 0x11, 0xa3, 0x9d, 0x53, 0x83, 0x2d, - 0x73, 0x31, 0x6a, 0x70, 0x5b, 0xa3, 0x64, 0x29, 0x26, 0xdb, 0x48, 0xfb, 0x1c, 0x39, 0x23, 0x19, 0x90, 0xd5, 0x99, - 0x84, 0x0e, 0x5d, 0x3d, 0x99, 0xca, 0xed, 0x28, 0xcc, 0x4d, 0x33, 0xd0, 0x67, 0x3b, 0x7c, 0x99, 0xfa, 0x9f, 0x36, - 0x57, 0xd6, 0xf4, 0x3d, 0x33, 0x19, 0xb1, 0x94, 0xe8, 0x4b, 0x06, 0xb3, 0x4f, 0xfb, 0x2e, 0xdf, 0xc1, 0x62, 0x7d, - 0x05, 0x7b, 0x55, 0xb1, 0x51, 0x1f, 0x5a, 0xcd, 0x98, 0x24, 0x8e, 0x25, 0xb7, 0x06, 0x25, 0x05, 0x95, 0x79, 0x8d, - 0x1a, 0x52, 0x31, 0xad, 0xb5, 0xb4, 0x13, 0xff, 0x17, 0x57, 0xcc, 0x4c, 0x0c, 0xfc, 0x18, 0x7b, 0xec, 0xe3, 0x47, - 0x6c, 0xbc, 0xdd, 0xbe, 0xe7, 0x0c, 0x1d, 0x93, 0x07, 0x08, 0x14, 0x3c, 0xf3, 0xd2, 0x25, 0xcd, 0xb9, 0xb5, 0x61, - 0xcd, 0x9a, 0x5a, 0xf9, 0xcf, 0xac, 0x9a, 0x0b, 0x1b, 0xfb, 0x44, 0xf8, 0x3a, 0xad, 0x5d, 0xc7, 0x3e, 0x84, 0x42, - 0x05, 0xf9, 0x42, 0xea, 0x60, 0xe6, 0xe2, 0x4d, 0x65, 0xf0, 0xb9, 0x2d, 0x8f, 0x92, 0x80, 0x21, 0x67, 0x23, 0x9f, - 0xa8, 0x15, 0xc1, 0x47, 0x8f, 0x08, 0x5f, 0xcc, 0xb6, 0x45, 0x14, 0x5c, 0x19, 0x25, 0xbc, 0xcb, 0xc8, 0x27, 0x37, - 0x5a, 0x7c, 0x35, 0x2d, 0xcb, 0xb3, 0x43, 0x6e, 0x27, 0xea, 0xfb, 0x41, 0xec, 0x82, 0xa0, 0xad, 0xc6, 0x82, 0x20, - 0x6b, 0xea, 0xbc, 0x49, 0x45, 0x82, 0xdf, 0x5a, 0x27, 0x9d, 0xd7, 0x89, 0x67, 0xdc, 0xe5, 0x3e, 0x24, 0x62, 0x04, - 0x6e, 0x8b, 0xee, 0xb7, 0x41, 0x94, 0x71, 0xe9, 0xe8, 0x64, 0x82, 0x47, 0x5d, 0xe2, 0xa4, 0xda, 0xf5, 0x7a, 0xd4, - 0xf6, 0x31, 0x1f, 0xfa, 0x01, 0xa8, 0x74, 0x1d, 0xe8, 0xbf, 0xa5, 0x9f, 0x64, 0x8e, 0xdc, 0xed, 0xf3, 0x41, 0x73, - 0x0b, 0xf4, 0x1d, 0xb5, 0x89, 0xa2, 0xee, 0x4b, 0xfc, 0x8c, 0x1c, 0xff, 0x97, 0x2a, 0x2b, 0x18, 0x02, 0x93, 0x99, - 0x68, 0x54, 0x5b, 0x90, 0xce, 0xc2, 0xe0, 0x70, 0xc7, 0xd7, 0x1a, 0x39, 0x60, 0x8b, 0x79, 0xc5, 0xa1, 0x1e, 0x34, - 0x82, 0x97, 0x50, 0x20, 0x86, 0x7b, 0x67, 0x68, 0x0c, 0x7a, 0x50, 0xec, 0x10, 0x06, 0x8a, 0x41, 0xcb, 0x52, 0x08, - 0xb4, 0x09, 0xa9, 0x76, 0xbf, 0x37, 0x47, 0xff, 0xd4, 0xef, 0xc8, 0x28, 0xa2, 0x51, 0xef, 0x1c, 0x24, 0x20, 0xe8, - 0x15, 0x07, 0x32, 0x50, 0xde, 0x2e, 0x89, 0x11, 0xcb, 0x78, 0x1c, 0xe4, 0xea, 0xe0, 0xf1, 0x4a, 0xc8, 0x99, 0x59, - 0x21, 0xe4, 0x18, 0xc0, 0xb0, 0xf6, 0xc0, 0xbd, 0x1c, 0x37, 0xb0, 0x09, 0x78, 0x26, 0x57, 0xd4, 0xb3, 0x59, 0x7d, - 0x3e, 0xfe, 0xbb, 0xbc, 0xb9, 0x6c, 0x71, 0x3f, 0x95, 0x8c, 0xc7, 0x1a, 0x4d, 0x15, 0xf8, 0xf0, 0x97, 0x0f, 0x9e, - 0x8f, 0x45, 0x91, 0x3e, 0x7d, 0x22, 0x81, 0x13, 0xa2, 0xeb, 0x92, 0xdf, 0x4c, 0x71, 0xac, 0x29, 0xa0, 0x86, 0xf3, - 0xb0, 0x73, 0x41, 0x78, 0x9c, 0xb0, 0x86, 0x8b, 0xc2, 0x1c, 0x76, 0x98, 0x60, 0x23, 0x8c, 0x6e, 0xa8, 0x21, 0x96, - 0xb4, 0x46, 0x7c, 0x3b, 0xc0, 0x25, 0xf8, 0x71, 0xa1, 0x95, 0x55, 0x09, 0xf1, 0xc7, 0x26, 0x9d, 0x01, 0x72, 0x89, - 0xb5, 0x7e, 0xca, 0xd3, 0xf9, 0x5b, 0x6d, 0x68, 0xe7, 0x79, 0xba, 0xb9, 0xb7, 0xe6, 0x70, 0xa6, 0x72, 0xe5, 0x24, - 0xa3, 0x18, 0x91, 0x1e, 0x95, 0x33, 0xf9, 0x2f, 0x0e, 0x13, 0x42, 0x66, 0x71, 0x74, 0xaf, 0x04, 0x46, 0xfb, 0x4a, - 0xd7, 0x33, 0xfe, 0x25, 0x22, 0x3f, 0x1b, 0xcd, 0x58, 0xbc, 0x42, 0xc9, 0xd5, 0xaa, 0x56, 0xfb, 0x5c, 0x8b, 0x5e, - 0x2a, 0x1a, 0xc7, 0x18, 0x35, 0xd7, 0x8c, 0x5f, 0x8c, 0x8d, 0x21, 0xd2, 0xe8, 0xc6, 0x6c, 0xfb, 0xa3, 0x25, 0xba, - 0xef, 0x7a, 0x22, 0x09, 0x9a, 0x6f, 0x10, 0x28, 0xc0, 0x2e, 0x26, 0x18, 0x92, 0xab, 0x30, 0x6b, 0x9a, 0xe5, 0x79, - 0x0a, 0x75, 0xad, 0xd9, 0x0b, 0xca, 0xf7, 0xba, 0xcb, 0xea, 0x52, 0xb6, 0x63, 0x5d, 0xf7, 0x28, 0x48, 0x1c, 0x35, - 0xce, 0x90, 0x98, 0x55, 0xcf, 0x92, 0x32, 0x2c, 0x11, 0xd2, 0x8a, 0x8b, 0x65, 0x4b, 0x9b, 0x4c, 0x61, 0x20, 0x6f, - 0x44, 0x37, 0x9d, 0x53, 0x21, 0x82, 0xdd, 0x59, 0x45, 0xa2, 0x4c, 0xdb, 0xb2, 0x8d, 0x16, 0x32, 0xf7, 0x6d, 0x28, - 0x74, 0x09, 0xf1, 0x83, 0xb7, 0x17, 0xee, 0x5e, 0x32, 0x8e, 0x10, 0xc6, 0x46, 0xc1, 0xc5, 0x47, 0xbd, 0xa4, 0xb6, - 0x72, 0x28, 0xe8, 0x9c, 0x6d, 0x96, 0x3e, 0xfe, 0x23, 0xab, 0xa6, 0xbc, 0xde, 0xb0, 0x52, 0xd9, 0xb0, 0x50, 0xc9, - 0x55, 0x2b, 0xf8, 0xa2, 0xd4, 0x8a, 0x09, 0x39, 0xf6, 0xd0, 0xa2, 0xf1, 0x80, 0x36, 0x51, 0x29, 0x67, 0x84, 0xe4, - 0xce, 0x9a, 0x66, 0xba, 0x06, 0xbb, 0x9b, 0x12, 0x60, 0xc7, 0x26, 0x53, 0xbd, 0x58, 0x78, 0x4a, 0x22, 0x0d, 0xdd, - 0x0a, 0xb9, 0xf3, 0x55, 0xee, 0x40, 0x21, 0x86, 0x75, 0x80, 0x85, 0xb3, 0x92, 0x81, 0xb0, 0x7d, 0x38, 0x8c, 0x1f, - 0xa3, 0xda, 0x02, 0xc6, 0x87, 0x10, 0xea, 0x7b, 0x03, 0x0c, 0x14, 0x1d, 0x9d, 0xd1, 0xe4, 0x2e, 0x67, 0xc8, 0xa0, - 0xef, 0x7d, 0x45, 0x09, 0xc9, 0x33, 0xf2, 0x7a, 0x2a, 0x59, 0x5c, 0x9d, 0x37, 0xad, 0xd0, 0x16, 0xeb, 0x77, 0xdf, - 0xda, 0x9a, 0xa2, 0xef, 0x88, 0x6b, 0x01, 0xd4, 0x0e, 0xd1, 0x77, 0x47, 0xd1, 0x9a, 0x76, 0xf3, 0x74, 0x99, 0x3f, - 0xc7, 0xbe, 0x9b, 0x08, 0x7f, 0xfa, 0x76, 0xdd, 0xf0, 0xf5, 0x32, 0xa0, 0xdc, 0x7b, 0xa3, 0xe0, 0x1c, 0xf5, 0x8e, - 0x0a, 0x44, 0x30, 0xc9, 0x9c, 0xee, 0xb4, 0x11, 0x74, 0x13, 0x91, 0x59, 0x3e, 0x5c, 0xfa, 0xcd, 0xfe, 0x57, 0x10, - 0xac, 0x41, 0x84, 0x0b, 0x7f, 0xd3, 0x20, 0x0e, 0x5e, 0x8a, 0x90, 0x74, 0x45, 0x30, 0xd1, 0x51, 0x41, 0x6c, 0xc5, - 0x76, 0xf1, 0xda, 0xac, 0x21, 0x10, 0x71, 0x0e, 0x2e, 0x9f, 0x59, 0xa1, 0x2c, 0xaa, 0xd7, 0xbe, 0x30, 0x44, 0xe5, - 0x66, 0x1f, 0xf4, 0xbf, 0x49, 0x16, 0xbe, 0x75, 0x70, 0x60, 0x65, 0x64, 0x2d, 0xb1, 0x3b, 0x6d, 0x2a, 0xb7, 0x82, - 0x1d, 0xb7, 0x73, 0xbd, 0xaf, 0x6f, 0x40, 0x69, 0xb4, 0xe5, 0x35, 0xbb, 0x4d, 0x99, 0xa9, 0x31, 0x3c, 0x66, 0xb5, - 0x68, 0x80, 0x09, 0x77, 0xd8, 0x2f, 0x2c, 0xd9, 0x3b, 0x98, 0x8a, 0xce, 0xfb, 0xf6, 0xcf, 0xcd, 0x14, 0x24, 0x4c, - 0xc7, 0x1c, 0x72, 0x07, 0x31, 0x63, 0x7a, 0x2a, 0x68, 0xbb, 0x8e, 0xf8, 0x5d, 0x24, 0x19, 0xf0, 0xbf, 0x2a, 0x65, - 0x4f, 0x23, 0x63, 0x46, 0xc8, 0xe8, 0xb6, 0xa4, 0x14, 0xe1, 0x5a, 0x1a, 0x0c, 0x8c, 0x11, 0xcc, 0xa7, 0x44, 0x0b, - 0xb1, 0xec, 0x0e, 0x2b, 0x12, 0xfb, 0x6c, 0xab, 0xd9, 0xdb, 0xc5, 0x7a, 0x4a, 0xd0, 0xb2, 0xde, 0x8b, 0x57, 0xaa, - 0xf3, 0x2e, 0x3c, 0xba, 0x6e, 0x37, 0x14, 0xc4, 0xf1, 0xd2, 0x6a, 0x6f, 0x81, 0x07, 0xed, 0xf3, 0x9f, 0x37, 0x8a, - 0x17, 0xb7, 0xca, 0x97, 0x10, 0xfc, 0xe0, 0x69, 0xb2, 0x18, 0xca, 0x20, 0x17, 0x2b, 0x17, 0x3c, 0x90, 0x2a, 0x6a, - 0xbb, 0xf5, 0x0a, 0x62, 0xf3, 0x7c, 0xf1, 0x69, 0x07, 0xc3, 0x33, 0x05, 0x1d, 0xec, 0x5f, 0xb6, 0xf5, 0x1b, 0xa0, - 0x75, 0x93, 0x21, 0xff, 0xae, 0x35, 0x1b, 0x64, 0x04, 0x1f, 0xbf, 0xda, 0xfe, 0x62, 0x0c, 0xd5, 0x9e, 0xd1, 0x32, - 0xec, 0x96, 0xbf, 0x47, 0x2e, 0xc1, 0xbe, 0x2b, 0x03, 0xc0, 0x5c, 0x2e, 0x63, 0xc4, 0xe7, 0xe4, 0x1b, 0x84, 0x01, - 0x10, 0xf9, 0xf5, 0x77, 0xfd, 0xf8, 0xd0, 0xdc, 0xad, 0x3c, 0x76, 0xec, 0x59, 0x22, 0x06, 0xc5, 0x3a, 0x66, 0x3b, - 0xf6, 0x21, 0x2b, 0x1e, 0xaa, 0x44, 0x74, 0xac, 0xf9, 0x90, 0xb9, 0x4f, 0xf1, 0xb0, 0xbd, 0xf3, 0xfd, 0x20, 0x8a, - 0x2c, 0x19, 0x25, 0xd9, 0x5f, 0x68, 0xe9, 0x7e, 0x7c, 0x41, 0x33, 0xa8, 0xdb, 0x13, 0xe4, 0x55, 0x04, 0x10, 0x8f, - 0xc1, 0xe0, 0xbf, 0x2e, 0xf3, 0x9e, 0x4b, 0x0b, 0xc0, 0xcf, 0x29, 0xbb, 0x8d, 0x79, 0x3e, 0xd7, 0x04, 0x82, 0x3e, - 0xeb, 0x9e, 0xe8, 0x11, 0x91, 0xe9, 0xa7, 0xb3, 0x63, 0x00, 0x72, 0x1a, 0x45, 0x3c, 0x62, 0xab, 0x6f, 0x3f, 0xb1, - 0xaa, 0x8b, 0xfb, 0xa3, 0x50, 0xdd, 0xa2, 0xa0, 0x33, 0x88, 0xd4, 0x2e, 0xce, 0x64, 0x24, 0x3b, 0x32, 0xcd, 0xd0, - 0x11, 0xed, 0xa5, 0x62, 0x4a, 0xc6, 0xb0, 0x1c, 0x23, 0xb6, 0x88, 0x23, 0x67, 0xd3, 0xc9, 0x12, 0x87, 0x61, 0x89, - 0xf3, 0x3e, 0x75, 0x08, 0x7a, 0xa5, 0x8a, 0x52, 0xbb, 0x18, 0xe7, 0xdb, 0x21, 0x8b, 0x06, 0xe0, 0x52, 0xe3, 0x1d, - 0x82, 0xe7, 0xc3, 0xab, 0xf1, 0x99, 0x2b, 0x72, 0x2c, 0x5c, 0xcf, 0x27, 0xb2, 0x63, 0x3c, 0x33, 0x90, 0x18, 0xc7, - 0x61, 0xae, 0xf3, 0xa0, 0x0e, 0xc1, 0x2e, 0x26, 0x68, 0xa4, 0xe7, 0x89, 0x7b, 0x30, 0xed, 0x68, 0x3d, 0x1b, 0xcd, - 0x1c, 0x58, 0x05, 0xc6, 0xfe, 0x01, 0x6d, 0x55, 0x0c, 0xc3, 0x23, 0xe3, 0x20, 0x0c, 0x67, 0xeb, 0xad, 0x4c, 0xaf, - 0x19, 0x42, 0xcb, 0x63, 0x65, 0x92, 0x81, 0xa6, 0x8d, 0x0f, 0xa3, 0xae, 0xf1, 0x9b, 0x7a, 0x02, 0xb4, 0x16, 0x9f, - 0x6d, 0xf1, 0xf1, 0xe2, 0xa0, 0x70, 0xe1, 0x92, 0xd1, 0x5f, 0x6c, 0x4d, 0x58, 0xd2, 0x9d, 0x2e, 0xce, 0xdc, 0x95, - 0xaf, 0xd3, 0x99, 0x34, 0xb7, 0x94, 0x65, 0x53, 0x79, 0xa0, 0xdb, 0x6e, 0x66, 0xff, 0xc7, 0x7f, 0x19, 0x3e, 0x30, - 0x74, 0x91, 0xb0, 0x09, 0xf1, 0x2d, 0x6a, 0xfc, 0x8b, 0x8f, 0xc6, 0x27, 0x63, 0x58, 0x0f, 0x33, 0x99, 0x3b, 0xcc, - 0x73, 0x0c, 0x7b, 0x8f, 0x8f, 0x7d, 0x18, 0x20, 0x26, 0x5f, 0x4d, 0x15, 0x16, 0x71, 0x8f, 0x81, 0xca, 0xd5, 0x70, - 0xec, 0x20, 0x42, 0xde, 0xd4, 0x3e, 0x2b, 0xf6, 0x9f, 0x09, 0xe2, 0xe1, 0xd9, 0x8e, 0xc2, 0x24, 0xc8, 0x37, 0xb3, - 0x21, 0x6f, 0x7d, 0x4d, 0xa5, 0x83, 0x3c, 0x2e, 0xb1, 0x68, 0xed, 0x2e, 0x85, 0xa1, 0x85, 0x2e, 0x42, 0x4b, 0x83, - 0xa5, 0x50, 0xf7, 0x4a, 0x83, 0x5c, 0x98, 0x3a, 0x17, 0x78, 0xf1, 0x19, 0xe0, 0x18, 0xdf, 0x1f, 0x0f, 0xa4, 0x2b, - 0x26, 0x73, 0x39, 0xc1, 0xfb, 0xb4, 0x69, 0xdd, 0x19, 0x28, 0x40, 0xda, 0xa7, 0xc2, 0x55, 0xbb, 0x0c, 0xb3, 0x2e, - 0x24, 0x73, 0x22, 0x4c, 0x66, 0xb2, 0x8b, 0xb0, 0xbf, 0x94, 0xcd, 0x90, 0xe2, 0x13, 0x6e, 0x72, 0x1b, 0xf8, 0xda, - 0x11, 0x1d, 0x05, 0x2d, 0xda, 0x36, 0xe5, 0x5c, 0xec, 0x04, 0x9d, 0xf0, 0xe8, 0x26, 0x78, 0xd9, 0xab, 0xd7, 0x38, - 0x6f, 0xe9, 0x75, 0x6f, 0x17, 0xf7, 0xde, 0xdd, 0x06, 0x18, 0xf8, 0x02, 0x39, 0xf3, 0x98, 0x19, 0xc5, 0xf1, 0x5f, - 0xa7, 0xe0, 0xec, 0x84, 0xcf, 0x08, 0x18, 0x40, 0x42, 0xb6, 0x61, 0xb1, 0x75, 0x80, 0x7d, 0xfc, 0x10, 0xd7, 0xa8, - 0x04, 0x8c, 0x54, 0x69, 0x70, 0x9c, 0x99, 0xaf, 0x59, 0x86, 0x64, 0x58, 0x2e, 0xa5, 0x87, 0x21, 0x66, 0x0e, 0xb8, - 0xb3, 0x5d, 0xf9, 0x56, 0x7c, 0x8e, 0x1e, 0xe5, 0x24, 0xbd, 0x8b, 0x05, 0x5a, 0x64, 0xc4, 0x07, 0x0a, 0x35, 0xc8, - 0x34, 0x31, 0xf8, 0x8c, 0x50, 0x40, 0x62, 0x86, 0x1b, 0x21, 0x50, 0x42, 0x9e, 0x2d, 0xbf, 0x8d, 0xa8, 0xe0, 0x44, - 0x28, 0x62, 0xd2, 0x12, 0xa9, 0x8e, 0x04, 0x99, 0x99, 0x21, 0xc9, 0xf4, 0x98, 0x1b, 0xd3, 0x81, 0x79, 0x01, 0xe6, - 0x54, 0xa6, 0x07, 0x90, 0x4f, 0xc6, 0x98, 0x55, 0x44, 0x98, 0xe9, 0xae, 0xbc, 0x48, 0x2a, 0x1a, 0xac, 0x61, 0x2e, - 0x9a, 0x8b, 0x25, 0x6a, 0xd7, 0x09, 0xe5, 0x14, 0x27, 0x57, 0xed, 0x82, 0xb4, 0x33, 0x98, 0xf2, 0x21, 0xe5, 0x9b, - 0x0e, 0x42, 0x5b, 0x87, 0xce, 0xaa, 0x41, 0xd8, 0x91, 0xc4, 0x26, 0x08, 0x09, 0xc9, 0x72, 0x07, 0xd2, 0x50, 0x26, - 0x42, 0x42, 0xe8, 0x24, 0x0d, 0xad, 0xd3, 0x35, 0x13, 0xf1, 0x69, 0x85, 0xc5, 0x36, 0x88, 0xc4, 0x12, 0x8d, 0x7d, - 0xdf, 0xca, 0x63, 0x78, 0xc1, 0x29, 0x2c, 0xb6, 0xc8, 0xaa, 0xc0, 0x18, 0x12, 0x09, 0xb3, 0xd5, 0x09, 0x53, 0xe7, - 0xf5, 0xfd, 0xcd, 0x80, 0xb3, 0xa7, 0x09, 0x99, 0x08, 0xc6, 0x15, 0x5d, 0x94, 0x2a, 0xcd, 0x17, 0x25, 0x0e, 0x95, - 0x1a, 0xbe, 0xba, 0xaa, 0xbc, 0x19, 0x90, 0x77, 0x36, 0xd5, 0x33, 0xde, 0xee, 0x87, 0x7a, 0xe2, 0xac, 0x0a, 0xc1, - 0x29, 0xaa, 0x4e, 0xf7, 0xff, 0x3d, 0x5f, 0x55, 0x12, 0xe5, 0x13, 0x25, 0x65, 0xd0, 0x5a, 0xdc, 0x16, 0x5b, 0x41, - 0xb9, 0x49, 0xd3, 0x29, 0x5f, 0x07, 0x15, 0xab, 0xab, 0x82, 0x81, 0x2e, 0xd8, 0x11, 0x10, 0x37, 0x83, 0x2e, 0x96, - 0x36, 0x96, 0xf2, 0x03, 0x84, 0xbe, 0x7e, 0xdb, 0x19, 0xa3, 0xed, 0xbd, 0xcc, 0x30, 0xa4, 0xf5, 0x33, 0x73, 0x2e, - 0x6d, 0x1e, 0x91, 0x20, 0x78, 0x0b, 0x9d, 0xb2, 0x7b, 0x25, 0x2f, 0x67, 0xae, 0x3c, 0x7b, 0xbc, 0x5b, 0xad, 0x80, - 0xdb, 0x55, 0x1a, 0x4e, 0x8b, 0xe3, 0xd9, 0x87, 0x4b, 0xe7, 0x11, 0x3c, 0x92, 0x32, 0xf0, 0x5e, 0x73, 0xa4, 0x1b, - 0x22, 0x1d, 0xf5, 0xbc, 0x57, 0xe0, 0x9c, 0x93, 0x45, 0x51, 0xf2, 0x26, 0x68, 0x7a, 0x7e, 0x17, 0x98, 0x47, 0x54, - 0x1c, 0x83, 0xaa, 0x50, 0x33, 0xcd, 0xaf, 0x2c, 0x04, 0x2e, 0x68, 0xae, 0xe6, 0xd3, 0xca, 0x94, 0x07, 0x52, 0x15, - 0xcb, 0x95, 0x36, 0xa5, 0x1c, 0x89, 0x0b, 0xba, 0xd9, 0x64, 0xf5, 0xc0, 0x20, 0x62, 0xa3, 0xff, 0x82, 0xc8, 0x23, - 0xc2, 0x5f, 0x15, 0xa5, 0x48, 0x87, 0x19, 0x59, 0x29, 0x06, 0x2c, 0x54, 0x40, 0x5a, 0x79, 0x37, 0x60, 0xcb, 0x6f, - 0x28, 0x24, 0x52, 0x6f, 0xeb, 0x3b, 0x24, 0x8b, 0xf8, 0xad, 0x93, 0xcd, 0xc6, 0xc4, 0x92, 0xcf, 0xb7, 0x67, 0xa2, - 0x21, 0x72, 0x32, 0x3b, 0xfa, 0x75, 0x1f, 0x30, 0xad, 0x18, 0x2e, 0x9d, 0x9d, 0xf2, 0x58, 0x1f, 0x5e, 0x06, 0x9b, - 0x4f, 0xc5, 0x98, 0x27, 0x35, 0x3c, 0x63, 0x99, 0x71, 0xab, 0x39, 0xd1, 0x15, 0xb4, 0xc1, 0x5e, 0x82, 0x2d, 0xf5, - 0xbc, 0x95, 0xe1, 0x63, 0xc2, 0x5f, 0x23, 0x7c, 0x02, 0x8e, 0x81, 0xf7, 0x9a, 0xa9, 0x74, 0x1e, 0xe8, 0xad, 0xf8, - 0x8c, 0x79, 0x1c, 0xc3, 0x1b, 0xbc, 0x48, 0x3e, 0xc1, 0xed, 0x29, 0x83, 0x1a, 0x2b, 0x1f, 0xde, 0xfc, 0xd0, 0x34, - 0x15, 0xd6, 0xc6, 0xcb, 0x61, 0x86, 0x7e, 0xfd, 0x57, 0xee, 0x7b, 0xde, 0x96, 0xf7, 0x7e, 0x6b, 0xf2, 0x0d, 0xdc, - 0x07, 0xa3, 0xde, 0x4d, 0x17, 0xc3, 0x79, 0x43, 0xed, 0xd7, 0x4b, 0xdc, 0x95, 0x59, 0x01, 0xe9, 0xdf, 0xd7, 0xe6, - 0xaf, 0x81, 0x85, 0x91, 0x63, 0x1f, 0x72, 0x22, 0x5b, 0x89, 0x46, 0xcb, 0xfc, 0xc2, 0xe8, 0x6f, 0x08, 0x0d, 0xf3, - 0x39, 0xe8, 0x8a, 0xbb, 0x21, 0xa1, 0x63, 0x66, 0x22, 0x2e, 0xb0, 0x6e, 0x4a, 0xd9, 0xb5, 0xce, 0xae, 0xb6, 0xaa, - 0xc7, 0x23, 0xd6, 0x55, 0xda, 0x7b, 0x05, 0xa1, 0x10, 0x71, 0x7d, 0x3e, 0x4d, 0xeb, 0x1b, 0xa3, 0x0c, 0x3a, 0xbc, - 0x11, 0x19, 0x5b, 0x3c, 0xfa, 0x0f, 0xcc, 0x8f, 0x28, 0x34, 0xcc, 0xa5, 0xb0, 0xb7, 0xb7, 0x89, 0xe3, 0x54, 0xf1, - 0x8c, 0xdc, 0xbe, 0xa7, 0xfa, 0xe2, 0x29, 0xed, 0xfd, 0x92, 0xa2, 0x15, 0x4e, 0xc6, 0xb8, 0x4e, 0x1e, 0xf3, 0x25, - 0x43, 0xa1, 0x08, 0x21, 0x8c, 0x53, 0xbf, 0x98, 0x33, 0xa4, 0x05, 0xde, 0x48, 0xdb, 0x36, 0xe4, 0x94, 0x30, 0x05, - 0x71, 0x3e, 0xc2, 0xc3, 0x39, 0xbb, 0xb5, 0x0a, 0x53, 0x77, 0x9c, 0xf5, 0x85, 0x86, 0x87, 0x3b, 0x64, 0xda, 0x21, - 0xec, 0x1b, 0x72, 0xc3, 0xce, 0xa6, 0x17, 0x2e, 0x34, 0x71, 0x7b, 0xdc, 0x3f, 0xa4, 0x25, 0xf3, 0x34, 0x01, 0xa2, - 0x31, 0xe6, 0xe5, 0x92, 0xbd, 0x36, 0xb6, 0xe3, 0x6d, 0x98, 0x0d, 0xa1, 0x36, 0x60, 0xdd, 0xc1, 0x99, 0x9e, 0xf9, - 0x1b, 0xc5, 0xfb, 0x72, 0x09, 0x8e, 0x97, 0xe2, 0x21, 0x2e, 0xfc, 0x67, 0x54, 0x58, 0x72, 0x12, 0xb3, 0xe0, 0x61, - 0x2b, 0x5e, 0x99, 0xe1, 0x32, 0xe9, 0x0b, 0x27, 0x50, 0xf9, 0xc0, 0x09, 0x14, 0x4e, 0x5f, 0xc4, 0xa4, 0x92, 0xf7, - 0x70, 0xca, 0x4e, 0xdf, 0xde, 0x8b, 0x63, 0x06, 0xf5, 0x9a, 0x4d, 0x8e, 0x9e, 0x64, 0x63, 0x56, 0x0d, 0x07, 0x51, - 0xdd, 0x69, 0x64, 0x90, 0x71, 0x78, 0x2f, 0x57, 0xd7, 0x91, 0x21, 0xe2, 0x08, 0x2a, 0xd4, 0x2f, 0xa4, 0xf3, 0xf3, - 0x79, 0x21, 0x03, 0x89, 0x06, 0x6d, 0x36, 0xec, 0x10, 0x55, 0x21, 0xaf, 0x13, 0x5e, 0x08, 0xad, 0xf0, 0x84, 0x1e, - 0x65, 0xd8, 0x1d, 0x2d, 0x32, 0xda, 0xed, 0x2b, 0x47, 0xd3, 0x85, 0x83, 0xff, 0x1c, 0x66, 0x0b, 0x74, 0xb8, 0x46, - 0x5d, 0xa4, 0xfb, 0xa9, 0x13, 0xaf, 0xfd, 0x0f, 0xa6, 0x8b, 0xae, 0x7d, 0x9a, 0xc9, 0x9c, 0x1e, 0x32, 0xa2, 0xf8, - 0xea, 0x85, 0xaf, 0xe9, 0x64, 0x5a, 0x33, 0x7d, 0x14, 0x5a, 0xe7, 0xa1, 0xca, 0xed, 0xc1, 0x78, 0x56, 0x93, 0xe1, - 0xa3, 0xab, 0xc0, 0x21, 0x68, 0x4a, 0x30, 0x73, 0x5f, 0x51, 0x63, 0x34, 0x12, 0x26, 0x9d, 0x05, 0x96, 0x37, 0xb3, - 0x61, 0x39, 0x6f, 0x85, 0x96, 0x8f, 0x39, 0xfe, 0xe0, 0x16, 0xdb, 0xfc, 0x54, 0xd8, 0x2c, 0x71, 0xf1, 0x85, 0x8d, - 0x65, 0xd4, 0x8b, 0xa9, 0xb4, 0x75, 0x8a, 0x15, 0xa9, 0xec, 0xa6, 0x6e, 0xbc, 0xa9, 0x5b, 0x5e, 0x4a, 0xce, 0xdb, - 0x14, 0xe5, 0x24, 0x77, 0x29, 0x14, 0x83, 0x81, 0x37, 0x72, 0xd6, 0x9e, 0xa2, 0x64, 0x72, 0x03, 0x9d, 0xe9, 0xeb, - 0xd8, 0xb6, 0xa2, 0x78, 0xb0, 0x17, 0xae, 0xac, 0x3c, 0x83, 0x44, 0xbe, 0x3c, 0x5f, 0xd4, 0x89, 0x85, 0xe2, 0x7c, - 0x37, 0x5f, 0x28, 0x56, 0xf0, 0x6d, 0x40, 0x3c, 0x3b, 0x6f, 0x05, 0xf8, 0x2b, 0xec, 0x70, 0x76, 0xe6, 0x3d, 0x98, - 0xab, 0x50, 0x04, 0x3b, 0x32, 0xf8, 0x46, 0x82, 0x6a, 0x26, 0x30, 0x59, 0x82, 0x60, 0x55, 0x16, 0xf3, 0x05, 0xc1, - 0x1a, 0x47, 0xa1, 0x64, 0xc3, 0xe5, 0x77, 0x66, 0x53, 0x14, 0x45, 0x22, 0xfc, 0xee, 0x1a, 0x26, 0xcf, 0x08, 0xa7, - 0xf8, 0x58, 0x55, 0xe6, 0x43, 0x8d, 0x17, 0x93, 0x68, 0x80, 0xfe, 0xcd, 0x56, 0x44, 0xfb, 0xd7, 0x51, 0xa3, 0x24, - 0xb8, 0x67, 0xe1, 0xda, 0x38, 0xeb, 0x8a, 0xeb, 0xf4, 0x9b, 0x2c, 0xf3, 0x5a, 0x84, 0xf9, 0x95, 0x0d, 0x59, 0xeb, - 0x7c, 0x0f, 0x87, 0x72, 0xa2, 0xee, 0xb3, 0x9c, 0x59, 0x72, 0x88, 0x7a, 0x4f, 0x47, 0x67, 0xe6, 0x90, 0xb3, 0xb8, - 0xba, 0x61, 0x0a, 0x32, 0x81, 0xd7, 0x4c, 0x23, 0x95, 0x81, 0x3f, 0x15, 0x05, 0x1c, 0x2e, 0xa7, 0xf8, 0x9f, 0x94, - 0x98, 0x1d, 0x04, 0x83, 0x30, 0x76, 0x77, 0xf5, 0x2b, 0x40, 0xd6, 0x16, 0x66, 0x07, 0xb7, 0x39, 0x6e, 0xa2, 0xc0, - 0xa8, 0x09, 0xde, 0x16, 0xf2, 0xa5, 0x25, 0x48, 0x89, 0xd5, 0xc8, 0x8b, 0x56, 0x9f, 0xc7, 0x30, 0x10, 0xf8, 0xa9, - 0x0b, 0xfb, 0x73, 0x4d, 0xc7, 0xe6, 0xd0, 0x34, 0x92, 0x67, 0xd2, 0x96, 0x84, 0x81, 0xa4, 0x9d, 0x68, 0xe3, 0x27, - 0x17, 0x9a, 0xea, 0x76, 0x0a, 0xe9, 0x7a, 0x39, 0x0d, 0x25, 0xb3, 0x28, 0x5c, 0x38, 0x9a, 0x53, 0x1e, 0xd0, 0xe9, - 0xd6, 0x6c, 0x4c, 0x76, 0x07, 0xc3, 0x95, 0x18, 0x4d, 0x1d, 0xc6, 0xb9, 0x28, 0xed, 0x31, 0x56, 0xaa, 0xc7, 0x7e, - 0x91, 0x36, 0x21, 0xc1, 0x13, 0x2a, 0x8e, 0x3c, 0xf0, 0xa8, 0xa2, 0x35, 0x44, 0x87, 0xc7, 0xf0, 0xc0, 0xa9, 0xb9, - 0xc1, 0x58, 0x1d, 0xc6, 0x40, 0x39, 0x92, 0x38, 0x45, 0x7e, 0xba, 0x63, 0xb8, 0xf0, 0x39, 0xff, 0x80, 0x99, 0x52, - 0x79, 0xe6, 0x73, 0x3d, 0xf8, 0x76, 0xc0, 0xf7, 0xfe, 0x1b, 0x8f, 0x91, 0x0d, 0xe3, 0xf0, 0xc3, 0xbf, 0xea, 0xb1, - 0xfc, 0xfd, 0x80, 0xe6, 0xc3, 0x49, 0x1e, 0x4c, 0x38, 0x2b, 0xb4, 0x80, 0x3f, 0xba, 0x32, 0xee, 0x16, 0x0c, 0xeb, - 0x23, 0x28, 0x22, 0x76, 0xe2, 0x70, 0xbc, 0x5c, 0x0b, 0x00, 0xe5, 0xc1, 0x6d, 0x80, 0xc8, 0x42, 0x34, 0x3f, 0x2f, - 0x17, 0xdf, 0xd6, 0x65, 0x68, 0x4b, 0x5b, 0x77, 0x8f, 0x13, 0x31, 0x6c, 0x26, 0x41, 0x2d, 0x44, 0xaf, 0x88, 0x18, - 0x11, 0x33, 0x43, 0xeb, 0x65, 0xfd, 0x9e, 0xb9, 0x1b, 0x08, 0xa3, 0x36, 0x6c, 0x84, 0x37, 0xec, 0x59, 0xbf, 0xb0, - 0xdc, 0x23, 0xb6, 0xaa, 0x80, 0x7d, 0x4b, 0x3e, 0x40, 0x91, 0x84, 0x2d, 0xed, 0xf8, 0x87, 0x13, 0xb1, 0xe8, 0x1f, - 0x42, 0xd8, 0xc4, 0x36, 0x28, 0x18, 0xbc, 0xd4, 0x36, 0x7b, 0x1b, 0x08, 0x31, 0x14, 0xeb, 0xb5, 0x1e, 0xc1, 0x89, - 0x1a, 0x40, 0x2a, 0x74, 0xcf, 0x58, 0x3d, 0x22, 0x93, 0xe7, 0x9f, 0x91, 0x96, 0x2d, 0x98, 0x29, 0x9f, 0x58, 0x3b, - 0x12, 0xec, 0xfc, 0x66, 0x45, 0xf2, 0x82, 0xef, 0x12, 0x49, 0xbe, 0xbe, 0x2b, 0xc6, 0xcf, 0xf8, 0x0f, 0x34, 0x29, - 0x04, 0x3a, 0xb8, 0x3a, 0x20, 0x32, 0xd4, 0x62, 0x19, 0xd5, 0xf1, 0x1e, 0x8b, 0x4c, 0x9c, 0x5e, 0xd8, 0xcc, 0xb3, - 0x0c, 0x0b, 0x27, 0x16, 0xc3, 0x28, 0x95, 0x5d, 0x6e, 0xd9, 0xde, 0x9f, 0x0c, 0x4e, 0xe5, 0x88, 0x52, 0x75, 0xbc, - 0xc6, 0xad, 0x1a, 0x9a, 0x43, 0x57, 0xa9, 0xcd, 0x68, 0x78, 0xec, 0x5f, 0xd7, 0x99, 0xd4, 0xb1, 0xa6, 0x03, 0x82, - 0xd7, 0x41, 0xaf, 0xd3, 0x82, 0xfb, 0x3b, 0x6f, 0x13, 0x6d, 0xc4, 0x20, 0x82, 0x82, 0x19, 0x82, 0x7d, 0x7e, 0xa8, - 0x25, 0x63, 0xc3, 0x68, 0x92, 0x54, 0xd4, 0xb1, 0x71, 0x66, 0x94, 0xf5, 0x9b, 0x74, 0x9c, 0xf2, 0x36, 0x12, 0x7a, - 0xf0, 0xbd, 0x3c, 0x5e, 0x71, 0xd2, 0x3a, 0x46, 0xc4, 0x05, 0xc7, 0xc3, 0x6d, 0xcc, 0xa1, 0xd9, 0x2c, 0xb6, 0xc0, - 0x61, 0x42, 0x6b, 0x61, 0xb3, 0x73, 0x96, 0x53, 0xbe, 0x92, 0xb2, 0x27, 0xe9, 0xcd, 0xab, 0x0d, 0x25, 0x00, 0xc2, - 0x44, 0xff, 0x48, 0x02, 0x9f, 0x15, 0xc8, 0x98, 0x23, 0x27, 0x39, 0x32, 0x3f, 0x56, 0xf3, 0x08, 0x28, 0x13, 0xc3, - 0xc5, 0xdb, 0x70, 0xd3, 0x4f, 0xd0, 0x42, 0x3b, 0xd8, 0xa9, 0x1b, 0x04, 0x41, 0x82, 0x1d, 0xe0, 0x2f, 0xfc, 0xd8, - 0x1e, 0xbf, 0xa5, 0xcb, 0xaf, 0x5b, 0x87, 0xff, 0x8f, 0x39, 0xb7, 0x0f, 0x1b, 0x5b, 0x3f, 0xd8, 0xaa, 0xef, 0x91, - 0xff, 0xc8, 0x0c, 0x5d, 0x0f, 0xf8, 0xf0, 0x81, 0x0d, 0x67, 0xcf, 0xd5, 0x00, 0x6e, 0x5b, 0xbf, 0x16, 0x58, 0x92, - 0x09, 0x22, 0xe5, 0xc4, 0x8e, 0xea, 0xcb, 0x64, 0xfd, 0xcd, 0xe0, 0xe6, 0xf4, 0x80, 0xfa, 0x07, 0x13, 0xbf, 0x04, - 0x5d, 0x76, 0xf7, 0x0b, 0xc8, 0xc4, 0xfa, 0xd4, 0x21, 0x57, 0x29, 0xfd, 0xfc, 0x62, 0xd9, 0xfe, 0x12, 0xa5, 0xab, - 0x6c, 0x70, 0x7f, 0xd1, 0x49, 0x41, 0xd8, 0xf4, 0xfa, 0x25, 0xd7, 0x36, 0xad, 0x7d, 0x52, 0xb9, 0xda, 0x11, 0xdf, - 0x05, 0x20, 0xc0, 0x4e, 0x95, 0xc9, 0xc9, 0x33, 0xfe, 0x48, 0x04, 0x9d, 0xb3, 0x5f, 0xf6, 0x37, 0xeb, 0xf0, 0x86, - 0x58, 0xdb, 0x5d, 0xbc, 0xb7, 0x5f, 0x80, 0xa0, 0x9c, 0x7b, 0x0d, 0x15, 0x0c, 0x42, 0xbc, 0x24, 0x40, 0xc8, 0x61, - 0x74, 0xe2, 0xa2, 0x8b, 0x1c, 0x62, 0xda, 0x48, 0x60, 0x5d, 0xa5, 0xed, 0x91, 0x63, 0xaf, 0xe5, 0x89, 0x6e, 0x61, - 0xdc, 0x42, 0x55, 0xc3, 0xa2, 0x01, 0x23, 0xcf, 0xc2, 0x0e, 0xe7, 0xe2, 0xa1, 0x47, 0x2b, 0xe8, 0x82, 0x34, 0xe1, - 0xb8, 0xd4, 0xef, 0xc3, 0x21, 0x28, 0x9b, 0xaf, 0x3a, 0xa1, 0xfb, 0x01, 0x2e, 0x4d, 0xd1, 0x1a, 0xf2, 0xe7, 0x62, - 0x3b, 0x23, 0x5c, 0x9e, 0x48, 0x4c, 0x16, 0x82, 0x38, 0xda, 0xd6, 0x2d, 0x93, 0xa1, 0x2e, 0x86, 0xf8, 0xf9, 0x48, - 0x69, 0x0b, 0x3d, 0xbc, 0x20, 0x90, 0x69, 0x82, 0x3a, 0x87, 0xdf, 0x24, 0xfc, 0xae, 0x30, 0x76, 0xc8, 0xcd, 0x74, - 0x18, 0x09, 0xd7, 0xb8, 0x13, 0x20, 0xb2, 0x34, 0x1f, 0x29, 0x6c, 0x5a, 0xd7, 0x51, 0x7f, 0x72, 0x09, 0x51, 0x7b, - 0xc4, 0x66, 0x3c, 0x69, 0xb0, 0x93, 0xe5, 0x37, 0x9d, 0x4b, 0x31, 0x44, 0x54, 0x99, 0x92, 0xbb, 0xe4, 0x9a, 0x38, - 0x92, 0x6b, 0x56, 0x19, 0x87, 0x12, 0x3a, 0x65, 0xa1, 0x6d, 0xe4, 0xb2, 0x83, 0x48, 0x3b, 0xe1, 0x98, 0x54, 0xd9, - 0xe4, 0xb1, 0x58, 0x88, 0x21, 0x33, 0xcd, 0x04, 0xeb, 0xeb, 0x0b, 0xcd, 0xaf, 0x6d, 0xc7, 0x40, 0x04, 0xd6, 0x1d, - 0x83, 0x4f, 0x05, 0x36, 0x2f, 0xa5, 0xa5, 0xd0, 0xab, 0x30, 0x75, 0xd5, 0x56, 0x2f, 0x94, 0xb6, 0x21, 0x64, 0x20, - 0x69, 0x67, 0x09, 0x1f, 0x65, 0x0b, 0x83, 0x9c, 0xf9, 0xbb, 0x05, 0x64, 0xdb, 0x83, 0x60, 0x7b, 0xcb, 0x94, 0xa5, - 0xbe, 0xb7, 0xfc, 0x5a, 0x12, 0x3e, 0x36, 0x21, 0x70, 0x19, 0x70, 0xd5, 0xee, 0x75, 0x18, 0x16, 0xf3, 0xc9, 0x0c, - 0xe6, 0x4f, 0x38, 0xd1, 0x54, 0xf8, 0x2a, 0x7d, 0xad, 0xac, 0xeb, 0x33, 0xef, 0x39, 0x79, 0xb6, 0x2d, 0x7e, 0xa5, - 0x75, 0xb1, 0x62, 0xa0, 0x17, 0x01, 0xdf, 0x56, 0xf3, 0x7d, 0x59, 0xdf, 0x85, 0xfa, 0xf4, 0x11, 0xd8, 0x0c, 0xf6, - 0xa0, 0x43, 0x77, 0x63, 0x32, 0x4a, 0xad, 0x9b, 0x67, 0xf6, 0xf6, 0xe3, 0xaf, 0x7b, 0xff, 0xd7, 0x53, 0x0c, 0xd1, - 0x0b, 0x60, 0x8a, 0x49, 0x5f, 0x47, 0x28, 0x3b, 0x64, 0x89, 0x69, 0x47, 0x2a, 0x51, 0x74, 0x45, 0x62, 0x96, 0xa5, - 0x00, 0xe5, 0x1b, 0xab, 0x47, 0x84, 0x6b, 0x25, 0x39, 0x80, 0x50, 0xab, 0x08, 0xde, 0x26, 0xd3, 0xfb, 0xaa, 0xd8, - 0x50, 0xc0, 0x02, 0xe6, 0xeb, 0x18, 0x76, 0x91, 0x41, 0xbe, 0xfe, 0x4b, 0xf6, 0x73, 0xc2, 0xe1, 0xc8, 0x05, 0x02, - 0x28, 0xd3, 0x76, 0x21, 0x4d, 0xf8, 0x75, 0xf1, 0xb6, 0x2a, 0xbe, 0x42, 0x6a, 0x49, 0x39, 0xd0, 0x4b, 0xf4, 0x7f, - 0xdd, 0x1d, 0xde, 0xc9, 0xe7, 0x27, 0x46, 0x3d, 0x11, 0x6e, 0x79, 0xf6, 0x95, 0x65, 0x56, 0xb9, 0xe2, 0xfe, 0xd0, - 0x61, 0x42, 0xb9, 0xdb, 0x33, 0xc9, 0xea, 0x44, 0xad, 0xc2, 0x0c, 0x7d, 0xe5, 0xfe, 0x67, 0xb6, 0x97, 0x7b, 0xae, - 0xf2, 0x50, 0x2c, 0x1c, 0xf8, 0xa2, 0xa1, 0xf1, 0x19, 0xa2, 0x21, 0xca, 0x8c, 0xd5, 0x80, 0x0d, 0xa0, 0xb4, 0xcf, - 0x87, 0x05, 0x2b, 0x99, 0x3a, 0x31, 0xaa, 0x34, 0x22, 0x83, 0x04, 0x53, 0xe0, 0xb9, 0xb4, 0x39, 0x14, 0x88, 0xa0, - 0x59, 0xa4, 0xd0, 0xe8, 0x47, 0x3a, 0xac, 0x71, 0x73, 0xa1, 0xee, 0x31, 0x64, 0x04, 0xc1, 0xc0, 0xb2, 0x79, 0x21, - 0x07, 0x1b, 0x45, 0xe1, 0xd4, 0x8f, 0x01, 0x05, 0xe5, 0x3f, 0xcc, 0x7c, 0xa9, 0xd9, 0x71, 0xc7, 0x6a, 0xc0, 0x17, - 0xf9, 0xf2, 0x7b, 0xe8, 0x2a, 0x94, 0x68, 0xe4, 0x26, 0x37, 0x49, 0x59, 0x04, 0xd1, 0xc3, 0x9f, 0xa0, 0x4a, 0x8a, - 0x98, 0x2e, 0xe2, 0x86, 0xd6, 0x5c, 0x2c, 0x64, 0xb2, 0xab, 0x07, 0x6e, 0x7d, 0xa3, 0x59, 0x4d, 0xf4, 0xea, 0xd8, - 0xbf, 0x90, 0x88, 0x4e, 0x58, 0x3c, 0x91, 0x57, 0x2c, 0x84, 0x19, 0x0c, 0x04, 0x28, 0xda, 0x36, 0x4a, 0xc5, 0xe8, - 0x75, 0x9f, 0xcf, 0x8e, 0xf3, 0xbd, 0xd8, 0x86, 0xa4, 0xd2, 0xe8, 0xc3, 0x00, 0x5a, 0xfd, 0xb4, 0x25, 0x5f, 0xb0, - 0xf8, 0x9f, 0xe4, 0x84, 0xb7, 0x3d, 0xf4, 0x14, 0xe2, 0x53, 0x0f, 0xd0, 0xf9, 0x2e, 0x81, 0xc2, 0xf4, 0xd2, 0x45, - 0xf0, 0xa8, 0x44, 0xdd, 0x98, 0x13, 0x4b, 0x9e, 0x43, 0x8b, 0x1f, 0xa8, 0xf1, 0x6b, 0x7b, 0xc5, 0xa0, 0x43, 0xe2, - 0x05, 0x05, 0x54, 0x45, 0x57, 0xb2, 0xf9, 0x94, 0x3a, 0x6d, 0x63, 0xb5, 0x58, 0x09, 0xde, 0xb4, 0x52, 0xeb, 0x9d, - 0x8a, 0x29, 0xbc, 0x1f, 0x2c, 0x20, 0x2c, 0x6a, 0x45, 0x62, 0xc9, 0x2f, 0x49, 0x8b, 0x5d, 0x00, 0x6d, 0x42, 0x41, - 0x98, 0x9d, 0xbd, 0x66, 0xec, 0xfb, 0x72, 0xa2, 0x17, 0xe5, 0x35, 0xe2, 0x1e, 0x0e, 0x01, 0x80, 0x61, 0xbf, 0x37, - 0x43, 0x31, 0xd2, 0xe1, 0xc2, 0x99, 0x9b, 0x24, 0x90, 0xb0, 0x4d, 0x42, 0x66, 0x67, 0xbb, 0x0c, 0xef, 0xff, 0xb7, - 0x86, 0x73, 0x83, 0xb5, 0x12, 0x6e, 0x1d, 0x5d, 0x65, 0x82, 0xbc, 0xb2, 0x8a, 0xea, 0x65, 0xee, 0xb8, 0xeb, 0xe5, - 0x40, 0x54, 0x5a, 0x8c, 0x67, 0xab, 0xf0, 0xb0, 0x4c, 0xe1, 0xb1, 0x6d, 0x41, 0x76, 0xe6, 0x25, 0xb8, 0x04, 0x44, - 0x1f, 0x64, 0x7c, 0xe4, 0x9d, 0x2c, 0xb0, 0x3c, 0x1b, 0x7f, 0xae, 0x5c, 0xef, 0x83, 0xf8, 0xd0, 0x45, 0x1a, 0xd7, - 0xd3, 0xe9, 0x1d, 0x4a, 0x32, 0xc1, 0xb4, 0xbb, 0x09, 0x8b, 0x55, 0x3b, 0x31, 0xf9, 0x46, 0x41, 0xdc, 0x80, 0xd4, - 0xbe, 0x1b, 0x07, 0xb2, 0x0d, 0xac, 0x37, 0x1f, 0xa3, 0x68, 0xe0, 0x7a, 0x44, 0x9c, 0x9b, 0xf5, 0xda, 0xb5, 0x69, - 0x41, 0x00, 0x52, 0x30, 0x6b, 0x09, 0xce, 0xbb, 0x72, 0x12, 0x80, 0x10, 0x5b, 0x00, 0x31, 0xdd, 0x40, 0x82, 0x3c, - 0xa2, 0x5a, 0x93, 0xd1, 0x37, 0x4b, 0x8f, 0x9f, 0x77, 0xc4, 0x1e, 0x2c, 0xda, 0xac, 0xe9, 0xe5, 0x0b, 0xb6, 0xfb, - 0xb9, 0x1d, 0xd4, 0x28, 0x27, 0xcf, 0x1a, 0xd9, 0x0d, 0x9b, 0x5b, 0xc7, 0xf2, 0x30, 0xa3, 0x87, 0x20, 0x96, 0xcc, - 0x7b, 0x47, 0x8b, 0x95, 0x50, 0x1d, 0xfc, 0x42, 0x50, 0x70, 0xb4, 0xfe, 0x0f, 0xda, 0x24, 0x63, 0x9b, 0x96, 0x35, - 0x6f, 0x2d, 0xce, 0x9a, 0xc2, 0xca, 0x25, 0xb3, 0xd4, 0xfb, 0xc5, 0x14, 0xf5, 0x54, 0xbe, 0xb5, 0x5a, 0xf6, 0x75, - 0x72, 0xd4, 0xd0, 0x1e, 0x79, 0x2f, 0x80, 0xc1, 0xb2, 0x35, 0xcd, 0xa2, 0x98, 0xc2, 0x8d, 0x63, 0xf9, 0xc6, 0x57, - 0x8b, 0x2f, 0x24, 0x4e, 0x98, 0xdb, 0x78, 0x92, 0x47, 0x32, 0x0e, 0xef, 0x53, 0x28, 0xdc, 0x08, 0xa5, 0x85, 0x29, - 0xe9, 0x38, 0x01, 0xc7, 0x6a, 0xb7, 0x5b, 0x51, 0x89, 0xd5, 0xc2, 0xd2, 0x78, 0x06, 0x30, 0x93, 0xd5, 0x8e, 0xb7, - 0x2a, 0x18, 0x6a, 0x90, 0x5c, 0xcc, 0x20, 0x98, 0xe9, 0x39, 0x63, 0x67, 0x5e, 0xe5, 0x17, 0x68, 0x6b, 0x63, 0x16, - 0x16, 0x5a, 0x36, 0x66, 0x76, 0x16, 0x25, 0x80, 0x35, 0x82, 0x5e, 0x4b, 0xe9, 0xee, 0xb9, 0x8e, 0xf8, 0xeb, 0x72, - 0xe4, 0x7c, 0xc5, 0x60, 0x3e, 0xf6, 0x2a, 0x7b, 0x9c, 0x7a, 0xf0, 0x22, 0xc0, 0x8c, 0x30, 0x61, 0xab, 0x7c, 0x82, - 0xf6, 0x6c, 0xe9, 0x3f, 0xf0, 0x0d, 0x6c, 0x8a, 0xd1, 0xcc, 0x18, 0x3b, 0x67, 0x96, 0x57, 0xf1, 0xae, 0x86, 0x35, - 0x64, 0x11, 0x63, 0xfa, 0x9c, 0x35, 0xc5, 0xdc, 0x46, 0x17, 0xf5, 0x15, 0x24, 0x82, 0xe5, 0xab, 0x0c, 0x03, 0x10, - 0x0e, 0x66, 0x37, 0x9a, 0x74, 0xb1, 0x01, 0xed, 0xf3, 0x7b, 0x20, 0x04, 0x06, 0x30, 0x5d, 0x9c, 0x0b, 0x34, 0xd1, - 0x01, 0x64, 0xf9, 0x03, 0x04, 0x00, 0x92, 0xc0, 0x0c, 0x45, 0x02, 0x44, 0xaf, 0x5a, 0xfa, 0x9a, 0x97, 0x97, 0xd8, - 0xe8, 0x31, 0x23, 0x08, 0xb6, 0x72, 0x97, 0xa2, 0xa0, 0xcc, 0xd6, 0x81, 0xae, 0xc7, 0xb7, 0x67, 0x55, 0x25, 0x29, - 0x42, 0x7e, 0x63, 0x44, 0xe5, 0x9f, 0x8d, 0xc5, 0xcc, 0xa6, 0xcc, 0x25, 0x3d, 0xf4, 0x2c, 0x93, 0xc5, 0x74, 0xb3, - 0x9f, 0x4f, 0x96, 0xa0, 0xd8, 0x43, 0x42, 0x76, 0xb1, 0xb0, 0xc1, 0xb6, 0x68, 0x28, 0x24, 0xf5, 0x8f, 0xa3, 0xf3, - 0x27, 0xf5, 0x28, 0x2a, 0x67, 0xcb, 0x7a, 0x42, 0xed, 0x98, 0x6b, 0x37, 0x02, 0x6b, 0x52, 0x9e, 0x0f, 0x9b, 0xb1, - 0xa5, 0x7e, 0xa9, 0x50, 0xca, 0xce, 0xac, 0x93, 0xd8, 0xc9, 0x79, 0xa1, 0xfa, 0xba, 0x4d, 0x32, 0x21, 0x8c, 0x03, - 0x63, 0x7f, 0x3a, 0x1b, 0x77, 0xbf, 0xe7, 0x17, 0x44, 0x2a, 0xe7, 0xc2, 0xb4, 0x0f, 0xd9, 0x5a, 0x35, 0x31, 0x05, - 0x9a, 0xf5, 0x34, 0x83, 0x8b, 0x04, 0xfa, 0x3c, 0x04, 0x7b, 0xa6, 0x5f, 0x85, 0x4c, 0x3b, 0x88, 0xf5, 0x07, 0x6d, - 0xfc, 0x88, 0xaf, 0x51, 0x22, 0xc3, 0xdf, 0x39, 0x01, 0x3a, 0x7e, 0x60, 0x49, 0xd8, 0x92, 0xc4, 0xdd, 0x5c, 0xa4, - 0xb2, 0xf1, 0x7d, 0xdc, 0x06, 0x72, 0x41, 0x14, 0x78, 0xae, 0x03, 0xdc, 0xc7, 0x98, 0x73, 0xaa, 0x1e, 0x35, 0xec, - 0xd7, 0xb4, 0x54, 0xf8, 0xb5, 0x70, 0x10, 0xb0, 0x0a, 0x20, 0xa1, 0xbf, 0xbc, 0x41, 0xcf, 0x99, 0x9d, 0x57, 0x0c, - 0x59, 0x20, 0x2e, 0x75, 0xe5, 0x2d, 0x74, 0x12, 0x00, 0x10, 0x5d, 0x11, 0x63, 0x80, 0x57, 0x3b, 0x6a, 0xfc, 0x02, - 0x0e, 0xbd, 0xd3, 0xba, 0xad, 0xb9, 0x9b, 0x40, 0x14, 0x21, 0x20, 0x40, 0x62, 0x6b, 0x28, 0x88, 0xbc, 0xe5, 0x20, - 0x92, 0x2a, 0xb1, 0xfb, 0x4a, 0x2b, 0x34, 0x0b, 0x6e, 0xa4, 0x23, 0xd2, 0x08, 0xa0, 0x57, 0xb0, 0x21, 0x66, 0x04, - 0xaa, 0x5c, 0x47, 0x1a, 0xbf, 0x44, 0xe3, 0xe0, 0xb5, 0x4a, 0xf4, 0x39, 0x65, 0xbd, 0xf7, 0x20, 0x5e, 0xcf, 0xad, - 0x55, 0xd7, 0xe7, 0x84, 0x10, 0x7d, 0x01, 0x6b, 0x28, 0x9b, 0x3f, 0x65, 0x27, 0xc0, 0x68, 0x20, 0x67, 0xfb, 0x32, - 0x57, 0x1d, 0x96, 0x77, 0x35, 0xcf, 0x1a, 0xdc, 0x94, 0x79, 0x44, 0x2e, 0x5d, 0x55, 0xed, 0x26, 0xae, 0x17, 0xb5, - 0x0b, 0x00, 0xc0, 0x63, 0xf5, 0x52, 0xee, 0x14, 0xb4, 0xa1, 0xf8, 0xc7, 0xba, 0xd2, 0xec, 0x8d, 0xf2, 0x8b, 0xe9, - 0xac, 0xa5, 0xe8, 0xb0, 0xde, 0x43, 0x6e, 0x56, 0x45, 0x05, 0xc0, 0x6a, 0xb7, 0xc2, 0x38, 0x4f, 0x6f, 0xfd, 0xbd, - 0x76, 0x5b, 0xab, 0x0d, 0xa6, 0x45, 0x9d, 0x67, 0x0d, 0x05, 0xe5, 0xd5, 0xb4, 0xfe, 0x17, 0x9e, 0xdd, 0xe5, 0x49, - 0x67, 0xcc, 0x54, 0x61, 0x9c, 0xba, 0xdb, 0xbc, 0xff, 0xfd, 0xcb, 0xb0, 0x25, 0xc4, 0x4e, 0x75, 0xeb, 0x7b, 0xad, - 0x7c, 0x32, 0xf3, 0xa3, 0xce, 0x70, 0xe3, 0x16, 0xb6, 0x19, 0x7b, 0x4d, 0x31, 0xa2, 0x9b, 0x65, 0x61, 0xbf, 0xac, - 0x9c, 0x36, 0xc2, 0xbe, 0xdb, 0xcf, 0xc7, 0x3e, 0xcc, 0x5d, 0x1f, 0x34, 0x75, 0xbc, 0x1d, 0x87, 0xa6, 0x40, 0x83, - 0x75, 0xc0, 0x30, 0x1f, 0xd0, 0xdf, 0xcd, 0x60, 0x90, 0x9a, 0x3c, 0x7a, 0x53, 0xb4, 0x42, 0xf4, 0x62, 0xf0, 0xa5, - 0x3a, 0x11, 0x8b, 0xd4, 0x91, 0x0a, 0xd0, 0xfa, 0x7e, 0xba, 0xac, 0x1a, 0x43, 0xe8, 0xd3, 0x6e, 0x23, 0xd7, 0xd8, - 0x41, 0x5a, 0x7c, 0x6e, 0x18, 0x3f, 0x90, 0x09, 0xc3, 0x37, 0x4d, 0x99, 0xbb, 0x6c, 0xab, 0xbf, 0xac, 0x24, 0xb9, - 0xeb, 0x96, 0x5e, 0x89, 0xce, 0x2a, 0x4c, 0xfd, 0x5a, 0x7d, 0x3f, 0x53, 0x4f, 0xa5, 0x5f, 0x6d, 0xa1, 0xea, 0xc8, - 0x72, 0x21, 0xc1, 0x69, 0x58, 0xb8, 0x56, 0x87, 0x33, 0xa7, 0x6e, 0xd6, 0xd9, 0x0e, 0x4e, 0xe0, 0x64, 0xc9, 0xa9, - 0xc5, 0x94, 0xbc, 0x89, 0x06, 0xc1, 0x61, 0x43, 0x50, 0xd8, 0x5c, 0x14, 0x37, 0x91, 0x50, 0x7d, 0xb3, 0x43, 0x8b, - 0xd3, 0x55, 0xf0, 0xcc, 0x57, 0x7d, 0x4f, 0xc2, 0x33, 0x36, 0x8b, 0x39, 0x53, 0xcd, 0x4b, 0xcd, 0x65, 0xd4, 0x00, - 0xa3, 0x7f, 0xc2, 0xcb, 0xef, 0x89, 0xbb, 0xf5, 0x20, 0x53, 0x52, 0xe5, 0x52, 0x4e, 0x51, 0xb5, 0x8a, 0x6b, 0x5b, - 0x43, 0xd1, 0x6b, 0x87, 0x47, 0xa6, 0x33, 0xb9, 0x0f, 0xde, 0x67, 0x85, 0xe7, 0x90, 0xe5, 0x4b, 0x2b, 0x81, 0x8d, - 0xb8, 0x55, 0xdd, 0xe6, 0x90, 0x6b, 0x2e, 0x4f, 0xe1, 0x79, 0x34, 0x14, 0xd3, 0x79, 0x79, 0x49, 0xef, 0x3b, 0x48, - 0x03, 0xe9, 0xe2, 0xca, 0x44, 0x6f, 0xef, 0xab, 0xea, 0xba, 0x03, 0x6d, 0x6f, 0x7a, 0x44, 0xa2, 0x6e, 0xbb, 0xaa, - 0x3a, 0xaf, 0x98, 0xda, 0x44, 0x37, 0x87, 0x96, 0xc0, 0x7f, 0x75, 0x79, 0x5c, 0x35, 0x5f, 0x02, 0x21, 0xa5, 0x44, - 0xb8, 0xe5, 0xd2, 0x73, 0xd7, 0x65, 0x10, 0x4e, 0x68, 0x8d, 0x4a, 0xd5, 0x6d, 0xc2, 0x4d, 0x56, 0x3d, 0x14, 0x04, - 0xea, 0x9f, 0x4b, 0x11, 0x8e, 0xbe, 0xba, 0x60, 0xda, 0x16, 0x9f, 0xbc, 0xb0, 0xae, 0x49, 0xd7, 0x1e, 0x56, 0xd0, - 0x61, 0x87, 0x95, 0xb4, 0xda, 0xb6, 0x25, 0x2e, 0x5a, 0x62, 0x7c, 0x43, 0xf7, 0x21, 0xb9, 0x61, 0xd9, 0x59, 0x01, - 0x1c, 0x0f, 0x4e, 0xbc, 0x15, 0xbe, 0xaf, 0x71, 0xbf, 0xa4, 0x51, 0x8b, 0xa7, 0x1b, 0x88, 0xf5, 0x02, 0xce, 0x08, - 0x39, 0x96, 0x1f, 0xb0, 0x71, 0x22, 0xd0, 0x6d, 0x99, 0xfe, 0x5f, 0x21, 0x95, 0xc5, 0xb2, 0x43, 0x80, 0x5b, 0xdc, - 0x45, 0x7e, 0x20, 0xad, 0x00, 0x64, 0x0a, 0xa4, 0x50, 0x88, 0xb7, 0x86, 0xfd, 0x43, 0x46, 0xf3, 0x93, 0xe6, 0xb1, - 0x65, 0x27, 0x3a, 0x84, 0xcc, 0x91, 0x22, 0x18, 0xb7, 0x5a, 0xa5, 0x6c, 0x3c, 0xbd, 0xc3, 0x31, 0xa2, 0x58, 0x5a, - 0xe3, 0xbf, 0x56, 0x55, 0xb8, 0x05, 0xec, 0xe6, 0x49, 0xcd, 0x5e, 0x2b, 0xb8, 0x44, 0xf6, 0x06, 0x8f, 0x4e, 0x15, - 0x3b, 0x0b, 0xa3, 0x66, 0x95, 0x2c, 0xf0, 0xf0, 0xd8, 0x17, 0xd6, 0xf1, 0x3f, 0x89, 0x04, 0xe5, 0xfb, 0xef, 0x12, - 0x27, 0x15, 0x0a, 0x85, 0x7d, 0x9a, 0x0f, 0xdb, 0x57, 0x0c, 0x28, 0x5b, 0xb0, 0xee, 0x89, 0x3c, 0x6e, 0x82, 0xab, - 0xaa, 0x03, 0x30, 0xba, 0x49, 0x2e, 0x4f, 0x08, 0x6e, 0x72, 0x15, 0x5a, 0x1b, 0xe4, 0x28, 0x1d, 0x70, 0x4a, 0xe4, - 0x56, 0x61, 0x8a, 0xe0, 0x12, 0xed, 0xa0, 0x44, 0x09, 0x86, 0x5b, 0x54, 0x83, 0xb2, 0x49, 0x3d, 0x52, 0x04, 0x7f, - 0x9d, 0x80, 0x0e, 0xc0, 0x3c, 0x2c, 0x9f, 0x72, 0x8d, 0xe0, 0x65, 0x64, 0xa5, 0x74, 0xd4, 0x1c, 0x83, 0x89, 0xa9, - 0x4c, 0x72, 0x4d, 0x27, 0x3c, 0x98, 0x36, 0xe2, 0x5c, 0x39, 0xa8, 0xed, 0x41, 0x3c, 0x09, 0xc3, 0x46, 0x9d, 0xf4, - 0x17, 0xfc, 0xf3, 0x51, 0x62, 0x30, 0xa1, 0xdd, 0x2c, 0xd1, 0x8b, 0xb0, 0x97, 0xf3, 0x72, 0xd2, 0xcd, 0x3a, 0x05, - 0x60, 0xab, 0xe5, 0x62, 0x07, 0x0c, 0x8c, 0x22, 0x7f, 0x04, 0xe4, 0x8a, 0x4f, 0x9f, 0x96, 0x2a, 0x1e, 0x8d, 0x59, - 0x9e, 0x70, 0xf1, 0xc9, 0x97, 0x36, 0x1b, 0x94, 0x8e, 0x26, 0x1d, 0xdf, 0x1a, 0x13, 0xbe, 0x93, 0xce, 0xc6, 0x2a, - 0x9c, 0x83, 0x28, 0x46, 0xa1, 0x1d, 0xd9, 0xa8, 0xac, 0xcb, 0x1c, 0xb6, 0x6f, 0x20, 0xd2, 0xeb, 0xb4, 0x22, 0xa4, - 0x6a, 0x41, 0xa6, 0xee, 0x70, 0x8a, 0x2b, 0x87, 0x50, 0xea, 0x99, 0x83, 0x32, 0xcc, 0x70, 0x94, 0x71, 0x75, 0xa7, - 0x91, 0x32, 0x20, 0x15, 0x22, 0x61, 0xce, 0x9c, 0xd6, 0xde, 0xe2, 0x04, 0x9b, 0xbd, 0x33, 0xf3, 0x69, 0xc2, 0xf5, - 0x5a, 0xd8, 0xd8, 0x39, 0xd6, 0x15, 0xb0, 0x6b, 0xcb, 0xe9, 0x46, 0x64, 0xaa, 0x9e, 0x1e, 0x0c, 0x39, 0x67, 0x56, - 0xd2, 0xf5, 0x5e, 0x3e, 0xaf, 0x39, 0xb4, 0x92, 0xee, 0x2b, 0x4b, 0x68, 0xc0, 0x10, 0xc7, 0xee, 0x8f, 0x9f, 0xe8, - 0xe0, 0x4f, 0xbe, 0xdc, 0xf8, 0xe4, 0xa7, 0xf6, 0x82, 0x53, 0x89, 0xb3, 0x41, 0xad, 0x95, 0x22, 0x99, 0xde, 0x98, - 0x31, 0x10, 0x12, 0x27, 0x34, 0xdc, 0xc3, 0x4b, 0x06, 0x8c, 0x62, 0xb4, 0x5e, 0x55, 0xa4, 0x4d, 0x6a, 0x80, 0x88, - 0x26, 0xdd, 0x21, 0xcd, 0xaa, 0x4e, 0xca, 0x32, 0x15, 0x57, 0x33, 0x57, 0x66, 0xca, 0xda, 0xd1, 0x50, 0x7b, 0x8b, - 0x90, 0x78, 0xa8, 0xe4, 0xdb, 0x81, 0xe3, 0x31, 0x0a, 0x62, 0x49, 0xa9, 0xf4, 0x2f, 0x4e, 0x3b, 0x3d, 0x7e, 0x8c, - 0xe2, 0x5e, 0x78, 0x93, 0x75, 0x8c, 0x61, 0x30, 0x9b, 0x0e, 0xf6, 0x43, 0x36, 0x22, 0xb1, 0x97, 0xb9, 0xb1, 0xd3, - 0xdd, 0x76, 0xd4, 0xe1, 0xc3, 0xc2, 0x78, 0x35, 0x7b, 0xec, 0x01, 0xb4, 0x2a, 0x58, 0xea, 0x54, 0x61, 0x3b, 0xfc, - 0xe2, 0xbf, 0xf2, 0x45, 0x7a, 0x50, 0x97, 0x0e, 0x89, 0xd6, 0x36, 0x24, 0x98, 0x07, 0x49, 0x91, 0x95, 0x5d, 0x82, - 0xb2, 0x66, 0xc5, 0xfa, 0x33, 0x05, 0x9f, 0x85, 0xe3, 0x9f, 0x4c, 0xbf, 0xec, 0xe5, 0x32, 0x9e, 0xf5, 0x75, 0xe6, - 0x2a, 0xb7, 0x9c, 0xa3, 0x64, 0x06, 0x77, 0x2c, 0xec, 0x75, 0x41, 0x8e, 0x71, 0x61, 0x03, 0xa0, 0x72, 0x8c, 0x41, - 0xc6, 0xa3, 0x87, 0x8e, 0x84, 0xf2, 0x30, 0x8e, 0xfe, 0x89, 0x1f, 0x5e, 0x47, 0x8d, 0x20, 0x43, 0x5c, 0x8a, 0x79, - 0xe1, 0xf1, 0x9c, 0x0d, 0x2e, 0xf1, 0x5c, 0x78, 0x87, 0xa3, 0x59, 0x1c, 0xc3, 0x79, 0x67, 0x8b, 0x56, 0xe5, 0x15, - 0xad, 0x1c, 0x57, 0x2e, 0xa4, 0x8b, 0x5e, 0xd6, 0x20, 0x0f, 0xa9, 0xa2, 0xc5, 0x6d, 0x38, 0x4d, 0x23, 0x13, 0x29, - 0x3b, 0x1b, 0x4f, 0x67, 0xa7, 0x2c, 0xed, 0x69, 0x39, 0x2c, 0x4b, 0x8a, 0xba, 0x90, 0x28, 0xcc, 0x1c, 0x92, 0x98, - 0x0a, 0x86, 0x5a, 0x6a, 0xcb, 0xb2, 0xa8, 0xa3, 0x18, 0x2a, 0x4d, 0x8d, 0x91, 0xa2, 0x5b, 0x4a, 0xf1, 0x2f, 0xb5, - 0x1c, 0x97, 0x5e, 0x1a, 0x0c, 0x23, 0x93, 0x47, 0x61, 0x19, 0xeb, 0x4b, 0x39, 0xbc, 0x74, 0xd3, 0x2f, 0xed, 0xee, - 0x35, 0xdd, 0x15, 0x82, 0xb6, 0x4c, 0xbe, 0xa9, 0xff, 0x83, 0xe6, 0x96, 0x3d, 0x60, 0x6c, 0xf6, 0xe3, 0xc3, 0x61, - 0xd3, 0xc6, 0x98, 0x95, 0x72, 0x8a, 0x8c, 0x9d, 0xaf, 0xd2, 0xc6, 0xd2, 0x51, 0xdf, 0xdd, 0x1d, 0x16, 0xc1, 0x61, - 0xf5, 0xe6, 0x08, 0x04, 0x59, 0x1b, 0x1f, 0x5c, 0x82, 0x36, 0xdd, 0xa4, 0x4b, 0x1f, 0x1e, 0x95, 0x21, 0x86, 0xbd, - 0x46, 0x2b, 0x46, 0xa0, 0xe7, 0xd2, 0xc6, 0xae, 0x80, 0x07, 0x23, 0x50, 0xc4, 0x45, 0xc7, 0x96, 0xb2, 0x9a, 0xb2, - 0x1a, 0x60, 0xce, 0x1a, 0xc4, 0x73, 0xd4, 0x99, 0x86, 0x7a, 0xee, 0x9e, 0xf4, 0x80, 0x11, 0x3b, 0x72, 0xf6, 0xeb, - 0x68, 0x31, 0xb4, 0x6c, 0xdd, 0xae, 0x6d, 0xda, 0xb8, 0x56, 0x4a, 0x0c, 0x78, 0xb4, 0x6e, 0x40, 0x6c, 0x13, 0x99, - 0xe9, 0x50, 0x28, 0xfc, 0xb8, 0x15, 0x3e, 0x63, 0xfd, 0x19, 0x0f, 0xd9, 0x53, 0x16, 0x37, 0xd1, 0xcc, 0x26, 0x58, - 0x82, 0xdf, 0x99, 0x0a, 0x22, 0xe3, 0x5d, 0xa7, 0xd2, 0x39, 0x42, 0xde, 0x94, 0x7a, 0xf4, 0x59, 0xa0, 0x2c, 0x8d, - 0xa8, 0xc4, 0xd1, 0xa8, 0x1a, 0x0b, 0xff, 0x77, 0xf6, 0x12, 0xdd, 0xc2, 0xbf, 0x56, 0xd8, 0x70, 0x5f, 0x11, 0x1b, - 0x97, 0x70, 0xcc, 0xf4, 0x6a, 0xdb, 0x9d, 0x15, 0x22, 0x28, 0xe0, 0xf3, 0x45, 0xef, 0xcd, 0x66, 0x9a, 0x09, 0x1a, - 0xef, 0xf0, 0xf4, 0x34, 0xcd, 0x67, 0xe4, 0x46, 0x68, 0xa6, 0x61, 0x6d, 0x4a, 0x8c, 0x83, 0xc0, 0xc5, 0x9e, 0x40, - 0x73, 0x53, 0x06, 0x26, 0x98, 0xe7, 0xc5, 0x96, 0x4f, 0xda, 0x3a, 0xdb, 0x03, 0x69, 0xb8, 0x69, 0x78, 0x7a, 0x57, - 0xda, 0x3e, 0xa6, 0xb3, 0xb8, 0xaa, 0xb5, 0xce, 0xda, 0x60, 0x14, 0x3f, 0xa0, 0x5f, 0x13, 0x41, 0xab, 0x97, 0x24, - 0x99, 0xa0, 0x39, 0xb4, 0x18, 0x65, 0xaf, 0x3a, 0xe3, 0xa4, 0x07, 0x68, 0xc9, 0xb8, 0x20, 0x6d, 0x75, 0xd9, 0x12, - 0x32, 0x47, 0xd1, 0x06, 0x68, 0x4a, 0x5a, 0xb1, 0x47, 0x5c, 0x65, 0x22, 0xff, 0xbc, 0xd0, 0xdb, 0x15, 0x61, 0xb9, - 0xfd, 0x5d, 0xe9, 0x86, 0x45, 0x5d, 0xec, 0xdf, 0x9f, 0x80, 0x35, 0xf2, 0x8f, 0xa1, 0xfd, 0x51, 0x40, 0x34, 0xfc, - 0xac, 0xe0, 0x76, 0xd0, 0x66, 0xaf, 0xec, 0xd7, 0x36, 0xf5, 0x53, 0x8b, 0xdd, 0xf0, 0xc8, 0xe1, 0x3f, 0x73, 0xb2, - 0x86, 0xa7, 0x3c, 0x70, 0xbd, 0x30, 0xb9, 0xfd, 0xc5, 0xdd, 0x8a, 0xde, 0xf2, 0x39, 0x6a, 0x37, 0xad, 0x7c, 0x28, - 0x06, 0x2f, 0x77, 0x6a, 0x77, 0xa2, 0x16, 0x35, 0x04, 0xa4, 0x5a, 0x38, 0x27, 0xae, 0x9f, 0x15, 0xa4, 0x05, 0x5a, - 0x98, 0xd3, 0xd1, 0x2d, 0x89, 0xf7, 0xac, 0x21, 0xeb, 0xa7, 0x0b, 0xb0, 0xe9, 0xd6, 0x2f, 0x90, 0x4a, 0x8a, 0x99, - 0x2c, 0xcd, 0x26, 0x14, 0x5f, 0x71, 0xd4, 0x69, 0x3a, 0xb8, 0x2f, 0xa1, 0x0d, 0xd4, 0xb0, 0xee, 0xc6, 0xe3, 0xfc, - 0xa9, 0xda, 0x13, 0x06, 0xdc, 0x30, 0x56, 0x87, 0xfc, 0x05, 0x69, 0x40, 0x6f, 0x47, 0x33, 0x2b, 0xb2, 0x1f, 0x04, - 0x03, 0xf0, 0xa9, 0xab, 0x80, 0x68, 0x81, 0x7e, 0xcb, 0x87, 0x13, 0x85, 0x2a, 0x88, 0x51, 0xd9, 0x1b, 0x60, 0x19, - 0xa0, 0xc8, 0xb6, 0x65, 0xf1, 0x5e, 0xb6, 0x62, 0x44, 0xdb, 0x97, 0xd0, 0x99, 0x3e, 0xc8, 0x10, 0x56, 0x5d, 0x21, - 0xc0, 0x9c, 0xee, 0x84, 0x6f, 0xeb, 0x7c, 0xf8, 0xdc, 0x19, 0x7b, 0xde, 0xd1, 0x2d, 0x6e, 0xcb, 0x32, 0x0d, 0x0d, - 0x55, 0x32, 0x0e, 0xdd, 0x8b, 0xd6, 0x96, 0xe2, 0xd6, 0xb5, 0x42, 0x3c, 0xfe, 0x42, 0x9e, 0x18, 0x93, 0xde, 0x85, - 0xc8, 0x30, 0x23, 0x98, 0x99, 0x45, 0xbd, 0xb4, 0xcc, 0x87, 0xc9, 0xe9, 0xa2, 0x81, 0xa0, 0x15, 0x7c, 0x5b, 0x0f, - 0xae, 0x8b, 0x3a, 0x7c, 0xbf, 0xae, 0x12, 0xad, 0x6f, 0xfa, 0xa9, 0xdf, 0x20, 0xbb, 0x9c, 0xe3, 0xa0, 0xcb, 0x0b, - 0x38, 0xbe, 0x0f, 0x2e, 0x6d, 0x58, 0xed, 0x6d, 0xaa, 0xf9, 0x27, 0xcc, 0xf2, 0x2d, 0x09, 0xcb, 0x4f, 0x1d, 0x0e, - 0x46, 0x09, 0x19, 0x4e, 0x3e, 0xc2, 0xb9, 0xb0, 0x45, 0x97, 0x7c, 0xb2, 0xa3, 0xa5, 0xa7, 0x81, 0x15, 0xd1, 0x2e, - 0xfc, 0x86, 0x6f, 0xeb, 0xb6, 0x10, 0x41, 0xdc, 0x60, 0x19, 0x03, 0x9e, 0x91, 0xca, 0x89, 0x54, 0x75, 0x98, 0xc0, - 0x34, 0x97, 0x30, 0x0d, 0xec, 0xd6, 0x00, 0x9a, 0x39, 0x99, 0x94, 0xb8, 0x02, 0x7d, 0x2a, 0xd5, 0xce, 0xab, 0x92, - 0x8c, 0xfe, 0x42, 0xd0, 0xce, 0xf5, 0x62, 0x46, 0x99, 0x97, 0xdb, 0xcd, 0x2e, 0xd2, 0xbc, 0x26, 0xc5, 0xd0, 0x0e, - 0x64, 0x76, 0x35, 0x0e, 0x99, 0xba, 0x4b, 0x6e, 0x3c, 0x38, 0xa9, 0x2e, 0x0c, 0xc2, 0x01, 0x42, 0x91, 0xa6, 0xd5, - 0x76, 0x08, 0xb3, 0xe8, 0xad, 0x29, 0xbc, 0x3b, 0x14, 0xae, 0x96, 0x08, 0x28, 0x41, 0xc4, 0x49, 0x2f, 0x3a, 0x54, - 0xf1, 0xe0, 0x6e, 0xd4, 0x9d, 0x41, 0x74, 0x95, 0x8b, 0xe5, 0x72, 0x7c, 0xaf, 0xc5, 0x9d, 0x60, 0x5a, 0x3d, 0xf6, - 0x7e, 0x20, 0x46, 0x7b, 0xbe, 0x11, 0x5a, 0x22, 0xfb, 0x0c, 0x55, 0xa5, 0xf7, 0xed, 0x87, 0xb4, 0x42, 0x4f, 0xe1, - 0xb1, 0x5a, 0x21, 0x51, 0xec, 0xd4, 0xb9, 0x0b, 0x34, 0x2b, 0x11, 0x77, 0x59, 0x26, 0x1e, 0x42, 0xbf, 0xab, 0x71, - 0xb7, 0x65, 0xd6, 0x27, 0x81, 0xb8, 0x9e, 0x44, 0x8a, 0xe5, 0x60, 0xad, 0xe1, 0x1d, 0xa9, 0xf3, 0x34, 0x78, 0x9b, - 0x73, 0xeb, 0x97, 0x4c, 0x35, 0x8e, 0x16, 0xb1, 0xfc, 0x21, 0x3d, 0x32, 0xa2, 0x00, 0xd5, 0xbf, 0xe9, 0x08, 0x48, - 0x5c, 0x99, 0xf1, 0xfb, 0xaa, 0xe3, 0x7a, 0x6e, 0xdd, 0xf0, 0x2c, 0xb1, 0x22, 0x62, 0xe1, 0xfc, 0x7d, 0x0d, 0x10, - 0x28, 0x2c, 0x67, 0x1b, 0xae, 0x79, 0x38, 0xea, 0xb2, 0xeb, 0xc1, 0x9d, 0xc2, 0x98, 0xba, 0x4e, 0x47, 0xd4, 0x1b, - 0xee, 0x6a, 0x2d, 0xd6, 0x12, 0xde, 0x54, 0x5a, 0x6c, 0x4e, 0x73, 0xc5, 0x1a, 0x97, 0x4d, 0x95, 0x5a, 0x27, 0x30, - 0xe9, 0x5a, 0xa7, 0x3f, 0x8e, 0xa1, 0x86, 0x32, 0x11, 0xd7, 0x44, 0x1d, 0x5c, 0x96, 0x4d, 0x51, 0xee, 0x32, 0xc1, - 0x49, 0xb2, 0xc1, 0x1d, 0x10, 0xa9, 0x5a, 0x5c, 0xe6, 0xb8, 0x69, 0x43, 0xa4, 0xf8, 0x4e, 0xba, 0xa6, 0x48, 0x8a, - 0xd3, 0xf4, 0xc2, 0xd3, 0xca, 0xf2, 0xa7, 0x4e, 0x69, 0x36, 0xbd, 0x43, 0x8a, 0xac, 0x28, 0x24, 0xee, 0x15, 0x14, - 0xe3, 0xa1, 0x45, 0x7f, 0x96, 0x39, 0x22, 0x3b, 0xd8, 0xde, 0x2d, 0xd7, 0x0d, 0xef, 0xbd, 0x3f, 0x5f, 0x8e, 0x44, - 0x74, 0x61, 0x7c, 0xb9, 0x84, 0x34, 0x4a, 0xf6, 0x13, 0x91, 0x17, 0x26, 0xa4, 0xb3, 0x57, 0x45, 0x02, 0x8e, 0xf4, - 0xca, 0x45, 0x5a, 0x57, 0xae, 0x15, 0xa1, 0xf7, 0x8b, 0x00, 0xef, 0x98, 0x51, 0x21, 0x66, 0x46, 0x8d, 0xe2, 0xfd, - 0x24, 0x42, 0x6c, 0x66, 0x2a, 0x36, 0x64, 0x53, 0x33, 0xd7, 0x1d, 0xca, 0x5c, 0x86, 0x4a, 0x1c, 0x89, 0x46, 0xe5, - 0x10, 0x1c, 0x9d, 0xb9, 0xde, 0xa3, 0xb0, 0xae, 0x60, 0xce, 0x5c, 0x30, 0xf2, 0x60, 0x75, 0xb1, 0xfe, 0xc2, 0x9d, - 0xa0, 0x3f, 0x4e, 0x44, 0xbf, 0xf3, 0x52, 0x53, 0x0d, 0xf0, 0xd0, 0x6c, 0xbb, 0x4e, 0xa0, 0x31, 0x05, 0x5a, 0x20, - 0xbd, 0x9a, 0x20, 0x68, 0xf8, 0xa4, 0x19, 0xe6, 0xa0, 0xa7, 0xfa, 0xe6, 0xd7, 0x2f, 0x2d, 0x6c, 0xcb, 0xb4, 0xad, - 0x30, 0x86, 0x5d, 0x1a, 0xb8, 0x33, 0x29, 0x34, 0xc4, 0xb0, 0xf5, 0xe1, 0x6c, 0x9b, 0xc8, 0xe5, 0xbe, 0x67, 0xb5, - 0x90, 0x4c, 0xd3, 0x19, 0x8e, 0xfc, 0xfb, 0xa4, 0xb3, 0x09, 0xc7, 0x31, 0x28, 0x3d, 0xf9, 0xb2, 0x25, 0x27, 0x35, - 0x4a, 0xeb, 0xd6, 0xd5, 0x05, 0x5c, 0x4f, 0x46, 0x32, 0x10, 0x0f, 0xd3, 0x88, 0xe5, 0x07, 0x70, 0x4d, 0xe5, 0x65, - 0x47, 0x1b, 0x7b, 0x20, 0x01, 0x58, 0xb6, 0x6b, 0x5e, 0x66, 0xd5, 0xc8, 0x57, 0x71, 0xc5, 0xe2, 0xeb, 0x9d, 0x64, - 0xca, 0x44, 0xb0, 0xaf, 0xe2, 0xdb, 0x17, 0xcc, 0x27, 0xb5, 0xb7, 0x43, 0xb4, 0x33, 0x8b, 0x84, 0xfd, 0x6a, 0x9b, - 0xb0, 0x90, 0x87, 0x07, 0x21, 0x61, 0xe3, 0x02, 0x36, 0x13, 0xf4, 0xe9, 0xd8, 0x2c, 0xe4, 0xae, 0xbb, 0xee, 0xbe, - 0x5b, 0xfe, 0xe4, 0xc6, 0x04, 0xb0, 0xe8, 0x96, 0x08, 0x2c, 0x24, 0x2a, 0x63, 0xa2, 0x74, 0x63, 0x7e, 0xae, 0xf6, - 0x7c, 0x55, 0x2a, 0xb5, 0x9a, 0x3d, 0x3f, 0xf0, 0xee, 0x78, 0xf8, 0xae, 0x8d, 0xeb, 0x4c, 0x68, 0x95, 0x79, 0xaf, - 0xfb, 0x07, 0x80, 0x9d, 0x79, 0x38, 0xef, 0x26, 0xf3, 0x9d, 0xa4, 0x5b, 0xa5, 0xcd, 0x3b, 0x61, 0x5a, 0xf8, 0xe5, - 0x17, 0x62, 0xaf, 0xf8, 0x4a, 0x07, 0xd1, 0xaf, 0x7a, 0xc1, 0x46, 0x13, 0x13, 0xf2, 0xec, 0x75, 0x44, 0x8b, 0x7e, - 0x6c, 0xa0, 0xe9, 0x9b, 0x72, 0x59, 0xea, 0x94, 0x61, 0xea, 0x90, 0xfd, 0xe1, 0x51, 0x1d, 0x06, 0xd0, 0xdc, 0x26, - 0x01, 0xf1, 0x5f, 0x40, 0xe6, 0xdc, 0x41, 0x80, 0x13, 0x45, 0x92, 0x8e, 0x5f, 0xfa, 0xf4, 0x1a, 0x9a, 0x3c, 0xcc, - 0x9a, 0x0d, 0xc5, 0x65, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x43, 0x83, 0xa8, 0xb3, 0xf7, 0x88, 0x6e, 0x2f, 0xed, 0xdd, - 0x97, 0x77, 0xef, 0x28, 0x59, 0x27, 0xa1, 0x62, 0x30, 0xa1, 0xfc, 0x4b, 0xd9, 0xcf, 0x69, 0x4f, 0xa5, 0x2b, 0x7b, - 0xa1, 0xe0, 0xd3, 0xda, 0xa0, 0x1a, 0x3b, 0xb0, 0x80, 0xf6, 0x22, 0x01, 0x15, 0xbb, 0xad, 0xb0, 0xae, 0x0a, 0x6c, - 0x3f, 0x89, 0xba, 0x92, 0x79, 0x28, 0xc0, 0xe1, 0xbf, 0x34, 0x84, 0x24, 0x64, 0x31, 0xf7, 0xeb, 0xab, 0x23, 0x6c, - 0xeb, 0xb8, 0xc6, 0x6c, 0x1e, 0xea, 0xa4, 0x87, 0xe5, 0x98, 0x37, 0xff, 0x83, 0x0a, 0x22, 0x2e, 0xab, 0xf1, 0x77, - 0x6d, 0x97, 0x76, 0xf4, 0x3a, 0x0c, 0x2b, 0x19, 0xab, 0x28, 0xff, 0xb0, 0x57, 0x3d, 0x72, 0x82, 0xf8, 0xdf, 0x81, - 0xd2, 0xbf, 0xa6, 0xb9, 0xe1, 0xed, 0x44, 0x3c, 0x4c, 0x52, 0x6d, 0xa6, 0x22, 0x0e, 0xa7, 0x74, 0xbf, 0x22, 0x19, - 0xd2, 0x44, 0xa2, 0x87, 0x4f, 0xf2, 0x91, 0xc6, 0xc3, 0x2a, 0x65, 0x1b, 0x32, 0x6c, 0xb6, 0xc6, 0x82, 0xa6, 0xed, - 0x73, 0xf7, 0xe7, 0x53, 0x6f, 0x86, 0x6a, 0x9d, 0xc0, 0xe6, 0xa5, 0x87, 0x2d, 0xb6, 0xee, 0x29, 0xa6, 0x7e, 0x0a, - 0xaa, 0x72, 0xc4, 0x1b, 0x62, 0x62, 0xaf, 0x54, 0x08, 0x3c, 0xf3, 0xe4, 0xc2, 0xc7, 0xc1, 0xfa, 0x8b, 0x63, 0x1f, - 0x2f, 0x70, 0xfe, 0x98, 0x9d, 0xe1, 0x9e, 0x8f, 0xbc, 0x7e, 0xcd, 0x8a, 0xdc, 0x11, 0x3b, 0x1d, 0xc5, 0x43, 0x2e, - 0xba, 0x13, 0xaa, 0x4a, 0x58, 0x2e, 0xcc, 0x55, 0xcb, 0xb5, 0x31, 0x28, 0x15, 0xca, 0x8a, 0xdc, 0x07, 0x7c, 0xb3, - 0xfb, 0x89, 0x55, 0xbe, 0x07, 0x65, 0x81, 0xef, 0x93, 0x08, 0xa4, 0xfa, 0x47, 0x99, 0x62, 0x0e, 0x98, 0x97, 0x66, - 0x17, 0xa9, 0x3f, 0xa1, 0x94, 0x03, 0x0f, 0x01, 0xdf, 0x1c, 0x70, 0x69, 0x68, 0xeb, 0x7f, 0xd0, 0xbe, 0xe7, 0x79, - 0xdb, 0xa7, 0x6c, 0x07, 0x4e, 0x62, 0x48, 0x09, 0x3b, 0x99, 0xa6, 0xa7, 0x38, 0xf7, 0x1e, 0x2b, 0xb4, 0xfa, 0x76, - 0xba, 0x6f, 0xd8, 0x1a, 0x2f, 0x5f, 0x28, 0xde, 0xb5, 0xa9, 0xfc, 0x49, 0x64, 0x51, 0x48, 0x6a, 0xb2, 0x67, 0xca, - 0x99, 0x5c, 0x9c, 0x15, 0x9e, 0x37, 0x18, 0xaa, 0x78, 0xc4, 0xd5, 0x12, 0xe7, 0xec, 0x3d, 0xba, 0x8a, 0x13, 0xde, - 0x90, 0x06, 0x02, 0x54, 0xb2, 0x0b, 0x8e, 0x18, 0x28, 0x6b, 0xcb, 0xfa, 0xb2, 0xdd, 0xed, 0xc7, 0x3a, 0xdc, 0xc1, - 0xd1, 0x48, 0x55, 0x45, 0xbe, 0x46, 0x07, 0x22, 0x63, 0x20, 0xa8, 0xf5, 0xfc, 0x26, 0xba, 0xd0, 0xfc, 0x6c, 0x92, - 0x58, 0x7f, 0x97, 0x75, 0xa3, 0xe4, 0x3f, 0xeb, 0x71, 0xe7, 0x08, 0x90, 0xc7, 0x79, 0x99, 0xc1, 0xc8, 0x97, 0x09, - 0xd1, 0x38, 0x1f, 0x7b, 0xb6, 0x86, 0xc0, 0x73, 0x8d, 0x16, 0x8b, 0x5e, 0x53, 0xc8, 0x7e, 0x6b, 0x76, 0x36, 0x12, - 0x2e, 0x3c, 0xce, 0x2e, 0xdc, 0x09, 0x17, 0x7e, 0xc3, 0x42, 0x7a, 0x0f, 0xb3, 0xe9, 0x78, 0x68, 0x16, 0x80, 0x52, - 0x43, 0xe2, 0xbf, 0xe8, 0xe3, 0xfd, 0xc4, 0x79, 0x9e, 0x36, 0x5b, 0x5e, 0xb4, 0x62, 0xc6, 0xf8, 0xfa, 0x76, 0x4b, - 0xb8, 0x0c, 0x34, 0x71, 0x8a, 0x98, 0xcf, 0x19, 0x46, 0x26, 0x8c, 0x86, 0xea, 0xf5, 0xf8, 0x02, 0x6f, 0x40, 0xc8, - 0x58, 0xb6, 0xd6, 0x6d, 0xed, 0x06, 0x5a, 0x6f, 0xb9, 0x48, 0xfb, 0x94, 0x6e, 0x22, 0x09, 0xd9, 0x78, 0x3e, 0x71, - 0xa6, 0xba, 0xd0, 0x4b, 0x83, 0xfd, 0x89, 0xc4, 0x8d, 0xf3, 0x47, 0x30, 0x04, 0xc7, 0xc1, 0x2e, 0xf8, 0x74, 0x9c, - 0x70, 0xb1, 0x38, 0x90, 0x91, 0x7a, 0x39, 0xbd, 0xd4, 0x47, 0x9b, 0x87, 0x57, 0x70, 0xe1, 0x7c, 0xf7, 0x88, 0xd5, - 0x2e, 0x8f, 0x06, 0x18, 0xd8, 0x8c, 0x9c, 0x90, 0xab, 0x39, 0x12, 0xfd, 0x92, 0x69, 0x6c, 0xd6, 0x50, 0xe7, 0x72, - 0x62, 0x29, 0xa6, 0x40, 0xae, 0x91, 0x4b, 0xbf, 0xc5, 0xf3, 0x57, 0x90, 0x6b, 0x58, 0x7e, 0xf0, 0x8d, 0x72, 0x39, - 0xb3, 0x4b, 0x75, 0xf7, 0x23, 0xc7, 0x9d, 0xeb, 0x5c, 0x1e, 0x7f, 0x03, 0x99, 0xcf, 0xf6, 0x85, 0xdf, 0xee, 0x6f, - 0x36, 0x35, 0xc7, 0x3f, 0xbd, 0x51, 0x0f, 0x36, 0xbb, 0xde, 0xde, 0xcb, 0x6f, 0xc1, 0x97, 0xf5, 0xf7, 0x08, 0x51, - 0x8f, 0xd3, 0xaa, 0x30, 0x2f, 0xb6, 0x6e, 0xfe, 0xeb, 0x37, 0xfb, 0x25, 0xe4, 0x66, 0x1f, 0xa2, 0x04, 0xd7, 0x1c, - 0x51, 0xe5, 0x2b, 0xb7, 0x6b, 0xd8, 0x91, 0x83, 0xbf, 0x2e, 0xa7, 0x9c, 0x77, 0xb5, 0x09, 0xad, 0x6d, 0x92, 0xe3, - 0x66, 0xdd, 0x55, 0x21, 0xb8, 0xc2, 0x99, 0xe8, 0xd6, 0x36, 0xac, 0x42, 0x4c, 0x96, 0x6f, 0xef, 0x0c, 0xee, 0x57, - 0x61, 0xc2, 0xde, 0x9e, 0x7b, 0xb3, 0x1c, 0xf8, 0x33, 0x90, 0x77, 0x99, 0xa5, 0xd5, 0x6f, 0x7e, 0x5e, 0xe5, 0xbe, - 0x0f, 0x78, 0xd3, 0xff, 0x57, 0x50, 0x9d, 0x39, 0x17, 0x2e, 0x5e, 0x5c, 0x88, 0xaf, 0x74, 0x83, 0x4b, 0xe8, 0x36, - 0xc7, 0x79, 0x03, 0x5f, 0x3a, 0x5c, 0x55, 0xf0, 0x3c, 0xb4, 0x64, 0x94, 0x47, 0xb5, 0x1c, 0x9b, 0xb9, 0x13, 0xb0, - 0x6c, 0x2b, 0xf3, 0x5b, 0x6c, 0x14, 0x00, 0x93, 0x2a, 0x48, 0x86, 0x32, 0x84, 0x7f, 0x86, 0x98, 0xfb, 0xaa, 0x70, - 0xf9, 0x4a, 0x44, 0xc7, 0x6e, 0xd7, 0x48, 0x4d, 0x8b, 0x2e, 0x82, 0xcb, 0x06, 0xf5, 0xe3, 0x9d, 0xf0, 0x0f, 0xf5, - 0xef, 0x73, 0xed, 0x84, 0x7f, 0xce, 0xb5, 0x11, 0xfe, 0x5e, 0x29, 0x21, 0xfc, 0xb3, 0xd2, 0x85, 0xa9, 0xb5, 0xe3, - 0xac, 0xaf, 0x5d, 0xd8, 0xd7, 0x76, 0xf6, 0x18, 0xa8, 0x3d, 0xb4, 0xf7, 0x75, 0x0e, 0xda, 0x89, 0xfd, 0x5a, 0x6f, - 0xc9, 0x01, 0x9f, 0xd7, 0x55, 0x96, 0x6c, 0x7c, 0xbe, 0xe8, 0xee, 0x73, 0xaa, 0x56, 0x3a, 0x1e, 0xa0, 0xfc, 0xe2, - 0x71, 0x58, 0xd7, 0x55, 0x94, 0xcd, 0x99, 0xa5, 0xd2, 0x4a, 0x67, 0x77, 0x0f, 0xc5, 0xd3, 0xc9, 0x23, 0xe8, 0x4c, - 0xd7, 0x70, 0x46, 0x2a, 0x13, 0xf8, 0x45, 0xd2, 0x8f, 0x8d, 0x4a, 0x2f, 0x1a, 0x2f, 0xde, 0x3d, 0x30, 0xe7, 0xf9, - 0xcb, 0x59, 0x44, 0x64, 0x5a, 0x41, 0xec, 0x1d, 0x4c, 0xc3, 0x61, 0xd6, 0x62, 0xbb, 0x03, 0x32, 0xdb, 0xb2, 0x95, - 0x58, 0x20, 0x84, 0xa1, 0x6d, 0xe1, 0xbf, 0x09, 0xd0, 0xaa, 0x36, 0x32, 0x49, 0xe6, 0x66, 0x4c, 0x9a, 0x46, 0xcf, - 0x41, 0x83, 0xd8, 0x0f, 0x65, 0xba, 0x23, 0x4e, 0x39, 0x3c, 0xaf, 0xe2, 0x0a, 0xb2, 0xfa, 0x13, 0xa5, 0xf8, 0x25, - 0x67, 0x0f, 0x77, 0x9f, 0x04, 0x34, 0xf8, 0x7f, 0x4d, 0xb6, 0x83, 0xfe, 0x84, 0xb6, 0xc6, 0x29, 0x97, 0x44, 0xda, - 0x2f, 0x94, 0xbc, 0x3d, 0xf7, 0x25, 0xbb, 0xbe, 0x75, 0xc6, 0x70, 0x7e, 0x6e, 0x42, 0x20, 0x77, 0xd5, 0x7e, 0xba, - 0xbf, 0x1f, 0x53, 0x91, 0x4d, 0xd7, 0x3d, 0x27, 0x58, 0xe3, 0x40, 0x2a, 0xd9, 0xcc, 0xe4, 0xfc, 0xfc, 0xd5, 0xff, - 0xd2, 0xdf, 0xa7, 0x94, 0x83, 0xbe, 0xe8, 0x4f, 0x7e, 0x77, 0x9c, 0x28, 0xa7, 0x5e, 0xe7, 0xcb, 0x07, 0xcf, 0x2a, - 0xe5, 0x7a, 0x40, 0xd7, 0x71, 0xba, 0xeb, 0x9f, 0xd4, 0x19, 0xed, 0xd0, 0x7c, 0x36, 0xfd, 0xcf, 0x29, 0xe5, 0x80, - 0xaf, 0xfa, 0xf3, 0xe9, 0x3d, 0x2c, 0xfe, 0xa1, 0x19, 0x7c, 0x64, 0x0b, 0x00, 0xe1, 0xf9, 0x51, 0xb5, 0x39, 0x0e, - 0x39, 0x93, 0x3b, 0xd7, 0x15, 0x5e, 0x51, 0xb5, 0x1a, 0x02, 0xb9, 0x58, 0x81, 0x2b, 0xf2, 0x31, 0x4f, 0x64, 0xe3, - 0x1b, 0xb0, 0x4b, 0x99, 0xbd, 0xc7, 0x2b, 0xd2, 0x6e, 0x9b, 0x4f, 0xf1, 0x89, 0x3e, 0x7f, 0x89, 0xba, 0xc9, 0x35, - 0xbc, 0x82, 0xb5, 0xa5, 0xa9, 0x38, 0x78, 0xc0, 0xbe, 0x23, 0x14, 0x06, 0xab, 0x91, 0xda, 0x07, 0x41, 0x4e, 0x6f, - 0x73, 0xb4, 0xc1, 0x38, 0x93, 0xbd, 0xdf, 0xc6, 0x82, 0xa5, 0xf0, 0xf8, 0xa1, 0x63, 0xb7, 0xa0, 0x1d, 0x3e, 0xe5, - 0xa2, 0xff, 0x02, 0xc6, 0xf0, 0x62, 0x00, 0x4e, 0xbc, 0xca, 0xa6, 0xeb, 0x2f, 0xc3, 0x99, 0x6f, 0x74, 0x2d, 0x57, - 0xd6, 0xee, 0xd7, 0xd0, 0xb5, 0x39, 0x3a, 0x93, 0xdc, 0x25, 0xa8, 0x30, 0xc2, 0x9c, 0xe1, 0xc5, 0x7b, 0xb3, 0x36, - 0xe6, 0x0c, 0x63, 0xa2, 0xd7, 0x82, 0x90, 0xd1, 0x7f, 0x26, 0xb8, 0xe6, 0x99, 0x36, 0x98, 0xb7, 0xfd, 0x7b, 0xec, - 0xd0, 0x36, 0x3b, 0xea, 0xad, 0xc6, 0xf7, 0x89, 0x34, 0x18, 0x95, 0x46, 0x63, 0x7d, 0x71, 0xfc, 0x6b, 0x90, 0xeb, - 0x34, 0xd3, 0x9f, 0xe1, 0xec, 0x4c, 0x5b, 0x3b, 0x6f, 0xde, 0xcc, 0xdc, 0xab, 0xe7, 0xf7, 0xfb, 0xe3, 0xfa, 0x68, - 0x18, 0x97, 0x8c, 0xb4, 0x20, 0x37, 0xcd, 0x5f, 0x55, 0x8f, 0xcd, 0x33, 0x73, 0x3c, 0x52, 0x3f, 0xf6, 0x4c, 0x01, - 0x1b, 0xe3, 0xbc, 0x46, 0x9a, 0xf1, 0x59, 0x5e, 0xc7, 0x9d, 0xc9, 0x82, 0x0d, 0x71, 0x3e, 0xdc, 0xde, 0xde, 0x77, - 0xc8, 0x0e, 0x34, 0xf9, 0xcd, 0xc7, 0xa2, 0x78, 0xe7, 0x3b, 0xbf, 0x03, 0xc5, 0xac, 0x6f, 0x97, 0x14, 0x1b, 0xd4, - 0x15, 0x98, 0x0d, 0xb8, 0xfc, 0xb2, 0x5d, 0x84, 0xbb, 0xa6, 0xaf, 0x8e, 0x27, 0x58, 0x52, 0x42, 0x68, 0xa5, 0xe0, - 0xb0, 0xd8, 0x34, 0xa3, 0x28, 0x2d, 0xd6, 0x49, 0xbf, 0xb1, 0x99, 0xb8, 0x5c, 0xbb, 0x81, 0x73, 0x83, 0xa0, 0x56, - 0x71, 0x56, 0xf4, 0x73, 0x44, 0xde, 0xe1, 0x97, 0xb9, 0x6a, 0x1b, 0x88, 0xe1, 0x25, 0xae, 0x59, 0x45, 0xf6, 0xf8, - 0x13, 0x06, 0xf4, 0xa8, 0x8f, 0xce, 0x21, 0x78, 0xf8, 0xa1, 0xc7, 0x32, 0x6f, 0xb6, 0x74, 0x78, 0xe7, 0x58, 0x57, - 0xdd, 0xa9, 0xf5, 0xd4, 0xfc, 0x35, 0xa9, 0xcd, 0xca, 0xd3, 0x11, 0x55, 0x43, 0xa2, 0xf6, 0x6a, 0x7c, 0xf6, 0xe3, - 0x41, 0xa5, 0x3d, 0x9b, 0x5f, 0x26, 0x5e, 0x18, 0x69, 0x79, 0x98, 0x78, 0x18, 0xc7, 0x41, 0x8a, 0x9a, 0xca, 0x2b, - 0xfe, 0x31, 0x18, 0x16, 0x71, 0xcd, 0xf6, 0xdb, 0x75, 0xf0, 0x4a, 0x48, 0xe9, 0xca, 0xb5, 0xd7, 0x15, 0xe8, 0xd8, - 0xe1, 0x57, 0xf7, 0xd3, 0xe9, 0x4c, 0x80, 0xca, 0x5f, 0x85, 0x49, 0xc0, 0x40, 0x24, 0xc2, 0x13, 0xcd, 0xc2, 0x8b, - 0xc2, 0x0f, 0x60, 0x8e, 0x99, 0x61, 0x35, 0xc0, 0x53, 0xd1, 0x5f, 0xaf, 0x0b, 0x61, 0x1d, 0x8e, 0xe0, 0x45, 0x6e, - 0x6f, 0x3e, 0xe6, 0xa1, 0x43, 0x91, 0x31, 0x72, 0xe6, 0x0d, 0x4b, 0xca, 0x1b, 0xea, 0xfd, 0x2a, 0x14, 0x7f, 0x03, - 0x83, 0x38, 0x67, 0x03, 0x50, 0x48, 0xed, 0x79, 0x04, 0x00, 0x4b, 0xf2, 0x89, 0x19, 0x78, 0xc3, 0xfb, 0xc1, 0x5e, - 0xb1, 0x5f, 0xfd, 0xce, 0xc5, 0x69, 0x16, 0xee, 0xcc, 0xfb, 0xc4, 0x18, 0xd9, 0x3d, 0x45, 0x10, 0x01, 0x92, 0x2c, - 0xa4, 0x13, 0x7b, 0x0f, 0xf1, 0x2b, 0x03, 0xcc, 0xc0, 0x24, 0x03, 0x38, 0x61, 0x3a, 0xd2, 0xba, 0xe1, 0x27, 0xd7, - 0x86, 0xad, 0xdc, 0x16, 0x4a, 0xb0, 0x88, 0xcc, 0xa3, 0xdb, 0x49, 0x9a, 0xa5, 0x74, 0xdf, 0xec, 0xf3, 0x41, 0xc6, - 0xf1, 0x97, 0xca, 0x79, 0xe2, 0x38, 0x7f, 0x43, 0x10, 0xad, 0x88, 0x28, 0x4f, 0xb7, 0x2e, 0x22, 0xbf, 0x83, 0x52, - 0x31, 0x01, 0xa8, 0x46, 0xc0, 0x54, 0x53, 0xac, 0xf9, 0xc5, 0x1d, 0xd0, 0xcb, 0x07, 0xda, 0x13, 0x8a, 0xfb, 0x59, - 0xa4, 0x58, 0x0f, 0xfb, 0x20, 0xb3, 0xb0, 0xcb, 0xc5, 0x68, 0xb3, 0x63, 0x29, 0x4b, 0xab, 0x68, 0x82, 0x01, 0x0d, - 0x66, 0x38, 0x9d, 0xf4, 0xfe, 0x51, 0x60, 0x66, 0xd3, 0x05, 0x3d, 0xc7, 0xa5, 0xd0, 0x6d, 0x0e, 0x0b, 0x21, 0x8e, - 0x86, 0xd0, 0xe7, 0x61, 0x28, 0x8c, 0x7e, 0x56, 0x9f, 0x58, 0x7d, 0xd6, 0xaf, 0xc5, 0x68, 0xad, 0x31, 0x63, 0x53, - 0x5d, 0x76, 0x5d, 0x01, 0xd8, 0xc8, 0x38, 0x83, 0x15, 0xf0, 0xe7, 0xab, 0x76, 0xb9, 0x46, 0xbc, 0xb1, 0xc9, 0xbf, - 0xb4, 0xc9, 0x6f, 0xa4, 0x9f, 0xc0, 0x8b, 0x90, 0xcc, 0xed, 0x09, 0xac, 0xa9, 0x9c, 0x97, 0xc4, 0x01, 0xd1, 0xe3, - 0x7c, 0x3f, 0x08, 0xfe, 0xa4, 0xb5, 0x78, 0x50, 0x6c, 0x61, 0xd2, 0x4a, 0xa9, 0x13, 0xf5, 0x6a, 0x9d, 0x36, 0xf2, - 0x41, 0x62, 0x12, 0x31, 0xa1, 0xba, 0xb3, 0x9f, 0xe6, 0x59, 0xcd, 0x82, 0xd9, 0x26, 0x2a, 0xf6, 0x0a, 0xdb, 0xb9, - 0x9d, 0x33, 0x24, 0xd9, 0x11, 0x9c, 0xea, 0xb2, 0x6c, 0xb8, 0xbb, 0x6d, 0x4d, 0xdf, 0x2c, 0x7c, 0x4d, 0xd7, 0x70, - 0x8c, 0xbb, 0xa0, 0x73, 0x6b, 0xbc, 0x25, 0xb6, 0x07, 0x83, 0x87, 0xc5, 0x93, 0xb3, 0x53, 0x35, 0xdd, 0x34, 0x32, - 0x73, 0x73, 0xaf, 0xa9, 0xab, 0x85, 0x76, 0x95, 0x80, 0xf9, 0x6c, 0x14, 0xaf, 0xb1, 0x65, 0xae, 0x91, 0x63, 0x6b, - 0x89, 0xbb, 0x65, 0xde, 0xb1, 0x18, 0xb9, 0x1b, 0x18, 0x15, 0xe6, 0x2e, 0x62, 0x98, 0xf9, 0x39, 0xf4, 0xf6, 0xc4, - 0x04, 0x42, 0xfd, 0xdb, 0x7a, 0x32, 0x83, 0x8b, 0x59, 0x1a, 0xc9, 0xb0, 0x1e, 0x94, 0xbd, 0x27, 0x5a, 0xfa, 0x88, - 0xe7, 0x82, 0xc1, 0xb6, 0x6d, 0x8f, 0x9b, 0x9d, 0x19, 0x03, 0x1f, 0x9a, 0x72, 0x07, 0xc1, 0x55, 0x79, 0x05, 0xcd, - 0x33, 0x78, 0x0c, 0x62, 0xf6, 0xed, 0x30, 0x9f, 0x17, 0xa2, 0x6e, 0x9f, 0xe8, 0xe2, 0xbf, 0x80, 0x50, 0xcc, 0x6e, - 0x75, 0xfe, 0xec, 0x5c, 0xbf, 0x0e, 0x1e, 0xb2, 0xc0, 0x63, 0x49, 0x52, 0x64, 0xf8, 0x37, 0x1d, 0x6d, 0x19, 0x8b, - 0x9e, 0x39, 0x8f, 0x5b, 0x12, 0x13, 0x4a, 0x75, 0x86, 0x91, 0x44, 0x79, 0x3d, 0xc2, 0xa2, 0x0a, 0xb1, 0xdb, 0x26, - 0xa4, 0x72, 0x74, 0x45, 0x64, 0x8a, 0x27, 0xc9, 0xcd, 0xce, 0x30, 0x1a, 0x41, 0x86, 0x82, 0x09, 0xaa, 0xda, 0xf7, - 0xa3, 0x39, 0x61, 0x1e, 0xac, 0x69, 0xa2, 0x1e, 0xde, 0x30, 0x65, 0x2c, 0x3c, 0x49, 0xee, 0x6d, 0x47, 0xcc, 0xad, - 0xeb, 0x38, 0x5f, 0x3c, 0x59, 0xb6, 0x72, 0x64, 0x89, 0xab, 0x8a, 0xd6, 0x94, 0xed, 0x83, 0x5a, 0x44, 0x94, 0xa1, - 0x44, 0xc2, 0x81, 0x2d, 0xa8, 0xb7, 0x97, 0xda, 0x6c, 0x20, 0xdc, 0x2b, 0xeb, 0x83, 0x56, 0xac, 0xa6, 0x6b, 0x2b, - 0xa5, 0x60, 0x01, 0x85, 0xb0, 0xd0, 0xd8, 0xb3, 0x9e, 0xdf, 0xae, 0x6b, 0x8a, 0xd7, 0xb7, 0x88, 0xd8, 0xc2, 0x7f, - 0xbc, 0xff, 0x1c, 0x2b, 0x00, 0xa3, 0xee, 0x59, 0x57, 0x14, 0x6f, 0x8d, 0x78, 0x8b, 0xe2, 0xcd, 0x8f, 0x37, 0xbb, - 0x1f, 0xe8, 0x12, 0x6b, 0x63, 0x36, 0xee, 0x5c, 0xa1, 0x75, 0xd8, 0x97, 0x8c, 0xd4, 0x7e, 0x2f, 0x97, 0x9f, 0xc6, - 0xaa, 0xf4, 0x9f, 0x56, 0x55, 0xca, 0xa6, 0x2f, 0x4e, 0xd5, 0x96, 0x2e, 0x23, 0xa4, 0xee, 0xe5, 0x30, 0xdb, 0xb7, - 0x4e, 0x5d, 0xdd, 0x96, 0xe2, 0xb3, 0x31, 0x31, 0x7e, 0xf9, 0xd7, 0xbb, 0x78, 0xa9, 0x61, 0x3a, 0x74, 0xe5, 0x9d, - 0xf7, 0xcc, 0x60, 0xc6, 0x15, 0x96, 0x84, 0x73, 0x34, 0x8b, 0x90, 0x31, 0xe2, 0xa1, 0xdc, 0xb9, 0x03, 0x6e, 0x23, - 0x08, 0x7c, 0x45, 0x57, 0x55, 0x92, 0x59, 0xea, 0x3b, 0x3a, 0xba, 0x38, 0x2c, 0x36, 0x39, 0xfc, 0xbd, 0x40, 0x41, - 0x6b, 0xbb, 0xaa, 0x5c, 0x3b, 0x57, 0x45, 0x4c, 0x55, 0x11, 0xe7, 0x9c, 0x46, 0xef, 0x89, 0x8d, 0x6f, 0xe6, 0xeb, - 0x29, 0xd5, 0xd0, 0x01, 0x29, 0x66, 0x39, 0x16, 0xe5, 0x54, 0x2c, 0x4a, 0x11, 0xb1, 0x7d, 0x09, 0x43, 0x65, 0x35, - 0x09, 0x44, 0xde, 0xdf, 0xb8, 0x71, 0x2c, 0x5f, 0x06, 0x0c, 0x56, 0xd1, 0x07, 0x82, 0xf3, 0x3b, 0x5d, 0x76, 0xf1, - 0x8f, 0xfe, 0x4a, 0xc9, 0x64, 0xd2, 0x0a, 0x43, 0xe0, 0x8e, 0xf8, 0xed, 0xbb, 0x17, 0xc8, 0x00, 0xe7, 0x8c, 0x1a, - 0x03, 0xe6, 0xdc, 0x34, 0x0d, 0x4e, 0x55, 0xb3, 0x0c, 0xda, 0xcd, 0x2b, 0x54, 0x42, 0x12, 0x43, 0x95, 0x36, 0xc3, - 0xaf, 0xb6, 0x48, 0x40, 0xce, 0x3f, 0x70, 0xb8, 0x72, 0x81, 0x54, 0x2e, 0x36, 0x16, 0x0a, 0x7c, 0xee, 0xc0, 0x2f, - 0xd0, 0xad, 0xf8, 0xe0, 0x1f, 0x67, 0x29, 0x8f, 0x34, 0xa0, 0x07, 0x6a, 0x87, 0x4c, 0x56, 0x2d, 0x39, 0x0a, 0x13, - 0x09, 0xa1, 0x0c, 0x3e, 0xe2, 0x2b, 0x32, 0x17, 0x73, 0xac, 0xeb, 0x9c, 0x9f, 0xe0, 0x36, 0x22, 0x06, 0x44, 0x0d, - 0x21, 0x92, 0x9c, 0xd4, 0xba, 0xa1, 0xc2, 0xe2, 0xe8, 0xd2, 0xa2, 0x88, 0x13, 0x24, 0x3b, 0x2f, 0x04, 0xff, 0x32, - 0x14, 0x33, 0x8d, 0x37, 0xfd, 0x1f, 0x27, 0xba, 0x1a, 0x99, 0xc9, 0x2e, 0x9a, 0x79, 0xd1, 0x13, 0x69, 0xc9, 0xe5, - 0x43, 0xa2, 0xd0, 0x3f, 0x88, 0xa3, 0xb7, 0xac, 0x25, 0x52, 0xb0, 0xa4, 0xcb, 0xda, 0xb2, 0xba, 0xb3, 0xb5, 0x72, - 0x8d, 0xc7, 0xdd, 0x53, 0x08, 0x0a, 0x7c, 0xb7, 0x95, 0xbc, 0x04, 0x2e, 0x92, 0x35, 0xb6, 0xdc, 0x27, 0x62, 0x74, - 0x4c, 0x37, 0x4a, 0x56, 0x47, 0xb6, 0xcf, 0x5f, 0x10, 0x4a, 0x72, 0xba, 0x56, 0x62, 0xeb, 0x7f, 0x8e, 0xba, 0xc9, - 0x45, 0x65, 0xab, 0x0e, 0x39, 0x88, 0x9b, 0xa9, 0x85, 0x30, 0x25, 0x7b, 0x27, 0xb0, 0x11, 0x22, 0xc3, 0xc5, 0x24, - 0x0b, 0x72, 0xee, 0xc5, 0x5f, 0x1c, 0x29, 0xf8, 0x45, 0xa4, 0x86, 0xb6, 0x4c, 0xe9, 0x7f, 0xb4, 0x8e, 0xf0, 0x6d, - 0x8f, 0x93, 0x64, 0xf8, 0xcf, 0x0b, 0x6e, 0x5b, 0x8b, 0x1d, 0xb3, 0x41, 0x12, 0xee, 0x9f, 0x99, 0x3e, 0xeb, 0xed, - 0x41, 0xbc, 0x50, 0x26, 0x04, 0x5e, 0xbd, 0x7c, 0xd3, 0xb3, 0xfa, 0xc3, 0xcb, 0xa8, 0xa4, 0x5a, 0x94, 0xef, 0xc7, - 0x5b, 0x83, 0x3d, 0x2a, 0x2f, 0xe0, 0x6f, 0x3f, 0xce, 0x39, 0x30, 0x0f, 0x5f, 0x69, 0xab, 0xb1, 0x84, 0xbd, 0x30, - 0xd8, 0xeb, 0x50, 0xb2, 0x8c, 0x23, 0xbb, 0xd9, 0x18, 0x73, 0xa1, 0x6b, 0x6d, 0xf6, 0x0f, 0x29, 0xd4, 0xea, 0x4e, - 0xf3, 0x1b, 0xbb, 0xaa, 0x15, 0xe6, 0x36, 0x0d, 0x3b, 0x2a, 0x99, 0x69, 0x5f, 0x6e, 0x30, 0x4d, 0x87, 0xec, 0x6d, - 0xa4, 0xb5, 0x7c, 0x73, 0xac, 0x2b, 0x6f, 0x75, 0x01, 0x85, 0x80, 0x09, 0xe7, 0x9a, 0x2b, 0x72, 0xad, 0x95, 0xfd, - 0x60, 0x8a, 0xfd, 0x7e, 0x06, 0x24, 0xa2, 0x2a, 0x92, 0x9a, 0x4d, 0x7d, 0xac, 0xd5, 0xda, 0x93, 0x86, 0x05, 0x96, - 0x4e, 0x2c, 0xc7, 0x9a, 0x17, 0x0c, 0x86, 0x32, 0x55, 0xab, 0x65, 0xee, 0x70, 0x95, 0x3d, 0xd5, 0xf2, 0x92, 0x57, - 0x0c, 0x1c, 0x24, 0x10, 0x9d, 0xf8, 0x1e, 0xee, 0x49, 0xe4, 0x3b, 0x73, 0xfa, 0xc6, 0x4c, 0x86, 0xa8, 0x2e, 0xc4, - 0x0a, 0x46, 0xd5, 0xdb, 0xc0, 0x50, 0x51, 0x35, 0x36, 0x74, 0x57, 0x7a, 0x69, 0x73, 0x1c, 0xee, 0x0b, 0x7b, 0x7c, - 0x41, 0xee, 0x63, 0xfe, 0x9c, 0xf5, 0xcf, 0x83, 0x2c, 0xa0, 0x5d, 0xd6, 0xdb, 0x8c, 0x91, 0x23, 0xbc, 0xde, 0x52, - 0xa9, 0xb2, 0x05, 0x5d, 0xf6, 0x9a, 0xb8, 0xa7, 0x83, 0xea, 0x89, 0x74, 0x13, 0x33, 0xa2, 0xaa, 0x27, 0x91, 0x24, - 0xe8, 0x8b, 0xcd, 0x20, 0x84, 0xe6, 0x49, 0x5a, 0x47, 0x19, 0xb9, 0x07, 0x75, 0x39, 0x32, 0x11, 0x5d, 0xc2, 0x50, - 0x9c, 0xb3, 0x75, 0x35, 0xc2, 0x90, 0x63, 0x3c, 0x16, 0xab, 0x92, 0x07, 0xf5, 0xbe, 0x85, 0x95, 0x5a, 0xb4, 0xe9, - 0x58, 0x2a, 0x2e, 0x37, 0x80, 0x8d, 0x1d, 0xed, 0xa4, 0x01, 0x73, 0x6a, 0xe7, 0x12, 0xec, 0xe4, 0xa6, 0x7a, 0x87, - 0x24, 0x03, 0x41, 0x1e, 0x08, 0x51, 0x18, 0xf0, 0xd5, 0xba, 0x22, 0x00, 0x34, 0xc7, 0x29, 0x12, 0x7f, 0x18, 0xce, - 0xeb, 0x2f, 0x24, 0x9d, 0x84, 0xe3, 0x6e, 0x2c, 0xf0, 0xf0, 0x79, 0x80, 0x46, 0x69, 0x24, 0x9b, 0xef, 0x81, 0x28, - 0x17, 0xf9, 0xab, 0xd8, 0xe8, 0x88, 0x21, 0xc2, 0x81, 0x1f, 0x77, 0x17, 0x92, 0xd6, 0x5b, 0xe0, 0xf2, 0x68, 0x66, - 0xb4, 0x5d, 0x03, 0x70, 0x1f, 0xa9, 0x01, 0xd0, 0x66, 0x43, 0xae, 0x9f, 0x0f, 0x8f, 0x51, 0xaf, 0x10, 0xde, 0x90, - 0x05, 0x7e, 0x5d, 0xa6, 0x36, 0xb7, 0x30, 0x5a, 0xd3, 0x4c, 0xbc, 0x95, 0x5f, 0xa7, 0xfb, 0xba, 0xdb, 0x31, 0xd0, - 0xbf, 0x5c, 0xe2, 0x88, 0x7c, 0x93, 0x54, 0x71, 0xd0, 0x63, 0x8e, 0x9e, 0xe3, 0x92, 0x66, 0x76, 0x6a, 0xc8, 0x73, - 0x93, 0xf2, 0x19, 0xca, 0x81, 0x86, 0x8f, 0xa7, 0x87, 0xec, 0x79, 0x5c, 0x7a, 0xa8, 0x8b, 0x87, 0x84, 0x32, 0x50, - 0x4f, 0xe0, 0xb9, 0x92, 0x40, 0x58, 0x9a, 0x3f, 0x27, 0xe6, 0x9e, 0x3f, 0x4d, 0x41, 0x45, 0x07, 0x2a, 0x9d, 0x9e, - 0x94, 0x05, 0xa4, 0x1e, 0xea, 0x30, 0xc4, 0x84, 0x07, 0xbd, 0x6c, 0xea, 0x7a, 0x5d, 0x47, 0x23, 0x24, 0x4d, 0x28, - 0x48, 0x5c, 0xe0, 0x14, 0x7d, 0x55, 0x32, 0x7f, 0xad, 0x48, 0x37, 0x8a, 0x54, 0x34, 0xb8, 0x97, 0x68, 0x91, 0x35, - 0x30, 0x46, 0x66, 0x47, 0x9a, 0xb2, 0x56, 0x5b, 0x2f, 0x00, 0x7c, 0x38, 0x04, 0x9f, 0x49, 0x44, 0xcc, 0x93, 0x68, - 0x22, 0x9b, 0x09, 0xe5, 0xcf, 0x7e, 0x6c, 0x14, 0xc0, 0xe5, 0x3c, 0x12, 0x34, 0x11, 0xf8, 0x44, 0x09, 0x38, 0x33, - 0x83, 0x0c, 0x67, 0xab, 0xa6, 0x11, 0x18, 0x0b, 0xad, 0xfd, 0x60, 0xd9, 0x27, 0x1c, 0x94, 0xe3, 0x62, 0x61, 0xe4, - 0x76, 0x2d, 0x8e, 0x5c, 0x2c, 0x12, 0x1b, 0x73, 0xf8, 0x6b, 0xfd, 0xdb, 0x24, 0xfd, 0xcb, 0x14, 0x3e, 0x29, 0x51, - 0x75, 0x1c, 0x29, 0xde, 0x74, 0x31, 0xde, 0x3a, 0xe3, 0x2a, 0xb5, 0x1c, 0x26, 0x0c, 0xa6, 0xb5, 0xff, 0x37, 0x1e, - 0xb5, 0x6d, 0x5f, 0x39, 0x9f, 0x82, 0x2b, 0x1e, 0x83, 0xc3, 0xba, 0x33, 0xe7, 0xd7, 0x4d, 0x13, 0x39, 0xb9, 0xdf, - 0x3f, 0xf4, 0x66, 0xd7, 0xdd, 0x46, 0x56, 0xb9, 0x94, 0xe6, 0xcc, 0x0b, 0xa2, 0x0f, 0x23, 0xcb, 0x67, 0x6b, 0xcc, - 0x09, 0x8d, 0x2f, 0x1d, 0x51, 0x2e, 0x3b, 0x3c, 0x7d, 0x11, 0x88, 0x97, 0xa3, 0x7d, 0xb1, 0x03, 0x62, 0x45, 0x89, - 0xb0, 0x67, 0x2a, 0x22, 0x8d, 0x63, 0x60, 0xbd, 0x0a, 0x47, 0x86, 0xc0, 0x29, 0x63, 0xec, 0x9a, 0xf5, 0x0f, 0x5b, - 0x91, 0x7d, 0x0e, 0xc9, 0x26, 0xcb, 0x66, 0xfc, 0x62, 0x3b, 0x5a, 0xaf, 0x44, 0x52, 0xd1, 0xb2, 0xe9, 0x5f, 0xda, - 0x8e, 0xc6, 0x7b, 0x31, 0x0e, 0x89, 0x23, 0x5c, 0xd2, 0x3b, 0xdf, 0xef, 0x1f, 0x46, 0x1d, 0xfe, 0x19, 0xf5, 0x0f, - 0x3f, 0xf8, 0x0f, 0xff, 0x8c, 0xf6, 0xc5, 0x0f, 0xfe, 0xe2, 0x9f, 0x11, 0xbf, 0xf8, 0x41, 0xa2, 0x4c, 0x9a, 0xbe, - 0x7a, 0x3c, 0x0f, 0xa6, 0x8a, 0xa1, 0x5c, 0x9e, 0x91, 0xad, 0x34, 0xc1, 0x2f, 0x7e, 0x48, 0xb8, 0xcf, 0x06, 0x92, - 0x72, 0x32, 0xb8, 0x60, 0x25, 0x2a, 0x59, 0x29, 0x93, 0x02, 0xf8, 0x34, 0xd4, 0x47, 0x34, 0xdb, 0xf7, 0xfc, 0x3b, - 0x95, 0x48, 0x1a, 0x03, 0xf1, 0x62, 0x0a, 0xba, 0x76, 0x4f, 0x9f, 0x79, 0xae, 0x15, 0x61, 0x94, 0xe5, 0x2c, 0xa3, - 0x5e, 0x21, 0x0e, 0x09, 0x31, 0x72, 0x39, 0x5f, 0xda, 0x2c, 0x04, 0x7d, 0xfb, 0x3e, 0xae, 0x53, 0xe5, 0x78, 0x09, - 0x01, 0x4a, 0xd6, 0x86, 0x40, 0x04, 0xf6, 0xb1, 0x17, 0x5f, 0x63, 0xad, 0xbd, 0x99, 0x54, 0xd1, 0x82, 0x6b, 0x72, - 0x30, 0xa6, 0x08, 0x89, 0x7b, 0xfa, 0x57, 0x2c, 0x26, 0x67, 0xe9, 0xa2, 0xcd, 0x2c, 0xdc, 0x13, 0xf4, 0x1c, 0xd0, - 0xa2, 0x18, 0x55, 0x33, 0xe5, 0x8a, 0x68, 0x34, 0xa7, 0x3d, 0xf3, 0x88, 0x93, 0xa5, 0xd8, 0x2e, 0x0b, 0x77, 0xde, - 0xe3, 0x17, 0xfd, 0x1b, 0x9c, 0xa4, 0x62, 0x9e, 0x05, 0xfb, 0x22, 0xc7, 0xf6, 0xde, 0x15, 0xb6, 0xb5, 0x06, 0xd3, - 0x13, 0xce, 0xd6, 0xe2, 0xfa, 0x6a, 0x06, 0x5f, 0x90, 0xf6, 0x63, 0x5b, 0x8a, 0x68, 0xfc, 0x3d, 0x99, 0xd8, 0x04, - 0xb7, 0x2f, 0xe4, 0x6b, 0x4b, 0x8d, 0x36, 0x2b, 0x96, 0x60, 0xc9, 0xed, 0x57, 0x5f, 0xd2, 0xb0, 0xc9, 0x9c, 0x25, - 0x69, 0x54, 0xdd, 0x04, 0x69, 0x53, 0xe0, 0x8b, 0x93, 0x15, 0xc6, 0x23, 0x90, 0x65, 0xee, 0x30, 0x39, 0x1e, 0x57, - 0xb5, 0x1c, 0x55, 0x09, 0x91, 0xf9, 0xac, 0xc2, 0x5a, 0x2d, 0x41, 0xc7, 0x8b, 0x03, 0x11, 0x42, 0x0e, 0xe3, 0xd2, - 0xa9, 0x65, 0x74, 0x5d, 0xd5, 0xde, 0x42, 0x9e, 0xc3, 0x1c, 0x79, 0x0d, 0xb6, 0x84, 0x92, 0xd5, 0x1c, 0x3d, 0xce, - 0x3c, 0xbb, 0xa1, 0x2b, 0xfb, 0xfd, 0xe3, 0x00, 0x1c, 0xbd, 0xd8, 0x7e, 0xc8, 0xe6, 0xae, 0xcf, 0x48, 0x24, 0x90, - 0x48, 0x7c, 0x01, 0xc0, 0x01, 0x00, 0x57, 0xbd, 0xa2, 0xa8, 0x03, 0x83, 0x56, 0xaa, 0x40, 0xcf, 0x14, 0xbc, 0x04, - 0x99, 0xa1, 0xed, 0xa0, 0xf2, 0x47, 0x94, 0xf0, 0xb5, 0x43, 0xb2, 0x98, 0xf0, 0xd2, 0x50, 0xbc, 0x8e, 0x09, 0xed, - 0xb6, 0x98, 0x99, 0x5e, 0xa2, 0xf0, 0x35, 0x52, 0x3a, 0x62, 0x5b, 0x80, 0x06, 0xe1, 0x39, 0x4f, 0x0b, 0x27, 0x45, - 0xe4, 0xe9, 0xb9, 0xf5, 0x6f, 0x79, 0xbb, 0xae, 0xa9, 0x3f, 0xd2, 0x8a, 0xa6, 0xa0, 0x0d, 0x61, 0xae, 0x9e, 0x56, - 0x3d, 0xa3, 0xaf, 0xe0, 0xcb, 0xa2, 0x1c, 0x7a, 0x7d, 0x93, 0xdb, 0x0d, 0xe9, 0xc3, 0x2b, 0x7a, 0x20, 0x9a, 0x74, - 0xf7, 0x1a, 0x09, 0x34, 0x97, 0x08, 0x16, 0xc3, 0x73, 0x5c, 0xda, 0x8d, 0x9f, 0x72, 0x8a, 0x82, 0x58, 0x05, 0x3e, - 0xa4, 0x87, 0x2f, 0x30, 0x64, 0x18, 0xd7, 0x6d, 0x16, 0xc4, 0xd5, 0x40, 0xeb, 0xfd, 0x57, 0x1c, 0xf6, 0xfa, 0x04, - 0x6c, 0x2c, 0x99, 0xaf, 0xd6, 0x2e, 0x8a, 0xbd, 0xe6, 0x8a, 0x74, 0xd7, 0x76, 0x08, 0xfc, 0xb9, 0xf8, 0xe8, 0x6f, - 0xcf, 0x8b, 0xf2, 0x2c, 0x3e, 0x11, 0xbe, 0x77, 0x8a, 0xf2, 0xd6, 0x68, 0x40, 0xfd, 0x71, 0x06, 0xa0, 0xb2, 0x1c, - 0x16, 0xa5, 0xe7, 0xa3, 0x51, 0x2d, 0x6e, 0xaf, 0xc9, 0x22, 0xde, 0x4f, 0xc2, 0x34, 0x9b, 0xaa, 0x3c, 0xb8, 0x37, - 0xe9, 0x85, 0xbe, 0xc7, 0x81, 0xea, 0x5e, 0x1b, 0x97, 0xee, 0xa6, 0x94, 0x20, 0x26, 0x23, 0xa3, 0x99, 0x66, 0x63, - 0xde, 0x86, 0x66, 0x71, 0xaa, 0x5f, 0xd0, 0x27, 0x52, 0x72, 0x20, 0x3b, 0x2b, 0x8b, 0x52, 0x31, 0x29, 0x09, 0xde, - 0xe2, 0xfa, 0xb3, 0x3c, 0x38, 0x30, 0x98, 0x5a, 0x75, 0x1e, 0x30, 0x12, 0xfb, 0x62, 0xf1, 0x11, 0xe8, 0xf8, 0xcd, - 0x1d, 0x64, 0x71, 0xd7, 0xc7, 0x54, 0x1a, 0x0d, 0x3f, 0x88, 0xd1, 0xa9, 0xaf, 0x20, 0x50, 0x53, 0xf7, 0xbf, 0x69, - 0xb2, 0x62, 0xf9, 0xa6, 0xa7, 0x8d, 0xbd, 0xd0, 0xce, 0x0e, 0xee, 0x6a, 0xd3, 0x48, 0x0c, 0x43, 0xfc, 0x93, 0x63, - 0xff, 0xee, 0xa3, 0x4b, 0x9b, 0xbb, 0xb0, 0xda, 0xcb, 0xf2, 0x20, 0x34, 0x08, 0x1d, 0x8a, 0x54, 0xb9, 0x2d, 0xc3, - 0xfa, 0x12, 0xe3, 0xe5, 0x49, 0xff, 0xa3, 0xd7, 0x07, 0x55, 0x8f, 0x5f, 0x60, 0x29, 0x95, 0x40, 0x2a, 0xaa, 0xd8, - 0xa4, 0x71, 0x57, 0xa5, 0xca, 0x72, 0xf7, 0xa7, 0x86, 0xee, 0xb5, 0x59, 0x04, 0x99, 0xea, 0x83, 0x8a, 0x52, 0x6a, - 0xa8, 0x09, 0xa5, 0x2d, 0x60, 0x0a, 0xab, 0x2c, 0x5f, 0xdb, 0xbb, 0xf3, 0x93, 0xaf, 0x94, 0x84, 0x03, 0x3e, 0x86, - 0xc5, 0x34, 0xf0, 0xef, 0x87, 0x48, 0x03, 0x37, 0xb5, 0x21, 0x85, 0x32, 0x86, 0xb4, 0x42, 0x30, 0x1f, 0x29, 0x74, - 0x98, 0xe0, 0x07, 0xce, 0xa0, 0xc8, 0x49, 0xc9, 0x4e, 0xe3, 0x37, 0x75, 0x8f, 0xa5, 0xe3, 0xcc, 0xc4, 0xa0, 0x8b, - 0x3a, 0xd3, 0x74, 0x5e, 0xdd, 0x5d, 0xc0, 0xe5, 0x58, 0xed, 0x75, 0x5d, 0x90, 0x0d, 0x4c, 0xc9, 0x0b, 0x1f, 0x91, - 0x84, 0xe4, 0x84, 0x9e, 0xd2, 0xa1, 0x42, 0x61, 0x38, 0x85, 0x66, 0xcb, 0xe1, 0x1d, 0xdb, 0xb8, 0x92, 0xb6, 0x85, - 0x9e, 0x0a, 0x75, 0x7b, 0x03, 0x3c, 0xd8, 0x55, 0x21, 0x27, 0x79, 0x62, 0x35, 0x40, 0x83, 0x11, 0xd0, 0x96, 0x25, - 0x4e, 0x35, 0x11, 0x8d, 0x46, 0x61, 0xe4, 0x29, 0x2d, 0x95, 0xec, 0x7a, 0xfe, 0x68, 0xb0, 0x62, 0x12, 0x7b, 0xb5, - 0x38, 0xe8, 0x89, 0x49, 0x4a, 0x9b, 0x75, 0xd9, 0xe2, 0xf1, 0x89, 0xd8, 0xa3, 0x52, 0xe9, 0x89, 0xbd, 0xdc, 0x4a, - 0xe4, 0x66, 0xdf, 0xd3, 0x38, 0x33, 0x34, 0x3a, 0xdf, 0x1b, 0x9d, 0x57, 0x76, 0x55, 0xf7, 0xaf, 0x89, 0xda, 0x2c, - 0x6f, 0xc6, 0x29, 0xea, 0x80, 0xe6, 0x63, 0x23, 0x48, 0xdf, 0x7f, 0x2a, 0x34, 0x10, 0x8a, 0x86, 0x99, 0x97, 0x3d, - 0x16, 0x23, 0xdd, 0x90, 0x29, 0x13, 0x12, 0xdc, 0xbb, 0x03, 0x03, 0x8f, 0x28, 0x4b, 0x91, 0x31, 0x9d, 0x20, 0x0c, - 0x11, 0x59, 0x27, 0x67, 0xde, 0xe7, 0xe6, 0xb7, 0xf7, 0xc4, 0xee, 0x0f, 0x61, 0x53, 0xcb, 0xcd, 0x1e, 0x4e, 0xef, - 0x7d, 0x39, 0x3c, 0xf4, 0xf6, 0x22, 0xb9, 0x36, 0xe3, 0x85, 0x65, 0xf6, 0x75, 0xd8, 0x7f, 0x91, 0xf9, 0xd8, 0x63, - 0xa6, 0x57, 0xac, 0x81, 0x2c, 0x9e, 0x59, 0x13, 0xc3, 0x2f, 0x41, 0x3b, 0x0a, 0x81, 0x76, 0x62, 0xb7, 0x64, 0x15, - 0x24, 0x20, 0x12, 0x63, 0x6a, 0x3b, 0x07, 0x03, 0x75, 0xac, 0xb3, 0x58, 0xb4, 0xfb, 0x77, 0x4f, 0x39, 0x6d, 0x01, - 0x28, 0x2f, 0x85, 0x7f, 0x76, 0x71, 0x4a, 0xec, 0xe3, 0x18, 0x63, 0x2b, 0xb8, 0x1e, 0x12, 0x48, 0x55, 0x30, 0xa1, - 0xd3, 0x14, 0x01, 0x5d, 0x9c, 0x31, 0xf1, 0x27, 0xc6, 0xe1, 0x5d, 0xcc, 0x81, 0xa6, 0xcc, 0xb6, 0x30, 0x72, 0x8c, - 0x29, 0xcd, 0xba, 0x30, 0x63, 0xf3, 0x54, 0x36, 0x69, 0xb1, 0x36, 0x86, 0x94, 0x2d, 0xb9, 0x77, 0x6d, 0x11, 0x32, - 0x61, 0xc8, 0xba, 0x86, 0x90, 0xee, 0x10, 0xfc, 0x39, 0x29, 0x81, 0xd5, 0xfb, 0xa5, 0xae, 0xd4, 0xb3, 0x8c, 0xba, - 0x4c, 0xd0, 0x29, 0x8e, 0x1c, 0xe9, 0x92, 0x98, 0x7f, 0x2b, 0x13, 0xc2, 0xe1, 0x4a, 0x5b, 0xba, 0x2d, 0xa1, 0x49, - 0x8a, 0xc9, 0xc9, 0x5d, 0x40, 0xbe, 0xeb, 0xf9, 0xa3, 0xe3, 0xc9, 0xdb, 0x08, 0xcf, 0x06, 0x91, 0xc0, 0x86, 0xd5, - 0x94, 0xa8, 0x86, 0xd5, 0x67, 0xaf, 0xdb, 0x1f, 0x1e, 0x51, 0xdf, 0x48, 0xc7, 0x50, 0x61, 0xf3, 0xda, 0x53, 0x32, - 0x71, 0x6f, 0x9a, 0xd2, 0x1c, 0x95, 0xff, 0x35, 0x77, 0x38, 0x85, 0xdf, 0xdf, 0xe0, 0xec, 0xe0, 0x59, 0xf7, 0xd4, - 0x50, 0xdc, 0xef, 0x3f, 0xa8, 0x50, 0x2d, 0x37, 0x14, 0x06, 0x68, 0xc2, 0xf7, 0x20, 0x97, 0x23, 0xdf, 0xcf, 0x5d, - 0xe5, 0x17, 0xf9, 0xa5, 0x6f, 0x5d, 0x1a, 0xc2, 0x56, 0x4a, 0xa5, 0x15, 0xad, 0x6b, 0xf9, 0xa1, 0xbc, 0x49, 0xba, - 0x43, 0x06, 0xaa, 0x3f, 0xaf, 0xb1, 0x77, 0xa8, 0x48, 0x63, 0xb7, 0x3d, 0x71, 0x87, 0x30, 0xad, 0x74, 0x29, 0xbc, - 0xa4, 0x51, 0x22, 0x46, 0x69, 0x38, 0x75, 0xa9, 0x96, 0xb5, 0x13, 0xf5, 0xec, 0x88, 0x5d, 0x28, 0x20, 0x54, 0xdf, - 0x33, 0x5a, 0xb6, 0xc0, 0xb0, 0x77, 0xca, 0xd3, 0x68, 0x65, 0x1d, 0xea, 0x5a, 0x5b, 0x53, 0x6d, 0xd7, 0x3b, 0xaf, - 0xa8, 0xc0, 0xda, 0xd2, 0xdb, 0x7a, 0x2c, 0xeb, 0x31, 0x57, 0xe1, 0xa6, 0x8c, 0xe0, 0x59, 0xea, 0x17, 0x78, 0x5f, - 0x2d, 0x8f, 0x14, 0x1e, 0x1d, 0xdd, 0x5e, 0x05, 0x74, 0x30, 0x99, 0x04, 0x1e, 0x7c, 0x2a, 0x6b, 0x95, 0xac, 0x17, - 0xc2, 0x73, 0x42, 0x18, 0x90, 0xb3, 0x3e, 0xd8, 0x76, 0xa3, 0x72, 0x89, 0xd6, 0xeb, 0x47, 0x16, 0x5a, 0x64, 0xed, - 0xdb, 0x32, 0x8d, 0x1b, 0x2a, 0x47, 0x35, 0xfa, 0x75, 0xca, 0xd9, 0x53, 0xcc, 0x13, 0x46, 0x7d, 0x62, 0xd0, 0xc8, - 0x9e, 0x18, 0x1e, 0xa1, 0xe6, 0x47, 0xe6, 0x34, 0x5f, 0xae, 0x87, 0x5f, 0x89, 0xc2, 0x5a, 0x1d, 0x3a, 0x05, 0x2a, - 0x04, 0xda, 0xb3, 0x95, 0xbb, 0x17, 0x35, 0x64, 0x78, 0x41, 0xb9, 0x02, 0x92, 0xb1, 0xe0, 0xbe, 0x19, 0x42, 0x51, - 0x2b, 0x19, 0xa7, 0x89, 0x7d, 0xde, 0xc3, 0x4c, 0x7a, 0xce, 0xaf, 0x22, 0xc0, 0xdd, 0x0b, 0x67, 0xd2, 0x3c, 0xb6, - 0xdc, 0xa2, 0xc2, 0x65, 0xa9, 0x09, 0xb1, 0x45, 0x13, 0x51, 0x02, 0x40, 0x2f, 0x87, 0x7d, 0x44, 0x8e, 0x74, 0x32, - 0x76, 0x6d, 0xdb, 0x92, 0xa0, 0x50, 0x19, 0xe7, 0x1b, 0x85, 0xe1, 0xae, 0x2d, 0xee, 0xff, 0xa6, 0x21, 0xf6, 0x0c, - 0xe6, 0xa1, 0xd9, 0x5a, 0xba, 0xf9, 0xa3, 0xe8, 0xf8, 0x01, 0x0d, 0x64, 0x5f, 0xd4, 0x41, 0xfc, 0xbf, 0xd2, 0x21, - 0x1e, 0x84, 0xa0, 0x78, 0x88, 0x2b, 0x59, 0xc4, 0x82, 0x74, 0x27, 0x9e, 0xc5, 0xb9, 0xcc, 0x69, 0x5a, 0x40, 0x50, - 0x1d, 0x08, 0x85, 0x2c, 0x37, 0x90, 0xc6, 0x1b, 0x9c, 0x38, 0x6f, 0x7c, 0x21, 0x09, 0x6c, 0x3d, 0x1b, 0xc9, 0x64, - 0x51, 0xce, 0x88, 0xc0, 0x1f, 0xf3, 0xdc, 0xfd, 0x63, 0xf8, 0x8c, 0xd9, 0x8c, 0xa7, 0xcd, 0xf2, 0x63, 0x44, 0xd8, - 0x59, 0x5b, 0x45, 0x98, 0x50, 0x22, 0x0d, 0x4e, 0x78, 0xfd, 0x67, 0x2a, 0xdc, 0x1a, 0xbe, 0x82, 0x77, 0x66, 0x56, - 0xcc, 0xa5, 0xf5, 0x6a, 0x91, 0xa4, 0x83, 0x30, 0xdf, 0x98, 0x7f, 0x8c, 0x91, 0xe9, 0x32, 0x66, 0x45, 0x3f, 0x1a, - 0x24, 0x8a, 0xb7, 0x1b, 0x8f, 0xc7, 0xb7, 0x11, 0x1c, 0xac, 0x16, 0x64, 0x73, 0x9c, 0x8d, 0x90, 0x3d, 0x64, 0x45, - 0x55, 0x63, 0x82, 0x50, 0x0a, 0x71, 0x0c, 0x11, 0x47, 0xfc, 0xab, 0x3e, 0x3d, 0xa4, 0xab, 0x2f, 0x45, 0x46, 0xf9, - 0xad, 0xfc, 0x2d, 0xf3, 0x1d, 0x7f, 0xc7, 0x54, 0x5c, 0xe7, 0x39, 0xc2, 0xef, 0xfd, 0x76, 0x06, 0x09, 0x49, 0x11, - 0xfe, 0xa3, 0x44, 0x80, 0x98, 0x7a, 0xb0, 0x01, 0xdc, 0x79, 0x75, 0x95, 0x93, 0xe0, 0xbe, 0x60, 0xe8, 0x6d, 0x8b, - 0x99, 0x79, 0x3c, 0x92, 0x7c, 0x87, 0xb1, 0x88, 0xdd, 0xe8, 0x83, 0x19, 0x3b, 0x71, 0xce, 0xc4, 0x64, 0xf6, 0x1f, - 0x23, 0x2c, 0xb0, 0x84, 0x81, 0x5a, 0x0b, 0xbf, 0x5d, 0x05, 0x70, 0xa7, 0xff, 0x60, 0xa4, 0xc0, 0x35, 0x7a, 0xe2, - 0x67, 0xba, 0x97, 0xb0, 0x09, 0x4e, 0xc4, 0x5e, 0x11, 0xdb, 0x73, 0xa0, 0x55, 0x6b, 0x2e, 0x84, 0xee, 0xce, 0xe9, - 0x20, 0x6c, 0xb1, 0x28, 0x8c, 0xf5, 0x3a, 0x4a, 0x6c, 0x56, 0x2d, 0xa7, 0x09, 0x43, 0xb6, 0xab, 0x50, 0x7b, 0x92, - 0x0b, 0x8b, 0x12, 0x13, 0xb9, 0x71, 0xbc, 0x29, 0xd6, 0x01, 0xf5, 0x5b, 0xbb, 0x36, 0xc1, 0xad, 0x17, 0x3c, 0x3a, - 0x16, 0x14, 0x5a, 0x8a, 0x18, 0x3c, 0x41, 0x64, 0xf0, 0xba, 0xac, 0x10, 0xa7, 0x17, 0xe9, 0xf7, 0xad, 0x97, 0x34, - 0x5a, 0xba, 0x9b, 0x45, 0xcc, 0x7e, 0x9e, 0xfd, 0x6a, 0xda, 0xfe, 0x96, 0x33, 0x32, 0x2e, 0x92, 0x16, 0x3d, 0x8d, - 0x12, 0x97, 0x5b, 0x30, 0x7b, 0x68, 0x75, 0xcc, 0xd0, 0x7f, 0xa7, 0xa5, 0xc5, 0x18, 0xbf, 0x13, 0xc5, 0xb4, 0x87, - 0x0b, 0x15, 0x89, 0x7b, 0x7a, 0x41, 0x81, 0xb6, 0x96, 0x78, 0xed, 0xf4, 0x4e, 0x57, 0x9f, 0x4f, 0xd7, 0x20, 0xfa, - 0xe6, 0x98, 0xae, 0x5b, 0x80, 0x2c, 0x97, 0x19, 0xd6, 0x68, 0x97, 0xf6, 0x85, 0xf2, 0xec, 0x81, 0xed, 0x93, 0xf1, - 0x6f, 0x31, 0xf5, 0x64, 0x48, 0x24, 0x2d, 0x51, 0x2a, 0x15, 0x38, 0xe9, 0x02, 0x89, 0x35, 0x1b, 0xb5, 0x5c, 0xa3, - 0xce, 0xf8, 0xb1, 0x3d, 0xae, 0x2c, 0x7f, 0x7a, 0xc9, 0xab, 0xb4, 0x72, 0x11, 0x88, 0x7d, 0x76, 0x29, 0x19, 0x50, - 0x4e, 0xe1, 0x8c, 0xec, 0xfe, 0x57, 0xb0, 0xda, 0x15, 0x40, 0xd5, 0x30, 0x7a, 0xb9, 0xd4, 0xa0, 0x14, 0xa5, 0x9f, - 0xee, 0x0f, 0x73, 0x10, 0xd6, 0x57, 0x67, 0xe1, 0xb5, 0x9f, 0x24, 0xba, 0xc4, 0x5f, 0x4c, 0xdb, 0x09, 0x27, 0xa9, - 0xbb, 0xe2, 0x37, 0x27, 0x13, 0xb0, 0xe8, 0x10, 0xaf, 0x56, 0x87, 0x9b, 0x79, 0x4b, 0x86, 0x4a, 0x64, 0x5d, 0x7c, - 0xe7, 0x02, 0xb8, 0xb0, 0xde, 0x3e, 0xcd, 0x42, 0xb2, 0xd6, 0x12, 0x3b, 0x09, 0xdd, 0xf0, 0x2c, 0x61, 0x04, 0x48, - 0xb0, 0x93, 0x01, 0x34, 0x79, 0xa7, 0xec, 0x63, 0xbd, 0x9a, 0x98, 0x82, 0x20, 0xa2, 0x7b, 0xcf, 0xc1, 0x6e, 0xb1, - 0xe7, 0x59, 0x61, 0x13, 0x62, 0xb3, 0xa3, 0xe9, 0xfb, 0x69, 0x02, 0xaf, 0x17, 0x9a, 0x8a, 0x8d, 0xc2, 0xd4, 0xc9, - 0x4b, 0x8c, 0x03, 0xf4, 0x65, 0x29, 0xa0, 0x86, 0xab, 0x68, 0xcb, 0x72, 0x92, 0x12, 0x5a, 0x06, 0x07, 0x9c, 0x21, - 0x72, 0xf0, 0x3f, 0x16, 0x34, 0x90, 0x75, 0xf8, 0x89, 0xa8, 0x05, 0x7f, 0x26, 0xad, 0x69, 0x56, 0x44, 0xab, 0xbd, - 0x8e, 0x35, 0x68, 0x5e, 0x26, 0xcf, 0x17, 0x06, 0xb0, 0x79, 0x2d, 0x64, 0xf5, 0x33, 0xfd, 0x56, 0x3c, 0x51, 0x7e, - 0xca, 0x41, 0xed, 0xa9, 0x3e, 0x5b, 0x21, 0xd9, 0x69, 0x56, 0x54, 0x44, 0x71, 0x3d, 0xd9, 0x9e, 0x8b, 0xef, 0xbe, - 0x4c, 0x14, 0xfc, 0x66, 0x00, 0x31, 0x24, 0x20, 0x82, 0xfd, 0x40, 0xd6, 0x01, 0xce, 0x17, 0x04, 0x53, 0x7e, 0xd2, - 0x43, 0xa0, 0x29, 0x47, 0x0a, 0x88, 0xd9, 0x8a, 0xd9, 0xa5, 0xf3, 0x40, 0x2b, 0xde, 0xbf, 0x4e, 0xd5, 0xac, 0xfd, - 0xf5, 0x94, 0x4e, 0x7a, 0xcb, 0xf9, 0x8f, 0x4a, 0x9a, 0x01, 0x1b, 0xe2, 0x82, 0x2a, 0x45, 0xc2, 0x2a, 0xa3, 0x40, - 0x34, 0x7a, 0x76, 0x1c, 0x59, 0x0a, 0xfb, 0xe7, 0x76, 0x7e, 0xde, 0xea, 0xd4, 0x96, 0xba, 0x9d, 0x4b, 0x89, 0x15, - 0x5c, 0x61, 0x6e, 0xf9, 0x0a, 0x00, 0x64, 0xa6, 0x0f, 0x4b, 0x07, 0x0d, 0xbe, 0xee, 0xbe, 0x70, 0xa0, 0x92, 0xb5, - 0x63, 0xf5, 0x43, 0xc6, 0xef, 0x0e, 0xe9, 0x15, 0xbd, 0x52, 0x65, 0xbe, 0xb9, 0xd7, 0x7b, 0xda, 0xea, 0xfa, 0xa5, - 0x61, 0x46, 0x5d, 0xaa, 0x96, 0xa7, 0xd7, 0xf8, 0xfd, 0x00, 0x5e, 0xae, 0xfd, 0x29, 0x28, 0x63, 0xfb, 0x28, 0x1d, - 0x7b, 0x05, 0xf6, 0xa4, 0x4f, 0x53, 0xd3, 0xd0, 0xaa, 0xc8, 0x94, 0xb7, 0x75, 0xdf, 0x0a, 0xf7, 0xbc, 0x3d, 0x91, - 0x71, 0x24, 0x75, 0x97, 0x92, 0xf7, 0xa5, 0xad, 0x83, 0xee, 0x77, 0x04, 0x0a, 0xbf, 0x3c, 0x9d, 0x52, 0xd0, 0xd7, - 0x84, 0x4b, 0x04, 0x0f, 0x2d, 0xaf, 0x4b, 0x37, 0xc3, 0x20, 0x72, 0xf4, 0x01, 0xdb, 0xd2, 0x86, 0xe0, 0xcf, 0x45, - 0xf8, 0xd9, 0x4e, 0x68, 0x26, 0x57, 0x81, 0xda, 0x10, 0x55, 0xf6, 0x90, 0x6c, 0x0a, 0x2c, 0x27, 0x52, 0x93, 0x7e, - 0xa8, 0x33, 0x81, 0x04, 0x53, 0xaf, 0x3c, 0xec, 0x82, 0x21, 0x8b, 0x5d, 0x69, 0x61, 0x60, 0x19, 0x26, 0xcf, 0x92, - 0x5f, 0xaf, 0xce, 0xa5, 0xd1, 0x02, 0x43, 0x00, 0xd3, 0xdc, 0xcb, 0x8b, 0xe6, 0x84, 0xe5, 0xef, 0x6e, 0x86, 0xf9, - 0x02, 0x07, 0xbe, 0x75, 0x31, 0xf3, 0x5a, 0x14, 0xe8, 0xb9, 0xe9, 0x59, 0x23, 0xed, 0x44, 0xc1, 0x49, 0x6d, 0xce, - 0x70, 0x08, 0x50, 0xd5, 0xec, 0xc3, 0xcc, 0x33, 0xf5, 0xe5, 0xac, 0x17, 0xc1, 0x5e, 0x5e, 0x23, 0xf0, 0xe5, 0xc7, - 0x39, 0xf6, 0x4e, 0x46, 0xe6, 0xaa, 0xb4, 0x27, 0x9e, 0x9b, 0x0b, 0xab, 0xbb, 0x25, 0x78, 0x2c, 0x10, 0xec, 0xfc, - 0x61, 0x1e, 0xf7, 0x75, 0xdd, 0x2b, 0x20, 0x98, 0x81, 0xf0, 0x09, 0x60, 0x0e, 0x86, 0x68, 0xa6, 0x97, 0x47, 0xff, - 0x39, 0x47, 0xaa, 0x8a, 0xa7, 0x00, 0xc7, 0x1c, 0x0c, 0xef, 0x4c, 0x27, 0x72, 0xb3, 0xd2, 0x5a, 0xed, 0x04, 0x0c, - 0x21, 0x37, 0xcd, 0x99, 0xa6, 0xdc, 0x00, 0xf9, 0x2e, 0x62, 0x98, 0xe1, 0x55, 0xec, 0x0b, 0xf1, 0x01, 0x63, 0x16, - 0xcd, 0x9d, 0x17, 0xf8, 0x47, 0x17, 0xb1, 0xdc, 0x79, 0x32, 0x53, 0xd6, 0xc2, 0x1a, 0x33, 0xa4, 0x90, 0xb9, 0x1f, - 0x71, 0x0a, 0xab, 0x6d, 0xda, 0x57, 0x01, 0x91, 0x5b, 0x5a, 0x37, 0x26, 0x5a, 0x03, 0x17, 0x5a, 0x13, 0xcd, 0xa1, - 0x5d, 0xdb, 0x1a, 0x6b, 0x5a, 0x9e, 0x7e, 0x32, 0x78, 0xf0, 0xcd, 0xbf, 0x7e, 0xf4, 0x55, 0xf3, 0x12, 0xd2, 0xe0, - 0xfa, 0xe8, 0xc2, 0xc9, 0x7e, 0xde, 0xf3, 0x76, 0x81, 0xcb, 0x9d, 0xbc, 0x26, 0xcf, 0xe9, 0x90, 0x4a, 0xec, 0xa4, - 0x02, 0x28, 0x82, 0xcf, 0x2d, 0x2d, 0x7b, 0x0f, 0x75, 0x22, 0x83, 0x0b, 0x55, 0xce, 0x38, 0x33, 0x8e, 0xf3, 0xfc, - 0x4a, 0xda, 0x1c, 0xdc, 0x7e, 0x1e, 0x5c, 0x0c, 0x04, 0x5f, 0xe8, 0x82, 0x4c, 0x83, 0x42, 0x47, 0x6d, 0x4d, 0x2d, - 0xb0, 0x38, 0xc0, 0x02, 0x91, 0x23, 0x08, 0x40, 0x0e, 0x91, 0xae, 0x55, 0xba, 0x8f, 0x07, 0xdd, 0x81, 0xf2, 0x46, - 0x60, 0x46, 0x86, 0x1d, 0xac, 0x1d, 0xeb, 0x2b, 0x57, 0x89, 0x08, 0x93, 0xb0, 0xb1, 0x98, 0xe1, 0x5f, 0x3c, 0x25, - 0xe5, 0x63, 0x1e, 0x76, 0xb3, 0xe0, 0xbc, 0x98, 0x57, 0x58, 0x9e, 0x9a, 0x20, 0x5d, 0xa8, 0xab, 0x6f, 0x39, 0x26, - 0xe7, 0xb4, 0xcb, 0x50, 0xd8, 0x22, 0x61, 0xa4, 0x6c, 0xd2, 0x4c, 0x64, 0x01, 0xc9, 0x38, 0x47, 0x0c, 0xe5, 0x0a, - 0xaf, 0x47, 0x95, 0x6c, 0xd7, 0xfc, 0x1b, 0xb3, 0x32, 0x2e, 0xc7, 0x8e, 0x75, 0xc3, 0xba, 0x43, 0x12, 0x95, 0x69, - 0x99, 0x7c, 0x2d, 0x8b, 0x13, 0x2f, 0xe6, 0x51, 0x88, 0xf7, 0xb3, 0x7e, 0x5b, 0x7e, 0xf1, 0xc7, 0xe5, 0xae, 0x1d, - 0x42, 0x99, 0x54, 0x0c, 0x62, 0x09, 0x13, 0x41, 0x8b, 0xd2, 0xf8, 0x8d, 0x00, 0x2d, 0xcf, 0x00, 0xda, 0x58, 0xfa, - 0xc1, 0x4a, 0xa6, 0x2a, 0x87, 0xd5, 0x52, 0xbd, 0x95, 0xa2, 0xbb, 0xcb, 0xf2, 0x32, 0xda, 0x2c, 0x92, 0x80, 0x00, - 0x37, 0xa7, 0x73, 0x35, 0x5f, 0x72, 0x1d, 0xc6, 0xeb, 0xb8, 0xb2, 0x54, 0x2a, 0x4c, 0xd1, 0x6c, 0xb0, 0x8c, 0x08, - 0xe3, 0xb6, 0xd6, 0xc7, 0xe2, 0xf8, 0x3d, 0x91, 0x4f, 0xa0, 0x5f, 0xe1, 0x2e, 0x77, 0x55, 0x05, 0xee, 0x26, 0x22, - 0x7a, 0x42, 0x2e, 0x03, 0xbe, 0x33, 0xaa, 0x37, 0x68, 0xc1, 0xb6, 0x6c, 0xb7, 0xd6, 0x63, 0x2a, 0x0f, 0x7d, 0x09, - 0x83, 0xbd, 0x59, 0xf4, 0xa8, 0x75, 0xa8, 0xe1, 0x78, 0xda, 0x70, 0x78, 0x37, 0xe8, 0x69, 0x40, 0x07, 0xa4, 0xbe, - 0xf6, 0xe3, 0x3f, 0x4e, 0x16, 0x80, 0x79, 0x41, 0x5d, 0x24, 0xb4, 0x1d, 0xe3, 0x1b, 0x68, 0x10, 0xe4, 0x0e, 0x04, - 0xdb, 0xf5, 0x7c, 0x0d, 0x17, 0x07, 0xbd, 0xb0, 0x24, 0xd4, 0xc2, 0x9b, 0xfa, 0x43, 0x08, 0x22, 0x98, 0x52, 0x12, - 0xeb, 0xfe, 0xd8, 0xec, 0xa1, 0xa0, 0x0f, 0x77, 0x38, 0xab, 0xc6, 0xf4, 0x27, 0xc4, 0x2a, 0x13, 0xe9, 0x81, 0xdd, - 0x45, 0x13, 0x0d, 0x0f, 0xfb, 0x41, 0x49, 0x4a, 0xa8, 0x0e, 0x19, 0x6d, 0xa0, 0x4c, 0xcc, 0xf1, 0x65, 0x87, 0x82, - 0x57, 0x52, 0x4b, 0x6c, 0x62, 0xb0, 0x6f, 0x1b, 0x4c, 0x89, 0x81, 0x3a, 0x84, 0xdc, 0x52, 0xe4, 0x3a, 0xc0, 0x16, - 0xb1, 0x3f, 0xad, 0x06, 0xca, 0x7e, 0x57, 0xf7, 0x7d, 0x7b, 0x05, 0x50, 0xe6, 0x9a, 0x9f, 0xf4, 0x7b, 0xa4, 0x7b, - 0xb0, 0x88, 0x5f, 0x87, 0xa0, 0x55, 0xd7, 0xd5, 0x9a, 0x38, 0xf3, 0x59, 0xb2, 0xe7, 0x86, 0x0b, 0x7f, 0x5f, 0x11, - 0xc8, 0x18, 0x69, 0x3a, 0x54, 0xb1, 0x15, 0xef, 0xcb, 0x28, 0x5a, 0x86, 0x7b, 0xe1, 0x77, 0x52, 0x10, 0x21, 0x42, - 0xc6, 0x30, 0xcd, 0x11, 0x74, 0x6a, 0x3e, 0x4f, 0x1a, 0x81, 0xea, 0x9a, 0x84, 0xb9, 0x67, 0xef, 0x15, 0xf1, 0x20, - 0x47, 0x8f, 0x46, 0x02, 0xb4, 0x7f, 0x8b, 0xaf, 0xbe, 0x69, 0x03, 0x23, 0x48, 0x1b, 0x41, 0x64, 0x70, 0x03, 0x8e, - 0x73, 0x7c, 0xd1, 0x42, 0x82, 0x44, 0x99, 0xee, 0x24, 0xf4, 0x4d, 0x9b, 0xb5, 0x06, 0x4f, 0xca, 0x8b, 0x72, 0xa3, - 0x02, 0x50, 0xa7, 0x85, 0x68, 0x56, 0x30, 0x67, 0x86, 0xec, 0xc8, 0x7b, 0xb0, 0xe1, 0xa1, 0x2e, 0x95, 0xe6, 0x31, - 0xa7, 0x2f, 0x10, 0x35, 0x97, 0x79, 0x52, 0xa3, 0x57, 0xd0, 0xb7, 0xa0, 0x38, 0x85, 0x36, 0xc6, 0xc4, 0xe9, 0xf2, - 0xd4, 0xa7, 0x6a, 0x24, 0x4a, 0xcf, 0xe6, 0xcb, 0x62, 0x1d, 0x71, 0x04, 0x76, 0xa1, 0x15, 0x63, 0xf0, 0xab, 0xb8, - 0x25, 0xe0, 0x20, 0xd3, 0x89, 0xa0, 0x23, 0x7d, 0x32, 0x72, 0x32, 0x63, 0xbd, 0x4b, 0x5f, 0x38, 0xd0, 0x43, 0x29, - 0xd5, 0x17, 0x18, 0x33, 0x84, 0x02, 0xfd, 0xd5, 0xf4, 0x06, 0xed, 0xaf, 0x72, 0x50, 0xbc, 0x98, 0xd0, 0x51, 0x11, - 0x43, 0x78, 0x88, 0xd4, 0x88, 0x42, 0x46, 0xa2, 0x03, 0x2c, 0x60, 0xe6, 0xdd, 0x74, 0x6b, 0xc9, 0x7b, 0xb1, 0x4e, - 0x9d, 0xe6, 0xe0, 0x29, 0x83, 0xf1, 0x46, 0x5e, 0xfa, 0x19, 0x3d, 0xf6, 0x65, 0x4b, 0xc8, 0xee, 0x8b, 0x09, 0x04, - 0xc8, 0x17, 0x3b, 0x64, 0x4c, 0xb1, 0x86, 0x35, 0x2d, 0xa9, 0x9a, 0x7d, 0xb4, 0x08, 0xfd, 0x31, 0xf5, 0x71, 0x96, - 0x65, 0x4a, 0xa8, 0x2d, 0x8c, 0x01, 0x11, 0x7a, 0xca, 0x29, 0x41, 0x43, 0xee, 0x83, 0x57, 0x34, 0xa8, 0x83, 0xfd, - 0xbe, 0x18, 0x9e, 0x74, 0x97, 0x43, 0x60, 0xbb, 0x26, 0xa0, 0xd3, 0x94, 0x42, 0x21, 0x36, 0xdc, 0x47, 0x35, 0x93, - 0xd4, 0x30, 0xa6, 0x89, 0xca, 0x07, 0xfc, 0x41, 0x6d, 0xc4, 0x2d, 0xdb, 0xb3, 0x78, 0x18, 0x61, 0xcf, 0x71, 0xe8, - 0x86, 0xb0, 0x0e, 0x88, 0xaa, 0x6a, 0x2e, 0x6b, 0x6e, 0x44, 0xcb, 0x33, 0x32, 0x98, 0x12, 0xa9, 0x5f, 0xa1, 0x75, - 0x50, 0xa9, 0xa0, 0x9e, 0xc5, 0x1f, 0x06, 0x9e, 0x5b, 0x42, 0xcb, 0xfd, 0x29, 0x92, 0x78, 0x31, 0x19, 0xcd, 0xa8, - 0x47, 0x78, 0xd9, 0xee, 0x10, 0x60, 0xdf, 0xb9, 0xb2, 0xd3, 0xb4, 0x68, 0xa3, 0x8c, 0x9d, 0xb8, 0xeb, 0xb6, 0xa6, - 0x12, 0xb4, 0x06, 0x94, 0x98, 0x7f, 0x57, 0x9f, 0x05, 0xdf, 0x0b, 0xa8, 0x98, 0x75, 0x00, 0xd7, 0x0b, 0xed, 0xb7, - 0x2f, 0xd1, 0x4e, 0x4a, 0x57, 0xdc, 0x9b, 0x44, 0x29, 0xdd, 0x47, 0xcc, 0x82, 0xb9, 0x90, 0xbb, 0xe3, 0xa2, 0xee, - 0xad, 0x9f, 0x04, 0xdc, 0x14, 0x75, 0x86, 0x2d, 0x94, 0x6c, 0x0e, 0x78, 0x29, 0x31, 0x05, 0x9a, 0xcb, 0x95, 0x11, - 0x78, 0x0d, 0x3d, 0x50, 0x07, 0x0d, 0x89, 0x5b, 0xeb, 0xb5, 0xa3, 0xd9, 0xfb, 0x43, 0x4b, 0x35, 0x59, 0xd0, 0xc6, - 0x48, 0xf2, 0x98, 0x39, 0x74, 0x56, 0x64, 0xba, 0xaa, 0x0a, 0x96, 0x9a, 0x5a, 0xaf, 0xf5, 0xcd, 0x7f, 0xf1, 0xbe, - 0x04, 0x08, 0x13, 0xf6, 0xac, 0x76, 0xd0, 0x3b, 0xec, 0x54, 0xbf, 0x59, 0xb8, 0xda, 0xc2, 0x45, 0xaa, 0x80, 0x80, - 0x2e, 0x59, 0x7d, 0x8d, 0xa5, 0xa7, 0x28, 0x88, 0x34, 0xe8, 0xaa, 0x6b, 0x02, 0x85, 0x60, 0xa5, 0x32, 0x7f, 0xba, - 0x30, 0x21, 0x47, 0x4c, 0x8e, 0xc8, 0xed, 0x75, 0x39, 0xe7, 0x67, 0x06, 0xa4, 0xa7, 0x23, 0x22, 0x21, 0xa7, 0x37, - 0x06, 0xef, 0x72, 0xd0, 0xd8, 0xdf, 0x05, 0x5c, 0xe1, 0x43, 0x02, 0xe7, 0x5d, 0x57, 0xca, 0x0d, 0x03, 0xdc, 0xf7, - 0x05, 0xd2, 0xd4, 0x14, 0x11, 0x1c, 0xa8, 0x76, 0xe4, 0x73, 0x76, 0xe4, 0xcf, 0xcd, 0xe8, 0x70, 0x6e, 0x8e, 0x77, - 0x8d, 0x22, 0xc4, 0x14, 0xbb, 0xcf, 0x03, 0x23, 0x51, 0x92, 0xf0, 0xa7, 0xeb, 0x40, 0x6b, 0xad, 0xfb, 0x05, 0xf7, - 0x20, 0x9e, 0x15, 0xe1, 0xfc, 0x03, 0xdb, 0x7c, 0xa0, 0xc9, 0x79, 0x79, 0xad, 0xad, 0x3b, 0x8a, 0x11, 0x80, 0xf6, - 0xc6, 0xf3, 0xb6, 0xf2, 0xe0, 0x06, 0x95, 0x41, 0x9e, 0xce, 0x04, 0xe3, 0x99, 0xab, 0xc1, 0x3c, 0x3b, 0x76, 0x14, - 0x00, 0x16, 0x02, 0x45, 0xa9, 0xa9, 0xcd, 0xea, 0x24, 0xae, 0x68, 0x47, 0xf7, 0x5b, 0x56, 0xe0, 0x04, 0xa4, 0x5e, - 0x38, 0x5e, 0xda, 0x06, 0xdf, 0x51, 0x48, 0x76, 0x67, 0x19, 0x07, 0xd9, 0x85, 0x7f, 0x0f, 0xb4, 0x88, 0xea, 0x0a, - 0x84, 0x8a, 0xa4, 0x89, 0x55, 0x49, 0x29, 0x92, 0x46, 0x68, 0x99, 0x6d, 0x41, 0x56, 0x9c, 0xed, 0x11, 0x9f, 0xb5, - 0x16, 0x78, 0x37, 0xe4, 0xb6, 0xc8, 0xe6, 0x0c, 0xf7, 0x44, 0xa0, 0x63, 0x4b, 0x28, 0x33, 0x2b, 0x85, 0x6d, 0xdc, - 0xd3, 0x4d, 0xda, 0xbb, 0x55, 0xd4, 0x0c, 0x1a, 0xd1, 0xb7, 0xb4, 0x4c, 0xfe, 0xbe, 0x5e, 0xa8, 0x95, 0x18, 0x1a, - 0x73, 0x88, 0xe9, 0xba, 0xb5, 0x30, 0xa9, 0x52, 0x9b, 0x7e, 0x56, 0xf4, 0xe9, 0x23, 0x0d, 0xe5, 0x90, 0x02, 0x38, - 0xa1, 0x14, 0x84, 0x21, 0x3f, 0x60, 0x08, 0xee, 0x14, 0xac, 0x91, 0x2c, 0x57, 0x91, 0xcb, 0x22, 0x97, 0xdd, 0xf1, - 0x0f, 0x16, 0x80, 0x42, 0x5f, 0xae, 0x50, 0xd0, 0x4f, 0xb4, 0xd6, 0x27, 0xea, 0x48, 0xa9, 0x49, 0xf1, 0xe9, 0xd2, - 0x5d, 0x56, 0x01, 0x35, 0x57, 0xaf, 0x8b, 0x06, 0xf4, 0x9a, 0xd2, 0x41, 0xe8, 0x11, 0x0a, 0x5b, 0x08, 0xa3, 0x3f, - 0x5a, 0xde, 0x4f, 0xee, 0xe5, 0xb8, 0x76, 0x9b, 0xa2, 0x7b, 0x3a, 0xbb, 0x63, 0xa4, 0x26, 0x99, 0x68, 0x59, 0x73, - 0x0c, 0xa7, 0x07, 0xbc, 0x98, 0x3c, 0x76, 0x4c, 0xd8, 0x6c, 0x52, 0x3d, 0xc6, 0x04, 0xe0, 0xc8, 0x06, 0x8b, 0x6d, - 0x2a, 0xad, 0x95, 0x09, 0x52, 0xdb, 0xac, 0x5f, 0xd6, 0xdc, 0x29, 0x8a, 0xdb, 0x9f, 0x03, 0x60, 0xde, 0x34, 0x99, - 0x36, 0x50, 0x4c, 0x11, 0xa3, 0xa4, 0x75, 0x71, 0xbc, 0x14, 0x2b, 0x2f, 0x3e, 0x14, 0xb8, 0x37, 0x42, 0xe5, 0xca, - 0x6a, 0xc3, 0xd5, 0x99, 0xdc, 0x0f, 0xb7, 0x38, 0x65, 0x4e, 0x22, 0x1e, 0xc0, 0xe8, 0x33, 0x66, 0xc3, 0xcd, 0x61, - 0x3f, 0x32, 0xdc, 0x2c, 0xa7, 0xf0, 0xa2, 0x78, 0xcb, 0xfc, 0xdc, 0x05, 0x54, 0xf6, 0x20, 0x4e, 0x77, 0x2a, 0xb5, - 0x5e, 0x67, 0x04, 0x48, 0xf8, 0x56, 0x92, 0xbd, 0x92, 0xb1, 0x13, 0x9f, 0x22, 0xd3, 0x83, 0x63, 0x58, 0x78, 0xc6, - 0x48, 0x6e, 0x9f, 0xa9, 0xa3, 0xbd, 0x7a, 0x46, 0xe7, 0x06, 0x74, 0xe7, 0xd5, 0x7b, 0x5b, 0x91, 0x9e, 0x9a, 0x69, - 0x3a, 0xf1, 0xa6, 0x01, 0xea, 0x7c, 0x70, 0x6d, 0x91, 0xce, 0x79, 0x05, 0x9b, 0x38, 0x14, 0x6e, 0x84, 0x6a, 0xf4, - 0x85, 0x7a, 0x0f, 0xab, 0x3a, 0x36, 0xdd, 0xc5, 0x6d, 0xd9, 0xa3, 0xe9, 0x17, 0x6b, 0x04, 0x62, 0x4f, 0xe2, 0xf1, - 0x29, 0x0d, 0x6e, 0x6f, 0x76, 0xa6, 0xad, 0x8e, 0x31, 0x50, 0x6d, 0x92, 0x5a, 0xe0, 0xf7, 0xc7, 0x9e, 0x96, 0x0b, - 0x67, 0x96, 0x77, 0x0d, 0x7c, 0x89, 0x5f, 0x80, 0xb0, 0x6a, 0xda, 0x50, 0x8f, 0xef, 0xb8, 0xca, 0xc6, 0x32, 0xf7, - 0x9a, 0x91, 0xe5, 0x30, 0xd7, 0x55, 0x9c, 0x6c, 0xaa, 0x23, 0x12, 0xa9, 0xed, 0xa7, 0xde, 0xbe, 0x3b, 0x6e, 0xdc, - 0xe3, 0x97, 0x83, 0x38, 0xd0, 0x54, 0xe4, 0xcc, 0xb0, 0xb0, 0x0a, 0xa7, 0xad, 0x25, 0x0d, 0x8d, 0xcb, 0x50, 0x10, - 0x90, 0x31, 0xff, 0xea, 0xe1, 0x20, 0x32, 0x6f, 0xdd, 0x90, 0x54, 0x55, 0x1a, 0x58, 0xa2, 0xbd, 0x38, 0xf0, 0x90, - 0xc2, 0x43, 0x91, 0x6c, 0x7d, 0xd1, 0x7e, 0x9d, 0x23, 0x0b, 0x1e, 0x08, 0x46, 0x99, 0x24, 0x06, 0xb6, 0x8e, 0x6e, - 0x8d, 0x74, 0x97, 0xf4, 0x32, 0x01, 0xfd, 0xa4, 0xe7, 0xf1, 0xc7, 0x38, 0x14, 0x65, 0xcd, 0xf9, 0x9b, 0x96, 0x64, - 0x9d, 0x47, 0x77, 0x55, 0x63, 0x1d, 0x12, 0xb1, 0xa1, 0xe5, 0xe8, 0x38, 0x2f, 0xcb, 0x92, 0xd3, 0xe0, 0x4f, 0xc0, - 0x58, 0x78, 0x67, 0x45, 0x51, 0xcd, 0x85, 0x54, 0xd3, 0x17, 0x7c, 0x02, 0xd7, 0xe1, 0x31, 0x7b, 0x69, 0x5b, 0xb1, - 0x1e, 0x2c, 0x87, 0x78, 0xce, 0x0d, 0x15, 0x46, 0xae, 0xb6, 0x66, 0x93, 0x7a, 0x0e, 0xd3, 0x58, 0x99, 0x43, 0xa1, - 0x94, 0x7b, 0x5e, 0xf1, 0xd4, 0xc5, 0xdc, 0xa1, 0x9b, 0x14, 0xa2, 0x57, 0x64, 0xe6, 0x54, 0x92, 0x26, 0xfd, 0xd8, - 0x36, 0x2a, 0x20, 0x00, 0x3a, 0x5a, 0x00, 0x68, 0xf7, 0x7d, 0xb5, 0x6c, 0x42, 0xb2, 0xf1, 0x59, 0x43, 0x32, 0xd7, - 0x3a, 0xde, 0xfa, 0x2a, 0xc7, 0x77, 0x57, 0x84, 0xd1, 0xbc, 0x3d, 0x30, 0x2b, 0x9c, 0x8b, 0x48, 0x31, 0x6e, 0xd1, - 0x02, 0x12, 0xe6, 0x11, 0x72, 0xbc, 0x1b, 0xa2, 0x7c, 0xad, 0x6c, 0x8e, 0xce, 0xf3, 0xf0, 0xb4, 0xb9, 0x62, 0xa1, - 0x14, 0xbd, 0x4c, 0x8e, 0xfd, 0xc6, 0xad, 0x05, 0x1a, 0xd3, 0x98, 0x87, 0x8d, 0x0f, 0xa3, 0x3c, 0x3d, 0xc2, 0xe8, - 0xfc, 0x10, 0x87, 0xa5, 0x23, 0x7d, 0x2d, 0x05, 0xe8, 0xf5, 0x9e, 0xec, 0xbf, 0x5f, 0x7d, 0x2f, 0xba, 0xc1, 0xe0, - 0xc2, 0x48, 0xa3, 0x38, 0x5f, 0x10, 0x5a, 0x62, 0x8e, 0xd2, 0x8e, 0x17, 0xf5, 0x88, 0x39, 0xe2, 0xe6, 0x12, 0xec, - 0x58, 0x39, 0xd4, 0xff, 0x17, 0x2e, 0x42, 0x79, 0x52, 0x57, 0x02, 0x9f, 0x0f, 0x3f, 0x2e, 0xfb, 0x05, 0x8e, 0x44, - 0xe4, 0x30, 0x8e, 0xf4, 0xd8, 0xd6, 0x08, 0xbd, 0x67, 0xe7, 0x1e, 0xa9, 0x37, 0x5e, 0x27, 0x84, 0x5c, 0x37, 0x94, - 0x52, 0x77, 0x50, 0xc6, 0x65, 0x09, 0x34, 0x6e, 0x0a, 0x21, 0xca, 0xf1, 0x9f, 0x72, 0xf3, 0x14, 0xd1, 0x77, 0x1d, - 0x28, 0x5d, 0xd5, 0xd4, 0x14, 0xdc, 0x0d, 0x18, 0x80, 0xb5, 0xb8, 0x8f, 0x1d, 0x52, 0xf9, 0x50, 0x16, 0x5e, 0x61, - 0x60, 0xb5, 0x28, 0x2b, 0x81, 0x5a, 0x66, 0x28, 0x62, 0x04, 0x27, 0x68, 0x2f, 0xc2, 0xac, 0xeb, 0x98, 0x95, 0x7b, - 0xd0, 0xa2, 0x9d, 0xdb, 0x86, 0xdd, 0xab, 0xe1, 0xf9, 0xe1, 0xbd, 0x9a, 0xb4, 0xd8, 0xd5, 0xb8, 0xe3, 0x01, 0x38, - 0x4a, 0xce, 0x7e, 0x01, 0x58, 0xf0, 0x28, 0x09, 0xec, 0xdc, 0x4c, 0x0f, 0x5b, 0xbb, 0x43, 0xe9, 0xb7, 0x19, 0x3e, - 0xdd, 0x11, 0xb3, 0x51, 0xd2, 0xcd, 0x3e, 0xfd, 0xa9, 0x83, 0xc3, 0xd2, 0x9b, 0x00, 0xcf, 0xb1, 0xee, 0xfe, 0x41, - 0xc2, 0x0e, 0xee, 0xf1, 0x2f, 0x1f, 0x9a, 0x22, 0x91, 0x8e, 0x98, 0xc5, 0x2d, 0x8e, 0x6a, 0xb2, 0xb3, 0xba, 0x6b, - 0xe4, 0xdc, 0x96, 0xc4, 0x55, 0x29, 0x21, 0xb9, 0x1c, 0x71, 0xcb, 0x24, 0x7b, 0x44, 0x19, 0x9c, 0xf6, 0xf6, 0xf2, - 0xda, 0xd8, 0x7b, 0x18, 0x57, 0x01, 0xa8, 0x09, 0x28, 0x17, 0x34, 0xc6, 0xbb, 0x0f, 0x01, 0x46, 0x69, 0xd5, 0xd9, - 0x19, 0xbd, 0x8b, 0x5b, 0x75, 0xb9, 0x61, 0x91, 0x19, 0xcd, 0x44, 0xcd, 0xe4, 0xee, 0x80, 0xca, 0x46, 0x0b, 0x83, - 0xec, 0x97, 0x5c, 0xf1, 0xa9, 0x2a, 0xd1, 0x4a, 0x8b, 0x9a, 0xd1, 0xe1, 0x42, 0x25, 0x74, 0x94, 0x88, 0x2d, 0x17, - 0xd3, 0xae, 0xbc, 0x15, 0x66, 0x7e, 0x08, 0xec, 0x95, 0x19, 0x91, 0xa6, 0x6c, 0x31, 0xcb, 0x11, 0x71, 0x7e, 0xd4, - 0x5d, 0xb3, 0x6a, 0x53, 0x1b, 0x67, 0x2d, 0x3c, 0xdd, 0x52, 0xe4, 0x14, 0x02, 0x17, 0x6d, 0xf7, 0x41, 0x06, 0xc1, - 0xb4, 0x51, 0xe4, 0x46, 0x6f, 0xdd, 0x17, 0x51, 0xc6, 0x2b, 0x32, 0x2e, 0x62, 0x36, 0xb7, 0x7b, 0xb2, 0xb2, 0xa3, - 0x44, 0x79, 0x1c, 0x93, 0xc9, 0xc8, 0x81, 0x4a, 0xda, 0x90, 0x6b, 0xc9, 0xfd, 0x6b, 0xc5, 0x45, 0x5c, 0xfc, 0xbf, - 0x79, 0xd9, 0xd6, 0x45, 0x2d, 0x60, 0x41, 0x07, 0x73, 0x44, 0x81, 0x79, 0x55, 0x4a, 0x07, 0x25, 0x1c, 0x45, 0xe4, - 0x67, 0x05, 0xb3, 0xab, 0x92, 0x35, 0xf8, 0xa0, 0x95, 0xee, 0x0c, 0x93, 0x86, 0x84, 0xcb, 0x35, 0xa9, 0xb5, 0x2d, - 0x1a, 0x19, 0xf1, 0xcc, 0xef, 0x46, 0x25, 0xc2, 0x48, 0x3c, 0xc8, 0x94, 0x98, 0x0b, 0xcf, 0x0a, 0x29, 0xf1, 0x65, - 0xce, 0x3e, 0xd7, 0x8b, 0x6e, 0xb4, 0xc8, 0x62, 0x7e, 0x18, 0xf9, 0xe5, 0x70, 0xb3, 0x5b, 0x11, 0xa3, 0xde, 0x9a, - 0xab, 0xbc, 0x40, 0x99, 0x8d, 0xab, 0x23, 0xc7, 0x9c, 0x03, 0x8d, 0x14, 0x02, 0x85, 0xf4, 0xe9, 0x84, 0x4b, 0x8b, - 0xcb, 0x81, 0x8d, 0x1a, 0xdf, 0x99, 0x8b, 0xa7, 0xa5, 0xbb, 0x8b, 0xa1, 0xe1, 0xb5, 0x43, 0x22, 0x88, 0xd0, 0x78, - 0x93, 0x51, 0x33, 0xb4, 0x2f, 0x76, 0x9d, 0xb7, 0x67, 0xfa, 0xf9, 0x85, 0xa4, 0x67, 0x69, 0xe3, 0x11, 0xe0, 0x52, - 0x52, 0x91, 0xe6, 0xd6, 0x7e, 0x91, 0x43, 0x36, 0xfc, 0x37, 0xcd, 0xfa, 0x15, 0x01, 0xdc, 0x49, 0x02, 0x42, 0x80, - 0x86, 0xd7, 0xf5, 0xcf, 0xc3, 0x58, 0xc2, 0x9e, 0x83, 0xe9, 0xae, 0x82, 0x7f, 0x27, 0x61, 0x72, 0x5e, 0x9a, 0xd0, - 0xf8, 0xa2, 0x4e, 0x0c, 0x76, 0xb2, 0x40, 0xb8, 0x05, 0x58, 0x41, 0x10, 0x08, 0x7a, 0x66, 0xa6, 0x98, 0x4a, 0xe8, - 0x4f, 0xa4, 0x82, 0x0c, 0x09, 0x30, 0xf1, 0xc6, 0x9d, 0x30, 0x28, 0xaa, 0x55, 0x3c, 0x6d, 0x62, 0x36, 0x9c, 0x34, - 0x0c, 0x32, 0xeb, 0x0f, 0xa1, 0xb3, 0x53, 0x4c, 0x93, 0x61, 0x7f, 0x67, 0x6f, 0x3c, 0x9d, 0xb5, 0x2b, 0x51, 0x4a, - 0xc5, 0x3e, 0x35, 0x79, 0x42, 0x2b, 0xaf, 0x0b, 0x51, 0x5f, 0xd0, 0x4b, 0xdc, 0x07, 0x2a, 0xba, 0x83, 0x27, 0x3b, - 0x8a, 0xf4, 0x36, 0x0e, 0x2c, 0x77, 0x90, 0x08, 0xb0, 0xa8, 0xf6, 0x5d, 0x33, 0x0a, 0x19, 0x32, 0x54, 0x01, 0xe6, - 0x1a, 0x73, 0xa7, 0x86, 0xda, 0x43, 0xb9, 0x91, 0x5c, 0x9b, 0x06, 0xab, 0x87, 0xb9, 0x2f, 0xaf, 0xac, 0xdb, 0xdc, - 0xe8, 0x10, 0xee, 0x3b, 0x06, 0x80, 0x5d, 0x8e, 0xc8, 0x70, 0x66, 0x72, 0x9b, 0x50, 0x3d, 0x40, 0x21, 0xab, 0xa6, - 0x9a, 0xd6, 0xe1, 0xf1, 0x92, 0x0f, 0xe2, 0x10, 0xd7, 0x84, 0xd8, 0xa8, 0x3c, 0x42, 0xcf, 0xcd, 0xd8, 0x27, 0xfa, - 0x3e, 0xe5, 0x8e, 0xe6, 0x1b, 0xa4, 0x8e, 0x5c, 0xa6, 0x3a, 0x8f, 0x13, 0x75, 0x6b, 0xac, 0x8e, 0x62, 0x8b, 0x30, - 0xe0, 0xc2, 0x26, 0x86, 0x43, 0x74, 0x2a, 0x4c, 0xb4, 0xc4, 0xbd, 0x8d, 0xb9, 0xea, 0xe5, 0xf6, 0xeb, 0xaa, 0x4b, - 0xfd, 0xb5, 0x84, 0x41, 0x64, 0x7a, 0x68, 0x00, 0x07, 0x42, 0xc6, 0xfa, 0x3a, 0x58, 0xc6, 0x71, 0x46, 0xea, 0x32, - 0x6a, 0x04, 0x63, 0xe9, 0x00, 0xe5, 0xac, 0x7a, 0x1c, 0xed, 0x02, 0x62, 0x79, 0x48, 0x6e, 0x9a, 0xcc, 0x08, 0xd9, - 0x22, 0x97, 0x5f, 0x6a, 0xa1, 0xbf, 0x0a, 0x5d, 0x83, 0x7d, 0x0f, 0xe8, 0x64, 0xc1, 0x31, 0xd4, 0x81, 0x9e, 0x75, - 0xeb, 0x59, 0x2d, 0x81, 0x36, 0xc7, 0xc8, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x6c, 0xc3, 0xbd, 0x03, 0x9c, 0x98, - 0xd2, 0xf5, 0x02, 0xdc, 0x76, 0x70, 0x69, 0xf8, 0xd8, 0x83, 0x6b, 0x75, 0x8c, 0x63, 0x67, 0x92, 0x66, 0xf2, 0x68, - 0xe2, 0xe6, 0x9c, 0x73, 0xa1, 0xc7, 0x39, 0x3c, 0x37, 0xb8, 0xfe, 0x4c, 0xc5, 0x78, 0xb9, 0x55, 0x09, 0xb4, 0x5c, - 0xe5, 0xac, 0x4b, 0x22, 0x96, 0xac, 0x38, 0x47, 0x5f, 0x08, 0xe4, 0x79, 0x9b, 0xdf, 0x2f, 0x34, 0xe8, 0x9c, 0xba, - 0xa8, 0xce, 0x31, 0xc9, 0xec, 0xf4, 0x60, 0xf3, 0x5e, 0x59, 0x1c, 0x1a, 0xab, 0x94, 0x8d, 0xf8, 0xa1, 0x71, 0x4f, - 0x6f, 0xef, 0x67, 0x36, 0x29, 0xe5, 0xcb, 0xa8, 0x72, 0x95, 0xdf, 0xc6, 0x81, 0xa6, 0x9d, 0x91, 0xc8, 0x6e, 0xeb, - 0xdb, 0x75, 0x92, 0x44, 0x24, 0xe9, 0xee, 0x82, 0x28, 0x3c, 0x83, 0x6f, 0x8c, 0x28, 0xd8, 0xd3, 0xa9, 0x75, 0xf9, - 0xd2, 0xcb, 0x72, 0xbc, 0xc2, 0xde, 0x15, 0x83, 0xb1, 0x70, 0x42, 0x07, 0x0b, 0x37, 0x0d, 0x34, 0xb0, 0x93, 0x24, - 0x6e, 0x55, 0x12, 0x6f, 0x5a, 0xfe, 0x99, 0x34, 0x37, 0x22, 0x4f, 0x45, 0x7c, 0x5d, 0xa2, 0xcf, 0x9c, 0x29, 0xd5, - 0xbd, 0x51, 0x45, 0x51, 0x8e, 0x79, 0x2a, 0x27, 0x2c, 0x4a, 0xba, 0x9d, 0x22, 0xf3, 0x64, 0xcf, 0x9b, 0xdb, 0x19, - 0x25, 0x4a, 0x20, 0x75, 0xa1, 0x97, 0xb9, 0x6b, 0x15, 0x3a, 0xd2, 0xc8, 0x98, 0x56, 0x35, 0x9b, 0xe8, 0x71, 0x38, - 0xfb, 0xc9, 0xca, 0x9e, 0xe0, 0xb6, 0xf7, 0xbc, 0xb3, 0x0f, 0x9b, 0x0b, 0xae, 0x43, 0x2b, 0x86, 0xcc, 0x80, 0x99, - 0x66, 0xee, 0x4c, 0x81, 0x2c, 0xec, 0xbe, 0xb2, 0x23, 0x51, 0xc6, 0xf4, 0x8f, 0xad, 0xd6, 0xf3, 0xe5, 0xa0, 0xea, - 0x98, 0xfc, 0xfe, 0x2b, 0x5d, 0xc3, 0x4d, 0x07, 0x45, 0x8e, 0xe1, 0x58, 0xd3, 0xde, 0x10, 0x87, 0x07, 0xc2, 0xf3, - 0x84, 0x18, 0x85, 0x15, 0x6c, 0x8b, 0x46, 0xad, 0xae, 0x02, 0x06, 0x6a, 0x0c, 0x4f, 0xc6, 0xde, 0x28, 0x2c, 0xa3, - 0xf1, 0x95, 0xdd, 0xca, 0x2b, 0x8b, 0x6e, 0x59, 0x93, 0xba, 0x55, 0x4e, 0xa9, 0x3f, 0xe2, 0x5a, 0xb9, 0xc3, 0x84, - 0xdc, 0x70, 0x9d, 0x14, 0x92, 0x7a, 0xe3, 0xb1, 0xc1, 0xb7, 0x76, 0x9e, 0x69, 0xa0, 0xdb, 0xd6, 0xd2, 0x36, 0xb1, - 0x83, 0x69, 0xb8, 0x6d, 0x18, 0xa6, 0xaa, 0x1d, 0xe5, 0xf3, 0xd7, 0xfb, 0xfb, 0xb3, 0xb0, 0x26, 0xb4, 0x69, 0xe8, - 0x6b, 0xa0, 0x6d, 0x8b, 0x62, 0x2e, 0x66, 0x9a, 0x32, 0xb6, 0xd8, 0x77, 0x20, 0xdb, 0x77, 0x7f, 0xb5, 0x92, 0xd0, - 0x24, 0x57, 0xe9, 0xfc, 0x92, 0xfc, 0xa4, 0xd3, 0x09, 0x22, 0x33, 0xbb, 0xc8, 0xef, 0x73, 0xa1, 0xbe, 0xbf, 0x50, - 0xbd, 0x52, 0x1b, 0x59, 0x0a, 0x88, 0xc2, 0x50, 0x78, 0x13, 0x02, 0xd3, 0x25, 0x0b, 0xff, 0x07, 0x3a, 0xce, 0xc9, - 0x98, 0x12, 0xd2, 0x1b, 0x55, 0x3d, 0xba, 0x21, 0xa1, 0x18, 0x5a, 0x58, 0x4e, 0xce, 0x4b, 0x0d, 0xba, 0x3a, 0x11, - 0x3a, 0xb2, 0x3c, 0x50, 0x01, 0x7e, 0xa2, 0xa0, 0x3a, 0x33, 0x33, 0xec, 0x7e, 0x12, 0x18, 0x4b, 0xab, 0x5a, 0xa5, - 0x5f, 0x74, 0x38, 0x5d, 0x51, 0x77, 0x4f, 0xbf, 0x62, 0x48, 0x74, 0x87, 0x5f, 0x2e, 0xb4, 0x3e, 0xb9, 0xb8, 0x14, - 0x68, 0xa4, 0xe3, 0x06, 0x0e, 0xe1, 0xa2, 0xb4, 0xe0, 0xbb, 0x94, 0xc1, 0x86, 0x39, 0x3c, 0xcc, 0x0e, 0xe0, 0x5c, - 0xb9, 0xad, 0x3c, 0x2b, 0x37, 0x81, 0xe9, 0x8b, 0x94, 0xd1, 0x89, 0x63, 0xd4, 0x7d, 0xbb, 0xfb, 0x51, 0x92, 0xf2, - 0xfa, 0xf1, 0x2a, 0x6b, 0x94, 0xbd, 0x67, 0x66, 0x69, 0x57, 0xf1, 0xa7, 0x26, 0xb9, 0x6b, 0x6b, 0xe8, 0xa4, 0x5b, - 0x01, 0xc0, 0x28, 0x37, 0x2b, 0x2c, 0x77, 0x01, 0xc8, 0x61, 0x73, 0x2f, 0x43, 0x41, 0x9a, 0xec, 0x44, 0x55, 0x62, - 0x42, 0x48, 0xa1, 0xfd, 0x71, 0x77, 0xee, 0x8f, 0x4e, 0x16, 0xd0, 0x51, 0xdf, 0x85, 0x6a, 0xe6, 0xed, 0xdf, 0x2e, - 0x77, 0xec, 0x60, 0x9a, 0xae, 0x01, 0xd3, 0x3c, 0x40, 0xe8, 0xae, 0xda, 0x41, 0xff, 0x12, 0xff, 0x94, 0xef, 0x2f, - 0x08, 0xda, 0xc1, 0x17, 0xd1, 0x9a, 0xf2, 0xb1, 0x38, 0x28, 0xa1, 0x6c, 0xdb, 0x2e, 0x4d, 0xc0, 0x14, 0x39, 0x48, - 0xb7, 0x90, 0x81, 0x28, 0x59, 0x08, 0x66, 0x50, 0xf9, 0x59, 0xbc, 0x4c, 0x7c, 0x9d, 0x8f, 0x36, 0x3c, 0x46, 0x14, - 0xae, 0x0a, 0xb9, 0x86, 0x61, 0xb4, 0x98, 0x57, 0xa7, 0x9d, 0x54, 0x1b, 0x87, 0x06, 0x35, 0xea, 0x18, 0xdb, 0x75, - 0x7c, 0xf8, 0xce, 0x12, 0x75, 0x83, 0xe6, 0xd5, 0x9a, 0x80, 0x1f, 0x1b, 0x8d, 0x15, 0x67, 0x0f, 0x71, 0x6a, 0xcd, - 0x78, 0xbc, 0x50, 0xf6, 0xa8, 0xea, 0x15, 0xb5, 0xc6, 0x41, 0x0e, 0x76, 0x5a, 0x1b, 0x93, 0x14, 0x72, 0xe7, 0xe1, - 0x52, 0xbe, 0x73, 0x0a, 0x97, 0xde, 0xa8, 0x44, 0x94, 0x07, 0xd0, 0x09, 0x5b, 0x2a, 0x6e, 0x54, 0xdc, 0x02, 0x2a, - 0x67, 0x7a, 0xb2, 0x24, 0xa6, 0x73, 0x12, 0x31, 0x66, 0x7c, 0x4a, 0xb7, 0xe3, 0x10, 0xd5, 0xd0, 0x0c, 0x3d, 0xbd, - 0x8f, 0xea, 0x09, 0x72, 0x40, 0x6a, 0xe3, 0x3a, 0x43, 0x88, 0x4e, 0x2a, 0x7c, 0x51, 0x2b, 0x62, 0xcb, 0xfc, 0x13, - 0x41, 0x6d, 0x5b, 0x33, 0x3f, 0x22, 0xca, 0xab, 0xa5, 0x6f, 0x72, 0x7f, 0xc5, 0x9e, 0xf1, 0x8a, 0xc7, 0xe8, 0xca, - 0x4b, 0x7e, 0x0e, 0xf3, 0xb3, 0x5f, 0x3f, 0x80, 0x09, 0x44, 0x9c, 0x67, 0x32, 0xea, 0x29, 0x39, 0x9a, 0xeb, 0x9c, - 0xf7, 0x2d, 0x74, 0x46, 0xc9, 0x34, 0x20, 0x62, 0x2d, 0xb3, 0x04, 0xe2, 0xc8, 0x24, 0x71, 0x51, 0x28, 0xeb, 0xa8, - 0x93, 0x47, 0x07, 0xbd, 0x37, 0x91, 0xfb, 0x82, 0x26, 0x7d, 0x05, 0xfe, 0xd8, 0x55, 0x5b, 0x5b, 0xb5, 0x6f, 0x5e, - 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0xe3, 0x5c, 0x15, 0xd0, 0xbf, 0xce, 0x95, 0xd6, 0x52, 0x5d, 0xa0, 0x8b, 0x43, 0x8e, - 0x51, 0x8b, 0xf2, 0xd4, 0x6a, 0x18, 0xda, 0x03, 0x65, 0xaf, 0x61, 0x42, 0x0f, 0xf8, 0xf9, 0x3a, 0xc9, 0x68, 0xf0, - 0xce, 0xc3, 0xb6, 0x1a, 0xd3, 0x45, 0xce, 0xbb, 0x05, 0x04, 0xdc, 0xae, 0xb7, 0xa4, 0x26, 0x42, 0x6a, 0xdc, 0x64, - 0x62, 0x8b, 0xc4, 0xbc, 0x8a, 0x3a, 0x9c, 0x5d, 0x21, 0xa9, 0x43, 0x6c, 0x8a, 0x11, 0xa6, 0xa0, 0x36, 0xe3, 0x62, - 0x43, 0x8b, 0x71, 0x13, 0x39, 0xb0, 0x36, 0x8f, 0x24, 0xe3, 0x70, 0x47, 0x33, 0x1d, 0x06, 0x72, 0x2d, 0xc1, 0x65, - 0x89, 0xe8, 0x6d, 0xaa, 0xf6, 0x1a, 0x32, 0x6c, 0x6e, 0x91, 0x2c, 0x94, 0x99, 0x1e, 0x0f, 0x81, 0x76, 0xfd, 0xa5, - 0x6d, 0x3b, 0x54, 0xf0, 0x97, 0xf3, 0x98, 0x14, 0xdb, 0xef, 0xb3, 0x5f, 0x3a, 0x88, 0x21, 0x9c, 0x3a, 0xdd, 0x37, - 0x01, 0xd6, 0x39, 0xe4, 0x14, 0x1b, 0xc2, 0x18, 0x67, 0x1c, 0xb5, 0xbb, 0x8e, 0x36, 0xf6, 0x53, 0x62, 0x08, 0x94, - 0x0e, 0xdf, 0xee, 0x68, 0xe5, 0x75, 0x47, 0xb6, 0x66, 0x7b, 0x49, 0x3b, 0xf2, 0x31, 0x39, 0x82, 0x49, 0x10, 0x49, - 0x4b, 0x03, 0xa1, 0x19, 0x83, 0xb7, 0x48, 0x0b, 0xd6, 0x7a, 0x06, 0xb4, 0xcc, 0xf5, 0x42, 0xa1, 0x05, 0x9e, 0xbe, - 0x31, 0x30, 0x29, 0x2c, 0x3a, 0xb8, 0xa4, 0x83, 0x67, 0x33, 0xcc, 0x16, 0xaa, 0xd5, 0xfa, 0xea, 0xc8, 0xf6, 0x26, - 0x51, 0x20, 0xec, 0xbc, 0xa4, 0x9b, 0xed, 0x47, 0x7e, 0x66, 0x9e, 0x80, 0x39, 0x39, 0xb7, 0xeb, 0xfe, 0xdc, 0xee, - 0xfd, 0x7a, 0x0d, 0x3e, 0xf6, 0x37, 0x38, 0xff, 0x0c, 0x31, 0x2c, 0x4b, 0x26, 0x4c, 0x57, 0x16, 0x93, 0x5f, 0x83, - 0xe6, 0x3e, 0xd9, 0x98, 0x4c, 0xef, 0x50, 0xa2, 0x89, 0xaf, 0xbb, 0x50, 0x60, 0x6c, 0x19, 0xd1, 0xcb, 0xfa, 0xed, - 0x3e, 0x3e, 0xbd, 0x2d, 0xda, 0x20, 0xa6, 0x5e, 0x59, 0x32, 0x1e, 0x56, 0xf4, 0xc5, 0x43, 0x50, 0x1a, 0x3f, 0xaa, - 0x4c, 0x06, 0x5f, 0xd4, 0xbb, 0x16, 0x12, 0xe1, 0x1f, 0xf5, 0x28, 0x4f, 0x66, 0x2b, 0x1b, 0xb6, 0x5d, 0x4f, 0xca, - 0x03, 0x21, 0x61, 0x34, 0xfd, 0xa3, 0x49, 0x6b, 0x2e, 0xa5, 0xe1, 0x6f, 0x96, 0xe2, 0xa2, 0xd9, 0x38, 0xca, 0xb6, - 0x12, 0x18, 0x5d, 0xd5, 0x42, 0xb2, 0x28, 0x3c, 0x2c, 0x78, 0x28, 0x5f, 0x56, 0xc2, 0xb2, 0x17, 0xdd, 0xe9, 0x44, - 0xbe, 0xb1, 0xf7, 0x2b, 0xf5, 0xff, 0x4f, 0x55, 0xfc, 0xf9, 0xa9, 0x9d, 0x28, 0xab, 0x9f, 0x75, 0xa1, 0xa3, 0x1a, - 0xeb, 0x63, 0xf3, 0xcf, 0xa7, 0xfe, 0xf5, 0x35, 0x9b, 0x9a, 0xbd, 0x6c, 0x07, 0x4c, 0xf7, 0x14, 0xb0, 0x65, 0xda, - 0x1e, 0xb6, 0x14, 0x3f, 0xde, 0xbe, 0x38, 0x6a, 0x17, 0x24, 0x3e, 0x61, 0xc1, 0x91, 0xa4, 0x78, 0x6c, 0xd0, 0x81, - 0x52, 0xcb, 0x80, 0x7a, 0x04, 0xfb, 0xb6, 0xb1, 0x23, 0xdf, 0x38, 0x4c, 0x7e, 0x33, 0xcd, 0xdb, 0x0e, 0x61, 0xde, - 0xe6, 0x21, 0xb0, 0x71, 0x9b, 0xbb, 0x1c, 0x18, 0x12, 0x07, 0x1a, 0x62, 0xa6, 0xfd, 0x17, 0xdd, 0x9f, 0xc9, 0xaa, - 0x4e, 0xa5, 0x43, 0x31, 0xe6, 0x6a, 0x25, 0xe6, 0xa4, 0x31, 0x37, 0xb4, 0x23, 0xdc, 0xb0, 0x37, 0xd2, 0x0b, 0x47, - 0xb7, 0x18, 0x71, 0x60, 0x44, 0x9d, 0x16, 0x7d, 0x41, 0xa2, 0xa2, 0xc9, 0x9e, 0x56, 0x1e, 0x5f, 0x08, 0x93, 0xc0, - 0xba, 0xdb, 0xec, 0x9c, 0xbf, 0x10, 0xc9, 0xec, 0x89, 0x30, 0x99, 0x43, 0xbd, 0x83, 0x97, 0x94, 0x68, 0xd5, 0xb6, - 0x5b, 0x07, 0x04, 0x76, 0x02, 0xe6, 0x69, 0x89, 0xbc, 0x4e, 0xc9, 0xec, 0xde, 0xbe, 0xf5, 0xb3, 0x4a, 0x99, 0x98, - 0x41, 0xcd, 0x3e, 0x0e, 0x49, 0x43, 0xc4, 0x71, 0x5c, 0xda, 0x6d, 0xc8, 0x0c, 0xc4, 0x58, 0x7f, 0x71, 0xf2, 0x64, - 0xf2, 0x02, 0xb5, 0x92, 0x26, 0xe1, 0x98, 0x1b, 0x0d, 0x13, 0x2b, 0xe3, 0x55, 0xc6, 0x15, 0xbb, 0x15, 0xfd, 0x24, - 0xf2, 0xa0, 0x45, 0x2b, 0xa1, 0xf7, 0x54, 0xb9, 0x48, 0x4a, 0x5a, 0xe1, 0x50, 0xa7, 0xfc, 0xc1, 0x50, 0x0e, 0x93, - 0x63, 0x59, 0xd7, 0x59, 0x8c, 0x61, 0x76, 0x96, 0x53, 0x18, 0xb9, 0xc5, 0x29, 0x62, 0xd1, 0x19, 0x72, 0x19, 0xd6, - 0x50, 0x01, 0x01, 0xe3, 0xc0, 0x14, 0x7e, 0xf2, 0x71, 0xa1, 0xfd, 0xed, 0x0c, 0x5c, 0xb6, 0xf1, 0x45, 0xc2, 0xd0, - 0x8d, 0x71, 0x2b, 0x98, 0xc1, 0x64, 0x88, 0x9e, 0xaf, 0xc0, 0xba, 0xdc, 0x89, 0xe7, 0x25, 0xcb, 0xa9, 0x66, 0xc8, - 0xa1, 0x59, 0x37, 0xeb, 0x75, 0xdf, 0x44, 0xab, 0x14, 0x0a, 0x88, 0x35, 0x4e, 0x5a, 0xd3, 0x35, 0xdd, 0x12, 0x74, - 0x44, 0x49, 0x66, 0x06, 0x33, 0x03, 0xe4, 0xec, 0x24, 0xa3, 0x56, 0x03, 0x7d, 0x31, 0x9c, 0x58, 0xcc, 0x34, 0x31, - 0x18, 0xb0, 0x36, 0x64, 0x1f, 0x64, 0x17, 0xbe, 0x01, 0xa0, 0xfa, 0xca, 0x29, 0xc3, 0x98, 0x4c, 0xde, 0x68, 0xa4, - 0x31, 0x5b, 0xf6, 0xbf, 0x68, 0xaf, 0x01, 0xac, 0x26, 0xd9, 0x8f, 0xf6, 0x02, 0x7d, 0x5d, 0xaf, 0x11, 0xd3, 0x16, - 0x3e, 0x61, 0xab, 0x03, 0xb6, 0x48, 0xea, 0x2e, 0x92, 0x18, 0x49, 0x7a, 0x9e, 0x6b, 0x34, 0xa2, 0x04, 0x43, 0xf5, - 0xd4, 0x2c, 0x7b, 0x1e, 0xa9, 0x78, 0x6b, 0xc2, 0x2b, 0x96, 0xe2, 0x00, 0x74, 0x41, 0xb5, 0x75, 0x08, 0xce, 0x76, - 0xbc, 0x22, 0x0a, 0x63, 0x3d, 0x8a, 0x25, 0x4e, 0xf8, 0x7d, 0xf1, 0x4a, 0x4e, 0x39, 0x42, 0x69, 0xc6, 0xe7, 0xe0, - 0x5c, 0x99, 0xc7, 0x1f, 0x7f, 0xe9, 0x63, 0x1c, 0xb1, 0x8f, 0x87, 0xd8, 0xe7, 0x67, 0x39, 0x3d, 0xff, 0x2e, 0xe1, - 0xa9, 0xf8, 0x2a, 0x7d, 0x0d, 0xef, 0x2c, 0x21, 0xe7, 0x3d, 0x08, 0xff, 0x85, 0x16, 0x07, 0xc3, 0x42, 0x27, 0xe7, - 0xa2, 0x1e, 0x9c, 0x5f, 0x3d, 0x27, 0xb8, 0xa8, 0xf1, 0x98, 0x00, 0x99, 0x4a, 0xca, 0xea, 0xb7, 0x44, 0x0a, 0x64, - 0x5d, 0x54, 0xc4, 0xc9, 0x13, 0x58, 0xa6, 0x80, 0x73, 0x47, 0x19, 0x06, 0x0d, 0x59, 0xf7, 0xe3, 0x6d, 0x67, 0x89, - 0x1d, 0x30, 0xff, 0x63, 0x52, 0xac, 0x5e, 0x83, 0x48, 0x06, 0x95, 0xb4, 0x93, 0x54, 0xfa, 0xa0, 0xc0, 0x03, 0x1b, - 0x4d, 0xce, 0xab, 0xa6, 0xb2, 0xcc, 0x13, 0xe8, 0x0c, 0x48, 0x63, 0x4b, 0x53, 0xc6, 0xa7, 0x19, 0xa0, 0x18, 0x85, - 0x37, 0xb2, 0xb5, 0x6a, 0x0c, 0x12, 0x49, 0x75, 0xfe, 0x8d, 0x3d, 0xce, 0x54, 0xe1, 0x55, 0x74, 0xe1, 0x9c, 0x9b, - 0x8f, 0x0e, 0x9c, 0x0f, 0x6b, 0x9b, 0xe1, 0xcb, 0x9f, 0x11, 0x2d, 0xb0, 0x6b, 0x52, 0x07, 0x55, 0x59, 0xf3, 0x92, - 0x4e, 0xf8, 0x27, 0x6c, 0x2f, 0x51, 0xcc, 0xe4, 0x25, 0xf5, 0x17, 0xd3, 0x11, 0x52, 0xf3, 0xd0, 0x65, 0xd6, 0xff, - 0x51, 0xcc, 0xe4, 0x78, 0x18, 0xab, 0xe9, 0x87, 0xc6, 0xf8, 0xb7, 0x88, 0x0a, 0xb8, 0x4f, 0xeb, 0x87, 0x2a, 0x32, - 0xb1, 0x3a, 0xae, 0x8d, 0x17, 0xe4, 0x3e, 0x86, 0xe9, 0x68, 0xb1, 0xca, 0xb2, 0x8c, 0x7b, 0xa5, 0xcc, 0xca, 0x14, - 0x82, 0xc3, 0x33, 0x65, 0x44, 0x15, 0x3a, 0xcf, 0x21, 0x2f, 0xcd, 0xfc, 0xb2, 0x4a, 0x85, 0xe9, 0x43, 0x99, 0x8b, - 0xce, 0x5b, 0xa2, 0xee, 0x7a, 0x5f, 0xf8, 0xfd, 0x13, 0x0a, 0x6d, 0x31, 0x10, 0xf2, 0xc1, 0x19, 0x9c, 0x26, 0xd1, - 0x3d, 0x32, 0x11, 0x79, 0xf8, 0x8b, 0x5d, 0xbf, 0x08, 0x95, 0xf4, 0xfc, 0x60, 0x1e, 0xbe, 0x76, 0x59, 0xdc, 0xbd, - 0xd2, 0xaf, 0xd5, 0xe7, 0xe8, 0x43, 0x09, 0x47, 0x41, 0x46, 0x69, 0xf7, 0xc3, 0xf2, 0x71, 0x1d, 0x28, 0x5f, 0xff, - 0x83, 0xe4, 0x73, 0xc8, 0xa2, 0x11, 0xd1, 0x12, 0x9d, 0x6a, 0x07, 0x47, 0xfd, 0x30, 0x0b, 0xe1, 0xdf, 0x64, 0x08, - 0xce, 0xa2, 0xab, 0x5e, 0x1e, 0x4c, 0xeb, 0xc9, 0x3f, 0x21, 0x93, 0xdf, 0x2f, 0xaa, 0xc9, 0xe1, 0x34, 0x5c, 0xf0, - 0x23, 0x15, 0xfd, 0xb0, 0xaa, 0xdb, 0xfb, 0x69, 0x9f, 0xa7, 0x3d, 0x04, 0xcc, 0x3e, 0xd2, 0x10, 0xc9, 0x9b, 0xa5, - 0x75, 0x18, 0x66, 0x09, 0x8b, 0x0b, 0x5a, 0x83, 0x9e, 0xaa, 0x5a, 0xa5, 0x55, 0xe0, 0x8c, 0x8f, 0x04, 0x1d, 0x34, - 0x70, 0xb4, 0x5c, 0x79, 0xf8, 0x42, 0xc0, 0xe2, 0xa4, 0x62, 0xbb, 0x2d, 0xca, 0xf2, 0x9e, 0xc1, 0x71, 0xb4, 0x88, - 0x9a, 0xcc, 0xcb, 0xaf, 0x52, 0x5b, 0xc9, 0xc5, 0x55, 0xb4, 0xe0, 0x8e, 0xbe, 0x90, 0x14, 0x4b, 0x2d, 0x0d, 0xf9, - 0xba, 0x94, 0x6c, 0xa3, 0x02, 0x95, 0x52, 0xae, 0xa9, 0x1a, 0x97, 0x33, 0x70, 0x65, 0x6c, 0x4d, 0x25, 0x0e, 0xb4, - 0x2a, 0x5e, 0x83, 0xe4, 0xd2, 0xf3, 0x6b, 0x84, 0x97, 0x08, 0x59, 0x06, 0x0e, 0x0f, 0x67, 0x25, 0x7d, 0x9e, 0x5c, - 0xc3, 0x28, 0x9e, 0xf3, 0x98, 0x83, 0xa9, 0xf3, 0x81, 0x32, 0x57, 0x34, 0x59, 0x8b, 0x8a, 0xe6, 0xe4, 0xd4, 0xb9, - 0xea, 0x80, 0xba, 0x22, 0x23, 0x30, 0x0b, 0xf7, 0x91, 0x1f, 0xa5, 0xa4, 0x57, 0xca, 0xf0, 0x15, 0xee, 0x44, 0x49, - 0xb6, 0xe3, 0x64, 0x38, 0xdc, 0xd1, 0xc6, 0xce, 0x85, 0x1a, 0x3f, 0x0a, 0x79, 0xa5, 0x6c, 0x8f, 0x91, 0x31, 0x94, - 0x5c, 0xec, 0x9e, 0xba, 0x2e, 0x1a, 0x22, 0x3d, 0x59, 0x10, 0x00, 0x91, 0x87, 0xb1, 0x0f, 0x16, 0x97, 0x47, 0x53, - 0x0b, 0x98, 0x98, 0xe7, 0xca, 0x4f, 0xda, 0x2b, 0x7c, 0xb5, 0x0e, 0x79, 0x15, 0xca, 0x24, 0x6a, 0xa5, 0xcd, 0xf8, - 0x4d, 0x59, 0x1e, 0x95, 0x57, 0xcb, 0x6a, 0xba, 0xa2, 0x7a, 0xd0, 0x98, 0x1e, 0xae, 0x53, 0x62, 0x6c, 0x2c, 0xb3, - 0x4e, 0xd5, 0x2b, 0xe6, 0xbf, 0xcf, 0xd6, 0x2b, 0x65, 0x75, 0x51, 0xd5, 0xf2, 0x2d, 0xca, 0xed, 0x8f, 0x10, 0x60, - 0x51, 0xc3, 0x03, 0xbe, 0x5e, 0x2e, 0x63, 0x58, 0xae, 0x09, 0x66, 0xd9, 0x2f, 0xaf, 0xb7, 0xd5, 0x10, 0xa4, 0x1d, - 0x8f, 0xe2, 0x39, 0xe8, 0x46, 0x0c, 0x68, 0xa4, 0xd4, 0x08, 0x58, 0x93, 0x42, 0x0c, 0x9e, 0x75, 0xfb, 0x13, 0x05, - 0x22, 0x15, 0x1c, 0xc1, 0x03, 0xc2, 0xa9, 0x89, 0xcb, 0x0f, 0xb3, 0xee, 0x16, 0x62, 0x48, 0xc5, 0xcb, 0x5d, 0xf9, - 0xb4, 0xa4, 0x64, 0x64, 0x83, 0x1a, 0x11, 0x92, 0x21, 0x04, 0x75, 0x33, 0x23, 0xa3, 0x0e, 0xce, 0x18, 0x7d, 0x23, - 0x62, 0xc0, 0x29, 0x05, 0x40, 0x1e, 0x73, 0x3a, 0x69, 0x2e, 0x5f, 0xe6, 0x2e, 0xfd, 0x03, 0x3d, 0x95, 0xe3, 0xd6, - 0x44, 0xd0, 0xa6, 0x57, 0x51, 0xe7, 0xa2, 0xe2, 0xe0, 0x7a, 0x59, 0x62, 0xc0, 0x44, 0xf3, 0x85, 0xab, 0xd3, 0xe4, - 0xb2, 0x85, 0x8f, 0xcf, 0x4d, 0xf6, 0xe1, 0x23, 0xe2, 0xf1, 0x04, 0x31, 0x3c, 0xec, 0xd4, 0x6d, 0x23, 0x07, 0x8c, - 0x00, 0x7f, 0xab, 0xdf, 0x4f, 0x5c, 0x5d, 0xb6, 0xcc, 0x05, 0xa9, 0xa1, 0x6f, 0xf0, 0xed, 0x60, 0xfc, 0xa9, 0xab, - 0x1b, 0x4f, 0xc9, 0xba, 0x47, 0x16, 0xdd, 0xbd, 0xac, 0xe1, 0x0b, 0x26, 0xe8, 0xfc, 0x3c, 0x23, 0xf7, 0xc9, 0x82, - 0xe5, 0xbe, 0x14, 0x8d, 0x04, 0x99, 0xc6, 0xc3, 0x14, 0x23, 0x72, 0x8d, 0x67, 0x39, 0x5a, 0x6b, 0x4c, 0x6c, 0xb9, - 0xe0, 0x88, 0xed, 0x34, 0xb8, 0x6c, 0x93, 0x8c, 0xa5, 0x1a, 0xdf, 0xdf, 0x44, 0x22, 0x18, 0xa9, 0xa1, 0x7d, 0x5e, - 0xd6, 0xa7, 0xca, 0xa7, 0xff, 0x63, 0x7e, 0x74, 0x61, 0x65, 0x98, 0x23, 0x30, 0xe3, 0x6b, 0xfc, 0x34, 0xd3, 0x12, - 0x58, 0x78, 0xd0, 0xda, 0xbd, 0xec, 0x6e, 0xac, 0x39, 0xa3, 0x1f, 0xa6, 0x3b, 0x25, 0xd9, 0x05, 0xb6, 0xe3, 0x5f, - 0x83, 0x9e, 0x0a, 0xa5, 0x1f, 0xd5, 0x81, 0xc5, 0x1f, 0x05, 0x89, 0x09, 0xc9, 0x50, 0x80, 0x03, 0xb9, 0x6a, 0xde, - 0x7b, 0xba, 0x1d, 0x4b, 0xe8, 0x11, 0x97, 0xce, 0x56, 0x5f, 0xde, 0xc8, 0xbc, 0x40, 0x67, 0xce, 0x7e, 0xb4, 0x79, - 0xbf, 0x65, 0x1e, 0x6f, 0x68, 0x2f, 0x8c, 0xdf, 0x50, 0x18, 0x5a, 0xe3, 0x4b, 0x48, 0x18, 0x0c, 0xdd, 0x19, 0xd6, - 0xde, 0xd4, 0x7b, 0xfc, 0xa2, 0xd7, 0xea, 0x2c, 0x98, 0xf1, 0xaa, 0x44, 0x2b, 0x13, 0x97, 0x1b, 0x4a, 0xf2, 0xe1, - 0x1e, 0xc1, 0x75, 0xfc, 0x6c, 0x27, 0xe1, 0xae, 0xc7, 0x37, 0xba, 0x60, 0x19, 0x06, 0xa6, 0x2b, 0x5c, 0x07, 0x62, - 0x08, 0x63, 0xcb, 0x08, 0xb2, 0xd4, 0x9f, 0xe8, 0x37, 0x8c, 0x82, 0xf1, 0xfb, 0xc3, 0xf5, 0x9b, 0xdd, 0xf1, 0x1f, - 0x56, 0x00, 0xce, 0x5d, 0x84, 0x23, 0xb0, 0xcc, 0x46, 0x50, 0x61, 0x81, 0x0b, 0x7d, 0x54, 0x9e, 0xa6, 0xca, 0x01, - 0xe8, 0x02, 0xf2, 0x73, 0x4c, 0xfb, 0xc3, 0xae, 0xf3, 0x7b, 0x29, 0xf2, 0xb3, 0x8d, 0x6e, 0xdf, 0x6f, 0x96, 0x6e, - 0x74, 0xbf, 0x6d, 0x71, 0x99, 0x70, 0x4d, 0xb3, 0xe1, 0x9a, 0x45, 0xa7, 0x77, 0x62, 0xc7, 0x4d, 0xed, 0x59, 0x5b, - 0x96, 0xe4, 0x64, 0xb4, 0x5f, 0x6b, 0xea, 0x32, 0x99, 0xd3, 0x6d, 0xcd, 0xe4, 0xec, 0xd4, 0x7c, 0xf3, 0x8f, 0x95, - 0x26, 0x8b, 0xfd, 0xc5, 0xfe, 0x3a, 0x8b, 0x1e, 0xc5, 0x97, 0x0b, 0x2d, 0xf3, 0xa6, 0xa8, 0x01, 0x7e, 0xbc, 0xd3, - 0x2c, 0x94, 0x10, 0xb6, 0x0e, 0x19, 0xf7, 0x36, 0x34, 0x40, 0x73, 0xf2, 0x4e, 0x90, 0xa2, 0x04, 0x92, 0x77, 0xac, - 0xc0, 0x52, 0xf1, 0x81, 0x61, 0xf0, 0xd8, 0xfb, 0xd4, 0xbb, 0x9a, 0xa2, 0xae, 0x70, 0x99, 0x68, 0xec, 0x46, 0x99, - 0x2f, 0xdc, 0x47, 0xb7, 0xd3, 0x7f, 0x44, 0xce, 0xe0, 0xaf, 0x44, 0xbe, 0x0f, 0x8e, 0x0f, 0x43, 0x47, 0x59, 0x3c, - 0xa9, 0xbc, 0xf2, 0xb9, 0x03, 0xb9, 0x7d, 0x2d, 0x9f, 0xe6, 0xba, 0x02, 0x89, 0x1c, 0xf3, 0xcd, 0x5c, 0xd4, 0xa2, - 0xd6, 0x4a, 0x73, 0xb7, 0x3c, 0x9a, 0x86, 0x18, 0x1d, 0x00, 0x90, 0x32, 0x60, 0xfc, 0x14, 0xab, 0xa9, 0x33, 0xfe, - 0xe9, 0x2c, 0xd5, 0x39, 0xdd, 0xdf, 0xbc, 0x23, 0xd3, 0x5b, 0x9a, 0x03, 0xbe, 0x0b, 0xf9, 0xbf, 0xfd, 0x13, 0xdd, - 0x3a, 0x26, 0xb2, 0x84, 0xd9, 0xc1, 0xd5, 0x8d, 0xe4, 0xa2, 0xf5, 0xad, 0x89, 0xab, 0x98, 0x78, 0xdf, 0xa7, 0xb6, - 0xc5, 0x43, 0x02, 0xa3, 0x29, 0xdc, 0x66, 0xd1, 0xe8, 0x25, 0x34, 0x0e, 0x33, 0x61, 0xb6, 0x8d, 0x8e, 0x65, 0x0d, - 0xc1, 0xf5, 0x3e, 0x21, 0xd5, 0xc5, 0x93, 0x39, 0xb3, 0xba, 0x7e, 0xf3, 0x54, 0x80, 0x27, 0x56, 0x51, 0x8d, 0x5e, - 0xda, 0xb6, 0x7b, 0xd4, 0xa5, 0xa6, 0xfb, 0x13, 0xa7, 0x11, 0xec, 0x51, 0x10, 0xa2, 0x03, 0x61, 0x79, 0xa4, 0xa1, - 0x63, 0x83, 0x7d, 0x9b, 0x0f, 0xd8, 0x0b, 0x00, 0x74, 0x80, 0x87, 0xe3, 0x26, 0x3a, 0xaf, 0xfa, 0xc7, 0x1e, 0x90, - 0x6a, 0x7c, 0x8f, 0x26, 0x55, 0x6e, 0xe4, 0x52, 0x75, 0x91, 0xa0, 0x6c, 0x1a, 0x1f, 0xdf, 0xe5, 0x56, 0xeb, 0xe1, - 0x25, 0xb1, 0x2a, 0x85, 0xda, 0xa6, 0xf7, 0x96, 0x8d, 0x6a, 0x6a, 0xfd, 0xc1, 0x69, 0xc1, 0xb1, 0xa1, 0x4b, 0xad, - 0xa7, 0xdb, 0xe2, 0x51, 0x6b, 0x9d, 0xde, 0x01, 0x9c, 0x6e, 0x20, 0x84, 0x23, 0x5e, 0xfe, 0x4a, 0x72, 0x0a, 0xf0, - 0x06, 0x70, 0x57, 0x9c, 0x80, 0xb0, 0x1d, 0x77, 0xe3, 0x9a, 0x2d, 0xfc, 0xd9, 0x05, 0x88, 0xb0, 0xae, 0x3a, 0xd7, - 0xa1, 0x3c, 0x0b, 0x2a, 0x8c, 0x52, 0x21, 0x01, 0xe1, 0x70, 0x39, 0x9b, 0x14, 0x84, 0x92, 0x80, 0xbe, 0x2a, 0xa6, - 0x3f, 0x94, 0xde, 0x76, 0xbb, 0x71, 0x21, 0x8f, 0xc4, 0xc3, 0x40, 0xc5, 0x7a, 0x4c, 0xdd, 0x17, 0xd8, 0xc6, 0x23, - 0x64, 0x2d, 0xa4, 0xa7, 0xe4, 0x0b, 0x04, 0x49, 0x2e, 0x05, 0x8f, 0x44, 0x2c, 0xee, 0x78, 0x42, 0x6a, 0xa5, 0x8b, - 0x81, 0x10, 0xf1, 0xfa, 0xc0, 0xc5, 0x1c, 0xee, 0x17, 0x76, 0x19, 0xf0, 0x38, 0x8b, 0x69, 0xd0, 0x93, 0xa8, 0xae, - 0xa2, 0xa7, 0x80, 0x74, 0x98, 0x35, 0x0c, 0x04, 0x9c, 0x52, 0xbf, 0xd6, 0x4d, 0x79, 0x43, 0x9c, 0xa5, 0xd7, 0x58, - 0x18, 0xb0, 0xdb, 0xe7, 0x4c, 0xda, 0x0a, 0xd9, 0x52, 0x6a, 0x28, 0x59, 0x09, 0x1a, 0x2e, 0x9d, 0xad, 0xa2, 0x45, - 0x2b, 0x08, 0x7f, 0x5c, 0xcb, 0x8c, 0xa8, 0xbf, 0x90, 0x69, 0xd6, 0xad, 0xbb, 0x84, 0xb4, 0x9a, 0x53, 0x3b, 0xb7, - 0x40, 0xbd, 0xa0, 0x81, 0x79, 0x8c, 0x41, 0x6b, 0x71, 0xa9, 0xc9, 0x5c, 0xd6, 0xc5, 0x30, 0xe3, 0x0d, 0xc3, 0xc3, - 0xc6, 0xac, 0x97, 0xc9, 0xc6, 0xd5, 0x8d, 0x4f, 0x73, 0x09, 0x3a, 0x18, 0x74, 0x91, 0x90, 0x52, 0x9b, 0x50, 0x91, - 0xff, 0x7a, 0xb1, 0x2e, 0x9c, 0x26, 0x24, 0x9b, 0xa9, 0xac, 0x0f, 0x68, 0x60, 0xcf, 0x08, 0x71, 0xf4, 0x03, 0x51, - 0x26, 0xef, 0x3f, 0x1e, 0xcf, 0x9e, 0xfa, 0x03, 0x64, 0xf2, 0x73, 0x1b, 0x4c, 0xb8, 0xd0, 0xe3, 0x04, 0x3e, 0x00, - 0x92, 0x4e, 0x34, 0x13, 0xac, 0xa7, 0x64, 0x75, 0x09, 0x90, 0xf4, 0x29, 0x79, 0x7a, 0x60, 0xc1, 0x54, 0xef, 0x94, - 0x82, 0x11, 0xc9, 0x00, 0x43, 0x3b, 0x69, 0x54, 0x96, 0x0c, 0x24, 0x7b, 0x68, 0x00, 0x7b, 0x0a, 0x05, 0x19, 0x23, - 0xce, 0x1e, 0xfb, 0x7c, 0x04, 0x04, 0xe5, 0xe1, 0x0c, 0xc2, 0xf4, 0x39, 0xc1, 0x46, 0x9e, 0x63, 0xb0, 0xc8, 0x8b, - 0x06, 0x39, 0x2a, 0x7b, 0x59, 0x2b, 0xfc, 0xd7, 0x11, 0x72, 0x81, 0xc1, 0x63, 0x7a, 0xd2, 0xc9, 0xb5, 0x7e, 0x53, - 0x2e, 0x41, 0xc1, 0xe8, 0x53, 0xd6, 0x10, 0xe3, 0xdc, 0x90, 0x2d, 0x99, 0x3b, 0xf5, 0x67, 0xee, 0x62, 0x8a, 0x6f, - 0xe5, 0xcc, 0x28, 0xcb, 0x34, 0xc4, 0x0b, 0x3f, 0x80, 0x83, 0x9f, 0x67, 0x13, 0x83, 0xc2, 0xfb, 0x4e, 0x97, 0xb1, - 0x20, 0x0e, 0x71, 0x95, 0x8f, 0x3e, 0x3d, 0x45, 0x8c, 0x1a, 0x2c, 0x26, 0xb7, 0xa8, 0xd7, 0x0c, 0x7b, 0x0b, 0xf5, - 0x99, 0xc1, 0x50, 0x9b, 0x44, 0x3d, 0xcd, 0x09, 0x1a, 0x1a, 0x5e, 0xf2, 0xa9, 0x92, 0x75, 0x1c, 0x2b, 0xfc, 0x72, - 0x05, 0x98, 0x0b, 0x4c, 0xf3, 0x34, 0x0e, 0x06, 0x2b, 0x2d, 0xd5, 0x30, 0xf2, 0x44, 0xf0, 0x10, 0x4a, 0xdd, 0xe8, - 0x05, 0x34, 0x80, 0xe1, 0x10, 0xd0, 0x8a, 0x5e, 0x5e, 0xf8, 0x48, 0x83, 0x54, 0xed, 0xc8, 0x29, 0xa3, 0x43, 0x4e, - 0x55, 0xfd, 0x85, 0xf8, 0x3f, 0x89, 0x82, 0xa4, 0xcd, 0x0d, 0xc4, 0x5b, 0xca, 0x6e, 0xea, 0x38, 0xcd, 0x1c, 0xa4, - 0xf7, 0x74, 0xb0, 0xd7, 0xca, 0x97, 0xb6, 0xc9, 0x0c, 0xbd, 0x1a, 0x8d, 0x43, 0x01, 0xa8, 0xfd, 0xc7, 0xdb, 0xce, - 0x93, 0x26, 0xe1, 0xcf, 0xb3, 0xdb, 0x6e, 0x41, 0x0f, 0xe1, 0x9d, 0x79, 0x28, 0x1e, 0x78, 0x5f, 0x4f, 0x37, 0x01, - 0x45, 0x87, 0x70, 0x0f, 0xb9, 0x89, 0x46, 0xfd, 0x44, 0x4f, 0x8d, 0xc9, 0x7e, 0xde, 0xbb, 0xc2, 0xe3, 0xcc, 0x09, - 0x00, 0x7b, 0x54, 0xc6, 0x05, 0x77, 0x94, 0x30, 0x4c, 0x6d, 0x68, 0xe3, 0xb2, 0xd3, 0x1d, 0xad, 0xe4, 0x5a, 0xa0, - 0x18, 0x04, 0xd0, 0x79, 0x3e, 0x7d, 0x3c, 0x75, 0x13, 0x61, 0x3b, 0x76, 0x30, 0x3a, 0x99, 0x3f, 0x5d, 0xa6, 0xe6, - 0x37, 0xc9, 0x75, 0x58, 0xd2, 0x4d, 0x13, 0x7a, 0xdf, 0x63, 0x73, 0x9b, 0xe7, 0x7c, 0xbc, 0xbb, 0x36, 0xde, 0x66, - 0x08, 0xd2, 0x00, 0xa0, 0xbc, 0x38, 0x20, 0x4f, 0x70, 0xdc, 0xb0, 0x1b, 0x06, 0x2c, 0x07, 0xa8, 0x91, 0x88, 0x20, - 0x0a, 0x48, 0x98, 0xfa, 0xe7, 0xc7, 0xa2, 0xb8, 0xfc, 0xc6, 0x17, 0x9d, 0x28, 0x4c, 0x48, 0x1a, 0x9a, 0xc6, 0xb3, - 0x87, 0x7d, 0x5b, 0xe7, 0x82, 0x35, 0xc6, 0x7d, 0x7e, 0xd8, 0x63, 0xdf, 0xb5, 0x56, 0x0d, 0xd6, 0x63, 0x99, 0xdb, - 0x4e, 0x51, 0xcf, 0xe1, 0xd2, 0x8f, 0xef, 0xe7, 0xc1, 0xab, 0x20, 0x92, 0x4a, 0xb1, 0xef, 0x72, 0xe4, 0x71, 0x01, - 0x86, 0x9a, 0xef, 0x38, 0xfa, 0x2b, 0xf4, 0x57, 0x20, 0x0a, 0x7c, 0x50, 0x42, 0x93, 0x2e, 0xf7, 0x2d, 0xf7, 0x24, - 0x06, 0x41, 0xe6, 0x35, 0x04, 0x79, 0xd5, 0x24, 0x7f, 0x60, 0x0f, 0x78, 0xa7, 0x2e, 0x94, 0x0a, 0x9d, 0x7a, 0xb4, - 0xe0, 0xc4, 0x62, 0x44, 0x1f, 0x38, 0xb6, 0x5b, 0x72, 0x16, 0x16, 0x79, 0x3a, 0x6e, 0xf6, 0x26, 0x91, 0x9b, 0x7b, - 0x5a, 0x58, 0x8a, 0x58, 0xbe, 0xe2, 0x4b, 0x36, 0x65, 0x12, 0x31, 0xc4, 0x66, 0x93, 0x4f, 0xf0, 0x1c, 0x53, 0x7b, - 0xbe, 0x12, 0xbd, 0x65, 0x13, 0xe1, 0x22, 0x17, 0x51, 0xfd, 0x53, 0x24, 0x1e, 0x76, 0x10, 0xd3, 0xf2, 0xfc, 0xe7, - 0xf7, 0x34, 0xab, 0xe4, 0xa9, 0x55, 0x67, 0x81, 0x11, 0xf4, 0xbd, 0x5e, 0xa8, 0x1c, 0xb4, 0xb1, 0xf4, 0xa9, 0xc9, - 0x1d, 0xe3, 0xc7, 0x17, 0xd4, 0x13, 0x03, 0x78, 0xf7, 0x37, 0x28, 0xdd, 0x0f, 0x1d, 0xf5, 0xad, 0x86, 0xa3, 0x33, - 0x01, 0x9a, 0xca, 0x41, 0x73, 0xc7, 0x09, 0x12, 0xf6, 0x79, 0x82, 0x7e, 0x21, 0xba, 0x4c, 0xd8, 0xe1, 0x73, 0xd6, - 0x34, 0x7f, 0x88, 0x9d, 0xfa, 0xf3, 0xd6, 0xcd, 0x39, 0x83, 0x8a, 0x3a, 0x9b, 0xb4, 0x1e, 0x00, 0xbd, 0xfb, 0x96, - 0x3a, 0x48, 0xbe, 0x5f, 0x3b, 0x35, 0xbb, 0xdf, 0x8f, 0xd0, 0xe7, 0xab, 0x66, 0x96, 0x03, 0x33, 0x31, 0x57, 0x48, - 0x42, 0xa7, 0x0a, 0xa9, 0xbf, 0xb8, 0xca, 0xcb, 0xb4, 0x8c, 0x4f, 0x9b, 0x0d, 0x2a, 0x77, 0xb2, 0x43, 0x25, 0x88, - 0x83, 0x37, 0x50, 0xa5, 0xfe, 0xce, 0xdb, 0xbd, 0xd4, 0xd4, 0xe6, 0xc9, 0xed, 0x2b, 0xab, 0xd5, 0x99, 0xef, 0x34, - 0x75, 0xea, 0xed, 0x9b, 0xcc, 0x2c, 0x8f, 0xf7, 0x3c, 0x70, 0xb3, 0xee, 0x1b, 0x59, 0x93, 0x98, 0xfd, 0x16, 0xd8, - 0xb8, 0x41, 0xd0, 0x11, 0xc2, 0x92, 0x66, 0x1e, 0xfb, 0x8f, 0x20, 0xa6, 0xc3, 0x45, 0xce, 0x6f, 0x35, 0xcf, 0x0c, - 0x0b, 0xf5, 0xdb, 0x23, 0x6a, 0x1d, 0xb1, 0x27, 0x10, 0xde, 0x68, 0x95, 0x3b, 0x5e, 0xa2, 0x13, 0xe0, 0xb6, 0x77, - 0xe5, 0x49, 0xa6, 0xcb, 0xe7, 0xaf, 0x26, 0x42, 0x37, 0x02, 0x32, 0xa4, 0x40, 0x95, 0xc0, 0x3e, 0xd8, 0xfc, 0x00, - 0x01, 0x4d, 0xb9, 0xd5, 0xf3, 0xbe, 0xae, 0x97, 0xc7, 0x8f, 0xef, 0xcd, 0x7e, 0x0b, 0x47, 0x5c, 0x6d, 0x15, 0xec, - 0x61, 0x2f, 0xe7, 0xd0, 0xe8, 0xcd, 0x83, 0x9f, 0x99, 0x29, 0x66, 0x21, 0xf1, 0xee, 0xa2, 0xbe, 0x61, 0x63, 0x66, - 0xcb, 0x9e, 0xc9, 0xac, 0x93, 0x47, 0xc9, 0x7a, 0xaa, 0x3c, 0x9c, 0x9c, 0xca, 0x73, 0x62, 0xca, 0x85, 0x05, 0xde, - 0xd0, 0xd5, 0xd3, 0x4b, 0xae, 0x78, 0x6b, 0x09, 0x92, 0x97, 0xf8, 0xe2, 0xe4, 0x2e, 0x40, 0x8e, 0x89, 0xda, 0xd9, - 0xb5, 0x0b, 0x52, 0xc1, 0x5e, 0x2f, 0x4b, 0x68, 0x70, 0x54, 0x8e, 0xed, 0x14, 0x3c, 0x13, 0xce, 0xc7, 0x82, 0x71, - 0x01, 0xe9, 0x2b, 0x56, 0xe5, 0xb3, 0x30, 0x8f, 0x54, 0x28, 0x02, 0x1f, 0x3c, 0x8a, 0x73, 0xd3, 0x47, 0x1c, 0x20, - 0xe0, 0x54, 0xbc, 0xef, 0x01, 0xbd, 0xbf, 0x69, 0xc8, 0xc2, 0xe4, 0x60, 0xcd, 0xef, 0x49, 0x61, 0x21, 0xca, 0x7f, - 0xbe, 0xbf, 0xb3, 0x1a, 0xa1, 0xc8, 0xe5, 0x18, 0x83, 0x28, 0x76, 0x9f, 0x43, 0x60, 0x6e, 0xaa, 0x68, 0x10, 0xa8, - 0xe5, 0x1f, 0x6d, 0x7f, 0xaa, 0x1f, 0x93, 0x12, 0xcc, 0x32, 0xc8, 0x9b, 0x31, 0x44, 0xcc, 0x70, 0x56, 0x6f, 0x99, - 0xc5, 0x02, 0x82, 0x3d, 0xe6, 0x5a, 0xb3, 0xc3, 0x1c, 0x48, 0x76, 0x55, 0x60, 0xb4, 0x25, 0x8a, 0xd4, 0x0b, 0x88, - 0x5d, 0x1a, 0xba, 0xaf, 0x0b, 0x8a, 0x74, 0x57, 0x25, 0x62, 0x2a, 0xab, 0xe5, 0xe4, 0x59, 0x8d, 0xfd, 0xad, 0xa1, - 0xea, 0xa9, 0x2f, 0xb1, 0x45, 0x63, 0xbe, 0x7b, 0xff, 0xcb, 0xc6, 0x8f, 0x84, 0x6f, 0xe7, 0x8a, 0x19, 0x0e, 0x37, - 0x87, 0xd1, 0x2e, 0x61, 0x35, 0x50, 0x63, 0xd0, 0x1c, 0x37, 0x96, 0x1b, 0x8f, 0xf8, 0x17, 0x9d, 0x12, 0x2b, 0xfb, - 0x5a, 0x5f, 0xe0, 0x73, 0xf0, 0x5e, 0xa7, 0x79, 0x41, 0x72, 0xfd, 0x0b, 0xdb, 0x23, 0x77, 0x42, 0x7a, 0xde, 0x30, - 0xcf, 0x5f, 0x55, 0x84, 0x32, 0xdb, 0x8e, 0x22, 0xaf, 0x6c, 0x00, 0xe5, 0x90, 0x6e, 0x13, 0x50, 0x5f, 0xba, 0x89, - 0xf7, 0xa1, 0x6e, 0xac, 0xf0, 0x12, 0x32, 0x6b, 0xa0, 0xb8, 0xa5, 0xb1, 0xaf, 0xce, 0x46, 0x21, 0x4d, 0xce, 0x64, - 0x8f, 0x08, 0xc5, 0x84, 0x02, 0xfd, 0xd3, 0x71, 0xd1, 0x54, 0x05, 0xad, 0xf7, 0x44, 0x54, 0xc7, 0xf2, 0xe5, 0x1a, - 0x2a, 0x99, 0xd9, 0x68, 0xa5, 0x3f, 0xc9, 0x71, 0xe3, 0x10, 0xf9, 0x2e, 0x33, 0x1d, 0x5d, 0xf8, 0x73, 0xca, 0x9d, - 0x34, 0xe0, 0xe2, 0x26, 0x3b, 0x92, 0xc0, 0xff, 0x2e, 0x73, 0x22, 0x14, 0xbe, 0x99, 0xad, 0x08, 0xe4, 0x6b, 0xd3, - 0xf2, 0xbf, 0x3a, 0xea, 0x73, 0xc2, 0x1d, 0xed, 0xca, 0xd5, 0x4c, 0xc2, 0xd9, 0x70, 0x20, 0xf3, 0xf1, 0xc6, 0x04, - 0xaf, 0x3c, 0x55, 0x65, 0xbf, 0x05, 0x5d, 0xf6, 0xc0, 0x9e, 0x4d, 0x8e, 0xa3, 0xd2, 0x51, 0xe7, 0xb5, 0x1d, 0xc5, - 0x0e, 0x43, 0xc3, 0xa2, 0x0d, 0x48, 0x10, 0xb5, 0x3a, 0xe2, 0x4f, 0x8b, 0x18, 0x09, 0x5a, 0x5f, 0x2c, 0x1e, 0xd6, - 0x03, 0x1f, 0x2d, 0x31, 0x89, 0x7d, 0xd6, 0x66, 0x49, 0xf6, 0xbd, 0x09, 0x4e, 0xca, 0x40, 0x79, 0xa1, 0x73, 0xa0, - 0x4c, 0x4c, 0xf9, 0x98, 0xe4, 0xa5, 0x16, 0x2b, 0xdc, 0x25, 0xaf, 0xa3, 0x3c, 0xa4, 0x48, 0xfe, 0x29, 0x06, 0x81, - 0xd1, 0xd1, 0x7b, 0x14, 0x79, 0xdc, 0x4c, 0x70, 0xcb, 0x7d, 0x7f, 0xc8, 0x88, 0x66, 0xa4, 0x99, 0xb5, 0x18, 0xbd, - 0x14, 0x23, 0xf3, 0x31, 0x1c, 0x8f, 0xdf, 0x33, 0x47, 0x2f, 0x28, 0x7d, 0x7e, 0x15, 0x30, 0xb9, 0x09, 0x74, 0x59, - 0x37, 0x35, 0x8e, 0xc9, 0xb3, 0x74, 0x22, 0xdf, 0xf3, 0x14, 0xa7, 0x82, 0xb6, 0x04, 0x19, 0x33, 0xbd, 0xd0, 0xcc, - 0x51, 0x60, 0x78, 0xb3, 0xd5, 0x38, 0x02, 0x06, 0xec, 0x3a, 0xea, 0xe1, 0xd7, 0x50, 0x3a, 0x64, 0x4a, 0x3f, 0xd2, - 0xc2, 0x39, 0x5f, 0xc9, 0x54, 0x6f, 0x7e, 0x2f, 0x90, 0x03, 0x71, 0xf1, 0xb9, 0x48, 0x5d, 0x4d, 0xf6, 0x97, 0x41, - 0x01, 0x32, 0xa6, 0x4a, 0xc8, 0xf4, 0x7f, 0x39, 0x4f, 0xf0, 0x76, 0x0c, 0xd6, 0x0c, 0x0e, 0x0c, 0x22, 0x3e, 0xee, - 0x62, 0x88, 0xbf, 0x0e, 0xff, 0x6d, 0x0a, 0xea, 0xca, 0x9d, 0x0f, 0x94, 0x35, 0xdf, 0x23, 0xa5, 0xc8, 0xec, 0xe5, - 0xbb, 0x57, 0xad, 0x50, 0x07, 0x35, 0xb6, 0xc5, 0x6a, 0xe6, 0xb5, 0xc5, 0xdf, 0xcf, 0xa0, 0xea, 0x4d, 0x7e, 0xb3, - 0xdb, 0x55, 0xd7, 0xa8, 0x8d, 0x1a, 0x8d, 0x9c, 0x60, 0xf4, 0x7a, 0x33, 0xec, 0xd6, 0x79, 0x7f, 0x55, 0x02, 0xaa, - 0x6c, 0xf6, 0xda, 0x77, 0x40, 0x28, 0xb4, 0xb5, 0x7e, 0x9e, 0x92, 0x55, 0xc6, 0xe5, 0x27, 0x09, 0x81, 0x46, 0x96, - 0xf0, 0xa3, 0x5c, 0x6f, 0x1e, 0xbd, 0xfa, 0xc1, 0x3f, 0xd2, 0x3c, 0x77, 0xeb, 0x43, 0xbd, 0xd2, 0x7e, 0x16, 0xb7, - 0xb9, 0xa4, 0x6e, 0x99, 0x2a, 0x82, 0x0e, 0x3d, 0xee, 0xe9, 0xca, 0x70, 0x1f, 0x10, 0x0f, 0xa7, 0xe8, 0x7f, 0x35, - 0x7f, 0x98, 0x78, 0xb8, 0x9b, 0x9b, 0x12, 0xca, 0x5c, 0xf3, 0xf7, 0xe2, 0x8b, 0x3d, 0x53, 0x44, 0xbb, 0x08, 0x3d, - 0xe7, 0xb4, 0x0e, 0x96, 0x4d, 0xd5, 0xb5, 0x86, 0x84, 0x3d, 0x82, 0x14, 0x53, 0x30, 0x6e, 0x76, 0x97, 0x84, 0x3d, - 0xe2, 0x9c, 0x41, 0x39, 0x14, 0x8a, 0x32, 0xbf, 0x15, 0x2e, 0x99, 0x96, 0xb4, 0xbd, 0xa2, 0xc0, 0x0f, 0x03, 0x3e, - 0x57, 0x64, 0x0e, 0xe4, 0xd9, 0xa3, 0x45, 0x36, 0x1f, 0xe5, 0xbe, 0x9d, 0x40, 0x2c, 0xaa, 0x76, 0x60, 0xcb, 0xcb, - 0x5e, 0x9c, 0x8d, 0x6c, 0xee, 0x49, 0x7c, 0xbd, 0xde, 0x0e, 0x0f, 0x89, 0xeb, 0xd0, 0xf6, 0x3a, 0xe5, 0xb0, 0x16, - 0xf5, 0xa4, 0xc6, 0xcd, 0xa1, 0xed, 0x86, 0xd8, 0x6c, 0xa7, 0x34, 0x7a, 0x1b, 0xc5, 0x36, 0x5b, 0x7b, 0xf1, 0xa4, - 0x73, 0x8c, 0x33, 0xe9, 0x72, 0x3f, 0xc6, 0xf9, 0x50, 0x6a, 0x88, 0xb6, 0x2d, 0xa5, 0x7b, 0xac, 0x1d, 0xb8, 0x81, - 0xad, 0xd9, 0xfb, 0x27, 0xa2, 0xb5, 0x89, 0x3a, 0x97, 0x34, 0x73, 0x55, 0x3f, 0x1d, 0x1e, 0xa7, 0x3e, 0x8e, 0x27, - 0x33, 0xaa, 0x45, 0xa9, 0x33, 0xd1, 0xe6, 0x00, 0xd8, 0x7b, 0x53, 0xaf, 0xbd, 0x2f, 0x98, 0xb3, 0x85, 0xbe, 0x5b, - 0xef, 0x16, 0x18, 0x8b, 0xf1, 0x19, 0x43, 0xdb, 0x9c, 0x5b, 0x06, 0x6e, 0x3e, 0xcb, 0x61, 0xca, 0x65, 0xeb, 0x69, - 0xd6, 0x88, 0x51, 0xf7, 0xff, 0xed, 0x99, 0x96, 0x32, 0xd2, 0xcb, 0x13, 0x32, 0xec, 0x14, 0x1e, 0x8e, 0xc9, 0x02, - 0x8a, 0x51, 0x5b, 0xe9, 0x79, 0xe5, 0x98, 0x44, 0xa5, 0xa3, 0x38, 0xd3, 0x7f, 0xf8, 0xca, 0xdf, 0xd5, 0x1d, 0xa4, - 0xe9, 0xc7, 0x96, 0x25, 0x7f, 0xc3, 0xd9, 0x10, 0x1d, 0x9e, 0x11, 0x99, 0xfc, 0x3f, 0x48, 0x4d, 0x8e, 0x14, 0xe2, - 0xd1, 0x01, 0x34, 0xd0, 0xa9, 0x93, 0x16, 0xb4, 0x1c, 0x9c, 0x80, 0xc8, 0x12, 0xcd, 0xe1, 0x05, 0xc0, 0x26, 0x6d, - 0x60, 0x42, 0x7e, 0xab, 0xf7, 0x5d, 0x5a, 0x03, 0xfc, 0x65, 0x1e, 0xf5, 0x28, 0x7e, 0x06, 0xb4, 0x68, 0x02, 0x51, - 0x91, 0xa4, 0x61, 0xad, 0x6d, 0xf7, 0xf6, 0x62, 0xbb, 0x8f, 0x0b, 0xc3, 0xfd, 0x01, 0x0f, 0x91, 0x10, 0x72, 0x3b, - 0x4a, 0x51, 0xd3, 0x39, 0x5f, 0xb5, 0x7a, 0x73, 0x08, 0x75, 0x36, 0x43, 0x2e, 0x32, 0x50, 0x4c, 0x8b, 0xf5, 0xbe, - 0xf2, 0x01, 0xff, 0xf8, 0xcb, 0x42, 0x57, 0x29, 0x9a, 0x35, 0x65, 0x8c, 0x01, 0xb8, 0x8d, 0x39, 0xdf, 0xef, 0xf4, - 0x34, 0xa6, 0x58, 0x38, 0x80, 0x87, 0xc3, 0x44, 0x31, 0x59, 0x78, 0x7f, 0xc1, 0x82, 0x20, 0x5e, 0xdf, 0x51, 0x80, - 0x48, 0x0f, 0xea, 0x93, 0x01, 0x21, 0x0b, 0x11, 0x04, 0x6b, 0x18, 0x25, 0xdd, 0xea, 0x9a, 0x75, 0x99, 0xf1, 0x27, - 0x3f, 0xa4, 0xae, 0x06, 0xfa, 0x27, 0x8d, 0x92, 0xce, 0x75, 0x15, 0x4a, 0x1f, 0xc4, 0xcb, 0x1c, 0x29, 0xcf, 0xfb, - 0x34, 0x79, 0x7a, 0xfe, 0xf4, 0xef, 0x9b, 0x99, 0x43, 0x79, 0x4c, 0x4e, 0xfe, 0xbe, 0x09, 0x77, 0x6f, 0x45, 0x5e, - 0x31, 0x35, 0x5f, 0xcd, 0x26, 0x2b, 0x0f, 0x19, 0xe7, 0x94, 0x48, 0x05, 0xa7, 0x56, 0x74, 0x7e, 0x21, 0x17, 0xdb, - 0xc6, 0xef, 0x04, 0x32, 0x67, 0x8f, 0xf4, 0x9e, 0x1d, 0xd4, 0x84, 0x96, 0x50, 0x60, 0xb3, 0x88, 0x1a, 0xf8, 0x4e, - 0x61, 0x33, 0x66, 0xf6, 0x9c, 0x14, 0x68, 0xb1, 0x0a, 0x6c, 0xc5, 0xf3, 0x98, 0x0c, 0xf1, 0xaa, 0x64, 0xae, 0x38, - 0xe1, 0xcf, 0x96, 0x99, 0x62, 0x3f, 0xa4, 0x52, 0x07, 0x77, 0x5e, 0xac, 0xdc, 0xb3, 0x5c, 0xbe, 0x7a, 0xfb, 0x49, - 0x39, 0xc4, 0xde, 0x23, 0x62, 0xc6, 0xeb, 0x67, 0x4b, 0x0e, 0xa9, 0x00, 0x25, 0x32, 0xb2, 0x61, 0xdc, 0x45, 0x42, - 0x8d, 0xb2, 0x71, 0x74, 0x05, 0x2a, 0x8e, 0x75, 0x2a, 0x02, 0x00, 0xfe, 0xd8, 0x3d, 0x15, 0x2e, 0xf0, 0xe0, 0x7a, - 0x21, 0x01, 0x65, 0xe4, 0xe9, 0x3b, 0x93, 0x29, 0x21, 0x3a, 0x6a, 0x79, 0xfc, 0x9d, 0x30, 0x56, 0xcf, 0x3d, 0x7b, - 0x7e, 0x94, 0x6a, 0x69, 0x23, 0x0c, 0x24, 0x96, 0x65, 0xd3, 0x59, 0xd8, 0xba, 0xad, 0xf0, 0xa8, 0x58, 0x81, 0x34, - 0x05, 0x68, 0xdd, 0xa4, 0x8d, 0x80, 0xb3, 0x30, 0x66, 0x5f, 0x06, 0x68, 0xa9, 0x82, 0xb1, 0xfa, 0x64, 0x66, 0xc3, - 0xd5, 0x86, 0xa0, 0xee, 0x47, 0x8f, 0xb9, 0x40, 0xc8, 0x8b, 0x05, 0x76, 0x2c, 0x53, 0x27, 0x7e, 0x2b, 0xfa, 0xb0, - 0x7c, 0xac, 0xa5, 0x45, 0x9b, 0x1d, 0x7d, 0x52, 0x56, 0x98, 0xdf, 0xe9, 0xbd, 0xd3, 0x82, 0xd5, 0x4a, 0x51, 0x7a, - 0x16, 0x82, 0xcb, 0x6e, 0x4f, 0x9a, 0x3a, 0xac, 0x7e, 0x30, 0x28, 0x90, 0x1c, 0x0c, 0xd9, 0x76, 0xe8, 0xa9, 0x83, - 0x21, 0x28, 0x79, 0xcd, 0x14, 0x60, 0xcd, 0xd4, 0x0f, 0x29, 0x8d, 0x26, 0xff, 0xaa, 0x4f, 0xfa, 0x4f, 0xfe, 0x67, - 0x58, 0xef, 0x5a, 0x01, 0xc9, 0xf6, 0x70, 0x3e, 0x3b, 0x4b, 0x0b, 0x66, 0xd0, 0x28, 0x08, 0xed, 0xc1, 0x94, 0x9a, - 0x93, 0x48, 0x0c, 0x4a, 0x21, 0x44, 0xf6, 0x27, 0xd3, 0x5b, 0x8e, 0x79, 0x1e, 0x8a, 0x0f, 0x1f, 0xb7, 0x34, 0xe9, - 0xb4, 0x39, 0x9e, 0x23, 0xb8, 0x2b, 0x70, 0x82, 0x12, 0xcc, 0x0a, 0xfa, 0x27, 0xbf, 0x7f, 0x08, 0x45, 0x2c, 0xd7, - 0x85, 0x02, 0x65, 0xcc, 0x9e, 0x11, 0xb9, 0x5d, 0x78, 0x44, 0xab, 0x90, 0xc5, 0xb8, 0x40, 0x0e, 0x0b, 0xfb, 0xeb, - 0x31, 0x0b, 0x46, 0x0d, 0xfb, 0xa9, 0x6e, 0x44, 0xfb, 0x10, 0x98, 0x11, 0x5b, 0xd4, 0xe6, 0xa6, 0x18, 0x84, 0x33, - 0xc4, 0x4d, 0x56, 0x5a, 0x17, 0xb4, 0xf4, 0x94, 0xbc, 0xa4, 0x40, 0x37, 0xf1, 0xa8, 0xc3, 0xa9, 0x53, 0xab, 0xe5, - 0xad, 0x0a, 0x5a, 0x0b, 0xce, 0x79, 0xbd, 0x7f, 0x86, 0xff, 0xcc, 0x61, 0x85, 0x38, 0xa9, 0x1e, 0x78, 0x66, 0xf3, - 0xe4, 0xe6, 0x9d, 0x8b, 0x87, 0x67, 0x13, 0xae, 0x79, 0x6a, 0xf5, 0xd5, 0x84, 0xff, 0x3d, 0x7d, 0xf2, 0x74, 0x92, - 0x9a, 0xa0, 0xfc, 0x30, 0xb8, 0xf2, 0xc4, 0x6b, 0x78, 0xef, 0xde, 0xe9, 0xf0, 0xeb, 0xa5, 0xcf, 0xd1, 0x7d, 0x26, - 0xdc, 0xb6, 0x70, 0x7b, 0x35, 0xb0, 0x5a, 0xd4, 0xa8, 0x4a, 0x30, 0x3e, 0xe3, 0xd6, 0xe3, 0xcf, 0x93, 0xc6, 0x04, - 0x39, 0x3a, 0xe7, 0x20, 0x19, 0x10, 0x12, 0xcc, 0x02, 0x9b, 0xf4, 0x78, 0x87, 0x65, 0x5a, 0x20, 0x25, 0x08, 0x21, - 0x69, 0xe8, 0x7e, 0x0c, 0x5d, 0x25, 0xb6, 0xb2, 0x88, 0x8c, 0x6a, 0xd8, 0xa1, 0x11, 0xa7, 0xda, 0x7d, 0x98, 0x62, - 0x1d, 0xf0, 0xa9, 0x66, 0x90, 0x20, 0x4a, 0x22, 0xef, 0xb9, 0xb8, 0xb8, 0x75, 0xd0, 0x8a, 0x4c, 0xb5, 0x9e, 0x7e, - 0x17, 0x0d, 0xb7, 0xfe, 0x7a, 0x7b, 0x9f, 0x59, 0x97, 0xd0, 0xd0, 0x8b, 0xb9, 0xf2, 0xeb, 0x22, 0x8e, 0x5a, 0x3c, - 0x25, 0x6a, 0xf1, 0x54, 0xc4, 0xbc, 0x18, 0x35, 0xf2, 0xca, 0x62, 0x84, 0x74, 0x2b, 0xd0, 0xad, 0x46, 0x4f, 0x92, - 0x65, 0x89, 0x70, 0xdf, 0x8a, 0x41, 0xfb, 0xac, 0x84, 0xf6, 0xd7, 0xea, 0x49, 0x25, 0xb8, 0x0e, 0x34, 0x7a, 0x0e, - 0x85, 0x97, 0x41, 0x9b, 0xb1, 0x53, 0x03, 0x77, 0x45, 0x16, 0xdf, 0xfa, 0x43, 0x4b, 0xd2, 0x86, 0x75, 0x1a, 0x50, - 0xcf, 0x34, 0xf8, 0x61, 0x2a, 0xc4, 0x63, 0xf9, 0x27, 0x9e, 0xbe, 0x78, 0x25, 0xd1, 0x74, 0xfd, 0x40, 0xf1, 0xa2, - 0xb8, 0x50, 0x41, 0xd5, 0xec, 0x01, 0x05, 0x9b, 0xee, 0xe4, 0x6a, 0x99, 0xeb, 0x84, 0x39, 0xe4, 0xe9, 0xae, 0xfa, - 0x83, 0x16, 0x9c, 0xbe, 0x7a, 0xcf, 0x37, 0xa0, 0xd3, 0xc2, 0x0a, 0x50, 0xe2, 0xfc, 0x16, 0xb5, 0x19, 0x07, 0x67, - 0x36, 0x4b, 0xf8, 0x5f, 0xaf, 0x36, 0x40, 0xed, 0xc1, 0xc3, 0x41, 0x4d, 0xa0, 0x82, 0xfc, 0xc2, 0x39, 0x4d, 0x69, - 0x18, 0x40, 0xc1, 0x45, 0xc6, 0xa1, 0x58, 0xce, 0x16, 0x8f, 0xbc, 0xd2, 0x8a, 0x5c, 0xc0, 0xba, 0xd3, 0xa7, 0xd1, - 0x41, 0x30, 0x9e, 0x62, 0xa5, 0x21, 0x6a, 0x31, 0xd4, 0x45, 0x5a, 0x69, 0xa4, 0xf8, 0x2b, 0x4b, 0xd4, 0xb5, 0xcc, - 0xa6, 0x73, 0x8f, 0xab, 0x86, 0xea, 0x4c, 0xbb, 0x20, 0xc0, 0x8a, 0x12, 0xb9, 0xb5, 0x8b, 0xae, 0xf6, 0xdb, 0xdf, - 0x76, 0x18, 0x7a, 0x73, 0xcd, 0x5f, 0xe6, 0xf9, 0xe1, 0xe3, 0x91, 0x96, 0x1e, 0x07, 0xe2, 0xa2, 0xe9, 0x44, 0x3f, - 0xc6, 0x16, 0xe1, 0xd9, 0xb8, 0x8b, 0xc8, 0x30, 0x1a, 0x94, 0xf4, 0x6d, 0x4d, 0x3c, 0x66, 0xd2, 0x0e, 0xa0, 0x9f, - 0x0b, 0xda, 0x1c, 0x00, 0x96, 0x22, 0x94, 0x5d, 0x04, 0x57, 0xa1, 0x7a, 0x6f, 0xd4, 0x95, 0x36, 0x36, 0xfb, 0x07, - 0x6a, 0x44, 0x60, 0x56, 0x3c, 0xc6, 0x28, 0x85, 0x9e, 0x40, 0x5e, 0xec, 0x52, 0xb5, 0x56, 0xa7, 0x65, 0x0b, 0xf1, - 0x5c, 0x7a, 0x36, 0x13, 0x40, 0xd4, 0xa4, 0x4f, 0x4c, 0x1a, 0xd8, 0x50, 0xa1, 0x4c, 0xf9, 0x90, 0xd4, 0x4a, 0xc0, - 0x35, 0x1f, 0x76, 0xd1, 0x3c, 0x01, 0x67, 0x07, 0xb6, 0x05, 0x71, 0x58, 0x35, 0x43, 0xae, 0xab, 0x73, 0xda, 0x2e, - 0xfa, 0xb4, 0xd5, 0x1a, 0xdb, 0xaf, 0x9f, 0xce, 0x94, 0xf7, 0xf3, 0x31, 0x61, 0x46, 0x40, 0x6a, 0x67, 0xfa, 0xef, - 0x89, 0x72, 0xfa, 0xfd, 0xc4, 0x55, 0xfa, 0xbf, 0x79, 0x2e, 0xc6, 0x92, 0x79, 0x7e, 0x18, 0xb9, 0xc3, 0x98, 0x0a, - 0x61, 0x8c, 0x93, 0xf0, 0x62, 0x3b, 0xbc, 0x68, 0x0c, 0xea, 0x6c, 0x72, 0x30, 0xe4, 0x4c, 0xc7, 0xde, 0x7b, 0x10, - 0x34, 0xfb, 0xa2, 0xb7, 0x68, 0xac, 0x51, 0xd2, 0xa2, 0x98, 0xf7, 0x01, 0x64, 0x58, 0x65, 0xfb, 0xff, 0x71, 0xf3, - 0x26, 0x89, 0xd5, 0x0a, 0xf2, 0x12, 0x97, 0x34, 0x0e, 0x2b, 0x1f, 0x25, 0x61, 0x7d, 0xda, 0xa8, 0x2c, 0xd1, 0x5c, - 0x3b, 0xfb, 0x6f, 0xb0, 0x6c, 0xd9, 0xb0, 0x4b, 0x79, 0xb8, 0x77, 0x60, 0x4c, 0xe3, 0x9b, 0x1b, 0x6f, 0xd2, 0xc6, - 0x96, 0xd6, 0x6e, 0xc6, 0xdb, 0xa5, 0x09, 0x93, 0x1d, 0xc7, 0xac, 0xd8, 0x2e, 0x32, 0x43, 0x45, 0x53, 0xd5, 0x47, - 0x33, 0x38, 0xb9, 0xa1, 0x82, 0xf6, 0x6f, 0x39, 0x64, 0xb0, 0x78, 0x98, 0xcd, 0x85, 0x68, 0x79, 0x5d, 0xf0, 0x1d, - 0x05, 0xe7, 0x64, 0x24, 0x25, 0x09, 0xb2, 0xa4, 0xfb, 0x8e, 0x83, 0x07, 0x4d, 0xa1, 0x6a, 0xc4, 0xed, 0x72, 0xb2, - 0x5f, 0x0b, 0xff, 0xba, 0x7c, 0xdc, 0x70, 0xda, 0xca, 0x39, 0x50, 0x88, 0x2f, 0x38, 0x6f, 0x4e, 0x88, 0x8c, 0xda, - 0x36, 0x5b, 0x2b, 0xc2, 0x91, 0x5f, 0x29, 0x12, 0xf5, 0x2f, 0x1a, 0x95, 0x42, 0xb5, 0x04, 0x60, 0x60, 0x47, 0x81, - 0xd5, 0x6f, 0xd1, 0xa5, 0x6a, 0x19, 0xa0, 0xf1, 0x2b, 0xf6, 0x36, 0x9e, 0xd5, 0x3c, 0x05, 0xfd, 0x82, 0xa8, 0x6d, - 0xad, 0x68, 0x82, 0xf3, 0xee, 0x85, 0x35, 0x3a, 0xf1, 0x7b, 0x1a, 0xfd, 0x3d, 0xc8, 0x0d, 0xe4, 0x93, 0x74, 0xbf, - 0x4b, 0x4d, 0x1f, 0xb0, 0x07, 0x63, 0x1c, 0x63, 0xb0, 0x6b, 0xe6, 0x99, 0xea, 0x4d, 0x55, 0x4b, 0x01, 0xef, 0xe9, - 0x6a, 0xd4, 0xdc, 0xe3, 0x77, 0x9d, 0x37, 0xab, 0xec, 0x30, 0xbe, 0xce, 0x17, 0x50, 0xb6, 0x68, 0xd7, 0xe5, 0x4e, - 0x72, 0x19, 0xeb, 0x52, 0x05, 0xa1, 0x04, 0x16, 0xa4, 0xa4, 0xe6, 0x10, 0x87, 0x5b, 0xb6, 0x6e, 0xae, 0xa3, 0x09, - 0xe9, 0xd6, 0x5f, 0x66, 0x3e, 0xb7, 0x83, 0xa3, 0x8a, 0x36, 0x44, 0x60, 0xb6, 0xd0, 0x86, 0x05, 0x1c, 0xae, 0xb4, - 0x79, 0x29, 0x82, 0x00, 0xbc, 0x1b, 0xf4, 0xb9, 0x66, 0xa0, 0x28, 0x18, 0x44, 0xde, 0x45, 0x0b, 0x16, 0x78, 0x0d, - 0x9e, 0x02, 0x7d, 0x12, 0x1b, 0xfe, 0x7b, 0xc2, 0xaa, 0xd8, 0x90, 0x2c, 0x61, 0x7d, 0xef, 0x91, 0x8a, 0xe4, 0x24, - 0x75, 0x91, 0x74, 0x7e, 0x0b, 0xcf, 0xd4, 0x71, 0xdd, 0x9a, 0xbf, 0x8c, 0x3e, 0xf2, 0x29, 0x5a, 0x2f, 0xa0, 0x1f, - 0xe3, 0x8a, 0x5d, 0xe6, 0x2f, 0x34, 0x9f, 0xf4, 0xcc, 0xbc, 0x46, 0xab, 0x33, 0xe0, 0x81, 0xa4, 0x13, 0x61, 0x29, - 0x5d, 0x32, 0xe7, 0x32, 0x00, 0xe4, 0x6b, 0x93, 0xdb, 0xde, 0x10, 0xe2, 0x4b, 0x76, 0x7d, 0x47, 0x10, 0x2a, 0x53, - 0xad, 0x7e, 0xf2, 0xdc, 0x23, 0x29, 0x84, 0xa5, 0x3a, 0xfd, 0x8c, 0xdb, 0xb4, 0xbd, 0x5d, 0x0d, 0xcf, 0x90, 0x49, - 0x62, 0x81, 0x29, 0xba, 0x06, 0xfd, 0x9d, 0x5d, 0x24, 0x55, 0x06, 0x21, 0x62, 0x06, 0x9f, 0x70, 0x36, 0x46, 0x5c, - 0x2a, 0x15, 0xfd, 0xd9, 0x1e, 0x48, 0x37, 0xbd, 0x4a, 0x55, 0x85, 0x2b, 0x21, 0x93, 0x89, 0x2d, 0xb5, 0x01, 0x8b, - 0x05, 0x78, 0xf0, 0xe8, 0x16, 0xb7, 0x65, 0xb9, 0x1b, 0x11, 0x9c, 0x16, 0x2d, 0x3d, 0xbd, 0x60, 0x99, 0xd0, 0x77, - 0xd2, 0xf5, 0xae, 0x29, 0xc2, 0x74, 0xbf, 0x49, 0xb7, 0x3f, 0x4a, 0xe9, 0xab, 0x4a, 0xe3, 0x0e, 0x5c, 0x63, 0x09, - 0x5c, 0x78, 0x8c, 0x48, 0x35, 0x24, 0xaa, 0x4f, 0x03, 0x90, 0x1e, 0x55, 0x4d, 0x72, 0x1c, 0xa4, 0x0e, 0x13, 0x57, - 0x46, 0x1a, 0x21, 0x2e, 0xc4, 0x6e, 0x74, 0xc8, 0x4e, 0x67, 0x21, 0x9f, 0x29, 0x37, 0x5b, 0x27, 0x89, 0x7c, 0xa8, - 0x7d, 0x28, 0x8a, 0x91, 0x0c, 0xd7, 0x30, 0xe6, 0xc7, 0x1c, 0xfd, 0x78, 0x77, 0x95, 0xaf, 0xcc, 0xd6, 0x71, 0x4e, - 0xc3, 0x7c, 0x1c, 0x2f, 0x2a, 0xff, 0x5c, 0xd6, 0x35, 0x5a, 0x78, 0x1e, 0x1b, 0x3f, 0x9c, 0x2a, 0xea, 0xd7, 0x33, - 0x0e, 0x75, 0x51, 0x1b, 0xba, 0xbc, 0x92, 0x72, 0xbd, 0x3b, 0x8b, 0xc5, 0x12, 0x36, 0xc7, 0xa4, 0x5c, 0xf2, 0x54, - 0x55, 0x4b, 0x47, 0x9f, 0x3d, 0x96, 0x6b, 0xc9, 0x3b, 0x01, 0x30, 0x15, 0xe9, 0x23, 0x2c, 0x68, 0x2f, 0x23, 0x46, - 0x88, 0xbd, 0xa4, 0x29, 0xa7, 0xec, 0xdd, 0xde, 0xba, 0xf5, 0x28, 0x64, 0x4b, 0x92, 0xdd, 0xbd, 0x19, 0xe1, 0x0b, - 0xf3, 0xe5, 0x81, 0xd3, 0x3a, 0x5c, 0x93, 0x17, 0xf7, 0x21, 0x8a, 0xbd, 0x44, 0x3a, 0x8c, 0xda, 0x52, 0xce, 0x4d, - 0x58, 0x52, 0x9a, 0x52, 0x6e, 0x1d, 0x52, 0x35, 0x6c, 0x29, 0xc6, 0x1c, 0xc9, 0x78, 0x64, 0x9e, 0x91, 0x7e, 0x46, - 0x78, 0xe3, 0x5b, 0xc7, 0x93, 0xac, 0xbb, 0x77, 0xde, 0x32, 0x2f, 0xf2, 0x2a, 0x39, 0x3f, 0x6f, 0x25, 0x36, 0x14, - 0x77, 0xf2, 0x08, 0x58, 0x4f, 0x1c, 0x64, 0x97, 0x26, 0x1f, 0x08, 0x52, 0x94, 0xac, 0x74, 0xfa, 0x9f, 0x73, 0xdd, - 0xfb, 0x37, 0x75, 0x68, 0xa2, 0xea, 0xd8, 0x76, 0x68, 0x49, 0xe6, 0xe1, 0xd7, 0x79, 0x97, 0xaa, 0x05, 0xa4, 0x80, - 0xc5, 0x22, 0x4a, 0xdd, 0x8c, 0x09, 0x93, 0xa4, 0xe3, 0x05, 0x62, 0x7e, 0xdc, 0x66, 0x26, 0xbe, 0xec, 0xfe, 0x2e, - 0x07, 0x34, 0x35, 0x84, 0xe4, 0x11, 0x14, 0xe7, 0x1f, 0xc2, 0x9b, 0x31, 0x15, 0xf1, 0x0d, 0x7d, 0xe5, 0x94, 0xda, - 0xa3, 0x17, 0x68, 0xd3, 0x93, 0x60, 0x71, 0xe1, 0x46, 0x50, 0x22, 0x13, 0x04, 0xc8, 0xee, 0x31, 0x80, 0xa5, 0x49, - 0xf6, 0xa2, 0xe9, 0x68, 0x40, 0x64, 0xb3, 0xb1, 0x25, 0xcc, 0xb1, 0xb9, 0x00, 0x5a, 0xb0, 0x33, 0xbf, 0x04, 0xca, - 0x46, 0x76, 0x78, 0x47, 0xff, 0x93, 0x37, 0xa4, 0x00, 0x63, 0x9a, 0xfa, 0xd0, 0x59, 0xaf, 0x02, 0xf7, 0xae, 0xcf, - 0xb0, 0x38, 0x20, 0x07, 0x6e, 0x18, 0x4a, 0x63, 0x67, 0xac, 0x2e, 0x69, 0x40, 0xcb, 0x45, 0x75, 0x41, 0x20, 0x24, - 0x86, 0x98, 0xd7, 0x0c, 0x85, 0x94, 0x24, 0x54, 0x4b, 0x37, 0x9d, 0xd8, 0x26, 0x28, 0xcc, 0x8e, 0xa7, 0x26, 0x0f, - 0x03, 0x8f, 0xcb, 0xb7, 0xcf, 0x4d, 0x07, 0x81, 0xc2, 0x15, 0x2f, 0x65, 0x34, 0x6c, 0xac, 0x9b, 0xf5, 0xd0, 0xaf, - 0x6f, 0x16, 0xd0, 0x6e, 0x57, 0x8e, 0x19, 0xb5, 0x4e, 0xf5, 0x4c, 0x70, 0x7a, 0x67, 0x80, 0x46, 0x44, 0x02, 0x34, - 0xf0, 0xa3, 0xfe, 0x86, 0x54, 0x2c, 0x11, 0xd6, 0x76, 0x5e, 0x99, 0xf5, 0x5d, 0xae, 0x2c, 0x74, 0x9e, 0x61, 0xe3, - 0x9c, 0x45, 0xab, 0x1a, 0xf1, 0x84, 0x04, 0x03, 0x91, 0x92, 0x9d, 0x73, 0x2e, 0x32, 0xbe, 0x4e, 0x69, 0xf0, 0x05, - 0xa7, 0xc7, 0x5f, 0xeb, 0x02, 0xe5, 0xf8, 0x97, 0x57, 0x6f, 0xf3, 0x06, 0xd8, 0xe2, 0x7a, 0xc4, 0x7c, 0x51, 0xe6, - 0xe5, 0x0f, 0xcf, 0x99, 0x39, 0xfd, 0x7b, 0xeb, 0x99, 0x80, 0x2a, 0x7f, 0xb6, 0x42, 0x02, 0xa9, 0x3c, 0xba, 0xf3, - 0x46, 0xb8, 0x4a, 0x3a, 0x8a, 0xc6, 0xac, 0x1d, 0xb7, 0x84, 0x1d, 0xac, 0x8a, 0x23, 0x08, 0x15, 0xff, 0x62, 0x06, - 0x90, 0x38, 0x0b, 0x5a, 0x3a, 0x1a, 0x54, 0xd1, 0x1e, 0xa8, 0x73, 0xc2, 0xc6, 0x7c, 0x22, 0x37, 0xe4, 0xcb, 0x9b, - 0x13, 0x1c, 0x64, 0x09, 0x49, 0xf0, 0xa8, 0xde, 0xbe, 0x45, 0xd9, 0x2e, 0x3b, 0x4c, 0xbd, 0xe9, 0xf1, 0x7b, 0x6e, - 0x01, 0x42, 0x9a, 0x3d, 0x44, 0x3e, 0x77, 0x23, 0x31, 0xbb, 0xf5, 0xcc, 0xb6, 0x23, 0x16, 0x63, 0x3b, 0x11, 0xb9, - 0x52, 0xc7, 0xb5, 0x79, 0x88, 0x8c, 0xb0, 0xc2, 0x58, 0x83, 0xcb, 0xaf, 0x15, 0x96, 0x56, 0x11, 0x34, 0xf6, 0x31, - 0x5d, 0x29, 0x87, 0x4d, 0xf6, 0x21, 0xfd, 0xa5, 0xac, 0xf5, 0xaf, 0xd0, 0xea, 0xec, 0x09, 0xfc, 0x8a, 0x91, 0xbd, - 0x87, 0x30, 0x58, 0x77, 0x2c, 0xbb, 0x16, 0x3c, 0x56, 0x41, 0xb9, 0x0f, 0x13, 0x09, 0xa1, 0x78, 0x78, 0x3f, 0xec, - 0xf2, 0x5d, 0x4b, 0x34, 0xc4, 0x21, 0x8b, 0x65, 0xa5, 0x36, 0x19, 0xc3, 0x95, 0x8c, 0x80, 0xcb, 0x73, 0x3d, 0x9e, - 0x5f, 0xed, 0xec, 0xae, 0x34, 0x92, 0xd0, 0x77, 0x03, 0xc7, 0xcb, 0xad, 0x63, 0xad, 0x2c, 0xda, 0x7a, 0x18, 0xe2, - 0x56, 0x17, 0x88, 0xcc, 0x08, 0x11, 0x73, 0xdb, 0x56, 0x0d, 0x89, 0xb3, 0x93, 0xae, 0xd0, 0xc7, 0x06, 0x86, 0x33, - 0xd8, 0x98, 0xaa, 0x3e, 0x77, 0x1f, 0x06, 0xb6, 0xff, 0x17, 0x54, 0x03, 0x3f, 0x5f, 0xae, 0x48, 0x08, 0x48, 0x58, - 0xe8, 0x59, 0x04, 0xb3, 0x1e, 0xae, 0xf2, 0xec, 0x25, 0x1a, 0x2e, 0x64, 0x68, 0x70, 0xfc, 0xf1, 0xdc, 0xf4, 0x82, - 0xe6, 0xf8, 0xfd, 0xec, 0xdc, 0x8c, 0xaf, 0x95, 0x34, 0xc9, 0x82, 0x53, 0x5e, 0x38, 0x5d, 0xbe, 0xe7, 0x8c, 0xe2, - 0x33, 0xed, 0xba, 0xef, 0x68, 0xf3, 0x99, 0x94, 0x75, 0x52, 0xe9, 0x26, 0x02, 0x95, 0x85, 0x4c, 0xde, 0xed, 0x05, - 0xe0, 0x6a, 0x23, 0xf4, 0x45, 0x73, 0x91, 0x99, 0x4a, 0x5f, 0x74, 0xb3, 0x3c, 0x44, 0xca, 0xf6, 0xf0, 0xe6, 0xb4, - 0x0c, 0x01, 0xaf, 0x4f, 0x6b, 0xf6, 0x6f, 0xec, 0x2c, 0x94, 0xae, 0xa3, 0xc6, 0xa8, 0x88, 0x9b, 0x0b, 0xa6, 0x2f, - 0x51, 0x31, 0x0d, 0x0e, 0xc2, 0x49, 0x03, 0x4e, 0x27, 0xb9, 0xd1, 0x05, 0xc9, 0x0b, 0x4c, 0x83, 0xd8, 0x13, 0x68, - 0x69, 0x03, 0x16, 0x15, 0x95, 0xfc, 0xe8, 0x32, 0x2e, 0x1e, 0xa1, 0x9d, 0x9e, 0x44, 0x45, 0xfc, 0xd1, 0x7b, 0xd2, - 0x0a, 0x7e, 0x9f, 0x83, 0xee, 0x7a, 0x4d, 0xa7, 0xf7, 0xa0, 0x18, 0xb4, 0x6d, 0xf3, 0xcf, 0x94, 0x41, 0x78, 0x38, - 0x2a, 0x74, 0xe0, 0x15, 0xe4, 0x08, 0x01, 0x5e, 0xed, 0x41, 0x9f, 0x07, 0x1e, 0xf3, 0x48, 0x71, 0x20, 0x6f, 0x1e, - 0xdb, 0x2b, 0xe9, 0x3c, 0xf1, 0x75, 0xee, 0xfb, 0xef, 0xba, 0x3a, 0x16, 0x0f, 0x6e, 0xc7, 0xde, 0xbd, 0x7f, 0x6c, - 0x2e, 0x8b, 0xcb, 0x93, 0x26, 0x1d, 0x5d, 0x97, 0xf1, 0xb6, 0x71, 0x92, 0xd3, 0xed, 0xe4, 0x5c, 0xe0, 0x1f, 0x5b, - 0x10, 0xbf, 0x2d, 0xe0, 0xb9, 0x95, 0xa4, 0xfa, 0x76, 0x76, 0xd1, 0x99, 0x9f, 0x1e, 0x2e, 0x95, 0xfb, 0xb8, 0xc9, - 0x76, 0x2c, 0xae, 0x76, 0xd0, 0x3a, 0x4f, 0xba, 0x9d, 0x5b, 0xc9, 0xad, 0xe3, 0x5a, 0xd3, 0x8f, 0xb9, 0xdd, 0xed, - 0x6e, 0x2d, 0xcc, 0xff, 0xc5, 0xd5, 0xd3, 0x71, 0x1c, 0x1b, 0xbf, 0x41, 0x41, 0x50, 0xb8, 0x83, 0x75, 0x7a, 0x99, - 0x3c, 0xe3, 0x0e, 0xd5, 0x28, 0x0d, 0x57, 0x73, 0x9a, 0x79, 0x64, 0x2e, 0x62, 0x9c, 0x6f, 0x88, 0x97, 0xd5, 0xa2, - 0xc3, 0x06, 0xfd, 0xf6, 0x99, 0x99, 0xff, 0xfc, 0x0a, 0x9c, 0xe8, 0xce, 0xee, 0x1b, 0xe8, 0xca, 0xe3, 0x9a, 0xa1, - 0x29, 0x47, 0x51, 0xb0, 0xe3, 0xba, 0x76, 0xda, 0x26, 0xe7, 0x5a, 0x38, 0xae, 0x5d, 0x0e, 0xbc, 0xda, 0xc5, 0x21, - 0x02, 0x94, 0x56, 0xc6, 0x3d, 0xa7, 0x4f, 0x3b, 0xf2, 0x67, 0xa6, 0x63, 0xd8, 0x75, 0x18, 0xc9, 0x48, 0x0c, 0x28, - 0xb1, 0xe8, 0x83, 0xba, 0x13, 0x08, 0x35, 0xb1, 0x67, 0x0d, 0x84, 0x12, 0x5c, 0xa2, 0xf5, 0x8d, 0x10, 0x80, 0x96, - 0x76, 0xe0, 0x65, 0x3d, 0x93, 0x93, 0x25, 0x6b, 0x18, 0x59, 0x9a, 0xff, 0x11, 0xd0, 0x90, 0x38, 0xdf, 0x22, 0x01, - 0x5c, 0xc4, 0xd6, 0xa3, 0xb4, 0x39, 0x7d, 0xa2, 0xf3, 0xec, 0xa3, 0x5c, 0x82, 0x34, 0x7f, 0x0e, 0x0c, 0x10, 0xb0, - 0xe1, 0x38, 0x11, 0x11, 0x4a, 0xe6, 0x17, 0x68, 0x2c, 0x36, 0x5f, 0x3f, 0x5e, 0x41, 0x6d, 0xff, 0xc6, 0x6b, 0x1b, - 0xe5, 0x7f, 0xb7, 0x54, 0x72, 0xfb, 0x6b, 0xbe, 0xfe, 0xba, 0xaf, 0xdf, 0xfe, 0x1a, 0x9a, 0x97, 0x7c, 0x37, 0x2d, - 0xf0, 0x4e, 0xd7, 0xbd, 0x82, 0x2d, 0x1e, 0x35, 0x3f, 0x5f, 0x63, 0x42, 0x9c, 0xe8, 0x41, 0xfa, 0xde, 0xf1, 0xa1, - 0xa2, 0xfb, 0xad, 0x67, 0x83, 0xcb, 0xc4, 0x7e, 0x8e, 0x5b, 0x54, 0x2f, 0x21, 0xf0, 0xd1, 0xd5, 0xb8, 0xca, 0xf4, - 0xbc, 0xd0, 0x9a, 0x67, 0xc2, 0x2e, 0x35, 0x54, 0xe2, 0x89, 0x2d, 0xe0, 0x03, 0xec, 0x75, 0xe5, 0x73, 0x71, 0xe1, - 0xd5, 0x6c, 0xc2, 0x93, 0x04, 0x03, 0x1d, 0xb8, 0x68, 0xfa, 0xea, 0x99, 0x87, 0xe2, 0x63, 0xf8, 0x73, 0xda, 0x54, - 0x13, 0xc8, 0x7a, 0x54, 0x63, 0x31, 0x62, 0x6d, 0x12, 0x46, 0xcb, 0x93, 0x61, 0x68, 0x4b, 0xc6, 0xd9, 0xac, 0xbc, - 0xa0, 0x0c, 0xd8, 0x07, 0x7c, 0xd6, 0x4b, 0xfa, 0x91, 0x4e, 0x91, 0x4f, 0xd5, 0xa7, 0xb4, 0xba, 0x79, 0x3c, 0xc1, - 0x7e, 0xe9, 0xa3, 0x86, 0x46, 0x9a, 0xc4, 0x55, 0xb8, 0x86, 0xbd, 0xc9, 0x9a, 0xa3, 0x17, 0xad, 0x45, 0x1c, 0x60, - 0x4e, 0x0b, 0xf6, 0x6f, 0x3e, 0x14, 0xcf, 0xf7, 0x93, 0x40, 0xdb, 0x45, 0xb3, 0x98, 0x51, 0x0a, 0x20, 0xca, 0xf4, - 0xe9, 0x0d, 0x38, 0x10, 0x9d, 0x33, 0x3d, 0x4b, 0xbe, 0x4d, 0x6c, 0x87, 0x73, 0x8b, 0x08, 0xb5, 0x70, 0x69, 0x8e, - 0x66, 0xb3, 0x85, 0x13, 0xb3, 0x77, 0x69, 0x2f, 0x92, 0x51, 0xa6, 0xa7, 0x3a, 0x8a, 0x49, 0xdf, 0x0f, 0x3e, 0x66, - 0x08, 0x0f, 0x12, 0x7a, 0x12, 0x16, 0xa9, 0x94, 0x9a, 0x82, 0x1d, 0xc8, 0x52, 0x68, 0x1c, 0x00, 0xd1, 0x3e, 0x8d, - 0xb8, 0x01, 0x07, 0x0f, 0xda, 0x18, 0x3a, 0x31, 0xdd, 0x93, 0x57, 0x92, 0x09, 0x82, 0xca, 0x9b, 0x25, 0x36, 0x6f, - 0xc9, 0x56, 0x54, 0xbe, 0xc1, 0xcd, 0xce, 0x9d, 0xa2, 0xec, 0x77, 0x3a, 0x2f, 0x98, 0xb2, 0xb2, 0xde, 0xa1, 0x6a, - 0x46, 0xbc, 0xae, 0xa0, 0x5c, 0xd3, 0x4d, 0x67, 0x83, 0x0e, 0x51, 0x37, 0x7e, 0xfb, 0xb7, 0x51, 0x6e, 0x1a, 0xdb, - 0x62, 0xbb, 0xe2, 0x19, 0xc1, 0x7a, 0x07, 0x67, 0x67, 0xe5, 0xb9, 0x1b, 0x91, 0x85, 0xc2, 0x3f, 0xc0, 0xc9, 0x9d, - 0x6a, 0x19, 0x1d, 0x23, 0x9a, 0xcb, 0xff, 0x5d, 0x46, 0x57, 0x95, 0xd3, 0x68, 0x0c, 0x09, 0x91, 0x0c, 0x6f, 0x02, - 0x10, 0xcf, 0xb3, 0x26, 0x63, 0x34, 0x8d, 0xd5, 0xb6, 0x73, 0x9a, 0x66, 0xdf, 0x9f, 0xe6, 0xfa, 0xfd, 0x99, 0xf0, - 0x04, 0xf9, 0x4d, 0xe7, 0x46, 0xbe, 0xfa, 0x44, 0xb1, 0xee, 0x81, 0x0e, 0xb0, 0xaa, 0x6f, 0xe4, 0x5c, 0xcd, 0x3c, - 0x88, 0x41, 0xdb, 0x0d, 0x2a, 0x1e, 0x00, 0xa0, 0x3f, 0xce, 0xcb, 0x9b, 0x7f, 0xa9, 0x9a, 0xbb, 0xe1, 0x04, 0x1b, - 0x2b, 0x97, 0xe1, 0x38, 0x5e, 0x0e, 0xfd, 0x89, 0x89, 0x9e, 0x13, 0xfa, 0x97, 0x8a, 0xa4, 0x2b, 0x74, 0x86, 0xc9, - 0xca, 0x2c, 0x0d, 0x29, 0xce, 0x50, 0x41, 0xff, 0xa5, 0xfa, 0xed, 0xba, 0xfb, 0x06, 0x52, 0xfc, 0x1b, 0xb7, 0xd5, - 0xf1, 0xdc, 0xa8, 0x32, 0x93, 0x5e, 0x9a, 0xe3, 0x96, 0x5c, 0xd5, 0xb4, 0x9a, 0xf9, 0xac, 0x5d, 0x32, 0xb5, 0x9b, - 0xc7, 0xbc, 0x32, 0xfe, 0x32, 0x4e, 0x24, 0x85, 0x6f, 0xce, 0x61, 0x80, 0x0a, 0x03, 0xed, 0x53, 0xfc, 0xf4, 0x22, - 0xd3, 0xd5, 0x9b, 0xb9, 0x51, 0xd4, 0x21, 0xd6, 0xe9, 0x07, 0x5a, 0x2f, 0xe8, 0x18, 0x76, 0xd6, 0x0a, 0xf2, 0xdc, - 0x27, 0x06, 0x2b, 0xf8, 0x89, 0x65, 0x28, 0x18, 0x35, 0x0d, 0xe8, 0xd7, 0x79, 0xb9, 0x19, 0x62, 0x13, 0x19, 0xa8, - 0x99, 0x52, 0x02, 0xb2, 0x1b, 0xd6, 0x1c, 0xeb, 0x62, 0xea, 0x41, 0x7a, 0xa2, 0x6d, 0xef, 0x3c, 0x08, 0xcd, 0xa0, - 0x2c, 0x5c, 0x3b, 0x22, 0x17, 0x85, 0xef, 0xe9, 0x7d, 0x68, 0xb8, 0xa0, 0x25, 0xb4, 0xcf, 0xdd, 0x84, 0x80, 0xe9, - 0x1e, 0x13, 0x18, 0x52, 0xba, 0x48, 0x0b, 0xe5, 0x66, 0xa1, 0x3c, 0x4f, 0x60, 0x05, 0xcb, 0xcc, 0xb3, 0xb9, 0x70, - 0xe4, 0xb0, 0xcf, 0xef, 0xdd, 0x16, 0xbb, 0xd5, 0x2a, 0xf7, 0x98, 0xb1, 0xa8, 0x78, 0x47, 0x0b, 0xfb, 0xaf, 0x46, - 0xc9, 0x91, 0x06, 0x5b, 0x35, 0xcb, 0xe4, 0x2b, 0x7c, 0xe6, 0x48, 0x6d, 0x6f, 0xe2, 0x7d, 0xc2, 0xa9, 0x40, 0xb8, - 0x23, 0x0a, 0x9d, 0xf1, 0x94, 0x59, 0x47, 0x1b, 0x70, 0xa6, 0x4e, 0x74, 0x3c, 0x3c, 0x29, 0x50, 0x0c, 0xbf, 0x35, - 0xa3, 0x01, 0xcf, 0x5d, 0x27, 0x22, 0x76, 0xaf, 0xc3, 0x10, 0x5f, 0x99, 0x65, 0xb2, 0xbf, 0xb4, 0x9a, 0xe9, 0x42, - 0x6c, 0x5b, 0x65, 0xee, 0x8a, 0x73, 0x76, 0x18, 0xce, 0x25, 0xe3, 0xb3, 0x83, 0xeb, 0xde, 0xc8, 0xbd, 0xc2, 0xe4, - 0x28, 0x76, 0x74, 0x29, 0xe0, 0x89, 0x33, 0xe4, 0xc3, 0xaa, 0xdc, 0xfd, 0xda, 0xaa, 0x57, 0xbf, 0xad, 0xec, 0x4b, - 0x14, 0xd1, 0xe7, 0x79, 0x48, 0x61, 0xc7, 0x13, 0x91, 0xad, 0x0d, 0x63, 0x5d, 0x20, 0x1e, 0x6a, 0x83, 0xf8, 0xe3, - 0x20, 0xb5, 0x1f, 0xe4, 0xbb, 0x0d, 0x2a, 0xcb, 0xef, 0x0e, 0xbf, 0x6d, 0x5f, 0x92, 0xb8, 0x97, 0x0c, 0x8a, 0xdb, - 0xea, 0xab, 0x48, 0x0c, 0xb8, 0x5f, 0xaa, 0x35, 0x5d, 0x14, 0xc7, 0x4f, 0x69, 0x98, 0xca, 0x14, 0xd5, 0x42, 0xd3, - 0xf6, 0x00, 0x5a, 0x30, 0x3a, 0x76, 0x67, 0x73, 0x67, 0xe6, 0x1f, 0x0f, 0x88, 0xc8, 0x09, 0xb5, 0xff, 0xa9, 0xbc, - 0x38, 0x9b, 0x11, 0x7d, 0xb0, 0x7f, 0xd7, 0x05, 0x6c, 0xfb, 0x7c, 0x98, 0xd4, 0x69, 0x88, 0x14, 0x7c, 0x58, 0xd3, - 0xc6, 0xff, 0xc5, 0x6b, 0x61, 0x34, 0x11, 0xbd, 0x53, 0x6f, 0x59, 0x29, 0x81, 0xed, 0x6a, 0x97, 0x52, 0xb9, 0x95, - 0xba, 0x89, 0x49, 0x59, 0xf0, 0x86, 0xba, 0x4b, 0xb2, 0x7e, 0x12, 0xb4, 0x21, 0xf7, 0x4e, 0x1b, 0x47, 0x1c, 0x62, - 0x24, 0xe5, 0xec, 0x62, 0xcc, 0xb5, 0x21, 0x74, 0xc0, 0xa3, 0xd4, 0xe4, 0xae, 0x7f, 0x26, 0x5d, 0xe9, 0x18, 0x09, - 0x0a, 0xf2, 0xbc, 0x03, 0xb6, 0x5e, 0xdd, 0xa9, 0xa6, 0xb8, 0x0e, 0x57, 0x5a, 0x97, 0xa0, 0x9e, 0x13, 0x83, 0xcf, - 0x36, 0x58, 0x54, 0xc0, 0x5b, 0xa0, 0x99, 0x8c, 0xbb, 0x86, 0x58, 0xce, 0xe6, 0xd3, 0x8f, 0x29, 0xc7, 0xfc, 0xca, - 0x8f, 0xcc, 0xe3, 0x05, 0xd1, 0x05, 0x70, 0xd1, 0x01, 0xcf, 0xe7, 0xe9, 0x4a, 0xf5, 0xf5, 0xf4, 0xaf, 0x2d, 0xf2, - 0x5f, 0xe4, 0x86, 0x6f, 0x76, 0x38, 0x0b, 0x4c, 0xaf, 0x2b, 0xec, 0x10, 0xe8, 0x0c, 0xea, 0x9c, 0xc2, 0xa4, 0x0f, - 0x01, 0x75, 0xe2, 0x1a, 0x37, 0x30, 0x59, 0x84, 0x30, 0x74, 0x49, 0x50, 0x39, 0x37, 0x1d, 0x68, 0xde, 0xfa, 0x9e, - 0x40, 0x06, 0x08, 0x0f, 0x55, 0x04, 0x2d, 0x32, 0x1e, 0xdc, 0x1b, 0x1c, 0x40, 0x58, 0xe7, 0x52, 0x4e, 0x35, 0x43, - 0xba, 0x0e, 0xd5, 0xc7, 0x2d, 0xd5, 0x2e, 0x26, 0xe4, 0x08, 0xfa, 0x52, 0xcf, 0xd0, 0xa6, 0xe9, 0x22, 0xbd, 0xc6, - 0x6e, 0xe9, 0x94, 0xaf, 0x1d, 0xc4, 0x36, 0xf4, 0x4c, 0xa2, 0xfb, 0x7c, 0x2d, 0x0f, 0x01, 0x32, 0xcd, 0x25, 0x20, - 0xd1, 0x9c, 0x82, 0xfa, 0xe1, 0x99, 0x94, 0xcb, 0x7f, 0x3f, 0x89, 0xd7, 0xb9, 0x7b, 0xff, 0xdb, 0x7f, 0x17, 0xab, - 0xea, 0xc3, 0xc2, 0xc6, 0x0f, 0xf4, 0xac, 0xc8, 0x67, 0xf5, 0xf6, 0x62, 0xd2, 0x2e, 0x69, 0xd9, 0x35, 0xec, 0x9f, - 0x19, 0x84, 0xb5, 0xd4, 0xd9, 0x44, 0xdd, 0xc8, 0x35, 0xbb, 0x0e, 0x31, 0x5e, 0xde, 0x43, 0x03, 0x2c, 0x49, 0xe3, - 0x65, 0xca, 0xea, 0x43, 0x7d, 0xea, 0x14, 0x81, 0x10, 0x75, 0xf4, 0x7a, 0x5c, 0x72, 0xe0, 0x22, 0xc7, 0x4d, 0xcf, - 0xc0, 0x3f, 0xfb, 0x47, 0xb1, 0x51, 0xe8, 0x60, 0xb5, 0x58, 0xbd, 0x3a, 0xb0, 0x71, 0xe3, 0x42, 0x0e, 0x2d, 0x6c, - 0x7d, 0xb5, 0x53, 0x26, 0x67, 0xea, 0xed, 0x3c, 0x44, 0xd1, 0x0d, 0x16, 0x4a, 0x5e, 0x19, 0x70, 0x9c, 0x7a, 0x69, - 0x78, 0x84, 0xc2, 0xac, 0xf0, 0x05, 0x9f, 0x94, 0xdb, 0x0d, 0x06, 0x53, 0x90, 0xb5, 0xdc, 0x59, 0x14, 0xe5, 0x5d, - 0xc8, 0xab, 0x88, 0xb1, 0x5c, 0x86, 0x58, 0x21, 0x94, 0x05, 0x6c, 0x47, 0xbf, 0x1f, 0x85, 0x24, 0xf7, 0xa4, 0xc4, - 0x9b, 0xce, 0x39, 0x52, 0xee, 0x12, 0xcc, 0xee, 0x2a, 0x8b, 0x93, 0x44, 0xea, 0x75, 0x1b, 0xc1, 0xa5, 0xc4, 0x0c, - 0x4d, 0x51, 0xe4, 0x26, 0x5d, 0x58, 0x70, 0x34, 0xac, 0xbd, 0x51, 0xdb, 0x48, 0x18, 0x24, 0x72, 0xcc, 0x08, 0xe9, - 0xcb, 0xbe, 0xa0, 0x7c, 0xb3, 0x4f, 0xa6, 0x8c, 0x41, 0x04, 0x34, 0x8a, 0x9e, 0x01, 0x84, 0x9e, 0xaf, 0xd1, 0x2e, - 0x89, 0xa6, 0x15, 0x8c, 0xb8, 0xaf, 0x80, 0x84, 0x8b, 0x26, 0xdd, 0xf0, 0xa7, 0x94, 0x69, 0xaa, 0x78, 0x9a, 0x00, - 0x45, 0xa3, 0xad, 0xf2, 0x6c, 0x6a, 0x3c, 0xf3, 0x34, 0xd8, 0x88, 0x7a, 0xd2, 0x64, 0x15, 0x0c, 0xd6, 0xb3, 0x91, - 0x84, 0x53, 0x6a, 0x32, 0x8a, 0x95, 0x81, 0x38, 0xfa, 0xe7, 0xb7, 0xe6, 0x35, 0xb5, 0xae, 0x16, 0x06, 0x99, 0xd1, - 0x83, 0x19, 0x1f, 0x4c, 0xd4, 0xb0, 0x39, 0x0f, 0xe3, 0x41, 0xa6, 0x4e, 0x75, 0xca, 0x28, 0x4a, 0x8c, 0xb3, 0x60, - 0x62, 0x0c, 0x39, 0xd2, 0x38, 0x60, 0xdd, 0x40, 0x9e, 0xd6, 0x9c, 0xcd, 0xa3, 0x66, 0xd2, 0xbd, 0xae, 0x8e, 0x3e, - 0xed, 0x2d, 0x5d, 0xff, 0xc5, 0xcc, 0x36, 0xec, 0xd8, 0xe4, 0x2f, 0xfd, 0xae, 0x99, 0x3e, 0xf4, 0x98, 0x37, 0xe3, - 0x60, 0x98, 0xd1, 0xf5, 0x67, 0x69, 0x71, 0xaf, 0x68, 0xd0, 0xe7, 0x4b, 0xad, 0x71, 0xb8, 0xfd, 0xfd, 0xc0, 0xda, - 0xdb, 0x5d, 0x63, 0x92, 0x34, 0x02, 0xca, 0x11, 0x12, 0x11, 0x1c, 0x5d, 0xf1, 0x1f, 0x67, 0x95, 0xff, 0xdd, 0x43, - 0x57, 0xe8, 0x41, 0xf8, 0x74, 0xdd, 0xf4, 0x69, 0x14, 0x30, 0x67, 0x2d, 0xdb, 0xd5, 0x67, 0x71, 0x35, 0xa4, 0xbf, - 0x26, 0x64, 0xdc, 0x38, 0x56, 0xff, 0xd8, 0xa6, 0xe4, 0x2f, 0x77, 0x93, 0xd8, 0x37, 0x4b, 0x7d, 0x67, 0x8b, 0x6a, - 0xfd, 0xe8, 0xd6, 0x9c, 0xb6, 0x64, 0xb4, 0x27, 0xe5, 0x5b, 0xdd, 0xe1, 0x69, 0x3b, 0xc4, 0x25, 0x9b, 0xf7, 0xe4, - 0x34, 0x65, 0x59, 0x6d, 0xcb, 0x71, 0x44, 0x7a, 0x90, 0x6f, 0x2c, 0x19, 0xa5, 0xa3, 0x8f, 0x59, 0x3f, 0xee, 0x4e, - 0x00, 0x99, 0xa7, 0x27, 0xd0, 0x54, 0xd7, 0xae, 0xec, 0xf8, 0x56, 0xdc, 0x77, 0xd6, 0xbd, 0x0f, 0xd9, 0xaf, 0x63, - 0x15, 0x01, 0x1d, 0xf7, 0xbe, 0x64, 0x76, 0xb9, 0xcd, 0x94, 0x0e, 0x9d, 0x62, 0x30, 0x9a, 0xaf, 0xb2, 0x24, 0x2a, - 0x88, 0x05, 0x6f, 0x89, 0x0f, 0xe2, 0x02, 0x00, 0x39, 0x47, 0x2d, 0x6a, 0xd9, 0x31, 0x96, 0x44, 0xf9, 0xae, 0x02, - 0x35, 0xe7, 0xd9, 0x59, 0x45, 0xa7, 0xee, 0x44, 0xaf, 0x4e, 0xb9, 0x4a, 0x73, 0x1a, 0xa1, 0xeb, 0xe1, 0x2b, 0x2f, - 0x51, 0xc9, 0x8a, 0xe6, 0x5d, 0x98, 0xbe, 0x62, 0xaf, 0xbd, 0x40, 0xc9, 0x3b, 0x52, 0x1a, 0x0a, 0x19, 0xd9, 0x1a, - 0x34, 0xb6, 0xce, 0x5d, 0x62, 0x49, 0x27, 0xcb, 0xa3, 0x84, 0xc2, 0x17, 0x73, 0x1f, 0xb7, 0xc6, 0x51, 0x4d, 0xcc, - 0x39, 0x82, 0x3d, 0xa9, 0xd2, 0xc9, 0x56, 0x39, 0x80, 0x5b, 0xd3, 0x2c, 0xc2, 0x06, 0x29, 0xb5, 0xcb, 0x71, 0x97, - 0x38, 0x93, 0xed, 0x14, 0x03, 0x83, 0xbe, 0xb6, 0xb1, 0x22, 0xd3, 0x79, 0x1c, 0x44, 0xf7, 0x13, 0x37, 0x1b, 0x24, - 0x18, 0x6c, 0xcf, 0x3a, 0xe5, 0x86, 0xe7, 0x8a, 0xa3, 0xec, 0x4a, 0x6c, 0x2d, 0xcf, 0xa6, 0xee, 0xf7, 0xe8, 0x8a, - 0xb9, 0xb2, 0xa6, 0x37, 0xa0, 0x89, 0x6a, 0xa0, 0x03, 0x3e, 0xe0, 0xc4, 0x91, 0x91, 0x33, 0x99, 0xc4, 0xaa, 0x8e, - 0x61, 0x6e, 0xd2, 0x19, 0x3c, 0xc1, 0x68, 0xde, 0x92, 0x79, 0xca, 0x29, 0x85, 0xdc, 0xfb, 0x9f, 0x1b, 0x8f, 0x50, - 0x35, 0xd7, 0x30, 0xbd, 0x15, 0xf0, 0x0e, 0x21, 0x9e, 0x7f, 0x88, 0x6e, 0xaf, 0xb4, 0xe0, 0xfd, 0x87, 0x89, 0x2c, - 0x39, 0x17, 0x2a, 0xac, 0xab, 0xdd, 0xe1, 0x3d, 0x64, 0x7a, 0x4a, 0x25, 0x18, 0x0a, 0x50, 0x61, 0xfa, 0x82, 0x7d, - 0x42, 0xe7, 0x98, 0xbb, 0xd6, 0x99, 0x10, 0x3b, 0x81, 0xdd, 0xd0, 0x09, 0x12, 0x69, 0xaa, 0x10, 0xfb, 0x82, 0xcf, - 0x95, 0x73, 0x51, 0x15, 0x7a, 0xc0, 0x2f, 0x7f, 0x13, 0x4b, 0xea, 0x37, 0x48, 0x9a, 0x6f, 0x38, 0x25, 0x84, 0x3e, - 0xf9, 0x17, 0xb1, 0xcf, 0x39, 0xdf, 0xc4, 0x4a, 0xb3, 0x9d, 0xd8, 0xfc, 0xcc, 0x3f, 0x1c, 0x39, 0x27, 0x93, 0x12, - 0x13, 0x96, 0x90, 0xb1, 0xa1, 0xf7, 0x49, 0xea, 0x26, 0x7f, 0xaa, 0xd3, 0x8f, 0xe6, 0x16, 0x7d, 0xf1, 0xdf, 0x59, - 0xe9, 0x2e, 0xa1, 0x50, 0x88, 0xa9, 0x33, 0x54, 0xc2, 0xb0, 0x87, 0xa7, 0xe1, 0xd3, 0x85, 0x39, 0x0e, 0x49, 0x22, - 0x5a, 0xe4, 0x70, 0x86, 0xf8, 0x0d, 0x80, 0x09, 0x34, 0x59, 0x89, 0x50, 0x51, 0x02, 0x7b, 0x04, 0x4f, 0xf2, 0xd9, - 0xd6, 0xf7, 0x5e, 0xe4, 0xe1, 0x44, 0x1a, 0xe5, 0x0a, 0x6e, 0x08, 0xa6, 0x7a, 0x6e, 0x23, 0x19, 0x31, 0x3c, 0x8a, - 0x56, 0xc9, 0xe7, 0x5a, 0x42, 0x59, 0xec, 0x3c, 0x08, 0xd6, 0x55, 0x76, 0x95, 0x9d, 0xc7, 0x02, 0xed, 0xe0, 0x40, - 0x13, 0x17, 0x48, 0xd2, 0x8d, 0xf1, 0x36, 0xc5, 0xac, 0xe8, 0xe1, 0xfb, 0x2a, 0xe6, 0x4d, 0x9d, 0x0b, 0x92, 0xd7, - 0xea, 0x3e, 0x65, 0xac, 0x61, 0x42, 0x9d, 0x1a, 0xd8, 0x48, 0x62, 0xd2, 0xb0, 0x84, 0xe3, 0x05, 0x9f, 0xc7, 0x60, - 0x69, 0x98, 0xe6, 0x39, 0x7b, 0xe8, 0xb5, 0x7e, 0x2b, 0xda, 0x93, 0x6f, 0x64, 0xe7, 0x4d, 0x8b, 0x72, 0x52, 0x8b, - 0x73, 0x5a, 0xac, 0x33, 0x44, 0xf4, 0x9a, 0xe5, 0x8a, 0xe7, 0xcc, 0xac, 0x03, 0x40, 0xe2, 0x49, 0x9f, 0x79, 0x7d, - 0xbc, 0x0f, 0x22, 0x51, 0xa9, 0xf4, 0x96, 0x45, 0xc8, 0xec, 0x93, 0xb2, 0x9a, 0xe1, 0xf0, 0xe4, 0xd2, 0x69, 0x09, - 0x15, 0xc3, 0xf5, 0x9b, 0xe7, 0x05, 0x54, 0x81, 0x99, 0xa1, 0x98, 0x63, 0x53, 0x39, 0x1b, 0x6f, 0xb0, 0xcc, 0x60, - 0x5c, 0x44, 0x42, 0x0d, 0xf6, 0x6e, 0x4a, 0x34, 0x0d, 0x3e, 0xcc, 0x19, 0x2b, 0x73, 0x1f, 0xf6, 0x7c, 0xe9, 0x29, - 0x66, 0x0f, 0x9f, 0xbb, 0xd7, 0xcc, 0x71, 0xfb, 0x3c, 0xa4, 0x5a, 0xee, 0x4e, 0x61, 0xcd, 0x9e, 0x51, 0x49, 0xcc, - 0x03, 0xd8, 0xe0, 0xd9, 0x95, 0x9d, 0xe9, 0x52, 0x0e, 0xd8, 0x9f, 0xe0, 0x0e, 0xe0, 0x58, 0xc1, 0x10, 0x05, 0xdc, - 0x46, 0x7e, 0xe3, 0xe6, 0xcc, 0x7c, 0xf3, 0x71, 0x60, 0xc3, 0x20, 0x32, 0x85, 0x32, 0x44, 0x4c, 0x95, 0x3e, 0xfc, - 0xbc, 0x87, 0xb3, 0xaf, 0x2e, 0x13, 0x4d, 0x65, 0x6f, 0x84, 0x62, 0x1a, 0x5e, 0xc3, 0x61, 0x1d, 0x98, 0xea, 0xe9, - 0x48, 0xa7, 0xe8, 0xd4, 0x4e, 0x62, 0x6a, 0xf5, 0xac, 0xd3, 0x51, 0xb9, 0xd9, 0x80, 0xc9, 0xa7, 0xd3, 0x2b, 0xb9, - 0x8f, 0x70, 0x68, 0x26, 0x13, 0xfe, 0xc4, 0x99, 0x79, 0x33, 0x65, 0x0f, 0xf1, 0x4b, 0x9f, 0x3e, 0x3c, 0xae, 0x07, - 0x8c, 0xf2, 0x9c, 0x01, 0xcf, 0xc7, 0xb8, 0x70, 0xc0, 0xfc, 0x6c, 0xca, 0x98, 0xfb, 0x22, 0x69, 0xa9, 0x4c, 0xcf, - 0x47, 0xeb, 0x7f, 0x56, 0xb3, 0xa4, 0x71, 0x82, 0xad, 0x51, 0x45, 0xfa, 0xa5, 0xc0, 0xdc, 0x03, 0x51, 0x0f, 0x43, - 0x9f, 0x48, 0xb1, 0x90, 0x28, 0x70, 0x74, 0x29, 0x75, 0xf8, 0xf7, 0x21, 0xe8, 0x31, 0x44, 0x4b, 0xbf, 0xb0, 0xcd, - 0xf9, 0x8e, 0xf9, 0x60, 0x6c, 0xd4, 0x76, 0xd6, 0x9d, 0x65, 0xa3, 0x95, 0x26, 0x8b, 0xfd, 0x36, 0x5b, 0xfc, 0xce, - 0x9f, 0xfb, 0x5a, 0x1e, 0x48, 0x46, 0xee, 0x64, 0x6e, 0xf6, 0xc2, 0x83, 0xcf, 0x6b, 0x5e, 0x49, 0x3f, 0x41, 0x57, - 0x82, 0x2b, 0xa1, 0xc3, 0x83, 0xd3, 0x18, 0x65, 0x0a, 0x5a, 0x41, 0x20, 0xf3, 0xc6, 0x66, 0xb7, 0x2f, 0x02, 0x69, - 0x0d, 0x21, 0x83, 0x5d, 0x5b, 0xbd, 0x44, 0x74, 0xde, 0x37, 0xc9, 0xe7, 0xec, 0x8d, 0x96, 0x75, 0x0f, 0x53, 0xea, - 0xff, 0x9c, 0xec, 0x86, 0x2c, 0xc3, 0x42, 0xa1, 0x8f, 0x9d, 0x1e, 0x47, 0x55, 0xa5, 0x51, 0x2a, 0x8e, 0x57, 0x94, - 0xeb, 0x04, 0x45, 0x85, 0x58, 0x5e, 0xff, 0x00, 0x80, 0x38, 0x4a, 0x19, 0xb4, 0xc7, 0x96, 0xaf, 0x50, 0x13, 0x04, - 0xc6, 0x45, 0x68, 0x58, 0x26, 0xa6, 0xb0, 0xcb, 0x2a, 0xd6, 0x71, 0x7a, 0x5c, 0xc4, 0x57, 0xa7, 0x10, 0xbd, 0xee, - 0x06, 0xaf, 0x12, 0x74, 0xae, 0xbd, 0xee, 0xeb, 0x39, 0xf4, 0x33, 0x9d, 0x7f, 0x04, 0x37, 0x39, 0x87, 0x25, 0x29, - 0x38, 0x25, 0xf5, 0x39, 0x8b, 0x1b, 0xbe, 0x0a, 0x0f, 0x9c, 0xb6, 0x78, 0xb4, 0x63, 0xd7, 0xac, 0xca, 0x8f, 0x5d, - 0x96, 0xd2, 0xc0, 0x90, 0x44, 0x75, 0x35, 0xe8, 0x18, 0xb4, 0x24, 0x72, 0xeb, 0x65, 0x7b, 0x8c, 0xbe, 0xc1, 0xe7, - 0xc7, 0x9b, 0xd3, 0x7d, 0x49, 0x68, 0x63, 0xb5, 0xcc, 0xca, 0xc5, 0x97, 0x28, 0x00, 0x4a, 0xf0, 0x00, 0x84, 0xf5, - 0x3b, 0x11, 0xfe, 0x5d, 0xf4, 0xe0, 0xc0, 0x23, 0x80, 0x22, 0xbc, 0x95, 0xe9, 0x2b, 0xaf, 0x09, 0xa5, 0x15, 0xe0, - 0xb8, 0x36, 0x55, 0x41, 0xde, 0x70, 0xfb, 0x47, 0x96, 0xec, 0x0b, 0x64, 0xec, 0x23, 0x21, 0xf1, 0x0e, 0xbb, 0x76, - 0xf7, 0x74, 0xc2, 0x09, 0xb0, 0x5b, 0x3a, 0xcd, 0xab, 0xb6, 0x94, 0x4d, 0x81, 0x2e, 0x06, 0x31, 0xce, 0xa0, 0xa6, - 0xd3, 0x07, 0xe9, 0xfb, 0x37, 0x66, 0xa1, 0x33, 0x04, 0xde, 0xe7, 0x02, 0xf6, 0x3a, 0x0c, 0xe5, 0xa3, 0xf6, 0x88, - 0x46, 0x90, 0xcb, 0xd5, 0xf1, 0x91, 0x81, 0x4a, 0x39, 0x6c, 0x98, 0x74, 0xfa, 0x99, 0x6a, 0xc9, 0x9e, 0xfa, 0xa6, - 0x9a, 0xa5, 0x9c, 0xc6, 0x27, 0x90, 0xea, 0xa8, 0x3c, 0xc1, 0x98, 0xab, 0x69, 0x9f, 0xde, 0xc7, 0x43, 0xad, 0x35, - 0xf0, 0x5e, 0xd7, 0x61, 0x60, 0xb8, 0xba, 0xcf, 0x9e, 0x7c, 0x8d, 0x71, 0xef, 0xf4, 0x6c, 0x8a, 0x9f, 0x0f, 0x3f, - 0x8e, 0xd0, 0x65, 0xf9, 0x71, 0x76, 0x53, 0x45, 0x78, 0x4f, 0x19, 0x35, 0xec, 0xf5, 0x33, 0x65, 0x9b, 0x45, 0xdf, - 0x27, 0x7d, 0x8a, 0x81, 0xaa, 0xbd, 0x3e, 0x5a, 0x4d, 0x28, 0x2e, 0x00, 0xe9, 0x3c, 0xa7, 0x59, 0xa9, 0x49, 0xa1, - 0xa6, 0xc9, 0x5e, 0x46, 0x56, 0x19, 0xf0, 0x0c, 0xfb, 0xd5, 0x23, 0xe8, 0x96, 0x55, 0x1a, 0xe5, 0x51, 0x87, 0xcd, - 0xfa, 0x93, 0xac, 0xfe, 0x3a, 0xc0, 0x06, 0x43, 0x8e, 0xd9, 0x93, 0x7a, 0xc9, 0x73, 0xae, 0x06, 0x9e, 0xe4, 0x8c, - 0x6b, 0x26, 0x6f, 0xed, 0x1a, 0x39, 0x1f, 0x6e, 0xc8, 0xbd, 0x7a, 0xe8, 0x9f, 0x7a, 0x59, 0x1b, 0x80, 0x2c, 0x86, - 0xd4, 0x7b, 0xce, 0xb4, 0xc9, 0x94, 0x90, 0x01, 0x99, 0x07, 0x3e, 0xaf, 0x3f, 0x07, 0x15, 0x56, 0xba, 0xf3, 0xda, - 0x5a, 0x8b, 0x42, 0xca, 0x13, 0x5e, 0x57, 0xc0, 0x12, 0x57, 0xb1, 0x32, 0x4c, 0x2b, 0x1b, 0xed, 0x9e, 0xf4, 0x97, - 0xc4, 0xfb, 0x32, 0x4b, 0x2c, 0x50, 0xba, 0xe6, 0x99, 0x8d, 0xd5, 0xbb, 0x99, 0xad, 0xf4, 0xec, 0xe4, 0xd7, 0xf1, - 0x45, 0xeb, 0xef, 0x53, 0xc7, 0xd6, 0x30, 0x86, 0xca, 0x79, 0xb3, 0xf3, 0x9b, 0x9c, 0xd2, 0x70, 0xcb, 0x68, 0x93, - 0x35, 0x33, 0x05, 0x5e, 0xae, 0xde, 0xae, 0xd1, 0x50, 0x85, 0xc8, 0xe2, 0xe0, 0x19, 0xa9, 0xfb, 0x5b, 0xdf, 0x1d, - 0x2f, 0x0d, 0x72, 0xdf, 0xc6, 0xf2, 0xa6, 0xd4, 0x12, 0xcd, 0x0b, 0xb9, 0x38, 0x6f, 0x61, 0xbe, 0xda, 0x37, 0x4d, - 0x3e, 0xd6, 0x26, 0x9c, 0x3a, 0x72, 0x9f, 0x14, 0x97, 0x91, 0xe6, 0xc2, 0x57, 0x21, 0x0e, 0xee, 0xe4, 0xc9, 0xbd, - 0xd7, 0x91, 0x52, 0x6f, 0x61, 0x8d, 0xb3, 0xf1, 0x71, 0xa7, 0x6e, 0x8d, 0x17, 0x1a, 0x34, 0xb2, 0x23, 0x83, 0x93, - 0xcf, 0x36, 0x7e, 0xd3, 0x0c, 0xe9, 0xb5, 0x87, 0x84, 0x60, 0xca, 0xfb, 0x46, 0xba, 0xc9, 0x5a, 0x09, 0xfe, 0xe9, - 0xaa, 0x46, 0xd4, 0x66, 0xe2, 0x5c, 0x9f, 0xf7, 0x43, 0x78, 0x3f, 0x74, 0x48, 0x9a, 0xcc, 0xa2, 0x44, 0x5f, 0x38, - 0x12, 0x73, 0xea, 0x29, 0x4e, 0x5a, 0x43, 0x6f, 0xe6, 0x10, 0xd6, 0x3b, 0x1f, 0xa6, 0xc5, 0xd1, 0xe1, 0x54, 0x91, - 0x66, 0x01, 0x07, 0x51, 0xa7, 0x70, 0x5d, 0x80, 0x03, 0x65, 0x5e, 0xbe, 0xa9, 0x07, 0x70, 0xf2, 0x03, 0x5c, 0x44, - 0x2f, 0xf3, 0x2d, 0x88, 0xe0, 0xdc, 0x54, 0x69, 0xa6, 0x85, 0xd9, 0x63, 0xc4, 0xde, 0xb6, 0xea, 0x9b, 0xe9, 0x67, - 0x26, 0x78, 0x29, 0x9c, 0x3c, 0x2f, 0x8f, 0xdb, 0x6c, 0x62, 0xf0, 0x21, 0x5a, 0xf5, 0x45, 0x91, 0xd3, 0xb8, 0xce, - 0x60, 0x9a, 0x9a, 0x9e, 0xf9, 0x20, 0xf2, 0x56, 0x00, 0x93, 0xd3, 0xb8, 0xaa, 0xe0, 0xdb, 0x7c, 0x31, 0xe7, 0xac, - 0x72, 0x12, 0x5f, 0x88, 0x31, 0x15, 0x49, 0xc5, 0x56, 0x45, 0x2a, 0x76, 0x24, 0x2e, 0x4a, 0x66, 0x37, 0x35, 0xc5, - 0x69, 0x6b, 0xde, 0x90, 0x94, 0xef, 0x59, 0x1b, 0x64, 0xa3, 0x42, 0x1c, 0x6f, 0x1f, 0xc2, 0xc5, 0xde, 0x92, 0xf4, - 0x29, 0x2c, 0x54, 0x75, 0x23, 0x09, 0x27, 0xa7, 0x06, 0x91, 0x5f, 0x2d, 0xf8, 0x63, 0x5f, 0xd2, 0x6a, 0x86, 0x6a, - 0x68, 0xec, 0x23, 0x5b, 0x9c, 0x8e, 0x32, 0xde, 0x24, 0xad, 0x85, 0x2f, 0xb1, 0x29, 0x16, 0x93, 0xab, 0xef, 0x74, - 0x1a, 0x5c, 0xb7, 0xf0, 0x7b, 0x38, 0x24, 0x4e, 0x2f, 0x8a, 0x94, 0x7e, 0x72, 0xf5, 0x9d, 0xb8, 0xf9, 0xa6, 0xdf, - 0x95, 0xc0, 0xdc, 0x1d, 0x5a, 0x69, 0xb1, 0x47, 0xda, 0x8a, 0x9f, 0xad, 0x4b, 0xc4, 0x57, 0xee, 0x1a, 0xcb, 0x6a, - 0xde, 0x7a, 0xfb, 0x04, 0xa5, 0x06, 0x41, 0xfe, 0x5b, 0xbb, 0xb1, 0x55, 0xc8, 0xa5, 0xd2, 0x41, 0xee, 0x21, 0xe9, - 0xa5, 0xc2, 0x6f, 0xa8, 0x73, 0x4f, 0x4f, 0x68, 0xa3, 0x12, 0xf1, 0x2e, 0x2e, 0x71, 0x86, 0x05, 0x3d, 0xce, 0xcd, - 0xc3, 0x7a, 0x0b, 0xbd, 0x62, 0xb7, 0x31, 0xe9, 0x69, 0x11, 0xcb, 0xf2, 0xb4, 0x53, 0xf7, 0x45, 0x09, 0x24, 0xfe, - 0x39, 0xdc, 0x81, 0xff, 0x4f, 0xd7, 0xa0, 0x35, 0x82, 0xca, 0xe5, 0xa6, 0x5e, 0x97, 0xf8, 0x90, 0xee, 0x78, 0xac, - 0xa2, 0xdb, 0x26, 0x1a, 0xdf, 0x70, 0x50, 0xc0, 0xd4, 0x5d, 0x65, 0xd4, 0xb1, 0x32, 0x67, 0x46, 0xb3, 0x59, 0x91, - 0xfd, 0x2b, 0x42, 0x5e, 0x15, 0x40, 0x08, 0xd2, 0x9a, 0x45, 0x13, 0x93, 0xfe, 0xdd, 0x74, 0x6e, 0x29, 0xc9, 0xac, - 0xc9, 0x9f, 0x36, 0xd5, 0xa9, 0x5b, 0xc0, 0xdd, 0xce, 0x21, 0xba, 0xd8, 0x6e, 0xad, 0x91, 0x67, 0xd0, 0xdb, 0x82, - 0xa3, 0x90, 0x35, 0x20, 0x9d, 0x38, 0x97, 0x4e, 0xfe, 0x16, 0x79, 0x0a, 0x70, 0x10, 0x05, 0x4d, 0x98, 0xca, 0x6e, - 0xb6, 0x85, 0x64, 0xe9, 0xea, 0x26, 0x82, 0x0f, 0x50, 0x09, 0x13, 0xa0, 0x8b, 0x3c, 0xaf, 0xbb, 0x77, 0xd2, 0x46, - 0x34, 0x46, 0x56, 0x67, 0xad, 0x0e, 0x92, 0x5c, 0x7f, 0xc8, 0xf2, 0xf7, 0x0f, 0x5c, 0x62, 0x7e, 0x41, 0x7c, 0x40, - 0x01, 0x1f, 0x3e, 0xf8, 0x16, 0xee, 0x38, 0xd4, 0xda, 0xed, 0xe6, 0x25, 0x0a, 0x9e, 0x84, 0xe6, 0xcf, 0x55, 0xef, - 0x74, 0x8f, 0x85, 0x48, 0xbc, 0xa7, 0x6e, 0x48, 0xd4, 0x4a, 0xb5, 0xe9, 0x7a, 0xba, 0x46, 0xf6, 0x5f, 0x0e, 0x7c, - 0x2e, 0x85, 0x4f, 0x1e, 0xd3, 0x8b, 0xdb, 0x88, 0x43, 0xa1, 0xd0, 0x57, 0xc6, 0x3f, 0x81, 0x51, 0x59, 0xfb, 0xc0, - 0x4d, 0x8a, 0x35, 0xe0, 0x32, 0x34, 0xc1, 0xad, 0xb8, 0x65, 0xac, 0x2a, 0x0f, 0x06, 0x3d, 0x85, 0x25, 0x48, 0x73, - 0xa1, 0xee, 0x99, 0x0c, 0x27, 0x41, 0x5a, 0x7d, 0x3e, 0x04, 0x41, 0xce, 0xf1, 0x4e, 0x6a, 0x55, 0xa4, 0xd2, 0xec, - 0xb1, 0x2a, 0x6b, 0x63, 0x9e, 0xc3, 0x30, 0x3a, 0x07, 0x14, 0xb5, 0xa9, 0xb0, 0xd5, 0xce, 0x10, 0x4a, 0x75, 0x1c, - 0x04, 0x36, 0x2d, 0x8d, 0x26, 0x69, 0x61, 0x07, 0x7a, 0x26, 0x61, 0xe6, 0x25, 0xcd, 0x4f, 0xa9, 0xc8, 0x57, 0xd3, - 0x46, 0x50, 0x4d, 0xdf, 0x0e, 0x24, 0x52, 0x1e, 0xab, 0xc9, 0xeb, 0x62, 0x66, 0xc7, 0x3a, 0xbc, 0x06, 0x0c, 0xe3, - 0x39, 0xc4, 0x12, 0x50, 0x24, 0x7c, 0xf5, 0xa9, 0x6e, 0x1c, 0x33, 0xe5, 0x3c, 0x17, 0xfe, 0xe4, 0xce, 0x64, 0x62, - 0xc1, 0x2b, 0x20, 0x94, 0xb8, 0xaa, 0xfb, 0x7a, 0x84, 0x6b, 0xd0, 0x4d, 0xd4, 0x0c, 0xf9, 0xe6, 0xf0, 0xd7, 0x48, - 0x11, 0x1a, 0x81, 0xac, 0x61, 0x86, 0x48, 0xa6, 0xf8, 0x08, 0x13, 0xe4, 0x1c, 0x30, 0xa6, 0xae, 0x36, 0xc0, 0xa5, - 0x3f, 0x4b, 0x64, 0x98, 0xb3, 0x69, 0x35, 0xd5, 0x07, 0xa3, 0xd0, 0x7d, 0x8f, 0x07, 0x0d, 0xea, 0xb1, 0x83, 0xd8, - 0x95, 0x82, 0xab, 0x7e, 0x8d, 0x8d, 0x06, 0x23, 0x90, 0xb3, 0x63, 0x2d, 0x36, 0x1b, 0x12, 0x04, 0x30, 0x9f, 0x28, - 0xdd, 0xfb, 0xe0, 0x79, 0x4f, 0xbf, 0x7c, 0x7a, 0x8d, 0x10, 0x32, 0x8c, 0x3b, 0x51, 0x6a, 0x66, 0x18, 0x6a, 0x94, - 0xf9, 0x04, 0xcd, 0xfc, 0x78, 0xe0, 0xe9, 0x0e, 0x6f, 0x17, 0xf4, 0x4a, 0xeb, 0xb7, 0xee, 0x91, 0xbc, 0x5c, 0x11, - 0x45, 0x68, 0x8d, 0xb6, 0x53, 0xf9, 0x70, 0xe7, 0xe2, 0x7a, 0x65, 0xbb, 0x7e, 0xa0, 0x0e, 0xad, 0x76, 0x07, 0x5f, - 0xd5, 0x9e, 0xf1, 0xa1, 0x4b, 0x72, 0x5e, 0x83, 0x65, 0xe0, 0xa1, 0xa5, 0x52, 0x34, 0xc7, 0x9b, 0xac, 0x67, 0x53, - 0x79, 0x30, 0x9a, 0x8d, 0x65, 0xb4, 0xfc, 0xc3, 0x8d, 0xe7, 0x7d, 0xa1, 0xd6, 0x30, 0x7b, 0x18, 0xc8, 0xee, 0x13, - 0x28, 0x99, 0xa3, 0xd0, 0x9d, 0xcd, 0x50, 0x45, 0x6d, 0x9e, 0x80, 0x62, 0x05, 0xbf, 0x78, 0xcb, 0x62, 0x3a, 0x67, - 0x8e, 0xf3, 0x35, 0xac, 0x7b, 0x1c, 0x35, 0x51, 0xd5, 0x91, 0x08, 0xc2, 0xab, 0xc5, 0x3d, 0xd1, 0x4b, 0x92, 0x8e, - 0x3a, 0x56, 0xe3, 0x3f, 0x73, 0x58, 0x4f, 0xed, 0xee, 0x68, 0xcb, 0x3e, 0xd7, 0x53, 0xba, 0x16, 0x50, 0x93, 0xe3, - 0x8e, 0x97, 0x50, 0x00, 0x7f, 0x4f, 0x35, 0x95, 0x88, 0x97, 0x69, 0x73, 0xb3, 0xe6, 0x60, 0x0c, 0x28, 0x23, 0x80, - 0x6a, 0x46, 0x23, 0xa3, 0x6f, 0xfc, 0x60, 0x62, 0xb8, 0xa3, 0x63, 0x4e, 0x74, 0xd0, 0x66, 0xf6, 0x37, 0x30, 0x23, - 0xd9, 0x0e, 0xa7, 0xee, 0x06, 0x35, 0x28, 0x9e, 0x04, 0x06, 0x11, 0x8d, 0xd5, 0x6c, 0x24, 0xf1, 0xdb, 0x6c, 0xbe, - 0x1e, 0xbc, 0x75, 0x00, 0x7e, 0xe1, 0x84, 0x59, 0x67, 0xb6, 0xea, 0x7b, 0x09, 0x10, 0xf0, 0xa3, 0xd4, 0x18, 0xf4, - 0xee, 0x84, 0xea, 0xc5, 0x0e, 0xa7, 0xac, 0xea, 0xc9, 0x39, 0x31, 0xf6, 0x4c, 0x3d, 0x00, 0xa4, 0x30, 0x45, 0x9d, - 0x8a, 0x93, 0x4f, 0xfe, 0xd4, 0x75, 0xc4, 0x63, 0x25, 0x2e, 0x33, 0x1c, 0x82, 0x0b, 0xa4, 0xd8, 0x8a, 0xd9, 0xba, - 0x08, 0xe4, 0x67, 0x32, 0x20, 0x19, 0x13, 0x5c, 0x03, 0xf4, 0xfe, 0x39, 0x91, 0x10, 0xa6, 0x0d, 0xa1, 0x58, 0x9a, - 0xba, 0xd4, 0x78, 0xa5, 0xd5, 0xc4, 0xd1, 0xa6, 0x4b, 0xca, 0x07, 0xd0, 0x05, 0x85, 0x7c, 0x56, 0x14, 0xfc, 0x78, - 0x86, 0x73, 0xaf, 0x11, 0xc5, 0x9e, 0xc1, 0xd1, 0x87, 0x0a, 0x48, 0x66, 0xa4, 0x10, 0x2d, 0xed, 0xc9, 0x8e, 0x20, - 0x20, 0x2f, 0x3b, 0x3b, 0x14, 0x54, 0x3d, 0x4c, 0xe0, 0x7b, 0xe4, 0xc0, 0x0b, 0x58, 0xe6, 0x48, 0x73, 0xba, 0x17, - 0x3e, 0x04, 0x76, 0x0e, 0xba, 0xf0, 0xb0, 0x8a, 0x3e, 0xa0, 0xda, 0x07, 0xd7, 0x35, 0x32, 0x7b, 0x15, 0x33, 0xca, - 0xc1, 0xaa, 0x6e, 0xcc, 0x36, 0xb1, 0xaf, 0x33, 0xd7, 0x35, 0xa0, 0xdf, 0x63, 0x3f, 0x03, 0xd8, 0xc3, 0x88, 0xd9, - 0x3a, 0x5e, 0xd2, 0x5b, 0xa0, 0xdb, 0xe0, 0x4a, 0x89, 0xa4, 0x61, 0xb2, 0xc0, 0xa4, 0x06, 0x76, 0x5a, 0x86, 0x45, - 0x98, 0x6f, 0xf4, 0x8e, 0x7d, 0x12, 0xa6, 0x73, 0xa0, 0x5d, 0x63, 0xb2, 0x49, 0xe9, 0x71, 0xae, 0xd0, 0x49, 0x08, - 0xa9, 0x11, 0xfb, 0x92, 0x19, 0x48, 0xe5, 0x31, 0x61, 0x8f, 0xab, 0xc1, 0x93, 0x81, 0xa5, 0x82, 0xfa, 0xd7, 0x66, - 0x29, 0x6d, 0xc9, 0x99, 0x23, 0x7c, 0x8a, 0xe5, 0xcf, 0xb0, 0x96, 0x60, 0xcb, 0x5a, 0xa0, 0xb4, 0xd7, 0x82, 0x8b, - 0x05, 0xb3, 0x0e, 0x05, 0xce, 0x60, 0xb6, 0xaf, 0x28, 0xc1, 0x6b, 0x79, 0x58, 0x27, 0xb1, 0x92, 0xf1, 0xcf, 0x8c, - 0xdf, 0x30, 0x72, 0x59, 0xca, 0x10, 0x99, 0xe9, 0xcf, 0x3d, 0x16, 0xef, 0x2d, 0x07, 0x9b, 0x49, 0x62, 0xf9, 0xf7, - 0xfb, 0xcf, 0x09, 0x1e, 0xf8, 0xa1, 0x27, 0xc2, 0x6a, 0x85, 0xa0, 0x67, 0x91, 0x51, 0x85, 0x9e, 0x91, 0x13, 0x05, - 0x70, 0x96, 0x3d, 0x9a, 0xeb, 0x4b, 0xea, 0xde, 0x11, 0xd2, 0x62, 0x73, 0xc2, 0xca, 0x9e, 0x33, 0x79, 0x0e, 0x8e, - 0xa2, 0x02, 0xa9, 0xce, 0x78, 0x0c, 0x38, 0xfd, 0x2d, 0xe7, 0xd5, 0xce, 0x77, 0x37, 0x88, 0x60, 0x4b, 0x7a, 0x3b, - 0x0e, 0x5f, 0x02, 0x98, 0x04, 0x93, 0x19, 0x72, 0x91, 0xcf, 0x4c, 0xd5, 0x6b, 0xfe, 0x49, 0x74, 0x14, 0xe2, 0x36, - 0x24, 0x22, 0xa1, 0x6c, 0x83, 0x3c, 0x8d, 0x23, 0xbb, 0x5b, 0x2a, 0xfd, 0xc0, 0x5f, 0xf0, 0x5d, 0xa7, 0x10, 0xe4, - 0xe0, 0x9d, 0x84, 0x57, 0x99, 0x0a, 0x67, 0xf9, 0xa6, 0x3b, 0xc2, 0x5b, 0x51, 0xc4, 0x43, 0x88, 0xdb, 0x1d, 0x28, - 0x1b, 0x08, 0x80, 0x46, 0x33, 0x0b, 0x70, 0x31, 0xc5, 0x1a, 0x8e, 0x38, 0xb8, 0x9c, 0xc3, 0x96, 0x65, 0x1c, 0x77, - 0x73, 0xdc, 0x65, 0x10, 0x29, 0xa2, 0x4b, 0x57, 0xa5, 0x4d, 0xd1, 0x63, 0x9b, 0x8a, 0xf0, 0xec, 0x53, 0x3c, 0x2d, - 0x6c, 0xa1, 0xaa, 0x69, 0xa2, 0x0f, 0x77, 0x21, 0xf2, 0x0c, 0x8d, 0x6e, 0xd7, 0x5e, 0x7f, 0x96, 0xb2, 0x37, 0x94, - 0xa1, 0xfc, 0x52, 0xdc, 0xe4, 0x7e, 0x5d, 0x6d, 0x01, 0xac, 0xe8, 0xc3, 0xbc, 0x27, 0xa0, 0xce, 0x5e, 0x71, 0x38, - 0x37, 0xdf, 0xc6, 0xcc, 0x2a, 0x37, 0xd6, 0xb0, 0x42, 0x27, 0x17, 0x6e, 0x1b, 0x6d, 0x1f, 0xe8, 0x74, 0x45, 0xc2, - 0x8f, 0x57, 0xbe, 0x8f, 0x8e, 0x48, 0x25, 0x99, 0x2b, 0x76, 0xa7, 0xfd, 0x2d, 0xc8, 0xd0, 0x03, 0x39, 0x79, 0x24, - 0x40, 0x82, 0x5e, 0xc0, 0x7c, 0x3e, 0x8f, 0xb6, 0x06, 0x0e, 0xdc, 0x28, 0x9f, 0x38, 0x87, 0xb8, 0x9b, 0x9b, 0xa5, - 0xc3, 0xd3, 0x52, 0xfa, 0x1e, 0x0a, 0x81, 0x13, 0xba, 0xa4, 0xca, 0x17, 0x8c, 0x24, 0x24, 0xf1, 0x4c, 0xa2, 0x73, - 0x98, 0x9b, 0x73, 0x1a, 0xb1, 0x3c, 0xb2, 0x32, 0xf4, 0xda, 0x51, 0x94, 0x77, 0x5c, 0xcd, 0x92, 0xee, 0xa3, 0x66, - 0x29, 0x63, 0xab, 0x0a, 0x23, 0x1a, 0x19, 0x9f, 0xb4, 0xd5, 0x8b, 0xa4, 0x1c, 0xb2, 0x2e, 0x52, 0x03, 0xdb, 0xc6, - 0x64, 0x66, 0x94, 0xdc, 0xc6, 0xf9, 0xa2, 0x32, 0xb0, 0x5d, 0x04, 0xad, 0x52, 0x3b, 0xd2, 0x41, 0x7d, 0x89, 0xea, - 0xfd, 0xc0, 0xda, 0x36, 0xc9, 0xdf, 0xd1, 0xaa, 0x93, 0xef, 0xa1, 0xab, 0x9c, 0x56, 0x3b, 0x10, 0xc6, 0xbd, 0xa2, - 0x8d, 0x02, 0x03, 0xc5, 0xee, 0xc1, 0x76, 0x15, 0x3a, 0xbd, 0xdf, 0x1a, 0x95, 0x6c, 0x3a, 0x05, 0x21, 0xa5, 0x2a, - 0x98, 0xa6, 0x0a, 0xab, 0x1b, 0x18, 0xb3, 0xbf, 0x3b, 0x6e, 0xbe, 0x73, 0x1c, 0x7b, 0xc5, 0x5c, 0x1f, 0x82, 0xbd, - 0xa0, 0x78, 0xad, 0x35, 0xf8, 0xe2, 0x34, 0x30, 0x13, 0x33, 0xb3, 0xd2, 0xf2, 0x76, 0xad, 0x39, 0xfe, 0x7a, 0x70, - 0xc7, 0x14, 0x3e, 0xd0, 0xfd, 0x98, 0x5b, 0x2d, 0xde, 0xcb, 0xb7, 0xa5, 0xc4, 0x97, 0x2e, 0xd5, 0x2e, 0xce, 0x42, - 0x27, 0x0e, 0xc3, 0x1c, 0x86, 0x56, 0x6c, 0x8d, 0x34, 0x7e, 0x81, 0x4d, 0xaf, 0xeb, 0x9d, 0x38, 0x62, 0xc0, 0xb5, - 0x9e, 0x23, 0x66, 0x3e, 0x73, 0xd9, 0x7b, 0x26, 0xe9, 0x34, 0x4c, 0x57, 0x23, 0x8e, 0x3a, 0x01, 0x35, 0x9f, 0x3a, - 0xb9, 0x3f, 0x3c, 0xa0, 0x90, 0x1d, 0xfa, 0xe8, 0xc7, 0xda, 0xbe, 0x4d, 0x49, 0x65, 0xc3, 0xd7, 0x70, 0x4e, 0x4c, - 0xce, 0x2e, 0xff, 0xf8, 0xd0, 0xa6, 0xd9, 0xe1, 0x58, 0x19, 0xc4, 0xab, 0x3e, 0x67, 0x6f, 0x50, 0xc4, 0xda, 0x94, - 0xdd, 0xea, 0x1d, 0x64, 0x36, 0xe7, 0xff, 0x80, 0x90, 0x84, 0x58, 0xaf, 0x86, 0xf9, 0x65, 0x88, 0x6e, 0xad, 0x6b, - 0x70, 0xce, 0x4f, 0xe7, 0x7b, 0xcc, 0x16, 0x3f, 0xf9, 0xa5, 0x2e, 0x99, 0x67, 0xeb, 0x04, 0x61, 0xb1, 0xec, 0xda, - 0x03, 0xbf, 0xc2, 0xfb, 0xe2, 0xf7, 0xf0, 0x85, 0x0d, 0x90, 0x10, 0xce, 0x2f, 0xe9, 0xd7, 0xef, 0x7f, 0x61, 0x1b, - 0xc4, 0xf6, 0x0f, 0x8f, 0xa7, 0x67, 0xae, 0xd2, 0xd2, 0xce, 0x1f, 0x07, 0x43, 0x98, 0x18, 0x01, 0x5a, 0x11, 0x24, - 0x21, 0x24, 0xd3, 0x07, 0x52, 0xb2, 0x6e, 0x6a, 0x9e, 0x56, 0x52, 0x56, 0xd1, 0xbe, 0x52, 0x9f, 0xee, 0xca, 0x9d, - 0x65, 0x42, 0xac, 0x2e, 0x4d, 0xfd, 0x50, 0xe0, 0xcb, 0xca, 0xa4, 0x2c, 0x49, 0xa1, 0x2b, 0xcf, 0xfe, 0x91, 0xfa, - 0x8e, 0x80, 0xcf, 0x35, 0x7a, 0x85, 0x60, 0xbc, 0xde, 0xee, 0xac, 0x41, 0x4f, 0x2b, 0x83, 0x49, 0x3d, 0xf2, 0xca, - 0x5e, 0x5a, 0x15, 0x5d, 0x5d, 0xf9, 0xae, 0xad, 0x6e, 0xc4, 0xb2, 0xf7, 0x9a, 0x61, 0x85, 0xbc, 0xab, 0xcc, 0x69, - 0x9a, 0x1c, 0xc6, 0x65, 0xf3, 0x35, 0xa2, 0x12, 0x69, 0x66, 0xef, 0x1a, 0x17, 0x9b, 0x4c, 0xd9, 0x67, 0xc1, 0x36, - 0xee, 0x82, 0x44, 0xe2, 0x04, 0x3b, 0x24, 0x24, 0x94, 0xf6, 0x4d, 0xd6, 0xae, 0x3a, 0x73, 0x3a, 0xc3, 0x38, 0xed, - 0x78, 0xd8, 0x47, 0x4c, 0xc7, 0xde, 0x22, 0x1d, 0x21, 0x3b, 0x75, 0x30, 0x66, 0x3c, 0x49, 0xaa, 0xe6, 0xa5, 0x8c, - 0x56, 0x27, 0xcf, 0x08, 0xcd, 0xda, 0x83, 0xc6, 0x44, 0x77, 0x41, 0xec, 0x9b, 0xa4, 0xca, 0x41, 0x0a, 0x27, 0xea, - 0x7b, 0xad, 0x87, 0xfd, 0x75, 0x43, 0xeb, 0x92, 0xc9, 0x5c, 0x42, 0x81, 0xc4, 0x32, 0xbf, 0x0c, 0x24, 0x2f, 0x34, - 0x9d, 0x0d, 0xb5, 0x95, 0x80, 0x9b, 0xda, 0xe2, 0xed, 0xf4, 0x3d, 0xdf, 0xcd, 0xea, 0x71, 0xbd, 0x47, 0xb7, 0xe0, - 0xae, 0x3d, 0xcc, 0x98, 0x96, 0x31, 0x61, 0x0f, 0x14, 0x68, 0x80, 0x9e, 0x0a, 0x1e, 0xea, 0x66, 0xf1, 0x57, 0x2e, - 0xc6, 0x6f, 0x8c, 0x3d, 0xaa, 0x23, 0x89, 0x3e, 0xa7, 0xd7, 0xe2, 0xea, 0x3e, 0x19, 0x0b, 0x02, 0x23, 0x1f, 0x9e, - 0x14, 0xcc, 0x70, 0x9a, 0x68, 0x32, 0xe1, 0x1d, 0x8e, 0x3a, 0x4d, 0x51, 0x9b, 0x81, 0x9d, 0xdc, 0x64, 0xd1, 0xc6, - 0xbb, 0xab, 0x5b, 0xdd, 0x7b, 0xc3, 0xb0, 0xe6, 0x70, 0x87, 0xc4, 0x51, 0xf7, 0x16, 0xb5, 0x1a, 0x97, 0x41, 0xdb, - 0x26, 0x5b, 0xb1, 0xb5, 0x5e, 0x55, 0xe3, 0x34, 0xef, 0xb8, 0x7a, 0x4d, 0xdb, 0xee, 0x40, 0xd4, 0x0b, 0xb1, 0xac, - 0xf9, 0xa8, 0x09, 0x32, 0x9a, 0xf2, 0xe3, 0xc1, 0x94, 0xc7, 0x82, 0x16, 0xa7, 0x5f, 0xb7, 0xb1, 0x32, 0xf1, 0xb3, - 0x70, 0x34, 0x21, 0xce, 0xef, 0xe3, 0xb0, 0x69, 0x56, 0xfa, 0x17, 0x75, 0x54, 0x2b, 0x42, 0x0a, 0xa3, 0x13, 0xe1, - 0x42, 0x61, 0x4d, 0x1a, 0x03, 0x5e, 0x7a, 0xf9, 0x89, 0xb8, 0x0f, 0xa7, 0x28, 0x50, 0x57, 0x88, 0x5e, 0x0f, 0x6d, - 0xe1, 0xc4, 0xc1, 0xd3, 0x9b, 0xca, 0x28, 0xf5, 0xcd, 0xfd, 0xcc, 0x1b, 0x9d, 0x7c, 0xa8, 0xf2, 0xb8, 0x41, 0xa8, - 0x70, 0xdf, 0x84, 0x21, 0x43, 0xaf, 0xe0, 0xfb, 0x26, 0x3b, 0x56, 0x7e, 0xd2, 0xe2, 0x3c, 0xb4, 0x25, 0xd6, 0x8e, - 0x87, 0x8f, 0x40, 0x6c, 0xcf, 0x1b, 0x98, 0x1e, 0xc8, 0xbf, 0xd9, 0x95, 0x35, 0x8c, 0x4a, 0x0a, 0x1b, 0xbb, 0xc2, - 0x75, 0x0a, 0x90, 0x51, 0x89, 0xf3, 0x38, 0x88, 0x02, 0x58, 0x6d, 0x3f, 0x50, 0xaa, 0x54, 0x42, 0x0a, 0xdc, 0xea, - 0xf4, 0x67, 0xe0, 0x76, 0xf0, 0x92, 0x1d, 0xb3, 0x7a, 0x88, 0xcc, 0xc6, 0x23, 0xcd, 0xd5, 0x86, 0x69, 0xd1, 0xcd, - 0x89, 0xb3, 0x30, 0xb1, 0xe6, 0x51, 0xe1, 0x1e, 0x35, 0x6e, 0x4e, 0x84, 0xcb, 0x45, 0x37, 0x71, 0x68, 0x3c, 0xdd, - 0xb6, 0xb3, 0x7a, 0xa7, 0xb7, 0x6e, 0xc0, 0x59, 0x3d, 0x53, 0x5f, 0x67, 0xb0, 0xe0, 0xfe, 0x53, 0x15, 0x2a, 0x74, - 0x02, 0x5b, 0x32, 0x81, 0x8b, 0x1f, 0x15, 0x9f, 0x59, 0xc0, 0x0b, 0x4d, 0x4a, 0xb5, 0x16, 0x30, 0xf8, 0xaa, 0x23, - 0x5e, 0x37, 0x2d, 0x4b, 0x3a, 0x54, 0xa5, 0xef, 0x7d, 0xa7, 0xaa, 0xb4, 0x46, 0xa6, 0xbb, 0x6d, 0xc3, 0xc9, 0x87, - 0x48, 0x8b, 0x29, 0x2d, 0x10, 0x01, 0x70, 0xfe, 0xf5, 0x03, 0x40, 0xf1, 0xad, 0x49, 0xb2, 0x16, 0xf2, 0x5c, 0x1d, - 0x4e, 0xb8, 0x4e, 0x79, 0xb2, 0x9c, 0xcb, 0x8e, 0x18, 0x18, 0x1c, 0x73, 0x56, 0x44, 0x2f, 0x72, 0xe4, 0x0c, 0x56, - 0xd9, 0xb4, 0x33, 0xc4, 0xd1, 0x11, 0xd8, 0x09, 0x51, 0x13, 0xc0, 0x20, 0xc6, 0x18, 0x36, 0x0b, 0x95, 0xcd, 0x68, - 0xe4, 0x36, 0x54, 0x03, 0xca, 0xd7, 0x38, 0xb1, 0x5d, 0xd6, 0x30, 0x74, 0x10, 0xc8, 0xe6, 0xc3, 0x67, 0x86, 0xfb, - 0x58, 0xfb, 0xbd, 0xd7, 0xd0, 0x32, 0x93, 0xe2, 0xf4, 0x69, 0xcb, 0xdc, 0xb9, 0x74, 0xe2, 0xb2, 0x78, 0x69, 0xf6, - 0xa2, 0xf7, 0x94, 0x8d, 0x29, 0x05, 0x59, 0x05, 0x3d, 0x1f, 0xcc, 0x03, 0x40, 0x31, 0x75, 0x99, 0x4c, 0x02, 0x9c, - 0x4b, 0x44, 0xe9, 0xb5, 0x4c, 0x08, 0x6c, 0x01, 0xd3, 0x72, 0xda, 0x5c, 0xe1, 0xee, 0xf9, 0x92, 0xcb, 0xd3, 0xb2, - 0x57, 0xe8, 0x35, 0xbf, 0xcf, 0xde, 0xd5, 0x57, 0x4d, 0xfb, 0xef, 0xcb, 0xef, 0x76, 0x3d, 0x91, 0x94, 0x81, 0xa8, - 0xda, 0xa9, 0x9c, 0x79, 0xd2, 0x81, 0x9d, 0x6d, 0x9d, 0xdf, 0x39, 0x9e, 0xff, 0xb1, 0x3e, 0x99, 0x3a, 0xb7, 0xa1, - 0xb1, 0xd8, 0xf8, 0xfd, 0x2e, 0xf3, 0xcc, 0x92, 0x15, 0x29, 0x21, 0x50, 0xf5, 0x48, 0x36, 0x9b, 0xd4, 0x0b, 0x52, - 0x8b, 0x1b, 0x1f, 0x91, 0x22, 0x05, 0x90, 0x86, 0x6c, 0x20, 0xee, 0x0d, 0x76, 0xec, 0xf6, 0xfd, 0x4d, 0x8d, 0x7d, - 0xed, 0x9a, 0x7e, 0xfd, 0xc8, 0xcd, 0xd7, 0x6e, 0xd1, 0xc7, 0x2d, 0x7a, 0x5e, 0xbf, 0x92, 0x92, 0x70, 0xf0, 0x6e, - 0x89, 0xc0, 0xb4, 0xc3, 0x9c, 0x7c, 0xb7, 0x4b, 0x33, 0x20, 0x68, 0x99, 0x45, 0xb1, 0x91, 0x6b, 0x2c, 0x61, 0x40, - 0x55, 0x41, 0x6e, 0xce, 0x99, 0x6a, 0x33, 0x10, 0xac, 0x77, 0xbc, 0xdc, 0x66, 0x34, 0x71, 0x87, 0x6a, 0x0d, 0xdc, - 0xc4, 0x85, 0x4b, 0x84, 0x9d, 0xe2, 0x2a, 0x9b, 0x93, 0xb3, 0x28, 0xe3, 0xef, 0x92, 0x7b, 0x75, 0x18, 0x18, 0x9b, - 0x0b, 0x2e, 0xdc, 0x76, 0x1e, 0xba, 0x70, 0xc4, 0x1b, 0x79, 0x5a, 0x90, 0x4a, 0xd3, 0x09, 0x14, 0x65, 0x6c, 0xcb, - 0x85, 0xac, 0x04, 0xfd, 0xc6, 0xa1, 0xcd, 0x45, 0x15, 0xf0, 0x4d, 0x3c, 0x55, 0x64, 0xb6, 0xaa, 0x62, 0x2c, 0xe2, - 0xb4, 0xa5, 0x54, 0x6f, 0xe7, 0x4f, 0x00, 0x8e, 0x21, 0xff, 0xe3, 0xd5, 0x44, 0xa0, 0x80, 0x2a, 0x71, 0x80, 0x90, - 0x99, 0xd5, 0x53, 0xf4, 0xe6, 0x0c, 0xa1, 0x1b, 0x90, 0xf2, 0xc1, 0x69, 0x0e, 0x7e, 0xd5, 0x6a, 0x6f, 0xab, 0xc2, - 0x96, 0x23, 0xab, 0x91, 0xa2, 0x09, 0xd0, 0x92, 0x42, 0x22, 0x59, 0x9c, 0x3a, 0xd6, 0xe7, 0xfa, 0xda, 0xfd, 0x23, - 0x0a, 0xd9, 0xf3, 0xf3, 0xf3, 0x7c, 0x6d, 0x0d, 0xd2, 0xc6, 0xe2, 0x2f, 0xed, 0x5a, 0x22, 0x26, 0xcd, 0xfc, 0x40, - 0x7d, 0x5d, 0x5b, 0x75, 0x5f, 0x45, 0xbd, 0xe1, 0xb9, 0x55, 0x3f, 0x66, 0x51, 0x7b, 0x35, 0x52, 0xda, 0x8f, 0xc5, - 0x5f, 0xfa, 0xbb, 0xe9, 0x6c, 0xb5, 0x8e, 0xe3, 0xe1, 0xcd, 0x75, 0xea, 0x30, 0x97, 0xbf, 0xc6, 0xda, 0x70, 0x68, - 0xbe, 0x01, 0xbb, 0x45, 0xf5, 0xa9, 0x76, 0x4d, 0x20, 0x54, 0xc0, 0xcd, 0x44, 0x70, 0x20, 0xee, 0x23, 0xfd, 0x8c, - 0x6a, 0xed, 0xab, 0x40, 0x8c, 0x56, 0xa6, 0x49, 0x4b, 0xb5, 0x1a, 0x9a, 0x29, 0xb3, 0x51, 0xc5, 0x50, 0x05, 0xee, - 0xec, 0xca, 0xd9, 0xa8, 0x33, 0x24, 0x2f, 0x07, 0x43, 0xe3, 0xe1, 0x38, 0x40, 0x1f, 0xac, 0x81, 0x17, 0xbd, 0xf2, - 0x8c, 0xf7, 0xfa, 0x99, 0x31, 0xd4, 0xd2, 0x63, 0x7e, 0x34, 0x78, 0xae, 0x76, 0x1c, 0x9c, 0x8a, 0xda, 0xa9, 0x60, - 0x9c, 0xb3, 0x28, 0x90, 0x01, 0x5e, 0x21, 0xb9, 0xc6, 0x70, 0x3e, 0x9e, 0x85, 0x15, 0xfd, 0xe4, 0x39, 0x6b, 0x6e, - 0x4b, 0x1e, 0xd0, 0x96, 0x2a, 0xa7, 0xf0, 0xad, 0xac, 0x91, 0x2c, 0xd2, 0x53, 0xef, 0xcc, 0x26, 0x51, 0xb1, 0xae, - 0x00, 0x20, 0x79, 0x0f, 0x3d, 0x33, 0x9d, 0x87, 0x72, 0x15, 0xc5, 0xab, 0x9c, 0x19, 0x37, 0x26, 0x0a, 0xef, 0x39, - 0x42, 0x19, 0x10, 0x31, 0x33, 0x0c, 0x9c, 0xd2, 0xbe, 0xb0, 0x3c, 0x07, 0xb0, 0x06, 0x10, 0x7f, 0x71, 0x1d, 0x6e, - 0x9d, 0x67, 0xa1, 0x34, 0x95, 0x1c, 0xcc, 0xc2, 0x90, 0x51, 0xbc, 0x37, 0xe9, 0xde, 0xc2, 0xee, 0x27, 0xe2, 0xae, - 0x27, 0x02, 0x9d, 0x5b, 0xbe, 0x57, 0x11, 0x05, 0x38, 0x7f, 0x06, 0x71, 0x1f, 0x54, 0xb9, 0xcc, 0x38, 0x75, 0x2c, - 0x3b, 0xd4, 0x0e, 0xde, 0x45, 0xd0, 0xa2, 0x55, 0x4d, 0xe1, 0xeb, 0xbe, 0x85, 0xe7, 0xe2, 0x45, 0xb8, 0xd6, 0x01, - 0x20, 0x09, 0x87, 0x68, 0x2e, 0x18, 0xde, 0x25, 0x16, 0xd6, 0x44, 0x9b, 0x3f, 0x49, 0x4a, 0x53, 0x15, 0x15, 0x65, - 0x6e, 0x69, 0x36, 0xaa, 0x21, 0x03, 0xf0, 0x04, 0xbd, 0xfc, 0x3e, 0xa3, 0xa2, 0x3f, 0xaa, 0xf2, 0xcc, 0xd2, 0xad, - 0xcb, 0x41, 0xaf, 0xc4, 0xea, 0x29, 0x86, 0x6d, 0x99, 0x3d, 0x58, 0xd0, 0xbc, 0xf8, 0xe2, 0x7f, 0xc3, 0x28, 0x7a, - 0x38, 0xae, 0xb4, 0xb1, 0xf0, 0xad, 0xa8, 0x7b, 0x68, 0xad, 0x8a, 0xfa, 0xbc, 0x8c, 0xa5, 0x83, 0xf6, 0x51, 0x5b, - 0xe6, 0x94, 0xaa, 0xbe, 0xcb, 0xfe, 0xdc, 0xa5, 0xfb, 0x54, 0x69, 0xda, 0x5b, 0x51, 0x88, 0xe0, 0xf9, 0x24, 0x45, - 0x0b, 0x55, 0x75, 0xb5, 0x20, 0xc0, 0x38, 0x45, 0x8a, 0x93, 0x5b, 0x5d, 0xe8, 0x61, 0x37, 0xb7, 0xa0, 0x9c, 0xbc, - 0xde, 0x0d, 0x22, 0xa4, 0x83, 0xde, 0xb7, 0x99, 0xb2, 0xca, 0x79, 0x43, 0x58, 0xf2, 0xca, 0xc5, 0x99, 0x29, 0x97, - 0x69, 0xa5, 0x55, 0xdc, 0xd0, 0xac, 0x35, 0x9d, 0x12, 0x30, 0x25, 0x17, 0xad, 0x4a, 0xce, 0xb3, 0xa1, 0x71, 0x91, - 0x6d, 0xd6, 0x5a, 0xd1, 0x74, 0x87, 0x05, 0x9e, 0x29, 0xac, 0xcb, 0x1e, 0x5c, 0xc3, 0x89, 0x06, 0xc7, 0x75, 0xbb, - 0x6d, 0x82, 0x08, 0xe4, 0x2e, 0xa6, 0x78, 0x3c, 0x31, 0xfc, 0x97, 0x3b, 0x14, 0x1f, 0x5e, 0x63, 0xaf, 0xa3, 0x18, - 0x29, 0xdf, 0x34, 0xd8, 0x3a, 0x02, 0xfc, 0x0b, 0x77, 0x29, 0xf5, 0x35, 0x24, 0x13, 0xca, 0xda, 0xcd, 0x39, 0x31, - 0x70, 0x52, 0xdc, 0xd2, 0x34, 0xe5, 0x65, 0x9e, 0xde, 0x47, 0x94, 0x17, 0xed, 0x2d, 0x62, 0x93, 0x86, 0xae, 0x8d, - 0xb8, 0x37, 0x98, 0x80, 0xe3, 0x7f, 0xb0, 0x11, 0x80, 0x13, 0x29, 0x9e, 0x70, 0x39, 0xce, 0x2c, 0xc5, 0x42, 0xbf, - 0x79, 0xa5, 0xb0, 0x4f, 0x61, 0x51, 0xd1, 0x9a, 0xcd, 0x75, 0x4b, 0xa5, 0x68, 0xc4, 0xa1, 0x4f, 0x52, 0x59, 0x9c, - 0xa7, 0x23, 0x3c, 0x9f, 0x52, 0x35, 0x3d, 0xcf, 0x31, 0xaf, 0xe3, 0x88, 0xb3, 0x39, 0x11, 0x92, 0x0f, 0xd3, 0x5c, - 0x1c, 0x31, 0xb6, 0xef, 0x72, 0xa9, 0x7c, 0x7c, 0xcb, 0x10, 0x85, 0x11, 0x2e, 0xc3, 0x09, 0xb2, 0xf4, 0xa7, 0x68, - 0x5b, 0x74, 0xa7, 0x6a, 0x12, 0x74, 0xad, 0x4e, 0x2e, 0x14, 0x67, 0xda, 0x27, 0x48, 0x28, 0xb9, 0xc1, 0x46, 0x07, - 0x35, 0x55, 0xe6, 0x47, 0xa5, 0x16, 0x37, 0xbf, 0x60, 0x61, 0x40, 0xeb, 0x9d, 0x71, 0xa6, 0xd8, 0x16, 0x6f, 0xad, - 0xe1, 0xce, 0x06, 0x66, 0xf7, 0x0a, 0x88, 0x2c, 0x22, 0xc7, 0x79, 0xcc, 0x70, 0xac, 0xb8, 0xfa, 0x22, 0x89, 0xe2, - 0x9c, 0xd0, 0xc6, 0x40, 0x8b, 0x8f, 0x7b, 0xba, 0x5a, 0xf0, 0x65, 0x1c, 0x76, 0x0d, 0x89, 0x2a, 0x4e, 0xef, 0xa2, - 0xcb, 0xfd, 0x44, 0x80, 0xe1, 0xc2, 0xc5, 0xf3, 0x7c, 0xef, 0x9c, 0xa8, 0x59, 0x38, 0xf9, 0xb0, 0xfd, 0x69, 0x90, - 0x90, 0xa3, 0xfe, 0x5a, 0xb8, 0x39, 0x6a, 0xaf, 0x5e, 0x69, 0x19, 0x6d, 0xf8, 0x91, 0x11, 0x2d, 0xef, 0x25, 0x9c, - 0x92, 0x61, 0x74, 0xfe, 0xc5, 0x8b, 0x19, 0x0e, 0x3c, 0x0a, 0xc7, 0xa0, 0x69, 0x00, 0x00, 0xd7, 0xab, 0x9f, 0xb0, - 0xb5, 0xa5, 0x9c, 0x11, 0xce, 0x65, 0x1b, 0x12, 0xac, 0x8c, 0x4b, 0x39, 0x5a, 0x1b, 0xcf, 0x09, 0x58, 0x32, 0xc7, - 0xad, 0x83, 0xc6, 0xa8, 0xe7, 0x79, 0xc7, 0x94, 0x63, 0xf3, 0x2c, 0x38, 0x6f, 0xf9, 0xbe, 0xd4, 0xe4, 0x0c, 0x82, - 0xe6, 0xaa, 0x29, 0xb1, 0x26, 0x2c, 0x7a, 0xe0, 0x72, 0x7f, 0x49, 0x9e, 0xb1, 0xc8, 0xdf, 0xcd, 0x30, 0x41, 0x2b, - 0x14, 0x8a, 0x86, 0x7c, 0x25, 0x34, 0x08, 0x96, 0xab, 0xb9, 0xe5, 0xbd, 0x18, 0x49, 0x4e, 0x35, 0x9b, 0xda, 0x8d, - 0x72, 0x68, 0x86, 0x29, 0x73, 0x70, 0x68, 0x3b, 0x3f, 0x11, 0x7c, 0xd9, 0x59, 0xd5, 0x82, 0x38, 0xfb, 0x5d, 0xb3, - 0x33, 0xa1, 0x85, 0x28, 0x55, 0x5f, 0x84, 0x3d, 0x9d, 0x98, 0x5a, 0x76, 0x5e, 0xc8, 0x9d, 0xa6, 0xe0, 0xad, 0xa6, - 0x6c, 0x0e, 0x29, 0xbe, 0x63, 0x3a, 0x32, 0x87, 0x8f, 0xc8, 0xb0, 0x1d, 0xd9, 0x4c, 0x93, 0x4b, 0x9f, 0x7e, 0xd6, - 0xeb, 0x7f, 0x74, 0x80, 0xc2, 0x3a, 0x06, 0x13, 0x9a, 0xe7, 0x79, 0x65, 0xad, 0xa9, 0x4c, 0x67, 0x8e, 0x35, 0x75, - 0x34, 0x50, 0xf0, 0xd4, 0x78, 0x0a, 0x11, 0x35, 0x25, 0x12, 0xad, 0x1e, 0xc2, 0x12, 0x50, 0x8e, 0xf7, 0x93, 0x98, - 0xeb, 0xf6, 0xa8, 0xb2, 0xf1, 0xdf, 0x88, 0x3e, 0x1a, 0x5a, 0x07, 0xbf, 0x9e, 0xd9, 0xa8, 0xf9, 0x45, 0xaa, 0x9c, - 0x42, 0x9f, 0x1f, 0x95, 0x34, 0xd6, 0x34, 0xe8, 0xc2, 0xc9, 0xc0, 0x2a, 0xe8, 0xa4, 0x02, 0xff, 0x97, 0x21, 0x67, - 0xac, 0x9c, 0x90, 0x87, 0x8a, 0xc5, 0xda, 0x75, 0xfd, 0x9a, 0x2f, 0x35, 0x66, 0x41, 0xfd, 0x7c, 0x00, 0x6a, 0x2d, - 0xe5, 0x42, 0x7e, 0x33, 0xdf, 0x86, 0x6a, 0xa3, 0x1b, 0x4e, 0x3a, 0xed, 0xd5, 0x2f, 0x85, 0x5c, 0xc4, 0x6a, 0x8a, - 0x0e, 0x69, 0x3c, 0x0d, 0x0a, 0x98, 0xf0, 0x9b, 0x72, 0x6e, 0xe2, 0x20, 0x41, 0x5e, 0x6a, 0x1c, 0x6b, 0xee, 0x7a, - 0x8c, 0xa3, 0xd5, 0x99, 0x95, 0x63, 0x17, 0xaa, 0x15, 0x97, 0xe7, 0x59, 0x54, 0xde, 0x2f, 0xf6, 0xa4, 0xa9, 0x75, - 0x65, 0xd5, 0xbf, 0xdc, 0x8a, 0x79, 0xa3, 0x6b, 0xa4, 0x68, 0xd8, 0x4c, 0xeb, 0xe4, 0x74, 0x51, 0x65, 0x56, 0x10, - 0x78, 0x1b, 0x9a, 0x8d, 0x90, 0xd8, 0x05, 0xfb, 0xd1, 0x1e, 0x2f, 0xbd, 0x5a, 0x9a, 0x22, 0xb8, 0x0b, 0x58, 0xd1, - 0x3f, 0x96, 0x16, 0x06, 0xa4, 0xb6, 0xa2, 0xa4, 0xb6, 0xad, 0xff, 0x36, 0x66, 0xb8, 0x9f, 0x55, 0x73, 0xef, 0x50, - 0xdf, 0x0e, 0x46, 0x8b, 0x8f, 0x49, 0x5f, 0x72, 0x6d, 0x97, 0x82, 0x9c, 0x2c, 0x81, 0xd5, 0x0b, 0xf6, 0x2a, 0xb0, - 0xf2, 0xfa, 0x63, 0xab, 0x0d, 0x99, 0xf0, 0xf6, 0x69, 0x32, 0xe7, 0x32, 0x2a, 0xf0, 0x28, 0xc1, 0xdd, 0xa7, 0x15, - 0x45, 0x59, 0x30, 0xee, 0xbf, 0xe4, 0xcc, 0x2f, 0x2b, 0x92, 0xa4, 0x21, 0xbe, 0xb1, 0x48, 0xfe, 0x10, 0x52, 0xde, - 0x81, 0x5b, 0x07, 0xc2, 0xb5, 0x59, 0x3b, 0x7d, 0x98, 0xcf, 0xe3, 0x03, 0xa3, 0x36, 0xf0, 0x9f, 0xaf, 0xff, 0x24, - 0x8e, 0x33, 0x78, 0xb6, 0x2b, 0x4d, 0xd6, 0x8d, 0x30, 0x91, 0xec, 0x7f, 0xb5, 0xfb, 0x2b, 0x05, 0x16, 0xe1, 0x2a, - 0x19, 0xba, 0x04, 0x74, 0x43, 0x53, 0x2c, 0x70, 0x9f, 0x02, 0x5d, 0x46, 0x3f, 0x09, 0x5d, 0xe5, 0x1a, 0xd3, 0xfb, - 0xa4, 0xe8, 0x03, 0x40, 0x5c, 0x12, 0x5d, 0xde, 0xd2, 0x7b, 0x15, 0x81, 0x0d, 0x0e, 0x90, 0x56, 0xde, 0x99, 0x14, - 0x3d, 0xf7, 0x91, 0xd5, 0x39, 0xf0, 0x7f, 0xdb, 0x65, 0xbb, 0x30, 0x74, 0x76, 0xcb, 0xfd, 0x70, 0x1d, 0x33, 0x1b, - 0x64, 0xd8, 0x13, 0xc5, 0xd8, 0x82, 0x8f, 0x8f, 0xfe, 0x31, 0x8f, 0x3c, 0xb7, 0x03, 0xbe, 0x51, 0x74, 0x50, 0x71, - 0xa8, 0x40, 0xfe, 0x2e, 0x84, 0x42, 0x5d, 0xb6, 0xd9, 0x02, 0xc0, 0xeb, 0x13, 0xd4, 0xd0, 0x89, 0x28, 0xf5, 0x06, - 0x54, 0xf9, 0x1e, 0xa4, 0x54, 0xc2, 0xfc, 0x43, 0x26, 0x53, 0x8d, 0x96, 0x8a, 0xa9, 0x2a, 0x8c, 0xa2, 0x38, 0xd8, - 0xa8, 0x2d, 0x0c, 0x8d, 0xf1, 0x8a, 0x31, 0xa3, 0xe6, 0xc7, 0xce, 0xc2, 0xdb, 0xd2, 0x5e, 0x8f, 0xf8, 0x24, 0x3b, - 0xe3, 0x6b, 0x0f, 0x4a, 0xd0, 0xe0, 0x2a, 0xc0, 0xeb, 0xb4, 0xfa, 0x1c, 0x45, 0x24, 0xb3, 0xcc, 0x1a, 0x1e, 0x88, - 0xfd, 0x88, 0x1a, 0x5f, 0x05, 0xbf, 0x7f, 0xae, 0x21, 0x9e, 0xc5, 0x6f, 0xee, 0x37, 0x7d, 0x67, 0x7f, 0x05, 0xd1, - 0xaf, 0x4e, 0xd1, 0xca, 0x09, 0xc7, 0x3c, 0x01, 0x5e, 0x37, 0x78, 0x01, 0xb6, 0x16, 0x6b, 0x9e, 0x5c, 0x8b, 0xcf, - 0x6d, 0xcd, 0x69, 0x50, 0x55, 0xf2, 0xab, 0x13, 0x4a, 0x68, 0x44, 0x06, 0x9b, 0x86, 0xa4, 0x99, 0x8d, 0xd4, 0xce, - 0x75, 0xc9, 0xc8, 0x40, 0x1a, 0xb8, 0xdb, 0xde, 0x5b, 0x86, 0x4f, 0xd0, 0xbe, 0x22, 0x47, 0x79, 0x1a, 0x23, 0xef, - 0x50, 0x56, 0x2a, 0x71, 0xb9, 0xdc, 0x6c, 0x8b, 0x3e, 0x4f, 0xfd, 0x8a, 0x7e, 0x93, 0xc0, 0xf2, 0xb8, 0x8b, 0x08, - 0x4e, 0xff, 0x57, 0x39, 0x6b, 0x1a, 0x7d, 0x51, 0x7d, 0x08, 0x07, 0x63, 0x7b, 0xd5, 0xdd, 0x36, 0xa5, 0x87, 0x9c, - 0x2d, 0x2d, 0xf2, 0x08, 0x86, 0x96, 0xef, 0x3f, 0xa6, 0x0a, 0x4b, 0x8e, 0x94, 0x76, 0xca, 0x93, 0x40, 0x2f, 0x35, - 0x6c, 0x27, 0xfe, 0x6d, 0x0d, 0xd7, 0xcf, 0x57, 0x6a, 0xe4, 0x16, 0xfe, 0x0f, 0xfe, 0xb3, 0x51, 0xae, 0x2e, 0x75, - 0xf2, 0xa0, 0x1d, 0x14, 0x47, 0x43, 0x72, 0x3c, 0x1b, 0xfb, 0x96, 0xd1, 0x28, 0x9e, 0x09, 0xfb, 0x2c, 0x0a, 0xd3, - 0xa0, 0xc7, 0xa2, 0xc1, 0xb2, 0xca, 0x00, 0xf2, 0xd0, 0x6b, 0x72, 0x46, 0x9c, 0x86, 0x13, 0xdc, 0x08, 0x9a, 0x1a, - 0xcd, 0x3a, 0x24, 0x75, 0x75, 0xa7, 0x60, 0x6a, 0x75, 0x99, 0x37, 0x43, 0x94, 0xcb, 0xfa, 0x7a, 0x77, 0x44, 0xc5, - 0xa3, 0x6c, 0x53, 0xfa, 0x16, 0xb1, 0xd1, 0x8e, 0x19, 0xe0, 0xc0, 0x1c, 0x10, 0xf2, 0xa2, 0x25, 0x2d, 0x67, 0x4e, - 0x51, 0x7e, 0x7a, 0x5e, 0x69, 0x1a, 0x30, 0x3b, 0x29, 0xc4, 0x1c, 0x45, 0x57, 0xa5, 0x2e, 0x8d, 0x41, 0xb6, 0xb0, - 0x13, 0x47, 0xea, 0x4b, 0x8b, 0x5e, 0xd2, 0xa1, 0x9b, 0x53, 0x0b, 0x8b, 0x71, 0x00, 0xdb, 0x74, 0x8f, 0xc5, 0x27, - 0xaa, 0x30, 0xac, 0xa5, 0xaf, 0x11, 0xfe, 0x7a, 0xd9, 0x7c, 0xde, 0xce, 0x9b, 0xd6, 0xcd, 0x59, 0x23, 0x9d, 0x18, - 0x72, 0x58, 0x9d, 0x60, 0x1d, 0x2d, 0x42, 0x96, 0xc5, 0x79, 0x9f, 0x57, 0xf9, 0x6c, 0x9c, 0x4b, 0xac, 0x4d, 0x18, - 0xb5, 0xbc, 0x35, 0xe7, 0x2e, 0x9d, 0x53, 0x54, 0xa4, 0x93, 0x58, 0xb6, 0x99, 0xf2, 0x41, 0x65, 0x50, 0x42, 0x2c, - 0xe4, 0x17, 0xfc, 0x5c, 0x14, 0xa7, 0x0f, 0x0b, 0xbd, 0x49, 0xed, 0x2c, 0xba, 0x32, 0x39, 0x18, 0x47, 0xd7, 0xfc, - 0xf7, 0xca, 0x87, 0x80, 0x2e, 0x11, 0x4f, 0x0d, 0x70, 0xc9, 0xf8, 0x9a, 0x82, 0x3a, 0x85, 0xb4, 0x6e, 0xe2, 0x3b, - 0x8d, 0xb3, 0x2e, 0x2d, 0xbb, 0x44, 0x7d, 0xb3, 0x39, 0x4a, 0x18, 0x1f, 0x37, 0xe5, 0xdd, 0x4f, 0x6d, 0x05, 0x43, - 0xb4, 0x4e, 0xcf, 0x3e, 0xba, 0x54, 0x01, 0x69, 0x66, 0x06, 0x35, 0xbd, 0x35, 0x5e, 0xc8, 0x30, 0x76, 0x2b, 0xe3, - 0xb9, 0x19, 0x27, 0xe9, 0xfc, 0xf8, 0x29, 0x1f, 0xf0, 0xb9, 0x29, 0xd5, 0xe4, 0xf5, 0xcd, 0x5e, 0x07, 0xd4, 0x33, - 0xc3, 0xc3, 0x69, 0xac, 0x7d, 0x2b, 0xdd, 0x82, 0x2f, 0xf6, 0x70, 0x28, 0x9b, 0x76, 0xfb, 0xf4, 0xa5, 0x6f, 0x9b, - 0x71, 0x73, 0x64, 0x59, 0xd2, 0xe0, 0xf1, 0x31, 0x51, 0xb5, 0x7f, 0x24, 0x62, 0x1c, 0xa4, 0xd3, 0x98, 0xd1, 0x88, - 0xfe, 0x4a, 0x7c, 0xe6, 0xaa, 0x0c, 0x57, 0x16, 0xf3, 0xa0, 0x24, 0xde, 0x96, 0x7e, 0x36, 0xa6, 0x15, 0xc2, 0xef, - 0x31, 0x3d, 0xa9, 0xd7, 0x43, 0x88, 0xf3, 0x94, 0x8b, 0x57, 0x1c, 0x4e, 0xae, 0xab, 0x7f, 0x42, 0x17, 0x86, 0x27, - 0xad, 0x2a, 0x80, 0xff, 0xe2, 0x06, 0xa4, 0x3d, 0x41, 0x1f, 0x7c, 0x97, 0xce, 0xc1, 0x75, 0x56, 0x5d, 0xe6, 0xd4, - 0xd8, 0x79, 0x1a, 0xcd, 0xd6, 0x05, 0xac, 0x36, 0x0d, 0x69, 0x82, 0x86, 0xd1, 0xdb, 0xee, 0x7d, 0x63, 0xe3, 0x3c, - 0x1b, 0xfa, 0x2e, 0x96, 0x10, 0xcf, 0x1f, 0x03, 0xfc, 0x78, 0x85, 0x58, 0x18, 0xf6, 0xdb, 0xa5, 0x99, 0x04, 0xcd, - 0xb0, 0xc9, 0x58, 0x92, 0x3c, 0xb5, 0xe4, 0xbe, 0xc9, 0xd5, 0x42, 0x8e, 0xcb, 0xa9, 0x26, 0x25, 0xea, 0xdc, 0xb7, - 0x35, 0x23, 0x73, 0x2a, 0xad, 0x32, 0x62, 0x95, 0x1a, 0xe0, 0xbe, 0x78, 0x0d, 0x44, 0xb0, 0xbb, 0xe6, 0x66, 0xc7, - 0xca, 0x02, 0x83, 0x8f, 0x2e, 0x8b, 0x6b, 0xa9, 0x6b, 0xe0, 0x78, 0x6b, 0x1d, 0x78, 0x5c, 0x1e, 0xc0, 0x91, 0x62, - 0x2c, 0xde, 0x66, 0x63, 0x19, 0xff, 0x2d, 0x51, 0x0d, 0x1f, 0x85, 0xaf, 0xd7, 0xc6, 0x79, 0x99, 0xf1, 0xe1, 0xe4, - 0x28, 0x95, 0x8c, 0xcb, 0x8d, 0x1e, 0x62, 0x1c, 0x2e, 0x87, 0xad, 0x72, 0xa6, 0x64, 0x86, 0x75, 0x39, 0xe6, 0x67, - 0x5c, 0xe9, 0x79, 0x23, 0xa6, 0x12, 0xca, 0x4b, 0xfa, 0x4c, 0x3f, 0x71, 0x65, 0x9c, 0x8d, 0xa2, 0x7d, 0xab, 0xb9, - 0x5f, 0x10, 0x7d, 0x76, 0x60, 0xcc, 0xc1, 0xd5, 0x53, 0x72, 0x1d, 0xda, 0xaa, 0xec, 0xcb, 0xf7, 0x49, 0xbe, 0x92, - 0x3e, 0xff, 0x25, 0x1b, 0x36, 0x16, 0x55, 0x92, 0x7c, 0xd4, 0x29, 0x44, 0x0e, 0xd3, 0x8a, 0x76, 0x8c, 0x0e, 0x60, - 0x0b, 0x82, 0xfa, 0x46, 0x40, 0xb4, 0x01, 0xe8, 0xbe, 0x4a, 0x45, 0x0f, 0x0c, 0x34, 0x6f, 0x51, 0xb6, 0x9c, 0xf4, - 0xb5, 0xe9, 0xe0, 0xdf, 0xfd, 0x55, 0x33, 0x6f, 0x44, 0x2f, 0x0b, 0xae, 0x10, 0x3a, 0x6d, 0x05, 0x7f, 0x34, 0x2d, - 0x79, 0x76, 0x5c, 0xea, 0x62, 0x97, 0xb6, 0x70, 0xf0, 0x73, 0x35, 0x7d, 0xf8, 0xab, 0x24, 0xc7, 0xae, 0x8d, 0x1a, - 0xc1, 0x71, 0x9e, 0x73, 0xdc, 0xb8, 0x40, 0x44, 0xcb, 0x42, 0xdb, 0x43, 0xd5, 0x22, 0x0d, 0xa7, 0xbe, 0x33, 0x47, - 0xc3, 0x04, 0xb0, 0x57, 0xec, 0x5d, 0x18, 0x58, 0xff, 0x2c, 0x8b, 0xe8, 0xc0, 0x8e, 0x70, 0x52, 0x9a, 0xf8, 0xfa, - 0xf4, 0x1e, 0xc4, 0xa5, 0x78, 0xe8, 0x8c, 0x1a, 0x04, 0x73, 0x9a, 0x4f, 0x0f, 0x9a, 0xb1, 0x72, 0x5b, 0x0a, 0xed, - 0xf9, 0x48, 0x9d, 0x40, 0x16, 0xa8, 0x58, 0x4d, 0xb5, 0x6b, 0x19, 0x41, 0xeb, 0x26, 0xd9, 0x1b, 0x8f, 0x64, 0x33, - 0x56, 0x1c, 0xbe, 0x02, 0x72, 0x73, 0xe3, 0xc6, 0x1d, 0x38, 0x67, 0xd5, 0x0a, 0x83, 0x33, 0x42, 0x64, 0x68, 0xbe, - 0x55, 0x8d, 0xc4, 0xf4, 0x95, 0x80, 0x06, 0x1c, 0x2e, 0x52, 0x50, 0xbf, 0xdb, 0xea, 0xb4, 0x77, 0x4a, 0x8f, 0x54, - 0xa2, 0x62, 0x20, 0x2a, 0xa7, 0x74, 0xc3, 0xb8, 0x7a, 0x2e, 0xba, 0x80, 0x89, 0x4e, 0xb1, 0x51, 0xb0, 0x28, 0xa3, - 0x5b, 0x15, 0x82, 0xcb, 0xf5, 0x60, 0xf3, 0xfd, 0xd5, 0xe9, 0xc6, 0xa6, 0x7f, 0x7d, 0x49, 0x83, 0x28, 0x14, 0x37, - 0x3e, 0x60, 0x17, 0x9d, 0x74, 0xbe, 0x49, 0x87, 0x4c, 0x1b, 0x19, 0xa3, 0xbe, 0x74, 0x7c, 0x30, 0xf5, 0x77, 0xff, - 0x28, 0x8d, 0x02, 0xae, 0x71, 0xa7, 0xeb, 0x19, 0x6e, 0x99, 0x77, 0x38, 0x85, 0x52, 0xc8, 0x76, 0x19, 0x91, 0xd6, - 0x7f, 0xb6, 0xc8, 0x37, 0x32, 0xe8, 0x49, 0x5c, 0xdf, 0xca, 0x68, 0xb7, 0xe9, 0xcd, 0xba, 0x3b, 0xa7, 0xe9, 0x16, - 0x00, 0x1e, 0xff, 0xa5, 0xd6, 0x3b, 0x91, 0x33, 0x11, 0xaa, 0x55, 0x04, 0x9f, 0xa4, 0x4c, 0xd9, 0xb1, 0xb6, 0x83, - 0x3e, 0xcd, 0xb0, 0xfe, 0xdd, 0x93, 0x10, 0xc9, 0x9c, 0x35, 0xbc, 0x21, 0xa8, 0x63, 0x5f, 0xe1, 0xac, 0x3e, 0x8b, - 0xd4, 0x3f, 0xe2, 0xea, 0x17, 0xd4, 0xa8, 0xa2, 0xc8, 0xc5, 0xae, 0x29, 0x1a, 0x87, 0x2e, 0xdc, 0xe4, 0x36, 0xeb, - 0x5d, 0x52, 0x36, 0xc0, 0xe8, 0xbf, 0xdc, 0xa4, 0x18, 0x99, 0xbb, 0xee, 0x6c, 0xaa, 0xac, 0xad, 0x82, 0x91, 0x14, - 0x8b, 0x10, 0xca, 0x5c, 0x67, 0xba, 0x2e, 0xb1, 0x7e, 0x69, 0x93, 0x97, 0x9d, 0x1a, 0x06, 0x67, 0x79, 0xd1, 0x3d, - 0xef, 0xa4, 0x47, 0xa1, 0x65, 0x41, 0x53, 0x4d, 0x21, 0x3d, 0xf8, 0x16, 0x46, 0x2b, 0x8f, 0xa6, 0x05, 0xd3, 0xda, - 0xeb, 0xc4, 0x14, 0xd5, 0xce, 0x8b, 0x50, 0x67, 0x9f, 0x50, 0x36, 0x16, 0x6e, 0x2d, 0x35, 0xb1, 0x2b, 0x1d, 0x82, - 0x6d, 0x8a, 0x00, 0x26, 0x77, 0x26, 0x88, 0x78, 0x70, 0x0d, 0x4a, 0xf5, 0x84, 0xa2, 0xbe, 0x41, 0x9e, 0xe1, 0x2e, - 0xaa, 0xc6, 0xb7, 0xa0, 0x0f, 0xbd, 0x2d, 0x75, 0xc3, 0xf0, 0x6c, 0xf1, 0x50, 0xca, 0x9b, 0xb2, 0x58, 0xb0, 0x5d, - 0x85, 0xaf, 0x64, 0x95, 0xc8, 0xda, 0x8f, 0x76, 0x68, 0xab, 0x99, 0x88, 0xd2, 0x56, 0xf6, 0x2a, 0x5d, 0xfa, 0xf8, - 0x55, 0x1b, 0xcc, 0xee, 0xf5, 0xf9, 0xaa, 0x0d, 0x31, 0x3d, 0x45, 0xfa, 0x49, 0xd8, 0x76, 0x1d, 0x11, 0xf7, 0x7f, - 0x96, 0x2d, 0x12, 0x66, 0x48, 0x19, 0xab, 0xf9, 0xf1, 0x0a, 0x61, 0xb1, 0x91, 0x16, 0xfb, 0xf3, 0xbd, 0xb0, 0xe4, - 0x3f, 0xd7, 0xea, 0xa0, 0x02, 0x0f, 0xc7, 0x79, 0xeb, 0xbb, 0x1b, 0xdf, 0x6b, 0xfe, 0xaa, 0x5b, 0x45, 0x20, 0xe9, - 0xba, 0x22, 0x72, 0xfb, 0x89, 0x4c, 0xe0, 0x0c, 0xc1, 0xb6, 0x6d, 0x02, 0xd6, 0xde, 0xdf, 0x22, 0x29, 0xc0, 0xc8, - 0x6f, 0x23, 0xfc, 0x63, 0x63, 0x6e, 0xf8, 0xfe, 0x14, 0x73, 0x73, 0x29, 0x5d, 0x24, 0x4f, 0x4e, 0x61, 0xbb, 0x64, - 0x01, 0xc2, 0x11, 0x38, 0x78, 0x3f, 0x35, 0x31, 0xdf, 0x6c, 0x28, 0x86, 0xe5, 0xd5, 0x89, 0x43, 0x51, 0xcd, 0x4f, - 0x0d, 0x45, 0x94, 0x87, 0xe9, 0x44, 0x75, 0x35, 0x21, 0x60, 0x2c, 0x1c, 0x43, 0x92, 0xc0, 0x05, 0x36, 0x40, 0x9d, - 0x62, 0x16, 0x7d, 0x3d, 0x72, 0x2b, 0xc6, 0x23, 0xdb, 0xca, 0xcd, 0xd0, 0x3e, 0xe6, 0x4d, 0x1d, 0x19, 0xb8, 0x39, - 0x76, 0xc6, 0x0f, 0x77, 0x76, 0x54, 0x56, 0x7a, 0x96, 0x9c, 0xce, 0xcd, 0x95, 0x58, 0xae, 0xc9, 0xee, 0x63, 0xa2, - 0xdd, 0x7d, 0x7b, 0x47, 0x64, 0x81, 0x18, 0xfd, 0x67, 0x75, 0x26, 0x67, 0xfb, 0x8d, 0x9c, 0xc0, 0xb7, 0x14, 0xea, - 0x05, 0x17, 0x13, 0x2e, 0xf7, 0x86, 0x57, 0xda, 0x3f, 0xf0, 0xca, 0x84, 0xcb, 0xa6, 0x5c, 0x8d, 0x6c, 0x64, 0x96, - 0xa8, 0x09, 0xf7, 0xff, 0x57, 0xf6, 0x1a, 0x62, 0x0b, 0xf0, 0x62, 0xec, 0x5b, 0x1b, 0x45, 0xbb, 0x9b, 0x85, 0x0e, - 0x57, 0xd8, 0x87, 0x77, 0x9c, 0x9a, 0xb7, 0xdd, 0x0d, 0xcc, 0xf4, 0x83, 0x44, 0x56, 0xbe, 0x4b, 0x0a, 0xfd, 0x9f, - 0xb1, 0xc7, 0xbe, 0x77, 0x6b, 0xa2, 0xe7, 0xf4, 0x38, 0xf8, 0xe7, 0xb6, 0x34, 0xc2, 0x6f, 0x93, 0x3e, 0x3f, 0xeb, - 0xc6, 0x50, 0x75, 0xf0, 0x6a, 0x7e, 0xd7, 0x64, 0xa2, 0x7f, 0x7d, 0x26, 0xe7, 0x7d, 0xfa, 0x80, 0x08, 0x55, 0xf3, - 0x89, 0xef, 0x02, 0xab, 0x58, 0x37, 0xc6, 0x8e, 0x76, 0x45, 0x11, 0x27, 0x1f, 0xd6, 0xdb, 0x64, 0x1a, 0xb7, 0x8e, - 0xb8, 0x78, 0x5f, 0xc1, 0x9d, 0x92, 0x50, 0xdd, 0x6f, 0x97, 0xa0, 0xc7, 0xa1, 0x3f, 0xd6, 0x1f, 0x16, 0x9f, 0x1b, - 0xeb, 0x0e, 0x6f, 0x94, 0xbc, 0x37, 0x46, 0x5d, 0x34, 0x61, 0xd7, 0x2f, 0x3b, 0xef, 0x34, 0x16, 0xf7, 0x86, 0x63, - 0x25, 0xa1, 0x80, 0x16, 0xb4, 0x7c, 0x81, 0x5f, 0x8a, 0x3c, 0x19, 0x61, 0xc2, 0xc9, 0x53, 0xbc, 0x55, 0xdf, 0x8a, - 0x18, 0xbc, 0x6e, 0xf2, 0xd5, 0xfc, 0x64, 0x36, 0xfe, 0xb3, 0xf4, 0xe5, 0x65, 0x96, 0x9d, 0xaa, 0xd7, 0x9e, 0x01, - 0x8d, 0x49, 0x99, 0x1f, 0xf1, 0xfc, 0xb3, 0xc7, 0xf9, 0x20, 0xc9, 0x97, 0x10, 0x4f, 0x9f, 0xca, 0x12, 0x40, 0x01, - 0x56, 0x2e, 0xde, 0x99, 0xc5, 0xe5, 0x0b, 0x1e, 0x26, 0x22, 0x65, 0x20, 0x6d, 0x83, 0x42, 0x06, 0x8c, 0xef, 0x34, - 0x20, 0xbc, 0x47, 0x16, 0x53, 0xe1, 0xaa, 0xeb, 0xfb, 0x55, 0x64, 0x77, 0x4e, 0x60, 0xd4, 0x6e, 0xff, 0x24, 0x9b, - 0x02, 0x35, 0x71, 0x00, 0xa8, 0x2b, 0x26, 0xe2, 0xf1, 0x4f, 0x80, 0xfb, 0x97, 0xe4, 0x48, 0x15, 0x1d, 0x60, 0x64, - 0x7c, 0xf5, 0xc4, 0xaa, 0x17, 0xbf, 0x42, 0x39, 0xe8, 0xcf, 0x5b, 0xda, 0xc1, 0x65, 0xaf, 0x6c, 0x64, 0xab, 0x93, - 0x89, 0x02, 0x3b, 0x59, 0x1e, 0x97, 0x55, 0x84, 0x13, 0x50, 0xd2, 0xb9, 0xa3, 0x43, 0x47, 0xe6, 0x9f, 0x0b, 0x07, - 0xa7, 0xc4, 0xf9, 0xeb, 0x67, 0xc5, 0x0f, 0x17, 0xfa, 0xa7, 0x7c, 0xdc, 0x1b, 0x78, 0xf7, 0x39, 0xd1, 0x40, 0x7f, - 0x37, 0xa9, 0xa2, 0x1c, 0x00, 0x1d, 0x38, 0x28, 0xfc, 0xea, 0x74, 0x78, 0x6d, 0x09, 0x2d, 0x35, 0x0b, 0x4e, 0xcb, - 0x1f, 0xfe, 0x09, 0x72, 0xb6, 0x34, 0x4f, 0x5a, 0x02, 0x41, 0x36, 0xae, 0x4d, 0x5f, 0x44, 0x6b, 0x6f, 0x3a, 0x65, - 0x89, 0x00, 0x6b, 0xc9, 0x29, 0x10, 0x25, 0x72, 0xaf, 0xdb, 0xec, 0xcd, 0xd4, 0x09, 0x2c, 0x53, 0x5b, 0x05, 0x88, - 0x0a, 0x6b, 0x31, 0x60, 0x10, 0xf3, 0x1a, 0xff, 0xb9, 0x56, 0xf3, 0xe4, 0xed, 0x9b, 0x27, 0x07, 0x84, 0x91, 0x30, - 0x50, 0x7c, 0x14, 0x60, 0x38, 0x23, 0xf8, 0x4b, 0xbd, 0xbe, 0x36, 0x8b, 0x01, 0x3f, 0x94, 0x54, 0xbc, 0xd8, 0x9b, - 0x32, 0xbd, 0x80, 0x8b, 0x90, 0xfe, 0x81, 0xfc, 0xc3, 0xa3, 0x96, 0xbd, 0x3a, 0xeb, 0x3a, 0xb5, 0x1d, 0x77, 0x8b, - 0xbe, 0x32, 0x9a, 0x03, 0xaf, 0x18, 0x5c, 0x16, 0x7d, 0x0e, 0x2c, 0xef, 0xbf, 0x96, 0xf7, 0xac, 0x0c, 0x7c, 0xc2, - 0xc1, 0xaa, 0xaf, 0xcc, 0x8d, 0x43, 0x0d, 0x19, 0x0b, 0x49, 0x91, 0x16, 0x20, 0x7a, 0xed, 0xc7, 0xe9, 0x80, 0x86, - 0xbd, 0x3a, 0xdb, 0x61, 0x81, 0x46, 0x8c, 0x74, 0x2e, 0xb5, 0xbb, 0xee, 0xe9, 0x91, 0x31, 0x7e, 0xde, 0xbd, 0x17, - 0x16, 0x4e, 0x99, 0x6d, 0xa8, 0xcb, 0x9f, 0x8a, 0xbe, 0x94, 0x94, 0xc1, 0xb6, 0x62, 0xcb, 0x3b, 0x01, 0xcc, 0x83, - 0xc9, 0x77, 0x27, 0xcc, 0xdd, 0x07, 0x9a, 0xc3, 0xa8, 0x79, 0xa5, 0x8a, 0x7c, 0xe3, 0x8b, 0xa8, 0xc6, 0xff, 0x05, - 0x3d, 0x15, 0x91, 0x45, 0xbe, 0x08, 0x6c, 0x21, 0xac, 0xa7, 0x80, 0x7f, 0x17, 0x43, 0x1d, 0x7e, 0xe9, 0x5e, 0x30, - 0x6c, 0x3b, 0xd6, 0xa9, 0x66, 0xb3, 0x79, 0xf3, 0xbe, 0xb1, 0x8d, 0x20, 0x2d, 0xa3, 0x8d, 0x98, 0x40, 0xdb, 0x0f, - 0x31, 0xee, 0xdf, 0x48, 0xdd, 0x88, 0x98, 0x7e, 0x11, 0xce, 0xac, 0x1f, 0x44, 0xf3, 0x4d, 0xb6, 0xa0, 0xb9, 0xfe, - 0x21, 0x69, 0x9f, 0xbc, 0x43, 0x80, 0x05, 0xe4, 0xd1, 0x2b, 0xcb, 0x6c, 0xac, 0x09, 0x4a, 0x09, 0x57, 0x1e, 0x92, - 0x8c, 0xf2, 0x26, 0xaa, 0x4f, 0x68, 0x6f, 0x25, 0x19, 0xa0, 0x81, 0xeb, 0xd8, 0x05, 0x53, 0xc7, 0xdc, 0xa6, 0xcb, - 0x7d, 0x37, 0xa1, 0x3d, 0x08, 0xe5, 0xda, 0x0b, 0xf8, 0xc2, 0xcd, 0x73, 0x17, 0x1e, 0x27, 0xd0, 0x1a, 0xe4, 0x7f, - 0x1c, 0x0f, 0xc9, 0x47, 0x59, 0x0a, 0x89, 0x55, 0x16, 0x42, 0x84, 0xda, 0x85, 0xdd, 0xdc, 0x28, 0x76, 0x3d, 0x09, - 0xd8, 0x91, 0x00, 0x20, 0x38, 0x53, 0x30, 0x89, 0xb3, 0x29, 0x0d, 0x61, 0xce, 0x51, 0xc3, 0x69, 0xf9, 0x19, 0x57, - 0x63, 0xba, 0xc0, 0x66, 0xe0, 0x04, 0x08, 0xf4, 0x37, 0xf6, 0x85, 0x23, 0x4b, 0xcb, 0xc9, 0xfc, 0xec, 0xc0, 0x09, - 0x90, 0xc3, 0xca, 0xd3, 0x26, 0x61, 0x4b, 0x70, 0xee, 0x4d, 0x7a, 0x3f, 0x52, 0x88, 0x04, 0x45, 0x54, 0x39, 0x7e, - 0x81, 0xab, 0xa5, 0x25, 0xe5, 0xac, 0x44, 0x6b, 0x15, 0xca, 0x10, 0xad, 0x37, 0xbe, 0x98, 0x75, 0x7a, 0xff, 0xab, - 0x4d, 0xe7, 0xa5, 0xb1, 0x38, 0xc4, 0x10, 0x38, 0x62, 0xa9, 0xfd, 0x54, 0x66, 0xe3, 0x85, 0xb3, 0xcc, 0xee, 0x9b, - 0xb1, 0xfd, 0x9a, 0xa6, 0x9a, 0x89, 0x37, 0xe5, 0xb7, 0x6d, 0xf6, 0xb0, 0xe0, 0x2a, 0x27, 0x7a, 0x1a, 0x7f, 0xf4, - 0xe6, 0x6c, 0xa7, 0xbf, 0x86, 0x4d, 0x26, 0x47, 0xc5, 0xc7, 0x1e, 0x41, 0xce, 0x85, 0x2a, 0x15, 0x22, 0xae, 0xb7, - 0xc3, 0x52, 0xe5, 0x9e, 0xe4, 0x4a, 0xe7, 0x58, 0x82, 0x92, 0x6c, 0x77, 0xb1, 0x78, 0xa9, 0xa1, 0x20, 0x8e, 0xcd, - 0xdd, 0x97, 0x72, 0xc1, 0xbb, 0x6d, 0x48, 0x6b, 0xef, 0x5e, 0xbf, 0xf2, 0xef, 0xd3, 0xb1, 0x95, 0x6c, 0x76, 0x9c, - 0x99, 0xd5, 0xec, 0x38, 0x16, 0xe4, 0xfc, 0x9c, 0xcc, 0x8b, 0x24, 0xbc, 0x4d, 0xda, 0xbf, 0x9e, 0xda, 0x33, 0xd5, - 0x06, 0x8a, 0x68, 0x8a, 0x52, 0xf7, 0x6f, 0x52, 0x93, 0xb0, 0x91, 0xe0, 0x2f, 0xd4, 0x0d, 0x63, 0xdd, 0x87, 0x55, - 0xf3, 0x95, 0xb3, 0x62, 0x63, 0x1f, 0xe4, 0x66, 0x6a, 0x5c, 0x14, 0x7c, 0x24, 0xe4, 0x4a, 0x2b, 0xc3, 0x06, 0xc7, - 0x81, 0xa6, 0xfc, 0x81, 0x29, 0x7f, 0x98, 0x61, 0x4d, 0x5c, 0x74, 0xab, 0xef, 0x93, 0xeb, 0x9d, 0x00, 0x60, 0xa4, - 0x33, 0x07, 0x0b, 0xb5, 0x02, 0xdf, 0x1e, 0x87, 0x8b, 0x03, 0x5c, 0x4f, 0x3b, 0xa4, 0xe8, 0x24, 0x4c, 0x7e, 0x1b, - 0x9f, 0x6d, 0xf2, 0x97, 0x76, 0xbd, 0x97, 0xee, 0x36, 0x79, 0x71, 0xd8, 0xde, 0x0a, 0xbd, 0x61, 0x20, 0xa2, 0x52, - 0x05, 0x95, 0x84, 0x20, 0xec, 0xb4, 0x5b, 0x19, 0xb0, 0x2a, 0x2d, 0xb6, 0xc0, 0x8f, 0xcb, 0xfa, 0x78, 0x7c, 0x2d, - 0x1a, 0x53, 0xeb, 0xa8, 0x42, 0x8d, 0xcb, 0xf9, 0x34, 0x80, 0x27, 0x2a, 0x9e, 0x1b, 0x03, 0x7d, 0x46, 0x01, 0x68, - 0x50, 0x64, 0x41, 0x48, 0x2b, 0x0c, 0xc5, 0x96, 0x1b, 0x33, 0x15, 0x78, 0xba, 0xf0, 0x17, 0xb8, 0x14, 0x69, 0x8c, - 0x40, 0xe5, 0xb5, 0x86, 0x97, 0xe6, 0xeb, 0x84, 0xc4, 0x2f, 0x8d, 0xbf, 0x9e, 0xe4, 0x14, 0x32, 0x05, 0xf0, 0x23, - 0x89, 0xd7, 0xe5, 0x25, 0x47, 0xc0, 0x9b, 0x01, 0xf6, 0x0c, 0x10, 0x4e, 0xd6, 0xe9, 0xbc, 0x0d, 0x8f, 0x08, 0x27, - 0xe0, 0xc6, 0x50, 0xb9, 0x27, 0x57, 0x56, 0x90, 0xb1, 0xee, 0x48, 0x7b, 0xbc, 0x64, 0x6b, 0xd2, 0xd6, 0xd9, 0x09, - 0xb5, 0xce, 0xd2, 0x43, 0x95, 0xb8, 0x0f, 0x2a, 0xc9, 0xa5, 0xe7, 0x01, 0x0e, 0xd3, 0xbe, 0x7c, 0x9b, 0x62, 0xe8, - 0x3d, 0xc6, 0x4c, 0x86, 0x64, 0x6c, 0x95, 0x55, 0x9a, 0x5e, 0x40, 0x13, 0x60, 0xdb, 0x2e, 0xb8, 0x69, 0x72, 0x78, - 0x23, 0x72, 0x0f, 0xe8, 0x5c, 0x70, 0x45, 0xf6, 0x8e, 0xd2, 0x9d, 0xd9, 0x08, 0xda, 0x78, 0x57, 0xd6, 0x64, 0x97, - 0x4a, 0xe0, 0x9b, 0x18, 0xf2, 0x71, 0x96, 0x12, 0x34, 0x6e, 0x1b, 0xbb, 0x2c, 0x81, 0x3a, 0x93, 0xb9, 0x9a, 0x55, - 0x79, 0xd2, 0x0c, 0x53, 0x99, 0xa2, 0xaa, 0x96, 0x5c, 0x13, 0x64, 0x02, 0xc2, 0xe4, 0xad, 0xc9, 0x75, 0x7d, 0x66, - 0x00, 0x92, 0x1e, 0x24, 0x67, 0xc1, 0xd8, 0x71, 0x23, 0xbc, 0xb0, 0x57, 0x89, 0x2d, 0x8c, 0x4f, 0xad, 0x49, 0x4e, - 0x4e, 0xd2, 0x9f, 0x8c, 0x97, 0xad, 0xa6, 0xcd, 0x8e, 0x2d, 0x09, 0x4d, 0x8b, 0x43, 0x0b, 0xb6, 0x52, 0xb7, 0x73, - 0x75, 0xb0, 0x35, 0x6b, 0x59, 0xc0, 0x60, 0x1b, 0x8d, 0x75, 0xc7, 0xf8, 0x99, 0x63, 0x22, 0x3c, 0x58, 0x36, 0xa6, - 0x3b, 0xb1, 0xbc, 0x48, 0xcc, 0x31, 0xd0, 0x1a, 0xf3, 0xe6, 0x2f, 0x30, 0xc6, 0x4c, 0xf0, 0x4a, 0xe5, 0x62, 0x59, - 0xd4, 0x67, 0x2d, 0x44, 0x84, 0x66, 0x31, 0xbc, 0xda, 0x80, 0xe0, 0xf1, 0x1a, 0xd7, 0x1b, 0x70, 0x37, 0xb0, 0xc8, - 0xc2, 0x22, 0xc2, 0x62, 0xbb, 0x23, 0x3a, 0x2a, 0x96, 0xf2, 0xa3, 0x47, 0xcf, 0x33, 0x21, 0x4f, 0x6d, 0x8e, 0x25, - 0x19, 0xd2, 0x1e, 0xf1, 0xdb, 0xd7, 0x58, 0x2c, 0xea, 0x16, 0xc6, 0x06, 0x63, 0x69, 0xe2, 0x1f, 0xc4, 0x57, 0xdd, - 0xbe, 0x06, 0x32, 0xee, 0x19, 0x7c, 0x92, 0xd1, 0x33, 0x7a, 0x79, 0xab, 0x1b, 0x20, 0x35, 0x1e, 0x75, 0x12, 0x0d, - 0x3c, 0x29, 0x09, 0x73, 0x73, 0x35, 0xa5, 0x4a, 0x93, 0x8c, 0x42, 0xcf, 0xeb, 0xa0, 0xc1, 0x5c, 0x03, 0x9c, 0xc4, - 0x96, 0x91, 0xbe, 0x59, 0x28, 0xc8, 0xdb, 0xbd, 0xfc, 0x39, 0x1f, 0x96, 0x46, 0x26, 0x1d, 0xba, 0xa5, 0x3d, 0x27, - 0xa3, 0x24, 0x21, 0x64, 0x68, 0x43, 0x54, 0x6b, 0x93, 0xca, 0x5e, 0x84, 0x5a, 0x91, 0x0a, 0x82, 0x1f, 0x76, 0x3a, - 0x4a, 0x3a, 0x05, 0x3d, 0x9d, 0xb2, 0xfa, 0x74, 0xba, 0xcd, 0x13, 0xd3, 0x3b, 0x9b, 0x67, 0x23, 0x02, 0x25, 0x3a, - 0xcf, 0x4f, 0x0f, 0x85, 0x8b, 0xdc, 0x82, 0x88, 0x5a, 0x73, 0x78, 0xcb, 0x60, 0x70, 0x31, 0x61, 0x2e, 0x55, 0xaf, - 0xd2, 0xf0, 0x07, 0x4f, 0x7c, 0xd7, 0xd6, 0xc2, 0x46, 0xab, 0xf4, 0xa6, 0x2c, 0x56, 0x69, 0x9e, 0x89, 0xa9, 0x67, - 0x5c, 0x21, 0x70, 0xd5, 0x10, 0xa1, 0x09, 0xdf, 0xd4, 0xf7, 0x84, 0xb2, 0x20, 0x60, 0x0c, 0xa9, 0xce, 0x62, 0x0c, - 0x0c, 0x32, 0x26, 0xeb, 0xd8, 0x1f, 0x76, 0x36, 0x45, 0xe6, 0xb5, 0x6e, 0x68, 0x66, 0xca, 0x4f, 0x35, 0xb0, 0xa8, - 0x15, 0x4a, 0x46, 0xe2, 0xb9, 0x3c, 0x4a, 0x51, 0xee, 0x41, 0xd9, 0xd3, 0x80, 0x58, 0x69, 0x53, 0xa6, 0x13, 0x42, - 0x96, 0x3c, 0x88, 0x65, 0x72, 0x61, 0xca, 0x92, 0x9c, 0xc4, 0x90, 0x0d, 0x39, 0x1b, 0x30, 0x7d, 0x15, 0x5a, 0x24, - 0x5c, 0x9e, 0x12, 0x89, 0xa2, 0x69, 0x4e, 0x88, 0xc3, 0x56, 0xe4, 0xd4, 0x60, 0xb5, 0x77, 0x30, 0xcf, 0xf0, 0x19, - 0x27, 0x99, 0xf5, 0x48, 0x50, 0xf1, 0xc7, 0x38, 0x06, 0x0c, 0x38, 0xb7, 0x39, 0x19, 0xc8, 0xbb, 0x61, 0xf6, 0xe8, - 0x02, 0x4d, 0xf9, 0x56, 0x5a, 0x00, 0x7b, 0xb4, 0x20, 0x19, 0xa8, 0xb2, 0x60, 0x05, 0xd7, 0x8f, 0x42, 0x81, 0xa7, - 0xcc, 0x1c, 0xcd, 0xb1, 0x50, 0x9f, 0x10, 0x51, 0xa9, 0x5c, 0x20, 0x5a, 0x75, 0x8e, 0x0d, 0xc6, 0xac, 0xd6, 0xe8, - 0xc4, 0x05, 0xbc, 0x48, 0x8d, 0xbf, 0xad, 0xa1, 0xd3, 0x4e, 0x3c, 0x18, 0x06, 0xfd, 0xf7, 0x25, 0x49, 0xf7, 0xa3, - 0x7b, 0xbc, 0x1f, 0xf5, 0x13, 0x9d, 0x79, 0xdf, 0x53, 0x1f, 0x3f, 0xf3, 0xed, 0x92, 0x81, 0xfc, 0x07, 0x8e, 0x0d, - 0xbc, 0x7f, 0x8e, 0xfa, 0x00, 0xef, 0xbf, 0x3e, 0x19, 0x37, 0x9f, 0x5d, 0x40, 0xdb, 0x86, 0x0b, 0x34, 0xe3, 0xb1, - 0xe6, 0x49, 0x0d, 0x56, 0xa4, 0xa0, 0x56, 0xb0, 0x96, 0xe5, 0x35, 0xdc, 0xf5, 0xe9, 0x1c, 0xdc, 0x13, 0x9b, 0xcb, - 0x3c, 0xf9, 0xe8, 0x03, 0xf0, 0x21, 0x58, 0xfe, 0x54, 0xbe, 0xe6, 0x27, 0x1a, 0x9a, 0xee, 0x20, 0x63, 0xe8, 0xb5, - 0xc4, 0x64, 0xf3, 0xa9, 0xe0, 0x5f, 0x2b, 0xb8, 0x7d, 0x51, 0xbd, 0x85, 0xc2, 0x99, 0x08, 0x29, 0x7f, 0x6c, 0xb3, - 0x3f, 0xa4, 0x4c, 0x34, 0x0d, 0xee, 0xe4, 0x69, 0xf8, 0xa5, 0x4b, 0x0a, 0x93, 0x2f, 0xea, 0xff, 0xf5, 0xf3, 0xcf, - 0x47, 0x07, 0xc6, 0xc4, 0xe4, 0x1d, 0x94, 0xfb, 0x7f, 0xce, 0x46, 0xc8, 0x4e, 0xe9, 0x7c, 0xb3, 0xf5, 0x5f, 0x04, - 0xc3, 0xf2, 0xf0, 0xfa, 0xbc, 0xb5, 0xeb, 0x43, 0x7c, 0x6d, 0xa0, 0x8d, 0x6d, 0xdb, 0xa4, 0xa2, 0xa4, 0x3e, 0xb8, - 0x02, 0x4b, 0x8c, 0x0b, 0x9a, 0x55, 0xf0, 0x98, 0x02, 0xb3, 0xd6, 0xbd, 0x99, 0x04, 0x4f, 0x39, 0xa3, 0xfd, 0x87, - 0xa0, 0x9d, 0xdc, 0xf0, 0x68, 0xb8, 0x2c, 0x8f, 0x69, 0x1a, 0xeb, 0x10, 0xb2, 0x7b, 0xa7, 0x54, 0x5f, 0xcc, 0x8a, - 0x96, 0x4a, 0x6d, 0x11, 0x20, 0xd2, 0x78, 0x57, 0x13, 0xab, 0x7a, 0x08, 0xfd, 0xa7, 0xeb, 0x34, 0x69, 0x12, 0xc3, - 0x38, 0xd9, 0x4a, 0x5f, 0x03, 0xb4, 0x01, 0xbe, 0xe8, 0x2f, 0x58, 0x79, 0xee, 0x6e, 0xca, 0x23, 0xc6, 0xcd, 0x07, - 0xde, 0x1f, 0x1d, 0x32, 0x71, 0x71, 0x68, 0xec, 0xfc, 0xb2, 0x27, 0x0e, 0xbb, 0xb2, 0xf8, 0x6b, 0xa8, 0xa9, 0xe7, - 0x40, 0x1b, 0xe6, 0x6a, 0x70, 0xec, 0x3a, 0x3d, 0x77, 0xa1, 0x78, 0x60, 0x0d, 0x91, 0xf2, 0x4e, 0xf6, 0xd0, 0xcb, - 0xd1, 0x46, 0xdf, 0xba, 0x5c, 0xe6, 0x1f, 0xe2, 0x9b, 0x7f, 0x20, 0x72, 0x82, 0x76, 0x7a, 0x96, 0x28, 0x02, 0x40, - 0xa6, 0xa7, 0xf0, 0x17, 0x97, 0x50, 0x86, 0x87, 0x89, 0xce, 0x06, 0xb9, 0xb7, 0x77, 0x2e, 0xe8, 0x93, 0xfd, 0x9b, - 0xe9, 0x5c, 0xce, 0x33, 0x0c, 0x4c, 0x3b, 0x81, 0x0d, 0x94, 0x91, 0x71, 0xec, 0x52, 0xfc, 0x04, 0xa3, 0xcb, 0x10, - 0x25, 0xb7, 0xec, 0x88, 0x97, 0xda, 0xa8, 0xe4, 0x0e, 0xd9, 0x79, 0x9e, 0x3b, 0x39, 0x4c, 0x1c, 0x1b, 0xa9, 0xad, - 0x0f, 0x08, 0x08, 0xc7, 0xf2, 0x30, 0x24, 0x93, 0xf5, 0x94, 0xe6, 0xd0, 0x72, 0xa2, 0x69, 0x1e, 0xb9, 0x3d, 0x02, - 0x3a, 0x1a, 0x2d, 0xd3, 0x60, 0xb4, 0xca, 0x3e, 0xda, 0x4c, 0x7c, 0x21, 0xba, 0xc6, 0x02, 0x5b, 0x3b, 0xe4, 0x85, - 0x11, 0xef, 0x33, 0xa0, 0xe0, 0xdb, 0xb0, 0xf5, 0x3d, 0x5f, 0x7a, 0xb8, 0x9c, 0xb8, 0xc5, 0x3c, 0x28, 0x32, 0xe6, - 0x6b, 0xe3, 0x57, 0x98, 0x4c, 0x68, 0xaf, 0x84, 0x7d, 0x1d, 0x9c, 0xb2, 0x1e, 0x4c, 0x40, 0xe9, 0xb9, 0x18, 0xcd, - 0xbb, 0x74, 0x82, 0x34, 0x65, 0x0a, 0x36, 0xa6, 0x2f, 0x14, 0xa5, 0x51, 0x47, 0x57, 0x74, 0x7a, 0xd6, 0x41, 0x2a, - 0x3c, 0xf9, 0xd4, 0x76, 0x4f, 0xdd, 0x33, 0x3a, 0x21, 0x7f, 0xd4, 0xd2, 0x6b, 0x9a, 0x06, 0x46, 0x9f, 0x55, 0x5b, - 0x9f, 0x7d, 0xfe, 0x7e, 0x95, 0x64, 0xe3, 0x7e, 0x9d, 0x6c, 0xd8, 0x9c, 0xe5, 0x01, 0xf8, 0xe7, 0x29, 0xb8, 0xff, - 0x80, 0x2e, 0x20, 0x66, 0x71, 0xd3, 0xfe, 0x08, 0x43, 0xf9, 0xb6, 0xfa, 0x7a, 0xc1, 0x6d, 0x8d, 0xce, 0x0f, 0x7f, - 0x3e, 0x6a, 0x38, 0x18, 0xa2, 0x6f, 0xff, 0x27, 0x9b, 0x03, 0x04, 0x00, 0xe7, 0xef, 0xc3, 0xeb, 0xb0, 0x45, 0xf4, - 0x73, 0xdc, 0xcc, 0x1d, 0x53, 0xcd, 0xde, 0xad, 0x63, 0x7c, 0x55, 0xa6, 0x2b, 0xc9, 0x6b, 0xee, 0x92, 0xc6, 0x65, - 0xb4, 0x0d, 0xaf, 0xc9, 0x66, 0x0e, 0x6a, 0xbf, 0x25, 0x40, 0x73, 0x24, 0x7b, 0xa8, 0x75, 0xf3, 0xbf, 0x2c, 0xb6, - 0x98, 0xd2, 0xbb, 0x9d, 0x56, 0xae, 0x3e, 0xdc, 0x71, 0xb1, 0xf7, 0xd7, 0x21, 0xc0, 0xe8, 0xde, 0xce, 0xda, 0x32, - 0xf2, 0x72, 0xfb, 0x38, 0x3d, 0x5c, 0x19, 0xd5, 0xcb, 0x58, 0x7f, 0x54, 0x9b, 0x66, 0x53, 0x4b, 0x01, 0xb8, 0xd5, - 0x88, 0x22, 0x07, 0x55, 0xd9, 0x19, 0x91, 0x74, 0xb6, 0xae, 0xc6, 0xf0, 0xd7, 0x02, 0x8b, 0xcb, 0x0a, 0x21, 0x82, - 0x37, 0x06, 0xea, 0x5c, 0x85, 0x63, 0xef, 0xb4, 0xfe, 0xe8, 0xe3, 0x6c, 0xfb, 0x66, 0xfb, 0xf7, 0x35, 0xd2, 0xa5, - 0xaa, 0x99, 0x39, 0xb5, 0x9b, 0xbd, 0x65, 0xb4, 0x43, 0xbc, 0xb7, 0xad, 0x6c, 0x12, 0x4a, 0x24, 0x0e, 0x2c, 0x2c, - 0xa3, 0xac, 0xaa, 0x53, 0x04, 0x58, 0x3a, 0x4d, 0xc3, 0xb6, 0x67, 0x8e, 0x92, 0x42, 0xd1, 0x56, 0xa6, 0x30, 0xca, - 0xe3, 0xa9, 0x87, 0x1a, 0xd9, 0xdd, 0x33, 0xc1, 0xd7, 0x6c, 0x21, 0x11, 0x79, 0xbe, 0x66, 0x61, 0x3a, 0x02, 0xa8, - 0x4d, 0x79, 0x3f, 0xc1, 0x29, 0x2e, 0x31, 0xd8, 0x50, 0x52, 0x44, 0x5f, 0x6f, 0x09, 0xa1, 0xa0, 0xf8, 0x7a, 0x2a, - 0xf0, 0xf5, 0x84, 0xeb, 0xab, 0x48, 0x47, 0x70, 0x52, 0xa7, 0x49, 0xf2, 0x47, 0x43, 0xa0, 0xef, 0x37, 0xcd, 0x64, - 0x1b, 0x63, 0x47, 0x5f, 0xb7, 0xe0, 0xaf, 0x27, 0xeb, 0x29, 0x1b, 0x5c, 0x7a, 0xf8, 0x37, 0xd0, 0x63, 0x0f, 0x18, - 0x07, 0x6b, 0x67, 0x14, 0x47, 0xf1, 0x57, 0x6c, 0x51, 0x5e, 0xb4, 0x3e, 0xf2, 0xe7, 0x04, 0x60, 0x72, 0x37, 0x0f, - 0x88, 0x13, 0xcb, 0x74, 0xa8, 0x6b, 0x42, 0x64, 0x27, 0x0d, 0x39, 0x35, 0x1a, 0x5f, 0x11, 0x6d, 0x6b, 0x46, 0x52, - 0x5b, 0xf1, 0xe5, 0x51, 0x2a, 0x71, 0x6d, 0xd6, 0x2c, 0xd6, 0x4b, 0xb2, 0xa1, 0xf2, 0xa0, 0xd9, 0x60, 0x16, 0x96, - 0x1f, 0xd8, 0x92, 0x73, 0xaf, 0x49, 0x87, 0xc1, 0x4e, 0x79, 0xea, 0x64, 0xe0, 0x94, 0x5d, 0xcc, 0x8e, 0x34, 0x80, - 0xcf, 0x6b, 0x92, 0x00, 0x6a, 0x56, 0x82, 0x63, 0xdf, 0x5b, 0x0e, 0xba, 0x77, 0x0a, 0xf4, 0x1f, 0xdb, 0x21, 0x53, - 0x79, 0x71, 0x27, 0x87, 0x8e, 0x08, 0x72, 0x36, 0x64, 0x4e, 0xa0, 0x86, 0x37, 0xd9, 0xa6, 0xf5, 0xeb, 0xc3, 0x83, - 0xe3, 0xfb, 0x9c, 0x75, 0x74, 0x7b, 0x93, 0xb8, 0x88, 0xaa, 0xf1, 0x0b, 0x01, 0xd2, 0x99, 0x1a, 0x37, 0x72, 0x77, - 0x23, 0xb2, 0x20, 0xa2, 0x24, 0x39, 0x6b, 0x4f, 0x67, 0x46, 0x20, 0x9a, 0x99, 0xaa, 0x38, 0x2a, 0x62, 0x22, 0x6d, - 0x50, 0x82, 0x91, 0x42, 0xfd, 0x95, 0xbf, 0x07, 0x06, 0xe2, 0x8e, 0xef, 0xac, 0x17, 0x04, 0x1e, 0xb0, 0x3b, 0x59, - 0xf7, 0xb1, 0xb5, 0x4a, 0xd0, 0x23, 0x21, 0x73, 0x61, 0x04, 0xe2, 0xfe, 0x3d, 0xbf, 0xe3, 0xaf, 0xbf, 0x7e, 0xf6, - 0x6d, 0x57, 0x77, 0xfa, 0x1f, 0xaf, 0x1d, 0xfa, 0x6c, 0xc6, 0x1d, 0x98, 0xaf, 0x04, 0x1f, 0xc1, 0x31, 0xa9, 0x16, - 0xd0, 0x3f, 0x64, 0x76, 0x2d, 0x77, 0x05, 0x34, 0x9c, 0x5c, 0x3b, 0xc0, 0x23, 0x70, 0xa0, 0x25, 0x9f, 0xac, 0xeb, - 0x79, 0xbd, 0xda, 0xe6, 0x9d, 0xeb, 0x2f, 0xff, 0x5c, 0xd7, 0x3e, 0x74, 0x45, 0xc7, 0x60, 0x51, 0x90, 0xe5, 0xef, - 0x04, 0x16, 0xd9, 0x81, 0xbb, 0xdc, 0x7f, 0x5a, 0x46, 0x71, 0x01, 0x2d, 0xff, 0xc1, 0x83, 0xb7, 0xd3, 0x85, 0x37, - 0x3b, 0x3e, 0x74, 0xe5, 0x94, 0xe3, 0xa6, 0xee, 0xf9, 0x4a, 0xbd, 0xab, 0x8d, 0x30, 0xea, 0xc1, 0x08, 0x9c, 0xed, - 0xe2, 0x83, 0xc0, 0x88, 0x43, 0xf2, 0x98, 0xc1, 0x36, 0xb9, 0x4d, 0x19, 0x43, 0xa4, 0x85, 0xc8, 0xe6, 0x56, 0xa8, - 0xb0, 0xa0, 0x48, 0xf0, 0xc2, 0x00, 0x99, 0xba, 0x8d, 0x29, 0x43, 0x8b, 0xd3, 0x7c, 0x3f, 0x1c, 0xdb, 0x19, 0xda, - 0xa2, 0x07, 0x8c, 0x29, 0x73, 0x4c, 0xcd, 0x2c, 0x10, 0xea, 0xee, 0x36, 0xc0, 0x19, 0xbd, 0x2d, 0x7a, 0x29, 0xf3, - 0xbe, 0x3e, 0x3f, 0x7e, 0xb6, 0x0c, 0xbc, 0xa7, 0x49, 0x1d, 0x5b, 0x90, 0x76, 0x24, 0xa7, 0xa6, 0xf3, 0x76, 0xa0, - 0x74, 0x65, 0xe1, 0x3a, 0xf3, 0xd5, 0x49, 0xc0, 0x9a, 0x4c, 0x99, 0x4d, 0x31, 0xda, 0x52, 0x51, 0x49, 0x34, 0x74, - 0xef, 0x64, 0xb2, 0xb6, 0xb7, 0x07, 0x44, 0x21, 0x19, 0xd7, 0x1e, 0x02, 0x56, 0x11, 0xbd, 0x03, 0x38, 0x1d, 0x83, - 0x56, 0xe3, 0xa7, 0x46, 0x9c, 0x17, 0xc1, 0xc3, 0x52, 0xda, 0xfc, 0xe0, 0xe2, 0xfa, 0xb0, 0x36, 0x18, 0x2f, 0x1c, - 0x6e, 0x41, 0xc0, 0xba, 0xec, 0x4d, 0xee, 0xc6, 0x83, 0xfe, 0xd7, 0x9d, 0x85, 0xab, 0xf5, 0x41, 0x6e, 0x7d, 0x3e, - 0xdb, 0xd7, 0xec, 0x3e, 0xf6, 0x7c, 0xcc, 0x3d, 0xfb, 0x78, 0x9d, 0xaf, 0x84, 0xa2, 0xec, 0xd4, 0x40, 0x7b, 0x4c, - 0xc5, 0x62, 0x00, 0x0d, 0x66, 0xb2, 0x24, 0x02, 0x2a, 0x58, 0x9c, 0x7d, 0x4b, 0xa7, 0xea, 0x04, 0xcc, 0xd4, 0x9e, - 0x69, 0xc6, 0xe7, 0xc2, 0x33, 0x36, 0x5f, 0x2c, 0x5d, 0xa7, 0x56, 0x30, 0x45, 0xa7, 0xeb, 0x5f, 0x39, 0xfc, 0x18, - 0x43, 0xa0, 0xc1, 0x28, 0x57, 0xe3, 0xad, 0x2a, 0x80, 0xe0, 0xfd, 0x5d, 0xc4, 0x30, 0x01, 0x91, 0xc5, 0xa1, 0x9e, - 0xea, 0xfd, 0xd0, 0xe5, 0xfe, 0x31, 0x8f, 0xed, 0x8b, 0xf1, 0xec, 0x8d, 0x06, 0x59, 0x64, 0xce, 0x21, 0xe7, 0xbe, - 0x12, 0xf4, 0xe2, 0xfa, 0x2a, 0x3f, 0xec, 0xc7, 0x3f, 0x60, 0x4e, 0x0e, 0x6e, 0xee, 0x28, 0x68, 0xd6, 0x23, 0x44, - 0x52, 0xe4, 0x82, 0x0c, 0xfd, 0x39, 0x18, 0xc2, 0x1a, 0xa9, 0x0d, 0xa6, 0x15, 0x31, 0x1a, 0xff, 0x2e, 0x8c, 0x05, - 0xcb, 0xb4, 0xf7, 0xac, 0x36, 0x1f, 0x9c, 0xd3, 0xaa, 0xf3, 0x08, 0x49, 0xb9, 0xe6, 0x58, 0x60, 0xa4, 0xe9, 0xf4, - 0xa8, 0xd5, 0xaf, 0xbf, 0x4e, 0xee, 0x52, 0xef, 0x95, 0xb1, 0x7a, 0x11, 0x5d, 0x69, 0xc8, 0x11, 0x70, 0x31, 0xa3, - 0xac, 0x47, 0x9e, 0xfa, 0x8f, 0x7f, 0xfc, 0x4e, 0xd0, 0x6f, 0x46, 0xd7, 0x0b, 0xbd, 0x5b, 0xe8, 0x27, 0x4e, 0xb6, - 0x40, 0x3e, 0x6a, 0xdc, 0xdb, 0x25, 0x8c, 0xd3, 0x94, 0x02, 0xdf, 0x72, 0xb3, 0xd1, 0x2b, 0x06, 0xb0, 0x81, 0x4a, - 0x84, 0x45, 0x9c, 0x39, 0x0f, 0x69, 0x34, 0x1b, 0x43, 0x01, 0xec, 0x02, 0xd7, 0xff, 0x42, 0xf3, 0xfa, 0xb6, 0xa5, - 0x5b, 0x47, 0x15, 0x3a, 0x84, 0x37, 0xfa, 0x13, 0x30, 0x33, 0x41, 0xca, 0xd9, 0x42, 0x3a, 0x7e, 0x18, 0xad, 0x1e, - 0x3a, 0x8f, 0xc7, 0x19, 0x63, 0xa9, 0x66, 0xe2, 0x81, 0x5e, 0xe6, 0x72, 0x26, 0xcf, 0x25, 0x52, 0x81, 0x0a, 0x88, - 0x80, 0xa8, 0x19, 0x15, 0x2d, 0x93, 0xd3, 0xfa, 0x0d, 0xe1, 0x79, 0xc3, 0x1e, 0xb9, 0x08, 0x02, 0xfd, 0x09, 0xd2, - 0xfe, 0xdc, 0xfe, 0x0e, 0xab, 0x0b, 0x1e, 0x18, 0xcc, 0x62, 0x4f, 0x34, 0x8c, 0x9a, 0x10, 0x64, 0x6a, 0xad, 0x34, - 0xb4, 0x00, 0xad, 0x23, 0x21, 0xc7, 0x20, 0x20, 0x6b, 0x79, 0x4c, 0xfa, 0xeb, 0x96, 0xb5, 0xef, 0x8d, 0x8a, 0xe3, - 0x56, 0xb2, 0x6e, 0xcb, 0xba, 0xf1, 0x93, 0x29, 0xe3, 0xec, 0x05, 0x0c, 0x1e, 0x76, 0x4e, 0x3a, 0xe2, 0x30, 0xe2, - 0xff, 0x08, 0x8e, 0x4f, 0x7a, 0x51, 0xef, 0x0f, 0xfe, 0xb8, 0x94, 0xae, 0xf2, 0xab, 0x8e, 0xc7, 0xeb, 0x0b, 0xf3, - 0x9a, 0xe7, 0x47, 0xfc, 0xb2, 0xa1, 0x25, 0xde, 0xb3, 0xb0, 0x93, 0x3e, 0x28, 0x3b, 0x5b, 0x1b, 0x2a, 0xe3, 0x9f, - 0xe6, 0xf3, 0xa7, 0x9f, 0xae, 0x63, 0x87, 0x21, 0xce, 0x45, 0x01, 0x5f, 0x7b, 0xfe, 0x1c, 0x9f, 0x74, 0xb6, 0x69, - 0x22, 0x95, 0x1b, 0xd1, 0xb8, 0x31, 0x66, 0x6d, 0xfc, 0x68, 0xc8, 0x0a, 0xb3, 0xfe, 0x0d, 0x3a, 0x2a, 0x9f, 0x7c, - 0x7b, 0x27, 0x15, 0x82, 0xdb, 0xa6, 0xc4, 0xe8, 0x39, 0xd0, 0xe3, 0x76, 0x27, 0x69, 0xe9, 0xdf, 0xed, 0xa1, 0x8d, - 0xc8, 0xc3, 0x66, 0x76, 0x48, 0x40, 0x48, 0x70, 0xc0, 0xbb, 0x50, 0x34, 0xbd, 0x41, 0xa0, 0x8b, 0x30, 0x5b, 0x23, - 0xe7, 0x48, 0xc3, 0xc9, 0xb0, 0xdf, 0x15, 0xa7, 0xbf, 0xc9, 0xf1, 0x21, 0x72, 0x00, 0x7f, 0xdf, 0x2e, 0x44, 0x4c, - 0xbf, 0xdb, 0xf3, 0x24, 0x8f, 0x8d, 0x90, 0xbd, 0x0e, 0x62, 0xe3, 0x29, 0xc9, 0x1b, 0x69, 0x29, 0x42, 0x24, 0xbb, - 0x38, 0x11, 0xe6, 0xf2, 0x7e, 0x15, 0xf7, 0xf4, 0x15, 0x9d, 0x38, 0x73, 0x8c, 0x34, 0xba, 0x68, 0xe9, 0x84, 0xf5, - 0xf1, 0xbf, 0xcd, 0x1c, 0x0b, 0x14, 0x84, 0x3f, 0xb3, 0x06, 0xd2, 0x71, 0xb7, 0x02, 0x78, 0x5b, 0x9c, 0x20, 0xc3, - 0xd7, 0xb2, 0xd4, 0xb0, 0x9e, 0x39, 0xa0, 0x09, 0x37, 0x0a, 0xdc, 0x30, 0x9c, 0x43, 0xad, 0x60, 0x0d, 0x0e, 0x3c, - 0x22, 0xff, 0x67, 0x96, 0x93, 0xee, 0x1d, 0x26, 0xb6, 0x74, 0x48, 0x0b, 0x44, 0xc2, 0x22, 0xd6, 0xdd, 0xb3, 0x49, - 0x35, 0x7c, 0x44, 0xa1, 0xd7, 0x2a, 0xee, 0x66, 0x93, 0x3f, 0x98, 0xdf, 0xc7, 0xca, 0x9d, 0x93, 0x95, 0x36, 0x79, - 0x9f, 0xb1, 0x05, 0x9d, 0x3f, 0x1a, 0x05, 0xe8, 0x9e, 0xbb, 0xb4, 0xb2, 0x9e, 0x29, 0xc0, 0x26, 0x3a, 0x7c, 0xc7, - 0x30, 0x19, 0x0d, 0x72, 0x7e, 0x93, 0x79, 0x12, 0x27, 0x90, 0xc1, 0xd0, 0x4b, 0xd0, 0x32, 0x93, 0x47, 0xb8, 0x73, - 0x6b, 0x1f, 0x90, 0xef, 0xe2, 0x75, 0x48, 0xc9, 0x4b, 0x1a, 0x89, 0xdb, 0xbd, 0x64, 0x53, 0x68, 0x71, 0x85, 0x54, - 0x42, 0xc7, 0xd6, 0x92, 0x63, 0x0b, 0x56, 0x3b, 0xea, 0x0e, 0x0f, 0x77, 0x99, 0xc1, 0x56, 0x89, 0xfe, 0x47, 0xc7, - 0x4a, 0xe6, 0xe0, 0x31, 0xbd, 0x10, 0xb6, 0x26, 0xc6, 0x71, 0xd2, 0x74, 0x41, 0x02, 0x4f, 0x85, 0x18, 0x70, 0x3e, - 0x60, 0x67, 0x54, 0xf3, 0x38, 0xc7, 0xe3, 0x04, 0xfa, 0x4c, 0x40, 0x78, 0x76, 0xbd, 0xe1, 0x7e, 0x0e, 0x45, 0x8c, - 0xc4, 0x10, 0x8c, 0xc2, 0x8f, 0xba, 0xa4, 0x3b, 0x03, 0x0c, 0x50, 0x2e, 0x65, 0x76, 0x0c, 0x40, 0x4a, 0x4c, 0x49, - 0x99, 0xe8, 0x41, 0x44, 0xf2, 0x52, 0x08, 0xa0, 0x0e, 0x51, 0x3b, 0x0c, 0x7f, 0x65, 0x71, 0xe0, 0xc1, 0xe5, 0x2b, - 0x84, 0x40, 0xb6, 0xe4, 0x31, 0x0a, 0x41, 0x6e, 0x9d, 0x77, 0xd9, 0xf4, 0x2d, 0xf5, 0xb7, 0x9a, 0x44, 0xd7, 0x89, - 0xac, 0xee, 0xcd, 0x41, 0x78, 0x36, 0x17, 0x03, 0xb4, 0x4f, 0xf0, 0x50, 0x73, 0xde, 0x4c, 0x60, 0x7a, 0x48, 0xff, - 0xb6, 0x42, 0x2c, 0x96, 0x5f, 0xdb, 0x53, 0xf5, 0xe4, 0xef, 0x43, 0x53, 0x5d, 0x6a, 0x4f, 0xa7, 0xee, 0x77, 0x6d, - 0xc1, 0x91, 0x5a, 0x66, 0xe3, 0xca, 0xf8, 0x3c, 0xef, 0xe2, 0xfc, 0xb4, 0xb9, 0x92, 0xe8, 0xcc, 0xaf, 0xa1, 0x59, - 0x85, 0x1a, 0xf3, 0x19, 0xd8, 0xbc, 0x46, 0x34, 0x1b, 0x69, 0x18, 0x29, 0x9a, 0x67, 0x9f, 0x97, 0x2f, 0xa5, 0x03, - 0x95, 0x49, 0xf5, 0xcc, 0x2e, 0x95, 0x38, 0xdf, 0x0b, 0x4d, 0x4d, 0xb7, 0x4f, 0x77, 0x2c, 0x16, 0xef, 0x4b, 0x5a, - 0x27, 0x8f, 0xa8, 0x35, 0x06, 0xee, 0x10, 0x7a, 0x52, 0xa0, 0xb3, 0x71, 0xb8, 0x45, 0xe9, 0x2b, 0x33, 0xba, 0x2a, - 0x8b, 0xbb, 0x0c, 0x75, 0x03, 0xa1, 0x6e, 0xd5, 0x9d, 0x8c, 0x8c, 0x2a, 0xe8, 0x32, 0x3a, 0x28, 0x66, 0xa3, 0x9c, - 0x15, 0xae, 0x87, 0x0c, 0x1f, 0x06, 0x25, 0x1b, 0xe0, 0x8f, 0x27, 0xff, 0xcf, 0x2f, 0xc1, 0xa9, 0xa5, 0x87, 0x23, - 0x79, 0x0d, 0xd9, 0x31, 0x94, 0x36, 0x18, 0xa4, 0xce, 0x9b, 0x14, 0x29, 0x47, 0x4c, 0x2d, 0xf3, 0xc5, 0x72, 0x54, - 0xe1, 0x7d, 0x7a, 0x7b, 0x01, 0x0f, 0xcf, 0x34, 0x69, 0x61, 0xc4, 0x89, 0xf9, 0xb7, 0xce, 0x01, 0x36, 0xe2, 0xa3, - 0x93, 0x51, 0x50, 0x29, 0x6e, 0x78, 0x35, 0x6d, 0x83, 0x57, 0x0b, 0xfd, 0x61, 0x5e, 0x1f, 0x77, 0xd7, 0x9a, 0xf7, - 0xbe, 0x8a, 0x2a, 0xe4, 0xc4, 0xe0, 0xcd, 0x33, 0x5c, 0xf0, 0xb6, 0xc7, 0x10, 0xcf, 0xa4, 0x7c, 0x2c, 0x41, 0xe9, - 0xaa, 0xad, 0x5c, 0xf3, 0x5d, 0xcc, 0x05, 0x15, 0x88, 0xc9, 0xa2, 0x7a, 0x55, 0xe3, 0xf3, 0xf7, 0x5e, 0x7e, 0xe6, - 0x48, 0x2f, 0x49, 0x90, 0xfa, 0x76, 0xa1, 0xb5, 0x06, 0xd1, 0xde, 0x32, 0xa7, 0x63, 0x2c, 0x79, 0xf5, 0x40, 0xa6, - 0x18, 0xab, 0x8f, 0xcf, 0x6d, 0xbd, 0x59, 0xd3, 0x3d, 0x1d, 0xf6, 0xe8, 0xff, 0x64, 0xf3, 0xd8, 0xa6, 0xe1, 0xe2, - 0x15, 0x57, 0x39, 0x48, 0x71, 0x03, 0xc8, 0xc3, 0x79, 0x2c, 0xe8, 0xcd, 0x35, 0xaf, 0x63, 0xc6, 0xcd, 0x5e, 0x60, - 0x6a, 0x13, 0xd9, 0x77, 0x6f, 0x5e, 0xcf, 0xaa, 0xc4, 0x99, 0x95, 0x35, 0x96, 0xa2, 0x24, 0x83, 0x32, 0xaf, 0x03, - 0x88, 0x12, 0xca, 0xa5, 0x63, 0x57, 0x22, 0xb2, 0xed, 0x79, 0xb6, 0x78, 0x77, 0x1e, 0x1a, 0xc6, 0x7a, 0x89, 0x8f, - 0xe9, 0xd7, 0x0b, 0x8c, 0x5b, 0x6e, 0x81, 0x5e, 0x74, 0x1d, 0xdc, 0x11, 0x27, 0x25, 0x0c, 0x51, 0xa4, 0xf1, 0x2f, - 0x75, 0xa4, 0x5c, 0x34, 0x9b, 0x0b, 0x16, 0x26, 0x52, 0xca, 0x56, 0x9b, 0x04, 0x6b, 0xd2, 0x66, 0xed, 0x39, 0xb1, - 0x28, 0x59, 0x0e, 0x08, 0x65, 0x63, 0xc8, 0x5d, 0x2f, 0x01, 0x66, 0x7d, 0x9f, 0x97, 0x91, 0x5d, 0x61, 0x13, 0x4b, - 0xf9, 0x07, 0x2d, 0xc4, 0x6b, 0x20, 0x1d, 0xfd, 0x43, 0xea, 0xf0, 0xd5, 0x94, 0xd6, 0xd2, 0x84, 0xba, 0x0b, 0xe1, - 0xad, 0x52, 0x00, 0x25, 0xca, 0xb2, 0x3e, 0x95, 0x00, 0x06, 0x31, 0x29, 0xa8, 0x42, 0x2c, 0x97, 0x2b, 0x4c, 0xe7, - 0x45, 0xb4, 0xe2, 0x5e, 0x36, 0x58, 0x3e, 0x95, 0xf4, 0xe1, 0x68, 0xa2, 0x72, 0xab, 0xbb, 0xed, 0xa0, 0x38, 0x60, - 0x64, 0xae, 0x3f, 0xa7, 0xc9, 0x3b, 0xf7, 0xd7, 0x03, 0xfd, 0x89, 0x00, 0x7e, 0x4e, 0x1c, 0x07, 0x97, 0x4f, 0xbe, - 0x4b, 0x35, 0x5b, 0x5d, 0xdd, 0xe3, 0x8e, 0xed, 0xd7, 0xf2, 0x0b, 0xc4, 0xc2, 0x49, 0x48, 0x74, 0x97, 0x93, 0x26, - 0xd8, 0xbc, 0xbf, 0x86, 0x64, 0x93, 0x30, 0x8d, 0x17, 0x0e, 0xca, 0x9a, 0xcf, 0x97, 0xe1, 0xa2, 0xb5, 0x15, 0x4c, - 0xf4, 0x41, 0xba, 0x57, 0xde, 0xcc, 0xe9, 0xad, 0x66, 0xc7, 0xc4, 0x52, 0x44, 0x36, 0xd5, 0xed, 0x27, 0xa7, 0x7b, - 0x43, 0xcc, 0xc0, 0xbe, 0x6f, 0x24, 0x4e, 0x61, 0x61, 0x68, 0x56, 0x88, 0x32, 0xf8, 0xa2, 0xe4, 0x24, 0x93, 0xa9, - 0xa5, 0x16, 0xb7, 0x95, 0x02, 0xca, 0x5e, 0xf8, 0x8f, 0x92, 0xba, 0x19, 0xed, 0xa7, 0xe4, 0x4a, 0xf7, 0x4d, 0x2a, - 0x0a, 0x78, 0x63, 0xd6, 0x78, 0x6f, 0x68, 0x6c, 0xf1, 0x15, 0x2d, 0x1e, 0x07, 0x83, 0x22, 0x19, 0x88, 0x85, 0x25, - 0x4d, 0x3a, 0xe5, 0xc3, 0x28, 0x26, 0xdc, 0x24, 0x5a, 0x10, 0x32, 0xf9, 0xee, 0x1d, 0xf6, 0x8e, 0x4d, 0xfb, 0x00, - 0x0a, 0xd3, 0x51, 0x75, 0xba, 0xf2, 0x8a, 0x76, 0xf0, 0xeb, 0x2c, 0x59, 0x22, 0xe1, 0x49, 0x5d, 0xee, 0x30, 0xd6, - 0x20, 0xa4, 0x45, 0xac, 0xca, 0x99, 0x0a, 0x6a, 0xcf, 0xf4, 0xb6, 0x76, 0x02, 0xef, 0x56, 0x4d, 0xcb, 0xb3, 0x72, - 0x80, 0x1b, 0xe7, 0x9b, 0x32, 0x18, 0x15, 0x89, 0x7a, 0x10, 0x28, 0x13, 0x94, 0x44, 0xa7, 0xd1, 0xa1, 0xf2, 0x4c, - 0x1c, 0xc4, 0x6e, 0x03, 0xfa, 0xbd, 0x66, 0x0e, 0x8e, 0x46, 0xf7, 0xf9, 0x2f, 0xfc, 0xc1, 0x3f, 0x71, 0x95, 0x7e, - 0xd1, 0x89, 0xca, 0x4a, 0x8b, 0xa4, 0x9a, 0x02, 0xf8, 0x7b, 0xdc, 0xf9, 0xf8, 0x7e, 0xa8, 0x30, 0xba, 0xb0, 0x73, - 0xf1, 0x4e, 0x97, 0xf9, 0xf3, 0x33, 0xf8, 0xf5, 0xf9, 0x79, 0xcd, 0x93, 0x2e, 0x3a, 0xda, 0x0e, 0x5d, 0x86, 0x8d, - 0x88, 0x12, 0x18, 0xaf, 0xae, 0x51, 0x48, 0x09, 0xb2, 0xfc, 0x00, 0x06, 0x1f, 0xdf, 0x1a, 0xe5, 0x3e, 0x95, 0x55, - 0xa0, 0x10, 0xf2, 0x56, 0xe9, 0xb0, 0x16, 0x71, 0x3e, 0xb0, 0x59, 0x54, 0x41, 0xef, 0x77, 0xe8, 0x52, 0xff, 0x54, - 0xf8, 0xf2, 0x6a, 0x3e, 0xf0, 0x0d, 0x4e, 0x27, 0xf0, 0xb0, 0xdc, 0x79, 0x2f, 0x83, 0x71, 0xc8, 0x59, 0x3f, 0x32, - 0xba, 0x77, 0x8a, 0xd9, 0x28, 0x33, 0xed, 0x78, 0x10, 0xb9, 0x74, 0xea, 0x3a, 0xc6, 0x33, 0x37, 0xca, 0x01, 0x8f, - 0xae, 0x37, 0x77, 0x98, 0x34, 0x52, 0xb4, 0xaa, 0x49, 0x5f, 0x6f, 0x89, 0x76, 0x43, 0xf3, 0xe1, 0x78, 0x80, 0x2c, - 0xa4, 0x3b, 0x8c, 0x9c, 0x39, 0xf4, 0xda, 0xd0, 0x3e, 0xcb, 0x20, 0xc3, 0x8d, 0xf3, 0x71, 0xaf, 0x9e, 0xc2, 0x29, - 0xc4, 0x71, 0x3e, 0x52, 0xa9, 0x4c, 0xe6, 0x8b, 0xcd, 0xd7, 0x00, 0x62, 0x33, 0x3d, 0x52, 0x93, 0xab, 0xa6, 0xef, - 0x4c, 0x09, 0xa2, 0x14, 0x09, 0xbf, 0xcd, 0x1c, 0xaf, 0xb8, 0x00, 0x9e, 0x19, 0xb0, 0x09, 0xad, 0x73, 0xe3, 0xaa, - 0xc0, 0xc3, 0xb4, 0xb8, 0x3f, 0x8a, 0xff, 0x09, 0xea, 0x89, 0x2e, 0xbf, 0xc1, 0x8c, 0x8d, 0x37, 0x8b, 0x57, 0xff, - 0x7a, 0x99, 0xfb, 0xfc, 0x15, 0x3f, 0x4a, 0xd6, 0xeb, 0xfb, 0xf1, 0x4d, 0xab, 0x87, 0xad, 0xe0, 0x1b, 0x85, 0x03, - 0x6c, 0x7a, 0x34, 0x3f, 0xee, 0x74, 0x0b, 0xfa, 0xb3, 0x3a, 0x20, 0xf4, 0xdd, 0x39, 0x9b, 0xf0, 0xe5, 0xe2, 0x42, - 0x9b, 0xd1, 0x5c, 0x5e, 0x06, 0xc5, 0xbe, 0x46, 0x50, 0x43, 0x4e, 0x6b, 0x46, 0x36, 0xce, 0x27, 0x53, 0xb8, 0x5c, - 0x26, 0x99, 0xdb, 0x2d, 0xd0, 0x17, 0xa0, 0x2b, 0xe5, 0xab, 0x75, 0x65, 0x43, 0xcd, 0xfc, 0x60, 0x86, 0xaf, 0xf6, - 0xe3, 0x33, 0x34, 0x5e, 0x5a, 0xda, 0xab, 0xf9, 0x18, 0x49, 0x5b, 0xaf, 0xba, 0x8e, 0xd0, 0x93, 0xad, 0xa2, 0xc6, - 0x93, 0xc2, 0x77, 0x2d, 0x06, 0xf4, 0x0e, 0x2c, 0xcf, 0x49, 0xed, 0xa6, 0x69, 0xb7, 0x18, 0x0d, 0xdb, 0x33, 0xaa, - 0xa1, 0x60, 0x3b, 0x77, 0xfd, 0xcc, 0x1e, 0x66, 0x73, 0x77, 0x35, 0xb7, 0xfc, 0x2a, 0xc0, 0x66, 0x1a, 0x28, 0xc7, - 0x61, 0x6d, 0x4d, 0xa7, 0x28, 0x89, 0x61, 0x50, 0x9a, 0x2a, 0x0a, 0x40, 0x05, 0xf0, 0x97, 0x69, 0x76, 0xe4, 0xa4, - 0xff, 0x7e, 0xbc, 0xe1, 0xf6, 0xc6, 0xc4, 0x62, 0x14, 0x3d, 0xff, 0x68, 0x46, 0xe0, 0xf4, 0x73, 0x8b, 0xee, 0x78, - 0xa8, 0xb8, 0x7d, 0x05, 0xcd, 0xeb, 0x9f, 0xe1, 0xcb, 0x67, 0xfe, 0xe5, 0x94, 0x97, 0x3f, 0xfd, 0xa7, 0x3c, 0x85, - 0x8f, 0xcf, 0x58, 0x30, 0x53, 0x88, 0xb9, 0x6c, 0x7a, 0xf0, 0xb2, 0x40, 0x17, 0x7a, 0x6b, 0x49, 0x35, 0x46, 0xd6, - 0x9b, 0xb5, 0x6e, 0x74, 0x9c, 0xb1, 0x59, 0xf1, 0x7b, 0xe2, 0xf6, 0x71, 0xa3, 0xb5, 0x2e, 0x27, 0x33, 0x58, 0xfe, - 0x0f, 0xe4, 0x10, 0x31, 0xd8, 0x3c, 0x7e, 0xf0, 0x03, 0xae, 0x1d, 0xfd, 0x7d, 0x1f, 0x96, 0xda, 0x4b, 0xe8, 0xe9, - 0xb9, 0xb8, 0x7c, 0x3d, 0x67, 0xcb, 0xf5, 0x9c, 0x2f, 0x97, 0x73, 0x79, 0x79, 0x39, 0x57, 0x1e, 0x5e, 0xed, 0xfb, - 0xd1, 0x82, 0x22, 0xad, 0x59, 0xe9, 0x81, 0x73, 0xc8, 0x75, 0xcb, 0x2c, 0x77, 0xb6, 0x52, 0xcf, 0xf8, 0x57, 0xb0, - 0xed, 0xbf, 0x34, 0x79, 0x70, 0xa3, 0x38, 0x93, 0x65, 0x5e, 0x6f, 0x58, 0x57, 0x3b, 0x34, 0x6b, 0x09, 0x96, 0x24, - 0xce, 0x1b, 0xaf, 0x7b, 0x97, 0x5d, 0x1a, 0x0e, 0x1b, 0xbd, 0x79, 0x36, 0x82, 0xd7, 0xc6, 0x08, 0xf9, 0xfd, 0x39, - 0x3b, 0x44, 0x0b, 0x24, 0x15, 0x6a, 0x46, 0xed, 0x70, 0x66, 0x8a, 0x34, 0x59, 0x12, 0x44, 0xcb, 0x9e, 0x7c, 0x9e, - 0x4e, 0x5e, 0x33, 0xde, 0x1d, 0xe9, 0xa0, 0x71, 0x1d, 0x46, 0x8c, 0xb2, 0xba, 0x9b, 0x4b, 0x0a, 0xbc, 0x0f, 0xec, - 0x54, 0xce, 0x9d, 0x70, 0x35, 0x45, 0x8f, 0x6f, 0x5a, 0x4e, 0x0b, 0x5a, 0x6f, 0xc6, 0xf2, 0x74, 0xa4, 0x1b, 0xe0, - 0x25, 0x75, 0xe7, 0xe5, 0x2e, 0xf8, 0x95, 0x51, 0x69, 0x23, 0x75, 0x4e, 0x75, 0x6e, 0xda, 0x94, 0x54, 0x5e, 0xfd, - 0xa6, 0x30, 0x88, 0xe1, 0x35, 0x9f, 0x55, 0xc2, 0x4b, 0xb3, 0x17, 0x4d, 0x0d, 0x2a, 0x0d, 0xa1, 0xb2, 0x2f, 0xd4, - 0x4e, 0x9c, 0xe5, 0x23, 0xa2, 0x92, 0xc8, 0xc7, 0x0f, 0xea, 0x6b, 0x25, 0x14, 0x6c, 0x83, 0x5c, 0x60, 0xe2, 0xb2, - 0x61, 0x89, 0xff, 0x7b, 0x33, 0x94, 0x64, 0xb3, 0x7f, 0x3f, 0x2f, 0x37, 0x83, 0x67, 0x25, 0xf4, 0x9d, 0xa6, 0x56, - 0xe8, 0x63, 0x05, 0xc1, 0x2f, 0x1b, 0xa2, 0x5d, 0x46, 0xb0, 0xc3, 0x9c, 0x40, 0x09, 0x08, 0xa9, 0xbf, 0x60, 0x71, - 0xb6, 0x6d, 0x0d, 0x90, 0x81, 0x15, 0x99, 0xf0, 0x9a, 0xc9, 0xd1, 0x56, 0x9d, 0x8f, 0x23, 0x83, 0xeb, 0x1b, 0xd9, - 0xb7, 0xf9, 0x75, 0xb5, 0x32, 0xd1, 0xf7, 0x57, 0xab, 0xd9, 0x04, 0x18, 0xf9, 0x7b, 0xf6, 0x27, 0x73, 0x5b, 0x97, - 0xfe, 0xe7, 0x4b, 0x20, 0x85, 0x8d, 0x68, 0x7a, 0x57, 0x1e, 0x81, 0x7b, 0x3b, 0xe1, 0xbd, 0xfd, 0x8e, 0x0c, 0xd6, - 0xde, 0x5b, 0xcc, 0xc9, 0xa2, 0xdc, 0x9f, 0x34, 0xf1, 0x06, 0xa4, 0xc1, 0xf9, 0x4b, 0x82, 0x6d, 0xb7, 0x86, 0xd6, - 0xed, 0x6b, 0x38, 0xdb, 0x3f, 0x72, 0x2d, 0x82, 0x06, 0x81, 0xee, 0x28, 0x2a, 0x41, 0x73, 0xc0, 0x1b, 0x39, 0x3b, - 0xe2, 0xe5, 0x44, 0x54, 0x13, 0x93, 0xa0, 0x87, 0x79, 0x43, 0xd6, 0xf9, 0xf7, 0x90, 0xbc, 0x17, 0x12, 0x10, 0xb1, - 0xbf, 0x52, 0x31, 0x0a, 0x70, 0x41, 0x7b, 0x69, 0x77, 0xb4, 0xa1, 0x06, 0xe1, 0x22, 0x07, 0xfe, 0x3d, 0xc1, 0xd8, - 0x5d, 0x7e, 0xc6, 0xe4, 0x38, 0xe7, 0x83, 0x40, 0xf2, 0xb6, 0x7f, 0x76, 0x61, 0xf1, 0xe4, 0xcf, 0x89, 0xfc, 0xd3, - 0x23, 0xf0, 0xc1, 0xfd, 0x13, 0x3c, 0xec, 0xab, 0x2b, 0xf2, 0x62, 0xe7, 0x43, 0xd3, 0x91, 0x42, 0x6d, 0x1b, 0xf6, - 0xe1, 0x6a, 0x94, 0xb7, 0xea, 0xe2, 0xd0, 0xeb, 0xad, 0x11, 0x79, 0xfd, 0xb9, 0x18, 0xe0, 0xdd, 0xbe, 0xc4, 0xfa, - 0x6a, 0xfa, 0x01, 0x8d, 0xdd, 0x37, 0x9c, 0xd7, 0xda, 0x57, 0x48, 0xf2, 0x24, 0xbb, 0x0b, 0x4b, 0x8a, 0x20, 0x4b, - 0xf9, 0xcc, 0x5e, 0x32, 0x04, 0x87, 0xca, 0xb3, 0x7d, 0x35, 0xb3, 0x3a, 0x33, 0x16, 0xe9, 0x70, 0x2d, 0x15, 0x00, - 0x6b, 0x7b, 0x67, 0x41, 0x0f, 0x05, 0x8a, 0x17, 0xe1, 0x13, 0x96, 0x2c, 0x7e, 0x66, 0xd6, 0x95, 0x75, 0xee, 0x4a, - 0xca, 0x83, 0xe5, 0xfa, 0x04, 0x4c, 0x4c, 0xcc, 0x5f, 0xe9, 0xa4, 0x75, 0xcd, 0xf7, 0x78, 0x32, 0x8a, 0x44, 0x0f, - 0x10, 0xcb, 0x9d, 0x06, 0x02, 0xdb, 0x96, 0xd8, 0xb8, 0x77, 0xf1, 0x34, 0x50, 0xff, 0xb4, 0xa3, 0x6d, 0x53, 0xfd, - 0xc9, 0xe6, 0x9f, 0x3e, 0xab, 0xc4, 0x08, 0xae, 0xbf, 0x25, 0x64, 0x87, 0xd7, 0x12, 0x83, 0x7e, 0xb8, 0x97, 0x93, - 0xf8, 0x63, 0xe4, 0x6c, 0xc9, 0xd9, 0x2e, 0xaa, 0xc9, 0xa5, 0xc6, 0xe3, 0x4e, 0x54, 0x75, 0xaa, 0x0a, 0x87, 0x56, - 0x24, 0xc8, 0x71, 0x9f, 0x91, 0xc7, 0x0c, 0xed, 0xac, 0x34, 0x0d, 0x22, 0xaa, 0x21, 0x84, 0xc7, 0xb3, 0x82, 0x81, - 0xa8, 0x0c, 0x5b, 0x32, 0x29, 0x0e, 0x14, 0xe7, 0xa6, 0x7c, 0x90, 0x41, 0xf3, 0xf7, 0xd1, 0xf3, 0x86, 0xcc, 0xc0, - 0xbc, 0xf1, 0x79, 0x3c, 0x18, 0x7c, 0x69, 0x1a, 0x05, 0x09, 0x1f, 0xe4, 0x40, 0x5d, 0x3b, 0x9f, 0x96, 0xff, 0x0c, - 0xbf, 0x7c, 0xd4, 0xbf, 0x72, 0xca, 0xe7, 0x9f, 0xfe, 0xd3, 0x3c, 0x39, 0x59, 0xc1, 0xf5, 0x59, 0x10, 0x3d, 0xb5, - 0x1c, 0xac, 0xfa, 0xf4, 0x97, 0x24, 0x7d, 0xec, 0xac, 0x88, 0x62, 0x7b, 0x47, 0x28, 0x11, 0xff, 0xc8, 0x39, 0xe2, - 0xb5, 0xc9, 0x1e, 0x6e, 0x6f, 0xf2, 0x84, 0x2b, 0x7f, 0x99, 0xa6, 0x3e, 0x7a, 0x80, 0x2b, 0xa2, 0xe5, 0xc6, 0x58, - 0x95, 0x26, 0x9f, 0x6c, 0x96, 0x9e, 0x44, 0x97, 0x56, 0x46, 0x1a, 0x0a, 0x6d, 0xb8, 0x0a, 0xae, 0xdd, 0x5b, 0x81, - 0xf8, 0xf6, 0xbe, 0x60, 0xbd, 0xaf, 0xe7, 0x7d, 0x90, 0x39, 0x1b, 0xa2, 0xb4, 0x64, 0x36, 0x44, 0xc7, 0xbd, 0xa0, - 0x67, 0x12, 0xa2, 0x38, 0xe8, 0x36, 0xcf, 0x24, 0xe6, 0xd0, 0xf1, 0xce, 0x08, 0x99, 0xfb, 0xea, 0x45, 0x7f, 0x53, - 0x7a, 0x41, 0x24, 0xbb, 0x81, 0x03, 0xe9, 0xc0, 0x0b, 0xe0, 0x4c, 0x2c, 0x5d, 0xba, 0x22, 0xdb, 0xdb, 0x52, 0x09, - 0xb9, 0x9c, 0xcf, 0xd4, 0x4a, 0x24, 0xcd, 0x84, 0xfb, 0xce, 0x17, 0xc6, 0xbc, 0x6a, 0x5a, 0x20, 0x5b, 0x1f, 0xbe, - 0x0c, 0x0c, 0x23, 0xa9, 0xa9, 0x3a, 0x9b, 0xed, 0x80, 0xa9, 0x2d, 0x61, 0x4a, 0xbb, 0x63, 0x34, 0x20, 0x48, 0x10, - 0x69, 0x94, 0xd1, 0xa1, 0xa0, 0xc7, 0xb0, 0x43, 0x82, 0x4e, 0x9c, 0xab, 0x14, 0x9d, 0xa0, 0xc4, 0x95, 0x17, 0x52, - 0xf4, 0xe8, 0xcd, 0x66, 0x31, 0x39, 0x71, 0x36, 0x7c, 0xa1, 0xef, 0x7a, 0xf2, 0x7a, 0x1a, 0xa4, 0xec, 0x5c, 0xe0, - 0x5e, 0xa3, 0x8b, 0x8b, 0x09, 0xf5, 0xe4, 0x78, 0x68, 0x6e, 0x98, 0xff, 0x2e, 0xc9, 0xa0, 0x0e, 0x5d, 0xc3, 0x4e, - 0xb8, 0x31, 0xa2, 0xf6, 0xba, 0x4e, 0x51, 0x6b, 0x9d, 0xd9, 0xba, 0xfb, 0xe1, 0x7c, 0x5a, 0x61, 0x52, 0xf9, 0x44, - 0x61, 0xa2, 0x49, 0xba, 0xd4, 0xa2, 0x4e, 0xd2, 0x64, 0x87, 0x12, 0x73, 0x1a, 0xa6, 0x8d, 0xd6, 0xb1, 0xd8, 0xd6, - 0x35, 0xb8, 0x90, 0xde, 0x84, 0xec, 0x4e, 0x6a, 0x82, 0x13, 0x4d, 0xfb, 0xff, 0x8f, 0xb7, 0x05, 0xad, 0x0c, 0x54, - 0x90, 0xea, 0xb9, 0x6d, 0x54, 0x17, 0xf0, 0x34, 0x73, 0x6f, 0x9b, 0x58, 0xd3, 0xbc, 0x9b, 0xc3, 0x09, 0x48, 0xc9, - 0xbd, 0x7a, 0x4b, 0xa4, 0x18, 0xc9, 0x08, 0x32, 0x88, 0xb5, 0x8b, 0x1a, 0x50, 0xc0, 0xa2, 0xba, 0x8e, 0x9c, 0x3e, - 0x84, 0x0b, 0x72, 0x63, 0xf4, 0x35, 0xb8, 0x3b, 0x70, 0x35, 0x72, 0xaa, 0x1b, 0x3c, 0xcd, 0x8d, 0x25, 0x77, 0x3b, - 0x79, 0xaa, 0x5f, 0x14, 0xe9, 0xdd, 0x2a, 0x8b, 0xd2, 0xca, 0xe1, 0x0f, 0x4d, 0xc5, 0x1f, 0xfb, 0x4a, 0x00, 0x44, - 0x77, 0xc6, 0xf6, 0xfb, 0x72, 0xe0, 0x49, 0xe7, 0xd8, 0x7a, 0x1f, 0x19, 0x70, 0x9b, 0x6b, 0xcb, 0xd6, 0xf6, 0xa9, - 0x0c, 0xc8, 0x3d, 0xe3, 0xb1, 0x74, 0x23, 0x33, 0xff, 0xfc, 0x54, 0x2e, 0xf4, 0xda, 0xa1, 0x5e, 0x80, 0x20, 0x73, - 0x9a, 0x5f, 0xd8, 0xdc, 0x3a, 0x25, 0xed, 0x28, 0x1f, 0xa8, 0x59, 0xe1, 0xe3, 0x48, 0x33, 0x3e, 0x45, 0x4d, 0x14, - 0x82, 0x9f, 0xc1, 0x17, 0x13, 0x1e, 0xf8, 0x9e, 0xef, 0xc5, 0xa8, 0xa1, 0xf7, 0xa2, 0x3f, 0x7b, 0x1a, 0xe5, 0x52, - 0x99, 0xd1, 0x75, 0x52, 0x12, 0xd3, 0x7f, 0xfc, 0x6f, 0x6e, 0xd5, 0xd4, 0x1f, 0xc5, 0x6c, 0x88, 0x7f, 0x7d, 0x4d, - 0x3e, 0x3d, 0x6b, 0xef, 0xce, 0x44, 0x42, 0x91, 0xe6, 0x9e, 0x36, 0x27, 0x3e, 0x0e, 0x14, 0xf0, 0xa7, 0xf8, 0x91, - 0xba, 0x99, 0xa4, 0x6b, 0x4d, 0x4f, 0xf3, 0xed, 0x36, 0xcc, 0xbb, 0x93, 0x7f, 0xb2, 0x01, 0xf7, 0x0b, 0xd4, 0x2a, - 0xf2, 0x76, 0x9b, 0x41, 0xdc, 0x9b, 0x89, 0xfe, 0xd5, 0x83, 0x31, 0xc8, 0x4f, 0x17, 0x89, 0x65, 0xb9, 0x9b, 0xad, - 0x69, 0xb1, 0x56, 0xc1, 0x76, 0x15, 0xf2, 0x11, 0x2a, 0xee, 0x96, 0x73, 0x72, 0xe8, 0x19, 0x0c, 0xfb, 0xbd, 0x69, - 0x53, 0xa9, 0x5a, 0x7b, 0x55, 0x8d, 0x26, 0xbb, 0x91, 0xdc, 0xda, 0x0b, 0xdb, 0xe8, 0x47, 0xc0, 0x6a, 0xfc, 0x28, - 0x5b, 0xbc, 0x8e, 0x58, 0x4c, 0xdc, 0x65, 0x7a, 0x4a, 0x8d, 0x20, 0xf2, 0x47, 0x9f, 0x18, 0x87, 0x15, 0xd9, 0xd9, - 0xdf, 0x92, 0x90, 0xbe, 0x77, 0x70, 0x91, 0xfe, 0x4b, 0x29, 0xfb, 0x03, 0x8f, 0x49, 0xac, 0x3f, 0xdb, 0x0f, 0x25, - 0x97, 0xf0, 0x71, 0x8b, 0xf8, 0x7c, 0x06, 0xdb, 0xdb, 0xf5, 0xd6, 0x7c, 0xa1, 0x4e, 0xdc, 0x1f, 0x06, 0x1d, 0x5f, - 0x52, 0x1e, 0xd6, 0x88, 0xf0, 0xb7, 0xe7, 0x07, 0xff, 0xda, 0xbc, 0x04, 0xa1, 0xb5, 0x33, 0xde, 0xe9, 0xf7, 0x69, - 0x25, 0xcf, 0xf0, 0xd3, 0x33, 0x7f, 0x75, 0xca, 0xc7, 0x9f, 0xfe, 0xd3, 0xbc, 0xf1, 0x12, 0xd3, 0xd8, 0x7a, 0x68, - 0xb8, 0x2f, 0xc3, 0xaf, 0xd5, 0xb1, 0x17, 0x57, 0xa0, 0x27, 0x47, 0x9d, 0xf8, 0xa5, 0xa9, 0x32, 0x17, 0xe8, 0x18, - 0xcd, 0xc2, 0x73, 0x39, 0x7b, 0x61, 0x42, 0x77, 0x94, 0x4b, 0x52, 0x6d, 0xcd, 0x6a, 0x6b, 0x9c, 0xe3, 0x82, 0x22, - 0xc1, 0xbc, 0xfb, 0x4e, 0xb4, 0xe2, 0x33, 0x97, 0xff, 0x52, 0x3c, 0x33, 0xc7, 0x5a, 0x1e, 0xe6, 0x83, 0x1a, 0x5b, - 0x8a, 0x53, 0xc5, 0xc6, 0x2f, 0x7f, 0x82, 0x07, 0xac, 0x87, 0xb2, 0x0f, 0xc2, 0xd2, 0xe8, 0x0c, 0x99, 0x91, 0xa3, - 0x48, 0x9d, 0x15, 0x7e, 0xab, 0x33, 0x24, 0xde, 0x9b, 0x34, 0x9d, 0xbe, 0x16, 0xa2, 0xc4, 0x5a, 0x51, 0x9d, 0x7c, - 0xb6, 0x3c, 0x0a, 0xaa, 0xbb, 0x48, 0x5f, 0x9d, 0xa4, 0x50, 0x83, 0xe5, 0x1f, 0xe6, 0x40, 0x92, 0xcc, 0xcf, 0x35, - 0x63, 0x47, 0x44, 0x09, 0xdd, 0x50, 0x37, 0x32, 0x08, 0xb4, 0x36, 0x1b, 0x70, 0xa0, 0xc9, 0x3f, 0x75, 0x4d, 0x42, - 0x1c, 0x78, 0x73, 0xc3, 0xa0, 0x9c, 0x9b, 0x65, 0x62, 0x6c, 0x0b, 0x18, 0xef, 0x49, 0x8b, 0x63, 0xcb, 0x33, 0xb4, - 0x34, 0x86, 0x87, 0x60, 0x31, 0x83, 0xd4, 0x98, 0xf0, 0xa1, 0xa1, 0x41, 0x25, 0xff, 0xd8, 0x28, 0xcd, 0x3b, 0x5a, - 0x75, 0x95, 0x1a, 0xd1, 0xc9, 0x01, 0xa5, 0xbc, 0x14, 0x23, 0xb0, 0xce, 0x54, 0xf7, 0xe4, 0x1c, 0x42, 0x8e, 0x3b, - 0xb9, 0x4a, 0x55, 0xf8, 0x1a, 0x83, 0x75, 0x5b, 0xdf, 0x67, 0x7f, 0xbf, 0xe9, 0x47, 0x65, 0x56, 0x48, 0xf6, 0x5a, - 0xbf, 0x0c, 0xb7, 0x7b, 0x5a, 0x2c, 0x9a, 0x5a, 0x77, 0xce, 0x90, 0x23, 0x4d, 0x84, 0xfd, 0x29, 0x9f, 0x00, 0x2a, - 0x41, 0xa4, 0x00, 0xc3, 0x66, 0xd5, 0xef, 0x11, 0x3d, 0xfb, 0x21, 0x2e, 0x1e, 0x28, 0x9e, 0xb5, 0xaf, 0x88, 0xd9, - 0x24, 0x58, 0x0d, 0xff, 0xef, 0x7d, 0x8a, 0xe1, 0xe1, 0x76, 0x39, 0xdc, 0x23, 0xfb, 0xd6, 0x39, 0x60, 0x9c, 0x7e, - 0x64, 0x43, 0xe3, 0x8f, 0x42, 0xe6, 0x80, 0xa6, 0xb4, 0x1b, 0x9c, 0x1c, 0xc9, 0x37, 0xdb, 0x20, 0xc5, 0x56, 0x26, - 0xda, 0xd9, 0x20, 0x1e, 0x4c, 0xa7, 0x2d, 0x84, 0x58, 0xae, 0x80, 0x86, 0x68, 0x68, 0x86, 0xf3, 0x2e, 0x7a, 0x24, - 0x87, 0xe7, 0x73, 0xf1, 0x80, 0x1f, 0x09, 0xa9, 0x00, 0xce, 0x45, 0x4d, 0x14, 0x79, 0xea, 0xcc, 0x89, 0x47, 0xdb, - 0x1c, 0x0f, 0xd3, 0xb0, 0x35, 0x82, 0x67, 0x27, 0x0f, 0x9a, 0x9f, 0x34, 0xb4, 0xed, 0x41, 0x3a, 0xcc, 0x12, 0x40, - 0x8d, 0xc9, 0xea, 0x78, 0x91, 0xb4, 0x17, 0xed, 0x2f, 0x27, 0x82, 0x19, 0x6d, 0xb9, 0xd3, 0x93, 0x0f, 0x9b, 0xa9, - 0x17, 0xef, 0x07, 0x05, 0x3b, 0x0d, 0xab, 0x56, 0x54, 0xc6, 0x6e, 0x1f, 0xfa, 0xba, 0x87, 0x57, 0x06, 0xc3, 0xf2, - 0x1e, 0x81, 0x16, 0x24, 0xf3, 0xd1, 0x47, 0xd9, 0x80, 0x8b, 0x3b, 0x7c, 0xd4, 0x80, 0x84, 0x8c, 0x87, 0xe5, 0x2c, - 0xf5, 0xc8, 0xea, 0x73, 0x07, 0xd4, 0xbc, 0xa9, 0x9d, 0x3d, 0x72, 0xc4, 0xe7, 0x90, 0x91, 0xec, 0x9f, 0x18, 0xf9, - 0xf0, 0x6d, 0x7c, 0x66, 0x81, 0x53, 0xc4, 0x85, 0xe8, 0xa1, 0xa3, 0xc2, 0xd4, 0x02, 0x0d, 0x3d, 0x85, 0x92, 0x09, - 0xe7, 0x31, 0xd5, 0x16, 0x16, 0xc7, 0xb5, 0x32, 0x2b, 0x89, 0xe9, 0xb5, 0x15, 0xca, 0xa8, 0x15, 0x1e, 0x4f, 0x4f, - 0xae, 0x28, 0x33, 0x69, 0x7c, 0xf0, 0x47, 0xc6, 0xc8, 0x84, 0x8c, 0xab, 0x0e, 0x6d, 0xc9, 0x8d, 0xc0, 0x5b, 0x10, - 0x49, 0xa6, 0x20, 0x9b, 0xc4, 0xc3, 0x04, 0x77, 0x76, 0x4f, 0x74, 0xa7, 0xac, 0x87, 0xe4, 0x2e, 0xdc, 0x2d, 0xb0, - 0x40, 0x9d, 0x7c, 0x30, 0x12, 0x73, 0x1e, 0xa7, 0xbd, 0xc7, 0xdf, 0x33, 0xb5, 0xe4, 0x22, 0x27, 0x92, 0xce, 0xe3, - 0x87, 0x2e, 0x08, 0x5c, 0x82, 0x3e, 0x2c, 0xf9, 0x1a, 0x4f, 0xcb, 0xe1, 0xbc, 0x8b, 0xbf, 0xb8, 0x1a, 0xfa, 0x46, - 0xae, 0x23, 0xb1, 0x46, 0xcc, 0x49, 0x35, 0x52, 0x5f, 0x14, 0xcb, 0xc0, 0x0e, 0x18, 0x13, 0xa1, 0xd1, 0x31, 0xd3, - 0xa1, 0xe5, 0x82, 0xc9, 0x54, 0x43, 0xc1, 0x2b, 0x9d, 0x59, 0x83, 0x56, 0x42, 0xbc, 0xd0, 0x8c, 0xd2, 0x88, 0x3e, - 0x30, 0x9e, 0x77, 0x0a, 0xc2, 0xb2, 0xa6, 0xc3, 0x6c, 0x3f, 0x0f, 0x7d, 0xdf, 0x80, 0x5a, 0xbd, 0xec, 0x29, 0x06, - 0x52, 0x64, 0x96, 0x28, 0x54, 0x42, 0x97, 0xc0, 0x6b, 0x14, 0x82, 0x76, 0xf6, 0xfd, 0x8d, 0x23, 0xca, 0x5b, 0xff, - 0x14, 0xe7, 0x75, 0x96, 0x7f, 0x45, 0x94, 0xf7, 0x6a, 0xfd, 0x6e, 0x18, 0x5b, 0xdd, 0x38, 0x0e, 0xbb, 0xf5, 0x4f, - 0x1d, 0xaa, 0xd4, 0xd4, 0xe9, 0x5c, 0xdf, 0xc7, 0xec, 0x01, 0xc8, 0xcb, 0xdd, 0x9e, 0x4e, 0xc9, 0x30, 0x27, 0x1a, - 0x94, 0x95, 0xb9, 0xca, 0x82, 0xf1, 0x2d, 0x17, 0x5b, 0x75, 0x70, 0x0e, 0xf1, 0x91, 0xd5, 0x35, 0x2e, 0x84, 0xae, - 0x32, 0x3f, 0x9e, 0x0f, 0xca, 0x2d, 0x29, 0xb9, 0x7e, 0x86, 0xfa, 0x99, 0x04, 0xca, 0x45, 0x98, 0x26, 0x50, 0xdc, - 0x89, 0xd1, 0x26, 0xd0, 0x55, 0x37, 0x50, 0xc5, 0x91, 0xfa, 0xfa, 0xd9, 0x87, 0x5b, 0x44, 0xd4, 0x1c, 0xf5, 0xb5, - 0x92, 0x99, 0x14, 0x53, 0xd0, 0xac, 0xcb, 0xc7, 0x97, 0xde, 0x18, 0xd6, 0xa2, 0xdb, 0x16, 0xe7, 0x00, 0x64, 0x97, - 0x48, 0xce, 0x21, 0x70, 0xd7, 0x48, 0x56, 0xad, 0xea, 0xec, 0x27, 0x33, 0x1b, 0xb2, 0x0b, 0xa9, 0xfd, 0x51, 0x3d, - 0x49, 0x35, 0x73, 0xdd, 0xd7, 0x8f, 0xe9, 0xb0, 0x63, 0x33, 0x2a, 0x9b, 0xa9, 0x94, 0xd3, 0x91, 0x9d, 0xbd, 0x98, - 0x89, 0xdb, 0xa1, 0x70, 0xaf, 0x2c, 0x32, 0xe4, 0x34, 0xec, 0x2b, 0x02, 0x64, 0xcb, 0x54, 0x0a, 0xd5, 0x9d, 0x48, - 0x47, 0x2f, 0xa1, 0xe7, 0xd9, 0xd4, 0xba, 0x80, 0x50, 0x3f, 0xcc, 0x6a, 0x83, 0x53, 0x20, 0x9d, 0x5f, 0x96, 0x22, - 0x7c, 0x2e, 0x66, 0x83, 0xac, 0x89, 0x00, 0xbc, 0x38, 0xc9, 0x4c, 0x72, 0x00, 0x70, 0x66, 0xa9, 0xf0, 0xb1, 0xde, - 0x1f, 0x3d, 0x72, 0xa8, 0x9b, 0xa0, 0x21, 0xf3, 0x14, 0x79, 0xa9, 0xcc, 0x27, 0x9a, 0xba, 0x6c, 0x1d, 0xc4, 0x8c, - 0x55, 0xfc, 0x5b, 0x2d, 0xc6, 0xa5, 0x9d, 0x77, 0xdd, 0xda, 0xa2, 0xd5, 0xc4, 0x93, 0xa1, 0x14, 0xb9, 0x49, 0x4e, - 0x9e, 0x1a, 0x6e, 0xbd, 0xbb, 0x50, 0x19, 0xc0, 0xae, 0x48, 0xea, 0xfe, 0x36, 0xff, 0xf7, 0x8c, 0xe1, 0x5e, 0x7c, - 0x57, 0x65, 0xa8, 0x80, 0x8b, 0x00, 0xe9, 0x6a, 0xd9, 0x9a, 0xeb, 0xad, 0x26, 0xf8, 0x51, 0x93, 0x3e, 0xac, 0xf2, - 0x3a, 0xed, 0xe9, 0xd5, 0x50, 0x06, 0x8b, 0x41, 0x4a, 0x48, 0xab, 0xaa, 0x71, 0x93, 0x66, 0x52, 0xda, 0xbf, 0xdf, - 0xec, 0x62, 0xdb, 0xea, 0x56, 0x0f, 0xc6, 0x4d, 0x5a, 0x64, 0xb1, 0xfe, 0x20, 0xed, 0xef, 0xbd, 0xdb, 0xb5, 0x20, - 0x16, 0x27, 0x15, 0xa6, 0xc2, 0x72, 0xfa, 0xcd, 0x52, 0x6e, 0xae, 0xa4, 0x3e, 0x62, 0x7a, 0xdb, 0x95, 0x1c, 0x9f, - 0x31, 0xef, 0x2b, 0x4f, 0x75, 0xef, 0x41, 0x0f, 0x20, 0x62, 0xc6, 0xd9, 0x3c, 0x8b, 0x84, 0x76, 0xfd, 0xd7, 0x14, - 0xaa, 0xbb, 0xfa, 0xd1, 0x50, 0xb1, 0xc4, 0x20, 0x81, 0x2c, 0xf6, 0xf1, 0xa3, 0xae, 0x1c, 0x0e, 0x1e, 0x46, 0x09, - 0x02, 0xd2, 0xdc, 0x4b, 0x46, 0xd1, 0xd8, 0xc0, 0x6f, 0xbd, 0x00, 0xda, 0xbd, 0xdf, 0xda, 0x67, 0x76, 0x27, 0x5e, - 0xe9, 0x1c, 0xf5, 0x8e, 0x84, 0x13, 0x02, 0xd5, 0xc8, 0x31, 0xae, 0x3f, 0x31, 0x6c, 0xea, 0x9f, 0xda, 0x72, 0xc5, - 0x1a, 0x16, 0xbf, 0x01, 0x19, 0x54, 0x11, 0x3f, 0x40, 0xc6, 0xc8, 0x69, 0x53, 0x6c, 0x46, 0xa7, 0x7a, 0xd8, 0xe5, - 0x11, 0x5b, 0xc0, 0x8a, 0x32, 0x86, 0x4f, 0x7f, 0xaa, 0x40, 0xc1, 0xbf, 0x71, 0x05, 0x5d, 0x6d, 0xd1, 0x6d, 0xb6, - 0xc6, 0x56, 0x54, 0x0c, 0x48, 0x0d, 0xfe, 0x24, 0x56, 0x13, 0xc8, 0x16, 0x2e, 0x35, 0x75, 0x60, 0x20, 0x53, 0x86, - 0xd9, 0x40, 0xa3, 0xeb, 0x13, 0x65, 0xfc, 0xe2, 0xf0, 0xde, 0xa0, 0x8f, 0xbe, 0x6f, 0x6a, 0x05, 0x9f, 0x76, 0xae, - 0xd8, 0x5c, 0x06, 0xdd, 0x81, 0x45, 0xb0, 0xa8, 0xed, 0xc9, 0xad, 0x3e, 0x7a, 0xe0, 0x5d, 0x90, 0xe9, 0x3d, 0xa3, - 0x14, 0xab, 0xea, 0x1d, 0xc0, 0x8d, 0x6b, 0xe4, 0xea, 0x3d, 0x77, 0x3d, 0xb6, 0x55, 0x2b, 0xd8, 0x42, 0x57, 0x05, - 0xd8, 0xfd, 0x5d, 0xe1, 0x1f, 0x69, 0x9c, 0x59, 0xc8, 0xe0, 0x99, 0xf5, 0x8a, 0x42, 0x66, 0x60, 0x46, 0xe2, 0xdb, - 0xda, 0xc1, 0x32, 0xc7, 0x7a, 0x81, 0x93, 0xc1, 0x75, 0x90, 0x05, 0x36, 0x61, 0x7c, 0x6a, 0xa8, 0x47, 0xa5, 0xc5, - 0x0f, 0xaa, 0x4f, 0x38, 0xfd, 0xf2, 0xd4, 0x0a, 0x8d, 0x05, 0x9f, 0x23, 0xf3, 0xf8, 0x63, 0xe4, 0x4d, 0xb8, 0xfd, - 0xec, 0x40, 0x87, 0x04, 0xe2, 0xad, 0x79, 0x74, 0x02, 0xb4, 0x54, 0x9a, 0x91, 0xe7, 0xaf, 0x2a, 0x10, 0xf4, 0x78, - 0x16, 0x50, 0x8d, 0xb0, 0x58, 0x79, 0xe7, 0xed, 0xbf, 0x9f, 0xa1, 0x74, 0x94, 0xc1, 0x5b, 0xa9, 0xdd, 0xaf, 0x18, - 0xe3, 0x7b, 0xa1, 0x12, 0xe1, 0x33, 0x94, 0x9f, 0x9b, 0x64, 0x24, 0x53, 0x9d, 0xcc, 0x45, 0x84, 0x9e, 0x6b, 0x6f, - 0x0c, 0xab, 0xa0, 0x40, 0x56, 0x43, 0xee, 0x25, 0xa3, 0x1e, 0x97, 0x2f, 0x1e, 0x0e, 0xad, 0xed, 0x43, 0xe0, 0x7a, - 0x56, 0xa9, 0x36, 0xea, 0xfb, 0x2b, 0x24, 0xb6, 0x3a, 0xce, 0x86, 0x9f, 0x26, 0x49, 0xda, 0x47, 0xea, 0x86, 0xf7, - 0x09, 0xe1, 0x02, 0xe1, 0x45, 0x5e, 0x9d, 0xd7, 0x3a, 0xbc, 0xed, 0x31, 0xe0, 0xb7, 0x6b, 0xe8, 0x93, 0x87, 0x07, - 0xcb, 0xef, 0xd3, 0xfd, 0xb2, 0x26, 0x4d, 0x36, 0x59, 0x42, 0xcc, 0xe7, 0x2d, 0x2b, 0x7d, 0x25, 0x79, 0xe6, 0xfe, - 0xa4, 0x3f, 0x74, 0xe9, 0xd9, 0xc7, 0x58, 0x69, 0x7f, 0xb3, 0x5b, 0x6f, 0x6e, 0x77, 0x67, 0xc4, 0x67, 0xf4, 0xb2, - 0x87, 0xa8, 0x65, 0xbf, 0x30, 0xa9, 0xea, 0x40, 0x0d, 0x21, 0x40, 0x81, 0x01, 0x1d, 0xce, 0x18, 0x8e, 0x25, 0x80, - 0xcb, 0xb5, 0x38, 0x02, 0x9f, 0xf5, 0x1f, 0xbf, 0x00, 0xa3, 0x55, 0x5c, 0xcd, 0x6c, 0xf5, 0x56, 0x20, 0x2c, 0x21, - 0xb2, 0xc1, 0x43, 0x85, 0x7f, 0xe6, 0xb7, 0x01, 0xdc, 0x04, 0x42, 0x4d, 0xa8, 0x85, 0x27, 0x5f, 0x84, 0x14, 0x48, - 0x0f, 0x7f, 0x73, 0x01, 0x67, 0x83, 0x8a, 0xf7, 0xb7, 0x82, 0xb2, 0xe5, 0xa0, 0xf1, 0xfc, 0x57, 0x5a, 0x99, 0xd3, - 0x5f, 0xc4, 0xf1, 0x36, 0xf2, 0xd5, 0x70, 0xde, 0x86, 0x33, 0x45, 0xbe, 0xc5, 0x55, 0x66, 0x05, 0x7e, 0x73, 0x63, - 0x5b, 0xb0, 0x47, 0xd4, 0x39, 0x20, 0xa9, 0x8b, 0x08, 0xa6, 0x1c, 0x43, 0xa2, 0xbf, 0x6c, 0x2f, 0x52, 0xfd, 0xfe, - 0x0c, 0x72, 0x2c, 0xe8, 0xbf, 0x18, 0x27, 0xce, 0x1c, 0x21, 0xca, 0x1e, 0xcf, 0x21, 0x19, 0x5b, 0xb9, 0x0d, 0xca, - 0xaf, 0x00, 0x21, 0x32, 0xe1, 0xb2, 0xc4, 0x48, 0xfd, 0xfb, 0xf7, 0x7a, 0x51, 0x16, 0x36, 0x3f, 0x67, 0xf8, 0xc9, - 0xaf, 0xa5, 0xfe, 0x51, 0xf1, 0x1c, 0x33, 0x53, 0x79, 0x31, 0xce, 0x54, 0x7f, 0xe4, 0x96, 0x7b, 0x6a, 0xac, 0x27, - 0x40, 0xc1, 0xc4, 0x39, 0x98, 0x6b, 0x70, 0xce, 0xff, 0xa3, 0x42, 0x6a, 0xcc, 0xbf, 0xe7, 0x8f, 0x2f, 0xec, 0x35, - 0xd4, 0xd5, 0x30, 0x17, 0x30, 0x02, 0x25, 0x87, 0xa1, 0x9f, 0x0b, 0x71, 0x20, 0x66, 0xff, 0x37, 0x05, 0x36, 0x5f, - 0x84, 0xc2, 0xa9, 0xfb, 0xd1, 0xa5, 0xc5, 0xd5, 0x9e, 0x4c, 0x12, 0xd0, 0xdb, 0x30, 0xce, 0x12, 0xdb, 0x1d, 0x63, - 0xf3, 0x9e, 0xc6, 0xe4, 0x59, 0x31, 0xf9, 0x0c, 0x7f, 0x7f, 0xd4, 0x8f, 0xf6, 0x94, 0x7f, 0x7e, 0xfa, 0x4b, 0xff, - 0xf6, 0xaf, 0x79, 0xee, 0x10, 0x67, 0xb1, 0xc3, 0x97, 0x43, 0xc6, 0xe2, 0xdd, 0x5e, 0x65, 0x67, 0xc5, 0xe4, 0xa3, - 0x6d, 0xf4, 0xe9, 0x77, 0xd7, 0x1f, 0x0f, 0xf1, 0xb6, 0xd0, 0xd2, 0xcc, 0x24, 0x75, 0x6e, 0x6e, 0x2a, 0x7d, 0xc9, - 0xed, 0x2e, 0x99, 0x04, 0xa4, 0x41, 0x46, 0x65, 0x31, 0xb5, 0x25, 0xd2, 0x58, 0x73, 0x05, 0xad, 0x82, 0xa1, 0x35, - 0xc7, 0x51, 0xf7, 0x25, 0x0a, 0xc0, 0x38, 0xaf, 0x10, 0x6d, 0x7a, 0x42, 0x65, 0x63, 0x83, 0x8d, 0x80, 0x33, 0xc8, - 0x30, 0x86, 0x8b, 0xbd, 0x96, 0xbc, 0x27, 0xd8, 0x46, 0xd2, 0x90, 0xe2, 0x4f, 0x65, 0xe3, 0x68, 0x8a, 0xeb, 0x6a, - 0x7c, 0xbd, 0xff, 0xa8, 0x1a, 0xa7, 0x18, 0x25, 0xbc, 0x29, 0xef, 0x48, 0x5a, 0x4d, 0x51, 0x82, 0x16, 0x22, 0x73, - 0x3b, 0x62, 0x16, 0xdc, 0x69, 0x5c, 0x8e, 0x03, 0x59, 0xa7, 0x6b, 0x3a, 0x1d, 0x65, 0x1c, 0x38, 0xb5, 0xca, 0xe8, - 0x9c, 0x20, 0xe9, 0xb5, 0xb8, 0xaa, 0x81, 0x72, 0xb2, 0x8c, 0x79, 0x0b, 0x3c, 0xfb, 0xd8, 0x39, 0xbe, 0x49, 0xa9, - 0xf3, 0x93, 0xd8, 0xf3, 0xf6, 0xe0, 0xfe, 0xe6, 0xf1, 0x6d, 0x7a, 0x34, 0x63, 0xd7, 0x84, 0x75, 0x3d, 0x5e, 0x53, - 0x42, 0xa8, 0x04, 0xea, 0x08, 0x10, 0xc6, 0xce, 0x1a, 0xd8, 0xd7, 0x21, 0xb3, 0x80, 0x96, 0xad, 0xff, 0xaf, 0x43, - 0x8e, 0x88, 0x40, 0xa3, 0x3f, 0x83, 0x42, 0xd2, 0x43, 0x99, 0xec, 0x0d, 0xf2, 0x5e, 0x0b, 0xfb, 0xcc, 0x1a, 0xd4, - 0x69, 0xc1, 0x8d, 0x40, 0x90, 0x74, 0xcb, 0xcc, 0x4d, 0x74, 0x3a, 0xcb, 0x4f, 0x2c, 0x3f, 0xc6, 0xb4, 0xe6, 0xbf, - 0x31, 0xa3, 0x9d, 0x93, 0xa7, 0xd3, 0xc2, 0x6a, 0x43, 0x81, 0x9b, 0x50, 0xaa, 0xd9, 0x32, 0x67, 0x5c, 0x83, 0xd2, - 0xa7, 0x69, 0x42, 0x37, 0x86, 0x4f, 0x43, 0xd6, 0x9f, 0xe4, 0x3d, 0xda, 0xba, 0x3e, 0x74, 0xcb, 0xb5, 0xa1, 0x6c, - 0xd6, 0x8d, 0xd8, 0xce, 0x0f, 0x6f, 0xa8, 0x8f, 0xc9, 0x22, 0xd0, 0x7d, 0x86, 0x5f, 0x3f, 0xea, 0x20, 0xa7, 0x7c, - 0xf9, 0xe9, 0x3f, 0xe5, 0x85, 0xee, 0x43, 0x28, 0x6a, 0x99, 0x82, 0x4f, 0x64, 0x3e, 0x1e, 0x1d, 0x65, 0xb3, 0x45, - 0xa6, 0x7e, 0xf5, 0xb9, 0x40, 0x9e, 0xbe, 0x5b, 0xb8, 0x17, 0xdf, 0xf2, 0x58, 0xdb, 0x8b, 0x03, 0x72, 0x91, 0x1b, - 0x09, 0xd0, 0x2b, 0x5b, 0x04, 0xf8, 0x83, 0x4a, 0x5d, 0x03, 0xfa, 0xca, 0xe7, 0xa0, 0x32, 0x80, 0xb2, 0xf2, 0x90, - 0x01, 0x0b, 0x9c, 0xc9, 0x01, 0x1f, 0x77, 0x94, 0xea, 0xa6, 0xf5, 0x9a, 0x85, 0x32, 0x01, 0x0b, 0x7e, 0xf1, 0xd4, - 0x91, 0x29, 0x4f, 0xd3, 0xa9, 0xfc, 0x0f, 0x97, 0x86, 0x69, 0x18, 0xe3, 0x52, 0x2b, 0xc5, 0x23, 0xcb, 0x17, 0x2d, - 0x99, 0x8b, 0xef, 0xfb, 0x38, 0xbb, 0xcc, 0x94, 0x3c, 0x5e, 0xd2, 0x6f, 0xb3, 0x33, 0xdd, 0x2b, 0x2d, 0xe5, 0x49, - 0x4b, 0xd1, 0x54, 0x7f, 0xf4, 0x17, 0x51, 0x89, 0x0f, 0xf8, 0x12, 0x90, 0x70, 0xce, 0x07, 0xd5, 0x1c, 0xcd, 0x14, - 0xf5, 0xf9, 0x01, 0x6e, 0x1b, 0x39, 0xdb, 0x37, 0xcb, 0x00, 0x1f, 0x0f, 0x45, 0xd9, 0xdb, 0x12, 0x52, 0x59, 0x76, - 0xf4, 0xc9, 0x79, 0xc9, 0x03, 0x65, 0x73, 0x05, 0x01, 0x8d, 0x08, 0xb1, 0xb7, 0x99, 0x87, 0xc4, 0x21, 0x50, 0xbd, - 0x43, 0x7f, 0x57, 0xf4, 0x51, 0x8a, 0x03, 0xe7, 0x7a, 0xbe, 0x65, 0xdd, 0x7e, 0xb6, 0x88, 0x3d, 0x27, 0xb6, 0x5a, - 0xab, 0xa4, 0x1c, 0x38, 0x74, 0xbb, 0x21, 0x5e, 0xba, 0x7f, 0xbf, 0x4e, 0x70, 0x72, 0x2e, 0xed, 0x97, 0x7b, 0x34, - 0x07, 0x04, 0x7d, 0xc0, 0xe2, 0xcf, 0x50, 0x92, 0xbe, 0xb5, 0xee, 0xee, 0xb4, 0xbb, 0x7b, 0xb4, 0x75, 0x5b, 0x1f, - 0x0e, 0xc1, 0x78, 0x8b, 0xd4, 0x3a, 0x33, 0x37, 0xfa, 0xb1, 0xec, 0x38, 0xe7, 0xe5, 0x75, 0xea, 0xa6, 0x76, 0x87, - 0xf2, 0x82, 0x44, 0xd7, 0x8a, 0x55, 0x94, 0x05, 0x0a, 0x46, 0xce, 0x74, 0xf6, 0x72, 0x86, 0x40, 0x82, 0x81, 0x5d, - 0x78, 0x88, 0x4f, 0xfc, 0x82, 0xee, 0x3f, 0x78, 0x6c, 0x77, 0xd3, 0x1d, 0x97, 0xc6, 0xb2, 0xc3, 0x77, 0x3b, 0xa5, - 0x2e, 0x08, 0x7a, 0xe5, 0x4e, 0x78, 0xdd, 0x63, 0xa8, 0xc9, 0x8d, 0x6b, 0x4b, 0xcd, 0x35, 0x82, 0x28, 0xde, 0x7d, - 0xce, 0x4b, 0x11, 0x4f, 0x3b, 0x50, 0x84, 0xe0, 0xf6, 0x15, 0x0d, 0xbe, 0x64, 0x34, 0x72, 0x85, 0x27, 0xe4, 0x3a, - 0xe9, 0xb3, 0xda, 0xaf, 0xb3, 0xd1, 0x03, 0x85, 0x31, 0xe1, 0x1d, 0xbd, 0x50, 0x73, 0x07, 0x5e, 0xc2, 0x36, 0x92, - 0x17, 0x70, 0xc6, 0x48, 0x54, 0xf1, 0x89, 0xc8, 0xa6, 0xd5, 0x95, 0x99, 0x81, 0x07, 0xc7, 0x4e, 0xc3, 0x30, 0x63, - 0x73, 0x9c, 0x20, 0x57, 0x1d, 0xc8, 0x8b, 0x19, 0xc1, 0x6f, 0x51, 0x19, 0x5a, 0x57, 0x93, 0xa2, 0xd0, 0xc0, 0x5a, - 0xa2, 0xff, 0x2e, 0xa8, 0xcc, 0xc3, 0x36, 0x74, 0x02, 0xb4, 0xf8, 0x4e, 0x44, 0x3f, 0xdd, 0x4d, 0xb2, 0xa8, 0xdf, - 0xb3, 0x8b, 0x86, 0x85, 0xcb, 0x80, 0x09, 0x63, 0x10, 0xd3, 0x61, 0x37, 0x5d, 0x51, 0x9b, 0x7b, 0x68, 0xbe, 0x39, - 0x41, 0x89, 0x47, 0x8b, 0x55, 0x64, 0x26, 0xb2, 0x31, 0xe3, 0x43, 0x15, 0x04, 0x45, 0x2d, 0x4d, 0x5c, 0x45, 0x88, - 0x00, 0xd6, 0x17, 0x8e, 0x4e, 0x07, 0x40, 0x80, 0x8b, 0xed, 0xb9, 0x64, 0x15, 0x2e, 0x2f, 0x2c, 0xe2, 0xe9, 0x11, - 0x1c, 0x5c, 0xff, 0xbf, 0x76, 0x17, 0xb5, 0xb4, 0xff, 0xca, 0x89, 0x5e, 0x3b, 0x7b, 0x52, 0x73, 0x9a, 0xe4, 0xa5, - 0x98, 0x9d, 0x9c, 0x1c, 0x64, 0x1e, 0xb3, 0xf8, 0xa4, 0x9e, 0x59, 0x74, 0x0c, 0xe5, 0xc1, 0x46, 0xcf, 0xd8, 0x47, - 0x97, 0x1c, 0x3b, 0xe4, 0x02, 0x8b, 0x53, 0x3e, 0x3b, 0xe1, 0x6b, 0x1e, 0x1a, 0x11, 0xcb, 0x20, 0xcc, 0x68, 0x35, - 0x81, 0xaf, 0x63, 0xec, 0xad, 0xb2, 0xe8, 0x39, 0x8a, 0x55, 0x14, 0xd0, 0x83, 0x9a, 0x1e, 0x9c, 0xba, 0x4b, 0x77, - 0xcf, 0x78, 0x09, 0xaa, 0xec, 0x28, 0x1d, 0xe2, 0xf9, 0xe3, 0xa2, 0x21, 0x82, 0x4e, 0x74, 0x66, 0x1d, 0xb3, 0xa9, - 0x94, 0xb9, 0xfe, 0x0b, 0x72, 0x1c, 0xb4, 0x7e, 0xe6, 0x2f, 0x1e, 0xe5, 0xfc, 0x74, 0x9e, 0xac, 0x5f, 0xbf, 0xe0, - 0xfc, 0xcc, 0xe5, 0xb7, 0xa3, 0x03, 0x97, 0x8f, 0x7f, 0x5d, 0x18, 0xfc, 0xc5, 0xc7, 0x33, 0x4e, 0x5f, 0xab, 0x25, - 0xbc, 0x3f, 0xe1, 0x9f, 0xe0, 0x2b, 0x9e, 0x98, 0xef, 0xa5, 0x3c, 0x4f, 0xf1, 0x45, 0x48, 0x20, 0x5f, 0x73, 0xbd, - 0x6c, 0x81, 0x28, 0x2e, 0xb5, 0x6e, 0x17, 0x82, 0x8d, 0x0a, 0x88, 0xdf, 0x4d, 0x03, 0x62, 0xb1, 0xea, 0x29, 0x6e, - 0xe2, 0x26, 0xcf, 0xd5, 0x60, 0xc6, 0x8d, 0x8e, 0x4a, 0xc6, 0x5c, 0x86, 0x06, 0x46, 0x1c, 0x93, 0x45, 0x7c, 0x26, - 0x83, 0xf0, 0x78, 0xd3, 0x95, 0x95, 0x4c, 0xa2, 0x31, 0xfa, 0xdb, 0xb4, 0xe3, 0xdb, 0x46, 0x9f, 0xde, 0x6b, 0xf4, - 0x65, 0xf3, 0x63, 0xaf, 0x1e, 0x2d, 0xdc, 0x1f, 0x5c, 0x0b, 0x36, 0x0e, 0xf2, 0xd4, 0xbf, 0xe8, 0xdc, 0x62, 0x7a, - 0x1c, 0x67, 0x1e, 0x5a, 0x23, 0xf7, 0xc1, 0x31, 0xae, 0xcc, 0xa6, 0x4d, 0x37, 0x9a, 0xd2, 0xbf, 0xb2, 0x58, 0x38, - 0xb0, 0xac, 0x73, 0x7b, 0xef, 0x3e, 0xf7, 0xa4, 0xb7, 0xee, 0x64, 0xad, 0x57, 0x39, 0x32, 0x1e, 0xbd, 0x00, 0xa2, - 0x16, 0x3b, 0xe9, 0x43, 0x5a, 0xe5, 0xce, 0xec, 0x75, 0x36, 0x00, 0xc9, 0xdf, 0x55, 0xdc, 0x39, 0x07, 0x24, 0xee, - 0x21, 0x31, 0xe9, 0x18, 0xfc, 0xba, 0x3c, 0x76, 0xef, 0x80, 0xfd, 0xf2, 0xff, 0x45, 0x46, 0xeb, 0x37, 0x2e, 0x91, - 0xc2, 0xa9, 0xe8, 0x18, 0x2b, 0x4a, 0xf8, 0x8e, 0xb4, 0x95, 0x12, 0xd5, 0x81, 0xf1, 0xf9, 0x0e, 0xc7, 0x60, 0x5f, - 0xd4, 0x50, 0x7c, 0x32, 0x0d, 0xc2, 0x87, 0xec, 0x80, 0xcf, 0x6c, 0x09, 0x11, 0x4a, 0x27, 0xdd, 0x91, 0x82, 0x02, - 0x64, 0x5c, 0x01, 0xc4, 0x0c, 0xd3, 0x86, 0x20, 0x07, 0x27, 0x0e, 0x7f, 0xe6, 0xcf, 0x1d, 0x92, 0x22, 0xdc, 0xc2, - 0xfb, 0xca, 0x04, 0xfe, 0x5a, 0xe2, 0xc7, 0x33, 0xf9, 0x63, 0x0c, 0x95, 0x57, 0x13, 0xb6, 0x73, 0xdf, 0xd7, 0xa4, - 0x74, 0x2a, 0xf3, 0x5d, 0x10, 0xb2, 0xca, 0x39, 0x5d, 0xde, 0x59, 0x9c, 0xec, 0xae, 0x6f, 0xad, 0x68, 0xb6, 0x13, - 0xf2, 0xe6, 0xb7, 0x95, 0xe8, 0x0f, 0x97, 0x2e, 0x7f, 0xfa, 0x7d, 0xff, 0x5a, 0x1c, 0xa0, 0x1a, 0x03, 0x7a, 0x1f, - 0xed, 0xc3, 0xd6, 0x7f, 0xdc, 0xbb, 0x69, 0x1f, 0xb6, 0xdb, 0x48, 0x5c, 0xc4, 0x7f, 0x42, 0x53, 0x3d, 0x0a, 0xde, - 0x6d, 0x85, 0x37, 0x0b, 0x17, 0x4e, 0x8d, 0x07, 0x7a, 0xe0, 0x32, 0x99, 0x30, 0x21, 0xf4, 0xee, 0x73, 0xb6, 0x7e, - 0xdf, 0x6c, 0x5d, 0x8c, 0x8d, 0x69, 0x6c, 0x9f, 0x8c, 0x25, 0x74, 0x23, 0x7b, 0xaf, 0x9a, 0x18, 0xba, 0xa6, 0x5b, - 0x83, 0x09, 0xfa, 0xb6, 0xe9, 0x60, 0x7f, 0x57, 0x34, 0x5d, 0x3b, 0x96, 0x19, 0xdd, 0xbc, 0x1c, 0x9b, 0x1d, 0xe9, - 0xac, 0x3d, 0xee, 0xd9, 0x78, 0xe8, 0x4d, 0x78, 0x09, 0x55, 0x3a, 0xf7, 0x12, 0xe4, 0x18, 0xee, 0x76, 0x06, 0xba, - 0x70, 0x1b, 0x47, 0x0a, 0x98, 0x12, 0x0c, 0x78, 0x08, 0x97, 0xfb, 0x22, 0xae, 0xd9, 0x9b, 0xd7, 0x3e, 0xbf, 0x9e, - 0x8c, 0x37, 0xda, 0x08, 0x17, 0x51, 0x66, 0xa0, 0x1e, 0x11, 0x75, 0x6a, 0x60, 0x85, 0xdc, 0x63, 0xc7, 0x43, 0x2d, - 0xd6, 0x5a, 0x32, 0x7b, 0xac, 0xa0, 0xc1, 0x2e, 0xa3, 0xfc, 0xd2, 0xcf, 0xcd, 0xf3, 0x6e, 0xfe, 0xd3, 0x1a, 0x4a, - 0x67, 0xf6, 0x88, 0x2b, 0x51, 0x28, 0x74, 0x9a, 0x1c, 0x68, 0x9b, 0x26, 0x3b, 0xd4, 0x9b, 0x21, 0x64, 0x83, 0xd7, - 0xba, 0xc7, 0x21, 0x4c, 0xa3, 0xa7, 0x3b, 0x7b, 0x8b, 0x7e, 0x81, 0xcd, 0x72, 0x76, 0x46, 0xda, 0xdd, 0xa8, 0x87, - 0x06, 0xc3, 0x6f, 0xc7, 0x03, 0x8e, 0x51, 0x6a, 0xad, 0x1e, 0x0a, 0x47, 0xe5, 0xab, 0x1d, 0xb9, 0x0d, 0xbc, 0x8a, - 0x7b, 0x6a, 0xda, 0x57, 0x53, 0x3d, 0x3d, 0xc8, 0x56, 0x17, 0xf7, 0x06, 0xd8, 0x48, 0x3b, 0x35, 0x1a, 0xfa, 0xc4, - 0x70, 0x88, 0xf3, 0xd8, 0xb9, 0xc8, 0xce, 0x92, 0x0e, 0x97, 0xb3, 0xda, 0xb3, 0xf1, 0xf8, 0x78, 0x22, 0x79, 0x19, - 0x77, 0x3b, 0x8f, 0xb5, 0x06, 0x06, 0x8e, 0xde, 0x37, 0x70, 0xe3, 0x4a, 0x08, 0x82, 0x1c, 0xdf, 0x97, 0xa1, 0x7c, - 0xc5, 0x82, 0xfb, 0x74, 0x77, 0xdb, 0x7d, 0x14, 0xda, 0x4e, 0x94, 0x8c, 0x13, 0xc1, 0xba, 0xa5, 0xbd, 0x6d, 0x29, - 0xd6, 0xf0, 0x9f, 0x3e, 0x64, 0xff, 0xc9, 0xdf, 0x10, 0xe5, 0xdd, 0xa0, 0xc0, 0xcc, 0xb5, 0xf0, 0x40, 0x23, 0x05, - 0x13, 0x77, 0x13, 0x14, 0x59, 0x72, 0x2f, 0x83, 0x23, 0x11, 0x51, 0xe7, 0x94, 0x78, 0x53, 0x3c, 0x67, 0x88, 0x44, - 0x36, 0xf6, 0x83, 0xe1, 0x40, 0xeb, 0x0d, 0xf4, 0x97, 0xd3, 0x4b, 0x4e, 0x77, 0x22, 0x7b, 0x8d, 0x37, 0x75, 0x20, - 0x85, 0xc0, 0x67, 0xd6, 0x3d, 0xc8, 0x78, 0x4b, 0xcb, 0x25, 0xea, 0x5b, 0x37, 0xee, 0xa4, 0x7a, 0xa8, 0xe7, 0xd1, - 0xda, 0x09, 0x2d, 0x13, 0xbc, 0x51, 0x89, 0x3f, 0x6f, 0x4d, 0xec, 0x8e, 0x6c, 0xdc, 0x28, 0x8a, 0x3b, 0xc2, 0xe9, - 0x86, 0x4c, 0x46, 0x39, 0x68, 0xfd, 0xec, 0x21, 0x21, 0x40, 0x1b, 0x8e, 0x8b, 0xac, 0x81, 0x45, 0x03, 0xdc, 0x83, - 0x1f, 0x01, 0x89, 0x45, 0x65, 0x9e, 0xa8, 0x43, 0x93, 0x3c, 0x2f, 0x99, 0xc1, 0xcb, 0x2e, 0x54, 0x72, 0xe1, 0x92, - 0x51, 0xc7, 0xb5, 0xb6, 0x94, 0xfc, 0xcc, 0xe9, 0xd9, 0x6d, 0xaa, 0x05, 0xa1, 0xe4, 0xdb, 0xbe, 0xed, 0x3a, 0x49, - 0x80, 0x0e, 0xee, 0x20, 0x09, 0x16, 0x42, 0x36, 0x6d, 0xe0, 0xda, 0xec, 0x27, 0x3e, 0x64, 0xd7, 0x29, 0x72, 0x4f, - 0x7c, 0xbc, 0x50, 0x31, 0xe2, 0x20, 0xd4, 0xbb, 0x4d, 0x80, 0x0a, 0xea, 0x7d, 0x28, 0x09, 0x82, 0xfc, 0x3f, 0x7e, - 0x50, 0xdc, 0x7b, 0x03, 0x6a, 0x7f, 0x62, 0x93, 0xbb, 0x0b, 0xdb, 0x19, 0xcf, 0xe8, 0xac, 0x67, 0xf8, 0x2f, 0xbd, - 0x13, 0xb7, 0x01}; + 0x5b, 0xa5, 0x72, 0x53, 0x82, 0x27, 0x1b, 0xbc, 0x80, 0x75, 0x03, 0x48, 0xa5, 0xee, 0x7f, 0x2b, 0x0f, 0x47, 0x11, + 0x6c, 0x9c, 0x30, 0x00, 0xbc, 0x78, 0xe3, 0x55, 0x06, 0x02, 0xe7, 0x01, 0x48, 0x39, 0xae, 0xfd, 0x5e, 0x40, 0x55, + 0x4d, 0x39, 0x3a, 0x86, 0x68, 0xb0, 0x4b, 0x00, 0x54, 0x6c, 0xdf, 0xed, 0x57, 0x28, 0x4a, 0x70, 0x44, 0x0e, 0x0a, + 0x69, 0x65, 0x69, 0xd3, 0x0b, 0x32, 0x81, 0x19, 0x99, 0x45, 0x41, 0x5c, 0x10, 0x08, 0x62, 0xa3, 0x51, 0x83, 0xcd, + 0x39, 0x4f, 0x9c, 0xe3, 0x34, 0x65, 0x23, 0x09, 0xb7, 0x1c, 0x9c, 0x0d, 0xdd, 0x8c, 0x40, 0x15, 0x18, 0xc2, 0xe1, + 0x0d, 0x6d, 0x41, 0xba, 0xf2, 0xe0, 0xce, 0x7b, 0x72, 0x4e, 0x34, 0xfe, 0x50, 0x23, 0x59, 0xda, 0x96, 0x63, 0x22, + 0x70, 0xf0, 0x6a, 0xb7, 0x8c, 0x88, 0x6e, 0x48, 0x1a, 0xf6, 0x45, 0xf5, 0xa0, 0xf6, 0x37, 0xf1, 0x4b, 0x22, 0x1c, + 0x2f, 0x73, 0x23, 0x8a, 0x31, 0x70, 0x24, 0x71, 0x67, 0x77, 0x29, 0xa1, 0x7d, 0xad, 0xb1, 0x07, 0x6b, 0x81, 0x56, + 0x9e, 0x58, 0x49, 0x4c, 0x4f, 0x54, 0x3f, 0x88, 0x99, 0x48, 0x93, 0x67, 0x63, 0xed, 0x72, 0xc1, 0x0d, 0x75, 0x3e, + 0x51, 0xff, 0x97, 0xe7, 0x7b, 0xc9, 0x07, 0xd3, 0x4d, 0xf1, 0x33, 0xbf, 0xf5, 0x5a, 0xc7, 0x8d, 0x5a, 0x44, 0x59, + 0xb7, 0xb4, 0xf1, 0x5d, 0x70, 0x1b, 0xcf, 0xdd, 0x66, 0xb5, 0xe0, 0x04, 0x41, 0x10, 0xcb, 0x00, 0xc7, 0x98, 0xa8, + 0x1f, 0x22, 0x6d, 0x84, 0x78, 0xf1, 0x7e, 0x44, 0xdf, 0xfe, 0x4b, 0xb5, 0xff, 0xfa, 0x0d, 0x7b, 0xb6, 0x6e, 0xaf, + 0x4d, 0xcf, 0xbc, 0x4d, 0x53, 0x8c, 0xb3, 0xd8, 0x7b, 0x56, 0xdb, 0x59, 0x59, 0x2a, 0x19, 0xc6, 0x3d, 0xe4, 0x45, + 0x0c, 0x01, 0x1c, 0x00, 0x1d, 0x49, 0xee, 0xa7, 0x7d, 0x9b, 0xf6, 0x9d, 0xee, 0xf3, 0xd8, 0xd6, 0x6f, 0xdb, 0x09, + 0xa9, 0x7d, 0xca, 0xc5, 0xdf, 0x31, 0x02, 0x2b, 0x31, 0x12, 0x63, 0x89, 0x96, 0xfb, 0x2a, 0x67, 0xfd, 0x79, 0x2e, + 0x37, 0x57, 0x8c, 0x46, 0x4e, 0x9e, 0x5a, 0x22, 0xb3, 0x00, 0xef, 0xa9, 0xfe, 0x18, 0x84, 0x77, 0xd9, 0xac, 0xb6, + 0xa9, 0xf6, 0x87, 0xa4, 0x14, 0x52, 0x85, 0x5d, 0x44, 0xc8, 0x19, 0x21, 0xb6, 0x92, 0xef, 0x97, 0xf6, 0x7b, 0x7f, + 0xe6, 0xfb, 0xf5, 0x0d, 0xc7, 0xb9, 0x19, 0x8e, 0x76, 0x1d, 0x86, 0x94, 0x3a, 0x29, 0xb5, 0x39, 0xb2, 0x18, 0x16, + 0x5e, 0x64, 0x69, 0x9f, 0x24, 0x5c, 0xc7, 0xff, 0x7a, 0x5f, 0x57, 0x5f, 0xbf, 0x76, 0x17, 0x2b, 0xce, 0x1d, 0x1d, + 0x29, 0x4b, 0xd8, 0xe7, 0x15, 0x37, 0x3d, 0x19, 0xc2, 0x23, 0xbc, 0x42, 0x91, 0xcc, 0x23, 0xa5, 0x72, 0x19, 0xc7, + 0xea, 0x18, 0xed, 0x1a, 0xd9, 0xa5, 0x56, 0x88, 0x8c, 0xd5, 0xf0, 0xff, 0xf5, 0x35, 0xad, 0xaf, 0x5f, 0x89, 0xb0, + 0xca, 0x5c, 0xea, 0x40, 0xa1, 0x99, 0xfd, 0x3d, 0x92, 0x9c, 0x65, 0xd9, 0x3d, 0x15, 0x82, 0x96, 0x69, 0x1b, 0x2f, + 0xe0, 0x00, 0x7a, 0xcd, 0xba, 0xf7, 0xbe, 0xaa, 0xfe, 0xfb, 0xe7, 0x0b, 0xa1, 0x3b, 0x44, 0x1b, 0xb8, 0xdc, 0x1d, + 0x26, 0x4b, 0x33, 0x6b, 0xaa, 0xe9, 0xce, 0xd8, 0x14, 0x05, 0x4a, 0x4c, 0x25, 0xca, 0x8f, 0x80, 0x95, 0x49, 0x4b, + 0x5d, 0x55, 0x94, 0xce, 0x7e, 0x48, 0x05, 0x65, 0x53, 0x36, 0x34, 0xc3, 0xb6, 0x75, 0xea, 0xfb, 0x93, 0xcc, 0xf7, + 0x13, 0x5e, 0x90, 0x8d, 0x0d, 0xcd, 0xb7, 0x2f, 0x4f, 0xd7, 0x71, 0x23, 0x2d, 0xb0, 0xc4, 0x22, 0xbd, 0x6f, 0x90, + 0x13, 0xa5, 0x12, 0xf3, 0x3f, 0xdc, 0x72, 0xe2, 0x12, 0x88, 0xd6, 0x66, 0x6f, 0x0b, 0xf1, 0x8a, 0x2f, 0x12, 0x3d, + 0x1f, 0x44, 0x3c, 0x4d, 0x2d, 0x5f, 0x6f, 0xfb, 0x25, 0x5f, 0xa5, 0x73, 0x29, 0x2f, 0xa5, 0x58, 0x49, 0x37, 0x57, + 0xba, 0xc0, 0xbb, 0xb7, 0xa9, 0x44, 0x69, 0x3a, 0xb0, 0x81, 0x1c, 0x8a, 0xa4, 0x8c, 0x2d, 0x50, 0xd8, 0x7b, 0x7f, + 0x3f, 0xfb, 0xaf, 0x5f, 0x9d, 0x5a, 0x9c, 0x39, 0x0c, 0x22, 0xde, 0x77, 0x34, 0xb0, 0x8f, 0xc7, 0x5b, 0xad, 0x1b, + 0x35, 0xc6, 0xec, 0xd2, 0xe0, 0x25, 0x51, 0xdb, 0xd3, 0x70, 0xcc, 0x65, 0x55, 0x7d, 0x8a, 0x0a, 0x8d, 0x18, 0x42, + 0x97, 0x67, 0xbf, 0xcf, 0x64, 0x1f, 0xd3, 0x0d, 0xcc, 0x60, 0xd8, 0xc8, 0x73, 0x82, 0x71, 0xbd, 0x10, 0xd1, 0xd6, + 0x60, 0xa9, 0xda, 0x8a, 0x21, 0x49, 0x97, 0xed, 0x91, 0x5d, 0x78, 0x51, 0xf6, 0x07, 0x7f, 0xeb, 0x3c, 0x3c, 0x12, + 0x95, 0x0f, 0x0f, 0xc9, 0x07, 0xd4, 0xea, 0x1b, 0x7e, 0xdf, 0xd7, 0xa6, 0x7b, 0x97, 0xc9, 0x61, 0x2b, 0xf1, 0x2f, + 0x8d, 0x52, 0x01, 0x68, 0x0b, 0xe0, 0x51, 0x80, 0x2e, 0x45, 0x3d, 0x35, 0x58, 0xfe, 0xff, 0xde, 0x4a, 0xcb, 0xed, + 0x8f, 0xb4, 0x20, 0xda, 0x01, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xca, 0x02, 0x5b, 0x0d, 0x90, 0xec, 0x71, + 0x66, 0x25, 0xad, 0xb5, 0xd8, 0x54, 0x5c, 0xf3, 0x2e, 0xf3, 0xbb, 0xe8, 0x8c, 0x1f, 0x86, 0x15, 0x26, 0xb3, 0x91, + 0xae, 0x9a, 0x65, 0x1b, 0x59, 0x4e, 0x03, 0x80, 0xe0, 0x7d, 0xef, 0xff, 0x28, 0xfc, 0xff, 0x23, 0x8b, 0xf3, 0x23, + 0xb2, 0x40, 0x45, 0x66, 0x15, 0xe7, 0x64, 0x15, 0x30, 0xa3, 0x2a, 0x90, 0x33, 0x2a, 0x80, 0x7d, 0x74, 0x40, 0x8e, + 0x13, 0xbd, 0xa6, 0xe9, 0x8e, 0x86, 0x94, 0xf7, 0x3b, 0x2d, 0x56, 0x6c, 0xca, 0xfb, 0xdd, 0x0e, 0x94, 0x35, 0x4b, + 0x69, 0xa5, 0xa3, 0xff, 0xd5, 0x99, 0xeb, 0x3f, 0xd6, 0x5d, 0x11, 0x26, 0x5f, 0x27, 0xdd, 0x30, 0x6c, 0xf1, 0xff, + 0x92, 0x41, 0x72, 0x1a, 0x60, 0x39, 0x28, 0x17, 0xe5, 0x94, 0xec, 0x32, 0x8d, 0x1d, 0xbb, 0xad, 0xc4, 0xc3, 0xc6, + 0x63, 0x5f, 0xd5, 0x1f, 0xc3, 0xef, 0xe1, 0x68, 0x41, 0x98, 0x3a, 0xd3, 0x34, 0xfd, 0x77, 0xfb, 0x63, 0xd9, 0xf7, + 0x3a, 0x3d, 0xe7, 0xe8, 0xef, 0xac, 0x42, 0x08, 0x24, 0x04, 0x14, 0x84, 0x60, 0xdd, 0xd9, 0x46, 0xb5, 0x2a, 0x5d, + 0x6d, 0xdd, 0x71, 0xd5, 0xaa, 0x69, 0xbe, 0x86, 0x3f, 0x04, 0x08, 0x81, 0x99, 0xbb, 0xc7, 0x70, 0x76, 0x39, 0x03, + 0x11, 0x09, 0xd1, 0x7f, 0x8f, 0x53, 0xca, 0x99, 0xd2, 0x83, 0xb4, 0x05, 0x42, 0xa4, 0xc6, 0x6b, 0x7b, 0xfd, 0xfd, + 0xf3, 0x78, 0xb9, 0x45, 0x74, 0x52, 0xdf, 0x2b, 0xd0, 0x1e, 0xa1, 0xed, 0x1f, 0x89, 0xa7, 0x3c, 0xe4, 0x11, 0xaf, + 0x04, 0x8b, 0x4d, 0xd2, 0xd5, 0x70, 0x9f, 0x00, 0x57, 0xf8, 0x16, 0x97, 0xb6, 0x76, 0x97, 0x9b, 0xac, 0xc5, 0x35, + 0x13, 0x6c, 0xee, 0x2c, 0x26, 0xce, 0x2d, 0x0e, 0x10, 0x4e, 0xc7, 0x88, 0xb6, 0xe0, 0x32, 0xd0, 0x1c, 0xe7, 0x0e, + 0x7e, 0xf9, 0xbc, 0x10, 0x4c, 0xa3, 0x3d, 0x94, 0x6c, 0xc7, 0x28, 0xc4, 0x14, 0x44, 0x9e, 0x17, 0xce, 0xde, 0x7d, + 0x60, 0x72, 0x3f, 0xa5, 0x62, 0x30, 0x0b, 0xa3, 0x27, 0x2c, 0x19, 0x68, 0x5a, 0x2f, 0xf9, 0x15, 0x80, 0x77, 0xf8, + 0x2e, 0x9c, 0xb0, 0x08, 0x94, 0xf1, 0xed, 0x17, 0xdc, 0x67, 0x18, 0x3f, 0x0b, 0xd3, 0xce, 0x0a, 0x75, 0xf0, 0x40, + 0xe0, 0xfd, 0xba, 0xf1, 0x8c, 0x5f, 0x28, 0x37, 0xec, 0x96, 0x61, 0xe6, 0x91, 0xce, 0x2f, 0xa7, 0xe8, 0x0a, 0x49, + 0x95, 0x0b, 0x62, 0xcf, 0x3d, 0x2e, 0xcd, 0xf9, 0x8f, 0x68, 0x79, 0x19, 0xb8, 0xa3, 0x37, 0x81, 0x98, 0xfa, 0x7b, + 0xeb, 0xaa, 0xd9, 0xde, 0x69, 0x11, 0x00, 0x48, 0xae, 0x5d, 0x1c, 0x66, 0xb4, 0x2d, 0xae, 0xaf, 0xe5, 0xd5, 0x6e, + 0xbc, 0x95, 0x7a, 0x98, 0xa0, 0x21, 0xd9, 0x30, 0x83, 0x33, 0xdb, 0x7f, 0x78, 0xf9, 0xf6, 0xda, 0x62, 0x5c, 0x46, + 0xcd, 0xfe, 0x3a, 0xad, 0x6d, 0xe8, 0x48, 0x1b, 0x90, 0xc3, 0x5d, 0xe9, 0xfa, 0x90, 0x52, 0x50, 0xd8, 0xb0, 0xc9, + 0xe0, 0xb9, 0xe8, 0x8e, 0xfb, 0x98, 0xd4, 0x12, 0x93, 0x75, 0x39, 0xe7, 0xd2, 0x00, 0xb3, 0x99, 0xbd, 0xbd, 0x76, + 0xa5, 0x01, 0x77, 0xf8, 0x71, 0xb7, 0x3f, 0x32, 0xb9, 0x17, 0x4d, 0xfc, 0x62, 0xc6, 0xe5, 0x71, 0x08, 0xec, 0xed, + 0x8f, 0xb4, 0xaf, 0x16, 0x34, 0x9b, 0x5b, 0x3f, 0xe6, 0x1b, 0x5f, 0x76, 0xd7, 0xa3, 0x08, 0x1a, 0x9a, 0x7c, 0x69, + 0xd0, 0xbc, 0x68, 0x7a, 0xf5, 0x19, 0xb5, 0x42, 0x7d, 0xe3, 0x27, 0x52, 0x78, 0xec, 0x26, 0xf1, 0xd7, 0x2e, 0xb7, + 0xef, 0x7e, 0xf7, 0x38, 0x78, 0xf4, 0x45, 0x0c, 0x2f, 0xdf, 0x5e, 0x3f, 0x6e, 0x9e, 0xe1, 0x39, 0xa3, 0x3a, 0x6c, + 0x86, 0x84, 0xa1, 0xe6, 0xf7, 0x5f, 0x32, 0xcc, 0xbe, 0x2c, 0x7b, 0x32, 0xab, 0xcb, 0x7f, 0xee, 0xeb, 0x23, 0x3e, + 0xa8, 0x5d, 0x3e, 0xe3, 0xd7, 0x3f, 0x10, 0x9e, 0xfe, 0x8b, 0xa4, 0x87, 0x75, 0x87, 0xf6, 0x67, 0x7d, 0x33, 0x7e, + 0xec, 0xaa, 0xb0, 0xef, 0xc3, 0x7c, 0x43, 0x68, 0x7b, 0x1e, 0x53, 0xd3, 0x2b, 0x51, 0xc1, 0x44, 0x1c, 0x07, 0x21, + 0x18, 0xb5, 0x75, 0x7a, 0x6b, 0x06, 0xe7, 0xf6, 0x0c, 0xc6, 0xec, 0xb6, 0x5a, 0x2c, 0x6d, 0x08, 0x6f, 0xe6, 0xc3, + 0xae, 0x8f, 0x0b, 0xf4, 0x17, 0x58, 0x8c, 0x21, 0xed, 0xfa, 0xfe, 0x4a, 0x5f, 0xad, 0x2c, 0xcb, 0x00, 0x40, 0x60, + 0xa8, 0x67, 0xc3, 0xd1, 0xb3, 0x44, 0xc6, 0x3c, 0x9b, 0xcf, 0x0d, 0xe9, 0x32, 0xf4, 0xc8, 0xf5, 0x4d, 0xb7, 0x06, + 0x0d, 0x2f, 0x16, 0x6c, 0xc0, 0x57, 0x2b, 0x05, 0xeb, 0x15, 0x16, 0xe4, 0xce, 0x59, 0x71, 0x7f, 0x0f, 0xa5, 0x66, + 0x4d, 0xc4, 0x72, 0xdc, 0x4a, 0x0e, 0xf2, 0xbe, 0x8f, 0x30, 0xd2, 0xd8, 0xd7, 0xf6, 0xd6, 0x8b, 0xeb, 0x3b, 0xa8, + 0x08, 0x7b, 0x28, 0xf7, 0xb2, 0x4a, 0x41, 0x6c, 0xef, 0x18, 0xd2, 0xb3, 0x7c, 0xdc, 0xd7, 0xd7, 0x6e, 0xe6, 0x84, + 0x0f, 0x46, 0x23, 0x43, 0x19, 0x37, 0xd6, 0xe4, 0x89, 0xd8, 0x8f, 0xab, 0x94, 0xe6, 0x31, 0xca, 0x0f, 0x3a, 0xf2, + 0x42, 0x8c, 0xc6, 0xa4, 0x17, 0xec, 0x3b, 0x59, 0x0a, 0x8d, 0xe3, 0xbc, 0x24, 0x1e, 0x6b, 0x71, 0x44, 0x0a, 0x68, + 0x14, 0x1f, 0xc8, 0x66, 0x46, 0x24, 0x40, 0xd5, 0x22, 0xed, 0x2c, 0x9c, 0x44, 0x2d, 0x4e, 0xb4, 0xc1, 0x7b, 0xbf, + 0xdf, 0x71, 0xe7, 0xa4, 0x84, 0x8b, 0x2f, 0x2e, 0xdb, 0x9e, 0x26, 0xe4, 0xe1, 0x97, 0x72, 0xb2, 0xe6, 0x89, 0x9e, + 0x92, 0x5b, 0x1e, 0xb1, 0xa9, 0xb0, 0x4c, 0xc6, 0x42, 0x0f, 0x14, 0x87, 0x6e, 0x99, 0x57, 0xf1, 0x8e, 0x2f, 0x9f, + 0xe1, 0x6a, 0xf7, 0x9b, 0xef, 0x2d, 0x5f, 0xcb, 0xcc, 0x57, 0xeb, 0x1e, 0xd0, 0xf8, 0xe0, 0x04, 0x9e, 0xb2, 0xbb, + 0x6f, 0xbc, 0x9b, 0xbc, 0x06, 0x78, 0xf9, 0xdc, 0x2f, 0x51, 0xbe, 0xa8, 0xfd, 0x86, 0xe8, 0x35, 0x80, 0xc0, 0x03, + 0x91, 0x6c, 0xc5, 0xd4, 0x5b, 0x4e, 0x64, 0x72, 0xff, 0x3e, 0xc3, 0x36, 0x7c, 0xf2, 0x6e, 0x1d, 0xaa, 0xa4, 0xb1, + 0x12, 0x9e, 0x49, 0xeb, 0x77, 0xaa, 0xf6, 0x39, 0x12, 0x18, 0x7b, 0x15, 0xcc, 0xb0, 0x3b, 0x86, 0x98, 0x9d, 0xa4, + 0x70, 0xdc, 0x17, 0x1b, 0x2c, 0xf3, 0x9b, 0x99, 0x43, 0xb7, 0x34, 0x3e, 0x86, 0x3b, 0x19, 0xab, 0xb4, 0x4d, 0xa5, + 0x71, 0xd7, 0xf8, 0x1b, 0x82, 0xc0, 0x55, 0x87, 0xda, 0xa3, 0x49, 0xbf, 0x64, 0x5f, 0x70, 0x1d, 0x9c, 0x09, 0x7a, + 0x59, 0x0e, 0x56, 0xb8, 0x54, 0x83, 0xe5, 0xad, 0x8f, 0x00, 0x02, 0x61, 0x5b, 0x10, 0xc2, 0x06, 0xdb, 0x6b, 0xe9, + 0x58, 0x8d, 0x9c, 0xb1, 0x79, 0xff, 0xf1, 0x66, 0x89, 0x1e, 0xca, 0x16, 0x4e, 0x53, 0x7d, 0x29, 0x6b, 0xb5, 0xdf, + 0xbb, 0x7f, 0xbe, 0xef, 0x00, 0x07, 0x09, 0xc3, 0x0b, 0x3a, 0x38, 0xfe, 0x1a, 0xbd, 0x15, 0x8b, 0x60, 0x61, 0xb4, + 0x6d, 0x7d, 0xf6, 0xed, 0xa1, 0x78, 0x66, 0x41, 0x7c, 0x33, 0x6b, 0xb7, 0xae, 0x2a, 0x8e, 0xb0, 0x55, 0xc3, 0x26, + 0x84, 0xd6, 0x10, 0x01, 0x98, 0xfa, 0x4b, 0x8d, 0x7c, 0xb7, 0x0d, 0xab, 0x4e, 0x45, 0x14, 0xdb, 0xaa, 0x10, 0x47, + 0x50, 0xc9, 0xc1, 0xa0, 0x8a, 0x42, 0x17, 0x76, 0x0f, 0x7e, 0xe2, 0x64, 0x5c, 0x50, 0xdc, 0x54, 0x3c, 0x7a, 0x7e, + 0x0b, 0x94, 0x81, 0xa9, 0xbf, 0x5c, 0x69, 0xef, 0x0f, 0x90, 0x3e, 0xd8, 0xc3, 0x4e, 0xc9, 0xe7, 0x2a, 0x9e, 0xd0, + 0x77, 0x27, 0x34, 0x81, 0xe1, 0xe1, 0xd8, 0x9b, 0xc4, 0x07, 0x12, 0xf0, 0xa0, 0x60, 0x41, 0xbe, 0xbf, 0x13, 0xea, + 0xa6, 0x4f, 0x03, 0x02, 0x88, 0xaf, 0xaa, 0xe3, 0x70, 0x84, 0x60, 0x45, 0x1d, 0x0b, 0xec, 0x89, 0x8a, 0x53, 0x72, + 0x44, 0x86, 0x71, 0x82, 0xfa, 0x06, 0xe8, 0xe6, 0x53, 0xa5, 0xfc, 0x0b, 0xb7, 0x9b, 0x44, 0xe2, 0x59, 0xdf, 0x2a, + 0xda, 0x65, 0xa4, 0x48, 0xe0, 0x8d, 0x58, 0x47, 0x95, 0x42, 0xe9, 0x06, 0xcb, 0x94, 0x22, 0x4e, 0xd3, 0xe0, 0xfa, + 0xd2, 0x4b, 0xbd, 0xd6, 0x4e, 0x2d, 0xfd, 0x7a, 0xdd, 0x04, 0xfa, 0x1a, 0x0f, 0x59, 0xf0, 0xa5, 0xfa, 0xa9, 0x26, + 0xb0, 0x1b, 0x68, 0x3b, 0x97, 0xda, 0x9f, 0xa1, 0x71, 0xb2, 0xa1, 0x7d, 0x2d, 0x6f, 0x21, 0x80, 0x29, 0xdc, 0xa0, + 0xb6, 0xbc, 0x48, 0xa6, 0x76, 0x22, 0x66, 0x7f, 0x6c, 0x22, 0x99, 0x20, 0xaf, 0x1c, 0x6c, 0x68, 0x1f, 0xda, 0xc2, + 0xf3, 0xa0, 0x04, 0xc3, 0xcf, 0x5a, 0xca, 0xc0, 0x8a, 0xb0, 0xad, 0xed, 0xd7, 0xc7, 0xb0, 0x09, 0xa6, 0x0c, 0x82, + 0x50, 0x7f, 0x09, 0xda, 0x69, 0x30, 0x79, 0xd4, 0x63, 0xc6, 0x3e, 0x9b, 0x39, 0xdf, 0x83, 0x1e, 0xa5, 0x92, 0x85, + 0x20, 0x39, 0x0c, 0xf4, 0xd7, 0x62, 0x62, 0x1c, 0xa1, 0x42, 0x22, 0xb4, 0x5b, 0x25, 0x03, 0xf7, 0x1f, 0x54, 0x0c, + 0x11, 0x76, 0x54, 0x9d, 0x4b, 0xb3, 0x6b, 0x54, 0x31, 0x50, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x23, 0x84, 0xd3, 0xa6, + 0xf6, 0xce, 0x5d, 0x24, 0xd2, 0x53, 0x29, 0x62, 0xb1, 0x71, 0x56, 0xba, 0xd4, 0x0c, 0x6b, 0x61, 0x2c, 0x27, 0x46, + 0xd0, 0x38, 0x73, 0x47, 0x54, 0xc7, 0xb7, 0xac, 0x61, 0x04, 0xb8, 0x47, 0xec, 0xb6, 0x07, 0xad, 0x00, 0xb9, 0x26, + 0x69, 0xa0, 0xa0, 0xbd, 0x31, 0x21, 0x8b, 0x02, 0x19, 0x19, 0x93, 0xe8, 0x46, 0x50, 0x72, 0xf7, 0x75, 0x24, 0x8f, + 0x01, 0x76, 0xe5, 0x64, 0x3d, 0x43, 0x24, 0xc4, 0xf1, 0xa6, 0x56, 0x04, 0x81, 0xb1, 0x0c, 0xb0, 0x63, 0xe9, 0xa8, + 0xe4, 0x5c, 0xdc, 0xa0, 0xa7, 0xaa, 0x99, 0x5f, 0xd8, 0xf5, 0x19, 0x8a, 0x34, 0xa2, 0x5d, 0x40, 0x40, 0xce, 0x5c, + 0x75, 0x1d, 0x18, 0x39, 0x48, 0x5c, 0xa3, 0x3b, 0xad, 0x90, 0x51, 0x44, 0x3e, 0x2e, 0x86, 0xe5, 0x05, 0xe4, 0x46, + 0x5c, 0x6c, 0x94, 0x65, 0xc8, 0x45, 0x1f, 0xb9, 0x0d, 0xde, 0xb9, 0xd1, 0x93, 0xae, 0x13, 0x96, 0x00, 0xac, 0xc7, + 0xb2, 0x98, 0x70, 0xab, 0xa6, 0x67, 0xbf, 0x01, 0x9a, 0x04, 0x5e, 0x3b, 0xea, 0x1c, 0xe2, 0xf8, 0x42, 0x8d, 0x6c, + 0xf0, 0x6f, 0x6a, 0x94, 0xb0, 0xb6, 0x0d, 0x2b, 0x67, 0x9c, 0x56, 0x51, 0xec, 0xb1, 0xf2, 0x4c, 0xc4, 0xfc, 0x05, + 0xa3, 0xe8, 0x34, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x85, 0x88, 0x3d, 0x02, 0x4d, 0x81, 0x7d, + 0x6f, 0x28, 0x4c, 0xeb, 0x23, 0xc9, 0x49, 0xda, 0x53, 0x74, 0x36, 0x67, 0xc3, 0x0c, 0xb1, 0x8b, 0x80, 0x6e, 0xcf, + 0xb9, 0x0e, 0x57, 0xf6, 0x45, 0x29, 0x3c, 0x25, 0x33, 0x6a, 0x09, 0x26, 0xc2, 0x64, 0x78, 0x95, 0x5d, 0x20, 0xf2, + 0xde, 0xa6, 0x99, 0x49, 0xef, 0xe9, 0x95, 0xfb, 0x13, 0x40, 0x1e, 0xf7, 0xe4, 0x7d, 0xa6, 0x29, 0xc3, 0x15, 0x0e, + 0x41, 0x6d, 0x57, 0xcc, 0x63, 0xb9, 0x4d, 0xad, 0x4a, 0x6e, 0x38, 0xe0, 0x62, 0x21, 0x35, 0xee, 0xee, 0x6a, 0x73, + 0x42, 0x03, 0x48, 0x55, 0x4b, 0x67, 0x83, 0xe7, 0x80, 0xe2, 0x3d, 0x01, 0x44, 0x22, 0x1a, 0x85, 0xef, 0xfc, 0x28, + 0x47, 0xe7, 0x24, 0x21, 0x14, 0xe6, 0xea, 0x76, 0x5e, 0x7e, 0xa6, 0x94, 0x59, 0x6e, 0x38, 0x3a, 0x00, 0xd8, 0xa2, + 0x7d, 0x51, 0xf8, 0x3c, 0x02, 0xf9, 0xff, 0xa4, 0xb0, 0xf1, 0xad, 0x69, 0xc7, 0x54, 0xf5, 0x6c, 0x56, 0xe7, 0x61, + 0x81, 0xe7, 0x38, 0x65, 0x82, 0xe7, 0xdf, 0x56, 0x77, 0x43, 0xd4, 0xf9, 0xa7, 0xd8, 0x01, 0x5b, 0x6d, 0xb3, 0xbb, + 0x1d, 0xbc, 0xae, 0x16, 0x27, 0x87, 0x4c, 0xaa, 0xce, 0xf6, 0xc1, 0x37, 0xfb, 0xe9, 0x5f, 0x4e, 0x7e, 0x33, 0xc6, + 0x02, 0xc8, 0xab, 0x82, 0xaa, 0xc8, 0xc8, 0x74, 0x40, 0x89, 0x57, 0x86, 0xcf, 0xc5, 0x00, 0x2d, 0x32, 0xaf, 0x5a, + 0x09, 0x14, 0x9a, 0xd5, 0x88, 0xf2, 0x06, 0x10, 0x64, 0x2b, 0xd4, 0x5c, 0xa3, 0xe0, 0x08, 0x79, 0xd2, 0x62, 0x63, + 0xde, 0xb0, 0x52, 0x8b, 0x66, 0x99, 0xb6, 0xa6, 0xc8, 0x22, 0xb0, 0x38, 0x20, 0xae, 0xbf, 0xa0, 0x75, 0x36, 0x30, + 0x95, 0xe7, 0x83, 0x11, 0x06, 0xd8, 0x0d, 0x37, 0x92, 0x4d, 0x8c, 0xbd, 0x12, 0x8a, 0x9c, 0x06, 0xd2, 0xd8, 0x8f, + 0xef, 0xae, 0xe5, 0xed, 0xae, 0x25, 0xa6, 0xbe, 0x3c, 0x9c, 0x18, 0x4d, 0x0c, 0x2d, 0xed, 0x86, 0xa5, 0x87, 0xa8, + 0x9f, 0x9d, 0xcc, 0x4c, 0x39, 0x5b, 0x7b, 0x0c, 0x0f, 0x5d, 0xe7, 0x92, 0xbc, 0x7f, 0x36, 0x03, 0x01, 0xf9, 0xad, + 0xc0, 0x1a, 0xd0, 0x26, 0x11, 0x45, 0x20, 0x1c, 0xe4, 0xf4, 0x2d, 0x71, 0xf4, 0x37, 0x03, 0x4b, 0x76, 0x3d, 0xd4, + 0x2d, 0x75, 0x8b, 0xb1, 0xac, 0x95, 0x95, 0x53, 0x50, 0x71, 0xe9, 0x99, 0x8c, 0x79, 0x20, 0xd9, 0xa0, 0x6a, 0xb0, + 0x92, 0x7d, 0xde, 0x2e, 0x1c, 0xa8, 0xa4, 0x90, 0xbd, 0x9f, 0x06, 0x79, 0x71, 0x7a, 0x91, 0xac, 0x56, 0x62, 0x8c, + 0x47, 0xa9, 0xb6, 0xb9, 0x0e, 0x88, 0xab, 0x0e, 0x6d, 0xe0, 0xc5, 0x85, 0xed, 0x76, 0xbb, 0x66, 0xab, 0x80, 0xac, + 0x95, 0x4e, 0xe4, 0x66, 0x16, 0x9d, 0xef, 0x2d, 0x22, 0x9d, 0xb5, 0xe5, 0x21, 0x2f, 0xe7, 0xb1, 0x0d, 0xb2, 0xe8, + 0x96, 0xf0, 0xc2, 0x98, 0xb0, 0x81, 0xe5, 0xee, 0xdb, 0xf8, 0x82, 0x43, 0x21, 0x29, 0xd3, 0xd3, 0x4c, 0xbb, 0x37, + 0xc4, 0x7c, 0x57, 0x4d, 0xb4, 0xc2, 0x16, 0xcc, 0x75, 0xf0, 0x8b, 0x64, 0xb5, 0x97, 0xa2, 0x5a, 0x3a, 0x1f, 0x66, + 0xef, 0xd2, 0x91, 0xda, 0xcb, 0x00, 0xd5, 0x4e, 0x63, 0x33, 0x8e, 0x73, 0x02, 0xfa, 0x28, 0x98, 0x59, 0xe1, 0x25, + 0x20, 0xbb, 0x48, 0x61, 0x85, 0x95, 0xba, 0xcd, 0x18, 0x96, 0x52, 0xf7, 0xc3, 0x44, 0x67, 0x19, 0x62, 0xe3, 0x49, + 0x5f, 0x1a, 0x7b, 0x34, 0x8a, 0x47, 0xa8, 0x22, 0xaa, 0xdd, 0x1f, 0x21, 0x4c, 0x48, 0x75, 0x86, 0x27, 0x30, 0xed, + 0xf9, 0x08, 0x1d, 0x17, 0x30, 0xbf, 0x98, 0x85, 0x76, 0xfb, 0x7a, 0x8b, 0x58, 0x78, 0xf5, 0x21, 0xc5, 0x35, 0xa5, + 0xb7, 0xf2, 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x58, 0xa1, 0x68, 0x34, 0x1f, + 0xee, 0x36, 0x03, 0x6c, 0x86, 0xa0, 0x44, 0x42, 0x71, 0x63, 0x98, 0xc5, 0x30, 0x63, 0x0d, 0x4c, 0xee, 0x16, 0xdd, + 0x9c, 0x64, 0xcd, 0x9d, 0x4c, 0x72, 0xe6, 0xbb, 0x9f, 0x18, 0xe5, 0xc6, 0x31, 0xc5, 0x5e, 0xc7, 0x57, 0x35, 0x59, + 0x5d, 0xab, 0xe9, 0x2d, 0xae, 0x9c, 0x10, 0xb4, 0xce, 0xe2, 0x3e, 0xad, 0x5d, 0x62, 0x02, 0xd8, 0x0a, 0xec, 0x4e, + 0x55, 0x24, 0x15, 0xf4, 0xa1, 0x31, 0xcc, 0x1d, 0x0c, 0x27, 0xb6, 0xa1, 0x92, 0xb5, 0x1c, 0x1d, 0xc4, 0xb6, 0x7f, + 0x1f, 0xe4, 0x0c, 0xe8, 0xf8, 0xed, 0x64, 0x4c, 0x85, 0x40, 0xcd, 0x22, 0xad, 0x2e, 0x43, 0xba, 0x14, 0xe2, 0x5a, + 0x59, 0x5e, 0x08, 0x92, 0xbc, 0x4f, 0xcc, 0x25, 0xca, 0xdb, 0x61, 0xea, 0x35, 0xac, 0xcb, 0x0e, 0x48, 0xa3, 0x17, + 0xaa, 0xf2, 0x1b, 0x16, 0xe1, 0x48, 0x13, 0x26, 0x6b, 0x67, 0x20, 0xe6, 0x35, 0x6a, 0x33, 0x45, 0xc6, 0xaa, 0x03, + 0x47, 0xa0, 0x1c, 0x9d, 0x97, 0x8d, 0xf5, 0x53, 0xb3, 0x46, 0x6f, 0x28, 0x0c, 0x6c, 0xcf, 0x73, 0x49, 0x19, 0x48, + 0x63, 0x2c, 0x84, 0x1b, 0x93, 0x4e, 0x15, 0xd4, 0x03, 0xd9, 0xb3, 0xbe, 0xc0, 0x78, 0x96, 0x98, 0xf0, 0x9d, 0x03, + 0x8e, 0xe7, 0xcb, 0x48, 0x2f, 0x5d, 0x13, 0xad, 0x68, 0x65, 0x21, 0xfe, 0xec, 0x64, 0xd6, 0x96, 0xb9, 0x0e, 0x7c, + 0x05, 0xa0, 0x3a, 0x99, 0x0a, 0x2a, 0x51, 0x25, 0x95, 0x50, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x6a, 0xac, 0xbc, 0x71, + 0xef, 0x46, 0x86, 0x3f, 0x7b, 0x03, 0x4b, 0xeb, 0xae, 0xf0, 0xc1, 0xd9, 0x5f, 0x65, 0x90, 0x22, 0xed, 0x99, 0xb1, + 0x1b, 0x1b, 0xf3, 0xcc, 0x91, 0xd7, 0xd7, 0x8e, 0x89, 0xff, 0x5d, 0xb8, 0x63, 0x92, 0xdd, 0x7b, 0x14, 0x32, 0xb6, + 0xe5, 0x80, 0xa8, 0xdb, 0x3a, 0x0e, 0x47, 0x6a, 0xf8, 0x93, 0x9c, 0xe2, 0x3f, 0xae, 0x82, 0xa8, 0x5d, 0x69, 0x21, + 0xf9, 0x48, 0xcf, 0x21, 0x6b, 0x30, 0x9a, 0x34, 0x26, 0x30, 0xde, 0x03, 0xa3, 0x4c, 0x88, 0x89, 0x18, 0xdd, 0x84, + 0x09, 0x67, 0x9e, 0x01, 0xfe, 0xd2, 0x94, 0x85, 0x6d, 0x11, 0xb0, 0xdb, 0xc5, 0x6c, 0x2f, 0x3a, 0x4c, 0x18, 0xe4, + 0xdd, 0xe5, 0x0b, 0xf9, 0x47, 0xe2, 0x61, 0x73, 0xd9, 0xdf, 0xf2, 0x52, 0x44, 0x89, 0x2a, 0x42, 0x98, 0x06, 0x09, + 0x0d, 0x75, 0x56, 0x14, 0x69, 0xcc, 0x10, 0x6b, 0x98, 0xe3, 0x27, 0x1b, 0x45, 0x48, 0x85, 0x50, 0x28, 0x02, 0xd1, + 0x19, 0x22, 0x8c, 0x9c, 0x27, 0x0c, 0xf0, 0xae, 0x01, 0xd0, 0x12, 0xb4, 0x63, 0xc8, 0x96, 0x5b, 0x27, 0x84, 0x16, + 0x73, 0x89, 0xdf, 0xe7, 0x52, 0xca, 0x52, 0x7d, 0xad, 0x2e, 0x0b, 0xee, 0x25, 0x57, 0x2a, 0x6e, 0xa0, 0xe8, 0x28, + 0x9e, 0x86, 0x0f, 0x4c, 0x4d, 0x1f, 0xa5, 0x53, 0x1b, 0x6b, 0x9a, 0x27, 0xce, 0x39, 0xb2, 0x1f, 0xa8, 0xbb, 0xb9, + 0x3b, 0x41, 0xdc, 0xa9, 0x2a, 0xa1, 0x2c, 0xc3, 0x4d, 0xb7, 0x4c, 0x97, 0x92, 0x1a, 0x2e, 0xda, 0x92, 0xfc, 0xb6, + 0x29, 0x3e, 0x78, 0xc3, 0xf1, 0xe9, 0x7d, 0xc1, 0xec, 0x36, 0x3f, 0x7e, 0x32, 0x37, 0x02, 0xb3, 0xe0, 0xd1, 0xcd, + 0xc3, 0x1b, 0x36, 0x50, 0xc0, 0x8e, 0x04, 0x86, 0xae, 0x78, 0xa3, 0x35, 0xf1, 0x48, 0x63, 0x3d, 0x38, 0x78, 0x4f, + 0x79, 0x18, 0xb7, 0xa4, 0x8b, 0xac, 0xeb, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0x87, 0xa7, 0xa7, 0x93, 0x3e, 0x69, 0x53, + 0x54, 0x5c, 0x91, 0xce, 0xcd, 0x47, 0x7f, 0x11, 0x2c, 0xcc, 0x63, 0xec, 0x9c, 0xc9, 0x38, 0x47, 0x67, 0xcc, 0xc6, + 0xc1, 0x0e, 0xc6, 0x8b, 0x7d, 0xcb, 0xef, 0x14, 0xc9, 0x2f, 0x65, 0x05, 0x68, 0x44, 0x21, 0xa8, 0xd3, 0x6e, 0x51, + 0x28, 0x81, 0x43, 0xff, 0xab, 0xac, 0xed, 0x7b, 0xe4, 0xe7, 0xb2, 0x8b, 0x25, 0x82, 0xd8, 0x8d, 0xcd, 0xea, 0x5c, + 0xdc, 0xad, 0x46, 0x36, 0xad, 0x5b, 0x48, 0xa8, 0x3f, 0xcc, 0xcc, 0xb3, 0x67, 0x7e, 0x35, 0x22, 0x78, 0x93, 0x6f, + 0x86, 0xf5, 0xcd, 0x98, 0xeb, 0xbf, 0x4a, 0xfa, 0x73, 0x25, 0x31, 0x8e, 0xdf, 0xc8, 0x80, 0xac, 0x39, 0x90, 0x05, + 0xa5, 0xe2, 0x56, 0x3e, 0xca, 0xe3, 0x3d, 0x7e, 0x14, 0x28, 0xa2, 0xc9, 0x94, 0x51, 0x72, 0x2d, 0x14, 0xf9, 0xc8, + 0xdb, 0xb3, 0xbb, 0x37, 0x9e, 0x8e, 0x1a, 0x2f, 0x37, 0x7f, 0xa0, 0xb7, 0x65, 0xab, 0x1b, 0x3f, 0x98, 0xbd, 0x2d, + 0xff, 0xf9, 0x88, 0x3a, 0x5d, 0x17, 0x19, 0xcf, 0x43, 0xbd, 0x85, 0x6c, 0x1a, 0xa9, 0x16, 0xdd, 0x46, 0x40, 0x37, + 0xe2, 0x98, 0x77, 0xdc, 0x6d, 0xc0, 0x17, 0xc0, 0xbb, 0x84, 0x81, 0x78, 0xff, 0xa0, 0xe7, 0xa6, 0xc9, 0xcb, 0xb3, + 0x29, 0x17, 0x77, 0x5e, 0xd9, 0xed, 0x1e, 0x80, 0xce, 0x4f, 0xab, 0x7f, 0xbc, 0xcf, 0xe1, 0x17, 0x3f, 0xf9, 0x67, + 0x95, 0x50, 0x41, 0xba, 0x6f, 0x8c, 0xab, 0xbc, 0x9c, 0xf5, 0xee, 0x7e, 0xd6, 0x6e, 0xbb, 0xe3, 0x49, 0x0d, 0xed, + 0xbf, 0x92, 0xef, 0x8a, 0x74, 0x1b, 0x65, 0xfc, 0x4b, 0xb0, 0xf8, 0x92, 0x85, 0xde, 0x0f, 0x40, 0xdc, 0x14, 0x69, + 0x0f, 0xe9, 0x6a, 0xc6, 0x0f, 0xe3, 0xdd, 0x68, 0xc7, 0xad, 0xab, 0x5d, 0x12, 0x2e, 0x6a, 0xc4, 0xfd, 0xbc, 0x76, + 0x33, 0xd7, 0x7b, 0x4c, 0xab, 0x69, 0x97, 0x7f, 0xe6, 0x20, 0xbc, 0xb4, 0x90, 0xb2, 0x36, 0xbd, 0xb6, 0x45, 0xe9, + 0x5a, 0x60, 0xf9, 0xcb, 0x59, 0x9b, 0x6e, 0x55, 0x68, 0xda, 0xa5, 0xca, 0xd7, 0xf8, 0x37, 0x4e, 0xc5, 0x2e, 0xe7, + 0x8f, 0xfe, 0x73, 0xf2, 0xf6, 0xf0, 0xd7, 0x92, 0x77, 0xcc, 0x45, 0x6e, 0xce, 0xdc, 0xdf, 0xc2, 0x15, 0x59, 0x16, + 0x17, 0xf9, 0xfc, 0xff, 0x95, 0x7b, 0xfc, 0xd7, 0xe1, 0xf9, 0xb9, 0x26, 0x64, 0x76, 0x54, 0xf3, 0x4a, 0x6a, 0x5e, + 0xfe, 0xdf, 0xe7, 0xc5, 0xd3, 0xab, 0x07, 0xa4, 0xc1, 0xf0, 0x8d, 0xd9, 0x66, 0x96, 0x95, 0xd1, 0xc2, 0x21, 0x1e, + 0xc3, 0xfb, 0x26, 0xaf, 0x41, 0x90, 0x37, 0x5d, 0x96, 0xd3, 0xe0, 0x6e, 0x2a, 0xc9, 0xec, 0x4a, 0x39, 0x2c, 0x6e, + 0xfd, 0x78, 0x59, 0x96, 0xcd, 0x65, 0x4f, 0xf3, 0x4d, 0xed, 0x85, 0xfc, 0xd3, 0x97, 0x54, 0xba, 0x04, 0xe7, 0x8f, + 0x7c, 0xbc, 0x5c, 0xfc, 0x9c, 0x8d, 0xcb, 0x8f, 0x09, 0x21, 0x0e, 0x69, 0x22, 0x4d, 0x03, 0xda, 0x31, 0x98, 0x0f, + 0x71, 0x6e, 0xb6, 0x39, 0xcc, 0x0d, 0xdf, 0xe3, 0x05, 0x60, 0x67, 0x1e, 0x5f, 0xd5, 0x8b, 0x81, 0x38, 0x1d, 0x87, + 0x40, 0x8e, 0x47, 0xff, 0xb7, 0x8e, 0x7e, 0xe8, 0x22, 0xbd, 0xc8, 0x2d, 0xdf, 0xba, 0x87, 0x95, 0xe6, 0xc6, 0xd1, + 0x68, 0xe4, 0x88, 0x6d, 0x76, 0x17, 0x81, 0x8f, 0xb1, 0xe8, 0xe4, 0xe0, 0x2d, 0xe2, 0xa5, 0x7e, 0x97, 0x98, 0x07, + 0x57, 0xf9, 0x77, 0x62, 0xf1, 0xa5, 0x38, 0xde, 0xdd, 0x3b, 0x02, 0xe0, 0xf5, 0xc4, 0x2b, 0x07, 0xa7, 0x65, 0x38, + 0x85, 0xa4, 0x4e, 0x54, 0xd6, 0x4a, 0x75, 0xcf, 0xbe, 0x8f, 0x17, 0x93, 0x08, 0xbc, 0x3f, 0xde, 0xf7, 0x09, 0x3b, + 0x5d, 0xa4, 0xe7, 0x78, 0xaf, 0x8c, 0x40, 0x80, 0x22, 0x0a, 0x90, 0x06, 0xf9, 0xa8, 0x6e, 0x91, 0xbf, 0xc0, 0x50, + 0xdf, 0x39, 0x5c, 0x7d, 0xae, 0x28, 0x90, 0x1e, 0xae, 0xd6, 0xc5, 0x7d, 0x0a, 0x50, 0x12, 0xdb, 0x84, 0x80, 0xed, + 0x3f, 0xbd, 0x6f, 0x07, 0xb6, 0xde, 0xa4, 0x5d, 0xcf, 0x20, 0x77, 0x6a, 0x62, 0xf7, 0x19, 0x46, 0xc6, 0x0b, 0xcf, + 0x0b, 0x9d, 0xf0, 0x28, 0xc7, 0x44, 0xaf, 0xa8, 0xac, 0xac, 0xe3, 0xce, 0x7c, 0xb0, 0xb2, 0xff, 0x5c, 0x42, 0x21, + 0x4c, 0x37, 0xe9, 0xcb, 0x2a, 0xa1, 0x4a, 0xf3, 0x0a, 0x6e, 0x65, 0x4c, 0x46, 0x2f, 0xa1, 0xce, 0xf8, 0x5d, 0x53, + 0x64, 0x8a, 0xb1, 0x0c, 0x98, 0xe9, 0x6f, 0xa6, 0x9c, 0x09, 0x00, 0xce, 0xe2, 0x32, 0x80, 0x04, 0xaa, 0xbe, 0xaa, + 0x95, 0x6f, 0x69, 0xc6, 0x29, 0x59, 0x47, 0xd9, 0x79, 0xae, 0x95, 0x52, 0x1e, 0x5f, 0x36, 0xb0, 0xe1, 0x4c, 0xc3, + 0x82, 0x2b, 0xf9, 0x64, 0xbb, 0x2f, 0x57, 0x73, 0x5d, 0xd6, 0xc3, 0x09, 0x30, 0xfb, 0xfd, 0x00, 0xfa, 0x96, 0x72, + 0xc5, 0x46, 0xd9, 0xcb, 0x3f, 0xf4, 0x06, 0x6b, 0xd0, 0xf0, 0xa1, 0x87, 0x29, 0x37, 0xbe, 0x50, 0xd4, 0x7f, 0x08, + 0x9c, 0x15, 0x23, 0x97, 0x6a, 0x4d, 0xa1, 0x97, 0x18, 0xa1, 0x9f, 0x65, 0x50, 0xb5, 0x7a, 0x63, 0x2a, 0x2a, 0x95, + 0xaf, 0xef, 0xb9, 0xc3, 0x95, 0xe5, 0xc0, 0x9d, 0xf9, 0xe4, 0x14, 0x90, 0x02, 0x44, 0x41, 0xac, 0x54, 0x7e, 0x1e, + 0x66, 0x9b, 0x90, 0xca, 0x20, 0x99, 0xbe, 0x50, 0x64, 0xdd, 0x37, 0xfa, 0x0b, 0x2b, 0xb6, 0xea, 0x25, 0x74, 0x0f, + 0x76, 0x78, 0xcf, 0x7d, 0x9b, 0xf7, 0x67, 0xcb, 0x59, 0xf5, 0xb4, 0xf4, 0xd6, 0x73, 0xb7, 0x6b, 0xe0, 0x52, 0xe7, + 0x00, 0x20, 0x2d, 0x97, 0x3a, 0x7f, 0xdf, 0xc4, 0xdd, 0xac, 0x36, 0x7e, 0x76, 0x51, 0x46, 0x47, 0x8f, 0x5b, 0xe9, + 0xe9, 0x91, 0x75, 0x61, 0x95, 0x74, 0x78, 0xdf, 0x44, 0xe0, 0xcb, 0x1f, 0xc3, 0xb0, 0x7a, 0x61, 0x7a, 0x6e, 0x50, + 0x9c, 0x09, 0x9b, 0x93, 0x7d, 0xf6, 0xce, 0xcd, 0x5b, 0x0d, 0x1f, 0xa2, 0x37, 0xe1, 0x73, 0x87, 0x7d, 0x2e, 0x02, + 0xe8, 0x36, 0x6b, 0x7e, 0xc6, 0x41, 0xd1, 0x2a, 0x54, 0x8b, 0x97, 0x25, 0xb0, 0x29, 0x59, 0xee, 0xe7, 0x78, 0x11, + 0x6c, 0x0a, 0xed, 0x8b, 0x20, 0x2f, 0x67, 0x54, 0xa1, 0x17, 0xd2, 0xbb, 0x0a, 0x5c, 0xb9, 0x15, 0x7c, 0x7f, 0xc5, + 0x60, 0x75, 0xd5, 0xb6, 0x14, 0x1f, 0xce, 0x18, 0xfd, 0xae, 0x02, 0xe6, 0xab, 0xaf, 0x98, 0xd9, 0xd0, 0xa7, 0x3d, + 0x0f, 0xab, 0xfb, 0xfe, 0xb5, 0xe5, 0x0b, 0x82, 0xef, 0xdf, 0x4c, 0x4d, 0xbb, 0x38, 0x9c, 0x12, 0x1b, 0x81, 0xb9, + 0x47, 0x88, 0xc3, 0x10, 0x69, 0x50, 0x77, 0x90, 0x6f, 0xef, 0x96, 0x24, 0x21, 0x4f, 0xd6, 0xbf, 0x78, 0xfc, 0xee, + 0x4c, 0x7a, 0x22, 0xbd, 0xf8, 0xe1, 0xe3, 0x75, 0x22, 0x2c, 0xdb, 0x0b, 0x35, 0xd9, 0xc1, 0xe3, 0x94, 0x5b, 0x79, + 0x80, 0x66, 0x0d, 0x5d, 0x74, 0xdb, 0x87, 0x74, 0x5c, 0x9c, 0x5f, 0x63, 0xe8, 0xfb, 0x06, 0xde, 0xcd, 0x0c, 0x0d, + 0x79, 0xcf, 0xd8, 0x5d, 0xf5, 0x81, 0x0a, 0x2b, 0xc9, 0x4b, 0xb9, 0x57, 0xf6, 0x5c, 0x74, 0xb5, 0x61, 0xe2, 0x1c, + 0x50, 0x7f, 0xb3, 0xcf, 0xcb, 0xae, 0x8a, 0x0f, 0xf8, 0x7a, 0xa5, 0x81, 0xaf, 0xeb, 0x0c, 0x35, 0x02, 0x3a, 0x48, + 0x91, 0x25, 0xe0, 0x33, 0xcc, 0xa8, 0x49, 0x38, 0xcd, 0xf4, 0x96, 0xf2, 0x3c, 0xca, 0x60, 0x51, 0x53, 0xba, 0xd0, + 0xe5, 0xdb, 0xae, 0x16, 0x73, 0x7a, 0x17, 0x13, 0xed, 0x52, 0xf3, 0xde, 0x7e, 0x00, 0x70, 0xb5, 0xdb, 0x90, 0x70, + 0x91, 0x7e, 0x14, 0xf7, 0xad, 0xf3, 0x63, 0xea, 0xeb, 0xe2, 0xe2, 0x11, 0x64, 0x2a, 0x98, 0x04, 0xb9, 0xe9, 0x73, + 0xfd, 0x17, 0x34, 0x31, 0x21, 0x3f, 0xf9, 0xb3, 0x04, 0x5f, 0xda, 0xb5, 0x5d, 0x0c, 0xc1, 0x47, 0x6a, 0x8d, 0xde, + 0x2d, 0x05, 0x64, 0x61, 0x3f, 0xec, 0x3d, 0xd7, 0x14, 0x64, 0xc7, 0x21, 0x69, 0x00, 0x7d, 0xdf, 0xa4, 0xe3, 0x17, + 0x16, 0xc6, 0x22, 0x91, 0x9a, 0xde, 0xc2, 0x76, 0x99, 0x6c, 0xa7, 0xaf, 0x6e, 0x6f, 0x19, 0x5f, 0x5d, 0xec, 0x7a, + 0x0a, 0xeb, 0x06, 0xb0, 0xc3, 0x46, 0x1b, 0x6f, 0xba, 0x80, 0xc3, 0x6d, 0x76, 0xc6, 0x94, 0x7a, 0x57, 0xdc, 0x24, + 0x0e, 0x03, 0xc1, 0x10, 0xf5, 0x22, 0x99, 0x45, 0xf9, 0x3d, 0xf5, 0x26, 0x1c, 0xf5, 0x90, 0xf6, 0x0f, 0x6e, 0xbe, + 0xff, 0x8f, 0x2a, 0x3d, 0x38, 0x1b, 0x06, 0x7e, 0xb2, 0x7b, 0x40, 0xf2, 0xd4, 0x54, 0xf4, 0x80, 0x26, 0x5b, 0x9e, + 0x04, 0xe2, 0xa6, 0x73, 0xed, 0xc3, 0xfe, 0x31, 0xe5, 0x1b, 0x02, 0x6a, 0x9e, 0x18, 0xa1, 0xda, 0x7a, 0xe4, 0x2f, + 0x6b, 0xa5, 0x37, 0xd6, 0x10, 0xcf, 0xaf, 0x08, 0xde, 0xaf, 0x5e, 0x1c, 0x7e, 0x2d, 0x69, 0xa0, 0xdc, 0x2e, 0x67, + 0xe9, 0xbf, 0xeb, 0x0a, 0x17, 0x02, 0x0f, 0xc9, 0xa7, 0x11, 0x92, 0x2b, 0x0b, 0x7c, 0xfc, 0xe2, 0x50, 0xe7, 0xd3, + 0xf7, 0xba, 0xf1, 0x59, 0xdd, 0x10, 0x85, 0x9c, 0x1f, 0xa0, 0xaa, 0x0d, 0x31, 0x46, 0x08, 0x17, 0x7c, 0xf4, 0xd1, + 0x65, 0x59, 0xa3, 0x25, 0x20, 0xed, 0xca, 0xe5, 0x8f, 0x17, 0x06, 0x5e, 0x2b, 0x7e, 0xcb, 0x61, 0x5e, 0xa6, 0x43, + 0x7c, 0xa5, 0xb1, 0x7d, 0x2d, 0x1d, 0x32, 0xd7, 0xd1, 0xa8, 0x08, 0x55, 0x15, 0xa9, 0xe7, 0xe2, 0xa3, 0xf5, 0xbb, + 0x6e, 0xe4, 0x33, 0x83, 0xc5, 0xa5, 0x65, 0x63, 0xc7, 0x49, 0x75, 0xc9, 0x33, 0x3c, 0x40, 0x67, 0xb0, 0xcf, 0xd9, + 0x76, 0xf1, 0x67, 0x95, 0xac, 0xe1, 0x00, 0x23, 0xb0, 0x07, 0x43, 0xae, 0x4a, 0x12, 0x64, 0x30, 0x36, 0x25, 0x97, + 0xa1, 0xe4, 0x7d, 0xbd, 0xb1, 0x59, 0x8e, 0xf2, 0xa0, 0xd0, 0x91, 0xe1, 0x8a, 0xff, 0xa9, 0xb7, 0x8a, 0x34, 0xbd, + 0xfc, 0xdc, 0x38, 0x5b, 0xe7, 0x74, 0xb3, 0x3b, 0xb2, 0xc3, 0x87, 0x51, 0x6e, 0x21, 0x4e, 0xa6, 0x79, 0x18, 0x09, + 0xac, 0x64, 0x6e, 0x9e, 0x0e, 0x80, 0xf8, 0x26, 0x33, 0x5a, 0xb7, 0xe4, 0x7f, 0xf2, 0xb5, 0xae, 0x23, 0x44, 0xb4, + 0xb1, 0xbe, 0xab, 0xe8, 0x0c, 0x12, 0x27, 0xb9, 0x41, 0x31, 0x9e, 0xaa, 0x98, 0x31, 0xc8, 0x96, 0xaa, 0x4e, 0xf2, + 0xfb, 0x4f, 0xbe, 0x4b, 0xa1, 0x37, 0xbd, 0x3d, 0x37, 0xeb, 0xb6, 0x93, 0xe5, 0x88, 0x1a, 0x29, 0x33, 0xbb, 0x31, + 0xe8, 0xa6, 0xa0, 0x10, 0x29, 0x29, 0xcf, 0x14, 0xe9, 0x18, 0x0e, 0xf7, 0xda, 0x1f, 0xe1, 0x89, 0xed, 0x58, 0xc2, + 0xda, 0x66, 0x81, 0x47, 0x80, 0xc0, 0x47, 0xfd, 0x16, 0x41, 0x34, 0xd5, 0x15, 0x15, 0x6a, 0x79, 0x63, 0x77, 0x76, + 0x74, 0x7b, 0x5a, 0x5b, 0xd0, 0x3e, 0x83, 0x3f, 0x15, 0x14, 0xdc, 0x76, 0xad, 0xe7, 0x64, 0x64, 0x45, 0xea, 0x42, + 0x30, 0x02, 0x32, 0xeb, 0x9f, 0x21, 0xe3, 0x53, 0x13, 0xa2, 0xee, 0x2f, 0x1b, 0x43, 0x8e, 0x84, 0x40, 0x80, 0xf0, + 0xb2, 0x7c, 0x96, 0xf0, 0x49, 0xa0, 0x08, 0x50, 0xf5, 0xb8, 0xf4, 0xca, 0x72, 0xa9, 0xd1, 0xf0, 0xa8, 0xd5, 0x80, + 0x6d, 0xbb, 0x40, 0xed, 0x80, 0x05, 0xd6, 0x4e, 0x61, 0x9d, 0x13, 0x52, 0x75, 0x29, 0x16, 0xdd, 0xaa, 0x2e, 0x52, + 0x9e, 0xcd, 0xeb, 0x4c, 0x11, 0x36, 0xad, 0x7f, 0xad, 0x7c, 0x99, 0x80, 0x68, 0x9b, 0xbf, 0x04, 0x6e, 0x8e, 0xcd, + 0xfe, 0x8f, 0x36, 0x13, 0xd3, 0x3a, 0xf5, 0x2a, 0x02, 0x94, 0x9d, 0x2a, 0xf1, 0x1a, 0x65, 0x0c, 0x4a, 0x50, 0xe7, + 0xc7, 0x5e, 0xa2, 0x82, 0x5c, 0x25, 0x7d, 0x31, 0x50, 0x80, 0x30, 0x5e, 0x3a, 0xe2, 0xa5, 0xab, 0xbc, 0xd8, 0x56, + 0xeb, 0x9c, 0x60, 0xec, 0xcd, 0xec, 0x05, 0xa4, 0x3e, 0x5d, 0xee, 0x24, 0x47, 0xd3, 0xc5, 0xb5, 0xcb, 0xab, 0x78, + 0xc8, 0x74, 0x59, 0x7c, 0x4c, 0x83, 0xa7, 0x2a, 0xe7, 0x89, 0x15, 0xc2, 0xff, 0xb6, 0x8c, 0x1b, 0xaf, 0x94, 0x69, + 0x81, 0x10, 0x6b, 0x49, 0x14, 0x38, 0xdf, 0x0c, 0x92, 0x87, 0xe5, 0x51, 0x69, 0x9a, 0xc7, 0xfe, 0xda, 0xd0, 0xec, + 0x49, 0xf6, 0x40, 0x92, 0x0f, 0xdb, 0xbe, 0x4b, 0x82, 0xb9, 0xef, 0x27, 0x1d, 0xc3, 0x44, 0x61, 0x1f, 0x34, 0xe4, + 0x71, 0xd5, 0x02, 0x08, 0x46, 0xee, 0x57, 0x5f, 0xcb, 0xdd, 0xb6, 0xed, 0x36, 0x08, 0x3e, 0xc7, 0x42, 0xc4, 0x5f, + 0x0c, 0x49, 0xf0, 0xed, 0xd5, 0x0b, 0x2a, 0x17, 0xab, 0x75, 0xc8, 0xbc, 0x3c, 0x25, 0xd9, 0xce, 0x93, 0xae, 0xef, + 0x9e, 0xf7, 0xfc, 0x8a, 0x88, 0xd3, 0x15, 0xcd, 0x4c, 0x9c, 0x23, 0xe9, 0xa8, 0xc4, 0x0b, 0xee, 0x0e, 0xea, 0xec, + 0xfd, 0x9c, 0xe2, 0x14, 0x93, 0xe6, 0x16, 0x15, 0x42, 0x17, 0x12, 0xba, 0xd6, 0xb9, 0x7c, 0x5d, 0x58, 0xbb, 0x79, + 0xa2, 0xf4, 0xfe, 0xa5, 0x99, 0x51, 0x54, 0xea, 0xe7, 0x62, 0x09, 0x24, 0x13, 0x72, 0xa2, 0xdf, 0xd8, 0xea, 0xa4, + 0xbb, 0x87, 0x6f, 0x6a, 0xa3, 0xc5, 0x3c, 0x88, 0x73, 0xc0, 0xca, 0x97, 0x61, 0x6f, 0x1b, 0x93, 0xe2, 0xf6, 0xd7, + 0x25, 0x64, 0xb5, 0xdd, 0x1f, 0x4a, 0x7f, 0xce, 0x05, 0x2e, 0xd1, 0x98, 0x18, 0x31, 0xc3, 0x2f, 0x44, 0x5a, 0xa3, + 0x44, 0xce, 0x3d, 0xce, 0x6d, 0x42, 0xfe, 0x2b, 0x53, 0x6f, 0xa4, 0xbb, 0x42, 0xc8, 0xff, 0xf3, 0x3c, 0xe2, 0x8e, + 0xe9, 0xe6, 0xde, 0xde, 0xc9, 0x30, 0x72, 0x0e, 0xcc, 0xda, 0x6e, 0xca, 0x2c, 0xdc, 0x45, 0x7a, 0x8b, 0x19, 0xd3, + 0xec, 0x10, 0xbc, 0x0c, 0x9d, 0x74, 0x52, 0x7c, 0xea, 0x00, 0xa1, 0xea, 0x08, 0x60, 0x4a, 0x16, 0xfa, 0x17, 0x28, + 0x5d, 0xbd, 0x58, 0xa6, 0x96, 0x4a, 0xcd, 0x75, 0x27, 0x16, 0x3f, 0xa1, 0xc0, 0x20, 0x7e, 0x71, 0xab, 0x35, 0x9d, + 0x1d, 0x52, 0x44, 0xa2, 0x27, 0xfd, 0x18, 0x1e, 0x63, 0xe5, 0x31, 0xeb, 0xa1, 0x50, 0x13, 0x5c, 0xef, 0x64, 0xd5, + 0xb3, 0x92, 0x20, 0x8d, 0x74, 0x0f, 0xb0, 0x37, 0x4f, 0xed, 0x51, 0xa2, 0x15, 0x02, 0x2f, 0x91, 0xc6, 0x0c, 0x89, + 0xf6, 0x21, 0xf6, 0x90, 0x98, 0x00, 0x6f, 0x0a, 0x26, 0xd8, 0x52, 0x68, 0x3b, 0x07, 0xce, 0x3b, 0x0a, 0x58, 0x9b, + 0x6b, 0xd4, 0x60, 0xe6, 0x91, 0x23, 0x26, 0xe2, 0x38, 0xfb, 0x5d, 0xd4, 0x21, 0x81, 0xe4, 0x10, 0xed, 0x9c, 0x6a, + 0x1a, 0xb4, 0x38, 0x73, 0x5e, 0x23, 0x57, 0x08, 0xc7, 0xa7, 0xa0, 0x8c, 0x23, 0xd8, 0x70, 0x7d, 0xcc, 0x25, 0xeb, + 0xb2, 0x22, 0x0a, 0x9b, 0x3b, 0x4b, 0xde, 0xaf, 0xe3, 0xf7, 0xa6, 0xb0, 0x92, 0x65, 0xe1, 0x9b, 0xa6, 0xd4, 0x33, + 0xe5, 0x73, 0x2f, 0xac, 0x4a, 0x7a, 0x76, 0x00, 0xf7, 0x88, 0xff, 0xc1, 0xe5, 0x66, 0xe4, 0xa7, 0x94, 0x82, 0x1a, + 0xf0, 0x47, 0x13, 0xda, 0x95, 0x0a, 0x8a, 0xc5, 0xc0, 0x48, 0xd3, 0x69, 0x5b, 0xa8, 0x97, 0x1a, 0x36, 0x30, 0xcc, + 0x63, 0xb2, 0x50, 0xe8, 0xd4, 0xfe, 0x86, 0xe7, 0xf3, 0x88, 0x46, 0xde, 0x4c, 0x1b, 0x64, 0xf9, 0x1d, 0xba, 0xd7, + 0x2a, 0x27, 0xf3, 0x6d, 0x05, 0x10, 0x3f, 0xf3, 0xb2, 0x60, 0x34, 0x54, 0x34, 0x29, 0x66, 0x30, 0x5c, 0x9a, 0x3f, + 0x71, 0x15, 0xa0, 0xc7, 0xf4, 0xd5, 0xda, 0xa2, 0x3a, 0xef, 0x40, 0xc4, 0x74, 0x1f, 0x94, 0x2a, 0x52, 0x5f, 0xe9, + 0x66, 0xab, 0xe3, 0x1c, 0xfc, 0xb1, 0xaa, 0xae, 0x20, 0xd1, 0x6e, 0x79, 0x34, 0xa6, 0xd1, 0xb1, 0x2f, 0x0e, 0xd9, + 0xb1, 0xc7, 0xf3, 0x0e, 0x45, 0xc8, 0xfd, 0xd9, 0x37, 0xa6, 0xf8, 0x24, 0x23, 0x69, 0x04, 0xfa, 0x0a, 0x84, 0xab, + 0x7e, 0xee, 0xae, 0xa8, 0xb0, 0xd5, 0xc8, 0x66, 0x41, 0x19, 0x86, 0xa8, 0xa6, 0xa7, 0x68, 0x1c, 0x78, 0x56, 0x90, + 0x88, 0x09, 0x01, 0x4a, 0xd8, 0xb5, 0x44, 0x0f, 0xfd, 0x1f, 0x66, 0x56, 0xbf, 0xf2, 0x86, 0xad, 0x4c, 0xeb, 0x00, + 0x52, 0x04, 0x84, 0x54, 0xca, 0xd5, 0xfd, 0x83, 0xb9, 0x70, 0x3c, 0x4a, 0x4c, 0x26, 0x3f, 0xcf, 0x3e, 0x80, 0x37, + 0x33, 0xbd, 0x3c, 0xf2, 0x13, 0x69, 0x62, 0x93, 0x7a, 0x4c, 0x6b, 0xa4, 0x76, 0xbb, 0x03, 0x5c, 0xad, 0xd2, 0x0b, + 0x53, 0xff, 0xa2, 0x08, 0x46, 0xff, 0x4a, 0x07, 0x69, 0xdd, 0xcb, 0x9c, 0x4b, 0xb0, 0x29, 0x7a, 0xdb, 0x06, 0x30, + 0xed, 0xdb, 0x52, 0x75, 0x23, 0x41, 0x8a, 0x6d, 0x53, 0xf8, 0xee, 0xf0, 0x12, 0x11, 0x8b, 0x33, 0x16, 0xab, 0xd5, + 0x1d, 0x2d, 0xe6, 0xc1, 0xf7, 0x53, 0x47, 0x10, 0xf6, 0xaf, 0xb0, 0x09, 0x6c, 0x3c, 0x40, 0x16, 0x7b, 0x90, 0x8e, + 0x58, 0xa9, 0xa6, 0x39, 0x8f, 0x56, 0x81, 0x95, 0xaa, 0x2c, 0xde, 0xc7, 0x95, 0xb4, 0xfb, 0x5a, 0x26, 0x0e, 0xa8, + 0xce, 0x21, 0xfc, 0xd6, 0xa2, 0x6f, 0x25, 0x64, 0x5e, 0xd7, 0x38, 0x02, 0xd4, 0x95, 0xb8, 0x12, 0x37, 0x0a, 0x92, + 0x91, 0x1f, 0x34, 0x93, 0x13, 0x74, 0x34, 0xf9, 0xf8, 0x81, 0x06, 0x1e, 0xba, 0xe7, 0x6f, 0xd4, 0x50, 0xec, 0xdb, + 0x55, 0x74, 0x28, 0xb4, 0x26, 0xd9, 0x7f, 0xf6, 0x9d, 0x69, 0xcd, 0x69, 0x46, 0x3d, 0x35, 0xc1, 0x9d, 0x7a, 0x5b, + 0x17, 0x5b, 0xa6, 0x71, 0xe4, 0x2e, 0xcc, 0x9c, 0xf1, 0xb5, 0xbd, 0x81, 0x38, 0xdf, 0x0b, 0x89, 0x9b, 0xe9, 0x88, + 0x29, 0xfd, 0xa4, 0x31, 0x02, 0x6a, 0x14, 0x1d, 0x6c, 0x64, 0xda, 0xb7, 0x02, 0x39, 0x9b, 0xa0, 0xa3, 0x2a, 0xa8, + 0xb6, 0x98, 0x99, 0xa5, 0x71, 0x6a, 0xa4, 0x05, 0x05, 0x2b, 0x8d, 0x41, 0x61, 0xa5, 0x2a, 0xc9, 0x5e, 0x94, 0x58, + 0x7a, 0x9e, 0xb3, 0xd0, 0xa1, 0x6c, 0x3a, 0x7c, 0x5a, 0x0b, 0x97, 0x84, 0xd1, 0xd6, 0xc2, 0x30, 0x6d, 0xb6, 0xd2, + 0xb6, 0xb2, 0xa2, 0x12, 0x2a, 0xb9, 0xbe, 0xa8, 0x24, 0x69, 0x1e, 0x61, 0x1c, 0x4f, 0x65, 0x76, 0x43, 0xf9, 0x0a, + 0x5b, 0xb7, 0xf1, 0xa1, 0xf0, 0x6f, 0x42, 0xc9, 0x6c, 0xc8, 0x80, 0x0c, 0x54, 0x12, 0xac, 0xe2, 0xf4, 0xf3, 0xe5, + 0x35, 0x67, 0x11, 0x97, 0x39, 0xf0, 0x6a, 0xea, 0xb5, 0x76, 0x1c, 0x4a, 0x7c, 0xed, 0xe4, 0x3f, 0xd3, 0xe4, 0xcf, + 0x12, 0x0e, 0xd7, 0xb9, 0xb2, 0xe2, 0x74, 0x58, 0xd0, 0x8f, 0xd8, 0xab, 0xcf, 0xd7, 0x4b, 0x62, 0xcb, 0xa3, 0x48, + 0xdd, 0x2b, 0x6d, 0xef, 0x3d, 0x1b, 0xa9, 0xd0, 0xac, 0xdd, 0x7d, 0xdf, 0x49, 0x5a, 0x65, 0x6a, 0xb5, 0x8b, 0x7b, + 0xd8, 0x40, 0x68, 0x6b, 0x52, 0x22, 0xee, 0xdd, 0xa4, 0x0c, 0x2f, 0x6d, 0x16, 0x40, 0xb5, 0x26, 0x14, 0xdf, 0x8d, + 0xeb, 0x44, 0xee, 0xc3, 0x33, 0x99, 0xbf, 0xdd, 0x7d, 0x30, 0xda, 0x0d, 0xec, 0x8a, 0xd0, 0x0f, 0xa2, 0x2d, 0x58, + 0x75, 0xe9, 0x8d, 0xba, 0xc0, 0x64, 0x51, 0xea, 0x60, 0xa4, 0x82, 0x2c, 0x5e, 0xb9, 0x03, 0xbb, 0x8e, 0x47, 0x10, + 0x40, 0x7f, 0xe3, 0xb8, 0xc5, 0x6d, 0x22, 0x15, 0xc1, 0x5d, 0x76, 0x9c, 0x54, 0x69, 0xbd, 0xcd, 0x8e, 0x63, 0xc1, + 0xd8, 0x52, 0xc8, 0xcc, 0x2a, 0x08, 0x5a, 0x09, 0xb4, 0xbe, 0x4a, 0x76, 0xba, 0x0c, 0xb3, 0x56, 0x14, 0xb0, 0x0f, + 0x2a, 0x39, 0xeb, 0x0f, 0x4a, 0x51, 0x5d, 0xc1, 0xf7, 0x71, 0x78, 0xfa, 0xdd, 0xc0, 0x01, 0x8b, 0xa1, 0x15, 0x82, + 0x23, 0xf6, 0x48, 0x87, 0x2d, 0xbd, 0xa9, 0x77, 0x7c, 0xae, 0xc2, 0x79, 0xf3, 0x58, 0xff, 0x07, 0xa9, 0x3e, 0xef, + 0xeb, 0x17, 0x38, 0xc1, 0x2f, 0x5e, 0x54, 0x8f, 0x77, 0xfc, 0xff, 0x06, 0x43, 0x54, 0x1d, 0xa6, 0xb6, 0xf8, 0x73, + 0x82, 0x74, 0x26, 0x0d, 0x7b, 0xb8, 0xbe, 0x92, 0x76, 0xbe, 0xa0, 0x1a, 0x7a, 0x64, 0x63, 0xb5, 0x1e, 0x94, 0x20, + 0x52, 0xde, 0xbb, 0x7d, 0x36, 0x2f, 0x25, 0xa5, 0x1a, 0xd1, 0x42, 0x4d, 0x7c, 0xb3, 0xe6, 0x4d, 0xb2, 0x16, 0x24, + 0xb1, 0xed, 0x59, 0x3b, 0xb2, 0x85, 0xf8, 0xfd, 0x5b, 0x8c, 0x26, 0x07, 0xf1, 0xde, 0xec, 0xba, 0x0c, 0xba, 0xd5, + 0xb3, 0xb4, 0x84, 0x55, 0x1b, 0xa8, 0x6a, 0xaa, 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0xf5, 0xeb, 0x4a, 0x3a, 0xa7, + 0xb4, 0x10, 0x6a, 0x19, 0xf7, 0x44, 0xb2, 0x88, 0xf8, 0x58, 0x05, 0x3f, 0x29, 0xcc, 0xa9, 0xbb, 0x68, 0x44, 0x16, + 0xa3, 0x57, 0x6e, 0xc3, 0x69, 0xab, 0xa5, 0x4a, 0x40, 0xac, 0xdf, 0xb5, 0x1a, 0x67, 0xb3, 0xc2, 0x89, 0xa1, 0xef, + 0xff, 0xc4, 0x55, 0xe1, 0x4b, 0x10, 0xc6, 0xf1, 0x99, 0x24, 0x4b, 0xf1, 0x19, 0xaf, 0x3c, 0xf0, 0x0e, 0xac, 0xe8, + 0x6e, 0x5f, 0xf1, 0xfb, 0x4f, 0x57, 0x61, 0x85, 0x66, 0x59, 0x51, 0x6e, 0x5d, 0x63, 0x49, 0xdd, 0x23, 0xc7, 0x79, + 0x71, 0x0f, 0x70, 0x26, 0x34, 0xa3, 0x22, 0x4c, 0x69, 0x24, 0x2d, 0x3f, 0x53, 0x5b, 0xb1, 0xf4, 0x09, 0xc5, 0x12, + 0x01, 0x32, 0xf8, 0xfe, 0x93, 0x44, 0x57, 0x1e, 0xeb, 0x00, 0xff, 0xa8, 0x58, 0xb9, 0x2c, 0x66, 0x85, 0x86, 0xba, + 0x00, 0xc9, 0xfa, 0xea, 0x4a, 0xd6, 0xec, 0x6c, 0x43, 0x04, 0x95, 0xba, 0xeb, 0x20, 0x40, 0x6c, 0xd7, 0x08, 0x7c, + 0xf9, 0xd7, 0x68, 0x58, 0x6f, 0x65, 0x41, 0x1d, 0x36, 0xd9, 0x05, 0x01, 0xd1, 0xbd, 0xe8, 0x97, 0x9e, 0x1b, 0xff, + 0xd8, 0xf8, 0x64, 0x63, 0xf9, 0xf0, 0x33, 0x72, 0x2d, 0xaa, 0x87, 0xcc, 0x16, 0x80, 0x98, 0x8d, 0x34, 0x1b, 0x27, + 0xba, 0x6a, 0xef, 0x7b, 0x8d, 0xb2, 0x4d, 0x86, 0xed, 0x12, 0xb3, 0x78, 0xb0, 0xa8, 0x31, 0x65, 0x64, 0x63, 0x8f, + 0x7b, 0xe5, 0xc1, 0x5d, 0xf6, 0x41, 0x04, 0x9d, 0xcb, 0x76, 0xcc, 0xb4, 0x76, 0x38, 0xaf, 0x1a, 0xbb, 0x42, 0x66, + 0x05, 0x9b, 0xc4, 0x41, 0x00, 0xd9, 0x65, 0xdd, 0x05, 0x53, 0xce, 0x69, 0x71, 0xc3, 0x62, 0x0f, 0x36, 0x50, 0x16, + 0x3a, 0xb0, 0x25, 0xd4, 0x50, 0x0a, 0xd3, 0x58, 0x7a, 0xe0, 0x6c, 0x05, 0xe6, 0x5a, 0x8f, 0x63, 0x5d, 0xb3, 0x4e, + 0xd1, 0xa5, 0x02, 0xd2, 0xe2, 0xe8, 0xf9, 0x4d, 0x1f, 0xd2, 0xbe, 0xdb, 0xda, 0xf0, 0xbd, 0x6e, 0xbc, 0x26, 0xc3, + 0x4a, 0x79, 0x12, 0xed, 0x55, 0xfd, 0xf6, 0x02, 0xa3, 0x5a, 0xf8, 0xcc, 0xe5, 0x4b, 0x25, 0xff, 0x6e, 0x0d, 0x03, + 0xcd, 0x17, 0x0a, 0x5f, 0xf5, 0x04, 0x32, 0x2d, 0x69, 0x51, 0xf0, 0xce, 0xf8, 0x69, 0xb3, 0x05, 0xe3, 0xfe, 0xcd, + 0x4d, 0xc5, 0xb8, 0xfe, 0xed, 0x4d, 0xd3, 0xaf, 0x86, 0xc0, 0x6f, 0x14, 0x24, 0xdd, 0x87, 0xed, 0x11, 0x04, 0x88, + 0x7b, 0xab, 0x5c, 0x36, 0xb9, 0x7e, 0xf3, 0xb8, 0xa1, 0xaf, 0x6e, 0xf9, 0xc7, 0x1d, 0xe0, 0x59, 0x92, 0x93, 0xad, + 0x2d, 0x8b, 0x47, 0xce, 0xec, 0xee, 0x65, 0x1c, 0xff, 0x00, 0x38, 0x85, 0xd5, 0xad, 0xfc, 0xe9, 0xfd, 0xcc, 0x9e, + 0x52, 0x73, 0xbd, 0xf5, 0xe7, 0xab, 0x5f, 0xb9, 0x6d, 0x1e, 0xab, 0x53, 0xc3, 0xc6, 0x4d, 0x63, 0x49, 0x66, 0x4b, + 0x30, 0x33, 0x07, 0x29, 0x9c, 0xaf, 0xd5, 0xe7, 0x8c, 0xa3, 0xb8, 0xce, 0x09, 0x23, 0x6c, 0x63, 0x90, 0x1f, 0xbf, + 0x24, 0x96, 0x92, 0xf9, 0xc7, 0xed, 0xca, 0x18, 0x26, 0x91, 0x6e, 0x4f, 0xbd, 0x97, 0xa9, 0xce, 0x29, 0xdb, 0x63, + 0x1e, 0x9b, 0xe0, 0x67, 0xd5, 0x23, 0xd0, 0x0a, 0xfc, 0x0b, 0x02, 0xb6, 0xbb, 0x2c, 0xb3, 0x07, 0x9a, 0x37, 0xff, + 0x03, 0x78, 0x23, 0x3a, 0x65, 0x61, 0x27, 0xbb, 0xbe, 0xf9, 0x5d, 0x87, 0xc3, 0x95, 0x61, 0x89, 0x1b, 0xc6, 0x30, + 0x60, 0x1c, 0xba, 0xb5, 0xb5, 0x27, 0xb5, 0x1b, 0x1c, 0xa4, 0x8a, 0xf7, 0x50, 0x8a, 0x75, 0x34, 0x2f, 0x2c, 0xff, + 0x28, 0x07, 0xca, 0x0a, 0x03, 0xf2, 0x60, 0xd8, 0xf9, 0x98, 0x35, 0x52, 0x0d, 0x5d, 0xba, 0x8e, 0x2b, 0xad, 0xb1, + 0x21, 0x1f, 0x33, 0xec, 0x7e, 0xef, 0x1c, 0x05, 0xed, 0xe9, 0x7a, 0xcb, 0x81, 0x33, 0xac, 0xbd, 0x2f, 0xe3, 0x3c, + 0xf5, 0x72, 0xc1, 0xce, 0xd4, 0xd0, 0x9f, 0xf7, 0x9b, 0xac, 0xa6, 0x60, 0xa3, 0x23, 0xa8, 0xd3, 0x4f, 0x2e, 0x4a, + 0x5c, 0x65, 0x46, 0xd6, 0xfd, 0x96, 0x54, 0x67, 0x82, 0x83, 0xac, 0x2b, 0x94, 0xdf, 0xc5, 0x99, 0xd0, 0x87, 0x26, + 0x35, 0x8b, 0x64, 0xe3, 0x7d, 0x94, 0x1e, 0x18, 0x22, 0x0b, 0x3d, 0x6e, 0xd6, 0x9e, 0xaf, 0x19, 0x27, 0xb1, 0xfc, + 0xd7, 0x85, 0xd3, 0x76, 0xab, 0xf6, 0x08, 0x06, 0x81, 0xe7, 0x5f, 0x45, 0xcc, 0xb6, 0x1a, 0xd6, 0x9d, 0x99, 0xa9, + 0xaa, 0x97, 0xeb, 0xd5, 0xdc, 0x5a, 0x8f, 0x09, 0x15, 0x54, 0x5e, 0xaa, 0xae, 0x32, 0x26, 0x32, 0xf2, 0x63, 0x41, + 0x39, 0xba, 0xba, 0xcd, 0x73, 0xde, 0xa3, 0x3d, 0x8b, 0xdc, 0x0c, 0x80, 0x91, 0x4e, 0xc8, 0x30, 0xe1, 0x16, 0x66, + 0x3a, 0xb2, 0x5a, 0x55, 0x16, 0xf0, 0x51, 0xc3, 0x17, 0x1d, 0xb4, 0xc0, 0xe4, 0xd5, 0x13, 0x87, 0xb3, 0x42, 0x8c, + 0x14, 0xf7, 0xb1, 0x9f, 0x10, 0xf3, 0xc7, 0x69, 0x26, 0xa6, 0x6a, 0xd6, 0x3e, 0xef, 0x7e, 0x07, 0x42, 0x13, 0x43, + 0x74, 0x58, 0x44, 0xaf, 0x43, 0x01, 0x9b, 0xe4, 0xb5, 0x55, 0xb5, 0xc8, 0xf0, 0xeb, 0x81, 0xc6, 0x32, 0x06, 0x21, + 0xcc, 0x25, 0x30, 0xab, 0xfd, 0x74, 0xdb, 0x05, 0x65, 0xa3, 0x48, 0x2b, 0x9c, 0xac, 0x57, 0xac, 0x35, 0xb1, 0x16, + 0x96, 0xe3, 0xa2, 0x43, 0x71, 0x15, 0x1a, 0xb1, 0x8a, 0xa8, 0x75, 0x89, 0x9f, 0xec, 0x14, 0x8d, 0x82, 0xb8, 0x6c, + 0x09, 0x22, 0x6a, 0x72, 0x72, 0xd7, 0x43, 0xea, 0x13, 0x2b, 0xa4, 0x29, 0x41, 0xf8, 0xce, 0x13, 0x94, 0x31, 0x02, + 0xb7, 0x55, 0x6a, 0x8c, 0x0d, 0x25, 0x99, 0x83, 0xc1, 0xf0, 0xcd, 0x04, 0x27, 0x7a, 0x09, 0x65, 0x46, 0xab, 0xe4, + 0x3e, 0x66, 0x4c, 0x63, 0x29, 0x27, 0x33, 0xa3, 0x6f, 0x58, 0xf8, 0xb3, 0x74, 0x21, 0xe7, 0xce, 0x5d, 0x5d, 0x9e, + 0xa9, 0xaf, 0xc8, 0xf3, 0xb9, 0x2d, 0x5c, 0x4b, 0xc6, 0x50, 0x7b, 0xd4, 0x94, 0xad, 0x78, 0xc3, 0x48, 0xaa, 0x71, + 0xfc, 0xaa, 0x97, 0x22, 0xac, 0xbb, 0x62, 0x78, 0xbd, 0xdd, 0x65, 0xe6, 0xda, 0x16, 0xd3, 0x5f, 0xcb, 0xfb, 0x19, + 0x5a, 0x0f, 0x7c, 0x35, 0x74, 0x73, 0x58, 0xf3, 0xfb, 0xa2, 0xdc, 0x23, 0x2c, 0xb7, 0x7f, 0x27, 0xc6, 0xed, 0xeb, + 0x5b, 0x30, 0x58, 0xc8, 0xe7, 0x66, 0x29, 0x6e, 0xb0, 0x7a, 0x90, 0x2e, 0x28, 0x1c, 0x89, 0xa9, 0x5c, 0xbd, 0x6c, + 0xc5, 0x4d, 0xed, 0x76, 0x9b, 0xb1, 0x4e, 0xa4, 0x56, 0xbe, 0x41, 0xb1, 0x6f, 0x7c, 0x81, 0xed, 0x8f, 0x30, 0xb4, + 0xeb, 0x15, 0xe7, 0xb6, 0xfa, 0xb7, 0xbc, 0xe3, 0xf7, 0xfd, 0x61, 0x13, 0x3a, 0xfe, 0x74, 0x7b, 0xe8, 0x86, 0x07, + 0xd2, 0x77, 0x69, 0x5f, 0x76, 0xa5, 0xa8, 0xbf, 0xe4, 0xc0, 0xa9, 0xf3, 0x63, 0x74, 0x5b, 0xf5, 0xa6, 0xde, 0xc7, + 0x11, 0x5e, 0x2a, 0xff, 0xc3, 0xda, 0xe2, 0x3e, 0xcd, 0x47, 0x7b, 0xde, 0x7a, 0xf2, 0xab, 0xdb, 0x74, 0x17, 0x56, + 0x35, 0x7f, 0x2b, 0x53, 0x1a, 0x2f, 0xce, 0x39, 0x60, 0xf6, 0x4f, 0xd4, 0x64, 0x0f, 0x91, 0xa9, 0xe4, 0x38, 0xae, + 0x62, 0x51, 0xeb, 0x49, 0xa1, 0x11, 0x79, 0xc3, 0xd5, 0x9e, 0x47, 0x83, 0x90, 0xd8, 0x01, 0x22, 0x3f, 0x16, 0x85, + 0xa1, 0x23, 0x16, 0x91, 0x76, 0x8d, 0xcf, 0x8b, 0xfa, 0x08, 0x85, 0x58, 0x4d, 0x84, 0x87, 0x05, 0x79, 0x1f, 0x01, + 0x54, 0xda, 0x4b, 0x5a, 0x5b, 0xe9, 0x20, 0xdb, 0x57, 0x82, 0x64, 0x72, 0x60, 0x24, 0xbd, 0x83, 0xd8, 0xce, 0x79, + 0x15, 0x2e, 0xbf, 0x98, 0x9b, 0x42, 0xee, 0xba, 0xca, 0x97, 0x3e, 0x69, 0x6c, 0x72, 0x80, 0xa3, 0xc2, 0xda, 0x57, + 0x4e, 0xc7, 0x41, 0x1f, 0xc4, 0x5e, 0xfe, 0x77, 0x16, 0xb8, 0x64, 0xdd, 0x05, 0xac, 0x97, 0xbe, 0xcf, 0xc3, 0x84, + 0x12, 0x6a, 0xd2, 0xb2, 0x44, 0x17, 0x36, 0x28, 0x55, 0xda, 0x6f, 0x21, 0xe2, 0xb0, 0xc5, 0x97, 0xdc, 0xa6, 0x51, + 0xb7, 0x52, 0xae, 0x6f, 0xe7, 0x94, 0x43, 0xeb, 0x8d, 0x1d, 0xc3, 0xd6, 0x62, 0xbc, 0x70, 0x18, 0x14, 0xa2, 0xa1, + 0xc6, 0x25, 0xcd, 0x57, 0x50, 0x6b, 0xe4, 0x8e, 0x45, 0x4b, 0x32, 0x9c, 0x3e, 0x6e, 0x39, 0x58, 0xa6, 0x81, 0x18, + 0xce, 0xa7, 0x9e, 0xbc, 0x26, 0xf9, 0x40, 0xc1, 0x0d, 0x9a, 0x65, 0x55, 0xd8, 0x1d, 0xd0, 0xbc, 0x0e, 0x1a, 0xad, + 0xa4, 0xc9, 0xa8, 0x4a, 0xba, 0x9f, 0xa6, 0xf8, 0x5d, 0xc6, 0xba, 0x57, 0x94, 0x12, 0xc6, 0xa8, 0xfe, 0xd0, 0x28, + 0x25, 0x07, 0x37, 0xd9, 0xb2, 0x27, 0xd4, 0x25, 0x62, 0xa2, 0x3c, 0x4f, 0xa1, 0x2b, 0xb4, 0x32, 0x72, 0xa8, 0xae, + 0x78, 0x83, 0x2c, 0x0e, 0x76, 0x96, 0x22, 0x99, 0x0f, 0x3a, 0x52, 0xef, 0x13, 0x4d, 0x21, 0x9c, 0xab, 0x64, 0x74, + 0xe3, 0xee, 0x94, 0x1e, 0x24, 0x70, 0xe2, 0x42, 0x47, 0xdb, 0xa1, 0xd7, 0x02, 0x76, 0xa3, 0x12, 0x7a, 0x8a, 0xdf, + 0xe9, 0xf3, 0x2c, 0x78, 0x3b, 0x12, 0xdb, 0x46, 0x31, 0xe6, 0xa8, 0x3a, 0xf5, 0x07, 0x6b, 0xdb, 0x71, 0xdf, 0x64, + 0xc3, 0x2f, 0x26, 0x7f, 0xd4, 0x41, 0x70, 0xcc, 0x3b, 0x59, 0x0e, 0x04, 0x32, 0x80, 0x4a, 0x27, 0x86, 0xf7, 0xc5, + 0x2e, 0x07, 0x85, 0x5f, 0xf5, 0x32, 0x57, 0xda, 0x96, 0x88, 0x8b, 0x8a, 0x83, 0x6f, 0x70, 0x3d, 0xa6, 0x7a, 0x2f, + 0x1d, 0x02, 0xe3, 0x1b, 0xa9, 0x70, 0x73, 0xdf, 0x0a, 0x03, 0x1d, 0x08, 0xca, 0xd9, 0xa8, 0x51, 0xa7, 0x3e, 0x5f, + 0x2d, 0xc8, 0x0b, 0x3c, 0x56, 0x8a, 0x63, 0xd7, 0x75, 0x2f, 0x3c, 0x96, 0x62, 0x3f, 0xa8, 0x50, 0xfe, 0xe7, 0x08, + 0x50, 0x89, 0x00, 0x46, 0xad, 0xd8, 0xca, 0xee, 0x7f, 0x31, 0x5d, 0xa6, 0xba, 0xa4, 0x48, 0xfd, 0x95, 0xe5, 0x24, + 0x7f, 0xe4, 0x61, 0x8f, 0xca, 0xc6, 0x83, 0x2d, 0x46, 0x81, 0x03, 0x78, 0x98, 0xa4, 0xf0, 0x56, 0xc6, 0x78, 0x5d, + 0xc5, 0x5a, 0x23, 0x15, 0x82, 0x64, 0x66, 0xb7, 0x8d, 0x7c, 0x91, 0x9f, 0x26, 0x41, 0x13, 0x3f, 0xa7, 0xde, 0x2b, + 0x4c, 0x3b, 0x76, 0xd6, 0x12, 0x05, 0xf4, 0xf2, 0x0e, 0xa1, 0x43, 0x56, 0xf1, 0xe5, 0xd4, 0x9a, 0x45, 0x40, 0x62, + 0x71, 0x6d, 0x7c, 0x4d, 0xb3, 0x7d, 0x9e, 0xc5, 0x08, 0xcb, 0x2f, 0xa8, 0x82, 0xcb, 0x14, 0xa8, 0x95, 0xda, 0xb3, + 0xee, 0x30, 0xd8, 0xa1, 0x2c, 0x63, 0x7a, 0x11, 0xb2, 0x28, 0xd2, 0xc4, 0x5a, 0xed, 0x62, 0x34, 0x20, 0xc1, 0x25, + 0x4c, 0x54, 0x28, 0x23, 0xcb, 0x18, 0x90, 0xe6, 0x96, 0xb5, 0x7d, 0x91, 0x51, 0x41, 0xbd, 0xfd, 0xcf, 0xac, 0xf6, + 0x3d, 0x2c, 0xd2, 0xf6, 0x4a, 0xba, 0x7e, 0xff, 0xdb, 0x4d, 0xe8, 0xf2, 0x45, 0xdf, 0x3d, 0x7c, 0xc5, 0x9a, 0xed, + 0x0d, 0x7c, 0xe9, 0xc3, 0xa0, 0x49, 0x99, 0x1c, 0x0a, 0x03, 0xcd, 0x32, 0x6e, 0x44, 0x6b, 0x07, 0x3c, 0xb2, 0xc3, + 0xb2, 0x89, 0xbc, 0xce, 0x6b, 0xaa, 0x67, 0x57, 0xa4, 0x61, 0x96, 0x26, 0xc5, 0x05, 0xa0, 0xb7, 0xbe, 0xd2, 0x35, + 0x55, 0x23, 0x4b, 0x60, 0x82, 0x62, 0x10, 0x6f, 0x4e, 0x65, 0x97, 0x36, 0xba, 0xf0, 0x28, 0x6f, 0x62, 0xac, 0x1f, + 0xb1, 0xdd, 0x01, 0x81, 0x4a, 0xd5, 0x02, 0x75, 0x2f, 0x0c, 0xe6, 0xe4, 0xaa, 0xa3, 0xda, 0xca, 0x48, 0x90, 0x4d, + 0xc3, 0x36, 0xbf, 0xd0, 0x70, 0x47, 0xc9, 0x26, 0x41, 0x52, 0xc8, 0x26, 0x63, 0xce, 0x8b, 0xda, 0xbd, 0x22, 0x66, + 0xa2, 0x4f, 0x1e, 0xdb, 0x39, 0xc8, 0x74, 0xb7, 0xcf, 0xe9, 0x63, 0x95, 0xc0, 0xe1, 0x9e, 0x46, 0x31, 0x3b, 0x5a, + 0xe1, 0xcf, 0x0b, 0xda, 0x9a, 0x61, 0xec, 0x21, 0x5c, 0xbd, 0x95, 0x12, 0x48, 0xdc, 0x8b, 0x2a, 0x38, 0xdb, 0x90, + 0xf4, 0xdb, 0xd1, 0x67, 0x4a, 0x8e, 0xe4, 0xca, 0x7e, 0x41, 0x5b, 0x27, 0x4e, 0x7c, 0x04, 0xe7, 0xed, 0xd6, 0x0b, + 0x43, 0x4f, 0x5b, 0xba, 0x0b, 0x5f, 0x16, 0xf7, 0x72, 0x75, 0x46, 0x3d, 0xb8, 0x8e, 0x4b, 0xb5, 0x20, 0x11, 0x2c, + 0x5a, 0xe7, 0x22, 0x5d, 0xe0, 0xe5, 0x78, 0xe4, 0xfc, 0x54, 0xc4, 0xae, 0xa0, 0x85, 0xf8, 0x90, 0x89, 0x8a, 0xf5, + 0xd6, 0xd1, 0x9f, 0xb8, 0x27, 0xd2, 0x20, 0xb7, 0xeb, 0xd1, 0x8e, 0xec, 0xe1, 0x47, 0xb5, 0xe4, 0x8a, 0xc2, 0x5e, + 0x25, 0x3b, 0xdf, 0xf5, 0x1a, 0x33, 0xeb, 0x9b, 0x65, 0x1f, 0x42, 0xb0, 0x80, 0xec, 0x14, 0xdf, 0xcb, 0x0b, 0xc8, + 0xbf, 0xc8, 0x58, 0x66, 0x31, 0x30, 0x93, 0x61, 0xc3, 0xe0, 0x1f, 0xb4, 0xa8, 0xd4, 0xcb, 0xe9, 0x38, 0xb8, 0x23, + 0x8e, 0x86, 0x43, 0x32, 0x55, 0x25, 0xdd, 0x3f, 0x18, 0x65, 0x5d, 0x0a, 0x27, 0x98, 0x64, 0xda, 0xfe, 0x15, 0xb4, + 0xda, 0x35, 0xef, 0x48, 0x72, 0x22, 0x3b, 0x53, 0xbb, 0xa6, 0x71, 0x43, 0xeb, 0x96, 0xce, 0x1d, 0xbd, 0x7b, 0x06, + 0x0f, 0xac, 0xbc, 0xe2, 0x6d, 0x49, 0xe2, 0x9d, 0x40, 0x85, 0x77, 0x03, 0x55, 0xde, 0x0b, 0xb4, 0xf1, 0xbe, 0xa4, + 0x9d, 0x0f, 0x02, 0x19, 0x5b, 0x88, 0xb9, 0xd5, 0x5c, 0x37, 0xb7, 0x9e, 0x8b, 0xb5, 0x7e, 0x30, 0x48, 0xb5, 0x1b, + 0xff, 0x9c, 0x3c, 0xfb, 0x52, 0xb7, 0xdd, 0x8e, 0xfb, 0xf9, 0xfe, 0x69, 0xb4, 0xb7, 0x3f, 0x99, 0x42, 0xe7, 0x45, + 0x12, 0x69, 0x7c, 0xee, 0xf5, 0x30, 0x04, 0xeb, 0xdc, 0x18, 0x7d, 0xdd, 0x05, 0x0d, 0xe5, 0x2e, 0x6c, 0x97, 0x7f, + 0xee, 0xfd, 0xc7, 0x93, 0x5f, 0x15, 0xf5, 0xd8, 0xfa, 0x50, 0x9a, 0xc5, 0x65, 0x00, 0xae, 0x3b, 0xd1, 0x78, 0xe5, + 0x82, 0x37, 0x86, 0xfe, 0xcc, 0x92, 0x96, 0x98, 0x47, 0x44, 0x3d, 0xd1, 0x12, 0xd7, 0x94, 0x49, 0x9f, 0x87, 0x2e, + 0xb1, 0xe4, 0xc8, 0x0d, 0xfb, 0x5b, 0xff, 0x85, 0x86, 0x3b, 0xad, 0xc6, 0x54, 0x8e, 0xfd, 0xfd, 0xb5, 0x81, 0xea, + 0x72, 0x28, 0xcd, 0xa6, 0x0f, 0x09, 0x13, 0xf5, 0x71, 0x0c, 0x77, 0x6e, 0x0c, 0x17, 0x78, 0x79, 0xb5, 0xa0, 0x5b, + 0x6d, 0xc0, 0x00, 0xcf, 0x79, 0x03, 0x50, 0xc9, 0x08, 0xfc, 0x0b, 0xde, 0xaf, 0x5a, 0x94, 0xe1, 0x8b, 0xd1, 0xef, + 0xce, 0xaf, 0xb6, 0x1f, 0x88, 0x13, 0x1e, 0x2d, 0x56, 0xe8, 0x9a, 0x99, 0xff, 0xb0, 0xc2, 0x7a, 0x8e, 0xbd, 0x9b, + 0xaf, 0x72, 0xde, 0xda, 0x0b, 0xe8, 0xed, 0xae, 0x40, 0x88, 0x40, 0xa3, 0xab, 0xc3, 0x59, 0xdf, 0xe6, 0x8f, 0x1f, + 0x52, 0x36, 0x13, 0x06, 0xe0, 0xd3, 0xca, 0x87, 0x7f, 0x37, 0x7f, 0x53, 0xbc, 0x48, 0xe1, 0x7e, 0xfd, 0xbe, 0x2a, + 0xc2, 0x7f, 0x61, 0x60, 0x7c, 0xc7, 0xc9, 0x05, 0x79, 0x6c, 0xde, 0xae, 0x2c, 0xef, 0xd0, 0xba, 0x68, 0xb1, 0xaf, + 0xcd, 0x13, 0x75, 0xf3, 0xf9, 0x27, 0xaa, 0x39, 0xb7, 0xab, 0xc7, 0xeb, 0xe6, 0xf7, 0xbb, 0xa9, 0x39, 0x7f, 0xc8, + 0x5f, 0xdd, 0x3f, 0x3a, 0xba, 0x6a, 0x38, 0x18, 0x5d, 0x7f, 0x9d, 0x65, 0xbb, 0x61, 0xfe, 0x7e, 0xd1, 0xca, 0x51, + 0x62, 0x95, 0x9a, 0xe5, 0x0f, 0x7b, 0x1f, 0xf3, 0x69, 0x5a, 0xd7, 0xbb, 0x5f, 0xbf, 0xc0, 0xfc, 0x0f, 0x71, 0x23, + 0xda, 0xc3, 0xe3, 0x3f, 0x1b, 0xff, 0xb4, 0x59, 0x73, 0x12, 0x7a, 0x32, 0xd6, 0x2a, 0x88, 0x1a, 0xe3, 0xe9, 0xf9, + 0xc8, 0x90, 0xc6, 0x7f, 0x7a, 0x52, 0x4e, 0x98, 0xe5, 0xc4, 0xd2, 0x7d, 0x4b, 0x78, 0x28, 0x15, 0xe5, 0x46, 0x71, + 0x3c, 0x26, 0xfc, 0xaf, 0x3d, 0xb9, 0x2d, 0x56, 0x29, 0x33, 0x80, 0xfb, 0xa1, 0xe6, 0xfb, 0xc5, 0x75, 0x32, 0x08, + 0xd2, 0x84, 0x89, 0x19, 0x83, 0x31, 0x51, 0x4e, 0xdd, 0x50, 0x08, 0xbe, 0x91, 0x53, 0x8a, 0x9c, 0x5a, 0xba, 0x3f, + 0x11, 0x1e, 0x0e, 0xcf, 0xee, 0x86, 0xa3, 0xdd, 0xcf, 0x1f, 0xb8, 0x9d, 0xe4, 0xd4, 0x98, 0x2f, 0x4f, 0x8d, 0xc6, + 0x9e, 0x01, 0x73, 0xba, 0x40, 0xa7, 0xd5, 0x33, 0xa4, 0xfd, 0x62, 0x20, 0x18, 0xba, 0xf2, 0xd0, 0x76, 0xf1, 0x6d, + 0x8b, 0xcb, 0x8f, 0x0d, 0x7a, 0xcd, 0xb0, 0x1a, 0xfc, 0x53, 0x03, 0xd6, 0x18, 0x13, 0x71, 0x8c, 0x09, 0x4c, 0xf9, + 0x96, 0x66, 0xdd, 0x92, 0x1d, 0x6c, 0xec, 0x29, 0xe5, 0x31, 0x52, 0x32, 0x87, 0xbc, 0x6c, 0xda, 0x98, 0x1b, 0x3c, + 0x2b, 0x9f, 0xe7, 0x76, 0xd2, 0x8e, 0xd0, 0x48, 0xc8, 0xf7, 0xac, 0xd8, 0xa4, 0xe8, 0xcc, 0x21, 0xee, 0x6c, 0x9d, + 0xcd, 0x31, 0x3e, 0x71, 0x44, 0x94, 0xdd, 0x7b, 0xd1, 0xd1, 0xbe, 0xd2, 0x17, 0xe4, 0x6c, 0x2e, 0xbf, 0xcd, 0x31, + 0xcf, 0xf2, 0xe8, 0x91, 0xf4, 0x42, 0xdf, 0x4b, 0x33, 0x8e, 0xc7, 0xbc, 0x6a, 0x69, 0x9e, 0xdd, 0x83, 0x78, 0x46, + 0x21, 0x68, 0x33, 0x4c, 0x7f, 0x7c, 0x33, 0x9f, 0x22, 0x75, 0x2f, 0xe3, 0x5e, 0x36, 0x0d, 0xe8, 0xb0, 0xa1, 0x03, + 0xaa, 0x42, 0x82, 0xa9, 0x55, 0xe8, 0x77, 0x2b, 0x2e, 0xb3, 0x55, 0x5a, 0xbc, 0x45, 0x73, 0x77, 0x65, 0x12, 0x97, + 0x11, 0xfa, 0xdd, 0xf5, 0x45, 0xb2, 0x3e, 0x03, 0xc6, 0x2d, 0x36, 0x14, 0xb3, 0xff, 0x58, 0xea, 0xf1, 0x89, 0x96, + 0x91, 0x81, 0x7d, 0x7d, 0x79, 0xee, 0xae, 0xb5, 0x67, 0x1b, 0x15, 0xb1, 0x31, 0xc5, 0xdc, 0xdc, 0xfa, 0x79, 0xb6, + 0x22, 0x99, 0xdc, 0x36, 0xe1, 0x0c, 0x98, 0xa3, 0x6b, 0xb8, 0x2b, 0x88, 0x71, 0x16, 0x40, 0x43, 0xe1, 0x6c, 0xdf, + 0x84, 0xcb, 0x0b, 0x49, 0x6c, 0x8c, 0x12, 0x7d, 0xe9, 0x7f, 0x77, 0x7e, 0x6a, 0xd0, 0x0f, 0x92, 0xd0, 0x73, 0xef, + 0xd1, 0xe9, 0xf6, 0xa7, 0xf9, 0x54, 0xfd, 0xac, 0xb5, 0x8d, 0x2f, 0xa0, 0x4f, 0x7d, 0x68, 0x79, 0xfb, 0x98, 0x51, + 0x80, 0x95, 0x94, 0xe2, 0x6b, 0x47, 0x75, 0x4c, 0xfd, 0x2d, 0x62, 0xea, 0xf8, 0x8d, 0x91, 0x47, 0xdd, 0xce, 0xa5, + 0x8f, 0x79, 0x33, 0xed, 0xb4, 0x67, 0x09, 0x38, 0xc7, 0x7b, 0xb1, 0xa5, 0x27, 0xbd, 0xee, 0x0b, 0x0e, 0x6c, 0x76, + 0x15, 0xf3, 0x36, 0xd7, 0xd0, 0x66, 0xed, 0xe6, 0xef, 0x6a, 0xec, 0x95, 0xf5, 0x56, 0x0f, 0x92, 0xad, 0xbe, 0xcc, + 0xf3, 0xf3, 0x6b, 0x7e, 0x5b, 0x2a, 0x95, 0xb8, 0x53, 0xc6, 0x77, 0xde, 0xff, 0xbe, 0x86, 0xea, 0xd4, 0x53, 0x46, + 0x29, 0xcc, 0x08, 0xcb, 0x27, 0xcf, 0xd3, 0xf2, 0x97, 0x5d, 0xd6, 0x67, 0x3b, 0x6f, 0xc1, 0xd1, 0xe5, 0xc0, 0x71, + 0x62, 0x16, 0x81, 0xef, 0xf1, 0x15, 0x84, 0xf2, 0xe5, 0x14, 0xb0, 0x25, 0xff, 0xc6, 0x84, 0xe4, 0x96, 0x67, 0x2d, + 0x49, 0x6d, 0x24, 0x16, 0x62, 0x38, 0x71, 0xda, 0xf5, 0x01, 0x20, 0xde, 0x22, 0x02, 0xf2, 0x49, 0xe6, 0x7e, 0xb0, + 0xa0, 0x17, 0xc3, 0x02, 0x7b, 0xbe, 0x14, 0x15, 0xbd, 0xe0, 0x1f, 0x32, 0x68, 0xd5, 0x4a, 0x66, 0x0a, 0x0f, 0x52, + 0x50, 0x72, 0xe2, 0xb1, 0xf8, 0x44, 0x08, 0x6d, 0x74, 0x16, 0xca, 0x30, 0x27, 0x6e, 0x79, 0x9a, 0x83, 0xab, 0xcb, + 0xac, 0xf5, 0x62, 0xec, 0xdd, 0x61, 0xe7, 0x11, 0x32, 0xdc, 0x1f, 0xae, 0xcb, 0xda, 0x92, 0xb6, 0x04, 0xb4, 0xd6, + 0x4e, 0x80, 0x3e, 0xea, 0xd2, 0x2d, 0x77, 0x5d, 0x02, 0x0b, 0xa7, 0xec, 0xee, 0x02, 0xec, 0x82, 0x64, 0xc6, 0xf9, + 0x19, 0xec, 0xdc, 0xe3, 0x0f, 0xf0, 0xfd, 0x0c, 0xda, 0x02, 0x7c, 0x3b, 0x83, 0xf5, 0xeb, 0x08, 0x7c, 0x3d, 0x03, + 0x73, 0x00, 0x67, 0x67, 0xf0, 0x57, 0xf1, 0x7b, 0xe9, 0xe9, 0x19, 0xf8, 0x97, 0x0a, 0x5f, 0xd8, 0x8d, 0x35, 0x84, + 0x13, 0xd6, 0xbc, 0x16, 0x8e, 0xe1, 0x80, 0xd7, 0xac, 0x5d, 0x61, 0x0f, 0xbf, 0x23, 0x63, 0xb0, 0x8f, 0xd8, 0x23, + 0x6f, 0x70, 0xc4, 0xec, 0x0e, 0x87, 0x97, 0x86, 0x77, 0xfb, 0xff, 0xb1, 0xb1, 0x3c, 0x4c, 0xd8, 0x7e, 0x8b, 0xbf, + 0x54, 0x42, 0x85, 0xcf, 0xff, 0x53, 0xbd, 0x80, 0xe9, 0x19, 0xd4, 0x05, 0xf8, 0x74, 0x06, 0xdb, 0x02, 0x7c, 0x3c, + 0x83, 0xdb, 0x52, 0xd7, 0x0d, 0x70, 0x70, 0x06, 0x7a, 0x07, 0x3e, 0x9c, 0xc1, 0xe6, 0x1b, 0x78, 0x73, 0x06, 0xea, + 0xf8, 0xed, 0x81, 0xb7, 0x67, 0xa0, 0x57, 0xe0, 0x9d, 0x67, 0x60, 0xe0, 0xfd, 0xdf, 0x38, 0x7f, 0x83, 0x91, 0x53, + 0x76, 0x9f, 0xe5, 0x2b, 0x46, 0xd3, 0x0f, 0xc9, 0x63, 0x27, 0xce, 0x2c, 0xc0, 0x67, 0xfb, 0x6f, 0xa4, 0xe9, 0x26, + 0x5b, 0x6c, 0x02, 0x29, 0x5c, 0x55, 0x66, 0x0c, 0x8c, 0xff, 0x23, 0x7e, 0x66, 0x0e, 0x86, 0x46, 0x12, 0x1b, 0xd9, + 0xc0, 0xaa, 0xed, 0xf9, 0x3f, 0xb6, 0x09, 0xbb, 0x5b, 0x45, 0xb6, 0x73, 0xef, 0xf1, 0xe3, 0xa3, 0xfb, 0xca, 0xa6, + 0xb1, 0x48, 0x03, 0xaa, 0xba, 0x80, 0x8e, 0x94, 0x52, 0x0b, 0xe6, 0x6e, 0xf5, 0x4f, 0x84, 0x6f, 0x2e, 0x78, 0x84, + 0xd9, 0xad, 0x34, 0x52, 0x80, 0x94, 0x99, 0xfe, 0x27, 0x57, 0x7b, 0xa4, 0x2c, 0x3d, 0xcb, 0xa2, 0xf2, 0xa9, 0xf7, + 0xc9, 0xcb, 0xe4, 0x98, 0x65, 0x2e, 0xd4, 0x38, 0xf4, 0xf3, 0x14, 0x02, 0xca, 0x21, 0x25, 0xdc, 0x9e, 0x86, 0x97, + 0x8c, 0xe1, 0x5b, 0x72, 0xeb, 0x05, 0xf6, 0x9e, 0x60, 0xc8, 0xed, 0x98, 0x02, 0xab, 0x98, 0xa9, 0x0d, 0xfa, 0x08, + 0xc4, 0x71, 0x53, 0x6a, 0xfc, 0x35, 0xfa, 0xf0, 0x76, 0xb1, 0xab, 0xe3, 0x60, 0x50, 0xf5, 0x3b, 0x0d, 0x8f, 0x88, + 0x4a, 0xca, 0x21, 0x8b, 0x16, 0x59, 0xb2, 0xfd, 0x85, 0x03, 0x4a, 0xd0, 0x44, 0xbb, 0xd2, 0xf2, 0x9a, 0x14, 0xbc, + 0x1c, 0x5d, 0x30, 0x19, 0x8e, 0x67, 0xf0, 0x0c, 0x52, 0x7f, 0xce, 0x1b, 0x5e, 0x01, 0xda, 0xe0, 0x93, 0xee, 0xd7, + 0x75, 0xc7, 0x17, 0x7a, 0x47, 0x69, 0xc6, 0x15, 0x3e, 0x8b, 0xdf, 0x30, 0xcb, 0x5c, 0xff, 0x46, 0x90, 0x66, 0x7b, + 0xeb, 0x69, 0x0b, 0x60, 0xfe, 0x01, 0xdb, 0xb3, 0x97, 0x33, 0x5c, 0x6c, 0xed, 0x51, 0x54, 0x2b, 0x2d, 0x38, 0xe8, + 0x6e, 0x33, 0xe0, 0x6e, 0x31, 0xb8, 0x67, 0x47, 0x7b, 0x25, 0x14, 0x4e, 0x44, 0xab, 0x0c, 0x45, 0x76, 0x00, 0xdf, + 0xb1, 0xb1, 0x25, 0x1a, 0xe9, 0xf4, 0xa0, 0x6f, 0xd0, 0xb6, 0x44, 0x10, 0xb6, 0x6e, 0xb7, 0x88, 0x81, 0xec, 0x55, + 0xe2, 0x7f, 0x5f, 0xee, 0x65, 0xd4, 0xd2, 0x4c, 0xdf, 0xe3, 0x3b, 0xe6, 0xa7, 0xb4, 0x50, 0x9f, 0x24, 0x65, 0xec, + 0x34, 0xfe, 0xe9, 0xcf, 0x90, 0xe7, 0x78, 0xd5, 0x55, 0x00, 0x14, 0xdc, 0xd0, 0x28, 0xfe, 0x90, 0xcf, 0x9a, 0xb0, + 0x70, 0x19, 0x79, 0x5c, 0x30, 0xc0, 0x2c, 0x73, 0xdc, 0xc4, 0xd8, 0x70, 0x71, 0x58, 0x70, 0x98, 0x99, 0x74, 0x99, + 0xd1, 0xeb, 0x62, 0x5c, 0x8a, 0xd6, 0x7d, 0x35, 0x35, 0x7e, 0x93, 0x19, 0xa1, 0x0f, 0x4f, 0xc3, 0x80, 0x5d, 0xc4, + 0xd8, 0xbf, 0x6b, 0x70, 0x55, 0x30, 0xb6, 0x55, 0x83, 0x15, 0xa5, 0x66, 0x95, 0xbf, 0x7c, 0x76, 0xd4, 0x1f, 0xde, + 0xe4, 0xd6, 0x33, 0x06, 0x0c, 0xfb, 0x82, 0x09, 0x6d, 0xca, 0xdf, 0x1b, 0x93, 0x88, 0x5e, 0x70, 0x6e, 0x7c, 0x4a, + 0x16, 0x6e, 0x9a, 0x61, 0x2a, 0x76, 0xd0, 0x24, 0x75, 0x08, 0xb1, 0x89, 0xbf, 0x7d, 0xf2, 0xe4, 0x39, 0xa4, 0x7c, + 0x4e, 0x44, 0x92, 0x68, 0x75, 0x47, 0xf1, 0x6c, 0xe2, 0x8a, 0x67, 0x41, 0x54, 0x72, 0x03, 0xc0, 0x11, 0xe8, 0xd2, + 0x74, 0xf8, 0xdd, 0x7e, 0xdc, 0x6b, 0x03, 0xcc, 0x36, 0xd6, 0xdd, 0xc7, 0xa1, 0x31, 0xe5, 0x19, 0xdd, 0x0f, 0x7a, + 0xe5, 0x39, 0x78, 0x9a, 0x5f, 0xa6, 0x24, 0x43, 0x86, 0xd5, 0xcc, 0xa1, 0xc3, 0x75, 0x54, 0xe5, 0x1a, 0xb4, 0xe0, + 0x63, 0xaa, 0xd4, 0xc8, 0x9b, 0xf7, 0x87, 0xeb, 0x82, 0xe4, 0x68, 0x07, 0xb4, 0xf6, 0x7a, 0x98, 0x5d, 0x08, 0x0c, + 0x52, 0x48, 0xb8, 0x63, 0x5b, 0x7b, 0x7f, 0xa7, 0x87, 0xeb, 0xed, 0x4b, 0x94, 0x5b, 0x6f, 0x7d, 0x60, 0x96, 0xfe, + 0xa4, 0xb3, 0x2b, 0xc3, 0x8e, 0xbf, 0x5a, 0x93, 0x0f, 0x6f, 0x6a, 0x6d, 0xa4, 0x64, 0xfa, 0xea, 0x82, 0x1f, 0x27, + 0x8c, 0x09, 0x9e, 0x81, 0x98, 0x10, 0xd5, 0xe9, 0x7a, 0x49, 0x22, 0x8a, 0xad, 0x09, 0x91, 0x52, 0x24, 0x11, 0xc9, + 0x49, 0xba, 0xab, 0x9b, 0xe2, 0x93, 0xd3, 0x13, 0x69, 0xe6, 0x0e, 0x0c, 0x60, 0xa9, 0x4f, 0xcf, 0xe6, 0x2c, 0x7f, + 0x23, 0x10, 0x7e, 0x94, 0x02, 0x96, 0xd6, 0x60, 0xf2, 0x80, 0xbd, 0xa4, 0x7e, 0xa6, 0xea, 0x2e, 0x9a, 0x14, 0xc9, + 0xa3, 0x67, 0x80, 0xad, 0x9c, 0x72, 0x84, 0x2a, 0xd3, 0x4c, 0x48, 0x8e, 0x73, 0x6b, 0x32, 0x27, 0x21, 0x94, 0x9c, + 0x99, 0x7b, 0xc4, 0xf2, 0x29, 0xfc, 0xb2, 0x29, 0x6f, 0x7a, 0x27, 0x5b, 0x8a, 0x75, 0x35, 0x84, 0xe1, 0xc4, 0x80, + 0xdf, 0x42, 0xec, 0xf5, 0xd6, 0x91, 0x34, 0xc8, 0x79, 0xf2, 0x8c, 0x23, 0x6c, 0x5c, 0x62, 0xa3, 0x6f, 0x36, 0x4a, + 0x12, 0x72, 0x40, 0x26, 0xbb, 0x50, 0x72, 0x72, 0x07, 0xef, 0xc1, 0xc7, 0x36, 0xdd, 0x9f, 0xff, 0xca, 0x13, 0xad, + 0x6a, 0x63, 0x60, 0xd5, 0xd7, 0x03, 0x59, 0x99, 0x7c, 0x25, 0x40, 0x5b, 0xc0, 0x85, 0xe4, 0x6f, 0x7f, 0xc5, 0x71, + 0x88, 0xaf, 0x32, 0xc8, 0x60, 0xd4, 0xe2, 0x8b, 0xc8, 0x3e, 0xb5, 0x62, 0xe3, 0xef, 0x94, 0xe6, 0x0a, 0x56, 0xb5, + 0x2f, 0x41, 0x64, 0x71, 0x68, 0xba, 0x4f, 0x73, 0xb0, 0x46, 0xad, 0x3f, 0x52, 0xe4, 0x6c, 0x8a, 0xd6, 0x1f, 0x4a, + 0x68, 0x24, 0x2b, 0xde, 0xea, 0x8b, 0x4b, 0xea, 0x2c, 0xaa, 0xa7, 0xa7, 0xc4, 0xa2, 0x62, 0x37, 0x6f, 0x6f, 0x71, + 0x4d, 0xd6, 0x2d, 0xb8, 0x1c, 0x59, 0x19, 0xbe, 0x5d, 0xe9, 0x6c, 0xca, 0xf3, 0x7b, 0x7a, 0x36, 0xb6, 0x60, 0x1f, + 0x7c, 0x6b, 0x53, 0x49, 0x73, 0x61, 0xc5, 0xaf, 0xf2, 0x70, 0x85, 0xdf, 0x90, 0xa0, 0x50, 0x85, 0x3f, 0xbd, 0x48, + 0x8e, 0x8b, 0xef, 0x88, 0x3d, 0x68, 0x5b, 0x83, 0x86, 0xb3, 0x08, 0x33, 0x21, 0x21, 0xe1, 0x00, 0x64, 0xf2, 0x61, + 0xdc, 0x2a, 0xa9, 0x25, 0xb6, 0xa4, 0x97, 0x23, 0x31, 0xe0, 0xf2, 0x5b, 0xb7, 0xc9, 0x4a, 0x57, 0x4f, 0xc1, 0x24, + 0x6e, 0x60, 0x05, 0x53, 0x8f, 0xe3, 0x1b, 0xa5, 0xb3, 0xd2, 0x12, 0x89, 0x04, 0x63, 0x21, 0x44, 0x7d, 0x3f, 0xf5, + 0x26, 0x33, 0x64, 0x45, 0x23, 0x8d, 0x48, 0xd3, 0x4d, 0x30, 0x03, 0x31, 0x81, 0xc2, 0x3c, 0xe6, 0xd6, 0x08, 0x11, + 0x66, 0x98, 0x6e, 0x22, 0x5d, 0xeb, 0x06, 0xcb, 0xf1, 0xfe, 0xa9, 0x1e, 0x8d, 0x79, 0xec, 0x06, 0xb5, 0xb6, 0x91, + 0x86, 0x31, 0x9e, 0xae, 0x10, 0x42, 0xb7, 0x10, 0xc5, 0xc3, 0x9a, 0xb5, 0x9a, 0xc6, 0x7e, 0x74, 0x6d, 0xf7, 0x20, + 0x00, 0xce, 0x63, 0x98, 0x5e, 0x06, 0x51, 0xd2, 0x2b, 0x13, 0x32, 0x1e, 0x91, 0x66, 0xe4, 0xc9, 0x15, 0xad, 0x22, + 0xad, 0xc1, 0xc2, 0xaa, 0x12, 0xc9, 0x9f, 0xa0, 0x52, 0x08, 0x49, 0xfa, 0x9e, 0xe6, 0xc3, 0xa3, 0xa5, 0x32, 0x56, + 0xbc, 0xa7, 0xef, 0xf3, 0xdb, 0xd5, 0x7c, 0x8d, 0x48, 0x98, 0x27, 0x40, 0x7c, 0x5d, 0xc0, 0x71, 0x5e, 0x95, 0x7c, + 0x0a, 0x12, 0x03, 0x03, 0xa1, 0x10, 0x6a, 0xbf, 0xc7, 0x99, 0xbb, 0x2a, 0x2b, 0x85, 0x20, 0x79, 0xb8, 0x15, 0xc5, + 0xcd, 0x48, 0xa5, 0xb1, 0x22, 0x48, 0xc6, 0x77, 0xf3, 0xa5, 0xaf, 0x25, 0x7b, 0xeb, 0x41, 0x26, 0x13, 0xc4, 0x59, + 0xfc, 0x7f, 0x96, 0x37, 0xcd, 0x7e, 0xbf, 0xf8, 0x52, 0x13, 0x23, 0x45, 0xb2, 0x97, 0x6a, 0xf2, 0xf4, 0x2f, 0x53, + 0x96, 0x01, 0x87, 0x44, 0x4b, 0x5f, 0xa1, 0x09, 0x0e, 0xb4, 0x21, 0xb3, 0x59, 0x80, 0x50, 0x48, 0x69, 0x31, 0xda, + 0x5d, 0xa4, 0x3a, 0xcb, 0xea, 0x98, 0x9d, 0x35, 0x33, 0x2c, 0x2a, 0xfd, 0x10, 0xb3, 0xa7, 0x61, 0xa6, 0x37, 0x59, + 0xf1, 0x8f, 0xd9, 0x4d, 0xca, 0xaf, 0xd9, 0x4d, 0x51, 0x06, 0x45, 0x1e, 0x1c, 0xe4, 0x90, 0x0b, 0xee, 0x26, 0x36, + 0x12, 0x75, 0x0f, 0x96, 0x0d, 0x93, 0x8b, 0x13, 0xbb, 0x24, 0x90, 0xb4, 0xc1, 0xe3, 0xbd, 0xde, 0x47, 0xf8, 0x90, + 0x0a, 0xf3, 0x7c, 0xfc, 0x21, 0x93, 0x93, 0xc9, 0x85, 0xcb, 0xea, 0x07, 0x66, 0x77, 0x41, 0xa2, 0x07, 0xe6, 0xc7, + 0xee, 0xd8, 0x49, 0x94, 0x82, 0x4c, 0xe6, 0x7a, 0x8b, 0xb4, 0xc7, 0xf4, 0xb1, 0x59, 0x75, 0xbf, 0x8c, 0xea, 0xfe, + 0xa0, 0xe8, 0x15, 0x8e, 0xb0, 0xf7, 0xa3, 0x72, 0x12, 0x68, 0xea, 0x29, 0x77, 0x6d, 0xe0, 0xde, 0xab, 0x58, 0x98, + 0xbc, 0x99, 0xe5, 0x1b, 0xcf, 0xb6, 0x2f, 0x52, 0xe7, 0xd9, 0x3a, 0x6a, 0x76, 0x1f, 0x97, 0x95, 0x64, 0x89, 0x73, + 0x81, 0x32, 0x46, 0xa0, 0x9a, 0x86, 0xe7, 0xae, 0x0b, 0x9b, 0x49, 0x69, 0x38, 0x8d, 0x9e, 0x50, 0x35, 0x48, 0x9d, + 0x53, 0x8a, 0x46, 0xb3, 0xf8, 0x2e, 0xe5, 0x9c, 0xe7, 0x4c, 0x38, 0x00, 0xa5, 0x94, 0x4b, 0x25, 0xcb, 0xf6, 0xf1, + 0x98, 0x0a, 0x7e, 0x67, 0xa2, 0xf0, 0x47, 0x17, 0x78, 0xe4, 0xba, 0xee, 0x6e, 0x08, 0x63, 0xe5, 0x0a, 0x3a, 0x83, + 0xf3, 0x3a, 0xf6, 0x8b, 0xce, 0x30, 0x19, 0x9e, 0xc1, 0xa8, 0x9e, 0xe5, 0x0c, 0xef, 0x57, 0x71, 0x5b, 0x56, 0x9e, + 0xbf, 0x73, 0x5d, 0x6b, 0xf3, 0x03, 0xce, 0x50, 0x53, 0x0f, 0x73, 0xa5, 0xc6, 0xf9, 0x9a, 0x01, 0x77, 0xaf, 0xe5, + 0x39, 0x58, 0x51, 0x61, 0xc1, 0x16, 0xcc, 0xb0, 0x01, 0xaa, 0x8b, 0xfc, 0x28, 0xa9, 0x60, 0x85, 0x0b, 0xaf, 0x57, + 0xfb, 0xeb, 0xaa, 0x0f, 0xa8, 0xa1, 0xcc, 0x3d, 0xae, 0xf0, 0x90, 0xfa, 0x0a, 0xbb, 0x12, 0x23, 0xbb, 0x05, 0xd7, + 0x78, 0xdc, 0xf6, 0xe6, 0xb5, 0x78, 0x2c, 0x9a, 0x9d, 0xf6, 0x23, 0xc6, 0x26, 0x16, 0xcf, 0xc2, 0x42, 0x27, 0xc9, + 0x99, 0xef, 0xbc, 0x57, 0x8a, 0xf2, 0xfc, 0x81, 0xb1, 0x9f, 0x25, 0x91, 0x20, 0x94, 0xd4, 0xf6, 0x4f, 0x08, 0xad, + 0x61, 0xaa, 0xa5, 0x34, 0x17, 0xd1, 0xe7, 0x1a, 0x0c, 0x98, 0x12, 0x66, 0x39, 0x8d, 0xca, 0x6b, 0x5b, 0xb6, 0x63, + 0xde, 0xf9, 0x53, 0xa9, 0x05, 0x91, 0xcc, 0x8f, 0xd1, 0x88, 0x60, 0x43, 0x4c, 0x90, 0x79, 0x33, 0x9f, 0x96, 0xd3, + 0x92, 0xcf, 0xbb, 0xf9, 0xc3, 0xe2, 0x81, 0xca, 0x6d, 0xf5, 0xb9, 0xa6, 0x33, 0x94, 0x87, 0xba, 0x7a, 0x53, 0x5d, + 0xa3, 0xbb, 0x39, 0xf4, 0x5d, 0x59, 0xe9, 0xbd, 0xf9, 0xef, 0x77, 0x67, 0xc9, 0x7b, 0xc0, 0xf4, 0xa2, 0x6a, 0xb4, + 0x9f, 0x00, 0x9e, 0xe5, 0xd2, 0xc1, 0xff, 0x54, 0xa4, 0x26, 0x57, 0xd1, 0x04, 0xf4, 0xdd, 0xcc, 0x0d, 0x48, 0x5b, + 0xd9, 0x74, 0x06, 0x8d, 0xa1, 0xe6, 0xa8, 0x5e, 0x19, 0xf1, 0xe7, 0xf2, 0xaf, 0x57, 0x18, 0x18, 0xd6, 0x32, 0x33, + 0x16, 0x21, 0x83, 0x59, 0x9a, 0xd8, 0xe4, 0x9d, 0xe6, 0xf4, 0xe7, 0x76, 0xed, 0xe6, 0xab, 0xdd, 0x7b, 0x0b, 0xb2, + 0xc0, 0x09, 0x86, 0x93, 0x4f, 0x1c, 0x2a, 0x8a, 0xcb, 0xb7, 0x75, 0x3d, 0xfd, 0xd7, 0xed, 0xdb, 0xd0, 0xfb, 0xe6, + 0xac, 0x98, 0xd4, 0xb4, 0xec, 0x1e, 0x4d, 0x0b, 0x30, 0x7f, 0x2a, 0x6e, 0xbf, 0xec, 0xf9, 0x36, 0x8e, 0x16, 0x47, + 0x07, 0xe3, 0x67, 0xf7, 0xd7, 0x3b, 0x06, 0xc0, 0xe3, 0xcf, 0x29, 0xa9, 0xa6, 0x39, 0x5d, 0xfc, 0x70, 0xca, 0xa1, + 0xc6, 0x39, 0x39, 0x4f, 0x81, 0x3c, 0x6c, 0xb7, 0xcd, 0xc3, 0x71, 0x53, 0x45, 0x4c, 0x67, 0x8e, 0xa0, 0x37, 0xe9, + 0x2b, 0x8a, 0x30, 0x53, 0xe1, 0xc2, 0xf4, 0x53, 0x96, 0xb2, 0xd4, 0xe8, 0x74, 0x91, 0x55, 0x39, 0x60, 0xe9, 0xdb, + 0x89, 0x6f, 0x3c, 0x22, 0x4d, 0xb1, 0xc1, 0xd8, 0x3a, 0xe4, 0x04, 0xb1, 0x0c, 0x1f, 0x8e, 0xe5, 0xed, 0x25, 0x5e, + 0xe2, 0x39, 0x56, 0xd7, 0xc9, 0x37, 0x6f, 0x82, 0x13, 0x63, 0x7b, 0x1e, 0x6e, 0xb0, 0xd1, 0x46, 0x3e, 0xe4, 0x46, + 0x33, 0x14, 0xb8, 0xaa, 0xc4, 0xac, 0x02, 0x7d, 0x41, 0x97, 0x83, 0xe7, 0xe6, 0x5d, 0x5b, 0x05, 0x6d, 0x02, 0x37, + 0x39, 0x83, 0xa3, 0x76, 0xa7, 0x36, 0x98, 0x7e, 0x3c, 0x17, 0xa4, 0xa7, 0xbe, 0x73, 0x1f, 0x52, 0xbe, 0xb1, 0x40, + 0x35, 0x62, 0x44, 0x0d, 0x1c, 0xe0, 0x65, 0x9f, 0x87, 0xe6, 0x0d, 0x95, 0xbd, 0x57, 0x0b, 0x08, 0xa3, 0x29, 0xe4, + 0xae, 0x00, 0xec, 0x84, 0x21, 0x42, 0x83, 0xa3, 0x13, 0x00, 0x2b, 0xdc, 0xc5, 0xa7, 0xe8, 0x7f, 0x63, 0xbf, 0xbe, + 0x57, 0x71, 0xae, 0xdf, 0x22, 0x4a, 0xd3, 0x14, 0xf9, 0xa3, 0x66, 0x0d, 0x41, 0xa8, 0xb7, 0xe1, 0x66, 0xe9, 0xcf, + 0x7e, 0x80, 0x73, 0x03, 0x6b, 0x2c, 0x89, 0xe1, 0x03, 0x13, 0x4e, 0xd1, 0x86, 0x2b, 0xea, 0xdb, 0x69, 0xb1, 0x70, + 0xee, 0xdf, 0xa8, 0xa8, 0xf7, 0xea, 0xfb, 0xa9, 0xac, 0x7c, 0x22, 0x23, 0x40, 0x9a, 0x9b, 0xa1, 0x23, 0x73, 0x5f, + 0x37, 0x6b, 0xb7, 0x9e, 0xf0, 0x64, 0xb2, 0xf6, 0x20, 0xfd, 0x1e, 0x2f, 0xe5, 0xbf, 0xdf, 0x19, 0xcf, 0xa3, 0x7e, + 0xa3, 0x81, 0x15, 0x45, 0xab, 0x76, 0x34, 0xb1, 0xbe, 0x05, 0x0c, 0x41, 0x20, 0x95, 0x52, 0x3c, 0x21, 0xbf, 0x04, + 0xa3, 0xd2, 0xad, 0xc8, 0xac, 0xcd, 0x09, 0xc3, 0xc2, 0xd3, 0x2d, 0xd0, 0x2b, 0x6e, 0x28, 0xdc, 0x6b, 0x3d, 0xa2, + 0xee, 0x53, 0xe9, 0xbe, 0xce, 0xf8, 0x83, 0xd5, 0x17, 0xa9, 0xde, 0xbe, 0xe7, 0xb7, 0xe5, 0xda, 0xdd, 0xe9, 0x7f, + 0x7d, 0xc8, 0xe7, 0xf6, 0xb4, 0xef, 0xf6, 0x3e, 0x6e, 0xd7, 0x48, 0x3f, 0x5e, 0xb6, 0xf5, 0x29, 0xd6, 0xb5, 0x5b, + 0x54, 0xd9, 0x34, 0x69, 0xb5, 0x89, 0xa7, 0x6c, 0xfc, 0x1b, 0xa2, 0x62, 0x73, 0x88, 0x23, 0xf3, 0xc8, 0xa4, 0x72, + 0xce, 0xcf, 0x7f, 0x59, 0xd8, 0xc3, 0xa9, 0x07, 0x5b, 0x39, 0x97, 0xc6, 0x5a, 0xb1, 0x51, 0x21, 0x52, 0x70, 0xc9, + 0xd6, 0xb8, 0xbb, 0xb0, 0xa4, 0xb1, 0x06, 0x6c, 0xc0, 0x50, 0xb6, 0x83, 0x42, 0x6a, 0xc9, 0xde, 0xd9, 0xf1, 0x7a, + 0x3b, 0x46, 0x7f, 0xb0, 0x95, 0x51, 0xbd, 0xed, 0xc8, 0x52, 0xcb, 0x9a, 0xd7, 0x82, 0x96, 0x39, 0xcf, 0x05, 0x9e, + 0x85, 0x32, 0xfd, 0x42, 0x58, 0x17, 0x52, 0x46, 0xeb, 0x80, 0x14, 0xcc, 0x1a, 0x77, 0x5e, 0x94, 0xa5, 0xfd, 0x55, + 0xbd, 0xb8, 0xd3, 0x55, 0x05, 0xba, 0xad, 0x18, 0x95, 0x78, 0xcb, 0x4f, 0x59, 0x95, 0xd0, 0x26, 0x45, 0x2d, 0xdf, + 0x55, 0xe9, 0xf1, 0xda, 0x59, 0x60, 0xb1, 0x8c, 0x14, 0xb3, 0xf1, 0xc0, 0xe8, 0x67, 0x22, 0xfd, 0x40, 0x7f, 0xaa, + 0x4c, 0x41, 0xb0, 0x71, 0xea, 0x92, 0x7f, 0x8f, 0x04, 0x8a, 0x10, 0x4d, 0xce, 0x05, 0x5a, 0xfa, 0x97, 0x26, 0x1e, + 0x15, 0xe5, 0xe4, 0x0a, 0x46, 0x2b, 0xc3, 0xa3, 0xfc, 0x69, 0xae, 0x2b, 0xf4, 0x3c, 0x51, 0xfb, 0x25, 0xbb, 0xfd, + 0x62, 0xe3, 0x68, 0x5b, 0xcc, 0x6b, 0x1c, 0xd9, 0x3b, 0xf6, 0x58, 0x29, 0x45, 0x6e, 0x9f, 0x7a, 0x60, 0xad, 0x4b, + 0x39, 0xee, 0xea, 0xe1, 0x25, 0xdc, 0x9b, 0xbe, 0x91, 0x83, 0xb2, 0xb8, 0x98, 0xb7, 0xfa, 0x91, 0xfe, 0x10, 0xaf, + 0x28, 0x62, 0xd7, 0x12, 0xf6, 0xe9, 0x25, 0xcd, 0xd7, 0xb4, 0xc8, 0x90, 0xe8, 0xf8, 0x4d, 0x1b, 0xe5, 0x8d, 0x61, + 0xd5, 0x39, 0xb8, 0xdf, 0x29, 0x79, 0x82, 0x9a, 0xc3, 0xcc, 0xb0, 0xb1, 0xba, 0x9a, 0xb7, 0x71, 0x72, 0x4f, 0xab, + 0x0a, 0xf7, 0x5c, 0x40, 0x7b, 0x9b, 0xe5, 0x5b, 0x50, 0x1f, 0x73, 0xd4, 0xba, 0xfd, 0xb4, 0x49, 0xca, 0x99, 0x17, + 0xde, 0xd7, 0xa1, 0xa1, 0xfb, 0x2a, 0x9d, 0xdb, 0x18, 0x19, 0xa7, 0x83, 0xaa, 0x4b, 0x06, 0xe3, 0xfe, 0xd1, 0xba, + 0x61, 0xf1, 0x54, 0x6d, 0xad, 0x95, 0xb3, 0xba, 0x95, 0xfe, 0x79, 0x52, 0xc3, 0xda, 0xe5, 0xbc, 0x1e, 0x06, 0x17, + 0xa7, 0x6a, 0xfe, 0xa9, 0x09, 0x96, 0x19, 0x9c, 0xc3, 0xa6, 0x0c, 0xb9, 0x10, 0xc7, 0x87, 0x79, 0x4f, 0xbd, 0xd4, + 0xda, 0x38, 0x47, 0xc2, 0x22, 0xea, 0xb7, 0x82, 0xa7, 0xb9, 0x7c, 0x63, 0xae, 0x7b, 0xd0, 0xd8, 0x26, 0xc3, 0xbf, + 0x2f, 0xe8, 0x5f, 0x7e, 0x19, 0xbe, 0x42, 0x42, 0x94, 0xb4, 0x97, 0x1c, 0xcd, 0x73, 0xed, 0x51, 0xd8, 0x73, 0x60, + 0x21, 0x5e, 0x71, 0x6f, 0x20, 0x7f, 0xa4, 0x5f, 0xfa, 0xe4, 0x14, 0x87, 0x28, 0xa2, 0x81, 0x70, 0xfe, 0x6d, 0x50, + 0x97, 0xd8, 0xf3, 0x89, 0x74, 0x36, 0x68, 0x1c, 0xd8, 0x0d, 0x10, 0x7a, 0x89, 0x4d, 0xd8, 0x4f, 0x54, 0x1b, 0x0c, + 0xe6, 0xd4, 0x34, 0x3d, 0x36, 0x76, 0x6b, 0x08, 0x14, 0xdf, 0x8d, 0xd1, 0xe6, 0x4e, 0x81, 0xd6, 0xcb, 0xa7, 0x9c, + 0x55, 0x59, 0x75, 0x01, 0x2e, 0x0b, 0xaa, 0xe5, 0x90, 0xab, 0x9f, 0xe8, 0x4e, 0x05, 0xa4, 0x4d, 0xec, 0x7f, 0xc6, + 0xf9, 0xc0, 0xde, 0x1b, 0x3f, 0x38, 0xa2, 0xf5, 0xd9, 0x86, 0x2e, 0x84, 0x59, 0xab, 0x43, 0x4a, 0x59, 0x24, 0x72, + 0xdb, 0x6a, 0x7d, 0x1e, 0x2b, 0xa6, 0xf0, 0xe0, 0xdf, 0x9f, 0x44, 0x1a, 0xd6, 0xaa, 0xe8, 0x22, 0x1a, 0xce, 0xb6, + 0x28, 0xcc, 0xeb, 0xf5, 0x20, 0x7f, 0x35, 0xe5, 0x64, 0x03, 0x77, 0x93, 0x51, 0x3a, 0x7b, 0x91, 0x4a, 0x1c, 0x37, + 0x5d, 0x6e, 0x3b, 0xee, 0x48, 0xb7, 0xd8, 0xed, 0x21, 0xa9, 0x5c, 0x16, 0x6a, 0x6f, 0xda, 0xa0, 0x07, 0x8c, 0xa5, + 0xb7, 0x40, 0x8a, 0x6d, 0x19, 0x20, 0x7b, 0xf8, 0x85, 0xa2, 0x84, 0xa8, 0x8b, 0xb9, 0xc0, 0x78, 0x03, 0x01, 0x51, + 0xf6, 0x3c, 0x0b, 0xb6, 0xb5, 0x3c, 0x9a, 0x23, 0x53, 0x9a, 0xa6, 0xaa, 0x3d, 0x87, 0x5c, 0xd2, 0xc5, 0x94, 0x1b, + 0xed, 0x65, 0xfd, 0x70, 0x19, 0x41, 0xd0, 0xfd, 0x96, 0x67, 0xd5, 0xe8, 0x25, 0x10, 0x96, 0x2b, 0x28, 0x4f, 0xa6, + 0xfb, 0x45, 0x53, 0x9c, 0x79, 0x1a, 0xa4, 0x9a, 0x1b, 0x9e, 0x36, 0x13, 0x16, 0x4e, 0x7c, 0x9b, 0x24, 0xfd, 0x51, + 0x2d, 0xaf, 0xb5, 0xf0, 0x81, 0x7a, 0x70, 0xdb, 0xf0, 0x72, 0x34, 0xef, 0x57, 0x5b, 0x9a, 0x53, 0x7e, 0x99, 0x34, + 0xab, 0x9b, 0x72, 0xcc, 0x6d, 0xcc, 0x7a, 0x89, 0x34, 0xda, 0x94, 0xb7, 0xb1, 0x51, 0x32, 0xab, 0xa4, 0x25, 0x72, + 0xfa, 0x1b, 0x4b, 0xa4, 0x86, 0xc9, 0xa5, 0xc8, 0xc5, 0x5f, 0xc9, 0x42, 0xda, 0x7a, 0x6b, 0x74, 0x27, 0x06, 0x4a, + 0xd7, 0x79, 0x8f, 0x5b, 0xc2, 0xb3, 0x5f, 0x02, 0x40, 0xb3, 0x2a, 0x6f, 0x90, 0x72, 0xb1, 0x0a, 0x67, 0x7e, 0xb6, + 0x45, 0x6f, 0x7b, 0x0e, 0xab, 0x55, 0x42, 0xbf, 0x6f, 0x75, 0x05, 0xdc, 0xc0, 0x3e, 0x0f, 0xeb, 0x83, 0x5d, 0x18, + 0xd5, 0x6b, 0x25, 0x84, 0xd5, 0x04, 0x85, 0xb0, 0x72, 0x25, 0xd9, 0x83, 0x28, 0x42, 0x0f, 0xdc, 0x1d, 0x52, 0x9b, + 0x89, 0x78, 0xbe, 0x86, 0xf0, 0xcf, 0x31, 0x7b, 0xa8, 0xe8, 0x92, 0x01, 0x0a, 0xea, 0x47, 0x40, 0x29, 0x64, 0x04, + 0x10, 0x90, 0x90, 0x17, 0x21, 0x98, 0x7a, 0x42, 0xe9, 0x26, 0x38, 0xd2, 0xff, 0xd1, 0x0b, 0x95, 0x95, 0x30, 0x23, + 0x3e, 0xa3, 0x60, 0x14, 0x06, 0x1c, 0xdf, 0x9d, 0x50, 0x78, 0xd4, 0x3c, 0x55, 0x43, 0x7e, 0x7d, 0x78, 0x4f, 0x2f, + 0xb6, 0xd1, 0xbe, 0x50, 0x1f, 0x40, 0x97, 0xba, 0xca, 0x0b, 0x3a, 0x0d, 0x52, 0x45, 0x03, 0x14, 0x21, 0xbc, 0x74, + 0x43, 0x31, 0xc0, 0x0c, 0x8d, 0xcd, 0xc9, 0xc8, 0x8a, 0x2e, 0x6e, 0xba, 0x19, 0x88, 0xbc, 0x70, 0x8e, 0x8d, 0xea, + 0x78, 0xfa, 0x4f, 0xd5, 0xdc, 0x4c, 0x83, 0xb4, 0xc6, 0xd9, 0xd4, 0xa9, 0xcd, 0x10, 0x33, 0x11, 0x71, 0x51, 0xad, + 0x4b, 0xee, 0x25, 0x34, 0x87, 0x5d, 0x78, 0xef, 0x13, 0x6f, 0x29, 0xa5, 0x70, 0x66, 0x75, 0xb6, 0xdb, 0x02, 0x2d, + 0xe9, 0x3c, 0x7b, 0xea, 0x1d, 0x2e, 0x32, 0x15, 0x11, 0xfe, 0x6c, 0x63, 0x32, 0x51, 0x8a, 0xf4, 0x0c, 0xb5, 0x5c, + 0x70, 0x94, 0xec, 0x2a, 0x64, 0xfa, 0x2f, 0x9c, 0xb2, 0x03, 0xd0, 0xb6, 0x9b, 0xf0, 0x6e, 0x72, 0xc7, 0x37, 0xde, + 0xdf, 0xab, 0xbd, 0x2b, 0x36, 0xb5, 0x6b, 0x1c, 0x62, 0x7a, 0xf7, 0x14, 0x7b, 0x40, 0xa0, 0xa2, 0xc5, 0x12, 0x1a, + 0x7b, 0x6e, 0x5e, 0x1e, 0x8f, 0x93, 0x15, 0x25, 0x67, 0x9f, 0xeb, 0x8b, 0x85, 0x6d, 0x3a, 0xf1, 0xd2, 0xed, 0x95, + 0xc3, 0x02, 0x3d, 0x8c, 0x40, 0x38, 0x85, 0x19, 0x4d, 0x80, 0x4e, 0x8f, 0x3b, 0x23, 0x41, 0x39, 0xf5, 0x15, 0x03, + 0x26, 0x90, 0xc7, 0x6a, 0xdc, 0x14, 0x2e, 0x21, 0x67, 0x7b, 0xac, 0x88, 0x91, 0x06, 0x63, 0xfb, 0x3a, 0x28, 0x1c, + 0xa0, 0x13, 0x67, 0x7b, 0xa0, 0xae, 0x13, 0xef, 0x15, 0x79, 0x4d, 0xac, 0x35, 0xde, 0xb7, 0xa6, 0x38, 0x9d, 0x94, + 0xaf, 0x25, 0x9a, 0x23, 0x9a, 0xd3, 0x16, 0xf9, 0x03, 0x58, 0x79, 0xac, 0xbf, 0xb2, 0xba, 0x2f, 0x67, 0xac, 0xbf, + 0x30, 0xb2, 0xe4, 0x36, 0x42, 0x37, 0x1c, 0xac, 0x55, 0x10, 0xed, 0xc1, 0xd6, 0x62, 0xed, 0x08, 0xcb, 0x66, 0x6f, + 0x6b, 0x01, 0xee, 0xb4, 0xe7, 0x22, 0x0a, 0x17, 0x2b, 0xf0, 0x9e, 0xae, 0x21, 0xaf, 0xc4, 0x19, 0xfd, 0x23, 0x9c, + 0x98, 0x83, 0x04, 0xb1, 0x81, 0x1e, 0x95, 0xf5, 0x1f, 0x86, 0xc8, 0xe8, 0x74, 0x33, 0x1a, 0xbb, 0x7c, 0x69, 0xb4, + 0x6a, 0x05, 0x30, 0xa8, 0x6f, 0xf3, 0x78, 0x58, 0xc6, 0x8b, 0x39, 0x0e, 0x6d, 0x6b, 0xdf, 0x78, 0x94, 0x59, 0x78, + 0xff, 0x09, 0x4c, 0x6b, 0xb8, 0x2d, 0xf2, 0x7f, 0x2f, 0xcb, 0x4b, 0x79, 0xb6, 0x2b, 0xe7, 0xe9, 0xbd, 0xdf, 0xab, + 0x3c, 0xbb, 0x3b, 0xbd, 0xb7, 0xd8, 0xe4, 0x81, 0x71, 0x31, 0x47, 0xc0, 0x69, 0xeb, 0xc3, 0xbb, 0xef, 0x5e, 0x1f, + 0xbc, 0xa7, 0x2f, 0x7a, 0xcb, 0x6f, 0x64, 0xd3, 0x87, 0xe1, 0x14, 0x4f, 0xf1, 0xf3, 0x25, 0xef, 0x5a, 0xff, 0x35, + 0xdb, 0x6c, 0xce, 0x6b, 0xef, 0x94, 0xeb, 0x16, 0x57, 0x0d, 0xed, 0xcf, 0xdb, 0x6a, 0x0a, 0x9c, 0x6c, 0x02, 0x45, + 0x7c, 0xdd, 0x15, 0xa7, 0xac, 0x34, 0x80, 0x40, 0xb8, 0x3e, 0xfd, 0x9b, 0x6f, 0x8c, 0x52, 0xd9, 0xe0, 0xed, 0xa7, + 0xe5, 0x27, 0xa3, 0xc3, 0x23, 0x82, 0x0b, 0xd9, 0x7a, 0xa4, 0x7f, 0xe7, 0xe9, 0xce, 0xd7, 0xf3, 0x3c, 0xaa, 0x41, + 0x05, 0x64, 0xa9, 0xc6, 0x99, 0x0d, 0xe2, 0x98, 0xbb, 0xcd, 0x55, 0x4b, 0xc2, 0x37, 0x0b, 0x16, 0xdd, 0x75, 0xc0, + 0x91, 0x17, 0xcc, 0x31, 0x44, 0x70, 0xf8, 0xde, 0x32, 0xca, 0x77, 0xdc, 0x89, 0x1d, 0x0f, 0xc2, 0x22, 0x2c, 0xcf, + 0x5a, 0xd1, 0xb0, 0xfa, 0x81, 0x37, 0x7b, 0xf9, 0xff, 0xda, 0x50, 0xad, 0x17, 0x51, 0x95, 0x6c, 0x2d, 0x04, 0x58, + 0x17, 0xdb, 0x3c, 0x7e, 0x8a, 0x37, 0x76, 0xad, 0x91, 0xc4, 0xc3, 0x73, 0xf7, 0xd3, 0x3d, 0x41, 0x39, 0xce, 0xcf, + 0x3b, 0xbc, 0x46, 0x74, 0x06, 0xf1, 0x11, 0x78, 0x2f, 0xd7, 0x36, 0x28, 0xf8, 0xff, 0xfc, 0x57, 0x97, 0xb1, 0x5a, + 0xd6, 0x03, 0x56, 0x37, 0xfc, 0xb4, 0x0d, 0xde, 0xba, 0xbf, 0x9d, 0x6f, 0xe8, 0xd3, 0xb8, 0xde, 0x63, 0xad, 0xde, + 0x59, 0x97, 0xd6, 0x8c, 0x4e, 0xc2, 0x32, 0x8b, 0xb9, 0x12, 0xb2, 0x9e, 0x6b, 0xf3, 0x48, 0x86, 0x0f, 0x6b, 0xdb, + 0x96, 0x92, 0x83, 0x36, 0x0e, 0x4d, 0xb9, 0xa4, 0x42, 0xda, 0x54, 0x46, 0xff, 0x66, 0xaa, 0x28, 0x99, 0xf5, 0x74, + 0xf6, 0x2c, 0xba, 0x61, 0xa1, 0x4f, 0x81, 0x0c, 0x3c, 0xaf, 0x83, 0xaa, 0x25, 0x69, 0x2a, 0x44, 0x46, 0xa8, 0xa6, + 0x01, 0x6a, 0x9f, 0x54, 0x35, 0x14, 0x9e, 0xeb, 0x39, 0x1d, 0xfc, 0xc2, 0x47, 0x22, 0x48, 0x46, 0x12, 0x47, 0x0d, + 0x32, 0x65, 0x6f, 0xd7, 0xba, 0x57, 0xd7, 0xe9, 0xa9, 0xd3, 0x9c, 0x6d, 0x3e, 0xf2, 0xbf, 0x72, 0x73, 0x52, 0x2c, + 0xb6, 0x11, 0x88, 0x0b, 0x79, 0x8b, 0x29, 0xdb, 0x63, 0xc3, 0x30, 0xa8, 0xe3, 0xd7, 0x9b, 0x36, 0x6e, 0xa3, 0x04, + 0x11, 0xad, 0xe3, 0x93, 0x66, 0x8d, 0x8b, 0xaf, 0x5b, 0xe6, 0x9b, 0xcb, 0xaf, 0xd7, 0x38, 0xaa, 0xf5, 0xd9, 0x4e, + 0x95, 0x9b, 0x6b, 0x71, 0x54, 0x9b, 0xc6, 0x24, 0x3d, 0x21, 0x5b, 0x5e, 0xa0, 0x4d, 0xb9, 0xc9, 0x78, 0x83, 0xd2, + 0x40, 0xea, 0x05, 0xf3, 0x70, 0xb4, 0x33, 0x4f, 0xc7, 0xb7, 0x13, 0x2b, 0x67, 0x13, 0x5d, 0xda, 0x4d, 0xad, 0x85, + 0xf0, 0x78, 0x31, 0xe6, 0x35, 0x87, 0x7c, 0x56, 0x71, 0xe6, 0x7a, 0x1e, 0x4a, 0x8a, 0x30, 0xe1, 0xda, 0x2c, 0xd1, + 0x9b, 0x9b, 0x10, 0x16, 0x4b, 0x4e, 0x17, 0x08, 0x1d, 0x24, 0xcd, 0x77, 0xb4, 0xcf, 0x57, 0x7a, 0x78, 0x7e, 0x7f, + 0x4a, 0xb4, 0xdd, 0x3c, 0xe9, 0xec, 0xf3, 0xbb, 0x67, 0x1a, 0x75, 0xab, 0x54, 0xdb, 0x2a, 0x8a, 0x59, 0x23, 0x01, + 0x57, 0xeb, 0x08, 0xf4, 0xaa, 0x96, 0x3d, 0xd4, 0xd2, 0x47, 0xdd, 0xd5, 0x51, 0xab, 0xe7, 0xa2, 0xd6, 0x3e, 0x95, + 0x2e, 0xcf, 0x37, 0x8d, 0xc2, 0x90, 0x8b, 0xa2, 0x18, 0xa5, 0xa7, 0xdd, 0xb5, 0xf9, 0x32, 0x37, 0xa0, 0x99, 0x7b, + 0x07, 0xb5, 0x3c, 0x0f, 0xa8, 0xe7, 0xc6, 0xff, 0xa9, 0xd8, 0xf2, 0x18, 0x11, 0xaa, 0x3c, 0x9b, 0xa7, 0x15, 0x88, + 0xea, 0xda, 0x92, 0x6f, 0x8c, 0x64, 0xff, 0xf0, 0x8f, 0x7a, 0x3f, 0x4e, 0x4e, 0xe5, 0xef, 0xc0, 0x1d, 0x7d, 0x10, + 0xf7, 0x90, 0xc2, 0x55, 0xbc, 0xe6, 0x2e, 0xb7, 0xc8, 0x34, 0xf8, 0xff, 0xf8, 0xa5, 0x1b, 0x60, 0xe7, 0x78, 0x39, + 0x89, 0xe8, 0x5d, 0x09, 0x4a, 0xda, 0x94, 0xe1, 0x9a, 0x13, 0x0c, 0xf0, 0x7b, 0xdd, 0x31, 0xe5, 0xbc, 0xb1, 0x1c, + 0xc5, 0x52, 0x03, 0x3e, 0x54, 0xf9, 0x84, 0xf6, 0x8f, 0xed, 0x25, 0xbb, 0xba, 0x3c, 0xb6, 0x8d, 0xb3, 0xd4, 0xa6, + 0x65, 0xfb, 0x48, 0x34, 0x82, 0xea, 0x25, 0x81, 0x25, 0xb5, 0xcb, 0xaf, 0x6c, 0xab, 0x50, 0x36, 0x9b, 0xe0, 0xb2, + 0xf6, 0xe6, 0xae, 0x2c, 0x46, 0x9a, 0x65, 0xec, 0x3b, 0xcc, 0x76, 0x63, 0xed, 0xf4, 0x08, 0x09, 0xd5, 0xd3, 0x8a, + 0x65, 0xe9, 0x0b, 0xb1, 0xa7, 0x9f, 0x8f, 0xfa, 0xa9, 0x3d, 0x05, 0x00, 0x30, 0x5a, 0xef, 0x51, 0xc9, 0x0e, 0xae, + 0xdb, 0x20, 0xc0, 0x07, 0x7a, 0x7d, 0x03, 0xa0, 0x39, 0x9e, 0xdd, 0x16, 0x2c, 0xc5, 0x4f, 0xe2, 0x23, 0xf3, 0xb0, + 0xb3, 0x0c, 0x26, 0x70, 0x6b, 0xd6, 0x01, 0xa7, 0x6b, 0x37, 0x36, 0x6d, 0x9c, 0xac, 0xb3, 0xe9, 0xeb, 0x72, 0x0a, + 0x88, 0xe7, 0x6e, 0xdc, 0x1e, 0xa6, 0x8d, 0xab, 0x3b, 0x86, 0xf4, 0x29, 0x5a, 0xd6, 0x1d, 0x3f, 0x23, 0x0a, 0xab, + 0x22, 0xcb, 0x72, 0x86, 0xbd, 0x62, 0x9a, 0xa8, 0x79, 0xcb, 0xad, 0x82, 0x9c, 0x15, 0x60, 0xed, 0xf5, 0x7a, 0x40, + 0x38, 0xb5, 0x1e, 0x7c, 0xfb, 0x3f, 0x75, 0xd4, 0x77, 0xeb, 0xb8, 0x0b, 0xe7, 0x46, 0x0b, 0xcf, 0x53, 0x88, 0xb2, + 0x3c, 0x20, 0xb3, 0xe5, 0xaf, 0xff, 0xf2, 0x94, 0x7c, 0xd2, 0xee, 0xf6, 0x6f, 0xe8, 0xd6, 0x4f, 0x00, 0xc7, 0x36, + 0x3b, 0x40, 0x37, 0x48, 0x75, 0x83, 0x08, 0xda, 0xef, 0x19, 0xe8, 0x66, 0xa0, 0x8c, 0x8a, 0x89, 0xcf, 0x1b, 0xdd, + 0x55, 0x00, 0xfa, 0xfe, 0x9c, 0x6d, 0x71, 0xee, 0xb3, 0x20, 0x6f, 0xc1, 0xaa, 0xd9, 0x1f, 0x05, 0x86, 0x6b, 0xfb, + 0x81, 0x33, 0x08, 0xea, 0x5a, 0x07, 0x4a, 0xbb, 0xdc, 0x3e, 0x5a, 0x01, 0x88, 0x58, 0x58, 0x13, 0x36, 0x51, 0xfd, + 0x97, 0x48, 0x97, 0x34, 0x24, 0x61, 0xa6, 0xfa, 0x89, 0xd8, 0xb3, 0x96, 0x18, 0x56, 0x7a, 0x80, 0x4d, 0x9c, 0x07, + 0x74, 0x83, 0x28, 0x5e, 0x87, 0x06, 0xff, 0x4e, 0x58, 0x90, 0xf7, 0x94, 0xfa, 0xcc, 0x50, 0xd5, 0xa5, 0xb0, 0xe6, + 0x51, 0xaa, 0xc1, 0xf0, 0x1c, 0xda, 0x00, 0x6b, 0x29, 0x6a, 0x6e, 0xbb, 0x24, 0x95, 0x20, 0xf1, 0xc6, 0xd4, 0x77, + 0x33, 0xe0, 0xdd, 0xac, 0x0c, 0xa0, 0x40, 0x52, 0x5f, 0x50, 0xf4, 0xe6, 0xd1, 0x77, 0x6b, 0xc2, 0xb3, 0xd3, 0xdd, + 0x88, 0x49, 0xb2, 0xae, 0xb6, 0x10, 0x11, 0x8b, 0x68, 0xdb, 0x56, 0x85, 0xa1, 0x03, 0x99, 0xe8, 0x51, 0x95, 0xa4, + 0x04, 0xff, 0xcd, 0xd8, 0x2e, 0x46, 0xd4, 0x30, 0xa0, 0xa0, 0x60, 0x6f, 0x8f, 0xdb, 0x85, 0x2f, 0x6f, 0x69, 0xcc, + 0x2d, 0x05, 0x5e, 0x85, 0xc6, 0xc3, 0x3a, 0x90, 0x2b, 0xa2, 0x41, 0xe7, 0x5c, 0x3b, 0xe3, 0xe4, 0xb8, 0x99, 0xf9, + 0x12, 0xcf, 0x9f, 0x5b, 0xfb, 0x7d, 0xa5, 0x14, 0xf9, 0x37, 0x28, 0x24, 0x9c, 0x5a, 0x55, 0xa3, 0xaa, 0x0f, 0x60, + 0x4d, 0xd7, 0x04, 0x77, 0xc6, 0xb3, 0x4f, 0x08, 0x24, 0x3f, 0xe5, 0x52, 0x67, 0x93, 0x36, 0x02, 0xa3, 0x2f, 0xc1, + 0xe4, 0x85, 0xe9, 0x6a, 0x01, 0x71, 0x78, 0xa0, 0x3f, 0x26, 0x8a, 0xe4, 0xa9, 0x22, 0x0a, 0x6a, 0x78, 0xaa, 0x32, + 0x5f, 0x2f, 0xf5, 0x3a, 0xb9, 0xd1, 0xd9, 0x13, 0x8f, 0x69, 0x9b, 0x9a, 0x21, 0x9b, 0xc9, 0x8b, 0xfb, 0xe1, 0xba, + 0x7b, 0x75, 0x1f, 0x14, 0x12, 0x27, 0x37, 0x0d, 0x90, 0xb7, 0xea, 0x44, 0x9e, 0x16, 0x24, 0x80, 0xe5, 0xd2, 0x34, + 0x6b, 0xbf, 0x3c, 0x9a, 0x20, 0x84, 0xcf, 0x86, 0xbd, 0x71, 0x5c, 0x34, 0x4d, 0x27, 0x06, 0x0e, 0x97, 0x37, 0x39, + 0x9e, 0x19, 0x99, 0xad, 0x3b, 0xdf, 0x34, 0x26, 0x1a, 0xba, 0x6a, 0x57, 0x86, 0xc9, 0x1b, 0xa7, 0x5b, 0xee, 0xd4, + 0xee, 0x42, 0x19, 0x5c, 0xa4, 0xcb, 0xa6, 0x6c, 0x04, 0x20, 0xba, 0x76, 0x68, 0x94, 0x27, 0x47, 0x61, 0x42, 0x73, + 0x5b, 0x83, 0x17, 0x40, 0xdb, 0x3f, 0xea, 0x46, 0xa9, 0x17, 0x22, 0x2b, 0x3c, 0xfe, 0x68, 0x23, 0xd7, 0xcb, 0xad, + 0x53, 0xe5, 0xe5, 0x3a, 0x6a, 0xe7, 0xe5, 0xd6, 0xad, 0x66, 0xa5, 0xa9, 0x4d, 0xd8, 0x08, 0x6c, 0x2f, 0xbd, 0xe4, + 0x19, 0x7a, 0xfa, 0x19, 0x7a, 0xc6, 0x36, 0x2f, 0x44, 0x4c, 0xd9, 0xfa, 0x95, 0x57, 0xa4, 0x75, 0x60, 0xff, 0xb3, + 0x7f, 0xdf, 0x40, 0x64, 0x2a, 0x56, 0xbb, 0x4a, 0xc4, 0x14, 0xc8, 0x5a, 0xa1, 0x7e, 0x64, 0x1f, 0xb4, 0xff, 0xda, + 0xfb, 0xed, 0x7d, 0x6e, 0x2a, 0x9a, 0x0c, 0xf8, 0xfd, 0x09, 0x33, 0xcd, 0x31, 0xc4, 0x12, 0x33, 0xba, 0x1f, 0x5d, + 0x47, 0x0e, 0xa6, 0xdf, 0x95, 0x12, 0xff, 0xc9, 0x5d, 0x6d, 0xb7, 0x9c, 0x89, 0x38, 0x22, 0xee, 0x76, 0x40, 0x37, + 0x41, 0x7c, 0x7d, 0xfc, 0xb2, 0x06, 0x97, 0xb9, 0xda, 0x17, 0x59, 0xc8, 0xf0, 0xfa, 0x83, 0x87, 0xec, 0x33, 0xef, + 0xb2, 0x53, 0x73, 0x86, 0x6b, 0x0b, 0xd7, 0x83, 0xe2, 0xcd, 0xcc, 0xaf, 0x03, 0x2f, 0x2a, 0xee, 0x54, 0x67, 0x2f, + 0xaa, 0xf1, 0x10, 0x1a, 0xcf, 0x02, 0xf7, 0x68, 0x9d, 0xd2, 0xbf, 0x66, 0x21, 0x3e, 0x9b, 0xbc, 0xb1, 0x99, 0xc7, + 0xdc, 0xcd, 0x1c, 0x82, 0x94, 0x9f, 0xe4, 0x52, 0x85, 0x91, 0x85, 0x74, 0xd3, 0x92, 0x55, 0xc2, 0x5b, 0xbc, 0x33, + 0x8f, 0xbb, 0x3f, 0x97, 0x78, 0x07, 0xf5, 0x8a, 0xf0, 0x22, 0xb3, 0x27, 0xd7, 0x31, 0x0c, 0xcc, 0x12, 0x2e, 0x64, + 0x0e, 0x8d, 0xd4, 0xdb, 0x5b, 0x3c, 0x71, 0x41, 0xf5, 0x63, 0x78, 0xe7, 0x5d, 0x76, 0x59, 0xc9, 0xed, 0xe1, 0x63, + 0x3d, 0x39, 0x4b, 0xdc, 0x0b, 0x66, 0xce, 0xad, 0xc7, 0x7d, 0x75, 0x26, 0x69, 0x76, 0xe4, 0x22, 0x41, 0x63, 0x01, + 0x2b, 0x31, 0x94, 0x9e, 0xde, 0x71, 0x3c, 0xbb, 0x23, 0xc0, 0x0f, 0x8e, 0xf5, 0x6d, 0x4d, 0xd9, 0x78, 0x72, 0x76, + 0xbd, 0x0d, 0xdc, 0x97, 0x5d, 0xf7, 0x2e, 0x46, 0xa9, 0xba, 0xa1, 0x89, 0x6b, 0x33, 0x10, 0xd8, 0xdd, 0x54, 0x3c, + 0x85, 0xa3, 0xe9, 0xc6, 0xf7, 0x4d, 0x5d, 0x9b, 0x8e, 0x02, 0xd2, 0x2e, 0x01, 0xad, 0x6d, 0xbf, 0xb8, 0xa1, 0x7b, + 0x04, 0xc3, 0x26, 0xc4, 0xc8, 0xe6, 0x6a, 0x3f, 0xac, 0xc7, 0x76, 0xdc, 0xd0, 0x51, 0x67, 0x19, 0x3e, 0x73, 0xd9, + 0x01, 0x7d, 0x26, 0x2f, 0xf4, 0x5d, 0x6c, 0x88, 0x4e, 0xb0, 0xee, 0xd8, 0xe0, 0x93, 0x80, 0x38, 0xbf, 0xf1, 0x0e, + 0x17, 0x70, 0xb9, 0xc0, 0x12, 0xc0, 0xfa, 0xec, 0xc4, 0xe0, 0x99, 0xbe, 0x8b, 0x5d, 0xc7, 0xb9, 0x27, 0xdc, 0x55, + 0x28, 0x05, 0x2e, 0xcd, 0x4f, 0x21, 0x4f, 0x5e, 0xe8, 0x5e, 0x3f, 0x9f, 0x25, 0xa6, 0xee, 0x62, 0x6b, 0x7d, 0xd8, + 0x94, 0x0a, 0x98, 0xfb, 0x94, 0x4e, 0xad, 0x83, 0xe2, 0xed, 0x13, 0x5a, 0x20, 0x0c, 0x63, 0x7b, 0xff, 0xaa, 0x89, + 0x61, 0x3c, 0x8d, 0x67, 0x0e, 0x82, 0x81, 0x11, 0x61, 0x80, 0x2f, 0xf1, 0x5e, 0x4e, 0x48, 0x9e, 0xa0, 0x99, 0x7d, + 0x36, 0x52, 0xec, 0x5d, 0x9e, 0xf4, 0xf5, 0xee, 0x4c, 0x66, 0x8f, 0x0f, 0xef, 0x02, 0x5a, 0xef, 0xc6, 0x4b, 0x0d, + 0x8f, 0x65, 0xed, 0x72, 0x25, 0x96, 0x42, 0xbc, 0x76, 0xd1, 0xfa, 0x6f, 0xda, 0xe4, 0xb0, 0x45, 0x33, 0x18, 0xf9, + 0x4e, 0x5f, 0x9a, 0x63, 0x79, 0x47, 0x5e, 0xd8, 0x48, 0x35, 0x80, 0xe2, 0xca, 0x20, 0xc3, 0x90, 0xb5, 0x77, 0x58, + 0x44, 0x41, 0x61, 0xe8, 0x8a, 0x47, 0x7d, 0x4a, 0x44, 0x9d, 0x04, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xae, 0x0c, 0x4e, + 0x01, 0xb5, 0xe2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x1a, 0x76, 0x26, 0xee, 0x2a, 0xb0, 0x3c, 0xe5, 0x83, 0x5d, 0x5c, + 0x60, 0xe2, 0xbf, 0xee, 0xf5, 0x89, 0x81, 0x23, 0xdd, 0x8d, 0xb0, 0x05, 0x30, 0x0d, 0x76, 0xe5, 0x95, 0xbc, 0xe4, + 0xa9, 0xd7, 0x10, 0x9c, 0x5c, 0x6d, 0x5e, 0x9f, 0xcc, 0xfa, 0x12, 0x84, 0x52, 0xaa, 0x11, 0x76, 0x0b, 0xec, 0xda, + 0x72, 0xb6, 0xae, 0x4e, 0x26, 0x6a, 0xdb, 0xc8, 0xb8, 0x61, 0x3f, 0x63, 0xed, 0x22, 0x76, 0x7d, 0xbc, 0xd8, 0x85, + 0x6c, 0x2a, 0x76, 0x2e, 0x4c, 0x8a, 0x9c, 0x41, 0x07, 0x0e, 0xb5, 0xc3, 0x19, 0x31, 0xd3, 0xed, 0x74, 0xc9, 0x76, + 0xfa, 0xe0, 0x9d, 0x76, 0x4e, 0x05, 0x74, 0x06, 0xe3, 0xec, 0xd4, 0x4e, 0x1a, 0xa1, 0x0b, 0x8c, 0xef, 0x4a, 0xe8, + 0x17, 0xb3, 0x54, 0xc3, 0x6b, 0xd6, 0x80, 0xb4, 0x92, 0x0a, 0xe6, 0xd9, 0x8a, 0x2d, 0x29, 0xdc, 0xe6, 0xc5, 0xd6, + 0xe2, 0x7f, 0xe9, 0x47, 0xba, 0x2e, 0x0f, 0x88, 0x20, 0x1b, 0x88, 0xd2, 0x49, 0xf0, 0x9f, 0xc5, 0x0c, 0x7f, 0x6e, + 0x60, 0xf4, 0x32, 0xb3, 0x78, 0x9a, 0xe5, 0xa8, 0x19, 0xdf, 0x19, 0xfe, 0x54, 0x46, 0xf2, 0x93, 0x2c, 0x27, 0xf0, + 0xbe, 0x0e, 0x01, 0x8e, 0x4c, 0xed, 0xe7, 0x2c, 0x67, 0xbc, 0x82, 0x96, 0x8d, 0xa2, 0x43, 0x14, 0xf5, 0xba, 0x7e, + 0xee, 0xc3, 0xe2, 0x9c, 0x50, 0x82, 0x91, 0x4d, 0x2f, 0xa1, 0x10, 0xa2, 0xf7, 0xcd, 0xb1, 0x18, 0x99, 0xbf, 0x28, + 0xe1, 0x04, 0x0b, 0x39, 0xd0, 0xbd, 0x2a, 0x20, 0x1d, 0x9f, 0x08, 0x0d, 0x13, 0x73, 0xb6, 0x91, 0xa9, 0xce, 0x26, + 0x16, 0xd2, 0x59, 0x71, 0xcd, 0xb1, 0x94, 0x56, 0x73, 0xe5, 0x75, 0x19, 0x75, 0x27, 0xe5, 0x97, 0xd0, 0xf4, 0x7a, + 0xcb, 0x59, 0x8c, 0x2a, 0xfc, 0xa7, 0xc3, 0x84, 0x6f, 0xd0, 0x2e, 0x2c, 0x67, 0x1d, 0x22, 0x54, 0xc1, 0x03, 0x5d, + 0x93, 0xbe, 0x8e, 0x56, 0xc3, 0x08, 0xcd, 0xdd, 0x0a, 0x0a, 0x84, 0xb4, 0x3f, 0xb0, 0xa8, 0x6d, 0xac, 0x9a, 0xb3, + 0x77, 0x47, 0x3b, 0x58, 0x35, 0x98, 0x9f, 0x1c, 0x05, 0xac, 0xba, 0x91, 0x70, 0xb1, 0xfc, 0x95, 0xc3, 0x43, 0x56, + 0x70, 0xf3, 0x01, 0xdc, 0x7e, 0x00, 0xe3, 0x98, 0xf1, 0x91, 0x3d, 0x69, 0x01, 0xc3, 0x99, 0xeb, 0x01, 0xef, 0x8d, + 0x53, 0x6f, 0xa4, 0xd1, 0x81, 0xa3, 0xab, 0xe5, 0x25, 0x7e, 0x28, 0x22, 0xc3, 0xaf, 0x49, 0x54, 0xd7, 0x34, 0x83, + 0x3c, 0x95, 0xd2, 0xe4, 0xd8, 0x1d, 0x50, 0x00, 0x7b, 0x1f, 0xe8, 0x98, 0xb6, 0x31, 0x93, 0xeb, 0x29, 0xba, 0x24, + 0xcd, 0xeb, 0x79, 0x68, 0x3f, 0x62, 0x9d, 0x11, 0x50, 0x8e, 0xed, 0x01, 0xf3, 0x5d, 0x03, 0x54, 0x2d, 0xcc, 0xf9, + 0x6f, 0x6a, 0x6b, 0x73, 0xe8, 0x58, 0x3d, 0x20, 0x2c, 0xf9, 0xf5, 0x51, 0x0b, 0xf2, 0xfb, 0x58, 0xe1, 0xb0, 0x45, + 0xfb, 0x62, 0x47, 0xaa, 0x0e, 0x6a, 0x85, 0xc1, 0x45, 0xa5, 0xca, 0xd4, 0x11, 0xc3, 0x0b, 0xb2, 0x49, 0x28, 0x14, + 0x1a, 0xc7, 0x13, 0x1b, 0xd0, 0xec, 0x8f, 0x58, 0x4a, 0xbb, 0x4b, 0x7e, 0xcd, 0x04, 0x91, 0xe6, 0xa5, 0xbf, 0xdb, + 0xe1, 0xa2, 0x0e, 0x17, 0xaf, 0x79, 0xa3, 0xe7, 0xb4, 0x09, 0xcd, 0x16, 0x63, 0xbc, 0x52, 0x6d, 0x82, 0xec, 0x4e, + 0xf3, 0xe8, 0x68, 0xc7, 0x16, 0x85, 0x24, 0x64, 0x7f, 0x79, 0x6d, 0x26, 0x47, 0x15, 0xfd, 0xbb, 0xc8, 0x59, 0x96, + 0x12, 0xe2, 0x1d, 0xf8, 0x45, 0x4f, 0xb9, 0x92, 0x46, 0xa7, 0xba, 0x23, 0xba, 0xa0, 0xa8, 0x7f, 0x76, 0x34, 0x0c, + 0xb3, 0x3c, 0x19, 0x54, 0xc1, 0x01, 0x8c, 0xd9, 0xe8, 0xa3, 0xeb, 0x85, 0x4b, 0x31, 0x98, 0xf2, 0xb0, 0x6a, 0xb3, + 0xb6, 0x61, 0xea, 0xc6, 0xb8, 0x30, 0x5c, 0x33, 0xb6, 0x31, 0x01, 0x18, 0xdb, 0x34, 0xdb, 0x4c, 0x9b, 0xfe, 0xfe, + 0xa9, 0xb0, 0x7a, 0x48, 0x24, 0x22, 0x90, 0x0f, 0xa2, 0x0f, 0x06, 0xa4, 0x7f, 0x5d, 0xa4, 0x60, 0x74, 0xa9, 0x15, + 0x3f, 0x89, 0x15, 0x1d, 0xf0, 0x9b, 0x8d, 0x77, 0x68, 0x18, 0x73, 0xde, 0x29, 0xc6, 0x5c, 0x9e, 0x82, 0x1d, 0x76, + 0x0e, 0xc2, 0x93, 0x2a, 0x46, 0xdb, 0x93, 0x58, 0x41, 0xd3, 0xf3, 0x05, 0xac, 0x6f, 0x12, 0x56, 0x63, 0x98, 0x56, + 0x33, 0x37, 0xc5, 0x5d, 0x2e, 0x3c, 0x66, 0x4d, 0xd6, 0x82, 0xf8, 0x20, 0x10, 0x59, 0x26, 0x41, 0x04, 0x3d, 0x16, + 0xde, 0x93, 0x99, 0x57, 0xc8, 0xd2, 0x0d, 0xba, 0x8c, 0x8c, 0xfb, 0xc0, 0x86, 0xfa, 0x41, 0xfd, 0xa0, 0x85, 0x74, + 0xa1, 0xf9, 0x6b, 0x54, 0xd5, 0x32, 0xcf, 0x71, 0xa3, 0x1c, 0x5a, 0x72, 0x6e, 0x8e, 0x40, 0x0b, 0x81, 0x50, 0x7b, + 0x35, 0x37, 0xc0, 0x58, 0x7e, 0x08, 0x87, 0x9c, 0x03, 0x40, 0x67, 0x31, 0xe1, 0xf1, 0x6d, 0x1b, 0x20, 0xb5, 0x71, + 0xf4, 0xa4, 0x6e, 0xed, 0xa6, 0xc9, 0x10, 0x41, 0x24, 0xbe, 0x1d, 0x03, 0xeb, 0xe7, 0xf9, 0x77, 0x11, 0x9d, 0x60, + 0xe8, 0xc7, 0xe2, 0x2e, 0x7f, 0x34, 0xf4, 0x54, 0x7f, 0x3e, 0x55, 0x4f, 0x62, 0xc4, 0x52, 0xc4, 0x8f, 0x79, 0x6d, + 0x2e, 0xa0, 0x14, 0xa5, 0xd9, 0x04, 0x46, 0x39, 0xd2, 0xe3, 0x4a, 0x92, 0x47, 0xa2, 0x81, 0x18, 0x44, 0xa3, 0xe2, + 0x9b, 0x2b, 0x5d, 0x3b, 0x87, 0xab, 0x78, 0xe5, 0xb1, 0xae, 0x97, 0xc7, 0xeb, 0x99, 0x9d, 0x7a, 0x2f, 0x07, 0xeb, + 0xd4, 0x3b, 0x2f, 0x44, 0x4b, 0x57, 0xc4, 0xe8, 0xf4, 0x13, 0x51, 0xab, 0x76, 0xbd, 0x6b, 0x04, 0x22, 0x09, 0x97, + 0xff, 0x19, 0x02, 0xb5, 0xf0, 0xe1, 0xd2, 0xb3, 0xc3, 0x62, 0x6e, 0x74, 0xf9, 0xa6, 0x19, 0x94, 0x02, 0x1e, 0xd4, + 0xea, 0xb8, 0x86, 0xe8, 0xdc, 0x56, 0xf2, 0x82, 0xd4, 0x7f, 0x12, 0xab, 0xa0, 0xe0, 0xbd, 0x95, 0xee, 0x79, 0x91, + 0x6a, 0xb8, 0xa9, 0x72, 0x07, 0xe8, 0xb5, 0xa8, 0x62, 0x4d, 0x83, 0x17, 0x76, 0xa6, 0x24, 0xf2, 0x81, 0x97, 0x10, + 0xa1, 0xfb, 0x4e, 0xcc, 0x1a, 0xa6, 0xad, 0x66, 0x67, 0xec, 0x46, 0x0f, 0xa1, 0x47, 0x31, 0x59, 0x5e, 0x2d, 0x21, + 0xe0, 0xb3, 0xdf, 0x46, 0xb3, 0xf7, 0x36, 0x25, 0x19, 0x17, 0xfe, 0x6d, 0x02, 0x4b, 0x6e, 0x71, 0x87, 0x41, 0x0c, + 0xd6, 0x1f, 0x09, 0x1e, 0x98, 0x83, 0xed, 0xa1, 0xb0, 0xac, 0x9e, 0xcd, 0x33, 0x0f, 0xb4, 0x8f, 0x51, 0x94, 0xd1, + 0x04, 0xf0, 0xc9, 0x7a, 0x47, 0x02, 0x80, 0x6c, 0x5d, 0xa1, 0x46, 0x9f, 0x74, 0x65, 0xdd, 0x55, 0x77, 0xc3, 0x52, + 0x19, 0xba, 0x1b, 0x59, 0x4b, 0x01, 0x1d, 0x8a, 0x53, 0x96, 0x59, 0xf4, 0xc6, 0x07, 0x55, 0x14, 0xf9, 0x3e, 0xb1, + 0x2d, 0x61, 0xea, 0xdb, 0x9b, 0x44, 0x17, 0x85, 0x44, 0x01, 0x61, 0x92, 0x9c, 0x78, 0x5f, 0x20, 0x71, 0xb6, 0x5e, + 0x22, 0x6a, 0xc2, 0xe5, 0x67, 0xf7, 0xca, 0x04, 0x1e, 0xb4, 0xf5, 0xac, 0xec, 0x02, 0x97, 0xd7, 0x17, 0x43, 0x10, + 0x05, 0x72, 0x0a, 0x62, 0x72, 0x09, 0x8a, 0x0f, 0xe6, 0x7a, 0x02, 0x4e, 0x91, 0xef, 0xa5, 0xe6, 0x7d, 0xe3, 0x00, + 0x1c, 0x85, 0x10, 0x8b, 0x91, 0x08, 0x08, 0xc9, 0x26, 0xc0, 0xa5, 0x15, 0x68, 0xf7, 0x17, 0x7b, 0xed, 0x0b, 0xf7, + 0x8f, 0xd8, 0xad, 0x30, 0x17, 0xb2, 0x30, 0x5a, 0x11, 0xdd, 0x4b, 0x02, 0x67, 0x87, 0x3a, 0xbf, 0x65, 0x96, 0xc6, + 0xb7, 0xee, 0xe7, 0xa0, 0x94, 0x80, 0xb0, 0xff, 0xc9, 0x38, 0x10, 0x00, 0x73, 0x69, 0x25, 0x6d, 0x89, 0x78, 0xf6, + 0x42, 0x9a, 0x0d, 0xfd, 0xc6, 0x86, 0x37, 0x0f, 0x15, 0x60, 0x49, 0xad, 0x5e, 0x30, 0x97, 0x55, 0xce, 0x68, 0x0d, + 0x4a, 0x78, 0xdb, 0x42, 0x57, 0xcf, 0x56, 0xbf, 0x17, 0xd5, 0x8f, 0xfb, 0xe1, 0x5b, 0xd5, 0x6d, 0x4f, 0xaa, 0x33, + 0xc9, 0x60, 0xf2, 0x54, 0xad, 0xa7, 0x59, 0x70, 0xf7, 0x7e, 0xa7, 0x00, 0x64, 0xa1, 0xf1, 0x76, 0xd6, 0xd9, 0xdc, + 0x1e, 0xfa, 0xc0, 0xfe, 0x80, 0x0b, 0x8a, 0x3f, 0x24, 0x1d, 0xdf, 0x27, 0x11, 0x11, 0x59, 0xdb, 0xb1, 0xcb, 0x5b, + 0xdb, 0x36, 0xad, 0x99, 0x97, 0x3e, 0x56, 0xdf, 0xfc, 0xf6, 0x96, 0xbc, 0x17, 0x25, 0x27, 0xe9, 0x0b, 0x56, 0xb7, + 0x68, 0x7b, 0xc8, 0xd3, 0x81, 0x09, 0x74, 0xeb, 0xbc, 0xf1, 0x4e, 0x31, 0xd2, 0xd4, 0x11, 0x47, 0x99, 0x8d, 0x0c, + 0x9e, 0xe9, 0x59, 0x1f, 0x1d, 0x28, 0x9e, 0x61, 0xba, 0x26, 0x62, 0x9f, 0xb8, 0xec, 0x0a, 0x3c, 0x21, 0x3a, 0x3e, + 0x82, 0x69, 0x43, 0xde, 0xaf, 0xc2, 0xfb, 0xe2, 0x58, 0xfc, 0x60, 0x31, 0x89, 0x7c, 0x90, 0x03, 0xbc, 0x0f, 0x6c, + 0x59, 0x61, 0x64, 0xe0, 0x73, 0xb6, 0x3b, 0x8e, 0x17, 0x80, 0x11, 0x0f, 0xb9, 0x47, 0x77, 0x7c, 0x0f, 0x02, 0xc7, + 0x33, 0xd5, 0x62, 0xe7, 0xb0, 0x04, 0x01, 0x90, 0x19, 0x2c, 0x8e, 0x8b, 0xd1, 0x28, 0x4a, 0x09, 0x78, 0x26, 0xa7, + 0x6e, 0xd5, 0x10, 0xcb, 0xec, 0x9b, 0x80, 0x72, 0xe9, 0x5a, 0x48, 0xc1, 0xad, 0xfa, 0xc6, 0x98, 0x90, 0x6e, 0x1b, + 0x0d, 0xb6, 0xf0, 0xaf, 0x05, 0xb1, 0xa4, 0x41, 0x5d, 0x93, 0xf7, 0x61, 0xb6, 0x50, 0xda, 0x9b, 0xae, 0xe3, 0xd4, + 0x25, 0x92, 0xb8, 0xb6, 0xc4, 0x48, 0x20, 0x98, 0x59, 0x87, 0x22, 0x8b, 0x21, 0xf6, 0xb1, 0xda, 0x02, 0x80, 0x27, + 0x10, 0x1d, 0x39, 0x66, 0xef, 0x11, 0xc5, 0xfd, 0x0b, 0xf8, 0x65, 0xf9, 0x03, 0x19, 0x7f, 0x7b, 0x3e, 0xce, 0x8e, + 0x28, 0xfa, 0x77, 0x12, 0x4f, 0x55, 0x2c, 0x81, 0x34, 0xb6, 0x03, 0x2c, 0x5d, 0x81, 0x5c, 0x06, 0x8e, 0x11, 0xeb, + 0x67, 0xd6, 0x27, 0xe0, 0xc7, 0x01, 0x16, 0x1d, 0xbf, 0x0e, 0x95, 0x5d, 0x4a, 0xe5, 0x6f, 0x95, 0x5b, 0x99, 0x31, + 0x38, 0x17, 0xba, 0x3b, 0x49, 0x53, 0xaf, 0xee, 0x6d, 0x43, 0x7d, 0x93, 0xa4, 0x7d, 0x6b, 0x09, 0x03, 0xee, 0xeb, + 0x24, 0x8d, 0xa1, 0xd0, 0x27, 0xcb, 0xe3, 0x26, 0xa9, 0x89, 0xa1, 0x37, 0x45, 0xbc, 0x9b, 0x6a, 0x8f, 0xd4, 0xee, + 0x4b, 0xd3, 0x2e, 0x02, 0xb3, 0xa4, 0xb1, 0x68, 0x32, 0xfc, 0x08, 0x58, 0x1c, 0x8a, 0x14, 0x23, 0x72, 0x19, 0x80, + 0xb0, 0x61, 0x07, 0x77, 0x52, 0x3d, 0xa6, 0xd9, 0x13, 0xf0, 0xd2, 0xa6, 0x78, 0xef, 0xaa, 0xc5, 0x84, 0x32, 0x61, + 0xf2, 0xe0, 0xad, 0xdd, 0x5c, 0x30, 0x53, 0x2a, 0x49, 0x20, 0x9b, 0xb2, 0x90, 0x2b, 0xf8, 0xd9, 0x8b, 0xbf, 0x7f, + 0x50, 0x54, 0x3a, 0x02, 0xee, 0x78, 0xd9, 0xfd, 0xb9, 0x11, 0xff, 0x64, 0x88, 0x47, 0x46, 0x66, 0xf8, 0x2f, 0x49, + 0xd6, 0xf8, 0x04, 0x32, 0x09, 0x2f, 0x69, 0x0f, 0xd2, 0x25, 0x3c, 0x52, 0xeb, 0x60, 0x96, 0x47, 0x1b, 0x9a, 0xc8, + 0xdf, 0x84, 0xc2, 0xaa, 0xab, 0x0c, 0x2c, 0xce, 0x32, 0xe4, 0xe7, 0x52, 0x73, 0x0c, 0xc0, 0x6f, 0x02, 0xf0, 0x86, + 0x86, 0x49, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x34, 0xe9, 0x3a, 0x55, 0x5d, 0x90, 0x1d, 0x65, 0xd0, 0x2e, 0x0c, 0x89, + 0x80, 0x9e, 0xef, 0x6d, 0xf1, 0xa0, 0x79, 0x7a, 0x93, 0x1f, 0x10, 0xf8, 0xd8, 0x4f, 0xa3, 0x55, 0x75, 0xa0, 0xd6, + 0xe8, 0x19, 0x41, 0x4f, 0x33, 0xe0, 0x36, 0x2e, 0x87, 0xb0, 0x8d, 0x63, 0x58, 0x98, 0xf1, 0x62, 0x18, 0x2f, 0x86, + 0x5c, 0x79, 0x7b, 0x0a, 0xb1, 0x80, 0xdd, 0x80, 0xd4, 0x2c, 0x27, 0x64, 0x27, 0x52, 0xf6, 0x20, 0x50, 0x10, 0xa1, + 0xfc, 0xe6, 0x65, 0xfc, 0x1b, 0x21, 0x28, 0x08, 0xb0, 0x82, 0x68, 0xd5, 0x81, 0x64, 0x6b, 0x13, 0x39, 0xad, 0x25, + 0x55, 0x71, 0x7e, 0x29, 0xc3, 0xe4, 0x77, 0xfd, 0xf9, 0x75, 0x1b, 0x6d, 0x18, 0xc3, 0x53, 0x73, 0xcd, 0x46, 0x93, + 0xe1, 0x53, 0x66, 0x7f, 0x21, 0xc4, 0xc1, 0x21, 0xbf, 0x15, 0xc3, 0x7a, 0x28, 0x6d, 0x18, 0x3c, 0xea, 0x5c, 0x5a, + 0x45, 0xa5, 0xbd, 0x61, 0x27, 0x1a, 0xc6, 0xde, 0xf2, 0xe7, 0x3b, 0x81, 0x8f, 0x81, 0x2b, 0x0c, 0x10, 0xf4, 0x7f, + 0xfb, 0x5b, 0xef, 0x00, 0xff, 0x31, 0xa2, 0xc8, 0x81, 0xdb, 0x0a, 0x83, 0x8c, 0x6d, 0xb3, 0xed, 0x36, 0xfa, 0x98, + 0x6b, 0x3d, 0xf1, 0x42, 0x27, 0x0b, 0xe3, 0xdd, 0x1f, 0x41, 0x19, 0xe6, 0x45, 0x12, 0xe7, 0x45, 0x54, 0xe9, 0xc3, + 0xa2, 0xaa, 0x22, 0xdd, 0x3f, 0x00, 0x30, 0x0a, 0xe7, 0xd3, 0xef, 0xdf, 0x10, 0xaf, 0xec, 0xc6, 0xf7, 0x6a, 0x24, + 0x9f, 0x13, 0xe2, 0xf5, 0xdc, 0x77, 0xb8, 0x03, 0xb3, 0x5f, 0x21, 0x98, 0xb9, 0x9c, 0x4c, 0x06, 0xd7, 0xf4, 0x1b, + 0x05, 0x72, 0xfc, 0xd8, 0x0d, 0x1d, 0xd8, 0x4c, 0xa7, 0xf6, 0x96, 0xef, 0x07, 0xf8, 0xcc, 0x19, 0xcd, 0xea, 0xcd, + 0x8f, 0xbe, 0x6c, 0x50, 0x16, 0xe1, 0x8f, 0x63, 0x72, 0x20, 0x75, 0x95, 0x2e, 0x21, 0xe0, 0x59, 0x9f, 0x34, 0xd0, + 0x10, 0x4e, 0x6d, 0x44, 0x7e, 0x7f, 0x1b, 0x22, 0x7c, 0x67, 0x4f, 0x39, 0xea, 0x44, 0x8f, 0xa8, 0x27, 0x64, 0xb6, + 0xdd, 0xd6, 0x07, 0x64, 0x59, 0xb0, 0xf9, 0x06, 0xce, 0x53, 0xd3, 0x92, 0xc3, 0x4f, 0xfd, 0xb9, 0x09, 0x55, 0xa4, + 0xec, 0x77, 0xf0, 0x26, 0xc9, 0xc8, 0xa8, 0x50, 0xfe, 0x37, 0x59, 0x6f, 0x51, 0x32, 0xe2, 0x4b, 0x62, 0x2a, 0x98, + 0x3e, 0xf2, 0x98, 0xcd, 0x48, 0x4a, 0x5d, 0x6b, 0x25, 0x0f, 0xbe, 0x87, 0x42, 0xe3, 0xf4, 0x06, 0x21, 0xd8, 0x60, + 0x5a, 0x41, 0x3c, 0x5a, 0x31, 0xca, 0x1a, 0x4f, 0x26, 0xef, 0xb7, 0x52, 0x13, 0x7a, 0x7c, 0x5b, 0x25, 0x8b, 0x27, + 0x73, 0x47, 0xca, 0x47, 0x12, 0x47, 0xda, 0x28, 0x68, 0xf1, 0xa6, 0xe3, 0xfd, 0xac, 0x33, 0x22, 0x05, 0xbd, 0x9c, + 0x1b, 0x91, 0xf2, 0xcb, 0x1b, 0x66, 0xdf, 0x1e, 0x5c, 0x1e, 0x3c, 0x3e, 0x16, 0x45, 0x4e, 0x81, 0xbb, 0x75, 0x0d, + 0x2f, 0xfb, 0xa2, 0x2b, 0x61, 0x28, 0xa7, 0x94, 0x07, 0x85, 0xc2, 0xc8, 0x16, 0x48, 0x43, 0x7e, 0x12, 0xf9, 0xfb, + 0x61, 0x3e, 0x63, 0xf8, 0xba, 0xf4, 0x49, 0xca, 0x4a, 0x62, 0x7f, 0x22, 0xd2, 0x64, 0xe2, 0x8d, 0x79, 0xbf, 0xff, + 0x63, 0xf6, 0x62, 0x3f, 0x54, 0x19, 0x33, 0x77, 0x93, 0xc8, 0x42, 0x1d, 0x94, 0xf2, 0x15, 0x4e, 0x3b, 0xfc, 0xff, + 0x46, 0xa2, 0xed, 0x42, 0x0f, 0x6f, 0x0f, 0x3c, 0x14, 0xad, 0x49, 0x62, 0xdb, 0x7b, 0xba, 0x04, 0x2b, 0x54, 0xdb, + 0xf8, 0x72, 0x1a, 0x79, 0x56, 0xf4, 0x6a, 0x77, 0xc5, 0x70, 0xef, 0xa0, 0xbe, 0xc9, 0xaa, 0xfd, 0xd4, 0x64, 0x1a, + 0x58, 0x81, 0xc0, 0x77, 0x41, 0x6e, 0x1d, 0x27, 0xae, 0xd7, 0xda, 0xdf, 0xad, 0x36, 0x61, 0xb5, 0xa1, 0x6e, 0x41, + 0x64, 0x5e, 0x30, 0xb0, 0x2c, 0x9a, 0x27, 0x11, 0x14, 0xc3, 0x32, 0x18, 0x72, 0xa6, 0x64, 0x81, 0xf3, 0x56, 0x40, + 0x1e, 0xdd, 0x2b, 0x38, 0x21, 0x61, 0xb4, 0x8e, 0x35, 0x1b, 0xf9, 0x22, 0x14, 0xf9, 0xaa, 0x6d, 0x36, 0x2e, 0xc5, + 0x3d, 0x4d, 0x6a, 0x15, 0xd0, 0x5c, 0x56, 0x30, 0x85, 0xf6, 0x8d, 0x42, 0xe2, 0x4c, 0x23, 0x79, 0xfe, 0x92, 0xee, + 0xc7, 0xb1, 0x41, 0x17, 0xf9, 0x2b, 0x0d, 0xdb, 0xce, 0xb5, 0xbe, 0xfb, 0xa0, 0x00, 0x5f, 0xa8, 0x23, 0xf3, 0x29, + 0xed, 0x2f, 0xab, 0xd6, 0x0d, 0x5f, 0xa8, 0xe5, 0x17, 0x13, 0xfd, 0xa5, 0x92, 0x66, 0x7f, 0x5f, 0x5a, 0xa0, 0x94, + 0xa7, 0x59, 0xae, 0x9a, 0x5a, 0x3e, 0xf2, 0x3f, 0xcd, 0x93, 0x09, 0x99, 0xd0, 0x39, 0x2c, 0x1f, 0x15, 0x69, 0x76, + 0x9f, 0x3f, 0x70, 0xff, 0x86, 0x57, 0xca, 0xde, 0x13, 0xe7, 0x31, 0xbd, 0xa7, 0xc4, 0xe6, 0xcc, 0x03, 0x0c, 0xb2, + 0x22, 0x4e, 0x6d, 0xab, 0xd9, 0x3b, 0x92, 0x39, 0x56, 0xdd, 0x65, 0x72, 0xc2, 0x64, 0xe8, 0xae, 0xe2, 0x83, 0x46, + 0xd8, 0xcd, 0xf7, 0x89, 0x0f, 0x2c, 0x82, 0x66, 0x94, 0xee, 0x6a, 0xb7, 0x7f, 0x2c, 0x57, 0xb1, 0x48, 0xa4, 0xc8, + 0x56, 0xd4, 0x6a, 0x9f, 0xe8, 0x21, 0x7f, 0x2b, 0xf9, 0xf9, 0x3f, 0x95, 0x88, 0x1b, 0x87, 0xd3, 0x7f, 0x4e, 0x54, + 0x10, 0x06, 0xb5, 0x43, 0x46, 0xb2, 0x84, 0x0a, 0x14, 0xc6, 0xce, 0x04, 0xdb, 0x5f, 0xb0, 0x1e, 0x60, 0x91, 0x48, + 0x22, 0x69, 0x28, 0x8f, 0x2c, 0x11, 0xa8, 0x12, 0xdf, 0x53, 0x97, 0xcd, 0x0f, 0x51, 0xb4, 0x71, 0x7d, 0x1e, 0x10, + 0x2a, 0xd3, 0x96, 0x2b, 0xe7, 0xb4, 0x72, 0xe5, 0x5e, 0x90, 0x18, 0x49, 0x24, 0x38, 0x82, 0xda, 0xa8, 0x21, 0x7c, + 0x48, 0x4a, 0x2f, 0x9d, 0x54, 0xde, 0xb5, 0xb8, 0x26, 0x8f, 0x02, 0x88, 0x4d, 0xc6, 0xf8, 0xf5, 0xe5, 0xaa, 0xdd, + 0x78, 0xba, 0x6c, 0xc4, 0xe2, 0x77, 0x0a, 0x38, 0x41, 0xba, 0xaf, 0x28, 0xa0, 0x37, 0x60, 0x55, 0x07, 0x7c, 0xfb, + 0x04, 0x8e, 0x4a, 0x07, 0x8a, 0xe9, 0xc8, 0xa1, 0x22, 0xbf, 0x03, 0xae, 0xdd, 0xad, 0x88, 0xf0, 0xed, 0xf2, 0x35, + 0x2b, 0x6a, 0x09, 0x41, 0xad, 0x35, 0x89, 0x66, 0xb6, 0x08, 0xc5, 0xc6, 0xbd, 0x80, 0xcb, 0x73, 0x28, 0xfa, 0xf0, + 0x12, 0x17, 0x71, 0xe0, 0xfd, 0xc5, 0x4b, 0x9b, 0x27, 0xd3, 0x29, 0xfd, 0xd6, 0x77, 0x74, 0xf0, 0xe8, 0xe5, 0xc3, + 0xb2, 0x48, 0x27, 0x29, 0x78, 0xc4, 0x20, 0x08, 0x93, 0xf4, 0x89, 0x47, 0x4c, 0x76, 0x9a, 0x77, 0x1e, 0xdc, 0xc5, + 0x05, 0xb2, 0x1f, 0x46, 0xf0, 0x10, 0xd9, 0x5e, 0x9a, 0x38, 0xa0, 0x3d, 0xb7, 0x75, 0x76, 0x32, 0x6e, 0x9e, 0x78, + 0x2f, 0x5a, 0xf0, 0x2a, 0xe6, 0x7d, 0xe2, 0x11, 0xc6, 0x0c, 0x7e, 0xee, 0x12, 0x92, 0x1c, 0x6b, 0xa9, 0xe0, 0x28, + 0xe8, 0x81, 0x7c, 0x31, 0x92, 0x51, 0x9a, 0xd1, 0xb7, 0x3f, 0x9b, 0xbb, 0x1d, 0xed, 0xaa, 0xdb, 0x6c, 0x83, 0x8b, + 0xae, 0x8c, 0x5f, 0xcf, 0x7d, 0xd9, 0xb1, 0xa3, 0x2b, 0x37, 0x0e, 0xd8, 0x96, 0xd1, 0x9b, 0x2e, 0xb1, 0x58, 0x69, + 0x0d, 0xa9, 0x20, 0xf6, 0x65, 0x4e, 0xe0, 0xd2, 0x4a, 0x73, 0x52, 0xb0, 0x06, 0xef, 0x32, 0x3d, 0x59, 0xad, 0xbe, + 0x7b, 0x29, 0xeb, 0xe1, 0x19, 0x7f, 0xdb, 0x0b, 0xd5, 0xc8, 0xc5, 0xef, 0xa7, 0x1c, 0x64, 0x1d, 0x5d, 0x64, 0xc8, + 0xa4, 0x2f, 0xd0, 0xde, 0x37, 0x59, 0x04, 0x36, 0xe1, 0x80, 0xdc, 0xbb, 0x95, 0xda, 0xc0, 0x65, 0xbc, 0xb1, 0x89, + 0xe8, 0x69, 0x2c, 0xc2, 0x69, 0x2f, 0xec, 0xc1, 0xdf, 0xd1, 0xcd, 0x34, 0xe7, 0xa9, 0xbc, 0x74, 0xdf, 0xde, 0xbb, + 0x74, 0xbf, 0x48, 0xbe, 0xc7, 0xee, 0xf3, 0xc5, 0xfb, 0x45, 0x1d, 0xde, 0x1c, 0xd8, 0x3f, 0x33, 0xbc, 0xb4, 0x47, + 0xcd, 0xcd, 0xdb, 0x9a, 0x7d, 0x2d, 0xf6, 0x5b, 0x87, 0x37, 0x5d, 0x44, 0x99, 0x9d, 0x33, 0x1a, 0x5b, 0xf3, 0x6b, + 0xbc, 0x7e, 0xfc, 0xf1, 0x67, 0xfe, 0x59, 0xce, 0x0b, 0x86, 0x61, 0x8d, 0x9f, 0x77, 0x59, 0x0f, 0xab, 0xb6, 0x7e, + 0x2c, 0xf0, 0xd1, 0xdc, 0xbc, 0xa3, 0xda, 0xb8, 0xb7, 0x48, 0x1f, 0xad, 0xdc, 0x35, 0x9f, 0x3c, 0x32, 0xb8, 0xf0, + 0x23, 0xf3, 0xf9, 0xa8, 0x1f, 0x41, 0xc8, 0xe5, 0x4f, 0xde, 0x45, 0x62, 0xfa, 0xc7, 0xd6, 0x2b, 0xb1, 0x88, 0x7d, + 0xaa, 0x81, 0x70, 0x37, 0x5e, 0xa4, 0x45, 0xd9, 0x77, 0xf4, 0x0b, 0x7b, 0x4c, 0x56, 0xef, 0x40, 0x04, 0x0a, 0x5a, + 0x9f, 0x9d, 0x24, 0x12, 0x3f, 0x44, 0xff, 0xe4, 0x8f, 0xa8, 0xd3, 0x4e, 0xb4, 0xff, 0xd8, 0x4e, 0xf8, 0xff, 0xa7, + 0x6b, 0x5b, 0xf5, 0x96, 0x0d, 0xf0, 0xd6, 0xff, 0x05, 0xa2, 0x0d, 0x6d, 0xaf, 0x04, 0xe9, 0xa1, 0x8b, 0x88, 0xfc, + 0xd9, 0xad, 0x66, 0x59, 0x61, 0xf5, 0x32, 0x57, 0x2c, 0xe3, 0x09, 0x9d, 0x93, 0x0b, 0x8d, 0x93, 0x34, 0x4d, 0x19, + 0xbc, 0x67, 0xd2, 0xec, 0x75, 0x2d, 0x43, 0xef, 0x36, 0x67, 0x8f, 0xd0, 0x49, 0x3a, 0xce, 0x92, 0x8a, 0x45, 0xb4, + 0x6e, 0x57, 0x6d, 0x9e, 0xad, 0x47, 0x70, 0x06, 0x07, 0x67, 0x59, 0x40, 0xef, 0xc1, 0x52, 0xdb, 0x9d, 0x1b, 0x3b, + 0x4c, 0xf7, 0x2f, 0x2d, 0x87, 0x23, 0x82, 0xc6, 0xde, 0x2c, 0xb7, 0xed, 0x8f, 0x4a, 0x0a, 0x15, 0xf1, 0xe6, 0xc0, + 0x40, 0x2f, 0x7e, 0x3d, 0x91, 0x65, 0xd0, 0x75, 0x2f, 0x5f, 0x0b, 0x61, 0x59, 0xab, 0xb9, 0x76, 0x18, 0x9f, 0x0b, + 0xab, 0x20, 0xb4, 0x0b, 0x21, 0xce, 0x5e, 0xe8, 0x3a, 0x01, 0x4d, 0x8c, 0x78, 0x8b, 0x0b, 0x09, 0x36, 0x39, 0x28, + 0x54, 0x50, 0x3a, 0x3e, 0xd2, 0xee, 0x41, 0x10, 0x7a, 0x2e, 0xc6, 0x0a, 0xc8, 0xb1, 0xdc, 0x4e, 0x65, 0x22, 0x9a, + 0x24, 0x04, 0xae, 0xf2, 0x43, 0xf8, 0x8c, 0x64, 0xbc, 0x9c, 0xda, 0x45, 0x58, 0x77, 0x9b, 0xaa, 0xcd, 0x41, 0xef, + 0xfe, 0x27, 0xac, 0x42, 0x17, 0x45, 0xd1, 0x7a, 0xd6, 0x59, 0x9e, 0x47, 0xcc, 0x03, 0xb3, 0x49, 0x81, 0x46, 0x11, + 0x8a, 0xd0, 0xbf, 0x27, 0xf6, 0xd0, 0x88, 0x2a, 0xa3, 0xba, 0x60, 0x31, 0xac, 0x30, 0x57, 0x4e, 0x4b, 0x69, 0xa7, + 0x2c, 0x77, 0xa3, 0x1d, 0xe0, 0xc7, 0x57, 0xff, 0x6c, 0x43, 0xff, 0x72, 0xe9, 0x63, 0xdb, 0x8b, 0x2d, 0x36, 0xbf, + 0x7e, 0x3e, 0x4b, 0xef, 0x0e, 0x4f, 0xa3, 0xd8, 0x82, 0x9a, 0x40, 0x25, 0x13, 0x85, 0x52, 0xf3, 0xba, 0xe0, 0x10, + 0xb4, 0x50, 0xfc, 0x68, 0x54, 0xd4, 0xfb, 0x79, 0x35, 0x01, 0x05, 0x09, 0x20, 0x1c, 0x4b, 0x1a, 0x69, 0x97, 0xd8, + 0x82, 0x48, 0xeb, 0xb3, 0xf2, 0x6e, 0x84, 0xd7, 0x36, 0x68, 0x8a, 0xe0, 0x90, 0x25, 0xd3, 0xc2, 0xb0, 0x22, 0x83, + 0x04, 0x18, 0xb7, 0x11, 0xd2, 0x8b, 0xe4, 0x1f, 0x50, 0x02, 0xf0, 0x2a, 0xa2, 0xbd, 0x51, 0x99, 0x88, 0xe4, 0xa5, + 0xac, 0x51, 0x0a, 0x4b, 0x00, 0x02, 0xff, 0x32, 0xbf, 0x22, 0x58, 0x22, 0xd5, 0x58, 0xa3, 0x35, 0x9d, 0x11, 0xa8, + 0xad, 0x7e, 0x07, 0x44, 0x98, 0xd7, 0xd8, 0xcd, 0x68, 0x7e, 0x43, 0xb3, 0x24, 0xc6, 0xb8, 0x6a, 0x6f, 0x3e, 0xe7, + 0x72, 0xbb, 0xe6, 0xb2, 0xdf, 0x5a, 0x0f, 0xec, 0x4d, 0xba, 0xcf, 0x3a, 0xf3, 0xc0, 0xc7, 0xa7, 0x15, 0xce, 0xeb, + 0x25, 0x99, 0x95, 0xc7, 0x47, 0x5f, 0xf7, 0xae, 0xb5, 0x50, 0x73, 0xf3, 0xbe, 0x3e, 0xdc, 0xbc, 0x77, 0x6d, 0x85, + 0x1f, 0xfc, 0x5f, 0xc6, 0xf1, 0xb4, 0x46, 0x56, 0xfe, 0x5a, 0x15, 0xd5, 0x36, 0x62, 0x98, 0x78, 0x3b, 0x65, 0x08, + 0xe4, 0xa9, 0xda, 0x83, 0xdd, 0x49, 0x54, 0xda, 0x6f, 0x2a, 0x52, 0xb7, 0x9d, 0x0b, 0x45, 0x67, 0xa2, 0x4d, 0x72, + 0xc2, 0x33, 0x9e, 0x6f, 0x8e, 0x30, 0x89, 0xa4, 0xe5, 0x3a, 0x53, 0x37, 0xdc, 0xfd, 0x5c, 0xae, 0x3f, 0x6e, 0x1a, + 0xd0, 0x21, 0x8b, 0x8f, 0xfb, 0x90, 0x51, 0x10, 0x34, 0xbc, 0x6c, 0x96, 0x09, 0x79, 0xac, 0x13, 0xeb, 0x6a, 0xf7, + 0x65, 0x8a, 0xba, 0x3f, 0xd7, 0x2f, 0xc4, 0xb1, 0xb7, 0xc3, 0x24, 0xb1, 0xb1, 0x64, 0x9a, 0xb5, 0x46, 0x1a, 0x79, + 0x70, 0x7a, 0x6a, 0x7b, 0xe6, 0x65, 0x67, 0xf5, 0xd6, 0xcc, 0x03, 0x1d, 0x70, 0x12, 0x69, 0x0b, 0xe6, 0x64, 0x5e, + 0xcc, 0xcf, 0x4f, 0x07, 0xe9, 0xc6, 0xfd, 0x5c, 0x8d, 0xed, 0x88, 0xc7, 0xa4, 0x27, 0x09, 0xfc, 0x44, 0x09, 0xbe, + 0x25, 0x91, 0x06, 0xe0, 0xe5, 0xeb, 0xcb, 0x11, 0x64, 0xb6, 0x0a, 0x48, 0x4c, 0xb6, 0xf5, 0xeb, 0x4f, 0x01, 0x83, + 0xce, 0x56, 0x20, 0x01, 0x43, 0xf1, 0x33, 0x68, 0xbd, 0xc6, 0x97, 0x1a, 0x24, 0x29, 0x31, 0x3e, 0x99, 0xe1, 0xe6, + 0x93, 0x28, 0xf0, 0xf0, 0x5b, 0x47, 0xb6, 0xd9, 0x0e, 0x65, 0x9c, 0x41, 0xf5, 0x98, 0xd6, 0xc3, 0x29, 0x33, 0xe3, + 0xf9, 0x4c, 0x7a, 0x1c, 0x7f, 0xab, 0x80, 0xbc, 0x0f, 0xcc, 0xdb, 0xa0, 0x6c, 0x82, 0x70, 0x02, 0x83, 0xcb, 0xb9, + 0x17, 0x9b, 0x40, 0x5c, 0xbf, 0x84, 0x35, 0xa6, 0x93, 0x3c, 0x9f, 0xab, 0xc3, 0x0f, 0xe3, 0xb7, 0x1e, 0xb9, 0x37, + 0xbd, 0x57, 0x8c, 0x4b, 0xd3, 0x7a, 0xc1, 0x30, 0xbb, 0x52, 0x6c, 0x80, 0x5a, 0x05, 0x33, 0x5b, 0x32, 0x6e, 0xa5, + 0x45, 0x16, 0x38, 0x6e, 0x7a, 0xef, 0xd4, 0xec, 0xae, 0xad, 0x07, 0xa4, 0x4f, 0x34, 0x44, 0x8c, 0x4f, 0x55, 0xe0, + 0x12, 0x75, 0xfc, 0x1e, 0x7f, 0x7a, 0xcf, 0x5f, 0xc3, 0x38, 0x15, 0x6f, 0xb6, 0xf1, 0x22, 0x63, 0x2b, 0xcb, 0xf3, + 0xf7, 0xf1, 0x9e, 0x43, 0x4b, 0x6b, 0x3f, 0x8c, 0x31, 0x58, 0xc9, 0x67, 0x0a, 0xf5, 0x84, 0x1d, 0xff, 0x22, 0x91, + 0xfe, 0xd9, 0x5a, 0xfa, 0x5b, 0xfc, 0x33, 0xc2, 0xff, 0x31, 0x0c, 0x95, 0xe6, 0xcb, 0x3f, 0xa2, 0xfe, 0x23, 0xbe, + 0x50, 0x56, 0x7a, 0x91, 0x73, 0x4f, 0xb5, 0xd9, 0x98, 0x8f, 0xf6, 0x26, 0x4e, 0x0a, 0x18, 0xc5, 0x99, 0x89, 0x82, + 0x38, 0xcf, 0xd5, 0xf9, 0x48, 0xf2, 0xb7, 0x9a, 0xb8, 0xf0, 0xcb, 0xf1, 0xd1, 0xf0, 0xf1, 0xdc, 0xa7, 0xe7, 0xfd, + 0x1e, 0x52, 0xb9, 0x2f, 0x12, 0xd5, 0xb6, 0xb2, 0x7d, 0xf2, 0xf7, 0x5d, 0xe7, 0x8e, 0x08, 0xac, 0x3f, 0x0f, 0x3e, + 0xb3, 0x8c, 0x3f, 0x19, 0x5e, 0xa6, 0x29, 0x5a, 0x33, 0x16, 0x5f, 0xe8, 0x33, 0xad, 0x8d, 0xdf, 0xb8, 0x55, 0x65, + 0x9b, 0x1a, 0x50, 0x9b, 0x6e, 0x82, 0xc4, 0xa4, 0x82, 0x06, 0x65, 0x9d, 0xfb, 0xf4, 0x07, 0x44, 0x1b, 0x12, 0x8a, + 0x7e, 0xfc, 0x43, 0x21, 0xe8, 0x2e, 0x41, 0x02, 0x90, 0xc4, 0x30, 0x33, 0x7e, 0x29, 0x48, 0x07, 0x34, 0x3c, 0xd4, + 0xdb, 0xcb, 0xc6, 0x56, 0x7d, 0x0e, 0x39, 0xfe, 0x6d, 0x74, 0x7f, 0x60, 0xf5, 0xd0, 0x80, 0x8a, 0xe3, 0x70, 0xf9, + 0x7f, 0xf4, 0x86, 0x30, 0x8a, 0x7a, 0x48, 0xa8, 0x2e, 0x16, 0x8d, 0x7f, 0x3a, 0x4a, 0xca, 0x19, 0x4a, 0x96, 0x72, + 0x1e, 0x15, 0x03, 0xcf, 0x82, 0xa0, 0xba, 0xa2, 0xc7, 0x26, 0xcf, 0xc5, 0xb3, 0x82, 0x43, 0xfe, 0x4f, 0xb0, 0xec, + 0x32, 0xc4, 0x64, 0x8c, 0xf8, 0xce, 0x4f, 0x10, 0x96, 0x64, 0x35, 0x6c, 0xcc, 0x1e, 0xc2, 0xed, 0x47, 0x6f, 0xa0, + 0x21, 0xdc, 0x7c, 0x7c, 0x80, 0x04, 0x7c, 0xe3, 0xcd, 0xea, 0x6a, 0x54, 0xbe, 0x30, 0xa7, 0x5d, 0x41, 0xdc, 0x18, + 0x02, 0x10, 0x89, 0xe0, 0x54, 0x52, 0x80, 0xfa, 0x26, 0x69, 0x8b, 0x80, 0xc5, 0x84, 0x6b, 0x43, 0x72, 0xd0, 0x8e, + 0x8b, 0xc9, 0x99, 0x72, 0x28, 0x73, 0xea, 0x28, 0x05, 0xe4, 0x24, 0x8f, 0x0e, 0x64, 0xd6, 0xed, 0xa5, 0x64, 0x7c, + 0x95, 0x8d, 0x76, 0xd9, 0x42, 0xf5, 0x49, 0x84, 0x99, 0x44, 0x8c, 0x54, 0xf0, 0x24, 0x67, 0x65, 0x82, 0x7e, 0xd1, + 0x2e, 0xa6, 0x36, 0xe2, 0xe1, 0xde, 0x66, 0x46, 0xec, 0x22, 0xd0, 0xe0, 0xca, 0x21, 0x79, 0xc5, 0xab, 0x90, 0x41, + 0x90, 0x09, 0x0b, 0x84, 0x05, 0x5c, 0x68, 0xf7, 0x7d, 0xe2, 0x78, 0xd8, 0xef, 0x47, 0xc1, 0x25, 0xe7, 0xf5, 0x86, + 0x5d, 0x82, 0x3b, 0xaf, 0x7a, 0x7d, 0x5d, 0x5b, 0x87, 0x8f, 0x9f, 0x33, 0x22, 0x05, 0x96, 0x41, 0xde, 0xe0, 0xe5, + 0x41, 0x18, 0xf8, 0x81, 0x3d, 0x82, 0x97, 0xa9, 0xb3, 0x2f, 0xc2, 0x90, 0x60, 0xd6, 0x93, 0x1a, 0xd2, 0x96, 0x05, + 0x57, 0xa7, 0xd3, 0x36, 0xdb, 0x51, 0xa0, 0x46, 0xa9, 0xde, 0x17, 0x86, 0x32, 0x25, 0x5a, 0x65, 0x13, 0xd8, 0x21, + 0x10, 0x2d, 0x5b, 0x11, 0xbe, 0xc5, 0xdc, 0x84, 0x05, 0x3a, 0xe9, 0xb4, 0xcd, 0x76, 0xb4, 0x08, 0xdf, 0x80, 0x4e, + 0x2e, 0x26, 0x5c, 0x4c, 0xb9, 0xf4, 0x84, 0xbc, 0x3a, 0xa9, 0x40, 0x89, 0x09, 0x78, 0x28, 0x23, 0xc3, 0x7c, 0x9a, + 0xf2, 0xa5, 0x27, 0xbf, 0x89, 0x59, 0xb4, 0x5f, 0xe6, 0x3c, 0x0d, 0xd2, 0x06, 0x13, 0x1b, 0xa4, 0xa6, 0xd5, 0x49, + 0x12, 0xdf, 0x1f, 0x5a, 0xc0, 0x0c, 0x4a, 0x73, 0x7c, 0x6e, 0x63, 0x52, 0x4a, 0x45, 0xc8, 0xb8, 0x5e, 0x1e, 0xf5, + 0xec, 0x7c, 0x18, 0x09, 0x6a, 0x76, 0x13, 0x7e, 0xb6, 0x17, 0x8d, 0x96, 0x8a, 0x97, 0x93, 0x50, 0xc2, 0x08, 0x89, + 0x95, 0x80, 0x04, 0x79, 0x93, 0xd9, 0x00, 0xe5, 0x4f, 0xca, 0x95, 0xfb, 0x4a, 0xc6, 0x63, 0x87, 0x70, 0xc0, 0xcf, + 0x1c, 0x03, 0x47, 0x19, 0x35, 0xfa, 0x47, 0xf3, 0xc1, 0x61, 0x74, 0xea, 0x12, 0x86, 0x09, 0xc8, 0x72, 0x89, 0x35, + 0xca, 0xf8, 0x30, 0x40, 0xf5, 0xba, 0x1f, 0x26, 0x1b, 0xfc, 0x11, 0x4d, 0x78, 0x24, 0x1b, 0xe6, 0xb0, 0xab, 0x16, + 0x9a, 0x18, 0xe4, 0x01, 0xe4, 0x16, 0x55, 0x46, 0x8e, 0xcc, 0xe9, 0x3d, 0xaa, 0x1c, 0xad, 0xd0, 0xf7, 0x11, 0xb0, + 0x94, 0xea, 0xd9, 0xb5, 0x34, 0x55, 0x00, 0x4b, 0x68, 0x25, 0x50, 0xb6, 0x31, 0x9b, 0x7c, 0x6f, 0xd9, 0xde, 0xb8, + 0xcc, 0x46, 0xfe, 0x22, 0x8d, 0x58, 0xc3, 0x96, 0x80, 0x73, 0xf5, 0x81, 0xd0, 0x76, 0xb2, 0x07, 0x10, 0xa2, 0xa4, + 0x17, 0x99, 0xbb, 0x32, 0x41, 0x6e, 0x5e, 0xf3, 0x89, 0x36, 0xcb, 0x00, 0x5b, 0x0d, 0xc1, 0x9d, 0xe7, 0xc2, 0x37, + 0xa9, 0x39, 0x29, 0xb8, 0xe0, 0xe7, 0xfb, 0x2b, 0x44, 0x15, 0x5e, 0xe4, 0xba, 0x1b, 0xae, 0x45, 0x3c, 0x37, 0xe6, + 0x5f, 0xab, 0xc6, 0x8b, 0x45, 0x19, 0x96, 0xca, 0xbf, 0xa1, 0xc9, 0x16, 0xb2, 0x6f, 0xa9, 0xa4, 0xf1, 0x6f, 0x09, + 0x7b, 0xe2, 0x83, 0xd1, 0x88, 0x32, 0xdc, 0xc0, 0x9a, 0xf8, 0xc8, 0xbc, 0x8a, 0x5e, 0x1c, 0x0f, 0x08, 0x0e, 0x02, + 0x94, 0x81, 0x93, 0x10, 0x06, 0xe2, 0x73, 0x8c, 0x35, 0x5f, 0xb3, 0x1e, 0x73, 0xde, 0xf4, 0x26, 0xcf, 0x35, 0xbf, + 0xe0, 0x35, 0xa0, 0x02, 0xda, 0xc3, 0x8e, 0x1e, 0xcb, 0x60, 0x42, 0x33, 0x1e, 0x42, 0x3e, 0x7d, 0xf0, 0xdb, 0xfc, + 0x8c, 0xc1, 0x2c, 0x0a, 0x09, 0x32, 0x9c, 0xae, 0xba, 0x99, 0xa1, 0xd5, 0x26, 0xf0, 0x7f, 0xbf, 0xbb, 0x19, 0x35, + 0x44, 0xde, 0x8b, 0x90, 0xe9, 0x06, 0x32, 0xda, 0x62, 0x1a, 0x36, 0xcd, 0x34, 0x5b, 0x0d, 0x86, 0xea, 0xa3, 0xa6, + 0xaf, 0xf1, 0xda, 0x6b, 0x1d, 0x95, 0x43, 0xa7, 0x36, 0x30, 0xbc, 0xe7, 0xbf, 0x77, 0x0f, 0x05, 0x79, 0x91, 0x14, + 0x72, 0x3b, 0x1d, 0x22, 0xc3, 0x4d, 0xec, 0x58, 0xf7, 0xfa, 0x9f, 0x31, 0xe3, 0xe4, 0x33, 0x93, 0x39, 0x81, 0x4d, + 0x53, 0x53, 0xb4, 0xa0, 0x9f, 0x36, 0x4b, 0x73, 0xa7, 0xac, 0xf5, 0x5a, 0xf0, 0x4b, 0xab, 0xd4, 0x38, 0x64, 0x55, + 0xc3, 0xcb, 0x0b, 0x5d, 0x3c, 0xf1, 0x82, 0xbf, 0x0c, 0x4c, 0xb8, 0xf1, 0x53, 0x2b, 0xea, 0xea, 0xe2, 0x85, 0xbe, + 0xef, 0x3e, 0x4b, 0x79, 0x48, 0xb4, 0x45, 0x16, 0x1a, 0xb2, 0xb9, 0xc9, 0x8b, 0x99, 0x2f, 0x36, 0xa3, 0x82, 0xcf, + 0x57, 0x68, 0x20, 0x1b, 0x1c, 0xb6, 0xd5, 0x35, 0xbe, 0xf0, 0xbc, 0x4b, 0xa4, 0x32, 0x72, 0xb1, 0x17, 0x1c, 0xc2, + 0x61, 0xb9, 0xb4, 0x98, 0xb5, 0x7a, 0xfe, 0x0e, 0x9d, 0xf1, 0x14, 0xa7, 0x90, 0xa8, 0x94, 0x8b, 0x4f, 0xcc, 0xfe, + 0xac, 0xef, 0xf7, 0x39, 0xc3, 0xfb, 0x03, 0xc9, 0x67, 0xfd, 0x63, 0x5f, 0x6d, 0x82, 0xbd, 0x93, 0xb7, 0x4a, 0xfb, + 0xda, 0x86, 0x65, 0xec, 0x23, 0x05, 0x04, 0x7f, 0x53, 0x38, 0x35, 0xf4, 0x08, 0x53, 0xd2, 0x72, 0x2f, 0xf2, 0xdb, + 0x8a, 0x68, 0x89, 0x06, 0xde, 0xe2, 0xb8, 0x48, 0x9f, 0xb6, 0xe5, 0x5d, 0xb6, 0xd4, 0xf1, 0xd0, 0xad, 0x8c, 0x25, + 0xd1, 0xa8, 0xd2, 0xf4, 0x41, 0xf4, 0xdc, 0xd9, 0x92, 0xe8, 0xed, 0xce, 0x68, 0xf6, 0x24, 0x1f, 0x13, 0xea, 0x1a, + 0x71, 0xab, 0x9e, 0xb7, 0xd8, 0xd7, 0xd4, 0xec, 0x86, 0x5e, 0xa8, 0x19, 0x2a, 0x21, 0xab, 0xd1, 0x17, 0x6a, 0xfd, + 0x28, 0x42, 0x92, 0xec, 0xf1, 0xeb, 0x9a, 0x5f, 0x3e, 0xdf, 0x48, 0x85, 0x72, 0x75, 0x51, 0x51, 0xa0, 0xf9, 0x79, + 0x9a, 0x78, 0x82, 0x72, 0x5e, 0x4b, 0x5f, 0x7d, 0x6a, 0x00, 0x2a, 0x42, 0x72, 0x6b, 0x87, 0x86, 0x34, 0xb4, 0xcc, + 0xcd, 0xb3, 0x79, 0x16, 0x8a, 0x00, 0xdd, 0x33, 0x4f, 0x3c, 0x75, 0x31, 0x6e, 0xf6, 0x82, 0x41, 0xc5, 0xce, 0x13, + 0x93, 0x01, 0x70, 0x92, 0x3a, 0x88, 0x46, 0xb0, 0xb7, 0x3b, 0xcd, 0x3e, 0xe6, 0xe2, 0x19, 0xb8, 0x10, 0xd6, 0xd3, + 0xf2, 0xda, 0xb3, 0x68, 0xd7, 0x33, 0xa4, 0x49, 0xb7, 0x6f, 0x57, 0xe3, 0xd1, 0x05, 0x77, 0x64, 0xd2, 0x48, 0x68, + 0xa9, 0x86, 0x42, 0xae, 0x52, 0xb9, 0xa3, 0xee, 0xac, 0x99, 0x52, 0x6e, 0xa2, 0x70, 0x2b, 0x73, 0xd9, 0xba, 0x8c, + 0xe5, 0x1c, 0x61, 0x85, 0xad, 0xcc, 0x12, 0xcf, 0x02, 0xfc, 0x08, 0x0c, 0xa2, 0x52, 0x95, 0x67, 0xa2, 0x08, 0x49, + 0xdd, 0x60, 0x81, 0x89, 0xec, 0x7d, 0xbf, 0x85, 0x02, 0x0f, 0xbe, 0xf2, 0x11, 0xa3, 0x48, 0x14, 0x02, 0x02, 0x68, + 0x30, 0xd0, 0x02, 0xaa, 0x59, 0x3a, 0xa8, 0x86, 0x0f, 0xa1, 0xf3, 0x22, 0x9e, 0x98, 0x24, 0x19, 0xf4, 0x6f, 0xff, + 0x43, 0x81, 0x98, 0xf4, 0x01, 0x92, 0x2a, 0x13, 0x80, 0x1b, 0x16, 0x8f, 0xd3, 0x68, 0x2e, 0x5b, 0x91, 0x2b, 0x3d, + 0x8e, 0x7c, 0x6e, 0x8b, 0x7a, 0xc1, 0xca, 0x4b, 0x48, 0x69, 0xc7, 0xf0, 0xb2, 0xd7, 0xa5, 0xc2, 0xcf, 0x5e, 0xf3, + 0x0b, 0x26, 0x17, 0xc6, 0x21, 0x29, 0x17, 0xca, 0x10, 0xd6, 0x03, 0x00, 0x99, 0x77, 0x03, 0xd5, 0x9b, 0x84, 0x87, + 0xad, 0xb2, 0x39, 0x14, 0x0c, 0xc1, 0xc1, 0xbd, 0xf3, 0x39, 0x21, 0x89, 0x79, 0x0c, 0x43, 0x00, 0x27, 0x71, 0x4a, + 0x68, 0x33, 0x97, 0x71, 0xa6, 0x4e, 0x4f, 0xb2, 0xeb, 0x40, 0xdc, 0xda, 0x12, 0x42, 0xb1, 0x97, 0x75, 0x62, 0xc8, + 0x92, 0xaa, 0xc7, 0xa4, 0xdc, 0x8c, 0x60, 0xd7, 0xfe, 0x14, 0x4f, 0x75, 0x18, 0x8a, 0x9b, 0x19, 0x18, 0x89, 0x99, + 0x90, 0x9c, 0x0d, 0x92, 0xe4, 0x99, 0x74, 0x59, 0x5b, 0x93, 0xba, 0xce, 0xdf, 0x32, 0x84, 0x47, 0x24, 0xe3, 0xfc, + 0x2a, 0x0f, 0x75, 0xc7, 0x95, 0x4d, 0xaa, 0x2c, 0x4f, 0x4f, 0xbe, 0xeb, 0x5e, 0xd7, 0x98, 0x1a, 0xde, 0x03, 0x6a, + 0x64, 0x71, 0xe8, 0x36, 0xe7, 0x63, 0x67, 0x82, 0x9f, 0xbb, 0x3c, 0x50, 0x17, 0x0f, 0x3b, 0x92, 0xd0, 0xcf, 0x37, + 0x78, 0x5d, 0x68, 0x74, 0xc6, 0x80, 0x9c, 0x24, 0xe7, 0xe2, 0x52, 0x0b, 0xd4, 0x58, 0xf0, 0xd5, 0x8e, 0xa4, 0x6e, + 0x23, 0x0f, 0x7c, 0x23, 0x2e, 0x84, 0x2e, 0x72, 0xdb, 0x74, 0x8d, 0xfc, 0x9c, 0xde, 0xad, 0x5a, 0xe0, 0x49, 0x7e, + 0xfd, 0x7b, 0x55, 0x7a, 0x42, 0xaf, 0x2a, 0x71, 0x16, 0x9f, 0xb8, 0x44, 0x37, 0xd3, 0x3c, 0x82, 0x93, 0xba, 0x6a, + 0xca, 0x00, 0xbd, 0x2e, 0xbc, 0x1d, 0x68, 0x12, 0x09, 0xbc, 0x30, 0xdd, 0x25, 0xae, 0xa4, 0x03, 0xe1, 0x41, 0xb1, + 0x87, 0x09, 0x26, 0x42, 0xa3, 0xcc, 0x86, 0x03, 0xc0, 0xcf, 0x21, 0xde, 0x8d, 0xf9, 0xab, 0x61, 0x59, 0x55, 0x0b, + 0x82, 0x3b, 0x65, 0x01, 0xd9, 0xcb, 0xc8, 0x80, 0x02, 0xea, 0x84, 0x2c, 0x28, 0x6d, 0xd4, 0xd8, 0x21, 0x67, 0x83, + 0x15, 0xaa, 0xe6, 0x01, 0xc7, 0x26, 0xdd, 0xda, 0xa7, 0x16, 0x62, 0x44, 0x83, 0x6a, 0x72, 0xfe, 0x3a, 0x40, 0x42, + 0xf9, 0x0c, 0x29, 0x70, 0xa4, 0x5f, 0x32, 0xff, 0x06, 0x4c, 0x7a, 0xa7, 0x20, 0xe8, 0x97, 0x21, 0xe3, 0x7e, 0xa9, + 0x23, 0x50, 0x5a, 0xc6, 0xf6, 0x0f, 0xc5, 0xf1, 0x0d, 0x67, 0x4c, 0xcf, 0xc9, 0xd7, 0x36, 0x9a, 0x3f, 0xaf, 0xd4, + 0x22, 0xc4, 0x4b, 0x42, 0x2a, 0x0c, 0x00, 0xbf, 0xb7, 0x92, 0xce, 0x63, 0xf0, 0xee, 0x01, 0xc7, 0x59, 0xad, 0x09, + 0xa5, 0x67, 0x40, 0xbe, 0xc5, 0xbf, 0x31, 0x4d, 0x07, 0x05, 0x70, 0x6a, 0x45, 0xde, 0xbb, 0xbb, 0xbb, 0x75, 0x28, + 0x18, 0xfa, 0x3a, 0x4c, 0x59, 0xbf, 0xe0, 0x28, 0x1b, 0xc8, 0x6d, 0xbb, 0xdd, 0x6d, 0x55, 0xd2, 0xce, 0x24, 0xc3, + 0x23, 0x89, 0x41, 0x2a, 0x8d, 0xfc, 0xac, 0x2b, 0xab, 0xcb, 0x2c, 0x8e, 0x14, 0x17, 0x80, 0xee, 0x78, 0x86, 0xcd, + 0x1b, 0x5b, 0xf5, 0x81, 0x77, 0x20, 0xcd, 0x75, 0x02, 0x00, 0xbc, 0xf0, 0x54, 0x31, 0xe1, 0x8e, 0xb9, 0xca, 0x4e, + 0xa2, 0x9e, 0x4c, 0x34, 0x07, 0xe7, 0xf9, 0xa8, 0x42, 0x3e, 0xe9, 0x0e, 0x2b, 0x3e, 0x2f, 0x02, 0xe2, 0x71, 0x9c, + 0x54, 0x06, 0x43, 0xa2, 0xe0, 0xa7, 0x22, 0xec, 0x78, 0xba, 0x70, 0x9e, 0xdc, 0x55, 0xe9, 0xce, 0x01, 0xaa, 0x21, + 0x01, 0xab, 0x82, 0x6d, 0xd8, 0xbc, 0xcc, 0x49, 0x5c, 0xb6, 0x33, 0x86, 0x64, 0x1d, 0x0e, 0x6a, 0xe1, 0x63, 0xaf, + 0xf4, 0x43, 0x52, 0x28, 0xc4, 0xb9, 0x08, 0xe7, 0x59, 0x48, 0x9e, 0x0e, 0x90, 0x19, 0x79, 0x39, 0x79, 0xaf, 0xdd, + 0xd9, 0xae, 0x5b, 0x82, 0x48, 0xb7, 0x78, 0x6b, 0xac, 0xa7, 0xe3, 0x95, 0x4d, 0xc7, 0x54, 0x05, 0x92, 0x4d, 0xa4, + 0x82, 0x2a, 0xa5, 0xc1, 0xca, 0xd3, 0x01, 0x50, 0x30, 0x37, 0xfc, 0xad, 0x71, 0x4f, 0xcb, 0x84, 0x61, 0x73, 0x34, + 0xd8, 0x24, 0x0e, 0xee, 0x07, 0x83, 0x4e, 0x21, 0x6e, 0xd4, 0x2e, 0x70, 0x0d, 0x36, 0xd1, 0xcc, 0xc4, 0x1e, 0xff, + 0x5e, 0x7e, 0x10, 0x59, 0x65, 0x57, 0x25, 0xcd, 0x44, 0xa2, 0x5c, 0xba, 0x08, 0xc9, 0x5e, 0xfd, 0x3b, 0xfd, 0x56, + 0xe8, 0x74, 0xa0, 0x00, 0x74, 0x1c, 0x29, 0x24, 0xc4, 0x4c, 0x93, 0xee, 0x89, 0xe7, 0xf7, 0x5f, 0x7f, 0xfd, 0xdd, + 0xd6, 0xd6, 0x7c, 0x15, 0xbc, 0xf3, 0x79, 0xd1, 0x84, 0xed, 0xce, 0x52, 0xea, 0xfa, 0x1d, 0x58, 0x00, 0x3b, 0xdb, + 0x78, 0x26, 0x86, 0xb7, 0x4d, 0xf4, 0xa0, 0x0b, 0xf2, 0xc2, 0xf1, 0xa3, 0xf6, 0x87, 0x8f, 0xb8, 0x55, 0x16, 0xe8, + 0xbd, 0xba, 0x33, 0x8b, 0x40, 0xcc, 0x00, 0x2a, 0x20, 0xaf, 0xa0, 0xab, 0x18, 0x82, 0xe0, 0x97, 0x06, 0x49, 0x87, + 0x13, 0xce, 0x04, 0x7c, 0x36, 0x08, 0xba, 0xf3, 0xb7, 0xc3, 0x8e, 0xee, 0x44, 0xbc, 0x77, 0xe8, 0xe2, 0xd7, 0x76, + 0xea, 0x90, 0x29, 0x4f, 0x2f, 0x8d, 0xae, 0xec, 0x42, 0x73, 0xbd, 0xd3, 0xa7, 0x12, 0xe2, 0x63, 0x36, 0x46, 0x2e, + 0x28, 0x5e, 0xc1, 0x40, 0xf3, 0x60, 0x93, 0x7c, 0xb1, 0xf5, 0x3a, 0xb8, 0x1f, 0x37, 0x8f, 0x14, 0xfb, 0x05, 0xd5, + 0x0f, 0xb8, 0x61, 0x17, 0x52, 0xcb, 0xc7, 0x05, 0xc6, 0xca, 0x38, 0x28, 0x7f, 0x4e, 0xbb, 0xd3, 0x0b, 0xbf, 0x58, + 0x14, 0x15, 0x53, 0x12, 0xbf, 0x4d, 0xc2, 0xa4, 0x71, 0xaf, 0x5b, 0xd3, 0xe3, 0xf4, 0xbc, 0x20, 0x9c, 0x3b, 0xb9, + 0x7b, 0xfe, 0x4b, 0xb4, 0x3e, 0x9b, 0xe3, 0x76, 0xd7, 0xad, 0xe9, 0x77, 0x83, 0xa5, 0x4a, 0x93, 0x6e, 0x69, 0xec, + 0x5c, 0xbd, 0x09, 0x97, 0x75, 0x11, 0x89, 0xee, 0xcf, 0x7a, 0x2c, 0xa8, 0xd4, 0x33, 0x33, 0x7f, 0x0a, 0xa2, 0x86, + 0xb8, 0xde, 0xea, 0xe2, 0xbd, 0x5e, 0x7c, 0x4b, 0x8e, 0xbd, 0x74, 0x95, 0x64, 0x30, 0xa8, 0x0e, 0x5d, 0x0d, 0x8b, + 0xe4, 0x88, 0xa8, 0x5f, 0x31, 0x09, 0x98, 0xf5, 0x9c, 0x8f, 0xae, 0xd7, 0xa2, 0x79, 0xfa, 0xd6, 0x13, 0xa1, 0x7f, + 0xae, 0xc3, 0xed, 0xfb, 0x04, 0xae, 0xb6, 0xad, 0x63, 0x19, 0x8d, 0xe2, 0xcb, 0x46, 0x22, 0x66, 0x61, 0x47, 0xa2, + 0x4f, 0xff, 0x80, 0x48, 0xa2, 0xfc, 0xa4, 0xa5, 0x07, 0x49, 0x25, 0xdb, 0x6f, 0xf8, 0x70, 0x1f, 0xb5, 0x10, 0x68, + 0x6f, 0xff, 0x28, 0x52, 0x35, 0xbd, 0x4c, 0x24, 0xb1, 0xea, 0x40, 0xbd, 0xa6, 0xd4, 0xe7, 0x3e, 0xff, 0x7c, 0xfb, + 0x1d, 0x25, 0x64, 0x9a, 0x28, 0x59, 0xce, 0x18, 0x40, 0xae, 0xb1, 0xbb, 0x92, 0x90, 0x35, 0xbc, 0x4c, 0x4a, 0xef, + 0xc3, 0xcf, 0x67, 0xeb, 0xd0, 0x77, 0xff, 0x94, 0xc6, 0x65, 0xc1, 0x39, 0xf3, 0x66, 0xfe, 0x98, 0x9e, 0x06, 0x82, + 0x35, 0xaf, 0xb1, 0x77, 0x97, 0xeb, 0xcb, 0xd2, 0xe9, 0xa2, 0x5d, 0x3a, 0x5d, 0xb4, 0xda, 0x1b, 0xe6, 0xdf, 0xac, + 0x63, 0x0e, 0xbc, 0x5a, 0xb6, 0x0d, 0xa6, 0x12, 0x3c, 0xb5, 0xe5, 0x3f, 0x3a, 0x03, 0x57, 0x1e, 0x90, 0x1a, 0x6d, + 0xa0, 0x4f, 0x65, 0x10, 0x74, 0x73, 0xc3, 0x82, 0xa6, 0xab, 0x32, 0x23, 0xcd, 0x7c, 0x24, 0x5d, 0xf0, 0x39, 0x8d, + 0x39, 0xd8, 0xa7, 0xa9, 0xf2, 0x32, 0x14, 0x33, 0x7e, 0x56, 0xda, 0x82, 0xa6, 0x43, 0xe1, 0x47, 0x5c, 0xa6, 0x06, + 0xf4, 0xa2, 0xf3, 0x6b, 0x98, 0xc7, 0x59, 0xfa, 0x9b, 0xa7, 0x18, 0xe3, 0xf3, 0x86, 0x4c, 0xe1, 0xb8, 0xeb, 0x5e, + 0xa2, 0x80, 0x9f, 0x13, 0x1a, 0xcb, 0xf8, 0xbd, 0x18, 0xb4, 0x2f, 0xd2, 0x6d, 0x2e, 0x02, 0xa7, 0x02, 0xe4, 0x0f, + 0x09, 0xe3, 0x40, 0xd1, 0xd1, 0x5e, 0x63, 0xdf, 0x29, 0x55, 0xa6, 0xcf, 0x3d, 0xad, 0xd1, 0x13, 0xa5, 0x4c, 0x3f, + 0x19, 0x63, 0xcc, 0xba, 0xc8, 0xb1, 0xa5, 0xf9, 0xc0, 0x20, 0x93, 0x7c, 0xe1, 0x22, 0xa7, 0xc7, 0x9c, 0x3a, 0x0b, + 0x74, 0xab, 0x50, 0x6b, 0x0f, 0x96, 0x3f, 0xa0, 0x72, 0x60, 0xa8, 0x28, 0xfb, 0x71, 0x8a, 0x2d, 0xe2, 0x43, 0xfb, + 0x0d, 0xb7, 0x90, 0xb8, 0xed, 0x45, 0x26, 0x82, 0x54, 0x83, 0xa2, 0x58, 0xdb, 0x24, 0x23, 0xb9, 0xa1, 0x8a, 0xc1, + 0x46, 0x2d, 0x9f, 0x3e, 0x83, 0xd3, 0xe5, 0xd3, 0xd3, 0x9c, 0x5a, 0xb4, 0x25, 0x33, 0xf5, 0x8c, 0xc4, 0xd2, 0x15, + 0x76, 0xf1, 0xf2, 0x6b, 0xbc, 0xa1, 0x7d, 0xcc, 0x40, 0x22, 0x29, 0xbd, 0x6a, 0x1a, 0xc4, 0x0c, 0x36, 0x90, 0x46, + 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x4e, 0x40, 0x00, 0x46, 0x0f, 0x3f, 0x7a, 0x43, 0xe9, 0xb4, 0xd9, 0xed, 0x76, 0x56, + 0x26, 0x50, 0x74, 0xcd, 0x27, 0x63, 0x92, 0x37, 0x84, 0x9d, 0xc5, 0x2d, 0x79, 0x2a, 0x84, 0x31, 0x78, 0x79, 0x66, + 0x6c, 0x31, 0x7f, 0x7e, 0x3d, 0xd6, 0x2f, 0x0c, 0x25, 0x51, 0x52, 0xc8, 0xbe, 0xd4, 0x2d, 0x33, 0x1c, 0x59, 0x9c, + 0xe6, 0xe4, 0xd2, 0x83, 0x33, 0xf5, 0x18, 0x78, 0x0e, 0x04, 0xf2, 0xfa, 0x0e, 0xfb, 0xed, 0xc0, 0x09, 0x47, 0xfc, + 0x14, 0xf3, 0xf1, 0x4f, 0xd5, 0x42, 0xf6, 0xcc, 0xea, 0xbc, 0x53, 0x16, 0xbb, 0x2a, 0x54, 0x51, 0x67, 0x0a, 0x2a, + 0xf8, 0xad, 0x43, 0x04, 0x6d, 0xfb, 0x49, 0x92, 0x21, 0x12, 0x55, 0x81, 0xfa, 0x6c, 0x26, 0x92, 0x60, 0x2e, 0xc0, + 0x92, 0xe5, 0x0d, 0xe7, 0xbc, 0xf6, 0xb7, 0xae, 0x49, 0xe6, 0x0d, 0x70, 0xd1, 0x7c, 0xda, 0xe9, 0xe9, 0x3a, 0xf2, + 0xad, 0x87, 0xa9, 0x75, 0xa8, 0x05, 0xb3, 0x84, 0x8b, 0x59, 0xb9, 0x89, 0x7d, 0x79, 0x1b, 0xa8, 0x99, 0x1c, 0x84, + 0xca, 0x9f, 0x98, 0x9c, 0x52, 0x1b, 0xa9, 0x90, 0xb5, 0x87, 0xcc, 0x49, 0x07, 0x21, 0xdc, 0x86, 0xf4, 0xdb, 0xf9, + 0x65, 0x87, 0x4c, 0xf6, 0xa3, 0x2d, 0x0c, 0xe9, 0xff, 0x7a, 0x85, 0x49, 0x68, 0x30, 0x42, 0xb8, 0x9f, 0x04, 0x08, + 0xf7, 0xa2, 0x53, 0x16, 0xe1, 0xc2, 0x9d, 0x47, 0x61, 0xbf, 0x77, 0x36, 0x54, 0x86, 0x05, 0xe7, 0x07, 0xcd, 0xcf, + 0x71, 0x10, 0x8e, 0xf5, 0x9a, 0x3c, 0x30, 0x7e, 0xfc, 0x91, 0xbd, 0x40, 0xc0, 0x7c, 0x37, 0x11, 0xb4, 0xea, 0x14, + 0x28, 0x0b, 0xd6, 0x38, 0x18, 0x48, 0x0a, 0x16, 0xfb, 0x46, 0xaa, 0x7a, 0x9b, 0xb2, 0x2d, 0x9f, 0xe5, 0x49, 0xc7, + 0xe9, 0x5f, 0xd6, 0x7a, 0x9b, 0x10, 0x62, 0x5f, 0xf4, 0xb9, 0xf2, 0x01, 0x4a, 0xb4, 0xda, 0xe7, 0xff, 0x25, 0xb8, + 0xf5, 0xf5, 0xdf, 0x79, 0x35, 0xd3, 0x46, 0x8a, 0x59, 0x14, 0x5e, 0x7b, 0xa9, 0xac, 0x19, 0x9f, 0x90, 0xad, 0x66, + 0x4d, 0x36, 0x4e, 0x05, 0xc5, 0x4d, 0x5d, 0x0b, 0xb6, 0x98, 0x96, 0x6c, 0xde, 0x16, 0x93, 0x78, 0x63, 0x7e, 0x49, + 0xcb, 0xb1, 0x39, 0x17, 0xda, 0x8a, 0x41, 0xa3, 0x8e, 0x87, 0x8d, 0x9e, 0x13, 0x9d, 0x32, 0x5d, 0xaf, 0x1c, 0x37, + 0x55, 0xb5, 0xbf, 0x04, 0x0e, 0x9d, 0xda, 0x0a, 0x91, 0x56, 0xcb, 0x51, 0x43, 0x9e, 0x61, 0x59, 0x2b, 0x03, 0xe1, + 0x3a, 0x90, 0x76, 0xe7, 0xaf, 0xb3, 0xe4, 0x59, 0x70, 0xcb, 0x12, 0x8f, 0xf0, 0xa5, 0x66, 0x72, 0x8b, 0xe4, 0x15, + 0x93, 0x28, 0x0f, 0xe5, 0xc1, 0xee, 0xfc, 0x7c, 0xa2, 0xbd, 0x92, 0x2c, 0xe7, 0x33, 0xcd, 0x0b, 0x10, 0x42, 0xa6, + 0x6b, 0x09, 0x6d, 0xd9, 0x0b, 0xf6, 0xc4, 0xb8, 0x7a, 0x4a, 0x92, 0xf9, 0x25, 0x38, 0xf8, 0xeb, 0x7e, 0x9b, 0xa5, + 0x35, 0xf8, 0xdb, 0xbb, 0xc5, 0x4c, 0x6c, 0x2f, 0xb4, 0x19, 0xa9, 0x90, 0x7d, 0xff, 0xd7, 0x81, 0x78, 0x13, 0x98, + 0x1f, 0xea, 0xa8, 0x71, 0x74, 0x4f, 0x35, 0xfe, 0x2f, 0x1c, 0x36, 0x5a, 0x7a, 0xed, 0x68, 0xae, 0x91, 0x80, 0xc9, + 0x91, 0x7b, 0x55, 0xdf, 0x8b, 0x82, 0xbd, 0xe1, 0x81, 0x40, 0x59, 0xcd, 0xfe, 0x7e, 0xfd, 0x20, 0x00, 0x70, 0xa5, + 0x67, 0x1d, 0xaf, 0xe5, 0x67, 0xdb, 0x6d, 0x6c, 0xc0, 0xe5, 0x5a, 0xc1, 0x7f, 0x15, 0x47, 0xe8, 0xaf, 0xcd, 0x24, + 0x87, 0xed, 0xba, 0x1e, 0x0a, 0x3a, 0x64, 0xcc, 0x29, 0x06, 0x71, 0x3d, 0xf9, 0x92, 0xf5, 0x3a, 0x30, 0x6f, 0x82, + 0xda, 0xfc, 0x62, 0xef, 0xc5, 0x5e, 0x65, 0xd2, 0xa0, 0x29, 0x82, 0xff, 0x02, 0xf5, 0x01, 0xfe, 0xf4, 0x82, 0xb0, + 0x28, 0x7e, 0x50, 0x1c, 0xce, 0xb0, 0xc0, 0x66, 0x56, 0x1a, 0x5a, 0x07, 0xc6, 0x8f, 0x19, 0x3d, 0xf5, 0x09, 0xc6, + 0xa1, 0xc8, 0xd9, 0x39, 0x38, 0xc9, 0x51, 0xaa, 0x95, 0xfb, 0xfb, 0x4d, 0x9e, 0x84, 0x49, 0x4b, 0x3b, 0xf7, 0x27, + 0x68, 0x1f, 0xab, 0x3f, 0xff, 0xc7, 0xb1, 0x9b, 0x31, 0x2c, 0xa3, 0x76, 0x13, 0xbf, 0x3f, 0x81, 0x1b, 0x35, 0x4f, + 0xa9, 0xdb, 0xbd, 0x33, 0x7f, 0xd7, 0xb7, 0xf6, 0xf8, 0x69, 0xa0, 0x34, 0x86, 0xb1, 0x00, 0xb1, 0x98, 0xc6, 0x4b, + 0x63, 0x79, 0x07, 0x33, 0x37, 0x6c, 0xa3, 0x6f, 0x66, 0x7c, 0xeb, 0xe7, 0x0c, 0x41, 0x03, 0x62, 0xd4, 0x74, 0x69, + 0x45, 0xa5, 0xdf, 0xa5, 0xb8, 0xf3, 0x26, 0x14, 0x68, 0x9e, 0xfb, 0x1c, 0x0a, 0xa7, 0xa3, 0x48, 0x25, 0x25, 0xc0, + 0x3a, 0x59, 0x7e, 0xd6, 0x2e, 0xe2, 0xfd, 0x85, 0xd0, 0x25, 0xbc, 0xae, 0x53, 0xc4, 0xaf, 0xc5, 0x70, 0x33, 0x4d, + 0x37, 0x1b, 0xa8, 0x2f, 0xcb, 0x2e, 0x9d, 0x83, 0x23, 0xf8, 0x6a, 0x8d, 0x54, 0x44, 0xce, 0x50, 0x5f, 0x24, 0xd6, + 0x70, 0xe8, 0x23, 0x0e, 0xd6, 0xa5, 0xea, 0x80, 0x26, 0xdf, 0xac, 0x76, 0xd9, 0x69, 0xa3, 0x39, 0x4d, 0x4d, 0x31, + 0x83, 0x18, 0x0e, 0x3e, 0x89, 0xd0, 0xd9, 0xb4, 0x8f, 0x9b, 0xac, 0x89, 0x33, 0x34, 0x0d, 0xd7, 0x31, 0x5a, 0x55, + 0xc2, 0xac, 0xb2, 0x8d, 0xc7, 0x53, 0xda, 0x55, 0xeb, 0x9e, 0x08, 0x3b, 0xe7, 0xd2, 0x51, 0xab, 0x09, 0xda, 0x26, + 0x22, 0x85, 0xe2, 0xb0, 0xd5, 0x84, 0xbe, 0x3b, 0xac, 0x58, 0x61, 0xc5, 0xdb, 0x25, 0xf5, 0x3a, 0x66, 0x1c, 0xae, + 0x84, 0xc5, 0x1c, 0x60, 0xe0, 0x97, 0xb1, 0xf2, 0x81, 0x9a, 0xe4, 0x54, 0x7a, 0x48, 0x79, 0x97, 0x52, 0x9d, 0xcc, + 0x63, 0xff, 0xe2, 0xee, 0xf5, 0xa5, 0xf9, 0xe2, 0x6e, 0x32, 0xde, 0x42, 0x98, 0x3a, 0x6d, 0xa0, 0x2e, 0x6b, 0x3b, + 0x22, 0x74, 0xb9, 0x4f, 0xb4, 0x18, 0xef, 0x29, 0x74, 0x97, 0x93, 0xce, 0x09, 0xd5, 0x7f, 0x0a, 0x44, 0xf9, 0x88, + 0x32, 0xc8, 0xdd, 0x9d, 0x8a, 0x5d, 0xc9, 0xd3, 0x9d, 0x24, 0x3e, 0x56, 0xdf, 0x30, 0x32, 0x68, 0x6d, 0x9d, 0xa8, + 0xf6, 0x9d, 0xf5, 0x3e, 0x41, 0x8c, 0x75, 0x4b, 0x2c, 0xcb, 0xb7, 0xcb, 0x1d, 0xd2, 0x80, 0x38, 0xb7, 0x97, 0x61, + 0x5d, 0xce, 0xd1, 0x08, 0xf3, 0x65, 0x2c, 0x25, 0x24, 0x20, 0x92, 0x3e, 0x4e, 0x48, 0x97, 0xe2, 0xef, 0xba, 0xc3, + 0x65, 0x79, 0x12, 0xc2, 0x7c, 0xf4, 0x32, 0x66, 0x52, 0x97, 0xe0, 0x6b, 0xbc, 0xc9, 0x2f, 0x09, 0xb8, 0x24, 0x9a, + 0x5e, 0x5f, 0x71, 0xaa, 0x4b, 0xd5, 0xdb, 0x16, 0x14, 0xa7, 0xe9, 0x57, 0x2d, 0xc9, 0x2d, 0xf1, 0x99, 0xb1, 0x60, + 0x10, 0xa8, 0x43, 0x45, 0x2f, 0x03, 0x15, 0x63, 0x2c, 0x22, 0x4e, 0x97, 0x5f, 0x32, 0xa9, 0xae, 0x74, 0xa8, 0xda, + 0xb3, 0xf7, 0x17, 0x4f, 0x76, 0x78, 0x34, 0x7d, 0xfa, 0xe3, 0xeb, 0x41, 0x0f, 0xaa, 0xa0, 0x53, 0xb8, 0xdd, 0xd9, + 0xc0, 0x50, 0x28, 0x40, 0x56, 0x76, 0x2e, 0xcb, 0x00, 0xea, 0x4c, 0x4d, 0x49, 0x77, 0x7d, 0xdd, 0x9b, 0x44, 0x7a, + 0xd9, 0x30, 0xe3, 0xe7, 0xd0, 0x92, 0x9f, 0x4d, 0xf3, 0xcb, 0x1d, 0x6d, 0x63, 0x39, 0xe2, 0x29, 0xb0, 0xb1, 0x30, + 0x78, 0x0f, 0x29, 0x6e, 0xc2, 0x20, 0x43, 0x0e, 0x92, 0xbc, 0xd2, 0x96, 0xe5, 0xb9, 0x96, 0x92, 0x0d, 0x33, 0x7e, + 0x4f, 0x8a, 0x02, 0xe5, 0x77, 0x89, 0xb7, 0x71, 0x43, 0x00, 0x4e, 0x50, 0xda, 0x1c, 0x39, 0x56, 0x71, 0x2b, 0xbf, + 0x31, 0x78, 0x11, 0x81, 0x9e, 0x29, 0x1c, 0xe3, 0xf9, 0xc3, 0x7e, 0x1c, 0x21, 0x48, 0x05, 0x3f, 0xac, 0xd4, 0x66, + 0x47, 0x2f, 0xfd, 0xd7, 0xac, 0xa6, 0x47, 0x46, 0xba, 0xdb, 0x24, 0x6a, 0xcb, 0x4e, 0x54, 0x80, 0x19, 0x44, 0x63, + 0xe0, 0x82, 0x3b, 0xc6, 0x34, 0x1f, 0xfe, 0xdb, 0x4f, 0xac, 0x3d, 0xcc, 0xdf, 0xce, 0x78, 0xe5, 0xc9, 0x4b, 0x64, + 0x81, 0x9a, 0x8f, 0x5d, 0x5f, 0x5e, 0xc6, 0x77, 0xeb, 0x3e, 0x9e, 0xba, 0x05, 0x59, 0x40, 0x80, 0x81, 0xf8, 0x99, + 0x33, 0xd1, 0x1b, 0xc2, 0x9d, 0xd4, 0xc4, 0xd3, 0x5a, 0xcd, 0x6f, 0xf2, 0xf6, 0xda, 0x45, 0x0d, 0xc9, 0x5b, 0x67, + 0xed, 0x66, 0x55, 0x7a, 0x6c, 0x4d, 0xf2, 0xfd, 0x9a, 0x49, 0x96, 0xfa, 0x5f, 0xc3, 0xad, 0xb1, 0x7d, 0xbb, 0x0a, + 0xcb, 0x3a, 0xcc, 0x5f, 0x5e, 0x5f, 0x72, 0x1c, 0xe7, 0xbc, 0xf8, 0x8d, 0x35, 0xb6, 0xf0, 0xe6, 0x64, 0x4b, 0xc2, + 0x65, 0x6a, 0x35, 0xf7, 0xac, 0x56, 0xb5, 0x67, 0x49, 0xc8, 0xcd, 0x5e, 0xf6, 0x00, 0x9d, 0xbf, 0x37, 0xe9, 0x73, + 0xfc, 0x5e, 0x67, 0xcd, 0xe9, 0x7b, 0x83, 0x34, 0xd7, 0x9f, 0x22, 0xb2, 0x78, 0x66, 0x9d, 0x3c, 0xaa, 0xec, 0x15, + 0x93, 0x69, 0x3e, 0x26, 0xe4, 0x0a, 0x61, 0x58, 0x55, 0xbb, 0x3e, 0x3d, 0xa1, 0xe2, 0x86, 0x03, 0xc8, 0x6d, 0x7c, + 0x3e, 0xc8, 0x0d, 0xfe, 0x5e, 0xd9, 0x59, 0x0e, 0x3a, 0x0b, 0x6d, 0x7e, 0xec, 0xa1, 0xee, 0xc7, 0xe1, 0x61, 0x08, + 0xae, 0xcc, 0xde, 0x9c, 0xaa, 0x5f, 0x03, 0xd2, 0xea, 0x9c, 0xdb, 0xae, 0x20, 0x17, 0x7b, 0xfd, 0x4a, 0xb9, 0x37, + 0x0a, 0x44, 0x63, 0x43, 0x49, 0xea, 0x2c, 0xf2, 0xdd, 0x90, 0x3a, 0xb9, 0xdb, 0xce, 0xe8, 0x68, 0x7d, 0xe2, 0x23, + 0xfe, 0x54, 0x0d, 0x55, 0x98, 0xaf, 0xe7, 0x36, 0xcb, 0x7a, 0x80, 0xc6, 0x11, 0x69, 0x56, 0xd7, 0x9b, 0x92, 0x5e, + 0xad, 0x88, 0x4c, 0x68, 0x0c, 0xbe, 0xc9, 0xe0, 0x20, 0x1f, 0x57, 0x42, 0x2f, 0x92, 0x6e, 0xca, 0x27, 0xfb, 0x5f, + 0x45, 0x7b, 0x31, 0x07, 0x10, 0xfb, 0x16, 0x5d, 0x60, 0xb6, 0x56, 0x60, 0x8f, 0xd0, 0x1c, 0x2f, 0x11, 0xbd, 0xac, + 0x2c, 0x54, 0x5c, 0x58, 0x13, 0xd6, 0x7a, 0x9f, 0xb5, 0xc2, 0x69, 0xee, 0xfc, 0x53, 0x5d, 0x84, 0x50, 0xe2, 0x53, + 0x99, 0xd5, 0x80, 0x62, 0xa8, 0x81, 0x64, 0x3f, 0x39, 0xbf, 0xf2, 0x59, 0x64, 0x06, 0xe4, 0x6b, 0xb7, 0xe3, 0x83, + 0x3b, 0x1e, 0x8c, 0x3b, 0xbe, 0x6d, 0x3f, 0xb5, 0xd6, 0x9b, 0x49, 0x56, 0x4d, 0x33, 0x73, 0xde, 0x05, 0x86, 0x1d, + 0x0e, 0x2e, 0xcf, 0xce, 0xe7, 0x2e, 0x68, 0xda, 0x13, 0x96, 0xa9, 0x45, 0x73, 0x1b, 0xf0, 0xe4, 0x23, 0x7a, 0x4a, + 0x23, 0x39, 0xbb, 0xc3, 0x7b, 0x20, 0x77, 0x28, 0x7d, 0x6a, 0x25, 0x5f, 0xb0, 0x62, 0xc1, 0x79, 0xb3, 0x20, 0x16, + 0xcb, 0xa6, 0xea, 0x25, 0x48, 0x3a, 0xc4, 0xf9, 0x6c, 0x70, 0x9d, 0x4a, 0xa1, 0x1b, 0xfc, 0x7f, 0x89, 0x91, 0x1c, + 0xb6, 0xa2, 0x20, 0x98, 0x3a, 0x27, 0x41, 0x25, 0x62, 0xff, 0x46, 0x86, 0x0e, 0xfe, 0x0c, 0xaa, 0x94, 0x7d, 0x44, + 0x97, 0x3e, 0xbb, 0x37, 0xc1, 0x89, 0xd8, 0xee, 0x19, 0xe9, 0x7c, 0x48, 0x68, 0x7f, 0x7e, 0xfe, 0xcd, 0x65, 0x1f, + 0x19, 0x62, 0xbe, 0xae, 0xdd, 0x9b, 0xf7, 0x20, 0xd5, 0xb3, 0x3f, 0x47, 0x2c, 0x86, 0xb3, 0xcc, 0x84, 0xe7, 0x51, + 0x4c, 0xaf, 0xdd, 0x37, 0x78, 0x12, 0x48, 0x18, 0x43, 0xd0, 0x3e, 0x5c, 0xe1, 0x9b, 0xaf, 0x22, 0x26, 0x6b, 0x48, + 0xf8, 0xf8, 0xac, 0xf8, 0xad, 0xb3, 0x17, 0xb5, 0xb8, 0x61, 0x68, 0xa6, 0x8e, 0xd3, 0x3c, 0x6f, 0xc1, 0x7d, 0x9e, + 0xda, 0x73, 0xa2, 0xd2, 0x68, 0x9d, 0xe7, 0xeb, 0x37, 0x61, 0x56, 0x2d, 0xdd, 0xe6, 0xef, 0xc2, 0xd8, 0x56, 0xa8, + 0x22, 0xff, 0xbc, 0x8b, 0xb0, 0x1f, 0x71, 0x1a, 0x68, 0x24, 0xbf, 0x6a, 0x4b, 0xbe, 0xf2, 0x4e, 0xc2, 0x2c, 0xcc, + 0x4d, 0xac, 0x8b, 0x8d, 0x32, 0x3f, 0x8b, 0xc9, 0xcf, 0x54, 0xe4, 0x63, 0xe3, 0x8a, 0xae, 0xf6, 0x09, 0xf1, 0xf0, + 0x68, 0x7d, 0x18, 0x77, 0xcb, 0x62, 0x6d, 0x56, 0xe6, 0x8b, 0xb2, 0x2b, 0xb5, 0xcf, 0xd3, 0x17, 0xfc, 0x68, 0xb1, + 0x3e, 0xd8, 0xb9, 0x97, 0x08, 0xc8, 0xa0, 0x5a, 0x96, 0xb6, 0x43, 0xe4, 0xe1, 0xe5, 0x26, 0x2f, 0x79, 0x9b, 0x27, + 0x2a, 0x4a, 0xdb, 0x21, 0xf0, 0xdd, 0x7d, 0x9d, 0x1c, 0xd0, 0x25, 0xcc, 0xd3, 0x15, 0x40, 0x6b, 0xc0, 0x42, 0x6e, + 0x56, 0x27, 0xf6, 0x5c, 0x95, 0x6c, 0xda, 0xdb, 0x35, 0xf9, 0x73, 0x07, 0x94, 0x13, 0x6e, 0xec, 0xcb, 0xc8, 0xb0, + 0x5c, 0x95, 0x6e, 0x84, 0xcf, 0xfa, 0xc8, 0x9d, 0x67, 0x1f, 0xf0, 0xc3, 0x6f, 0xc9, 0x3d, 0xfa, 0xeb, 0x3c, 0x32, + 0x2d, 0xdf, 0x16, 0x34, 0x6a, 0x1c, 0xa2, 0xf1, 0x56, 0x12, 0x10, 0x15, 0x55, 0x03, 0x1e, 0x53, 0x7e, 0x16, 0x2c, + 0x8f, 0x64, 0x94, 0x1d, 0xf2, 0xa5, 0xb6, 0xfb, 0xb1, 0x35, 0xf1, 0xcf, 0xac, 0x43, 0xab, 0xac, 0x4f, 0x86, 0x2f, + 0xb5, 0xdd, 0xde, 0x7b, 0xa1, 0x80, 0x08, 0xb0, 0x87, 0xc1, 0xe7, 0xd8, 0x5a, 0x2d, 0xf8, 0xfc, 0xf8, 0xf9, 0x81, + 0x3b, 0x56, 0xcc, 0x79, 0xdf, 0xf5, 0x5d, 0x80, 0x92, 0xcc, 0x08, 0x03, 0x3b, 0x66, 0x37, 0xc6, 0x90, 0xc4, 0x49, + 0xa3, 0x71, 0x1f, 0xc4, 0x09, 0xbd, 0x35, 0xec, 0x00, 0x70, 0x89, 0x3c, 0x19, 0x2e, 0x53, 0x48, 0x97, 0xc8, 0x87, + 0xe9, 0x7b, 0x5c, 0x91, 0x45, 0x02, 0x7c, 0xc3, 0x6b, 0x25, 0xdb, 0x26, 0x58, 0x41, 0x8b, 0x62, 0x0e, 0x64, 0x3a, + 0x4b, 0x15, 0xdf, 0x30, 0xe2, 0x9c, 0x3f, 0x74, 0x9b, 0x37, 0x17, 0x33, 0x5e, 0x3f, 0x9f, 0xfa, 0xb4, 0x97, 0x09, + 0xed, 0x68, 0x4e, 0x33, 0x30, 0xa0, 0xe8, 0x57, 0xc5, 0xe6, 0x4f, 0xb0, 0x44, 0xc9, 0x3f, 0xda, 0xc8, 0xce, 0x9f, + 0x10, 0xfa, 0x88, 0x24, 0x60, 0xa2, 0xb1, 0xfd, 0x74, 0x4e, 0xd1, 0xdb, 0xaa, 0x86, 0xae, 0x08, 0x0b, 0xef, 0x83, + 0x1d, 0x5b, 0xb8, 0x36, 0x43, 0xd1, 0x38, 0xa2, 0x1e, 0x98, 0xf7, 0x65, 0xc7, 0x69, 0xbe, 0x6f, 0x6c, 0x10, 0xa4, + 0x3e, 0x6f, 0x45, 0x26, 0x07, 0x24, 0x25, 0x36, 0xb0, 0xf0, 0xb8, 0x79, 0xba, 0xac, 0x4b, 0xbe, 0x77, 0x59, 0x9d, + 0xba, 0xa2, 0xb1, 0x85, 0x12, 0x67, 0x2c, 0x1a, 0x8c, 0x29, 0x11, 0x49, 0xe6, 0x42, 0xb0, 0x46, 0xc3, 0xdf, 0x7c, + 0x22, 0x68, 0x3e, 0xe1, 0xb1, 0xf7, 0x09, 0x77, 0x32, 0x99, 0xde, 0x50, 0x13, 0x65, 0x3b, 0x7a, 0xf7, 0xf3, 0x81, + 0xd2, 0x4e, 0x73, 0x3e, 0x96, 0x31, 0x73, 0xc9, 0x02, 0x94, 0x99, 0x08, 0x11, 0x90, 0x43, 0x8f, 0x3b, 0xc9, 0x22, + 0x41, 0xaf, 0xf1, 0x15, 0x26, 0x52, 0xd3, 0x91, 0xd9, 0xeb, 0x6a, 0x22, 0x1a, 0x8f, 0x1c, 0x29, 0xf0, 0x62, 0xbc, + 0xc9, 0xa8, 0x4b, 0xb1, 0x5a, 0xbc, 0x61, 0x92, 0x29, 0x7e, 0xf2, 0xd7, 0xf6, 0x27, 0x27, 0xe4, 0xbd, 0x9e, 0x5a, + 0xa1, 0xdf, 0xf3, 0xc6, 0xd6, 0xa5, 0xa0, 0xdd, 0xff, 0x6c, 0xc9, 0x28, 0xda, 0x98, 0x56, 0xcf, 0xe2, 0x4b, 0xfd, + 0xa2, 0x97, 0xc8, 0xe5, 0x4d, 0x1e, 0xdb, 0x87, 0x11, 0xa3, 0xd0, 0x5a, 0x85, 0xd9, 0x7b, 0x8f, 0x62, 0x63, 0xef, + 0xb5, 0x42, 0x34, 0xce, 0x21, 0xba, 0x84, 0xcb, 0x8d, 0x97, 0xc8, 0x24, 0x3e, 0x39, 0xe3, 0x2c, 0xf3, 0x6f, 0xa9, + 0x48, 0x58, 0xce, 0x32, 0x8f, 0xd1, 0xc3, 0xde, 0x54, 0x25, 0x9b, 0x02, 0x4e, 0x51, 0xd6, 0x8a, 0xb8, 0x99, 0xce, + 0x77, 0xad, 0x40, 0x6b, 0xe2, 0x67, 0x30, 0x8a, 0xc9, 0x6a, 0xf2, 0xe6, 0xd5, 0x7f, 0x73, 0xe2, 0x5f, 0x54, 0x33, + 0xfe, 0x50, 0xc6, 0xf8, 0x97, 0x8b, 0x75, 0x58, 0xf9, 0x7d, 0x73, 0x28, 0x09, 0x70, 0x8d, 0x93, 0x4a, 0x7c, 0xad, + 0x70, 0x8e, 0x00, 0xfa, 0xae, 0xbb, 0x24, 0xd4, 0x0b, 0x8e, 0x06, 0x1d, 0x16, 0x23, 0x58, 0x1c, 0x13, 0x7d, 0x74, + 0xff, 0x77, 0xc5, 0x00, 0x2d, 0x46, 0x23, 0xd7, 0x5f, 0xcf, 0xc5, 0xb1, 0x22, 0xc9, 0x26, 0x57, 0x58, 0x88, 0x11, + 0x02, 0x08, 0xb9, 0x48, 0x02, 0x1d, 0xe7, 0x07, 0x9f, 0x8a, 0x17, 0x8d, 0x48, 0x01, 0x68, 0x48, 0xfb, 0x6b, 0x80, + 0xc0, 0x21, 0x98, 0x23, 0x41, 0x30, 0x92, 0x67, 0x01, 0x91, 0x13, 0xb2, 0x77, 0xa2, 0x42, 0x84, 0x59, 0x1d, 0xec, + 0x7a, 0x83, 0xba, 0x80, 0x2d, 0x9a, 0xe7, 0x48, 0x50, 0x54, 0x21, 0x22, 0x2c, 0x2b, 0x36, 0x57, 0xaf, 0xd6, 0xbc, + 0x47, 0x85, 0x17, 0x85, 0x2e, 0x99, 0x3e, 0xcd, 0x2e, 0xa1, 0xcc, 0x2f, 0xc0, 0xbf, 0x16, 0x75, 0x60, 0xcf, 0xbb, + 0x0e, 0x1d, 0x5b, 0x71, 0x72, 0x2a, 0x2e, 0x7f, 0xce, 0x39, 0x00, 0x4a, 0x7a, 0xd6, 0x21, 0x86, 0x06, 0x9d, 0xeb, + 0x96, 0x6b, 0xd2, 0x00, 0x0c, 0x97, 0x8c, 0x57, 0x86, 0xda, 0xd6, 0xb3, 0xeb, 0x17, 0x7f, 0x46, 0x66, 0x8e, 0x0e, + 0x4d, 0xbc, 0x88, 0x12, 0x77, 0x59, 0x5c, 0x02, 0x15, 0xaf, 0xf3, 0x51, 0xad, 0x6b, 0xe5, 0x95, 0xed, 0x1a, 0x87, + 0x0b, 0x1a, 0x82, 0x2d, 0xbc, 0x6a, 0xc0, 0x75, 0xb8, 0xac, 0x8b, 0xc0, 0x8f, 0x9e, 0x16, 0x05, 0xca, 0xdb, 0xb5, + 0x20, 0x0d, 0x3d, 0xd9, 0x89, 0xca, 0xa7, 0x69, 0xe9, 0xef, 0xcd, 0x7a, 0xf9, 0x8e, 0x16, 0x53, 0x8e, 0x43, 0x85, + 0x3f, 0x03, 0xc2, 0xa6, 0xb8, 0x1b, 0x14, 0x0d, 0xe5, 0xc5, 0x0d, 0x84, 0x72, 0x3a, 0x3b, 0x7c, 0xdb, 0x69, 0x56, + 0x11, 0xc4, 0xbc, 0x1f, 0xfd, 0xa7, 0x5c, 0x56, 0x60, 0xe9, 0x74, 0xec, 0x71, 0x93, 0x39, 0x47, 0x79, 0xde, 0xf6, + 0x8d, 0xd4, 0xa9, 0x45, 0x48, 0x55, 0xbc, 0x5a, 0xf4, 0x55, 0xba, 0xf7, 0x69, 0x83, 0x99, 0xb7, 0x59, 0xb1, 0x07, + 0xd9, 0x8a, 0x8d, 0x68, 0x96, 0xbc, 0xee, 0x31, 0x25, 0xd5, 0x47, 0x4c, 0x1c, 0xa0, 0x5b, 0xde, 0x2f, 0x1e, 0xc3, + 0x54, 0xaf, 0x30, 0x62, 0xb5, 0xd9, 0x5f, 0x00, 0x73, 0x6f, 0xdc, 0xcf, 0x35, 0x7b, 0xe6, 0x53, 0x29, 0xa4, 0x58, + 0x85, 0xf0, 0xba, 0x2a, 0x33, 0x38, 0xf9, 0x14, 0x82, 0x21, 0x7f, 0xf9, 0x31, 0xf3, 0xeb, 0x55, 0xf7, 0x87, 0x19, + 0xcf, 0xea, 0x7b, 0x3a, 0x60, 0x6f, 0xa8, 0x0d, 0xaf, 0x7b, 0x0a, 0x71, 0x45, 0x98, 0xdd, 0xb3, 0x53, 0x60, 0xcd, + 0x64, 0x70, 0xdf, 0xb1, 0x29, 0xea, 0x09, 0xfc, 0x28, 0x9c, 0x37, 0x0b, 0xe6, 0x6f, 0x79, 0xc5, 0x68, 0xde, 0x4c, + 0x91, 0x74, 0xe1, 0xc1, 0x88, 0x4f, 0x19, 0x97, 0x28, 0x5b, 0xfa, 0x90, 0x7e, 0x87, 0x78, 0x23, 0xc7, 0x9b, 0xb5, + 0xf4, 0x8d, 0xe2, 0xb0, 0xd5, 0x64, 0x1b, 0x12, 0xa6, 0x00, 0x68, 0x91, 0xf3, 0x11, 0x30, 0x5d, 0xaf, 0xd9, 0x8a, + 0xb2, 0x0d, 0x61, 0x91, 0x86, 0x86, 0x50, 0x34, 0xac, 0x17, 0x4c, 0x4d, 0x8a, 0xbb, 0x43, 0x23, 0x26, 0xc6, 0x73, + 0xc6, 0xf2, 0x0b, 0xf2, 0xd3, 0xa2, 0x4c, 0x5b, 0x63, 0x2f, 0xae, 0xcc, 0x0a, 0x26, 0x1e, 0x34, 0x13, 0x20, 0x09, + 0xe0, 0xd5, 0x2a, 0xea, 0x8c, 0xf3, 0x54, 0x62, 0x73, 0x7f, 0xe3, 0x09, 0x19, 0x20, 0xd0, 0x29, 0x69, 0xa2, 0xa3, + 0xab, 0xf5, 0x41, 0x8a, 0xbd, 0x00, 0x94, 0x9d, 0xb0, 0xc1, 0x32, 0x86, 0x06, 0x58, 0xd7, 0x66, 0x73, 0x8a, 0x6b, + 0xd9, 0x53, 0x27, 0xb3, 0x36, 0xf2, 0x34, 0x7f, 0xb8, 0xb4, 0x30, 0x22, 0xc6, 0x45, 0xcd, 0x27, 0xe2, 0xab, 0x29, + 0x46, 0xa0, 0xf5, 0x04, 0xe4, 0xf5, 0x70, 0xca, 0xdb, 0x75, 0x8d, 0x71, 0xe9, 0x9a, 0x64, 0xf2, 0xa2, 0xc0, 0xa9, + 0x2f, 0x93, 0x7f, 0x19, 0x7f, 0x02, 0x9b, 0x78, 0x4e, 0x27, 0x3e, 0x4e, 0xb6, 0x3a, 0x51, 0x54, 0x40, 0x54, 0x8b, + 0xf0, 0x4a, 0x7a, 0x11, 0x92, 0x9a, 0xf1, 0x32, 0x10, 0xea, 0x78, 0xa3, 0x01, 0xc9, 0xfb, 0xba, 0x12, 0x5e, 0x5b, + 0xbe, 0x5c, 0x84, 0xbc, 0xd9, 0x0e, 0x6b, 0x77, 0x3e, 0x9d, 0x6e, 0x6f, 0x56, 0xc8, 0x0d, 0x50, 0x3a, 0x19, 0xae, + 0x82, 0xbe, 0xa1, 0xd9, 0x91, 0x3c, 0xa1, 0x23, 0x5f, 0x66, 0x65, 0x4c, 0xc2, 0xe2, 0x74, 0x43, 0x8e, 0x4a, 0x5e, + 0x29, 0xed, 0x2e, 0x64, 0x4f, 0x71, 0xaa, 0x3b, 0x58, 0x0f, 0x44, 0xe5, 0x10, 0x53, 0x6a, 0x14, 0x9e, 0xc4, 0xad, + 0x1c, 0x59, 0xfb, 0xb0, 0x4e, 0x2e, 0xbc, 0x8a, 0x33, 0x1d, 0xd2, 0xb6, 0xb5, 0xb9, 0xdb, 0x6c, 0x54, 0xa4, 0xcb, + 0x12, 0x69, 0xef, 0xed, 0xfa, 0x65, 0xd5, 0xa3, 0x49, 0x8a, 0xd2, 0xf7, 0x25, 0x8e, 0x2f, 0xeb, 0xa8, 0x7b, 0x3b, + 0x89, 0x25, 0x7c, 0x64, 0x99, 0x38, 0x05, 0x77, 0xc0, 0x58, 0x65, 0x27, 0xa2, 0x16, 0x48, 0xea, 0xbf, 0xf4, 0xb2, + 0x9e, 0x82, 0x14, 0xef, 0x96, 0xf5, 0x7a, 0x86, 0xc4, 0x7c, 0xc9, 0x18, 0xad, 0xc1, 0x00, 0x55, 0xd0, 0xf3, 0xd5, + 0x73, 0x40, 0xe0, 0x99, 0x4d, 0x2f, 0xbf, 0x13, 0x45, 0x9c, 0xdd, 0x65, 0x85, 0x26, 0x5a, 0x3c, 0xcb, 0x1e, 0x16, + 0xd8, 0x57, 0x0a, 0xf2, 0xec, 0xea, 0x25, 0x85, 0x96, 0x4d, 0x18, 0xf3, 0x1b, 0xa6, 0xbe, 0x02, 0xfb, 0xf2, 0x5a, + 0x99, 0x74, 0x56, 0x77, 0xb5, 0xc6, 0x02, 0xcf, 0x8b, 0x2a, 0x48, 0xa2, 0xde, 0x86, 0x99, 0x95, 0x89, 0x53, 0x3e, + 0xaa, 0x0a, 0x96, 0xb3, 0xf3, 0xdd, 0x94, 0xd0, 0xe8, 0xd1, 0x7f, 0xd5, 0x35, 0x09, 0xaa, 0xf4, 0xc8, 0x8c, 0x63, + 0x70, 0x11, 0x2d, 0xf4, 0xb3, 0x76, 0x5d, 0x54, 0x74, 0x7e, 0xcd, 0x62, 0x5a, 0x5f, 0x97, 0x92, 0x36, 0x3a, 0x2b, + 0xa4, 0xc4, 0xa2, 0x31, 0xcf, 0x2a, 0x64, 0xfb, 0xbd, 0xab, 0xad, 0xd5, 0x06, 0xc2, 0x4d, 0x26, 0x25, 0x48, 0x4a, + 0xc2, 0x3f, 0x94, 0x67, 0x5b, 0x46, 0x34, 0x2a, 0xad, 0x91, 0x2e, 0xaa, 0xd6, 0x9c, 0xb7, 0xa2, 0x30, 0x7f, 0xc2, + 0xe2, 0xbc, 0x46, 0xde, 0x08, 0x85, 0x00, 0xe1, 0x22, 0xfc, 0x39, 0x80, 0xfb, 0x3b, 0x96, 0x15, 0x0f, 0xab, 0xe9, + 0x29, 0xaf, 0xd4, 0x36, 0x8e, 0xc0, 0x01, 0x79, 0x8b, 0x93, 0xc1, 0x05, 0x92, 0x11, 0x26, 0x7e, 0x85, 0x68, 0x83, + 0xa5, 0x62, 0x52, 0x5a, 0x7c, 0xae, 0x6c, 0x42, 0xa7, 0x4f, 0xcb, 0x8a, 0xb9, 0xfa, 0x80, 0x3e, 0x5b, 0x55, 0x76, + 0xbe, 0x76, 0x0c, 0x43, 0x7e, 0x32, 0x5b, 0xe4, 0x49, 0xc9, 0xef, 0xc0, 0x98, 0x96, 0x37, 0x49, 0x6e, 0x53, 0x0d, + 0xfa, 0x58, 0x55, 0xf8, 0xea, 0x3d, 0xe7, 0x22, 0x3e, 0x98, 0xab, 0x11, 0xe9, 0x57, 0x83, 0xa9, 0x7f, 0xad, 0xdf, + 0xa7, 0x92, 0xe8, 0xd8, 0xe9, 0xba, 0xd0, 0xbc, 0x83, 0x4b, 0x2a, 0x2a, 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0x94, + 0x91, 0xda, 0xd7, 0x12, 0x59, 0x9b, 0x95, 0x3b, 0xd9, 0x7e, 0xb4, 0x9a, 0xcd, 0x30, 0xe5, 0xa5, 0xf5, 0xae, 0xac, + 0x2b, 0x3f, 0xe8, 0xca, 0x0e, 0xe9, 0x83, 0x7a, 0x22, 0x97, 0x4d, 0xe1, 0xe7, 0x5b, 0x9b, 0x03, 0x94, 0xfa, 0x5f, + 0x68, 0x5c, 0x86, 0xb3, 0x81, 0x4d, 0xe8, 0xea, 0x40, 0x7c, 0x50, 0xe6, 0x92, 0x6c, 0x5f, 0xf0, 0x84, 0xba, 0xee, + 0x82, 0x79, 0xd6, 0x15, 0x8b, 0xa2, 0xff, 0xf8, 0x9e, 0x85, 0xf7, 0xf4, 0xc9, 0xb0, 0xf2, 0x80, 0x7a, 0x79, 0xac, + 0xe5, 0xb2, 0x0e, 0x4c, 0x56, 0x12, 0x53, 0x4d, 0x58, 0xd5, 0x2d, 0xcd, 0x61, 0xeb, 0x8c, 0xe6, 0x34, 0xdd, 0x24, + 0xdf, 0x1f, 0x28, 0x9c, 0x44, 0x86, 0xbf, 0x5a, 0xdb, 0x81, 0x81, 0x06, 0x89, 0xea, 0x02, 0x54, 0x4a, 0xdc, 0x2f, + 0x54, 0x6b, 0x52, 0x95, 0x65, 0x07, 0x0a, 0x4b, 0xbe, 0x51, 0xd5, 0x2d, 0xbf, 0x5d, 0x94, 0xa8, 0x60, 0x94, 0xff, + 0xa9, 0x75, 0x59, 0x40, 0xb4, 0x1d, 0x5c, 0xeb, 0xb1, 0x57, 0x3e, 0xed, 0x62, 0x38, 0xde, 0x61, 0x57, 0xbf, 0xd3, + 0xea, 0x1c, 0xd5, 0x85, 0xa5, 0xc4, 0xb9, 0x57, 0xc8, 0x73, 0xb6, 0xb3, 0x9f, 0xf3, 0xf6, 0xa2, 0x83, 0x32, 0x7e, + 0xb9, 0x35, 0xcc, 0x6c, 0x16, 0xae, 0x8a, 0x80, 0x19, 0x7d, 0x75, 0x25, 0x00, 0xb0, 0x80, 0x29, 0x61, 0x61, 0xc4, + 0x8e, 0xa3, 0x3c, 0x73, 0x4c, 0x65, 0x9f, 0x7b, 0x46, 0xd7, 0x37, 0x27, 0xee, 0x91, 0xcb, 0x1d, 0xb4, 0x5a, 0x89, + 0xe3, 0x64, 0x61, 0x2d, 0x5f, 0x74, 0x05, 0xa6, 0x09, 0x49, 0x97, 0x5f, 0xcd, 0x81, 0x54, 0xad, 0xee, 0xc4, 0x3c, + 0x67, 0x13, 0x40, 0x6f, 0xdf, 0x35, 0x01, 0x8f, 0xc9, 0xf1, 0xcd, 0xe8, 0xde, 0x02, 0x33, 0xd2, 0xf5, 0x85, 0xd0, + 0x77, 0x2b, 0x99, 0xaf, 0x5b, 0xa3, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xe3, 0x12, 0xdb, 0xd0, 0xd2, 0x5d, 0x2f, + 0x82, 0x18, 0x08, 0x44, 0x72, 0x63, 0x14, 0x78, 0x7f, 0x76, 0xae, 0x7b, 0x31, 0x64, 0x29, 0x68, 0x46, 0x0f, 0x5e, + 0xb0, 0x5d, 0x26, 0x24, 0x13, 0xf9, 0x0e, 0x0d, 0x81, 0x95, 0xb9, 0x13, 0xfd, 0x08, 0xf0, 0xaa, 0xb8, 0xb5, 0xdf, + 0x27, 0xfa, 0xbd, 0xea, 0x43, 0x71, 0xe9, 0xb5, 0x82, 0xca, 0x6a, 0x24, 0xde, 0x0c, 0x3a, 0xe0, 0xd1, 0xe5, 0xa7, + 0x4a, 0x8c, 0x66, 0x10, 0x3c, 0x40, 0x14, 0x11, 0x65, 0xf6, 0x95, 0xdc, 0x16, 0x77, 0x87, 0x53, 0x40, 0x20, 0x63, + 0xd6, 0x65, 0x17, 0xc3, 0x44, 0x60, 0x89, 0xf9, 0x66, 0x7c, 0x31, 0x82, 0x1f, 0xdb, 0x7d, 0x54, 0xce, 0x45, 0xb9, + 0x06, 0x63, 0x1b, 0xf3, 0x99, 0x15, 0x7b, 0x82, 0x6f, 0x34, 0xd2, 0xd1, 0xcb, 0x18, 0xca, 0x25, 0xca, 0xc1, 0x4a, + 0xf7, 0x09, 0xf4, 0x60, 0x45, 0x15, 0x20, 0xce, 0x6e, 0x9c, 0x71, 0x6a, 0xc0, 0x2c, 0xb9, 0x21, 0x2d, 0x68, 0x72, + 0xea, 0xf0, 0x6b, 0x3a, 0x7a, 0x0e, 0x30, 0x29, 0xee, 0xc9, 0xcb, 0xe1, 0xd4, 0xb4, 0xd6, 0xd3, 0x5a, 0x7f, 0x03, + 0x0d, 0xb1, 0xa0, 0x2d, 0x6a, 0x67, 0x6f, 0xc0, 0xcc, 0x17, 0x6c, 0x1b, 0x6a, 0x8d, 0x3f, 0xec, 0x87, 0x16, 0x76, + 0x92, 0xe1, 0x34, 0x88, 0x24, 0xce, 0xc1, 0x34, 0x0a, 0xf1, 0x87, 0x56, 0x97, 0x15, 0xab, 0xf2, 0xc4, 0x6f, 0xdd, + 0x5f, 0x2b, 0xa5, 0xd1, 0xe7, 0x9f, 0xc5, 0xc2, 0x19, 0x99, 0xd8, 0xaf, 0xf6, 0xc2, 0xc2, 0xa2, 0xb2, 0x03, 0x57, + 0x35, 0x1a, 0x9e, 0x25, 0x2f, 0x85, 0xa7, 0x1c, 0x56, 0x68, 0x99, 0x09, 0x3f, 0x8f, 0xf3, 0x6a, 0xec, 0xcd, 0xa8, + 0x46, 0xb5, 0x62, 0x0a, 0xea, 0xf4, 0xe8, 0x40, 0xb8, 0x4c, 0x01, 0x56, 0xd9, 0x02, 0xd4, 0x9f, 0x5f, 0xe7, 0x1e, + 0x7d, 0x1a, 0x06, 0x2f, 0xca, 0x31, 0xd6, 0x20, 0xe8, 0x1d, 0x44, 0x21, 0x46, 0x47, 0xd2, 0x37, 0x29, 0xbd, 0xf9, + 0x23, 0x8f, 0xf1, 0x0d, 0xf1, 0x77, 0xc1, 0xce, 0xb7, 0xdc, 0xe7, 0xce, 0xe2, 0x35, 0x66, 0xcd, 0x75, 0xb4, 0x0e, + 0x43, 0xdd, 0x25, 0x30, 0x0d, 0x41, 0xc3, 0x44, 0x13, 0x04, 0x63, 0xc9, 0x73, 0xba, 0x36, 0x9a, 0xa0, 0xf4, 0x42, + 0x12, 0xfc, 0xbf, 0x4a, 0x78, 0x39, 0xa7, 0x72, 0x3a, 0x8a, 0x5a, 0xf0, 0x10, 0x5c, 0x55, 0x43, 0x2d, 0x50, 0x27, + 0x0f, 0x4f, 0xa1, 0x25, 0x63, 0x05, 0x9e, 0x63, 0x9f, 0x9b, 0x34, 0xc0, 0x78, 0x24, 0xf3, 0xb0, 0x61, 0xc2, 0x15, + 0x7a, 0xb6, 0x98, 0x33, 0x3b, 0xe6, 0x6d, 0x85, 0x91, 0xbd, 0x19, 0x97, 0x78, 0xf6, 0x3a, 0x16, 0xb3, 0xed, 0x71, + 0x68, 0x31, 0x37, 0x0f, 0x1c, 0xb5, 0x58, 0x9b, 0x08, 0x0a, 0x7d, 0x03, 0x5b, 0x80, 0xc1, 0x4e, 0xce, 0xaa, 0x51, + 0x42, 0xb2, 0xe6, 0x16, 0x40, 0x9e, 0xe9, 0x28, 0x84, 0x54, 0x36, 0xfc, 0xc4, 0x5a, 0xf2, 0x77, 0x60, 0xe7, 0xfc, + 0xcd, 0xc3, 0x40, 0x88, 0xda, 0x46, 0x68, 0x02, 0xfa, 0xea, 0xb5, 0x96, 0x10, 0x20, 0x0c, 0x82, 0x2b, 0xfa, 0xcb, + 0x9e, 0x84, 0x6e, 0x2e, 0xaf, 0xcb, 0x7b, 0x42, 0xd4, 0x75, 0xb0, 0x1e, 0x91, 0xf1, 0xdc, 0x15, 0xfe, 0xab, 0xde, + 0x0f, 0x12, 0x25, 0x14, 0x4b, 0x45, 0xf2, 0x23, 0xaa, 0x23, 0xc6, 0x11, 0xda, 0xd1, 0x49, 0x3e, 0x76, 0x85, 0x81, + 0x38, 0x54, 0x5b, 0x66, 0x7a, 0x7e, 0xc4, 0x56, 0x33, 0xf6, 0x28, 0xb8, 0x9e, 0x2c, 0x35, 0xbc, 0x40, 0x94, 0xae, + 0x7f, 0x04, 0x34, 0x93, 0xff, 0x98, 0xd9, 0xe6, 0xa9, 0xd9, 0x47, 0x45, 0xdf, 0x64, 0x76, 0x8e, 0x2c, 0x38, 0x8a, + 0xc2, 0x2b, 0x21, 0xf0, 0x52, 0x47, 0x3c, 0x35, 0x52, 0xc4, 0x3c, 0x64, 0x9a, 0x82, 0x5c, 0x0f, 0xe8, 0x0b, 0x4d, + 0x8e, 0xaa, 0x2e, 0xc7, 0xf4, 0x40, 0x81, 0x58, 0x1d, 0xdb, 0x11, 0xe2, 0xe2, 0x36, 0x11, 0xc3, 0x69, 0xd5, 0x65, + 0x0f, 0x49, 0xad, 0xf3, 0x74, 0xcc, 0x14, 0xe4, 0xc0, 0x4d, 0x58, 0xfd, 0xce, 0x71, 0x68, 0x17, 0x05, 0xb7, 0x6f, + 0xa9, 0x44, 0xb2, 0x51, 0xa6, 0xfb, 0x32, 0xfc, 0x20, 0x9a, 0x45, 0x03, 0xc8, 0x06, 0x7c, 0xa5, 0x3f, 0x8c, 0xa2, + 0xeb, 0x3b, 0xbf, 0xcc, 0x9a, 0x29, 0x5b, 0xbf, 0xdb, 0x30, 0xdb, 0x3a, 0x1e, 0x28, 0xb4, 0xa6, 0x85, 0x46, 0x9b, + 0xfa, 0xac, 0xf0, 0xad, 0x75, 0x02, 0x31, 0x39, 0xb9, 0xd9, 0xc8, 0x63, 0xb0, 0x8e, 0xb0, 0xee, 0x31, 0x36, 0x27, + 0xf1, 0x2f, 0xb5, 0x99, 0x0b, 0xc2, 0x33, 0x2b, 0x59, 0xf0, 0x0f, 0xba, 0x19, 0x6c, 0x39, 0x6f, 0xc2, 0xbf, 0xb1, + 0xa6, 0x09, 0x93, 0x35, 0x69, 0x05, 0xe5, 0x90, 0xd4, 0x6e, 0x68, 0xb4, 0x4e, 0x5e, 0xb6, 0x28, 0x10, 0x52, 0x13, + 0xcf, 0x45, 0x75, 0x27, 0xa3, 0xa5, 0x17, 0xe9, 0xc6, 0xde, 0x37, 0x3f, 0x87, 0xcf, 0xb4, 0xc2, 0x8b, 0x15, 0xc2, + 0x80, 0xfe, 0x64, 0x58, 0xdf, 0xab, 0xa4, 0xdd, 0x57, 0xed, 0x64, 0xd1, 0xda, 0x98, 0xaf, 0x02, 0x26, 0xd6, 0x3d, + 0xc5, 0xbc, 0x5c, 0x9d, 0xf4, 0xf7, 0xae, 0xc5, 0x16, 0xc6, 0x23, 0x99, 0x47, 0x72, 0x4a, 0xf8, 0x63, 0x40, 0xe3, + 0xdf, 0x50, 0x46, 0x0d, 0x0c, 0x34, 0x58, 0x3d, 0x1a, 0xca, 0x75, 0x00, 0x0e, 0x31, 0x34, 0x11, 0xc9, 0x40, 0x3b, + 0x81, 0x3b, 0x9a, 0x09, 0x52, 0x4f, 0x5b, 0x82, 0x4d, 0x3c, 0x47, 0x37, 0x31, 0x39, 0x19, 0xbb, 0x00, 0x57, 0xe0, + 0x96, 0xf5, 0x0c, 0xdb, 0x6e, 0xb3, 0x5d, 0x84, 0x94, 0x9a, 0x0a, 0xb6, 0xf0, 0x58, 0x6b, 0x02, 0x78, 0x4a, 0x35, + 0xd1, 0xa2, 0x21, 0xd5, 0x97, 0x4e, 0xc0, 0x7e, 0x71, 0xd2, 0x98, 0x5b, 0xd3, 0x58, 0x59, 0x3e, 0x0d, 0xbc, 0xd4, + 0x64, 0x4d, 0xac, 0xd0, 0x67, 0x9c, 0x72, 0x04, 0xe2, 0x1d, 0x7e, 0x73, 0x79, 0x33, 0x49, 0x6f, 0x0b, 0xfd, 0xd8, + 0x64, 0x80, 0x61, 0xe4, 0x1c, 0xe1, 0x17, 0x33, 0xec, 0x6c, 0xc3, 0xf9, 0xe7, 0x04, 0xc9, 0x78, 0x51, 0xf8, 0x57, + 0xe3, 0x05, 0xe9, 0xa8, 0x26, 0x21, 0xfe, 0x81, 0xe8, 0xd7, 0x0b, 0xce, 0xa0, 0x81, 0x36, 0xfb, 0x72, 0x59, 0xb3, + 0xb0, 0x2a, 0x68, 0xb4, 0xcf, 0xcd, 0x57, 0xb3, 0xe5, 0xdb, 0xeb, 0x7f, 0x94, 0xeb, 0x9e, 0x73, 0x1c, 0xb9, 0xd7, + 0x1c, 0x97, 0xbd, 0x2c, 0xf9, 0x41, 0x4b, 0xeb, 0x9d, 0x72, 0xda, 0xca, 0x45, 0x57, 0x50, 0xc2, 0x3f, 0xf6, 0x4f, + 0x8a, 0x64, 0xe7, 0x11, 0x2c, 0x89, 0x72, 0xb9, 0xe6, 0xe2, 0x8d, 0xd5, 0xbd, 0xbd, 0x13, 0x2c, 0x0c, 0x6e, 0xfc, + 0x82, 0x3c, 0x41, 0x92, 0xf2, 0x43, 0xf9, 0x5d, 0x0a, 0x71, 0xb6, 0x9d, 0xd5, 0x75, 0xb4, 0x8a, 0x78, 0xec, 0x5d, + 0x0e, 0x17, 0x76, 0x88, 0xd2, 0xe5, 0x83, 0x8b, 0xab, 0x59, 0x6b, 0x99, 0x2a, 0x93, 0x74, 0xc6, 0x33, 0x16, 0x70, + 0x9c, 0xc9, 0x32, 0x44, 0xd0, 0x33, 0x48, 0xc4, 0xe8, 0x7b, 0x17, 0x2c, 0x46, 0xc3, 0xd6, 0xea, 0xdb, 0x44, 0xd0, + 0x16, 0x14, 0xcd, 0x22, 0x7a, 0x31, 0x32, 0x15, 0x5e, 0x67, 0x13, 0x5a, 0xae, 0x64, 0x5e, 0x42, 0xab, 0x21, 0x6b, + 0x58, 0x94, 0xfb, 0x34, 0xf1, 0x83, 0x79, 0x3e, 0xb7, 0x50, 0x5b, 0x19, 0xab, 0x9f, 0x70, 0x66, 0xa9, 0x73, 0x41, + 0xb3, 0x5f, 0xd3, 0x5c, 0x81, 0xe7, 0xc9, 0xe6, 0xcb, 0x6f, 0xc4, 0xfa, 0x78, 0xca, 0xcf, 0xa0, 0xca, 0xdb, 0x84, + 0x25, 0xec, 0xcf, 0xa9, 0x52, 0x3c, 0xb2, 0xe1, 0x96, 0x55, 0x4b, 0x51, 0x1d, 0x8b, 0x24, 0x8a, 0x8c, 0x9d, 0x0c, + 0x67, 0xe8, 0x85, 0xc4, 0xb3, 0x59, 0x83, 0x09, 0x93, 0xf3, 0x2c, 0xde, 0x29, 0xcc, 0x95, 0x48, 0x12, 0x8b, 0x34, + 0x42, 0x91, 0xf6, 0x2d, 0xb9, 0x4c, 0xf2, 0x53, 0x93, 0xdb, 0x91, 0x50, 0xe5, 0x15, 0xfe, 0x1a, 0x70, 0x49, 0x88, + 0x54, 0xa0, 0x12, 0x9f, 0xfb, 0x8e, 0x58, 0xa2, 0x49, 0x15, 0xa5, 0x28, 0xa8, 0x97, 0xe9, 0x5f, 0x31, 0x2f, 0x4d, + 0x69, 0xec, 0x8e, 0xc0, 0xdd, 0x77, 0x19, 0x2b, 0x89, 0x3b, 0x8e, 0x99, 0x4c, 0x6b, 0x01, 0xd8, 0xa3, 0xcb, 0x4d, + 0xde, 0xe5, 0x80, 0xcb, 0xe3, 0xe3, 0x16, 0x40, 0xb0, 0x87, 0x05, 0xfc, 0xb5, 0x9d, 0x4b, 0x1d, 0x67, 0x24, 0x22, + 0x16, 0x9c, 0x21, 0x8b, 0x27, 0x6f, 0x00, 0x48, 0xce, 0xef, 0xe2, 0xe7, 0x05, 0x6d, 0x07, 0x40, 0x15, 0x8e, 0x0a, + 0x40, 0xec, 0x90, 0x60, 0xd0, 0x85, 0x77, 0xb2, 0xaf, 0x5a, 0xb3, 0xe3, 0xed, 0x05, 0x75, 0x1b, 0xcd, 0x3c, 0xd2, + 0x93, 0x92, 0x08, 0xe2, 0x0c, 0xb3, 0x1f, 0x04, 0x25, 0xaa, 0x57, 0xf5, 0x84, 0x30, 0x3a, 0x5b, 0x92, 0xc5, 0x4d, + 0x83, 0x80, 0xb4, 0x8f, 0x10, 0x33, 0xd9, 0x2e, 0xe5, 0x98, 0x7c, 0xed, 0x19, 0xe7, 0xac, 0x39, 0x43, 0x28, 0x1a, + 0xd8, 0xad, 0x25, 0x10, 0xeb, 0x1c, 0xca, 0x68, 0x28, 0x4d, 0xf9, 0x85, 0x1c, 0x41, 0xad, 0x63, 0xaf, 0x4c, 0x86, + 0x76, 0x1b, 0xdc, 0xfd, 0x80, 0x14, 0x29, 0xdc, 0xa3, 0x81, 0x65, 0x93, 0xd5, 0xe2, 0x92, 0x59, 0xbc, 0xe5, 0x91, + 0x62, 0x25, 0xb3, 0x1f, 0x04, 0xc3, 0x0b, 0xac, 0xe1, 0x62, 0x91, 0x8e, 0x12, 0xb2, 0x0a, 0x2e, 0x8b, 0xf5, 0xfe, + 0xec, 0xd6, 0x5d, 0x37, 0x05, 0xb9, 0xcd, 0xc9, 0x98, 0x29, 0xc7, 0xe3, 0x0a, 0xd2, 0x86, 0x5c, 0x1e, 0x07, 0x69, + 0xa4, 0xa9, 0x50, 0x3a, 0xb3, 0x7e, 0xba, 0x3f, 0xd5, 0xe3, 0xc5, 0x5c, 0x9d, 0x2c, 0x20, 0xa0, 0x8d, 0x3b, 0x70, + 0xca, 0x2a, 0x2c, 0x09, 0x87, 0x24, 0x6c, 0x78, 0x00, 0xa6, 0x5a, 0x3f, 0x8a, 0x4a, 0xfc, 0xbb, 0x64, 0x13, 0x41, + 0xa5, 0xe7, 0x06, 0xe7, 0x67, 0x69, 0x3c, 0x19, 0x85, 0x9f, 0xc4, 0x14, 0xce, 0x38, 0xcc, 0x11, 0xa2, 0xb2, 0x44, + 0xbf, 0x41, 0x89, 0xe7, 0x7e, 0x5a, 0xf2, 0x7f, 0xb6, 0x71, 0xfe, 0xa0, 0x8c, 0xe6, 0xd9, 0xb2, 0xe9, 0xb3, 0x05, + 0xc3, 0xde, 0x96, 0xb4, 0xb5, 0xee, 0x2c, 0x8a, 0xff, 0x8d, 0xea, 0xf0, 0xe9, 0x0e, 0x93, 0x58, 0x0f, 0x5c, 0x49, + 0xf0, 0xa9, 0x39, 0xe1, 0xd3, 0x9d, 0x3a, 0xe1, 0x87, 0x84, 0x88, 0x77, 0x8c, 0x8c, 0xb6, 0xc6, 0xd4, 0x6c, 0x05, + 0x8b, 0x4b, 0x2f, 0x2a, 0x82, 0x9d, 0x64, 0xd8, 0x94, 0x77, 0xbf, 0xe3, 0x95, 0x66, 0x07, 0x09, 0xe1, 0x45, 0xaa, + 0xed, 0x5c, 0xa3, 0xc5, 0x9c, 0x16, 0x50, 0x4a, 0x2a, 0x25, 0xd1, 0x6c, 0x1a, 0xc7, 0x6a, 0x81, 0x9f, 0x17, 0x24, + 0xb9, 0x55, 0xac, 0xfb, 0xb5, 0x33, 0x9c, 0xa8, 0x92, 0x9a, 0x92, 0x9a, 0xba, 0xb4, 0xa4, 0xc7, 0x60, 0xfe, 0xb7, + 0xc6, 0x44, 0xca, 0x35, 0x2e, 0x3c, 0xf0, 0x84, 0x32, 0x7e, 0x3d, 0x54, 0x3b, 0x59, 0x85, 0x33, 0xaf, 0xef, 0x2f, + 0xc3, 0xa1, 0xce, 0x85, 0x33, 0x0e, 0xdd, 0x70, 0x39, 0xb6, 0xdd, 0x6f, 0xed, 0xfc, 0x05, 0xfc, 0x45, 0x50, 0x2c, + 0x49, 0xa4, 0x66, 0xee, 0xfc, 0xa0, 0xec, 0xd4, 0x61, 0xee, 0x50, 0xa3, 0x95, 0xf1, 0xd4, 0x38, 0xd7, 0xd7, 0x58, + 0xa6, 0x37, 0x6a, 0x52, 0x45, 0x58, 0xd3, 0x40, 0x0d, 0x0f, 0xe9, 0x3c, 0x0b, 0x7a, 0x6a, 0x65, 0xfb, 0x74, 0xd0, + 0x07, 0x09, 0xcf, 0xa9, 0x80, 0x38, 0x13, 0x45, 0x2e, 0xbe, 0xf6, 0xfe, 0x32, 0xef, 0x57, 0x70, 0xb0, 0x41, 0xc9, + 0x5c, 0x3c, 0xb3, 0x38, 0x47, 0xcf, 0x0c, 0xe7, 0xf4, 0x99, 0xb5, 0xb3, 0x1d, 0xf6, 0x73, 0x29, 0x76, 0x25, 0xb0, + 0x28, 0x49, 0xca, 0x74, 0x5c, 0xb9, 0x3a, 0x9c, 0x3b, 0x0b, 0xe7, 0x91, 0xa9, 0x3a, 0xc5, 0x60, 0x52, 0xa6, 0xb4, + 0x7a, 0x62, 0x5b, 0x62, 0x6c, 0x99, 0x40, 0xb0, 0x4b, 0xbf, 0xae, 0xdc, 0xf6, 0x8b, 0xbb, 0x24, 0x85, 0xda, 0xd2, + 0xda, 0xf4, 0x24, 0x0a, 0x59, 0xf3, 0x4b, 0x1b, 0x4f, 0x89, 0xbd, 0xf3, 0x63, 0x15, 0x1d, 0xa4, 0x4b, 0x71, 0xac, + 0xdd, 0x89, 0x80, 0xcb, 0xb5, 0xa1, 0xfc, 0xb4, 0x35, 0x10, 0xd9, 0xf3, 0x16, 0xc9, 0xca, 0x1f, 0xca, 0xb0, 0x3c, + 0x21, 0x84, 0x89, 0xc0, 0xca, 0x58, 0x28, 0xad, 0x24, 0xb0, 0x0a, 0x7c, 0x94, 0xaa, 0xc5, 0xec, 0xb4, 0xf8, 0x3e, + 0x84, 0x6c, 0x8e, 0x9b, 0xd0, 0x9d, 0x00, 0xf2, 0x7a, 0x06, 0xd3, 0x55, 0x88, 0x02, 0xcd, 0x0c, 0x20, 0xe1, 0x87, + 0xec, 0xf6, 0x05, 0xcc, 0x1f, 0xd3, 0xb5, 0x5b, 0xb5, 0x72, 0x17, 0xed, 0x74, 0x2e, 0x89, 0x55, 0x9a, 0x6a, 0x52, + 0x5c, 0x94, 0x64, 0x21, 0xb1, 0x68, 0xe0, 0x95, 0x2b, 0x56, 0x9d, 0xfb, 0xc0, 0x6f, 0xd8, 0x36, 0x9e, 0xaf, 0xfa, + 0x31, 0xae, 0x40, 0xd5, 0xa8, 0x86, 0x1d, 0x7e, 0x00, 0xa6, 0xa6, 0x17, 0x09, 0x62, 0xb1, 0x59, 0xec, 0xce, 0x40, + 0x47, 0xf6, 0x51, 0xf1, 0xa4, 0x4c, 0x25, 0x0b, 0x54, 0x72, 0x8d, 0x14, 0x56, 0x5b, 0xb3, 0xa8, 0x4d, 0xc4, 0x7b, + 0xee, 0xd0, 0xba, 0x8a, 0xcb, 0x4c, 0x11, 0x7b, 0xa8, 0xe8, 0x33, 0x7a, 0xee, 0xc3, 0x2d, 0xbe, 0x87, 0x14, 0xc1, + 0x96, 0x8a, 0x91, 0x29, 0x09, 0xed, 0xc9, 0x0a, 0xa5, 0xc9, 0x12, 0x3c, 0x34, 0x50, 0x85, 0x0d, 0xf9, 0x0c, 0x07, + 0x6c, 0x3f, 0xa6, 0xf0, 0x64, 0x81, 0x12, 0x73, 0xa8, 0x76, 0x73, 0xf0, 0x5d, 0xed, 0x80, 0x77, 0x64, 0xcc, 0xcb, + 0xe4, 0x26, 0x17, 0xde, 0x91, 0xae, 0xbf, 0x1f, 0x07, 0x3b, 0x44, 0x18, 0xea, 0xa6, 0x80, 0xf4, 0xbc, 0x97, 0x0b, + 0x45, 0x89, 0x6f, 0xad, 0x18, 0xa8, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd4, 0x03, 0x3f, 0x21, 0xc8, 0x01, + 0x95, 0xd1, 0xa7, 0x2b, 0xda, 0xe2, 0xfa, 0xf3, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, 0x1d, 0x30, 0x8d, 0xfa, 0x68, + 0x68, 0xf7, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x17, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, 0xec, 0xd8, 0x3c, 0xba, 0xe1, + 0xdb, 0xf5, 0xc9, 0x80, 0xa1, 0x65, 0xd6, 0xdb, 0xa7, 0xab, 0x8f, 0xc6, 0xe7, 0x9a, 0x1a, 0x15, 0xc7, 0x45, 0x32, + 0x64, 0xaa, 0xa8, 0xf3, 0xc9, 0x26, 0x2a, 0x62, 0x6d, 0x2e, 0xfb, 0xce, 0x87, 0x31, 0xe8, 0xb1, 0x45, 0x95, 0x11, + 0xd7, 0x8e, 0xd9, 0xaf, 0x2f, 0xd6, 0xe5, 0x78, 0x9c, 0xd3, 0x07, 0x12, 0xa6, 0xed, 0x24, 0x42, 0xdd, 0x89, 0xf2, + 0x4d, 0x53, 0x9a, 0x05, 0x61, 0x3f, 0x58, 0xa4, 0x63, 0x0d, 0x9b, 0x6f, 0xc6, 0x6c, 0x6e, 0xa0, 0xba, 0xf2, 0x03, + 0xd4, 0x81, 0xb8, 0x18, 0x70, 0xf1, 0x0e, 0x8c, 0x39, 0xf3, 0xef, 0xb8, 0xbf, 0x2a, 0xa5, 0x34, 0xea, 0xf8, 0xb2, + 0xd4, 0xc8, 0xf6, 0x7e, 0xd9, 0x7f, 0x65, 0xf6, 0x21, 0xdf, 0x15, 0xa8, 0x50, 0x85, 0x34, 0x34, 0x89, 0x7a, 0xed, + 0x00, 0xb1, 0x9d, 0x8d, 0x26, 0x6a, 0xc5, 0x22, 0x52, 0x1e, 0x01, 0x0e, 0xe5, 0xf0, 0x5e, 0xb7, 0x0d, 0x23, 0xbe, + 0xbd, 0x4a, 0x3d, 0xd3, 0x96, 0x68, 0x1d, 0x0c, 0xf1, 0x2e, 0x5a, 0x4d, 0xe2, 0xcc, 0x0c, 0xe9, 0xd8, 0x99, 0xba, + 0x5f, 0xa2, 0xe8, 0x5d, 0x16, 0xd8, 0x6a, 0xae, 0xb6, 0x7e, 0x67, 0x45, 0x1f, 0xc2, 0x6a, 0xd9, 0xea, 0x7b, 0x31, + 0xd3, 0xd8, 0x4c, 0x9c, 0x20, 0x16, 0x40, 0xb3, 0x77, 0xee, 0x12, 0xc5, 0x98, 0xd9, 0x70, 0x59, 0xcc, 0x12, 0x29, + 0xc2, 0x0e, 0xe8, 0x24, 0x1a, 0x30, 0x31, 0xa7, 0x38, 0x36, 0x62, 0xdf, 0x27, 0xad, 0x6c, 0xe2, 0x4a, 0x28, 0x83, + 0x32, 0x69, 0xdd, 0x4e, 0xbf, 0x4c, 0x7c, 0xef, 0x5b, 0x40, 0xd3, 0x29, 0x73, 0x02, 0x7b, 0xce, 0x11, 0xe2, 0x0b, + 0x10, 0xe4, 0x56, 0x25, 0xef, 0x01, 0x96, 0xea, 0x9c, 0xa5, 0xeb, 0x53, 0x6f, 0x6c, 0x4b, 0xea, 0x89, 0xc3, 0xcc, + 0xf1, 0x3c, 0x2a, 0xbd, 0x02, 0xed, 0xe7, 0xbd, 0xef, 0xad, 0x6a, 0x9b, 0xf8, 0xeb, 0xf5, 0x01, 0x25, 0x46, 0xb3, + 0xb1, 0xa5, 0x9e, 0x6a, 0x69, 0xbe, 0xa9, 0x83, 0x9b, 0x10, 0xa2, 0x73, 0x5b, 0xb1, 0x66, 0xcd, 0xda, 0x91, 0x65, + 0xf4, 0xaf, 0x60, 0x85, 0x6f, 0x60, 0x2d, 0x2e, 0x01, 0xcd, 0xdf, 0x18, 0xdf, 0x08, 0x79, 0x5c, 0x7e, 0xa0, 0xf3, + 0x33, 0x46, 0x5d, 0x85, 0xa9, 0x22, 0xe1, 0xe1, 0xa5, 0xd6, 0x6b, 0x2d, 0xe8, 0x98, 0x96, 0x8f, 0x35, 0xf8, 0x42, + 0x4d, 0xab, 0x1d, 0xbc, 0xe5, 0x57, 0x6a, 0xea, 0x42, 0xe7, 0xe7, 0xa9, 0x03, 0x29, 0x5e, 0x7e, 0x45, 0x62, 0x8e, + 0xe5, 0xb7, 0x19, 0xfa, 0xe8, 0x7b, 0xf8, 0x75, 0xc3, 0x0f, 0x3a, 0x2f, 0x50, 0x49, 0x35, 0xce, 0x30, 0x0e, 0xe7, + 0xa7, 0x59, 0x35, 0x62, 0xa6, 0x08, 0x3f, 0x38, 0x75, 0x60, 0xf5, 0xba, 0x96, 0x87, 0x2e, 0x45, 0xa8, 0x02, 0x62, + 0x4f, 0xe3, 0xe7, 0x43, 0x98, 0x2a, 0xa6, 0x22, 0x81, 0x30, 0xa9, 0xd0, 0x9e, 0x92, 0x82, 0xdd, 0x62, 0xd5, 0xae, + 0x7a, 0xb7, 0x62, 0x5e, 0x93, 0x89, 0x80, 0x31, 0xde, 0x81, 0xe6, 0xcd, 0x6c, 0x5b, 0x87, 0xce, 0x89, 0x1d, 0x15, + 0xd8, 0x03, 0x32, 0xf6, 0x0e, 0x77, 0xbf, 0x99, 0x01, 0x27, 0x5c, 0xc3, 0xf4, 0x3c, 0x34, 0x1b, 0xdd, 0x70, 0xe5, + 0x5b, 0xfa, 0x74, 0xe6, 0xc4, 0xd9, 0x02, 0xcd, 0xd7, 0xc8, 0x56, 0xa2, 0xab, 0x9e, 0xa0, 0xee, 0x81, 0x64, 0x6f, + 0xdf, 0x5c, 0xf7, 0x76, 0x77, 0x05, 0x49, 0xa7, 0xbb, 0x19, 0xb0, 0x3b, 0x5c, 0xf0, 0x6e, 0xf5, 0x4c, 0x22, 0x09, + 0x00, 0x90, 0x3d, 0xe9, 0x3e, 0x0a, 0x5b, 0xe8, 0x4e, 0xb7, 0xbf, 0x76, 0x53, 0x59, 0xd0, 0x26, 0x5d, 0x79, 0x0c, + 0x6d, 0x13, 0x46, 0xc4, 0x90, 0x5d, 0x97, 0x91, 0x75, 0x4b, 0x5f, 0x08, 0x17, 0xf0, 0x88, 0x03, 0xb6, 0xc3, 0x76, + 0x41, 0x30, 0x12, 0x90, 0x90, 0x73, 0x21, 0xfe, 0x36, 0x0d, 0x35, 0x2b, 0xb8, 0xdb, 0x6c, 0x88, 0xdd, 0x24, 0xa1, + 0x3f, 0xe8, 0x0a, 0x6f, 0x6e, 0xbd, 0x1c, 0x2b, 0x28, 0xf3, 0xd1, 0x73, 0xb5, 0x9f, 0x35, 0x53, 0x7b, 0x3a, 0x69, + 0x69, 0xc6, 0xbc, 0x54, 0x6a, 0x9e, 0xc8, 0xbb, 0xb9, 0x81, 0x67, 0xe3, 0x99, 0x39, 0xc4, 0x89, 0x2d, 0x4d, 0xeb, + 0x66, 0xcc, 0xd1, 0xee, 0x6c, 0x3e, 0xf6, 0xec, 0xab, 0x9f, 0xcb, 0xbc, 0x54, 0x9f, 0xcd, 0xcd, 0xd2, 0xac, 0x9c, + 0x3f, 0x43, 0x54, 0xd8, 0x56, 0x16, 0x53, 0x4d, 0xe2, 0x18, 0x04, 0x46, 0x8b, 0x6e, 0x6f, 0xa1, 0x19, 0x76, 0x31, + 0x3b, 0xce, 0xa5, 0x59, 0x77, 0x7b, 0x85, 0xe3, 0x97, 0x99, 0xaf, 0x55, 0xed, 0x8d, 0x1b, 0x25, 0x0a, 0x4e, 0x87, + 0x83, 0xf3, 0xb0, 0xfd, 0x4b, 0x91, 0x37, 0x33, 0x8c, 0x25, 0x81, 0x68, 0x2d, 0x5a, 0xb8, 0xca, 0x68, 0xb5, 0x59, + 0x15, 0x21, 0x39, 0xb5, 0x33, 0xff, 0x85, 0x06, 0x90, 0x5a, 0xf0, 0x0a, 0x75, 0x73, 0x81, 0x05, 0xc7, 0xa8, 0xd4, + 0xa1, 0xf1, 0x29, 0xa7, 0x24, 0x43, 0x2a, 0x3a, 0xec, 0x72, 0xa2, 0x75, 0x4e, 0xb6, 0x1c, 0x01, 0x08, 0x94, 0x6a, + 0xc3, 0x06, 0x53, 0x1f, 0x26, 0x99, 0x5b, 0x99, 0x8e, 0x30, 0x53, 0x05, 0xc6, 0xdf, 0xac, 0x16, 0x7b, 0x97, 0x73, + 0x91, 0x24, 0xcc, 0xed, 0x0c, 0x3d, 0x59, 0x80, 0x0e, 0x63, 0x70, 0x7c, 0x3b, 0xf9, 0xa9, 0xfe, 0xb4, 0xba, 0x22, + 0xe3, 0xd4, 0x31, 0x39, 0x7b, 0x6d, 0x07, 0x05, 0x8d, 0xda, 0xee, 0x65, 0x78, 0xcd, 0xb3, 0x02, 0xed, 0xf3, 0xbf, + 0xda, 0xbd, 0xdd, 0xbc, 0xf0, 0xe5, 0xb7, 0x90, 0x15, 0x48, 0x3d, 0xc1, 0x6b, 0x53, 0x19, 0x95, 0x6a, 0xe7, 0x12, + 0x6d, 0xbf, 0x3c, 0x21, 0xc9, 0xb6, 0xf1, 0x6f, 0x91, 0x4b, 0x29, 0x90, 0xfc, 0x7d, 0x6d, 0x24, 0xb2, 0xc5, 0x2c, + 0x49, 0x98, 0xea, 0x35, 0x49, 0x75, 0x1e, 0xd6, 0xb1, 0x9b, 0x8e, 0xff, 0x2c, 0x43, 0xf4, 0x34, 0x12, 0x52, 0xeb, + 0x6d, 0x4d, 0xe6, 0x61, 0x1d, 0xdd, 0xc9, 0x16, 0xcf, 0x79, 0xc4, 0x53, 0x41, 0xc6, 0x6c, 0xb3, 0xee, 0x52, 0x89, + 0x44, 0x2d, 0x58, 0x06, 0xda, 0xed, 0x66, 0x38, 0x45, 0xad, 0x03, 0x14, 0x3b, 0x15, 0x7d, 0x19, 0xba, 0xd2, 0xd4, + 0x67, 0xb2, 0xa1, 0xb0, 0x52, 0x8b, 0xba, 0xbd, 0x94, 0x7a, 0xce, 0x86, 0xae, 0xbc, 0x3c, 0x99, 0x6b, 0xbe, 0x03, + 0xd8, 0x46, 0x1b, 0x4b, 0x37, 0x80, 0x6e, 0x34, 0x03, 0x37, 0x21, 0x03, 0x50, 0xd6, 0x14, 0x2a, 0x37, 0x35, 0xb8, + 0xa4, 0x9e, 0x95, 0x62, 0x0e, 0x48, 0x04, 0x67, 0xec, 0xdb, 0x00, 0x63, 0x7f, 0x8d, 0x9c, 0xc3, 0x55, 0xeb, 0xaa, + 0xad, 0x60, 0x6d, 0x9d, 0x3e, 0x6d, 0x1c, 0xc6, 0x2b, 0xfb, 0x27, 0xe0, 0xbb, 0x78, 0x51, 0x3b, 0x32, 0xfd, 0x2d, + 0x8e, 0x35, 0x84, 0x42, 0xd7, 0x27, 0x86, 0xc2, 0x8c, 0xc1, 0x30, 0xbb, 0xbb, 0x20, 0x4c, 0xaf, 0x2f, 0x05, 0x0c, + 0x0b, 0x37, 0x97, 0x62, 0xc7, 0xf1, 0xf3, 0x07, 0xfb, 0x89, 0x22, 0x1c, 0x9a, 0xa9, 0x10, 0x3e, 0x97, 0xae, 0x8c, + 0x82, 0x9c, 0x99, 0xcc, 0x09, 0x3c, 0xd8, 0x3e, 0x07, 0xd4, 0x28, 0x12, 0x8a, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x4d, + 0xc2, 0x05, 0xe9, 0xcb, 0x71, 0x7d, 0x34, 0xbd, 0x86, 0x29, 0x59, 0x99, 0xb7, 0x48, 0xfc, 0x6c, 0x99, 0xf5, 0x11, + 0xe1, 0x74, 0xaf, 0x6d, 0x60, 0x8b, 0xb5, 0x6d, 0xef, 0xd7, 0x3d, 0xe0, 0xca, 0xc2, 0x81, 0xa1, 0x8d, 0x4c, 0x7d, + 0xb5, 0xa1, 0x97, 0x14, 0x71, 0xfe, 0x15, 0x3d, 0x32, 0x7e, 0x30, 0xf6, 0x7d, 0x07, 0x77, 0x0a, 0xa4, 0xb7, 0x39, + 0xbf, 0x61, 0xa6, 0xf7, 0x60, 0x75, 0x03, 0x35, 0xac, 0xc1, 0xa5, 0x32, 0x4b, 0x8d, 0xf9, 0x17, 0xb7, 0xc4, 0x27, + 0x0b, 0x8e, 0x12, 0x9f, 0x42, 0xe2, 0x1a, 0xae, 0x4f, 0x1f, 0x1f, 0x99, 0xf4, 0x6d, 0x12, 0x8a, 0xec, 0x56, 0x2c, + 0xdb, 0x43, 0xc5, 0x98, 0x1c, 0xee, 0x8a, 0xab, 0x36, 0x38, 0x60, 0x88, 0xd2, 0xd1, 0x10, 0x49, 0x83, 0x26, 0x0e, + 0x24, 0x8c, 0xf7, 0xc5, 0x0c, 0xcb, 0x0d, 0x5d, 0xbc, 0x22, 0x7a, 0x6b, 0xcd, 0xce, 0xa4, 0xec, 0x65, 0x45, 0xbe, + 0x29, 0xd5, 0xe4, 0x63, 0xba, 0x5a, 0x4f, 0x4b, 0xaf, 0x2d, 0xf7, 0x58, 0x00, 0x74, 0xaf, 0x8e, 0x7f, 0xbd, 0xef, + 0x75, 0xd5, 0x67, 0x22, 0xdf, 0xfa, 0x7a, 0x18, 0xbe, 0xdd, 0x7f, 0xa9, 0xa3, 0x38, 0xb8, 0x45, 0xec, 0xdf, 0xfe, + 0x48, 0x59, 0xd4, 0xd6, 0xaa, 0x1f, 0xd4, 0xc1, 0xa1, 0xa7, 0x1e, 0x37, 0x67, 0x61, 0x4d, 0x30, 0xe1, 0x54, 0x81, + 0x73, 0xa6, 0x83, 0xd0, 0xc6, 0xf2, 0x6f, 0x1c, 0xd5, 0xa6, 0x6e, 0xdc, 0xa0, 0x3c, 0xe3, 0xd9, 0x58, 0x19, 0xea, + 0xb2, 0x95, 0x9d, 0xf9, 0xb2, 0xf3, 0x8c, 0x9c, 0xf7, 0xac, 0xa6, 0x5f, 0x1a, 0x0b, 0x7c, 0xa5, 0xe2, 0x08, 0xe1, + 0x67, 0xc0, 0xbb, 0xc4, 0xb1, 0x63, 0x66, 0x7c, 0x0c, 0x4a, 0xbb, 0x5b, 0xd2, 0xe8, 0x30, 0xb2, 0x1d, 0x74, 0x9d, + 0xcb, 0x64, 0x44, 0x50, 0x10, 0x22, 0xe4, 0x30, 0xb4, 0x43, 0x28, 0x67, 0xfb, 0xb1, 0xaa, 0xdc, 0x5e, 0xf4, 0x06, + 0xf3, 0x4a, 0xb6, 0x50, 0x04, 0x4c, 0x09, 0xbe, 0x5f, 0xd5, 0xd4, 0x88, 0x7d, 0xd3, 0xbf, 0x3d, 0x7c, 0x9a, 0x8b, + 0x9a, 0xa0, 0x01, 0xff, 0x3b, 0x96, 0xd5, 0xa0, 0x37, 0x56, 0x5f, 0x68, 0xd9, 0xb7, 0x86, 0x1c, 0x18, 0x55, 0x92, + 0xb6, 0x6e, 0x2f, 0x64, 0x95, 0x39, 0x57, 0xbb, 0x42, 0xf5, 0xa5, 0x47, 0x39, 0x99, 0xa6, 0x00, 0x30, 0x5d, 0x69, + 0x01, 0x71, 0x41, 0x21, 0xb4, 0xe0, 0xb0, 0x9a, 0x85, 0x4c, 0x5f, 0xcf, 0x4e, 0x61, 0xc1, 0x68, 0xbc, 0x30, 0xad, + 0x0d, 0x89, 0x32, 0x33, 0xa7, 0x4c, 0x4a, 0x77, 0xa9, 0xdd, 0x82, 0x3c, 0xf8, 0x2d, 0x2d, 0x1b, 0x80, 0x11, 0x13, + 0xc9, 0x77, 0x61, 0x13, 0x59, 0xfb, 0x7c, 0xce, 0xb8, 0xcd, 0xec, 0x49, 0xdf, 0xd4, 0xf4, 0x64, 0xe3, 0x34, 0x58, + 0x7f, 0x84, 0x9c, 0xe7, 0x6e, 0xa4, 0x6c, 0x6d, 0xe2, 0x96, 0xfb, 0x12, 0x1d, 0x43, 0x9f, 0x68, 0x97, 0x13, 0x76, + 0x40, 0x07, 0xfa, 0x4c, 0x5a, 0xc3, 0x35, 0x10, 0xe5, 0x30, 0x88, 0xa7, 0x72, 0x28, 0xae, 0x97, 0x3d, 0x46, 0x9d, + 0xc6, 0x02, 0x35, 0xb0, 0xc2, 0x17, 0x18, 0x46, 0x55, 0x05, 0x7b, 0xe0, 0x6f, 0x82, 0x9c, 0xae, 0xbe, 0x53, 0x2c, + 0x79, 0xd3, 0x12, 0xd1, 0x2e, 0x98, 0xb0, 0x0e, 0x2a, 0x1e, 0x63, 0xab, 0x49, 0x4a, 0x83, 0xa1, 0xeb, 0xc9, 0x77, + 0x41, 0xc6, 0x66, 0x32, 0xd2, 0xb4, 0x80, 0x3b, 0xcc, 0xed, 0x3c, 0x29, 0xcc, 0x21, 0x96, 0x8d, 0xab, 0xb8, 0x71, + 0xed, 0x6b, 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcd, 0x8b, 0xf6, 0x11, 0xaf, 0x63, 0x89, 0x65, 0xad, 0x9c, + 0xee, 0x30, 0xc2, 0x80, 0x88, 0xfb, 0x48, 0x17, 0xcc, 0x2c, 0xb5, 0xb5, 0xb8, 0x2a, 0x62, 0x59, 0xb6, 0x6b, 0x2c, + 0x06, 0x60, 0x14, 0xd8, 0x1f, 0xce, 0x6b, 0x19, 0x34, 0x7a, 0x3e, 0x7c, 0xba, 0x22, 0xa7, 0x65, 0x6d, 0x86, 0x0d, + 0xcf, 0xa6, 0x03, 0x54, 0xb8, 0x26, 0x56, 0xe7, 0x25, 0xd8, 0x8b, 0xb5, 0xe5, 0xe8, 0xdf, 0xbb, 0xf4, 0x22, 0x9e, + 0x17, 0x84, 0x70, 0x2a, 0x36, 0x5b, 0x1a, 0x20, 0x0e, 0x60, 0x17, 0x53, 0x1d, 0x10, 0x82, 0xba, 0xb3, 0xda, 0x03, + 0xf2, 0xf9, 0x6b, 0x86, 0xbe, 0x8f, 0x84, 0x6f, 0x02, 0x64, 0xa6, 0xa0, 0x3c, 0x51, 0xfb, 0x14, 0x45, 0xf4, 0xe0, + 0x27, 0x5d, 0x65, 0xb3, 0x16, 0x75, 0x12, 0x38, 0x1d, 0x71, 0x72, 0x16, 0xa3, 0x70, 0x5e, 0x3e, 0x13, 0xc0, 0x97, + 0x6b, 0x34, 0x98, 0x16, 0xdb, 0x28, 0x4e, 0xd9, 0x4e, 0xba, 0x5b, 0x03, 0x74, 0xc7, 0xe7, 0x88, 0xc3, 0x41, 0x26, + 0xca, 0xde, 0xae, 0x33, 0x5d, 0x86, 0x75, 0x53, 0x47, 0xbd, 0x9f, 0x28, 0x7c, 0x4a, 0xdd, 0xe3, 0x7d, 0x2e, 0x45, + 0x50, 0x21, 0x54, 0x12, 0xd4, 0x32, 0xa4, 0x3f, 0x6a, 0x79, 0x4e, 0x8d, 0xd4, 0x29, 0x8f, 0xcb, 0x05, 0x49, 0x6a, + 0xfb, 0x3e, 0x7b, 0xb4, 0x2f, 0x4f, 0xe4, 0x8e, 0x1b, 0x38, 0xd1, 0xb5, 0x02, 0x86, 0x4e, 0x73, 0x0f, 0x76, 0xde, + 0x8a, 0x8a, 0x64, 0x22, 0x8a, 0xa1, 0xbd, 0x84, 0xb3, 0x2a, 0xbb, 0x49, 0x42, 0x7f, 0x16, 0x2b, 0x9c, 0xd9, 0xb9, + 0x0c, 0xb5, 0x69, 0x6c, 0x61, 0x90, 0x51, 0x21, 0xb4, 0xdb, 0x98, 0x47, 0x98, 0xdc, 0x45, 0x6e, 0xf0, 0x2b, 0xad, + 0x54, 0x2e, 0x15, 0x92, 0xa6, 0x4b, 0x6f, 0xfd, 0x2f, 0x3b, 0x6a, 0xc5, 0x8d, 0xb7, 0x36, 0xca, 0x35, 0xca, 0xc5, + 0xcc, 0xf9, 0x8f, 0xd8, 0xe3, 0x12, 0x6b, 0xd8, 0x82, 0xcb, 0x86, 0xae, 0x50, 0x59, 0x4a, 0x03, 0x47, 0x1e, 0x88, + 0xa4, 0xee, 0x6b, 0x38, 0xe2, 0x16, 0xd5, 0x9f, 0xec, 0xf5, 0xc1, 0x06, 0xb5, 0x63, 0x36, 0x72, 0xb1, 0x8d, 0x5a, + 0xa1, 0x0b, 0x59, 0x45, 0x0d, 0x5c, 0x92, 0xb7, 0x60, 0x9a, 0x0c, 0xd1, 0x4d, 0x92, 0xb8, 0x7b, 0x3a, 0xc3, 0x2c, + 0x33, 0xbd, 0xe8, 0x7f, 0x56, 0xa2, 0xd2, 0xa1, 0xac, 0xb9, 0x92, 0xc3, 0x59, 0x47, 0xf5, 0xe3, 0xb0, 0x1f, 0xe2, + 0xd8, 0x74, 0x87, 0xe5, 0x80, 0x01, 0xac, 0x3a, 0xcc, 0x91, 0xa2, 0xf1, 0x62, 0xeb, 0xbb, 0x7d, 0xb7, 0x8d, 0x94, + 0xd0, 0xd0, 0x2f, 0x76, 0x08, 0xd8, 0xb7, 0xdf, 0x86, 0x39, 0xe3, 0xb6, 0x36, 0x8e, 0xf6, 0x51, 0x44, 0xda, 0x54, + 0x10, 0xfc, 0x91, 0x34, 0x39, 0xc0, 0x36, 0x5d, 0xca, 0x61, 0x73, 0xe5, 0xde, 0x67, 0x86, 0xc5, 0x94, 0x11, 0x31, + 0xab, 0xf7, 0x54, 0xe8, 0xaf, 0x7f, 0xf7, 0xdf, 0x2d, 0x5a, 0x5a, 0x34, 0xca, 0x8b, 0xf3, 0x72, 0x30, 0xb6, 0xea, + 0xd2, 0x7b, 0xb3, 0x34, 0xd6, 0x01, 0x40, 0xe5, 0xee, 0xfd, 0x45, 0x88, 0xbb, 0xeb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, + 0x93, 0xf2, 0xa9, 0xa7, 0x6c, 0x2c, 0x89, 0x3c, 0x65, 0xd6, 0xce, 0xed, 0x33, 0xbb, 0x09, 0x80, 0xf1, 0xbf, 0x32, + 0x3f, 0x2d, 0x2c, 0xf4, 0x9d, 0x56, 0x72, 0x51, 0xdb, 0x68, 0x67, 0xf4, 0x3e, 0x47, 0x81, 0x39, 0x40, 0x24, 0x27, + 0xe4, 0x3d, 0xbe, 0xa2, 0x78, 0xfc, 0x3f, 0x66, 0xa5, 0x61, 0xe3, 0xc4, 0x8e, 0xf2, 0xed, 0xc7, 0x0d, 0x1b, 0x29, + 0x39, 0x0f, 0x23, 0x23, 0x4c, 0xff, 0x1e, 0x99, 0x38, 0x8d, 0xca, 0xce, 0x3e, 0x2a, 0x88, 0x7a, 0xe2, 0xe3, 0xfb, + 0x73, 0x6c, 0xdd, 0x3f, 0x12, 0x2d, 0x65, 0x10, 0x96, 0x02, 0x38, 0x29, 0xf3, 0x48, 0xc3, 0x02, 0x98, 0xa2, 0x79, + 0x90, 0xf1, 0xc9, 0x69, 0x68, 0xbf, 0x7f, 0xe9, 0xf4, 0x1a, 0xb4, 0xbb, 0xc6, 0x30, 0x91, 0x35, 0x38, 0x77, 0x75, + 0xfb, 0x68, 0xd0, 0xdb, 0x7b, 0xde, 0x7e, 0x34, 0xe9, 0xad, 0xcd, 0x59, 0x43, 0x1b, 0x12, 0xc7, 0x3f, 0x6c, 0xff, + 0xa5, 0x9e, 0x27, 0x7b, 0xb7, 0x9a, 0x49, 0x91, 0x75, 0x39, 0xc4, 0x69, 0xd8, 0x52, 0x24, 0x1e, 0x80, 0xb8, 0xd4, + 0xfe, 0x58, 0xb2, 0xbc, 0xda, 0x83, 0xa2, 0xff, 0xd1, 0xfc, 0x48, 0x6b, 0xb2, 0x0f, 0xbe, 0x4c, 0xa1, 0x6a, 0xf7, + 0x33, 0xba, 0x3b, 0xbf, 0x07, 0x39, 0xb6, 0x59, 0x9a, 0xf8, 0xe2, 0xad, 0xa3, 0xe7, 0x89, 0xb4, 0x16, 0x5a, 0x99, + 0x61, 0x7a, 0xea, 0x1e, 0xc3, 0x52, 0x24, 0x4b, 0xcb, 0xde, 0xf2, 0x35, 0xe7, 0xe9, 0x4c, 0x7f, 0x7c, 0x10, 0xd7, + 0xb7, 0x7d, 0x4a, 0x7c, 0x8a, 0x98, 0x5f, 0xed, 0x13, 0xe0, 0x2c, 0x09, 0x1e, 0x47, 0x44, 0xa0, 0xb3, 0x15, 0xe5, + 0x23, 0x55, 0x75, 0xcd, 0xae, 0xff, 0xd1, 0xca, 0x02, 0x3b, 0x33, 0x1b, 0x77, 0x2b, 0x67, 0xfa, 0xe8, 0x34, 0xcf, + 0x72, 0x43, 0x3b, 0x90, 0x8b, 0x0d, 0x70, 0x60, 0xff, 0xb6, 0x49, 0x30, 0xac, 0x6d, 0xb8, 0x3f, 0x52, 0xbd, 0x31, + 0x4a, 0xfe, 0x46, 0x00, 0x46, 0x51, 0xd1, 0x56, 0xf1, 0xe6, 0x1a, 0xba, 0x90, 0x51, 0xbd, 0x3f, 0x79, 0x0f, 0xdf, + 0xef, 0x43, 0x1f, 0xba, 0x75, 0xd0, 0x5a, 0x70, 0x2a, 0x8b, 0x72, 0x39, 0xda, 0x3c, 0xef, 0x46, 0x5c, 0x7a, 0xf9, + 0x4d, 0x4f, 0x94, 0x7a, 0xfb, 0x6b, 0x07, 0x5b, 0x5a, 0x7e, 0x44, 0xa6, 0x9e, 0x24, 0x0a, 0x39, 0xd6, 0x4e, 0xf0, + 0x6a, 0xe9, 0x48, 0xc5, 0x81, 0xc3, 0xdd, 0x93, 0x91, 0x6f, 0xe6, 0x8c, 0x5d, 0x4b, 0x3a, 0x1e, 0x6c, 0x0c, 0xeb, + 0xe6, 0x6b, 0x29, 0xcd, 0x32, 0xeb, 0xd5, 0x3d, 0x3b, 0x11, 0x5e, 0x70, 0x78, 0x25, 0xb6, 0x29, 0xa4, 0xf9, 0xd5, + 0x44, 0x02, 0x37, 0xaf, 0xf7, 0x05, 0x20, 0x97, 0xb9, 0x74, 0x2e, 0xd8, 0x82, 0x74, 0xc5, 0x7f, 0x8e, 0x2a, 0xd0, + 0x27, 0x3f, 0xb3, 0x4a, 0xd7, 0xfa, 0x4a, 0x59, 0xa5, 0xf2, 0x1c, 0xdf, 0xd1, 0xa4, 0xd8, 0x3b, 0xda, 0x93, 0xd9, + 0x21, 0x1c, 0x8d, 0xc1, 0xcd, 0xfd, 0x46, 0x25, 0x65, 0x16, 0xa7, 0x5e, 0x92, 0xfe, 0x4b, 0xc2, 0x0c, 0x83, 0x84, + 0x04, 0x31, 0xff, 0x47, 0xdc, 0x98, 0xa3, 0x0e, 0x69, 0x0c, 0x4e, 0x64, 0x82, 0xd1, 0x42, 0x21, 0xba, 0x29, 0xcb, + 0x95, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xda, 0x65, 0x8d, 0x34, 0x2f, 0x7d, 0x0f, 0xbb, 0x87, 0x81, 0x14, 0x34, + 0x0a, 0x4b, 0x63, 0x0c, 0xec, 0xec, 0x26, 0x6d, 0x63, 0xb8, 0xd5, 0x1b, 0x68, 0x0a, 0x77, 0xef, 0xe9, 0x1a, 0xfa, + 0x5c, 0x24, 0x12, 0x4b, 0x7a, 0xb4, 0x8b, 0xc9, 0xb5, 0x96, 0xca, 0xb2, 0x5a, 0x8e, 0xdf, 0x4e, 0xf7, 0xb2, 0xbc, + 0x20, 0x68, 0xc8, 0x81, 0x93, 0xa3, 0xc0, 0x29, 0x97, 0x77, 0x32, 0x0d, 0x8e, 0x83, 0xb7, 0x99, 0x85, 0xc4, 0x1f, + 0xe4, 0x6d, 0xe8, 0xc8, 0x9c, 0xfd, 0xa0, 0x4d, 0x7f, 0xd4, 0x54, 0x85, 0x59, 0xd4, 0x43, 0x24, 0x03, 0x93, 0xee, + 0xde, 0x36, 0x06, 0x1d, 0x1f, 0xd7, 0x35, 0x6c, 0xee, 0x23, 0x0c, 0xae, 0x90, 0x08, 0xcd, 0xb1, 0x90, 0x3c, 0x03, + 0x9f, 0xe2, 0x61, 0x93, 0xa7, 0xcc, 0xdd, 0x8e, 0x89, 0xe3, 0xed, 0xe7, 0x9a, 0x26, 0x7b, 0xd9, 0xab, 0x7a, 0xf2, + 0x14, 0xb5, 0x5f, 0xb5, 0x6c, 0x46, 0x5a, 0xae, 0x79, 0x37, 0xf7, 0x30, 0x7a, 0x3e, 0xc5, 0x03, 0x3b, 0x08, 0xdc, + 0x19, 0xb1, 0x38, 0xc6, 0xf9, 0xbd, 0x55, 0x3c, 0x8c, 0xd1, 0x75, 0x19, 0x60, 0xd4, 0x06, 0xa2, 0x0f, 0x82, 0xf8, + 0x3e, 0x3b, 0x60, 0xdd, 0x39, 0xb0, 0x78, 0x63, 0x7a, 0xdc, 0x26, 0xe1, 0xb4, 0xd4, 0x27, 0xe3, 0x43, 0x36, 0x07, + 0x24, 0x54, 0x8a, 0x39, 0x0b, 0x42, 0x34, 0x01, 0x62, 0x0e, 0x29, 0xc9, 0x5e, 0xed, 0x03, 0x28, 0x62, 0x2e, 0x54, + 0x2e, 0x9a, 0x83, 0x1e, 0x10, 0x82, 0x1c, 0x66, 0x6c, 0xff, 0x31, 0x7e, 0x0c, 0x0f, 0x77, 0x58, 0xc8, 0x32, 0xe7, + 0x0d, 0x2e, 0xf2, 0xfd, 0x57, 0xc0, 0x5c, 0xba, 0x7a, 0xab, 0xbe, 0xd3, 0x13, 0xa4, 0xf4, 0x3e, 0x4b, 0x95, 0x5a, + 0x45, 0xee, 0x62, 0x95, 0x10, 0x5e, 0x17, 0x69, 0x34, 0x50, 0xd2, 0xdd, 0xa1, 0x1f, 0x7e, 0x05, 0x11, 0xd3, 0x17, + 0x12, 0xf0, 0x27, 0xf2, 0x03, 0xb1, 0xe0, 0xf5, 0x86, 0xa2, 0x30, 0x20, 0x7a, 0x0c, 0xb5, 0xf0, 0x0c, 0x95, 0x8a, + 0x93, 0xac, 0xe0, 0xee, 0x30, 0x4a, 0xd9, 0x3f, 0x4e, 0xe4, 0xc7, 0xaa, 0x3a, 0x76, 0x69, 0xd3, 0x5d, 0xc5, 0x6f, + 0x4b, 0xf6, 0x02, 0x88, 0x99, 0x2a, 0x3b, 0x53, 0x25, 0x22, 0x5f, 0x17, 0x88, 0xa0, 0x24, 0x3d, 0x4b, 0x76, 0xaf, + 0x86, 0xcf, 0xac, 0x62, 0x47, 0x9c, 0xd9, 0x25, 0x87, 0x80, 0xdf, 0x39, 0x99, 0xd8, 0xf4, 0xc1, 0xde, 0x79, 0xa0, + 0x4d, 0x1f, 0xa4, 0xc5, 0x5f, 0x16, 0x24, 0xf2, 0x0f, 0x5d, 0xf7, 0x16, 0x8c, 0x4d, 0x5a, 0x7f, 0x33, 0xf6, 0x20, + 0x6c, 0x8f, 0xb9, 0x79, 0x3b, 0x72, 0xcd, 0x7c, 0x89, 0x51, 0xee, 0xcd, 0xe9, 0x34, 0x7b, 0x9b, 0x61, 0x57, 0x37, + 0x7a, 0xd0, 0xac, 0x46, 0xfa, 0xe2, 0x27, 0xaa, 0xea, 0xe9, 0x06, 0x50, 0xef, 0xfc, 0xf4, 0xe9, 0xe8, 0xcb, 0x30, + 0x5b, 0x43, 0x72, 0x98, 0x30, 0x2f, 0xaa, 0xb1, 0xe7, 0xfa, 0x0c, 0xc1, 0xac, 0xa4, 0x7d, 0x07, 0x66, 0xe9, 0xb7, + 0x4c, 0x24, 0x87, 0x3e, 0xc5, 0xbe, 0x65, 0x45, 0x30, 0x48, 0xe7, 0xae, 0x46, 0xc5, 0x71, 0x16, 0xfa, 0x68, 0xda, + 0x72, 0x5f, 0xd4, 0xc8, 0x6d, 0x89, 0xd3, 0xe7, 0x72, 0xce, 0x40, 0xd8, 0x2f, 0xee, 0x38, 0xb3, 0xbe, 0xf3, 0x0e, + 0x49, 0x6b, 0x3d, 0x43, 0xbf, 0xa6, 0xf5, 0xd2, 0xad, 0xff, 0x3e, 0xf2, 0x56, 0xa6, 0x1d, 0x56, 0xcb, 0x39, 0x4d, + 0x4f, 0x55, 0xd9, 0x1b, 0x3c, 0x29, 0x03, 0x94, 0x2c, 0xa0, 0xbb, 0xac, 0x2d, 0x77, 0x13, 0xa0, 0xfe, 0x3a, 0xd2, + 0xb5, 0xfe, 0xce, 0x0a, 0x18, 0x14, 0x81, 0xda, 0x7e, 0x95, 0xf3, 0xa4, 0xbd, 0x12, 0x1f, 0x7f, 0xaf, 0x28, 0x36, + 0x5b, 0x9e, 0xbc, 0x15, 0xc8, 0x44, 0x3f, 0x0d, 0xcf, 0x9d, 0x9f, 0xab, 0x59, 0x98, 0x98, 0x4f, 0x97, 0x96, 0xdf, + 0xe3, 0x43, 0x77, 0x01, 0xad, 0xf7, 0x19, 0x21, 0x8d, 0xf9, 0x3f, 0xc7, 0x2c, 0x4b, 0xbc, 0x42, 0xb3, 0x7c, 0x1b, + 0xe0, 0x98, 0x0e, 0x4f, 0x49, 0xe3, 0x39, 0x0e, 0x28, 0x74, 0x83, 0x52, 0x6f, 0x37, 0x43, 0x2d, 0xc9, 0xc3, 0x42, + 0x41, 0x26, 0xfd, 0x88, 0xe6, 0x51, 0x76, 0x24, 0x80, 0x91, 0x69, 0xf5, 0xb7, 0xb9, 0xb6, 0xc8, 0xa3, 0x56, 0xfb, + 0x55, 0xe1, 0x5e, 0x9f, 0x45, 0xa3, 0xff, 0x6e, 0x06, 0x9c, 0x58, 0x1b, 0xb2, 0x37, 0x01, 0xd3, 0x88, 0x62, 0x8a, + 0x82, 0x1f, 0x0b, 0x92, 0x42, 0xa5, 0xe2, 0x5d, 0xd8, 0x22, 0x2c, 0x5c, 0x6a, 0x69, 0x19, 0x6b, 0xe2, 0x79, 0x0b, + 0xd0, 0xd1, 0xfe, 0xeb, 0xe2, 0xbb, 0xec, 0x99, 0xc1, 0x28, 0x29, 0xf7, 0x18, 0x8f, 0x04, 0xf5, 0x38, 0x2b, 0x01, + 0xfb, 0x2d, 0x84, 0xf8, 0x4a, 0x50, 0x93, 0x26, 0x75, 0x17, 0xc1, 0xe9, 0x36, 0x14, 0x70, 0x19, 0xad, 0x35, 0x12, + 0x34, 0x7c, 0x77, 0x92, 0x16, 0xb0, 0x2a, 0x78, 0x2f, 0x71, 0xc9, 0x8f, 0x81, 0x99, 0x8a, 0xee, 0xf0, 0x07, 0xd3, + 0xc7, 0x3b, 0xca, 0xf3, 0xb2, 0xd3, 0xba, 0xf6, 0x6e, 0xc3, 0x20, 0x8c, 0x18, 0x9f, 0x19, 0xe8, 0xc8, 0x5e, 0x0f, + 0xd8, 0x92, 0xc9, 0x18, 0x1b, 0xf0, 0x84, 0x28, 0xc8, 0x68, 0x9d, 0x8f, 0x2c, 0x5f, 0xec, 0xeb, 0x1e, 0x06, 0x27, + 0x64, 0x6c, 0x1c, 0x81, 0x1b, 0x35, 0x20, 0x43, 0xc2, 0x2c, 0xe1, 0xc7, 0x1e, 0xe1, 0x58, 0x3b, 0xf8, 0xaf, 0xb4, + 0x01, 0x05, 0xe4, 0x68, 0x4f, 0x0a, 0x49, 0xe6, 0x31, 0xcc, 0x1a, 0x14, 0x3e, 0x22, 0x43, 0x99, 0x93, 0xff, 0x1c, + 0x4b, 0x8a, 0x0d, 0xc7, 0xb1, 0x18, 0x99, 0x75, 0x1c, 0x7f, 0xea, 0xcc, 0x6f, 0x1b, 0xde, 0x83, 0x2a, 0x7a, 0xba, + 0x0e, 0x1e, 0x42, 0x29, 0x42, 0xb9, 0x99, 0x09, 0xe5, 0x47, 0x58, 0x74, 0x67, 0xb4, 0x01, 0xad, 0x1f, 0xa3, 0x47, + 0xbe, 0x7e, 0x83, 0x93, 0xcb, 0x50, 0x81, 0x75, 0xf1, 0xc3, 0x0f, 0xc4, 0xf4, 0xd9, 0x3b, 0x16, 0x6b, 0xe5, 0x6c, + 0x4e, 0x7d, 0xc9, 0xd0, 0x05, 0x5f, 0xa7, 0xeb, 0x13, 0xef, 0x95, 0x09, 0x52, 0xb3, 0xb0, 0x5a, 0x27, 0x36, 0x91, + 0x49, 0x8b, 0xd3, 0xe4, 0xdd, 0xfc, 0xe5, 0x69, 0x36, 0xf1, 0xca, 0xa5, 0xc0, 0xa4, 0x67, 0x51, 0x25, 0x36, 0x32, + 0xd3, 0x65, 0xc3, 0xbf, 0x1c, 0xe5, 0xf3, 0x6c, 0xa8, 0x67, 0x9e, 0x5f, 0xd0, 0x8d, 0xfb, 0xc3, 0x2c, 0x12, 0x6a, + 0x76, 0x5b, 0xe7, 0xcc, 0x4e, 0xb5, 0xcd, 0x7f, 0xb0, 0x73, 0xfb, 0xd8, 0xf7, 0x99, 0x8f, 0x64, 0x96, 0xae, 0x28, + 0x09, 0xbb, 0xe3, 0x21, 0xe9, 0x14, 0x93, 0x15, 0x67, 0x4e, 0x03, 0xf5, 0x5c, 0x16, 0xe7, 0x35, 0xb9, 0xbb, 0x80, + 0xb7, 0x82, 0x29, 0x03, 0x24, 0xd5, 0xf1, 0x45, 0x70, 0x55, 0x11, 0x38, 0x35, 0xb5, 0x50, 0x45, 0xf1, 0xb8, 0x33, + 0xdb, 0x2d, 0xa0, 0xea, 0xa7, 0x6a, 0x71, 0x69, 0xa4, 0xa2, 0x84, 0x67, 0xb2, 0x15, 0xa6, 0x40, 0xa6, 0x2b, 0x27, + 0xcd, 0x49, 0xac, 0x70, 0xd0, 0xcf, 0x22, 0x27, 0xd9, 0x8b, 0xaa, 0x76, 0xc3, 0x4b, 0x5b, 0x6b, 0x56, 0x18, 0xed, + 0x6c, 0xb5, 0x48, 0x27, 0x52, 0xb1, 0x7d, 0xa8, 0x1e, 0x0a, 0xf7, 0xdd, 0x04, 0x56, 0x6a, 0xa4, 0xb2, 0xfc, 0x75, + 0xa4, 0x86, 0x47, 0xfc, 0xb5, 0x49, 0x07, 0x49, 0xc3, 0x86, 0x1d, 0x6d, 0x6e, 0x9b, 0xcb, 0xa0, 0x58, 0xd6, 0x38, + 0x8c, 0x4a, 0x43, 0xb7, 0x11, 0xf9, 0x0a, 0xe5, 0x91, 0x7d, 0x13, 0x79, 0x43, 0x2c, 0xd9, 0x43, 0xbc, 0x46, 0xc2, + 0x24, 0xa5, 0x8f, 0x62, 0x8b, 0xc6, 0x85, 0xa2, 0x5b, 0xa6, 0xdd, 0xa6, 0x3b, 0x57, 0x49, 0x2e, 0xd3, 0x53, 0xcf, + 0xb3, 0x40, 0x29, 0xac, 0x44, 0x44, 0x42, 0xc8, 0x98, 0x67, 0x6f, 0xfc, 0xd4, 0xf4, 0xdc, 0x23, 0x4a, 0x34, 0xfb, + 0x02, 0xef, 0x85, 0x3e, 0x88, 0x11, 0x1f, 0x9b, 0x90, 0x63, 0xf8, 0xca, 0xe9, 0xf0, 0xbd, 0x6d, 0x4e, 0xfe, 0x68, + 0xe7, 0xe3, 0x89, 0x32, 0x25, 0xaa, 0x76, 0xf1, 0xb4, 0x81, 0xc4, 0x1a, 0x20, 0x9e, 0xa5, 0x63, 0x09, 0x4a, 0xa3, + 0xc7, 0x60, 0xe7, 0xf3, 0x6a, 0x97, 0x85, 0xda, 0xf4, 0x74, 0x97, 0xa5, 0x09, 0x70, 0xc1, 0x8e, 0xd2, 0xdb, 0xc4, + 0xee, 0xee, 0x2f, 0x1c, 0xd0, 0xdd, 0x37, 0x19, 0xd9, 0x68, 0x76, 0xd9, 0x90, 0xb0, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, + 0x25, 0x52, 0x21, 0xde, 0xd8, 0x37, 0x80, 0x99, 0x4c, 0x7b, 0xa6, 0xd1, 0x03, 0x91, 0xe2, 0x37, 0x60, 0x3b, 0x50, + 0x09, 0x0d, 0x32, 0x12, 0xf5, 0x93, 0x08, 0x35, 0x31, 0xee, 0x71, 0xfe, 0xe3, 0x9a, 0x72, 0x74, 0x90, 0x40, 0x8e, + 0x07, 0xbb, 0x67, 0x9d, 0x11, 0xc5, 0x59, 0x4f, 0x5a, 0xd5, 0x3c, 0x73, 0xd1, 0xa1, 0x74, 0x66, 0x1f, 0x28, 0xd1, + 0x13, 0x45, 0x7f, 0xb9, 0x1d, 0xe9, 0x47, 0x80, 0xc1, 0xb0, 0x2b, 0xcc, 0x7f, 0x32, 0x9d, 0x70, 0x41, 0x44, 0x3d, + 0x77, 0x57, 0xbd, 0x1d, 0x16, 0x3b, 0x93, 0xc9, 0xf8, 0xe4, 0x97, 0x81, 0xbb, 0x6f, 0x87, 0x88, 0xb4, 0x89, 0xdb, + 0x18, 0xf9, 0x64, 0x12, 0x30, 0xdb, 0xd5, 0x8d, 0x6a, 0x46, 0x3a, 0x26, 0x11, 0x53, 0xeb, 0x37, 0xf6, 0x79, 0x9b, + 0x5e, 0xbb, 0x07, 0xff, 0xfd, 0x06, 0x4d, 0x90, 0x7a, 0xa6, 0x8a, 0xc5, 0xfb, 0x70, 0xe7, 0xa0, 0xfb, 0xcb, 0xf6, + 0x59, 0x5e, 0xf6, 0xb0, 0x14, 0x32, 0xb4, 0x4a, 0xd4, 0xf9, 0x58, 0x3b, 0x8c, 0x74, 0x7e, 0xa6, 0x61, 0xb9, 0xd6, + 0x7f, 0xaa, 0x3a, 0x98, 0xf5, 0x9b, 0xc1, 0x49, 0x65, 0xb1, 0xa8, 0xa6, 0x92, 0x0b, 0xef, 0xe0, 0x6b, 0x38, 0xb7, + 0x86, 0x7e, 0xed, 0xa6, 0xf2, 0xd4, 0x55, 0xe1, 0xb2, 0xef, 0xa2, 0x9f, 0xb0, 0xa9, 0xbf, 0x8a, 0x41, 0xf9, 0xeb, + 0xe0, 0x14, 0x54, 0x6f, 0xc8, 0x1b, 0x23, 0x75, 0x17, 0xef, 0x17, 0x52, 0x62, 0x72, 0xc4, 0x3f, 0x0a, 0x86, 0x46, + 0x69, 0x5b, 0xaa, 0x63, 0xec, 0x2c, 0x98, 0xec, 0xac, 0x76, 0x5b, 0xff, 0x8e, 0x82, 0x27, 0xda, 0xce, 0xef, 0x7e, + 0x24, 0x35, 0x0f, 0xb0, 0xce, 0xfa, 0xf2, 0x23, 0x70, 0x5e, 0xdb, 0x8f, 0xd4, 0xf3, 0xa1, 0x98, 0x9e, 0x68, 0x7d, + 0xcc, 0xda, 0xf3, 0x6c, 0xc1, 0x9e, 0xef, 0x59, 0x08, 0x35, 0x52, 0x67, 0xfc, 0xc0, 0xcc, 0xef, 0x42, 0x67, 0x3b, + 0xec, 0xb2, 0x63, 0xad, 0x79, 0xbf, 0x32, 0x63, 0xa5, 0xca, 0x7a, 0xe7, 0xd8, 0x91, 0x6b, 0x8d, 0x27, 0x63, 0x18, + 0x48, 0x1a, 0xab, 0x9b, 0xe1, 0xd4, 0x09, 0x95, 0x6f, 0x66, 0x41, 0xc7, 0x4e, 0xa2, 0x9b, 0xe5, 0x22, 0x4a, 0xa4, + 0xc8, 0xdf, 0x06, 0x99, 0x62, 0x38, 0x64, 0xc2, 0xa3, 0xb8, 0x37, 0x41, 0xc2, 0xbc, 0x56, 0x52, 0x26, 0x56, 0x3b, + 0xba, 0x5e, 0xa5, 0x47, 0xc1, 0xc1, 0x9a, 0x2a, 0x69, 0x33, 0x10, 0x75, 0xa9, 0xfb, 0xb0, 0xa6, 0xfb, 0x43, 0xa3, + 0x3a, 0xd8, 0x5f, 0x79, 0x2b, 0xb5, 0x68, 0xfe, 0x45, 0x0d, 0xc7, 0x6a, 0x84, 0xcd, 0x0c, 0x78, 0x1c, 0xfd, 0x1f, + 0x49, 0xa1, 0x43, 0xd7, 0x02, 0xa0, 0xf6, 0xc7, 0xf2, 0x06, 0x45, 0x31, 0x02, 0xb4, 0x1f, 0x56, 0xde, 0x48, 0x7d, + 0xca, 0x1f, 0xcc, 0xae, 0xdb, 0x8e, 0x2c, 0x17, 0xc1, 0x58, 0x93, 0x6d, 0x00, 0x08, 0xcb, 0x17, 0xb0, 0x81, 0x28, + 0x1a, 0x45, 0xd9, 0xd2, 0x3b, 0xec, 0x16, 0x2f, 0x21, 0x5a, 0xf3, 0x98, 0x50, 0xf4, 0x0d, 0xa9, 0xa4, 0xb2, 0xac, + 0xf0, 0xfd, 0xab, 0x0b, 0xe6, 0x5a, 0x18, 0xbd, 0xb5, 0xe7, 0x56, 0xb6, 0xe8, 0xbc, 0xbb, 0xab, 0xe9, 0x9f, 0xda, + 0xd5, 0xf0, 0x91, 0x6d, 0xc0, 0x8c, 0x2c, 0x6c, 0xc9, 0x0f, 0x4f, 0xeb, 0x26, 0x1c, 0xff, 0x28, 0x2a, 0x46, 0x85, + 0x2b, 0x08, 0x16, 0xb5, 0x46, 0x9c, 0x92, 0x7f, 0x1c, 0x00, 0x05, 0xda, 0xc3, 0x92, 0x08, 0x89, 0x51, 0x95, 0xa1, + 0x12, 0xd9, 0x53, 0xf1, 0xab, 0x36, 0x90, 0xc1, 0x24, 0x1c, 0x4a, 0x06, 0x6e, 0x6a, 0xd7, 0x9c, 0x98, 0x9d, 0xb9, + 0xf5, 0x1f, 0xb7, 0x8c, 0xd5, 0x30, 0x61, 0x89, 0xfa, 0x14, 0x66, 0x7a, 0x59, 0xf5, 0x08, 0x8f, 0xa6, 0x85, 0xee, + 0x21, 0x48, 0x2d, 0x8b, 0x84, 0xdf, 0xb3, 0x8e, 0x50, 0x23, 0x98, 0x90, 0xdd, 0xb3, 0x32, 0x0e, 0x21, 0xd7, 0xe9, + 0x71, 0xc6, 0x0b, 0x50, 0xcb, 0x7a, 0x9d, 0xb1, 0xcc, 0x91, 0xd7, 0x82, 0x2e, 0xc9, 0x05, 0xd5, 0x6b, 0x94, 0x0d, + 0x33, 0xae, 0x3f, 0x97, 0x44, 0x23, 0xdf, 0xa0, 0xa1, 0x76, 0xe4, 0x39, 0xf1, 0x79, 0xce, 0xd1, 0x14, 0xc9, 0x1d, + 0x3d, 0x83, 0x56, 0x33, 0x5b, 0x73, 0xd3, 0x9b, 0xaf, 0x36, 0x23, 0x6c, 0x77, 0x3c, 0x4e, 0x99, 0x26, 0x4e, 0x06, + 0xe7, 0x47, 0xa0, 0xcd, 0x9d, 0x96, 0xdc, 0xb8, 0xf8, 0x3f, 0x44, 0x1e, 0xdd, 0x3c, 0x9e, 0x23, 0x98, 0xcb, 0x6d, + 0x8c, 0xe2, 0xe1, 0xe6, 0xd8, 0x05, 0x36, 0xec, 0xff, 0x13, 0x17, 0x5d, 0x13, 0xf1, 0xe2, 0x50, 0x2b, 0x51, 0x09, + 0x71, 0x62, 0x7d, 0xb6, 0x0f, 0xa4, 0xf5, 0x88, 0x84, 0x13, 0x65, 0x9d, 0xcd, 0xc2, 0x38, 0xd6, 0x65, 0xf0, 0xe1, + 0x07, 0x6a, 0x09, 0x41, 0x60, 0x98, 0xbf, 0xc4, 0xfe, 0x04, 0x56, 0x5c, 0x88, 0x42, 0x19, 0xf1, 0xc2, 0xbf, 0xfa, + 0x8c, 0xcf, 0x69, 0x56, 0x56, 0xba, 0xc6, 0xe5, 0xc8, 0x4c, 0xad, 0x61, 0x4e, 0x9e, 0xb0, 0x69, 0x8a, 0x58, 0x4c, + 0xcf, 0x0d, 0x53, 0xcc, 0x08, 0x68, 0x68, 0xce, 0xb9, 0x23, 0x65, 0x4d, 0x82, 0x97, 0x31, 0x29, 0x96, 0x02, 0x74, + 0x85, 0x2e, 0x33, 0xbb, 0xed, 0x0c, 0xe3, 0x60, 0xc8, 0xcd, 0x02, 0x40, 0xb8, 0x12, 0x41, 0x2d, 0x02, 0xcf, 0x8a, + 0x7d, 0x25, 0x32, 0x07, 0x73, 0x91, 0xa3, 0xde, 0xeb, 0xa4, 0xbf, 0x41, 0xc2, 0x25, 0xbc, 0x95, 0x02, 0x27, 0x03, + 0xba, 0x4c, 0xa4, 0x40, 0xf3, 0x12, 0x21, 0xc6, 0x1a, 0x90, 0xd4, 0x36, 0x7e, 0xb9, 0x88, 0x70, 0xcf, 0x07, 0xd9, + 0x70, 0xd6, 0x0d, 0x02, 0x20, 0x8f, 0xf2, 0xfa, 0x3b, 0x8b, 0x74, 0x87, 0x39, 0x01, 0x89, 0x0b, 0x8e, 0x91, 0x13, + 0xda, 0x39, 0x35, 0xd8, 0x32, 0x17, 0xa3, 0x8c, 0xdb, 0x1a, 0x25, 0x4b, 0xe1, 0x6c, 0x23, 0xed, 0x36, 0x72, 0x46, + 0x32, 0x50, 0xeb, 0x32, 0x09, 0x3b, 0x74, 0xed, 0xc9, 0x54, 0x6e, 0x07, 0x78, 0x67, 0xcd, 0x40, 0x9f, 0x6e, 0x3d, + 0x1f, 0xfb, 0x9f, 0x36, 0x57, 0xc9, 0xf4, 0x7d, 0x93, 0x31, 0x62, 0x2e, 0xd1, 0x97, 0x1c, 0x66, 0x9f, 0xf6, 0xfb, + 0x7c, 0x07, 0x8b, 0xf5, 0x55, 0xfc, 0x55, 0xc5, 0x46, 0xfd, 0xd4, 0x7a, 0xc1, 0x24, 0x49, 0x2c, 0xb9, 0x35, 0x28, + 0x29, 0xa8, 0xcc, 0xdb, 0xa8, 0x21, 0x2b, 0xa6, 0xb5, 0x66, 0x3b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, + 0x71, 0xc4, 0x3e, 0x79, 0xc4, 0xc6, 0xdb, 0xdb, 0x0f, 0x9c, 0xa1, 0x63, 0xf2, 0x00, 0x81, 0x42, 0x64, 0x5e, 0xba, + 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xca, 0x7f, 0x66, 0xd7, 0xfa, 0xd0, 0xd8, 0x27, 0xc2, 0xd7, 0xd9, 0xda, + 0xed, 0xd8, 0x87, 0x50, 0xa8, 0x22, 0x5f, 0x48, 0x1d, 0xcc, 0x5c, 0xbc, 0xa9, 0x0c, 0x6e, 0x7a, 0xfb, 0x28, 0x09, + 0x30, 0x39, 0x1b, 0xfd, 0x44, 0xad, 0x08, 0x3e, 0x7b, 0x44, 0xf8, 0x62, 0xbb, 0x2d, 0xa2, 0xe0, 0xca, 0x68, 0xc6, + 0xbb, 0x8c, 0x7e, 0x72, 0xa3, 0xc5, 0x2f, 0xd3, 0xb2, 0x3c, 0x7b, 0x6a, 0x3b, 0x85, 0xf6, 0x71, 0x10, 0xbb, 0x22, + 0x68, 0x6b, 0x63, 0x41, 0x90, 0x35, 0x75, 0xd9, 0xa4, 0x22, 0xc5, 0x6f, 0xad, 0x93, 0xce, 0xeb, 0xc4, 0x33, 0xdb, + 0xe5, 0x3e, 0x24, 0x62, 0x04, 0x6e, 0x8b, 0x6e, 0xb7, 0x41, 0x54, 0x70, 0xe9, 0xe8, 0x64, 0x82, 0x47, 0x5d, 0xe2, + 0xa4, 0xda, 0xf5, 0x76, 0xdc, 0xfe, 0xd9, 0x1c, 0xf6, 0x03, 0x50, 0xe9, 0x3a, 0xd0, 0x7f, 0x4b, 0xaf, 0x64, 0x8e, + 0x3d, 0xec, 0xcd, 0x41, 0x73, 0x0b, 0xf4, 0x53, 0xb5, 0x89, 0xa2, 0xee, 0x0b, 0xfa, 0xcc, 0x38, 0xfe, 0x2f, 0x55, + 0x56, 0x30, 0x14, 0x26, 0x33, 0xd1, 0xac, 0xb6, 0x20, 0x9d, 0x85, 0x41, 0xed, 0x87, 0xb7, 0x1a, 0x39, 0x60, 0x8b, + 0x79, 0xc4, 0xa1, 0x1e, 0x34, 0x82, 0x97, 0x50, 0x20, 0xcc, 0xbd, 0x33, 0x34, 0x06, 0x3d, 0x28, 0x0f, 0x90, 0x81, + 0x62, 0xd0, 0xb2, 0x14, 0x1a, 0xda, 0x84, 0x54, 0xbb, 0xdf, 0x1f, 0xbd, 0x3e, 0xf4, 0x7b, 0x35, 0x8a, 0x68, 0xd4, + 0x3b, 0x07, 0x09, 0x28, 0x7a, 0xc5, 0x81, 0x0c, 0x94, 0x37, 0x4b, 0x62, 0xc4, 0x32, 0x1e, 0x07, 0xb9, 0x3a, 0x78, + 0xbc, 0x52, 0x72, 0x3c, 0x2b, 0x84, 0x1e, 0x03, 0x18, 0xd6, 0x3d, 0x70, 0x2f, 0xbb, 0x15, 0x2c, 0x02, 0x9e, 0xd5, + 0x2b, 0xea, 0xd9, 0x6a, 0x3e, 0xd4, 0xbf, 0x97, 0x17, 0xef, 0xb7, 0xb4, 0x9f, 0x4a, 0xec, 0xb1, 0xac, 0xa9, 0x02, + 0x1f, 0xfe, 0xfc, 0x29, 0xf3, 0xb1, 0x58, 0xa4, 0x4f, 0x9f, 0x5c, 0xc3, 0x09, 0xd1, 0x75, 0xc9, 0xbf, 0x70, 0x71, + 0x6c, 0x53, 0x40, 0x0d, 0xa7, 0x61, 0xe7, 0x8a, 0xf0, 0x38, 0x61, 0x0d, 0x17, 0x45, 0x38, 0xec, 0xe0, 0x60, 0x23, + 0x8c, 0x6e, 0xa8, 0x21, 0x96, 0xf4, 0x4e, 0x7c, 0x3b, 0xc0, 0x25, 0xf8, 0x79, 0xa1, 0x97, 0x49, 0x80, 0xf8, 0x63, + 0x8b, 0xc1, 0x04, 0xb9, 0xc4, 0xda, 0x6c, 0xca, 0x6e, 0xf5, 0x5e, 0x6b, 0xda, 0x79, 0x9a, 0x6e, 0xee, 0xad, 0xd9, + 0x9c, 0xa8, 0x3c, 0x70, 0x92, 0x51, 0x5c, 0x90, 0x1e, 0xd5, 0x33, 0xf9, 0x2f, 0x8e, 0x13, 0x40, 0x66, 0xf1, 0xe0, + 0x5e, 0x09, 0x8c, 0xed, 0x2b, 0x5d, 0x8b, 0xf8, 0x97, 0xc8, 0xf8, 0xd9, 0x68, 0xc6, 0xec, 0x15, 0x96, 0x5c, 0x6d, + 0xa8, 0x0d, 0x07, 0xcc, 0x45, 0x2f, 0x15, 0x9d, 0x63, 0x8c, 0x5a, 0xd8, 0x8c, 0x5f, 0x8c, 0xdd, 0x42, 0xa4, 0x51, + 0x8d, 0xd9, 0xf6, 0x6b, 0x4b, 0x74, 0xdf, 0xe3, 0x89, 0x24, 0x68, 0x5e, 0x12, 0x50, 0x80, 0x5d, 0x4c, 0x30, 0x24, + 0xd7, 0x30, 0x8c, 0x69, 0x86, 0xe7, 0x29, 0xd4, 0xb5, 0x9e, 0x1a, 0x95, 0x97, 0xba, 0xcb, 0xda, 0x5c, 0xb6, 0x9b, + 0x3c, 0xee, 0x51, 0x90, 0x38, 0x6a, 0x9c, 0xa1, 0x61, 0x56, 0x3d, 0x43, 0xca, 0xb0, 0x84, 0x48, 0x2b, 0x2e, 0xf2, + 0xb6, 0x76, 0x99, 0xc2, 0x40, 0xde, 0x89, 0x6e, 0x3a, 0xa7, 0x42, 0x04, 0xbb, 0x8b, 0x8a, 0x84, 0x4d, 0xdb, 0xb2, + 0x89, 0x16, 0x3a, 0xf7, 0x6d, 0x28, 0x74, 0x09, 0xf1, 0x43, 0xb6, 0x17, 0xee, 0x5e, 0x22, 0xf6, 0x10, 0xc6, 0xe6, + 0x88, 0x2d, 0x3e, 0xea, 0x25, 0xad, 0x97, 0x43, 0x42, 0x70, 0xb6, 0x59, 0xfa, 0xfc, 0x77, 0x6c, 0xe8, 0xca, 0xcb, + 0x0d, 0x8d, 0xca, 0x8e, 0xae, 0xaf, 0xae, 0x5a, 0x25, 0x16, 0xa9, 0xc6, 0x1c, 0x72, 0xe2, 0xa1, 0x45, 0xe7, 0x01, + 0x6d, 0xe2, 0xac, 0x9c, 0x11, 0x92, 0x3b, 0x6b, 0x51, 0xe8, 0x1a, 0xec, 0xbd, 0x0b, 0x00, 0x3b, 0x36, 0x99, 0xea, + 0xc5, 0xca, 0x53, 0x92, 0x60, 0xe8, 0x56, 0xe8, 0x9d, 0xaf, 0x72, 0x07, 0x0a, 0x31, 0xac, 0x03, 0x2c, 0x9c, 0x95, + 0xcc, 0x09, 0xdb, 0x87, 0xf5, 0xf8, 0x31, 0xaa, 0x2d, 0x60, 0x7c, 0x08, 0xa1, 0xbe, 0xb7, 0x71, 0x1b, 0x8a, 0x8e, + 0xce, 0x68, 0x72, 0x97, 0x13, 0x64, 0xd0, 0x77, 0xae, 0x94, 0x4c, 0xf1, 0x84, 0xbc, 0x9c, 0x39, 0x52, 0xa8, 0xf2, + 0xa6, 0x55, 0xfa, 0x62, 0xfb, 0xf6, 0x4b, 0x1f, 0x61, 0x5d, 0x23, 0x2e, 0x15, 0x63, 0x3d, 0x20, 0xfb, 0xee, 0x28, + 0x5a, 0xd3, 0x5e, 0x3c, 0x5d, 0x11, 0xcf, 0xf1, 0x26, 0x1c, 0xe1, 0x4f, 0x9f, 0xaf, 0xab, 0xd5, 0x79, 0x40, 0xb9, + 0xf7, 0x66, 0xc1, 0x31, 0xea, 0x1d, 0x97, 0x88, 0x60, 0xd2, 0x39, 0xdd, 0x69, 0x33, 0xa8, 0x26, 0x22, 0x33, 0x7c, + 0xb8, 0xf4, 0xdb, 0xfd, 0xaf, 0x20, 0x58, 0x77, 0x11, 0x2e, 0xdc, 0xd2, 0x20, 0x0e, 0x59, 0x8a, 0x90, 0x76, 0x45, + 0x30, 0xd2, 0x51, 0x41, 0x6c, 0xc5, 0x4e, 0x8a, 0x3c, 0x5f, 0x43, 0x20, 0xe2, 0x1c, 0x5c, 0x3e, 0xb3, 0x0a, 0x2f, + 0xaa, 0xd7, 0x3f, 0x37, 0x48, 0xe9, 0xb2, 0x3a, 0xe8, 0x7f, 0x9d, 0x2c, 0xfc, 0xe4, 0xe0, 0xc0, 0xcb, 0xc8, 0xda, + 0xda, 0xec, 0xb4, 0xa9, 0xde, 0x0a, 0x76, 0xdc, 0xce, 0xf5, 0xbe, 0x7e, 0x03, 0x4a, 0xa3, 0xad, 0xa8, 0xd9, 0x6d, + 0xca, 0x4c, 0x8d, 0xe1, 0x31, 0xab, 0x45, 0x03, 0x5c, 0xb8, 0xc3, 0xfe, 0x64, 0xc0, 0xde, 0xc1, 0x54, 0xf4, 0xbc, + 0x6f, 0xff, 0xec, 0x64, 0x86, 0x84, 0xe9, 0x84, 0x43, 0xee, 0xc0, 0x67, 0x4c, 0x4f, 0x27, 0x7d, 0x2f, 0x10, 0xbf, + 0x8a, 0x24, 0x9b, 0xf0, 0xb7, 0x0a, 0xef, 0x69, 0x64, 0x6c, 0x09, 0x19, 0xdd, 0x16, 0x95, 0x22, 0x52, 0x4b, 0x83, + 0x81, 0x31, 0x8a, 0xf9, 0x94, 0x68, 0x26, 0x96, 0xdd, 0x61, 0x43, 0x62, 0x9f, 0xed, 0x39, 0x7b, 0xbb, 0x98, 0x4d, + 0x09, 0x5a, 0x56, 0x7b, 0xf1, 0x6a, 0x6d, 0xde, 0x2b, 0x8f, 0xae, 0x8f, 0x1b, 0x18, 0xb1, 0x3f, 0xb7, 0xda, 0x5b, + 0xe0, 0x41, 0x07, 0xfc, 0xf3, 0x9d, 0xe2, 0xc5, 0xad, 0xf2, 0x25, 0x04, 0x3f, 0x64, 0x9a, 0x2c, 0x81, 0x32, 0xc8, + 0xc5, 0x96, 0x0b, 0x1e, 0x48, 0x15, 0xb5, 0xdd, 0x7a, 0x8c, 0xd8, 0x3c, 0x9f, 0x7c, 0xda, 0xc1, 0xf0, 0x4c, 0x41, + 0x07, 0xfb, 0x97, 0xed, 0xfd, 0x06, 0x68, 0xdd, 0x64, 0xc8, 0xbf, 0x6b, 0xdd, 0x04, 0x19, 0xc1, 0xc7, 0xaf, 0xb6, + 0xbf, 0xb0, 0xe6, 0xd3, 0xd4, 0x76, 0x8c, 0x96, 0x41, 0xb7, 0xfc, 0x5d, 0x72, 0x0a, 0x71, 0x5d, 0xed, 0x01, 0x7c, + 0xba, 0x8c, 0x01, 0x5f, 0xa2, 0x6f, 0x90, 0x1a, 0x40, 0xe4, 0xb7, 0x1f, 0xf5, 0xe3, 0xa7, 0xe6, 0x66, 0xf5, 0x43, + 0xc7, 0x86, 0x12, 0x31, 0x38, 0xac, 0x42, 0xb6, 0xe3, 0x00, 0xa0, 0xe2, 0x61, 0xe5, 0x88, 0x0e, 0x9a, 0x0f, 0x05, + 0xfb, 0x14, 0x0f, 0x3b, 0x07, 0x5f, 0xd7, 0x45, 0x91, 0x35, 0xa2, 0x24, 0x07, 0x4b, 0x25, 0xdd, 0x2f, 0x8e, 0xd2, + 0x0c, 0xaa, 0xf6, 0x04, 0x71, 0x15, 0x01, 0xc4, 0x63, 0x30, 0xba, 0xaf, 0x4b, 0xbf, 0xe7, 0x8a, 0x05, 0xe0, 0xe7, + 0x14, 0x6e, 0x63, 0x9e, 0x8f, 0x29, 0x80, 0xa0, 0xcf, 0x86, 0x06, 0x73, 0x88, 0x48, 0xc6, 0xe9, 0xec, 0x5a, 0x8c, + 0xf2, 0x32, 0xf2, 0xed, 0x88, 0xad, 0x22, 0x7f, 0xc7, 0x2a, 0x2f, 0x2e, 0xee, 0x85, 0x64, 0x17, 0xab, 0x74, 0x06, + 0x91, 0xda, 0x85, 0x99, 0x8c, 0x46, 0x47, 0xa6, 0xe9, 0x04, 0xd1, 0x5e, 0x2a, 0xa4, 0x64, 0x18, 0xe5, 0x18, 0xc5, + 0x22, 0x8e, 0x9c, 0x83, 0x93, 0x25, 0x0c, 0xc3, 0x92, 0xe0, 0xbf, 0x69, 0x40, 0xd0, 0x2b, 0x95, 0x14, 0xec, 0xa2, + 0x84, 0xb7, 0x43, 0x06, 0x0d, 0x80, 0xa5, 0xc6, 0x3b, 0x24, 0x4f, 0x35, 0xaa, 0x93, 0x73, 0xad, 0xc8, 0x70, 0x2a, + 0x75, 0x21, 0x3b, 0xc6, 0x13, 0x02, 0x89, 0x71, 0xde, 0xf9, 0x3c, 0x0f, 0x1a, 0x20, 0xf6, 0x64, 0x6a, 0x8d, 0xf4, + 0xbc, 0x62, 0x0f, 0x66, 0x5b, 0xda, 0x86, 0x46, 0x33, 0x07, 0x46, 0x02, 0x9b, 0x3f, 0x30, 0x53, 0x15, 0x53, 0xf3, + 0xc8, 0x31, 0x08, 0x43, 0x68, 0xbd, 0x95, 0xd5, 0x01, 0x21, 0xb4, 0x3c, 0x29, 0x93, 0x0c, 0xe2, 0xda, 0xf8, 0x30, + 0xea, 0x1a, 0x1f, 0x34, 0x12, 0xa0, 0x35, 0x73, 0xb5, 0xc5, 0xc7, 0xb3, 0x85, 0xc2, 0x19, 0x4b, 0x46, 0x7f, 0xb6, + 0x35, 0xb5, 0x92, 0xee, 0xe6, 0xee, 0xaf, 0xb0, 0xe5, 0xeb, 0xe4, 0x22, 0xdd, 0x2e, 0x65, 0x5b, 0x50, 0x1e, 0x68, + 0xb7, 0x9b, 0x59, 0xff, 0xfc, 0x37, 0x1f, 0x3f, 0x22, 0x74, 0x91, 0xb0, 0x0b, 0xc9, 0x2d, 0xea, 0xf8, 0x8b, 0x8f, + 0x86, 0x27, 0x63, 0xd8, 0xee, 0x0c, 0xcc, 0x1d, 0xe6, 0x39, 0x86, 0xbd, 0xc7, 0xc7, 0x31, 0x0c, 0x10, 0x93, 0xaf, + 0xa6, 0x0a, 0x13, 0x79, 0x87, 0x81, 0xca, 0x55, 0xaf, 0x1d, 0x20, 0x22, 0xce, 0xd4, 0x3e, 0x89, 0xe6, 0x9f, 0xa9, + 0xc8, 0xfb, 0x67, 0xdb, 0x13, 0x92, 0x20, 0x5f, 0xcf, 0x9a, 0xb8, 0x8e, 0x29, 0xf0, 0x00, 0xdb, 0x97, 0x58, 0x34, + 0x76, 0x97, 0x84, 0xd0, 0x42, 0x17, 0xa1, 0xa4, 0xc1, 0x87, 0x50, 0xf5, 0x6a, 0x95, 0x6c, 0x98, 0x0a, 0x0b, 0xbc, + 0xf8, 0xf4, 0x70, 0x0c, 0xef, 0x8f, 0x07, 0xca, 0x05, 0x85, 0x5c, 0x4e, 0xf0, 0x21, 0x6e, 0x1a, 0x7b, 0x06, 0x52, + 0x90, 0xf6, 0x4d, 0xe1, 0x9a, 0x9f, 0x8c, 0xac, 0x0b, 0x1d, 0x59, 0x4e, 0x4e, 0x4c, 0xf6, 0x24, 0xfc, 0x8b, 0x92, + 0x19, 0x92, 0xbc, 0x1c, 0x9c, 0xda, 0xc0, 0xd7, 0x2e, 0xe9, 0x28, 0xd7, 0xa2, 0x6d, 0xc3, 0xaf, 0x15, 0x27, 0xe8, + 0x94, 0x43, 0x37, 0xc1, 0xcb, 0x5e, 0x7d, 0x4e, 0xcd, 0x8d, 0xef, 0x95, 0xb7, 0x8b, 0xfb, 0xd7, 0xab, 0x01, 0x0e, + 0xbe, 0x40, 0x8e, 0xf7, 0xcc, 0x28, 0xce, 0xbf, 0x1d, 0xc6, 0xab, 0xe5, 0x98, 0x21, 0x30, 0x81, 0x84, 0x4c, 0x23, + 0x62, 0x1b, 0x4e, 0xf0, 0xf1, 0x43, 0x9d, 0xa3, 0x92, 0xd0, 0xd2, 0x8a, 0x83, 0xe3, 0x5c, 0x7f, 0x1b, 0x65, 0x48, + 0x29, 0xcb, 0xa5, 0x8c, 0x30, 0xc4, 0xc4, 0x01, 0x39, 0xdb, 0x95, 0xef, 0xc5, 0xe7, 0xcc, 0x33, 0x0d, 0xa4, 0x77, + 0xf1, 0x80, 0x16, 0x19, 0xf5, 0x07, 0x85, 0x1a, 0x44, 0x9a, 0x18, 0x7c, 0x46, 0x49, 0x20, 0x31, 0xc6, 0x46, 0x08, + 0x94, 0x90, 0x63, 0xeb, 0x07, 0x8b, 0x2a, 0x4c, 0x84, 0x22, 0x80, 0x96, 0x68, 0x79, 0x24, 0x28, 0xc8, 0x0c, 0x69, + 0xa4, 0xc7, 0xdc, 0x2d, 0x1d, 0x98, 0x16, 0x60, 0x4a, 0xc5, 0x23, 0x80, 0x7c, 0x32, 0x86, 0xa9, 0x88, 0x60, 0x70, + 0x57, 0x5e, 0x26, 0x0d, 0x1d, 0xd6, 0x30, 0x17, 0xcd, 0xc5, 0x94, 0x79, 0x19, 0x85, 0x72, 0x82, 0xc9, 0x55, 0x3b, + 0x21, 0xee, 0x0c, 0xa6, 0x75, 0x17, 0xf3, 0x79, 0x80, 0xd0, 0xf6, 0xd6, 0xd9, 0x14, 0x28, 0x33, 0x92, 0xd8, 0x04, + 0x11, 0x91, 0x0c, 0x76, 0x20, 0x0d, 0x45, 0x22, 0x24, 0x84, 0x4a, 0x52, 0xd0, 0x3a, 0x99, 0x13, 0x11, 0x9f, 0x56, + 0x58, 0xec, 0x83, 0xb4, 0x58, 0x22, 0x9b, 0xf7, 0xad, 0x32, 0xcc, 0x0f, 0x04, 0x85, 0x15, 0x8b, 0xac, 0x0a, 0x16, + 0x21, 0x91, 0xb0, 0x7a, 0x9d, 0x30, 0x76, 0x5e, 0x5f, 0x7c, 0x9a, 0x08, 0x4a, 0x9c, 0xd0, 0x91, 0x60, 0x1c, 0xab, + 0xa2, 0x58, 0xc9, 0x9f, 0x14, 0x39, 0xac, 0xd8, 0xf0, 0xe5, 0x55, 0xe9, 0x26, 0x91, 0x7c, 0xc7, 0xae, 0xfa, 0x95, + 0xb0, 0xfb, 0xa1, 0x9e, 0x38, 0xab, 0x44, 0x72, 0x8a, 0x6a, 0xab, 0xfb, 0x4f, 0xcf, 0x57, 0x95, 0x44, 0x79, 0xa1, + 0xa4, 0x0c, 0x7a, 0x8f, 0xdb, 0x62, 0x2f, 0x28, 0x36, 0x69, 0x76, 0xcc, 0xb7, 0xbd, 0x4a, 0xe4, 0x55, 0xc1, 0x94, + 0x2e, 0xc4, 0x12, 0x10, 0x37, 0x83, 0x65, 0x28, 0x6d, 0xcc, 0xf9, 0x07, 0x08, 0x7d, 0xf5, 0x3e, 0x2a, 0xb3, 0x1f, + 0xfd, 0x60, 0x05, 0x4d, 0x5c, 0x3f, 0xb3, 0xe6, 0x7a, 0x93, 0x46, 0x24, 0x30, 0xce, 0x42, 0x2f, 0xc5, 0xbe, 0x1a, + 0x97, 0x33, 0x57, 0x9a, 0x3d, 0xde, 0x8c, 0x56, 0x20, 0x76, 0x95, 0x86, 0x1d, 0x71, 0x3c, 0x07, 0x80, 0x74, 0x1e, + 0x85, 0x23, 0xa9, 0x14, 0xde, 0x6b, 0x81, 0xeb, 0x86, 0x68, 0x4b, 0x3d, 0x1f, 0x19, 0x80, 0x73, 0xb2, 0xc8, 0x4a, + 0xde, 0x84, 0x8c, 0xc4, 0xbf, 0x3c, 0xf3, 0x98, 0x31, 0xf6, 0x5e, 0x55, 0x18, 0x21, 0xcd, 0xaf, 0x5e, 0xa8, 0xb8, + 0x60, 0x63, 0x35, 0x9f, 0x96, 0xa7, 0x3c, 0x90, 0x2a, 0x9f, 0xaf, 0xb4, 0xa9, 0x1f, 0x39, 0x1f, 0x89, 0xb9, 0xb9, + 0x99, 0x93, 0x7a, 0x60, 0x10, 0xb1, 0x71, 0x9f, 0x20, 0xf2, 0x48, 0xf1, 0x67, 0x45, 0x2e, 0xd2, 0x61, 0x05, 0x56, + 0x0a, 0x01, 0x0b, 0x0d, 0x90, 0x56, 0xde, 0x4f, 0xb0, 0xe5, 0xd7, 0x24, 0x1a, 0x52, 0x2f, 0x99, 0x0d, 0xa8, 0x06, + 0xf1, 0x7b, 0x27, 0x9b, 0xcd, 0x9d, 0x9c, 0xce, 0xb7, 0x27, 0x6b, 0x86, 0xc8, 0x11, 0x74, 0xf4, 0xeb, 0xfe, 0x8e, + 0xbd, 0x20, 0x6d, 0x3a, 0x3b, 0xd9, 0x5a, 0x1f, 0x5e, 0x01, 0x93, 0x4e, 0xc5, 0x48, 0x93, 0x1a, 0x95, 0xb0, 0xcc, + 0x94, 0x4d, 0x29, 0xd1, 0x15, 0xd8, 0x4a, 0xc9, 0xc1, 0x96, 0x24, 0x9f, 0x79, 0xf8, 0x98, 0x74, 0xd7, 0x08, 0x17, + 0xe0, 0x18, 0x78, 0x2f, 0x83, 0xd2, 0x79, 0x60, 0xf4, 0x62, 0x10, 0xf3, 0x24, 0x84, 0x37, 0x5c, 0x96, 0xbc, 0x6c, + 0xed, 0xc9, 0x8a, 0x1a, 0xab, 0x6f, 0xdf, 0x7c, 0x3b, 0xe8, 0xca, 0xac, 0xd9, 0xc9, 0xef, 0xe7, 0x26, 0x5f, 0x77, + 0xcd, 0xf7, 0xbc, 0x6d, 0x7f, 0xc7, 0xb5, 0xcb, 0x37, 0x38, 0x2e, 0x18, 0x05, 0x3b, 0x5d, 0xac, 0x4e, 0x1b, 0x74, + 0x5c, 0x2f, 0x61, 0x57, 0x66, 0x04, 0xb4, 0x7b, 0x5f, 0xeb, 0x7f, 0x07, 0x98, 0x99, 0x62, 0x1f, 0x09, 0x22, 0x59, + 0x89, 0x6a, 0xcf, 0xfc, 0x42, 0xed, 0x2f, 0x08, 0x05, 0xf3, 0x35, 0xc8, 0xa3, 0xb7, 0x43, 0xc2, 0x68, 0x99, 0x89, + 0x38, 0xc1, 0x86, 0x05, 0x8f, 0xae, 0xe7, 0x72, 0xb6, 0xc5, 0x0e, 0x8f, 0xad, 0xae, 0xda, 0xdc, 0xab, 0x14, 0xf9, + 0x88, 0xeb, 0xe3, 0x19, 0x7a, 0xdf, 0x99, 0x79, 0xd0, 0xd1, 0x85, 0x48, 0xd8, 0xe2, 0x3a, 0x7e, 0x60, 0xbe, 0x46, + 0xa1, 0x60, 0xae, 0x94, 0xb9, 0xbd, 0x45, 0xdd, 0x4f, 0x75, 0xcf, 0xc9, 0xee, 0xfb, 0x92, 0x6f, 0x7e, 0xa4, 0xbd, + 0x1f, 0x45, 0xb3, 0xc2, 0x13, 0x2b, 0x5c, 0x47, 0xcf, 0xe6, 0x37, 0x1f, 0x33, 0x45, 0x08, 0x61, 0x04, 0xfd, 0xc2, + 0xaf, 0x70, 0x2d, 0xf0, 0x46, 0x99, 0xb6, 0x61, 0x2f, 0xa9, 0xa5, 0x20, 0xae, 0x1d, 0x1e, 0xce, 0xd9, 0xad, 0x35, + 0x59, 0xec, 0x8e, 0xab, 0xbe, 0xd0, 0x28, 0x7f, 0x87, 0x4c, 0x3b, 0x7c, 0xf3, 0x0d, 0xb9, 0x61, 0xaf, 0xa6, 0x4f, + 0x46, 0x68, 0xe2, 0x4e, 0xbd, 0x7e, 0x0a, 0x24, 0xf3, 0x34, 0x01, 0xa2, 0x31, 0xfc, 0xdf, 0x25, 0x7b, 0x34, 0xa6, + 0x13, 0x36, 0xcc, 0x86, 0xac, 0x36, 0x60, 0xec, 0x21, 0x89, 0x1e, 0x7f, 0x45, 0xfe, 0xdf, 0x9a, 0x04, 0xc7, 0x4b, + 0x71, 0x9f, 0x1b, 0xfe, 0xb2, 0x0c, 0xb3, 0x9c, 0xc4, 0x2c, 0xb8, 0x65, 0xc5, 0xab, 0x20, 0x5c, 0xa6, 0x5d, 0x61, + 0x19, 0x96, 0x0b, 0x2c, 0x43, 0x59, 0x7d, 0x11, 0x49, 0x22, 0xed, 0x91, 0x98, 0x9d, 0xce, 0xde, 0x8b, 0x13, 0xb2, + 0xe3, 0x06, 0x4d, 0x8e, 0x2e, 0xb2, 0x31, 0x13, 0x45, 0xed, 0x41, 0x23, 0x83, 0x72, 0x35, 0x78, 0xb9, 0x86, 0x8e, + 0x0c, 0xe1, 0x6a, 0x54, 0xa1, 0x71, 0x21, 0x9d, 0x4f, 0x2f, 0x8f, 0x0c, 0x24, 0x19, 0x34, 0xc5, 0xb0, 0x23, 0x54, + 0xc5, 0xbc, 0x4e, 0xf5, 0x42, 0x6a, 0x85, 0x47, 0xf2, 0x28, 0xc3, 0xf2, 0xd2, 0x22, 0xa3, 0xdd, 0xbe, 0x72, 0x74, + 0x5d, 0x38, 0x8e, 0x9f, 0xc3, 0x64, 0xa1, 0x0e, 0xd7, 0x60, 0x20, 0xdd, 0x4f, 0x1f, 0x79, 0xe9, 0x7f, 0x34, 0x5d, + 0x0d, 0xed, 0xb3, 0x85, 0xf8, 0xea, 0x21, 0x23, 0x8e, 0xaf, 0x5e, 0x58, 0x84, 0xa3, 0xe5, 0x96, 0xe9, 0xe3, 0x98, + 0x6d, 0x1d, 0xaa, 0xdc, 0x1a, 0x8d, 0x67, 0xb5, 0x18, 0x3f, 0xba, 0x0a, 0x1a, 0x82, 0xa6, 0x24, 0x0b, 0xf7, 0x15, + 0x75, 0x41, 0x56, 0x30, 0x19, 0xac, 0xb0, 0xbc, 0x99, 0xdf, 0xa7, 0xb5, 0xa9, 0xb4, 0x7c, 0x24, 0xf8, 0x07, 0x0f, + 0xb1, 0xac, 0x4f, 0x85, 0xdd, 0x12, 0x17, 0x0f, 0x2c, 0xe4, 0x59, 0x2f, 0xdc, 0x68, 0xeb, 0x94, 0xab, 0x72, 0xd9, + 0x2d, 0x5d, 0x78, 0x55, 0xb7, 0xbc, 0x14, 0x82, 0xd7, 0x21, 0xc9, 0x49, 0x6e, 0x42, 0x2c, 0x06, 0x03, 0x6f, 0xe4, + 0xa4, 0xef, 0x14, 0x5c, 0xc8, 0x0d, 0x74, 0xa5, 0xaf, 0x13, 0x4b, 0x01, 0x05, 0xb0, 0x17, 0x1e, 0xd8, 0x78, 0x02, + 0x89, 0x3c, 0xbf, 0x5e, 0xd4, 0x89, 0x0e, 0x07, 0xbf, 0x9f, 0xaf, 0x14, 0x07, 0xf0, 0x5d, 0x82, 0x7c, 0x71, 0xde, + 0x48, 0xf0, 0x0f, 0xb0, 0xc3, 0xd9, 0xb9, 0xbf, 0xc1, 0x5c, 0xc2, 0x92, 0xec, 0x28, 0xe0, 0xb3, 0x02, 0xab, 0x9b, + 0x80, 0x8b, 0x04, 0xc1, 0x41, 0x5b, 0x2c, 0x17, 0x04, 0x87, 0x34, 0x0a, 0x15, 0xf3, 0x21, 0x3f, 0x37, 0x9b, 0x92, + 0x28, 0x92, 0xe1, 0xe7, 0xd7, 0xe0, 0x32, 0x23, 0x9c, 0xe2, 0x63, 0x4d, 0x95, 0x0f, 0x75, 0x5e, 0x8c, 0x74, 0x02, + 0x0c, 0x6f, 0xa6, 0x21, 0xda, 0x3f, 0x46, 0x8d, 0x92, 0xca, 0x3d, 0x0b, 0x97, 0xc6, 0xd9, 0x10, 0x2e, 0xf3, 0x6f, + 0xb2, 0xcc, 0x6b, 0x29, 0x96, 0x57, 0x36, 0x65, 0xc1, 0xf9, 0x1e, 0xd6, 0x71, 0xe4, 0xee, 0xb3, 0x5e, 0x59, 0x72, + 0x88, 0x76, 0xcb, 0x47, 0x67, 0x39, 0xa0, 0x57, 0x71, 0x75, 0xe3, 0x14, 0xc4, 0x91, 0x97, 0x97, 0x91, 0xca, 0x70, + 0x3c, 0x95, 0x04, 0x1c, 0xa9, 0xa7, 0xf8, 0xbf, 0x29, 0xe1, 0x1d, 0x04, 0x83, 0x30, 0x76, 0x0f, 0xf5, 0x2b, 0x40, + 0xd1, 0x16, 0x66, 0x07, 0x37, 0x25, 0x6e, 0xe2, 0xc0, 0x28, 0x47, 0x6f, 0x83, 0xf9, 0xd2, 0x12, 0xb4, 0xc2, 0x6a, + 0x46, 0xa0, 0xd5, 0xe7, 0x71, 0xaf, 0x08, 0xfc, 0xd4, 0x85, 0xe3, 0x79, 0x5e, 0x43, 0x77, 0x68, 0x1a, 0xcb, 0x33, + 0x69, 0x4b, 0xc2, 0x40, 0xd2, 0x2c, 0xb4, 0xf1, 0xe3, 0x73, 0x4d, 0x75, 0x3b, 0x8b, 0xe8, 0x7a, 0xbd, 0x0c, 0xa5, + 0x88, 0x58, 0xb4, 0x70, 0x34, 0x27, 0x1b, 0xd0, 0xe9, 0x3e, 0xd9, 0x98, 0x1a, 0x0e, 0x86, 0x90, 0x18, 0xb9, 0x0d, + 0xe3, 0x9c, 0xd8, 0xf0, 0x84, 0x2a, 0xd5, 0x13, 0x3f, 0x45, 0x5b, 0x89, 0xe0, 0x09, 0x95, 0x46, 0x1e, 0x78, 0x54, + 0xd1, 0x1a, 0x90, 0xc3, 0xc3, 0x47, 0xe0, 0x94, 0x6f, 0x30, 0x56, 0x47, 0x28, 0x50, 0x8e, 0x60, 0x4e, 0x91, 0x1f, + 0xee, 0xf0, 0x21, 0x7c, 0x2d, 0x4f, 0x30, 0x53, 0x6b, 0x2f, 0xc7, 0x5c, 0x0f, 0xb9, 0x1d, 0xf2, 0xb0, 0xff, 0xc4, + 0xcb, 0xc8, 0x46, 0x68, 0xf8, 0x91, 0x5f, 0xf5, 0x58, 0x7f, 0x3d, 0xc0, 0x7c, 0x3a, 0xd9, 0x83, 0x09, 0x67, 0x05, + 0x40, 0xfc, 0xd1, 0x55, 0x70, 0x37, 0x68, 0x58, 0x1f, 0x63, 0x12, 0x66, 0x27, 0x0e, 0x87, 0x6f, 0xa5, 0x02, 0x50, + 0x9e, 0x87, 0x19, 0x89, 0x2c, 0x24, 0xf3, 0xf3, 0x72, 0x8a, 0x6d, 0x51, 0xa6, 0xb6, 0xb4, 0x75, 0x0d, 0x38, 0x91, + 0xc5, 0xcd, 0x24, 0x79, 0x0a, 0x35, 0x2a, 0x22, 0x46, 0xc2, 0x2c, 0xd8, 0x7a, 0x99, 0xb0, 0xc7, 0x6f, 0x8c, 0x61, + 0xd4, 0xa6, 0x8d, 0xf4, 0x86, 0xbd, 0xea, 0x4f, 0xd6, 0xef, 0x11, 0x5b, 0x15, 0xe0, 0xbe, 0xa5, 0x1f, 0xa0, 0x48, + 0xe3, 0x96, 0x76, 0xf2, 0xd3, 0x89, 0x04, 0xfa, 0x87, 0x18, 0x36, 0x89, 0x0d, 0x0a, 0x8e, 0x2f, 0xb5, 0x29, 0xde, + 0x06, 0xce, 0x0c, 0xc5, 0x7a, 0xad, 0x67, 0xe0, 0x44, 0x1b, 0x41, 0x2a, 0x74, 0xcf, 0x58, 0x1e, 0x91, 0xa9, 0xf3, + 0x4f, 0x48, 0xcb, 0x16, 0xa6, 0x25, 0x9f, 0xe4, 0x74, 0x24, 0xd9, 0xf9, 0x29, 0x9a, 0xe4, 0x9d, 0xde, 0x25, 0x52, + 0x7c, 0x7d, 0x19, 0x66, 0x2f, 0xff, 0x84, 0x9a, 0x14, 0x22, 0x1d, 0x5c, 0xdd, 0x30, 0x31, 0xd4, 0x0a, 0x8c, 0xea, + 0x78, 0x9f, 0x8a, 0x4c, 0x1c, 0x0f, 0x6a, 0xe6, 0x45, 0x85, 0xc1, 0x13, 0x4b, 0x70, 0x94, 0xca, 0xae, 0xb6, 0xec, + 0x2d, 0x9c, 0x0c, 0x7e, 0x8a, 0x35, 0x49, 0xd5, 0xf1, 0x82, 0xb6, 0x6a, 0x68, 0x0e, 0x5d, 0x33, 0x6f, 0x66, 0xc7, + 0x63, 0xff, 0x2a, 0x61, 0xd1, 0xc0, 0x9a, 0x0e, 0x88, 0x5e, 0x07, 0xfd, 0x9c, 0x16, 0xdc, 0x2f, 0xbc, 0x0e, 0xbc, + 0x11, 0x83, 0x08, 0x0a, 0x66, 0x28, 0xf1, 0x79, 0xb5, 0x40, 0xc6, 0x86, 0x62, 0x92, 0x54, 0xd2, 0xb1, 0x71, 0x65, + 0x94, 0x8d, 0xcb, 0xf4, 0x72, 0xca, 0xdb, 0x2c, 0xe8, 0x21, 0x6f, 0xe5, 0x2b, 0x88, 0x93, 0xc6, 0x31, 0x22, 0x02, + 0x1c, 0x0f, 0x97, 0x39, 0x87, 0xbc, 0x59, 0x6c, 0x41, 0x4f, 0x09, 0xad, 0xc1, 0xcd, 0xce, 0x59, 0x4f, 0xf9, 0x52, + 0x3c, 0x5d, 0x14, 0x97, 0xdd, 0x6f, 0xa0, 0x00, 0x08, 0x03, 0xff, 0x23, 0x09, 0x7d, 0x56, 0x20, 0x63, 0x8e, 0x07, + 0xc9, 0x91, 0xe5, 0xb1, 0x96, 0x47, 0xa0, 0x85, 0x18, 0xa9, 0xde, 0x86, 0xbf, 0xf3, 0x29, 0x5e, 0x68, 0x07, 0x2b, + 0x77, 0x83, 0x20, 0x48, 0x70, 0x00, 0xfc, 0x85, 0xf7, 0xdd, 0xd0, 0x07, 0xef, 0xb7, 0x7b, 0x87, 0xff, 0xa7, 0x39, + 0xb3, 0x8f, 0x18, 0xdb, 0x7e, 0x88, 0x55, 0xdf, 0x25, 0xff, 0xf1, 0xd0, 0xd0, 0x06, 0xe8, 0xe1, 0x03, 0x1b, 0xce, + 0xde, 0xd3, 0x10, 0x6e, 0xdb, 0xa8, 0x02, 0x96, 0x14, 0x86, 0x48, 0x39, 0xa9, 0xa3, 0xfa, 0x22, 0x95, 0xdc, 0x24, + 0xfe, 0x3c, 0x33, 0x50, 0xfd, 0x83, 0x85, 0x5f, 0x83, 0x2f, 0xbb, 0x07, 0x05, 0x66, 0x62, 0x7d, 0x1a, 0x50, 0xaa, + 0xd4, 0x61, 0x7e, 0xf1, 0xd0, 0xfe, 0x1a, 0xb5, 0xab, 0x6c, 0x78, 0x7f, 0xd1, 0x95, 0x82, 0xb0, 0xc5, 0xe5, 0x21, + 0xd7, 0xe6, 0xde, 0x3e, 0xad, 0x5d, 0xed, 0x03, 0xef, 0x0a, 0x11, 0x60, 0xa7, 0xce, 0xe4, 0xe4, 0x19, 0x9f, 0x9a, + 0x40, 0xe7, 0xec, 0xde, 0xfe, 0x66, 0x03, 0x7e, 0x34, 0xc0, 0x76, 0x57, 0xf7, 0xf6, 0x01, 0x0c, 0xca, 0x65, 0xd4, + 0x50, 0x21, 0x31, 0xc4, 0x4b, 0x2a, 0x48, 0x39, 0x8a, 0xce, 0x87, 0xc8, 0x93, 0x43, 0x4c, 0x1b, 0x09, 0xae, 0xab, + 0xb4, 0x3d, 0x72, 0x12, 0xb4, 0x3c, 0xb2, 0x7b, 0x18, 0xb7, 0x51, 0x71, 0x5c, 0x64, 0x34, 0xf2, 0x0c, 0xee, 0x70, + 0xae, 0x23, 0xf4, 0x68, 0x55, 0x0a, 0x90, 0x26, 0x5c, 0x41, 0xfd, 0x3e, 0x9c, 0x8d, 0xb2, 0x87, 0xaa, 0xe5, 0xd8, + 0x4f, 0xe0, 0x35, 0x45, 0xef, 0xc8, 0x9f, 0x5b, 0x99, 0x15, 0xe1, 0xf2, 0xca, 0x62, 0xb2, 0x10, 0xcc, 0xd1, 0x36, + 0x6e, 0x99, 0x74, 0xf0, 0x0c, 0xf5, 0xfc, 0x50, 0xb5, 0x87, 0x15, 0x5f, 0x10, 0xc9, 0x34, 0xc5, 0x9d, 0xc3, 0xaf, + 0x63, 0x7e, 0x55, 0x38, 0x05, 0x72, 0x37, 0x1d, 0x26, 0xc2, 0x35, 0xdb, 0x4d, 0x90, 0x45, 0x9a, 0x0f, 0x15, 0xba, + 0x7d, 0xd6, 0x51, 0x9f, 0xb9, 0xc4, 0xa8, 0x3d, 0x4a, 0x66, 0x7c, 0xc2, 0x76, 0xbb, 0x91, 0x7e, 0xd1, 0xb5, 0x14, + 0x43, 0x24, 0x95, 0x29, 0xa5, 0x4b, 0x69, 0x89, 0x23, 0xb5, 0x0c, 0x65, 0x1c, 0x4a, 0xe8, 0x14, 0x40, 0xdb, 0x78, + 0xc8, 0x4c, 0x22, 0xed, 0x54, 0xfb, 0xac, 0xca, 0x64, 0x8f, 0xc5, 0x91, 0x30, 0x64, 0xe1, 0x99, 0x60, 0x7d, 0x7f, + 0xae, 0xf9, 0x92, 0x02, 0x55, 0x19, 0xac, 0x3b, 0x06, 0x7f, 0x2c, 0xb4, 0x79, 0x29, 0x2f, 0x85, 0x5e, 0x85, 0xa9, + 0x50, 0x5b, 0xbd, 0xb4, 0x4e, 0x1b, 0x42, 0x05, 0xb2, 0x76, 0x96, 0xe8, 0x51, 0x36, 0x38, 0xc8, 0xf1, 0xbf, 0x0d, + 0x22, 0xdb, 0x1e, 0x04, 0xdb, 0x7b, 0xa6, 0x22, 0xf5, 0xbd, 0xd5, 0x77, 0x9b, 0xf1, 0x89, 0x09, 0x81, 0xcb, 0x80, + 0xab, 0xce, 0xc7, 0x6e, 0x6c, 0xc3, 0x1f, 0x11, 0xe0, 0xef, 0x70, 0xe5, 0xa9, 0xf0, 0x55, 0xfa, 0x5a, 0xd9, 0xca, + 0x2b, 0xef, 0x39, 0x05, 0xb6, 0x6d, 0x7d, 0xa5, 0x09, 0x58, 0x31, 0xd0, 0x8b, 0x80, 0x6f, 0x73, 0xf2, 0x03, 0xf9, + 0xbc, 0x0b, 0xed, 0x99, 0x13, 0xb0, 0x19, 0xec, 0xc1, 0x8e, 0xdd, 0x8d, 0xd1, 0x28, 0x35, 0xe1, 0x57, 0xe6, 0xf6, + 0xa3, 0xaf, 0xa5, 0xff, 0xfc, 0x25, 0x86, 0xe8, 0x25, 0x30, 0x85, 0xf3, 0xd7, 0x11, 0xea, 0x0e, 0x59, 0x52, 0xda, + 0x91, 0x6a, 0x14, 0x5d, 0x54, 0x61, 0x5d, 0x0b, 0xb0, 0x42, 0x63, 0xf5, 0x8d, 0xe1, 0xb5, 0x92, 0x74, 0x14, 0x6b, + 0x2d, 0x86, 0xb7, 0xe9, 0xfc, 0xbe, 0x8a, 0x9d, 0x04, 0x2c, 0x60, 0xbe, 0x4e, 0x70, 0x17, 0x19, 0xec, 0x0e, 0xf7, + 0x6c, 0x3f, 0x27, 0x1a, 0x8e, 0x5c, 0x28, 0x80, 0x0a, 0x6f, 0x17, 0xd2, 0xa4, 0x5f, 0xe7, 0x3f, 0x57, 0xc5, 0x77, + 0x4c, 0x2d, 0x39, 0x4c, 0xf4, 0x52, 0xe3, 0x5f, 0xf7, 0xc6, 0x0f, 0xe5, 0xeb, 0xe5, 0x83, 0xbd, 0x10, 0x6e, 0x79, + 0x8e, 0x95, 0x15, 0x51, 0x0d, 0x71, 0x7f, 0xe8, 0x64, 0x46, 0xb9, 0x9b, 0x6b, 0x92, 0xd5, 0x49, 0x5a, 0x05, 0x4f, + 0x7d, 0x95, 0xf1, 0x67, 0x66, 0x94, 0x7b, 0x6e, 0x2c, 0x43, 0x89, 0x74, 0xe0, 0x8b, 0x86, 0xe6, 0x67, 0xa8, 0x8e, + 0x28, 0x9e, 0xab, 0x01, 0x1b, 0x40, 0x69, 0x5e, 0x0f, 0x03, 0x6b, 0x99, 0xba, 0x30, 0xaa, 0x36, 0xa2, 0xa0, 0x04, + 0x53, 0x48, 0x6b, 0x69, 0x4b, 0x2c, 0x50, 0x51, 0xb3, 0xa8, 0xb1, 0xd1, 0xcf, 0x74, 0x58, 0xe3, 0x66, 0x87, 0x7b, + 0x82, 0x19, 0x41, 0x50, 0x45, 0xb6, 0x3e, 0xb4, 0xaa, 0x46, 0x51, 0x3c, 0xf5, 0x73, 0x40, 0x41, 0xf9, 0x8f, 0x2b, + 0x5f, 0xda, 0xe2, 0xb8, 0x63, 0x35, 0xe0, 0x8b, 0xe2, 0xfd, 0x1e, 0xb9, 0x2a, 0x25, 0x36, 0x71, 0x93, 0x5b, 0x34, + 0x65, 0x04, 0xb1, 0xa7, 0x3f, 0x41, 0x95, 0x14, 0x29, 0x5d, 0xc4, 0x0d, 0xad, 0xb9, 0x38, 0x59, 0xa2, 0x0d, 0xf5, + 0xc0, 0xad, 0x6f, 0x64, 0x68, 0xa2, 0x57, 0xfb, 0xf2, 0x8d, 0x42, 0x0c, 0xc2, 0x92, 0x85, 0xbc, 0x62, 0x62, 0xcc, + 0x60, 0xe0, 0x48, 0xd1, 0xb6, 0x51, 0x2e, 0x46, 0x6f, 0xc4, 0x72, 0x75, 0x9c, 0xef, 0x64, 0x3b, 0x8a, 0x4a, 0x67, + 0xdc, 0x2b, 0xd0, 0xe6, 0xa7, 0x6d, 0xff, 0x86, 0xa7, 0xff, 0xa4, 0x26, 0x5c, 0x8f, 0xd0, 0xb3, 0x08, 0x9f, 0x7a, + 0x40, 0x2c, 0x8f, 0x81, 0x14, 0xa6, 0xe7, 0x2f, 0x52, 0x38, 0x46, 0xd2, 0x8d, 0x25, 0xb1, 0xe4, 0x39, 0x4e, 0xf1, + 0x3d, 0x75, 0xbe, 0xa4, 0x03, 0xea, 0xe8, 0xe4, 0x16, 0x12, 0x68, 0x9a, 0x09, 0xc9, 0xe6, 0x13, 0xda, 0xbc, 0x4c, + 0xcd, 0xba, 0x41, 0xf2, 0x96, 0xa7, 0x96, 0xef, 0x54, 0x2c, 0xe3, 0xfb, 0x21, 0x12, 0x42, 0xd6, 0x2b, 0x6a, 0x96, + 0xfc, 0x82, 0x94, 0xed, 0x02, 0xb4, 0x4b, 0x05, 0x61, 0x71, 0xf6, 0x9a, 0x98, 0xfb, 0x4a, 0xa5, 0x1f, 0xca, 0x6b, + 0xa4, 0x3d, 0x1c, 0x02, 0x00, 0xe3, 0x7e, 0x6f, 0xc2, 0xc4, 0xe8, 0x0c, 0x17, 0x4e, 0xd4, 0x52, 0x21, 0x09, 0xdb, + 0x24, 0x65, 0x76, 0x6f, 0xd6, 0xf1, 0xc3, 0x5f, 0x63, 0x38, 0x37, 0x5a, 0x2b, 0xe1, 0x36, 0xd0, 0x55, 0x67, 0xc8, + 0xab, 0x73, 0xc4, 0xde, 0xdc, 0x29, 0x7f, 0x2e, 0x07, 0xa1, 0xd2, 0x6a, 0x3e, 0x5b, 0x85, 0x5b, 0x30, 0x85, 0x27, + 0x5e, 0x13, 0x6c, 0x30, 0x2f, 0xe1, 0x25, 0xa0, 0xc6, 0x20, 0xe3, 0x23, 0x1f, 0x6c, 0x81, 0x95, 0xd5, 0xf8, 0x73, + 0xec, 0xdf, 0x87, 0xb9, 0xdb, 0xb3, 0x68, 0xe3, 0x7a, 0x31, 0x7d, 0x40, 0x49, 0x26, 0x9c, 0x76, 0xb7, 0x60, 0xdd, + 0xd0, 0x4e, 0x4c, 0xa1, 0x51, 0x31, 0x37, 0x20, 0x75, 0xec, 0xc6, 0xa1, 0xb6, 0xa3, 0xf5, 0xe6, 0x23, 0x8a, 0x06, + 0x71, 0x8e, 0xc8, 0xd6, 0x66, 0xbd, 0xb6, 0xb4, 0x5b, 0x18, 0x40, 0x29, 0x58, 0x4e, 0x09, 0xce, 0xbb, 0x72, 0xd1, + 0x2e, 0x0a, 0xb3, 0x05, 0x90, 0xd2, 0x0d, 0x64, 0xc8, 0x23, 0xea, 0x35, 0x99, 0x63, 0xb7, 0xf4, 0xf8, 0xd9, 0x40, + 0xec, 0x47, 0xbf, 0x24, 0xe3, 0xcc, 0xc0, 0xa4, 0xbd, 0x2f, 0x29, 0x79, 0xa2, 0x9c, 0xbc, 0x6a, 0xe4, 0x30, 0x6c, + 0xe9, 0x1d, 0xcb, 0xc3, 0x8c, 0x1e, 0x82, 0x04, 0x99, 0xf7, 0x8e, 0xe9, 0x12, 0x21, 0xbe, 0x87, 0x85, 0x80, 0x69, + 0xb4, 0xfe, 0xb7, 0xda, 0xe5, 0x53, 0x9f, 0xe7, 0x36, 0xed, 0xad, 0x3b, 0x74, 0xc5, 0x95, 0x4b, 0x6e, 0xfd, 0xa8, + 0x9e, 0xa9, 0xda, 0xa9, 0x7c, 0x6f, 0xb5, 0xec, 0xeb, 0x1c, 0xa4, 0xa1, 0x3d, 0xf2, 0x41, 0xbb, 0xd8, 0x58, 0xb6, + 0xa6, 0x59, 0x34, 0xb3, 0x68, 0xe3, 0x58, 0xd9, 0xc5, 0xb7, 0xc4, 0x23, 0x71, 0xc1, 0xdc, 0xc6, 0xa3, 0x32, 0x12, + 0x3b, 0x3c, 0xa2, 0x2d, 0x7c, 0x23, 0xb4, 0x6d, 0x98, 0x8b, 0x8f, 0x13, 0x70, 0xac, 0x2d, 0x9f, 0x96, 0x63, 0x66, + 0xb5, 0x88, 0x32, 0x59, 0x01, 0x8c, 0x8b, 0xda, 0x71, 0x6f, 0x82, 0xa1, 0x0e, 0xc9, 0xc5, 0x1a, 0x84, 0x30, 0xbd, + 0x16, 0xea, 0xcc, 0xab, 0xfc, 0x8a, 0x6c, 0x6d, 0x2c, 0xc2, 0x42, 0xcb, 0xc6, 0xcc, 0x64, 0x4d, 0x0b, 0x60, 0x8d, + 0xa0, 0xd7, 0x6b, 0xb8, 0x7b, 0x6e, 0xa9, 0xfc, 0x19, 0x1c, 0xb9, 0xf8, 0x18, 0xcc, 0xc7, 0x5e, 0xa5, 0xa4, 0xa9, + 0x87, 0xcf, 0x13, 0xcd, 0x08, 0x8e, 0x5b, 0xe5, 0x0d, 0xb5, 0x67, 0xc3, 0xff, 0x81, 0xaf, 0xe1, 0x73, 0x4e, 0x6e, + 0x85, 0x71, 0x70, 0x66, 0xed, 0x8b, 0x77, 0x75, 0x8c, 0x98, 0x45, 0x8c, 0xf1, 0x25, 0x6b, 0x4a, 0xb9, 0xf9, 0x2c, + 0xd6, 0x47, 0x50, 0x04, 0x96, 0xaf, 0x31, 0x19, 0x21, 0x1c, 0x2c, 0x6e, 0x34, 0x19, 0x62, 0x03, 0xdd, 0x9b, 0x7b, + 0x40, 0x0c, 0x06, 0xe0, 0x21, 0xce, 0x05, 0x59, 0xe8, 0x00, 0xb2, 0xfc, 0x01, 0x12, 0x08, 0x49, 0x60, 0x81, 0x22, + 0x21, 0x23, 0xaf, 0x5a, 0x87, 0x9a, 0x97, 0xb3, 0xcb, 0x0c, 0x17, 0x10, 0x0c, 0x5b, 0xb9, 0x4b, 0xab, 0x51, 0x9b, + 0xed, 0x2d, 0x96, 0x81, 0xde, 0x9e, 0x35, 0x95, 0xa4, 0x48, 0xf9, 0xb5, 0xe9, 0x18, 0xff, 0x78, 0xc8, 0x56, 0x74, + 0xae, 0x18, 0xc3, 0xfd, 0x48, 0x9e, 0xdd, 0xf9, 0xcb, 0xc2, 0x72, 0xb1, 0x1e, 0x4a, 0x3d, 0x34, 0x66, 0x17, 0x0b, + 0x1d, 0xb6, 0x45, 0xc3, 0x22, 0x52, 0xff, 0x24, 0xbc, 0x1e, 0xdc, 0xa3, 0xa8, 0x9c, 0x4c, 0xf0, 0x84, 0xda, 0xb9, + 0xb4, 0x6e, 0x04, 0xde, 0xa5, 0x3c, 0x9f, 0xa6, 0x60, 0x4b, 0xe3, 0x52, 0xa1, 0x94, 0x9d, 0x19, 0xd3, 0xa8, 0x93, + 0xf3, 0xd2, 0x1a, 0xeb, 0x36, 0x69, 0xc1, 0x18, 0x07, 0xa1, 0xfe, 0x74, 0xd6, 0x6f, 0xfe, 0x2d, 0x3f, 0x13, 0x52, + 0x39, 0x97, 0xdc, 0x3f, 0x64, 0x5a, 0xd5, 0xd4, 0x12, 0x68, 0x26, 0xd0, 0x0c, 0x7e, 0x2d, 0x90, 0xcf, 0x43, 0xb8, + 0x67, 0xfa, 0x2c, 0xc4, 0xfd, 0x20, 0x26, 0x1c, 0xb4, 0xf1, 0x86, 0x5e, 0xa3, 0x44, 0xea, 0xbf, 0x25, 0x03, 0x3a, + 0xb9, 0xc5, 0x42, 0xa9, 0x25, 0x89, 0xf3, 0xb5, 0x48, 0x75, 0xe7, 0xfb, 0xb8, 0x8e, 0x72, 0x41, 0x94, 0x74, 0xae, + 0x03, 0xdc, 0x27, 0x94, 0x73, 0x5a, 0x23, 0x6a, 0x24, 0xac, 0xd9, 0x4a, 0xe1, 0xd7, 0xe0, 0x41, 0x20, 0x3a, 0x80, + 0x84, 0xfd, 0xe1, 0xd5, 0xf6, 0x9a, 0xd9, 0xf9, 0xa0, 0x90, 0x05, 0xe2, 0x52, 0xb7, 0xdd, 0x62, 0x27, 0x21, 0x00, + 0xd1, 0x6d, 0x12, 0x0c, 0x14, 0xd4, 0x8e, 0xd3, 0x6f, 0xd0, 0xd0, 0x3b, 0xad, 0xec, 0xdd, 0xdd, 0x84, 0xa2, 0x08, + 0x21, 0x01, 0x12, 0x7b, 0xa0, 0xd2, 0x50, 0x10, 0x45, 0xcb, 0x41, 0x44, 0x28, 0xb1, 0xfb, 0xb8, 0x17, 0xa2, 0x82, + 0x1b, 0xe9, 0x88, 0x34, 0x62, 0xe8, 0x15, 0x6c, 0x88, 0x80, 0x40, 0x95, 0x87, 0x91, 0xc6, 0x2f, 0x09, 0x57, 0xb7, + 0x82, 0x4e, 0xd4, 0xc5, 0x9c, 0xb2, 0xb5, 0xf7, 0x20, 0x86, 0xe7, 0xb6, 0x92, 0x3e, 0x09, 0x42, 0xf4, 0x29, 0x98, + 0x43, 0x99, 0x7f, 0xca, 0x18, 0x63, 0x34, 0x90, 0xb3, 0x7d, 0x11, 0x22, 0x32, 0xb1, 0x9c, 0x51, 0x06, 0xa6, 0xd0, + 0x11, 0xb9, 0x44, 0x86, 0xfe, 0xe4, 0xe6, 0x8b, 0xda, 0x93, 0x1a, 0xc7, 0x75, 0xac, 0x5e, 0xaa, 0x67, 0x0d, 0xb6, + 0xa1, 0xf8, 0x47, 0xf2, 0xd8, 0x1c, 0x26, 0xe5, 0x17, 0x43, 0xd4, 0xe5, 0xec, 0xb0, 0xde, 0x43, 0x16, 0xab, 0xa2, + 0x01, 0x60, 0xb5, 0x5b, 0x61, 0x9d, 0x67, 0xa6, 0x7e, 0xa7, 0xcb, 0x1b, 0x5b, 0x5b, 0xb8, 0x45, 0x5d, 0xa8, 0x86, + 0x82, 0xf2, 0x6a, 0x50, 0x7f, 0xc2, 0xe8, 0x2f, 0x4f, 0x25, 0xe6, 0x19, 0x21, 0x99, 0xa7, 0xee, 0x1d, 0x7f, 0x09, + 0x8f, 0xc3, 0x96, 0x70, 0x75, 0xaa, 0xdb, 0x7f, 0xa9, 0xe2, 0xc9, 0xcc, 0xad, 0x46, 0xbe, 0x71, 0x0b, 0x85, 0x62, + 0x2f, 0x57, 0x23, 0xba, 0x0f, 0xad, 0xb2, 0x5f, 0xf6, 0x91, 0x6c, 0x84, 0x39, 0xcc, 0xe7, 0x63, 0x9f, 0x06, 0x1e, + 0x9f, 0x7b, 0xea, 0x78, 0x3b, 0xc0, 0x4d, 0x81, 0xcd, 0xd6, 0x81, 0xf0, 0x7c, 0x40, 0xf7, 0xd9, 0xa8, 0xc9, 0xba, + 0xd7, 0x45, 0x01, 0x62, 0x0b, 0x83, 0x2b, 0xad, 0x7f, 0xe4, 0x45, 0xd6, 0x17, 0x55, 0xa0, 0xed, 0x97, 0xe9, 0xbe, + 0x28, 0x0c, 0x0d, 0x4f, 0xbb, 0x8d, 0xd8, 0x63, 0x07, 0xcd, 0x92, 0xd6, 0x30, 0x79, 0x25, 0x1d, 0xe4, 0x6f, 0x62, + 0xb2, 0x48, 0x94, 0xbf, 0xfd, 0x35, 0x39, 0xc9, 0x5d, 0x6f, 0x76, 0x7b, 0x29, 0x6a, 0x2a, 0x4c, 0xfd, 0x5d, 0xfb, + 0xb0, 0x52, 0xff, 0x95, 0x7e, 0xb9, 0x0a, 0x75, 0x47, 0xd6, 0x82, 0x44, 0x4e, 0xc3, 0x90, 0x6b, 0x75, 0x58, 0x73, + 0xaa, 0xf3, 0x6c, 0x9d, 0xb5, 0x1d, 0x3e, 0x81, 0x9b, 0x25, 0x67, 0x09, 0x53, 0xf1, 0xa6, 0x26, 0x04, 0x87, 0x81, + 0xa0, 0x30, 0x5c, 0x14, 0x87, 0x48, 0x58, 0xbc, 0xd9, 0xe1, 0x85, 0xd3, 0x65, 0xb0, 0xf1, 0xd5, 0x7e, 0xa1, 0xcc, + 0x33, 0xb6, 0x0b, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x18, 0x35, 0xc0, 0xea, 0x9f, 0xf0, 0xf1, 0x7b, 0x12, 0xb6, 0x1e, + 0x74, 0x49, 0x6a, 0xd9, 0x54, 0x4a, 0x54, 0x5b, 0xc6, 0x35, 0xd6, 0x50, 0x71, 0xed, 0xf0, 0xc8, 0xea, 0x0c, 0xfd, + 0x47, 0xe7, 0x8b, 0xc4, 0x73, 0x48, 0x27, 0x8f, 0x56, 0x82, 0x68, 0x71, 0xcb, 0xba, 0xf5, 0xa1, 0xaf, 0xb9, 0x1c, + 0x85, 0x6d, 0x34, 0x94, 0xd2, 0x45, 0xbc, 0xa4, 0x76, 0x1d, 0x94, 0x81, 0xf4, 0x70, 0x65, 0xa2, 0xb3, 0x0f, 0xd4, + 0xb0, 0xee, 0x40, 0xe3, 0x4d, 0x8f, 0x29, 0xb4, 0xb1, 0xab, 0x16, 0xf3, 0x8a, 0xa9, 0x53, 0x74, 0x4b, 0x6c, 0x09, + 0xec, 0xae, 0xcb, 0xe1, 0xd6, 0xf4, 0x25, 0x10, 0x53, 0x4a, 0xc4, 0xb7, 0x5c, 0x6a, 0xee, 0xba, 0x8e, 0xe2, 0x13, + 0xb6, 0x42, 0x4b, 0xd6, 0xad, 0xc3, 0x6d, 0xac, 0xf5, 0x5a, 0x10, 0x52, 0xff, 0x52, 0x8b, 0x70, 0xf0, 0xea, 0x82, + 0x65, 0x5b, 0x7c, 0x74, 0xc2, 0x86, 0x16, 0x6d, 0x7b, 0x54, 0x41, 0x8b, 0x1d, 0x55, 0xe3, 0xa5, 0xcd, 0x5c, 0xe2, + 0x6a, 0x26, 0xc6, 0x37, 0xf4, 0xdb, 0x14, 0x07, 0x96, 0x9d, 0x15, 0xa0, 0xf1, 0xe0, 0xa4, 0xb7, 0x22, 0x2f, 0x35, + 0x3b, 0xa8, 0x99, 0x51, 0xcb, 0x67, 0x9a, 0x48, 0xeb, 0x05, 0xac, 0x11, 0xda, 0x5a, 0x7e, 0xe0, 0x8a, 0x13, 0x09, + 0xb6, 0x65, 0xfa, 0x7f, 0x98, 0x92, 0x56, 0x62, 0x47, 0x00, 0xcf, 0xb8, 0x8b, 0xfe, 0x81, 0x66, 0x05, 0x30, 0xa6, + 0x60, 0x26, 0x14, 0xf2, 0xb3, 0xe1, 0x08, 0x19, 0xdb, 0x3f, 0x69, 0x1f, 0x5b, 0x76, 0x73, 0x80, 0x00, 0x47, 0x96, + 0x81, 0x71, 0xef, 0x55, 0x2a, 0xda, 0xd3, 0x19, 0x8e, 0x51, 0xd5, 0xd2, 0x9a, 0xfb, 0x95, 0xaa, 0x24, 0x33, 0x60, + 0x37, 0x2f, 0x9a, 0xf6, 0xda, 0x22, 0x97, 0x28, 0xce, 0x90, 0xd5, 0xa9, 0x22, 0xb3, 0x30, 0xd6, 0xae, 0x92, 0x05, + 0x11, 0x1f, 0xfb, 0xc2, 0x19, 0xff, 0xd3, 0x94, 0xa0, 0xfc, 0xb8, 0xaf, 0xe9, 0xa4, 0x42, 0xa5, 0xb0, 0x8f, 0xcb, + 0x69, 0x7c, 0xc5, 0xc0, 0xa4, 0x02, 0x1b, 0x1a, 0xcc, 0x8f, 0x9b, 0x60, 0x50, 0x75, 0x00, 0x8f, 0x6e, 0x1a, 0xc5, + 0x5b, 0x06, 0xdf, 0x94, 0x2e, 0xb4, 0x1c, 0xe5, 0xa8, 0x1c, 0x70, 0xe6, 0xc8, 0xad, 0xc9, 0x4a, 0x04, 0x57, 0xd6, + 0x0e, 0x52, 0x54, 0x60, 0xb8, 0xb3, 0x6a, 0x90, 0xe6, 0xd2, 0x23, 0x25, 0xe3, 0xaf, 0x0b, 0xd0, 0x02, 0x08, 0xc3, + 0xca, 0xbf, 0xdc, 0x2c, 0xe3, 0x15, 0xca, 0x4a, 0xe9, 0x54, 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x7a, 0x3a, 0xe1, + 0x8d, 0xe7, 0x88, 0x73, 0x41, 0x50, 0x3b, 0xd5, 0x7c, 0x6f, 0x30, 0x0c, 0xea, 0xa4, 0x33, 0x40, 0x3e, 0x6a, 0x1a, + 0x4c, 0x78, 0x6d, 0xc9, 0xd1, 0x8b, 0xb8, 0xae, 0xc0, 0x72, 0x62, 0x67, 0x57, 0x09, 0x20, 0x97, 0xd6, 0xc2, 0x0e, + 0x32, 0x30, 0x96, 0xf1, 0xc7, 0x40, 0xee, 0xf8, 0xf4, 0x49, 0x69, 0xd9, 0x23, 0xeb, 0x95, 0x0d, 0x17, 0x9f, 0x7c, + 0x32, 0x7a, 0x83, 0xa5, 0xa2, 0xc9, 0xfd, 0x67, 0x63, 0x41, 0xdf, 0xc9, 0x06, 0x63, 0x2d, 0x3a, 0x07, 0x51, 0xae, + 0x42, 0x3b, 0xf2, 0x55, 0x59, 0x97, 0x05, 0xd9, 0xbe, 0x01, 0x29, 0x3f, 0xa7, 0x15, 0xa1, 0x54, 0x0b, 0x2a, 0x79, + 0x87, 0x55, 0x5c, 0x10, 0x42, 0xa9, 0x01, 0x07, 0x65, 0x08, 0x70, 0x94, 0x71, 0x77, 0xa7, 0x91, 0x00, 0x90, 0x8a, + 0xa1, 0x60, 0xce, 0x5c, 0xd6, 0xde, 0xe2, 0x02, 0x5b, 0x9c, 0x33, 0x73, 0x8d, 0xe1, 0x79, 0x2d, 0xcc, 0xd7, 0x1c, + 0x2b, 0x12, 0xc8, 0xda, 0x72, 0xba, 0x16, 0x5d, 0xaa, 0xa7, 0x47, 0x43, 0x81, 0xcc, 0x4a, 0x72, 0xee, 0xe5, 0xf3, + 0x0a, 0xa1, 0x95, 0xe4, 0xbf, 0x59, 0x62, 0x03, 0xc6, 0x38, 0xb1, 0x7f, 0x7c, 0xa1, 0x42, 0x7e, 0xe4, 0x71, 0xe3, + 0x90, 0x1f, 0x87, 0x13, 0x9c, 0x52, 0x02, 0x06, 0xb5, 0xf6, 0x39, 0x67, 0x7a, 0x63, 0xce, 0x44, 0x4c, 0x9c, 0xf0, + 0xf2, 0x3d, 0x7c, 0x64, 0xc0, 0x28, 0x45, 0xdb, 0x41, 0x45, 0xca, 0xb4, 0x02, 0x48, 0x68, 0xda, 0x1e, 0x5a, 0xaf, + 0xc5, 0xa4, 0xac, 0x98, 0xe2, 0x9a, 0xe6, 0x8a, 0xb7, 0xac, 0x1d, 0x35, 0xb5, 0x6f, 0x3c, 0x93, 0x78, 0x88, 0xe3, + 0xe7, 0x89, 0xaf, 0x13, 0x24, 0x84, 0x48, 0xa9, 0xf0, 0x17, 0x67, 0x5b, 0x3d, 0x7e, 0x49, 0xc5, 0xbd, 0xf0, 0x01, + 0x74, 0x8c, 0xa1, 0x31, 0x9b, 0x0a, 0x71, 0x43, 0x36, 0x43, 0xe2, 0xa8, 0x73, 0x23, 0xd3, 0xdd, 0x66, 0xd5, 0xe1, + 0xc3, 0xc9, 0xf2, 0xd3, 0xec, 0xb1, 0x17, 0x23, 0xc8, 0x60, 0xad, 0xd3, 0x8a, 0xdb, 0xe1, 0xb7, 0xff, 0x5b, 0xae, + 0x48, 0x8f, 0xea, 0xda, 0x22, 0xd1, 0xf9, 0x15, 0x12, 0x4c, 0x8b, 0xa4, 0xc8, 0xea, 0x5d, 0xca, 0x64, 0xdb, 0x2b, + 0x36, 0x5e, 0xcb, 0xe0, 0xb2, 0xb0, 0x38, 0x15, 0xf3, 0xcb, 0x5e, 0x8b, 0xc9, 0xae, 0xaf, 0x8b, 0xaf, 0xca, 0xcc, + 0x39, 0x56, 0x9e, 0x21, 0x8c, 0x85, 0xbd, 0x2e, 0x68, 0x53, 0x5a, 0xd8, 0x74, 0x50, 0x3d, 0x86, 0x29, 0xe3, 0xd1, + 0x6b, 0x47, 0x42, 0x7a, 0xa8, 0x75, 0xff, 0x26, 0xaf, 0xaf, 0xa3, 0xc2, 0x00, 0x10, 0x97, 0x22, 0x2c, 0x3c, 0x9e, + 0xc1, 0xe0, 0x12, 0x83, 0xc2, 0x3b, 0xec, 0xf4, 0xe2, 0x1a, 0xce, 0x3b, 0x37, 0xae, 0xd4, 0x72, 0x8a, 0x2d, 0x1d, + 0x27, 0x5f, 0x48, 0xcf, 0x7a, 0x45, 0x81, 0xbe, 0xa5, 0x66, 0x2d, 0x6e, 0xcd, 0x69, 0x0a, 0xc5, 0x90, 0xb2, 0xab, + 0xf6, 0x74, 0xef, 0xd4, 0xb5, 0x3d, 0x3b, 0x1f, 0xd6, 0x35, 0x45, 0xbb, 0x92, 0xa8, 0xf4, 0x1c, 0x91, 0x18, 0x2b, + 0x86, 0x76, 0xae, 0xad, 0xeb, 0xa2, 0x8e, 0x6a, 0xa8, 0xd6, 0x35, 0x46, 0xaa, 0x6e, 0x29, 0xd5, 0xbf, 0xd4, 0x7a, + 0x5c, 0x7a, 0x6d, 0x30, 0xf4, 0x9e, 0x3c, 0x8a, 0x97, 0x89, 0xba, 0x94, 0xdb, 0x4b, 0x9f, 0xea, 0x75, 0xbb, 0x7d, + 0xeb, 0xbb, 0xff, 0x53, 0xd0, 0xd6, 0xc5, 0x37, 0xf1, 0x3f, 0xc8, 0xff, 0x67, 0x0f, 0x18, 0x5b, 0x7c, 0x7c, 0x38, + 0xae, 0xb4, 0x59, 0x57, 0x36, 0x39, 0x25, 0x8f, 0x9d, 0x6f, 0xfa, 0x8a, 0xa5, 0x83, 0xba, 0xbb, 0x3b, 0x39, 0x0b, + 0x0e, 0x9b, 0x33, 0x47, 0x30, 0x50, 0x94, 0xc9, 0xcd, 0x95, 0xd1, 0xa6, 0xeb, 0x74, 0xa9, 0xc3, 0x2f, 0x4b, 0x93, + 0x90, 0xbd, 0xc6, 0x4b, 0x8c, 0x60, 0x9e, 0x4b, 0x99, 0xd8, 0x02, 0x5e, 0x39, 0x43, 0x51, 0x0f, 0x1d, 0x5b, 0x4a, + 0x30, 0x65, 0xd5, 0x20, 0x3e, 0xcb, 0x14, 0xcf, 0x51, 0x65, 0x1a, 0xd5, 0x73, 0xf7, 0xa6, 0x07, 0x8c, 0xc8, 0xc8, + 0xd9, 0xaf, 0x32, 0xeb, 0x42, 0x07, 0xeb, 0xf6, 0x6c, 0x7f, 0xc4, 0xb3, 0x52, 0x62, 0xc0, 0xbd, 0xb3, 0x01, 0xb1, + 0x43, 0x63, 0x95, 0x43, 0xa1, 0xf8, 0xc7, 0xad, 0x70, 0x99, 0xa8, 0xcf, 0x78, 0xcb, 0x5e, 0xb2, 0xb8, 0x0d, 0xcd, + 0xac, 0x43, 0xbe, 0x33, 0x15, 0x44, 0xec, 0x5d, 0xa7, 0xea, 0x39, 0x42, 0xd6, 0x94, 0x7a, 0xfc, 0x59, 0xa2, 0x2c, + 0x8d, 0xa8, 0xc4, 0xd1, 0xa8, 0x1a, 0x0b, 0xff, 0x77, 0xe6, 0x12, 0xdd, 0xc9, 0xfe, 0x19, 0x61, 0xe6, 0xbe, 0x22, + 0x56, 0x2e, 0xe1, 0x84, 0xe9, 0xd5, 0x36, 0x9d, 0x15, 0x22, 0x28, 0xe0, 0xf3, 0x45, 0xef, 0xcd, 0xa6, 0x2e, 0x04, + 0x8d, 0x77, 0x79, 0xde, 0x85, 0xf9, 0x8c, 0xdc, 0x08, 0xcd, 0x34, 0xac, 0x4d, 0x89, 0x72, 0x10, 0xb8, 0xe8, 0x09, + 0x34, 0xe7, 0x32, 0x30, 0xc1, 0x34, 0x2f, 0xb6, 0x7e, 0xd2, 0xd6, 0x99, 0x1e, 0x48, 0x43, 0x8c, 0x5a, 0x64, 0x9e, + 0xde, 0x95, 0xa6, 0x8f, 0xe9, 0xac, 0xd2, 0x3a, 0x6b, 0x03, 0x2b, 0x7e, 0x40, 0x31, 0x13, 0x41, 0xab, 0x97, 0x24, + 0xa9, 0xa0, 0x39, 0xb4, 0xe8, 0x65, 0xaf, 0x3a, 0x49, 0x41, 0xdd, 0xa9, 0x25, 0xe3, 0x82, 0xb0, 0xaf, 0x6d, 0xf7, + 0x84, 0xcc, 0x51, 0xb4, 0x41, 0x9a, 0x92, 0x4b, 0xbe, 0x47, 0x5c, 0x65, 0x3c, 0xff, 0xbc, 0x50, 0xf8, 0x02, 0x58, + 0x6e, 0x7f, 0x57, 0x96, 0xc3, 0xa2, 0x2e, 0x16, 0xbf, 0x9c, 0x80, 0x35, 0xf2, 0x8f, 0xe1, 0xfe, 0x28, 0x20, 0x1a, + 0x7e, 0x56, 0xb0, 0x3b, 0x68, 0xb3, 0x5f, 0x8c, 0xb3, 0xdd, 0xc7, 0xbd, 0xc5, 0x6e, 0xb8, 0xec, 0xf8, 0xcb, 0x27, + 0xeb, 0xf6, 0xb4, 0x07, 0xae, 0x0d, 0x83, 0xdb, 0x5f, 0x9c, 0xbf, 0xa6, 0xc1, 0xf3, 0x2d, 0x63, 0x37, 0x5b, 0xf9, + 0x90, 0xdf, 0xa3, 0xdc, 0xa9, 0xcb, 0xe5, 0x52, 0xd4, 0x10, 0x90, 0x6a, 0xe6, 0x9c, 0xb8, 0x7e, 0x52, 0x90, 0x16, + 0x68, 0x61, 0x4a, 0x47, 0xb7, 0x24, 0xde, 0x8b, 0x86, 0xac, 0x37, 0x17, 0x60, 0xd3, 0x6d, 0x2f, 0x90, 0x4a, 0x8a, + 0x99, 0x22, 0x2d, 0x26, 0x14, 0x3f, 0xe7, 0xa8, 0x93, 0x3b, 0xb8, 0x2f, 0xa1, 0x4d, 0x64, 0x58, 0x77, 0x93, 0x71, + 0xfe, 0x54, 0xed, 0x09, 0x3d, 0x6e, 0x18, 0xab, 0x43, 0x7e, 0x8b, 0x34, 0xa0, 0xf7, 0xe3, 0x99, 0x14, 0xd9, 0x0f, + 0x83, 0x02, 0xf8, 0xd4, 0x55, 0x40, 0xb5, 0x40, 0xbf, 0xe5, 0xe3, 0x89, 0x4c, 0x19, 0xc4, 0xa8, 0xec, 0x0d, 0xd0, + 0x48, 0x50, 0x64, 0x9b, 0xb2, 0x78, 0x3f, 0x2d, 0x08, 0xe8, 0x43, 0x09, 0x9d, 0xe9, 0x93, 0x0c, 0x11, 0xd5, 0x15, + 0x3c, 0xcc, 0xe9, 0x4e, 0xf8, 0xa6, 0xce, 0x87, 0xcf, 0x9d, 0xb1, 0xe7, 0x2d, 0xed, 0x0a, 0x5b, 0x86, 0x69, 0x68, + 0xa8, 0x82, 0x71, 0xe8, 0x5e, 0xb4, 0xf4, 0x14, 0xb7, 0xa1, 0xe4, 0xe3, 0xf1, 0xe7, 0xf2, 0xcb, 0x44, 0xd4, 0xdf, + 0x26, 0x32, 0xcc, 0x08, 0x7a, 0x66, 0x51, 0x2f, 0xae, 0x70, 0x61, 0x74, 0xba, 0x6a, 0x20, 0x68, 0x79, 0xbf, 0xad, + 0x07, 0xd7, 0xf9, 0x31, 0xdc, 0x38, 0x57, 0x89, 0x36, 0x4e, 0xe3, 0xde, 0x6f, 0x50, 0x5c, 0x2e, 0x71, 0xd0, 0xe5, + 0x05, 0x12, 0xdf, 0x07, 0xd7, 0x76, 0x59, 0xed, 0x6d, 0xaa, 0xf9, 0xcb, 0x7a, 0xe5, 0x0d, 0x09, 0x3b, 0x6f, 0x12, + 0x0e, 0xa4, 0x84, 0x0c, 0x27, 0x1f, 0x91, 0x5c, 0xd8, 0xa0, 0x4b, 0x3e, 0xde, 0xd2, 0xd0, 0x51, 0xc3, 0x8a, 0x68, + 0x17, 0x7e, 0xc3, 0x8f, 0x75, 0x5b, 0x88, 0x20, 0x6e, 0xb0, 0x4c, 0x00, 0xcf, 0x48, 0xe6, 0x44, 0x56, 0x75, 0x98, + 0xc0, 0x34, 0x97, 0x30, 0x0d, 0xec, 0xb6, 0x01, 0x34, 0x3e, 0x99, 0x94, 0xb8, 0x02, 0xdd, 0x2c, 0xd5, 0xce, 0xab, + 0x92, 0x8c, 0xfd, 0x85, 0xa0, 0x9d, 0xeb, 0x0f, 0x8f, 0x32, 0x2f, 0xb7, 0x9b, 0x5d, 0xa4, 0x79, 0x39, 0xc5, 0xd0, + 0x0e, 0x64, 0x76, 0x35, 0x0c, 0x99, 0xba, 0x4b, 0xea, 0x3c, 0x38, 0xa9, 0x2e, 0x0c, 0xc2, 0x21, 0x5c, 0x91, 0xa6, + 0x35, 0x17, 0x84, 0x59, 0x74, 0x6b, 0x0a, 0xef, 0x76, 0xc0, 0xd5, 0x12, 0x01, 0x25, 0x88, 0x38, 0xe9, 0x45, 0x87, + 0x55, 0x3c, 0xb8, 0x1b, 0x75, 0x67, 0x90, 0x96, 0x95, 0x8b, 0x95, 0x62, 0x7c, 0xa1, 0xc5, 0x9d, 0x60, 0x5a, 0x05, + 0xf7, 0x7e, 0x20, 0x46, 0x7b, 0xbe, 0x16, 0x4a, 0x1e, 0x63, 0xa4, 0xa2, 0x3c, 0xfa, 0xf6, 0x43, 0x4a, 0x7e, 0xd4, + 0xf0, 0x58, 0x2b, 0x94, 0x2a, 0x76, 0xea, 0xda, 0x05, 0x9d, 0x95, 0x08, 0xbb, 0x2c, 0x13, 0x2f, 0xa1, 0xdf, 0xd5, + 0xb0, 0xdb, 0x32, 0x1b, 0xbb, 0x40, 0xdc, 0x9e, 0x44, 0x4a, 0xe4, 0x60, 0xad, 0xe1, 0x1d, 0xc9, 0xf3, 0x34, 0x78, + 0x5b, 0x72, 0xeb, 0x97, 0x0c, 0xc5, 0xad, 0xb6, 0x60, 0xf1, 0x43, 0x7a, 0x74, 0x44, 0x01, 0xaa, 0x7f, 0xd3, 0x91, + 0x20, 0x71, 0xcb, 0x8c, 0xdf, 0x55, 0xe5, 0xe6, 0xb9, 0xb9, 0xe1, 0x59, 0x62, 0x55, 0xc4, 0xc2, 0xf9, 0xfb, 0x1a, + 0x20, 0x50, 0x48, 0x67, 0x33, 0xd7, 0x3c, 0x12, 0x75, 0xc5, 0xf5, 0xe0, 0x4e, 0x65, 0x4c, 0xdd, 0xa7, 0x23, 0xd5, + 0x1b, 0xee, 0x6a, 0x6c, 0xa9, 0x25, 0xbc, 0xa9, 0xb0, 0xa5, 0x3b, 0xcd, 0x15, 0x5b, 0x5c, 0xe6, 0x2a, 0xb5, 0x9d, + 0xc0, 0xb4, 0x6b, 0x9d, 0xfe, 0x38, 0x86, 0x1a, 0xca, 0x44, 0xdc, 0x26, 0xea, 0xe0, 0xb2, 0x6c, 0x8a, 0x72, 0x97, + 0x09, 0x4e, 0x92, 0x0d, 0xee, 0x80, 0x48, 0xd5, 0xe2, 0x32, 0xc7, 0x4d, 0x1b, 0x22, 0xc5, 0x77, 0xd2, 0x35, 0x45, + 0x52, 0x9c, 0xa6, 0x17, 0x9e, 0x46, 0x56, 0x6e, 0x76, 0x4a, 0x33, 0xe9, 0x1d, 0x52, 0x64, 0x45, 0x21, 0x71, 0xaf, + 0x22, 0x05, 0x0f, 0xad, 0xfa, 0xb3, 0xcc, 0x29, 0xd9, 0xc1, 0xf4, 0x6e, 0xb9, 0xee, 0xef, 0xc3, 0xc7, 0xf3, 0xf5, + 0x48, 0x44, 0x17, 0xc6, 0x57, 0x4a, 0x48, 0x56, 0x72, 0x90, 0x84, 0xbc, 0xe0, 0x90, 0xce, 0x5e, 0x15, 0x09, 0x38, + 0xd2, 0x2b, 0x17, 0x69, 0x5d, 0xb9, 0x56, 0x05, 0xda, 0xc1, 0x72, 0xca, 0xa8, 0x10, 0x33, 0x63, 0x8d, 0xe2, 0xfd, + 0x38, 0xbc, 0x3b, 0x1e, 0xa4, 0x3b, 0x92, 0x4d, 0xcd, 0x5c, 0x77, 0x28, 0x71, 0x19, 0x2a, 0x38, 0x12, 0x27, 0x2a, + 0x87, 0xe0, 0xe8, 0xcc, 0xf5, 0x1e, 0x0b, 0xeb, 0x0a, 0xe6, 0xcc, 0x79, 0x96, 0x07, 0xab, 0xab, 0xf5, 0x17, 0xee, + 0x7a, 0xfd, 0x7a, 0x22, 0xfa, 0x9d, 0x97, 0x9a, 0x6a, 0x80, 0x87, 0x16, 0xdb, 0x75, 0x3c, 0x8d, 0x29, 0xd0, 0x02, + 0xe9, 0xd5, 0x04, 0x45, 0xc3, 0x27, 0xcd, 0x30, 0x07, 0x3d, 0xd5, 0x37, 0x6f, 0xa3, 0x66, 0xb6, 0x65, 0x9a, 0x56, + 0x18, 0x66, 0x97, 0x06, 0xee, 0x4c, 0x72, 0x0d, 0x31, 0x6c, 0xfd, 0x7a, 0xb6, 0x4d, 0xe4, 0x72, 0xdf, 0xb3, 0x5a, + 0x08, 0xa6, 0xe9, 0x98, 0x23, 0xff, 0x3e, 0xc9, 0x61, 0xc2, 0x71, 0x0c, 0x4a, 0x4f, 0xbc, 0x2c, 0xc5, 0x2c, 0x27, + 0x61, 0x65, 0x5d, 0x5d, 0xc0, 0xf5, 0x64, 0x24, 0x02, 0xf1, 0x28, 0xb5, 0x58, 0x7e, 0x00, 0xd7, 0x54, 0x5e, 0xef, + 0x68, 0x63, 0x0f, 0x04, 0x00, 0xcb, 0xf6, 0xcc, 0x49, 0xaf, 0x1a, 0xf9, 0x2a, 0xa6, 0x90, 0x5c, 0xbe, 0x93, 0x4c, + 0x46, 0x04, 0xfb, 0x2a, 0xbd, 0xbf, 0xa0, 0x1f, 0xd4, 0xde, 0x8e, 0x10, 0xd1, 0x8b, 0x84, 0xfd, 0x72, 0x9b, 0x26, + 0x21, 0x0e, 0x5f, 0x98, 0x88, 0x8d, 0x0b, 0xd8, 0x8a, 0xd0, 0x97, 0xc7, 0x56, 0x26, 0xf3, 0xba, 0xeb, 0xf0, 0xfb, + 0x2d, 0x1f, 0xdc, 0x18, 0xc1, 0x24, 0xb2, 0x25, 0x02, 0x0b, 0x91, 0xca, 0x98, 0x28, 0xbe, 0x08, 0x3f, 0x57, 0xfb, + 0xbe, 0x51, 0x4c, 0x25, 0x9b, 0x3d, 0xdf, 0xf1, 0xee, 0x78, 0xfa, 0xae, 0xf5, 0xeb, 0xac, 0x90, 0x21, 0xd3, 0x5e, + 0xf7, 0x0f, 0x00, 0x3d, 0xf3, 0xa6, 0xbc, 0x9d, 0xcc, 0x77, 0x92, 0x76, 0x95, 0x36, 0xef, 0x34, 0xd1, 0xc0, 0xaf, + 0xbf, 0x11, 0x7a, 0xc5, 0x57, 0x9a, 0x88, 0x7e, 0xd5, 0x0b, 0x36, 0xab, 0xa8, 0x90, 0x67, 0xae, 0xc3, 0x9a, 0xf5, + 0xed, 0x1c, 0x9a, 0xbe, 0x29, 0xa5, 0x39, 0x4f, 0x06, 0x53, 0x87, 0xf4, 0x55, 0x46, 0x75, 0x30, 0xa0, 0xb9, 0x83, + 0x0d, 0xd2, 0xdf, 0x00, 0xcf, 0xb9, 0x83, 0x00, 0x27, 0x8a, 0x24, 0x0d, 0xbf, 0x74, 0xf3, 0x2a, 0x9a, 0x3c, 0x8c, + 0x9a, 0x0c, 0xc5, 0x65, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x43, 0x83, 0xa8, 0xb3, 0xf7, 0x88, 0xdd, 0x5e, 0xda, 0x7b, + 0xf0, 0x9f, 0x3e, 0x50, 0xb2, 0x2e, 0x42, 0xc5, 0x60, 0x42, 0xf9, 0x4b, 0xd9, 0x2f, 0x69, 0xcf, 0x4a, 0x57, 0xe6, + 0x42, 0xc1, 0xbc, 0x36, 0xa8, 0xc6, 0x01, 0x2c, 0xa0, 0xbd, 0x48, 0x40, 0xc5, 0x6e, 0x2b, 0x6c, 0xc8, 0x04, 0xdb, + 0x4f, 0x62, 0x5d, 0x89, 0x1f, 0x0a, 0x70, 0xf8, 0x9b, 0x86, 0x90, 0x84, 0x2c, 0xe6, 0x7e, 0x9d, 0x97, 0x6d, 0x5b, + 0xc7, 0x6d, 0xcc, 0xe6, 0x91, 0xbc, 0x8d, 0xb0, 0x9c, 0xf0, 0xe6, 0x7f, 0x98, 0x07, 0xe2, 0xb2, 0xea, 0x6f, 0x6b, + 0xbb, 0xb4, 0xa3, 0xd7, 0x61, 0x58, 0x89, 0xad, 0x62, 0xf9, 0x87, 0xb9, 0xea, 0xb1, 0x03, 0xb8, 0xbf, 0x87, 0xca, + 0xf0, 0x96, 0xe6, 0x86, 0xb7, 0xe3, 0x79, 0xa9, 0x41, 0xf6, 0x99, 0x8a, 0x24, 0x9c, 0xd2, 0xfd, 0x8a, 0x64, 0x48, + 0x13, 0x89, 0x1e, 0x3d, 0xc9, 0x47, 0x1a, 0x0f, 0xab, 0x94, 0x6d, 0xe8, 0xb0, 0xd9, 0xee, 0xa0, 0xf3, 0xf6, 0xb9, + 0xfb, 0xcb, 0xa9, 0xb7, 0x40, 0xb5, 0x4e, 0x61, 0xf3, 0xd2, 0xc3, 0x16, 0x5b, 0xf7, 0x2c, 0xa6, 0x7e, 0x0a, 0xb2, + 0x72, 0x24, 0x1b, 0x62, 0x22, 0xdd, 0x3b, 0x2d, 0x9e, 0x79, 0x94, 0xc0, 0xdd, 0x4d, 0x7d, 0x73, 0xec, 0xe3, 0x79, + 0xc9, 0x1f, 0xb3, 0x33, 0xdc, 0xf3, 0xa1, 0x97, 0xef, 0x59, 0x91, 0x3b, 0x62, 0xa7, 0xa3, 0x78, 0xc8, 0x45, 0x77, + 0x42, 0x59, 0x09, 0xcb, 0xf9, 0xb9, 0x6a, 0xa5, 0x36, 0x06, 0xa5, 0x42, 0x59, 0x96, 0x7b, 0x9f, 0x6c, 0xdd, 0x41, + 0x42, 0x95, 0xef, 0x41, 0x49, 0xe0, 0xf7, 0x49, 0x04, 0x52, 0xfd, 0xa3, 0x54, 0x21, 0x66, 0xcc, 0x4b, 0x33, 0x2f, + 0xd4, 0x9f, 0x50, 0xca, 0x81, 0x87, 0x80, 0x6f, 0x09, 0xb8, 0x34, 0xb4, 0xf5, 0xdf, 0x6d, 0x18, 0xd3, 0xb2, 0x1f, + 0x6b, 0xf4, 0xf7, 0x14, 0xf8, 0xbd, 0x06, 0xee, 0x89, 0x3a, 0x3f, 0x9d, 0x62, 0xf0, 0x68, 0xa1, 0xd7, 0xb7, 0xd3, + 0x7d, 0xc3, 0xd4, 0x78, 0xe5, 0x42, 0xf1, 0xad, 0x4d, 0xe5, 0x8f, 0xa1, 0x76, 0x5d, 0x0b, 0x4d, 0xf6, 0x42, 0x39, + 0x53, 0x8a, 0xb3, 0xc2, 0x9b, 0x06, 0x43, 0x2b, 0x1e, 0x49, 0xb5, 0xc4, 0x39, 0x7b, 0x8f, 0x5d, 0xc5, 0x09, 0xef, + 0x48, 0x03, 0x05, 0x2a, 0x99, 0x05, 0x47, 0x0c, 0x94, 0xf6, 0x65, 0x7d, 0x99, 0xee, 0xf6, 0x63, 0x2d, 0xee, 0xe0, + 0x78, 0x84, 0xaa, 0x22, 0x5f, 0x21, 0x27, 0x1e, 0x39, 0x90, 0x28, 0xf5, 0xfc, 0x26, 0xaa, 0xd0, 0xfc, 0x74, 0xa2, + 0x68, 0x7f, 0x97, 0x0d, 0xad, 0xe8, 0x3f, 0x1b, 0xfe, 0xec, 0x11, 0x20, 0x8f, 0x73, 0xd2, 0xf7, 0x09, 0xb6, 0x4c, + 0x88, 0xc6, 0xe5, 0xd8, 0xb7, 0x35, 0x78, 0x5e, 0x6a, 0xb4, 0x58, 0xf4, 0x72, 0x21, 0xfb, 0x8d, 0xd9, 0x58, 0x89, + 0x39, 0x73, 0xe1, 0x8d, 0x3b, 0xa1, 0xe1, 0x37, 0x0c, 0xa4, 0xf7, 0xb0, 0x9e, 0x84, 0x99, 0x66, 0x01, 0x28, 0x35, + 0xb4, 0xd0, 0x47, 0x8b, 0x9d, 0xeb, 0x3c, 0x39, 0xde, 0xf0, 0xa6, 0x14, 0x01, 0xe3, 0xeb, 0xfb, 0x1b, 0x42, 0x33, + 0x50, 0x24, 0x25, 0x62, 0x3e, 0x01, 0x8c, 0x62, 0x30, 0x6a, 0xaa, 0xd7, 0xe3, 0x01, 0x9f, 0x60, 0x10, 0x5f, 0x6c, + 0x7d, 0x79, 0x33, 0x6e, 0x20, 0xee, 0x86, 0xb3, 0x94, 0x4f, 0xc9, 0x77, 0x23, 0x01, 0x8c, 0x97, 0x7f, 0x02, 0x54, + 0x17, 0x5a, 0x6d, 0xb0, 0xbf, 0x13, 0xdb, 0x71, 0x7e, 0x01, 0x4d, 0xf0, 0x35, 0xd8, 0x05, 0x3f, 0x8e, 0x7f, 0x28, + 0xac, 0x6e, 0xa4, 0xa5, 0x5e, 0x4e, 0x47, 0x7d, 0xb6, 0x99, 0xf9, 0x00, 0x1b, 0xce, 0x37, 0x0f, 0x1b, 0xe5, 0xfa, + 0x8b, 0x09, 0x03, 0xf3, 0xca, 0x09, 0xa5, 0x9b, 0x23, 0x99, 0x5f, 0x32, 0xac, 0xcd, 0x1a, 0xfa, 0x5c, 0x4e, 0x5c, + 0xf2, 0x2d, 0x90, 0x6b, 0xa4, 0xda, 0x6f, 0xf1, 0xf2, 0x1b, 0xa4, 0x1e, 0x96, 0xef, 0x7f, 0x56, 0x4a, 0x17, 0xb1, + 0xa9, 0xcd, 0x7e, 0xe4, 0xb8, 0x4b, 0x9f, 0xcb, 0x93, 0xcf, 0x90, 0xfd, 0xd9, 0x1c, 0xf2, 0x79, 0x7f, 0xb5, 0x7b, + 0xb7, 0xfc, 0x33, 0x9b, 0xed, 0xc5, 0x66, 0xd7, 0xdb, 0xbb, 0xf9, 0x33, 0xf8, 0x3a, 0xfc, 0x1e, 0xc1, 0x6a, 0x6e, + 0x0f, 0x0a, 0x3e, 0x4c, 0xdf, 0xfc, 0xd7, 0x6f, 0xf6, 0x83, 0x81, 0x66, 0x1f, 0xa2, 0x00, 0x57, 0x88, 0xa8, 0x72, + 0x66, 0x5c, 0xc3, 0xae, 0xb8, 0xc7, 0xf6, 0x38, 0xe5, 0x7c, 0x5f, 0x9b, 0x50, 0x6e, 0xb3, 0x98, 0x36, 0x2b, 0x57, + 0x57, 0x38, 0x13, 0xdd, 0xfa, 0x86, 0x5d, 0x08, 0xc9, 0xf2, 0xed, 0x5d, 0xc0, 0x43, 0x31, 0x2a, 0xec, 0xed, 0xb9, + 0xe7, 0xe5, 0xc0, 0x9f, 0xa1, 0xbc, 0xc6, 0x4b, 0xab, 0xdf, 0xfa, 0x5c, 0xec, 0xa1, 0x0f, 0x78, 0x33, 0x7e, 0x2b, + 0xa8, 0xce, 0x7c, 0x16, 0x9a, 0x2c, 0x2e, 0xc4, 0x97, 0xba, 0xc1, 0x25, 0xf4, 0x32, 0xc7, 0x64, 0x03, 0x5f, 0x3a, + 0x5c, 0x55, 0xc8, 0x3c, 0xb4, 0x64, 0x94, 0x47, 0x6c, 0x39, 0x31, 0x73, 0xb7, 0x9a, 0x64, 0x5a, 0x99, 0x1f, 0xdd, + 0xc8, 0xc1, 0x83, 0x12, 0x92, 0x74, 0x65, 0x08, 0xff, 0x18, 0x27, 0xee, 0x45, 0xb0, 0xf1, 0x5e, 0x58, 0x8b, 0x76, + 0xf5, 0x50, 0x35, 0xeb, 0x26, 0x68, 0xd6, 0xa9, 0x1e, 0xef, 0x84, 0xbf, 0xa7, 0x7f, 0x3c, 0xd3, 0x46, 0xf8, 0xf3, + 0x99, 0x56, 0xc2, 0x1f, 0xa7, 0x8a, 0x09, 0x7f, 0x9e, 0xea, 0xcc, 0xd4, 0xfa, 0xc2, 0xbe, 0x7e, 0x63, 0x5f, 0xdf, + 0xd9, 0x63, 0xa0, 0xf6, 0xd0, 0xde, 0xcb, 0x1c, 0xb4, 0x13, 0x7b, 0x5b, 0x6f, 0xc9, 0x21, 0x9f, 0xcb, 0x2a, 0x4b, + 0x36, 0x3f, 0x37, 0xba, 0xfb, 0x9c, 0xca, 0xc2, 0xe3, 0x01, 0xca, 0x1a, 0x8f, 0xa3, 0xba, 0x16, 0x51, 0x31, 0x67, + 0x96, 0xb4, 0x5e, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x4e, 0x1c, 0x43, 0x0e, 0xaa, 0x86, 0x33, 0x52, 0x99, 0x20, 0x7f, + 0x34, 0xfd, 0xd8, 0x28, 0xf7, 0xa2, 0xf1, 0xc2, 0xdd, 0x3d, 0x53, 0x9e, 0xbf, 0x92, 0x46, 0x44, 0xa6, 0x15, 0xf8, + 0xde, 0xc1, 0x34, 0x2c, 0x66, 0x2d, 0x36, 0x3b, 0x20, 0xb3, 0x23, 0x7a, 0x09, 0x05, 0x42, 0xe8, 0xdb, 0x16, 0xfe, + 0xb3, 0x00, 0xa5, 0x62, 0x57, 0x46, 0x89, 0x78, 0x5c, 0x83, 0xa2, 0xd6, 0x5b, 0xd0, 0x20, 0x76, 0x43, 0x99, 0xee, + 0x88, 0x31, 0x87, 0x97, 0x55, 0x5c, 0x41, 0x56, 0xbf, 0x9c, 0x8b, 0x5f, 0xe7, 0xec, 0xe1, 0xf9, 0x46, 0x40, 0x83, + 0xff, 0xd7, 0x64, 0x3b, 0xe8, 0x4f, 0x68, 0x6b, 0x9c, 0x72, 0x49, 0xa5, 0xfd, 0x42, 0xce, 0xdb, 0x73, 0x5f, 0x67, + 0xd7, 0xb7, 0xce, 0x18, 0xc9, 0xcf, 0x39, 0x04, 0x72, 0x57, 0xed, 0xa7, 0xbb, 0x7d, 0x4c, 0x41, 0x56, 0x5d, 0xf7, + 0x9c, 0x60, 0x9d, 0x9d, 0xa9, 0xd4, 0xcd, 0x94, 0xfc, 0xfc, 0xd5, 0xff, 0xb2, 0xbf, 0x4f, 0xc9, 0x87, 0x7d, 0xad, + 0xd7, 0xfc, 0x72, 0x2c, 0xe7, 0x53, 0xaf, 0xf3, 0xf9, 0xfd, 0x17, 0xe5, 0x74, 0x3d, 0xa4, 0xe9, 0x38, 0xdd, 0xf5, + 0x8f, 0xe9, 0x82, 0x7e, 0xe9, 0x3e, 0x9b, 0xfe, 0x7a, 0x4a, 0x3e, 0xe4, 0x1b, 0xbd, 0x7e, 0x72, 0x97, 0x16, 0xff, + 0xa9, 0xe9, 0x72, 0x64, 0x0b, 0x00, 0xe5, 0xf9, 0x51, 0xb2, 0x39, 0x0e, 0x39, 0xd3, 0x3b, 0xd7, 0x15, 0xb6, 0xa8, + 0x5a, 0x0d, 0x8e, 0x5c, 0xac, 0x40, 0x8b, 0x7c, 0xc2, 0x13, 0xd9, 0xf8, 0x06, 0xec, 0x52, 0x66, 0xef, 0xb1, 0x0a, + 0xa4, 0xdb, 0xe6, 0xd3, 0x6c, 0x26, 0xcf, 0x5f, 0xa3, 0x6d, 0x76, 0x0d, 0xcb, 0x4c, 0xda, 0xd2, 0x54, 0x5c, 0x79, + 0xc0, 0x81, 0x03, 0x14, 0x06, 0xab, 0x91, 0x3a, 0x00, 0x46, 0x4e, 0xef, 0x30, 0xf4, 0xd9, 0x38, 0xce, 0xde, 0x6f, + 0x63, 0xc6, 0x52, 0x78, 0xec, 0xc8, 0xa2, 0x19, 0xed, 0xf0, 0x09, 0x37, 0xfd, 0x69, 0x26, 0xd4, 0x8f, 0x06, 0xe0, + 0xc4, 0x59, 0x36, 0x5d, 0x7f, 0xbb, 0x4f, 0x3c, 0xeb, 0x5a, 0xae, 0xac, 0x3f, 0x94, 0xd0, 0xb5, 0x39, 0x3a, 0x93, + 0xdc, 0x25, 0xa8, 0x30, 0xc2, 0x9c, 0xe1, 0xc5, 0x7b, 0xb3, 0x3a, 0xa5, 0x48, 0x7d, 0xa2, 0xd7, 0x82, 0x90, 0xd1, + 0x7f, 0x32, 0x98, 0xc6, 0x91, 0x1c, 0xb9, 0x3e, 0xf6, 0xef, 0x31, 0x43, 0xdb, 0xcc, 0xa8, 0xb7, 0x1a, 0x3b, 0x20, + 0xd2, 0xc0, 0x2a, 0x59, 0x63, 0x7d, 0x4b, 0xfc, 0x6b, 0x90, 0xeb, 0x34, 0x6b, 0x3c, 0xc3, 0xd9, 0x99, 0xb6, 0x27, + 0x3b, 0xdd, 0xcc, 0xdc, 0xaf, 0xb7, 0x3f, 0x8f, 0xdf, 0xdb, 0xef, 0x87, 0x71, 0xe9, 0x48, 0x0b, 0x72, 0xd3, 0x62, + 0xab, 0x7a, 0x6c, 0x9d, 0x4c, 0xcb, 0x0f, 0xd5, 0x8f, 0x0d, 0x0a, 0xc4, 0x18, 0xe7, 0x35, 0xd2, 0x8c, 0xcf, 0xf2, + 0x36, 0x2e, 0xc8, 0x82, 0x0d, 0x71, 0x3e, 0xdc, 0xde, 0x3e, 0x0a, 0xb2, 0x03, 0x4d, 0x7e, 0xf3, 0x0e, 0xdd, 0xd7, + 0x7e, 0xe7, 0x77, 0xa0, 0x98, 0xf5, 0xed, 0x25, 0xd5, 0x06, 0x75, 0x05, 0x7a, 0x03, 0x2e, 0xbf, 0x68, 0x13, 0xe6, + 0xae, 0xe1, 0xbc, 0xfc, 0x19, 0x0b, 0x49, 0x28, 0x5a, 0x29, 0x38, 0x2c, 0x36, 0xcd, 0x28, 0x4a, 0x8b, 0x75, 0xd1, + 0xaf, 0x6d, 0xc6, 0x9b, 0x6b, 0x37, 0x70, 0x6e, 0x10, 0x64, 0x31, 0x6b, 0x45, 0x3f, 0x46, 0xe4, 0x5d, 0xd6, 0xcc, + 0x56, 0xdb, 0x40, 0x0c, 0x2f, 0x71, 0xcd, 0x5a, 0x6c, 0x77, 0xcf, 0x60, 0x40, 0x8f, 0xf8, 0xe8, 0x1c, 0x82, 0x47, + 0x1e, 0x7a, 0x2c, 0x7e, 0x37, 0xa5, 0xc3, 0x3b, 0xc7, 0x5a, 0x0a, 0x91, 0xe5, 0x64, 0xfa, 0xc7, 0xa9, 0xcd, 0xc8, + 0xd3, 0x11, 0x25, 0x43, 0xa2, 0xfa, 0xc6, 0x3e, 0xfb, 0xd1, 0x20, 0xad, 0x3d, 0x9b, 0x35, 0x8e, 0x17, 0x2c, 0xad, + 0x0f, 0x8e, 0x87, 0x71, 0x1c, 0xa4, 0xa8, 0xa9, 0xac, 0xe2, 0x1f, 0x93, 0x61, 0x91, 0xae, 0xd9, 0x7e, 0x57, 0x06, + 0xaf, 0x84, 0x84, 0xae, 0x5c, 0x7b, 0x2d, 0x40, 0xc7, 0x2e, 0x6b, 0xf9, 0x33, 0xa7, 0x0b, 0x01, 0x2a, 0xbf, 0x08, + 0x93, 0x00, 0x43, 0x24, 0xca, 0x13, 0x79, 0xe1, 0x45, 0xd1, 0x47, 0x30, 0x87, 0x66, 0x58, 0x0d, 0xa6, 0xa9, 0xe8, + 0xaf, 0xd7, 0x99, 0x50, 0xc6, 0x01, 0xbc, 0xc8, 0xed, 0xcd, 0xc7, 0x32, 0x74, 0x28, 0xd2, 0x46, 0xce, 0x3c, 0x33, + 0xa7, 0xbc, 0xa1, 0x3e, 0x14, 0xa1, 0xf8, 0x4f, 0x30, 0x48, 0x72, 0x36, 0x00, 0x85, 0xac, 0x3d, 0x8f, 0x00, 0x60, + 0x49, 0x3f, 0x31, 0x03, 0x6f, 0xf8, 0xa7, 0xb3, 0xf1, 0x65, 0x91, 0xb1, 0x5f, 0xfd, 0x9b, 0x4b, 0xd3, 0x2c, 0xdc, + 0x59, 0xd5, 0xb3, 0x7b, 0x8a, 0x20, 0x0a, 0x24, 0x59, 0x28, 0x27, 0xf6, 0x1e, 0xe2, 0x57, 0x06, 0x98, 0x41, 0x48, + 0x06, 0x48, 0xc2, 0x74, 0xa4, 0x75, 0xe6, 0x27, 0xd7, 0x84, 0xad, 0xde, 0x16, 0x4a, 0xb0, 0x88, 0xce, 0xa3, 0xdb, + 0x2a, 0xcd, 0x5a, 0xba, 0x1f, 0xf6, 0xe6, 0x20, 0xe3, 0xe4, 0xcb, 0xca, 0x79, 0xe2, 0x3c, 0x7f, 0x43, 0x22, 0x7b, + 0x11, 0x51, 0x5e, 0x6e, 0x5d, 0x44, 0x7e, 0x05, 0xa5, 0x62, 0x03, 0xa0, 0x1a, 0x09, 0x53, 0x4d, 0xf1, 0xee, 0x17, + 0x77, 0xc0, 0x28, 0x1f, 0x68, 0x4f, 0x28, 0xee, 0x27, 0x2b, 0x63, 0x3d, 0xcc, 0x83, 0xcc, 0x22, 0x2e, 0x57, 0xa3, + 0xcd, 0x4e, 0x68, 0xa4, 0x5e, 0xd1, 0x04, 0x03, 0x1a, 0x96, 0xe1, 0x74, 0x6a, 0xeb, 0x1f, 0x05, 0xcb, 0x6c, 0xba, + 0x4e, 0xcf, 0x71, 0x29, 0x74, 0x5b, 0xf7, 0x49, 0x21, 0x8e, 0x86, 0xd0, 0xed, 0x28, 0x14, 0x46, 0x3f, 0xab, 0xf0, + 0xa2, 0x3e, 0xeb, 0xd7, 0xa2, 0x33, 0xd6, 0x98, 0xa1, 0xab, 0x2e, 0xbb, 0xa1, 0x00, 0x6c, 0xc4, 0xce, 0x10, 0x05, + 0x72, 0x7b, 0xd5, 0x2e, 0xd7, 0x70, 0x2f, 0x62, 0xf2, 0x1f, 0x5a, 0xef, 0x37, 0xda, 0x4f, 0xe0, 0x8f, 0x92, 0xcc, + 0xad, 0x09, 0xac, 0xa9, 0x9c, 0x97, 0xc4, 0x01, 0xd1, 0xe3, 0x7c, 0x3f, 0x08, 0xfe, 0xa4, 0xb5, 0x78, 0x50, 0x6c, + 0x11, 0xd2, 0x4a, 0xa9, 0x13, 0xf5, 0xda, 0x3a, 0x4d, 0xe4, 0x83, 0xc4, 0xa4, 0x62, 0x42, 0x75, 0x5a, 0xfb, 0x69, + 0x5e, 0xab, 0x59, 0xe0, 0x6d, 0xa2, 0x12, 0xaf, 0x30, 0x9d, 0xdb, 0x25, 0x43, 0xd2, 0x1d, 0xc1, 0xa9, 0x2e, 0x2b, + 0x86, 0xbb, 0xdb, 0xd6, 0xec, 0x17, 0x03, 0x5f, 0xd3, 0x35, 0x1c, 0xe3, 0x2e, 0xe8, 0xdc, 0x18, 0x6f, 0x88, 0xed, + 0xc1, 0xe0, 0x61, 0xf5, 0xe4, 0xec, 0xb4, 0x9a, 0x6e, 0x1a, 0x95, 0xb9, 0xb9, 0xd7, 0xd4, 0xd5, 0x42, 0xbf, 0x4a, + 0x60, 0xf9, 0x6c, 0x94, 0x6f, 0xb1, 0x67, 0xae, 0x51, 0x60, 0x6b, 0x89, 0xbb, 0x65, 0xd9, 0xb1, 0x18, 0xbd, 0x1b, + 0x18, 0x15, 0xd6, 0x2e, 0x62, 0xf0, 0xfc, 0x1c, 0xf6, 0xf6, 0xc4, 0x04, 0x42, 0xfd, 0x9b, 0x7a, 0xb2, 0x80, 0x8b, + 0x59, 0x1a, 0xc9, 0xb0, 0x1e, 0x94, 0xbd, 0x27, 0x5a, 0xfa, 0x88, 0xe7, 0x82, 0x60, 0xdb, 0x76, 0x8a, 0xad, 0x6b, + 0x18, 0x03, 0x1f, 0xba, 0xc6, 0x1d, 0x04, 0xd7, 0xec, 0x56, 0x34, 0xcf, 0xe0, 0x31, 0x88, 0x39, 0x30, 0xc2, 0x7c, + 0x5e, 0xaa, 0xba, 0x7d, 0xa2, 0xb3, 0xff, 0x02, 0x42, 0x31, 0xbb, 0xd5, 0xe5, 0xd6, 0x69, 0xe3, 0x21, 0x43, 0x16, + 0x64, 0x2c, 0x49, 0x8a, 0x8c, 0xfc, 0xa6, 0xa3, 0x2d, 0x63, 0xd1, 0x33, 0x97, 0x71, 0x4b, 0x6a, 0x42, 0xa9, 0xce, + 0xa6, 0x21, 0x51, 0x5e, 0x8f, 0xb0, 0xa8, 0x42, 0xec, 0x36, 0x87, 0x54, 0xce, 0x5c, 0x11, 0x99, 0xe2, 0x49, 0xda, + 0x66, 0x67, 0xb0, 0x46, 0x90, 0xa1, 0x60, 0x82, 0xaa, 0xf6, 0xfd, 0xe8, 0xfe, 0x86, 0x79, 0x30, 0xa6, 0xa9, 0x7a, + 0x78, 0xc3, 0x94, 0x89, 0xf0, 0x24, 0x6d, 0x6f, 0x3b, 0x62, 0xdb, 0xba, 0x8e, 0xf3, 0xec, 0x7b, 0xf2, 0x56, 0x8e, + 0x2c, 0xd9, 0x9a, 0xb2, 0x35, 0x15, 0xfb, 0xa0, 0x16, 0x15, 0x65, 0x28, 0x91, 0x48, 0x60, 0x2b, 0xea, 0xed, 0xa5, + 0x3a, 0x1b, 0x88, 0xf4, 0xca, 0x7a, 0xbf, 0x26, 0xcf, 0xe9, 0xda, 0x4a, 0x29, 0x58, 0x40, 0x21, 0x2c, 0x34, 0xf6, + 0xac, 0xef, 0x7f, 0x9c, 0xd7, 0xb0, 0x1f, 0x7e, 0xcc, 0x88, 0x2d, 0xfc, 0xea, 0xfd, 0x7a, 0x82, 0x01, 0x46, 0xdd, + 0x8b, 0xae, 0x48, 0xdf, 0x1b, 0xfa, 0x1e, 0xe9, 0xbb, 0xaf, 0xef, 0x66, 0x3f, 0xd0, 0x35, 0xd6, 0x86, 0x37, 0xee, + 0xdc, 0x42, 0xeb, 0x88, 0x2f, 0xb1, 0xd4, 0x41, 0x7f, 0x5b, 0x7e, 0x9a, 0xa8, 0xb2, 0x5f, 0x5b, 0x49, 0x29, 0x9b, + 0xbe, 0x24, 0x55, 0x1b, 0xba, 0x8c, 0x90, 0xba, 0x57, 0x82, 0xb7, 0x6f, 0x9d, 0xba, 0xba, 0x2d, 0xe5, 0xa7, 0xe3, + 0x62, 0xfc, 0xf2, 0xaf, 0x0e, 0xf1, 0x52, 0xc6, 0x74, 0xe8, 0xca, 0x3b, 0xef, 0xd9, 0x4a, 0x8d, 0x2b, 0xcc, 0x09, + 0xe7, 0x78, 0xb2, 0x90, 0x31, 0xea, 0xa1, 0xdc, 0xb9, 0x03, 0x2e, 0x23, 0x08, 0x7c, 0x45, 0x57, 0x55, 0x8a, 0x59, + 0xea, 0x3b, 0x06, 0x96, 0xf9, 0x3e, 0xd1, 0xe5, 0xf0, 0xf7, 0x02, 0x09, 0x7d, 0xea, 0xaa, 0x72, 0xed, 0x4a, 0x35, + 0x62, 0x6c, 0x8a, 0x24, 0xe7, 0x64, 0xbd, 0xcb, 0x8b, 0xbc, 0xf0, 0xd7, 0xd3, 0xaa, 0xa6, 0x03, 0x52, 0xcc, 0x4a, + 0x2c, 0xca, 0xa9, 0x58, 0x94, 0x22, 0x62, 0xfb, 0x12, 0x86, 0xca, 0x66, 0x12, 0x88, 0xbc, 0xb7, 0x73, 0x91, 0x58, + 0xbe, 0x02, 0x18, 0xac, 0xaa, 0x0f, 0x84, 0xe4, 0x77, 0x76, 0xd9, 0x25, 0x3f, 0xf6, 0x57, 0x4a, 0x26, 0x93, 0x56, + 0x18, 0x02, 0x77, 0xc4, 0x6f, 0x9f, 0x0e, 0x18, 0x13, 0x9c, 0x33, 0xda, 0x18, 0x30, 0xe7, 0xa6, 0x69, 0x48, 0xaa, + 0x9a, 0xb5, 0xca, 0xdd, 0xbc, 0xc2, 0x4c, 0x48, 0x62, 0xa8, 0xca, 0xcd, 0xf0, 0x6b, 0x3d, 0x52, 0x90, 0xf3, 0xf7, + 0x5c, 0x5d, 0x90, 0x31, 0x2a, 0x67, 0x3a, 0x99, 0x04, 0x5f, 0x07, 0xf0, 0x01, 0x73, 0x2b, 0x3e, 0xf8, 0xc7, 0x59, + 0xca, 0x23, 0x1b, 0xd0, 0x03, 0xb5, 0x43, 0x35, 0x56, 0x2d, 0x25, 0x0a, 0x13, 0x09, 0xa1, 0x0c, 0x3e, 0xe2, 0x33, + 0x99, 0x8b, 0x39, 0xab, 0xfb, 0x5c, 0x2c, 0xdb, 0x0e, 0x24, 0x06, 0x44, 0x99, 0x10, 0x49, 0x4e, 0x6a, 0xdd, 0x50, + 0x61, 0x71, 0x74, 0x69, 0xb1, 0x88, 0x13, 0x24, 0xd3, 0x7a, 0x21, 0xf8, 0x97, 0x1d, 0x5b, 0xc9, 0xf1, 0xa6, 0xff, + 0x66, 0x34, 0x57, 0x23, 0x33, 0xd9, 0x45, 0x6b, 0x5e, 0xf4, 0x8b, 0xb4, 0xe6, 0xf2, 0x21, 0x51, 0xe8, 0x1f, 0x68, + 0xdd, 0x5b, 0xd6, 0x10, 0x29, 0x58, 0xd2, 0x15, 0x7d, 0x45, 0xdb, 0x5d, 0x7a, 0x59, 0xe0, 0x71, 0xf7, 0x31, 0x41, + 0x82, 0xef, 0xb6, 0x8a, 0x97, 0xc0, 0x45, 0xb2, 0xc6, 0x9e, 0xfb, 0x44, 0x16, 0x1d, 0xd3, 0x8d, 0xd2, 0xd5, 0x91, + 0x9d, 0xd3, 0x37, 0x88, 0x92, 0x9c, 0x5d, 0x2b, 0x31, 0xf5, 0x3f, 0x47, 0xdd, 0xe4, 0xa2, 0xb2, 0x67, 0x87, 0x1c, + 0xc4, 0xcd, 0xd4, 0x42, 0x98, 0x92, 0xbd, 0x13, 0xd8, 0x08, 0x91, 0x91, 0x62, 0x52, 0x04, 0x25, 0xf7, 0x92, 0x2f, + 0x89, 0x14, 0xf2, 0x47, 0xa5, 0x86, 0xb6, 0x4c, 0xe9, 0x7f, 0xb4, 0x8e, 0xf0, 0xed, 0x0c, 0x27, 0x49, 0xf9, 0xe4, + 0x05, 0xb7, 0xad, 0xdd, 0x8e, 0xd9, 0x20, 0x09, 0xf7, 0xcf, 0x2c, 0x9f, 0xf5, 0xf6, 0x20, 0xff, 0x50, 0x26, 0x04, + 0x78, 0xeb, 0x9b, 0x5e, 0xd5, 0x2f, 0x01, 0xa3, 0x92, 0x6a, 0x51, 0x79, 0x3b, 0x39, 0x97, 0x38, 0xe5, 0xf2, 0x02, + 0x7e, 0xf9, 0x7e, 0xce, 0x81, 0x79, 0xf8, 0x4a, 0x5b, 0x4d, 0x14, 0xec, 0x87, 0xc3, 0x1e, 0x43, 0xc9, 0x0a, 0x1b, + 0xd9, 0xcd, 0xc6, 0xb8, 0x0b, 0x5d, 0x6b, 0xb3, 0x7e, 0x0a, 0xa9, 0x57, 0x77, 0x9c, 0xde, 0xc5, 0x55, 0x8d, 0x34, + 0xb7, 0x69, 0xc4, 0x51, 0xc9, 0x4c, 0x07, 0x72, 0x87, 0x69, 0x3a, 0x66, 0x6f, 0x23, 0xc1, 0xf2, 0xcd, 0x59, 0x5b, + 0x79, 0x2b, 0xef, 0x49, 0x08, 0x98, 0x70, 0xc0, 0x5c, 0xd1, 0xb0, 0x56, 0x0e, 0x82, 0x39, 0xf6, 0x7b, 0xad, 0x90, + 0x98, 0xaa, 0x48, 0x7a, 0x36, 0xf1, 0xb9, 0x56, 0x6b, 0xcf, 0x1a, 0x09, 0x59, 0x3a, 0x05, 0x8e, 0x35, 0x4f, 0x14, + 0x0c, 0x65, 0x6a, 0x56, 0xcb, 0x3c, 0xe0, 0x2a, 0x7b, 0xae, 0xe5, 0x95, 0x40, 0x0c, 0x1c, 0x14, 0x90, 0x9c, 0xf8, + 0x1e, 0xee, 0x49, 0xec, 0x3b, 0x73, 0x86, 0xc6, 0x4c, 0x86, 0xa8, 0xce, 0x4a, 0x15, 0x58, 0xd7, 0xdb, 0xc0, 0x54, + 0x51, 0x6b, 0x6e, 0xe8, 0x9e, 0x0c, 0xd6, 0xd7, 0x38, 0x3c, 0x10, 0xf6, 0xf8, 0x82, 0xdc, 0x87, 0xbf, 0xcf, 0xca, + 0x63, 0x67, 0x0b, 0x68, 0xc0, 0x7a, 0xf3, 0x1c, 0x39, 0xa2, 0xeb, 0x2d, 0x95, 0x2b, 0x5b, 0xd0, 0x65, 0xaf, 0xe9, + 0xfd, 0xd3, 0x41, 0x75, 0xb9, 0xdc, 0xcc, 0x8c, 0xa8, 0xe2, 0xc9, 0x24, 0x09, 0xfa, 0x10, 0x33, 0x28, 0xa9, 0x79, + 0x2a, 0xeb, 0x88, 0x89, 0x7b, 0xb0, 0xbc, 0x23, 0x13, 0xd3, 0x25, 0x98, 0xe3, 0x9c, 0xad, 0x8b, 0x06, 0x87, 0x1c, + 0x0e, 0x58, 0xa2, 0x4b, 0x1e, 0xdc, 0xfb, 0x56, 0x56, 0x6a, 0xd1, 0x97, 0x63, 0xa9, 0x84, 0xdc, 0x00, 0x36, 0x76, + 0xb4, 0x93, 0x0b, 0xe5, 0xd4, 0x4e, 0x10, 0xec, 0xe4, 0xa6, 0xf6, 0x0e, 0x49, 0x06, 0xc8, 0x1e, 0x08, 0x55, 0x19, + 0xf0, 0x79, 0x5d, 0x11, 0x00, 0x9a, 0xe3, 0x12, 0x89, 0x3f, 0x08, 0xe3, 0xe5, 0x37, 0x8a, 0x41, 0x83, 0xe3, 0x6e, + 0x66, 0x38, 0x78, 0x1d, 0xc0, 0x28, 0x8d, 0x12, 0xf3, 0x23, 0x10, 0xe5, 0x62, 0x7f, 0x95, 0x18, 0x1d, 0x29, 0x44, + 0x38, 0xf4, 0x8b, 0xdd, 0x85, 0xb4, 0xf5, 0x16, 0x6c, 0x65, 0x36, 0x2b, 0xb3, 0x5d, 0x03, 0x68, 0x1f, 0xa9, 0x01, + 0xd0, 0x66, 0xc3, 0x43, 0x3f, 0x37, 0xdd, 0x67, 0x3e, 0x43, 0xf7, 0x8e, 0x22, 0xf0, 0xeb, 0x32, 0x35, 0xdf, 0xc2, + 0x05, 0x4c, 0x33, 0xf5, 0x5e, 0x5e, 0x2d, 0xf7, 0x75, 0xb7, 0x63, 0x20, 0xbc, 0x5c, 0x62, 0x8f, 0xf8, 0x29, 0xab, + 0xe2, 0xa0, 0xc7, 0x1c, 0xbd, 0x46, 0x90, 0x66, 0x66, 0x69, 0xc8, 0x73, 0x0b, 0xe5, 0x33, 0x92, 0x03, 0xf9, 0x98, + 0x2c, 0x0f, 0xd9, 0xcb, 0x70, 0xe5, 0xa1, 0xae, 0x23, 0x24, 0x55, 0x90, 0x7a, 0x02, 0xcf, 0xd5, 0x0c, 0xc2, 0xb2, + 0x8f, 0xe7, 0xc4, 0xdc, 0xf3, 0xb7, 0x29, 0x68, 0xe4, 0x40, 0xa5, 0xf3, 0x93, 0xb2, 0x80, 0xdc, 0x43, 0x1d, 0xa6, + 0x98, 0xf1, 0xa0, 0x97, 0x5d, 0x95, 0x64, 0x38, 0x1a, 0xa1, 0xf1, 0x84, 0x82, 0xe4, 0x05, 0xc1, 0xd1, 0x57, 0x4b, + 0xe5, 0xaf, 0x24, 0xe5, 0x4d, 0x56, 0x96, 0x0d, 0xee, 0x25, 0x5e, 0x64, 0x0d, 0x9c, 0x59, 0xd8, 0xd1, 0xa6, 0xac, + 0x19, 0x13, 0x04, 0x80, 0x0f, 0x87, 0xe0, 0xc8, 0x22, 0x62, 0x59, 0x44, 0x13, 0xc5, 0x38, 0x96, 0x3f, 0x7b, 0xf8, + 0xa6, 0x08, 0xae, 0xd7, 0x91, 0xa0, 0x85, 0xc0, 0x27, 0x0e, 0xc0, 0x33, 0x33, 0x88, 0x78, 0xb6, 0xda, 0x3c, 0x02, + 0x13, 0xa9, 0xb5, 0x1f, 0x8d, 0xf8, 0x84, 0x13, 0xe7, 0xb8, 0x44, 0x1a, 0xb9, 0x5d, 0x8b, 0xc3, 0x21, 0x91, 0x89, + 0x9d, 0x39, 0xf2, 0xb1, 0xf1, 0x5d, 0x91, 0xff, 0x65, 0x16, 0x3d, 0x29, 0x51, 0x73, 0x39, 0x52, 0xbc, 0x69, 0x1b, + 0xa2, 0x55, 0xc6, 0xb5, 0xf4, 0x72, 0x98, 0x30, 0x58, 0xc0, 0xfe, 0xdf, 0x7c, 0x30, 0x1a, 0x8d, 0x95, 0xf3, 0x31, + 0xb8, 0xe2, 0x21, 0x3a, 0x6c, 0x38, 0x6a, 0x7d, 0xdd, 0x34, 0x99, 0x93, 0x0f, 0xfb, 0x6f, 0x7b, 0xb3, 0xeb, 0x6e, + 0x23, 0xea, 0x5c, 0x4a, 0x73, 0xe6, 0x85, 0xd0, 0x87, 0x91, 0xd5, 0x8b, 0x35, 0xe6, 0x84, 0xe6, 0x97, 0x8e, 0xa8, + 0x56, 0x1c, 0x9e, 0x3e, 0x08, 0xc5, 0xcb, 0xd1, 0x3e, 0xc4, 0x01, 0xb1, 0xa1, 0x44, 0xd9, 0x33, 0x95, 0x90, 0xc6, + 0x31, 0xb0, 0x5e, 0x85, 0x83, 0x40, 0xe0, 0xb4, 0x61, 0xbb, 0x66, 0xfd, 0x16, 0x2b, 0x4a, 0xc8, 0x21, 0xd5, 0x64, + 0xd9, 0x8c, 0x1f, 0x62, 0x47, 0x13, 0x94, 0x48, 0x29, 0x5a, 0x36, 0xfd, 0xc3, 0xb6, 0x23, 0x07, 0x2f, 0xa1, 0x21, + 0x71, 0x04, 0x2f, 0xbd, 0xf3, 0x87, 0xfd, 0x37, 0xeb, 0x23, 0xcf, 0x51, 0xbf, 0xe5, 0x21, 0xdf, 0xf2, 0x1c, 0xed, + 0x43, 0x1e, 0xf2, 0x21, 0xcf, 0x11, 0x3f, 0xe4, 0x41, 0xb2, 0x38, 0x4f, 0x5f, 0xdb, 0x7f, 0x0e, 0xc7, 0x4c, 0xa1, + 0x5c, 0x9e, 0x89, 0xad, 0xe4, 0xe8, 0x17, 0x1f, 0x32, 0xee, 0xb3, 0x89, 0x94, 0x3c, 0x21, 0x5e, 0x89, 0x12, 0x97, + 0xac, 0x2c, 0x93, 0x02, 0xf8, 0x34, 0xc4, 0xa7, 0x37, 0xdb, 0x77, 0xfc, 0x23, 0xac, 0x51, 0x74, 0x26, 0xe2, 0xc5, + 0x98, 0x8c, 0xd3, 0x3d, 0x73, 0xeb, 0x85, 0xad, 0x89, 0x90, 0x2c, 0x67, 0x04, 0x6d, 0x08, 0x71, 0xc8, 0x88, 0x91, + 0xcb, 0xf9, 0x64, 0xb4, 0xc4, 0xd0, 0xb7, 0xef, 0xa2, 0xd7, 0xcc, 0xfe, 0x1c, 0x03, 0x48, 0x95, 0xe7, 0x06, 0x64, + 0xe0, 0x18, 0x7b, 0xf5, 0x31, 0xd6, 0xa7, 0xe7, 0x45, 0x15, 0x0d, 0xba, 0x26, 0x87, 0x63, 0x4e, 0x90, 0x64, 0xa4, + 0x7f, 0xc5, 0xba, 0xec, 0x2c, 0x5d, 0x36, 0xaf, 0xc2, 0x3d, 0x61, 0xbe, 0x04, 0xb4, 0x28, 0x21, 0xd5, 0xcc, 0x72, + 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xa4, 0xc9, 0x52, 0x6d, 0x97, 0x85, 0xbb, 0xec, 0xf1, 0x0b, 0xfe, 0xe1, 0x9e, + 0xe6, 0x66, 0x91, 0x41, 0xfb, 0x22, 0x67, 0xf7, 0xde, 0x15, 0xb6, 0xb5, 0x06, 0xf3, 0x13, 0x29, 0xd6, 0x22, 0x7c, + 0x35, 0xa6, 0x17, 0xa4, 0x3d, 0x7c, 0x83, 0x22, 0x1a, 0xdf, 0x67, 0x13, 0x5b, 0x86, 0xf6, 0x96, 0x7c, 0x6d, 0xa9, + 0xc9, 0x66, 0xc5, 0x1a, 0x2c, 0xb9, 0xfd, 0xf6, 0x25, 0xb5, 0x43, 0x97, 0xb9, 0x28, 0xb2, 0x49, 0x75, 0x53, 0xac, + 0x4d, 0x81, 0x2f, 0xc9, 0x56, 0x84, 0x8e, 0x40, 0x51, 0xb9, 0xcb, 0xe2, 0x70, 0xb9, 0xaa, 0xe5, 0xd4, 0x94, 0x10, + 0x69, 0xc8, 0x2a, 0xcc, 0xf4, 0x52, 0x7c, 0xbc, 0x38, 0x14, 0x21, 0xe5, 0x28, 0xa1, 0x33, 0xb5, 0x9c, 0xae, 0x6b, + 0xf5, 0xb7, 0x50, 0xe0, 0xe0, 0x4b, 0x5e, 0x43, 0x2c, 0x61, 0xa9, 0x6a, 0x0e, 0x11, 0x67, 0x9e, 0xdd, 0xd0, 0x95, + 0x87, 0xfd, 0xf7, 0x21, 0x04, 0x79, 0xb1, 0xfd, 0x94, 0xae, 0x5d, 0x9f, 0x91, 0x49, 0x20, 0x91, 0x84, 0x02, 0x80, + 0x03, 0x00, 0xae, 0x7a, 0x05, 0xab, 0x02, 0x93, 0x5e, 0xab, 0xc0, 0xc0, 0x14, 0x3c, 0x41, 0x99, 0xa1, 0x1d, 0xe0, + 0xf2, 0x47, 0xa4, 0xf4, 0xda, 0x21, 0x5b, 0x4c, 0x04, 0x34, 0x94, 0xc0, 0x31, 0xa1, 0xdd, 0x16, 0xe3, 0xe5, 0x25, + 0x0a, 0x2f, 0x89, 0xd2, 0x51, 0xdb, 0x02, 0x34, 0x90, 0x57, 0xb3, 0x2c, 0x9c, 0x96, 0x91, 0xe7, 0x6b, 0x13, 0xde, + 0xf2, 0x76, 0x5d, 0x6e, 0x3f, 0xb2, 0x35, 0x4d, 0x21, 0x1b, 0x82, 0x7d, 0xcf, 0xd6, 0x3d, 0x63, 0xa8, 0x10, 0x6f, + 0xb1, 0x1c, 0x7a, 0xe3, 0xba, 0x56, 0x1b, 0xd2, 0x87, 0x3e, 0x7a, 0x28, 0xba, 0x72, 0x37, 0x8c, 0x04, 0x5a, 0x4b, + 0x04, 0xab, 0xe1, 0x39, 0x03, 0xed, 0x26, 0x2f, 0x25, 0x47, 0x41, 0xaa, 0x02, 0x1f, 0xd2, 0xcd, 0x37, 0x2c, 0x66, + 0xb0, 0xeb, 0x36, 0x0b, 0xe4, 0x6a, 0xa0, 0xf5, 0xf1, 0x3b, 0x0d, 0x7b, 0x7d, 0x02, 0x36, 0x96, 0x2e, 0x57, 0xdb, + 0x2e, 0x8a, 0xa3, 0xe6, 0x8a, 0xe6, 0xae, 0xed, 0x14, 0xfa, 0x73, 0xf1, 0x39, 0xdc, 0x9e, 0x27, 0x8d, 0xef, 0xf3, + 0x13, 0xe1, 0x7b, 0x97, 0x35, 0xde, 0x1b, 0x0d, 0xa8, 0x3f, 0xce, 0xc4, 0x58, 0x8b, 0x1c, 0x15, 0x65, 0xe0, 0xa3, + 0x59, 0x2d, 0xee, 0xa0, 0x29, 0x32, 0xde, 0x6b, 0x04, 0x77, 0x9b, 0x5a, 0x65, 0x70, 0xaf, 0xb5, 0x01, 0x7d, 0x8f, + 0x83, 0xd4, 0xbd, 0x36, 0xda, 0xd9, 0xb9, 0x96, 0xa0, 0x16, 0x23, 0xa3, 0x95, 0x66, 0x63, 0xbb, 0x0d, 0xdd, 0xba, + 0xa5, 0x7e, 0x41, 0x9f, 0xca, 0xc9, 0x81, 0xec, 0xac, 0xae, 0x4a, 0xc5, 0xa4, 0x25, 0x78, 0x8b, 0xeb, 0x7b, 0x65, + 0x4a, 0x64, 0xe0, 0x56, 0x75, 0x99, 0x30, 0x12, 0x07, 0xb0, 0xf8, 0xc8, 0x9d, 0xf1, 0xeb, 0x07, 0xa8, 0x14, 0x1e, + 0x9f, 0x8b, 0x52, 0x78, 0xfc, 0x41, 0xf8, 0x4c, 0x7d, 0x05, 0x91, 0x9a, 0xba, 0xff, 0x32, 0x8f, 0x4a, 0xe5, 0x9b, + 0xbd, 0x6c, 0xec, 0x85, 0x79, 0x1b, 0x40, 0xbe, 0x4d, 0x33, 0x31, 0x98, 0xf9, 0x27, 0x27, 0xba, 0xdb, 0x10, 0x65, + 0x73, 0x0f, 0xd1, 0x7b, 0x45, 0x1d, 0x86, 0x8e, 0xa1, 0x43, 0x91, 0x1a, 0xb7, 0x75, 0x5c, 0x5f, 0xb2, 0x02, 0x9e, + 0xf4, 0xdf, 0x79, 0x7c, 0x52, 0x75, 0xfb, 0x0d, 0x4b, 0x9c, 0x49, 0xa4, 0x92, 0x8a, 0x4d, 0x27, 0xee, 0x2a, 0x35, + 0x59, 0xee, 0xbd, 0xed, 0x90, 0xa0, 0x2d, 0x32, 0xc8, 0x54, 0xef, 0x57, 0x24, 0xce, 0xa1, 0x66, 0x94, 0xa6, 0x82, + 0xa9, 0xac, 0xb2, 0xf2, 0x64, 0xde, 0x9c, 0x7f, 0xc4, 0xa7, 0x34, 0x1e, 0xf0, 0x31, 0x2c, 0x66, 0x23, 0xff, 0x7e, + 0xc4, 0xe8, 0xe8, 0xa6, 0x36, 0xac, 0x52, 0x26, 0x98, 0x56, 0x28, 0xe1, 0x63, 0x05, 0xc1, 0x09, 0x7e, 0x10, 0x4c, + 0x8e, 0x9c, 0x94, 0xac, 0x3c, 0x7e, 0xb3, 0xde, 0x62, 0xf8, 0x38, 0x33, 0xb1, 0xf1, 0x55, 0x9d, 0x69, 0x71, 0x87, + 0xee, 0xae, 0xf0, 0x72, 0xac, 0x4a, 0x86, 0x0b, 0xb2, 0x89, 0xb1, 0x8e, 0xc2, 0x67, 0x24, 0x29, 0x39, 0x91, 0xa7, + 0x74, 0x64, 0x32, 0x13, 0x38, 0x05, 0x67, 0x61, 0xfc, 0xa0, 0x36, 0xae, 0xa4, 0x6f, 0xa1, 0xa7, 0x45, 0xba, 0x3d, + 0x23, 0x0f, 0x76, 0x55, 0xef, 0x51, 0x16, 0x44, 0x19, 0x69, 0x30, 0x42, 0xda, 0xb2, 0xc4, 0xb8, 0x26, 0x62, 0x93, + 0x51, 0x18, 0x65, 0x5a, 0x6b, 0x2d, 0xbb, 0x16, 0x7f, 0x37, 0x54, 0x33, 0x4d, 0xbd, 0x5a, 0x9c, 0xfc, 0xc4, 0x24, + 0xad, 0x19, 0x2e, 0x5b, 0x7c, 0x78, 0xa1, 0xf6, 0xa8, 0x54, 0x07, 0x62, 0x6f, 0x67, 0x14, 0x4a, 0xb7, 0xef, 0x69, + 0x88, 0xa7, 0x46, 0xe7, 0xa5, 0xd3, 0x79, 0x75, 0xaa, 0xba, 0x6f, 0x4c, 0xd4, 0xb6, 0xfb, 0x66, 0x9c, 0xe2, 0x19, + 0xd0, 0x7c, 0x62, 0x04, 0x1d, 0xfa, 0x4f, 0x85, 0x06, 0x61, 0xd1, 0x30, 0xf3, 0xd9, 0x03, 0x18, 0xe9, 0xa6, 0x4c, + 0x6b, 0x46, 0x82, 0x7b, 0x8f, 0x60, 0xe0, 0x31, 0x69, 0x1e, 0xd9, 0x98, 0x4e, 0x18, 0x86, 0xa8, 0xa2, 0x93, 0xb3, + 0xec, 0x73, 0xf3, 0xfb, 0x3d, 0xea, 0xba, 0xdd, 0xb0, 0xa9, 0xe5, 0xbc, 0x87, 0xd3, 0xfb, 0xbf, 0xb9, 0xe8, 0xa4, + 0xbf, 0x9c, 0x5d, 0x5b, 0xe8, 0xc2, 0xe2, 0x7d, 0x1d, 0xf6, 0xbf, 0x91, 0xf9, 0xc8, 0x53, 0xa5, 0x77, 0x18, 0x03, + 0x19, 0x3a, 0xb3, 0x26, 0xca, 0x2f, 0x0c, 0xed, 0x28, 0x24, 0xd9, 0x89, 0xdd, 0x54, 0x4d, 0x90, 0x80, 0x48, 0x8c, + 0xa9, 0xef, 0x1c, 0x0c, 0xb4, 0x53, 0x9d, 0xc5, 0xa4, 0x2d, 0x5f, 0x81, 0x72, 0x5a, 0x06, 0x2c, 0x2f, 0x55, 0x78, + 0x76, 0x1d, 0xd4, 0xd4, 0xc7, 0x09, 0xc5, 0x56, 0x70, 0x3d, 0x64, 0x90, 0xaa, 0x12, 0x42, 0xa7, 0x29, 0x02, 0xbb, + 0x38, 0x36, 0xf1, 0xc7, 0x86, 0xf1, 0x03, 0xac, 0x81, 0xa6, 0xb5, 0xd8, 0xc2, 0x41, 0x52, 0xcc, 0xfc, 0x2d, 0x4d, + 0x8f, 0xab, 0xf4, 0xca, 0x3b, 0x05, 0xd6, 0x26, 0x98, 0xb2, 0x25, 0xb7, 0x6e, 0x2d, 0x42, 0x21, 0x8c, 0x59, 0xd7, + 0x90, 0xca, 0x3b, 0x24, 0x7f, 0x46, 0x16, 0xf0, 0x76, 0xbf, 0x54, 0x48, 0x3d, 0x2b, 0xcc, 0xae, 0x13, 0x74, 0x52, + 0x10, 0x47, 0xba, 0x44, 0xfc, 0xff, 0xca, 0x84, 0x10, 0x7c, 0xda, 0xf0, 0x6d, 0x09, 0x4d, 0x52, 0x9c, 0x5d, 0xb9, + 0x0b, 0x78, 0xec, 0x7a, 0xfd, 0x2c, 0x59, 0xa3, 0xef, 0xf0, 0xd9, 0x20, 0x16, 0xd8, 0x88, 0x9e, 0x9a, 0xd4, 0xb0, + 0xfa, 0xea, 0x95, 0xdd, 0xee, 0x11, 0xf5, 0x8d, 0x62, 0x0a, 0x15, 0xce, 0x7e, 0xf6, 0x94, 0x38, 0xed, 0x4d, 0xd3, + 0x5a, 0x92, 0xf2, 0xbf, 0xe4, 0x8e, 0x20, 0xf1, 0xaf, 0x37, 0x04, 0x05, 0x3c, 0x1b, 0x9e, 0x1a, 0x92, 0xfb, 0xfd, + 0x5b, 0x15, 0xaa, 0xbd, 0x0e, 0x66, 0x82, 0x2e, 0xbc, 0x07, 0x09, 0x8e, 0xfc, 0x20, 0xcb, 0xc6, 0x2f, 0x0a, 0x4b, + 0xdf, 0x98, 0x3b, 0xc4, 0x9e, 0x38, 0xd3, 0x93, 0xe6, 0x51, 0x7e, 0x58, 0xc1, 0x24, 0xdd, 0x21, 0x83, 0x7c, 0x7e, + 0x81, 0xb1, 0x77, 0x84, 0x95, 0x53, 0xb7, 0x7d, 0x79, 0x07, 0xb1, 0xac, 0x74, 0xc9, 0xbd, 0xd4, 0x9a, 0x12, 0x46, + 0x6d, 0x38, 0xcb, 0xab, 0x56, 0xf4, 0xe5, 0x76, 0xb6, 0xd1, 0x27, 0x2a, 0x20, 0x56, 0xdf, 0x33, 0x39, 0x2d, 0x91, + 0x61, 0xff, 0xb4, 0x5e, 0x4d, 0x9e, 0x0e, 0x43, 0x5d, 0x6b, 0x87, 0x54, 0xdb, 0xf5, 0x4e, 0x05, 0x0a, 0x8c, 0x2d, + 0xbd, 0xa5, 0x67, 0xe9, 0x70, 0xcc, 0x35, 0x78, 0xb1, 0x8c, 0xe0, 0x79, 0xea, 0x07, 0x78, 0x5f, 0x2d, 0x8f, 0x25, + 0xee, 0x1d, 0xdd, 0xf8, 0x02, 0x3a, 0x98, 0xce, 0x02, 0x0f, 0xbf, 0x1d, 0xb0, 0x4a, 0x36, 0x26, 0x73, 0xaf, 0x89, + 0x60, 0x40, 0x29, 0xfa, 0x60, 0xdf, 0x8d, 0x55, 0x4a, 0x34, 0x41, 0x3f, 0xb2, 0xd8, 0xa2, 0x5b, 0xdf, 0x56, 0x44, + 0x3c, 0xe3, 0x72, 0x54, 0x43, 0xfc, 0x29, 0x67, 0x2f, 0xb1, 0x4c, 0x18, 0xc9, 0xc2, 0xa0, 0x91, 0xbd, 0xe0, 0x23, + 0x4a, 0xcf, 0x0f, 0x2d, 0xed, 0xbe, 0x5d, 0x0f, 0x3f, 0x12, 0xc1, 0x5a, 0x1d, 0x84, 0x03, 0x15, 0x8a, 0xec, 0xd9, + 0xca, 0xcd, 0xc1, 0x0d, 0x19, 0x01, 0x28, 0x57, 0x40, 0x36, 0x16, 0xfc, 0xee, 0x86, 0xb0, 0xb8, 0x95, 0x8c, 0xcb, + 0xc4, 0x3e, 0x6f, 0x66, 0x22, 0x3d, 0x27, 0x57, 0x11, 0xe0, 0xe6, 0xa0, 0x99, 0x34, 0x8f, 0x2d, 0xb7, 0xa8, 0xb8, + 0x02, 0x6a, 0x42, 0x6d, 0xd1, 0x44, 0x54, 0x08, 0xd0, 0xeb, 0x69, 0x1f, 0x11, 0xb1, 0x4e, 0xc6, 0xc0, 0xb6, 0x2d, + 0x99, 0x54, 0x2a, 0xe3, 0x7a, 0xa7, 0x38, 0xdc, 0xb5, 0xdd, 0xfd, 0xdf, 0x64, 0x66, 0xcf, 0x60, 0x19, 0x5a, 0xac, + 0x65, 0x77, 0x7f, 0x14, 0xfb, 0xe3, 0x80, 0x06, 0x32, 0x3f, 0xd4, 0x41, 0xf2, 0xd7, 0x3a, 0x43, 0x5c, 0x4a, 0x41, + 0xf9, 0x10, 0x57, 0xb2, 0xc8, 0x05, 0xe9, 0x4e, 0xba, 0xca, 0x73, 0x99, 0x93, 0x7b, 0x40, 0x50, 0x1f, 0x08, 0x85, + 0x2c, 0x37, 0x90, 0xc6, 0x1b, 0x9c, 0x38, 0x6f, 0xe2, 0x91, 0x84, 0xb6, 0x9e, 0x49, 0x64, 0xb2, 0x68, 0xc7, 0x32, + 0xf0, 0xc9, 0xaf, 0xdd, 0x4f, 0x3e, 0xc6, 0x66, 0xe3, 0x40, 0x9b, 0xe5, 0xc9, 0x32, 0xcc, 0xaa, 0xad, 0x2a, 0x4e, + 0x58, 0x32, 0x99, 0x26, 0xbc, 0xfe, 0x2b, 0xac, 0xdc, 0x1a, 0xbe, 0x82, 0x0f, 0x66, 0xb6, 0x84, 0x4b, 0x9b, 0x6f, + 0x91, 0xa2, 0xc3, 0x30, 0xdd, 0xe4, 0xf8, 0x18, 0x13, 0xd3, 0xc5, 0x66, 0xc5, 0x30, 0x1a, 0x14, 0x89, 0xb7, 0x9b, + 0xaf, 0xf6, 0xef, 0x13, 0x38, 0x58, 0x2d, 0xc8, 0xd6, 0xee, 0xaf, 0xc1, 0x65, 0x0f, 0x59, 0x49, 0xd5, 0x98, 0x20, + 0xb4, 0x42, 0x1a, 0x43, 0xd4, 0x25, 0xfe, 0x55, 0x5f, 0x1e, 0xd2, 0xf5, 0xd7, 0x32, 0xa3, 0xf8, 0x5e, 0xfe, 0x5e, + 0xf8, 0x8e, 0x7f, 0x60, 0x2a, 0x69, 0xf3, 0x1c, 0xe1, 0xeb, 0xa0, 0x4b, 0x83, 0x84, 0xa8, 0x89, 0x7c, 0x5b, 0x32, + 0x40, 0xcc, 0x7a, 0x88, 0x01, 0xdc, 0x65, 0x75, 0xab, 0x24, 0x21, 0x63, 0xc1, 0x30, 0xd8, 0x16, 0x2b, 0xf3, 0x78, + 0x46, 0xea, 0x1d, 0xc6, 0x22, 0x71, 0x3e, 0x0f, 0x16, 0xec, 0xd4, 0x75, 0x26, 0xa6, 0x8b, 0xff, 0x98, 0x60, 0x81, + 0x25, 0x18, 0x6b, 0x2d, 0xfc, 0x74, 0x55, 0xc0, 0x9d, 0xe1, 0x43, 0x88, 0x02, 0xb7, 0xc9, 0x13, 0x3f, 0xd3, 0x3d, + 0xc5, 0x2e, 0x38, 0x95, 0x7a, 0x45, 0xd6, 0x9f, 0x03, 0xad, 0x5a, 0x73, 0xa9, 0xce, 0xee, 0x5c, 0x0e, 0xc2, 0x54, + 0x8b, 0xc2, 0x84, 0xd7, 0x51, 0xe2, 0xab, 0x6a, 0x39, 0x4d, 0x18, 0x5a, 0xbf, 0x0a, 0xf5, 0x27, 0xb9, 0xa8, 0x28, + 0xe1, 0xc4, 0x4d, 0xd2, 0x4d, 0x05, 0x07, 0xd4, 0xef, 0xed, 0xda, 0x84, 0xb7, 0x5e, 0xf0, 0x1c, 0x58, 0x50, 0xe8, + 0x39, 0x62, 0xf0, 0x8c, 0x91, 0xc1, 0xeb, 0xb2, 0x41, 0x07, 0xbd, 0x4c, 0x7f, 0xdb, 0x7e, 0xa9, 0xb5, 0xe7, 0xbb, + 0x59, 0xe4, 0x1c, 0xe4, 0xd9, 0xaf, 0xa6, 0xef, 0xef, 0x39, 0x13, 0xe3, 0xa2, 0x79, 0xd1, 0xd3, 0xe0, 0xb4, 0xdc, + 0xa0, 0xd9, 0x43, 0xd0, 0x31, 0xc3, 0xf6, 0x33, 0x2d, 0x2f, 0xc6, 0xf4, 0x9d, 0x38, 0xa6, 0x3d, 0xec, 0xfa, 0x99, + 0xb9, 0xa7, 0x17, 0x14, 0x68, 0xef, 0x89, 0xb7, 0x9d, 0xde, 0xe9, 0xea, 0xf3, 0xe5, 0x9a, 0x44, 0xdf, 0xac, 0xcb, + 0x75, 0x0b, 0xd0, 0xf5, 0x32, 0x16, 0x8d, 0x56, 0x65, 0x9f, 0x2b, 0xcf, 0xee, 0xf9, 0xbe, 0x30, 0xfd, 0x2d, 0xdc, + 0x4e, 0x86, 0x4c, 0xd2, 0x52, 0xb5, 0x52, 0x45, 0x93, 0x2e, 0x90, 0x58, 0x33, 0x49, 0xcb, 0x35, 0x1a, 0xcc, 0xf7, + 0xdd, 0xe5, 0xca, 0xf2, 0x27, 0x16, 0xa2, 0x52, 0x2f, 0xdf, 0x12, 0xa9, 0xcf, 0x06, 0x8b, 0x54, 0x84, 0x25, 0xca, + 0x8d, 0x67, 0x00, 0xab, 0x5d, 0x01, 0xd4, 0x9c, 0xa2, 0x97, 0x4b, 0x45, 0xc0, 0xc4, 0xe9, 0xa7, 0xfb, 0xcd, 0x14, + 0x86, 0xeb, 0xab, 0xb3, 0xf2, 0xda, 0x2f, 0x1a, 0xb9, 0xc4, 0x9f, 0x4f, 0x1f, 0x0a, 0x41, 0xa3, 0xee, 0x8a, 0xdf, + 0x5c, 0x48, 0x00, 0xe4, 0x10, 0xaf, 0xd5, 0x40, 0xba, 0x79, 0x4b, 0xba, 0x4e, 0x64, 0x5d, 0xbc, 0x4b, 0x05, 0x5c, + 0x59, 0xef, 0x80, 0x6e, 0x21, 0xdd, 0x6a, 0x89, 0x83, 0x84, 0x6e, 0xf8, 0x50, 0x70, 0x02, 0x25, 0xd8, 0xc9, 0x04, + 0x99, 0xbc, 0x53, 0xde, 0x12, 0x5e, 0x4d, 0x4c, 0x51, 0x10, 0xc9, 0xbd, 0x97, 0x68, 0xb7, 0x28, 0x79, 0x6b, 0xb0, + 0x09, 0xb1, 0xdb, 0x91, 0xc7, 0x7e, 0x72, 0xe4, 0xf5, 0xd2, 0xe6, 0x62, 0xa3, 0x32, 0x75, 0xf2, 0x92, 0xd2, 0x00, + 0xdb, 0x5b, 0x0a, 0x68, 0xe1, 0x2a, 0xa6, 0xba, 0x9c, 0xe6, 0x84, 0x16, 0xd3, 0x80, 0x33, 0x94, 0x1c, 0xfd, 0x4f, + 0x24, 0x1d, 0x6c, 0x1d, 0x7e, 0x72, 0xd1, 0x83, 0x17, 0xac, 0x35, 0xcd, 0x4a, 0x68, 0xb5, 0x27, 0xd8, 0x82, 0xe6, + 0x55, 0xf2, 0xa9, 0x51, 0x00, 0x9b, 0x17, 0x20, 0xab, 0x9f, 0x3e, 0xee, 0xc5, 0x23, 0xe7, 0xa7, 0x1c, 0xdc, 0x9e, + 0xea, 0x5b, 0x2f, 0x2c, 0x3b, 0xcd, 0x4a, 0x8a, 0x28, 0xc2, 0x93, 0xed, 0x85, 0xf8, 0xee, 0xcb, 0x48, 0x2e, 0x2e, + 0x13, 0x30, 0x43, 0x02, 0x22, 0xd8, 0xf7, 0xe4, 0x03, 0xdc, 0xa9, 0x81, 0x30, 0xad, 0xdf, 0x79, 0x10, 0x34, 0xad, + 0x33, 0x07, 0xc4, 0x4c, 0xc3, 0xec, 0xd2, 0x18, 0x70, 0xc3, 0xfb, 0xd7, 0x38, 0x77, 0x83, 0x7f, 0xac, 0xcc, 0x8a, + 0x66, 0xd3, 0xc0, 0xa6, 0x75, 0x43, 0x36, 0xc4, 0x85, 0x55, 0x8a, 0xc6, 0x55, 0xc6, 0x42, 0xd1, 0xe8, 0xd9, 0xab, + 0xcc, 0x52, 0xd9, 0x3f, 0x37, 0xad, 0x3f, 0xf6, 0x36, 0xb5, 0x25, 0x31, 0x6b, 0x29, 0x89, 0x86, 0xab, 0xcc, 0xcc, + 0xb1, 0x02, 0x10, 0x99, 0xe9, 0x43, 0x12, 0xd4, 0xe0, 0xeb, 0xf0, 0x85, 0x15, 0x53, 0xe5, 0x25, 0xbb, 0x1f, 0x32, + 0xfe, 0xf2, 0xd0, 0x41, 0xd1, 0x3b, 0x58, 0x85, 0x6f, 0x19, 0xf5, 0x9e, 0x06, 0x5d, 0xbf, 0xb4, 0x5a, 0x51, 0x97, + 0x9a, 0xe5, 0xe9, 0x67, 0xfc, 0x7e, 0x20, 0x9e, 0xc0, 0xfe, 0x54, 0x9c, 0xb1, 0x7d, 0x94, 0x7b, 0xc9, 0xe0, 0x9e, + 0xf4, 0x49, 0xea, 0x27, 0x34, 0x3a, 0x0a, 0xe7, 0x6d, 0xdd, 0xb7, 0x42, 0x5f, 0xb6, 0x27, 0x36, 0x8e, 0xa4, 0xee, + 0x52, 0xf2, 0x81, 0xb4, 0x75, 0xd0, 0x7d, 0x41, 0x90, 0xf0, 0x2b, 0xcb, 0x29, 0x05, 0x02, 0x13, 0x2e, 0x11, 0x47, + 0x08, 0xbc, 0x2e, 0xdd, 0x58, 0x40, 0x95, 0xe8, 0x03, 0xbb, 0xa5, 0x0d, 0xc1, 0xef, 0x40, 0xf8, 0xc5, 0x4e, 0x68, + 0x26, 0x57, 0x85, 0x9a, 0x99, 0x2a, 0x7b, 0x84, 0x36, 0x41, 0xcb, 0x89, 0xf4, 0xa4, 0x27, 0x0d, 0x26, 0xd0, 0x68, + 0xea, 0x95, 0x4f, 0x87, 0x60, 0xe8, 0x6a, 0x57, 0x5a, 0x1c, 0x58, 0x41, 0xc9, 0x40, 0xc3, 0x7a, 0x75, 0x29, 0x9d, + 0x16, 0x18, 0x03, 0x84, 0xe7, 0x5e, 0x5e, 0x36, 0x47, 0x2c, 0x7f, 0x77, 0x4b, 0x96, 0x1b, 0x1c, 0xf8, 0xd6, 0xc9, + 0xad, 0xe6, 0x92, 0x91, 0x9e, 0x9b, 0xbe, 0xed, 0xac, 0x9d, 0x28, 0x28, 0xab, 0xcd, 0x05, 0x0f, 0x01, 0x6a, 0x9a, + 0x7d, 0xd8, 0x62, 0x0b, 0x02, 0xce, 0x7a, 0x11, 0x12, 0xe4, 0x6d, 0x02, 0xbe, 0x7c, 0x3f, 0xc7, 0xde, 0x13, 0x51, + 0xb9, 0xac, 0xec, 0xc9, 0xe7, 0xb7, 0x8b, 0xaa, 0xbb, 0x25, 0x78, 0x56, 0x20, 0xdc, 0xf9, 0xc3, 0x38, 0xef, 0xeb, + 0xba, 0x57, 0x00, 0x58, 0x91, 0xf0, 0x49, 0x21, 0x07, 0x04, 0xa3, 0x99, 0x5e, 0xd5, 0xfd, 0x6d, 0xce, 0xa8, 0x29, + 0x9e, 0x22, 0x9c, 0x1c, 0x10, 0x7c, 0x67, 0x3a, 0x51, 0x9b, 0x95, 0xd6, 0x6a, 0x47, 0x64, 0x08, 0xa5, 0x6b, 0x8e, + 0xbb, 0x72, 0x03, 0x94, 0xbb, 0x48, 0x60, 0x86, 0x57, 0xb9, 0x2f, 0xc4, 0x87, 0x34, 0xbb, 0x6c, 0x19, 0xbc, 0x20, + 0x4f, 0xbb, 0x8a, 0xe5, 0x2e, 0x93, 0x71, 0x5d, 0x0b, 0x5b, 0xcc, 0x90, 0x43, 0xe6, 0x7e, 0xc6, 0x29, 0x6c, 0xb6, + 0x69, 0x9f, 0x27, 0x46, 0x6e, 0x69, 0xc3, 0x98, 0x08, 0x06, 0x2e, 0xb4, 0x26, 0xf2, 0x45, 0xbb, 0xb6, 0xdd, 0x9c, + 0xa1, 0xbc, 0xfa, 0xc9, 0xe0, 0xc1, 0x37, 0xff, 0xea, 0x8b, 0x27, 0xb3, 0xc7, 0x7d, 0x2e, 0x1e, 0x9f, 0x79, 0xff, + 0x74, 0x3f, 0xef, 0x65, 0xbb, 0xc0, 0xf5, 0x4e, 0x5e, 0x53, 0xe0, 0x74, 0x28, 0x25, 0x71, 0xd2, 0x01, 0x14, 0xc1, + 0x6d, 0x3b, 0x96, 0x87, 0x88, 0x75, 0xa2, 0xa0, 0x0b, 0x55, 0xce, 0x34, 0x33, 0x8e, 0xf3, 0xe5, 0x95, 0xb4, 0x35, + 0xb8, 0xfd, 0x3c, 0xa4, 0x1a, 0x08, 0xbe, 0xd0, 0x85, 0x09, 0x0d, 0x26, 0x23, 0x6e, 0x6b, 0xda, 0x12, 0x8b, 0x25, + 0x2e, 0x10, 0x39, 0x43, 0x01, 0xc8, 0x21, 0xd3, 0x05, 0xa5, 0xfb, 0x64, 0x32, 0x3c, 0x52, 0xde, 0x88, 0xcc, 0xc8, + 0x70, 0x40, 0xb2, 0x63, 0x7d, 0xe7, 0x6a, 0x26, 0xc2, 0x24, 0xec, 0x22, 0x3c, 0xfd, 0x4b, 0x96, 0xa4, 0x7c, 0xcc, + 0xd3, 0x7e, 0xae, 0x98, 0x80, 0x79, 0x45, 0xe9, 0x25, 0x45, 0xe9, 0x42, 0x0d, 0x7d, 0xcb, 0xb1, 0x38, 0xa7, 0x01, + 0x43, 0x61, 0xaa, 0x84, 0x51, 0x16, 0xd3, 0x66, 0x22, 0x0b, 0x68, 0xc1, 0x39, 0x0a, 0x96, 0x2b, 0x02, 0x8f, 0x2a, + 0xb9, 0x2e, 0xe5, 0x37, 0x11, 0x15, 0x5a, 0x8e, 0x1d, 0x70, 0xc3, 0xba, 0x63, 0x90, 0x95, 0x09, 0x4c, 0xbe, 0xad, + 0x4a, 0x32, 0x2f, 0x39, 0x62, 0x11, 0xde, 0x2f, 0xe7, 0xdb, 0x6e, 0xd7, 0x38, 0x80, 0xbb, 0x76, 0x48, 0x15, 0x56, + 0x31, 0x28, 0x10, 0x26, 0x8a, 0x17, 0xa5, 0xf1, 0x07, 0x09, 0xb6, 0x3a, 0x46, 0xb4, 0xb1, 0xf4, 0xa3, 0x95, 0xb8, + 0x29, 0x47, 0xf4, 0xb2, 0x46, 0x2b, 0x45, 0xbd, 0xcb, 0x0a, 0x18, 0x6d, 0x91, 0x49, 0x48, 0x80, 0xf3, 0xd5, 0xb9, + 0x9a, 0x5f, 0x1f, 0x3a, 0x6a, 0xdb, 0x00, 0x59, 0x2a, 0x15, 0xa7, 0x68, 0x31, 0x58, 0x46, 0x82, 0x71, 0x5b, 0xb3, + 0x0a, 0x1c, 0xbf, 0x67, 0xf2, 0x00, 0xfa, 0x2d, 0xda, 0xe5, 0xae, 0x6a, 0x20, 0x7c, 0x94, 0x11, 0x5d, 0xb0, 0xcb, + 0x40, 0xde, 0x84, 0xd4, 0x1b, 0xb4, 0x60, 0x9b, 0xb6, 0x5b, 0xeb, 0xb9, 0xa8, 0x0f, 0x7d, 0x01, 0x9b, 0x74, 0x59, + 0x51, 0xa3, 0xb5, 0xa1, 0x86, 0xc3, 0xd5, 0x86, 0x23, 0xbb, 0x41, 0x4f, 0x13, 0x3a, 0x20, 0xf5, 0xb5, 0x9f, 0xde, + 0xae, 0x2c, 0x00, 0xfe, 0x81, 0xba, 0x48, 0xf4, 0xfb, 0x32, 0xbe, 0x81, 0x06, 0x41, 0x19, 0x40, 0xb0, 0x93, 0xae, + 0xad, 0xf4, 0x1c, 0x0c, 0xc2, 0x9a, 0x51, 0x0b, 0x6f, 0xca, 0x8f, 0x29, 0xc8, 0x10, 0x4e, 0x49, 0x6c, 0xf0, 0xa6, + 0xdb, 0xc3, 0xc2, 0x3e, 0xdc, 0xe1, 0xac, 0x36, 0xa5, 0x3f, 0x21, 0x9a, 0x4c, 0x74, 0x00, 0x76, 0x57, 0x4d, 0x6c, + 0x7c, 0xd8, 0x0f, 0x2b, 0x72, 0x42, 0x75, 0xa8, 0xe8, 0x13, 0x65, 0x62, 0x9b, 0x5f, 0x76, 0x24, 0x79, 0xa1, 0xb4, + 0xc4, 0x17, 0x06, 0xfb, 0xa6, 0x8b, 0xb1, 0x50, 0x71, 0x80, 0xc4, 0x1c, 0x32, 0xa6, 0x3b, 0x6e, 0x11, 0x07, 0xd3, + 0x66, 0xa0, 0xec, 0x6f, 0xd6, 0xdb, 0x81, 0xad, 0x01, 0x28, 0x73, 0xcb, 0x4f, 0xfa, 0x5b, 0x14, 0x47, 0xb0, 0xa8, + 0x5f, 0x47, 0xa0, 0x25, 0xd7, 0xb5, 0x4f, 0xe2, 0x2c, 0x67, 0xe9, 0x91, 0x1b, 0x2e, 0xfa, 0x7d, 0x55, 0x24, 0x13, + 0xa2, 0xe9, 0x50, 0xc7, 0x56, 0x7c, 0xac, 0xa3, 0xd8, 0x2a, 0xdc, 0x80, 0xdf, 0x49, 0x43, 0xc4, 0x08, 0x19, 0xe3, + 0xb4, 0x24, 0xd0, 0xa9, 0xe5, 0x3c, 0x6d, 0x04, 0x6a, 0x6b, 0x52, 0xe6, 0x9e, 0xed, 0x4f, 0xa4, 0x83, 0x92, 0x3c, + 0xb2, 0x02, 0x68, 0xff, 0x56, 0x1f, 0x7d, 0x69, 0xa5, 0x20, 0x48, 0xb3, 0x24, 0x32, 0x38, 0xa3, 0xe3, 0x1c, 0x37, + 0x5e, 0x48, 0x90, 0x2c, 0x1e, 0x4e, 0x42, 0x9f, 0xb4, 0x59, 0x6b, 0xf0, 0xa4, 0xbc, 0x28, 0x37, 0x2e, 0x00, 0x75, + 0x7a, 0xc8, 0x16, 0x0d, 0x73, 0x16, 0xc8, 0x4e, 0xbc, 0x87, 0x18, 0x1e, 0xea, 0x52, 0x69, 0x01, 0x73, 0x7a, 0x86, + 0xa4, 0xb9, 0x2c, 0xb2, 0x1a, 0x17, 0x04, 0xfd, 0x66, 0xf2, 0x23, 0xf4, 0x39, 0x26, 0x4e, 0x97, 0xa7, 0x31, 0x55, + 0x23, 0x71, 0x7a, 0x36, 0xcf, 0xc0, 0x3a, 0x62, 0x8f, 0xec, 0x42, 0x2b, 0x86, 0xe8, 0x57, 0x71, 0x29, 0xe1, 0x30, + 0xcb, 0x0b, 0x41, 0x47, 0xf9, 0xc5, 0xc8, 0xd9, 0x8c, 0x09, 0x2e, 0x7d, 0xe2, 0x86, 0x1f, 0x4a, 0xa9, 0xa1, 0x80, + 0xcd, 0x10, 0x82, 0xf4, 0x57, 0x12, 0x7d, 0xb0, 0xd6, 0xc0, 0xf3, 0x9e, 0x2e, 0x26, 0xdc, 0x6b, 0xc2, 0x8c, 0x87, + 0x48, 0x4d, 0x28, 0x74, 0x22, 0x3a, 0x00, 0x43, 0x58, 0x76, 0xd3, 0xad, 0x25, 0xef, 0xc5, 0x3a, 0x0d, 0x9a, 0x83, + 0xa7, 0x0c, 0xc6, 0x1b, 0xb9, 0x1c, 0x47, 0x8c, 0xd8, 0xd7, 0x3d, 0x21, 0x7b, 0x2f, 0x46, 0x10, 0x21, 0x5f, 0x1c, + 0x90, 0x31, 0x45, 0x3b, 0xd5, 0xb4, 0xa4, 0x6b, 0xf6, 0xd9, 0x22, 0xf4, 0xcd, 0xed, 0x71, 0x46, 0x64, 0x4a, 0xaa, + 0x2f, 0x4c, 0x10, 0x11, 0x7a, 0x3a, 0x48, 0xc1, 0x9c, 0xdd, 0x07, 0xaf, 0x28, 0x02, 0x01, 0xd6, 0xdb, 0x6a, 0x78, + 0x52, 0x9d, 0x4f, 0x81, 0xed, 0xba, 0x90, 0x4e, 0xb3, 0x34, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x37, 0x49, 0x0d, 0x63, + 0xba, 0xa8, 0x7c, 0xc0, 0x1f, 0xd4, 0x47, 0xdc, 0xa2, 0xbf, 0x8a, 0xc7, 0x19, 0xf6, 0x92, 0x86, 0x6e, 0x12, 0xdb, + 0x84, 0xa8, 0xaa, 0xc6, 0xba, 0xe6, 0x66, 0xf4, 0xb8, 0x22, 0x03, 0xd7, 0x48, 0xfd, 0x06, 0xad, 0x83, 0x4a, 0x0b, + 0xeb, 0x59, 0x7c, 0x0a, 0xf2, 0xdc, 0x1a, 0x5b, 0xee, 0x4f, 0x90, 0xc4, 0x8b, 0xd1, 0x69, 0x46, 0x7b, 0x86, 0x97, + 0x19, 0x0e, 0x01, 0xf6, 0x9d, 0xe3, 0xdd, 0xae, 0xdd, 0x6f, 0x49, 0xc6, 0x4e, 0xc2, 0x9f, 0x6d, 0x5d, 0x92, 0x34, + 0x06, 0xd4, 0x94, 0x7f, 0x57, 0x3f, 0xe4, 0xb1, 0x17, 0x50, 0x71, 0x1f, 0x23, 0x5d, 0x2f, 0x34, 0x9f, 0xbe, 0x44, + 0x3b, 0xad, 0xdc, 0x3a, 0xbc, 0x45, 0x26, 0xee, 0x3e, 0xc2, 0x00, 0x73, 0x21, 0x77, 0x47, 0xa0, 0xee, 0xad, 0x5f, + 0x10, 0x6f, 0x8a, 0xba, 0xc2, 0x54, 0x4a, 0xb6, 0x1a, 0xbc, 0x96, 0x98, 0x85, 0x9a, 0xcb, 0x95, 0x46, 0xd8, 0xca, + 0x11, 0xa8, 0x83, 0x8e, 0xa4, 0xad, 0xf5, 0xda, 0xc6, 0xac, 0xf2, 0x54, 0x6e, 0x26, 0x0b, 0xfa, 0x1c, 0x49, 0x99, + 0x33, 0x87, 0xce, 0x8a, 0x42, 0x57, 0x25, 0x61, 0xa9, 0xe5, 0xd6, 0xeb, 0xb3, 0x8e, 0x5f, 0xbc, 0xb7, 0x03, 0x88, + 0x05, 0x7b, 0x56, 0x3b, 0x19, 0x1c, 0x76, 0x5b, 0x5c, 0x56, 0xb9, 0xda, 0xa6, 0x44, 0x59, 0x42, 0x60, 0x2e, 0x59, + 0x7d, 0x0d, 0xd0, 0x53, 0x14, 0x45, 0x1a, 0x74, 0xd5, 0x75, 0x41, 0x42, 0xb8, 0x52, 0xf1, 0x77, 0x17, 0x66, 0xe4, + 0x08, 0x97, 0x88, 0xdc, 0x41, 0x57, 0x4a, 0x7e, 0x3c, 0x21, 0x3d, 0x9d, 0x10, 0x09, 0xbd, 0xbc, 0x31, 0x78, 0x97, + 0x83, 0xc7, 0xfe, 0x2e, 0xe4, 0x0a, 0x1f, 0x12, 0x6c, 0x39, 0x0c, 0xa5, 0xdc, 0x14, 0xe1, 0xbe, 0x2f, 0xd0, 0x49, + 0xb9, 0x8a, 0xe0, 0x20, 0xb5, 0x23, 0x9f, 0xab, 0x23, 0x7f, 0x66, 0x73, 0x0a, 0x97, 0xe6, 0x64, 0xd7, 0x28, 0x42, + 0x99, 0x62, 0xef, 0x79, 0x62, 0x60, 0x4a, 0x12, 0x3e, 0xbb, 0x4e, 0x64, 0xad, 0x75, 0x7f, 0xa7, 0x3d, 0x88, 0x17, + 0x4d, 0xa4, 0xfc, 0x20, 0x36, 0x1f, 0x68, 0x71, 0x5d, 0x5e, 0x63, 0xeb, 0x8e, 0x62, 0x06, 0xa0, 0xb9, 0xc9, 0xba, + 0xad, 0x32, 0xb9, 0xc1, 0x2a, 0x20, 0x4f, 0x67, 0xa1, 0xf1, 0x2c, 0xcd, 0x60, 0x9e, 0x9f, 0x38, 0x2b, 0x46, 0x2a, + 0x04, 0x8a, 0xd2, 0x52, 0x9b, 0xd5, 0x49, 0x5c, 0xc9, 0x8e, 0x3d, 0x6e, 0xd9, 0x42, 0x27, 0x20, 0xd5, 0xe3, 0x04, + 0xb4, 0x0d, 0xde, 0x51, 0x4a, 0x76, 0x67, 0x19, 0x07, 0xdb, 0x85, 0x7f, 0x07, 0x66, 0x1d, 0xea, 0xab, 0x08, 0x2a, + 0xd2, 0x26, 0xb6, 0x6a, 0x4a, 0x91, 0x74, 0x42, 0xeb, 0x62, 0x0b, 0x8a, 0xe2, 0x6a, 0x8f, 0xf8, 0xaa, 0x95, 0xe1, + 0xce, 0xec, 0xb6, 0xc8, 0xe6, 0x0c, 0xf7, 0x64, 0xe0, 0x8c, 0x2d, 0xa1, 0xcd, 0xac, 0x25, 0xf6, 0x71, 0x4f, 0x37, + 0xe9, 0xef, 0xb6, 0x92, 0x66, 0xd0, 0x88, 0xa1, 0xa5, 0x65, 0xf2, 0xef, 0x8d, 0xc9, 0xbc, 0x16, 0x43, 0x63, 0x4e, + 0x31, 0xdd, 0x30, 0x70, 0x8b, 0x2a, 0xb5, 0x19, 0xd7, 0x8a, 0x3e, 0xfd, 0x4e, 0x23, 0x39, 0xa4, 0x00, 0x4d, 0x28, + 0x05, 0x11, 0xc8, 0x97, 0x14, 0x82, 0x3b, 0x25, 0xdb, 0x44, 0x96, 0x5b, 0x89, 0xcb, 0xa2, 0xd3, 0xc3, 0xf1, 0x0f, + 0x27, 0xa0, 0x42, 0x5f, 0xae, 0x58, 0xd0, 0x4f, 0xf4, 0x3e, 0x26, 0xea, 0x58, 0xca, 0xc9, 0xf1, 0xe9, 0xd2, 0x55, + 0x55, 0x01, 0x2d, 0x57, 0xaf, 0x8b, 0x0e, 0xce, 0x35, 0x65, 0x80, 0xd4, 0x63, 0x14, 0xb6, 0x10, 0x26, 0x7f, 0x04, + 0xde, 0x4f, 0xef, 0xe5, 0xb8, 0xed, 0x36, 0x45, 0x8f, 0x74, 0x76, 0xa7, 0x48, 0x4d, 0x2a, 0xd1, 0xca, 0xc9, 0x31, + 0x9e, 0x1e, 0xf2, 0x62, 0x0c, 0xd8, 0x31, 0x71, 0xb3, 0x49, 0x0d, 0x18, 0x13, 0x80, 0x23, 0x33, 0x15, 0xdb, 0x54, + 0x5b, 0x2b, 0x13, 0xa2, 0xb6, 0xe5, 0x7c, 0x59, 0x4b, 0xa7, 0x28, 0xef, 0x60, 0x0e, 0x81, 0x79, 0xee, 0x32, 0x6d, + 0xa0, 0x9a, 0x22, 0xb3, 0xa4, 0x1d, 0xd5, 0xf1, 0x52, 0x6c, 0xbc, 0xf8, 0xa9, 0xc0, 0xbd, 0x91, 0xaa, 0x57, 0x56, + 0x0b, 0x6e, 0xce, 0x94, 0x71, 0xb8, 0xc5, 0x55, 0xe1, 0x24, 0xe2, 0x01, 0x8c, 0x3e, 0x63, 0x31, 0x9c, 0x2f, 0xf6, + 0x23, 0x3e, 0x2c, 0x6a, 0x0a, 0x6f, 0xab, 0xb7, 0x72, 0x5c, 0x86, 0x80, 0xea, 0x11, 0xc4, 0xe9, 0x4e, 0x65, 0xc1, + 0xeb, 0x8c, 0x1c, 0x11, 0xbe, 0x95, 0xe2, 0xa8, 0x64, 0x1c, 0xc4, 0x67, 0xb1, 0xe9, 0xc1, 0x31, 0x2d, 0x3c, 0x63, + 0x22, 0x77, 0xc0, 0x3c, 0xa3, 0xf1, 0x3d, 0x3e, 0x73, 0x43, 0x7c, 0xe7, 0xb5, 0xf7, 0xb6, 0x22, 0x3d, 0x37, 0xb3, + 0xf9, 0xc4, 0x9b, 0x86, 0xa8, 0xf3, 0xe1, 0xad, 0x27, 0x3a, 0xe7, 0x15, 0x2c, 0xe2, 0x50, 0xb8, 0x21, 0xcd, 0xe8, + 0x0b, 0xed, 0x1e, 0xb2, 0x79, 0x6a, 0xba, 0x8b, 0x0b, 0xd8, 0xa3, 0xe9, 0x77, 0x67, 0x04, 0xc4, 0x3e, 0x41, 0xc4, + 0x97, 0x3c, 0xb8, 0xbd, 0x75, 0x2b, 0x6d, 0x75, 0x8c, 0x91, 0x6a, 0xd3, 0xdc, 0x02, 0xbf, 0xdf, 0x97, 0x30, 0x7b, + 0x1c, 0x83, 0x77, 0x0d, 0x02, 0xc4, 0x2f, 0x40, 0x58, 0x35, 0x6d, 0x68, 0xc0, 0x77, 0xf8, 0x32, 0x5b, 0xe6, 0x5e, + 0x23, 0xaa, 0x1e, 0xe6, 0xf2, 0xc5, 0xc9, 0xae, 0x36, 0x22, 0x95, 0xdb, 0x7e, 0xe2, 0xcf, 0x0f, 0x86, 0x25, 0x3d, + 0x47, 0x87, 0x71, 0x20, 0x37, 0xe4, 0xcc, 0x28, 0xb1, 0x09, 0xa7, 0xad, 0x9c, 0x87, 0xc6, 0x3c, 0x15, 0x04, 0x64, + 0xf8, 0xff, 0x7a, 0x38, 0x48, 0xcc, 0x5b, 0x37, 0x28, 0x57, 0xd5, 0x06, 0xd6, 0x64, 0x2f, 0x0e, 0x22, 0xa8, 0xf2, + 0x50, 0xa4, 0x58, 0x5f, 0x74, 0x58, 0x97, 0xc4, 0x42, 0x26, 0x82, 0x51, 0x21, 0x49, 0x90, 0xad, 0xa3, 0x5b, 0xa3, + 0xdc, 0x25, 0xbd, 0x4e, 0x40, 0xcf, 0xf4, 0x32, 0xfe, 0x18, 0xc7, 0xa2, 0xac, 0x25, 0x7f, 0xee, 0x49, 0xb6, 0xcb, + 0xe8, 0xae, 0x66, 0xac, 0x23, 0x22, 0x36, 0xb4, 0x1c, 0x1d, 0xe7, 0x65, 0x51, 0x72, 0xdc, 0xb4, 0x27, 0x70, 0x2c, + 0xbc, 0xb3, 0xa2, 0x68, 0xe6, 0x42, 0xae, 0xe9, 0xab, 0x63, 0x8a, 0xd6, 0xe1, 0x31, 0x7b, 0x6d, 0xdb, 0x12, 0x3d, + 0x5c, 0x8e, 0xf1, 0x52, 0x1a, 0x2a, 0x34, 0x87, 0xda, 0x5a, 0x5d, 0xea, 0x39, 0x2c, 0x63, 0xc5, 0x17, 0x85, 0x52, + 0xee, 0xa2, 0xe1, 0xa9, 0x8b, 0x69, 0x40, 0x37, 0x69, 0x44, 0x3f, 0x91, 0x99, 0x53, 0x8d, 0x3c, 0xe9, 0xc7, 0xbe, + 0x51, 0x85, 0x01, 0xd0, 0xf1, 0x8a, 0x91, 0xec, 0xbe, 0x2f, 0x57, 0x87, 0x12, 0x7c, 0x7a, 0xd6, 0x51, 0x2c, 0xb5, + 0x8e, 0xf7, 0x79, 0x2d, 0xc7, 0x77, 0x37, 0x84, 0xd1, 0xba, 0x3d, 0x30, 0x2b, 0x9c, 0x8b, 0x49, 0x31, 0x6e, 0xd9, + 0x0a, 0x13, 0xe6, 0x11, 0x4a, 0xbc, 0x9b, 0xa2, 0xb1, 0x5f, 0x99, 0x12, 0x9d, 0x17, 0xe1, 0x65, 0x73, 0xc5, 0x42, + 0xa9, 0x7a, 0x71, 0x89, 0xfd, 0xc6, 0xbd, 0xed, 0x39, 0xe4, 0xb9, 0x0c, 0x1b, 0x6f, 0x67, 0x79, 0x7a, 0xc4, 0xe4, + 0xfc, 0x08, 0x9b, 0x79, 0x20, 0x7d, 0x2d, 0x04, 0x18, 0xf5, 0x9e, 0x1c, 0xbf, 0x7c, 0xdf, 0xcb, 0xae, 0x71, 0xbc, + 0x30, 0xd2, 0x38, 0xce, 0x17, 0xe4, 0x29, 0xb1, 0x44, 0x69, 0xe6, 0x8b, 0x7a, 0x94, 0x03, 0xf1, 0xdc, 0x0b, 0x76, + 0x3d, 0x6d, 0xc7, 0xbf, 0x17, 0xee, 0x4a, 0x7a, 0x34, 0xfa, 0x04, 0xbe, 0x1e, 0xfe, 0x73, 0x74, 0x58, 0x90, 0x44, + 0x44, 0x4f, 0xe3, 0x48, 0x4f, 0x6d, 0x59, 0xea, 0x3d, 0x3b, 0xd6, 0x44, 0xbd, 0xf1, 0x3a, 0x23, 0x94, 0xb6, 0xa1, + 0x94, 0xb6, 0x83, 0x32, 0x82, 0x25, 0xb0, 0x69, 0x53, 0x08, 0x51, 0x8d, 0xff, 0x82, 0x9b, 0xa7, 0x08, 0x3f, 0xeb, + 0x44, 0x69, 0x36, 0x53, 0x53, 0x74, 0x67, 0x34, 0x00, 0x6b, 0x79, 0x9f, 0x0d, 0xd0, 0xfa, 0xa1, 0xae, 0xbc, 0xc2, + 0xc0, 0x6a, 0x55, 0x57, 0x02, 0xb5, 0x22, 0x50, 0x82, 0x04, 0x4e, 0x78, 0x2f, 0x22, 0xa2, 0x1b, 0x98, 0x54, 0x7a, + 0xb0, 0x65, 0x3b, 0xb7, 0x0d, 0xbb, 0xd7, 0xd2, 0xe7, 0x87, 0xf7, 0x6a, 0xd2, 0x53, 0x57, 0x76, 0xc7, 0x43, 0xe4, + 0x24, 0x39, 0xbb, 0x07, 0x88, 0xe4, 0x51, 0x32, 0xd8, 0xb9, 0x7b, 0x7b, 0xda, 0xda, 0x1d, 0x62, 0x61, 0x5b, 0xf0, + 0xd3, 0x1d, 0xb1, 0x18, 0xa5, 0xdd, 0xec, 0x93, 0x9f, 0x67, 0x70, 0x58, 0x7a, 0x0b, 0xe0, 0x29, 0xd6, 0xdd, 0x5f, + 0xcd, 0xac, 0xe8, 0x1e, 0xff, 0xe2, 0xa1, 0x2b, 0x0a, 0xe9, 0x88, 0x59, 0xdc, 0xe2, 0xb8, 0x2e, 0x3b, 0xab, 0xbb, + 0x45, 0xce, 0x6d, 0x49, 0x84, 0x4a, 0x09, 0xc9, 0xe5, 0x98, 0x95, 0x1a, 0xdb, 0x23, 0xca, 0xe0, 0xb4, 0xb7, 0x97, + 0x7e, 0x63, 0xde, 0xc2, 0xf4, 0x05, 0xa0, 0x26, 0x60, 0xb9, 0x20, 0x1b, 0xef, 0x3e, 0x00, 0xcc, 0xd2, 0xaa, 0xab, + 0x33, 0x06, 0x17, 0xb7, 0xee, 0x7a, 0xc3, 0x22, 0x33, 0x9a, 0x89, 0xba, 0xc9, 0xdd, 0x11, 0x55, 0x8c, 0x16, 0x26, + 0xdb, 0x2f, 0xa5, 0xe1, 0xd3, 0x6a, 0x44, 0x2b, 0x2d, 0x5a, 0x46, 0x87, 0x5d, 0x5f, 0xc9, 0x51, 0x22, 0xb1, 0x5c, + 0x2c, 0xbb, 0xf2, 0x56, 0x98, 0xf8, 0x31, 0xb1, 0x36, 0x66, 0x44, 0x5a, 0xb2, 0x85, 0xc1, 0x11, 0x49, 0x79, 0xd4, + 0xdd, 0xb2, 0x6a, 0x72, 0x1b, 0x67, 0x2b, 0x3c, 0xdd, 0x52, 0xd4, 0x14, 0xaa, 0x43, 0xb4, 0xdd, 0x07, 0x19, 0x24, + 0xd3, 0x46, 0x91, 0xf3, 0xb9, 0xed, 0xb1, 0x88, 0x3a, 0x5d, 0xd1, 0x69, 0x91, 0x88, 0xb9, 0xdd, 0x53, 0xb4, 0x1d, + 0x25, 0xc9, 0x93, 0x94, 0x4c, 0x27, 0x0e, 0x54, 0xd3, 0x86, 0x5c, 0x4b, 0xef, 0x5f, 0x2b, 0x02, 0x71, 0xf1, 0x1f, + 0xf2, 0xb2, 0xed, 0xbb, 0x03, 0x83, 0x08, 0x3a, 0x98, 0x23, 0x09, 0xcc, 0x4b, 0x2d, 0x1d, 0x94, 0x48, 0x12, 0x91, + 0x9f, 0x34, 0xcc, 0xae, 0x4b, 0xd6, 0xe8, 0x83, 0x56, 0xba, 0x33, 0x99, 0x35, 0x24, 0x52, 0xaf, 0x49, 0x6d, 0x6d, + 0xb1, 0x89, 0x11, 0xcf, 0x7c, 0x67, 0x9d, 0x88, 0x22, 0xf1, 0x20, 0x73, 0x62, 0xa9, 0x3c, 0x5b, 0x44, 0x89, 0xaf, + 0x70, 0xf6, 0xb5, 0x5e, 0xec, 0x4e, 0x8b, 0x2c, 0xe6, 0x87, 0x91, 0x5f, 0x0e, 0x37, 0xbb, 0x15, 0x29, 0xea, 0xad, + 0xf1, 0xe5, 0x05, 0xcd, 0x6c, 0x5c, 0x3b, 0x71, 0xcc, 0x19, 0xd2, 0x48, 0x21, 0x48, 0x48, 0x9f, 0x8e, 0xf0, 0x5a, + 0x04, 0x07, 0x36, 0x6a, 0x7a, 0xc7, 0x9e, 0x67, 0x2b, 0x77, 0x57, 0x43, 0xc3, 0xb6, 0x43, 0x22, 0x48, 0xd0, 0x78, + 0x93, 0x59, 0x33, 0x34, 0x3f, 0xec, 0x3a, 0x6f, 0xcf, 0xf5, 0xf0, 0x8d, 0x62, 0x60, 0x69, 0x13, 0x09, 0xe0, 0x52, + 0x51, 0x95, 0xe6, 0xd6, 0x7e, 0x90, 0x43, 0x36, 0xe2, 0x8b, 0x56, 0xfd, 0x8a, 0x80, 0xee, 0x24, 0x21, 0x21, 0x40, + 0xd3, 0xeb, 0xfa, 0x3e, 0x5c, 0x24, 0x2c, 0x0e, 0x08, 0xdf, 0x55, 0xf0, 0xdf, 0x24, 0x4d, 0xaf, 0x4b, 0x13, 0xfa, + 0xb1, 0x28, 0x97, 0x83, 0x83, 0x2c, 0x10, 0x6f, 0x01, 0xd1, 0x10, 0x04, 0x82, 0x42, 0x58, 0x38, 0xa6, 0x12, 0xfa, + 0x17, 0x5a, 0x43, 0xc1, 0x04, 0x98, 0x8e, 0xc6, 0xb9, 0x34, 0x28, 0xaa, 0xad, 0x74, 0x9a, 0x53, 0x36, 0x5c, 0x34, + 0x0c, 0x32, 0xeb, 0x9f, 0xc2, 0x10, 0xa7, 0x98, 0x26, 0xe3, 0xfe, 0x2e, 0xc1, 0x78, 0xba, 0x6d, 0x3e, 0x51, 0xca, + 0x6a, 0x9f, 0xb5, 0x78, 0x42, 0x2b, 0x9e, 0x57, 0xa2, 0x3e, 0xa7, 0xd7, 0xde, 0x7f, 0xf4, 0x86, 0xef, 0xe0, 0xc9, + 0x47, 0x25, 0x7a, 0x1b, 0x27, 0x96, 0x3b, 0x58, 0x04, 0x58, 0xe4, 0x7d, 0xd7, 0x8c, 0xa4, 0x40, 0x86, 0x3a, 0xc0, + 0x5c, 0x63, 0x6e, 0xfb, 0x48, 0x0d, 0x6d, 0x0f, 0xe5, 0xde, 0xe4, 0xda, 0x34, 0xac, 0x7a, 0x58, 0x60, 0x79, 0x75, + 0xdd, 0xe6, 0xe6, 0x00, 0x79, 0xec, 0x5a, 0x8c, 0x08, 0x72, 0x44, 0x86, 0xe3, 0xc1, 0x6d, 0x42, 0x41, 0x80, 0x02, + 0xaa, 0xa6, 0x9a, 0xd6, 0xe1, 0xfe, 0x9c, 0x0f, 0xe2, 0x50, 0xd7, 0x84, 0xd8, 0xa8, 0x3c, 0x42, 0xaf, 0xb9, 0xef, + 0x13, 0xfd, 0x3e, 0xe5, 0x86, 0xc6, 0x1b, 0x24, 0x40, 0x2e, 0xae, 0xce, 0x93, 0x44, 0xdd, 0x18, 0xab, 0xa3, 0x38, + 0x22, 0x0c, 0x50, 0x98, 0x63, 0x38, 0xdc, 0x4e, 0x05, 0x47, 0x4b, 0x02, 0x6d, 0x2c, 0x55, 0x2f, 0xb7, 0xdf, 0x66, + 0x5d, 0xea, 0x1f, 0x14, 0x0c, 0xa2, 0xd3, 0x43, 0x5e, 0x38, 0x10, 0x32, 0xd6, 0xf7, 0xe1, 0xf2, 0x1e, 0x67, 0xb4, + 0x2e, 0xa3, 0x46, 0x30, 0x06, 0x0f, 0x50, 0xce, 0xaa, 0xc7, 0xd1, 0x2e, 0x20, 0x96, 0x87, 0xf4, 0xa1, 0xc9, 0x8c, + 0x90, 0x2d, 0x72, 0xf9, 0xa5, 0x16, 0xf9, 0xab, 0xd0, 0xb5, 0x78, 0xee, 0x01, 0x9d, 0x5a, 0x70, 0x0c, 0x75, 0x83, + 0xaf, 0xba, 0xe9, 0xaa, 0x96, 0xda, 0x36, 0xc7, 0xc8, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x6c, 0xdf, 0x7b, 0x07, + 0x80, 0x98, 0x02, 0x7a, 0x01, 0xb0, 0x1d, 0x5e, 0x0a, 0x3e, 0xf1, 0xe0, 0xb6, 0x3a, 0xec, 0xd8, 0x99, 0xa4, 0x71, + 0x1e, 0x4d, 0xbd, 0x39, 0xc7, 0x5c, 0xe8, 0x71, 0xec, 0xe7, 0x06, 0xd7, 0x9f, 0xac, 0x18, 0xbe, 0x6d, 0x4d, 0x70, + 0x78, 0xae, 0x72, 0x36, 0x24, 0x11, 0x4b, 0xd6, 0x3d, 0x47, 0x5f, 0x48, 0xe4, 0x69, 0x1b, 0xdf, 0x2f, 0xf4, 0xd5, + 0x39, 0x75, 0x91, 0x9d, 0x63, 0x92, 0x09, 0xf4, 0x60, 0xf2, 0x5e, 0x59, 0x1c, 0x1a, 0xab, 0x94, 0x59, 0xfc, 0xd0, + 0xb9, 0xa6, 0xb7, 0xf7, 0xab, 0x75, 0x29, 0xe5, 0x53, 0xad, 0x72, 0x2b, 0xbf, 0x8d, 0x1d, 0x4d, 0x3b, 0x35, 0xa0, + 0xdd, 0xd6, 0x37, 0x74, 0x1a, 0x45, 0x24, 0xe9, 0xee, 0x82, 0x5b, 0x78, 0x06, 0xd3, 0x18, 0x51, 0xb0, 0xe7, 0x53, + 0xeb, 0xf2, 0xb5, 0x97, 0x95, 0x78, 0x45, 0xbc, 0x2b, 0x06, 0x63, 0xe5, 0x84, 0x0e, 0x16, 0x69, 0x1a, 0x68, 0xe0, + 0x24, 0x49, 0xdc, 0xaa, 0x24, 0x7e, 0x6a, 0xf9, 0x17, 0xd4, 0xdc, 0xa8, 0x3c, 0x15, 0xf1, 0x75, 0x49, 0x98, 0x39, + 0x2e, 0xd5, 0xbd, 0x51, 0x79, 0x50, 0x8e, 0x79, 0xba, 0x66, 0x2c, 0x5a, 0xba, 0x9d, 0x22, 0xf3, 0x64, 0xcf, 0x9b, + 0x9b, 0x11, 0x25, 0x4a, 0x84, 0xea, 0x42, 0xaf, 0x72, 0x6d, 0x16, 0x3a, 0xd2, 0x88, 0x4d, 0x6b, 0x35, 0x9b, 0xd8, + 0xfd, 0x70, 0x0e, 0x52, 0x95, 0x3d, 0xc1, 0x35, 0xf4, 0xbc, 0x13, 0x86, 0xcd, 0xb5, 0xae, 0x43, 0x23, 0x86, 0xcc, + 0x80, 0x99, 0x66, 0x01, 0xa6, 0x40, 0x16, 0x71, 0x5f, 0x0d, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0xf5, 0x7c, 0xab, + 0xad, 0x3a, 0x26, 0xff, 0x32, 0x78, 0x0d, 0x67, 0x00, 0x45, 0x89, 0xe1, 0x44, 0xd3, 0x5e, 0xa9, 0xd5, 0x00, 0x61, + 0x9e, 0x10, 0xa3, 0xb0, 0x82, 0x6d, 0xd1, 0x68, 0xd5, 0x55, 0x30, 0x80, 0x1a, 0xe6, 0xc9, 0x08, 0x8d, 0x22, 0x32, + 0x1a, 0x5f, 0xd8, 0x8d, 0xbc, 0xb2, 0x00, 0xcb, 0x9a, 0xf4, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x8e, 0x12, + 0x72, 0xc3, 0x0d, 0x9a, 0x36, 0xa9, 0x37, 0x1e, 0x07, 0x7c, 0x6b, 0xc6, 0x99, 0x86, 0x76, 0xdb, 0x5a, 0xb9, 0x0f, + 0xec, 0xc0, 0x0d, 0xb7, 0x0d, 0xdf, 0xa9, 0x6a, 0x27, 0xf3, 0xf5, 0xeb, 0xdd, 0xee, 0x12, 0x6b, 0x42, 0x9b, 0x8e, + 0xb2, 0x06, 0xb6, 0x6d, 0x51, 0xcc, 0xc5, 0x48, 0xd7, 0x78, 0xb7, 0xd8, 0x77, 0x20, 0xdb, 0xf7, 0x60, 0xad, 0x92, + 0x90, 0x93, 0xab, 0x74, 0x7e, 0x8d, 0x7e, 0xd2, 0xe9, 0x2a, 0x91, 0x99, 0x5d, 0xe4, 0x77, 0x99, 0xa9, 0xef, 0x65, + 0xaa, 0xc7, 0xb5, 0x56, 0xa4, 0xc0, 0x56, 0xa8, 0x0a, 0xcf, 0x21, 0x30, 0x5d, 0xb2, 0xf2, 0x7f, 0x20, 0xe2, 0x9c, + 0x8c, 0x2b, 0xa1, 0xbd, 0x51, 0x35, 0x03, 0x18, 0x12, 0x8a, 0xa1, 0x89, 0xe5, 0xf4, 0xb8, 0xd4, 0x20, 0xaa, 0x93, + 0x06, 0x90, 0xe5, 0x81, 0x10, 0xf0, 0x13, 0x05, 0xd4, 0x99, 0x99, 0x30, 0xf0, 0x93, 0xc0, 0x59, 0x5a, 0x4d, 0x91, + 0x7e, 0x31, 0xe0, 0x0c, 0x45, 0xdd, 0x90, 0x7e, 0xc5, 0x94, 0xe8, 0x0e, 0xbf, 0x52, 0x68, 0x7d, 0x6a, 0x66, 0x2e, + 0x98, 0x91, 0x4e, 0x1a, 0xf8, 0x15, 0x2e, 0x6a, 0x0b, 0xfe, 0x32, 0xa5, 0x26, 0x33, 0x45, 0x98, 0xc9, 0x01, 0x5c, + 0x2a, 0xb7, 0xc5, 0xb3, 0xaa, 0x26, 0x30, 0xfb, 0x22, 0x65, 0x74, 0xe2, 0x18, 0x75, 0xdf, 0x6e, 0x38, 0x4a, 0x52, + 0xde, 0xfe, 0x7a, 0x95, 0x35, 0xca, 0x0e, 0x99, 0x59, 0xea, 0x2a, 0xfe, 0xd4, 0x24, 0x77, 0xbd, 0x0c, 0x9d, 0x74, + 0x2b, 0xb8, 0x65, 0x94, 0xf3, 0x0c, 0xcb, 0xdd, 0x18, 0xd1, 0x61, 0x73, 0x2f, 0x5d, 0xdf, 0xa5, 0xc9, 0xce, 0xad, + 0x4a, 0x4c, 0x08, 0x29, 0xb4, 0x5f, 0x9f, 0x9d, 0xfb, 0xe3, 0xd5, 0xf6, 0xdb, 0x51, 0xdf, 0x73, 0xe3, 0x7c, 0x3a, + 0xfe, 0xed, 0x72, 0xdb, 0x1d, 0x4c, 0x33, 0x54, 0x61, 0x5a, 0x3a, 0x08, 0xdd, 0x35, 0x0f, 0xd0, 0xbf, 0x24, 0x3e, + 0xf5, 0xfb, 0x0b, 0x2a, 0x1d, 0xd0, 0x26, 0xb3, 0x35, 0x15, 0xb2, 0x38, 0x28, 0xa1, 0x6c, 0xd3, 0x2e, 0x4d, 0x8b, + 0x29, 0x72, 0xa0, 0x6e, 0x21, 0x03, 0x52, 0xb2, 0x70, 0x99, 0x41, 0xe5, 0x57, 0xf1, 0x3a, 0xf1, 0x75, 0x7e, 0xb5, + 0x31, 0x32, 0xa2, 0x70, 0x55, 0xc8, 0x35, 0x7c, 0x47, 0x8b, 0x79, 0x01, 0xed, 0xa4, 0xda, 0x38, 0xf4, 0x55, 0xa3, + 0x8e, 0x49, 0xa0, 0xe3, 0xc3, 0x4f, 0x3e, 0x53, 0x37, 0x98, 0xdd, 0xad, 0x09, 0xf8, 0xb1, 0x39, 0x7b, 0x71, 0xa3, + 0x87, 0x38, 0xb5, 0x96, 0x7d, 0xbc, 0x50, 0xf6, 0xa8, 0x1a, 0x79, 0x6b, 0x8d, 0x83, 0xdc, 0xa4, 0x61, 0x6d, 0x38, + 0x29, 0x14, 0xe0, 0xe1, 0x52, 0x7e, 0x48, 0x0a, 0x97, 0xde, 0xa8, 0x44, 0x98, 0x07, 0xb0, 0x13, 0xb6, 0xd4, 0xbd, + 0x51, 0x49, 0x0b, 0xa8, 0x1e, 0xe9, 0xc9, 0xa0, 0x98, 0xce, 0x89, 0xc4, 0x98, 0xf1, 0x25, 0xdd, 0xf4, 0x43, 0xb4, + 0xba, 0x66, 0xd8, 0xc3, 0xfb, 0x58, 0x90, 0x20, 0x87, 0x04, 0x1b, 0xd7, 0x19, 0x42, 0xec, 0xa4, 0xc2, 0xf7, 0x7c, + 0x55, 0x6c, 0x99, 0x7f, 0x46, 0xa8, 0x6d, 0xeb, 0xbe, 0xed, 0x11, 0xe5, 0xb5, 0xd2, 0xb7, 0xb9, 0xbf, 0xe2, 0x8c, + 0xf1, 0x72, 0x86, 0xc6, 0x23, 0x2f, 0xfb, 0x39, 0xcc, 0xcf, 0x7e, 0x75, 0x03, 0x16, 0x20, 0x71, 0x6c, 0xc1, 0xb1, + 0xa7, 0xe4, 0x68, 0xae, 0x73, 0x3e, 0xb6, 0x11, 0xcc, 0x92, 0x69, 0x40, 0x64, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, + 0x71, 0x91, 0x28, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7c, 0x6f, 0x22, 0xf7, 0x05, 0x2d, 0x46, 0x59, 0xfc, 0xb1, 0xab, + 0xb6, 0xb6, 0x8a, 0x1c, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0xe3, 0x58, 0x15, 0x50, 0xbe, 0xce, 0x95, 0xd6, 0x52, + 0x5d, 0xa0, 0x8b, 0x43, 0xf7, 0x51, 0x8b, 0x8a, 0x6a, 0x35, 0x18, 0xf7, 0x40, 0xd9, 0x6b, 0x98, 0xd0, 0x03, 0x7e, + 0xb6, 0x0e, 0x63, 0x36, 0x78, 0xe7, 0xcd, 0xb1, 0x1a, 0xd3, 0x45, 0xce, 0x7b, 0x0b, 0xa8, 0x75, 0xbb, 0xde, 0x92, + 0x9a, 0x08, 0xad, 0x71, 0x93, 0x71, 0x58, 0x24, 0x7c, 0x17, 0x75, 0x38, 0x41, 0x21, 0x09, 0x20, 0x36, 0xc5, 0x08, + 0x53, 0xd0, 0x9a, 0x71, 0xb1, 0xa1, 0x85, 0xdd, 0x44, 0x77, 0xac, 0xcd, 0x23, 0xca, 0x38, 0xdc, 0xd1, 0x4c, 0x87, + 0xb9, 0xb9, 0x96, 0xe0, 0x7b, 0x89, 0xe8, 0x6d, 0xaa, 0xa6, 0x1d, 0x15, 0x36, 0xb7, 0x69, 0x64, 0xcc, 0x4c, 0x8f, + 0x77, 0x81, 0x76, 0xe3, 0xc9, 0xe8, 0x27, 0x54, 0xf0, 0xe7, 0x73, 0x5f, 0x24, 0x03, 0xf7, 0xd9, 0xe7, 0x01, 0x62, + 0x68, 0x4f, 0x9d, 0xee, 0x37, 0xb5, 0xac, 0x73, 0xc0, 0x14, 0x9b, 0xc4, 0xec, 0x67, 0x1c, 0xf5, 0x87, 0x1d, 0x6d, + 0x1c, 0x24, 0xc5, 0x10, 0x28, 0x1d, 0x7e, 0xdc, 0xd1, 0xca, 0xeb, 0xb6, 0xec, 0xdd, 0xf6, 0x1a, 0x77, 0xe4, 0x63, + 0xaa, 0x07, 0x93, 0x20, 0x49, 0xcb, 0xb1, 0x08, 0xcd, 0x18, 0xbc, 0x45, 0x5a, 0xb0, 0xb6, 0x47, 0x40, 0xcb, 0x5c, + 0x2f, 0x14, 0x7a, 0xe0, 0xe9, 0x3b, 0x73, 0x27, 0x85, 0xc5, 0x58, 0x2e, 0xe9, 0xe0, 0xd9, 0x04, 0xb3, 0x59, 0xd5, + 0x6a, 0x7d, 0x77, 0x68, 0x7b, 0xea, 0x2d, 0x10, 0x76, 0x5e, 0xea, 0x9b, 0x81, 0x23, 0x3f, 0xb3, 0x96, 0xc1, 0x94, + 0x73, 0xbb, 0xc1, 0xbb, 0xfe, 0xe8, 0x6f, 0xca, 0xe0, 0x63, 0x7f, 0x8d, 0xe3, 0xf7, 0x54, 0xdd, 0xb2, 0x74, 0xc2, + 0x74, 0x65, 0x3e, 0x46, 0x2b, 0x35, 0xf7, 0x39, 0x8c, 0xc9, 0x74, 0x80, 0x12, 0x1b, 0xf9, 0xba, 0x0b, 0x07, 0xd4, + 0x2d, 0xa3, 0xf8, 0x8a, 0x5f, 0xd6, 0x6f, 0xf7, 0x25, 0xed, 0x6d, 0xf7, 0x5b, 0x30, 0x53, 0xaf, 0xac, 0x04, 0x8f, + 0x0a, 0x02, 0x3c, 0x04, 0x95, 0xc9, 0xa3, 0xca, 0x12, 0xf0, 0x45, 0xbd, 0x0b, 0x90, 0x88, 0x3c, 0xad, 0x47, 0x79, + 0x09, 0x1b, 0xd5, 0xb0, 0xed, 0x7a, 0x5a, 0x1d, 0x08, 0x89, 0xd1, 0x1c, 0x4f, 0x9b, 0xb5, 0xe6, 0x5a, 0x19, 0x7e, + 0x89, 0x12, 0x17, 0xcf, 0xc6, 0x51, 0xb5, 0x51, 0x20, 0xe4, 0xaa, 0x16, 0x4a, 0xc4, 0xa2, 0xc3, 0x42, 0xa6, 0xf2, + 0x65, 0x65, 0x2c, 0x7b, 0x71, 0xb4, 0x9c, 0xc8, 0xd7, 0xf6, 0xd2, 0xc2, 0x7e, 0x1f, 0x1a, 0x7f, 0xfb, 0x50, 0x61, + 0xca, 0xea, 0xa7, 0x3d, 0x19, 0x71, 0x8d, 0xf5, 0xb1, 0xf5, 0xf6, 0xa1, 0x7f, 0x7c, 0xaf, 0xa6, 0x66, 0xbc, 0xed, + 0x90, 0xee, 0x96, 0x03, 0xb6, 0xc2, 0xdb, 0xc3, 0x96, 0xfc, 0xef, 0xb7, 0x2f, 0x76, 0xec, 0x82, 0xcc, 0x27, 0x2c, + 0x18, 0x91, 0x14, 0x8f, 0x4d, 0x06, 0x50, 0x6e, 0x19, 0xd0, 0x88, 0x60, 0x5f, 0x37, 0x76, 0xe4, 0x6b, 0xcb, 0x1c, + 0x97, 0xe9, 0xb2, 0x1f, 0x20, 0xcb, 0xbe, 0x0c, 0x81, 0x9d, 0xdb, 0x32, 0xe4, 0x80, 0x59, 0x1c, 0xc8, 0xcc, 0x4c, + 0xfb, 0x8f, 0x5a, 0x5e, 0xa1, 0x53, 0x4a, 0xb6, 0x33, 0x1f, 0xd0, 0xad, 0x31, 0xd9, 0xe8, 0x42, 0xb0, 0x2e, 0x74, + 0xb2, 0x23, 0xdc, 0xb8, 0x37, 0xd2, 0x0f, 0x8e, 0x6e, 0x31, 0xa7, 0x81, 0x11, 0xcf, 0xb4, 0x98, 0x16, 0x68, 0xc4, + 0x4f, 0x72, 0x55, 0x2f, 0xf5, 0x40, 0xd6, 0xe9, 0x5a, 0x8c, 0x2e, 0xdf, 0x08, 0x6c, 0xf6, 0x44, 0x9c, 0xcc, 0xa1, + 0xde, 0x21, 0x20, 0x25, 0x5a, 0xa5, 0xef, 0xd6, 0x01, 0xa1, 0x9d, 0x80, 0x65, 0x5a, 0x62, 0xaf, 0x53, 0x32, 0xda, + 0xf7, 0x6f, 0xfc, 0x49, 0x39, 0x0d, 0xd4, 0x52, 0x89, 0xd1, 0x2d, 0x41, 0x41, 0xcc, 0x71, 0x5c, 0x3a, 0x6f, 0x8a, + 0x48, 0xcc, 0x58, 0x7f, 0x71, 0xf4, 0x3d, 0xa3, 0x1f, 0x40, 0xad, 0xa4, 0xa9, 0x70, 0xcc, 0x8d, 0x9a, 0x91, 0x85, + 0xc1, 0x97, 0x11, 0x62, 0xb7, 0xc5, 0x3f, 0x89, 0x3c, 0x9d, 0xa2, 0x15, 0xd0, 0x3d, 0x55, 0x2d, 0xb2, 0x92, 0x56, + 0x39, 0xd4, 0x29, 0xbf, 0x0a, 0x96, 0xc3, 0xe4, 0x58, 0xc6, 0x75, 0x16, 0x43, 0x98, 0x9c, 0xe5, 0x14, 0x4a, 0x6e, + 0x71, 0x0a, 0x5f, 0xb4, 0xcc, 0x2e, 0xc3, 0x1a, 0x2a, 0x20, 0x64, 0x1c, 0x84, 0xc3, 0x4f, 0xfe, 0x54, 0x68, 0x7f, + 0x33, 0x4b, 0x36, 0x7a, 0xf7, 0x51, 0x98, 0xa0, 0x07, 0xe7, 0x56, 0x31, 0x83, 0xc9, 0x10, 0x3d, 0x57, 0xa1, 0x15, + 0xdc, 0x89, 0xe7, 0xb4, 0xc8, 0xa9, 0x7a, 0xc8, 0xa0, 0x55, 0x37, 0xeb, 0x75, 0x5f, 0x47, 0x29, 0x27, 0x42, 0x48, + 0x23, 0x4e, 0x5a, 0x53, 0x35, 0xd5, 0x12, 0x7c, 0x44, 0x49, 0x46, 0x8a, 0x33, 0x03, 0xe4, 0xec, 0xa4, 0xa2, 0x56, + 0x02, 0xe5, 0x19, 0x4e, 0x2a, 0x66, 0x9a, 0x93, 0x18, 0xb0, 0xde, 0x35, 0xde, 0xcf, 0xa6, 0xe9, 0x02, 0x80, 0xea, + 0x4b, 0xc7, 0x48, 0x7d, 0xd6, 0xf1, 0xa4, 0x1e, 0xfa, 0x62, 0xd9, 0xff, 0xa8, 0x9d, 0x3a, 0x30, 0x1a, 0xc4, 0xb8, + 0xda, 0x8f, 0x30, 0x38, 0x37, 0x23, 0x86, 0xcd, 0xfc, 0x81, 0xad, 0x0e, 0xd8, 0x26, 0xaa, 0xb9, 0x48, 0xa2, 0xa5, + 0xe8, 0x79, 0xa6, 0xde, 0x85, 0x1a, 0x0d, 0xd5, 0x53, 0x77, 0x3d, 0xf2, 0xc8, 0x4a, 0xb7, 0x26, 0x32, 0x88, 0x14, + 0x4b, 0xa4, 0x0b, 0xaa, 0xf3, 0x8d, 0xc0, 0xd9, 0x4e, 0x06, 0xa6, 0x30, 0xd6, 0xa3, 0xb8, 0xa5, 0x09, 0xbf, 0x2b, + 0x19, 0xda, 0x29, 0x73, 0x54, 0xc6, 0x21, 0x07, 0xd7, 0xca, 0x3c, 0xf9, 0xf9, 0xb7, 0x3e, 0xa5, 0x11, 0x07, 0x78, + 0x4c, 0x7d, 0x7e, 0x86, 0xeb, 0xeb, 0x6f, 0x92, 0x5f, 0x8a, 0x5b, 0xe9, 0x27, 0x7c, 0x67, 0x89, 0x38, 0xef, 0xc1, + 0xf0, 0xad, 0xea, 0x71, 0x60, 0x11, 0xba, 0x72, 0x2e, 0xea, 0xc1, 0xf9, 0xd3, 0x0b, 0x82, 0x17, 0xe5, 0x80, 0x09, + 0x90, 0xa9, 0xe6, 0xac, 0x7e, 0x4b, 0xe4, 0x40, 0xc6, 0x45, 0x55, 0x9a, 0x3c, 0x81, 0xbc, 0x04, 0x9c, 0x3b, 0xc9, + 0x60, 0x32, 0x64, 0xdd, 0x8f, 0xb7, 0x9d, 0xc4, 0x77, 0xc0, 0xfa, 0x8f, 0x49, 0xc6, 0xb9, 0x06, 0x81, 0x14, 0x2b, + 0x69, 0x27, 0xab, 0xf4, 0x41, 0x81, 0x07, 0x26, 0x99, 0x9c, 0x97, 0x4d, 0x69, 0x33, 0x4f, 0xa0, 0x33, 0xa0, 0x8d, + 0xad, 0x4d, 0x19, 0x9f, 0x56, 0x80, 0x12, 0x12, 0xde, 0xc8, 0xd6, 0x56, 0x67, 0x90, 0xca, 0xaa, 0xf3, 0xcf, 0xf6, + 0x38, 0x53, 0x85, 0xbe, 0xe8, 0xa2, 0x39, 0x37, 0xef, 0x1d, 0x38, 0x1f, 0xd6, 0xe6, 0xe9, 0xcb, 0x9f, 0x12, 0x55, + 0x70, 0xd7, 0xa4, 0x01, 0xaa, 0xba, 0xe5, 0x25, 0x9d, 0xf1, 0x4f, 0xd8, 0x5f, 0x62, 0x09, 0x53, 0x90, 0xb4, 0x3f, + 0x84, 0x8f, 0x90, 0xf6, 0x11, 0xf2, 0x66, 0xfb, 0x3f, 0x4a, 0x99, 0x1c, 0x0f, 0xb6, 0x9a, 0xfd, 0xb0, 0x29, 0xfe, + 0x2d, 0xb2, 0x06, 0xee, 0xab, 0xf5, 0xc3, 0xaa, 0x32, 0x89, 0x3e, 0xae, 0x8d, 0x17, 0x94, 0x31, 0x86, 0xe9, 0x64, + 0xb1, 0xea, 0xba, 0x8c, 0x1b, 0x52, 0x66, 0x65, 0xf0, 0xd1, 0xe1, 0x03, 0x4d, 0x48, 0x2a, 0x74, 0x3e, 0xc5, 0xbc, + 0x34, 0xf3, 0xeb, 0x26, 0x15, 0xe1, 0x0f, 0x65, 0xce, 0x3b, 0x6f, 0x89, 0xba, 0xeb, 0x7d, 0xd5, 0x2f, 0x0f, 0x68, + 0xb4, 0x4d, 0x4f, 0x28, 0x07, 0x67, 0x70, 0x9a, 0x64, 0xf4, 0xcc, 0x44, 0x3c, 0x22, 0x1f, 0xe2, 0xfa, 0x45, 0x68, + 0xa4, 0x97, 0x87, 0x1c, 0x11, 0xbf, 0xcb, 0xe2, 0xee, 0x15, 0xbf, 0xd1, 0x5f, 0x92, 0x0f, 0x4b, 0x3a, 0x4a, 0x62, + 0xad, 0xdd, 0x0f, 0x73, 0x4c, 0xda, 0x40, 0xc5, 0xff, 0x0f, 0x13, 0xaf, 0x29, 0x8b, 0x2c, 0xa3, 0x25, 0xba, 0xaa, + 0x1d, 0x1c, 0xed, 0xc3, 0x22, 0x45, 0xbe, 0xc8, 0x10, 0x52, 0x44, 0xb7, 0x46, 0x79, 0x08, 0xaf, 0x27, 0xff, 0xa8, + 0x2c, 0xfc, 0x61, 0xd5, 0x4d, 0x4f, 0xa7, 0x91, 0x8a, 0x1f, 0xe9, 0xe8, 0xfb, 0x55, 0xdd, 0xde, 0x4f, 0x7b, 0xb3, + 0xd8, 0x43, 0xc0, 0xec, 0x33, 0x0d, 0x91, 0xbd, 0x59, 0xf6, 0x19, 0x86, 0x49, 0xdc, 0xe2, 0x8a, 0xd7, 0xa0, 0xa7, + 0xca, 0x56, 0xee, 0x0d, 0x38, 0xe3, 0x0b, 0x43, 0x07, 0x19, 0x8f, 0x96, 0x2b, 0x8f, 0xdf, 0xf0, 0x00, 0x4e, 0xaa, + 0xb6, 0xdb, 0xa2, 0x2c, 0xed, 0x19, 0x9c, 0x24, 0x8b, 0x78, 0x92, 0x79, 0xf1, 0x65, 0x4a, 0x2f, 0x29, 0xd9, 0x8c, + 0x12, 0xde, 0xd1, 0x17, 0xa2, 0x42, 0x2a, 0xb5, 0x21, 0x5f, 0x95, 0x92, 0x6d, 0x34, 0xa4, 0x52, 0xca, 0x15, 0x57, + 0xe3, 0x72, 0x1a, 0xaf, 0x8c, 0xed, 0x21, 0xbb, 0x85, 0x57, 0xc5, 0xeb, 0x14, 0x21, 0xbd, 0xbe, 0x46, 0x38, 0x71, + 0x53, 0x64, 0x90, 0xf8, 0x70, 0x56, 0xd2, 0xe5, 0xc9, 0x35, 0x58, 0xf3, 0x9c, 0xa3, 0x1c, 0xcc, 0xba, 0x3e, 0x50, + 0xe6, 0x7c, 0x93, 0xf6, 0xa8, 0xc8, 0x57, 0x4e, 0x9d, 0xab, 0x0d, 0xa8, 0xcb, 0x77, 0x02, 0x66, 0xe1, 0x3e, 0x1e, + 0x47, 0x25, 0xe9, 0x8d, 0x32, 0xe2, 0xc3, 0x9d, 0x20, 0xc5, 0x66, 0x9e, 0x8c, 0xc4, 0x3b, 0xda, 0xd8, 0xb9, 0x68, + 0xa4, 0x8f, 0x42, 0x7c, 0x4a, 0x50, 0x43, 0x1a, 0xa3, 0xd9, 0xc5, 0xee, 0x65, 0x90, 0x60, 0x88, 0x2c, 0xd9, 0x82, + 0x20, 0x44, 0x1e, 0x96, 0x31, 0x58, 0x52, 0x1f, 0x4d, 0xad, 0x60, 0x62, 0x99, 0x2b, 0x3f, 0x9c, 0xde, 0xa2, 0x57, + 0xeb, 0x48, 0x86, 0x5c, 0x27, 0xb1, 0x20, 0x6d, 0xc6, 0xcf, 0x75, 0x79, 0xd4, 0xde, 0x02, 0xab, 0xe9, 0x4a, 0xea, + 0x41, 0x63, 0x7a, 0xbc, 0x4e, 0x49, 0xb1, 0xb1, 0xce, 0x3a, 0x55, 0x15, 0xca, 0x7f, 0x9f, 0xad, 0x8a, 0x8b, 0xab, + 0x96, 0x6f, 0x71, 0x54, 0xef, 0x6c, 0x12, 0x02, 0x00, 0x35, 0x3c, 0xa4, 0xfa, 0x01, 0xc6, 0xb0, 0xdc, 0x33, 0xcc, + 0xb2, 0x0f, 0xd7, 0x1b, 0x34, 0x04, 0x6d, 0xc7, 0xe3, 0xc4, 0x16, 0xf9, 0x46, 0x0c, 0x68, 0xa4, 0xd4, 0x04, 0xd8, + 0x66, 0x85, 0x18, 0x3c, 0xeb, 0xf6, 0x27, 0x8a, 0x82, 0xa8, 0xe0, 0x88, 0x01, 0x10, 0x4e, 0x39, 0x2d, 0x3f, 0x2a, + 0xfc, 0xb0, 0x90, 0x60, 0x2a, 0x5e, 0x0e, 0xe4, 0xd3, 0x12, 0x10, 0x14, 0x83, 0xb2, 0x0c, 0x2d, 0x10, 0x82, 0xbe, + 0x99, 0x89, 0x51, 0x07, 0x67, 0x8c, 0xbe, 0x11, 0x31, 0xe0, 0x94, 0x02, 0x10, 0x8f, 0x39, 0x5d, 0x6b, 0x29, 0x5f, + 0x97, 0x2e, 0xfd, 0x8e, 0x9e, 0xca, 0x49, 0xe9, 0x85, 0xb0, 0x4d, 0xaf, 0x62, 0x5e, 0x8b, 0x4a, 0xa2, 0xeb, 0x65, + 0x73, 0x19, 0x1b, 0x9e, 0x2f, 0x5c, 0x9d, 0x56, 0x6f, 0xb6, 0xf0, 0xe1, 0x35, 0x17, 0x1f, 0x3e, 0x24, 0xb7, 0x2d, + 0xa3, 0xe0, 0xc3, 0x4e, 0xc3, 0x36, 0x72, 0x20, 0x08, 0xf0, 0xb7, 0xf5, 0xf5, 0x64, 0x6b, 0xb2, 0x15, 0x2e, 0x48, + 0x0f, 0xfb, 0x06, 0xdf, 0x0e, 0xc1, 0x9f, 0x68, 0xcd, 0x78, 0xcc, 0xd6, 0x3d, 0x34, 0xe4, 0xee, 0x65, 0x8d, 0x5f, + 0x30, 0x41, 0xe7, 0x67, 0x99, 0x79, 0x1f, 0x12, 0x5a, 0xee, 0x4b, 0xda, 0xe8, 0x11, 0xd3, 0x78, 0x14, 0x5d, 0x21, + 0xae, 0xf1, 0x2c, 0x3b, 0x3f, 0x1a, 0x1b, 0xb1, 0x9c, 0x38, 0x62, 0x3b, 0xcd, 0x2e, 0xdb, 0xe4, 0xd2, 0x52, 0x8d, + 0x6f, 0xef, 0x2a, 0x13, 0x8c, 0xaa, 0xa1, 0x7d, 0x5e, 0xd6, 0x67, 0x95, 0xcf, 0xfc, 0xfb, 0xfc, 0xad, 0x8b, 0x2a, + 0xc3, 0x1c, 0xa2, 0x19, 0x5f, 0xe3, 0x67, 0xa8, 0x4b, 0x28, 0xd2, 0x03, 0xf7, 0x7b, 0x99, 0xdd, 0x58, 0x73, 0x26, + 0x3f, 0xc2, 0x77, 0x4a, 0xb2, 0x0b, 0x6c, 0xc7, 0xbf, 0x8d, 0x7a, 0x2a, 0x94, 0x7e, 0xd4, 0x06, 0x16, 0x7f, 0x90, + 0xa4, 0x16, 0x24, 0x43, 0x09, 0x0e, 0xe2, 0xaa, 0x65, 0xef, 0xe9, 0x76, 0x6d, 0xc5, 0x82, 0x70, 0xe9, 0x6c, 0xed, + 0xe5, 0x8d, 0x69, 0x10, 0xe8, 0x44, 0x0b, 0xa3, 0xcd, 0xd9, 0x88, 0x79, 0xbc, 0xa1, 0x6a, 0x98, 0xbe, 0xa1, 0x34, + 0xb4, 0xc6, 0x17, 0xa0, 0x18, 0x26, 0x98, 0x22, 0xc2, 0xde, 0xb4, 0xf7, 0xf8, 0xc5, 0x86, 0xd5, 0x59, 0x50, 0xe3, + 0x55, 0x19, 0x21, 0x13, 0x97, 0x2b, 0x49, 0xf2, 0xe1, 0x3d, 0x81, 0xeb, 0xf8, 0xa7, 0xdd, 0x88, 0x77, 0x3d, 0xbe, + 0x93, 0x87, 0x65, 0x98, 0x98, 0x6e, 0xd1, 0x3a, 0x10, 0x43, 0x1c, 0x5b, 0xa1, 0x90, 0xa5, 0xfe, 0x58, 0xbd, 0x61, + 0x12, 0x8c, 0x9f, 0x1f, 0xac, 0xde, 0xcc, 0x8e, 0xff, 0x88, 0x06, 0x70, 0xee, 0x62, 0x1c, 0x81, 0x11, 0x66, 0x49, + 0x85, 0x1b, 0x65, 0x68, 0xa1, 0x8f, 0x8a, 0xab, 0xa9, 0x72, 0xe0, 0xc8, 0x12, 0xf2, 0x9a, 0xd2, 0xfe, 0x70, 0x3e, + 0xf3, 0xbb, 0x29, 0xf1, 0x33, 0x9d, 0x6e, 0xdf, 0xad, 0x1d, 0x56, 0x30, 0x1d, 0x07, 0xde, 0x1a, 0x29, 0xc8, 0xb1, + 0x14, 0xac, 0x6d, 0x39, 0x93, 0xe2, 0xb8, 0xa9, 0x3d, 0xeb, 0x55, 0x95, 0x9c, 0xd4, 0xfc, 0x6b, 0x9d, 0xac, 0x4d, + 0x3a, 0x73, 0x5b, 0x67, 0xfc, 0x74, 0x82, 0xbb, 0xf9, 0x5e, 0x69, 0x52, 0xf1, 0x3f, 0xcc, 0xaf, 0xb3, 0x64, 0xb5, + 0xf9, 0x78, 0xa1, 0x15, 0xb6, 0x89, 0x64, 0x80, 0xaf, 0xef, 0x34, 0x7d, 0x53, 0x20, 0x21, 0x6c, 0x57, 0xd3, 0xbd, + 0x0f, 0x0d, 0xd0, 0x9c, 0xb2, 0x13, 0xa4, 0xa8, 0x80, 0xd4, 0x9d, 0x58, 0x61, 0x90, 0x63, 0x60, 0x18, 0x3c, 0xf6, + 0x3e, 0xf5, 0x6e, 0x2d, 0x51, 0x57, 0x78, 0x2c, 0x34, 0x76, 0x63, 0xb0, 0x5a, 0x3e, 0x75, 0xe7, 0xff, 0x88, 0x5e, + 0xc1, 0xdf, 0x92, 0xf9, 0x1e, 0xf0, 0x0f, 0x82, 0x5a, 0xb6, 0x5a, 0x54, 0xde, 0x0a, 0xb9, 0x03, 0xfb, 0x78, 0x80, + 0x4f, 0x73, 0xf9, 0x40, 0x62, 0x6f, 0x8f, 0xcd, 0xdc, 0x75, 0x4d, 0xaf, 0xd5, 0x66, 0x6e, 0x75, 0xb4, 0x0c, 0x31, + 0x3a, 0x00, 0x20, 0x65, 0xc0, 0xf8, 0x29, 0xd6, 0x71, 0x67, 0xfc, 0x93, 0x79, 0xd0, 0xe7, 0x74, 0x7f, 0xf7, 0x3e, + 0x84, 0xdf, 0xd2, 0x12, 0xf1, 0x5d, 0xc4, 0xff, 0x1d, 0x5c, 0xf8, 0xd6, 0x31, 0x51, 0x25, 0x65, 0x07, 0x57, 0xe7, + 0xf0, 0x4d, 0xcf, 0x7b, 0x17, 0x57, 0x31, 0x8e, 0xbe, 0x87, 0x65, 0xf1, 0x47, 0x42, 0xa3, 0x29, 0x7c, 0x2d, 0x62, + 0x93, 0x97, 0xd0, 0x70, 0x33, 0x61, 0xb1, 0x8d, 0x2e, 0xcb, 0x1a, 0xc2, 0xeb, 0x7d, 0xa2, 0xb2, 0x8b, 0x27, 0x93, + 0x89, 0xba, 0xbe, 0x64, 0x29, 0xc0, 0xe5, 0xa6, 0x9a, 0xd1, 0x4b, 0xfb, 0x76, 0x8f, 0xba, 0xf4, 0x74, 0xff, 0xc1, + 0x65, 0x04, 0xaf, 0xd3, 0x66, 0xab, 0x3c, 0x37, 0x7d, 0x6a, 0x23, 0x3a, 0xa2, 0x7d, 0x5b, 0x57, 0xea, 0x05, 0x00, + 0x3a, 0xc0, 0x8b, 0xe3, 0x26, 0xba, 0x6a, 0xfa, 0xc7, 0x11, 0x90, 0xd6, 0xfc, 0x1e, 0x9b, 0x55, 0xb9, 0x91, 0x57, + 0x6a, 0x57, 0x09, 0xca, 0x8e, 0xf3, 0xe3, 0xbb, 0xd6, 0x5b, 0x3d, 0xbc, 0x54, 0x50, 0x29, 0xac, 0x6d, 0x7a, 0x6f, + 0xe9, 0xa4, 0xa7, 0x7d, 0x7e, 0x70, 0x5a, 0x50, 0x37, 0x74, 0xa9, 0xf5, 0x65, 0x07, 0x1e, 0xb5, 0x3e, 0x80, 0x9c, + 0xee, 0x60, 0x84, 0x23, 0x7a, 0x7f, 0x25, 0x6d, 0x09, 0xf0, 0x06, 0x68, 0x57, 0x9c, 0x80, 0xb6, 0x1d, 0x77, 0xe3, + 0xe6, 0x5b, 0xf8, 0xb3, 0x47, 0x90, 0x50, 0x5d, 0x75, 0x6e, 0xc9, 0xb4, 0x6b, 0x41, 0x45, 0x48, 0x2a, 0x24, 0x24, + 0x1c, 0x2e, 0x57, 0x97, 0x82, 0x51, 0x12, 0xd0, 0x57, 0x85, 0xc7, 0x43, 0xd9, 0xdb, 0x6e, 0x37, 0xae, 0x95, 0x91, + 0x64, 0x1a, 0xa8, 0x82, 0xc7, 0xd4, 0x1d, 0x72, 0x1f, 0x8f, 0x52, 0xb5, 0x90, 0x1e, 0xeb, 0x1f, 0x10, 0x24, 0x0d, + 0x0a, 0x1e, 0x99, 0x58, 0xdc, 0xd1, 0x40, 0xd4, 0x4a, 0x87, 0x1a, 0x66, 0xf6, 0x8e, 0x0b, 0x2e, 0xe6, 0xa8, 0x34, + 0xec, 0x32, 0xe0, 0x49, 0x66, 0x96, 0x41, 0x9f, 0x20, 0x77, 0x55, 0x3d, 0x15, 0xa6, 0xc3, 0x72, 0xc2, 0x00, 0xf1, + 0x94, 0xfa, 0x95, 0xdb, 0x5c, 0x37, 0xf8, 0x96, 0x24, 0x07, 0x60, 0xc0, 0xae, 0xb7, 0x42, 0xda, 0x2a, 0xdb, 0xa5, + 0xb2, 0xb1, 0x64, 0x25, 0x6c, 0xb8, 0xec, 0x62, 0x15, 0x01, 0xad, 0x20, 0xfa, 0x71, 0x8d, 0x30, 0x92, 0xfe, 0x42, + 0xa6, 0xd9, 0xb0, 0xfd, 0x39, 0xa6, 0xd5, 0x92, 0xdb, 0xb9, 0x25, 0xda, 0x00, 0x0d, 0xf8, 0x31, 0x86, 0xac, 0x25, + 0xb5, 0x26, 0xf6, 0xd6, 0xc5, 0xe4, 0xf9, 0x86, 0xe1, 0x69, 0x63, 0xd6, 0xcb, 0x64, 0xe3, 0xea, 0xc6, 0xa7, 0xb9, + 0x14, 0x1f, 0x0c, 0xba, 0x28, 0x4c, 0xa9, 0x39, 0x56, 0xe4, 0x5f, 0x02, 0xeb, 0xc2, 0x65, 0x42, 0xb2, 0x99, 0xca, + 0x84, 0x80, 0xc6, 0x6e, 0xcf, 0x08, 0x71, 0xf6, 0x03, 0x71, 0x26, 0xef, 0x2b, 0x5a, 0xd4, 0x20, 0x4f, 0x18, 0x8b, + 0x5f, 0xf6, 0xb0, 0xbb, 0x4d, 0xf3, 0xbc, 0x60, 0xcf, 0xb4, 0x62, 0x9d, 0x68, 0x26, 0x5c, 0x4f, 0xc9, 0xea, 0x1a, + 0x21, 0xe9, 0x53, 0xea, 0xf4, 0xc0, 0x8a, 0xa9, 0xbd, 0x53, 0x0a, 0x2c, 0x53, 0x10, 0x86, 0x76, 0xf2, 0xa8, 0x2c, + 0x29, 0xa9, 0x7a, 0x68, 0xbb, 0xb8, 0xa7, 0x50, 0x90, 0x31, 0xe2, 0xea, 0xb1, 0xcf, 0xcf, 0x00, 0x41, 0x79, 0x3a, + 0x83, 0x32, 0x7d, 0x4e, 0xb8, 0x91, 0xe7, 0x0c, 0x2d, 0xf2, 0x62, 0x62, 0x8e, 0x2a, 0x41, 0xd6, 0x48, 0xff, 0x55, + 0x84, 0x5c, 0x68, 0xf0, 0xf0, 0x48, 0x3a, 0x0d, 0xeb, 0x37, 0xc5, 0x0b, 0x0a, 0xce, 0x9f, 0xb2, 0x86, 0x18, 0xe7, + 0x86, 0x90, 0xe0, 0xfe, 0x70, 0x7f, 0xe6, 0x2e, 0x96, 0x11, 0x5a, 0xa5, 0x30, 0x2a, 0x2a, 0x99, 0x79, 0xe1, 0x87, + 0xb0, 0x0d, 0xf3, 0x62, 0x62, 0x50, 0x78, 0xdf, 0xa5, 0xf5, 0x99, 0x70, 0x88, 0xab, 0x6a, 0x8a, 0x79, 0x87, 0x14, + 0x35, 0x18, 0x4a, 0x6e, 0xf1, 0x5c, 0x33, 0x1a, 0x3d, 0xd6, 0x67, 0x46, 0x43, 0x6d, 0x92, 0xfc, 0x6a, 0x4e, 0xb0, + 0xb1, 0xe1, 0xa5, 0x90, 0xaa, 0x45, 0xc7, 0x01, 0xe1, 0x57, 0x1a, 0xc0, 0x5c, 0x68, 0x9a, 0xa7, 0x1d, 0x10, 0xb4, + 0xd2, 0x52, 0x0d, 0xa3, 0xaf, 0x08, 0x1e, 0x22, 0xa9, 0x1b, 0x83, 0x80, 0x8d, 0x60, 0x38, 0x04, 0xb4, 0xc5, 0x2f, + 0x2f, 0x7c, 0xa4, 0x61, 0xaa, 0x76, 0xec, 0x58, 0xce, 0x21, 0xa7, 0xca, 0xe0, 0x11, 0xff, 0x33, 0x11, 0x4c, 0xda, + 0xdc, 0x48, 0xbc, 0xa5, 0xec, 0xa6, 0x8e, 0xd3, 0xcc, 0x41, 0xfe, 0x96, 0x8e, 0xf6, 0x5a, 0xf9, 0xc2, 0x36, 0x99, + 0xb1, 0x57, 0xa3, 0x79, 0x28, 0x00, 0xb5, 0xff, 0x68, 0xdf, 0x65, 0xd1, 0x24, 0x7c, 0x3e, 0xbb, 0xef, 0x06, 0xf5, + 0x10, 0xd9, 0x99, 0x87, 0x62, 0xa5, 0xfb, 0x7a, 0xba, 0x34, 0x12, 0x1d, 0xc2, 0x35, 0xe6, 0x26, 0x9a, 0xed, 0x13, + 0x3d, 0x75, 0x26, 0xfb, 0xf9, 0xe8, 0x12, 0x2f, 0x67, 0x4e, 0x00, 0xd8, 0x23, 0x9e, 0x17, 0xdc, 0x51, 0xe2, 0x30, + 0xb5, 0xa9, 0x9d, 0x60, 0xa7, 0x3b, 0xda, 0xd8, 0xb5, 0x40, 0x29, 0x08, 0xa0, 0xf3, 0x7c, 0xfa, 0x7c, 0xfa, 0x32, + 0x86, 0xed, 0xd8, 0xc1, 0xe4, 0x64, 0x7e, 0xb1, 0x74, 0xcd, 0x6d, 0x91, 0xe9, 0xb0, 0xa4, 0x9b, 0x26, 0xe4, 0xbe, + 0x47, 0xe7, 0x36, 0xcf, 0xfa, 0xd3, 0xee, 0xda, 0x78, 0xa7, 0x21, 0x09, 0x8b, 0x00, 0xe5, 0xc5, 0x2e, 0x71, 0xe2, + 0xc0, 0x0d, 0xe7, 0xfb, 0x82, 0xc5, 0x82, 0x35, 0x12, 0x31, 0x44, 0x01, 0x19, 0x53, 0xff, 0xfc, 0x84, 0xee, 0xfa, + 0x1d, 0x5f, 0x0d, 0xa2, 0xe0, 0x98, 0x34, 0xd4, 0x9d, 0x57, 0x0f, 0xbb, 0x3e, 0xe6, 0x4c, 0x35, 0xc6, 0x7d, 0xee, + 0xfe, 0x80, 0x7d, 0xd7, 0x5a, 0xd3, 0x5c, 0x8f, 0x79, 0x69, 0x3b, 0xc5, 0x73, 0x0e, 0xe7, 0xf1, 0xe1, 0x7e, 0x1e, + 0xfc, 0x66, 0x78, 0x52, 0x29, 0xb6, 0x5d, 0x8e, 0x3c, 0xc9, 0x41, 0xd7, 0xf3, 0x1d, 0xfb, 0x78, 0x8f, 0xe1, 0x1e, + 0x24, 0x81, 0x0f, 0xaa, 0x54, 0x75, 0x96, 0xfb, 0x16, 0x0f, 0xc4, 0x06, 0x41, 0xe1, 0x75, 0x84, 0x78, 0x4d, 0x27, + 0xbf, 0x67, 0x07, 0xd8, 0x80, 0x2b, 0x20, 0x0f, 0xf8, 0x6c, 0xc5, 0x40, 0x5d, 0xc1, 0x90, 0xd9, 0xb7, 0x5b, 0x72, + 0x96, 0x66, 0x05, 0x3a, 0xe9, 0xf6, 0x26, 0x99, 0x5b, 0x0f, 0x34, 0xb0, 0x14, 0x89, 0x7c, 0xc9, 0xef, 0x58, 0x95, + 0x88, 0x45, 0x11, 0x9b, 0x4d, 0x3e, 0xc6, 0x62, 0x09, 0xf5, 0xfa, 0x52, 0xe4, 0x3d, 0x1f, 0x30, 0x67, 0x59, 0xc7, + 0xea, 0x9f, 0xc6, 0xee, 0x6e, 0x17, 0x31, 0xcc, 0xaf, 0x7f, 0xee, 0x81, 0xba, 0x58, 0x9e, 0xa7, 0xea, 0xcc, 0x30, + 0x82, 0xfd, 0x56, 0x2f, 0xb4, 0x1c, 0xb4, 0x31, 0x8f, 0xa9, 0xc9, 0x2d, 0xe9, 0xe3, 0x0b, 0xca, 0x89, 0x0e, 0xd0, + 0xfd, 0x15, 0x4a, 0xf7, 0x43, 0x47, 0x7d, 0xab, 0xfa, 0x7d, 0xe0, 0xa0, 0xea, 0x1c, 0x54, 0x77, 0x9c, 0x24, 0xb6, + 0x2b, 0x8a, 0x63, 0x58, 0x88, 0x6e, 0x0b, 0x76, 0xf8, 0x8c, 0x35, 0xcd, 0x1f, 0xe0, 0x80, 0xbb, 0x9b, 0x8c, 0x29, + 0x92, 0x4c, 0x3a, 0x9b, 0xd4, 0x1e, 0x00, 0xbd, 0x9f, 0xad, 0x73, 0x90, 0xbe, 0x5f, 0x3b, 0x54, 0xfb, 0xf3, 0xf8, + 0x80, 0xf3, 0x7c, 0xd9, 0xc4, 0x5c, 0x91, 0x38, 0x71, 0x85, 0x14, 0x74, 0x86, 0x50, 0xfa, 0x0b, 0x87, 0xbc, 0xcd, + 0xf3, 0xf4, 0xba, 0x99, 0xa8, 0x72, 0x27, 0xbb, 0x74, 0x82, 0x38, 0x78, 0x03, 0x01, 0x1e, 0x97, 0xfd, 0x5e, 0x6a, + 0xda, 0xe6, 0xc9, 0xed, 0x90, 0xd5, 0xea, 0xca, 0x77, 0xda, 0x07, 0x7c, 0x73, 0x93, 0x91, 0xc6, 0xf9, 0x9e, 0x87, + 0x9e, 0xca, 0xbe, 0x91, 0x35, 0x49, 0xed, 0xb7, 0x40, 0xc7, 0x55, 0x49, 0xc7, 0x18, 0x0d, 0x27, 0xf3, 0xe8, 0xbf, + 0x03, 0x31, 0x1c, 0xae, 0xcc, 0xbe, 0xd1, 0x38, 0x52, 0x74, 0xf8, 0xf2, 0xb0, 0x05, 0x47, 0xec, 0x49, 0x7c, 0x2f, + 0x5e, 0xe5, 0x4a, 0x97, 0xe8, 0x04, 0xb8, 0xed, 0x5d, 0x79, 0x63, 0xd3, 0xe5, 0xf3, 0xbf, 0x8f, 0x06, 0xdf, 0x1c, + 0x11, 0x31, 0x05, 0xaa, 0x24, 0xf6, 0xc1, 0xe6, 0x7b, 0x48, 0x68, 0xb2, 0x4b, 0x54, 0x61, 0xe8, 0x81, 0xb7, 0xd9, + 0xc6, 0x2d, 0x1c, 0x71, 0xf5, 0x55, 0x48, 0x80, 0xbd, 0x5c, 0xf7, 0xcc, 0xe8, 0x1e, 0xfc, 0xd4, 0xb4, 0x52, 0x84, + 0xc4, 0x37, 0x17, 0xf7, 0x0d, 0x1b, 0x8d, 0x58, 0xf6, 0x42, 0x66, 0x5d, 0x3c, 0x4a, 0xd1, 0xd3, 0x2a, 0xc3, 0xe9, + 0xa5, 0x3c, 0x27, 0x26, 0xab, 0x2c, 0xc8, 0x86, 0xae, 0x9e, 0xbe, 0xe5, 0xba, 0xf7, 0x56, 0x43, 0xf6, 0x12, 0xdf, + 0xbd, 0x72, 0x17, 0x20, 0xc7, 0xc4, 0xd3, 0x19, 0xd8, 0x05, 0xa9, 0x68, 0xaf, 0x97, 0x15, 0x36, 0x38, 0x56, 0x89, + 0xed, 0x14, 0x7c, 0x20, 0x36, 0x9f, 0x0b, 0x2e, 0x15, 0xa4, 0x2f, 0xc9, 0xfa, 0xfc, 0x2a, 0xc4, 0x1a, 0x98, 0x24, + 0xf0, 0xfe, 0xb3, 0x2c, 0x66, 0xfb, 0x12, 0x07, 0x08, 0x1c, 0x17, 0xef, 0x7b, 0x40, 0xef, 0x6f, 0x39, 0x92, 0x99, + 0x1c, 0xac, 0xc5, 0x7d, 0xc9, 0xcc, 0x08, 0xfe, 0xeb, 0xc7, 0x3b, 0x6b, 0x85, 0x8a, 0x5c, 0x8f, 0x61, 0x42, 0xb1, + 0xfb, 0x6e, 0xe7, 0x38, 0x37, 0x55, 0x82, 0x33, 0xa8, 0xe5, 0xef, 0xef, 0x78, 0x89, 0x86, 0x24, 0xe3, 0x36, 0x80, + 0xba, 0xac, 0x98, 0x74, 0x01, 0x2e, 0xea, 0xad, 0xc8, 0xd8, 0x51, 0xb0, 0xc7, 0x52, 0x6b, 0x76, 0x9c, 0x03, 0xc9, + 0xae, 0x16, 0x1a, 0x6d, 0x89, 0x22, 0xf7, 0x02, 0x62, 0x97, 0xcc, 0xf7, 0x75, 0xc5, 0x91, 0xee, 0x2a, 0x65, 0x4a, + 0x65, 0x4e, 0x39, 0x79, 0x92, 0x52, 0x7f, 0x63, 0xa8, 0x7a, 0xea, 0x0b, 0xec, 0x99, 0xb9, 0x3c, 0x5e, 0xcf, 0x37, + 0x7e, 0x24, 0x78, 0xbf, 0x56, 0x0c, 0x82, 0x58, 0xa1, 0xd9, 0x2e, 0x61, 0x32, 0x50, 0xa3, 0x3c, 0x39, 0x6e, 0x2c, + 0x37, 0x5e, 0xe2, 0x5f, 0x74, 0x95, 0x58, 0x99, 0x9f, 0xf5, 0x05, 0xb9, 0x0e, 0xde, 0xeb, 0x32, 0x2f, 0x49, 0xad, + 0xff, 0xb0, 0x3d, 0x1e, 0x4e, 0xd4, 0xaf, 0x37, 0xcc, 0xf3, 0xbb, 0x81, 0x54, 0x66, 0xdb, 0x51, 0x94, 0x95, 0x19, + 0x51, 0x0e, 0xed, 0x36, 0x01, 0xed, 0xa5, 0x5b, 0x5c, 0x40, 0xdd, 0xd8, 0xa2, 0x4b, 0x88, 0x61, 0xa0, 0xb8, 0x95, + 0x49, 0xa8, 0xce, 0xc6, 0x21, 0x4d, 0x29, 0x64, 0x8f, 0x88, 0xc5, 0x84, 0x85, 0xfa, 0xa7, 0xc3, 0xd3, 0xac, 0x06, + 0x5a, 0xef, 0x91, 0x6a, 0x8e, 0x15, 0xef, 0x1a, 0xaa, 0xb1, 0xb0, 0xd1, 0x2a, 0xff, 0x22, 0xc7, 0x8d, 0x43, 0x94, + 0x37, 0x5d, 0xe8, 0xe8, 0xc2, 0xbf, 0xa6, 0xd2, 0x49, 0x03, 0x2e, 0xce, 0xc5, 0x91, 0x04, 0xfe, 0xdf, 0xba, 0x24, + 0x42, 0xf1, 0x5b, 0xc4, 0x8a, 0x20, 0xbe, 0x36, 0xad, 0xfc, 0x6b, 0x27, 0x7d, 0x4e, 0xbc, 0xa3, 0x5d, 0xa5, 0x9a, + 0x49, 0x78, 0x31, 0x9c, 0xc8, 0x7c, 0x72, 0xe0, 0xc2, 0x57, 0x3e, 0x99, 0xec, 0xfe, 0x48, 0x28, 0x9f, 0xd8, 0xb3, + 0xc9, 0x71, 0x5a, 0x3b, 0xea, 0xfc, 0xe0, 0x97, 0x62, 0x07, 0xf3, 0xb0, 0x68, 0x53, 0x14, 0x8a, 0x5a, 0x1d, 0x8a, + 0x97, 0x45, 0x24, 0x82, 0x26, 0x14, 0xab, 0x87, 0x09, 0xc0, 0xc7, 0x4b, 0x8c, 0x72, 0x9f, 0xb5, 0x75, 0xa4, 0xfa, + 0xde, 0x84, 0x60, 0x65, 0xa0, 0xf6, 0xe8, 0x1c, 0x68, 0x13, 0x9b, 0x7a, 0xcc, 0xf2, 0x52, 0xab, 0x15, 0xee, 0x9a, + 0xd7, 0x71, 0x19, 0x5a, 0x95, 0xfc, 0x13, 0x64, 0x37, 0x9a, 0x53, 0x0c, 0x01, 0x45, 0x5f, 0x6e, 0x26, 0xb8, 0xe5, + 0xbe, 0x3f, 0x60, 0x38, 0x51, 0x9a, 0x15, 0xed, 0x29, 0x7a, 0x29, 0x12, 0xf3, 0x31, 0x96, 0x8e, 0xdf, 0xb3, 0x39, + 0xad, 0x28, 0x7d, 0x76, 0x67, 0xa0, 0xb8, 0x09, 0x74, 0x59, 0x37, 0x35, 0x4e, 0xd8, 0xb3, 0xb4, 0x6c, 0xf7, 0xdc, + 0xca, 0xb1, 0xa2, 0xad, 0x51, 0xc6, 0x4c, 0xaf, 0x34, 0x4b, 0x12, 0x18, 0xfe, 0xb1, 0xd5, 0x38, 0x0a, 0x07, 0xec, + 0x3a, 0xeb, 0xe1, 0x57, 0x68, 0xd8, 0x66, 0xca, 0x3f, 0xd2, 0xe2, 0xb9, 0xf8, 0x64, 0x6a, 0x30, 0xbf, 0x17, 0xa8, + 0x90, 0xb8, 0xf8, 0x4c, 0x34, 0xfd, 0x3e, 0xda, 0x5f, 0x47, 0x05, 0xc8, 0x98, 0x2a, 0x63, 0xe5, 0xff, 0x2b, 0x6d, + 0xd9, 0x6e, 0xc7, 0x71, 0xcd, 0x90, 0xc8, 0xa0, 0xd2, 0xe3, 0x2e, 0xee, 0xe9, 0xd7, 0xd1, 0x7f, 0x89, 0xa8, 0xae, + 0xdc, 0x79, 0x45, 0x5d, 0xf3, 0x5d, 0x52, 0x8b, 0xcc, 0x5e, 0xbf, 0x7b, 0xd5, 0x2a, 0x75, 0x50, 0x63, 0x5b, 0x6c, + 0xbc, 0xae, 0x2d, 0x7e, 0x7d, 0x00, 0xcd, 0xde, 0xe4, 0x37, 0xb3, 0x5d, 0x75, 0x8d, 0xd4, 0xa9, 0xd1, 0xd8, 0x31, + 0x8c, 0xde, 0xde, 0x0c, 0xbb, 0x0d, 0x3e, 0xb6, 0x46, 0x40, 0xab, 0x98, 0xbd, 0xfe, 0xbd, 0x0a, 0x0a, 0x7d, 0xab, + 0x9f, 0xc7, 0xba, 0xc9, 0xb8, 0xfc, 0xa1, 0x82, 0x40, 0x33, 0x4b, 0xe4, 0x51, 0x1e, 0x37, 0x8f, 0xde, 0x7a, 0xe2, + 0xb7, 0x36, 0xcf, 0xdd, 0xe4, 0x9e, 0x7c, 0xda, 0xaf, 0xe2, 0x36, 0x57, 0xf5, 0x2d, 0xe3, 0x2a, 0xe8, 0xb0, 0xdc, + 0x96, 0xaf, 0x0c, 0xbf, 0x57, 0xd0, 0xe1, 0x14, 0xfd, 0xfb, 0xe4, 0x0f, 0x1b, 0xb6, 0x8f, 0xda, 0x94, 0x50, 0x39, + 0x34, 0xbf, 0x51, 0x1f, 0x12, 0x98, 0x22, 0xb3, 0x8b, 0x3a, 0xe7, 0x5c, 0xb4, 0xa3, 0x65, 0x53, 0x6d, 0xad, 0x21, + 0xa1, 0x24, 0x90, 0x6a, 0x09, 0xc6, 0xad, 0xfd, 0x39, 0x69, 0x8f, 0xb8, 0x56, 0x50, 0x0e, 0x9d, 0xa3, 0xcc, 0x6f, + 0x45, 0xc8, 0xe7, 0x39, 0x6c, 0x6f, 0x71, 0xe0, 0x47, 0x10, 0x9f, 0x2b, 0x5a, 0x07, 0xf2, 0xfc, 0x51, 0x56, 0x2e, + 0x67, 0xb5, 0x6f, 0x27, 0x11, 0x33, 0x55, 0x3b, 0xb0, 0xe5, 0x05, 0xaf, 0xcc, 0x16, 0x76, 0xf7, 0xa4, 0x63, 0xbd, + 0xc1, 0xdf, 0x1f, 0x12, 0xd7, 0xa1, 0x1f, 0x79, 0xc9, 0x61, 0x5b, 0xd6, 0x53, 0xea, 0x56, 0xc7, 0x69, 0x37, 0xc5, + 0x62, 0x3b, 0xeb, 0x44, 0x6f, 0x83, 0xed, 0x6a, 0xe7, 0x51, 0x3e, 0x9d, 0x39, 0xc6, 0x35, 0xe9, 0x72, 0x3f, 0xa6, + 0xe9, 0x54, 0x6b, 0x88, 0x96, 0x2d, 0xa5, 0x7b, 0xac, 0x57, 0x2c, 0x60, 0x6b, 0xf6, 0xfe, 0xa1, 0x68, 0xeb, 0xa2, + 0x2d, 0x25, 0x28, 0x66, 0x6a, 0xf3, 0xd6, 0x22, 0x98, 0x3f, 0x92, 0x37, 0xeb, 0xa4, 0xce, 0x44, 0x5b, 0x53, 0x9f, + 0xfc, 0xa3, 0xa9, 0x47, 0xde, 0x17, 0x2c, 0xc5, 0x42, 0x3f, 0xac, 0x77, 0x0b, 0x8c, 0x25, 0xf4, 0x8c, 0xa1, 0x6d, + 0xce, 0xad, 0x23, 0x97, 0x90, 0xe5, 0x30, 0xe5, 0x8a, 0xc3, 0x69, 0x0e, 0x91, 0x25, 0xdd, 0xff, 0x97, 0xb7, 0x5e, + 0xcb, 0x48, 0xaf, 0x4f, 0xe8, 0xb8, 0x53, 0xf8, 0xf3, 0x32, 0x59, 0x40, 0x39, 0xd6, 0x56, 0x7a, 0x5e, 0xd9, 0x17, + 0x91, 0xf9, 0x28, 0x2e, 0xfc, 0x1f, 0xbe, 0xf2, 0x58, 0xfa, 0x9d, 0x75, 0xfd, 0x98, 0xba, 0xe4, 0xaf, 0xb9, 0x8f, + 0x86, 0x4e, 0x5a, 0x08, 0x99, 0xfc, 0x9f, 0x48, 0xca, 0x8e, 0x2c, 0xc2, 0xa3, 0x03, 0x9c, 0xc0, 0xce, 0x9d, 0x6c, + 0x49, 0x2b, 0x21, 0x19, 0x88, 0xae, 0xd1, 0x1c, 0xcd, 0x40, 0x36, 0x69, 0x03, 0x21, 0x3c, 0x6e, 0xce, 0x7d, 0x97, + 0xb9, 0x44, 0xfa, 0x65, 0x1e, 0xcd, 0xd0, 0x3d, 0x33, 0x64, 0xd1, 0x04, 0xa2, 0x23, 0x29, 0xc3, 0x56, 0xdb, 0xee, + 0xaf, 0x26, 0x76, 0x1f, 0x67, 0xd4, 0xb7, 0x07, 0xdc, 0x67, 0x84, 0x94, 0xdb, 0x51, 0x8e, 0x9a, 0x7e, 0xf0, 0x55, + 0x6b, 0x37, 0x87, 0x50, 0x17, 0x33, 0xe4, 0xb2, 0x00, 0x25, 0xbc, 0x58, 0xef, 0xeb, 0xf3, 0x13, 0xfd, 0xf1, 0x97, + 0x89, 0x21, 0xaa, 0x9a, 0x35, 0x69, 0x8a, 0x01, 0xb8, 0x8d, 0x39, 0xdf, 0xed, 0xbc, 0xf3, 0xe1, 0xdc, 0x6c, 0x41, + 0x98, 0xad, 0xa0, 0x18, 0xdd, 0x7c, 0x6c, 0xb0, 0x20, 0x88, 0xd7, 0x9f, 0x28, 0x51, 0xa4, 0x07, 0xf5, 0xc9, 0xd4, + 0x97, 0xb2, 0x90, 0x41, 0x8a, 0x86, 0x45, 0xd1, 0xad, 0x6e, 0x59, 0xd7, 0x05, 0x7f, 0x0a, 0x43, 0x96, 0x6f, 0x60, + 0x78, 0xb2, 0x49, 0xd2, 0xb9, 0x2e, 0x61, 0x8a, 0x27, 0xf3, 0x32, 0x47, 0x2a, 0xf3, 0x3e, 0x43, 0x3b, 0xbd, 0xfd, + 0xe4, 0x1f, 0xd8, 0x0a, 0x87, 0xfa, 0x32, 0x39, 0xf9, 0xdb, 0x07, 0xfe, 0xfe, 0xac, 0x65, 0xc5, 0xd4, 0x72, 0xb5, + 0x98, 0xac, 0xbc, 0x2a, 0x38, 0xa7, 0x24, 0x2a, 0xb8, 0xb4, 0xa2, 0xf3, 0x03, 0x0f, 0x89, 0x6d, 0xfc, 0xa5, 0x40, + 0xe6, 0xe2, 0x91, 0xbd, 0x67, 0x07, 0xb5, 0x46, 0x20, 0x14, 0xc4, 0x2c, 0xaa, 0x05, 0xbe, 0x33, 0x59, 0x37, 0x66, + 0xf6, 0x92, 0x14, 0x68, 0x31, 0x1a, 0x6c, 0xfb, 0xd1, 0x47, 0x43, 0xbc, 0x2a, 0x85, 0x2b, 0xc9, 0xf8, 0xb3, 0x15, + 0xa6, 0x24, 0x0c, 0x59, 0xb9, 0x83, 0xbb, 0x2c, 0x56, 0xae, 0x45, 0x2e, 0x5f, 0xde, 0x7f, 0x9c, 0xaa, 0xda, 0x7b, + 0x44, 0x2c, 0x78, 0xfd, 0x4c, 0x51, 0xd5, 0x1a, 0x50, 0x26, 0xa3, 0x3b, 0xc6, 0x5d, 0x2c, 0xd4, 0x28, 0x6b, 0x66, + 0x57, 0xa0, 0xe6, 0xd8, 0xa6, 0xa2, 0x10, 0xe0, 0x8f, 0xb7, 0x97, 0xca, 0x05, 0x1e, 0xcc, 0x0d, 0x85, 0x28, 0xa3, + 0x2c, 0xdf, 0x99, 0x8c, 0x85, 0xd1, 0x51, 0x2b, 0xc3, 0xbf, 0x89, 0x62, 0xf5, 0xdc, 0xb3, 0xd7, 0xc7, 0x49, 0xaf, + 0x1b, 0x61, 0xa0, 0xa9, 0x2c, 0x9b, 0x6e, 0xdb, 0xd6, 0x6d, 0x85, 0x6f, 0xaa, 0x15, 0xc8, 0x53, 0x80, 0xd6, 0x55, + 0xd8, 0x08, 0x38, 0x83, 0x63, 0xf6, 0x65, 0x80, 0x1e, 0x1a, 0x18, 0xab, 0xbf, 0xb4, 0x62, 0xb8, 0xb5, 0x21, 0xa8, + 0x07, 0xf1, 0xcb, 0x5c, 0x20, 0x64, 0x60, 0x81, 0x1d, 0x8d, 0xdc, 0x89, 0xdf, 0x76, 0x7a, 0x9f, 0x7e, 0xaf, 0x97, + 0x8d, 0xb6, 0x46, 0xc8, 0xac, 0xac, 0xb0, 0xdc, 0xe9, 0xde, 0xe9, 0x21, 0x6a, 0x94, 0x58, 0xe7, 0x2c, 0x34, 0x97, + 0xdd, 0x59, 0x35, 0x08, 0xae, 0x7e, 0x30, 0x28, 0x90, 0x1c, 0x0c, 0xc5, 0x76, 0x19, 0x41, 0xd0, 0x10, 0xd4, 0x47, + 0x79, 0x09, 0xb0, 0x66, 0x90, 0x43, 0x2b, 0xa3, 0xc5, 0xbf, 0xea, 0x8b, 0xfe, 0xd3, 0xff, 0xb1, 0xe8, 0x5d, 0x13, + 0x60, 0xd9, 0x1e, 0xae, 0x67, 0x67, 0x78, 0xc1, 0x0c, 0x1a, 0x15, 0xa3, 0x3d, 0x84, 0x53, 0x73, 0x9a, 0x88, 0x41, + 0x2d, 0x85, 0xd8, 0xfe, 0xc4, 0xa3, 0xe5, 0xe4, 0xc8, 0x43, 0xfe, 0xdb, 0x87, 0x12, 0x16, 0x9d, 0xe6, 0xcb, 0x73, + 0x04, 0x77, 0x05, 0x4e, 0x71, 0x82, 0xd9, 0xc2, 0xfe, 0xc9, 0x97, 0x4f, 0xa5, 0x89, 0x39, 0x74, 0x81, 0xa1, 0xcc, + 0xd5, 0x33, 0x22, 0x6f, 0x17, 0x99, 0xd1, 0xaa, 0x54, 0x09, 0x2d, 0x90, 0x43, 0xa6, 0xfc, 0x3c, 0x66, 0xc1, 0xa8, + 0x61, 0x3f, 0xd7, 0x8d, 0x64, 0x1f, 0x02, 0x33, 0x62, 0x8b, 0xda, 0x5c, 0x14, 0x83, 0x70, 0x85, 0xb8, 0xc9, 0x46, + 0xeb, 0x82, 0x96, 0x9e, 0xd2, 0x2e, 0xa9, 0xc8, 0x4d, 0x3c, 0xee, 0xc7, 0x51, 0xb8, 0xd5, 0xf2, 0x56, 0x8c, 0xde, + 0x83, 0x53, 0x59, 0xef, 0x1f, 0xe3, 0x0f, 0x86, 0x03, 0xc4, 0x51, 0x5c, 0x71, 0x62, 0xf7, 0xc3, 0xc5, 0x5f, 0xce, + 0xdc, 0x9e, 0x02, 0x97, 0x47, 0x6a, 0xf9, 0x72, 0xc5, 0xff, 0x13, 0x1f, 0xdd, 0x85, 0xd4, 0x0c, 0xe5, 0x07, 0xc1, + 0x03, 0x8f, 0xbc, 0x84, 0x8f, 0xfe, 0x0c, 0x3a, 0xfc, 0x6a, 0xe5, 0xb7, 0x53, 0xbf, 0x09, 0xef, 0x2d, 0xdc, 0x5e, + 0x6b, 0xae, 0xd6, 0x35, 0x56, 0x09, 0xe3, 0x0b, 0x6d, 0x3d, 0xfe, 0x92, 0x34, 0x26, 0x8c, 0xb3, 0x73, 0x0e, 0x0b, + 0x8d, 0x20, 0xc1, 0x2c, 0xb8, 0x49, 0x8f, 0x0f, 0x5c, 0xa6, 0x15, 0x51, 0x82, 0x10, 0x92, 0xcc, 0xf7, 0x63, 0xe8, + 0x2a, 0xb1, 0x1d, 0x89, 0x64, 0x54, 0x16, 0x87, 0x46, 0x9c, 0xaa, 0xf8, 0x69, 0x8a, 0x75, 0xc2, 0xa7, 0x9a, 0x81, + 0x87, 0x38, 0x89, 0xbc, 0xef, 0xec, 0xe6, 0x3d, 0x40, 0x2b, 0x0a, 0xd5, 0x0a, 0xfa, 0x2a, 0x9a, 0xb6, 0xfe, 0x7a, + 0x7b, 0x8f, 0x6d, 0x97, 0x3c, 0xa1, 0xd7, 0x73, 0xfc, 0xab, 0xda, 0xd5, 0x5a, 0x39, 0xa5, 0x6b, 0xfd, 0x74, 0xbb, + 0xb0, 0x98, 0x35, 0x7a, 0xbc, 0x98, 0x21, 0x6f, 0x05, 0xde, 0x6a, 0x7c, 0x8a, 0x36, 0x68, 0x82, 0xfb, 0x56, 0x6d, + 0x76, 0xc8, 0x4a, 0xb8, 0xfe, 0xac, 0x9e, 0x54, 0x92, 0x70, 0xa0, 0x31, 0x70, 0x58, 0x74, 0x19, 0xb4, 0x99, 0x3b, + 0x35, 0x70, 0x57, 0x24, 0x87, 0xd6, 0x1f, 0x58, 0xd1, 0x6c, 0xb5, 0x85, 0x0e, 0x34, 0x30, 0x0d, 0x7e, 0x1c, 0x99, + 0x79, 0x2c, 0xff, 0xd0, 0xf3, 0x5f, 0x06, 0x89, 0xae, 0xe3, 0x13, 0xec, 0x43, 0xf2, 0x45, 0x05, 0x4d, 0x87, 0x27, + 0x14, 0x2c, 0x3a, 0xc9, 0xd5, 0x26, 0x77, 0x19, 0x73, 0x28, 0xcb, 0x5d, 0xf5, 0x37, 0x23, 0xd1, 0xe9, 0xab, 0xf7, + 0x7c, 0x47, 0x3a, 0x2d, 0x6c, 0x08, 0x25, 0xce, 0x2f, 0x51, 0x5f, 0x71, 0x70, 0x66, 0xb1, 0x9e, 0xfe, 0xeb, 0xb5, + 0x4e, 0x58, 0x7b, 0xf0, 0x70, 0x58, 0xde, 0xb8, 0x20, 0xbf, 0x30, 0xd2, 0x92, 0x86, 0x01, 0x34, 0x5c, 0xb4, 0x38, + 0x35, 0xcb, 0x39, 0xf0, 0xc8, 0x2b, 0x73, 0xa2, 0x06, 0xaa, 0x3b, 0x7d, 0x1a, 0x1d, 0x94, 0xe0, 0x29, 0x5e, 0x9a, + 0xb2, 0x16, 0xd3, 0xf2, 0xa4, 0xd5, 0x1a, 0x4a, 0xbf, 0xb2, 0x24, 0x5d, 0x2b, 0x7c, 0x3a, 0xd7, 0xb4, 0x6a, 0xa8, + 0xc1, 0xbc, 0x0b, 0x02, 0xac, 0x28, 0x89, 0x5b, 0x9b, 0xe5, 0xdb, 0x6f, 0x7f, 0xd9, 0xe1, 0x18, 0x26, 0x3f, 0x7f, + 0x59, 0xc4, 0x6f, 0x1f, 0x6a, 0x98, 0xc7, 0x3c, 0x10, 0x17, 0x4f, 0x27, 0xfa, 0x39, 0xf5, 0x04, 0xcf, 0xa4, 0x5d, + 0xc4, 0x86, 0xd1, 0x80, 0xf3, 0xb7, 0x75, 0xab, 0x58, 0x58, 0x3b, 0x80, 0x61, 0x2e, 0xe8, 0x6b, 0x00, 0x18, 0x8e, + 0x50, 0x76, 0x21, 0x5a, 0x85, 0xea, 0xbd, 0xd1, 0x20, 0x6d, 0x6c, 0xb5, 0x27, 0x5a, 0x44, 0x10, 0x51, 0xbc, 0x8c, + 0x51, 0x0a, 0x8d, 0x41, 0x5e, 0xe2, 0x52, 0xb5, 0xc2, 0xce, 0xcb, 0x16, 0xfc, 0xb9, 0x70, 0x2a, 0x10, 0x44, 0x4d, + 0x64, 0x16, 0xb2, 0x91, 0x0d, 0x55, 0xda, 0x94, 0xd7, 0x59, 0xad, 0x46, 0x5c, 0xf3, 0xe1, 0xcd, 0x89, 0x05, 0xe4, + 0xec, 0xc0, 0xb6, 0x20, 0x0e, 0xab, 0x66, 0xc8, 0x89, 0x3e, 0xa7, 0x2d, 0xa3, 0xe7, 0x5b, 0xad, 0xb1, 0x53, 0xde, + 0x15, 0xea, 0x7e, 0xce, 0x47, 0x2c, 0x0c, 0x48, 0xed, 0xce, 0xff, 0x27, 0x68, 0x67, 0xdf, 0x97, 0x2b, 0x1d, 0xfe, + 0xe6, 0x6d, 0x31, 0x97, 0xdc, 0x8b, 0xa3, 0xc8, 0x15, 0xc7, 0x54, 0x08, 0x63, 0x5c, 0x84, 0x17, 0xfb, 0xe1, 0x55, + 0x67, 0x50, 0xe7, 0x65, 0x40, 0x43, 0x8e, 0x07, 0xf6, 0xde, 0x83, 0xa0, 0xc5, 0x17, 0x7b, 0x8b, 0xc6, 0x1a, 0x94, + 0x17, 0xc5, 0xb6, 0x0f, 0x20, 0xc3, 0xa6, 0xdc, 0xff, 0x8f, 0x9b, 0x17, 0xb9, 0x4b, 0x36, 0x12, 0x2f, 0x71, 0x29, + 0x5c, 0xb5, 0xf1, 0x77, 0x49, 0x05, 0x9f, 0x36, 0x62, 0x10, 0xcd, 0xb5, 0x93, 0x7f, 0x83, 0x65, 0xcb, 0xea, 0x2e, + 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8f, 0x6f, 0x6e, 0xbc, 0x0a, 0x0b, 0x7b, 0x38, 0x0c, 0x33, 0xde, 0xe3, 0x2e, 0x76, + 0xbd, 0xad, 0xaa, 0xd8, 0x2e, 0x32, 0xe6, 0xa2, 0xa9, 0x35, 0x46, 0x33, 0xb8, 0xb9, 0xa1, 0x85, 0xed, 0xdf, 0x4a, + 0xe8, 0x68, 0xf1, 0xb0, 0x75, 0x17, 0xe2, 0xe5, 0x75, 0xa1, 0x76, 0x14, 0x5c, 0xb2, 0x91, 0x94, 0x2c, 0xc8, 0xb0, + 0xee, 0x3b, 0xce, 0x01, 0x34, 0x85, 0xab, 0x11, 0xb7, 0x6b, 0xd9, 0x7e, 0x2d, 0xfd, 0xcb, 0xf2, 0x71, 0x33, 0xe8, + 0x90, 0x73, 0xa0, 0x10, 0x5f, 0x08, 0xd9, 0x9c, 0x10, 0x9d, 0xb4, 0x6d, 0xf5, 0x5e, 0x84, 0x23, 0xbf, 0x52, 0x64, + 0xea, 0x9f, 0x37, 0x33, 0x4c, 0xb5, 0x1e, 0xc1, 0xc0, 0x0e, 0x09, 0x57, 0xbf, 0xc5, 0xd0, 0xba, 0x65, 0xc0, 0xc6, + 0xaf, 0xe8, 0x6d, 0x3c, 0xab, 0x45, 0x0a, 0xf9, 0x05, 0x51, 0xdf, 0x5a, 0xd1, 0x04, 0xd7, 0xdd, 0x0b, 0x6b, 0x08, + 0xf3, 0x7b, 0x1a, 0x72, 0x0f, 0x6a, 0x03, 0xf9, 0x34, 0xdf, 0xef, 0x52, 0xf3, 0x07, 0x1c, 0xc1, 0x18, 0xe7, 0x1c, + 0xec, 0x9a, 0x7b, 0x6e, 0x8d, 0xa6, 0xaa, 0x6d, 0x03, 0x7b, 0x4b, 0xd7, 0xa3, 0x16, 0x1e, 0xbf, 0xed, 0xde, 0x3a, + 0xcb, 0x0e, 0xe3, 0x4d, 0xb9, 0x80, 0x8a, 0x45, 0x7b, 0xa1, 0xf2, 0x2c, 0x97, 0x31, 0x2e, 0x55, 0x20, 0x4e, 0x60, + 0x41, 0x4a, 0x6a, 0x6e, 0xca, 0x70, 0xcb, 0xd6, 0x65, 0x70, 0x34, 0x21, 0xdd, 0xfa, 0xf3, 0xcc, 0xe7, 0x66, 0x72, + 0x54, 0xd1, 0xa7, 0x08, 0xcc, 0x12, 0x7d, 0x5a, 0xc0, 0x51, 0xa6, 0xaf, 0x4b, 0x11, 0x24, 0xe2, 0xdd, 0xa0, 0xcf, + 0xb5, 0x02, 0x45, 0x21, 0x31, 0xf2, 0x2e, 0x7a, 0xb4, 0x40, 0x3f, 0x78, 0x1a, 0x8c, 0x49, 0x7c, 0xfa, 0xef, 0xb2, + 0x57, 0xf1, 0x29, 0x59, 0xca, 0xfa, 0xde, 0x90, 0x4a, 0xe4, 0x24, 0x0d, 0x91, 0x74, 0x7e, 0xaa, 0xc0, 0xd4, 0x71, + 0xee, 0xcd, 0x5f, 0xa1, 0x1f, 0x7a, 0x2b, 0x26, 0x08, 0xd8, 0x8f, 0x71, 0x11, 0xd7, 0xe5, 0x0b, 0xfb, 0x98, 0x0e, + 0xcc, 0x02, 0xa3, 0xd5, 0x19, 0xf1, 0x40, 0xd2, 0x49, 0xb0, 0x94, 0x5d, 0x33, 0x97, 0x3a, 0x00, 0xe4, 0x6b, 0x93, + 0xcb, 0xde, 0x11, 0xe2, 0x4b, 0x76, 0x7d, 0x47, 0x10, 0x29, 0x53, 0xad, 0xa2, 0x1d, 0xb9, 0x47, 0x9a, 0x08, 0x96, + 0xea, 0x14, 0x2d, 0x6d, 0xb3, 0xed, 0xed, 0xec, 0x78, 0xee, 0xef, 0x72, 0x5f, 0x61, 0x8a, 0x16, 0xd4, 0xdf, 0xc5, + 0x45, 0x52, 0x55, 0x10, 0x21, 0x66, 0x70, 0x83, 0xb3, 0x31, 0xe2, 0x52, 0xa9, 0xe4, 0xcf, 0xf6, 0x40, 0x73, 0xd3, + 0xab, 0xd4, 0x54, 0xb8, 0x1a, 0x0b, 0x9b, 0xd8, 0x52, 0x3b, 0xb0, 0x44, 0x82, 0x07, 0x4f, 0x6f, 0x71, 0x5f, 0x96, + 0xbb, 0x13, 0xc1, 0x69, 0xd1, 0xd2, 0x13, 0x0f, 0xcb, 0x44, 0xbe, 0x93, 0xdd, 0xee, 0x9a, 0x22, 0xcd, 0x1e, 0x37, + 0xe9, 0x0e, 0x47, 0x29, 0x63, 0x55, 0x69, 0xde, 0x81, 0x6b, 0x2e, 0x81, 0x8b, 0x8e, 0x11, 0xad, 0x87, 0x26, 0xf5, + 0x69, 0x00, 0x5a, 0x40, 0xb5, 0x16, 0x39, 0x0e, 0xea, 0x80, 0x89, 0x2b, 0x1a, 0x06, 0x97, 0x00, 0xb1, 0xf3, 0x19, + 0xb2, 0xf3, 0x59, 0xc8, 0xb7, 0x94, 0x9b, 0x6d, 0x90, 0x44, 0xbe, 0x6a, 0x7d, 0x28, 0x36, 0x23, 0xf1, 0xa1, 0xa1, + 0x0f, 0xcf, 0x35, 0xfa, 0xf1, 0xcd, 0x55, 0xbf, 0xe2, 0xad, 0xe3, 0x9c, 0x06, 0x1f, 0x93, 0x74, 0xd1, 0x0a, 0xcf, + 0x65, 0x79, 0xa7, 0x85, 0xa7, 0xf1, 0x14, 0x86, 0x53, 0x65, 0xfd, 0x6a, 0x73, 0xd5, 0xf2, 0xd4, 0x46, 0x51, 0x5f, + 0x49, 0xf1, 0xef, 0xce, 0xc4, 0x6a, 0x89, 0x98, 0x63, 0x52, 0xae, 0x79, 0x5a, 0x4d, 0x4b, 0xc7, 0xff, 0xfc, 0xd0, + 0xf9, 0xa5, 0xec, 0x04, 0xc0, 0x54, 0xc6, 0x18, 0x61, 0xc5, 0x7b, 0x19, 0x35, 0x43, 0xec, 0x25, 0xb3, 0xc3, 0x58, + 0xa3, 0xda, 0x3f, 0xdd, 0x7a, 0x14, 0xb6, 0x25, 0xe9, 0xe1, 0xde, 0x42, 0xf0, 0x85, 0xac, 0xf4, 0xef, 0xb6, 0x8e, + 0xb4, 0xe4, 0xc5, 0x45, 0x8c, 0x92, 0x20, 0x91, 0x8e, 0xa3, 0xb6, 0x56, 0x73, 0x13, 0x16, 0x1a, 0xc6, 0x52, 0x5b, + 0xa7, 0xac, 0x16, 0xb6, 0x14, 0x63, 0x8e, 0x64, 0x3c, 0x32, 0xcf, 0x48, 0xcf, 0x11, 0xde, 0xe5, 0xd6, 0xd1, 0xa0, + 0xea, 0xee, 0xb9, 0xf6, 0xc2, 0x8b, 0xf6, 0x25, 0xe7, 0x9f, 0x5b, 0x49, 0x0d, 0xc5, 0x9d, 0x0c, 0x8d, 0xea, 0x89, + 0xc3, 0xec, 0xda, 0xe4, 0x03, 0x41, 0x13, 0x27, 0x2b, 0x9d, 0xe1, 0xe7, 0xdc, 0xf2, 0x17, 0xc7, 0x53, 0x13, 0xad, + 0x81, 0x6d, 0x47, 0x16, 0x6a, 0x03, 0xfc, 0x06, 0x6f, 0x42, 0xb3, 0x80, 0x96, 0xb0, 0x18, 0xe2, 0xd4, 0xcd, 0x98, + 0x34, 0x49, 0x3a, 0x5d, 0x20, 0xfc, 0x74, 0x9b, 0x99, 0x8e, 0x65, 0x0f, 0x77, 0x39, 0x90, 0xa9, 0xa1, 0x14, 0x8f, + 0xa0, 0xb9, 0x3c, 0x89, 0x6e, 0xc6, 0x54, 0xc2, 0x37, 0x6c, 0x9f, 0xb3, 0xf4, 0x1e, 0xbd, 0x42, 0x9b, 0x9e, 0x05, + 0x2b, 0x8f, 0x1b, 0x41, 0x8b, 0x4c, 0x18, 0x20, 0xbb, 0xe7, 0x00, 0x96, 0x16, 0xdb, 0x8b, 0xa6, 0xa3, 0x23, 0x91, + 0x2d, 0xc6, 0xd6, 0x38, 0xc7, 0xe6, 0x2a, 0xd4, 0x82, 0x9d, 0xe5, 0x25, 0x50, 0x36, 0xb2, 0xc3, 0x3b, 0xc6, 0x9f, + 0xbc, 0x21, 0x01, 0x4c, 0x69, 0xea, 0xd3, 0x2e, 0x7a, 0x15, 0x6c, 0xef, 0xfa, 0x58, 0xc4, 0x81, 0x39, 0x70, 0xc3, + 0x58, 0x1a, 0x3b, 0x53, 0x75, 0xcd, 0x03, 0x5a, 0xa9, 0xaa, 0x2b, 0x06, 0x21, 0x09, 0xc6, 0xbc, 0x3c, 0x15, 0x52, + 0xb3, 0x50, 0x2d, 0xdd, 0x74, 0x6a, 0x9b, 0xa0, 0xb0, 0x38, 0x9e, 0x9a, 0x3d, 0x0c, 0x32, 0x5c, 0xbf, 0x7f, 0x66, + 0x06, 0x48, 0x12, 0xae, 0x04, 0x94, 0xd1, 0xb0, 0xb3, 0x6d, 0xd6, 0x43, 0xbf, 0xdd, 0x24, 0xa2, 0xdd, 0xae, 0x1c, + 0x33, 0xea, 0x83, 0xea, 0x85, 0xe1, 0xf4, 0xce, 0x08, 0x8d, 0x84, 0x04, 0xd8, 0xc8, 0x8f, 0xfa, 0x0b, 0x52, 0xb1, + 0xc4, 0x45, 0xdb, 0x79, 0x61, 0xd6, 0xef, 0xf3, 0x40, 0x66, 0xf0, 0x04, 0x9b, 0xe6, 0x2c, 0x82, 0x6a, 0x24, 0x0b, + 0x12, 0x04, 0x44, 0xd5, 0xb6, 0x4f, 0x55, 0xb5, 0x15, 0x34, 0xce, 0xe3, 0x17, 0x9c, 0x9e, 0x7e, 0x6d, 0x10, 0x54, + 0xe2, 0x5f, 0xd9, 0xbc, 0xc5, 0x6b, 0x60, 0x8b, 0xeb, 0x91, 0xf2, 0x45, 0x5d, 0x96, 0x3f, 0xba, 0xb0, 0x4a, 0xfa, + 0xf7, 0xd6, 0x58, 0x88, 0x2a, 0x7f, 0xba, 0x42, 0x21, 0xa9, 0x3c, 0xba, 0xf3, 0x46, 0xf0, 0x25, 0x3b, 0x89, 0xc6, + 0xa2, 0x9d, 0xf4, 0x84, 0x1d, 0xae, 0x4a, 0x23, 0x88, 0x14, 0xff, 0x62, 0x45, 0x90, 0xb8, 0x2a, 0x5a, 0x76, 0x32, + 0x68, 0x25, 0x7b, 0xa0, 0xce, 0x89, 0x1b, 0xf3, 0x72, 0x6d, 0xca, 0xb7, 0x77, 0x27, 0x3a, 0xc8, 0x1a, 0x93, 0xe0, + 0x51, 0x83, 0x7d, 0xcb, 0x64, 0xbb, 0xec, 0x38, 0xf5, 0xa6, 0xa7, 0xef, 0xb9, 0x19, 0x09, 0x69, 0x09, 0x10, 0xf9, + 0xda, 0x8d, 0xc4, 0xec, 0xd6, 0xe3, 0x6d, 0x47, 0x2c, 0xe6, 0x76, 0x22, 0x4a, 0xa3, 0x8e, 0x6b, 0xf3, 0x10, 0x85, + 0x60, 0x85, 0xb1, 0x44, 0x97, 0x5f, 0x49, 0xe4, 0x16, 0x0b, 0x1b, 0xfb, 0x58, 0x7d, 0xca, 0x61, 0x93, 0x03, 0x84, + 0x70, 0xa9, 0x5b, 0xfd, 0x2b, 0xf4, 0x36, 0x7b, 0x42, 0xbf, 0x62, 0xe4, 0xe0, 0xa1, 0x0c, 0xd6, 0xad, 0x79, 0xd7, + 0x82, 0xc7, 0x2a, 0x2a, 0xf7, 0x61, 0x11, 0x21, 0x14, 0xf7, 0xfb, 0xd1, 0x50, 0xed, 0x5a, 0x62, 0x44, 0xf4, 0x28, + 0x19, 0x48, 0x6d, 0x3a, 0x85, 0x2b, 0x51, 0xc4, 0xe5, 0xa5, 0x1d, 0xcf, 0x67, 0x3b, 0xbb, 0x1b, 0x8d, 0x34, 0xf6, + 0xdd, 0xc0, 0xf1, 0x72, 0x2b, 0xcd, 0x1a, 0x8b, 0xb6, 0xef, 0x67, 0xb7, 0xb6, 0x05, 0xa2, 0x30, 0x62, 0xc4, 0xdc, + 0xb6, 0xf3, 0x09, 0xe9, 0x60, 0x27, 0x9f, 0xb1, 0x8f, 0x0d, 0x8c, 0x67, 0x30, 0x9b, 0xaa, 0xbe, 0xf6, 0xee, 0x67, + 0xf6, 0xbf, 0x0b, 0x6a, 0x23, 0x3f, 0x5f, 0xae, 0x44, 0x08, 0x68, 0x5c, 0xe8, 0x45, 0x86, 0x88, 0x1e, 0x4d, 0xb2, + 0x73, 0xd7, 0xe8, 0x25, 0xf6, 0xba, 0x90, 0x61, 0x87, 0xe3, 0x8f, 0xd6, 0x66, 0x4f, 0x68, 0x8e, 0xbf, 0x9f, 0x5d, + 0x1b, 0xfb, 0x5a, 0x8d, 0x93, 0x2c, 0x58, 0x95, 0x89, 0xd3, 0xf5, 0x7b, 0x8e, 0x28, 0x3e, 0xd3, 0xa9, 0xfb, 0x8e, + 0x36, 0x9e, 0x49, 0xd9, 0x48, 0x2a, 0xdd, 0x48, 0xa0, 0x32, 0x2b, 0x93, 0x77, 0x7b, 0x01, 0x50, 0x6d, 0x04, 0x58, + 0x34, 0x17, 0x9a, 0xa9, 0xec, 0x8b, 0xce, 0xd3, 0x43, 0xa4, 0x1c, 0x0f, 0x6f, 0x8e, 0x96, 0xa1, 0xc5, 0xeb, 0xd3, + 0x9c, 0xfd, 0x9b, 0x5b, 0x0d, 0x1d, 0xed, 0x1d, 0x15, 0x49, 0x73, 0xc1, 0xf4, 0xff, 0x62, 0xc5, 0x34, 0x00, 0x84, + 0x83, 0x06, 0x9c, 0xae, 0x72, 0x83, 0x0b, 0x92, 0x17, 0x98, 0xe6, 0xe2, 0x4c, 0xa0, 0xb5, 0x0d, 0x44, 0x54, 0xb4, + 0xe6, 0x47, 0x97, 0x71, 0xf1, 0x88, 0x76, 0x8e, 0x41, 0x54, 0xd4, 0xdf, 0xf6, 0x99, 0xb4, 0x82, 0xd9, 0xe7, 0x1c, + 0xb8, 0x5e, 0x33, 0x95, 0x12, 0x14, 0x83, 0xed, 0xb6, 0xfd, 0x36, 0x65, 0x10, 0x6a, 0xf4, 0x77, 0x52, 0xa1, 0x03, + 0xa3, 0x20, 0x47, 0x08, 0xe4, 0xdd, 0x1e, 0xf4, 0x59, 0x50, 0xd4, 0x33, 0xe2, 0x80, 0x9d, 0xbf, 0x76, 0x1c, 0xce, + 0x50, 0x7c, 0x9d, 0xfb, 0xf1, 0xdb, 0xba, 0x68, 0x1e, 0xdc, 0xf8, 0x43, 0xff, 0xfe, 0x11, 0x6d, 0x8b, 0xf6, 0x09, + 0x36, 0xc7, 0xcf, 0xe8, 0xf0, 0xb6, 0x19, 0x9c, 0x79, 0x7b, 0x42, 0x23, 0x10, 0x5b, 0x90, 0x3c, 0x17, 0xe8, 0x9c, + 0x43, 0x13, 0x9e, 0x67, 0xcd, 0x4c, 0x7e, 0xfa, 0x26, 0x55, 0xee, 0xa3, 0xec, 0xf8, 0x58, 0x74, 0xbb, 0xc4, 0x33, + 0x94, 0x6e, 0xe7, 0x56, 0x72, 0xdb, 0x87, 0x60, 0xfe, 0xe1, 0xb7, 0xbb, 0xdd, 0x63, 0x65, 0xfe, 0xcf, 0x4f, 0xd6, + 0x44, 0x3f, 0xdb, 0x45, 0xf3, 0xcb, 0x2a, 0x08, 0x0a, 0x5f, 0xee, 0x3a, 0xbd, 0x2c, 0xd0, 0xb8, 0x43, 0xd5, 0xb5, + 0x86, 0xab, 0xb9, 0x9a, 0xb9, 0x67, 0x2e, 0xee, 0x38, 0x9f, 0x91, 0x97, 0xd5, 0xe2, 0x7a, 0x40, 0xbf, 0x7d, 0x35, + 0xe6, 0x3f, 0xbf, 0x84, 0x26, 0xe5, 0xdc, 0xfd, 0x89, 0xf0, 0x7f, 0x83, 0x6b, 0x7a, 0xe7, 0x8e, 0xa2, 0xe0, 0x8c, + 0xeb, 0x9a, 0x61, 0x9b, 0x9c, 0x73, 0xe1, 0xb8, 0x4e, 0x39, 0xf0, 0xea, 0x10, 0x9b, 0x80, 0x30, 0xad, 0x8c, 0x67, + 0x4e, 0x9f, 0x46, 0xf2, 0x67, 0x0c, 0x18, 0x76, 0x1d, 0x82, 0x86, 0x60, 0x40, 0x89, 0xc5, 0xe8, 0xd4, 0x9d, 0x8c, + 0xa9, 0x26, 0x42, 0xd6, 0x80, 0x2d, 0x81, 0x12, 0xad, 0x6f, 0x81, 0x00, 0x5a, 0x3a, 0x81, 0x97, 0x8d, 0x8a, 0x1e, + 0x2d, 0x59, 0xc3, 0xe0, 0x60, 0xfe, 0x47, 0x1c, 0x8e, 0xe0, 0x7c, 0x8b, 0x84, 0xb8, 0x9b, 0x5b, 0x8f, 0xd2, 0xc6, + 0xf4, 0x89, 0xbe, 0x66, 0x1f, 0xf5, 0x14, 0xa4, 0xf9, 0xaf, 0x8b, 0x01, 0x82, 0x61, 0x38, 0x4e, 0x38, 0x5e, 0x25, + 0xf3, 0x0b, 0xa2, 0x76, 0xb1, 0xfe, 0xe5, 0x0c, 0xc6, 0xf6, 0x6f, 0xbc, 0xb6, 0x91, 0xff, 0x7f, 0x83, 0x25, 0xb7, + 0xbf, 0xe4, 0xe6, 0xcb, 0xbf, 0x96, 0xc7, 0x5f, 0xbe, 0xe6, 0x5b, 0xbe, 0x9b, 0x26, 0x78, 0xa7, 0xeb, 0x5e, 0xc9, + 0x50, 0xf3, 0xf3, 0x15, 0x46, 0xb8, 0x86, 0xc1, 0xd1, 0x58, 0x00, 0x1f, 0x2a, 0xda, 0x1c, 0x3d, 0x1b, 0x28, 0x13, + 0xfb, 0x35, 0x1e, 0x51, 0xbd, 0x5e, 0x81, 0x8f, 0x5d, 0x8d, 0x6b, 0x99, 0x5e, 0x26, 0x5a, 0xf3, 0x5c, 0xd9, 0xa5, + 0x86, 0x8a, 0x3b, 0xda, 0x02, 0xbe, 0x41, 0x5f, 0x57, 0xbe, 0xc4, 0x3a, 0xb2, 0xd9, 0x94, 0x27, 0x09, 0x4a, 0x3c, + 0x70, 0xd1, 0xf0, 0xd5, 0x33, 0xdb, 0x62, 0x7d, 0xf8, 0x73, 0xd1, 0x54, 0x13, 0x88, 0x7a, 0x54, 0x63, 0x36, 0x62, + 0xad, 0x55, 0x46, 0xcb, 0xab, 0x61, 0xe8, 0x48, 0xc6, 0xc5, 0xac, 0x32, 0xa1, 0x0c, 0xe8, 0x07, 0x4c, 0xd6, 0x2b, + 0xfa, 0x47, 0x3b, 0x45, 0xbe, 0x54, 0x9f, 0x52, 0xd4, 0xc3, 0xe3, 0x09, 0x8e, 0x53, 0x1f, 0x35, 0xfc, 0xa6, 0x49, + 0x5c, 0x85, 0x6b, 0x38, 0x37, 0x59, 0x73, 0xe6, 0x65, 0x6b, 0x97, 0x3a, 0x98, 0xd3, 0x84, 0xfd, 0x5b, 0xdb, 0x62, + 0xf1, 0x79, 0x12, 0x68, 0xbb, 0x68, 0x26, 0x97, 0xca, 0x5a, 0x10, 0x65, 0xfa, 0xf0, 0x06, 0x12, 0x88, 0xce, 0xb9, + 0x06, 0xea, 0xdb, 0xd4, 0x71, 0x38, 0xb7, 0x68, 0xab, 0x16, 0x2e, 0xad, 0xde, 0x6c, 0xa6, 0x70, 0xc2, 0x67, 0x97, + 0xf6, 0x22, 0x99, 0x68, 0xde, 0xe5, 0x89, 0x64, 0xfa, 0x6e, 0xec, 0xb3, 0x01, 0x71, 0x8b, 0x41, 0xcf, 0xc2, 0x44, + 0x19, 0xae, 0x29, 0xd8, 0x75, 0x95, 0x18, 0xc7, 0x01, 0xe0, 0xec, 0xd3, 0x90, 0x1b, 0x70, 0x78, 0x5d, 0x1b, 0x43, + 0x27, 0xba, 0x5b, 0xf4, 0x4a, 0x0a, 0x42, 0x50, 0xe5, 0xb0, 0xc4, 0xe6, 0x3d, 0xd9, 0x0b, 0xcb, 0x37, 0x78, 0xd8, + 0xb9, 0x53, 0x32, 0xe1, 0x4e, 0xe7, 0x09, 0x53, 0x56, 0xd1, 0x3b, 0xe4, 0x66, 0xc4, 0xeb, 0x0a, 0x8c, 0x29, 0x5c, + 0x01, 0x1b, 0x74, 0x88, 0xba, 0xf1, 0xdb, 0xef, 0x7a, 0xb9, 0xd9, 0xbb, 0x2d, 0x36, 0x33, 0x9e, 0xd1, 0x5a, 0xef, + 0x60, 0xed, 0x2c, 0xbd, 0xb6, 0x33, 0xb2, 0x50, 0x20, 0xc0, 0xc9, 0xdd, 0x66, 0x3d, 0x38, 0x46, 0x34, 0x97, 0xff, + 0x3b, 0x8b, 0x5d, 0x55, 0x4e, 0xbd, 0x31, 0xf4, 0x8a, 0x64, 0xe4, 0x10, 0x80, 0x64, 0x9c, 0x35, 0x1d, 0xa3, 0xd9, + 0xbb, 0xda, 0x76, 0x0e, 0xd3, 0xec, 0xdb, 0x34, 0xd7, 0xef, 0x4f, 0xe6, 0x5e, 0x20, 0x3f, 0x03, 0x37, 0xca, 0xd5, + 0x27, 0x8c, 0x75, 0x0f, 0xb4, 0x34, 0xb3, 0xfa, 0x46, 0x9e, 0xab, 0x19, 0xcb, 0x6d, 0xb0, 0xef, 0x06, 0x15, 0x0f, + 0xb0, 0xa0, 0x3f, 0xc9, 0xcb, 0xf3, 0x77, 0xaa, 0xe6, 0x6e, 0x7a, 0x84, 0x8d, 0x95, 0xcb, 0x70, 0x12, 0x2f, 0x87, + 0xfe, 0x05, 0x47, 0xcf, 0x89, 0xf9, 0x5f, 0x56, 0x24, 0x5d, 0x31, 0xcf, 0x30, 0x99, 0x18, 0xa5, 0x21, 0xc5, 0x19, + 0x2a, 0xe8, 0x7f, 0x58, 0x70, 0xbb, 0x6e, 0xd8, 0x40, 0x8a, 0x7f, 0xe3, 0x3e, 0x3b, 0x9e, 0x7b, 0xab, 0xcc, 0xa4, + 0x97, 0xcd, 0x71, 0x4b, 0xae, 0x6a, 0x5a, 0xcd, 0x7c, 0x56, 0x90, 0x4c, 0xdb, 0xcd, 0x63, 0x5e, 0x19, 0xbf, 0x74, + 0x13, 0xc9, 0x64, 0x4f, 0x67, 0x37, 0x40, 0x6b, 0x07, 0xda, 0xa7, 0xc4, 0xe9, 0x49, 0xa7, 0xab, 0x37, 0x3b, 0xa3, + 0x68, 0x9b, 0x5c, 0xa7, 0x1f, 0x68, 0xbd, 0xa0, 0xa3, 0xdb, 0x59, 0x2b, 0xc9, 0x73, 0x9f, 0xd8, 0x24, 0xc1, 0x4f, + 0xae, 0x63, 0xc1, 0xb1, 0x69, 0x40, 0x3f, 0xce, 0xcb, 0xf3, 0x4d, 0xde, 0x45, 0x06, 0x7c, 0xa6, 0xb0, 0xd9, 0xec, + 0x86, 0x31, 0xc7, 0x86, 0x18, 0x21, 0x48, 0x97, 0xe7, 0xed, 0x69, 0xdd, 0x09, 0x8d, 0xb7, 0x2c, 0x5c, 0x9b, 0x93, + 0x8b, 0xc2, 0xcf, 0xf4, 0xda, 0x34, 0x5c, 0xd0, 0x14, 0xda, 0xe7, 0x7e, 0x9a, 0x84, 0xe9, 0x1e, 0x93, 0xa8, 0x1a, + 0xee, 0xa6, 0x85, 0xfa, 0xb0, 0x50, 0x9e, 0x37, 0xe0, 0x05, 0x2b, 0xdc, 0xf3, 0x39, 0x39, 0x16, 0xf6, 0xe6, 0xbd, + 0xdb, 0x07, 0xb0, 0x5a, 0xcb, 0x3d, 0x66, 0xdc, 0xf1, 0xbe, 0xa3, 0x95, 0xfd, 0xd7, 0xb2, 0xe4, 0x58, 0x87, 0xad, + 0x9a, 0x65, 0xf0, 0x15, 0xa1, 0x39, 0x52, 0x03, 0x4d, 0x7c, 0x40, 0xa0, 0x0a, 0x84, 0x3b, 0x32, 0x6d, 0x67, 0x3c, + 0x65, 0xd4, 0xd1, 0x86, 0xa3, 0xa9, 0x13, 0x3b, 0x1e, 0x9e, 0x14, 0x5b, 0x0c, 0xbf, 0x35, 0xbd, 0x01, 0xcf, 0x7d, + 0x0f, 0xb4, 0xdd, 0xbd, 0x0e, 0x53, 0x7c, 0x65, 0x56, 0xd8, 0xc1, 0xaa, 0xd5, 0x18, 0x84, 0xd8, 0xb4, 0xca, 0xdc, + 0x15, 0x53, 0x02, 0x0c, 0xe7, 0xd4, 0xf8, 0xe2, 0xe0, 0x36, 0x34, 0x72, 0x6f, 0x32, 0x05, 0x4a, 0x1c, 0x5d, 0x0b, + 0x78, 0x92, 0xc6, 0x7c, 0x5a, 0x55, 0xc0, 0xaf, 0x8d, 0x7a, 0x15, 0x06, 0x74, 0xf1, 0x2e, 0x89, 0x1e, 0xf4, 0x90, + 0x22, 0x8e, 0xa7, 0x22, 0x5b, 0x13, 0xc6, 0xba, 0xce, 0xf6, 0xa1, 0x36, 0xf0, 0x7b, 0x45, 0xb5, 0x1f, 0xe0, 0xdd, + 0x06, 0x95, 0x95, 0x77, 0x87, 0xdf, 0x36, 0xb7, 0x24, 0xee, 0x25, 0x87, 0xe2, 0xba, 0xfa, 0x2a, 0x22, 0x03, 0x1e, + 0x94, 0x6a, 0x4d, 0x17, 0xc5, 0xf1, 0x53, 0x0a, 0xc6, 0x32, 0x45, 0x75, 0x32, 0xd3, 0xf6, 0x62, 0x84, 0x68, 0x74, + 0xec, 0x68, 0x73, 0x67, 0xe6, 0xcf, 0x27, 0x44, 0xe4, 0x04, 0xdb, 0xff, 0x54, 0x5e, 0x9c, 0x8d, 0x48, 0x18, 0xec, + 0xdf, 0x36, 0x43, 0x6a, 0x9f, 0xaa, 0x49, 0x9d, 0x86, 0x48, 0xd9, 0x0f, 0x6b, 0x5a, 0xff, 0xbf, 0xf8, 0x5c, 0x18, + 0x0d, 0x44, 0xef, 0xd4, 0x5b, 0x57, 0x4a, 0x60, 0xbb, 0xda, 0xa5, 0xf2, 0x52, 0xfa, 0xbc, 0x6f, 0x75, 0x13, 0x93, + 0xb2, 0xe0, 0x4d, 0xed, 0xcf, 0xd1, 0xfa, 0x49, 0xab, 0x0d, 0xb9, 0x77, 0xfa, 0xd4, 0xe3, 0x10, 0x23, 0x29, 0x27, + 0x88, 0xb1, 0xd4, 0x86, 0x10, 0x81, 0x47, 0x59, 0x83, 0xbb, 0xfe, 0xc9, 0x44, 0x6d, 0x93, 0x06, 0x68, 0x94, 0xe7, + 0x6d, 0xb1, 0xf5, 0xea, 0x4e, 0xe9, 0x8a, 0xdb, 0xe1, 0xca, 0xd6, 0x25, 0x60, 0x3a, 0x31, 0xf8, 0x74, 0x47, 0x77, + 0x0a, 0x78, 0x13, 0xec, 0x26, 0x13, 0xd0, 0x10, 0xc3, 0xd9, 0x7c, 0xf1, 0xcf, 0x96, 0x63, 0x7e, 0xe9, 0x07, 0x6c, + 0x0d, 0x92, 0x06, 0x70, 0x66, 0x00, 0x5b, 0x9f, 0x37, 0x57, 0xaa, 0x6f, 0x0f, 0xff, 0xda, 0x32, 0x7e, 0x47, 0x6e, + 0xf8, 0x7a, 0xdb, 0xd5, 0xc1, 0xf2, 0xc2, 0xb0, 0x43, 0xa0, 0x33, 0xa8, 0x4b, 0x0a, 0x93, 0xde, 0x05, 0xd4, 0xb9, + 0xd7, 0xb8, 0x81, 0x2b, 0x23, 0x84, 0x61, 0xc8, 0x83, 0xca, 0xb9, 0xbd, 0xc2, 0xbd, 0xf5, 0x3d, 0x81, 0x16, 0x20, + 0x3c, 0x54, 0xa1, 0x6d, 0x91, 0x49, 0xe7, 0xde, 0x60, 0xbb, 0x84, 0x75, 0x29, 0xe5, 0x54, 0x6b, 0x4e, 0xd7, 0x21, + 0xf9, 0xb8, 0xad, 0xfa, 0x16, 0x03, 0x72, 0x04, 0xa1, 0xd4, 0x33, 0x64, 0xd7, 0x70, 0x91, 0x5e, 0x6e, 0x8e, 0x74, + 0xca, 0xd7, 0x02, 0x62, 0x9b, 0xba, 0xdb, 0xa2, 0xfb, 0x7c, 0x2b, 0x0f, 0x41, 0x66, 0x9a, 0x4b, 0x40, 0xa2, 0x31, + 0x05, 0xf5, 0xc3, 0x30, 0x29, 0x97, 0xff, 0x5e, 0x23, 0x5e, 0xe7, 0xf1, 0xfa, 0xe7, 0x27, 0xab, 0xea, 0xc3, 0xf6, + 0x07, 0x3f, 0xd0, 0x7b, 0xb1, 0x69, 0xad, 0xde, 0x5e, 0xac, 0xbe, 0x9b, 0x15, 0xd4, 0xcf, 0x2c, 0x99, 0x41, 0x18, + 0x4b, 0x9d, 0x9d, 0xf1, 0x41, 0x5c, 0xf3, 0x1b, 0xb6, 0x5c, 0xde, 0x23, 0xf5, 0x2e, 0x93, 0x34, 0x99, 0xa6, 0xac, + 0x3e, 0xad, 0x4f, 0x3b, 0x45, 0xa0, 0x8d, 0x3a, 0x7a, 0x0d, 0xa7, 0x1c, 0xb8, 0x68, 0xd3, 0xa2, 0xbb, 0xcb, 0x3f, + 0x0b, 0x96, 0x85, 0x6e, 0x7f, 0x5d, 0x0e, 0xd6, 0x0d, 0x9f, 0x57, 0x74, 0x2e, 0x9c, 0xc8, 0xa1, 0x85, 0x05, 0x56, + 0x3b, 0x65, 0x70, 0xa6, 0xde, 0x64, 0x8b, 0x13, 0xdd, 0x44, 0x07, 0x79, 0x65, 0xac, 0xe3, 0xd4, 0x4b, 0xc3, 0x01, + 0xba, 0x66, 0x85, 0xcf, 0xf9, 0xa8, 0xcf, 0xfb, 0x13, 0x3a, 0x53, 0x90, 0xb5, 0xdc, 0x59, 0x14, 0xcb, 0xbb, 0x90, + 0x57, 0x51, 0x7d, 0xb9, 0x18, 0x59, 0x21, 0x94, 0x05, 0x6c, 0x7b, 0x7d, 0x1c, 0x87, 0x22, 0xf7, 0xa4, 0xc4, 0xd3, + 0xce, 0x39, 0x52, 0xee, 0x12, 0xe4, 0xee, 0x8a, 0xc5, 0x69, 0x24, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x86, 0xae, + 0x28, 0x72, 0x8b, 0x21, 0x04, 0x1c, 0x0d, 0x6f, 0x6f, 0xb4, 0x6d, 0xa4, 0x0c, 0x12, 0xc5, 0xce, 0x08, 0xe9, 0x97, + 0xb9, 0xa1, 0x7c, 0xb3, 0x0f, 0xa6, 0x8c, 0x41, 0x04, 0x04, 0x2a, 0xc8, 0x00, 0x2c, 0xfb, 0xca, 0xb9, 0x1a, 0x06, + 0xe3, 0x0c, 0x46, 0x02, 0x2b, 0xa0, 0xd7, 0x45, 0x93, 0x6e, 0xf8, 0x53, 0x78, 0x9a, 0x2a, 0x9e, 0xa6, 0x85, 0xa2, + 0xd1, 0x51, 0x79, 0x36, 0xa5, 0x6b, 0x9e, 0x06, 0x0b, 0x52, 0x4f, 0x9a, 0x1c, 0x36, 0x06, 0xf3, 0x68, 0x24, 0xe1, + 0x9e, 0x9a, 0x8c, 0x62, 0x65, 0x68, 0x1c, 0xfd, 0xb3, 0x3b, 0xc4, 0x39, 0x74, 0x50, 0x0b, 0xde, 0xcc, 0xe8, 0xe1, + 0xcc, 0x0f, 0x41, 0x6a, 0xd8, 0x5c, 0x85, 0xf9, 0x45, 0xa6, 0x4e, 0x75, 0xca, 0x28, 0x4b, 0x8c, 0xb3, 0x60, 0xed, + 0x18, 0x72, 0xa4, 0x7e, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, 0xb6, 0xf4, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, + 0xde, 0xd2, 0xf5, 0x5f, 0xcc, 0x6c, 0xdd, 0x8e, 0x39, 0x7f, 0xe9, 0xe7, 0xbb, 0xe9, 0x43, 0x1f, 0xf3, 0x66, 0xec, + 0x0c, 0x33, 0xba, 0xfe, 0x22, 0x2d, 0x1e, 0x14, 0x0d, 0x8a, 0x7c, 0xa9, 0x31, 0x8e, 0xb4, 0xbf, 0x1f, 0x9a, 0x46, + 0xbb, 0xdb, 0x3b, 0x49, 0x1a, 0x61, 0xcb, 0x11, 0x7a, 0x23, 0x38, 0x76, 0xc5, 0x7f, 0x5c, 0x55, 0xfe, 0x77, 0x4f, + 0xfd, 0xbe, 0x3d, 0x08, 0x5f, 0xd5, 0x4d, 0x1f, 0x46, 0x01, 0x73, 0xd6, 0xba, 0x5d, 0x7d, 0x96, 0x50, 0x43, 0xfa, + 0x6b, 0x82, 0xfa, 0x8d, 0x63, 0xf5, 0x8f, 0x69, 0x4a, 0xfe, 0x62, 0x57, 0xc1, 0xc6, 0x6c, 0xfd, 0x58, 0xd8, 0xa3, + 0x5a, 0x39, 0x3e, 0x77, 0xa7, 0x2d, 0x19, 0xed, 0x49, 0xf9, 0x56, 0x77, 0x78, 0xda, 0x49, 0x59, 0xca, 0xe6, 0x3d, + 0xb5, 0x98, 0x4c, 0x57, 0xdb, 0x4a, 0x1c, 0x91, 0x1e, 0xe4, 0x1b, 0x73, 0x46, 0xe9, 0xf8, 0x7d, 0xe5, 0x8f, 0xbb, + 0x93, 0xd8, 0xcc, 0xd3, 0x93, 0x70, 0x0b, 0xb4, 0x2b, 0xfb, 0x7e, 0x2b, 0xee, 0x3b, 0x29, 0xfe, 0x76, 0xd9, 0xaf, + 0x73, 0x95, 0x02, 0x1e, 0xf7, 0xbe, 0x60, 0xfb, 0xf9, 0x3a, 0x52, 0xd8, 0x8e, 0x14, 0x43, 0xb6, 0xf9, 0xaa, 0x4b, + 0xa2, 0x0a, 0x59, 0xf0, 0x06, 0xf9, 0x20, 0xae, 0x05, 0x20, 0xe7, 0xb4, 0x45, 0x2d, 0xfb, 0x8e, 0x25, 0x51, 0xbe, + 0xab, 0x40, 0x2d, 0x79, 0x76, 0x51, 0xd1, 0xa9, 0x3b, 0xe1, 0xab, 0x53, 0xcf, 0xd2, 0x9c, 0x86, 0xe8, 0x7a, 0x58, + 0xf2, 0x12, 0x95, 0xac, 0x9a, 0xde, 0x4d, 0xf0, 0x2b, 0xf6, 0xda, 0x13, 0x94, 0xbc, 0x23, 0xa5, 0xa1, 0x90, 0x51, + 0xac, 0x41, 0x7d, 0xeb, 0xdc, 0x25, 0x96, 0x74, 0xb4, 0x3c, 0xea, 0x55, 0xf8, 0x62, 0xee, 0xe3, 0xd6, 0x38, 0x2a, + 0xc7, 0x9c, 0x23, 0xd8, 0x93, 0x2a, 0x9d, 0x4c, 0x95, 0x03, 0xc0, 0x9a, 0x66, 0x11, 0x31, 0x48, 0xa9, 0x5d, 0x8e, + 0xbb, 0xf8, 0x16, 0x6c, 0x67, 0x31, 0xc8, 0xd2, 0xd7, 0x36, 0x19, 0x95, 0xce, 0x63, 0x27, 0xba, 0x1f, 0xbb, 0xda, + 0xc0, 0xc3, 0x60, 0x7b, 0xd6, 0x29, 0x57, 0x32, 0x56, 0x1c, 0x65, 0x57, 0x62, 0x6a, 0x79, 0xb6, 0x74, 0xbd, 0x45, + 0x54, 0xac, 0x95, 0x35, 0xbd, 0x0d, 0xd3, 0x53, 0xc1, 0x73, 0x3f, 0x3e, 0x61, 0x71, 0x64, 0xe4, 0x38, 0x93, 0x58, + 0xd5, 0x21, 0xcc, 0x4d, 0x3a, 0x82, 0x27, 0x48, 0x2d, 0x47, 0x32, 0x4f, 0x39, 0xa5, 0x50, 0xa1, 0xff, 0xa5, 0xf1, + 0x08, 0x55, 0x73, 0x75, 0xd3, 0x5b, 0x85, 0xef, 0x10, 0x84, 0xfe, 0x21, 0xba, 0x05, 0xe3, 0x82, 0xf7, 0xef, 0x25, + 0x22, 0xd5, 0x52, 0x28, 0x59, 0x5e, 0x5d, 0xd6, 0x98, 0xa1, 0xcd, 0x3b, 0x4a, 0xc9, 0x50, 0xa0, 0x0a, 0xd3, 0x17, + 0x7c, 0x6e, 0x10, 0x0e, 0xb9, 0x6b, 0x1d, 0x05, 0xb1, 0x22, 0xd8, 0x0d, 0x9d, 0x20, 0xa1, 0xae, 0x0a, 0xb1, 0x2f, + 0xc4, 0x1c, 0x9f, 0xcb, 0xac, 0xd0, 0x03, 0xfe, 0xe4, 0x37, 0xb1, 0xa4, 0xfe, 0x06, 0x46, 0xfe, 0x0d, 0xab, 0xb4, + 0xa1, 0x4f, 0xf9, 0x41, 0xec, 0x73, 0x21, 0x6f, 0x6a, 0xa6, 0xd9, 0x8e, 0xcb, 0x7e, 0xe6, 0xef, 0x4d, 0x78, 0xec, + 0x2d, 0xb1, 0xf3, 0x58, 0x50, 0xb9, 0x8c, 0x21, 0x06, 0xaa, 0x9b, 0xfc, 0x89, 0xd2, 0x3f, 0x9c, 0x4e, 0xfc, 0x66, + 0xbe, 0xb3, 0xb6, 0x3f, 0x5f, 0x85, 0x42, 0xec, 0x75, 0x86, 0x96, 0x30, 0x84, 0xf0, 0x64, 0x3e, 0xbb, 0x30, 0x27, + 0x21, 0x49, 0x45, 0x8b, 0x12, 0xce, 0x70, 0x7f, 0x03, 0x20, 0x03, 0x0d, 0x56, 0xa2, 0x54, 0xd4, 0x8b, 0x3d, 0x82, + 0x49, 0x3e, 0xdb, 0x7a, 0xd8, 0x8b, 0x3c, 0x5a, 0x48, 0xa3, 0x5c, 0xc1, 0x06, 0x30, 0xd5, 0x73, 0x1b, 0x89, 0xc5, + 0x48, 0x2f, 0x5a, 0x4b, 0xbe, 0xd4, 0x12, 0xea, 0x62, 0xe7, 0x61, 0xb0, 0xae, 0x1a, 0x54, 0x76, 0x1e, 0x0b, 0x66, + 0x3a, 0x07, 0x72, 0x5c, 0xa0, 0x51, 0x37, 0x26, 0xc7, 0x14, 0xb3, 0x6a, 0x85, 0x1f, 0xaa, 0x98, 0xb7, 0x74, 0x29, + 0xd8, 0xbc, 0x56, 0x77, 0xc7, 0xbb, 0x86, 0x09, 0x75, 0x68, 0x60, 0x96, 0x24, 0xa8, 0x61, 0x09, 0xeb, 0x0b, 0x3e, + 0x8f, 0xc1, 0x3c, 0x60, 0x9a, 0xb7, 0xd9, 0xed, 0x18, 0xf5, 0x5b, 0x35, 0x9f, 0x7a, 0xab, 0x3c, 0x6f, 0xb9, 0xc3, + 0x2b, 0x35, 0x37, 0xa7, 0xc5, 0x3c, 0x42, 0x44, 0xaf, 0xdb, 0x90, 0xf0, 0x9c, 0xb9, 0x97, 0xb8, 0x90, 0x78, 0xd2, + 0x67, 0x5e, 0x1f, 0x1f, 0x77, 0x22, 0xc7, 0xa8, 0xf4, 0xd6, 0x45, 0xc8, 0xec, 0x83, 0xb2, 0x72, 0x77, 0x78, 0x72, + 0xe9, 0xb4, 0x84, 0x4a, 0xd6, 0xf5, 0x9b, 0x4f, 0x13, 0xa8, 0xc2, 0x60, 0x86, 0xe2, 0x14, 0x9b, 0xea, 0xd1, 0x78, + 0x83, 0x79, 0x04, 0xe3, 0x22, 0x12, 0x6a, 0x30, 0x0f, 0x2e, 0xd1, 0x34, 0x12, 0x31, 0x67, 0xac, 0x6e, 0x07, 0xb0, + 0xe7, 0x4b, 0x4f, 0x31, 0x7b, 0x78, 0x6d, 0x2f, 0x99, 0xe3, 0xf6, 0x25, 0x70, 0x5b, 0xee, 0x4e, 0xb1, 0x9a, 0x3d, + 0x56, 0x49, 0x8d, 0x03, 0xd8, 0x48, 0xa3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, 0x76, 0x7f, 0x82, 0x27, 0x80, 0x63, 0x04, + 0x83, 0x13, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0xb1, 0xf2, 0xcd, 0x27, 0x81, 0x0d, 0x41, 0x64, 0x0a, 0x2b, 0x44, 0x4c, + 0x95, 0x21, 0xfc, 0xbc, 0x8b, 0xb3, 0xaf, 0x2e, 0x13, 0x4d, 0xb5, 0xd1, 0x08, 0xc5, 0x3c, 0xbc, 0x86, 0x9b, 0x79, + 0x60, 0xaa, 0xc7, 0x9a, 0x4e, 0x11, 0xd5, 0x4e, 0x62, 0x6a, 0xf5, 0xac, 0x63, 0xad, 0x5c, 0x6d, 0x8b, 0xc9, 0x27, + 0xea, 0x95, 0x3c, 0x40, 0x23, 0x9a, 0xc9, 0x84, 0x6f, 0x39, 0x33, 0x1f, 0xa6, 0xec, 0x11, 0x7e, 0x1d, 0xc3, 0x87, + 0xc7, 0x8d, 0xc0, 0x28, 0xcf, 0xc9, 0xce, 0x16, 0x32, 0x2e, 0x1c, 0x58, 0xfc, 0x69, 0xc8, 0x98, 0xfb, 0xa2, 0xe8, + 0xa9, 0x4c, 0x2f, 0x26, 0x2f, 0x7f, 0x56, 0xf3, 0x64, 0x1e, 0x08, 0x5b, 0xa3, 0x8a, 0xf4, 0x4b, 0xa3, 0xc5, 0x62, + 0x90, 0x7a, 0x18, 0xc6, 0x40, 0x8a, 0x85, 0x8a, 0x81, 0xa3, 0x4b, 0x75, 0xc0, 0xff, 0x4f, 0x41, 0x8f, 0x21, 0x7b, + 0x46, 0xdb, 0x6d, 0xce, 0xb7, 0xac, 0x27, 0x73, 0x63, 0xdf, 0xd9, 0x76, 0xf2, 0xc6, 0x03, 0x4e, 0x16, 0xfb, 0x85, + 0x59, 0xfc, 0x2e, 0x9f, 0x07, 0x4a, 0xec, 0x25, 0x41, 0x32, 0x0a, 0x90, 0x39, 0x9f, 0x85, 0x87, 0xd0, 0x6b, 0x5e, + 0x09, 0x51, 0xd0, 0x95, 0xe2, 0x4a, 0xa0, 0xf5, 0xe0, 0x34, 0x40, 0xa6, 0xc2, 0x15, 0x04, 0x32, 0x6f, 0x7e, 0x5c, + 0xee, 0x6e, 0x02, 0x69, 0x7b, 0x85, 0x0c, 0x66, 0x6e, 0xf5, 0x12, 0xa9, 0xf3, 0x81, 0x59, 0xbe, 0x64, 0x6f, 0x6c, + 0x59, 0xf7, 0xe0, 0x4c, 0x3f, 0x73, 0x74, 0x1a, 0xb2, 0xb2, 0x16, 0x0a, 0x9b, 0xec, 0xf4, 0x24, 0xaa, 0x2a, 0x45, + 0xf2, 0x8a, 0x72, 0x51, 0x50, 0x54, 0x08, 0xd3, 0xeb, 0x1f, 0x02, 0x42, 0x8e, 0x52, 0x06, 0xed, 0xb1, 0xe5, 0x2b, + 0x8c, 0x08, 0x81, 0x71, 0x21, 0x1a, 0x56, 0x90, 0x29, 0xec, 0xb2, 0x8a, 0x71, 0x9c, 0x9e, 0xa8, 0xba, 0x8b, 0x53, + 0x88, 0x3d, 0xef, 0x86, 0xcc, 0x12, 0x74, 0x6e, 0xb4, 0x35, 0xc6, 0x31, 0xf4, 0x33, 0xd1, 0x3f, 0x82, 0x1b, 0x9d, + 0xc3, 0x1a, 0x15, 0x9c, 0x1a, 0xfb, 0x9c, 0xc5, 0x3b, 0xbe, 0x0a, 0xf7, 0x7b, 0xda, 0x92, 0xde, 0x8e, 0x5d, 0x33, + 0x2b, 0x3f, 0x82, 0x2c, 0xa5, 0x2d, 0x43, 0x12, 0xd5, 0xb5, 0x97, 0x8e, 0x41, 0x53, 0x22, 0xb7, 0x9e, 0xcf, 0xc9, + 0xe8, 0x1b, 0x4c, 0x7e, 0xbc, 0x39, 0xdd, 0x97, 0x84, 0x0e, 0x56, 0x8b, 0x67, 0x2e, 0xbe, 0xc4, 0x26, 0xd0, 0x82, + 0x07, 0x00, 0xce, 0xdf, 0x89, 0xeb, 0xdf, 0x45, 0x0f, 0x0e, 0x63, 0x04, 0xb0, 0x10, 0x6f, 0xc5, 0xb0, 0xf2, 0x36, + 0xa2, 0xb4, 0x02, 0x20, 0xd7, 0xa6, 0x2a, 0xc0, 0x1b, 0x86, 0x6f, 0xb2, 0x64, 0x9f, 0xe3, 0x38, 0xdb, 0xb3, 0x42, + 0xe2, 0x1d, 0xfe, 0x59, 0x1f, 0x5e, 0x99, 0x70, 0x2e, 0xd8, 0x2d, 0x1d, 0xe7, 0x55, 0xdb, 0x88, 0xa4, 0xed, 0x62, + 0x10, 0xe3, 0x0c, 0x12, 0xa9, 0x0f, 0xd2, 0xf7, 0x57, 0x61, 0x21, 0x1a, 0x02, 0xef, 0x8b, 0x0a, 0xec, 0x75, 0x14, + 0x46, 0x93, 0xda, 0x23, 0x1a, 0x41, 0x4f, 0x57, 0x27, 0x24, 0x03, 0x95, 0x42, 0x6c, 0x98, 0x44, 0xfd, 0x4c, 0xb5, + 0xdd, 0x50, 0x7d, 0x53, 0xad, 0xa6, 0x50, 0xe3, 0x13, 0x30, 0x75, 0x28, 0x29, 0x18, 0x73, 0x6d, 0xd8, 0xa7, 0x8f, + 0x1d, 0x51, 0x6b, 0x0d, 0x4e, 0xef, 0x5f, 0x85, 0x81, 0x61, 0xb9, 0xd9, 0x7c, 0xf1, 0x15, 0x76, 0x9d, 0x73, 0x2f, + 0x50, 0x7d, 0x1f, 0xfd, 0x38, 0xae, 0x2e, 0xcb, 0xef, 0x7a, 0x37, 0xb5, 0x10, 0xef, 0xa9, 0xa3, 0x86, 0xfd, 0x94, + 0xc8, 0xf9, 0x2e, 0xc5, 0x7d, 0xdc, 0x51, 0x01, 0xf4, 0x79, 0xc8, 0x48, 0xab, 0x09, 0xc5, 0x05, 0x20, 0x5d, 0xc6, + 0x34, 0x2b, 0x0d, 0x54, 0xa8, 0xd9, 0x68, 0x2f, 0x23, 0xab, 0x0c, 0xc2, 0x41, 0xfb, 0xd5, 0x23, 0x28, 0x96, 0x55, + 0xba, 0xc9, 0x23, 0x80, 0xcd, 0xfa, 0x95, 0xdc, 0xfc, 0x17, 0x01, 0x1b, 0x0c, 0x0b, 0x36, 0x2f, 0xea, 0x25, 0xcf, + 0x79, 0x04, 0x98, 0xe4, 0x8c, 0xeb, 0x41, 0xb4, 0xfe, 0x6b, 0xd3, 0x7c, 0xb0, 0xe5, 0xde, 0x3b, 0x02, 0x49, 0xbd, + 0xac, 0x0d, 0xb0, 0xb2, 0x18, 0x52, 0xef, 0x39, 0x3f, 0x35, 0x32, 0x25, 0x20, 0x20, 0xfe, 0xc2, 0xd7, 0xf5, 0xeb, + 0xb0, 0x5e, 0xab, 0x74, 0xe7, 0x53, 0xd3, 0x5a, 0x15, 0x52, 0x9e, 0xcc, 0x5a, 0x45, 0x3e, 0x71, 0x55, 0x33, 0xc3, + 0xb4, 0x36, 0xaf, 0x4e, 0x4f, 0xfa, 0x0b, 0xca, 0x7d, 0x91, 0x33, 0x00, 0xe1, 0x35, 0x8f, 0x0f, 0x56, 0xef, 0x66, + 0xdf, 0x36, 0xae, 0x56, 0xb6, 0xfb, 0x17, 0x6d, 0x7c, 0x9a, 0xb1, 0x5b, 0xc3, 0x18, 0x54, 0xce, 0xcb, 0xc9, 0x6f, + 0x4a, 0x4a, 0x23, 0x2d, 0xa3, 0xcd, 0xb1, 0xcb, 0xa9, 0xf6, 0xe5, 0xea, 0xdd, 0x1a, 0x84, 0x15, 0x22, 0xb3, 0x07, + 0xcf, 0x08, 0x1f, 0x6f, 0xfd, 0x50, 0x08, 0x55, 0x69, 0xc7, 0x58, 0xde, 0x2c, 0x86, 0xa1, 0xf9, 0x5c, 0x8a, 0xcb, + 0x11, 0xe6, 0x5b, 0xe7, 0xa6, 0x29, 0x64, 0x6d, 0x22, 0xa9, 0xa3, 0xc0, 0xa4, 0xb8, 0x8c, 0x34, 0xe7, 0x5f, 0xc6, + 0x89, 0xe4, 0x5e, 0x29, 0x9f, 0xd4, 0x53, 0xea, 0x2d, 0xd8, 0x08, 0xc2, 0x9f, 0xd4, 0x2d, 0x7b, 0xa1, 0x41, 0xb3, + 0x4d, 0x92, 0xc1, 0xc9, 0xe7, 0x07, 0xbf, 0xc9, 0x5d, 0x7a, 0x0d, 0x91, 0x10, 0x4c, 0xf9, 0xdc, 0x36, 0xdd, 0x64, + 0xac, 0x04, 0xa4, 0xab, 0x1a, 0x6d, 0xd8, 0x4c, 0xd1, 0xf5, 0x79, 0x3f, 0xc8, 0xfb, 0xa1, 0x23, 0xb2, 0x18, 0x5b, + 0x94, 0xf0, 0x0b, 0x47, 0x62, 0x4e, 0xdd, 0x14, 0xa5, 0x35, 0xf4, 0xf6, 0x61, 0x76, 0xbd, 0xdb, 0x6b, 0xb9, 0x24, + 0x1d, 0x4e, 0x2b, 0xd2, 0x2c, 0x00, 0x21, 0xea, 0x14, 0xaa, 0x09, 0x38, 0x50, 0xe6, 0xe5, 0x2f, 0x91, 0x40, 0xca, + 0x0f, 0x70, 0x21, 0xbd, 0xcc, 0xe7, 0x28, 0x82, 0xf3, 0x50, 0xa5, 0x05, 0x17, 0x66, 0x8f, 0x81, 0xdf, 0x75, 0x4d, + 0xbf, 0x05, 0x7f, 0x66, 0x8a, 0x97, 0xc2, 0xc9, 0xf3, 0x72, 0xaf, 0xe1, 0x21, 0x06, 0x1f, 0x9c, 0x55, 0x5f, 0xf4, + 0x72, 0x1a, 0xd7, 0x19, 0xd8, 0xbd, 0xec, 0x81, 0xf9, 0x30, 0xf3, 0x56, 0x00, 0x99, 0xd3, 0xb8, 0xaa, 0xc0, 0x73, + 0x5e, 0xcd, 0xb5, 0x46, 0x39, 0xbd, 0x5f, 0x88, 0x31, 0x0d, 0xa5, 0x62, 0x6b, 0x98, 0x8a, 0x03, 0xc5, 0x45, 0xc9, + 0xbd, 0xac, 0x29, 0x4e, 0x9b, 0xf3, 0x86, 0xa4, 0x7c, 0x47, 0x03, 0x6d, 0x5e, 0xcd, 0x93, 0x7b, 0xfc, 0x8b, 0x7a, + 0xde, 0x7b, 0x1c, 0xbe, 0xbc, 0x99, 0x16, 0x83, 0x9c, 0x0f, 0x90, 0x53, 0x03, 0xc7, 0x6f, 0x4d, 0xf8, 0x63, 0x6e, + 0x69, 0x35, 0xc6, 0x1a, 0x9a, 0xf8, 0xc8, 0x56, 0x00, 0x29, 0xe3, 0x4d, 0x52, 0x2b, 0x7c, 0xa9, 0x43, 0xb1, 0x98, + 0x2c, 0xbf, 0x0b, 0x34, 0xb8, 0xc1, 0xd2, 0x33, 0x1c, 0x52, 0xd4, 0x8b, 0xa2, 0xa5, 0x3f, 0x51, 0x7e, 0x37, 0xee, + 0x3f, 0xed, 0x77, 0x4b, 0x60, 0xee, 0x71, 0x5b, 0x69, 0xb1, 0x91, 0xd0, 0x4d, 0x5b, 0xc9, 0xab, 0x0d, 0x55, 0x77, + 0xe7, 0xae, 0x89, 0xac, 0xe6, 0xba, 0x46, 0xa5, 0x06, 0x61, 0xfc, 0x5e, 0xbb, 0xb1, 0xcd, 0xb4, 0xb5, 0xd2, 0x41, + 0x9f, 0x21, 0xe9, 0xa5, 0xa2, 0xdd, 0xa0, 0x63, 0x4f, 0x4f, 0x68, 0xc7, 0x12, 0xf1, 0x1e, 0x21, 0x71, 0x86, 0x85, + 0x62, 0x5c, 0x98, 0x47, 0xf4, 0x56, 0x7a, 0xc5, 0x61, 0x63, 0xd2, 0xd3, 0x6c, 0x2c, 0xcb, 0x2b, 0x9c, 0xba, 0x2f, + 0x52, 0x40, 0xf1, 0xcf, 0xd1, 0x01, 0xfc, 0x33, 0x5d, 0x83, 0xd6, 0xe0, 0x54, 0x2e, 0x77, 0xf5, 0xba, 0xc4, 0x87, + 0x76, 0xc7, 0x13, 0x09, 0xdd, 0x0e, 0xd1, 0xf8, 0x86, 0xae, 0x70, 0xa3, 0x78, 0x95, 0x51, 0xc7, 0xca, 0xb4, 0x66, + 0xe4, 0xc3, 0x8a, 0xec, 0x5f, 0x20, 0xf2, 0xaa, 0x10, 0x85, 0x20, 0xad, 0x45, 0x34, 0x31, 0xd9, 0x7f, 0x9a, 0xe4, + 0x35, 0xa5, 0x99, 0x6d, 0xf4, 0xa7, 0x4d, 0x4d, 0xdb, 0x11, 0x70, 0xb7, 0x73, 0x13, 0x5d, 0xec, 0xcc, 0xa5, 0xb0, + 0x57, 0x50, 0xda, 0x42, 0xa2, 0x90, 0x75, 0x21, 0x5a, 0x6e, 0x97, 0x5a, 0xf9, 0xad, 0xf2, 0x14, 0x00, 0x10, 0x05, + 0x4d, 0xe8, 0xca, 0x6e, 0xb6, 0x77, 0xc5, 0xd2, 0xd5, 0x43, 0x04, 0x1f, 0x90, 0x12, 0x1c, 0xa0, 0x8b, 0x3c, 0xae, + 0xbb, 0x77, 0xb3, 0x8d, 0xc8, 0x46, 0xb6, 0x68, 0xad, 0x0e, 0xbc, 0x5c, 0xbf, 0xde, 0xe5, 0xff, 0xdf, 0xf7, 0xd8, + 0xfc, 0x05, 0x1c, 0x50, 0xb8, 0x0f, 0x1f, 0x4c, 0x0b, 0x4f, 0x1c, 0x6a, 0xfd, 0xd7, 0x86, 0x12, 0x05, 0x4f, 0xa2, + 0xf1, 0x73, 0xcd, 0x3a, 0x3d, 0x62, 0x14, 0x89, 0x8f, 0xd4, 0x03, 0x89, 0x5a, 0xad, 0x35, 0x3d, 0xae, 0xae, 0xd3, + 0xfa, 0x2f, 0x86, 0x7d, 0xb5, 0xab, 0x18, 0xe2, 0x4e, 0x2f, 0x6e, 0x23, 0x89, 0x42, 0xa1, 0xcf, 0x26, 0x3e, 0x61, + 0xa0, 0xb2, 0xe6, 0x0b, 0x0f, 0x29, 0x96, 0x97, 0xcb, 0xd0, 0x74, 0xa1, 0xc5, 0x6d, 0x81, 0x1a, 0x0f, 0x06, 0x3d, + 0x6b, 0x97, 0x20, 0xcd, 0xae, 0xff, 0x8c, 0x33, 0x9c, 0xb4, 0xd2, 0xea, 0xf3, 0x62, 0x08, 0xd9, 0xc7, 0x3b, 0xa9, + 0x55, 0xa1, 0x8c, 0xb3, 0xc7, 0xaa, 0xac, 0x0d, 0xbf, 0x86, 0x6a, 0x74, 0x8e, 0x55, 0xd4, 0xa6, 0xae, 0xad, 0x76, + 0xc6, 0xa0, 0x54, 0xc7, 0x81, 0x60, 0xd3, 0xd2, 0xc5, 0x20, 0x2d, 0xe2, 0x40, 0x1f, 0x48, 0xf2, 0xb8, 0xa4, 0xf9, + 0x2e, 0x15, 0xf9, 0x72, 0xd1, 0x10, 0x9a, 0xeb, 0xaa, 0xc2, 0x36, 0xe5, 0xb1, 0xa6, 0xa8, 0x8b, 0x9b, 0x1d, 0xeb, + 0xf0, 0x1a, 0x30, 0x8c, 0x17, 0xe0, 0x4a, 0x80, 0x93, 0xf2, 0xd5, 0xa7, 0x06, 0x3b, 0x66, 0x0a, 0x3d, 0x17, 0xfe, + 0xf8, 0xb4, 0x26, 0x13, 0x2b, 0x5e, 0xb5, 0x42, 0x89, 0xab, 0xc4, 0x53, 0x1d, 0x96, 0x4b, 0x37, 0xb1, 0x46, 0xc8, + 0x67, 0xe2, 0xaf, 0xd1, 0x22, 0xec, 0x0d, 0x64, 0x0d, 0xcb, 0x64, 0x32, 0x25, 0x24, 0x4c, 0x90, 0x73, 0xc0, 0x98, + 0x3a, 0xc9, 0x17, 0x97, 0xfe, 0x2c, 0xdc, 0xa1, 0xcf, 0xa6, 0xb5, 0x74, 0xdf, 0x49, 0x85, 0xee, 0x7b, 0x32, 0xe9, + 0x50, 0x4f, 0x1c, 0xc4, 0xcc, 0x14, 0x5c, 0x1d, 0xb7, 0xd8, 0x68, 0x30, 0x38, 0x3a, 0x3b, 0xd6, 0x62, 0x8b, 0x21, + 0x61, 0x03, 0xe6, 0x13, 0xb5, 0x7b, 0x1f, 0x3e, 0x93, 0xf4, 0xcb, 0xd7, 0x4b, 0x84, 0x90, 0xc1, 0xee, 0x44, 0xa9, + 0x19, 0x33, 0xd4, 0x34, 0x33, 0x05, 0xcd, 0xfc, 0xe8, 0x24, 0xd2, 0x1d, 0xde, 0x4c, 0xe8, 0x95, 0x06, 0xb7, 0xee, + 0xa9, 0xbe, 0x5c, 0x91, 0x46, 0x68, 0x8d, 0x39, 0x50, 0xf9, 0x70, 0x5a, 0x17, 0xd7, 0x2b, 0xdb, 0xf5, 0x03, 0x7e, + 0x68, 0xb5, 0x3b, 0x78, 0xd2, 0x20, 0xe3, 0x43, 0x93, 0xe4, 0xbc, 0x06, 0x2b, 0xc0, 0x43, 0x83, 0xa5, 0x68, 0x89, + 0x37, 0x45, 0xcf, 0x26, 0xfb, 0x68, 0xb4, 0x18, 0x8b, 0xb5, 0xfc, 0xfd, 0x9d, 0xa7, 0x7d, 0x21, 0xd5, 0x28, 0x7b, + 0x18, 0xc8, 0xee, 0x13, 0x28, 0x99, 0xa3, 0xd0, 0x9d, 0xcd, 0x50, 0xc5, 0x68, 0x9e, 0x00, 0x63, 0x05, 0xbf, 0xb8, + 0x66, 0x31, 0x9d, 0x33, 0xc7, 0xf9, 0x1a, 0x4e, 0x12, 0x47, 0x4d, 0x9c, 0x5b, 0x4f, 0x04, 0xe5, 0xd5, 0x62, 0x49, + 0xf4, 0x92, 0xa2, 0xa3, 0x8e, 0xd5, 0xf8, 0x8f, 0x89, 0xf5, 0xd4, 0x9c, 0x8e, 0x76, 0x3e, 0x8d, 0x15, 0x54, 0xd2, + 0x02, 0x6a, 0x72, 0x2c, 0xfb, 0x12, 0x0a, 0xdc, 0xff, 0xa7, 0x9a, 0x4a, 0xc5, 0xcb, 0x74, 0xb8, 0x59, 0x73, 0x60, + 0x03, 0xea, 0x08, 0xa0, 0xba, 0x35, 0x23, 0xa3, 0x6f, 0x7c, 0x7f, 0xa1, 0xee, 0xc6, 0x98, 0x03, 0x1d, 0xb4, 0x2d, + 0xfa, 0x1b, 0xe8, 0x91, 0x6c, 0x97, 0x83, 0x78, 0x83, 0xf2, 0x16, 0x4f, 0x02, 0x2f, 0x11, 0x4d, 0xd4, 0x6c, 0xac, + 0xe3, 0xb7, 0xd9, 0x3a, 0x0e, 0xde, 0x3a, 0x00, 0xbf, 0xb0, 0x6c, 0xc6, 0x99, 0x8d, 0xfa, 0x5e, 0x41, 0x0c, 0xf8, + 0x51, 0xec, 0x6c, 0xfc, 0xe9, 0x84, 0xda, 0x93, 0x1d, 0x4e, 0x39, 0x36, 0xca, 0x39, 0x61, 0x7b, 0xa6, 0x12, 0x00, + 0x29, 0x74, 0x51, 0x67, 0xc5, 0xc9, 0x4f, 0xbc, 0x15, 0x3b, 0xe2, 0x31, 0x12, 0x57, 0x88, 0x84, 0xe0, 0x82, 0x2a, + 0xb6, 0x6a, 0xb5, 0xea, 0xdc, 0xfc, 0x4c, 0x86, 0x4d, 0xc6, 0x04, 0x8b, 0x05, 0xbd, 0x7f, 0x46, 0x24, 0x84, 0x69, + 0x43, 0x48, 0x96, 0x26, 0x90, 0x1a, 0x8f, 0x5b, 0xf3, 0x24, 0x6d, 0xba, 0x04, 0x7e, 0x5d, 0x5d, 0x50, 0xa8, 0xb4, + 0xa2, 0xe0, 0xe7, 0x35, 0x1c, 0x7b, 0x8d, 0x30, 0xf6, 0x0c, 0x40, 0x1f, 0x49, 0xa0, 0xcc, 0x48, 0x61, 0x31, 0xb5, + 0xa7, 0x38, 0x82, 0x5a, 0x79, 0xd9, 0xd9, 0xae, 0xef, 0xaa, 0x1e, 0x26, 0xf0, 0x57, 0xcc, 0x81, 0x17, 0x50, 0xe6, + 0x48, 0x73, 0xba, 0x5f, 0xfe, 0x01, 0x20, 0xdc, 0x78, 0xfe, 0x8a, 0x08, 0xe9, 0x50, 0xed, 0x03, 0x74, 0x8d, 0xca, + 0x5e, 0xc5, 0x8c, 0x72, 0xb0, 0xaa, 0x1b, 0xb3, 0x4d, 0xe2, 0xeb, 0xf8, 0xba, 0x06, 0xe6, 0xf7, 0xc4, 0xcf, 0x40, + 0xee, 0x61, 0x64, 0xd9, 0x3a, 0x99, 0xd2, 0x5b, 0x6d, 0xb7, 0xc1, 0x95, 0x12, 0x69, 0xc3, 0x64, 0x59, 0x93, 0x1a, + 0xe8, 0x69, 0x05, 0x16, 0xc1, 0xbf, 0xd1, 0x3b, 0xf6, 0x8d, 0x30, 0x9d, 0x63, 0xdb, 0x35, 0x9c, 0x4d, 0x4a, 0x8f, + 0x73, 0x95, 0x4e, 0x4a, 0x48, 0x4d, 0xc5, 0x97, 0xcc, 0xb8, 0x52, 0x1e, 0x13, 0xce, 0x71, 0x35, 0x18, 0x32, 0x0c, + 0xa9, 0xa0, 0xfe, 0x36, 0x59, 0x4a, 0x53, 0x72, 0x96, 0x08, 0x9f, 0x62, 0xf9, 0x33, 0xaa, 0x25, 0xb7, 0x6d, 0xe0, + 0x98, 0xf6, 0x9a, 0xe5, 0x62, 0xc1, 0x8b, 0xf9, 0x13, 0x04, 0x03, 0x1f, 0x5f, 0x51, 0x4b, 0x9e, 0xcb, 0x83, 0x9d, + 0xc4, 0x48, 0xc6, 0xbf, 0x67, 0xda, 0x0d, 0x91, 0xcb, 0x52, 0x85, 0xc8, 0x4c, 0x7f, 0xe6, 0x61, 0xf5, 0x61, 0x39, + 0xd8, 0x4c, 0x11, 0xd3, 0xbf, 0xdf, 0x3f, 0x35, 0x18, 0xc1, 0x0f, 0x3d, 0x39, 0x6d, 0x46, 0x08, 0x7a, 0x16, 0x1d, + 0x55, 0xd8, 0x23, 0x72, 0xa2, 0x00, 0xc9, 0xb2, 0x47, 0xb1, 0xbe, 0xa4, 0x8e, 0x8e, 0xb1, 0x1e, 0x87, 0x13, 0x56, + 0xf6, 0x1c, 0xc9, 0x73, 0x50, 0x57, 0xcd, 0x92, 0xea, 0xd8, 0x63, 0xc0, 0xea, 0x6f, 0x38, 0x95, 0xae, 0xb9, 0xbb, + 0x41, 0x04, 0x5b, 0x22, 0xed, 0x38, 0x72, 0x09, 0xa0, 0x13, 0x4c, 0x61, 0xc8, 0x79, 0x3e, 0x1e, 0xaa, 0x97, 0xbf, + 0x25, 0x3a, 0x2a, 0x71, 0x43, 0x89, 0x74, 0x4b, 0x94, 0x4e, 0x2f, 0x63, 0xcf, 0xee, 0x96, 0x4a, 0xff, 0xc0, 0x03, + 0x4c, 0xd7, 0x29, 0x04, 0x39, 0xe4, 0x24, 0xe1, 0xad, 0x4c, 0x85, 0xb3, 0x7c, 0xd3, 0x1d, 0xdc, 0xb3, 0x88, 0xf1, + 0x10, 0xee, 0xed, 0x0e, 0xb8, 0x0d, 0x2c, 0x46, 0x8d, 0x66, 0x32, 0x70, 0x31, 0xc5, 0x18, 0x8e, 0x38, 0xa4, 0x9c, + 0x23, 0x96, 0x95, 0x3d, 0xee, 0xe6, 0xec, 0x94, 0x41, 0xb4, 0x88, 0x2e, 0x43, 0x95, 0x36, 0x49, 0x8f, 0x1d, 0xb2, + 0x90, 0xf6, 0x29, 0x9e, 0x11, 0xb6, 0x51, 0xd5, 0x69, 0xa2, 0xef, 0x9e, 0x82, 0xe3, 0x19, 0x3a, 0xc3, 0xae, 0x3d, + 0x3f, 0x51, 0xd8, 0x1b, 0x86, 0x50, 0x7e, 0xc9, 0xaf, 0x32, 0x7f, 0x5d, 0x4d, 0x01, 0xac, 0xd8, 0x86, 0xf9, 0x84, + 0x20, 0xce, 0x5c, 0x71, 0x58, 0xe7, 0xdf, 0x6c, 0x66, 0x2b, 0x37, 0xd6, 0xf0, 0x42, 0xa7, 0x14, 0x6e, 0x1b, 0xfd, + 0x1c, 0xe8, 0xec, 0x8a, 0x84, 0x1f, 0x3d, 0xc7, 0x01, 0x64, 0x23, 0x95, 0x64, 0xae, 0xb8, 0xa7, 0xf6, 0xb7, 0x20, + 0xae, 0x1e, 0xc8, 0xc9, 0xa3, 0x17, 0x24, 0xe8, 0x25, 0xf4, 0xe7, 0xf3, 0xe8, 0x5c, 0xa2, 0x61, 0x6f, 0x94, 0x4f, + 0xde, 0x9f, 0xb1, 0x98, 0x5b, 0xa4, 0xc3, 0xb4, 0x94, 0xbe, 0x87, 0xc9, 0x1c, 0x27, 0x14, 0x49, 0xd5, 0x37, 0x8c, + 0x24, 0x78, 0xf1, 0x4c, 0xa2, 0x73, 0x21, 0x37, 0xe7, 0x34, 0x62, 0xb9, 0x67, 0x95, 0xd5, 0x6b, 0x47, 0x51, 0xde, + 0x71, 0x35, 0x4b, 0xba, 0x49, 0xcd, 0x52, 0xc7, 0x56, 0x15, 0x66, 0x34, 0x32, 0xbe, 0x70, 0xab, 0x17, 0x49, 0x39, + 0x64, 0x83, 0x94, 0x0d, 0x6c, 0x1a, 0x93, 0x85, 0x51, 0x73, 0xb3, 0xf3, 0x45, 0xdc, 0xb1, 0x5d, 0x05, 0xad, 0x52, + 0x25, 0xe9, 0xa0, 0x7e, 0x50, 0xed, 0xfd, 0x40, 0xdb, 0x26, 0xc9, 0xdf, 0xd5, 0xac, 0x8b, 0xef, 0xa1, 0xab, 0x9c, + 0x56, 0x3b, 0x10, 0xe6, 0xa3, 0xa2, 0x1d, 0x03, 0x03, 0x45, 0xf1, 0x60, 0x7b, 0x0a, 0x5d, 0xde, 0x6f, 0x8d, 0x4a, + 0x26, 0x9d, 0x02, 0x9b, 0xb2, 0x2a, 0x98, 0xa6, 0x0a, 0xab, 0xf3, 0x1a, 0xb3, 0xbf, 0x3d, 0x2e, 0x3b, 0x09, 0xec, + 0x25, 0xe3, 0x1e, 0x9f, 0x82, 0xdf, 0x50, 0xbc, 0xc6, 0x1a, 0x72, 0x71, 0x1a, 0x98, 0x49, 0x98, 0x45, 0x69, 0xfd, + 0x76, 0xad, 0x7b, 0xfb, 0xb7, 0x5d, 0x3f, 0xa4, 0xf0, 0x81, 0x1e, 0x27, 0x46, 0xcd, 0xfc, 0xa3, 0xfc, 0x5a, 0x4a, + 0x7c, 0xe9, 0xeb, 0x96, 0xbb, 0xbf, 0x52, 0x27, 0xb1, 0x86, 0x39, 0x0c, 0xad, 0xd8, 0x1a, 0xc9, 0x7e, 0x41, 0x4c, + 0x6f, 0xd7, 0x3b, 0x49, 0xc4, 0x80, 0x73, 0x3d, 0x47, 0x96, 0xf9, 0xcc, 0x15, 0xf4, 0x4c, 0x22, 0x34, 0x4c, 0x57, + 0x33, 0x8e, 0x5a, 0x86, 0x5a, 0x4c, 0x1d, 0xc3, 0x1f, 0x1e, 0x32, 0x19, 0x3b, 0x94, 0xd1, 0x8f, 0x75, 0x7c, 0x9b, + 0x1a, 0xcb, 0x86, 0xaf, 0xa1, 0xdc, 0xb3, 0xcb, 0x3f, 0x3a, 0xd4, 0xe6, 0x71, 0x8f, 0xc7, 0xea, 0x20, 0x5e, 0xad, + 0xf6, 0xec, 0x0d, 0x8a, 0x58, 0x9f, 0xd6, 0xb0, 0x3a, 0xb8, 0xcc, 0xe6, 0xfc, 0x1c, 0x6c, 0x12, 0x5c, 0xbd, 0xd5, + 0xcd, 0x2f, 0x43, 0x74, 0x6b, 0x5c, 0x43, 0x72, 0x7e, 0x76, 0xbe, 0x87, 0x8f, 0xf8, 0xc9, 0xcf, 0xb4, 0x64, 0x9e, + 0xad, 0x13, 0xd8, 0x64, 0xd9, 0xb5, 0x65, 0x7e, 0x94, 0x3b, 0xbc, 0x2f, 0xfe, 0x67, 0x7d, 0x61, 0x03, 0x04, 0x84, + 0xf3, 0x4b, 0xfa, 0xc5, 0xe1, 0x39, 0xdb, 0x20, 0x76, 0xbe, 0xf9, 0xbe, 0x48, 0x73, 0x95, 0x06, 0x77, 0xfe, 0xd8, + 0x19, 0x82, 0x63, 0x04, 0xd8, 0x8b, 0xa0, 0x11, 0x21, 0x99, 0xde, 0x91, 0x52, 0x74, 0xb3, 0xc6, 0x69, 0x25, 0x65, + 0x2d, 0xdc, 0x57, 0xda, 0xd4, 0x5d, 0xb9, 0xbb, 0xa8, 0x88, 0xd9, 0xa5, 0x09, 0x0e, 0x05, 0x16, 0x23, 0x93, 0xb2, + 0x24, 0x85, 0xa6, 0xbc, 0xf8, 0x47, 0x82, 0x1d, 0x01, 0x93, 0x6b, 0xb4, 0x0a, 0xc1, 0x38, 0x9f, 0x77, 0x56, 0xa5, + 0xa7, 0x91, 0x21, 0xa8, 0x1e, 0x79, 0x65, 0x4b, 0x35, 0x8b, 0xa6, 0xa6, 0x7c, 0x97, 0x5a, 0x37, 0x62, 0xd8, 0x7b, + 0xd5, 0x72, 0x82, 0xbc, 0xab, 0xc4, 0xc9, 0x4d, 0x0e, 0xe3, 0x92, 0xf9, 0x1a, 0x41, 0x89, 0x34, 0xb3, 0x77, 0x09, + 0x93, 0x4d, 0xa6, 0x9c, 0xb3, 0x60, 0x5b, 0xc7, 0x20, 0x91, 0x38, 0x96, 0x1d, 0x12, 0x72, 0x95, 0xf6, 0x4d, 0x96, + 0xa2, 0x3a, 0x73, 0x2a, 0x43, 0x3f, 0xed, 0x78, 0x39, 0x47, 0x4c, 0xc7, 0xd9, 0x22, 0x1d, 0x23, 0x06, 0x10, 0xc6, + 0x8c, 0x27, 0x48, 0xd5, 0xbc, 0x94, 0xd1, 0xea, 0xe2, 0x19, 0xae, 0x51, 0x7b, 0x10, 0x98, 0xe8, 0x18, 0xc4, 0xbe, + 0x4e, 0x68, 0x9c, 0x88, 0xe6, 0x44, 0x79, 0xaf, 0xb5, 0xb0, 0xdd, 0x37, 0xb4, 0x2e, 0x99, 0xc2, 0xa5, 0x14, 0x48, + 0x2c, 0xf3, 0xeb, 0x40, 0xf2, 0x42, 0xd3, 0x58, 0xd1, 0x6a, 0x09, 0xc0, 0xd4, 0x16, 0xcf, 0xd3, 0xb7, 0x7c, 0x33, + 0xab, 0xc7, 0xec, 0x33, 0xba, 0x05, 0xb8, 0xf6, 0x29, 0x65, 0x5c, 0x0f, 0x1e, 0x7b, 0xa0, 0x40, 0x03, 0xf4, 0x94, + 0x73, 0xb7, 0xf8, 0x2b, 0xdb, 0x10, 0xaf, 0x43, 0x37, 0xa8, 0x65, 0x89, 0x3e, 0xe7, 0xd7, 0xe2, 0xe2, 0x3f, 0xe5, + 0x2e, 0x08, 0x8c, 0x5c, 0x7c, 0x52, 0xd0, 0xc3, 0x69, 0xa2, 0xcb, 0x84, 0xc7, 0x7b, 0xd4, 0x69, 0x0a, 0xca, 0x0d, + 0xcc, 0xe2, 0x26, 0x8b, 0x26, 0xdd, 0x5d, 0xdb, 0xea, 0xde, 0x1d, 0x8e, 0x35, 0x37, 0x75, 0x88, 0x3d, 0x75, 0x6f, + 0x56, 0x4d, 0x71, 0xf1, 0x6d, 0xdb, 0x64, 0x1a, 0xb6, 0x36, 0x8a, 0x4a, 0x9a, 0xe6, 0x2d, 0x6b, 0x7f, 0x91, 0xed, + 0x34, 0xc0, 0xdb, 0x85, 0x44, 0xd7, 0x7c, 0xb4, 0x04, 0xb1, 0xa5, 0xfc, 0x78, 0x31, 0xe5, 0xb1, 0xa2, 0xc5, 0x19, + 0xd6, 0x4d, 0xaa, 0x4c, 0xf2, 0x0c, 0x1d, 0x4d, 0xa8, 0xf3, 0x7d, 0x1c, 0x56, 0x8d, 0x46, 0xff, 0xbc, 0x4e, 0xcd, + 0x08, 0x93, 0xd0, 0xe8, 0x44, 0x38, 0x73, 0x18, 0x97, 0xc6, 0x88, 0x97, 0x5e, 0x7e, 0xcc, 0x3f, 0x98, 0x53, 0x14, + 0x58, 0x4f, 0x70, 0x5e, 0x0f, 0x6d, 0xe6, 0xc4, 0x21, 0xd0, 0x73, 0x63, 0x94, 0xf5, 0x25, 0xfd, 0xcc, 0x1b, 0x8d, + 0x7d, 0x28, 0xb9, 0x20, 0x08, 0x15, 0x9e, 0x73, 0x1c, 0x32, 0xcc, 0x40, 0x5f, 0x37, 0xd9, 0x02, 0x3f, 0x6b, 0x73, + 0x1e, 0xf6, 0x45, 0xac, 0x2d, 0x47, 0x17, 0x83, 0xaf, 0x9e, 0xd7, 0x31, 0x3f, 0x90, 0xbf, 0x5d, 0x2b, 0xe3, 0x18, + 0x95, 0x68, 0x10, 0xbb, 0x22, 0x6d, 0x0a, 0x80, 0xa8, 0xd4, 0x39, 0x0e, 0xa2, 0x02, 0xc6, 0xda, 0x0f, 0x94, 0x26, + 0x94, 0x91, 0x02, 0x58, 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x23, 0xd9, 0x35, 0xab, 0x8f, 0x91, 0xc5, 0x79, 0xb4, 0xbb, + 0x9a, 0x38, 0x2d, 0xba, 0x7b, 0x71, 0x51, 0x26, 0xc6, 0x3d, 0x2a, 0xda, 0x92, 0xc6, 0xad, 0x01, 0x73, 0x56, 0x74, + 0x6b, 0x32, 0x95, 0xab, 0x3b, 0x76, 0x96, 0xe0, 0xf4, 0xd6, 0x15, 0x58, 0xeb, 0x0e, 0xe6, 0xeb, 0x74, 0x56, 0xdc, + 0x7f, 0xa2, 0x20, 0x4d, 0x23, 0xb0, 0x66, 0x13, 0xa4, 0xfa, 0xd1, 0x92, 0x33, 0x0b, 0x58, 0xa5, 0x49, 0x69, 0x69, + 0x05, 0x0c, 0x3e, 0xdb, 0x88, 0x37, 0x6c, 0xcf, 0x9a, 0x0e, 0xab, 0xd1, 0xf7, 0xbe, 0x53, 0x93, 0xda, 0x23, 0xd3, + 0xdd, 0xf6, 0xe6, 0x14, 0x42, 0xf4, 0x85, 0x29, 0xcd, 0x14, 0x01, 0x70, 0xfe, 0xd3, 0x13, 0xc0, 0xed, 0xdb, 0x83, + 0x60, 0xa9, 0xe4, 0xb9, 0xda, 0x9c, 0xb0, 0x03, 0x22, 0x5b, 0xce, 0x75, 0x47, 0x42, 0x0c, 0x8e, 0x39, 0xa3, 0xa2, + 0x17, 0x24, 0x71, 0x06, 0xad, 0x6c, 0x75, 0x0d, 0xf8, 0xad, 0xc3, 0x81, 0x09, 0x51, 0x8e, 0x60, 0xf0, 0x8e, 0x31, + 0x6c, 0x66, 0x72, 0x9b, 0xd1, 0x40, 0x34, 0x54, 0x43, 0x96, 0x2f, 0x7b, 0xb1, 0x3d, 0xda, 0xd1, 0x7c, 0x60, 0xc9, + 0xfc, 0xe6, 0x13, 0xe1, 0x3e, 0xb6, 0x7b, 0xd8, 0xab, 0xef, 0x85, 0x49, 0x75, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, + 0xb8, 0xae, 0x5e, 0x9a, 0xbd, 0xe9, 0x1f, 0xce, 0xc6, 0x22, 0x07, 0x59, 0x05, 0xfd, 0x79, 0x30, 0x0f, 0x04, 0xd5, + 0xd4, 0x65, 0xb2, 0x08, 0x70, 0xa9, 0x11, 0xa5, 0xd7, 0x3a, 0x23, 0xb0, 0x0d, 0x8c, 0xeb, 0xb1, 0xb9, 0xc2, 0xd3, + 0xf3, 0x59, 0x12, 0x0d, 0x72, 0x28, 0x15, 0x7a, 0xcd, 0xe7, 0xa3, 0x0f, 0x4a, 0xfe, 0xeb, 0xf2, 0xb4, 0xfe, 0x4b, + 0xca, 0x19, 0xa8, 0xa6, 0x9d, 0xca, 0x3f, 0x96, 0x75, 0x10, 0x6f, 0x5b, 0xd7, 0x77, 0xae, 0xe7, 0x3f, 0x4c, 0x48, + 0xa6, 0xce, 0x6d, 0xe8, 0x2c, 0x26, 0x7d, 0xbf, 0x4b, 0xb4, 0x71, 0xb6, 0x22, 0x25, 0x06, 0xaa, 0xf6, 0x05, 0xd9, + 0xa4, 0xde, 0x24, 0xb5, 0xba, 0xf1, 0x91, 0xb6, 0xc8, 0x0a, 0x6e, 0x1a, 0xb2, 0x81, 0xfa, 0x69, 0xef, 0x8e, 0xdd, + 0xbe, 0x3f, 0x99, 0xbb, 0xaf, 0xdd, 0xe6, 0xdf, 0x28, 0xbb, 0xfd, 0xdc, 0x1b, 0x69, 0x36, 0x14, 0x3d, 0x6f, 0xbc, + 0x6c, 0x4b, 0xc6, 0xc1, 0x5b, 0x33, 0x03, 0xc1, 0x61, 0x4e, 0x3e, 0xd6, 0x79, 0x06, 0x24, 0x2d, 0xb3, 0x68, 0x03, + 0x72, 0x8d, 0x4b, 0x1c, 0x50, 0x55, 0xb0, 0xf3, 0x99, 0xa9, 0x36, 0x27, 0x12, 0xd7, 0x3b, 0x59, 0x1e, 0x76, 0x74, + 0x71, 0x87, 0x69, 0x99, 0x6e, 0xe2, 0xc2, 0xd1, 0x0d, 0x3b, 0x25, 0x4d, 0x36, 0x4f, 0x34, 0x9b, 0x4e, 0xbf, 0x4b, + 0xfa, 0xe6, 0x30, 0x90, 0x36, 0x67, 0x3e, 0xdc, 0x74, 0x1e, 0xba, 0xd0, 0x15, 0xee, 0x26, 0x15, 0xa9, 0xb4, 0x9c, + 0x40, 0x55, 0xc7, 0xb6, 0x52, 0x50, 0x94, 0xe2, 0xdf, 0x7c, 0x6f, 0x78, 0x58, 0x15, 0x7c, 0x13, 0x13, 0x49, 0xcc, + 0xd6, 0xaa, 0xf1, 0x85, 0x38, 0xfd, 0x41, 0x99, 0xb7, 0xf3, 0xf9, 0x24, 0x8e, 0x21, 0xff, 0xbd, 0x6a, 0x2a, 0x52, + 0x40, 0x93, 0x38, 0x48, 0xc8, 0xcc, 0xd8, 0x29, 0xfa, 0x78, 0x42, 0xe8, 0x4c, 0x52, 0x3e, 0xb8, 0xcc, 0xc1, 0x2f, + 0xbb, 0x3d, 0xba, 0xad, 0x72, 0x9b, 0x5b, 0x81, 0x3d, 0x55, 0x53, 0xa4, 0x25, 0x85, 0x4c, 0xba, 0x3a, 0x75, 0x6c, + 0x9c, 0xf5, 0xb5, 0xfb, 0x6f, 0x55, 0xc9, 0x9e, 0xbf, 0x3e, 0xe7, 0x6b, 0xe3, 0x90, 0x26, 0x15, 0xff, 0x8e, 0xdb, + 0x75, 0x77, 0x03, 0xc0, 0x9f, 0xb5, 0x4a, 0x89, 0x97, 0xd2, 0x35, 0xdd, 0x57, 0xd1, 0x6e, 0x78, 0xb6, 0xea, 0x27, + 0x4c, 0xd9, 0x9b, 0x91, 0xf2, 0x7e, 0xa2, 0xfe, 0xd2, 0xc3, 0x96, 0xa3, 0x19, 0x70, 0x32, 0xbc, 0xb9, 0x9d, 0x3b, + 0xcc, 0xf9, 0xd7, 0xd8, 0x1a, 0x0e, 0xbb, 0x6f, 0x40, 0x6f, 0x51, 0x1c, 0xb5, 0x6b, 0xa2, 0x64, 0x02, 0x01, 0x13, + 0xc1, 0x81, 0xb8, 0x8f, 0xd5, 0x48, 0x66, 0xed, 0x4b, 0xd8, 0x1d, 0xad, 0x4c, 0x8b, 0x96, 0x6a, 0xcd, 0xa7, 0x42, + 0x99, 0x49, 0x2a, 0x86, 0xd5, 0xc0, 0x9f, 0x5d, 0x39, 0x2d, 0xf8, 0x12, 0x58, 0x5e, 0xee, 0x78, 0x16, 0xb6, 0x0b, + 0x79, 0x7f, 0xfb, 0x60, 0x0d, 0xf8, 0x58, 0x9f, 0xb2, 0xe2, 0xbd, 0xfe, 0x77, 0x61, 0x43, 0x2d, 0x3d, 0xe6, 0xd7, + 0x66, 0xe1, 0x07, 0xe7, 0x35, 0x0e, 0x6e, 0x55, 0xed, 0x54, 0x31, 0x2e, 0x45, 0x14, 0x40, 0x80, 0x57, 0x34, 0x7c, + 0x47, 0x9d, 0xc7, 0xb3, 0xba, 0x44, 0x3f, 0x7e, 0xdf, 0x6d, 0x69, 0x4b, 0x12, 0x10, 0xa5, 0xca, 0x29, 0x72, 0x2b, + 0x27, 0xd7, 0x2c, 0x92, 0xa5, 0x77, 0x66, 0xd3, 0xa8, 0x68, 0x1a, 0x00, 0x48, 0xdf, 0x23, 0xcf, 0x82, 0xe7, 0x50, + 0x6e, 0x25, 0xf1, 0x56, 0xc9, 0x4c, 0x80, 0x89, 0xc2, 0x0f, 0x12, 0x21, 0x0c, 0x88, 0xbc, 0x1b, 0x06, 0x69, 0x6d, + 0x5f, 0xb8, 0x3e, 0x03, 0x58, 0x26, 0xc4, 0x5f, 0xdc, 0x87, 0x5b, 0xe7, 0xd3, 0xc1, 0xc9, 0x8d, 0x1c, 0x22, 0x82, + 0xd9, 0x28, 0xdd, 0x9b, 0x1c, 0x59, 0x65, 0xf7, 0x93, 0xab, 0x56, 0x4f, 0x04, 0x54, 0x5a, 0xbe, 0x57, 0xdc, 0x8c, + 0x38, 0x7f, 0x06, 0xdd, 0x6d, 0x70, 0xe5, 0x2a, 0xe7, 0xb4, 0x53, 0xd9, 0x21, 0xd9, 0xfe, 0xbb, 0x08, 0x5a, 0x94, + 0xcd, 0x14, 0xbe, 0x94, 0x2d, 0x3c, 0xb7, 0xd5, 0x95, 0xdb, 0x00, 0x90, 0x45, 0x62, 0x34, 0x17, 0x0d, 0xef, 0x92, + 0x08, 0xe3, 0xa2, 0xcd, 0x9f, 0xaa, 0x4f, 0xb3, 0x1a, 0x2a, 0xca, 0x46, 0xb5, 0xd9, 0x68, 0x86, 0x0c, 0xc4, 0x13, + 0xf4, 0xf2, 0xab, 0x1d, 0xe0, 0xc7, 0x2a, 0x79, 0xb2, 0x74, 0x1b, 0xf1, 0xb6, 0x3e, 0x49, 0xd4, 0xd3, 0x56, 0xf7, + 0x65, 0x98, 0x2c, 0x68, 0x9e, 0x3e, 0xff, 0xdf, 0x1d, 0xe0, 0x97, 0x90, 0x87, 0x2b, 0x16, 0xbe, 0x53, 0x75, 0x1f, + 0xaf, 0xaa, 0x70, 0xb1, 0x5e, 0x36, 0xe7, 0x83, 0x0e, 0x20, 0x47, 0xaa, 0xfa, 0x7d, 0x0e, 0xd3, 0x90, 0xe5, 0xb7, + 0x46, 0x17, 0x6e, 0x45, 0xc1, 0x81, 0xe7, 0xbd, 0x16, 0x2d, 0xd4, 0xd4, 0x55, 0x46, 0x84, 0x71, 0x4a, 0x50, 0x87, + 0x5b, 0x5d, 0xf0, 0xb4, 0x9b, 0x5b, 0x50, 0x49, 0x9e, 0x77, 0x93, 0x08, 0xe9, 0xc0, 0x7b, 0xb7, 0x52, 0x56, 0xbd, + 0x6e, 0x08, 0xc3, 0x5e, 0x39, 0xbb, 0x0a, 0x95, 0x3a, 0xad, 0xb4, 0x86, 0x1b, 0x5a, 0xb5, 0xa6, 0x68, 0xe0, 0xe4, + 0x94, 0xaa, 0x55, 0x2d, 0x79, 0xd6, 0x74, 0x6e, 0xb2, 0xcd, 0x5c, 0x56, 0x74, 0xdd, 0x21, 0xc3, 0x2b, 0x85, 0x75, + 0x5d, 0x07, 0xd7, 0x70, 0xa2, 0xc1, 0x79, 0xdf, 0x6e, 0x5b, 0x8e, 0x14, 0xd9, 0x2e, 0x56, 0x17, 0xee, 0xe8, 0xf8, + 0x2f, 0x0f, 0x28, 0x3e, 0x1d, 0xb5, 0xe4, 0x51, 0x8c, 0xac, 0xd0, 0x34, 0xb8, 0x06, 0x22, 0xfc, 0x0b, 0xaf, 0x4d, + 0xda, 0x6b, 0x4a, 0x26, 0xd4, 0xad, 0x9b, 0x73, 0x38, 0x48, 0x4b, 0xfc, 0xd2, 0x34, 0x8d, 0xb7, 0x79, 0x7a, 0x1f, + 0x4d, 0x56, 0xb5, 0xb7, 0x88, 0x4d, 0x7a, 0x76, 0x6d, 0x64, 0xb8, 0xc1, 0x84, 0x3c, 0xfe, 0x07, 0x3b, 0x01, 0x3a, + 0x91, 0x92, 0x05, 0x97, 0xe3, 0xca, 0x52, 0x0c, 0xf5, 0x9b, 0x57, 0x26, 0xeb, 0x53, 0x58, 0x64, 0x5e, 0x46, 0xae, + 0x5b, 0x2a, 0x47, 0xc3, 0x0f, 0x7d, 0x92, 0x2a, 0xe2, 0x3c, 0x03, 0x11, 0x78, 0xca, 0x6a, 0xe9, 0x79, 0x8e, 0x59, + 0x1b, 0x47, 0x92, 0xf9, 0x20, 0x24, 0x1f, 0xc6, 0xa5, 0x18, 0x52, 0x6c, 0xdf, 0xd8, 0x52, 0xe5, 0xf8, 0x86, 0x10, + 0x95, 0x13, 0xae, 0xa0, 0x09, 0x63, 0xed, 0x4f, 0x51, 0x51, 0x74, 0x67, 0xb5, 0x24, 0xd8, 0xad, 0x3a, 0x39, 0xa9, + 0xce, 0x34, 0x7f, 0x80, 0xc1, 0xd2, 0x1b, 0x74, 0x74, 0x58, 0x57, 0x63, 0x7e, 0x74, 0xb0, 0xe2, 0xd6, 0x57, 0x36, + 0x99, 0x45, 0xdb, 0x98, 0x71, 0xa6, 0xd4, 0x16, 0xdf, 0x5b, 0x9b, 0x5d, 0x04, 0x66, 0xf7, 0x0a, 0x97, 0x28, 0x22, + 0x67, 0xeb, 0x98, 0x91, 0x54, 0x71, 0xed, 0x10, 0xa9, 0xea, 0x9c, 0xd0, 0xc7, 0x40, 0x8b, 0xcf, 0x38, 0x5d, 0x2d, + 0xc4, 0x36, 0x0e, 0xbb, 0x8e, 0x4c, 0x95, 0xe4, 0x77, 0xd1, 0xe7, 0x7e, 0x2c, 0xc1, 0xe6, 0x02, 0xe2, 0x39, 0xdf, + 0x3b, 0x17, 0x6a, 0x16, 0x76, 0x21, 0xec, 0x60, 0x1a, 0x25, 0xe4, 0x68, 0xbf, 0x56, 0x7e, 0x8e, 0xe0, 0xd5, 0x2b, + 0x3d, 0x93, 0x0d, 0x3f, 0x11, 0xd1, 0xca, 0x52, 0xc2, 0x91, 0x0c, 0xa3, 0xf7, 0x2f, 0xde, 0xdc, 0x70, 0x90, 0xa1, + 0xf0, 0x0c, 0x36, 0x0f, 0x44, 0xc0, 0xed, 0xdd, 0x4f, 0x98, 0xd6, 0x52, 0x29, 0x08, 0xe7, 0x0a, 0x86, 0x04, 0x1b, + 0xe3, 0x52, 0x66, 0x6b, 0x93, 0x35, 0x01, 0x6b, 0xe1, 0x88, 0x3a, 0x68, 0x4c, 0x7a, 0x9e, 0x77, 0x9a, 0xd6, 0x31, + 0xff, 0x29, 0xb8, 0x60, 0xf9, 0x9e, 0x8d, 0xeb, 0x15, 0x04, 0xcd, 0x35, 0xae, 0xb1, 0xa6, 0xbb, 0xe8, 0x41, 0xea, + 0xfd, 0x35, 0x7b, 0xc6, 0x2a, 0x7f, 0xb7, 0xc0, 0x24, 0xd0, 0xa0, 0x50, 0x34, 0xe5, 0x2b, 0xa1, 0x43, 0x88, 0x5e, + 0xcd, 0x1b, 0xff, 0x2a, 0x7a, 0x96, 0x53, 0xcd, 0xe4, 0x76, 0xa3, 0x1a, 0x9a, 0x61, 0xca, 0x14, 0x12, 0xda, 0xc6, + 0x0f, 0x24, 0x5f, 0x76, 0xcb, 0xd4, 0xc2, 0x9c, 0xfd, 0x97, 0x16, 0xc7, 0xb1, 0x85, 0xaa, 0x55, 0x5f, 0x84, 0x39, + 0x4e, 0x4c, 0x5b, 0x77, 0xd9, 0xc8, 0x9d, 0xcd, 0x21, 0xa8, 0xa6, 0x6c, 0x6e, 0xd4, 0xbd, 0x63, 0x3e, 0x32, 0x87, + 0xb7, 0xc8, 0xef, 0x76, 0x64, 0x5e, 0x26, 0x97, 0x7d, 0xfc, 0xac, 0xd7, 0xbf, 0x09, 0x80, 0xc4, 0x36, 0x06, 0x8e, + 0xcd, 0xf3, 0xae, 0xb1, 0x96, 0x1b, 0xd3, 0x45, 0x62, 0x4d, 0x1d, 0x00, 0x0a, 0x9e, 0x72, 0xa0, 0x50, 0x49, 0x53, + 0x12, 0x04, 0xf5, 0x10, 0x72, 0x44, 0x39, 0xbe, 0x5d, 0xc4, 0x5c, 0xd7, 0xab, 0xc9, 0xc6, 0xbf, 0xdc, 0xfa, 0x68, + 0xd5, 0x07, 0xb4, 0xfb, 0x99, 0x8d, 0x7a, 0x58, 0xa4, 0xc6, 0x29, 0x0c, 0xf9, 0x11, 0xe7, 0xb1, 0xa6, 0x41, 0x37, + 0x4e, 0x06, 0x5a, 0x41, 0x2f, 0x15, 0xf8, 0xdf, 0x42, 0x39, 0x63, 0xe5, 0x46, 0x79, 0xa8, 0x58, 0xad, 0x5d, 0xf7, + 0xaf, 0xf8, 0x32, 0x62, 0x12, 0xa6, 0x87, 0x27, 0x60, 0xd6, 0x52, 0xae, 0xe4, 0xe7, 0xf5, 0x36, 0x54, 0x0b, 0x0f, + 0x38, 0xe9, 0xbc, 0xae, 0x3e, 0x07, 0x72, 0x91, 0x35, 0x53, 0x74, 0x68, 0xce, 0xd3, 0xa0, 0x82, 0x09, 0xbf, 0xad, + 0xe7, 0x26, 0x09, 0xba, 0xd4, 0x38, 0x56, 0x1e, 0x76, 0x1f, 0x47, 0xa3, 0xb3, 0x28, 0x27, 0x2e, 0x54, 0x63, 0x97, + 0xe7, 0x59, 0x54, 0x39, 0x2f, 0xf6, 0xa4, 0xab, 0x75, 0x65, 0xad, 0xbd, 0xa5, 0x15, 0xf3, 0xc6, 0x50, 0x4b, 0x52, + 0x73, 0x98, 0xd6, 0x89, 0x34, 0xb3, 0x68, 0x58, 0x99, 0x55, 0x08, 0xde, 0x86, 0xdd, 0x46, 0x88, 0xec, 0x82, 0x83, + 0xb4, 0x10, 0x2f, 0xbd, 0x59, 0x6a, 0x38, 0xc1, 0x53, 0xc8, 0x15, 0xfd, 0xc3, 0x69, 0x61, 0x40, 0x6a, 0x2b, 0x4a, + 0x66, 0xfd, 0xe8, 0xbf, 0xd9, 0x0c, 0xf7, 0x33, 0xd7, 0xca, 0x3b, 0xd4, 0x1f, 0x07, 0xa3, 0xd9, 0x8f, 0x49, 0x9f, + 0x72, 0xde, 0x2e, 0x05, 0x98, 0x2c, 0xc1, 0xb9, 0x17, 0xec, 0xcd, 0x80, 0x96, 0x37, 0x5e, 0x35, 0xb9, 0x21, 0x13, + 0xae, 0x9f, 0x24, 0x71, 0x2e, 0x56, 0x41, 0x7a, 0x09, 0xee, 0xbd, 0x68, 0xa8, 0x95, 0x05, 0xe9, 0xfe, 0x63, 0xb6, + 0xf8, 0x6b, 0x83, 0x91, 0x29, 0x88, 0x4f, 0x9e, 0xb0, 0xb7, 0x24, 0x8d, 0x4f, 0xe0, 0xd6, 0xb1, 0xe1, 0xda, 0xac, + 0x40, 0x1f, 0xfc, 0x79, 0xb2, 0x70, 0x68, 0x0d, 0xfc, 0xe7, 0xbb, 0x7f, 0x19, 0xaa, 0x1e, 0x3c, 0xdb, 0x99, 0x26, + 0xeb, 0x86, 0x9a, 0x48, 0xc3, 0x5f, 0xed, 0x7d, 0x01, 0xb8, 0x08, 0x57, 0x31, 0x03, 0x12, 0xd0, 0x95, 0xae, 0x58, + 0x60, 0x98, 0x02, 0xbb, 0x8c, 0xfe, 0x04, 0xbc, 0xad, 0x5c, 0x63, 0x3a, 0x4c, 0x8a, 0x4d, 0x00, 0xc4, 0x25, 0x01, + 0xf2, 0x96, 0x0e, 0x55, 0x04, 0x3a, 0x38, 0xc4, 0x7a, 0x79, 0x67, 0x12, 0xdf, 0xb9, 0x8f, 0xac, 0xce, 0x81, 0x3f, + 0x0d, 0xc8, 0x76, 0xa1, 0x00, 0x76, 0xcb, 0xbd, 0x5d, 0x87, 0x47, 0x83, 0x0c, 0x29, 0x51, 0x8c, 0x25, 0xf8, 0xf8, + 0x64, 0x1e, 0xf3, 0x98, 0xe7, 0xe3, 0x80, 0x6f, 0xf4, 0x01, 0x54, 0x1c, 0x2a, 0x90, 0xbf, 0x0b, 0x51, 0xa1, 0x2e, + 0xf7, 0xd1, 0x02, 0xc0, 0xe8, 0x13, 0xcc, 0xa1, 0x13, 0xb7, 0xd4, 0x1b, 0x50, 0xe5, 0x7b, 0x90, 0x52, 0x09, 0xfe, + 0x46, 0x26, 0x53, 0xd5, 0x9e, 0x8a, 0x59, 0x55, 0x18, 0x45, 0x24, 0x6c, 0xd4, 0x16, 0xc2, 0x1d, 0x63, 0x46, 0xcd, + 0x8f, 0x9d, 0x79, 0x1c, 0x4b, 0x7b, 0x3d, 0x12, 0x4a, 0x76, 0xc6, 0x7b, 0x0f, 0x4a, 0xe1, 0xe0, 0x2a, 0x80, 0xfb, + 0xb4, 0xfa, 0x9c, 0x4a, 0x8c, 0x99, 0x65, 0xd1, 0xf0, 0x50, 0x7a, 0x93, 0xa8, 0xf1, 0x55, 0x70, 0xfd, 0xcd, 0x40, + 0xbc, 0x8a, 0x3f, 0x7b, 0xdc, 0xf4, 0x71, 0xf5, 0xbf, 0x21, 0xe0, 0xea, 0x2c, 0x5c, 0x39, 0x61, 0x9f, 0x27, 0xc8, + 0xd7, 0x0d, 0xde, 0x2e, 0x5b, 0x4b, 0x34, 0x4f, 0x66, 0xe9, 0x73, 0x67, 0x58, 0xa0, 0xaa, 0xaa, 0xf9, 0x2d, 0x0a, + 0x25, 0x64, 0x91, 0x41, 0x68, 0x48, 0x9a, 0x99, 0x48, 0xed, 0xdc, 0x5b, 0x6e, 0x62, 0x47, 0x1a, 0x78, 0xda, 0xee, + 0x3d, 0xc3, 0xc7, 0x68, 0x30, 0x14, 0xc9, 0x33, 0xb8, 0xf2, 0x06, 0xba, 0x52, 0x49, 0xca, 0xe5, 0x7c, 0x2c, 0xfa, + 0x32, 0xf4, 0x2b, 0xfa, 0x4d, 0x5a, 0x96, 0xc7, 0x5d, 0x24, 0x52, 0xff, 0x57, 0xb9, 0xe6, 0x34, 0xfa, 0xbc, 0x34, + 0xb6, 0x51, 0x31, 0x68, 0x70, 0xdb, 0x14, 0x08, 0x39, 0x53, 0x5a, 0x94, 0x1e, 0x0c, 0x2d, 0x7d, 0xff, 0xc3, 0x55, + 0x58, 0xba, 0xa7, 0xb4, 0x53, 0x9e, 0x5e, 0xf4, 0x52, 0x83, 0x81, 0xf8, 0x77, 0xb2, 0xe4, 0x4d, 0x5f, 0xa9, 0x91, + 0x4c, 0xfc, 0x1f, 0xbc, 0xb4, 0x51, 0x2e, 0x97, 0x3a, 0xa5, 0xd3, 0x0e, 0x8a, 0xa3, 0x2e, 0x39, 0x1e, 0xc5, 0xbe, + 0x65, 0x34, 0x8a, 0x57, 0xca, 0x3e, 0x8b, 0x89, 0x1b, 0xf4, 0x44, 0x34, 0x68, 0xd6, 0x32, 0x80, 0x26, 0x7a, 0x4d, + 0xc9, 0x88, 0x53, 0x77, 0x82, 0x1b, 0x81, 0x32, 0xab, 0x68, 0x43, 0x52, 0x37, 0xbe, 0x31, 0x98, 0x5a, 0x3d, 0xee, + 0x87, 0x21, 0x2a, 0x65, 0x7d, 0xfb, 0x74, 0x44, 0xd5, 0x57, 0xd9, 0xa5, 0xf4, 0xad, 0x62, 0xa3, 0x5d, 0xea, 0x70, + 0xc7, 0x1c, 0xd8, 0xe4, 0x99, 0x41, 0x2d, 0x67, 0x0e, 0x31, 0x3f, 0x3d, 0x8f, 0x36, 0x0e, 0x98, 0x9d, 0x18, 0x62, + 0x8e, 0x3a, 0x57, 0x25, 0x90, 0xc6, 0x60, 0x3a, 0xb1, 0x93, 0x44, 0xea, 0x4b, 0xcb, 0x5e, 0xaf, 0x54, 0x31, 0xa7, + 0x96, 0x96, 0xfd, 0x00, 0x76, 0xf8, 0x4a, 0xcb, 0x4f, 0x54, 0x61, 0x68, 0x76, 0xcb, 0x1a, 0xe1, 0xaf, 0x36, 0xbd, + 0x8e, 0xd7, 0xf1, 0x2a, 0x95, 0xa5, 0x3b, 0x20, 0x86, 0x1c, 0xcc, 0x4e, 0xb0, 0x01, 0x29, 0xa2, 0x65, 0x71, 0xbe, + 0xe6, 0x29, 0x9f, 0x8d, 0x63, 0x89, 0xb5, 0xd1, 0x63, 0xcb, 0xdb, 0xe6, 0xdc, 0xa3, 0x19, 0xa1, 0x22, 0x51, 0x62, + 0xd9, 0xd6, 0xb0, 0xb8, 0x11, 0x0b, 0x4a, 0x88, 0x25, 0xfa, 0x05, 0x3f, 0x23, 0xe2, 0x6a, 0x80, 0xde, 0xa4, 0x76, + 0x06, 0x5d, 0x05, 0x1d, 0x8c, 0xa3, 0x6b, 0xfe, 0x3b, 0x0d, 0x37, 0x85, 0x2e, 0x11, 0xb7, 0x0d, 0x70, 0xc9, 0xc5, + 0x0c, 0x83, 0x3a, 0x85, 0xac, 0x6e, 0xe2, 0x5b, 0x5d, 0xe4, 0x7f, 0x62, 0xf1, 0x27, 0xb8, 0x90, 0x17, 0x97, 0x86, + 0x17, 0xe4, 0xa6, 0xbc, 0xf7, 0x5b, 0xdc, 0xc8, 0x10, 0xad, 0x7c, 0xfa, 0xe8, 0xf2, 0x62, 0x91, 0x66, 0xdc, 0xa9, + 0xe9, 0xad, 0xf1, 0xb9, 0x6e, 0x45, 0x7f, 0x32, 0x9e, 0x9b, 0x71, 0x92, 0x66, 0xe4, 0xa7, 0x7c, 0xc8, 0xef, 0xa1, + 0x54, 0x33, 0x9c, 0x57, 0x73, 0x1d, 0x50, 0xcf, 0x0c, 0x5f, 0x4e, 0x63, 0x1d, 0x98, 0x74, 0x0b, 0xfe, 0xb0, 0x87, + 0x43, 0xd9, 0xb4, 0xb7, 0x4f, 0xde, 0xf0, 0xb9, 0xd5, 0x3d, 0x5d, 0x32, 0x4a, 0x1a, 0x4c, 0x7d, 0x54, 0xb5, 0xdf, + 0x97, 0x68, 0x1c, 0xc4, 0xd3, 0x18, 0x6b, 0x44, 0xff, 0x4b, 0x7c, 0x7c, 0x55, 0x86, 0x37, 0xc0, 0x3c, 0x28, 0x49, + 0x8e, 0xa5, 0x5f, 0x8c, 0x69, 0x84, 0xc8, 0x7b, 0xcc, 0x2f, 0xea, 0xf5, 0x60, 0xe3, 0x32, 0xe4, 0xe2, 0x15, 0xd1, + 0xe3, 0xd9, 0xe2, 0x5b, 0xe8, 0xc2, 0x70, 0x98, 0x9a, 0x00, 0xfe, 0x1f, 0x65, 0x0f, 0xd4, 0x0f, 0xa1, 0x7c, 0x99, + 0x36, 0xb6, 0x9f, 0x6d, 0x9a, 0x65, 0x46, 0xde, 0x9d, 0x27, 0x6b, 0xb6, 0x91, 0xc4, 0xda, 0x34, 0x6a, 0x13, 0x34, + 0x5a, 0xbd, 0xcd, 0xd9, 0x37, 0x36, 0xa6, 0xd1, 0xd0, 0xf7, 0x68, 0xa6, 0xf4, 0xfa, 0x31, 0x7d, 0x71, 0x7d, 0x87, + 0x98, 0x18, 0xf6, 0x9b, 0xd5, 0x3a, 0x24, 0x36, 0xba, 0xdb, 0x71, 0xc6, 0xfa, 0x1e, 0xd1, 0x7d, 0x93, 0xcb, 0x42, + 0x4e, 0x6e, 0x42, 0xa6, 0x12, 0x75, 0xed, 0xdb, 0x6a, 0xd8, 0xde, 0x03, 0x94, 0x51, 0xb3, 0xd4, 0xc0, 0xe8, 0x8b, + 0xd7, 0xe5, 0x0c, 0xc1, 0x35, 0xb7, 0xde, 0xb8, 0x40, 0x64, 0xf0, 0xd1, 0xb4, 0xcc, 0x65, 0x51, 0x03, 0x27, 0x47, + 0xeb, 0x20, 0xfd, 0xf2, 0x20, 0x1e, 0xa9, 0xfa, 0xe2, 0x6d, 0xcd, 0xc0, 0x8a, 0x96, 0xa8, 0x86, 0x0f, 0x7c, 0xbc, + 0x36, 0xce, 0xcb, 0x8c, 0x5f, 0x4e, 0x8e, 0xd2, 0x0d, 0xe3, 0xca, 0xda, 0xee, 0x62, 0x1c, 0xae, 0xba, 0xad, 0x4a, + 0xa6, 0x64, 0xc6, 0xbe, 0x25, 0x99, 0x9f, 0x49, 0xa5, 0xe7, 0x8d, 0x9a, 0x97, 0xb0, 0xd9, 0xf3, 0x67, 0x3a, 0xc5, + 0x95, 0x49, 0x36, 0x0a, 0xdd, 0xff, 0xd1, 0x8d, 0x58, 0x7a, 0x8f, 0x0e, 0x8c, 0x39, 0xb8, 0x7a, 0x4a, 0xcf, 0x43, + 0x5b, 0x0d, 0xef, 0xe9, 0xfb, 0x34, 0x5f, 0x89, 0xcf, 0x7f, 0xe9, 0x86, 0x8d, 0x45, 0x9d, 0xf4, 0x7e, 0xd5, 0x29, + 0x24, 0x0e, 0x6e, 0x45, 0x3b, 0x21, 0x27, 0xf9, 0x09, 0x41, 0x7d, 0xd9, 0xa0, 0xda, 0x00, 0x6c, 0x58, 0xa5, 0xa2, + 0x2e, 0x06, 0x5a, 0x8e, 0x28, 0x5b, 0x0f, 0xfa, 0xda, 0xb4, 0x3d, 0xdd, 0x5f, 0x35, 0xab, 0x6d, 0xeb, 0x65, 0x09, + 0x53, 0x96, 0x4e, 0xdb, 0x85, 0x3a, 0x6d, 0xc9, 0x33, 0xfd, 0x52, 0x17, 0x73, 0xda, 0xc4, 0xc1, 0xcf, 0x95, 0xbf, + 0x87, 0xdb, 0xda, 0x1d, 0xbb, 0xd6, 0xc8, 0x06, 0xc7, 0xed, 0x31, 0xc7, 0xd9, 0x05, 0x22, 0x5a, 0x16, 0xda, 0x1e, + 0xaa, 0x16, 0xa9, 0x3b, 0xf5, 0x9d, 0x09, 0xbb, 0x09, 0x20, 0x54, 0xec, 0x5d, 0x92, 0x3c, 0x7c, 0x96, 0xd9, 0xe8, + 0xc0, 0x6e, 0xb2, 0x52, 0x9b, 0xf8, 0xfa, 0x94, 0x99, 0x96, 0xa2, 0xab, 0x33, 0x6a, 0xe0, 0xce, 0x69, 0x3e, 0x39, + 0x68, 0x26, 0xca, 0x6d, 0x13, 0xd9, 0xf3, 0x91, 0x3a, 0x41, 0x5d, 0xa0, 0x12, 0x35, 0xad, 0x53, 0xcb, 0x08, 0x0a, + 0x37, 0xc9, 0xde, 0x78, 0xa4, 0x9b, 0xb1, 0x62, 0xfb, 0x15, 0xa8, 0x9b, 0xb3, 0x1b, 0x77, 0x60, 0xc8, 0xaa, 0x15, + 0x6a, 0x67, 0x04, 0xc7, 0xd0, 0x7c, 0x2d, 0x29, 0x12, 0x86, 0x95, 0x80, 0x1d, 0x38, 0x52, 0xa4, 0x20, 0xb8, 0xdb, + 0xea, 0xfc, 0x0d, 0x94, 0x1e, 0x51, 0xa2, 0xc2, 0x2b, 0x2a, 0xa7, 0x74, 0x83, 0x5d, 0x3d, 0x17, 0x20, 0x60, 0x0a, + 0x28, 0x36, 0x32, 0x8b, 0xca, 0x76, 0xab, 0x42, 0xf6, 0x72, 0x3d, 0xb8, 0xbc, 0xf9, 0x40, 0xdd, 0xd8, 0xf4, 0xdd, + 0x97, 0x34, 0xe8, 0x84, 0xe2, 0xc1, 0x07, 0xec, 0xb1, 0x15, 0xf1, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, 0xea, 0x4b, + 0xe4, 0x83, 0x69, 0xff, 0xee, 0x97, 0xc3, 0x2a, 0xe0, 0xea, 0x77, 0xba, 0x91, 0x43, 0xc5, 0xbc, 0x1b, 0x10, 0xa2, + 0x90, 0x01, 0x19, 0xd1, 0xd6, 0x7f, 0xb6, 0xf4, 0xb5, 0x44, 0x3b, 0xda, 0xda, 0x27, 0x01, 0xd9, 0x43, 0x6f, 0xb6, + 0xc1, 0x39, 0x19, 0x2c, 0x00, 0x0c, 0xfe, 0x0b, 0xcd, 0x37, 0x89, 0xa5, 0x84, 0x56, 0x45, 0xf0, 0x71, 0x68, 0x66, + 0x6f, 0xcc, 0xa8, 0xfa, 0x34, 0x03, 0xe8, 0x9e, 0x84, 0x50, 0xe6, 0x6c, 0xaf, 0x37, 0x04, 0x75, 0xec, 0x17, 0x8a, + 0xd5, 0x67, 0x70, 0xc3, 0xff, 0xe8, 0xab, 0x5f, 0xe0, 0x5e, 0x45, 0x51, 0x13, 0xbb, 0xa6, 0x68, 0x1c, 0x4a, 0xb8, + 0xc9, 0x85, 0xf5, 0x2e, 0x09, 0x02, 0x8d, 0xfe, 0x2b, 0x35, 0xc5, 0xc8, 0x02, 0xba, 0xb3, 0x85, 0xc0, 0x5a, 0xc1, + 0x48, 0x4a, 0x44, 0x28, 0x65, 0xae, 0x33, 0x8b, 0xb7, 0xec, 0xea, 0x97, 0xb6, 0xc4, 0xea, 0xcd, 0x3b, 0x06, 0x67, + 0xc5, 0xf2, 0xed, 0x79, 0x27, 0x33, 0x2f, 0xb4, 0x2c, 0x10, 0xd5, 0x14, 0xd2, 0x97, 0xbc, 0x85, 0xd1, 0xca, 0x63, + 0xe3, 0x82, 0x69, 0x7d, 0xff, 0x52, 0xaa, 0x6a, 0xe7, 0x45, 0xa8, 0xab, 0x97, 0xd1, 0xc4, 0xc2, 0xad, 0xa5, 0x0c, + 0xec, 0x4a, 0x44, 0xb0, 0x4d, 0x11, 0xc0, 0xe4, 0x6b, 0x20, 0x44, 0x3c, 0xa8, 0x82, 0x52, 0x3d, 0x61, 0x61, 0xdf, + 0xa0, 0xe0, 0xdd, 0x5d, 0x74, 0x8d, 0x6f, 0x81, 0x88, 0xde, 0x96, 0xc0, 0x30, 0x3c, 0x2e, 0x9e, 0x4a, 0x79, 0x53, + 0x12, 0xb0, 0x5d, 0x85, 0xef, 0x45, 0x94, 0x9b, 0xb5, 0x1f, 0x8d, 0x68, 0xab, 0x0d, 0x12, 0xa5, 0x45, 0xf6, 0x1a, + 0x4f, 0x9b, 0xfc, 0xaa, 0x79, 0x67, 0xf7, 0x36, 0x7d, 0xd5, 0x86, 0x30, 0x3c, 0x45, 0x3a, 0x25, 0x6c, 0xbb, 0x48, + 0xc4, 0xfd, 0x1f, 0x67, 0x8a, 0x16, 0xfb, 0x6c, 0x9c, 0x4b, 0xb5, 0xeb, 0x3b, 0x04, 0x8c, 0x9f, 0xd5, 0x43, 0x77, + 0xfd, 0xa9, 0x1c, 0xeb, 0x6f, 0x46, 0x1d, 0x54, 0xe0, 0xe1, 0x6e, 0x96, 0x7e, 0x8d, 0xc6, 0xf7, 0x5a, 0x7c, 0xd9, + 0xfb, 0x8a, 0x00, 0xbc, 0x78, 0x13, 0xef, 0xa2, 0xfd, 0x44, 0x27, 0x70, 0x8c, 0xb0, 0x6d, 0x93, 0x80, 0xb5, 0x8f, + 0x5f, 0x91, 0x14, 0xe4, 0xc8, 0xef, 0x40, 0xfe, 0xb7, 0xc6, 0xdc, 0xf0, 0x1d, 0x15, 0x73, 0x4b, 0x29, 0x5d, 0x25, + 0x4f, 0x4e, 0x61, 0x7b, 0xcc, 0x02, 0xc4, 0x11, 0x38, 0x78, 0x3f, 0xb1, 0x27, 0x7f, 0xba, 0xa0, 0x6e, 0x46, 0x47, + 0x8a, 0x43, 0xb1, 0x9a, 0x9f, 0x1a, 0x1a, 0x29, 0x0f, 0xd3, 0x11, 0x41, 0x4d, 0x68, 0x31, 0x16, 0x8e, 0x2e, 0x49, + 0x00, 0x81, 0x09, 0x50, 0xa7, 0xc8, 0xa2, 0xaf, 0x47, 0x6e, 0xc5, 0xa4, 0x67, 0x5b, 0xb9, 0x74, 0xed, 0x13, 0xde, + 0xd4, 0x9e, 0x81, 0x5b, 0xab, 0xc6, 0x68, 0x75, 0x67, 0x47, 0x65, 0xa5, 0xc7, 0xe4, 0x74, 0x6e, 0xae, 0xc4, 0x72, + 0x4d, 0x71, 0x1f, 0x8e, 0x76, 0x0f, 0xea, 0x1d, 0x51, 0x04, 0x62, 0x4c, 0x94, 0xd9, 0x99, 0x9c, 0xed, 0x37, 0x7a, + 0x00, 0xdf, 0x52, 0x50, 0x2f, 0x98, 0x0f, 0xb8, 0xdc, 0x5b, 0xde, 0x91, 0x79, 0xe0, 0x95, 0x09, 0x47, 0x4d, 0xb9, + 0xf6, 0x66, 0x23, 0xb3, 0x44, 0x4d, 0x78, 0xfe, 0xbf, 0x1a, 0x6a, 0x48, 0x2c, 0x20, 0x93, 0xb1, 0x6f, 0xdf, 0x55, + 0xe4, 0xd3, 0x2c, 0x74, 0xb8, 0xc2, 0x01, 0xd4, 0x71, 0x6a, 0x6a, 0xc0, 0x0d, 0x78, 0xf8, 0x41, 0x42, 0x2b, 0xdf, + 0x25, 0xd4, 0xf8, 0xe7, 0x7e, 0xc6, 0xbe, 0x77, 0x9b, 0x6d, 0x9e, 0xd3, 0x2b, 0xc0, 0xd2, 0xe8, 0xfe, 0x36, 0xe9, + 0x8b, 0x83, 0x06, 0x0c, 0x55, 0x27, 0xaf, 0x16, 0xd3, 0xc6, 0x76, 0xf3, 0xaf, 0xcf, 0xe4, 0xbc, 0xa3, 0xf7, 0xa5, + 0xe7, 0xb6, 0xb9, 0x1f, 0x77, 0x75, 0x57, 0xb1, 0x6e, 0x5e, 0x34, 0xc4, 0x8a, 0x22, 0x2e, 0x3e, 0xac, 0x77, 0xb7, + 0x73, 0xbb, 0x75, 0x24, 0xc5, 0x3b, 0x05, 0x77, 0x4a, 0x4a, 0x75, 0xcf, 0x8c, 0xa1, 0x27, 0xec, 0xbd, 0x6c, 0xdc, + 0xff, 0x72, 0xe9, 0xac, 0xbb, 0xe2, 0xae, 0x72, 0xf0, 0xc6, 0xa4, 0x8b, 0x16, 0xec, 0xfa, 0x45, 0xaf, 0xdf, 0x7c, + 0xa1, 0x7e, 0x5a, 0xd1, 0x2d, 0x4a, 0x28, 0xa0, 0x0d, 0x2d, 0x5f, 0x10, 0xef, 0x84, 0xca, 0x46, 0x77, 0xc2, 0xc9, + 0xd3, 0xe2, 0xbe, 0xfa, 0x4e, 0xc6, 0xe0, 0x2f, 0x90, 0xaf, 0xe6, 0x51, 0xf0, 0xf1, 0x9f, 0xc4, 0x2f, 0x2f, 0x8b, + 0xfa, 0xcd, 0x8b, 0xd7, 0x5e, 0x0b, 0x80, 0x69, 0x9d, 0x1f, 0xf1, 0xe2, 0x7b, 0x4b, 0xe7, 0x41, 0x92, 0x3f, 0x62, + 0x3c, 0xfb, 0x28, 0x4b, 0x80, 0x04, 0x58, 0xa5, 0x7a, 0x67, 0x16, 0xc4, 0xe3, 0xfb, 0x30, 0x11, 0x39, 0x03, 0x09, + 0x1b, 0x14, 0x0a, 0xc2, 0xf8, 0x4e, 0x23, 0xc2, 0x7b, 0x14, 0x31, 0x15, 0x5e, 0x76, 0x7d, 0xbf, 0x4a, 0x71, 0xb0, + 0x02, 0xa3, 0x76, 0xfb, 0x2f, 0x26, 0x53, 0x60, 0x4f, 0x1c, 0x4c, 0xd4, 0x15, 0x4e, 0x78, 0xfc, 0xe1, 0xe4, 0xfe, + 0x25, 0x3d, 0x52, 0x55, 0x87, 0x39, 0x32, 0xbe, 0xb6, 0xaa, 0xea, 0xc5, 0xaf, 0xd0, 0xb6, 0x2f, 0x67, 0xa9, 0xb5, + 0x74, 0xd9, 0xab, 0x81, 0x6c, 0xed, 0x6c, 0xa2, 0xba, 0x3b, 0x59, 0x1e, 0x97, 0x1b, 0xc2, 0x10, 0x88, 0x75, 0xee, + 0xf2, 0xc8, 0x25, 0xdb, 0xc7, 0xc2, 0xc5, 0x29, 0xdb, 0xfc, 0xec, 0x59, 0xfa, 0xcb, 0x42, 0x79, 0xca, 0xb7, 0xde, + 0xc2, 0xdb, 0xaf, 0x89, 0x1e, 0xf4, 0x77, 0xd3, 0x26, 0xca, 0x01, 0xd1, 0x81, 0x83, 0xc6, 0xf7, 0xa7, 0xf7, 0xff, + 0xa8, 0x19, 0x52, 0x3d, 0x6b, 0x49, 0x2b, 0x07, 0x7f, 0x48, 0x9c, 0x2d, 0xcd, 0x61, 0x2a, 0x11, 0x24, 0xe3, 0xda, + 0xf4, 0x32, 0x59, 0x7b, 0xd3, 0x76, 0x97, 0x1d, 0x90, 0xb5, 0xe4, 0x14, 0x88, 0x1a, 0xb9, 0xd7, 0x35, 0xdf, 0x42, + 0xa8, 0x93, 0x58, 0xa6, 0xb6, 0x7b, 0x8d, 0x3a, 0x83, 0xb5, 0x04, 0xd0, 0x20, 0xe6, 0x35, 0xfe, 0x37, 0x43, 0x33, + 0xfe, 0xf6, 0xcd, 0x93, 0x83, 0x1b, 0x46, 0x82, 0xa9, 0xf8, 0x28, 0x80, 0xe1, 0x8c, 0xe0, 0x49, 0xbd, 0xbe, 0xf6, + 0x25, 0x06, 0xfa, 0xa1, 0xa4, 0xea, 0xc5, 0xde, 0xcd, 0xce, 0x2b, 0x70, 0x51, 0xda, 0x3f, 0x50, 0x7c, 0x43, 0x9a, + 0x91, 0x5a, 0xd9, 0xab, 0x7b, 0xef, 0xd4, 0x76, 0xd2, 0x6b, 0xc9, 0x82, 0xe6, 0xc0, 0x4b, 0x06, 0xb7, 0x24, 0x67, + 0x60, 0x79, 0x7f, 0x2e, 0x3d, 0xd9, 0x19, 0xf8, 0x44, 0xea, 0x97, 0xfa, 0x4a, 0xdc, 0x2c, 0x09, 0x65, 0x2c, 0x24, + 0xd5, 0xfd, 0x0a, 0x44, 0xaf, 0xff, 0xe8, 0x46, 0x85, 0x86, 0xbd, 0x3a, 0xdb, 0x31, 0x90, 0x46, 0x8c, 0xf6, 0x2e, + 0xb5, 0xde, 0xee, 0xe9, 0x91, 0x31, 0x7d, 0xde, 0xfb, 0xb9, 0xea, 0xdc, 0x91, 0xd9, 0x86, 0x54, 0xff, 0x54, 0xcc, + 0x5a, 0x52, 0x21, 0xdb, 0x8a, 0xed, 0xb4, 0x02, 0x77, 0x1e, 0x4c, 0xde, 0x1d, 0x98, 0xbb, 0x0f, 0x64, 0x0e, 0x63, + 0xad, 0x2b, 0x55, 0x95, 0x1b, 0x5f, 0xc4, 0xd0, 0xef, 0x03, 0xc9, 0x2c, 0xb2, 0x48, 0xaa, 0xc0, 0x16, 0x6a, 0x23, + 0xef, 0xdd, 0xcf, 0xc5, 0xaa, 0xd3, 0x2f, 0x4d, 0x82, 0x74, 0xff, 0x46, 0xe4, 0x9a, 0x19, 0x79, 0xf3, 0xbe, 0xda, + 0x46, 0x30, 0xac, 0xa3, 0x8d, 0x48, 0xa1, 0x9d, 0x2f, 0x19, 0xfe, 0x33, 0x92, 0x77, 0x62, 0xa6, 0x7f, 0x90, 0xce, + 0xac, 0x1f, 0x84, 0xf1, 0x76, 0xbf, 0x40, 0x73, 0xfe, 0xa1, 0x80, 0x67, 0x2f, 0x14, 0x60, 0x01, 0x69, 0xf4, 0x4a, + 0xea, 0x63, 0x4d, 0x50, 0x4e, 0xb8, 0x32, 0x94, 0x6c, 0x94, 0xd7, 0x52, 0x7b, 0x42, 0xfb, 0xa6, 0x64, 0x03, 0x6c, + 0xe2, 0x3a, 0x76, 0xd1, 0xd4, 0xb1, 0xc0, 0x74, 0xb9, 0x7f, 0x71, 0x6c, 0x0f, 0x52, 0xb9, 0x70, 0x01, 0x5f, 0xe8, + 0x02, 0x77, 0x61, 0x38, 0x40, 0x6b, 0x50, 0xff, 0x71, 0xdc, 0x14, 0xff, 0x50, 0x4a, 0x25, 0xb1, 0xc9, 0x42, 0xa9, + 0x50, 0x7b, 0x88, 0x9f, 0x1b, 0xe5, 0x5a, 0x4f, 0x82, 0x6b, 0xa4, 0x08, 0x08, 0x8e, 0x2b, 0x26, 0x71, 0x35, 0xa5, + 0x21, 0xb8, 0x73, 0xf4, 0x99, 0xd7, 0xf2, 0x2b, 0xa1, 0xec, 0xba, 0xc0, 0x67, 0x60, 0x05, 0x18, 0xec, 0x2f, 0xec, + 0x0b, 0x47, 0x17, 0x2d, 0x67, 0xeb, 0xb3, 0x03, 0x27, 0x40, 0x1e, 0x2b, 0x4f, 0x24, 0x61, 0x6b, 0x72, 0xee, 0x4d, + 0x6e, 0xdf, 0x33, 0x85, 0x68, 0x52, 0x44, 0xd5, 0xe3, 0x17, 0xb8, 0x20, 0x2d, 0xa9, 0x64, 0xa5, 0xa0, 0x55, 0xa8, + 0x40, 0xb4, 0xd1, 0xc6, 0xd5, 0xaa, 0xd3, 0xfb, 0xa7, 0x11, 0x9d, 0x97, 0xc6, 0xda, 0x10, 0x43, 0xe0, 0x88, 0xb5, + 0xf5, 0x53, 0x85, 0x8d, 0x37, 0xc9, 0xba, 0xb8, 0xcf, 0x63, 0xfb, 0x35, 0x43, 0x33, 0x12, 0x6f, 0x2a, 0x6f, 0x9b, + 0xe2, 0x61, 0xc1, 0x1b, 0x27, 0x7a, 0xa1, 0x5f, 0xb0, 0x39, 0xe1, 0xf4, 0xd7, 0x75, 0x97, 0xc9, 0xb1, 0xfa, 0xd8, + 0x43, 0x48, 0xb9, 0x50, 0xa3, 0x42, 0xa4, 0xe7, 0xed, 0xd8, 0x5c, 0xb9, 0xc7, 0xd2, 0xe8, 0x1c, 0xd7, 0xa4, 0x24, + 0xdb, 0xcd, 0xf0, 0xd2, 0xa6, 0x82, 0x38, 0x71, 0x77, 0x3f, 0xa8, 0x05, 0xef, 0xb6, 0x21, 0xad, 0x69, 0xfd, 0xfa, + 0x95, 0x3f, 0xbf, 0x71, 0x56, 0x52, 0x2c, 0x92, 0x45, 0xd4, 0x6c, 0xd7, 0x4f, 0xec, 0xf2, 0x67, 0xd2, 0xfb, 0x2c, + 0xbc, 0xc9, 0xda, 0xbf, 0x1e, 0xe1, 0x4b, 0xae, 0x4d, 0x29, 0x92, 0x29, 0xca, 0xdd, 0xbf, 0x49, 0x90, 0x10, 0x19, + 0xfe, 0x42, 0x00, 0xc6, 0xba, 0xa7, 0x55, 0xf3, 0xd1, 0x59, 0x89, 0xb3, 0x0f, 0xbc, 0x06, 0xe0, 0xa2, 0xe0, 0x0b, + 0xa3, 0x34, 0x5a, 0xb1, 0x18, 0x1c, 0x07, 0x9a, 0xca, 0x07, 0x5c, 0xff, 0x30, 0xa3, 0x42, 0x29, 0x36, 0xd4, 0xf7, + 0x13, 0xa7, 0x65, 0x42, 0x40, 0x23, 0x9d, 0x39, 0xb7, 0x51, 0x2b, 0xf0, 0xed, 0x71, 0x3d, 0x1c, 0xe4, 0x7a, 0xda, + 0x21, 0xf8, 0x34, 0x4d, 0x7e, 0x73, 0xc8, 0xe6, 0xf2, 0xa5, 0xd9, 0xef, 0xa5, 0x1b, 0x26, 0x2f, 0x36, 0xf4, 0x56, + 0xd8, 0x08, 0x03, 0x51, 0x8d, 0x2a, 0x68, 0x24, 0x24, 0x61, 0xa7, 0xbd, 0x26, 0x38, 0x9a, 0xd2, 0x62, 0x2a, 0xfc, + 0xa4, 0xae, 0x4f, 0xc6, 0xd7, 0xa2, 0x31, 0xb5, 0x8e, 0x1b, 0xf1, 0x71, 0x39, 0x9f, 0x01, 0xc8, 0x42, 0xc5, 0x73, + 0x4b, 0xa2, 0xcf, 0x28, 0x38, 0x1e, 0x54, 0x59, 0x31, 0xd2, 0x0e, 0x43, 0x11, 0x72, 0x63, 0xa6, 0x71, 0x1c, 0x17, + 0xfe, 0x82, 0xd3, 0x2a, 0x8d, 0x31, 0xaa, 0xbc, 0xb6, 0xe9, 0xa5, 0xf9, 0x3a, 0xa1, 0x3a, 0x97, 0xf1, 0xd7, 0x93, + 0xef, 0xb9, 0x92, 0x29, 0x40, 0x1e, 0x69, 0xbc, 0x61, 0xef, 0x78, 0x06, 0xbc, 0x99, 0xc1, 0x25, 0x01, 0x48, 0x27, + 0xeb, 0x74, 0x6e, 0xc3, 0x23, 0xd2, 0x09, 0x38, 0x3b, 0xaa, 0xf4, 0xe4, 0xca, 0x4a, 0x32, 0xd6, 0x1d, 0xc6, 0x7c, + 0xc9, 0xc6, 0xa5, 0x8d, 0xb7, 0x53, 0x66, 0x9d, 0xa5, 0xcb, 0x94, 0x88, 0x07, 0x95, 0xa4, 0xf1, 0x32, 0xc0, 0x61, + 0x9a, 0x97, 0x6f, 0xd3, 0x5a, 0x7e, 0xcf, 0x70, 0x93, 0x21, 0x15, 0x4d, 0x56, 0x69, 0x76, 0x01, 0x20, 0xc0, 0xb6, + 0x5d, 0x74, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x8e, 0xec, 0x1d, 0xb5, 0x3b, 0xb3, 0xc7, 0x41, + 0x80, 0x77, 0x75, 0x4b, 0x76, 0x29, 0x13, 0xdf, 0xc4, 0xd0, 0xf5, 0xab, 0x96, 0x00, 0xb8, 0x01, 0x76, 0x59, 0x12, + 0x75, 0x26, 0x73, 0x81, 0x55, 0x79, 0xcc, 0xc3, 0x54, 0xa6, 0x98, 0xaa, 0x05, 0x5b, 0x82, 0x5c, 0x40, 0xb9, 0xbc, + 0x71, 0xb9, 0xae, 0xaf, 0x02, 0x40, 0xd1, 0xc3, 0x38, 0x2a, 0x26, 0x9e, 0x1b, 0xe9, 0x85, 0xbd, 0xaa, 0x40, 0x61, + 0x7c, 0x6a, 0x4b, 0x72, 0x72, 0x29, 0xfd, 0xc9, 0x64, 0xdb, 0x6a, 0xb6, 0xdb, 0xc9, 0x45, 0x42, 0xd7, 0x92, 0xd8, + 0x42, 0x2e, 0xa9, 0xdb, 0xbb, 0x3a, 0xc4, 0xf2, 0x5e, 0x16, 0x30, 0xda, 0x46, 0x67, 0xdd, 0x55, 0x1f, 0xd6, 0x94, + 0x08, 0x27, 0xcb, 0xc6, 0x7c, 0x27, 0xd6, 0x17, 0xa9, 0x35, 0x06, 0x1a, 0x67, 0xde, 0xfa, 0x25, 0x43, 0xcd, 0x04, + 0x9f, 0x54, 0x2f, 0x96, 0xc5, 0x7c, 0xe6, 0x82, 0xa8, 0xd8, 0x2c, 0xee, 0x5f, 0x6d, 0xba, 0xe0, 0x74, 0x4d, 0xda, + 0x0d, 0xa4, 0x1b, 0x58, 0x34, 0xdc, 0x45, 0x84, 0x45, 0xfb, 0x23, 0x9a, 0x15, 0xcb, 0x0a, 0xa3, 0xc7, 0x4f, 0xe6, + 0xd8, 0x53, 0xc1, 0xb1, 0xb4, 0x40, 0xc2, 0x11, 0xbf, 0x79, 0x8d, 0xd5, 0xa2, 0x6e, 0x65, 0x4c, 0x34, 0x96, 0xa6, + 0xfe, 0x61, 0x21, 0x6d, 0xfb, 0x1a, 0xa8, 0xfe, 0x19, 0x7c, 0x12, 0xdb, 0x19, 0x83, 0xbc, 0xb1, 0x0d, 0x6c, 0xe5, + 0x80, 0x3a, 0x09, 0xa5, 0x27, 0x25, 0xe5, 0x6e, 0x2e, 0x50, 0xaa, 0x34, 0xcd, 0x28, 0xf6, 0xbc, 0x4e, 0x34, 0x5d, + 0xd7, 0x08, 0x27, 0x19, 0x39, 0xd1, 0xe7, 0x8d, 0x82, 0xbc, 0xdd, 0xe6, 0xb2, 0x2f, 0x0d, 0x9c, 0x75, 0xe8, 0x36, + 0x9c, 0xc9, 0x28, 0x69, 0x08, 0x09, 0xda, 0x10, 0x66, 0x6d, 0xb2, 0xd5, 0x22, 0xb4, 0x0d, 0x69, 0x51, 0xf0, 0xc3, + 0xee, 0x1b, 0xcc, 0x23, 0xe8, 0xe9, 0x94, 0xf1, 0x87, 0xd3, 0x6f, 0x2e, 0x1f, 0xee, 0x6c, 0x32, 0x27, 0x02, 0x2d, + 0x3a, 0xcf, 0xa7, 0x87, 0xe2, 0x45, 0x81, 0x20, 0x22, 0x68, 0x0e, 0x6f, 0x09, 0x4e, 0x3e, 0x26, 0xf4, 0x5a, 0xf5, + 0x16, 0x75, 0xf8, 0xc4, 0x83, 0xef, 0xda, 0x3e, 0x21, 0x0e, 0x46, 0x6f, 0xda, 0xf2, 0x28, 0xcd, 0x33, 0x09, 0xf5, + 0xd4, 0x15, 0x03, 0x57, 0x95, 0x8c, 0x1c, 0xbf, 0x59, 0x5f, 0x13, 0x62, 0x45, 0xc0, 0x18, 0x52, 0xbd, 0xc5, 0x18, + 0x1c, 0x32, 0xe6, 0xe5, 0x38, 0x18, 0xd7, 0x6c, 0x8a, 0x2c, 0x6b, 0x43, 0xd9, 0x5d, 0xf9, 0xe9, 0x5c, 0x8c, 0x56, + 0xa1, 0x6c, 0x24, 0x9e, 0xe5, 0x51, 0x8a, 0x71, 0x0f, 0xab, 0x9e, 0x46, 0xc4, 0x96, 0x35, 0x75, 0x3e, 0x21, 0xf4, + 0xd9, 0x83, 0x98, 0xb3, 0x0b, 0x53, 0x16, 0x7a, 0x89, 0xa1, 0x2a, 0xbd, 0x0d, 0x98, 0xbe, 0x15, 0x5b, 0x24, 0xda, + 0x8e, 0x44, 0xa2, 0x98, 0xe0, 0x84, 0x38, 0x6c, 0x45, 0x8e, 0x07, 0xab, 0xbd, 0x83, 0xc9, 0xe8, 0x33, 0x4e, 0x0b, + 0xeb, 0x91, 0x98, 0xfd, 0x31, 0x4e, 0x09, 0x03, 0xce, 0xed, 0x4e, 0x4c, 0x79, 0x37, 0x22, 0x1e, 0x7d, 0x20, 0xd7, + 0x6f, 0xa5, 0x45, 0xb0, 0xc7, 0x13, 0x39, 0x52, 0x15, 0xc5, 0x0a, 0x6e, 0x1f, 0x85, 0x0c, 0x4f, 0x5d, 0x38, 0x9a, + 0xb3, 0x61, 0x3c, 0x10, 0x51, 0x6d, 0x5c, 0xd8, 0xb4, 0x96, 0x81, 0x89, 0xc6, 0x8c, 0xd5, 0xe8, 0xe0, 0x02, 0x5e, + 0xe4, 0xfd, 0xef, 0x0b, 0xa6, 0x69, 0x2d, 0x1f, 0x34, 0x83, 0xfe, 0xbb, 0x32, 0xdb, 0x2c, 0x1f, 0xde, 0xd7, 0xcb, + 0x87, 0xfd, 0x44, 0xce, 0xdc, 0xef, 0xaa, 0xb7, 0x9f, 0xfe, 0x69, 0x21, 0x07, 0xf9, 0xb7, 0xbc, 0x0a, 0x83, 0xab, + 0xad, 0xe3, 0x89, 0x1b, 0x5c, 0x4d, 0x5f, 0x3b, 0xe4, 0xb3, 0x2b, 0x6a, 0xdb, 0x70, 0x91, 0x66, 0x3c, 0xb6, 0x3c, + 0x59, 0x83, 0x15, 0x59, 0x54, 0x2b, 0x58, 0x3b, 0xc9, 0x13, 0xdd, 0xf5, 0xd9, 0x25, 0xb8, 0x27, 0x2f, 0x26, 0x32, + 0x65, 0xf6, 0x01, 0xf8, 0x50, 0x22, 0x7f, 0x62, 0xb7, 0xf0, 0xdf, 0x51, 0x05, 0xdd, 0x41, 0xc1, 0x50, 0x6b, 0x49, + 0xd8, 0xe6, 0x0b, 0x25, 0xbf, 0x96, 0x08, 0x7c, 0x51, 0xbd, 0x85, 0x75, 0x43, 0xca, 0x9f, 0x58, 0x6e, 0x4f, 0xa9, + 0x13, 0x4d, 0xa3, 0x3b, 0x79, 0x1a, 0x7e, 0xe9, 0x92, 0xe0, 0xb2, 0x4d, 0xfd, 0xbf, 0xbe, 0xff, 0xaf, 0xd7, 0x09, + 0x26, 0x21, 0xef, 0x20, 0x1e, 0x2e, 0x5f, 0x0c, 0xae, 0x3a, 0xd2, 0xf9, 0x66, 0x1f, 0xbe, 0x89, 0x86, 0xe5, 0x61, + 0xfd, 0xbc, 0xf7, 0x17, 0x5d, 0x7e, 0x6f, 0xa2, 0xef, 0x60, 0xdb, 0xb4, 0xa1, 0xb4, 0x3d, 0xa4, 0x01, 0x4b, 0x8d, + 0x0b, 0x9a, 0x55, 0xf1, 0xd8, 0x14, 0x16, 0xab, 0x7b, 0x7b, 0x4d, 0x9e, 0x72, 0x6c, 0xfd, 0x87, 0xa0, 0x83, 0xcc, + 0xf1, 0x68, 0xb8, 0x2c, 0xcf, 0xd2, 0x2c, 0xd6, 0x31, 0xe8, 0xee, 0x9d, 0x50, 0x7b, 0xb1, 0x18, 0x5a, 0x1b, 0xb5, + 0x45, 0x92, 0x48, 0xe3, 0x5d, 0x5d, 0x6c, 0xea, 0x21, 0x74, 0x69, 0xeb, 0x34, 0x6d, 0x12, 0xc7, 0x38, 0xd9, 0x96, + 0xbd, 0x06, 0xe8, 0x95, 0xbe, 0xe8, 0x2f, 0x58, 0x7a, 0x6d, 0xbf, 0xd6, 0x47, 0x8c, 0x9b, 0x0d, 0xbc, 0x3f, 0x3a, + 0x65, 0xe2, 0xe2, 0xd0, 0xd8, 0xf9, 0x16, 0x27, 0x0e, 0x7b, 0x7e, 0x8d, 0x4b, 0xaa, 0xa9, 0x97, 0x48, 0x1b, 0xc6, + 0x6a, 0x70, 0x62, 0xe9, 0x5f, 0xdb, 0x58, 0x3c, 0x48, 0x8e, 0x48, 0x65, 0x27, 0x33, 0xf5, 0x72, 0xb4, 0xf0, 0xb7, + 0xae, 0xd6, 0xf5, 0x87, 0xf8, 0xe6, 0x1f, 0x88, 0x9d, 0xa8, 0x9d, 0x5e, 0x34, 0x8a, 0x0c, 0x21, 0xd3, 0x53, 0xfc, + 0x8b, 0x5b, 0x28, 0xc3, 0x69, 0xa2, 0xb3, 0x51, 0xee, 0xed, 0x9d, 0x23, 0x3f, 0x24, 0xbc, 0x71, 0xe7, 0x72, 0x59, + 0x61, 0x60, 0xda, 0x01, 0x36, 0x50, 0x41, 0xc6, 0x81, 0xa5, 0xf8, 0x09, 0x66, 0x97, 0x21, 0xca, 0x6e, 0x99, 0x11, + 0x2f, 0x6d, 0xa7, 0xd2, 0x18, 0xb2, 0xf3, 0x22, 0x77, 0xf1, 0x98, 0x38, 0x36, 0x52, 0x1b, 0x9f, 0x14, 0x10, 0x8e, + 0xf5, 0x61, 0xc8, 0xa6, 0xdb, 0x29, 0x79, 0x6a, 0x39, 0x05, 0x9a, 0x47, 0x7e, 0x8f, 0x88, 0x8e, 0xc6, 0xd6, 0x69, + 0x50, 0x7b, 0x16, 0x1f, 0x2d, 0x17, 0xbe, 0x10, 0x2d, 0xef, 0x02, 0x5b, 0x33, 0xe4, 0x05, 0xab, 0xf7, 0x29, 0x10, + 0xe4, 0x36, 0x6c, 0x7f, 0xcf, 0x97, 0xee, 0xef, 0xac, 0x61, 0x88, 0x79, 0xd0, 0x64, 0xcc, 0xd7, 0x1c, 0x56, 0x84, + 0x4d, 0x59, 0xaf, 0x84, 0x7d, 0x1d, 0x9c, 0xba, 0x1e, 0x4e, 0x52, 0xe9, 0xb9, 0x1a, 0xcd, 0xbb, 0x74, 0xa4, 0x34, + 0x65, 0x8a, 0x36, 0xa6, 0x77, 0x7d, 0x4e, 0x36, 0x47, 0x57, 0x74, 0x3c, 0xeb, 0xa0, 0x14, 0x1e, 0x3e, 0xb5, 0xc1, + 0xa9, 0x7b, 0x46, 0x2f, 0xe4, 0xd7, 0x20, 0xbd, 0xa6, 0x45, 0x15, 0xf4, 0x69, 0xf5, 0x83, 0x17, 0x1f, 0xbf, 0x5b, + 0x25, 0xd0, 0xd8, 0xec, 0x93, 0x0d, 0xc1, 0x59, 0x1e, 0x80, 0x1f, 0x16, 0xf8, 0xff, 0x80, 0x3e, 0x20, 0x66, 0x73, + 0xd3, 0xfe, 0x30, 0x87, 0xf2, 0x4d, 0xf3, 0xf5, 0x42, 0x98, 0x16, 0x9d, 0x1f, 0x7c, 0xa8, 0x1b, 0x04, 0xd8, 0x64, + 0xcf, 0xff, 0x2b, 0xc8, 0x01, 0x82, 0x09, 0xe7, 0xef, 0xe3, 0x7a, 0x38, 0xbf, 0xd1, 0xcf, 0x11, 0x99, 0x3b, 0xdc, + 0xcc, 0xde, 0x4d, 0xbb, 0xf4, 0xaa, 0x2c, 0x36, 0x92, 0xd7, 0xc2, 0xa5, 0x8d, 0xcb, 0x69, 0x1b, 0xd1, 0x92, 0x2d, + 0x12, 0x2c, 0x7c, 0x4b, 0x00, 0x70, 0xa4, 0x7b, 0xa8, 0x6d, 0xf3, 0xbf, 0x28, 0xb6, 0x18, 0x2b, 0xb8, 0x9d, 0xd6, + 0xae, 0xae, 0xfd, 0xd0, 0x76, 0x9b, 0x65, 0x0c, 0x30, 0x7a, 0xb0, 0x33, 0x57, 0x19, 0x65, 0xb9, 0x43, 0x9c, 0x3d, + 0x5c, 0x19, 0xb5, 0xcb, 0x98, 0x70, 0x54, 0xeb, 0x66, 0xb5, 0xa7, 0x02, 0x02, 0x35, 0x62, 0xb1, 0x83, 0xae, 0xcc, + 0x8a, 0x48, 0x3a, 0x7b, 0x6f, 0xc6, 0xf0, 0x6e, 0x83, 0xc5, 0x65, 0xcc, 0x88, 0xe4, 0x8d, 0x81, 0x36, 0xb7, 0xe2, + 0xb1, 0x77, 0x7a, 0xf3, 0xe0, 0xfe, 0xf6, 0xe6, 0xf2, 0xe6, 0x76, 0x89, 0xb7, 0x89, 0x2e, 0xd5, 0x1a, 0x99, 0x53, + 0x7b, 0xbe, 0x96, 0x8c, 0x76, 0xc8, 0xf7, 0xb6, 0xd5, 0xba, 0x84, 0x16, 0x49, 0x80, 0x48, 0x2b, 0x24, 0xab, 0xea, + 0x94, 0x01, 0x0e, 0x9d, 0xa6, 0x61, 0xdb, 0xe3, 0x5e, 0x52, 0x28, 0xd8, 0xca, 0x84, 0xa3, 0x3c, 0x3b, 0xf5, 0x54, + 0x23, 0x73, 0xf6, 0x4c, 0x70, 0x5d, 0x2c, 0x24, 0x22, 0xcf, 0xd7, 0x9c, 0x2c, 0x1e, 0x01, 0xcc, 0x9c, 0xdf, 0x4f, + 0xf3, 0x14, 0x97, 0x38, 0x6c, 0xaa, 0x51, 0x46, 0x5f, 0x6f, 0x09, 0xa1, 0xa1, 0x78, 0x39, 0x14, 0xf8, 0x7a, 0xc2, + 0xf5, 0x5d, 0xa4, 0x23, 0x78, 0x42, 0xc7, 0x49, 0xf2, 0x4b, 0x43, 0x66, 0xdf, 0x6f, 0x9a, 0xc9, 0x36, 0xea, 0x8a, + 0xbe, 0x6e, 0xc9, 0x5f, 0x4f, 0xc6, 0x69, 0x6d, 0x70, 0xe9, 0xf8, 0x6f, 0xa0, 0x7b, 0x41, 0x8c, 0x83, 0x85, 0x33, + 0x88, 0xa3, 0xf0, 0x2b, 0xb6, 0x20, 0x2f, 0x3a, 0xef, 0xf9, 0x73, 0x02, 0x70, 0xb9, 0x5b, 0x06, 0x17, 0x26, 0x96, + 0x79, 0xac, 0xcb, 0x18, 0xd9, 0xc9, 0x42, 0x4e, 0x8d, 0xda, 0x57, 0x44, 0xdb, 0x9a, 0x09, 0xec, 0x47, 0x7c, 0x79, + 0x9c, 0x4a, 0x5c, 0x9b, 0x31, 0x8b, 0x8d, 0x18, 0xbc, 0xa9, 0x3c, 0x28, 0x36, 0x98, 0x85, 0xe7, 0xfb, 0xd6, 0x10, + 0x52, 0x6b, 0xd2, 0x61, 0xb0, 0x53, 0x5e, 0xc4, 0x36, 0x70, 0xca, 0x2e, 0x6e, 0xc7, 0x5a, 0x8c, 0x5f, 0xd7, 0x78, + 0xc5, 0x58, 0x47, 0x2d, 0x38, 0xce, 0x7b, 0xcb, 0x61, 0x9b, 0x60, 0x40, 0xff, 0xb1, 0x13, 0x34, 0xf3, 0xca, 0x9d, + 0x6c, 0x1d, 0x10, 0xe4, 0x6c, 0xc8, 0x12, 0x41, 0x0d, 0xbf, 0x26, 0x9b, 0x36, 0x96, 0x17, 0x9d, 0xe3, 0xfb, 0x8c, + 0x69, 0x47, 0xfb, 0x2c, 0x72, 0x11, 0x25, 0xe3, 0x57, 0x12, 0xa4, 0x73, 0x65, 0x37, 0x72, 0x77, 0x23, 0xf2, 0xa0, + 0x4d, 0x49, 0xe8, 0xad, 0x3d, 0x03, 0x37, 0x3c, 0x37, 0x5f, 0xa9, 0x9a, 0xa3, 0x2c, 0x26, 0x02, 0x83, 0x22, 0x8c, + 0x84, 0xf5, 0x57, 0xff, 0x2b, 0x70, 0x50, 0x77, 0x7c, 0x67, 0xbd, 0xa0, 0xe9, 0x01, 0xbb, 0x1b, 0x75, 0x1d, 0x4a, + 0xab, 0x04, 0x05, 0x11, 0x32, 0x17, 0x86, 0x49, 0xdc, 0xbf, 0xef, 0xde, 0xdd, 0xfd, 0xfe, 0x58, 0x94, 0x5d, 0xdd, + 0x2d, 0xf6, 0x63, 0x4b, 0x3e, 0x9b, 0xb1, 0x91, 0xf9, 0x6a, 0xf0, 0x81, 0x8e, 0x49, 0xb7, 0x40, 0xfe, 0x21, 0xb3, + 0xe7, 0x61, 0x9b, 0x41, 0x23, 0xd1, 0xb5, 0x43, 0x32, 0x20, 0x07, 0x3a, 0xe4, 0x93, 0x0d, 0x3c, 0x97, 0x47, 0xdb, + 0xbc, 0xbb, 0xbc, 0xfe, 0x73, 0xb9, 0xf7, 0xa1, 0x2b, 0xea, 0x83, 0xc5, 0x9a, 0x59, 0xfe, 0xce, 0xc9, 0x22, 0x3b, + 0x70, 0xdb, 0xcd, 0x97, 0xe1, 0x14, 0xaf, 0x66, 0xcb, 0x7f, 0xf0, 0xff, 0xdb, 0xe9, 0xc2, 0x9b, 0x3d, 0xe9, 0x44, + 0xe3, 0x98, 0xe3, 0x96, 0xf7, 0xec, 0x4c, 0xbf, 0x6b, 0x33, 0x13, 0xd2, 0x83, 0x51, 0x34, 0xdb, 0x25, 0x9d, 0xc0, + 0xa8, 0x2e, 0x79, 0xb8, 0xb1, 0x4d, 0x29, 0x53, 0x26, 0x33, 0xd2, 0x42, 0x25, 0x73, 0x2b, 0xd4, 0xb9, 0xa0, 0x48, + 0xf3, 0x85, 0x01, 0x12, 0x75, 0x9b, 0xd3, 0xda, 0x95, 0x38, 0xcd, 0xfb, 0xe6, 0xd8, 0xce, 0xc8, 0x16, 0x25, 0xa0, + 0x4d, 0x99, 0x13, 0x9a, 0x4f, 0x9a, 0x42, 0xdd, 0xdd, 0xce, 0x74, 0x46, 0x6f, 0x93, 0x56, 0x75, 0xda, 0xd7, 0x77, + 0xfd, 0x67, 0x6b, 0xe4, 0x3d, 0x4d, 0x5a, 0xdb, 0x82, 0x74, 0x46, 0x72, 0x6a, 0x3a, 0x9f, 0x06, 0xca, 0xd0, 0x16, + 0x1e, 0x67, 0xbe, 0xf5, 0x22, 0x60, 0x4d, 0x96, 0xcc, 0xa6, 0xe8, 0x6d, 0xa9, 0xa8, 0x5b, 0xec, 0xd9, 0xbd, 0x93, + 0xc9, 0xda, 0xde, 0x1e, 0x10, 0x99, 0x62, 0x58, 0x7b, 0x44, 0xd8, 0x2e, 0xa2, 0x77, 0x00, 0xc7, 0x7d, 0xd2, 0x73, + 0xf8, 0xd4, 0xc8, 0xd7, 0x45, 0xf0, 0xa8, 0x94, 0x36, 0x3f, 0x38, 0x7b, 0xd1, 0x1d, 0x1b, 0x8c, 0x97, 0x0e, 0xb7, + 0xa0, 0xe6, 0xba, 0x6c, 0xba, 0xc6, 0xdd, 0xfd, 0xdf, 0xfe, 0xb6, 0xb5, 0xf0, 0x07, 0x8e, 0x0f, 0x32, 0xbb, 0xa1, + 0xbb, 0xb7, 0xfc, 0xa2, 0x8b, 0xb9, 0xf8, 0xb2, 0x9f, 0x66, 0x67, 0x46, 0xb9, 0x29, 0xc8, 0x4e, 0x45, 0xda, 0x63, + 0x12, 0x15, 0x03, 0xd8, 0xd3, 0x4c, 0x96, 0x64, 0x40, 0x0d, 0xab, 0x57, 0xdf, 0xd2, 0xa9, 0x3b, 0x35, 0x67, 0x6a, + 0xcf, 0x34, 0xf6, 0xb9, 0xf0, 0x88, 0xdd, 0x17, 0x6b, 0xd7, 0x69, 0x6b, 0x98, 0x82, 0xd3, 0x8d, 0x2f, 0xfe, 0xf8, + 0xcb, 0x86, 0x40, 0x8d, 0x51, 0xae, 0xf9, 0xaf, 0xb5, 0x03, 0x08, 0xde, 0xdf, 0x45, 0x98, 0x0b, 0xc8, 0xac, 0xba, + 0x7a, 0xaa, 0xf7, 0x23, 0xdb, 0xcd, 0x43, 0x11, 0x3b, 0x67, 0xbb, 0x17, 0x4f, 0x01, 0x14, 0x99, 0x25, 0x85, 0x9c, + 0xab, 0x36, 0xf4, 0xd2, 0x78, 0x97, 0x1e, 0xf6, 0xd3, 0x27, 0x98, 0x93, 0x43, 0x98, 0x3b, 0x08, 0x9a, 0xcd, 0x20, + 0x81, 0x14, 0xb9, 0x20, 0x66, 0x3f, 0x07, 0x47, 0x58, 0x23, 0x95, 0xc1, 0x34, 0x32, 0x46, 0xbb, 0xe7, 0xca, 0x58, + 0x30, 0x4f, 0x7b, 0x5f, 0xe9, 0xe2, 0xae, 0x77, 0xa0, 0x3a, 0x7b, 0x48, 0xca, 0xcd, 0xfa, 0x02, 0x23, 0xa0, 0xd3, + 0x83, 0x56, 0x3f, 0xfd, 0x39, 0x85, 0x6b, 0xd8, 0x2b, 0xbb, 0x8d, 0x95, 0xe8, 0x0e, 0x20, 0x07, 0xe2, 0x12, 0x4e, + 0x59, 0x7b, 0x9e, 0xfa, 0x77, 0xbf, 0xfe, 0x1e, 0xf9, 0x8b, 0xf3, 0x72, 0xe5, 0x87, 0x95, 0x6f, 0x6d, 0x61, 0x0b, + 0x94, 0x5e, 0xe3, 0xde, 0x2e, 0x31, 0x8d, 0x63, 0x69, 0xfa, 0x96, 0xf3, 0x89, 0x5e, 0xe1, 0x89, 0x0d, 0x54, 0x22, + 0x3c, 0xe2, 0x4a, 0x79, 0x68, 0xa3, 0xd9, 0xec, 0xfa, 0x6e, 0xee, 0x02, 0xd7, 0xff, 0xc2, 0x17, 0xd6, 0xfa, 0xed, + 0x7b, 0x1c, 0x26, 0x23, 0x82, 0x37, 0xfa, 0xa3, 0x30, 0x31, 0x42, 0xc9, 0xd9, 0xc9, 0xb0, 0xff, 0x30, 0x3a, 0x7a, + 0xe8, 0x3c, 0xfa, 0x19, 0x13, 0xa5, 0x66, 0x7c, 0xe7, 0x0f, 0x73, 0x39, 0x93, 0xe7, 0x52, 0xb1, 0x40, 0x6b, 0x12, + 0x01, 0x51, 0x31, 0x2a, 0x3a, 0x4c, 0x4e, 0xe3, 0x37, 0x94, 0xe7, 0x0d, 0x0b, 0xe2, 0x22, 0x08, 0x8a, 0x2f, 0x50, + 0xf6, 0x67, 0xd7, 0x0f, 0x5c, 0xdd, 0xb0, 0x63, 0x30, 0x43, 0x3d, 0xd1, 0xd0, 0x6a, 0x42, 0x90, 0xb1, 0xb5, 0x52, + 0x05, 0x01, 0x4a, 0x47, 0x42, 0x8a, 0x41, 0xcd, 0xac, 0xe5, 0x31, 0xe9, 0xaf, 0x5b, 0x06, 0xef, 0x8d, 0x8a, 0xe3, + 0x32, 0x5a, 0xb7, 0x6d, 0xd5, 0x70, 0x6d, 0xca, 0x38, 0x7a, 0x01, 0xa6, 0xc3, 0xce, 0x49, 0x06, 0x1a, 0x46, 0xfc, + 0xaf, 0x81, 0xe1, 0x42, 0x56, 0x9b, 0x6e, 0x17, 0x87, 0x76, 0xed, 0xc6, 0x7c, 0x22, 0xd8, 0x5f, 0x36, 0x4c, 0x23, + 0xcf, 0x7b, 0xfc, 0x32, 0xd8, 0x12, 0xef, 0x59, 0xf8, 0x69, 0x1f, 0x94, 0x9d, 0xaf, 0xc1, 0xca, 0xf8, 0xd9, 0x7c, + 0xbe, 0xfb, 0x72, 0xf5, 0x1d, 0x86, 0x34, 0x17, 0x05, 0x62, 0xcd, 0xeb, 0xe7, 0xf8, 0x54, 0xba, 0x1c, 0x27, 0xc2, + 0xfa, 0x44, 0x34, 0x6e, 0xd6, 0x95, 0x0b, 0x3f, 0xf2, 0xb6, 0xc2, 0x7d, 0xfd, 0x06, 0x3b, 0x28, 0x9f, 0x7c, 0xbf, + 0x1b, 0x0b, 0xc1, 0xd3, 0xa6, 0x24, 0xe4, 0x39, 0xd0, 0x5b, 0xb7, 0x5b, 0x45, 0x4b, 0xbf, 0x96, 0x87, 0x66, 0x99, + 0x87, 0xf3, 0xc9, 0x98, 0x80, 0x88, 0xe0, 0x40, 0xce, 0x42, 0xd1, 0xf4, 0x22, 0x4c, 0xba, 0x08, 0x3e, 0x35, 0x72, + 0x8e, 0x38, 0x9c, 0xc6, 0xfd, 0xae, 0x30, 0xfd, 0x4d, 0x9e, 0x74, 0x19, 0xfb, 0xe9, 0xef, 0xdb, 0x75, 0x11, 0xd2, + 0xef, 0x79, 0x36, 0xfb, 0x2f, 0x34, 0x42, 0xfe, 0x36, 0x8a, 0x8d, 0xc7, 0x28, 0x6f, 0x14, 0x95, 0x08, 0x11, 0xed, + 0x92, 0x48, 0x98, 0xcb, 0xfb, 0x55, 0xc2, 0xc7, 0xaf, 0xe8, 0x85, 0x33, 0xc7, 0x40, 0xa3, 0x8b, 0x1e, 0x4f, 0xd8, + 0xd8, 0xfd, 0x79, 0x1a, 0x63, 0x81, 0x35, 0xc3, 0x9f, 0x05, 0x80, 0x74, 0xda, 0xad, 0x00, 0xd1, 0x86, 0x26, 0xc8, + 0x70, 0x5d, 0xe7, 0x1a, 0xd6, 0x33, 0x87, 0xe0, 0xf3, 0x46, 0xc8, 0x0d, 0xf1, 0x1c, 0x82, 0x82, 0x7b, 0x70, 0x60, + 0x89, 0xe2, 0x9f, 0x59, 0x47, 0x3d, 0x77, 0x98, 0x58, 0xd2, 0x21, 0x0d, 0x89, 0x84, 0x2c, 0xd7, 0xdd, 0xab, 0x51, + 0x01, 0x3e, 0x66, 0xb2, 0x16, 0x54, 0x3c, 0x9b, 0x4d, 0x7e, 0x35, 0xbf, 0x13, 0xa5, 0xd7, 0xd1, 0x91, 0x36, 0x79, + 0x37, 0x58, 0x82, 0xce, 0xdf, 0x19, 0x05, 0x40, 0x2f, 0x55, 0x5a, 0x05, 0x66, 0x42, 0xd8, 0xc4, 0x86, 0xef, 0x18, + 0x26, 0xa3, 0xcd, 0x9c, 0xdf, 0x64, 0x36, 0x0b, 0x13, 0xc8, 0x60, 0x68, 0x15, 0x40, 0x96, 0xed, 0x11, 0xee, 0x52, + 0xda, 0x07, 0xd4, 0xbb, 0xb8, 0xec, 0x73, 0xf4, 0x39, 0x8d, 0x24, 0xec, 0x5e, 0xaa, 0x31, 0x41, 0x5c, 0x45, 0x4b, + 0xcc, 0xb1, 0xb5, 0xe4, 0xd0, 0x42, 0xf4, 0x8e, 0xd0, 0x61, 0x77, 0x97, 0x19, 0x6c, 0x95, 0xd8, 0x7f, 0x78, 0xac, + 0x64, 0x0e, 0x9e, 0xa5, 0x67, 0xc2, 0xd6, 0x88, 0x1d, 0x27, 0x0d, 0x17, 0x24, 0x88, 0x58, 0x08, 0x4f, 0xe7, 0x03, + 0x71, 0x46, 0xb5, 0x88, 0xff, 0xa3, 0xe3, 0x04, 0xfa, 0x4a, 0xa2, 0x88, 0xec, 0x46, 0xa7, 0xfd, 0x1c, 0x0a, 0x18, + 0x89, 0x23, 0x18, 0x85, 0x9f, 0xa1, 0xa4, 0xbb, 0x4c, 0x18, 0xa0, 0x5c, 0x48, 0xec, 0xf0, 0x84, 0x94, 0x98, 0x12, + 0x6a, 0xa4, 0x07, 0x09, 0xc9, 0xcb, 0x22, 0x00, 0x75, 0x08, 0xda, 0xa1, 0xf9, 0x2b, 0x43, 0x03, 0x0f, 0x2e, 0x5f, + 0xa1, 0x24, 0x32, 0x39, 0x8f, 0x51, 0x48, 0x72, 0xeb, 0xbc, 0xcb, 0x96, 0xb4, 0xb0, 0xbf, 0xd5, 0x28, 0xaa, 0x22, + 0x59, 0xdd, 0xcb, 0x1a, 0xe1, 0xd9, 0x9a, 0x49, 0xb0, 0x3e, 0xb9, 0x8e, 0xb5, 0x90, 0x93, 0x09, 0x4c, 0x8b, 0xf6, + 0x6f, 0xab, 0xe4, 0x22, 0xff, 0x4a, 0xcf, 0xe6, 0x85, 0xdf, 0x85, 0xae, 0x7a, 0xa9, 0x3f, 0x93, 0x76, 0xd0, 0x99, + 0x05, 0x47, 0x6a, 0x99, 0x8d, 0x3b, 0xe3, 0xf3, 0xa2, 0x1b, 0xd6, 0x5f, 0x26, 0x55, 0x12, 0xbd, 0xf0, 0x6b, 0x68, + 0x56, 0x61, 0x41, 0xf9, 0x0c, 0x62, 0x5e, 0x23, 0x9a, 0x8d, 0x36, 0x8c, 0x14, 0xe0, 0xc5, 0xe7, 0xe5, 0x39, 0x77, + 0xa0, 0x32, 0x2a, 0xcc, 0xe2, 0x52, 0x49, 0xf0, 0xbd, 0x70, 0xec, 0xd0, 0x3e, 0xd3, 0xa6, 0xc8, 0xde, 0x97, 0x40, + 0x27, 0x8f, 0x68, 0x03, 0x06, 0xee, 0x10, 0x6a, 0x52, 0xa0, 0xb3, 0x71, 0xb8, 0x45, 0xed, 0x2b, 0x33, 0xba, 0x2a, + 0x45, 0xd1, 0x3c, 0xcd, 0x18, 0xa4, 0xba, 0x55, 0x0b, 0x19, 0x19, 0xed, 0xa0, 0xcb, 0xe8, 0xa0, 0x84, 0x8f, 0xe5, + 0xac, 0xf0, 0x78, 0xc8, 0x70, 0x61, 0x92, 0x6c, 0x80, 0x4f, 0x8f, 0xfe, 0xef, 0x0f, 0xce, 0xa9, 0xa5, 0xe3, 0x91, + 0xbc, 0x62, 0x76, 0xc4, 0xd2, 0x4c, 0x41, 0xea, 0x72, 0x92, 0x22, 0x75, 0x8b, 0xa9, 0x65, 0x71, 0xb0, 0x1c, 0x55, + 0x44, 0x9d, 0xde, 0x9e, 0x0a, 0x0a, 0x07, 0x06, 0x2d, 0x8c, 0x34, 0x31, 0xdf, 0x2c, 0x59, 0x7b, 0xa5, 0xe8, 0xde, + 0xc9, 0x08, 0x55, 0xaa, 0x1b, 0x5e, 0xb9, 0x6c, 0xf0, 0xda, 0xdc, 0x7f, 0x90, 0xbf, 0x8b, 0x25, 0xb7, 0x72, 0x0c, + 0x66, 0x23, 0xcc, 0x89, 0xe8, 0xcd, 0x6b, 0x25, 0xe3, 0x6d, 0x5f, 0xcb, 0x70, 0x40, 0xe9, 0x58, 0x9a, 0xa5, 0xab, + 0x66, 0xe7, 0x9a, 0x5f, 0x42, 0x2e, 0xd8, 0x81, 0x98, 0x74, 0x66, 0xad, 0x16, 0xe6, 0xd7, 0x5e, 0x79, 0xe6, 0x48, + 0xcf, 0x49, 0xd0, 0x70, 0xbb, 0xc8, 0x5a, 0x83, 0x58, 0x6f, 0x99, 0xd3, 0x61, 0x4b, 0x5e, 0xbb, 0xb0, 0x29, 0x86, + 0xe1, 0xf8, 0xcc, 0xec, 0x13, 0xcc, 0xf6, 0x4c, 0xb4, 0xc7, 0xfe, 0x67, 0x36, 0x0b, 0x6d, 0x1a, 0x12, 0xae, 0xb8, + 0xf2, 0x41, 0x8a, 0xab, 0x89, 0x3c, 0x9c, 0xc7, 0x8c, 0xde, 0x5c, 0x71, 0x1d, 0x73, 0x7b, 0xb2, 0x17, 0x84, 0x99, + 0x03, 0xfb, 0x6e, 0xfc, 0x30, 0xaa, 0x12, 0x67, 0x52, 0x96, 0x2d, 0xc5, 0x52, 0x0c, 0xf2, 0xbc, 0x0e, 0x71, 0x28, + 0x95, 0x0b, 0x62, 0x57, 0x24, 0xb2, 0xed, 0x59, 0xb2, 0x78, 0xef, 0xfa, 0x69, 0x05, 0xd5, 0x4b, 0x7c, 0x24, 0xbb, + 0x3d, 0x13, 0xda, 0x72, 0x0b, 0xb2, 0x83, 0xae, 0x83, 0x3b, 0xd2, 0xa4, 0x04, 0x6f, 0x8a, 0x32, 0xfa, 0x4b, 0x1d, + 0x29, 0x15, 0x2d, 0xe6, 0x82, 0x99, 0x89, 0x14, 0xb3, 0xb5, 0x4d, 0x42, 0x80, 0x34, 0x49, 0x7b, 0x89, 0x2c, 0x6a, + 0x9e, 0x03, 0x86, 0x6d, 0x61, 0xc8, 0x3d, 0x5f, 0x02, 0x8c, 0xfa, 0x3e, 0x0f, 0x27, 0x73, 0x84, 0x4d, 0xa2, 0xe4, + 0xef, 0xb5, 0xb6, 0x5d, 0xc3, 0xd6, 0xd1, 0x3f, 0x34, 0x84, 0xaf, 0xa6, 0xb2, 0x86, 0x25, 0xcc, 0xaa, 0x10, 0xde, + 0x2a, 0x0d, 0x50, 0xa4, 0x2c, 0xeb, 0xc3, 0x92, 0x80, 0x09, 0x93, 0x82, 0x76, 0x88, 0xe5, 0x2a, 0x8d, 0xd9, 0x69, + 0x11, 0x5b, 0x73, 0x2f, 0x5b, 0x1c, 0x7f, 0xf5, 0xfb, 0x17, 0x47, 0xa4, 0x72, 0x3b, 0x7f, 0xed, 0x20, 0x3b, 0x60, + 0x64, 0xa1, 0x3f, 0x5b, 0x76, 0x74, 0xee, 0xbf, 0x9e, 0xe2, 0x77, 0x09, 0xfc, 0x3d, 0x72, 0x1c, 0x88, 0x87, 0xdc, + 0xb5, 0x9e, 0x0d, 0x54, 0xf7, 0xb8, 0xac, 0xee, 0x7b, 0xe5, 0x1c, 0xa9, 0x70, 0x12, 0x22, 0xdd, 0xe5, 0xb0, 0x04, + 0xab, 0xf7, 0xd7, 0x90, 0x6c, 0x0a, 0xa6, 0x89, 0xc2, 0x46, 0x59, 0xf3, 0xd5, 0x61, 0xb8, 0xd8, 0x60, 0x05, 0x97, + 0x70, 0x30, 0xf4, 0xda, 0x9b, 0x39, 0xbd, 0xd5, 0xec, 0x8e, 0x41, 0x13, 0xd9, 0x74, 0x77, 0x90, 0x8a, 0xed, 0x0d, + 0x09, 0x4f, 0xff, 0x73, 0x23, 0x07, 0x04, 0xc0, 0xd2, 0xac, 0x90, 0x64, 0xf0, 0x55, 0xce, 0x49, 0x26, 0x53, 0x4b, + 0xcd, 0x6e, 0x2b, 0x05, 0x92, 0xbd, 0xf0, 0xdf, 0xa2, 0xba, 0x19, 0xed, 0xa7, 0xe4, 0x0e, 0xfa, 0x26, 0x3b, 0x34, + 0xf0, 0xc6, 0x9c, 0xf6, 0xde, 0xd0, 0xc4, 0xe2, 0x2b, 0x80, 0x88, 0xc3, 0x01, 0x99, 0x78, 0xc6, 0xc2, 0x12, 0x90, + 0x4e, 0xf5, 0x30, 0x88, 0x09, 0x57, 0x91, 0x16, 0x9c, 0x99, 0x7c, 0xf7, 0x0e, 0x53, 0xe4, 0xd3, 0x3e, 0x83, 0xc6, + 0xec, 0xa0, 0x3a, 0x5d, 0x7b, 0x45, 0x87, 0x7e, 0x9d, 0x39, 0x4b, 0x24, 0x3d, 0xe9, 0xcb, 0x8d, 0x63, 0x99, 0x20, + 0x2d, 0x62, 0xca, 0x67, 0x2a, 0xe8, 0x73, 0xa6, 0xb7, 0x7d, 0x13, 0x78, 0x73, 0xd4, 0xb4, 0x32, 0x2a, 0x07, 0xb8, + 0x49, 0xba, 0x29, 0x83, 0x51, 0x91, 0xac, 0x87, 0x01, 0x2a, 0x41, 0x4e, 0x74, 0x1a, 0x1b, 0x6a, 0x8f, 0xc3, 0x20, + 0x71, 0x1b, 0x50, 0xef, 0x35, 0x33, 0x3a, 0x1a, 0xdd, 0xe7, 0xbf, 0xf0, 0xff, 0xc3, 0xf7, 0x7f, 0x16, 0x8d, 0x93, + 0x5e, 0xa8, 0xac, 0xb4, 0x40, 0xaa, 0x19, 0x81, 0x7e, 0x8f, 0x3b, 0xaf, 0xee, 0x61, 0x85, 0xd1, 0xa5, 0x9d, 0xdb, + 0xee, 0xf4, 0xb8, 0x7f, 0x7d, 0x0a, 0x3f, 0x7f, 0xf7, 0x75, 0xcd, 0xaf, 0xf4, 0x5e, 0x9e, 0x29, 0x87, 0xae, 0x71, + 0x23, 0x92, 0x04, 0xc6, 0xab, 0x6b, 0x14, 0x5a, 0x81, 0x2c, 0xbf, 0x40, 0xc1, 0xc7, 0xb7, 0x46, 0xbb, 0x4f, 0xbb, + 0x22, 0xc8, 0x84, 0xbc, 0x55, 0x10, 0xd6, 0x36, 0x1c, 0x0f, 0x6c, 0x16, 0x5d, 0xd0, 0xfb, 0x1d, 0xba, 0x86, 0x9f, + 0x32, 0x5f, 0x5e, 0xcd, 0x05, 0xdf, 0xe0, 0x74, 0x02, 0xba, 0xe5, 0xce, 0x7b, 0x15, 0xd8, 0x21, 0x67, 0xfd, 0xc8, + 0xe8, 0xde, 0x29, 0x64, 0xa3, 0xc4, 0xb4, 0x63, 0xa1, 0xed, 0xda, 0xa9, 0xdb, 0x21, 0x1e, 0xdf, 0x28, 0x05, 0x3c, + 0x3a, 0x6c, 0x6e, 0x9c, 0x34, 0x52, 0xb0, 0x6a, 0x6f, 0x7d, 0x3d, 0xb7, 0xb9, 0x15, 0xcb, 0x07, 0x5b, 0x6f, 0x20, + 0x09, 0xe9, 0xc6, 0x91, 0x33, 0xa5, 0x5e, 0x1b, 0xda, 0xa7, 0xd9, 0xca, 0xcd, 0x4d, 0xd2, 0x71, 0xaf, 0x9e, 0xc6, + 0x09, 0xe3, 0x38, 0x97, 0x54, 0x26, 0x4e, 0x7c, 0x89, 0xf9, 0xf2, 0x44, 0x6c, 0xa6, 0x25, 0x35, 0xba, 0xca, 0x75, + 0x67, 0x4a, 0x14, 0xa4, 0xe8, 0xf9, 0xdb, 0x2c, 0xe1, 0x8a, 0x6b, 0xc2, 0x33, 0x03, 0x35, 0xa1, 0x75, 0xee, 0x5e, + 0x66, 0x78, 0x70, 0x89, 0xfb, 0xe3, 0xc4, 0xbf, 0x50, 0x3d, 0xb1, 0xe5, 0x57, 0x94, 0xb1, 0xf1, 0x66, 0xdd, 0xdd, + 0xbf, 0xa7, 0xc4, 0x7d, 0x7e, 0x2a, 0x8e, 0xa2, 0xf5, 0xf6, 0xfd, 0xe4, 0x2a, 0xd6, 0xf3, 0xa9, 0xe0, 0x1b, 0x45, + 0x00, 0x9c, 0xf4, 0x68, 0x59, 0xee, 0xb4, 0x1a, 0x7c, 0x06, 0x02, 0x22, 0xdf, 0x9d, 0xb3, 0x6b, 0x7f, 0x3c, 0x25, + 0xd3, 0x66, 0x34, 0x97, 0x97, 0x41, 0xb3, 0xaf, 0x11, 0x00, 0xc8, 0x69, 0xcd, 0xc8, 0xc7, 0xf9, 0x10, 0x06, 0x97, + 0xcb, 0x24, 0x73, 0xbb, 0x05, 0x70, 0x01, 0xb9, 0x52, 0xbe, 0x5a, 0x57, 0x31, 0xd4, 0xcc, 0x8b, 0x70, 0x7c, 0xb5, + 0x97, 0x4f, 0xd1, 0x4e, 0x58, 0xda, 0xab, 0xb9, 0x8c, 0x04, 0xd6, 0xab, 0x0e, 0x11, 0x7a, 0xb2, 0x35, 0xf2, 0xf8, + 0x32, 0xf3, 0xdd, 0x96, 0x03, 0x6a, 0x07, 0x96, 0x57, 0x5b, 0xcd, 0x49, 0xd3, 0x6e, 0x79, 0x34, 0xdb, 0x33, 0xaa, + 0xa1, 0x60, 0x39, 0x77, 0xfb, 0x91, 0x1d, 0x67, 0x4b, 0x75, 0x35, 0xb7, 0xfa, 0x82, 0xb0, 0x2d, 0x16, 0xc8, 0xc7, + 0x11, 0xb0, 0xa6, 0x13, 0x5a, 0x92, 0x39, 0x28, 0x4d, 0x3b, 0x0a, 0x40, 0x07, 0xf0, 0x64, 0x1a, 0xf7, 0x94, 0xf4, + 0xdf, 0x81, 0xb7, 0x6b, 0x7d, 0xd2, 0xa1, 0x18, 0x05, 0xcf, 0x3f, 0x9c, 0x01, 0x38, 0xfd, 0xde, 0xda, 0xfb, 0xd9, + 0xbb, 0x35, 0xa0, 0xe6, 0x5a, 0xae, 0x1c, 0xc1, 0x7f, 0x2a, 0x32, 0x65, 0x45, 0xcc, 0xb7, 0x23, 0x54, 0xaa, 0xb0, + 0xdc, 0xab, 0x80, 0xbf, 0xdf, 0x0d, 0xb7, 0xff, 0xaf, 0x8a, 0xc9, 0x3d, 0xfc, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, + 0x6d, 0x58, 0x5b, 0xee, 0x7f, 0x6b, 0xc0, 0xf4, 0xbb, 0x02, 0x35, 0xc1, 0xf6, 0x6f, 0xdf, 0xb9, 0x24, 0x97, 0xf5, + 0xe1, 0xde, 0xc9, 0x4a, 0x0f, 0x53, 0x7a, 0x30, 0xf0, 0x08, 0xff, 0x7f, 0x96, 0x81, 0xec, 0x05, 0x85, 0xc9, 0xc2, + 0xfe, 0xfb, 0x59, 0x2a, 0xa0, 0x9f, 0x12, 0x65, 0x8d, 0x23, 0xde, 0xd6, 0x7e, 0x5a, 0xa3, 0x1f, 0x23, 0xa2, 0x58, + 0xa7, 0x82, 0x7e, 0x55, 0x9f, 0x27, 0x88, 0xef, 0x7d, 0x5c, 0xfa, 0x12, 0x2a, 0x86, 0x07, 0xca, 0xde, 0x5d, 0xc1, + 0xf9, 0x91, 0x6e, 0xc7, 0x45, 0xa1, 0xf9, 0x53, 0xe5, 0x8f, 0xdb, 0x7a, 0xae, 0xf2, 0x7e, 0x45, 0xda, 0x37, 0xb9, + 0xf5, 0x57, 0x51, 0xd2, 0xbd, 0x20, 0x8b, 0x2c, 0x16, 0x77, 0xe7, 0x22, 0xf9, 0xc4, 0xd9, 0x03, 0xdb, 0x39, 0x9b, + 0x47, 0x78, 0x32, 0xa7, 0xb1, 0x48, 0x44, 0x67, 0xe1, 0xf5, 0x40, 0x93, 0x8a, 0x5d, 0x1f, 0xe0, 0xbb, 0x0f, 0xfc, + 0xe4, 0x94, 0x2f, 0x7e, 0xf2, 0x57, 0x3e, 0x46, 0x8f, 0xf5, 0x29, 0x9b, 0x60, 0xf0, 0x4a, 0x97, 0x53, 0x3d, 0x7b, + 0x79, 0x68, 0x48, 0xf4, 0xa6, 0xc6, 0xca, 0x7e, 0xa0, 0x67, 0xab, 0xa9, 0xee, 0x92, 0xb1, 0x42, 0xcb, 0xbb, 0xe2, + 0xf6, 0xd1, 0xba, 0x1a, 0x5f, 0x69, 0xdc, 0x4d, 0xcb, 0xf7, 0x24, 0xea, 0x60, 0x71, 0xf3, 0xe3, 0x4e, 0xbd, 0x6d, + 0x5b, 0xe5, 0xbf, 0x0b, 0xd0, 0x1f, 0x6c, 0xf4, 0x4e, 0xe6, 0x30, 0xa7, 0x57, 0x7e, 0x9e, 0xe3, 0x95, 0xc3, 0x9c, + 0x5d, 0xd9, 0xcd, 0xb9, 0x95, 0xeb, 0x39, 0xff, 0xf0, 0x71, 0x70, 0x93, 0x27, 0xc1, 0x2e, 0x1f, 0x63, 0x88, 0xb3, + 0xb3, 0x0f, 0xc3, 0x2d, 0xe7, 0x8f, 0x11, 0xb7, 0x6d, 0xca, 0x0a, 0x52, 0x4f, 0x7d, 0x3c, 0xf9, 0xf8, 0xde, 0x7a, + 0x97, 0x7e, 0x65, 0xb3, 0xab, 0x3d, 0xad, 0xc6, 0xcb, 0x22, 0x8a, 0xc4, 0x5c, 0x6d, 0xca, 0xfb, 0xad, 0x1b, 0x66, + 0x02, 0x36, 0xed, 0xf9, 0xb6, 0xed, 0xc8, 0xcd, 0x95, 0xea, 0x9f, 0xcf, 0xa8, 0x4b, 0xe6, 0x3b, 0xf2, 0x48, 0x6a, + 0x66, 0xaf, 0xea, 0xcc, 0x3b, 0xd3, 0x44, 0x11, 0x24, 0x08, 0xa2, 0x7c, 0xbe, 0x90, 0xc9, 0xdc, 0xd2, 0x2a, 0x41, + 0xd0, 0xd8, 0x37, 0x60, 0x49, 0x99, 0xac, 0x5b, 0x57, 0xcc, 0x74, 0x06, 0xf2, 0x69, 0x0f, 0x6b, 0xc2, 0x9b, 0xc1, + 0xe1, 0x7c, 0xdd, 0xf5, 0xd9, 0xe5, 0xbd, 0xcf, 0x3d, 0xea, 0xb8, 0xbf, 0x15, 0x37, 0x20, 0x07, 0x73, 0x9f, 0x27, + 0x77, 0x21, 0x6b, 0xac, 0xd3, 0x86, 0x72, 0x4e, 0x75, 0x6d, 0xda, 0x60, 0x88, 0x5e, 0xfd, 0x42, 0x98, 0x48, 0x5b, + 0x3c, 0x9f, 0xd6, 0xd2, 0x37, 0x05, 0x2e, 0x6d, 0x66, 0xd0, 0x69, 0x58, 0x2c, 0x66, 0x12, 0xc2, 0x89, 0x8b, 0x7a, + 0xb4, 0xa9, 0x24, 0x89, 0xf1, 0xb3, 0xfe, 0x5a, 0x2e, 0x23, 0x38, 0x50, 0x0b, 0x4c, 0x5c, 0x17, 0x69, 0xf4, 0x1f, + 0xcc, 0x50, 0x6f, 0x9b, 0xfd, 0xa0, 0xcd, 0x8d, 0x29, 0x7c, 0x85, 0x7e, 0xd2, 0xf4, 0x0a, 0xb5, 0x7b, 0x11, 0x1f, + 0x89, 0x21, 0xf2, 0x01, 0x6c, 0x3b, 0xcc, 0x09, 0xb4, 0x80, 0x73, 0xc4, 0x18, 0x2c, 0x4e, 0x95, 0xea, 0x6c, 0x92, + 0xb7, 0x22, 0x46, 0x5b, 0xb2, 0x1d, 0x6d, 0xd5, 0xb9, 0x1c, 0x5b, 0xb4, 0xb9, 0x91, 0x7d, 0xf3, 0x9f, 0xab, 0x7c, + 0xa3, 0x7d, 0x7f, 0xb5, 0x0a, 0xec, 0x81, 0x91, 0xbf, 0x6b, 0x7f, 0x33, 0x97, 0xb2, 0xec, 0xff, 0x63, 0x72, 0x32, + 0x7b, 0x23, 0x81, 0xf8, 0x95, 0xe7, 0x69, 0x25, 0x9e, 0x84, 0x91, 0xfd, 0x8e, 0x3c, 0xa1, 0xca, 0xb7, 0xd1, 0x96, + 0x96, 0xe5, 0x7e, 0xb7, 0x96, 0x1f, 0x93, 0xe9, 0x5c, 0xbe, 0xf5, 0x84, 0x21, 0xb7, 0xe7, 0x89, 0x78, 0x9f, 0x00, + 0xe7, 0xe6, 0x78, 0x69, 0x9e, 0x7c, 0xe3, 0x91, 0x69, 0xc1, 0x16, 0x80, 0x37, 0x72, 0x76, 0x24, 0xca, 0x49, 0x22, + 0x2d, 0x86, 0x7a, 0xfc, 0xd6, 0xd9, 0xea, 0xef, 0xcd, 0x01, 0x57, 0x00, 0x26, 0x0f, 0xf8, 0x70, 0x24, 0x3f, 0x6e, + 0xdb, 0x09, 0xdb, 0x98, 0x35, 0xc4, 0xe4, 0x61, 0x72, 0x50, 0x7e, 0x15, 0xb4, 0x1a, 0xe9, 0x0b, 0x97, 0x93, 0xcc, + 0x02, 0xe7, 0x90, 0xb8, 0xef, 0x2f, 0x22, 0x9f, 0xfe, 0x5d, 0xe6, 0x4f, 0x0e, 0xce, 0x4c, 0xf1, 0x1f, 0xa3, 0xf1, + 0x40, 0x46, 0xe6, 0x45, 0xfd, 0x53, 0xa3, 0xb5, 0x54, 0x3b, 0x3b, 0x8a, 0x9b, 0x2b, 0x6b, 0x6f, 0xcd, 0x9a, 0x03, + 0xd6, 0x5b, 0x23, 0xf3, 0xc6, 0x32, 0xa2, 0x69, 0x23, 0x7e, 0x09, 0xe7, 0xd5, 0x71, 0x9d, 0x07, 0xe4, 0x37, 0x84, + 0x10, 0xe6, 0xd5, 0x7a, 0xcb, 0x53, 0xb8, 0x5e, 0x2f, 0x75, 0x34, 0xa7, 0xa1, 0xcf, 0x3c, 0x4b, 0x03, 0xcd, 0x80, + 0xe8, 0xd9, 0x79, 0xf5, 0x99, 0xd7, 0x99, 0xb9, 0x18, 0x8f, 0x4e, 0x68, 0xa6, 0x4e, 0xb8, 0xe7, 0x83, 0x19, 0x0b, + 0x14, 0x9b, 0xf8, 0x09, 0x49, 0xe0, 0xf1, 0x93, 0xa3, 0xbc, 0x73, 0x4e, 0xc9, 0xc3, 0x3b, 0x7e, 0x00, 0x0d, 0x40, + 0xe6, 0x1d, 0x24, 0xad, 0xb6, 0xbd, 0xc7, 0x6a, 0x14, 0x09, 0xbe, 0xcc, 0x95, 0xf1, 0xb4, 0xc9, 0x17, 0x6e, 0x36, + 0xb3, 0x7b, 0x57, 0x0f, 0x9e, 0x6f, 0x56, 0xbb, 0xbe, 0xcd, 0x9a, 0xcf, 0x6c, 0xfe, 0xe9, 0xd3, 0x22, 0x2e, 0x67, + 0x94, 0xb9, 0x9e, 0x53, 0xe8, 0x35, 0x23, 0x93, 0x0e, 0xdd, 0x73, 0x89, 0x9d, 0x90, 0x05, 0x4d, 0x6e, 0xe1, 0xa2, + 0x9a, 0x84, 0xfb, 0xda, 0xef, 0x84, 0xd4, 0xa9, 0x5a, 0xd4, 0x1b, 0xa3, 0x27, 0xbb, 0xf8, 0x19, 0x7b, 0xcc, 0x3b, + 0x33, 0x39, 0x91, 0x01, 0x78, 0x51, 0xd9, 0x14, 0x58, 0x9e, 0x35, 0x01, 0x04, 0x65, 0x58, 0x86, 0xd6, 0x12, 0x40, + 0x61, 0x6e, 0xca, 0x07, 0x19, 0xb4, 0xfc, 0x1c, 0x7f, 0x5d, 0x9e, 0x1b, 0x98, 0x37, 0x3e, 0x4e, 0x4e, 0xd0, 0x9c, + 0x14, 0xca, 0x85, 0x88, 0x0f, 0x0a, 0xa0, 0x46, 0x05, 0x9e, 0xd1, 0xbd, 0x0f, 0xf0, 0xdf, 0x0f, 0xfb, 0x75, 0x9d, + 0xf2, 0xef, 0x4f, 0xfe, 0x69, 0xee, 0x3d, 0xf1, 0xaf, 0x4b, 0x49, 0x0a, 0x08, 0x9e, 0xc2, 0xbe, 0xb9, 0xde, 0xbf, + 0x4d, 0xee, 0x55, 0xed, 0x6e, 0x23, 0xa3, 0x3a, 0xb1, 0x30, 0x94, 0xfe, 0x7a, 0xe4, 0xca, 0x37, 0x1f, 0x62, 0xdb, + 0xc3, 0xa6, 0x3f, 0xdc, 0xf7, 0xab, 0x7c, 0x73, 0x21, 0x53, 0xbb, 0x69, 0x45, 0x62, 0x95, 0x62, 0xc0, 0x95, 0x82, + 0x86, 0x39, 0x67, 0x0f, 0xdf, 0xce, 0xd6, 0x46, 0x1a, 0xf1, 0x86, 0xb8, 0x12, 0xab, 0xee, 0x93, 0x50, 0xf9, 0xf6, + 0xfe, 0xf5, 0xd2, 0xb2, 0xf3, 0xb9, 0xf5, 0x0b, 0xc9, 0x00, 0xb3, 0x40, 0xe2, 0x53, 0x71, 0xe4, 0x3e, 0x94, 0x74, + 0x92, 0xa2, 0x78, 0x0c, 0x6d, 0x81, 0x05, 0xa3, 0x21, 0x97, 0xc6, 0x00, 0x59, 0x6a, 0x89, 0x47, 0x5d, 0x4c, 0x2f, + 0xf8, 0xbe, 0xed, 0x06, 0xcd, 0xf7, 0x86, 0x27, 0x1f, 0x7a, 0x6d, 0x62, 0x04, 0xa5, 0x2b, 0xb0, 0xbd, 0xad, 0x18, + 0x91, 0xcb, 0xa5, 0xe4, 0x9f, 0x26, 0x0f, 0x50, 0xb8, 0xef, 0x9e, 0xf8, 0x5c, 0x2c, 0x14, 0xa5, 0xc8, 0x7c, 0x10, + 0x57, 0x83, 0x88, 0x93, 0x06, 0xaa, 0xae, 0x36, 0x76, 0x20, 0xcc, 0xb2, 0x31, 0xa5, 0xc6, 0x0b, 0x1a, 0x10, 0x44, + 0x88, 0x6c, 0x62, 0x05, 0x22, 0xd4, 0xc3, 0xfc, 0x70, 0x43, 0xc7, 0x8a, 0x3a, 0x45, 0x27, 0xa8, 0xa9, 0xb4, 0x86, + 0x34, 0x3d, 0x7a, 0x85, 0x0d, 0x8c, 0x4e, 0x9c, 0x4d, 0x57, 0xe1, 0xbd, 0xe1, 0xce, 0xbe, 0x37, 0x8f, 0x79, 0x2e, + 0xd3, 0x1e, 0x84, 0x4a, 0xc3, 0x58, 0x4f, 0xb7, 0xc4, 0xe9, 0x9e, 0x6d, 0xe6, 0x25, 0xd5, 0x7c, 0x77, 0xb7, 0x67, + 0xed, 0x39, 0x1b, 0x51, 0xbb, 0xad, 0x83, 0xa3, 0xdb, 0x60, 0xac, 0xcf, 0xbb, 0xbb, 0xbc, 0xa0, 0x3d, 0xa9, 0x62, + 0x22, 0x36, 0xd1, 0xa4, 0x01, 0x20, 0xda, 0x51, 0x9a, 0xec, 0xf3, 0x93, 0x9d, 0x1a, 0x08, 0xa5, 0x23, 0x28, 0x6d, + 0x63, 0x33, 0x51, 0x55, 0x6f, 0xf2, 0xb8, 0x8e, 0x9b, 0x30, 0x43, 0x41, 0xcd, 0x7f, 0x3f, 0x0a, 0xb6, 0xdc, 0x19, + 0x98, 0x20, 0xd6, 0x73, 0xdb, 0xd2, 0x5d, 0xc0, 0x03, 0x9c, 0xbe, 0xed, 0xc0, 0x9b, 0x46, 0x7c, 0x1e, 0x1e, 0xa7, + 0xc7, 0xba, 0x17, 0x6e, 0x89, 0x12, 0x23, 0x19, 0x41, 0x06, 0xb9, 0xf6, 0xd8, 0x07, 0x2f, 0x61, 0x91, 0xae, 0x23, + 0xc7, 0x0f, 0xe1, 0x82, 0xc2, 0x84, 0x70, 0x1a, 0xee, 0x5e, 0x14, 0x75, 0x9b, 0xdd, 0xee, 0x89, 0xd1, 0xce, 0x96, + 0xdc, 0xd5, 0x6e, 0x90, 0x79, 0x14, 0xe8, 0xdd, 0x2a, 0x8b, 0xb2, 0xb5, 0x23, 0x1f, 0x36, 0x93, 0x7c, 0x1c, 0x48, + 0xa6, 0xbe, 0xbb, 0x33, 0xb4, 0x3f, 0x90, 0x9d, 0xb6, 0xef, 0x12, 0x5a, 0x1f, 0xa0, 0x9a, 0x56, 0xed, 0xb6, 0x65, + 0xdb, 0xf6, 0x69, 0x19, 0x90, 0x7b, 0xac, 0x7d, 0xe9, 0x46, 0xc6, 0xff, 0xfc, 0x04, 0x23, 0xad, 0x3b, 0xf4, 0x0b, + 0x73, 0x97, 0x9d, 0x46, 0xb6, 0x37, 0x57, 0x4f, 0x51, 0x5a, 0xfb, 0xc0, 0x2c, 0x1a, 0x1f, 0x47, 0x60, 0x7c, 0x06, + 0x4d, 0x84, 0xc1, 0xcf, 0xf0, 0x8b, 0x85, 0x74, 0xb9, 0x22, 0xf7, 0x62, 0x02, 0xe8, 0xdd, 0xe8, 0xcf, 0x9e, 0x41, + 0xb5, 0x54, 0x65, 0x74, 0x9d, 0x14, 0xc5, 0xf4, 0xb7, 0xff, 0x9f, 0xab, 0x81, 0xfa, 0x83, 0x18, 0x85, 0xbe, 0xfc, + 0xe2, 0xe8, 0x5a, 0x57, 0x6c, 0x7a, 0xfe, 0x82, 0xee, 0x03, 0x2e, 0xf1, 0x82, 0x01, 0x3e, 0x8b, 0xc8, 0xdc, 0x24, + 0x73, 0xad, 0xd1, 0x69, 0xec, 0x6d, 0xb0, 0x77, 0x27, 0xff, 0x64, 0x10, 0xf7, 0x0b, 0x68, 0x3b, 0xd3, 0xdd, 0x20, + 0x83, 0x54, 0x9f, 0x13, 0xfd, 0xc3, 0xc0, 0x06, 0xf9, 0xc9, 0xa2, 0x5c, 0x46, 0x38, 0x9f, 0x14, 0x1d, 0x63, 0x15, + 0x62, 0x57, 0x21, 0xf7, 0x8d, 0x74, 0x37, 0x06, 0x76, 0xe8, 0x19, 0x0c, 0xfb, 0xdd, 0x69, 0x53, 0xa9, 0xa0, 0xbd, + 0xaa, 0x46, 0x93, 0xdd, 0x48, 0x6e, 0xed, 0x45, 0x6c, 0xf4, 0x43, 0xc0, 0x10, 0x37, 0x55, 0x8b, 0xdb, 0x01, 0x0b, + 0x87, 0x5d, 0x5c, 0x47, 0x77, 0x04, 0x99, 0x3f, 0x7c, 0x62, 0xc1, 0x15, 0xd9, 0xf9, 0xdf, 0x12, 0x4c, 0xdf, 0x3b, + 0xad, 0xcc, 0xff, 0x53, 0xcc, 0xfe, 0xd0, 0xf3, 0x8a, 0xac, 0x3f, 0x7b, 0xbf, 0x28, 0xba, 0x84, 0xcb, 0x2d, 0x12, + 0xf3, 0x29, 0x34, 0xfd, 0xf5, 0xd6, 0x7c, 0x23, 0x24, 0xee, 0x0f, 0x26, 0x04, 0x9b, 0x94, 0xc5, 0x18, 0x11, 0xfe, + 0xf5, 0xf6, 0xab, 0xf9, 0xd7, 0xa4, 0x25, 0x88, 0xa0, 0xaa, 0xf1, 0x4e, 0x7f, 0xcf, 0x68, 0xf9, 0x01, 0xfe, 0xfd, + 0x81, 0x3f, 0x39, 0xe5, 0xef, 0x9f, 0xfc, 0xd3, 0x2c, 0xbd, 0x25, 0x57, 0xf3, 0x19, 0x72, 0xb0, 0xac, 0x22, 0x01, + 0x2f, 0x5e, 0xcb, 0x91, 0x37, 0x3b, 0x88, 0x07, 0x32, 0xff, 0xea, 0x24, 0x2e, 0xd0, 0x31, 0xf2, 0x21, 0x4f, 0x4b, + 0xf2, 0x82, 0xb1, 0x3b, 0xaa, 0xa5, 0x99, 0xb6, 0xd5, 0xbb, 0x84, 0xda, 0xc5, 0x20, 0x4b, 0x30, 0xdf, 0xff, 0x24, + 0x72, 0x52, 0xd2, 0x98, 0x7f, 0x2b, 0x1f, 0x8f, 0xee, 0x59, 0x1a, 0x98, 0xa2, 0x62, 0xfe, 0xea, 0x45, 0xca, 0x93, + 0xd5, 0x1f, 0xa3, 0x11, 0xf7, 0x8d, 0x99, 0x85, 0xe8, 0x03, 0x3b, 0x43, 0x62, 0xe4, 0xb8, 0x7b, 0x71, 0xd2, 0xf8, + 0xad, 0x4e, 0x90, 0x78, 0xcb, 0x34, 0x48, 0x5f, 0x8b, 0x43, 0xb9, 0x56, 0x8d, 0x4f, 0x3c, 0x58, 0xa4, 0xfd, 0x6d, + 0x77, 0x96, 0xbe, 0xf5, 0xf2, 0xb8, 0x32, 0x7d, 0x99, 0x70, 0x17, 0xc6, 0x22, 0xce, 0x35, 0x56, 0x54, 0x24, 0x46, + 0xe0, 0x10, 0xc5, 0xdb, 0x02, 0x80, 0xd9, 0x28, 0x76, 0x71, 0xfc, 0xc7, 0xef, 0xda, 0xc2, 0x89, 0x44, 0x4b, 0x91, + 0xd4, 0xdc, 0x61, 0x7c, 0xa3, 0xf1, 0x98, 0xc1, 0x78, 0x4f, 0x54, 0xfd, 0xc5, 0xf2, 0x98, 0x95, 0x5a, 0x8f, 0x52, + 0x3c, 0x66, 0x7c, 0x69, 0x34, 0x58, 0x62, 0xcf, 0x43, 0x98, 0xfc, 0x4b, 0xa3, 0xe4, 0xf7, 0x52, 0xec, 0x6a, 0x69, + 0x24, 0xb6, 0x0e, 0xc4, 0x4c, 0x66, 0x71, 0x02, 0xeb, 0x4c, 0x75, 0x4f, 0xce, 0xc6, 0x4b, 0xa5, 0x79, 0x05, 0xad, + 0x0b, 0x7f, 0xa0, 0x9d, 0xe0, 0xd6, 0x5f, 0x3c, 0xbf, 0xe9, 0x56, 0x0e, 0x47, 0xae, 0xd8, 0x6b, 0xfd, 0x3d, 0xde, + 0xee, 0xa9, 0xfa, 0xcb, 0x35, 0xd0, 0x9d, 0x63, 0xb3, 0x49, 0x93, 0xe1, 0x60, 0xe4, 0x13, 0x40, 0x27, 0x48, 0x8e, + 0x66, 0x58, 0xa1, 0xe7, 0x5d, 0x02, 0xb3, 0x5f, 0xf2, 0xe2, 0x10, 0x25, 0x04, 0x7c, 0x6b, 0xb3, 0x98, 0x84, 0xe8, + 0xe1, 0xff, 0xb9, 0x97, 0x7e, 0xbd, 0xb8, 0x5d, 0x8e, 0xb4, 0x05, 0x72, 0xeb, 0x1c, 0x30, 0x0e, 0x7c, 0xb5, 0x31, + 0x50, 0x2e, 0x44, 0x66, 0x44, 0x53, 0x3a, 0x1b, 0x9c, 0x6e, 0x43, 0x3e, 0x5b, 0xf3, 0xf8, 0x46, 0x25, 0x3a, 0xa7, + 0x4e, 0xd2, 0x8c, 0x5b, 0x1b, 0xc4, 0x58, 0x2e, 0x44, 0x43, 0x2c, 0x74, 0x6c, 0x0d, 0x2e, 0x76, 0xdc, 0x0e, 0x8f, + 0xe7, 0xa2, 0x11, 0x3f, 0x92, 0x10, 0x11, 0x9c, 0x8b, 0x99, 0x18, 0xf2, 0xa1, 0x19, 0x01, 0xec, 0xe7, 0x79, 0x7c, + 0x61, 0x1a, 0x66, 0x8f, 0xe0, 0xd9, 0xcb, 0x13, 0xf1, 0x93, 0x46, 0x30, 0x44, 0xc8, 0x86, 0x49, 0x02, 0xd8, 0x63, + 0xb2, 0xd6, 0x6f, 0xdc, 0xda, 0xcb, 0xbe, 0xbf, 0x2c, 0x1b, 0xb7, 0xf3, 0xdf, 0xb1, 0xf8, 0x61, 0x12, 0xf5, 0xea, + 0x9d, 0x08, 0x61, 0x57, 0x8c, 0xde, 0xc9, 0x2a, 0x74, 0x55, 0x44, 0xdf, 0xf7, 0xf0, 0xb1, 0xc6, 0x06, 0xe1, 0x8f, + 0xe1, 0x29, 0x90, 0x37, 0x91, 0xdd, 0xbf, 0x13, 0x5c, 0xdc, 0xf8, 0xd1, 0x9e, 0xc2, 0xce, 0xd8, 0x21, 0x74, 0xa9, + 0x92, 0x49, 0xd1, 0x1d, 0x94, 0x26, 0x9a, 0x6a, 0x78, 0xa1, 0x40, 0x7c, 0x0c, 0x5b, 0x76, 0x35, 0xe3, 0x23, 0xc5, + 0x6f, 0xe3, 0xc5, 0x02, 0xa7, 0x98, 0x60, 0xf4, 0xf0, 0xc0, 0x84, 0xb1, 0x05, 0x6a, 0xf4, 0x10, 0x15, 0x53, 0xce, + 0x63, 0xaa, 0x4b, 0x16, 0x27, 0x7b, 0x65, 0x56, 0x6b, 0xa7, 0x4f, 0x93, 0x54, 0xac, 0x57, 0x58, 0x9e, 0x59, 0xbd, + 0x6a, 0x97, 0x09, 0xf0, 0xc1, 0xff, 0x38, 0x04, 0x26, 0x64, 0x5c, 0x75, 0x6a, 0xfb, 0x30, 0x46, 0x78, 0xf3, 0x3b, + 0xc9, 0x84, 0xb2, 0x49, 0x3e, 0x8c, 0x70, 0x67, 0xf7, 0x44, 0x77, 0x8a, 0x33, 0x26, 0x77, 0x51, 0x0d, 0x83, 0x99, + 0x4e, 0xd0, 0x87, 0xfb, 0x85, 0x39, 0x8f, 0x2b, 0xbc, 0xc7, 0xdf, 0x32, 0xaa, 0x13, 0xe2, 0xf5, 0x45, 0xba, 0x88, + 0x1f, 0x38, 0x05, 0xdb, 0x05, 0x54, 0xc3, 0x08, 0x5c, 0x87, 0xd3, 0xba, 0x23, 0x89, 0xe2, 0x8e, 0x4a, 0x50, 0xdf, + 0x48, 0xf9, 0xbb, 0x63, 0x23, 0x96, 0xa8, 0x1a, 0xe9, 0x2f, 0x4a, 0x79, 0x60, 0x87, 0xf4, 0xa4, 0xd4, 0xe8, 0x98, + 0xa9, 0x53, 0xd3, 0xe0, 0x72, 0x90, 0xbb, 0xe0, 0x95, 0xce, 0xec, 0xc1, 0xb9, 0x58, 0x78, 0xa1, 0x19, 0xa2, 0x1e, + 0xe1, 0xda, 0x78, 0xea, 0x92, 0xc4, 0xa9, 0x6a, 0x49, 0xc2, 0x72, 0xd2, 0xe9, 0x4a, 0x03, 0xf7, 0xea, 0x65, 0x8f, + 0x31, 0x90, 0x26, 0xb3, 0x04, 0xa1, 0x7a, 0x5e, 0x23, 0xbc, 0x46, 0x0a, 0x92, 0x76, 0x1e, 0xf6, 0x37, 0x09, 0x28, + 0x6f, 0xfd, 0x43, 0xbd, 0xa2, 0xc0, 0xf2, 0xa7, 0x82, 0xbc, 0x57, 0xeb, 0x6f, 0x33, 0xea, 0x46, 0x37, 0x09, 0xc3, + 0x6e, 0xfd, 0xc3, 0xc6, 0x2a, 0x35, 0x39, 0x9d, 0xf4, 0x6d, 0xb1, 0x7b, 0x00, 0xf2, 0x72, 0xb7, 0x37, 0xc4, 0x64, + 0x44, 0x10, 0x35, 0x07, 0x2e, 0x42, 0x75, 0xc6, 0xf8, 0x76, 0xa2, 0x1b, 0x35, 0xad, 0x11, 0x62, 0xc9, 0xea, 0x1a, + 0x17, 0x72, 0x57, 0x4c, 0x9c, 0x8c, 0x44, 0xe8, 0x96, 0xe4, 0x5c, 0x7f, 0x80, 0xc3, 0x07, 0x92, 0x29, 0x15, 0xc1, + 0x65, 0x82, 0xa4, 0xfa, 0xbc, 0x89, 0xa0, 0x5b, 0x0d, 0x10, 0x58, 0x02, 0xa9, 0x96, 0xb9, 0x59, 0xdc, 0x32, 0x22, + 0x70, 0x54, 0xcb, 0x57, 0x27, 0x52, 0x38, 0xa3, 0xd9, 0xce, 0x1f, 0x5f, 0xfa, 0xc8, 0xbc, 0x55, 0x85, 0x61, 0x49, + 0x01, 0xe8, 0xca, 0xf8, 0x92, 0x42, 0x90, 0x4a, 0xf9, 0xa2, 0x5b, 0xab, 0x9a, 0xb9, 0x4e, 0x6c, 0xe8, 0xc6, 0x0b, + 0xcc, 0xaf, 0xd5, 0x86, 0x81, 0xcd, 0xdd, 0xae, 0x65, 0xae, 0xd8, 0x20, 0xe7, 0x1d, 0xb5, 0x2d, 0x1f, 0x96, 0xd3, + 0xd1, 0xd5, 0x8c, 0x85, 0x8b, 0xdb, 0xa1, 0x48, 0x7d, 0x60, 0x32, 0xe4, 0x34, 0xba, 0x5f, 0x02, 0x32, 0xff, 0xb4, + 0x34, 0x6a, 0x37, 0x5f, 0x30, 0x7a, 0x0e, 0xbd, 0x8c, 0xe3, 0xd9, 0x45, 0xfe, 0x00, 0xa1, 0xec, 0x0d, 0x4e, 0xa1, + 0xb1, 0x01, 0x9d, 0x8b, 0xf0, 0x99, 0x18, 0x05, 0xd6, 0x91, 0x00, 0xbc, 0x38, 0xb7, 0x71, 0x74, 0x00, 0xa8, 0x35, + 0xaa, 0x80, 0xfb, 0xfd, 0xd1, 0x23, 0x87, 0x28, 0xe2, 0x86, 0xdc, 0x53, 0xd4, 0xa5, 0x3c, 0x9f, 0x48, 0x2b, 0x0b, + 0x1f, 0xa6, 0xc8, 0x2b, 0x7e, 0xa1, 0x17, 0x76, 0x69, 0xe7, 0xa7, 0xa5, 0x9b, 0xf7, 0x4b, 0x4d, 0x3c, 0x95, 0xa3, + 0x9f, 0x53, 0x35, 0x65, 0x50, 0xd2, 0xf5, 0xee, 0x22, 0xa2, 0x03, 0x73, 0x2c, 0x6c, 0xf7, 0x03, 0xa7, 0x9a, 0xb6, + 0xca, 0xe4, 0x6e, 0xe5, 0xa1, 0x02, 0x15, 0x1c, 0xa4, 0xeb, 0x65, 0x7b, 0xef, 0x3f, 0xb1, 0xe1, 0x87, 0x4d, 0xf9, + 0x30, 0xd5, 0x75, 0xda, 0xd3, 0xab, 0xa1, 0x0d, 0x91, 0x83, 0xb4, 0x90, 0xb6, 0xab, 0xc6, 0xbd, 0x35, 0x93, 0xd6, + 0xfe, 0xcd, 0xa6, 0x97, 0xed, 0x14, 0x3b, 0x7f, 0x8c, 0x7a, 0x05, 0x51, 0xe4, 0xfa, 0xbd, 0x74, 0xf5, 0x73, 0xe9, + 0x76, 0x2d, 0x48, 0x3f, 0x50, 0x05, 0xcd, 0x2c, 0xa7, 0xbf, 0x2c, 0xf9, 0xe6, 0x96, 0xd2, 0xc7, 0xf4, 0x87, 0x38, + 0xe7, 0xf8, 0xcc, 0xf0, 0x4c, 0x1d, 0x3d, 0xe8, 0x14, 0x11, 0xcd, 0x38, 0x9b, 0x67, 0xd1, 0x74, 0x16, 0xf0, 0x9a, + 0x54, 0x70, 0x57, 0x3f, 0x1c, 0x3a, 0xd6, 0xb4, 0x8b, 0x90, 0xc5, 0x3e, 0x7e, 0xd8, 0xb5, 0x23, 0xe8, 0x61, 0x14, + 0x14, 0x90, 0xe6, 0x5e, 0x32, 0xca, 0x26, 0x06, 0x7e, 0xeb, 0x25, 0xb0, 0xdd, 0xfb, 0xad, 0x7d, 0x64, 0x77, 0xe2, + 0x95, 0x79, 0x15, 0xf4, 0x8e, 0x44, 0x8d, 0x08, 0x55, 0xdb, 0x0e, 0x71, 0x7d, 0xe5, 0xd8, 0xc4, 0xa6, 0x2c, 0x57, + 0x4c, 0xb8, 0xf8, 0x0d, 0xa0, 0x20, 0x4b, 0x72, 0x08, 0x3a, 0x44, 0x4e, 0x1b, 0xdc, 0x39, 0x3a, 0xd5, 0xa3, 0x16, + 0x7f, 0xe6, 0x0b, 0xf4, 0xb8, 0x26, 0x94, 0x51, 0x40, 0x3b, 0x50, 0xf0, 0x99, 0xec, 0xa0, 0xab, 0x55, 0x76, 0x99, + 0xad, 0xb1, 0x81, 0x08, 0x10, 0x52, 0xd1, 0x9f, 0xa6, 0xa7, 0x05, 0x5d, 0xc2, 0xa5, 0x46, 0x0e, 0xda, 0x97, 0xca, + 0x30, 0x0e, 0x75, 0x74, 0x7d, 0x2a, 0x8f, 0x5f, 0x0d, 0x2c, 0x01, 0xe0, 0xe8, 0x33, 0x08, 0x3b, 0xf8, 0x6c, 0xe7, + 0x8a, 0xc5, 0x65, 0xd0, 0x1d, 0x18, 0xd2, 0xbe, 0xda, 0xb9, 0xea, 0xa7, 0xe8, 0xb7, 0xf6, 0x2e, 0xbe, 0x54, 0xd8, + 0x33, 0x2a, 0xb1, 0x46, 0xe8, 0x10, 0x99, 0x71, 0x8d, 0xbc, 0x7b, 0xcf, 0xbd, 0x1f, 0xdb, 0xe8, 0x15, 0x6c, 0xa1, + 0x4b, 0x48, 0x66, 0x05, 0x2e, 0xfc, 0x47, 0x80, 0x0b, 0x0f, 0x8d, 0x9e, 0x05, 0x56, 0x94, 0x32, 0x03, 0x37, 0x92, + 0xdf, 0xec, 0x1d, 0x2c, 0xb3, 0xf4, 0x96, 0xf0, 0x84, 0xb2, 0x36, 0xca, 0x02, 0x9b, 0x60, 0x9f, 0x1a, 0xa2, 0x3d, + 0x74, 0xfc, 0xa0, 0xfd, 0x09, 0xa7, 0x7f, 0x7f, 0xea, 0x09, 0x1a, 0x0b, 0x3e, 0x46, 0x16, 0xf1, 0x87, 0x69, 0x2f, + 0xdd, 0xed, 0x67, 0x86, 0x46, 0x88, 0x20, 0xde, 0x9a, 0xa5, 0x33, 0x52, 0x49, 0xa5, 0x99, 0x6a, 0xde, 0xef, 0x40, + 0xb0, 0x5b, 0x52, 0x82, 0xdd, 0x08, 0x8b, 0x27, 0xde, 0xb3, 0xf6, 0xe5, 0x05, 0x31, 0x61, 0x31, 0xc5, 0x64, 0xed, + 0x11, 0x40, 0xf1, 0x2e, 0xdc, 0x44, 0x94, 0x74, 0xe5, 0xc7, 0x22, 0x19, 0xc9, 0x9f, 0x49, 0x34, 0x17, 0x49, 0x49, + 0xaf, 0xdd, 0x65, 0x7a, 0xb6, 0x02, 0x55, 0x79, 0xbb, 0xe7, 0x46, 0xed, 0x11, 0x36, 0xbe, 0x1b, 0xd4, 0x81, 0x0f, + 0xc8, 0xf5, 0x2c, 0x71, 0x78, 0xff, 0x12, 0x06, 0x34, 0x14, 0xcb, 0x96, 0x10, 0x17, 0x39, 0xee, 0xf3, 0x95, 0xfa, + 0xc0, 0x38, 0x21, 0x2c, 0xf0, 0xf5, 0x22, 0xd0, 0x9a, 0x83, 0xc4, 0xf7, 0x2b, 0x7e, 0xe1, 0x89, 0x82, 0xfa, 0x78, + 0x71, 0xda, 0x3f, 0xea, 0x4d, 0x5f, 0xd5, 0x4c, 0x93, 0xf3, 0x89, 0x90, 0x50, 0x3e, 0xcf, 0xb3, 0x50, 0x3a, 0x86, + 0x49, 0x8e, 0x4f, 0xfa, 0xe2, 0x92, 0x2e, 0x7c, 0x0c, 0xab, 0xf6, 0x57, 0xa3, 0xb0, 0xea, 0xe2, 0x7d, 0xd2, 0x67, + 0xf4, 0xcb, 0x15, 0x56, 0x8d, 0xf6, 0x0b, 0x17, 0x46, 0x75, 0x28, 0xa9, 0xaf, 0x80, 0x00, 0x06, 0xee, 0x70, 0xc7, + 0xaf, 0x13, 0x35, 0x0d, 0x69, 0xb5, 0x86, 0x20, 0x17, 0xfa, 0x0f, 0x7e, 0x07, 0xbf, 0x6f, 0x39, 0x48, 0x22, 0x07, + 0x1a, 0x3a, 0x94, 0x06, 0x58, 0x69, 0x50, 0x19, 0x54, 0x90, 0xe1, 0xd1, 0xd9, 0x29, 0x72, 0x4b, 0xa2, 0x0a, 0x0c, + 0x35, 0xf5, 0xd4, 0x51, 0x99, 0x00, 0xaf, 0x40, 0xed, 0x07, 0x67, 0x15, 0x21, 0xfa, 0x6b, 0x49, 0x0b, 0xea, 0x14, + 0xe9, 0xf3, 0x4b, 0x0b, 0x40, 0xec, 0x2f, 0x22, 0xdd, 0x69, 0xf8, 0xa4, 0xee, 0x3b, 0x32, 0x00, 0xae, 0x7c, 0x03, + 0x22, 0x20, 0x92, 0xb8, 0xb3, 0x0c, 0x5a, 0xc9, 0x4f, 0xe4, 0x3a, 0x27, 0x51, 0xaa, 0x8b, 0xb2, 0x02, 0x74, 0x6b, + 0x28, 0xe9, 0x2f, 0xda, 0xd1, 0x84, 0xd7, 0xcf, 0x77, 0x38, 0x16, 0xe8, 0x9f, 0x8e, 0xff, 0xb5, 0x40, 0x5a, 0x1a, + 0x02, 0xd7, 0x5b, 0x65, 0x18, 0xd4, 0x77, 0x8a, 0xc0, 0xbc, 0x44, 0xa5, 0x01, 0x25, 0x01, 0xeb, 0x95, 0xfa, 0xfb, + 0x6f, 0x75, 0xf4, 0x15, 0xa8, 0xdd, 0x3a, 0xfa, 0xa9, 0xe7, 0x7b, 0xf8, 0x83, 0xf4, 0x56, 0x3b, 0x40, 0x7f, 0x9c, + 0x67, 0xaa, 0x3f, 0x74, 0x76, 0x3d, 0x62, 0x30, 0x27, 0xe0, 0x82, 0x8c, 0x73, 0x92, 0x1f, 0xc1, 0x56, 0xfc, 0x0f, + 0x8b, 0x54, 0x63, 0xd2, 0xfd, 0xa3, 0x15, 0x78, 0x0d, 0x5d, 0x6a, 0x72, 0x4e, 0xe1, 0x0a, 0xa8, 0x1c, 0xaa, 0xeb, + 0x9c, 0x8a, 0x95, 0x64, 0xe6, 0xbf, 0xac, 0x60, 0xf3, 0xa8, 0x14, 0xa7, 0xcb, 0x0f, 0xaf, 0x5c, 0x62, 0xed, 0xc9, + 0xc5, 0x2f, 0x6e, 0x18, 0x9f, 0x52, 0xef, 0xce, 0xf7, 0xd4, 0x93, 0x0f, 0x3b, 0x26, 0x3f, 0xc0, 0x4f, 0x1f, 0xf6, + 0x9d, 0xe5, 0x94, 0x4f, 0x3f, 0xf9, 0xa5, 0xdf, 0xea, 0xd7, 0x3c, 0xf7, 0x03, 0x77, 0x66, 0x3b, 0xec, 0x1f, 0x09, + 0x6f, 0xa6, 0xcb, 0xbb, 0x86, 0x65, 0xeb, 0x15, 0x93, 0xaf, 0x97, 0x42, 0x9f, 0xfe, 0xe2, 0xfa, 0xa3, 0x07, 0xee, + 0x3d, 0x87, 0x92, 0x66, 0x1c, 0xd5, 0xb9, 0x39, 0x6b, 0xb0, 0xa5, 0x6d, 0x1c, 0x4d, 0x82, 0xad, 0x81, 0x30, 0x19, + 0x1a, 0xa1, 0x89, 0x0a, 0x7a, 0xed, 0x82, 0x52, 0xc1, 0x50, 0x9a, 0xe3, 0xb8, 0x7e, 0x32, 0x09, 0x84, 0xda, 0x22, + 0xa2, 0x6e, 0x4d, 0xab, 0x6c, 0x7c, 0xb0, 0x10, 0x70, 0x06, 0x15, 0xc6, 0x90, 0xdc, 0xeb, 0x0e, 0x04, 0xa6, 0x90, + 0x34, 0xc4, 0xf8, 0x53, 0xf9, 0x38, 0x8a, 0xe2, 0xba, 0x0a, 0x5f, 0x1f, 0xdc, 0x74, 0xe3, 0x94, 0xa3, 0x84, 0x8a, + 0xf2, 0x8e, 0x04, 0x6a, 0x8a, 0x16, 0x6c, 0x29, 0x32, 0x97, 0x23, 0x16, 0xc9, 0x9d, 0xc6, 0xe5, 0x18, 0x42, 0x41, + 0x3a, 0xd0, 0xe9, 0xc4, 0x4a, 0x21, 0xb1, 0x55, 0x21, 0x24, 0x08, 0xcd, 0x6e, 0xcb, 0x6b, 0x15, 0x50, 0x4e, 0xea, + 0xdf, 0xd3, 0x16, 0xf8, 0xba, 0x97, 0xe7, 0xf8, 0xa6, 0x95, 0xce, 0xab, 0xdc, 0xf3, 0xfc, 0xe0, 0xf9, 0xed, 0xf6, + 0x7b, 0x7c, 0x34, 0x63, 0xd5, 0x84, 0x8d, 0x1f, 0xf7, 0x31, 0x21, 0xd4, 0x02, 0x55, 0x04, 0x08, 0xad, 0xb2, 0x06, + 0xd6, 0x75, 0xc8, 0x2c, 0xa1, 0xe1, 0xeb, 0x9f, 0x3a, 0xe4, 0x88, 0x1b, 0x6c, 0xc2, 0x9b, 0xb0, 0xc8, 0xc3, 0x51, + 0x47, 0x7b, 0x03, 0xae, 0xb5, 0x70, 0x40, 0x29, 0x50, 0x67, 0x4b, 0xce, 0x12, 0x41, 0xd4, 0x2d, 0xb3, 0x30, 0x55, + 0xe9, 0x2c, 0xaf, 0x3c, 0x3f, 0x82, 0x5e, 0xb3, 0xbf, 0xd6, 0x49, 0xf0, 0xe4, 0xe9, 0x6c, 0x69, 0x6d, 0x43, 0x81, + 0x9b, 0xd2, 0x2a, 0x9f, 0xac, 0x6d, 0x3c, 0xfa, 0xb1, 0x4f, 0x92, 0x12, 0xba, 0xc4, 0x27, 0x41, 0xea, 0x93, 0xbc, + 0x4b, 0x4b, 0xd7, 0x87, 0x2e, 0xb9, 0x36, 0x54, 0x35, 0x77, 0x23, 0xa6, 0xf2, 0xc3, 0x1b, 0x9a, 0x77, 0xf2, 0x2d, + 0xd2, 0xfd, 0x00, 0xff, 0xfb, 0xb0, 0x33, 0x4e, 0xf9, 0xef, 0x27, 0xff, 0x94, 0x47, 0x76, 0x1d, 0x42, 0xb5, 0x97, + 0x29, 0x78, 0xdf, 0xe6, 0xa3, 0x5f, 0xae, 0xad, 0x46, 0x71, 0x3d, 0xfe, 0xd9, 0xaf, 0x42, 0xf5, 0xf4, 0x17, 0xcb, + 0x8c, 0x4b, 0xdf, 0x4e, 0xd9, 0xcc, 0x2f, 0x8e, 0x39, 0xf3, 0xdc, 0x70, 0xd3, 0x2d, 0xda, 0x90, 0x5e, 0x21, 0xec, + 0xd4, 0xe5, 0x49, 0x17, 0x7d, 0xae, 0x88, 0x7b, 0x71, 0x12, 0x45, 0x0f, 0x51, 0x16, 0x87, 0xd6, 0x94, 0xd3, 0xcc, + 0xec, 0xa3, 0x58, 0x37, 0x1d, 0x29, 0x60, 0x08, 0x17, 0xb0, 0xe0, 0x17, 0x9f, 0x69, 0x3c, 0x63, 0x73, 0xe6, 0xf0, + 0x3f, 0x78, 0x50, 0xb2, 0xcc, 0x19, 0x0f, 0xf2, 0x55, 0x2d, 0x59, 0xbe, 0xe9, 0x60, 0xed, 0xe4, 0x7e, 0x00, 0x7f, + 0x99, 0x59, 0xd3, 0xe1, 0x92, 0x7e, 0x9b, 0xdd, 0xfa, 0x83, 0xd6, 0x52, 0x1e, 0x74, 0x10, 0xb4, 0xd6, 0xa7, 0xfd, + 0x4d, 0x4c, 0xea, 0x03, 0xbe, 0xd5, 0x1c, 0x6c, 0x97, 0xee, 0x9c, 0x47, 0x33, 0x45, 0xfb, 0x95, 0x69, 0x6e, 0xef, + 0xf0, 0x3a, 0x13, 0xad, 0x88, 0xb8, 0x3c, 0x54, 0xf1, 0xd9, 0x0d, 0xe7, 0xc8, 0xcc, 0xee, 0x70, 0x9f, 0x1e, 0x28, + 0x1e, 0x90, 0xcd, 0x15, 0xda, 0x79, 0xf0, 0x10, 0xab, 0xcd, 0x3c, 0xd4, 0x8e, 0xf9, 0xde, 0x74, 0x6e, 0x18, 0xaf, + 0x0c, 0xae, 0x49, 0xa3, 0xe0, 0x7a, 0xbe, 0x35, 0xde, 0x3d, 0x93, 0x3a, 0xea, 0x6c, 0x47, 0x1b, 0xd0, 0x2a, 0xb5, + 0x6b, 0xb2, 0x7a, 0x47, 0xb4, 0x9b, 0xc5, 0xbf, 0x5f, 0x85, 0xeb, 0x7b, 0x07, 0x7b, 0x7e, 0xe3, 0x30, 0x94, 0xa3, + 0x0f, 0xb1, 0xbb, 0xca, 0xff, 0x14, 0x2d, 0xab, 0x6e, 0xad, 0xbb, 0x3a, 0xed, 0xde, 0x49, 0xba, 0xa4, 0xac, 0x8f, + 0x60, 0x30, 0x39, 0x39, 0x77, 0x1d, 0xa5, 0x42, 0x3f, 0x86, 0x9f, 0xa4, 0xbc, 0x3c, 0x5d, 0x1f, 0xd6, 0x79, 0x09, + 0xbd, 0x70, 0xd8, 0x49, 0xeb, 0x1f, 0xbf, 0x5f, 0xe0, 0x13, 0x98, 0x9a, 0x5e, 0x37, 0xa3, 0x61, 0x51, 0x48, 0xda, + 0x1f, 0xc3, 0xce, 0xa5, 0xf1, 0x1b, 0xaa, 0xff, 0xe0, 0xa8, 0x22, 0xb8, 0x3a, 0x2e, 0xb5, 0xa2, 0x8a, 0xef, 0xb3, + 0x4d, 0xdd, 0x62, 0x41, 0xd8, 0xbf, 0x13, 0x39, 0x6a, 0x0c, 0x35, 0x55, 0x5c, 0x5b, 0x54, 0x04, 0x04, 0x89, 0x8b, + 0xfc, 0x5c, 0x3c, 0xac, 0xba, 0x17, 0xbc, 0x29, 0x2a, 0xd0, 0xed, 0x2b, 0x04, 0x55, 0x4e, 0x0a, 0xa6, 0x99, 0xec, + 0x5c, 0x17, 0x7d, 0x5a, 0x7f, 0xda, 0x52, 0xe8, 0x81, 0x70, 0x4c, 0x58, 0x82, 0x85, 0x8a, 0x3b, 0xc8, 0xc1, 0xd3, + 0xe3, 0xf6, 0x82, 0x1f, 0xab, 0x18, 0xed, 0xf8, 0x44, 0x32, 0x07, 0xeb, 0x92, 0x71, 0x03, 0x0f, 0x8e, 0x95, 0x86, + 0xe1, 0x58, 0x01, 0x70, 0x68, 0x76, 0x75, 0x22, 0x7f, 0x68, 0x46, 0xf0, 0x57, 0x24, 0x43, 0xeb, 0x12, 0x35, 0x85, + 0x06, 0xd6, 0x32, 0x7a, 0xae, 0x98, 0x78, 0x31, 0x05, 0x9d, 0x80, 0x20, 0xcb, 0x93, 0x43, 0x7a, 0xb8, 0x8b, 0x64, + 0x51, 0xbd, 0x67, 0x17, 0x8b, 0x48, 0x97, 0x81, 0x06, 0xd3, 0x20, 0xa4, 0xc3, 0x6a, 0xba, 0x6a, 0x6f, 0xee, 0x91, + 0xa5, 0x79, 0x4c, 0x8c, 0x95, 0x86, 0x9e, 0xd5, 0x38, 0xb0, 0xe1, 0x96, 0x09, 0x0b, 0x87, 0xc4, 0xd1, 0xc9, 0x61, + 0x15, 0x91, 0xa0, 0x59, 0xdf, 0x82, 0xac, 0x74, 0x00, 0x1b, 0xf0, 0x30, 0xaf, 0x2e, 0xb1, 0xbb, 0x6d, 0xcd, 0x22, + 0x9e, 0x59, 0x86, 0x61, 0x5d, 0xfc, 0xa7, 0xae, 0x39, 0x61, 0xfb, 0xdf, 0x3c, 0x1e, 0x1e, 0x8b, 0xae, 0x36, 0x16, + 0x4b, 0xb1, 0x07, 0x3d, 0xa2, 0xfb, 0xc3, 0xc7, 0xc3, 0x9b, 0xc0, 0x24, 0x3e, 0xe9, 0x67, 0x16, 0x34, 0x13, 0xdb, + 0xd9, 0xe8, 0x09, 0xfb, 0x68, 0x9b, 0x62, 0x87, 0x54, 0x60, 0x51, 0xd3, 0xd9, 0x09, 0xd5, 0x69, 0x68, 0x24, 0x69, + 0x86, 0x50, 0x58, 0xed, 0x0d, 0x7e, 0x11, 0x62, 0x6f, 0xaf, 0xfb, 0x7b, 0x0e, 0x62, 0x2d, 0x06, 0xa8, 0x41, 0x4d, + 0x8b, 0xc4, 0xee, 0xd2, 0xdd, 0x33, 0x5e, 0x02, 0x55, 0x1d, 0x95, 0x43, 0x0a, 0xb3, 0x5c, 0x8c, 0x68, 0x43, 0x27, + 0x59, 0x62, 0x1d, 0x93, 0xa9, 0x94, 0xb8, 0xfe, 0xbb, 0x04, 0x12, 0x14, 0x1e, 0xd9, 0x91, 0x70, 0xcb, 0x9f, 0x27, + 0xfc, 0xf9, 0x0b, 0xb6, 0x1a, 0x6c, 0xa7, 0x00, 0x5c, 0x3e, 0xfa, 0xfc, 0x0e, 0xe4, 0x2f, 0x54, 0x0c, 0xfc, 0xbc, + 0x70, 0xc2, 0x0b, 0xf0, 0x4f, 0xb0, 0x14, 0x89, 0xe9, 0x5e, 0x4a, 0xf3, 0x14, 0x6b, 0x98, 0x40, 0xaf, 0xcb, 0x7e, + 0xd9, 0x02, 0x87, 0x11, 0xc4, 0xa5, 0xee, 0xdb, 0x05, 0xb4, 0x51, 0x01, 0x28, 0x8b, 0x6a, 0xe0, 0x58, 0xc7, 0xdb, + 0x26, 0x45, 0xdc, 0xf4, 0xab, 0x04, 0x99, 0xd1, 0x2b, 0xb1, 0xb8, 0x0c, 0x5d, 0x5b, 0x39, 0x4e, 0x53, 0xf4, 0x99, + 0x0c, 0x36, 0xcc, 0x3a, 0x15, 0x81, 0x99, 0xf4, 0xf0, 0xa0, 0x6f, 0xd3, 0x9a, 0x6f, 0xd7, 0xf5, 0xf2, 0x6e, 0x93, + 0x5f, 0x77, 0x7c, 0xf9, 0xea, 0xc9, 0x85, 0x94, 0x48, 0x5b, 0xa0, 0x5b, 0xaa, 0xa7, 0xc5, 0xd6, 0xba, 0xd1, 0xf4, + 0xb8, 0xc2, 0xf0, 0x50, 0x19, 0x4d, 0xfd, 0x69, 0x52, 0x98, 0xcd, 0x16, 0xdd, 0xe8, 0x63, 0xff, 0x4a, 0x02, 0x0d, + 0x96, 0x2d, 0xf5, 0xde, 0x9b, 0x05, 0x0b, 0x7a, 0xeb, 0x20, 0x6b, 0xb9, 0xca, 0x91, 0x7b, 0x42, 0x51, 0x5d, 0x20, + 0x28, 0xf2, 0xb0, 0x48, 0x2b, 0xdc, 0x99, 0xbd, 0xcc, 0x06, 0xf4, 0x21, 0xe3, 0x4a, 0xee, 0x9c, 0x03, 0x25, 0xd3, + 0xe6, 0x4d, 0x7a, 0xef, 0x2f, 0x76, 0x7a, 0xec, 0xde, 0x41, 0x86, 0xe5, 0xff, 0x8d, 0xea, 0x6a, 0xbe, 0x25, 0x45, + 0x0a, 0x8f, 0xa2, 0x7d, 0xac, 0x4a, 0xe1, 0x3b, 0xc2, 0x56, 0x0a, 0x54, 0x07, 0xda, 0x57, 0xa4, 0x2e, 0x61, 0x6e, + 0xd6, 0x41, 0x60, 0x65, 0x3a, 0xfc, 0x2b, 0x52, 0x03, 0x7e, 0xb3, 0x05, 0x44, 0x88, 0x9d, 0xec, 0x21, 0x7c, 0x14, + 0x00, 0xc7, 0x15, 0x00, 0xcd, 0x88, 0xdc, 0xe0, 0xe4, 0xe0, 0x21, 0xee, 0x8f, 0x57, 0x77, 0x59, 0x51, 0xe1, 0xbd, + 0x45, 0x58, 0x07, 0xf0, 0xd7, 0x72, 0xb8, 0x9e, 0x97, 0xfe, 0xc2, 0x87, 0xea, 0x09, 0x2a, 0x77, 0xee, 0xeb, 0x82, + 0xa1, 0x3c, 0x95, 0x38, 0x36, 0xd0, 0x55, 0x79, 0x6b, 0xaf, 0xb4, 0x99, 0x04, 0xbb, 0x1b, 0xa1, 0xa9, 0x0e, 0xa3, + 0x21, 0x6e, 0x7e, 0x5b, 0xd9, 0xfa, 0xc3, 0xc5, 0xed, 0x9f, 0xdf, 0x9d, 0x0b, 0x3f, 0xc0, 0x25, 0x06, 0x6c, 0xea, + 0x20, 0xc4, 0x7e, 0xe7, 0xdc, 0x04, 0x42, 0x88, 0x3d, 0x06, 0x93, 0x29, 0x62, 0x26, 0x34, 0x95, 0xa3, 0x10, 0x82, + 0x49, 0xde, 0x52, 0x6d, 0xc8, 0x85, 0x07, 0xd9, 0x21, 0x33, 0x65, 0x6a, 0x13, 0xc2, 0x26, 0xdc, 0xb6, 0x8d, 0x75, + 0x73, 0x65, 0x31, 0x36, 0x77, 0x5b, 0x7d, 0x61, 0x45, 0xe8, 0xed, 0x5d, 0xdf, 0xea, 0xdc, 0xee, 0x9a, 0xfc, 0x08, + 0x3a, 0x64, 0xef, 0x8a, 0x0a, 0x07, 0xbb, 0x93, 0xd3, 0x45, 0xd2, 0x6c, 0x08, 0x24, 0x16, 0x08, 0x81, 0x5f, 0x68, + 0x68, 0x86, 0x8c, 0xf1, 0xc8, 0x2b, 0xdf, 0xb8, 0x2a, 0x3b, 0xf6, 0x12, 0x54, 0xbd, 0x87, 0x98, 0x73, 0x9f, 0x86, + 0x75, 0x1c, 0xc9, 0x61, 0xea, 0x66, 0xe8, 0x87, 0xb0, 0xdd, 0x24, 0x71, 0x99, 0x8e, 0xe4, 0x3e, 0xbb, 0xbf, 0xf4, + 0x7c, 0x37, 0x6a, 0xe1, 0x22, 0xda, 0x14, 0x50, 0x8f, 0x48, 0x76, 0xea, 0xda, 0x8b, 0xf4, 0x63, 0x8e, 0xc4, 0x5d, + 0xd9, 0x5a, 0xd2, 0xfc, 0x28, 0xa0, 0x21, 0x3a, 0xa3, 0xf8, 0xd2, 0xcf, 0x46, 0x7b, 0x9a, 0xff, 0xea, 0x87, 0xab, + 0xb3, 0xff, 0xd1, 0xae, 0x44, 0xa1, 0xe2, 0xc9, 0x31, 0xd0, 0x36, 0x5f, 0x92, 0x72, 0x1d, 0x4b, 0x64, 0x9c, 0xd7, + 0x86, 0x77, 0xcb, 0x06, 0x82, 0x3d, 0xea, 0x1c, 0xd1, 0xfa, 0x05, 0x76, 0x08, 0xdd, 0xd9, 0xd1, 0x40, 0xd7, 0x1e, + 0xfa, 0xe7, 0xfa, 0xdf, 0xfe, 0xe7, 0xd6, 0xae, 0x52, 0x6a, 0xa9, 0x1e, 0x72, 0x47, 0xe5, 0x25, 0x09, 0xd1, 0x01, + 0xa8, 0x48, 0x23, 0x70, 0x5f, 0x6e, 0xad, 0xf9, 0x5d, 0x59, 0x67, 0xfe, 0xa7, 0x05, 0x63, 0x24, 0x72, 0x7a, 0x43, + 0x48, 0xd8, 0x84, 0x24, 0x8e, 0x9d, 0xeb, 0x8c, 0xb3, 0xa4, 0x69, 0x11, 0xba, 0xba, 0x53, 0x8f, 0x04, 0xcb, 0x93, + 0x36, 0xcb, 0xb8, 0x21, 0x5b, 0x6e, 0xbb, 0x49, 0xfa, 0xe8, 0xe7, 0xae, 0xd5, 0x5c, 0x01, 0x41, 0x50, 0xb5, 0x2c, + 0x2f, 0x8d, 0xc8, 0xab, 0x0d, 0xf7, 0x65, 0xf9, 0x6b, 0xf7, 0x53, 0x18, 0x69, 0x51, 0x1b, 0x9c, 0x72, 0xd6, 0xad, + 0x7a, 0x50, 0x2d, 0x45, 0x19, 0x59, 0xf5, 0x21, 0xfa, 0x4f, 0x70, 0x83, 0x97, 0x77, 0x37, 0x47, 0x2f, 0xa6, 0x16, + 0x5e, 0x70, 0x24, 0x67, 0xe2, 0xee, 0xfc, 0x28, 0x4b, 0xec, 0x65, 0xd0, 0x97, 0x88, 0xea, 0x9c, 0x18, 0x6f, 0x8a, + 0x67, 0x06, 0xa2, 0xdb, 0xd4, 0xf7, 0x4d, 0x70, 0x90, 0xf1, 0x0d, 0xb2, 0x3f, 0x27, 0x48, 0x4e, 0x7d, 0xa2, 0xf1, + 0x32, 0x98, 0xb6, 0x23, 0x05, 0xc7, 0xc7, 0x76, 0x0f, 0x38, 0xde, 0xc8, 0xe5, 0x42, 0xf5, 0xad, 0xbb, 0xff, 0xc3, + 0xea, 0x61, 0x76, 0x06, 0xc7, 0x9d, 0x4d, 0xcb, 0x04, 0xaf, 0x58, 0xe2, 0x4f, 0xb5, 0x89, 0xdd, 0x9e, 0x4d, 0xba, + 0xe3, 0x72, 0x7b, 0x38, 0xbb, 0x0b, 0xad, 0x51, 0xee, 0x36, 0x7f, 0x01, 0x48, 0x21, 0xd0, 0x86, 0xfd, 0xa2, 0x70, + 0x10, 0xd4, 0x00, 0x1f, 0x00, 0x23, 0xb4, 0xc4, 0x62, 0x45, 0x9e, 0x68, 0x28, 0xad, 0x72, 0x46, 0x4c, 0x83, 0xe7, + 0x83, 0x77, 0x95, 0xc4, 0xa5, 0xf4, 0x77, 0x61, 0x73, 0x4b, 0x89, 0xcf, 0x9c, 0x7e, 0x7c, 0x9b, 0xea, 0xbb, 0x2e, + 0x39, 0x5b, 0xbe, 0xf7, 0x9c, 0x56, 0x1a, 0x3a, 0xb8, 0x83, 0x8f, 0xd5, 0x16, 0x42, 0x36, 0x6e, 0xa0, 0xdb, 0xec, + 0x0f, 0xb9, 0x67, 0xe7, 0xa9, 0x62, 0x4f, 0xb2, 0x5c, 0x58, 0xac, 0x08, 0x17, 0xae, 0xde, 0x2d, 0x02, 0x58, 0x90, + 0xef, 0x43, 0x1f, 0xcb, 0xac, 0xe4, 0xc7, 0x0f, 0xfc, 0xcf, 0x83, 0x00, 0x8b, 0x92, 0xe5, 0x34, 0xa1, 0xca, 0x9d, + 0x41, 0xcc, 0xb3, 0x9e, 0x91, 0x35, 0x9b, 0x7c, 0xe8, 0x00}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From c03faf2d9a19fb6da7e5422a10e89aeb032c42df Mon Sep 17 00:00:00 2001 From: Jas Strong Date: Sat, 10 Jan 2026 11:40:14 -0800 Subject: [PATCH 0028/2030] [aqi] Fix precision loss for low PM concentration values (#13120) Co-authored-by: jas --- .../components/aqi/abstract_aqi_calculator.h | 2 +- esphome/components/aqi/aqi_calculator.h | 34 +++++++++++-------- esphome/components/aqi/aqi_sensor.cpp | 3 +- esphome/components/aqi/caqi_calculator.h | 30 +++++++++------- 4 files changed, 38 insertions(+), 31 deletions(-) diff --git a/esphome/components/aqi/abstract_aqi_calculator.h b/esphome/components/aqi/abstract_aqi_calculator.h index 7836c76cdc..299962fa17 100644 --- a/esphome/components/aqi/abstract_aqi_calculator.h +++ b/esphome/components/aqi/abstract_aqi_calculator.h @@ -6,7 +6,7 @@ namespace esphome::aqi { class AbstractAQICalculator { public: - virtual uint16_t get_aqi(uint16_t pm2_5_value, uint16_t pm10_0_value) = 0; + virtual uint16_t get_aqi(float pm2_5_value, float pm10_0_value) = 0; }; } // namespace esphome::aqi diff --git a/esphome/components/aqi/aqi_calculator.h b/esphome/components/aqi/aqi_calculator.h index 35dc35a44a..993504c1e9 100644 --- a/esphome/components/aqi/aqi_calculator.h +++ b/esphome/components/aqi/aqi_calculator.h @@ -1,6 +1,7 @@ #pragma once -#include +#include +#include #include "abstract_aqi_calculator.h" // https://document.airnow.gov/technical-assistance-document-for-the-reporting-of-daily-air-quailty.pdf @@ -9,11 +10,11 @@ namespace esphome::aqi { class AQICalculator : public AbstractAQICalculator { public: - uint16_t get_aqi(uint16_t pm2_5_value, uint16_t pm10_0_value) override { - int pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); - int pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); + uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override { + float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); + float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return (pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index; + return static_cast(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); } protected: @@ -21,25 +22,28 @@ class AQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; - static constexpr int PM2_5_GRID[NUM_LEVELS][2] = {{0, 9}, {10, 35}, {36, 55}, {56, 125}, {126, 225}, {226, INT_MAX}}; + static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {{0.0f, 9.0f}, {9.1f, 35.4f}, + {35.5f, 55.4f}, {55.5f, 125.4f}, + {125.5f, 225.4f}, {225.5f, std::numeric_limits::max()}}; - static constexpr int PM10_0_GRID[NUM_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, - {255, 354}, {355, 424}, {425, INT_MAX}}; + static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {{0.0f, 54.0f}, {55.0f, 154.0f}, + {155.0f, 254.0f}, {255.0f, 354.0f}, + {355.0f, 424.0f}, {425.0f, std::numeric_limits::max()}}; - static int calculate_index(uint16_t value, const int array[NUM_LEVELS][2]) { + static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); if (grid_index == -1) { - return -1; + return -1.0f; } - int aqi_lo = INDEX_GRID[grid_index][0]; - int aqi_hi = INDEX_GRID[grid_index][1]; - int conc_lo = array[grid_index][0]; - int conc_hi = array[grid_index][1]; + float aqi_lo = INDEX_GRID[grid_index][0]; + float aqi_hi = INDEX_GRID[grid_index][1]; + float conc_lo = array[grid_index][0]; + float conc_hi = array[grid_index][1]; return (value - conc_lo) * (aqi_hi - aqi_lo) / (conc_hi - conc_lo) + aqi_lo; } - static int get_grid_index(uint16_t value, const int array[NUM_LEVELS][2]) { + static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { if (value >= array[i][0] && value <= array[i][1]) { return i; diff --git a/esphome/components/aqi/aqi_sensor.cpp b/esphome/components/aqi/aqi_sensor.cpp index cdc9f35ba6..2d8a780cc7 100644 --- a/esphome/components/aqi/aqi_sensor.cpp +++ b/esphome/components/aqi/aqi_sensor.cpp @@ -44,8 +44,7 @@ void AQISensor::calculate_aqi_() { return; } - uint16_t aqi = - calculator->get_aqi(static_cast(this->pm_2_5_value_), static_cast(this->pm_10_0_value_)); + uint16_t aqi = calculator->get_aqi(this->pm_2_5_value_, this->pm_10_0_value_); this->publish_state(aqi); } diff --git a/esphome/components/aqi/caqi_calculator.h b/esphome/components/aqi/caqi_calculator.h index 9906c179f6..d2ec4bb98f 100644 --- a/esphome/components/aqi/caqi_calculator.h +++ b/esphome/components/aqi/caqi_calculator.h @@ -1,16 +1,18 @@ #pragma once +#include +#include #include "abstract_aqi_calculator.h" namespace esphome::aqi { class CAQICalculator : public AbstractAQICalculator { public: - uint16_t get_aqi(uint16_t pm2_5_value, uint16_t pm10_0_value) override { - int pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); - int pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); + uint16_t get_aqi(float pm2_5_value, float pm10_0_value) override { + float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); + float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return (pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index; + return static_cast(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); } protected: @@ -18,25 +20,27 @@ class CAQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 75}, {76, 100}, {101, 400}}; - static constexpr int PM2_5_GRID[NUM_LEVELS][2] = {{0, 15}, {16, 30}, {31, 55}, {56, 110}, {111, 400}}; + static constexpr float PM2_5_GRID[NUM_LEVELS][2] = { + {0.0f, 15.0f}, {15.1f, 30.0f}, {30.1f, 55.0f}, {55.1f, 110.0f}, {110.1f, std::numeric_limits::max()}}; - static constexpr int PM10_0_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 90}, {91, 180}, {181, 400}}; + static constexpr float PM10_0_GRID[NUM_LEVELS][2] = { + {0.0f, 25.0f}, {25.1f, 50.0f}, {50.1f, 90.0f}, {90.1f, 180.0f}, {180.1f, std::numeric_limits::max()}}; - static int calculate_index(uint16_t value, const int array[NUM_LEVELS][2]) { + static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); if (grid_index == -1) { - return -1; + return -1.0f; } - int aqi_lo = INDEX_GRID[grid_index][0]; - int aqi_hi = INDEX_GRID[grid_index][1]; - int conc_lo = array[grid_index][0]; - int conc_hi = array[grid_index][1]; + float aqi_lo = INDEX_GRID[grid_index][0]; + float aqi_hi = INDEX_GRID[grid_index][1]; + float conc_lo = array[grid_index][0]; + float conc_hi = array[grid_index][1]; return (value - conc_lo) * (aqi_hi - aqi_lo) / (conc_hi - conc_lo) + aqi_lo; } - static int get_grid_index(uint16_t value, const int array[NUM_LEVELS][2]) { + static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { if (value >= array[i][0] && value <= array[i][1]) { return i; From 6c981d8b71fc6695a80ffe24aedad337c3eba4c1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 10 Jan 2026 15:26:42 -0500 Subject: [PATCH 0029/2030] [esp32_hosted] Bump component versions (#13118) Co-authored-by: Claude Opus 4.5 --- esphome/components/esp32_hosted/__init__.py | 6 +++--- esphome/idf_component.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 9c9d1d4bb4..e40431c851 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -93,9 +93,9 @@ async def to_code(config): framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] os.environ["ESP_IDF_VERSION"] = f"{framework_ver.major}.{framework_ver.minor}" if framework_ver >= cv.Version(5, 5, 0): - esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.2.2") - esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.3") - esp32.add_idf_component(name="espressif/esp_hosted", ref="2.7.0") + esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.2.4") + esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") + esp32.add_idf_component(name="espressif/esp_hosted", ref="2.9.3") else: esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0") esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 2dc5b94847..045b3f9168 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -6,15 +6,15 @@ dependencies: espressif/mdns: version: 1.9.1 espressif/esp_wifi_remote: - version: 1.2.2 + version: 1.2.4 rules: - if: "target in [esp32h2, esp32p4]" espressif/eppp_link: - version: 1.1.3 + version: 1.1.4 rules: - if: "target in [esp32h2, esp32p4]" espressif/esp_hosted: - version: 2.7.0 + version: 2.9.3 rules: - if: "target in [esp32h2, esp32p4]" zorxx/multipart-parser: From de82f96ccb3b38480a441ae1aa255ada455f9c28 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 10 Jan 2026 14:43:31 -1000 Subject: [PATCH 0030/2030] [core] Rename FixedVector::shrink_to_fit() to release() for clarity (#13130) --- esphome/components/wifi/wifi_component.cpp | 4 ++-- esphome/core/helpers.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index afdaa0b6e8..352081fe31 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2014,8 +2014,8 @@ void WiFiComponent::release_scan_results_() { // std::vector - use swap trick since shrink_to_fit is non-binding decltype(this->scan_result_)().swap(this->scan_result_); #else - // FixedVector::shrink_to_fit() actually frees all memory - this->scan_result_.shrink_to_fit(); + // FixedVector::release() frees all memory + this->scan_result_.release(); #endif } } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index acba420d3e..05d2d475c1 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -293,8 +293,8 @@ template class FixedVector { size_ = 0; } - // Shrink capacity to fit current size (frees all memory) - void shrink_to_fit() { + // Release all memory (destroys elements and frees memory) + void release() { cleanup_(); reset_(); } From 5725a4840e3900eaa7d8ca9cc3f9719161577197 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Jan 2026 01:09:25 +0000 Subject: [PATCH 0031/2030] Bump aioesphomeapi from 43.10.1 to 43.11.0 (#13132) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 00f81f793f..eb177e1411 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 -aioesphomeapi==43.10.1 +aioesphomeapi==43.11.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From f2eb61a767d986fa425efbc5ef233c3456054fab Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sat, 10 Jan 2026 19:43:27 -0600 Subject: [PATCH 0032/2030] [api] Proto code generator changes for #12985 (#13100) Co-authored-by: J. Nick Koston --- esphome/components/api/api_options.proto | 11 +++ script/api_protobuf/api_protobuf.py | 85 ++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/esphome/components/api/api_options.proto b/esphome/components/api/api_options.proto index 6b33408e2f..1916e84625 100644 --- a/esphome/components/api/api_options.proto +++ b/esphome/components/api/api_options.proto @@ -80,4 +80,15 @@ extend google.protobuf.FieldOptions { // Example: [(container_pointer_no_template) = "light::ColorModeMask"] // generates: const light::ColorModeMask *supported_color_modes{}; optional string container_pointer_no_template = 50014; + + // packed_buffer: Expose raw packed buffer instead of decoding into container + // When set on a packed repeated field, the generated code stores a pointer + // to the raw protobuf buffer instead of decoding values. This enables + // zero-copy passthrough when the consumer can decode on-demand. + // The field must be a packed repeated field (packed=true). + // Generates three fields: + // - const uint8_t *_data_{nullptr}; + // - uint16_t _length_{0}; + // - uint16_t _count_{0}; + optional bool packed_buffer = 50015 [default=false]; } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 274a672c7c..c61555805e 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -339,6 +339,9 @@ def create_field_type_info( ) -> TypeInfo: """Create the appropriate TypeInfo instance for a field, handling repeated fields and custom options.""" if field.label == FieldDescriptorProto.LABEL_REPEATED: + # Check if this is a packed_buffer field (zero-copy packed repeated) + if get_field_opt(field, pb.packed_buffer, False): + return PackedBufferTypeInfo(field) # Check if this repeated field has fixed_array_with_length_define option if ( fixed_size := get_field_opt(field, pb.fixed_array_with_length_define) @@ -947,6 +950,88 @@ class PointerToStringBufferType(PointerToBufferTypeBase): return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string +class PackedBufferTypeInfo(TypeInfo): + """Type for packed repeated fields that expose raw buffer instead of decoding. + + When a repeated field is marked with [(packed_buffer) = true], this type + generates code that stores a pointer to the raw protobuf buffer along with + its length and the count of values. This enables zero-copy passthrough when + the consumer can decode the packed varints on-demand. + """ + + def __init__(self, field: descriptor.FieldDescriptorProto) -> None: + # packed_buffer is decode-only (SOURCE_CLIENT messages) + super().__init__(field, needs_decode=True, needs_encode=False) + + @property + def cpp_type(self) -> str: + # Not used - we have multiple fields + return "const uint8_t*" + + @property + def wire_type(self) -> WireType: + """Packed fields use LENGTH_DELIMITED wire type.""" + return WireType.LENGTH_DELIMITED + + @property + def public_content(self) -> list[str]: + """Generate three fields: data pointer, length, and count.""" + return [ + f"const uint8_t *{self.field_name}_data_{{nullptr}};", + f"uint16_t {self.field_name}_length_{{0}};", + f"uint16_t {self.field_name}_count_{{0}};", + ] + + @property + def decode_length_content(self) -> str: + """Store pointer to buffer and calculate count of packed varints.""" + return f"""case {self.number}: {{ + this->{self.field_name}_data_ = value.data(); + this->{self.field_name}_length_ = value.size(); + this->{self.field_name}_count_ = count_packed_varints(value.data(), value.size()); + break; + }}""" + + @property + def encode_content(self) -> str: + """No encoding - this is decode-only for SOURCE_CLIENT messages.""" + return None + + @property + def dump_content(self) -> str: + """Dump shows buffer info but not decoded values.""" + return ( + f'out.append(" {self.name}: ");\n' + + 'out.append("packed buffer [");\n' + + f"out.append(std::to_string(this->{self.field_name}_count_));\n" + + 'out.append(" values, ");\n' + + f"out.append(std::to_string(this->{self.field_name}_length_));\n" + + 'out.append(" bytes]\\n");' + ) + + def dump(self, name: str) -> str: + """Dump method for packed buffer - not typically used but required by abstract base.""" + return 'out.append("packed buffer");' + + def get_size_calculation(self, name: str, force: bool = False) -> str: + """No size calculation needed - decode-only.""" + return "" + + def get_estimated_size(self) -> int: + """Estimate size for packed buffer field. + + Typical IR/RF timing array has ~50-200 values, each encoded as 1-3 bytes. + Estimate 100 values * 2 bytes = 200 bytes typical. + """ + return ( + self.calculate_field_id_size() + 2 + 200 + ) # field ID + length varint + data + + @classmethod + def can_use_dump_field(cls) -> bool: + return False + + class FixedArrayBytesType(TypeInfo): """Special type for fixed-size byte arrays.""" From e34532f2835adf621d22d3ae9b3c6023d71e46d5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 10 Jan 2026 16:42:35 -1000 Subject: [PATCH 0033/2030] [sensor] Use C++17 nested namespace syntax (#13116) --- esphome/components/sensor/automation.cpp | 6 ++---- esphome/components/sensor/automation.h | 6 ++---- esphome/components/sensor/filter.cpp | 6 ++---- esphome/components/sensor/filter.h | 6 ++---- esphome/components/sensor/sensor.cpp | 6 ++---- esphome/components/sensor/sensor.h | 6 ++---- 6 files changed, 12 insertions(+), 24 deletions(-) diff --git a/esphome/components/sensor/automation.cpp b/esphome/components/sensor/automation.cpp index f53c43d1f6..977719db9b 100644 --- a/esphome/components/sensor/automation.cpp +++ b/esphome/components/sensor/automation.cpp @@ -1,10 +1,8 @@ #include "automation.h" #include "esphome/core/log.h" -namespace esphome { -namespace sensor { +namespace esphome::sensor { static const char *const TAG = "sensor.automation"; -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor diff --git a/esphome/components/sensor/automation.h b/esphome/components/sensor/automation.h index df7d31a0c9..996c7fc9b5 100644 --- a/esphome/components/sensor/automation.h +++ b/esphome/components/sensor/automation.h @@ -4,8 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/components/sensor/sensor.h" -namespace esphome { -namespace sensor { +namespace esphome::sensor { class SensorStateTrigger : public Trigger { public: @@ -107,5 +106,4 @@ template class SensorInRangeCondition : public Condition float max_{NAN}; }; -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index c8c6540112..8450ec4c4e 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -5,8 +5,7 @@ #include "esphome/core/log.h" #include "sensor.h" -namespace esphome { -namespace sensor { +namespace esphome::sensor { static const char *const TAG = "sensor.filter"; @@ -574,5 +573,4 @@ void StreamingMovingAverageFilter::reset_batch() { this->valid_count_ = 0; } -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 92a9184c18..15c7656a7b 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -7,8 +7,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" -namespace esphome { -namespace sensor { +namespace esphome::sensor { class Sensor; @@ -632,5 +631,4 @@ class StreamingMovingAverageFilter : public StreamingFilter { size_t valid_count_{0}; }; -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index c1d28bf260..64678f8d0c 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -3,8 +3,7 @@ #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" -namespace esphome { -namespace sensor { +namespace esphome::sensor { static const char *const TAG = "sensor"; @@ -135,5 +134,4 @@ void Sensor::internal_send_state_to_frontend(float state) { #endif } -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index a792c0d3fd..d9046020f6 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -9,8 +9,7 @@ #include #include -namespace esphome { -namespace sensor { +namespace esphome::sensor { void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *obj); @@ -143,5 +142,4 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa } sensor_flags_{}; }; -} // namespace sensor -} // namespace esphome +} // namespace esphome::sensor From 6222fae907fbca9aca9f373081b74707cbc96e85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 10 Jan 2026 16:43:15 -1000 Subject: [PATCH 0034/2030] [libretiny] Disable BLE stack on BK7231N to save ~21KB RAM (#13131) --- esphome/components/libretiny/__init__.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 4c8a1999f9..4fbbcde6c3 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -32,6 +32,7 @@ from .const import ( CONF_SDK_SILENT, CONF_UART_PORT, FAMILIES, + FAMILY_BK7231N, FAMILY_COMPONENT, FAMILY_FRIENDLY, KEY_BOARD, @@ -50,6 +51,22 @@ CODEOWNERS = ["@kuba2k2"] AUTO_LOAD = ["preferences"] IS_TARGET_PLATFORM = True +# BK7231N SDK options to disable unused features. +# Disabling BLE saves ~21KB RAM and ~200KB Flash because BLE init code is +# called unconditionally by the SDK. ESPHome doesn't use BLE on LibreTiny. +# +# This only works on BK7231N (BLE 5.x). Other BK72XX chips using BLE 4.2 +# (BK7231T, BK7231Q, BK7251; BK7252 boards use the BK7251 family) have a bug +# where the BLE library still links and references undefined symbols when +# CFG_SUPPORT_BLE=0. +# +# Other options like CFG_TX_EVM_TEST, CFG_RX_SENSITIVITY_TEST, CFG_SUPPORT_BKREG, +# CFG_SUPPORT_OTA_HTTP, and CFG_USE_SPI_SLAVE were evaluated but provide no # NOLINT +# measurable benefit - the linker already strips unreferenced code via -gc-sections. +_BK7231N_SYS_CONFIG_OPTIONS = [ + "CFG_SUPPORT_BLE=0", +] + def _detect_variant(value): if KEY_LIBRETINY not in CORE.data: @@ -346,4 +363,10 @@ async def component_to_code(config): cg.add_platformio_option("custom_fw_name", "esphome") cg.add_platformio_option("custom_fw_version", __version__) + # Apply chip-specific SDK options to save RAM/Flash + if config[CONF_FAMILY] == FAMILY_BK7231N: + cg.add_platformio_option( + "custom_options.sys_config#h", _BK7231N_SYS_CONFIG_OPTIONS + ) + await cg.register_component(var, config) From a1395af7636e787dda0e1e916d8afc4fbcd2b046 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 10 Jan 2026 17:07:21 -1000 Subject: [PATCH 0035/2030] [helpers] Add format_hex_prefixed_to for "0x" prefixed hex formatting (#13115) --- esphome/components/one_wire/one_wire.cpp | 6 +++-- .../sml/text_sensor/sml_text_sensor.cpp | 6 ++--- esphome/core/helpers.h | 23 +++++++++++++++++++ 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/esphome/components/one_wire/one_wire.cpp b/esphome/components/one_wire/one_wire.cpp index fd139d0ddc..187f559ca6 100644 --- a/esphome/components/one_wire/one_wire.cpp +++ b/esphome/components/one_wire/one_wire.cpp @@ -6,8 +6,10 @@ namespace one_wire { static const char *const TAG = "one_wire"; const std::string &OneWireDevice::get_address_name() { - if (this->address_name_.empty()) - this->address_name_ = std::string("0x") + format_hex(this->address_); + if (this->address_name_.empty()) { + char hex_buf[19]; // "0x" + 16 hex chars + null + this->address_name_ = format_hex_prefixed_to(hex_buf, this->address_); + } return this->address_name_; } diff --git a/esphome/components/sml/text_sensor/sml_text_sensor.cpp b/esphome/components/sml/text_sensor/sml_text_sensor.cpp index 6ceff26fe5..17b93ecccf 100644 --- a/esphome/components/sml/text_sensor/sml_text_sensor.cpp +++ b/esphome/components/sml/text_sensor/sml_text_sensor.cpp @@ -24,11 +24,9 @@ void SmlTextSensor::publish_val(const ObisInfo &obis_info) { case SML_HEX: { // Buffer for "0x" + up to 32 bytes as hex + null char buf[67]; - buf[0] = '0'; - buf[1] = 'x'; - // Max 32 bytes of data fit in remaining buffer ((65-1)/2) + // Max 32 bytes of data fit in buffer ((67-3)/2) size_t hex_bytes = std::min(obis_info.value.size(), size_t(32)); - format_hex_to(buf + 2, sizeof(buf) - 2, obis_info.value.begin(), hex_bytes); + format_hex_prefixed_to(buf, obis_info.value.begin(), hex_bytes); publish_state(buf, 2 + hex_bytes * 2); break; } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 05d2d475c1..cd43709f7d 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -759,6 +759,29 @@ inline char *format_hex_to(char (&buffer)[N], T val) { /// Calculate buffer size needed for format_hex_to: "XXXXXXXX...\0" = bytes * 2 + 1 constexpr size_t format_hex_size(size_t byte_count) { return byte_count * 2 + 1; } +/// Calculate buffer size needed for format_hex_prefixed_to: "0xXXXXXXXX...\0" = bytes * 2 + 3 +constexpr size_t format_hex_prefixed_size(size_t byte_count) { return byte_count * 2 + 3; } + +/// Format an unsigned integer as "0x" prefixed lowercase hex to buffer. +template::value, int> = 0> +inline char *format_hex_prefixed_to(char (&buffer)[N], T val) { + static_assert(N >= sizeof(T) * 2 + 3, "Buffer too small for prefixed hex"); + buffer[0] = '0'; + buffer[1] = 'x'; + val = convert_big_endian(val); + format_hex_to(buffer + 2, N - 2, reinterpret_cast(&val), sizeof(T)); + return buffer; +} + +/// Format byte array as "0x" prefixed lowercase hex to buffer. +template inline char *format_hex_prefixed_to(char (&buffer)[N], const uint8_t *data, size_t length) { + static_assert(N >= 5, "Buffer must hold at least '0x' + one hex byte + null"); + buffer[0] = '0'; + buffer[1] = 'x'; + format_hex_to(buffer + 2, N - 2, data, length); + return buffer; +} + /// Calculate buffer size needed for format_hex_pretty_to with separator: "XX:XX:...:XX\0" constexpr size_t format_hex_pretty_size(size_t byte_count) { return byte_count * 3; } From 5ae46a43695982a16d83683b4e6181f22a9621e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Jan 2026 09:49:17 -1000 Subject: [PATCH 0036/2030] Bump aioesphomeapi from 43.11.0 to 43.12.0 (#13139) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index eb177e1411..d3bb5b5dc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 -aioesphomeapi==43.11.0 +aioesphomeapi==43.12.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 742d724e652f8d1716c4e551c69eb08de2885bfa Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:16:55 -0500 Subject: [PATCH 0037/2030] [seeed_mr24hpc1] Add ifdef guards for conditional entity types (#13147) Co-authored-by: Claude Opus 4.5 --- .../seeed_mr24hpc1/seeed_mr24hpc1.cpp | 432 +++++++++++------- 1 file changed, 273 insertions(+), 159 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 4c0416d727..08d83f9390 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -64,15 +64,21 @@ void MR24HPC1Component::dump_config() { void MR24HPC1Component::setup() { this->check_uart_settings(115200); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); // Zero out the custom mode } +#endif +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(0); } +#endif +#ifdef USE_TEXT_SENSOR if (this->custom_mode_end_text_sensor_ != nullptr) { this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); } +#endif this->set_custom_end_mode(); this->poll_time_base_func_check_ = true; this->check_dev_inf_sign_ = true; @@ -353,6 +359,7 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { // Parses data frames related to product information void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { +#ifdef USE_TEXT_SENSOR uint16_t product_len = encode_uint16(data[FRAME_COMMAND_WORD_INDEX + 1], data[FRAME_COMMAND_WORD_INDEX + 2]); if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_MODE) { if ((this->product_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { @@ -388,109 +395,153 @@ void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { ESP_LOGD(TAG, "Reply: get firmwareVersion error!"); } } +#endif } // Parsing the underlying open parameters void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *data) { - if (data[FRAME_COMMAND_WORD_INDEX] == 0x00) { - if (this->underlying_open_function_switch_ != nullptr) { - this->underlying_open_function_switch_->publish_state( - data[FRAME_DATA_INDEX]); // Underlying Open Parameter Switch Status Updates - } - if (data[FRAME_DATA_INDEX]) { - this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; - } else { - this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; - } - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { - if (this->custom_spatial_static_value_sensor_ != nullptr) { - this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } - if (this->custom_presence_of_detection_sensor_ != nullptr) { - this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f); - } - if (this->custom_spatial_motion_value_sensor_ != nullptr) { - this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]); - } - if (this->custom_motion_distance_sensor_ != nullptr) { - this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f); - } - if (this->custom_motion_speed_sensor_ != nullptr) { - this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f); - } - } else if ((data[FRAME_COMMAND_WORD_INDEX] == 0x06) || (data[FRAME_COMMAND_WORD_INDEX] == 0x86)) { - // none:0x00 close_to:0x01 far_away:0x02 - if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { - this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); - } - } else if ((this->movement_signs_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x07) || (data[FRAME_COMMAND_WORD_INDEX] == 0x87))) { - this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->existence_threshold_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { - this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->motion_threshold_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x09) || (data[FRAME_COMMAND_WORD_INDEX] == 0x89))) { - this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->existence_boundary_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) { - if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { - this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); - } - } else if ((this->motion_boundary_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) { - if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { - this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); - } - } else if ((this->motion_trigger_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) { - uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - this->motion_trigger_number_->publish_state(motion_trigger_time); - } else if ((this->motion_to_rest_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0d) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8d))) { - uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - this->motion_to_rest_number_->publish_state(move_to_rest_time); - } else if ((this->custom_unman_time_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0e) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8e))) { - uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - float custom_unmanned_time = enter_unmanned_time / 1000.0; - this->custom_unman_time_number_->publish_state(custom_unmanned_time); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x80) { - if (data[FRAME_DATA_INDEX]) { - this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; - } else { - this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; - } - if (this->underlying_open_function_switch_ != nullptr) { - this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]); - } - } else if ((this->custom_spatial_static_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x81)) { - this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->custom_spatial_motion_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x82)) { - this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->custom_presence_of_detection_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x83)) { - this->custom_presence_of_detection_sensor_->publish_state( - S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); - } else if ((this->custom_motion_distance_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x84)) { - this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f); - } else if ((this->custom_motion_speed_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x85)) { - this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f); + switch (data[FRAME_COMMAND_WORD_INDEX]) { + case 0x00: + case 0x80: +#ifdef USE_SWITCH + if (this->underlying_open_function_switch_ != nullptr) { + this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]); + } +#endif + this->s_output_info_switch_flag_ = data[FRAME_DATA_INDEX] ? OUTPUT_SWITCH_ON : OUTPUT_SWTICH_OFF; + break; +#ifdef USE_SENSOR + case 0x01: + if (this->custom_spatial_static_value_sensor_ != nullptr) { + this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + if (this->custom_presence_of_detection_sensor_ != nullptr) { + this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f); + } + if (this->custom_spatial_motion_value_sensor_ != nullptr) { + this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]); + } + if (this->custom_motion_distance_sensor_ != nullptr) { + this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f); + } + if (this->custom_motion_speed_sensor_ != nullptr) { + this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f); + } + break; + case 0x07: + case 0x87: + if (this->movement_signs_sensor_ != nullptr) { + this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x81: + if (this->custom_spatial_static_value_sensor_ != nullptr) { + this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x82: + if (this->custom_spatial_motion_value_sensor_ != nullptr) { + this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x83: + if (this->custom_presence_of_detection_sensor_ != nullptr) { + this->custom_presence_of_detection_sensor_->publish_state( + S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); + } + break; + case 0x84: + if (this->custom_motion_distance_sensor_ != nullptr) { + this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f); + } + break; + case 0x85: + if (this->custom_motion_speed_sensor_ != nullptr) { + this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x06: + case 0x86: + // none:0x00 close_to:0x01 far_away:0x02 + if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_NUMBER + case 0x08: + case 0x88: + if (this->existence_threshold_number_ != nullptr) { + this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x09: + case 0x89: + if (this->motion_threshold_number_ != nullptr) { + this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x0c: + case 0x8c: + if (this->motion_trigger_number_ != nullptr) { + uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->motion_trigger_number_->publish_state(motion_trigger_time); + } + break; + case 0x0d: + case 0x8d: + if (this->motion_to_rest_number_ != nullptr) { + uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->motion_to_rest_number_->publish_state(move_to_rest_time); + } + break; + case 0x0e: + case 0x8e: + if (this->custom_unman_time_number_ != nullptr) { + uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->custom_unman_time_number_->publish_state(enter_unmanned_time / 1000.0f); + } + break; +#endif +#ifdef USE_SELECT + case 0x0a: + case 0x8a: + if (this->existence_boundary_select_ != nullptr) { + if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { + this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); + } + } + break; + case 0x0b: + case 0x8b: + if (this->motion_boundary_select_ != nullptr) { + if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { + this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); + } + } + break; +#endif } } void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) { switch (data[FRAME_CONTROL_WORD_INDEX]) { case 0x01: { - if ((this->heartbeat_state_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x01)) { - this->heartbeat_state_text_sensor_->publish_state("Equipment Normal"); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) { + if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) { ESP_LOGD(TAG, "Reply: query restart packet"); - } else if (this->heartbeat_state_text_sensor_ != nullptr) { - this->heartbeat_state_text_sensor_->publish_state("Equipment Abnormal"); + break; } +#ifdef USE_TEXT_SENSOR + if (this->heartbeat_state_text_sensor_ != nullptr) { + this->heartbeat_state_text_sensor_->publish_state( + data[FRAME_COMMAND_WORD_INDEX] == 0x01 ? "Equipment Normal" : "Equipment Abnormal"); + } +#endif } break; case 0x02: { this->r24_frame_parse_product_information_(data); @@ -511,86 +562,123 @@ void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) { } void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) { - if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { - ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) { - if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { - this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); - } else { - ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); - } - } else if ((this->sensitivity_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { - // 1-3 - this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x09) { - // 1-4 - if (this->custom_mode_num_sensor_ != nullptr) { - this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } - if (this->custom_mode_number_ != nullptr) { - this->custom_mode_number_->publish_state(0); - } - if (this->custom_mode_end_text_sensor_ != nullptr) { - this->custom_mode_end_text_sensor_->publish_state("Setup in progress"); - } - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x81) { - ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) { - if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { - this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); - } else { - ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); - } - } else if ((this->custom_mode_end_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x0A)) { - this->custom_mode_end_text_sensor_->publish_state("Set Success!"); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x89) { - if (data[FRAME_DATA_INDEX] == 0) { - if (this->custom_mode_end_text_sensor_ != nullptr) { - this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); + switch (data[FRAME_COMMAND_WORD_INDEX]) { + case 0x01: + case 0x81: + ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); + break; + case 0x09: +#ifdef USE_SENSOR + if (this->custom_mode_num_sensor_ != nullptr) { + this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); } +#endif +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif +#ifdef USE_TEXT_SENSOR + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Setup in progress"); + } +#endif + break; + case 0x89: +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); } - } else { - if (this->custom_mode_num_sensor_ != nullptr) { - this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); +#endif + if (data[FRAME_DATA_INDEX] == 0) { +#ifdef USE_TEXT_SENSOR + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); + } +#endif +#ifdef USE_NUMBER + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); + } +#endif } - } - } else { - ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; +#ifdef USE_SELECT + case 0x07: + case 0x87: + if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { + this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); + } else { + ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_NUMBER + case 0x08: + case 0x88: + if (this->sensitivity_number_ != nullptr) { + this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x0A: + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Set Success!"); + } + break; +#endif + default: + ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; } } void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) { - if ((this->has_target_binary_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x01) || (data[FRAME_COMMAND_WORD_INDEX] == 0x81))) { - this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); - } else if ((this->motion_status_text_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x02) || (data[FRAME_COMMAND_WORD_INDEX] == 0x82))) { - if (data[FRAME_DATA_INDEX] < 3) { - this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]); - } - } else if ((this->movement_signs_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x03) || (data[FRAME_COMMAND_WORD_INDEX] == 0x83))) { - this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->unman_time_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) { - // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08 - if (data[FRAME_DATA_INDEX] < 9) { - this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]); - } - } else if ((this->keep_away_text_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) { - // none:0x00 close_to:0x01 far_away:0x02 - if (data[FRAME_DATA_INDEX] < 3) { - this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); - } - } else { - ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + switch (data[FRAME_COMMAND_WORD_INDEX]) { +#ifdef USE_BINARY_SENSOR + case 0x01: + case 0x81: + if (this->has_target_binary_sensor_ != nullptr) { + this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_SENSOR + case 0x03: + case 0x83: + if (this->movement_signs_sensor_ != nullptr) { + this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x02: + case 0x82: + if ((this->motion_status_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]); + } + break; + case 0x0B: + case 0x8B: + // none:0x00 close_to:0x01 far_away:0x02 + if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_SELECT + case 0x0A: + case 0x8A: + // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08 + if ((this->unman_time_select_ != nullptr) && (data[FRAME_DATA_INDEX] < 9)) { + this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif + default: + ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; } } @@ -695,12 +783,15 @@ void MR24HPC1Component::set_underlying_open_function(bool enable) { } else { this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF)); } +#ifdef USE_TEXT_SENSOR if (this->keep_away_text_sensor_ != nullptr) { this->keep_away_text_sensor_->publish_state(""); } if (this->motion_status_text_sensor_ != nullptr) { this->motion_status_text_sensor_->publish_state(""); } +#endif +#ifdef USE_SENSOR if (this->custom_spatial_static_value_sensor_ != nullptr) { this->custom_spatial_static_value_sensor_->publish_state(NAN); } @@ -716,6 +807,7 @@ void MR24HPC1Component::set_underlying_open_function(bool enable) { if (this->custom_motion_speed_sensor_ != nullptr) { this->custom_motion_speed_sensor_->publish_state(NAN); } +#endif } void MR24HPC1Component::set_scene_mode(uint8_t value) { @@ -723,12 +815,16 @@ void MR24HPC1Component::set_scene_mode(uint8_t value) { uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x07, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); this->send_query_(send_data, send_data_len); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(0); } +#endif this->get_scene_mode(); this->get_sensitivity(); this->get_custom_mode(); @@ -768,9 +864,11 @@ void MR24HPC1Component::set_unman_time(uint8_t value) { void MR24HPC1Component::set_custom_mode(uint8_t mode) { if (mode == 0) { this->set_custom_end_mode(); // Equivalent to end setting +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif return; } uint8_t send_data_len = 10; @@ -793,9 +891,11 @@ void MR24HPC1Component::set_custom_end_mode() { uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x0a, 0x00, 0x01, 0x0F, 0xCB, 0x54, 0x43}; this->send_query_(send_data, send_data_len); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); // Clear setpoints } +#endif this->get_existence_boundary(); this->get_motion_boundary(); this->get_existence_threshold(); @@ -809,8 +909,10 @@ void MR24HPC1Component::set_custom_end_mode() { } void MR24HPC1Component::set_existence_boundary(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0A, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -819,8 +921,10 @@ void MR24HPC1Component::set_existence_boundary(uint8_t value) { } void MR24HPC1Component::set_motion_boundary(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0B, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -829,8 +933,10 @@ void MR24HPC1Component::set_motion_boundary(uint8_t value) { } void MR24HPC1Component::set_existence_threshold(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -839,8 +945,10 @@ void MR24HPC1Component::set_existence_threshold(uint8_t value) { } void MR24HPC1Component::set_motion_threshold(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x09, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -849,8 +957,10 @@ void MR24HPC1Component::set_motion_threshold(uint8_t value) { } void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 13; uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, value, 0x00, 0x54, 0x43}; send_data[10] = get_frame_crc_sum(send_data, send_data_len); @@ -859,8 +969,10 @@ void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { } void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t h8_num = (value >> 8) & 0xff; uint8_t l8_num = value & 0xff; uint8_t send_data_len = 13; @@ -871,8 +983,10 @@ void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { } void MR24HPC1Component::set_custom_unman_time(uint16_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint32_t value_ms = value * 1000; uint8_t h24_num = (value_ms >> 24) & 0xff; uint8_t h16_num = (value_ms >> 16) & 0xff; From 68064dc974fc62aaeb464ebaae3838e62d6a7f66 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:17:07 -1000 Subject: [PATCH 0038/2030] [web_server] Fix v1 compilation on ESP-IDF by adding missing write method (#13153) --- esphome/components/web_server_idf/web_server_idf.h | 1 + tests/components/web_server/test_v1.esp32-idf.yaml | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/components/web_server/test_v1.esp32-idf.yaml diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 5f9f598388..cae7006d96 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -80,6 +80,7 @@ class AsyncResponseStream : public AsyncWebServerResponse { void print(const std::string &str) { this->content_.append(str); } void print(float value); void printf(const char *fmt, ...) __attribute__((format(printf, 2, 3))); + void write(uint8_t c) { this->content_.push_back(static_cast(c)); } protected: std::string content_; diff --git a/tests/components/web_server/test_v1.esp32-idf.yaml b/tests/components/web_server/test_v1.esp32-idf.yaml new file mode 100644 index 0000000000..389a930284 --- /dev/null +++ b/tests/components/web_server/test_v1.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common_v1.yaml From 909bd1074affdd5dab29a8fbee49eda742b5ed6d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:17:18 -1000 Subject: [PATCH 0039/2030] [wifi] Fix captive portal/improv only attempting last configured network (#13086) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/wifi/wifi_component.cpp | 117 ++++++++++++++++----- esphome/components/wifi/wifi_component.h | 12 ++- 2 files changed, 104 insertions(+), 25 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 352081fe31..ff6284c073 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -48,7 +48,7 @@ static const char *const TAG = "wifi"; /// The WiFi component uses a state machine with priority degradation to handle connection failures /// and automatically cycle through different BSSIDs in mesh networks or multiple configured networks. /// -/// Connection Flow: +/// Normal Connection Flow (SCAN_BASED): /// ┌──────────────────────────────────────────────────────────────────────┐ /// │ Fast Connect Path (Optional) │ /// ├──────────────────────────────────────────────────────────────────────┤ @@ -109,10 +109,13 @@ static const char *const TAG = "wifi"; /// │ (Skip Hidden1/Hidden2, try Hidden3 from example) │ /// │ - If none → Skip RETRY_HIDDEN, go to step 5 │ /// │ ↓ │ -/// │ 5. FAILED → RESTARTING_ADAPTER (skipped if AP/improv active) │ +/// │ 5. FAILED → RESTARTING_ADAPTER │ +/// │ - Normal: restart adapter, clear state │ +/// │ - AP/improv active: skip restart, just disconnect │ /// │ ↓ │ /// │ 6. Loop back to start: │ /// │ - If first network is hidden → EXPLICIT_HIDDEN (retry cycle) │ +/// │ - If AP/improv active → RETRY_HIDDEN (blind retry, see below) │ /// │ - Otherwise → SCAN_CONNECTING (rescan) │ /// │ ↓ │ /// │ 7. RESCAN → Apply stored priorities, sort again │ @@ -134,8 +137,10 @@ static const char *const TAG = "wifi"; /// - FAST_CONNECT_CYCLING_APS: Cycle through remaining configured networks (1 attempt each, fast_connect only) /// - EXPLICIT_HIDDEN: Try consecutive networks marked hidden:true before scanning (1 attempt per SSID) /// - SCAN_CONNECTING: Connect using scan results (2 attempts per BSSID) -/// - RETRY_HIDDEN: Try networks not found in scan (1 attempt per SSID, skipped if none found) -/// - RESTARTING_ADAPTER: Restart WiFi adapter to clear stuck state +/// - RETRY_HIDDEN: Behavior controlled by RetryHiddenMode: +/// * SCAN_BASED: Try networks not found in scan (truly hidden, 1 attempt per SSID) +/// * BLIND_RETRY: Cycle through ALL networks when scanning disabled (AP active) +/// - RESTARTING_ADAPTER: Restart WiFi adapter to clear stuck state (restart skipped if AP active) /// /// Hidden Network Handling: /// - Networks marked 'hidden: true' before first non-hidden → Tried in EXPLICIT_HIDDEN phase @@ -146,6 +151,35 @@ static const char *const TAG = "wifi"; /// - Networks marked 'hidden: true' always use hidden mode, even if broadcasting SSID /// /// ┌──────────────────────────────────────────────────────────────────────┐ +/// │ Captive Portal / Improv Mode (AP active, scanning disabled) │ +/// ├──────────────────────────────────────────────────────────────────────┤ +/// │ When captive_portal or esp32_improv is active, WiFi scanning is │ +/// │ disabled because it disrupts AP clients (radio leaves AP channel │ +/// │ to hop through other channels, causing client disconnections). │ +/// │ │ +/// │ Flow with RetryHiddenMode::BLIND_RETRY: │ +/// │ │ +/// │ 1. RESTARTING_ADAPTER → In this mode, skip adapter restart and │ +/// │ just disconnect (normal mode restarts the adapter) │ +/// │ - Sets retry_hidden_mode_ = BLIND_RETRY │ +/// │ - Enter extended cooldown (30s vs normal 500ms) │ +/// │ ↓ │ +/// │ 2. determine_next_phase_() returns RETRY_HIDDEN (skips scanning) │ +/// │ ↓ │ +/// │ 3. RETRY_HIDDEN with BLIND_RETRY mode: │ +/// │ - find_next_hidden_sta_() ignores scan_result_ │ +/// │ - ALL configured networks become candidates │ +/// │ - Cycles through networks: Net1 → Net2 → Net3 → ... │ +/// │ ↓ │ +/// │ 4. After exhausting all networks → Back to RESTARTING_ADAPTER │ +/// │ - Loop continues until connection succeeds or user configures │ +/// │ new credentials via captive portal │ +/// │ │ +/// │ The 30s cooldown gives users time to interact with captive portal │ +/// │ without constant connection attempts disrupting the AP. │ +/// └──────────────────────────────────────────────────────────────────────┘ +/// +/// ┌──────────────────────────────────────────────────────────────────────┐ /// │ Post-Connect Roaming (for stationary devices) │ /// ├──────────────────────────────────────────────────────────────────────┤ /// │ Purpose: Handle AP reboot or power loss scenarios where device │ @@ -332,7 +366,23 @@ bool WiFiComponent::ssid_was_seen_in_scan_(const std::string &ssid) const { } int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) { - // Find next SSID that wasn't in scan results (might be hidden) + // Find next SSID to try in RETRY_HIDDEN phase. + // + // This function operates in two modes based on retry_hidden_mode_: + // + // 1. SCAN_BASED mode: + // After SCAN_CONNECTING phase, only returns networks that were NOT visible + // in the scan (truly hidden networks that need probe requests). + // + // 2. BLIND_RETRY mode: + // When captive portal/improv is active, scanning is skipped to avoid + // disrupting the AP. In this mode, ALL configured networks are returned + // as candidates, cycling through them sequentially. This allows the device + // to keep trying all networks while users configure WiFi via captive portal. + // + // Additionally, if EXPLICIT_HIDDEN phase was executed (first network marked hidden:true), + // those networks are skipped here since they were already tried. + // bool include_explicit_hidden = !this->went_through_explicit_hidden_phase_(); // Start searching from start_index + 1 for (size_t i = start_index + 1; i < this->sta_.size(); i++) { @@ -349,9 +399,9 @@ int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) { } } - // If we didn't scan this cycle, treat all networks as potentially hidden - // Otherwise, only retry networks that weren't seen in the scan - if (!this->did_scan_this_cycle_ || !this->ssid_was_seen_in_scan_(sta.get_ssid())) { + // In BLIND_RETRY mode, treat all networks as candidates + // In SCAN_BASED mode, only retry networks that weren't seen in the scan + if (this->retry_hidden_mode_ == RetryHiddenMode::BLIND_RETRY || !this->ssid_was_seen_in_scan_(sta.get_ssid())) { ESP_LOGD(TAG, "Hidden candidate " LOG_SECRET("'%s'") " at index %d", sta.get_ssid().c_str(), static_cast(i)); return static_cast(i); } @@ -1158,7 +1208,7 @@ void WiFiComponent::check_scanning_finished() { return; } this->scan_done_ = false; - this->did_scan_this_cycle_ = true; + this->retry_hidden_mode_ = RetryHiddenMode::SCAN_BASED; if (this->scan_result_.empty()) { ESP_LOGW(TAG, "No networks found"); @@ -1463,8 +1513,23 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() { if (this->went_through_explicit_hidden_phase_()) { return WiFiRetryPhase::EXPLICIT_HIDDEN; } - // Skip scanning when captive portal/improv is active to avoid disrupting AP - // Even passive scans can cause brief AP disconnections on ESP32 + // Skip scanning when captive portal/improv is active to avoid disrupting AP. + // + // WHY SCANNING DISRUPTS AP MODE: + // WiFi scanning requires the radio to leave the AP's channel and hop through + // other channels to listen for beacons. During this time (even for passive scans), + // the AP cannot service connected clients - they experience disconnections or + // timeouts. On ESP32, even passive scans cause brief but noticeable disruptions + // that break captive portal HTTP requests and DNS lookups. + // + // BLIND RETRY MODE: + // When captive portal/improv is active, we use RETRY_HIDDEN as a "try all networks + // blindly" mode. Since retry_hidden_mode_ is set to BLIND_RETRY (in RESTARTING_ADAPTER + // transition), find_next_hidden_sta_() will treat ALL configured networks as + // candidates, cycling through them without requiring scan results. + // + // This allows users to configure WiFi via captive portal while the device keeps + // attempting to connect to all configured networks in sequence. if (this->is_captive_portal_active_() || this->is_esp32_improv_active_()) { return WiFiRetryPhase::RETRY_HIDDEN; } @@ -1533,19 +1598,19 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) { break; case WiFiRetryPhase::RETRY_HIDDEN: - // Starting hidden mode - find first SSID that wasn't in scan results - if (old_phase == WiFiRetryPhase::SCAN_CONNECTING) { - // Keep scan results so we can skip SSIDs that were visible in the scan - // Don't clear scan_result_ - we need it to know which SSIDs are NOT hidden + // Always reset to first candidate when entering this phase. + // This phase can be entered from: + // - SCAN_CONNECTING: normal flow, find_next_hidden_sta_() skips networks visible in scan + // - RESTARTING_ADAPTER: captive portal active, find_next_hidden_sta_() tries ALL networks + // + // The retry_hidden_mode_ controls the behavior: + // - SCAN_BASED: scan_result_ is checked, visible networks are skipped + // - BLIND_RETRY: scan_result_ is ignored, all networks become candidates + // We don't clear scan_result_ here - the mode controls whether it's consulted. + this->selected_sta_index_ = this->find_next_hidden_sta_(-1); - // If first network is marked hidden, we went through EXPLICIT_HIDDEN phase - // In that case, skip networks marked hidden:true (already tried) - // Otherwise, include them (they haven't been tried yet) - this->selected_sta_index_ = this->find_next_hidden_sta_(-1); - - if (this->selected_sta_index_ == -1) { - ESP_LOGD(TAG, "All SSIDs visible or already tried, skipping hidden mode"); - } + if (this->selected_sta_index_ == -1) { + ESP_LOGD(TAG, "All SSIDs visible or already tried, skipping hidden mode"); } break; @@ -1561,7 +1626,11 @@ bool WiFiComponent::transition_to_phase_(WiFiRetryPhase new_phase) { this->wifi_disconnect_(); } // Clear scan flag - we're starting a new retry cycle - this->did_scan_this_cycle_ = false; + // This is critical for captive portal/improv flow: when determine_next_phase_() + // returns RETRY_HIDDEN (because scanning is skipped), find_next_hidden_sta_() + // will see BLIND_RETRY mode and treat ALL networks as candidates, + // effectively cycling through all configured networks without scan results. + this->retry_hidden_mode_ = RetryHiddenMode::BLIND_RETRY; // Always enter cooldown after restart (or skip-restart) to allow stabilization // Use extended cooldown when AP is active to avoid constant scanning that blocks DNS this->state_ = WIFI_COMPONENT_STATE_COOLDOWN; diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 9b606bd692..b4c4a622d5 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -124,6 +124,16 @@ enum class RoamingState : uint8_t { RECONNECTING, }; +/// Controls how RETRY_HIDDEN phase selects networks to try +enum class RetryHiddenMode : uint8_t { + /// Normal mode: scan completed, only try networks NOT visible in scan results + /// (truly hidden networks that need probe requests) + SCAN_BASED, + /// Blind retry mode: scanning disabled (captive portal/improv active), + /// try ALL configured networks sequentially without consulting scan results + BLIND_RETRY, +}; + /// Struct for setting static IPs in WiFiComponent. struct ManualIP { network::IPAddress static_ip; @@ -676,7 +686,7 @@ class WiFiComponent : public Component { bool enable_on_boot_{true}; bool got_ipv4_address_{false}; bool keep_scan_results_{false}; - bool did_scan_this_cycle_{false}; + RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; bool skip_cooldown_next_cycle_{false}; bool post_connect_roaming_{true}; // Enabled by default RoamingState roaming_state_{RoamingState::IDLE}; From 723ca57617548887bd8b08dfc66f74cbdccadd9a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:17:32 -1000 Subject: [PATCH 0040/2030] [uptime] Format text sensor output on stack to avoid heap allocations (#13150) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../uptime/text_sensor/uptime_text_sensor.cpp | 94 ++++++++++++------- .../uptime/text_sensor/uptime_text_sensor.h | 1 - 2 files changed, 62 insertions(+), 33 deletions(-) diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index 94585379fe..b7b3273f39 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -9,6 +9,19 @@ namespace uptime { static const char *const TAG = "uptime.sensor"; +// Clamp position to valid buffer range when snprintf indicates truncation +static size_t clamp_buffer_pos(size_t pos, size_t buf_size) { return pos < buf_size ? pos : buf_size - 1; } + +static void append_unit(char *buf, size_t buf_size, size_t &pos, const char *separator, unsigned value, + const char *label) { + if (pos > 0) { + pos += snprintf(buf + pos, buf_size - pos, "%s", separator); + pos = clamp_buffer_pos(pos, buf_size); + } + pos += snprintf(buf + pos, buf_size - pos, "%u%s", value, label); + pos = clamp_buffer_pos(pos, buf_size); +} + void UptimeTextSensor::setup() { this->last_ms_ = millis(); if (this->last_ms_ < 60 * 1000) @@ -16,11 +29,6 @@ void UptimeTextSensor::setup() { this->update(); } -void UptimeTextSensor::insert_buffer_(std::string &buffer, const char *key, unsigned value) const { - buffer.insert(0, this->separator_); - buffer.insert(0, str_sprintf("%u%s", value, key)); -} - void UptimeTextSensor::update() { auto now = millis(); // get whole seconds since last update. Note that even if the millis count has overflowed between updates, @@ -29,36 +37,58 @@ void UptimeTextSensor::update() { this->last_ms_ = now - delta % 1000; // save remainder for next update delta /= 1000; this->uptime_ += delta; - auto uptime = this->uptime_; + uint32_t uptime = this->uptime_; unsigned interval = this->get_update_interval() / 1000; - std::string buffer{}; - // display from the largest unit that corresponds to the update interval, drop larger units that are zero. - while (true) { // enable use of break for early exit - unsigned remainder = uptime % 60; - uptime /= 60; - if (interval < 30) { - this->insert_buffer_(buffer, this->seconds_text_, remainder); - if (!this->expand_ && uptime == 0) - break; + + // Calculate all time units + unsigned seconds = uptime % 60; + uptime /= 60; + unsigned minutes = uptime % 60; + uptime /= 60; + unsigned hours = uptime % 24; + uptime /= 24; + unsigned days = uptime; + + // Determine which units to display based on interval thresholds + bool seconds_enabled = interval < 30; + bool minutes_enabled = interval < 1800; + bool hours_enabled = interval < 12 * 3600; + + // Show from highest non-zero unit (or all in expand mode) down to smallest enabled + bool show_days = this->expand_ || days > 0; + bool show_hours = hours_enabled && (show_days || hours > 0); + bool show_minutes = minutes_enabled && (show_hours || minutes > 0); + bool show_seconds = seconds_enabled && (show_minutes || seconds > 0); + + // If nothing shown, show smallest enabled unit + if (!show_days && !show_hours && !show_minutes && !show_seconds) { + if (seconds_enabled) { + show_seconds = true; + } else if (minutes_enabled) { + show_minutes = true; + } else if (hours_enabled) { + show_hours = true; + } else { + show_days = true; } - remainder = uptime % 60; - uptime /= 60; - if (interval < 1800) { - this->insert_buffer_(buffer, this->minutes_text_, remainder); - if (!this->expand_ && uptime == 0) - break; - } - remainder = uptime % 24; - uptime /= 24; - if (interval < 12 * 3600) { - this->insert_buffer_(buffer, this->hours_text_, remainder); - if (!this->expand_ && uptime == 0) - break; - } - this->insert_buffer_(buffer, this->days_text_, (unsigned) uptime); - break; } - this->publish_state(buffer); + + // Build output string on stack + // Home Assistant max state length is 255 chars + null terminator + char buf[256]; + size_t pos = 0; + buf[0] = '\0'; // Initialize for empty case + + if (show_days) + append_unit(buf, sizeof(buf), pos, this->separator_, days, this->days_text_); + if (show_hours) + append_unit(buf, sizeof(buf), pos, this->separator_, hours, this->hours_text_); + if (show_minutes) + append_unit(buf, sizeof(buf), pos, this->separator_, minutes, this->minutes_text_); + if (show_seconds) + append_unit(buf, sizeof(buf), pos, this->separator_, seconds, this->seconds_text_); + + this->publish_state(buf); } float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; } diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.h b/esphome/components/uptime/text_sensor/uptime_text_sensor.h index 8dd058998c..947d9c91e9 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.h +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.h @@ -29,7 +29,6 @@ class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent void set_seconds(const char *seconds_text) { this->seconds_text_ = seconds_text; } protected: - void insert_buffer_(std::string &buffer, const char *key, unsigned value) const; const char *days_text_; const char *hours_text_; const char *minutes_text_; From 6a3737bac3443f4d62cd2d793cdc4afa7c34bf0f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:17:44 -1000 Subject: [PATCH 0041/2030] [improv_serial] Use int8_to_str to avoid heap allocation for RSSI formatting (#13149) --- .../components/improv_serial/improv_serial_component.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 936ff414b1..17d630fe83 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -267,8 +267,10 @@ bool ImprovSerialComponent::parse_improv_payload_(improv::ImprovCommand &command if (std::find(networks.begin(), networks.end(), ssid) != networks.end()) continue; // Send each ssid separately to avoid overflowing the buffer - std::vector data = improv::build_rpc_response( - improv::GET_WIFI_NETWORKS, {ssid, str_sprintf("%d", scan.get_rssi()), YESNO(scan.get_with_auth())}, false); + char rssi_buf[5]; // int8_t: -128 to 127, max 4 chars + null + *int8_to_str(rssi_buf, scan.get_rssi()) = '\0'; + std::vector data = + improv::build_rpc_response(improv::GET_WIFI_NETWORKS, {ssid, rssi_buf, YESNO(scan.get_with_auth())}, false); this->send_response_(data); networks.push_back(ssid); } From 684790c2aba71738fb0cbbb326bb1c00d8849dca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:17:57 -1000 Subject: [PATCH 0042/2030] [web_server_idf] Reduce heap usage in DefaultHeaders and auth (#13141) --- .../components/web_server_base/__init__.py | 2 ++ .../web_server_base/web_server_base.h | 2 ++ .../web_server_idf/web_server_idf.cpp | 32 +++++++++++++------ .../web_server_idf/web_server_idf.h | 11 +++++-- esphome/core/defines.h | 1 + 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 4cf76eba0e..d5d75b395d 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -34,6 +34,8 @@ async def to_code(config): cg.add(cg.RawExpression(f"{web_server_base_ns}::global_web_server_base = {var}")) if CORE.is_esp32: + # Count for StaticVector in web_server_idf - matches headers added in init() + cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1) return if CORE.using_arduino: diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 7e95e00f29..0c25467f1b 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -100,6 +100,8 @@ class WebServerBase : public Component { } this->server_ = std::make_unique(this->port_); // All content is controlled and created by user - so allowing all origins is fine here. + // NOTE: Currently 1 header. If more are added, update in __init__.py: + // cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1) DefaultHeaders::Instance().addHeader(ESPHOME_F("Access-Control-Allow-Origin"), ESPHOME_F("*")); this->server_->begin(); diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 5062aa1e6c..55d2040a3a 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -309,8 +309,8 @@ void AsyncWebServerRequest::init_response_(AsyncWebServerResponse *rsp, int code } httpd_resp_set_hdr(*this, "Accept-Ranges", "none"); - for (const auto &pair : DefaultHeaders::Instance().headers_) { - httpd_resp_set_hdr(*this, pair.first.c_str(), pair.second.c_str()); + for (const auto &header : DefaultHeaders::Instance().headers_) { + httpd_resp_set_hdr(*this, header.name, header.value); } delete this->rsp_; @@ -335,17 +335,29 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw return false; } - std::string user_info; - user_info += username; - user_info += ':'; - user_info += password; + // Build user:pass in stack buffer to avoid heap allocation + constexpr size_t max_user_info_len = 256; + char user_info[max_user_info_len]; + size_t user_len = strlen(username); + size_t pass_len = strlen(password); + size_t user_info_len = user_len + 1 + pass_len; + + if (user_info_len >= max_user_info_len) { + ESP_LOGW(TAG, "Credentials too long for authentication"); + return false; + } + + memcpy(user_info, username, user_len); + user_info[user_len] = ':'; + memcpy(user_info + user_len + 1, password, pass_len); + user_info[user_info_len] = '\0'; size_t n = 0, out; - esp_crypto_base64_encode(nullptr, 0, &n, reinterpret_cast(user_info.c_str()), user_info.size()); + esp_crypto_base64_encode(nullptr, 0, &n, reinterpret_cast(user_info), user_info_len); auto digest = std::unique_ptr(new char[n + 1]); esp_crypto_base64_encode(reinterpret_cast(digest.get()), n, &out, - reinterpret_cast(user_info.c_str()), user_info.size()); + reinterpret_cast(user_info), user_info_len); return strcmp(digest.get(), auth_str + auth_prefix_len) == 0; } @@ -483,8 +495,8 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(const AsyncWebServerRequest * httpd_resp_set_hdr(req, "Cache-Control", "no-cache"); httpd_resp_set_hdr(req, "Connection", "keep-alive"); - for (const auto &pair : DefaultHeaders::Instance().headers_) { - httpd_resp_set_hdr(req, pair.first.c_str(), pair.second.c_str()); + for (const auto &header : DefaultHeaders::Instance().headers_) { + httpd_resp_set_hdr(req, header.name, header.value); } httpd_resp_send_chunk(req, CRLF_STR, CRLF_LEN); diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index cae7006d96..2a334a11e3 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -2,6 +2,7 @@ #ifdef USE_ESP32 #include "esphome/core/defines.h" +#include "esphome/core/helpers.h" #include #include @@ -327,6 +328,11 @@ class AsyncEventSource : public AsyncWebHandler { }; #endif // USE_WEBSERVER +struct HttpHeader { + const char *name; + const char *value; +}; + class DefaultHeaders { friend class AsyncWebServerRequest; #ifdef USE_WEBSERVER @@ -335,13 +341,14 @@ class DefaultHeaders { public: // NOLINTNEXTLINE(readability-identifier-naming) - void addHeader(const char *name, const char *value) { this->headers_.emplace_back(name, value); } + void addHeader(const char *name, const char *value) { this->headers_.push_back({name, value}); } // NOLINTNEXTLINE(readability-identifier-naming) static DefaultHeaders &Instance(); protected: - std::vector> headers_; + // Stack-allocated, no reallocation machinery. Count defined in web_server_base where headers are added. + StaticVector headers_; }; } // namespace web_server_idf diff --git a/esphome/core/defines.h b/esphome/core/defines.h index ae94f6ef5f..adb2921b68 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -213,6 +213,7 @@ #define USE_WEBSERVER_PORT 80 // NOLINT #define USE_WEBSERVER_GZIP #define USE_WEBSERVER_SORTING +#define WEB_SERVER_DEFAULT_HEADERS_COUNT 1 #define USE_CAPTIVE_PORTAL_GZIP #define USE_WIFI_11KV_SUPPORT #define USE_WIFI_FAST_CONNECT From 26e90b4ca6cb1ee6fcf1e98deb3e45cc9db89b39 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:18:13 -1000 Subject: [PATCH 0043/2030] [light] Move LightColorValues::lerp() out of header to reduce code duplication (#13138) --- .../components/light/light_color_values.cpp | 28 +++++++++++++++++++ esphome/components/light/light_color_values.h | 21 +------------- 2 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 esphome/components/light/light_color_values.cpp diff --git a/esphome/components/light/light_color_values.cpp b/esphome/components/light/light_color_values.cpp new file mode 100644 index 0000000000..2f22bb3c68 --- /dev/null +++ b/esphome/components/light/light_color_values.cpp @@ -0,0 +1,28 @@ +#include "light_color_values.h" + +#include + +namespace esphome::light { + +LightColorValues LightColorValues::lerp(const LightColorValues &start, const LightColorValues &end, float completion) { + // Directly interpolate the raw values to avoid getter/setter overhead. + // This is safe because: + // - All LightColorValues have their values clamped when set via the setters + // - std::lerp guarantees output is in the same range as inputs + // - Therefore the output doesn't need clamping, so we can skip the setters + LightColorValues v; + v.color_mode_ = end.color_mode_; + v.state_ = std::lerp(start.state_, end.state_, completion); + v.brightness_ = std::lerp(start.brightness_, end.brightness_, completion); + v.color_brightness_ = std::lerp(start.color_brightness_, end.color_brightness_, completion); + v.red_ = std::lerp(start.red_, end.red_, completion); + v.green_ = std::lerp(start.green_, end.green_, completion); + v.blue_ = std::lerp(start.blue_, end.blue_, completion); + v.white_ = std::lerp(start.white_, end.white_, completion); + v.color_temperature_ = std::lerp(start.color_temperature_, end.color_temperature_, completion); + v.cold_white_ = std::lerp(start.cold_white_, end.cold_white_, completion); + v.warm_white_ = std::lerp(start.warm_white_, end.warm_white_, completion); + return v; +} + +} // namespace esphome::light diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index bedfad2c35..97756b9f26 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -82,26 +82,7 @@ class LightColorValues { * @param completion The completion value. 0 -> start, 1 -> end. * @return The linearly interpolated LightColorValues. */ - static LightColorValues lerp(const LightColorValues &start, const LightColorValues &end, float completion) { - // Directly interpolate the raw values to avoid getter/setter overhead. - // This is safe because: - // - All LightColorValues have their values clamped when set via the setters - // - std::lerp guarantees output is in the same range as inputs - // - Therefore the output doesn't need clamping, so we can skip the setters - LightColorValues v; - v.color_mode_ = end.color_mode_; - v.state_ = std::lerp(start.state_, end.state_, completion); - v.brightness_ = std::lerp(start.brightness_, end.brightness_, completion); - v.color_brightness_ = std::lerp(start.color_brightness_, end.color_brightness_, completion); - v.red_ = std::lerp(start.red_, end.red_, completion); - v.green_ = std::lerp(start.green_, end.green_, completion); - v.blue_ = std::lerp(start.blue_, end.blue_, completion); - v.white_ = std::lerp(start.white_, end.white_, completion); - v.color_temperature_ = std::lerp(start.color_temperature_, end.color_temperature_, completion); - v.cold_white_ = std::lerp(start.cold_white_, end.cold_white_, completion); - v.warm_white_ = std::lerp(start.warm_white_, end.warm_white_, completion); - return v; - } + static LightColorValues lerp(const LightColorValues &start, const LightColorValues &end, float completion); /** Normalize the color (RGB/W) component. * From ace3ff21700803740e0ca687dc49e2faf6d70f6e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:18:24 -1000 Subject: [PATCH 0044/2030] [safe_mode] Conditionally compile callback when on_safe_mode is configured (#13136) --- esphome/components/safe_mode/__init__.py | 8 +++++--- esphome/components/safe_mode/automation.h | 11 +++++++---- esphome/components/safe_mode/safe_mode.cpp | 8 ++++---- esphome/components/safe_mode/safe_mode.h | 10 ++++++---- esphome/core/defines.h | 1 + 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index 9944d71722..d1754aaad7 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -59,9 +59,11 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - for conf in config.get(CONF_ON_SAFE_MODE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + if on_safe_mode_config := config.get(CONF_ON_SAFE_MODE): + cg.add_define("USE_SAFE_MODE_CALLBACK") + for conf in on_safe_mode_config: + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) condition = var.should_enter_safe_mode( config[CONF_NUM_ATTEMPTS], diff --git a/esphome/components/safe_mode/automation.h b/esphome/components/safe_mode/automation.h index 1ffa86a588..952ed4da33 100644 --- a/esphome/components/safe_mode/automation.h +++ b/esphome/components/safe_mode/automation.h @@ -1,10 +1,12 @@ #pragma once +#include "esphome/core/defines.h" + +#ifdef USE_SAFE_MODE_CALLBACK #include "safe_mode.h" #include "esphome/core/automation.h" -namespace esphome { -namespace safe_mode { +namespace esphome::safe_mode { class SafeModeTrigger : public Trigger<> { public: @@ -13,5 +15,6 @@ class SafeModeTrigger : public Trigger<> { } }; -} // namespace safe_mode -} // namespace esphome +} // namespace esphome::safe_mode + +#endif // USE_SAFE_MODE_CALLBACK diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index c7bd8748f5..ef6ebea247 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -13,8 +13,7 @@ #include #endif -namespace esphome { -namespace safe_mode { +namespace esphome::safe_mode { static const char *const TAG = "safe_mode"; @@ -126,7 +125,9 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en ESP_LOGW(TAG, "SAFE MODE IS ACTIVE"); +#ifdef USE_SAFE_MODE_CALLBACK this->safe_mode_callback_.call(); +#endif return true; } @@ -157,5 +158,4 @@ void SafeModeComponent::on_safe_shutdown() { this->clean_rtc(); } -} // namespace safe_mode -} // namespace esphome +} // namespace esphome::safe_mode diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 028b7b11cb..4aefd11458 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -5,8 +5,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" -namespace esphome { -namespace safe_mode { +namespace esphome::safe_mode { /// SafeModeComponent provides a safe way to recover from repeated boot failures class SafeModeComponent : public Component { @@ -25,9 +24,11 @@ class SafeModeComponent : public Component { void on_safe_shutdown() override; +#ifdef USE_SAFE_MODE_CALLBACK void add_on_safe_mode_callback(std::function &&callback) { this->safe_mode_callback_.add(std::move(callback)); } +#endif protected: void write_rtc_(uint32_t val); @@ -43,11 +44,12 @@ class SafeModeComponent : public Component { uint8_t safe_mode_num_attempts_{0}; // Larger objects at the end ESPPreferenceObject rtc_; +#ifdef USE_SAFE_MODE_CALLBACK CallbackManager safe_mode_callback_{}; +#endif static const uint32_t ENTER_SAFE_MODE_MAGIC = 0x5afe5afe; ///< a magic number to indicate that safe mode should be entered on next boot }; -} // namespace safe_mode -} // namespace esphome +} // namespace esphome::safe_mode diff --git a/esphome/core/defines.h b/esphome/core/defines.h index adb2921b68..ed5f152e9f 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -100,6 +100,7 @@ #define USE_OUTPUT #define USE_POWER_SUPPLY #define USE_QR_CODE +#define USE_SAFE_MODE_CALLBACK #define USE_SELECT #define USE_SENSOR #define USE_STATUS_LED From 52132ea3bc6e575f621bb0ade5a75ba7ea084714 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:18:37 -1000 Subject: [PATCH 0045/2030] [ch422g][lc709203f][qmc5883l] Avoid heap allocation in status_set_warning calls (#13152) --- esphome/components/ch422g/ch422g.cpp | 8 ++++++-- esphome/components/lc709203f/lc709203f.cpp | 14 +++++++++----- esphome/components/qmc5883l/qmc5883l.cpp | 12 +++++++++--- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index f47b67da6f..d031c31294 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -93,7 +93,9 @@ bool CH422GComponent::read_inputs_() { bool CH422GComponent::write_reg_(uint8_t reg, uint8_t value) { auto err = this->bus_->write_readv(reg, &value, 1, nullptr, 0); if (err != i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("write failed for register 0x%X, error %d", reg, err).c_str()); + char buf[64]; + snprintf(buf, sizeof(buf), "write failed for register 0x%X, error %d", reg, err); + this->status_set_warning(buf); return false; } this->status_clear_warning(); @@ -104,7 +106,9 @@ uint8_t CH422GComponent::read_reg_(uint8_t reg) { uint8_t value; auto err = this->bus_->write_readv(reg, nullptr, 0, &value, 1); if (err != i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("read failed for register 0x%X, error %d", reg, err).c_str()); + char buf[64]; + snprintf(buf, sizeof(buf), "read failed for register 0x%X, error %d", reg, err); + this->status_set_warning(buf); return 0; } this->status_clear_warning(); diff --git a/esphome/components/lc709203f/lc709203f.cpp b/esphome/components/lc709203f/lc709203f.cpp index ad9d6b3098..8c7018124a 100644 --- a/esphome/components/lc709203f/lc709203f.cpp +++ b/esphome/components/lc709203f/lc709203f.cpp @@ -183,11 +183,14 @@ uint8_t Lc709203f::get_register_(uint8_t register_to_read, uint16_t *register_va return_code = this->read_register(register_to_read, &read_buffer[3], 3); if (return_code != i2c::NO_ERROR) { // Error on the i2c bus - this->status_set_warning( - str_sprintf("Error code %d when reading from register 0x%02X", return_code, register_to_read).c_str()); + char buf[64]; + snprintf(buf, sizeof(buf), "Error code %d when reading from register 0x%02X", return_code, register_to_read); + this->status_set_warning(buf); } else if (crc8(read_buffer, 5, 0x00, 0x07, true) != read_buffer[5]) { // I2C indicated OK, but the CRC of the data does not matcth. - this->status_set_warning(str_sprintf("CRC error reading from register 0x%02X", register_to_read).c_str()); + char buf[64]; + snprintf(buf, sizeof(buf), "CRC error reading from register 0x%02X", register_to_read); + this->status_set_warning(buf); } else { *register_value = ((uint16_t) read_buffer[4] << 8) | (uint16_t) read_buffer[3]; return i2c::NO_ERROR; @@ -225,8 +228,9 @@ uint8_t Lc709203f::set_register_(uint8_t register_to_set, uint16_t value_to_set) if (return_code == i2c::NO_ERROR) { return return_code; } else { - this->status_set_warning( - str_sprintf("Error code %d when writing to register 0x%02X", return_code, register_to_set).c_str()); + char buf[64]; + snprintf(buf, sizeof(buf), "Error code %d when writing to register 0x%02X", return_code, register_to_set); + this->status_set_warning(buf); } } diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index d2041a2d52..693614581c 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -105,7 +105,9 @@ void QMC5883LComponent::update() { if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG) { err = this->read_register(QMC5883L_REGISTER_STATUS, &status, 1); if (err != i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("status read failed (%d)", err).c_str()); + char buf[32]; + snprintf(buf, sizeof(buf), "status read failed (%d)", err); + this->status_set_warning(buf); return; } } @@ -127,7 +129,9 @@ void QMC5883LComponent::update() { } err = this->read_bytes_16_le_(start, &raw[dest], 3 - dest); if (err != i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("mag read failed (%d)", err).c_str()); + char buf[32]; + snprintf(buf, sizeof(buf), "mag read failed (%d)", err); + this->status_set_warning(buf); return; } @@ -155,7 +159,9 @@ void QMC5883LComponent::update() { uint16_t raw_temp; err = this->read_bytes_16_le_(QMC5883L_REGISTER_TEMPERATURE_LSB, &raw_temp); if (err != i2c::ERROR_OK) { - this->status_set_warning(str_sprintf("temp read failed (%d)", err).c_str()); + char buf[32]; + snprintf(buf, sizeof(buf), "temp read failed (%d)", err); + this->status_set_warning(buf); return; } temp = int16_t(raw_temp) * 0.01f; From 38e2e4a56d86f8b5f665a6ab6e66519de5513666 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:18:49 -1000 Subject: [PATCH 0046/2030] [runtime_stats] Fix log output formatting alignment (#13155) --- esphome/components/runtime_stats/runtime_stats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index 7e837a18e8..9a1e1a109a 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -29,7 +29,7 @@ void RuntimeStatsCollector::record_component_time(Component *component, uint32_t void RuntimeStatsCollector::log_stats_() { ESP_LOGI(TAG, "Component Runtime Statistics\n" - "Period stats (last %" PRIu32 "ms):", + " Period stats (last %" PRIu32 "ms):", this->log_interval_); // First collect stats we want to display @@ -55,7 +55,7 @@ void RuntimeStatsCollector::log_stats_() { } // Log total stats since boot - ESP_LOGI(TAG, "Total stats (since boot):"); + ESP_LOGI(TAG, " Total stats (since boot):"); // Re-sort by total runtime for all-time stats std::sort(stats_to_display.begin(), stats_to_display.end(), From 45c0796e40bda25ef741bcda5818d4476dc09fda Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:19:00 -1000 Subject: [PATCH 0047/2030] [ci] Add RP2040 to memory impact analysis (#13134) --- script/determine-jobs.py | 11 ++- tests/script/test_determine_jobs.py | 129 ++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 4 deletions(-) diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 44e8e4b5ab..a61c9bf08d 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -90,6 +90,7 @@ class Platform(StrEnum): ESP32_S2_IDF = "esp32-s2-idf" ESP32_S3_IDF = "esp32-s3-idf" BK72XX_ARD = "bk72xx-ard" # LibreTiny BK7231N + RP2040_ARD = "rp2040-ard" # Raspberry Pi Pico # Memory impact analysis constants @@ -122,6 +123,7 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset( # 3. ESP32 IDF - Primary ESP32 platform, most representative of modern ESPHome # 4-6. Other ESP32 variants - Less commonly used but still supported # 7. BK72XX - LibreTiny platform (good for detecting LibreTiny-specific changes) +# 8. RP2040 - Raspberry Pi Pico platform MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee) Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained, fastest builds) @@ -130,6 +132,7 @@ MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.ESP32_S2_IDF, # ESP32-S2 IDF Platform.ESP32_S3_IDF, # ESP32-S3 IDF Platform.BK72XX_ARD, # LibreTiny BK7231N + Platform.RP2040_ARD, # Raspberry Pi Pico ] @@ -408,7 +411,7 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None: - wifi_component_esp8266.cpp, *_esp8266.h -> ESP8266_ARD - *_esp32*.cpp -> ESP32 IDF (generic) - *_libretiny.cpp, *_bk72*.* -> BK72XX (LibreTiny) - - *_pico.cpp, *_rp2040.* -> RP2040 (not in preference list) + - *_pico.cpp, *_rp2040.* -> RP2040_ARD Args: filename: File path to check @@ -445,9 +448,9 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None: if "libretiny" in filename_lower or "bk72" in filename_lower: return Platform.BK72XX_ARD - # RP2040 is not in MEMORY_IMPACT_PLATFORM_PREFERENCE - # if "pico" in filename_lower or "rp2040" in filename_lower: - # return None # No RP2040 platform preference + # RP2040 / Raspberry Pi Pico + if "pico" in filename_lower or "rp2040" in filename_lower: + return Platform.RP2040_ARD return None diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 291a23967b..bd20cb3e21 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -1421,6 +1421,135 @@ def test_detect_memory_impact_config_runs_at_component_limit(tmp_path: Path) -> assert len(result["components"]) == 40 +# Tests for _detect_platform_hint_from_filename function + + +@pytest.mark.parametrize( + ("filename", "expected_platform"), + [ + # ESP-IDF platform detection + ("esphome/components/wifi/wifi_esp_idf.cpp", determine_jobs.Platform.ESP32_IDF), + ( + "esphome/components/wifi/wifi_component_esp_idf.cpp", + determine_jobs.Platform.ESP32_IDF, + ), + ( + "esphome/components/ethernet/ethernet_idf.cpp", + determine_jobs.Platform.ESP32_IDF, + ), + # ESP32 variant detection with IDF suffix + ( + "esphome/components/ble/esp32c3_idf.cpp", + determine_jobs.Platform.ESP32_C3_IDF, + ), + ( + "esphome/components/ble/esp32c6_idf.cpp", + determine_jobs.Platform.ESP32_C6_IDF, + ), + ( + "esphome/components/ble/esp32s2_idf.cpp", + determine_jobs.Platform.ESP32_S2_IDF, + ), + ( + "esphome/components/ble/esp32s3_idf.cpp", + determine_jobs.Platform.ESP32_S3_IDF, + ), + # ESP8266 detection + ( + "esphome/components/wifi/wifi_esp8266.cpp", + determine_jobs.Platform.ESP8266_ARD, + ), + ("esphome/core/helpers_esp8266.h", determine_jobs.Platform.ESP8266_ARD), + # Generic ESP32 detection (without IDF suffix) + ("esphome/components/wifi/wifi_esp32.cpp", determine_jobs.Platform.ESP32_IDF), + ( + "esphome/components/ethernet/ethernet_esp32.cpp", + determine_jobs.Platform.ESP32_IDF, + ), + # LibreTiny / BK72xx detection + ( + "esphome/components/wifi/wifi_libretiny.cpp", + determine_jobs.Platform.BK72XX_ARD, + ), + ("esphome/components/ble/ble_bk72xx.cpp", determine_jobs.Platform.BK72XX_ARD), + # RP2040 / Raspberry Pi Pico detection + ("esphome/components/gpio/gpio_rp2040.cpp", determine_jobs.Platform.RP2040_ARD), + ("esphome/components/wifi/wifi_rp2040.cpp", determine_jobs.Platform.RP2040_ARD), + ("esphome/components/i2c/i2c_pico.cpp", determine_jobs.Platform.RP2040_ARD), + ("esphome/components/spi/spi_pico.cpp", determine_jobs.Platform.RP2040_ARD), + ( + "tests/components/rp2040/test.rp2040-ard.yaml", + determine_jobs.Platform.RP2040_ARD, + ), + # No platform hint (generic files) + ("esphome/components/wifi/wifi.cpp", None), + ("esphome/components/sensor/sensor.h", None), + ("esphome/core/helpers.h", None), + ("README.md", None), + ], + ids=[ + "esp_idf_suffix", + "esp_idf_component_suffix", + "idf_suffix", + "esp32c3_idf", + "esp32c6_idf", + "esp32s2_idf", + "esp32s3_idf", + "esp8266_suffix", + "esp8266_core_header", + "generic_esp32", + "esp32_in_name", + "libretiny", + "bk72xx", + "rp2040_gpio", + "rp2040_wifi", + "pico_i2c", + "pico_spi", + "rp2040_test_yaml", + "generic_wifi_no_hint", + "generic_sensor_no_hint", + "core_helpers_no_hint", + "readme_no_hint", + ], +) +def test_detect_platform_hint_from_filename( + filename: str, expected_platform: determine_jobs.Platform | None +) -> None: + """Test _detect_platform_hint_from_filename correctly detects platform hints.""" + result = determine_jobs._detect_platform_hint_from_filename(filename) + assert result == expected_platform + + +@pytest.mark.parametrize( + ("filename", "expected_platform"), + [ + # RP2040/Pico with different cases + ("file_RP2040.cpp", determine_jobs.Platform.RP2040_ARD), + ("file_Rp2040.cpp", determine_jobs.Platform.RP2040_ARD), + ("file_PICO.cpp", determine_jobs.Platform.RP2040_ARD), + ("file_Pico.cpp", determine_jobs.Platform.RP2040_ARD), + # ESP8266 with different cases + ("file_ESP8266.cpp", determine_jobs.Platform.ESP8266_ARD), + # ESP32 with different cases + ("file_ESP32.cpp", determine_jobs.Platform.ESP32_IDF), + ], + ids=[ + "rp2040_uppercase", + "rp2040_mixedcase", + "pico_uppercase", + "pico_titlecase", + "esp8266_uppercase", + "esp32_uppercase", + ], +) +def test_detect_platform_hint_from_filename_case_insensitive( + filename: str, expected_platform: determine_jobs.Platform +) -> None: + """Test that platform detection is case-insensitive.""" + result = determine_jobs._detect_platform_hint_from_filename(filename) + assert result == expected_platform + + def test_component_batching_beta_branch_40_per_batch( tmp_path: Path, mock_should_run_integration_tests: Mock, From eeeae53f76b57c52af9ca442d6e9aba7ca8521db Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:40:09 -1000 Subject: [PATCH 0048/2030] [fan] Return StringRef from get_preset_mode() for safety and modern API (#13092) --- esphome/components/api/api_connection.cpp | 2 +- esphome/components/copy/fan/copy_fan.cpp | 18 ++++--- esphome/components/copy/fan/copy_fan.h | 2 +- esphome/components/fan/automation.h | 7 ++- esphome/components/fan/fan.cpp | 45 ++++++++++++----- esphome/components/fan/fan.h | 14 ++++-- .../components/hbridge/fan/hbridge_fan.cpp | 2 +- esphome/components/speed/fan/speed_fan.cpp | 2 +- .../components/template/fan/template_fan.cpp | 2 +- tests/components/copy/common.yaml | 3 ++ tests/components/fan/common.yaml | 48 +++++++++++++++++++ 11 files changed, 113 insertions(+), 32 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index fb3548d117..4bc19a8bad 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -443,7 +443,7 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co if (traits.supports_direction()) msg.direction = static_cast(fan->direction); if (traits.supports_preset_modes() && fan->has_preset_mode()) - msg.preset_mode = StringRef(fan->get_preset_mode()); + msg.preset_mode = fan->get_preset_mode(); return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); } uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, diff --git a/esphome/components/copy/fan/copy_fan.cpp b/esphome/components/copy/fan/copy_fan.cpp index d35ece950b..b4a43cf2f1 100644 --- a/esphome/components/copy/fan/copy_fan.cpp +++ b/esphome/components/copy/fan/copy_fan.cpp @@ -8,20 +8,24 @@ static const char *const TAG = "copy.fan"; void CopyFan::setup() { source_->add_on_state_callback([this]() { - this->state = source_->state; - this->oscillating = source_->oscillating; - this->speed = source_->speed; - this->direction = source_->direction; - this->set_preset_mode_(source_->get_preset_mode()); + this->copy_state_from_source_(); this->publish_state(); }); + this->copy_state_from_source_(); + this->publish_state(); +} + +void CopyFan::copy_state_from_source_() { this->state = source_->state; this->oscillating = source_->oscillating; this->speed = source_->speed; this->direction = source_->direction; - this->set_preset_mode_(source_->get_preset_mode()); - this->publish_state(); + if (source_->has_preset_mode()) { + this->set_preset_mode_(source_->get_preset_mode()); + } else { + this->clear_preset_mode_(); + } } void CopyFan::dump_config() { LOG_FAN("", "Copy Fan", this); } diff --git a/esphome/components/copy/fan/copy_fan.h b/esphome/components/copy/fan/copy_fan.h index b474975bc4..988129f07b 100644 --- a/esphome/components/copy/fan/copy_fan.h +++ b/esphome/components/copy/fan/copy_fan.h @@ -16,7 +16,7 @@ class CopyFan : public fan::Fan, public Component { protected: void control(const fan::FanCall &call) override; - ; + void copy_state_from_source_(); fan::Fan *source_; }; diff --git a/esphome/components/fan/automation.h b/esphome/components/fan/automation.h index ce1db6fc64..77abc2f13f 100644 --- a/esphome/components/fan/automation.h +++ b/esphome/components/fan/automation.h @@ -212,19 +212,18 @@ class FanPresetSetTrigger : public Trigger { public: FanPresetSetTrigger(Fan *state) { state->add_on_state_callback([this, state]() { - const auto *preset_mode = state->get_preset_mode(); + auto preset_mode = state->get_preset_mode(); auto should_trigger = preset_mode != this->last_preset_mode_; this->last_preset_mode_ = preset_mode; if (should_trigger) { - // Trigger with empty string when nullptr to maintain backward compatibility - this->trigger(preset_mode != nullptr ? preset_mode : ""); + this->trigger(std::string(preset_mode)); } }); this->last_preset_mode_ = state->get_preset_mode(); } protected: - const char *last_preset_mode_{nullptr}; + StringRef last_preset_mode_{}; }; } // namespace fan diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 0ffb60e50d..2e48d84eb9 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -61,7 +61,7 @@ void FanCall::perform() { if (this->direction_.has_value()) { ESP_LOGD(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(*this->direction_))); } - if (this->has_preset_mode()) { + if (this->preset_mode_ != nullptr) { ESP_LOGD(TAG, " Preset Mode: %s", this->preset_mode_); } this->parent_.control(*this); @@ -83,7 +83,7 @@ void FanCall::validate_() { *this->binary_state_ // ..,and no preset mode will be active... && !this->has_preset_mode() && - this->parent_.get_preset_mode() == nullptr + !this->parent_.has_preset_mode() // ...and neither current nor new speed is available... && traits.supports_speed() && this->parent_.speed == 0 && !this->speed_.has_value()) { // ...set speed to 100% @@ -154,16 +154,16 @@ const char *Fan::find_preset_mode_(const char *preset_mode, size_t len) { return this->get_traits().find_preset_mode(preset_mode, len); } -bool Fan::set_preset_mode_(const char *preset_mode) { - if (preset_mode == nullptr) { - // Treat nullptr as clearing the preset mode +bool Fan::set_preset_mode_(const char *preset_mode, size_t len) { + if (preset_mode == nullptr || len == 0) { + // Treat nullptr or empty string as clearing the preset mode (no valid preset is "") if (this->preset_mode_ == nullptr) { return false; // No change } this->clear_preset_mode_(); return true; } - const char *validated = this->find_preset_mode_(preset_mode); + const char *validated = this->find_preset_mode_(preset_mode, len); if (validated == nullptr || this->preset_mode_ == validated) { return false; // Preset mode not supported or no change } @@ -171,10 +171,31 @@ bool Fan::set_preset_mode_(const char *preset_mode) { return true; } -bool Fan::set_preset_mode_(const std::string &preset_mode) { return this->set_preset_mode_(preset_mode.c_str()); } +bool Fan::set_preset_mode_(const char *preset_mode) { + return this->set_preset_mode_(preset_mode, preset_mode ? strlen(preset_mode) : 0); +} + +bool Fan::set_preset_mode_(const std::string &preset_mode) { + return this->set_preset_mode_(preset_mode.data(), preset_mode.size()); +} + +bool Fan::set_preset_mode_(StringRef preset_mode) { + // Safe: find_preset_mode_ only uses the input for comparison and returns + // a pointer from traits, so the input StringRef's lifetime doesn't matter. + return this->set_preset_mode_(preset_mode.c_str(), preset_mode.size()); +} void Fan::clear_preset_mode_() { this->preset_mode_ = nullptr; } +void Fan::apply_preset_mode_(const FanCall &call) { + if (call.has_preset_mode()) { + this->set_preset_mode_(call.get_preset_mode()); + } else if (call.get_speed().has_value()) { + // Manually setting speed clears preset (per Home Assistant convention) + this->clear_preset_mode_(); + } +} + void Fan::add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); } void Fan::publish_state() { auto traits = this->get_traits(); @@ -192,9 +213,8 @@ void Fan::publish_state() { if (traits.supports_direction()) { ESP_LOGD(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(this->direction))); } - const char *preset = this->get_preset_mode(); - if (preset != nullptr) { - ESP_LOGD(TAG, " Preset Mode: %s", preset); + if (this->preset_mode_ != nullptr) { + ESP_LOGD(TAG, " Preset Mode: %s", this->preset_mode_); } this->state_callback_.call(); #if defined(USE_FAN) && defined(USE_CONTROLLER_REGISTRY) @@ -249,12 +269,11 @@ void Fan::save_state_() { state.speed = this->speed; state.direction = this->direction; - const char *preset = this->get_preset_mode(); - if (preset != nullptr) { + if (this->has_preset_mode()) { const auto &preset_modes = traits.supported_preset_modes(); // Find index of current preset mode (pointer comparison is safe since preset is from traits) for (size_t i = 0; i < preset_modes.size(); i++) { - if (preset_modes[i] == preset) { + if (preset_modes[i] == this->preset_mode_) { state.preset_mode = i; break; } diff --git a/esphome/components/fan/fan.h b/esphome/components/fan/fan.h index 7c79fda83e..55d4ba8825 100644 --- a/esphome/components/fan/fan.h +++ b/esphome/components/fan/fan.h @@ -5,6 +5,7 @@ #include "esphome/core/log.h" #include "esphome/core/optional.h" #include "esphome/core/preferences.h" +#include "esphome/core/string_ref.h" #include "fan_traits.h" namespace esphome { @@ -128,8 +129,11 @@ class Fan : public EntityBase { /// Set the restore mode of this fan. void set_restore_mode(FanRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } - /// Get the current preset mode (returns pointer to string stored in traits, or nullptr if not set) - const char *get_preset_mode() const { return this->preset_mode_; } + /// Get the current preset mode. + /// Returns a StringRef of the string stored in traits, or empty ref if not set. + /// The returned ref points to string literals from codegen (static storage). + /// Traits are set once at startup and valid for the lifetime of the program. + StringRef get_preset_mode() const { return StringRef::from_maybe_nullptr(this->preset_mode_); } /// Check if a preset mode is currently active bool has_preset_mode() const { return this->preset_mode_ != nullptr; } @@ -146,11 +150,15 @@ class Fan : public EntityBase { void dump_traits_(const char *tag, const char *prefix); /// Set the preset mode (finds and stores pointer from traits). Returns true if changed. + /// Passing nullptr or empty string clears the preset mode. + bool set_preset_mode_(const char *preset_mode, size_t len); bool set_preset_mode_(const char *preset_mode); - /// Set the preset mode (finds and stores pointer from traits). Returns true if changed. bool set_preset_mode_(const std::string &preset_mode); + bool set_preset_mode_(StringRef preset_mode); /// Clear the preset mode void clear_preset_mode_(); + /// Apply preset mode from a FanCall (handles speed-clears-preset convention) + void apply_preset_mode_(const FanCall &call); /// Find and return the matching preset mode pointer from traits, or nullptr if not found. const char *find_preset_mode_(const char *preset_mode); const char *find_preset_mode_(const char *preset_mode, size_t len); diff --git a/esphome/components/hbridge/fan/hbridge_fan.cpp b/esphome/components/hbridge/fan/hbridge_fan.cpp index 488208b725..9bf58f9d1e 100644 --- a/esphome/components/hbridge/fan/hbridge_fan.cpp +++ b/esphome/components/hbridge/fan/hbridge_fan.cpp @@ -57,7 +57,7 @@ void HBridgeFan::control(const fan::FanCall &call) { this->oscillating = *call.get_oscillating(); if (call.get_direction().has_value()) this->direction = *call.get_direction(); - this->set_preset_mode_(call.get_preset_mode()); + this->apply_preset_mode_(call); this->write_state_(); this->publish_state(); diff --git a/esphome/components/speed/fan/speed_fan.cpp b/esphome/components/speed/fan/speed_fan.cpp index 801593c2ac..af98e3a51f 100644 --- a/esphome/components/speed/fan/speed_fan.cpp +++ b/esphome/components/speed/fan/speed_fan.cpp @@ -29,7 +29,7 @@ void SpeedFan::control(const fan::FanCall &call) { this->oscillating = *call.get_oscillating(); if (call.get_direction().has_value()) this->direction = *call.get_direction(); - this->set_preset_mode_(call.get_preset_mode()); + this->apply_preset_mode_(call); this->write_state_(); this->publish_state(); diff --git a/esphome/components/template/fan/template_fan.cpp b/esphome/components/template/fan/template_fan.cpp index 384e6b0ca1..0e1920a984 100644 --- a/esphome/components/template/fan/template_fan.cpp +++ b/esphome/components/template/fan/template_fan.cpp @@ -28,7 +28,7 @@ void TemplateFan::control(const fan::FanCall &call) { this->oscillating = *call.get_oscillating(); if (call.get_direction().has_value() && this->has_direction_) this->direction = *call.get_direction(); - this->set_preset_mode_(call.get_preset_mode()); + this->apply_preset_mode_(call); this->publish_state(); } diff --git a/tests/components/copy/common.yaml b/tests/components/copy/common.yaml index a73b3467e6..a376004b2f 100644 --- a/tests/components/copy/common.yaml +++ b/tests/components/copy/common.yaml @@ -7,6 +7,9 @@ fan: - platform: speed id: fan_speed output: fan_output_1 + preset_modes: + - Eco + - Turbo - platform: copy source_id: fan_speed name: Fan Speed Copy diff --git a/tests/components/fan/common.yaml b/tests/components/fan/common.yaml index 55c2a656fd..099bbfef08 100644 --- a/tests/components/fan/common.yaml +++ b/tests/components/fan/common.yaml @@ -9,3 +9,51 @@ fan: has_oscillating: true has_direction: true speed_count: 3 + +# Test lambdas using get_preset_mode() which returns StringRef +# These examples match the migration guide in the PR description +binary_sensor: + - platform: template + id: fan_has_preset + name: "Fan Has Preset" + lambda: |- + // Migration guide: Checking if preset mode is set + // Use empty() or has_preset_mode() + if (!id(test_fan).get_preset_mode().empty()) { + // preset is set + } + if (id(test_fan).has_preset_mode()) { + // preset is set + } + + // Migration guide: Comparing preset mode + // Use == operator directly (safe, works even when empty) + if (id(test_fan).get_preset_mode() == "Eco") { + return true; + } + + // Migration guide: Checking for no preset + if (id(test_fan).get_preset_mode().empty()) { + // no preset + } + if (!id(test_fan).has_preset_mode()) { + // no preset + } + + // Migration guide: Getting as std::string + std::string preset = std::string(id(test_fan).get_preset_mode()); + + // Migration guide: Logging option 1 + // Use .c_str() - works because StringRef points to null-terminated string in traits + ESP_LOGD("test", "Preset: %s", id(test_fan).get_preset_mode().c_str()); + + // Migration guide: Logging option 2 + // Use %.*s format (safer, no null-termination assumption) + auto preset_ref = id(test_fan).get_preset_mode(); + ESP_LOGD("test", "Preset: %.*s", (int)preset_ref.size(), preset_ref.c_str()); + + // Test != comparison + if (id(test_fan).get_preset_mode() != "Sleep") { + return true; + } + return false; From 23f9f70b7187c4b8a292ccf3f0751ccbd6167c96 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:40:43 -1000 Subject: [PATCH 0049/2030] [select] Return StringRef from current_option() (#13095) --- esphome/components/api/api_connection.cpp | 2 +- .../display_menu_base/menu_item.cpp | 3 +- esphome/components/ld2410/ld2410.cpp | 7 ++-- esphome/components/ld2412/ld2412.cpp | 7 ++-- esphome/components/ld2450/ld2450.cpp | 6 ++-- esphome/components/mqtt/mqtt_select.cpp | 3 +- .../prometheus/prometheus_handler.cpp | 3 +- esphome/components/select/select.cpp | 4 ++- esphome/components/select/select.h | 11 ++++--- esphome/components/web_server/web_server.cpp | 11 ++++--- esphome/components/web_server/web_server.h | 2 +- tests/components/template/common-base.yaml | 32 +++++++++++++++++++ 12 files changed, 68 insertions(+), 23 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 4bc19a8bad..a4df75630c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -914,7 +914,7 @@ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection bool is_single) { auto *select = static_cast(entity); SelectStateResponse resp; - resp.state = StringRef(select->current_option()); + resp.state = select->current_option(); resp.missing_state = !select->has_state(); return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); } diff --git a/esphome/components/display_menu_base/menu_item.cpp b/esphome/components/display_menu_base/menu_item.cpp index 08f758045e..ad8b03de60 100644 --- a/esphome/components/display_menu_base/menu_item.cpp +++ b/esphome/components/display_menu_base/menu_item.cpp @@ -42,7 +42,8 @@ std::string MenuItemSelect::get_value_text() const { result = this->value_getter_.value()(this); } else { if (this->select_var_ != nullptr) { - result = this->select_var_->current_option(); + auto option = this->select_var_->current_option(); + result.assign(option.c_str(), option.size()); } } diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index c9b4333f7e..5294f7cd36 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -442,7 +442,8 @@ bool LD2410Component::handle_ack_data_() { ESP_LOGV(TAG, "Baud rate change"); #ifdef USE_SELECT if (this->baud_rate_select_ != nullptr) { - ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option()); + auto baud = this->baud_rate_select_->current_option(); + ESP_LOGE(TAG, "Change baud rate to %.*s and reinstall", (int) baud.size(), baud.c_str()); } #endif break; @@ -766,10 +767,10 @@ void LD2410Component::set_light_out_control() { #endif #ifdef USE_SELECT if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) { - this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option()); + this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option().c_str()); } if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->has_state()) { - this->out_pin_level_ = find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option()); + this->out_pin_level_ = find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option().c_str()); } #endif this->set_config_mode_(true); diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 620ac9886b..c2f441e472 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -486,7 +486,8 @@ bool LD2412Component::handle_ack_data_() { ESP_LOGV(TAG, "Baud rate change"); #ifdef USE_SELECT if (this->baud_rate_select_ != nullptr) { - ESP_LOGW(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option()); + auto baud = this->baud_rate_select_->current_option(); + ESP_LOGW(TAG, "Change baud rate to %.*s and reinstall", (int) baud.size(), baud.c_str()); } #endif break; @@ -790,7 +791,7 @@ void LD2412Component::set_basic_config() { 1, TOTAL_GATES, DEFAULT_PRESENCE_TIMEOUT, 0, #endif #ifdef USE_SELECT - find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option()), + find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option().c_str()), #else 0x01, // Default value if not using select #endif @@ -844,7 +845,7 @@ void LD2412Component::set_light_out_control() { #endif #ifdef USE_SELECT if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) { - this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option()); + this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option().c_str()); } #endif uint8_t value[2] = {this->light_function_, this->light_threshold_}; diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 3b85694bc0..58d469b2a7 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -637,7 +637,8 @@ bool LD2450Component::handle_ack_data_() { ESP_LOGV(TAG, "Baud rate change"); #ifdef USE_SELECT if (this->baud_rate_select_ != nullptr) { - ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option()); + auto baud = this->baud_rate_select_->current_option(); + ESP_LOGE(TAG, "Change baud rate to %.*s and reinstall", (int) baud.size(), baud.c_str()); } #endif break; @@ -718,7 +719,8 @@ bool LD2450Component::handle_ack_data_() { this->publish_zone_type(); #ifdef USE_SELECT if (this->zone_type_select_ != nullptr) { - ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->current_option()); + auto zone = this->zone_type_select_->current_option(); + ESP_LOGV(TAG, "Change zone type to: %.*s", (int) zone.size(), zone.c_str()); } #endif if (this->buffer_data_[10] == 0x00) { diff --git a/esphome/components/mqtt/mqtt_select.cpp b/esphome/components/mqtt/mqtt_select.cpp index 09d90ed46e..03ab82312b 100644 --- a/esphome/components/mqtt/mqtt_select.cpp +++ b/esphome/components/mqtt/mqtt_select.cpp @@ -43,7 +43,8 @@ void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon } bool MQTTSelectComponent::send_initial_state() { if (this->select_->has_state()) { - return this->publish_state(this->select_->current_option()); + auto option = this->select_->current_option(); + return this->publish_state(std::string(option.c_str(), option.size())); } else { return true; } diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 88b357041a..75910fa73d 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -709,7 +709,8 @@ void PrometheusHandler::select_row_(AsyncResponseStream *stream, select::Select stream->print(ESPHOME_F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(ESPHOME_F("\",value=\"")); - stream->print(obj->current_option()); + // c_str() is safe as option values are null-terminated strings from codegen + stream->print(obj->current_option().c_str()); stream->print(ESPHOME_F("\"} ")); stream->print(ESPHOME_F("1.0")); stream->print(ESPHOME_F("\n")); diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index 28d7eb07d4..3d70e94d47 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -38,7 +38,9 @@ void Select::publish_state(size_t index) { #endif } -const char *Select::current_option() const { return this->has_state() ? this->option_at(this->active_index_) : ""; } +StringRef Select::current_option() const { + return this->has_state() ? StringRef(this->option_at(this->active_index_)) : StringRef(); +} void Select::add_on_state_callback(std::function &&callback) { this->state_callback_.add(std::move(callback)); diff --git a/esphome/components/select/select.h b/esphome/components/select/select.h index 330d18ce6f..8b05487704 100644 --- a/esphome/components/select/select.h +++ b/esphome/components/select/select.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" +#include "esphome/core/string_ref.h" #include "select_call.h" #include "select_traits.h" @@ -33,8 +34,8 @@ class Select : public EntityBase { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - /// @deprecated Use current_option() instead. This member will be removed in ESPHome 2026.5.0. - ESPDEPRECATED("Use current_option() instead of .state. Will be removed in 2026.5.0", "2025.11.0") + /// @deprecated Use current_option() instead. This member will be removed in ESPHome 2026.7.0. + ESPDEPRECATED("Use current_option() instead of .state. Will be removed in 2026.7.0", "2026.1.0") std::string state{}; Select() = default; @@ -45,8 +46,10 @@ class Select : public EntityBase { void publish_state(const char *state); void publish_state(size_t index); - /// Return the currently selected option (as const char* from flash). - const char *current_option() const; + /// Return the currently selected option, or empty StringRef if no state. + /// The returned StringRef points to string literals from codegen (static storage). + /// Traits are set once at startup and valid for the lifetime of the program. + StringRef current_option() const; /// Instantiate a SelectCall object to modify this select component's state. SelectCall make_call() { return SelectCall(this); } diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 12115083f6..41d225c0d8 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1393,7 +1393,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->select_json_(obj, obj->has_state() ? obj->current_option() : "", detail); + std::string data = this->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -1414,17 +1414,18 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM } std::string WebServer::select_state_json_generator(WebServer *web_server, void *source) { auto *obj = (select::Select *) (source); - return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : "", DETAIL_STATE); + return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_STATE); } std::string WebServer::select_all_json_generator(WebServer *web_server, void *source) { auto *obj = (select::Select *) (source); - return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : "", DETAIL_ALL); + return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_ALL); } -std::string WebServer::select_json_(select::Select *obj, const char *value, JsonDetail start_config) { +std::string WebServer::select_json_(select::Select *obj, StringRef value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); - set_json_icon_state_value(root, obj, "select", value, value, start_config); + // value points to null-terminated string literals from codegen (via current_option()) + set_json_icon_state_value(root, obj, "select", value.c_str(), value.c_str(), start_config); if (start_config == DETAIL_ALL) { JsonArray opt = root[ESPHOME_F("option")].to(); for (auto &option : obj->traits.get_options()) { diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index c52cf981e0..b62686f0aa 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -627,7 +627,7 @@ class WebServer : public Controller, std::string text_json_(text::Text *obj, const std::string &value, JsonDetail start_config); #endif #ifdef USE_SELECT - std::string select_json_(select::Select *obj, const char *value, JsonDetail start_config); + std::string select_json_(select::Select *obj, StringRef value, JsonDetail start_config); #endif #ifdef USE_CLIMATE std::string climate_json_(climate::Climate *obj, JsonDetail start_config); diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index e050c0b307..134ad4d046 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -243,6 +243,7 @@ number: select: - platform: template + id: template_select name: "Template select" optimistic: true options: @@ -250,6 +251,37 @@ select: - two - three initial_option: two + # Test current_option() returning std::string_view - migration guide examples + on_value: + - lambda: |- + // Migration guide: Check if select has a state + // OLD: if (id(template_select).current_option() != nullptr) + // NEW: Check with .empty() + if (!id(template_select).current_option().empty()) { + ESP_LOGI("test", "Select has state"); + } + + // Migration guide: Compare option values + // OLD: if (strcmp(id(template_select).current_option(), "one") == 0) + // NEW: Direct comparison works safely even when empty + if (id(template_select).current_option() == "one") { + ESP_LOGI("test", "Option is 'one'"); + } + if (id(template_select).current_option() != "two") { + ESP_LOGI("test", "Option is not 'two'"); + } + + // Migration guide: Logging options + // Option 1: Using .c_str() - StringRef guarantees null-termination + ESP_LOGI("test", "Current option: %s", id(template_select).current_option().c_str()); + + // Option 2: Using %.*s format with size + auto option = id(template_select).current_option(); + ESP_LOGI("test", "Current option (safe): %.*s", (int) option.size(), option.c_str()); + + // Migration guide: Store in std::string + std::string stored_option(id(template_select).current_option()); + ESP_LOGI("test", "Stored: %s", stored_option.c_str()); lock: - platform: template From f1b11b185548d21fec2be3ee2e45b4346e7e5929 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:52:39 -1000 Subject: [PATCH 0050/2030] [light] Return StringRef from LightEffect::get_name() and LightState::get_effect_name() (#13105) --- esphome/components/api/api_connection.cpp | 5 +- esphome/components/e131/e131.cpp | 10 ++-- .../e131/e131_addressable_light_effect.cpp | 5 +- esphome/components/light/light_call.cpp | 13 ++-- esphome/components/light/light_effect.h | 5 +- .../components/light/light_json_schema.cpp | 2 +- esphome/components/light/light_state.cpp | 10 +--- esphome/components/light/light_state.h | 10 ++-- esphome/components/mqtt/mqtt_light.cpp | 6 +- .../prometheus/prometheus_handler.cpp | 3 +- esphome/core/helpers.cpp | 3 + esphome/core/helpers.h | 2 + tests/components/light/common.yaml | 59 +++++++++++++++++++ 13 files changed, 97 insertions(+), 36 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index a4df75630c..f0fc5ba71c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -499,7 +499,7 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection * resp.cold_white = values.get_cold_white(); resp.warm_white = values.get_warm_white(); if (light->supports_effects()) { - resp.effect = light->get_effect_name_ref(); + resp.effect = light->get_effect_name(); } return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); } @@ -522,7 +522,8 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c effects_list.init(light_effects.size() + 1); effects_list.push_back("None"); for (auto *effect : light_effects) { - effects_list.push_back(effect->get_name()); + // c_str() is safe as effect names are null-terminated strings from codegen + effects_list.push_back(effect->get_name().c_str()); } } msg.effects = &effects_list; diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index c10c88faf2..f11e7f4fe3 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -82,8 +82,9 @@ void E131Component::add_effect(E131AddressableLightEffect *light_effect) { return; } - ESP_LOGD(TAG, "Registering '%s' for universes %d-%d.", light_effect->get_name(), light_effect->get_first_universe(), - light_effect->get_last_universe()); + auto effect_name = light_effect->get_name(); + ESP_LOGD(TAG, "Registering '%.*s' for universes %d-%d.", (int) effect_name.size(), effect_name.c_str(), + light_effect->get_first_universe(), light_effect->get_last_universe()); light_effects_.push_back(light_effect); @@ -98,8 +99,9 @@ void E131Component::remove_effect(E131AddressableLightEffect *light_effect) { return; } - ESP_LOGD(TAG, "Unregistering '%s' for universes %d-%d.", light_effect->get_name(), light_effect->get_first_universe(), - light_effect->get_last_universe()); + auto effect_name = light_effect->get_name(); + ESP_LOGD(TAG, "Unregistering '%.*s' for universes %d-%d.", (int) effect_name.size(), effect_name.c_str(), + light_effect->get_first_universe(), light_effect->get_last_universe()); // Swap with last element and pop for O(1) removal (order doesn't matter) *it = light_effects_.back(); diff --git a/esphome/components/e131/e131_addressable_light_effect.cpp b/esphome/components/e131/e131_addressable_light_effect.cpp index 780e181f04..7d62f739a2 100644 --- a/esphome/components/e131/e131_addressable_light_effect.cpp +++ b/esphome/components/e131/e131_addressable_light_effect.cpp @@ -58,8 +58,9 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + packet.count - 1)); auto *input_data = packet.values + 1; - ESP_LOGV(TAG, "Applying data for '%s' on %d universe, for %" PRId32 "-%d.", get_name(), universe, output_offset, - output_end); + auto effect_name = get_name(); + ESP_LOGV(TAG, "Applying data for '%.*s' on %d universe, for %" PRId32 "-%d.", (int) effect_name.size(), + effect_name.c_str(), universe, output_offset, output_end); switch (channels_) { case E131_MONO: diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 8161e8b814..234d641f0d 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -1,4 +1,5 @@ #include + #include "light_call.h" #include "light_state.h" #include "esphome/core/log.h" @@ -153,15 +154,15 @@ void LightCall::perform() { } else if (this->has_effect_()) { // EFFECT - const char *effect_s; + StringRef effect_s; if (this->effect_ == 0u) { - effect_s = "None"; + effect_s = StringRef::from_lit("None"); } else { effect_s = this->parent_->effects_[this->effect_ - 1]->get_name(); } if (publish) { - ESP_LOGD(TAG, " Effect: '%s'", effect_s); + ESP_LOGD(TAG, " Effect: '%.*s'", (int) effect_s.size(), effect_s.c_str()); } this->parent_->start_effect_(this->effect_); @@ -511,11 +512,9 @@ LightCall &LightCall::set_effect(const char *effect, size_t len) { } bool found = false; + StringRef effect_ref(effect, len); for (uint32_t i = 0; i < this->parent_->effects_.size(); i++) { - LightEffect *e = this->parent_->effects_[i]; - const char *name = e->get_name(); - - if (strncasecmp(effect, name, len) == 0 && name[len] == '\0') { + if (str_equals_case_insensitive(effect_ref, this->parent_->effects_[i]->get_name())) { this->set_effect(i + 1); found = true; break; diff --git a/esphome/components/light/light_effect.h b/esphome/components/light/light_effect.h index aa1f6f7899..a89e3fec5a 100644 --- a/esphome/components/light/light_effect.h +++ b/esphome/components/light/light_effect.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/string_ref.h" namespace esphome::light { @@ -23,9 +24,9 @@ class LightEffect { /** * Returns the name of this effect. - * The returned pointer is valid for the lifetime of the program and must not be freed. + * The underlying data is valid for the lifetime of the program (static string from codegen). */ - const char *get_name() const { return this->name_; } + StringRef get_name() const { return StringRef(this->name_); } /// Internal method called by the LightState when this light effect is registered in it. virtual void init() {} diff --git a/esphome/components/light/light_json_schema.cpp b/esphome/components/light/light_json_schema.cpp index 98b03f9458..f370980737 100644 --- a/esphome/components/light/light_json_schema.cpp +++ b/esphome/components/light/light_json_schema.cpp @@ -36,7 +36,7 @@ static const char *get_color_mode_json_str(ColorMode mode) { void LightJSONSchema::dump_json(LightState &state, JsonObject root) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson if (state.supports_effects()) { - root[ESPHOME_F("effect")] = state.get_effect_name_ref(); + root[ESPHOME_F("effect")] = state.get_effect_name().c_str(); root[ESPHOME_F("effect_index")] = state.get_current_effect_index(); root[ESPHOME_F("effect_count")] = state.get_effect_count(); } diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index 5a50bae50b..91bb2e2f1f 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -162,20 +162,12 @@ void LightState::publish_state() { LightOutput *LightState::get_output() const { return this->output_; } -static constexpr const char *EFFECT_NONE = "None"; static constexpr auto EFFECT_NONE_REF = StringRef::from_lit("None"); -std::string LightState::get_effect_name() { +StringRef LightState::get_effect_name() { if (this->active_effect_index_ > 0) { return this->effects_[this->active_effect_index_ - 1]->get_name(); } - return EFFECT_NONE; -} - -StringRef LightState::get_effect_name_ref() { - if (this->active_effect_index_ > 0) { - return StringRef(this->effects_[this->active_effect_index_ - 1]->get_name()); - } return EFFECT_NONE_REF; } diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index a21c2c7693..83b9226d03 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -140,9 +140,7 @@ class LightState : public EntityBase, public Component { LightOutput *get_output() const; /// Return the name of the current effect, or if no effect is active "None". - std::string get_effect_name(); - /// Return the name of the current effect as StringRef (for API usage) - StringRef get_effect_name_ref(); + StringRef get_effect_name(); /** Add a listener for remote values changes. * Listener is notified when the light's remote values change (state, brightness, color, etc.) @@ -191,11 +189,11 @@ class LightState : public EntityBase, public Component { /// Get effect index by name. Returns 0 if effect not found. uint32_t get_effect_index(const std::string &effect_name) const { - if (strcasecmp(effect_name.c_str(), "none") == 0) { + if (str_equals_case_insensitive(effect_name, "none")) { return 0; } for (size_t i = 0; i < this->effects_.size(); i++) { - if (strcasecmp(effect_name.c_str(), this->effects_[i]->get_name()) == 0) { + if (str_equals_case_insensitive(effect_name, this->effects_[i]->get_name())) { return i + 1; // Effects are 1-indexed in active_effect_index_ } } @@ -218,7 +216,7 @@ class LightState : public EntityBase, public Component { if (index > this->effects_.size()) { return ""; // Invalid index } - return this->effects_[index - 1]->get_name(); + return std::string(this->effects_[index - 1]->get_name()); } /// The result of all the current_values_as_* methods have gamma correction applied. diff --git a/esphome/components/mqtt/mqtt_light.cpp b/esphome/components/mqtt/mqtt_light.cpp index 2d588ed10b..fac19f3210 100644 --- a/esphome/components/mqtt/mqtt_light.cpp +++ b/esphome/components/mqtt/mqtt_light.cpp @@ -80,8 +80,10 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery if (this->state_->supports_effects()) { root[ESPHOME_F("effect")] = true; JsonArray effect_list = root[MQTT_EFFECT_LIST].to(); - for (auto *effect : this->state_->get_effects()) - effect_list.add(effect->get_name()); + for (auto *effect : this->state_->get_effects()) { + // c_str() is safe as effect names are null-terminated strings from codegen + effect_list.add(effect->get_name().c_str()); + } effect_list.add(ESPHOME_F("None")); } } diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 75910fa73d..f4c6f6804b 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -363,13 +363,14 @@ void PrometheusHandler::light_row_(AsyncResponseStream *stream, light::LightStat // Skip effect metrics if light has no effects if (!obj->get_effects().empty()) { // Effect - std::string effect = obj->get_effect_name(); + StringRef effect = obj->get_effect_name(); print_metric_labels_(stream, ESPHOME_F("esphome_light_effect_active"), obj, area, node, friendly_name); stream->print(ESPHOME_F("\",effect=\"")); // Only vary based on effect if (effect == "None") { stream->print(ESPHOME_F("None\"} 0\n")); } else { + // c_str() is safe as effect names are null-terminated strings from codegen stream->print(effect.c_str()); stream->print(ESPHOME_F("\"} 1\n")); } diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 8671dc7f82..309407fbec 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -162,6 +162,9 @@ float random_float() { return static_cast(random_uint32()) / static_cast< bool str_equals_case_insensitive(const std::string &a, const std::string &b) { return strcasecmp(a.c_str(), b.c_str()) == 0; } +bool str_equals_case_insensitive(StringRef a, StringRef b) { + return a.size() == b.size() && strncasecmp(a.c_str(), b.c_str(), a.size()) == 0; +} #if __cplusplus >= 202002L bool str_startswith(const std::string &str, const std::string &start) { return str.starts_with(start); } bool str_endswith(const std::string &str, const std::string &end) { return str.ends_with(end); } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index cd43709f7d..bf559d2bc6 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -511,6 +511,8 @@ template constexpr T convert_little_endian(T val) { /// Compare strings for equality in case-insensitive manner. bool str_equals_case_insensitive(const std::string &a, const std::string &b); +/// Compare StringRefs for equality in case-insensitive manner. +bool str_equals_case_insensitive(StringRef a, StringRef b); /// Check whether a string starts with a value. bool str_startswith(const std::string &str, const std::string &start); diff --git a/tests/components/light/common.yaml b/tests/components/light/common.yaml index 247fc19aba..55525fc67f 100644 --- a/tests/components/light/common.yaml +++ b/tests/components/light/common.yaml @@ -1,6 +1,65 @@ esphome: on_boot: then: + # Test LightEffect::get_name() returns StringRef + - lambda: |- + // Test LightEffect::get_name() returns StringRef + auto &effects = id(test_monochromatic_light).get_effects(); + if (!effects.empty()) { + // Test: get_name() returns StringRef + StringRef name = effects[0]->get_name(); + + // Test: comparison with string literal works directly + if (name == "Strobe") { + ESP_LOGI("test", "Found Strobe effect"); + } + + // Test: safe logging with %.*s format + ESP_LOGI("test", "Effect name: %.*s", (int) name.size(), name.c_str()); + + // Test: .c_str() for functions expecting const char* + ESP_LOGI("test", "Effect: %s", name.c_str()); + + // Test: explicit conversion to std::string + std::string name_str(name.c_str(), name.size()); + ESP_LOGI("test", "As string: %s", name_str.c_str()); + + // Test: size() method + ESP_LOGI("test", "Name length: %d", (int) name.size()); + } + + # Test LightState::get_effect_name() returns StringRef + - lambda: |- + // Test LightState::get_effect_name() returns StringRef + StringRef current_effect = id(test_monochromatic_light).get_effect_name(); + + // Test: comparison with "None" works directly + if (current_effect == "None") { + ESP_LOGI("test", "No effect active"); + } + + // Test: safe logging + ESP_LOGI("test", "Current effect: %.*s", (int) current_effect.size(), current_effect.c_str()); + + # Test str_equals_case_insensitive with StringRef + - lambda: |- + // Test str_equals_case_insensitive(StringRef, StringRef) + auto &effects = id(test_monochromatic_light).get_effects(); + if (!effects.empty()) { + StringRef name = effects[0]->get_name(); + + // Test: case-insensitive comparison + if (str_equals_case_insensitive(name, "STROBE")) { + ESP_LOGI("test", "Case-insensitive match works"); + } + + // Test: case-insensitive with StringRef from string + std::string search = "strobe"; + if (str_equals_case_insensitive(StringRef(search.c_str(), search.size()), name)) { + ESP_LOGI("test", "Reverse comparison works"); + } + } + - light.toggle: test_binary_light - light.turn_off: test_rgb_light - light.turn_on: From e1aac7601d95adeddb19f1877cf97408de2e1381 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:52:54 -1000 Subject: [PATCH 0051/2030] [event] Return StringRef from get_last_event_type() (#13104) --- esphome/components/api/api_connection.cpp | 11 ++++++----- esphome/components/api/api_connection.h | 4 ++-- esphome/components/event/event.h | 8 ++++++-- esphome/components/prometheus/prometheus_handler.cpp | 5 +++-- esphome/components/web_server/web_server.cpp | 9 +++------ esphome/components/web_server/web_server.h | 2 +- tests/components/event/common.yaml | 11 +++++++++++ 7 files changed, 32 insertions(+), 18 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index f0fc5ba71c..656dbedb8a 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1415,14 +1415,15 @@ void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequ #endif #ifdef USE_EVENT -void APIConnection::send_event(event::Event *event, const char *event_type) { - this->send_message_smart_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE, +void APIConnection::send_event(event::Event *event, StringRef event_type) { + // get_last_event_type() returns StringRef pointing to null-terminated string literals from codegen + this->send_message_smart_(event, MessageCreator(event_type.c_str()), EventResponse::MESSAGE_TYPE, EventResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_event_response(event::Event *event, const char *event_type, APIConnection *conn, +uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint32_t remaining_size, bool is_single) { EventResponse resp; - resp.event_type = StringRef(event_type); + resp.event_type = event_type; return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single); } @@ -2056,7 +2057,7 @@ uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnec // Special case: EventResponse uses const char * pointer if (message_type == EventResponse::MESSAGE_TYPE) { auto *e = static_cast(entity); - return APIConnection::try_send_event_response(e, data_.const_char_ptr, conn, remaining_size, is_single); + return APIConnection::try_send_event_response(e, StringRef(data_.const_char_ptr), conn, remaining_size, is_single); } #endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 15d79a25ec..0289b3d2ff 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -173,7 +173,7 @@ class APIConnection final : public APIServerConnection { #endif #ifdef USE_EVENT - void send_event(event::Event *event, const char *event_type); + void send_event(event::Event *event, StringRef event_type); #endif #ifdef USE_UPDATE @@ -469,7 +469,7 @@ class APIConnection final : public APIServerConnection { bool is_single); #endif #ifdef USE_EVENT - static uint16_t try_send_event_response(event::Event *event, const char *event_type, APIConnection *conn, + static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint32_t remaining_size, bool is_single); static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); #endif diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index 0d5850d339..27700e32d8 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -7,6 +7,7 @@ #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" +#include "esphome/core/string_ref.h" namespace esphome { namespace event { @@ -44,8 +45,11 @@ class Event : public EntityBase, public EntityBase_DeviceClass { /// Return the event types supported by this event. const FixedVector &get_event_types() const { return this->types_; } - /// Return the last triggered event type (pointer to string in types_), or nullptr if no event triggered yet. - const char *get_last_event_type() const { return this->last_event_type_; } + /// Return the last triggered event type, or empty StringRef if no event triggered yet. + StringRef get_last_event_type() const { return StringRef::from_maybe_nullptr(this->last_event_type_); } + + /// Check if an event has been triggered. + bool has_event() const { return this->last_event_type_ != nullptr; } void add_on_event_callback(std::function &&callback); diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index f4c6f6804b..dd577a4dbc 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -600,7 +600,7 @@ void PrometheusHandler::event_row_(AsyncResponseStream *stream, event::Event *ob std::string &friendly_name) { if (obj->is_internal() && !this->include_internal_) return; - if (obj->get_last_event_type() != nullptr) { + if (obj->has_event()) { // We have a valid event type, output this value stream->print(ESPHOME_F("esphome_event_failed{id=\"")); stream->print(relabel_id_(obj).c_str()); @@ -619,7 +619,8 @@ void PrometheusHandler::event_row_(AsyncResponseStream *stream, event::Event *ob stream->print(ESPHOME_F("\",name=\"")); stream->print(relabel_name_(obj).c_str()); stream->print(ESPHOME_F("\",last_event_type=\"")); - stream->print(obj->get_last_event_type()); + // get_last_event_type() returns StringRef (null-terminated) + stream->print(obj->get_last_event_type().c_str()); stream->print(ESPHOME_F("\"} ")); stream->print(ESPHOME_F("1.0")); stream->print(ESPHOME_F("\n")); diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 41d225c0d8..76a516d90f 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1958,7 +1958,7 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa // Note: request->method() is always HTTP_GET here (canHandle ensures this) if (entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->event_json_(obj, "", detail); + std::string data = this->event_json_(obj, StringRef(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -1966,10 +1966,7 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa request->send(404); } -static std::string get_event_type(event::Event *event) { - const char *last_type = event ? event->get_last_event_type() : nullptr; - return last_type ? last_type : ""; -} +static StringRef get_event_type(event::Event *event) { return event ? event->get_last_event_type() : StringRef(); } std::string WebServer::event_state_json_generator(WebServer *web_server, void *source) { auto *event = static_cast(source); @@ -1980,7 +1977,7 @@ std::string WebServer::event_all_json_generator(WebServer *web_server, void *sou auto *event = static_cast(source); return web_server->event_json_(event, get_event_type(event), DETAIL_ALL); } -std::string WebServer::event_json_(event::Event *obj, const std::string &event_type, JsonDetail start_config) { +std::string WebServer::event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index b62686f0aa..55fa89679e 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -643,7 +643,7 @@ class WebServer : public Controller, alarm_control_panel::AlarmControlPanelState value, JsonDetail start_config); #endif #ifdef USE_EVENT - std::string event_json_(event::Event *obj, const std::string &event_type, JsonDetail start_config); + std::string event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config); #endif #ifdef USE_WATER_HEATER std::string water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config); diff --git a/tests/components/event/common.yaml b/tests/components/event/common.yaml index 71cc19a6b0..555d049c70 100644 --- a/tests/components/event/common.yaml +++ b/tests/components/event/common.yaml @@ -7,3 +7,14 @@ event: - template_event_type2 on_event: - logger.log: Event fired + - lambda: |- + // Test get_last_event_type() returns StringRef + if (id(some_event).has_event()) { + auto event_type = id(some_event).get_last_event_type(); + // Compare with string literal using == + if (event_type == "template_event_type1") { + ESP_LOGD("test", "Event type is template_event_type1"); + } + // Log using %.*s format for StringRef + ESP_LOGD("test", "Event type: %.*s", (int) event_type.size(), event_type.c_str()); + } From ea8ae2ae6066cc1e8ad3abaf749f74d579d09296 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:53:06 -1000 Subject: [PATCH 0052/2030] [climate] Return StringRef from get_custom_fan_mode() and get_custom_preset() (#13103) --- esphome/components/api/api_connection.cpp | 4 ++-- .../bedjet/climate/bedjet_climate.cpp | 21 ++++++++++--------- esphome/components/climate/climate.cpp | 10 ++++----- esphome/components/climate/climate.h | 21 ++++++++++++------- esphome/components/midea/air_conditioner.cpp | 6 ++++-- esphome/components/mqtt/mqtt_climate.cpp | 4 ++-- .../thermostat/thermostat_climate.cpp | 7 ++++--- .../thermostat/thermostat_climate.h | 8 ++++++- tests/components/midea/common.yaml | 19 +++++++++++++++++ tests/components/thermostat/common.yaml | 14 +++++++++++++ 10 files changed, 81 insertions(+), 33 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 656dbedb8a..d6f0d84550 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -676,13 +676,13 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection if (traits.get_supports_fan_modes() && climate->fan_mode.has_value()) resp.fan_mode = static_cast(climate->fan_mode.value()); if (!traits.get_supported_custom_fan_modes().empty() && climate->has_custom_fan_mode()) { - resp.custom_fan_mode = StringRef(climate->get_custom_fan_mode()); + resp.custom_fan_mode = climate->get_custom_fan_mode(); } if (traits.get_supports_presets() && climate->preset.has_value()) { resp.preset = static_cast(climate->preset.value()); } if (!traits.get_supported_custom_presets().empty() && climate->has_custom_preset()) { - resp.custom_preset = StringRef(climate->get_custom_preset()); + resp.custom_preset = climate->get_custom_preset(); } if (traits.get_supports_swing_modes()) resp.swing_mode = static_cast(climate->swing_mode); diff --git a/esphome/components/bedjet/climate/bedjet_climate.cpp b/esphome/components/bedjet/climate/bedjet_climate.cpp index 716d4d4241..68a0342873 100644 --- a/esphome/components/bedjet/climate/bedjet_climate.cpp +++ b/esphome/components/bedjet/climate/bedjet_climate.cpp @@ -164,21 +164,21 @@ void BedJetClimate::control(const ClimateCall &call) { return; } } else if (call.has_custom_preset()) { - const char *preset = call.get_custom_preset(); + auto preset = call.get_custom_preset(); bool result; - if (strcmp(preset, "M1") == 0) { + if (preset == "M1") { result = this->parent_->button_memory1(); - } else if (strcmp(preset, "M2") == 0) { + } else if (preset == "M2") { result = this->parent_->button_memory2(); - } else if (strcmp(preset, "M3") == 0) { + } else if (preset == "M3") { result = this->parent_->button_memory3(); - } else if (strcmp(preset, "LTD HT") == 0) { + } else if (preset == "LTD HT") { result = this->parent_->button_heat(); - } else if (strcmp(preset, "EXT HT") == 0) { + } else if (preset == "EXT HT") { result = this->parent_->button_ext_heat(); } else { - ESP_LOGW(TAG, "Unsupported preset: %s", preset); + ESP_LOGW(TAG, "Unsupported preset: %.*s", (int) preset.size(), preset.c_str()); return; } @@ -208,10 +208,11 @@ void BedJetClimate::control(const ClimateCall &call) { this->set_fan_mode_(fan_mode); } } else if (call.has_custom_fan_mode()) { - const char *fan_mode = call.get_custom_fan_mode(); - auto fan_index = bedjet_fan_speed_to_step(fan_mode); + auto fan_mode = call.get_custom_fan_mode(); + auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str()); if (fan_index <= 19) { - ESP_LOGV(TAG, "[%s] Converted fan mode %s to bedjet fan step %d", this->get_name().c_str(), fan_mode, fan_index); + ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(), + (int) fan_mode.size(), fan_mode.c_str(), fan_index); bool result = this->parent_->set_fan_index(fan_index); if (result) { this->set_custom_fan_mode_(fan_mode); diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 2d35509493..7611d33cbf 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -682,19 +682,19 @@ bool Climate::set_fan_mode_(ClimateFanMode mode) { return set_primary_mode(this->fan_mode, this->custom_fan_mode_, mode); } -bool Climate::set_custom_fan_mode_(const char *mode) { +bool Climate::set_custom_fan_mode_(const char *mode, size_t len) { auto traits = this->get_traits(); - return set_custom_mode(this->custom_fan_mode_, this->fan_mode, traits.find_custom_fan_mode_(mode), - this->has_custom_fan_mode()); + return set_custom_mode(this->custom_fan_mode_, this->fan_mode, + traits.find_custom_fan_mode_(mode, len), this->has_custom_fan_mode()); } void Climate::clear_custom_fan_mode_() { this->custom_fan_mode_ = nullptr; } bool Climate::set_preset_(ClimatePreset preset) { return set_primary_mode(this->preset, this->custom_preset_, preset); } -bool Climate::set_custom_preset_(const char *preset) { +bool Climate::set_custom_preset_(const char *preset, size_t len) { auto traits = this->get_traits(); - return set_custom_mode(this->custom_preset_, this->preset, traits.find_custom_preset_(preset), + return set_custom_mode(this->custom_preset_, this->preset, traits.find_custom_preset_(preset, len), this->has_custom_preset()); } diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index 06adb580cf..6fac254502 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -5,6 +5,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/preferences.h" +#include "esphome/core/string_ref.h" #include "climate_mode.h" #include "climate_traits.h" @@ -110,8 +111,8 @@ class ClimateCall { const optional &get_fan_mode() const; const optional &get_swing_mode() const; const optional &get_preset() const; - const char *get_custom_fan_mode() const { return this->custom_fan_mode_; } - const char *get_custom_preset() const { return this->custom_preset_; } + StringRef get_custom_fan_mode() const { return StringRef::from_maybe_nullptr(this->custom_fan_mode_); } + StringRef get_custom_preset() const { return StringRef::from_maybe_nullptr(this->custom_preset_); } bool has_custom_fan_mode() const { return this->custom_fan_mode_ != nullptr; } bool has_custom_preset() const { return this->custom_preset_ != nullptr; } @@ -266,11 +267,11 @@ class Climate : public EntityBase { /// The active swing mode of the climate device. ClimateSwingMode swing_mode{CLIMATE_SWING_OFF}; - /// Get the active custom fan mode (read-only access). - const char *get_custom_fan_mode() const { return this->custom_fan_mode_; } + /// Get the active custom fan mode (read-only access). Returns StringRef. + StringRef get_custom_fan_mode() const { return StringRef::from_maybe_nullptr(this->custom_fan_mode_); } - /// Get the active custom preset (read-only access). - const char *get_custom_preset() const { return this->custom_preset_; } + /// Get the active custom preset (read-only access). Returns StringRef. + StringRef get_custom_preset() const { return StringRef::from_maybe_nullptr(this->custom_preset_); } protected: friend ClimateCall; @@ -280,7 +281,9 @@ class Climate : public EntityBase { bool set_fan_mode_(ClimateFanMode mode); /// Set custom fan mode. Reset primary fan mode. Return true if fan mode has been changed. - bool set_custom_fan_mode_(const char *mode); + bool set_custom_fan_mode_(const char *mode) { return this->set_custom_fan_mode_(mode, strlen(mode)); } + bool set_custom_fan_mode_(const char *mode, size_t len); + bool set_custom_fan_mode_(StringRef mode) { return this->set_custom_fan_mode_(mode.c_str(), mode.size()); } /// Clear custom fan mode. void clear_custom_fan_mode_(); @@ -288,7 +291,9 @@ class Climate : public EntityBase { bool set_preset_(ClimatePreset preset); /// Set custom preset. Reset primary preset. Return true if preset has been changed. - bool set_custom_preset_(const char *preset); + bool set_custom_preset_(const char *preset) { return this->set_custom_preset_(preset, strlen(preset)); } + bool set_custom_preset_(const char *preset, size_t len); + bool set_custom_preset_(StringRef preset) { return this->set_custom_preset_(preset.c_str(), preset.size()); } /// Clear custom preset. void clear_custom_preset_(); diff --git a/esphome/components/midea/air_conditioner.cpp b/esphome/components/midea/air_conditioner.cpp index a6a8d52549..bc750e3713 100644 --- a/esphome/components/midea/air_conditioner.cpp +++ b/esphome/components/midea/air_conditioner.cpp @@ -65,12 +65,14 @@ void AirConditioner::control(const ClimateCall &call) { if (call.get_preset().has_value()) { ctrl.preset = Converters::to_midea_preset(call.get_preset().value()); } else if (call.has_custom_preset()) { - ctrl.preset = Converters::to_midea_preset(call.get_custom_preset()); + // get_custom_preset() returns StringRef pointing to null-terminated string literals from codegen + ctrl.preset = Converters::to_midea_preset(call.get_custom_preset().c_str()); } if (call.get_fan_mode().has_value()) { ctrl.fanMode = Converters::to_midea_fan_mode(call.get_fan_mode().value()); } else if (call.has_custom_fan_mode()) { - ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode()); + // get_custom_fan_mode() returns StringRef pointing to null-terminated string literals from codegen + ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode().c_str()); } this->base_.control(ctrl); } diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 77aabb2461..625fb715a7 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -357,7 +357,7 @@ bool MQTTClimateComponent::publish_state_() { } } if (this->device_->has_custom_preset()) - payload = this->device_->get_custom_preset(); + payload = this->device_->get_custom_preset().c_str(); if (!this->publish(this->get_preset_state_topic(), payload)) success = false; } @@ -429,7 +429,7 @@ bool MQTTClimateComponent::publish_state_() { } } if (this->device_->has_custom_fan_mode()) - payload = this->device_->get_custom_fan_mode(); + payload = this->device_->get_custom_fan_mode().c_str(); if (!this->publish(this->get_fan_mode_state_topic(), payload)) success = false; } diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index d5fb259dad..0416438dcd 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -1218,11 +1218,12 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { } } -void ThermostatClimate::change_custom_preset_(const char *custom_preset) { +void ThermostatClimate::change_custom_preset_(const char *custom_preset, size_t len) { // Linear search through custom preset configurations const ThermostatClimateTargetTempConfig *config = nullptr; for (const auto &entry : this->custom_preset_config_) { - if (strcmp(entry.name, custom_preset) == 0) { + // Compare first len chars, then verify entry.name ends there (same length) + if (strncmp(entry.name, custom_preset, len) == 0 && entry.name[len] == '\0') { config = &entry.config; break; } @@ -1231,7 +1232,7 @@ void ThermostatClimate::change_custom_preset_(const char *custom_preset) { if (config != nullptr) { ESP_LOGV(TAG, "Custom preset %s requested", custom_preset); if (this->change_preset_internal_(*config) || !this->has_custom_preset() || - strcmp(this->get_custom_preset(), custom_preset) != 0) { + this->get_custom_preset() != custom_preset) { // Fire any preset changed trigger if defined Trigger<> *trig = this->preset_change_trigger_; // Use the base class method which handles pointer lookup and preset reset internally diff --git a/esphome/components/thermostat/thermostat_climate.h b/esphome/components/thermostat/thermostat_climate.h index 564b6127b3..d37c9a68a6 100644 --- a/esphome/components/thermostat/thermostat_climate.h +++ b/esphome/components/thermostat/thermostat_climate.h @@ -214,7 +214,13 @@ class ThermostatClimate : public climate::Climate, public Component { /// Change to a provided preset setting; will reset temperature, mode, fan, and swing modes accordingly void change_preset_(climate::ClimatePreset preset); /// Change to a provided custom preset setting; will reset temperature, mode, fan, and swing modes accordingly - void change_custom_preset_(const char *custom_preset); + void change_custom_preset_(const char *custom_preset) { + this->change_custom_preset_(custom_preset, strlen(custom_preset)); + } + void change_custom_preset_(const char *custom_preset, size_t len); + void change_custom_preset_(StringRef custom_preset) { + this->change_custom_preset_(custom_preset.c_str(), custom_preset.size()); + } /// Applies the temperature, mode, fan, and swing modes of the provided config. /// This is agnostic of custom vs built in preset diff --git a/tests/components/midea/common.yaml b/tests/components/midea/common.yaml index fec85aee96..c7b18a6701 100644 --- a/tests/components/midea/common.yaml +++ b/tests/components/midea/common.yaml @@ -12,6 +12,25 @@ climate: x.set_mode(CLIMATE_MODE_FAN_ONLY); on_state: - logger.log: State changed! + - lambda: |- + // Test get_custom_fan_mode() returns StringRef + if (id(midea_unit).has_custom_fan_mode()) { + auto fan_mode = id(midea_unit).get_custom_fan_mode(); + // Compare with string literal using == + if (fan_mode == "SILENT") { + ESP_LOGD("test", "Fan mode is SILENT"); + } + // Log using %.*s format for StringRef + ESP_LOGD("test", "Custom fan mode: %.*s", (int) fan_mode.size(), fan_mode.c_str()); + } + // Test get_custom_preset() returns StringRef + if (id(midea_unit).has_custom_preset()) { + auto preset = id(midea_unit).get_custom_preset(); + // Check if empty + if (!preset.empty()) { + ESP_LOGD("test", "Custom preset: %.*s", (int) preset.size(), preset.c_str()); + } + } transmitter_id: xmitr period: 1s num_attempts: 5 diff --git a/tests/components/thermostat/common.yaml b/tests/components/thermostat/common.yaml index 63bd174e14..69e258f2e3 100644 --- a/tests/components/thermostat/common.yaml +++ b/tests/components/thermostat/common.yaml @@ -5,6 +5,7 @@ sensor: climate: - platform: thermostat + id: test_thermostat name: Test Thermostat sensor: thermostat_sensor humidity_sensor: thermostat_sensor @@ -15,6 +16,19 @@ climate: - name: Away default_target_temperature_low: 16°C default_target_temperature_high: 20°C + on_state: + - lambda: |- + // Test get_custom_preset() returns std::string_view + // "Default Preset" is a custom preset (not a standard ClimatePreset name) + if (id(test_thermostat).has_custom_preset()) { + auto preset = id(test_thermostat).get_custom_preset(); + // Compare with string literal using == + if (preset == "Default Preset") { + ESP_LOGD("test", "Preset is Default Preset"); + } + // Log using %.*s format for StringRef + ESP_LOGD("test", "Custom preset: %.*s", (int) preset.size(), preset.c_str()); + } idle_action: - logger.log: idle_action cool_action: From 912f94d1e825a35f98d6dc3731962f6e0f69dcc2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 17:54:06 -1000 Subject: [PATCH 0053/2030] [api] Use StringRef for HomeassistantServiceMap.value to eliminate heap allocations (#13154) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api.proto | 4 +- esphome/components/api/api_options.proto | 1 - esphome/components/api/api_pb2.h | 4 +- esphome/components/api/custom_api_device.h | 4 +- .../components/api/homeassistant_service.h | 43 ++++++++++++++--- .../number/homeassistant_number.cpp | 7 ++- .../switch/homeassistant_switch.cpp | 2 +- esphome/core/automation.h | 6 +++ script/api_protobuf/api_protobuf.py | 48 +++---------------- 9 files changed, 61 insertions(+), 58 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 652b456850..d6384456d5 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -763,7 +763,7 @@ message SubscribeHomeassistantServicesRequest { message HomeassistantServiceMap { string key = 1; - string value = 2 [(no_zero_copy) = true]; + string value = 2; } message HomeassistantActionRequest { @@ -779,7 +779,7 @@ message HomeassistantActionRequest { bool is_event = 5; uint32 call_id = 6 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES"]; bool wants_response = 7 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"]; - string response_template = 8 [(no_zero_copy) = true, (field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"]; + string response_template = 8 [(field_ifdef) = "USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON"]; } // Message sent by Home Assistant to ESPHome with service call response data diff --git a/esphome/components/api/api_options.proto b/esphome/components/api/api_options.proto index 1916e84625..a863f2c7a8 100644 --- a/esphome/components/api/api_options.proto +++ b/esphome/components/api/api_options.proto @@ -27,7 +27,6 @@ extend google.protobuf.MessageOptions { extend google.protobuf.FieldOptions { optional string field_ifdef = 1042; optional uint32 fixed_array_size = 50007; - optional bool no_zero_copy = 50008 [default=false]; optional bool fixed_array_skip_zero = 50009 [default=false]; optional string fixed_array_size_define = 50010; optional string fixed_array_with_length_define = 50011; diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 01fe44d7c7..e21b8596ca 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1053,7 +1053,7 @@ class SubscribeHomeassistantServicesRequest final : public ProtoMessage { class HomeassistantServiceMap final : public ProtoMessage { public: StringRef key{}; - std::string value{}; + StringRef value{}; void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -1081,7 +1081,7 @@ class HomeassistantActionRequest final : public ProtoMessage { bool wants_response{false}; #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - std::string response_template{}; + StringRef response_template{}; #endif void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index b16164270b..2fd9cb0dd2 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -265,7 +265,7 @@ class CustomAPIDevice { for (auto &it : data) { auto &kv = resp.data.emplace_back(); kv.key = StringRef(it.first); - kv.value = it.second; // value is std::string (no_zero_copy), assign directly + kv.value = StringRef(it.second); // data map lives until send completes } global_api_server->send_homeassistant_action(resp); } @@ -308,7 +308,7 @@ class CustomAPIDevice { for (auto &it : data) { auto &kv = resp.data.emplace_back(); kv.key = StringRef(it.first); - kv.value = it.second; // value is std::string (no_zero_copy), assign directly + kv.value = StringRef(it.second); // data map lives until send completes } global_api_server->send_homeassistant_action(resp); } diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index a17c99b8ba..9bffe18764 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -149,11 +149,21 @@ template class HomeAssistantServiceCallAction : public Actionservice_.value(x...); resp.service = StringRef(service_value); resp.is_event = this->flags_.is_event; - this->populate_service_map(resp.data, this->data_, x...); - this->populate_service_map(resp.data_template, this->data_template_, x...); - this->populate_service_map(resp.variables, this->variables_, x...); + + // Local storage for lambda-evaluated strings - lives until after send + FixedVector data_storage; + FixedVector data_template_storage; + FixedVector variables_storage; + + this->populate_service_map(resp.data, this->data_, data_storage, x...); + this->populate_service_map(resp.data_template, this->data_template_, data_template_storage, x...); + this->populate_service_map(resp.variables, this->variables_, variables_storage, x...); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES +#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON + // IMPORTANT: Declare at outer scope so it lives until send_homeassistant_action returns. + std::string response_template_value; +#endif if (this->flags_.wants_status) { // Generate a unique call ID for this service call static uint32_t call_id_counter = 1; @@ -164,8 +174,8 @@ template class HomeAssistantServiceCallAction : public Actionflags_.has_response_template) { - std::string response_template_value = this->response_template_.value(x...); - resp.response_template = response_template_value; + response_template_value = this->response_template_.value(x...); + resp.response_template = StringRef(response_template_value); } } #endif @@ -205,12 +215,31 @@ template class HomeAssistantServiceCallAction : public Action - static void populate_service_map(VectorType &dest, SourceType &source, Ts... x) { + static void populate_service_map(VectorType &dest, SourceType &source, FixedVector &value_storage, + Ts... x) { dest.init(source.size()); + + // Count non-static strings to allocate exact storage needed + size_t lambda_count = 0; + for (const auto &it : source) { + if (!it.value.is_static_string()) { + lambda_count++; + } + } + value_storage.init(lambda_count); + for (auto &it : source) { auto &kv = dest.emplace_back(); kv.key = StringRef(it.key); - kv.value = it.value.value(x...); + + if (it.value.is_static_string()) { + // Static string from YAML - zero allocation + kv.value = StringRef(it.value.get_static_string()); + } else { + // Lambda evaluation - store result, reference it + value_storage.push_back(it.value.value(x...)); + kv.value = StringRef(value_storage.back()); + } } } diff --git a/esphome/components/homeassistant/number/homeassistant_number.cpp b/esphome/components/homeassistant/number/homeassistant_number.cpp index 82387a81e9..92ecd5ea39 100644 --- a/esphome/components/homeassistant/number/homeassistant_number.cpp +++ b/esphome/components/homeassistant/number/homeassistant_number.cpp @@ -91,11 +91,14 @@ void HomeassistantNumber::control(float value) { resp.data.init(2); auto &entity_id = resp.data.emplace_back(); entity_id.key = ENTITY_ID_KEY; - entity_id.value = this->entity_id_; + entity_id.value = StringRef(this->entity_id_); auto &entity_value = resp.data.emplace_back(); entity_value.key = VALUE_KEY; - entity_value.value = to_string(value); + // Stack buffer - no heap allocation; %g produces shortest representation + char value_buf[16]; + snprintf(value_buf, sizeof(value_buf), "%g", value); + entity_value.value = StringRef(value_buf); api::global_api_server->send_homeassistant_action(resp); } diff --git a/esphome/components/homeassistant/switch/homeassistant_switch.cpp b/esphome/components/homeassistant/switch/homeassistant_switch.cpp index 79d17eb290..cc3d582bf3 100644 --- a/esphome/components/homeassistant/switch/homeassistant_switch.cpp +++ b/esphome/components/homeassistant/switch/homeassistant_switch.cpp @@ -55,7 +55,7 @@ void HomeassistantSwitch::write_state(bool state) { resp.data.init(1); auto &entity_id_kv = resp.data.emplace_back(); entity_id_kv.key = ENTITY_ID_KEY; - entity_id_kv.value = this->entity_id_; + entity_id_kv.value = StringRef(this->entity_id_); api::global_api_server->send_homeassistant_action(resp); } diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 61d2944acf..585b434bb2 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -159,6 +159,12 @@ template class TemplatableValue { return this->value(x...); } + /// Check if this holds a static string (const char* stored without allocation) + bool is_static_string() const { return this->type_ == STATIC_STRING; } + + /// Get the static string pointer (only valid if is_static_string() returns true) + const char *get_static_string() const { return this->static_str_; } + protected: enum : uint8_t { NONE, diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index c61555805e..118c87356e 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -376,10 +376,8 @@ def create_field_type_info( return BytesType(field, needs_decode, needs_encode) - # Special handling for string fields - use StringRef for zero-copy unless no_zero_copy is set + # Special handling for string fields - use StringRef for zero-copy if field.type == 9: - if get_field_opt(field, pb.no_zero_copy, False): - return StringType(field, needs_decode, needs_encode) return PointerToStringBufferType(field, None) validate_field_type(field.type, field.name) @@ -585,15 +583,12 @@ class StringType(TypeInfo): def public_content(self) -> list[str]: content: list[str] = [] - # Check if no_zero_copy option is set - no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False) - - # Add std::string storage if message needs decoding OR if no_zero_copy is set - if self._needs_decode or no_zero_copy: + # Add std::string storage if message needs decoding + if self._needs_decode: content.append(f"std::string {self.field_name}{{}};") - # Only add StringRef if encoding is needed AND no_zero_copy is not set - if self._needs_encode and not no_zero_copy: + # Add StringRef if encoding is needed + if self._needs_encode: content.extend( [ # Add StringRef field if message needs encoding @@ -608,27 +603,14 @@ class StringType(TypeInfo): @property def encode_content(self) -> str: - # Check if no_zero_copy option is set - no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False) - - if no_zero_copy: - # Use the std::string directly - return f"buffer.encode_string({self.number}, this->{self.field_name});" # Use the StringRef return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);" def dump(self, name): - # Check if no_zero_copy option is set - no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False) - # If name is 'it', this is a repeated field element - always use string if name == "it": return "append_quoted_string(out, StringRef(it));" - # If no_zero_copy is set, always use std::string - if no_zero_copy: - return f'out.append("\'").append(this->{self.field_name}).append("\'");' - # For SOURCE_CLIENT only, always use std::string if not self._needs_encode: return f'out.append("\'").append(this->{self.field_name}).append("\'");' @@ -648,13 +630,6 @@ class StringType(TypeInfo): @property def dump_content(self) -> str: - # Check if no_zero_copy option is set - no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False) - - # If no_zero_copy is set, always use std::string - if no_zero_copy: - return f'dump_field(out, "{self.name}", this->{self.field_name});' - # For SOURCE_CLIENT only, use std::string if not self._needs_encode: return f'dump_field(out, "{self.name}", this->{self.field_name});' @@ -670,17 +645,8 @@ class StringType(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - # Check if no_zero_copy option is set - no_zero_copy = get_field_opt(self._field, pb.no_zero_copy, False) - - # For SOURCE_CLIENT only messages or no_zero_copy, use the string field directly - if not self._needs_encode or no_zero_copy: - # For no_zero_copy, we need to use .size() on the string - if no_zero_copy and name != "it": - field_id_size = self.calculate_field_id_size() - return ( - f"size.add_length({field_id_size}, this->{self.field_name}.size());" - ) + # For SOURCE_CLIENT only messages, use the string field directly + if not self._needs_encode: return self._get_simple_size_calculation(name, force, "add_length") # Check if this is being called from a repeated field context From 595217786cc889b431b974728defbfe780e612d9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 11 Jan 2026 18:47:57 -1000 Subject: [PATCH 0054/2030] [tuya][rc522][remote_base] Migrate format_hex_pretty() to stack-based alternatives (#13158) --- esphome/components/rc522/rc522.cpp | 5 ++++- esphome/components/remote_base/midea_protocol.h | 2 ++ esphome/components/tuya/text_sensor/tuya_text_sensor.cpp | 9 ++++++--- esphome/core/entity_base.h | 3 +++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/esphome/components/rc522/rc522.cpp b/esphome/components/rc522/rc522.cpp index 8f8740c925..470c50109e 100644 --- a/esphome/components/rc522/rc522.cpp +++ b/esphome/components/rc522/rc522.cpp @@ -492,7 +492,10 @@ bool RC522BinarySensor::process(std::vector &data) { this->found_ = result; return result; } -void RC522Trigger::process(std::vector &data) { this->trigger(format_hex_pretty(data, '-', false)); } +void RC522Trigger::process(std::vector &data) { + char uid_buf[format_hex_pretty_size(RC522_MAX_UID_SIZE)]; + this->trigger(format_hex_pretty_to(uid_buf, data.data(), data.size(), '-')); +} } // namespace rc522 } // namespace esphome diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index 0a5de8e9df..c3030d565e 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -29,6 +29,8 @@ class MideaData { bool is_valid() const { return this->data_[OFFSET_CS] == this->calc_cs_(); } void finalize() { this->data_[OFFSET_CS] = this->calc_cs_(); } bool is_compliment(const MideaData &rhs) const; + /// @deprecated Allocates heap memory. Use to_str() instead. Removed in 2026.7.0. + ESPDEPRECATED("Allocates heap memory. Use to_str() instead. Removed in 2026.7.0.", "2026.1.0") std::string to_string() const { return format_hex_pretty(this->data_.data(), this->data_.size()); } /// Buffer size for to_str(): 6 bytes = "AA.BB.CC.DD.EE.FF\0" static constexpr size_t TO_STR_BUFFER_SIZE = format_hex_pretty_size(6); diff --git a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp index 3c492d609d..36b6d630ae 100644 --- a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp +++ b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp @@ -1,4 +1,5 @@ #include "tuya_text_sensor.h" +#include "esphome/core/entity_base.h" #include "esphome/core/log.h" namespace esphome { @@ -14,9 +15,11 @@ void TuyaTextSensor::setup() { this->publish_state(datapoint.value_string); break; case TuyaDatapointType::RAW: { - std::string data = format_hex_pretty(datapoint.value_raw); - ESP_LOGD(TAG, "MCU reported text sensor %u is: %s", datapoint.id, data.c_str()); - this->publish_state(data); + char hex_buf[MAX_STATE_LEN + 1]; + const char *formatted = + format_hex_pretty_to(hex_buf, sizeof(hex_buf), datapoint.value_raw.data(), datapoint.value_raw.size()); + ESP_LOGD(TAG, "MCU reported text sensor %u is: %s", datapoint.id, formatted); + this->publish_state(formatted); break; } case TuyaDatapointType::ENUM: { diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 5f75872a0f..f91bd9b20c 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -26,6 +26,9 @@ static constexpr size_t ESPHOME_DOMAIN_MAX_LEN = 20; // Maximum size for object_id buffer (friendly_name + null + margin) static constexpr size_t OBJECT_ID_MAX_LEN = 128; +// Maximum state length that Home Assistant will accept without raising ValueError +static constexpr size_t MAX_STATE_LEN = 255; + enum EntityCategory : uint8_t { ENTITY_CATEGORY_NONE = 0, ENTITY_CATEGORY_CONFIG = 1, From 83eebdf15da04184c2fa1bd3d34aaab541739c6f Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 11 Jan 2026 23:01:23 -0600 Subject: [PATCH 0055/2030] [infrared] Implement experimental API/Core/component for new component/entity type (#13129) Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- CODEOWNERS | 1 + esphome/components/api/api.proto | 48 ++++++ esphome/components/api/api_connection.cpp | 32 ++++ esphome/components/api/api_connection.h | 9 ++ esphome/components/api/api_pb2.cpp | 93 +++++++++++ esphome/components/api/api_pb2.h | 65 ++++++++ esphome/components/api/api_pb2_dump.cpp | 44 +++++ esphome/components/api/api_pb2_service.cpp | 16 ++ esphome/components/api/api_pb2_service.h | 11 ++ esphome/components/api/api_server.cpp | 15 ++ esphome/components/api/api_server.h | 3 + esphome/components/api/list_entities.cpp | 3 + esphome/components/api/list_entities.h | 3 + esphome/components/api/subscribe_state.h | 3 + esphome/components/infrared/__init__.py | 76 +++++++++ esphome/components/infrared/infrared.cpp | 150 ++++++++++++++++++ esphome/components/infrared/infrared.h | 130 +++++++++++++++ .../components/web_server/list_entities.cpp | 7 + esphome/components/web_server/list_entities.h | 3 + esphome/core/application.h | 15 ++ esphome/core/component_iterator.cpp | 6 + esphome/core/component_iterator.h | 12 ++ esphome/core/defines.h | 5 +- tests/components/web_server/common.yaml | 1 + 24 files changed, 750 insertions(+), 1 deletion(-) create mode 100644 esphome/components/infrared/__init__.py create mode 100644 esphome/components/infrared/infrared.cpp create mode 100644 esphome/components/infrared/infrared.h diff --git a/CODEOWNERS b/CODEOWNERS index bdcc86ef0c..48318ee064 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -249,6 +249,7 @@ esphome/components/ina260/* @mreditor97 esphome/components/ina2xx_base/* @latonita esphome/components/ina2xx_i2c/* @latonita esphome/components/ina2xx_spi/* @latonita +esphome/components/infrared/* @kbx81 esphome/components/inkbird_ibsth1_mini/* @fkirill esphome/components/inkplate/* @jesserockz @JosipKuci esphome/components/integration/* @OttoWinter diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index d6384456d5..597da25883 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -66,6 +66,8 @@ service APIConnection { rpc zwave_proxy_frame(ZWaveProxyFrame) returns (void) {} rpc zwave_proxy_request(ZWaveProxyRequest) returns (void) {} + + rpc infrared_rf_transmit_raw_timings(InfraredRFTransmitRawTimingsRequest) returns (void) {} } @@ -2437,3 +2439,49 @@ message ZWaveProxyRequest { ZWaveProxyRequestType type = 1; bytes data = 2; } + +// ==================== INFRARED ==================== +// Note: Feature and capability flag enums are defined in +// esphome/components/infrared/infrared.h + +// Listing of infrared instances +message ListEntitiesInfraredResponse { + option (id) = 135; + option (base_class) = "InfoResponseProtoMessage"; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_INFRARED"; + + string object_id = 1; + fixed32 key = 2; + string name = 3; + string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"]; + bool disabled_by_default = 5; + EntityCategory entity_category = 6; + uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"]; + uint32 capabilities = 8; // Bitfield of InfraredCapabilityFlags +} + +// Command to transmit infrared/RF data using raw timings +message InfraredRFTransmitRawTimingsRequest { + option (id) = 136; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_IR_RF"; + + uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"]; + fixed32 key = 2; // Key identifying the transmitter instance + uint32 carrier_frequency = 3; // Carrier frequency in Hz + uint32 repeat_count = 4; // Number of times to transmit (1 = once, 2 = twice, etc.) + repeated sint32 timings = 5 [packed = true, (packed_buffer) = true]; // Raw timings in microseconds (zigzag-encoded): positive = mark (LED/TX on), negative = space (LED/TX off) +} + +// Event message for received infrared/RF data +message InfraredRFReceiveEvent { + option (id) = 137; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_IR_RF"; + option (no_delay) = true; + + uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"]; + fixed32 key = 2; // Key identifying the receiver instance + repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods +} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index d6f0d84550..65f8c1a8cc 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -46,6 +46,9 @@ #ifdef USE_WATER_HEATER #include "esphome/components/water_heater/water_heater.h" #endif +#ifdef USE_INFRARED +#include "esphome/components/infrared/infrared.h" +#endif namespace esphome::api { @@ -1438,6 +1441,35 @@ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *c } #endif +#ifdef USE_IR_RF +void APIConnection::infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) { + // TODO: When RF is implemented, add a field to the message to distinguish IR vs RF + // and dispatch to the appropriate entity type based on that field. +#ifdef USE_INFRARED + ENTITY_COMMAND_MAKE_CALL(infrared::Infrared, infrared, infrared) + call.set_carrier_frequency(msg.carrier_frequency); + call.set_raw_timings_packed(msg.timings_data_, msg.timings_length_, msg.timings_count_); + call.set_repeat_count(msg.repeat_count); + call.perform(); +#endif +} + +void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) { + this->send_message(msg, InfraredRFReceiveEvent::MESSAGE_TYPE); +} +#endif + +#ifdef USE_INFRARED +uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, + bool is_single) { + auto *infrared = static_cast(entity); + ListEntitiesInfraredResponse msg; + msg.capabilities = infrared->get_capability_flags(); + return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size, + is_single); +} +#endif + #ifdef USE_UPDATE bool APIConnection::send_update_state(update::UpdateEntity *update) { return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE, diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 0289b3d2ff..b3d072ff69 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -172,6 +172,11 @@ class APIConnection final : public APIServerConnection { void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; #endif +#ifdef USE_IR_RF + void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) override; + void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg); +#endif + #ifdef USE_EVENT void send_event(event::Event *event, StringRef event_type); #endif @@ -468,6 +473,10 @@ class APIConnection final : public APIServerConnection { static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); #endif +#ifdef USE_INFRARED + static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, + bool is_single); +#endif #ifdef USE_EVENT static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint32_t remaining_size, bool is_single); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 03a6639b5e..743f51dac7 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3347,5 +3347,98 @@ void ZWaveProxyRequest::calculate_size(ProtoSize &size) const { size.add_length(1, this->data_len); } #endif +#ifdef USE_INFRARED +void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer buffer) const { + buffer.encode_string(1, this->object_id); + buffer.encode_fixed32(2, this->key); + buffer.encode_string(3, this->name); +#ifdef USE_ENTITY_ICON + buffer.encode_string(4, this->icon); +#endif + buffer.encode_bool(5, this->disabled_by_default); + buffer.encode_uint32(6, static_cast(this->entity_category)); +#ifdef USE_DEVICES + buffer.encode_uint32(7, this->device_id); +#endif + buffer.encode_uint32(8, this->capabilities); +} +void ListEntitiesInfraredResponse::calculate_size(ProtoSize &size) const { + size.add_length(1, this->object_id.size()); + size.add_fixed32(1, this->key); + size.add_length(1, this->name.size()); +#ifdef USE_ENTITY_ICON + size.add_length(1, this->icon.size()); +#endif + size.add_bool(1, this->disabled_by_default); + size.add_uint32(1, static_cast(this->entity_category)); +#ifdef USE_DEVICES + size.add_uint32(1, this->device_id); +#endif + size.add_uint32(1, this->capabilities); +} +#endif +#ifdef USE_IR_RF +bool InfraredRFTransmitRawTimingsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { +#ifdef USE_DEVICES + case 1: + this->device_id = value.as_uint32(); + break; +#endif + case 3: + this->carrier_frequency = value.as_uint32(); + break; + case 4: + this->repeat_count = value.as_uint32(); + break; + default: + return false; + } + return true; +} +bool InfraredRFTransmitRawTimingsRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 5: { + this->timings_data_ = value.data(); + this->timings_length_ = value.size(); + this->timings_count_ = count_packed_varints(value.data(), value.size()); + break; + } + default: + return false; + } + return true; +} +bool InfraredRFTransmitRawTimingsRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { + switch (field_id) { + case 2: + this->key = value.as_fixed32(); + break; + default: + return false; + } + return true; +} +void InfraredRFReceiveEvent::encode(ProtoWriteBuffer buffer) const { +#ifdef USE_DEVICES + buffer.encode_uint32(1, this->device_id); +#endif + buffer.encode_fixed32(2, this->key); + for (const auto &it : *this->timings) { + buffer.encode_sint32(3, it, true); + } +} +void InfraredRFReceiveEvent::calculate_size(ProtoSize &size) const { +#ifdef USE_DEVICES + size.add_uint32(1, this->device_id); +#endif + size.add_fixed32(1, this->key); + if (!this->timings->empty()) { + for (const auto &it : *this->timings) { + size.add_sint32_force(1, it); + } + } +} +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index e21b8596ca..0ab38b8b85 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -3049,5 +3049,70 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; #endif +#ifdef USE_INFRARED +class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 135; + static constexpr uint8_t ESTIMATED_SIZE = 44; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "list_entities_infrared_response"; } +#endif + uint32_t capabilities{0}; + void encode(ProtoWriteBuffer buffer) const override; + void calculate_size(ProtoSize &size) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: +}; +#endif +#ifdef USE_IR_RF +class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 136; + static constexpr uint8_t ESTIMATED_SIZE = 220; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "infrared_rf_transmit_raw_timings_request"; } +#endif +#ifdef USE_DEVICES + uint32_t device_id{0}; +#endif + uint32_t key{0}; + uint32_t carrier_frequency{0}; + uint32_t repeat_count{0}; + const uint8_t *timings_data_{nullptr}; + uint16_t timings_length_{0}; + uint16_t timings_count_{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: + bool decode_32bit(uint32_t field_id, Proto32Bit value) override; + bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class InfraredRFReceiveEvent final : public ProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 137; + static constexpr uint8_t ESTIMATED_SIZE = 17; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "infrared_rf_receive_event"; } +#endif +#ifdef USE_DEVICES + uint32_t device_id{0}; +#endif + uint32_t key{0}; + const std::vector *timings{}; + void encode(ProtoWriteBuffer buffer) const override; + void calculate_size(ProtoSize &size) const override; +#ifdef HAS_PROTO_MESSAGE_DUMP + void dump_to(std::string &out) const override; +#endif + + protected: +}; +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 160a9a93c9..8e4d55d11b 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -2309,6 +2309,50 @@ void ZWaveProxyRequest::dump_to(std::string &out) const { out.append("\n"); } #endif +#ifdef USE_INFRARED +void ListEntitiesInfraredResponse::dump_to(std::string &out) const { + MessageDumpHelper helper(out, "ListEntitiesInfraredResponse"); + dump_field(out, "object_id", this->object_id); + dump_field(out, "key", this->key); + dump_field(out, "name", this->name); +#ifdef USE_ENTITY_ICON + dump_field(out, "icon", this->icon); +#endif + dump_field(out, "disabled_by_default", this->disabled_by_default); + dump_field(out, "entity_category", static_cast(this->entity_category)); +#ifdef USE_DEVICES + dump_field(out, "device_id", this->device_id); +#endif + dump_field(out, "capabilities", this->capabilities); +} +#endif +#ifdef USE_IR_RF +void InfraredRFTransmitRawTimingsRequest::dump_to(std::string &out) const { + MessageDumpHelper helper(out, "InfraredRFTransmitRawTimingsRequest"); +#ifdef USE_DEVICES + dump_field(out, "device_id", this->device_id); +#endif + dump_field(out, "key", this->key); + dump_field(out, "carrier_frequency", this->carrier_frequency); + dump_field(out, "repeat_count", this->repeat_count); + out.append(" timings: "); + out.append("packed buffer ["); + out.append(std::to_string(this->timings_count_)); + out.append(" values, "); + out.append(std::to_string(this->timings_length_)); + out.append(" bytes]\n"); +} +void InfraredRFReceiveEvent::dump_to(std::string &out) const { + MessageDumpHelper helper(out, "InfraredRFReceiveEvent"); +#ifdef USE_DEVICES + dump_field(out, "device_id", this->device_id); +#endif + dump_field(out, "key", this->key); + for (const auto &it : *this->timings) { + dump_field(out, "timings", it, 4); + } +} +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index c9bf638ad7..576b802443 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -621,6 +621,17 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, this->on_water_heater_command_request(msg); break; } +#endif +#ifdef USE_IR_RF + case InfraredRFTransmitRawTimingsRequest::MESSAGE_TYPE: { + InfraredRFTransmitRawTimingsRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + ESP_LOGVV(TAG, "on_infrared_rf_transmit_raw_timings_request: %s", msg.dump().c_str()); +#endif + this->on_infrared_rf_transmit_raw_timings_request(msg); + break; + } #endif default: break; @@ -819,6 +830,11 @@ void APIServerConnection::on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) { th #ifdef USE_ZWAVE_PROXY void APIServerConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) { this->zwave_proxy_request(msg); } #endif +#ifdef USE_IR_RF +void APIServerConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) { + this->infrared_rf_transmit_raw_timings(msg); +} +#endif void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { // Check authentication/connection requirements for messages diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index e2a23827dc..4bd6a7b6a4 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -217,6 +217,11 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_ZWAVE_PROXY virtual void on_z_wave_proxy_request(const ZWaveProxyRequest &value){}; #endif + +#ifdef USE_IR_RF + virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){}; +#endif + protected: void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; @@ -347,6 +352,9 @@ class APIServerConnection : public APIServerConnectionBase { #endif #ifdef USE_ZWAVE_PROXY virtual void zwave_proxy_request(const ZWaveProxyRequest &msg) = 0; +#endif +#ifdef USE_IR_RF + virtual void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) = 0; #endif protected: void on_hello_request(const HelloRequest &msg) override; @@ -473,6 +481,9 @@ class APIServerConnection : public APIServerConnectionBase { #endif #ifdef USE_ZWAVE_PROXY void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override; +#endif +#ifdef USE_IR_RF + void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) override; #endif void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 336672f50b..949262098f 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -347,6 +347,21 @@ void APIServer::on_zwave_proxy_request(const esphome::api::ProtoMessage &msg) { } #endif +#ifdef USE_IR_RF +void APIServer::send_infrared_rf_receive_event([[maybe_unused]] uint32_t device_id, uint32_t key, + const std::vector *timings) { + InfraredRFReceiveEvent resp{}; +#ifdef USE_DEVICES + resp.device_id = device_id; +#endif + resp.key = key; + resp.timings = timings; + + for (auto &c : this->clients_) + c->send_infrared_rf_receive_event(resp); +} +#endif + #ifdef USE_ALARM_CONTROL_PANEL API_DISPATCH_UPDATE(alarm_control_panel::AlarmControlPanel, alarm_control_panel) #endif diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index f5b57f994a..93421ef801 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -185,6 +185,9 @@ class APIServer : public Component, #ifdef USE_ZWAVE_PROXY void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg); #endif +#ifdef USE_IR_RF + void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector *timings); +#endif bool is_connected(bool state_subscription_only = false) const; diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index 2470899c93..fe43a47c3b 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -76,6 +76,9 @@ LIST_ENTITIES_HANDLER(alarm_control_panel, alarm_control_panel::AlarmControlPane #ifdef USE_WATER_HEATER LIST_ENTITIES_HANDLER(water_heater, water_heater::WaterHeater, ListEntitiesWaterHeaterResponse) #endif +#ifdef USE_INFRARED +LIST_ENTITIES_HANDLER(infrared, infrared::Infrared, ListEntitiesInfraredResponse) +#endif #ifdef USE_EVENT LIST_ENTITIES_HANDLER(event, event::Event, ListEntitiesEventResponse) #endif diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 04e6525eb0..912aab72b2 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -85,6 +85,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_WATER_HEATER bool on_water_heater(water_heater::WaterHeater *entity) override; #endif +#ifdef USE_INFRARED + bool on_infrared(infrared::Infrared *entity) override; +#endif #ifdef USE_EVENT bool on_event(event::Event *entity) override; #endif diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 9230000ace..3c9f33835a 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -79,6 +79,9 @@ class InitialStateIterator : public ComponentIterator { #ifdef USE_WATER_HEATER bool on_water_heater(water_heater::WaterHeater *entity) override; #endif +#ifdef USE_INFRARED + bool on_infrared(infrared::Infrared *infrared) override { return true; }; +#endif #ifdef USE_EVENT bool on_event(event::Event *event) override { return true; }; #endif diff --git a/esphome/components/infrared/__init__.py b/esphome/components/infrared/__init__.py new file mode 100644 index 0000000000..5c759d6fd9 --- /dev/null +++ b/esphome/components/infrared/__init__.py @@ -0,0 +1,76 @@ +""" +Infrared component for ESPHome. + +WARNING: This component is EXPERIMENTAL. The API (both Python configuration +and C++ interfaces) may change at any time without following the normal +breaking changes policy. Use at your own risk. + +Once the API is considered stable, this warning will be removed. +""" + +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID +from esphome.core import CORE, coroutine_with_priority +from esphome.core.entity_helpers import setup_entity +from esphome.coroutine import CoroPriority +from esphome.types import ConfigType + +CODEOWNERS = ["@kbx81"] +AUTO_LOAD = ["remote_base"] + +IS_PLATFORM_COMPONENT = True + +infrared_ns = cg.esphome_ns.namespace("infrared") +Infrared = infrared_ns.class_("Infrared", cg.EntityBase, cg.Component) +InfraredCall = infrared_ns.class_("InfraredCall") +InfraredTraits = infrared_ns.class_("InfraredTraits") + +CONF_INFRARED_ID = "infrared_id" +CONF_SUPPORTS_TRANSMITTER = "supports_transmitter" +CONF_SUPPORTS_RECEIVER = "supports_receiver" + + +def infrared_schema(class_: type[cg.MockObjClass]) -> cv.Schema: + """Create a schema for an infrared platform. + + :param class_: The infrared class to use for this schema. + :return: An extended schema for infrared configuration. + """ + entity_schema = cv.ENTITY_BASE_SCHEMA.extend(cv.COMPONENT_SCHEMA) + return entity_schema.extend( + { + cv.GenerateID(): cv.declare_id(class_), + } + ) + + +async def setup_infrared_core_(var: cg.Pvariable, config: ConfigType) -> None: + """Set up core infrared configuration.""" + await setup_entity(var, config, "infrared") + + +async def register_infrared(var: cg.Pvariable, config: ConfigType) -> None: + """Register an infrared device with the core.""" + cg.add_define("USE_IR_RF") + await cg.register_component(var, config) + await setup_infrared_core_(var, config) + cg.add(cg.App.register_infrared(var)) + CORE.register_platform_component("infrared", var) + + +async def new_infrared(config: ConfigType, *args) -> cg.Pvariable: + """Create a new Infrared instance. + + :param config: Configuration dictionary. + :param args: Additional arguments to pass to new_Pvariable. + :return: The created Infrared instance. + """ + var = cg.new_Pvariable(config[CONF_ID], *args) + await register_infrared(var, config) + return var + + +@coroutine_with_priority(CoroPriority.CORE) +async def to_code(config: ConfigType) -> None: + cg.add_global(infrared_ns.using) diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp new file mode 100644 index 0000000000..384ff431a5 --- /dev/null +++ b/esphome/components/infrared/infrared.cpp @@ -0,0 +1,150 @@ +#include "infrared.h" +#include "esphome/core/log.h" + +#ifdef USE_API +#include "esphome/components/api/api_server.h" +#endif + +namespace esphome::infrared { + +static const char *const TAG = "infrared"; + +// ========== InfraredCall ========== + +InfraredCall &InfraredCall::set_carrier_frequency(uint32_t frequency) { + this->carrier_frequency_ = frequency; + return *this; +} + +InfraredCall &InfraredCall::set_raw_timings(const std::vector &timings) { + this->raw_timings_ = &timings; + this->packed_data_ = nullptr; // Clear packed if vector is set + return *this; +} + +InfraredCall &InfraredCall::set_raw_timings_packed(const uint8_t *data, uint16_t length, uint16_t count) { + this->packed_data_ = data; + this->packed_length_ = length; + this->packed_count_ = count; + this->raw_timings_ = nullptr; // Clear vector if packed is set + return *this; +} + +InfraredCall &InfraredCall::set_repeat_count(uint32_t count) { + this->repeat_count_ = count; + return *this; +} + +void InfraredCall::perform() { + if (this->parent_ != nullptr) { + this->parent_->control(*this); + } +} + +// ========== Infrared ========== + +void Infrared::setup() { + // Set up traits based on configuration + this->traits_.set_supports_transmitter(this->has_transmitter()); + this->traits_.set_supports_receiver(this->has_receiver()); + + // Register as listener for received IR data + if (this->receiver_ != nullptr) { + this->receiver_->register_listener(this); + } +} + +void Infrared::dump_config() { + ESP_LOGCONFIG(TAG, + "Infrared '%s'\n" + " Supports Transmitter: %s\n" + " Supports Receiver: %s", + this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()), + YESNO(this->traits_.get_supports_receiver())); +} + +InfraredCall Infrared::make_call() { return InfraredCall(this); } + +void Infrared::control(const InfraredCall &call) { + if (this->transmitter_ == nullptr) { + ESP_LOGW(TAG, "No transmitter configured"); + return; + } + + if (!call.has_raw_timings()) { + ESP_LOGE(TAG, "No raw timings provided"); + return; + } + + // Create transmit data object + auto transmit_call = this->transmitter_->transmit(); + auto *transmit_data = transmit_call.get_data(); + + // Set carrier frequency + if (call.get_carrier_frequency().has_value()) { + transmit_data->set_carrier_frequency(call.get_carrier_frequency().value()); + } + + // Set timings based on format + if (call.is_packed()) { + // Zero-copy from packed protobuf data + ESP_LOGD(TAG, "Transmitting raw timings: timing_count=%u, repeat_count=%u", call.get_packed_count(), + call.get_repeat_count()); + transmit_data->set_data_from_packed_sint32(call.get_packed_data(), call.get_packed_length(), + call.get_packed_count()); + } else { + // From vector (lambdas/automations) + const auto &timings = call.get_raw_timings(); + if (timings.empty()) { + ESP_LOGE(TAG, "Raw timings array is empty"); + return; + } + ESP_LOGD(TAG, "Transmitting raw timings: timing_count=%zu, repeat_count=%u", timings.size(), + call.get_repeat_count()); + // Timings format: positive values = mark (LED on), negative values = space (LED off) + for (const auto &timing : timings) { + if (timing > 0) { + transmit_data->mark(static_cast(timing)); + } else { + transmit_data->space(static_cast(-timing)); + } + } + } + + // Set repeat count + if (call.get_repeat_count() > 0) { + transmit_call.set_send_times(call.get_repeat_count()); + } + + // Perform transmission + transmit_call.perform(); +} + +uint32_t Infrared::get_capability_flags() const { + uint32_t flags = 0; + + // Add transmit/receive capability based on traits + if (this->traits_.get_supports_transmitter()) + flags |= InfraredCapability::CAPABILITY_TRANSMITTER; + if (this->traits_.get_supports_receiver()) + flags |= InfraredCapability::CAPABILITY_RECEIVER; + + return flags; +} + +bool Infrared::on_receive(remote_base::RemoteReceiveData data) { + // Forward received IR data to API server +#if defined(USE_API) && defined(USE_IR_RF) + if (api::global_api_server != nullptr) { +#ifdef USE_DEVICES + uint32_t device_id = this->get_device_id(); +#else + uint32_t device_id = 0; +#endif + api::global_api_server->send_infrared_rf_receive_event(device_id, this->get_object_id_hash(), &data.get_raw_data()); + } +#endif + return false; // Don't consume the event, allow other listeners to process it +} + +} // namespace esphome::infrared diff --git a/esphome/components/infrared/infrared.h b/esphome/components/infrared/infrared.h new file mode 100644 index 0000000000..3a891301f4 --- /dev/null +++ b/esphome/components/infrared/infrared.h @@ -0,0 +1,130 @@ +#pragma once + +// WARNING: This component is EXPERIMENTAL. The API may change at any time +// without following the normal breaking changes policy. Use at your own risk. +// Once the API is considered stable, this warning will be removed. + +#include "esphome/core/component.h" +#include "esphome/core/entity_base.h" +#include "esphome/components/remote_base/remote_base.h" + +#include + +namespace esphome::infrared { + +/// Capability flags for individual infrared instances +enum InfraredCapability : uint32_t { + CAPABILITY_TRANSMITTER = 1 << 0, // Can transmit signals + CAPABILITY_RECEIVER = 1 << 1, // Can receive signals +}; + +/// Forward declarations +class Infrared; + +/// InfraredCall - Builder pattern for transmitting infrared signals +class InfraredCall { + public: + explicit InfraredCall(Infrared *parent) : parent_(parent) {} + + /// Set the carrier frequency in Hz + InfraredCall &set_carrier_frequency(uint32_t frequency); + /// Set the raw timings (positive = mark, negative = space) + /// Note: The timings vector must outlive the InfraredCall (zero-copy reference) + InfraredCall &set_raw_timings(const std::vector &timings); + /// Set the raw timings from packed protobuf sint32 data (zero-copy from wire) + /// Note: The data must outlive the InfraredCall + InfraredCall &set_raw_timings_packed(const uint8_t *data, uint16_t length, uint16_t count); + /// Set the number of times to repeat transmission (1 = transmit once, 2 = transmit twice, etc.) + InfraredCall &set_repeat_count(uint32_t count); + + /// Perform the transmission + void perform(); + + /// Get the carrier frequency + const optional &get_carrier_frequency() const { return this->carrier_frequency_; } + /// Get the raw timings (only valid if set via set_raw_timings, not packed) + const std::vector &get_raw_timings() const { return *this->raw_timings_; } + /// Check if raw timings have been set (either vector or packed) + bool has_raw_timings() const { return this->raw_timings_ != nullptr || this->packed_data_ != nullptr; } + /// Check if using packed data format + bool is_packed() const { return this->packed_data_ != nullptr; } + /// Get packed data (only valid if set via set_raw_timings_packed) + const uint8_t *get_packed_data() const { return this->packed_data_; } + uint16_t get_packed_length() const { return this->packed_length_; } + uint16_t get_packed_count() const { return this->packed_count_; } + /// Get the repeat count + uint32_t get_repeat_count() const { return this->repeat_count_; } + + protected: + uint32_t repeat_count_{1}; + Infrared *parent_; + optional carrier_frequency_; + // Vector-based timings (for lambdas/automations) + const std::vector *raw_timings_{nullptr}; + // Packed protobuf timings (for API zero-copy) + const uint8_t *packed_data_{nullptr}; + uint16_t packed_length_{0}; + uint16_t packed_count_{0}; +}; + +/// InfraredTraits - Describes the capabilities of an infrared implementation +class InfraredTraits { + public: + bool get_supports_transmitter() const { return this->supports_transmitter_; } + void set_supports_transmitter(bool supports) { this->supports_transmitter_ = supports; } + + bool get_supports_receiver() const { return this->supports_receiver_; } + void set_supports_receiver(bool supports) { this->supports_receiver_ = supports; } + + protected: + bool supports_transmitter_{false}; + bool supports_receiver_{false}; +}; + +/// Infrared - Base class for infrared remote control implementations +class Infrared : public Component, public EntityBase, public remote_base::RemoteReceiverListener { + public: + Infrared() = default; + + void setup() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; } + + /// Set the remote receiver component + void set_receiver(remote_base::RemoteReceiverBase *receiver) { this->receiver_ = receiver; } + /// Set the remote transmitter component + void set_transmitter(remote_base::RemoteTransmitterBase *transmitter) { this->transmitter_ = transmitter; } + + /// Check if this infrared has a transmitter configured + bool has_transmitter() const { return this->transmitter_ != nullptr; } + /// Check if this infrared has a receiver configured + bool has_receiver() const { return this->receiver_ != nullptr; } + + /// Get the traits for this infrared implementation + InfraredTraits &get_traits() { return this->traits_; } + const InfraredTraits &get_traits() const { return this->traits_; } + + /// Create a call object for transmitting + InfraredCall make_call(); + + /// Get capability flags for this infrared instance + uint32_t get_capability_flags() const; + + /// Called when IR data is received (from RemoteReceiverListener) + bool on_receive(remote_base::RemoteReceiveData data) override; + + protected: + friend class InfraredCall; + + /// Perform the actual transmission (called by InfraredCall) + virtual void control(const InfraredCall &call); + + // Underlying hardware components + remote_base::RemoteReceiverBase *receiver_{nullptr}; + remote_base::RemoteTransmitterBase *transmitter_{nullptr}; + + // Traits describing capabilities + InfraredTraits traits_; +}; + +} // namespace esphome::infrared diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 1e852f6a96..0af9521326 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -141,6 +141,13 @@ bool ListEntitiesIterator::on_water_heater(water_heater::WaterHeater *obj) { } #endif +#ifdef USE_INFRARED +bool ListEntitiesIterator::on_infrared(infrared::Infrared *obj) { + // Infrared web_server support not yet implemented - this stub acknowledges the entity + return true; +} +#endif + #ifdef USE_EVENT bool ListEntitiesIterator::on_event(event::Event *obj) { // Null event type, since we are just iterating over entities diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index 56fd91a8c6..d0a4fa2725 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -82,6 +82,9 @@ class ListEntitiesIterator : public ComponentIterator { #ifdef USE_WATER_HEATER bool on_water_heater(water_heater::WaterHeater *obj) override; #endif +#ifdef USE_INFRARED + bool on_infrared(infrared::Infrared *obj) override; +#endif #ifdef USE_EVENT bool on_event(event::Event *obj) override; #endif diff --git a/esphome/core/application.h b/esphome/core/application.h index 13461b3ebd..592bf809f1 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -91,6 +91,9 @@ #ifdef USE_WATER_HEATER #include "esphome/components/water_heater/water_heater.h" #endif +#ifdef USE_INFRARED +#include "esphome/components/infrared/infrared.h" +#endif #ifdef USE_EVENT #include "esphome/components/event/event.h" #endif @@ -223,6 +226,10 @@ class Application { void register_water_heater(water_heater::WaterHeater *water_heater) { this->water_heaters_.push_back(water_heater); } #endif +#ifdef USE_INFRARED + void register_infrared(infrared::Infrared *infrared) { this->infrareds_.push_back(infrared); } +#endif + #ifdef USE_EVENT void register_event(event::Event *event) { this->events_.push_back(event); } #endif @@ -457,6 +464,11 @@ class Application { GET_ENTITY_METHOD(water_heater::WaterHeater, water_heater, water_heaters) #endif +#ifdef USE_INFRARED + auto &get_infrareds() const { return this->infrareds_; } + GET_ENTITY_METHOD(infrared::Infrared, infrared, infrareds) +#endif + #ifdef USE_EVENT auto &get_events() const { return this->events_; } GET_ENTITY_METHOD(event::Event, event, events) @@ -656,6 +668,9 @@ class Application { #ifdef USE_WATER_HEATER StaticVector water_heaters_{}; #endif +#ifdef USE_INFRARED + StaticVector infrareds_{}; +#endif #ifdef USE_UPDATE StaticVector updates_{}; #endif diff --git a/esphome/core/component_iterator.cpp b/esphome/core/component_iterator.cpp index 4015d8ec60..ff76b2b81b 100644 --- a/esphome/core/component_iterator.cpp +++ b/esphome/core/component_iterator.cpp @@ -169,6 +169,12 @@ void ComponentIterator::advance() { break; #endif +#ifdef USE_INFRARED + case IteratorState::INFRARED: + this->process_platform_item_(App.get_infrareds(), &ComponentIterator::on_infrared); + break; +#endif + #ifdef USE_EVENT case IteratorState::EVENT: this->process_platform_item_(App.get_events(), &ComponentIterator::on_event); diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index 37d1960601..e13d81a8e4 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -16,6 +16,12 @@ class UserServiceDescriptor; } // namespace api #endif +#ifdef USE_INFRARED +namespace infrared { +class Infrared; +} // namespace infrared +#endif + class ComponentIterator { public: void begin(bool include_internal = false); @@ -87,6 +93,9 @@ class ComponentIterator { #ifdef USE_WATER_HEATER virtual bool on_water_heater(water_heater::WaterHeater *water_heater) = 0; #endif +#ifdef USE_INFRARED + virtual bool on_infrared(infrared::Infrared *infrared) = 0; +#endif #ifdef USE_EVENT virtual bool on_event(event::Event *event) = 0; #endif @@ -167,6 +176,9 @@ class ComponentIterator { #ifdef USE_WATER_HEATER WATER_HEATER, #endif +#ifdef USE_INFRARED + INFRARED, +#endif #ifdef USE_EVENT EVENT, #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index ed5f152e9f..633b0c6c5e 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -49,6 +49,8 @@ #define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT #define USE_IMAGE #define USE_IMPROV_SERIAL_NEXT_URL +#define USE_INFRARED +#define USE_IR_RF #define USE_JSON #define USE_LIGHT #define USE_LOCK @@ -321,9 +323,9 @@ // Default counts for static analysis #define CONTROLLER_REGISTRY_MAX 2 +#define ESPHOME_AREA_COUNT 10 #define ESPHOME_COMPONENT_COUNT 50 #define ESPHOME_DEVICE_COUNT 10 -#define ESPHOME_AREA_COUNT 10 #define ESPHOME_ENTITY_ALARM_CONTROL_PANEL_COUNT 1 #define ESPHOME_ENTITY_BINARY_SENSOR_COUNT 1 #define ESPHOME_ENTITY_BUTTON_COUNT 1 @@ -333,6 +335,7 @@ #define ESPHOME_ENTITY_DATETIME_COUNT 1 #define ESPHOME_ENTITY_EVENT_COUNT 1 #define ESPHOME_ENTITY_FAN_COUNT 1 +#define ESPHOME_ENTITY_INFRARED_COUNT 1 #define ESPHOME_ENTITY_LIGHT_COUNT 1 #define ESPHOME_ENTITY_LOCK_COUNT 1 #define ESPHOME_ENTITY_MEDIA_PLAYER_COUNT 1 diff --git a/tests/components/web_server/common.yaml b/tests/components/web_server/common.yaml index 82307c189c..35a605484c 100644 --- a/tests/components/web_server/common.yaml +++ b/tests/components/web_server/common.yaml @@ -37,3 +37,4 @@ datetime: event: update: water_heater: +infrared: From 29cef3bc5d8f8cc01da2a1db17f936649667790d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 11 Jan 2026 19:26:40 -1000 Subject: [PATCH 0056/2030] Bump aioesphomeapi from 43.12.0 to 43.13.0 (#13160) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d3bb5b5dc5..9994148cf6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 -aioesphomeapi==43.12.0 +aioesphomeapi==43.13.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 6c68ebe86e8c6a0f717ea7ed3b4056c16fb98ab1 Mon Sep 17 00:00:00 2001 From: Jas Strong Date: Mon, 12 Jan 2026 06:25:43 -0800 Subject: [PATCH 0057/2030] [rd03d] Filter targets with sentinel speed values (#13146) Co-authored-by: jas --- esphome/components/rd03d/rd03d.cpp | 50 +++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index 44e479c153..d9b0b59fe9 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -21,6 +21,11 @@ static constexpr uint8_t CMD_FRAME_FOOTER[] = {0x04, 0x03, 0x02, 0x01}; static constexpr uint16_t CMD_SINGLE_TARGET = 0x0080; static constexpr uint16_t CMD_MULTI_TARGET = 0x0090; +// Speed sentinel values (cm/s) - radar outputs these when no valid Doppler measurement +// FMCW radars detect motion via Doppler shift; targets with these speeds are likely noise +static constexpr int16_t SPEED_SENTINEL_248 = 248; +static constexpr int16_t SPEED_SENTINEL_256 = 256; + // Decode coordinate/speed value from RD-03D format // Per datasheet: MSB=1 means positive, MSB=0 means negative static constexpr int16_t decode_value(uint8_t low_byte, uint8_t high_byte) { @@ -31,6 +36,13 @@ static constexpr int16_t decode_value(uint8_t low_byte, uint8_t high_byte) { return value; } +// Check if speed value indicates a valid Doppler measurement +// Zero, ±248, or ±256 cm/s are sentinel values from the radar firmware +static constexpr bool is_speed_valid(int16_t speed) { + int16_t abs_speed = speed < 0 ? -speed : speed; + return speed != 0 && abs_speed != SPEED_SENTINEL_248 && abs_speed != SPEED_SENTINEL_256; +} + void RD03DComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up RD-03D..."); this->set_timeout(SETUP_TIMEOUT_MS, [this]() { this->apply_config_(); }); @@ -136,8 +148,12 @@ void RD03DComponent::process_frame_() { int16_t speed = decode_value(speed_low, speed_high); uint16_t resolution = (res_high << 8) | res_low; - // Check if target is present (non-zero coordinates) - bool target_present = (x != 0 || y != 0); + // Check if target is present + // Requires non-zero coordinates AND valid speed (not a sentinel value) + // FMCW radars detect motion via Doppler; sentinel speed indicates no real target + bool has_position = (x != 0 || y != 0); + bool has_valid_speed = is_speed_valid(speed); + bool target_present = has_position && has_valid_speed; if (target_present) { target_count++; } @@ -169,20 +185,21 @@ void RD03DComponent::process_frame_() { #ifdef USE_SENSOR void RD03DComponent::publish_target_(uint8_t target_num, int16_t x, int16_t y, int16_t speed, uint16_t resolution) { TargetSensor &target = this->targets_[target_num]; + bool valid = is_speed_valid(speed); - // Publish X coordinate (mm) + // Publish X coordinate (mm) - NaN if target invalid if (target.x != nullptr) { - target.x->publish_state(x); + target.x->publish_state(valid ? static_cast(x) : NAN); } - // Publish Y coordinate (mm) + // Publish Y coordinate (mm) - NaN if target invalid if (target.y != nullptr) { - target.y->publish_state(y); + target.y->publish_state(valid ? static_cast(y) : NAN); } - // Publish speed (convert from cm/s to mm/s) + // Publish speed (convert from cm/s to mm/s) - NaN if target invalid if (target.speed != nullptr) { - target.speed->publish_state(static_cast(speed) * 10.0f); + target.speed->publish_state(valid ? static_cast(speed) * 10.0f : NAN); } // Publish resolution (mm) @@ -190,20 +207,23 @@ void RD03DComponent::publish_target_(uint8_t target_num, int16_t x, int16_t y, i target.resolution->publish_state(resolution); } - // Calculate and publish distance (mm) + // Calculate and publish distance (mm) - NaN if target invalid if (target.distance != nullptr) { - float distance = std::hypot(static_cast(x), static_cast(y)); - target.distance->publish_state(distance); + if (valid) { + target.distance->publish_state(std::hypot(static_cast(x), static_cast(y))); + } else { + target.distance->publish_state(NAN); + } } - // Calculate and publish angle (degrees) + // Calculate and publish angle (degrees) - NaN if target invalid // Angle is measured from the Y axis (radar forward direction) if (target.angle != nullptr) { - if (x == 0 && y == 0) { - target.angle->publish_state(0); - } else { + if (valid) { float angle = std::atan2(static_cast(x), static_cast(y)) * 180.0f / M_PI; target.angle->publish_state(angle); + } else { + target.angle->publish_state(NAN); } } } From 353daa97d0f6f9468bbfba238c4f79493ad59992 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 12 Jan 2026 15:45:15 +0100 Subject: [PATCH 0058/2030] [nrf52,zigbee] Warning if spaces in description (#13114) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/zigbee/__init__.py | 11 ++++++++++- esphome/components/zigbee/zigbee_zephyr.py | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index cf37e890c4..e363164997 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -1,3 +1,4 @@ +import logging from typing import Any from esphome import automation, core @@ -6,7 +7,7 @@ from esphome.components.nrf52.boards import BOOTLOADER_CONFIG, Section from esphome.components.zephyr import zephyr_add_pm_static, zephyr_data from esphome.components.zephyr.const import KEY_BOOTLOADER import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_INTERNAL +from esphome.const import CONF_ID, CONF_INTERNAL, CONF_NAME from esphome.core import CORE from esphome.types import ConfigType @@ -24,6 +25,8 @@ from .const_zephyr import ( ) from .zigbee_zephyr import zephyr_binary_sensor, zephyr_sensor +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@tomaszduda23"] @@ -107,6 +110,12 @@ async def setup_sensor(entity: cg.MockObj, config: ConfigType) -> None: def consume_endpoint(config: ConfigType) -> ConfigType: if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): return config + if " " in config[CONF_NAME]: + _LOGGER.warning( + "Spaces in '%s' work with ZHA but not Zigbee2MQTT. For Zigbee2MQTT use '%s'", + config[CONF_NAME], + config[CONF_NAME].replace(" ", "_"), + ) data: dict[str, Any] = CORE.data.setdefault(KEY_ZIGBEE, {}) slots: list[str] = data.setdefault(KEY_EP_NUMBER, []) slots.extend([""]) diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index d8a2716603..71ea0da6a7 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -212,6 +212,8 @@ def zigbee_assign(target: cg.MockObj, expression: cg.RawExpression | int) -> str def zigbee_set_string(target: cg.MockObj, value: str) -> str: """Set a ZCL string value and return the target name (arrays decay to pointers).""" + # Zigbee supports only ASCII + value = value.encode("ascii", "ignore").decode() cg.add( cg.RawExpression( f"ZB_ZCL_SET_STRING_VAL({target}, {cg.safe_exp(value)}, ZB_ZCL_STRING_CONST_SIZE({cg.safe_exp(value)}))" From 7ea6bcef88c55631aff114bad0214d250c7cb3a2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 07:37:58 -1000 Subject: [PATCH 0059/2030] [api] Use stack buffer for bytes field dumping in proto message logs (#13162) --- esphome/components/api/api_pb2_dump.cpp | 62 +++++++++---------------- script/api_protobuf/api_protobuf.py | 52 ++++++++++++++++----- 2 files changed, 64 insertions(+), 50 deletions(-) diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 8e4d55d11b..9550ecbcdd 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -100,6 +100,16 @@ template static void dump_field(std::string &out, const char *field_ out.append("\n"); } +// Helper for bytes fields - uses stack buffer to avoid heap allocation +// Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer +static void dump_bytes_field(std::string &out, const char *field_name, const uint8_t *data, size_t len, + int indent = 2) { + char hex_buf[format_hex_pretty_size(160)]; + append_field_prefix(out, field_name, indent); + format_hex_pretty_to(hex_buf, data, len); + append_with_newline(out, hex_buf); +} + template<> const char *proto_enum_to_string(enums::EntityCategory value) { switch (value) { case enums::ENTITY_CATEGORY_NONE: @@ -1127,16 +1137,12 @@ void SubscribeLogsRequest::dump_to(std::string &out) const { void SubscribeLogsResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "SubscribeLogsResponse"); dump_field(out, "level", static_cast(this->level)); - out.append(" message: "); - out.append(format_hex_pretty(this->message_ptr_, this->message_len_)); - out.append("\n"); + dump_bytes_field(out, "message", this->message_ptr_, this->message_len_); } #ifdef USE_API_NOISE void NoiseEncryptionSetKeyRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "NoiseEncryptionSetKeyRequest"); - out.append(" key: "); - out.append(format_hex_pretty(this->key, this->key_len)); - out.append("\n"); + dump_bytes_field(out, "key", this->key, this->key_len); } void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "NoiseEncryptionSetKeyResponse"); @@ -1189,9 +1195,7 @@ void HomeassistantActionResponse::dump_to(std::string &out) const { dump_field(out, "success", this->success); dump_field(out, "error_message", this->error_message); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - out.append(" response_data: "); - out.append(format_hex_pretty(this->response_data, this->response_data_len)); - out.append("\n"); + dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); #endif } #endif @@ -1278,9 +1282,7 @@ void ExecuteServiceResponse::dump_to(std::string &out) const { dump_field(out, "success", this->success); dump_field(out, "error_message", this->error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - out.append(" response_data: "); - out.append(format_hex_pretty(this->response_data, this->response_data_len)); - out.append("\n"); + dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); #endif } #endif @@ -1302,9 +1304,7 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const { void CameraImageResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "CameraImageResponse"); dump_field(out, "key", this->key); - out.append(" data: "); - out.append(format_hex_pretty(this->data_ptr_, this->data_len_)); - out.append("\n"); + dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); dump_field(out, "done", this->done); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); @@ -1705,9 +1705,7 @@ void BluetoothLERawAdvertisement::dump_to(std::string &out) const { dump_field(out, "address", this->address); dump_field(out, "rssi", this->rssi); dump_field(out, "address_type", this->address_type); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); } void BluetoothLERawAdvertisementsResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothLERawAdvertisementsResponse"); @@ -1792,18 +1790,14 @@ void BluetoothGATTReadResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTReadResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); - out.append(" data: "); - out.append(format_hex_pretty(this->data_ptr_, this->data_len_)); - out.append("\n"); + dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); } void BluetoothGATTWriteRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTWriteRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_field(out, "response", this->response); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); } void BluetoothGATTReadDescriptorRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTReadDescriptorRequest"); @@ -1814,9 +1808,7 @@ void BluetoothGATTWriteDescriptorRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTWriteDescriptorRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); } void BluetoothGATTNotifyRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTNotifyRequest"); @@ -1828,9 +1820,7 @@ void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const { MessageDumpHelper helper(out, "BluetoothGATTNotifyDataResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); - out.append(" data: "); - out.append(format_hex_pretty(this->data_ptr_, this->data_len_)); - out.append("\n"); + dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); } void SubscribeBluetoothConnectionsFreeRequest::dump_to(std::string &out) const { out.append("SubscribeBluetoothConnectionsFreeRequest {}"); @@ -1934,9 +1924,7 @@ void VoiceAssistantEventResponse::dump_to(std::string &out) const { } void VoiceAssistantAudio::dump_to(std::string &out) const { MessageDumpHelper helper(out, "VoiceAssistantAudio"); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); dump_field(out, "end", this->end); } void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const { @@ -2297,16 +2285,12 @@ void UpdateCommandRequest::dump_to(std::string &out) const { #ifdef USE_ZWAVE_PROXY void ZWaveProxyFrame::dump_to(std::string &out) const { MessageDumpHelper helper(out, "ZWaveProxyFrame"); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); } void ZWaveProxyRequest::dump_to(std::string &out) const { MessageDumpHelper helper(out, "ZWaveProxyRequest"); dump_field(out, "type", static_cast(this->type)); - out.append(" data: "); - out.append(format_hex_pretty(this->data, this->data_len)); - out.append("\n"); + dump_bytes_field(out, "data", this->data, this->data_len); } #endif #ifdef USE_INFRARED diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 118c87356e..a10a912186 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -786,10 +786,32 @@ class BytesType(TypeInfo): @property def dump_content(self) -> str: - o = f'out.append(" {self.name}: ");\n' - o += self.dump(f"this->{self.field_name}") + "\n" - o += 'out.append("\\n");' - return o + # For SOURCE_CLIENT only, always use std::string + if not self._needs_encode: + return ( + f'dump_bytes_field(out, "{self.name}", ' + f"reinterpret_cast(this->{self.field_name}.data()), " + f"this->{self.field_name}.size());" + ) + + # For SOURCE_SERVER, always use pointer/length + if not self._needs_decode: + return ( + f'dump_bytes_field(out, "{self.name}", ' + f"this->{self.field_name}_ptr_, this->{self.field_name}_len_);" + ) + + # For SOURCE_BOTH, check if pointer is set (sending) or use string (received) + return ( + f"if (this->{self.field_name}_ptr_ != nullptr) {{\n" + f' dump_bytes_field(out, "{self.name}", ' + f"this->{self.field_name}_ptr_, this->{self.field_name}_len_);\n" + f"}} else {{\n" + f' dump_bytes_field(out, "{self.name}", ' + f"reinterpret_cast(this->{self.field_name}.data()), " + f"this->{self.field_name}.size());\n" + f"}}" + ) def get_size_calculation(self, name: str, force: bool = False) -> str: return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);" @@ -862,9 +884,8 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): @property def dump_content(self) -> str: return ( - f'out.append(" {self.name}: ");\n' - + f"out.append({self.dump(self.field_name)});\n" - + 'out.append("\\n");' + f'dump_bytes_field(out, "{self.name}", ' + f"this->{self.field_name}, this->{self.field_name}_len);" ) def get_size_calculation(self, name: str, force: bool = False) -> str: @@ -1062,10 +1083,10 @@ class FixedArrayBytesType(TypeInfo): @property def dump_content(self) -> str: - o = f'out.append(" {self.name}: ");\n' - o += f"out.append(format_hex_pretty(this->{self.field_name}, this->{self.field_name}_len));\n" - o += 'out.append("\\n");' - return o + return ( + f'dump_bytes_field(out, "{self.name}", ' + f"this->{self.field_name}, this->{self.field_name}_len);" + ) def get_size_calculation(self, name: str, force: bool = False) -> str: # Use the actual length stored in the _len field @@ -2658,6 +2679,15 @@ static void dump_field(std::string &out, const char *field_name, T value, int in out.append("\\n"); } +// Helper for bytes fields - uses stack buffer to avoid heap allocation +// Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer +static void dump_bytes_field(std::string &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { + char hex_buf[format_hex_pretty_size(160)]; + append_field_prefix(out, field_name, indent); + format_hex_pretty_to(hex_buf, data, len); + append_with_newline(out, hex_buf); +} + """ content += "namespace enums {\n\n" From 8cccfa5369535059fd7e05aebaa58fcabe07a0d7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 07:38:20 -1000 Subject: [PATCH 0060/2030] [mqtt][prometheus][graph] Migrate value_accuracy_to_string() to stack-based alternative (#13159) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/graph/graph.cpp | 24 +++++----- .../components/mqtt/custom_mqtt_device.cpp | 5 ++- esphome/components/mqtt/mqtt_climate.cpp | 13 +++--- esphome/components/mqtt/mqtt_cover.cpp | 6 ++- esphome/components/mqtt/mqtt_sensor.cpp | 4 +- esphome/components/mqtt/mqtt_valve.cpp | 3 +- .../prometheus/prometheus_handler.cpp | 45 ++++++++++--------- .../prometheus/prometheus_handler.h | 2 +- esphome/core/helpers.h | 3 +- 9 files changed, 60 insertions(+), 45 deletions(-) diff --git a/esphome/components/graph/graph.cpp b/esphome/components/graph/graph.cpp index e3b9119108..c43cd07fe0 100644 --- a/esphome/components/graph/graph.cpp +++ b/esphome/components/graph/graph.cpp @@ -232,17 +232,19 @@ void GraphLegend::init(Graph *g) { ESP_LOGI(TAGL, " %s %d %d", txtstr.c_str(), fw, fh); if (this->values_ != VALUE_POSITION_TYPE_NONE) { - std::string valstr = - value_accuracy_to_string(trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals()); + char valstr[VALUE_ACCURACY_MAX_LEN]; if (this->units_) { - valstr += trace->sensor_->get_unit_of_measurement_ref(); + value_accuracy_with_uom_to_buf(valstr, trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals(), + trace->sensor_->get_unit_of_measurement_ref()); + } else { + value_accuracy_to_buf(valstr, trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals()); } - this->font_value_->measure(valstr.c_str(), &fw, &fos, &fbl, &fh); + this->font_value_->measure(valstr, &fw, &fos, &fbl, &fh); if (fw > valw) valw = fw; if (fh > valh) valh = fh; - ESP_LOGI(TAGL, " %s %d %d", valstr.c_str(), fw, fh); + ESP_LOGI(TAGL, " %s %d %d", valstr, fw, fh); } } // Add extra margin @@ -368,13 +370,15 @@ void Graph::draw_legend(display::Display *buff, uint16_t x_offset, uint16_t y_of if (legend_->values_ != VALUE_POSITION_TYPE_NONE) { int xv = x + legend_->xv_; int yv = y + legend_->yv_; - std::string valstr = - value_accuracy_to_string(trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals()); + char valstr[VALUE_ACCURACY_MAX_LEN]; if (legend_->units_) { - valstr += trace->sensor_->get_unit_of_measurement_ref(); + value_accuracy_with_uom_to_buf(valstr, trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals(), + trace->sensor_->get_unit_of_measurement_ref()); + } else { + value_accuracy_to_buf(valstr, trace->sensor_->get_state(), trace->sensor_->get_accuracy_decimals()); } - buff->printf(xv, yv, legend_->font_value_, trace->get_line_color(), TextAlign::TOP_CENTER, "%s", valstr.c_str()); - ESP_LOGV(TAG, " value: %s", valstr.c_str()); + buff->printf(xv, yv, legend_->font_value_, trace->get_line_color(), TextAlign::TOP_CENTER, "%s", valstr); + ESP_LOGV(TAG, " value: %s", valstr); } x += legend_->xs_; y += legend_->ys_; diff --git a/esphome/components/mqtt/custom_mqtt_device.cpp b/esphome/components/mqtt/custom_mqtt_device.cpp index 25a8a82066..c900e3861d 100644 --- a/esphome/components/mqtt/custom_mqtt_device.cpp +++ b/esphome/components/mqtt/custom_mqtt_device.cpp @@ -12,8 +12,9 @@ bool CustomMQTTDevice::publish(const std::string &topic, const std::string &payl return global_mqtt_client->publish(topic, payload, qos, retain); } bool CustomMQTTDevice::publish(const std::string &topic, float value, int8_t number_decimals) { - auto str = value_accuracy_to_string(value, number_decimals); - return this->publish(topic, str); + char buf[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(buf, value, number_decimals); + return this->publish(topic, buf); } bool CustomMQTTDevice::publish(const std::string &topic, int value) { char buffer[24]; diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 625fb715a7..c7e086115b 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -291,35 +291,36 @@ bool MQTTClimateComponent::publish_state_() { success = false; int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); + char payload[VALUE_ACCURACY_MAX_LEN]; if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE) && !std::isnan(this->device_->current_temperature)) { - std::string payload = value_accuracy_to_string(this->device_->current_temperature, current_accuracy); + value_accuracy_to_buf(payload, this->device_->current_temperature, current_accuracy); if (!this->publish(this->get_current_temperature_state_topic(), payload)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { - std::string payload = value_accuracy_to_string(this->device_->target_temperature_low, target_accuracy); + value_accuracy_to_buf(payload, this->device_->target_temperature_low, target_accuracy); if (!this->publish(this->get_target_temperature_low_state_topic(), payload)) success = false; - payload = value_accuracy_to_string(this->device_->target_temperature_high, target_accuracy); + value_accuracy_to_buf(payload, this->device_->target_temperature_high, target_accuracy); if (!this->publish(this->get_target_temperature_high_state_topic(), payload)) success = false; } else { - std::string payload = value_accuracy_to_string(this->device_->target_temperature, target_accuracy); + value_accuracy_to_buf(payload, this->device_->target_temperature, target_accuracy); if (!this->publish(this->get_target_temperature_state_topic(), payload)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY) && !std::isnan(this->device_->current_humidity)) { - std::string payload = value_accuracy_to_string(this->device_->current_humidity, 0); + value_accuracy_to_buf(payload, this->device_->current_humidity, 0); if (!this->publish(this->get_current_humidity_state_topic(), payload)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY) && !std::isnan(this->device_->target_humidity)) { - std::string payload = value_accuracy_to_string(this->device_->target_humidity, 0); + value_accuracy_to_buf(payload, this->device_->target_humidity, 0); if (!this->publish(this->get_target_humidity_state_topic(), payload)) success = false; } diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index 4505027485..2164b5ca44 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -98,12 +98,14 @@ bool MQTTCoverComponent::publish_state() { auto traits = this->cover_->get_traits(); bool success = true; if (traits.get_supports_position()) { - std::string pos = value_accuracy_to_string(roundf(this->cover_->position * 100), 0); + char pos[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(pos, roundf(this->cover_->position * 100), 0); if (!this->publish(this->get_position_state_topic(), pos)) success = false; } if (traits.get_supports_tilt()) { - std::string pos = value_accuracy_to_string(roundf(this->cover_->tilt * 100), 0); + char pos[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(pos, roundf(this->cover_->tilt * 100), 0); if (!this->publish(this->get_tilt_state_topic(), pos)) success = false; } diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index 14eb160e72..cfe6923a5f 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -82,7 +82,9 @@ bool MQTTSensorComponent::publish_state(float value) { if (mqtt::global_mqtt_client->is_publish_nan_as_none() && std::isnan(value)) return this->publish(this->get_state_topic_(), "None"); int8_t accuracy = this->sensor_->get_accuracy_decimals(); - return this->publish(this->get_state_topic_(), value_accuracy_to_string(value, accuracy)); + char buf[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(buf, value, accuracy); + return this->publish(this->get_state_topic_(), buf); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index a4c893f84b..b4cc367bc5 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -73,7 +73,8 @@ bool MQTTValveComponent::publish_state() { auto traits = this->valve_->get_traits(); bool success = true; if (traits.get_supports_position()) { - std::string pos = value_accuracy_to_string(roundf(this->valve_->position * 100), 0); + char pos[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(pos, roundf(this->valve_->position * 100), 0); if (!this->publish(this->get_position_state_topic(), pos)) success = false; } diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index dd577a4dbc..e2639a2298 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -194,7 +194,9 @@ void PrometheusHandler::sensor_row_(AsyncResponseStream *stream, sensor::Sensor stream->print(ESPHOME_F("\",unit=\"")); stream->print(obj->get_unit_of_measurement_ref().c_str()); stream->print(ESPHOME_F("\"} ")); - stream->print(value_accuracy_to_string(obj->state, obj->get_accuracy_decimals()).c_str()); + char value_buf[VALUE_ACCURACY_MAX_LEN]; + value_accuracy_to_buf(value_buf, obj->state, obj->get_accuracy_decimals()); + stream->print(value_buf); stream->print(ESPHOME_F("\n")); } else { // Invalid state @@ -954,7 +956,7 @@ void PrometheusHandler::climate_setting_row_(AsyncResponseStream *stream, climat void PrometheusHandler::climate_value_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name, std::string &category, - std::string &climate_value) { + const char *climate_value) { stream->print(ESPHOME_F("esphome_climate_value{id=\"")); stream->print(relabel_id_(obj).c_str()); add_area_label_(stream, area); @@ -965,7 +967,7 @@ void PrometheusHandler::climate_value_row_(AsyncResponseStream *stream, climate: stream->print(ESPHOME_F("\",category=\"")); stream->print(category.c_str()); stream->print(ESPHOME_F("\"} ")); - stream->print(climate_value.c_str()); + stream->print(climate_value); stream->print(ESPHOME_F("\n")); } @@ -1003,14 +1005,15 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima // Now see if traits is supported int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); + char value_buf[VALUE_ACCURACY_MAX_LEN]; // max temp std::string max_temp = "maximum_temperature"; - auto max_temp_value = value_accuracy_to_string(traits.get_visual_max_temperature(), target_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, max_temp, max_temp_value); - // max temp - std::string min_temp = "mininum_temperature"; - auto min_temp_value = value_accuracy_to_string(traits.get_visual_min_temperature(), target_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, min_temp, min_temp_value); + value_accuracy_to_buf(value_buf, traits.get_visual_max_temperature(), target_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, max_temp, value_buf); + // min temp + std::string min_temp = "minimum_temperature"; + value_accuracy_to_buf(value_buf, traits.get_visual_min_temperature(), target_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, min_temp, value_buf); // now check optional traits if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) { std::string current_temp = "current_temperature"; @@ -1018,8 +1021,8 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, true); any_failures = true; } else { - auto current_temp_value = value_accuracy_to_string(obj->current_temperature, current_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, current_temp, current_temp_value); + value_accuracy_to_buf(value_buf, obj->current_temperature, current_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, current_temp, value_buf); climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, false); } } @@ -1029,8 +1032,8 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, true); any_failures = true; } else { - auto current_humidity_value = value_accuracy_to_string(obj->current_humidity, 0); - climate_value_row_(stream, obj, area, node, friendly_name, current_humidity, current_humidity_value); + value_accuracy_to_buf(value_buf, obj->current_humidity, 0); + climate_value_row_(stream, obj, area, node, friendly_name, current_humidity, value_buf); climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, false); } } @@ -1040,23 +1043,23 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, true); any_failures = true; } else { - auto target_humidity_value = value_accuracy_to_string(obj->target_humidity, 0); - climate_value_row_(stream, obj, area, node, friendly_name, target_humidity, target_humidity_value); + value_accuracy_to_buf(value_buf, obj->target_humidity, 0); + climate_value_row_(stream, obj, area, node, friendly_name, target_humidity, value_buf); climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, false); } } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { std::string target_temp_low = "target_temperature_low"; - auto target_temp_low_value = value_accuracy_to_string(obj->target_temperature_low, target_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, target_temp_low, target_temp_low_value); + value_accuracy_to_buf(value_buf, obj->target_temperature_low, target_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, target_temp_low, value_buf); std::string target_temp_high = "target_temperature_high"; - auto target_temp_high_value = value_accuracy_to_string(obj->target_temperature_high, target_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, target_temp_high, target_temp_high_value); + value_accuracy_to_buf(value_buf, obj->target_temperature_high, target_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, target_temp_high, value_buf); } else { std::string target_temp = "target_temperature"; - auto target_temp_value = value_accuracy_to_string(obj->target_temperature, target_accuracy); - climate_value_row_(stream, obj, area, node, friendly_name, target_temp, target_temp_value); + value_accuracy_to_buf(value_buf, obj->target_temperature, target_accuracy); + climate_value_row_(stream, obj, area, node, friendly_name, target_temp, value_buf); } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { std::string climate_trait_category = "action"; diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index 24243c8c98..fc48ad67e3 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -207,7 +207,7 @@ class PrometheusHandler : public AsyncWebHandler, public Component { void climate_setting_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, std::string &friendly_name, std::string &setting, const LogString *setting_value); void climate_value_row_(AsyncResponseStream *stream, climate::Climate *obj, std::string &area, std::string &node, - std::string &friendly_name, std::string &category, std::string &climate_value); + std::string &friendly_name, std::string &category, const char *climate_value); #endif web_server_base::WebServerBase *base_; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index bf559d2bc6..396a58464f 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1027,7 +1027,8 @@ enum ParseOnOffState : uint8_t { /// Parse a string that contains either on, off or toggle. ParseOnOffState parse_on_off(const char *str, const char *on = nullptr, const char *off = nullptr); -/// Create a string from a value and an accuracy in decimals. +/// @deprecated Allocates heap memory. Use value_accuracy_to_buf() instead. Removed in 2026.7.0. +ESPDEPRECATED("Allocates heap memory. Use value_accuracy_to_buf() instead. Removed in 2026.7.0.", "2026.1.0") std::string value_accuracy_to_string(float value, int8_t accuracy_decimals); /// Maximum buffer size for value_accuracy formatting (float ~15 chars + space + UOM ~40 chars + null) From 7f0e4eaa84ada41d72af40b5bbf0564c60a945fb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 07:38:39 -1000 Subject: [PATCH 0061/2030] [nfc] Use stack-based hex formatting in pn7150/pn7160 components (#13163) --- esphome/components/nfc/automation.cpp | 6 +- .../nfc/binary_sensor/nfc_binary_sensor.cpp | 4 +- esphome/components/nfc/nfc.cpp | 11 +++ esphome/components/nfc/nfc.h | 14 ++++ esphome/components/pn532/pn532.cpp | 3 +- .../components/pn532/pn532_mifare_classic.cpp | 3 +- .../pn532/pn532_mifare_ultralight.cpp | 3 +- esphome/components/pn7150/pn7150.cpp | 63 +++++++++++------ .../pn7150/pn7150_mifare_classic.cpp | 22 +++--- .../pn7150/pn7150_mifare_ultralight.cpp | 3 +- esphome/components/pn7160/pn7160.cpp | 70 ++++++++++++------- .../pn7160/pn7160_mifare_classic.cpp | 22 +++--- .../pn7160/pn7160_mifare_ultralight.cpp | 3 +- 13 files changed, 154 insertions(+), 73 deletions(-) diff --git a/esphome/components/nfc/automation.cpp b/esphome/components/nfc/automation.cpp index ff00340df0..e2956e4c12 100644 --- a/esphome/components/nfc/automation.cpp +++ b/esphome/components/nfc/automation.cpp @@ -1,9 +1,13 @@ #include "automation.h" +#include "nfc.h" namespace esphome { namespace nfc { -void NfcOnTagTrigger::process(const std::unique_ptr &tag) { this->trigger(format_uid(tag->get_uid()), *tag); } +void NfcOnTagTrigger::process(const std::unique_ptr &tag) { + char uid_buf[FORMAT_UID_BUFFER_SIZE]; + this->trigger(std::string(format_uid_to(uid_buf, tag->get_uid())), *tag); +} } // namespace nfc } // namespace esphome diff --git a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp index bc19fa7213..b62b243cc6 100644 --- a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp +++ b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp @@ -1,4 +1,5 @@ #include "nfc_binary_sensor.h" +#include "../nfc.h" #include "../nfc_helpers.h" #include "esphome/core/log.h" @@ -24,7 +25,8 @@ void NfcTagBinarySensor::dump_config() { return; } if (!this->uid_.empty()) { - ESP_LOGCONFIG(TAG, " Tag UID: %s", format_bytes(this->uid_).c_str()); + char uid_buf[FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGCONFIG(TAG, " Tag UID: %s", format_bytes_to(uid_buf, this->uid_)); } } diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index d3a2481693..82e86b936a 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -8,9 +8,20 @@ namespace nfc { static const char *const TAG = "nfc"; +char *format_uid_to(char *buffer, const std::vector &uid) { + return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-'); +} + +char *format_bytes_to(char *buffer, const std::vector &bytes) { + return format_hex_pretty_to(buffer, FORMAT_BYTES_BUFFER_SIZE, bytes.data(), bytes.size(), ' '); +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" std::string format_uid(const std::vector &uid) { return format_hex_pretty(uid, '-', false); } std::string format_bytes(const std::vector &bytes) { return format_hex_pretty(bytes, ' ', false); } +#pragma GCC diagnostic pop uint8_t guess_tag_type(uint8_t uid_length) { if (uid_length == 4) { diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index 9879cfdb03..6568c60a85 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -53,7 +53,21 @@ static const uint8_t DEFAULT_KEY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; static const uint8_t NDEF_KEY[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; +/// Max UID size is 10 bytes, formatted as "XX-XX-XX-XX-XX-XX-XX-XX-XX-XX\0" = 30 chars +static constexpr size_t FORMAT_UID_BUFFER_SIZE = 30; +/// Format UID to buffer with '-' separator (e.g., "04-11-22-33"). Returns buffer for inline use. +char *format_uid_to(char *buffer, const std::vector &uid); + +/// Buffer size for format_bytes_to (64 bytes max = 192 chars with space separator) +static constexpr size_t FORMAT_BYTES_BUFFER_SIZE = 192; +/// Format bytes to buffer with ' ' separator (e.g., "04 11 22 33"). Returns buffer for inline use. +char *format_bytes_to(char *buffer, const std::vector &bytes); + +// Remove before 2026.6.0 +ESPDEPRECATED("Use format_uid_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") std::string format_uid(const std::vector &uid); +// Remove before 2026.6.0 +ESPDEPRECATED("Use format_bytes_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") std::string format_bytes(const std::vector &bytes); uint8_t guess_tag_type(uint8_t uid_length); diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index d5e892a576..8f0c5581d4 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -197,7 +197,8 @@ void PN532::loop() { trigger->process(tag); if (report) { - ESP_LOGD(TAG, "Found new tag '%s'", nfc::format_uid(nfcid).c_str()); + char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE]; + ESP_LOGD(TAG, "Found new tag '%s'", nfc::format_uid_to(uid_buf, nfcid)); if (tag->has_ndef_message()) { const auto &message = tag->get_ndef_message(); const auto &records = message->get_records(); diff --git a/esphome/components/pn532/pn532_mifare_classic.cpp b/esphome/components/pn532/pn532_mifare_classic.cpp index 943f8c5519..28ab22e160 100644 --- a/esphome/components/pn532/pn532_mifare_classic.cpp +++ b/esphome/components/pn532/pn532_mifare_classic.cpp @@ -77,7 +77,8 @@ bool PN532::read_mifare_classic_block_(uint8_t block_num, std::vector & } data.erase(data.begin()); - ESP_LOGVV(TAG, " Block %d: %s", block_num, nfc::format_bytes(data).c_str()); + char data_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, " Block %d: %s", block_num, nfc::format_bytes_to(data_buf, data)); return true; } diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index f823829a6c..0221ba31c5 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -71,7 +71,8 @@ bool PN532::read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes } } - ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes(data).c_str()); + char data_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes_to(data_buf, data)); return true; } diff --git a/esphome/components/pn7150/pn7150.cpp b/esphome/components/pn7150/pn7150.cpp index f6ddcb0767..e1ba3761d4 100644 --- a/esphome/components/pn7150/pn7150.cpp +++ b/esphome/components/pn7150/pn7150.cpp @@ -203,7 +203,8 @@ uint8_t PN7150::set_test_mode(const TestMode test_mode, const std::vectortag_listeners_) { listener->tag_off(*this->discovered_endpoint_[tag_index].tag); } - ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid(this->discovered_endpoint_[tag_index].tag->get_uid()).c_str()); + char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE]; + ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid_to(uid_buf, this->discovered_endpoint_[tag_index].tag->get_uid())); this->discovered_endpoint_.erase(this->discovered_endpoint_.begin() + tag_index); } } @@ -772,26 +777,33 @@ void PN7150::process_message_() { ESP_LOGV(TAG, "Unimplemented NCI Core OID received: 0x%02X", rx.get_oid()); } } else { - ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes(rx.get_message()).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes_to(buf, rx.get_message())); } break; - case nfc::NCI_PKT_MT_CTRL_RESPONSE: + case nfc::NCI_PKT_MT_CTRL_RESPONSE: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; ESP_LOGV(TAG, "Unimplemented GID: 0x%02X OID: 0x%02X Full response: %s", rx.get_gid(), rx.get_oid(), - nfc::format_bytes(rx.get_message()).c_str()); + nfc::format_bytes_to(buf, rx.get_message())); break; + } - case nfc::NCI_PKT_MT_CTRL_COMMAND: - ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes(rx.get_message()).c_str()); + case nfc::NCI_PKT_MT_CTRL_COMMAND: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes_to(buf, rx.get_message())); break; + } case nfc::NCI_PKT_MT_DATA: this->process_data_message_(rx); break; - default: - ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes(rx.get_message()).c_str()); + default: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes_to(buf, rx.get_message())); break; + } } } @@ -872,8 +884,9 @@ void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi case EP_READ: default: if (!working_endpoint.trig_called) { + char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE]; ESP_LOGI(TAG, "Read tag type %s with UID %s", working_endpoint.tag->get_tag_type().c_str(), - nfc::format_uid(working_endpoint.tag->get_uid()).c_str()); + nfc::format_uid_to(uid_buf, working_endpoint.tag->get_uid())); if (this->read_endpoint_data_(*working_endpoint.tag) != nfc::STATUS_OK) { ESP_LOGW(TAG, " Unable to read NDEF record(s)"); } else if (working_endpoint.tag->has_ndef_message()) { @@ -964,7 +977,8 @@ void PN7150::process_rf_deactivate_oid_(nfc::NciMessage &rx) { } void PN7150::process_data_message_(nfc::NciMessage &rx) { - ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes(rx.get_message()).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes_to(buf, rx.get_message())); std::vector ndef_response; this->card_emu_t4t_get_response_(rx.get_message(), ndef_response); @@ -978,7 +992,7 @@ void PN7150::process_data_message_(nfc::NciMessage &rx) { uint8_t(ndef_response_size & 0x00FF)}; tx_msg.insert(tx_msg.end(), ndef_response.begin(), ndef_response.end()); nfc::NciMessage tx(tx_msg); - ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx, NFCC_DEFAULT_TIMEOUT, false) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending reply for card emulation failed"); } @@ -1031,7 +1045,8 @@ void PN7150::card_emu_t4t_get_response_(std::vector &response, std::vec uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3]; uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4]; - ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes(ndef_message).c_str()); + char ndef_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes_to(ndef_buf, ndef_message)); if (length <= (ndef_msg_size + offset + 2)) { if (offset == 0) { @@ -1070,7 +1085,8 @@ void PN7150::card_emu_t4t_get_response_(std::vector &response, std::vec ndef_msg_written.insert(ndef_msg_written.end(), response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5, response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5 + length); - ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes(ndef_msg_written).c_str()); + char ndef_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes_to(ndef_buf, ndef_msg_written)); ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK)); } } @@ -1079,6 +1095,7 @@ void PN7150::card_emu_t4t_get_response_(std::vector &response, std::vec uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint16_t timeout, const bool expect_notification) { uint8_t retries = NFCC_MAX_COMM_FAILS; + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; while (retries) { // first, send the message we need to send @@ -1086,7 +1103,7 @@ uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint ESP_LOGE(TAG, "Error sending message"); return nfc::STATUS_FAILED; } - ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes_to(buf, tx.get_message())); // next, the NFCC should send back a response if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) { ESP_LOGW(TAG, "Error receiving message"); @@ -1098,24 +1115,24 @@ uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint break; } } - ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message())); // validate the response based on the message type that was sent (command vs. data) if (!tx.message_type_is(nfc::NCI_PKT_MT_DATA)) { // for commands, the GID and OID should match and the status should be OK if ((rx.get_gid() != tx.get_gid()) || (rx.get_oid()) != tx.get_oid()) { - ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } if (!rx.simple_status_response_is(nfc::STATUS_OK)) { - ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes_to(buf, rx.get_message())); } return rx.get_simple_status_response(); } else { // when requesting data from the endpoint, the first response is from the NFCC; we must validate this, first if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_NOTIFICATION)) || (!rx.gid_is(nfc::NCI_CORE_GID)) || (!rx.oid_is(nfc::NCI_CORE_CONN_CREDITS_OID)) || (!rx.message_length_is(3))) { - ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } @@ -1125,7 +1142,7 @@ uint8_t PN7150::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint ESP_LOGE(TAG, "Error receiving data from endpoint"); return nfc::STATUS_FAILED; } - ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message())); } return nfc::STATUS_OK; diff --git a/esphome/components/pn7150/pn7150_mifare_classic.cpp b/esphome/components/pn7150/pn7150_mifare_classic.cpp index 0443929f69..dee81b610a 100644 --- a/esphome/components/pn7150/pn7150_mifare_classic.cpp +++ b/esphome/components/pn7150/pn7150_mifare_classic.cpp @@ -70,7 +70,8 @@ uint8_t PN7150::read_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Timeout reading tag data"); return nfc::STATUS_FAILED; @@ -79,13 +80,13 @@ uint8_t PN7150::read_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending MFC_AUTHENTICATE_REQ failed"); return nfc::STATUS_FAILED; @@ -119,7 +121,7 @@ uint8_t PN7150::auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, c if ((!rx.message_type_is(nfc::NCI_PKT_MT_DATA)) || (!rx.simple_status_response_is(MFC_AUTHENTICATE_OID)) || (rx.get_message()[4] != nfc::STATUS_OK)) { ESP_LOGE(TAG, "MFC authentication failed - block 0x%02x", block_num); - ESP_LOGVV(TAG, "MFC_AUTHENTICATE_RSP: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "MFC_AUTHENTICATE_RSP: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } @@ -238,7 +240,8 @@ uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending XCHG_DATA_REQ failed"); return nfc::STATUS_FAILED; @@ -247,7 +250,7 @@ uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { ESP_LOGE(TAG, "MFC XCHG_DATA timed out waiting for XCHG_DATA_RSP during block write"); return nfc::STATUS_FAILED; @@ -256,7 +259,7 @@ uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending halt XCHG_DATA_REQ failed"); return nfc::STATUS_FAILED; diff --git a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp index b107f6f79e..ac15475bad 100644 --- a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp +++ b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp @@ -72,7 +72,8 @@ uint8_t PN7150::read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_b } } - ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes(data).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes_to(buf, data)); return nfc::STATUS_OK; } diff --git a/esphome/components/pn7160/pn7160.cpp b/esphome/components/pn7160/pn7160.cpp index 8c8028b04a..1a38dce5fd 100644 --- a/esphome/components/pn7160/pn7160.cpp +++ b/esphome/components/pn7160/pn7160.cpp @@ -215,7 +215,8 @@ uint8_t PN7160::set_test_mode(const TestMode test_mode, const std::vector features(rx.get_message().begin() + 4, rx.get_message().begin() + 8); + char feat_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; ESP_LOGD(TAG, "Hardware version: %u\n" "ROM code version: %u\n" "FLASH major version: %u\n" "FLASH minor version: %u\n" "Features: %s", - hw_version, rom_code_version, flash_major_version, flash_minor_version, nfc::format_bytes(features).c_str()); + hw_version, rom_code_version, flash_major_version, flash_minor_version, + nfc::format_bytes_to(feat_buf, features)); return rx.get_simple_status_response(); } @@ -599,7 +606,8 @@ void PN7160::erase_tag_(const uint8_t tag_index) { for (auto *listener : this->tag_listeners_) { listener->tag_off(*this->discovered_endpoint_[tag_index].tag); } - ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid(this->discovered_endpoint_[tag_index].tag->get_uid()).c_str()); + char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE]; + ESP_LOGI(TAG, "Tag %s removed", nfc::format_uid_to(uid_buf, this->discovered_endpoint_[tag_index].tag->get_uid())); this->discovered_endpoint_.erase(this->discovered_endpoint_.begin() + tag_index); } } @@ -796,26 +804,33 @@ void PN7160::process_message_() { ESP_LOGV(TAG, "Unimplemented NCI Core OID received: 0x%02X", rx.get_oid()); } } else { - ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes(rx.get_message()).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented notification: %s", nfc::format_bytes_to(buf, rx.get_message())); } break; - case nfc::NCI_PKT_MT_CTRL_RESPONSE: + case nfc::NCI_PKT_MT_CTRL_RESPONSE: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; ESP_LOGV(TAG, "Unimplemented GID: 0x%02X OID: 0x%02X Full response: %s", rx.get_gid(), rx.get_oid(), - nfc::format_bytes(rx.get_message()).c_str()); + nfc::format_bytes_to(buf, rx.get_message())); break; + } - case nfc::NCI_PKT_MT_CTRL_COMMAND: - ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes(rx.get_message()).c_str()); + case nfc::NCI_PKT_MT_CTRL_COMMAND: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented command: %s", nfc::format_bytes_to(buf, rx.get_message())); break; + } case nfc::NCI_PKT_MT_DATA: this->process_data_message_(rx); break; - default: - ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes(rx.get_message()).c_str()); + default: { + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGV(TAG, "Unimplemented message type: %s", nfc::format_bytes_to(buf, rx.get_message())); break; + } } } @@ -896,8 +911,9 @@ void PN7160::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi case EP_READ: default: if (!working_endpoint.trig_called) { + char uid_buf[nfc::FORMAT_UID_BUFFER_SIZE]; ESP_LOGI(TAG, "Read tag type %s with UID %s", working_endpoint.tag->get_tag_type().c_str(), - nfc::format_uid(working_endpoint.tag->get_uid()).c_str()); + nfc::format_uid_to(uid_buf, working_endpoint.tag->get_uid())); if (this->read_endpoint_data_(*working_endpoint.tag) != nfc::STATUS_OK) { ESP_LOGW(TAG, " Unable to read NDEF record(s)"); } else if (working_endpoint.tag->has_ndef_message()) { @@ -988,7 +1004,8 @@ void PN7160::process_rf_deactivate_oid_(nfc::NciMessage &rx) { } void PN7160::process_data_message_(nfc::NciMessage &rx) { - ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes(rx.get_message()).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Received data message: %s", nfc::format_bytes_to(buf, rx.get_message())); std::vector ndef_response; this->card_emu_t4t_get_response_(rx.get_message(), ndef_response); @@ -1002,7 +1019,7 @@ void PN7160::process_data_message_(nfc::NciMessage &rx) { uint8_t(ndef_response_size & 0x00FF)}; tx_msg.insert(tx_msg.end(), ndef_response.begin(), ndef_response.end()); nfc::NciMessage tx(tx_msg); - ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Sending data message: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx, NFCC_DEFAULT_TIMEOUT, false) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending reply for card emulation failed"); } @@ -1055,7 +1072,8 @@ void PN7160::card_emu_t4t_get_response_(std::vector &response, std::vec uint16_t offset = (response[nfc::NCI_PKT_HEADER_SIZE + 2] << 8) + response[nfc::NCI_PKT_HEADER_SIZE + 3]; uint8_t length = response[nfc::NCI_PKT_HEADER_SIZE + 4]; - ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes(ndef_message).c_str()); + char ndef_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Encoded NDEF message: %s", nfc::format_bytes_to(ndef_buf, ndef_message)); if (length <= (ndef_msg_size + offset + 2)) { if (offset == 0) { @@ -1094,7 +1112,8 @@ void PN7160::card_emu_t4t_get_response_(std::vector &response, std::vec ndef_msg_written.insert(ndef_msg_written.end(), response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5, response.begin() + nfc::NCI_PKT_HEADER_SIZE + 5 + length); - ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes(ndef_msg_written).c_str()); + char write_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGD(TAG, "Received %u-byte NDEF message: %s", length, nfc::format_bytes_to(write_buf, ndef_msg_written)); ndef_response.insert(ndef_response.end(), std::begin(CARD_EMU_T4T_OK), std::end(CARD_EMU_T4T_OK)); } } @@ -1103,6 +1122,7 @@ void PN7160::card_emu_t4t_get_response_(std::vector &response, std::vec uint8_t PN7160::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint16_t timeout, const bool expect_notification) { uint8_t retries = NFCC_MAX_COMM_FAILS; + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; while (retries) { // first, send the message we need to send @@ -1110,7 +1130,7 @@ uint8_t PN7160::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint ESP_LOGE(TAG, "Error sending message"); return nfc::STATUS_FAILED; } - ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Wrote: %s", nfc::format_bytes_to(buf, tx.get_message())); // next, the NFCC should send back a response if (this->read_nfcc(rx, timeout) != nfc::STATUS_OK) { ESP_LOGW(TAG, "Error receiving message"); @@ -1122,24 +1142,24 @@ uint8_t PN7160::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint break; } } - ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message())); // validate the response based on the message type that was sent (command vs. data) if (!tx.message_type_is(nfc::NCI_PKT_MT_DATA)) { // for commands, the GID and OID should match and the status should be OK if ((rx.get_gid() != tx.get_gid()) || (rx.get_oid()) != tx.get_oid()) { - ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Incorrect response to command: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } if (!rx.simple_status_response_is(nfc::STATUS_OK)) { - ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Error in response to command: %s", nfc::format_bytes_to(buf, rx.get_message())); } return rx.get_simple_status_response(); } else { // when requesting data from the endpoint, the first response is from the NFCC; we must validate this, first if ((!rx.message_type_is(nfc::NCI_PKT_MT_CTRL_NOTIFICATION)) || (!rx.gid_is(nfc::NCI_CORE_GID)) || (!rx.oid_is(nfc::NCI_CORE_CONN_CREDITS_OID)) || (!rx.message_length_is(3))) { - ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGE(TAG, "Incorrect response to data message: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } @@ -1149,7 +1169,7 @@ uint8_t PN7160::transceive_(nfc::NciMessage &tx, nfc::NciMessage &rx, const uint ESP_LOGE(TAG, "Error receiving data from endpoint"); return nfc::STATUS_FAILED; } - ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "Read: %s", nfc::format_bytes_to(buf, rx.get_message())); } return nfc::STATUS_OK; diff --git a/esphome/components/pn7160/pn7160_mifare_classic.cpp b/esphome/components/pn7160/pn7160_mifare_classic.cpp index fa63cc00d5..57d2042eaa 100644 --- a/esphome/components/pn7160/pn7160_mifare_classic.cpp +++ b/esphome/components/pn7160/pn7160_mifare_classic.cpp @@ -69,8 +69,9 @@ uint8_t PN7160::read_mifare_classic_tag_(nfc::NfcTag &tag) { uint8_t PN7160::read_mifare_classic_block_(uint8_t block_num, std::vector &data) { nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, {XCHG_DATA_OID, nfc::MIFARE_CMD_READ, block_num}); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; - ESP_LOGVV(TAG, "Read XCHG_DATA_REQ: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Read XCHG_DATA_REQ: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Timeout reading tag data"); return nfc::STATUS_FAILED; @@ -79,13 +80,13 @@ uint8_t PN7160::read_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending MFC_AUTHENTICATE_REQ failed"); return nfc::STATUS_FAILED; @@ -119,7 +121,7 @@ uint8_t PN7160::auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, c if ((!rx.message_type_is(nfc::NCI_PKT_MT_DATA)) || (!rx.simple_status_response_is(MFC_AUTHENTICATE_OID)) || (rx.get_message()[4] != nfc::STATUS_OK)) { ESP_LOGE(TAG, "MFC authentication failed - block 0x%02x", block_num); - ESP_LOGVV(TAG, "MFC_AUTHENTICATE_RSP: %s", nfc::format_bytes(rx.get_message()).c_str()); + ESP_LOGVV(TAG, "MFC_AUTHENTICATE_RSP: %s", nfc::format_bytes_to(buf, rx.get_message())); return nfc::STATUS_FAILED; } @@ -237,8 +239,9 @@ uint8_t PN7160::format_mifare_classic_ndef_() { uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, std::vector &write_data) { nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, {XCHG_DATA_OID, nfc::MIFARE_CMD_WRITE, block_num}); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; - ESP_LOGVV(TAG, "Write XCHG_DATA_REQ 1: %s", nfc::format_bytes(tx.get_message()).c_str()); + ESP_LOGVV(TAG, "Write XCHG_DATA_REQ 1: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending XCHG_DATA_REQ failed"); return nfc::STATUS_FAILED; @@ -247,7 +250,7 @@ uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { ESP_LOGE(TAG, "MFC XCHG_DATA timed out waiting for XCHG_DATA_RSP during block write"); return nfc::STATUS_FAILED; @@ -256,7 +259,7 @@ uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, std::vectortransceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Sending halt XCHG_DATA_REQ failed"); return nfc::STATUS_FAILED; diff --git a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp index 65daac494f..584385f113 100644 --- a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp +++ b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp @@ -72,7 +72,8 @@ uint8_t PN7160::read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_b } } - ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes(data).c_str()); + char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Data read: %s", nfc::format_bytes_to(buf, data)); return nfc::STATUS_OK; } From 7e1cda8f9fb900832217ef12ec6b522623b9e849 Mon Sep 17 00:00:00 2001 From: mikaabra Date: Mon, 12 Jan 2026 18:50:59 +0100 Subject: [PATCH 0062/2030] [esp32_can] Add listen-only mode to esp32_can component (#13084) Co-authored-by: Claude Opus 4.5 --- esphome/components/esp32_can/canbus.py | 10 ++++++++++ esphome/components/esp32_can/esp32_can.cpp | 15 ++++++++++++++- esphome/components/esp32_can/esp32_can.h | 7 +++++++ tests/components/esp32_can/common.yaml | 1 + tests/components/esp32_can/test.esp32-c6-idf.yaml | 14 +++----------- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index 0899a0dc2b..0768b35507 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -19,6 +19,7 @@ from esphome.components.esp32 import ( import esphome.config_validation as cv from esphome.const import ( CONF_ID, + CONF_MODE, CONF_RX_PIN, CONF_RX_QUEUE_LEN, CONF_TX_PIN, @@ -33,6 +34,13 @@ CONF_TX_ENQUEUE_TIMEOUT = "tx_enqueue_timeout" esp32_can_ns = cg.esphome_ns.namespace("esp32_can") esp32_can = esp32_can_ns.class_("ESP32Can", CanbusComponent) +# Mode options - consistent with MCP2515 component +CanMode = esp32_can_ns.enum("CanMode") +CAN_MODES = { + "NORMAL": CanMode.CAN_MODE_NORMAL, + "LISTENONLY": CanMode.CAN_MODE_LISTEN_ONLY, +} + # Currently the driver only supports a subset of the bit rates defined in canbus # The supported bit rates differ between ESP32 variants. # See ESP-IDF Programming Guide --> API Reference --> Two-Wire Automotive Interface (TWAI) @@ -95,6 +103,7 @@ CONFIG_SCHEMA = canbus.CANBUS_SCHEMA.extend( cv.Optional(CONF_BIT_RATE, default="125KBPS"): validate_bit_rate, cv.Required(CONF_RX_PIN): pins.internal_gpio_input_pin_number, cv.Required(CONF_TX_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_MODE, default="NORMAL"): cv.enum(CAN_MODES, upper=True), cv.Optional(CONF_RX_QUEUE_LEN): cv.uint32_t, cv.Optional(CONF_TX_QUEUE_LEN): cv.uint32_t, cv.Optional(CONF_TX_ENQUEUE_TIMEOUT): cv.positive_time_period_milliseconds, @@ -117,6 +126,7 @@ async def to_code(config): cg.add(var.set_rx(config[CONF_RX_PIN])) cg.add(var.set_tx(config[CONF_TX_PIN])) + cg.add(var.set_mode(config[CONF_MODE])) if (rx_queue_len := config.get(CONF_RX_QUEUE_LEN)) is not None: cg.add(var.set_rx_queue_len(rx_queue_len)) if (tx_queue_len := config.get(CONF_TX_QUEUE_LEN)) is not None: diff --git a/esphome/components/esp32_can/esp32_can.cpp b/esphome/components/esp32_can/esp32_can.cpp index d50964187d..f521b63430 100644 --- a/esphome/components/esp32_can/esp32_can.cpp +++ b/esphome/components/esp32_can/esp32_can.cpp @@ -75,8 +75,15 @@ bool ESP32Can::setup_internal() { return false; } + // Select TWAI mode based on configuration + twai_mode_t twai_mode = (this->mode_ == CAN_MODE_LISTEN_ONLY) ? TWAI_MODE_LISTEN_ONLY : TWAI_MODE_NORMAL; + + if (this->mode_ == CAN_MODE_LISTEN_ONLY) { + ESP_LOGI(TAG, "CAN bus configured in LISTEN_ONLY mode (passive, no ACKs)"); + } + twai_general_config_t g_config = - TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, TWAI_MODE_NORMAL); + TWAI_GENERAL_CONFIG_DEFAULT((gpio_num_t) this->tx_, (gpio_num_t) this->rx_, twai_mode); g_config.controller_id = next_twai_ctrl_num++; if (this->tx_queue_len_.has_value()) { g_config.tx_queue_len = this->tx_queue_len_.value(); @@ -111,6 +118,12 @@ bool ESP32Can::setup_internal() { } canbus::Error ESP32Can::send_message(struct canbus::CanFrame *frame) { + // In listen-only mode, we cannot transmit + if (this->mode_ == CAN_MODE_LISTEN_ONLY) { + ESP_LOGW(TAG, "Cannot send messages in LISTEN_ONLY mode"); + return canbus::ERROR_FAIL; + } + if (this->twai_handle_ == nullptr) { // not setup yet or setup failed return canbus::ERROR_FAIL; diff --git a/esphome/components/esp32_can/esp32_can.h b/esphome/components/esp32_can/esp32_can.h index dc44aceb36..c3f200271b 100644 --- a/esphome/components/esp32_can/esp32_can.h +++ b/esphome/components/esp32_can/esp32_can.h @@ -10,10 +10,16 @@ namespace esphome { namespace esp32_can { +enum CanMode : uint8_t { + CAN_MODE_NORMAL = 0, + CAN_MODE_LISTEN_ONLY = 1, +}; + class ESP32Can : public canbus::Canbus { public: void set_rx(int rx) { rx_ = rx; } void set_tx(int tx) { tx_ = tx; } + void set_mode(CanMode mode) { mode_ = mode; } void set_tx_queue_len(uint32_t tx_queue_len) { this->tx_queue_len_ = tx_queue_len; } void set_rx_queue_len(uint32_t rx_queue_len) { this->rx_queue_len_ = rx_queue_len; } void set_tx_enqueue_timeout_ms(uint32_t tx_enqueue_timeout_ms) { @@ -28,6 +34,7 @@ class ESP32Can : public canbus::Canbus { int rx_{-1}; int tx_{-1}; + CanMode mode_{CAN_MODE_NORMAL}; TickType_t tx_enqueue_timeout_ticks_{}; optional tx_queue_len_{}; optional rx_queue_len_{}; diff --git a/tests/components/esp32_can/common.yaml b/tests/components/esp32_can/common.yaml index 4349c470f3..3b9b33c048 100644 --- a/tests/components/esp32_can/common.yaml +++ b/tests/components/esp32_can/common.yaml @@ -18,6 +18,7 @@ canbus: tx_pin: ${tx_pin} can_id: 4 bit_rate: 50kbps + mode: NORMAL on_frame: - can_id: 500 then: diff --git a/tests/components/esp32_can/test.esp32-c6-idf.yaml b/tests/components/esp32_can/test.esp32-c6-idf.yaml index 6ef730c378..ac978482fc 100644 --- a/tests/components/esp32_can/test.esp32-c6-idf.yaml +++ b/tests/components/esp32_can/test.esp32-c6-idf.yaml @@ -12,17 +12,7 @@ esphome: canbus_id: esp32_internal_can can_id: 0x100 data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] - - canbus.send: - # Extended ID explicit - canbus_id: esp32_internal_can_2 - use_extended_id: true - can_id: 0x100 - data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] - - canbus.send: - # Standard ID by default - canbus_id: esp32_internal_can_2 - can_id: 0x100 - data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] + # Note: esp32_internal_can_2 uses LISTENONLY mode, so no send actions canbus: - platform: esp32_can @@ -31,6 +21,7 @@ canbus: tx_pin: GPIO7 can_id: 4 bit_rate: 50kbps + mode: NORMAL on_frame: - can_id: 500 then: @@ -62,6 +53,7 @@ canbus: tx_pin: GPIO9 can_id: 4 bit_rate: 50kbps + mode: LISTENONLY on_frame: - can_id: 500 then: From 0c3433d0568c53122048ebb849c239b89d0451f0 Mon Sep 17 00:00:00 2001 From: Jasper van der Neut - Stulen Date: Mon, 12 Jan 2026 18:57:58 +0100 Subject: [PATCH 0063/2030] [deep_sleep] Fix GPIO wakeup comment (#12815) --- esphome/components/deep_sleep/deep_sleep_esp32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/deep_sleep/deep_sleep_esp32.cpp b/esphome/components/deep_sleep/deep_sleep_esp32.cpp index 833be8e76c..ea1cd00c5f 100644 --- a/esphome/components/deep_sleep/deep_sleep_esp32.cpp +++ b/esphome/components/deep_sleep/deep_sleep_esp32.cpp @@ -26,7 +26,7 @@ namespace deep_sleep { // - ext0: Single pin wakeup using RTC GPIO (esp_sleep_enable_ext0_wakeup) // - ext1: Multiple pin wakeup (esp_sleep_enable_ext1_wakeup) // - Touch: Touch pad wakeup (esp_sleep_enable_touchpad_wakeup) -// - GPIO wakeup: GPIO wakeup for non-RTC pins (esp_deep_sleep_enable_gpio_wakeup) +// - GPIO wakeup: GPIO wakeup for RTC pins (esp_deep_sleep_enable_gpio_wakeup) static const char *const TAG = "deep_sleep"; From 61a89a97d7d2e401d2dffcdac8388c26b94c2d0a Mon Sep 17 00:00:00 2001 From: Jasper van der Neut - Stulen Date: Mon, 12 Jan 2026 19:03:13 +0100 Subject: [PATCH 0064/2030] [deep_sleep] Fix GPIO wakeup on ESP32-C3/C6 (#12803) --- .../components/deep_sleep/deep_sleep_esp32.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/esphome/components/deep_sleep/deep_sleep_esp32.cpp b/esphome/components/deep_sleep/deep_sleep_esp32.cpp index ea1cd00c5f..79c34f627a 100644 --- a/esphome/components/deep_sleep/deep_sleep_esp32.cpp +++ b/esphome/components/deep_sleep/deep_sleep_esp32.cpp @@ -127,22 +127,14 @@ void DeepSleepComponent::deep_sleep_() { defined(USE_ESP32_VARIANT_ESP32C61) if (this->wakeup_pin_ != nullptr) { const auto gpio_pin = gpio_num_t(this->wakeup_pin_->get_pin()); - if (this->wakeup_pin_->get_flags() & gpio::FLAG_PULLUP) { - gpio_sleep_set_pull_mode(gpio_pin, GPIO_PULLUP_ONLY); - } else if (this->wakeup_pin_->get_flags() & gpio::FLAG_PULLDOWN) { - gpio_sleep_set_pull_mode(gpio_pin, GPIO_PULLDOWN_ONLY); - } - gpio_sleep_set_direction(gpio_pin, GPIO_MODE_INPUT); - gpio_hold_en(gpio_pin); -#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP - // Some ESP32 variants support holding a single GPIO during deep sleep without this function - // For those variants, gpio_hold_en() is sufficient to hold the pin state during deep sleep - gpio_deep_sleep_hold_en(); -#endif + // Make sure GPIO is in input mode, not all RTC GPIO pins are input by default + gpio_set_direction(gpio_pin, GPIO_MODE_INPUT); bool level = !this->wakeup_pin_->is_inverted(); if (this->wakeup_pin_mode_ == WAKEUP_PIN_MODE_INVERT_WAKEUP && this->wakeup_pin_->digital_read()) { level = !level; } + // Internal pullup/pulldown resistors are enabled automatically, when + // ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS is set (by default it is) esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(), static_cast(level)); } From 71d532a34947c5dbf9ac385ee6a716f8fafd9bb4 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Mon, 12 Jan 2026 19:31:09 +0100 Subject: [PATCH 0065/2030] [nrf52,sdk] Add framework version support (#12489) --- esphome/components/nrf52/__init__.py | 48 ++++++++++++++++--- esphome/components/zephyr/__init__.py | 29 ++++++----- .../components/nrf52/test.nrf52-adafruit.yaml | 2 + 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index bf90a41df5..5fb8abddfc 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -8,6 +8,7 @@ from esphome import pins import esphome.codegen as cg from esphome.components.zephyr import ( copy_files as zephyr_copy_files, + zephyr_add_overlay, zephyr_add_pm_static, zephyr_add_prj_conf, zephyr_data, @@ -26,6 +27,7 @@ from esphome.const import ( CONF_FRAMEWORK, CONF_ID, CONF_RESET_PIN, + CONF_VERSION, CONF_VOLTAGE, KEY_CORE, KEY_FRAMEWORK_VERSION, @@ -59,7 +61,6 @@ def set_core_data(config: ConfigType) -> ConfigType: zephyr_set_core_data(config) CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_NRF52 CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = KEY_ZEPHYR - CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version(2, 6, 1) if config[KEY_BOOTLOADER] in BOOTLOADER_CONFIG: zephyr_add_pm_static(BOOTLOADER_CONFIG[config[KEY_BOOTLOADER]]) @@ -67,6 +68,12 @@ def set_core_data(config: ConfigType) -> ConfigType: return config +def set_framework(config: ConfigType) -> ConfigType: + version = cv.Version.parse(cv.version_number(config[CONF_FRAMEWORK][CONF_VERSION])) + CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = version + return config + + BOOTLOADERS = [ BOOTLOADER_ADAFRUIT, BOOTLOADER_ADAFRUIT_NRF52_SD132, @@ -133,8 +140,14 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean, } ), + cv.Optional(CONF_FRAMEWORK, default={CONF_VERSION: "2.6.1-7"}): cv.Schema( + { + cv.Required(CONF_VERSION): cv.string_strict, + } + ), } ), + set_framework, ) @@ -173,7 +186,7 @@ async def to_code(config: ConfigType) -> None: cg.add_platformio_option( "platform_packages", [ - "platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v2.6.1-7.zip", + f"platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v{CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}.zip", "platformio/toolchain-gccarmnoneeabi@https://github.com/tomaszduda23/toolchain-sdk-ng/archive/refs/tags/v0.17.4-0.zip", ], ) @@ -200,7 +213,17 @@ async def to_code(config: ConfigType) -> None: if dfu_config := config.get(CONF_DFU): CORE.add_job(_dfu_to_code, dfu_config) - zephyr_add_prj_conf("BOARD_ENABLE_DCDC", config[CONF_DCDC]) + framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] + if framework_ver < cv.Version(2, 9, 2): + zephyr_add_prj_conf("BOARD_ENABLE_DCDC", config[CONF_DCDC]) + else: + zephyr_add_overlay( + f""" + ®1 {{ + regulator-initial-mode = <{"NRF5X_REG_MODE_DCDC" if config[CONF_DCDC] else "NRF5X_REG_MODE_LDO"}>; + }}; + """ + ) if reg0_config := config.get(CONF_REG0): value = VOLTAGE_LEVELS.index(reg0_config[CONF_VOLTAGE]) @@ -209,8 +232,12 @@ async def to_code(config: ConfigType) -> None: cg.add_define("USE_NRF52_UICR_ERASE") # c++ support - zephyr_add_prj_conf("CPLUSPLUS", True) - zephyr_add_prj_conf("LIB_CPLUSPLUS", True) + if framework_ver < cv.Version(2, 9, 2): + zephyr_add_prj_conf("CPLUSPLUS", True) + zephyr_add_prj_conf("LIB_CPLUSPLUS", True) + else: + zephyr_add_prj_conf("CPP", True) + zephyr_add_prj_conf("REQUIRES_FULL_LIBCPP", True) # watchdog zephyr_add_prj_conf("WATCHDOG", True) zephyr_add_prj_conf("WDT_DISABLE_AT_BOOT", False) @@ -218,7 +245,16 @@ async def to_code(config: ConfigType) -> None: zephyr_add_prj_conf("UART_CONSOLE", False) zephyr_add_prj_conf("CONSOLE", False) # use NFC pins as GPIO - zephyr_add_prj_conf("NFCT_PINS_AS_GPIOS", True) + if framework_ver < cv.Version(2, 9, 2): + zephyr_add_prj_conf("NFCT_PINS_AS_GPIOS", True) + else: + zephyr_add_overlay( + """ + &uicr { + nfct-pins-as-gpios; + }; + """ + ) @coroutine_with_priority(CoroPriority.DIAGNOSTICS) diff --git a/esphome/components/zephyr/__init__.py b/esphome/components/zephyr/__init__.py index a91d976e6b..8e3ae86bbe 100644 --- a/esphome/components/zephyr/__init__.py +++ b/esphome/components/zephyr/__init__.py @@ -3,7 +3,8 @@ import textwrap from typing import TypedDict import esphome.codegen as cg -from esphome.const import CONF_BOARD +import esphome.config_validation as cv +from esphome.const import CONF_BOARD, KEY_CORE, KEY_FRAMEWORK_VERSION from esphome.core import CORE from esphome.helpers import copy_file_if_changed, write_file_if_changed @@ -150,6 +151,9 @@ def _format_prj_conf_val(value: PrjConfValueType) -> str: def zephyr_add_cdc_acm(config, id): + framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] + if CORE.is_nrf52 and framework_ver >= cv.Version(3, 2, 0): + zephyr_add_prj_conf("CONFIG_USB_DEVICE_STACK_NEXT", False) zephyr_add_prj_conf("USB_DEVICE_STACK", True) zephyr_add_prj_conf("USB_CDC_ACM", True) # prevent device to go to susspend, without this communication stop working in python @@ -159,12 +163,12 @@ def zephyr_add_cdc_acm(config, id): zephyr_add_prj_conf("USB_CDC_ACM_LOG_LEVEL_WRN", True) zephyr_add_overlay( f""" -&zephyr_udc0 {{ - cdc_acm_uart{id}: cdc_acm_uart{id} {{ - compatible = "zephyr,cdc-acm-uart"; - }}; -}}; -""" + &zephyr_udc0 {{ + cdc_acm_uart{id}: cdc_acm_uart{id} {{ + compatible = "zephyr,cdc-acm-uart"; + }}; + }}; + """ ) @@ -184,11 +188,12 @@ def copy_files(): if user: zephyr_add_overlay( f""" -/ {{ - zephyr,user {{ - {[f"{key} = {', '.join(value)};" for key, value in user.items()][0]} -}}; -}};""" + / {{ + zephyr,user {{ + {[f"{key} = {', '.join(value)};" for key, value in user.items()][0]} + }}; + }}; + """ ) want_opts = zephyr_data()[KEY_PRJ_CONF] diff --git a/tests/components/nrf52/test.nrf52-adafruit.yaml b/tests/components/nrf52/test.nrf52-adafruit.yaml index 5fa0d6e88f..0ad31993ae 100644 --- a/tests/components/nrf52/test.nrf52-adafruit.yaml +++ b/tests/components/nrf52/test.nrf52-adafruit.yaml @@ -19,3 +19,5 @@ nrf52: reg0: voltage: 2.1V uicr_erase: true + framework: + version: "2.6.1-7" From 9f9341a7005701d53f6c0cd1b863bf51b2891958 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 08:42:10 -1000 Subject: [PATCH 0066/2030] [web_server] Fix select compilation error in v1 (#13169) --- esphome/components/web_server/web_server_v1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp index c3fe6f6780..ae4bbfa557 100644 --- a/esphome/components/web_server/web_server_v1.cpp +++ b/esphome/components/web_server/web_server_v1.cpp @@ -202,7 +202,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { stream.print(""); for (auto const &option : select->traits.get_options()) { stream.print(""); } stream.print(""); From c50bf45496e8a4c956dd37a2ed78654869cecf34 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:09:54 -0500 Subject: [PATCH 0067/2030] [ltr_als_ps] Remove incorrect device_class from count sensors (#13167) Co-authored-by: Claude Opus 4.5 --- esphome/components/ltr_als_ps/sensor.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py index 27263d0bff..0dbcff1bfb 100644 --- a/esphome/components/ltr_als_ps/sensor.py +++ b/esphome/components/ltr_als_ps/sensor.py @@ -16,7 +16,6 @@ from esphome.const import ( CONF_REPEAT, CONF_TRIGGER_ID, CONF_TYPE, - DEVICE_CLASS_DISTANCE, DEVICE_CLASS_ILLUMINANCE, ICON_BRIGHTNESS_5, ICON_BRIGHTNESS_6, @@ -169,7 +168,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_5, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -179,7 +177,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_7, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -189,7 +186,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_PROXIMITY, accuracy_decimals=0, - device_class=DEVICE_CLASS_DISTANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -198,7 +194,6 @@ CONFIG_SCHEMA = cv.All( sensor.sensor_schema( icon=ICON_GAIN, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, From f9ffd134df87dddbb411623bfafbf39348f13b4b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:10:15 -0500 Subject: [PATCH 0068/2030] [packet_transport] Fix packet size check to account for round4 padding (#13165) Co-authored-by: Claude Opus 4.5 --- esphome/components/packet_transport/packet_transport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index 4a53ab110b..cefe9a604e 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -274,7 +274,7 @@ void PacketTransport::flush_() { void PacketTransport::add_binary_data_(uint8_t key, const char *id, bool data) { auto len = 1 + 1 + 1 + strlen(id); - if (len + this->header_.size() + this->data_.size() > this->get_max_packet_size()) { + if (round4(this->header_.size()) + round4(this->data_.size() + len) > this->get_max_packet_size()) { this->flush_(); this->init_data_(); } @@ -289,7 +289,7 @@ void PacketTransport::add_data_(uint8_t key, const char *id, float data) { void PacketTransport::add_data_(uint8_t key, const char *id, uint32_t data) { auto len = 4 + 1 + 1 + strlen(id); - if (len + this->header_.size() + this->data_.size() > this->get_max_packet_size()) { + if (round4(this->header_.size()) + round4(this->data_.size() + len) > this->get_max_packet_size()) { this->flush_(); this->init_data_(); } From 81e639a6bad5d92e3789ac1f4261953317ee5a4a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 09:35:49 -1000 Subject: [PATCH 0069/2030] [core] Migrate callers and soft deprecate get_mac_address()/get_mac_address_pretty() (#13157) --- esphome/components/debug/debug_zephyr.cpp | 10 ++++++---- esphome/components/mqtt/mqtt_client.cpp | 9 ++++++--- esphome/components/mqtt/mqtt_component.cpp | 11 +++++++++-- esphome/core/helpers.h | 4 ++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index 85880595b6..3f9af03b2b 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -322,6 +322,8 @@ size_t DebugComponent::get_device_info_(std::span return "Unspecified"; }; + char mac_pretty[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + get_mac_address_pretty_into_buffer(mac_pretty); ESP_LOGD(TAG, "Code page size: %u, code size: %u, device id: 0x%08x%08x\n" "Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n" @@ -330,10 +332,10 @@ size_t DebugComponent::get_device_info_(std::span "RAM: %ukB, Flash: %ukB, production test: %sdone", NRF_FICR->CODEPAGESIZE, NRF_FICR->CODESIZE, NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], NRF_FICR->ER[0], NRF_FICR->ER[1], NRF_FICR->ER[2], NRF_FICR->ER[3], NRF_FICR->IR[0], NRF_FICR->IR[1], NRF_FICR->IR[2], - NRF_FICR->IR[3], (NRF_FICR->DEVICEADDRTYPE & 0x1 ? "Random" : "Public"), get_mac_address_pretty().c_str(), - NRF_FICR->INFO.PART, NRF_FICR->INFO.VARIANT >> 24 & 0xFF, NRF_FICR->INFO.VARIANT >> 16 & 0xFF, - NRF_FICR->INFO.VARIANT >> 8 & 0xFF, NRF_FICR->INFO.VARIANT & 0xFF, package(NRF_FICR->INFO.PACKAGE), - NRF_FICR->INFO.RAM, NRF_FICR->INFO.FLASH, (NRF_FICR->PRODTEST[0] == 0xBB42319F ? "" : "not ")); + NRF_FICR->IR[3], (NRF_FICR->DEVICEADDRTYPE & 0x1 ? "Random" : "Public"), mac_pretty, NRF_FICR->INFO.PART, + NRF_FICR->INFO.VARIANT >> 24 & 0xFF, NRF_FICR->INFO.VARIANT >> 16 & 0xFF, NRF_FICR->INFO.VARIANT >> 8 & 0xFF, + NRF_FICR->INFO.VARIANT & 0xFF, package(NRF_FICR->INFO.PACKAGE), NRF_FICR->INFO.RAM, NRF_FICR->INFO.FLASH, + (NRF_FICR->PRODTEST[0] == 0xBB42319F ? "" : "not ")); bool n_reset_enabled = NRF_UICR->PSELRESET[0] == NRF_UICR->PSELRESET[1] && (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) == UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos; diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 652f55734b..0ab5b238b5 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -28,8 +28,9 @@ static const char *const TAG = "mqtt"; MQTTClientComponent::MQTTClientComponent() { global_mqtt_client = this; - const std::string mac_addr = get_mac_address(); - this->credentials_.client_id = make_name_with_suffix(App.get_name(), '-', mac_addr.c_str(), mac_addr.size()); + char mac_addr[MAC_ADDRESS_BUFFER_SIZE]; + get_mac_address_into_buffer(mac_addr); + this->credentials_.client_id = make_name_with_suffix(App.get_name(), '-', mac_addr, MAC_ADDRESS_BUFFER_SIZE - 1); } // Connection @@ -102,7 +103,9 @@ void MQTTClientComponent::send_device_info_() { root[ESPHOME_F("port")] = api::global_api_server->get_port(); #endif root[ESPHOME_F("version")] = ESPHOME_VERSION; - root[ESPHOME_F("mac")] = get_mac_address(); + char mac_buf[MAC_ADDRESS_BUFFER_SIZE]; + get_mac_address_into_buffer(mac_buf); + root[ESPHOME_F("mac")] = mac_buf; #ifdef USE_ESP8266 root[ESPHOME_F("platform")] = ESPHOME_F("ESP8266"); diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index d838d1789f..40eb15acdd 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -187,7 +187,13 @@ bool MQTTComponent::send_discovery_() { char friendly_name_hash[9]; sprintf(friendly_name_hash, "%08" PRIx32, fnv1_hash(this->friendly_name_())); friendly_name_hash[8] = 0; // ensure the hash-string ends with null - root[MQTT_UNIQUE_ID] = get_mac_address() + "-" + this->component_type() + "-" + friendly_name_hash; + // Format: mac-component_type-hash (e.g. "aabbccddeeff-sensor-12345678") + // MAC (12) + "-" (1) + domain (max 20) + "-" (1) + hash (8) + null (1) = 43 + char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11]; + char mac_buf[MAC_ADDRESS_BUFFER_SIZE]; + get_mac_address_into_buffer(mac_buf); + snprintf(unique_id, sizeof(unique_id), "%s-%s-%s", mac_buf, this->component_type(), friendly_name_hash); + root[MQTT_UNIQUE_ID] = unique_id; } else { // default to almost-unique ID. It's a hack but the only way to get that // gorgeous device registry view. @@ -203,7 +209,8 @@ bool MQTTComponent::send_discovery_() { std::string node_area = App.get_area(); JsonObject device_info = root[MQTT_DEVICE].to(); - const auto mac = get_mac_address(); + char mac[MAC_ADDRESS_BUFFER_SIZE]; + get_mac_address_into_buffer(mac); device_info[MQTT_DEVICE_IDENTIFIERS] = mac; device_info[MQTT_DEVICE_NAME] = node_friendly_name; #ifdef ESPHOME_PROJECT_NAME diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 396a58464f..8847586f0a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1306,9 +1306,13 @@ class HighFrequencyLoopRequester { void get_mac_address_raw(uint8_t *mac); // NOLINT(readability-non-const-parameter) /// Get the device MAC address as a string, in lowercase hex notation. +/// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. +/// Use get_mac_address_into_buffer() instead. std::string get_mac_address(); /// Get the device MAC address as a string, in colon-separated uppercase hex notation. +/// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. +/// Use get_mac_address_pretty_into_buffer() instead. std::string get_mac_address_pretty(); /// Get the device MAC address into the given buffer, in lowercase hex notation. From 655e2b43cbc7c34f1ed2307d1b0e4cfcee8c7ae7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 11:27:42 -1000 Subject: [PATCH 0070/2030] [infrared] Use set_data() for vector timings in control() (#13171) --- esphome/components/infrared/infrared.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 384ff431a5..5f8d63926a 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -88,27 +88,15 @@ void Infrared::control(const InfraredCall &call) { // Set timings based on format if (call.is_packed()) { // Zero-copy from packed protobuf data - ESP_LOGD(TAG, "Transmitting raw timings: timing_count=%u, repeat_count=%u", call.get_packed_count(), - call.get_repeat_count()); transmit_data->set_data_from_packed_sint32(call.get_packed_data(), call.get_packed_length(), call.get_packed_count()); + ESP_LOGD(TAG, "Transmitting packed raw timings: count=%u, repeat=%u", call.get_packed_count(), + call.get_repeat_count()); } else { // From vector (lambdas/automations) - const auto &timings = call.get_raw_timings(); - if (timings.empty()) { - ESP_LOGE(TAG, "Raw timings array is empty"); - return; - } - ESP_LOGD(TAG, "Transmitting raw timings: timing_count=%zu, repeat_count=%u", timings.size(), + transmit_data->set_data(call.get_raw_timings()); + ESP_LOGD(TAG, "Transmitting raw timings: count=%zu, repeat=%u", call.get_raw_timings().size(), call.get_repeat_count()); - // Timings format: positive values = mark (LED on), negative values = space (LED off) - for (const auto &timing : timings) { - if (timing > 0) { - transmit_data->mark(static_cast(timing)); - } else { - transmit_data->space(static_cast(-timing)); - } - } } // Set repeat count From 889886909be4858cf58dacd5ee46995fb02540a1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 12:48:54 -1000 Subject: [PATCH 0071/2030] [core] Soft deprecate heap-allocating string helpers to prevent fragmentation patterns (#13156) --- .ai/instructions.md | 25 ++++++++++++++--------- esphome/core/helpers.h | 40 ++++++++++++++++++++++++++++++++++-- script/ci-custom.py | 46 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 12 deletions(-) diff --git a/.ai/instructions.md b/.ai/instructions.md index 994d517f75..3c24177827 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -293,6 +293,12 @@ This document provides essential context for AI models interacting with this pro * **Configuration Design:** Aim for simplicity with sensible defaults, while allowing for advanced customization. * **Embedded Systems Optimization:** ESPHome targets resource-constrained microcontrollers. Be mindful of flash size and RAM usage. + **Why Heap Allocation Matters:** + + ESP devices run for months with small heaps shared between Wi-Fi, BLE, LWIP, and application code. Over time, repeated allocations of different sizes fragment the heap. Failures happen when the largest contiguous block shrinks, even if total free heap is still large. We have seen field crashes caused by this. + + **Heap allocation after `setup()` should be avoided unless absolutely unavoidable.** Every allocation/deallocation cycle contributes to fragmentation. ESPHome treats runtime heap allocation as a long-term reliability bug, not a performance issue. Helpers that hide allocation (`std::string`, `std::to_string`, string-returning helpers) are being deprecated and replaced with buffer and view based APIs. + **STL Container Guidelines:** ESPHome runs on embedded systems with limited resources. Choose containers carefully: @@ -322,15 +328,15 @@ This document provides essential context for AI models interacting with this pro std::array buffer; ``` - 2. **Compile-time-known fixed sizes with vector-like API:** Use `StaticVector` from `esphome/core/helpers.h` for fixed-size stack allocation with `push_back()` interface. + 2. **Compile-time-known fixed sizes with vector-like API:** Use `StaticVector` from `esphome/core/helpers.h` for compile-time fixed size with `push_back()` interface (no dynamic allocation). ```cpp // Bad - generates STL realloc code (_M_realloc_insert) std::vector services; services.reserve(5); // Still includes reallocation machinery - // Good - compile-time fixed size, stack allocated, no reallocation machinery - StaticVector services; // Allocates all MAX_SERVICES on stack - services.push_back(record1); // Tracks count but all slots allocated + // Good - compile-time fixed size, no dynamic allocation + StaticVector services; + services.push_back(record1); ``` Use `cg.add_define("MAX_SERVICES", count)` to set the size from Python configuration. Like `std::array` but with vector-like API (`push_back()`, `size()`) and no STL reallocation code. @@ -372,22 +378,21 @@ This document provides essential context for AI models interacting with this pro ``` Linear search on small datasets (1-16 elements) is often faster than hashing/tree overhead, but this depends on lookup frequency and access patterns. For frequent lookups in hot code paths, the O(1) vs O(n) complexity difference may still matter even for small datasets. `std::vector` with simple structs is usually fine—it's the heavy containers (`map`, `set`, `unordered_map`) that should be avoided for small datasets unless profiling shows otherwise. - 5. **Detection:** Look for these patterns in compiler output: + 5. **Avoid `std::deque`:** It allocates in 512-byte blocks regardless of element size, guaranteeing at least 512 bytes of RAM usage immediately. This is a major source of crashes on memory-constrained devices. + + 6. **Detection:** Look for these patterns in compiler output: - Large code sections with STL symbols (vector, map, set) - `alloc`, `realloc`, `dealloc` in symbol names - `_M_realloc_insert`, `_M_default_append` (vector reallocation) - Red-black tree code (`rb_tree`, `_Rb_tree`) - Hash table infrastructure (`unordered_map`, `hash`) - **When to optimize:** + **Prioritize optimization effort for:** - Core components (API, network, logger) - Widely-used components (mdns, wifi, ble) - Components causing flash size complaints - **When not to optimize:** - - Single-use niche components - - Code where readability matters more than bytes - - Already using appropriate containers + Note: Avoiding heap allocation after `setup()` is always required regardless of component type. The prioritization above is about the effort spent on container optimization (e.g., migrating from `std::vector` to `StaticVector`). * **State Management:** Use `CORE.data` for component state that needs to persist during configuration generation. Avoid module-level mutable globals. diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 8847586f0a..2e9c0e6b13 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -520,6 +520,7 @@ bool str_startswith(const std::string &str, const std::string &start); bool str_endswith(const std::string &str, const std::string &end); /// Truncate a string to a specific length. +/// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. std::string str_truncate(const std::string &str, size_t length); /// Extract the part of the string until either the first occurrence of the specified character, or the end @@ -531,11 +532,13 @@ std::string str_until(const std::string &str, char ch); /// Convert the string to lower case. std::string str_lower_case(const std::string &str); /// Convert the string to upper case. +/// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. std::string str_upper_case(const std::string &str); /// Convert a single char to snake_case: lowercase and space to underscore. constexpr char to_snake_case_char(char c) { return (c == ' ') ? '_' : (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; } /// Convert the string to snake case (lowercase with underscores). +/// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. std::string str_snake_case(const std::string &str); /// Sanitize a single char: keep alphanumerics, dashes, underscores; replace others with underscore. @@ -758,6 +761,16 @@ inline char *format_hex_to(char (&buffer)[N], T val) { return format_hex_to(buffer, reinterpret_cast(&val), sizeof(T)); } +/// Format std::vector as lowercase hex to buffer. +template inline char *format_hex_to(char (&buffer)[N], const std::vector &data) { + return format_hex_to(buffer, data.data(), data.size()); +} + +/// Format std::array as lowercase hex to buffer. +template inline char *format_hex_to(char (&buffer)[N], const std::array &data) { + return format_hex_to(buffer, data.data(), data.size()); +} + /// Calculate buffer size needed for format_hex_to: "XXXXXXXX...\0" = bytes * 2 + 1 constexpr size_t format_hex_size(size_t byte_count) { return byte_count * 2 + 1; } @@ -807,6 +820,18 @@ inline char *format_hex_pretty_to(char (&buffer)[N], const uint8_t *data, size_t return format_hex_pretty_to(buffer, N, data, length, separator); } +/// Format std::vector as uppercase hex with separator to buffer. +template +inline char *format_hex_pretty_to(char (&buffer)[N], const std::vector &data, char separator = ':') { + return format_hex_pretty_to(buffer, data.data(), data.size(), separator); +} + +/// Format std::array as uppercase hex with separator to buffer. +template +inline char *format_hex_pretty_to(char (&buffer)[N], const std::array &data, char separator = ':') { + return format_hex_pretty_to(buffer, data.data(), data.size(), separator); +} + /// Calculate buffer size needed for format_hex_pretty_to with uint16_t data: "XXXX:XXXX:...:XXXX\0" constexpr size_t format_hex_pretty_uint16_size(size_t count) { return count * 5; } @@ -840,8 +865,8 @@ static constexpr size_t MAC_ADDRESS_PRETTY_BUFFER_SIZE = format_hex_pretty_size( static constexpr size_t MAC_ADDRESS_BUFFER_SIZE = MAC_ADDRESS_SIZE * 2 + 1; /// Format MAC address as XX:XX:XX:XX:XX:XX (uppercase, colon separators) -inline void format_mac_addr_upper(const uint8_t *mac, char *output) { - format_hex_pretty_to(output, MAC_ADDRESS_PRETTY_BUFFER_SIZE, mac, MAC_ADDRESS_SIZE, ':'); +inline char *format_mac_addr_upper(const uint8_t *mac, char *output) { + return format_hex_pretty_to(output, MAC_ADDRESS_PRETTY_BUFFER_SIZE, mac, MAC_ADDRESS_SIZE, ':'); } /// Format MAC address as xxxxxxxxxxxxxx (lowercase, no separators) @@ -850,16 +875,27 @@ inline void format_mac_addr_lower_no_sep(const uint8_t *mac, char *output) { } /// Format the six-byte array \p mac into a MAC address. +/// @warning Allocates heap memory. Use format_mac_addr_upper() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. std::string format_mac_address_pretty(const uint8_t mac[6]); /// Format the byte array \p data of length \p len in lowercased hex. +/// @warning Allocates heap memory. Use format_hex_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. std::string format_hex(const uint8_t *data, size_t length); /// Format the vector \p data in lowercased hex. +/// @warning Allocates heap memory. Use format_hex_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. std::string format_hex(const std::vector &data); /// Format an unsigned integer in lowercased hex, starting with the most significant byte. +/// @warning Allocates heap memory. Use format_hex_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. template::value, int> = 0> std::string format_hex(T val) { val = convert_big_endian(val); return format_hex(reinterpret_cast(&val), sizeof(T)); } +/// Format the std::array \p data in lowercased hex. +/// @warning Allocates heap memory. Use format_hex_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. template std::string format_hex(const std::array &data) { return format_hex(data.data(), data.size()); } diff --git a/script/ci-custom.py b/script/ci-custom.py index 77d2ab287d..1e2d07885e 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -679,6 +679,52 @@ def lint_trailing_whitespace(fname, match): return "Trailing whitespace detected" +# Heap-allocating helpers that cause fragmentation on long-running embedded devices. +# These return std::string and should be replaced with stack-based alternatives. +HEAP_ALLOCATING_HELPERS = { + "format_hex": "format_hex_to() with a stack buffer", + "format_mac_address_pretty": "format_mac_addr_upper() with a stack buffer", + "get_mac_address": "get_mac_address_into_buffer() with a stack buffer", + "get_mac_address_pretty": "get_mac_address_pretty_into_buffer() with a stack buffer", + "str_truncate": "removal (function is unused)", + "str_upper_case": "removal (function is unused)", + "str_snake_case": "removal (function is unused)", +} + + +@lint_re_check( + # Use negative lookahead to exclude _to/_into_buffer variants + # format_hex(?!_) ensures we don't match format_hex_to, format_hex_pretty_to, etc. + # get_mac_address(?!_) ensures we don't match get_mac_address_into_buffer, etc. + r"[^\w](" + r"format_hex(?!_)|" + r"format_mac_address_pretty|" + r"get_mac_address_pretty(?!_)|" + r"get_mac_address(?!_)|" + r"str_truncate|" + r"str_upper_case|" + r"str_snake_case" + r")\s*\(", + include=cpp_include, + exclude=[ + # The definitions themselves + "esphome/core/helpers.h", + "esphome/core/helpers.cpp", + ], +) +def lint_no_heap_allocating_helpers(fname, match): + func = match.group(1) + replacement = HEAP_ALLOCATING_HELPERS.get(func, "a stack-based alternative") + return ( + f"{highlight(func + '()')} allocates heap memory. On long-running embedded devices, " + f"repeated heap allocations fragment memory over time. Even infrequent allocations " + f"become time bombs - the heap eventually cannot satisfy requests even with free " + f"memory available.\n" + f"Please use {replacement} instead.\n" + f"(If strictly necessary, add `// NOLINT` to the end of the line)" + ) + + @lint_content_find_check( "ESP_LOG", include=["*.h", "*.tcc"], From 54fc10714d72c835bd16ec9f0c638614cbe9bbe8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 18:06:41 -0500 Subject: [PATCH 0072/2030] [remote_transmitter] Fix ESP8266 timing by using busy loop (#13172) Co-authored-by: Claude --- .../components/remote_transmitter/remote_transmitter.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/esphome/components/remote_transmitter/remote_transmitter.cpp b/esphome/components/remote_transmitter/remote_transmitter.cpp index 576143bcbc..f20789fb9f 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter.cpp @@ -40,13 +40,10 @@ void RemoteTransmitterComponent::await_target_time_() { if (this->target_time_ == 0) { this->target_time_ = current_time; } else if ((int32_t) (this->target_time_ - current_time) > 0) { -#if defined(USE_LIBRETINY) || defined(USE_RP2040) - // busy loop is required for libretiny and rp2040 as interrupts are disabled + // busy loop is required as interrupts are disabled and delayMicroseconds() + // may not work correctly in interrupt-disabled contexts on all platforms while ((int32_t) (this->target_time_ - micros()) > 0) ; -#else - delayMicroseconds(this->target_time_ - current_time); -#endif } } From 297f05d60015cd524efba118dfcf8b32aa617e5d Mon Sep 17 00:00:00 2001 From: lullius Date: Tue, 13 Jan 2026 00:08:33 +0100 Subject: [PATCH 0073/2030] [tuya] add color_type_lowercase option (#13101) Co-authored-by: lullius <> --- esphome/components/tuya/light/__init__.py | 3 +++ esphome/components/tuya/light/tuya_light.cpp | 11 +++++++---- esphome/components/tuya/light/tuya_light.h | 8 +++----- tests/components/tuya/common.yaml | 3 +++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/esphome/components/tuya/light/__init__.py b/esphome/components/tuya/light/__init__.py index 4d2ccba8b1..bf2d3daf98 100644 --- a/esphome/components/tuya/light/__init__.py +++ b/esphome/components/tuya/light/__init__.py @@ -26,6 +26,7 @@ CONF_RGB_DATAPOINT = "rgb_datapoint" CONF_HSV_DATAPOINT = "hsv_datapoint" CONF_COLOR_DATAPOINT = "color_datapoint" CONF_COLOR_TYPE = "color_type" +CONF_COLOR_TYPE_LOWERCASE = "color_type_lowercase" TuyaColorType = tuya_ns.enum("TuyaColorType") @@ -47,6 +48,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, cv.Inclusive(CONF_COLOR_DATAPOINT, "color"): cv.uint8_t, cv.Inclusive(CONF_COLOR_TYPE, "color"): cv.enum(COLOR_TYPES, upper=True), + cv.Optional(CONF_COLOR_TYPE_LOWERCASE, default=False): cv.boolean, cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean, cv.Inclusive( CONF_COLOR_TEMPERATURE_DATAPOINT, "color_temperature" @@ -91,6 +93,7 @@ async def to_code(config): if CONF_COLOR_DATAPOINT in config: cg.add(var.set_color_id(config[CONF_COLOR_DATAPOINT])) cg.add(var.set_color_type(config[CONF_COLOR_TYPE])) + cg.add(var.set_color_type_lowercase(config[CONF_COLOR_TYPE_LOWERCASE])) if CONF_COLOR_TEMPERATURE_DATAPOINT in config: cg.add(var.set_color_temperature_id(config[CONF_COLOR_TEMPERATURE_DATAPOINT])) cg.add(var.set_color_temperature_invert(config[CONF_COLOR_TEMPERATURE_INVERT])) diff --git a/esphome/components/tuya/light/tuya_light.cpp b/esphome/components/tuya/light/tuya_light.cpp index 815a089d9f..c487f9f50b 100644 --- a/esphome/components/tuya/light/tuya_light.cpp +++ b/esphome/components/tuya/light/tuya_light.cpp @@ -190,7 +190,8 @@ void TuyaLight::write_state(light::LightState *state) { switch (*this->color_type_) { case TuyaColorType::RGB: { char buffer[7]; - sprintf(buffer, "%02X%02X%02X", int(red * 255), int(green * 255), int(blue * 255)); + const char *format_str = this->color_type_lowercase_ ? "%02x%02x%02x" : "%02X%02X%02X"; + sprintf(buffer, format_str, int(red * 255), int(green * 255), int(blue * 255)); color_value = buffer; break; } @@ -199,7 +200,8 @@ void TuyaLight::write_state(light::LightState *state) { float saturation, value; rgb_to_hsv(red, green, blue, hue, saturation, value); char buffer[13]; - sprintf(buffer, "%04X%04X%04X", hue, int(saturation * 1000), int(value * 1000)); + const char *format_str = this->color_type_lowercase_ ? "%04x%04x%04x" : "%04X%04X%04X"; + sprintf(buffer, format_str, hue, int(saturation * 1000), int(value * 1000)); color_value = buffer; break; } @@ -208,8 +210,9 @@ void TuyaLight::write_state(light::LightState *state) { float saturation, value; rgb_to_hsv(red, green, blue, hue, saturation, value); char buffer[15]; - sprintf(buffer, "%02X%02X%02X%04X%02X%02X", int(red * 255), int(green * 255), int(blue * 255), hue, - int(saturation * 255), int(value * 255)); + const char *format_str = this->color_type_lowercase_ ? "%02x%02x%02x%04x%02x%02x" : "%02X%02X%02X%04X%02X%02X"; + sprintf(buffer, format_str, int(red * 255), int(green * 255), int(blue * 255), hue, int(saturation * 255), + int(value * 255)); color_value = buffer; break; } diff --git a/esphome/components/tuya/light/tuya_light.h b/esphome/components/tuya/light/tuya_light.h index bd9920f18f..ded94f390a 100644 --- a/esphome/components/tuya/light/tuya_light.h +++ b/esphome/components/tuya/light/tuya_light.h @@ -7,11 +7,7 @@ namespace esphome { namespace tuya { -enum TuyaColorType { - RGB, - HSV, - RGBHSV, -}; +enum TuyaColorType { RGB, HSV, RGBHSV }; class TuyaLight : public Component, public light::LightOutput { public: @@ -28,6 +24,7 @@ class TuyaLight : public Component, public light::LightOutput { void set_color_temperature_invert(bool color_temperature_invert) { this->color_temperature_invert_ = color_temperature_invert; } + void set_color_type_lowercase(bool color_type_lowercase) { this->color_type_lowercase_ = color_type_lowercase; } void set_tuya_parent(Tuya *parent) { this->parent_ = parent; } void set_min_value(uint32_t min_value) { min_value_ = min_value; } void set_max_value(uint32_t max_value) { max_value_ = max_value; } @@ -63,6 +60,7 @@ class TuyaLight : public Component, public light::LightOutput { float cold_white_temperature_; float warm_white_temperature_; bool color_temperature_invert_{false}; + bool color_type_lowercase_{false}; bool color_interlock_{false}; light::LightState *state_{nullptr}; }; diff --git a/tests/components/tuya/common.yaml b/tests/components/tuya/common.yaml index e177b7d056..9986d398f1 100644 --- a/tests/components/tuya/common.yaml +++ b/tests/components/tuya/common.yaml @@ -38,11 +38,14 @@ light: dimmer_datapoint: 2 min_value_datapoint: 3 color_temperature_datapoint: 4 + color_datapoint: 5 min_value: 1 max_value: 100 cold_white_color_temperature: 153 mireds warm_white_color_temperature: 500 mireds gamma_correct: 1 + color_type: RGB + color_type_lowercase: true number: - platform: tuya From 5890cdf69a70eaa0a9f9e2e2374da34940caf44d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 16:31:51 -1000 Subject: [PATCH 0074/2030] Bump github/codeql-action from 4.31.9 to 4.31.10 (#13173) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e63c3075dd..399fb13aa5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9 + uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: category: "/language:${{matrix.language}}" From e9469cbe483901ba446744eb78d037d1840c3a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= Date: Tue, 13 Jan 2026 04:40:27 +0100 Subject: [PATCH 0075/2030] [mqtt] templatable state and command topics (#12441) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- esphome/components/mqtt/__init__.py | 8 +++- esphome/components/mqtt/mqtt_component.cpp | 20 +++------- esphome/components/mqtt/mqtt_component.h | 19 +++++----- esphome/config_validation.py | 8 +++- esphome/core/automation.h | 44 ++++++++++++++++++---- tests/components/mqtt/common.yaml | 3 +- 6 files changed, 66 insertions(+), 36 deletions(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index d57cedd144..f7518771d7 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -572,9 +572,13 @@ async def register_mqtt_component(var, config): if not config.get(CONF_DISCOVERY, True): cg.add(var.disable_discovery()) if CONF_STATE_TOPIC in config: - cg.add(var.set_custom_state_topic(config[CONF_STATE_TOPIC])) + state_topic = await cg.templatable(config[CONF_STATE_TOPIC], [], cg.std_string) + cg.add(var.set_custom_state_topic(state_topic)) if CONF_COMMAND_TOPIC in config: - cg.add(var.set_custom_command_topic(config[CONF_COMMAND_TOPIC])) + command_topic = await cg.templatable( + config[CONF_COMMAND_TOPIC], [], cg.std_string + ) + cg.add(var.set_custom_command_topic(command_topic)) if CONF_COMMAND_RETAIN in config: cg.add(var.set_command_retain(config[CONF_COMMAND_RETAIN])) if CONF_AVAILABILITY in config: diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 40eb15acdd..13f496c6a7 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -94,14 +94,14 @@ std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) con } std::string MQTTComponent::get_state_topic_() const { - if (this->has_custom_state_topic_) - return this->custom_state_topic_.str(); + if (this->custom_state_topic_.has_value()) + return this->custom_state_topic_.value(); return this->get_default_topic_for_("state"); } std::string MQTTComponent::get_command_topic_() const { - if (this->has_custom_command_topic_) - return this->custom_command_topic_.str(); + if (this->custom_command_topic_.has_value()) + return this->custom_command_topic_.value(); return this->get_default_topic_for_("command"); } @@ -273,14 +273,6 @@ MQTTComponent::MQTTComponent() = default; float MQTTComponent::get_setup_priority() const { return setup_priority::AFTER_CONNECTION; } void MQTTComponent::disable_discovery() { this->discovery_enabled_ = false; } -void MQTTComponent::set_custom_state_topic(const char *custom_state_topic) { - this->custom_state_topic_ = StringRef(custom_state_topic); - this->has_custom_state_topic_ = true; -} -void MQTTComponent::set_custom_command_topic(const char *custom_command_topic) { - this->custom_command_topic_ = StringRef(custom_command_topic); - this->has_custom_command_topic_ = true; -} void MQTTComponent::set_command_retain(bool command_retain) { this->command_retain_ = command_retain; } void MQTTComponent::set_availability(std::string topic, std::string payload_available, @@ -349,13 +341,13 @@ StringRef MQTTComponent::get_default_object_id_to_(std::spanget_entity()->get_icon_ref(); } bool MQTTComponent::is_disabled_by_default_() const { return this->get_entity()->is_disabled_by_default(); } bool MQTTComponent::is_internal() { - if (this->has_custom_state_topic_) { + if (this->custom_state_topic_.has_value()) { // If the custom state_topic is null, return true as it is internal and should not publish // else, return false, as it is explicitly set to a topic, so it is not internal and should publish return this->get_state_topic_().empty(); } - if (this->has_custom_command_topic_) { + if (this->custom_command_topic_.has_value()) { // If the custom command_topic is null, return true as it is internal and should not publish // else, return false, as it is explicitly set to a topic, so it is not internal and should publish return this->get_command_topic_().empty(); diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index e0b751f05f..11dfd093f3 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -6,6 +6,7 @@ #include +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -109,10 +110,13 @@ class MQTTComponent : public Component { /// Override this method to return the component type (e.g. "light", "sensor", ...) virtual const char *component_type() const = 0; - /// Set a custom state topic. Set to "" for default behavior. - void set_custom_state_topic(const char *custom_state_topic); - /// Set a custom command topic. Set to "" for default behavior. - void set_custom_command_topic(const char *custom_command_topic); + /// Set a custom state topic. Do not set for default behavior. + template void set_custom_state_topic(T &&custom_state_topic) { + this->custom_state_topic_ = std::forward(custom_state_topic); + } + template void set_custom_command_topic(T &&custom_command_topic) { + this->custom_command_topic_ = std::forward(custom_command_topic); + } /// Set whether command message should be retained. void set_command_retain(bool command_retain); @@ -203,14 +207,11 @@ class MQTTComponent : public Component { /// Get the object ID for this MQTT component, writing to the provided buffer. StringRef get_default_object_id_to_(std::span buf) const; - StringRef custom_state_topic_{}; - StringRef custom_command_topic_{}; + TemplatableValue custom_state_topic_{}; + TemplatableValue custom_command_topic_{}; std::unique_ptr availability_; - bool has_custom_state_topic_{false}; - bool has_custom_command_topic_{false}; - bool command_retain_{false}; bool retain_{true}; uint8_t qos_{0}; diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 81a30cb0b7..8e2fadbea8 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1966,7 +1966,9 @@ MQTT_COMPONENT_SCHEMA = Schema( Optional(CONF_RETAIN): All(requires_component("mqtt"), boolean), Optional(CONF_DISCOVERY): All(requires_component("mqtt"), boolean), Optional(CONF_SUBSCRIBE_QOS): All(requires_component("mqtt"), mqtt_qos), - Optional(CONF_STATE_TOPIC): All(requires_component("mqtt"), publish_topic), + Optional(CONF_STATE_TOPIC): All( + requires_component("mqtt"), templatable(publish_topic) + ), Optional(CONF_AVAILABILITY): All( requires_component("mqtt"), Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA) ), @@ -1975,7 +1977,9 @@ MQTT_COMPONENT_SCHEMA = Schema( MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend( { - Optional(CONF_COMMAND_TOPIC): All(requires_component("mqtt"), subscribe_topic), + Optional(CONF_COMMAND_TOPIC): All( + requires_component("mqtt"), templatable(subscribe_topic) + ), Optional(CONF_COMMAND_RETAIN): All(requires_component("mqtt"), boolean), } ) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 585b434bb2..eac469d0fc 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -42,6 +42,10 @@ template struct gens<0, S...> { using type = seq; }; #define TEMPLATABLE_VALUE(type, name) TEMPLATABLE_VALUE_(type, name) template class TemplatableValue { + // For std::string, store pointer to heap-allocated string to keep union pointer-sized. + // For other types, store value inline. + static constexpr bool USE_HEAP_STORAGE = std::same_as; + public: TemplatableValue() : type_(NONE) {} @@ -52,7 +56,11 @@ template class TemplatableValue { } template TemplatableValue(F value) requires(!std::invocable) : type_(VALUE) { - new (&this->value_) T(std::move(value)); + if constexpr (USE_HEAP_STORAGE) { + this->value_ = new T(std::move(value)); + } else { + new (&this->value_) T(std::move(value)); + } } // For stateless lambdas (convertible to function pointer): use function pointer @@ -71,7 +79,11 @@ template class TemplatableValue { // Copy constructor TemplatableValue(const TemplatableValue &other) : type_(other.type_) { if (this->type_ == VALUE) { - new (&this->value_) T(other.value_); + if constexpr (USE_HEAP_STORAGE) { + this->value_ = new T(*other.value_); + } else { + new (&this->value_) T(other.value_); + } } else if (this->type_ == LAMBDA) { this->f_ = new std::function(*other.f_); } else if (this->type_ == STATELESS_LAMBDA) { @@ -84,7 +96,12 @@ template class TemplatableValue { // Move constructor TemplatableValue(TemplatableValue &&other) noexcept : type_(other.type_) { if (this->type_ == VALUE) { - new (&this->value_) T(std::move(other.value_)); + if constexpr (USE_HEAP_STORAGE) { + this->value_ = other.value_; + other.value_ = nullptr; + } else { + new (&this->value_) T(std::move(other.value_)); + } } else if (this->type_ == LAMBDA) { this->f_ = other.f_; other.f_ = nullptr; @@ -115,23 +132,31 @@ template class TemplatableValue { ~TemplatableValue() { if (this->type_ == VALUE) { - this->value_.~T(); + if constexpr (USE_HEAP_STORAGE) { + delete this->value_; + } else { + this->value_.~T(); + } } else if (this->type_ == LAMBDA) { delete this->f_; } // STATELESS_LAMBDA/STATIC_STRING/NONE: no cleanup needed (pointers, not heap-allocated) } - bool has_value() { return this->type_ != NONE; } + bool has_value() const { return this->type_ != NONE; } - T value(X... x) { + T value(X... x) const { switch (this->type_) { case STATELESS_LAMBDA: return this->stateless_f_(x...); // Direct function pointer call case LAMBDA: return (*this->f_)(x...); // std::function call case VALUE: - return this->value_; + if constexpr (USE_HEAP_STORAGE) { + return *this->value_; + } else { + return this->value_; + } case STATIC_STRING: // if constexpr required: code must compile for all T, but STATIC_STRING // can only be set when T is std::string (enforced by constructor constraint) @@ -174,8 +199,11 @@ template class TemplatableValue { STATIC_STRING, // For const char* when T is std::string - avoids heap allocation } type_; + // For std::string, use heap pointer to minimize union size (4 bytes vs 12+). + // For other types, store value inline as before. + using ValueStorage = std::conditional_t; union { - T value_; + ValueStorage value_; // T for inline storage, T* for heap storage std::function *f_; T (*stateless_f_)(X...); const char *static_str_; // For STATIC_STRING type diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index 33988cebb4..4cf2692593 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -91,6 +91,7 @@ button: - platform: template name: "Template Button" state_topic: some/topic/button + command_topic: !lambda return "some/topic/button/command"; qos: 2 on_press: - mqtt.disable @@ -295,7 +296,7 @@ event: fan: - platform: template name: Template Fan - state_topic: some/topic/fan + state_topic: !lambda return "some/topic/fan"; direction_state_topic: some/topic/direction/state direction_command_topic: some/topic/direction/command qos: 2 From 6c043be4d352ff8b3d7b75a8152bbae00e89e5c5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 20:55:23 -1000 Subject: [PATCH 0076/2030] [ci] Add format_hex_pretty to heap-allocating helper lint check (#13178) --- esphome/components/nfc/nfc.cpp | 6 +++--- esphome/components/rc522/rc522.cpp | 2 +- esphome/components/remote_base/midea_protocol.h | 2 +- script/ci-custom.py | 5 ++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index 82e86b936a..f60d2671cd 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -18,9 +18,9 @@ char *format_bytes_to(char *buffer, const std::vector &bytes) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -std::string format_uid(const std::vector &uid) { return format_hex_pretty(uid, '-', false); } - -std::string format_bytes(const std::vector &bytes) { return format_hex_pretty(bytes, ' ', false); } +// Deprecated wrappers intentionally use heap-allocating version for backward compatibility +std::string format_uid(const std::vector &uid) { return format_hex_pretty(uid, '-', false); } // NOLINT +std::string format_bytes(const std::vector &bytes) { return format_hex_pretty(bytes, ' ', false); } // NOLINT #pragma GCC diagnostic pop uint8_t guess_tag_type(uint8_t uid_length) { diff --git a/esphome/components/rc522/rc522.cpp b/esphome/components/rc522/rc522.cpp index 470c50109e..91fae7fa34 100644 --- a/esphome/components/rc522/rc522.cpp +++ b/esphome/components/rc522/rc522.cpp @@ -220,7 +220,7 @@ void RC522::loop() { std::vector rfid_uid(std::begin(uid_buffer_), std::begin(uid_buffer_) + uid_idx_); uid_idx_ = 0; - // ESP_LOGD(TAG, "Processing '%s'", format_hex_pretty(rfid_uid, '-', false).c_str()); + // ESP_LOGD(TAG, "Processing '%s'", format_hex_pretty(rfid_uid, '-', false).c_str()); // NOLINT pcd_antenna_off_(); state_ = STATE_INIT; // scan again on next update bool report = true; diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index c3030d565e..ddefff867a 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -31,7 +31,7 @@ class MideaData { bool is_compliment(const MideaData &rhs) const; /// @deprecated Allocates heap memory. Use to_str() instead. Removed in 2026.7.0. ESPDEPRECATED("Allocates heap memory. Use to_str() instead. Removed in 2026.7.0.", "2026.1.0") - std::string to_string() const { return format_hex_pretty(this->data_.data(), this->data_.size()); } + std::string to_string() const { return format_hex_pretty(this->data_.data(), this->data_.size()); } // NOLINT /// Buffer size for to_str(): 6 bytes = "AA.BB.CC.DD.EE.FF\0" static constexpr size_t TO_STR_BUFFER_SIZE = format_hex_pretty_size(6); /// Format to buffer, returns pointer to buffer diff --git a/script/ci-custom.py b/script/ci-custom.py index 1e2d07885e..e63e61e096 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -683,6 +683,7 @@ def lint_trailing_whitespace(fname, match): # These return std::string and should be replaced with stack-based alternatives. HEAP_ALLOCATING_HELPERS = { "format_hex": "format_hex_to() with a stack buffer", + "format_hex_pretty": "format_hex_pretty_to() with a stack buffer", "format_mac_address_pretty": "format_mac_addr_upper() with a stack buffer", "get_mac_address": "get_mac_address_into_buffer() with a stack buffer", "get_mac_address_pretty": "get_mac_address_pretty_into_buffer() with a stack buffer", @@ -696,15 +697,17 @@ HEAP_ALLOCATING_HELPERS = { # Use negative lookahead to exclude _to/_into_buffer variants # format_hex(?!_) ensures we don't match format_hex_to, format_hex_pretty_to, etc. # get_mac_address(?!_) ensures we don't match get_mac_address_into_buffer, etc. + # CPP_RE_EOL captures rest of line so NOLINT comments are detected r"[^\w](" r"format_hex(?!_)|" + r"format_hex_pretty(?!_)|" r"format_mac_address_pretty|" r"get_mac_address_pretty(?!_)|" r"get_mac_address(?!_)|" r"str_truncate|" r"str_upper_case|" r"str_snake_case" - r")\s*\(", + r")\s*\(" + CPP_RE_EOL, include=cpp_include, exclude=[ # The definitions themselves From 675103bed0896932cc2e13439db066ee9d4fe246 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 20:55:40 -1000 Subject: [PATCH 0077/2030] [esphome] Fix OTA backend abort not being called on error (#13182) --- esphome/components/esphome/ota/ota_esphome.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index dfa637f701..b2ae185687 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -370,12 +370,14 @@ void ESPHomeOTAComponent::handle_data_() { error: this->write_byte_(static_cast(error_code)); - this->cleanup_connection_(); + // Abort backend before cleanup - cleanup_connection_() destroys the backend if (this->backend_ != nullptr && update_started) { this->backend_->abort(); } + this->cleanup_connection_(); + this->status_momentary_error("err", 5000); #ifdef USE_OTA_STATE_LISTENER this->notify_state_(ota::OTA_ERROR, 0.0f, static_cast(error_code)); From 6823e17b3bdb30f691419de998b0ce2600fe4e05 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 13 Jan 2026 01:44:24 -0600 Subject: [PATCH 0078/2030] [ir_rf_proxy] New component (#12985) Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- CODEOWNERS | 1 + esphome/components/ir_rf_proxy/__init__.py | 11 +++ esphome/components/ir_rf_proxy/infrared.py | 77 +++++++++++++++++++ .../components/ir_rf_proxy/ir_rf_proxy.cpp | 23 ++++++ esphome/components/ir_rf_proxy/ir_rf_proxy.h | 32 ++++++++ tests/components/infrared/common.yaml | 42 ++++++++++ tests/components/infrared/test.esp32-idf.yaml | 5 ++ .../components/infrared/test.esp8266-ard.yaml | 5 ++ .../components/infrared/test.rp2040-ard.yaml | 5 ++ tests/components/ir_rf_proxy/common.yaml | 42 ++++++++++ .../ir_rf_proxy/test.esp32-idf.yaml | 5 ++ .../ir_rf_proxy/test.esp8266-ard.yaml | 5 ++ .../ir_rf_proxy/test.rp2040-ard.yaml | 5 ++ 13 files changed, 258 insertions(+) create mode 100644 esphome/components/ir_rf_proxy/__init__.py create mode 100644 esphome/components/ir_rf_proxy/infrared.py create mode 100644 esphome/components/ir_rf_proxy/ir_rf_proxy.cpp create mode 100644 esphome/components/ir_rf_proxy/ir_rf_proxy.h create mode 100644 tests/components/infrared/common.yaml create mode 100644 tests/components/infrared/test.esp32-idf.yaml create mode 100644 tests/components/infrared/test.esp8266-ard.yaml create mode 100644 tests/components/infrared/test.rp2040-ard.yaml create mode 100644 tests/components/ir_rf_proxy/common.yaml create mode 100644 tests/components/ir_rf_proxy/test.esp32-idf.yaml create mode 100644 tests/components/ir_rf_proxy/test.esp8266-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 48318ee064..8a37aeb29f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -255,6 +255,7 @@ esphome/components/inkplate/* @jesserockz @JosipKuci esphome/components/integration/* @OttoWinter esphome/components/internal_temperature/* @Mat931 esphome/components/interval/* @esphome/core +esphome/components/ir_rf_proxy/* @kbx81 esphome/components/jsn_sr04t/* @Mafus1 esphome/components/json/* @esphome/core esphome/components/kamstrup_kmp/* @cfeenstra1024 diff --git a/esphome/components/ir_rf_proxy/__init__.py b/esphome/components/ir_rf_proxy/__init__.py new file mode 100644 index 0000000000..bc4079ede7 --- /dev/null +++ b/esphome/components/ir_rf_proxy/__init__.py @@ -0,0 +1,11 @@ +"""IR/RF Proxy component - provides remote_base backend for infrared platform.""" + +import esphome.codegen as cg + +CODEOWNERS = ["@kbx81"] + +# Namespace and constants exported for infrared.py platform +ir_rf_proxy_ns = cg.esphome_ns.namespace("ir_rf_proxy") + +CONF_REMOTE_RECEIVER_ID = "remote_receiver_id" +CONF_REMOTE_TRANSMITTER_ID = "remote_transmitter_id" diff --git a/esphome/components/ir_rf_proxy/infrared.py b/esphome/components/ir_rf_proxy/infrared.py new file mode 100644 index 0000000000..4a4d9fa860 --- /dev/null +++ b/esphome/components/ir_rf_proxy/infrared.py @@ -0,0 +1,77 @@ +"""Infrared platform implementation using remote_base (remote_transmitter/receiver).""" + +from typing import Any + +import esphome.codegen as cg +from esphome.components import infrared, remote_receiver, remote_transmitter +import esphome.config_validation as cv +from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_FREQUENCY +import esphome.final_validate as fv + +from . import CONF_REMOTE_RECEIVER_ID, CONF_REMOTE_TRANSMITTER_ID, ir_rf_proxy_ns + +CODEOWNERS = ["@kbx81"] +DEPENDENCIES = ["infrared"] + +IrRfProxy = ir_rf_proxy_ns.class_("IrRfProxy", infrared.Infrared) + +CONFIG_SCHEMA = cv.All( + infrared.infrared_schema(IrRfProxy).extend( + { + cv.Optional(CONF_FREQUENCY, default=0): cv.frequency, + cv.Optional(CONF_REMOTE_RECEIVER_ID): cv.use_id( + remote_receiver.RemoteReceiverComponent + ), + cv.Optional(CONF_REMOTE_TRANSMITTER_ID): cv.use_id( + remote_transmitter.RemoteTransmitterComponent + ), + } + ), + cv.has_exactly_one_key(CONF_REMOTE_RECEIVER_ID, CONF_REMOTE_TRANSMITTER_ID), +) + + +def _final_validate(config: dict[str, Any]) -> None: + """Validate that transmitters have a proper carrier duty cycle.""" + # Only validate if this is an infrared (not RF) configuration with a transmitter + if config.get(CONF_FREQUENCY, 0) != 0 or CONF_REMOTE_TRANSMITTER_ID not in config: + return + + # Get the transmitter configuration + transmitter_id = config[CONF_REMOTE_TRANSMITTER_ID] + full_config = fv.full_config.get() + transmitter_path = full_config.get_path_for_id(transmitter_id)[:-1] + transmitter_config = full_config.get_config_for_path(transmitter_path) + + # Check if carrier_duty_percent set to 0 or 100 + # Note: remote_transmitter schema requires this field and validates 1-100%, + # but we double-check here for infrared to provide a helpful error message + duty_percent = transmitter_config.get(CONF_CARRIER_DUTY_PERCENT) + if duty_percent in {0, 100}: + raise cv.Invalid( + f"Transmitter '{transmitter_id}' must have '{CONF_CARRIER_DUTY_PERCENT}' configured with " + "an intermediate value (typically 30-50%) for infrared transmission. If this is an RF " + f"transmitter, configure this infrared with a '{CONF_FREQUENCY}' value greater than 0" + ) + + +FINAL_VALIDATE_SCHEMA = _final_validate + + +async def to_code(config: dict[str, Any]) -> None: + """Code generation for remote_base infrared platform.""" + # Create and register the infrared entity + var = await infrared.new_infrared(config) + + # Set frequency / 1000; zero indicates infrared hardware + cg.add(var.set_frequency(config[CONF_FREQUENCY] / 1000)) + + # Link transmitter if specified + if CONF_REMOTE_TRANSMITTER_ID in config: + transmitter = await cg.get_variable(config[CONF_REMOTE_TRANSMITTER_ID]) + cg.add(var.set_transmitter(transmitter)) + + # Link receiver if specified + if CONF_REMOTE_RECEIVER_ID in config: + receiver = await cg.get_variable(config[CONF_REMOTE_RECEIVER_ID]) + cg.add(var.set_receiver(receiver)) diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp b/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp new file mode 100644 index 0000000000..5239a4667c --- /dev/null +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.cpp @@ -0,0 +1,23 @@ +#include "ir_rf_proxy.h" +#include "esphome/core/log.h" + +namespace esphome::ir_rf_proxy { + +static const char *const TAG = "ir_rf_proxy"; + +void IrRfProxy::dump_config() { + ESP_LOGCONFIG(TAG, + "IR/RF Proxy '%s'\n" + " Supports Transmitter: %s\n" + " Supports Receiver: %s", + this->get_name().c_str(), YESNO(this->traits_.get_supports_transmitter()), + YESNO(this->traits_.get_supports_receiver())); + + if (this->is_rf()) { + ESP_LOGCONFIG(TAG, " Hardware Type: RF (%.3f MHz)", this->frequency_khz_ / 1e3f); + } else { + ESP_LOGCONFIG(TAG, " Hardware Type: Infrared"); + } +} + +} // namespace esphome::ir_rf_proxy diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.h b/esphome/components/ir_rf_proxy/ir_rf_proxy.h new file mode 100644 index 0000000000..d7c8919def --- /dev/null +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.h @@ -0,0 +1,32 @@ +#pragma once + +// WARNING: This component is EXPERIMENTAL. The API may change at any time +// without following the normal breaking changes policy. Use at your own risk. +// Once the API is considered stable, this warning will be removed. + +#include "esphome/components/infrared/infrared.h" +#include "esphome/components/remote_transmitter/remote_transmitter.h" +#include "esphome/components/remote_receiver/remote_receiver.h" + +namespace esphome::ir_rf_proxy { + +/// IrRfProxy - Infrared platform implementation using remote_transmitter/receiver as backend +class IrRfProxy : public infrared::Infrared { + public: + IrRfProxy() = default; + + void dump_config() override; + + /// Set RF frequency in kHz (0 = infrared, non-zero = RF) + void set_frequency(uint32_t frequency_khz) { this->frequency_khz_ = frequency_khz; } + /// Get RF frequency in kHz + uint32_t get_frequency() const { return this->frequency_khz_; } + /// Check if this is RF mode (non-zero frequency) + bool is_rf() const { return this->frequency_khz_ > 0; } + + protected: + // RF frequency in kHz (Hz / 1000); 0 = infrared, non-zero = RF + uint32_t frequency_khz_{0}; +}; + +} // namespace esphome::ir_rf_proxy diff --git a/tests/components/infrared/common.yaml b/tests/components/infrared/common.yaml new file mode 100644 index 0000000000..cd2b10d31b --- /dev/null +++ b/tests/components/infrared/common.yaml @@ -0,0 +1,42 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +remote_transmitter: + id: ir_transmitter + pin: ${tx_pin} + carrier_duty_percent: 50% + +remote_receiver: + id: ir_receiver + pin: ${rx_pin} + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared transmitter + - platform: ir_rf_proxy + id: ir_tx + name: "IR Transmitter" + remote_transmitter_id: ir_transmitter + + # Infrared receiver + - platform: ir_rf_proxy + id: ir_rx + name: "IR Receiver" + remote_receiver_id: ir_receiver + + # RF 433MHz transmitter + - platform: ir_rf_proxy + id: rf_433_tx + name: "RF 433 Transmitter" + frequency: 433 MHz + remote_transmitter_id: ir_transmitter + + # RF 900MHz receiver + - platform: ir_rf_proxy + id: rf_900_rx + name: "RF 900 Receiver" + frequency: 900 MHz + remote_receiver_id: ir_receiver diff --git a/tests/components/infrared/test.esp32-idf.yaml b/tests/components/infrared/test.esp32-idf.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/infrared/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/infrared/test.esp8266-ard.yaml b/tests/components/infrared/test.esp8266-ard.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/infrared/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/infrared/test.rp2040-ard.yaml b/tests/components/infrared/test.rp2040-ard.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/infrared/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ir_rf_proxy/common.yaml b/tests/components/ir_rf_proxy/common.yaml new file mode 100644 index 0000000000..cd2b10d31b --- /dev/null +++ b/tests/components/ir_rf_proxy/common.yaml @@ -0,0 +1,42 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +remote_transmitter: + id: ir_transmitter + pin: ${tx_pin} + carrier_duty_percent: 50% + +remote_receiver: + id: ir_receiver + pin: ${rx_pin} + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared transmitter + - platform: ir_rf_proxy + id: ir_tx + name: "IR Transmitter" + remote_transmitter_id: ir_transmitter + + # Infrared receiver + - platform: ir_rf_proxy + id: ir_rx + name: "IR Receiver" + remote_receiver_id: ir_receiver + + # RF 433MHz transmitter + - platform: ir_rf_proxy + id: rf_433_tx + name: "RF 433 Transmitter" + frequency: 433 MHz + remote_transmitter_id: ir_transmitter + + # RF 900MHz receiver + - platform: ir_rf_proxy + id: rf_900_rx + name: "RF 900 Receiver" + frequency: 900 MHz + remote_receiver_id: ir_receiver diff --git a/tests/components/ir_rf_proxy/test.esp32-idf.yaml b/tests/components/ir_rf_proxy/test.esp32-idf.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/ir_rf_proxy/test.esp32-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ir_rf_proxy/test.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml diff --git a/tests/components/ir_rf_proxy/test.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml new file mode 100644 index 0000000000..b516342f3b --- /dev/null +++ b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml @@ -0,0 +1,5 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +<<: !include common.yaml From df4a3e8915068f684318ca04a3fed0c56b51cd8a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 21:47:11 -1000 Subject: [PATCH 0079/2030] [socket] Call lwip_read/lwip_write directly on ESP32 to reduce network I/O latency (#13179) --- esphome/components/socket/bsd_sockets_impl.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.cpp b/esphome/components/socket/bsd_sockets_impl.cpp index 73be025376..b670b9c068 100644 --- a/esphome/components/socket/bsd_sockets_impl.cpp +++ b/esphome/components/socket/bsd_sockets_impl.cpp @@ -79,7 +79,13 @@ class BSDSocketImpl final : public Socket { return ::setsockopt(this->fd_, level, optname, optval, optlen); } int listen(int backlog) override { return ::listen(this->fd_, backlog); } - ssize_t read(void *buf, size_t len) override { return ::read(this->fd_, buf, len); } + ssize_t read(void *buf, size_t len) override { +#ifdef USE_ESP32 + return ::lwip_read(this->fd_, buf, len); +#else + return ::read(this->fd_, buf, len); +#endif + } ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) override { #if defined(USE_ESP32) || defined(USE_HOST) return ::recvfrom(this->fd_, buf, len, 0, addr, addr_len); @@ -94,7 +100,13 @@ class BSDSocketImpl final : public Socket { return ::readv(this->fd_, iov, iovcnt); #endif } - ssize_t write(const void *buf, size_t len) override { return ::write(this->fd_, buf, len); } + ssize_t write(const void *buf, size_t len) override { +#ifdef USE_ESP32 + return ::lwip_write(this->fd_, buf, len); +#else + return ::write(this->fd_, buf, len); +#endif + } ssize_t send(void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); } ssize_t writev(const struct iovec *iov, int iovcnt) override { #if defined(USE_ESP32) From 1327776d5b4587b6adacb140e301264c49e0db6f Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 13 Jan 2026 00:32:11 -0800 Subject: [PATCH 0080/2030] [bme68x_bsec2] use EntityBase instead of Component for the id (#13185) Co-authored-by: Samuel Sieb --- esphome/components/bme68x_bsec2/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/bme68x_bsec2/sensor.py b/esphome/components/bme68x_bsec2/sensor.py index 45a9e54c1e..f21a9b8138 100644 --- a/esphome/components/bme68x_bsec2/sensor.py +++ b/esphome/components/bme68x_bsec2/sensor.py @@ -50,7 +50,7 @@ TYPES = [ CONFIG_SCHEMA = cv.Schema( { - cv.GenerateID(): cv.declare_id(cg.Component), + cv.GenerateID(): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_BME68X_BSEC2_ID): cv.use_id(BME68xBSEC2Component), cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, From 48f5296d24dd91061446527128c6d429f5a5eb98 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 13 Jan 2026 00:32:20 -0800 Subject: [PATCH 0081/2030] [ld24xx] add id to support extending (#13183) Co-authored-by: Samuel Sieb --- esphome/components/ld2410/binary_sensor.py | 2 ++ esphome/components/ld2410/button/__init__.py | 2 ++ esphome/components/ld2410/number/__init__.py | 1 + esphome/components/ld2410/select/__init__.py | 2 ++ esphome/components/ld2410/sensor.py | 2 ++ esphome/components/ld2410/switch/__init__.py | 2 ++ esphome/components/ld2410/text_sensor.py | 2 ++ esphome/components/ld2412/binary_sensor.py | 2 ++ esphome/components/ld2412/button/__init__.py | 2 ++ esphome/components/ld2412/number/__init__.py | 1 + esphome/components/ld2412/select/__init__.py | 2 ++ esphome/components/ld2412/sensor.py | 2 ++ esphome/components/ld2412/switch/__init__.py | 2 ++ esphome/components/ld2412/text_sensor.py | 2 ++ esphome/components/ld2450/binary_sensor.py | 2 ++ esphome/components/ld2450/button/__init__.py | 2 ++ esphome/components/ld2450/number/__init__.py | 1 + esphome/components/ld2450/select/__init__.py | 8 +++++++- esphome/components/ld2450/sensor.py | 2 ++ esphome/components/ld2450/switch/__init__.py | 2 ++ esphome/components/ld2450/text_sensor.py | 2 ++ tests/components/ld2410/common.yaml | 7 +++++++ tests/components/ld2412/common.yaml | 7 +++++++ tests/components/ld2450/common.yaml | 7 +++++++ 24 files changed, 65 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2410/binary_sensor.py b/esphome/components/ld2410/binary_sensor.py index 4e35f67fbe..fb5b5cabff 100644 --- a/esphome/components/ld2410/binary_sensor.py +++ b/esphome/components/ld2410/binary_sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_HAS_MOVING_TARGET, CONF_HAS_STILL_TARGET, CONF_HAS_TARGET, + CONF_ID, DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_PRESENCE, @@ -19,6 +20,7 @@ DEPENDENCIES = ["ld2410"] CONF_OUT_PIN_PRESENCE_STATUS = "out_pin_presence_status" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_OCCUPANCY, diff --git a/esphome/components/ld2410/button/__init__.py b/esphome/components/ld2410/button/__init__.py index 1cd56082c3..fa6f31ee25 100644 --- a/esphome/components/ld2410/button/__init__.py +++ b/esphome/components/ld2410/button/__init__.py @@ -3,6 +3,7 @@ from esphome.components import button import esphome.config_validation as cv from esphome.const import ( CONF_FACTORY_RESET, + CONF_ID, CONF_RESTART, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, @@ -21,6 +22,7 @@ RestartButton = ld2410_ns.class_("RestartButton", button.Button) CONF_QUERY_PARAMS = "query_params" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_FACTORY_RESET): button.button_schema( FactoryResetButton, diff --git a/esphome/components/ld2410/number/__init__.py b/esphome/components/ld2410/number/__init__.py index ffa4e7e146..01dbcc785d 100644 --- a/esphome/components/ld2410/number/__init__.py +++ b/esphome/components/ld2410/number/__init__.py @@ -31,6 +31,7 @@ TIMEOUT_GROUP = "timeout" CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Inclusive(CONF_TIMEOUT, TIMEOUT_GROUP): number.number_schema( MaxDistanceTimeoutNumber, diff --git a/esphome/components/ld2410/select/__init__.py b/esphome/components/ld2410/select/__init__.py index 686afdef14..9c4f654aa1 100644 --- a/esphome/components/ld2410/select/__init__.py +++ b/esphome/components/ld2410/select/__init__.py @@ -3,6 +3,7 @@ from esphome.components import select import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, + CONF_ID, ENTITY_CATEGORY_CONFIG, ICON_LIGHTBULB, ICON_RULER, @@ -22,6 +23,7 @@ CONF_OUT_PIN_LEVEL = "out_pin_level" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_DISTANCE_RESOLUTION): select.select_schema( DistanceResolutionSelect, diff --git a/esphome/components/ld2410/sensor.py b/esphome/components/ld2410/sensor.py index 3bd34963bc..459018e263 100644 --- a/esphome/components/ld2410/sensor.py +++ b/esphome/components/ld2410/sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv from esphome.const import ( + CONF_ID, CONF_LIGHT, CONF_MOVING_DISTANCE, DEVICE_CLASS_DISTANCE, @@ -28,6 +29,7 @@ CONF_STILL_ENERGY = "still_energy" CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, diff --git a/esphome/components/ld2410/switch/__init__.py b/esphome/components/ld2410/switch/__init__.py index 71b8a40a29..4276b28a71 100644 --- a/esphome/components/ld2410/switch/__init__.py +++ b/esphome/components/ld2410/switch/__init__.py @@ -3,6 +3,7 @@ from esphome.components import switch import esphome.config_validation as cv from esphome.const import ( CONF_BLUETOOTH, + CONF_ID, DEVICE_CLASS_SWITCH, ENTITY_CATEGORY_CONFIG, ICON_BLUETOOTH, @@ -17,6 +18,7 @@ EngineeringModeSwitch = ld2410_ns.class_("EngineeringModeSwitch", switch.Switch) CONF_ENGINEERING_MODE = "engineering_mode" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_ENGINEERING_MODE): switch.switch_schema( EngineeringModeSwitch, diff --git a/esphome/components/ld2410/text_sensor.py b/esphome/components/ld2410/text_sensor.py index 5a021d9163..a34c8ec0d2 100644 --- a/esphome/components/ld2410/text_sensor.py +++ b/esphome/components/ld2410/text_sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import text_sensor import esphome.config_validation as cv from esphome.const import ( + CONF_ID, CONF_MAC_ADDRESS, CONF_VERSION, ENTITY_CATEGORY_DIAGNOSTIC, @@ -14,6 +15,7 @@ from . import CONF_LD2410_ID, LD2410Component DEPENDENCIES = ["ld2410"] CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2410_ID): cv.use_id(LD2410Component), cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema( entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon=ICON_CHIP diff --git a/esphome/components/ld2412/binary_sensor.py b/esphome/components/ld2412/binary_sensor.py index aa1b0d2cd8..98fa5965cd 100644 --- a/esphome/components/ld2412/binary_sensor.py +++ b/esphome/components/ld2412/binary_sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_HAS_MOVING_TARGET, CONF_HAS_STILL_TARGET, CONF_HAS_TARGET, + CONF_ID, DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_RUNNING, @@ -20,6 +21,7 @@ DEPENDENCIES = ["ld2412"] CONF_DYNAMIC_BACKGROUND_CORRECTION_STATUS = "dynamic_background_correction_status" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional( CONF_DYNAMIC_BACKGROUND_CORRECTION_STATUS diff --git a/esphome/components/ld2412/button/__init__.py b/esphome/components/ld2412/button/__init__.py index e78cad4b88..e0ca285265 100644 --- a/esphome/components/ld2412/button/__init__.py +++ b/esphome/components/ld2412/button/__init__.py @@ -3,6 +3,7 @@ from esphome.components import button import esphome.config_validation as cv from esphome.const import ( CONF_FACTORY_RESET, + CONF_ID, CONF_RESTART, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, @@ -26,6 +27,7 @@ CONF_QUERY_PARAMS = "query_params" CONF_START_DYNAMIC_BACKGROUND_CORRECTION = "start_dynamic_background_correction" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_FACTORY_RESET): button.button_schema( FactoryResetButton, diff --git a/esphome/components/ld2412/number/__init__.py b/esphome/components/ld2412/number/__init__.py index 5b0d6d8749..b6e1c8d039 100644 --- a/esphome/components/ld2412/number/__init__.py +++ b/esphome/components/ld2412/number/__init__.py @@ -31,6 +31,7 @@ TIMEOUT_GROUP = "timeout" CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_LIGHT_THRESHOLD): number.number_schema( LightThresholdNumber, diff --git a/esphome/components/ld2412/select/__init__.py b/esphome/components/ld2412/select/__init__.py index d71ce460d9..a54cd700ed 100644 --- a/esphome/components/ld2412/select/__init__.py +++ b/esphome/components/ld2412/select/__init__.py @@ -3,6 +3,7 @@ from esphome.components import select import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, + CONF_ID, ENTITY_CATEGORY_CONFIG, ICON_LIGHTBULB, ICON_RULER, @@ -22,6 +23,7 @@ CONF_OUT_PIN_LEVEL = "out_pin_level" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_BAUD_RATE): select.select_schema( BaudRateSelect, diff --git a/esphome/components/ld2412/sensor.py b/esphome/components/ld2412/sensor.py index 0bfbd9bf1d..f562afe0ee 100644 --- a/esphome/components/ld2412/sensor.py +++ b/esphome/components/ld2412/sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv from esphome.const import ( + CONF_ID, CONF_LIGHT, CONF_MOVING_DISTANCE, DEVICE_CLASS_DISTANCE, @@ -28,6 +29,7 @@ CONF_STILL_ENERGY = "still_energy" CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_DETECTION_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, diff --git a/esphome/components/ld2412/switch/__init__.py b/esphome/components/ld2412/switch/__init__.py index df994687ec..7a87e9e483 100644 --- a/esphome/components/ld2412/switch/__init__.py +++ b/esphome/components/ld2412/switch/__init__.py @@ -3,6 +3,7 @@ from esphome.components import switch import esphome.config_validation as cv from esphome.const import ( CONF_BLUETOOTH, + CONF_ID, DEVICE_CLASS_SWITCH, ENTITY_CATEGORY_CONFIG, ICON_BLUETOOTH, @@ -17,6 +18,7 @@ EngineeringModeSwitch = LD2412_ns.class_("EngineeringModeSwitch", switch.Switch) CONF_ENGINEERING_MODE = "engineering_mode" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_BLUETOOTH): switch.switch_schema( BluetoothSwitch, diff --git a/esphome/components/ld2412/text_sensor.py b/esphome/components/ld2412/text_sensor.py index 1074494933..22fba5193e 100644 --- a/esphome/components/ld2412/text_sensor.py +++ b/esphome/components/ld2412/text_sensor.py @@ -2,6 +2,7 @@ import esphome.codegen as cg from esphome.components import text_sensor import esphome.config_validation as cv from esphome.const import ( + CONF_ID, CONF_MAC_ADDRESS, CONF_VERSION, ENTITY_CATEGORY_DIAGNOSTIC, @@ -14,6 +15,7 @@ from . import CONF_LD2412_ID, LD2412Component DEPENDENCIES = ["ld2412"] CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2412_ID): cv.use_id(LD2412Component), cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema( entity_category=ENTITY_CATEGORY_DIAGNOSTIC, icon=ICON_CHIP diff --git a/esphome/components/ld2450/binary_sensor.py b/esphome/components/ld2450/binary_sensor.py index 37f722b0fa..89e629253a 100644 --- a/esphome/components/ld2450/binary_sensor.py +++ b/esphome/components/ld2450/binary_sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_HAS_MOVING_TARGET, CONF_HAS_STILL_TARGET, CONF_HAS_TARGET, + CONF_ID, DEVICE_CLASS_MOTION, DEVICE_CLASS_OCCUPANCY, ) @@ -18,6 +19,7 @@ ICON_SHIELD_ACCOUNT = "mdi:shield-account" ICON_TARGET_ACCOUNT = "mdi:target-account" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_HAS_TARGET): binary_sensor.binary_sensor_schema( device_class=DEVICE_CLASS_OCCUPANCY, diff --git a/esphome/components/ld2450/button/__init__.py b/esphome/components/ld2450/button/__init__.py index 429aa59389..682487d750 100644 --- a/esphome/components/ld2450/button/__init__.py +++ b/esphome/components/ld2450/button/__init__.py @@ -3,6 +3,7 @@ from esphome.components import button import esphome.config_validation as cv from esphome.const import ( CONF_FACTORY_RESET, + CONF_ID, CONF_RESTART, DEVICE_CLASS_RESTART, ENTITY_CATEGORY_CONFIG, @@ -17,6 +18,7 @@ FactoryResetButton = ld2450_ns.class_("FactoryResetButton", button.Button) RestartButton = ld2450_ns.class_("RestartButton", button.Button) CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_FACTORY_RESET): button.button_schema( FactoryResetButton, diff --git a/esphome/components/ld2450/number/__init__.py b/esphome/components/ld2450/number/__init__.py index d2098f6131..799c0703f2 100644 --- a/esphome/components/ld2450/number/__init__.py +++ b/esphome/components/ld2450/number/__init__.py @@ -28,6 +28,7 @@ ZoneCoordinateNumber = ld2450_ns.class_("ZoneCoordinateNumber", number.Number) CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Required(CONF_PRESENCE_TIMEOUT): number.number_schema( PresenceTimeoutNumber, diff --git a/esphome/components/ld2450/select/__init__.py b/esphome/components/ld2450/select/__init__.py index 25dd819637..4f237dc94f 100644 --- a/esphome/components/ld2450/select/__init__.py +++ b/esphome/components/ld2450/select/__init__.py @@ -1,7 +1,12 @@ import esphome.codegen as cg from esphome.components import select import esphome.config_validation as cv -from esphome.const import CONF_BAUD_RATE, ENTITY_CATEGORY_CONFIG, ICON_THERMOMETER +from esphome.const import ( + CONF_BAUD_RATE, + CONF_ID, + ENTITY_CATEGORY_CONFIG, + ICON_THERMOMETER, +) from .. import CONF_LD2450_ID, LD2450Component, ld2450_ns @@ -11,6 +16,7 @@ BaudRateSelect = ld2450_ns.class_("BaudRateSelect", select.Select) ZoneTypeSelect = ld2450_ns.class_("ZoneTypeSelect", select.Select) CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_BAUD_RATE): select.select_schema( BaudRateSelect, diff --git a/esphome/components/ld2450/sensor.py b/esphome/components/ld2450/sensor.py index 4a3597d583..3dee8bf470 100644 --- a/esphome/components/ld2450/sensor.py +++ b/esphome/components/ld2450/sensor.py @@ -4,6 +4,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_ANGLE, CONF_DISTANCE, + CONF_ID, CONF_RESOLUTION, CONF_SPEED, CONF_X, @@ -40,6 +41,7 @@ UNIT_MILLIMETER_PER_SECOND = "mm/s" CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_TARGET_COUNT): sensor.sensor_schema( accuracy_decimals=0, diff --git a/esphome/components/ld2450/switch/__init__.py b/esphome/components/ld2450/switch/__init__.py index 2d76b75781..0c0c92377b 100644 --- a/esphome/components/ld2450/switch/__init__.py +++ b/esphome/components/ld2450/switch/__init__.py @@ -3,6 +3,7 @@ from esphome.components import switch import esphome.config_validation as cv from esphome.const import ( CONF_BLUETOOTH, + CONF_ID, DEVICE_CLASS_SWITCH, ENTITY_CATEGORY_CONFIG, ICON_BLUETOOTH, @@ -17,6 +18,7 @@ MultiTargetSwitch = ld2450_ns.class_("MultiTargetSwitch", switch.Switch) CONF_MULTI_TARGET = "multi_target" CONFIG_SCHEMA = { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_BLUETOOTH): switch.switch_schema( BluetoothSwitch, diff --git a/esphome/components/ld2450/text_sensor.py b/esphome/components/ld2450/text_sensor.py index 89b6939a29..4e5d7d419b 100644 --- a/esphome/components/ld2450/text_sensor.py +++ b/esphome/components/ld2450/text_sensor.py @@ -3,6 +3,7 @@ from esphome.components import text_sensor import esphome.config_validation as cv from esphome.const import ( CONF_DIRECTION, + CONF_ID, CONF_MAC_ADDRESS, CONF_VERSION, ENTITY_CATEGORY_DIAGNOSTIC, @@ -20,6 +21,7 @@ MAX_TARGETS = 3 CONFIG_SCHEMA = cv.Schema( { + cv.GenerateID(CONF_ID): cv.declare_id(cg.EntityBase), cv.GenerateID(CONF_LD2450_ID): cv.use_id(LD2450Component), cv.Optional(CONF_VERSION): text_sensor.text_sensor_schema( entity_category=ENTITY_CATEGORY_DIAGNOSTIC, diff --git a/tests/components/ld2410/common.yaml b/tests/components/ld2410/common.yaml index 7d168bf7ec..71b1ffd049 100644 --- a/tests/components/ld2410/common.yaml +++ b/tests/components/ld2410/common.yaml @@ -3,6 +3,7 @@ ld2410: binary_sensor: - platform: ld2410 + id: ld2410_binary has_target: name: presence has_moving_target: @@ -14,6 +15,7 @@ binary_sensor: button: - platform: ld2410 + id: ld2410_button factory_reset: name: factory reset restart: @@ -23,6 +25,7 @@ button: number: - platform: ld2410 + id: ld2410_number light_threshold: name: light threshold timeout: @@ -79,6 +82,7 @@ number: select: - platform: ld2410 + id: ld2410_select distance_resolution: name: distance resolution baud_rate: @@ -90,6 +94,7 @@ select: sensor: - platform: ld2410 + id: ld2410_sensor light: name: light moving_distance: @@ -150,6 +155,7 @@ sensor: switch: - platform: ld2410 + id: ld2410_switch engineering_mode: name: control ld2410 engineering mode bluetooth: @@ -157,6 +163,7 @@ switch: text_sensor: - platform: ld2410 + id: ld2410_textsensor version: name: presenece sensor version mac_address: diff --git a/tests/components/ld2412/common.yaml b/tests/components/ld2412/common.yaml index 18c4612ffe..c5bda688dc 100644 --- a/tests/components/ld2412/common.yaml +++ b/tests/components/ld2412/common.yaml @@ -3,6 +3,7 @@ ld2412: binary_sensor: - platform: ld2412 + id: ld2412_binary dynamic_background_correction_status: name: Dynamic Background Correction Status has_target: @@ -14,6 +15,7 @@ binary_sensor: button: - platform: ld2412 + id: ld2412_button factory_reset: name: Factory reset restart: @@ -25,6 +27,7 @@ button: number: - platform: ld2412 + id: ld2412_number light_threshold: name: Light Threshold timeout: @@ -106,6 +109,7 @@ number: select: - platform: ld2412 + id: ld2412_select light_function: name: Light Function out_pin_level: @@ -129,6 +133,7 @@ select: sensor: - platform: ld2412 + id: ld2412_sensor light: name: Light moving_distance: @@ -214,6 +219,7 @@ sensor: switch: - platform: ld2412 + id: ld2412_switch bluetooth: name: Bluetooth engineering_mode: @@ -221,6 +227,7 @@ switch: text_sensor: - platform: ld2412 + id: ld2412_textsensor version: name: Firmware version mac_address: diff --git a/tests/components/ld2450/common.yaml b/tests/components/ld2450/common.yaml index 9dcefffd09..cfa3c922fc 100644 --- a/tests/components/ld2450/common.yaml +++ b/tests/components/ld2450/common.yaml @@ -3,6 +3,7 @@ ld2450: button: - platform: ld2450 + id: ld2450_button ld2450_id: ld2450_radar factory_reset: name: LD2450 Factory Reset @@ -13,6 +14,7 @@ button: sensor: - platform: ld2450 + id: ld2450_sensor ld2450_id: ld2450_radar target_count: name: Presence Target Count @@ -83,6 +85,7 @@ sensor: binary_sensor: - platform: ld2450 + id: ld2450_binary ld2450_id: ld2450_radar has_target: name: Presence @@ -93,6 +96,7 @@ binary_sensor: switch: - platform: ld2450 + id: ld2450_switch ld2450_id: ld2450_radar bluetooth: name: Bluetooth @@ -101,6 +105,7 @@ switch: text_sensor: - platform: ld2450 + id: ld2450_textsensor ld2450_id: ld2450_radar version: name: LD2450 Firmware @@ -118,6 +123,7 @@ text_sensor: number: - platform: ld2450 + id: ld2450_number ld2450_id: ld2450_radar presence_timeout: name: Timeout @@ -151,6 +157,7 @@ number: select: - platform: ld2450 + id: ld2450_select ld2450_id: ld2450_radar baud_rate: name: Baud Rate From a1727a8901f6e666363bad71c548ec93760f51ef Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 7 Jan 2026 00:41:24 -0800 Subject: [PATCH 0082/2030] [espnow] fix channel validation (#13057) --- esphome/components/espnow/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index cc2c02d4c0..1f5ca1104a 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -66,11 +66,17 @@ CONF_WAIT_FOR_SENT = "wait_for_sent" MAX_ESPNOW_PACKET_SIZE = 250 # Maximum size of the payload in bytes +def validate_channel(value): + if value is None: + raise cv.Invalid("channel is required if wifi is not configured") + return wifi.validate_channel(value) + + CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(ESPNowComponent), - cv.OnlyWithout(CONF_CHANNEL, CONF_WIFI): wifi.validate_channel, + cv.OnlyWithout(CONF_CHANNEL, CONF_WIFI): validate_channel, cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, cv.Optional(CONF_AUTO_ADD_PEER, default=False): cv.boolean, cv.Optional(CONF_PEERS): cv.ensure_list(cv.mac_address), From dca8def0f2c41420051f1c976f8c0c1b0ac94708 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:16:55 -0500 Subject: [PATCH 0083/2030] [seeed_mr24hpc1] Add ifdef guards for conditional entity types (#13147) Co-authored-by: Claude Opus 4.5 --- .../seeed_mr24hpc1/seeed_mr24hpc1.cpp | 432 +++++++++++------- 1 file changed, 273 insertions(+), 159 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 4c0416d727..08d83f9390 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -64,15 +64,21 @@ void MR24HPC1Component::dump_config() { void MR24HPC1Component::setup() { this->check_uart_settings(115200); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); // Zero out the custom mode } +#endif +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(0); } +#endif +#ifdef USE_TEXT_SENSOR if (this->custom_mode_end_text_sensor_ != nullptr) { this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); } +#endif this->set_custom_end_mode(); this->poll_time_base_func_check_ = true; this->check_dev_inf_sign_ = true; @@ -353,6 +359,7 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { // Parses data frames related to product information void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { +#ifdef USE_TEXT_SENSOR uint16_t product_len = encode_uint16(data[FRAME_COMMAND_WORD_INDEX + 1], data[FRAME_COMMAND_WORD_INDEX + 2]); if (data[FRAME_COMMAND_WORD_INDEX] == COMMAND_PRODUCT_MODE) { if ((this->product_model_text_sensor_ != nullptr) && (product_len < PRODUCT_BUF_MAX_SIZE)) { @@ -388,109 +395,153 @@ void MR24HPC1Component::r24_frame_parse_product_information_(uint8_t *data) { ESP_LOGD(TAG, "Reply: get firmwareVersion error!"); } } +#endif } // Parsing the underlying open parameters void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *data) { - if (data[FRAME_COMMAND_WORD_INDEX] == 0x00) { - if (this->underlying_open_function_switch_ != nullptr) { - this->underlying_open_function_switch_->publish_state( - data[FRAME_DATA_INDEX]); // Underlying Open Parameter Switch Status Updates - } - if (data[FRAME_DATA_INDEX]) { - this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; - } else { - this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; - } - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { - if (this->custom_spatial_static_value_sensor_ != nullptr) { - this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } - if (this->custom_presence_of_detection_sensor_ != nullptr) { - this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f); - } - if (this->custom_spatial_motion_value_sensor_ != nullptr) { - this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]); - } - if (this->custom_motion_distance_sensor_ != nullptr) { - this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f); - } - if (this->custom_motion_speed_sensor_ != nullptr) { - this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f); - } - } else if ((data[FRAME_COMMAND_WORD_INDEX] == 0x06) || (data[FRAME_COMMAND_WORD_INDEX] == 0x86)) { - // none:0x00 close_to:0x01 far_away:0x02 - if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { - this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); - } - } else if ((this->movement_signs_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x07) || (data[FRAME_COMMAND_WORD_INDEX] == 0x87))) { - this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->existence_threshold_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { - this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->motion_threshold_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x09) || (data[FRAME_COMMAND_WORD_INDEX] == 0x89))) { - this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->existence_boundary_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) { - if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { - this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); - } - } else if ((this->motion_boundary_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) { - if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { - this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); - } - } else if ((this->motion_trigger_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) { - uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - this->motion_trigger_number_->publish_state(motion_trigger_time); - } else if ((this->motion_to_rest_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0d) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8d))) { - uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - this->motion_to_rest_number_->publish_state(move_to_rest_time); - } else if ((this->custom_unman_time_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0e) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8e))) { - uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], - data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); - float custom_unmanned_time = enter_unmanned_time / 1000.0; - this->custom_unman_time_number_->publish_state(custom_unmanned_time); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x80) { - if (data[FRAME_DATA_INDEX]) { - this->s_output_info_switch_flag_ = OUTPUT_SWITCH_ON; - } else { - this->s_output_info_switch_flag_ = OUTPUT_SWTICH_OFF; - } - if (this->underlying_open_function_switch_ != nullptr) { - this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]); - } - } else if ((this->custom_spatial_static_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x81)) { - this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->custom_spatial_motion_value_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x82)) { - this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->custom_presence_of_detection_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x83)) { - this->custom_presence_of_detection_sensor_->publish_state( - S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); - } else if ((this->custom_motion_distance_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x84)) { - this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f); - } else if ((this->custom_motion_speed_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x85)) { - this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f); + switch (data[FRAME_COMMAND_WORD_INDEX]) { + case 0x00: + case 0x80: +#ifdef USE_SWITCH + if (this->underlying_open_function_switch_ != nullptr) { + this->underlying_open_function_switch_->publish_state(data[FRAME_DATA_INDEX]); + } +#endif + this->s_output_info_switch_flag_ = data[FRAME_DATA_INDEX] ? OUTPUT_SWITCH_ON : OUTPUT_SWTICH_OFF; + break; +#ifdef USE_SENSOR + case 0x01: + if (this->custom_spatial_static_value_sensor_ != nullptr) { + this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + if (this->custom_presence_of_detection_sensor_ != nullptr) { + this->custom_presence_of_detection_sensor_->publish_state(data[FRAME_DATA_INDEX + 1] * 0.5f); + } + if (this->custom_spatial_motion_value_sensor_ != nullptr) { + this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX + 2]); + } + if (this->custom_motion_distance_sensor_ != nullptr) { + this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX + 3] * 0.5f); + } + if (this->custom_motion_speed_sensor_ != nullptr) { + this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX + 4] - 10) * 0.5f); + } + break; + case 0x07: + case 0x87: + if (this->movement_signs_sensor_ != nullptr) { + this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x81: + if (this->custom_spatial_static_value_sensor_ != nullptr) { + this->custom_spatial_static_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x82: + if (this->custom_spatial_motion_value_sensor_ != nullptr) { + this->custom_spatial_motion_value_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x83: + if (this->custom_presence_of_detection_sensor_ != nullptr) { + this->custom_presence_of_detection_sensor_->publish_state( + S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); + } + break; + case 0x84: + if (this->custom_motion_distance_sensor_ != nullptr) { + this->custom_motion_distance_sensor_->publish_state(data[FRAME_DATA_INDEX] * 0.5f); + } + break; + case 0x85: + if (this->custom_motion_speed_sensor_ != nullptr) { + this->custom_motion_speed_sensor_->publish_state((data[FRAME_DATA_INDEX] - 10) * 0.5f); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x06: + case 0x86: + // none:0x00 close_to:0x01 far_away:0x02 + if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_NUMBER + case 0x08: + case 0x88: + if (this->existence_threshold_number_ != nullptr) { + this->existence_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x09: + case 0x89: + if (this->motion_threshold_number_ != nullptr) { + this->motion_threshold_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; + case 0x0c: + case 0x8c: + if (this->motion_trigger_number_ != nullptr) { + uint32_t motion_trigger_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->motion_trigger_number_->publish_state(motion_trigger_time); + } + break; + case 0x0d: + case 0x8d: + if (this->motion_to_rest_number_ != nullptr) { + uint32_t move_to_rest_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->motion_to_rest_number_->publish_state(move_to_rest_time); + } + break; + case 0x0e: + case 0x8e: + if (this->custom_unman_time_number_ != nullptr) { + uint32_t enter_unmanned_time = encode_uint32(data[FRAME_DATA_INDEX], data[FRAME_DATA_INDEX + 1], + data[FRAME_DATA_INDEX + 2], data[FRAME_DATA_INDEX + 3]); + this->custom_unman_time_number_->publish_state(enter_unmanned_time / 1000.0f); + } + break; +#endif +#ifdef USE_SELECT + case 0x0a: + case 0x8a: + if (this->existence_boundary_select_ != nullptr) { + if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { + this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); + } + } + break; + case 0x0b: + case 0x8b: + if (this->motion_boundary_select_ != nullptr) { + if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) { + this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1); + } + } + break; +#endif } } void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) { switch (data[FRAME_CONTROL_WORD_INDEX]) { case 0x01: { - if ((this->heartbeat_state_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x01)) { - this->heartbeat_state_text_sensor_->publish_state("Equipment Normal"); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) { + if (data[FRAME_COMMAND_WORD_INDEX] == 0x02) { ESP_LOGD(TAG, "Reply: query restart packet"); - } else if (this->heartbeat_state_text_sensor_ != nullptr) { - this->heartbeat_state_text_sensor_->publish_state("Equipment Abnormal"); + break; } +#ifdef USE_TEXT_SENSOR + if (this->heartbeat_state_text_sensor_ != nullptr) { + this->heartbeat_state_text_sensor_->publish_state( + data[FRAME_COMMAND_WORD_INDEX] == 0x01 ? "Equipment Normal" : "Equipment Abnormal"); + } +#endif } break; case 0x02: { this->r24_frame_parse_product_information_(data); @@ -511,86 +562,123 @@ void MR24HPC1Component::r24_parse_data_frame_(uint8_t *data, uint8_t len) { } void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) { - if (data[FRAME_COMMAND_WORD_INDEX] == 0x01) { - ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) { - if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { - this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); - } else { - ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); - } - } else if ((this->sensitivity_number_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x08) || (data[FRAME_COMMAND_WORD_INDEX] == 0x88))) { - // 1-3 - this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x09) { - // 1-4 - if (this->custom_mode_num_sensor_ != nullptr) { - this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } - if (this->custom_mode_number_ != nullptr) { - this->custom_mode_number_->publish_state(0); - } - if (this->custom_mode_end_text_sensor_ != nullptr) { - this->custom_mode_end_text_sensor_->publish_state("Setup in progress"); - } - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x81) { - ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) { - if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { - this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); - } else { - ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); - } - } else if ((this->custom_mode_end_text_sensor_ != nullptr) && (data[FRAME_COMMAND_WORD_INDEX] == 0x0A)) { - this->custom_mode_end_text_sensor_->publish_state("Set Success!"); - } else if (data[FRAME_COMMAND_WORD_INDEX] == 0x89) { - if (data[FRAME_DATA_INDEX] == 0) { - if (this->custom_mode_end_text_sensor_ != nullptr) { - this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); + switch (data[FRAME_COMMAND_WORD_INDEX]) { + case 0x01: + case 0x81: + ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]); + break; + case 0x09: +#ifdef USE_SENSOR + if (this->custom_mode_num_sensor_ != nullptr) { + this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); } +#endif +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif +#ifdef USE_TEXT_SENSOR + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Setup in progress"); + } +#endif + break; + case 0x89: +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); } - } else { - if (this->custom_mode_num_sensor_ != nullptr) { - this->custom_mode_num_sensor_->publish_state(data[FRAME_DATA_INDEX]); +#endif + if (data[FRAME_DATA_INDEX] == 0) { +#ifdef USE_TEXT_SENSOR + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Not in custom mode"); + } +#endif +#ifdef USE_NUMBER + if (this->custom_mode_number_ != nullptr) { + this->custom_mode_number_->publish_state(0); + } +#endif } - } - } else { - ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; +#ifdef USE_SELECT + case 0x07: + case 0x87: + if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) { + this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]); + } else { + ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_NUMBER + case 0x08: + case 0x88: + if (this->sensitivity_number_ != nullptr) { + this->sensitivity_number_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x0A: + if (this->custom_mode_end_text_sensor_ != nullptr) { + this->custom_mode_end_text_sensor_->publish_state("Set Success!"); + } + break; +#endif + default: + ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; } } void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) { - if ((this->has_target_binary_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x01) || (data[FRAME_COMMAND_WORD_INDEX] == 0x81))) { - this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); - } else if ((this->motion_status_text_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x02) || (data[FRAME_COMMAND_WORD_INDEX] == 0x82))) { - if (data[FRAME_DATA_INDEX] < 3) { - this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]); - } - } else if ((this->movement_signs_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x03) || (data[FRAME_COMMAND_WORD_INDEX] == 0x83))) { - this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); - } else if ((this->unman_time_select_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) { - // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08 - if (data[FRAME_DATA_INDEX] < 9) { - this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]); - } - } else if ((this->keep_away_text_sensor_ != nullptr) && - ((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) { - // none:0x00 close_to:0x01 far_away:0x02 - if (data[FRAME_DATA_INDEX] < 3) { - this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); - } - } else { - ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + switch (data[FRAME_COMMAND_WORD_INDEX]) { +#ifdef USE_BINARY_SENSOR + case 0x01: + case 0x81: + if (this->has_target_binary_sensor_ != nullptr) { + this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_SENSOR + case 0x03: + case 0x83: + if (this->movement_signs_sensor_ != nullptr) { + this->movement_signs_sensor_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif +#ifdef USE_TEXT_SENSOR + case 0x02: + case 0x82: + if ((this->motion_status_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->motion_status_text_sensor_->publish_state(S_MOTION_STATUS_STR[data[FRAME_DATA_INDEX]]); + } + break; + case 0x0B: + case 0x8B: + // none:0x00 close_to:0x01 far_away:0x02 + if ((this->keep_away_text_sensor_ != nullptr) && (data[FRAME_DATA_INDEX] < 3)) { + this->keep_away_text_sensor_->publish_state(S_KEEP_AWAY_STR[data[FRAME_DATA_INDEX]]); + } + break; +#endif +#ifdef USE_SELECT + case 0x0A: + case 0x8A: + // none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08 + if ((this->unman_time_select_ != nullptr) && (data[FRAME_DATA_INDEX] < 9)) { + this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]); + } + break; +#endif + default: + ESP_LOGD(TAG, "[%s] No found COMMAND_WORD(%02X) in Frame", __FUNCTION__, data[FRAME_COMMAND_WORD_INDEX]); + break; } } @@ -695,12 +783,15 @@ void MR24HPC1Component::set_underlying_open_function(bool enable) { } else { this->send_query_(UNDERLYING_SWITCH_OFF, sizeof(UNDERLYING_SWITCH_OFF)); } +#ifdef USE_TEXT_SENSOR if (this->keep_away_text_sensor_ != nullptr) { this->keep_away_text_sensor_->publish_state(""); } if (this->motion_status_text_sensor_ != nullptr) { this->motion_status_text_sensor_->publish_state(""); } +#endif +#ifdef USE_SENSOR if (this->custom_spatial_static_value_sensor_ != nullptr) { this->custom_spatial_static_value_sensor_->publish_state(NAN); } @@ -716,6 +807,7 @@ void MR24HPC1Component::set_underlying_open_function(bool enable) { if (this->custom_motion_speed_sensor_ != nullptr) { this->custom_motion_speed_sensor_->publish_state(NAN); } +#endif } void MR24HPC1Component::set_scene_mode(uint8_t value) { @@ -723,12 +815,16 @@ void MR24HPC1Component::set_scene_mode(uint8_t value) { uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x07, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); this->send_query_(send_data, send_data_len); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif +#ifdef USE_SENSOR if (this->custom_mode_num_sensor_ != nullptr) { this->custom_mode_num_sensor_->publish_state(0); } +#endif this->get_scene_mode(); this->get_sensitivity(); this->get_custom_mode(); @@ -768,9 +864,11 @@ void MR24HPC1Component::set_unman_time(uint8_t value) { void MR24HPC1Component::set_custom_mode(uint8_t mode) { if (mode == 0) { this->set_custom_end_mode(); // Equivalent to end setting +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); } +#endif return; } uint8_t send_data_len = 10; @@ -793,9 +891,11 @@ void MR24HPC1Component::set_custom_end_mode() { uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x05, 0x0a, 0x00, 0x01, 0x0F, 0xCB, 0x54, 0x43}; this->send_query_(send_data, send_data_len); +#ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); // Clear setpoints } +#endif this->get_existence_boundary(); this->get_motion_boundary(); this->get_existence_threshold(); @@ -809,8 +909,10 @@ void MR24HPC1Component::set_custom_end_mode() { } void MR24HPC1Component::set_existence_boundary(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0A, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -819,8 +921,10 @@ void MR24HPC1Component::set_existence_boundary(uint8_t value) { } void MR24HPC1Component::set_motion_boundary(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x0B, 0x00, 0x01, (uint8_t) (value + 1), 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -829,8 +933,10 @@ void MR24HPC1Component::set_motion_boundary(uint8_t value) { } void MR24HPC1Component::set_existence_threshold(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x08, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -839,8 +945,10 @@ void MR24HPC1Component::set_existence_threshold(uint8_t value) { } void MR24HPC1Component::set_motion_threshold(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 10; uint8_t send_data[10] = {0x53, 0x59, 0x08, 0x09, 0x00, 0x01, value, 0x00, 0x54, 0x43}; send_data[7] = get_frame_crc_sum(send_data, send_data_len); @@ -849,8 +957,10 @@ void MR24HPC1Component::set_motion_threshold(uint8_t value) { } void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t send_data_len = 13; uint8_t send_data[13] = {0x53, 0x59, 0x08, 0x0C, 0x00, 0x04, 0x00, 0x00, 0x00, value, 0x00, 0x54, 0x43}; send_data[10] = get_frame_crc_sum(send_data, send_data_len); @@ -859,8 +969,10 @@ void MR24HPC1Component::set_motion_trigger_time(uint8_t value) { } void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint8_t h8_num = (value >> 8) & 0xff; uint8_t l8_num = value & 0xff; uint8_t send_data_len = 13; @@ -871,8 +983,10 @@ void MR24HPC1Component::set_motion_to_rest_time(uint16_t value) { } void MR24HPC1Component::set_custom_unman_time(uint16_t value) { +#ifdef USE_SENSOR if ((this->custom_mode_num_sensor_ != nullptr) && (this->custom_mode_num_sensor_->state == 0)) return; // You'll have to check that you're in custom mode to set it up +#endif uint32_t value_ms = value * 1000; uint8_t h24_num = (value_ms >> 24) & 0xff; uint8_t h16_num = (value_ms >> 16) & 0xff; From dede47477b50e8fef8c85e196e0c87eaf828bbef Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:09:54 -0500 Subject: [PATCH 0084/2030] [ltr_als_ps] Remove incorrect device_class from count sensors (#13167) Co-authored-by: Claude Opus 4.5 --- esphome/components/ltr_als_ps/sensor.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py index 27263d0bff..0dbcff1bfb 100644 --- a/esphome/components/ltr_als_ps/sensor.py +++ b/esphome/components/ltr_als_ps/sensor.py @@ -16,7 +16,6 @@ from esphome.const import ( CONF_REPEAT, CONF_TRIGGER_ID, CONF_TYPE, - DEVICE_CLASS_DISTANCE, DEVICE_CLASS_ILLUMINANCE, ICON_BRIGHTNESS_5, ICON_BRIGHTNESS_6, @@ -169,7 +168,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_5, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -179,7 +177,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_7, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -189,7 +186,6 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_COUNTS, icon=ICON_PROXIMITY, accuracy_decimals=0, - device_class=DEVICE_CLASS_DISTANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, @@ -198,7 +194,6 @@ CONFIG_SCHEMA = cv.All( sensor.sensor_schema( icon=ICON_GAIN, accuracy_decimals=0, - device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), key=CONF_NAME, From 3911991de2254fe77c2b1381f67612a14c262f59 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:10:15 -0500 Subject: [PATCH 0085/2030] [packet_transport] Fix packet size check to account for round4 padding (#13165) Co-authored-by: Claude Opus 4.5 --- esphome/components/packet_transport/packet_transport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index da7f5f8bff..8ae2f759d0 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -269,7 +269,7 @@ void PacketTransport::flush_() { void PacketTransport::add_binary_data_(uint8_t key, const char *id, bool data) { auto len = 1 + 1 + 1 + strlen(id); - if (len + this->header_.size() + this->data_.size() > this->get_max_packet_size()) { + if (round4(this->header_.size()) + round4(this->data_.size() + len) > this->get_max_packet_size()) { this->flush_(); this->init_data_(); } @@ -284,7 +284,7 @@ void PacketTransport::add_data_(uint8_t key, const char *id, float data) { void PacketTransport::add_data_(uint8_t key, const char *id, uint32_t data) { auto len = 4 + 1 + 1 + strlen(id); - if (len + this->header_.size() + this->data_.size() > this->get_max_packet_size()) { + if (round4(this->header_.size()) + round4(this->data_.size() + len) > this->get_max_packet_size()) { this->flush_(); this->init_data_(); } From 9504e92458176808313087c7a0f85375fc3d33d5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 12 Jan 2026 18:06:41 -0500 Subject: [PATCH 0086/2030] [remote_transmitter] Fix ESP8266 timing by using busy loop (#13172) Co-authored-by: Claude --- .../components/remote_transmitter/remote_transmitter.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/esphome/components/remote_transmitter/remote_transmitter.cpp b/esphome/components/remote_transmitter/remote_transmitter.cpp index 576143bcbc..f20789fb9f 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter.cpp @@ -40,13 +40,10 @@ void RemoteTransmitterComponent::await_target_time_() { if (this->target_time_ == 0) { this->target_time_ = current_time; } else if ((int32_t) (this->target_time_ - current_time) > 0) { -#if defined(USE_LIBRETINY) || defined(USE_RP2040) - // busy loop is required for libretiny and rp2040 as interrupts are disabled + // busy loop is required as interrupts are disabled and delayMicroseconds() + // may not work correctly in interrupt-disabled contexts on all platforms while ((int32_t) (this->target_time_ - micros()) > 0) ; -#else - delayMicroseconds(this->target_time_ - current_time); -#endif } } From d6507ce329f0fef53b76fbfcb0bcb3554a9627cc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 12 Jan 2026 20:55:40 -1000 Subject: [PATCH 0087/2030] [esphome] Fix OTA backend abort not being called on error (#13182) --- esphome/components/esphome/ota/ota_esphome.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 6cfd543553..175bc40f81 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -395,12 +395,14 @@ void ESPHomeOTAComponent::handle_data_() { error: this->write_byte_(static_cast(error_code)); - this->cleanup_connection_(); + // Abort backend before cleanup - cleanup_connection_() destroys the backend if (this->backend_ != nullptr && update_started) { this->backend_->abort(); } + this->cleanup_connection_(); + this->status_momentary_error("err", 5000); #ifdef USE_OTA_STATE_CALLBACK this->state_callback_.call(ota::OTA_ERROR, 0.0f, static_cast(error_code)); From f4c17e15ea4490c644361ed4137e892a6bbaa664 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 13 Jan 2026 11:01:21 -0500 Subject: [PATCH 0088/2030] Bump version to 2025.12.6 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 079606c501..a23e21dd0d 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2025.12.5 +PROJECT_NUMBER = 2025.12.6 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index d1a7104ca4..6771b9f265 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2025.12.5" +__version__ = "2025.12.6" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 7abb374f2a701f2d6a2aa0a7b7fe0fc78949784f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 08:04:33 -1000 Subject: [PATCH 0089/2030] [improv_serial] Use stack buffers for webserver URL formatting (#13175) --- .../components/improv_serial/improv_serial_component.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index 17d630fe83..b4d9943955 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -193,8 +193,12 @@ std::vector ImprovSerialComponent::build_rpc_settings_response_(improv: #ifdef USE_WEBSERVER for (auto &ip : wifi::global_wifi_component->wifi_sta_ip_addresses()) { if (ip.is_ip4()) { - std::string webserver_url = "http://" + ip.str() + ":" + to_string(USE_WEBSERVER_PORT); - urls.push_back(webserver_url); + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + ip.str_to(ip_buf); + // "http://" (7) + IP (40) + ":" (1) + port (5) + null (1) = 54 + char webserver_url[7 + network::IP_ADDRESS_BUFFER_SIZE + 1 + 5 + 1]; + snprintf(webserver_url, sizeof(webserver_url), "http://%s:%u", ip_buf, USE_WEBSERVER_PORT); + urls.emplace_back(webserver_url); break; } } From 7fed9144a675c76437d45aa7d24cc901bc31036b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 08:04:48 -1000 Subject: [PATCH 0090/2030] [api] Use stack buffer for VERY_VERBOSE proto message dumps (#13176) --- esphome/components/api/api_connection.cpp | 3 +- esphome/components/api/api_pb2.h | 296 ++++++------ esphome/components/api/api_pb2_dump.cpp | 505 ++++++++++++++------- esphome/components/api/api_pb2_service.cpp | 124 ++--- esphome/components/api/api_pb2_service.h | 6 +- esphome/components/api/proto.cpp | 8 - esphome/components/api/proto.h | 60 ++- script/api_protobuf/api_protobuf.py | 80 ++-- 8 files changed, 661 insertions(+), 421 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 65f8c1a8cc..ea18d06511 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -305,7 +305,8 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess #ifdef HAS_PROTO_MESSAGE_DUMP // If in log-only mode, just log and return if (conn->flags_.log_only_mode) { - conn->log_send_message_(msg.message_name(), msg.dump()); + DumpBuffer dump_buf; + conn->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); return 1; // Return non-zero to indicate "success" for logging } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 0ab38b8b85..cf6c65f285 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -362,7 +362,7 @@ class HelloRequest final : public ProtoDecodableMessage { uint32_t api_version_major{0}; uint32_t api_version_minor{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -383,7 +383,7 @@ class HelloResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -396,7 +396,7 @@ class DisconnectRequest final : public ProtoMessage { const char *message_name() const override { return "disconnect_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -409,7 +409,7 @@ class DisconnectResponse final : public ProtoMessage { const char *message_name() const override { return "disconnect_response"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -422,7 +422,7 @@ class PingRequest final : public ProtoMessage { const char *message_name() const override { return "ping_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -435,7 +435,7 @@ class PingResponse final : public ProtoMessage { const char *message_name() const override { return "ping_response"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -448,7 +448,7 @@ class DeviceInfoRequest final : public ProtoMessage { const char *message_name() const override { return "device_info_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -461,7 +461,7 @@ class AreaInfo final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -476,7 +476,7 @@ class DeviceInfo final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -541,7 +541,7 @@ class DeviceInfoResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -554,7 +554,7 @@ class ListEntitiesRequest final : public ProtoMessage { const char *message_name() const override { return "list_entities_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -567,7 +567,7 @@ class ListEntitiesDoneResponse final : public ProtoMessage { const char *message_name() const override { return "list_entities_done_response"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -580,7 +580,7 @@ class SubscribeStatesRequest final : public ProtoMessage { const char *message_name() const override { return "subscribe_states_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -598,7 +598,7 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -615,7 +615,7 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -637,7 +637,7 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -655,7 +655,7 @@ class CoverStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -673,7 +673,7 @@ class CoverCommandRequest final : public CommandProtoMessage { float tilt{0.0f}; bool stop{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -697,7 +697,7 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -717,7 +717,7 @@ class FanStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -740,7 +740,7 @@ class FanCommandRequest final : public CommandProtoMessage { bool has_preset_mode{false}; StringRef preset_mode{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -764,7 +764,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -791,7 +791,7 @@ class LightStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -830,7 +830,7 @@ class LightCommandRequest final : public CommandProtoMessage { bool has_effect{false}; StringRef effect{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -855,7 +855,7 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -872,7 +872,7 @@ class SensorStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -891,7 +891,7 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -907,7 +907,7 @@ class SwitchStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -921,7 +921,7 @@ class SwitchCommandRequest final : public CommandProtoMessage { #endif bool state{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -941,7 +941,7 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -958,7 +958,7 @@ class TextSensorStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -974,7 +974,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage { enums::LogLevel level{}; bool dump_config{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -997,7 +997,7 @@ class SubscribeLogsResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1013,7 +1013,7 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage { const uint8_t *key{nullptr}; uint16_t key_len{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1030,7 +1030,7 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1045,7 +1045,7 @@ class SubscribeHomeassistantServicesRequest final : public ProtoMessage { const char *message_name() const override { return "subscribe_homeassistant_services_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1057,7 +1057,7 @@ class HomeassistantServiceMap final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1086,7 +1086,7 @@ class HomeassistantActionRequest final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1108,7 +1108,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { uint16_t response_data_len{0}; #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1125,7 +1125,7 @@ class SubscribeHomeAssistantStatesRequest final : public ProtoMessage { const char *message_name() const override { return "subscribe_home_assistant_states_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1143,7 +1143,7 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1159,7 +1159,7 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage { StringRef state{}; StringRef attribute{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1174,7 +1174,7 @@ class GetTimeRequest final : public ProtoMessage { const char *message_name() const override { return "get_time_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1189,7 +1189,7 @@ class GetTimeResponse final : public ProtoDecodableMessage { uint32_t epoch_seconds{0}; StringRef timezone{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1204,7 +1204,7 @@ class ListEntitiesServicesArgument final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1223,7 +1223,7 @@ class ListEntitiesServicesResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1241,7 +1241,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { FixedVector string_array{}; void decode(const uint8_t *buffer, size_t length) override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1266,7 +1266,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { #endif void decode(const uint8_t *buffer, size_t length) override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1293,7 +1293,7 @@ class ExecuteServiceResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1310,7 +1310,7 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1332,7 +1332,7 @@ class CameraImageResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1347,7 +1347,7 @@ class CameraImageRequest final : public ProtoDecodableMessage { bool single{false}; bool stream{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1383,7 +1383,7 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1411,7 +1411,7 @@ class ClimateStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1444,7 +1444,7 @@ class ClimateCommandRequest final : public CommandProtoMessage { bool has_target_humidity{false}; float target_humidity{0.0f}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1469,7 +1469,7 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1490,7 +1490,7 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1509,7 +1509,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage { float target_temperature_low{0.0f}; float target_temperature_high{0.0f}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1534,7 +1534,7 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1551,7 +1551,7 @@ class NumberStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1565,7 +1565,7 @@ class NumberCommandRequest final : public CommandProtoMessage { #endif float state{0.0f}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1585,7 +1585,7 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1602,7 +1602,7 @@ class SelectStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1616,7 +1616,7 @@ class SelectCommandRequest final : public CommandProtoMessage { #endif StringRef state{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1639,7 +1639,7 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1655,7 +1655,7 @@ class SirenStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1676,7 +1676,7 @@ class SirenCommandRequest final : public CommandProtoMessage { bool has_volume{false}; float volume{0.0f}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1700,7 +1700,7 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1716,7 +1716,7 @@ class LockStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1732,7 +1732,7 @@ class LockCommandRequest final : public CommandProtoMessage { bool has_code{false}; StringRef code{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1753,7 +1753,7 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1766,7 +1766,7 @@ class ButtonCommandRequest final : public CommandProtoMessage { const char *message_name() const override { return "button_command_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1785,7 +1785,7 @@ class MediaPlayerSupportedFormat final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1803,7 +1803,7 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1821,7 +1821,7 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1842,7 +1842,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage { bool has_announcement{false}; bool announcement{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1861,7 +1861,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes #endif uint32_t flags{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1877,7 +1877,7 @@ class BluetoothLERawAdvertisement final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1894,7 +1894,7 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1911,7 +1911,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage { bool has_address_type{false}; uint32_t address_type{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1931,7 +1931,7 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1945,7 +1945,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage { #endif uint64_t address{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1959,7 +1959,7 @@ class BluetoothGATTDescriptor final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1974,7 +1974,7 @@ class BluetoothGATTCharacteristic final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -1988,7 +1988,7 @@ class BluetoothGATTService final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2005,7 +2005,7 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2021,7 +2021,7 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2036,7 +2036,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage { uint64_t address{0}; uint32_t handle{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2060,7 +2060,7 @@ class BluetoothGATTReadResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2078,7 +2078,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage { const uint8_t *data{nullptr}; uint16_t data_len{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2095,7 +2095,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { uint64_t address{0}; uint32_t handle{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2113,7 +2113,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { const uint8_t *data{nullptr}; uint16_t data_len{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2131,7 +2131,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { uint32_t handle{0}; bool enable{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2155,7 +2155,7 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2168,7 +2168,7 @@ class SubscribeBluetoothConnectionsFreeRequest final : public ProtoMessage { const char *message_name() const override { return "subscribe_bluetooth_connections_free_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2186,7 +2186,7 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2204,7 +2204,7 @@ class BluetoothGATTErrorResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2221,7 +2221,7 @@ class BluetoothGATTWriteResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2238,7 +2238,7 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2256,7 +2256,7 @@ class BluetoothDevicePairingResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2274,7 +2274,7 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2287,7 +2287,7 @@ class UnsubscribeBluetoothLEAdvertisementsRequest final : public ProtoMessage { const char *message_name() const override { return "unsubscribe_bluetooth_le_advertisements_request"; } #endif #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2305,7 +2305,7 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2323,7 +2323,7 @@ class BluetoothScannerStateResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2337,7 +2337,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage { #endif enums::BluetoothScannerMode mode{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2355,7 +2355,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage { bool subscribe{false}; uint32_t flags{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2369,7 +2369,7 @@ class VoiceAssistantAudioSettings final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2389,7 +2389,7 @@ class VoiceAssistantRequest final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2404,7 +2404,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage { uint32_t port{0}; bool error{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2415,7 +2415,7 @@ class VoiceAssistantEventData final : public ProtoDecodableMessage { StringRef name{}; StringRef value{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2431,7 +2431,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage { enums::VoiceAssistantEvent event_type{}; std::vector data{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2451,7 +2451,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2472,7 +2472,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { uint32_t seconds_left{0}; bool is_active{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2491,7 +2491,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { StringRef preannounce_media_id{}; bool start_conversation{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2509,7 +2509,7 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2522,7 +2522,7 @@ class VoiceAssistantWakeWord final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2537,7 +2537,7 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage { StringRef model_hash{}; StringRef url{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2553,7 +2553,7 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { #endif std::vector external_wake_words{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2572,7 +2572,7 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2586,7 +2586,7 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage { #endif std::vector active_wake_words{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2607,7 +2607,7 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2623,7 +2623,7 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2638,7 +2638,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage { enums::AlarmControlPanelStateCommand command{}; StringRef code{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2662,7 +2662,7 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2679,7 +2679,7 @@ class TextStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2693,7 +2693,7 @@ class TextCommandRequest final : public CommandProtoMessage { #endif StringRef state{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2713,7 +2713,7 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2732,7 +2732,7 @@ class DateStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2748,7 +2748,7 @@ class DateCommandRequest final : public CommandProtoMessage { uint32_t month{0}; uint32_t day{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2767,7 +2767,7 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2786,7 +2786,7 @@ class TimeStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2802,7 +2802,7 @@ class TimeCommandRequest final : public CommandProtoMessage { uint32_t minute{0}; uint32_t second{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2823,7 +2823,7 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2839,7 +2839,7 @@ class EventResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2860,7 +2860,7 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2877,7 +2877,7 @@ class ValveStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2893,7 +2893,7 @@ class ValveCommandRequest final : public CommandProtoMessage { float position{0.0f}; bool stop{false}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2912,7 +2912,7 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2929,7 +2929,7 @@ class DateTimeStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2943,7 +2943,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage { #endif uint32_t epoch_seconds{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2963,7 +2963,7 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -2987,7 +2987,7 @@ class UpdateStateResponse final : public StateResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3001,7 +3001,7 @@ class UpdateCommandRequest final : public CommandProtoMessage { #endif enums::UpdateCommand command{}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3022,7 +3022,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3041,7 +3041,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3061,7 +3061,7 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3085,7 +3085,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { uint16_t timings_length_{0}; uint16_t timings_count_{0}; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: @@ -3108,7 +3108,7 @@ class InfraredRFReceiveEvent final : public ProtoMessage { void encode(ProtoWriteBuffer buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP - void dump_to(std::string &out) const override; + const char *dump_to(DumpBuffer &out) const override; #endif protected: diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 9550ecbcdd..29121f05e0 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -10,7 +10,7 @@ namespace esphome::api { // Helper function to append a quoted string, handling empty StringRef -static inline void append_quoted_string(std::string &out, const StringRef &ref) { +static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { out.append(ref.c_str()); @@ -19,82 +19,88 @@ static inline void append_quoted_string(std::string &out, const StringRef &ref) } // Common helpers for dump_field functions -static inline void append_field_prefix(std::string &out, const char *field_name, int indent) { +static inline void append_field_prefix(DumpBuffer &out, const char *field_name, int indent) { out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(std::string &out, const char *str) { +static inline void append_with_newline(DumpBuffer &out, const char *str) { out.append(str); out.append("\n"); } +static inline void append_uint(DumpBuffer &out, uint32_t value) { + char buf[16]; + snprintf(buf, sizeof(buf), "%" PRIu32, value); + out.append(buf); +} + // RAII helper for message dump formatting class MessageDumpHelper { public: - MessageDumpHelper(std::string &out, const char *message_name) : out_(out) { + MessageDumpHelper(DumpBuffer &out, const char *message_name) : out_(out) { out_.append(message_name); out_.append(" {\n"); } ~MessageDumpHelper() { out_.append(" }"); } private: - std::string &out_; + DumpBuffer &out_; }; // Helper functions to reduce code duplication in dump methods -static void dump_field(std::string &out, const char *field_name, int32_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRId32, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, uint32_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRIu32, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, float value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%g", value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, uint64_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRIu64, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, bool value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append(YESNO(value)); out.append("\n"); } -static void dump_field(std::string &out, const char *field_name, const std::string &value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, const std::string &value, int indent = 2) { append_field_prefix(out, field_name, indent); - out.append("'").append(value).append("'"); + out.append("'").append(value.c_str()).append("'"); out.append("\n"); } -static void dump_field(std::string &out, const char *field_name, StringRef value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, StringRef value, int indent = 2) { append_field_prefix(out, field_name, indent); append_quoted_string(out, value); out.append("\n"); } -static void dump_field(std::string &out, const char *field_name, const char *value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, const char *value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append("'").append(value).append("'"); out.append("\n"); } -template static void dump_field(std::string &out, const char *field_name, T value, int indent = 2) { +template static void dump_field(DumpBuffer &out, const char *field_name, T value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append(proto_enum_to_string(value)); out.append("\n"); @@ -102,8 +108,7 @@ template static void dump_field(std::string &out, const char *field_ // Helper for bytes fields - uses stack buffer to avoid heap allocation // Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer -static void dump_bytes_field(std::string &out, const char *field_name, const uint8_t *data, size_t len, - int indent = 2) { +static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); @@ -743,40 +748,59 @@ template<> const char *proto_enum_to_string(enums: } #endif -void HelloRequest::dump_to(std::string &out) const { +const char *HelloRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HelloRequest"); dump_field(out, "client_info", this->client_info); dump_field(out, "api_version_major", this->api_version_major); dump_field(out, "api_version_minor", this->api_version_minor); + return out.c_str(); } -void HelloResponse::dump_to(std::string &out) const { +const char *HelloResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HelloResponse"); dump_field(out, "api_version_major", this->api_version_major); dump_field(out, "api_version_minor", this->api_version_minor); dump_field(out, "server_info", this->server_info); dump_field(out, "name", this->name); + return out.c_str(); +} +const char *DisconnectRequest::dump_to(DumpBuffer &out) const { + out.append("DisconnectRequest {}"); + return out.c_str(); +} +const char *DisconnectResponse::dump_to(DumpBuffer &out) const { + out.append("DisconnectResponse {}"); + return out.c_str(); +} +const char *PingRequest::dump_to(DumpBuffer &out) const { + out.append("PingRequest {}"); + return out.c_str(); +} +const char *PingResponse::dump_to(DumpBuffer &out) const { + out.append("PingResponse {}"); + return out.c_str(); +} +const char *DeviceInfoRequest::dump_to(DumpBuffer &out) const { + out.append("DeviceInfoRequest {}"); + return out.c_str(); } -void DisconnectRequest::dump_to(std::string &out) const { out.append("DisconnectRequest {}"); } -void DisconnectResponse::dump_to(std::string &out) const { out.append("DisconnectResponse {}"); } -void PingRequest::dump_to(std::string &out) const { out.append("PingRequest {}"); } -void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {}"); } -void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); } #ifdef USE_AREAS -void AreaInfo::dump_to(std::string &out) const { +const char *AreaInfo::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "AreaInfo"); dump_field(out, "area_id", this->area_id); dump_field(out, "name", this->name); + return out.c_str(); } #endif #ifdef USE_DEVICES -void DeviceInfo::dump_to(std::string &out) const { +const char *DeviceInfo::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DeviceInfo"); dump_field(out, "device_id", this->device_id); dump_field(out, "name", this->name); dump_field(out, "area_id", this->area_id); + return out.c_str(); } #endif -void DeviceInfoResponse::dump_to(std::string &out) const { +const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DeviceInfoResponse"); dump_field(out, "name", this->name); dump_field(out, "mac_address", this->mac_address); @@ -837,12 +861,22 @@ void DeviceInfoResponse::dump_to(std::string &out) const { #ifdef USE_ZWAVE_PROXY dump_field(out, "zwave_home_id", this->zwave_home_id); #endif + return out.c_str(); +} +const char *ListEntitiesRequest::dump_to(DumpBuffer &out) const { + out.append("ListEntitiesRequest {}"); + return out.c_str(); +} +const char *ListEntitiesDoneResponse::dump_to(DumpBuffer &out) const { + out.append("ListEntitiesDoneResponse {}"); + return out.c_str(); +} +const char *SubscribeStatesRequest::dump_to(DumpBuffer &out) const { + out.append("SubscribeStatesRequest {}"); + return out.c_str(); } -void ListEntitiesRequest::dump_to(std::string &out) const { out.append("ListEntitiesRequest {}"); } -void ListEntitiesDoneResponse::dump_to(std::string &out) const { out.append("ListEntitiesDoneResponse {}"); } -void SubscribeStatesRequest::dump_to(std::string &out) const { out.append("SubscribeStatesRequest {}"); } #ifdef USE_BINARY_SENSOR -void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { +const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesBinarySensorResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -857,8 +891,9 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void BinarySensorStateResponse::dump_to(std::string &out) const { +const char *BinarySensorStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BinarySensorStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -866,10 +901,11 @@ void BinarySensorStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_COVER -void ListEntitiesCoverResponse::dump_to(std::string &out) const { +const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesCoverResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -887,8 +923,9 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void CoverStateResponse::dump_to(std::string &out) const { +const char *CoverStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "CoverStateResponse"); dump_field(out, "key", this->key); dump_field(out, "position", this->position); @@ -897,8 +934,9 @@ void CoverStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void CoverCommandRequest::dump_to(std::string &out) const { +const char *CoverCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "CoverCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_position", this->has_position); @@ -909,10 +947,11 @@ void CoverCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_FAN -void ListEntitiesFanResponse::dump_to(std::string &out) const { +const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesFanResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -932,8 +971,9 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void FanStateResponse::dump_to(std::string &out) const { +const char *FanStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "FanStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -944,8 +984,9 @@ void FanStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void FanCommandRequest::dump_to(std::string &out) const { +const char *FanCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "FanCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_state", this->has_state); @@ -961,10 +1002,11 @@ void FanCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_LIGHT -void ListEntitiesLightResponse::dump_to(std::string &out) const { +const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesLightResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -985,8 +1027,9 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void LightStateResponse::dump_to(std::string &out) const { +const char *LightStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "LightStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -1004,8 +1047,9 @@ void LightStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void LightCommandRequest::dump_to(std::string &out) const { +const char *LightCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "LightCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_state", this->has_state); @@ -1037,10 +1081,11 @@ void LightCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_SENSOR -void ListEntitiesSensorResponse::dump_to(std::string &out) const { +const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesSensorResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1058,8 +1103,9 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SensorStateResponse::dump_to(std::string &out) const { +const char *SensorStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SensorStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -1067,10 +1113,11 @@ void SensorStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_SWITCH -void ListEntitiesSwitchResponse::dump_to(std::string &out) const { +const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesSwitchResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1085,26 +1132,29 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SwitchStateResponse::dump_to(std::string &out) const { +const char *SwitchStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SwitchStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SwitchCommandRequest::dump_to(std::string &out) const { +const char *SwitchCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SwitchCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_TEXT_SENSOR -void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { +const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesTextSensorResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1118,8 +1168,9 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void TextSensorStateResponse::dump_to(std::string &out) const { +const char *TextSensorStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "TextSensorStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -1127,38 +1178,45 @@ void TextSensorStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif -void SubscribeLogsRequest::dump_to(std::string &out) const { +const char *SubscribeLogsRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeLogsRequest"); dump_field(out, "level", static_cast(this->level)); dump_field(out, "dump_config", this->dump_config); + return out.c_str(); } -void SubscribeLogsResponse::dump_to(std::string &out) const { +const char *SubscribeLogsResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeLogsResponse"); dump_field(out, "level", static_cast(this->level)); dump_bytes_field(out, "message", this->message_ptr_, this->message_len_); + return out.c_str(); } #ifdef USE_API_NOISE -void NoiseEncryptionSetKeyRequest::dump_to(std::string &out) const { +const char *NoiseEncryptionSetKeyRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "NoiseEncryptionSetKeyRequest"); dump_bytes_field(out, "key", this->key, this->key_len); + return out.c_str(); } -void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const { +const char *NoiseEncryptionSetKeyResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "NoiseEncryptionSetKeyResponse"); dump_field(out, "success", this->success); + return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -void SubscribeHomeassistantServicesRequest::dump_to(std::string &out) const { +const char *SubscribeHomeassistantServicesRequest::dump_to(DumpBuffer &out) const { out.append("SubscribeHomeassistantServicesRequest {}"); + return out.c_str(); } -void HomeassistantServiceMap::dump_to(std::string &out) const { +const char *HomeassistantServiceMap::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HomeassistantServiceMap"); dump_field(out, "key", this->key); dump_field(out, "value", this->value); + return out.c_str(); } -void HomeassistantActionRequest::dump_to(std::string &out) const { +const char *HomeassistantActionRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HomeassistantActionRequest"); dump_field(out, "service", this->service); for (const auto &it : this->data) { @@ -1186,10 +1244,11 @@ void HomeassistantActionRequest::dump_to(std::string &out) const { #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON dump_field(out, "response_template", this->response_template); #endif + return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES -void HomeassistantActionResponse::dump_to(std::string &out) const { +const char *HomeassistantActionResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HomeassistantActionResponse"); dump_field(out, "call_id", this->call_id); dump_field(out, "success", this->success); @@ -1197,38 +1256,47 @@ void HomeassistantActionResponse::dump_to(std::string &out) const { #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); #endif + return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_STATES -void SubscribeHomeAssistantStatesRequest::dump_to(std::string &out) const { +const char *SubscribeHomeAssistantStatesRequest::dump_to(DumpBuffer &out) const { out.append("SubscribeHomeAssistantStatesRequest {}"); + return out.c_str(); } -void SubscribeHomeAssistantStateResponse::dump_to(std::string &out) const { +const char *SubscribeHomeAssistantStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeHomeAssistantStateResponse"); dump_field(out, "entity_id", this->entity_id); dump_field(out, "attribute", this->attribute); dump_field(out, "once", this->once); + return out.c_str(); } -void HomeAssistantStateResponse::dump_to(std::string &out) const { +const char *HomeAssistantStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HomeAssistantStateResponse"); dump_field(out, "entity_id", this->entity_id); dump_field(out, "state", this->state); dump_field(out, "attribute", this->attribute); + return out.c_str(); } #endif -void GetTimeRequest::dump_to(std::string &out) const { out.append("GetTimeRequest {}"); } -void GetTimeResponse::dump_to(std::string &out) const { +const char *GetTimeRequest::dump_to(DumpBuffer &out) const { + out.append("GetTimeRequest {}"); + return out.c_str(); +} +const char *GetTimeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "GetTimeResponse"); dump_field(out, "epoch_seconds", this->epoch_seconds); dump_field(out, "timezone", this->timezone); + return out.c_str(); } #ifdef USE_API_USER_DEFINED_ACTIONS -void ListEntitiesServicesArgument::dump_to(std::string &out) const { +const char *ListEntitiesServicesArgument::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesServicesArgument"); dump_field(out, "name", this->name); dump_field(out, "type", static_cast(this->type)); + return out.c_str(); } -void ListEntitiesServicesResponse::dump_to(std::string &out) const { +const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesServicesResponse"); dump_field(out, "name", this->name); dump_field(out, "key", this->key); @@ -1238,8 +1306,9 @@ void ListEntitiesServicesResponse::dump_to(std::string &out) const { out.append("\n"); } dump_field(out, "supports_response", static_cast(this->supports_response)); + return out.c_str(); } -void ExecuteServiceArgument::dump_to(std::string &out) const { +const char *ExecuteServiceArgument::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ExecuteServiceArgument"); dump_field(out, "bool_", this->bool_); dump_field(out, "legacy_int", this->legacy_int); @@ -1258,8 +1327,9 @@ void ExecuteServiceArgument::dump_to(std::string &out) const { for (const auto &it : this->string_array) { dump_field(out, "string_array", it, 4); } + return out.c_str(); } -void ExecuteServiceRequest::dump_to(std::string &out) const { +const char *ExecuteServiceRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ExecuteServiceRequest"); dump_field(out, "key", this->key); for (const auto &it : this->args) { @@ -1273,10 +1343,11 @@ void ExecuteServiceRequest::dump_to(std::string &out) const { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES dump_field(out, "return_response", this->return_response); #endif + return out.c_str(); } #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES -void ExecuteServiceResponse::dump_to(std::string &out) const { +const char *ExecuteServiceResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ExecuteServiceResponse"); dump_field(out, "call_id", this->call_id); dump_field(out, "success", this->success); @@ -1284,10 +1355,11 @@ void ExecuteServiceResponse::dump_to(std::string &out) const { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); #endif + return out.c_str(); } #endif #ifdef USE_CAMERA -void ListEntitiesCameraResponse::dump_to(std::string &out) const { +const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesCameraResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1300,8 +1372,9 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void CameraImageResponse::dump_to(std::string &out) const { +const char *CameraImageResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "CameraImageResponse"); dump_field(out, "key", this->key); dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); @@ -1309,15 +1382,17 @@ void CameraImageResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void CameraImageRequest::dump_to(std::string &out) const { +const char *CameraImageRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "CameraImageRequest"); dump_field(out, "single", this->single); dump_field(out, "stream", this->stream); + return out.c_str(); } #endif #ifdef USE_CLIMATE -void ListEntitiesClimateResponse::dump_to(std::string &out) const { +const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesClimateResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1360,8 +1435,9 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const { dump_field(out, "device_id", this->device_id); #endif dump_field(out, "feature_flags", this->feature_flags); + return out.c_str(); } -void ClimateStateResponse::dump_to(std::string &out) const { +const char *ClimateStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ClimateStateResponse"); dump_field(out, "key", this->key); dump_field(out, "mode", static_cast(this->mode)); @@ -1380,8 +1456,9 @@ void ClimateStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void ClimateCommandRequest::dump_to(std::string &out) const { +const char *ClimateCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ClimateCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_mode", this->has_mode); @@ -1407,10 +1484,11 @@ void ClimateCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_WATER_HEATER -void ListEntitiesWaterHeaterResponse::dump_to(std::string &out) const { +const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesWaterHeaterResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1430,8 +1508,9 @@ void ListEntitiesWaterHeaterResponse::dump_to(std::string &out) const { dump_field(out, "supported_modes", static_cast(it), 4); } dump_field(out, "supported_features", this->supported_features); + return out.c_str(); } -void WaterHeaterStateResponse::dump_to(std::string &out) const { +const char *WaterHeaterStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "WaterHeaterStateResponse"); dump_field(out, "key", this->key); dump_field(out, "current_temperature", this->current_temperature); @@ -1443,8 +1522,9 @@ void WaterHeaterStateResponse::dump_to(std::string &out) const { dump_field(out, "state", this->state); dump_field(out, "target_temperature_low", this->target_temperature_low); dump_field(out, "target_temperature_high", this->target_temperature_high); + return out.c_str(); } -void WaterHeaterCommandRequest::dump_to(std::string &out) const { +const char *WaterHeaterCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "WaterHeaterCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_fields", this->has_fields); @@ -1456,10 +1536,11 @@ void WaterHeaterCommandRequest::dump_to(std::string &out) const { dump_field(out, "state", this->state); dump_field(out, "target_temperature_low", this->target_temperature_low); dump_field(out, "target_temperature_high", this->target_temperature_high); + return out.c_str(); } #endif #ifdef USE_NUMBER -void ListEntitiesNumberResponse::dump_to(std::string &out) const { +const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesNumberResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1478,8 +1559,9 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void NumberStateResponse::dump_to(std::string &out) const { +const char *NumberStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "NumberStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -1487,18 +1569,20 @@ void NumberStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void NumberCommandRequest::dump_to(std::string &out) const { +const char *NumberCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "NumberCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_SELECT -void ListEntitiesSelectResponse::dump_to(std::string &out) const { +const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesSelectResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1514,8 +1598,9 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SelectStateResponse::dump_to(std::string &out) const { +const char *SelectStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SelectStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -1523,18 +1608,20 @@ void SelectStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SelectCommandRequest::dump_to(std::string &out) const { +const char *SelectCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SelectCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_SIREN -void ListEntitiesSirenResponse::dump_to(std::string &out) const { +const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesSirenResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1552,16 +1639,18 @@ void ListEntitiesSirenResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SirenStateResponse::dump_to(std::string &out) const { +const char *SirenStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SirenStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void SirenCommandRequest::dump_to(std::string &out) const { +const char *SirenCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SirenCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_state", this->has_state); @@ -1575,10 +1664,11 @@ void SirenCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_LOCK -void ListEntitiesLockResponse::dump_to(std::string &out) const { +const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesLockResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1595,16 +1685,18 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void LockStateResponse::dump_to(std::string &out) const { +const char *LockStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "LockStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", static_cast(this->state)); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void LockCommandRequest::dump_to(std::string &out) const { +const char *LockCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "LockCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "command", static_cast(this->command)); @@ -1613,10 +1705,11 @@ void LockCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_BUTTON -void ListEntitiesButtonResponse::dump_to(std::string &out) const { +const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesButtonResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1630,25 +1723,28 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void ButtonCommandRequest::dump_to(std::string &out) const { +const char *ButtonCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ButtonCommandRequest"); dump_field(out, "key", this->key); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_MEDIA_PLAYER -void MediaPlayerSupportedFormat::dump_to(std::string &out) const { +const char *MediaPlayerSupportedFormat::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "MediaPlayerSupportedFormat"); dump_field(out, "format", this->format); dump_field(out, "sample_rate", this->sample_rate); dump_field(out, "num_channels", this->num_channels); dump_field(out, "purpose", static_cast(this->purpose)); dump_field(out, "sample_bytes", this->sample_bytes); + return out.c_str(); } -void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { +const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesMediaPlayerResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -1668,8 +1764,9 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const { dump_field(out, "device_id", this->device_id); #endif dump_field(out, "feature_flags", this->feature_flags); + return out.c_str(); } -void MediaPlayerStateResponse::dump_to(std::string &out) const { +const char *MediaPlayerStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "MediaPlayerStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", static_cast(this->state)); @@ -1678,8 +1775,9 @@ void MediaPlayerStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void MediaPlayerCommandRequest::dump_to(std::string &out) const { +const char *MediaPlayerCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "MediaPlayerCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_command", this->has_command); @@ -1693,55 +1791,63 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_BLUETOOTH_PROXY -void SubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const { +const char *SubscribeBluetoothLEAdvertisementsRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeBluetoothLEAdvertisementsRequest"); dump_field(out, "flags", this->flags); + return out.c_str(); } -void BluetoothLERawAdvertisement::dump_to(std::string &out) const { +const char *BluetoothLERawAdvertisement::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothLERawAdvertisement"); dump_field(out, "address", this->address); dump_field(out, "rssi", this->rssi); dump_field(out, "address_type", this->address_type); dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); } -void BluetoothLERawAdvertisementsResponse::dump_to(std::string &out) const { +const char *BluetoothLERawAdvertisementsResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothLERawAdvertisementsResponse"); for (uint16_t i = 0; i < this->advertisements_len; i++) { out.append(" advertisements: "); this->advertisements[i].dump_to(out); out.append("\n"); } + return out.c_str(); } -void BluetoothDeviceRequest::dump_to(std::string &out) const { +const char *BluetoothDeviceRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDeviceRequest"); dump_field(out, "address", this->address); dump_field(out, "request_type", static_cast(this->request_type)); dump_field(out, "has_address_type", this->has_address_type); dump_field(out, "address_type", this->address_type); + return out.c_str(); } -void BluetoothDeviceConnectionResponse::dump_to(std::string &out) const { +const char *BluetoothDeviceConnectionResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDeviceConnectionResponse"); dump_field(out, "address", this->address); dump_field(out, "connected", this->connected); dump_field(out, "mtu", this->mtu); dump_field(out, "error", this->error); + return out.c_str(); } -void BluetoothGATTGetServicesRequest::dump_to(std::string &out) const { +const char *BluetoothGATTGetServicesRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTGetServicesRequest"); dump_field(out, "address", this->address); + return out.c_str(); } -void BluetoothGATTDescriptor::dump_to(std::string &out) const { +const char *BluetoothGATTDescriptor::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTDescriptor"); for (const auto &it : this->uuid) { dump_field(out, "uuid", it, 4); } dump_field(out, "handle", this->handle); dump_field(out, "short_uuid", this->short_uuid); + return out.c_str(); } -void BluetoothGATTCharacteristic::dump_to(std::string &out) const { +const char *BluetoothGATTCharacteristic::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTCharacteristic"); for (const auto &it : this->uuid) { dump_field(out, "uuid", it, 4); @@ -1754,8 +1860,9 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const { out.append("\n"); } dump_field(out, "short_uuid", this->short_uuid); + return out.c_str(); } -void BluetoothGATTService::dump_to(std::string &out) const { +const char *BluetoothGATTService::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTService"); for (const auto &it : this->uuid) { dump_field(out, "uuid", it, 4); @@ -1767,8 +1874,9 @@ void BluetoothGATTService::dump_to(std::string &out) const { out.append("\n"); } dump_field(out, "short_uuid", this->short_uuid); + return out.c_str(); } -void BluetoothGATTGetServicesResponse::dump_to(std::string &out) const { +const char *BluetoothGATTGetServicesResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTGetServicesResponse"); dump_field(out, "address", this->address); for (const auto &it : this->services) { @@ -1776,124 +1884,146 @@ void BluetoothGATTGetServicesResponse::dump_to(std::string &out) const { it.dump_to(out); out.append("\n"); } + return out.c_str(); } -void BluetoothGATTGetServicesDoneResponse::dump_to(std::string &out) const { +const char *BluetoothGATTGetServicesDoneResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTGetServicesDoneResponse"); dump_field(out, "address", this->address); + return out.c_str(); } -void BluetoothGATTReadRequest::dump_to(std::string &out) const { +const char *BluetoothGATTReadRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTReadRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); + return out.c_str(); } -void BluetoothGATTReadResponse::dump_to(std::string &out) const { +const char *BluetoothGATTReadResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTReadResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + return out.c_str(); } -void BluetoothGATTWriteRequest::dump_to(std::string &out) const { +const char *BluetoothGATTWriteRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTWriteRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_field(out, "response", this->response); dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); } -void BluetoothGATTReadDescriptorRequest::dump_to(std::string &out) const { +const char *BluetoothGATTReadDescriptorRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTReadDescriptorRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); + return out.c_str(); } -void BluetoothGATTWriteDescriptorRequest::dump_to(std::string &out) const { +const char *BluetoothGATTWriteDescriptorRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTWriteDescriptorRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); } -void BluetoothGATTNotifyRequest::dump_to(std::string &out) const { +const char *BluetoothGATTNotifyRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTNotifyRequest"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_field(out, "enable", this->enable); + return out.c_str(); } -void BluetoothGATTNotifyDataResponse::dump_to(std::string &out) const { +const char *BluetoothGATTNotifyDataResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTNotifyDataResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + return out.c_str(); } -void SubscribeBluetoothConnectionsFreeRequest::dump_to(std::string &out) const { +const char *SubscribeBluetoothConnectionsFreeRequest::dump_to(DumpBuffer &out) const { out.append("SubscribeBluetoothConnectionsFreeRequest {}"); + return out.c_str(); } -void BluetoothConnectionsFreeResponse::dump_to(std::string &out) const { +const char *BluetoothConnectionsFreeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothConnectionsFreeResponse"); dump_field(out, "free", this->free); dump_field(out, "limit", this->limit); for (const auto &it : this->allocated) { dump_field(out, "allocated", it, 4); } + return out.c_str(); } -void BluetoothGATTErrorResponse::dump_to(std::string &out) const { +const char *BluetoothGATTErrorResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTErrorResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); dump_field(out, "error", this->error); + return out.c_str(); } -void BluetoothGATTWriteResponse::dump_to(std::string &out) const { +const char *BluetoothGATTWriteResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTWriteResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); + return out.c_str(); } -void BluetoothGATTNotifyResponse::dump_to(std::string &out) const { +const char *BluetoothGATTNotifyResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothGATTNotifyResponse"); dump_field(out, "address", this->address); dump_field(out, "handle", this->handle); + return out.c_str(); } -void BluetoothDevicePairingResponse::dump_to(std::string &out) const { +const char *BluetoothDevicePairingResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDevicePairingResponse"); dump_field(out, "address", this->address); dump_field(out, "paired", this->paired); dump_field(out, "error", this->error); + return out.c_str(); } -void BluetoothDeviceUnpairingResponse::dump_to(std::string &out) const { +const char *BluetoothDeviceUnpairingResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDeviceUnpairingResponse"); dump_field(out, "address", this->address); dump_field(out, "success", this->success); dump_field(out, "error", this->error); + return out.c_str(); } -void UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(std::string &out) const { +const char *UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(DumpBuffer &out) const { out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}"); + return out.c_str(); } -void BluetoothDeviceClearCacheResponse::dump_to(std::string &out) const { +const char *BluetoothDeviceClearCacheResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDeviceClearCacheResponse"); dump_field(out, "address", this->address); dump_field(out, "success", this->success); dump_field(out, "error", this->error); + return out.c_str(); } -void BluetoothScannerStateResponse::dump_to(std::string &out) const { +const char *BluetoothScannerStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothScannerStateResponse"); dump_field(out, "state", static_cast(this->state)); dump_field(out, "mode", static_cast(this->mode)); dump_field(out, "configured_mode", static_cast(this->configured_mode)); + return out.c_str(); } -void BluetoothScannerSetModeRequest::dump_to(std::string &out) const { +const char *BluetoothScannerSetModeRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothScannerSetModeRequest"); dump_field(out, "mode", static_cast(this->mode)); + return out.c_str(); } #endif #ifdef USE_VOICE_ASSISTANT -void SubscribeVoiceAssistantRequest::dump_to(std::string &out) const { +const char *SubscribeVoiceAssistantRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeVoiceAssistantRequest"); dump_field(out, "subscribe", this->subscribe); dump_field(out, "flags", this->flags); + return out.c_str(); } -void VoiceAssistantAudioSettings::dump_to(std::string &out) const { +const char *VoiceAssistantAudioSettings::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantAudioSettings"); dump_field(out, "noise_suppression_level", this->noise_suppression_level); dump_field(out, "auto_gain", this->auto_gain); dump_field(out, "volume_multiplier", this->volume_multiplier); + return out.c_str(); } -void VoiceAssistantRequest::dump_to(std::string &out) const { +const char *VoiceAssistantRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantRequest"); dump_field(out, "start", this->start); dump_field(out, "conversation_id", this->conversation_id); @@ -1902,18 +2032,21 @@ void VoiceAssistantRequest::dump_to(std::string &out) const { this->audio_settings.dump_to(out); out.append("\n"); dump_field(out, "wake_word_phrase", this->wake_word_phrase); + return out.c_str(); } -void VoiceAssistantResponse::dump_to(std::string &out) const { +const char *VoiceAssistantResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantResponse"); dump_field(out, "port", this->port); dump_field(out, "error", this->error); + return out.c_str(); } -void VoiceAssistantEventData::dump_to(std::string &out) const { +const char *VoiceAssistantEventData::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantEventData"); dump_field(out, "name", this->name); dump_field(out, "value", this->value); + return out.c_str(); } -void VoiceAssistantEventResponse::dump_to(std::string &out) const { +const char *VoiceAssistantEventResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantEventResponse"); dump_field(out, "event_type", static_cast(this->event_type)); for (const auto &it : this->data) { @@ -1921,13 +2054,15 @@ void VoiceAssistantEventResponse::dump_to(std::string &out) const { it.dump_to(out); out.append("\n"); } + return out.c_str(); } -void VoiceAssistantAudio::dump_to(std::string &out) const { +const char *VoiceAssistantAudio::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantAudio"); dump_bytes_field(out, "data", this->data, this->data_len); dump_field(out, "end", this->end); + return out.c_str(); } -void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const { +const char *VoiceAssistantTimerEventResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantTimerEventResponse"); dump_field(out, "event_type", static_cast(this->event_type)); dump_field(out, "timer_id", this->timer_id); @@ -1935,27 +2070,31 @@ void VoiceAssistantTimerEventResponse::dump_to(std::string &out) const { dump_field(out, "total_seconds", this->total_seconds); dump_field(out, "seconds_left", this->seconds_left); dump_field(out, "is_active", this->is_active); + return out.c_str(); } -void VoiceAssistantAnnounceRequest::dump_to(std::string &out) const { +const char *VoiceAssistantAnnounceRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantAnnounceRequest"); dump_field(out, "media_id", this->media_id); dump_field(out, "text", this->text); dump_field(out, "preannounce_media_id", this->preannounce_media_id); dump_field(out, "start_conversation", this->start_conversation); + return out.c_str(); } -void VoiceAssistantAnnounceFinished::dump_to(std::string &out) const { +const char *VoiceAssistantAnnounceFinished::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantAnnounceFinished"); dump_field(out, "success", this->success); + return out.c_str(); } -void VoiceAssistantWakeWord::dump_to(std::string &out) const { +const char *VoiceAssistantWakeWord::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantWakeWord"); dump_field(out, "id", this->id); dump_field(out, "wake_word", this->wake_word); for (const auto &it : this->trained_languages) { dump_field(out, "trained_languages", it, 4); } + return out.c_str(); } -void VoiceAssistantExternalWakeWord::dump_to(std::string &out) const { +const char *VoiceAssistantExternalWakeWord::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantExternalWakeWord"); dump_field(out, "id", this->id); dump_field(out, "wake_word", this->wake_word); @@ -1966,16 +2105,18 @@ void VoiceAssistantExternalWakeWord::dump_to(std::string &out) const { dump_field(out, "model_size", this->model_size); dump_field(out, "model_hash", this->model_hash); dump_field(out, "url", this->url); + return out.c_str(); } -void VoiceAssistantConfigurationRequest::dump_to(std::string &out) const { +const char *VoiceAssistantConfigurationRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantConfigurationRequest"); for (const auto &it : this->external_wake_words) { out.append(" external_wake_words: "); it.dump_to(out); out.append("\n"); } + return out.c_str(); } -void VoiceAssistantConfigurationResponse::dump_to(std::string &out) const { +const char *VoiceAssistantConfigurationResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantConfigurationResponse"); for (const auto &it : this->available_wake_words) { out.append(" available_wake_words: "); @@ -1986,16 +2127,18 @@ void VoiceAssistantConfigurationResponse::dump_to(std::string &out) const { dump_field(out, "active_wake_words", it, 4); } dump_field(out, "max_active_wake_words", this->max_active_wake_words); + return out.c_str(); } -void VoiceAssistantSetConfiguration::dump_to(std::string &out) const { +const char *VoiceAssistantSetConfiguration::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "VoiceAssistantSetConfiguration"); for (const auto &it : this->active_wake_words) { dump_field(out, "active_wake_words", it, 4); } + return out.c_str(); } #endif #ifdef USE_ALARM_CONTROL_PANEL -void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { +const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesAlarmControlPanelResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2011,16 +2154,18 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void AlarmControlPanelStateResponse::dump_to(std::string &out) const { +const char *AlarmControlPanelStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "AlarmControlPanelStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", static_cast(this->state)); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void AlarmControlPanelCommandRequest::dump_to(std::string &out) const { +const char *AlarmControlPanelCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "AlarmControlPanelCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "command", static_cast(this->command)); @@ -2028,10 +2173,11 @@ void AlarmControlPanelCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_TEXT -void ListEntitiesTextResponse::dump_to(std::string &out) const { +const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesTextResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2048,8 +2194,9 @@ void ListEntitiesTextResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void TextStateResponse::dump_to(std::string &out) const { +const char *TextStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "TextStateResponse"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); @@ -2057,18 +2204,20 @@ void TextStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void TextCommandRequest::dump_to(std::string &out) const { +const char *TextCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "TextCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "state", this->state); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_DATETIME_DATE -void ListEntitiesDateResponse::dump_to(std::string &out) const { +const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesDateResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2081,8 +2230,9 @@ void ListEntitiesDateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void DateStateResponse::dump_to(std::string &out) const { +const char *DateStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DateStateResponse"); dump_field(out, "key", this->key); dump_field(out, "missing_state", this->missing_state); @@ -2092,8 +2242,9 @@ void DateStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void DateCommandRequest::dump_to(std::string &out) const { +const char *DateCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DateCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "year", this->year); @@ -2102,10 +2253,11 @@ void DateCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_DATETIME_TIME -void ListEntitiesTimeResponse::dump_to(std::string &out) const { +const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesTimeResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2118,8 +2270,9 @@ void ListEntitiesTimeResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void TimeStateResponse::dump_to(std::string &out) const { +const char *TimeStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "TimeStateResponse"); dump_field(out, "key", this->key); dump_field(out, "missing_state", this->missing_state); @@ -2129,8 +2282,9 @@ void TimeStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void TimeCommandRequest::dump_to(std::string &out) const { +const char *TimeCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "TimeCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "hour", this->hour); @@ -2139,10 +2293,11 @@ void TimeCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_EVENT -void ListEntitiesEventResponse::dump_to(std::string &out) const { +const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesEventResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2159,18 +2314,20 @@ void ListEntitiesEventResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void EventResponse::dump_to(std::string &out) const { +const char *EventResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "EventResponse"); dump_field(out, "key", this->key); dump_field(out, "event_type", this->event_type); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_VALVE -void ListEntitiesValveResponse::dump_to(std::string &out) const { +const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesValveResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2187,8 +2344,9 @@ void ListEntitiesValveResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void ValveStateResponse::dump_to(std::string &out) const { +const char *ValveStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ValveStateResponse"); dump_field(out, "key", this->key); dump_field(out, "position", this->position); @@ -2196,8 +2354,9 @@ void ValveStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void ValveCommandRequest::dump_to(std::string &out) const { +const char *ValveCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ValveCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "has_position", this->has_position); @@ -2206,10 +2365,11 @@ void ValveCommandRequest::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_DATETIME_DATETIME -void ListEntitiesDateTimeResponse::dump_to(std::string &out) const { +const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesDateTimeResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2222,8 +2382,9 @@ void ListEntitiesDateTimeResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void DateTimeStateResponse::dump_to(std::string &out) const { +const char *DateTimeStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DateTimeStateResponse"); dump_field(out, "key", this->key); dump_field(out, "missing_state", this->missing_state); @@ -2231,18 +2392,20 @@ void DateTimeStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void DateTimeCommandRequest::dump_to(std::string &out) const { +const char *DateTimeCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DateTimeCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "epoch_seconds", this->epoch_seconds); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_UPDATE -void ListEntitiesUpdateResponse::dump_to(std::string &out) const { +const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesUpdateResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2256,8 +2419,9 @@ void ListEntitiesUpdateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void UpdateStateResponse::dump_to(std::string &out) const { +const char *UpdateStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "UpdateStateResponse"); dump_field(out, "key", this->key); dump_field(out, "missing_state", this->missing_state); @@ -2272,29 +2436,33 @@ void UpdateStateResponse::dump_to(std::string &out) const { #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } -void UpdateCommandRequest::dump_to(std::string &out) const { +const char *UpdateCommandRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "UpdateCommandRequest"); dump_field(out, "key", this->key); dump_field(out, "command", static_cast(this->command)); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); #endif + return out.c_str(); } #endif #ifdef USE_ZWAVE_PROXY -void ZWaveProxyFrame::dump_to(std::string &out) const { +const char *ZWaveProxyFrame::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ZWaveProxyFrame"); dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); } -void ZWaveProxyRequest::dump_to(std::string &out) const { +const char *ZWaveProxyRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ZWaveProxyRequest"); dump_field(out, "type", static_cast(this->type)); dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); } #endif #ifdef USE_INFRARED -void ListEntitiesInfraredResponse::dump_to(std::string &out) const { +const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesInfraredResponse"); dump_field(out, "object_id", this->object_id); dump_field(out, "key", this->key); @@ -2308,10 +2476,11 @@ void ListEntitiesInfraredResponse::dump_to(std::string &out) const { dump_field(out, "device_id", this->device_id); #endif dump_field(out, "capabilities", this->capabilities); + return out.c_str(); } #endif #ifdef USE_IR_RF -void InfraredRFTransmitRawTimingsRequest::dump_to(std::string &out) const { +const char *InfraredRFTransmitRawTimingsRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "InfraredRFTransmitRawTimingsRequest"); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); @@ -2321,12 +2490,13 @@ void InfraredRFTransmitRawTimingsRequest::dump_to(std::string &out) const { dump_field(out, "repeat_count", this->repeat_count); out.append(" timings: "); out.append("packed buffer ["); - out.append(std::to_string(this->timings_count_)); + append_uint(out, this->timings_count_); out.append(" values, "); - out.append(std::to_string(this->timings_length_)); + append_uint(out, this->timings_length_); out.append(" bytes]\n"); + return out.c_str(); } -void InfraredRFReceiveEvent::dump_to(std::string &out) const { +const char *InfraredRFReceiveEvent::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "InfraredRFReceiveEvent"); #ifdef USE_DEVICES dump_field(out, "device_id", this->device_id); @@ -2335,6 +2505,7 @@ void InfraredRFReceiveEvent::dump_to(std::string &out) const { for (const auto &it : *this->timings) { dump_field(out, "timings", it, 4); } + return out.c_str(); } #endif diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 576b802443..4b7148e6c0 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -8,8 +8,12 @@ namespace esphome::api { static const char *const TAG = "api.service"; #ifdef HAS_PROTO_MESSAGE_DUMP -void APIServerConnectionBase::log_send_message_(const char *name, const std::string &dump) { - ESP_LOGVV(TAG, "send_message %s: %s", name, dump.c_str()); +void APIServerConnectionBase::log_send_message_(const char *name, const char *dump) { + ESP_LOGVV(TAG, "send_message %s: %s", name, dump); +} +void APIServerConnectionBase::log_receive_message_(const LogString *name, const ProtoMessage &msg) { + DumpBuffer dump_buf; + ESP_LOGVV(TAG, "%s: %s", LOG_STR_ARG(name), msg.dump_to(dump_buf)); } #endif @@ -19,7 +23,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, HelloRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_hello_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_hello_request"), msg); #endif this->on_hello_request(msg); break; @@ -28,7 +32,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, DisconnectRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_disconnect_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_disconnect_request"), msg); #endif this->on_disconnect_request(msg); break; @@ -37,7 +41,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, DisconnectResponse msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_disconnect_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_disconnect_response"), msg); #endif this->on_disconnect_response(msg); break; @@ -46,7 +50,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, PingRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_ping_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_ping_request"), msg); #endif this->on_ping_request(msg); break; @@ -55,7 +59,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, PingResponse msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_ping_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_ping_response"), msg); #endif this->on_ping_response(msg); break; @@ -64,7 +68,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, DeviceInfoRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_device_info_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_device_info_request"), msg); #endif this->on_device_info_request(msg); break; @@ -73,7 +77,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ListEntitiesRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_list_entities_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_list_entities_request"), msg); #endif this->on_list_entities_request(msg); break; @@ -82,7 +86,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeStatesRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_states_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_states_request"), msg); #endif this->on_subscribe_states_request(msg); break; @@ -91,7 +95,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeLogsRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_logs_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_logs_request"), msg); #endif this->on_subscribe_logs_request(msg); break; @@ -101,7 +105,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, CoverCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_cover_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_cover_command_request"), msg); #endif this->on_cover_command_request(msg); break; @@ -112,7 +116,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, FanCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_fan_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_fan_command_request"), msg); #endif this->on_fan_command_request(msg); break; @@ -123,7 +127,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, LightCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_light_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_light_command_request"), msg); #endif this->on_light_command_request(msg); break; @@ -134,7 +138,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SwitchCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_switch_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_switch_command_request"), msg); #endif this->on_switch_command_request(msg); break; @@ -145,7 +149,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeHomeassistantServicesRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_homeassistant_services_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_homeassistant_services_request"), msg); #endif this->on_subscribe_homeassistant_services_request(msg); break; @@ -155,7 +159,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, GetTimeResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_get_time_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_get_time_response"), msg); #endif this->on_get_time_response(msg); break; @@ -165,7 +169,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeHomeAssistantStatesRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_home_assistant_states_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_home_assistant_states_request"), msg); #endif this->on_subscribe_home_assistant_states_request(msg); break; @@ -176,7 +180,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, HomeAssistantStateResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_home_assistant_state_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_home_assistant_state_response"), msg); #endif this->on_home_assistant_state_response(msg); break; @@ -187,7 +191,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ExecuteServiceRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_execute_service_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_execute_service_request"), msg); #endif this->on_execute_service_request(msg); break; @@ -198,7 +202,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, CameraImageRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_camera_image_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_camera_image_request"), msg); #endif this->on_camera_image_request(msg); break; @@ -209,7 +213,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ClimateCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_climate_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_climate_command_request"), msg); #endif this->on_climate_command_request(msg); break; @@ -220,7 +224,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, NumberCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_number_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_number_command_request"), msg); #endif this->on_number_command_request(msg); break; @@ -231,7 +235,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SelectCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_select_command_request"), msg); #endif this->on_select_command_request(msg); break; @@ -242,7 +246,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SirenCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_siren_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_siren_command_request"), msg); #endif this->on_siren_command_request(msg); break; @@ -253,7 +257,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, LockCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_lock_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_lock_command_request"), msg); #endif this->on_lock_command_request(msg); break; @@ -264,7 +268,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ButtonCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_button_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_button_command_request"), msg); #endif this->on_button_command_request(msg); break; @@ -275,7 +279,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, MediaPlayerCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_media_player_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_media_player_command_request"), msg); #endif this->on_media_player_command_request(msg); break; @@ -286,7 +290,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeBluetoothLEAdvertisementsRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_le_advertisements_request"), msg); #endif this->on_subscribe_bluetooth_le_advertisements_request(msg); break; @@ -297,7 +301,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothDeviceRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_device_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_device_request"), msg); #endif this->on_bluetooth_device_request(msg); break; @@ -308,7 +312,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTGetServicesRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_get_services_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_get_services_request"), msg); #endif this->on_bluetooth_gatt_get_services_request(msg); break; @@ -319,7 +323,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTReadRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_read_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_read_request"), msg); #endif this->on_bluetooth_gatt_read_request(msg); break; @@ -330,7 +334,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTWriteRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_write_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_write_request"), msg); #endif this->on_bluetooth_gatt_write_request(msg); break; @@ -341,7 +345,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTReadDescriptorRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_read_descriptor_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_read_descriptor_request"), msg); #endif this->on_bluetooth_gatt_read_descriptor_request(msg); break; @@ -352,7 +356,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTWriteDescriptorRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_write_descriptor_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_write_descriptor_request"), msg); #endif this->on_bluetooth_gatt_write_descriptor_request(msg); break; @@ -363,7 +367,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothGATTNotifyRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_gatt_notify_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_gatt_notify_request"), msg); #endif this->on_bluetooth_gatt_notify_request(msg); break; @@ -374,7 +378,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeBluetoothConnectionsFreeRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_connections_free_request"), msg); #endif this->on_subscribe_bluetooth_connections_free_request(msg); break; @@ -385,7 +389,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, UnsubscribeBluetoothLEAdvertisementsRequest msg; // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_unsubscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_unsubscribe_bluetooth_le_advertisements_request"), msg); #endif this->on_unsubscribe_bluetooth_le_advertisements_request(msg); break; @@ -396,7 +400,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, SubscribeVoiceAssistantRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_subscribe_voice_assistant_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_subscribe_voice_assistant_request"), msg); #endif this->on_subscribe_voice_assistant_request(msg); break; @@ -407,7 +411,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_response"), msg); #endif this->on_voice_assistant_response(msg); break; @@ -418,7 +422,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantEventResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_event_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_event_response"), msg); #endif this->on_voice_assistant_event_response(msg); break; @@ -429,7 +433,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, AlarmControlPanelCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_alarm_control_panel_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_alarm_control_panel_command_request"), msg); #endif this->on_alarm_control_panel_command_request(msg); break; @@ -440,7 +444,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, TextCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_text_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_text_command_request"), msg); #endif this->on_text_command_request(msg); break; @@ -451,7 +455,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, DateCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_date_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_date_command_request"), msg); #endif this->on_date_command_request(msg); break; @@ -462,7 +466,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, TimeCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_time_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_time_command_request"), msg); #endif this->on_time_command_request(msg); break; @@ -473,7 +477,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantAudio msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_audio: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_audio"), msg); #endif this->on_voice_assistant_audio(msg); break; @@ -484,7 +488,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ValveCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_valve_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_valve_command_request"), msg); #endif this->on_valve_command_request(msg); break; @@ -495,7 +499,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, DateTimeCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_date_time_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_date_time_command_request"), msg); #endif this->on_date_time_command_request(msg); break; @@ -506,7 +510,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantTimerEventResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_timer_event_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_timer_event_response"), msg); #endif this->on_voice_assistant_timer_event_response(msg); break; @@ -517,7 +521,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, UpdateCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_update_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_update_command_request"), msg); #endif this->on_update_command_request(msg); break; @@ -528,7 +532,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantAnnounceRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_announce_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_announce_request"), msg); #endif this->on_voice_assistant_announce_request(msg); break; @@ -539,7 +543,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantConfigurationRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_configuration_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_configuration_request"), msg); #endif this->on_voice_assistant_configuration_request(msg); break; @@ -550,7 +554,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, VoiceAssistantSetConfiguration msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_voice_assistant_set_configuration: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_voice_assistant_set_configuration"), msg); #endif this->on_voice_assistant_set_configuration(msg); break; @@ -561,7 +565,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, NoiseEncryptionSetKeyRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_noise_encryption_set_key_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_noise_encryption_set_key_request"), msg); #endif this->on_noise_encryption_set_key_request(msg); break; @@ -572,7 +576,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, BluetoothScannerSetModeRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_bluetooth_scanner_set_mode_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_bluetooth_scanner_set_mode_request"), msg); #endif this->on_bluetooth_scanner_set_mode_request(msg); break; @@ -583,7 +587,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ZWaveProxyFrame msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_z_wave_proxy_frame: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_z_wave_proxy_frame"), msg); #endif this->on_z_wave_proxy_frame(msg); break; @@ -594,7 +598,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, ZWaveProxyRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_z_wave_proxy_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_z_wave_proxy_request"), msg); #endif this->on_z_wave_proxy_request(msg); break; @@ -605,7 +609,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, HomeassistantActionResponse msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_homeassistant_action_response: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_homeassistant_action_response"), msg); #endif this->on_homeassistant_action_response(msg); break; @@ -616,7 +620,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, WaterHeaterCommandRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_water_heater_command_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_water_heater_command_request"), msg); #endif this->on_water_heater_command_request(msg); break; @@ -627,7 +631,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, InfraredRFTransmitRawTimingsRequest msg; msg.decode(msg_data, msg_size); #ifdef HAS_PROTO_MESSAGE_DUMP - ESP_LOGVV(TAG, "on_infrared_rf_transmit_raw_timings_request: %s", msg.dump().c_str()); + this->log_receive_message_(LOG_STR("on_infrared_rf_transmit_raw_timings_request"), msg); #endif this->on_infrared_rf_transmit_raw_timings_request(msg); break; diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 4bd6a7b6a4..200991c282 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -12,14 +12,16 @@ class APIServerConnectionBase : public ProtoService { public: #ifdef HAS_PROTO_MESSAGE_DUMP protected: - void log_send_message_(const char *name, const std::string &dump); + void log_send_message_(const char *name, const char *dump); + void log_receive_message_(const LogString *name, const ProtoMessage &msg); public: #endif bool send_message(const ProtoMessage &msg, uint8_t message_type) { #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_send_message_(msg.message_name(), msg.dump()); + DumpBuffer dump_buf; + this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); #endif return this->send_message_(msg, message_type); } diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 4f0d0846d7..eac26997cf 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -139,12 +139,4 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { } } -#ifdef HAS_PROTO_MESSAGE_DUMP -std::string ProtoMessage::dump() const { - std::string out; - this->dump_to(out); - return out; -} -#endif - } // namespace esphome::api diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index a336a9493d..2e0df297c3 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -362,6 +362,63 @@ class ProtoWriteBuffer { std::vector *buffer_; }; +#ifdef HAS_PROTO_MESSAGE_DUMP +/** + * Fixed-size buffer for message dumps - avoids heap allocation. + * Sized to match the logger's default tx_buffer_size (512 bytes) + * since anything larger gets truncated anyway. + */ +class DumpBuffer { + public: + // Matches default tx_buffer_size in logger component + static constexpr size_t CAPACITY = 512; + + DumpBuffer() : pos_(0) { buf_[0] = '\0'; } + + DumpBuffer &append(const char *str) { + if (str) { + append_impl_(str, strlen(str)); + } + return *this; + } + + DumpBuffer &append(const char *str, size_t len) { + append_impl_(str, len); + return *this; + } + + DumpBuffer &append(size_t n, char c) { + size_t space = CAPACITY - 1 - pos_; + if (n > space) + n = space; + if (n > 0) { + memset(buf_ + pos_, c, n); + pos_ += n; + buf_[pos_] = '\0'; + } + return *this; + } + + const char *c_str() const { return buf_; } + size_t size() const { return pos_; } + + private: + void append_impl_(const char *str, size_t len) { + size_t space = CAPACITY - 1 - pos_; + if (len > space) + len = space; + if (len > 0) { + memcpy(buf_ + pos_, str, len); + pos_ += len; + buf_[pos_] = '\0'; + } + } + + char buf_[CAPACITY]; + size_t pos_; +}; +#endif + class ProtoMessage { public: virtual ~ProtoMessage() = default; @@ -370,8 +427,7 @@ class ProtoMessage { // Default implementation for messages with no fields virtual void calculate_size(ProtoSize &size) const {} #ifdef HAS_PROTO_MESSAGE_DUMP - std::string dump() const; - virtual void dump_to(std::string &out) const = 0; + virtual const char *dump_to(DumpBuffer &out) const = 0; virtual const char *message_name() const { return "unknown"; } #endif }; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index a10a912186..7625458f9f 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -990,9 +990,9 @@ class PackedBufferTypeInfo(TypeInfo): return ( f'out.append(" {self.name}: ");\n' + 'out.append("packed buffer [");\n' - + f"out.append(std::to_string(this->{self.field_name}_count_));\n" + + f"append_uint(out, this->{self.field_name}_count_);\n" + 'out.append(" values, ");\n' - + f"out.append(std::to_string(this->{self.field_name}_length_));\n" + + f"append_uint(out, this->{self.field_name}_length_);\n" + 'out.append(" bytes]\\n");' ) @@ -2216,24 +2216,22 @@ def build_message_type( # dump_to method declaration in header prot = "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - prot += "void dump_to(std::string &out) const override;\n" + prot += "const char *dump_to(DumpBuffer &out) const override;\n" prot += "#endif\n" public_content.append(prot) # dump_to implementation will go in dump_cpp - dump_impl = f"void {desc.name}::dump_to(std::string &out) const {{" + dump_impl = f"const char *{desc.name}::dump_to(DumpBuffer &out) const {{" if dump: # Always use MessageDumpHelper for consistent output formatting dump_impl += "\n" dump_impl += f' MessageDumpHelper helper(out, "{desc.name}");\n' dump_impl += indent("\n".join(dump)) + "\n" + dump_impl += " return out.c_str();\n" else: - o2 = f'out.append("{desc.name} {{}}");' - if len(dump_impl) + len(o2) + 3 < 120: - dump_impl += f" {o2} " - else: - dump_impl += "\n" - dump_impl += f" {o2}\n" + dump_impl += "\n" + dump_impl += f' out.append("{desc.name} {{}}");\n' + dump_impl += " return out.c_str();\n" dump_impl += "}\n" if base_class: @@ -2521,7 +2519,7 @@ def build_service_message_type( case += "// Empty message: no decode needed\n" if log: case += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - case += f'ESP_LOGVV(TAG, "{func}: %s", msg.dump().c_str());\n' + case += f'this->log_receive_message_(LOG_STR("{func}"), msg);\n' case += "#endif\n" case += f"this->{func}(msg);\n" case += "break;" @@ -2588,7 +2586,7 @@ namespace esphome::api { namespace esphome::api { // Helper function to append a quoted string, handling empty StringRef -static inline void append_quoted_string(std::string &out, const StringRef &ref) { +static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { out.append(ref.c_str()); @@ -2597,83 +2595,89 @@ static inline void append_quoted_string(std::string &out, const StringRef &ref) } // Common helpers for dump_field functions -static inline void append_field_prefix(std::string &out, const char *field_name, int indent) { +static inline void append_field_prefix(DumpBuffer &out, const char *field_name, int indent) { out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(std::string &out, const char *str) { +static inline void append_with_newline(DumpBuffer &out, const char *str) { out.append(str); out.append("\\n"); } +static inline void append_uint(DumpBuffer &out, uint32_t value) { + char buf[16]; + snprintf(buf, sizeof(buf), "%" PRIu32, value); + out.append(buf); +} + // RAII helper for message dump formatting class MessageDumpHelper { public: - MessageDumpHelper(std::string &out, const char *message_name) : out_(out) { + MessageDumpHelper(DumpBuffer &out, const char *message_name) : out_(out) { out_.append(message_name); out_.append(" {\\n"); } ~MessageDumpHelper() { out_.append(" }"); } private: - std::string &out_; + DumpBuffer &out_; }; // Helper functions to reduce code duplication in dump methods -static void dump_field(std::string &out, const char *field_name, int32_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRId32, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, uint32_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRIu32, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, float value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%g", value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, uint64_t value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { char buffer[64]; append_field_prefix(out, field_name, indent); snprintf(buffer, 64, "%" PRIu64, value); append_with_newline(out, buffer); } -static void dump_field(std::string &out, const char *field_name, bool value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append(YESNO(value)); out.append("\\n"); } -static void dump_field(std::string &out, const char *field_name, const std::string &value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, const std::string &value, int indent = 2) { append_field_prefix(out, field_name, indent); - out.append("'").append(value).append("'"); + out.append("'").append(value.c_str()).append("'"); out.append("\\n"); } -static void dump_field(std::string &out, const char *field_name, StringRef value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, StringRef value, int indent = 2) { append_field_prefix(out, field_name, indent); append_quoted_string(out, value); out.append("\\n"); } -static void dump_field(std::string &out, const char *field_name, const char *value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, const char *value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append("'").append(value).append("'"); out.append("\\n"); } template -static void dump_field(std::string &out, const char *field_name, T value, int indent = 2) { +static void dump_field(DumpBuffer &out, const char *field_name, T value, int indent = 2) { append_field_prefix(out, field_name, indent); out.append(proto_enum_to_string(value)); out.append("\\n"); @@ -2681,7 +2685,7 @@ static void dump_field(std::string &out, const char *field_name, T value, int in // Helper for bytes fields - uses stack buffer to avoid heap allocation // Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer -static void dump_bytes_field(std::string &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { +static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); @@ -2843,25 +2847,35 @@ static const char *const TAG = "api.service"; hpp += f"class {class_name} : public ProtoService {{\n" hpp += " public:\n" - # Add logging helper method declaration + # Add logging helper method declarations hpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" hpp += " protected:\n" - hpp += " void log_send_message_(const char *name, const std::string &dump);\n" + hpp += " void log_send_message_(const char *name, const char *dump);\n" + hpp += ( + " void log_receive_message_(const LogString *name, const ProtoMessage &msg);\n" + ) hpp += " public:\n" hpp += "#endif\n\n" # Add non-template send_message method hpp += " bool send_message(const ProtoMessage &msg, uint8_t message_type) {\n" hpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - hpp += " this->log_send_message_(msg.message_name(), msg.dump());\n" + hpp += " DumpBuffer dump_buf;\n" + hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n" hpp += "#endif\n" hpp += " return this->send_message_(msg, message_type);\n" hpp += " }\n\n" - # Add logging helper method implementation to cpp + # Add logging helper method implementations to cpp cpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - cpp += f"void {class_name}::log_send_message_(const char *name, const std::string &dump) {{\n" - cpp += ' ESP_LOGVV(TAG, "send_message %s: %s", name, dump.c_str());\n' + cpp += ( + f"void {class_name}::log_send_message_(const char *name, const char *dump) {{\n" + ) + cpp += ' ESP_LOGVV(TAG, "send_message %s: %s", name, dump);\n' + cpp += "}\n" + cpp += f"void {class_name}::log_receive_message_(const LogString *name, const ProtoMessage &msg) {{\n" + cpp += " DumpBuffer dump_buf;\n" + cpp += ' ESP_LOGVV(TAG, "%s: %s", LOG_STR_ARG(name), msg.dump_to(dump_buf));\n' cpp += "}\n" cpp += "#endif\n\n" From 3d40979c966ee6fb866d54e52bff6fa3314218c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 08:05:04 -1000 Subject: [PATCH 0091/2030] [mqtt] Avoid intermediate string allocations in publish calls (#13174) --- .../components/mqtt/custom_mqtt_device.cpp | 8 +++--- esphome/components/mqtt/mqtt_climate.cpp | 25 ++++++++++--------- esphome/components/mqtt/mqtt_component.cpp | 6 ++++- esphome/components/mqtt/mqtt_component.h | 8 ++++++ esphome/components/mqtt/mqtt_cover.cpp | 8 +++--- esphome/components/mqtt/mqtt_fan.cpp | 5 ++-- esphome/components/mqtt/mqtt_sensor.cpp | 6 ++--- esphome/components/mqtt/mqtt_valve.cpp | 4 +-- 8 files changed, 42 insertions(+), 28 deletions(-) diff --git a/esphome/components/mqtt/custom_mqtt_device.cpp b/esphome/components/mqtt/custom_mqtt_device.cpp index c900e3861d..7ff65bb42c 100644 --- a/esphome/components/mqtt/custom_mqtt_device.cpp +++ b/esphome/components/mqtt/custom_mqtt_device.cpp @@ -13,13 +13,13 @@ bool CustomMQTTDevice::publish(const std::string &topic, const std::string &payl } bool CustomMQTTDevice::publish(const std::string &topic, float value, int8_t number_decimals) { char buf[VALUE_ACCURACY_MAX_LEN]; - value_accuracy_to_buf(buf, value, number_decimals); - return this->publish(topic, buf); + size_t len = value_accuracy_to_buf(buf, value, number_decimals); + return global_mqtt_client->publish(topic, buf, len); } bool CustomMQTTDevice::publish(const std::string &topic, int value) { char buffer[24]; - sprintf(buffer, "%d", value); - return this->publish(topic, buffer); + int len = snprintf(buffer, sizeof(buffer), "%d", value); + return global_mqtt_client->publish(topic, buffer, len); } bool CustomMQTTDevice::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos, bool retain) { return global_mqtt_client->publish_json(topic, f, qos, retain); diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index c7e086115b..37d643f9e7 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -292,36 +292,37 @@ bool MQTTClimateComponent::publish_state_() { int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); char payload[VALUE_ACCURACY_MAX_LEN]; + size_t len; if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE) && !std::isnan(this->device_->current_temperature)) { - value_accuracy_to_buf(payload, this->device_->current_temperature, current_accuracy); - if (!this->publish(this->get_current_temperature_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->current_temperature, current_accuracy); + if (!this->publish(this->get_current_temperature_state_topic(), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { - value_accuracy_to_buf(payload, this->device_->target_temperature_low, target_accuracy); - if (!this->publish(this->get_target_temperature_low_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->target_temperature_low, target_accuracy); + if (!this->publish(this->get_target_temperature_low_state_topic(), payload, len)) success = false; - value_accuracy_to_buf(payload, this->device_->target_temperature_high, target_accuracy); - if (!this->publish(this->get_target_temperature_high_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->target_temperature_high, target_accuracy); + if (!this->publish(this->get_target_temperature_high_state_topic(), payload, len)) success = false; } else { - value_accuracy_to_buf(payload, this->device_->target_temperature, target_accuracy); - if (!this->publish(this->get_target_temperature_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->target_temperature, target_accuracy); + if (!this->publish(this->get_target_temperature_state_topic(), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY) && !std::isnan(this->device_->current_humidity)) { - value_accuracy_to_buf(payload, this->device_->current_humidity, 0); - if (!this->publish(this->get_current_humidity_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->current_humidity, 0); + if (!this->publish(this->get_current_humidity_state_topic(), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY) && !std::isnan(this->device_->target_humidity)) { - value_accuracy_to_buf(payload, this->device_->target_humidity, 0); - if (!this->publish(this->get_target_humidity_state_topic(), payload)) + len = value_accuracy_to_buf(payload, this->device_->target_humidity, 0); + if (!this->publish(this->get_target_humidity_state_topic(), payload, len)) success = false; } diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 13f496c6a7..20c111de43 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -106,9 +106,13 @@ std::string MQTTComponent::get_command_topic_() const { } bool MQTTComponent::publish(const std::string &topic, const std::string &payload) { + return this->publish(topic, payload.data(), payload.size()); +} + +bool MQTTComponent::publish(const std::string &topic, const char *payload, size_t payload_length) { if (topic.empty()) return false; - return global_mqtt_client->publish(topic, payload, this->qos_, this->retain_); + return global_mqtt_client->publish(topic, payload, payload_length, this->qos_, this->retain_); } bool MQTTComponent::publish_json(const std::string &topic, const json::json_build_t &f) { diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 11dfd093f3..676e3ad35d 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -140,6 +140,14 @@ class MQTTComponent : public Component { */ bool publish(const std::string &topic, const std::string &payload); + /** Send a MQTT message. + * + * @param topic The topic. + * @param payload The payload buffer. + * @param payload_length The length of the payload. + */ + bool publish(const std::string &topic, const char *payload, size_t payload_length); + /** Construct and send a JSON MQTT message. * * @param topic The topic. diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index 2164b5ca44..f2df6af236 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -99,14 +99,14 @@ bool MQTTCoverComponent::publish_state() { bool success = true; if (traits.get_supports_position()) { char pos[VALUE_ACCURACY_MAX_LEN]; - value_accuracy_to_buf(pos, roundf(this->cover_->position * 100), 0); - if (!this->publish(this->get_position_state_topic(), pos)) + size_t len = value_accuracy_to_buf(pos, roundf(this->cover_->position * 100), 0); + if (!this->publish(this->get_position_state_topic(), pos, len)) success = false; } if (traits.get_supports_tilt()) { char pos[VALUE_ACCURACY_MAX_LEN]; - value_accuracy_to_buf(pos, roundf(this->cover_->tilt * 100), 0); - if (!this->publish(this->get_tilt_state_topic(), pos)) + size_t len = value_accuracy_to_buf(pos, roundf(this->cover_->tilt * 100), 0); + if (!this->publish(this->get_tilt_state_topic(), pos, len)) success = false; } const char *state_s = this->cover_->current_operation == COVER_OPERATION_OPENING ? "opening" diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index bd6c98b679..a6f0503588 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -174,8 +174,9 @@ bool MQTTFanComponent::publish_state() { } auto traits = this->state_->get_traits(); if (traits.supports_speed()) { - std::string payload = to_string(this->state_->speed); - bool success = this->publish(this->get_speed_level_state_topic(), payload); + char buf[12]; + int len = snprintf(buf, sizeof(buf), "%d", this->state_->speed); + bool success = this->publish(this->get_speed_level_state_topic(), buf, len); failed = failed || !success; } return !failed; diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index cfe6923a5f..c14c889d47 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -80,11 +80,11 @@ bool MQTTSensorComponent::send_initial_state() { } bool MQTTSensorComponent::publish_state(float value) { if (mqtt::global_mqtt_client->is_publish_nan_as_none() && std::isnan(value)) - return this->publish(this->get_state_topic_(), "None"); + return this->publish(this->get_state_topic_(), "None", 4); int8_t accuracy = this->sensor_->get_accuracy_decimals(); char buf[VALUE_ACCURACY_MAX_LEN]; - value_accuracy_to_buf(buf, value, accuracy); - return this->publish(this->get_state_topic_(), buf); + size_t len = value_accuracy_to_buf(buf, value, accuracy); + return this->publish(this->get_state_topic_(), buf, len); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index b4cc367bc5..2faaace46b 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -74,8 +74,8 @@ bool MQTTValveComponent::publish_state() { bool success = true; if (traits.get_supports_position()) { char pos[VALUE_ACCURACY_MAX_LEN]; - value_accuracy_to_buf(pos, roundf(this->valve_->position * 100), 0); - if (!this->publish(this->get_position_state_topic(), pos)) + size_t len = value_accuracy_to_buf(pos, roundf(this->valve_->position * 100), 0); + if (!this->publish(this->get_position_state_topic(), pos, len)) success = false; } const char *state_s = this->valve_->current_operation == VALVE_OPERATION_OPENING ? "opening" From 4d96c60696ca0fa4894689f2d3dbbf7303ef2f96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Jan 2026 09:36:58 -1000 Subject: [PATCH 0092/2030] Bump yamllint from 1.37.1 to 1.38.0 (#13192) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_dev.txt b/requirements_dev.txt index 16e051fcd7..0884e5b5e4 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,4 +1,4 @@ # Useful stuff when working in a development environment clang-format==13.0.1 # also change in .pre-commit-config.yaml and Dockerfile when updating clang-tidy==18.1.8 # When updating clang-tidy, also update Dockerfile -yamllint==1.37.1 # also change in .pre-commit-config.yaml when updating +yamllint==1.38.0 # also change in .pre-commit-config.yaml when updating From 733f57da5029fa4c9af3a925199751e4a35dfd84 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 13 Jan 2026 19:42:36 +0000 Subject: [PATCH 0093/2030] [i2s_audio] Bugfix: Buffer overflow in software volume control (#13190) --- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp | 2 +- 1 file changed, 1 insertion(+), 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 53e378c41e..c934d12d65 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -340,8 +340,8 @@ void I2SAudioSpeaker::speaker_task(void *params) { const uint32_t read_delay = (this_speaker->current_stream_info_.frames_to_microseconds(frames_written) / 1000) / 2; - uint8_t *new_data = transfer_buffer->get_buffer_end(); // track start of any newly copied bytes size_t bytes_read = transfer_buffer->transfer_data_from_source(pdMS_TO_TICKS(read_delay)); + uint8_t *new_data = transfer_buffer->get_buffer_end() - bytes_read; if (bytes_read > 0) { if (this_speaker->q15_volume_factor_ < INT16_MAX) { From a060d1d0446187e1d255c376dd505785b2a6df72 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 11:33:36 -1000 Subject: [PATCH 0094/2030] [wifi] Fix ESP8266 disconnect callback order to set error flag before notifying listeners (#13189) --- esphome/components/wifi/wifi_component_esp8266.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index b7d820413c..61c4584d09 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -543,7 +543,12 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { } s_sta_connected = false; s_sta_connecting = false; + // IMPORTANT: Set error flag BEFORE notifying listeners. + // This ensures is_connected() returns false during listener callbacks, + // which is critical for proper reconnection logic (e.g., roaming). + global_wifi_component->error_from_callback_ = true; #ifdef USE_WIFI_LISTENERS + // Notify listeners AFTER setting error flag so they see correct state static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : global_wifi_component->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); @@ -635,10 +640,6 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { break; } - if (event->event == EVENT_STAMODE_DISCONNECTED) { - global_wifi_component->error_from_callback_ = true; - } - WiFiMockClass::_event_callback(event); } From 3d74d1e7f06cc91a55e44e1b19f8e07e9e904077 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 11:39:11 -1000 Subject: [PATCH 0095/2030] [libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code (#13191) --- .github/PULL_REQUEST_TEMPLATE.md | 1 + esphome/components/bk72xx/__init__.py | 27 +- esphome/components/bk72xx/boards.py | 1309 +++++------ esphome/components/libretiny/__init__.py | 23 +- esphome/components/libretiny/const.py | 1 + .../libretiny/generate_components.py | 69 +- esphome/components/ln882x/__init__.py | 27 +- esphome/components/ln882x/boards.py | 332 +-- esphome/components/rtl87xx/__init__.py | 36 +- esphome/components/rtl87xx/boards.py | 1971 +++++++++-------- esphome/core/scheduler.cpp | 5 +- .../components/libretiny/test.ln882x-ard.yaml | 2 + .../libretiny/test.rtl87xx-ard.yaml | 2 + 13 files changed, 2040 insertions(+), 1765 deletions(-) create mode 100644 tests/components/libretiny/test.ln882x-ard.yaml create mode 100644 tests/components/libretiny/test.rtl87xx-ard.yaml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 41dd02458e..d1ef3bd822 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -27,6 +27,7 @@ - [ ] RP2040 - [ ] BK72xx - [ ] RTL87xx +- [ ] LN882x - [ ] nRF52840 ## Example entry for `config.yaml`: diff --git a/esphome/components/bk72xx/__init__.py b/esphome/components/bk72xx/__init__.py index 5b14d0529d..7fed742d2e 100644 --- a/esphome/components/bk72xx/__init__.py +++ b/esphome/components/bk72xx/__init__.py @@ -1,9 +1,23 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. -# For custom pin validators, put validate_pin() or validate_usage() -# in gpio.py file in this directory. -# For changing schema/pin schema, put COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA -# in schema.py file in this directory. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. + +To customize this component: + - Pin validators: Create gpio.py with validate_pin() or validate_usage() + - Schema extensions: Create schema.py with COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA + +Platform-specific code should be added to the main libretiny component +(__init__.py in esphome/components/libretiny/) rather than here. +""" from esphome import pins from esphome.components import libretiny @@ -27,6 +41,7 @@ COMPONENT_DATA = LibreTinyComponent( board_pins=BK72XX_BOARD_PINS, pin_validation=None, usage_validation=None, + supports_atomics=False, ) diff --git a/esphome/components/bk72xx/boards.py b/esphome/components/bk72xx/boards.py index 8e3e8a97a2..3850dbe266 100644 --- a/esphome/components/bk72xx/boards.py +++ b/esphome/components/bk72xx/boards.py @@ -1,5 +1,16 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. +""" from esphome.components.libretiny.const import ( FAMILY_BK7231N, @@ -9,6 +20,22 @@ from esphome.components.libretiny.const import ( ) BK72XX_BOARDS = { + "wb2l-m1": { + "name": "WB2L_M1 Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "cbu": { + "name": "CBU Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "generic-bk7231t-qfn32-tuya": { + "name": "Generic - BK7231T (Tuya QFN32)", + "family": FAMILY_BK7231T, + }, + "generic-bk7231n-qfn32-tuya": { + "name": "Generic - BK7231N (Tuya QFN32)", + "family": FAMILY_BK7231N, + }, "cb1s": { "name": "CB1S Wi-Fi Module", "family": FAMILY_BK7231N, @@ -17,85 +44,324 @@ BK72XX_BOARDS = { "name": "CB2L Wi-Fi Module", "family": FAMILY_BK7231N, }, - "cb2s": { - "name": "CB2S Wi-Fi Module", - "family": FAMILY_BK7231N, - }, - "cb3l": { - "name": "CB3L Wi-Fi Module", + "cblc5": { + "name": "CBLC5 Wi-Fi Module", "family": FAMILY_BK7231N, }, "cb3s": { "name": "CB3S Wi-Fi Module", "family": FAMILY_BK7231N, }, - "cb3se": { - "name": "CB3SE Wi-Fi Module", - "family": FAMILY_BK7231N, - }, - "cblc5": { - "name": "CBLC5 Wi-Fi Module", - "family": FAMILY_BK7231N, - }, - "cbu": { - "name": "CBU Wi-Fi Module", - "family": FAMILY_BK7231N, - }, - "generic-bk7231n-qfn32-tuya": { - "name": "Generic - BK7231N (Tuya QFN32)", - "family": FAMILY_BK7231N, - }, - "generic-bk7231t-qfn32-tuya": { - "name": "Generic - BK7231T (Tuya QFN32)", - "family": FAMILY_BK7231T, - }, - "generic-bk7252": { - "name": "Generic - BK7252", - "family": FAMILY_BK7251, - }, - "lsc-lma35-t": { - "name": "LSC LMA35 BK7231T", + "wb3s": { + "name": "WB3S Wi-Fi Module", "family": FAMILY_BK7231T, }, "lsc-lma35": { "name": "LSC LMA35 BK7231N", "family": FAMILY_BK7231N, }, - "wa2": { - "name": "WA2 Wi-Fi Module", - "family": FAMILY_BK7231Q, - }, - "wb1s": { - "name": "WB1S Wi-Fi Module", - "family": FAMILY_BK7231T, - }, - "wb2l-m1": { - "name": "WB2L_M1 Wi-Fi Module", - "family": FAMILY_BK7231N, + "generic-bk7252": { + "name": "Generic - BK7252", + "family": FAMILY_BK7251, }, "wb2l": { "name": "WB2L Wi-Fi Module", "family": FAMILY_BK7231T, }, - "wb2s": { - "name": "WB2S Wi-Fi Module", - "family": FAMILY_BK7231T, - }, - "wb3l": { - "name": "WB3L Wi-Fi Module", - "family": FAMILY_BK7231T, - }, - "wb3s": { - "name": "WB3S Wi-Fi Module", + "wb1s": { + "name": "WB1S Wi-Fi Module", "family": FAMILY_BK7231T, }, "wblc5": { "name": "WBLC5 Wi-Fi Module", "family": FAMILY_BK7231T, }, + "cb2s": { + "name": "CB2S Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "wa2": { + "name": "WA2 Wi-Fi Module", + "family": FAMILY_BK7231Q, + }, + "cb3l": { + "name": "CB3L Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "lsc-lma35-t": { + "name": "LSC LMA35 BK7231T", + "family": FAMILY_BK7231T, + }, + "cb3se": { + "name": "CB3SE Wi-Fi Module", + "family": FAMILY_BK7231N, + }, + "wb3l": { + "name": "WB3L Wi-Fi Module", + "family": FAMILY_BK7231T, + }, + "wb2s": { + "name": "WB2S Wi-Fi Module", + "family": FAMILY_BK7231T, + }, } BK72XX_BOARD_PINS = { + "wb2l-m1": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P10": 10, + "P11": 11, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 8, + "D1": 7, + "D2": 6, + "D3": 26, + "D4": 24, + "D5": 10, + "D6": 11, + "D7": 1, + "D8": 0, + "D9": 20, + "D10": 21, + "D11": 23, + "D12": 22, + "A0": 23, + }, + "cbu": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "CS": 15, + "MISO": 17, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P15": 15, + "P16": 16, + "P17": 17, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "P28": 28, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCK": 14, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 14, + "D1": 16, + "D2": 20, + "D3": 22, + "D4": 23, + "D5": 1, + "D6": 0, + "D7": 8, + "D8": 7, + "D9": 6, + "D10": 26, + "D11": 24, + "D12": 11, + "D13": 10, + "D14": 28, + "D15": 9, + "D16": 17, + "D17": 15, + "D18": 21, + "A0": 23, + }, + "generic-bk7231t-qfn32-tuya": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "CS": 15, + "MISO": 17, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P15": 15, + "P16": 16, + "P17": 17, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "P28": 28, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCK": 14, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 0, + "D1": 1, + "D2": 6, + "D3": 7, + "D4": 8, + "D5": 9, + "D6": 10, + "D7": 11, + "D8": 14, + "D9": 15, + "D10": 16, + "D11": 17, + "D12": 20, + "D13": 21, + "D14": 22, + "D15": 23, + "D16": 24, + "D17": 26, + "D18": 28, + "A0": 23, + }, + "generic-bk7231n-qfn32-tuya": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "CS": 15, + "MISO": 17, + "MOSI": 16, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P15": 15, + "P16": 16, + "P17": 17, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "P28": 28, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCK": 14, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 0, + "D1": 1, + "D2": 6, + "D3": 7, + "D4": 8, + "D5": 9, + "D6": 10, + "D7": 11, + "D8": 14, + "D9": 15, + "D10": 16, + "D11": 17, + "D12": 20, + "D13": 21, + "D14": 22, + "D15": 23, + "D16": 24, + "D17": 26, + "D18": 28, + "A0": 23, + }, "cb1s": { "WIRE1_SCL": 20, "WIRE1_SDA": 21, @@ -183,28 +449,22 @@ BK72XX_BOARD_PINS = { "D7": 11, "D8": 21, }, - "cb2s": { + "cblc5": { "WIRE2_SCL": 0, "WIRE2_SDA": 1, "SERIAL1_RX": 10, "SERIAL1_TX": 11, "SERIAL2_RX": 1, "SERIAL2_TX": 0, - "ADC3": 23, "P0": 0, "P1": 1, "P6": 6, - "P7": 7, - "P8": 8, "P10": 10, "P11": 11, "P21": 21, - "P23": 23, "P24": 24, "P26": 26, "PWM0": 6, - "PWM1": 7, - "PWM2": 8, "PWM4": 24, "PWM5": 26, "RX1": 10, @@ -214,61 +474,14 @@ BK72XX_BOARD_PINS = { "SDA2": 1, "TX1": 11, "TX2": 0, - "D0": 6, - "D1": 7, - "D2": 8, - "D3": 23, - "D4": 10, - "D5": 11, - "D6": 24, - "D7": 26, - "D8": 0, - "D9": 1, - "D10": 21, - "A0": 23, - }, - "cb3l": { - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P6": 6, - "P7": 7, - "P8": 8, - "P9": 9, - "P10": 10, - "P11": 11, - "P14": 14, - "P21": 21, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM3": 9, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "SCK": 14, - "SCL2": 0, - "SDA1": 21, - "TX1": 11, - "TX2": 0, - "D0": 23, - "D1": 14, + "D0": 24, + "D1": 6, "D2": 26, - "D3": 24, - "D4": 6, - "D5": 9, + "D3": 11, + "D4": 10, + "D5": 1, "D6": 0, "D7": 21, - "D8": 8, - "D9": 7, - "D10": 10, - "D11": 11, - "A0": 23, }, "cb3s": { "WIRE1_SCL": 20, @@ -321,7 +534,9 @@ BK72XX_BOARD_PINS = { "D13": 20, "A0": 23, }, - "cb3se": { + "wb3s": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, "WIRE2_SCL": 0, "WIRE2_SDA": 1, "SERIAL1_RX": 10, @@ -329,9 +544,6 @@ BK72XX_BOARD_PINS = { "SERIAL2_RX": 1, "SERIAL2_TX": 0, "ADC3": 23, - "CS": 15, - "MISO": 17, - "MOSI": 16, "P0": 0, "P1": 1, "P6": 6, @@ -341,10 +553,8 @@ BK72XX_BOARD_PINS = { "P10": 10, "P11": 11, "P14": 14, - "P15": 15, - "P16": 16, - "P17": 17, "P20": 20, + "P21": 21, "P22": 22, "P23": 23, "P24": 24, @@ -360,6 +570,7 @@ BK72XX_BOARD_PINS = { "SCK": 14, "SCL1": 20, "SCL2": 0, + "SDA1": 21, "SDA2": 1, "TX1": 11, "TX2": 0, @@ -368,57 +579,19 @@ BK72XX_BOARD_PINS = { "D2": 26, "D3": 24, "D4": 6, - "D5": 9, + "D5": 7, "D6": 0, "D7": 1, - "D8": 8, - "D9": 7, + "D8": 9, + "D9": 8, "D10": 10, "D11": 11, - "D12": 15, - "D13": 22, + "D12": 22, + "D13": 21, "D14": 20, - "D15": 17, - "D16": 16, "A0": 23, }, - "cblc5": { - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "P0": 0, - "P1": 1, - "P6": 6, - "P10": 10, - "P11": 11, - "P21": 21, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 24, - "D1": 6, - "D2": 26, - "D3": 11, - "D4": 10, - "D5": 1, - "D6": 0, - "D7": 21, - }, - "cbu": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, + "lsc-lma35": { "WIRE2_SCL": 0, "WIRE2_SDA": 1, "SERIAL1_RX": 10, @@ -426,8 +599,6 @@ BK72XX_BOARD_PINS = { "SERIAL2_RX": 1, "SERIAL2_TX": 0, "ADC3": 23, - "CS": 15, - "MISO": 17, "MOSI": 16, "P0": 0, "P1": 1, @@ -438,16 +609,12 @@ BK72XX_BOARD_PINS = { "P10": 10, "P11": 11, "P14": 14, - "P15": 15, "P16": 16, - "P17": 17, - "P20": 20, "P21": 21, "P22": 22, "P23": 23, "P24": 24, "P26": 26, - "P28": 28, "PWM0": 6, "PWM1": 7, "PWM2": 8, @@ -457,167 +624,26 @@ BK72XX_BOARD_PINS = { "RX1": 10, "RX2": 1, "SCK": 14, - "SCL1": 20, "SCL2": 0, "SDA1": 21, "SDA2": 1, "TX1": 11, "TX2": 0, - "D0": 14, - "D1": 16, - "D2": 20, - "D3": 22, - "D4": 23, - "D5": 1, - "D6": 0, + "D0": 26, + "D1": 14, + "D2": 16, + "D3": 24, + "D4": 22, + "D5": 0, + "D6": 23, "D7": 8, - "D8": 7, - "D9": 6, - "D10": 26, - "D11": 24, - "D12": 11, - "D13": 10, - "D14": 28, - "D15": 9, - "D16": 17, - "D17": 15, - "D18": 21, - "A0": 23, - }, - "generic-bk7231n-qfn32-tuya": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "CS": 15, - "MISO": 17, - "MOSI": 16, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P9": 9, - "P10": 10, - "P11": 11, - "P14": 14, - "P15": 15, - "P16": 16, - "P17": 17, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "P28": 28, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM3": 9, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCK": 14, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 0, - "D1": 1, - "D2": 6, - "D3": 7, - "D4": 8, - "D5": 9, - "D6": 10, - "D7": 11, - "D8": 14, - "D9": 15, - "D10": 16, - "D11": 17, - "D12": 20, - "D13": 21, - "D14": 22, - "D15": 23, - "D16": 24, - "D17": 26, - "D18": 28, - "A0": 23, - }, - "generic-bk7231t-qfn32-tuya": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "CS": 15, - "MISO": 17, - "MOSI": 16, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P9": 9, - "P10": 10, - "P11": 11, - "P14": 14, - "P15": 15, - "P16": 16, - "P17": 17, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "P28": 28, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM3": 9, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCK": 14, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 0, - "D1": 1, - "D2": 6, - "D3": 7, - "D4": 8, - "D5": 9, - "D6": 10, - "D7": 11, - "D8": 14, - "D9": 15, - "D10": 16, - "D11": 17, - "D12": 20, - "D13": 21, - "D14": 22, - "D15": 23, - "D16": 24, - "D17": 26, - "D18": 28, + "D8": 9, + "D9": 21, + "D10": 6, + "D11": 7, + "D12": 10, + "D13": 11, + "D14": 1, "A0": 23, }, "generic-bk7252": { @@ -740,6 +766,280 @@ BK72XX_BOARD_PINS = { "A6": 12, "A7": 13, }, + "wb2l": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P10": 10, + "P11": 11, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 8, + "D1": 7, + "D2": 6, + "D3": 26, + "D4": 24, + "D5": 10, + "D6": 11, + "D7": 1, + "D8": 0, + "D9": 20, + "D10": 21, + "D11": 23, + "D12": 22, + "A0": 23, + }, + "wb1s": { + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCL2": 0, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 11, + "D1": 10, + "D2": 26, + "D3": 24, + "D4": 0, + "D5": 8, + "D6": 7, + "D7": 1, + "D8": 9, + "D9": 6, + "D10": 23, + "A0": 23, + }, + "wblc5": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P1": 1, + "P6": 6, + "P10": 10, + "P11": 11, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 24, + "D1": 6, + "D2": 26, + "D3": 10, + "D4": 11, + "D5": 1, + "D6": 0, + "D7": 20, + "D8": 21, + "D9": 22, + "D10": 23, + "A0": 23, + }, + "cb2s": { + "WIRE2_SCL": 0, + "WIRE2_SDA": 1, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_RX": 1, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P1": 1, + "P6": 6, + "P7": 7, + "P8": 8, + "P10": 10, + "P11": 11, + "P21": 21, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "RX2": 1, + "SCL2": 0, + "SDA1": 21, + "SDA2": 1, + "TX1": 11, + "TX2": 0, + "D0": 6, + "D1": 7, + "D2": 8, + "D3": 23, + "D4": 10, + "D5": 11, + "D6": 24, + "D7": 26, + "D8": 0, + "D9": 1, + "D10": 21, + "A0": 23, + }, + "wa2": { + "WIRE1_SCL": 20, + "WIRE1_SDA": 21, + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_TX": 0, + "ADC1": 4, + "ADC3": 23, + "P0": 0, + "P4": 4, + "P6": 6, + "P7": 7, + "P8": 8, + "P10": 10, + "P11": 11, + "P18": 18, + "P19": 19, + "P20": 20, + "P21": 21, + "P22": 22, + "P23": 23, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM4": 18, + "PWM5": 19, + "RX1": 10, + "SCL1": 20, + "SCL2": 0, + "SDA1": 21, + "TX1": 11, + "TX2": 0, + "D0": 8, + "D1": 7, + "D2": 6, + "D3": 23, + "D4": 10, + "D5": 11, + "D6": 18, + "D7": 19, + "D8": 20, + "D9": 4, + "D10": 0, + "D11": 21, + "D12": 22, + "A0": 23, + }, + "cb3l": { + "SERIAL1_RX": 10, + "SERIAL1_TX": 11, + "SERIAL2_TX": 0, + "ADC3": 23, + "P0": 0, + "P6": 6, + "P7": 7, + "P8": 8, + "P9": 9, + "P10": 10, + "P11": 11, + "P14": 14, + "P21": 21, + "P23": 23, + "P24": 24, + "P26": 26, + "PWM0": 6, + "PWM1": 7, + "PWM2": 8, + "PWM3": 9, + "PWM4": 24, + "PWM5": 26, + "RX1": 10, + "SCK": 14, + "SCL2": 0, + "SDA1": 21, + "TX1": 11, + "TX2": 0, + "D0": 23, + "D1": 14, + "D2": 26, + "D3": 24, + "D4": 6, + "D5": 9, + "D6": 0, + "D7": 21, + "D8": 8, + "D9": 7, + "D10": 10, + "D11": 11, + "A0": 23, + }, "lsc-lma35-t": { "WIRE2_SCL": 0, "WIRE2_SDA": 1, @@ -795,7 +1095,7 @@ BK72XX_BOARD_PINS = { "D14": 1, "A0": 23, }, - "lsc-lma35": { + "cb3se": { "WIRE2_SCL": 0, "WIRE2_SDA": 1, "SERIAL1_RX": 10, @@ -803,6 +1103,8 @@ BK72XX_BOARD_PINS = { "SERIAL2_RX": 1, "SERIAL2_TX": 0, "ADC3": 23, + "CS": 15, + "MISO": 17, "MOSI": 16, "P0": 0, "P1": 1, @@ -813,8 +1115,10 @@ BK72XX_BOARD_PINS = { "P10": 10, "P11": 11, "P14": 14, + "P15": 15, "P16": 16, - "P21": 21, + "P17": 17, + "P20": 20, "P22": 22, "P23": 23, "P24": 24, @@ -828,273 +1132,28 @@ BK72XX_BOARD_PINS = { "RX1": 10, "RX2": 1, "SCK": 14, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 26, - "D1": 14, - "D2": 16, - "D3": 24, - "D4": 22, - "D5": 0, - "D6": 23, - "D7": 8, - "D8": 9, - "D9": 21, - "D10": 6, - "D11": 7, - "D12": 10, - "D13": 11, - "D14": 1, - "A0": 23, - }, - "wa2": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_TX": 0, - "ADC1": 4, - "ADC3": 23, - "P0": 0, - "P4": 4, - "P6": 6, - "P7": 7, - "P8": 8, - "P10": 10, - "P11": 11, - "P18": 18, - "P19": 19, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM4": 18, - "PWM5": 19, - "RX1": 10, "SCL1": 20, "SCL2": 0, - "SDA1": 21, - "TX1": 11, - "TX2": 0, - "D0": 8, - "D1": 7, - "D2": 6, - "D3": 23, - "D4": 10, - "D5": 11, - "D6": 18, - "D7": 19, - "D8": 20, - "D9": 4, - "D10": 0, - "D11": 21, - "D12": 22, - "A0": 23, - }, - "wb1s": { - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P9": 9, - "P10": 10, - "P11": 11, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM3": 9, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL2": 0, "SDA2": 1, "TX1": 11, "TX2": 0, - "D0": 11, - "D1": 10, + "D0": 23, + "D1": 14, "D2": 26, "D3": 24, - "D4": 0, - "D5": 8, - "D6": 7, + "D4": 6, + "D5": 9, + "D6": 0, "D7": 1, - "D8": 9, - "D9": 6, - "D10": 23, - "A0": 23, - }, - "wb2l-m1": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P10": 10, - "P11": 11, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 8, - "D1": 7, - "D2": 6, - "D3": 26, - "D4": 24, - "D5": 10, - "D6": 11, - "D7": 1, - "D8": 0, - "D9": 20, - "D10": 21, - "D11": 23, - "D12": 22, - "A0": 23, - }, - "wb2l": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P10": 10, - "P11": 11, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 8, - "D1": 7, - "D2": 6, - "D3": 26, - "D4": 24, - "D5": 10, - "D6": 11, - "D7": 1, - "D8": 0, - "D9": 20, - "D10": 21, - "D11": 23, - "D12": 22, - "A0": 23, - }, - "wb2s": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P1": 1, - "P6": 6, - "P7": 7, - "P8": 8, - "P9": 9, - "P10": 10, - "P11": 11, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM1": 7, - "PWM2": 8, - "PWM3": 9, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 8, - "D1": 7, - "D2": 6, - "D3": 23, - "D4": 10, - "D5": 11, - "D6": 24, - "D7": 26, - "D8": 20, - "D9": 9, - "D10": 1, - "D11": 0, - "D12": 21, + "D8": 8, + "D9": 7, + "D10": 10, + "D11": 11, + "D12": 15, "D13": 22, + "D14": 20, + "D15": 17, + "D16": 16, "A0": 23, }, "wb3l": { @@ -1157,7 +1216,7 @@ BK72XX_BOARD_PINS = { "D15": 1, "A0": 23, }, - "wb3s": { + "wb2s": { "WIRE1_SCL": 20, "WIRE1_SDA": 21, "WIRE2_SCL": 0, @@ -1175,7 +1234,6 @@ BK72XX_BOARD_PINS = { "P9": 9, "P10": 10, "P11": 11, - "P14": 14, "P20": 20, "P21": 21, "P22": 22, @@ -1190,73 +1248,26 @@ BK72XX_BOARD_PINS = { "PWM5": 26, "RX1": 10, "RX2": 1, - "SCK": 14, "SCL1": 20, "SCL2": 0, "SDA1": 21, "SDA2": 1, "TX1": 11, "TX2": 0, - "D0": 23, - "D1": 14, - "D2": 26, - "D3": 24, - "D4": 6, - "D5": 7, - "D6": 0, - "D7": 1, - "D8": 9, - "D9": 8, - "D10": 10, - "D11": 11, - "D12": 22, - "D13": 21, - "D14": 20, - "A0": 23, - }, - "wblc5": { - "WIRE1_SCL": 20, - "WIRE1_SDA": 21, - "WIRE2_SCL": 0, - "WIRE2_SDA": 1, - "SERIAL1_RX": 10, - "SERIAL1_TX": 11, - "SERIAL2_RX": 1, - "SERIAL2_TX": 0, - "ADC3": 23, - "P0": 0, - "P1": 1, - "P6": 6, - "P10": 10, - "P11": 11, - "P20": 20, - "P21": 21, - "P22": 22, - "P23": 23, - "P24": 24, - "P26": 26, - "PWM0": 6, - "PWM4": 24, - "PWM5": 26, - "RX1": 10, - "RX2": 1, - "SCL1": 20, - "SCL2": 0, - "SDA1": 21, - "SDA2": 1, - "TX1": 11, - "TX2": 0, - "D0": 24, - "D1": 6, - "D2": 26, - "D3": 10, - "D4": 11, - "D5": 1, - "D6": 0, - "D7": 20, - "D8": 21, - "D9": 22, - "D10": 23, + "D0": 8, + "D1": 7, + "D2": 6, + "D3": 23, + "D4": 10, + "D5": 11, + "D6": 24, + "D7": 26, + "D8": 20, + "D9": 9, + "D10": 1, + "D11": 0, + "D12": 21, + "D13": 22, "A0": 23, }, } diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 4fbbcde6c3..8318722b80 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -35,6 +35,7 @@ from .const import ( FAMILY_BK7231N, FAMILY_COMPONENT, FAMILY_FRIENDLY, + FAMILY_RTL8710B, KEY_BOARD, KEY_COMPONENT, KEY_COMPONENT_DATA, @@ -278,11 +279,23 @@ async def component_to_code(config): cg.add_build_flag(f"-DUSE_LIBRETINY_VARIANT_{config[CONF_FAMILY]}") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", FAMILY_FRIENDLY[config[CONF_FAMILY]]) - # LibreTiny uses MULTI_NO_ATOMICS because platforms like BK7231N (ARM968E-S) lack - # exclusive load/store (no LDREX/STREX). std::atomic RMW operations require libatomic, - # which is not linked to save flash (4-8KB). Even if linked, libatomic would use locks - # (ATOMIC_INT_LOCK_FREE=1), so explicit FreeRTOS mutexes are simpler and equivalent. - cg.add_define(ThreadModel.MULTI_NO_ATOMICS) + # Set threading model based on chip architecture + component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA] + if component.supports_atomics: + # RTL87xx (Cortex-M4) and LN882x (Cortex-M4F) have LDREX/STREX + cg.add_define(ThreadModel.MULTI_ATOMICS) + else: + # BK72xx uses ARM968E-S (ARMv5TE) which lacks LDREX/STREX. + # std::atomic RMW operations would require libatomic (not linked to save + # 4-8KB flash). Even if linked, it would use locks, so explicit FreeRTOS + # mutexes are simpler and equivalent. + cg.add_define(ThreadModel.MULTI_NO_ATOMICS) + + # RTL8710B needs FreeRTOS 8.2.3+ for xTaskNotifyGive/ulTaskNotifyTake + # required by AsyncTCP 3.4.3+ (https://github.com/esphome/esphome/issues/10220) + # RTL8720C (ambz2) requires FreeRTOS 10.x so this only applies to RTL8710B + if config[CONF_FAMILY] == FAMILY_RTL8710B: + cg.add_platformio_option("custom_versions.freertos", "8.2.3") # force using arduino framework cg.add_platformio_option("framework", "arduino") diff --git a/esphome/components/libretiny/const.py b/esphome/components/libretiny/const.py index 671992f8bd..bc4ca99ab4 100644 --- a/esphome/components/libretiny/const.py +++ b/esphome/components/libretiny/const.py @@ -11,6 +11,7 @@ class LibreTinyComponent: board_pins: dict[str, dict[str, int]] pin_validation: Callable[[int], int] usage_validation: Callable[[dict], dict] + supports_atomics: bool = False # True for Cortex-M4(F) with LDREX/STREX CONF_LIBRETINY = "libretiny" diff --git a/esphome/components/libretiny/generate_components.py b/esphome/components/libretiny/generate_components.py index c750b79317..41b4389446 100644 --- a/esphome/components/libretiny/generate_components.py +++ b/esphome/components/libretiny/generate_components.py @@ -11,13 +11,27 @@ from black import FileMode, format_str from ltchiptool import Board, Family from ltchiptool.util.lvm import LVM -BASE_CODE_INIT = """ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. -# For custom pin validators, put validate_pin() or validate_usage() -# in gpio.py file in this directory. -# For changing schema/pin schema, put COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA -# in schema.py file in this directory. +BASE_CODE_INIT = ''' +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. + +To customize this component: + - Pin validators: Create gpio.py with validate_pin() or validate_usage() + - Schema extensions: Create schema.py with COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA + +Platform-specific code should be added to the main libretiny component +(__init__.py in esphome/components/libretiny/) rather than here. +""" from esphome import pins from esphome.components import libretiny @@ -31,8 +45,9 @@ from esphome.core import CORE {IMPORTS} -CODEOWNERS = ["@kuba2k2"] +CODEOWNERS = {CODEOWNERS} AUTO_LOAD = ["libretiny"] +IS_TARGET_PLATFORM = True COMPONENT_DATA = LibreTinyComponent( name=COMPONENT_{COMPONENT}, @@ -40,6 +55,7 @@ COMPONENT_DATA = LibreTinyComponent( board_pins={COMPONENT}_BOARD_PINS, pin_validation={PIN_VALIDATION}, usage_validation={USAGE_VALIDATION}, + supports_atomics={SUPPORTS_ATOMICS}, ) @@ -63,11 +79,22 @@ async def to_code(config): @pins.PIN_SCHEMA_REGISTRY.register("{COMPONENT_LOWER}", PIN_SCHEMA) async def pin_to_code(config): return await libretiny.gpio.component_pin_to_code(config) -""" +''' -BASE_CODE_BOARDS = """ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. +BASE_CODE_BOARDS = ''' +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. +""" from esphome.components.libretiny.const import {FAMILIES} @@ -76,7 +103,7 @@ from esphome.components.libretiny.const import {FAMILIES} {COMPONENT}_BOARD_PINS = {PINS_JSON} BOARDS = {COMPONENT}_BOARDS -""" +''' # variable names in component extension code VAR_SCHEMA = "COMPONENT_SCHEMA" @@ -97,6 +124,19 @@ COMPONENT_MAP = { "ln882x": "lightning-ln882x", } +# Components with Cortex-M4(F) have LDREX/STREX for native atomic support. +# BK72xx uses ARM968E-S (ARMv5TE) which lacks these instructions. +COMPONENT_SUPPORTS_ATOMICS = { + "rtl87xx": True, # Cortex-M4 + "ln882x": True, # Cortex-M4F + "bk72xx": False, # ARM968E-S +} + +# CODEOWNERS for each component. If not specified, defaults to @kuba2k2. +COMPONENT_CODEOWNERS = { + "ln882x": ["@lamauny"], +} + def subst(code: str, key: str, value: str) -> str: return code.replace(f"{{{key}}}", value) @@ -140,6 +180,7 @@ def write_component_code( "boards": {"{COMPONENT}_BOARDS", "{COMPONENT}_BOARD_PINS"}, } # substitution values + codeowners = COMPONENT_CODEOWNERS.get(component, ["@kuba2k2"]) values = dict( COMPONENT=component.upper(), COMPONENT_LOWER=component.lower(), @@ -147,6 +188,8 @@ def write_component_code( PIN_SCHEMA=PIN_SCHEMA_BASE, PIN_VALIDATION="None", USAGE_VALIDATION="None", + SUPPORTS_ATOMICS=str(COMPONENT_SUPPORTS_ATOMICS.get(component, False)), + CODEOWNERS=repr(codeowners), ) # parse gpio.py file to find custom validators diff --git a/esphome/components/ln882x/__init__.py b/esphome/components/ln882x/__init__.py index 6a76218f87..5c637bdf62 100644 --- a/esphome/components/ln882x/__init__.py +++ b/esphome/components/ln882x/__init__.py @@ -1,9 +1,23 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. -# For custom pin validators, put validate_pin() or validate_usage() -# in gpio.py file in this directory. -# For changing schema/pin schema, put COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA -# in schema.py file in this directory. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. + +To customize this component: + - Pin validators: Create gpio.py with validate_pin() or validate_usage() + - Schema extensions: Create schema.py with COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA + +Platform-specific code should be added to the main libretiny component +(__init__.py in esphome/components/libretiny/) rather than here. +""" from esphome import pins from esphome.components import libretiny @@ -27,6 +41,7 @@ COMPONENT_DATA = LibreTinyComponent( board_pins=LN882X_BOARD_PINS, pin_validation=None, usage_validation=None, + supports_atomics=True, ) diff --git a/esphome/components/ln882x/boards.py b/esphome/components/ln882x/boards.py index 43f25994a7..600371951d 100644 --- a/esphome/components/ln882x/boards.py +++ b/esphome/components/ln882x/boards.py @@ -1,9 +1,28 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. +""" from esphome.components.libretiny.const import FAMILY_LN882H LN882X_BOARDS = { + "generic-ln882hki": { + "name": "Generic - LN882HKI", + "family": FAMILY_LN882H, + }, + "wb02a": { + "name": "WB02A Wi-Fi/BLE Module", + "family": FAMILY_LN882H, + }, "wl2s": { "name": "WL2S Wi-Fi/BLE Module", "family": FAMILY_LN882H, @@ -12,13 +31,195 @@ LN882X_BOARDS = { "name": "LN-02 Wi-Fi/BLE Module", "family": FAMILY_LN882H, }, - "generic-ln882hki": { - "name": "Generic - LN882HKI", - "family": FAMILY_LN882H, - }, } LN882X_BOARD_PINS = { + "generic-ln882hki": { + "WIRE0_SCL_0": 0, + "WIRE0_SCL_1": 1, + "WIRE0_SCL_2": 2, + "WIRE0_SCL_3": 3, + "WIRE0_SCL_4": 4, + "WIRE0_SCL_5": 5, + "WIRE0_SCL_6": 6, + "WIRE0_SCL_7": 7, + "WIRE0_SCL_8": 8, + "WIRE0_SCL_9": 9, + "WIRE0_SCL_10": 10, + "WIRE0_SCL_11": 11, + "WIRE0_SCL_12": 12, + "WIRE0_SCL_13": 19, + "WIRE0_SCL_14": 20, + "WIRE0_SCL_15": 21, + "WIRE0_SCL_16": 22, + "WIRE0_SCL_17": 23, + "WIRE0_SCL_18": 24, + "WIRE0_SCL_19": 25, + "WIRE0_SDA_0": 0, + "WIRE0_SDA_1": 1, + "WIRE0_SDA_2": 2, + "WIRE0_SDA_3": 3, + "WIRE0_SDA_4": 4, + "WIRE0_SDA_5": 5, + "WIRE0_SDA_6": 6, + "WIRE0_SDA_7": 7, + "WIRE0_SDA_8": 8, + "WIRE0_SDA_9": 9, + "WIRE0_SDA_10": 10, + "WIRE0_SDA_11": 11, + "WIRE0_SDA_12": 12, + "WIRE0_SDA_13": 19, + "WIRE0_SDA_14": 20, + "WIRE0_SDA_15": 21, + "WIRE0_SDA_16": 22, + "WIRE0_SDA_17": 23, + "WIRE0_SDA_18": 24, + "WIRE0_SDA_19": 25, + "SERIAL0_RX": 3, + "SERIAL0_TX": 2, + "SERIAL1_RX": 24, + "SERIAL1_TX": 25, + "ADC2": 0, + "ADC3": 1, + "ADC4": 4, + "ADC5": 19, + "ADC6": 20, + "ADC7": 21, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA05": 5, + "PA5": 5, + "PA06": 6, + "PA6": 6, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PB03": 19, + "PB3": 19, + "PB04": 20, + "PB4": 20, + "PB05": 21, + "PB5": 21, + "PB06": 22, + "PB6": 22, + "PB07": 23, + "PB7": 23, + "PB08": 24, + "PB8": 24, + "PB09": 25, + "PB9": 25, + "RX0": 3, + "RX1": 24, + "TX0": 2, + "TX1": 25, + "D0": 0, + "D1": 1, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 5, + "D6": 6, + "D7": 7, + "D8": 8, + "D9": 9, + "D10": 10, + "D11": 11, + "D12": 12, + "D13": 19, + "D14": 20, + "D15": 21, + "D16": 22, + "D17": 23, + "D18": 24, + "D19": 25, + "A2": 0, + "A3": 1, + "A4": 4, + "A5": 19, + "A6": 20, + "A7": 21, + }, + "wb02a": { + "WIRE0_SCL_0": 7, + "WIRE0_SCL_1": 5, + "WIRE0_SCL_2": 3, + "WIRE0_SCL_3": 10, + "WIRE0_SCL_4": 2, + "WIRE0_SCL_5": 1, + "WIRE0_SCL_6": 4, + "WIRE0_SCL_7": 5, + "WIRE0_SCL_8": 9, + "WIRE0_SCL_9": 24, + "WIRE0_SCL_10": 25, + "WIRE0_SDA_0": 7, + "WIRE0_SDA_1": 5, + "WIRE0_SDA_2": 3, + "WIRE0_SDA_3": 10, + "WIRE0_SDA_4": 2, + "WIRE0_SDA_5": 1, + "WIRE0_SDA_6": 4, + "WIRE0_SDA_7": 5, + "WIRE0_SDA_8": 9, + "WIRE0_SDA_9": 24, + "WIRE0_SDA_10": 25, + "SERIAL0_RX": 3, + "SERIAL0_TX": 2, + "SERIAL1_RX": 24, + "SERIAL1_TX": 25, + "ADC3": 1, + "ADC4": 4, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA05": 5, + "PA5": 5, + "PA07": 7, + "PA7": 7, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PB08": 24, + "PB8": 24, + "PB09": 25, + "PB9": 25, + "RX0": 3, + "RX1": 24, + "SCL0": 25, + "SDA0": 25, + "TX0": 2, + "TX1": 25, + "D0": 7, + "D1": 5, + "D2": 3, + "D3": 10, + "D4": 2, + "D5": 1, + "D6": 4, + "D7": 9, + "D8": 24, + "D9": 25, + "A0": 1, + "A1": 4, + }, "wl2s": { "WIRE0_SCL_0": 7, "WIRE0_SCL_1": 12, @@ -161,125 +362,6 @@ LN882X_BOARD_PINS = { "A1": 1, "A2": 0, }, - "generic-ln882hki": { - "WIRE0_SCL_0": 0, - "WIRE0_SCL_1": 1, - "WIRE0_SCL_2": 2, - "WIRE0_SCL_3": 3, - "WIRE0_SCL_4": 4, - "WIRE0_SCL_5": 5, - "WIRE0_SCL_6": 6, - "WIRE0_SCL_7": 7, - "WIRE0_SCL_8": 8, - "WIRE0_SCL_9": 9, - "WIRE0_SCL_10": 10, - "WIRE0_SCL_11": 11, - "WIRE0_SCL_12": 12, - "WIRE0_SCL_13": 19, - "WIRE0_SCL_14": 20, - "WIRE0_SCL_15": 21, - "WIRE0_SCL_16": 22, - "WIRE0_SCL_17": 23, - "WIRE0_SCL_18": 24, - "WIRE0_SCL_19": 25, - "WIRE0_SDA_0": 0, - "WIRE0_SDA_1": 1, - "WIRE0_SDA_2": 2, - "WIRE0_SDA_3": 3, - "WIRE0_SDA_4": 4, - "WIRE0_SDA_5": 5, - "WIRE0_SDA_6": 6, - "WIRE0_SDA_7": 7, - "WIRE0_SDA_8": 8, - "WIRE0_SDA_9": 9, - "WIRE0_SDA_10": 10, - "WIRE0_SDA_11": 11, - "WIRE0_SDA_12": 12, - "WIRE0_SDA_13": 19, - "WIRE0_SDA_14": 20, - "WIRE0_SDA_15": 21, - "WIRE0_SDA_16": 22, - "WIRE0_SDA_17": 23, - "WIRE0_SDA_18": 24, - "WIRE0_SDA_19": 25, - "SERIAL0_RX": 3, - "SERIAL0_TX": 2, - "SERIAL1_RX": 24, - "SERIAL1_TX": 25, - "ADC2": 0, - "ADC3": 1, - "ADC4": 4, - "ADC5": 19, - "ADC6": 20, - "ADC7": 21, - "PA00": 0, - "PA0": 0, - "PA01": 1, - "PA1": 1, - "PA02": 2, - "PA2": 2, - "PA03": 3, - "PA3": 3, - "PA04": 4, - "PA4": 4, - "PA05": 5, - "PA5": 5, - "PA06": 6, - "PA6": 6, - "PA07": 7, - "PA7": 7, - "PA08": 8, - "PA8": 8, - "PA09": 9, - "PA9": 9, - "PA10": 10, - "PA11": 11, - "PA12": 12, - "PB03": 19, - "PB3": 19, - "PB04": 20, - "PB4": 20, - "PB05": 21, - "PB5": 21, - "PB06": 22, - "PB6": 22, - "PB07": 23, - "PB7": 23, - "PB08": 24, - "PB8": 24, - "PB09": 25, - "PB9": 25, - "RX0": 3, - "RX1": 24, - "TX0": 2, - "TX1": 25, - "D0": 0, - "D1": 1, - "D2": 2, - "D3": 3, - "D4": 4, - "D5": 5, - "D6": 6, - "D7": 7, - "D8": 8, - "D9": 9, - "D10": 10, - "D11": 11, - "D12": 12, - "D13": 19, - "D14": 20, - "D15": 21, - "D16": 22, - "D17": 23, - "D18": 24, - "D19": 25, - "A2": 0, - "A3": 1, - "A4": 4, - "A5": 19, - "A6": 20, - "A7": 21, - }, } BOARDS = LN882X_BOARDS diff --git a/esphome/components/rtl87xx/__init__.py b/esphome/components/rtl87xx/__init__.py index 8f27544108..6fd750d51e 100644 --- a/esphome/components/rtl87xx/__init__.py +++ b/esphome/components/rtl87xx/__init__.py @@ -1,18 +1,29 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. -# For custom pin validators, put validate_pin() or validate_usage() -# in gpio.py file in this directory. -# For changing schema/pin schema, put COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA -# in schema.py file in this directory. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. + +To customize this component: + - Pin validators: Create gpio.py with validate_pin() or validate_usage() + - Schema extensions: Create schema.py with COMPONENT_SCHEMA or COMPONENT_PIN_SCHEMA + +Platform-specific code should be added to the main libretiny component +(__init__.py in esphome/components/libretiny/) rather than here. +""" from esphome import pins -import esphome.codegen as cg from esphome.components import libretiny from esphome.components.libretiny.const import ( COMPONENT_RTL87XX, - FAMILY_RTL8710B, KEY_COMPONENT_DATA, - KEY_FAMILY, KEY_LIBRETINY, LibreTinyComponent, ) @@ -24,13 +35,13 @@ CODEOWNERS = ["@kuba2k2"] AUTO_LOAD = ["libretiny"] IS_TARGET_PLATFORM = True - COMPONENT_DATA = LibreTinyComponent( name=COMPONENT_RTL87XX, boards=RTL87XX_BOARDS, board_pins=RTL87XX_BOARD_PINS, pin_validation=None, usage_validation=None, + supports_atomics=True, ) @@ -48,11 +59,6 @@ CONFIG_SCHEMA.prepend_extra(_set_core_data) async def to_code(config): - # Use FreeRTOS 8.2.3+ for xTaskNotifyGive/ulTaskNotifyTake required by AsyncTCP 3.4.3+ - # https://github.com/esphome/esphome/issues/10220 - # Only for RTL8710B (ambz) - RTL8720C (ambz2) requires FreeRTOS 10.x - if CORE.data[KEY_LIBRETINY][KEY_FAMILY] == FAMILY_RTL8710B: - cg.add_platformio_option("custom_versions.freertos", "8.2.3") return await libretiny.component_to_code(config) diff --git a/esphome/components/rtl87xx/boards.py b/esphome/components/rtl87xx/boards.py index e737767a56..5a3228fb1d 100644 --- a/esphome/components/rtl87xx/boards.py +++ b/esphome/components/rtl87xx/boards.py @@ -1,21 +1,52 @@ -# This file was auto-generated by libretiny/generate_components.py -# Do not modify its contents. +""" +██╗ ██╗ █████╗ ██████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗ +██║ ██║██╔══██╗██╔══██╗████╗ ██║██║████╗ ██║██╔════╝ +██║ █╗ ██║███████║██████╔╝██╔██╗ ██║██║██╔██╗ ██║██║ ███╗ +██║███╗██║██╔══██║██╔══██╗██║╚██╗██║██║██║╚██╗██║██║ ██║ +╚███╔███╔╝██║ ██║██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝ + ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝ + + AUTO-GENERATED FILE - DO NOT EDIT! + +This file was auto-generated by libretiny/generate_components.py. +Any manual changes WILL BE LOST on regeneration. +""" from esphome.components.libretiny.const import FAMILY_RTL8710B, FAMILY_RTL8720C RTL87XX_BOARDS = { - "bw12": { - "name": "BW12", + "wr3le": { + "name": "WR3LE Wi-Fi Module", "family": FAMILY_RTL8710B, }, - "bw15": { - "name": "BW15", - "family": FAMILY_RTL8720C, + "wr2": { + "name": "WR2 Wi-Fi Module", + "family": FAMILY_RTL8710B, }, "generic-rtl8710bn-2mb-468k": { "name": "Generic - RTL8710BN (2M/468k)", "family": FAMILY_RTL8710B, }, + "wr1e": { + "name": "WR1E Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3e": { + "name": "WR3E Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "wr3": { + "name": "WR3 Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, + "afw121t": { + "name": "AFW121T", + "family": FAMILY_RTL8710B, + }, + "wr3n": { + "name": "WR3N Wi-Fi Module", + "family": FAMILY_RTL8710B, + }, "generic-rtl8710bn-2mb-788k": { "name": "Generic - RTL8710BN (2M/788k)", "family": FAMILY_RTL8710B, @@ -24,70 +55,827 @@ RTL87XX_BOARDS = { "name": "Generic - RTL8710BX (4M/980k)", "family": FAMILY_RTL8710B, }, - "generic-rtl8720cf-2mb-992k": { - "name": "Generic - RTL8720CF (2M/992k)", - "family": FAMILY_RTL8720C, - }, - "t102-v1.1": { - "name": "T102_V1.1", - "family": FAMILY_RTL8710B, - }, - "t103-v1.0": { - "name": "T103_V1.0", + "wr2e": { + "name": "WR2E Wi-Fi Module", "family": FAMILY_RTL8710B, }, "t112-v1.1": { "name": "T112_V1.1", "family": FAMILY_RTL8710B, }, - "wr1": { - "name": "WR1 Wi-Fi Module", - "family": FAMILY_RTL8710B, - }, - "wr1e": { - "name": "WR1E Wi-Fi Module", - "family": FAMILY_RTL8710B, - }, - "wr2": { - "name": "WR2 Wi-Fi Module", - "family": FAMILY_RTL8710B, - }, - "wr2e": { - "name": "WR2E Wi-Fi Module", - "family": FAMILY_RTL8710B, - }, - "wr2l": { - "name": "WR2L Wi-Fi Module", + "wr3l": { + "name": "WR3L Wi-Fi Module", "family": FAMILY_RTL8710B, }, "wr2le": { "name": "WR2LE Wi-Fi Module", "family": FAMILY_RTL8710B, }, - "wr3": { - "name": "WR3 Wi-Fi Module", + "bw15": { + "name": "BW15", + "family": FAMILY_RTL8720C, + }, + "t103-v1.0": { + "name": "T103_V1.0", "family": FAMILY_RTL8710B, }, - "wr3e": { - "name": "WR3E Wi-Fi Module", + "generic-rtl8720cf-2mb-992k": { + "name": "Generic - RTL8720CF (2M/992k)", + "family": FAMILY_RTL8720C, + }, + "bw12": { + "name": "BW12", "family": FAMILY_RTL8710B, }, - "wr3l": { - "name": "WR3L Wi-Fi Module", + "t102-v1.1": { + "name": "T102_V1.1", "family": FAMILY_RTL8710B, }, - "wr3le": { - "name": "WR3LE Wi-Fi Module", + "wr2l": { + "name": "WR2L Wi-Fi Module", "family": FAMILY_RTL8710B, }, - "wr3n": { - "name": "WR3N Wi-Fi Module", + "wr1": { + "name": "WR1 Wi-Fi Module", "family": FAMILY_RTL8710B, }, } RTL87XX_BOARD_PINS = { - "bw12": { + "wr3le": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 29, + "WIRE0_SCL_1": 22, + "WIRE0_SDA_0": 30, + "WIRE0_SDA_1": 19, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 29, + "D1": 14, + "D2": 15, + "D3": 22, + "D4": 0, + "D5": 30, + "D6": 19, + "D7": 5, + "D8": 12, + "D9": 18, + "D10": 23, + "A0": 19, + "A1": 41, + }, + "wr2": { + "WIRE0_SCL": 29, + "WIRE0_SDA": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC2": 41, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 29, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 12, + "D1": 0, + "D2": 5, + "D4": 18, + "D5": 23, + "D6": 14, + "D7": 15, + "D8": 30, + "D9": 29, + "A1": 41, + }, + "generic-rtl8710bn-2mb-468k": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "FCS": 6, + "FD0": 9, + "FD1": 7, + "FD2": 8, + "FD3": 11, + "FSCK": 10, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA06": 6, + "PA6": 6, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 0, + "D1": 5, + "D2": 6, + "D3": 7, + "D4": 8, + "D5": 9, + "D6": 10, + "D7": 11, + "D8": 12, + "D9": 14, + "D10": 15, + "D11": 18, + "D12": 19, + "D13": 22, + "D14": 23, + "D15": 29, + "D16": 30, + "A0": 19, + "A1": 41, + }, + "wr1e": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 29, + "WIRE0_SCL_1": 22, + "WIRE0_SDA_0": 30, + "WIRE0_SDA_1": 19, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM3": 12, + "PWM4": 29, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 23, + "D1": 18, + "D2": 14, + "D3": 15, + "D4": 30, + "D5": 12, + "D6": 5, + "D7": 29, + "D8": 19, + "D9": 22, + "A0": 19, + "A1": 41, + }, + "wr3e": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 29, + "WIRE0_SCL_1": 22, + "WIRE0_SDA_0": 30, + "WIRE0_SDA_1": 19, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 29, + "D1": 14, + "D2": 15, + "D3": 22, + "D4": 0, + "D5": 30, + "D6": 19, + "D7": 5, + "D8": 12, + "D9": 18, + "D10": 23, + "A0": 19, + "A1": 41, + }, + "wr3": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 22, + "D1": 19, + "D2": 14, + "D3": 15, + "D4": 0, + "D5": 29, + "D6": 30, + "D7": 5, + "D8": 12, + "D9": 18, + "D10": 23, + "A0": 19, + "A1": 41, + }, + "afw121t": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 29, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 14, + "D1": 15, + "D2": 0, + "D3": 12, + "D4": 29, + "D5": 5, + "D6": 18, + "D7": 19, + "D8": 22, + "D9": 23, + "D10": 30, + }, + "wr3n": { + "WIRE0_SCL": 29, + "WIRE0_SDA": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC2": 41, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 29, + "D1": 14, + "D2": 15, + "D3": 0, + "D4": 30, + "D5": 5, + "D6": 12, + "D7": 18, + "D8": 23, + "A1": 41, + }, + "generic-rtl8710bn-2mb-788k": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "FCS": 6, + "FD0": 9, + "FD1": 7, + "FD2": 8, + "FD3": 11, + "FSCK": 10, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA06": 6, + "PA6": 6, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 0, + "D1": 5, + "D2": 6, + "D3": 7, + "D4": 8, + "D5": 9, + "D6": 10, + "D7": 11, + "D8": 12, + "D9": 14, + "D10": 15, + "D11": 18, + "D12": 19, + "D13": 22, + "D14": 23, + "D15": 29, + "D16": 30, + "A0": 19, + "A1": 41, + }, + "generic-rtl8710bx-4mb-980k": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "FCS": 6, + "FD0": 9, + "FD1": 7, + "FD2": 8, + "FD3": 11, + "FSCK": 10, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA06": 6, + "PA6": 6, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 30, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 0, + "D1": 5, + "D2": 6, + "D3": 7, + "D4": 8, + "D5": 9, + "D6": 10, + "D7": 11, + "D8": 12, + "D9": 14, + "D10": 15, + "D11": 18, + "D12": 19, + "D13": 22, + "D14": 23, + "D15": 29, + "D16": 30, + "A0": 19, + }, + "wr2e": { + "WIRE0_SCL": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MOSI0": 23, + "MOSI1": 23, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM3": 12, + "PWM4": 29, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 12, + "D1": 19, + "D2": 5, + "D3": 18, + "D4": 23, + "D5": 14, + "D6": 15, + "D7": 30, + "D8": 29, + "A0": 19, + "A1": 41, + }, + "t112-v1.1": { "SPI0_CS": 19, "SPI0_MISO": 22, "SPI0_MOSI": 23, @@ -143,18 +931,111 @@ RTL87XX_BOARD_PINS = { "SDA1": 23, "TX0": 23, "TX2": 30, - "D0": 5, - "D1": 29, - "D2": 0, - "D3": 19, - "D4": 22, - "D5": 30, - "D6": 14, + "D0": 29, + "D1": 19, + "D2": 15, + "D3": 14, + "D4": 0, + "D5": 5, + "D6": 18, "D7": 12, - "D8": 15, + "D8": 23, + "D9": 22, + "D10": 30, + "A0": 19, + }, + "wr3l": { + "SPI0_CS": 19, + "SPI0_MISO": 22, + "SPI0_MOSI": 23, + "SPI0_SCK": 18, + "SPI1_CS": 19, + "SPI1_MISO": 22, + "SPI1_MOSI": 23, + "SPI1_SCK": 18, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_CTS": 19, + "SERIAL0_RTS": 22, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "ADC1": 19, + "ADC2": 41, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "MISO0": 22, + "MISO1": 22, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA19": 19, + "PA22": 22, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL1": 18, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 22, + "D1": 19, + "D2": 14, + "D3": 15, + "D4": 0, + "D5": 29, + "D6": 30, + "D7": 5, + "D8": 12, "D9": 18, "D10": 23, "A0": 19, + "A1": 41, + }, + "wr2le": { + "MISO0": 22, + "MISO1": 22, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA22": 22, + "PWM0": 14, + "PWM1": 15, + "PWM3": 12, + "PWM4": 5, + "PWM5": 22, + "RTS0": 22, + "SCL0": 22, + "D0": 15, + "D1": 14, + "D2": 5, + "D3": 22, + "D4": 12, }, "bw15": { "SPI0_CS_0": 2, @@ -226,7 +1107,7 @@ RTL87XX_BOARD_PINS = { "D11": 13, "D12": 14, }, - "generic-rtl8710bn-2mb-468k": { + "t103-v1.0": { "SPI0_CS": 19, "SPI0_MISO": 22, "SPI0_MOSI": 23, @@ -252,12 +1133,6 @@ RTL87XX_BOARD_PINS = { "CS0": 19, "CS1": 19, "CTS0": 19, - "FCS": 6, - "FD0": 9, - "FD1": 7, - "FD2": 8, - "FD3": 11, - "FSCK": 10, "MISO0": 22, "MISO1": 22, "MOSI0": 23, @@ -266,16 +1141,6 @@ RTL87XX_BOARD_PINS = { "PA0": 0, "PA05": 5, "PA5": 5, - "PA06": 6, - "PA6": 6, - "PA07": 7, - "PA7": 7, - "PA08": 8, - "PA8": 8, - "PA09": 9, - "PA9": 9, - "PA10": 10, - "PA11": 11, "PA12": 12, "PA14": 14, "PA15": 15, @@ -288,7 +1153,7 @@ RTL87XX_BOARD_PINS = { "PWM1": 15, "PWM2": 0, "PWM3": 12, - "PWM4": 30, + "PWM4": 5, "PWM5": 22, "RTS0": 22, "RX0": 18, @@ -299,210 +1164,20 @@ RTL87XX_BOARD_PINS = { "SDA1": 23, "TX0": 23, "TX2": 30, - "D0": 0, - "D1": 5, - "D2": 6, - "D3": 7, - "D4": 8, - "D5": 9, - "D6": 10, - "D7": 11, + "D0": 19, + "D1": 14, + "D2": 15, + "D3": 0, + "D4": 22, + "D5": 29, + "D6": 30, + "D7": 5, "D8": 12, - "D9": 14, - "D10": 15, - "D11": 18, - "D12": 19, - "D13": 22, - "D14": 23, - "D15": 29, - "D16": 30, + "D9": 18, + "D10": 23, "A0": 19, "A1": 41, }, - "generic-rtl8710bn-2mb-788k": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 22, - "WIRE0_SCL_1": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "FCS": 6, - "FD0": 9, - "FD1": 7, - "FD2": 8, - "FD3": 11, - "FSCK": 10, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA06": 6, - "PA6": 6, - "PA07": 7, - "PA7": 7, - "PA08": 8, - "PA8": 8, - "PA09": 9, - "PA9": 9, - "PA10": 10, - "PA11": 11, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 30, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 0, - "D1": 5, - "D2": 6, - "D3": 7, - "D4": 8, - "D5": 9, - "D6": 10, - "D7": 11, - "D8": 12, - "D9": 14, - "D10": 15, - "D11": 18, - "D12": 19, - "D13": 22, - "D14": 23, - "D15": 29, - "D16": 30, - "A0": 19, - "A1": 41, - }, - "generic-rtl8710bx-4mb-980k": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 22, - "WIRE0_SCL_1": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "FCS": 6, - "FD0": 9, - "FD1": 7, - "FD2": 8, - "FD3": 11, - "FSCK": 10, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA06": 6, - "PA6": 6, - "PA07": 7, - "PA7": 7, - "PA08": 8, - "PA8": 8, - "PA09": 9, - "PA9": 9, - "PA10": 10, - "PA11": 11, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 30, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 0, - "D1": 5, - "D2": 6, - "D3": 7, - "D4": 8, - "D5": 9, - "D6": 10, - "D7": 11, - "D8": 12, - "D9": 14, - "D10": 15, - "D11": 18, - "D12": 19, - "D13": 22, - "D14": 23, - "D15": 29, - "D16": 30, - "A0": 19, - }, "generic-rtl8720cf-2mb-992k": { "SPI0_CS_0": 2, "SPI0_CS_1": 7, @@ -601,124 +1276,7 @@ RTL87XX_BOARD_PINS = { "D18": 20, "D19": 23, }, - "t102-v1.1": { - "WIRE0_SCL": 29, - "WIRE0_SDA": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 29, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL0": 29, - "SCL1": 18, - "SDA0": 30, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 12, - "D1": 0, - "D2": 5, - "D3": 30, - "D4": 29, - "D5": 18, - "D6": 23, - "D7": 14, - "D8": 15, - }, - "t103-v1.0": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 22, - "WIRE0_SCL_1": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 19, - "D1": 14, - "D2": 15, - "D3": 0, - "D4": 22, - "D5": 29, - "D6": 30, - "D7": 5, - "D8": 12, - "D9": 18, - "D10": 23, - "A0": 19, - "A1": 41, - }, - "t112-v1.1": { + "bw12": { "SPI0_CS": 19, "SPI0_MISO": 22, "SPI0_MOSI": 23, @@ -774,17 +1332,86 @@ RTL87XX_BOARD_PINS = { "SDA1": 23, "TX0": 23, "TX2": 30, - "D0": 29, - "D1": 19, - "D2": 15, - "D3": 14, - "D4": 0, - "D5": 5, - "D6": 18, + "D0": 5, + "D1": 29, + "D2": 0, + "D3": 19, + "D4": 22, + "D5": 30, + "D6": 14, "D7": 12, - "D8": 23, - "D9": 22, - "D10": 30, + "D8": 15, + "D9": 18, + "D10": 23, + "A0": 19, + }, + "t102-v1.1": { + "WIRE0_SCL": 29, + "WIRE0_SDA": 30, + "WIRE1_SCL": 18, + "WIRE1_SDA": 23, + "SERIAL0_RX": 18, + "SERIAL0_TX": 23, + "SERIAL2_RX": 29, + "SERIAL2_TX": 30, + "MOSI0": 23, + "MOSI1": 23, + "PA00": 0, + "PA0": 0, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA18": 18, + "PA23": 23, + "PA29": 29, + "PA30": 30, + "PWM1": 15, + "PWM2": 0, + "PWM3": 12, + "PWM4": 29, + "RX0": 18, + "RX2": 29, + "SCK0": 18, + "SCK1": 18, + "SCL0": 29, + "SCL1": 18, + "SDA0": 30, + "SDA1": 23, + "TX0": 23, + "TX2": 30, + "D0": 12, + "D1": 0, + "D2": 5, + "D3": 30, + "D4": 29, + "D5": 18, + "D6": 23, + "D7": 14, + "D8": 15, + }, + "wr2l": { + "ADC1": 19, + "CS0": 19, + "CS1": 19, + "CTS0": 19, + "PA05": 5, + "PA5": 5, + "PA12": 12, + "PA14": 14, + "PA15": 15, + "PA19": 19, + "PWM0": 14, + "PWM1": 15, + "PWM3": 12, + "PWM4": 5, + "SDA0": 19, + "D0": 15, + "D1": 14, + "D2": 5, + "D3": 19, + "D4": 12, "A0": 19, }, "wr1": { @@ -855,550 +1482,6 @@ RTL87XX_BOARD_PINS = { "A0": 19, "A1": 41, }, - "wr1e": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM3": 12, - "PWM4": 29, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 23, - "D1": 18, - "D2": 14, - "D3": 15, - "D4": 30, - "D5": 12, - "D6": 5, - "D7": 29, - "D8": 19, - "D9": 22, - "A0": 19, - "A1": 41, - }, - "wr2": { - "WIRE0_SCL": 29, - "WIRE0_SDA": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC2": 41, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 29, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL0": 29, - "SCL1": 18, - "SDA0": 30, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 12, - "D1": 0, - "D2": 5, - "D4": 18, - "D5": 23, - "D6": 14, - "D7": 15, - "D8": 30, - "D9": 29, - "A1": 41, - }, - "wr2e": { - "WIRE0_SCL": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MOSI0": 23, - "MOSI1": 23, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM3": 12, - "PWM4": 29, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL0": 29, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 12, - "D1": 19, - "D2": 5, - "D3": 18, - "D4": 23, - "D5": 14, - "D6": 15, - "D7": 30, - "D8": 29, - "A0": 19, - "A1": 41, - }, - "wr2l": { - "ADC1": 19, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA19": 19, - "PWM0": 14, - "PWM1": 15, - "PWM3": 12, - "PWM4": 5, - "SDA0": 19, - "D0": 15, - "D1": 14, - "D2": 5, - "D3": 19, - "D4": 12, - "A0": 19, - }, - "wr2le": { - "MISO0": 22, - "MISO1": 22, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA22": 22, - "PWM0": 14, - "PWM1": 15, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "SCL0": 22, - "D0": 15, - "D1": 14, - "D2": 5, - "D3": 22, - "D4": 12, - }, - "wr3": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 22, - "WIRE0_SCL_1": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 22, - "D1": 19, - "D2": 14, - "D3": 15, - "D4": 0, - "D5": 29, - "D6": 30, - "D7": 5, - "D8": 12, - "D9": 18, - "D10": 23, - "A0": 19, - "A1": 41, - }, - "wr3e": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 29, - "D1": 14, - "D2": 15, - "D3": 22, - "D4": 0, - "D5": 30, - "D6": 19, - "D7": 5, - "D8": 12, - "D9": 18, - "D10": 23, - "A0": 19, - "A1": 41, - }, - "wr3l": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 22, - "WIRE0_SCL_1": 29, - "WIRE0_SDA_0": 19, - "WIRE0_SDA_1": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 22, - "D1": 19, - "D2": 14, - "D3": 15, - "D4": 0, - "D5": 29, - "D6": 30, - "D7": 5, - "D8": 12, - "D9": 18, - "D10": 23, - "A0": 19, - "A1": 41, - }, - "wr3le": { - "SPI0_CS": 19, - "SPI0_MISO": 22, - "SPI0_MOSI": 23, - "SPI0_SCK": 18, - "SPI1_CS": 19, - "SPI1_MISO": 22, - "SPI1_MOSI": 23, - "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_CTS": 19, - "SERIAL0_RTS": 22, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC1": 19, - "ADC2": 41, - "CS0": 19, - "CS1": 19, - "CTS0": 19, - "MISO0": 22, - "MISO1": 22, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA19": 19, - "PA22": 22, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "PWM5": 22, - "RTS0": 22, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL1": 18, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 29, - "D1": 14, - "D2": 15, - "D3": 22, - "D4": 0, - "D5": 30, - "D6": 19, - "D7": 5, - "D8": 12, - "D9": 18, - "D10": 23, - "A0": 19, - "A1": 41, - }, - "wr3n": { - "WIRE0_SCL": 29, - "WIRE0_SDA": 30, - "WIRE1_SCL": 18, - "WIRE1_SDA": 23, - "SERIAL0_RX": 18, - "SERIAL0_TX": 23, - "SERIAL2_RX": 29, - "SERIAL2_TX": 30, - "ADC2": 41, - "MOSI0": 23, - "MOSI1": 23, - "PA00": 0, - "PA0": 0, - "PA05": 5, - "PA5": 5, - "PA12": 12, - "PA14": 14, - "PA15": 15, - "PA18": 18, - "PA23": 23, - "PA29": 29, - "PA30": 30, - "PWM1": 15, - "PWM2": 0, - "PWM3": 12, - "PWM4": 5, - "RX0": 18, - "RX2": 29, - "SCK0": 18, - "SCK1": 18, - "SCL0": 29, - "SCL1": 18, - "SDA0": 30, - "SDA1": 23, - "TX0": 23, - "TX2": 30, - "D0": 29, - "D1": 14, - "D2": 15, - "D3": 0, - "D4": 30, - "D5": 5, - "D6": 12, - "D7": 18, - "D8": 23, - "A1": 41, - }, } BOARDS = RTL87XX_BOARDS diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 8b713523b6..b28cb947c7 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -612,8 +612,9 @@ uint64_t Scheduler::millis_64_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags // - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, RP2040, etc.) - // - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny) - // - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, etc.) + // - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny BK72xx) + // - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, LibreTiny + // RTL87xx/LN882x, etc.) // // Make sure all changes are synchronized if you edit this function. // diff --git a/tests/components/libretiny/test.ln882x-ard.yaml b/tests/components/libretiny/test.ln882x-ard.yaml new file mode 100644 index 0000000000..fa33431b92 --- /dev/null +++ b/tests/components/libretiny/test.ln882x-ard.yaml @@ -0,0 +1,2 @@ +logger: + level: VERBOSE diff --git a/tests/components/libretiny/test.rtl87xx-ard.yaml b/tests/components/libretiny/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..fa33431b92 --- /dev/null +++ b/tests/components/libretiny/test.rtl87xx-ard.yaml @@ -0,0 +1,2 @@ +logger: + level: VERBOSE From e45cad45fe360de3be7992dc0ce1b43e22cbf01b Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Tue, 13 Jan 2026 23:39:28 +0100 Subject: [PATCH 0096/2030] [nrf52,zigbee] Add binary output as switch (#13083) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/switch/__init__.py | 5 +- esphome/components/zigbee/__init__.py | 16 ++- esphome/components/zigbee/const_zephyr.py | 2 + .../zigbee/zigbee_switch_zephyr.cpp | 111 ++++++++++++++++++ .../components/zigbee/zigbee_switch_zephyr.h | 83 +++++++++++++ esphome/components/zigbee/zigbee_zephyr.cpp | 8 +- esphome/components/zigbee/zigbee_zephyr.h | 2 +- esphome/components/zigbee/zigbee_zephyr.py | 34 +++++- tests/components/zigbee/common.yaml | 9 +- 9 files changed, 260 insertions(+), 10 deletions(-) create mode 100644 esphome/components/zigbee/zigbee_switch_zephyr.cpp create mode 100644 esphome/components/zigbee/zigbee_switch_zephyr.h diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index e9473012cf..7424d7c92f 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -1,7 +1,7 @@ from esphome import automation from esphome.automation import Condition, maybe_simple_id import esphome.codegen as cg -from esphome.components import mqtt, web_server +from esphome.components import mqtt, web_server, zigbee import esphome.config_validation as cv from esphome.const import ( CONF_DEVICE_CLASS, @@ -74,6 +74,7 @@ validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True) _SWITCH_SCHEMA = ( cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend(zigbee.SWITCH_SCHEMA) .extend( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSwitchComponent), @@ -103,6 +104,7 @@ _SWITCH_SCHEMA = ( _SWITCH_SCHEMA.add_extra(entity_duplicate_validator("switch")) +_SWITCH_SCHEMA.add_extra(zigbee.validate_switch) def switch_schema( @@ -165,6 +167,7 @@ async def setup_switch_core_(var, config): cg.add(var.set_device_class(device_class)) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) + await zigbee.setup_switch(var, config) async def register_switch(var, config): diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index e363164997..2281dd38a9 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -23,7 +23,7 @@ from .const_zephyr import ( ZigbeeComponent, zigbee_ns, ) -from .zigbee_zephyr import zephyr_binary_sensor, zephyr_sensor +from .zigbee_zephyr import zephyr_binary_sensor, zephyr_sensor, zephyr_switch _LOGGER = logging.getLogger(__name__) @@ -41,6 +41,7 @@ def zigbee_set_core_data(config: ConfigType) -> ConfigType: BINARY_SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_binary_sensor) SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_sensor) +SWITCH_SCHEMA = cv.Schema({}).extend(zephyr_switch) CONFIG_SCHEMA = cv.All( cv.Schema( @@ -107,6 +108,15 @@ async def setup_sensor(entity: cg.MockObj, config: ConfigType) -> None: await zephyr_setup_sensor(entity, config) +async def setup_switch(entity: cg.MockObj, config: ConfigType) -> None: + if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): + return + if CORE.using_zephyr: + from .zigbee_zephyr import zephyr_setup_switch + + await zephyr_setup_switch(entity, config) + + def consume_endpoint(config: ConfigType) -> ConfigType: if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): return config @@ -130,6 +140,10 @@ def validate_sensor(config: ConfigType) -> ConfigType: return consume_endpoint(config) +def validate_switch(config: ConfigType) -> ConfigType: + return consume_endpoint(config) + + ZIGBEE_ACTION_SCHEMA = automation.maybe_simple_id( cv.Schema( { diff --git a/esphome/components/zigbee/const_zephyr.py b/esphome/components/zigbee/const_zephyr.py index 8d1f229b6e..0372f22593 100644 --- a/esphome/components/zigbee/const_zephyr.py +++ b/esphome/components/zigbee/const_zephyr.py @@ -11,6 +11,7 @@ CONF_ON_JOIN = "on_join" CONF_WIPE_ON_BOOT = "wipe_on_boot" CONF_ZIGBEE_BINARY_SENSOR = "zigbee_binary_sensor" CONF_ZIGBEE_SENSOR = "zigbee_sensor" +CONF_ZIGBEE_SWITCH = "zigbee_switch" CONF_POWER_SOURCE = "power_source" POWER_SOURCE = { "UNKNOWN": "ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN", @@ -35,3 +36,4 @@ ZB_ZCL_CLUSTER_ID_BASIC = "ZB_ZCL_CLUSTER_ID_BASIC" ZB_ZCL_CLUSTER_ID_IDENTIFY = "ZB_ZCL_CLUSTER_ID_IDENTIFY" ZB_ZCL_CLUSTER_ID_BINARY_INPUT = "ZB_ZCL_CLUSTER_ID_BINARY_INPUT" ZB_ZCL_CLUSTER_ID_ANALOG_INPUT = "ZB_ZCL_CLUSTER_ID_ANALOG_INPUT" +ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT = "ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT" diff --git a/esphome/components/zigbee/zigbee_switch_zephyr.cpp b/esphome/components/zigbee/zigbee_switch_zephyr.cpp new file mode 100644 index 0000000000..5454f262f9 --- /dev/null +++ b/esphome/components/zigbee/zigbee_switch_zephyr.cpp @@ -0,0 +1,111 @@ +#include "zigbee_switch_zephyr.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_SWITCH) +#include "esphome/core/log.h" +#include + +extern "C" { +#include +#include +#include +#include +#include +} + +namespace esphome::zigbee { + +static const char *const TAG = "zigbee_on_off.switch"; + +void ZigbeeSwitch::dump_config() { + ESP_LOGCONFIG(TAG, + "Zigbee Switch\n" + " Endpoint: %d, present_value %u", + this->endpoint_, this->cluster_attributes_->present_value); +} + +void ZigbeeSwitch::setup() { + this->parent_->add_callback(this->endpoint_, [this](zb_bufid_t bufid) { this->zcl_device_cb_(bufid); }); + this->switch_->add_on_state_callback([this](bool state) { + this->cluster_attributes_->present_value = state ? ZB_TRUE : ZB_FALSE; + ESP_LOGD(TAG, "Set attribute endpoint: %d, present_value %d", this->endpoint_, + this->cluster_attributes_->present_value); + ZB_ZCL_SET_ATTRIBUTE(this->endpoint_, ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, + ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID, &this->cluster_attributes_->present_value, + ZB_FALSE); + this->parent_->flush(); + }); +} + +void ZigbeeSwitch::zcl_device_cb_(zb_bufid_t bufid) { + zb_zcl_device_callback_param_t *p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); + zb_zcl_device_callback_id_t device_cb_id = p_device_cb_param->device_cb_id; + zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; + zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; + + p_device_cb_param->status = RET_OK; + + switch (device_cb_id) { + /* ZCL set attribute value */ + case ZB_ZCL_SET_ATTR_VALUE_CB_ID: + if (cluster_id == ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT) { + uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8; + ESP_LOGI(TAG, "Binary output attribute setting to %hd", value); + if (attr_id == ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID) { + this->defer([this, value]() { + this->cluster_attributes_->present_value = value ? ZB_TRUE : ZB_FALSE; + this->switch_->publish_state(value); + }); + } + } else { + /* other clusters attribute handled here */ + ESP_LOGI(TAG, "Unhandled cluster attribute id: %d", cluster_id); + } + break; + default: + p_device_cb_param->status = RET_ERROR; + break; + } + + ESP_LOGD(TAG, "%s status: %hd", __func__, p_device_cb_param->status); +} + +const zb_uint8_t ZB_ZCL_BINARY_OUTPUT_STATUS_FLAG_MAX_VALUE = 0x0F; + +static zb_ret_t check_value_binary_output_server(zb_uint16_t attr_id, zb_uint8_t endpoint, + zb_uint8_t *value) { // NOLINT(readability-non-const-parameter) + zb_ret_t ret = RET_OK; + ZVUNUSED(endpoint); + + switch (attr_id) { + case ZB_ZCL_ATTR_BINARY_OUTPUT_OUT_OF_SERVICE_ID: + case ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID: + ret = ZB_ZCL_CHECK_BOOL_VALUE(*value) ? RET_OK : RET_ERROR; + break; + + case ZB_ZCL_ATTR_BINARY_OUTPUT_STATUS_FLAG_ID: + if (*value > ZB_ZCL_BINARY_OUTPUT_STATUS_FLAG_MAX_VALUE) { + ret = RET_ERROR; + } + break; + + default: + break; + } + + return ret; +} + +} // namespace esphome::zigbee + +void zb_zcl_binary_output_init_server() { + zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, + esphome::zigbee::check_value_binary_output_server, + (zb_zcl_cluster_write_attr_hook_t) NULL, (zb_zcl_cluster_handler_t) NULL); +} + +void zb_zcl_binary_output_init_client() { + zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_CLIENT_ROLE, + (zb_zcl_cluster_check_value_t) NULL, (zb_zcl_cluster_write_attr_hook_t) NULL, + (zb_zcl_cluster_handler_t) NULL); +} + +#endif diff --git a/esphome/components/zigbee/zigbee_switch_zephyr.h b/esphome/components/zigbee/zigbee_switch_zephyr.h new file mode 100644 index 0000000000..b774c23b3c --- /dev/null +++ b/esphome/components/zigbee/zigbee_switch_zephyr.h @@ -0,0 +1,83 @@ +#pragma once + +#include "esphome/components/zigbee/zigbee_zephyr.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_SWITCH) +#include "esphome/core/component.h" +#include "esphome/components/switch/switch.h" +extern "C" { +#include +#include +} + +#define ZB_ZCL_BINARY_OUTPUT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t) 0x0001u) + +// NOLINTNEXTLINE(readability-identifier-naming) +enum zb_zcl_binary_output_attr_e { + ZB_ZCL_ATTR_BINARY_OUTPUT_DESCRIPTION_ID = 0x001C, + ZB_ZCL_ATTR_BINARY_OUTPUT_OUT_OF_SERVICE_ID = 0x0051, + ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID = 0x0055, + ZB_ZCL_ATTR_BINARY_OUTPUT_STATUS_FLAG_ID = 0x006F, +}; + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_OUTPUT_OUT_OF_SERVICE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_BINARY_OUTPUT_OUT_OF_SERVICE_ID, ZB_ZCL_ATTR_TYPE_BOOL, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID, ZB_ZCL_ATTR_TYPE_BOOL, \ + ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_REPORTING, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_OUTPUT_STATUS_FLAG_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_BINARY_OUTPUT_STATUS_FLAG_ID, ZB_ZCL_ATTR_TYPE_8BITMAP, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_BINARY_OUTPUT_DESCRIPTION_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_BINARY_OUTPUT_DESCRIPTION_ID, ZB_ZCL_ATTR_TYPE_CHAR_STRING, ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ + (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), (void *) (data_ptr) \ + } + +#define ESPHOME_ZB_ZCL_DECLARE_BINARY_OUTPUT_ATTRIB_LIST(attr_list, out_of_service, present_value, status_flag, \ + description) \ + ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_BINARY_OUTPUT) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_OUTPUT_OUT_OF_SERVICE_ID, (out_of_service)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID, (present_value)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_OUTPUT_STATUS_FLAG_ID, (status_flag)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_BINARY_OUTPUT_DESCRIPTION_ID, (description)) \ + ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST + +void zb_zcl_binary_output_init_server(); +void zb_zcl_binary_output_init_client(); + +#define ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT_SERVER_ROLE_INIT zb_zcl_binary_output_init_server +#define ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT_CLIENT_ROLE_INIT zb_zcl_binary_output_init_client + +namespace esphome::zigbee { + +class ZigbeeSwitch : public ZigbeeEntity, public Component { + public: + ZigbeeSwitch(switch_::Switch *s) : switch_(s) {} + void set_cluster_attributes(BinaryAttrs &cluster_attributes) { this->cluster_attributes_ = &cluster_attributes; } + + void setup() override; + + void dump_config() override; + + protected: + void zcl_device_cb_(zb_bufid_t bufid); + + BinaryAttrs *cluster_attributes_{nullptr}; + switch_::Switch *switch_; +}; + +} // namespace esphome::zigbee +#endif diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index 9a421aaec1..e43ab8f84d 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -104,9 +104,15 @@ void ZigbeeComponent::zcl_device_cb(zb_bufid_t bufid) { ESP_LOGI(TAG, "Zcl_device_cb %s id %hd, cluster_id %d, attr_id %d, endpoint: %d", __func__, device_cb_id, cluster_id, attr_id, endpoint); + /* Set default response value. */ + p_device_cb_param->status = RET_OK; + // endpoints are enumerated from 1 if (global_zigbee->callbacks_.size() >= endpoint) { - global_zigbee->callbacks_[endpoint - 1](bufid); + const auto &cb = global_zigbee->callbacks_[endpoint - 1]; + if (cb) { + cb(bufid); + } return; } p_device_cb_param->status = RET_ERROR; diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index fa23907bf4..d5f1257f9c 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -81,7 +81,7 @@ class ZigbeeComponent : public Component { #ifdef USE_ZIGBEE_WIPE_ON_BOOT void erase_flash_(int area); #endif - StaticVector, ZIGBEE_ENDPOINTS_COUNT> callbacks_; + std::array, ZIGBEE_ENDPOINTS_COUNT> callbacks_{}; CallbackManager join_cb_; Trigger<> join_trigger_; bool need_flush_{false}; diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index 71ea0da6a7..7f1f7dc57f 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -55,6 +55,7 @@ from .const_zephyr import ( CONF_ZIGBEE_BINARY_SENSOR, CONF_ZIGBEE_ID, CONF_ZIGBEE_SENSOR, + CONF_ZIGBEE_SWITCH, KEY_EP_NUMBER, KEY_ZIGBEE, POWER_SOURCE, @@ -62,6 +63,7 @@ from .const_zephyr import ( ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ZB_ZCL_CLUSTER_ID_BASIC, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, + ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_ID_IDENTIFY, ZB_ZCL_IDENTIFY_ATTRS_T, AnalogAttrs, @@ -72,6 +74,7 @@ from .const_zephyr import ( ZigbeeBinarySensor = zigbee_ns.class_("ZigbeeBinarySensor", cg.Component) ZigbeeSensor = zigbee_ns.class_("ZigbeeSensor", cg.Component) +ZigbeeSwitch = zigbee_ns.class_("ZigbeeSwitch", cg.Component) # BACnet engineering units mapping (ZCL uses BACnet unit codes) # See: https://github.com/zigpy/zha/blob/dev/zha/application/platforms/number/bacnet.py @@ -126,6 +129,15 @@ zephyr_sensor = cv.Schema( } ) +zephyr_switch = cv.Schema( + { + cv.OnlyWith(CONF_ZIGBEE_ID, ["nrf52", "zigbee"]): cv.use_id(ZigbeeComponent), + cv.OnlyWith(CONF_ZIGBEE_SWITCH, ["nrf52", "zigbee"]): cv.declare_id( + ZigbeeSwitch + ), + } +) + async def zephyr_to_code(config: ConfigType) -> None: zephyr_add_prj_conf("ZIGBEE", True) @@ -320,6 +332,10 @@ async def zephyr_setup_sensor(entity: cg.MockObj, config: ConfigType) -> None: CORE.add_job(_add_sensor, entity, config) +async def zephyr_setup_switch(entity: cg.MockObj, config: ConfigType) -> None: + CORE.add_job(_add_switch, entity, config) + + def _slot_index() -> int: """Find the next available endpoint slot""" slot = next( @@ -332,7 +348,7 @@ def _slot_index() -> int: return slot -async def _add_zigbee_input( +async def _add_zigbee_ep( entity: cg.MockObj, config: ConfigType, component_key, @@ -389,7 +405,7 @@ async def _add_zigbee_input( async def _add_binary_sensor(entity: cg.MockObj, config: ConfigType) -> None: - await _add_zigbee_input( + await _add_zigbee_ep( entity, config, CONF_ZIGBEE_BINARY_SENSOR, @@ -405,7 +421,7 @@ async def _add_sensor(entity: cg.MockObj, config: ConfigType) -> None: unit = config.get(CONF_UNIT_OF_MEASUREMENT, "") bacnet_unit = BACNET_UNITS.get(unit, BACNET_UNIT_NO_UNITS) - await _add_zigbee_input( + await _add_zigbee_ep( entity, config, CONF_ZIGBEE_SENSOR, @@ -415,3 +431,15 @@ async def _add_sensor(entity: cg.MockObj, config: ConfigType) -> None: "ZB_HA_CUSTOM_ATTR_DEVICE_ID", extra_field_values={"engineering_units": bacnet_unit}, ) + + +async def _add_switch(entity: cg.MockObj, config: ConfigType) -> None: + await _add_zigbee_ep( + entity, + config, + CONF_ZIGBEE_SWITCH, + BinaryAttrs, + "ESPHOME_ZB_ZCL_DECLARE_BINARY_OUTPUT_ATTRIB_LIST", + ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, + "ZB_HA_CUSTOM_ATTR_DEVICE_ID", + ) diff --git a/tests/components/zigbee/common.yaml b/tests/components/zigbee/common.yaml index c91569bdbe..11100e1e0c 100644 --- a/tests/components/zigbee/common.yaml +++ b/tests/components/zigbee/common.yaml @@ -11,9 +11,7 @@ binary_sensor: - platform: template name: "Garage Door Open 5" - platform: template - name: "Garage Door Open 6" - - platform: template - name: "Garage Door Open 7" + name: "Garage Door Internal" internal: True sensor: @@ -36,3 +34,8 @@ output: type: binary write_action: - zigbee.factory_reset + +switch: + - platform: template + name: "Template Switch" + optimistic: true From 45e000f09148591e8c84daf6d35fb6a429e1e6ef Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 13 Jan 2026 18:27:45 -0500 Subject: [PATCH 0097/2030] [ota] Mark partition valid when OTA begins to prevent rollback blocking (#13195) Co-authored-by: Claude Opus 4.5 --- .../components/esp32_hosted/update/esp32_hosted_update.cpp | 7 +++++++ esphome/components/ota/ota_backend_esp_idf.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index fcec1a5f20..9f8ae3277e 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef USE_ESP32_HOSTED_HTTP_UPDATE #include "esphome/components/json/json_util.h" @@ -442,6 +443,12 @@ void Esp32HostedUpdate::perform(bool force) { this->status_clear_error(); this->publish_state(); +#ifdef USE_OTA_ROLLBACK + // Mark the host partition as valid before rebooting, in case the safe mode + // timer hasn't expired yet. + esp_ota_mark_app_valid_cancel_rollback(); +#endif + // Schedule a restart to ensure everything is in sync ESP_LOGI(TAG, "Restarting in 1 second"); this->set_timeout(1000, []() { App.safe_reboot(); }); diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index f278c3741f..93c65a9624 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -14,6 +14,13 @@ namespace ota { std::unique_ptr make_ota_backend() { return make_unique(); } OTAResponseTypes IDFOTABackend::begin(size_t image_size) { +#ifdef USE_OTA_ROLLBACK + // If we're starting an OTA, the current boot is good enough - mark it valid + // to prevent rollback and allow the OTA to proceed even if the safe mode + // timer hasn't expired yet. + esp_ota_mark_app_valid_cancel_rollback(); +#endif + this->partition_ = esp_ota_get_next_update_partition(nullptr); if (this->partition_ == nullptr) { return OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION; From 52c631384a224002a286fa21296ffdfc2a8b39cf Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:28:24 +1100 Subject: [PATCH 0098/2030] [epaper_spi] Add Waveshare 2.13v3 (#13117) --- esphome/components/epaper_spi/display.py | 1 + esphome/components/epaper_spi/epaper_spi.cpp | 53 +--- esphome/components/epaper_spi/epaper_spi.h | 23 +- ...er_spi_ssd1677.cpp => epaper_spi_mono.cpp} | 56 ++-- ...epaper_spi_ssd1677.h => epaper_spi_mono.h} | 13 +- .../epaper_spi/epaper_spi_spectra_e6.cpp | 13 +- .../epaper_spi/epaper_waveshare.cpp | 47 +++ .../components/epaper_spi/epaper_waveshare.h | 30 ++ .../components/epaper_spi/models/__init__.py | 3 + .../components/epaper_spi/models/ssd1677.py | 15 +- .../components/epaper_spi/models/waveshare.py | 88 ++++++ tests/component_tests/epaper_spi/__init__.py | 0 tests/component_tests/epaper_spi/test_init.py | 291 ++++++++++++++++++ .../epaper_spi/test.esp32-s3-idf.yaml | 32 +- 14 files changed, 566 insertions(+), 99 deletions(-) rename esphome/components/epaper_spi/{epaper_spi_ssd1677.cpp => epaper_spi_mono.cpp} (53%) rename esphome/components/epaper_spi/{epaper_spi_ssd1677.h => epaper_spi_mono.h} (57%) create mode 100644 esphome/components/epaper_spi/epaper_waveshare.cpp create mode 100644 esphome/components/epaper_spi/epaper_waveshare.h create mode 100644 esphome/components/epaper_spi/models/waveshare.py create mode 100644 tests/component_tests/epaper_spi/__init__.py create mode 100644 tests/component_tests/epaper_spi/test_init.py diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index b7e71a3cae..a77e291237 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -184,6 +184,7 @@ async def to_code(config): height, init_sequence_id, init_sequence_length, + *model.get_constructor_args(config), ) # Rotation is handled by setting the transform diff --git a/esphome/components/epaper_spi/epaper_spi.cpp b/esphome/components/epaper_spi/epaper_spi.cpp index 0b600feeae..db803305a5 100644 --- a/esphome/components/epaper_spi/epaper_spi.cpp +++ b/esphome/components/epaper_spi/epaper_spi.cpp @@ -54,20 +54,14 @@ void EPaperBase::setup_pins_() const { float EPaperBase::get_setup_priority() const { return setup_priority::PROCESSOR; } void EPaperBase::command(uint8_t value) { - this->start_command_(); + ESP_LOGV(TAG, "Command: 0x%02X", value); + this->dc_pin_->digital_write(false); + this->enable(); this->write_byte(value); - this->end_command_(); -} - -void EPaperBase::data(uint8_t value) { - this->start_data_(); - this->write_byte(value); - this->end_data_(); + this->disable(); } // write a command followed by zero or more bytes of data. -// The command is the first byte, length is the length of data only in the second byte, followed by the data. -// [COMMAND, LENGTH, DATA...] void EPaperBase::cmd_data(uint8_t command, const uint8_t *ptr, size_t length) { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(EPAPER_MAX_CMD_LOG_BYTES)]; @@ -130,14 +124,10 @@ void EPaperBase::wait_for_idle_(bool should_wait) { void EPaperBase::loop() { auto now = millis(); - if (this->delay_until_ != 0) { - // using modulus arithmetic to handle wrap-around - int diff = now - this->delay_until_; - if (diff < 0) { - return; - } - this->delay_until_ = 0; - } + // using modulus arithmetic to handle wrap-around + int diff = now - this->delay_until_; + if (diff < 0) + return; if (this->waiting_for_idle_) { if (this->is_idle_()) { this->waiting_for_idle_ = false; @@ -192,7 +182,7 @@ void EPaperBase::process_state_() { this->set_state_(EPaperState::RESET); break; case EPaperState::INITIALISE: - this->initialise_(); + this->initialise(this->update_count_ != 0); this->set_state_(EPaperState::TRANSFER_DATA); break; case EPaperState::TRANSFER_DATA: @@ -230,11 +220,11 @@ void EPaperBase::set_state_(EPaperState state, uint16_t delay) { ESP_LOGV(TAG, "Exit state %s", this->epaper_state_to_string_()); this->state_ = state; this->wait_for_idle_(state > EPaperState::SHOULD_WAIT); - if (delay != 0) { - this->delay_until_ = millis() + delay; - } else { - this->delay_until_ = 0; - } + // allow subclasses to nominate delays + if (delay == 0) + delay = this->next_delay_; + this->next_delay_ = 0; + this->delay_until_ = millis() + delay; ESP_LOGV(TAG, "Enter state %s, delay %u, wait_for_idle=%s", this->epaper_state_to_string_(), delay, TRUEFALSE(this->waiting_for_idle_)); if (state == EPaperState::IDLE) { @@ -242,22 +232,14 @@ void EPaperBase::set_state_(EPaperState state, uint16_t delay) { } } -void EPaperBase::start_command_() { - this->dc_pin_->digital_write(false); - this->enable(); -} - -void EPaperBase::end_command_() { this->disable(); } - void EPaperBase::start_data_() { this->dc_pin_->digital_write(true); this->enable(); } -void EPaperBase::end_data_() { this->disable(); } void EPaperBase::on_safe_shutdown() { this->deep_sleep(); } -void EPaperBase::initialise_() { +void EPaperBase::initialise(bool partial) { size_t index = 0; auto *sequence = this->init_sequence_; @@ -317,9 +299,8 @@ bool EPaperBase::rotate_coordinates_(int &x, int &y) { void HOT EPaperBase::draw_pixel_at(int x, int y, Color color) { if (!rotate_coordinates_(x, y)) return; - const size_t pixel_position = y * this->width_ + x; - const size_t byte_position = pixel_position / 8; - const uint8_t bit_position = pixel_position % 8; + const size_t byte_position = y * this->row_width_ + x / 8; + const uint8_t bit_position = x % 8; const uint8_t pixel_bit = 0x80 >> bit_position; const auto original = this->buffer_[byte_position]; if ((color_to_bit(color) == 0)) { diff --git a/esphome/components/epaper_spi/epaper_spi.h b/esphome/components/epaper_spi/epaper_spi.h index b587b07e8f..521543f026 100644 --- a/esphome/components/epaper_spi/epaper_spi.h +++ b/esphome/components/epaper_spi/epaper_spi.h @@ -36,14 +36,16 @@ class EPaperBase : public Display, public spi::SPIDevice { public: - EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, - size_t init_sequence_length, DisplayType display_type = DISPLAY_TYPE_BINARY) + EPaperBase(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence = nullptr, + size_t init_sequence_length = 0, DisplayType display_type = DISPLAY_TYPE_BINARY) : name_(name), width_(width), height_(height), init_sequence_(init_sequence), init_sequence_length_(init_sequence_length), - display_type_(display_type) {} + display_type_(display_type) { + this->row_width_ = (this->width_ + 7) / 8; // width of a row in bytes + } void set_dc_pin(GPIOPin *dc_pin) { dc_pin_ = dc_pin; } float get_setup_priority() const override; void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } @@ -54,9 +56,13 @@ class EPaperBase : public Display, void dump_config() override; void command(uint8_t value); - void data(uint8_t value); void cmd_data(uint8_t command, const uint8_t *ptr, size_t length); + // variant with in-place initializer list + void cmd_data(uint8_t command, std::initializer_list data) { + this->cmd_data(command, data.begin(), data.size()); + } + void update() override; void loop() override; @@ -109,7 +115,7 @@ class EPaperBase : public Display, bool is_idle_() const; void setup_pins_() const; virtual bool reset(); - void initialise_(); + virtual void initialise(bool partial); void wait_for_idle_(bool should_wait); bool init_buffer_(size_t buffer_length); bool rotate_coordinates_(int &x, int &y); @@ -143,14 +149,12 @@ class EPaperBase : public Display, void set_state_(EPaperState state, uint16_t delay = 0); - void start_command_(); - void end_command_(); void start_data_(); - void end_data_(); // properties initialised in the constructor const char *name_; uint16_t width_; + uint16_t row_width_; // width of a row in bytes uint16_t height_; const uint8_t *init_sequence_; size_t init_sequence_length_; @@ -163,7 +167,8 @@ class EPaperBase : public Display, GPIOPin *busy_pin_{}; GPIOPin *reset_pin_{}; bool waiting_for_idle_{}; - uint32_t delay_until_{}; + uint32_t delay_until_{}; // timestamp until which to delay processing + uint16_t next_delay_{}; // milliseconds to delay before next state uint8_t transform_{}; uint8_t update_count_{}; // these values represent the bounds of the updated buffer. Note that x_high and y_high diff --git a/esphome/components/epaper_spi/epaper_spi_ssd1677.cpp b/esphome/components/epaper_spi/epaper_spi_mono.cpp similarity index 53% rename from esphome/components/epaper_spi/epaper_spi_ssd1677.cpp rename to esphome/components/epaper_spi/epaper_spi_mono.cpp index e4f04657ad..d10022c4ac 100644 --- a/esphome/components/epaper_spi/epaper_spi_ssd1677.cpp +++ b/esphome/components/epaper_spi/epaper_spi_mono.cpp @@ -1,25 +1,24 @@ -#include "epaper_spi_ssd1677.h" +#include "epaper_spi_mono.h" #include #include "esphome/core/log.h" namespace esphome::epaper_spi { -static constexpr const char *const TAG = "epaper_spi.ssd1677"; +static constexpr const char *const TAG = "epaper_spi.mono"; -void EPaperSSD1677::refresh_screen(bool partial) { +void EPaperMono::refresh_screen(bool partial) { ESP_LOGV(TAG, "Refresh screen"); - this->command(0x22); - this->data(partial ? 0xFF : 0xF7); + this->cmd_data(0x22, {partial ? (uint8_t) 0xFF : (uint8_t) 0xF7}); this->command(0x20); } -void EPaperSSD1677::deep_sleep() { +void EPaperMono::deep_sleep() { ESP_LOGV(TAG, "Deep sleep"); this->command(0x10); } -bool EPaperSSD1677::reset() { +bool EPaperMono::reset() { if (EPaperBase::reset()) { this->command(0x12); return true; @@ -27,29 +26,24 @@ bool EPaperSSD1677::reset() { return false; } -bool HOT EPaperSSD1677::transfer_data() { +void EPaperMono::set_window() { + // round x-coordinates to byte boundaries + this->x_low_ &= ~7; + this->x_high_ += 7; + this->x_high_ &= ~7; + this->cmd_data(0x44, {(uint8_t) this->x_low_, (uint8_t) (this->x_low_ / 256), (uint8_t) (this->x_high_ - 1), + (uint8_t) ((this->x_high_ - 1) / 256)}); + this->cmd_data(0x4E, {(uint8_t) this->x_low_, (uint8_t) (this->x_low_ / 256)}); + this->cmd_data(0x45, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256), (uint8_t) (this->y_high_ - 1), + (uint8_t) ((this->y_high_ - 1) / 256)}); + this->cmd_data(0x4F, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256)}); +} + +bool HOT EPaperMono::transfer_data() { auto start_time = millis(); if (this->current_data_index_ == 0) { - uint8_t data[4]{}; // round to byte boundaries - this->x_low_ &= ~7; - this->y_low_ &= ~7; - this->x_high_ += 7; - this->x_high_ &= ~7; - this->y_high_ += 7; - this->y_high_ &= ~7; - data[0] = this->x_low_; - data[1] = this->x_low_ / 256; - data[2] = this->x_high_ - 1; - data[3] = (this->x_high_ - 1) / 256; - cmd_data(0x4E, data, 2); - cmd_data(0x44, data, sizeof(data)); - data[0] = this->y_low_; - data[1] = this->y_low_ / 256; - data[2] = this->y_high_ - 1; - data[3] = (this->y_high_ - 1) / 256; - cmd_data(0x4F, data, 2); - this->cmd_data(0x45, data, sizeof(data)); + this->set_window(); // for monochrome, we still need to clear the red data buffer at least once to prevent it // causing dirty pixels after partial refresh. this->command(this->send_red_ ? 0x26 : 0x24); @@ -58,10 +52,10 @@ bool HOT EPaperSSD1677::transfer_data() { size_t row_length = (this->x_high_ - this->x_low_) / 8; FixedVector bytes_to_send{}; bytes_to_send.init(row_length); - ESP_LOGV(TAG, "Writing bytes at line %zu at %ums", this->current_data_index_, (unsigned) millis()); + ESP_LOGV(TAG, "Writing %u bytes at line %zu at %ums", row_length, this->current_data_index_, (unsigned) millis()); this->start_data_(); while (this->current_data_index_ != this->y_high_) { - size_t data_idx = (this->current_data_index_ * this->width_ + this->x_low_) / 8; + size_t data_idx = this->current_data_index_ * this->row_width_ + this->x_low_ / 8; for (size_t i = 0; i != row_length; i++) { bytes_to_send[i] = this->send_red_ ? 0 : this->buffer_[data_idx++]; } @@ -69,12 +63,12 @@ bool HOT EPaperSSD1677::transfer_data() { this->write_array(&bytes_to_send.front(), row_length); // NOLINT if (millis() - start_time > MAX_TRANSFER_TIME) { // Let the main loop run and come back next loop - this->end_data_(); + this->disable(); return false; } } - this->end_data_(); + this->disable(); this->current_data_index_ = 0; if (this->send_red_) { this->send_red_ = false; diff --git a/esphome/components/epaper_spi/epaper_spi_ssd1677.h b/esphome/components/epaper_spi/epaper_spi_mono.h similarity index 57% rename from esphome/components/epaper_spi/epaper_spi_ssd1677.h rename to esphome/components/epaper_spi/epaper_spi_mono.h index 47584d24c0..f44b59e803 100644 --- a/esphome/components/epaper_spi/epaper_spi_ssd1677.h +++ b/esphome/components/epaper_spi/epaper_spi_mono.h @@ -3,13 +3,15 @@ #include "epaper_spi.h" namespace esphome::epaper_spi { - -class EPaperSSD1677 : public EPaperBase { +/** + * A class for monochrome epaper displays. + */ +class EPaperMono : public EPaperBase { public: - EPaperSSD1677(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, - size_t init_sequence_length) + EPaperMono(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, + size_t init_sequence_length) : EPaperBase(name, width, height, init_sequence, init_sequence_length, DISPLAY_TYPE_BINARY) { - this->buffer_length_ = width * height / 8; // 8 pixels per byte + this->buffer_length_ = (width + 7) / 8 * height; // 8 pixels per byte, rounded up } protected: @@ -18,6 +20,7 @@ class EPaperSSD1677 : public EPaperBase { void power_off() override{}; void deep_sleep() override; bool reset() override; + virtual void set_window(); bool transfer_data() override; bool send_red_{true}; }; diff --git a/esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp b/esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp index be243145fc..1ef2dd12c3 100644 --- a/esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp +++ b/esphome/components/epaper_spi/epaper_spi_spectra_e6.cpp @@ -80,20 +80,17 @@ void EPaperSpectraE6::power_on() { void EPaperSpectraE6::power_off() { ESP_LOGV(TAG, "Power off"); - this->command(0x02); - this->data(0x00); + this->cmd_data(0x02, {0x00}); } void EPaperSpectraE6::refresh_screen(bool partial) { ESP_LOGV(TAG, "Refresh"); - this->command(0x12); - this->data(0x00); + this->cmd_data(0x12, {0x00}); } void EPaperSpectraE6::deep_sleep() { ESP_LOGV(TAG, "Deep sleep"); - this->command(0x07); - this->data(0xA5); + this->cmd_data(0x07, {0xA5}); } void EPaperSpectraE6::fill(Color color) { @@ -143,7 +140,7 @@ bool HOT EPaperSpectraE6::transfer_data() { if (buf_idx == sizeof bytes_to_send) { this->start_data_(); this->write_array(bytes_to_send, buf_idx); - this->end_data_(); + this->disable(); ESP_LOGV(TAG, "Wrote %d bytes at %ums", buf_idx, (unsigned) millis()); buf_idx = 0; @@ -157,7 +154,7 @@ bool HOT EPaperSpectraE6::transfer_data() { if (buf_idx != 0) { this->start_data_(); this->write_array(bytes_to_send, buf_idx); - this->end_data_(); + this->disable(); } this->current_data_index_ = 0; return true; diff --git a/esphome/components/epaper_spi/epaper_waveshare.cpp b/esphome/components/epaper_spi/epaper_waveshare.cpp new file mode 100644 index 0000000000..8d382d86e7 --- /dev/null +++ b/esphome/components/epaper_spi/epaper_waveshare.cpp @@ -0,0 +1,47 @@ +#include "epaper_waveshare.h" + +namespace esphome::epaper_spi { + +static const char *const TAG = "epaper_spi.waveshare"; + +void EpaperWaveshare::initialise(bool partial) { + EPaperBase::initialise(partial); + if (partial) { + this->cmd_data(0x32, this->partial_lut_, this->partial_lut_length_); + this->cmd_data(0x3C, {0x80}); + this->cmd_data(0x22, {0xC0}); + this->command(0x20); + this->next_delay_ = 100; + } else { + this->cmd_data(0x32, this->lut_, this->lut_length_); + this->cmd_data(0x3C, {0x05}); + } + this->send_red_ = true; +} + +void EpaperWaveshare::set_window() { + this->x_low_ &= ~7; + this->x_high_ += 7; + this->x_high_ &= ~7; + uint16_t x_start = this->x_low_ / 8; + uint16_t x_end = (this->x_high_ - 1) / 8; + this->cmd_data(0x44, {(uint8_t) x_start, (uint8_t) (x_end)}); + this->cmd_data(0x4E, {(uint8_t) x_start}); + this->cmd_data(0x45, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256), (uint8_t) (this->y_high_ - 1), + (uint8_t) ((this->y_high_ - 1) / 256)}); + this->cmd_data(0x4F, {(uint8_t) this->y_low_, (uint8_t) (this->y_low_ / 256)}); + ESP_LOGV(TAG, "Set window X: %u-%u, Y: %u-%u", this->x_low_, this->x_high_, this->y_low_, this->y_high_); +} + +void EpaperWaveshare::refresh_screen(bool partial) { + if (partial) { + this->cmd_data(0x22, {0x0F}); + } else { + this->cmd_data(0x22, {0xC7}); + } + this->command(0x20); + this->next_delay_ = partial ? 100 : 3000; +} + +void EpaperWaveshare::deep_sleep() { this->cmd_data(0x10, {0x01}); } +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/epaper_waveshare.h b/esphome/components/epaper_spi/epaper_waveshare.h new file mode 100644 index 0000000000..6b894cfd09 --- /dev/null +++ b/esphome/components/epaper_spi/epaper_waveshare.h @@ -0,0 +1,30 @@ +#pragma once +#include "epaper_spi.h" +#include "epaper_spi_mono.h" + +namespace esphome::epaper_spi { +/** + * An epaper display that needs LUTs to be sent to it. + */ +class EpaperWaveshare : public EPaperMono { + public: + EpaperWaveshare(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, + size_t init_sequence_length, const uint8_t *lut, size_t lut_length, const uint8_t *partial_lut, + uint16_t partial_lut_length) + : EPaperMono(name, width, height, init_sequence, init_sequence_length), + lut_(lut), + lut_length_(lut_length), + partial_lut_(partial_lut), + partial_lut_length_(partial_lut_length) {} + + protected: + void initialise(bool partial) override; + void set_window() override; + void refresh_screen(bool partial) override; + void deep_sleep() override; + const uint8_t *lut_; + size_t lut_length_; + const uint8_t *partial_lut_; + uint16_t partial_lut_length_; +}; +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/models/__init__.py b/esphome/components/epaper_spi/models/__init__.py index 019eb31d18..3fcf3217ec 100644 --- a/esphome/components/epaper_spi/models/__init__.py +++ b/esphome/components/epaper_spi/models/__init__.py @@ -32,6 +32,9 @@ class EpaperModel: return cv.Required(name) return cv.Optional(name, default=self.get_default(name, fallback)) + def get_constructor_args(self, config) -> tuple: + return () + def get_dimensions(self, config) -> tuple[int, int]: if CONF_DIMENSIONS in config: # Explicit dimensions, just use as is diff --git a/esphome/components/epaper_spi/models/ssd1677.py b/esphome/components/epaper_spi/models/ssd1677.py index 3eb53d650e..f7e012f162 100644 --- a/esphome/components/epaper_spi/models/ssd1677.py +++ b/esphome/components/epaper_spi/models/ssd1677.py @@ -4,10 +4,9 @@ from . import EpaperModel class SSD1677(EpaperModel): - def __init__(self, name, class_name="EPaperSSD1677", **kwargs): - if CONF_DATA_RATE not in kwargs: - kwargs[CONF_DATA_RATE] = "20MHz" - super().__init__(name, class_name, **kwargs) + def __init__(self, name, class_name="EPaperMono", data_rate="20MHz", **defaults): + defaults[CONF_DATA_RATE] = data_rate + super().__init__(name, class_name, **defaults) # fmt: off def get_init_sequence(self, config: dict): @@ -23,11 +22,15 @@ class SSD1677(EpaperModel): ssd1677 = SSD1677("ssd1677") -ssd1677.extend( - "seeed-ee04-mono-4.26", +wave_4_26 = ssd1677.extend( + "waveshare-4.26in", width=800, height=480, mirror_x=True, +) + +wave_4_26.extend( + "seeed-ee04-mono-4.26", cs_pin=44, dc_pin=10, reset_pin=38, diff --git a/esphome/components/epaper_spi/models/waveshare.py b/esphome/components/epaper_spi/models/waveshare.py new file mode 100644 index 0000000000..74a288977d --- /dev/null +++ b/esphome/components/epaper_spi/models/waveshare.py @@ -0,0 +1,88 @@ +import esphome.codegen as cg +from esphome.core import ID + +from ..display import CONF_INIT_SEQUENCE_ID +from . import EpaperModel + + +class WaveshareModel(EpaperModel): + def __init__(self, name, lut, lut_partial=None, **defaults): + super().__init__(name, "EpaperWaveshare", **defaults) + self.lut = lut + self.lut_partial = lut_partial + + def get_constructor_args(self, config) -> tuple: + lut = ( + cg.static_const_array( + ID(config[CONF_INIT_SEQUENCE_ID].id + "_lut", type=cg.uint8), self.lut + ), + len(self.lut), + ) + if self.lut_partial is None: + lut_partial = cg.nullptr, 0 + else: + lut_partial = ( + cg.static_const_array( + ID( + config[CONF_INIT_SEQUENCE_ID].id + "_lut_partial", type=cg.uint8 + ), + self.lut_partial, + ), + len(self.lut_partial), + ) + return *lut, *lut_partial + + +# fmt: off +WaveshareModel( + "waveshare-2.13in-v3", + width=122, + height=250, + initsequence=( + (0x01, 0x27, 0x01, 0x00), # driver output control + (0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00), + (0x11, 0x03), # Data entry mode + (0x3F, 0x22), # Undocumented command + (0x2C, 0x36), # write VCOM register + (0x04, 0x41, 0x0C, 0x32), # SRC voltage + (0x03, 0x17), # Gate voltage + (0x21, 0x00, 0x80), # Display update control + (0x18, 0x80), # Select internal temperature sensor + ), + lut=( + 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x80, 0x4A, 0x40, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x4A, 0x80, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0x0, 0x0, + 0xF, 0x0, 0x0, 0x2, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x0, 0x0, 0x0, + ), + lut_partial=( + 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x40, 0x40, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x0, 0x0, 0x0, + ), +) diff --git a/tests/component_tests/epaper_spi/__init__.py b/tests/component_tests/epaper_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/epaper_spi/test_init.py b/tests/component_tests/epaper_spi/test_init.py new file mode 100644 index 0000000000..71e66cd043 --- /dev/null +++ b/tests/component_tests/epaper_spi/test_init.py @@ -0,0 +1,291 @@ +"""Tests for epaper_spi configuration validation.""" + +from collections.abc import Callable +from typing import Any + +import pytest + +from esphome import config_validation as cv +from esphome.components.epaper_spi.display import ( + CONFIG_SCHEMA, + FINAL_VALIDATE_SCHEMA, + MODELS, +) +from esphome.components.esp32 import ( + KEY_BOARD, + KEY_VARIANT, + VARIANT_ESP32, + VARIANT_ESP32S3, +) +from esphome.const import ( + CONF_BUSY_PIN, + CONF_CS_PIN, + CONF_DC_PIN, + CONF_DIMENSIONS, + CONF_HEIGHT, + CONF_INIT_SEQUENCE, + CONF_RESET_PIN, + CONF_WIDTH, + PlatformFramework, +) +from esphome.types import ConfigType +from tests.component_tests.types import SetCoreConfigCallable + + +def run_schema_validation( + config: ConfigType, with_final_validate: bool = False +) -> None: + """Run schema validation on a configuration. + + Args: + config: The configuration to validate + with_final_validate: If True, also run final validation (requires full config setup) + """ + result = CONFIG_SCHEMA(config) + if with_final_validate: + FINAL_VALIDATE_SCHEMA(result) + return result + + +@pytest.mark.parametrize( + ("config", "error_match"), + [ + pytest.param( + "a string", + "expected a dictionary", + id="invalid_string_config", + ), + pytest.param( + {"id": "display_id"}, + r"required key not provided @ data\['model'\]", + id="missing_model", + ), + pytest.param( + { + "id": "display_id", + "model": "ssd1677", + "dimensions": {"width": 200, "height": 200}, + }, + r"required key not provided @ data\['dc_pin'\]", + id="missing_dc_pin", + ), + ], +) +def test_basic_configuration_errors( + config: str | ConfigType, + error_match: str, + set_core_config: SetCoreConfigCallable, +) -> None: + """Test basic configuration validation errors""" + + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + with pytest.raises(cv.Invalid, match=error_match): + CONFIG_SCHEMA(config) + + +def test_all_predefined_models( + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test all predefined epaper models validate successfully with appropriate defaults.""" + + # Test all models, providing default values where necessary + for name, model in MODELS.items(): + # SEEED models are designed for ESP32-S3 hardware + if name in ("SEEED-EE04-MONO-4.26", "SEEED-RETERMINAL-E1002"): + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={ + KEY_BOARD: "esp32-s3-devkitc-1", + KEY_VARIANT: VARIANT_ESP32S3, + }, + ) + else: + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + config = {"model": name} + + # Add ID field + config["id"] = "test_display" + + # Add required fields that don't have defaults + # Use safe GPIO pins that work on ESP32 (avoiding flash pins 6-11) + if not model.get_default(CONF_DC_PIN): + config[CONF_DC_PIN] = 21 + + # Add dimensions if not provided by model + if not model.get_default(CONF_WIDTH): + config[CONF_DIMENSIONS] = {CONF_HEIGHT: 240, CONF_WIDTH: 320} + + # Add init sequence if model doesn't provide one + if model.initsequence is None: + config[CONF_INIT_SEQUENCE] = [[0xA0, 0x01]] + + # Add other optional pins that some models might require + if not model.get_default(CONF_BUSY_PIN): + config[CONF_BUSY_PIN] = 22 + + if not model.get_default(CONF_RESET_PIN): + config[CONF_RESET_PIN] = 23 + + if not model.get_default(CONF_CS_PIN): + config[CONF_CS_PIN] = 5 + + run_schema_validation(config) + + +@pytest.mark.parametrize( + "model_name", + [pytest.param(name, id=name.lower()) for name in sorted(MODELS.keys())], +) +def test_individual_models( + model_name: str, + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test each epaper model individually to ensure it validates correctly.""" + # SEEED models are designed for ESP32-S3 hardware + if model_name in ("SEEED-EE04-MONO-4.26", "SEEED-RETERMINAL-E1002"): + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={ + KEY_BOARD: "esp32-s3-devkitc-1", + KEY_VARIANT: VARIANT_ESP32S3, + }, + ) + else: + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + model = MODELS[model_name] + config: dict[str, Any] = {"model": model_name, "id": "test_display"} + + # Add required fields based on model defaults + # Use safe GPIO pins that work on ESP32 + if not model.get_default(CONF_DC_PIN): + config[CONF_DC_PIN] = 21 + + if not model.get_default(CONF_WIDTH): + config[CONF_DIMENSIONS] = {CONF_HEIGHT: 240, CONF_WIDTH: 320} + + if model.initsequence is None: + config[CONF_INIT_SEQUENCE] = [[0xA0, 0x01]] + + if not model.get_default(CONF_BUSY_PIN): + config[CONF_BUSY_PIN] = 22 + + if not model.get_default(CONF_RESET_PIN): + config[CONF_RESET_PIN] = 23 + + if not model.get_default(CONF_CS_PIN): + config[CONF_CS_PIN] = 5 + + # This should not raise any exceptions + run_schema_validation(config) + + +def test_model_with_explicit_dimensions( + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test model configuration with explicitly provided dimensions.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + run_schema_validation( + { + "id": "test_display", + "model": "ssd1677", + "dc_pin": 21, + "busy_pin": 22, + "reset_pin": 23, + "cs_pin": 5, + "dimensions": { + "width": 200, + "height": 200, + }, + } + ) + + +def test_model_with_transform( + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test model configuration with transform options.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + run_schema_validation( + { + "id": "test_display", + "model": "ssd1677", + "dc_pin": 21, + "busy_pin": 22, + "reset_pin": 23, + "cs_pin": 5, + "dimensions": { + "width": 200, + "height": 200, + }, + "transform": { + "mirror_x": True, + "mirror_y": False, + }, + } + ) + + +def test_model_with_full_update_every( + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test model configuration with full_update_every option.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + run_schema_validation( + { + "id": "test_display", + "model": "ssd1677", + "dc_pin": 21, + "busy_pin": 22, + "reset_pin": 23, + "cs_pin": 5, + "dimensions": { + "width": 200, + "height": 200, + }, + "full_update_every": 10, + } + ) diff --git a/tests/components/epaper_spi/test.esp32-s3-idf.yaml b/tests/components/epaper_spi/test.esp32-s3-idf.yaml index d330b4127d..621a819c3c 100644 --- a/tests/components/epaper_spi/test.esp32-s3-idf.yaml +++ b/tests/components/epaper_spi/test.esp32-s3-idf.yaml @@ -8,15 +8,39 @@ display: dimensions: width: 800 height: 480 - cs_pin: GPIO5 - dc_pin: GPIO17 - reset_pin: GPIO16 - busy_pin: GPIO4 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 rotation: 0 update_interval: 60s lambda: |- it.circle(64, 64, 50, Color::BLACK); + - platform: epaper_spi + spi_id: spi_bus + model: waveshare-2.13in-v3 + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + - platform: epaper_spi model: seeed-reterminal-e1002 - platform: epaper_spi From be12e3667ac58e66837b146317c6b91d9cd8203d Mon Sep 17 00:00:00 2001 From: Cougar Date: Wed, 14 Jan 2026 01:30:15 +0200 Subject: [PATCH 0099/2030] [ssd1306_i2c] fix "SSD1306 72x40" display initialization (add SSD1306B Iref setup) (#13148) --- esphome/components/ssd1306_base/ssd1306_base.cpp | 10 ++++++++++ esphome/components/ssd1306_base/ssd1306_base.h | 1 + esphome/components/ssd1306_i2c/ssd1306_i2c.cpp | 6 +++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index b0c39033e3..e0e7f94ce0 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -32,6 +32,8 @@ static const uint8_t SSD1306_COMMAND_PAGE_ADDRESS = 0x22; static const uint8_t SSD1306_COMMAND_NORMAL_DISPLAY = 0xA6; static const uint8_t SSD1306_COMMAND_INVERSE_DISPLAY = 0xA7; +static const uint8_t SSD1306B_COMMAND_SELECT_IREF = 0xAD; + static const uint8_t SSD1305_COMMAND_SET_BRIGHTNESS = 0x82; static const uint8_t SSD1305_COMMAND_SET_AREA_COLOR = 0xD8; @@ -95,6 +97,12 @@ void SSD1306::setup() { this->command(0x8B); } } else { + if (this->is_ssd1306b_()) { + // Select external or internal Iref (0xAD) + this->command(SSD1306B_COMMAND_SELECT_IREF); + // Enable internal Iref and change from 19ua (POR) to 30uA + this->command(0x20 | 0x10); + } // Enable charge pump (0x8D) this->command(SSD1306_COMMAND_CHARGE_PUMP); if (this->external_vcc_) { @@ -226,6 +234,8 @@ bool SSD1306::is_sh1107_() const { return this->model_ == SH1107_MODEL_128_64 || bool SSD1306::is_ssd1305_() const { return this->model_ == SSD1305_MODEL_128_64 || this->model_ == SSD1305_MODEL_128_32; } +bool SSD1306::is_ssd1306b_() const { return this->model_ == SSD1306_MODEL_72_40; } + void SSD1306::update() { this->do_update_(); this->display(); diff --git a/esphome/components/ssd1306_base/ssd1306_base.h b/esphome/components/ssd1306_base/ssd1306_base.h index 14ec309ae0..a573437386 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.h +++ b/esphome/components/ssd1306_base/ssd1306_base.h @@ -63,6 +63,7 @@ class SSD1306 : public display::DisplayBuffer { bool is_sh1106_() const; bool is_sh1107_() const; bool is_ssd1305_() const; + bool is_ssd1306b_() const; void draw_absolute_pixel_internal(int x, int y, Color color) override; diff --git a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp index ab6fee7b02..47a21a8ff4 100644 --- a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +++ b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp @@ -62,9 +62,9 @@ void HOT I2CSSD1306::write_display_data() { } } else { size_t block_size = 16; - if ((this->get_buffer_length_() & 8) == 8) { - // use smaller block size for e.g. 72x40 displays where buffer size is multiple of 8, not 16 - block_size = 8; + if ((this->get_buffer_length_() % 24) == 0) { + // use 24 byte block size for e.g. 72x40 displays where buffer size is multiple of 24, not 16 + block_size = 24; } for (uint32_t i = 0; i < this->get_buffer_length_();) { From 5dfdd05122c58a3441c7e5237d03ba06763a5a91 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 15:43:02 -1000 Subject: [PATCH 0100/2030] [logger] Use RAII guards for recursion protection and optimize hot path (#13194) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/logger/logger.cpp | 66 +++++++++++++------- esphome/components/logger/logger.h | 90 +++++++++++++++------------- 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 1b41bc3d47..d7ed39c8e8 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -23,30 +23,57 @@ static const char *const TAG = "logger"; // - Messages are serialized through main loop for proper console output // - Fallback to emergency console logging only if ring buffer is full // - WITHOUT task log buffer: Only emergency console output, no callbacks +// +// Optimized for the common case: 99.9% of logs come from the main thread void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT if (level > this->level_for(tag)) return; #if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Get task handle once - used for both main task check and passing to non-main thread handler TaskHandle_t current_task = xTaskGetCurrentTaskHandle(); - bool is_main_task = (current_task == main_task_); + const bool is_main_task = (current_task == this->main_task_); #else // USE_HOST - pthread_t current_thread = pthread_self(); - bool is_main_task = pthread_equal(current_thread, main_thread_); + const bool is_main_task = pthread_equal(pthread_self(), this->main_thread_); #endif - // Check and set recursion guard - uses pthread TLS for per-thread/task state - if (this->check_and_set_task_log_recursion_(is_main_task)) { - return; // Recursion detected - } - - // Main thread/task uses the shared buffer for efficiency - if (is_main_task) { + // Fast path: main thread, no recursion (99.9% of all logs) + if (is_main_task && !this->main_task_recursion_guard_) [[likely]] { + RecursionGuard guard(this->main_task_recursion_guard_); + // Format and send to both console and callbacks this->log_message_to_buffer_and_send_(level, tag, line, format, args); - this->reset_task_log_recursion_(is_main_task); return; } + // Main task with recursion - silently drop to prevent infinite loop + if (is_main_task) { + return; + } + + // Non-main thread handling (~0.1% of logs) +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + this->log_vprintf_non_main_thread_(level, tag, line, format, args, current_task); +#else // USE_HOST + this->log_vprintf_non_main_thread_(level, tag, line, format, args); +#endif +} + +// Handles non-main thread logging only +// Kept separate from hot path to improve instruction cache performance +#if defined(USE_ESP32) || defined(USE_LIBRETINY) +void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, + TaskHandle_t current_task) { +#else // USE_HOST +void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args) { +#endif + // Check if already in recursion for this non-main thread/task + if (this->is_non_main_task_recursive_()) { + return; + } + + // RAII guard - automatically resets on any return path + auto guard = this->make_non_main_task_guard_(); + bool message_sent = false; #ifdef USE_ESPHOME_TASK_LOG_BUFFER // For non-main threads/tasks, queue the message for callbacks @@ -85,21 +112,17 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch this->write_msg_(console_buffer, buffer_at); } - // Reset the recursion guard for this thread/task - this->reset_task_log_recursion_(is_main_task); + // RAII guard automatically resets on return } #else -// Implementation for all other platforms +// Implementation for all other platforms (single-task, no threading) void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT if (level > this->level_for(tag) || global_recursion_guard_) return; - global_recursion_guard_ = true; - + RecursionGuard guard(global_recursion_guard_); // Format and send to both console and callbacks this->log_message_to_buffer_and_send_(level, tag, line, format, args); - - global_recursion_guard_ = false; } #endif // USE_ESP32 / USE_HOST / USE_LIBRETINY @@ -130,7 +153,7 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas if (level > this->level_for(tag) || global_recursion_guard_) return; - global_recursion_guard_ = true; + RecursionGuard guard(global_recursion_guard_); this->tx_buffer_at_ = 0; // Copy format string from progmem @@ -140,9 +163,8 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas this->tx_buffer_[this->tx_buffer_at_++] = ch = (char) progmem_read_byte(format_pgm_p++); } - // Buffer full from copying format + // Buffer full from copying format - RAII guard handles cleanup on return if (this->tx_buffer_at_ >= this->tx_buffer_size_) { - global_recursion_guard_ = false; // Make sure to reset the recursion guard before returning return; } @@ -161,8 +183,6 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas // Write to console starting at the msg_start this->write_tx_buffer_to_console_(msg_start, &msg_length); - - global_recursion_guard_ = false; } #endif // USE_STORE_LOG_STR_IN_FLASH diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index c58ca8ddce..306bc9b143 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -229,6 +229,31 @@ class Logger : public Component { #endif protected: + // RAII guard for recursion flags - sets flag on construction, clears on destruction + class RecursionGuard { + public: + explicit RecursionGuard(bool &flag) : flag_(flag) { flag_ = true; } + ~RecursionGuard() { flag_ = false; } + RecursionGuard(const RecursionGuard &) = delete; + RecursionGuard &operator=(const RecursionGuard &) = delete; + RecursionGuard(RecursionGuard &&) = delete; + RecursionGuard &operator=(RecursionGuard &&) = delete; + + private: + bool &flag_; + }; + +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) + // Handles non-main thread logging only (~0.1% of calls) +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // ESP32/LibreTiny: Pass task handle to avoid calling xTaskGetCurrentTaskHandle() twice + void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, + TaskHandle_t current_task); +#else // USE_HOST + // Host: No task handle parameter needed (not used in send_message_thread_safe) + void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args); +#endif +#endif void process_messages_(); void write_msg_(const char *msg, size_t len); @@ -348,10 +373,10 @@ class Logger : public Component { const device *uart_dev_{nullptr}; #endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) - void *main_task_ = nullptr; // Only used for thread name identification + void *main_task_{nullptr}; // Main thread/task for fast path comparison #endif #ifdef USE_HOST - pthread_t main_thread_{}; // Main thread for identification + pthread_t main_thread_{}; // Main thread for pthread_equal() comparison #endif #ifdef USE_ESP32 // Task-specific recursion guards: @@ -434,29 +459,28 @@ class Logger : public Component { #endif #if defined(USE_ESP32) || defined(USE_HOST) - inline bool HOT check_and_set_task_log_recursion_(bool is_main_task) { - if (is_main_task) { - const bool was_recursive = main_task_recursion_guard_; - main_task_recursion_guard_ = true; - return was_recursive; + // RAII guard for non-main task recursion using pthread TLS + class NonMainTaskRecursionGuard { + public: + explicit NonMainTaskRecursionGuard(pthread_key_t key) : key_(key) { + pthread_setspecific(key_, reinterpret_cast(1)); } + ~NonMainTaskRecursionGuard() { pthread_setspecific(key_, nullptr); } + NonMainTaskRecursionGuard(const NonMainTaskRecursionGuard &) = delete; + NonMainTaskRecursionGuard &operator=(const NonMainTaskRecursionGuard &) = delete; + NonMainTaskRecursionGuard(NonMainTaskRecursionGuard &&) = delete; + NonMainTaskRecursionGuard &operator=(NonMainTaskRecursionGuard &&) = delete; - intptr_t current = (intptr_t) pthread_getspecific(log_recursion_key_); - if (current != 0) - return true; + private: + pthread_key_t key_; + }; - pthread_setspecific(log_recursion_key_, (void *) 1); - return false; - } + // Check if non-main task is already in recursion (via TLS) + inline bool HOT is_non_main_task_recursive_() const { return pthread_getspecific(log_recursion_key_) != nullptr; } - inline void HOT reset_task_log_recursion_(bool is_main_task) { - if (is_main_task) { - main_task_recursion_guard_ = false; - return; - } + // Create RAII guard for non-main task recursion + inline NonMainTaskRecursionGuard make_non_main_task_guard_() { return NonMainTaskRecursionGuard(log_recursion_key_); } - pthread_setspecific(log_recursion_key_, (void *) 0); - } #elif defined(USE_LIBRETINY) // LibreTiny doesn't have FreeRTOS TLS, so use a simple approach: // - Main task uses dedicated boolean (same as ESP32) @@ -466,29 +490,11 @@ class Logger : public Component { // - Cross-task "recursion" is prevented by the buffer mutex anyway // - Missing a recursive call from another task is acceptable (falls back to direct output) - inline bool HOT check_and_set_task_log_recursion_(bool is_main_task) { - if (is_main_task) { - const bool was_recursive = main_task_recursion_guard_; - main_task_recursion_guard_ = true; - return was_recursive; - } + // Check if non-main task is already in recursion + inline bool HOT is_non_main_task_recursive_() const { return non_main_task_recursion_guard_; } - // For non-main tasks, use a simple shared guard - // This may block legitimate concurrent logs from different tasks, - // but that's acceptable - they'll fall back to direct console output - const bool was_recursive = non_main_task_recursion_guard_; - non_main_task_recursion_guard_ = true; - return was_recursive; - } - - inline void HOT reset_task_log_recursion_(bool is_main_task) { - if (is_main_task) { - main_task_recursion_guard_ = false; - return; - } - - non_main_task_recursion_guard_ = false; - } + // Create RAII guard for non-main task recursion (uses shared boolean for all non-main tasks) + inline RecursionGuard make_non_main_task_guard_() { return RecursionGuard(non_main_task_recursion_guard_); } #endif #ifdef USE_HOST From 2793e33baf8bded6e0c68704caf2527891d777d4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 15:43:17 -1000 Subject: [PATCH 0101/2030] [logger] Use StaticVector for log listeners with compile-time sizing (#13196) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/__init__.py | 4 ++++ esphome/components/ble_nus/__init__.py | 6 +++++- esphome/components/logger/__init__.py | 22 +++++++++++++++++++++- esphome/components/logger/logger.cpp | 2 ++ esphome/components/logger/logger.h | 14 +++++++++++++- esphome/components/mqtt/__init__.py | 3 +++ esphome/components/syslog/__init__.py | 3 ++- esphome/components/web_server/__init__.py | 3 +++ esphome/core/defines.h | 2 ++ 9 files changed, 55 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 0e2c612279..9bff9f5635 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -4,6 +4,7 @@ import logging from esphome import automation from esphome.automation import Condition import esphome.codegen as cg +from esphome.components.logger import request_log_listener from esphome.config_helpers import get_logger_level import esphome.config_validation as cv from esphome.const import ( @@ -326,6 +327,9 @@ async def to_code(config: ConfigType) -> None: # Track controller registration for StaticVector sizing CORE.register_controller() + # Request a log listener slot for API log streaming + request_log_listener() + cg.add(var.set_port(config[CONF_PORT])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY])) diff --git a/esphome/components/ble_nus/__init__.py b/esphome/components/ble_nus/__init__.py index 9570005902..6581ce1cfa 100644 --- a/esphome/components/ble_nus/__init__.py +++ b/esphome/components/ble_nus/__init__.py @@ -1,4 +1,5 @@ import esphome.codegen as cg +from esphome.components.logger import request_log_listener from esphome.components.zephyr import zephyr_add_prj_conf import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_LOGS, CONF_TYPE @@ -25,5 +26,8 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) zephyr_add_prj_conf("BT_NUS", True) - cg.add(var.set_expose_log(config[CONF_TYPE] == CONF_LOGS)) + expose_log = config[CONF_TYPE] == CONF_LOGS + cg.add(var.set_expose_log(expose_log)) + if expose_log: + request_log_listener() # Request a log listener slot for BLE NUS log streaming await cg.register_component(var, config) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 7691458df5..cadd0a14ae 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -421,6 +421,7 @@ async def to_code(config): await cg.register_component(log, config) for conf in config.get(CONF_ON_MESSAGE, []): + request_log_listener() # Each on_message trigger needs a listener slot trigger = cg.new_Pvariable( conf[CONF_TRIGGER_ID], log, LOG_LEVEL_SEVERITY.index(conf[CONF_LEVEL]) ) @@ -546,6 +547,7 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( # Keys for CORE.data storage DOMAIN = "logger" KEY_LEVEL_LISTENERS = "level_listeners" +KEY_LOG_LISTENERS = "log_listeners" def request_logger_level_listeners() -> None: @@ -558,8 +560,26 @@ def request_logger_level_listeners() -> None: CORE.data.setdefault(DOMAIN, {})[KEY_LEVEL_LISTENERS] = True +def request_log_listener() -> None: + """Request a log listener slot. + + Components that need to receive log messages should call this function + during their code generation. This increments the listener count used + to size the StaticVector. + """ + data = CORE.data.setdefault(DOMAIN, {}) + data[KEY_LOG_LISTENERS] = data.get(KEY_LOG_LISTENERS, 0) + 1 + + @coroutine_with_priority(CoroPriority.FINAL) async def final_step(): """Final code generation step to configure optional logger features.""" - if CORE.data.get(DOMAIN, {}).get(KEY_LEVEL_LISTENERS, False): + domain_data = CORE.data.get(DOMAIN, {}) + if domain_data.get(KEY_LEVEL_LISTENERS, False): cg.add_define("USE_LOGGER_LEVEL_LISTENERS") + + # Only generate log listener code if any component needs it + log_listener_count = domain_data.get(KEY_LOG_LISTENERS, 0) + if log_listener_count > 0: + cg.add_define("USE_LOG_LISTENERS") + cg.add_define("ESPHOME_LOG_MAX_LISTENERS", log_listener_count) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index d7ed39c8e8..34430dbafa 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -178,8 +178,10 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas this->tx_buffer_at_ - msg_start; // Don't subtract 1 - tx_buffer_at_ is already at the null terminator position // Listeners get message first (before console write) +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_ + msg_start, msg_length); +#endif // Write to console starting at the msg_start this->write_tx_buffer_to_console_(msg_start, &msg_length); diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 306bc9b143..3e8538c2ae 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -212,8 +212,13 @@ class Logger : public Component { inline uint8_t level_for(const char *tag); +#ifdef USE_LOG_LISTENERS /// Register a log listener to receive log messages void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); } +#else + /// No-op when log listeners are disabled + void add_log_listener(LogListener *listener) {} +#endif #ifdef USE_LOGGER_LEVEL_LISTENERS /// Register a listener for log level changes @@ -318,8 +323,10 @@ class Logger : public Component { this->tx_buffer_size_); // Listeners get message WITHOUT newline (for API/MQTT/syslog) +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); +#endif // Console gets message WITH newline (if platform needs it) this->write_tx_buffer_to_console_(); @@ -336,8 +343,10 @@ class Logger : public Component { this->write_body_to_buffer_(text, text_length, this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); this->tx_buffer_[this->tx_buffer_at_] = '\0'; +#ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); +#endif } #endif @@ -394,7 +403,10 @@ class Logger : public Component { #ifdef USE_LOGGER_RUNTIME_TAG_LEVELS std::map log_levels_{}; #endif - std::vector log_listeners_; // Log message listeners (API, MQTT, syslog, etc.) +#ifdef USE_LOG_LISTENERS + StaticVector + log_listeners_; // Log message listeners (API, MQTT, syslog, etc.) +#endif #ifdef USE_LOGGER_LEVEL_LISTENERS std::vector level_listeners_; // Log level change listeners #endif diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index f7518771d7..f53df5564c 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -350,6 +350,7 @@ def exp_mqtt_message(config): async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + # Add required libraries for ESP8266 and LibreTiny if CORE.is_esp8266 or CORE.is_libretiny: # https://github.com/heman/async-mqtt-client/blob/master/library.json @@ -432,6 +433,8 @@ async def to_code(config): cg.add(var.disable_log_message()) else: cg.add(var.set_log_message_template(exp_mqtt_message(log_topic))) + # Request a log listener slot only when log topic is enabled + logger.request_log_listener() if CONF_LEVEL in log_topic: cg.add(var.set_log_level(logger.LOG_LEVELS[log_topic[CONF_LEVEL]])) diff --git a/esphome/components/syslog/__init__.py b/esphome/components/syslog/__init__.py index 80b79d2040..08626404f7 100644 --- a/esphome/components/syslog/__init__.py +++ b/esphome/components/syslog/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg from esphome.components import udp -from esphome.components.logger import LOG_LEVELS, is_log_level +from esphome.components.logger import LOG_LEVELS, is_log_level, request_log_listener from esphome.components.time import RealTimeClock from esphome.components.udp import CONF_UDP_ID import esphome.config_validation as cv @@ -36,6 +36,7 @@ async def to_code(config): level = LOG_LEVELS[config[CONF_LEVEL]] var = cg.new_Pvariable(config[CONF_ID], level, time) await cg.register_component(var, config) + request_log_listener() # Request a log listener slot for syslog await cg.register_parented(var, parent) cg.add(var.set_strip(config[CONF_STRIP])) cg.add(var.set_facility(config[CONF_FACILITY])) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 7937e7a540..16ac9d054c 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -4,6 +4,7 @@ import gzip import esphome.codegen as cg from esphome.components import web_server_base +from esphome.components.logger import request_log_listener from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID import esphome.config_validation as cv from esphome.const import ( @@ -313,6 +314,8 @@ async def to_code(config): if config.get(CONF_OTA) is False: cg.add_define("USE_WEBSERVER_OTA_DISABLED") cg.add(var.set_expose_log(config[CONF_LOG])) + if config[CONF_LOG]: + request_log_listener() # Request a log listener slot for web server log streaming if config[CONF_ENABLE_PRIVATE_NETWORK_ACCESS]: cg.add_define("USE_WEBSERVER_PRIVATE_NETWORK_ACCESS") if CONF_AUTH in config: diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 633b0c6c5e..3cc48c6008 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -20,6 +20,8 @@ // logger #define ESPHOME_LOG_LEVEL ESPHOME_LOG_LEVEL_VERY_VERBOSE +#define USE_LOG_LISTENERS +#define ESPHOME_LOG_MAX_LISTENERS 8 // Feature flags #define USE_ALARM_CONTROL_PANEL From 47ee2f4ad904e9b5968593b479533bc9aa976a3b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 16:20:39 -1000 Subject: [PATCH 0102/2030] [wifi] Use StaticVector for WiFi listeners with per-type compile-time sizing (#13197) --- esphome/components/wifi/__init__.py | 56 +++++++++++++++---- esphome/components/wifi/wifi_component.h | 40 ++++++++++--- .../wifi/wifi_component_esp8266.cpp | 14 ++--- .../wifi/wifi_component_esp_idf.cpp | 16 +++--- .../wifi/wifi_component_libretiny.cpp | 16 +++--- .../components/wifi/wifi_component_pico_w.cpp | 14 ++--- esphome/components/wifi_info/text_sensor.py | 34 +++++------ .../wifi_info/wifi_info_text_sensor.cpp | 22 ++++++-- .../wifi_info/wifi_info_text_sensor.h | 10 +++- esphome/components/wifi_signal/sensor.py | 2 +- .../wifi_signal/wifi_signal_sensor.h | 6 +- esphome/core/defines.h | 9 ++- 12 files changed, 161 insertions(+), 78 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 26aec29b6d..98266eb589 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -624,7 +624,11 @@ async def wifi_disable_to_code(config, action_id, template_arg, args): KEEP_SCAN_RESULTS_KEY = "wifi_keep_scan_results" RUNTIME_POWER_SAVE_KEY = "wifi_runtime_power_save" -WIFI_LISTENERS_KEY = "wifi_listeners" +# Keys for listener counts +IP_STATE_LISTENERS_KEY = "wifi_ip_state_listeners" +SCAN_RESULTS_LISTENERS_KEY = "wifi_scan_results_listeners" +CONNECT_STATE_LISTENERS_KEY = "wifi_connect_state_listeners" +POWER_SAVE_LISTENERS_KEY = "wifi_power_save_listeners" def request_wifi_scan_results(): @@ -650,15 +654,28 @@ def enable_runtime_power_save_control(): CORE.data[RUNTIME_POWER_SAVE_KEY] = True -def request_wifi_listeners() -> None: - """Request that WiFi state listeners be compiled in. +def request_wifi_ip_state_listener() -> None: + """Request an IP state listener slot.""" + CORE.data[IP_STATE_LISTENERS_KEY] = CORE.data.get(IP_STATE_LISTENERS_KEY, 0) + 1 - Components that need to be notified about WiFi state changes (IP address changes, - scan results, connection state) should call this function during their code generation. - This enables the add_ip_state_listener(), add_scan_results_listener(), - and add_connect_state_listener() APIs. - """ - CORE.data[WIFI_LISTENERS_KEY] = True + +def request_wifi_scan_results_listener() -> None: + """Request a scan results listener slot.""" + CORE.data[SCAN_RESULTS_LISTENERS_KEY] = ( + CORE.data.get(SCAN_RESULTS_LISTENERS_KEY, 0) + 1 + ) + + +def request_wifi_connect_state_listener() -> None: + """Request a connect state listener slot.""" + CORE.data[CONNECT_STATE_LISTENERS_KEY] = ( + CORE.data.get(CONNECT_STATE_LISTENERS_KEY, 0) + 1 + ) + + +def request_wifi_power_save_listener() -> None: + """Request a power save listener slot.""" + CORE.data[POWER_SAVE_LISTENERS_KEY] = CORE.data.get(POWER_SAVE_LISTENERS_KEY, 0) + 1 @coroutine_with_priority(CoroPriority.FINAL) @@ -670,8 +687,25 @@ async def final_step(): ) if CORE.data.get(RUNTIME_POWER_SAVE_KEY, False): cg.add_define("USE_WIFI_RUNTIME_POWER_SAVE") - if CORE.data.get(WIFI_LISTENERS_KEY, False): - cg.add_define("USE_WIFI_LISTENERS") + + # Generate listener defines - each listener type has its own #ifdef + ip_state_count = CORE.data.get(IP_STATE_LISTENERS_KEY, 0) + scan_results_count = CORE.data.get(SCAN_RESULTS_LISTENERS_KEY, 0) + connect_state_count = CORE.data.get(CONNECT_STATE_LISTENERS_KEY, 0) + power_save_count = CORE.data.get(POWER_SAVE_LISTENERS_KEY, 0) + + if ip_state_count: + cg.add_define("USE_WIFI_IP_STATE_LISTENERS") + cg.add_define("ESPHOME_WIFI_IP_STATE_LISTENERS", ip_state_count) + if scan_results_count: + cg.add_define("USE_WIFI_SCAN_RESULTS_LISTENERS") + cg.add_define("ESPHOME_WIFI_SCAN_RESULTS_LISTENERS", scan_results_count) + if connect_state_count: + cg.add_define("USE_WIFI_CONNECT_STATE_LISTENERS") + cg.add_define("ESPHOME_WIFI_CONNECT_STATE_LISTENERS", connect_state_count) + if power_save_count: + cg.add_define("USE_WIFI_POWER_SAVE_LISTENERS") + cg.add_define("ESPHOME_WIFI_POWER_SAVE_LISTENERS", power_save_count) @automation.register_action( diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index b4c4a622d5..dfc91fb5da 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -275,6 +275,9 @@ struct LTWiFiEvent; * * Components can implement this interface to receive IP address updates * without the overhead of std::function callbacks. + * + * @note Components must call wifi.request_wifi_ip_state_listener() in their + * Python to_code() to register for this listener type. */ class WiFiIPStateListener { public: @@ -286,6 +289,9 @@ class WiFiIPStateListener { * * Components can implement this interface to receive scan results * without the overhead of std::function callbacks. + * + * @note Components must call wifi.request_wifi_scan_results_listener() in their + * Python to_code() to register for this listener type. */ class WiFiScanResultsListener { public: @@ -296,6 +302,9 @@ class WiFiScanResultsListener { * * Components can implement this interface to receive connection updates * without the overhead of std::function callbacks. + * + * @note Components must call wifi.request_wifi_connect_state_listener() in their + * Python to_code() to register for this listener type. */ class WiFiConnectStateListener { public: @@ -306,6 +315,9 @@ class WiFiConnectStateListener { * * Components can implement this interface to receive power save mode updates * without the overhead of std::function callbacks. + * + * @note Components must call wifi.request_wifi_power_save_listener() in their + * Python to_code() to register for this listener type. */ class WiFiPowerSaveListener { public: @@ -444,26 +456,32 @@ class WiFiComponent : public Component { int32_t get_wifi_channel(); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS /** Add a listener for IP state changes. * Listener receives: IP addresses, DNS address 1, DNS address 2 */ void add_ip_state_listener(WiFiIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); } +#endif // USE_WIFI_IP_STATE_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS /// Add a listener for WiFi scan results void add_scan_results_listener(WiFiScanResultsListener *listener) { this->scan_results_listeners_.push_back(listener); } +#endif // USE_WIFI_SCAN_RESULTS_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS /** Add a listener for WiFi connection state changes. * Listener receives: SSID, BSSID */ void add_connect_state_listener(WiFiConnectStateListener *listener) { this->connect_state_listeners_.push_back(listener); } +#endif // USE_WIFI_CONNECT_STATE_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS /** Add a listener for WiFi power save mode changes. * Listener receives: WiFiPowerSaveMode */ void add_power_save_listener(WiFiPowerSaveListener *listener) { this->power_save_listeners_.push_back(listener); } -#endif // USE_WIFI_LISTENERS +#endif // USE_WIFI_POWER_SAVE_LISTENERS #ifdef USE_WIFI_RUNTIME_POWER_SAVE /** Request high-performance mode (no power saving) for improved WiFi latency. @@ -628,12 +646,18 @@ class WiFiComponent : public Component { WiFiAP ap_; #endif float output_power_{NAN}; -#ifdef USE_WIFI_LISTENERS - std::vector ip_state_listeners_; - std::vector scan_results_listeners_; - std::vector connect_state_listeners_; - std::vector power_save_listeners_; -#endif // USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS + StaticVector ip_state_listeners_; +#endif +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS + StaticVector scan_results_listeners_; +#endif +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + StaticVector connect_state_listeners_; +#endif +#ifdef USE_WIFI_POWER_SAVE_LISTENERS + StaticVector power_save_listeners_; +#endif ESPPreferenceObject pref_; #ifdef USE_WIFI_FAST_CONNECT ESPPreferenceObject fast_connect_pref_; diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 61c4584d09..6fb5dd5769 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -105,7 +105,7 @@ bool WiFiComponent::wifi_apply_power_save_() { } wifi_fpm_auto_sleep_set_in_null_mode(1); bool success = wifi_set_sleep_type(power_save); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); @@ -511,12 +511,13 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { it.channel); #endif s_sta_connected = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS for (auto *listener : global_wifi_component->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); } +#endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#ifdef USE_WIFI_MANUAL_IP +#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = global_wifi_component->get_selected_sta_(); config && config->get_manual_ip().has_value()) { for (auto *listener : global_wifi_component->ip_state_listeners_) { @@ -524,7 +525,6 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { global_wifi_component->get_dns_address(0), global_wifi_component->get_dns_address(1)); } } -#endif #endif break; } @@ -547,7 +547,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { // This ensures is_connected() returns false during listener callbacks, // which is critical for proper reconnection logic (e.g., roaming). global_wifi_component->error_from_callback_ = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS // Notify listeners AFTER setting error flag so they see correct state static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : global_wifi_component->connect_state_listeners_) { @@ -578,7 +578,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { ESP_LOGV(TAG, "static_ip=%s gateway=%s netmask=%s", network::IPAddress(&it.ip).str_to(ip_buf), network::IPAddress(&it.gw).str_to(gw_buf), network::IPAddress(&it.mask).str_to(mask_buf)); s_sta_got_ip = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : global_wifi_component->ip_state_listeners_) { listener->on_ip_state(global_wifi_component->wifi_sta_ip_addresses(), global_wifi_component->get_dns_address(0), global_wifi_component->get_dns_address(1)); @@ -771,7 +771,7 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { it->is_hidden != 0); } this->scan_done_ = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : global_wifi_component->scan_results_listeners_) { listener->on_wifi_scan_results(global_wifi_component->scan_result_); } diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 820725ed31..848ec3e11c 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -281,7 +281,7 @@ bool WiFiComponent::wifi_apply_power_save_() { break; } bool success = esp_wifi_set_ps(power_save) == ESP_OK; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); @@ -741,18 +741,18 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { (const char *) it.ssid, bssid_buf, it.channel, get_auth_mode_str(it.authmode)); #endif s_sta_connected = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); } +#endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#ifdef USE_WIFI_MANUAL_IP +#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } } -#endif #endif } else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_DISCONNECTED) { @@ -774,7 +774,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { s_sta_connected = false; s_sta_connecting = false; error_from_callback_ = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); @@ -788,7 +788,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { #endif /* USE_NETWORK_IPV6 */ ESP_LOGV(TAG, "static_ip=" IPSTR " gateway=" IPSTR, IP2STR(&it.ip_info.ip), IP2STR(&it.ip_info.gw)); this->got_ipv4_address_ = true; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } @@ -799,7 +799,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { const auto &it = data->data.ip_got_ip6; ESP_LOGV(TAG, "IPv6 address=" IPV6STR, IPV62STR(it.ip6_info.ip)); this->num_ipv6_addresses_++; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } @@ -843,7 +843,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { scan_result_.emplace_back(bssid, ssid, record.primary, record.rssi, record.authmode != WIFI_AUTH_OPEN, ssid.empty()); } -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { listener->on_wifi_scan_results(this->scan_result_); } diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index c5b6a8ad96..162ed4e835 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -144,7 +144,7 @@ bool WiFiComponent::wifi_sta_pre_setup_() { } bool WiFiComponent::wifi_apply_power_save_() { bool success = WiFi.setSleep(this->power_save_ != WIFI_POWER_SAVE_NONE); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); @@ -455,19 +455,19 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // Note: We don't set CONNECTED state here yet - wait for GOT_IP // This matches ESP32 IDF behavior where s_sta_connected is set but // wifi_sta_connect_status_() also checks got_ipv4_address_ -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); } +#endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#ifdef USE_WIFI_MANUAL_IP +#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_state = LTWiFiSTAState::CONNECTED; for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } } -#endif #endif break; } @@ -521,7 +521,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { this->error_from_callback_ = true; } -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); @@ -547,7 +547,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { ESP_LOGV(TAG, "static_ip=%s gateway=%s", network::IPAddress(WiFi.localIP()).str_to(ip_buf), network::IPAddress(WiFi.gatewayIP()).str_to(gw_buf)); s_sta_state = LTWiFiSTAState::CONNECTED; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } @@ -556,7 +556,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { } case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { ESP_LOGV(TAG, "Got IPv6"); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } @@ -677,7 +677,7 @@ void WiFiComponent::wifi_scan_done_callback_() { ssid.length() == 0); } WiFi.scanDelete(); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { listener->on_wifi_scan_results(this->scan_result_); } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 1aa737ff4a..29ac096d94 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -55,7 +55,7 @@ bool WiFiComponent::wifi_apply_power_save_() { } int ret = cyw43_wifi_pm(&cyw43_state, pm); bool success = ret == 0; -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS if (success) { for (auto *listener : this->power_save_listeners_) { listener->on_wifi_power_save(this->power_save_); @@ -245,7 +245,7 @@ void WiFiComponent::wifi_loop_() { if (this->state_ == WIFI_COMPONENT_STATE_STA_SCANNING && !cyw43_wifi_scan_active(&cyw43_state)) { this->scan_done_ = true; ESP_LOGV(TAG, "Scan done"); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { listener->on_wifi_scan_results(this->scan_result_); } @@ -263,28 +263,28 @@ void WiFiComponent::wifi_loop_() { // Just connected s_sta_was_connected = true; ESP_LOGV(TAG, "Connected"); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS String ssid = WiFi.SSID(); bssid_t bssid = this->wifi_bssid(); for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(ssid.c_str(), ssid.length()), bssid); } +#endif // For static IP configurations, notify IP listeners immediately as the IP is already configured -#ifdef USE_WIFI_MANUAL_IP +#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_had_ip = true; for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } } -#endif #endif } else if (!is_connected && s_sta_was_connected) { // Just disconnected s_sta_was_connected = false; s_sta_had_ip = false; ESP_LOGV(TAG, "Disconnected"); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS static constexpr uint8_t EMPTY_BSSID[6] = {}; for (auto *listener : this->connect_state_listeners_) { listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); @@ -305,7 +305,7 @@ void WiFiComponent::wifi_loop_() { // Just got IP address s_sta_had_ip = true; ESP_LOGV(TAG, "Got IP address"); -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 8a7f192367..9ecb5b7490 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -69,16 +69,6 @@ CONFIG_SCHEMA = cv.Schema( } ) -# Keys that require WiFi listeners -_NETWORK_INFO_KEYS = { - CONF_SSID, - CONF_BSSID, - CONF_IP_ADDRESS, - CONF_DNS_ADDRESS, - CONF_SCAN_RESULTS, - CONF_POWER_SAVE_MODE, -} - async def setup_conf(config, key): if key in config: @@ -88,16 +78,28 @@ async def setup_conf(config, key): async def to_code(config): - # Request WiFi listeners for any sensor that needs them - if _NETWORK_INFO_KEYS.intersection(config): - wifi.request_wifi_listeners() + # Request specific WiFi listeners based on which sensors are configured + # SSID and BSSID use WiFiConnectStateListener + if CONF_SSID in config or CONF_BSSID in config: + wifi.request_wifi_connect_state_listener() + + # IP address and DNS use WiFiIPStateListener + if CONF_IP_ADDRESS in config or CONF_DNS_ADDRESS in config: + wifi.request_wifi_ip_state_listener() + + # Scan results use WiFiScanResultsListener + if CONF_SCAN_RESULTS in config: + wifi.request_wifi_scan_results_listener() + wifi.request_wifi_scan_results() + + # Power save mode uses WiFiPowerSaveListener + if CONF_POWER_SAVE_MODE in config: + wifi.request_wifi_power_save_listener() await setup_conf(config, CONF_SSID) await setup_conf(config, CONF_BSSID) await setup_conf(config, CONF_MAC_ADDRESS) - if CONF_SCAN_RESULTS in config: - await setup_conf(config, CONF_SCAN_RESULTS) - wifi.request_wifi_scan_results() + await setup_conf(config, CONF_SCAN_RESULTS) await setup_conf(config, CONF_DNS_ADDRESS) await setup_conf(config, CONF_POWER_SAVE_MODE) if conf := config.get(CONF_IP_ADDRESS): diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index 2c0e66eeaf..a63b30b892 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -10,9 +10,7 @@ namespace esphome::wifi_info { static const char *const TAG = "wifi_info"; -#ifdef USE_WIFI_LISTENERS - -static constexpr size_t MAX_STATE_LENGTH = 255; +#ifdef USE_WIFI_IP_STATE_LISTENERS /******************** * IPAddressWiFiInfo @@ -58,6 +56,10 @@ void DNSAddressWifiInfo::on_ip_state(const network::IPAddresses &ips, const netw this->publish_state(buf); } +#endif // USE_WIFI_IP_STATE_LISTENERS + +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS + /********************** * ScanResultsWiFiInfo *********************/ @@ -80,9 +82,9 @@ static char *format_scan_entry(char *buf, const char *ssid, size_t ssid_len, int } void ScanResultsWiFiInfo::on_wifi_scan_results(const wifi::wifi_scan_vector_t &results) { - char buf[MAX_STATE_LENGTH + 1]; + char buf[MAX_STATE_LEN + 1]; char *ptr = buf; - const char *end = buf + MAX_STATE_LENGTH; + const char *end = buf + MAX_STATE_LEN; for (const auto &scan : results) { if (scan.get_is_hidden()) @@ -98,6 +100,10 @@ void ScanResultsWiFiInfo::on_wifi_scan_results(const wifi::wifi_scan_vector_tpublish_state(buf); } +#endif // USE_WIFI_SCAN_RESULTS_LISTENERS + +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + /*************** * SSIDWiFiInfo **************/ @@ -126,6 +132,10 @@ void BSSIDWiFiInfo::on_wifi_connect_state(StringRef ssid, std::spanpublish_state(buf); } +#endif // USE_WIFI_CONNECT_STATE_LISTENERS + +#ifdef USE_WIFI_POWER_SAVE_LISTENERS + /************************ * PowerSaveModeWiFiInfo ***********************/ @@ -182,7 +192,7 @@ void PowerSaveModeWiFiInfo::on_wifi_power_save(wifi::WiFiPowerSaveMode mode) { this->publish_state(mode_str); } -#endif +#endif // USE_WIFI_POWER_SAVE_LISTENERS /********************* * MacAddressWifiInfo diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 6beb1372f5..8ef35a5f5d 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -11,7 +11,7 @@ namespace esphome::wifi_info { -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS class IPAddressWiFiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiIPStateListener { public: void setup() override; @@ -35,7 +35,9 @@ class DNSAddressWifiInfo final : public Component, public text_sensor::TextSenso void on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, const network::IPAddress &dns2) override; }; +#endif // USE_WIFI_IP_STATE_LISTENERS +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS class ScanResultsWiFiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiScanResultsListener { @@ -47,7 +49,9 @@ class ScanResultsWiFiInfo final : public Component, // WiFiScanResultsListener interface void on_wifi_scan_results(const wifi::wifi_scan_vector_t &results) override; }; +#endif // USE_WIFI_SCAN_RESULTS_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS class SSIDWiFiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiConnectStateListener { public: void setup() override; @@ -65,7 +69,9 @@ class BSSIDWiFiInfo final : public Component, public text_sensor::TextSensor, pu // WiFiConnectStateListener interface void on_wifi_connect_state(StringRef ssid, std::span bssid) override; }; +#endif // USE_WIFI_CONNECT_STATE_LISTENERS +#ifdef USE_WIFI_POWER_SAVE_LISTENERS class PowerSaveModeWiFiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiPowerSaveListener { @@ -76,7 +82,7 @@ class PowerSaveModeWiFiInfo final : public Component, // WiFiPowerSaveListener interface void on_wifi_power_save(wifi::WiFiPowerSaveMode mode) override; }; -#endif +#endif // USE_WIFI_POWER_SAVE_LISTENERS class MacAddressWifiInfo final : public Component, public text_sensor::TextSensor { public: diff --git a/esphome/components/wifi_signal/sensor.py b/esphome/components/wifi_signal/sensor.py index 82cb90c745..075cfd96c6 100644 --- a/esphome/components/wifi_signal/sensor.py +++ b/esphome/components/wifi_signal/sensor.py @@ -25,6 +25,6 @@ CONFIG_SCHEMA = sensor.sensor_schema( async def to_code(config): - wifi.request_wifi_listeners() + wifi.request_wifi_connect_state_listener() var = await sensor.new_sensor(config) await cg.register_component(var, config) diff --git a/esphome/components/wifi_signal/wifi_signal_sensor.h b/esphome/components/wifi_signal/wifi_signal_sensor.h index 2e1f8cbb2b..9ff4cc54a0 100644 --- a/esphome/components/wifi_signal/wifi_signal_sensor.h +++ b/esphome/components/wifi_signal/wifi_signal_sensor.h @@ -9,13 +9,13 @@ #include namespace esphome::wifi_signal { -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS class WiFiSignalSensor : public sensor::Sensor, public PollingComponent, public wifi::WiFiConnectStateListener { #else class WiFiSignalSensor : public sensor::Sensor, public PollingComponent { #endif public: -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS void setup() override { wifi::global_wifi_component->add_connect_state_listener(this); } #endif void update() override { @@ -28,7 +28,7 @@ class WiFiSignalSensor : public sensor::Sensor, public PollingComponent { float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } -#ifdef USE_WIFI_LISTENERS +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS // WiFiConnectStateListener interface - update RSSI immediately on connect void on_wifi_connect_state(StringRef ssid, std::span bssid) override { this->update(); } #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 3cc48c6008..673397fa31 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -222,7 +222,14 @@ #define USE_CAPTIVE_PORTAL_GZIP #define USE_WIFI_11KV_SUPPORT #define USE_WIFI_FAST_CONNECT -#define USE_WIFI_LISTENERS +#define USE_WIFI_IP_STATE_LISTENERS +#define USE_WIFI_SCAN_RESULTS_LISTENERS +#define USE_WIFI_CONNECT_STATE_LISTENERS +#define USE_WIFI_POWER_SAVE_LISTENERS +#define ESPHOME_WIFI_IP_STATE_LISTENERS 2 +#define ESPHOME_WIFI_SCAN_RESULTS_LISTENERS 2 +#define ESPHOME_WIFI_CONNECT_STATE_LISTENERS 2 +#define ESPHOME_WIFI_POWER_SAVE_LISTENERS 2 #define USE_WIFI_RUNTIME_POWER_SAVE #define USB_HOST_MAX_REQUESTS 16 From 8b49d465f80c51aa1c6be09064327a874bff569b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 17:44:43 -1000 Subject: [PATCH 0103/2030] [bh1750] Eliminate heap allocations by replacing callbacks with state machine (#11950) --- esphome/components/bh1750/bh1750.cpp | 306 ++++++++++++++++++--------- esphome/components/bh1750/bh1750.h | 34 ++- 2 files changed, 232 insertions(+), 108 deletions(-) diff --git a/esphome/components/bh1750/bh1750.cpp b/esphome/components/bh1750/bh1750.cpp index 2fc476c17d..bd7c667c25 100644 --- a/esphome/components/bh1750/bh1750.cpp +++ b/esphome/components/bh1750/bh1750.cpp @@ -1,8 +1,8 @@ #include "bh1750.h" #include "esphome/core/log.h" +#include "esphome/core/application.h" -namespace esphome { -namespace bh1750 { +namespace esphome::bh1750 { static const char *const TAG = "bh1750.sensor"; @@ -13,6 +13,31 @@ static const uint8_t BH1750_COMMAND_ONE_TIME_L = 0b00100011; static const uint8_t BH1750_COMMAND_ONE_TIME_H = 0b00100000; static const uint8_t BH1750_COMMAND_ONE_TIME_H2 = 0b00100001; +static constexpr uint32_t MEASUREMENT_TIMEOUT_MS = 2000; +static constexpr float HIGH_LIGHT_THRESHOLD_LX = 7000.0f; + +// Measurement time constants (datasheet values) +static constexpr uint16_t MTREG_DEFAULT = 69; +static constexpr uint16_t MTREG_MIN = 31; +static constexpr uint16_t MTREG_MAX = 254; +static constexpr uint16_t MEAS_TIME_L_MS = 24; // L-resolution max measurement time @ mtreg=69 +static constexpr uint16_t MEAS_TIME_H_MS = 180; // H/H2-resolution max measurement time @ mtreg=69 + +// Conversion constants (datasheet formulas) +static constexpr float RESOLUTION_DIVISOR = 1.2f; // counts to lux conversion divisor +static constexpr float MODE_H2_DIVISOR = 2.0f; // H2 mode has 2x higher resolution + +// MTreg calculation constants +static constexpr int COUNTS_TARGET = 50000; // Target counts for optimal range (avoid saturation) +static constexpr int COUNTS_NUMERATOR = 10; +static constexpr int COUNTS_DENOMINATOR = 12; + +// MTreg register bit manipulation constants +static constexpr uint8_t MTREG_HI_SHIFT = 5; // High 3 bits start at bit 5 +static constexpr uint8_t MTREG_HI_MASK = 0b111; // 3-bit mask for high bits +static constexpr uint8_t MTREG_LO_SHIFT = 0; // Low 5 bits start at bit 0 +static constexpr uint8_t MTREG_LO_MASK = 0b11111; // 5-bit mask for low bits + /* bh1750 properties: @@ -43,74 +68,7 @@ void BH1750Sensor::setup() { this->mark_failed(); return; } -} - -void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function &f) { - // turn on (after one-shot sensor automatically powers down) - uint8_t turn_on = BH1750_COMMAND_POWER_ON; - if (this->write(&turn_on, 1) != i2c::ERROR_OK) { - ESP_LOGW(TAG, "Power on failed"); - f(NAN); - return; - } - - if (active_mtreg_ != mtreg) { - // set mtreg - uint8_t mtreg_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> 5) & 0b111); - uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> 0) & 0b11111); - if (this->write(&mtreg_hi, 1) != i2c::ERROR_OK || this->write(&mtreg_lo, 1) != i2c::ERROR_OK) { - ESP_LOGW(TAG, "Set measurement time failed"); - active_mtreg_ = 0; - f(NAN); - return; - } - active_mtreg_ = mtreg; - } - - uint8_t cmd; - uint16_t meas_time; - switch (mode) { - case BH1750_MODE_L: - cmd = BH1750_COMMAND_ONE_TIME_L; - meas_time = 24 * mtreg / 69; - break; - case BH1750_MODE_H: - cmd = BH1750_COMMAND_ONE_TIME_H; - meas_time = 180 * mtreg / 69; - break; - case BH1750_MODE_H2: - cmd = BH1750_COMMAND_ONE_TIME_H2; - meas_time = 180 * mtreg / 69; - break; - default: - f(NAN); - return; - } - if (this->write(&cmd, 1) != i2c::ERROR_OK) { - ESP_LOGW(TAG, "Start measurement failed"); - f(NAN); - return; - } - - // probably not needed, but adjust for rounding - meas_time++; - - this->set_timeout("read", meas_time, [this, mode, mtreg, f]() { - uint16_t raw_value; - if (this->read(reinterpret_cast(&raw_value), 2) != i2c::ERROR_OK) { - ESP_LOGW(TAG, "Read data failed"); - f(NAN); - return; - } - raw_value = i2c::i2ctohs(raw_value); - - float lx = float(raw_value) / 1.2f; - lx *= 69.0f / mtreg; - if (mode == BH1750_MODE_H2) - lx /= 2.0f; - - f(lx); - }); + this->state_ = IDLE; } void BH1750Sensor::dump_config() { @@ -124,45 +82,189 @@ void BH1750Sensor::dump_config() { } void BH1750Sensor::update() { - // first do a quick measurement in L-mode with full range - // to find right range - this->read_lx_(BH1750_MODE_L, 31, [this](float val) { - if (std::isnan(val)) { - this->status_set_warning(); - this->publish_state(NAN); + const uint32_t now = millis(); + + // Start coarse measurement to determine optimal mode/mtreg + if (this->state_ != IDLE) { + // Safety timeout: reset if stuck + if (now - this->measurement_start_time_ > MEASUREMENT_TIMEOUT_MS) { + ESP_LOGW(TAG, "Measurement timeout, resetting state"); + this->state_ = IDLE; + } else { + ESP_LOGW(TAG, "Previous measurement not complete, skipping update"); return; } + } - BH1750Mode use_mode; - uint8_t use_mtreg; - if (val <= 7000) { - use_mode = BH1750_MODE_H2; - use_mtreg = 254; - } else { - use_mode = BH1750_MODE_H; - // lx = counts / 1.2 * (69 / mtreg) - // -> mtreg = counts / 1.2 * (69 / lx) - // calculate for counts=50000 (allow some range to not saturate, but maximize mtreg) - // -> mtreg = 50000*(10/12)*(69/lx) - int ideal_mtreg = 50000 * 10 * 69 / (12 * (int) val); - use_mtreg = std::min(254, std::max(31, ideal_mtreg)); - } - ESP_LOGV(TAG, "L result: %f -> Calculated mode=%d, mtreg=%d", val, (int) use_mode, use_mtreg); + if (!this->start_measurement_(BH1750_MODE_L, MTREG_MIN, now)) { + this->status_set_warning(); + this->publish_state(NAN); + return; + } - this->read_lx_(use_mode, use_mtreg, [this](float val) { - if (std::isnan(val)) { - this->status_set_warning(); - this->publish_state(NAN); - return; + this->state_ = WAITING_COARSE_MEASUREMENT; + this->enable_loop(); // Enable loop while measurement in progress +} + +void BH1750Sensor::loop() { + const uint32_t now = App.get_loop_component_start_time(); + + switch (this->state_) { + case IDLE: + // Disable loop when idle to save cycles + this->disable_loop(); + break; + + case WAITING_COARSE_MEASUREMENT: + if (now - this->measurement_start_time_ >= this->measurement_duration_) { + this->state_ = READING_COARSE_RESULT; } - ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), val); + break; + + case READING_COARSE_RESULT: { + float lx; + if (!this->read_measurement_(lx)) { + this->fail_and_reset_(); + break; + } + + this->process_coarse_result_(lx); + + // Start fine measurement with optimal settings + // fetch millis() again since the read can take a bit + if (!this->start_measurement_(this->fine_mode_, this->fine_mtreg_, millis())) { + this->fail_and_reset_(); + break; + } + + this->state_ = WAITING_FINE_MEASUREMENT; + break; + } + + case WAITING_FINE_MEASUREMENT: + if (now - this->measurement_start_time_ >= this->measurement_duration_) { + this->state_ = READING_FINE_RESULT; + } + break; + + case READING_FINE_RESULT: { + float lx; + if (!this->read_measurement_(lx)) { + this->fail_and_reset_(); + break; + } + + ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), lx); this->status_clear_warning(); - this->publish_state(val); - }); - }); + this->publish_state(lx); + this->state_ = IDLE; + break; + } + } +} + +bool BH1750Sensor::start_measurement_(BH1750Mode mode, uint8_t mtreg, uint32_t now) { + // Power on + uint8_t turn_on = BH1750_COMMAND_POWER_ON; + if (this->write(&turn_on, 1) != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Power on failed"); + return false; + } + + // Set MTreg if changed + if (this->active_mtreg_ != mtreg) { + uint8_t mtreg_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> MTREG_HI_SHIFT) & MTREG_HI_MASK); + uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> MTREG_LO_SHIFT) & MTREG_LO_MASK); + if (this->write(&mtreg_hi, 1) != i2c::ERROR_OK || this->write(&mtreg_lo, 1) != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Set measurement time failed"); + this->active_mtreg_ = 0; + return false; + } + this->active_mtreg_ = mtreg; + } + + // Start measurement + uint8_t cmd; + uint16_t meas_time; + switch (mode) { + case BH1750_MODE_L: + cmd = BH1750_COMMAND_ONE_TIME_L; + meas_time = MEAS_TIME_L_MS * mtreg / MTREG_DEFAULT; + break; + case BH1750_MODE_H: + cmd = BH1750_COMMAND_ONE_TIME_H; + meas_time = MEAS_TIME_H_MS * mtreg / MTREG_DEFAULT; + break; + case BH1750_MODE_H2: + cmd = BH1750_COMMAND_ONE_TIME_H2; + meas_time = MEAS_TIME_H_MS * mtreg / MTREG_DEFAULT; + break; + default: + return false; + } + + if (this->write(&cmd, 1) != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Start measurement failed"); + return false; + } + + // Store current measurement parameters + this->current_mode_ = mode; + this->current_mtreg_ = mtreg; + this->measurement_start_time_ = now; + this->measurement_duration_ = meas_time + 1; // Add 1ms for safety + + return true; +} + +bool BH1750Sensor::read_measurement_(float &lx_out) { + uint16_t raw_value; + if (this->read(reinterpret_cast(&raw_value), 2) != i2c::ERROR_OK) { + ESP_LOGW(TAG, "Read data failed"); + return false; + } + raw_value = i2c::i2ctohs(raw_value); + + float lx = float(raw_value) / RESOLUTION_DIVISOR; + lx *= float(MTREG_DEFAULT) / this->current_mtreg_; + if (this->current_mode_ == BH1750_MODE_H2) { + lx /= MODE_H2_DIVISOR; + } + + lx_out = lx; + return true; +} + +void BH1750Sensor::process_coarse_result_(float lx) { + if (std::isnan(lx)) { + // Use defaults if coarse measurement failed + this->fine_mode_ = BH1750_MODE_H2; + this->fine_mtreg_ = MTREG_MAX; + return; + } + + if (lx <= HIGH_LIGHT_THRESHOLD_LX) { + this->fine_mode_ = BH1750_MODE_H2; + this->fine_mtreg_ = MTREG_MAX; + } else { + this->fine_mode_ = BH1750_MODE_H; + // lx = counts / 1.2 * (69 / mtreg) + // -> mtreg = counts / 1.2 * (69 / lx) + // calculate for counts=50000 (allow some range to not saturate, but maximize mtreg) + // -> mtreg = 50000*(10/12)*(69/lx) + int ideal_mtreg = COUNTS_TARGET * COUNTS_NUMERATOR * MTREG_DEFAULT / (COUNTS_DENOMINATOR * (int) lx); + this->fine_mtreg_ = std::min((int) MTREG_MAX, std::max((int) MTREG_MIN, ideal_mtreg)); + } + + ESP_LOGV(TAG, "L result: %.1f -> Calculated mode=%d, mtreg=%d", lx, (int) this->fine_mode_, this->fine_mtreg_); +} + +void BH1750Sensor::fail_and_reset_() { + this->status_set_warning(); + this->publish_state(NAN); + this->state_ = IDLE; } float BH1750Sensor::get_setup_priority() const { return setup_priority::DATA; } -} // namespace bh1750 -} // namespace esphome +} // namespace esphome::bh1750 diff --git a/esphome/components/bh1750/bh1750.h b/esphome/components/bh1750/bh1750.h index a31eb33609..0460427954 100644 --- a/esphome/components/bh1750/bh1750.h +++ b/esphome/components/bh1750/bh1750.h @@ -4,10 +4,9 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" -namespace esphome { -namespace bh1750 { +namespace esphome::bh1750 { -enum BH1750Mode { +enum BH1750Mode : uint8_t { BH1750_MODE_L, BH1750_MODE_H, BH1750_MODE_H2, @@ -21,13 +20,36 @@ class BH1750Sensor : public sensor::Sensor, public PollingComponent, public i2c: void setup() override; void dump_config() override; void update() override; + void loop() override; float get_setup_priority() const override; protected: - void read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function &f); + // State machine states + enum State : uint8_t { + IDLE, + WAITING_COARSE_MEASUREMENT, + READING_COARSE_RESULT, + WAITING_FINE_MEASUREMENT, + READING_FINE_RESULT, + }; + // 4-byte aligned members + uint32_t measurement_start_time_{0}; + uint32_t measurement_duration_{0}; + + // 1-byte members grouped together to minimize padding + State state_{IDLE}; + BH1750Mode current_mode_{BH1750_MODE_L}; + uint8_t current_mtreg_{31}; + BH1750Mode fine_mode_{BH1750_MODE_H2}; + uint8_t fine_mtreg_{254}; uint8_t active_mtreg_{0}; + + // Helper methods + bool start_measurement_(BH1750Mode mode, uint8_t mtreg, uint32_t now); + bool read_measurement_(float &lx_out); + void process_coarse_result_(float lx); + void fail_and_reset_(); }; -} // namespace bh1750 -} // namespace esphome +} // namespace esphome::bh1750 From c8cc29a9913bef814fed5cb036eaca2f9c8879a2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 13 Jan 2026 17:58:06 -1000 Subject: [PATCH 0104/2030] [api] Reduce batch RAM usage by 33% via switch dispatch (#13199) --- esphome/components/api/api_connection.cpp | 247 +++++++++++++++------- esphome/components/api/api_connection.h | 117 +++------- esphome/components/api/api_server.cpp | 7 +- esphome/components/api/list_entities.h | 5 +- esphome/components/event/event.h | 19 ++ 5 files changed, 229 insertions(+), 166 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index ea18d06511..0804985cc5 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -265,8 +265,7 @@ void APIConnection::loop() { // If we can't send the ping request directly (tx_buffer full), // schedule it at the front of the batch so it will be sent with priority ESP_LOGW(TAG, "Buffer full, ping queued"); - this->schedule_message_front_(nullptr, &APIConnection::try_send_ping_request, PingRequest::MESSAGE_TYPE, - PingRequest::ESTIMATED_SIZE); + this->schedule_message_front_(nullptr, PingRequest::MESSAGE_TYPE, PingRequest::ESTIMATED_SIZE); this->flags_.sent_ping = true; // Mark as sent to avoid scheduling multiple pings } } @@ -362,8 +361,8 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess #ifdef USE_BINARY_SENSOR bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) { - return this->send_message_smart_(binary_sensor, &APIConnection::try_send_binary_sensor_state, - BinarySensorStateResponse::MESSAGE_TYPE, BinarySensorStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(binary_sensor, BinarySensorStateResponse::MESSAGE_TYPE, + BinarySensorStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -389,8 +388,7 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne #ifdef USE_COVER bool APIConnection::send_cover_state(cover::Cover *cover) { - return this->send_message_smart_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE, - CoverStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(cover, CoverStateResponse::MESSAGE_TYPE, CoverStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -430,8 +428,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) { #ifdef USE_FAN bool APIConnection::send_fan_state(fan::Fan *fan) { - return this->send_message_smart_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE, - FanStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(fan, FanStateResponse::MESSAGE_TYPE, FanStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -482,8 +479,7 @@ void APIConnection::fan_command(const FanCommandRequest &msg) { #ifdef USE_LIGHT bool APIConnection::send_light_state(light::LightState *light) { - return this->send_message_smart_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE, - LightStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(light, LightStateResponse::MESSAGE_TYPE, LightStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -569,8 +565,7 @@ void APIConnection::light_command(const LightCommandRequest &msg) { #ifdef USE_SENSOR bool APIConnection::send_sensor_state(sensor::Sensor *sensor) { - return this->send_message_smart_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE, - SensorStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(sensor, SensorStateResponse::MESSAGE_TYPE, SensorStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -598,8 +593,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection * #ifdef USE_SWITCH bool APIConnection::send_switch_state(switch_::Switch *a_switch) { - return this->send_message_smart_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE, - SwitchStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(a_switch, SwitchStateResponse::MESSAGE_TYPE, SwitchStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -633,8 +627,8 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) { #ifdef USE_TEXT_SENSOR bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) { - return this->send_message_smart_(text_sensor, &APIConnection::try_send_text_sensor_state, - TextSensorStateResponse::MESSAGE_TYPE, TextSensorStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(text_sensor, TextSensorStateResponse::MESSAGE_TYPE, + TextSensorStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -658,8 +652,7 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect #ifdef USE_CLIMATE bool APIConnection::send_climate_state(climate::Climate *climate) { - return this->send_message_smart_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE, - ClimateStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(climate, ClimateStateResponse::MESSAGE_TYPE, ClimateStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -754,8 +747,7 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) { #ifdef USE_NUMBER bool APIConnection::send_number_state(number::Number *number) { - return this->send_message_smart_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE, - NumberStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(number, NumberStateResponse::MESSAGE_TYPE, NumberStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -789,8 +781,7 @@ void APIConnection::number_command(const NumberCommandRequest &msg) { #ifdef USE_DATETIME_DATE bool APIConnection::send_date_state(datetime::DateEntity *date) { - return this->send_message_smart_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE, - DateStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(date, DateStateResponse::MESSAGE_TYPE, DateStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -818,8 +809,7 @@ void APIConnection::date_command(const DateCommandRequest &msg) { #ifdef USE_DATETIME_TIME bool APIConnection::send_time_state(datetime::TimeEntity *time) { - return this->send_message_smart_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE, - TimeStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(time, TimeStateResponse::MESSAGE_TYPE, TimeStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -847,8 +837,8 @@ void APIConnection::time_command(const TimeCommandRequest &msg) { #ifdef USE_DATETIME_DATETIME bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) { - return this->send_message_smart_(datetime, &APIConnection::try_send_datetime_state, - DateTimeStateResponse::MESSAGE_TYPE, DateTimeStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(datetime, DateTimeStateResponse::MESSAGE_TYPE, + DateTimeStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -878,8 +868,7 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { #ifdef USE_TEXT bool APIConnection::send_text_state(text::Text *text) { - return this->send_message_smart_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE, - TextStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(text, TextStateResponse::MESSAGE_TYPE, TextStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -911,8 +900,7 @@ void APIConnection::text_command(const TextCommandRequest &msg) { #ifdef USE_SELECT bool APIConnection::send_select_state(select::Select *select) { - return this->send_message_smart_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE, - SelectStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(select, SelectStateResponse::MESSAGE_TYPE, SelectStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -956,8 +944,7 @@ void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg #ifdef USE_LOCK bool APIConnection::send_lock_state(lock::Lock *a_lock) { - return this->send_message_smart_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE, - LockStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(a_lock, LockStateResponse::MESSAGE_TYPE, LockStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, @@ -997,8 +984,7 @@ void APIConnection::lock_command(const LockCommandRequest &msg) { #ifdef USE_VALVE bool APIConnection::send_valve_state(valve::Valve *valve) { - return this->send_message_smart_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE, - ValveStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(valve, ValveStateResponse::MESSAGE_TYPE, ValveStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -1032,8 +1018,8 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) { #ifdef USE_MEDIA_PLAYER bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) { - return this->send_message_smart_(media_player, &APIConnection::try_send_media_player_state, - MediaPlayerStateResponse::MESSAGE_TYPE, MediaPlayerStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(media_player, MediaPlayerStateResponse::MESSAGE_TYPE, + MediaPlayerStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -1315,8 +1301,7 @@ void APIConnection::zwave_proxy_request(const ZWaveProxyRequest &msg) { #ifdef USE_ALARM_CONTROL_PANEL bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) { - return this->send_message_smart_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state, - AlarmControlPanelStateResponse::MESSAGE_TYPE, + return this->send_message_smart_(a_alarm_control_panel, AlarmControlPanelStateResponse::MESSAGE_TYPE, AlarmControlPanelStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, @@ -1369,8 +1354,8 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe #ifdef USE_WATER_HEATER bool APIConnection::send_water_heater_state(water_heater::WaterHeater *water_heater) { - return this->send_message_smart_(water_heater, &APIConnection::try_send_water_heater_state, - WaterHeaterStateResponse::MESSAGE_TYPE, WaterHeaterStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(water_heater, WaterHeaterStateResponse::MESSAGE_TYPE, + WaterHeaterStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -1419,10 +1404,11 @@ void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequ #endif #ifdef USE_EVENT -void APIConnection::send_event(event::Event *event, StringRef event_type) { - // get_last_event_type() returns StringRef pointing to null-terminated string literals from codegen - this->send_message_smart_(event, MessageCreator(event_type.c_str()), EventResponse::MESSAGE_TYPE, - EventResponse::ESTIMATED_SIZE); +// Event is a special case - unlike other entities with simple state fields, +// events store their state in a member accessed via obj->get_last_event_type() +void APIConnection::send_event(event::Event *event) { + this->send_message_smart_(event, EventResponse::MESSAGE_TYPE, EventResponse::ESTIMATED_SIZE, + event->get_last_event_type_index()); } uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -1473,8 +1459,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection #ifdef USE_UPDATE bool APIConnection::send_update_state(update::UpdateEntity *update) { - return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE, - UpdateStateResponse::ESTIMATED_SIZE); + return this->send_message_smart_(update, UpdateStateResponse::MESSAGE_TYPE, UpdateStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) { @@ -1897,30 +1882,31 @@ void APIConnection::on_fatal_error() { this->flags_.remove = true; } -void APIConnection::DeferredBatch::add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, - uint8_t estimated_size) { +void APIConnection::DeferredBatch::add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, + uint8_t aux_data_index) { // Check if we already have a message of this type for this entity // This provides deduplication per entity/message_type combination // O(n) but optimized for RAM and not performance. - for (auto &item : items) { - if (item.entity == entity && item.message_type == message_type) { - // Replace with new creator - item.creator = creator; - return; + // Skip deduplication for events - they are edge-triggered, every occurrence matters +#ifdef USE_EVENT + if (message_type != EventResponse::MESSAGE_TYPE) +#endif + { + for (const auto &item : items) { + if (item.entity == entity && item.message_type == message_type) + return; // Already queued } } - - // No existing item found, add new one - items.emplace_back(entity, creator, message_type, estimated_size); + // No existing item found (or event), add new one + items.push_back({entity, message_type, estimated_size, aux_data_index}); } -void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type, - uint8_t estimated_size) { +void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { // Add high priority message and swap to front // This avoids expensive vector::insert which shifts all elements // Note: We only ever have one high-priority message at a time (ping OR disconnect) // If we're disconnecting, pings are blocked, so this simple swap is sufficient - items.emplace_back(entity, creator, message_type, estimated_size); + items.push_back({entity, message_type, estimated_size, AUX_DATA_UNUSED}); if (items.size() > 1) { // Swap the new high-priority item to the front std::swap(items.front(), items.back()); @@ -1959,19 +1945,17 @@ void APIConnection::process_batch_() { if (num_items == 1) { const auto &item = this->deferred_batch_[0]; - // Let the creator calculate size and encode if it fits - uint16_t payload_size = - item.creator(item.entity, this, std::numeric_limits::max(), true, item.message_type); + // Let dispatch_message_ calculate size and encode if it fits + uint16_t payload_size = this->dispatch_message_(item, std::numeric_limits::max(), true); if (payload_size > 0 && this->send_buffer(ProtoWriteBuffer{&shared_buf}, item.message_type)) { #ifdef HAS_PROTO_MESSAGE_DUMP - // Log messages after send attempt for VV debugging - // It's safe to use the buffer for logging at this point regardless of send result + // Log message after send attempt for VV debugging this->log_batch_item_(item); #endif this->clear_batch_(); } else if (payload_size == 0) { - // Message too large + // Message too large to fit in available space ESP_LOGW(TAG, "Message too large to send: type=%u", item.message_type); this->clear_batch_(); } @@ -2016,9 +2000,9 @@ void APIConnection::process_batch_() { // Process items and encode directly to buffer (up to our limit) for (size_t i = 0; i < messages_to_process; i++) { const auto &item = this->deferred_batch_[i]; - // Try to encode message - // The creator will calculate overhead to determine if the message fits - uint16_t payload_size = item.creator(item.entity, this, remaining_size, false, item.message_type); + // Try to encode message via dispatch + // The dispatch function calculates overhead to determine if the message fits + uint16_t payload_size = this->dispatch_message_(item, remaining_size, false); if (payload_size == 0) { // Message won't fit, stop processing @@ -2084,18 +2068,129 @@ void APIConnection::process_batch_() { } } -uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single, uint8_t message_type) const { +// Dispatch message encoding based on message_type +// Switch assigns function pointer, single call site for smaller code size +uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, + bool is_single) { #ifdef USE_EVENT - // Special case: EventResponse uses const char * pointer - if (message_type == EventResponse::MESSAGE_TYPE) { - auto *e = static_cast(entity); - return APIConnection::try_send_event_response(e, StringRef(data_.const_char_ptr), conn, remaining_size, is_single); + // Events need aux_data_index to look up event type from entity + if (item.message_type == EventResponse::MESSAGE_TYPE) { + // Skip if aux_data_index is invalid (should never happen in normal operation) + if (item.aux_data_index == DeferredBatch::AUX_DATA_UNUSED) + return 0; + auto *event = static_cast(item.entity); + return try_send_event_response(event, StringRef::from_maybe_nullptr(event->get_event_type(item.aux_data_index)), + this, remaining_size, is_single); } #endif - // All other message types use function pointers - return data_.function_ptr(entity, conn, remaining_size, is_single); + // All other message types use function pointer lookup via switch + MessageCreatorPtr func = nullptr; + +// Macros to reduce repetitive switch cases +#define CASE_STATE_INFO(entity_name, StateResp, InfoResp) \ + case StateResp::MESSAGE_TYPE: \ + func = &try_send_##entity_name##_state; \ + break; \ + case InfoResp::MESSAGE_TYPE: \ + func = &try_send_##entity_name##_info; \ + break; +#define CASE_INFO_ONLY(entity_name, InfoResp) \ + case InfoResp::MESSAGE_TYPE: \ + func = &try_send_##entity_name##_info; \ + break; + + switch (item.message_type) { +#ifdef USE_BINARY_SENSOR + CASE_STATE_INFO(binary_sensor, BinarySensorStateResponse, ListEntitiesBinarySensorResponse) +#endif +#ifdef USE_COVER + CASE_STATE_INFO(cover, CoverStateResponse, ListEntitiesCoverResponse) +#endif +#ifdef USE_FAN + CASE_STATE_INFO(fan, FanStateResponse, ListEntitiesFanResponse) +#endif +#ifdef USE_LIGHT + CASE_STATE_INFO(light, LightStateResponse, ListEntitiesLightResponse) +#endif +#ifdef USE_SENSOR + CASE_STATE_INFO(sensor, SensorStateResponse, ListEntitiesSensorResponse) +#endif +#ifdef USE_SWITCH + CASE_STATE_INFO(switch, SwitchStateResponse, ListEntitiesSwitchResponse) +#endif +#ifdef USE_BUTTON + CASE_INFO_ONLY(button, ListEntitiesButtonResponse) +#endif +#ifdef USE_TEXT_SENSOR + CASE_STATE_INFO(text_sensor, TextSensorStateResponse, ListEntitiesTextSensorResponse) +#endif +#ifdef USE_CLIMATE + CASE_STATE_INFO(climate, ClimateStateResponse, ListEntitiesClimateResponse) +#endif +#ifdef USE_NUMBER + CASE_STATE_INFO(number, NumberStateResponse, ListEntitiesNumberResponse) +#endif +#ifdef USE_DATETIME_DATE + CASE_STATE_INFO(date, DateStateResponse, ListEntitiesDateResponse) +#endif +#ifdef USE_DATETIME_TIME + CASE_STATE_INFO(time, TimeStateResponse, ListEntitiesTimeResponse) +#endif +#ifdef USE_DATETIME_DATETIME + CASE_STATE_INFO(datetime, DateTimeStateResponse, ListEntitiesDateTimeResponse) +#endif +#ifdef USE_TEXT + CASE_STATE_INFO(text, TextStateResponse, ListEntitiesTextResponse) +#endif +#ifdef USE_SELECT + CASE_STATE_INFO(select, SelectStateResponse, ListEntitiesSelectResponse) +#endif +#ifdef USE_LOCK + CASE_STATE_INFO(lock, LockStateResponse, ListEntitiesLockResponse) +#endif +#ifdef USE_VALVE + CASE_STATE_INFO(valve, ValveStateResponse, ListEntitiesValveResponse) +#endif +#ifdef USE_MEDIA_PLAYER + CASE_STATE_INFO(media_player, MediaPlayerStateResponse, ListEntitiesMediaPlayerResponse) +#endif +#ifdef USE_ALARM_CONTROL_PANEL + CASE_STATE_INFO(alarm_control_panel, AlarmControlPanelStateResponse, ListEntitiesAlarmControlPanelResponse) +#endif +#ifdef USE_WATER_HEATER + CASE_STATE_INFO(water_heater, WaterHeaterStateResponse, ListEntitiesWaterHeaterResponse) +#endif +#ifdef USE_CAMERA + CASE_INFO_ONLY(camera, ListEntitiesCameraResponse) +#endif +#ifdef USE_INFRARED + CASE_INFO_ONLY(infrared, ListEntitiesInfraredResponse) +#endif +#ifdef USE_EVENT + CASE_INFO_ONLY(event, ListEntitiesEventResponse) +#endif +#ifdef USE_UPDATE + CASE_STATE_INFO(update, UpdateStateResponse, ListEntitiesUpdateResponse) +#endif + // Special messages (not entity state/info) + case ListEntitiesDoneResponse::MESSAGE_TYPE: + func = &try_send_list_info_done; + break; + case DisconnectRequest::MESSAGE_TYPE: + func = &try_send_disconnect_request; + break; + case PingRequest::MESSAGE_TYPE: + func = &try_send_ping_request; + break; + default: + return 0; + } + +#undef CASE_STATE_INFO +#undef CASE_INFO_ONLY + + return func(item.entity, this, remaining_size, is_single); } uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index b3d072ff69..21bf4c4073 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -12,6 +12,7 @@ #include "esphome/core/string_ref.h" #include +#include #include namespace esphome::api { @@ -38,8 +39,8 @@ class APIConnection final : public APIServerConnection { void loop(); bool send_list_info_done() { - return this->schedule_message_(nullptr, &APIConnection::try_send_list_info_done, - ListEntitiesDoneResponse::MESSAGE_TYPE, ListEntitiesDoneResponse::ESTIMATED_SIZE); + return this->schedule_message_(nullptr, ListEntitiesDoneResponse::MESSAGE_TYPE, + ListEntitiesDoneResponse::ESTIMATED_SIZE); } #ifdef USE_BINARY_SENSOR bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor); @@ -178,7 +179,7 @@ class APIConnection final : public APIServerConnection { #endif #ifdef USE_EVENT - void send_event(event::Event *event, StringRef event_type); + void send_event(event::Event *event); #endif #ifdef USE_UPDATE @@ -540,33 +541,17 @@ class APIConnection final : public APIServerConnection { // Function pointer type for message encoding using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single); - class MessageCreator { - public: - MessageCreator(MessageCreatorPtr ptr) { data_.function_ptr = ptr; } - explicit MessageCreator(const char *str_value) { data_.const_char_ptr = str_value; } - - // Call operator - uses message_type to determine union type - uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single, - uint8_t message_type) const; - - private: - union Data { - MessageCreatorPtr function_ptr; - const char *const_char_ptr; - } data_; // 4 bytes on 32-bit, 8 bytes on 64-bit - }; - // Generic batching mechanism for both state updates and entity info struct DeferredBatch { - struct BatchItem { - EntityBase *entity; // Entity pointer - MessageCreator creator; // Function that creates the message when needed - uint8_t message_type; // Message type for overhead calculation (max 255) - uint8_t estimated_size; // Estimated message size (max 255 bytes) + // Sentinel value for unused aux_data_index + static constexpr uint8_t AUX_DATA_UNUSED = std::numeric_limits::max(); - // Constructor for creating BatchItem - BatchItem(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) - : entity(entity), creator(creator), message_type(message_type), estimated_size(estimated_size) {} + struct BatchItem { + EntityBase *entity; // 4 bytes - Entity pointer + uint8_t message_type; // 1 byte - Message type for protocol and dispatch + uint8_t estimated_size; // 1 byte - Estimated message size (max 255 bytes) + uint8_t aux_data_index{AUX_DATA_UNUSED}; // 1 byte - For events: index into entity's event_types + // 1 byte padding }; std::vector items; @@ -575,10 +560,11 @@ class APIConnection final : public APIServerConnection { // No pre-allocation - log connections never use batching, and for // connections that do, buffers are released after initial sync anyway - // Add item to the batch - void add_item(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size); + // Add item to the batch (with deduplication) + void add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, + uint8_t aux_data_index = AUX_DATA_UNUSED); // Add item to the front of the batch (for high priority messages like ping) - void add_item_front(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size); + void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size); // Clear all items void clear() { @@ -592,6 +578,7 @@ class APIConnection final : public APIServerConnection { bool empty() const { return items.empty(); } size_t size() const { return items.size(); } const BatchItem &operator[](size_t index) const { return items[index]; } + // Release excess capacity - only releases if items already empty void release_buffer() { // Safe to call: batch is processed before release_buffer is called, @@ -663,17 +650,15 @@ class APIConnection final : public APIServerConnection { this->flags_.batch_scheduled = false; } -#ifdef HAS_PROTO_MESSAGE_DUMP - // Helper to log a proto message from a MessageCreator object - void log_proto_message_(EntityBase *entity, const MessageCreator &creator, uint8_t message_type) { - this->flags_.log_only_mode = true; - creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type); - this->flags_.log_only_mode = false; - } + // Dispatch message encoding based on message_type - replaces function pointer storage + // Switch assigns pointer, single call site for smaller code size + uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool is_single); +#ifdef HAS_PROTO_MESSAGE_DUMP void log_batch_item_(const DeferredBatch::BatchItem &item) { - // Use the helper to log the message - this->log_proto_message_(item.entity, item.creator, item.message_type); + this->flags_.log_only_mode = true; + this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true); + this->flags_.log_only_mode = false; } #endif @@ -698,63 +683,31 @@ class APIConnection final : public APIServerConnection { // Helper method to send a message either immediately or via batching // Tries immediate send if should_send_immediately_() returns true and buffer has space // Falls back to batching if immediate send fails or isn't applicable - bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint8_t message_type, - uint8_t estimated_size) { + bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, + uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) { if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) { - // Now actually encode and send - if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true) && + DeferredBatch::BatchItem item{entity, message_type, estimated_size, aux_data_index}; + if (this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true) && this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) { #ifdef HAS_PROTO_MESSAGE_DUMP - // Log the message in verbose mode - this->log_proto_message_(entity, MessageCreator(creator), message_type); + this->log_batch_item_(item); #endif return true; } - - // If immediate send failed, fall through to batching } - - // Fall back to scheduled batching - return this->schedule_message_(entity, creator, message_type, estimated_size); - } - - // Overload for MessageCreator (used by events which need to capture event_type) - bool send_message_smart_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) { - // Try to send immediately if message type should bypass batching and buffer has space - if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) { - // Now actually encode and send - if (creator(entity, this, MAX_BATCH_PACKET_SIZE, true, message_type) && - this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) { -#ifdef HAS_PROTO_MESSAGE_DUMP - // Log the message in verbose mode - this->log_proto_message_(entity, creator, message_type); -#endif - return true; - } - - // If immediate send failed, fall through to batching - } - - // Fall back to scheduled batching - return this->schedule_message_(entity, creator, message_type, estimated_size); + return this->schedule_message_(entity, message_type, estimated_size, aux_data_index); } // Helper function to schedule a deferred message with known message type - bool schedule_message_(EntityBase *entity, MessageCreator creator, uint8_t message_type, uint8_t estimated_size) { - this->deferred_batch_.add_item(entity, creator, message_type, estimated_size); + bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, + uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) { + this->deferred_batch_.add_item(entity, message_type, estimated_size, aux_data_index); return this->schedule_batch_(); } - // Overload for function pointers (for info messages and current state reads) - bool schedule_message_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type, - uint8_t estimated_size) { - return schedule_message_(entity, MessageCreator(function_ptr), message_type, estimated_size); - } - // Helper function to schedule a high priority message at the front of the batch - bool schedule_message_front_(EntityBase *entity, MessageCreatorPtr function_ptr, uint8_t message_type, - uint8_t estimated_size) { - this->deferred_batch_.add_item_front(entity, MessageCreator(function_ptr), message_type, estimated_size); + bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { + this->deferred_batch_.add_item_front(entity, message_type, estimated_size); return this->schedule_batch_(); } diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 949262098f..a1fe33edb2 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -318,13 +318,11 @@ API_DISPATCH_UPDATE(water_heater::WaterHeater, water_heater) #endif #ifdef USE_EVENT -// Event is a special case - unlike other entities with simple state fields, -// events store their state in a member accessed via obj->get_last_event_type() void APIServer::on_event(event::Event *obj) { if (obj->is_internal()) return; for (auto &c : this->clients_) - c->send_event(obj, obj->get_last_event_type()); + c->send_event(obj); } #endif @@ -615,8 +613,7 @@ void APIServer::on_shutdown() { if (!c->send_message(req, DisconnectRequest::MESSAGE_TYPE)) { // If we can't send the disconnect request directly (tx_buffer full), // schedule it at the front of the batch so it will be sent with priority - c->schedule_message_front_(nullptr, &APIConnection::try_send_disconnect_request, DisconnectRequest::MESSAGE_TYPE, - DisconnectRequest::ESTIMATED_SIZE); + c->schedule_message_front_(nullptr, DisconnectRequest::MESSAGE_TYPE, DisconnectRequest::ESTIMATED_SIZE); } } } diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 912aab72b2..bef36dd015 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -9,11 +9,10 @@ namespace esphome::api { class APIConnection; // Macro for generating ListEntitiesIterator handlers -// Calls schedule_message_ with try_send_*_info +// Calls schedule_message_ which dispatches to try_send_*_info #define LIST_ENTITIES_HANDLER(entity_type, EntityClass, ResponseType) \ bool ListEntitiesIterator::on_##entity_type(EntityClass *entity) { /* NOLINT(bugprone-macro-parentheses) */ \ - return this->client_->schedule_message_(entity, &APIConnection::try_send_##entity_type##_info, \ - ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \ + return this->client_->schedule_message_(entity, ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \ } class ListEntitiesIterator : public ComponentIterator { diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index 27700e32d8..f77ad326d9 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -48,6 +49,24 @@ class Event : public EntityBase, public EntityBase_DeviceClass { /// Return the last triggered event type, or empty StringRef if no event triggered yet. StringRef get_last_event_type() const { return StringRef::from_maybe_nullptr(this->last_event_type_); } + /// Return event type by index, or nullptr if index is out of bounds. + const char *get_event_type(uint8_t index) const { + return index < this->types_.size() ? this->types_[index] : nullptr; + } + + /// Return index of last triggered event type, or max uint8_t if no event triggered yet. + uint8_t get_last_event_type_index() const { + if (this->last_event_type_ == nullptr) + return std::numeric_limits::max(); + // Most events have <3 types, uint8_t is sufficient for all reasonable scenarios + const uint8_t size = static_cast(this->types_.size()); + for (uint8_t i = 0; i < size; i++) { + if (this->types_[i] == this->last_event_type_) + return i; + } + return std::numeric_limits::max(); + } + /// Check if an event has been triggered. bool has_event() const { return this->last_event_type_ != nullptr; } From 9c5f4e52881efa404a853e2338db82ef937a3218 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 14 Jan 2026 11:07:18 +0100 Subject: [PATCH 0105/2030] [usb_cdc_acm] move esp32 implementation to new file (#12824) Co-authored-by: Keith Burzinski --- esphome/components/usb_cdc_acm/__init__.py | 1 + .../components/usb_cdc_acm/usb_cdc_acm.cpp | 353 +----------------- esphome/components/usb_cdc_acm/usb_cdc_acm.h | 25 +- .../usb_cdc_acm/usb_cdc_acm_esp32.cpp | 349 +++++++++++++++++ esphome/core/defines.h | 1 + 5 files changed, 377 insertions(+), 352 deletions(-) create mode 100644 esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp diff --git a/esphome/components/usb_cdc_acm/__init__.py b/esphome/components/usb_cdc_acm/__init__.py index 6693d8e75e..bfe177a4da 100644 --- a/esphome/components/usb_cdc_acm/__init__.py +++ b/esphome/components/usb_cdc_acm/__init__.py @@ -74,3 +74,4 @@ async def to_code(config: ConfigType) -> None: add_idf_sdkconfig_option( "CONFIG_TINYUSB_CDC_TX_BUFSIZE", config[CONF_TX_BUFFER_SIZE] ) + cg.add_define("ESPHOME_MAX_USB_CDC_INSTANCES", num_interfaces) diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp index 29120a3d0b..a4c2e6c4a4 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp @@ -3,181 +3,17 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" - -#include -#include "freertos/FreeRTOS.h" -#include "freertos/ringbuf.h" -#include "freertos/task.h" -#include "esp_log.h" - -#include "tusb.h" -#include "tusb_cdc_acm.h" - namespace esphome::usb_cdc_acm { -static const char *TAG = "usb_cdc_acm"; - -// Maximum bytes to log in very verbose hex output (168 * 3 = 504, under TX buffer size of 512) -static constexpr size_t USB_CDC_MAX_LOG_BYTES = 168; - -static constexpr size_t USB_TX_TASK_STACK_SIZE = 4096; -static constexpr size_t USB_TX_TASK_STACK_SIZE_VV = 8192; +static const char *const TAG = "usb_cdc_acm"; // Global component instance for managing USB device -USBCDCACMComponent *global_usb_cdc_component = nullptr; - -static USBCDCACMInstance *get_instance_by_itf(int itf) { - if (global_usb_cdc_component == nullptr) { - return nullptr; - } - return global_usb_cdc_component->get_interface_by_number(itf); -} - -static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) { - USBCDCACMInstance *instance = get_instance_by_itf(itf); - if (instance == nullptr) { - ESP_LOGE(TAG, "RX callback: invalid interface %d", itf); - return; - } - - size_t rx_size = 0; - static uint8_t rx_buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE] = {0}; - - // read from USB - esp_err_t ret = - tinyusb_cdcacm_read(static_cast(itf), rx_buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size); - ESP_LOGV(TAG, "tinyusb_cdc_rx_callback itf=%d (size: %u)", itf, rx_size); -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE - char rx_hex_buf[format_hex_pretty_size(USB_CDC_MAX_LOG_BYTES)]; -#endif - ESP_LOGVV(TAG, "rx_buf = %s", format_hex_pretty_to(rx_hex_buf, rx_buf, rx_size)); - - if (ret == ESP_OK && rx_size > 0) { - RingbufHandle_t rx_ringbuf = instance->get_rx_ringbuf(); - if (rx_ringbuf != nullptr) { - BaseType_t send_res = xRingbufferSend(rx_ringbuf, rx_buf, rx_size, 0); - if (send_res != pdTRUE) { - ESP_LOGE(TAG, "USB RX itf=%d: buffer full, %u bytes lost", itf, rx_size); - } else { - ESP_LOGV(TAG, "USB RX itf=%d: queued %u bytes", itf, rx_size); - } - } - } -} - -static void tinyusb_cdc_line_state_changed_callback(int itf, cdcacm_event_t *event) { - USBCDCACMInstance *instance = get_instance_by_itf(itf); - if (instance == nullptr) { - ESP_LOGE(TAG, "Line state callback: invalid interface %d", itf); - return; - } - - int dtr = event->line_state_changed_data.dtr; - int rts = event->line_state_changed_data.rts; - ESP_LOGV(TAG, "Line state itf=%d: DTR=%d, RTS=%d", itf, dtr, rts); - - // Queue event for processing in main loop - instance->queue_line_state_event(dtr != 0, rts != 0); -} - -static void tinyusb_cdc_line_coding_changed_callback(int itf, cdcacm_event_t *event) { - USBCDCACMInstance *instance = get_instance_by_itf(itf); - if (instance == nullptr) { - ESP_LOGE(TAG, "Line coding callback: invalid interface %d", itf); - return; - } - - uint32_t bit_rate = event->line_coding_changed_data.p_line_coding->bit_rate; - uint8_t stop_bits = event->line_coding_changed_data.p_line_coding->stop_bits; - uint8_t parity = event->line_coding_changed_data.p_line_coding->parity; - uint8_t data_bits = event->line_coding_changed_data.p_line_coding->data_bits; - ESP_LOGV(TAG, "Line coding itf=%d: bit_rate=%" PRIu32 " stop_bits=%u parity=%u data_bits=%u", itf, bit_rate, - stop_bits, parity, data_bits); - - // Queue event for processing in main loop - instance->queue_line_coding_event(bit_rate, stop_bits, parity, data_bits); -} - -static esp_err_t ringbuf_read_bytes(RingbufHandle_t ring_buf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size, - TickType_t xTicksToWait) { - size_t read_sz; - uint8_t *buf = static_cast(xRingbufferReceiveUpTo(ring_buf, &read_sz, xTicksToWait, out_buf_sz)); - - if (buf == nullptr) { - return ESP_FAIL; - } - - memcpy(out_buf, buf, read_sz); - vRingbufferReturnItem(ring_buf, (void *) buf); - *rx_data_size = read_sz; - - // Buffer's data can be wrapped, in which case we should perform another read - buf = static_cast(xRingbufferReceiveUpTo(ring_buf, &read_sz, 0, out_buf_sz - *rx_data_size)); - if (buf != nullptr) { - memcpy(out_buf + *rx_data_size, buf, read_sz); - vRingbufferReturnItem(ring_buf, (void *) buf); - *rx_data_size += read_sz; - } - - return ESP_OK; -} +USBCDCACMComponent *global_usb_cdc_component = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) //============================================================================== // USBCDCACMInstance Implementation //============================================================================== -void USBCDCACMInstance::setup() { - this->usb_tx_ringbuf_ = xRingbufferCreate(CONFIG_TINYUSB_CDC_TX_BUFSIZE, RINGBUF_TYPE_BYTEBUF); - if (this->usb_tx_ringbuf_ == nullptr) { - ESP_LOGE(TAG, "USB TX buffer creation error for itf %d", this->itf_); - this->parent_->mark_failed(); - return; - } - - this->usb_rx_ringbuf_ = xRingbufferCreate(CONFIG_TINYUSB_CDC_RX_BUFSIZE, RINGBUF_TYPE_BYTEBUF); - if (this->usb_rx_ringbuf_ == nullptr) { - ESP_LOGE(TAG, "USB RX buffer creation error for itf %d", this->itf_); - this->parent_->mark_failed(); - return; - } - - // Configure this CDC interface - const tinyusb_config_cdcacm_t acm_cfg = { - .usb_dev = TINYUSB_USBDEV_0, - .cdc_port = this->itf_, - .callback_rx = &tinyusb_cdc_rx_callback, - .callback_rx_wanted_char = NULL, - .callback_line_state_changed = &tinyusb_cdc_line_state_changed_callback, - .callback_line_coding_changed = &tinyusb_cdc_line_coding_changed_callback, - }; - - esp_err_t result = tusb_cdc_acm_init(&acm_cfg); - if (result != ESP_OK) { - ESP_LOGE(TAG, "tusb_cdc_acm_init failed: %d", result); - this->parent_->mark_failed(); - return; - } - - // Use a larger stack size for (very) verbose logging - const size_t stack_size = esp_log_level_get(TAG) > ESP_LOG_DEBUG ? USB_TX_TASK_STACK_SIZE_VV : USB_TX_TASK_STACK_SIZE; - - // Create a simple, unique task name per interface - char task_name[] = "usb_tx_0"; - task_name[sizeof(task_name) - 1] = format_hex_char(static_cast(this->itf_)); - xTaskCreate(usb_tx_task_fn, task_name, stack_size, this, 4, &this->usb_tx_task_handle_); - - if (this->usb_tx_task_handle_ == nullptr) { - ESP_LOGE(TAG, "Failed to create USB TX task for itf %d", this->itf_); - this->parent_->mark_failed(); - return; - } -} - -void USBCDCACMInstance::loop() { - // Process events from the lock-free queue - this->process_events_(); -} - void USBCDCACMInstance::queue_line_state_event(bool dtr, bool rts) { // Allocate event from pool CDCEvent *event = this->event_pool_.allocate(); @@ -288,170 +124,6 @@ void USBCDCACMInstance::process_events_() { } } -void USBCDCACMInstance::usb_tx_task_fn(void *arg) { - auto *instance = static_cast(arg); - instance->usb_tx_task(); -} - -void USBCDCACMInstance::usb_tx_task() { - uint8_t data[CONFIG_TINYUSB_CDC_TX_BUFSIZE] = {0}; - size_t tx_data_size = 0; - - while (1) { - // Wait for a notification from the bridge component - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - - // When we do wake up, we can be sure there is data in the ring buffer - esp_err_t ret = ringbuf_read_bytes(this->usb_tx_ringbuf_, data, CONFIG_TINYUSB_CDC_TX_BUFSIZE, &tx_data_size, 0); - - if (ret != ESP_OK) { - ESP_LOGE(TAG, "USB TX itf=%d: RingBuf read failed", this->itf_); - continue; - } else if (tx_data_size == 0) { - ESP_LOGD(TAG, "USB TX itf=%d: RingBuf empty, skipping", this->itf_); - continue; - } - - ESP_LOGV(TAG, "USB TX itf=%d: Read %d bytes from buffer", this->itf_, tx_data_size); -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE - char tx_hex_buf[format_hex_pretty_size(USB_CDC_MAX_LOG_BYTES)]; -#endif - ESP_LOGVV(TAG, "data = %s", format_hex_pretty_to(tx_hex_buf, data, tx_data_size)); - - // Serial data will be split up into 64 byte chunks to be sent over USB so this - // usually will take multiple iterations - uint8_t *data_head = &data[0]; - - while (tx_data_size > 0) { - size_t queued = tinyusb_cdcacm_write_queue(this->itf_, data_head, tx_data_size); - ESP_LOGV(TAG, "USB TX itf=%d: enqueued: size=%d, queued=%u", this->itf_, tx_data_size, queued); - - tx_data_size -= queued; - data_head += queued; - - ESP_LOGV(TAG, "USB TX itf=%d: waiting 10ms for flush", this->itf_); - esp_err_t flush_ret = tinyusb_cdcacm_write_flush(this->itf_, pdMS_TO_TICKS(10)); - - if (flush_ret != ESP_OK) { - ESP_LOGE(TAG, "USB TX itf=%d: flush failed", this->itf_); - tud_cdc_n_write_clear(this->itf_); - break; - } - } - } -} - -//============================================================================== -// UARTComponent Interface Implementation -//============================================================================== - -void USBCDCACMInstance::write_array(const uint8_t *data, size_t len) { - if (len == 0) { - return; - } - - // Write data to TX ring buffer - BaseType_t send_res = xRingbufferSend(this->usb_tx_ringbuf_, data, len, 0); - if (send_res != pdTRUE) { - ESP_LOGW(TAG, "USB TX itf=%d: buffer full, %u bytes dropped", this->itf_, len); - return; - } - - // Notify TX task that data is available - if (this->usb_tx_task_handle_ != nullptr) { - xTaskNotifyGive(this->usb_tx_task_handle_); - } -} - -bool USBCDCACMInstance::peek_byte(uint8_t *data) { - if (this->has_peek_) { - *data = this->peek_buffer_; - return true; - } - - if (this->read_byte(&this->peek_buffer_)) { - *data = this->peek_buffer_; - this->has_peek_ = true; - return true; - } - - return false; -} - -bool USBCDCACMInstance::read_array(uint8_t *data, size_t len) { - if (len == 0) { - return true; - } - - size_t original_len = len; - size_t bytes_read = 0; - - // First, use the peek buffer if available - if (this->has_peek_) { - data[0] = this->peek_buffer_; - this->has_peek_ = false; - bytes_read = 1; - data++; - if (--len == 0) { // Decrement len first, then check it... - return true; // No more to read - } - } - - // Read remaining bytes from RX ring buffer - size_t rx_size = 0; - uint8_t *buf = static_cast(xRingbufferReceiveUpTo(this->usb_rx_ringbuf_, &rx_size, 0, len)); - if (buf == nullptr) { - return false; - } - - memcpy(data, buf, rx_size); - vRingbufferReturnItem(this->usb_rx_ringbuf_, (void *) buf); - bytes_read += rx_size; - data += rx_size; - len -= rx_size; - if (len == 0) { - return true; // No more to read - } - - // Buffer's data may wrap around, in which case we should perform another read - buf = static_cast(xRingbufferReceiveUpTo(this->usb_rx_ringbuf_, &rx_size, 0, len)); - if (buf == nullptr) { - return false; - } - - memcpy(data, buf, rx_size); - vRingbufferReturnItem(this->usb_rx_ringbuf_, (void *) buf); - bytes_read += rx_size; - - return bytes_read == original_len; -} - -int USBCDCACMInstance::available() { - UBaseType_t waiting = 0; - if (this->usb_rx_ringbuf_ != nullptr) { - vRingbufferGetInfo(this->usb_rx_ringbuf_, nullptr, nullptr, nullptr, nullptr, &waiting); - } - return static_cast(waiting) + (this->has_peek_ ? 1 : 0); -} - -void USBCDCACMInstance::flush() { - // Wait for TX ring buffer to be empty - if (this->usb_tx_ringbuf_ == nullptr) { - return; - } - - UBaseType_t waiting = 1; - while (waiting > 0) { - vRingbufferGetInfo(this->usb_tx_ringbuf_, nullptr, nullptr, nullptr, nullptr, &waiting); - if (waiting > 0) { - vTaskDelay(pdMS_TO_TICKS(1)); - } - } - - // Also wait for USB to finish transmitting - tinyusb_cdcacm_write_flush(this->itf_, pdMS_TO_TICKS(100)); -} - //============================================================================== // USBCDCACMComponent Implementation //============================================================================== @@ -460,7 +132,7 @@ USBCDCACMComponent::USBCDCACMComponent() { global_usb_cdc_component = this; } void USBCDCACMComponent::setup() { // Setup all registered interfaces - for (auto interface : this->interfaces_) { + for (auto *interface : this->interfaces_) { if (interface != nullptr) { interface->setup(); } @@ -469,7 +141,7 @@ void USBCDCACMComponent::setup() { void USBCDCACMComponent::loop() { // Call loop() on all registered interfaces to process events - for (auto interface : this->interfaces_) { + for (auto *interface : this->interfaces_) { if (interface != nullptr) { interface->loop(); } @@ -480,21 +152,28 @@ void USBCDCACMComponent::dump_config() { ESP_LOGCONFIG(TAG, "USB CDC-ACM:\n" " Number of Interfaces: %d", - this->interfaces_[MAX_USB_CDC_INSTANCES - 1] != nullptr ? MAX_USB_CDC_INSTANCES : 1); + ESPHOME_MAX_USB_CDC_INSTANCES); + for (uint8_t i = 0; i < ESPHOME_MAX_USB_CDC_INSTANCES; ++i) { + if (this->interfaces_[i] != nullptr) { + this->interfaces_[i]->dump_config(); + } else { + ESP_LOGCONFIG(TAG, " Interface %u is disabled", i); + } + } } void USBCDCACMComponent::add_interface(USBCDCACMInstance *interface) { uint8_t itf_num = static_cast(interface->get_itf()); - if (itf_num < MAX_USB_CDC_INSTANCES) { + if (itf_num < ESPHOME_MAX_USB_CDC_INSTANCES) { this->interfaces_[itf_num] = interface; } else { - ESP_LOGE(TAG, "Interface number must be less than %u", MAX_USB_CDC_INSTANCES); + ESP_LOGE(TAG, "Interface number must be less than %u", ESPHOME_MAX_USB_CDC_INSTANCES); } } USBCDCACMInstance *USBCDCACMComponent::get_interface_by_number(uint8_t itf) { - for (auto interface : this->interfaces_) { - if ((interface != nullptr) && (interface->get_itf() == static_cast(itf))) { + for (auto *interface : this->interfaces_) { + if ((interface != nullptr) && (interface->get_itf() == itf)) { return interface; } } diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index 8c00f5d52f..065d7282d5 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -13,7 +13,6 @@ namespace esphome::usb_cdc_acm { static const uint8_t EVENT_QUEUE_SIZE = 12; -static const uint8_t MAX_USB_CDC_INSTANCES = 2; // Callback types for line coding and line state changes using LineCodingCallback = std::function; @@ -53,14 +52,13 @@ class USBCDCACMComponent; /// Represents a single CDC ACM interface instance class USBCDCACMInstance : public uart::UARTComponent, public Parented { public: - void set_interface_number(uint8_t itf) { this->itf_ = static_cast(itf); } - void setup(); void loop(); + void dump_config(); + void set_interface_number(uint8_t itf) { this->itf_ = itf; } // Get the CDC port number for this instance - tinyusb_cdcacm_itf_t get_itf() const { return this->itf_; } - + uint8_t get_itf() const { return this->itf_; } // Ring buffer accessors for bridge components RingbufHandle_t get_tx_ringbuf() const { return this->usb_tx_ringbuf_; } RingbufHandle_t get_rx_ringbuf() const { return this->usb_rx_ringbuf_; } @@ -72,7 +70,7 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parentedline_coding_callback_ = std::move(callback); } void set_line_state_callback(LineStateCallback callback) { this->line_state_callback_ = std::move(callback); } - // Called from TinyUSB task context (SPSC producer) - queues event for processing in main loop + // Called from USB core task context queues event for processing in main loop void queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, uint8_t data_bits); void queue_line_state_event(bool dtr, bool rts); @@ -87,17 +85,18 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented event_pool_; LockFreeQueue event_queue_; - - // RX buffer for peek functionality - uint8_t peek_buffer_{0}; - bool has_peek_{false}; }; /// Main USB CDC ACM component that manages the USB device and all CDC interfaces @@ -126,7 +121,7 @@ class USBCDCACMComponent : public Component { USBCDCACMInstance *get_interface_by_number(uint8_t itf); protected: - std::array interfaces_{nullptr, nullptr}; + std::array interfaces_{}; }; extern USBCDCACMComponent *global_usb_cdc_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp new file mode 100644 index 0000000000..5c91150f30 --- /dev/null +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -0,0 +1,349 @@ +#if defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) +#include "usb_cdc_acm.h" +#include "esphome/core/application.h" +#include "esphome/core/log.h" + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/ringbuf.h" +#include "freertos/task.h" +#include "esp_log.h" + +#include "tusb.h" +#include "tusb_cdc_acm.h" + +namespace esphome::usb_cdc_acm { + +static const char *const TAG = "usb_cdc_acm"; + +// Maximum bytes to log in very verbose hex output (168 * 3 = 504, under TX buffer size of 512) +static constexpr size_t USB_CDC_MAX_LOG_BYTES = 168; + +static constexpr size_t USB_TX_TASK_STACK_SIZE = 4096; +static constexpr size_t USB_TX_TASK_STACK_SIZE_VV = 8192; + +static USBCDCACMInstance *get_instance_by_itf(int itf) { + if (global_usb_cdc_component == nullptr) { + return nullptr; + } + return global_usb_cdc_component->get_interface_by_number(itf); +} + +static void tinyusb_cdc_rx_callback(int itf, cdcacm_event_t *event) { + USBCDCACMInstance *instance = get_instance_by_itf(itf); + if (instance == nullptr) { + ESP_LOGE(TAG, "RX callback: invalid interface %d", itf); + return; + } + + size_t rx_size = 0; + static uint8_t rx_buf[CONFIG_TINYUSB_CDC_RX_BUFSIZE] = {0}; + + // read from USB + esp_err_t ret = + tinyusb_cdcacm_read(static_cast(itf), rx_buf, CONFIG_TINYUSB_CDC_RX_BUFSIZE, &rx_size); + ESP_LOGV(TAG, "tinyusb_cdc_rx_callback itf=%d (size: %u)", itf, rx_size); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char rx_hex_buf[format_hex_pretty_size(USB_CDC_MAX_LOG_BYTES)]; +#endif + ESP_LOGVV(TAG, "rx_buf = %s", format_hex_pretty_to(rx_hex_buf, rx_buf, rx_size)); + + if (ret == ESP_OK && rx_size > 0) { + RingbufHandle_t rx_ringbuf = instance->get_rx_ringbuf(); + if (rx_ringbuf != nullptr) { + BaseType_t send_res = xRingbufferSend(rx_ringbuf, rx_buf, rx_size, 0); + if (send_res != pdTRUE) { + ESP_LOGE(TAG, "USB RX itf=%d: buffer full, %u bytes lost", itf, rx_size); + } else { + ESP_LOGV(TAG, "USB RX itf=%d: queued %u bytes", itf, rx_size); + } + } + } +} + +static void tinyusb_cdc_line_state_changed_callback(int itf, cdcacm_event_t *event) { + USBCDCACMInstance *instance = get_instance_by_itf(itf); + if (instance == nullptr) { + ESP_LOGE(TAG, "Line state callback: invalid interface %d", itf); + return; + } + + int dtr = event->line_state_changed_data.dtr; + int rts = event->line_state_changed_data.rts; + ESP_LOGV(TAG, "Line state itf=%d: DTR=%d, RTS=%d", itf, dtr, rts); + + // Queue event for processing in main loop + instance->queue_line_state_event(dtr != 0, rts != 0); +} + +static void tinyusb_cdc_line_coding_changed_callback(int itf, cdcacm_event_t *event) { + USBCDCACMInstance *instance = get_instance_by_itf(itf); + if (instance == nullptr) { + ESP_LOGE(TAG, "Line coding callback: invalid interface %d", itf); + return; + } + + uint32_t bit_rate = event->line_coding_changed_data.p_line_coding->bit_rate; + uint8_t stop_bits = event->line_coding_changed_data.p_line_coding->stop_bits; + uint8_t parity = event->line_coding_changed_data.p_line_coding->parity; + uint8_t data_bits = event->line_coding_changed_data.p_line_coding->data_bits; + ESP_LOGV(TAG, "Line coding itf=%d: bit_rate=%" PRIu32 " stop_bits=%u parity=%u data_bits=%u", itf, bit_rate, + stop_bits, parity, data_bits); + + // Queue event for processing in main loop + instance->queue_line_coding_event(bit_rate, stop_bits, parity, data_bits); +} + +static esp_err_t ringbuf_read_bytes(RingbufHandle_t ring_buf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size, + TickType_t xTicksToWait) { + size_t read_sz; + uint8_t *buf = static_cast(xRingbufferReceiveUpTo(ring_buf, &read_sz, xTicksToWait, out_buf_sz)); + + if (buf == nullptr) { + return ESP_FAIL; + } + + memcpy(out_buf, buf, read_sz); + vRingbufferReturnItem(ring_buf, (void *) buf); + *rx_data_size = read_sz; + + // Buffer's data can be wrapped, in which case we should perform another read + buf = static_cast(xRingbufferReceiveUpTo(ring_buf, &read_sz, 0, out_buf_sz - *rx_data_size)); + if (buf != nullptr) { + memcpy(out_buf + *rx_data_size, buf, read_sz); + vRingbufferReturnItem(ring_buf, (void *) buf); + *rx_data_size += read_sz; + } + + return ESP_OK; +} + +//============================================================================== +// USBCDCACMInstance Implementation +//============================================================================== + +void USBCDCACMInstance::setup() { + this->usb_tx_ringbuf_ = xRingbufferCreate(CONFIG_TINYUSB_CDC_TX_BUFSIZE, RINGBUF_TYPE_BYTEBUF); + if (this->usb_tx_ringbuf_ == nullptr) { + ESP_LOGE(TAG, "USB TX buffer creation error for itf %d", this->itf_); + this->parent_->mark_failed(); + return; + } + + this->usb_rx_ringbuf_ = xRingbufferCreate(CONFIG_TINYUSB_CDC_RX_BUFSIZE, RINGBUF_TYPE_BYTEBUF); + if (this->usb_rx_ringbuf_ == nullptr) { + ESP_LOGE(TAG, "USB RX buffer creation error for itf %d", this->itf_); + this->parent_->mark_failed(); + return; + } + + // Configure this CDC interface + const tinyusb_config_cdcacm_t acm_cfg = { + .usb_dev = TINYUSB_USBDEV_0, + .cdc_port = static_cast(this->itf_), + .callback_rx = &tinyusb_cdc_rx_callback, + .callback_rx_wanted_char = NULL, + .callback_line_state_changed = &tinyusb_cdc_line_state_changed_callback, + .callback_line_coding_changed = &tinyusb_cdc_line_coding_changed_callback, + }; + + esp_err_t result = tusb_cdc_acm_init(&acm_cfg); + if (result != ESP_OK) { + ESP_LOGE(TAG, "tusb_cdc_acm_init failed: %d", result); + this->parent_->mark_failed(); + return; + } + + // Use a larger stack size for (very) verbose logging + const size_t stack_size = esp_log_level_get(TAG) > ESP_LOG_DEBUG ? USB_TX_TASK_STACK_SIZE_VV : USB_TX_TASK_STACK_SIZE; + + // Create a simple, unique task name per interface + char task_name[] = "usb_tx_0"; + task_name[sizeof(task_name) - 1] = format_hex_char(static_cast(this->itf_)); + xTaskCreate(usb_tx_task_fn, task_name, stack_size, this, 4, &this->usb_tx_task_handle_); + + if (this->usb_tx_task_handle_ == nullptr) { + ESP_LOGE(TAG, "Failed to create USB TX task for itf %d", this->itf_); + this->parent_->mark_failed(); + return; + } +} + +void USBCDCACMInstance::loop() { + // Process events from the lock-free queue + this->process_events_(); +} + +void USBCDCACMInstance::dump_config() {} + +void USBCDCACMInstance::usb_tx_task_fn(void *arg) { + auto *instance = static_cast(arg); + instance->usb_tx_task(); +} + +void USBCDCACMInstance::usb_tx_task() { + uint8_t data[CONFIG_TINYUSB_CDC_TX_BUFSIZE] = {0}; + size_t tx_data_size = 0; + + while (1) { + // Wait for a notification from the bridge component + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + // When we do wake up, we can be sure there is data in the ring buffer + esp_err_t ret = ringbuf_read_bytes(this->usb_tx_ringbuf_, data, CONFIG_TINYUSB_CDC_TX_BUFSIZE, &tx_data_size, 0); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "USB TX itf=%d: RingBuf read failed", this->itf_); + continue; + } else if (tx_data_size == 0) { + ESP_LOGD(TAG, "USB TX itf=%d: RingBuf empty, skipping", this->itf_); + continue; + } + + ESP_LOGV(TAG, "USB TX itf=%d: Read %d bytes from buffer", this->itf_, tx_data_size); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char tx_hex_buf[format_hex_pretty_size(USB_CDC_MAX_LOG_BYTES)]; +#endif + ESP_LOGVV(TAG, "data = %s", format_hex_pretty_to(tx_hex_buf, data, tx_data_size)); + + // Serial data will be split up into 64 byte chunks to be sent over USB so this + // usually will take multiple iterations + uint8_t *data_head = &data[0]; + + while (tx_data_size > 0) { + size_t queued = + tinyusb_cdcacm_write_queue(static_cast(this->itf_), data_head, tx_data_size); + ESP_LOGV(TAG, "USB TX itf=%d: enqueued: size=%d, queued=%u", this->itf_, tx_data_size, queued); + + tx_data_size -= queued; + data_head += queued; + + ESP_LOGV(TAG, "USB TX itf=%d: waiting 10ms for flush", this->itf_); + esp_err_t flush_ret = + tinyusb_cdcacm_write_flush(static_cast(this->itf_), pdMS_TO_TICKS(10)); + + if (flush_ret != ESP_OK) { + ESP_LOGE(TAG, "USB TX itf=%d: flush failed", this->itf_); + tud_cdc_n_write_clear(this->itf_); + break; + } + } + } +} + +//============================================================================== +// UARTComponent Interface Implementation +//============================================================================== + +void USBCDCACMInstance::write_array(const uint8_t *data, size_t len) { + if (len == 0) { + return; + } + + // Write data to TX ring buffer + BaseType_t send_res = xRingbufferSend(this->usb_tx_ringbuf_, data, len, 0); + if (send_res != pdTRUE) { + ESP_LOGW(TAG, "USB TX itf=%d: buffer full, %u bytes dropped", this->itf_, len); + return; + } + + // Notify TX task that data is available + if (this->usb_tx_task_handle_ != nullptr) { + xTaskNotifyGive(this->usb_tx_task_handle_); + } +} + +bool USBCDCACMInstance::peek_byte(uint8_t *data) { + if (this->has_peek_) { + *data = this->peek_buffer_; + return true; + } + + if (this->read_byte(&this->peek_buffer_)) { + *data = this->peek_buffer_; + this->has_peek_ = true; + return true; + } + + return false; +} + +bool USBCDCACMInstance::read_array(uint8_t *data, size_t len) { + if (len == 0) { + return true; + } + + size_t original_len = len; + size_t bytes_read = 0; + + // First, use the peek buffer if available + if (this->has_peek_) { + data[0] = this->peek_buffer_; + this->has_peek_ = false; + bytes_read = 1; + data++; + if (--len == 0) { // Decrement len first, then check it... + return true; // No more to read + } + } + + // Read remaining bytes from RX ring buffer + size_t rx_size = 0; + uint8_t *buf = static_cast(xRingbufferReceiveUpTo(this->usb_rx_ringbuf_, &rx_size, 0, len)); + if (buf == nullptr) { + return false; + } + + memcpy(data, buf, rx_size); + vRingbufferReturnItem(this->usb_rx_ringbuf_, (void *) buf); + bytes_read += rx_size; + data += rx_size; + len -= rx_size; + if (len == 0) { + return true; // No more to read + } + + // Buffer's data may wrap around, in which case we should perform another read + buf = static_cast(xRingbufferReceiveUpTo(this->usb_rx_ringbuf_, &rx_size, 0, len)); + if (buf == nullptr) { + return false; + } + + memcpy(data, buf, rx_size); + vRingbufferReturnItem(this->usb_rx_ringbuf_, (void *) buf); + bytes_read += rx_size; + + return bytes_read == original_len; +} + +int USBCDCACMInstance::available() { + UBaseType_t waiting = 0; + if (this->usb_rx_ringbuf_ != nullptr) { + vRingbufferGetInfo(this->usb_rx_ringbuf_, nullptr, nullptr, nullptr, nullptr, &waiting); + } + return static_cast(waiting) + (this->has_peek_ ? 1 : 0); +} + +void USBCDCACMInstance::flush() { + // Wait for TX ring buffer to be empty + if (this->usb_tx_ringbuf_ == nullptr) { + return; + } + + UBaseType_t waiting = 1; + while (waiting > 0) { + vRingbufferGetInfo(this->usb_tx_ringbuf_, nullptr, nullptr, nullptr, nullptr, &waiting); + if (waiting > 0) { + vTaskDelay(pdMS_TO_TICKS(1)); + } + } + + // Also wait for USB to finish transmitting + tinyusb_cdcacm_write_flush(static_cast(this->itf_), pdMS_TO_TICKS(100)); +} + +void USBCDCACMInstance::check_logger_conflict() {} + +} // namespace esphome::usb_cdc_acm +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 673397fa31..bb40cd4ad1 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -358,3 +358,4 @@ #define ESPHOME_ENTITY_UPDATE_COUNT 1 #define ESPHOME_ENTITY_VALVE_COUNT 1 #define ESPHOME_ENTITY_WATER_HEATER_COUNT 1 +#define ESPHOME_MAX_USB_CDC_INSTANCES 1 From d5f557ad1c325fa28c5a63d6f10c3b39c358f785 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 14 Jan 2026 04:15:31 -1000 Subject: [PATCH 0106/2030] [scheduler] Eliminate heap allocations for std::string names and add uint32_t ID API (#13200) --- esphome/components/api/api_server.cpp | 18 +- esphome/core/base_automation.h | 8 +- esphome/core/component.cpp | 47 +++ esphome/core/component.h | 47 +++ esphome/core/progmem.h | 4 + esphome/core/scheduler.cpp | 327 +++++++++++------- esphome/core/scheduler.h | 191 +++++----- .../fixtures/scheduler_numeric_id_test.yaml | 173 +++++++++ .../fixtures/scheduler_retry_test.yaml | 21 -- .../test_scheduler_numeric_id_test.py | 217 ++++++++++++ .../integration/test_scheduler_retry_test.py | 19 +- 11 files changed, 816 insertions(+), 256 deletions(-) create mode 100644 tests/integration/fixtures/scheduler_numeric_id_test.yaml create mode 100644 tests/integration/test_scheduler_numeric_id_test.py diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a1fe33edb2..a4eeb4dd5e 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -645,18 +645,18 @@ uint32_t APIServer::register_active_action_call(uint32_t client_call_id, APIConn this->active_action_calls_.push_back({action_call_id, client_call_id, conn}); // Schedule automatic cleanup after timeout (client will have given up by then) - this->set_timeout(str_sprintf("action_call_%u", action_call_id), USE_API_ACTION_CALL_TIMEOUT_MS, - [this, action_call_id]() { - ESP_LOGD(TAG, "Action call %u timed out", action_call_id); - this->unregister_active_action_call(action_call_id); - }); + // Uses numeric ID overload to avoid heap allocation from str_sprintf + this->set_timeout(action_call_id, USE_API_ACTION_CALL_TIMEOUT_MS, [this, action_call_id]() { + ESP_LOGD(TAG, "Action call %u timed out", action_call_id); + this->unregister_active_action_call(action_call_id); + }); return action_call_id; } void APIServer::unregister_active_action_call(uint32_t action_call_id) { - // Cancel the timeout for this action call - this->cancel_timeout(str_sprintf("action_call_%u", action_call_id)); + // Cancel the timeout for this action call (uses numeric ID overload) + this->cancel_timeout(action_call_id); // Swap-and-pop is more efficient than remove_if for unordered vectors for (size_t i = 0; i < this->active_action_calls_.size(); i++) { @@ -672,8 +672,8 @@ void APIServer::unregister_active_action_calls_for_connection(APIConnection *con // Remove all active action calls for disconnected connection using swap-and-pop for (size_t i = 0; i < this->active_action_calls_.size();) { if (this->active_action_calls_[i].connection == conn) { - // Cancel the timeout for this action call - this->cancel_timeout(str_sprintf("action_call_%u", this->active_action_calls_[i].action_call_id)); + // Cancel the timeout for this action call (uses numeric ID overload) + this->cancel_timeout(this->active_action_calls_[i].action_call_id); std::swap(this->active_action_calls_[i], this->active_action_calls_.back()); this->active_action_calls_.pop_back(); diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index e8878ac251..19d0ccf972 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -191,15 +191,15 @@ template class DelayAction : public Action, public Compon // instead of std::bind to avoid bind overhead (~16 bytes heap + faster execution) if constexpr (sizeof...(Ts) == 0) { App.scheduler.set_timer_common_( - this, Scheduler::SchedulerItem::TIMEOUT, - /* is_static_string= */ true, "delay", this->delay_.value(), [this]() { this->play_next_(); }, + this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::STATIC_STRING, "delay", 0, this->delay_.value(), + [this]() { this->play_next_(); }, /* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1); } else { // For delays with arguments, use std::bind to preserve argument values // Arguments must be copied because original references may be invalid after delay auto f = std::bind(&DelayAction::play_next_, this, x...); - App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, - /* is_static_string= */ true, "delay", this->delay_.value(x...), std::move(f), + App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::STATIC_STRING, + "delay", 0, this->delay_.value(x...), std::move(f), /* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1); } } diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 90be6cf646..2f61f7d195 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -118,7 +118,10 @@ void Component::setup() {} void Component::loop() {} void Component::set_interval(const std::string &name, uint32_t interval, std::function &&f) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_interval(this, name, interval, std::move(f)); +#pragma GCC diagnostic pop } void Component::set_interval(const char *name, uint32_t interval, std::function &&f) { // NOLINT @@ -126,7 +129,10 @@ void Component::set_interval(const char *name, uint32_t interval, std::function< } bool Component::cancel_interval(const std::string &name) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" return App.scheduler.cancel_interval(this, name); +#pragma GCC diagnostic pop } bool Component::cancel_interval(const char *name) { // NOLINT @@ -135,7 +141,10 @@ bool Component::cancel_interval(const char *name) { // NOLINT void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, float backoff_increase_factor) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); +#pragma GCC diagnostic pop } void Component::set_retry(const char *name, uint32_t initial_wait_time, uint8_t max_attempts, @@ -144,7 +153,10 @@ void Component::set_retry(const char *name, uint32_t initial_wait_time, uint8_t } bool Component::cancel_retry(const std::string &name) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" return App.scheduler.cancel_retry(this, name); +#pragma GCC diagnostic pop } bool Component::cancel_retry(const char *name) { // NOLINT @@ -152,7 +164,10 @@ bool Component::cancel_retry(const char *name) { // NOLINT } void Component::set_timeout(const std::string &name, uint32_t timeout, std::function &&f) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_timeout(this, name, timeout, std::move(f)); +#pragma GCC diagnostic pop } void Component::set_timeout(const char *name, uint32_t timeout, std::function &&f) { // NOLINT @@ -160,13 +175,36 @@ void Component::set_timeout(const char *name, uint32_t timeout, std::function &&f) { // NOLINT + App.scheduler.set_timeout(this, id, timeout, std::move(f)); +} + +bool Component::cancel_timeout(uint32_t id) { return App.scheduler.cancel_timeout(this, id); } + +void Component::set_interval(uint32_t id, uint32_t interval, std::function &&f) { // NOLINT + App.scheduler.set_interval(this, id, interval, std::move(f)); +} + +bool Component::cancel_interval(uint32_t id) { return App.scheduler.cancel_interval(this, id); } + +void Component::set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, + std::function &&f, float backoff_increase_factor) { // NOLINT + App.scheduler.set_retry(this, id, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); +} + +bool Component::cancel_retry(uint32_t id) { return App.scheduler.cancel_retry(this, id); } + void Component::call_loop() { this->loop(); } void Component::call_setup() { this->setup(); } void Component::call_dump_config() { @@ -301,10 +339,19 @@ void Component::defer(std::function &&f) { // NOLINT App.scheduler.set_timeout(this, static_cast(nullptr), 0, std::move(f)); } bool Component::cancel_defer(const std::string &name) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return App.scheduler.cancel_timeout(this, name); +#pragma GCC diagnostic pop +} +bool Component::cancel_defer(const char *name) { // NOLINT return App.scheduler.cancel_timeout(this, name); } void Component::defer(const std::string &name, std::function &&f) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_timeout(this, name, 0, std::move(f)); +#pragma GCC diagnostic pop } void Component::defer(const char *name, std::function &&f) { // NOLINT App.scheduler.set_timeout(this, name, 0, std::move(f)); diff --git a/esphome/core/component.h b/esphome/core/component.h index 32f594d6f8..49349d4199 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -306,6 +306,8 @@ class Component { * * @see cancel_interval() */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(const std::string &name, uint32_t interval, std::function &&f); // NOLINT /** Set an interval function with a const char* name. @@ -324,6 +326,14 @@ class Component { */ void set_interval(const char *name, uint32_t interval, std::function &&f); // NOLINT + /** Set an interval function with a numeric ID (zero heap allocation). + * + * @param id The numeric identifier for this interval function + * @param interval The interval in ms + * @param f The function to call + */ + void set_interval(uint32_t id, uint32_t interval, std::function &&f); // NOLINT + void set_interval(uint32_t interval, std::function &&f); // NOLINT /** Cancel an interval function. @@ -331,8 +341,11 @@ class Component { * @param name The identifier for this interval function. * @return Whether an interval functions was deleted. */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(const std::string &name); // NOLINT bool cancel_interval(const char *name); // NOLINT + bool cancel_interval(uint32_t id); // NOLINT /** Set an retry function with a unique name. Empty name means no cancelling possible. * @@ -364,12 +377,25 @@ class Component { * @param backoff_increase_factor time between retries is multiplied by this factor on every retry after the first * @see cancel_retry() */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT std::function &&f, float backoff_increase_factor = 1.0f); // NOLINT void set_retry(const char *name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT std::function &&f, float backoff_increase_factor = 1.0f); // NOLINT + /** Set a retry function with a numeric ID (zero heap allocation). + * + * @param id The numeric identifier for this retry function + * @param initial_wait_time The wait time after the first execution + * @param max_attempts The max number of attempts + * @param f The function to call + * @param backoff_increase_factor The factor to increase the retry interval by + */ + void set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT + std::function &&f, float backoff_increase_factor = 1.0f); // NOLINT + void set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, // NOLINT float backoff_increase_factor = 1.0f); // NOLINT @@ -378,8 +404,11 @@ class Component { * @param name The identifier for this retry function. * @return Whether a retry function was deleted. */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_retry(const std::string &name); // NOLINT bool cancel_retry(const char *name); // NOLINT + bool cancel_retry(uint32_t id); // NOLINT /** Set a timeout function with a unique name. * @@ -395,6 +424,8 @@ class Component { * * @see cancel_timeout() */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(const std::string &name, uint32_t timeout, std::function &&f); // NOLINT /** Set a timeout function with a const char* name. @@ -413,6 +444,14 @@ class Component { */ void set_timeout(const char *name, uint32_t timeout, std::function &&f); // NOLINT + /** Set a timeout function with a numeric ID (zero heap allocation). + * + * @param id The numeric identifier for this timeout function + * @param timeout The timeout in ms + * @param f The function to call + */ + void set_timeout(uint32_t id, uint32_t timeout, std::function &&f); // NOLINT + void set_timeout(uint32_t timeout, std::function &&f); // NOLINT /** Cancel a timeout function. @@ -420,8 +459,11 @@ class Component { * @param name The identifier for this timeout function. * @return Whether a timeout functions was deleted. */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(const std::string &name); // NOLINT bool cancel_timeout(const char *name); // NOLINT + bool cancel_timeout(uint32_t id); // NOLINT /** Defer a callback to the next loop() call. * @@ -430,6 +472,8 @@ class Component { * @param name The name of the defer function. * @param f The callback. */ + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") void defer(const std::string &name, std::function &&f); // NOLINT /** Defer a callback to the next loop() call with a const char* name. @@ -451,7 +495,10 @@ class Component { void defer(std::function &&f); // NOLINT /// Cancel a defer callback using the specified name, name must not be empty. + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_defer(const std::string &name); // NOLINT + bool cancel_defer(const char *name); // NOLINT // Ordered for optimal packing on 32-bit systems const LogString *component_source_{nullptr}; diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index d1594f47e7..fe9c9b5a75 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -8,11 +8,15 @@ // ESP8266 uses Arduino macros #define ESPHOME_F(string_literal) F(string_literal) #define ESPHOME_PGM_P PGM_P +#define ESPHOME_PSTR(s) PSTR(s) #define ESPHOME_strncpy_P strncpy_P #define ESPHOME_strncat_P strncat_P +#define ESPHOME_snprintf_P snprintf_P #else #define ESPHOME_F(string_literal) (string_literal) #define ESPHOME_PGM_P const char * +#define ESPHOME_PSTR(s) (s) #define ESPHOME_strncpy_P strncpy #define ESPHOME_strncat_P strncat +#define ESPHOME_snprintf_P snprintf #endif diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index b28cb947c7..047bf4ef17 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -5,6 +5,7 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include #include #include @@ -32,6 +33,34 @@ static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits::max() // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; +#if defined(ESPHOME_LOG_HAS_VERBOSE) || defined(ESPHOME_DEBUG_SCHEDULER) +// Helper struct for formatting scheduler item names consistently in logs +// Uses a stack buffer to avoid heap allocation +// Uses ESPHOME_snprintf_P/ESPHOME_PSTR for ESP8266 to keep format strings in flash +struct SchedulerNameLog { + char buffer[20]; // Enough for "id:4294967295" or "hash:0xFFFFFFFF" or "(null)" + + // Format a scheduler item name for logging + // Returns pointer to formatted string (either static_name or internal buffer) + const char *format(Scheduler::NameType name_type, const char *static_name, uint32_t hash_or_id) { + using NameType = Scheduler::NameType; + if (name_type == NameType::STATIC_STRING) { + if (static_name) + return static_name; + // Copy "(null)" to buffer to keep it in flash on ESP8266 + ESPHOME_strncpy_P(buffer, ESPHOME_PSTR("(null)"), sizeof(buffer)); + return buffer; + } else if (name_type == NameType::HASHED_STRING) { + ESPHOME_snprintf_P(buffer, sizeof(buffer), ESPHOME_PSTR("hash:0x%08" PRIX32), hash_or_id); + return buffer; + } else { // NUMERIC_ID + ESPHOME_snprintf_P(buffer, sizeof(buffer), ESPHOME_PSTR("id:%" PRIu32), hash_or_id); + return buffer; + } + } +}; +#endif + // Uncomment to debug scheduler // #define ESPHOME_DEBUG_SCHEDULER @@ -76,17 +105,15 @@ static void validate_static_string(const char *name) { // avoid the main thread modifying the list while it is being accessed. // Common implementation for both timeout and interval -void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type type, bool is_static_string, - const void *name_ptr, uint32_t delay, std::function func, bool is_retry, - bool skip_cancel) { - // Get the name as const char* - const char *name_cstr = this->get_name_cstr_(is_static_string, name_ptr); - +// name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id +void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, + const char *static_name, uint32_t hash_or_id, uint32_t delay, + std::function func, bool is_retry, bool skip_cancel) { if (delay == SCHEDULER_DONT_RUN) { - // Still need to cancel existing timer if name is not empty + // Still need to cancel existing timer if we have a name/id if (!skip_cancel) { LockGuard guard{this->lock_}; - this->cancel_item_locked_(component, name_cstr, type); + this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } return; } @@ -98,23 +125,19 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type LockGuard guard{this->lock_}; // Create and populate the scheduler item - std::unique_ptr item; - if (!this->scheduler_item_pool_.empty()) { - // Reuse from pool - item = std::move(this->scheduler_item_pool_.back()); - this->scheduler_item_pool_.pop_back(); -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Reused item from pool (pool size now: %zu)", this->scheduler_item_pool_.size()); -#endif - } else { - // Allocate new if pool is empty - item = make_unique(); -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Allocated new item (pool empty)"); -#endif - } + auto item = this->get_item_from_pool_locked_(); item->component = component; - item->set_name(name_cstr, !is_static_string); + switch (name_type) { + case NameType::STATIC_STRING: + item->set_static_name(static_name); + break; + case NameType::HASHED_STRING: + item->set_hashed_name(hash_or_id); + break; + case NameType::NUMERIC_ID: + item->set_numeric_id(hash_or_id); + break; + } item->type = type; item->callback = std::move(func); // Reset remove flag - recycled items may have been cancelled (remove=true) in previous use @@ -127,7 +150,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type if (delay == 0 && type == SchedulerItem::TIMEOUT) { // Put in defer queue for guaranteed FIFO execution if (!skip_cancel) { - this->cancel_item_locked_(component, name_cstr, type); + this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } this->defer_queue_.push_back(std::move(item)); return; @@ -141,24 +164,32 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Calculate random offset (0 to min(interval/2, 5s)) uint32_t offset = (uint32_t) (std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); item->set_next_execution(now + offset); - ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", name_cstr ? name_cstr : "", delay, - offset); +#ifdef ESPHOME_LOG_HAS_VERBOSE + SchedulerNameLog name_log; + ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", + name_log.format(name_type, static_name, hash_or_id), delay, offset); +#endif } else { item->interval = 0; item->set_next_execution(now + delay); } #ifdef ESPHOME_DEBUG_SCHEDULER - this->debug_log_timer_(item.get(), is_static_string, name_cstr, type, delay, now); + this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now); #endif /* ESPHOME_DEBUG_SCHEDULER */ // For retries, check if there's a cancelled timeout first - if (is_retry && name_cstr != nullptr && type == SchedulerItem::TIMEOUT && - (has_cancelled_timeout_in_container_locked_(this->items_, component, name_cstr, /* match_retry= */ true) || - has_cancelled_timeout_in_container_locked_(this->to_add_, component, name_cstr, /* match_retry= */ true))) { + // Skip check for anonymous retries (STATIC_STRING with nullptr) - they can't be cancelled by name + if (is_retry && (name_type != NameType::STATIC_STRING || static_name != nullptr) && type == SchedulerItem::TIMEOUT && + (has_cancelled_timeout_in_container_locked_(this->items_, component, name_type, static_name, hash_or_id, + /* match_retry= */ true) || + has_cancelled_timeout_in_container_locked_(this->to_add_, component, name_type, static_name, hash_or_id, + /* match_retry= */ true))) { // Skip scheduling - the retry was cancelled #ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", name_cstr); + SchedulerNameLog skip_name_log; + ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", + skip_name_log.format(name_type, static_name, hash_or_id)); #endif return; } @@ -166,7 +197,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // If name is provided, do atomic cancel-and-add (unless skip_cancel is true) // Cancel existing items if (!skip_cancel) { - this->cancel_item_locked_(component, name_cstr, type); + this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } // Add new item directly to to_add_ // since we have the lock held @@ -174,33 +205,51 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type } void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, std::function func) { - this->set_timer_common_(component, SchedulerItem::TIMEOUT, true, name, timeout, std::move(func)); + this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::STATIC_STRING, name, 0, timeout, + std::move(func)); } void HOT Scheduler::set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function func) { - this->set_timer_common_(component, SchedulerItem::TIMEOUT, false, &name, timeout, std::move(func)); + this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), + timeout, std::move(func)); +} +void HOT Scheduler::set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function func) { + this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::NUMERIC_ID, nullptr, id, timeout, + std::move(func)); } bool HOT Scheduler::cancel_timeout(Component *component, const std::string &name) { - return this->cancel_item_(component, false, &name, SchedulerItem::TIMEOUT); + return this->cancel_item_(component, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), SchedulerItem::TIMEOUT); } bool HOT Scheduler::cancel_timeout(Component *component, const char *name) { - return this->cancel_item_(component, true, name, SchedulerItem::TIMEOUT); + return this->cancel_item_(component, NameType::STATIC_STRING, name, 0, SchedulerItem::TIMEOUT); +} +bool HOT Scheduler::cancel_timeout(Component *component, uint32_t id) { + return this->cancel_item_(component, NameType::NUMERIC_ID, nullptr, id, SchedulerItem::TIMEOUT); } void HOT Scheduler::set_interval(Component *component, const std::string &name, uint32_t interval, std::function func) { - this->set_timer_common_(component, SchedulerItem::INTERVAL, false, &name, interval, std::move(func)); + this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), + interval, std::move(func)); } void HOT Scheduler::set_interval(Component *component, const char *name, uint32_t interval, std::function func) { - this->set_timer_common_(component, SchedulerItem::INTERVAL, true, name, interval, std::move(func)); + this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::STATIC_STRING, name, 0, interval, + std::move(func)); +} +void HOT Scheduler::set_interval(Component *component, uint32_t id, uint32_t interval, std::function func) { + this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::NUMERIC_ID, nullptr, id, interval, + std::move(func)); } bool HOT Scheduler::cancel_interval(Component *component, const std::string &name) { - return this->cancel_item_(component, false, &name, SchedulerItem::INTERVAL); + return this->cancel_item_(component, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), SchedulerItem::INTERVAL); } bool HOT Scheduler::cancel_interval(Component *component, const char *name) { - return this->cancel_item_(component, true, name, SchedulerItem::INTERVAL); + return this->cancel_item_(component, NameType::STATIC_STRING, name, 0, SchedulerItem::INTERVAL); +} +bool HOT Scheduler::cancel_interval(Component *component, uint32_t id) { + return this->cancel_item_(component, NameType::NUMERIC_ID, nullptr, id, SchedulerItem::INTERVAL); } struct RetryArgs { @@ -208,17 +257,15 @@ struct RetryArgs { std::function func; Component *component; Scheduler *scheduler; - const char *name; // Points to static string or owned copy + // Union for name storage - only one is used based on name_type + union { + const char *static_name; // For STATIC_STRING + uint32_t hash_or_id; // For HASHED_STRING or NUMERIC_ID + } name_; uint32_t current_interval; float backoff_increase_factor; + Scheduler::NameType name_type; // Discriminator for name_ union uint8_t retry_countdown; - bool name_is_dynamic; // True if name needs delete[] - - ~RetryArgs() { - if (this->name_is_dynamic && this->name) { - delete[] this->name; - } - } }; void retry_handler(const std::shared_ptr &args) { @@ -226,31 +273,38 @@ void retry_handler(const std::shared_ptr &args) { if (retry_result == RetryResult::DONE || args->retry_countdown <= 0) return; // second execution of `func` happens after `initial_wait_time` - // Pass is_static_string=true because args->name is owned by the shared_ptr + // args->name_ is owned by the shared_ptr // which is captured in the lambda and outlives the SchedulerItem + const char *static_name = (args->name_type == Scheduler::NameType::STATIC_STRING) ? args->name_.static_name : nullptr; + uint32_t hash_or_id = (args->name_type != Scheduler::NameType::STATIC_STRING) ? args->name_.hash_or_id : 0; args->scheduler->set_timer_common_( - args->component, Scheduler::SchedulerItem::TIMEOUT, true, args->name, args->current_interval, - [args]() { retry_handler(args); }, /* is_retry= */ true); + args->component, Scheduler::SchedulerItem::TIMEOUT, args->name_type, static_name, hash_or_id, + args->current_interval, [args]() { retry_handler(args); }, + /* is_retry= */ true); // backoff_increase_factor applied to third & later executions args->current_interval *= args->backoff_increase_factor; } -void HOT Scheduler::set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, - uint32_t initial_wait_time, uint8_t max_attempts, +void HOT Scheduler::set_retry_common_(Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id, uint32_t initial_wait_time, uint8_t max_attempts, std::function func, float backoff_increase_factor) { - const char *name_cstr = this->get_name_cstr_(is_static_string, name_ptr); - - if (name_cstr != nullptr) - this->cancel_retry(component, name_cstr); + this->cancel_retry_(component, name_type, static_name, hash_or_id); if (initial_wait_time == SCHEDULER_DONT_RUN) return; - ESP_LOGVV(TAG, "set_retry(name='%s', initial_wait_time=%" PRIu32 ", max_attempts=%u, backoff_factor=%0.1f)", - name_cstr ? name_cstr : "", initial_wait_time, max_attempts, backoff_increase_factor); +#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE + { + SchedulerNameLog name_log; + ESP_LOGVV(TAG, "set_retry(name='%s', initial_wait_time=%" PRIu32 ", max_attempts=%u, backoff_factor=%0.1f)", + name_log.format(name_type, static_name, hash_or_id), initial_wait_time, max_attempts, + backoff_increase_factor); + } +#endif if (backoff_increase_factor < 0.0001) { - ESP_LOGE(TAG, "backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor, name_cstr ? name_cstr : ""); + ESP_LOGE(TAG, "set_retry: backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor, + (name_type == NameType::STATIC_STRING && static_name) ? static_name : ""); backoff_increase_factor = 1; } @@ -258,56 +312,56 @@ void HOT Scheduler::set_retry_common_(Component *component, bool is_static_strin args->func = std::move(func); args->component = component; args->scheduler = this; + args->name_type = name_type; + if (name_type == NameType::STATIC_STRING) { + args->name_.static_name = static_name; + } else { + args->name_.hash_or_id = hash_or_id; + } args->current_interval = initial_wait_time; args->backoff_increase_factor = backoff_increase_factor; args->retry_countdown = max_attempts; - // Store name - either as static pointer or owned copy - if (name_cstr == nullptr || name_cstr[0] == '\0') { - // Empty or null name - use empty string literal - args->name = ""; - args->name_is_dynamic = false; - } else if (is_static_string) { - // Static string - just store the pointer - args->name = name_cstr; - args->name_is_dynamic = false; - } else { - // Dynamic string - make a copy - size_t len = strlen(name_cstr); - char *copy = new char[len + 1]; - memcpy(copy, name_cstr, len + 1); - args->name = copy; - args->name_is_dynamic = true; - } - // First execution of `func` immediately - use set_timer_common_ with is_retry=true - // Pass is_static_string=true because args->name is owned by the shared_ptr - // which is captured in the lambda and outlives the SchedulerItem this->set_timer_common_( - component, SchedulerItem::TIMEOUT, true, args->name, 0, [args]() { retry_handler(args); }, + component, SchedulerItem::TIMEOUT, name_type, static_name, hash_or_id, 0, [args]() { retry_handler(args); }, /* is_retry= */ true); } +void HOT Scheduler::set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor) { + this->set_retry_common_(component, NameType::STATIC_STRING, name, 0, initial_wait_time, max_attempts, std::move(func), + backoff_increase_factor); +} + +bool HOT Scheduler::cancel_retry_(Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id) { + return this->cancel_item_(component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, + /* match_retry= */ true); +} +bool HOT Scheduler::cancel_retry(Component *component, const char *name) { + return this->cancel_retry_(component, NameType::STATIC_STRING, name, 0); +} + void HOT Scheduler::set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function func, float backoff_increase_factor) { - this->set_retry_common_(component, false, &name, initial_wait_time, max_attempts, std::move(func), - backoff_increase_factor); + this->set_retry_common_(component, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), initial_wait_time, + max_attempts, std::move(func), backoff_increase_factor); } -void HOT Scheduler::set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, - std::function func, float backoff_increase_factor) { - this->set_retry_common_(component, true, name, initial_wait_time, max_attempts, std::move(func), - backoff_increase_factor); -} bool HOT Scheduler::cancel_retry(Component *component, const std::string &name) { - return this->cancel_retry(component, name.c_str()); + return this->cancel_retry_(component, NameType::HASHED_STRING, nullptr, fnv1a_hash(name)); } -bool HOT Scheduler::cancel_retry(Component *component, const char *name) { - // Cancel timeouts that have is_retry flag set - LockGuard guard{this->lock_}; - return this->cancel_item_locked_(component, name, SchedulerItem::TIMEOUT, /* match_retry= */ true); +void HOT Scheduler::set_retry(Component *component, uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor) { + this->set_retry_common_(component, NameType::NUMERIC_ID, nullptr, id, initial_wait_time, max_attempts, + std::move(func), backoff_increase_factor); +} + +bool HOT Scheduler::cancel_retry(Component *component, uint32_t id) { + return this->cancel_retry_(component, NameType::NUMERIC_ID, nullptr, id); } optional HOT Scheduler::next_schedule_in(uint32_t now) { @@ -391,10 +445,11 @@ void HOT Scheduler::call(uint32_t now) { item = this->pop_raw_locked_(); } - const char *name = item->get_name(); + SchedulerNameLog name_log; bool is_cancelled = is_item_removed_(item.get()); ESP_LOGD(TAG, " %s '%s/%s' interval=%" PRIu32 " next_execution in %" PRIu64 "ms at %" PRIu64 "%s", - item->get_type_str(), LOG_STR_ARG(item->get_source()), name ? name : "(null)", item->interval, + item->get_type_str(), LOG_STR_ARG(item->get_source()), + name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval, item->get_next_execution() - now_64, item->get_next_execution(), is_cancelled ? " [CANCELLED]" : ""); old_items.push_back(std::move(item)); @@ -458,10 +513,13 @@ void HOT Scheduler::call(uint32_t now) { #endif #ifdef ESPHOME_DEBUG_SCHEDULER - const char *item_name = item->get_name(); - ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")", - item->get_type_str(), LOG_STR_ARG(item->get_source()), item_name ? item_name : "(null)", item->interval, - item->get_next_execution(), now_64); + { + SchedulerNameLog name_log; + ESP_LOGV(TAG, "Running %s '%s/%s' with interval=%" PRIu32 " next_execution=%" PRIu64 " (now=%" PRIu64 ")", + item->get_type_str(), LOG_STR_ARG(item->get_source()), + name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval, + item->get_next_execution(), now_64); + } #endif /* ESPHOME_DEBUG_SCHEDULER */ // Warning: During callback(), a lot of stuff can happen, including: @@ -560,33 +618,29 @@ uint32_t HOT Scheduler::execute_item_(SchedulerItem *item, uint32_t now) { return guard.finish(); } -// Common implementation for cancel operations -bool HOT Scheduler::cancel_item_(Component *component, bool is_static_string, const void *name_ptr, - SchedulerItem::Type type) { - // Get the name as const char* - const char *name_cstr = this->get_name_cstr_(is_static_string, name_ptr); - - // obtain lock because this function iterates and can be called from non-loop task context +// Common implementation for cancel operations - handles locking +bool HOT Scheduler::cancel_item_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry) { LockGuard guard{this->lock_}; - return this->cancel_item_locked_(component, name_cstr, type); + return this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type, match_retry); } -// Helper to cancel items by name - must be called with lock held -bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_cstr, SchedulerItem::Type type, - bool match_retry) { - // Early return if name is invalid - no items to cancel - if (name_cstr == nullptr) { +// Helper to cancel items - must be called with lock held +// name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id +bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { + // Early return if static string name is invalid + if (name_type == NameType::STATIC_STRING && static_name == nullptr) { return false; } size_t total_cancelled = 0; - // Check all containers for matching items #ifndef ESPHOME_THREAD_SINGLE // Mark items in defer queue as cancelled (they'll be skipped when processed) if (type == SchedulerItem::TIMEOUT) { - total_cancelled += - this->mark_matching_items_removed_locked_(this->defer_queue_, component, name_cstr, type, match_retry); + total_cancelled += this->mark_matching_items_removed_locked_(this->defer_queue_, component, name_type, static_name, + hash_or_id, type, match_retry); } #endif /* not ESPHOME_THREAD_SINGLE */ @@ -596,14 +650,15 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, const char *name_c // would destroy the callback while it's running (use-after-free). // Only the main loop in call() should recycle items after execution completes. if (!this->items_.empty()) { - size_t heap_cancelled = - this->mark_matching_items_removed_locked_(this->items_, component, name_cstr, type, match_retry); + size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_, component, name_type, static_name, + hash_or_id, type, match_retry); total_cancelled += heap_cancelled; this->to_remove_ += heap_cancelled; } // Cancel items in to_add_ - total_cancelled += this->mark_matching_items_removed_locked_(this->to_add_, component, name_cstr, type, match_retry); + total_cancelled += this->mark_matching_items_removed_locked_(this->to_add_, component, name_type, static_name, + hash_or_id, type, match_retry); return total_cancelled > 0; } @@ -785,8 +840,6 @@ void Scheduler::recycle_item_main_loop_(std::unique_ptr item) { if (this->scheduler_item_pool_.size() < MAX_POOL_SIZE) { // Clear callback to release captured resources item->callback = nullptr; - // Clear dynamic name if any - item->clear_dynamic_name(); this->scheduler_item_pool_.push_back(std::move(item)); #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Recycled item to pool (pool size now: %zu)", this->scheduler_item_pool_.size()); @@ -800,24 +853,44 @@ void Scheduler::recycle_item_main_loop_(std::unique_ptr item) { } #ifdef ESPHOME_DEBUG_SCHEDULER -void Scheduler::debug_log_timer_(const SchedulerItem *item, bool is_static_string, const char *name_cstr, - SchedulerItem::Type type, uint32_t delay, uint64_t now) { +void Scheduler::debug_log_timer_(const SchedulerItem *item, NameType name_type, const char *static_name, + uint32_t hash_or_id, SchedulerItem::Type type, uint32_t delay, uint64_t now) { // Validate static strings in debug mode - if (is_static_string && name_cstr != nullptr) { - validate_static_string(name_cstr); + if (name_type == NameType::STATIC_STRING && static_name != nullptr) { + validate_static_string(static_name); } // Debug logging + SchedulerNameLog name_log; const char *type_str = (type == SchedulerItem::TIMEOUT) ? "timeout" : "interval"; if (type == SchedulerItem::TIMEOUT) { ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()), - name_cstr ? name_cstr : "(null)", type_str, delay); + name_log.format(name_type, static_name, hash_or_id), type_str, delay); } else { ESP_LOGD(TAG, "set_%s(name='%s/%s', %s=%" PRIu32 ", offset=%" PRIu32 ")", type_str, LOG_STR_ARG(item->get_source()), - name_cstr ? name_cstr : "(null)", type_str, delay, + name_log.format(name_type, static_name, hash_or_id), type_str, delay, static_cast(item->get_next_execution() - now)); } } #endif /* ESPHOME_DEBUG_SCHEDULER */ +// Helper to get or create a scheduler item from the pool +// IMPORTANT: Caller must hold the scheduler lock before calling this function. +std::unique_ptr Scheduler::get_item_from_pool_locked_() { + std::unique_ptr item; + if (!this->scheduler_item_pool_.empty()) { + item = std::move(this->scheduler_item_pool_.back()); + this->scheduler_item_pool_.pop_back(); +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Reused item from pool (pool size now: %zu)", this->scheduler_item_pool_.size()); +#endif + } else { + item = make_unique(); +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Allocated new item (pool empty)"); +#endif + } + return item; +} + } // namespace esphome diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 5bf3d19adb..8c2e349180 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -1,9 +1,10 @@ #pragma once #include "esphome/core/defines.h" -#include -#include #include +#include +#include +#include #ifdef ESPHOME_THREAD_MULTI_ATOMICS #include #endif @@ -29,7 +30,9 @@ class Scheduler { template friend class DelayAction; public: - // Public API - accepts std::string for backward compatibility + // std::string overload - deprecated, use const char* or uint32_t instead + // Remove before 2026.7.0 + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function func); /** Set a timeout with a const char* name. @@ -39,14 +42,17 @@ class Scheduler { * - A string literal (e.g., "update") * - A static const char* variable * - A pointer with lifetime >= the scheduled task - * - * For dynamic strings, use the std::string overload instead. */ void set_timeout(Component *component, const char *name, uint32_t timeout, std::function func); + /// Set a timeout with a numeric ID (zero heap allocation) + void set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function func); + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(Component *component, const std::string &name); bool cancel_timeout(Component *component, const char *name); + bool cancel_timeout(Component *component, uint32_t id); + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(Component *component, const std::string &name, uint32_t interval, std::function func); /** Set an interval with a const char* name. @@ -56,19 +62,29 @@ class Scheduler { * - A string literal (e.g., "update") * - A static const char* variable * - A pointer with lifetime >= the scheduled task - * - * For dynamic strings, use the std::string overload instead. */ void set_interval(Component *component, const char *name, uint32_t interval, std::function func); + /// Set an interval with a numeric ID (zero heap allocation) + void set_interval(Component *component, uint32_t id, uint32_t interval, std::function func); + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(Component *component, const std::string &name); bool cancel_interval(Component *component, const char *name); + bool cancel_interval(Component *component, uint32_t id); + + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function func, float backoff_increase_factor = 1.0f); void set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, std::function func, float backoff_increase_factor = 1.0f); + /// Set a retry with a numeric ID (zero heap allocation) + void set_retry(Component *component, uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, + std::function func, float backoff_increase_factor = 1.0f); + + ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_retry(Component *component, const std::string &name); bool cancel_retry(Component *component, const char *name); + bool cancel_retry(Component *component, uint32_t id); // Calculate when the next scheduled item should run // @param now Fresh timestamp from millis() - must not be stale/cached @@ -83,14 +99,22 @@ class Scheduler { void process_to_add(); + // Name storage type discriminator for SchedulerItem + // Used to distinguish between static strings, hashed strings, and numeric IDs + enum class NameType : uint8_t { + STATIC_STRING = 0, // const char* pointer to static/flash storage + HASHED_STRING = 1, // uint32_t FNV-1a hash of a runtime string + NUMERIC_ID = 2 // uint32_t numeric identifier + }; + protected: struct SchedulerItem { // Ordered by size to minimize padding Component *component; - // Optimized name storage using tagged union + // Optimized name storage using tagged union - zero heap allocation union { - const char *static_name; // For string literals (no allocation) - char *dynamic_name; // For allocated strings + const char *static_name; // For STATIC_STRING (string literals, no allocation) + uint32_t hash_or_id; // For HASHED_STRING or NUMERIC_ID } name_; uint32_t interval; // Split time to handle millis() rollover. The scheduler combines the 32-bit millis() @@ -109,19 +133,19 @@ class Scheduler { // Place atomic separately since it can't be packed with bit fields std::atomic remove{false}; - // Bit-packed fields (3 bits used, 5 bits padding in 1 byte) - enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; - bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[]) - bool is_retry : 1; // True if this is a retry timeout - // 5 bits padding -#else - // Single-threaded or multi-threaded without atomics: can pack all fields together // Bit-packed fields (4 bits used, 4 bits padding in 1 byte) enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; + NameType name_type_ : 2; // Discriminator for name_ union (STATIC_STRING, HASHED_STRING, NUMERIC_ID) + bool is_retry : 1; // True if this is a retry timeout + // 4 bits padding +#else + // Single-threaded or multi-threaded without atomics: can pack all fields together + // Bit-packed fields (5 bits used, 3 bits padding in 1 byte) + enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; bool remove : 1; - bool name_is_dynamic : 1; // True if name was dynamically allocated (needs delete[]) - bool is_retry : 1; // True if this is a retry timeout - // 4 bits padding + NameType name_type_ : 2; // Discriminator for name_ union (STATIC_STRING, HASHED_STRING, NUMERIC_ID) + bool is_retry : 1; // True if this is a retry timeout + // 3 bits padding #endif // Constructor @@ -133,19 +157,19 @@ class Scheduler { #ifdef ESPHOME_THREAD_MULTI_ATOMICS // remove is initialized in the member declaration as std::atomic{false} type(TIMEOUT), - name_is_dynamic(false), + name_type_(NameType::STATIC_STRING), is_retry(false) { #else type(TIMEOUT), remove(false), - name_is_dynamic(false), + name_type_(NameType::STATIC_STRING), is_retry(false) { #endif name_.static_name = nullptr; } - // Destructor to clean up dynamic names - ~SchedulerItem() { clear_dynamic_name(); } + // Destructor - no dynamic memory to clean up + ~SchedulerItem() = default; // Delete copy operations to prevent accidental copies SchedulerItem(const SchedulerItem &) = delete; @@ -155,36 +179,31 @@ class Scheduler { SchedulerItem(SchedulerItem &&) = delete; SchedulerItem &operator=(SchedulerItem &&) = delete; - // Helper to get the name regardless of storage type - const char *get_name() const { return name_is_dynamic ? name_.dynamic_name : name_.static_name; } + // Helper to get the static name (only valid for STATIC_STRING type) + const char *get_name() const { return (name_type_ == NameType::STATIC_STRING) ? name_.static_name : nullptr; } - // Helper to clear dynamic name if allocated - void clear_dynamic_name() { - if (name_is_dynamic && name_.dynamic_name) { - delete[] name_.dynamic_name; - name_.dynamic_name = nullptr; - name_is_dynamic = false; - } + // Helper to get the hash or numeric ID (only valid for HASHED_STRING or NUMERIC_ID types) + uint32_t get_name_hash_or_id() const { return (name_type_ != NameType::STATIC_STRING) ? name_.hash_or_id : 0; } + + // Helper to get the name type + NameType get_name_type() const { return name_type_; } + + // Helper to set a static string name (no allocation) + void set_static_name(const char *name) { + name_.static_name = name; + name_type_ = NameType::STATIC_STRING; } - // Helper to set name with proper ownership - void set_name(const char *name, bool make_copy = false) { - // Clean up old dynamic name if any - clear_dynamic_name(); + // Helper to set a hashed string name (hash computed from std::string) + void set_hashed_name(uint32_t hash) { + name_.hash_or_id = hash; + name_type_ = NameType::HASHED_STRING; + } - if (!name) { - // nullptr case - no name provided - name_.static_name = nullptr; - } else if (make_copy) { - // Make a copy for dynamic strings (including empty strings) - size_t len = strlen(name); - name_.dynamic_name = new char[len + 1]; - memcpy(name_.dynamic_name, name, len + 1); - name_is_dynamic = true; - } else { - // Use static string directly (including empty strings) - name_.static_name = name; - } + // Helper to set a numeric ID name + void set_numeric_id(uint32_t id) { + name_.hash_or_id = id; + name_type_ = NameType::NUMERIC_ID; } static bool cmp(const std::unique_ptr &a, const std::unique_ptr &b); @@ -207,12 +226,18 @@ class Scheduler { }; // Common implementation for both timeout and interval - void set_timer_common_(Component *component, SchedulerItem::Type type, bool is_static_string, const void *name_ptr, - uint32_t delay, std::function func, bool is_retry = false, bool skip_cancel = false); + // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id + void set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, const char *static_name, + uint32_t hash_or_id, uint32_t delay, std::function func, bool is_retry = false, + bool skip_cancel = false); // Common implementation for retry - void set_retry_common_(Component *component, bool is_static_string, const void *name_ptr, uint32_t initial_wait_time, - uint8_t max_attempts, std::function func, float backoff_increase_factor); + // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id + void set_retry_common_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, + uint32_t initial_wait_time, uint8_t max_attempts, std::function func, + float backoff_increase_factor); + // Common implementation for cancel_retry + bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); uint64_t millis_64_(uint32_t now); // Cleanup logically deleted items from the scheduler @@ -222,21 +247,22 @@ class Scheduler { // Remove and return the front item from the heap // IMPORTANT: Caller must hold the scheduler lock before calling this function. std::unique_ptr pop_raw_locked_(); + // Get or create a scheduler item from the pool + // IMPORTANT: Caller must hold the scheduler lock before calling this function. + std::unique_ptr get_item_from_pool_locked_(); private: - // Helper to cancel items by name - must be called with lock held - bool cancel_item_locked_(Component *component, const char *name, SchedulerItem::Type type, bool match_retry = false); + // Helper to cancel items - must be called with lock held + // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id + bool cancel_item_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry = false); - // Helper to extract name as const char* from either static string or std::string - inline const char *get_name_cstr_(bool is_static_string, const void *name_ptr) { - return is_static_string ? static_cast(name_ptr) : static_cast(name_ptr)->c_str(); - } + // Common implementation for cancel operations - handles locking + bool cancel_item_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry = false); - // Common implementation for cancel operations - bool cancel_item_(Component *component, bool is_static_string, const void *name_ptr, SchedulerItem::Type type); - - // Helper to check if two scheduler item names match - inline bool HOT names_match_(const char *name1, const char *name2) const { + // Helper to check if two static string names match + inline bool HOT names_match_static_(const char *name1, const char *name2) const { // Check pointer equality first (common for static strings), then string contents // The core ESPHome codebase uses static strings (const char*) for component names, // making pointer comparison effective. The std::string overloads exist only for @@ -245,10 +271,11 @@ class Scheduler { } // Helper function to check if item matches criteria for cancellation + // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // IMPORTANT: Must be called with scheduler lock held inline bool HOT matches_item_locked_(const std::unique_ptr &item, Component *component, - const char *name_cstr, SchedulerItem::Type type, bool match_retry, - bool skip_removed = true) const { + NameType name_type, const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const { // THREAD SAFETY: Check for nullptr first to prevent LoadProhibited crashes. On multi-threaded // platforms, items can be moved out of defer_queue_ during processing, leaving nullptr entries. // PR #11305 added nullptr checks in callers (mark_matching_items_removed_locked_() and @@ -261,7 +288,14 @@ class Scheduler { (match_retry && !item->is_retry)) { return false; } - return this->names_match_(item->get_name(), name_cstr); + // Name type must match + if (item->get_name_type() != name_type) + return false; + // For static strings, compare the string content; for hash/ID, compare the value + if (name_type == NameType::STATIC_STRING) { + return this->names_match_static_(item->get_name(), static_name); + } + return item->get_name_hash_or_id() == hash_or_id; } // Helper to execute a scheduler item @@ -283,7 +317,7 @@ class Scheduler { #ifdef ESPHOME_DEBUG_SCHEDULER // Helper for debug logging in set_timer_common_ - extracted to reduce code size - void debug_log_timer_(const SchedulerItem *item, bool is_static_string, const char *name_cstr, + void debug_log_timer_(const SchedulerItem *item, NameType name_type, const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, uint32_t delay, uint64_t now); #endif /* ESPHOME_DEBUG_SCHEDULER */ @@ -410,11 +444,13 @@ class Scheduler { } // Helper to mark matching items in a container as removed + // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal // IMPORTANT: Must be called with scheduler lock held template - size_t mark_matching_items_removed_locked_(Container &container, Component *component, const char *name_cstr, - SchedulerItem::Type type, bool match_retry) { + size_t mark_matching_items_removed_locked_(Container &container, Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, + bool match_retry) { size_t count = 0; for (auto &item : container) { // Skip nullptr items (can happen in defer_queue_ when items are being processed) @@ -423,8 +459,7 @@ class Scheduler { // the vector can still contain nullptr items from the processing loop. This check prevents crashes. if (!item) continue; - if (this->matches_item_locked_(item, component, name_cstr, type, match_retry)) { - // Mark item for removal (platform-specific) + if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { this->set_item_removed_(item.get(), true); count++; } @@ -433,10 +468,12 @@ class Scheduler { } // Template helper to check if any item in a container matches our criteria + // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // IMPORTANT: Must be called with scheduler lock held template - bool has_cancelled_timeout_in_container_locked_(const Container &container, Component *component, - const char *name_cstr, bool match_retry) const { + bool has_cancelled_timeout_in_container_locked_(const Container &container, Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, + bool match_retry) const { for (const auto &item : container) { // Skip nullptr items (can happen in defer_queue_ when items are being processed) // The defer_queue_ uses index-based processing: items are std::moved out but left in the @@ -445,8 +482,8 @@ class Scheduler { if (!item) continue; if (is_item_removed_(item.get()) && - this->matches_item_locked_(item, component, name_cstr, SchedulerItem::TIMEOUT, match_retry, - /* skip_removed= */ false)) { + this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, + match_retry, /* skip_removed= */ false)) { return true; } } diff --git a/tests/integration/fixtures/scheduler_numeric_id_test.yaml b/tests/integration/fixtures/scheduler_numeric_id_test.yaml new file mode 100644 index 0000000000..bf60f2fda9 --- /dev/null +++ b/tests/integration/fixtures/scheduler_numeric_id_test.yaml @@ -0,0 +1,173 @@ +esphome: + name: scheduler-numeric-id-test + on_boot: + priority: -100 + then: + - logger.log: "Starting scheduler numeric ID tests" + +host: +api: +logger: + level: VERBOSE + +globals: + - id: timeout_counter + type: int + initial_value: '0' + - id: interval_counter + type: int + initial_value: '0' + - id: retry_counter + type: int + initial_value: '0' + - id: tests_done + type: bool + initial_value: 'false' + - id: results_reported + type: bool + initial_value: 'false' + +script: + - id: test_numeric_ids + then: + - logger.log: "Testing numeric ID timeouts and intervals" + - lambda: |- + auto *component1 = id(test_sensor1); + + // Test 1: Numeric ID with set_timeout (uint32_t) + App.scheduler.set_timeout(component1, 1001U, 50, []() { + ESP_LOGI("test", "Numeric timeout 1001 fired"); + id(timeout_counter) += 1; + }); + + // Test 2: Another numeric ID timeout + App.scheduler.set_timeout(component1, 1002U, 100, []() { + ESP_LOGI("test", "Numeric timeout 1002 fired"); + id(timeout_counter) += 1; + }); + + // Test 3: Numeric ID with set_interval + App.scheduler.set_interval(component1, 2001U, 200, []() { + ESP_LOGI("test", "Numeric interval 2001 fired, count: %d", id(interval_counter)); + id(interval_counter) += 1; + if (id(interval_counter) >= 3) { + App.scheduler.cancel_interval(id(test_sensor1), 2001U); + ESP_LOGI("test", "Cancelled numeric interval 2001"); + } + }); + + // Test 4: Cancel timeout with numeric ID + App.scheduler.set_timeout(component1, 3001U, 5000, []() { + ESP_LOGE("test", "ERROR: Timeout 3001 should have been cancelled"); + }); + App.scheduler.cancel_timeout(component1, 3001U); + ESP_LOGI("test", "Cancelled numeric timeout 3001"); + + // Test 5: Multiple timeouts with same numeric ID - only last should execute + for (int i = 0; i < 5; i++) { + App.scheduler.set_timeout(component1, 4001U, 300 + i*10, [i]() { + ESP_LOGI("test", "Duplicate numeric timeout %d fired", i); + id(timeout_counter) += 1; + }); + } + ESP_LOGI("test", "Created 5 timeouts with same numeric ID 4001"); + + // Test 6: Cancel non-existent numeric ID + bool cancelled_nonexistent = App.scheduler.cancel_timeout(component1, 9999U); + ESP_LOGI("test", "Cancel non-existent numeric ID result: %s", + cancelled_nonexistent ? "true (unexpected!)" : "false (expected)"); + + // Test 7: Component method uint32_t overloads + class TestNumericComponent : public Component { + public: + void test_numeric_methods() { + // Test set_timeout with uint32_t ID + this->set_timeout(5001U, 150, []() { + ESP_LOGI("test", "Component numeric timeout 5001 fired"); + id(timeout_counter) += 1; + }); + + // Test set_interval with uint32_t ID + // Capture 'this' pointer so we can cancel with correct component + auto *self = this; + this->set_interval(5002U, 400, [self]() { + ESP_LOGI("test", "Component numeric interval 5002 fired"); + id(interval_counter) += 1; + // Cancel after first fire - must use same component pointer + App.scheduler.cancel_interval(self, 5002U); + }); + } + }; + + static TestNumericComponent test_component; + test_component.test_numeric_methods(); + + // Test 8: Zero ID (edge case) + App.scheduler.set_timeout(component1, 0U, 200, []() { + ESP_LOGI("test", "Numeric timeout with ID 0 fired"); + id(timeout_counter) += 1; + }); + + // Test 9: Max uint32_t ID (edge case) + App.scheduler.set_timeout(component1, 0xFFFFFFFFU, 250, []() { + ESP_LOGI("test", "Numeric timeout with max ID fired"); + id(timeout_counter) += 1; + }); + + // Test 10: set_retry with numeric ID + App.scheduler.set_retry(component1, 6001U, 50, 3, + [](uint8_t retry_countdown) { + id(retry_counter)++; + ESP_LOGI("test", "Numeric retry 6001 attempt %d (countdown=%d)", + id(retry_counter), retry_countdown); + if (id(retry_counter) >= 2) { + ESP_LOGI("test", "Numeric retry 6001 done"); + return RetryResult::DONE; + } + return RetryResult::RETRY; + }); + + // Test 11: cancel_retry with numeric ID + App.scheduler.set_retry(component1, 6002U, 100, 5, + [](uint8_t retry_countdown) { + ESP_LOGE("test", "ERROR: Numeric retry 6002 should have been cancelled"); + return RetryResult::RETRY; + }); + App.scheduler.cancel_retry(component1, 6002U); + ESP_LOGI("test", "Cancelled numeric retry 6002"); + + - id: report_results + then: + - lambda: |- + ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d", + id(timeout_counter), id(interval_counter), id(retry_counter)); + +sensor: + - platform: template + name: Test Sensor 1 + id: test_sensor1 + lambda: return 1.0; + update_interval: never + +interval: + # Run numeric ID tests after boot + - interval: 0.1s + then: + - if: + condition: + lambda: 'return id(tests_done) == false;' + then: + - lambda: 'id(tests_done) = true;' + - script.execute: test_numeric_ids + - logger.log: "Started numeric ID tests" + + # Report results after tests complete + - interval: 0.2s + then: + - if: + condition: + lambda: 'return id(tests_done) && !id(results_reported);' + then: + - lambda: 'id(results_reported) = true;' + - delay: 1.5s + - script.execute: report_results diff --git a/tests/integration/fixtures/scheduler_retry_test.yaml b/tests/integration/fixtures/scheduler_retry_test.yaml index 11fff6c395..ffe9082a69 100644 --- a/tests/integration/fixtures/scheduler_retry_test.yaml +++ b/tests/integration/fixtures/scheduler_retry_test.yaml @@ -43,9 +43,6 @@ globals: - id: static_char_retry_counter type: int initial_value: '0' - - id: mixed_cancel_result - type: bool - initial_value: 'false' # Using different component types for each test to ensure isolation sensor: @@ -271,23 +268,6 @@ script: ESP_LOGI("test", "Static cancel result: %s", result ? "true" : "false"); }); - # Test 10: Mix string and const char* cancel - - logger.log: "=== Test 10: Mixed string/const char* ===" - - lambda: |- - auto *component = id(immediate_done_sensor); - - // Set with std::string - std::string str_name = "mixed_retry"; - App.scheduler.set_retry(component, str_name, 40, 3, - [](uint8_t retry_countdown) { - ESP_LOGI("test", "Mixed retry - should be cancelled"); - return RetryResult::RETRY; - }); - - // Cancel with const char* - id(mixed_cancel_result) = App.scheduler.cancel_retry(component, "mixed_retry"); - ESP_LOGI("test", "Mixed cancel result: %s", id(mixed_cancel_result) ? "true" : "false"); - # Wait for all tests to complete before reporting - delay: 500ms @@ -303,5 +283,4 @@ script: ESP_LOGI("test", "Multiple same name counter: %d (expected 20+)", id(multiple_same_name_counter)); ESP_LOGI("test", "Const char retry counter: %d (expected 1)", id(const_char_retry_counter)); ESP_LOGI("test", "Static char retry counter: %d (expected 1)", id(static_char_retry_counter)); - ESP_LOGI("test", "Mixed cancel result: %s (expected true)", id(mixed_cancel_result) ? "true" : "false"); ESP_LOGI("test", "All retry tests completed"); diff --git a/tests/integration/test_scheduler_numeric_id_test.py b/tests/integration/test_scheduler_numeric_id_test.py new file mode 100644 index 0000000000..510256b9a4 --- /dev/null +++ b/tests/integration/test_scheduler_numeric_id_test.py @@ -0,0 +1,217 @@ +"""Test scheduler numeric ID (uint32_t) overloads.""" + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_scheduler_numeric_id_test( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that scheduler handles numeric IDs (uint32_t) correctly.""" + # Track counts + timeout_count = 0 + interval_count = 0 + retry_count = 0 + + # Events for each test completion + numeric_timeout_1001_fired = asyncio.Event() + numeric_timeout_1002_fired = asyncio.Event() + numeric_interval_2001_fired = asyncio.Event() + numeric_interval_cancelled = asyncio.Event() + numeric_timeout_cancelled = asyncio.Event() + duplicate_timeout_fired = asyncio.Event() + component_timeout_fired = asyncio.Event() + component_interval_fired = asyncio.Event() + zero_id_timeout_fired = asyncio.Event() + max_id_timeout_fired = asyncio.Event() + numeric_retry_done = asyncio.Event() + numeric_retry_cancelled = asyncio.Event() + final_results_logged = asyncio.Event() + + # Track interval counts + numeric_interval_count = 0 + numeric_retry_count = 0 + + def on_log_line(line: str) -> None: + nonlocal timeout_count, interval_count, retry_count + nonlocal numeric_interval_count, numeric_retry_count + + # Strip ANSI color codes + clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line) + + # Check for numeric timeout completions + if "Numeric timeout 1001 fired" in clean_line: + numeric_timeout_1001_fired.set() + timeout_count += 1 + + elif "Numeric timeout 1002 fired" in clean_line: + numeric_timeout_1002_fired.set() + timeout_count += 1 + + # Check for numeric interval + elif "Numeric interval 2001 fired" in clean_line: + match = re.search(r"count: (\d+)", clean_line) + if match: + numeric_interval_count = int(match.group(1)) + numeric_interval_2001_fired.set() + + elif "Cancelled numeric interval 2001" in clean_line: + numeric_interval_cancelled.set() + + elif "Cancelled numeric timeout 3001" in clean_line: + numeric_timeout_cancelled.set() + + # Check for duplicate timeout (only last should fire) + elif "Duplicate numeric timeout" in clean_line: + match = re.search(r"timeout (\d+) fired", clean_line) + if match and match.group(1) == "4": + duplicate_timeout_fired.set() + timeout_count += 1 + + # Check for component method tests + elif "Component numeric timeout 5001 fired" in clean_line: + component_timeout_fired.set() + timeout_count += 1 + + elif "Component numeric interval 5002 fired" in clean_line: + component_interval_fired.set() + interval_count += 1 + + # Check for edge case tests + elif "Numeric timeout with ID 0 fired" in clean_line: + zero_id_timeout_fired.set() + timeout_count += 1 + + elif "Numeric timeout with max ID fired" in clean_line: + max_id_timeout_fired.set() + timeout_count += 1 + + # Check for numeric retry tests + elif "Numeric retry 6001 attempt" in clean_line: + match = re.search(r"attempt (\d+)", clean_line) + if match: + numeric_retry_count = int(match.group(1)) + + elif "Numeric retry 6001 done" in clean_line: + numeric_retry_done.set() + + elif "Cancelled numeric retry 6002" in clean_line: + numeric_retry_cancelled.set() + + # Check for final results + elif "Final results" in clean_line: + match = re.search( + r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+)", clean_line + ) + if match: + timeout_count = int(match.group(1)) + interval_count = int(match.group(2)) + retry_count = int(match.group(3)) + final_results_logged.set() + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + # Verify we can connect + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "scheduler-numeric-id-test" + + # Wait for numeric timeout tests + try: + await asyncio.wait_for(numeric_timeout_1001_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric timeout 1001 did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(numeric_timeout_1002_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric timeout 1002 did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(numeric_interval_2001_fired.wait(), timeout=1.0) + except TimeoutError: + pytest.fail("Numeric interval 2001 did not fire within 1 second") + + try: + await asyncio.wait_for(numeric_interval_cancelled.wait(), timeout=2.0) + except TimeoutError: + pytest.fail("Numeric interval 2001 was not cancelled within 2 seconds") + + # Verify numeric interval ran at least twice + assert numeric_interval_count >= 2, ( + f"Expected numeric interval to run at least 2 times, got {numeric_interval_count}" + ) + + # Verify numeric timeout was cancelled + assert numeric_timeout_cancelled.is_set(), ( + "Numeric timeout 3001 should have been cancelled" + ) + + # Wait for duplicate timeout (only last one should fire) + try: + await asyncio.wait_for(duplicate_timeout_fired.wait(), timeout=1.0) + except TimeoutError: + pytest.fail("Duplicate numeric timeout did not fire within 1 second") + + # Wait for component method tests + try: + await asyncio.wait_for(component_timeout_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Component numeric timeout did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(component_interval_fired.wait(), timeout=1.0) + except TimeoutError: + pytest.fail("Component numeric interval did not fire within 1 second") + + # Wait for edge case tests + try: + await asyncio.wait_for(zero_id_timeout_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Zero ID timeout did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(max_id_timeout_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Max ID timeout did not fire within 0.5 seconds") + + # Wait for numeric retry tests + try: + await asyncio.wait_for(numeric_retry_done.wait(), timeout=1.0) + except TimeoutError: + pytest.fail( + f"Numeric retry 6001 did not complete. Count: {numeric_retry_count}" + ) + + assert numeric_retry_count >= 2, ( + f"Expected at least 2 numeric retry attempts, got {numeric_retry_count}" + ) + + # Verify numeric retry was cancelled + assert numeric_retry_cancelled.is_set(), ( + "Numeric retry 6002 should have been cancelled" + ) + + # Wait for final results + try: + await asyncio.wait_for(final_results_logged.wait(), timeout=3.0) + except TimeoutError: + pytest.fail("Final results were not logged within 3 seconds") + + # Verify results + assert timeout_count >= 6, f"Expected at least 6 timeouts, got {timeout_count}" + assert interval_count >= 3, ( + f"Expected at least 3 interval fires, got {interval_count}" + ) + assert retry_count >= 2, ( + f"Expected at least 2 retry attempts, got {retry_count}" + ) diff --git a/tests/integration/test_scheduler_retry_test.py b/tests/integration/test_scheduler_retry_test.py index c04b7197c9..910034e5bb 100644 --- a/tests/integration/test_scheduler_retry_test.py +++ b/tests/integration/test_scheduler_retry_test.py @@ -25,7 +25,6 @@ async def test_scheduler_retry_test( multiple_name_done = asyncio.Event() const_char_done = asyncio.Event() static_char_done = asyncio.Event() - mixed_cancel_done = asyncio.Event() test_complete = asyncio.Event() # Track retry counts @@ -42,14 +41,13 @@ async def test_scheduler_retry_test( # Track specific test results cancel_result = None empty_cancel_result = None - mixed_cancel_result = None backoff_intervals = [] def on_log_line(line: str) -> None: nonlocal simple_retry_count, backoff_retry_count, immediate_done_count nonlocal cancel_retry_count, empty_name_retry_count, component_retry_count nonlocal multiple_name_count, const_char_retry_count, static_char_retry_count - nonlocal cancel_result, empty_cancel_result, mixed_cancel_result + nonlocal cancel_result, empty_cancel_result # Strip ANSI color codes clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line) @@ -129,11 +127,6 @@ async def test_scheduler_retry_test( # This is part of test 9, but we don't track it separately pass - # Mixed cancel test - elif "Mixed cancel result:" in clean_line: - mixed_cancel_result = "true" in clean_line - mixed_cancel_done.set() - # Test completion elif "All retry tests completed" in clean_line: test_complete.set() @@ -279,16 +272,6 @@ async def test_scheduler_retry_test( f"Expected 1 static char retry call, got {static_char_retry_count}" ) - # Wait for mixed cancel test - try: - await asyncio.wait_for(mixed_cancel_done.wait(), timeout=1.0) - except TimeoutError: - pytest.fail("Mixed cancel test did not complete") - - assert mixed_cancel_result is True, ( - "Mixed string/const char cancel should have succeeded" - ) - # Wait for test completion try: await asyncio.wait_for(test_complete.wait(), timeout=1.0) From d6fa1d6e5fe8db861e774b82165655cca4bbe7a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 14 Jan 2026 04:17:47 -1000 Subject: [PATCH 0107/2030] [ethernet_info] Convert to event-driven IP state listener pattern (#13203) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ethernet/__init__.py | 25 +++++++ .../ethernet/ethernet_component.cpp | 23 +++++++ .../components/ethernet/ethernet_component.h | 27 ++++++++ .../ethernet_info_text_sensor.cpp | 36 ++++++++++ .../ethernet_info/ethernet_info_text_sensor.h | 65 ++++++------------- .../components/ethernet_info/text_sensor.py | 28 ++++---- esphome/core/defines.h | 2 + 7 files changed, 148 insertions(+), 58 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index f140f395e4..1f2fe61fe1 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -61,6 +61,21 @@ DEPENDENCIES = ["esp32"] AUTO_LOAD = ["network"] LOGGER = logging.getLogger(__name__) +# Key for tracking IP state listener count in CORE.data +ETHERNET_IP_STATE_LISTENERS_KEY = "ethernet_ip_state_listeners" + + +def request_ethernet_ip_state_listener() -> None: + """Request an IP state listener slot. + + Components that implement EthernetIPStateListener should call this + in their to_code() to register for IP state notifications. + """ + CORE.data[ETHERNET_IP_STATE_LISTENERS_KEY] = ( + CORE.data.get(ETHERNET_IP_STATE_LISTENERS_KEY, 0) + 1 + ) + + # RMII pins that are hardcoded on ESP32 classic and cannot be changed # These pins are used by the internal Ethernet MAC when using RMII PHYs ESP32_RMII_FIXED_PINS = { @@ -411,6 +426,8 @@ async def to_code(config): if CORE.using_arduino: cg.add_library("WiFi", None) + CORE.add_job(final_step) + def _final_validate_rmii_pins(config: ConfigType) -> None: """Validate that RMII pins are not used by other components.""" @@ -467,3 +484,11 @@ def _final_validate(config: ConfigType) -> ConfigType: FINAL_VALIDATE_SCHEMA = _final_validate + + +@coroutine_with_priority(CoroPriority.FINAL) +async def final_step(): + """Final code generation step to configure optional Ethernet features.""" + if ip_state_count := CORE.data.get(ETHERNET_IP_STATE_LISTENERS_KEY, 0): + cg.add_define("USE_ETHERNET_IP_STATE_LISTENERS") + cg.add_define("ESPHOME_ETHERNET_IP_STATE_LISTENERS", ip_state_count) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 896c5cc874..70f8ce1204 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -472,6 +472,12 @@ void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base break; case ETHERNET_EVENT_CONNECTED: event_name = "ETH connected"; + // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here +#if defined(USE_ETHERNET_IP_STATE_LISTENERS) && defined(USE_ETHERNET_MANUAL_IP) + if (global_eth_component->manual_ip_.has_value()) { + global_eth_component->notify_ip_state_listeners_(); + } +#endif break; case ETHERNET_EVENT_DISCONNECTED: event_name = "ETH disconnected"; @@ -498,6 +504,9 @@ void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_b global_eth_component->connected_ = true; global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes #endif /* USE_NETWORK_IPV6 */ +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + global_eth_component->notify_ip_state_listeners_(); +#endif } #if USE_NETWORK_IPV6 @@ -514,9 +523,23 @@ void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_ global_eth_component->connected_ = global_eth_component->got_ipv4_address_; global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes #endif +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + global_eth_component->notify_ip_state_listeners_(); +#endif } #endif /* USE_NETWORK_IPV6 */ +#ifdef USE_ETHERNET_IP_STATE_LISTENERS +void EthernetComponent::notify_ip_state_listeners_() { + auto ips = this->get_ip_addresses(); + auto dns1 = this->get_dns_address(0); + auto dns2 = this->get_dns_address(1); + for (auto *listener : this->ip_state_listeners_) { + listener->on_ip_state(ips, dns1, dns2); + } +} +#endif // USE_ETHERNET_IP_STATE_LISTENERS + void EthernetComponent::finish_connect_() { #if USE_NETWORK_IPV6 // Retry IPv6 link-local setup if it failed during initial connect diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 490a9d026e..34380047d1 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -17,6 +17,22 @@ namespace esphome { namespace ethernet { +#ifdef USE_ETHERNET_IP_STATE_LISTENERS +/** Listener interface for Ethernet IP state changes. + * + * Components can implement this interface to receive IP address updates + * without the overhead of std::function callbacks or polling. + * + * @note Components must call ethernet.request_ethernet_ip_state_listener() in their + * Python to_code() to register for this listener type. + */ +class EthernetIPStateListener { + public: + virtual void on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, + const network::IPAddress &dns2) = 0; +}; +#endif // USE_ETHERNET_IP_STATE_LISTENERS + enum EthernetType : uint8_t { ETHERNET_TYPE_UNKNOWN = 0, ETHERNET_TYPE_LAN8720, @@ -99,12 +115,19 @@ class EthernetComponent : public Component { eth_speed_t get_link_speed(); bool powerdown(); +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + void add_ip_state_listener(EthernetIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); } +#endif + protected: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); #if LWIP_IPV6 static void got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); #endif /* LWIP_IPV6 */ +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + void notify_ip_state_listeners_(); +#endif void start_connect_(); void finish_connect_(); @@ -163,6 +186,10 @@ class EthernetComponent : public Component { esp_eth_phy_t *phy_{nullptr}; optional> fixed_mac_; +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + StaticVector ip_state_listeners_; +#endif + private: // Stores a pointer to a string literal (static storage duration). // ONLY set from Python-generated code with string literals - never dynamic strings. diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index 35e18c7de5..72ce9c86e2 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp @@ -7,8 +7,44 @@ namespace esphome::ethernet_info { static const char *const TAG = "ethernet_info"; +#ifdef USE_ETHERNET_IP_STATE_LISTENERS +void IPAddressEthernetInfo::setup() { ethernet::global_eth_component->add_ip_state_listener(this); } + void IPAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo IPAddress", this); } + +void IPAddressEthernetInfo::on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, + const network::IPAddress &dns2) { + char buf[network::IP_ADDRESS_BUFFER_SIZE]; + ips[0].str_to(buf); + this->publish_state(buf); + uint8_t sensor = 0; + for (const auto &ip : ips) { + if (ip.is_set()) { + if (this->ip_sensors_[sensor] != nullptr) { + ip.str_to(buf); + this->ip_sensors_[sensor]->publish_state(buf); + } + sensor++; + } + } +} + +void DNSAddressEthernetInfo::setup() { ethernet::global_eth_component->add_ip_state_listener(this); } + void DNSAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo DNS Address", this); } + +void DNSAddressEthernetInfo::on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, + const network::IPAddress &dns2) { + // IP_ADDRESS_BUFFER_SIZE (40) = max IP (39) + null; space reuses first null's slot + char buf[network::IP_ADDRESS_BUFFER_SIZE * 2]; + dns1.str_to(buf); + size_t len1 = strlen(buf); + buf[len1] = ' '; + dns2.str_to(buf + len1 + 1); + this->publish_state(buf); +} +#endif // USE_ETHERNET_IP_STATE_LISTENERS + void MACAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo MAC Address", this); } } // namespace esphome::ethernet_info diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index 5b858b772f..912a39a83f 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.h +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.h @@ -8,64 +8,37 @@ namespace esphome::ethernet_info { -class IPAddressEthernetInfo : public PollingComponent, public text_sensor::TextSensor { +#ifdef USE_ETHERNET_IP_STATE_LISTENERS +class IPAddressEthernetInfo final : public Component, + public text_sensor::TextSensor, + public ethernet::EthernetIPStateListener { public: - void update() override { - auto ips = ethernet::global_eth_component->get_ip_addresses(); - if (ips != this->last_ips_) { - this->last_ips_ = ips; - char buf[network::IP_ADDRESS_BUFFER_SIZE]; - ips[0].str_to(buf); - this->publish_state(buf); - uint8_t sensor = 0; - for (auto &ip : ips) { - if (ip.is_set()) { - if (this->ip_sensors_[sensor] != nullptr) { - ip.str_to(buf); - this->ip_sensors_[sensor]->publish_state(buf); - } - sensor++; - } - } - } - } - - float get_setup_priority() const override { return setup_priority::ETHERNET; } + void setup() override; void dump_config() override; void add_ip_sensors(uint8_t index, text_sensor::TextSensor *s) { this->ip_sensors_[index] = s; } + // EthernetIPStateListener interface + void on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, + const network::IPAddress &dns2) override; + protected: - network::IPAddresses last_ips_; - std::array ip_sensors_; + std::array ip_sensors_{}; }; -class DNSAddressEthernetInfo : public PollingComponent, public text_sensor::TextSensor { +class DNSAddressEthernetInfo final : public Component, + public text_sensor::TextSensor, + public ethernet::EthernetIPStateListener { public: - void update() override { - auto dns1 = ethernet::global_eth_component->get_dns_address(0); - auto dns2 = ethernet::global_eth_component->get_dns_address(1); - - if (dns1 != this->last_dns1_ || dns2 != this->last_dns2_) { - this->last_dns1_ = dns1; - this->last_dns2_ = dns2; - // IP_ADDRESS_BUFFER_SIZE (40) = max IP (39) + null; space reuses first null's slot - char buf[network::IP_ADDRESS_BUFFER_SIZE * 2]; - dns1.str_to(buf); - size_t len1 = strlen(buf); - buf[len1] = ' '; - dns2.str_to(buf + len1 + 1); - this->publish_state(buf); - } - } - float get_setup_priority() const override { return setup_priority::ETHERNET; } + void setup() override; void dump_config() override; - protected: - network::IPAddress last_dns1_; - network::IPAddress last_dns2_; + // EthernetIPStateListener interface + void on_ip_state(const network::IPAddresses &ips, const network::IPAddress &dns1, + const network::IPAddress &dns2) override; }; +#endif // USE_ETHERNET_IP_STATE_LISTENERS -class MACAddressEthernetInfo : public Component, public text_sensor::TextSensor { +class MACAddressEthernetInfo final : public Component, public text_sensor::TextSensor { public: void setup() override { char buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; diff --git a/esphome/components/ethernet_info/text_sensor.py b/esphome/components/ethernet_info/text_sensor.py index 31da516e44..8c20cf332c 100644 --- a/esphome/components/ethernet_info/text_sensor.py +++ b/esphome/components/ethernet_info/text_sensor.py @@ -1,5 +1,5 @@ import esphome.codegen as cg -from esphome.components import text_sensor +from esphome.components import ethernet, text_sensor import esphome.config_validation as cv from esphome.const import ( CONF_DNS_ADDRESS, @@ -13,24 +13,22 @@ DEPENDENCIES = ["ethernet"] ethernet_info_ns = cg.esphome_ns.namespace("ethernet_info") IPAddressEthernetInfo = ethernet_info_ns.class_( - "IPAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent + "IPAddressEthernetInfo", text_sensor.TextSensor, cg.Component ) DNSAddressEthernetInfo = ethernet_info_ns.class_( - "DNSAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent + "DNSAddressEthernetInfo", text_sensor.TextSensor, cg.Component ) MACAddressEthernetInfo = ethernet_info_ns.class_( - "MACAddressEthernetInfo", text_sensor.TextSensor, cg.PollingComponent + "MACAddressEthernetInfo", text_sensor.TextSensor, cg.Component ) CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema( IPAddressEthernetInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC - ) - .extend(cv.polling_component_schema("1s")) - .extend( + ).extend( { cv.Optional(f"address_{x}"): text_sensor.text_sensor_schema( entity_category=ENTITY_CATEGORY_DIAGNOSTIC, @@ -40,7 +38,7 @@ 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 ), @@ -49,6 +47,12 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): + # Request Ethernet IP state listener slots - one per sensor type + if CONF_IP_ADDRESS in config: + ethernet.request_ethernet_ip_state_listener() + if CONF_DNS_ADDRESS in config: + ethernet.request_ethernet_ip_state_listener() + if conf := config.get(CONF_IP_ADDRESS): ip_info = await text_sensor.new_text_sensor(config[CONF_IP_ADDRESS]) await cg.register_component(ip_info, config[CONF_IP_ADDRESS]) @@ -57,8 +61,8 @@ async def to_code(config): sens = await text_sensor.new_text_sensor(sensor_conf) cg.add(ip_info.add_ip_sensors(x, sens)) 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]) + dns_info = await text_sensor.new_text_sensor(conf) + await cg.register_component(dns_info, conf) 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]) + mac_info = await text_sensor.new_text_sensor(conf) + await cg.register_component(mac_info, conf) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index bb40cd4ad1..c229d1df7d 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -238,6 +238,8 @@ #define USE_ETHERNET #define USE_ETHERNET_KSZ8081 #define USE_ETHERNET_MANUAL_IP +#define USE_ETHERNET_IP_STATE_LISTENERS +#define ESPHOME_ETHERNET_IP_STATE_LISTENERS 2 #endif #ifdef USE_ESP32 From 068b497b9b6a46136eb3b69900c53f930d4dfd0e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 14 Jan 2026 04:18:17 -1000 Subject: [PATCH 0108/2030] [web_server] Store method/domain comparison strings in flash on ESP8266 (#13205) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/web_server/web_server.cpp | 89 ++++++++++---------- esphome/components/web_server/web_server.h | 6 ++ esphome/core/string_ref.h | 21 +++++ 3 files changed, 72 insertions(+), 44 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 76a516d90f..0525c93096 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1,6 +1,7 @@ #include "web_server.h" #ifdef USE_WEBSERVER #include "esphome/components/json/json_util.h" +#include "esphome/core/progmem.h" #include "esphome/components/network/util.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" @@ -679,11 +680,11 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM enum SwitchAction { NONE, TOGGLE, TURN_ON, TURN_OFF }; SwitchAction action = NONE; - if (match.method_equals("toggle")) { + if (match.method_equals(ESPHOME_F("toggle"))) { action = TOGGLE; - } else if (match.method_equals("turn_on")) { + } else if (match.method_equals(ESPHOME_F("turn_on"))) { action = TURN_ON; - } else if (match.method_equals("turn_off")) { + } else if (match.method_equals(ESPHOME_F("turn_off"))) { action = TURN_OFF; } @@ -741,7 +742,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM auto detail = get_request_detail(request); std::string data = this->button_json_(obj, detail); request->send(200, "application/json", data.c_str()); - } else if (match.method_equals("press")) { + } else if (match.method_equals(ESPHOME_F("press"))) { this->defer([obj]() { obj->press(); }); request->send(200); return; @@ -829,12 +830,12 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc auto detail = get_request_detail(request); std::string data = this->fan_json_(obj, detail); request->send(200, "application/json", data.c_str()); - } else if (match.method_equals("toggle")) { + } else if (match.method_equals(ESPHOME_F("toggle"))) { this->defer([obj]() { obj->toggle().perform(); }); request->send(200); } else { - bool is_on = match.method_equals("turn_on"); - bool is_off = match.method_equals("turn_off"); + bool is_on = match.method_equals(ESPHOME_F("turn_on")); + bool is_off = match.method_equals(ESPHOME_F("turn_off")); if (!is_on && !is_off) { request->send(404); return; @@ -910,12 +911,12 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa auto detail = get_request_detail(request); std::string data = this->light_json_(obj, detail); request->send(200, "application/json", data.c_str()); - } else if (match.method_equals("toggle")) { + } else if (match.method_equals(ESPHOME_F("toggle"))) { this->defer([obj]() { obj->toggle().perform(); }); request->send(200); } else { - bool is_on = match.method_equals("turn_on"); - bool is_off = match.method_equals("turn_off"); + bool is_on = match.method_equals(ESPHOME_F("turn_on")); + bool is_off = match.method_equals(ESPHOME_F("turn_off")); if (!is_on && !is_off) { request->send(404); return; @@ -1014,7 +1015,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa } } - if (!found && !match.method_equals("set")) { + if (!found && !match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1080,7 +1081,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1147,7 +1148,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1211,7 +1212,7 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1274,7 +1275,7 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1340,7 +1341,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1398,7 +1399,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1457,7 +1458,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1613,11 +1614,11 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat enum LockAction { NONE, LOCK, UNLOCK, OPEN }; LockAction action = NONE; - if (match.method_equals("lock")) { + if (match.method_equals(ESPHOME_F("lock"))) { action = LOCK; - } else if (match.method_equals("unlock")) { + } else if (match.method_equals(ESPHOME_F("unlock"))) { action = UNLOCK; - } else if (match.method_equals("open")) { + } else if (match.method_equals(ESPHOME_F("open"))) { action = OPEN; } @@ -1706,7 +1707,7 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa } } - if (!found && !match.method_equals("set")) { + if (!found && !match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -1849,7 +1850,7 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons request->send(200, "application/json", data.c_str()); return; } - if (!match.method_equals("set")) { + if (!match.method_equals(ESPHOME_F("set"))) { request->send(404); return; } @@ -2029,7 +2030,7 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM return; } - if (!match.method_equals("install")) { + if (!match.method_equals(ESPHOME_F("install"))) { request->send(404); return; } @@ -2244,102 +2245,102 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { if (false) { // Start chain for else-if macro pattern } #ifdef USE_SENSOR - else if (match.domain_equals("sensor")) { + else if (match.domain_equals(ESPHOME_F("sensor"))) { this->handle_sensor_request(request, match); } #endif #ifdef USE_SWITCH - else if (match.domain_equals("switch")) { + else if (match.domain_equals(ESPHOME_F("switch"))) { this->handle_switch_request(request, match); } #endif #ifdef USE_BUTTON - else if (match.domain_equals("button")) { + else if (match.domain_equals(ESPHOME_F("button"))) { this->handle_button_request(request, match); } #endif #ifdef USE_BINARY_SENSOR - else if (match.domain_equals("binary_sensor")) { + else if (match.domain_equals(ESPHOME_F("binary_sensor"))) { this->handle_binary_sensor_request(request, match); } #endif #ifdef USE_FAN - else if (match.domain_equals("fan")) { + else if (match.domain_equals(ESPHOME_F("fan"))) { this->handle_fan_request(request, match); } #endif #ifdef USE_LIGHT - else if (match.domain_equals("light")) { + else if (match.domain_equals(ESPHOME_F("light"))) { this->handle_light_request(request, match); } #endif #ifdef USE_TEXT_SENSOR - else if (match.domain_equals("text_sensor")) { + else if (match.domain_equals(ESPHOME_F("text_sensor"))) { this->handle_text_sensor_request(request, match); } #endif #ifdef USE_COVER - else if (match.domain_equals("cover")) { + else if (match.domain_equals(ESPHOME_F("cover"))) { this->handle_cover_request(request, match); } #endif #ifdef USE_NUMBER - else if (match.domain_equals("number")) { + else if (match.domain_equals(ESPHOME_F("number"))) { this->handle_number_request(request, match); } #endif #ifdef USE_DATETIME_DATE - else if (match.domain_equals("date")) { + else if (match.domain_equals(ESPHOME_F("date"))) { this->handle_date_request(request, match); } #endif #ifdef USE_DATETIME_TIME - else if (match.domain_equals("time")) { + else if (match.domain_equals(ESPHOME_F("time"))) { this->handle_time_request(request, match); } #endif #ifdef USE_DATETIME_DATETIME - else if (match.domain_equals("datetime")) { + else if (match.domain_equals(ESPHOME_F("datetime"))) { this->handle_datetime_request(request, match); } #endif #ifdef USE_TEXT - else if (match.domain_equals("text")) { + else if (match.domain_equals(ESPHOME_F("text"))) { this->handle_text_request(request, match); } #endif #ifdef USE_SELECT - else if (match.domain_equals("select")) { + else if (match.domain_equals(ESPHOME_F("select"))) { this->handle_select_request(request, match); } #endif #ifdef USE_CLIMATE - else if (match.domain_equals("climate")) { + else if (match.domain_equals(ESPHOME_F("climate"))) { this->handle_climate_request(request, match); } #endif #ifdef USE_LOCK - else if (match.domain_equals("lock")) { + else if (match.domain_equals(ESPHOME_F("lock"))) { this->handle_lock_request(request, match); } #endif #ifdef USE_VALVE - else if (match.domain_equals("valve")) { + else if (match.domain_equals(ESPHOME_F("valve"))) { this->handle_valve_request(request, match); } #endif #ifdef USE_ALARM_CONTROL_PANEL - else if (match.domain_equals("alarm_control_panel")) { + else if (match.domain_equals(ESPHOME_F("alarm_control_panel"))) { this->handle_alarm_control_panel_request(request, match); } #endif #ifdef USE_UPDATE - else if (match.domain_equals("update")) { + else if (match.domain_equals(ESPHOME_F("update"))) { this->handle_update_request(request, match); } #endif #ifdef USE_WATER_HEATER - else if (match.domain_equals("water_heater")) { + else if (match.domain_equals(ESPHOME_F("water_heater"))) { this->handle_water_heater_request(request, match); } #endif diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 55fa89679e..91625476f4 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -62,6 +62,12 @@ struct UrlMatch { bool domain_equals(const char *str) const { return this->domain == str; } bool method_equals(const char *str) const { return this->method == str; } +#ifdef USE_ESP8266 + // Overloads for flash strings on ESP8266 + bool domain_equals(const __FlashStringHelper *str) const { return this->domain == str; } + bool method_equals(const __FlashStringHelper *str) const { return this->method == str; } +#endif + /// Match entity by name first, then fall back to object_id with deprecation warning /// Returns EntityMatchResult with match status and whether action segment is empty EntityMatchResult match_entity(EntityBase *entity) const; diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index 505fdd906a..44ca79c81b 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -11,6 +11,10 @@ #include "esphome/components/json/json_util.h" #endif // USE_JSON +#ifdef USE_ESP8266 +#include +#endif // USE_ESP8266 + namespace esphome { /** @@ -107,6 +111,23 @@ inline bool operator!=(const StringRef &lhs, const char *rhs) { return !(lhs == inline bool operator!=(const char *lhs, const StringRef &rhs) { return !(rhs == lhs); } +#ifdef USE_ESP8266 +inline bool operator==(const StringRef &lhs, const __FlashStringHelper *rhs) { + PGM_P p = reinterpret_cast(rhs); + size_t rhs_len = strlen_P(p); + if (lhs.size() != rhs_len) { + return false; + } + return memcmp_P(lhs.c_str(), p, rhs_len) == 0; +} + +inline bool operator==(const __FlashStringHelper *lhs, const StringRef &rhs) { return rhs == lhs; } + +inline bool operator!=(const StringRef &lhs, const __FlashStringHelper *rhs) { return !(lhs == rhs); } + +inline bool operator!=(const __FlashStringHelper *lhs, const StringRef &rhs) { return !(rhs == lhs); } +#endif // USE_ESP8266 + inline bool operator<(const StringRef &lhs, const StringRef &rhs) { return std::lexicographical_compare(std::begin(lhs), std::end(lhs), std::begin(rhs), std::end(rhs)); } From 66b4af1777ad1c29b7eab7850acfbe1f3b4b13e4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:19:45 -0500 Subject: [PATCH 0109/2030] Bump version to 2026.1.0b1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 503979b61e..e98eac6aa5 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0-dev +PROJECT_NUMBER = 2026.1.0b1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 7a18428a61..95ccfb9dee 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0-dev" +__version__ = "2026.1.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f44036310cab452c69cbf816837fdfc9203535c3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:19:45 -0500 Subject: [PATCH 0110/2030] Bump version to 2026.2.0-dev --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 503979b61e..efc2f464e3 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0-dev +PROJECT_NUMBER = 2026.2.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 7a18428a61..c88d5811b4 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0-dev" +__version__ = "2026.2.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f1e5d3a39ae3213ba8f175c21236b65829038e7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:40:26 -1000 Subject: [PATCH 0111/2030] Bump resvg-py from 0.2.5 to 0.2.6 (#13211) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9994148cf6..a707fda059 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,7 @@ ruamel.yaml==0.19.1 # dashboard_import ruamel.yaml.clib==0.2.15 # dashboard_import esphome-glyphsets==0.2.0 pillow==11.3.0 -resvg-py==0.2.5 +resvg-py==0.2.6 freetype-py==2.5.1 jinja2==3.1.6 bleak==2.1.1 From 03f3deff41bb747b60398cf1ff9c5c8888136550 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 14 Jan 2026 15:24:42 -1000 Subject: [PATCH 0112/2030] [lvgl] Use stack buffer for event code formatting, document justified str_sprintf usage (#13220) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/lvgl/lv_validation.py | 1 + esphome/components/lvgl/lvgl_esphome.cpp | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 947e44b131..3c1838219c 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -413,6 +413,7 @@ class TextValidator(LValidator): str_args = [str(x) for x in value[CONF_ARGS]] arg_expr = cg.RawExpression(",".join(str_args)) format_str = cpp_string_escape(format_str) + # str_sprintf justified: user-defined format, can't optimize without permanent RAM cost sprintf_str = f"str_sprintf({format_str}, {arg_expr}).c_str()" if nanval := value.get(CONF_IF_NAN): nanval = cpp_string_escape(nanval) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 50dba94a2b..bb373abb88 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -65,7 +65,10 @@ std::string lv_event_code_name_for(uint8_t event_code) { if (event_code < sizeof(EVENT_NAMES) / sizeof(EVENT_NAMES[0])) { return EVENT_NAMES[event_code]; } - return str_sprintf("%2d", event_code); + // max 4 bytes: "%u" with uint8_t (max 255, 3 digits) + null + char buf[4]; + snprintf(buf, sizeof(buf), "%u", event_code); + return buf; } static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { From 9da2c08f363df712eb601cde4eebf25eebfc37f4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:27:26 +1100 Subject: [PATCH 0113/2030] [image] Correctly handle dimensions in physical units (#13209) --- esphome/components/image/__init__.py | 13 ++--- .../image/config/mm_dimensions.svg | 5 ++ tests/component_tests/image/test_init.py | 55 ++++++++++++++++++- 3 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 tests/component_tests/image/config/mm_dimensions.svg diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 3f8d909824..6ff75d7709 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -665,15 +665,10 @@ async def write_image(config, all_frames=False): if is_svg_file(path): import resvg_py - if resize: - width, height = resize - # resvg-py allows rendering by width/height directly - image_data = resvg_py.svg_to_bytes( - svg_path=str(path), width=int(width), height=int(height) - ) - else: - # Default size - image_data = resvg_py.svg_to_bytes(svg_path=str(path)) + resize = resize or (None, None) + image_data = resvg_py.svg_to_bytes( + svg_path=str(path), width=resize[0], height=resize[1], dpi=100 + ) # Convert bytes to Pillow Image image = Image.open(io.BytesIO(image_data)) diff --git a/tests/component_tests/image/config/mm_dimensions.svg b/tests/component_tests/image/config/mm_dimensions.svg new file mode 100644 index 0000000000..bb64433a4d --- /dev/null +++ b/tests/component_tests/image/config/mm_dimensions.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/component_tests/image/test_init.py b/tests/component_tests/image/test_init.py index 930bbac8d1..c9481a0e1d 100644 --- a/tests/component_tests/image/test_init.py +++ b/tests/component_tests/image/test_init.py @@ -5,17 +5,21 @@ from __future__ import annotations from collections.abc import Callable from pathlib import Path from typing import Any +from unittest.mock import MagicMock, patch import pytest from esphome import config_validation as cv from esphome.components.image import ( + CONF_INVERT_ALPHA, + CONF_OPAQUE, CONF_TRANSPARENCY, CONFIG_SCHEMA, get_all_image_metadata, get_image_metadata, + write_image, ) -from esphome.const import CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE +from esphome.const import CONF_DITHER, CONF_FILE, CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE from esphome.core import CORE @@ -350,3 +354,52 @@ def test_get_all_image_metadata_empty() -> None: "get_all_image_metadata should always return a dict" ) # Length could be 0 or more depending on what's in CORE at test time + + +@pytest.fixture +def mock_progmem_array(): + """Mock progmem_array to avoid needing a proper ID object in tests.""" + with patch("esphome.components.image.cg.progmem_array") as mock_progmem: + mock_progmem.return_value = MagicMock() + yield mock_progmem + + +@pytest.mark.asyncio +async def test_svg_with_mm_dimensions_succeeds( + component_config_path: Callable[[str], Path], + mock_progmem_array: MagicMock, +) -> None: + """Test that SVG files with dimensions in mm are successfully processed.""" + # Create a config for write_image without CONF_RESIZE + config = { + CONF_FILE: component_config_path("mm_dimensions.svg"), + CONF_TYPE: "BINARY", + CONF_TRANSPARENCY: CONF_OPAQUE, + CONF_DITHER: "NONE", + CONF_INVERT_ALPHA: False, + CONF_RAW_DATA_ID: "test_raw_data_id", + } + + # This should succeed without raising an error + result = await write_image(config) + + # Verify that write_image returns the expected tuple + assert isinstance(result, tuple), "write_image should return a tuple" + assert len(result) == 6, "write_image should return 6 values" + + prog_arr, width, height, image_type, trans_value, frame_count = result + + # Verify the dimensions are positive integers + # At 100 DPI, 10mm = ~39 pixels (10mm * 100dpi / 25.4mm_per_inch) + assert isinstance(width, int), "Width should be an integer" + assert isinstance(height, int), "Height should be an integer" + assert width > 0, "Width should be positive" + assert height > 0, "Height should be positive" + assert frame_count == 1, "Single image should have frame_count of 1" + # Verify we got reasonable dimensions from the mm-based SVG + assert 30 < width < 50, ( + f"Width should be around 39 pixels for 10mm at 100dpi, got {width}" + ) + assert 30 < height < 50, ( + f"Height should be around 39 pixels for 10mm at 100dpi, got {height}" + ) From 78aee4f49815f970d8ce427bd7e2c1db96f5231b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 14 Jan 2026 19:48:55 -1000 Subject: [PATCH 0114/2030] [web_server] Remove unused button_state_json_generator (#13235) --- esphome/components/web_server/web_server.cpp | 3 --- esphome/components/web_server/web_server.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 0525c93096..cf984ea247 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -753,9 +753,6 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } -std::string WebServer::button_state_json_generator(WebServer *web_server, void *source) { - return web_server->button_json_((button::Button *) (source), DETAIL_STATE); -} std::string WebServer::button_all_json_generator(WebServer *web_server, void *source) { return web_server->button_json_((button::Button *) (source), DETAIL_ALL); } diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 91625476f4..b1a495ebef 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -295,7 +295,7 @@ class WebServer : public Controller, /// Handle a button request under '/button//press'. void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string button_state_json_generator(WebServer *web_server, void *source); + // Buttons are stateless, so there is no button_state_json_generator static std::string button_all_json_generator(WebServer *web_server, void *source); #endif From 49c881d067ac901c0a24d1dee5d4d053d08f93be Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 00:13:05 -1000 Subject: [PATCH 0115/2030] [core] Optimize and normalize entity state publishing logs with >> format (#13236) --- .../components/alarm_control_panel/alarm_control_panel.cpp | 3 ++- esphome/components/binary_sensor/binary_sensor.cpp | 2 +- esphome/components/climate/climate.cpp | 2 +- esphome/components/cover/cover.cpp | 2 +- esphome/components/datetime/date_entity.cpp | 2 +- esphome/components/datetime/datetime_entity.cpp | 4 ++-- esphome/components/datetime/time_entity.cpp | 3 +-- esphome/components/event/event.cpp | 2 +- esphome/components/fan/fan.cpp | 2 +- esphome/components/lock/lock.cpp | 2 +- esphome/components/number/number.cpp | 2 +- esphome/components/select/select.cpp | 2 +- esphome/components/sensor/sensor.cpp | 4 ++-- esphome/components/switch/switch.cpp | 2 +- esphome/components/text/text.cpp | 4 ++-- esphome/components/text_sensor/text_sensor.cpp | 2 +- esphome/components/update/update_entity.cpp | 2 +- esphome/components/valve/valve.cpp | 2 +- esphome/components/water_heater/water_heater.cpp | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 89c0908a74..248b5065ad 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -31,7 +31,8 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { this->last_update_ = millis(); if (state != this->current_state_) { auto prev_state = this->current_state_; - ESP_LOGD(TAG, "Set state to: %s, previous: %s", LOG_STR_ARG(alarm_control_panel_state_to_string(state)), + ESP_LOGD(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(), + LOG_STR_ARG(alarm_control_panel_state_to_string(state)), LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state))); this->current_state_ = state; // Single state callback - triggers check get_state() for specific states diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index 86b7350aa8..4fe2a019e0 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -44,7 +44,7 @@ bool BinarySensor::set_new_state(const optional &new_state) { #if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_binary_sensor_update(this); #endif - ESP_LOGD(TAG, "'%s': %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); + ESP_LOGD(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); return true; } return false; diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 7611d33cbf..816bd5dfcb 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -436,7 +436,7 @@ void Climate::save_state_() { } void Climate::publish_state() { - ESP_LOGD(TAG, "'%s' - Sending state:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode))); diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index feac9823b9..97b8c2213e 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -153,7 +153,7 @@ void Cover::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); this->tilt = clamp(this->tilt, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index c061bc81f7..c5ea051914 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -30,7 +30,7 @@ void DateEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending date %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); + ESP_LOGD(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); this->state_callback_.call(); #if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_date_update(this); diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index 694f9c5721..fd3901fcfc 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -45,8 +45,8 @@ void DateTimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending datetime %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, - this->month_, this->day_, this->hour_, this->minute_, this->second_); + ESP_LOGD(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_, + this->day_, this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_datetime_update(this); diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index 0e71c95238..d0b8875ed1 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -26,8 +26,7 @@ void TimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending time %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, - this->second_); + ESP_LOGD(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_time_update(this); diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp index 4c74a11388..8015f2255a 100644 --- a/esphome/components/event/event.cpp +++ b/esphome/components/event/event.cpp @@ -22,7 +22,7 @@ void Event::trigger(const std::string &event_type) { return; } this->last_event_type_ = found; - ESP_LOGD(TAG, "'%s' Triggered event '%s'", this->get_name().c_str(), this->last_event_type_); + ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_); this->event_callback_.call(event_type); #if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_event(this); diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 2e48d84eb9..02fde730eb 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -201,7 +201,7 @@ void Fan::publish_state() { auto traits = this->get_traits(); ESP_LOGD(TAG, - "'%s' - Sending state:\n" + "'%s' >>\n" " State: %s", this->name_.c_str(), ONOFF(this->state)); if (traits.supports_speed()) { diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 018f5113e3..aca6ec10f3 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -52,7 +52,7 @@ void Lock::publish_state(LockState state) { this->state = state; this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s': Sending state %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); + ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); this->state_callback_.call(); #if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_lock_update(this); diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index 992100ead0..b0af604189 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -31,7 +31,7 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o void Number::publish_state(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s': Sending state %f", this->get_name().c_str(), state); + ESP_LOGD(TAG, "'%s' >> %.2f", this->get_name().c_str(), state); this->state_callback_.call(state); #if defined(USE_NUMBER) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_number_update(this); diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index 3d70e94d47..91e27b30de 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -31,7 +31,7 @@ void Select::publish_state(size_t index) { #pragma GCC diagnostic ignored "-Wdeprecated-declarations" this->state = option; // Update deprecated member for backward compatibility #pragma GCC diagnostic pop - ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", this->get_name().c_str(), option, index); + ESP_LOGD(TAG, "'%s' >> %s (%zu)", this->get_name().c_str(), option, index); this->state_callback_.call(index); #if defined(USE_SELECT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_select_update(this); diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index 64678f8d0c..9fdb7bbafd 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -126,8 +126,8 @@ float Sensor::get_raw_state() const { return this->raw_state; } void Sensor::internal_send_state_to_frontend(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s': Sending state %.5f %s with %d decimals of accuracy", this->get_name().c_str(), state, - this->get_unit_of_measurement_ref().c_str(), this->get_accuracy_decimals()); + ESP_LOGD(TAG, "'%s' >> %.*f %s", this->get_name().c_str(), std::max(0, (int) this->get_accuracy_decimals()), state, + this->get_unit_of_measurement_ref().c_str()); this->callback_.call(state); #if defined(USE_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_sensor_update(this); diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 3c3a437ff3..069533fa78 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -62,7 +62,7 @@ void Switch::publish_state(bool state) { if (restore_mode & RESTORE_MODE_PERSISTENT_MASK) this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s': Sending state %s", this->name_.c_str(), ONOFF(this->state)); + ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), ONOFF(this->state)); this->state_callback_.call(this->state); #if defined(USE_SWITCH) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_switch_update(this); diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index c2ade56f69..e3f74b685b 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -20,9 +20,9 @@ void Text::publish_state(const char *state, size_t len) { this->state.assign(state, len); } if (this->traits.get_mode() == TEXT_MODE_PASSWORD) { - ESP_LOGD(TAG, "'%s': Sending state " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); } else { - ESP_LOGD(TAG, "'%s': Sending state %s", this->get_name().c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->state.c_str()); } this->state_callback_.call(this->state); #if defined(USE_TEXT) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 66301564a4..86e2387dc7 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -116,7 +116,7 @@ void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) void TextSensor::notify_frontend_() { this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending state '%s'", this->name_.c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> '%s'", this->name_.c_str(), this->state.c_str()); this->callback_.call(this->state); #if defined(USE_TEXT_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_text_sensor_update(this); diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 6d13341a8a..515e4c2c18 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "update"; void UpdateEntity::publish_state() { ESP_LOGD(TAG, - "'%s' - Publishing:\n" + "'%s' >>\n" " Current Version: %s", this->name_.c_str(), this->update_info_.current_version.c_str()); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index fed113afc2..a9086747ce 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -133,7 +133,7 @@ void Valve::add_on_state_callback(std::function &&f) { this->state_callb void Valve::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index d092203d06..7b947057e1 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -153,7 +153,7 @@ void WaterHeater::setup() { void WaterHeater::publish_state() { auto traits = this->get_traits(); ESP_LOGD(TAG, - "'%s' - Sending state:\n" + "'%s' >>\n" " Mode: %s", this->name_.c_str(), LOG_STR_ARG(water_heater_mode_to_string(this->mode_))); if (!std::isnan(this->current_temperature_)) { From 9d42bfd161a6058b5ae9eaa4a41d7a1c64db0290 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 07:38:18 -1000 Subject: [PATCH 0116/2030] [api] Fix state updates being sent to clients that did not subscribe (#13237) --- esphome/components/api/api_server.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a4eeb4dd5e..a63d33f73b 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -241,8 +241,10 @@ void APIServer::handle_disconnect(APIConnection *conn) {} void APIServer::on_##entity_name##_update(entity_type *obj) { /* NOLINT(bugprone-macro-parentheses) */ \ if (obj->is_internal()) \ return; \ - for (auto &c : this->clients_) \ - c->send_##entity_name##_state(obj); \ + for (auto &c : this->clients_) { \ + if (c->flags_.state_subscription) \ + c->send_##entity_name##_state(obj); \ + } \ } #ifdef USE_BINARY_SENSOR @@ -321,8 +323,10 @@ API_DISPATCH_UPDATE(water_heater::WaterHeater, water_heater) void APIServer::on_event(event::Event *obj) { if (obj->is_internal()) return; - for (auto &c : this->clients_) - c->send_event(obj); + for (auto &c : this->clients_) { + if (c->flags_.state_subscription) + c->send_event(obj); + } } #endif @@ -331,8 +335,10 @@ void APIServer::on_event(event::Event *obj) { void APIServer::on_update(update::UpdateEntity *obj) { if (obj->is_internal()) return; - for (auto &c : this->clients_) - c->send_update_state(obj); + for (auto &c : this->clients_) { + if (c->flags_.state_subscription) + c->send_update_state(obj); + } } #endif From 22a4ec69c2c531394b22fbbf4b7e03f1dea2ab04 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 07:38:44 -1000 Subject: [PATCH 0117/2030] [core] Fix platform subcomponents not filtering source files (#13208) --- esphome/components/debug/sensor.py | 6 +++++- esphome/components/debug/text_sensor.py | 6 +++++- esphome/components/nextion/display.py | 7 ++++++- esphome/components/remote_receiver/binary_sensor.py | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index 4484f15935..6a8e2cd828 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -17,7 +17,11 @@ from esphome.const import ( UNIT_PERCENT, ) -from . import CONF_DEBUG_ID, DebugComponent +from . import ( # noqa: F401 pylint: disable=unused-import + CONF_DEBUG_ID, + FILTER_SOURCE_FILES, + DebugComponent, +) DEPENDENCIES = ["debug"] diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 96ef231850..c69b8d9461 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -8,7 +8,11 @@ from esphome.const import ( ICON_RESTART, ) -from . import CONF_DEBUG_ID, DebugComponent +from . import ( # noqa: F401 pylint: disable=unused-import + CONF_DEBUG_ID, + FILTER_SOURCE_FILES, + DebugComponent, +) DEPENDENCIES = ["debug"] diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index b95df55a61..0b4ba3a171 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -11,7 +11,12 @@ from esphome.const import ( ) from esphome.core import CORE, TimePeriod -from . import Nextion, nextion_ns, nextion_ref +from . import ( # noqa: F401 pylint: disable=unused-import + FILTER_SOURCE_FILES, + Nextion, + nextion_ns, + nextion_ref, +) from .base_component import ( CONF_AUTO_WAKE_ON_TOUCH, CONF_COMMAND_SPACING, diff --git a/esphome/components/remote_receiver/binary_sensor.py b/esphome/components/remote_receiver/binary_sensor.py index 218b40d6cc..fe3e2af950 100644 --- a/esphome/components/remote_receiver/binary_sensor.py +++ b/esphome/components/remote_receiver/binary_sensor.py @@ -1,5 +1,7 @@ from esphome.components import binary_sensor, remote_base +from . import FILTER_SOURCE_FILES # noqa: F401 pylint: disable=unused-import + DEPENDENCIES = ["remote_receiver"] CONFIG_SCHEMA = remote_base.validate_binary_sensor From 9003844eda7d7ddeea60cab318e914beea59f471 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 08:29:11 -1000 Subject: [PATCH 0118/2030] [core] Fix ESP32-S2/S3 hardware SHA crash by aligning HashBase digest buffer (#13234) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../update/esp32_hosted_update.cpp | 6 ++---- .../components/esphome/ota/ota_esphome.cpp | 12 ++++------- esphome/components/sha256/sha256.cpp | 20 +++++++++---------- esphome/components/sha256/sha256.h | 11 +++++----- esphome/core/hash_base.h | 10 +++++++++- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index 9f8ae3277e..d69a438578 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -294,8 +294,7 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { } // Stream firmware to coprocessor while computing SHA256 - // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); uint8_t buffer[CHUNK_SIZE]; @@ -352,8 +351,7 @@ bool Esp32HostedUpdate::write_embedded_firmware_to_coprocessor_() { } // Verify SHA256 before writing - // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); hasher.add(this->firmware_data_, this->firmware_size_); hasher.calculate(); diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index b2ae185687..df2ea98f2c 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -563,11 +563,9 @@ bool ESPHomeOTAComponent::handle_auth_send_() { // [1+hex_size...1+2*hex_size-1]: cnonce (hex_size bytes) - client's nonce // [1+2*hex_size...1+3*hex_size-1]: response (hex_size bytes) - client's hash - // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame + // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for - // hardware SHA acceleration DMA operations. - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; const size_t hex_size = hasher.get_size() * 2; const size_t nonce_len = hasher.get_size() / 4; @@ -639,11 +637,9 @@ bool ESPHomeOTAComponent::handle_auth_read_() { const char *cnonce = nonce + hex_size; const char *response = cnonce + hex_size; - // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame + // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for - // hardware SHA acceleration DMA operations. - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); hasher.add(this->password_.c_str(), this->password_.length()); diff --git a/esphome/components/sha256/sha256.cpp b/esphome/components/sha256/sha256.cpp index 48559d7c73..23995e6534 100644 --- a/esphome/components/sha256/sha256.cpp +++ b/esphome/components/sha256/sha256.cpp @@ -10,26 +10,24 @@ namespace esphome::sha256 { #if defined(USE_ESP32) || defined(USE_LIBRETINY) -// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): +// CRITICAL ESP32 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): // -// The ESP32-S3 uses hardware DMA for SHA acceleration. The mbedtls_sha256_context structure contains -// internal state that the DMA engine references. This imposes three critical constraints: +// ESP32 variants (except original ESP32) use DMA-based hardware SHA acceleration that requires +// 32-byte aligned digest buffers. This is handled automatically via HashBase::digest_ which has +// alignas(32) on these platforms. Two additional constraints apply: // -// 1. ALIGNMENT: The SHA256 object MUST be declared with `alignas(32)` for proper DMA alignment. -// Without this, the DMA engine may crash with an abort in sha_hal_read_digest(). -// -// 2. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to +// 1. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to // write to incorrect memory locations. This results in null pointer dereferences and crashes. // ALWAYS use fixed-size arrays (e.g., char buf[65], not char buf[size+1]). // -// 3. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same +// 2. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same // function. NEVER pass the SHA256 object or HashBase pointer to another function. When the stack // frame changes (function call/return), the DMA references become invalid and will produce // truncated hash output (20 bytes instead of 32) or corrupt memory. // // CORRECT USAGE: // void my_function() { -// alignas(32) sha256::SHA256 hasher; // Created locally with proper alignment +// sha256::SHA256 hasher; // hasher.init(); // hasher.add(data, len); // Any size, no chunking needed // hasher.calculate(); @@ -37,9 +35,9 @@ namespace esphome::sha256 { // // hasher destroyed when function returns // } // -// INCORRECT USAGE (WILL FAIL ON ESP32-S3): +// INCORRECT USAGE (WILL FAIL): // void my_function() { -// sha256::SHA256 hasher; // WRONG: Missing alignas(32) +// sha256::SHA256 hasher; // helper(&hasher); // WRONG: Passed to different stack frame // } // void helper(HashBase *h) { diff --git a/esphome/components/sha256/sha256.h b/esphome/components/sha256/sha256.h index 17d80636f1..bafb359485 100644 --- a/esphome/components/sha256/sha256.h +++ b/esphome/components/sha256/sha256.h @@ -24,13 +24,14 @@ namespace esphome::sha256 { /// SHA256 hash implementation. /// -/// CRITICAL for ESP32-S3 with IDF 5.5.x hardware SHA acceleration: -/// 1. SHA256 objects MUST be declared with `alignas(32)` for proper DMA alignment -/// 2. The object MUST stay in the same stack frame (no passing to other functions) -/// 3. NO Variable Length Arrays (VLAs) in the same function +/// CRITICAL for ESP32 variants (except original) with IDF 5.5.x hardware SHA acceleration: +/// 1. The object MUST stay in the same stack frame (no passing to other functions) +/// 2. NO Variable Length Arrays (VLAs) in the same function +/// +/// Note: Alignment is handled automatically via the HashBase::digest_ member. /// /// Example usage: -/// alignas(32) sha256::SHA256 hasher; +/// sha256::SHA256 hasher; /// hasher.init(); /// hasher.add(data, len); /// hasher.calculate(); diff --git a/esphome/core/hash_base.h b/esphome/core/hash_base.h index 0c1c2dce33..606cd3080c 100644 --- a/esphome/core/hash_base.h +++ b/esphome/core/hash_base.h @@ -44,7 +44,15 @@ class HashBase { virtual size_t get_size() const = 0; protected: - uint8_t digest_[32]; // Storage sized for max(MD5=16, SHA256=32) bytes +// ESP32 variants with DMA-based hardware SHA (all except original ESP32) require 32-byte aligned buffers. +// Original ESP32 uses a different hardware SHA implementation without DMA alignment requirements. +// Other platforms (ESP8266, RP2040, LibreTiny) use software SHA and don't need alignment. +// Storage sized for max(MD5=16, SHA256=32) bytes +#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32) + alignas(32) uint8_t digest_[32]; +#else + uint8_t digest_[32]; +#endif }; } // namespace esphome From 0dc5a7c9a42da5107ab0a9a7eb8c6d36020b0f5d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:17:00 -0500 Subject: [PATCH 0119/2030] [safe_mode] Detect bootloader rollback support at runtime (#13230) Co-authored-by: Claude Opus 4.5 --- esphome/components/safe_mode/safe_mode.cpp | 23 +++++++++++++++++++--- esphome/components/safe_mode/safe_mode.h | 7 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index ef6ebea247..f32511531a 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -9,7 +9,7 @@ #include #include -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) #include #endif @@ -26,6 +26,17 @@ void SafeModeComponent::dump_config() { this->safe_mode_boot_is_good_after_ / 1000, // because milliseconds this->safe_mode_num_attempts_, this->safe_mode_enable_time_ / 1000); // because milliseconds +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + const char *state_str; + if (this->ota_state_ == ESP_OTA_IMG_NEW) { + state_str = "not supported"; + } else if (this->ota_state_ == ESP_OTA_IMG_PENDING_VERIFY) { + state_str = "supported"; + } else { + state_str = "support unknown"; + } + ESP_LOGCONFIG(TAG, " Bootloader rollback: %s", state_str); +#endif if (this->safe_mode_rtc_value_ > 1 && this->safe_mode_rtc_value_ != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { auto remaining_restarts = this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_; @@ -36,7 +47,7 @@ void SafeModeComponent::dump_config() { } } -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); if (last_invalid != nullptr) { ESP_LOGW(TAG, @@ -55,7 +66,7 @@ void SafeModeComponent::loop() { ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); this->clean_rtc(); this->boot_successful_ = true; -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) // Mark OTA partition as valid to prevent rollback esp_ota_mark_app_valid_cancel_rollback(); #endif @@ -90,6 +101,12 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en this->safe_mode_num_attempts_ = num_attempts; this->rtc_ = global_preferences->make_preference(233825507UL, false); +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + // Check partition state to detect if bootloader supports rollback + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_get_state_partition(running, &this->ota_state_); +#endif + uint32_t rtc_val = this->read_rtc_(); this->safe_mode_rtc_value_ = rtc_val; diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 4aefd11458..d6f669f39f 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -5,6 +5,10 @@ #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) +#include +#endif + namespace esphome::safe_mode { /// SafeModeComponent provides a safe way to recover from repeated boot failures @@ -42,6 +46,9 @@ class SafeModeComponent : public Component { // Group 1-byte members together to minimize padding bool boot_successful_{false}; ///< set to true after boot is considered successful uint8_t safe_mode_num_attempts_{0}; +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + esp_ota_img_states_t ota_state_{ESP_OTA_IMG_UNDEFINED}; +#endif // Larger objects at the end ESPPreferenceObject rtc_; #ifdef USE_SAFE_MODE_CALLBACK From 6380458d78f64840fd9f3b487b71e951cb3b56a2 Mon Sep 17 00:00:00 2001 From: John Stenger Date: Thu, 15 Jan 2026 11:18:08 -0800 Subject: [PATCH 0120/2030] [qr_code] Allocate and free memory for QR code buffer (#13161) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- esphome/components/qr_code/qr_code.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/qr_code/qr_code.cpp b/esphome/components/qr_code/qr_code.cpp index c2db741e17..0322c8a141 100644 --- a/esphome/components/qr_code/qr_code.cpp +++ b/esphome/components/qr_code/qr_code.cpp @@ -27,7 +27,16 @@ void QrCode::set_ecc(qrcodegen_Ecc ecc) { void QrCode::generate_qr_code() { ESP_LOGV(TAG, "Generating QR code"); + +#ifdef USE_ESP32 + // ESP32 has 8KB stack, safe to allocate ~4KB buffer on stack uint8_t tempbuffer[qrcodegen_BUFFER_LEN_MAX]; +#else + // Other platforms (ESP8266: 4KB, RP2040: 2KB, LibreTiny: ~4KB) have smaller stacks + // Allocate buffer on heap to avoid stack overflow + auto tempbuffer_owner = std::make_unique(qrcodegen_BUFFER_LEN_MAX); + uint8_t *tempbuffer = tempbuffer_owner.get(); +#endif if (!qrcodegen_encodeText(this->value_.c_str(), tempbuffer, this->qr_, this->ecc_, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true)) { From 41dceb76ec3bea38e787ba0cdb6cf44d9de8a77e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 09:56:35 -1000 Subject: [PATCH 0121/2030] [web_server][captive_portal] Change default compression from Brotli to gzip (#13246) --- esphome/components/captive_portal/__init__.py | 2 +- esphome/components/web_server/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index 4b30dc5d16..049618219e 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -44,7 +44,7 @@ CONFIG_SCHEMA = cv.All( cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id( web_server_base.WebServerBase ), - cv.Optional(CONF_COMPRESSION, default="br"): cv.one_of("br", "gzip"), + cv.Optional(CONF_COMPRESSION, default="gzip"): cv.one_of("gzip", "br"), } ).extend(cv.COMPONENT_SCHEMA), cv.only_on( diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 16ac9d054c..3f1e094afc 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -203,7 +203,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_OTA): cv.boolean, cv.Optional(CONF_LOG, default=True): cv.boolean, cv.Optional(CONF_LOCAL): cv.boolean, - cv.Optional(CONF_COMPRESSION, default="br"): cv.one_of("br", "gzip"), + cv.Optional(CONF_COMPRESSION, default="gzip"): cv.one_of("gzip", "br"), cv.Optional(CONF_SORTING_GROUPS): cv.ensure_list(sorting_group), } ).extend(cv.COMPONENT_SCHEMA), From 04273501016f7a60961893c3da19bbf0211a9625 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 09:59:40 -1000 Subject: [PATCH 0122/2030] Bump ruff from 0.14.11 to 0.14.12 (#13244) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 092a06fd66..e0bc943ab4 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.11 # also change in .pre-commit-config.yaml when updating +ruff==0.14.12 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From 3c63ff5e367665bb41f665a66b217b076f4602a4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:27:26 +1100 Subject: [PATCH 0123/2030] [image] Correctly handle dimensions in physical units (#13209) --- esphome/components/image/__init__.py | 13 ++--- .../image/config/mm_dimensions.svg | 5 ++ tests/component_tests/image/test_init.py | 55 ++++++++++++++++++- 3 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 tests/component_tests/image/config/mm_dimensions.svg diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 3f8d909824..6ff75d7709 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -665,15 +665,10 @@ async def write_image(config, all_frames=False): if is_svg_file(path): import resvg_py - if resize: - width, height = resize - # resvg-py allows rendering by width/height directly - image_data = resvg_py.svg_to_bytes( - svg_path=str(path), width=int(width), height=int(height) - ) - else: - # Default size - image_data = resvg_py.svg_to_bytes(svg_path=str(path)) + resize = resize or (None, None) + image_data = resvg_py.svg_to_bytes( + svg_path=str(path), width=resize[0], height=resize[1], dpi=100 + ) # Convert bytes to Pillow Image image = Image.open(io.BytesIO(image_data)) diff --git a/tests/component_tests/image/config/mm_dimensions.svg b/tests/component_tests/image/config/mm_dimensions.svg new file mode 100644 index 0000000000..bb64433a4d --- /dev/null +++ b/tests/component_tests/image/config/mm_dimensions.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/component_tests/image/test_init.py b/tests/component_tests/image/test_init.py index 930bbac8d1..c9481a0e1d 100644 --- a/tests/component_tests/image/test_init.py +++ b/tests/component_tests/image/test_init.py @@ -5,17 +5,21 @@ from __future__ import annotations from collections.abc import Callable from pathlib import Path from typing import Any +from unittest.mock import MagicMock, patch import pytest from esphome import config_validation as cv from esphome.components.image import ( + CONF_INVERT_ALPHA, + CONF_OPAQUE, CONF_TRANSPARENCY, CONFIG_SCHEMA, get_all_image_metadata, get_image_metadata, + write_image, ) -from esphome.const import CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE +from esphome.const import CONF_DITHER, CONF_FILE, CONF_ID, CONF_RAW_DATA_ID, CONF_TYPE from esphome.core import CORE @@ -350,3 +354,52 @@ def test_get_all_image_metadata_empty() -> None: "get_all_image_metadata should always return a dict" ) # Length could be 0 or more depending on what's in CORE at test time + + +@pytest.fixture +def mock_progmem_array(): + """Mock progmem_array to avoid needing a proper ID object in tests.""" + with patch("esphome.components.image.cg.progmem_array") as mock_progmem: + mock_progmem.return_value = MagicMock() + yield mock_progmem + + +@pytest.mark.asyncio +async def test_svg_with_mm_dimensions_succeeds( + component_config_path: Callable[[str], Path], + mock_progmem_array: MagicMock, +) -> None: + """Test that SVG files with dimensions in mm are successfully processed.""" + # Create a config for write_image without CONF_RESIZE + config = { + CONF_FILE: component_config_path("mm_dimensions.svg"), + CONF_TYPE: "BINARY", + CONF_TRANSPARENCY: CONF_OPAQUE, + CONF_DITHER: "NONE", + CONF_INVERT_ALPHA: False, + CONF_RAW_DATA_ID: "test_raw_data_id", + } + + # This should succeed without raising an error + result = await write_image(config) + + # Verify that write_image returns the expected tuple + assert isinstance(result, tuple), "write_image should return a tuple" + assert len(result) == 6, "write_image should return 6 values" + + prog_arr, width, height, image_type, trans_value, frame_count = result + + # Verify the dimensions are positive integers + # At 100 DPI, 10mm = ~39 pixels (10mm * 100dpi / 25.4mm_per_inch) + assert isinstance(width, int), "Width should be an integer" + assert isinstance(height, int), "Height should be an integer" + assert width > 0, "Width should be positive" + assert height > 0, "Height should be positive" + assert frame_count == 1, "Single image should have frame_count of 1" + # Verify we got reasonable dimensions from the mm-based SVG + assert 30 < width < 50, ( + f"Width should be around 39 pixels for 10mm at 100dpi, got {width}" + ) + assert 30 < height < 50, ( + f"Height should be around 39 pixels for 10mm at 100dpi, got {height}" + ) From 0b5a3506ccccec9a53d2fff180dfdf4d6bfa1963 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 00:13:05 -1000 Subject: [PATCH 0124/2030] [core] Optimize and normalize entity state publishing logs with >> format (#13236) --- .../components/alarm_control_panel/alarm_control_panel.cpp | 3 ++- esphome/components/binary_sensor/binary_sensor.cpp | 2 +- esphome/components/climate/climate.cpp | 2 +- esphome/components/cover/cover.cpp | 2 +- esphome/components/datetime/date_entity.cpp | 2 +- esphome/components/datetime/datetime_entity.cpp | 4 ++-- esphome/components/datetime/time_entity.cpp | 3 +-- esphome/components/event/event.cpp | 2 +- esphome/components/fan/fan.cpp | 2 +- esphome/components/lock/lock.cpp | 2 +- esphome/components/number/number.cpp | 2 +- esphome/components/select/select.cpp | 2 +- esphome/components/sensor/sensor.cpp | 4 ++-- esphome/components/switch/switch.cpp | 2 +- esphome/components/text/text.cpp | 4 ++-- esphome/components/text_sensor/text_sensor.cpp | 2 +- esphome/components/update/update_entity.cpp | 2 +- esphome/components/valve/valve.cpp | 2 +- esphome/components/water_heater/water_heater.cpp | 2 +- 19 files changed, 23 insertions(+), 23 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 89c0908a74..248b5065ad 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -31,7 +31,8 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { this->last_update_ = millis(); if (state != this->current_state_) { auto prev_state = this->current_state_; - ESP_LOGD(TAG, "Set state to: %s, previous: %s", LOG_STR_ARG(alarm_control_panel_state_to_string(state)), + ESP_LOGD(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(), + LOG_STR_ARG(alarm_control_panel_state_to_string(state)), LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state))); this->current_state_ = state; // Single state callback - triggers check get_state() for specific states diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index 86b7350aa8..4fe2a019e0 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -44,7 +44,7 @@ bool BinarySensor::set_new_state(const optional &new_state) { #if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_binary_sensor_update(this); #endif - ESP_LOGD(TAG, "'%s': %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); + ESP_LOGD(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); return true; } return false; diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 7611d33cbf..816bd5dfcb 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -436,7 +436,7 @@ void Climate::save_state_() { } void Climate::publish_state() { - ESP_LOGD(TAG, "'%s' - Sending state:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode))); diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index feac9823b9..97b8c2213e 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -153,7 +153,7 @@ void Cover::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); this->tilt = clamp(this->tilt, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index c061bc81f7..c5ea051914 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -30,7 +30,7 @@ void DateEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending date %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); + ESP_LOGD(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); this->state_callback_.call(); #if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_date_update(this); diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index 694f9c5721..fd3901fcfc 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -45,8 +45,8 @@ void DateTimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending datetime %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, - this->month_, this->day_, this->hour_, this->minute_, this->second_); + ESP_LOGD(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_, + this->day_, this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_datetime_update(this); diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index 0e71c95238..d0b8875ed1 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -26,8 +26,7 @@ void TimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending time %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, - this->second_); + ESP_LOGD(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_time_update(this); diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp index 4c74a11388..8015f2255a 100644 --- a/esphome/components/event/event.cpp +++ b/esphome/components/event/event.cpp @@ -22,7 +22,7 @@ void Event::trigger(const std::string &event_type) { return; } this->last_event_type_ = found; - ESP_LOGD(TAG, "'%s' Triggered event '%s'", this->get_name().c_str(), this->last_event_type_); + ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_); this->event_callback_.call(event_type); #if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_event(this); diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 2e48d84eb9..02fde730eb 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -201,7 +201,7 @@ void Fan::publish_state() { auto traits = this->get_traits(); ESP_LOGD(TAG, - "'%s' - Sending state:\n" + "'%s' >>\n" " State: %s", this->name_.c_str(), ONOFF(this->state)); if (traits.supports_speed()) { diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 018f5113e3..aca6ec10f3 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -52,7 +52,7 @@ void Lock::publish_state(LockState state) { this->state = state; this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s': Sending state %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); + ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); this->state_callback_.call(); #if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_lock_update(this); diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index 992100ead0..b0af604189 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -31,7 +31,7 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o void Number::publish_state(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s': Sending state %f", this->get_name().c_str(), state); + ESP_LOGD(TAG, "'%s' >> %.2f", this->get_name().c_str(), state); this->state_callback_.call(state); #if defined(USE_NUMBER) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_number_update(this); diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index 3d70e94d47..91e27b30de 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -31,7 +31,7 @@ void Select::publish_state(size_t index) { #pragma GCC diagnostic ignored "-Wdeprecated-declarations" this->state = option; // Update deprecated member for backward compatibility #pragma GCC diagnostic pop - ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", this->get_name().c_str(), option, index); + ESP_LOGD(TAG, "'%s' >> %s (%zu)", this->get_name().c_str(), option, index); this->state_callback_.call(index); #if defined(USE_SELECT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_select_update(this); diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index 64678f8d0c..9fdb7bbafd 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -126,8 +126,8 @@ float Sensor::get_raw_state() const { return this->raw_state; } void Sensor::internal_send_state_to_frontend(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s': Sending state %.5f %s with %d decimals of accuracy", this->get_name().c_str(), state, - this->get_unit_of_measurement_ref().c_str(), this->get_accuracy_decimals()); + ESP_LOGD(TAG, "'%s' >> %.*f %s", this->get_name().c_str(), std::max(0, (int) this->get_accuracy_decimals()), state, + this->get_unit_of_measurement_ref().c_str()); this->callback_.call(state); #if defined(USE_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_sensor_update(this); diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 3c3a437ff3..069533fa78 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -62,7 +62,7 @@ void Switch::publish_state(bool state) { if (restore_mode & RESTORE_MODE_PERSISTENT_MASK) this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s': Sending state %s", this->name_.c_str(), ONOFF(this->state)); + ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), ONOFF(this->state)); this->state_callback_.call(this->state); #if defined(USE_SWITCH) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_switch_update(this); diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index c2ade56f69..e3f74b685b 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -20,9 +20,9 @@ void Text::publish_state(const char *state, size_t len) { this->state.assign(state, len); } if (this->traits.get_mode() == TEXT_MODE_PASSWORD) { - ESP_LOGD(TAG, "'%s': Sending state " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); } else { - ESP_LOGD(TAG, "'%s': Sending state %s", this->get_name().c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->state.c_str()); } this->state_callback_.call(this->state); #if defined(USE_TEXT) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 66301564a4..86e2387dc7 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -116,7 +116,7 @@ void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) void TextSensor::notify_frontend_() { this->set_has_state(true); - ESP_LOGD(TAG, "'%s': Sending state '%s'", this->name_.c_str(), this->state.c_str()); + ESP_LOGD(TAG, "'%s' >> '%s'", this->name_.c_str(), this->state.c_str()); this->callback_.call(this->state); #if defined(USE_TEXT_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_text_sensor_update(this); diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 6d13341a8a..515e4c2c18 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "update"; void UpdateEntity::publish_state() { ESP_LOGD(TAG, - "'%s' - Publishing:\n" + "'%s' >>\n" " Current Version: %s", this->name_.c_str(), this->update_info_.current_version.c_str()); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index fed113afc2..a9086747ce 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -133,7 +133,7 @@ void Valve::add_on_state_callback(std::function &&f) { this->state_callb void Valve::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str()); + ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index d092203d06..7b947057e1 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -153,7 +153,7 @@ void WaterHeater::setup() { void WaterHeater::publish_state() { auto traits = this->get_traits(); ESP_LOGD(TAG, - "'%s' - Sending state:\n" + "'%s' >>\n" " Mode: %s", this->name_.c_str(), LOG_STR_ARG(water_heater_mode_to_string(this->mode_))); if (!std::isnan(this->current_temperature_)) { From 9030dc9d4e8499feaa29e61eece3697afbc80172 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 07:38:18 -1000 Subject: [PATCH 0125/2030] [api] Fix state updates being sent to clients that did not subscribe (#13237) --- esphome/components/api/api_server.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a4eeb4dd5e..a63d33f73b 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -241,8 +241,10 @@ void APIServer::handle_disconnect(APIConnection *conn) {} void APIServer::on_##entity_name##_update(entity_type *obj) { /* NOLINT(bugprone-macro-parentheses) */ \ if (obj->is_internal()) \ return; \ - for (auto &c : this->clients_) \ - c->send_##entity_name##_state(obj); \ + for (auto &c : this->clients_) { \ + if (c->flags_.state_subscription) \ + c->send_##entity_name##_state(obj); \ + } \ } #ifdef USE_BINARY_SENSOR @@ -321,8 +323,10 @@ API_DISPATCH_UPDATE(water_heater::WaterHeater, water_heater) void APIServer::on_event(event::Event *obj) { if (obj->is_internal()) return; - for (auto &c : this->clients_) - c->send_event(obj); + for (auto &c : this->clients_) { + if (c->flags_.state_subscription) + c->send_event(obj); + } } #endif @@ -331,8 +335,10 @@ void APIServer::on_event(event::Event *obj) { void APIServer::on_update(update::UpdateEntity *obj) { if (obj->is_internal()) return; - for (auto &c : this->clients_) - c->send_update_state(obj); + for (auto &c : this->clients_) { + if (c->flags_.state_subscription) + c->send_update_state(obj); + } } #endif From 737c2b8732b34cc04888206b301197247b0f831c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 07:38:44 -1000 Subject: [PATCH 0126/2030] [core] Fix platform subcomponents not filtering source files (#13208) --- esphome/components/debug/sensor.py | 6 +++++- esphome/components/debug/text_sensor.py | 6 +++++- esphome/components/nextion/display.py | 7 ++++++- esphome/components/remote_receiver/binary_sensor.py | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index 4484f15935..6a8e2cd828 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -17,7 +17,11 @@ from esphome.const import ( UNIT_PERCENT, ) -from . import CONF_DEBUG_ID, DebugComponent +from . import ( # noqa: F401 pylint: disable=unused-import + CONF_DEBUG_ID, + FILTER_SOURCE_FILES, + DebugComponent, +) DEPENDENCIES = ["debug"] diff --git a/esphome/components/debug/text_sensor.py b/esphome/components/debug/text_sensor.py index 96ef231850..c69b8d9461 100644 --- a/esphome/components/debug/text_sensor.py +++ b/esphome/components/debug/text_sensor.py @@ -8,7 +8,11 @@ from esphome.const import ( ICON_RESTART, ) -from . import CONF_DEBUG_ID, DebugComponent +from . import ( # noqa: F401 pylint: disable=unused-import + CONF_DEBUG_ID, + FILTER_SOURCE_FILES, + DebugComponent, +) DEPENDENCIES = ["debug"] diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index b95df55a61..0b4ba3a171 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -11,7 +11,12 @@ from esphome.const import ( ) from esphome.core import CORE, TimePeriod -from . import Nextion, nextion_ns, nextion_ref +from . import ( # noqa: F401 pylint: disable=unused-import + FILTER_SOURCE_FILES, + Nextion, + nextion_ns, + nextion_ref, +) from .base_component import ( CONF_AUTO_WAKE_ON_TOUCH, CONF_COMMAND_SPACING, diff --git a/esphome/components/remote_receiver/binary_sensor.py b/esphome/components/remote_receiver/binary_sensor.py index 218b40d6cc..fe3e2af950 100644 --- a/esphome/components/remote_receiver/binary_sensor.py +++ b/esphome/components/remote_receiver/binary_sensor.py @@ -1,5 +1,7 @@ from esphome.components import binary_sensor, remote_base +from . import FILTER_SOURCE_FILES # noqa: F401 pylint: disable=unused-import + DEPENDENCIES = ["remote_receiver"] CONFIG_SCHEMA = remote_base.validate_binary_sensor From 1ad0969099bbd82263c1aa2e8f7546cb2777fb24 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 08:29:11 -1000 Subject: [PATCH 0127/2030] [core] Fix ESP32-S2/S3 hardware SHA crash by aligning HashBase digest buffer (#13234) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../update/esp32_hosted_update.cpp | 6 ++---- .../components/esphome/ota/ota_esphome.cpp | 12 ++++------- esphome/components/sha256/sha256.cpp | 20 +++++++++---------- esphome/components/sha256/sha256.h | 11 +++++----- esphome/core/hash_base.h | 10 +++++++++- 5 files changed, 30 insertions(+), 29 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index 9f8ae3277e..d69a438578 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -294,8 +294,7 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { } // Stream firmware to coprocessor while computing SHA256 - // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); uint8_t buffer[CHUNK_SIZE]; @@ -352,8 +351,7 @@ bool Esp32HostedUpdate::write_embedded_firmware_to_coprocessor_() { } // Verify SHA256 before writing - // Hardware SHA acceleration requires 32-byte alignment on some chips (ESP32-S3 with IDF 5.5.x+) - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); hasher.add(this->firmware_data_, this->firmware_size_); hasher.calculate(); diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index b2ae185687..df2ea98f2c 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -563,11 +563,9 @@ bool ESPHomeOTAComponent::handle_auth_send_() { // [1+hex_size...1+2*hex_size-1]: cnonce (hex_size bytes) - client's nonce // [1+2*hex_size...1+3*hex_size-1]: response (hex_size bytes) - client's hash - // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame + // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for - // hardware SHA acceleration DMA operations. - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; const size_t hex_size = hasher.get_size() * 2; const size_t nonce_len = hasher.get_size() / 4; @@ -639,11 +637,9 @@ bool ESPHomeOTAComponent::handle_auth_read_() { const char *cnonce = nonce + hex_size; const char *response = cnonce + hex_size; - // CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame + // CRITICAL ESP32-S2/S3 HARDWARE SHA ACCELERATION: Hash object must stay in same stack frame // (no passing to other functions). All hash operations must happen in this function. - // NOTE: On ESP32-S3 with IDF 5.5.x, the SHA256 context must be properly aligned for - // hardware SHA acceleration DMA operations. - alignas(32) sha256::SHA256 hasher; + sha256::SHA256 hasher; hasher.init(); hasher.add(this->password_.c_str(), this->password_.length()); diff --git a/esphome/components/sha256/sha256.cpp b/esphome/components/sha256/sha256.cpp index 48559d7c73..23995e6534 100644 --- a/esphome/components/sha256/sha256.cpp +++ b/esphome/components/sha256/sha256.cpp @@ -10,26 +10,24 @@ namespace esphome::sha256 { #if defined(USE_ESP32) || defined(USE_LIBRETINY) -// CRITICAL ESP32-S3 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): +// CRITICAL ESP32 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): // -// The ESP32-S3 uses hardware DMA for SHA acceleration. The mbedtls_sha256_context structure contains -// internal state that the DMA engine references. This imposes three critical constraints: +// ESP32 variants (except original ESP32) use DMA-based hardware SHA acceleration that requires +// 32-byte aligned digest buffers. This is handled automatically via HashBase::digest_ which has +// alignas(32) on these platforms. Two additional constraints apply: // -// 1. ALIGNMENT: The SHA256 object MUST be declared with `alignas(32)` for proper DMA alignment. -// Without this, the DMA engine may crash with an abort in sha_hal_read_digest(). -// -// 2. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to +// 1. NO VARIABLE LENGTH ARRAYS (VLAs): VLAs corrupt the stack layout, causing the DMA engine to // write to incorrect memory locations. This results in null pointer dereferences and crashes. // ALWAYS use fixed-size arrays (e.g., char buf[65], not char buf[size+1]). // -// 3. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same +// 2. SAME STACK FRAME ONLY: The SHA256 object must be created and used entirely within the same // function. NEVER pass the SHA256 object or HashBase pointer to another function. When the stack // frame changes (function call/return), the DMA references become invalid and will produce // truncated hash output (20 bytes instead of 32) or corrupt memory. // // CORRECT USAGE: // void my_function() { -// alignas(32) sha256::SHA256 hasher; // Created locally with proper alignment +// sha256::SHA256 hasher; // hasher.init(); // hasher.add(data, len); // Any size, no chunking needed // hasher.calculate(); @@ -37,9 +35,9 @@ namespace esphome::sha256 { // // hasher destroyed when function returns // } // -// INCORRECT USAGE (WILL FAIL ON ESP32-S3): +// INCORRECT USAGE (WILL FAIL): // void my_function() { -// sha256::SHA256 hasher; // WRONG: Missing alignas(32) +// sha256::SHA256 hasher; // helper(&hasher); // WRONG: Passed to different stack frame // } // void helper(HashBase *h) { diff --git a/esphome/components/sha256/sha256.h b/esphome/components/sha256/sha256.h index 17d80636f1..bafb359485 100644 --- a/esphome/components/sha256/sha256.h +++ b/esphome/components/sha256/sha256.h @@ -24,13 +24,14 @@ namespace esphome::sha256 { /// SHA256 hash implementation. /// -/// CRITICAL for ESP32-S3 with IDF 5.5.x hardware SHA acceleration: -/// 1. SHA256 objects MUST be declared with `alignas(32)` for proper DMA alignment -/// 2. The object MUST stay in the same stack frame (no passing to other functions) -/// 3. NO Variable Length Arrays (VLAs) in the same function +/// CRITICAL for ESP32 variants (except original) with IDF 5.5.x hardware SHA acceleration: +/// 1. The object MUST stay in the same stack frame (no passing to other functions) +/// 2. NO Variable Length Arrays (VLAs) in the same function +/// +/// Note: Alignment is handled automatically via the HashBase::digest_ member. /// /// Example usage: -/// alignas(32) sha256::SHA256 hasher; +/// sha256::SHA256 hasher; /// hasher.init(); /// hasher.add(data, len); /// hasher.calculate(); diff --git a/esphome/core/hash_base.h b/esphome/core/hash_base.h index 0c1c2dce33..606cd3080c 100644 --- a/esphome/core/hash_base.h +++ b/esphome/core/hash_base.h @@ -44,7 +44,15 @@ class HashBase { virtual size_t get_size() const = 0; protected: - uint8_t digest_[32]; // Storage sized for max(MD5=16, SHA256=32) bytes +// ESP32 variants with DMA-based hardware SHA (all except original ESP32) require 32-byte aligned buffers. +// Original ESP32 uses a different hardware SHA implementation without DMA alignment requirements. +// Other platforms (ESP8266, RP2040, LibreTiny) use software SHA and don't need alignment. +// Storage sized for max(MD5=16, SHA256=32) bytes +#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32) + alignas(32) uint8_t digest_[32]; +#else + uint8_t digest_[32]; +#endif }; } // namespace esphome From 3f6412ba07d36f1d32b8bfa6a8c99452aaecc598 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:17:00 -0500 Subject: [PATCH 0128/2030] [safe_mode] Detect bootloader rollback support at runtime (#13230) Co-authored-by: Claude Opus 4.5 --- esphome/components/safe_mode/safe_mode.cpp | 23 +++++++++++++++++++--- esphome/components/safe_mode/safe_mode.h | 7 +++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index ef6ebea247..f32511531a 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -9,7 +9,7 @@ #include #include -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) #include #endif @@ -26,6 +26,17 @@ void SafeModeComponent::dump_config() { this->safe_mode_boot_is_good_after_ / 1000, // because milliseconds this->safe_mode_num_attempts_, this->safe_mode_enable_time_ / 1000); // because milliseconds +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + const char *state_str; + if (this->ota_state_ == ESP_OTA_IMG_NEW) { + state_str = "not supported"; + } else if (this->ota_state_ == ESP_OTA_IMG_PENDING_VERIFY) { + state_str = "supported"; + } else { + state_str = "support unknown"; + } + ESP_LOGCONFIG(TAG, " Bootloader rollback: %s", state_str); +#endif if (this->safe_mode_rtc_value_ > 1 && this->safe_mode_rtc_value_ != SafeModeComponent::ENTER_SAFE_MODE_MAGIC) { auto remaining_restarts = this->safe_mode_num_attempts_ - this->safe_mode_rtc_value_; @@ -36,7 +47,7 @@ void SafeModeComponent::dump_config() { } } -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); if (last_invalid != nullptr) { ESP_LOGW(TAG, @@ -55,7 +66,7 @@ void SafeModeComponent::loop() { ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); this->clean_rtc(); this->boot_successful_ = true; -#ifdef USE_OTA_ROLLBACK +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) // Mark OTA partition as valid to prevent rollback esp_ota_mark_app_valid_cancel_rollback(); #endif @@ -90,6 +101,12 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en this->safe_mode_num_attempts_ = num_attempts; this->rtc_ = global_preferences->make_preference(233825507UL, false); +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + // Check partition state to detect if bootloader supports rollback + const esp_partition_t *running = esp_ota_get_running_partition(); + esp_ota_get_state_partition(running, &this->ota_state_); +#endif + uint32_t rtc_val = this->read_rtc_(); this->safe_mode_rtc_value_ = rtc_val; diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 4aefd11458..d6f669f39f 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -5,6 +5,10 @@ #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) +#include +#endif + namespace esphome::safe_mode { /// SafeModeComponent provides a safe way to recover from repeated boot failures @@ -42,6 +46,9 @@ class SafeModeComponent : public Component { // Group 1-byte members together to minimize padding bool boot_successful_{false}; ///< set to true after boot is considered successful uint8_t safe_mode_num_attempts_{0}; +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + esp_ota_img_states_t ota_state_{ESP_OTA_IMG_UNDEFINED}; +#endif // Larger objects at the end ESPPreferenceObject rtc_; #ifdef USE_SAFE_MODE_CALLBACK From f88cf1b83add8eae7896f029b1df32100e4a1868 Mon Sep 17 00:00:00 2001 From: John Stenger Date: Thu, 15 Jan 2026 11:18:08 -0800 Subject: [PATCH 0129/2030] [qr_code] Allocate and free memory for QR code buffer (#13161) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- esphome/components/qr_code/qr_code.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/qr_code/qr_code.cpp b/esphome/components/qr_code/qr_code.cpp index c2db741e17..0322c8a141 100644 --- a/esphome/components/qr_code/qr_code.cpp +++ b/esphome/components/qr_code/qr_code.cpp @@ -27,7 +27,16 @@ void QrCode::set_ecc(qrcodegen_Ecc ecc) { void QrCode::generate_qr_code() { ESP_LOGV(TAG, "Generating QR code"); + +#ifdef USE_ESP32 + // ESP32 has 8KB stack, safe to allocate ~4KB buffer on stack uint8_t tempbuffer[qrcodegen_BUFFER_LEN_MAX]; +#else + // Other platforms (ESP8266: 4KB, RP2040: 2KB, LibreTiny: ~4KB) have smaller stacks + // Allocate buffer on heap to avoid stack overflow + auto tempbuffer_owner = std::make_unique(qrcodegen_BUFFER_LEN_MAX); + uint8_t *tempbuffer = tempbuffer_owner.get(); +#endif if (!qrcodegen_encodeText(this->value_.c_str(), tempbuffer, this->qr_, this->ecc_, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true)) { From dacd185afbceb4a17d84a6bbd7896c5619b94c3b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 09:56:35 -1000 Subject: [PATCH 0130/2030] [web_server][captive_portal] Change default compression from Brotli to gzip (#13246) --- esphome/components/captive_portal/__init__.py | 2 +- esphome/components/web_server/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index 4b30dc5d16..049618219e 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -44,7 +44,7 @@ CONFIG_SCHEMA = cv.All( cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id( web_server_base.WebServerBase ), - cv.Optional(CONF_COMPRESSION, default="br"): cv.one_of("br", "gzip"), + cv.Optional(CONF_COMPRESSION, default="gzip"): cv.one_of("gzip", "br"), } ).extend(cv.COMPONENT_SCHEMA), cv.only_on( diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 16ac9d054c..3f1e094afc 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -203,7 +203,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_OTA): cv.boolean, cv.Optional(CONF_LOG, default=True): cv.boolean, cv.Optional(CONF_LOCAL): cv.boolean, - cv.Optional(CONF_COMPRESSION, default="br"): cv.one_of("br", "gzip"), + cv.Optional(CONF_COMPRESSION, default="gzip"): cv.one_of("gzip", "br"), cv.Optional(CONF_SORTING_GROUPS): cv.ensure_list(sorting_group), } ).extend(cv.COMPONENT_SCHEMA), From c151b2da67ab3a2ee2f9a999233323582370d97f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:26:04 -0500 Subject: [PATCH 0131/2030] Bump version to 2026.1.0b2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index e98eac6aa5..aa6a2f169e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0b1 +PROJECT_NUMBER = 2026.1.0b2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 95ccfb9dee..e99fbb8283 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0b1" +__version__ = "2026.1.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 00cc9e44b61b2ae8b275dbdc35479e0149f2389f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 10:38:24 -1000 Subject: [PATCH 0132/2030] [analyze_memory] Fix ELF section mapping for RTL87xx and LN882X platforms (#13213) --- esphome/analyze_memory/const.py | 40 ++++++++++++++++++++++++++--- script/determine-jobs.py | 17 +++++++++--- tests/script/test_determine_jobs.py | 22 ++++++++++++++++ 3 files changed, 73 insertions(+), 6 deletions(-) diff --git a/esphome/analyze_memory/const.py b/esphome/analyze_memory/const.py index 9933bd77fd..aadc6a231c 100644 --- a/esphome/analyze_memory/const.py +++ b/esphome/analyze_memory/const.py @@ -9,10 +9,44 @@ ESPHOME_COMPONENT_PATTERN = re.compile(r"esphome::([a-zA-Z0-9_]+)::") # Maps standard section names to their various platform-specific variants # Note: Order matters! More specific patterns (.bss) must come before general ones (.dram) # because ESP-IDF uses names like ".dram0.bss" which would match ".dram" otherwise +# +# Platform-specific sections: +# - ESP8266/ESP32: .iram*, .dram* +# - LibreTiny RTL87xx: .xip.code_* (flash), .ram.code_* (RAM) +# - LibreTiny BK7231: .itcm.code (fast RAM), .vectors (interrupt vectors) +# - LibreTiny LN882X: .flash_text, .flash_copy* (flash code) SECTION_MAPPING = { - ".text": frozenset([".text", ".iram"]), - ".rodata": frozenset([".rodata"]), - ".bss": frozenset([".bss"]), # Must be before .data to catch ".dram0.bss" + ".text": frozenset( + [ + ".text", + ".iram", + # LibreTiny RTL87xx XIP (eXecute In Place) flash code + ".xip.code", + # LibreTiny RTL87xx RAM code + ".ram.code_text", + # LibreTiny BK7231 fast RAM code and vectors + ".itcm.code", + ".vectors", + # LibreTiny LN882X flash code + ".flash_text", + ".flash_copy", + ] + ), + ".rodata": frozenset( + [ + ".rodata", + # LibreTiny RTL87xx read-only data in RAM + ".ram.code_rodata", + ] + ), + # .bss patterns - must be before .data to catch ".dram0.bss" + ".bss": frozenset( + [ + ".bss", + # LibreTiny LN882X BSS + ".bss_ram", + ] + ), ".data": frozenset([".data", ".dram"]), } diff --git a/script/determine-jobs.py b/script/determine-jobs.py index a61c9bf08d..7ecbfb225e 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -90,6 +90,8 @@ class Platform(StrEnum): ESP32_S2_IDF = "esp32-s2-idf" ESP32_S3_IDF = "esp32-s3-idf" BK72XX_ARD = "bk72xx-ard" # LibreTiny BK7231N + RTL87XX_ARD = "rtl87xx-ard" # LibreTiny RTL8720x + LN882X_ARD = "ln882x-ard" # LibreTiny LN882x RP2040_ARD = "rp2040-ard" # Raspberry Pi Pico @@ -122,8 +124,8 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset( # fastest build times, most sensitive to code size changes # 3. ESP32 IDF - Primary ESP32 platform, most representative of modern ESPHome # 4-6. Other ESP32 variants - Less commonly used but still supported -# 7. BK72XX - LibreTiny platform (good for detecting LibreTiny-specific changes) -# 8. RP2040 - Raspberry Pi Pico platform +# 7-9. LibreTiny platforms (BK72XX, RTL87XX, LN882X) - good for detecting LibreTiny-specific changes +# 10. RP2040 - Raspberry Pi Pico platform MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee) Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained, fastest builds) @@ -132,6 +134,8 @@ MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.ESP32_S2_IDF, # ESP32-S2 IDF Platform.ESP32_S3_IDF, # ESP32-S3 IDF Platform.BK72XX_ARD, # LibreTiny BK7231N + Platform.RTL87XX_ARD, # LibreTiny RTL8720x + Platform.LN882X_ARD, # LibreTiny LN882x Platform.RP2040_ARD, # Raspberry Pi Pico ] @@ -411,6 +415,8 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None: - wifi_component_esp8266.cpp, *_esp8266.h -> ESP8266_ARD - *_esp32*.cpp -> ESP32 IDF (generic) - *_libretiny.cpp, *_bk72*.* -> BK72XX (LibreTiny) + - *_rtl87*.* -> RTL87XX (LibreTiny Realtek) + - *_ln882*.* -> LN882X (LibreTiny Lightning) - *_pico.cpp, *_rp2040.* -> RP2040_ARD Args: @@ -444,7 +450,12 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None: if "esp32" in filename_lower: return Platform.ESP32_IDF - # LibreTiny (via 'libretiny' pattern or BK72xx-specific files) + # LibreTiny platforms (check specific variants before generic libretiny) + # Check specific variants first to handle paths like libretiny/wifi_rtl87xx.cpp + if "rtl87" in filename_lower: + return Platform.RTL87XX_ARD + if "ln882" in filename_lower: + return Platform.LN882X_ARD if "libretiny" in filename_lower or "bk72" in filename_lower: return Platform.BK72XX_ARD diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index bd20cb3e21..52025513a8 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -1472,6 +1472,24 @@ def test_detect_memory_impact_config_runs_at_component_limit(tmp_path: Path) -> determine_jobs.Platform.BK72XX_ARD, ), ("esphome/components/ble/ble_bk72xx.cpp", determine_jobs.Platform.BK72XX_ARD), + # RTL87xx (LibreTiny Realtek) detection + ( + "tests/components/logger/test.rtl87xx-ard.yaml", + determine_jobs.Platform.RTL87XX_ARD, + ), + ( + "esphome/components/libretiny/wifi_rtl87xx.cpp", + determine_jobs.Platform.RTL87XX_ARD, + ), + # LN882x (LibreTiny Lightning) detection + ( + "tests/components/logger/test.ln882x-ard.yaml", + determine_jobs.Platform.LN882X_ARD, + ), + ( + "esphome/components/libretiny/wifi_ln882x.cpp", + determine_jobs.Platform.LN882X_ARD, + ), # RP2040 / Raspberry Pi Pico detection ("esphome/components/gpio/gpio_rp2040.cpp", determine_jobs.Platform.RP2040_ARD), ("esphome/components/wifi/wifi_rp2040.cpp", determine_jobs.Platform.RP2040_ARD), @@ -1501,6 +1519,10 @@ def test_detect_memory_impact_config_runs_at_component_limit(tmp_path: Path) -> "esp32_in_name", "libretiny", "bk72xx", + "rtl87xx_test_yaml", + "rtl87xx_wifi", + "ln882x_test_yaml", + "ln882x_wifi", "rp2040_gpio", "rp2040_wifi", "pico_i2c", From 535c3eb2a221a62e68612cc7fa4322866e6f5fb9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 11:32:02 -1000 Subject: [PATCH 0133/2030] [sprinkler] Fix scheduler deprecation warnings and heap churn with FixedVector (#13251) --- esphome/components/sprinkler/sprinkler.cpp | 6 ++++-- esphome/components/sprinkler/sprinkler.h | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index ca9f85abd8..2813b4450b 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -332,6 +332,7 @@ Sprinkler::Sprinkler(const std::string &name) { // The `name` is needed to set timers up, hence non-default constructor // replaces `set_name()` method previously existed this->name_ = name; + this->timer_.init(2); this->timer_.push_back({this->name_ + "sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)}); this->timer_.push_back({this->name_ + "vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); } @@ -1574,7 +1575,8 @@ const LogString *Sprinkler::state_as_str_(SprinklerState state) { void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { if (this->timer_duration_(timer_index) > 0) { - this->set_timeout(this->timer_[timer_index].name, this->timer_duration_(timer_index), + // FixedVector ensures timer_ can't be resized, so .c_str() pointers remain valid + this->set_timeout(this->timer_[timer_index].name.c_str(), this->timer_duration_(timer_index), this->timer_cbf_(timer_index)); this->timer_[timer_index].start_time = millis(); this->timer_[timer_index].active = true; @@ -1585,7 +1587,7 @@ void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { bool Sprinkler::cancel_timer_(const SprinklerTimerIndex timer_index) { this->timer_[timer_index].active = false; - return this->cancel_timeout(this->timer_[timer_index].name); + return this->cancel_timeout(this->timer_[timer_index].name.c_str()); } bool Sprinkler::timer_active_(const SprinklerTimerIndex timer_index) { return this->timer_[timer_index].active; } diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index 25e2d42446..273c0e9208 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -3,6 +3,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" #include "esphome/components/number/number.h" #include "esphome/components/switch/switch.h" @@ -553,8 +554,8 @@ class Sprinkler : public Component { /// Sprinkler valve operator objects std::vector valve_op_{2}; - /// Valve control timers - std::vector timer_{}; + /// Valve control timers - FixedVector enforces that this can never grow beyond init() size + FixedVector timer_; /// Other Sprinkler instances we should be aware of (used to check if pumps are in use) std::vector other_controllers_; From 2eabc1b96b839c4afc48a3d23441ebfcbff0187d Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 15 Jan 2026 20:22:05 -0600 Subject: [PATCH 0134/2030] [helpers] Add base85 support (#13254) Co-authored-by: J. Nick Koston --- esphome/core/helpers.cpp | 49 ++++++++++++++++++++++++++++++++++++++++ esphome/core/helpers.h | 8 +++++++ 2 files changed, 57 insertions(+) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 309407fbec..b5bf849c30 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -617,6 +617,55 @@ std::vector base64_decode(const std::string &encoded_string) { return ret; } +/// Encode int32 to 5 base85 characters + null terminator +/// Standard ASCII85 alphabet: '!' (33) = 0 through 'u' (117) = 84 +inline void base85_encode_int32(int32_t value, std::span output) { + uint32_t v = static_cast(value); + // Encode least significant digit first, then reverse + for (int i = 4; i >= 0; i--) { + output[i] = static_cast('!' + (v % 85)); + v /= 85; + } + output[5] = '\0'; +} + +/// Decode 5 base85 characters to int32 +inline bool base85_decode_int32(const char *input, int32_t &out) { + uint8_t c0 = static_cast(input[0] - '!'); + uint8_t c1 = static_cast(input[1] - '!'); + uint8_t c2 = static_cast(input[2] - '!'); + uint8_t c3 = static_cast(input[3] - '!'); + uint8_t c4 = static_cast(input[4] - '!'); + + // Each digit must be 0-84. Since uint8_t wraps, chars below '!' become > 84 + if (c0 > 84 || c1 > 84 || c2 > 84 || c3 > 84 || c4 > 84) + return false; + + // 85^4 = 52200625, 85^3 = 614125, 85^2 = 7225, 85^1 = 85 + out = static_cast(c0 * 52200625u + c1 * 614125u + c2 * 7225u + c3 * 85u + c4); + return true; +} + +/// Decode base85 string directly into vector (no intermediate buffer) +bool base85_decode_int32_vector(const std::string &base85, std::vector &out) { + size_t len = base85.size(); + if (len % 5 != 0) + return false; + + out.clear(); + const char *ptr = base85.data(); + const char *end = ptr + len; + + while (ptr < end) { + int32_t value; + if (!base85_decode_int32(ptr, value)) + return false; + out.push_back(value); + ptr += 5; + } + return true; +} + // Colors float gamma_correct(float value, float gamma) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 2e9c0e6b13..d5a04b7eb1 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1086,6 +1086,14 @@ std::vector base64_decode(const std::string &encoded_string); size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len); size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len); +/// Size of buffer needed for base85 encoded int32 (5 chars + null terminator) +static constexpr size_t BASE85_INT32_ENCODED_SIZE = 6; + +void base85_encode_int32(int32_t value, std::span output); + +bool base85_decode_int32(const char *input, int32_t &out); +bool base85_decode_int32_vector(const std::string &base85, std::vector &out); + ///@} /// @name Colors From d2528af649a59a7c7d63d423863f223ca281707e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:48:44 -1000 Subject: [PATCH 0135/2030] [dallas_temp] Use const char* for set_timeout to fix deprecation warning and heap churn (#13250) --- esphome/components/dallas_temp/dallas_temp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index a1b684abbf..13f2fa59bd 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -44,7 +44,7 @@ void DallasTemperatureSensor::update() { this->send_command_(DALLAS_COMMAND_START_CONVERSION); - this->set_timeout(this->get_address_name(), this->millis_to_wait_for_conversion_(), [this] { + this->set_timeout(this->get_address_name().c_str(), this->millis_to_wait_for_conversion_(), [this] { if (!this->read_scratch_pad_() || !this->check_scratch_pad_()) { this->publish_state(NAN); return; From 4eda9e965f9bb444bbfd82e624fd1b551e111837 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:49:01 -1000 Subject: [PATCH 0136/2030] [api] Fix clock conflicts when multiple clients connected to homeassistant time (#13253) --- esphome/components/api/api_server.cpp | 4 +++- esphome/components/time/real_time_clock.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a63d33f73b..ed97c3b9a2 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -558,8 +558,10 @@ bool APIServer::clear_noise_psk(bool make_active) { #ifdef USE_HOMEASSISTANT_TIME void APIServer::request_time() { for (auto &client : this->clients_) { - if (!client->flags_.remove && client->is_authenticated()) + if (!client->flags_.remove && client->is_authenticated()) { client->send_time_request(); + return; // Only request from one client to avoid clock conflicts + } } } #endif diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 639af4457f..f217d14c55 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -31,6 +31,18 @@ void RealTimeClock::dump_config() { void RealTimeClock::synchronize_epoch_(uint32_t epoch) { ESP_LOGVV(TAG, "Got epoch %" PRIu32, epoch); + // Skip if time is already synchronized to avoid unnecessary writes, log spam, + // and prevent clock jumping backwards due to network latency + constexpr time_t min_valid_epoch = 1546300800; // January 1, 2019 + time_t current_time = this->timestamp_now(); + // Check if time is valid (year >= 2019) before comparing + if (current_time >= min_valid_epoch) { + // Unsigned subtraction handles wraparound correctly, then cast to signed + int32_t diff = static_cast(epoch - static_cast(current_time)); + if (diff >= -1 && diff <= 1) { + return; + } + } // Update UTC epoch time. #ifdef USE_ZEPHYR struct timespec ts; From b1230ec6bb47d08e422d62917a90d24a6bc42f6e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:49:19 -1000 Subject: [PATCH 0137/2030] [esp32_ble_client] Reduce GATT data event logging to prevent firmware update failures (#13252) --- .../esp32_ble_client/ble_client_base.cpp | 38 +++++++++++-------- .../esp32_ble_client/ble_client_base.h | 3 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 149fcc79d5..01f79156a9 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -193,10 +193,18 @@ void BLEClientBase::log_event_(const char *name) { ESP_LOGD(TAG, "[%d] [%s] %s", this->connection_index_, this->address_str_, name); } -void BLEClientBase::log_gattc_event_(const char *name) { +void BLEClientBase::log_gattc_lifecycle_event_(const char *name) { ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_%s_EVT", this->connection_index_, this->address_str_, name); } +void BLEClientBase::log_gattc_data_event_(const char *name) { + // Data transfer events are logged at VERBOSE level because logging to UART creates + // delays that cause timing issues during time-sensitive BLE operations. This is + // especially problematic during pairing or firmware updates which require rapid + // writes to many characteristics - the log spam can cause these operations to fail. + ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_%s_EVT", this->connection_index_, this->address_str_, name); +} + void BLEClientBase::log_gattc_warning_(const char *operation, esp_gatt_status_t status) { ESP_LOGW(TAG, "[%d] [%s] %s error, status=%d", this->connection_index_, this->address_str_, operation, status); } @@ -280,7 +288,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_OPEN_EVT: { if (!this->check_addr(param->open.remote_bda)) return false; - this->log_gattc_event_("OPEN"); + this->log_gattc_lifecycle_event_("OPEN"); // conn_id was already set in ESP_GATTC_CONNECT_EVT this->service_count_ = 0; @@ -331,7 +339,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_CONNECT_EVT: { if (!this->check_addr(param->connect.remote_bda)) return false; - this->log_gattc_event_("CONNECT"); + this->log_gattc_lifecycle_event_("CONNECT"); this->conn_id_ = param->connect.conn_id; // Start MTU negotiation immediately as recommended by ESP-IDF examples // (gatt_client, ble_throughput) which call esp_ble_gattc_send_mtu_req in @@ -376,7 +384,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_CLOSE_EVT: { if (this->conn_id_ != param->close.conn_id) return false; - this->log_gattc_event_("CLOSE"); + this->log_gattc_lifecycle_event_("CLOSE"); this->release_services(); this->set_state(espbt::ClientState::IDLE); this->conn_id_ = UNSET_CONN_ID; @@ -404,7 +412,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_SEARCH_CMPL_EVT: { if (this->conn_id_ != param->search_cmpl.conn_id) return false; - this->log_gattc_event_("SEARCH_CMPL"); + this->log_gattc_lifecycle_event_("SEARCH_CMPL"); // For V3_WITHOUT_CACHE, switch back to medium connection parameters after service discovery // This balances performance with bandwidth usage after the critical discovery phase if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) { @@ -431,35 +439,35 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_READ_DESCR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("READ_DESCR"); + this->log_gattc_data_event_("READ_DESCR"); break; } case ESP_GATTC_WRITE_DESCR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("WRITE_DESCR"); + this->log_gattc_data_event_("WRITE_DESCR"); break; } case ESP_GATTC_WRITE_CHAR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("WRITE_CHAR"); + this->log_gattc_data_event_("WRITE_CHAR"); break; } case ESP_GATTC_READ_CHAR_EVT: { if (this->conn_id_ != param->read.conn_id) return false; - this->log_gattc_event_("READ_CHAR"); + this->log_gattc_data_event_("READ_CHAR"); break; } case ESP_GATTC_NOTIFY_EVT: { if (this->conn_id_ != param->notify.conn_id) return false; - this->log_gattc_event_("NOTIFY"); + this->log_gattc_data_event_("NOTIFY"); break; } case ESP_GATTC_REG_FOR_NOTIFY_EVT: { - this->log_gattc_event_("REG_FOR_NOTIFY"); + this->log_gattc_data_event_("REG_FOR_NOTIFY"); if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE || this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) { // Client is responsible for flipping the descriptor value @@ -491,7 +499,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ esp_err_t status = esp_ble_gattc_write_char_descr(this->gattc_if_, this->conn_id_, desc_result.handle, sizeof(notify_en), (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE); - ESP_LOGD(TAG, "Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties); + ESP_LOGV(TAG, "Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties); if (status) { this->log_gattc_warning_("esp_ble_gattc_write_char_descr", status); } @@ -499,13 +507,13 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: { - this->log_gattc_event_("UNREG_FOR_NOTIFY"); + this->log_gattc_data_event_("UNREG_FOR_NOTIFY"); break; } default: - // ideally would check all other events for matching conn_id - ESP_LOGD(TAG, "[%d] [%s] Event %d", this->connection_index_, this->address_str_, event); + // Unknown events logged at VERBOSE to avoid UART delays during time-sensitive operations + ESP_LOGV(TAG, "[%d] [%s] Event %d", this->connection_index_, this->address_str_, event); break; } return true; diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index 92c7444ee1..c52f0e5d2d 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -127,7 +127,8 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { // 6 bytes used, 2 bytes padding void log_event_(const char *name); - void log_gattc_event_(const char *name); + void log_gattc_lifecycle_event_(const char *name); + void log_gattc_data_event_(const char *name); void update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, const char *param_type); void set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, From 42491569c87f8be4ff7a4dd813256b2e7d9893b1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 17:53:53 -1000 Subject: [PATCH 0138/2030] [analyze_memory] Add nRF52/Zephyr platform support for memory analysis (#13249) --- esphome/analyze_memory/__init__.py | 8 ++- esphome/analyze_memory/const.py | 18 ++++++- esphome/analyze_memory/helpers.py | 8 +-- esphome/analyze_memory/toolchain.py | 84 ++++++++++++++++++++++++++++- script/determine-jobs.py | 9 +++- tests/script/test_determine_jobs.py | 30 +++++++++++ 6 files changed, 148 insertions(+), 9 deletions(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index 9c935c78fa..63ef0e74ed 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -22,7 +22,7 @@ from .helpers import ( map_section_name, parse_symbol_line, ) -from .toolchain import find_tool, run_tool +from .toolchain import find_tool, resolve_tool_path, run_tool if TYPE_CHECKING: from esphome.platformio_api import IDEData @@ -132,6 +132,12 @@ class MemoryAnalyzer: readelf_path = readelf_path or idedata.readelf_path _LOGGER.debug("Using toolchain paths from PlatformIO idedata") + # Validate paths exist, fall back to find_tool if they don't + # This handles cases like Zephyr where cc_path doesn't include full path + # and the toolchain prefix may differ (e.g., arm-zephyr-eabi- vs arm-none-eabi-) + objdump_path = resolve_tool_path("objdump", objdump_path, objdump_path) + readelf_path = resolve_tool_path("readelf", readelf_path, objdump_path) + self.objdump_path = objdump_path or "objdump" self.readelf_path = readelf_path or "readelf" self.external_components = external_components or set() diff --git a/esphome/analyze_memory/const.py b/esphome/analyze_memory/const.py index aadc6a231c..83547b1eb5 100644 --- a/esphome/analyze_memory/const.py +++ b/esphome/analyze_memory/const.py @@ -15,6 +15,7 @@ ESPHOME_COMPONENT_PATTERN = re.compile(r"esphome::([a-zA-Z0-9_]+)::") # - LibreTiny RTL87xx: .xip.code_* (flash), .ram.code_* (RAM) # - LibreTiny BK7231: .itcm.code (fast RAM), .vectors (interrupt vectors) # - LibreTiny LN882X: .flash_text, .flash_copy* (flash code) +# - Zephyr/nRF52: text, rodata, datas, bss (no leading dots) SECTION_MAPPING = { ".text": frozenset( [ @@ -30,6 +31,9 @@ SECTION_MAPPING = { # LibreTiny LN882X flash code ".flash_text", ".flash_copy", + # Zephyr/nRF52 sections (no leading dots) + "text", + "rom_start", ] ), ".rodata": frozenset( @@ -37,6 +41,8 @@ SECTION_MAPPING = { ".rodata", # LibreTiny RTL87xx read-only data in RAM ".ram.code_rodata", + # Zephyr/nRF52 sections (no leading dots) + "rodata", ] ), # .bss patterns - must be before .data to catch ".dram0.bss" @@ -45,9 +51,19 @@ SECTION_MAPPING = { ".bss", # LibreTiny LN882X BSS ".bss_ram", + # Zephyr/nRF52 sections (no leading dots) + "bss", + "noinit", + ] + ), + ".data": frozenset( + [ + ".data", + ".dram", + # Zephyr/nRF52 sections (no leading dots) + "datas", ] ), - ".data": frozenset([".data", ".dram"]), } # Section to ComponentMemory attribute mapping diff --git a/esphome/analyze_memory/helpers.py b/esphome/analyze_memory/helpers.py index cb503b37c5..a6ca7e7f0d 100644 --- a/esphome/analyze_memory/helpers.py +++ b/esphome/analyze_memory/helpers.py @@ -94,13 +94,13 @@ def parse_symbol_line(line: str) -> tuple[str, str, int, str] | None: return None # Find section, size, and name + # Try each part as a potential section name for i, part in enumerate(parts): - if not part.startswith("."): - continue - + # Skip parts that are clearly flags, addresses, or other metadata + # Sections start with '.' (standard ELF) or are known section names (Zephyr) section = map_section_name(part) if not section: - break + continue # Need at least size field after section if i + 1 >= len(parts): diff --git a/esphome/analyze_memory/toolchain.py b/esphome/analyze_memory/toolchain.py index 23d85e9700..3a8a5f7be4 100644 --- a/esphome/analyze_memory/toolchain.py +++ b/esphome/analyze_memory/toolchain.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import os from pathlib import Path import subprocess from typing import TYPE_CHECKING @@ -17,10 +18,82 @@ TOOLCHAIN_PREFIXES = [ "xtensa-lx106-elf-", # ESP8266 "xtensa-esp32-elf-", # ESP32 "xtensa-esp-elf-", # ESP32 (newer IDF) + "arm-zephyr-eabi-", # nRF52/Zephyr SDK + "arm-none-eabi-", # Generic ARM (RP2040, etc.) "", # System default (no prefix) ] +def _find_in_platformio_packages(tool_name: str) -> str | None: + """Search for a tool in PlatformIO package directories. + + This handles cases like Zephyr SDK where tools are installed in nested + directories that aren't in PATH. + + Args: + tool_name: Name of the tool (e.g., "readelf", "objdump") + + Returns: + Full path to the tool or None if not found + """ + # Get PlatformIO packages directory + platformio_home = Path(os.path.expanduser("~/.platformio/packages")) + if not platformio_home.exists(): + return None + + # Search patterns for toolchains that might contain the tool + # Order matters - more specific patterns first + search_patterns = [ + # Zephyr SDK deeply nested structure (4 levels) + # e.g., toolchain-gccarmnoneeabi/zephyr-sdk-0.17.4/arm-zephyr-eabi/bin/arm-zephyr-eabi-objdump + f"toolchain-*/*/*/bin/*-{tool_name}", + # Zephyr SDK nested structure (3 levels) + f"toolchain-*/*/bin/*-{tool_name}", + f"toolchain-*/bin/*-{tool_name}", + # Standard PlatformIO toolchain structure + f"toolchain-*/bin/*{tool_name}", + ] + + for pattern in search_patterns: + matches = list(platformio_home.glob(pattern)) + if matches: + # Sort to get consistent results, prefer arm-zephyr-eabi over arm-none-eabi + matches.sort(key=lambda p: ("zephyr" not in str(p), str(p))) + tool_path = str(matches[0]) + _LOGGER.debug("Found %s in PlatformIO packages: %s", tool_name, tool_path) + return tool_path + + return None + + +def resolve_tool_path( + tool_name: str, + derived_path: str | None, + objdump_path: str | None = None, +) -> str | None: + """Resolve a tool path, falling back to find_tool if derived path doesn't exist. + + Args: + tool_name: Name of the tool (e.g., "objdump", "readelf") + derived_path: Path derived from idedata (may not exist for some platforms) + objdump_path: Path to objdump binary to derive other tool paths from + + Returns: + Resolved path to the tool, or the original derived_path if it exists + """ + if derived_path and not Path(derived_path).exists(): + found = find_tool(tool_name, objdump_path) + if found: + _LOGGER.debug( + "Derived %s path %s not found, using %s", + tool_name, + derived_path, + found, + ) + return found + return derived_path + + def find_tool( tool_name: str, objdump_path: str | None = None, @@ -28,7 +101,8 @@ def find_tool( """Find a toolchain tool by name. First tries to derive the tool path from objdump_path (if provided), - then falls back to searching for platform-specific tools. + then searches PlatformIO package directories (for cross-compile toolchains), + and finally falls back to searching for platform-specific tools in PATH. Args: tool_name: Name of the tool (e.g., "objdump", "nm", "c++filt") @@ -47,7 +121,13 @@ def find_tool( _LOGGER.debug("Found %s at: %s", tool_name, potential_path) return potential_path - # Try platform-specific tools + # Search in PlatformIO packages directory first (handles Zephyr SDK, etc.) + # This must come before PATH search because system tools (e.g., /usr/bin/objdump) + # are for the host architecture, not the target (ARM, Xtensa, etc.) + if found := _find_in_platformio_packages(tool_name): + return found + + # Try platform-specific tools in PATH (fallback for when tools are installed globally) for prefix in TOOLCHAIN_PREFIXES: cmd = f"{prefix}{tool_name}" try: diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 7ecbfb225e..318ac04a7d 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -93,6 +93,7 @@ class Platform(StrEnum): RTL87XX_ARD = "rtl87xx-ard" # LibreTiny RTL8720x LN882X_ARD = "ln882x-ard" # LibreTiny LN882x RP2040_ARD = "rp2040-ard" # Raspberry Pi Pico + NRF52_ZEPHYR = "nrf52-adafruit" # Nordic nRF52 (Zephyr) # Memory impact analysis constants @@ -112,7 +113,7 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset( "rtl87xx", # Realtek RTL87xx platform implementation (uses LibreTiny) "ln882x", # Winner Micro LN882x platform implementation (uses LibreTiny) "host", # Host platform (for testing on development machine) - "nrf52", # Nordic nRF52 platform implementation + "nrf52", # Nordic nRF52 platform implementation (uses Zephyr) } ) @@ -126,6 +127,7 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset( # 4-6. Other ESP32 variants - Less commonly used but still supported # 7-9. LibreTiny platforms (BK72XX, RTL87XX, LN882X) - good for detecting LibreTiny-specific changes # 10. RP2040 - Raspberry Pi Pico platform +# 11. nRF52 - Nordic nRF52 with Zephyr (good for detecting Zephyr-specific changes) MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.ESP32_C6_IDF, # ESP32-C6 IDF (newest, supports Thread/Zigbee) Platform.ESP8266_ARD, # ESP8266 Arduino (most memory constrained, fastest builds) @@ -137,6 +139,7 @@ MEMORY_IMPACT_PLATFORM_PREFERENCE = [ Platform.RTL87XX_ARD, # LibreTiny RTL8720x Platform.LN882X_ARD, # LibreTiny LN882x Platform.RP2040_ARD, # Raspberry Pi Pico + Platform.NRF52_ZEPHYR, # Nordic nRF52 (Zephyr) ] @@ -463,6 +466,10 @@ def _detect_platform_hint_from_filename(filename: str) -> Platform | None: if "pico" in filename_lower or "rp2040" in filename_lower: return Platform.RP2040_ARD + # nRF52 / Zephyr + if "nrf52" in filename_lower or "zephyr" in filename_lower: + return Platform.NRF52_ZEPHYR + return None diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 52025513a8..61ef8985df 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -1499,6 +1499,23 @@ def test_detect_memory_impact_config_runs_at_component_limit(tmp_path: Path) -> "tests/components/rp2040/test.rp2040-ard.yaml", determine_jobs.Platform.RP2040_ARD, ), + # nRF52 / Zephyr detection + ( + "tests/components/logger/test.nrf52-adafruit.yaml", + determine_jobs.Platform.NRF52_ZEPHYR, + ), + ( + "esphome/components/nrf52/gpio.cpp", + determine_jobs.Platform.NRF52_ZEPHYR, + ), + ( + "esphome/components/zephyr/core.cpp", + determine_jobs.Platform.NRF52_ZEPHYR, + ), + ( + "esphome/components/zephyr_ble_server/ble_server.cpp", + determine_jobs.Platform.NRF52_ZEPHYR, + ), # No platform hint (generic files) ("esphome/components/wifi/wifi.cpp", None), ("esphome/components/sensor/sensor.h", None), @@ -1528,6 +1545,10 @@ def test_detect_memory_impact_config_runs_at_component_limit(tmp_path: Path) -> "pico_i2c", "pico_spi", "rp2040_test_yaml", + "nrf52_test_yaml", + "nrf52_gpio", + "zephyr_core", + "zephyr_ble_server", "generic_wifi_no_hint", "generic_sensor_no_hint", "core_helpers_no_hint", @@ -1554,6 +1575,11 @@ def test_detect_platform_hint_from_filename( ("file_ESP8266.cpp", determine_jobs.Platform.ESP8266_ARD), # ESP32 with different cases ("file_ESP32.cpp", determine_jobs.Platform.ESP32_IDF), + # nRF52/Zephyr with different cases + ("file_NRF52.cpp", determine_jobs.Platform.NRF52_ZEPHYR), + ("file_Nrf52.cpp", determine_jobs.Platform.NRF52_ZEPHYR), + ("file_ZEPHYR.cpp", determine_jobs.Platform.NRF52_ZEPHYR), + ("file_Zephyr.cpp", determine_jobs.Platform.NRF52_ZEPHYR), ], ids=[ "rp2040_uppercase", @@ -1562,6 +1588,10 @@ def test_detect_platform_hint_from_filename( "pico_titlecase", "esp8266_uppercase", "esp32_uppercase", + "nrf52_uppercase", + "nrf52_mixedcase", + "zephyr_uppercase", + "zephyr_titlecase", ], ) def test_detect_platform_hint_from_filename_case_insensitive( From b37cb812a71a70082a40018a9ad50a56ae6dbd4f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 18:03:11 -1000 Subject: [PATCH 0139/2030] [core] Add buf_append_printf helper for safe buffer formatting (#13258) --- esphome/core/helpers.h | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index d5a04b7eb1..9dc289c743 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1,8 +1,11 @@ #pragma once +#include #include #include +#include #include +#include #include #include #include @@ -18,6 +21,7 @@ #ifdef USE_ESP8266 #include +#include #endif #ifdef USE_RP2040 @@ -568,6 +572,53 @@ std::string __attribute__((format(printf, 1, 3))) str_snprintf(const char *fmt, /// sprintf-like function returning std::string. std::string __attribute__((format(printf, 1, 2))) str_sprintf(const char *fmt, ...); +#ifdef USE_ESP8266 +// ESP8266: Use vsnprintf_P to keep format strings in flash (PROGMEM) +// Format strings must be wrapped with PSTR() macro +/// Safely append formatted string to buffer, returning new position (capped at size). +/// @param buf Output buffer +/// @param size Total buffer size +/// @param pos Current position in buffer +/// @param fmt Format string (must be in PROGMEM on ESP8266) +/// @return New position after appending (capped at size on overflow) +inline size_t buf_append_printf_p(char *buf, size_t size, size_t pos, PGM_P fmt, ...) { + if (pos >= size) { + return size; + } + va_list args; + va_start(args, fmt); + int written = vsnprintf_P(buf + pos, size - pos, fmt, args); + va_end(args); + if (written < 0) { + return pos; // encoding error + } + return std::min(pos + static_cast(written), size); +} +#define buf_append_printf(buf, size, pos, fmt, ...) buf_append_printf_p(buf, size, pos, PSTR(fmt), ##__VA_ARGS__) +#else +/// Safely append formatted string to buffer, returning new position (capped at size). +/// Handles snprintf edge cases: negative returns (encoding errors) and truncation. +/// @param buf Output buffer +/// @param size Total buffer size +/// @param pos Current position in buffer +/// @param fmt printf-style format string +/// @return New position after appending (capped at size on overflow) +__attribute__((format(printf, 4, 5))) inline size_t buf_append_printf(char *buf, size_t size, size_t pos, + const char *fmt, ...) { + if (pos >= size) { + return size; + } + va_list args; + va_start(args, fmt); + int written = vsnprintf(buf + pos, size - pos, fmt, args); + va_end(args); + if (written < 0) { + return pos; // encoding error + } + return std::min(pos + static_cast(written), size); +} +#endif + /// Concatenate a name with a separator and suffix using an efficient stack-based approach. /// This avoids multiple heap allocations during string construction. /// Maximum name length supported is 120 characters for friendly names. From 14b7539094833cd5fab4e09852cce72639399dad Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 15 Jan 2026 22:04:21 -0600 Subject: [PATCH 0140/2030] [infrared, remote_base] Optimize IR transmit path for `web_server` base85 data (#13238) --- esphome/components/infrared/infrared.cpp | 21 ++++++++- esphome/components/infrared/infrared.h | 43 +++++++++++++++---- .../components/remote_base/remote_base.cpp | 4 ++ esphome/components/remote_base/remote_base.h | 5 +++ 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 5f8d63926a..294d69e523 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -18,7 +18,15 @@ InfraredCall &InfraredCall::set_carrier_frequency(uint32_t frequency) { InfraredCall &InfraredCall::set_raw_timings(const std::vector &timings) { this->raw_timings_ = &timings; - this->packed_data_ = nullptr; // Clear packed if vector is set + this->packed_data_ = nullptr; + this->base85_ptr_ = nullptr; + return *this; +} + +InfraredCall &InfraredCall::set_raw_timings_base85(const std::string &base85) { + this->base85_ptr_ = &base85; + this->raw_timings_ = nullptr; + this->packed_data_ = nullptr; return *this; } @@ -26,7 +34,8 @@ InfraredCall &InfraredCall::set_raw_timings_packed(const uint8_t *data, uint16_t this->packed_data_ = data; this->packed_length_ = length; this->packed_count_ = count; - this->raw_timings_ = nullptr; // Clear vector if packed is set + this->raw_timings_ = nullptr; + this->base85_ptr_ = nullptr; return *this; } @@ -92,6 +101,14 @@ void Infrared::control(const InfraredCall &call) { call.get_packed_count()); ESP_LOGD(TAG, "Transmitting packed raw timings: count=%u, repeat=%u", call.get_packed_count(), call.get_repeat_count()); + } else if (call.is_base85()) { + // Decode base85 directly into transmit buffer (zero heap allocations) + if (!transmit_data->set_data_from_base85(call.get_base85_data())) { + ESP_LOGE(TAG, "Invalid base85 data"); + return; + } + ESP_LOGD(TAG, "Transmitting base85 raw timings: count=%zu, repeat=%u", transmit_data->get_data().size(), + call.get_repeat_count()); } else { // From vector (lambdas/automations) transmit_data->set_data(call.get_raw_timings()); diff --git a/esphome/components/infrared/infrared.h b/esphome/components/infrared/infrared.h index 3a891301f4..ba426c9daa 100644 --- a/esphome/components/infrared/infrared.h +++ b/esphome/components/infrared/infrared.h @@ -28,12 +28,29 @@ class InfraredCall { /// Set the carrier frequency in Hz InfraredCall &set_carrier_frequency(uint32_t frequency); - /// Set the raw timings (positive = mark, negative = space) - /// Note: The timings vector must outlive the InfraredCall (zero-copy reference) + + // ===== Raw Timings Methods ===== + // All set_raw_timings_* methods store pointers/references to external data. + // The referenced data must remain valid until perform() completes. + // Safe pattern: call.set_raw_timings_xxx(data); call.perform(); // synchronous + // Unsafe pattern: call.set_raw_timings_xxx(data); defer([call]() { call.perform(); }); // data may be gone! + + /// Set the raw timings from a vector (positive = mark, negative = space) + /// @note Lifetime: Stores a pointer to the vector. The vector must outlive perform(). + /// @note Usage: Primarily for lambdas/automations where the vector is in scope. InfraredCall &set_raw_timings(const std::vector &timings); - /// Set the raw timings from packed protobuf sint32 data (zero-copy from wire) - /// Note: The data must outlive the InfraredCall + + /// Set the raw timings from base85-encoded int32 data + /// @note Lifetime: Stores a pointer to the string. The string must outlive perform(). + /// @note Usage: For web_server where the encoded string is on the stack. + /// @note Decoding happens at perform() time, directly into the transmit buffer. + InfraredCall &set_raw_timings_base85(const std::string &base85); + + /// Set the raw timings from packed protobuf sint32 data (zigzag + varint encoded) + /// @note Lifetime: Stores a pointer to the buffer. The buffer must outlive perform(). + /// @note Usage: For API component where data comes directly from the protobuf message. InfraredCall &set_raw_timings_packed(const uint8_t *data, uint16_t length, uint16_t count); + /// Set the number of times to repeat transmission (1 = transmit once, 2 = transmit twice, etc.) InfraredCall &set_repeat_count(uint32_t count); @@ -42,12 +59,18 @@ class InfraredCall { /// Get the carrier frequency const optional &get_carrier_frequency() const { return this->carrier_frequency_; } - /// Get the raw timings (only valid if set via set_raw_timings, not packed) + /// Get the raw timings (only valid if set via set_raw_timings, not packed or base85) const std::vector &get_raw_timings() const { return *this->raw_timings_; } - /// Check if raw timings have been set (either vector or packed) - bool has_raw_timings() const { return this->raw_timings_ != nullptr || this->packed_data_ != nullptr; } + /// Check if raw timings have been set (vector, packed, or base85) + bool has_raw_timings() const { + return this->raw_timings_ != nullptr || this->packed_data_ != nullptr || this->base85_ptr_ != nullptr; + } /// Check if using packed data format bool is_packed() const { return this->packed_data_ != nullptr; } + /// Check if using base85 data format + bool is_base85() const { return this->base85_ptr_ != nullptr; } + /// Get the base85 data string + const std::string &get_base85_data() const { return *this->base85_ptr_; } /// Get packed data (only valid if set via set_raw_timings_packed) const uint8_t *get_packed_data() const { return this->packed_data_; } uint16_t get_packed_length() const { return this->packed_length_; } @@ -59,9 +82,11 @@ class InfraredCall { uint32_t repeat_count_{1}; Infrared *parent_; optional carrier_frequency_; - // Vector-based timings (for lambdas/automations) + // Pointer to vector-based timings (caller-owned, must outlive perform()) const std::vector *raw_timings_{nullptr}; - // Packed protobuf timings (for API zero-copy) + // Pointer to base85-encoded string (caller-owned, must outlive perform()) + const std::string *base85_ptr_{nullptr}; + // Pointer to packed protobuf buffer (caller-owned, must outlive perform()) const uint8_t *packed_data_{nullptr}; uint16_t packed_length_{0}; uint16_t packed_count_{0}; diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 2f1c107bf4..e3d9463243 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -159,6 +159,10 @@ void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t } } +bool RemoteTransmitData::set_data_from_base85(const std::string &base85) { + return base85_decode_int32_vector(base85, this->data_); +} + /* RemoteTransmitterBase */ void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index a11e0271af..2d7642cc31 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -36,6 +36,11 @@ class RemoteTransmitData { /// @param len Length of the buffer in bytes /// @param count Number of values (for reserve optimization) void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count); + /// Set data from base85-encoded int32 values + /// Decodes directly into internal buffer (zero heap allocations) + /// @param base85 Base85-encoded string (5 chars per int32 value) + /// @return true if successful, false if decode failed or invalid size + bool set_data_from_base85(const std::string &base85); void reset() { this->data_.clear(); this->carrier_frequency_ = 0; From 8263a8273ff034a2f8c6684914c6da6906a45001 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 18:08:26 -1000 Subject: [PATCH 0141/2030] [debug] Add min_free heap sensor for ESP32 and LibreTiny, add fragmentation for ESP32 (#13231) --- esphome/components/debug/debug_component.h | 10 ++++-- esphome/components/debug/debug_esp32.cpp | 13 +++++++- esphome/components/debug/debug_libretiny.cpp | 3 ++ esphome/components/debug/sensor.py | 31 +++++++++++++++++-- tests/components/debug/common.yaml | 2 ++ tests/components/debug/test.bk72xx-ard.yaml | 5 +++ tests/components/debug/test.esp32-ard.yaml | 7 +++++ tests/components/debug/test.esp32-idf.yaml | 4 +++ tests/components/debug/test.esp32-s2-idf.yaml | 7 +++++ tests/components/debug/test.esp8266-ard.yaml | 5 +++ tests/components/debug/test.ln882x-ard.yaml | 5 +++ tests/components/debug/test.rtl87xx-ard.yaml | 6 ++++ 12 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 tests/components/debug/test.rtl87xx-ard.yaml diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 5783bc5418..6cf52d890c 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -74,8 +74,11 @@ class DebugComponent : public PollingComponent { #ifdef USE_SENSOR void set_free_sensor(sensor::Sensor *free_sensor) { free_sensor_ = free_sensor; } void set_block_sensor(sensor::Sensor *block_sensor) { block_sensor_ = block_sensor; } -#if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2) +#if (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)) || defined(USE_ESP32) void set_fragmentation_sensor(sensor::Sensor *fragmentation_sensor) { fragmentation_sensor_ = fragmentation_sensor; } +#endif +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + void set_min_free_sensor(sensor::Sensor *min_free_sensor) { min_free_sensor_ = min_free_sensor; } #endif void set_loop_time_sensor(sensor::Sensor *loop_time_sensor) { loop_time_sensor_ = loop_time_sensor; } #ifdef USE_ESP32 @@ -97,8 +100,11 @@ class DebugComponent : public PollingComponent { sensor::Sensor *free_sensor_{nullptr}; sensor::Sensor *block_sensor_{nullptr}; -#if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2) +#if (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)) || defined(USE_ESP32) sensor::Sensor *fragmentation_sensor_{nullptr}; +#endif +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + sensor::Sensor *min_free_sensor_{nullptr}; #endif sensor::Sensor *loop_time_sensor_{nullptr}; #ifdef USE_ESP32 diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index ebb6abf4da..8c41011f7d 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -234,8 +234,19 @@ size_t DebugComponent::get_device_info_(std::span void DebugComponent::update_platform_() { #ifdef USE_SENSOR + uint32_t max_alloc = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL); if (this->block_sensor_ != nullptr) { - this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL)); + this->block_sensor_->publish_state(max_alloc); + } + if (this->min_free_sensor_ != nullptr) { + this->min_free_sensor_->publish_state(heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL)); + } + if (this->fragmentation_sensor_ != nullptr) { + uint32_t free_heap = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + if (free_heap > 0) { + float fragmentation = 100.0f - (100.0f * max_alloc / free_heap); + this->fragmentation_sensor_->publish_state(fragmentation); + } } if (this->psram_sensor_ != nullptr) { this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index 4f07a4cc17..aae27c8ca2 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -51,6 +51,9 @@ void DebugComponent::update_platform_() { if (this->block_sensor_ != nullptr) { this->block_sensor_->publish_state(lt_heap_get_max_alloc()); } + if (this->min_free_sensor_ != nullptr) { + this->min_free_sensor_->publish_state(lt_heap_get_min_free()); + } #endif } diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index 6a8e2cd828..0a716d666e 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -11,6 +11,9 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, ICON_COUNTER, ICON_TIMER, + PLATFORM_BK72XX, + PLATFORM_LN882X, + PLATFORM_RTL87XX, UNIT_BYTES, UNIT_HERTZ, UNIT_MILLISECOND, @@ -25,6 +28,7 @@ from . import ( # noqa: F401 pylint: disable=unused-import DEPENDENCIES = ["debug"] +CONF_MIN_FREE = "min_free" CONF_PSRAM = "psram" CONFIG_SCHEMA = { @@ -42,8 +46,14 @@ CONFIG_SCHEMA = { entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), cv.Optional(CONF_FRAGMENTATION): cv.All( - cv.only_on_esp8266, - cv.require_framework_version(esp8266_arduino=cv.Version(2, 5, 2)), + cv.Any( + cv.All( + cv.only_on_esp8266, + cv.require_framework_version(esp8266_arduino=cv.Version(2, 5, 2)), + ), + cv.only_on_esp32, + msg="This feature is only available on ESP8266 (Arduino 2.5.2+) and ESP32", + ), sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, icon=ICON_COUNTER, @@ -51,6 +61,19 @@ CONFIG_SCHEMA = { entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), ), + cv.Optional(CONF_MIN_FREE): cv.All( + cv.Any( + cv.only_on_esp32, + cv.only_on([PLATFORM_BK72XX, PLATFORM_LN882X, PLATFORM_RTL87XX]), + msg="This feature is only available on ESP32 and LibreTiny (BK72xx, LN882x, RTL87xx)", + ), + sensor.sensor_schema( + unit_of_measurement=UNIT_BYTES, + icon=ICON_COUNTER, + accuracy_decimals=0, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + ), cv.Optional(CONF_LOOP_TIME): sensor.sensor_schema( unit_of_measurement=UNIT_MILLISECOND, icon=ICON_TIMER, @@ -93,6 +116,10 @@ async def to_code(config): sens = await sensor.new_sensor(fragmentation_conf) cg.add(debug_component.set_fragmentation_sensor(sens)) + if min_free_conf := config.get(CONF_MIN_FREE): + sens = await sensor.new_sensor(min_free_conf) + cg.add(debug_component.set_min_free_sensor(sens)) + if loop_time_conf := config.get(CONF_LOOP_TIME): sens = await sensor.new_sensor(loop_time_conf) cg.add(debug_component.set_loop_time_sensor(sens)) diff --git a/tests/components/debug/common.yaml b/tests/components/debug/common.yaml index d9a61f8df0..59ba39c3a4 100644 --- a/tests/components/debug/common.yaml +++ b/tests/components/debug/common.yaml @@ -11,6 +11,8 @@ sensor: - platform: debug free: name: "Heap Free" + block: + name: "Heap Block" loop_time: name: "Loop Time" cpu_frequency: diff --git a/tests/components/debug/test.bk72xx-ard.yaml b/tests/components/debug/test.bk72xx-ard.yaml index dade44d145..fdae374788 100644 --- a/tests/components/debug/test.bk72xx-ard.yaml +++ b/tests/components/debug/test.bk72xx-ard.yaml @@ -1 +1,6 @@ <<: !include common.yaml + +sensor: + - platform: debug + min_free: + name: "Heap Min Free" diff --git a/tests/components/debug/test.esp32-ard.yaml b/tests/components/debug/test.esp32-ard.yaml index 8e19a4d627..8f93b0925e 100644 --- a/tests/components/debug/test.esp32-ard.yaml +++ b/tests/components/debug/test.esp32-ard.yaml @@ -2,3 +2,10 @@ esp32: cpu_frequency: 240MHz + +sensor: + - platform: debug + fragmentation: + name: "Heap Fragmentation" + min_free: + name: "Heap Min Free" diff --git a/tests/components/debug/test.esp32-idf.yaml b/tests/components/debug/test.esp32-idf.yaml index f7483a54b3..6a9996ad06 100644 --- a/tests/components/debug/test.esp32-idf.yaml +++ b/tests/components/debug/test.esp32-idf.yaml @@ -9,5 +9,9 @@ sensor: name: "Heap Free" psram: name: "Free PSRAM" + fragmentation: + name: "Heap Fragmentation" + min_free: + name: "Heap Min Free" psram: diff --git a/tests/components/debug/test.esp32-s2-idf.yaml b/tests/components/debug/test.esp32-s2-idf.yaml index dade44d145..80919b0bab 100644 --- a/tests/components/debug/test.esp32-s2-idf.yaml +++ b/tests/components/debug/test.esp32-s2-idf.yaml @@ -1 +1,8 @@ <<: !include common.yaml + +sensor: + - platform: debug + fragmentation: + name: "Heap Fragmentation" + min_free: + name: "Heap Min Free" diff --git a/tests/components/debug/test.esp8266-ard.yaml b/tests/components/debug/test.esp8266-ard.yaml index dade44d145..1398087bf0 100644 --- a/tests/components/debug/test.esp8266-ard.yaml +++ b/tests/components/debug/test.esp8266-ard.yaml @@ -1 +1,6 @@ <<: !include common.yaml + +sensor: + - platform: debug + fragmentation: + name: "Heap Fragmentation" diff --git a/tests/components/debug/test.ln882x-ard.yaml b/tests/components/debug/test.ln882x-ard.yaml index dade44d145..fdae374788 100644 --- a/tests/components/debug/test.ln882x-ard.yaml +++ b/tests/components/debug/test.ln882x-ard.yaml @@ -1 +1,6 @@ <<: !include common.yaml + +sensor: + - platform: debug + min_free: + name: "Heap Min Free" diff --git a/tests/components/debug/test.rtl87xx-ard.yaml b/tests/components/debug/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..fdae374788 --- /dev/null +++ b/tests/components/debug/test.rtl87xx-ard.yaml @@ -0,0 +1,6 @@ +<<: !include common.yaml + +sensor: + - platform: debug + min_free: + name: "Heap Min Free" From 68affe0b9c0c99f91c1e3ee456c1d233bad20607 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 18:55:32 -1000 Subject: [PATCH 0142/2030] [core] Add --device hint when DNS resolution fails (#13240) --- esphome/__main__.py | 7 ++++++- esphome/espota2.py | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 3849a585ca..545464be10 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -222,8 +222,13 @@ def choose_upload_log_host( else: resolved.append(device) if not resolved: + if CORE.dashboard: + hint = "If you know the IP, set 'use_address' in your network config." + else: + hint = "If you know the IP, try --device " raise EsphomeError( - f"All specified devices {defaults} could not be resolved. Is the device connected to the network?" + f"All specified devices {defaults} could not be resolved. " + f"Is the device connected to the network? {hint}" ) return resolved diff --git a/esphome/espota2.py b/esphome/espota2.py index 6349ad0fa8..95dd602ad2 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -400,6 +400,8 @@ def run_ota_impl_( "Error resolving IP address of %s. Is it connected to WiFi?", remote_host, ) + if not CORE.dashboard: + _LOGGER.error("(If you know the IP, try --device )") _LOGGER.error( "(If this error persists, please set a static IP address: " "https://esphome.io/components/wifi/#manual-ips)" From 5b37d2fb274bd8e873cb7bbe9dc6fedf9259e767 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 16 Jan 2026 02:55:24 -0600 Subject: [PATCH 0143/2030] [helpers] Support `base64url` encoding (#13264) --- esphome/core/helpers.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index b5bf849c30..96b2d46d78 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -487,19 +487,26 @@ static constexpr const char *BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; -// Helper function to find the index of a base64 character in the lookup table. +// Helper function to find the index of a base64/base64url character in the lookup table. // Returns the character's position (0-63) if found, or 0 if not found. +// Supports both standard base64 (+/) and base64url (-_) alphabets. // NOTE: This returns 0 for both 'A' (valid base64 char at index 0) and invalid characters. // This is safe because is_base64() is ALWAYS checked before calling this function, // preventing invalid characters from ever reaching here. The base64_decode function // stops processing at the first invalid character due to the is_base64() check in its // while loop condition, making this edge case harmless in practice. static inline uint8_t base64_find_char(char c) { + // Handle base64url variants: '-' maps to '+' (index 62), '_' maps to '/' (index 63) + if (c == '-') + return 62; + if (c == '_') + return 63; const char *pos = strchr(BASE64_CHARS, c); return pos ? (pos - BASE64_CHARS) : 0; } -static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/')); } +// Check if character is valid base64 or base64url +static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == '/') || (c == '-') || (c == '_')); } std::string base64_encode(const std::vector &buf) { return base64_encode(buf.data(), buf.size()); } From 4906f87751a4670e08f4e254be647cc96b389fb8 Mon Sep 17 00:00:00 2001 From: Remco van Essen Date: Fri, 16 Jan 2026 11:17:32 +0100 Subject: [PATCH 0144/2030] [mipi_dsi] add JC8012P4A1 (#13241) --- esphome/components/mipi_dsi/models/guition.py | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) diff --git a/esphome/components/mipi_dsi/models/guition.py b/esphome/components/mipi_dsi/models/guition.py index cd566633f9..db13c7f6cc 100644 --- a/esphome/components/mipi_dsi/models/guition.py +++ b/esphome/components/mipi_dsi/models/guition.py @@ -101,4 +101,225 @@ DriverChip( (0xFF, 0x77, 0x01, 0x00, 0x00, 0x00), ] ) + +# jc8012P4A1 Driver Configuration (jd9365) +# Using parameters from esp_lcd_jd9365.h and the working full init sequence +# ---------------------------------------------------------------------------------------------------------------------- +# * Resolution: 800x1280 +# * PCLK Frequency: 60 MHz +# * DSI Lane Bit Rate: 1 Gbps (using 2-Lane DSI configuration) +# * Horizontal Timing (hsync_pulse_width=20, hsync_back_porch=20, hsync_front_porch=40) +# * Vertical Timing (vsync_pulse_width=4, vsync_back_porch=8, vsync_front_porch=20) +# ---------------------------------------------------------------------------------------------------------------------- +DriverChip( + "JC8012P4A1", + width=800, + height=1280, + hsync_back_porch=20, + hsync_pulse_width=20, + hsync_front_porch=40, + vsync_back_porch=8, + vsync_pulse_width=4, + vsync_front_porch=20, + pclk_frequency="60MHz", + lane_bit_rate="1Gbps", + swap_xy=cv.UNDEFINED, + color_order="RGB", + reset_pin=27, + initsequence=[ + (0xE0, 0x00), + (0xE1, 0x93), + (0xE2, 0x65), + (0xE3, 0xF8), + (0x80, 0x01), + (0xE0, 0x01), + (0x00, 0x00), + (0x01, 0x39), + (0x03, 0x10), + (0x04, 0x41), + (0x0C, 0x74), + (0x17, 0x00), + (0x18, 0xD7), + (0x19, 0x00), + (0x1A, 0x00), + (0x1B, 0xD7), + (0x1C, 0x00), + (0x24, 0xFE), + (0x35, 0x26), + (0x37, 0x69), + (0x38, 0x05), + (0x39, 0x06), + (0x3A, 0x08), + (0x3C, 0x78), + (0x3D, 0xFF), + (0x3E, 0xFF), + (0x3F, 0xFF), + (0x40, 0x06), + (0x41, 0xA0), + (0x43, 0x14), + (0x44, 0x0B), + (0x45, 0x30), + (0x4B, 0x04), + (0x55, 0x02), + (0x57, 0x89), + (0x59, 0x0A), + (0x5A, 0x28), + (0x5B, 0x15), + (0x5D, 0x50), + (0x5E, 0x37), + (0x5F, 0x29), + (0x60, 0x1E), + (0x61, 0x1D), + (0x62, 0x12), + (0x63, 0x1A), + (0x64, 0x08), + (0x65, 0x25), + (0x66, 0x26), + (0x67, 0x28), + (0x68, 0x49), + (0x69, 0x3A), + (0x6A, 0x43), + (0x6B, 0x3A), + (0x6C, 0x3B), + (0x6D, 0x32), + (0x6E, 0x1F), + (0x6F, 0x0E), + (0x70, 0x50), + (0x71, 0x37), + (0x72, 0x29), + (0x73, 0x1E), + (0x74, 0x1D), + (0x75, 0x12), + (0x76, 0x1A), + (0x77, 0x08), + (0x78, 0x25), + (0x79, 0x26), + (0x7A, 0x28), + (0x7B, 0x49), + (0x7C, 0x3A), + (0x7D, 0x43), + (0x7E, 0x3A), + (0x7F, 0x3B), + (0x80, 0x32), + (0x81, 0x1F), + (0x82, 0x0E), + (0xE0, 0x02), + (0x00, 0x1F), + (0x01, 0x1F), + (0x02, 0x52), + (0x03, 0x51), + (0x04, 0x50), + (0x05, 0x4B), + (0x06, 0x4A), + (0x07, 0x49), + (0x08, 0x48), + (0x09, 0x47), + (0x0A, 0x46), + (0x0B, 0x45), + (0x0C, 0x44), + (0x0D, 0x40), + (0x0E, 0x41), + (0x0F, 0x1F), + (0x10, 0x1F), + (0x11, 0x1F), + (0x12, 0x1F), + (0x13, 0x1F), + (0x14, 0x1F), + (0x15, 0x1F), + (0x16, 0x1F), + (0x17, 0x1F), + (0x18, 0x52), + (0x19, 0x51), + (0x1A, 0x50), + (0x1B, 0x4B), + (0x1C, 0x4A), + (0x1D, 0x49), + (0x1E, 0x48), + (0x1F, 0x47), + (0x20, 0x46), + (0x21, 0x45), + (0x22, 0x44), + (0x23, 0x40), + (0x24, 0x41), + (0x25, 0x1F), + (0x26, 0x1F), + (0x27, 0x1F), + (0x28, 0x1F), + (0x29, 0x1F), + (0x2A, 0x1F), + (0x2B, 0x1F), + (0x2C, 0x1F), + (0x2D, 0x1F), + (0x2E, 0x52), + (0x2F, 0x40), + (0x30, 0x41), + (0x31, 0x48), + (0x32, 0x49), + (0x33, 0x4A), + (0x34, 0x4B), + (0x35, 0x44), + (0x36, 0x45), + (0x37, 0x46), + (0x38, 0x47), + (0x39, 0x51), + (0x3A, 0x50), + (0x3B, 0x1F), + (0x3C, 0x1F), + (0x3D, 0x1F), + (0x3E, 0x1F), + (0x3F, 0x1F), + (0x40, 0x1F), + (0x41, 0x1F), + (0x42, 0x1F), + (0x43, 0x1F), + (0x44, 0x52), + (0x45, 0x40), + (0x46, 0x41), + (0x47, 0x48), + (0x48, 0x49), + (0x49, 0x4A), + (0x4A, 0x4B), + (0x4B, 0x44), + (0x4C, 0x45), + (0x4D, 0x46), + (0x4E, 0x47), + (0x4F, 0x51), + (0x50, 0x50), + (0x51, 0x1F), + (0x52, 0x1F), + (0x53, 0x1F), + (0x54, 0x1F), + (0x55, 0x1F), + (0x56, 0x1F), + (0x57, 0x1F), + (0x58, 0x40), + (0x59, 0x00), + (0x5A, 0x00), + (0x5B, 0x10), + (0x5C, 0x05), + (0x5D, 0x50), + (0x5E, 0x01), + (0x5F, 0x02), + (0x60, 0x50), + (0x61, 0x06), + (0x62, 0x04), + (0x63, 0x03), + (0x64, 0x64), + (0x65, 0x65), + (0x66, 0x0B), + (0x67, 0x73), + (0x68, 0x07), + (0x69, 0x06), + (0x6A, 0x64), + (0x6B, 0x08), + (0x6C, 0x00), + (0x6D, 0x32), + (0x6E, 0x08), + (0xE0, 0x04), + (0x2C, 0x6B), + (0x35, 0x08), + (0x37, 0x00), + (0xE0, 0x00), + ] +) # fmt: on From 16adae7359983dac9b9732109a65217b13797d11 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Sat, 17 Jan 2026 01:19:09 +1000 Subject: [PATCH 0145/2030] [ntc, resistance] change log level to verbose (#13268) --- esphome/components/ntc/ntc.cpp | 2 +- esphome/components/resistance/resistance_sensor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ntc/ntc.cpp b/esphome/components/ntc/ntc.cpp index b08f84029b..cc500ba429 100644 --- a/esphome/components/ntc/ntc.cpp +++ b/esphome/components/ntc/ntc.cpp @@ -23,7 +23,7 @@ void NTC::process_(float value) { double v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr; auto temp = float(1.0 / v - 273.15); - ESP_LOGD(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp); + ESP_LOGV(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp); this->publish_state(temp); } diff --git a/esphome/components/resistance/resistance_sensor.cpp b/esphome/components/resistance/resistance_sensor.cpp index 6e57214449..706a059de3 100644 --- a/esphome/components/resistance/resistance_sensor.cpp +++ b/esphome/components/resistance/resistance_sensor.cpp @@ -39,7 +39,7 @@ void ResistanceSensor::process_(float value) { } res *= this->resistor_; - ESP_LOGD(TAG, "'%s' - Resistance %.1fΩ", this->name_.c_str(), res); + ESP_LOGV(TAG, "'%s' - Resistance %.1fΩ", this->name_.c_str(), res); this->publish_state(res); } From 916b028fb276718294fe356673a4a18a707d0599 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 08:30:22 -1000 Subject: [PATCH 0146/2030] [mqtt] Replace sprintf with snprintf for friendly name hash (#13262) --- esphome/components/mqtt/mqtt_component.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 20c111de43..8e4b3437ab 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -189,8 +189,7 @@ bool MQTTComponent::send_discovery_() { StringRef object_id = this->get_default_object_id_to_(object_id_buf); if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) { char friendly_name_hash[9]; - sprintf(friendly_name_hash, "%08" PRIx32, fnv1_hash(this->friendly_name_())); - friendly_name_hash[8] = 0; // ensure the hash-string ends with null + snprintf(friendly_name_hash, sizeof(friendly_name_hash), "%08" PRIx32, fnv1_hash(this->friendly_name_())); // Format: mac-component_type-hash (e.g. "aabbccddeeff-sensor-12345678") // MAC (12) + "-" (1) + domain (max 20) + "-" (1) + hash (8) + null (1) = 43 char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11]; From bc78f80f779c78fb4afa7efad313bd8f10d90420 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 09:36:29 -1000 Subject: [PATCH 0147/2030] Bump actions/cache from 5.0.1 to 5.0.2 (#13276) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 434aa388f7..81d3c826d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: venv # yamllint disable-line rule:line-length @@ -157,7 +157,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Save Python virtual environment cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: venv key: ${{ runner.os }}-${{ steps.restore-python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -193,7 +193,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Restore components graph cache - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -223,7 +223,7 @@ jobs: echo "component-test-batches=$(echo "$output" | jq -c '.component_test_batches')" >> $GITHUB_OUTPUT - name: Save components graph cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -245,7 +245,7 @@ jobs: python-version: "3.13" - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: venv key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -334,14 +334,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} @@ -413,14 +413,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -502,14 +502,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -735,7 +735,7 @@ jobs: - name: Restore cached memory analysis id: cache-memory-analysis if: steps.check-script.outputs.skip != 'true' - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -759,7 +759,7 @@ jobs: - name: Cache platformio if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} @@ -800,7 +800,7 @@ jobs: - name: Save memory analysis to cache if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success' - uses: actions/cache/save@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -847,7 +847,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} From 3057a0484fb2e68639c43305a7fc8ac22d1be6ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 09:36:42 -1000 Subject: [PATCH 0148/2030] Bump actions/cache from 5.0.1 to 5.0.2 in /.github/actions/restore-python (#13277) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/restore-python/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index 75586fd854..370c8bcc46 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -22,7 +22,7 @@ runs: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 with: path: venv # yamllint disable-line rule:line-length From 6832efbacca0d64cc53cb68a811a332eaee0b62b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 16 Jan 2026 15:24:28 -0500 Subject: [PATCH 0149/2030] Add Claude Code PR workflow skill (#13271) Co-authored-by: Claude Opus 4.5 --- .claude/skills/pr-workflow/SKILL.md | 96 +++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 .claude/skills/pr-workflow/SKILL.md diff --git a/.claude/skills/pr-workflow/SKILL.md b/.claude/skills/pr-workflow/SKILL.md new file mode 100644 index 0000000000..4ec2551804 --- /dev/null +++ b/.claude/skills/pr-workflow/SKILL.md @@ -0,0 +1,96 @@ +--- +name: pr-workflow +description: Create pull requests for esphome. Use when creating PRs, submitting changes, or preparing contributions. +allowed-tools: Read, Bash, Glob, Grep +--- + +# ESPHome PR Workflow + +When creating a pull request for esphome, follow these steps: + +## 1. Create Branch from Upstream + +Always base your branch on **upstream** (not origin/fork) to ensure you have the latest code: + +```bash +git fetch upstream +git checkout -b upstream/dev +``` + +## 2. Read the PR Template + +Before creating a PR, read `.github/PULL_REQUEST_TEMPLATE.md` to understand required fields. + +## 3. Create the PR + +Use `gh pr create` with the **full template** filled in. Never skip or abbreviate sections. + +Required fields: +- **What does this implement/fix?**: Brief description of changes +- **Types of changes**: Check ONE appropriate box (Bugfix, New feature, Breaking change, etc.) +- **Related issue**: Use `fixes ` syntax if applicable +- **Pull request in esphome-docs**: Link if docs are needed +- **Test Environment**: Check platforms you tested on +- **Example config.yaml**: Include working example YAML +- **Checklist**: Verify code is tested and tests added + +## 4. Example PR Body + +```markdown +# What does this implement/fix? + + + +## Types of changes + +- [ ] Bugfix (non-breaking change which fixes an issue) +- [x] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Developer breaking change (an API change that could break external components) +- [ ] Code quality improvements to existing code or addition of tests +- [ ] Other + +**Related issue or feature (if applicable):** + +- fixes https://github.com/esphome/esphome/issues/XXX + +**Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** + +- esphome/esphome-docs#XXX + +## Test Environment + +- [x] ESP32 +- [x] ESP32 IDF +- [ ] ESP8266 +- [ ] RP2040 +- [ ] BK72xx +- [ ] RTL87xx +- [ ] LN882x +- [ ] nRF52840 + +## Example entry for `config.yaml`: + +```yaml +# Example config.yaml +component_name: + id: my_component + option: value +``` + +## Checklist: + - [x] The code change is tested and works locally. + - [x] Tests have been added to verify that the new code works (under `tests/` folder). + +If user exposed functionality or configuration variables are added/changed: + - [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs). +``` + +## 5. Push and Create PR + +```bash +git push -u origin +gh pr create --repo esphome/esphome --base dev --title "[component] Brief description" +``` + +Title should be prefixed with the component name in brackets, e.g. `[safe_mode] Add feature`. From a6808841389508ba06bd01ba32ea059c12dc032d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:29:02 +0000 Subject: [PATCH 0150/2030] Bump ruff from 0.14.12 to 0.14.13 (#13275) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3295cf070a..06f9bf2a5b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.14.11 + rev: v0.14.13 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index e0bc943ab4..d93a5d108f 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.12 # also change in .pre-commit-config.yaml when updating +ruff==0.14.13 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From c5e4a608849e2bb956bd20da40d1229c1543b4f5 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 17 Jan 2026 08:35:40 +1100 Subject: [PATCH 0151/2030] [select] Add condition for testing select option (#13267) Co-authored-by: J. Nick Koston --- esphome/components/select/__init__.py | 45 +++++++++++++++++++++- esphome/components/select/automation.h | 30 +++++++++++++++ tests/components/template/common-base.yaml | 12 ++++++ 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 7c50fe02c0..c51131a292 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -8,17 +8,20 @@ from esphome.const import ( CONF_ICON, CONF_ID, CONF_INDEX, + CONF_LAMBDA, CONF_MODE, CONF_MQTT_ID, CONF_ON_VALUE, CONF_OPERATION, CONF_OPTION, + CONF_OPTIONS, CONF_TRIGGER_ID, CONF_WEB_SERVER, ) -from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity -from esphome.cpp_generator import MockObjClass +from esphome.cpp_generator import MockObjClass, TemplateArguments +from esphome.cpp_types import global_ns CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True @@ -38,6 +41,9 @@ SelectSetAction = select_ns.class_("SelectSetAction", automation.Action) SelectSetIndexAction = select_ns.class_("SelectSetIndexAction", automation.Action) SelectOperationAction = select_ns.class_("SelectOperationAction", automation.Action) +# Conditions +SelectIsCondition = select_ns.class_("SelectIsCondition", automation.Condition) + # Enums SelectOperation = select_ns.enum("SelectOperation") SELECT_OPERATION_OPTIONS = { @@ -165,6 +171,41 @@ async def select_set_index_to_code(config, action_id, template_arg, args): return var +@automation.register_condition( + "select.is", + SelectIsCondition, + OPERATION_BASE_SCHEMA.extend( + { + cv.Optional(CONF_OPTIONS): cv.All( + cv.ensure_list(cv.string_strict), cv.Length(min=1) + ), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + } + ).add_extra(cv.has_exactly_one_key(CONF_OPTIONS, CONF_LAMBDA)), +) +async def select_is_to_code(config, condition_id, template_arg, args): + paren = await cg.get_variable(config[CONF_ID]) + if options := config.get(CONF_OPTIONS): + # List of constant options + # Create a constexpr and pass that with a template length + arr_id = ID( + f"{condition_id}_data", + is_declaration=True, + type=global_ns.namespace("constexpr char * const"), + ) + arg = cg.static_const_array(arr_id, cg.ArrayInitializer(*options)) + template_arg = TemplateArguments(len(options), *template_arg) + else: + # Lambda + arg = await cg.process_lambda( + config[CONF_LAMBDA], + [(global_ns.namespace("StringRef &").operator("const"), "current")] + args, + return_type=cg.bool_, + ) + template_arg = TemplateArguments(0, *template_arg) + return cg.new_Pvariable(condition_id, template_arg, paren, arg) + + @automation.register_action( "select.operation", SelectOperationAction, diff --git a/esphome/components/select/automation.h b/esphome/components/select/automation.h index dda5403557..81e8a3561d 100644 --- a/esphome/components/select/automation.h +++ b/esphome/components/select/automation.h @@ -66,4 +66,34 @@ template class SelectOperationAction : public Action { Select *select_; }; +template class SelectIsCondition : public Condition { + public: + SelectIsCondition(Select *parent, const char *const *option_list) : parent_(parent), option_list_(option_list) {} + + bool check(const Ts &...x) override { + auto current = this->parent_->current_option(); + for (size_t i = 0; i != N; i++) { + if (current == this->option_list_[i]) { + return true; + } + } + return false; + } + + protected: + Select *parent_; + const char *const *option_list_; +}; + +template class SelectIsCondition<0, Ts...> : public Condition { + public: + SelectIsCondition(Select *parent, std::function &&f) + : parent_(parent), f_(f) {} + + bool check(const Ts &...x) override { return this->f_(this->parent_->current_option(), x...); } + + protected: + Select *parent_; + std::function f_; +}; } // namespace esphome::select diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index 134ad4d046..3b888c3d19 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -53,6 +53,17 @@ binary_sensor: // Garage Door is closed. return false; } + - platform: template + id: select_binary_sensor + name: Select is one or two + condition: + any: + - select.is: + id: template_select + options: [one, two] + - select.is: + id: template_select + lambda: return current == id(template_text).state; - platform: template id: other_binary_sensor name: "Garage Door Closed" @@ -320,6 +331,7 @@ valve: text: - platform: template + id: template_text name: "Template text" optimistic: true min_length: 0 From 52ac9e18616a1a8688745badcf09520c0370ef7c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 12:56:47 -1000 Subject: [PATCH 0152/2030] [remote_base] Replace unsafe sprintf with buf_append_printf; fix buffer overflow (#13257) Co-authored-by: Keith Burzinski Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../components/remote_base/aeha_protocol.cpp | 4 +-- .../components/remote_base/raw_protocol.cpp | 27 ++++++++---------- .../components/remote_base/remote_base.cpp | 28 ++++++++----------- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/esphome/components/remote_base/aeha_protocol.cpp b/esphome/components/remote_base/aeha_protocol.cpp index 04fe731817..3b926e7981 100644 --- a/esphome/components/remote_base/aeha_protocol.cpp +++ b/esphome/components/remote_base/aeha_protocol.cpp @@ -85,8 +85,8 @@ optional AEHAProtocol::decode(RemoteReceiveData src) { std::string AEHAProtocol::format_data_(const std::vector &data) { std::string out; for (uint8_t byte : data) { - char buf[6]; - sprintf(buf, "0x%02X,", byte); + char buf[8]; // "0x%02X," = 5 chars + null + margin + snprintf(buf, sizeof(buf), "0x%02X,", byte); out += buf; } out.pop_back(); diff --git a/esphome/components/remote_base/raw_protocol.cpp b/esphome/components/remote_base/raw_protocol.cpp index ef0cb8454e..7e6be3b77e 100644 --- a/esphome/components/remote_base/raw_protocol.cpp +++ b/esphome/components/remote_base/raw_protocol.cpp @@ -1,4 +1,5 @@ #include "raw_protocol.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" namespace esphome { @@ -8,36 +9,30 @@ static const char *const TAG = "remote.raw"; bool RawDumper::dump(RemoteReceiveData src) { char buffer[256]; - uint32_t buffer_offset = 0; - buffer_offset += sprintf(buffer, "Received Raw: "); + size_t pos = buf_append_printf(buffer, sizeof(buffer), 0, "Received Raw: "); for (int32_t i = 0; i < src.size() - 1; i++) { const int32_t value = src[i]; - const uint32_t remaining_length = sizeof(buffer) - buffer_offset; - int written; + size_t prev_pos = pos; if (i + 1 < src.size() - 1) { - written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32 ", ", value); + pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value); } else { - written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32, value); + pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value); } - if (written < 0 || written >= int(remaining_length)) { - // write failed, flush... - buffer[buffer_offset] = '\0'; + if (pos >= sizeof(buffer) - 1) { + // buffer full, flush and continue + buffer[prev_pos] = '\0'; ESP_LOGI(TAG, "%s", buffer); - buffer_offset = 0; - written = sprintf(buffer, " "); if (i + 1 < src.size() - 1) { - written += sprintf(buffer + written, "%" PRId32 ", ", value); + pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value); } else { - written += sprintf(buffer + written, "%" PRId32, value); + pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value); } } - - buffer_offset += written; } - if (buffer_offset != 0) { + if (pos != 0) { ESP_LOGI(TAG, "%s", buffer); } return true; diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index e3d9463243..53c9c38c7d 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -1,4 +1,5 @@ #include "remote_base.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include @@ -169,36 +170,31 @@ void RemoteTransmitterBase::send_(uint32_t send_times, uint32_t send_wait) { #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE const auto &vec = this->temp_.get_data(); char buffer[256]; - uint32_t buffer_offset = 0; - buffer_offset += sprintf(buffer, "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait); + size_t pos = buf_append_printf(buffer, sizeof(buffer), 0, + "Sending times=%" PRIu32 " wait=%" PRIu32 "ms: ", send_times, send_wait); for (size_t i = 0; i < vec.size(); i++) { const int32_t value = vec[i]; - const uint32_t remaining_length = sizeof(buffer) - buffer_offset; - int written; + size_t prev_pos = pos; if (i + 1 < vec.size()) { - written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32 ", ", value); + pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32 ", ", value); } else { - written = snprintf(buffer + buffer_offset, remaining_length, "%" PRId32, value); + pos = buf_append_printf(buffer, sizeof(buffer), pos, "%" PRId32, value); } - if (written < 0 || written >= int(remaining_length)) { - // write failed, flush... - buffer[buffer_offset] = '\0'; + if (pos >= sizeof(buffer) - 1) { + // buffer full, flush and continue + buffer[prev_pos] = '\0'; ESP_LOGVV(TAG, "%s", buffer); - buffer_offset = 0; - written = sprintf(buffer, " "); if (i + 1 < vec.size()) { - written += sprintf(buffer + written, "%" PRId32 ", ", value); + pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32 ", ", value); } else { - written += sprintf(buffer + written, "%" PRId32, value); + pos = buf_append_printf(buffer, sizeof(buffer), 0, " %" PRId32, value); } } - - buffer_offset += written; } - if (buffer_offset != 0) { + if (pos != 0) { ESP_LOGVV(TAG, "%s", buffer); } #endif From 58a9e30017b7094c9cf8bfb0739b610ba5bcd450 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 16 Jan 2026 17:05:19 -0600 Subject: [PATCH 0153/2030] [helpers] Add `base64_decode_int32_vector` function (#13289) Co-authored-by: J. Nick Koston --- esphome/core/helpers.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ esphome/core/helpers.h | 6 ++++++ 2 files changed, 46 insertions(+) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 96b2d46d78..5cad2308df 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -624,6 +624,46 @@ std::vector base64_decode(const std::string &encoded_string) { return ret; } +/// Decode base64/base64url string directly into vector of little-endian int32 values +/// @param base64 Base64 or base64url encoded string (both +/ and -_ accepted) +/// @param out Output vector (cleared and filled with decoded int32 values) +/// @return true if successful, false if decode failed or invalid size +bool base64_decode_int32_vector(const std::string &base64, std::vector &out) { + // Decode in chunks to minimize stack usage + constexpr size_t chunk_bytes = 48; // 12 int32 values + constexpr size_t chunk_chars = 64; // 48 * 4/3 = 64 chars + uint8_t chunk[chunk_bytes]; + + out.clear(); + + const uint8_t *input = reinterpret_cast(base64.data()); + size_t remaining = base64.size(); + size_t pos = 0; + + while (remaining > 0) { + size_t chars_to_decode = std::min(remaining, chunk_chars); + size_t decoded_len = base64_decode(input + pos, chars_to_decode, chunk, chunk_bytes); + + if (decoded_len == 0) + return false; + + // Parse little-endian int32 values + for (size_t i = 0; i + 3 < decoded_len; i += 4) { + int32_t timing = static_cast(encode_uint32(chunk[i + 3], chunk[i + 2], chunk[i + 1], chunk[i])); + out.push_back(timing); + } + + // Check for incomplete int32 in last chunk + if (remaining <= chunk_chars && (decoded_len % 4) != 0) + return false; + + pos += chars_to_decode; + remaining -= chars_to_decode; + } + + return !out.empty(); +} + /// Encode int32 to 5 base85 characters + null terminator /// Standard ASCII85 alphabet: '!' (33) = 0 through 'u' (117) = 84 inline void base85_encode_int32(int32_t value, std::span output) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 9dc289c743..000762c9bf 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1137,6 +1137,12 @@ std::vector base64_decode(const std::string &encoded_string); size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len); size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len); +/// Decode base64/base64url string directly into vector of little-endian int32 values +/// @param base64 Base64 or base64url encoded string (both +/ and -_ accepted) +/// @param out Output vector (cleared and filled with decoded int32 values) +/// @return true if successful, false if decode failed or invalid size +bool base64_decode_int32_vector(const std::string &base64, std::vector &out); + /// Size of buffer needed for base85 encoded int32 (5 chars + null terminator) static constexpr size_t BASE85_INT32_ENCODED_SIZE = 6; From f7ad324d81175881b3997833a110904d2df1ac0a Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 16 Jan 2026 18:15:27 -0600 Subject: [PATCH 0154/2030] [infrared, remote_base] Replace `base85` with `base64url` for web server infrared transmissions (#13265) --- esphome/components/infrared/infrared.cpp | 27 ++++++++++++------- esphome/components/infrared/infrared.h | 24 ++++++++--------- .../components/remote_base/remote_base.cpp | 6 ++--- esphome/components/remote_base/remote_base.h | 8 +++--- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 294d69e523..4431869951 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -19,12 +19,12 @@ InfraredCall &InfraredCall::set_carrier_frequency(uint32_t frequency) { InfraredCall &InfraredCall::set_raw_timings(const std::vector &timings) { this->raw_timings_ = &timings; this->packed_data_ = nullptr; - this->base85_ptr_ = nullptr; + this->base64url_ptr_ = nullptr; return *this; } -InfraredCall &InfraredCall::set_raw_timings_base85(const std::string &base85) { - this->base85_ptr_ = &base85; +InfraredCall &InfraredCall::set_raw_timings_base64url(const std::string &base64url) { + this->base64url_ptr_ = &base64url; this->raw_timings_ = nullptr; this->packed_data_ = nullptr; return *this; @@ -35,7 +35,7 @@ InfraredCall &InfraredCall::set_raw_timings_packed(const uint8_t *data, uint16_t this->packed_length_ = length; this->packed_count_ = count; this->raw_timings_ = nullptr; - this->base85_ptr_ = nullptr; + this->base64url_ptr_ = nullptr; return *this; } @@ -101,13 +101,22 @@ void Infrared::control(const InfraredCall &call) { call.get_packed_count()); ESP_LOGD(TAG, "Transmitting packed raw timings: count=%u, repeat=%u", call.get_packed_count(), call.get_repeat_count()); - } else if (call.is_base85()) { - // Decode base85 directly into transmit buffer (zero heap allocations) - if (!transmit_data->set_data_from_base85(call.get_base85_data())) { - ESP_LOGE(TAG, "Invalid base85 data"); + } else if (call.is_base64url()) { + // Decode base64url (URL-safe) into transmit buffer + if (!transmit_data->set_data_from_base64url(call.get_base64url_data())) { + ESP_LOGE(TAG, "Invalid base64url data"); return; } - ESP_LOGD(TAG, "Transmitting base85 raw timings: count=%zu, repeat=%u", transmit_data->get_data().size(), + // Sanity check: validate timing values are within reasonable bounds + constexpr int32_t max_timing_us = 500000; // 500ms absolute max + for (int32_t timing : transmit_data->get_data()) { + int32_t abs_timing = timing < 0 ? -timing : timing; + if (abs_timing > max_timing_us) { + ESP_LOGE(TAG, "Invalid timing value: %d µs (max %d)", timing, max_timing_us); + return; + } + } + ESP_LOGD(TAG, "Transmitting base64url raw timings: count=%zu, repeat=%u", transmit_data->get_data().size(), call.get_repeat_count()); } else { // From vector (lambdas/automations) diff --git a/esphome/components/infrared/infrared.h b/esphome/components/infrared/infrared.h index ba426c9daa..59535f499a 100644 --- a/esphome/components/infrared/infrared.h +++ b/esphome/components/infrared/infrared.h @@ -40,11 +40,11 @@ class InfraredCall { /// @note Usage: Primarily for lambdas/automations where the vector is in scope. InfraredCall &set_raw_timings(const std::vector &timings); - /// Set the raw timings from base85-encoded int32 data + /// Set the raw timings from base64url-encoded little-endian int32 data /// @note Lifetime: Stores a pointer to the string. The string must outlive perform(). - /// @note Usage: For web_server where the encoded string is on the stack. + /// @note Usage: For web_server - base64url is fully URL-safe (uses '-' and '_'). /// @note Decoding happens at perform() time, directly into the transmit buffer. - InfraredCall &set_raw_timings_base85(const std::string &base85); + InfraredCall &set_raw_timings_base64url(const std::string &base64url); /// Set the raw timings from packed protobuf sint32 data (zigzag + varint encoded) /// @note Lifetime: Stores a pointer to the buffer. The buffer must outlive perform(). @@ -59,18 +59,18 @@ class InfraredCall { /// Get the carrier frequency const optional &get_carrier_frequency() const { return this->carrier_frequency_; } - /// Get the raw timings (only valid if set via set_raw_timings, not packed or base85) + /// Get the raw timings (only valid if set via set_raw_timings) const std::vector &get_raw_timings() const { return *this->raw_timings_; } - /// Check if raw timings have been set (vector, packed, or base85) + /// Check if raw timings have been set (any format) bool has_raw_timings() const { - return this->raw_timings_ != nullptr || this->packed_data_ != nullptr || this->base85_ptr_ != nullptr; + return this->raw_timings_ != nullptr || this->packed_data_ != nullptr || this->base64url_ptr_ != nullptr; } /// Check if using packed data format bool is_packed() const { return this->packed_data_ != nullptr; } - /// Check if using base85 data format - bool is_base85() const { return this->base85_ptr_ != nullptr; } - /// Get the base85 data string - const std::string &get_base85_data() const { return *this->base85_ptr_; } + /// Check if using base64url data format + bool is_base64url() const { return this->base64url_ptr_ != nullptr; } + /// Get the base64url data string + const std::string &get_base64url_data() const { return *this->base64url_ptr_; } /// Get packed data (only valid if set via set_raw_timings_packed) const uint8_t *get_packed_data() const { return this->packed_data_; } uint16_t get_packed_length() const { return this->packed_length_; } @@ -84,8 +84,8 @@ class InfraredCall { optional carrier_frequency_; // Pointer to vector-based timings (caller-owned, must outlive perform()) const std::vector *raw_timings_{nullptr}; - // Pointer to base85-encoded string (caller-owned, must outlive perform()) - const std::string *base85_ptr_{nullptr}; + // Pointer to base64url-encoded string (caller-owned, must outlive perform()) + const std::string *base64url_ptr_{nullptr}; // Pointer to packed protobuf buffer (caller-owned, must outlive perform()) const uint8_t *packed_data_{nullptr}; uint16_t packed_length_{0}; diff --git a/esphome/components/remote_base/remote_base.cpp b/esphome/components/remote_base/remote_base.cpp index 53c9c38c7d..b4a549f0be 100644 --- a/esphome/components/remote_base/remote_base.cpp +++ b/esphome/components/remote_base/remote_base.cpp @@ -2,8 +2,6 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include - namespace esphome { namespace remote_base { @@ -160,8 +158,8 @@ void RemoteTransmitData::set_data_from_packed_sint32(const uint8_t *data, size_t } } -bool RemoteTransmitData::set_data_from_base85(const std::string &base85) { - return base85_decode_int32_vector(base85, this->data_); +bool RemoteTransmitData::set_data_from_base64url(const std::string &base64url) { + return base64_decode_int32_vector(base64url, this->data_); } /* RemoteTransmitterBase */ diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 2d7642cc31..0cac28506f 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -36,11 +36,11 @@ class RemoteTransmitData { /// @param len Length of the buffer in bytes /// @param count Number of values (for reserve optimization) void set_data_from_packed_sint32(const uint8_t *data, size_t len, size_t count); - /// Set data from base85-encoded int32 values - /// Decodes directly into internal buffer (zero heap allocations) - /// @param base85 Base85-encoded string (5 chars per int32 value) + /// Set data from base64url-encoded little-endian int32 values + /// Base64url is URL-safe: uses '-' instead of '+', '_' instead of '/' + /// @param base64url Base64url-encoded string of little-endian int32 values /// @return true if successful, false if decode failed or invalid size - bool set_data_from_base85(const std::string &base85); + bool set_data_from_base64url(const std::string &base64url); void reset() { this->data_.clear(); this->carrier_frequency_ = 0; From 510c874061cd73ec95afcd26ab4f814463776d9e Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 16 Jan 2026 19:23:41 -0600 Subject: [PATCH 0155/2030] [helpers] Remove `base85` functions (#13266) --- esphome/core/helpers.cpp | 49 ---------------------------------------- esphome/core/helpers.h | 8 ------- 2 files changed, 57 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 5cad2308df..5de1c70562 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -664,55 +664,6 @@ bool base64_decode_int32_vector(const std::string &base64, std::vector return !out.empty(); } -/// Encode int32 to 5 base85 characters + null terminator -/// Standard ASCII85 alphabet: '!' (33) = 0 through 'u' (117) = 84 -inline void base85_encode_int32(int32_t value, std::span output) { - uint32_t v = static_cast(value); - // Encode least significant digit first, then reverse - for (int i = 4; i >= 0; i--) { - output[i] = static_cast('!' + (v % 85)); - v /= 85; - } - output[5] = '\0'; -} - -/// Decode 5 base85 characters to int32 -inline bool base85_decode_int32(const char *input, int32_t &out) { - uint8_t c0 = static_cast(input[0] - '!'); - uint8_t c1 = static_cast(input[1] - '!'); - uint8_t c2 = static_cast(input[2] - '!'); - uint8_t c3 = static_cast(input[3] - '!'); - uint8_t c4 = static_cast(input[4] - '!'); - - // Each digit must be 0-84. Since uint8_t wraps, chars below '!' become > 84 - if (c0 > 84 || c1 > 84 || c2 > 84 || c3 > 84 || c4 > 84) - return false; - - // 85^4 = 52200625, 85^3 = 614125, 85^2 = 7225, 85^1 = 85 - out = static_cast(c0 * 52200625u + c1 * 614125u + c2 * 7225u + c3 * 85u + c4); - return true; -} - -/// Decode base85 string directly into vector (no intermediate buffer) -bool base85_decode_int32_vector(const std::string &base85, std::vector &out) { - size_t len = base85.size(); - if (len % 5 != 0) - return false; - - out.clear(); - const char *ptr = base85.data(); - const char *end = ptr + len; - - while (ptr < end) { - int32_t value; - if (!base85_decode_int32(ptr, value)) - return false; - out.push_back(value); - ptr += 5; - } - return true; -} - // Colors float gamma_correct(float value, float gamma) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 000762c9bf..0acc6bdc60 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1143,14 +1143,6 @@ size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *b /// @return true if successful, false if decode failed or invalid size bool base64_decode_int32_vector(const std::string &base64, std::vector &out); -/// Size of buffer needed for base85 encoded int32 (5 chars + null terminator) -static constexpr size_t BASE85_INT32_ENCODED_SIZE = 6; - -void base85_encode_int32(int32_t value, std::span output); - -bool base85_decode_int32(const char *input, int32_t &out); -bool base85_decode_int32_vector(const std::string &base85, std::vector &out); - ///@} /// @name Colors From 69d7b6e9210390051318bd8e6410727689de08d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 15:46:15 -1000 Subject: [PATCH 0156/2030] [api] Use subtraction for protobuf bounds checking (#13306) --- esphome/components/api/proto.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index eac26997cf..2a0ddf91db 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -48,14 +48,14 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size } uint32_t field_length = res->as_uint32(); ptr += consumed; - if (ptr + field_length > end) { + if (field_length > static_cast(end - ptr)) { return count; // Out of bounds } ptr += field_length; break; } case WIRE_TYPE_FIXED32: { // 32-bit - skip 4 bytes - if (ptr + 4 > end) { + if (end - ptr < 4) { return count; } ptr += 4; @@ -110,7 +110,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { } uint32_t field_length = res->as_uint32(); ptr += consumed; - if (ptr + field_length > end) { + if (field_length > static_cast(end - ptr)) { ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer)); return; } @@ -121,7 +121,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { break; } case WIRE_TYPE_FIXED32: { // 32-bit - if (ptr + 4 > end) { + if (end - ptr < 4) { ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); return; } From bbe11555183d544850c22a160ca93bac70e2e57d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 16:08:04 -1000 Subject: [PATCH 0157/2030] [web_server] Skip defer on ESP8266 where callbacks already run in main loop (#13261) --- esphome/components/web_server/web_server.cpp | 134 ++++++++++--------- esphome/components/web_server/web_server.h | 8 ++ 2 files changed, 81 insertions(+), 61 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index cf984ea247..0e71d82233 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -658,6 +658,24 @@ std::string WebServer::text_sensor_json_(text_sensor::TextSensor *obj, const std #endif #ifdef USE_SWITCH +enum SwitchAction : uint8_t { SWITCH_ACTION_NONE, SWITCH_ACTION_TOGGLE, SWITCH_ACTION_TURN_ON, SWITCH_ACTION_TURN_OFF }; + +static void execute_switch_action(switch_::Switch *obj, SwitchAction action) { + switch (action) { + case SWITCH_ACTION_TOGGLE: + obj->toggle(); + break; + case SWITCH_ACTION_TURN_ON: + obj->turn_on(); + break; + case SWITCH_ACTION_TURN_OFF: + obj->turn_off(); + break; + default: + break; + } +} + void WebServer::on_switch_update(switch_::Switch *obj) { if (!this->include_internal_ && obj->is_internal()) return; @@ -676,34 +694,22 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM return; } - // Handle action methods with single defer and response - enum SwitchAction { NONE, TOGGLE, TURN_ON, TURN_OFF }; - SwitchAction action = NONE; + SwitchAction action = SWITCH_ACTION_NONE; if (match.method_equals(ESPHOME_F("toggle"))) { - action = TOGGLE; + action = SWITCH_ACTION_TOGGLE; } else if (match.method_equals(ESPHOME_F("turn_on"))) { - action = TURN_ON; + action = SWITCH_ACTION_TURN_ON; } else if (match.method_equals(ESPHOME_F("turn_off"))) { - action = TURN_OFF; + action = SWITCH_ACTION_TURN_OFF; } - if (action != NONE) { - this->defer([obj, action]() { - switch (action) { - case TOGGLE: - obj->toggle(); - break; - case TURN_ON: - obj->turn_on(); - break; - case TURN_OFF: - obj->turn_off(); - break; - default: - break; - } - }); + if (action != SWITCH_ACTION_NONE) { +#ifdef USE_ESP8266 + execute_switch_action(obj, action); +#else + this->defer([obj, action]() { execute_switch_action(obj, action); }); +#endif request->send(200); } else { request->send(404); @@ -743,7 +749,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM std::string data = this->button_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("press"))) { - this->defer([obj]() { obj->press(); }); + DEFER_ACTION(obj, obj->press()); request->send(200); return; } else { @@ -828,7 +834,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc std::string data = this->fan_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("toggle"))) { - this->defer([obj]() { obj->toggle().perform(); }); + DEFER_ACTION(obj, obj->toggle().perform()); request->send(200); } else { bool is_on = match.method_equals(ESPHOME_F("turn_on")); @@ -859,7 +865,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc return; } } - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); } return; @@ -909,7 +915,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa std::string data = this->light_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("toggle"))) { - this->defer([obj]() { obj->toggle().perform(); }); + DEFER_ACTION(obj, obj->toggle().perform()); request->send(200); } else { bool is_on = match.method_equals(ESPHOME_F("turn_on")); @@ -938,7 +944,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa parse_string_param_(request, ESPHOME_F("effect"), call, &decltype(call)::set_effect); } - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); } return; @@ -1027,7 +1033,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); parse_float_param_(request, ESPHOME_F("tilt"), call, &decltype(call)::set_tilt); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1086,7 +1092,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM auto call = obj->make_call(); parse_float_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1159,7 +1165,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_date); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1223,7 +1229,7 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_time); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1286,7 +1292,7 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_datetime); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1346,7 +1352,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat auto call = obj->make_call(); parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1404,7 +1410,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM auto call = obj->make_call(); parse_string_param_(request, ESPHOME_F("option"), call, &decltype(call)::set_option); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1473,7 +1479,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url parse_float_param_(request, ESPHOME_F("target_temperature_low"), call, &decltype(call)::set_target_temperature_low); parse_float_param_(request, ESPHOME_F("target_temperature"), call, &decltype(call)::set_target_temperature); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1589,6 +1595,24 @@ std::string WebServer::climate_json_(climate::Climate *obj, JsonDetail start_con #endif #ifdef USE_LOCK +enum LockAction : uint8_t { LOCK_ACTION_NONE, LOCK_ACTION_LOCK, LOCK_ACTION_UNLOCK, LOCK_ACTION_OPEN }; + +static void execute_lock_action(lock::Lock *obj, LockAction action) { + switch (action) { + case LOCK_ACTION_LOCK: + obj->lock(); + break; + case LOCK_ACTION_UNLOCK: + obj->unlock(); + break; + case LOCK_ACTION_OPEN: + obj->open(); + break; + default: + break; + } +} + void WebServer::on_lock_update(lock::Lock *obj) { if (!this->include_internal_ && obj->is_internal()) return; @@ -1607,34 +1631,22 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat return; } - // Handle action methods with single defer and response - enum LockAction { NONE, LOCK, UNLOCK, OPEN }; - LockAction action = NONE; + LockAction action = LOCK_ACTION_NONE; if (match.method_equals(ESPHOME_F("lock"))) { - action = LOCK; + action = LOCK_ACTION_LOCK; } else if (match.method_equals(ESPHOME_F("unlock"))) { - action = UNLOCK; + action = LOCK_ACTION_UNLOCK; } else if (match.method_equals(ESPHOME_F("open"))) { - action = OPEN; + action = LOCK_ACTION_OPEN; } - if (action != NONE) { - this->defer([obj, action]() { - switch (action) { - case LOCK: - obj->lock(); - break; - case UNLOCK: - obj->unlock(); - break; - case OPEN: - obj->open(); - break; - default: - break; - } - }); + if (action != LOCK_ACTION_NONE) { +#ifdef USE_ESP8266 + execute_lock_action(obj, action); +#else + this->defer([obj, action]() { execute_lock_action(obj, action); }); +#endif request->send(200); } else { request->send(404); @@ -1717,7 +1729,7 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1796,7 +1808,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques return; } - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -1872,7 +1884,7 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons // Parse on/off parameter parse_bool_param_(request, ESPHOME_F("is_on"), base_call, &water_heater::WaterHeaterCall::set_on); - this->defer([call]() mutable { call.perform(); }); + DEFER_ACTION(call, call.perform()); request->send(200); return; } @@ -2032,7 +2044,7 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM return; } - this->defer([obj]() mutable { obj->perform(); }); + DEFER_ACTION(obj, obj->perform()); request->send(200); return; } diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index b1a495ebef..c434d664cf 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -42,6 +42,14 @@ using ParamNameType = const __FlashStringHelper *; using ParamNameType = const char *; #endif +// ESP8266 is single-threaded, so actions can execute directly in request context. +// Multi-core platforms need to defer to main loop thread for thread safety. +#ifdef USE_ESP8266 +#define DEFER_ACTION(capture, action) action +#else +#define DEFER_ACTION(capture, action) this->defer([capture]() mutable { action; }) +#endif + /// Result of matching a URL against an entity struct EntityMatchResult { bool matched; ///< True if entity matched the URL From e54d5ee8980dbf138813ae678289280c0f95fdad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 17:16:38 -1000 Subject: [PATCH 0158/2030] [hmac_sha256] Replace unsafe sprintf with format_hex_to (#13290) --- esphome/components/hmac_sha256/hmac_sha256.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/esphome/components/hmac_sha256/hmac_sha256.cpp b/esphome/components/hmac_sha256/hmac_sha256.cpp index cf5daf63af..2146e961bc 100644 --- a/esphome/components/hmac_sha256/hmac_sha256.cpp +++ b/esphome/components/hmac_sha256/hmac_sha256.cpp @@ -1,4 +1,3 @@ -#include #include #include "hmac_sha256.h" #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_HOST) @@ -26,9 +25,7 @@ void HmacSHA256::calculate() { mbedtls_md_hmac_finish(&this->ctx_, this->digest_ void HmacSHA256::get_bytes(uint8_t *output) { memcpy(output, this->digest_, SHA256_DIGEST_SIZE); } void HmacSHA256::get_hex(char *output) { - for (size_t i = 0; i < SHA256_DIGEST_SIZE; i++) { - sprintf(output + (i * 2), "%02x", this->digest_[i]); - } + format_hex_to(output, SHA256_DIGEST_SIZE * 2 + 1, this->digest_, SHA256_DIGEST_SIZE); } bool HmacSHA256::equals_bytes(const uint8_t *expected) { From 92808a09c7548a6284e53ae94ffcf61e717ff89c Mon Sep 17 00:00:00 2001 From: Stuart Parmenter Date: Fri, 16 Jan 2026 19:17:36 -0800 Subject: [PATCH 0159/2030] [hub75] Bump esp-hub75 version to 0.3.0 (#13243) --- esphome/components/hub75/display.py | 58 ++++++++++++++++++++++++----- esphome/idf_component.yml | 4 +- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 20c731e730..0eeb4bba33 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -1,3 +1,4 @@ +import logging from typing import Any from esphome import automation, pins @@ -18,13 +19,16 @@ from esphome.const import ( CONF_ROTATION, CONF_UPDATE_INTERVAL, ) -from esphome.core import ID +from esphome.core import ID, EnumValue from esphome.cpp_generator import MockObj, TemplateArgsType import esphome.final_validate as fv +from esphome.helpers import add_class_to_obj from esphome.types import ConfigType from . import boards, hub75_ns +_LOGGER = logging.getLogger(__name__) + DEPENDENCIES = ["esp32"] CODEOWNERS = ["@stuartparmenter"] @@ -120,13 +124,51 @@ PANEL_LAYOUTS = { } Hub75ScanWiring = cg.global_ns.enum("Hub75ScanWiring", is_class=True) -SCAN_PATTERNS = { +SCAN_WIRINGS = { "STANDARD_TWO_SCAN": Hub75ScanWiring.STANDARD_TWO_SCAN, - "FOUR_SCAN_16PX_HIGH": Hub75ScanWiring.FOUR_SCAN_16PX_HIGH, - "FOUR_SCAN_32PX_HIGH": Hub75ScanWiring.FOUR_SCAN_32PX_HIGH, - "FOUR_SCAN_64PX_HIGH": Hub75ScanWiring.FOUR_SCAN_64PX_HIGH, + "SCAN_1_4_16PX_HIGH": Hub75ScanWiring.SCAN_1_4_16PX_HIGH, + "SCAN_1_8_32PX_HIGH": Hub75ScanWiring.SCAN_1_8_32PX_HIGH, + "SCAN_1_8_40PX_HIGH": Hub75ScanWiring.SCAN_1_8_40PX_HIGH, + "SCAN_1_8_64PX_HIGH": Hub75ScanWiring.SCAN_1_8_64PX_HIGH, } +# Deprecated scan wiring names - mapped to new names +DEPRECATED_SCAN_WIRINGS = { + "FOUR_SCAN_16PX_HIGH": "SCAN_1_4_16PX_HIGH", + "FOUR_SCAN_32PX_HIGH": "SCAN_1_8_32PX_HIGH", + "FOUR_SCAN_64PX_HIGH": "SCAN_1_8_64PX_HIGH", +} + + +def _validate_scan_wiring(value): + """Validate scan_wiring with deprecation warnings for old names.""" + value = cv.string(value).upper().replace(" ", "_") + + # Check if using deprecated name + # Remove deprecated names in 2026.7.0 + if value in DEPRECATED_SCAN_WIRINGS: + new_name = DEPRECATED_SCAN_WIRINGS[value] + _LOGGER.warning( + "Scan wiring '%s' is deprecated and will be removed in ESPHome 2026.7.0. " + "Please use '%s' instead.", + value, + new_name, + ) + value = new_name + + # Validate against allowed values + if value not in SCAN_WIRINGS: + raise cv.Invalid( + f"Unknown scan wiring '{value}'. " + f"Valid options are: {', '.join(sorted(SCAN_WIRINGS.keys()))}" + ) + + # Return as EnumValue like cv.enum does + result = add_class_to_obj(value, EnumValue) + result.enum_value = SCAN_WIRINGS[value] + return result + + Hub75ClockSpeed = cg.global_ns.enum("Hub75ClockSpeed", is_class=True) CLOCK_SPEEDS = { "8MHZ": Hub75ClockSpeed.HZ_8M, @@ -382,9 +424,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_LAYOUT_COLS): cv.positive_int, cv.Optional(CONF_LAYOUT): cv.enum(PANEL_LAYOUTS, upper=True, space="_"), # Panel hardware configuration - cv.Optional(CONF_SCAN_WIRING): cv.enum( - SCAN_PATTERNS, upper=True, space="_" - ), + cv.Optional(CONF_SCAN_WIRING): _validate_scan_wiring, cv.Optional(CONF_SHIFT_DRIVER): cv.enum(SHIFT_DRIVERS, upper=True), # Display configuration cv.Optional(CONF_DOUBLE_BUFFER): cv.boolean, @@ -547,7 +587,7 @@ def _build_config_struct( async def to_code(config: ConfigType) -> None: add_idf_component( name="esphome/esp-hub75", - ref="0.2.2", + ref="0.3.0", ) # Set compile-time configuration via build flags (so external library sees them) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 045b3f9168..5903e68e8e 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -28,8 +28,8 @@ dependencies: rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: - version: 0.2.2 + version: 0.3.0 rules: - - if: "target in [esp32, esp32s2, esp32s3, esp32p4]" + - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" esp32async/asynctcp: version: 3.4.91 From 1f4221abfa5b6298dba5fa8ee9ca4f770cad9023 Mon Sep 17 00:00:00 2001 From: Mike Ford <60777900+HLFCode@users.noreply.github.com> Date: Sat, 17 Jan 2026 03:18:48 +0000 Subject: [PATCH 0160/2030] [http_request] Unable to handle chunked responses (#7884) Co-authored-by: J. Nick Koston --- esphome/components/http_request/http_request.h | 4 +--- .../components/http_request/http_request_idf.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 1b5fd9f00e..a8c2cdfc63 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -242,9 +242,7 @@ template class HttpRequestSendAction : public Action { return; } - size_t content_length = container->content_length; - size_t max_length = std::min(content_length, this->max_response_buffer_size_); - + size_t max_length = this->max_response_buffer_size_; #ifdef USE_HTTP_REQUEST_RESPONSE if (this->capture_response_.value(x...)) { std::string response_body; diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 725a9c1c1e..1de947ba5b 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -213,18 +213,12 @@ 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; + this->feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, max_len); + this->feed_wdt(); + if (read_len > 0) { + this->bytes_read_ += read_len; } - - this->feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); - this->feed_wdt(); - this->bytes_read_ += read_len; - this->duration_ms += (millis() - start); return read_len; From 9caf78aa7e9fcad5767ae841d416495d9a6ecd8e Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 13 Jan 2026 19:42:36 +0000 Subject: [PATCH 0161/2030] [i2s_audio] Bugfix: Buffer overflow in software volume control (#13190) --- esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp | 2 +- 1 file changed, 1 insertion(+), 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 53e378c41e..c934d12d65 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -340,8 +340,8 @@ void I2SAudioSpeaker::speaker_task(void *params) { const uint32_t read_delay = (this_speaker->current_stream_info_.frames_to_microseconds(frames_written) / 1000) / 2; - uint8_t *new_data = transfer_buffer->get_buffer_end(); // track start of any newly copied bytes size_t bytes_read = transfer_buffer->transfer_data_from_source(pdMS_TO_TICKS(read_delay)); + uint8_t *new_data = transfer_buffer->get_buffer_end() - bytes_read; if (bytes_read > 0) { if (this_speaker->q15_volume_factor_ < INT16_MAX) { From 6f29dbd6f123ea9fa95f702b0ff6b4f8a4015477 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 15:46:15 -1000 Subject: [PATCH 0162/2030] [api] Use subtraction for protobuf bounds checking (#13306) --- esphome/components/api/proto.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 4f0d0846d7..b496ad5110 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -48,14 +48,14 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size } uint32_t field_length = res->as_uint32(); ptr += consumed; - if (ptr + field_length > end) { + if (field_length > static_cast(end - ptr)) { return count; // Out of bounds } ptr += field_length; break; } case WIRE_TYPE_FIXED32: { // 32-bit - skip 4 bytes - if (ptr + 4 > end) { + if (end - ptr < 4) { return count; } ptr += 4; @@ -110,7 +110,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { } uint32_t field_length = res->as_uint32(); ptr += consumed; - if (ptr + field_length > end) { + if (field_length > static_cast(end - ptr)) { ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer)); return; } @@ -121,7 +121,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { break; } case WIRE_TYPE_FIXED32: { // 32-bit - if (ptr + 4 > end) { + if (end - ptr < 4) { ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); return; } From ec7f72e2802a3b3a20f83b90c94b791a441524fa Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 16 Jan 2026 22:24:05 -0500 Subject: [PATCH 0163/2030] Bump version to 2025.12.7 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index a23e21dd0d..7638fa4317 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2025.12.6 +PROJECT_NUMBER = 2025.12.7 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 6771b9f265..e8f9c932cd 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2025.12.6" +__version__ = "2025.12.7" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f88e8fc43b6deb87c1f9f516cc14961f5510d097 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 11:32:02 -1000 Subject: [PATCH 0164/2030] [sprinkler] Fix scheduler deprecation warnings and heap churn with FixedVector (#13251) --- esphome/components/sprinkler/sprinkler.cpp | 6 ++++-- esphome/components/sprinkler/sprinkler.h | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index ca9f85abd8..2813b4450b 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -332,6 +332,7 @@ Sprinkler::Sprinkler(const std::string &name) { // The `name` is needed to set timers up, hence non-default constructor // replaces `set_name()` method previously existed this->name_ = name; + this->timer_.init(2); this->timer_.push_back({this->name_ + "sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)}); this->timer_.push_back({this->name_ + "vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); } @@ -1574,7 +1575,8 @@ const LogString *Sprinkler::state_as_str_(SprinklerState state) { void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { if (this->timer_duration_(timer_index) > 0) { - this->set_timeout(this->timer_[timer_index].name, this->timer_duration_(timer_index), + // FixedVector ensures timer_ can't be resized, so .c_str() pointers remain valid + this->set_timeout(this->timer_[timer_index].name.c_str(), this->timer_duration_(timer_index), this->timer_cbf_(timer_index)); this->timer_[timer_index].start_time = millis(); this->timer_[timer_index].active = true; @@ -1585,7 +1587,7 @@ void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { bool Sprinkler::cancel_timer_(const SprinklerTimerIndex timer_index) { this->timer_[timer_index].active = false; - return this->cancel_timeout(this->timer_[timer_index].name); + return this->cancel_timeout(this->timer_[timer_index].name.c_str()); } bool Sprinkler::timer_active_(const SprinklerTimerIndex timer_index) { return this->timer_[timer_index].active; } diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index 25e2d42446..273c0e9208 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -3,6 +3,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" #include "esphome/components/number/number.h" #include "esphome/components/switch/switch.h" @@ -553,8 +554,8 @@ class Sprinkler : public Component { /// Sprinkler valve operator objects std::vector valve_op_{2}; - /// Valve control timers - std::vector timer_{}; + /// Valve control timers - FixedVector enforces that this can never grow beyond init() size + FixedVector timer_; /// Other Sprinkler instances we should be aware of (used to check if pumps are in use) std::vector other_controllers_; From 973fc4c5dc14b5d42326dd007c7e04e89aa8042a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:48:44 -1000 Subject: [PATCH 0165/2030] [dallas_temp] Use const char* for set_timeout to fix deprecation warning and heap churn (#13250) --- esphome/components/dallas_temp/dallas_temp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index a1b684abbf..13f2fa59bd 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -44,7 +44,7 @@ void DallasTemperatureSensor::update() { this->send_command_(DALLAS_COMMAND_START_CONVERSION); - this->set_timeout(this->get_address_name(), this->millis_to_wait_for_conversion_(), [this] { + this->set_timeout(this->get_address_name().c_str(), this->millis_to_wait_for_conversion_(), [this] { if (!this->read_scratch_pad_() || !this->check_scratch_pad_()) { this->publish_state(NAN); return; From edb303e495b073a33433c5212ed417a120b24a11 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:49:01 -1000 Subject: [PATCH 0166/2030] [api] Fix clock conflicts when multiple clients connected to homeassistant time (#13253) --- esphome/components/api/api_server.cpp | 4 +++- esphome/components/time/real_time_clock.cpp | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index a63d33f73b..ed97c3b9a2 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -558,8 +558,10 @@ bool APIServer::clear_noise_psk(bool make_active) { #ifdef USE_HOMEASSISTANT_TIME void APIServer::request_time() { for (auto &client : this->clients_) { - if (!client->flags_.remove && client->is_authenticated()) + if (!client->flags_.remove && client->is_authenticated()) { client->send_time_request(); + return; // Only request from one client to avoid clock conflicts + } } } #endif diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 639af4457f..f217d14c55 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -31,6 +31,18 @@ void RealTimeClock::dump_config() { void RealTimeClock::synchronize_epoch_(uint32_t epoch) { ESP_LOGVV(TAG, "Got epoch %" PRIu32, epoch); + // Skip if time is already synchronized to avoid unnecessary writes, log spam, + // and prevent clock jumping backwards due to network latency + constexpr time_t min_valid_epoch = 1546300800; // January 1, 2019 + time_t current_time = this->timestamp_now(); + // Check if time is valid (year >= 2019) before comparing + if (current_time >= min_valid_epoch) { + // Unsigned subtraction handles wraparound correctly, then cast to signed + int32_t diff = static_cast(epoch - static_cast(current_time)); + if (diff >= -1 && diff <= 1) { + return; + } + } // Update UTC epoch time. #ifdef USE_ZEPHYR struct timespec ts; From 50aa4b1992d627659126d76a63c65763abbfddfe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 15 Jan 2026 16:49:19 -1000 Subject: [PATCH 0167/2030] [esp32_ble_client] Reduce GATT data event logging to prevent firmware update failures (#13252) --- .../esp32_ble_client/ble_client_base.cpp | 38 +++++++++++-------- .../esp32_ble_client/ble_client_base.h | 3 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 149fcc79d5..01f79156a9 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -193,10 +193,18 @@ void BLEClientBase::log_event_(const char *name) { ESP_LOGD(TAG, "[%d] [%s] %s", this->connection_index_, this->address_str_, name); } -void BLEClientBase::log_gattc_event_(const char *name) { +void BLEClientBase::log_gattc_lifecycle_event_(const char *name) { ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_%s_EVT", this->connection_index_, this->address_str_, name); } +void BLEClientBase::log_gattc_data_event_(const char *name) { + // Data transfer events are logged at VERBOSE level because logging to UART creates + // delays that cause timing issues during time-sensitive BLE operations. This is + // especially problematic during pairing or firmware updates which require rapid + // writes to many characteristics - the log spam can cause these operations to fail. + ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_%s_EVT", this->connection_index_, this->address_str_, name); +} + void BLEClientBase::log_gattc_warning_(const char *operation, esp_gatt_status_t status) { ESP_LOGW(TAG, "[%d] [%s] %s error, status=%d", this->connection_index_, this->address_str_, operation, status); } @@ -280,7 +288,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_OPEN_EVT: { if (!this->check_addr(param->open.remote_bda)) return false; - this->log_gattc_event_("OPEN"); + this->log_gattc_lifecycle_event_("OPEN"); // conn_id was already set in ESP_GATTC_CONNECT_EVT this->service_count_ = 0; @@ -331,7 +339,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_CONNECT_EVT: { if (!this->check_addr(param->connect.remote_bda)) return false; - this->log_gattc_event_("CONNECT"); + this->log_gattc_lifecycle_event_("CONNECT"); this->conn_id_ = param->connect.conn_id; // Start MTU negotiation immediately as recommended by ESP-IDF examples // (gatt_client, ble_throughput) which call esp_ble_gattc_send_mtu_req in @@ -376,7 +384,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_CLOSE_EVT: { if (this->conn_id_ != param->close.conn_id) return false; - this->log_gattc_event_("CLOSE"); + this->log_gattc_lifecycle_event_("CLOSE"); this->release_services(); this->set_state(espbt::ClientState::IDLE); this->conn_id_ = UNSET_CONN_ID; @@ -404,7 +412,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_SEARCH_CMPL_EVT: { if (this->conn_id_ != param->search_cmpl.conn_id) return false; - this->log_gattc_event_("SEARCH_CMPL"); + this->log_gattc_lifecycle_event_("SEARCH_CMPL"); // For V3_WITHOUT_CACHE, switch back to medium connection parameters after service discovery // This balances performance with bandwidth usage after the critical discovery phase if (this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) { @@ -431,35 +439,35 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_READ_DESCR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("READ_DESCR"); + this->log_gattc_data_event_("READ_DESCR"); break; } case ESP_GATTC_WRITE_DESCR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("WRITE_DESCR"); + this->log_gattc_data_event_("WRITE_DESCR"); break; } case ESP_GATTC_WRITE_CHAR_EVT: { if (this->conn_id_ != param->write.conn_id) return false; - this->log_gattc_event_("WRITE_CHAR"); + this->log_gattc_data_event_("WRITE_CHAR"); break; } case ESP_GATTC_READ_CHAR_EVT: { if (this->conn_id_ != param->read.conn_id) return false; - this->log_gattc_event_("READ_CHAR"); + this->log_gattc_data_event_("READ_CHAR"); break; } case ESP_GATTC_NOTIFY_EVT: { if (this->conn_id_ != param->notify.conn_id) return false; - this->log_gattc_event_("NOTIFY"); + this->log_gattc_data_event_("NOTIFY"); break; } case ESP_GATTC_REG_FOR_NOTIFY_EVT: { - this->log_gattc_event_("REG_FOR_NOTIFY"); + this->log_gattc_data_event_("REG_FOR_NOTIFY"); if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE || this->connection_type_ == espbt::ConnectionType::V3_WITHOUT_CACHE) { // Client is responsible for flipping the descriptor value @@ -491,7 +499,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ esp_err_t status = esp_ble_gattc_write_char_descr(this->gattc_if_, this->conn_id_, desc_result.handle, sizeof(notify_en), (uint8_t *) ¬ify_en, ESP_GATT_WRITE_TYPE_RSP, ESP_GATT_AUTH_REQ_NONE); - ESP_LOGD(TAG, "Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties); + ESP_LOGV(TAG, "Wrote notify descriptor %d, properties=%d", notify_en, char_result.properties); if (status) { this->log_gattc_warning_("esp_ble_gattc_write_char_descr", status); } @@ -499,13 +507,13 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: { - this->log_gattc_event_("UNREG_FOR_NOTIFY"); + this->log_gattc_data_event_("UNREG_FOR_NOTIFY"); break; } default: - // ideally would check all other events for matching conn_id - ESP_LOGD(TAG, "[%d] [%s] Event %d", this->connection_index_, this->address_str_, event); + // Unknown events logged at VERBOSE to avoid UART delays during time-sensitive operations + ESP_LOGV(TAG, "[%d] [%s] Event %d", this->connection_index_, this->address_str_, event); break; } return true; diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index 92c7444ee1..c52f0e5d2d 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -127,7 +127,8 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { // 6 bytes used, 2 bytes padding void log_event_(const char *name); - void log_gattc_event_(const char *name); + void log_gattc_lifecycle_event_(const char *name); + void log_gattc_data_event_(const char *name); void update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, const char *param_type); void set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, From e1800d2fe25561979a64be1d3dcbc471f17eefa6 Mon Sep 17 00:00:00 2001 From: mrtoy-me <118446898+mrtoy-me@users.noreply.github.com> Date: Sat, 17 Jan 2026 01:19:09 +1000 Subject: [PATCH 0168/2030] [ntc, resistance] change log level to verbose (#13268) --- esphome/components/ntc/ntc.cpp | 2 +- esphome/components/resistance/resistance_sensor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ntc/ntc.cpp b/esphome/components/ntc/ntc.cpp index b08f84029b..cc500ba429 100644 --- a/esphome/components/ntc/ntc.cpp +++ b/esphome/components/ntc/ntc.cpp @@ -23,7 +23,7 @@ void NTC::process_(float value) { double v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr; auto temp = float(1.0 / v - 273.15); - ESP_LOGD(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp); + ESP_LOGV(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp); this->publish_state(temp); } diff --git a/esphome/components/resistance/resistance_sensor.cpp b/esphome/components/resistance/resistance_sensor.cpp index 6e57214449..706a059de3 100644 --- a/esphome/components/resistance/resistance_sensor.cpp +++ b/esphome/components/resistance/resistance_sensor.cpp @@ -39,7 +39,7 @@ void ResistanceSensor::process_(float value) { } res *= this->resistor_; - ESP_LOGD(TAG, "'%s' - Resistance %.1fΩ", this->name_.c_str(), res); + ESP_LOGV(TAG, "'%s' - Resistance %.1fΩ", this->name_.c_str(), res); this->publish_state(res); } From d8463f48136aa94c870184a77ce71a8848b9ac50 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Jan 2026 17:16:38 -1000 Subject: [PATCH 0169/2030] [hmac_sha256] Replace unsafe sprintf with format_hex_to (#13290) --- esphome/components/hmac_sha256/hmac_sha256.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/esphome/components/hmac_sha256/hmac_sha256.cpp b/esphome/components/hmac_sha256/hmac_sha256.cpp index cf5daf63af..2146e961bc 100644 --- a/esphome/components/hmac_sha256/hmac_sha256.cpp +++ b/esphome/components/hmac_sha256/hmac_sha256.cpp @@ -1,4 +1,3 @@ -#include #include #include "hmac_sha256.h" #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_HOST) @@ -26,9 +25,7 @@ void HmacSHA256::calculate() { mbedtls_md_hmac_finish(&this->ctx_, this->digest_ void HmacSHA256::get_bytes(uint8_t *output) { memcpy(output, this->digest_, SHA256_DIGEST_SIZE); } void HmacSHA256::get_hex(char *output) { - for (size_t i = 0; i < SHA256_DIGEST_SIZE; i++) { - sprintf(output + (i * 2), "%02x", this->digest_[i]); - } + format_hex_to(output, SHA256_DIGEST_SIZE * 2 + 1, this->digest_, SHA256_DIGEST_SIZE); } bool HmacSHA256::equals_bytes(const uint8_t *expected) { From 60e333db088c0de3c2a2f8fe26f50f08ce0aca60 Mon Sep 17 00:00:00 2001 From: Stuart Parmenter Date: Fri, 16 Jan 2026 19:17:36 -0800 Subject: [PATCH 0170/2030] [hub75] Bump esp-hub75 version to 0.3.0 (#13243) --- esphome/components/hub75/display.py | 58 ++++++++++++++++++++++++----- esphome/idf_component.yml | 4 +- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 20c731e730..0eeb4bba33 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -1,3 +1,4 @@ +import logging from typing import Any from esphome import automation, pins @@ -18,13 +19,16 @@ from esphome.const import ( CONF_ROTATION, CONF_UPDATE_INTERVAL, ) -from esphome.core import ID +from esphome.core import ID, EnumValue from esphome.cpp_generator import MockObj, TemplateArgsType import esphome.final_validate as fv +from esphome.helpers import add_class_to_obj from esphome.types import ConfigType from . import boards, hub75_ns +_LOGGER = logging.getLogger(__name__) + DEPENDENCIES = ["esp32"] CODEOWNERS = ["@stuartparmenter"] @@ -120,13 +124,51 @@ PANEL_LAYOUTS = { } Hub75ScanWiring = cg.global_ns.enum("Hub75ScanWiring", is_class=True) -SCAN_PATTERNS = { +SCAN_WIRINGS = { "STANDARD_TWO_SCAN": Hub75ScanWiring.STANDARD_TWO_SCAN, - "FOUR_SCAN_16PX_HIGH": Hub75ScanWiring.FOUR_SCAN_16PX_HIGH, - "FOUR_SCAN_32PX_HIGH": Hub75ScanWiring.FOUR_SCAN_32PX_HIGH, - "FOUR_SCAN_64PX_HIGH": Hub75ScanWiring.FOUR_SCAN_64PX_HIGH, + "SCAN_1_4_16PX_HIGH": Hub75ScanWiring.SCAN_1_4_16PX_HIGH, + "SCAN_1_8_32PX_HIGH": Hub75ScanWiring.SCAN_1_8_32PX_HIGH, + "SCAN_1_8_40PX_HIGH": Hub75ScanWiring.SCAN_1_8_40PX_HIGH, + "SCAN_1_8_64PX_HIGH": Hub75ScanWiring.SCAN_1_8_64PX_HIGH, } +# Deprecated scan wiring names - mapped to new names +DEPRECATED_SCAN_WIRINGS = { + "FOUR_SCAN_16PX_HIGH": "SCAN_1_4_16PX_HIGH", + "FOUR_SCAN_32PX_HIGH": "SCAN_1_8_32PX_HIGH", + "FOUR_SCAN_64PX_HIGH": "SCAN_1_8_64PX_HIGH", +} + + +def _validate_scan_wiring(value): + """Validate scan_wiring with deprecation warnings for old names.""" + value = cv.string(value).upper().replace(" ", "_") + + # Check if using deprecated name + # Remove deprecated names in 2026.7.0 + if value in DEPRECATED_SCAN_WIRINGS: + new_name = DEPRECATED_SCAN_WIRINGS[value] + _LOGGER.warning( + "Scan wiring '%s' is deprecated and will be removed in ESPHome 2026.7.0. " + "Please use '%s' instead.", + value, + new_name, + ) + value = new_name + + # Validate against allowed values + if value not in SCAN_WIRINGS: + raise cv.Invalid( + f"Unknown scan wiring '{value}'. " + f"Valid options are: {', '.join(sorted(SCAN_WIRINGS.keys()))}" + ) + + # Return as EnumValue like cv.enum does + result = add_class_to_obj(value, EnumValue) + result.enum_value = SCAN_WIRINGS[value] + return result + + Hub75ClockSpeed = cg.global_ns.enum("Hub75ClockSpeed", is_class=True) CLOCK_SPEEDS = { "8MHZ": Hub75ClockSpeed.HZ_8M, @@ -382,9 +424,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_LAYOUT_COLS): cv.positive_int, cv.Optional(CONF_LAYOUT): cv.enum(PANEL_LAYOUTS, upper=True, space="_"), # Panel hardware configuration - cv.Optional(CONF_SCAN_WIRING): cv.enum( - SCAN_PATTERNS, upper=True, space="_" - ), + cv.Optional(CONF_SCAN_WIRING): _validate_scan_wiring, cv.Optional(CONF_SHIFT_DRIVER): cv.enum(SHIFT_DRIVERS, upper=True), # Display configuration cv.Optional(CONF_DOUBLE_BUFFER): cv.boolean, @@ -547,7 +587,7 @@ def _build_config_struct( async def to_code(config: ConfigType) -> None: add_idf_component( name="esphome/esp-hub75", - ref="0.2.2", + ref="0.3.0", ) # Set compile-time configuration via build flags (so external library sees them) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 045b3f9168..5903e68e8e 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -28,8 +28,8 @@ dependencies: rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: - version: 0.2.2 + version: 0.3.0 rules: - - if: "target in [esp32, esp32s2, esp32s3, esp32p4]" + - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" esp32async/asynctcp: version: 3.4.91 From 2947642ca5452b0aaa70958eac28a598bcb8b625 Mon Sep 17 00:00:00 2001 From: Mike Ford <60777900+HLFCode@users.noreply.github.com> Date: Sat, 17 Jan 2026 03:18:48 +0000 Subject: [PATCH 0171/2030] [http_request] Unable to handle chunked responses (#7884) Co-authored-by: J. Nick Koston --- esphome/components/http_request/http_request.h | 4 +--- .../components/http_request/http_request_idf.cpp | 16 +++++----------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 1b5fd9f00e..a8c2cdfc63 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -242,9 +242,7 @@ template class HttpRequestSendAction : public Action { return; } - size_t content_length = container->content_length; - size_t max_length = std::min(content_length, this->max_response_buffer_size_); - + size_t max_length = this->max_response_buffer_size_; #ifdef USE_HTTP_REQUEST_RESPONSE if (this->capture_response_.value(x...)) { std::string response_body; diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 725a9c1c1e..1de947ba5b 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -213,18 +213,12 @@ 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; + this->feed_wdt(); + int read_len = esp_http_client_read(this->client_, (char *) buf, max_len); + this->feed_wdt(); + if (read_len > 0) { + this->bytes_read_ += read_len; } - - this->feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, bufsize); - this->feed_wdt(); - this->bytes_read_ += read_len; - this->duration_ms += (millis() - start); return read_len; From 19514ccdf46cba78fac445be095ec91d34260519 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:05:59 -0500 Subject: [PATCH 0172/2030] Bump version to 2026.1.0b3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index aa6a2f169e..4b38bb779e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0b2 +PROJECT_NUMBER = 2026.1.0b3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index e99fbb8283..35ce8b3cd6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0b2" +__version__ = "2026.1.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 3f892711c7c31e92ba4a8a732e8e34a4338bf54e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 11:09:42 -1000 Subject: [PATCH 0173/2030] [core][opentherm] Add format_bin_to(), soft-deprecate format_bin() (#13232) --- esphome/components/opentherm/opentherm.cpp | 5 +- esphome/core/helpers.cpp | 28 ++++++++--- esphome/core/helpers.h | 57 ++++++++++++++++++++++ script/ci-custom.py | 2 + 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/esphome/components/opentherm/opentherm.cpp b/esphome/components/opentherm/opentherm.cpp index c6443f1282..2bf438a52f 100644 --- a/esphome/components/opentherm/opentherm.cpp +++ b/esphome/components/opentherm/opentherm.cpp @@ -561,8 +561,9 @@ const char *OpenTherm::message_id_to_str(MessageId id) { } void OpenTherm::debug_data(OpenthermData &data) { - ESP_LOGD(TAG, "%s %s %s %s", format_bin(data.type).c_str(), format_bin(data.id).c_str(), - format_bin(data.valueHB).c_str(), format_bin(data.valueLB).c_str()); + char type_buf[9], id_buf[9], hb_buf[9], lb_buf[9]; + ESP_LOGD(TAG, "%s %s %s %s", format_bin_to(type_buf, data.type), format_bin_to(id_buf, data.id), + format_bin_to(hb_buf, data.valueHB), format_bin_to(lb_buf, data.valueLB)); ESP_LOGD(TAG, "type: %s; id: %u; HB: %u; LB: %u; uint_16: %u; float: %f", this->message_type_to_str((MessageType) data.type), data.id, data.valueHB, data.valueLB, data.u16(), data.f88()); diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 5de1c70562..4e3761675d 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -404,15 +404,31 @@ std::string format_hex_pretty(const std::string &data, char separator, bool show return format_hex_pretty_uint8(reinterpret_cast(data.data()), data.length(), separator, show_length); } +char *format_bin_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length) { + if (buffer_size == 0) { + return buffer; + } + // Calculate max bytes we can format: each byte needs 8 chars + size_t max_bytes = (buffer_size - 1) / 8; + if (max_bytes == 0 || length == 0) { + buffer[0] = '\0'; + return buffer; + } + size_t bytes_to_format = std::min(length, max_bytes); + + for (size_t byte_idx = 0; byte_idx < bytes_to_format; byte_idx++) { + for (size_t bit_idx = 0; bit_idx < 8; bit_idx++) { + buffer[byte_idx * 8 + bit_idx] = ((data[byte_idx] >> (7 - bit_idx)) & 1) + '0'; + } + } + buffer[bytes_to_format * 8] = '\0'; + return buffer; +} + std::string format_bin(const uint8_t *data, size_t length) { std::string result; result.resize(length * 8); - for (size_t byte_idx = 0; byte_idx < length; byte_idx++) { - for (size_t bit_idx = 0; bit_idx < 8; bit_idx++) { - result[byte_idx * 8 + bit_idx] = ((data[byte_idx] >> (7 - bit_idx)) & 1) + '0'; - } - } - + format_bin_to(&result[0], length * 8 + 1, data, length); return result; } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 0acc6bdc60..409c691cb1 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1096,9 +1096,66 @@ std::string format_hex_pretty(T val, char separator = '.', bool show_length = tr return format_hex_pretty(reinterpret_cast(&val), sizeof(T), separator, show_length); } +/// Calculate buffer size needed for format_bin_to: "01234567...\0" = bytes * 8 + 1 +constexpr size_t format_bin_size(size_t byte_count) { return byte_count * 8 + 1; } + +/** Format byte array as binary string to buffer. + * + * Each byte is formatted as 8 binary digits (MSB first). + * Truncates output if data exceeds buffer capacity. + * + * @param buffer Output buffer to write to. + * @param buffer_size Size of the output buffer. + * @param data Pointer to the byte array to format. + * @param length Number of bytes in the array. + * @return Pointer to buffer. + * + * Buffer size needed: length * 8 + 1 (use format_bin_size()). + * + * Example: + * @code + * char buf[9]; // format_bin_size(1) + * format_bin_to(buf, sizeof(buf), data, 1); // "10101011" + * @endcode + */ +char *format_bin_to(char *buffer, size_t buffer_size, const uint8_t *data, size_t length); + +/// Format byte array as binary to buffer. Automatically deduces buffer size. +template inline char *format_bin_to(char (&buffer)[N], const uint8_t *data, size_t length) { + static_assert(N >= 9, "Buffer must hold at least one binary byte (9 chars)"); + return format_bin_to(buffer, N, data, length); +} + +/** Format an unsigned integer in binary to buffer, MSB first. + * + * @tparam N Buffer size (must be >= sizeof(T) * 8 + 1). + * @tparam T Unsigned integer type. + * @param buffer Output buffer to write to. + * @param val The unsigned integer value to format. + * @return Pointer to buffer. + * + * Example: + * @code + * char buf[9]; // format_bin_size(sizeof(uint8_t)) + * format_bin_to(buf, uint8_t{0xAA}); // "10101010" + * char buf16[17]; // format_bin_size(sizeof(uint16_t)) + * format_bin_to(buf16, uint16_t{0x1234}); // "0001001000110100" + * @endcode + */ +template::value, int> = 0> +inline char *format_bin_to(char (&buffer)[N], T val) { + static_assert(N >= sizeof(T) * 8 + 1, "Buffer too small for type"); + val = convert_big_endian(val); + return format_bin_to(buffer, reinterpret_cast(&val), sizeof(T)); +} + /// Format the byte array \p data of length \p len in binary. +/// @warning Allocates heap memory. Use format_bin_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. std::string format_bin(const uint8_t *data, size_t length); /// Format an unsigned integer in binary, starting with the most significant byte. +/// @warning Allocates heap memory. Use format_bin_to() with a stack buffer instead. +/// Causes heap fragmentation on long-running devices. template::value, int> = 0> std::string format_bin(T val) { val = convert_big_endian(val); return format_bin(reinterpret_cast(&val), sizeof(T)); diff --git a/script/ci-custom.py b/script/ci-custom.py index e63e61e096..e227ec873e 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -682,6 +682,7 @@ def lint_trailing_whitespace(fname, match): # Heap-allocating helpers that cause fragmentation on long-running embedded devices. # These return std::string and should be replaced with stack-based alternatives. HEAP_ALLOCATING_HELPERS = { + "format_bin": "format_bin_to() with a stack buffer", "format_hex": "format_hex_to() with a stack buffer", "format_hex_pretty": "format_hex_pretty_to() with a stack buffer", "format_mac_address_pretty": "format_mac_addr_upper() with a stack buffer", @@ -699,6 +700,7 @@ HEAP_ALLOCATING_HELPERS = { # get_mac_address(?!_) ensures we don't match get_mac_address_into_buffer, etc. # CPP_RE_EOL captures rest of line so NOLINT comments are detected r"[^\w](" + r"format_bin(?!_)|" r"format_hex(?!_)|" r"format_hex_pretty(?!_)|" r"format_mac_address_pretty|" From b25a2f8d8e0d31284a3489431b310d02be1ef6ab Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sat, 17 Jan 2026 16:01:13 -0600 Subject: [PATCH 0174/2030] [infrared][web_server] Implement initial `web_server` support (#13202) Co-authored-by: J. Nick Koston Co-authored-by: J. Nick Koston --- .../components/web_server/list_entities.cpp | 2 +- esphome/components/web_server/web_server.cpp | 116 ++++++++++++++++++ esphome/components/web_server/web_server.h | 10 ++ 3 files changed, 127 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 0af9521326..8458298062 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -143,7 +143,7 @@ bool ListEntitiesIterator::on_water_heater(water_heater::WaterHeater *obj) { #ifdef USE_INFRARED bool ListEntitiesIterator::on_infrared(infrared::Infrared *obj) { - // Infrared web_server support not yet implemented - this stub acknowledges the entity + this->events_->deferrable_send_state(obj, "state_detail_all", WebServer::infrared_all_json_generator); return true; } #endif diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 0e71d82233..593e0c32e3 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -33,6 +33,10 @@ #include "esphome/components/water_heater/water_heater.h" #endif +#ifdef USE_INFRARED +#include "esphome/components/infrared/infrared.h" +#endif + #ifdef USE_WEBSERVER_LOCAL #if USE_WEBSERVER_VERSION == 2 #include "server_index_v2.h" @@ -1952,6 +1956,110 @@ std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDe } #endif +#ifdef USE_INFRARED +void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const UrlMatch &match) { + for (infrared::Infrared *obj : App.get_infrareds()) { + auto entity_match = match.match_entity(obj); + if (!entity_match.matched) + continue; + + if (request->method() == HTTP_GET && entity_match.action_is_empty) { + auto detail = get_request_detail(request); + std::string data = this->infrared_json_(obj, detail); + request->send(200, ESPHOME_F("application/json"), data.c_str()); + return; + } + if (!match.method_equals(ESPHOME_F("transmit"))) { + request->send(404); + return; + } + + // Only allow transmit if the device supports it + if (!obj->has_transmitter()) { + request->send(400, ESPHOME_F("text/plain"), "Device does not support transmission"); + return; + } + + // Parse parameters + auto call = obj->make_call(); + + // Parse carrier frequency (optional) + if (request->hasParam(ESPHOME_F("carrier_frequency"))) { + auto value = parse_number(request->getParam(ESPHOME_F("carrier_frequency"))->value().c_str()); + if (value.has_value()) { + call.set_carrier_frequency(*value); + } + } + + // Parse repeat count (optional, defaults to 1) + if (request->hasParam(ESPHOME_F("repeat_count"))) { + auto value = parse_number(request->getParam(ESPHOME_F("repeat_count"))->value().c_str()); + if (value.has_value()) { + call.set_repeat_count(*value); + } + } + + // Parse base64url-encoded raw timings (required) + // Base64url is URL-safe: uses A-Za-z0-9-_ (no special characters needing escaping) + if (!request->hasParam(ESPHOME_F("data"))) { + request->send(400, ESPHOME_F("text/plain"), "Missing 'data' parameter"); + return; + } + + // .c_str() is required for Arduino framework where value() returns Arduino String instead of std::string + std::string encoded = + request->getParam(ESPHOME_F("data"))->value().c_str(); // NOLINT(readability-redundant-string-cstr) + + // Validate base64url is not empty + if (encoded.empty()) { + request->send(400, ESPHOME_F("text/plain"), "Empty 'data' parameter"); + return; + } + +#ifdef USE_ESP8266 + // ESP8266 is single-threaded, call directly + call.set_raw_timings_base64url(encoded); + call.perform(); +#else + // Defer to main loop for thread safety. Move encoded string into lambda to ensure + // it outlives the call - set_raw_timings_base64url stores a pointer, so the string + // must remain valid until perform() completes. + this->defer([call, encoded = std::move(encoded)]() mutable { + call.set_raw_timings_base64url(encoded); + call.perform(); + }); +#endif + + request->send(200); + return; + } + request->send(404); +} + +std::string WebServer::infrared_all_json_generator(WebServer *web_server, void *source) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + return web_server->infrared_json_(static_cast(source), DETAIL_ALL); +} + +std::string WebServer::infrared_json_(infrared::Infrared *obj, JsonDetail start_config) { + json::JsonBuilder builder; + JsonObject root = builder.root(); + + set_json_icon_state_value(root, obj, "infrared", "", 0, start_config); + + auto traits = obj->get_traits(); + + root[ESPHOME_F("supports_transmitter")] = traits.get_supports_transmitter(); + root[ESPHOME_F("supports_receiver")] = traits.get_supports_receiver(); + + if (start_config == DETAIL_ALL) { + this->add_sorting_info_(root, obj); + } + + return builder.serialize(); +} +#endif + #ifdef USE_EVENT void WebServer::on_event(event::Event *obj) { if (!this->include_internal_ && obj->is_internal()) @@ -2187,6 +2295,9 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const { #endif #ifdef USE_WATER_HEATER "water_heater", +#endif +#ifdef USE_INFRARED + "infrared", #endif }; @@ -2352,6 +2463,11 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { else if (match.domain_equals(ESPHOME_F("water_heater"))) { this->handle_water_heater_request(request, match); } +#endif +#ifdef USE_INFRARED + else if (match.domain_equals(ESPHOME_F("infrared"))) { + this->handle_infrared_request(request, match); + } #endif else { // No matching handler found - send 404 diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index c434d664cf..92a5c7edee 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -460,6 +460,13 @@ class WebServer : public Controller, static std::string water_heater_all_json_generator(WebServer *web_server, void *source); #endif +#ifdef USE_INFRARED + /// Handle an infrared request under '/infrared//transmit'. + void handle_infrared_request(AsyncWebServerRequest *request, const UrlMatch &match); + + static std::string infrared_all_json_generator(WebServer *web_server, void *source); +#endif + #ifdef USE_EVENT void on_event(event::Event *obj) override; @@ -662,6 +669,9 @@ class WebServer : public Controller, #ifdef USE_WATER_HEATER std::string water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config); #endif +#ifdef USE_INFRARED + std::string infrared_json_(infrared::Infrared *obj, JsonDetail start_config); +#endif #ifdef USE_UPDATE std::string update_json_(update::UpdateEntity *obj, JsonDetail start_config); #endif From d31b733dce983f66171c1ab0d0b5d01ab2ea1f40 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 12:06:25 -1000 Subject: [PATCH 0175/2030] [light] Store color mode JSON strings in flash on ESP8266 (#13314) --- .../components/light/light_json_schema.cpp | 50 ++++++++++--------- esphome/core/progmem.h | 4 ++ 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/esphome/components/light/light_json_schema.cpp b/esphome/components/light/light_json_schema.cpp index f370980737..631f59221f 100644 --- a/esphome/components/light/light_json_schema.cpp +++ b/esphome/components/light/light_json_schema.cpp @@ -1,4 +1,5 @@ #include "light_json_schema.h" +#include "color_mode.h" #include "light_output.h" #include "esphome/core/progmem.h" @@ -8,29 +9,32 @@ namespace esphome::light { // See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema -// Get JSON string for color mode using linear search (avoids large switch jump table) -static const char *get_color_mode_json_str(ColorMode mode) { - // Parallel arrays: mode values and their corresponding strings - // Uses less RAM than a switch jump table on sparse enum values - static constexpr ColorMode MODES[] = { - ColorMode::ON_OFF, - ColorMode::BRIGHTNESS, - ColorMode::WHITE, - ColorMode::COLOR_TEMPERATURE, - ColorMode::COLD_WARM_WHITE, - ColorMode::RGB, - ColorMode::RGB_WHITE, - ColorMode::RGB_COLOR_TEMPERATURE, - ColorMode::RGB_COLD_WARM_WHITE, - }; - static constexpr const char *STRINGS[] = { - "onoff", "brightness", "white", "color_temp", "cwww", "rgb", "rgbw", "rgbct", "rgbww", - }; - for (size_t i = 0; i < sizeof(MODES) / sizeof(MODES[0]); i++) { - if (MODES[i] == mode) - return STRINGS[i]; +// Get JSON string for color mode. +// ColorMode enum values are sparse bitmasks (0, 1, 3, 7, 11, 19, 35, 39, 47, 51) which would +// generate a large jump table. Converting to bit index (0-9) allows a compact switch. +static ProgmemStr get_color_mode_json_str(ColorMode mode) { + switch (ColorModeBitPolicy::to_bit(mode)) { + case 1: + return ESPHOME_F("onoff"); + case 2: + return ESPHOME_F("brightness"); + case 3: + return ESPHOME_F("white"); + case 4: + return ESPHOME_F("color_temp"); + case 5: + return ESPHOME_F("cwww"); + case 6: + return ESPHOME_F("rgb"); + case 7: + return ESPHOME_F("rgbw"); + case 8: + return ESPHOME_F("rgbct"); + case 9: + return ESPHOME_F("rgbww"); + default: + return nullptr; } - return nullptr; } void LightJSONSchema::dump_json(LightState &state, JsonObject root) { @@ -44,7 +48,7 @@ void LightJSONSchema::dump_json(LightState &state, JsonObject root) { auto values = state.remote_values; const auto color_mode = values.get_color_mode(); - const char *mode_str = get_color_mode_json_str(color_mode); + const auto *mode_str = get_color_mode_json_str(color_mode); if (mode_str != nullptr) { root[ESPHOME_F("color_mode")] = mode_str; } diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index fe9c9b5a75..6c3e4cec96 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -12,6 +12,8 @@ #define ESPHOME_strncpy_P strncpy_P #define ESPHOME_strncat_P strncat_P #define ESPHOME_snprintf_P snprintf_P +// Type for pointers to PROGMEM strings (for use with ESPHOME_F return values) +using ProgmemStr = const __FlashStringHelper *; #else #define ESPHOME_F(string_literal) (string_literal) #define ESPHOME_PGM_P const char * @@ -19,4 +21,6 @@ #define ESPHOME_strncpy_P strncpy #define ESPHOME_strncat_P strncat #define ESPHOME_snprintf_P snprintf +// Type for pointers to strings (no PROGMEM on non-ESP8266 platforms) +using ProgmemStr = const char *; #endif From e4fb6988ff96ba121f646bf7fc842c2e7fc0ea6d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 12:29:29 -1000 Subject: [PATCH 0176/2030] [web_server] Use ESPHOME_F for canHandle domain checks to reduce ESP8266 RAM (#13315) Co-authored-by: Keith Burzinski --- esphome/components/web_server/web_server.cpp | 178 ++++++++++--------- 1 file changed, 91 insertions(+), 87 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 593e0c32e3..61b9ea5163 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -2191,24 +2191,21 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const { const auto &url = request->url(); const auto method = request->method(); - // Static URL checks - static const char *const STATIC_URLS[] = { - "/", + // Static URL checks - use ESPHOME_F to keep strings in flash on ESP8266 + if (url == ESPHOME_F("/")) + return true; #if !defined(USE_ESP32) && defined(USE_ARDUINO) - "/events", + if (url == ESPHOME_F("/events")) + return true; #endif #ifdef USE_WEBSERVER_CSS_INCLUDE - "/0.css", + if (url == ESPHOME_F("/0.css")) + return true; #endif #ifdef USE_WEBSERVER_JS_INCLUDE - "/0.js", + if (url == ESPHOME_F("/0.js")) + return true; #endif - }; - - for (const auto &static_url : STATIC_URLS) { - if (url == static_url) - return true; - } #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS if (method == HTTP_OPTIONS && request->hasHeader(ESPHOME_F("Access-Control-Request-Private-Network"))) @@ -2228,93 +2225,100 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const { if (!is_get_or_post) return false; - // Use lookup tables for domain checks - static const char *const GET_ONLY_DOMAINS[] = { + // Check GET-only domains - use ESPHOME_F to keep strings in flash on ESP8266 + if (is_get) { #ifdef USE_SENSOR - "sensor", + if (match.domain_equals(ESPHOME_F("sensor"))) + return true; #endif #ifdef USE_BINARY_SENSOR - "binary_sensor", + if (match.domain_equals(ESPHOME_F("binary_sensor"))) + return true; #endif #ifdef USE_TEXT_SENSOR - "text_sensor", + if (match.domain_equals(ESPHOME_F("text_sensor"))) + return true; #endif #ifdef USE_EVENT - "event", + if (match.domain_equals(ESPHOME_F("event"))) + return true; #endif - }; - - static const char *const GET_POST_DOMAINS[] = { -#ifdef USE_SWITCH - "switch", -#endif -#ifdef USE_BUTTON - "button", -#endif -#ifdef USE_FAN - "fan", -#endif -#ifdef USE_LIGHT - "light", -#endif -#ifdef USE_COVER - "cover", -#endif -#ifdef USE_NUMBER - "number", -#endif -#ifdef USE_DATETIME_DATE - "date", -#endif -#ifdef USE_DATETIME_TIME - "time", -#endif -#ifdef USE_DATETIME_DATETIME - "datetime", -#endif -#ifdef USE_TEXT - "text", -#endif -#ifdef USE_SELECT - "select", -#endif -#ifdef USE_CLIMATE - "climate", -#endif -#ifdef USE_LOCK - "lock", -#endif -#ifdef USE_VALVE - "valve", -#endif -#ifdef USE_ALARM_CONTROL_PANEL - "alarm_control_panel", -#endif -#ifdef USE_UPDATE - "update", -#endif -#ifdef USE_WATER_HEATER - "water_heater", -#endif -#ifdef USE_INFRARED - "infrared", -#endif - }; - - // Check GET-only domains - if (is_get) { - for (const auto &domain : GET_ONLY_DOMAINS) { - if (match.domain_equals(domain)) - return true; - } } // Check GET+POST domains if (is_get_or_post) { - for (const auto &domain : GET_POST_DOMAINS) { - if (match.domain_equals(domain)) - return true; - } +#ifdef USE_SWITCH + if (match.domain_equals(ESPHOME_F("switch"))) + return true; +#endif +#ifdef USE_BUTTON + if (match.domain_equals(ESPHOME_F("button"))) + return true; +#endif +#ifdef USE_FAN + if (match.domain_equals(ESPHOME_F("fan"))) + return true; +#endif +#ifdef USE_LIGHT + if (match.domain_equals(ESPHOME_F("light"))) + return true; +#endif +#ifdef USE_COVER + if (match.domain_equals(ESPHOME_F("cover"))) + return true; +#endif +#ifdef USE_NUMBER + if (match.domain_equals(ESPHOME_F("number"))) + return true; +#endif +#ifdef USE_DATETIME_DATE + if (match.domain_equals(ESPHOME_F("date"))) + return true; +#endif +#ifdef USE_DATETIME_TIME + if (match.domain_equals(ESPHOME_F("time"))) + return true; +#endif +#ifdef USE_DATETIME_DATETIME + if (match.domain_equals(ESPHOME_F("datetime"))) + return true; +#endif +#ifdef USE_TEXT + if (match.domain_equals(ESPHOME_F("text"))) + return true; +#endif +#ifdef USE_SELECT + if (match.domain_equals(ESPHOME_F("select"))) + return true; +#endif +#ifdef USE_CLIMATE + if (match.domain_equals(ESPHOME_F("climate"))) + return true; +#endif +#ifdef USE_LOCK + if (match.domain_equals(ESPHOME_F("lock"))) + return true; +#endif +#ifdef USE_VALVE + if (match.domain_equals(ESPHOME_F("valve"))) + return true; +#endif +#ifdef USE_ALARM_CONTROL_PANEL + if (match.domain_equals(ESPHOME_F("alarm_control_panel"))) + return true; +#endif +#ifdef USE_UPDATE + if (match.domain_equals(ESPHOME_F("update"))) + return true; +#endif +#ifdef USE_WATER_HEATER + if (match.domain_equals(ESPHOME_F("water_heater"))) + return true; +#endif +#ifdef USE_INFRARED + if (match.domain_equals(ESPHOME_F("infrared"))) + return true; +#endif } return false; From 4d4283bcfa1fa9f7d1139a45206418b476b07a7b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:50:23 -1000 Subject: [PATCH 0177/2030] [udp] Store addresses in flash instead of heap (#13330) --- esphome/components/udp/__init__.py | 3 +- esphome/components/udp/udp_component.cpp | 12 +- esphome/components/udp/udp_component.h | 14 +- tests/components/udp/common.yaml | 5 +- .../fixtures/udp_send_receive.yaml | 33 ++++ tests/integration/test_udp.py | 171 ++++++++++++++++++ 6 files changed, 222 insertions(+), 16 deletions(-) create mode 100644 tests/integration/fixtures/udp_send_receive.yaml create mode 100644 tests/integration/test_udp.py diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 69abf4b989..9be196d420 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -108,8 +108,7 @@ async def to_code(config): cg.add(var.set_broadcast_port(conf_port[CONF_BROADCAST_PORT])) if (listen_address := str(config[CONF_LISTEN_ADDRESS])) != "255.255.255.255": cg.add(var.set_listen_address(listen_address)) - for address in config[CONF_ADDRESSES]: - cg.add(var.add_address(str(address))) + cg.add(var.set_addresses([str(addr) for addr in config[CONF_ADDRESSES]])) if on_receive := config.get(CONF_ON_RECEIVE): on_receive = on_receive[0] trigger = cg.new_Pvariable(on_receive[CONF_TRIGGER_ID]) diff --git a/esphome/components/udp/udp_component.cpp b/esphome/components/udp/udp_component.cpp index 4474efeb77..947a59dfa9 100644 --- a/esphome/components/udp/udp_component.cpp +++ b/esphome/components/udp/udp_component.cpp @@ -5,8 +5,7 @@ #include "esphome/components/network/util.h" #include "udp_component.h" -namespace esphome { -namespace udp { +namespace esphome::udp { static const char *const TAG = "udp"; @@ -95,7 +94,7 @@ void UDPComponent::setup() { // 8266 and RP2040 `Duino for (const auto &address : this->addresses_) { auto ipaddr = IPAddress(); - ipaddr.fromString(address.c_str()); + ipaddr.fromString(address); this->ipaddrs_.push_back(ipaddr); } if (this->should_listen_) @@ -130,8 +129,8 @@ void UDPComponent::dump_config() { " Listen Port: %u\n" " Broadcast Port: %u", this->listen_port_, this->broadcast_port_); - for (const auto &address : this->addresses_) - ESP_LOGCONFIG(TAG, " Address: %s", address.c_str()); + for (const char *address : this->addresses_) + ESP_LOGCONFIG(TAG, " Address: %s", address); if (this->listen_address_.has_value()) { char addr_buf[network::IP_ADDRESS_BUFFER_SIZE]; ESP_LOGCONFIG(TAG, " Listen address: %s", this->listen_address_.value().str_to(addr_buf)); @@ -162,7 +161,6 @@ void UDPComponent::send_packet(const uint8_t *data, size_t size) { } #endif } -} // namespace udp -} // namespace esphome +} // namespace esphome::udp #endif diff --git a/esphome/components/udp/udp_component.h b/esphome/components/udp/udp_component.h index 065789ae28..9967e4dbbb 100644 --- a/esphome/components/udp/udp_component.h +++ b/esphome/components/udp/udp_component.h @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #ifdef USE_NETWORK +#include "esphome/core/helpers.h" #include "esphome/components/network/ip_address.h" #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) #include "esphome/components/socket/socket.h" @@ -9,15 +10,17 @@ #ifdef USE_SOCKET_IMPL_LWIP_TCP #include #endif +#include #include -namespace esphome { -namespace udp { +namespace esphome::udp { static const size_t MAX_PACKET_SIZE = 508; class UDPComponent : public Component { public: - void add_address(const char *addr) { this->addresses_.emplace_back(addr); } + void set_addresses(std::initializer_list addresses) { this->addresses_ = addresses; } + /// Prevent accidental use of std::string which would dangle + void set_addresses(std::initializer_list addresses) = delete; void set_listen_address(const char *listen_addr) { this->listen_address_ = network::IPAddress(listen_addr); } void set_listen_port(uint16_t port) { this->listen_port_ = port; } void set_broadcast_port(uint16_t port) { this->broadcast_port_ = port; } @@ -49,11 +52,10 @@ class UDPComponent : public Component { std::vector ipaddrs_{}; WiFiUDP udp_client_{}; #endif - std::vector addresses_{}; + FixedVector addresses_{}; optional listen_address_{}; }; -} // namespace udp -} // namespace esphome +} // namespace esphome::udp #endif diff --git a/tests/components/udp/common.yaml b/tests/components/udp/common.yaml index 98546d49ef..3466e8d2ee 100644 --- a/tests/components/udp/common.yaml +++ b/tests/components/udp/common.yaml @@ -5,7 +5,10 @@ wifi: udp: id: my_udp listen_address: 239.0.60.53 - addresses: ["239.0.60.53"] + addresses: + - "239.0.60.53" + - "192.168.1.255" + - "10.0.0.255" on_receive: - logger.log: format: "Received %d bytes" diff --git a/tests/integration/fixtures/udp_send_receive.yaml b/tests/integration/fixtures/udp_send_receive.yaml new file mode 100644 index 0000000000..155d932722 --- /dev/null +++ b/tests/integration/fixtures/udp_send_receive.yaml @@ -0,0 +1,33 @@ +esphome: + name: udp-test + +host: + +api: + services: + - service: send_udp_message + then: + - udp.write: + id: test_udp + data: "HELLO_UDP_TEST" + - service: send_udp_bytes + then: + - udp.write: + id: test_udp + data: [0x55, 0x44, 0x50, 0x5F, 0x42, 0x59, 0x54, 0x45, 0x53] # "UDP_BYTES" + +logger: + level: DEBUG + +udp: + - id: test_udp + addresses: + - "127.0.0.1" + - "127.0.0.2" + port: + listen_port: UDP_LISTEN_PORT_PLACEHOLDER + broadcast_port: UDP_BROADCAST_PORT_PLACEHOLDER + on_receive: + - logger.log: + format: "Received UDP: %d bytes" + args: [data.size()] diff --git a/tests/integration/test_udp.py b/tests/integration/test_udp.py new file mode 100644 index 0000000000..74c7ef60e3 --- /dev/null +++ b/tests/integration/test_udp.py @@ -0,0 +1,171 @@ +"""Integration test for UDP component.""" + +from __future__ import annotations + +import asyncio +from collections.abc import AsyncGenerator +import contextlib +from contextlib import asynccontextmanager +from dataclasses import dataclass, field +import socket + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@dataclass +class UDPReceiver: + """Collects UDP messages received.""" + + messages: list[bytes] = field(default_factory=list) + message_received: asyncio.Event = field(default_factory=asyncio.Event) + + def on_message(self, data: bytes) -> None: + """Called when a message is received.""" + self.messages.append(data) + self.message_received.set() + + async def wait_for_message(self, timeout: float = 5.0) -> bytes: + """Wait for a message to be received.""" + await asyncio.wait_for(self.message_received.wait(), timeout=timeout) + return self.messages[-1] + + async def wait_for_content(self, content: bytes, timeout: float = 5.0) -> bytes: + """Wait for a specific message content.""" + deadline = asyncio.get_event_loop().time() + timeout + while True: + for msg in self.messages: + if content in msg: + return msg + remaining = deadline - asyncio.get_event_loop().time() + if remaining <= 0: + raise TimeoutError( + f"Content {content!r} not found in messages: {self.messages}" + ) + try: + await asyncio.wait_for(self.message_received.wait(), timeout=remaining) + self.message_received.clear() + except TimeoutError: + raise TimeoutError( + f"Content {content!r} not found in messages: {self.messages}" + ) from None + + +@asynccontextmanager +async def udp_listener(port: int = 0) -> AsyncGenerator[tuple[int, UDPReceiver]]: + """Async context manager that listens for UDP messages. + + Args: + port: Port to listen on. 0 for auto-assign. + + Yields: + Tuple of (port, UDPReceiver) where port is the UDP port being listened on. + """ + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(("127.0.0.1", port)) + sock.setblocking(False) + actual_port = sock.getsockname()[1] + + receiver = UDPReceiver() + + async def receive_messages() -> None: + """Background task to receive UDP messages.""" + loop = asyncio.get_running_loop() + while True: + try: + data = await loop.sock_recv(sock, 4096) + if data: + receiver.on_message(data) + except BlockingIOError: + await asyncio.sleep(0.01) + except Exception: + break + + task = asyncio.create_task(receive_messages()) + try: + yield actual_port, receiver + finally: + task.cancel() + with contextlib.suppress(asyncio.CancelledError): + await task + sock.close() + + +@pytest.mark.asyncio +async def test_udp_send_receive( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test UDP component can send messages with multiple addresses configured.""" + # Track log lines to verify dump_config output + log_lines: list[str] = [] + + def on_log_line(line: str) -> None: + log_lines.append(line) + + async with udp_listener() as (udp_port, receiver): + # Replace placeholders in the config + config = yaml_config.replace("UDP_LISTEN_PORT_PLACEHOLDER", str(udp_port + 1)) + config = config.replace("UDP_BROADCAST_PORT_PLACEHOLDER", str(udp_port)) + + async with ( + run_compiled(config, line_callback=on_log_line), + api_client_connected() as client, + ): + # Verify device is running + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "udp-test" + + # Get services + _, services = await client.list_entities_services() + + # Test sending string message + send_message_service = next( + (s for s in services if s.name == "send_udp_message"), None + ) + assert send_message_service is not None, ( + "send_udp_message service not found" + ) + + await client.execute_service(send_message_service, {}) + + try: + msg = await receiver.wait_for_content(b"HELLO_UDP_TEST", timeout=5.0) + assert b"HELLO_UDP_TEST" in msg + except TimeoutError: + pytest.fail( + f"UDP string message not received. Got: {receiver.messages}" + ) + + # Test sending bytes + send_bytes_service = next( + (s for s in services if s.name == "send_udp_bytes"), None + ) + assert send_bytes_service is not None, "send_udp_bytes service not found" + + await client.execute_service(send_bytes_service, {}) + + try: + msg = await receiver.wait_for_content(b"UDP_BYTES", timeout=5.0) + assert b"UDP_BYTES" in msg + except TimeoutError: + pytest.fail(f"UDP bytes message not received. Got: {receiver.messages}") + + # Verify we received at least 2 messages (string + bytes) + assert len(receiver.messages) >= 2, ( + f"Expected at least 2 messages, got {len(receiver.messages)}" + ) + + # Verify dump_config logged all configured addresses + # This tests that FixedVector stores addresses correctly + log_text = "\n".join(log_lines) + assert "Address: 127.0.0.1" in log_text, ( + f"Address 127.0.0.1 not found in dump_config. Log: {log_text[-2000:]}" + ) + assert "Address: 127.0.0.2" in log_text, ( + f"Address 127.0.0.2 not found in dump_config. Log: {log_text[-2000:]}" + ) From 0a1e7ee50b1eae6a32e1318a3cf34b6cd5d2f1f1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:50:42 -1000 Subject: [PATCH 0178/2030] [pipsolar] Store command strings in flash (#13336) --- .../components/pipsolar/output/pipsolar_output.cpp | 2 +- .../components/pipsolar/output/pipsolar_output.h | 8 +++++--- .../components/pipsolar/switch/pipsolar_switch.cpp | 11 +++-------- .../components/pipsolar/switch/pipsolar_switch.h | 13 ++++++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/esphome/components/pipsolar/output/pipsolar_output.cpp b/esphome/components/pipsolar/output/pipsolar_output.cpp index 163fbf4eb2..ebfb9a7bbc 100644 --- a/esphome/components/pipsolar/output/pipsolar_output.cpp +++ b/esphome/components/pipsolar/output/pipsolar_output.cpp @@ -9,7 +9,7 @@ static const char *const TAG = "pipsolar.output"; void PipsolarOutput::write_state(float state) { char tmp[10]; - sprintf(tmp, this->set_command_.c_str(), state); + snprintf(tmp, sizeof(tmp), this->set_command_, state); if (std::find(this->possible_values_.begin(), this->possible_values_.end(), state) != this->possible_values_.end()) { ESP_LOGD(TAG, "Will write: %s out of value %f / %02.0f", tmp, state, state); diff --git a/esphome/components/pipsolar/output/pipsolar_output.h b/esphome/components/pipsolar/output/pipsolar_output.h index b4b8000962..66eda8e391 100644 --- a/esphome/components/pipsolar/output/pipsolar_output.h +++ b/esphome/components/pipsolar/output/pipsolar_output.h @@ -15,13 +15,15 @@ class PipsolarOutput : public output::FloatOutput { public: PipsolarOutput() {} void set_parent(Pipsolar *parent) { this->parent_ = parent; } - void set_set_command(const std::string &command) { this->set_command_ = command; }; + void set_set_command(const char *command) { this->set_command_ = command; } + /// Prevent accidental use of std::string which would dangle + void set_set_command(const std::string &command) = delete; void set_possible_values(std::vector possible_values) { this->possible_values_ = std::move(possible_values); } - void set_value(float value) { this->write_state(value); }; + void set_value(float value) { this->write_state(value); } protected: void write_state(float state) override; - std::string set_command_; + const char *set_command_{nullptr}; Pipsolar *parent_; std::vector possible_values_; }; diff --git a/esphome/components/pipsolar/switch/pipsolar_switch.cpp b/esphome/components/pipsolar/switch/pipsolar_switch.cpp index 649d951618..512587511b 100644 --- a/esphome/components/pipsolar/switch/pipsolar_switch.cpp +++ b/esphome/components/pipsolar/switch/pipsolar_switch.cpp @@ -9,14 +9,9 @@ static const char *const TAG = "pipsolar.switch"; void PipsolarSwitch::dump_config() { LOG_SWITCH("", "Pipsolar Switch", this); } void PipsolarSwitch::write_state(bool state) { - if (state) { - if (!this->on_command_.empty()) { - this->parent_->queue_command(this->on_command_); - } - } else { - if (!this->off_command_.empty()) { - this->parent_->queue_command(this->off_command_); - } + const char *command = state ? this->on_command_ : this->off_command_; + if (command != nullptr) { + this->parent_->queue_command(command); } } diff --git a/esphome/components/pipsolar/switch/pipsolar_switch.h b/esphome/components/pipsolar/switch/pipsolar_switch.h index 11ff6c853a..bb62d4794a 100644 --- a/esphome/components/pipsolar/switch/pipsolar_switch.h +++ b/esphome/components/pipsolar/switch/pipsolar_switch.h @@ -9,15 +9,18 @@ namespace pipsolar { class Pipsolar; class PipsolarSwitch : public switch_::Switch, public Component { public: - void set_parent(Pipsolar *parent) { this->parent_ = parent; }; - void set_on_command(const std::string &command) { this->on_command_ = command; }; - void set_off_command(const std::string &command) { this->off_command_ = command; }; + void set_parent(Pipsolar *parent) { this->parent_ = parent; } + void set_on_command(const char *command) { this->on_command_ = command; } + void set_off_command(const char *command) { this->off_command_ = command; } + /// Prevent accidental use of std::string which would dangle + void set_on_command(const std::string &command) = delete; + void set_off_command(const std::string &command) = delete; void dump_config() override; protected: void write_state(bool state) override; - std::string on_command_; - std::string off_command_; + const char *on_command_{nullptr}; + const char *off_command_{nullptr}; Pipsolar *parent_; }; From ee2a81923b4900edd3d8156f3049690af07c8e53 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:51:01 -1000 Subject: [PATCH 0179/2030] [sun] Store text sensor format string in flash (#13335) --- esphome/components/sun/text_sensor/sun_text_sensor.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/sun/text_sensor/sun_text_sensor.h b/esphome/components/sun/text_sensor/sun_text_sensor.h index 9345a32223..c3b60ffd65 100644 --- a/esphome/components/sun/text_sensor/sun_text_sensor.h +++ b/esphome/components/sun/text_sensor/sun_text_sensor.h @@ -14,7 +14,9 @@ class SunTextSensor : public text_sensor::TextSensor, public PollingComponent { void set_parent(Sun *parent) { parent_ = parent; } void set_elevation(double elevation) { elevation_ = elevation; } void set_sunrise(bool sunrise) { sunrise_ = sunrise; } - void set_format(const std::string &format) { format_ = format; } + void set_format(const char *format) { this->format_ = format; } + /// Prevent accidental use of std::string which would dangle + void set_format(const std::string &format) = delete; void update() override { optional res; @@ -29,14 +31,14 @@ class SunTextSensor : public text_sensor::TextSensor, public PollingComponent { } char buf[ESPTime::STRFTIME_BUFFER_SIZE]; - size_t len = res->strftime_to(buf, this->format_.c_str()); + size_t len = res->strftime_to(buf, this->format_); this->publish_state(buf, len); } void dump_config() override; protected: - std::string format_{}; + const char *format_{nullptr}; Sun *parent_; double elevation_; bool sunrise_; From ed58b9372f90e834e23f1a86e6c5320b8da4bb67 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:51:12 -1000 Subject: [PATCH 0180/2030] [template] Store text initial_value in flash and avoid heap allocation in setup (#13332) --- .../template/text/template_text.cpp | 25 ++++++++++++------- .../components/template/text/template_text.h | 6 +++-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/esphome/components/template/text/template_text.cpp b/esphome/components/template/text/template_text.cpp index 32ed8f047b..5acbb6e15a 100644 --- a/esphome/components/template/text/template_text.cpp +++ b/esphome/components/template/text/template_text.cpp @@ -8,16 +8,23 @@ static const char *const TAG = "template.text"; void TemplateText::setup() { if (this->f_.has_value()) return; - std::string value = this->initial_value_; - if (!this->pref_) { - ESP_LOGD(TAG, "State from initial: %s", value.c_str()); - } else { - uint32_t key = this->get_preference_hash(); - key += this->traits.get_min_length() << 2; - key += this->traits.get_max_length() << 4; - key += fnv1_hash(this->traits.get_pattern_c_str()) << 6; - this->pref_->setup(key, value); + + if (this->pref_ == nullptr) { + // No restore - use const char* directly, no heap allocation needed + if (this->initial_value_ != nullptr && this->initial_value_[0] != '\0') { + ESP_LOGD(TAG, "State from initial: %s", this->initial_value_); + this->publish_state(this->initial_value_); + } + return; } + + // Need std::string for pref_->setup() to fill from flash + std::string value{this->initial_value_ != nullptr ? this->initial_value_ : ""}; + uint32_t key = this->get_preference_hash(); + key += this->traits.get_min_length() << 2; + key += this->traits.get_max_length() << 4; + key += fnv1_hash(this->traits.get_pattern_c_str()) << 6; + this->pref_->setup(key, value); if (!value.empty()) this->publish_state(value); } diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index 178b410ed2..e5e5e4f4a8 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -70,13 +70,15 @@ class TemplateText final : public text::Text, public PollingComponent { Trigger *get_set_trigger() const { return this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } - void set_initial_value(const std::string &initial_value) { this->initial_value_ = initial_value; } + void set_initial_value(const char *initial_value) { this->initial_value_ = initial_value; } + /// Prevent accidental use of std::string which would dangle + void set_initial_value(const std::string &initial_value) = delete; void set_value_saver(TemplateTextSaverBase *restore_value_saver) { this->pref_ = restore_value_saver; } protected: void control(const std::string &value) override; bool optimistic_ = false; - std::string initial_value_; + const char *initial_value_{nullptr}; Trigger *set_trigger_ = new Trigger(); TemplateLambda f_{}; From 4cc0f874f75b1d83245ae2de67512df1ea385223 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:51:26 -1000 Subject: [PATCH 0181/2030] [wireguard] Store configuration strings in flash instead of heap (#13331) --- esphome/components/wireguard/__init__.py | 15 ++++- esphome/components/wireguard/wireguard.cpp | 71 ++++++++++++---------- esphome/components/wireguard/wireguard.h | 61 ++++++++++++------- 3 files changed, 91 insertions(+), 56 deletions(-) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 50c7980215..124d9a8c32 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -30,6 +30,7 @@ _WG_KEY_REGEX = re.compile(r"^[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=$") wireguard_ns = cg.esphome_ns.namespace("wireguard") Wireguard = wireguard_ns.class_("Wireguard", cg.Component, cg.PollingComponent) +AllowedIP = wireguard_ns.struct("AllowedIP") WireguardPeerOnlineCondition = wireguard_ns.class_( "WireguardPeerOnlineCondition", automation.Condition ) @@ -108,8 +109,18 @@ async def to_code(config): ) ) - for ip in allowed_ips: - cg.add(var.add_allowed_ip(str(ip.network_address), str(ip.netmask))) + cg.add( + var.set_allowed_ips( + [ + cg.StructInitializer( + AllowedIP, + ("ip", str(ip.network_address)), + ("netmask", str(ip.netmask)), + ) + for ip in allowed_ips + ] + ) + ) cg.add(var.set_srctime(await cg.get_variable(config[CONF_TIME_ID]))) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index 7810a40ae1..2022e25b6c 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -13,8 +13,7 @@ #include #include -namespace esphome { -namespace wireguard { +namespace esphome::wireguard { static const char *const TAG = "wireguard"; @@ -28,16 +27,16 @@ static const char *const LOGMSG_ONLINE = "online"; static const char *const LOGMSG_OFFLINE = "offline"; void Wireguard::setup() { - this->wg_config_.address = this->address_.c_str(); - this->wg_config_.private_key = this->private_key_.c_str(); - this->wg_config_.endpoint = this->peer_endpoint_.c_str(); - this->wg_config_.public_key = this->peer_public_key_.c_str(); + this->wg_config_.address = this->address_; + this->wg_config_.private_key = this->private_key_; + this->wg_config_.endpoint = this->peer_endpoint_; + this->wg_config_.public_key = this->peer_public_key_; this->wg_config_.port = this->peer_port_; - this->wg_config_.netmask = this->netmask_.c_str(); + this->wg_config_.netmask = this->netmask_; this->wg_config_.persistent_keepalive = this->keepalive_; - if (!this->preshared_key_.empty()) - this->wg_config_.preshared_key = this->preshared_key_.c_str(); + if (this->preshared_key_ != nullptr) + this->wg_config_.preshared_key = this->preshared_key_; this->publish_enabled_state(); @@ -131,6 +130,10 @@ void Wireguard::update() { } void Wireguard::dump_config() { + char private_key_masked[MASK_KEY_BUFFER_SIZE]; + char preshared_key_masked[MASK_KEY_BUFFER_SIZE]; + mask_key_to(private_key_masked, sizeof(private_key_masked), this->private_key_); + mask_key_to(preshared_key_masked, sizeof(preshared_key_masked), this->preshared_key_); // clang-format off ESP_LOGCONFIG( TAG, @@ -142,13 +145,13 @@ void Wireguard::dump_config() { " Peer Port: " LOG_SECRET("%d") "\n" " Peer Public Key: " LOG_SECRET("%s") "\n" " Peer Pre-shared Key: " LOG_SECRET("%s"), - this->address_.c_str(), this->netmask_.c_str(), mask_key(this->private_key_).c_str(), - this->peer_endpoint_.c_str(), this->peer_port_, this->peer_public_key_.c_str(), - (!this->preshared_key_.empty() ? mask_key(this->preshared_key_).c_str() : "NOT IN USE")); + this->address_, this->netmask_, private_key_masked, + this->peer_endpoint_, this->peer_port_, this->peer_public_key_, + (this->preshared_key_ != nullptr ? preshared_key_masked : "NOT IN USE")); // clang-format on ESP_LOGCONFIG(TAG, " Peer Allowed IPs:"); - for (auto &allowed_ip : this->allowed_ips_) { - ESP_LOGCONFIG(TAG, " - %s/%s", std::get<0>(allowed_ip).c_str(), std::get<1>(allowed_ip).c_str()); + for (const AllowedIP &allowed_ip : this->allowed_ips_) { + ESP_LOGCONFIG(TAG, " - %s/%s", allowed_ip.ip, allowed_ip.netmask); } ESP_LOGCONFIG(TAG, " Peer Persistent Keepalive: %d%s", this->keepalive_, (this->keepalive_ > 0 ? "s" : " (DISABLED)")); @@ -176,18 +179,6 @@ time_t Wireguard::get_latest_handshake() const { return result; } -void Wireguard::set_address(const std::string &address) { this->address_ = address; } -void Wireguard::set_netmask(const std::string &netmask) { this->netmask_ = netmask; } -void Wireguard::set_private_key(const std::string &key) { this->private_key_ = key; } -void Wireguard::set_peer_endpoint(const std::string &endpoint) { this->peer_endpoint_ = endpoint; } -void Wireguard::set_peer_public_key(const std::string &key) { this->peer_public_key_ = key; } -void Wireguard::set_peer_port(const uint16_t port) { this->peer_port_ = port; } -void Wireguard::set_preshared_key(const std::string &key) { this->preshared_key_ = key; } - -void Wireguard::add_allowed_ip(const std::string &ip, const std::string &netmask) { - this->allowed_ips_.emplace_back(ip, netmask); -} - void Wireguard::set_keepalive(const uint16_t seconds) { this->keepalive_ = seconds; } void Wireguard::set_reboot_timeout(const uint32_t seconds) { this->reboot_timeout_ = seconds; } void Wireguard::set_srctime(time::RealTimeClock *srctime) { this->srctime_ = srctime; } @@ -274,9 +265,8 @@ void Wireguard::start_connection_() { ESP_LOGD(TAG, "Configuring allowed IPs list"); bool allowed_ips_ok = true; - for (std::tuple ip : this->allowed_ips_) { - allowed_ips_ok &= - (esp_wireguard_add_allowed_ip(&(this->wg_ctx_), std::get<0>(ip).c_str(), std::get<1>(ip).c_str()) == ESP_OK); + for (const AllowedIP &ip : this->allowed_ips_) { + allowed_ips_ok &= (esp_wireguard_add_allowed_ip(&(this->wg_ctx_), ip.ip, ip.netmask) == ESP_OK); } if (allowed_ips_ok) { @@ -299,8 +289,25 @@ void Wireguard::stop_connection_() { } } -std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); } +void mask_key_to(char *buffer, size_t len, const char *key) { + // Format: "XXXXX[...]=\0" = MASK_KEY_BUFFER_SIZE chars minimum + if (len < MASK_KEY_BUFFER_SIZE || key == nullptr) { + if (len > 0) + buffer[0] = '\0'; + return; + } + // Copy first 5 characters of the key + size_t i = 0; + for (; i < 5 && key[i] != '\0'; ++i) { + buffer[i] = key[i]; + } + // Append "[...]=" + const char *suffix = "[...]="; + for (size_t j = 0; suffix[j] != '\0' && (i + j) < len - 1; ++j) { + buffer[i + j] = suffix[j]; + } + buffer[i + 6] = '\0'; +} -} // namespace wireguard -} // namespace esphome +} // namespace esphome::wireguard #endif diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h index f8f79b835d..e8470c75cd 100644 --- a/esphome/components/wireguard/wireguard.h +++ b/esphome/components/wireguard/wireguard.h @@ -2,10 +2,10 @@ #include "esphome/core/defines.h" #ifdef USE_WIREGUARD #include -#include -#include +#include #include "esphome/core/component.h" +#include "esphome/core/helpers.h" #include "esphome/components/time/real_time_clock.h" #ifdef USE_BINARY_SENSOR @@ -22,8 +22,13 @@ #include -namespace esphome { -namespace wireguard { +namespace esphome::wireguard { + +/// Allowed IP entry for WireGuard peer configuration. +struct AllowedIP { + const char *ip; + const char *netmask; +}; /// Main Wireguard component class. class Wireguard : public PollingComponent { @@ -37,15 +42,25 @@ class Wireguard : public PollingComponent { float get_setup_priority() const override { return esphome::setup_priority::BEFORE_CONNECTION; } - void set_address(const std::string &address); - void set_netmask(const std::string &netmask); - void set_private_key(const std::string &key); - void set_peer_endpoint(const std::string &endpoint); - void set_peer_public_key(const std::string &key); - void set_peer_port(uint16_t port); - void set_preshared_key(const std::string &key); + void set_address(const char *address) { this->address_ = address; } + void set_netmask(const char *netmask) { this->netmask_ = netmask; } + void set_private_key(const char *key) { this->private_key_ = key; } + void set_peer_endpoint(const char *endpoint) { this->peer_endpoint_ = endpoint; } + void set_peer_public_key(const char *key) { this->peer_public_key_ = key; } + void set_peer_port(uint16_t port) { this->peer_port_ = port; } + void set_preshared_key(const char *key) { this->preshared_key_ = key; } - void add_allowed_ip(const std::string &ip, const std::string &netmask); + /// Prevent accidental use of std::string which would dangle + void set_address(const std::string &address) = delete; + void set_netmask(const std::string &netmask) = delete; + void set_private_key(const std::string &key) = delete; + void set_peer_endpoint(const std::string &endpoint) = delete; + void set_peer_public_key(const std::string &key) = delete; + void set_preshared_key(const std::string &key) = delete; + + void set_allowed_ips(std::initializer_list ips) { this->allowed_ips_ = ips; } + /// Prevent accidental use of std::string which would dangle + void set_allowed_ips(std::initializer_list> ips) = delete; void set_keepalive(uint16_t seconds); void set_reboot_timeout(uint32_t seconds); @@ -83,14 +98,14 @@ class Wireguard : public PollingComponent { time_t get_latest_handshake() const; protected: - std::string address_; - std::string netmask_; - std::string private_key_; - std::string peer_endpoint_; - std::string peer_public_key_; - std::string preshared_key_; + const char *address_{nullptr}; + const char *netmask_{nullptr}; + const char *private_key_{nullptr}; + const char *peer_endpoint_{nullptr}; + const char *peer_public_key_{nullptr}; + const char *preshared_key_{nullptr}; - std::vector> allowed_ips_; + FixedVector allowed_ips_; uint16_t peer_port_; uint16_t keepalive_; @@ -142,8 +157,11 @@ class Wireguard : public PollingComponent { void suspend_wdt(); void resume_wdt(); +/// Size of buffer required for mask_key_to: 5 chars + "[...]=" + null = 12 +static constexpr size_t MASK_KEY_BUFFER_SIZE = 12; + /// Strip most part of the key only for secure printing -std::string mask_key(const std::string &key); +void mask_key_to(char *buffer, size_t len, const char *key); /// Condition to check if remote peer is online. template class WireguardPeerOnlineCondition : public Condition, public Parented { @@ -169,6 +187,5 @@ template class WireguardDisableAction : public Action, pu void play(const Ts &...x) override { this->parent_->disable(); } }; -} // namespace wireguard -} // namespace esphome +} // namespace esphome::wireguard #endif From d6a0c8ffbb5859fb2f02b583657228a6343919d8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:52:06 -1000 Subject: [PATCH 0182/2030] [template] Store alarm control panel codes in flash instead of heap (#13329) --- .../template/alarm_control_panel/__init__.py | 3 +-- .../template_alarm_control_panel.cpp | 8 +++++++- .../template_alarm_control_panel.h | 14 +++++++++----- tests/components/alarm_control_panel/common.yaml | 3 +++ 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/esphome/components/template/alarm_control_panel/__init__.py b/esphome/components/template/alarm_control_panel/__init__.py index 256c7f276a..59624a5f53 100644 --- a/esphome/components/template/alarm_control_panel/__init__.py +++ b/esphome/components/template/alarm_control_panel/__init__.py @@ -118,8 +118,7 @@ async def to_code(config): var = await alarm_control_panel.new_alarm_control_panel(config) await cg.register_component(var, config) if CONF_CODES in config: - for acode in config[CONF_CODES]: - cg.add(var.add_code(acode)) + cg.add(var.set_codes(config[CONF_CODES])) if CONF_REQUIRES_CODE_TO_ARM in config: cg.add(var.set_requires_code_to_arm(config[CONF_REQUIRES_CODE_TO_ARM])) diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp index 50e43da8d5..028d6f0879 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp @@ -206,7 +206,13 @@ bool TemplateAlarmControlPanel::is_code_valid_(optional code) { if (!this->codes_.empty()) { if (code.has_value()) { ESP_LOGVV(TAG, "Checking code: %s", code.value().c_str()); - return (std::count(this->codes_.begin(), this->codes_.end(), code.value()) == 1); + // Use strcmp for const char* comparison + const char *code_cstr = code.value().c_str(); + for (const char *stored_code : this->codes_) { + if (strcmp(stored_code, code_cstr) == 0) + return true; + } + return false; } ESP_LOGD(TAG, "No code provided"); return false; diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h index 2038d8f1b0..df3b64fb6e 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "esphome/core/automation.h" @@ -86,11 +87,14 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl AlarmSensorType type = ALARM_SENSOR_TYPE_DELAYED); #endif - /** add a code + /** Set the codes (from initializer list). * - * @param code The code + * @param codes The list of valid codes */ - void add_code(const std::string &code) { this->codes_.push_back(code); } + void set_codes(std::initializer_list codes) { this->codes_ = codes; } + + // Deleted overload to catch incorrect std::string usage at compile time + void set_codes(std::initializer_list codes) = delete; /** set requires a code to arm * @@ -155,8 +159,8 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl uint32_t pending_time_; // the time in trigger uint32_t trigger_time_; - // a list of codes - std::vector codes_; + // a list of codes (const char* pointers to string literals in flash) + FixedVector codes_; // requires a code to arm bool requires_code_to_arm_ = false; bool supports_arm_home_ = false; diff --git a/tests/components/alarm_control_panel/common.yaml b/tests/components/alarm_control_panel/common.yaml index 142bf3c7e6..39d5739255 100644 --- a/tests/components/alarm_control_panel/common.yaml +++ b/tests/components/alarm_control_panel/common.yaml @@ -9,6 +9,8 @@ alarm_control_panel: name: Alarm Panel codes: - "1234" + - "5678" + - "0000" requires_code_to_arm: true arming_home_time: 1s arming_night_time: 1s @@ -29,6 +31,7 @@ alarm_control_panel: name: Alarm Panel 2 codes: - "1234" + - "9999" requires_code_to_arm: true arming_home_time: 1s arming_night_time: 1s From 01cdc4ed58465610cf307b48ed5573834190e837 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:52:19 -1000 Subject: [PATCH 0183/2030] [core] Add fnv1_hash_extend() string overloads, use in atm90e32 (#13326) --- esphome/components/atm90e32/atm90e32.cpp | 9 ++++++--- esphome/core/helpers.h | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/esphome/components/atm90e32/atm90e32.cpp b/esphome/components/atm90e32/atm90e32.cpp index 634260b5e9..f4c199cb98 100644 --- a/esphome/components/atm90e32/atm90e32.cpp +++ b/esphome/components/atm90e32/atm90e32.cpp @@ -158,12 +158,14 @@ void ATM90E32Component::setup() { if (this->enable_offset_calibration_) { // Initialize flash storage for offset calibrations - uint32_t o_hash = fnv1_hash(std::string("_offset_calibration_") + this->cs_summary_); + uint32_t o_hash = fnv1_hash("_offset_calibration_"); + o_hash = fnv1_hash_extend(o_hash, this->cs_summary_); this->offset_pref_ = global_preferences->make_preference(o_hash, true); this->restore_offset_calibrations_(); // Initialize flash storage for power offset calibrations - uint32_t po_hash = fnv1_hash(std::string("_power_offset_calibration_") + this->cs_summary_); + uint32_t po_hash = fnv1_hash("_power_offset_calibration_"); + po_hash = fnv1_hash_extend(po_hash, this->cs_summary_); this->power_offset_pref_ = global_preferences->make_preference(po_hash, true); this->restore_power_offset_calibrations_(); } else { @@ -183,7 +185,8 @@ void ATM90E32Component::setup() { if (this->enable_gain_calibration_) { // Initialize flash storage for gain calibration - uint32_t g_hash = fnv1_hash(std::string("_gain_calibration_") + this->cs_summary_); + uint32_t g_hash = fnv1_hash("_gain_calibration_"); + g_hash = fnv1_hash_extend(g_hash, this->cs_summary_); this->gain_calibration_pref_ = global_preferences->make_preference(g_hash, true); this->restore_gain_calibrations_(); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 409c691cb1..cdc051fc90 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -395,6 +395,28 @@ constexpr uint32_t FNV1_OFFSET_BASIS = 2166136261UL; /// FNV-1 32-bit prime constexpr uint32_t FNV1_PRIME = 16777619UL; +/// Extend a FNV-1 hash with an integer (hashes each byte). +template constexpr uint32_t fnv1_hash_extend(uint32_t hash, T value) { + using UnsignedT = std::make_unsigned_t; + UnsignedT uvalue = static_cast(value); + for (size_t i = 0; i < sizeof(T); i++) { + hash *= FNV1_PRIME; + hash ^= (uvalue >> (i * 8)) & 0xFF; + } + return hash; +} +/// Extend a FNV-1 hash with additional string data. +constexpr uint32_t fnv1_hash_extend(uint32_t hash, const char *str) { + if (str) { + while (*str) { + hash *= FNV1_PRIME; + hash ^= *str++; + } + } + return hash; +} +inline uint32_t fnv1_hash_extend(uint32_t hash, const std::string &str) { return fnv1_hash_extend(hash, str.c_str()); } + /// Extend a FNV-1a hash with additional string data. constexpr uint32_t fnv1a_hash_extend(uint32_t hash, const char *str) { if (str) { From 728236270cdb25f3887f6e2bbf4918d29b0aba68 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 15:53:01 -1000 Subject: [PATCH 0184/2030] [weikai] Replace bitset to_string with format_bin_to (#13297) --- esphome/components/weikai/weikai.cpp | 49 +++++++++++--------- esphome/components/weikai/weikai.h | 1 - esphome/components/weikai_spi/weikai_spi.cpp | 25 +++++----- esphome/components/weikai_spi/weikai_spi.h | 1 - 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index 3384a0572f..197b516bb2 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -4,19 +4,13 @@ /// @details The classes declared in this file can be used by the Weikai family #include "weikai.h" +#include "esphome/core/helpers.h" namespace esphome { namespace weikai { static const char *const TAG = "weikai"; -/// @brief convert an int to binary representation as C++ std::string -/// @param val integer to convert -/// @return a std::string -inline std::string i2s(uint8_t val) { return std::bitset<8>(val).to_string(); } -/// Convert std::string to C string -#define I2S2CS(val) (i2s(val).c_str()) - /// @brief measure the time elapsed between two calls /// @param last_time time of the previous call /// @return the elapsed time in milliseconds @@ -170,17 +164,18 @@ void WeikaiComponent::test_gpio_input_() { static bool init_input{false}; static uint8_t state{0}; uint8_t value; + char bin_buf[9]; // 8 binary digits + null if (!init_input) { init_input = true; // set all pins in input mode this->reg(WKREG_GPDIR, 0) = 0x00; ESP_LOGI(TAG, "initializing all pins to input mode"); state = this->reg(WKREG_GPDAT, 0); - ESP_LOGI(TAG, "initial input data state = %02X (%s)", state, I2S2CS(state)); + ESP_LOGI(TAG, "initial input data state = %02X (%s)", state, format_bin_to(bin_buf, state)); } value = this->reg(WKREG_GPDAT, 0); if (value != state) { - ESP_LOGI(TAG, "Input data changed from %02X to %02X (%s)", state, value, I2S2CS(value)); + ESP_LOGI(TAG, "Input data changed from %02X to %02X (%s)", state, value, format_bin_to(bin_buf, value)); state = value; } } @@ -188,6 +183,7 @@ void WeikaiComponent::test_gpio_input_() { void WeikaiComponent::test_gpio_output_() { static bool init_output{false}; static uint8_t state{0}; + char bin_buf[9]; // 8 binary digits + null if (!init_output) { init_output = true; // set all pins in output mode @@ -198,7 +194,7 @@ void WeikaiComponent::test_gpio_output_() { } state = ~state; this->reg(WKREG_GPDAT, 0) = state; - ESP_LOGI(TAG, "Flipping all outputs to %02X (%s)", state, I2S2CS(state)); + ESP_LOGI(TAG, "Flipping all outputs to %02X (%s)", state, format_bin_to(bin_buf, state)); delay(100); // NOLINT } #endif @@ -208,7 +204,9 @@ void WeikaiComponent::test_gpio_output_() { /////////////////////////////////////////////////////////////////////////////// bool WeikaiComponent::read_pin_val_(uint8_t pin) { this->input_state_ = this->reg(WKREG_GPDAT, 0); - ESP_LOGVV(TAG, "reading input pin %u = %u in_state %s", pin, this->input_state_ & (1 << pin), I2S2CS(input_state_)); + char bin_buf[9]; + ESP_LOGVV(TAG, "reading input pin %u = %u in_state %s", pin, this->input_state_ & (1 << pin), + format_bin_to(bin_buf, this->input_state_)); return this->input_state_ & (1 << pin); } @@ -218,7 +216,9 @@ void WeikaiComponent::write_pin_val_(uint8_t pin, bool value) { } else { this->output_state_ &= ~(1 << pin); } - ESP_LOGVV(TAG, "writing output pin %d with %d out_state %s", pin, uint8_t(value), I2S2CS(this->output_state_)); + char bin_buf[9]; + ESP_LOGVV(TAG, "writing output pin %d with %d out_state %s", pin, uint8_t(value), + format_bin_to(bin_buf, this->output_state_)); this->reg(WKREG_GPDAT, 0) = this->output_state_; } @@ -232,7 +232,8 @@ void WeikaiComponent::set_pin_direction_(uint8_t pin, gpio::Flags flags) { ESP_LOGE(TAG, "pin %d direction invalid", pin); } } - ESP_LOGVV(TAG, "setting pin %d direction to %d pin_config=%s", pin, flags, I2S2CS(this->pin_config_)); + char bin_buf[9]; + ESP_LOGVV(TAG, "setting pin %d direction to %d pin_config=%s", pin, flags, format_bin_to(bin_buf, this->pin_config_)); this->reg(WKREG_GPDIR, 0) = this->pin_config_; // TODO check ~ } @@ -241,7 +242,6 @@ void WeikaiGPIOPin::setup() { flags_ == gpio::FLAG_INPUT ? "Input" : this->flags_ == gpio::FLAG_OUTPUT ? "Output" : "NOT SPECIFIED"); - // ESP_LOGCONFIG(TAG, "Setting GPIO pins mode to '%s' %02X", I2S2CS(this->flags_), this->flags_); this->pin_mode(this->flags_); } @@ -297,8 +297,9 @@ void WeikaiChannel::set_line_param_() { break; // no parity 000x } this->reg(WKREG_LCR) = lcr; // write LCR + char bin_buf[9]; ESP_LOGV(TAG, " line config: %d data_bits, %d stop_bits, parity %s register [%s]", this->data_bits_, - this->stop_bits_, p2s(this->parity_), I2S2CS(lcr)); + this->stop_bits_, p2s(this->parity_), format_bin_to(bin_buf, lcr)); } void WeikaiChannel::set_baudrate_() { @@ -334,7 +335,8 @@ size_t WeikaiChannel::tx_in_fifo_() { if (tfcnt == 0) { uint8_t const fsr = this->reg(WKREG_FSR); if (fsr & FSR_TFFULL) { - ESP_LOGVV(TAG, "tx FIFO full FSR=%s", I2S2CS(fsr)); + char bin_buf[9]; + ESP_LOGVV(TAG, "tx FIFO full FSR=%s", format_bin_to(bin_buf, fsr)); tfcnt = FIFO_SIZE; } } @@ -346,14 +348,15 @@ size_t WeikaiChannel::rx_in_fifo_() { size_t available = this->reg(WKREG_RFCNT); uint8_t const fsr = this->reg(WKREG_FSR); if (fsr & (FSR_RFOE | FSR_RFLB | FSR_RFFE | FSR_RFPE)) { + char bin_buf[9]; if (fsr & FSR_RFOE) - ESP_LOGE(TAG, "Receive data overflow FSR=%s", I2S2CS(fsr)); + ESP_LOGE(TAG, "Receive data overflow FSR=%s", format_bin_to(bin_buf, fsr)); if (fsr & FSR_RFLB) - ESP_LOGE(TAG, "Receive line break FSR=%s", I2S2CS(fsr)); + ESP_LOGE(TAG, "Receive line break FSR=%s", format_bin_to(bin_buf, fsr)); if (fsr & FSR_RFFE) - ESP_LOGE(TAG, "Receive frame error FSR=%s", I2S2CS(fsr)); + ESP_LOGE(TAG, "Receive frame error FSR=%s", format_bin_to(bin_buf, fsr)); if (fsr & FSR_RFPE) - ESP_LOGE(TAG, "Receive parity error FSR=%s", I2S2CS(fsr)); + ESP_LOGE(TAG, "Receive parity error FSR=%s", format_bin_to(bin_buf, fsr)); } if ((available == 0) && (fsr & FSR_RFDAT)) { // here we should be very careful because we can have something like this: @@ -362,11 +365,13 @@ size_t WeikaiChannel::rx_in_fifo_() { // - so to be sure we need to do another read of RFCNT and if it is still zero -> buffer full available = this->reg(WKREG_RFCNT); if (available == 0) { // still zero ? - ESP_LOGV(TAG, "rx FIFO is full FSR=%s", I2S2CS(fsr)); + char bin_buf[9]; + ESP_LOGV(TAG, "rx FIFO is full FSR=%s", format_bin_to(bin_buf, fsr)); available = FIFO_SIZE; } } - ESP_LOGVV(TAG, "rx FIFO contain %d bytes - FSR status=%s", available, I2S2CS(fsr)); + char bin_buf2[9]; + ESP_LOGVV(TAG, "rx FIFO contain %d bytes - FSR status=%s", available, format_bin_to(bin_buf2, fsr)); return available; } diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h index a27c14106d..4440d9414e 100644 --- a/esphome/components/weikai/weikai.h +++ b/esphome/components/weikai/weikai.h @@ -8,7 +8,6 @@ /// wk2132_i2c, wk2168_i2c, wk2204_i2c, wk2212_i2c #pragma once -#include #include #include #include "esphome/core/component.h" diff --git a/esphome/components/weikai_spi/weikai_spi.cpp b/esphome/components/weikai_spi/weikai_spi.cpp index 7bcb817f09..20671a5815 100644 --- a/esphome/components/weikai_spi/weikai_spi.cpp +++ b/esphome/components/weikai_spi/weikai_spi.cpp @@ -10,13 +10,6 @@ namespace weikai_spi { using namespace weikai; static const char *const TAG = "weikai_spi"; -/// @brief convert an int to binary representation as C++ std::string -/// @param val integer to convert -/// @return a std::string -inline std::string i2s(uint8_t val) { return std::bitset<8>(val).to_string(); } -/// Convert std::string to C string -#define I2S2CS(val) (i2s(val).c_str()) - /// @brief measure the time elapsed between two calls /// @param last_time time of the previous call /// @return the elapsed time in microseconds @@ -107,7 +100,8 @@ uint8_t WeikaiRegisterSPI::read_reg() const { spi_comp->write_byte(cmd); uint8_t val = spi_comp->read_byte(); spi_comp->disable(); - ESP_LOGVV(TAG, "WeikaiRegisterSPI::read_reg() cmd=%s(%02X) reg=%s ch=%d buf=%02X", I2S2CS(cmd), cmd, + char bin_buf[9]; + ESP_LOGVV(TAG, "WeikaiRegisterSPI::read_reg() cmd=%s(%02X) reg=%s ch=%d buf=%02X", format_bin_to(bin_buf, cmd), cmd, reg_to_str(this->register_, this->comp_->page1()), this->channel_, val); return val; } @@ -120,8 +114,9 @@ void WeikaiRegisterSPI::read_fifo(uint8_t *data, size_t length) const { spi_comp->read_array(data, length); spi_comp->disable(); #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - ESP_LOGVV(TAG, "WeikaiRegisterSPI::read_fifo() cmd=%s(%02X) ch=%d len=%d buffer", I2S2CS(cmd), cmd, this->channel_, - length); + char bin_buf[9]; + ESP_LOGVV(TAG, "WeikaiRegisterSPI::read_fifo() cmd=%s(%02X) ch=%d len=%d buffer", format_bin_to(bin_buf, cmd), cmd, + this->channel_, length); print_buffer(data, length); #endif } @@ -132,8 +127,9 @@ void WeikaiRegisterSPI::write_reg(uint8_t value) { spi_comp->enable(); spi_comp->write_array(buf, 2); spi_comp->disable(); - ESP_LOGVV(TAG, "WeikaiRegisterSPI::write_reg() cmd=%s(%02X) reg=%s ch=%d buf=%02X", I2S2CS(buf[0]), buf[0], - reg_to_str(this->register_, this->comp_->page1()), this->channel_, buf[1]); + char bin_buf[9]; + ESP_LOGVV(TAG, "WeikaiRegisterSPI::write_reg() cmd=%s(%02X) reg=%s ch=%d buf=%02X", format_bin_to(bin_buf, buf[0]), + buf[0], reg_to_str(this->register_, this->comp_->page1()), this->channel_, buf[1]); } void WeikaiRegisterSPI::write_fifo(uint8_t *data, size_t length) { @@ -145,8 +141,9 @@ void WeikaiRegisterSPI::write_fifo(uint8_t *data, size_t length) { spi_comp->disable(); #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - ESP_LOGVV(TAG, "WeikaiRegisterSPI::write_fifo() cmd=%s(%02X) ch=%d len=%d buffer", I2S2CS(cmd), cmd, this->channel_, - length); + char bin_buf[9]; + ESP_LOGVV(TAG, "WeikaiRegisterSPI::write_fifo() cmd=%s(%02X) ch=%d len=%d buffer", format_bin_to(bin_buf, cmd), cmd, + this->channel_, length); print_buffer(data, length); #endif } diff --git a/esphome/components/weikai_spi/weikai_spi.h b/esphome/components/weikai_spi/weikai_spi.h index dd0dc8d495..a75b85dc8e 100644 --- a/esphome/components/weikai_spi/weikai_spi.h +++ b/esphome/components/weikai_spi/weikai_spi.h @@ -6,7 +6,6 @@ /// wk2124_spi, wk2132_spi, wk2168_spi, wk2204_spi, wk2212_spi, #pragma once -#include #include #include "esphome/core/component.h" #include "esphome/components/uart/uart.h" From 21794e28e554155c3e8bc2462ae0aeb956dc2c47 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 17:26:51 -1000 Subject: [PATCH 0185/2030] [modbus_controller] Use stack buffers instead of heap-allocating string helpers (#13221) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../modbus_controller/modbus_controller.h | 15 +++++++++++---- .../text_sensor/modbus_textsensor.cpp | 16 ++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index 6ed05715cb..fca2926568 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -271,24 +271,31 @@ class ServerRegister { // Formats a raw value into a string representation based on the value type for debugging std::string format_value(int64_t value) const { + // max 44: float with %.1f can be up to 42 chars (3.4e38 → 39 integer digits + sign + decimal + 1 digit) + // plus null terminator = 43, rounded to 44 for 4-byte alignment + char buf[44]; switch (this->value_type) { case SensorValueType::U_WORD: case SensorValueType::U_DWORD: case SensorValueType::U_DWORD_R: case SensorValueType::U_QWORD: case SensorValueType::U_QWORD_R: - return std::to_string(static_cast(value)); + buf_append_printf(buf, sizeof(buf), 0, "%" PRIu64, static_cast(value)); + return buf; case SensorValueType::S_WORD: case SensorValueType::S_DWORD: case SensorValueType::S_DWORD_R: case SensorValueType::S_QWORD: case SensorValueType::S_QWORD_R: - return std::to_string(value); + buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, value); + return buf; case SensorValueType::FP32_R: case SensorValueType::FP32: - return str_sprintf("%.1f", bit_cast(static_cast(value))); + buf_append_printf(buf, sizeof(buf), 0, "%.1f", bit_cast(static_cast(value))); + return buf; default: - return std::to_string(value); + buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, value); + return buf; } } diff --git a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp index 89e86741b0..b26411b72e 100644 --- a/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp +++ b/esphome/components/modbus_controller/text_sensor/modbus_textsensor.cpp @@ -16,12 +16,20 @@ void ModbusTextSensor::parse_and_publish(const std::vector &data) { while ((items_left > 0) && index < data.size()) { uint8_t b = data[index]; switch (this->encode_) { - case RawEncoding::HEXBYTES: - output_str += str_snprintf("%02x", 2, b); + case RawEncoding::HEXBYTES: { + // max 3: 2 hex digits + null + char hex_buf[3]; + snprintf(hex_buf, sizeof(hex_buf), "%02x", b); + output_str += hex_buf; break; - case RawEncoding::COMMA: - output_str += str_sprintf(index != this->offset ? ",%d" : "%d", b); + } + case RawEncoding::COMMA: { + // max 5: optional ','(1) + uint8(3) + null, for both ",%d" and "%d" + char dec_buf[5]; + snprintf(dec_buf, sizeof(dec_buf), index != this->offset ? ",%d" : "%d", b); + output_str += dec_buf; break; + } case RawEncoding::ANSI: if (b < 0x20) break; From db0b32bfc9b15031ee3399ac8c560aaabf42892a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 18:06:54 -1000 Subject: [PATCH 0186/2030] [network] Fix IPAddress::str_to() to lowercase IPv6 hex digits (#13325) --- esphome/components/network/ip_address.h | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index b719d1a70e..3dfcf0cb64 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -43,6 +43,14 @@ namespace network { /// Buffer size for IP address string (IPv6 max: 39 chars + null) static constexpr size_t IP_ADDRESS_BUFFER_SIZE = 40; +/// Lowercase hex digits in IP address string (A-F -> a-f for IPv6 per RFC 5952) +inline void lowercase_ip_str(char *buf) { + for (char *p = buf; *p; ++p) { + if (*p >= 'A' && *p <= 'F') + *p += 32; + } +} + struct IPAddress { public: #ifdef USE_HOST @@ -52,10 +60,15 @@ struct IPAddress { } IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); } IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; } - std::string str() const { return str_lower_case(inet_ntoa(ip_addr_)); } + std::string str() const { + char buf[IP_ADDRESS_BUFFER_SIZE]; + this->str_to(buf); + return buf; + } /// Write IP address to buffer. Buffer must be at least IP_ADDRESS_BUFFER_SIZE bytes. char *str_to(char *buf) const { - return const_cast(inet_ntop(AF_INET, &ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE)); + inet_ntop(AF_INET, &ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); + return buf; // IPv4 only, no hex letters to lowercase } #else IPAddress() { ip_addr_set_zero(&ip_addr_); } @@ -134,9 +147,18 @@ struct IPAddress { bool is_ip4() const { return IP_IS_V4(&ip_addr_); } bool is_ip6() const { return IP_IS_V6(&ip_addr_); } bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); } - std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); } + std::string str() const { + char buf[IP_ADDRESS_BUFFER_SIZE]; + this->str_to(buf); + return buf; + } /// Write IP address to buffer. Buffer must be at least IP_ADDRESS_BUFFER_SIZE bytes. - char *str_to(char *buf) const { return ipaddr_ntoa_r(&ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); } + /// Output is lowercased per RFC 5952 (IPv6 hex digits a-f). + char *str_to(char *buf) const { + ipaddr_ntoa_r(&ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); + lowercase_ip_str(buf); + return buf; + } bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); } bool operator!=(const IPAddress &other) const { return !ip_addr_cmp(&ip_addr_, &other.ip_addr_); } IPAddress &operator+=(uint8_t increase) { From 680e92a226b7c643157ed2eb7d5d679a95879adc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 08:36:56 -1000 Subject: [PATCH 0187/2030] [core] Add str_endswith_ignore_case to avoid heap allocation in audio file type detection (#13313) --- esphome/components/audio/audio_reader.cpp | 8 +++----- esphome/core/helpers.cpp | 7 +++++++ esphome/core/helpers.h | 9 +++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/esphome/components/audio/audio_reader.cpp b/esphome/components/audio/audio_reader.cpp index 7794187a69..4e4bd31f9b 100644 --- a/esphome/components/audio/audio_reader.cpp +++ b/esphome/components/audio/audio_reader.cpp @@ -185,18 +185,16 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) { return err; } - std::string url_string = str_lower_case(url); - - if (str_endswith(url_string, ".wav")) { + if (str_endswith_ignore_case(url, ".wav")) { file_type = AudioFileType::WAV; } #ifdef USE_AUDIO_MP3_SUPPORT - else if (str_endswith(url_string, ".mp3")) { + else if (str_endswith_ignore_case(url, ".mp3")) { file_type = AudioFileType::MP3; } #endif #ifdef USE_AUDIO_FLAC_SUPPORT - else if (str_endswith(url_string, ".flac")) { + else if (str_endswith_ignore_case(url, ".flac")) { file_type = AudioFileType::FLAC; } #endif diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 4e3761675d..44c20845e8 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -174,6 +174,13 @@ bool str_endswith(const std::string &str, const std::string &end) { return str.rfind(end) == (str.size() - end.size()); } #endif + +bool str_endswith_ignore_case(const char *str, size_t str_len, const char *suffix, size_t suffix_len) { + if (suffix_len > str_len) + return false; + return strncasecmp(str + str_len - suffix_len, suffix, suffix_len) == 0; +} + std::string str_truncate(const std::string &str, size_t length) { return str.length() > length ? str.substr(0, length) : str; } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index cdc051fc90..8b581eb97a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -545,6 +545,15 @@ bool str_startswith(const std::string &str, const std::string &start); /// Check whether a string ends with a value. bool str_endswith(const std::string &str, const std::string &end); +/// Case-insensitive check if string ends with suffix (no heap allocation). +bool str_endswith_ignore_case(const char *str, size_t str_len, const char *suffix, size_t suffix_len); +inline bool str_endswith_ignore_case(const char *str, const char *suffix) { + return str_endswith_ignore_case(str, strlen(str), suffix, strlen(suffix)); +} +inline bool str_endswith_ignore_case(const std::string &str, const char *suffix) { + return str_endswith_ignore_case(str.c_str(), str.size(), suffix, strlen(suffix)); +} + /// Truncate a string to a specific length. /// @warning Allocates heap memory. Avoid in new code - causes heap fragmentation on long-running devices. std::string str_truncate(const std::string &str, size_t length); From baf2b0e3c9908b0c418f74069d3b1d4836830f6a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:23:11 -1000 Subject: [PATCH 0188/2030] [api] Fix truncation of Home Assistant attributes longer than 255 characters (#13348) --- esphome/components/api/api_connection.cpp | 19 ++++++------ esphome/components/i2c/i2c.cpp | 8 ++--- esphome/components/i2c/i2c_bus.h | 24 +++------------ esphome/core/helpers.h | 29 +++++++++++++++++++ .../fixtures/api_homeassistant.yaml | 19 ++++++++++++ tests/integration/test_api_homeassistant.py | 27 +++++++++++++++-- 6 files changed, 90 insertions(+), 36 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 0804985cc5..25512de4c7 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1712,17 +1712,16 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes } // Create null-terminated state for callback (parse_number needs null-termination) - // HA state max length is 255, so 256 byte buffer covers all cases - char state_buf[256]; - size_t copy_len = msg.state.size(); - if (copy_len >= sizeof(state_buf)) { - copy_len = sizeof(state_buf) - 1; // Truncate to leave space for null terminator + // HA state max length is 255 characters, but attributes can be much longer + // Use stack buffer for common case (states), heap fallback for large attributes + size_t state_len = msg.state.size(); + SmallBufferWithHeapFallback<256> state_buf_alloc(state_len + 1); + char *state_buf = reinterpret_cast(state_buf_alloc.get()); + if (state_len > 0) { + memcpy(state_buf, msg.state.c_str(), state_len); } - if (copy_len > 0) { - memcpy(state_buf, msg.state.c_str(), copy_len); - } - state_buf[copy_len] = '\0'; - it.callback(StringRef(state_buf, copy_len)); + state_buf[state_len] = '\0'; + it.callback(StringRef(state_buf, state_len)); } } #endif diff --git a/esphome/components/i2c/i2c.cpp b/esphome/components/i2c/i2c.cpp index f8c7a1b40b..c1e7336ce4 100644 --- a/esphome/components/i2c/i2c.cpp +++ b/esphome/components/i2c/i2c.cpp @@ -42,8 +42,8 @@ ErrorCode I2CDevice::read_register16(uint16_t a_register, uint8_t *data, size_t } ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len) const { - SmallBufferWithHeapFallback<17> buffer_alloc; // Most I2C writes are <= 16 bytes - uint8_t *buffer = buffer_alloc.get(len + 1); + SmallBufferWithHeapFallback<17> buffer_alloc(len + 1); // Most I2C writes are <= 16 bytes + uint8_t *buffer = buffer_alloc.get(); buffer[0] = a_register; std::copy(data, data + len, buffer + 1); @@ -51,8 +51,8 @@ ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, siz } ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len) const { - SmallBufferWithHeapFallback<18> buffer_alloc; // Most I2C writes are <= 16 bytes + 2 for register - uint8_t *buffer = buffer_alloc.get(len + 2); + SmallBufferWithHeapFallback<18> buffer_alloc(len + 2); // Most I2C writes are <= 16 bytes + 2 for register + uint8_t *buffer = buffer_alloc.get(); buffer[0] = a_register >> 8; buffer[1] = a_register; diff --git a/esphome/components/i2c/i2c_bus.h b/esphome/components/i2c/i2c_bus.h index 1acbe506a3..3de5d5ca7b 100644 --- a/esphome/components/i2c/i2c_bus.h +++ b/esphome/components/i2c/i2c_bus.h @@ -11,22 +11,6 @@ namespace esphome { namespace i2c { -/// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large -template class SmallBufferWithHeapFallback { - public: - uint8_t *get(size_t size) { - if (size <= STACK_SIZE) { - return this->stack_buffer_; - } - this->heap_buffer_ = std::unique_ptr(new uint8_t[size]); - return this->heap_buffer_.get(); - } - - private: - uint8_t stack_buffer_[STACK_SIZE]; - std::unique_ptr heap_buffer_; -}; - /// @brief Error codes returned by I2CBus and I2CDevice methods enum ErrorCode { NO_ERROR = 0, ///< No error found during execution of method @@ -92,8 +76,8 @@ class I2CBus { total_len += read_buffers[i].len; } - SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C reads are small - uint8_t *buffer = buffer_alloc.get(total_len); + SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C reads are small + uint8_t *buffer = buffer_alloc.get(); auto err = this->write_readv(address, nullptr, 0, buffer, total_len); if (err != ERROR_OK) @@ -116,8 +100,8 @@ class I2CBus { total_len += write_buffers[i].len; } - SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C writes are small - uint8_t *buffer = buffer_alloc.get(total_len); + SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C writes are small + uint8_t *buffer = buffer_alloc.get(); size_t pos = 0; for (size_t i = 0; i != count; i++) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 8b581eb97a..4185596c7b 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -366,6 +366,35 @@ template class FixedVector { const T *end() const { return data_ + size_; } }; +/// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large +/// This is useful when most operations need a small buffer but occasionally need larger ones. +/// The stack buffer avoids heap allocation in the common case, while heap fallback handles edge cases. +template class SmallBufferWithHeapFallback { + public: + explicit SmallBufferWithHeapFallback(size_t size) { + if (size <= STACK_SIZE) { + this->buffer_ = this->stack_buffer_; + } else { + this->heap_buffer_ = new uint8_t[size]; + this->buffer_ = this->heap_buffer_; + } + } + ~SmallBufferWithHeapFallback() { delete[] this->heap_buffer_; } + + // Delete copy and move operations to prevent double-delete + SmallBufferWithHeapFallback(const SmallBufferWithHeapFallback &) = delete; + SmallBufferWithHeapFallback &operator=(const SmallBufferWithHeapFallback &) = delete; + SmallBufferWithHeapFallback(SmallBufferWithHeapFallback &&) = delete; + SmallBufferWithHeapFallback &operator=(SmallBufferWithHeapFallback &&) = delete; + + uint8_t *get() { return this->buffer_; } + + private: + uint8_t stack_buffer_[STACK_SIZE]; + uint8_t *heap_buffer_{nullptr}; + uint8_t *buffer_; +}; + ///@} /// @name Mathematics diff --git a/tests/integration/fixtures/api_homeassistant.yaml b/tests/integration/fixtures/api_homeassistant.yaml index 8fe23b9a19..2d77821ff3 100644 --- a/tests/integration/fixtures/api_homeassistant.yaml +++ b/tests/integration/fixtures/api_homeassistant.yaml @@ -108,6 +108,25 @@ text_sensor: format: "HA Empty state updated: %s" args: ['x.c_str()'] + # Test long attribute handling (>255 characters) + # HA states are limited to 255 chars, but attributes are not + - platform: homeassistant + name: "HA Long Attribute" + entity_id: sensor.long_data + attribute: long_value + id: ha_long_attribute + on_value: + then: + - logger.log: + format: "HA Long attribute received, length: %d" + args: ['x.size()'] + # Log the first 50 and last 50 chars to verify no truncation + - lambda: |- + if (x.size() >= 100) { + ESP_LOGI("test", "Long attribute first 50 chars: %.50s", x.c_str()); + ESP_LOGI("test", "Long attribute last 50 chars: %s", x.c_str() + x.size() - 50); + } + # Number component for testing HA number control number: - platform: template diff --git a/tests/integration/test_api_homeassistant.py b/tests/integration/test_api_homeassistant.py index 3fe0dfe045..b4adedf873 100644 --- a/tests/integration/test_api_homeassistant.py +++ b/tests/integration/test_api_homeassistant.py @@ -40,6 +40,7 @@ async def test_api_homeassistant( humidity_update_future = loop.create_future() motion_update_future = loop.create_future() weather_update_future = loop.create_future() + long_attr_future = loop.create_future() # Number future ha_number_future = loop.create_future() @@ -58,6 +59,7 @@ async def test_api_homeassistant( humidity_update_pattern = re.compile(r"HA Humidity state updated: ([\d.]+)") motion_update_pattern = re.compile(r"HA Motion state changed: (ON|OFF)") weather_update_pattern = re.compile(r"HA Weather condition updated: (\w+)") + long_attr_pattern = re.compile(r"HA Long attribute received, length: (\d+)") # Number pattern ha_number_pattern = re.compile(r"Setting HA number to: ([\d.]+)") @@ -143,8 +145,14 @@ async def test_api_homeassistant( elif not weather_update_future.done() and weather_update_pattern.search(line): weather_update_future.set_result(line) - # Check number pattern - elif not ha_number_future.done() and ha_number_pattern.search(line): + # Check long attribute pattern - separate if since it can come at different times + if not long_attr_future.done(): + match = long_attr_pattern.search(line) + if match: + long_attr_future.set_result(int(match.group(1))) + + # Check number pattern - separate if since it can come at different times + if not ha_number_future.done(): match = ha_number_pattern.search(line) if match: ha_number_future.set_result(match.group(1)) @@ -179,6 +187,14 @@ async def test_api_homeassistant( client.send_home_assistant_state("binary_sensor.external_motion", "", "ON") client.send_home_assistant_state("weather.home", "condition", "sunny") + # Send a long attribute (300 characters) to test that attributes aren't truncated + # HA states are limited to 255 chars, but attributes are NOT limited + # This tests the fix for the 256-byte buffer truncation bug + long_attr_value = "X" * 300 # 300 chars - enough to expose truncation bug + client.send_home_assistant_state( + "sensor.long_data", "long_value", long_attr_value + ) + # Test edge cases for zero-copy implementation safety # Empty entity_id should be silently ignored (no crash) client.send_home_assistant_state("", "", "should_be_ignored") @@ -225,6 +241,13 @@ async def test_api_homeassistant( number_value = await asyncio.wait_for(ha_number_future, timeout=5.0) assert number_value == "42.5", f"Unexpected number value: {number_value}" + # Long attribute test - verify 300 chars weren't truncated to 255 + long_attr_len = await asyncio.wait_for(long_attr_future, timeout=5.0) + assert long_attr_len == 300, ( + f"Long attribute was truncated! Expected 300 chars, got {long_attr_len}. " + "This indicates the 256-byte truncation bug." + ) + # Wait for completion await asyncio.wait_for(tests_complete_future, timeout=5.0) From 1a55254258e93f479b8ccd76cae2bb1264cb50d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:28:24 -1000 Subject: [PATCH 0189/2030] [status] Convert to PollingComponent to reduce CPU usage (#13342) --- esphome/components/status/binary_sensor.py | 4 ++-- esphome/components/status/status_binary_sensor.cpp | 8 +++----- esphome/components/status/status_binary_sensor.h | 10 ++++------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/esphome/components/status/binary_sensor.py b/esphome/components/status/binary_sensor.py index c1a4a52ce2..f0c7c87e17 100644 --- a/esphome/components/status/binary_sensor.py +++ b/esphome/components/status/binary_sensor.py @@ -7,14 +7,14 @@ DEPENDENCIES = ["network"] status_ns = cg.esphome_ns.namespace("status") StatusBinarySensor = status_ns.class_( - "StatusBinarySensor", binary_sensor.BinarySensor, cg.Component + "StatusBinarySensor", binary_sensor.BinarySensor, cg.PollingComponent ) CONFIG_SCHEMA = binary_sensor.binary_sensor_schema( StatusBinarySensor, device_class=DEVICE_CLASS_CONNECTIVITY, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, -).extend(cv.COMPONENT_SCHEMA) +).extend(cv.polling_component_schema("1s")) async def to_code(config): diff --git a/esphome/components/status/status_binary_sensor.cpp b/esphome/components/status/status_binary_sensor.cpp index 1795a9c41b..2c95be8569 100644 --- a/esphome/components/status/status_binary_sensor.cpp +++ b/esphome/components/status/status_binary_sensor.cpp @@ -10,12 +10,11 @@ #include "esphome/components/api/api_server.h" #endif -namespace esphome { -namespace status { +namespace esphome::status { static const char *const TAG = "status"; -void StatusBinarySensor::loop() { +void StatusBinarySensor::update() { bool status = network::is_connected(); #ifdef USE_MQTT if (mqtt::global_mqtt_client != nullptr) { @@ -33,5 +32,4 @@ void StatusBinarySensor::loop() { void StatusBinarySensor::setup() { this->publish_initial_state(false); } void StatusBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "Status Binary Sensor", this); } -} // namespace status -} // namespace esphome +} // namespace esphome::status diff --git a/esphome/components/status/status_binary_sensor.h b/esphome/components/status/status_binary_sensor.h index feda8b6328..7e8c31d741 100644 --- a/esphome/components/status/status_binary_sensor.h +++ b/esphome/components/status/status_binary_sensor.h @@ -3,12 +3,11 @@ #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" -namespace esphome { -namespace status { +namespace esphome::status { -class StatusBinarySensor : public binary_sensor::BinarySensor, public Component { +class StatusBinarySensor : public binary_sensor::BinarySensor, public PollingComponent { public: - void loop() override; + void update() override; void setup() override; void dump_config() override; @@ -16,5 +15,4 @@ class StatusBinarySensor : public binary_sensor::BinarySensor, public Component bool is_status_binary_sensor() const override { return true; } }; -} // namespace status -} // namespace esphome +} // namespace esphome::status From b44727aee67b8896dddf89ece727171aee5578ee Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:29:31 -1000 Subject: [PATCH 0190/2030] [socket] Eliminate heap allocations in set_sockaddr() (#13228) --- esphome/components/socket/socket.cpp | 10 +++++----- esphome/components/socket/socket.h | 12 +++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index c92e33393b..bb94ecb675 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -107,9 +107,9 @@ std::unique_ptr socket_ip_loop_monitored(int type, int protocol) { #endif /* USE_NETWORK_IPV6 */ } -socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) { +socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port) { #if USE_NETWORK_IPV6 - if (ip_address.find(':') != std::string::npos) { + if (strchr(ip_address, ':') != nullptr) { if (addrlen < sizeof(sockaddr_in6)) { errno = EINVAL; return 0; @@ -121,14 +121,14 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri #ifdef USE_SOCKET_IMPL_BSD_SOCKETS // Use standard inet_pton for BSD sockets - if (inet_pton(AF_INET6, ip_address.c_str(), &server->sin6_addr) != 1) { + if (inet_pton(AF_INET6, ip_address, &server->sin6_addr) != 1) { errno = EINVAL; return 0; } #else // Use LWIP-specific functions ip6_addr_t ip6; - inet6_aton(ip_address.c_str(), &ip6); + inet6_aton(ip_address, &ip6); memcpy(server->sin6_addr.un.u32_addr, ip6.addr, sizeof(ip6.addr)); #endif return sizeof(sockaddr_in6); @@ -141,7 +141,7 @@ socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::stri auto *server = reinterpret_cast(addr); memset(server, 0, sizeof(sockaddr_in)); server->sin_family = AF_INET; - server->sin_addr.s_addr = inet_addr(ip_address.c_str()); + server->sin_addr.s_addr = inet_addr(ip_address); server->sin_port = htons(port); return sizeof(sockaddr_in); } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 9f9f61de85..d74804fdb0 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -87,7 +87,17 @@ std::unique_ptr socket_loop_monitored(int domain, int type, int protocol std::unique_ptr socket_ip_loop_monitored(int type, int protocol); /// Set a sockaddr to the specified address and port for the IP version used by socket_ip(). -socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port); +/// @param addr Destination sockaddr structure +/// @param addrlen Size of the addr buffer +/// @param ip_address Null-terminated IP address string (IPv4 or IPv6) +/// @param port Port number in host byte order +/// @return Size of the sockaddr structure used, or 0 on error +socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port); + +/// Convenience overload for std::string (backward compatible). +inline socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const std::string &ip_address, uint16_t port) { + return set_sockaddr(addr, addrlen, ip_address.c_str(), port); +} /// Set a sockaddr to the any address and specified port for the IP version used by socket_ip(). socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port); From 2f7270cf8f6f069191920f81503466361e42515b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:36:32 -1000 Subject: [PATCH 0191/2030] [uart] Replace unsafe sprintf with buf_append_printf in debugger (#13288) --- esphome/components/uart/uart_debugger.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_debugger.cpp b/esphome/components/uart/uart_debugger.cpp index b51a57d68e..5490154d01 100644 --- a/esphome/components/uart/uart_debugger.cpp +++ b/esphome/components/uart/uart_debugger.cpp @@ -107,7 +107,7 @@ void UARTDebug::log_hex(UARTDirection direction, std::vector bytes, uin if (i > 0) { res += separator; } - sprintf(buf, "%02X", bytes[i]); + buf_append_printf(buf, sizeof(buf), 0, "%02X", bytes[i]); res += buf; } ESP_LOGD(TAG, "%s", res.c_str()); @@ -147,7 +147,7 @@ void UARTDebug::log_string(UARTDirection direction, std::vector bytes) } else if (bytes[i] == 92) { res += "\\\\"; } else if (bytes[i] < 32 || bytes[i] > 127) { - sprintf(buf, "\\x%02X", bytes[i]); + buf_append_printf(buf, sizeof(buf), 0, "\\x%02X", bytes[i]); res += buf; } else { res += bytes[i]; @@ -166,11 +166,13 @@ void UARTDebug::log_int(UARTDirection direction, std::vector bytes, uin } else { res += ">>> "; } + char buf[4]; // max 3 digits for uint8_t (255) + null for (size_t i = 0; i < len; i++) { if (i > 0) { res += separator; } - res += to_string(bytes[i]); + buf_append_printf(buf, sizeof(buf), 0, "%u", bytes[i]); + res += buf; } ESP_LOGD(TAG, "%s", res.c_str()); delay(10); @@ -189,7 +191,7 @@ void UARTDebug::log_binary(UARTDirection direction, std::vector bytes, if (i > 0) { res += separator; } - sprintf(buf, "0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(bytes[i]), bytes[i]); + buf_append_printf(buf, sizeof(buf), 0, "0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(bytes[i]), bytes[i]); res += buf; } ESP_LOGD(TAG, "%s", res.c_str()); From 7b0db659d18722c827919bab0049f036cbae6ca1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:36:46 -1000 Subject: [PATCH 0192/2030] [rc522_spi] Replace unsafe sprintf with buf_append_printf (#13291) --- esphome/components/rc522_spi/rc522_spi.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/rc522_spi/rc522_spi.cpp b/esphome/components/rc522_spi/rc522_spi.cpp index 23e92be65a..40da449814 100644 --- a/esphome/components/rc522_spi/rc522_spi.cpp +++ b/esphome/components/rc522_spi/rc522_spi.cpp @@ -1,4 +1,5 @@ #include "rc522_spi.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" // Based on: @@ -70,7 +71,7 @@ void RC522Spi::pcd_read_register(PcdRegister reg, ///< The register to read fro index++; #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - sprintf(cstrb, " %x", values[0]); + buf_append_printf(cstrb, sizeof(cstrb), 0, " %x", values[0]); buf.append(cstrb); #endif } @@ -78,7 +79,7 @@ void RC522Spi::pcd_read_register(PcdRegister reg, ///< The register to read fro values[index] = transfer_byte(address); // Read value and tell that we want to read the same address again. #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - sprintf(cstrb, " %x", values[index]); + buf_append_printf(cstrb, sizeof(cstrb), 0, " %x", values[index]); buf.append(cstrb); #endif @@ -88,7 +89,7 @@ void RC522Spi::pcd_read_register(PcdRegister reg, ///< The register to read fro #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE buf = buf + " "; - sprintf(cstrb, "%x", values[index]); + buf_append_printf(cstrb, sizeof(cstrb), 0, "%x", values[index]); buf.append(cstrb); ESP_LOGVV(TAG, "read_register_array_(%x, %d, , %d) -> %s", reg, count, rx_align, buf.c_str()); @@ -127,7 +128,7 @@ void RC522Spi::pcd_write_register(PcdRegister reg, ///< The register to write t transfer_byte(values[index]); #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - sprintf(cstrb, " %x", values[index]); + buf_append_printf(cstrb, sizeof(cstrb), 0, " %x", values[index]); buf.append(cstrb); #endif } From 052b05df56947a262724b63ab332cf97fae8e3db Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:37:02 -1000 Subject: [PATCH 0193/2030] [tuya] Replace unsafe sprintf with snprintf in light color formatting (#13292) --- esphome/components/tuya/light/tuya_light.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/tuya/light/tuya_light.cpp b/esphome/components/tuya/light/tuya_light.cpp index c487f9f50b..097b3c1af8 100644 --- a/esphome/components/tuya/light/tuya_light.cpp +++ b/esphome/components/tuya/light/tuya_light.cpp @@ -191,7 +191,7 @@ void TuyaLight::write_state(light::LightState *state) { case TuyaColorType::RGB: { char buffer[7]; const char *format_str = this->color_type_lowercase_ ? "%02x%02x%02x" : "%02X%02X%02X"; - sprintf(buffer, format_str, int(red * 255), int(green * 255), int(blue * 255)); + snprintf(buffer, sizeof(buffer), format_str, int(red * 255), int(green * 255), int(blue * 255)); color_value = buffer; break; } @@ -201,7 +201,7 @@ void TuyaLight::write_state(light::LightState *state) { rgb_to_hsv(red, green, blue, hue, saturation, value); char buffer[13]; const char *format_str = this->color_type_lowercase_ ? "%04x%04x%04x" : "%04X%04X%04X"; - sprintf(buffer, format_str, hue, int(saturation * 1000), int(value * 1000)); + snprintf(buffer, sizeof(buffer), format_str, hue, int(saturation * 1000), int(value * 1000)); color_value = buffer; break; } @@ -211,8 +211,8 @@ void TuyaLight::write_state(light::LightState *state) { rgb_to_hsv(red, green, blue, hue, saturation, value); char buffer[15]; const char *format_str = this->color_type_lowercase_ ? "%02x%02x%02x%04x%02x%02x" : "%02X%02X%02X%04X%02X%02X"; - sprintf(buffer, format_str, int(red * 255), int(green * 255), int(blue * 255), hue, int(saturation * 255), - int(value * 255)); + snprintf(buffer, sizeof(buffer), format_str, int(red * 255), int(green * 255), int(blue * 255), hue, + int(saturation * 255), int(value * 255)); color_value = buffer; break; } From 5b92d0b89e1e6a6b4cb87c8bdeaeb5a1adb4bdc8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:37:14 -1000 Subject: [PATCH 0194/2030] [wiegand] Replace heap-allocating to_string with stack buffers (#13294) --- esphome/components/wiegand/wiegand.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/esphome/components/wiegand/wiegand.cpp b/esphome/components/wiegand/wiegand.cpp index dd1443d10c..f3f578794a 100644 --- a/esphome/components/wiegand/wiegand.cpp +++ b/esphome/components/wiegand/wiegand.cpp @@ -1,4 +1,5 @@ #include "wiegand.h" +#include #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -69,32 +70,35 @@ void Wiegand::loop() { for (auto *trigger : this->raw_triggers_) trigger->trigger(count, value); if (count == 26) { - std::string tag = to_string((value >> 1) & 0xffffff); - ESP_LOGD(TAG, "received 26-bit tag: %s", tag.c_str()); + char tag_buf[12]; // max 8 digits for 24-bit value + null + buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu32, static_cast((value >> 1) & 0xffffff)); + ESP_LOGD(TAG, "received 26-bit tag: %s", tag_buf); if (!check_eparity(value, 13, 13) || !check_oparity(value, 0, 13)) { ESP_LOGW(TAG, "invalid parity"); return; } for (auto *trigger : this->tag_triggers_) - trigger->trigger(tag); + trigger->trigger(tag_buf); } else if (count == 34) { - std::string tag = to_string((value >> 1) & 0xffffffff); - ESP_LOGD(TAG, "received 34-bit tag: %s", tag.c_str()); + char tag_buf[12]; // max 10 digits for 32-bit value + null + buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu32, static_cast((value >> 1) & 0xffffffff)); + ESP_LOGD(TAG, "received 34-bit tag: %s", tag_buf); if (!check_eparity(value, 17, 17) || !check_oparity(value, 0, 17)) { ESP_LOGW(TAG, "invalid parity"); return; } for (auto *trigger : this->tag_triggers_) - trigger->trigger(tag); + trigger->trigger(tag_buf); } else if (count == 37) { - std::string tag = to_string((value >> 1) & 0x7ffffffff); - ESP_LOGD(TAG, "received 37-bit tag: %s", tag.c_str()); + char tag_buf[12]; // max 11 digits for 35-bit value + null + buf_append_printf(tag_buf, sizeof(tag_buf), 0, "%" PRIu64, static_cast((value >> 1) & 0x7ffffffff)); + ESP_LOGD(TAG, "received 37-bit tag: %s", tag_buf); if (!check_eparity(value, 18, 19) || !check_oparity(value, 0, 19)) { ESP_LOGW(TAG, "invalid parity"); return; } for (auto *trigger : this->tag_triggers_) - trigger->trigger(tag); + trigger->trigger(tag_buf); } else if (count == 4) { for (auto *trigger : this->key_triggers_) trigger->trigger(value); From 0f3bac5dd65dcc62e9b3ef72aafbe8eafd4090f2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:37:29 -1000 Subject: [PATCH 0195/2030] [nextion] Replace to_string with stack buffer and fix unsafe sprintf (#13295) --- esphome/components/nextion/nextion.cpp | 6 ++++-- esphome/components/nextion/nextion_upload_arduino.cpp | 2 +- esphome/components/nextion/nextion_upload_esp32.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index d77af510d7..354288e1a3 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -1,6 +1,7 @@ #include "nextion.h" #include #include "esphome/core/application.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/util.h" @@ -1283,8 +1284,9 @@ void Nextion::check_pending_waveform_() { size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size() : 255; // ADDT command can only send 255 - std::string command = "addt " + to_string(component->get_component_id()) + "," + - to_string(component->get_wave_channel_id()) + "," + to_string(buffer_to_send); + char command[24]; // "addt " + uint8 + "," + uint8 + "," + uint8 + null = max 17 chars + buf_append_printf(command, sizeof(command), 0, "addt %u,%u,%zu", component->get_component_id(), + component->get_wave_channel_id(), buffer_to_send); if (!this->send_command_(command)) { delete nb; // NOLINT(cppcoreguidelines-owning-memory) this->waveform_queue_.pop_front(); diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index d210bad004..220c75f9d3 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -34,7 +34,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { } char range_header[32]; - sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); + buf_append_printf(range_header, sizeof(range_header), 0, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); ESP_LOGV(TAG, "Range: %s", range_header); http_client.addHeader("Range", range_header); int code = http_client.GET(); diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index 712fa8e78e..c4e6ff7182 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -36,7 +36,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r } char range_header[32]; - sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); + buf_append_printf(range_header, sizeof(range_header), 0, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end); ESP_LOGV(TAG, "Range: %s", range_header); esp_http_client_set_header(http_client, "Range", range_header); ESP_LOGV(TAG, "Open HTTP"); From eb664291444e32136d097e27b1ba889f1445e856 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:39:23 -1000 Subject: [PATCH 0196/2030] [sml] Use stack buffers instead of str_sprintf (#13222) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/sml/sml_parser.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 85e5a2da03..16e37949dc 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -104,7 +104,10 @@ std::vector SmlFile::get_obis_info() { std::string bytes_repr(const BytesView &buffer) { std::string repr; for (auto const value : buffer) { - repr += str_sprintf("%02x", value & 0xff); + // max 3: 2 hex digits + null + char hex_buf[3]; + snprintf(hex_buf, sizeof(hex_buf), "%02x", static_cast(value)); + repr += hex_buf; } return repr; } @@ -146,7 +149,11 @@ ObisInfo::ObisInfo(const BytesView &server_id, const SmlNode &val_list_entry) : } std::string ObisInfo::code_repr() const { - return str_sprintf("%d-%d:%d.%d.%d", this->code[0], this->code[1], this->code[2], this->code[3], this->code[4]); + // max 20: "255-255:255.255.255" (19 chars) + null + char buf[20]; + snprintf(buf, sizeof(buf), "%d-%d:%d.%d.%d", this->code[0], this->code[1], this->code[2], this->code[3], + this->code[4]); + return buf; } } // namespace sml From f60c03e350482edf652eb91da62cbdbb6c03c5a5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:39:53 -1000 Subject: [PATCH 0197/2030] [syslog] Use buf_append_printf for ESP8266 flash optimization (#13286) --- esphome/components/syslog/esphome_syslog.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/syslog/esphome_syslog.cpp b/esphome/components/syslog/esphome_syslog.cpp index 83ad6b2720..376de54db4 100644 --- a/esphome/components/syslog/esphome_syslog.cpp +++ b/esphome/components/syslog/esphome_syslog.cpp @@ -47,29 +47,27 @@ void Syslog::log_(const int level, const char *tag, const char *message, size_t size_t remaining = sizeof(packet); // Write PRI - abort if this fails as packet would be malformed - int ret = snprintf(packet, remaining, "<%d>", pri); - if (ret <= 0 || static_cast(ret) >= remaining) { - return; + offset = buf_append_printf(packet, sizeof(packet), 0, "<%d>", pri); + if (offset == 0) { + return; // PRI always produces at least "<0>" (3 chars), so 0 means error } - offset = ret; - remaining -= ret; + remaining -= offset; // Write timestamp directly into packet (RFC 5424: use "-" if time not valid or strftime fails) auto now = this->time_->now(); size_t ts_written = now.is_valid() ? now.strftime(packet + offset, remaining, "%b %e %H:%M:%S") : 0; if (ts_written > 0) { offset += ts_written; - remaining -= ts_written; } else if (remaining > 0) { packet[offset++] = '-'; - remaining--; } // Write hostname, tag, and message - ret = snprintf(packet + offset, remaining, " %s %s: %.*s", App.get_name().c_str(), tag, (int) len, message); - if (ret > 0) { - // snprintf returns chars that would be written; clamp to actual buffer space - offset += std::min(static_cast(ret), remaining > 0 ? remaining - 1 : 0); + offset = buf_append_printf(packet, sizeof(packet), offset, " %s %s: %.*s", App.get_name().c_str(), tag, (int) len, + message); + // Clamp to exclude null terminator position if buffer was filled + if (offset >= sizeof(packet)) { + offset = sizeof(packet) - 1; } if (offset > 0) { From 67871a1683cac8b35c0e7d2a3ca885597e8cbbc5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:40:14 -1000 Subject: [PATCH 0198/2030] [ccs811] Use buf_append_printf for buffer safety and ESP8266 flash optimization (#13300) --- esphome/components/ccs811/ccs811.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ccs811/ccs811.cpp b/esphome/components/ccs811/ccs811.cpp index 84355f2793..9ff01b32b2 100644 --- a/esphome/components/ccs811/ccs811.cpp +++ b/esphome/components/ccs811/ccs811.cpp @@ -81,8 +81,8 @@ void CCS811Component::setup() { bootloader_version, application_version); if (this->version_ != nullptr) { char version[20]; // "15.15.15 (0xffff)" is 17 chars, plus NUL, plus wiggle room - sprintf(version, "%d.%d.%d (0x%02x)", (application_version >> 12 & 15), (application_version >> 8 & 15), - (application_version >> 4 & 15), application_version); + buf_append_printf(version, sizeof(version), 0, "%d.%d.%d (0x%02x)", (application_version >> 12 & 15), + (application_version >> 8 & 15), (application_version >> 4 & 15), application_version); ESP_LOGD(TAG, "publishing version state: %s", version); this->version_->publish_state(version); } From 226867b05caeaa9ba1644ca493830ec7d9126044 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:40:53 -1000 Subject: [PATCH 0199/2030] [esp8266] Use direct SDK calls instead of Arduino ESP class wrappers (#13353) --- esphome/components/esp8266/core.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 200ca567c2..784b87916b 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -6,7 +6,11 @@ #include "esphome/core/helpers.h" #include "preferences.h" #include -#include +#include + +extern "C" { +#include +} namespace esphome { @@ -16,23 +20,19 @@ void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { - ESP.restart(); // NOLINT(readability-static-accessed-through-instance) + system_restart(); // restart() doesn't always end execution while (true) { // NOLINT(clang-diagnostic-unreachable-code) yield(); } } void arch_init() {} -void IRAM_ATTR HOT arch_feed_wdt() { - ESP.wdtFeed(); // NOLINT(readability-static-accessed-through-instance) -} +void IRAM_ATTR HOT arch_feed_wdt() { system_soft_wdt_feed(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } -uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { - return ESP.getCycleCount(); // NOLINT(readability-static-accessed-through-instance) -} +uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return esp_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return F_CPU; } void force_link_symbols() { From 6cbe67200494a7e98d8fd3f581c5c2535cfd5b4c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:41:07 -1000 Subject: [PATCH 0200/2030] [tuya] Use buf_append_printf for ESP8266 flash optimization (#13287) --- esphome/components/tuya/text_sensor/tuya_text_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp index 36b6d630ae..b15fb6f85a 100644 --- a/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp +++ b/esphome/components/tuya/text_sensor/tuya_text_sensor.cpp @@ -24,7 +24,7 @@ void TuyaTextSensor::setup() { } case TuyaDatapointType::ENUM: { char buf[4]; // uint8_t max is 3 digits + null - snprintf(buf, sizeof(buf), "%u", datapoint.value_enum); + buf_append_printf(buf, sizeof(buf), 0, "%u", datapoint.value_enum); ESP_LOGD(TAG, "MCU reported text sensor %u is: %s", datapoint.id, buf); this->publish_state(buf); break; From 635983f163f74193849b7400a6ce4456245c4c0c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:41:19 -1000 Subject: [PATCH 0201/2030] [uptime] Use buf_append_printf for ESP8266 flash optimization (#13282) --- .../components/uptime/text_sensor/uptime_text_sensor.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index b7b3273f39..acd3980a1a 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -9,17 +9,12 @@ namespace uptime { static const char *const TAG = "uptime.sensor"; -// Clamp position to valid buffer range when snprintf indicates truncation -static size_t clamp_buffer_pos(size_t pos, size_t buf_size) { return pos < buf_size ? pos : buf_size - 1; } - static void append_unit(char *buf, size_t buf_size, size_t &pos, const char *separator, unsigned value, const char *label) { if (pos > 0) { - pos += snprintf(buf + pos, buf_size - pos, "%s", separator); - pos = clamp_buffer_pos(pos, buf_size); + pos = buf_append_printf(buf, buf_size, pos, "%s", separator); } - pos += snprintf(buf + pos, buf_size - pos, "%u%s", value, label); - pos = clamp_buffer_pos(pos, buf_size); + pos = buf_append_printf(buf, buf_size, pos, "%u%s", value, label); } void UptimeTextSensor::setup() { From d8849b16f24a09611e7cd5bce686adf4fffa4b6f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:41:34 -1000 Subject: [PATCH 0202/2030] [gpio] Use buf_append_printf in dump_summary for ESP8266 flash optimization (#13283) --- esphome/components/ch422g/ch422g.cpp | 2 +- esphome/components/esp8266/gpio.cpp | 2 +- esphome/components/max6956/max6956.cpp | 2 +- esphome/components/mcp23016/mcp23016.cpp | 2 +- esphome/components/mcp23xxx_base/mcp23xxx_base.cpp | 2 +- esphome/components/mpr121/mpr121.cpp | 2 +- esphome/components/pca6416a/pca6416a.cpp | 2 +- esphome/components/pca9554/pca9554.cpp | 2 +- esphome/components/pcf8574/pcf8574.cpp | 2 +- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp | 2 +- esphome/components/sn74hc165/sn74hc165.cpp | 2 +- esphome/components/sn74hc595/sn74hc595.cpp | 2 +- esphome/components/sx1509/sx1509_gpio_pin.cpp | 2 +- esphome/components/tca9555/tca9555.cpp | 2 +- esphome/components/weikai/weikai.cpp | 2 +- esphome/components/xl9535/xl9535.cpp | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index d031c31294..eef95b9ba2 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -133,7 +133,7 @@ bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pi void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); } size_t CH422GGPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "EXIO%u via CH422G", this->pin_); + return buf_append_printf(buffer, len, 0, "EXIO%u via CH422G", this->pin_); } void CH422GGPIOPin::set_flags(gpio::Flags flags) { flags_ = flags; diff --git a/esphome/components/esp8266/gpio.cpp b/esphome/components/esp8266/gpio.cpp index 7a5ee08984..659233443e 100644 --- a/esphome/components/esp8266/gpio.cpp +++ b/esphome/components/esp8266/gpio.cpp @@ -99,7 +99,7 @@ void ESP8266GPIOPin::pin_mode(gpio::Flags flags) { } size_t ESP8266GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "GPIO%u", this->pin_); + return buf_append_printf(buffer, len, 0, "GPIO%u", this->pin_); } bool ESP8266GPIOPin::digital_read() { diff --git a/esphome/components/max6956/max6956.cpp b/esphome/components/max6956/max6956.cpp index 13fe5a5323..6ba17f11d1 100644 --- a/esphome/components/max6956/max6956.cpp +++ b/esphome/components/max6956/max6956.cpp @@ -162,7 +162,7 @@ void MAX6956GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this- bool MAX6956GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void MAX6956GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t MAX6956GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via Max6956", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via Max6956", this->pin_); } } // namespace max6956 diff --git a/esphome/components/mcp23016/mcp23016.cpp b/esphome/components/mcp23016/mcp23016.cpp index 87c2668962..56b2ecf9f4 100644 --- a/esphome/components/mcp23016/mcp23016.cpp +++ b/esphome/components/mcp23016/mcp23016.cpp @@ -100,7 +100,7 @@ void MCP23016GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this bool MCP23016GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void MCP23016GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t MCP23016GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via MCP23016", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via MCP23016", this->pin_); } } // namespace mcp23016 diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp b/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp index 302f6b8280..535119fc5c 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp @@ -17,7 +17,7 @@ template void MCP23XXXGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } template size_t MCP23XXXGPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via MCP23XXX", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via MCP23XXX", this->pin_); } template class MCP23XXXGPIOPin<8>; diff --git a/esphome/components/mpr121/mpr121.cpp b/esphome/components/mpr121/mpr121.cpp index 4b358e384c..cd9c81fe03 100644 --- a/esphome/components/mpr121/mpr121.cpp +++ b/esphome/components/mpr121/mpr121.cpp @@ -154,7 +154,7 @@ void MPR121GPIOPin::digital_write(bool value) { } size_t MPR121GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "ELE%u on MPR121", this->pin_); + return buf_append_printf(buffer, len, 0, "ELE%u on MPR121", this->pin_); } } // namespace mpr121 diff --git a/esphome/components/pca6416a/pca6416a.cpp b/esphome/components/pca6416a/pca6416a.cpp index 909bac5f05..f393af88ce 100644 --- a/esphome/components/pca6416a/pca6416a.cpp +++ b/esphome/components/pca6416a/pca6416a.cpp @@ -181,7 +181,7 @@ void PCA6416AGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this bool PCA6416AGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void PCA6416AGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t PCA6416AGPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via PCA6416A", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via PCA6416A", this->pin_); } } // namespace pca6416a diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index a6f9c2396c..c574ce6593 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -130,7 +130,7 @@ void PCA9554GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this- bool PCA9554GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void PCA9554GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t PCA9554GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via PCA9554", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via PCA9554", this->pin_); } } // namespace pca9554 diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index 8bdd312ab9..b7d3848f0e 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -107,7 +107,7 @@ void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this- bool PCF8574GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void PCF8574GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t PCF8574GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via PCF8574", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via PCF8574", this->pin_); } } // namespace pcf8574 diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index f3a1f013d9..fdff11dedb 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -165,7 +165,7 @@ void PI4IOE5V6408GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t PI4IOE5V6408GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via PI4IOE5V6408", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via PI4IOE5V6408", this->pin_); } } // namespace pi4ioe5v6408 diff --git a/esphome/components/sn74hc165/sn74hc165.cpp b/esphome/components/sn74hc165/sn74hc165.cpp index 718e0b86ed..63b3f98521 100644 --- a/esphome/components/sn74hc165/sn74hc165.cpp +++ b/esphome/components/sn74hc165/sn74hc165.cpp @@ -65,7 +65,7 @@ float SN74HC165Component::get_setup_priority() const { return setup_priority::IO bool SN74HC165GPIOPin::digital_read() { return this->parent_->digital_read_(this->pin_) != this->inverted_; } size_t SN74HC165GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via SN74HC165", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via SN74HC165", this->pin_); } } // namespace sn74hc165 diff --git a/esphome/components/sn74hc595/sn74hc595.cpp b/esphome/components/sn74hc595/sn74hc595.cpp index 6b5c5d9fc4..1bb8c7936d 100644 --- a/esphome/components/sn74hc595/sn74hc595.cpp +++ b/esphome/components/sn74hc595/sn74hc595.cpp @@ -94,7 +94,7 @@ void SN74HC595GPIOPin::digital_write(bool value) { this->parent_->digital_write_(this->pin_, value != this->inverted_); } size_t SN74HC595GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via SN74HC595", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via SN74HC595", this->pin_); } } // namespace sn74hc595 diff --git a/esphome/components/sx1509/sx1509_gpio_pin.cpp b/esphome/components/sx1509/sx1509_gpio_pin.cpp index 41a99eba4b..a7e5d0514d 100644 --- a/esphome/components/sx1509/sx1509_gpio_pin.cpp +++ b/esphome/components/sx1509/sx1509_gpio_pin.cpp @@ -13,7 +13,7 @@ void SX1509GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this-> bool SX1509GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void SX1509GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t SX1509GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via sx1509", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via sx1509", this->pin_); } } // namespace sx1509 diff --git a/esphome/components/tca9555/tca9555.cpp b/esphome/components/tca9555/tca9555.cpp index 376de6a370..79c5253898 100644 --- a/esphome/components/tca9555/tca9555.cpp +++ b/esphome/components/tca9555/tca9555.cpp @@ -139,7 +139,7 @@ void TCA9555GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this- bool TCA9555GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } void TCA9555GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } size_t TCA9555GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via TCA9555", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via TCA9555", this->pin_); } } // namespace tca9555 diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index 197b516bb2..d0a8f8366b 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -246,7 +246,7 @@ void WeikaiGPIOPin::setup() { } size_t WeikaiGPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via WeiKai %s", this->pin_, this->parent_->get_name()); + return buf_append_printf(buffer, len, 0, "%u via WeiKai %s", this->pin_, this->parent_->get_name()); } /////////////////////////////////////////////////////////////////////////////// diff --git a/esphome/components/xl9535/xl9535.cpp b/esphome/components/xl9535/xl9535.cpp index dd6c8188eb..cfcbeeeb8d 100644 --- a/esphome/components/xl9535/xl9535.cpp +++ b/esphome/components/xl9535/xl9535.cpp @@ -111,7 +111,7 @@ void XL9535Component::pin_mode(uint8_t pin, gpio::Flags mode) { void XL9535GPIOPin::setup() { this->pin_mode(this->flags_); } size_t XL9535GPIOPin::dump_summary(char *buffer, size_t len) const { - return snprintf(buffer, len, "%u via XL9535", this->pin_); + return buf_append_printf(buffer, len, 0, "%u via XL9535", this->pin_); } void XL9535GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } From 3182222d60e5d32ccdd3d1cefdc7e02d666038f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:41:47 -1000 Subject: [PATCH 0203/2030] [esp32_hosted] Use stack buffer instead of str_sprintf for version string (#13226) --- .../components/esp32_hosted/update/esp32_hosted_update.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index d69a438578..a82ee48718 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -69,7 +69,10 @@ void Esp32HostedUpdate::setup() { // Get coprocessor version esp_hosted_coprocessor_fwver_t ver_info; if (esp_hosted_get_coprocessor_fwversion(&ver_info) == ESP_OK) { - this->update_info_.current_version = str_sprintf("%d.%d.%d", ver_info.major1, ver_info.minor1, ver_info.patch1); + // 16 bytes: "255.255.255" (11 chars) + null + safety margin + char buf[16]; + snprintf(buf, sizeof(buf), "%d.%d.%d", ver_info.major1, ver_info.minor1, ver_info.patch1); + this->update_info_.current_version = buf; } else { this->update_info_.current_version = "unknown"; } From ea0fac96cbfcea1866749f5e6d4dacaf04f4b472 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:42:04 -1000 Subject: [PATCH 0204/2030] [core][mqtt] Add str_sanitize_to(), soft-deprecate str_sanitize() (#13233) --- esphome/components/mqtt/mqtt_client.cpp | 3 ++- esphome/components/mqtt/mqtt_component.cpp | 5 +++-- esphome/core/helpers.cpp | 19 +++++++++++++++---- esphome/core/helpers.h | 18 ++++++++++++++++++ script/ci-custom.py | 2 ++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 0ab5b238b5..7d4050284f 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -635,7 +635,8 @@ void MQTTClientComponent::set_log_message_template(MQTTMessage &&message) { this const MQTTDiscoveryInfo &MQTTClientComponent::get_discovery_info() const { return this->discovery_info_; } void MQTTClientComponent::set_topic_prefix(const std::string &topic_prefix, const std::string &check_topic_prefix) { if (App.is_name_add_mac_suffix_enabled() && (topic_prefix == check_topic_prefix)) { - this->topic_prefix_ = str_sanitize(App.get_name()); + char buf[ESPHOME_DEVICE_NAME_MAX_LEN + 1]; + this->topic_prefix_ = str_sanitize_to(buf, App.get_name().c_str()); } else { this->topic_prefix_ = topic_prefix; } diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 8e4b3437ab..3b9290259b 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -48,7 +48,8 @@ void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; void MQTTComponent::set_retain(bool retain) { this->retain_ = retain; } std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const { - std::string sanitized_name = str_sanitize(App.get_name()); + char sanitized_name[ESPHOME_DEVICE_NAME_MAX_LEN + 1]; + str_sanitize_to(sanitized_name, App.get_name().c_str()); const char *comp_type = this->component_type(); char object_id_buf[OBJECT_ID_MAX_LEN]; StringRef object_id = this->get_default_object_id_to_(object_id_buf); @@ -60,7 +61,7 @@ std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discove p = append_char(p, '/'); p = append_str(p, comp_type, strlen(comp_type)); p = append_char(p, '/'); - p = append_str(p, sanitized_name.data(), sanitized_name.size()); + p = append_str(p, sanitized_name, strlen(sanitized_name)); p = append_char(p, '/'); p = append_str(p, object_id.c_str(), object_id.size()); p = append_str(p, "/config", 7); diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 44c20845e8..e7b901d71f 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -206,11 +206,22 @@ std::string str_snake_case(const std::string &str) { } return result; } -std::string str_sanitize(const std::string &str) { - std::string result = str; - for (char &c : result) { - c = to_sanitized_char(c); +char *str_sanitize_to(char *buffer, size_t buffer_size, const char *str) { + if (buffer_size == 0) { + return buffer; } + size_t i = 0; + while (*str && i < buffer_size - 1) { + buffer[i++] = to_sanitized_char(*str++); + } + buffer[i] = '\0'; + return buffer; +} + +std::string str_sanitize(const std::string &str) { + std::string result; + result.resize(str.size()); + str_sanitize_to(&result[0], str.size() + 1, str.c_str()); return result; } std::string str_snprintf(const char *fmt, size_t len, ...) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 4185596c7b..bd3a4def05 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -609,7 +609,25 @@ std::string str_snake_case(const std::string &str); constexpr char to_sanitized_char(char c) { return (c == '-' || c == '_' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) ? c : '_'; } + +/** Sanitize a string to buffer, keeping only alphanumerics, dashes, and underscores. + * + * @param buffer Output buffer to write to. + * @param buffer_size Size of the output buffer. + * @param str Input string to sanitize. + * @return Pointer to buffer. + * + * Buffer size needed: strlen(str) + 1. + */ +char *str_sanitize_to(char *buffer, size_t buffer_size, const char *str); + +/// Sanitize a string to buffer. Automatically deduces buffer size. +template inline char *str_sanitize_to(char (&buffer)[N], const char *str) { + return str_sanitize_to(buffer, N, str); +} + /// Sanitizes the input string by removing all characters but alphanumerics, dashes and underscores. +/// @warning Allocates heap memory. Use str_sanitize_to() with a stack buffer instead. std::string str_sanitize(const std::string &str); /// Calculate FNV-1 hash of a string while applying snake_case + sanitize transformations. diff --git a/script/ci-custom.py b/script/ci-custom.py index e227ec873e..ee2e73872c 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -688,6 +688,7 @@ HEAP_ALLOCATING_HELPERS = { "format_mac_address_pretty": "format_mac_addr_upper() with a stack buffer", "get_mac_address": "get_mac_address_into_buffer() with a stack buffer", "get_mac_address_pretty": "get_mac_address_pretty_into_buffer() with a stack buffer", + "str_sanitize": "str_sanitize_to() with a stack buffer", "str_truncate": "removal (function is unused)", "str_upper_case": "removal (function is unused)", "str_snake_case": "removal (function is unused)", @@ -706,6 +707,7 @@ HEAP_ALLOCATING_HELPERS = { r"format_mac_address_pretty|" r"get_mac_address_pretty(?!_)|" r"get_mac_address(?!_)|" + r"str_sanitize(?!_)|" r"str_truncate|" r"str_upper_case|" r"str_snake_case" From dfbf79d6d6af4c3ddd09f448f73c908fd102130f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:42:19 -1000 Subject: [PATCH 0205/2030] [homeassistant] Use buf_append_printf for ESP8266 flash optimization (#13284) --- .../components/homeassistant/number/homeassistant_number.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/homeassistant/number/homeassistant_number.cpp b/esphome/components/homeassistant/number/homeassistant_number.cpp index 92ecd5ea39..00ea88ff16 100644 --- a/esphome/components/homeassistant/number/homeassistant_number.cpp +++ b/esphome/components/homeassistant/number/homeassistant_number.cpp @@ -97,7 +97,7 @@ void HomeassistantNumber::control(float value) { entity_value.key = VALUE_KEY; // Stack buffer - no heap allocation; %g produces shortest representation char value_buf[16]; - snprintf(value_buf, sizeof(value_buf), "%g", value); + buf_append_printf(value_buf, sizeof(value_buf), 0, "%g", value); entity_value.value = StringRef(value_buf); api::global_api_server->send_homeassistant_action(resp); From d9fc625c6aab64837b412062d18f0fe86e9d09e6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:43:05 -1000 Subject: [PATCH 0206/2030] [web_server] Simplify datetime formatting with buf_append_printf (#13281) --- esphome/components/web_server/web_server.cpp | 21 ++++---------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 61b9ea5163..e538a35e8c 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1188,11 +1188,7 @@ std::string WebServer::date_json_(datetime::DateEntity *obj, JsonDetail start_co // Format: YYYY-MM-DD (max 10 chars + null) char value[12]; -#ifdef USE_ESP8266 - snprintf_P(value, sizeof(value), PSTR("%d-%02d-%02d"), obj->year, obj->month, obj->day); -#else - snprintf(value, sizeof(value), "%d-%02d-%02d", obj->year, obj->month, obj->day); -#endif + buf_append_printf(value, sizeof(value), 0, "%d-%02d-%02d", obj->year, obj->month, obj->day); set_json_icon_state_value(root, obj, "date", value, value, start_config); if (start_config == DETAIL_ALL) { this->add_sorting_info_(root, obj); @@ -1251,11 +1247,7 @@ std::string WebServer::time_json_(datetime::TimeEntity *obj, JsonDetail start_co // Format: HH:MM:SS (8 chars + null) char value[12]; -#ifdef USE_ESP8266 - snprintf_P(value, sizeof(value), PSTR("%02d:%02d:%02d"), obj->hour, obj->minute, obj->second); -#else - snprintf(value, sizeof(value), "%02d:%02d:%02d", obj->hour, obj->minute, obj->second); -#endif + buf_append_printf(value, sizeof(value), 0, "%02d:%02d:%02d", obj->hour, obj->minute, obj->second); set_json_icon_state_value(root, obj, "time", value, value, start_config); if (start_config == DETAIL_ALL) { this->add_sorting_info_(root, obj); @@ -1314,13 +1306,8 @@ std::string WebServer::datetime_json_(datetime::DateTimeEntity *obj, JsonDetail // Format: YYYY-MM-DD HH:MM:SS (max 19 chars + null) char value[24]; -#ifdef USE_ESP8266 - snprintf_P(value, sizeof(value), PSTR("%d-%02d-%02d %02d:%02d:%02d"), obj->year, obj->month, obj->day, obj->hour, - obj->minute, obj->second); -#else - snprintf(value, sizeof(value), "%d-%02d-%02d %02d:%02d:%02d", obj->year, obj->month, obj->day, obj->hour, obj->minute, - obj->second); -#endif + buf_append_printf(value, sizeof(value), 0, "%d-%02d-%02d %02d:%02d:%02d", obj->year, obj->month, obj->day, obj->hour, + obj->minute, obj->second); set_json_icon_state_value(root, obj, "datetime", value, value, start_config); if (start_config == DETAIL_ALL) { this->add_sorting_info_(root, obj); From b9e72a877419302950c991dab158ec2e80e73c2c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:43:19 -1000 Subject: [PATCH 0207/2030] [daikin_arc] Fix undefined behavior in sprintf calls (#13279) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/daikin_arc/daikin_arc.cpp | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp index f05342f482..4726310806 100644 --- a/esphome/components/daikin_arc/daikin_arc.cpp +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -258,8 +258,9 @@ bool DaikinArcClimate::parse_state_frame_(const uint8_t frame[]) { } char buf[DAIKIN_STATE_FRAME_SIZE * 3 + 1] = {0}; + size_t pos = 0; for (size_t i = 0; i < DAIKIN_STATE_FRAME_SIZE; i++) { - sprintf(buf, "%s%02x ", buf, frame[i]); + pos = buf_append_printf(buf, sizeof(buf), pos, "%02x ", frame[i]); } ESP_LOGD(TAG, "FRAME %s", buf); @@ -349,8 +350,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { if (data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) { valid_daikin_frame = true; size_t bytes_count = data.size() / 2 / 8; - std::unique_ptr buf(new char[bytes_count * 3 + 1]); - buf[0] = '\0'; + size_t buf_size = bytes_count * 3 + 1; + std::unique_ptr buf(new char[buf_size]()); // value-initialize (zero-fill) + size_t buf_pos = 0; for (size_t i = 0; i < bytes_count; i++) { uint8_t byte = 0; for (int8_t bit = 0; bit < 8; bit++) { @@ -361,19 +363,19 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { break; } } - sprintf(buf.get(), "%s%02x ", buf.get(), byte); + buf_pos = buf_append_printf(buf.get(), buf_size, buf_pos, "%02x ", byte); } ESP_LOGD(TAG, "WHOLE FRAME %s size: %d", buf.get(), data.size()); } if (!valid_daikin_frame) { - char sbuf[16 * 10 + 1]; - sbuf[0] = '\0'; + char sbuf[16 * 10 + 1] = {0}; + size_t sbuf_pos = 0; for (size_t j = 0; j < static_cast(data.size()); j++) { if ((j - 2) % 16 == 0) { if (j > 0) { ESP_LOGD(TAG, "DATA %04x: %s", (j - 16 > 0xffff ? 0 : j - 16), sbuf); } - sbuf[0] = '\0'; + sbuf_pos = 0; } char type_ch = ' '; // debug_tolerance = 25% @@ -401,9 +403,10 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { type_ch = '0'; if (abs(data[j]) > 100000) { - sprintf(sbuf, "%s%-5d[%c] ", sbuf, data[j] > 0 ? 99999 : -99999, type_ch); + sbuf_pos = buf_append_printf(sbuf, sizeof(sbuf), sbuf_pos, "%-5d[%c] ", data[j] > 0 ? 99999 : -99999, type_ch); } else { - sprintf(sbuf, "%s%-5d[%c] ", sbuf, (int) (round(data[j] / 10.) * 10), type_ch); + sbuf_pos = + buf_append_printf(sbuf, sizeof(sbuf), sbuf_pos, "%-5d[%c] ", (int) (round(data[j] / 10.) * 10), type_ch); } if (j + 1 == static_cast(data.size())) { ESP_LOGD(TAG, "DATA %04x: %s", (j - 8 > 0xffff ? 0 : j - 8), sbuf); From 98ccab87a7c26c2bb681597c12fe72f579c16019 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:43:36 -1000 Subject: [PATCH 0208/2030] [tormatic] Use stack buffers instead of str_sprintf in debug methods (#13225) --- .../components/tormatic/tormatic_protocol.h | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/esphome/components/tormatic/tormatic_protocol.h b/esphome/components/tormatic/tormatic_protocol.h index e26535e985..057713b884 100644 --- a/esphome/components/tormatic/tormatic_protocol.h +++ b/esphome/components/tormatic/tormatic_protocol.h @@ -55,6 +55,7 @@ enum MessageType : uint16_t { COMMAND = 0x0106, }; +// Max string length: 7 ("Unknown"/"Command"). Update print() buffer sizes if adding longer strings. inline const char *message_type_to_str(MessageType t) { switch (t) { case STATUS: @@ -83,7 +84,11 @@ struct MessageHeader { } std::string print() { - return str_sprintf("MessageHeader: seq %d, len %d, type %s", this->seq, this->len, message_type_to_str(this->type)); + // 64 bytes: "MessageHeader: seq " + uint16 + ", len " + uint32 + ", type " + type + safety margin + char buf[64]; + buf_append_printf(buf, sizeof(buf), 0, "MessageHeader: seq %d, len %d, type %s", this->seq, this->len, + message_type_to_str(this->type)); + return buf; } void byteswap() { @@ -131,6 +136,7 @@ inline CoverOperation gate_status_to_cover_operation(GateStatus s) { return COVER_OPERATION_IDLE; } +// Max string length: 11 ("Ventilating"). Update print() buffer sizes if adding longer strings. inline const char *gate_status_to_str(GateStatus s) { switch (s) { case PAUSED: @@ -170,7 +176,12 @@ struct StatusReply { GateStatus state; uint8_t trailer = 0x0; - std::string print() { return str_sprintf("StatusReply: state %s", gate_status_to_str(this->state)); } + std::string print() { + // 48 bytes: "StatusReply: state " (19) + state (11) + safety margin + char buf[48]; + buf_append_printf(buf, sizeof(buf), 0, "StatusReply: state %s", gate_status_to_str(this->state)); + return buf; + } void byteswap(){}; } __attribute__((packed)); @@ -202,7 +213,12 @@ struct CommandRequestReply { CommandRequestReply() = default; CommandRequestReply(GateStatus state) { this->state = state; } - std::string print() { return str_sprintf("CommandRequestReply: state %s", gate_status_to_str(this->state)); } + std::string print() { + // 56 bytes: "CommandRequestReply: state " (27) + state (11) + safety margin + char buf[56]; + buf_append_printf(buf, sizeof(buf), 0, "CommandRequestReply: state %s", gate_status_to_str(this->state)); + return buf; + } void byteswap() { this->type = convert_big_endian(this->type); } } __attribute__((packed)); From 8142f5db44bfd7d54342ceb938d5d35bd2319359 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:43:50 -1000 Subject: [PATCH 0209/2030] [zephyr] Avoid heap allocation in preferences key formatting (#13215) --- esphome/components/zephyr/preferences.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/esphome/components/zephyr/preferences.cpp b/esphome/components/zephyr/preferences.cpp index 08b361b8fb..311133a813 100644 --- a/esphome/components/zephyr/preferences.cpp +++ b/esphome/components/zephyr/preferences.cpp @@ -5,6 +5,8 @@ #include "esphome/core/preferences.h" #include "esphome/core/log.h" #include +#include +#include namespace esphome { namespace zephyr { @@ -13,6 +15,9 @@ static const char *const TAG = "zephyr.preferences"; #define ESPHOME_SETTINGS_KEY "esphome" +// Buffer size for key: "esphome/" (8) + max hex uint32 (8) + null terminator (1) = 17; use 20 for safety margin +static constexpr size_t KEY_BUFFER_SIZE = 20; + class ZephyrPreferenceBackend : public ESPPreferenceBackend { public: ZephyrPreferenceBackend(uint32_t type) { this->type_ = type; } @@ -27,7 +32,9 @@ class ZephyrPreferenceBackend : public ESPPreferenceBackend { bool load(uint8_t *data, size_t len) override { if (len != this->data.size()) { - ESP_LOGE(TAG, "size of setting key %s changed, from: %u, to: %u", get_key().c_str(), this->data.size(), len); + char key_buf[KEY_BUFFER_SIZE]; + this->format_key(key_buf, sizeof(key_buf)); + ESP_LOGE(TAG, "size of setting key %s changed, from: %u, to: %u", key_buf, this->data.size(), len); return false; } std::memcpy(data, this->data.data(), len); @@ -36,7 +43,7 @@ class ZephyrPreferenceBackend : public ESPPreferenceBackend { } uint32_t get_type() const { return this->type_; } - std::string get_key() const { return str_sprintf(ESPHOME_SETTINGS_KEY "/%" PRIx32, this->type_); } + void format_key(char *buf, size_t size) const { snprintf(buf, size, ESPHOME_SETTINGS_KEY "/%" PRIx32, this->type_); } std::vector data; @@ -85,7 +92,9 @@ class ZephyrPreferences : public ESPPreferences { } printf("type %u size %u\n", type, this->backends_.size()); auto *pref = new ZephyrPreferenceBackend(type); // NOLINT(cppcoreguidelines-owning-memory) - ESP_LOGD(TAG, "Add new setting %s.", pref->get_key().c_str()); + char key_buf[KEY_BUFFER_SIZE]; + pref->format_key(key_buf, sizeof(key_buf)); + ESP_LOGD(TAG, "Add new setting %s.", key_buf); this->backends_.push_back(pref); return ESPPreferenceObject(pref); } @@ -134,9 +143,10 @@ class ZephyrPreferences : public ESPPreferences { static int export_settings(int (*cb)(const char *name, const void *value, size_t val_len)) { for (auto *backend : static_cast(global_preferences)->backends_) { - auto name = backend->get_key(); - int err = cb(name.c_str(), backend->data.data(), backend->data.size()); - ESP_LOGD(TAG, "save in flash, name %s, len %u, err %d", name.c_str(), backend->data.size(), err); + char name[KEY_BUFFER_SIZE]; + backend->format_key(name, sizeof(name)); + int err = cb(name, backend->data.data(), backend->data.size()); + ESP_LOGD(TAG, "save in flash, name %s, len %u, err %d", name, backend->data.size(), err); } return 0; } From e40201a98db065a54dd508908244f8d6e4961b40 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:44:27 -1000 Subject: [PATCH 0210/2030] [cse7766] Use stack buffer for verbose debug logging (#13217) --- esphome/components/cse7766/cse7766.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 71fe15f0ae..4432195365 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -207,20 +207,24 @@ void CSE7766Component::parse_data_() { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE { - std::string buf = "Parsed:"; + // Buffer: 7 + 15 + 33 + 15 + 25 = 95 chars max + null, rounded to 128 for safety margin. + // Float sizes with %.4f can be up to 11 chars for large values (e.g., 999999.9999). + char buf[128]; + size_t pos = buf_append_printf(buf, sizeof(buf), 0, "Parsed:"); if (have_voltage) { - buf += str_sprintf(" V=%fV", voltage); + pos = buf_append_printf(buf, sizeof(buf), pos, " V=%.4fV", voltage); } if (have_current) { - buf += str_sprintf(" I=%fmA (~%fmA)", current * 1000.0f, calculated_current * 1000.0f); + pos = buf_append_printf(buf, sizeof(buf), pos, " I=%.4fmA (~%.4fmA)", current * 1000.0f, + calculated_current * 1000.0f); } if (have_power) { - buf += str_sprintf(" P=%fW", power); + pos = buf_append_printf(buf, sizeof(buf), pos, " P=%.4fW", power); } if (energy != 0.0f) { - buf += str_sprintf(" E=%fkWh (%u)", energy, cf_pulses); + buf_append_printf(buf, sizeof(buf), pos, " E=%.4fkWh (%u)", energy, cf_pulses); } - ESP_LOGVV(TAG, "%s", buf.c_str()); + ESP_LOGVV(TAG, "%s", buf); } #endif } From 126190d26a0570fe2f5030de85491980ee63506e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:44:41 -1000 Subject: [PATCH 0211/2030] [ezo] Replace str_sprintf with stack-based formatting (#13218) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ezo/ezo.cpp | 28 +++++++++++++++++----------- esphome/components/ezo/ezo.h | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/esphome/components/ezo/ezo.cpp b/esphome/components/ezo/ezo.cpp index 2e92c58e29..e4036021df 100644 --- a/esphome/components/ezo/ezo.cpp +++ b/esphome/components/ezo/ezo.cpp @@ -160,7 +160,7 @@ void EZOSensor::loop() { this->commands_.pop_front(); } -void EZOSensor::add_command_(const std::string &command, EzoCommandType command_type, uint16_t delay_ms) { +void EZOSensor::add_command_(const char *command, EzoCommandType command_type, uint16_t delay_ms) { std::unique_ptr ezo_command(new EzoCommand); ezo_command->command = command; ezo_command->command_type = command_type; @@ -169,13 +169,17 @@ void EZOSensor::add_command_(const std::string &command, EzoCommandType command_ } void EZOSensor::set_calibration_point_(EzoCalibrationType type, float value) { - std::string payload = str_sprintf("Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value); + // max 21: "Cal,"(4) + type(4) + ","(1) + float(11) + null; use 24 for safety + char payload[24]; + snprintf(payload, sizeof(payload), "Cal,%s,%0.2f", EZO_CALIBRATION_TYPE_STRINGS[type], value); this->add_command_(payload, EzoCommandType::EZO_CALIBRATION, 900); } void EZOSensor::set_address(uint8_t address) { if (address > 0 && address < 128) { - std::string payload = str_sprintf("I2C,%u", address); + // max 8: "I2C,"(4) + uint8(3) + null + char payload[8]; + snprintf(payload, sizeof(payload), "I2C,%u", address); this->new_address_ = address; this->add_command_(payload, EzoCommandType::EZO_I2C); } else { @@ -194,7 +198,9 @@ void EZOSensor::get_slope() { this->add_command_("Slope,?", EzoCommandType::EZO_ void EZOSensor::get_t() { this->add_command_("T,?", EzoCommandType::EZO_T); } void EZOSensor::set_t(float value) { - std::string payload = str_sprintf("T,%0.2f", value); + // max 14 bytes: "T,"(2) + float with "%0.2f" (up to 11 chars) + null(1); use 16 for alignment + char payload[16]; + snprintf(payload, sizeof(payload), "T,%0.2f", value); this->add_command_(payload, EzoCommandType::EZO_T); } @@ -215,7 +221,9 @@ void EZOSensor::set_calibration_point_high(float value) { } void EZOSensor::set_calibration_generic(float value) { - std::string payload = str_sprintf("Cal,%0.2f", value); + // exact 16 bytes: "Cal," (4) + float with "%0.2f" (up to 11 chars, e.g. "-9999999.99") + null (1) = 16 + char payload[16]; + snprintf(payload, sizeof(payload), "Cal,%0.2f", value); this->add_command_(payload, EzoCommandType::EZO_CALIBRATION, 900); } @@ -223,13 +231,11 @@ void EZOSensor::clear_calibration() { this->add_command_("Cal,clear", EzoCommand void EZOSensor::get_led_state() { this->add_command_("L,?", EzoCommandType::EZO_LED); } -void EZOSensor::set_led_state(bool on) { - std::string to_send = "L,"; - to_send += on ? "1" : "0"; - this->add_command_(to_send, EzoCommandType::EZO_LED); -} +void EZOSensor::set_led_state(bool on) { this->add_command_(on ? "L,1" : "L,0", EzoCommandType::EZO_LED); } -void EZOSensor::send_custom(const std::string &to_send) { this->add_command_(to_send, EzoCommandType::EZO_CUSTOM); } +void EZOSensor::send_custom(const std::string &to_send) { + this->add_command_(to_send.c_str(), EzoCommandType::EZO_CUSTOM); +} } // namespace ezo } // namespace esphome diff --git a/esphome/components/ezo/ezo.h b/esphome/components/ezo/ezo.h index 00dd98fc80..f1a2802cbd 100644 --- a/esphome/components/ezo/ezo.h +++ b/esphome/components/ezo/ezo.h @@ -92,7 +92,7 @@ class EZOSensor : public sensor::Sensor, public PollingComponent, public i2c::I2 std::deque> commands_; int new_address_; - void add_command_(const std::string &command, EzoCommandType command_type, uint16_t delay_ms = 300); + void add_command_(const char *command, EzoCommandType command_type, uint16_t delay_ms = 300); void set_calibration_point_(EzoCalibrationType type, float value); From f453a8d9a16adcee38cbc8c40bf13140bb50ae11 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:44:56 -1000 Subject: [PATCH 0212/2030] [dfrobot_sen0395] Reduce heap allocations in command building (#13219) --- .../components/dfrobot_sen0395/commands.cpp | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/esphome/components/dfrobot_sen0395/commands.cpp b/esphome/components/dfrobot_sen0395/commands.cpp index 8bb6ddf942..2c44c6fba9 100644 --- a/esphome/components/dfrobot_sen0395/commands.cpp +++ b/esphome/components/dfrobot_sen0395/commands.cpp @@ -127,7 +127,9 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float this->min2_ = min2 = this->max2_ = max2 = this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 = this->max4_ = max4 = -1; - this->cmd_ = str_sprintf("detRangeCfg -1 %.0f %.0f", min1 / 0.15, max1 / 0.15); + char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null + snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f", min1 / 0.15, max1 / 0.15); + this->cmd_ = buf; } else if (min3 < 0 || max3 < 0) { this->min1_ = min1 = round(min1 / 0.15) * 0.15; this->max1_ = max1 = round(max1 / 0.15) * 0.15; @@ -135,7 +137,10 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float this->max2_ = max2 = round(max2 / 0.15) * 0.15; this->min3_ = min3 = this->max3_ = max3 = this->min4_ = min4 = this->max4_ = max4 = -1; - this->cmd_ = str_sprintf("detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15); + char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null + snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15, + max2 / 0.15); + this->cmd_ = buf; } else if (min4 < 0 || max4 < 0) { this->min1_ = min1 = round(min1 / 0.15) * 0.15; this->max1_ = max1 = round(max1 / 0.15) * 0.15; @@ -145,9 +150,10 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float this->max3_ = max3 = round(max3 / 0.15) * 0.15; this->min4_ = min4 = this->max4_ = max4 = -1; - this->cmd_ = str_sprintf("detRangeCfg -1 " - "%.0f %.0f %.0f %.0f %.0f %.0f", - min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15); + char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null + snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, min2 / 0.15, + max2 / 0.15, min3 / 0.15, max3 / 0.15); + this->cmd_ = buf; } else { this->min1_ = min1 = round(min1 / 0.15) * 0.15; this->max1_ = max1 = round(max1 / 0.15) * 0.15; @@ -158,10 +164,10 @@ DetRangeCfgCommand::DetRangeCfgCommand(float min1, float max1, float min2, float this->min4_ = min4 = round(min4 / 0.15) * 0.15; this->max4_ = max4 = round(max4 / 0.15) * 0.15; - this->cmd_ = str_sprintf("detRangeCfg -1 " - "%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", - min1 / 0.15, max1 / 0.15, min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15, min4 / 0.15, - max4 / 0.15); + char buf[72]; // max 72: "detRangeCfg -1 "(15) + 8 * (float(5) + space(1)) + null + snprintf(buf, sizeof(buf), "detRangeCfg -1 %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", min1 / 0.15, max1 / 0.15, + min2 / 0.15, max2 / 0.15, min3 / 0.15, max3 / 0.15, min4 / 0.15, max4 / 0.15); + this->cmd_ = buf; } this->min1_ = min1; @@ -203,7 +209,10 @@ SetLatencyCommand::SetLatencyCommand(float delay_after_detection, float delay_af delay_after_disappear = std::round(delay_after_disappear / 0.025f) * 0.025f; this->delay_after_detection_ = clamp(delay_after_detection, 0.0f, 1638.375f); this->delay_after_disappear_ = clamp(delay_after_disappear, 0.0f, 1638.375f); - this->cmd_ = str_sprintf("setLatency %.03f %.03f", this->delay_after_detection_, this->delay_after_disappear_); + // max 32: "setLatency "(11) + float(8) + " "(1) + float(8) + null, rounded to 32 + char buf[32]; + snprintf(buf, sizeof(buf), "setLatency %.03f %.03f", this->delay_after_detection_, this->delay_after_disappear_); + this->cmd_ = buf; }; uint8_t SetLatencyCommand::on_message(std::string &message) { From e99dbe05f73a5735995366d55804198affc68fcd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:52:34 -1000 Subject: [PATCH 0213/2030] [toshiba] Replace to_string with stack buffer in debug logging (#13296) --- esphome/components/toshiba/toshiba.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/esphome/components/toshiba/toshiba.cpp b/esphome/components/toshiba/toshiba.cpp index 5efa70d6b4..7b5e78af52 100644 --- a/esphome/components/toshiba/toshiba.cpp +++ b/esphome/components/toshiba/toshiba.cpp @@ -1,5 +1,6 @@ #include "toshiba.h" #include "esphome/components/remote_base/toshiba_ac_protocol.h" +#include "esphome/core/helpers.h" #include @@ -427,10 +428,17 @@ void ToshibaClimate::setup() { // Never send nan to HA if (std::isnan(this->target_temperature)) this->target_temperature = 24; +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE // Log final state for debugging HA errors - ESP_LOGV(TAG, "Setup complete - Mode: %d, Fan: %s, Swing: %d, Temp: %.1f", static_cast(this->mode), - this->fan_mode.has_value() ? std::to_string(static_cast(this->fan_mode.value())).c_str() : "NONE", + const char *fan_mode_str = "NONE"; + char fan_mode_buf[4]; // max 3 digits for fan mode enum + null + if (this->fan_mode.has_value()) { + buf_append_printf(fan_mode_buf, sizeof(fan_mode_buf), 0, "%d", static_cast(this->fan_mode.value())); + fan_mode_str = fan_mode_buf; + } + ESP_LOGV(TAG, "Setup complete - Mode: %d, Fan: %s, Swing: %d, Temp: %.1f", static_cast(this->mode), fan_mode_str, static_cast(this->swing_mode), this->target_temperature); +#endif } void ToshibaClimate::transmit_state() { From e80a9402228907b01230d992f6248e6f590f6fa5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:52:49 -1000 Subject: [PATCH 0214/2030] [gdk101] Use stack buffer to eliminate heap allocation for firmware version (#13224) --- esphome/components/gdk101/gdk101.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/gdk101/gdk101.cpp b/esphome/components/gdk101/gdk101.cpp index 617e2138fb..ddf38f2f55 100644 --- a/esphome/components/gdk101/gdk101.cpp +++ b/esphome/components/gdk101/gdk101.cpp @@ -163,9 +163,10 @@ bool GDK101Component::read_fw_version_(uint8_t *data) { return false; } - const std::string fw_version_str = str_sprintf("%d.%d", data[0], data[1]); - - this->fw_version_text_sensor_->publish_state(fw_version_str); + // max 8: "255.255" (7 chars) + null + char buf[8]; + snprintf(buf, sizeof(buf), "%d.%d", data[0], data[1]); + this->fw_version_text_sensor_->publish_state(buf); } #endif // USE_TEXT_SENSOR return true; From d8a28f6fba5c6dba85223da3386674992680ed1a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:54:30 -1000 Subject: [PATCH 0215/2030] [scheduler] Replace resize() with erase() to save ~ 436 bytes flash (#13214) --- esphome/core/scheduler.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 8c2e349180..7de1023e6d 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -403,7 +403,9 @@ class Scheduler { for (size_t i = 0; i < remaining; i++) { this->defer_queue_[i] = std::move(this->defer_queue_[this->defer_queue_front_ + i]); } - this->defer_queue_.resize(remaining); + // Use erase() instead of resize() to avoid instantiating _M_default_append + // (saves ~156 bytes flash). Erasing from the end is O(1) - no shifting needed. + this->defer_queue_.erase(this->defer_queue_.begin() + remaining, this->defer_queue_.end()); } this->defer_queue_front_ = 0; } From 86a1b4cf694026ea77f2c37d406b55e84203b122 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 19:51:11 -1000 Subject: [PATCH 0216/2030] [select][fan] Use StringRef for on_value/on_preset_set triggers to avoid heap allocation (#13324) --- esphome/codegen.py | 1 + esphome/components/fan/__init__.py | 4 +- esphome/components/fan/automation.h | 4 +- esphome/components/select/__init__.py | 4 +- esphome/components/select/automation.h | 4 +- esphome/core/string_ref.h | 64 ++++++++ esphome/cpp_types.py | 1 + .../fixtures/select_stringref_trigger.yaml | 85 +++++++++++ .../test_select_stringref_trigger.py | 143 ++++++++++++++++++ 9 files changed, 302 insertions(+), 8 deletions(-) create mode 100644 tests/integration/fixtures/select_stringref_trigger.yaml create mode 100644 tests/integration/test_select_stringref_trigger.py diff --git a/esphome/codegen.py b/esphome/codegen.py index 6d55c6023d..4a2a5975c6 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -69,6 +69,7 @@ from esphome.cpp_types import ( # noqa: F401 JsonObjectConst, Parented, PollingComponent, + StringRef, arduino_json_ns, bool_, const_char_ptr, diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 35a351e8f1..6010aa8ed4 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -77,7 +77,7 @@ FanSpeedSetTrigger = fan_ns.class_( "FanSpeedSetTrigger", automation.Trigger.template(cg.int_) ) FanPresetSetTrigger = fan_ns.class_( - "FanPresetSetTrigger", automation.Trigger.template(cg.std_string) + "FanPresetSetTrigger", automation.Trigger.template(cg.StringRef) ) FanIsOnCondition = fan_ns.class_("FanIsOnCondition", automation.Condition.template()) @@ -287,7 +287,7 @@ async def setup_fan_core_(var, config): await automation.build_automation(trigger, [(cg.int_, "x")], conf) for conf in config.get(CONF_ON_PRESET_SET, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + await automation.build_automation(trigger, [(cg.StringRef, "x")], conf) async def register_fan(var, config): diff --git a/esphome/components/fan/automation.h b/esphome/components/fan/automation.h index 77abc2f13f..3c3b0ce519 100644 --- a/esphome/components/fan/automation.h +++ b/esphome/components/fan/automation.h @@ -208,7 +208,7 @@ class FanSpeedSetTrigger : public Trigger { int last_speed_; }; -class FanPresetSetTrigger : public Trigger { +class FanPresetSetTrigger : public Trigger { public: FanPresetSetTrigger(Fan *state) { state->add_on_state_callback([this, state]() { @@ -216,7 +216,7 @@ class FanPresetSetTrigger : public Trigger { auto should_trigger = preset_mode != this->last_preset_mode_; this->last_preset_mode_ = preset_mode; if (should_trigger) { - this->trigger(std::string(preset_mode)); + this->trigger(preset_mode); } }); this->last_preset_mode_ = state->get_preset_mode(); diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index c51131a292..84ad591ba1 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -33,7 +33,7 @@ SelectPtr = Select.operator("ptr") # Triggers SelectStateTrigger = select_ns.class_( "SelectStateTrigger", - automation.Trigger.template(cg.std_string, cg.size_t), + automation.Trigger.template(cg.StringRef, cg.size_t), ) # Actions @@ -100,7 +100,7 @@ async def setup_select_core_(var, config, *, options: list[str]): for conf in config.get(CONF_ON_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation( - trigger, [(cg.std_string, "x"), (cg.size_t, "i")], conf + trigger, [(cg.StringRef, "x"), (cg.size_t, "i")], conf ) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: diff --git a/esphome/components/select/automation.h b/esphome/components/select/automation.h index 81e8a3561d..ffdabd5f7c 100644 --- a/esphome/components/select/automation.h +++ b/esphome/components/select/automation.h @@ -6,11 +6,11 @@ namespace esphome::select { -class SelectStateTrigger : public Trigger { +class SelectStateTrigger : public Trigger { public: explicit SelectStateTrigger(Select *parent) : parent_(parent) { parent->add_on_state_callback( - [this](size_t index) { this->trigger(std::string(this->parent_->option_at(index)), index); }); + [this](size_t index) { this->trigger(StringRef(this->parent_->option_at(index)), index); }); } protected: diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index 44ca79c81b..d502c4d27f 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -72,6 +72,7 @@ class StringRef { constexpr const char *c_str() const { return base_; } constexpr size_type size() const { return len_; } + constexpr size_type length() const { return len_; } constexpr bool empty() const { return len_ == 0; } constexpr const_reference operator[](size_type pos) const { return *(base_ + pos); } @@ -80,6 +81,32 @@ class StringRef { operator std::string() const { return str(); } + /// Find first occurrence of substring, returns std::string::npos if not found. + /// Note: Requires the underlying string to be null-terminated. + size_type find(const char *s, size_type pos = 0) const { + if (pos >= len_) + return std::string::npos; + const char *result = std::strstr(base_ + pos, s); + // Verify entire match is within bounds (strstr searches to null terminator) + if (result && result + std::strlen(s) <= base_ + len_) + return static_cast(result - base_); + return std::string::npos; + } + size_type find(char c, size_type pos = 0) const { + if (pos >= len_) + return std::string::npos; + const void *result = std::memchr(base_ + pos, static_cast(c), len_ - pos); + return result ? static_cast(static_cast(result) - base_) : std::string::npos; + } + + /// Return substring as std::string + std::string substr(size_type pos = 0, size_type count = std::string::npos) const { + if (pos >= len_) + return std::string(); + size_type actual_count = (count == std::string::npos || pos + count > len_) ? len_ - pos : count; + return std::string(base_ + pos, actual_count); + } + private: const char *base_; size_type len_; @@ -160,6 +187,43 @@ inline std::string operator+(const std::string &lhs, const StringRef &rhs) { str.append(rhs.c_str(), rhs.size()); return str; } +// String conversion functions for ADL compatibility (allows stoi(x) where x is StringRef) +// Must be in esphome namespace for ADL to find them. Uses strtol/strtod directly to avoid heap allocation. +namespace internal { +// NOLINTBEGIN(google-runtime-int) +template inline R parse_number(const StringRef &str, size_t *pos, F conv) { + char *end; + R result = conv(str.c_str(), &end); + // Set pos to 0 on conversion failure (when no characters consumed), otherwise index after number + if (pos) + *pos = (end == str.c_str()) ? 0 : static_cast(end - str.c_str()); + return result; +} +template inline R parse_number(const StringRef &str, size_t *pos, int base, F conv) { + char *end; + R result = conv(str.c_str(), &end, base); + // Set pos to 0 on conversion failure (when no characters consumed), otherwise index after number + if (pos) + *pos = (end == str.c_str()) ? 0 : static_cast(end - str.c_str()); + return result; +} +// NOLINTEND(google-runtime-int) +} // namespace internal +// NOLINTBEGIN(readability-identifier-naming,google-runtime-int) +inline int stoi(const StringRef &str, size_t *pos = nullptr, int base = 10) { + return static_cast(internal::parse_number(str, pos, base, std::strtol)); +} +inline long stol(const StringRef &str, size_t *pos = nullptr, int base = 10) { + return internal::parse_number(str, pos, base, std::strtol); +} +inline float stof(const StringRef &str, size_t *pos = nullptr) { + return internal::parse_number(str, pos, std::strtof); +} +inline double stod(const StringRef &str, size_t *pos = nullptr) { + return internal::parse_number(str, pos, std::strtod); +} +// NOLINTEND(readability-identifier-naming,google-runtime-int) + #ifdef USE_JSON // NOLINTNEXTLINE(readability-identifier-naming) inline void convertToJson(const StringRef &src, JsonVariant dst) { dst.set(src.c_str()); } diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 0d1813f63b..7001c38857 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -44,3 +44,4 @@ gpio_Flags = gpio_ns.enum("Flags", is_class=True) EntityCategory = esphome_ns.enum("EntityCategory") Parented = esphome_ns.class_("Parented") ESPTime = esphome_ns.struct("ESPTime") +StringRef = esphome_ns.class_("StringRef") diff --git a/tests/integration/fixtures/select_stringref_trigger.yaml b/tests/integration/fixtures/select_stringref_trigger.yaml new file mode 100644 index 0000000000..bb1e1fd843 --- /dev/null +++ b/tests/integration/fixtures/select_stringref_trigger.yaml @@ -0,0 +1,85 @@ +esphome: + name: select-stringref-test + friendly_name: Select StringRef Test + +host: + +logger: + level: DEBUG + +api: + +select: + - platform: template + name: "Test Select" + id: test_select + optimistic: true + options: + - "Option A" + - "Option B" + - "Option C" + initial_option: "Option A" + on_value: + then: + # Test 1: Log the value directly (StringRef -> const char* via c_str()) + - logger.log: + format: "Select value: %s" + args: ['x.c_str()'] + # Test 2: String concatenation (StringRef + const char* -> std::string) + - lambda: |- + std::string with_suffix = x + " selected"; + ESP_LOGI("test", "Concatenated: %s", with_suffix.c_str()); + # Test 3: Comparison (StringRef == const char*) + - lambda: |- + if (x == "Option B") { + ESP_LOGI("test", "Option B was selected"); + } + # Test 4: Use index parameter (variable name is 'i') + - lambda: |- + ESP_LOGI("test", "Select index: %d", (int)i); + # Test 5: StringRef.length() method + - lambda: |- + ESP_LOGI("test", "Length: %d", (int)x.length()); + # Test 6: StringRef.find() method with substring + - lambda: |- + if (x.find("Option") != std::string::npos) { + ESP_LOGI("test", "Found 'Option' in value"); + } + # Test 7: StringRef.find() method with character + - lambda: |- + size_t space_pos = x.find(' '); + if (space_pos != std::string::npos) { + ESP_LOGI("test", "Space at position: %d", (int)space_pos); + } + # Test 8: StringRef.substr() method + - lambda: |- + std::string prefix = x.substr(0, 6); + ESP_LOGI("test", "Substr prefix: %s", prefix.c_str()); + + # Second select with numeric options to test ADL functions + - platform: template + name: "Baud Rate" + id: baud_select + optimistic: true + options: + - "9600" + - "115200" + initial_option: "9600" + on_value: + then: + # Test 9: stoi via ADL + - lambda: |- + int baud = stoi(x); + ESP_LOGI("test", "stoi result: %d", baud); + # Test 10: stol via ADL + - lambda: |- + long baud_long = stol(x); + ESP_LOGI("test", "stol result: %ld", baud_long); + # Test 11: stof via ADL + - lambda: |- + float baud_float = stof(x); + ESP_LOGI("test", "stof result: %.0f", baud_float); + # Test 12: stod via ADL + - lambda: |- + double baud_double = stod(x); + ESP_LOGI("test", "stod result: %.0f", baud_double); diff --git a/tests/integration/test_select_stringref_trigger.py b/tests/integration/test_select_stringref_trigger.py new file mode 100644 index 0000000000..7fc72a2290 --- /dev/null +++ b/tests/integration/test_select_stringref_trigger.py @@ -0,0 +1,143 @@ +"""Integration test for select on_value trigger with StringRef parameter.""" + +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_select_stringref_trigger( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test select on_value trigger passes StringRef that works with string operations.""" + loop = asyncio.get_running_loop() + + # Track log messages to verify StringRef operations work + value_logged_future = loop.create_future() + concatenated_future = loop.create_future() + comparison_future = loop.create_future() + index_logged_future = loop.create_future() + length_future = loop.create_future() + find_substr_future = loop.create_future() + find_char_future = loop.create_future() + substr_future = loop.create_future() + # ADL functions + stoi_future = loop.create_future() + stol_future = loop.create_future() + stof_future = loop.create_future() + stod_future = loop.create_future() + + # Patterns to match in logs + value_pattern = re.compile(r"Select value: Option B") + concatenated_pattern = re.compile(r"Concatenated: Option B selected") + comparison_pattern = re.compile(r"Option B was selected") + index_pattern = re.compile(r"Select index: 1") + length_pattern = re.compile(r"Length: 8") # "Option B" is 8 chars + find_substr_pattern = re.compile(r"Found 'Option' in value") + find_char_pattern = re.compile(r"Space at position: 6") # space at index 6 + substr_pattern = re.compile(r"Substr prefix: Option") + # ADL function patterns (115200 from baud rate select) + stoi_pattern = re.compile(r"stoi result: 115200") + stol_pattern = re.compile(r"stol result: 115200") + stof_pattern = re.compile(r"stof result: 115200") + stod_pattern = re.compile(r"stod result: 115200") + + def check_output(line: str) -> None: + """Check log output for expected messages.""" + if not value_logged_future.done() and value_pattern.search(line): + value_logged_future.set_result(True) + if not concatenated_future.done() and concatenated_pattern.search(line): + concatenated_future.set_result(True) + if not comparison_future.done() and comparison_pattern.search(line): + comparison_future.set_result(True) + if not index_logged_future.done() and index_pattern.search(line): + index_logged_future.set_result(True) + if not length_future.done() and length_pattern.search(line): + length_future.set_result(True) + if not find_substr_future.done() and find_substr_pattern.search(line): + find_substr_future.set_result(True) + if not find_char_future.done() and find_char_pattern.search(line): + find_char_future.set_result(True) + if not substr_future.done() and substr_pattern.search(line): + substr_future.set_result(True) + # ADL functions + if not stoi_future.done() and stoi_pattern.search(line): + stoi_future.set_result(True) + if not stol_future.done() and stol_pattern.search(line): + stol_future.set_result(True) + if not stof_future.done() and stof_pattern.search(line): + stof_future.set_result(True) + if not stod_future.done() and stod_pattern.search(line): + stod_future.set_result(True) + + async with ( + run_compiled(yaml_config, line_callback=check_output), + api_client_connected() as client, + ): + # Verify device info + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "select-stringref-test" + + # List entities to find our select + entities, _ = await client.list_entities_services() + + select_entity = next( + (e for e in entities if hasattr(e, "options") and e.name == "Test Select"), + None, + ) + assert select_entity is not None, "Test Select entity not found" + + baud_entity = next( + (e for e in entities if hasattr(e, "options") and e.name == "Baud Rate"), + None, + ) + assert baud_entity is not None, "Baud Rate entity not found" + + # Change select to Option B - this should trigger on_value with StringRef + client.select_command(select_entity.key, "Option B") + # Change baud to 115200 - this tests ADL functions (stoi, stol, stof, stod) + client.select_command(baud_entity.key, "115200") + + # Wait for all log messages confirming StringRef operations work + try: + await asyncio.wait_for( + asyncio.gather( + value_logged_future, + concatenated_future, + comparison_future, + index_logged_future, + length_future, + find_substr_future, + find_char_future, + substr_future, + stoi_future, + stol_future, + stof_future, + stod_future, + ), + timeout=5.0, + ) + except TimeoutError: + results = { + "value_logged": value_logged_future.done(), + "concatenated": concatenated_future.done(), + "comparison": comparison_future.done(), + "index_logged": index_logged_future.done(), + "length": length_future.done(), + "find_substr": find_substr_future.done(), + "find_char": find_char_future.done(), + "substr": substr_future.done(), + "stoi": stoi_future.done(), + "stol": stol_future.done(), + "stof": stof_future.done(), + "stod": stod_future.done(), + } + pytest.fail(f"StringRef operations failed - received: {results}") From bfcc0e26a367625df7db7165172a4f0846b39421 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 22:22:44 -1000 Subject: [PATCH 0217/2030] [dfrobot_sen0395][pipsolar][sim800l][wl_134] Replace sprintf with snprintf/buf_append_printf (#13301) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/dfrobot_sen0395/commands.h | 8 ++++---- esphome/components/pipsolar/output/pipsolar_output.cpp | 2 +- esphome/components/sim800l/sim800l.cpp | 5 +++-- esphome/components/wl_134/wl_134.cpp | 5 +++-- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/esphome/components/dfrobot_sen0395/commands.h b/esphome/components/dfrobot_sen0395/commands.h index cf3ba50be0..3b0551b184 100644 --- a/esphome/components/dfrobot_sen0395/commands.h +++ b/esphome/components/dfrobot_sen0395/commands.h @@ -75,8 +75,8 @@ class SetLatencyCommand : public Command { class SensorCfgStartCommand : public Command { public: SensorCfgStartCommand(bool startup_mode) : startup_mode_(startup_mode) { - char tmp_cmd[20] = {0}; - sprintf(tmp_cmd, "sensorCfgStart %d", startup_mode); + char tmp_cmd[20]; // "sensorCfgStart " (15) + "0/1" (1) + null = 17 + buf_append_printf(tmp_cmd, sizeof(tmp_cmd), 0, "sensorCfgStart %d", startup_mode); cmd_ = std::string(tmp_cmd); } uint8_t on_message(std::string &message) override; @@ -142,8 +142,8 @@ class SensitivityCommand : public Command { SensitivityCommand(uint8_t sensitivity) : sensitivity_(sensitivity) { if (sensitivity > 9) sensitivity_ = sensitivity = 9; - char tmp_cmd[20] = {0}; - sprintf(tmp_cmd, "setSensitivity %d", sensitivity); + char tmp_cmd[20]; // "setSensitivity " (15) + "0-9" (1) + null = 17 + buf_append_printf(tmp_cmd, sizeof(tmp_cmd), 0, "setSensitivity %d", sensitivity); cmd_ = std::string(tmp_cmd); }; uint8_t on_message(std::string &message) override; diff --git a/esphome/components/pipsolar/output/pipsolar_output.cpp b/esphome/components/pipsolar/output/pipsolar_output.cpp index ebfb9a7bbc..60f6342759 100644 --- a/esphome/components/pipsolar/output/pipsolar_output.cpp +++ b/esphome/components/pipsolar/output/pipsolar_output.cpp @@ -8,7 +8,7 @@ namespace pipsolar { static const char *const TAG = "pipsolar.output"; void PipsolarOutput::write_state(float state) { - char tmp[10]; + char tmp[16]; snprintf(tmp, sizeof(tmp), this->set_command_, state); if (std::find(this->possible_values_.begin(), this->possible_values_.end(), state) != this->possible_values_.end()) { diff --git a/esphome/components/sim800l/sim800l.cpp b/esphome/components/sim800l/sim800l.cpp index e3edda0e72..251e18648b 100644 --- a/esphome/components/sim800l/sim800l.cpp +++ b/esphome/components/sim800l/sim800l.cpp @@ -1,4 +1,5 @@ #include "sim800l.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include @@ -50,8 +51,8 @@ void Sim800LComponent::update() { } else if (state_ == STATE_RECEIVED_SMS) { // Serial Buffer should have flushed. // Send cmd to delete received sms - char delete_cmd[20]; - sprintf(delete_cmd, "AT+CMGD=%d", this->parse_index_); + char delete_cmd[20]; // "AT+CMGD=" (8) + uint8_t (max 3) + null = 12 <= 20 + buf_append_printf(delete_cmd, sizeof(delete_cmd), 0, "AT+CMGD=%d", this->parse_index_); this->send_cmd_(delete_cmd); this->state_ = STATE_CHECK_SMS; this->expect_ack_ = true; diff --git a/esphome/components/wl_134/wl_134.cpp b/esphome/components/wl_134/wl_134.cpp index 20a145d183..a589f71c84 100644 --- a/esphome/components/wl_134/wl_134.cpp +++ b/esphome/components/wl_134/wl_134.cpp @@ -1,4 +1,5 @@ #include "wl_134.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include @@ -78,8 +79,8 @@ Wl134Component::Rfid134Error Wl134Component::read_packet_() { reading.id, reading.country, reading.isData ? "true" : "false", reading.isAnimal ? "true" : "false", reading.reserved0, reading.reserved1); - char buf[20]; - sprintf(buf, "%03d%012lld", reading.country, reading.id); + char buf[20]; // "%03d" (3) + "%012" PRId64 (12) + null = 16 max + buf_append_printf(buf, sizeof(buf), 0, "%03d%012" PRId64, reading.country, reading.id); this->publish_state(buf); if (this->do_reset_) { this->set_timeout(1000, [this]() { this->publish_state(""); }); From f8bd4ef57d67127914affeff02f1da6265f50c2a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 22:22:57 -1000 Subject: [PATCH 0218/2030] [template][event] Use StringRef for set_action and on_event triggers (#13328) --- esphome/components/event/__init__.py | 4 +--- esphome/components/event/automation.h | 4 ++-- esphome/components/event/event.cpp | 4 ++-- esphome/components/event/event.h | 4 ++-- esphome/components/template/select/__init__.py | 2 +- esphome/components/template/select/template_select.cpp | 2 +- esphome/components/template/select/template_select.h | 5 +++-- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index e2b69ba872..8fac7a279c 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -90,9 +90,7 @@ async def setup_event_core_(var, config, *, event_types: list[str]): for conf in config.get(CONF_ON_EVENT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.std_string, "event_type")], conf - ) + await automation.build_automation(trigger, [(cg.StringRef, "event_type")], conf) cg.add(var.set_event_types(event_types)) diff --git a/esphome/components/event/automation.h b/esphome/components/event/automation.h index 5bdba18687..7730506c10 100644 --- a/esphome/components/event/automation.h +++ b/esphome/components/event/automation.h @@ -14,10 +14,10 @@ template class TriggerEventAction : public Action, public void play(const Ts &...x) override { this->parent_->trigger(this->event_type_.value(x...)); } }; -class EventTrigger : public Trigger { +class EventTrigger : public Trigger { public: EventTrigger(Event *event) { - event->add_on_event_callback([this](const std::string &event_type) { this->trigger(event_type); }); + event->add_on_event_callback([this](StringRef event_type) { this->trigger(event_type); }); } }; diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp index 8015f2255a..667d4218f3 100644 --- a/esphome/components/event/event.cpp +++ b/esphome/components/event/event.cpp @@ -23,7 +23,7 @@ void Event::trigger(const std::string &event_type) { } this->last_event_type_ = found; ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_); - this->event_callback_.call(event_type); + this->event_callback_.call(StringRef(found)); #if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_event(this); #endif @@ -45,7 +45,7 @@ void Event::set_event_types(const std::vector &event_types) { this->last_event_type_ = nullptr; // Reset when types change } -void Event::add_on_event_callback(std::function &&callback) { +void Event::add_on_event_callback(std::function &&callback) { this->event_callback_.add(std::move(callback)); } diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index f77ad326d9..b5519a0520 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -70,10 +70,10 @@ class Event : public EntityBase, public EntityBase_DeviceClass { /// Check if an event has been triggered. bool has_event() const { return this->last_event_type_ != nullptr; } - void add_on_event_callback(std::function &&callback); + void add_on_event_callback(std::function &&callback); protected: - LazyCallbackManager event_callback_; + LazyCallbackManager event_callback_; FixedVector types_; private: diff --git a/esphome/components/template/select/__init__.py b/esphome/components/template/select/__init__.py index 0e9c240547..574f1f5fb7 100644 --- a/esphome/components/template/select/__init__.py +++ b/esphome/components/template/select/__init__.py @@ -88,5 +88,5 @@ async def to_code(config): if CONF_SET_ACTION in config: await automation.build_automation( - var.get_set_trigger(), [(cg.std_string, "x")], config[CONF_SET_ACTION] + var.get_set_trigger(), [(cg.StringRef, "x")], config[CONF_SET_ACTION] ) diff --git a/esphome/components/template/select/template_select.cpp b/esphome/components/template/select/template_select.cpp index 9d2df0956b..818abfc1d7 100644 --- a/esphome/components/template/select/template_select.cpp +++ b/esphome/components/template/select/template_select.cpp @@ -41,7 +41,7 @@ void TemplateSelect::update() { } void TemplateSelect::control(size_t index) { - this->set_trigger_->trigger(std::string(this->option_at(index))); + this->set_trigger_->trigger(StringRef(this->option_at(index))); if (this->optimistic_) this->publish_state(index); diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 2757c51405..114d25b9ce 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -4,6 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" +#include "esphome/core/string_ref.h" #include "esphome/core/template_lambda.h" namespace esphome::template_ { @@ -17,7 +18,7 @@ class TemplateSelect final : public select::Select, public PollingComponent { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } + Trigger *get_set_trigger() const { return this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_initial_option_index(size_t initial_option_index) { this->initial_option_index_ = initial_option_index; } void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } @@ -27,7 +28,7 @@ class TemplateSelect final : public select::Select, public PollingComponent { bool optimistic_ = false; size_t initial_option_index_{0}; bool restore_value_ = false; - Trigger *set_trigger_ = new Trigger(); + Trigger *set_trigger_ = new Trigger(); TemplateLambda f_; ESPPreferenceObject pref_; From 892e9b006fa4c9fed028eeda51af08fbfa027e55 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 23:57:27 -1000 Subject: [PATCH 0219/2030] [api] Use MAX_STATE_LEN constant for Home Assistant state buffer (#13278) --- esphome/components/api/api_connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 25512de4c7..0364879ccd 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1715,7 +1715,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes // HA state max length is 255 characters, but attributes can be much longer // Use stack buffer for common case (states), heap fallback for large attributes size_t state_len = msg.state.size(); - SmallBufferWithHeapFallback<256> state_buf_alloc(state_len + 1); + SmallBufferWithHeapFallback state_buf_alloc(state_len + 1); char *state_buf = reinterpret_cast(state_buf_alloc.get()); if (state_len > 0) { memcpy(state_buf, msg.state.c_str(), state_len); From ee264d0fd444c74be13bdb683a1f49c70617762b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 23:57:42 -1000 Subject: [PATCH 0220/2030] [anova] Replace sprintf with bounds-checked alternatives (#13303) --- esphome/components/anova/anova_base.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/anova/anova_base.cpp b/esphome/components/anova/anova_base.cpp index ce4febbe37..fef4f1d852 100644 --- a/esphome/components/anova/anova_base.cpp +++ b/esphome/components/anova/anova_base.cpp @@ -18,31 +18,31 @@ AnovaPacket *AnovaCodec::clean_packet_() { AnovaPacket *AnovaCodec::get_read_device_status_request() { this->current_query_ = READ_DEVICE_STATUS; - sprintf((char *) this->packet_.data, "%s", CMD_READ_DEVICE_STATUS); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_DEVICE_STATUS); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_read_target_temp_request() { this->current_query_ = READ_TARGET_TEMPERATURE; - sprintf((char *) this->packet_.data, "%s", CMD_READ_TARGET_TEMP); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_TARGET_TEMP); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_read_current_temp_request() { this->current_query_ = READ_CURRENT_TEMPERATURE; - sprintf((char *) this->packet_.data, "%s", CMD_READ_CURRENT_TEMP); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_CURRENT_TEMP); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_read_unit_request() { this->current_query_ = READ_UNIT; - sprintf((char *) this->packet_.data, "%s", CMD_READ_UNIT); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_UNIT); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_read_data_request() { this->current_query_ = READ_DATA; - sprintf((char *) this->packet_.data, "%s", CMD_READ_DATA); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_READ_DATA); return this->clean_packet_(); } @@ -50,25 +50,25 @@ AnovaPacket *AnovaCodec::get_set_target_temp_request(float temperature) { this->current_query_ = SET_TARGET_TEMPERATURE; if (this->fahrenheit_) temperature = ctof(temperature); - sprintf((char *) this->packet_.data, CMD_SET_TARGET_TEMP, temperature); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), CMD_SET_TARGET_TEMP, temperature); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_set_unit_request(char unit) { this->current_query_ = SET_UNIT; - sprintf((char *) this->packet_.data, CMD_SET_TEMP_UNIT, unit); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), CMD_SET_TEMP_UNIT, unit); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_start_request() { this->current_query_ = START; - sprintf((char *) this->packet_.data, CMD_START); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_START); return this->clean_packet_(); } AnovaPacket *AnovaCodec::get_stop_request() { this->current_query_ = STOP; - sprintf((char *) this->packet_.data, CMD_STOP); + snprintf((char *) this->packet_.data, sizeof(this->packet_.data), "%s", CMD_STOP); return this->clean_packet_(); } From a0d3d54d69a9f76eec891dbfb125083f533f1e25 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 20 Jan 2026 05:13:36 +1100 Subject: [PATCH 0221/2030] [mipi_spi] Add variants of ESP32-2432S028 displays (#13340) --- esphome/components/mipi_spi/mipi_spi.h | 9 ++-- .../components/mipi_spi/models/adafruit.py | 2 - esphome/components/mipi_spi/models/amoled.py | 3 -- esphome/components/mipi_spi/models/cyd.py | 43 +++++++++++++++++-- esphome/components/mipi_spi/models/ili.py | 30 ++++++++++++- esphome/components/mipi_spi/models/jc.py | 2 - esphome/components/mipi_spi/models/lanbon.py | 2 - esphome/components/mipi_spi/models/lilygo.py | 2 - 8 files changed, 70 insertions(+), 23 deletions(-) diff --git a/esphome/components/mipi_spi/mipi_spi.h b/esphome/components/mipi_spi/mipi_spi.h index a59cb8104b..fd5bc97596 100644 --- a/esphome/components/mipi_spi/mipi_spi.h +++ b/esphome/components/mipi_spi/mipi_spi.h @@ -224,12 +224,9 @@ class MipiSpi : public display::Display, this->madctl_ & MADCTL_BGR ? "BGR" : "RGB", DISPLAYPIXEL * 8, IS_BIG_ENDIAN ? "Big" : "Little"); if (this->brightness_.has_value()) esph_log_config(TAG, " Brightness: %u", this->brightness_.value()); - if (this->cs_ != nullptr) - esph_log_config(TAG, " CS Pin: %s", this->cs_->dump_summary().c_str()); - if (this->reset_pin_ != nullptr) - esph_log_config(TAG, " Reset Pin: %s", this->reset_pin_->dump_summary().c_str()); - if (this->dc_pin_ != nullptr) - esph_log_config(TAG, " DC Pin: %s", this->dc_pin_->dump_summary().c_str()); + log_pin(TAG, " CS Pin: ", this->cs_); + log_pin(TAG, " Reset Pin: ", this->reset_pin_); + log_pin(TAG, " DC Pin: ", this->dc_pin_); esph_log_config(TAG, " SPI Mode: %d\n" " SPI Data rate: %dMHz\n" diff --git a/esphome/components/mipi_spi/models/adafruit.py b/esphome/components/mipi_spi/models/adafruit.py index 0e91107bee..26790b1493 100644 --- a/esphome/components/mipi_spi/models/adafruit.py +++ b/esphome/components/mipi_spi/models/adafruit.py @@ -26,5 +26,3 @@ ST7789V.extend( reset_pin=40, invert_colors=True, ) - -models = {} diff --git a/esphome/components/mipi_spi/models/amoled.py b/esphome/components/mipi_spi/models/amoled.py index 4d6c8da4b0..32cad70ac0 100644 --- a/esphome/components/mipi_spi/models/amoled.py +++ b/esphome/components/mipi_spi/models/amoled.py @@ -105,6 +105,3 @@ CO5300 = DriverChip( (WCE, 0x00), ), ) - - -models = {} diff --git a/esphome/components/mipi_spi/models/cyd.py b/esphome/components/mipi_spi/models/cyd.py index a25ecf33a8..7229412f18 100644 --- a/esphome/components/mipi_spi/models/cyd.py +++ b/esphome/components/mipi_spi/models/cyd.py @@ -1,10 +1,45 @@ -from .ili import ILI9341 +from .ili import ILI9341, ILI9342, ST7789V ILI9341.extend( + # ESP32-2432S028 CYD board with Micro USB, has ILI9341 controller "ESP32-2432S028", data_rate="40MHz", - cs_pin=15, - dc_pin=2, + cs_pin={"number": 15, "ignore_strapping_warning": True}, + dc_pin={"number": 2, "ignore_strapping_warning": True}, ) -models = {} +ST7789V.extend( + # ESP32-2432S028 CYD board with USB C + Micro USB, has ST7789V controller + "ESP32-2432S028-7789", + data_rate="40MHz", + cs_pin={"number": 15, "ignore_strapping_warning": True}, + dc_pin={"number": 2, "ignore_strapping_warning": True}, +) + +# fmt: off + +ILI9342.extend( + # ESP32-2432S028 CYD board with USB C + Micro USB, has ILI9342 controller + "ESP32-2432S028-9342", + data_rate="40MHz", + cs_pin={"number": 15, "ignore_strapping_warning": True}, + dc_pin={"number": 2, "ignore_strapping_warning": True}, + initsequence=( + (0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02), # Power Control A + (0xCF, 0x00, 0xC1, 0x30), # Power Control B + (0xE8, 0x85, 0x00, 0x78), # Driver timing control A + (0xEA, 0x00, 0x00), # Driver timing control B + (0xED, 0x64, 0x03, 0x12, 0x81), # Power on sequence control + (0xF7, 0x20), # Pump ratio control + (0xC0, 0x23), # Power Control 1 + (0xC1, 0x10), # Power Control 2 + (0xC5, 0x3E, 0x28), # VCOM Control 1 + (0xC7, 0x86), # VCOM Control 2 + (0xB1, 0x00, 0x1B), # Frame Rate Control + (0xB6, 0x0A, 0xA2, 0x27, 0x00), # Display Function Control + (0xF2, 0x00), # Enable 3G + (0x26, 0x01), # Gamma Set + (0xE0, 0x00, 0x0C, 0x11, 0x04, 0x11, 0x08, 0x37, 0x89, 0x4C, 0x06, 0x0C, 0x0A, 0x2E, 0x34, 0x0F), # Positive Gamma Correction + (0xE1, 0x00, 0x0B, 0x11, 0x05, 0x13, 0x09, 0x33, 0x67, 0x48, 0x07, 0x0E, 0x0B, 0x23, 0x33, 0x0F), # Negative Gamma Correction + ) +) diff --git a/esphome/components/mipi_spi/models/ili.py b/esphome/components/mipi_spi/models/ili.py index 60a25c32a9..6b672b0859 100644 --- a/esphome/components/mipi_spi/models/ili.py +++ b/esphome/components/mipi_spi/models/ili.py @@ -148,6 +148,34 @@ ILI9341 = DriverChip( ), ), ) + +# fmt: off + +ILI9342 = DriverChip( + "ILI9342", + width=320, + height=240, + mirror_x=True, + initsequence=( + (0xCB, 0x39, 0x2C, 0x00, 0x34, 0x02), # Power Control A + (0xCF, 0x00, 0xC1, 0x30), # Power Control B + (0xE8, 0x85, 0x00, 0x78), # Driver timing control A + (0xEA, 0x00, 0x00), # Driver timing control B + (0xED, 0x64, 0x03, 0x12, 0x81), # Power on sequence control + (0xF7, 0x20), # Pump ratio control + (0xC0, 0x23), # Power Control 1 + (0xC1, 0x10), # Power Control 2 + (0xC5, 0x3E, 0x28), # VCOM Control 1 + (0xC7, 0x86), # VCOM Control 2 + (0xB1, 0x00, 0x1B), # Frame Rate Control + (0xB6, 0x0A, 0xA2, 0x27, 0x00), # Display Function Control + (0xF2, 0x00), # Enable 3G + (0x26, 0x01), # Gamma Set + (0xE0, 0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00), # Positive Gamma + (0xE1, 0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00), # Negative Gamma + ), +) + # M5Stack Core2 uses ILI9341 chip - mirror_x disabled for correct orientation ILI9341.extend( "M5CORE2", @@ -758,5 +786,3 @@ ST7796.extend( dc_pin=0, invert_colors=True, ) - -models = {} diff --git a/esphome/components/mipi_spi/models/jc.py b/esphome/components/mipi_spi/models/jc.py index 5b936fd956..854814f572 100644 --- a/esphome/components/mipi_spi/models/jc.py +++ b/esphome/components/mipi_spi/models/jc.py @@ -588,5 +588,3 @@ DriverChip( (0x29, 0x00), ), ) - -models = {} diff --git a/esphome/components/mipi_spi/models/lanbon.py b/esphome/components/mipi_spi/models/lanbon.py index 6f9aa58674..8cec3c8317 100644 --- a/esphome/components/mipi_spi/models/lanbon.py +++ b/esphome/components/mipi_spi/models/lanbon.py @@ -11,5 +11,3 @@ ST7789V.extend( dc_pin=21, reset_pin=18, ) - -models = {} diff --git a/esphome/components/mipi_spi/models/lilygo.py b/esphome/components/mipi_spi/models/lilygo.py index 13ddc67465..46ec809029 100644 --- a/esphome/components/mipi_spi/models/lilygo.py +++ b/esphome/components/mipi_spi/models/lilygo.py @@ -56,5 +56,3 @@ ST7796.extend( backlight_pin=48, invert_colors=True, ) - -models = {} From 1996bc425f27de225d2b9baf7b394c07ed3ac657 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 19 Jan 2026 14:46:24 -0500 Subject: [PATCH 0222/2030] [core] Fix state leakage and module caching when processing multiple configurations (#13368) Co-authored-by: Claude Opus 4.5 --- esphome/__main__.py | 112 ++++++++++++++++++++++------------ tests/unit_tests/test_main.py | 66 +++++++++++++++++++- 2 files changed, 139 insertions(+), 39 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 545464be10..09d2855eb1 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1,5 +1,6 @@ # PYTHON_ARGCOMPLETE_OK import argparse +from collections.abc import Callable from datetime import datetime import functools import getpass @@ -936,11 +937,21 @@ def command_dashboard(args: ArgsProtocol) -> int | None: return dashboard.start_dashboard(args) -def command_update_all(args: ArgsProtocol) -> int | None: +def run_multiple_configs( + files: list, command_builder: Callable[[str], list[str]] +) -> int: + """Run a command for each configuration file in a subprocess. + + Args: + files: List of configuration files to process. + command_builder: Callable that takes a file path and returns a command list. + + Returns: + Number of failed files. + """ import click success = {} - files = list_yaml_files(args.configuration) twidth = 60 def print_bar(middle_text): @@ -950,17 +961,19 @@ def command_update_all(args: ArgsProtocol) -> int | None: safe_print(f"{half_line}{middle_text}{half_line}") for f in files: - safe_print(f"Updating {color(AnsiFore.CYAN, str(f))}") + f_path = Path(f) if not isinstance(f, Path) else f + + if any(f_path.name == x for x in SECRETS_FILES): + _LOGGER.warning("Skipping secrets file %s", f_path) + continue + + safe_print(f"Processing {color(AnsiFore.CYAN, str(f))}") safe_print("-" * twidth) safe_print() - if CORE.dashboard: - rc = run_external_process( - "esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA" - ) - else: - rc = run_external_process( - "esphome", "run", f, "--no-logs", "--device", "OTA" - ) + + cmd = command_builder(f) + rc = run_external_process(*cmd) + if rc == 0: print_bar(f"[{color(AnsiFore.BOLD_GREEN, 'SUCCESS')}] {str(f)}") success[f] = True @@ -975,6 +988,8 @@ def command_update_all(args: ArgsProtocol) -> int | None: print_bar(f"[{color(AnsiFore.BOLD_WHITE, 'SUMMARY')}]") failed = 0 for f in files: + if f not in success: + continue # Skipped file if success[f]: safe_print(f" - {str(f)}: {color(AnsiFore.GREEN, 'SUCCESS')}") else: @@ -983,6 +998,17 @@ def command_update_all(args: ArgsProtocol) -> int | None: return failed +def command_update_all(args: ArgsProtocol) -> int | None: + files = list_yaml_files(args.configuration) + + def build_command(f): + if CORE.dashboard: + return ["esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA"] + return ["esphome", "run", f, "--no-logs", "--device", "OTA"] + + return run_multiple_configs(files, build_command) + + def command_idedata(args: ArgsProtocol, config: ConfigType) -> int: import json @@ -1533,38 +1559,48 @@ def run_esphome(argv): _LOGGER.info("ESPHome %s", const.__version__) - for conf_path in args.configuration: - conf_path = Path(conf_path) - if any(conf_path.name == x for x in SECRETS_FILES): - _LOGGER.warning("Skipping secrets file %s", conf_path) - continue + # Multiple configurations: use subprocesses to avoid state leakage + # between compilations (e.g., LVGL touchscreen state in module globals) + if len(args.configuration) > 1: + # Build command by reusing argv, replacing all configs with single file + # argv[0] is the program path, skip it since we prefix with "esphome" + def build_command(f): + return ( + ["esphome"] + + [arg for arg in argv[1:] if arg not in args.configuration] + + [str(f)] + ) - CORE.config_path = conf_path - CORE.dashboard = args.dashboard + return run_multiple_configs(args.configuration, build_command) - # For logs command, skip updating external components - skip_external = args.command == "logs" - config = read_config( - dict(args.substitution) if args.substitution else {}, - skip_external_update=skip_external, - ) - if config is None: - return 2 - CORE.config = config + # Single configuration + conf_path = Path(args.configuration[0]) + if any(conf_path.name == x for x in SECRETS_FILES): + _LOGGER.warning("Skipping secrets file %s", conf_path) + return 0 - if args.command not in POST_CONFIG_ACTIONS: - safe_print(f"Unknown command {args.command}") + CORE.config_path = conf_path + CORE.dashboard = args.dashboard - try: - rc = POST_CONFIG_ACTIONS[args.command](args, config) - except EsphomeError as e: - _LOGGER.error(e, exc_info=args.verbose) - return 1 - if rc != 0: - return rc + # For logs command, skip updating external components + skip_external = args.command == "logs" + config = read_config( + dict(args.substitution) if args.substitution else {}, + skip_external_update=skip_external, + ) + if config is None: + return 2 + CORE.config = config - CORE.reset() - return 0 + if args.command not in POST_CONFIG_ACTIONS: + safe_print(f"Unknown command {args.command}") + return 1 + + try: + return POST_CONFIG_ACTIONS[args.command](args, config) + except EsphomeError as e: + _LOGGER.error(e, exc_info=args.verbose) + return 1 def main(): diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index fd8f04ded5..3268f7ee87 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -34,6 +34,7 @@ from esphome.__main__ import ( has_non_ip_address, has_resolvable_address, mqtt_get_ip, + run_esphome, run_miniterm, show_logs, upload_program, @@ -1988,7 +1989,7 @@ esp32: clean_output = strip_ansi_codes(captured.out) assert "test-device_123.yaml" in clean_output - assert "Updating" in clean_output + assert "Processing" in clean_output assert "SUCCESS" in clean_output assert "SUMMARY" in clean_output @@ -3172,3 +3173,66 @@ def test_run_miniterm_buffer_limit_prevents_unbounded_growth() -> None: x_count = printed_line.count("X") assert x_count < 150, f"Expected truncation but got {x_count} X's" assert x_count == 95, f"Expected 95 X's after truncation but got {x_count}" + + +def test_run_esphome_multiple_configs_with_secrets( + tmp_path: Path, + mock_run_external_process: Mock, + capfd: CaptureFixture[str], + caplog: pytest.LogCaptureFixture, +) -> None: + """Test run_esphome with multiple configs and secrets file. + + Verifies: + - Multiple configs use subprocess isolation + - Secrets files are skipped with warning + - Secrets files don't appear in summary + """ + # Create two config files and a secrets file + yaml_file1 = tmp_path / "device1.yaml" + yaml_file1.write_text(""" +esphome: + name: device1 + +esp32: + board: nodemcu-32s +""") + yaml_file2 = tmp_path / "device2.yaml" + yaml_file2.write_text(""" +esphome: + name: device2 + +esp32: + board: nodemcu-32s +""") + secrets_file = tmp_path / "secrets.yaml" + secrets_file.write_text("wifi_password: secret123\n") + + setup_core(tmp_path=tmp_path) + mock_run_external_process.return_value = 0 + + # run_esphome expects argv[0] to be the program name (gets sliced off by parse_args) + with caplog.at_level(logging.WARNING): + result = run_esphome( + ["esphome", "compile", str(yaml_file1), str(secrets_file), str(yaml_file2)] + ) + + assert result == 0 + + # Check secrets file was skipped with warning + assert "Skipping secrets file" in caplog.text + assert "secrets.yaml" in caplog.text + + captured = capfd.readouterr() + clean_output = strip_ansi_codes(captured.out) + + # Both config files should be processed + assert "device1.yaml" in clean_output + assert "device2.yaml" in clean_output + assert "SUMMARY" in clean_output + + # Secrets should not appear in summary + summary_section = ( + clean_output.split("SUMMARY")[1] if "SUMMARY" in clean_output else "" + ) + assert "secrets.yaml" not in summary_section From 0193464f92e90f765242b6ce0837f009ee611cdb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:34:49 -1000 Subject: [PATCH 0223/2030] [dsmr] Avoid std::string allocation for decryption key (#13375) --- esphome/components/dsmr/__init__.py | 22 +++------------------- esphome/components/dsmr/dsmr.cpp | 19 +++++++------------ esphome/components/dsmr/dsmr.h | 2 +- esphome/config_validation.py | 8 ++++---- 4 files changed, 15 insertions(+), 36 deletions(-) diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index 0ba68daf5d..386da3ce21 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -25,29 +25,13 @@ dsmr_ns = cg.esphome_ns.namespace("esphome::dsmr") Dsmr = dsmr_ns.class_("Dsmr", cg.Component, uart.UARTDevice) -def _validate_key(value): - value = cv.string_strict(value) - parts = [value[i : i + 2] for i in range(0, len(value), 2)] - if len(parts) != 16: - raise cv.Invalid("Decryption key must consist of 16 hexadecimal numbers") - parts_int = [] - if any(len(part) != 2 for part in parts): - raise cv.Invalid("Decryption key must be format XX") - for part in parts: - try: - parts_int.append(int(part, 16)) - except ValueError: - # pylint: disable=raise-missing-from - raise cv.Invalid("Decryption key must be hex values from 00 to FF") - - return "".join(f"{part:02X}" for part in parts_int) - - CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(Dsmr), - cv.Optional(CONF_DECRYPTION_KEY): _validate_key, + cv.Optional(CONF_DECRYPTION_KEY): lambda value: cv.bind_key( + value, name="Decryption key" + ), cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean, cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, cv.Optional(CONF_WATER_MBUS_ID, default=2): cv.int_, diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index 5c62aa93ab..c78d37bf5e 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -1,4 +1,5 @@ #include "dsmr.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include @@ -294,8 +295,8 @@ void Dsmr::dump_config() { DSMR_TEXT_SENSOR_LIST(DSMR_LOG_TEXT_SENSOR, ) } -void Dsmr::set_decryption_key(const std::string &decryption_key) { - if (decryption_key.empty()) { +void Dsmr::set_decryption_key(const char *decryption_key) { + if (decryption_key == nullptr || decryption_key[0] == '\0') { ESP_LOGI(TAG, "Disabling decryption"); this->decryption_key_.clear(); if (this->crypt_telegram_ != nullptr) { @@ -305,21 +306,15 @@ void Dsmr::set_decryption_key(const std::string &decryption_key) { return; } - if (decryption_key.length() != 32) { - ESP_LOGE(TAG, "Error, decryption key must be 32 character long"); + if (!parse_hex(decryption_key, this->decryption_key_, 16)) { + ESP_LOGE(TAG, "Error, decryption key must be 32 hex characters"); + this->decryption_key_.clear(); return; } - this->decryption_key_.clear(); ESP_LOGI(TAG, "Decryption key is set"); // Verbose level prints decryption key - ESP_LOGV(TAG, "Using decryption key: %s", decryption_key.c_str()); - - char temp[3] = {0}; - for (int i = 0; i < 16; i++) { - strncpy(temp, &(decryption_key.c_str()[i * 2]), 2); - this->decryption_key_.push_back(std::strtoul(temp, nullptr, 16)); - } + ESP_LOGV(TAG, "Using decryption key: %s", decryption_key); if (this->crypt_telegram_ == nullptr) { this->crypt_telegram_ = new uint8_t[this->max_telegram_len_]; // NOLINT diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index 56ba75b5fa..b7e05a22b3 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -63,7 +63,7 @@ class Dsmr : public Component, public uart::UARTDevice { void dump_config() override; - void set_decryption_key(const std::string &decryption_key); + void set_decryption_key(const char *decryption_key); void set_max_telegram_length(size_t length) { this->max_telegram_len_ = length; } void set_request_pin(GPIOPin *request_pin) { this->request_pin_ = request_pin; } void set_request_interval(uint32_t interval) { this->request_interval_ = interval; } diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 8e2fadbea8..b7ab02013d 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1046,20 +1046,20 @@ def mac_address(value): return core.MACAddress(*parts_int) -def bind_key(value): +def bind_key(value, *, name="Bind key"): value = string_strict(value) parts = [value[i : i + 2] for i in range(0, len(value), 2)] if len(parts) != 16: - raise Invalid("Bind key must consist of 16 hexadecimal numbers") + raise Invalid(f"{name} must consist of 16 hexadecimal numbers") parts_int = [] if any(len(part) != 2 for part in parts): - raise Invalid("Bind key must be format XX") + raise Invalid(f"{name} must be format XX") for part in parts: try: parts_int.append(int(part, 16)) except ValueError: # pylint: disable=raise-missing-from - raise Invalid("Bind key must be hex values from 00 to FF") + raise Invalid(f"{name} must be hex values from 00 to FF") return "".join(f"{part:02X}" for part in parts_int) From 8ec31dd7693028d1e987d39b67708c04133ebc66 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:35:19 -1000 Subject: [PATCH 0224/2030] [voice_assistant] Deprecate Timer::to_string() in favor of heap-free to_str() (#13377) --- esphome/components/voice_assistant/voice_assistant.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index b1b3df7bbd..d61a8fbbc1 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -81,6 +81,8 @@ struct Timer { this->id.c_str(), this->name.c_str(), this->total_seconds, this->seconds_left, YESNO(this->is_active)); return buffer.data(); } + // Remove before 2026.8.0 + ESPDEPRECATED("Use to_str() instead. Removed in 2026.8.0", "2026.2.0") std::string to_string() const { char buffer[TO_STR_BUFFER_SIZE]; return this->to_str(buffer); From 8998ef0bc309ec1ed5f97dc8ab372a6c5007f332 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:35:32 -1000 Subject: [PATCH 0225/2030] [network] Deprecate IPAddress::str() in favor of heap-free str_to() (#13378) --- esphome/components/network/ip_address.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index 3dfcf0cb64..d0ac8164af 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -60,6 +60,8 @@ struct IPAddress { } IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); } IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; } + // Remove before 2026.8.0 + ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); @@ -147,6 +149,8 @@ struct IPAddress { bool is_ip4() const { return IP_IS_V4(&ip_addr_); } bool is_ip6() const { return IP_IS_V6(&ip_addr_); } bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); } + // Remove before 2026.8.0 + ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); From 5d787e2512aecfb7ef434a00e3cca74d51c67f4d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:35:58 -1000 Subject: [PATCH 0226/2030] [sprinkler] Eliminate std::string heap allocations (#13379) --- esphome/components/sprinkler/sprinkler.cpp | 20 +++++++++----------- esphome/components/sprinkler/sprinkler.h | 8 ++++---- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 2813b4450b..35310fa2f9 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -327,14 +327,13 @@ SprinklerValveOperator *SprinklerValveRunRequest::valve_operator() { return this SprinklerValveRunRequestOrigin SprinklerValveRunRequest::request_is_from() { return this->origin_; } -Sprinkler::Sprinkler() {} -Sprinkler::Sprinkler(const std::string &name) { - // The `name` is needed to set timers up, hence non-default constructor - // replaces `set_name()` method previously existed - this->name_ = name; +Sprinkler::Sprinkler() : Sprinkler("") {} +Sprinkler::Sprinkler(const char *name) : name_(name) { + // The `name` is stored for dump_config logging this->timer_.init(2); - this->timer_.push_back({this->name_ + "sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)}); - this->timer_.push_back({this->name_ + "vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); + // Timer names only need to be unique within this component instance + this->timer_.push_back({"sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)}); + this->timer_.push_back({"vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); } void Sprinkler::setup() { this->all_valves_off_(true); } @@ -1575,8 +1574,7 @@ const LogString *Sprinkler::state_as_str_(SprinklerState state) { void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { if (this->timer_duration_(timer_index) > 0) { - // FixedVector ensures timer_ can't be resized, so .c_str() pointers remain valid - this->set_timeout(this->timer_[timer_index].name.c_str(), this->timer_duration_(timer_index), + this->set_timeout(this->timer_[timer_index].name, this->timer_duration_(timer_index), this->timer_cbf_(timer_index)); this->timer_[timer_index].start_time = millis(); this->timer_[timer_index].active = true; @@ -1587,7 +1585,7 @@ void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { bool Sprinkler::cancel_timer_(const SprinklerTimerIndex timer_index) { this->timer_[timer_index].active = false; - return this->cancel_timeout(this->timer_[timer_index].name.c_str()); + return this->cancel_timeout(this->timer_[timer_index].name); } bool Sprinkler::timer_active_(const SprinklerTimerIndex timer_index) { return this->timer_[timer_index].active; } @@ -1618,7 +1616,7 @@ void Sprinkler::sm_timer_callback_() { } void Sprinkler::dump_config() { - ESP_LOGCONFIG(TAG, "Sprinkler Controller -- %s", this->name_.c_str()); + ESP_LOGCONFIG(TAG, "Sprinkler Controller -- %s", this->name_); if (this->manual_selection_delay_.has_value()) { ESP_LOGCONFIG(TAG, " Manual Selection Delay: %" PRIu32 " seconds", this->manual_selection_delay_.value_or(0)); } diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index 273c0e9208..04efa28031 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -11,7 +11,7 @@ namespace esphome::sprinkler { -const std::string MIN_STR = "min"; +inline constexpr const char *MIN_STR = "min"; enum SprinklerState : uint8_t { // NOTE: these states are used by both SprinklerValveOperator and Sprinkler (the controller)! @@ -49,7 +49,7 @@ struct SprinklerQueueItem { }; struct SprinklerTimer { - const std::string name; + const char *name; bool active; uint32_t time; uint32_t start_time; @@ -176,7 +176,7 @@ class SprinklerValveRunRequest { class Sprinkler : public Component { public: Sprinkler(); - Sprinkler(const std::string &name); + Sprinkler(const char *name); void setup() override; void loop() override; void dump_config() override; @@ -504,7 +504,7 @@ class Sprinkler : public Component { uint32_t start_delay_{0}; uint32_t stop_delay_{0}; - std::string name_; + const char *name_{""}; /// Sprinkler controller state SprinklerState state_{IDLE}; From b5fe271d6bc9cc069d31e2c8706594c2b819eb09 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:36:47 -1000 Subject: [PATCH 0227/2030] [sprinkler] Disable loops when idle to reduce CPU overhead (#13381) --- esphome/components/sprinkler/sprinkler.cpp | 36 +++++++++++++++------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 35310fa2f9..369ee5e6ff 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -43,13 +43,11 @@ SprinklerControllerSwitch::SprinklerControllerSwitch() : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {} void SprinklerControllerSwitch::loop() { - if (!this->f_.has_value()) - return; + // Loop is only enabled when f_ has a value (see setup()) auto s = (*this->f_)(); - if (!s.has_value()) - return; - - this->publish_state(*s); + if (s.has_value()) { + this->publish_state(*s); + } } void SprinklerControllerSwitch::write_state(bool state) { @@ -74,7 +72,13 @@ float SprinklerControllerSwitch::get_setup_priority() const { return setup_prior Trigger<> *SprinklerControllerSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; } Trigger<> *SprinklerControllerSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; } -void SprinklerControllerSwitch::setup() { this->state = this->get_initial_state_with_restore_mode().value_or(false); } +void SprinklerControllerSwitch::setup() { + this->state = this->get_initial_state_with_restore_mode().value_or(false); + // Disable loop if no state lambda is set - nothing to poll + if (!this->f_.has_value()) { + this->disable_loop(); + } +} void SprinklerControllerSwitch::dump_config() { LOG_SWITCH("", "Sprinkler Switch", this); } @@ -336,15 +340,23 @@ Sprinkler::Sprinkler(const char *name) : name_(name) { this->timer_.push_back({"vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); } -void Sprinkler::setup() { this->all_valves_off_(true); } +void Sprinkler::setup() { + this->all_valves_off_(true); + // Start with loop disabled - nothing to do when idle + this->disable_loop(); +} void Sprinkler::loop() { for (auto &vo : this->valve_op_) { vo.loop(); } - if (this->prev_req_.has_request() && this->prev_req_.has_valve_operator() && - this->prev_req_.valve_operator()->state() == IDLE) { - this->prev_req_.reset(); + if (this->prev_req_.has_request()) { + if (this->prev_req_.has_valve_operator() && this->prev_req_.valve_operator()->state() == IDLE) { + this->prev_req_.reset(); + } + } else if (this->state_ == IDLE) { + // Nothing more to do - disable loop until next activation + this->disable_loop(); } } @@ -1332,6 +1344,8 @@ void Sprinkler::start_valve_(SprinklerValveRunRequest *req) { if (!this->is_a_valid_valve(req->valve())) { return; // we can't do anything if the valve number isn't valid } + // Enable loop to monitor valve operator states + this->enable_loop(); for (auto &vo : this->valve_op_) { // find the first available SprinklerValveOperator, load it and start it up if (vo.state() == IDLE) { auto run_duration = req->run_duration() ? req->run_duration() : this->valve_run_duration_adjusted(req->valve()); From 62b6c9bf7cee3a67fab39f6dc9870d69add352dd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:37:03 -1000 Subject: [PATCH 0228/2030] [esp32_ble] Deprecate ESPBTUUID::to_string() in favor of heap-free to_str() (#13376) --- esphome/components/esp32_ble/ble_uuid.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index ae593955a4..6c8ef7bfd9 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -46,6 +46,8 @@ class ESPBTUUID { esp_bt_uuid_t get_uuid() const; + // Remove before 2026.8.0 + ESPDEPRECATED("Use to_str() instead. Removed in 2026.8.0", "2026.2.0") std::string to_string() const; const char *to_str(std::span output) const; From 4e0e7796ded16e118bb95ff63fc956850d9b3e7f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:37:19 -1000 Subject: [PATCH 0229/2030] [mqtt] Remove unnecessary defer in ESP8266 on_message callback (#13373) --- esphome/components/mqtt/mqtt_client.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 7d4050284f..f8517c4f89 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -610,18 +610,10 @@ static bool topic_match(const char *message, const char *subscription) { } void MQTTClientComponent::on_message(const std::string &topic, const std::string &payload) { -#ifdef USE_ESP8266 - // on ESP8266, this is called in lwIP/AsyncTCP task; some components do not like running - // from a different task. - this->defer([this, topic, payload]() { -#endif - for (auto &subscription : this->subscriptions_) { - if (topic_match(topic.c_str(), subscription.topic.c_str())) - subscription.callback(topic, payload); - } -#ifdef USE_ESP8266 - }); -#endif + for (auto &subscription : this->subscriptions_) { + if (topic_match(topic.c_str(), subscription.topic.c_str())) + subscription.callback(topic, payload); + } } // Setters From 8ade9dfc107b752bb5ac3cf03936f75bb85f5af6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:37:33 -1000 Subject: [PATCH 0230/2030] [shtcx] Use LogString for type to_string to save RAM on ESP8266 (#13370) --- esphome/components/shtcx/shtcx.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/shtcx/shtcx.cpp b/esphome/components/shtcx/shtcx.cpp index 933dd9bde9..aca305b88d 100644 --- a/esphome/components/shtcx/shtcx.cpp +++ b/esphome/components/shtcx/shtcx.cpp @@ -13,14 +13,14 @@ static const uint16_t SHTCX_COMMAND_READ_ID_REGISTER = 0xEFC8; static const uint16_t SHTCX_COMMAND_SOFT_RESET = 0x805D; static const uint16_t SHTCX_COMMAND_POLLING_H = 0x7866; -inline const char *to_string(SHTCXType type) { +static const LogString *shtcx_type_to_string(SHTCXType type) { switch (type) { case SHTCX_TYPE_SHTC3: - return "SHTC3"; + return LOG_STR("SHTC3"); case SHTCX_TYPE_SHTC1: - return "SHTC1"; + return LOG_STR("SHTC1"); default: - return "UNKNOWN"; + return LOG_STR("UNKNOWN"); } } @@ -52,7 +52,7 @@ void SHTCXComponent::dump_config() { ESP_LOGCONFIG(TAG, "SHTCx:\n" " Model: %s (%04x)", - to_string(this->type_), this->sensor_id_); + LOG_STR_ARG(shtcx_type_to_string(this->type_)), this->sensor_id_); LOG_I2C_DEVICE(this); if (this->is_failed()) { ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); From b48d4ab785f1deb84d59865b2a0abb9adc69a44f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:37:54 -1000 Subject: [PATCH 0231/2030] [mqtt] Reduce heap allocations in publish path (#13372) --- esphome/components/mqtt/mqtt_client.cpp | 51 ++++++++++++++++--------- esphome/components/mqtt/mqtt_client.h | 6 +++ 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index f8517c4f89..96eba37a57 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -5,6 +5,7 @@ #include #include "esphome/components/network/util.h" #include "esphome/core/application.h" +#include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/version.h" @@ -66,10 +67,13 @@ void MQTTClientComponent::setup() { "esphome/discover", [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); - std::string topic = "esphome/ping/"; - topic.append(App.get_name()); + // Format topic on stack - subscribe() copies it + // "esphome/ping/" (13) + name (ESPHOME_DEVICE_NAME_MAX_LEN) + null (1) + constexpr size_t ping_topic_buffer_size = 13 + ESPHOME_DEVICE_NAME_MAX_LEN + 1; + char ping_topic[ping_topic_buffer_size]; + buf_append_printf(ping_topic, sizeof(ping_topic), 0, "esphome/ping/%s", App.get_name().c_str()); this->subscribe( - topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); + ping_topic, [this](const std::string &topic, const std::string &payload) { this->send_device_info_(); }, 2); } if (this->enable_on_boot_) { @@ -81,8 +85,11 @@ void MQTTClientComponent::send_device_info_() { if (!this->is_connected() or !this->is_discovery_ip_enabled()) { return; } - std::string topic = "esphome/discover/"; - topic.append(App.get_name()); + // Format topic on stack to avoid heap allocation + // "esphome/discover/" (17) + name (ESPHOME_DEVICE_NAME_MAX_LEN) + null (1) + constexpr size_t topic_buffer_size = 17 + ESPHOME_DEVICE_NAME_MAX_LEN + 1; + char topic[topic_buffer_size]; + buf_append_printf(topic, sizeof(topic), 0, "esphome/discover/%s", App.get_name().c_str()); // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson this->publish_json( @@ -500,39 +507,49 @@ bool MQTTClientComponent::publish(const std::string &topic, const std::string &p bool MQTTClientComponent::publish(const std::string &topic, const char *payload, size_t payload_length, uint8_t qos, bool retain) { - return publish({.topic = topic, .payload = std::string(payload, payload_length), .qos = qos, .retain = retain}); + return this->publish(topic.c_str(), payload, payload_length, qos, retain); } bool MQTTClientComponent::publish(const MQTTMessage &message) { + return this->publish(message.topic.c_str(), message.payload.c_str(), message.payload.length(), message.qos, + message.retain); +} +bool MQTTClientComponent::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos, + bool retain) { + return this->publish_json(topic.c_str(), f, qos, retain); +} + +bool MQTTClientComponent::publish(const char *topic, const char *payload, size_t payload_length, uint8_t qos, + bool retain) { if (!this->is_connected()) { - // critical components will re-transmit their messages return false; } - bool logging_topic = this->log_message_.topic == message.topic; - bool ret = this->mqtt_backend_.publish(message); + size_t topic_len = strlen(topic); + bool logging_topic = (topic_len == this->log_message_.topic.size()) && + (memcmp(this->log_message_.topic.c_str(), topic, topic_len) == 0); + bool ret = this->mqtt_backend_.publish(topic, payload, payload_length, qos, retain); delay(0); if (!ret && !logging_topic && this->is_connected()) { delay(0); - ret = this->mqtt_backend_.publish(message); + ret = this->mqtt_backend_.publish(topic, payload, payload_length, qos, retain); delay(0); } if (!logging_topic) { if (ret) { - ESP_LOGV(TAG, "Publish(topic='%s' payload='%s' retain=%d qos=%d)", message.topic.c_str(), message.payload.c_str(), - message.retain, message.qos); + ESP_LOGV(TAG, "Publish(topic='%s' retain=%d qos=%d)", topic, retain, qos); + ESP_LOGVV(TAG, "Publish payload (len=%u): '%.*s'", payload_length, static_cast(payload_length), payload); } else { - ESP_LOGV(TAG, "Publish failed for topic='%s' (len=%u). Will retry", message.topic.c_str(), - message.payload.length()); + ESP_LOGV(TAG, "Publish failed for topic='%s' (len=%u). Will retry", topic, payload_length); this->status_momentary_warning("publish", 1000); } } return ret != 0; } -bool MQTTClientComponent::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos, - bool retain) { + +bool MQTTClientComponent::publish_json(const char *topic, const json::json_build_t &f, uint8_t qos, bool retain) { std::string message = json::build_json(f); - return this->publish(topic, message, qos, retain); + return this->publish(topic, message.c_str(), message.length(), qos, retain); } void MQTTClientComponent::enable() { diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 9e9db03b19..38bc0b4da3 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -229,6 +229,9 @@ class MQTTClientComponent : public Component bool publish(const std::string &topic, const char *payload, size_t payload_length, uint8_t qos = 0, bool retain = false); + /// Publish directly without creating MQTTMessage (avoids heap allocation for topic) + bool publish(const char *topic, const char *payload, size_t payload_length, uint8_t qos = 0, bool retain = false); + /** Construct and send a JSON MQTT message. * * @param topic The topic. @@ -237,6 +240,9 @@ class MQTTClientComponent : public Component */ bool publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos = 0, bool retain = false); + /// Publish JSON directly without heap allocation for topic + bool publish_json(const char *topic, const json::json_build_t &f, uint8_t qos = 0, bool retain = false); + /// Setup the MQTT client, registering a bunch of callbacks and attempting to connect. void setup() override; void dump_config() override; From e88093ca605411cdd5f500c90d888d9ab66428e2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:38:08 -1000 Subject: [PATCH 0232/2030] [am43][lightwaverf][rf_bridge][spi_led_strip] Replace sprintf with safe alternatives (#13302) --- esphome/components/am43/am43_base.cpp | 18 ++++++------------ esphome/components/lightwaverf/lightwaverf.cpp | 8 ++++++-- esphome/components/rf_bridge/rf_bridge.cpp | 11 ++++++----- .../components/spi_led_strip/spi_led_strip.cpp | 14 +++++++------- 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/esphome/components/am43/am43_base.cpp b/esphome/components/am43/am43_base.cpp index af474dcb79..d70e638382 100644 --- a/esphome/components/am43/am43_base.cpp +++ b/esphome/components/am43/am43_base.cpp @@ -1,21 +1,12 @@ #include "am43_base.h" +#include "esphome/core/helpers.h" #include -#include namespace esphome { namespace am43 { const uint8_t START_PACKET[5] = {0x00, 0xff, 0x00, 0x00, 0x9a}; -std::string pkt_to_hex(const uint8_t *data, uint16_t len) { - char buf[64]; - memset(buf, 0, 64); - for (int i = 0; i < len; i++) - sprintf(&buf[i * 2], "%02x", data[i]); - std::string ret = buf; - return ret; -} - Am43Packet *Am43Encoder::get_battery_level_request() { uint8_t data = 0x1; return this->encode_(0xA2, &data, 1); @@ -73,7 +64,9 @@ Am43Packet *Am43Encoder::encode_(uint8_t command, uint8_t *data, uint8_t length) memcpy(&this->packet_.data[7], data, length); this->packet_.length = length + 7; this->checksum_(); - ESP_LOGV("am43", "ENC(%d): 0x%s", packet_.length, pkt_to_hex(packet_.data, packet_.length).c_str()); + char hex_buf[format_hex_size(sizeof(this->packet_.data))]; + ESP_LOGV("am43", "ENC(%d): 0x%s", this->packet_.length, + format_hex_to(hex_buf, this->packet_.data, this->packet_.length)); return &this->packet_; } @@ -88,7 +81,8 @@ void Am43Decoder::decode(const uint8_t *data, uint16_t length) { this->has_set_state_response_ = false; this->has_position_ = false; this->has_pin_response_ = false; - ESP_LOGV("am43", "DEC(%d): 0x%s", length, pkt_to_hex(data, length).c_str()); + char hex_buf[format_hex_size(24)]; // Max expected packet size + ESP_LOGV("am43", "DEC(%d): 0x%s", length, format_hex_to(hex_buf, data, length)); if (length < 2 || data[0] != 0x9a) return; diff --git a/esphome/components/lightwaverf/lightwaverf.cpp b/esphome/components/lightwaverf/lightwaverf.cpp index 31ac1fc576..2b44195c97 100644 --- a/esphome/components/lightwaverf/lightwaverf.cpp +++ b/esphome/components/lightwaverf/lightwaverf.cpp @@ -1,3 +1,4 @@ +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #ifdef USE_ESP8266 @@ -44,13 +45,16 @@ void LightWaveRF::send_rx(const std::vector &msg, uint8_t repeats, bool } void LightWaveRF::print_msg_(uint8_t *msg, uint8_t len) { - char buffer[65]; +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG + char buffer[65]; // max 10 entries * 6 chars + null ESP_LOGD(TAG, " Received code (len:%i): ", len); + size_t pos = 0; for (int i = 0; i < len; i++) { - sprintf(&buffer[i * 6], "0x%02x, ", msg[i]); + pos = buf_append_printf(buffer, sizeof(buffer), pos, "0x%02x, ", msg[i]); } ESP_LOGD(TAG, "[%s]", buffer); +#endif } void LightWaveRF::dump_config() { diff --git a/esphome/components/rf_bridge/rf_bridge.cpp b/esphome/components/rf_bridge/rf_bridge.cpp index 52ce037dbe..8105767485 100644 --- a/esphome/components/rf_bridge/rf_bridge.cpp +++ b/esphome/components/rf_bridge/rf_bridge.cpp @@ -1,6 +1,7 @@ #include "rf_bridge.h" -#include "esphome/core/log.h" #include "esphome/core/application.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" #include #include @@ -72,9 +73,9 @@ bool RFBridgeComponent::parse_bridge_byte_(uint8_t byte) { data.length = raw[2]; data.protocol = raw[3]; - char next_byte[3]; + char next_byte[3]; // 2 hex chars + null for (uint8_t i = 0; i < data.length - 1; i++) { - sprintf(next_byte, "%02X", raw[4 + i]); + buf_append_printf(next_byte, sizeof(next_byte), 0, "%02X", raw[4 + i]); data.code += next_byte; } @@ -90,10 +91,10 @@ bool RFBridgeComponent::parse_bridge_byte_(uint8_t byte) { uint8_t buckets = raw[2] << 1; std::string str; - char next_byte[3]; + char next_byte[3]; // 2 hex chars + null for (uint32_t i = 0; i <= at; i++) { - sprintf(next_byte, "%02X", raw[i]); + buf_append_printf(next_byte, sizeof(next_byte), 0, "%02X", raw[i]); str += next_byte; if ((i > 3) && buckets) { buckets--; diff --git a/esphome/components/spi_led_strip/spi_led_strip.cpp b/esphome/components/spi_led_strip/spi_led_strip.cpp index afb51afe3a..ff8d2e6ee0 100644 --- a/esphome/components/spi_led_strip/spi_led_strip.cpp +++ b/esphome/components/spi_led_strip/spi_led_strip.cpp @@ -1,4 +1,5 @@ #include "spi_led_strip.h" +#include "esphome/core/helpers.h" namespace esphome { namespace spi_led_strip { @@ -47,15 +48,14 @@ void SpiLedStrip::dump_config() { void SpiLedStrip::write_state(light::LightState *state) { if (this->is_failed()) return; - if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE) { - char strbuf[49]; - size_t len = std::min(this->buffer_size_, (size_t) (sizeof(strbuf) - 1) / 3); - memset(strbuf, 0, sizeof(strbuf)); - for (size_t i = 0; i != len; i++) { - sprintf(strbuf + i * 3, "%02X ", this->buf_[i]); - } +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + { + char strbuf[49]; // format_hex_pretty_size(16) = 48, fits 16 bytes + size_t len = std::min(this->buffer_size_, (size_t) 16); + format_hex_pretty_to(strbuf, sizeof(strbuf), this->buf_, len, ' '); esph_log_v(TAG, "write_state: buf = %s", strbuf); } +#endif this->enable(); this->write_array(this->buf_, this->buffer_size_); this->disable(); From 5d7b38b26164940883c2d45715d20b85cb7de874 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:38:22 -1000 Subject: [PATCH 0233/2030] [ezo_pmp] Replace sprintf with bounds-checked snprintf (#13304) --- esphome/components/ezo_pmp/ezo_pmp.cpp | 47 ++++++++++++++------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/esphome/components/ezo_pmp/ezo_pmp.cpp b/esphome/components/ezo_pmp/ezo_pmp.cpp index 61b601328a..9d2f4fc687 100644 --- a/esphome/components/ezo_pmp/ezo_pmp.cpp +++ b/esphome/components/ezo_pmp/ezo_pmp.cpp @@ -318,90 +318,93 @@ void EzoPMP::send_next_command_() { switch (this->next_command_) { // Read Commands case EZO_PMP_COMMAND_READ_DOSING: // Page 54 - command_buffer_length = sprintf((char *) command_buffer, "D,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "D,?"); break; case EZO_PMP_COMMAND_READ_SINGLE_REPORT: // Single Report (page 53) - command_buffer_length = sprintf((char *) command_buffer, "R"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "R"); break; case EZO_PMP_COMMAND_READ_MAX_FLOW_RATE: - command_buffer_length = sprintf((char *) command_buffer, "DC,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "DC,?"); break; case EZO_PMP_COMMAND_READ_PAUSE_STATUS: - command_buffer_length = sprintf((char *) command_buffer, "P,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "P,?"); break; case EZO_PMP_COMMAND_READ_TOTAL_VOLUME_DOSED: - command_buffer_length = sprintf((char *) command_buffer, "TV,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "TV,?"); break; case EZO_PMP_COMMAND_READ_ABSOLUTE_TOTAL_VOLUME_DOSED: - command_buffer_length = sprintf((char *) command_buffer, "ATV,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "ATV,?"); break; case EZO_PMP_COMMAND_READ_CALIBRATION_STATUS: - command_buffer_length = sprintf((char *) command_buffer, "Cal,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "Cal,?"); break; case EZO_PMP_COMMAND_READ_PUMP_VOLTAGE: - command_buffer_length = sprintf((char *) command_buffer, "PV,?"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "PV,?"); break; // Non-Read Commands case EZO_PMP_COMMAND_FIND: // Find (page 52) - command_buffer_length = sprintf((char *) command_buffer, "Find"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "Find"); wait_time_for_command = 60000; // This command will block all updates for a minute break; case EZO_PMP_COMMAND_DOSE_CONTINUOUSLY: // Continuous Dispensing (page 54) - command_buffer_length = sprintf((char *) command_buffer, "D,*"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "D,*"); break; case EZO_PMP_COMMAND_CLEAR_TOTAL_VOLUME_DOSED: // Clear Total Volume Dosed (page 64) - command_buffer_length = sprintf((char *) command_buffer, "Clear"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "Clear"); break; case EZO_PMP_COMMAND_CLEAR_CALIBRATION: // Clear Calibration (page 65) - command_buffer_length = sprintf((char *) command_buffer, "Cal,clear"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "Cal,clear"); break; case EZO_PMP_COMMAND_PAUSE_DOSING: // Pause (page 61) - command_buffer_length = sprintf((char *) command_buffer, "P"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "P"); break; case EZO_PMP_COMMAND_STOP_DOSING: // Stop (page 62) - command_buffer_length = sprintf((char *) command_buffer, "X"); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "X"); break; // Non-Read commands with parameters case EZO_PMP_COMMAND_DOSE_VOLUME: // Volume Dispensing (page 55) - command_buffer_length = sprintf((char *) command_buffer, "D,%0.1f", this->next_command_volume_); + command_buffer_length = + snprintf((char *) command_buffer, sizeof(command_buffer), "D,%0.1f", this->next_command_volume_); break; case EZO_PMP_COMMAND_DOSE_VOLUME_OVER_TIME: // Dose over time (page 56) - command_buffer_length = - sprintf((char *) command_buffer, "D,%0.1f,%i", this->next_command_volume_, this->next_command_duration_); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "D,%0.1f,%i", + this->next_command_volume_, this->next_command_duration_); break; case EZO_PMP_COMMAND_DOSE_WITH_CONSTANT_FLOW_RATE: // Constant Flow Rate (page 57) - command_buffer_length = - sprintf((char *) command_buffer, "DC,%0.1f,%i", this->next_command_volume_, this->next_command_duration_); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "DC,%0.1f,%i", + this->next_command_volume_, this->next_command_duration_); break; case EZO_PMP_COMMAND_SET_CALIBRATION_VOLUME: // Set Calibration Volume (page 65) - command_buffer_length = sprintf((char *) command_buffer, "Cal,%0.2f", this->next_command_volume_); + command_buffer_length = + snprintf((char *) command_buffer, sizeof(command_buffer), "Cal,%0.2f", this->next_command_volume_); break; case EZO_PMP_COMMAND_CHANGE_I2C_ADDRESS: // Change I2C Address (page 73) - command_buffer_length = sprintf((char *) command_buffer, "I2C,%i", this->next_command_duration_); + command_buffer_length = + snprintf((char *) command_buffer, sizeof(command_buffer), "I2C,%i", this->next_command_duration_); break; case EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS: // Run an arbitrary command - command_buffer_length = sprintf((char *) command_buffer, this->arbitrary_command_, this->next_command_duration_); + command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "%s", this->arbitrary_command_); ESP_LOGI(TAG, "Sending arbitrary command: %s", (char *) command_buffer); break; From ea70faf642e12f6d6cab14b70cee6861bda1cdc0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:38:56 -1000 Subject: [PATCH 0234/2030] [debug] Use shared buf_append_printf helper from core (#13260) --- esphome/components/debug/debug_component.cpp | 2 +- esphome/components/debug/debug_component.h | 41 +------------------- esphome/components/debug/debug_esp32.cpp | 30 +++++++------- esphome/components/debug/debug_esp8266.cpp | 22 +++++------ esphome/components/debug/debug_libretiny.cpp | 12 +++--- esphome/components/debug/debug_rp2040.cpp | 2 +- esphome/components/debug/debug_zephyr.cpp | 20 +++++----- 7 files changed, 45 insertions(+), 84 deletions(-) diff --git a/esphome/components/debug/debug_component.cpp b/esphome/components/debug/debug_component.cpp index ae38fb2ccd..15f68c3a3b 100644 --- a/esphome/components/debug/debug_component.cpp +++ b/esphome/components/debug/debug_component.cpp @@ -30,7 +30,7 @@ void DebugComponent::dump_config() { char device_info_buffer[DEVICE_INFO_BUFFER_SIZE]; ESP_LOGD(TAG, "ESPHome version %s", ESPHOME_VERSION); - size_t pos = buf_append(device_info_buffer, DEVICE_INFO_BUFFER_SIZE, 0, "%s", ESPHOME_VERSION); + size_t pos = buf_append_printf(device_info_buffer, DEVICE_INFO_BUFFER_SIZE, 0, "%s", ESPHOME_VERSION); this->free_heap_ = get_free_heap_(); ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_); diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index 6cf52d890c..e4f4bb36eb 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -5,12 +5,6 @@ #include "esphome/core/helpers.h" #include "esphome/core/macros.h" #include -#include -#include -#include -#ifdef USE_ESP8266 -#include -#endif #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" @@ -25,40 +19,7 @@ namespace debug { static constexpr size_t DEVICE_INFO_BUFFER_SIZE = 256; static constexpr size_t RESET_REASON_BUFFER_SIZE = 128; -#ifdef USE_ESP8266 -// ESP8266: Use vsnprintf_P to keep format strings in flash (PROGMEM) -// Format strings must be wrapped with PSTR() macro -inline size_t buf_append_p(char *buf, size_t size, size_t pos, PGM_P fmt, ...) { - if (pos >= size) { - return size; - } - va_list args; - va_start(args, fmt); - int written = vsnprintf_P(buf + pos, size - pos, fmt, args); - va_end(args); - if (written < 0) { - return pos; // encoding error - } - return std::min(pos + static_cast(written), size); -} -#define buf_append(buf, size, pos, fmt, ...) buf_append_p(buf, size, pos, PSTR(fmt), ##__VA_ARGS__) -#else -/// Safely append formatted string to buffer, returning new position (capped at size) -__attribute__((format(printf, 4, 5))) inline size_t buf_append(char *buf, size_t size, size_t pos, const char *fmt, - ...) { - if (pos >= size) { - return size; - } - va_list args; - va_start(args, fmt); - int written = vsnprintf(buf + pos, size - pos, fmt, args); - va_end(args); - if (written < 0) { - return pos; // encoding error - } - return std::min(pos + static_cast(written), size); -} -#endif +// buf_append_printf is now provided by esphome/core/helpers.h class DebugComponent : public PollingComponent { public: diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 8c41011f7d..aad4c7426c 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -173,8 +173,8 @@ size_t DebugComponent::get_device_info_(std::span uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode); - pos = buf_append(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, - flash_mode); + pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, + flash_mode); #endif esp_chip_info_t info; @@ -182,52 +182,52 @@ size_t DebugComponent::get_device_info_(std::span const char *model = ESPHOME_VARIANT; // Build features string - pos = buf_append(buf, size, pos, "|Chip: %s Features:", model); + pos = buf_append_printf(buf, size, pos, "|Chip: %s Features:", model); bool first_feature = true; for (const auto &feature : CHIP_FEATURES) { if (info.features & feature.bit) { - pos = buf_append(buf, size, pos, "%s%s", first_feature ? "" : ", ", feature.name); + pos = buf_append_printf(buf, size, pos, "%s%s", first_feature ? "" : ", ", feature.name); first_feature = false; info.features &= ~feature.bit; } } if (info.features != 0) { - pos = buf_append(buf, size, pos, "%sOther:0x%" PRIx32, first_feature ? "" : ", ", info.features); + pos = buf_append_printf(buf, size, pos, "%sOther:0x%" PRIx32, first_feature ? "" : ", ", info.features); } ESP_LOGD(TAG, "Chip: Model=%s, Cores=%u, Revision=%u", model, info.cores, info.revision); - pos = buf_append(buf, size, pos, " Cores:%u Revision:%u", info.cores, info.revision); + pos = buf_append_printf(buf, size, pos, " Cores:%u Revision:%u", info.cores, info.revision); uint32_t cpu_freq_mhz = arch_get_cpu_freq_hz() / 1000000; ESP_LOGD(TAG, "CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); - pos = buf_append(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); + pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); // Framework detection #ifdef USE_ARDUINO ESP_LOGD(TAG, "Framework: Arduino"); - pos = buf_append(buf, size, pos, "|Framework: Arduino"); + pos = buf_append_printf(buf, size, pos, "|Framework: Arduino"); #elif defined(USE_ESP32) ESP_LOGD(TAG, "Framework: ESP-IDF"); - pos = buf_append(buf, size, pos, "|Framework: ESP-IDF"); + pos = buf_append_printf(buf, size, pos, "|Framework: ESP-IDF"); #else ESP_LOGW(TAG, "Framework: UNKNOWN"); - pos = buf_append(buf, size, pos, "|Framework: UNKNOWN"); + pos = buf_append_printf(buf, size, pos, "|Framework: UNKNOWN"); #endif ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version()); - pos = buf_append(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version()); + pos = buf_append_printf(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version()); uint8_t mac[6]; get_mac_address_raw(mac); ESP_LOGD(TAG, "EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - pos = buf_append(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], - mac[5]); + pos = buf_append_printf(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5]); char reason_buffer[RESET_REASON_BUFFER_SIZE]; const char *reset_reason = get_reset_reason_(std::span(reason_buffer)); - pos = buf_append(buf, size, pos, "|Reset: %s", reset_reason); + pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason); const char *wakeup_cause = get_wakeup_cause_(std::span(reason_buffer)); - pos = buf_append(buf, size, pos, "|Wakeup: %s", wakeup_cause); + pos = buf_append_printf(buf, size, pos, "|Wakeup: %s", wakeup_cause); return pos; } diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 274f77e20d..19f15d7d98 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -53,8 +53,8 @@ size_t DebugComponent::get_device_info_(std::span uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode); - pos = buf_append(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, - flash_mode); + pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, + flash_mode); #if !defined(CLANG_TIDY) char reason_buffer[RESET_REASON_BUFFER_SIZE]; @@ -77,15 +77,15 @@ size_t DebugComponent::get_device_info_(std::span chip_id, ESP.getSdkVersion(), ESP.getCoreVersion().c_str(), boot_version, boot_mode, cpu_freq, flash_chip_id, reset_reason, ESP.getResetInfo().c_str()); - pos = buf_append(buf, size, pos, "|Chip: 0x%08" PRIX32, chip_id); - pos = buf_append(buf, size, pos, "|SDK: %s", ESP.getSdkVersion()); - pos = buf_append(buf, size, pos, "|Core: %s", ESP.getCoreVersion().c_str()); - pos = buf_append(buf, size, pos, "|Boot: %u", boot_version); - pos = buf_append(buf, size, pos, "|Mode: %u", boot_mode); - pos = buf_append(buf, size, pos, "|CPU: %u", cpu_freq); - pos = buf_append(buf, size, pos, "|Flash: 0x%08" PRIX32, flash_chip_id); - pos = buf_append(buf, size, pos, "|Reset: %s", reset_reason); - pos = buf_append(buf, size, pos, "|%s", ESP.getResetInfo().c_str()); + pos = buf_append_printf(buf, size, pos, "|Chip: 0x%08" PRIX32, chip_id); + pos = buf_append_printf(buf, size, pos, "|SDK: %s", ESP.getSdkVersion()); + pos = buf_append_printf(buf, size, pos, "|Core: %s", ESP.getCoreVersion().c_str()); + pos = buf_append_printf(buf, size, pos, "|Boot: %u", boot_version); + pos = buf_append_printf(buf, size, pos, "|Mode: %u", boot_mode); + pos = buf_append_printf(buf, size, pos, "|CPU: %u", cpu_freq); + pos = buf_append_printf(buf, size, pos, "|Flash: 0x%08" PRIX32, flash_chip_id); + pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason); + pos = buf_append_printf(buf, size, pos, "|%s", ESP.getResetInfo().c_str()); #endif return pos; diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index aae27c8ca2..14bbdb945a 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -36,12 +36,12 @@ size_t DebugComponent::get_device_info_(std::span lt_get_version(), lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz(), mac_id, lt_get_board_code(), flash_kib, ram_kib, reset_reason); - pos = buf_append(buf, size, pos, "|Version: %s", LT_BANNER_STR + 10); - pos = buf_append(buf, size, pos, "|Reset Reason: %s", reset_reason); - pos = buf_append(buf, size, pos, "|Chip Name: %s", lt_cpu_get_model_name()); - pos = buf_append(buf, size, pos, "|Chip ID: 0x%06" PRIX32, mac_id); - pos = buf_append(buf, size, pos, "|Flash: %" PRIu32 " KiB", flash_kib); - pos = buf_append(buf, size, pos, "|RAM: %" PRIu32 " KiB", ram_kib); + pos = buf_append_printf(buf, size, pos, "|Version: %s", LT_BANNER_STR + 10); + pos = buf_append_printf(buf, size, pos, "|Reset Reason: %s", reset_reason); + pos = buf_append_printf(buf, size, pos, "|Chip Name: %s", lt_cpu_get_model_name()); + pos = buf_append_printf(buf, size, pos, "|Chip ID: 0x%06" PRIX32, mac_id); + pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 " KiB", flash_kib); + pos = buf_append_printf(buf, size, pos, "|RAM: %" PRIu32 " KiB", ram_kib); return pos; } diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index a426a73bc2..c9d41942db 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -19,7 +19,7 @@ size_t DebugComponent::get_device_info_(std::span uint32_t cpu_freq = rp2040.f_cpu(); ESP_LOGD(TAG, "CPU Frequency: %" PRIu32, cpu_freq); - pos = buf_append(buf, size, pos, "|CPU Frequency: %" PRIu32, cpu_freq); + pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32, cpu_freq); return pos; } diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index 3f9af03b2b..6a88522b0d 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -20,9 +20,9 @@ static size_t append_reset_reason(char *buf, size_t size, size_t pos, bool set, return pos; } if (pos > 0) { - pos = buf_append(buf, size, pos, ", "); + pos = buf_append_printf(buf, size, pos, ", "); } - return buf_append(buf, size, pos, "%s", reason); + return buf_append_printf(buf, size, pos, "%s", reason); } static inline uint32_t read_mem_u32(uintptr_t addr) { @@ -140,7 +140,7 @@ size_t DebugComponent::get_device_info_(std::span const char *supply_status = (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) ? "Normal voltage." : "High voltage."; ESP_LOGD(TAG, "Main supply status: %s", supply_status); - pos = buf_append(buf, size, pos, "|Main supply status: %s", supply_status); + pos = buf_append_printf(buf, size, pos, "|Main supply status: %s", supply_status); // Regulator stage 0 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) { @@ -172,16 +172,16 @@ size_t DebugComponent::get_device_info_(std::span reg0_voltage = "???V"; } ESP_LOGD(TAG, "Regulator stage 0: %s, %s", reg0_type, reg0_voltage); - pos = buf_append(buf, size, pos, "|Regulator stage 0: %s, %s", reg0_type, reg0_voltage); + pos = buf_append_printf(buf, size, pos, "|Regulator stage 0: %s, %s", reg0_type, reg0_voltage); } else { ESP_LOGD(TAG, "Regulator stage 0: disabled"); - pos = buf_append(buf, size, pos, "|Regulator stage 0: disabled"); + pos = buf_append_printf(buf, size, pos, "|Regulator stage 0: disabled"); } // Regulator stage 1 const char *reg1_type = nrf_power_dcdcen_get(NRF_POWER) ? "DC/DC" : "LDO"; ESP_LOGD(TAG, "Regulator stage 1: %s", reg1_type); - pos = buf_append(buf, size, pos, "|Regulator stage 1: %s", reg1_type); + pos = buf_append_printf(buf, size, pos, "|Regulator stage 1: %s", reg1_type); // USB power state const char *usb_state; @@ -195,7 +195,7 @@ size_t DebugComponent::get_device_info_(std::span usb_state = "disconnected"; } ESP_LOGD(TAG, "USB power state: %s", usb_state); - pos = buf_append(buf, size, pos, "|USB power state: %s", usb_state); + pos = buf_append_printf(buf, size, pos, "|USB power state: %s", usb_state); // Power-fail comparator bool enabled; @@ -300,14 +300,14 @@ size_t DebugComponent::get_device_info_(std::span break; } ESP_LOGD(TAG, "Power-fail comparator: %s, VDDH: %s", pof_voltage, vddh_voltage); - pos = buf_append(buf, size, pos, "|Power-fail comparator: %s, VDDH: %s", pof_voltage, vddh_voltage); + pos = buf_append_printf(buf, size, pos, "|Power-fail comparator: %s, VDDH: %s", pof_voltage, vddh_voltage); } else { ESP_LOGD(TAG, "Power-fail comparator: %s", pof_voltage); - pos = buf_append(buf, size, pos, "|Power-fail comparator: %s", pof_voltage); + pos = buf_append_printf(buf, size, pos, "|Power-fail comparator: %s", pof_voltage); } } else { ESP_LOGD(TAG, "Power-fail comparator: disabled"); - pos = buf_append(buf, size, pos, "|Power-fail comparator: disabled"); + pos = buf_append_printf(buf, size, pos, "|Power-fail comparator: disabled"); } auto package = [](uint32_t value) { From 280d46002535de0ae2b88678ef6e804aa7959cb1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:40:20 -1000 Subject: [PATCH 0235/2030] [statsd] Use direct appends and stack buffer instead of str_sprintf (#13223) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/statsd/statsd.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/esphome/components/statsd/statsd.cpp b/esphome/components/statsd/statsd.cpp index 7729f36858..7d773bc56e 100644 --- a/esphome/components/statsd/statsd.cpp +++ b/esphome/components/statsd/statsd.cpp @@ -114,14 +114,22 @@ void StatsdComponent::update() { // This implies you can't explicitly set a gauge to a negative number without first setting it to zero. if (val < 0) { if (this->prefix_) { - out.append(str_sprintf("%s.", this->prefix_)); + out.append(this->prefix_); + out.append("."); } - out.append(str_sprintf("%s:0|g\n", s.name)); + out.append(s.name); + out.append(":0|g\n"); } if (this->prefix_) { - out.append(str_sprintf("%s.", this->prefix_)); + out.append(this->prefix_); + out.append("."); } - out.append(str_sprintf("%s:%f|g\n", s.name, val)); + out.append(s.name); + // Buffer for ":" + value + "|g\n". + // %f with -DBL_MAX can produce up to 321 chars, plus ":" and "|g\n" (4) + null = 326 + char val_buf[330]; + buf_append_printf(val_buf, sizeof(val_buf), 0, ":%f|g\n", val); + out.append(val_buf); if (out.length() > SEND_THRESHOLD) { this->send_(&out); From d0e50ed03078f10755bef8c032c20752c8c661f0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:40:51 -1000 Subject: [PATCH 0236/2030] [lock] Extract set_state_ helper to reduce code duplication (#13359) --- esphome/components/lock/lock.cpp | 12 +++++------- esphome/components/lock/lock.h | 3 +++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index aca6ec10f3..9fa1ba3600 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -28,16 +28,14 @@ const LogString *lock_state_to_string(LockState state) { Lock::Lock() : state(LOCK_STATE_NONE) {} LockCall Lock::make_call() { return LockCall(this); } -void Lock::lock() { +void Lock::set_state_(LockState state) { auto call = this->make_call(); - call.set_state(LOCK_STATE_LOCKED); - this->control(call); -} -void Lock::unlock() { - auto call = this->make_call(); - call.set_state(LOCK_STATE_UNLOCKED); + call.set_state(state); this->control(call); } + +void Lock::lock() { this->set_state_(LOCK_STATE_LOCKED); } +void Lock::unlock() { this->set_state_(LOCK_STATE_UNLOCKED); } void Lock::open() { if (traits.get_supports_open()) { ESP_LOGD(TAG, "'%s' Opening.", this->get_name().c_str()); diff --git a/esphome/components/lock/lock.h b/esphome/components/lock/lock.h index f77b11b145..b518c8b846 100644 --- a/esphome/components/lock/lock.h +++ b/esphome/components/lock/lock.h @@ -156,6 +156,9 @@ class Lock : public EntityBase { protected: friend LockCall; + /// Helper for lock/unlock convenience methods + void set_state_(LockState state); + /** Perform the open latch action with hardware. This method is optional to implement * when creating a new lock. * From aeea340bc66109def4cb346ede88bd23b98f856a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:41:03 -1000 Subject: [PATCH 0237/2030] [cs5460a] Remove unnecessary empty loop override (#13357) --- esphome/components/cs5460a/cs5460a.h | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/cs5460a/cs5460a.h b/esphome/components/cs5460a/cs5460a.h index 11b13f5851..99c3017510 100644 --- a/esphome/components/cs5460a/cs5460a.h +++ b/esphome/components/cs5460a/cs5460a.h @@ -76,7 +76,6 @@ class CS5460AComponent : public Component, void restart() { restart_(); } void setup() override; - void loop() override {} void dump_config() override; protected: From 6cf320fd608c73bb24c580100894a5bf25c24d8c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:41:55 -1000 Subject: [PATCH 0238/2030] [mqtt] Eliminate per-entity loop overhead and heap churn (#13356) --- esphome/components/mqtt/mqtt_client.cpp | 6 ++++++ esphome/components/mqtt/mqtt_component.cpp | 12 ++++-------- esphome/components/mqtt/mqtt_component.h | 5 +++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 96eba37a57..de79b61358 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -403,6 +403,12 @@ void MQTTClientComponent::loop() { this->last_connected_ = now; this->resubscribe_subscriptions_(); + + // Process pending resends for all MQTT components centrally + // This is more efficient than each component polling in its own loop + for (MQTTComponent *component : this->children_) { + component->process_resend(); + } } break; } diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 3b9290259b..2ba466af3b 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -308,16 +308,12 @@ void MQTTComponent::call_setup() { } } -void MQTTComponent::call_loop() { - if (this->is_internal()) +void MQTTComponent::process_resend() { + // Called by MQTTClientComponent when connected to process pending resends + // Note: is_internal() check not needed - internal components are never registered + if (!this->resend_state_) return; - this->loop(); - - if (!this->resend_state_ || !this->is_connected_()) { - return; - } - this->resend_state_ = false; if (this->is_discovery_enabled()) { if (!this->send_discovery_()) { diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 676e3ad35d..dea91e3d5a 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -81,8 +81,6 @@ class MQTTComponent : public Component { /// Override setup_ so that we can call send_discovery() when needed. void call_setup() override; - void call_loop() override; - void call_dump_config() override; /// Send discovery info the Home Assistant, override this. @@ -133,6 +131,9 @@ class MQTTComponent : public Component { /// Internal method for the MQTT client base to schedule a resend of the state on reconnect. void schedule_resend_state(); + /// Process pending resend if needed (called by MQTTClientComponent) + void process_resend(); + /** Send a MQTT message. * * @param topic The topic. From c213de4861762cf3474e4fad8ec2ce3c37440c67 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Jan 2026 17:42:08 -1000 Subject: [PATCH 0239/2030] [mapping] Use stack buffers for numeric key error logging (#13299) --- esphome/components/mapping/mapping.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/mapping/mapping.h b/esphome/components/mapping/mapping.h index 99c1f38829..2b8f0d39b2 100644 --- a/esphome/components/mapping/mapping.h +++ b/esphome/components/mapping/mapping.h @@ -2,6 +2,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include #include #include @@ -43,8 +44,17 @@ template class Mapping { esph_log_e(TAG, "Key '%p' not found in mapping", key); } else if constexpr (std::is_same_v) { esph_log_e(TAG, "Key '%s' not found in mapping", key.c_str()); + } else if constexpr (std::is_integral_v) { + char buf[24]; // enough for 64-bit integer + if constexpr (std::is_unsigned_v) { + buf_append_printf(buf, sizeof(buf), 0, "%" PRIu64, static_cast(key)); + } else { + buf_append_printf(buf, sizeof(buf), 0, "%" PRId64, static_cast(key)); + } + esph_log_e(TAG, "Key '%s' not found in mapping", buf); } else { - esph_log_e(TAG, "Key '%s' not found in mapping", to_string(key).c_str()); + // All supported key types are handled above - this should never be reached + static_assert(sizeof(K) == 0, "Unsupported key type for Mapping error logging"); } return {}; } From ed4ebffa74233328c36418f854e662845bf9f911 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 19 Jan 2026 22:57:54 -0500 Subject: [PATCH 0240/2030] [x9c] Fix potentiometer unable to decrement (#13382) Co-authored-by: Claude Opus 4.5 --- esphome/components/x9c/x9c.cpp | 8 ++++---- esphome/components/x9c/x9c.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/x9c/x9c.cpp b/esphome/components/x9c/x9c.cpp index 8f66c46015..773e52d6e1 100644 --- a/esphome/components/x9c/x9c.cpp +++ b/esphome/components/x9c/x9c.cpp @@ -6,7 +6,7 @@ namespace x9c { static const char *const TAG = "x9c.output"; -void X9cOutput::trim_value(int change_amount) { +void X9cOutput::trim_value(int32_t change_amount) { if (change_amount == 0) { return; } @@ -47,17 +47,17 @@ void X9cOutput::setup() { if (this->initial_value_ <= 0.50) { this->trim_value(-101); // Set min value (beyond 0) - this->trim_value(static_cast(roundf(this->initial_value_ * 100))); + this->trim_value(lroundf(this->initial_value_ * 100)); } else { this->trim_value(101); // Set max value (beyond 100) - this->trim_value(static_cast(roundf(this->initial_value_ * 100) - 100)); + this->trim_value(lroundf(this->initial_value_ * 100) - 100); } this->pot_value_ = this->initial_value_; this->write_state(this->initial_value_); } void X9cOutput::write_state(float state) { - this->trim_value(static_cast(roundf((state - this->pot_value_) * 100))); + this->trim_value(lroundf((state - this->pot_value_) * 100)); this->pot_value_ = state; } diff --git a/esphome/components/x9c/x9c.h b/esphome/components/x9c/x9c.h index e7cc29a6cc..66c3df14e1 100644 --- a/esphome/components/x9c/x9c.h +++ b/esphome/components/x9c/x9c.h @@ -18,7 +18,7 @@ class X9cOutput : public output::FloatOutput, public Component { void setup() override; void dump_config() override; - void trim_value(int change_amount); + void trim_value(int32_t change_amount); protected: void write_state(float state) override; From e2319ba6515c16a672b5f4b04bc9d8a997bf7e73 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 07:55:59 -1000 Subject: [PATCH 0241/2030] [wifi_info] Fix missing state when both IP+DNS or SSID+BSSID configure (#13385) --- esphome/components/wifi_info/text_sensor.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 9ecb5b7490..5f72d0aa74 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -79,13 +79,17 @@ async def setup_conf(config, key): async def to_code(config): # Request specific WiFi listeners based on which sensors are configured + # Each sensor needs its own listener slot - call request for EACH sensor + # SSID and BSSID use WiFiConnectStateListener - if CONF_SSID in config or CONF_BSSID in config: - wifi.request_wifi_connect_state_listener() + for key in (CONF_SSID, CONF_BSSID): + if key in config: + wifi.request_wifi_connect_state_listener() # IP address and DNS use WiFiIPStateListener - if CONF_IP_ADDRESS in config or CONF_DNS_ADDRESS in config: - wifi.request_wifi_ip_state_listener() + for key in (CONF_IP_ADDRESS, CONF_DNS_ADDRESS): + if key in config: + wifi.request_wifi_ip_state_listener() # Scan results use WiFiScanResultsListener if CONF_SCAN_RESULTS in config: From 79ccacd6d6e402243af91c3ef253759c272bf6ce Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 21 Jan 2026 06:24:42 +1100 Subject: [PATCH 0242/2030] [helpers] Allow reading capacity of FixedVector (#13391) --- esphome/core/helpers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index bd3a4def05..7de952a712 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -348,6 +348,8 @@ template class FixedVector { size_t size() const { return size_; } bool empty() const { return size_ == 0; } + size_t capacity() const { return capacity_; } + bool full() const { return size_ == capacity_; } /// Access element without bounds checking (matches std::vector behavior) /// Caller must ensure index is valid (i < size()) From 85a5a26519f9ee8477acbedc9c8f285a7f0d6154 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 17 Jan 2026 18:06:54 -1000 Subject: [PATCH 0243/2030] [network] Fix IPAddress::str_to() to lowercase IPv6 hex digits (#13325) --- esphome/components/network/ip_address.h | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index b719d1a70e..3dfcf0cb64 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -43,6 +43,14 @@ namespace network { /// Buffer size for IP address string (IPv6 max: 39 chars + null) static constexpr size_t IP_ADDRESS_BUFFER_SIZE = 40; +/// Lowercase hex digits in IP address string (A-F -> a-f for IPv6 per RFC 5952) +inline void lowercase_ip_str(char *buf) { + for (char *p = buf; *p; ++p) { + if (*p >= 'A' && *p <= 'F') + *p += 32; + } +} + struct IPAddress { public: #ifdef USE_HOST @@ -52,10 +60,15 @@ struct IPAddress { } IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); } IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; } - std::string str() const { return str_lower_case(inet_ntoa(ip_addr_)); } + std::string str() const { + char buf[IP_ADDRESS_BUFFER_SIZE]; + this->str_to(buf); + return buf; + } /// Write IP address to buffer. Buffer must be at least IP_ADDRESS_BUFFER_SIZE bytes. char *str_to(char *buf) const { - return const_cast(inet_ntop(AF_INET, &ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE)); + inet_ntop(AF_INET, &ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); + return buf; // IPv4 only, no hex letters to lowercase } #else IPAddress() { ip_addr_set_zero(&ip_addr_); } @@ -134,9 +147,18 @@ struct IPAddress { bool is_ip4() const { return IP_IS_V4(&ip_addr_); } bool is_ip6() const { return IP_IS_V6(&ip_addr_); } bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); } - std::string str() const { return str_lower_case(ipaddr_ntoa(&ip_addr_)); } + std::string str() const { + char buf[IP_ADDRESS_BUFFER_SIZE]; + this->str_to(buf); + return buf; + } /// Write IP address to buffer. Buffer must be at least IP_ADDRESS_BUFFER_SIZE bytes. - char *str_to(char *buf) const { return ipaddr_ntoa_r(&ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); } + /// Output is lowercased per RFC 5952 (IPv6 hex digits a-f). + char *str_to(char *buf) const { + ipaddr_ntoa_r(&ip_addr_, buf, IP_ADDRESS_BUFFER_SIZE); + lowercase_ip_str(buf); + return buf; + } bool operator==(const IPAddress &other) const { return ip_addr_cmp(&ip_addr_, &other.ip_addr_); } bool operator!=(const IPAddress &other) const { return !ip_addr_cmp(&ip_addr_, &other.ip_addr_); } IPAddress &operator+=(uint8_t increase) { From 21886dd3ac0ab96b525d9ebb71589764cedec4e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 18 Jan 2026 18:23:11 -1000 Subject: [PATCH 0244/2030] [api] Fix truncation of Home Assistant attributes longer than 255 characters (#13348) --- esphome/components/api/api_connection.cpp | 19 ++++++------ esphome/components/i2c/i2c.cpp | 8 ++--- esphome/components/i2c/i2c_bus.h | 24 +++------------ esphome/core/helpers.h | 29 +++++++++++++++++++ .../fixtures/api_homeassistant.yaml | 19 ++++++++++++ tests/integration/test_api_homeassistant.py | 27 +++++++++++++++-- 6 files changed, 90 insertions(+), 36 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 0804985cc5..25512de4c7 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1712,17 +1712,16 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes } // Create null-terminated state for callback (parse_number needs null-termination) - // HA state max length is 255, so 256 byte buffer covers all cases - char state_buf[256]; - size_t copy_len = msg.state.size(); - if (copy_len >= sizeof(state_buf)) { - copy_len = sizeof(state_buf) - 1; // Truncate to leave space for null terminator + // HA state max length is 255 characters, but attributes can be much longer + // Use stack buffer for common case (states), heap fallback for large attributes + size_t state_len = msg.state.size(); + SmallBufferWithHeapFallback<256> state_buf_alloc(state_len + 1); + char *state_buf = reinterpret_cast(state_buf_alloc.get()); + if (state_len > 0) { + memcpy(state_buf, msg.state.c_str(), state_len); } - if (copy_len > 0) { - memcpy(state_buf, msg.state.c_str(), copy_len); - } - state_buf[copy_len] = '\0'; - it.callback(StringRef(state_buf, copy_len)); + state_buf[state_len] = '\0'; + it.callback(StringRef(state_buf, state_len)); } } #endif diff --git a/esphome/components/i2c/i2c.cpp b/esphome/components/i2c/i2c.cpp index f8c7a1b40b..c1e7336ce4 100644 --- a/esphome/components/i2c/i2c.cpp +++ b/esphome/components/i2c/i2c.cpp @@ -42,8 +42,8 @@ ErrorCode I2CDevice::read_register16(uint16_t a_register, uint8_t *data, size_t } ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, size_t len) const { - SmallBufferWithHeapFallback<17> buffer_alloc; // Most I2C writes are <= 16 bytes - uint8_t *buffer = buffer_alloc.get(len + 1); + SmallBufferWithHeapFallback<17> buffer_alloc(len + 1); // Most I2C writes are <= 16 bytes + uint8_t *buffer = buffer_alloc.get(); buffer[0] = a_register; std::copy(data, data + len, buffer + 1); @@ -51,8 +51,8 @@ ErrorCode I2CDevice::write_register(uint8_t a_register, const uint8_t *data, siz } ErrorCode I2CDevice::write_register16(uint16_t a_register, const uint8_t *data, size_t len) const { - SmallBufferWithHeapFallback<18> buffer_alloc; // Most I2C writes are <= 16 bytes + 2 for register - uint8_t *buffer = buffer_alloc.get(len + 2); + SmallBufferWithHeapFallback<18> buffer_alloc(len + 2); // Most I2C writes are <= 16 bytes + 2 for register + uint8_t *buffer = buffer_alloc.get(); buffer[0] = a_register >> 8; buffer[1] = a_register; diff --git a/esphome/components/i2c/i2c_bus.h b/esphome/components/i2c/i2c_bus.h index 1acbe506a3..3de5d5ca7b 100644 --- a/esphome/components/i2c/i2c_bus.h +++ b/esphome/components/i2c/i2c_bus.h @@ -11,22 +11,6 @@ namespace esphome { namespace i2c { -/// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large -template class SmallBufferWithHeapFallback { - public: - uint8_t *get(size_t size) { - if (size <= STACK_SIZE) { - return this->stack_buffer_; - } - this->heap_buffer_ = std::unique_ptr(new uint8_t[size]); - return this->heap_buffer_.get(); - } - - private: - uint8_t stack_buffer_[STACK_SIZE]; - std::unique_ptr heap_buffer_; -}; - /// @brief Error codes returned by I2CBus and I2CDevice methods enum ErrorCode { NO_ERROR = 0, ///< No error found during execution of method @@ -92,8 +76,8 @@ class I2CBus { total_len += read_buffers[i].len; } - SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C reads are small - uint8_t *buffer = buffer_alloc.get(total_len); + SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C reads are small + uint8_t *buffer = buffer_alloc.get(); auto err = this->write_readv(address, nullptr, 0, buffer, total_len); if (err != ERROR_OK) @@ -116,8 +100,8 @@ class I2CBus { total_len += write_buffers[i].len; } - SmallBufferWithHeapFallback<128> buffer_alloc; // Most I2C writes are small - uint8_t *buffer = buffer_alloc.get(total_len); + SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C writes are small + uint8_t *buffer = buffer_alloc.get(); size_t pos = 0; for (size_t i = 0; i != count; i++) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 2e9c0e6b13..536260773b 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -362,6 +362,35 @@ template class FixedVector { const T *end() const { return data_ + size_; } }; +/// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large +/// This is useful when most operations need a small buffer but occasionally need larger ones. +/// The stack buffer avoids heap allocation in the common case, while heap fallback handles edge cases. +template class SmallBufferWithHeapFallback { + public: + explicit SmallBufferWithHeapFallback(size_t size) { + if (size <= STACK_SIZE) { + this->buffer_ = this->stack_buffer_; + } else { + this->heap_buffer_ = new uint8_t[size]; + this->buffer_ = this->heap_buffer_; + } + } + ~SmallBufferWithHeapFallback() { delete[] this->heap_buffer_; } + + // Delete copy and move operations to prevent double-delete + SmallBufferWithHeapFallback(const SmallBufferWithHeapFallback &) = delete; + SmallBufferWithHeapFallback &operator=(const SmallBufferWithHeapFallback &) = delete; + SmallBufferWithHeapFallback(SmallBufferWithHeapFallback &&) = delete; + SmallBufferWithHeapFallback &operator=(SmallBufferWithHeapFallback &&) = delete; + + uint8_t *get() { return this->buffer_; } + + private: + uint8_t stack_buffer_[STACK_SIZE]; + uint8_t *heap_buffer_{nullptr}; + uint8_t *buffer_; +}; + ///@} /// @name Mathematics diff --git a/tests/integration/fixtures/api_homeassistant.yaml b/tests/integration/fixtures/api_homeassistant.yaml index 8fe23b9a19..2d77821ff3 100644 --- a/tests/integration/fixtures/api_homeassistant.yaml +++ b/tests/integration/fixtures/api_homeassistant.yaml @@ -108,6 +108,25 @@ text_sensor: format: "HA Empty state updated: %s" args: ['x.c_str()'] + # Test long attribute handling (>255 characters) + # HA states are limited to 255 chars, but attributes are not + - platform: homeassistant + name: "HA Long Attribute" + entity_id: sensor.long_data + attribute: long_value + id: ha_long_attribute + on_value: + then: + - logger.log: + format: "HA Long attribute received, length: %d" + args: ['x.size()'] + # Log the first 50 and last 50 chars to verify no truncation + - lambda: |- + if (x.size() >= 100) { + ESP_LOGI("test", "Long attribute first 50 chars: %.50s", x.c_str()); + ESP_LOGI("test", "Long attribute last 50 chars: %s", x.c_str() + x.size() - 50); + } + # Number component for testing HA number control number: - platform: template diff --git a/tests/integration/test_api_homeassistant.py b/tests/integration/test_api_homeassistant.py index 3fe0dfe045..b4adedf873 100644 --- a/tests/integration/test_api_homeassistant.py +++ b/tests/integration/test_api_homeassistant.py @@ -40,6 +40,7 @@ async def test_api_homeassistant( humidity_update_future = loop.create_future() motion_update_future = loop.create_future() weather_update_future = loop.create_future() + long_attr_future = loop.create_future() # Number future ha_number_future = loop.create_future() @@ -58,6 +59,7 @@ async def test_api_homeassistant( humidity_update_pattern = re.compile(r"HA Humidity state updated: ([\d.]+)") motion_update_pattern = re.compile(r"HA Motion state changed: (ON|OFF)") weather_update_pattern = re.compile(r"HA Weather condition updated: (\w+)") + long_attr_pattern = re.compile(r"HA Long attribute received, length: (\d+)") # Number pattern ha_number_pattern = re.compile(r"Setting HA number to: ([\d.]+)") @@ -143,8 +145,14 @@ async def test_api_homeassistant( elif not weather_update_future.done() and weather_update_pattern.search(line): weather_update_future.set_result(line) - # Check number pattern - elif not ha_number_future.done() and ha_number_pattern.search(line): + # Check long attribute pattern - separate if since it can come at different times + if not long_attr_future.done(): + match = long_attr_pattern.search(line) + if match: + long_attr_future.set_result(int(match.group(1))) + + # Check number pattern - separate if since it can come at different times + if not ha_number_future.done(): match = ha_number_pattern.search(line) if match: ha_number_future.set_result(match.group(1)) @@ -179,6 +187,14 @@ async def test_api_homeassistant( client.send_home_assistant_state("binary_sensor.external_motion", "", "ON") client.send_home_assistant_state("weather.home", "condition", "sunny") + # Send a long attribute (300 characters) to test that attributes aren't truncated + # HA states are limited to 255 chars, but attributes are NOT limited + # This tests the fix for the 256-byte buffer truncation bug + long_attr_value = "X" * 300 # 300 chars - enough to expose truncation bug + client.send_home_assistant_state( + "sensor.long_data", "long_value", long_attr_value + ) + # Test edge cases for zero-copy implementation safety # Empty entity_id should be silently ignored (no crash) client.send_home_assistant_state("", "", "should_be_ignored") @@ -225,6 +241,13 @@ async def test_api_homeassistant( number_value = await asyncio.wait_for(ha_number_future, timeout=5.0) assert number_value == "42.5", f"Unexpected number value: {number_value}" + # Long attribute test - verify 300 chars weren't truncated to 255 + long_attr_len = await asyncio.wait_for(long_attr_future, timeout=5.0) + assert long_attr_len == 300, ( + f"Long attribute was truncated! Expected 300 chars, got {long_attr_len}. " + "This indicates the 256-byte truncation bug." + ) + # Wait for completion await asyncio.wait_for(tests_complete_future, timeout=5.0) From 47dc5d0a1fd0994f793e892c54a901cb838bbfea Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 19 Jan 2026 14:46:24 -0500 Subject: [PATCH 0245/2030] [core] Fix state leakage and module caching when processing multiple configurations (#13368) Co-authored-by: Claude Opus 4.5 --- esphome/__main__.py | 112 ++++++++++++++++++++++------------ tests/unit_tests/test_main.py | 66 +++++++++++++++++++- 2 files changed, 139 insertions(+), 39 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 3849a585ca..6cec481abc 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1,5 +1,6 @@ # PYTHON_ARGCOMPLETE_OK import argparse +from collections.abc import Callable from datetime import datetime import functools import getpass @@ -931,11 +932,21 @@ def command_dashboard(args: ArgsProtocol) -> int | None: return dashboard.start_dashboard(args) -def command_update_all(args: ArgsProtocol) -> int | None: +def run_multiple_configs( + files: list, command_builder: Callable[[str], list[str]] +) -> int: + """Run a command for each configuration file in a subprocess. + + Args: + files: List of configuration files to process. + command_builder: Callable that takes a file path and returns a command list. + + Returns: + Number of failed files. + """ import click success = {} - files = list_yaml_files(args.configuration) twidth = 60 def print_bar(middle_text): @@ -945,17 +956,19 @@ def command_update_all(args: ArgsProtocol) -> int | None: safe_print(f"{half_line}{middle_text}{half_line}") for f in files: - safe_print(f"Updating {color(AnsiFore.CYAN, str(f))}") + f_path = Path(f) if not isinstance(f, Path) else f + + if any(f_path.name == x for x in SECRETS_FILES): + _LOGGER.warning("Skipping secrets file %s", f_path) + continue + + safe_print(f"Processing {color(AnsiFore.CYAN, str(f))}") safe_print("-" * twidth) safe_print() - if CORE.dashboard: - rc = run_external_process( - "esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA" - ) - else: - rc = run_external_process( - "esphome", "run", f, "--no-logs", "--device", "OTA" - ) + + cmd = command_builder(f) + rc = run_external_process(*cmd) + if rc == 0: print_bar(f"[{color(AnsiFore.BOLD_GREEN, 'SUCCESS')}] {str(f)}") success[f] = True @@ -970,6 +983,8 @@ def command_update_all(args: ArgsProtocol) -> int | None: print_bar(f"[{color(AnsiFore.BOLD_WHITE, 'SUMMARY')}]") failed = 0 for f in files: + if f not in success: + continue # Skipped file if success[f]: safe_print(f" - {str(f)}: {color(AnsiFore.GREEN, 'SUCCESS')}") else: @@ -978,6 +993,17 @@ def command_update_all(args: ArgsProtocol) -> int | None: return failed +def command_update_all(args: ArgsProtocol) -> int | None: + files = list_yaml_files(args.configuration) + + def build_command(f): + if CORE.dashboard: + return ["esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA"] + return ["esphome", "run", f, "--no-logs", "--device", "OTA"] + + return run_multiple_configs(files, build_command) + + def command_idedata(args: ArgsProtocol, config: ConfigType) -> int: import json @@ -1528,38 +1554,48 @@ def run_esphome(argv): _LOGGER.info("ESPHome %s", const.__version__) - for conf_path in args.configuration: - conf_path = Path(conf_path) - if any(conf_path.name == x for x in SECRETS_FILES): - _LOGGER.warning("Skipping secrets file %s", conf_path) - continue + # Multiple configurations: use subprocesses to avoid state leakage + # between compilations (e.g., LVGL touchscreen state in module globals) + if len(args.configuration) > 1: + # Build command by reusing argv, replacing all configs with single file + # argv[0] is the program path, skip it since we prefix with "esphome" + def build_command(f): + return ( + ["esphome"] + + [arg for arg in argv[1:] if arg not in args.configuration] + + [str(f)] + ) - CORE.config_path = conf_path - CORE.dashboard = args.dashboard + return run_multiple_configs(args.configuration, build_command) - # For logs command, skip updating external components - skip_external = args.command == "logs" - config = read_config( - dict(args.substitution) if args.substitution else {}, - skip_external_update=skip_external, - ) - if config is None: - return 2 - CORE.config = config + # Single configuration + conf_path = Path(args.configuration[0]) + if any(conf_path.name == x for x in SECRETS_FILES): + _LOGGER.warning("Skipping secrets file %s", conf_path) + return 0 - if args.command not in POST_CONFIG_ACTIONS: - safe_print(f"Unknown command {args.command}") + CORE.config_path = conf_path + CORE.dashboard = args.dashboard - try: - rc = POST_CONFIG_ACTIONS[args.command](args, config) - except EsphomeError as e: - _LOGGER.error(e, exc_info=args.verbose) - return 1 - if rc != 0: - return rc + # For logs command, skip updating external components + skip_external = args.command == "logs" + config = read_config( + dict(args.substitution) if args.substitution else {}, + skip_external_update=skip_external, + ) + if config is None: + return 2 + CORE.config = config - CORE.reset() - return 0 + if args.command not in POST_CONFIG_ACTIONS: + safe_print(f"Unknown command {args.command}") + return 1 + + try: + return POST_CONFIG_ACTIONS[args.command](args, config) + except EsphomeError as e: + _LOGGER.error(e, exc_info=args.verbose) + return 1 def main(): diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index fd8f04ded5..3268f7ee87 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -34,6 +34,7 @@ from esphome.__main__ import ( has_non_ip_address, has_resolvable_address, mqtt_get_ip, + run_esphome, run_miniterm, show_logs, upload_program, @@ -1988,7 +1989,7 @@ esp32: clean_output = strip_ansi_codes(captured.out) assert "test-device_123.yaml" in clean_output - assert "Updating" in clean_output + assert "Processing" in clean_output assert "SUCCESS" in clean_output assert "SUMMARY" in clean_output @@ -3172,3 +3173,66 @@ def test_run_miniterm_buffer_limit_prevents_unbounded_growth() -> None: x_count = printed_line.count("X") assert x_count < 150, f"Expected truncation but got {x_count} X's" assert x_count == 95, f"Expected 95 X's after truncation but got {x_count}" + + +def test_run_esphome_multiple_configs_with_secrets( + tmp_path: Path, + mock_run_external_process: Mock, + capfd: CaptureFixture[str], + caplog: pytest.LogCaptureFixture, +) -> None: + """Test run_esphome with multiple configs and secrets file. + + Verifies: + - Multiple configs use subprocess isolation + - Secrets files are skipped with warning + - Secrets files don't appear in summary + """ + # Create two config files and a secrets file + yaml_file1 = tmp_path / "device1.yaml" + yaml_file1.write_text(""" +esphome: + name: device1 + +esp32: + board: nodemcu-32s +""") + yaml_file2 = tmp_path / "device2.yaml" + yaml_file2.write_text(""" +esphome: + name: device2 + +esp32: + board: nodemcu-32s +""") + secrets_file = tmp_path / "secrets.yaml" + secrets_file.write_text("wifi_password: secret123\n") + + setup_core(tmp_path=tmp_path) + mock_run_external_process.return_value = 0 + + # run_esphome expects argv[0] to be the program name (gets sliced off by parse_args) + with caplog.at_level(logging.WARNING): + result = run_esphome( + ["esphome", "compile", str(yaml_file1), str(secrets_file), str(yaml_file2)] + ) + + assert result == 0 + + # Check secrets file was skipped with warning + assert "Skipping secrets file" in caplog.text + assert "secrets.yaml" in caplog.text + + captured = capfd.readouterr() + clean_output = strip_ansi_codes(captured.out) + + # Both config files should be processed + assert "device1.yaml" in clean_output + assert "device2.yaml" in clean_output + assert "SUMMARY" in clean_output + + # Secrets should not appear in summary + summary_section = ( + clean_output.split("SUMMARY")[1] if "SUMMARY" in clean_output else "" + ) + assert "secrets.yaml" not in summary_section From b89c127f6283f38c946eee1b4c9768d5482dfb1c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 19 Jan 2026 22:57:54 -0500 Subject: [PATCH 0246/2030] [x9c] Fix potentiometer unable to decrement (#13382) Co-authored-by: Claude Opus 4.5 --- esphome/components/x9c/x9c.cpp | 8 ++++---- esphome/components/x9c/x9c.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/x9c/x9c.cpp b/esphome/components/x9c/x9c.cpp index 8f66c46015..773e52d6e1 100644 --- a/esphome/components/x9c/x9c.cpp +++ b/esphome/components/x9c/x9c.cpp @@ -6,7 +6,7 @@ namespace x9c { static const char *const TAG = "x9c.output"; -void X9cOutput::trim_value(int change_amount) { +void X9cOutput::trim_value(int32_t change_amount) { if (change_amount == 0) { return; } @@ -47,17 +47,17 @@ void X9cOutput::setup() { if (this->initial_value_ <= 0.50) { this->trim_value(-101); // Set min value (beyond 0) - this->trim_value(static_cast(roundf(this->initial_value_ * 100))); + this->trim_value(lroundf(this->initial_value_ * 100)); } else { this->trim_value(101); // Set max value (beyond 100) - this->trim_value(static_cast(roundf(this->initial_value_ * 100) - 100)); + this->trim_value(lroundf(this->initial_value_ * 100) - 100); } this->pot_value_ = this->initial_value_; this->write_state(this->initial_value_); } void X9cOutput::write_state(float state) { - this->trim_value(static_cast(roundf((state - this->pot_value_) * 100))); + this->trim_value(lroundf((state - this->pot_value_) * 100)); this->pot_value_ = state; } diff --git a/esphome/components/x9c/x9c.h b/esphome/components/x9c/x9c.h index e7cc29a6cc..66c3df14e1 100644 --- a/esphome/components/x9c/x9c.h +++ b/esphome/components/x9c/x9c.h @@ -18,7 +18,7 @@ class X9cOutput : public output::FloatOutput, public Component { void setup() override; void dump_config() override; - void trim_value(int change_amount); + void trim_value(int32_t change_amount); protected: void write_state(float state) override; From b04373687e785be01933a2ad120f0d2603dd6b17 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 07:55:59 -1000 Subject: [PATCH 0247/2030] [wifi_info] Fix missing state when both IP+DNS or SSID+BSSID configure (#13385) --- esphome/components/wifi_info/text_sensor.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 9ecb5b7490..5f72d0aa74 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -79,13 +79,17 @@ async def setup_conf(config, key): async def to_code(config): # Request specific WiFi listeners based on which sensors are configured + # Each sensor needs its own listener slot - call request for EACH sensor + # SSID and BSSID use WiFiConnectStateListener - if CONF_SSID in config or CONF_BSSID in config: - wifi.request_wifi_connect_state_listener() + for key in (CONF_SSID, CONF_BSSID): + if key in config: + wifi.request_wifi_connect_state_listener() # IP address and DNS use WiFiIPStateListener - if CONF_IP_ADDRESS in config or CONF_DNS_ADDRESS in config: - wifi.request_wifi_ip_state_listener() + for key in (CONF_IP_ADDRESS, CONF_DNS_ADDRESS): + if key in config: + wifi.request_wifi_ip_state_listener() # Scan results use WiFiScanResultsListener if CONF_SCAN_RESULTS in config: From 7dc40881e29a231db06b1f868b48b037c5b2f443 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 20 Jan 2026 15:55:03 -0500 Subject: [PATCH 0248/2030] Bump version to 2026.1.0b4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 4b38bb779e..7f21cde032 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0b3 +PROJECT_NUMBER = 2026.1.0b4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 35ce8b3cd6..626b46a809 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0b3" +__version__ = "2026.1.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 3c0f43db9e9ebccb713efa35880966e9d5721821 Mon Sep 17 00:00:00 2001 From: polyfloyd Date: Wed, 21 Jan 2026 00:58:47 +0100 Subject: [PATCH 0249/2030] Add the max_delta filter (#12605) Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/sensor/__init__.py | 74 ++++--- esphome/components/sensor/filter.cpp | 33 ++-- esphome/components/sensor/filter.h | 14 +- tests/components/template/common-base.yaml | 2 + .../fixtures/sensor_filters_delta.yaml | 180 ++++++++++++++++++ .../integration/test_sensor_filters_delta.py | 163 ++++++++++++++++ 6 files changed, 420 insertions(+), 46 deletions(-) create mode 100644 tests/integration/fixtures/sensor_filters_delta.yaml create mode 100644 tests/integration/test_sensor_filters_delta.py diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 2ac45a55ac..ebbe0fbccc 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, + CONF_BASELINE, CONF_BELOW, CONF_CALIBRATION, CONF_DEVICE_CLASS, @@ -38,7 +39,6 @@ from esphome.const import ( CONF_TIMEOUT, CONF_TO, CONF_TRIGGER_ID, - CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, CONF_VALUE, CONF_WEB_SERVER, @@ -107,7 +107,7 @@ from esphome.const import ( ) from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity -from esphome.cpp_generator import MockObjClass +from esphome.cpp_generator import MockObj, MockObjClass from esphome.util import Registry CODEOWNERS = ["@esphome/core"] @@ -574,38 +574,56 @@ async def lambda_filter_to_code(config, filter_id): return automation.new_lambda_pvariable(filter_id, lambda_, StatelessLambdaFilter) -DELTA_SCHEMA = cv.Schema( - { - cv.Required(CONF_VALUE): cv.positive_float, - cv.Optional(CONF_TYPE, default="absolute"): cv.one_of( - "absolute", "percentage", lower=True - ), - } +def validate_delta_value(value): + if isinstance(value, str) and value.endswith("%"): + # Check it's a well-formed percentage, but return the string as-is + try: + cv.positive_float(value[:-1]) + return value + except cv.Invalid as exc: + raise cv.Invalid("Malformed delta % value") from exc + return cv.positive_float(value) + + +# This ideally would be done with `cv.maybe_simple_value` but it doesn't seem to respect the default for min_value. +DELTA_SCHEMA = cv.Any( + cv.All( + { + # Ideally this would be 'default=float("inf")' but it doesn't translate well to C++ + cv.Optional(CONF_MAX_VALUE): validate_delta_value, + cv.Optional(CONF_MIN_VALUE, default="0.0"): validate_delta_value, + cv.Optional(CONF_BASELINE): cv.templatable(cv.float_), + }, + cv.has_at_least_one_key(CONF_MAX_VALUE, CONF_MIN_VALUE), + ), + validate_delta_value, ) -def validate_delta(config): - try: - value = cv.positive_float(config) - return DELTA_SCHEMA({CONF_VALUE: value, CONF_TYPE: "absolute"}) - except cv.Invalid: - pass - try: - value = cv.percentage(config) - return DELTA_SCHEMA({CONF_VALUE: value, CONF_TYPE: "percentage"}) - except cv.Invalid: - pass - raise cv.Invalid("Delta filter requires a positive number or percentage value.") +def _get_delta(value): + if isinstance(value, str): + assert value.endswith("%") + return 0.0, float(value[:-1]) + return value, 0.0 -@FILTER_REGISTRY.register("delta", DeltaFilter, cv.Any(DELTA_SCHEMA, validate_delta)) +@FILTER_REGISTRY.register("delta", DeltaFilter, DELTA_SCHEMA) async def delta_filter_to_code(config, filter_id): - percentage = config[CONF_TYPE] == "percentage" - return cg.new_Pvariable( - filter_id, - config[CONF_VALUE], - percentage, - ) + # The config could be just the min_value, or it could be a dict. + max = MockObj("std::numeric_limits::infinity()"), 0 + if isinstance(config, dict): + min = _get_delta(config[CONF_MIN_VALUE]) + if CONF_MAX_VALUE in config: + max = _get_delta(config[CONF_MAX_VALUE]) + else: + min = _get_delta(config) + var = cg.new_Pvariable(filter_id, *min, *max) + if isinstance(config, dict) and (baseline_lambda := config.get(CONF_BASELINE)): + baseline = await cg.process_lambda( + baseline_lambda, [(float, "x")], return_type=float + ) + cg.add(var.set_baseline(baseline)) + return var @FILTER_REGISTRY.register("or", OrFilter, validate_filters) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 8450ec4c4e..3adf28748d 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -291,22 +291,27 @@ optional ThrottleWithPriorityFilter::new_value(float value) { } // DeltaFilter -DeltaFilter::DeltaFilter(float delta, bool percentage_mode) - : delta_(delta), current_delta_(delta), last_value_(NAN), percentage_mode_(percentage_mode) {} +DeltaFilter::DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1) + : min_a0_(min_a0), min_a1_(min_a1), max_a0_(max_a0), max_a1_(max_a1) {} + +void DeltaFilter::set_baseline(float (*fn)(float)) { this->baseline_ = fn; } + optional DeltaFilter::new_value(float value) { - if (std::isnan(value)) { - if (std::isnan(this->last_value_)) { - return {}; - } else { - return this->last_value_ = value; - } + // Always yield the first value. + if (std::isnan(this->last_value_)) { + this->last_value_ = value; + return value; } - float diff = fabsf(value - this->last_value_); - if (std::isnan(this->last_value_) || (diff > 0.0f && diff >= this->current_delta_)) { - if (this->percentage_mode_) { - this->current_delta_ = fabsf(value * this->delta_); - } - return this->last_value_ = value; + // calculate min and max using the linear equation + float ref = this->baseline_(this->last_value_); + float min = fabsf(this->min_a0_ + ref * this->min_a1_); + float max = fabsf(this->max_a0_ + ref * this->max_a1_); + float delta = fabsf(value - ref); + // if there is no reference, e.g. for the first value, just accept this one, + // otherwise accept only if within range. + if (delta > min && delta <= max) { + this->last_value_ = value; + return value; } return {}; } diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 15c7656a7b..573b916a5d 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -452,15 +452,21 @@ class HeartbeatFilter : public Filter, public Component { class DeltaFilter : public Filter { public: - explicit DeltaFilter(float delta, bool percentage_mode); + explicit DeltaFilter(float min_a0, float min_a1, float max_a0, float max_a1); + + void set_baseline(float (*fn)(float)); optional new_value(float value) override; protected: - float delta_; - float current_delta_; + // These values represent linear equations for the min and max values but in practice only one of a0 and a1 will be + // non-zero Each limit is calculated as fabs(a0 + value * a1) + + float min_a0_, min_a1_, max_a0_, max_a1_; + // default baseline is the previous value + float (*baseline_)(float) = [](float last_value) { return last_value; }; + float last_value_{NAN}; - bool percentage_mode_; }; class OrFilter : public Filter { diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index 3b888c3d19..afc3fd9819 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -121,6 +121,8 @@ sensor: min_value: -10.0 - debounce: 0.1s - delta: 5.0 + - delta: + max_value: 2% - exponential_moving_average: alpha: 0.1 send_every: 15 diff --git a/tests/integration/fixtures/sensor_filters_delta.yaml b/tests/integration/fixtures/sensor_filters_delta.yaml new file mode 100644 index 0000000000..19bd2d5ca4 --- /dev/null +++ b/tests/integration/fixtures/sensor_filters_delta.yaml @@ -0,0 +1,180 @@ +esphome: + name: test-delta-filters + +host: +api: + batch_delay: 0ms # Disable batching to receive all state updates +logger: + level: DEBUG + +sensor: + - platform: template + name: "Source Sensor 1" + id: source_sensor_1 + accuracy_decimals: 1 + + - platform: template + name: "Source Sensor 2" + id: source_sensor_2 + accuracy_decimals: 1 + + - platform: template + name: "Source Sensor 3" + id: source_sensor_3 + accuracy_decimals: 1 + + - platform: template + name: "Source Sensor 4" + id: source_sensor_4 + accuracy_decimals: 1 + + - platform: copy + source_id: source_sensor_1 + name: "Filter Min" + id: filter_min + filters: + - delta: + min_value: 10 + + - platform: copy + source_id: source_sensor_2 + name: "Filter Max" + id: filter_max + filters: + - delta: + max_value: 10 + + - platform: copy + source_id: source_sensor_3 + id: test_3_baseline + filters: + - median: + window_size: 6 + send_every: 1 + send_first_at: 1 + + - platform: copy + source_id: source_sensor_3 + name: "Filter Baseline Max" + id: filter_baseline_max + filters: + - delta: + max_value: 10 + baseline: !lambda return id(test_3_baseline).state; + + - platform: copy + source_id: source_sensor_4 + name: "Filter Zero Delta" + id: filter_zero_delta + filters: + - delta: 0 + +script: + - id: test_filter_min + then: + - sensor.template.publish: + id: source_sensor_1 + state: 1.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_1 + state: 5.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_1 + state: 12.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_1 + state: 8.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_1 + state: -2.0 + + - id: test_filter_max + then: + - sensor.template.publish: + id: source_sensor_2 + state: 1.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_2 + state: 5.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_2 + state: 40.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_2 + state: 10.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_2 + state: -40.0 # Filtered out + + - id: test_filter_baseline_max + then: + - sensor.template.publish: + id: source_sensor_3 + state: 1.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_3 + state: 2.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_3 + state: 3.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_3 + state: 40.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_3 + state: 20.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_3 + state: 20.0 + + - id: test_filter_zero_delta + then: + - sensor.template.publish: + id: source_sensor_4 + state: 1.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_4 + state: 1.0 # Filtered out + - delay: 20ms + - sensor.template.publish: + id: source_sensor_4 + state: 2.0 + +button: + - platform: template + name: "Test Filter Min" + id: btn_filter_min + on_press: + - script.execute: test_filter_min + + - platform: template + name: "Test Filter Max" + id: btn_filter_max + on_press: + - script.execute: test_filter_max + + - platform: template + name: "Test Filter Baseline Max" + id: btn_filter_baseline_max + on_press: + - script.execute: test_filter_baseline_max + + - platform: template + name: "Test Filter Zero Delta" + id: btn_filter_zero_delta + on_press: + - script.execute: test_filter_zero_delta diff --git a/tests/integration/test_sensor_filters_delta.py b/tests/integration/test_sensor_filters_delta.py new file mode 100644 index 0000000000..c7a26bf9d1 --- /dev/null +++ b/tests/integration/test_sensor_filters_delta.py @@ -0,0 +1,163 @@ +"""Test sensor DeltaFilter functionality.""" + +from __future__ import annotations + +import asyncio + +from aioesphomeapi import ButtonInfo, EntityState, SensorState +import pytest + +from .state_utils import InitialStateHelper, build_key_to_entity_mapping +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_sensor_filters_delta( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + loop = asyncio.get_running_loop() + + sensor_values: dict[str, list[float]] = { + "filter_min": [], + "filter_max": [], + "filter_baseline_max": [], + "filter_zero_delta": [], + } + + filter_min_done = loop.create_future() + filter_max_done = loop.create_future() + filter_baseline_max_done = loop.create_future() + filter_zero_delta_done = loop.create_future() + + def on_state(state: EntityState) -> None: + if not isinstance(state, SensorState) or state.missing_state: + return + + sensor_name = key_to_sensor.get(state.key) + if sensor_name not in sensor_values: + return + + sensor_values[sensor_name].append(state.state) + + # Check completion conditions + if ( + sensor_name == "filter_min" + and len(sensor_values[sensor_name]) == 3 + and not filter_min_done.done() + ): + filter_min_done.set_result(True) + elif ( + sensor_name == "filter_max" + and len(sensor_values[sensor_name]) == 3 + and not filter_max_done.done() + ): + filter_max_done.set_result(True) + elif ( + sensor_name == "filter_baseline_max" + and len(sensor_values[sensor_name]) == 4 + and not filter_baseline_max_done.done() + ): + filter_baseline_max_done.set_result(True) + elif ( + sensor_name == "filter_zero_delta" + and len(sensor_values[sensor_name]) == 2 + and not filter_zero_delta_done.done() + ): + filter_zero_delta_done.set_result(True) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + # Get entities and build key mapping + entities, _ = await client.list_entities_services() + key_to_sensor = build_key_to_entity_mapping( + entities, + { + "filter_min": "Filter Min", + "filter_max": "Filter Max", + "filter_baseline_max": "Filter Baseline Max", + "filter_zero_delta": "Filter Zero Delta", + }, + ) + + # Set up initial state helper with all entities + initial_state_helper = InitialStateHelper(entities) + + # Subscribe to state changes with wrapper + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + # Wait for initial states + await initial_state_helper.wait_for_initial_states() + + # Find all buttons + button_name_map = { + "Test Filter Min": "filter_min", + "Test Filter Max": "filter_max", + "Test Filter Baseline Max": "filter_baseline_max", + "Test Filter Zero Delta": "filter_zero_delta", + } + buttons = {} + for entity in entities: + if isinstance(entity, ButtonInfo) and entity.name in button_name_map: + buttons[button_name_map[entity.name]] = entity.key + + assert len(buttons) == 4, f"Expected 3 buttons, found {len(buttons)}" + + # Test 1: Min + sensor_values["filter_min"].clear() + client.button_command(buttons["filter_min"]) + try: + await asyncio.wait_for(filter_min_done, timeout=2.0) + except TimeoutError: + pytest.fail(f"Test 1 timed out. Values: {sensor_values['filter_min']}") + + expected = [1.0, 12.0, -2.0] + assert sensor_values["filter_min"] == pytest.approx(expected), ( + f"Test 1 failed: expected {expected}, got {sensor_values['filter_min']}" + ) + + # Test 2: Max + sensor_values["filter_max"].clear() + client.button_command(buttons["filter_max"]) + try: + await asyncio.wait_for(filter_max_done, timeout=2.0) + except TimeoutError: + pytest.fail(f"Test 2 timed out. Values: {sensor_values['filter_max']}") + + expected = [1.0, 5.0, 10.0] + assert sensor_values["filter_max"] == pytest.approx(expected), ( + f"Test 2 failed: expected {expected}, got {sensor_values['filter_max']}" + ) + + # Test 3: Baseline Max + sensor_values["filter_baseline_max"].clear() + client.button_command(buttons["filter_baseline_max"]) + try: + await asyncio.wait_for(filter_baseline_max_done, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Test 3 timed out. Values: {sensor_values['filter_baseline_max']}" + ) + + expected = [1.0, 2.0, 3.0, 20.0] + assert sensor_values["filter_baseline_max"] == pytest.approx(expected), ( + f"Test 3 failed: expected {expected}, got {sensor_values['filter_baseline_max']}" + ) + + # Test 4: Zero Delta + sensor_values["filter_zero_delta"].clear() + client.button_command(buttons["filter_zero_delta"]) + try: + await asyncio.wait_for(filter_zero_delta_done, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Test 4 timed out. Values: {sensor_values['filter_zero_delta']}" + ) + + expected = [1.0, 2.0] + assert sensor_values["filter_zero_delta"] == pytest.approx(expected), ( + f"Test 4 failed: expected {expected}, got {sensor_values['filter_zero_delta']}" + ) From 90edf32acff5b8b6cd58aa3533334244621f383f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 20 Jan 2026 21:15:02 -0500 Subject: [PATCH 0250/2030] Bump version to 2026.1.0 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 7f21cde032..70eeefb85e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0b4 +PROJECT_NUMBER = 2026.1.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 626b46a809..951414f006 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0b4" +__version__ = "2026.1.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 1f3a0490a71970839ed2b80643fde6d914e19f80 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:49:40 -1000 Subject: [PATCH 0251/2030] [wifi] Process scan results one at a time to avoid heap allocation (#13400) --- .../wifi/wifi_component_esp_idf.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 848ec3e11c..99474ac2f8 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -827,16 +827,17 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } uint16_t number = it.number; - auto records = std::make_unique(number); - err = esp_wifi_scan_get_ap_records(&number, records.get()); - if (err != ESP_OK) { - ESP_LOGW(TAG, "esp_wifi_scan_get_ap_records failed: %s", esp_err_to_name(err)); - return; - } - scan_result_.init(number); - for (int i = 0; i < number; i++) { - auto &record = records[i]; + + // Process one record at a time to avoid large buffer allocation + wifi_ap_record_t record; + for (uint16_t i = 0; i < number; i++) { + err = esp_wifi_scan_get_ap_record(&record); + if (err != ESP_OK) { + ESP_LOGW(TAG, "esp_wifi_scan_get_ap_record failed: %s", esp_err_to_name(err)); + esp_wifi_clear_ap_list(); // Free remaining records not yet retrieved + break; + } bssid_t bssid; std::copy(record.bssid, record.bssid + 6, bssid.begin()); std::string ssid(reinterpret_cast(record.ssid)); From cd4cb8b3ec465c2c9961084d8ff52e119a4e06ee Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:50:01 -1000 Subject: [PATCH 0252/2030] [datetime] Add const char * overloads for string parsing to avoid heap allocation (#13363) --- esphome/components/datetime/date_entity.cpp | 4 +-- esphome/components/datetime/date_entity.h | 4 ++- .../components/datetime/datetime_entity.cpp | 4 +-- esphome/components/datetime/datetime_entity.h | 6 +++- esphome/components/datetime/time_entity.cpp | 4 +-- esphome/components/datetime/time_entity.h | 4 ++- esphome/core/time.cpp | 33 ++++++++++--------- esphome/core/time.h | 16 +++++++-- 8 files changed, 47 insertions(+), 28 deletions(-) diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index c5ea051914..3ba488c0aa 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -106,9 +106,9 @@ DateCall &DateCall::set_date(uint16_t year, uint8_t month, uint8_t day) { DateCall &DateCall::set_date(ESPTime time) { return this->set_date(time.year, time.month, time.day_of_month); }; -DateCall &DateCall::set_date(const std::string &date) { +DateCall &DateCall::set_date(const char *date, size_t len) { ESPTime val{}; - if (!ESPTime::strptime(date, val)) { + if (!ESPTime::strptime(date, len, val)) { ESP_LOGE(TAG, "Could not convert the date string to an ESPTime object"); return *this; } diff --git a/esphome/components/datetime/date_entity.h b/esphome/components/datetime/date_entity.h index 069116d162..955fd92c45 100644 --- a/esphome/components/datetime/date_entity.h +++ b/esphome/components/datetime/date_entity.h @@ -67,7 +67,9 @@ class DateCall { void perform(); DateCall &set_date(uint16_t year, uint8_t month, uint8_t day); DateCall &set_date(ESPTime time); - DateCall &set_date(const std::string &date); + DateCall &set_date(const char *date, size_t len); + DateCall &set_date(const char *date) { return this->set_date(date, strlen(date)); } + DateCall &set_date(const std::string &date) { return this->set_date(date.c_str(), date.size()); } DateCall &set_year(uint16_t year) { this->year_ = year; diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index fd3901fcfc..730abb3ca8 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -163,9 +163,9 @@ DateTimeCall &DateTimeCall::set_datetime(ESPTime datetime) { datetime.second); }; -DateTimeCall &DateTimeCall::set_datetime(const std::string &datetime) { +DateTimeCall &DateTimeCall::set_datetime(const char *datetime, size_t len) { ESPTime val{}; - if (!ESPTime::strptime(datetime, val)) { + if (!ESPTime::strptime(datetime, len, val)) { ESP_LOGE(TAG, "Could not convert the time string to an ESPTime object"); return *this; } diff --git a/esphome/components/datetime/datetime_entity.h b/esphome/components/datetime/datetime_entity.h index 018346b34b..b5b8cd677e 100644 --- a/esphome/components/datetime/datetime_entity.h +++ b/esphome/components/datetime/datetime_entity.h @@ -71,7 +71,11 @@ class DateTimeCall { void perform(); DateTimeCall &set_datetime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second); DateTimeCall &set_datetime(ESPTime datetime); - DateTimeCall &set_datetime(const std::string &datetime); + DateTimeCall &set_datetime(const char *datetime, size_t len); + DateTimeCall &set_datetime(const char *datetime) { return this->set_datetime(datetime, strlen(datetime)); } + DateTimeCall &set_datetime(const std::string &datetime) { + return this->set_datetime(datetime.c_str(), datetime.size()); + } DateTimeCall &set_datetime(time_t epoch_seconds); DateTimeCall &set_year(uint16_t year) { diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index d0b8875ed1..74e43fbbe7 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -74,9 +74,9 @@ TimeCall &TimeCall::set_time(uint8_t hour, uint8_t minute, uint8_t second) { TimeCall &TimeCall::set_time(ESPTime time) { return this->set_time(time.hour, time.minute, time.second); }; -TimeCall &TimeCall::set_time(const std::string &time) { +TimeCall &TimeCall::set_time(const char *time, size_t len) { ESPTime val{}; - if (!ESPTime::strptime(time, val)) { + if (!ESPTime::strptime(time, len, val)) { ESP_LOGE(TAG, "Could not convert the time string to an ESPTime object"); return *this; } diff --git a/esphome/components/datetime/time_entity.h b/esphome/components/datetime/time_entity.h index d3be3130b1..e4bb113eb5 100644 --- a/esphome/components/datetime/time_entity.h +++ b/esphome/components/datetime/time_entity.h @@ -69,7 +69,9 @@ class TimeCall { void perform(); TimeCall &set_time(uint8_t hour, uint8_t minute, uint8_t second); TimeCall &set_time(ESPTime time); - TimeCall &set_time(const std::string &time); + TimeCall &set_time(const char *time, size_t len); + TimeCall &set_time(const char *time) { return this->set_time(time, strlen(time)); } + TimeCall &set_time(const std::string &time) { return this->set_time(time.c_str(), time.size()); } TimeCall &set_hour(uint8_t hour) { this->hour_ = hour; diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 4047033f84..554431c631 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -67,7 +67,7 @@ std::string ESPTime::strftime(const char *format) { std::string ESPTime::strftime(const std::string &format) { return this->strftime(format.c_str()); } -bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { +bool ESPTime::strptime(const char *time_to_parse, size_t len, ESPTime &esp_time) { uint16_t year; uint8_t month; uint8_t day; @@ -75,40 +75,41 @@ bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { uint8_t minute; uint8_t second; int num; + const int ilen = static_cast(len); - if (sscanf(time_to_parse.c_str(), "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu %n", &year, &month, &day, // NOLINT - &hour, // NOLINT - &minute, // NOLINT - &second, &num) == 6 && // NOLINT - num == static_cast(time_to_parse.size())) { + if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu %n", &year, &month, &day, // NOLINT + &hour, // NOLINT + &minute, // NOLINT + &second, &num) == 6 && // NOLINT + num == ilen) { 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 = 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 == static_cast(time_to_parse.size())) { + } else if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %02hhu:%02hhu %n", &year, &month, &day, // NOLINT + &hour, // NOLINT + &minute, &num) == 5 && // NOLINT + num == ilen) { 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 == static_cast(time_to_parse.size())) { + } else if (sscanf(time_to_parse, "%02hhu:%02hhu:%02hhu %n", &hour, &minute, &second, &num) == 3 && // NOLINT + num == ilen) { esp_time.hour = hour; esp_time.minute = minute; esp_time.second = second; - } else if (sscanf(time_to_parse.c_str(), "%02hhu:%02hhu %n", &hour, &minute, &num) == 2 && // NOLINT - num == static_cast(time_to_parse.size())) { + } else if (sscanf(time_to_parse, "%02hhu:%02hhu %n", &hour, &minute, &num) == 2 && // NOLINT + num == ilen) { esp_time.hour = hour; esp_time.minute = minute; esp_time.second = 0; - } else if (sscanf(time_to_parse.c_str(), "%04hu-%02hhu-%02hhu %n", &year, &month, &day, &num) == 3 && // NOLINT - num == static_cast(time_to_parse.size())) { + } else if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %n", &year, &month, &day, &num) == 3 && // NOLINT + num == ilen) { esp_time.year = year; esp_time.month = month; esp_time.day_of_month = day; diff --git a/esphome/core/time.h b/esphome/core/time.h index f6f1d57dbb..87ebb5c221 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -80,11 +81,20 @@ struct ESPTime { } /** Convert a string to ESPTime struct as specified by the format argument. - * @param time_to_parse null-terminated c string formatet like this: 2020-08-25 05:30:00. + * @param time_to_parse c string formatted like this: 2020-08-25 05:30:00. + * @param len length of the string (not including null terminator if present) * @param esp_time an instance of a ESPTime struct - * @return the success sate of the parsing + * @return the success state of the parsing */ - static bool strptime(const std::string &time_to_parse, ESPTime &esp_time); + static bool strptime(const char *time_to_parse, size_t len, ESPTime &esp_time); + /// @copydoc strptime(const char *, size_t, ESPTime &) + static bool strptime(const char *time_to_parse, ESPTime &esp_time) { + return strptime(time_to_parse, strlen(time_to_parse), esp_time); + } + /// @copydoc strptime(const char *, size_t, ESPTime &) + static bool strptime(const std::string &time_to_parse, ESPTime &esp_time) { + return strptime(time_to_parse.c_str(), time_to_parse.size(), esp_time); + } /// Convert a C tm struct instance with a C unix epoch timestamp to an ESPTime instance. static ESPTime from_c_tm(struct tm *c_tm, time_t c_time); From 3ca5e5e4e47adc8014feb002b3d20e7da3552f62 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:50:13 -1000 Subject: [PATCH 0253/2030] [wifi] ESP8266: Use direct SDK calls to reduce flash and heap allocation (#13349) --- .../wifi/wifi_component_esp8266.cpp | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 6fb5dd5769..de0600cf5b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -920,7 +920,16 @@ bssid_t WiFiComponent::wifi_bssid() { } return bssid; } -std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } +std::string WiFiComponent::wifi_ssid() { + struct station_config conf {}; + if (!wifi_station_get_config(&conf)) { + return ""; + } + // conf.ssid is uint8[32], not null-terminated if full + auto *ssid_s = reinterpret_cast(conf.ssid); + size_t len = strnlen(ssid_s, sizeof(conf.ssid)); + return {ssid_s, len}; +} const char *WiFiComponent::wifi_ssid_to(std::span buffer) { struct station_config conf {}; if (!wifi_station_get_config(&conf)) { @@ -934,16 +943,24 @@ const char *WiFiComponent::wifi_ssid_to(std::span buffer return buffer.data(); } int8_t WiFiComponent::wifi_rssi() { - if (WiFi.status() != WL_CONNECTED) + if (wifi_station_get_connect_status() != STATION_GOT_IP) return WIFI_RSSI_DISCONNECTED; - int8_t rssi = WiFi.RSSI(); + sint8 rssi = wifi_station_get_rssi(); // Values >= 31 are error codes per NONOS SDK API, not valid RSSI readings return rssi >= 31 ? WIFI_RSSI_DISCONNECTED : rssi; } -int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); } -network::IPAddress WiFiComponent::wifi_subnet_mask_() { return {(const ip_addr_t *) WiFi.subnetMask()}; } -network::IPAddress WiFiComponent::wifi_gateway_ip_() { return {(const ip_addr_t *) WiFi.gatewayIP()}; } -network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return {(const ip_addr_t *) WiFi.dnsIP(num)}; } +int32_t WiFiComponent::get_wifi_channel() { return wifi_get_channel(); } +network::IPAddress WiFiComponent::wifi_subnet_mask_() { + struct ip_info ip {}; + wifi_get_ip_info(STATION_IF, &ip); + return network::IPAddress(&ip.netmask); +} +network::IPAddress WiFiComponent::wifi_gateway_ip_() { + struct ip_info ip {}; + wifi_get_ip_info(STATION_IF, &ip); + return network::IPAddress(&ip.gw); +} +network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(dns_getserver(num)); } void WiFiComponent::wifi_loop_() {} } // namespace esphome::wifi From 6bad697fc6bd042f8c1efcdf289cb2ca96ca2651 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:50:27 -1000 Subject: [PATCH 0254/2030] [debug] ESP8266: Eliminate heap allocations from Arduino String functions (#13352) --- esphome/components/debug/debug_esp8266.cpp | 117 ++++++++++++++++----- 1 file changed, 90 insertions(+), 27 deletions(-) diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 19f15d7d98..a4b6468b49 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -3,21 +3,80 @@ #include "esphome/core/log.h" #include +extern "C" { +#include + +// Global reset info struct populated by SDK at boot +extern struct rst_info resetInfo; + +// Core version - either a string pointer or a version number to format as hex +extern uint32_t core_version; +extern const char *core_release; +} + namespace esphome { namespace debug { static const char *const TAG = "debug"; +// Get reset reason string from reason code (no heap allocation) +// Returns LogString* pointing to flash (PROGMEM) on ESP8266 +static const LogString *get_reset_reason_str(uint32_t reason) { + switch (reason) { + case REASON_DEFAULT_RST: + return LOG_STR("Power On"); + case REASON_WDT_RST: + return LOG_STR("Hardware Watchdog"); + case REASON_EXCEPTION_RST: + return LOG_STR("Exception"); + case REASON_SOFT_WDT_RST: + return LOG_STR("Software Watchdog"); + case REASON_SOFT_RESTART: + return LOG_STR("Software/System restart"); + case REASON_DEEP_SLEEP_AWAKE: + return LOG_STR("Deep-Sleep Wake"); + case REASON_EXT_SYS_RST: + return LOG_STR("External System"); + default: + return LOG_STR("Unknown"); + } +} + +// Size for core version hex buffer +static constexpr size_t CORE_VERSION_BUFFER_SIZE = 12; + +// Get core version string (no heap allocation) +// Returns either core_release directly or formats core_version as hex into provided buffer +static const char *get_core_version_str(std::span buffer) { + if (core_release != nullptr) { + return core_release; + } + snprintf_P(buffer.data(), CORE_VERSION_BUFFER_SIZE, PSTR("%08x"), core_version); + return buffer.data(); +} + +// Size for reset info buffer +static constexpr size_t RESET_INFO_BUFFER_SIZE = 200; + +// Get detailed reset info string (no heap allocation) +// For watchdog/exception resets, includes detailed exception info +static const char *get_reset_info_str(std::span buffer, uint32_t reason) { + if (reason >= REASON_WDT_RST && reason <= REASON_SOFT_WDT_RST) { + snprintf_P(buffer.data(), RESET_INFO_BUFFER_SIZE, + PSTR("Fatal exception:%d flag:%d (%s) epc1:0x%08x epc2:0x%08x epc3:0x%08x excvaddr:0x%08x depc:0x%08x"), + static_cast(resetInfo.exccause), static_cast(reason), + LOG_STR_ARG(get_reset_reason_str(reason)), resetInfo.epc1, resetInfo.epc2, resetInfo.epc3, + resetInfo.excvaddr, resetInfo.depc); + return buffer.data(); + } + return LOG_STR_ARG(get_reset_reason_str(reason)); +} + const char *DebugComponent::get_reset_reason_(std::span buffer) { - char *buf = buffer.data(); -#if !defined(CLANG_TIDY) - String reason = ESP.getResetReason(); // NOLINT - snprintf_P(buf, RESET_REASON_BUFFER_SIZE, PSTR("%s"), reason.c_str()); - return buf; -#else - buf[0] = '\0'; - return buf; -#endif + // Copy from flash to provided buffer + strncpy_P(buffer.data(), (PGM_P) get_reset_reason_str(resetInfo.reason), RESET_REASON_BUFFER_SIZE - 1); + buffer[RESET_REASON_BUFFER_SIZE - 1] = '\0'; + return buffer.data(); } const char *DebugComponent::get_wakeup_cause_(std::span buffer) { @@ -33,37 +92,42 @@ size_t DebugComponent::get_device_info_(std::span constexpr size_t size = DEVICE_INFO_BUFFER_SIZE; char *buf = buffer.data(); - const char *flash_mode; + const LogString *flash_mode; switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) case FM_QIO: - flash_mode = "QIO"; + flash_mode = LOG_STR("QIO"); break; case FM_QOUT: - flash_mode = "QOUT"; + flash_mode = LOG_STR("QOUT"); break; case FM_DIO: - flash_mode = "DIO"; + flash_mode = LOG_STR("DIO"); break; case FM_DOUT: - flash_mode = "DOUT"; + flash_mode = LOG_STR("DOUT"); break; default: - flash_mode = "UNKNOWN"; + flash_mode = LOG_STR("UNKNOWN"); } - uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT - uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT - ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode); + uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT(readability-static-accessed-through-instance) + uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT(readability-static-accessed-through-instance) + ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, + LOG_STR_ARG(flash_mode)); pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, - flash_mode); + LOG_STR_ARG(flash_mode)); -#if !defined(CLANG_TIDY) char reason_buffer[RESET_REASON_BUFFER_SIZE]; - const char *reset_reason = get_reset_reason_(std::span(reason_buffer)); + const char *reset_reason = get_reset_reason_(reason_buffer); + char core_version_buffer[CORE_VERSION_BUFFER_SIZE]; + char reset_info_buffer[RESET_INFO_BUFFER_SIZE]; + // NOLINTBEGIN(readability-static-accessed-through-instance) uint32_t chip_id = ESP.getChipId(); uint8_t boot_version = ESP.getBootVersion(); uint8_t boot_mode = ESP.getBootMode(); uint8_t cpu_freq = ESP.getCpuFreqMHz(); uint32_t flash_chip_id = ESP.getFlashChipId(); + const char *sdk_version = ESP.getSdkVersion(); + // NOLINTEND(readability-static-accessed-through-instance) ESP_LOGD(TAG, "Chip ID: 0x%08" PRIX32 "\n" @@ -74,19 +138,18 @@ size_t DebugComponent::get_device_info_(std::span "Flash Chip ID=0x%08" PRIX32 "\n" "Reset Reason: %s\n" "Reset Info: %s", - chip_id, ESP.getSdkVersion(), ESP.getCoreVersion().c_str(), boot_version, boot_mode, cpu_freq, flash_chip_id, - reset_reason, ESP.getResetInfo().c_str()); + chip_id, sdk_version, get_core_version_str(core_version_buffer), boot_version, boot_mode, cpu_freq, + flash_chip_id, reset_reason, get_reset_info_str(reset_info_buffer, resetInfo.reason)); pos = buf_append_printf(buf, size, pos, "|Chip: 0x%08" PRIX32, chip_id); - pos = buf_append_printf(buf, size, pos, "|SDK: %s", ESP.getSdkVersion()); - pos = buf_append_printf(buf, size, pos, "|Core: %s", ESP.getCoreVersion().c_str()); + pos = buf_append_printf(buf, size, pos, "|SDK: %s", sdk_version); + pos = buf_append_printf(buf, size, pos, "|Core: %s", get_core_version_str(core_version_buffer)); pos = buf_append_printf(buf, size, pos, "|Boot: %u", boot_version); pos = buf_append_printf(buf, size, pos, "|Mode: %u", boot_mode); pos = buf_append_printf(buf, size, pos, "|CPU: %u", cpu_freq); pos = buf_append_printf(buf, size, pos, "|Flash: 0x%08" PRIX32, flash_chip_id); pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason); - pos = buf_append_printf(buf, size, pos, "|%s", ESP.getResetInfo().c_str()); -#endif + pos = buf_append_printf(buf, size, pos, "|%s", get_reset_info_str(reset_info_buffer, resetInfo.reason)); return pos; } From 41a060668c5eab9aa7c6aa5d816e0457430a9628 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:50:39 -1000 Subject: [PATCH 0255/2030] [api] Use stack buffers for noise handshake messages (#13399) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../components/api/api_frame_helper_noise.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 21b0463dfe..4a9257231d 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -3,6 +3,7 @@ #ifdef USE_API_NOISE #include "api_connection.h" // For ClientInfo struct #include "esphome/core/application.h" +#include "esphome/core/entity_base.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -256,28 +257,30 @@ APIError APINoiseFrameHelper::state_action_() { } if (state_ == State::SERVER_HELLO) { // send server hello - constexpr size_t mac_len = 13; // 12 hex chars + null terminator const std::string &name = App.get_name(); - char mac[mac_len]; + char mac[MAC_ADDRESS_BUFFER_SIZE]; get_mac_address_into_buffer(mac); // Calculate positions and sizes size_t name_len = name.size() + 1; // including null terminator size_t name_offset = 1; size_t mac_offset = name_offset + name_len; - size_t total_size = 1 + name_len + mac_len; + size_t total_size = 1 + name_len + MAC_ADDRESS_BUFFER_SIZE; - auto msg = std::make_unique(total_size); + // 1 (proto) + name (max ESPHOME_DEVICE_NAME_MAX_LEN) + 1 (name null) + // + mac (MAC_ADDRESS_BUFFER_SIZE - 1) + 1 (mac null) + constexpr size_t max_msg_size = 1 + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + MAC_ADDRESS_BUFFER_SIZE; + uint8_t msg[max_msg_size]; // chosen proto msg[0] = 0x01; // node name, terminated by null byte - std::memcpy(msg.get() + name_offset, name.c_str(), name_len); + std::memcpy(msg + name_offset, name.c_str(), name_len); // node mac, terminated by null byte - std::memcpy(msg.get() + mac_offset, mac, mac_len); + std::memcpy(msg + mac_offset, mac, MAC_ADDRESS_BUFFER_SIZE); - aerr = write_frame_(msg.get(), total_size); + aerr = write_frame_(msg, total_size); if (aerr != APIError::OK) return aerr; @@ -353,35 +356,32 @@ APIError APINoiseFrameHelper::state_action_() { return APIError::OK; } void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reason) { + // Max reject message: "Bad handshake packet len" (24) + 1 (failure byte) = 25 bytes + uint8_t data[32]; + data[0] = 0x01; // failure + #ifdef USE_STORE_LOG_STR_IN_FLASH // On ESP8266 with flash strings, we need to use PROGMEM-aware functions size_t reason_len = strlen_P(reinterpret_cast(reason)); - size_t data_size = reason_len + 1; - auto data = std::make_unique(data_size); - data[0] = 0x01; // failure - - // Copy error message from PROGMEM if (reason_len > 0) { - memcpy_P(data.get() + 1, reinterpret_cast(reason), reason_len); + memcpy_P(data + 1, reinterpret_cast(reason), reason_len); } #else // Normal memory access const char *reason_str = LOG_STR_ARG(reason); size_t reason_len = strlen(reason_str); - size_t data_size = reason_len + 1; - auto data = std::make_unique(data_size); - data[0] = 0x01; // failure - - // Copy error message in bulk if (reason_len > 0) { - std::memcpy(data.get() + 1, reason_str, reason_len); + // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - binary protocol, not a C string + std::memcpy(data + 1, reason_str, reason_len); } #endif + size_t data_size = reason_len + 1; + // temporarily remove failed state auto orig_state = state_; state_ = State::EXPLICIT_REJECT; - write_frame_(data.get(), data_size); + write_frame_(data, data_size); state_ = orig_state; } APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { From 31608543c2581cc032c1a327f87afa59bc2d0341 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:50:53 -1000 Subject: [PATCH 0256/2030] [esp32_ble_tracker] Optimize loop with state change tracking for ~85% CPU reduction (#13337) --- .../bluetooth_proxy/bluetooth_connection.cpp | 4 +- .../esp32_ble_client/ble_client_base.cpp | 34 +++++------ .../esp32_ble_client/ble_client_base.h | 2 +- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 42 +++++++++++--- .../esp32_ble_tracker/esp32_ble_tracker.h | 58 +++++++++++++++++-- 5 files changed, 107 insertions(+), 33 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 1d6f7e23b3..60f56fda54 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -135,8 +135,8 @@ void BluetoothConnection::loop() { // - For V3_WITH_CACHE: Services are never sent, disable after INIT state // - For V3_WITHOUT_CACHE: Disable only after service discovery is complete // (send_service_ == DONE_SENDING_SERVICES, which is only set after services are sent) - if (this->state_ != espbt::ClientState::INIT && (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE || - this->send_service_ == DONE_SENDING_SERVICES)) { + if (this->state() != espbt::ClientState::INIT && (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE || + this->send_service_ == DONE_SENDING_SERVICES)) { this->disable_loop(); } } diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 01f79156a9..c464c89390 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -50,7 +50,7 @@ void BLEClientBase::loop() { this->set_state(espbt::ClientState::INIT); return; } - if (this->state_ == espbt::ClientState::INIT) { + if (this->state() == espbt::ClientState::INIT) { auto ret = esp_ble_gattc_app_register(this->app_id); if (ret) { ESP_LOGE(TAG, "gattc app register failed. app_id=%d code=%d", this->app_id, ret); @@ -60,7 +60,7 @@ void BLEClientBase::loop() { } // If idle, we can disable the loop as connect() // will enable it again when a connection is needed. - else if (this->state_ == espbt::ClientState::IDLE) { + else if (this->state() == espbt::ClientState::IDLE) { this->disable_loop(); } } @@ -86,7 +86,7 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) { return false; if (this->address_ == 0 || device.address_uint64() != this->address_) return false; - if (this->state_ != espbt::ClientState::IDLE) + if (this->state() != espbt::ClientState::IDLE) return false; this->log_event_("Found device"); @@ -102,10 +102,10 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) { void BLEClientBase::connect() { // Prevent duplicate connection attempts - if (this->state_ == espbt::ClientState::CONNECTING || this->state_ == espbt::ClientState::CONNECTED || - this->state_ == espbt::ClientState::ESTABLISHED) { + if (this->state() == espbt::ClientState::CONNECTING || this->state() == espbt::ClientState::CONNECTED || + this->state() == espbt::ClientState::ESTABLISHED) { ESP_LOGW(TAG, "[%d] [%s] Connection already in progress, state=%s", this->connection_index_, this->address_str_, - espbt::client_state_to_string(this->state_)); + espbt::client_state_to_string(this->state())); return; } ESP_LOGI(TAG, "[%d] [%s] 0x%02x Connecting", this->connection_index_, this->address_str_, this->remote_addr_type_); @@ -133,12 +133,12 @@ void BLEClientBase::connect() { esp_err_t BLEClientBase::pair() { return esp_ble_set_encryption(this->remote_bda_, ESP_BLE_SEC_ENCRYPT); } void BLEClientBase::disconnect() { - if (this->state_ == espbt::ClientState::IDLE || this->state_ == espbt::ClientState::DISCONNECTING) { + if (this->state() == espbt::ClientState::IDLE || this->state() == espbt::ClientState::DISCONNECTING) { ESP_LOGI(TAG, "[%d] [%s] Disconnect requested, but already %s", this->connection_index_, this->address_str_, - espbt::client_state_to_string(this->state_)); + espbt::client_state_to_string(this->state())); return; } - if (this->state_ == espbt::ClientState::CONNECTING || this->conn_id_ == UNSET_CONN_ID) { + if (this->state() == espbt::ClientState::CONNECTING || this->conn_id_ == UNSET_CONN_ID) { ESP_LOGD(TAG, "[%d] [%s] Disconnect before connected, disconnect scheduled", this->connection_index_, this->address_str_); this->want_disconnect_ = true; @@ -150,7 +150,7 @@ void BLEClientBase::disconnect() { void BLEClientBase::unconditional_disconnect() { // Disconnect without checking the state. ESP_LOGI(TAG, "[%d] [%s] Disconnecting (conn_id: %d).", this->connection_index_, this->address_str_, this->conn_id_); - if (this->state_ == espbt::ClientState::DISCONNECTING) { + if (this->state() == espbt::ClientState::DISCONNECTING) { this->log_error_("Already disconnecting"); return; } @@ -170,7 +170,7 @@ void BLEClientBase::unconditional_disconnect() { this->log_gattc_warning_("esp_ble_gattc_close", err); } - if (this->state_ == espbt::ClientState::DISCOVERED) { + if (this->state() == espbt::ClientState::DISCOVERED) { this->set_address(0); this->set_state(espbt::ClientState::IDLE); } else { @@ -295,18 +295,18 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ // ESP-IDF's BLE stack may send ESP_GATTC_OPEN_EVT after esp_ble_gattc_open() returns an // error, if the error occurred at the BTA/GATT layer. This can result in the event // arriving after we've already transitioned to IDLE state. - if (this->state_ == espbt::ClientState::IDLE) { + if (this->state() == espbt::ClientState::IDLE) { ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_OPEN_EVT in IDLE state (status=%d), ignoring", this->connection_index_, this->address_str_, param->open.status); break; } - if (this->state_ != espbt::ClientState::CONNECTING) { + if (this->state() != espbt::ClientState::CONNECTING) { // This should not happen but lets log it in case it does // because it means we have a bad assumption about how the // ESP BT stack works. ESP_LOGE(TAG, "[%d] [%s] ESP_GATTC_OPEN_EVT in %s state (status=%d)", this->connection_index_, - this->address_str_, espbt::client_state_to_string(this->state_), param->open.status); + this->address_str_, espbt::client_state_to_string(this->state()), param->open.status); } if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) { this->log_gattc_warning_("Connection open", param->open.status); @@ -327,7 +327,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ if (this->connection_type_ == espbt::ConnectionType::V3_WITH_CACHE) { // Cached connections already connected with medium parameters, no update needed // only set our state, subclients might have more stuff to do yet. - this->state_ = espbt::ClientState::ESTABLISHED; + this->set_state_internal_(espbt::ClientState::ESTABLISHED); break; } // For V3_WITHOUT_CACHE, we already set fast params before connecting @@ -356,7 +356,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ return false; // Check if we were disconnected while waiting for service discovery if (param->disconnect.reason == ESP_GATT_CONN_TERMINATE_PEER_USER && - this->state_ == espbt::ClientState::CONNECTED) { + this->state() == espbt::ClientState::CONNECTED) { this->log_warning_("Remote closed during discovery"); } else { ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason 0x%02x", this->connection_index_, this->address_str_, @@ -433,7 +433,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ #endif } ESP_LOGI(TAG, "[%d] [%s] Service discovery complete", this->connection_index_, this->address_str_); - this->state_ = espbt::ClientState::ESTABLISHED; + this->set_state_internal_(espbt::ClientState::ESTABLISHED); break; } case ESP_GATTC_READ_DESCR_EVT: { diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index c52f0e5d2d..c2336b2349 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -44,7 +44,7 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { void unconditional_disconnect(); void release_services(); - bool connected() { return this->state_ == espbt::ClientState::ESTABLISHED; } + bool connected() { return this->state() == espbt::ClientState::ESTABLISHED; } void set_auto_connect(bool auto_connect) { this->auto_connect_ = auto_connect; } diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 995755ac84..73a298d279 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -105,15 +105,13 @@ void ESP32BLETracker::loop() { } // Check for scan timeout - moved here from scheduler to avoid false reboots - // when the loop is blocked + // when the loop is blocked. This must run every iteration for safety. if (this->scanner_state_ == ScannerState::RUNNING) { switch (this->scan_timeout_state_) { case ScanTimeoutState::MONITORING: { - uint32_t now = App.get_loop_component_start_time(); - uint32_t timeout_ms = this->scan_duration_ * 2000; // Robust time comparison that handles rollover correctly // This works because unsigned arithmetic wraps around predictably - if ((now - this->scan_start_time_) > timeout_ms) { + if ((App.get_loop_component_start_time() - this->scan_start_time_) > this->scan_timeout_ms_) { // First time we've seen the timeout exceeded - wait one more loop iteration // This ensures all components have had a chance to process pending events // This is because esp32_ble may not have run yet and called @@ -128,13 +126,31 @@ void ESP32BLETracker::loop() { ESP_LOGE(TAG, "Scan never terminated, rebooting"); App.reboot(); break; - case ScanTimeoutState::INACTIVE: - // This case should be unreachable - scanner and timeout states are always synchronized break; } } + // Fast path: skip expensive client state counting and processing + // if no state has changed since last loop iteration. + // + // How state changes ensure we reach the code below: + // - handle_scanner_failure_(): scanner_state_ becomes FAILED via set_scanner_state_(), or + // scan_set_param_failed_ requires scanner_state_==RUNNING which can only be reached via + // set_scanner_state_(RUNNING) in gap_scan_start_complete_() (scan params are set during + // STARTING, not RUNNING, so version is always incremented before this condition is true) + // - start_scan_(): scanner_state_ becomes IDLE via set_scanner_state_() in cleanup_scan_state_() + // - try_promote_discovered_clients_(): client enters DISCOVERED via set_state(), or + // connecting client finishes (state change), or scanner reaches RUNNING/IDLE + // + // All conditions that affect the logic below are tied to state changes that increment + // state_version_, so the fast path is safe. + if (this->state_version_ == this->last_processed_version_) { + return; + } + this->last_processed_version_ = this->state_version_; + + // State changed - do full processing ClientStateCounts counts = this->count_client_states_(); if (counts != this->client_state_counts_) { this->client_state_counts_ = counts; @@ -142,6 +158,7 @@ void ESP32BLETracker::loop() { this->client_state_counts_.discovered, this->client_state_counts_.disconnecting); } + // Scanner failure: reached when set_scanner_state_(FAILED) or scan_set_param_failed_ set if (this->scanner_state_ == ScannerState::FAILED || (this->scan_set_param_failed_ && this->scanner_state_ == ScannerState::RUNNING)) { this->handle_scanner_failure_(); @@ -160,6 +177,8 @@ void ESP32BLETracker::loop() { */ + // Start scan: reached when scanner_state_ becomes IDLE (via set_scanner_state_()) and + // all clients are idle (their state changes increment version when they finish) if (this->scanner_state_ == ScannerState::IDLE && !counts.connecting && !counts.disconnecting && !counts.discovered) { #ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE this->update_coex_preference_(false); @@ -168,8 +187,9 @@ void ESP32BLETracker::loop() { this->start_scan_(false); // first = false } } - // If there is a discovered client and no connecting - // clients, then promote the discovered client to ready to connect. + // Promote discovered clients: reached when a client's state becomes DISCOVERED (via set_state()), + // or when a blocking condition clears (connecting client finishes, scanner reaches RUNNING/IDLE). + // All these trigger state_version_ increment, so we'll process and check promotion eligibility. // We check both RUNNING and IDLE states because: // - RUNNING: gap_scan_event_handler initiates stop_scan_() but promotion can happen immediately // - IDLE: Scanner has already stopped (naturally or by gap_scan_event_handler) @@ -236,6 +256,7 @@ void ESP32BLETracker::start_scan_(bool first) { // Start timeout monitoring in loop() instead of using scheduler // This prevents false reboots when the loop is blocked this->scan_start_time_ = App.get_loop_component_start_time(); + this->scan_timeout_ms_ = this->scan_duration_ * 2000; this->scan_timeout_state_ = ScanTimeoutState::MONITORING; esp_err_t err = esp_ble_gap_set_scan_params(&this->scan_params_); @@ -253,6 +274,10 @@ void ESP32BLETracker::start_scan_(bool first) { void ESP32BLETracker::register_client(ESPBTClient *client) { #ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT client->app_id = ++this->app_id_; + // Give client a pointer to our state_version_ so it can notify us of state changes. + // This enables loop() fast-path optimization - we skip expensive work when no state changed. + // Safe because ESP32BLETracker (singleton) outlives all registered clients. + client->set_tracker_state_version(&this->state_version_); this->clients_.push_back(client); this->recalculate_advertisement_parser_types(); #endif @@ -382,6 +407,7 @@ void ESP32BLETracker::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_i void ESP32BLETracker::set_scanner_state_(ScannerState state) { this->scanner_state_ = state; + this->state_version_++; for (auto *listener : this->scanner_state_listeners_) { listener->on_scanner_state(state); } diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index f538a0eddc..fa0cdb6f45 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -216,6 +216,19 @@ enum class ConnectionType : uint8_t { V3_WITHOUT_CACHE }; +/// Base class for BLE GATT clients that connect to remote devices. +/// +/// State Change Tracking Design: +/// ----------------------------- +/// ESP32BLETracker::loop() needs to know when client states change to avoid +/// expensive polling. Rather than checking all clients every iteration (~7000/min), +/// we use a version counter owned by ESP32BLETracker that clients increment on +/// state changes. The tracker compares versions to skip work when nothing changed. +/// +/// Ownership: ESP32BLETracker owns state_version_. Clients hold a non-owning +/// pointer (tracker_state_version_) set during register_client(). Clients +/// increment the counter through this pointer when their state changes. +/// The pointer may be null if the client is not registered with a tracker. class ESPBTClient : public ESPBTDeviceListener { public: virtual bool gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, @@ -225,26 +238,49 @@ class ESPBTClient : public ESPBTDeviceListener { virtual void disconnect() = 0; bool disconnect_pending() const { return this->want_disconnect_; } void cancel_pending_disconnect() { this->want_disconnect_ = false; } + + /// Set the client state with IDLE handling (clears want_disconnect_). + /// Notifies the tracker of state change for loop optimization. virtual void set_state(ClientState st) { - this->state_ = st; + this->set_state_internal_(st); if (st == ClientState::IDLE) { this->want_disconnect_ = false; } } - ClientState state() const { return state_; } + ClientState state() const { return this->state_; } + + /// Called by ESP32BLETracker::register_client() to enable state change notifications. + /// The pointer must remain valid for the lifetime of the client (guaranteed since + /// ESP32BLETracker is a singleton that outlives all clients). + void set_tracker_state_version(uint8_t *version) { this->tracker_state_version_ = version; } // Memory optimized layout uint8_t app_id; // App IDs are small integers assigned sequentially protected: - // Group 1: 1-byte types - ClientState state_{ClientState::INIT}; + /// Set state without IDLE handling - use for direct state transitions. + /// Increments the tracker's state version counter to signal that loop() + /// should do full processing on the next iteration. + void set_state_internal_(ClientState st) { + this->state_ = st; + // Notify tracker that state changed (tracker_state_version_ is owned by ESP32BLETracker) + if (this->tracker_state_version_ != nullptr) { + (*this->tracker_state_version_)++; + } + } + // want_disconnect_ is set to true when a disconnect is requested // while the client is connecting. This is used to disconnect the // client as soon as we get the connection id (conn_id_) from the // ESP_GATTC_OPEN_EVT event. bool want_disconnect_{false}; - // 2 bytes used, 2 bytes padding + + private: + ClientState state_{ClientState::INIT}; + /// Non-owning pointer to ESP32BLETracker::state_version_. When this client's + /// state changes, we increment the tracker's counter to signal that loop() + /// should perform full processing. Null if client not registered with tracker. + uint8_t *tracker_state_version_{nullptr}; }; class ESP32BLETracker : public Component, @@ -380,6 +416,16 @@ class ESP32BLETracker : public Component, // Group 4: 1-byte types (enums, uint8_t, bool) uint8_t app_id_{0}; uint8_t scan_start_fail_count_{0}; + /// Version counter for loop() fast-path optimization. Incremented when: + /// - Scanner state changes (via set_scanner_state_()) + /// - Any registered client's state changes (clients hold pointer to this counter) + /// Owned by this class; clients receive non-owning pointer via register_client(). + /// When loop() sees state_version_ == last_processed_version_, it skips expensive + /// client state counting and takes the fast path (just timeout check + return). + uint8_t state_version_{0}; + /// Last state_version_ value when loop() did full processing. Compared against + /// state_version_ to detect if any state changed since last iteration. + uint8_t last_processed_version_{0}; ScannerState scanner_state_{ScannerState::IDLE}; bool scan_continuous_; bool scan_active_; @@ -396,6 +442,8 @@ class ESP32BLETracker : public Component, EXCEEDED_WAIT, // Timeout exceeded, waiting one loop before reboot }; uint32_t scan_start_time_{0}; + /// Precomputed timeout value: scan_duration_ * 2000 + uint32_t scan_timeout_ms_{0}; ScanTimeoutState scan_timeout_state_{ScanTimeoutState::INACTIVE}; }; From 258b73d7f6341610e54cef5c81a7be6aab8b31b6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:51:06 -1000 Subject: [PATCH 0257/2030] [core] Eliminate global constructor overhead for component vectors (#13386) --- esphome/core/component.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 2f61f7d195..98e8c02d07 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -47,18 +47,21 @@ struct ComponentPriorityOverride { }; // Error messages for failed components +// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead +// This is never freed as error messages persist for the lifetime of the device // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -std::unique_ptr> component_error_messages; +std::vector *component_error_messages = nullptr; // Setup priority overrides - freed after setup completes +// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -std::unique_ptr> setup_priority_overrides; +std::vector *setup_priority_overrides = nullptr; // Helper to store error messages - reduces duplication between deprecated and new API // Remove before 2026.6.0 when deprecated const char* API is removed void store_component_error_message(const Component *component, const char *message, bool is_flash_ptr) { // Lazy allocate the error messages vector if needed if (!component_error_messages) { - component_error_messages = std::make_unique>(); + component_error_messages = new std::vector(); } // Check if this component already has an error message for (auto &entry : *component_error_messages) { @@ -467,7 +470,7 @@ float Component::get_actual_setup_priority() const { void Component::set_setup_priority(float priority) { // Lazy allocate the vector if needed if (!setup_priority_overrides) { - setup_priority_overrides = std::make_unique>(); + setup_priority_overrides = new std::vector(); // Reserve some space to avoid reallocations (most configs have < 10 overrides) setup_priority_overrides->reserve(10); } @@ -553,7 +556,8 @@ WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {} void clear_setup_priority_overrides() { // Free the setup priority map completely - setup_priority_overrides.reset(); + delete setup_priority_overrides; + setup_priority_overrides = nullptr; } } // namespace esphome From 1095bde2dbc15e449ac2d5249fed4c8452b8c89e Mon Sep 17 00:00:00 2001 From: Jasper van der Neut - Stulen Date: Wed, 21 Jan 2026 04:51:39 +0100 Subject: [PATCH 0258/2030] [cc1101] Add on_packet listener callback code (packet_transport) (#13344) --- esphome/components/cc1101/cc1101.cpp | 9 ++++++++- esphome/components/cc1101/cc1101.h | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/esphome/components/cc1101/cc1101.cpp b/esphome/components/cc1101/cc1101.cpp index c4507a54e5..46cd89e0e8 100644 --- a/esphome/components/cc1101/cc1101.cpp +++ b/esphome/components/cc1101/cc1101.cpp @@ -152,6 +152,13 @@ void CC1101Component::setup() { } } +void CC1101Component::call_listeners_(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi) { + for (auto &listener : this->listeners_) { + listener->on_packet(packet, freq_offset, rssi, lqi); + } + this->packet_trigger_->trigger(packet, freq_offset, rssi, lqi); +} + void CC1101Component::loop() { if (this->state_.PKT_FORMAT != static_cast(PacketFormat::PACKET_FORMAT_FIFO) || this->gdo0_pin_ == nullptr || !this->gdo0_pin_->digital_read()) { @@ -198,7 +205,7 @@ void CC1101Component::loop() { bool crc_ok = (this->state_.LQI & STATUS_CRC_OK_MASK) != 0; uint8_t lqi = this->state_.LQI & STATUS_LQI_MASK; if (this->state_.CRC_EN == 0 || crc_ok) { - this->packet_trigger_->trigger(this->packet_, freq_offset, rssi, lqi); + this->call_listeners_(this->packet_, freq_offset, rssi, lqi); } // Return to rx diff --git a/esphome/components/cc1101/cc1101.h b/esphome/components/cc1101/cc1101.h index 43ae5b3612..6e3f01af90 100644 --- a/esphome/components/cc1101/cc1101.h +++ b/esphome/components/cc1101/cc1101.h @@ -11,6 +11,11 @@ namespace esphome::cc1101 { enum class CC1101Error { NONE = 0, TIMEOUT, PARAMS, CRC_ERROR, FIFO_OVERFLOW, PLL_LOCK }; +class CC1101Listener { + public: + virtual void on_packet(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi) = 0; +}; + class CC1101Component : public Component, public spi::SPIDevice { @@ -73,6 +78,7 @@ class CC1101Component : public Component, // Packet mode operations CC1101Error transmit_packet(const std::vector &packet); + void register_listener(CC1101Listener *listener) { this->listeners_.push_back(listener); } Trigger, float, float, uint8_t> *get_packet_trigger() const { return this->packet_trigger_; } protected: @@ -89,9 +95,11 @@ class CC1101Component : public Component, InternalGPIOPin *gdo0_pin_{nullptr}; // Packet handling + void call_listeners_(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi); Trigger, float, float, uint8_t> *packet_trigger_{ new Trigger, float, float, uint8_t>()}; std::vector packet_; + std::vector listeners_; // Low-level Helpers uint8_t strobe_(Command cmd); From acdc7bd8929844aa0e5d816a140f09bc30b8cf78 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 20 Jan 2026 22:51:54 -0500 Subject: [PATCH 0259/2030] [json] Use ESP-IDF component registry for ArduinoJson on ESP32 (#13280) Co-authored-by: Claude Opus 4.5 --- .clang-tidy.hash | 2 +- esphome/components/json/__init__.py | 9 +++++++-- esphome/idf_component.yml | 2 ++ platformio.ini | 5 ++++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 9661c2ca02..b448915e27 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -d272a88e8ca28ae9340a9a03295a566432a52cb696501908f57764475bf7ca65 +d15ae81646ac0ee76b2586716fe697f187281523ee6db566aed26542a9f98d1a diff --git a/esphome/components/json/__init__.py b/esphome/components/json/__init__.py index 4cd737c60d..28fdcd41ef 100644 --- a/esphome/components/json/__init__.py +++ b/esphome/components/json/__init__.py @@ -1,6 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome.core import CoroPriority, coroutine_with_priority +from esphome.core import CORE, CoroPriority, coroutine_with_priority CODEOWNERS = ["@esphome/core"] json_ns = cg.esphome_ns.namespace("json") @@ -12,6 +12,11 @@ CONFIG_SCHEMA = cv.All( @coroutine_with_priority(CoroPriority.BUS) async def to_code(config): - cg.add_library("bblanchon/ArduinoJson", "7.4.2") + if CORE.is_esp32: + from esphome.components.esp32 import add_idf_component + + add_idf_component(name="bblanchon/arduinojson", ref="7.4.2") + else: + cg.add_library("bblanchon/ArduinoJson", "7.4.2") cg.add_define("USE_JSON") cg.add_global(json_ns.using) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 5903e68e8e..e19c1a1c87 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -1,4 +1,6 @@ dependencies: + bblanchon/arduinojson: + version: "7.4.2" espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: diff --git a/platformio.ini b/platformio.ini index 4180971b54..a54aa0964c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,6 @@ build_flags = [common] ; Base dependencies for all environments lib_deps_base = - bblanchon/ArduinoJson@7.4.2 ; json wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.2 ; mlx90393 pavlodn/HaierProtocol@0.9.31 ; haier @@ -111,6 +110,7 @@ platform_packages = framework = arduino lib_deps = ${common:arduino.lib_deps} + bblanchon/ArduinoJson@7.4.2 ; json ESP8266WiFi ; wifi (Arduino built-in) Update ; ota (Arduino built-in) ESP32Async/ESPAsyncTCP@2.0.0 ; async_tcp @@ -201,6 +201,7 @@ platform_packages = framework = arduino lib_deps = ${common:arduino.lib_deps} + bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.7.8 ; web_server_base build_flags = ${common:arduino.build_flags} @@ -216,6 +217,7 @@ platform = libretiny@1.9.2 framework = arduino lib_compat_mode = soft lib_deps = + bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.7.8 ; web_server_base droscy/esp_wireguard@0.4.2 ; wireguard build_flags = @@ -239,6 +241,7 @@ build_flags = -DUSE_NRF52 lib_deps = ${common.lib_deps_base} + bblanchon/ArduinoJson@7.4.2 ; json ; All the actual environments are defined below. From df74d307c83ade59741627f1cccca13d28f71302 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 20 Jan 2026 22:52:04 -0500 Subject: [PATCH 0260/2030] [esp32] Add support for native ESP-IDF builds (#13272) Co-authored-by: Claude Opus 4.5 Co-authored-by: J. Nick Koston --- esphome/__main__.py | 65 ++++++-- esphome/build_gen/espidf.py | 139 ++++++++++++++++ esphome/components/esp32/__init__.py | 139 ++++++++-------- esphome/components/esp32/const.py | 1 + esphome/const.py | 1 + esphome/core/__init__.py | 4 + esphome/espidf_api.py | 229 +++++++++++++++++++++++++++ 7 files changed, 502 insertions(+), 76 deletions(-) create mode 100644 esphome/build_gen/espidf.py create mode 100644 esphome/espidf_api.py diff --git a/esphome/__main__.py b/esphome/__main__.py index 09d2855eb1..55297e8d9b 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -43,6 +43,7 @@ from esphome.const import ( CONF_SUBSTITUTIONS, CONF_TOPIC, ENV_NOGITIGNORE, + KEY_NATIVE_IDF, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, @@ -116,6 +117,7 @@ class ArgsProtocol(Protocol): configuration: str name: str upload_speed: str | None + native_idf: bool def choose_prompt(options, purpose: str = None): @@ -500,12 +502,15 @@ def wrap_to_code(name, comp): return wrapped -def write_cpp(config: ConfigType) -> int: +def write_cpp(config: ConfigType, native_idf: bool = False) -> int: if not get_bool_env(ENV_NOGITIGNORE): writer.write_gitignore() + # Store native_idf flag so esp32 component can check it + CORE.data[KEY_NATIVE_IDF] = native_idf + generate_cpp_contents(config) - return write_cpp_file() + return write_cpp_file(native_idf=native_idf) def generate_cpp_contents(config: ConfigType) -> None: @@ -519,32 +524,54 @@ def generate_cpp_contents(config: ConfigType) -> None: CORE.flush_tasks() -def write_cpp_file() -> int: +def write_cpp_file(native_idf: bool = False) -> int: code_s = indent(CORE.cpp_main_section) writer.write_cpp(code_s) - from esphome.build_gen import platformio + if native_idf and CORE.is_esp32 and CORE.target_framework == "esp-idf": + from esphome.build_gen import espidf - platformio.write_project() + espidf.write_project() + else: + from esphome.build_gen import platformio + + platformio.write_project() return 0 def compile_program(args: ArgsProtocol, config: ConfigType) -> int: - from esphome import platformio_api + native_idf = getattr(args, "native_idf", False) # NOTE: "Build path:" format is parsed by script/ci_memory_impact_extract.py # If you change this format, update the regex in that script as well _LOGGER.info("Compiling app... Build path: %s", CORE.build_path) - rc = platformio_api.run_compile(config, CORE.verbose) - if rc != 0: - return rc + + if native_idf and CORE.is_esp32 and CORE.target_framework == "esp-idf": + from esphome import espidf_api + + rc = espidf_api.run_compile(config, CORE.verbose) + if rc != 0: + return rc + + # Create factory.bin and ota.bin + espidf_api.create_factory_bin() + espidf_api.create_ota_bin() + else: + from esphome import platformio_api + + rc = platformio_api.run_compile(config, CORE.verbose) + if rc != 0: + return rc + + idedata = platformio_api.get_idedata(config) + if idedata is None: + return 1 # Check if firmware was rebuilt and emit build_info + create manifest _check_and_emit_build_info() - idedata = platformio_api.get_idedata(config) - return 0 if idedata is not None else 1 + return 0 def _check_and_emit_build_info() -> None: @@ -801,7 +828,8 @@ def command_vscode(args: ArgsProtocol) -> int | None: def command_compile(args: ArgsProtocol, config: ConfigType) -> int | None: - exit_code = write_cpp(config) + native_idf = getattr(args, "native_idf", False) + exit_code = write_cpp(config, native_idf=native_idf) if exit_code != 0: return exit_code if args.only_generate: @@ -856,7 +884,8 @@ def command_logs(args: ArgsProtocol, config: ConfigType) -> int | None: def command_run(args: ArgsProtocol, config: ConfigType) -> int | None: - exit_code = write_cpp(config) + native_idf = getattr(args, "native_idf", False) + exit_code = write_cpp(config, native_idf=native_idf) if exit_code != 0: return exit_code exit_code = compile_program(args, config) @@ -1310,6 +1339,11 @@ def parse_args(argv): help="Only generate source code, do not compile.", action="store_true", ) + parser_compile.add_argument( + "--native-idf", + help="Build with native ESP-IDF instead of PlatformIO (ESP32 esp-idf framework only).", + action="store_true", + ) parser_upload = subparsers.add_parser( "upload", @@ -1391,6 +1425,11 @@ def parse_args(argv): help="Reset the device before starting serial logs.", default=os.getenv("ESPHOME_SERIAL_LOGGING_RESET"), ) + parser_run.add_argument( + "--native-idf", + help="Build with native ESP-IDF instead of PlatformIO (ESP32 esp-idf framework only).", + action="store_true", + ) parser_clean = subparsers.add_parser( "clean-mqtt", diff --git a/esphome/build_gen/espidf.py b/esphome/build_gen/espidf.py new file mode 100644 index 0000000000..f45efb82c1 --- /dev/null +++ b/esphome/build_gen/espidf.py @@ -0,0 +1,139 @@ +"""ESP-IDF direct build generator for ESPHome.""" + +import json +from pathlib import Path + +from esphome.components.esp32 import get_esp32_variant +from esphome.core import CORE +from esphome.helpers import mkdir_p, write_file_if_changed + + +def get_available_components() -> list[str] | None: + """Get list of available ESP-IDF components from project_description.json. + + Returns only internal ESP-IDF components, excluding external/managed + components (from idf_component.yml). + """ + project_desc = Path(CORE.build_path) / "build" / "project_description.json" + if not project_desc.exists(): + return None + + try: + with open(project_desc, encoding="utf-8") as f: + data = json.load(f) + + component_info = data.get("build_component_info", {}) + + result = [] + for name, info in component_info.items(): + # Exclude our own src component + if name == "src": + continue + + # Exclude managed/external components + comp_dir = info.get("dir", "") + if "managed_components" in comp_dir: + continue + + result.append(name) + + return result + except (json.JSONDecodeError, OSError): + return None + + +def has_discovered_components() -> bool: + """Check if we have discovered components from a previous configure.""" + return get_available_components() is not None + + +def get_project_cmakelists() -> str: + """Generate the top-level CMakeLists.txt for ESP-IDF project.""" + # Get IDF target from ESP32 variant (e.g., ESP32S3 -> esp32s3) + variant = get_esp32_variant() + idf_target = variant.lower().replace("-", "") + + return f"""\ +# Auto-generated by ESPHome +cmake_minimum_required(VERSION 3.16) + +set(IDF_TARGET {idf_target}) +set(EXTRA_COMPONENT_DIRS ${{CMAKE_SOURCE_DIR}}/src) + +include($ENV{{IDF_PATH}}/tools/cmake/project.cmake) +project({CORE.name}) +""" + + +def get_component_cmakelists(minimal: bool = False) -> str: + """Generate the main component CMakeLists.txt.""" + idf_requires = [] if minimal else (get_available_components() or []) + requires_str = " ".join(idf_requires) + + # Extract compile definitions from build flags (-DXXX -> XXX) + compile_defs = [flag[2:] for flag in CORE.build_flags if flag.startswith("-D")] + compile_defs_str = "\n ".join(compile_defs) if compile_defs else "" + + # Extract compile options (-W flags, excluding linker flags) + compile_opts = [ + flag + for flag in CORE.build_flags + if flag.startswith("-W") and not flag.startswith("-Wl,") + ] + compile_opts_str = "\n ".join(compile_opts) if compile_opts else "" + + # Extract linker options (-Wl, flags) + link_opts = [flag for flag in CORE.build_flags if flag.startswith("-Wl,")] + link_opts_str = "\n ".join(link_opts) if link_opts else "" + + return f"""\ +# Auto-generated by ESPHome +file(GLOB_RECURSE app_sources + "${{CMAKE_CURRENT_SOURCE_DIR}}/*.cpp" + "${{CMAKE_CURRENT_SOURCE_DIR}}/*.c" + "${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.cpp" + "${{CMAKE_CURRENT_SOURCE_DIR}}/esphome/*.c" +) + +idf_component_register( + SRCS ${{app_sources}} + INCLUDE_DIRS "." "esphome" + REQUIRES {requires_str} +) + +# Apply C++ standard +target_compile_features(${{COMPONENT_LIB}} PUBLIC cxx_std_20) + +# ESPHome compile definitions +target_compile_definitions(${{COMPONENT_LIB}} PUBLIC + {compile_defs_str} +) + +# ESPHome compile options +target_compile_options(${{COMPONENT_LIB}} PUBLIC + {compile_opts_str} +) + +# ESPHome linker options +target_link_options(${{COMPONENT_LIB}} PUBLIC + {link_opts_str} +) +""" + + +def write_project(minimal: bool = False) -> None: + """Write ESP-IDF project files.""" + mkdir_p(CORE.build_path) + mkdir_p(CORE.relative_src_path()) + + # Write top-level CMakeLists.txt + write_file_if_changed( + CORE.relative_build_path("CMakeLists.txt"), + get_project_cmakelists(), + ) + + # Write component CMakeLists.txt in src/ + write_file_if_changed( + CORE.relative_src_path("CMakeLists.txt"), + get_component_cmakelists(minimal=minimal), + ) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 45fe8d1c26..07446ab046 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -34,6 +34,7 @@ from esphome.const import ( KEY_CORE, KEY_FRAMEWORK_VERSION, KEY_NAME, + KEY_NATIVE_IDF, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_ESP32, @@ -53,6 +54,7 @@ from .const import ( # noqa KEY_COMPONENTS, KEY_ESP32, KEY_EXTRA_BUILD_FILES, + KEY_FLASH_SIZE, KEY_PATH, KEY_REF, KEY_REPO, @@ -199,6 +201,7 @@ def set_core_data(config): ) CORE.data[KEY_ESP32][KEY_BOARD] = config[CONF_BOARD] + CORE.data[KEY_ESP32][KEY_FLASH_SIZE] = config[CONF_FLASH_SIZE] CORE.data[KEY_ESP32][KEY_VARIANT] = variant CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES] = {} @@ -962,12 +965,54 @@ async def _add_yaml_idf_components(components: list[ConfigType]): async def to_code(config): - cg.add_platformio_option("board", config[CONF_BOARD]) - cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE]) - cg.add_platformio_option( - "board_upload.maximum_size", - int(config[CONF_FLASH_SIZE].removesuffix("MB")) * 1024 * 1024, - ) + framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] + conf = config[CONF_FRAMEWORK] + + # Check if using native ESP-IDF build (--native-idf) + use_platformio = not CORE.data.get(KEY_NATIVE_IDF, False) + if use_platformio: + # Clear IDF environment variables to avoid conflicts with PlatformIO's ESP-IDF + # but keep them when using --native-idf for native ESP-IDF builds + for clean_var in ("IDF_PATH", "IDF_TOOLS_PATH"): + os.environ.pop(clean_var, None) + + cg.add_platformio_option("lib_ldf_mode", "off") + cg.add_platformio_option("lib_compat_mode", "strict") + cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION]) + cg.add_platformio_option("board", config[CONF_BOARD]) + cg.add_platformio_option("board_upload.flash_size", config[CONF_FLASH_SIZE]) + cg.add_platformio_option( + "board_upload.maximum_size", + int(config[CONF_FLASH_SIZE].removesuffix("MB")) * 1024 * 1024, + ) + + if CONF_SOURCE in conf: + cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) + + add_extra_script( + "pre", + "pre_build.py", + Path(__file__).parent / "pre_build.py.script", + ) + + add_extra_script( + "post", + "post_build.py", + Path(__file__).parent / "post_build.py.script", + ) + + # In testing mode, add IRAM fix script to allow linking grouped component tests + # Similar to ESP8266's approach but for ESP-IDF + if CORE.testing_mode: + cg.add_build_flag("-DESPHOME_TESTING_MODE") + add_extra_script( + "pre", + "iram_fix.py", + Path(__file__).parent / "iram_fix.py.script", + ) + else: + cg.add_build_flag("-Wno-error=format") + cg.set_cpp_standard("gnu++20") cg.add_build_flag("-DUSE_ESP32") cg.add_build_flag("-Wl,-z,noexecstack") @@ -977,79 +1022,49 @@ async def to_code(config): cg.add_define("ESPHOME_VARIANT", VARIANT_FRIENDLY[variant]) cg.add_define(ThreadModel.MULTI_ATOMICS) - cg.add_platformio_option("lib_ldf_mode", "off") - cg.add_platformio_option("lib_compat_mode", "strict") - - framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] - - conf = config[CONF_FRAMEWORK] - cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION]) - if CONF_SOURCE in conf: - cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]]) - if conf[CONF_ADVANCED][CONF_IGNORE_EFUSE_CUSTOM_MAC]: cg.add_define("USE_ESP32_IGNORE_EFUSE_CUSTOM_MAC") - for clean_var in ("IDF_PATH", "IDF_TOOLS_PATH"): - os.environ.pop(clean_var, None) - # Set the location of the IDF component manager cache os.environ["IDF_COMPONENT_CACHE_PATH"] = str( CORE.relative_internal_path(".espressif") ) - add_extra_script( - "pre", - "pre_build.py", - Path(__file__).parent / "pre_build.py.script", - ) - - add_extra_script( - "post", - "post_build.py", - Path(__file__).parent / "post_build.py.script", - ) - - # In testing mode, add IRAM fix script to allow linking grouped component tests - # Similar to ESP8266's approach but for ESP-IDF - if CORE.testing_mode: - cg.add_build_flag("-DESPHOME_TESTING_MODE") - add_extra_script( - "pre", - "iram_fix.py", - Path(__file__).parent / "iram_fix.py.script", - ) - if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: - cg.add_platformio_option("framework", "espidf") cg.add_build_flag("-DUSE_ESP_IDF") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF") + if use_platformio: + cg.add_platformio_option("framework", "espidf") else: - cg.add_platformio_option("framework", "arduino, espidf") cg.add_build_flag("-DUSE_ARDUINO") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO") + if use_platformio: + cg.add_platformio_option("framework", "arduino, espidf") + + # Add IDF framework source for Arduino builds to ensure it uses the same version as + # the ESP-IDF framework + if (idf_ver := ARDUINO_IDF_VERSION_LOOKUP.get(framework_ver)) is not None: + cg.add_platformio_option( + "platform_packages", + [_format_framework_espidf_version(idf_ver, None)], + ) + + # ESP32-S2 Arduino: Disable USB Serial on boot to avoid TinyUSB dependency + if get_esp32_variant() == VARIANT_ESP32S2: + cg.add_build_unflag("-DARDUINO_USB_CDC_ON_BOOT=1") + cg.add_build_unflag("-DARDUINO_USB_CDC_ON_BOOT=0") + cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=0") + cg.add_define( "USE_ARDUINO_VERSION_CODE", cg.RawExpression( f"VERSION_CODE({framework_ver.major}, {framework_ver.minor}, {framework_ver.patch})" ), ) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_PSK_MODES", True) add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True) - # Add IDF framework source for Arduino builds to ensure it uses the same version as - # the ESP-IDF framework - if (idf_ver := ARDUINO_IDF_VERSION_LOOKUP.get(framework_ver)) is not None: - cg.add_platformio_option( - "platform_packages", [_format_framework_espidf_version(idf_ver, None)] - ) - - # ESP32-S2 Arduino: Disable USB Serial on boot to avoid TinyUSB dependency - if get_esp32_variant() == VARIANT_ESP32S2: - cg.add_build_unflag("-DARDUINO_USB_CDC_ON_BOOT=1") - cg.add_build_unflag("-DARDUINO_USB_CDC_ON_BOOT=0") - cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=0") - cg.add_build_flag("-Wno-nonnull-compare") add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) @@ -1196,7 +1211,8 @@ async def to_code(config): "CONFIG_VFS_SUPPORT_DIR", not advanced[CONF_DISABLE_VFS_SUPPORT_DIR] ) - cg.add_platformio_option("board_build.partitions", "partitions.csv") + if use_platformio: + cg.add_platformio_option("board_build.partitions", "partitions.csv") if CONF_PARTITIONS in config: add_extra_build_file( "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS]) @@ -1361,19 +1377,16 @@ def copy_files(): _write_idf_component_yml() if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: + flash_size = CORE.data[KEY_ESP32][KEY_FLASH_SIZE] if CORE.using_arduino: write_file_if_changed( CORE.relative_build_path("partitions.csv"), - get_arduino_partition_csv( - CORE.platformio_options.get("board_upload.flash_size") - ), + get_arduino_partition_csv(flash_size), ) else: write_file_if_changed( CORE.relative_build_path("partitions.csv"), - get_idf_partition_csv( - CORE.platformio_options.get("board_upload.flash_size") - ), + get_idf_partition_csv(flash_size), ) # IDF build scripts look for version string to put in the build. # However, if the build path does not have an initialized git repo, diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index dfb736f615..2a9456db23 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -2,6 +2,7 @@ import esphome.codegen as cg KEY_ESP32 = "esp32" KEY_BOARD = "board" +KEY_FLASH_SIZE = "flash_size" KEY_VARIANT = "variant" KEY_SDKCONFIG_OPTIONS = "sdkconfig_options" KEY_COMPONENTS = "components" diff --git a/esphome/const.py b/esphome/const.py index c88d5811b4..d955387f7f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1379,6 +1379,7 @@ KEY_FRAMEWORK_VERSION = "framework_version" KEY_NAME = "name" KEY_VARIANT = "variant" KEY_PAST_SAFE_MODE = "past_safe_mode" +KEY_NATIVE_IDF = "native_idf" # Entity categories ENTITY_CATEGORY_NONE = "" diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 70593d8153..9a7dd49609 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -17,6 +17,7 @@ from esphome.const import ( CONF_WEB_SERVER, CONF_WIFI, KEY_CORE, + KEY_NATIVE_IDF, KEY_TARGET_FRAMEWORK, KEY_TARGET_PLATFORM, PLATFORM_BK72XX, @@ -763,6 +764,9 @@ class EsphomeCore: @property def firmware_bin(self) -> Path: + # Check if using native ESP-IDF build (--native-idf) + if self.data.get(KEY_NATIVE_IDF, False): + return self.relative_build_path("build", f"{self.name}.bin") if self.is_libretiny: return self.relative_pioenvs_path(self.name, "firmware.uf2") return self.relative_pioenvs_path(self.name, "firmware.bin") diff --git a/esphome/espidf_api.py b/esphome/espidf_api.py new file mode 100644 index 0000000000..9e9c57bfbd --- /dev/null +++ b/esphome/espidf_api.py @@ -0,0 +1,229 @@ +"""ESP-IDF direct build API for ESPHome.""" + +import json +import logging +import os +from pathlib import Path +import shutil +import subprocess + +from esphome.components.esp32.const import KEY_ESP32, KEY_FLASH_SIZE +from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME +from esphome.core import CORE, EsphomeError + +_LOGGER = logging.getLogger(__name__) + + +def _get_idf_path() -> Path | None: + """Get IDF_PATH from environment or common locations.""" + # Check environment variable first + if "IDF_PATH" in os.environ: + path = Path(os.environ["IDF_PATH"]) + if path.is_dir(): + return path + + # Check common installation locations + common_paths = [ + Path.home() / "esp" / "esp-idf", + Path.home() / ".espressif" / "esp-idf", + Path("/opt/esp-idf"), + ] + + for path in common_paths: + if path.is_dir() and (path / "tools" / "idf.py").is_file(): + return path + + return None + + +def _get_idf_env() -> dict[str, str]: + """Get environment variables needed for ESP-IDF build. + + Requires the user to have sourced export.sh before running esphome. + """ + env = os.environ.copy() + + idf_path = _get_idf_path() + if idf_path is None: + raise EsphomeError( + "ESP-IDF not found. Please install ESP-IDF and source export.sh:\n" + " git clone -b v5.3.2 --recursive https://github.com/espressif/esp-idf.git ~/esp-idf\n" + " cd ~/esp-idf && ./install.sh\n" + " source ~/esp-idf/export.sh\n" + "See: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/" + ) + + env["IDF_PATH"] = str(idf_path) + return env + + +def run_idf_py( + *args, cwd: Path | None = None, capture_output: bool = False +) -> int | str: + """Run idf.py with the given arguments.""" + idf_path = _get_idf_path() + if idf_path is None: + raise EsphomeError("ESP-IDF not found") + + env = _get_idf_env() + idf_py = idf_path / "tools" / "idf.py" + + cmd = ["python", str(idf_py)] + list(args) + + if cwd is None: + cwd = CORE.build_path + + _LOGGER.debug("Running: %s", " ".join(cmd)) + _LOGGER.debug(" in directory: %s", cwd) + + if capture_output: + result = subprocess.run( + cmd, + cwd=cwd, + env=env, + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0: + _LOGGER.error("idf.py failed:\n%s", result.stderr) + return result.stdout + result = subprocess.run( + cmd, + cwd=cwd, + env=env, + check=False, + ) + return result.returncode + + +def run_reconfigure() -> int: + """Run cmake reconfigure only (no build).""" + return run_idf_py("reconfigure") + + +def run_compile(config, verbose: bool) -> int: + """Compile the ESP-IDF project. + + Uses two-phase configure to auto-discover available components: + 1. If no previous build, configure with minimal REQUIRES to discover components + 2. Regenerate CMakeLists.txt with discovered components + 3. Run full build + """ + from esphome.build_gen.espidf import has_discovered_components, write_project + + # Check if we need to do discovery phase + if not has_discovered_components(): + _LOGGER.info("Discovering available ESP-IDF components...") + write_project(minimal=True) + rc = run_reconfigure() + if rc != 0: + _LOGGER.error("Component discovery failed") + return rc + _LOGGER.info("Regenerating CMakeLists.txt with discovered components...") + write_project(minimal=False) + + # Build + args = ["build"] + + if verbose: + args.append("-v") + + # Add parallel job limit if configured + if CONF_COMPILE_PROCESS_LIMIT in config.get(CONF_ESPHOME, {}): + limit = config[CONF_ESPHOME][CONF_COMPILE_PROCESS_LIMIT] + args.extend(["-j", str(limit)]) + + # Set the sdkconfig file + sdkconfig_path = CORE.relative_build_path(f"sdkconfig.{CORE.name}") + if sdkconfig_path.is_file(): + args.extend(["-D", f"SDKCONFIG={sdkconfig_path}"]) + + return run_idf_py(*args) + + +def get_firmware_path() -> Path: + """Get the path to the compiled firmware binary.""" + build_dir = CORE.relative_build_path("build") + return build_dir / f"{CORE.name}.bin" + + +def get_factory_firmware_path() -> Path: + """Get the path to the factory firmware (with bootloader).""" + build_dir = CORE.relative_build_path("build") + return build_dir / f"{CORE.name}.factory.bin" + + +def create_factory_bin() -> bool: + """Create factory.bin by merging bootloader, partition table, and app.""" + build_dir = CORE.relative_build_path("build") + flasher_args_path = build_dir / "flasher_args.json" + + if not flasher_args_path.is_file(): + _LOGGER.warning("flasher_args.json not found, cannot create factory.bin") + return False + + try: + with open(flasher_args_path, encoding="utf-8") as f: + flash_data = json.load(f) + except (json.JSONDecodeError, OSError) as e: + _LOGGER.error("Failed to read flasher_args.json: %s", e) + return False + + # Get flash size from config + flash_size = CORE.data[KEY_ESP32][KEY_FLASH_SIZE] + + # Build esptool merge command + sections = [] + for addr, fname in sorted( + flash_data.get("flash_files", {}).items(), key=lambda kv: int(kv[0], 16) + ): + file_path = build_dir / fname + if file_path.is_file(): + sections.extend([addr, str(file_path)]) + else: + _LOGGER.warning("Flash file not found: %s", file_path) + + if not sections: + _LOGGER.warning("No flash sections found") + return False + + output_path = get_factory_firmware_path() + chip = flash_data.get("extra_esptool_args", {}).get("chip", "esp32") + + cmd = [ + "python", + "-m", + "esptool", + "--chip", + chip, + "merge_bin", + "--flash_size", + flash_size, + "--output", + str(output_path), + ] + sections + + _LOGGER.info("Creating factory.bin...") + result = subprocess.run(cmd, capture_output=True, text=True, check=False) + + if result.returncode != 0: + _LOGGER.error("Failed to create factory.bin: %s", result.stderr) + return False + + _LOGGER.info("Created: %s", output_path) + return True + + +def create_ota_bin() -> bool: + """Copy the firmware to .ota.bin for ESPHome OTA compatibility.""" + firmware_path = get_firmware_path() + ota_path = firmware_path.with_suffix(".ota.bin") + + if not firmware_path.is_file(): + _LOGGER.warning("Firmware not found: %s", firmware_path) + return False + + shutil.copy(firmware_path, ota_path) + _LOGGER.info("Created: %s", ota_path) + return True From 307c3e1061f1854bb84cd899136de303d464a647 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:52:12 -1000 Subject: [PATCH 0261/2030] [core] Simplify LazyCallbackManager memory management (#13387) --- esphome/core/helpers.h | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 7de952a712..1b9d05748a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1345,16 +1345,30 @@ template class LazyCallbackManager; * * Memory overhead comparison (32-bit systems): * - CallbackManager: 12 bytes (empty std::vector) - * - LazyCallbackManager: 4 bytes (nullptr unique_ptr) + * - LazyCallbackManager: 4 bytes (nullptr pointer) + * + * Uses plain pointer instead of unique_ptr to avoid template instantiation overhead. + * The class is explicitly non-copyable/non-movable for Rule of Five compliance. * * @tparam Ts The arguments for the callbacks, wrapped in void(). */ template class LazyCallbackManager { public: + LazyCallbackManager() = default; + /// Destructor - clean up allocated CallbackManager if any. + /// In practice this never runs (entities live for device lifetime) but included for correctness. + ~LazyCallbackManager() { delete this->callbacks_; } + + // Non-copyable and non-movable (entities are never copied or moved) + LazyCallbackManager(const LazyCallbackManager &) = delete; + LazyCallbackManager &operator=(const LazyCallbackManager &) = delete; + LazyCallbackManager(LazyCallbackManager &&) = delete; + LazyCallbackManager &operator=(LazyCallbackManager &&) = delete; + /// Add a callback to the list. Allocates the underlying CallbackManager on first use. void add(std::function &&callback) { if (!this->callbacks_) { - this->callbacks_ = make_unique>(); + this->callbacks_ = new CallbackManager(); } this->callbacks_->add(std::move(callback)); } @@ -1376,7 +1390,7 @@ template class LazyCallbackManager { void operator()(Ts... args) { this->call(args...); } protected: - std::unique_ptr> callbacks_; + CallbackManager *callbacks_{nullptr}; }; /// Helper class to deduplicate items in a series of values. From 54d682532375346fc2d98a4131898fcfa998c0be Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:52:28 -1000 Subject: [PATCH 0262/2030] [esp32] [libretiny] Use stack buffer for preference comparison (#13398) --- esphome/components/esp32/preferences.cpp | 3 ++- esphome/components/libretiny/preferences.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index 08439746b6..4e0bb68133 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -181,7 +181,8 @@ class ESP32Preferences : public ESPPreferences { if (actual_len != to_save.len) { return true; } - auto stored_data = std::make_unique(actual_len); + // Most preferences are small, use stack buffer with heap fallback for large ones + SmallBufferWithHeapFallback<256> stored_data(actual_len); err = nvs_get_blob(nvs_handle, key_str, stored_data.get(), &actual_len); if (err != 0) { ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 68bc279767..978dcce3fa 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -166,8 +166,8 @@ class LibreTinyPreferences : public ESPPreferences { return true; } - // Allocate buffer on heap to avoid stack allocation for large data - auto stored_data = std::make_unique(kv.value_len); + // Most preferences are small, use stack buffer with heap fallback for large ones + SmallBufferWithHeapFallback<256> stored_data(kv.value_len); fdb_blob_make(&this->blob, stored_data.get(), kv.value_len); size_t actual_len = fdb_kv_get_blob(db, key_str, &this->blob); if (actual_len != kv.value_len) { From fbde91358c337e0d6806b851f297016c75d8ac48 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:52:43 -1000 Subject: [PATCH 0263/2030] [mdns] Use stack buffer for txt records on ESP32 (#13401) --- esphome/components/mdns/mdns_esp32.cpp | 7 ++++--- esphome/core/helpers.h | 14 ++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/esphome/components/mdns/mdns_esp32.cpp b/esphome/components/mdns/mdns_esp32.cpp index e6b43e59cb..3123f3b604 100644 --- a/esphome/components/mdns/mdns_esp32.cpp +++ b/esphome/components/mdns/mdns_esp32.cpp @@ -24,13 +24,14 @@ static void register_esp32(MDNSComponent *comp, StaticVector(service.txt_records.size()); + // Stack buffer for up to 16 txt records, heap fallback for more + SmallBufferWithHeapFallback<16, mdns_txt_item_t> txt_records(service.txt_records.size()); for (size_t i = 0; i < service.txt_records.size(); i++) { const auto &record = service.txt_records[i]; // key and value are either compile-time string literals in flash or pointers to dynamic_txt_values_ // Both remain valid for the lifetime of this function, and ESP-IDF makes internal copies - txt_records[i].key = MDNS_STR_ARG(record.key); - txt_records[i].value = MDNS_STR_ARG(record.value); + txt_records.get()[i].key = MDNS_STR_ARG(record.key); + txt_records.get()[i].value = MDNS_STR_ARG(record.value); } uint16_t port = const_cast &>(service.port).value(); err = mdns_service_add(nullptr, MDNS_STR_ARG(service.service_type), MDNS_STR_ARG(service.proto), port, diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 1b9d05748a..6c06757d8c 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -371,13 +371,15 @@ template class FixedVector { /// @brief Helper class for efficient buffer allocation - uses stack for small sizes, heap for large /// This is useful when most operations need a small buffer but occasionally need larger ones. /// The stack buffer avoids heap allocation in the common case, while heap fallback handles edge cases. -template class SmallBufferWithHeapFallback { +/// @tparam STACK_SIZE Number of elements in the stack buffer +/// @tparam T Element type (default: uint8_t) +template class SmallBufferWithHeapFallback { public: explicit SmallBufferWithHeapFallback(size_t size) { if (size <= STACK_SIZE) { this->buffer_ = this->stack_buffer_; } else { - this->heap_buffer_ = new uint8_t[size]; + this->heap_buffer_ = new T[size]; this->buffer_ = this->heap_buffer_; } } @@ -389,12 +391,12 @@ template class SmallBufferWithHeapFallback { SmallBufferWithHeapFallback(SmallBufferWithHeapFallback &&) = delete; SmallBufferWithHeapFallback &operator=(SmallBufferWithHeapFallback &&) = delete; - uint8_t *get() { return this->buffer_; } + T *get() { return this->buffer_; } private: - uint8_t stack_buffer_[STACK_SIZE]; - uint8_t *heap_buffer_{nullptr}; - uint8_t *buffer_; + T stack_buffer_[STACK_SIZE]; + T *heap_buffer_{nullptr}; + T *buffer_; }; ///@} From 346f3d38d5bb26540cc8d945949a065b2916c19c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:52:58 -1000 Subject: [PATCH 0264/2030] [logger] Use raw pointer for task log buffer to match tx_buffer pattern (#13402) --- esphome/components/logger/logger.cpp | 15 ++++++++------- esphome/components/logger/logger.h | 6 +++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 34430dbafa..3a726d4046 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -1,8 +1,5 @@ #include "logger.h" #include -#ifdef USE_ESPHOME_TASK_LOG_BUFFER -#include // For unique_ptr -#endif #include "esphome/core/application.h" #include "esphome/core/hal.h" @@ -199,7 +196,8 @@ inline uint8_t Logger::level_for(const char *tag) { Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate), tx_buffer_size_(tx_buffer_size) { // add 1 to buffer size for null terminator - this->tx_buffer_ = new char[this->tx_buffer_size_ + 1]; // NOLINT + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed + this->tx_buffer_ = new char[this->tx_buffer_size_ + 1]; #if defined(USE_ESP32) || defined(USE_LIBRETINY) this->main_task_ = xTaskGetCurrentTaskHandle(); #elif defined(USE_ZEPHYR) @@ -212,11 +210,14 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate void Logger::init_log_buffer(size_t total_buffer_size) { #ifdef USE_HOST // Host uses slot count instead of byte size - this->log_buffer_ = esphome::make_unique(total_buffer_size); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed + this->log_buffer_ = new logger::TaskLogBufferHost(total_buffer_size); #elif defined(USE_ESP32) - this->log_buffer_ = esphome::make_unique(total_buffer_size); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed + this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size); #elif defined(USE_LIBRETINY) - this->log_buffer_ = esphome::make_unique(total_buffer_size); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed + this->log_buffer_ = new logger::TaskLogBufferLibreTiny(total_buffer_size); #endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 3e8538c2ae..fe9cab4993 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -412,11 +412,11 @@ class Logger : public Component { #endif #ifdef USE_ESPHOME_TASK_LOG_BUFFER #ifdef USE_HOST - std::unique_ptr log_buffer_; // Will be initialized with init_log_buffer + logger::TaskLogBufferHost *log_buffer_{nullptr}; // Allocated once, never freed #elif defined(USE_ESP32) - std::unique_ptr log_buffer_; // Will be initialized with init_log_buffer + logger::TaskLogBuffer *log_buffer_{nullptr}; // Allocated once, never freed #elif defined(USE_LIBRETINY) - std::unique_ptr log_buffer_; // Will be initialized with init_log_buffer + logger::TaskLogBufferLibreTiny *log_buffer_{nullptr}; // Allocated once, never freed #endif #endif From 7a2734fae99b586973789ecbcb075084e43b61bb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:53:10 -1000 Subject: [PATCH 0265/2030] [libretiny] Disable unused LWIP statistics to save RAM and flash (#13404) --- esphome/components/libretiny/__init__.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 8318722b80..503ec7e167 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -382,4 +382,11 @@ async def component_to_code(config): "custom_options.sys_config#h", _BK7231N_SYS_CONFIG_OPTIONS ) + # Disable LWIP statistics to save RAM - not needed in production + # Must explicitly disable all sub-stats to avoid redefinition warnings + cg.add_platformio_option( + "custom_options.lwip", + ["LWIP_STATS=0", "MEM_STATS=0", "MEMP_STATS=0"], + ) + await cg.register_component(var, config) From 7e43abd86f9c88d0ed321355e0dfd1cf3c68acd5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:53:23 -1000 Subject: [PATCH 0266/2030] [web_server_idf] Use direct member for ListEntitiesIterator instead of unique_ptr (#13405) --- .../components/web_server_idf/web_server_idf.cpp | 14 +++++++------- esphome/components/web_server_idf/web_server_idf.h | 7 +++++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 55d2040a3a..abeda5fc46 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -487,7 +487,7 @@ void AsyncEventSource::deferrable_send_state(void *source, const char *event_typ AsyncEventSourceResponse::AsyncEventSourceResponse(const AsyncWebServerRequest *request, esphome::web_server_idf::AsyncEventSource *server, esphome::web_server::WebServer *ws) - : server_(server), web_server_(ws), entities_iterator_(new esphome::web_server::ListEntitiesIterator(ws, server)) { + : server_(server), web_server_(ws), entities_iterator_(ws, server) { httpd_req_t *req = *request; httpd_resp_set_status(req, HTTPD_200); @@ -531,12 +531,12 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(const AsyncWebServerRequest * } #endif - this->entities_iterator_->begin(ws->include_internal_); + this->entities_iterator_.begin(ws->include_internal_); // just dump them all up-front and take advantage of the deferred queue // on second thought that takes too long, but leaving the commented code here for debug purposes - // while(!this->entities_iterator_->completed()) { - // this->entities_iterator_->advance(); + // while(!this->entities_iterator_.completed()) { + // this->entities_iterator_.advance(); //} } @@ -634,8 +634,8 @@ void AsyncEventSourceResponse::process_buffer_() { void AsyncEventSourceResponse::loop() { process_buffer_(); process_deferred_queue_(); - if (!this->entities_iterator_->completed()) - this->entities_iterator_->advance(); + if (!this->entities_iterator_.completed()) + this->entities_iterator_.advance(); } bool AsyncEventSourceResponse::try_send_nodefer(const char *message, const char *event, uint32_t id, @@ -781,7 +781,7 @@ void AsyncEventSourceResponse::deferrable_send_state(void *source, const char *e message_generator_t *message_generator) { // allow all json "details_all" to go through before publishing bare state events, this avoids unnamed entries showing // up in the web GUI and reduces event load during initial connect - if (!entities_iterator_->completed() && 0 != strcmp(event_type, "state_detail_all")) + if (!this->entities_iterator_.completed() && 0 != strcmp(event_type, "state_detail_all")) return; if (source == nullptr) diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 2a334a11e3..a6c984792a 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -13,11 +13,14 @@ #include #include +#ifdef USE_WEBSERVER +#include "esphome/components/web_server/list_entities.h" +#endif + namespace esphome { #ifdef USE_WEBSERVER namespace web_server { class WebServer; -class ListEntitiesIterator; }; // namespace web_server #endif namespace web_server_idf { @@ -284,7 +287,7 @@ class AsyncEventSourceResponse { std::atomic fd_{}; std::vector deferred_queue_; esphome::web_server::WebServer *web_server_; - std::unique_ptr entities_iterator_; + esphome::web_server::ListEntitiesIterator entities_iterator_; std::string event_buffer_{""}; size_t event_bytes_sent_; uint16_t consecutive_send_failures_{0}; From fc16ad806aa939f8fdc28b816ef04a8b3afed34e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:53:36 -1000 Subject: [PATCH 0267/2030] [ci] Block sprintf/vsprintf usage, suggest snprintf alternatives (#13305) --- script/ci-custom.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/script/ci-custom.py b/script/ci-custom.py index ee2e73872c..01e197057a 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -732,6 +732,26 @@ def lint_no_heap_allocating_helpers(fname, match): ) +@lint_re_check( + # Match sprintf/vsprintf but not snprintf/vsnprintf + # [^\w] ensures we don't match the safe variants + r"[^\w](v?sprintf)\s*\(" + CPP_RE_EOL, + include=cpp_include, +) +def lint_no_sprintf(fname, match): + func = match.group(1) + safe_func = func.replace("sprintf", "snprintf") + return ( + f"{highlight(func + '()')} is not allowed in ESPHome. It has no buffer size limit " + f"and can cause buffer overflows.\n" + f"Please use one of these alternatives:\n" + f" - {highlight(safe_func + '(buf, sizeof(buf), fmt, ...)')} for general formatting\n" + f" - {highlight('buf_append_printf(buf, sizeof(buf), pos, fmt, ...)')} for " + f"offset-based formatting (also stores format strings in flash on ESP8266)\n" + f"(If strictly necessary, add `// NOLINT` to the end of the line)" + ) + + @lint_content_find_check( "ESP_LOG", include=["*.h", "*.tcc"], From 0b60fd0c8c6b9ff704b25e6730b1de6521b1d918 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 21:49:14 -1000 Subject: [PATCH 0268/2030] [core] Avoid heap allocation in str_equals_case_insensitive with string literals (#13312) --- esphome/core/helpers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 6c06757d8c..ed5c4911ad 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -572,6 +572,10 @@ template constexpr T convert_little_endian(T val) { bool str_equals_case_insensitive(const std::string &a, const std::string &b); /// Compare StringRefs for equality in case-insensitive manner. bool str_equals_case_insensitive(StringRef a, StringRef b); +/// Compare C strings for equality in case-insensitive manner (no heap allocation). +inline bool str_equals_case_insensitive(const char *a, const char *b) { return strcasecmp(a, b) == 0; } +inline bool str_equals_case_insensitive(const std::string &a, const char *b) { return strcasecmp(a.c_str(), b) == 0; } +inline bool str_equals_case_insensitive(const char *a, const std::string &b) { return strcasecmp(a, b.c_str()) == 0; } /// Check whether a string starts with a value. bool str_startswith(const std::string &str, const std::string &start); From 37eaf10f751ccb4f04d34c94953309b0e9ae84b4 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Wed, 21 Jan 2026 12:40:41 +0000 Subject: [PATCH 0269/2030] [audio] Bump esp-audio-libs to 2.0.3 (#13346) --- .clang-tidy.hash | 2 +- esphome/components/audio/__init__.py | 6 +++++- esphome/components/audio/audio_decoder.cpp | 2 +- esphome/idf_component.yml | 2 ++ platformio.ini | 2 -- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index b448915e27..75f0fc9c98 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -d15ae81646ac0ee76b2586716fe697f187281523ee6db566aed26542a9f98d1a +a34e66dce18eaf9d2d094fedf6b9799bbd9ec1e734f76a29544e3f6d61786c3e diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index 7b03e4b6a7..6c721652e1 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -1,4 +1,5 @@ import esphome.codegen as cg +from esphome.components.esp32 import add_idf_component import esphome.config_validation as cv from esphome.const import CONF_BITS_PER_SAMPLE, CONF_NUM_CHANNELS, CONF_SAMPLE_RATE import esphome.final_validate as fv @@ -165,4 +166,7 @@ def final_validate_audio_schema( async def to_code(config): - cg.add_library("esphome/esp-audio-libs", "2.0.1") + add_idf_component( + name="esphome/esp-audio-libs", + ref="2.0.3", + ) diff --git a/esphome/components/audio/audio_decoder.cpp b/esphome/components/audio/audio_decoder.cpp index d1ad571a52..8f514468c4 100644 --- a/esphome/components/audio/audio_decoder.cpp +++ b/esphome/components/audio/audio_decoder.cpp @@ -300,7 +300,7 @@ FileDecoderState AudioDecoder::decode_mp3_() { // Advance read pointer to match the offset for the syncword this->input_transfer_buffer_->decrease_buffer_length(offset); - uint8_t *buffer_start = this->input_transfer_buffer_->get_buffer_start(); + const uint8_t *buffer_start = this->input_transfer_buffer_->get_buffer_start(); buffer_length = (int) this->input_transfer_buffer_->available(); int err = esp_audio_libs::helix_decoder::MP3Decode(this->mp3_decoder_, &buffer_start, &buffer_length, diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index e19c1a1c87..9be787d0cd 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -1,6 +1,8 @@ dependencies: bblanchon/arduinojson: version: "7.4.2" + esphome/esp-audio-libs: + version: 2.0.3 espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: diff --git a/platformio.ini b/platformio.ini index a54aa0964c..62de5aa0d7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -154,7 +154,6 @@ lib_deps = makuna/NeoPixelBus@2.8.0 ; neopixelbus esphome/ESP32-audioI2S@2.3.0 ; i2s_audio droscy/esp_wireguard@0.4.2 ; wireguard - esphome/esp-audio-libs@2.0.1 ; audio kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word build_flags = @@ -178,7 +177,6 @@ lib_deps = ${common:idf.lib_deps} droscy/esp_wireguard@0.4.2 ; wireguard kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word - esphome/esp-audio-libs@2.0.1 ; audio build_flags = ${common:idf.build_flags} -Wno-nonnull-compare From 29555c0ddc3a6d637789f89cd4120667e945412c Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:32:55 -0500 Subject: [PATCH 0270/2030] =?UTF-8?q?[lvgl]=20Validate=20LVGL=20dropdown?= =?UTF-8?q?=20symbols=20require=20Unicode=20codepoint=20=E2=89=A5=200x100?= =?UTF-8?q?=20(#13394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/lvgl/widgets/dropdown.py | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/esphome/components/lvgl/widgets/dropdown.py b/esphome/components/lvgl/widgets/dropdown.py index 9ff183f3dd..ca89bb625b 100644 --- a/esphome/components/lvgl/widgets/dropdown.py +++ b/esphome/components/lvgl/widgets/dropdown.py @@ -1,3 +1,4 @@ +from esphome import codegen as cg import esphome.config_validation as cv from esphome.const import CONF_OPTIONS @@ -24,6 +25,34 @@ from .label import CONF_LABEL CONF_DROPDOWN = "dropdown" CONF_DROPDOWN_LIST = "dropdown_list" +# Example valid dropdown symbol (left arrow) for error messages +EXAMPLE_DROPDOWN_SYMBOL = "\U00002190" # ← + + +def dropdown_symbol_validator(value): + """ + Validate that the dropdown symbol is a single Unicode character + with a codepoint of 0x100 (256) or greater. + This is required because LVGL uses codepoints below 0x100 for internal symbols. + """ + value = cv.string(value) + # len(value) counts Unicode code points, not grapheme clusters or bytes + if len(value) != 1: + raise cv.Invalid( + f"Dropdown symbol must be a single character, got '{value}' with length {len(value)}" + ) + codepoint = ord(value) + if codepoint < 0x100: + # Format the example symbol as a Unicode escape for the error message + example_escape = f"\\U{ord(EXAMPLE_DROPDOWN_SYMBOL):08X}" + raise cv.Invalid( + f"Dropdown symbol must have a Unicode codepoint of 0x100 (256) or greater. " + f"'{value}' has codepoint {codepoint} (0x{codepoint:X}). " + f"Use a character like '{example_escape}' ({EXAMPLE_DROPDOWN_SYMBOL}) or other Unicode symbols with codepoint >= 0x100." + ) + return value + + lv_dropdown_t = LvSelect("LvDropdownType", parents=(LvCompound,)) lv_dropdown_list_t = LvType("lv_dropdown_list_t") @@ -33,7 +62,7 @@ dropdown_list_spec = WidgetType( DROPDOWN_BASE_SCHEMA = cv.Schema( { - cv.Optional(CONF_SYMBOL): lv_text, + cv.Optional(CONF_SYMBOL): dropdown_symbol_validator, cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int, cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text, cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec.parts), @@ -70,7 +99,7 @@ class DropdownType(WidgetType): if options := config.get(CONF_OPTIONS): lv_add(w.var.set_options(options)) if symbol := config.get(CONF_SYMBOL): - lv.dropdown_set_symbol(w.var.obj, await lv_text.process(symbol)) + lv.dropdown_set_symbol(w.var.obj, cg.safe_exp(symbol)) if (selected := config.get(CONF_SELECTED_INDEX)) is not None: value = await lv_int.process(selected) lv_add(w.var.set_selected_index(value, literal("LV_ANIM_OFF"))) From 5f2394ef80105bd911c80398624e454afc07a594 Mon Sep 17 00:00:00 2001 From: maikeljkwak Date: Wed, 21 Jan 2026 18:34:52 +0100 Subject: [PATCH 0271/2030] [hc8, mhz19] Moving constant CONF_WARMUP_TIME to const.py (#13392) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/hc8/sensor.py | 3 +-- esphome/components/mhz19/sensor.py | 2 +- esphome/const.py | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/hc8/sensor.py b/esphome/components/hc8/sensor.py index 90698b2661..2f39b47f3c 100644 --- a/esphome/components/hc8/sensor.py +++ b/esphome/components/hc8/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_BASELINE, CONF_CO2, CONF_ID, + CONF_WARMUP_TIME, DEVICE_CLASS_CARBON_DIOXIDE, ICON_MOLECULE_CO2, STATE_CLASS_MEASUREMENT, @@ -14,8 +15,6 @@ from esphome.const import ( DEPENDENCIES = ["uart"] -CONF_WARMUP_TIME = "warmup_time" - hc8_ns = cg.esphome_ns.namespace("hc8") HC8Component = hc8_ns.class_("HC8Component", cg.PollingComponent, uart.UARTDevice) HC8CalibrateAction = hc8_ns.class_("HC8CalibrateAction", automation.Action) diff --git a/esphome/components/mhz19/sensor.py b/esphome/components/mhz19/sensor.py index 1f698be404..2841afde7a 100644 --- a/esphome/components/mhz19/sensor.py +++ b/esphome/components/mhz19/sensor.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_CO2, CONF_ID, CONF_TEMPERATURE, + CONF_WARMUP_TIME, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_TEMPERATURE, ICON_MOLECULE_CO2, @@ -18,7 +19,6 @@ from esphome.const import ( DEPENDENCIES = ["uart"] CONF_AUTOMATIC_BASELINE_CALIBRATION = "automatic_baseline_calibration" -CONF_WARMUP_TIME = "warmup_time" CONF_DETECTION_RANGE = "detection_range" mhz19_ns = cg.esphome_ns.namespace("mhz19") diff --git a/esphome/const.py b/esphome/const.py index d955387f7f..4243b2e25d 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1086,6 +1086,7 @@ CONF_WAKEUP_PIN = "wakeup_pin" CONF_WAND_ID = "wand_id" CONF_WARM_WHITE = "warm_white" CONF_WARM_WHITE_COLOR_TEMPERATURE = "warm_white_color_temperature" +CONF_WARMUP_TIME = "warmup_time" CONF_WATCHDOG_THRESHOLD = "watchdog_threshold" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" CONF_WATER_HEATER = "water_heater" From 6014bba3d1a5a26f164b8eaf49263d66778acc4e Mon Sep 17 00:00:00 2001 From: Dawid Date: Wed, 21 Jan 2026 18:37:10 +0100 Subject: [PATCH 0272/2030] [zephyr] Small build fixes for the logger/gpio subsystems (#13242) Co-authored-by: dawret --- esphome/components/zephyr/gpio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/zephyr/gpio.h b/esphome/components/zephyr/gpio.h index c9540f4f01..94f25f02ac 100644 --- a/esphome/components/zephyr/gpio.h +++ b/esphome/components/zephyr/gpio.h @@ -2,7 +2,7 @@ #ifdef USE_ZEPHYR #include "esphome/core/hal.h" -struct device; +#include namespace esphome { namespace zephyr { From 333ace25c9f324a1bccd3edcefed0d7e4ea53a82 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 21 Jan 2026 18:41:56 +0100 Subject: [PATCH 0273/2030] [adc] Fix indent (#11933) --- esphome/components/adc/sensor.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index 607609bbc7..64dd22b0c3 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -160,21 +160,21 @@ async def to_code(config): zephyr_add_user("io-channels", f"<&adc {channel_id}>") zephyr_add_overlay( f""" -&adc {{ - #address-cells = <1>; - #size-cells = <0>; + &adc {{ + #address-cells = <1>; + #size-cells = <0>; - channel@{channel_id} {{ - reg = <{channel_id}>; - zephyr,gain = "{gain}"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; - zephyr,resolution = <14>; - zephyr,oversampling = <8>; - }}; -}}; -""" + channel@{channel_id} {{ + reg = <{channel_id}>; + zephyr,gain = "{gain}"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <14>; + zephyr,oversampling = <8>; + }}; + }}; + """ ) From 5345c96ff38c4e9b988679c9f133078d4c817440 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:18:37 -0500 Subject: [PATCH 0274/2030] [http_request] Fix verify_ssl: false not working on ESP32 (#13422) Co-authored-by: Claude Opus 4.5 --- esphome/components/http_request/__init__.py | 1 + esphome/components/http_request/http_request_idf.cpp | 2 +- esphome/components/http_request/http_request_idf.h | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index b133aa69b2..9f74fb1023 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -157,6 +157,7 @@ async def to_code(config): if CORE.is_esp32: cg.add(var.set_buffer_size_rx(config[CONF_BUFFER_SIZE_RX])) cg.add(var.set_buffer_size_tx(config[CONF_BUFFER_SIZE_TX])) + cg.add(var.set_verify_ssl(config[CONF_VERIFY_SSL])) if config.get(CONF_VERIFY_SSL): esp32.add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 1de947ba5b..eedd321d80 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -89,7 +89,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c config.max_redirection_count = this->redirect_limit_; config.auth_type = HTTP_AUTH_TYPE_BASIC; #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - if (secure) { + if (secure && this->verify_ssl_) { config.crt_bundle_attach = esp_crt_bundle_attach; } #endif diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 4dc4736423..0fae67f5bc 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -34,6 +34,7 @@ class HttpRequestIDF : public HttpRequestComponent { void set_buffer_size_rx(uint16_t buffer_size_rx) { this->buffer_size_rx_ = buffer_size_rx; } void set_buffer_size_tx(uint16_t buffer_size_tx) { this->buffer_size_tx_ = buffer_size_tx; } + void set_verify_ssl(bool verify_ssl) { this->verify_ssl_ = verify_ssl; } protected: std::shared_ptr perform(const std::string &url, const std::string &method, const std::string &body, @@ -42,6 +43,7 @@ class HttpRequestIDF : public HttpRequestComponent { // if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE uint16_t buffer_size_rx_{}; uint16_t buffer_size_tx_{}; + bool verify_ssl_{true}; /// @brief Monitors the http client events to gather response headers static esp_err_t http_event_handler(esp_http_client_event_t *evt); From e62368e058a15f35c69298af830de62ec85e688d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:19:36 -0500 Subject: [PATCH 0275/2030] [heatpumpir] Add ESP-IDF support, bump to 1.0.40 (#13042) --- .clang-tidy.hash | 2 +- esphome/components/heatpumpir/climate.py | 4 ++-- esphome/components/heatpumpir/heatpumpir.cpp | 2 +- esphome/components/heatpumpir/heatpumpir.h | 2 +- esphome/components/heatpumpir/ir_sender_esphome.cpp | 2 +- esphome/components/heatpumpir/ir_sender_esphome.h | 2 +- platformio.ini | 3 ++- tests/components/heatpumpir/test.esp32-idf.yaml | 4 ++++ 8 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 tests/components/heatpumpir/test.esp32-idf.yaml diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 75f0fc9c98..0204b50264 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -a34e66dce18eaf9d2d094fedf6b9799bbd9ec1e734f76a29544e3f6d61786c3e +c0335c9688ce9defb4a7d4446b93460547e22df055668bacd7d963c770f0c65f diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index ec6eac670f..0d760938d0 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -107,7 +107,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_MAX_TEMPERATURE): cv.temperature, } ), - cv.only_with_arduino, + cv.Any(cv.only_with_arduino, cv.only_on_esp32), ) @@ -126,6 +126,6 @@ async def to_code(config): cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE])) cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) - cg.add_library("tonia/HeatpumpIR", "1.0.37") + cg.add_library("tonia/HeatpumpIR", "1.0.40") if CORE.is_libretiny or CORE.is_esp32: CORE.add_platformio_option("lib_ignore", ["IRremoteESP8266"]) diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 67447a3123..1f1362f8d8 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -1,6 +1,6 @@ #include "heatpumpir.h" -#ifdef USE_ARDUINO +#if defined(USE_ARDUINO) || defined(USE_ESP32) #include #include "ir_sender_esphome.h" diff --git a/esphome/components/heatpumpir/heatpumpir.h b/esphome/components/heatpumpir/heatpumpir.h index ed43ffdc83..6270dd1e5a 100644 --- a/esphome/components/heatpumpir/heatpumpir.h +++ b/esphome/components/heatpumpir/heatpumpir.h @@ -1,6 +1,6 @@ #pragma once -#ifdef USE_ARDUINO +#if defined(USE_ARDUINO) || defined(USE_ESP32) #include "esphome/components/climate_ir/climate_ir.h" diff --git a/esphome/components/heatpumpir/ir_sender_esphome.cpp b/esphome/components/heatpumpir/ir_sender_esphome.cpp index 173d595119..f010c72dac 100644 --- a/esphome/components/heatpumpir/ir_sender_esphome.cpp +++ b/esphome/components/heatpumpir/ir_sender_esphome.cpp @@ -1,6 +1,6 @@ #include "ir_sender_esphome.h" -#ifdef USE_ARDUINO +#if defined(USE_ARDUINO) || defined(USE_ESP32) namespace esphome { namespace heatpumpir { diff --git a/esphome/components/heatpumpir/ir_sender_esphome.h b/esphome/components/heatpumpir/ir_sender_esphome.h index 944d0e859c..c4209145ba 100644 --- a/esphome/components/heatpumpir/ir_sender_esphome.h +++ b/esphome/components/heatpumpir/ir_sender_esphome.h @@ -1,6 +1,6 @@ #pragma once -#ifdef USE_ARDUINO +#if defined(USE_ARDUINO) || defined(USE_ESP32) #include "esphome/components/remote_base/remote_base.h" #include // arduino-heatpump library diff --git a/platformio.ini b/platformio.ini index 62de5aa0d7..b109284933 100644 --- a/platformio.ini +++ b/platformio.ini @@ -84,7 +84,7 @@ lib_deps = fastled/FastLED@3.9.16 ; fastled_base freekode/TM1651@1.0.1 ; tm1651 dudanov/MideaUART@1.1.9 ; midea - tonia/HeatpumpIR@1.0.37 ; heatpumpir + tonia/HeatpumpIR@1.0.40 ; heatpumpir build_flags = ${common.build_flags} -DUSE_ARDUINO @@ -177,6 +177,7 @@ lib_deps = ${common:idf.lib_deps} droscy/esp_wireguard@0.4.2 ; wireguard kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word + tonia/HeatpumpIR@1.0.40 ; heatpumpir build_flags = ${common:idf.build_flags} -Wno-nonnull-compare diff --git a/tests/components/heatpumpir/test.esp32-idf.yaml b/tests/components/heatpumpir/test.esp32-idf.yaml new file mode 100644 index 0000000000..e891f9dc85 --- /dev/null +++ b/tests/components/heatpumpir/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + remote_transmitter: !include ../../test_build_components/common/remote_transmitter/esp32-idf.yaml + +<<: !include common.yaml From 4abae8d445510467f4438760f324631111ffc942 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 09:37:04 -1000 Subject: [PATCH 0276/2030] Bump setuptools from 80.9.0 to 80.10.1 (#13429) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d6aa584237..47dd4b7473 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools==80.9.0", "wheel>=0.43,<0.46"] +requires = ["setuptools==80.10.1", "wheel>=0.43,<0.46"] build-backend = "setuptools.build_meta" [project] From 673f46f76195a356bf24d8769399c19682a6d95f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 09:37:18 -1000 Subject: [PATCH 0277/2030] Bump peter-evans/create-pull-request from 8.0.0 to 8.1.0 (#13430) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/sync-device-classes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 8c830d99c7..97fbf7aa9e 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -41,7 +41,7 @@ jobs: python script/run-in-env.py pre-commit run --all-files - name: Commit changes - uses: peter-evans/create-pull-request@98357b18bf14b5342f975ff684046ec3b2a07725 # v8.0.0 + uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0 with: commit-message: "Synchronise Device Classes from Home Assistant" committer: esphomebot From 11e0d536e4fa8f34dfdb57d7b19c77a0e2f9f581 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 21 Jan 2026 21:15:51 +0100 Subject: [PATCH 0278/2030] [debug] Print reg0 value from config if mismatched on nrf52 (#11867) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/debug/debug_zephyr.cpp | 52 +++++++++---------- esphome/core/helpers.h | 2 + .../components/debug/test.nrf52-adafruit.yaml | 4 ++ 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index 6a88522b0d..0291cc3061 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -132,6 +132,26 @@ void DebugComponent::log_partition_info_() { flash_area_foreach(fa_cb, nullptr); } +static const char *regout0_to_str(uint32_t value) { + switch (value) { + case (UICR_REGOUT0_VOUT_DEFAULT): + return "1.8V (default)"; + case (UICR_REGOUT0_VOUT_1V8): + return "1.8V"; + case (UICR_REGOUT0_VOUT_2V1): + return "2.1V"; + case (UICR_REGOUT0_VOUT_2V4): + return "2.4V"; + case (UICR_REGOUT0_VOUT_2V7): + return "2.7V"; + case (UICR_REGOUT0_VOUT_3V0): + return "3.0V"; + case (UICR_REGOUT0_VOUT_3V3): + return "3.3V"; + } + return "???V"; +} + size_t DebugComponent::get_device_info_(std::span buffer, size_t pos) { constexpr size_t size = DEVICE_INFO_BUFFER_SIZE; char *buf = buffer.data(); @@ -145,34 +165,14 @@ size_t DebugComponent::get_device_info_(std::span // Regulator stage 0 if (nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_HIGH) { const char *reg0_type = nrf_power_dcdcen_vddh_get(NRF_POWER) ? "DC/DC" : "LDO"; - const char *reg0_voltage; - switch (NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) { - case (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "1.8V (default)"; - break; - case (UICR_REGOUT0_VOUT_1V8 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "1.8V"; - break; - case (UICR_REGOUT0_VOUT_2V1 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "2.1V"; - break; - case (UICR_REGOUT0_VOUT_2V4 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "2.4V"; - break; - case (UICR_REGOUT0_VOUT_2V7 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "2.7V"; - break; - case (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "3.0V"; - break; - case (UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos): - reg0_voltage = "3.3V"; - break; - default: - reg0_voltage = "???V"; - } + const char *reg0_voltage = regout0_to_str((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) >> UICR_REGOUT0_VOUT_Pos); ESP_LOGD(TAG, "Regulator stage 0: %s, %s", reg0_type, reg0_voltage); pos = buf_append_printf(buf, size, pos, "|Regulator stage 0: %s, %s", reg0_type, reg0_voltage); +#ifdef USE_NRF52_REG0_VOUT + if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) >> UICR_REGOUT0_VOUT_Pos != USE_NRF52_REG0_VOUT) { + ESP_LOGE(TAG, "Regulator stage 0: expected %s", regout0_to_str(USE_NRF52_REG0_VOUT)); + } +#endif } else { ESP_LOGD(TAG, "Regulator stage 0: disabled"); pos = buf_append_printf(buf, size, pos, "|Regulator stage 0: disabled"); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index ed5c4911ad..1aa29fa3f7 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -17,6 +17,8 @@ #include #include +#include + #include "esphome/core/optional.h" #ifdef USE_ESP8266 diff --git a/tests/components/debug/test.nrf52-adafruit.yaml b/tests/components/debug/test.nrf52-adafruit.yaml index dade44d145..6a446634af 100644 --- a/tests/components/debug/test.nrf52-adafruit.yaml +++ b/tests/components/debug/test.nrf52-adafruit.yaml @@ -1 +1,5 @@ <<: !include common.yaml + +nrf52: + reg0: + voltage: 2.1V From 9d967b01c870716a2aaca116582604cc2295b2b3 Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Wed, 21 Jan 2026 21:32:39 +0100 Subject: [PATCH 0279/2030] Expose sockaddr to string formatter (#12351) --- esphome/components/socket/socket.cpp | 14 +++++++------- esphome/components/socket/socket.h | 3 +++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index bb94ecb675..fd8725b363 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -46,15 +46,15 @@ static inline const char *esphome_inet_ntop6(const void *addr, char *buf, size_t #endif // Format sockaddr into caller-provided buffer, returns length written (excluding null) -static size_t format_sockaddr_to(const struct sockaddr_storage &storage, std::span buf) { - if (storage.ss_family == AF_INET) { - const auto *addr = reinterpret_cast(&storage); +size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::span buf) { + if (addr_ptr->sa_family == AF_INET && len >= sizeof(const struct sockaddr_in)) { + const auto *addr = reinterpret_cast(addr_ptr); if (esphome_inet_ntop4(&addr->sin_addr, buf.data(), buf.size()) != nullptr) return strlen(buf.data()); } #if USE_NETWORK_IPV6 - else if (storage.ss_family == AF_INET6) { - const auto *addr = reinterpret_cast(&storage); + else if (addr_ptr->sa_family == AF_INET6 && len >= sizeof(sockaddr_in6)) { + const auto *addr = reinterpret_cast(addr_ptr); #ifndef USE_SOCKET_IMPL_LWIP_TCP // Format IPv4-mapped IPv6 addresses as regular IPv4 (not supported on ESP8266 raw TCP) if (addr->sin6_addr.un.u32_addr[0] == 0 && addr->sin6_addr.un.u32_addr[1] == 0 && @@ -78,7 +78,7 @@ size_t Socket::getpeername_to(std::span buf) { buf[0] = '\0'; return 0; } - return format_sockaddr_to(storage, buf); + return format_sockaddr_to(reinterpret_cast(&storage), len, buf); } size_t Socket::getsockname_to(std::span buf) { @@ -88,7 +88,7 @@ size_t Socket::getsockname_to(std::span buf) { buf[0] = '\0'; return 0; } - return format_sockaddr_to(storage, buf); + return format_sockaddr_to(reinterpret_cast(&storage), len, buf); } std::unique_ptr socket_ip(int type, int protocol) { diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index d74804fdb0..e8b0948acd 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -102,6 +102,9 @@ inline socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const st /// Set a sockaddr to the any address and specified port for the IP version used by socket_ip(). socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t port); +/// Format sockaddr into caller-provided buffer, returns length written (excluding null) +size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::span buf); + #if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) /// Delay that can be woken early by socket activity. /// On ESP8266, lwip callbacks set a flag and call esp_schedule() to wake the delay. From 8dd1aec60672f26d1ec2a2d16a576752bde14e64 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:17:11 -0500 Subject: [PATCH 0280/2030] [esp32] Add warning for experimental 400MHz on ESP32-P4 (#13433) Co-authored-by: Claude Opus 4.5 --- esphome/components/esp32/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 07446ab046..e23a70a373 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -182,6 +182,12 @@ def set_core_data(config): path=[CONF_CPU_FREQUENCY], ) + if variant == VARIANT_ESP32P4 and cpu_frequency == "400MHZ": + _LOGGER.warning( + "400MHz on ESP32-P4 is experimental and may not boot. " + "Consider using 360MHz instead. See https://github.com/esphome/esphome/issues/13425" + ) + CORE.data[KEY_ESP32] = {} CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP32 conf = config[CONF_FRAMEWORK] From ebf589560d88844dfd0c2bb56376124d18fba59e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 14:03:49 -1000 Subject: [PATCH 0281/2030] [wifi] Fix bk72xx manual_ip preventing API connection (#13426) --- esphome/components/wifi/wifi_component_libretiny.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 162ed4e835..cc9f4ec193 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -460,13 +460,15 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); } #endif - // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) + // For static IP configurations, GOT_IP event may not fire, so set connected state here +#ifdef USE_WIFI_MANUAL_IP if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_state = LTWiFiSTAState::CONNECTED; +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } +#endif } #endif break; From ce5ec7a78f3cc5be9871e8dd09c6b8c042d289d8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 14:04:07 -1000 Subject: [PATCH 0282/2030] [spi] Fix display init failure by marking displays as write-only for half-duplex mode (#13431) --- esphome/components/epaper_spi/display.py | 2 +- esphome/components/ili9xxx/display.py | 2 +- esphome/components/max7219/display.py | 2 +- esphome/components/max7219digit/display.py | 2 +- esphome/components/mipi_rgb/display.py | 2 +- esphome/components/mipi_spi/display.py | 4 +--- esphome/components/pcd8544/display.py | 2 +- esphome/components/qspi_dbi/display.py | 2 +- esphome/components/spi/__init__.py | 7 ++++++- esphome/components/spi/spi_esp_idf.cpp | 5 ++++- esphome/components/ssd1306_spi/display.py | 2 +- esphome/components/ssd1322_spi/display.py | 2 +- esphome/components/ssd1325_spi/display.py | 2 +- esphome/components/ssd1327_spi/display.py | 2 +- esphome/components/ssd1331_spi/display.py | 2 +- esphome/components/ssd1351_spi/display.py | 2 +- esphome/components/st7567_spi/display.py | 2 +- esphome/components/st7701s/display.py | 2 +- esphome/components/st7735/display.py | 2 +- esphome/components/st7789v/display.py | 2 +- esphome/components/st7920/display.py | 2 +- esphome/components/waveshare_epaper/display.py | 2 +- 22 files changed, 30 insertions(+), 24 deletions(-) diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index a77e291237..8cc7b2663c 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -190,7 +190,7 @@ async def to_code(config): # Rotation is handled by setting the transform display_config = {k: v for k, v in config.items() if k != CONF_ROTATION} await display.register_display(var, display_config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 9588bccd55..bfb2300f4f 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -223,7 +223,7 @@ async def to_code(config): var = cg.Pvariable(config[CONF_ID], rhs) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) if init_sequences := config.get(CONF_INIT_SEQUENCE): diff --git a/esphome/components/max7219/display.py b/esphome/components/max7219/display.py index c9d10f3c45..a434125148 100644 --- a/esphome/components/max7219/display.py +++ b/esphome/components/max7219/display.py @@ -29,7 +29,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index fef121ff10..e6d53efc5d 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -86,7 +86,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) diff --git a/esphome/components/mipi_rgb/display.py b/esphome/components/mipi_rgb/display.py index 96e167b2e6..084fe6de14 100644 --- a/esphome/components/mipi_rgb/display.py +++ b/esphome/components/mipi_rgb/display.py @@ -260,7 +260,7 @@ async def to_code(config): cg.add(var.set_enable_pins(enable)) if CONF_SPI_ID in config: - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) sequence, madctl = model.get_sequence(config) cg.add(var.set_init_sequence(sequence)) cg.add(var.set_madctl(madctl)) diff --git a/esphome/components/mipi_spi/display.py b/esphome/components/mipi_spi/display.py index 69bf133c68..8dccfa3a92 100644 --- a/esphome/components/mipi_spi/display.py +++ b/esphome/components/mipi_spi/display.py @@ -443,6 +443,4 @@ async def to_code(config): ) cg.add(var.set_writer(lambda_)) await display.register_display(var, config) - await spi.register_spi_device(var, config) - # Displays are write-only, set the SPI device to write-only as well - cg.add(var.set_write_only(True)) + await spi.register_spi_device(var, config, write_only=True) diff --git a/esphome/components/pcd8544/display.py b/esphome/components/pcd8544/display.py index 2c24b133da..9d993c2105 100644 --- a/esphome/components/pcd8544/display.py +++ b/esphome/components/pcd8544/display.py @@ -44,7 +44,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/qspi_dbi/display.py b/esphome/components/qspi_dbi/display.py index e4440c9b81..48d1f6d12e 100644 --- a/esphome/components/qspi_dbi/display.py +++ b/esphome/components/qspi_dbi/display.py @@ -161,7 +161,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) chip = DriverChip.chips[config[CONF_MODEL]] if chip.initsequence: diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index e890567abf..931882be8d 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -39,6 +39,7 @@ from esphome.const import ( ) from esphome.core import CORE, CoroPriority, coroutine_with_priority import esphome.final_validate as fv +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") @@ -448,9 +449,13 @@ def spi_device_schema( ) -async def register_spi_device(var, config): +async def register_spi_device( + var: cg.Pvariable, config: ConfigType, write_only: bool = False +) -> None: parent = await cg.get_variable(config[CONF_SPI_ID]) cg.add(var.set_spi_parent(parent)) + if write_only: + cg.add(var.set_write_only(True)) if cs_pin := config.get(CONF_CS_PIN): pin = await cg.gpio_pin_expression(cs_pin) cg.add(var.set_cs_pin(pin)) diff --git a/esphome/components/spi/spi_esp_idf.cpp b/esphome/components/spi/spi_esp_idf.cpp index a1837fa58d..107b6a3f1a 100644 --- a/esphome/components/spi/spi_esp_idf.cpp +++ b/esphome/components/spi/spi_esp_idf.cpp @@ -195,8 +195,11 @@ class SPIDelegateHw : public SPIDelegate { config.post_cb = nullptr; if (this->bit_order_ == BIT_ORDER_LSB_FIRST) config.flags |= SPI_DEVICE_BIT_LSBFIRST; - if (this->write_only_) + if (this->write_only_) { config.flags |= SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY; + ESP_LOGD(TAG, "SPI device with CS pin %d using half-duplex mode (write-only)", + Utility::get_pin_no(this->cs_pin_)); + } esp_err_t const err = spi_bus_add_device(this->channel_, &config, &this->handle_); if (err != ESP_OK) { ESP_LOGE(TAG, "Add device failed - err %X", err); diff --git a/esphome/components/ssd1306_spi/display.py b/esphome/components/ssd1306_spi/display.py index 4af41073d4..26953b4f39 100644 --- a/esphome/components/ssd1306_spi/display.py +++ b/esphome/components/ssd1306_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1306_base.setup_ssd1306(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1322_spi/display.py b/esphome/components/ssd1322_spi/display.py index 849e71abee..3d01caf874 100644 --- a/esphome/components/ssd1322_spi/display.py +++ b/esphome/components/ssd1322_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1322_base.setup_ssd1322(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1325_spi/display.py b/esphome/components/ssd1325_spi/display.py index e18db33c68..dbb9a14ac2 100644 --- a/esphome/components/ssd1325_spi/display.py +++ b/esphome/components/ssd1325_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1325_base.setup_ssd1325(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1327_spi/display.py b/esphome/components/ssd1327_spi/display.py index b622c098ec..f052764a91 100644 --- a/esphome/components/ssd1327_spi/display.py +++ b/esphome/components/ssd1327_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1327_base.setup_ssd1327(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1331_spi/display.py b/esphome/components/ssd1331_spi/display.py index 50895b3175..c16780302f 100644 --- a/esphome/components/ssd1331_spi/display.py +++ b/esphome/components/ssd1331_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1331_base.setup_ssd1331(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1351_spi/display.py b/esphome/components/ssd1351_spi/display.py index bd7033c3d4..2a6e984029 100644 --- a/esphome/components/ssd1351_spi/display.py +++ b/esphome/components/ssd1351_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1351_base.setup_ssd1351(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7567_spi/display.py b/esphome/components/st7567_spi/display.py index 305aa35024..02cd2c105c 100644 --- a/esphome/components/st7567_spi/display.py +++ b/esphome/components/st7567_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await st7567_base.setup_st7567(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index 3078158d25..a8b12dfa28 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -173,7 +173,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) sequence = [] for seq in config[CONF_INIT_SEQUENCE]: diff --git a/esphome/components/st7735/display.py b/esphome/components/st7735/display.py index 2761214315..9dc69f27ff 100644 --- a/esphome/components/st7735/display.py +++ b/esphome/components/st7735/display.py @@ -99,7 +99,7 @@ async def to_code(config): config[CONF_INVERT_COLORS], ) await setup_st7735(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index 8259eacf2d..c9f4199616 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -177,7 +177,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) cg.add(var.set_model_str(config[CONF_MODEL])) diff --git a/esphome/components/st7920/display.py b/esphome/components/st7920/display.py index de7b2247dd..ef33fac6c6 100644 --- a/esphome/components/st7920/display.py +++ b/esphome/components/st7920/display.py @@ -28,7 +28,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) if CONF_LAMBDA in config: lambda_ = await cg.process_lambda( diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index cea0b2be5e..5db7a1fc3d 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -239,7 +239,7 @@ async def to_code(config): raise NotImplementedError() await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) From 19c1d3aee70133d9e59564791c522bdac5b6c29b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 20:41:59 -0500 Subject: [PATCH 0283/2030] [esp32] Bump Arduino to 3.3.6, platform to 55.03.36 (#13438) Co-authored-by: Claude Opus 4.5 --- .clang-tidy.hash | 2 +- esphome/components/esp32/__init__.py | 23 +++++++++++++++-------- esphome/core/defines.h | 2 +- platformio.ini | 6 +++--- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 0204b50264..0a272d21ba 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -c0335c9688ce9defb4a7d4446b93460547e22df055668bacd7d963c770f0c65f +15dc295268b2dcf75942f42759b3ddec64eba89f75525698eb39c95a7f4b14ce diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index e23a70a373..da49fdc070 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -348,7 +348,12 @@ def add_extra_build_file(filename: str, path: Path) -> bool: def _format_framework_arduino_version(ver: cv.Version) -> str: # format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to # a PIO pioarduino/framework-arduinoespressif32 value - return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{str(ver)}/esp32-{str(ver)}.zip" + # 3.3.6+ changed filename from esp32-{ver}.zip to esp32-core-{ver}.tar.xz + if ver >= cv.Version(3, 3, 6): + filename = f"esp32-core-{ver}.tar.xz" + else: + filename = f"esp32-{ver}.zip" + return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{ver}/{filename}" def _format_framework_espidf_version(ver: cv.Version, release: str) -> str: @@ -383,11 +388,12 @@ def _is_framework_url(source: str) -> bool: # The default/recommended arduino framework version # - https://github.com/espressif/arduino-esp32/releases ARDUINO_FRAMEWORK_VERSION_LOOKUP = { - "recommended": cv.Version(3, 3, 5), - "latest": cv.Version(3, 3, 5), - "dev": cv.Version(3, 3, 5), + "recommended": cv.Version(3, 3, 6), + "latest": cv.Version(3, 3, 6), + "dev": cv.Version(3, 3, 6), } ARDUINO_PLATFORM_VERSION_LOOKUP = { + cv.Version(3, 3, 6): cv.Version(55, 3, 36), cv.Version(3, 3, 5): cv.Version(55, 3, 35), cv.Version(3, 3, 4): cv.Version(55, 3, 31, "2"), cv.Version(3, 3, 3): cv.Version(55, 3, 31, "2"), @@ -405,6 +411,7 @@ ARDUINO_PLATFORM_VERSION_LOOKUP = { # These versions correspond to pioarduino/esp-idf releases # See: https://github.com/pioarduino/esp-idf/releases ARDUINO_IDF_VERSION_LOOKUP = { + cv.Version(3, 3, 6): cv.Version(5, 5, 2), cv.Version(3, 3, 5): cv.Version(5, 5, 2), cv.Version(3, 3, 4): cv.Version(5, 5, 1), cv.Version(3, 3, 3): cv.Version(5, 5, 1), @@ -427,7 +434,7 @@ ESP_IDF_FRAMEWORK_VERSION_LOOKUP = { "dev": cv.Version(5, 5, 2), } ESP_IDF_PLATFORM_VERSION_LOOKUP = { - cv.Version(5, 5, 2): cv.Version(55, 3, 35), + cv.Version(5, 5, 2): cv.Version(55, 3, 36), cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"), cv.Version(5, 5, 0): cv.Version(55, 3, 31, "2"), cv.Version(5, 4, 3): cv.Version(55, 3, 32), @@ -444,9 +451,9 @@ ESP_IDF_PLATFORM_VERSION_LOOKUP = { # The platform-espressif32 version # - https://github.com/pioarduino/platform-espressif32/releases PLATFORM_VERSION_LOOKUP = { - "recommended": cv.Version(55, 3, 35), - "latest": cv.Version(55, 3, 35), - "dev": cv.Version(55, 3, 35), + "recommended": cv.Version(55, 3, 36), + "latest": cv.Version(55, 3, 36), + "dev": cv.Version(55, 3, 36), } diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c229d1df7d..7c13823fba 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -234,7 +234,7 @@ #define USB_HOST_MAX_REQUESTS 16 #ifdef USE_ARDUINO -#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 5) +#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 6) #define USE_ETHERNET #define USE_ETHERNET_KSZ8081 #define USE_ETHERNET_MANUAL_IP diff --git a/platformio.ini b/platformio.ini index b109284933..e9a588e4fd 100644 --- a/platformio.ini +++ b/platformio.ini @@ -133,9 +133,9 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script ; This are common settings for the ESP32 (all variants) using Arduino. [common:esp32-arduino] extends = common:arduino -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.35/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip platform_packages = - pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.5/esp32-3.3.5.zip + pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6.tar.xz framework = arduino, espidf ; Arduino as an ESP-IDF component lib_deps = @@ -168,7 +168,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script ; This are common settings for the ESP32 (all variants) using IDF. [common:esp32-idf] extends = common:idf -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.35/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip platform_packages = pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz From 645832a0708573c8763ee50b7fc5564fabb619ea Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 22 Jan 2026 03:10:12 +0100 Subject: [PATCH 0284/2030] [nextion] Add configurable startup and queue timeout constants (#11098) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: J. Nick Koston Co-authored-by: Keith Burzinski --- esphome/components/nextion/base_component.py | 2 ++ esphome/components/nextion/display.py | 18 ++++++++++ esphome/components/nextion/nextion.cpp | 36 ++++++++++++-------- esphome/components/nextion/nextion.h | 29 ++++++++++++++-- tests/components/nextion/common.yaml | 2 ++ 5 files changed, 70 insertions(+), 17 deletions(-) diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 392481e39a..86551cbe23 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -16,6 +16,7 @@ CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start" CONF_FONT_ID = "font_id" CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color" CONF_MAX_COMMANDS_PER_LOOP = "max_commands_per_loop" +CONF_MAX_QUEUE_AGE = "max_queue_age" CONF_MAX_QUEUE_SIZE = "max_queue_size" CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow" CONF_ON_PAGE = "on_page" @@ -25,6 +26,7 @@ CONF_ON_WAKE = "on_wake" CONF_PRECISION = "precision" CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake" CONF_START_UP_PAGE = "start_up_page" +CONF_STARTUP_OVERRIDE_MS = "startup_override_ms" CONF_TFT_URL = "tft_url" CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout" CONF_VARIABLE_NAME = "variable_name" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 0b4ba3a171..ffc509fc64 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -23,6 +23,7 @@ from .base_component import ( CONF_DUMP_DEVICE_INFO, CONF_EXIT_REPARSE_ON_START, CONF_MAX_COMMANDS_PER_LOOP, + CONF_MAX_QUEUE_AGE, CONF_MAX_QUEUE_SIZE, CONF_ON_BUFFER_OVERFLOW, CONF_ON_PAGE, @@ -31,6 +32,7 @@ from .base_component import ( CONF_ON_WAKE, CONF_SKIP_CONNECTION_HANDSHAKE, CONF_START_UP_PAGE, + CONF_STARTUP_OVERRIDE_MS, CONF_TFT_URL, CONF_TOUCH_SLEEP_TIMEOUT, CONF_WAKE_UP_PAGE, @@ -65,6 +67,12 @@ CONFIG_SCHEMA = ( ), cv.Optional(CONF_DUMP_DEVICE_INFO, default=False): cv.boolean, cv.Optional(CONF_EXIT_REPARSE_ON_START, default=False): cv.boolean, + cv.Optional(CONF_MAX_QUEUE_AGE, default="8000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=TimePeriod(milliseconds=0), max=TimePeriod(milliseconds=65535) + ), + ), cv.Optional(CONF_MAX_COMMANDS_PER_LOOP): cv.uint16_t, cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int, cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation( @@ -100,6 +108,12 @@ CONFIG_SCHEMA = ( } ), cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean, + cv.Optional(CONF_STARTUP_OVERRIDE_MS, default="8000ms"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range( + min=TimePeriod(milliseconds=0), max=TimePeriod(milliseconds=65535) + ), + ), cv.Optional(CONF_START_UP_PAGE): cv.uint8_t, cv.Optional(CONF_TFT_URL): cv.url, cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.Any( @@ -138,6 +152,8 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await uart.register_uart_device(var, config) + cg.add(var.set_max_queue_age(config[CONF_MAX_QUEUE_AGE])) + if max_queue_size := config.get(CONF_MAX_QUEUE_SIZE): cg.add_define("USE_NEXTION_MAX_QUEUE_SIZE") cg.add(var.set_max_queue_size(max_queue_size)) @@ -146,6 +162,8 @@ async def to_code(config): cg.add_define("USE_NEXTION_COMMAND_SPACING") cg.add(var.set_command_spacing(command_spacing.total_milliseconds)) + cg.add(var.set_startup_override_ms(config[CONF_STARTUP_OVERRIDE_MS])) + if CONF_BRIGHTNESS in config: cg.add(var.set_brightness(config[CONF_BRIGHTNESS])) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 354288e1a3..4bba33f961 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -152,21 +152,25 @@ void Nextion::dump_config() { #else // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE ESP_LOGCONFIG(TAG, #ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - " Device Model: %s\n" - " FW Version: %s\n" - " Serial Number: %s\n" - " Flash Size: %s\n" + " Device Model: %s\n" + " FW Version: %s\n" + " Serial Number: %s\n" + " Flash Size: %s\n" + " Max queue age: %u ms\n" + " Startup override: %u ms\n", #endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO #ifdef USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START - " Exit reparse: YES\n" + " Exit reparse: YES\n" #endif // USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START - " Wake On Touch: %s\n" - " Touch Timeout: %" PRIu16, + " Wake On Touch: %s\n" + " Touch Timeout: %" PRIu16, #ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO this->device_model_.c_str(), this->firmware_version_.c_str(), this->serial_number_.c_str(), - this->flash_size_.c_str(), + this->flash_size_.c_str(), this->max_q_age_ms_, + this->startup_override_ms_ #endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - YESNO(this->connection_state_.auto_wake_on_touch_), this->touch_sleep_timeout_); + YESNO(this->connection_state_.auto_wake_on_touch_), + this->touch_sleep_timeout_); #endif // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP @@ -174,21 +178,21 @@ void Nextion::dump_config() { #endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP if (this->wake_up_page_ != 255) { - ESP_LOGCONFIG(TAG, " Wake Up Page: %u", this->wake_up_page_); + ESP_LOGCONFIG(TAG, " Wake Up Page: %u", this->wake_up_page_); } #ifdef USE_NEXTION_CONF_START_UP_PAGE if (this->start_up_page_ != 255) { - ESP_LOGCONFIG(TAG, " Start Up Page: %u", this->start_up_page_); + ESP_LOGCONFIG(TAG, " Start Up Page: %u", this->start_up_page_); } #endif // USE_NEXTION_CONF_START_UP_PAGE #ifdef USE_NEXTION_COMMAND_SPACING - ESP_LOGCONFIG(TAG, " Cmd spacing: %u ms", this->command_pacer_.get_spacing()); + ESP_LOGCONFIG(TAG, " Cmd spacing: %u ms", this->command_pacer_.get_spacing()); #endif // USE_NEXTION_COMMAND_SPACING #ifdef USE_NEXTION_MAX_QUEUE_SIZE - ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_); + ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_); #endif } @@ -336,7 +340,8 @@ void Nextion::loop() { if (this->started_ms_ == 0) this->started_ms_ = App.get_loop_component_start_time(); - if (this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { + if (this->startup_override_ms_ > 0 && + this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { ESP_LOGV(TAG, "Manual ready set"); this->connection_state_.nextion_reports_is_setup_ = true; } @@ -845,7 +850,8 @@ void Nextion::process_nextion_commands_() { const uint32_t ms = App.get_loop_component_start_time(); - if (!this->nextion_queue_.empty() && this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) { + if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() && + this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) { for (size_t i = 0; i < this->nextion_queue_.size(); i++) { NextionComponentBase *component = this->nextion_queue_[i]->component; if (this->nextion_queue_[i]->queue_time + this->max_q_age_ms_ < ms) { diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 331e901578..c543e14bfe 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1309,6 +1309,30 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ bool is_connected() { return this->connection_state_.is_connected_; } + /** + * @brief Set the maximum age for queue items + * @param age_ms Maximum age in milliseconds before queue items are removed + */ + inline void set_max_queue_age(uint16_t age_ms) { this->max_q_age_ms_ = age_ms; } + + /** + * @brief Get the maximum age for queue items + * @return Maximum age in milliseconds + */ + inline uint16_t get_max_queue_age() const { return this->max_q_age_ms_; } + + /** + * @brief Set the startup override timeout + * @param timeout_ms Time in milliseconds to wait before forcing setup complete + */ + inline void set_startup_override_ms(uint16_t timeout_ms) { this->startup_override_ms_ = timeout_ms; } + + /** + * @brief Get the startup override timeout + * @return Startup override timeout in milliseconds + */ + inline uint16_t get_startup_override_ms() const { return this->startup_override_ms_; } + protected: #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP uint16_t max_commands_per_loop_{1000}; @@ -1479,9 +1503,10 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void reset_(bool reset_nextion = true); std::string command_data_; - const uint16_t startup_override_ms_ = 8000; - const uint16_t max_q_age_ms_ = 8000; uint32_t started_ms_ = 0; + + uint16_t startup_override_ms_ = 8000; ///< Timeout before forcing setup complete + uint16_t max_q_age_ms_ = 8000; ///< Maximum age for queue items in ms }; } // namespace nextion diff --git a/tests/components/nextion/common.yaml b/tests/components/nextion/common.yaml index f5ee12a51c..48a7292f43 100644 --- a/tests/components/nextion/common.yaml +++ b/tests/components/nextion/common.yaml @@ -277,6 +277,8 @@ display: command_spacing: 5ms max_commands_per_loop: 20 max_queue_size: 50 + startup_override_ms: 10000ms # Wait 10s for display ready + max_queue_age: 5000ms # Remove queue items after 5s on_sleep: then: lambda: 'ESP_LOGD("display","Display went to sleep");' From aa5092bdc272bf93bd7b675438608dda3f41b517 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:35:43 -1000 Subject: [PATCH 0285/2030] [mqtt] Use stack buffers for discovery message formatting (#13216) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/mqtt/custom_mqtt_device.cpp | 2 +- esphome/components/mqtt/mqtt_client.cpp | 12 ++++- esphome/components/mqtt/mqtt_component.cpp | 49 +++++++++++++------ esphome/components/mqtt/mqtt_fan.cpp | 2 +- esphome/components/mqtt/mqtt_number.cpp | 2 +- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/esphome/components/mqtt/custom_mqtt_device.cpp b/esphome/components/mqtt/custom_mqtt_device.cpp index 7ff65bb42c..64521f5cf3 100644 --- a/esphome/components/mqtt/custom_mqtt_device.cpp +++ b/esphome/components/mqtt/custom_mqtt_device.cpp @@ -18,7 +18,7 @@ bool CustomMQTTDevice::publish(const std::string &topic, float value, int8_t num } bool CustomMQTTDevice::publish(const std::string &topic, int value) { char buffer[24]; - int len = snprintf(buffer, sizeof(buffer), "%d", value); + size_t len = buf_append_printf(buffer, sizeof(buffer), 0, "%d", value); return global_mqtt_client->publish(topic, buffer, len); } bool CustomMQTTDevice::publish_json(const std::string &topic, const json::json_build_t &f, uint8_t qos, bool retain) { diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index de79b61358..e7364f3406 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -98,7 +98,17 @@ void MQTTClientComponent::send_device_info_() { uint8_t index = 0; for (auto &ip : network::get_ip_addresses()) { if (ip.is_set()) { - root["ip" + (index == 0 ? "" : esphome::to_string(index))] = ip.str(); + char key[8]; // "ip" + up to 3 digits + null + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + if (index == 0) { + key[0] = 'i'; + key[1] = 'p'; + key[2] = '\0'; + } else { + buf_append_printf(key, sizeof(key), 0, "ip%u", index); + } + ip.str_to(ip_buf); + root[key] = ip_buf; index++; } } diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 2ba466af3b..cb8b92cad0 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -190,27 +190,37 @@ bool MQTTComponent::send_discovery_() { StringRef object_id = this->get_default_object_id_to_(object_id_buf); if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) { char friendly_name_hash[9]; - snprintf(friendly_name_hash, sizeof(friendly_name_hash), "%08" PRIx32, fnv1_hash(this->friendly_name_())); + buf_append_printf(friendly_name_hash, sizeof(friendly_name_hash), 0, "%08" PRIx32, + fnv1_hash(this->friendly_name_())); // Format: mac-component_type-hash (e.g. "aabbccddeeff-sensor-12345678") // MAC (12) + "-" (1) + domain (max 20) + "-" (1) + hash (8) + null (1) = 43 char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11]; char mac_buf[MAC_ADDRESS_BUFFER_SIZE]; get_mac_address_into_buffer(mac_buf); - snprintf(unique_id, sizeof(unique_id), "%s-%s-%s", mac_buf, this->component_type(), friendly_name_hash); + buf_append_printf(unique_id, sizeof(unique_id), 0, "%s-%s-%s", mac_buf, this->component_type(), + friendly_name_hash); root[MQTT_UNIQUE_ID] = unique_id; } else { // default to almost-unique ID. It's a hack but the only way to get that // gorgeous device registry view. - root[MQTT_UNIQUE_ID] = "ESP" + std::string(this->component_type()) + object_id.c_str(); + // "ESP" (3) + component_type (max 20) + object_id (max 128) + null + char unique_id_buf[3 + MQTT_COMPONENT_TYPE_MAX_LEN + OBJECT_ID_MAX_LEN + 1]; + buf_append_printf(unique_id_buf, sizeof(unique_id_buf), 0, "ESP%s%s", this->component_type(), + object_id.c_str()); + root[MQTT_UNIQUE_ID] = unique_id_buf; } const std::string &node_name = App.get_name(); - if (discovery_info.object_id_generator == MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR) - root[MQTT_OBJECT_ID] = node_name + "_" + object_id.c_str(); + if (discovery_info.object_id_generator == MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR) { + // node_name (max 31) + "_" (1) + object_id (max 128) + null + char object_id_full[ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1]; + buf_append_printf(object_id_full, sizeof(object_id_full), 0, "%s_%s", node_name.c_str(), object_id.c_str()); + root[MQTT_OBJECT_ID] = object_id_full; + } const std::string &friendly_name_ref = App.get_friendly_name(); const std::string &node_friendly_name = friendly_name_ref.empty() ? node_name : friendly_name_ref; - std::string node_area = App.get_area(); + const char *node_area = App.get_area(); JsonObject device_info = root[MQTT_DEVICE].to(); char mac[MAC_ADDRESS_BUFFER_SIZE]; @@ -221,18 +231,29 @@ bool MQTTComponent::send_discovery_() { device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_PROJECT_VERSION " (ESPHome " ESPHOME_VERSION ")"; const char *model = std::strchr(ESPHOME_PROJECT_NAME, '.'); device_info[MQTT_DEVICE_MODEL] = model == nullptr ? ESPHOME_BOARD : model + 1; - device_info[MQTT_DEVICE_MANUFACTURER] = - model == nullptr ? ESPHOME_PROJECT_NAME : std::string(ESPHOME_PROJECT_NAME, model - ESPHOME_PROJECT_NAME); + if (model == nullptr) { + device_info[MQTT_DEVICE_MANUFACTURER] = ESPHOME_PROJECT_NAME; + } else { + // Extract manufacturer (part before '.') using stack buffer to avoid heap allocation + // memcpy is used instead of strncpy since we know the exact length and strncpy + // would still require manual null-termination + char manufacturer[sizeof(ESPHOME_PROJECT_NAME)]; + size_t len = model - ESPHOME_PROJECT_NAME; + memcpy(manufacturer, ESPHOME_PROJECT_NAME, len); + manufacturer[len] = '\0'; + device_info[MQTT_DEVICE_MANUFACTURER] = manufacturer; + } #else static const char ver_fmt[] PROGMEM = ESPHOME_VERSION " (config hash 0x%08" PRIx32 ")"; + // Buffer sized for format string expansion: ~4 bytes net growth from format specifier to 8 hex digits, plus + // safety margin + char version_buf[sizeof(ver_fmt) + 8]; #ifdef USE_ESP8266 - char fmt_buf[sizeof(ver_fmt)]; - strcpy_P(fmt_buf, ver_fmt); - const char *fmt = fmt_buf; + snprintf_P(version_buf, sizeof(version_buf), ver_fmt, App.get_config_hash()); #else - const char *fmt = ver_fmt; + snprintf(version_buf, sizeof(version_buf), ver_fmt, App.get_config_hash()); #endif - device_info[MQTT_DEVICE_SW_VERSION] = str_sprintf(fmt, App.get_config_hash()); + device_info[MQTT_DEVICE_SW_VERSION] = version_buf; device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD; #if defined(USE_ESP8266) || defined(USE_ESP32) device_info[MQTT_DEVICE_MANUFACTURER] = "Espressif"; @@ -246,7 +267,7 @@ bool MQTTComponent::send_discovery_() { device_info[MQTT_DEVICE_MANUFACTURER] = "Host"; #endif #endif - if (!node_area.empty()) { + if (node_area[0] != '\0') { device_info[MQTT_DEVICE_SUGGESTED_AREA] = node_area; } diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index a6f0503588..0909090023 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -175,7 +175,7 @@ bool MQTTFanComponent::publish_state() { auto traits = this->state_->get_traits(); if (traits.supports_speed()) { char buf[12]; - int len = snprintf(buf, sizeof(buf), "%d", this->state_->speed); + size_t len = buf_append_printf(buf, sizeof(buf), 0, "%d", this->state_->speed); bool success = this->publish(this->get_speed_level_state_topic(), buf, len); failed = failed || !success; } diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index 8342210ee4..471c0d1208 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -75,7 +75,7 @@ bool MQTTNumberComponent::send_initial_state() { } bool MQTTNumberComponent::publish_state(float value) { char buffer[64]; - snprintf(buffer, sizeof(buffer), "%f", value); + buf_append_printf(buffer, sizeof(buffer), 0, "%f", value); return this->publish(this->get_state_topic_(), buffer); } From 99aa83564e9e2961b2d771da3b8262ed6df01a7f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:35:59 -1000 Subject: [PATCH 0286/2030] [mqtt] Reduce heap allocations in hot paths (#13362) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../mqtt/mqtt_alarm_control_panel.cpp | 2 +- .../components/mqtt/mqtt_binary_sensor.cpp | 2 +- esphome/components/mqtt/mqtt_component.cpp | 101 ++++++++++++------ esphome/components/mqtt/mqtt_component.h | 69 ++++++++---- esphome/components/mqtt/mqtt_cover.cpp | 2 +- esphome/components/mqtt/mqtt_date.cpp | 2 +- esphome/components/mqtt/mqtt_datetime.cpp | 2 +- esphome/components/mqtt/mqtt_light.cpp | 2 +- esphome/components/mqtt/mqtt_number.cpp | 2 +- esphome/components/mqtt/mqtt_select.cpp | 2 +- esphome/components/mqtt/mqtt_sensor.cpp | 2 +- esphome/components/mqtt/mqtt_text.cpp | 2 +- esphome/components/mqtt/mqtt_time.cpp | 2 +- esphome/components/mqtt/mqtt_valve.cpp | 2 +- esphome/core/automation.h | 57 ++++++++-- 15 files changed, 179 insertions(+), 72 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index 6245d10882..715e6feed8 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -43,7 +43,7 @@ void MQTTAlarmControlPanelComponent::setup() { void MQTTAlarmControlPanelComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT alarm_control_panel '%s':", this->alarm_control_panel_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); ESP_LOGCONFIG(TAG, " Supported Features: %" PRIu32 "\n" " Requires Code to Disarm: %s\n" diff --git a/esphome/components/mqtt/mqtt_binary_sensor.cpp b/esphome/components/mqtt/mqtt_binary_sensor.cpp index a37043406b..7cbb5dcc0e 100644 --- a/esphome/components/mqtt/mqtt_binary_sensor.cpp +++ b/esphome/components/mqtt/mqtt_binary_sensor.cpp @@ -19,7 +19,7 @@ void MQTTBinarySensorComponent::setup() { void MQTTBinarySensorComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Binary Sensor '%s':", this->binary_sensor_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, false) + LOG_MQTT_COMPONENT(true, false); } MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor *binary_sensor) : binary_sensor_(binary_sensor) { diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index cb8b92cad0..7607a4e817 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -27,20 +27,23 @@ inline char *append_char(char *p, char c) { // Max lengths for stack-based topic building. // These limits are enforced at Python config validation time in mqtt/__init__.py // using cv.Length() validators for topic_prefix and discovery_prefix. -// MQTT_COMPONENT_TYPE_MAX_LEN and MQTT_SUFFIX_MAX_LEN are defined in mqtt_component.h. +// MQTT_COMPONENT_TYPE_MAX_LEN, MQTT_SUFFIX_MAX_LEN, and MQTT_DEFAULT_TOPIC_MAX_LEN are in mqtt_component.h. // ESPHOME_DEVICE_NAME_MAX_LEN and OBJECT_ID_MAX_LEN are defined in entity_base.h. // This ensures the stack buffers below are always large enough. -static constexpr size_t TOPIC_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) static constexpr size_t DISCOVERY_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) - -// Stack buffer sizes - safe because all inputs are length-validated at config time -// Format: prefix + "/" + type + "/" + object_id + "/" + suffix + null -static constexpr size_t DEFAULT_TOPIC_MAX_LEN = - TOPIC_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1 + MQTT_SUFFIX_MAX_LEN + 1; // Format: prefix + "/" + type + "/" + name + "/" + object_id + "/config" + null static constexpr size_t DISCOVERY_TOPIC_MAX_LEN = DISCOVERY_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 7 + 1; +// Function implementation of LOG_MQTT_COMPONENT macro to reduce code size +void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, bool command_topic) { + char buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + if (state_topic) + ESP_LOGCONFIG(tag, " State Topic: '%s'", obj->get_state_topic_to_(buf).c_str()); + if (command_topic) + ESP_LOGCONFIG(tag, " Command Topic: '%s'", obj->get_command_topic_to_(buf).c_str()); +} + void MQTTComponent::set_qos(uint8_t qos) { this->qos_ = qos; } void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; } @@ -69,19 +72,18 @@ std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discove return std::string(buf, p - buf); } -std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) const { +StringRef MQTTComponent::get_default_topic_for_to_(std::span buf, const char *suffix, + size_t suffix_len) const { const std::string &topic_prefix = global_mqtt_client->get_topic_prefix(); if (topic_prefix.empty()) { - // If the topic_prefix is null, the default topic should be null - return ""; + return StringRef(); // Empty topic_prefix means no default topic } const char *comp_type = this->component_type(); char object_id_buf[OBJECT_ID_MAX_LEN]; StringRef object_id = this->get_default_object_id_to_(object_id_buf); - char buf[DEFAULT_TOPIC_MAX_LEN]; - char *p = buf; + char *p = buf.data(); p = append_str(p, topic_prefix.data(), topic_prefix.size()); p = append_char(p, '/'); @@ -89,21 +91,44 @@ std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) con p = append_char(p, '/'); p = append_str(p, object_id.c_str(), object_id.size()); p = append_char(p, '/'); - p = append_str(p, suffix.data(), suffix.size()); + p = append_str(p, suffix, suffix_len); + *p = '\0'; - return std::string(buf, p - buf); + return StringRef(buf.data(), p - buf.data()); +} + +std::string MQTTComponent::get_default_topic_for_(const std::string &suffix) const { + char buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + StringRef ref = this->get_default_topic_for_to_(buf, suffix.data(), suffix.size()); + return std::string(ref.c_str(), ref.size()); +} + +StringRef MQTTComponent::get_state_topic_to_(std::span buf) const { + if (this->custom_state_topic_.has_value()) { + // Returns ref to existing data for static/value, uses buf only for lambda case + return this->custom_state_topic_.ref_or_copy_to(buf.data(), buf.size()); + } + return this->get_default_topic_for_to_(buf, "state", 5); +} + +StringRef MQTTComponent::get_command_topic_to_(std::span buf) const { + if (this->custom_command_topic_.has_value()) { + // Returns ref to existing data for static/value, uses buf only for lambda case + return this->custom_command_topic_.ref_or_copy_to(buf.data(), buf.size()); + } + return this->get_default_topic_for_to_(buf, "command", 7); } std::string MQTTComponent::get_state_topic_() const { - if (this->custom_state_topic_.has_value()) - return this->custom_state_topic_.value(); - return this->get_default_topic_for_("state"); + char buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + StringRef ref = this->get_state_topic_to_(buf); + return std::string(ref.c_str(), ref.size()); } std::string MQTTComponent::get_command_topic_() const { - if (this->custom_command_topic_.has_value()) - return this->custom_command_topic_.value(); - return this->get_default_topic_for_("command"); + char buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + StringRef ref = this->get_command_topic_to_(buf); + return std::string(ref.c_str(), ref.size()); } bool MQTTComponent::publish(const std::string &topic, const std::string &payload) { @@ -168,10 +193,14 @@ bool MQTTComponent::send_discovery_() { break; } - if (config.state_topic) - root[MQTT_STATE_TOPIC] = this->get_state_topic_(); - if (config.command_topic) - root[MQTT_COMMAND_TOPIC] = this->get_command_topic_(); + if (config.state_topic) { + char state_topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + root[MQTT_STATE_TOPIC] = this->get_state_topic_to_(state_topic_buf); + } + if (config.command_topic) { + char command_topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + root[MQTT_COMMAND_TOPIC] = this->get_command_topic_to_(command_topic_buf); + } if (this->command_retain_) root[MQTT_COMMAND_RETAIN] = true; @@ -309,7 +338,9 @@ void MQTTComponent::set_availability(std::string topic, std::string payload_avai } void MQTTComponent::disable_availability() { this->set_availability("", "", ""); } void MQTTComponent::call_setup() { - if (this->is_internal()) + // Cache is_internal result once during setup - topics don't change after this + this->is_internal_ = this->compute_is_internal_(); + if (this->is_internal_) return; this->setup(); @@ -361,26 +392,28 @@ StringRef MQTTComponent::get_default_object_id_to_(std::spanget_entity()->get_icon_ref(); } bool MQTTComponent::is_disabled_by_default_() const { return this->get_entity()->is_disabled_by_default(); } -bool MQTTComponent::is_internal() { +bool MQTTComponent::compute_is_internal_() { if (this->custom_state_topic_.has_value()) { - // If the custom state_topic is null, return true as it is internal and should not publish + // If the custom state_topic is empty, return true as it is internal and should not publish // else, return false, as it is explicitly set to a topic, so it is not internal and should publish - return this->get_state_topic_().empty(); + // Using is_empty() avoids heap allocation for non-lambda cases + return this->custom_state_topic_.is_empty(); } if (this->custom_command_topic_.has_value()) { - // If the custom command_topic is null, return true as it is internal and should not publish + // If the custom command_topic is empty, return true as it is internal and should not publish // else, return false, as it is explicitly set to a topic, so it is not internal and should publish - return this->get_command_topic_().empty(); + // Using is_empty() avoids heap allocation for non-lambda cases + return this->custom_command_topic_.is_empty(); } - // No custom topics have been set - if (this->get_default_topic_for_("").empty()) { - // If the default topic prefix is null, then the component, by default, is internal and should not publish + // No custom topics have been set - check topic_prefix directly to avoid allocation + if (global_mqtt_client->get_topic_prefix().empty()) { + // If the default topic prefix is empty, then the component, by default, is internal and should not publish return true; } - // Use ESPHome's component internal state if topic_prefix is not null with no custom state_topic or command_topic + // Use ESPHome's component internal state if topic_prefix is not empty with no custom state_topic or command_topic return this->get_entity()->is_internal(); } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index dea91e3d5a..1a5e6db3af 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -20,17 +20,22 @@ struct SendDiscoveryConfig { bool command_topic{true}; ///< If the command topic should be included. Default to true. }; -// Max lengths for stack-based topic building (must match mqtt_component.cpp) +// Max lengths for stack-based topic building. +// These limits are enforced at Python config validation time in mqtt/__init__.py +// using cv.Length() validators for topic_prefix and discovery_prefix. +// This ensures the stack buffers are always large enough. static constexpr size_t MQTT_COMPONENT_TYPE_MAX_LEN = 20; static constexpr size_t MQTT_SUFFIX_MAX_LEN = 32; +static constexpr size_t MQTT_TOPIC_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) +// Stack buffer size - safe because all inputs are length-validated at config time +// Format: prefix + "/" + type + "/" + object_id + "/" + suffix + null +static constexpr size_t MQTT_DEFAULT_TOPIC_MAX_LEN = + MQTT_TOPIC_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1 + MQTT_SUFFIX_MAX_LEN + 1; -#define LOG_MQTT_COMPONENT(state_topic, command_topic) \ - if (state_topic) { \ - ESP_LOGCONFIG(TAG, " State Topic: '%s'", this->get_state_topic_().c_str()); \ - } \ - if (command_topic) { \ - ESP_LOGCONFIG(TAG, " Command Topic: '%s'", this->get_command_topic_().c_str()); \ - } +class MQTTComponent; // Forward declaration +void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, bool command_topic); + +#define LOG_MQTT_COMPONENT(state_topic, command_topic) log_mqtt_component(TAG, this, state_topic, command_topic) // Macro to define component_type() with compile-time length verification // Usage: MQTT_COMPONENT_TYPE(MQTTSensorComponent, "sensor") @@ -74,6 +79,8 @@ static constexpr size_t MQTT_SUFFIX_MAX_LEN = 32; * a clean separation. */ class MQTTComponent : public Component { + friend void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, bool command_topic); + public: /// Constructs a MQTTComponent. explicit MQTTComponent(); @@ -88,7 +95,8 @@ class MQTTComponent : public Component { virtual bool send_initial_state() = 0; - virtual bool is_internal(); + /// Returns cached is_internal result (computed once during setup). + bool is_internal() const { return this->is_internal_; } /// Set QOS for state messages. void set_qos(uint8_t qos); @@ -179,7 +187,16 @@ class MQTTComponent : public Component { /// Helper method to get the discovery topic for this component. std::string get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const; - /** Get this components state/command/... topic. + /** Get this components state/command/... topic into a buffer. + * + * @param buf The buffer to write to (must be exactly MQTT_DEFAULT_TOPIC_MAX_LEN). + * @param suffix The suffix/key such as "state" or "command". + * @return StringRef pointing to the buffer with the topic. + */ + StringRef get_default_topic_for_to_(std::span buf, const char *suffix, + size_t suffix_len) const; + + /** Get this components state/command/... topic (allocates std::string). * * @param suffix The suffix/key such as "state" or "command". * @return The full topic. @@ -200,10 +217,20 @@ class MQTTComponent : public Component { /// Get whether the underlying Entity is disabled by default bool is_disabled_by_default_() const; - /// Get the MQTT topic that new states will be shared to. + /// Get the MQTT state topic into a buffer (no heap allocation for non-lambda custom topics). + /// @param buf Buffer of exactly MQTT_DEFAULT_TOPIC_MAX_LEN bytes. + /// @return StringRef pointing to the topic in the buffer. + StringRef get_state_topic_to_(std::span buf) const; + + /// Get the MQTT command topic into a buffer (no heap allocation for non-lambda custom topics). + /// @param buf Buffer of exactly MQTT_DEFAULT_TOPIC_MAX_LEN bytes. + /// @return StringRef pointing to the topic in the buffer. + StringRef get_command_topic_to_(std::span buf) const; + + /// Get the MQTT topic that new states will be shared to (allocates std::string). std::string get_state_topic_() const; - /// Get the MQTT topic for listening to commands. + /// Get the MQTT topic for listening to commands (allocates std::string). std::string get_command_topic_() const; bool is_connected_() const; @@ -221,12 +248,18 @@ class MQTTComponent : public Component { std::unique_ptr availability_; - bool command_retain_{false}; - bool retain_{true}; - uint8_t qos_{0}; - uint8_t subscribe_qos_{0}; - bool discovery_enabled_{true}; - bool resend_state_{false}; + // Packed bitfields - QoS values are 0-2, bools are flags + uint8_t qos_ : 2 {0}; + uint8_t subscribe_qos_ : 2 {0}; + bool command_retain_ : 1 {false}; + bool retain_ : 1 {true}; + bool discovery_enabled_ : 1 {true}; + bool resend_state_ : 1 {false}; + bool is_internal_ : 1 {false}; ///< Cached result of compute_is_internal_(), set during setup + + /// Compute is_internal status based on topics and entity state. + /// Called once during setup to cache the result. + bool compute_is_internal_(); }; } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index f2df6af236..493514c8fb 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -51,7 +51,7 @@ void MQTTCoverComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT cover '%s':", this->cover_->get_name().c_str()); auto traits = this->cover_->get_traits(); bool has_command_topic = traits.get_supports_position() || !traits.get_supports_tilt(); - LOG_MQTT_COMPONENT(true, has_command_topic) + LOG_MQTT_COMPONENT(true, has_command_topic); if (traits.get_supports_position()) { ESP_LOGCONFIG(TAG, " Position State Topic: '%s'\n" diff --git a/esphome/components/mqtt/mqtt_date.cpp b/esphome/components/mqtt/mqtt_date.cpp index dba7c1a671..cbe4045486 100644 --- a/esphome/components/mqtt/mqtt_date.cpp +++ b/esphome/components/mqtt/mqtt_date.cpp @@ -36,7 +36,7 @@ void MQTTDateComponent::setup() { void MQTTDateComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Date '%s':", this->date_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); } MQTT_COMPONENT_TYPE(MQTTDateComponent, "date") diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp index 5f1cf19b97..f7b4ef0685 100644 --- a/esphome/components/mqtt/mqtt_datetime.cpp +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -47,7 +47,7 @@ void MQTTDateTimeComponent::setup() { void MQTTDateTimeComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT DateTime '%s':", this->datetime_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); } MQTT_COMPONENT_TYPE(MQTTDateTimeComponent, "datetime") diff --git a/esphome/components/mqtt/mqtt_light.cpp b/esphome/components/mqtt/mqtt_light.cpp index fac19f3210..e43cb63f4f 100644 --- a/esphome/components/mqtt/mqtt_light.cpp +++ b/esphome/components/mqtt/mqtt_light.cpp @@ -90,7 +90,7 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery bool MQTTJSONLightComponent::send_initial_state() { return this->publish_state_(); } void MQTTJSONLightComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Light '%s':", this->state_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index 471c0d1208..a014096c5f 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -30,7 +30,7 @@ void MQTTNumberComponent::setup() { void MQTTNumberComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Number '%s':", this->number_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, false) + LOG_MQTT_COMPONENT(true, false); } MQTT_COMPONENT_TYPE(MQTTNumberComponent, "number") diff --git a/esphome/components/mqtt/mqtt_select.cpp b/esphome/components/mqtt/mqtt_select.cpp index 03ab82312b..2d830998ec 100644 --- a/esphome/components/mqtt/mqtt_select.cpp +++ b/esphome/components/mqtt/mqtt_select.cpp @@ -25,7 +25,7 @@ void MQTTSelectComponent::setup() { void MQTTSelectComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Select '%s':", this->select_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, false) + LOG_MQTT_COMPONENT(true, false); } MQTT_COMPONENT_TYPE(MQTTSelectComponent, "select") diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index c14c889d47..f136b82355 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -28,7 +28,7 @@ void MQTTSensorComponent::dump_config() { if (this->get_expire_after() > 0) { ESP_LOGCONFIG(TAG, " Expire After: %" PRIu32 "s", this->get_expire_after() / 1000); } - LOG_MQTT_COMPONENT(true, false) + LOG_MQTT_COMPONENT(true, false); } MQTT_COMPONENT_TYPE(MQTTSensorComponent, "sensor") diff --git a/esphome/components/mqtt/mqtt_text.cpp b/esphome/components/mqtt/mqtt_text.cpp index cee94965c6..fed9224b42 100644 --- a/esphome/components/mqtt/mqtt_text.cpp +++ b/esphome/components/mqtt/mqtt_text.cpp @@ -26,7 +26,7 @@ void MQTTTextComponent::setup() { void MQTTTextComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT text '%s':", this->text_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); } MQTT_COMPONENT_TYPE(MQTTTextComponent, "text") diff --git a/esphome/components/mqtt/mqtt_time.cpp b/esphome/components/mqtt/mqtt_time.cpp index b75325022a..8749c3b59e 100644 --- a/esphome/components/mqtt/mqtt_time.cpp +++ b/esphome/components/mqtt/mqtt_time.cpp @@ -36,7 +36,7 @@ void MQTTTimeComponent::setup() { void MQTTTimeComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Time '%s':", this->time_->get_name().c_str()); - LOG_MQTT_COMPONENT(true, true) + LOG_MQTT_COMPONENT(true, true); } MQTT_COMPONENT_TYPE(MQTTTimeComponent, "time") diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 2faaace46b..8e66a69c6f 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -39,7 +39,7 @@ void MQTTValveComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT valve '%s':", this->valve_->get_name().c_str()); auto traits = this->valve_->get_traits(); bool has_command_topic = traits.get_supports_position(); - LOG_MQTT_COMPONENT(true, has_command_topic) + LOG_MQTT_COMPONENT(true, has_command_topic); if (traits.get_supports_position()) { ESP_LOGCONFIG(TAG, " Position State Topic: '%s'\n" diff --git a/esphome/core/automation.h b/esphome/core/automation.h index eac469d0fc..31a2fc06f4 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -4,6 +4,7 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#include "esphome/core/string_ref.h" #include #include #include @@ -190,15 +191,55 @@ template class TemplatableValue { /// Get the static string pointer (only valid if is_static_string() returns true) const char *get_static_string() const { return this->static_str_; } - protected: - enum : uint8_t { - NONE, - VALUE, - LAMBDA, - STATELESS_LAMBDA, - STATIC_STRING, // For const char* when T is std::string - avoids heap allocation - } type_; + /// Check if the string value is empty without allocating (for std::string specialization). + /// For NONE, returns true. For STATIC_STRING/VALUE, checks without allocation. + /// For LAMBDA/STATELESS_LAMBDA, must call value() which may allocate. + bool is_empty() const requires std::same_as { + switch (this->type_) { + case NONE: + return true; + case STATIC_STRING: + return this->static_str_ == nullptr || this->static_str_[0] == '\0'; + case VALUE: + return this->value_->empty(); + default: // LAMBDA/STATELESS_LAMBDA - must call value() + return this->value().empty(); + } + } + /// Get a StringRef to the string value without heap allocation when possible. + /// For STATIC_STRING/VALUE, returns reference to existing data (no allocation). + /// For LAMBDA/STATELESS_LAMBDA, calls value(), copies to provided buffer, returns ref to buffer. + /// @param lambda_buf Buffer used only for lambda case (must remain valid while StringRef is used). + /// @param lambda_buf_size Size of the buffer. + /// @return StringRef pointing to the string data. + StringRef ref_or_copy_to(char *lambda_buf, size_t lambda_buf_size) const requires std::same_as { + switch (this->type_) { + case NONE: + return StringRef(); + case STATIC_STRING: + if (this->static_str_ == nullptr) + return StringRef(); + return StringRef(this->static_str_, strlen(this->static_str_)); + case VALUE: + return StringRef(this->value_->data(), this->value_->size()); + default: { // LAMBDA/STATELESS_LAMBDA - must call value() and copy + std::string result = this->value(); + size_t copy_len = std::min(result.size(), lambda_buf_size - 1); + memcpy(lambda_buf, result.data(), copy_len); + lambda_buf[copy_len] = '\0'; + return StringRef(lambda_buf, copy_len); + } + } + } + + protected : enum : uint8_t { + NONE, + VALUE, + LAMBDA, + STATELESS_LAMBDA, + STATIC_STRING, // For const char* when T is std::string - avoids heap allocation + } type_; // For std::string, use heap pointer to minimize union size (4 bytes vs 12+). // For other types, store value inline as before. using ValueStorage = std::conditional_t; From a9ce3df04c9f4db4b0d66d461d6380c45b7354d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:36:12 -1000 Subject: [PATCH 0287/2030] [esp8266] Use SmallBufferWithHeapFallback in preferences (#13397) --- esphome/components/esp8266/preferences.cpp | 25 ++++------------------ 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index 47987b4a95..35d1cd07f7 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -12,7 +12,6 @@ extern "C" { #include "preferences.h" #include -#include namespace esphome::esp8266 { @@ -143,16 +142,8 @@ class ESP8266PreferenceBackend : public ESPPreferenceBackend { return false; const size_t buffer_size = static_cast(this->length_words) + 1; - uint32_t stack_buffer[PREF_BUFFER_WORDS]; - std::unique_ptr heap_buffer; - uint32_t *buffer; - - if (buffer_size <= PREF_BUFFER_WORDS) { - buffer = stack_buffer; - } else { - heap_buffer = make_unique(buffer_size); - buffer = heap_buffer.get(); - } + SmallBufferWithHeapFallback buffer_alloc(buffer_size); + uint32_t *buffer = buffer_alloc.get(); memset(buffer, 0, buffer_size * sizeof(uint32_t)); memcpy(buffer, data, len); @@ -167,16 +158,8 @@ class ESP8266PreferenceBackend : public ESPPreferenceBackend { return false; const size_t buffer_size = static_cast(this->length_words) + 1; - uint32_t stack_buffer[PREF_BUFFER_WORDS]; - std::unique_ptr heap_buffer; - uint32_t *buffer; - - if (buffer_size <= PREF_BUFFER_WORDS) { - buffer = stack_buffer; - } else { - heap_buffer = make_unique(buffer_size); - buffer = heap_buffer.get(); - } + SmallBufferWithHeapFallback buffer_alloc(buffer_size); + uint32_t *buffer = buffer_alloc.get(); bool ret = this->in_flash ? load_from_flash(this->offset, buffer, buffer_size) : load_from_rtc(this->offset, buffer, buffer_size); From a1c4d5626857d8eecb656b8d588de99759090356 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 18:37:13 -1000 Subject: [PATCH 0288/2030] [alarm_control_panel] Reduce heap allocations in arm/disarm methods (#13358) --- .../alarm_control_panel.cpp | 55 ++++++------------- .../alarm_control_panel/alarm_control_panel.h | 30 ++++++++-- .../alarm_control_panel_call.cpp | 6 +- .../alarm_control_panel_call.h | 3 +- .../alarm_control_panel/automation.h | 30 +--------- 5 files changed, 49 insertions(+), 75 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 248b5065ad..ab0a780cef 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -67,52 +67,29 @@ void AlarmControlPanel::add_on_ready_callback(std::function &&callback) this->ready_callback_.add(std::move(callback)); } -void AlarmControlPanel::arm_away(optional code) { +void AlarmControlPanel::arm_with_code_(AlarmControlPanelCall &(AlarmControlPanelCall::*arm_method)(), + const char *code) { auto call = this->make_call(); - call.arm_away(); - if (code.has_value()) - call.set_code(code.value()); + (call.*arm_method)(); + if (code != nullptr) + call.set_code(code); call.perform(); } -void AlarmControlPanel::arm_home(optional code) { - auto call = this->make_call(); - call.arm_home(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); +void AlarmControlPanel::arm_away(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_away, code); } + +void AlarmControlPanel::arm_home(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_home, code); } + +void AlarmControlPanel::arm_night(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::arm_night, code); } + +void AlarmControlPanel::arm_vacation(const char *code) { + this->arm_with_code_(&AlarmControlPanelCall::arm_vacation, code); } -void AlarmControlPanel::arm_night(optional code) { - auto call = this->make_call(); - call.arm_night(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); +void AlarmControlPanel::arm_custom_bypass(const char *code) { + this->arm_with_code_(&AlarmControlPanelCall::arm_custom_bypass, code); } -void AlarmControlPanel::arm_vacation(optional code) { - auto call = this->make_call(); - call.arm_vacation(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} - -void AlarmControlPanel::arm_custom_bypass(optional code) { - auto call = this->make_call(); - call.arm_custom_bypass(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} - -void AlarmControlPanel::disarm(optional code) { - auto call = this->make_call(); - call.disarm(); - if (code.has_value()) - call.set_code(code.value()); - call.perform(); -} +void AlarmControlPanel::disarm(const char *code) { this->arm_with_code_(&AlarmControlPanelCall::disarm, code); } } // namespace esphome::alarm_control_panel diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.h b/esphome/components/alarm_control_panel/alarm_control_panel.h index 340f15bcd6..e8dc197e26 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel.h @@ -76,37 +76,53 @@ class AlarmControlPanel : public EntityBase { * * @param code The code */ - void arm_away(optional code = nullopt); + void arm_away(const char *code = nullptr); + void arm_away(const optional &code) { + this->arm_away(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in home mode * * @param code The code */ - void arm_home(optional code = nullopt); + void arm_home(const char *code = nullptr); + void arm_home(const optional &code) { + this->arm_home(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in night mode * * @param code The code */ - void arm_night(optional code = nullopt); + void arm_night(const char *code = nullptr); + void arm_night(const optional &code) { + this->arm_night(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in vacation mode * * @param code The code */ - void arm_vacation(optional code = nullopt); + void arm_vacation(const char *code = nullptr); + void arm_vacation(const optional &code) { + this->arm_vacation(code.has_value() ? code.value().c_str() : nullptr); + } /** arm the alarm in custom bypass mode * * @param code The code */ - void arm_custom_bypass(optional code = nullopt); + void arm_custom_bypass(const char *code = nullptr); + void arm_custom_bypass(const optional &code) { + this->arm_custom_bypass(code.has_value() ? code.value().c_str() : nullptr); + } /** disarm the alarm * * @param code The code */ - void disarm(optional code = nullopt); + void disarm(const char *code = nullptr); + void disarm(const optional &code) { this->disarm(code.has_value() ? code.value().c_str() : nullptr); } /** Get the state * @@ -118,6 +134,8 @@ class AlarmControlPanel : public EntityBase { protected: friend AlarmControlPanelCall; + // Helper to reduce code duplication for arm/disarm methods + void arm_with_code_(AlarmControlPanelCall &(AlarmControlPanelCall::*arm_method)(), const char *code); // in order to store last panel state in flash ESPPreferenceObject pref_; // current state diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp index 5e98d58368..ba58ee3904 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp @@ -10,8 +10,10 @@ static const char *const TAG = "alarm_control_panel"; AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent_(parent) {} -AlarmControlPanelCall &AlarmControlPanelCall::set_code(const std::string &code) { - this->code_ = code; +AlarmControlPanelCall &AlarmControlPanelCall::set_code(const char *code) { + if (code != nullptr) { + this->code_ = std::string(code); + } return *this; } diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.h b/esphome/components/alarm_control_panel/alarm_control_panel_call.h index cff00900dd..58764ea166 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.h @@ -14,7 +14,8 @@ class AlarmControlPanelCall { public: AlarmControlPanelCall(AlarmControlPanel *parent); - AlarmControlPanelCall &set_code(const std::string &code); + AlarmControlPanelCall &set_code(const char *code); + AlarmControlPanelCall &set_code(const std::string &code) { return this->set_code(code.c_str()); } AlarmControlPanelCall &arm_away(); AlarmControlPanelCall &arm_home(); AlarmControlPanelCall &arm_night(); diff --git a/esphome/components/alarm_control_panel/automation.h b/esphome/components/alarm_control_panel/automation.h index ce5ceadb47..4ff34de0d5 100644 --- a/esphome/components/alarm_control_panel/automation.h +++ b/esphome/components/alarm_control_panel/automation.h @@ -66,15 +66,7 @@ template class ArmAwayAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_away(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_away(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_; @@ -86,15 +78,7 @@ template class ArmHomeAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_home(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_home(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_; @@ -106,15 +90,7 @@ template class ArmNightAction : public Action { TEMPLATABLE_VALUE(std::string, code) - void play(const Ts &...x) override { - auto call = this->alarm_control_panel_->make_call(); - auto code = this->code_.optional_value(x...); - if (code.has_value()) { - call.set_code(code.value()); - } - call.arm_night(); - call.perform(); - } + void play(const Ts &...x) override { this->alarm_control_panel_->arm_night(this->code_.optional_value(x...)); } protected: AlarmControlPanel *alarm_control_panel_; From 5bbf9153ca9adcef7dbe4479eb917aea55d5f576 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 19:48:32 -1000 Subject: [PATCH 0289/2030] [http_request] Fix OTA failures on ESP8266/Arduino by making read semantics consistent (#13435) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../update/esp32_hosted_update.cpp | 49 ++++-- .../components/http_request/http_request.h | 151 +++++++++++++++++- .../http_request/http_request_arduino.cpp | 29 +++- .../http_request/http_request_idf.cpp | 43 ++++- .../http_request/ota/ota_http_request.cpp | 62 +++---- .../update/http_request_update.cpp | 31 ++-- 6 files changed, 296 insertions(+), 69 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index a82ee48718..ebcdd5f36e 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -11,6 +11,7 @@ #include #ifdef USE_ESP32_HOSTED_HTTP_UPDATE +#include "esphome/components/http_request/http_request.h" #include "esphome/components/json/json_util.h" #include "esphome/components/network/util.h" #endif @@ -184,15 +185,23 @@ bool Esp32HostedUpdate::fetch_manifest_() { } // Read manifest JSON into string (manifest is small, ~1KB max) + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly std::string json_str; json_str.reserve(container->content_length); uint8_t buf[256]; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->http_request_parent_->get_timeout(); while (container->get_bytes_read() < container->content_length) { - int read = container->read(buf, sizeof(buf)); - if (read > 0) { - json_str.append(reinterpret_cast(buf), read); - } + int read_or_error = container->read(buf, sizeof(buf)); + App.feed_wdt(); yield(); + auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == http_request::HttpReadLoopResult::RETRY) + continue; + if (result != http_request::HttpReadLoopResult::DATA) + break; // ERROR or TIMEOUT + json_str.append(reinterpret_cast(buf), read_or_error); } container->end(); @@ -297,32 +306,38 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { } // Stream firmware to coprocessor while computing SHA256 + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly sha256::SHA256 hasher; hasher.init(); uint8_t buffer[CHUNK_SIZE]; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->http_request_parent_->get_timeout(); while (container->get_bytes_read() < total_size) { - int read = container->read(buffer, sizeof(buffer)); + int read_or_error = container->read(buffer, sizeof(buffer)); // Feed watchdog and give other tasks a chance to run App.feed_wdt(); yield(); - // Exit loop if no data available (stream closed or end of data) - if (read <= 0) { - if (read < 0) { - ESP_LOGE(TAG, "Stream closed with error"); - esp_hosted_slave_ota_end(); // NOLINT - container->end(); - this->status_set_error(LOG_STR("Download failed")); - return false; + auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == http_request::HttpReadLoopResult::RETRY) + continue; + if (result != http_request::HttpReadLoopResult::DATA) { + if (result == http_request::HttpReadLoopResult::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading firmware data"); + } else { + ESP_LOGE(TAG, "Error reading firmware data: %d", read_or_error); } - // read == 0: no more data available, exit loop - break; + esp_hosted_slave_ota_end(); // NOLINT + container->end(); + this->status_set_error(LOG_STR("Download failed")); + return false; } - hasher.add(buffer, read); - err = esp_hosted_slave_ota_write(buffer, read); // NOLINT + hasher.add(buffer, read_or_error); + err = esp_hosted_slave_ota_write(buffer, read_or_error); // NOLINT if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err)); esp_hosted_slave_ota_end(); // NOLINT diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index a8c2cdfc63..fb39ca504c 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -79,6 +79,81 @@ inline bool is_redirect(int const status) { */ inline bool is_success(int const status) { return status >= HTTP_STATUS_OK && status < HTTP_STATUS_MULTIPLE_CHOICES; } +/* + * HTTP Container Read Semantics + * ============================= + * + * IMPORTANT: These semantics differ from standard BSD sockets! + * + * BSD socket read() returns: + * > 0: bytes read + * == 0: connection closed (EOF) + * < 0: error (check errno) + * + * HttpContainer::read() returns: + * > 0: bytes read successfully + * == 0: no data available yet OR all content read + * (caller should check bytes_read vs content_length) + * < 0: error or connection closed (caller should EXIT) + * HTTP_ERROR_CONNECTION_CLOSED (-1) = connection closed prematurely + * other negative values = platform-specific errors + * + * Platform behaviors: + * - ESP-IDF: blocking reads, 0 only returned when all content read + * - Arduino: non-blocking, 0 means "no data yet" or "all content read" + * + * Use the helper functions below instead of checking return values directly: + * - http_read_loop_result(): for manual loops with per-chunk processing + * - http_read_fully(): for simple "read N bytes into buffer" operations + */ + +/// Error code returned by HttpContainer::read() when connection closed prematurely +/// NOTE: Unlike BSD sockets where 0 means EOF, here 0 means "no data yet, retry" +static constexpr int HTTP_ERROR_CONNECTION_CLOSED = -1; + +/// Status of a read operation +enum class HttpReadStatus : uint8_t { + OK, ///< Read completed successfully + ERROR, ///< Read error occurred + TIMEOUT, ///< Timeout waiting for data +}; + +/// Result of an HTTP read operation +struct HttpReadResult { + HttpReadStatus status; ///< Status of the read operation + int error_code; ///< Error code from read() on failure, 0 on success +}; + +/// Result of processing a non-blocking read with timeout (for manual loops) +enum class HttpReadLoopResult : uint8_t { + DATA, ///< Data was read, process it + RETRY, ///< No data yet, already delayed, caller should continue loop + ERROR, ///< Read error, caller should exit loop + TIMEOUT, ///< Timeout waiting for data, caller should exit loop +}; + +/// Process a read result with timeout tracking and delay handling +/// @param bytes_read_or_error Return value from read() - positive for bytes read, negative for error +/// @param last_data_time Time of last successful read, updated when data received +/// @param timeout_ms Maximum time to wait for data +/// @return DATA if data received, RETRY if should continue loop, ERROR/TIMEOUT if should exit +inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, + uint32_t timeout_ms) { + if (bytes_read_or_error > 0) { + last_data_time = millis(); + return HttpReadLoopResult::DATA; + } + if (bytes_read_or_error < 0) { + return HttpReadLoopResult::ERROR; + } + // bytes_read_or_error == 0: no data available yet + if (millis() - last_data_time >= timeout_ms) { + return HttpReadLoopResult::TIMEOUT; + } + delay(1); // Small delay to prevent tight spinning + return HttpReadLoopResult::RETRY; +} + class HttpRequestComponent; class HttpContainer : public Parented { @@ -88,6 +163,33 @@ class HttpContainer : public Parented { int status_code; uint32_t duration_ms; + /** + * @brief Read data from the HTTP response body. + * + * WARNING: These semantics differ from BSD sockets! + * BSD sockets: 0 = EOF (connection closed) + * This method: 0 = no data yet OR all content read, negative = error/closed + * + * @param buf Buffer to read data into + * @param max_len Maximum number of bytes to read + * @return + * - > 0: Number of bytes read successfully + * - 0: No data available yet OR all content read + * (check get_bytes_read() >= content_length to distinguish) + * - HTTP_ERROR_CONNECTION_CLOSED (-1): Connection closed prematurely + * - < -1: Other error (platform-specific error code) + * + * Platform notes: + * - ESP-IDF: blocking read, 0 only when all content read + * - Arduino: non-blocking, 0 can mean "no data yet" or "all content read" + * + * Use get_bytes_read() and content_length to track progress. + * When get_bytes_read() >= content_length, all data has been received. + * + * IMPORTANT: Do not use raw return values directly. Use these helpers: + * - http_read_loop_result(): for loops with per-chunk processing + * - http_read_fully(): for simple "read N bytes" operations + */ virtual int read(uint8_t *buf, size_t max_len) = 0; virtual void end() = 0; @@ -110,6 +212,38 @@ class HttpContainer : public Parented { std::map> response_headers_{}; }; +/// Read data from HTTP container into buffer with timeout handling +/// Handles feed_wdt, yield, and timeout checking internally +/// @param container The HTTP container to read from +/// @param buffer Buffer to read into +/// @param total_size Total bytes to read +/// @param chunk_size Maximum bytes per read call +/// @param timeout_ms Read timeout in milliseconds +/// @return HttpReadResult with status and error_code on failure +inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, size_t total_size, size_t chunk_size, + uint32_t timeout_ms) { + size_t read_index = 0; + uint32_t last_data_time = millis(); + + while (read_index < total_size) { + int read_bytes_or_error = container->read(buffer + read_index, std::min(chunk_size, total_size - read_index)); + + App.feed_wdt(); + yield(); + + auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result == HttpReadLoopResult::ERROR) + return {HttpReadStatus::ERROR, read_bytes_or_error}; + if (result == HttpReadLoopResult::TIMEOUT) + return {HttpReadStatus::TIMEOUT, 0}; + + read_index += read_bytes_or_error; + } + return {HttpReadStatus::OK, 0}; +} + class HttpRequestResponseTrigger : public Trigger, std::string &> { public: void process(const std::shared_ptr &container, std::string &response_body) { @@ -124,6 +258,7 @@ class HttpRequestComponent : public Component { void set_useragent(const char *useragent) { this->useragent_ = useragent; } void set_timeout(uint32_t timeout) { this->timeout_ = timeout; } + uint32_t get_timeout() const { return this->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; } @@ -249,15 +384,21 @@ template class HttpRequestSendAction : public Action { RAMAllocator allocator; uint8_t *buf = allocator.allocate(max_length); if (buf != nullptr) { + // NOTE: HttpContainer::read() has non-BSD socket semantics - see top of this file + // Use http_read_loop_result() helper instead of checking return values directly size_t read_index = 0; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->parent_->get_timeout(); while (container->get_bytes_read() < max_length) { - int read = container->read(buf + read_index, std::min(max_length - read_index, 512)); - if (read <= 0) { - break; - } + int read_or_error = container->read(buf + read_index, std::min(max_length - read_index, 512)); App.feed_wdt(); yield(); - read_index += read; + auto result = http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result != HttpReadLoopResult::DATA) + break; // ERROR or TIMEOUT + read_index += read_or_error; } response_body.reserve(read_index); response_body.assign((char *) buf, read_index); diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index a653942b18..8ec4d2bc4b 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -139,6 +139,23 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur return container; } +// Arduino HTTP read implementation +// +// WARNING: Return values differ from BSD sockets! See http_request.h for full documentation. +// +// Arduino's WiFiClient is inherently non-blocking - available() returns 0 when +// no data is ready. We use connected() to distinguish "no data yet" from +// "connection closed". +// +// WiFiClient behavior: +// available() > 0: data ready to read +// available() == 0 && connected(): no data yet, still connected +// available() == 0 && !connected(): connection closed +// +// We normalize to HttpContainer::read() contract (NOT BSD socket semantics!): +// > 0: bytes read +// 0: no data yet, retry <-- NOTE: 0 means retry, NOT EOF! +// < 0: error/connection closed <-- connection closed returns -1, not 0 int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); @@ -146,7 +163,7 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { WiFiClient *stream_ptr = this->client_.getStreamPtr(); if (stream_ptr == nullptr) { ESP_LOGE(TAG, "Stream pointer vanished!"); - return -1; + return HTTP_ERROR_CONNECTION_CLOSED; } int available_data = stream_ptr->available(); @@ -154,7 +171,15 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { if (bufsize == 0) { this->duration_ms += (millis() - start); - return 0; + // Check if we've read all expected content + if (this->bytes_read_ >= this->content_length) { + return 0; // All content read successfully + } + // No data available - check if connection is still open + if (!stream_ptr->connected()) { + return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed prematurely + } + return 0; // No data yet, caller should retry } App.feed_wdt(); diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index eedd321d80..b6fb7f7ea9 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -209,26 +209,57 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c return container; } +// ESP-IDF HTTP read implementation (blocking mode) +// +// WARNING: Return values differ from BSD sockets! See http_request.h for full documentation. +// +// esp_http_client_read() in blocking mode returns: +// > 0: bytes read +// 0: connection closed (end of stream) +// < 0: error +// +// We normalize to HttpContainer::read() contract: +// > 0: bytes read +// 0: no data yet / all content read (caller should check bytes_read vs content_length) +// < 0: error/connection closed int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); - this->feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, max_len); - this->feed_wdt(); - if (read_len > 0) { - this->bytes_read_ += read_len; + // Check if we've already read all expected content + if (this->bytes_read_ >= this->content_length) { + return 0; // All content read successfully } + + this->feed_wdt(); + int read_len_or_error = esp_http_client_read(this->client_, (char *) buf, max_len); + this->feed_wdt(); + this->duration_ms += (millis() - start); - return read_len; + if (read_len_or_error > 0) { + this->bytes_read_ += read_len_or_error; + return read_len_or_error; + } + + // Connection closed by server before all content received + if (read_len_or_error == 0) { + return HTTP_ERROR_CONNECTION_CLOSED; + } + + // Negative value - error, return the actual error code for debugging + return read_len_or_error; } void HttpContainerIDF::end() { + if (this->client_ == nullptr) { + return; // Already cleaned up + } watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); esp_http_client_close(this->client_); esp_http_client_cleanup(this->client_); + this->client_ = nullptr; } void HttpContainerIDF::feed_wdt() { diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 2a7db9137f..6c77e75d8c 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -115,39 +115,47 @@ uint8_t OtaHttpRequestComponent::do_ota_() { return error_code; } + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->parent_->get_timeout(); + while (container->get_bytes_read() < container->content_length) { - // read a maximum of chunk_size bytes into buf. (real read size returned) - 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); + // read a maximum of chunk_size bytes into buf. (real read size returned, or negative error code) + int bufsize_or_error = container->read(buf, OtaHttpRequestComponent::HTTP_RECV_BUFFER); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize_or_error = %i", container->get_bytes_read(), + container->content_length, bufsize_or_error); // feed watchdog and give other tasks a chance to run App.feed_wdt(); yield(); - // Exit loop if no data available (stream closed or end of data) - if (bufsize <= 0) { - if (bufsize < 0) { - ESP_LOGE(TAG, "Stream closed with error"); - this->cleanup_(std::move(backend), container); - return OTA_CONNECTION_ERROR; + auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result != HttpReadLoopResult::DATA) { + if (result == HttpReadLoopResult::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading data"); + } else { + ESP_LOGE(TAG, "Error reading data: %d", bufsize_or_error); } - // bufsize == 0: no more data available, exit loop - break; + this->cleanup_(std::move(backend), container); + return OTA_CONNECTION_ERROR; } - if (bufsize <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { + // At this point bufsize_or_error > 0, so it's a valid size + if (bufsize_or_error <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { // add read bytes to MD5 - md5_receive.add(buf, bufsize); + md5_receive.add(buf, bufsize_or_error); // write bytes to OTA backend this->update_started_ = true; - error_code = backend->write(buf, bufsize); + error_code = backend->write(buf, bufsize_or_error); 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, - container->get_bytes_read() - bufsize, container->content_length); + container->get_bytes_read() - bufsize_or_error, container->content_length); this->cleanup_(std::move(backend), container); return error_code; } @@ -244,19 +252,19 @@ bool OtaHttpRequestComponent::http_get_md5_() { } this->md5_expected_.resize(MD5_SIZE); - int read_len = 0; - while (container->get_bytes_read() < MD5_SIZE) { - read_len = container->read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); - if (read_len <= 0) { - break; - } - App.feed_wdt(); - yield(); - } + auto result = http_read_fully(container.get(), (uint8_t *) this->md5_expected_.data(), MD5_SIZE, MD5_SIZE, + this->parent_->get_timeout()); container->end(); - ESP_LOGV(TAG, "Read len: %u, MD5 expected: %u", read_len, MD5_SIZE); - return read_len == MD5_SIZE; + if (result.status != HttpReadStatus::OK) { + if (result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading MD5"); + } else { + ESP_LOGE(TAG, "Error reading MD5: %d", result.error_code); + } + return false; + } + return true; } bool OtaHttpRequestComponent::validate_url_(const std::string &url) { diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 82b391e01f..c63e55d159 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -11,7 +11,12 @@ namespace http_request { // The update function runs in a task only on ESP32s. #ifdef USE_ESP32 -#define UPDATE_RETURN vTaskDelete(nullptr) // Delete the current update task +// vTaskDelete doesn't return, but clang-tidy doesn't know that +#define UPDATE_RETURN \ + do { \ + vTaskDelete(nullptr); \ + __builtin_unreachable(); \ + } while (0) #else #define UPDATE_RETURN return #endif @@ -70,19 +75,21 @@ void HttpRequestUpdate::update_task(void *params) { UPDATE_RETURN; } - size_t read_index = 0; - while (container->get_bytes_read() < container->content_length) { - int read_bytes = container->read(data + read_index, MAX_READ_SIZE); - - yield(); - - if (read_bytes <= 0) { - // Network error or connection closed - break to avoid infinite loop - break; + auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, + this_update->request_parent_->get_timeout()); + if (read_result.status != HttpReadStatus::OK) { + if (read_result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading manifest"); + } else { + ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); } - - read_index += read_bytes; + // Defer to main loop to avoid race condition on component_state_ read-modify-write + this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to read manifest")); }); + allocator.deallocate(data, container->content_length); + container->end(); + UPDATE_RETURN; } + size_t read_index = container->get_bytes_read(); bool valid = false; { // Ensures the response string falls out of scope and deallocates before the task ends From 8d1379a2752291d2f4e33d5831d51c2afd59f7ce Mon Sep 17 00:00:00 2001 From: Rene Guca <45061891+rguca@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:54:10 +0100 Subject: [PATCH 0290/2030] [dht] Increase delay for DHT22 and RHT03 (#13446) --- esphome/components/dht/dht.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 6cb204c8de..276ea24717 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -89,10 +89,8 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r delayMicroseconds(500); } else if (this->model_ == DHT_MODEL_DHT22_TYPE2) { delayMicroseconds(2000); - } else if (this->model_ == DHT_MODEL_AM2120 || this->model_ == DHT_MODEL_AM2302) { - delayMicroseconds(1000); } else { - delayMicroseconds(800); + delayMicroseconds(1000); } #ifdef USE_ESP32 From d6a41ed51ebfaeae140b13775f3059d68bd746f4 Mon Sep 17 00:00:00 2001 From: Sven Kocksch Date: Thu, 22 Jan 2026 16:31:38 +0100 Subject: [PATCH 0291/2030] [mipi_dsi] Add M5Stack Tab5 (Rev2/V2) DriverChip (#12074) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/mipi_dsi/models/m5stack.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/esphome/components/mipi_dsi/models/m5stack.py b/esphome/components/mipi_dsi/models/m5stack.py index 6055c77f8f..2298f76cd4 100644 --- a/esphome/components/mipi_dsi/models/m5stack.py +++ b/esphome/components/mipi_dsi/models/m5stack.py @@ -55,3 +55,44 @@ DriverChip( (0x35,), (0xFE,), ], ) + +DriverChip( + "M5STACK-TAB5-V2", + height=1280, + width=720, + hsync_back_porch=40, + hsync_pulse_width=2, + hsync_front_porch=40, + vsync_back_porch=8, + vsync_pulse_width=2, + vsync_front_porch=220, + pclk_frequency="80MHz", + lane_bit_rate="960Mbps", + swap_xy=cv.UNDEFINED, + color_order="RGB", + initsequence=[ + (0x60, 0x71, 0x23, 0xa2), + (0x60, 0x71, 0x23, 0xa3), + (0x60, 0x71, 0x23, 0xa4), + (0xA4, 0x31), + (0xD7, 0x10, 0x0A, 0x10, 0x2A, 0x80, 0x80), + (0x90, 0x71, 0x23, 0x5A, 0x20, 0x24, 0x09, 0x09), + (0xA3, 0x80, 0x01, 0x88, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x4F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x6F, 0x58, 0x00, 0x00, 0x00, 0xFF), + (0xA6, 0x03, 0x00, 0x24, 0x55, 0x36, 0x00, 0x39, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, 0x55, 0x38, 0x00, 0x37, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, 0x11, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0xEC, 0x11, 0x00, 0x03, 0x00, 0x03, 0x6E, 0x6E, 0xFF, 0xFF, 0x00, 0x08, 0x80, 0x08, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00), + (0xA7, 0x19, 0x19, 0x80, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x44, 0x03, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x25, 0x34, 0x40, 0x00, 0x02, 0x01, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, 0x64, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x6E, 0x6E, 0x84, 0xFF, 0x08, 0x80, 0x44), + (0xAC, 0x03, 0x19, 0x19, 0x18, 0x18, 0x06, 0x13, 0x13, 0x11, 0x11, 0x08, 0x08, 0x0A, 0x0A, 0x1C, 0x1C, 0x07, 0x07, 0x00, 0x00, 0x02, 0x02, 0x01, 0x19, 0x19, 0x18, 0x18, 0x06, 0x12, 0x12, 0x10, 0x10, 0x09, 0x09, 0x0B, 0x0B, 0x1C, 0x1C, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01), + (0xAD, 0xF0, 0x00, 0x46, 0x00, 0x03, 0x50, 0x50, 0xFF, 0xFF, 0xF0, 0x40, 0x06, 0x01, 0x07, 0x42, 0x42, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF), + (0xAE, 0xFE, 0x3F, 0x3F, 0xFE, 0x3F, 0x3F, 0x00), + (0xB2, 0x15, 0x19, 0x05, 0x23, 0x49, 0xAF, 0x03, 0x2E, 0x5C, 0xD2, 0xFF, 0x10, 0x20, 0xFD, 0x20, 0xC0, 0x00), + (0xE8, 0x20, 0x6F, 0x04, 0x97, 0x97, 0x3E, 0x04, 0xDC, 0xDC, 0x3E, 0x06, 0xFA, 0x26, 0x3E), + (0x75, 0x03, 0x04), + (0xE7, 0x3B, 0x00, 0x00, 0x7C, 0xA1, 0x8C, 0x20, 0x1A, 0xF0, 0xB1, 0x50, 0x00, 0x50, 0xB1, 0x50, 0xB1, 0x50, 0xD8, 0x00, 0x55, 0x00, 0xB1, 0x00, 0x45, 0xC9, 0x6A, 0xFF, 0x5A, 0xD8, 0x18, 0x88, 0x15, 0xB1, 0x01, 0x01, 0x77), + (0xEA, 0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2C), + (0xB0, 0x22, 0x43, 0x11, 0x61, 0x25, 0x43, 0x43), + (0xb7, 0x00, 0x00, 0x73, 0x73), + (0xBF, 0xA6, 0xAA), + (0xA9, 0x00, 0x00, 0x73, 0xFF, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03), + (0xC8, 0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF), + (0xC9, 0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF), + ], +) From 4ac7fe84b41fe383d681339e900228b0817a6e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=2E=20=C3=81rkosi=20R=C3=B3bert?= Date: Thu, 22 Jan 2026 17:14:14 +0100 Subject: [PATCH 0292/2030] [bthome_mithermometer] add encrypted beacon support (#13428) --- .../bthome_mithermometer/__init__.py | 10 +- .../bthome_mithermometer/bthome_ble.cpp | 135 +++++++++++++++--- .../bthome_mithermometer/bthome_ble.h | 7 + .../bthome_mithermometer/common.yaml | 1 + 4 files changed, 136 insertions(+), 17 deletions(-) diff --git a/esphome/components/bthome_mithermometer/__init__.py b/esphome/components/bthome_mithermometer/__init__.py index 0e84278afa..8ce216da22 100644 --- a/esphome/components/bthome_mithermometer/__init__.py +++ b/esphome/components/bthome_mithermometer/__init__.py @@ -1,7 +1,8 @@ import esphome.codegen as cg from esphome.components import esp32_ble_tracker import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_MAC_ADDRESS +from esphome.const import CONF_BINDKEY, CONF_ID, CONF_MAC_ADDRESS +from esphome.core import HexInt CODEOWNERS = ["@nagyrobi"] DEPENDENCIES = ["esp32_ble_tracker"] @@ -22,6 +23,7 @@ def bthome_mithermometer_base_schema(extra_schema=None): { cv.GenerateID(CONF_ID): cv.declare_id(BTHomeMiThermometer), cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_BINDKEY): cv.bind_key, } ) .extend(BLE_DEVICE_SCHEMA) @@ -34,3 +36,9 @@ async def setup_bthome_mithermometer(var, config): await cg.register_component(var, config) await esp32_ble_tracker.register_ble_device(var, config) cg.add(var.set_address(config[CONF_MAC_ADDRESS].as_hex)) + if bindkey := config.get(CONF_BINDKEY): + bindkey_bytes = [ + HexInt(int(bindkey[index : index + 2], 16)) + for index in range(0, len(bindkey), 2) + ] + cg.add(var.set_bindkey(cg.ArrayInitializer(*bindkey_bytes))) diff --git a/esphome/components/bthome_mithermometer/bthome_ble.cpp b/esphome/components/bthome_mithermometer/bthome_ble.cpp index d1c5165896..2b73d8735c 100644 --- a/esphome/components/bthome_mithermometer/bthome_ble.cpp +++ b/esphome/components/bthome_mithermometer/bthome_ble.cpp @@ -3,15 +3,23 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include #include +#include #include #ifdef USE_ESP32 +#include "mbedtls/ccm.h" + namespace esphome { namespace bthome_mithermometer { static const char *const TAG = "bthome_mithermometer"; +static constexpr size_t BTHOME_BINDKEY_SIZE = 16; +static constexpr size_t BTHOME_NONCE_SIZE = 13; +static constexpr size_t BTHOME_MIC_SIZE = 4; +static constexpr size_t BTHOME_COUNTER_SIZE = 4; static const char *format_mac_address(std::span buffer, uint64_t address) { std::array mac{}; @@ -130,6 +138,10 @@ void BTHomeMiThermometer::dump_config() { char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; ESP_LOGCONFIG(TAG, "BTHome MiThermometer"); ESP_LOGCONFIG(TAG, " MAC Address: %s", format_mac_address(addr_buf, this->address_)); + if (this->has_bindkey_) { + char bindkey_hex[format_hex_pretty_size(BTHOME_BINDKEY_SIZE)]; + ESP_LOGCONFIG(TAG, " Bindkey: %s", format_hex_pretty_to(bindkey_hex, this->bindkey_, BTHOME_BINDKEY_SIZE, '.')); + } LOG_SENSOR(" ", "Temperature", this->temperature_); LOG_SENSOR(" ", "Humidity", this->humidity_); LOG_SENSOR(" ", "Battery Level", this->battery_level_); @@ -150,6 +162,60 @@ bool BTHomeMiThermometer::parse_device(const esp32_ble_tracker::ESPBTDevice &dev return matched; } +void BTHomeMiThermometer::set_bindkey(std::initializer_list bindkey) { + if (bindkey.size() != sizeof(this->bindkey_)) { + ESP_LOGW(TAG, "BTHome bindkey size mismatch: %zu", bindkey.size()); + return; + } + std::copy(bindkey.begin(), bindkey.end(), this->bindkey_); + this->has_bindkey_ = true; +} + +bool BTHomeMiThermometer::decrypt_bthome_payload_(const std::vector &data, uint64_t source_address, + std::vector &payload) const { + if (data.size() <= 1 + BTHOME_COUNTER_SIZE + BTHOME_MIC_SIZE) { + ESP_LOGVV(TAG, "Encrypted BTHome payload too short: %zu", data.size()); + return false; + } + + const size_t ciphertext_size = data.size() - 1 - BTHOME_COUNTER_SIZE - BTHOME_MIC_SIZE; + payload.resize(ciphertext_size); + + std::array mac{}; + for (size_t i = 0; i < MAC_ADDRESS_SIZE; i++) { + mac[i] = (source_address >> ((MAC_ADDRESS_SIZE - 1 - i) * 8)) & 0xFF; + } + + std::array nonce{}; + memcpy(nonce.data(), mac.data(), mac.size()); + nonce[6] = 0xD2; + nonce[7] = 0xFC; + nonce[8] = data[0]; + memcpy(nonce.data() + 9, &data[data.size() - BTHOME_COUNTER_SIZE - BTHOME_MIC_SIZE], BTHOME_COUNTER_SIZE); + + const uint8_t *ciphertext = data.data() + 1; + const uint8_t *mic = data.data() + data.size() - BTHOME_MIC_SIZE; + + mbedtls_ccm_context ctx; + mbedtls_ccm_init(&ctx); + + int ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, this->bindkey_, BTHOME_BINDKEY_SIZE * 8); + if (ret) { + ESP_LOGVV(TAG, "mbedtls_ccm_setkey() failed."); + mbedtls_ccm_free(&ctx); + return false; + } + + ret = mbedtls_ccm_auth_decrypt(&ctx, ciphertext_size, nonce.data(), nonce.size(), nullptr, 0, ciphertext, + payload.data(), mic, BTHOME_MIC_SIZE); + mbedtls_ccm_free(&ctx); + if (ret) { + ESP_LOGVV(TAG, "BTHome decryption failed (ret=%d).", ret); + return false; + } + return true; +} + bool BTHomeMiThermometer::handle_service_data_(const esp32_ble_tracker::ServiceData &service_data, const esp32_ble_tracker::ESPBTDevice &device) { if (!service_data.uuid.contains(0xD2, 0xFC)) { @@ -173,51 +239,88 @@ bool BTHomeMiThermometer::handle_service_data_(const esp32_ble_tracker::ServiceD return false; } - char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; - if (is_encrypted) { - ESP_LOGV(TAG, "Ignoring encrypted BTHome frame from %s", device.address_str_to(addr_buf)); + uint64_t source_address = device.address_uint64(); + bool address_matches = source_address == this->address_; + if (!is_encrypted && mac_included && data.size() >= 7) { + uint64_t advertised_address = 0; + for (int i = 5; i >= 0; i--) { + advertised_address = (advertised_address << 8) | data[1 + i]; + } + address_matches = address_matches || advertised_address == this->address_; + } + + if (is_encrypted && !this->has_bindkey_) { + if (address_matches) { + char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + ESP_LOGE(TAG, "Encrypted BTHome frame received but no bindkey configured for %s", + device.address_str_to(addr_buf)); + } return false; } - size_t payload_index = 1; - uint64_t source_address = device.address_uint64(); + if (!is_encrypted && this->has_bindkey_) { + if (address_matches) { + char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + ESP_LOGE(TAG, "Unencrypted BTHome frame received with bindkey configured for %s", + device.address_str_to(addr_buf)); + } + return false; + } + std::vector decrypted_payload; + const uint8_t *payload = nullptr; + size_t payload_size = 0; + + if (is_encrypted) { + if (!this->decrypt_bthome_payload_(data, source_address, decrypted_payload)) { + char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + ESP_LOGVV(TAG, "Failed to decrypt BTHome frame from %s", device.address_str_to(addr_buf)); + return false; + } + payload = decrypted_payload.data(); + payload_size = decrypted_payload.size(); + } else { + payload = data.data() + 1; + payload_size = data.size() - 1; + } if (mac_included) { - if (data.size() < 7) { + if (payload_size < 6) { ESP_LOGVV(TAG, "BTHome payload missing MAC address"); return false; } source_address = 0; for (int i = 5; i >= 0; i--) { - source_address = (source_address << 8) | data[1 + i]; + source_address = (source_address << 8) | payload[i]; } - payload_index = 7; + payload += 6; + payload_size -= 6; } + char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; if (source_address != this->address_) { ESP_LOGVV(TAG, "BTHome frame from unexpected device %s", format_mac_address(addr_buf, source_address)); return false; } - if (payload_index >= data.size()) { + if (payload_size == 0) { ESP_LOGVV(TAG, "BTHome payload empty after header"); return false; } bool reported = false; - size_t offset = payload_index; + size_t offset = 0; uint8_t last_type = 0; - while (offset < data.size()) { - const uint8_t obj_type = data[offset++]; + while (offset < payload_size) { + const uint8_t obj_type = payload[offset++]; size_t value_length = 0; bool has_length_byte = obj_type == 0x53; // text objects include explicit length if (has_length_byte) { - if (offset >= data.size()) { + if (offset >= payload_size) { break; } - value_length = data[offset++]; + value_length = payload[offset++]; } else { if (!get_bthome_value_length(obj_type, value_length)) { ESP_LOGVV(TAG, "Unknown BTHome object 0x%02X", obj_type); @@ -229,12 +332,12 @@ bool BTHomeMiThermometer::handle_service_data_(const esp32_ble_tracker::ServiceD break; } - if (offset + value_length > data.size()) { + if (offset + value_length > payload_size) { ESP_LOGVV(TAG, "BTHome object length exceeds payload"); break; } - const uint8_t *value = &data[offset]; + const uint8_t *value = &payload[offset]; offset += value_length; if (obj_type < last_type) { diff --git a/esphome/components/bthome_mithermometer/bthome_ble.h b/esphome/components/bthome_mithermometer/bthome_ble.h index 3d2380b48d..ef3038ec93 100644 --- a/esphome/components/bthome_mithermometer/bthome_ble.h +++ b/esphome/components/bthome_mithermometer/bthome_ble.h @@ -5,6 +5,8 @@ #include "esphome/core/component.h" #include +#include +#include #ifdef USE_ESP32 @@ -14,6 +16,7 @@ namespace bthome_mithermometer { class BTHomeMiThermometer : public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: void set_address(uint64_t address) { this->address_ = address; } + void set_bindkey(std::initializer_list bindkey); void set_temperature(sensor::Sensor *temperature) { this->temperature_ = temperature; } void set_humidity(sensor::Sensor *humidity) { this->humidity_ = humidity; } @@ -27,9 +30,13 @@ class BTHomeMiThermometer : public esp32_ble_tracker::ESPBTDeviceListener, publi protected: bool handle_service_data_(const esp32_ble_tracker::ServiceData &service_data, const esp32_ble_tracker::ESPBTDevice &device); + bool decrypt_bthome_payload_(const std::vector &data, uint64_t source_address, + std::vector &payload) const; uint64_t address_{0}; optional last_packet_id_{}; + bool has_bindkey_{false}; + uint8_t bindkey_[16]; sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; diff --git a/tests/components/bthome_mithermometer/common.yaml b/tests/components/bthome_mithermometer/common.yaml index ba94e46878..7a68fae966 100644 --- a/tests/components/bthome_mithermometer/common.yaml +++ b/tests/components/bthome_mithermometer/common.yaml @@ -3,6 +3,7 @@ esp32_ble_tracker: sensor: - platform: bthome_mithermometer mac_address: A4:C1:38:4E:16:78 + bindkey: eef418daf699a0c188f3bfd17e4565d9 temperature: name: "BTHome Temperature" humidity: From ddb762f8f53006a6ac53fe70ca066704de556830 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 08:09:14 -1000 Subject: [PATCH 0293/2030] [api] Limit Nagle batching for log messages to reduce LWIP buffer pressure (#13439) --- esphome/components/api/api_connection.cpp | 19 +------ esphome/components/api/api_frame_helper.h | 67 +++++++++++++++-------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 0364879ccd..1626f395e6 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1844,23 +1844,8 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { return false; } - // Toggle Nagle's algorithm based on message type to prevent log messages from - // filling the TCP send buffer and crowding out important state updates. - // - // This honors the `no_delay` proto option - SubscribeLogsResponse is the only - // message with `option (no_delay) = false;` in api.proto, indicating it should - // allow Nagle coalescing. This option existed since 2019 but was never implemented. - // - // - Log messages: Enable Nagle (NODELAY=false) so small log packets coalesce - // into fewer, larger packets. They flush naturally via TCP delayed ACK timer - // (~200ms), buffer filling, or when a state update triggers a flush. - // - // - All other messages (state updates, responses): Disable Nagle (NODELAY=true) - // for immediate delivery. These are time-sensitive and should not be delayed. - // - // This must be done proactively BEFORE the buffer fills up - checking buffer - // state here would be too late since we'd already be in a degraded state. - this->helper_->set_nodelay(!is_log_message); + // Set TCP_NODELAY based on message type - see set_nodelay_for_message() for details + this->helper_->set_nodelay_for_message(is_log_message); APIError err = this->helper_->write_protobuf_packet(message_type, buffer); if (err == APIError::WOULD_BLOCK) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 27ec1ff915..f311e34fd7 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -120,26 +120,39 @@ class APIFrameHelper { } return APIError::OK; } - /// Toggle TCP_NODELAY socket option to control Nagle's algorithm. - /// - /// This is used to allow log messages to coalesce (Nagle enabled) while keeping - /// state updates low-latency (NODELAY enabled). Without this, many small log - /// packets fill the TCP send buffer, crowding out important state updates. - /// - /// State is tracked to minimize setsockopt() overhead - on lwip_raw (ESP8266/RP2040) - /// this is just a boolean assignment; on other platforms it's a lightweight syscall. - /// - /// @param enable true to enable NODELAY (disable Nagle), false to enable Nagle - /// @return true if successful or already in desired state - bool set_nodelay(bool enable) { - if (this->nodelay_enabled_ == enable) - return true; - int val = enable ? 1 : 0; - int err = this->socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int)); - if (err == 0) { - this->nodelay_enabled_ = enable; + // Manage TCP_NODELAY (Nagle's algorithm) based on message type. + // + // For non-log messages (sensor data, state updates): Always disable Nagle + // (NODELAY on) for immediate delivery - these are time-sensitive. + // + // For log messages: Use Nagle to coalesce multiple small log packets into + // fewer larger packets, reducing WiFi overhead. However, we limit batching + // to 3 messages to avoid excessive LWIP buffer pressure on memory-constrained + // devices like ESP8266. LWIP's TCP_OVERSIZE option coalesces the data into + // shared pbufs, but holding data too long waiting for Nagle's timer causes + // buffer exhaustion and dropped messages. + // + // Flow: Log 1 (Nagle on) -> Log 2 (Nagle on) -> Log 3 (NODELAY, flush all) + // + void set_nodelay_for_message(bool is_log_message) { + if (!is_log_message) { + if (this->nodelay_state_ != NODELAY_ON) { + this->set_nodelay_raw_(true); + this->nodelay_state_ = NODELAY_ON; + } + return; + } + + // Log messages 1-3: state transitions -1 -> 1 -> 2 -> -1 (flush on 3rd) + if (this->nodelay_state_ == NODELAY_ON) { + this->set_nodelay_raw_(false); + this->nodelay_state_ = 1; + } else if (this->nodelay_state_ >= LOG_NAGLE_COUNT) { + this->set_nodelay_raw_(true); + this->nodelay_state_ = NODELAY_ON; + } else { + this->nodelay_state_++; } - return err == 0; } virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0; // Write multiple protobuf messages in a single operation @@ -229,10 +242,18 @@ class APIFrameHelper { uint8_t tx_buf_head_{0}; uint8_t tx_buf_tail_{0}; uint8_t tx_buf_count_{0}; - // Tracks TCP_NODELAY state to minimize setsockopt() calls. Initialized to true - // since init_common_() enables NODELAY. Used by set_nodelay() to allow log - // messages to coalesce while keeping state updates low-latency. - bool nodelay_enabled_{true}; + // Nagle batching state for log messages. NODELAY_ON (-1) means NODELAY is enabled + // (immediate send). Values 1-2 count log messages in the current Nagle batch. + // After LOG_NAGLE_COUNT logs, we switch to NODELAY to flush and reset. + static constexpr int8_t NODELAY_ON = -1; + static constexpr int8_t LOG_NAGLE_COUNT = 2; + int8_t nodelay_state_{NODELAY_ON}; + + // Internal helper to set TCP_NODELAY socket option + void set_nodelay_raw_(bool enable) { + int val = enable ? 1 : 0; + this->socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int)); + } // Common initialization for both plaintext and noise protocols APIError init_common_(); From 3c5fc638d5a3a289c4fa721d486723dd2536959f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 10:42:14 -1000 Subject: [PATCH 0294/2030] [wifi] Fix stale error_from_callback_ causing immediate connection failures (#13450) --- esphome/components/wifi/wifi_component.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index ff6284c073..52d9b2b442 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -565,6 +565,11 @@ void WiFiComponent::start() { void WiFiComponent::restart_adapter() { ESP_LOGW(TAG, "Restarting adapter"); this->wifi_mode_(false, {}); + // Clear error flag here because restart_adapter() enters COOLDOWN state, + // and check_connecting_finished() is called after cooldown without going + // through start_connecting() first. Without this clear, stale errors would + // trigger spurious "failed (callback)" logs. The canonical clear location + // is in start_connecting(); this is the only exception to that pattern. this->error_from_callback_ = false; } @@ -618,8 +623,6 @@ void WiFiComponent::loop() { if (!this->is_connected()) { ESP_LOGW(TAG, "Connection lost; reconnecting"); this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; - // Clear error flag before reconnecting so first attempt is not seen as immediate failure - this->error_from_callback_ = false; this->retry_connect(); } else { this->status_clear_warning(); @@ -963,6 +966,12 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { ESP_LOGV(TAG, " Hidden: %s", YESNO(ap.get_hidden())); #endif + // Clear any stale error from previous connection attempt. + // This is the canonical location for clearing the flag since all connection + // attempts go through start_connecting(). The only other clear is in + // restart_adapter() which enters COOLDOWN without calling start_connecting(). + this->error_from_callback_ = false; + if (!this->wifi_sta_connect_(ap)) { ESP_LOGE(TAG, "wifi_sta_connect_ failed"); // Enter cooldown to allow WiFi hardware to stabilize @@ -1068,7 +1077,6 @@ void WiFiComponent::enable() { return; ESP_LOGD(TAG, "Enabling"); - this->error_from_callback_ = false; this->state_ = WIFI_COMPONENT_STATE_OFF; this->start(); } @@ -1329,11 +1337,6 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { // Reset to initial phase on successful connection (don't log transition, just reset state) this->retry_phase_ = WiFiRetryPhase::INITIAL_CONNECT; this->num_retried_ = 0; - // Ensure next connection attempt does not inherit error state - // so when WiFi disconnects later we start fresh and don't see - // the first connection as a failure. - this->error_from_callback_ = false; - if (this->has_ap()) { #ifdef USE_CAPTIVE_PORTAL if (this->is_captive_portal_active_()) { @@ -1844,8 +1847,6 @@ void WiFiComponent::retry_connect() { this->advance_to_next_target_or_increment_retry_(); } - this->error_from_callback_ = false; - yield(); // Check if we have a valid target before building params // After exhausting all networks in a phase, selected_sta_index_ may be -1 @@ -2171,7 +2172,6 @@ void WiFiComponent::process_roaming_scan_() { this->roaming_state_ = RoamingState::CONNECTING; // Connect directly - wifi_sta_connect_ handles disconnect internally - this->error_from_callback_ = false; this->start_connecting(roam_params); } From b06568c132b033b7f35cf5668343bf0b0e9007ae Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:07:41 -0500 Subject: [PATCH 0295/2030] [fingerprint_grow] Use buffer-based dump_summary to fix deprecation warnings (#13447) Co-authored-by: Claude Opus 4.5 --- .../fingerprint_grow/fingerprint_grow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index eb7ede8fe9..da4535fc82 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -1,4 +1,5 @@ #include "fingerprint_grow.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" #include @@ -532,14 +533,21 @@ void FingerprintGrowComponent::sensor_sleep_() { } void FingerprintGrowComponent::dump_config() { + char sensing_pin_buf[GPIO_SUMMARY_MAX_LEN]; + char power_pin_buf[GPIO_SUMMARY_MAX_LEN]; + if (this->has_sensing_pin_) { + this->sensing_pin_->dump_summary(sensing_pin_buf, sizeof(sensing_pin_buf)); + } + if (this->has_power_pin_) { + this->sensor_power_pin_->dump_summary(power_pin_buf, sizeof(power_pin_buf)); + } ESP_LOGCONFIG(TAG, "GROW_FINGERPRINT_READER:\n" " System Identifier Code: 0x%.4X\n" " Touch Sensing Pin: %s\n" " Sensor Power Pin: %s", - this->system_identifier_code_, - this->has_sensing_pin_ ? this->sensing_pin_->dump_summary().c_str() : "None", - this->has_power_pin_ ? this->sensor_power_pin_->dump_summary().c_str() : "None"); + this->system_identifier_code_, this->has_sensing_pin_ ? sensing_pin_buf : "None", + this->has_power_pin_ ? power_pin_buf : "None"); if (this->idle_period_to_sleep_ms_ < UINT32_MAX) { ESP_LOGCONFIG(TAG, " Idle Period to Sleep: %" PRIu32 " ms", this->idle_period_to_sleep_ms_); } else { From afbbdd1492052ac3bda24e05f076d4baad8d8979 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:10:55 -0500 Subject: [PATCH 0296/2030] [aqi] Remove unit_of_measurement to fix Home Assistant warning (#13448) Co-authored-by: Claude Opus 4.5 --- esphome/components/aqi/sensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/aqi/sensor.py b/esphome/components/aqi/sensor.py index 0b5ee8d75a..5842aea88c 100644 --- a/esphome/components/aqi/sensor.py +++ b/esphome/components/aqi/sensor.py @@ -13,14 +13,11 @@ from . import AQI_CALCULATION_TYPE, CONF_CALCULATION_TYPE, aqi_ns CODEOWNERS = ["@jasstrong"] DEPENDENCIES = ["sensor"] -UNIT_INDEX = "index" - AQISensor = aqi_ns.class_("AQISensor", sensor.Sensor, cg.Component) CONFIG_SCHEMA = ( sensor.sensor_schema( AQISensor, - unit_of_measurement=UNIT_INDEX, accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, From 6d7956a062e491333dabf053d32bb00840b33304 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Fri, 23 Jan 2026 10:15:42 +1300 Subject: [PATCH 0297/2030] Update webserver local assets to 20260122-204614 (#13455) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/web_server/server_index_v2.h | 2528 +-- .../components/web_server/server_index_v3.h | 15257 ++++++++-------- 2 files changed, 8961 insertions(+), 8824 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index b224354a6b..7c24ae28c6 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,1239 +10,1307 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xdb, 0x72, 0xe3, 0x46, 0x96, 0xe0, 0xf3, - 0xfa, 0x2b, 0x20, 0x58, 0x2d, 0x23, 0x9b, 0x49, 0xf0, 0x22, 0xa9, 0x4a, 0x05, 0x32, 0xc9, 0x56, 0xa9, 0xca, 0x5d, - 0x76, 0xd7, 0xcd, 0xa5, 0xb2, 0xdd, 0x6e, 0x5a, 0x2d, 0x42, 0x40, 0x92, 0x48, 0x17, 0x08, 0xd0, 0x40, 0x52, 0x17, - 0x93, 0x98, 0xd8, 0x0f, 0xd8, 0x88, 0x8d, 0xd8, 0xa7, 0x7d, 0xd9, 0xd8, 0x79, 0xd8, 0x8f, 0xd8, 0xe7, 0xf9, 0x94, - 0xf9, 0x81, 0xdd, 0x4f, 0xd8, 0x38, 0x79, 0x01, 0x12, 0xbc, 0xa8, 0x54, 0xb6, 0x7b, 0x66, 0x1e, 0x36, 0x1c, 0x56, - 0x11, 0x89, 0xbc, 0x9c, 0x3c, 0x79, 0xf2, 0xdc, 0x33, 0xd1, 0xdf, 0x0b, 0xd3, 0x80, 0xdf, 0xcd, 0xa9, 0x15, 0xf1, - 0x59, 0x3c, 0xe8, 0xab, 0xbf, 0xd4, 0x0f, 0x07, 0xfd, 0x98, 0x25, 0x1f, 0xac, 0x8c, 0xc6, 0x84, 0x05, 0x69, 0x62, - 0x45, 0x19, 0x9d, 0x90, 0xd0, 0xe7, 0xbe, 0xc7, 0x66, 0xfe, 0x94, 0x5a, 0xad, 0x41, 0x7f, 0x46, 0xb9, 0x6f, 0x05, - 0x91, 0x9f, 0xe5, 0x94, 0x93, 0x6f, 0xdf, 0x7f, 0xd9, 0x3c, 0x19, 0xf4, 0xf3, 0x20, 0x63, 0x73, 0x6e, 0x41, 0x97, - 0x64, 0x96, 0x86, 0x8b, 0x98, 0x0e, 0x5a, 0xad, 0x9b, 0x9b, 0x1b, 0xf7, 0xa7, 0xfc, 0xb3, 0x20, 0x4d, 0x72, 0x6e, - 0xbd, 0x24, 0x37, 0x2c, 0x09, 0xd3, 0x1b, 0xcc, 0x38, 0x79, 0xe9, 0x9e, 0x47, 0x7e, 0x98, 0xde, 0xbc, 0x4b, 0x53, - 0x7e, 0x70, 0xe0, 0xc8, 0xc7, 0xbb, 0xb3, 0xf3, 0x73, 0x42, 0xc8, 0x75, 0xca, 0x42, 0xab, 0xbd, 0x5a, 0x55, 0x85, - 0x6e, 0xe2, 0x73, 0x76, 0x4d, 0x65, 0x13, 0x74, 0x70, 0x60, 0xfb, 0x61, 0x3a, 0xe7, 0x34, 0x3c, 0xe7, 0x77, 0x31, - 0x3d, 0x8f, 0x28, 0xe5, 0xb9, 0xcd, 0x12, 0xeb, 0x59, 0x1a, 0x2c, 0x66, 0x34, 0xe1, 0xee, 0x3c, 0x4b, 0x79, 0x0a, - 0x90, 0x1c, 0x1c, 0xd8, 0x19, 0x9d, 0xc7, 0x7e, 0x40, 0xe1, 0xfd, 0xd9, 0xf9, 0x79, 0xd5, 0xa2, 0xaa, 0x84, 0x73, - 0x4e, 0xce, 0xef, 0x66, 0x57, 0x69, 0xec, 0x20, 0x1c, 0x73, 0x92, 0xd0, 0x1b, 0xeb, 0x7b, 0xea, 0x7f, 0x78, 0xe5, - 0xcf, 0x7b, 0x41, 0xec, 0xe7, 0xb9, 0x75, 0xcb, 0x97, 0x62, 0x0a, 0xd9, 0x22, 0xe0, 0x69, 0xe6, 0x70, 0x4c, 0x31, - 0x43, 0x4b, 0x36, 0x71, 0x78, 0xc4, 0x72, 0xf7, 0x72, 0x3f, 0xc8, 0xf3, 0x77, 0x34, 0x5f, 0xc4, 0x7c, 0x9f, 0xec, - 0xb5, 0x31, 0xdb, 0x23, 0x24, 0xe7, 0x88, 0x47, 0x59, 0x7a, 0x63, 0x3d, 0xcf, 0xb2, 0x34, 0x73, 0xec, 0xb3, 0xf3, - 0x73, 0x59, 0xc3, 0x62, 0xb9, 0x95, 0xa4, 0xdc, 0x2a, 0xfb, 0xf3, 0xaf, 0x62, 0xea, 0x5a, 0xdf, 0xe6, 0xd4, 0x1a, - 0x2f, 0x92, 0xdc, 0x9f, 0xd0, 0xb3, 0xf3, 0xf3, 0xb1, 0x95, 0x66, 0xd6, 0x38, 0xc8, 0xf3, 0xb1, 0xc5, 0x92, 0x9c, - 0x53, 0x3f, 0x74, 0x6d, 0xd4, 0x13, 0x83, 0x05, 0x79, 0xfe, 0x9e, 0xde, 0x72, 0xc2, 0xb1, 0x78, 0xe4, 0x84, 0x16, - 0x53, 0xca, 0xad, 0xbc, 0x9c, 0x97, 0x83, 0x96, 0x31, 0xe5, 0x16, 0x27, 0xe2, 0x7d, 0xda, 0x93, 0xb8, 0xa7, 0xf2, - 0x91, 0xf7, 0xd8, 0xc4, 0x61, 0xfc, 0xe0, 0x80, 0x97, 0x78, 0x46, 0x72, 0x6a, 0x16, 0x23, 0x74, 0x4f, 0x97, 0x1d, - 0x1c, 0x50, 0x37, 0xa6, 0xc9, 0x94, 0x47, 0x84, 0x90, 0x4e, 0x8f, 0x1d, 0x1c, 0x38, 0x9c, 0xc4, 0xdc, 0x9d, 0x52, - 0xee, 0x50, 0x84, 0x70, 0xd5, 0xfa, 0xe0, 0xc0, 0x91, 0x48, 0x48, 0x89, 0x44, 0x5c, 0x0d, 0xc7, 0xc8, 0x55, 0xd8, - 0x3f, 0xbf, 0x4b, 0x02, 0xc7, 0x84, 0x1f, 0x61, 0x76, 0x70, 0x10, 0x73, 0x37, 0x87, 0x1e, 0x31, 0x47, 0xa8, 0xc8, - 0x28, 0x5f, 0x64, 0x89, 0xc5, 0x0b, 0x9e, 0x9e, 0xf3, 0x8c, 0x25, 0x53, 0x07, 0x2d, 0x75, 0x99, 0xd1, 0xb0, 0x28, - 0x24, 0xb8, 0xaf, 0x39, 0x49, 0xc8, 0x00, 0x46, 0xbc, 0xe5, 0x0e, 0xac, 0x62, 0x3a, 0xb1, 0x12, 0x42, 0xec, 0x5c, - 0xb4, 0xb5, 0x87, 0x89, 0x97, 0x34, 0x6c, 0x1b, 0x4b, 0x28, 0x71, 0xce, 0x11, 0xfe, 0x40, 0x9c, 0x04, 0xbb, 0xae, - 0xcb, 0x11, 0x19, 0x2c, 0x35, 0x56, 0x12, 0x63, 0x9e, 0xc3, 0x64, 0xd4, 0xbe, 0xf0, 0xb8, 0x9b, 0xd1, 0x70, 0x11, - 0x50, 0xc7, 0x61, 0x38, 0xc7, 0x19, 0x22, 0x03, 0xd6, 0x70, 0x52, 0x32, 0x80, 0xe5, 0x4e, 0xeb, 0x6b, 0x4d, 0xc8, - 0x5e, 0x1b, 0x29, 0x18, 0x53, 0x0d, 0x20, 0x60, 0x58, 0xc1, 0x93, 0x12, 0x62, 0x27, 0x8b, 0xd9, 0x15, 0xcd, 0xec, - 0xb2, 0x5a, 0xaf, 0x46, 0x16, 0x8b, 0x9c, 0x5a, 0x41, 0x9e, 0x5b, 0x93, 0x45, 0x12, 0x70, 0x96, 0x26, 0x96, 0xdd, - 0x48, 0x1b, 0xb6, 0x24, 0x87, 0x92, 0x1a, 0x6c, 0x54, 0x20, 0x27, 0x47, 0x8d, 0x64, 0x94, 0x35, 0x3a, 0x17, 0x18, - 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0xef, 0x38, 0xcc, 0x52, 0x4c, 0x91, 0xf1, - 0x61, 0xe2, 0x6e, 0x6e, 0x14, 0xc2, 0xdd, 0x99, 0x3f, 0x77, 0x28, 0x19, 0x50, 0x41, 0x5c, 0x7e, 0x12, 0x00, 0xac, - 0xb5, 0x75, 0x1b, 0x52, 0x8f, 0xba, 0x15, 0x49, 0x21, 0x8f, 0xbb, 0x93, 0x34, 0x7b, 0xee, 0x07, 0x11, 0xb4, 0x2b, - 0x09, 0x26, 0xd4, 0xfb, 0x2d, 0xc8, 0xa8, 0xcf, 0xe9, 0xf3, 0x98, 0xc2, 0x93, 0x63, 0x8b, 0x96, 0x36, 0xc2, 0x39, - 0x79, 0xe9, 0xc6, 0x8c, 0xbf, 0x4e, 0x93, 0x80, 0xf6, 0x72, 0x83, 0xba, 0x18, 0xac, 0xfb, 0x29, 0xe7, 0x19, 0xbb, - 0x5a, 0x70, 0xea, 0xd8, 0x09, 0xd4, 0xb0, 0x71, 0x8e, 0x30, 0x73, 0x39, 0xbd, 0xe5, 0x67, 0x69, 0xc2, 0x69, 0xc2, - 0x09, 0xd5, 0x48, 0xc5, 0x89, 0xeb, 0xcf, 0xe7, 0x34, 0x09, 0xcf, 0x22, 0x16, 0x87, 0x0e, 0x43, 0x05, 0x2a, 0x70, - 0xc4, 0x09, 0xcc, 0x91, 0x0c, 0x12, 0x0f, 0xfe, 0xec, 0x9e, 0x8d, 0xc3, 0xc9, 0x40, 0x6c, 0x0a, 0x4a, 0x6c, 0xbb, - 0x37, 0x49, 0x33, 0x47, 0xcd, 0xc0, 0x4a, 0x27, 0x16, 0x87, 0x31, 0xde, 0x2d, 0x62, 0x9a, 0x23, 0xda, 0x20, 0xac, - 0x5c, 0x46, 0x85, 0xe0, 0xd7, 0x40, 0xf1, 0x05, 0x72, 0x12, 0xe4, 0x25, 0xbd, 0x6b, 0x3f, 0xb3, 0xbe, 0x57, 0x3b, - 0xea, 0x99, 0xe6, 0x66, 0x01, 0x27, 0xcf, 0x5c, 0x9e, 0x2d, 0x72, 0x4e, 0xc3, 0xf7, 0x77, 0x73, 0x9a, 0xe3, 0xa7, - 0x9c, 0x04, 0x7c, 0x18, 0x70, 0x97, 0xce, 0xe6, 0xfc, 0xee, 0x5c, 0x30, 0x46, 0xcf, 0xb6, 0x71, 0x08, 0x35, 0x33, - 0xea, 0x07, 0xc0, 0xcc, 0x14, 0xb6, 0xde, 0xa6, 0xf1, 0xdd, 0x84, 0xc5, 0xf1, 0xf9, 0x62, 0x3e, 0x4f, 0x33, 0x8e, - 0xff, 0x4a, 0x96, 0x3c, 0xad, 0x50, 0x03, 0x6b, 0xb9, 0xcc, 0x6f, 0x18, 0x0f, 0x22, 0x87, 0xa3, 0x65, 0xe0, 0xe7, - 0xd4, 0x7a, 0x9a, 0xa6, 0x31, 0xf5, 0x61, 0xd2, 0xc9, 0xf0, 0x29, 0xf7, 0x92, 0x45, 0x1c, 0xf7, 0xae, 0x32, 0xea, - 0x7f, 0xe8, 0x89, 0xd7, 0x6f, 0xae, 0x7e, 0xa2, 0x01, 0xf7, 0xc4, 0xef, 0xd3, 0x2c, 0xf3, 0xef, 0xa0, 0x22, 0x21, - 0x50, 0x6d, 0x98, 0x78, 0x5f, 0x9f, 0xbf, 0x79, 0xed, 0xca, 0x4d, 0xc2, 0x26, 0x77, 0x4e, 0x52, 0x6e, 0xbc, 0xa4, - 0xc0, 0x93, 0x2c, 0x9d, 0xad, 0x0d, 0x2d, 0xb1, 0x96, 0xf4, 0x76, 0x80, 0x40, 0x49, 0xb2, 0x27, 0xbb, 0x36, 0x21, - 0x78, 0x2d, 0x68, 0x1e, 0x5e, 0x12, 0x3d, 0xee, 0x22, 0x8e, 0x3d, 0x59, 0xec, 0x24, 0xe8, 0x7e, 0x68, 0x79, 0x76, - 0xb7, 0xa4, 0x44, 0xc0, 0x39, 0x07, 0x09, 0x03, 0x30, 0x06, 0x3e, 0x0f, 0xa2, 0x25, 0x15, 0x9d, 0x15, 0x1a, 0x62, - 0x5a, 0x14, 0xf8, 0xb4, 0xa4, 0x77, 0x0e, 0x80, 0x08, 0x46, 0x45, 0xf8, 0x6a, 0x05, 0x13, 0x46, 0xf8, 0x6f, 0x64, - 0xe9, 0xeb, 0xf9, 0x78, 0x7b, 0x6d, 0x0c, 0xfb, 0xd2, 0x93, 0xdc, 0x05, 0x07, 0x69, 0x72, 0x4d, 0x33, 0x4e, 0x33, - 0xef, 0xaf, 0x38, 0xa3, 0x93, 0x18, 0xa0, 0xd8, 0xeb, 0xe0, 0xc8, 0xcf, 0xcf, 0x22, 0x3f, 0x99, 0xd2, 0xd0, 0x3b, - 0xe5, 0x05, 0xe6, 0x9c, 0xd8, 0x13, 0x96, 0xf8, 0x31, 0xfb, 0x85, 0x86, 0xb6, 0x12, 0x07, 0xcf, 0x2d, 0x7a, 0xcb, - 0x69, 0x12, 0xe6, 0xd6, 0x8b, 0xf7, 0xaf, 0x5e, 0xaa, 0x85, 0xac, 0x49, 0x08, 0xb4, 0xcc, 0x17, 0x73, 0x9a, 0x39, - 0x08, 0x2b, 0x09, 0xf1, 0x9c, 0x09, 0xee, 0xf8, 0xca, 0x9f, 0xcb, 0x12, 0x96, 0x7f, 0x3b, 0x0f, 0x7d, 0x4e, 0xdf, - 0xd2, 0x24, 0x64, 0xc9, 0x94, 0xec, 0x75, 0x64, 0x79, 0xe4, 0xab, 0x17, 0x61, 0x59, 0x74, 0xb9, 0xff, 0x3c, 0x16, - 0x13, 0x2f, 0x1f, 0x17, 0x0e, 0x2a, 0x72, 0xee, 0x73, 0x16, 0x58, 0x7e, 0x18, 0x7e, 0x95, 0x30, 0xce, 0x04, 0x80, - 0x19, 0xac, 0x0f, 0xd0, 0x28, 0x95, 0xb2, 0x42, 0x03, 0xee, 0x20, 0xec, 0x38, 0x4a, 0x02, 0x44, 0x48, 0x2d, 0xd8, - 0xc1, 0x41, 0xc5, 0xef, 0x87, 0xd4, 0x93, 0x2f, 0xc9, 0xe8, 0x02, 0xb9, 0xf3, 0x45, 0x0e, 0x2b, 0xad, 0x87, 0x00, - 0xf1, 0x92, 0x5e, 0xe5, 0x34, 0xbb, 0xa6, 0x61, 0x49, 0x1d, 0xb9, 0x83, 0x96, 0x6b, 0x63, 0xa8, 0x7d, 0xc1, 0xc9, - 0xe8, 0xa2, 0x67, 0x32, 0x6e, 0xaa, 0x08, 0x3d, 0x4b, 0xe7, 0x34, 0xe3, 0x8c, 0xe6, 0x25, 0x2f, 0x71, 0x40, 0x8c, - 0x96, 0xfc, 0x24, 0x27, 0x7a, 0x7e, 0x73, 0x87, 0x61, 0x8a, 0x6a, 0x1c, 0x43, 0x4b, 0xda, 0xe7, 0xd7, 0x42, 0x64, - 0xe4, 0x98, 0x21, 0xcc, 0x25, 0xa4, 0x39, 0x42, 0x05, 0xc2, 0x5c, 0x83, 0x2b, 0x79, 0x91, 0x1a, 0xed, 0x0e, 0x64, - 0x35, 0xf9, 0x9b, 0x90, 0xd5, 0xc0, 0xd1, 0x7c, 0x4e, 0x0f, 0x0e, 0x1c, 0xea, 0x96, 0x54, 0x41, 0xf6, 0x3a, 0x6a, - 0x8d, 0x0c, 0x64, 0xed, 0x00, 0x1b, 0x06, 0xe6, 0x98, 0x22, 0xbc, 0x47, 0xdd, 0x24, 0x3d, 0x0d, 0x02, 0x9a, 0xe7, - 0x69, 0x76, 0x70, 0xb0, 0x27, 0xea, 0x97, 0xea, 0x04, 0xac, 0xe1, 0x9b, 0x9b, 0xa4, 0x82, 0x00, 0x55, 0x22, 0x56, - 0x09, 0x06, 0x0e, 0x82, 0x4a, 0x68, 0x1c, 0xf6, 0x50, 0x6b, 0x1e, 0x9e, 0x7d, 0x79, 0x69, 0x37, 0x38, 0x56, 0x68, - 0x98, 0x52, 0x3d, 0xf4, 0xdd, 0x33, 0x2a, 0x75, 0x2b, 0xa1, 0x79, 0x6c, 0x60, 0x46, 0x6e, 0x20, 0x37, 0xa4, 0x13, - 0x96, 0x18, 0xd3, 0xae, 0x81, 0x84, 0x39, 0xce, 0x51, 0x61, 0x2c, 0xe8, 0xd6, 0xae, 0x85, 0x52, 0x23, 0x57, 0x6e, - 0x39, 0x15, 0x8a, 0x84, 0xb1, 0x8c, 0x23, 0x7a, 0x51, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x4c, 0x00, 0x3a, 0xe2, 0x17, - 0x3d, 0xf5, 0x9e, 0xe4, 0x12, 0x73, 0x19, 0xfd, 0x79, 0x41, 0x73, 0x2e, 0xe9, 0xd8, 0xe1, 0x38, 0xc3, 0x0c, 0x15, - 0xb0, 0xdf, 0x26, 0x6c, 0xba, 0xc8, 0x40, 0xdf, 0x81, 0xbd, 0x48, 0x93, 0xc5, 0x8c, 0xea, 0xa7, 0x6d, 0xb0, 0xbd, - 0x99, 0x83, 0x44, 0xcc, 0x81, 0xa6, 0xef, 0x27, 0x27, 0x80, 0x95, 0xa3, 0xd5, 0xea, 0x6f, 0xba, 0x93, 0x6a, 0x29, - 0x4b, 0x1d, 0x6d, 0x7d, 0x4d, 0x38, 0x52, 0x12, 0x79, 0xaf, 0x23, 0xc1, 0xe7, 0xfc, 0x82, 0xec, 0xb5, 0x4b, 0x1a, - 0x56, 0x58, 0x95, 0xe0, 0x48, 0x24, 0xbe, 0x91, 0x5d, 0x21, 0x21, 0xe0, 0x6b, 0xe4, 0xe2, 0x46, 0x1b, 0x94, 0x1a, - 0x91, 0x11, 0xa8, 0x1a, 0x6e, 0x74, 0xb1, 0x8b, 0x9c, 0x34, 0x3f, 0x70, 0xf8, 0xe6, 0xbb, 0x8a, 0x6d, 0x5c, 0xd7, - 0xd9, 0xc6, 0xda, 0x34, 0xec, 0x79, 0xd9, 0xc4, 0x2e, 0xa9, 0x4c, 0x6d, 0xf4, 0xea, 0x15, 0x66, 0x02, 0x98, 0x6a, - 0x4a, 0x46, 0x17, 0xaf, 0xfd, 0x19, 0xcd, 0x1d, 0x8a, 0xf0, 0xae, 0x0a, 0x92, 0x3c, 0xa1, 0xca, 0x85, 0x21, 0x39, - 0x73, 0x90, 0x9c, 0x0c, 0x49, 0xc5, 0xac, 0xbe, 0xe1, 0x72, 0x4c, 0x47, 0xf9, 0x45, 0xa5, 0xcf, 0x19, 0x93, 0x17, - 0x22, 0x59, 0xd1, 0xb7, 0xc6, 0x9f, 0x2c, 0x93, 0x48, 0x13, 0x7a, 0x43, 0x8e, 0xf0, 0x5e, 0x7b, 0x7d, 0x25, 0x75, - 0xad, 0x6a, 0x8e, 0xa3, 0x0b, 0x58, 0x07, 0x21, 0x31, 0x5c, 0x96, 0x8b, 0x7f, 0x6b, 0x3b, 0x0d, 0xd0, 0x76, 0x0e, - 0x84, 0xe1, 0x4e, 0x62, 0x9f, 0x3b, 0x9d, 0x56, 0x1b, 0x94, 0xd1, 0x6b, 0x0a, 0x02, 0x05, 0xa1, 0xcd, 0xa9, 0x50, - 0x77, 0x91, 0xe4, 0x11, 0x9b, 0x70, 0x27, 0xe2, 0x82, 0xa5, 0xd0, 0x38, 0xa7, 0x16, 0xaf, 0xa9, 0xc4, 0x82, 0xdd, - 0x44, 0x40, 0x6c, 0xa5, 0xfe, 0x45, 0x35, 0xa4, 0x82, 0x6d, 0x01, 0x77, 0xa8, 0xd4, 0xe9, 0x8a, 0xcb, 0xe8, 0xda, - 0x0c, 0x54, 0xc6, 0xce, 0x50, 0xf6, 0xe8, 0x29, 0x66, 0xc0, 0x0c, 0xad, 0x95, 0x79, 0x26, 0x87, 0x50, 0x85, 0xdc, - 0xe5, 0xe9, 0xcb, 0xf4, 0x86, 0x66, 0x67, 0x3e, 0x00, 0xef, 0xc9, 0xe6, 0x85, 0x14, 0x04, 0x82, 0xdf, 0xf3, 0x9e, - 0xa6, 0x97, 0x4b, 0x31, 0xf1, 0xb7, 0x59, 0x3a, 0x63, 0x39, 0x05, 0x65, 0x4d, 0xe2, 0x3f, 0x81, 0x7d, 0x26, 0x36, - 0x24, 0x08, 0x1b, 0x5a, 0xd2, 0xd7, 0xe9, 0xcb, 0x3a, 0x7d, 0x5d, 0xee, 0x3f, 0x9f, 0x6a, 0x06, 0x58, 0xdf, 0xc6, - 0x08, 0x3b, 0xca, 0xa4, 0x30, 0xe4, 0x9c, 0x1b, 0x21, 0x25, 0xe1, 0x57, 0x2b, 0x6e, 0x58, 0x6e, 0x35, 0x75, 0x91, - 0xca, 0x6d, 0x83, 0x0a, 0x3f, 0x0c, 0x41, 0xb1, 0xcb, 0xd2, 0x38, 0x36, 0x44, 0x15, 0x66, 0xbd, 0x52, 0x38, 0x5d, - 0xee, 0x3f, 0x3f, 0xbf, 0x4f, 0x3e, 0xc1, 0x7b, 0x53, 0x44, 0x69, 0x40, 0x93, 0x90, 0x66, 0x60, 0x49, 0x1a, 0xab, - 0xa5, 0xa4, 0xec, 0x59, 0x9a, 0x24, 0x34, 0xe0, 0x34, 0x04, 0x43, 0x85, 0x11, 0xee, 0x46, 0x69, 0xce, 0xcb, 0xc2, - 0x0a, 0x7a, 0x66, 0x40, 0xcf, 0xdc, 0xc0, 0x8f, 0x63, 0x47, 0x1a, 0x25, 0xb3, 0xf4, 0x9a, 0x6e, 0x81, 0xba, 0x57, - 0x03, 0xb9, 0xec, 0x86, 0x1a, 0xdd, 0x50, 0x37, 0x9f, 0xc7, 0x2c, 0xa0, 0xa5, 0xe8, 0x3a, 0x77, 0x59, 0x12, 0xd2, - 0x5b, 0xe0, 0x23, 0x68, 0x30, 0x18, 0xb4, 0x71, 0x07, 0x15, 0x12, 0xe1, 0xcb, 0x0d, 0xc4, 0xde, 0x23, 0x34, 0x81, - 0xc8, 0xc8, 0x60, 0xb9, 0x8d, 0x1f, 0x50, 0x64, 0x48, 0x4a, 0xa6, 0x8d, 0x2b, 0xc9, 0x9d, 0x11, 0x0e, 0x69, 0x4c, - 0x39, 0xd5, 0xdc, 0x1c, 0x54, 0x68, 0xb9, 0x75, 0xdf, 0x95, 0xf8, 0x2b, 0xc9, 0x49, 0xef, 0x32, 0xbd, 0xe6, 0x79, - 0x69, 0xac, 0x57, 0xcb, 0x53, 0x61, 0x7b, 0xc8, 0xe5, 0xf2, 0xf8, 0x9c, 0xfb, 0x41, 0x24, 0xad, 0x74, 0x67, 0x63, - 0x4a, 0x55, 0x1f, 0x8a, 0xb3, 0x97, 0x9b, 0xe8, 0x9d, 0x06, 0x73, 0x1b, 0x0a, 0xce, 0x15, 0x53, 0xa0, 0x60, 0xf8, - 0xc9, 0x65, 0x3b, 0xf3, 0xe3, 0xf8, 0xca, 0x0f, 0x3e, 0xd4, 0xa9, 0xbf, 0x22, 0x03, 0xb2, 0xce, 0x8d, 0x8d, 0x57, - 0x06, 0xcb, 0x32, 0xe7, 0xad, 0xb9, 0x74, 0x6d, 0xa3, 0x38, 0x7b, 0xed, 0x8a, 0xec, 0xeb, 0x0b, 0xbd, 0x93, 0xda, - 0x05, 0x44, 0x4c, 0xcd, 0xcc, 0x01, 0x2e, 0xf0, 0x51, 0x8a, 0xd3, 0xfc, 0x40, 0xd1, 0x1d, 0x98, 0x1b, 0xc5, 0x1a, - 0x20, 0x1c, 0x2d, 0x8b, 0x90, 0xe5, 0xbb, 0x31, 0xf0, 0xbb, 0x40, 0xf9, 0xcc, 0x18, 0xe1, 0xa1, 0x80, 0x96, 0x3c, - 0x4e, 0x69, 0xcd, 0x25, 0x64, 0x4a, 0x9f, 0xd0, 0x8c, 0xe6, 0x2f, 0xa0, 0xbb, 0x08, 0x7a, 0x7f, 0x23, 0x5f, 0x81, - 0x56, 0x06, 0x50, 0xe4, 0x3d, 0x53, 0x9d, 0xa8, 0x51, 0x80, 0xe2, 0xa9, 0x4c, 0x88, 0xdc, 0xac, 0x66, 0x3f, 0x2a, - 0x8d, 0x5d, 0x9a, 0xe0, 0x8a, 0xe5, 0xa6, 0xc4, 0x71, 0x9c, 0x1c, 0x4c, 0x38, 0xad, 0xda, 0x57, 0x93, 0xc8, 0x37, - 0x26, 0x91, 0xbb, 0x86, 0x9d, 0x85, 0x2a, 0x5a, 0x36, 0x9a, 0x7b, 0x7f, 0x45, 0x66, 0x25, 0x50, 0x57, 0x5d, 0xe0, - 0xcf, 0xa8, 0x64, 0xb7, 0x31, 0xe1, 0x38, 0x55, 0x36, 0x8e, 0xa2, 0x34, 0x60, 0x18, 0x55, 0x93, 0x0c, 0xc9, 0xad, - 0x51, 0xb3, 0x77, 0x33, 0x9c, 0xa2, 0x35, 0xdd, 0xbe, 0x28, 0x14, 0x8e, 0x28, 0x52, 0x6b, 0x53, 0x53, 0x8a, 0x0d, - 0xac, 0xe0, 0x8c, 0x28, 0x45, 0x58, 0xea, 0x3d, 0xeb, 0xb8, 0x29, 0xfb, 0xdd, 0x23, 0x24, 0xab, 0x50, 0x53, 0xd3, - 0x28, 0xb5, 0x6a, 0x95, 0x21, 0x1c, 0x69, 0x9d, 0x34, 0xad, 0xe6, 0x4d, 0x88, 0xad, 0x1d, 0x12, 0xf6, 0x70, 0x59, - 0xb3, 0x0a, 0x3d, 0xa3, 0x5a, 0xe1, 0x01, 0x4b, 0x4d, 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xfa, 0x31, 0x10, 0x9e, - 0x9a, 0x08, 0x37, 0x30, 0x9b, 0x49, 0xce, 0x95, 0x5d, 0x90, 0xa8, 0xde, 0xd6, 0xa1, 0x38, 0x95, 0xeb, 0xb0, 0x81, - 0xc4, 0x75, 0xd5, 0x53, 0x90, 0x20, 0xd8, 0xb0, 0x39, 0x28, 0x77, 0xa6, 0x7c, 0x70, 0x00, 0x76, 0xb6, 0x5a, 0x6d, - 0x10, 0xdd, 0x56, 0x0d, 0x14, 0xb9, 0x95, 0x5d, 0xb8, 0x5a, 0x9d, 0x72, 0xe4, 0x28, 0xdd, 0x17, 0x53, 0x34, 0xd4, - 0x1c, 0xf7, 0xf4, 0x25, 0xd4, 0x12, 0xaa, 0x68, 0x55, 0x52, 0x1a, 0x0d, 0x75, 0x9a, 0xad, 0xaf, 0x13, 0x37, 0xd8, - 0xf6, 0xd9, 0x06, 0xf7, 0x12, 0x85, 0x4a, 0x4c, 0x57, 0x53, 0x3e, 0x53, 0x5d, 0x33, 0x84, 0x90, 0x97, 0x0b, 0x3b, - 0x66, 0x6f, 0x9b, 0x69, 0x79, 0x70, 0x90, 0x1b, 0x1d, 0x5d, 0x96, 0x6c, 0xe2, 0x27, 0x07, 0x44, 0x72, 0x7e, 0x97, - 0x08, 0xdd, 0xe5, 0x27, 0x2d, 0x84, 0x36, 0x0c, 0xd3, 0x76, 0x0f, 0x0c, 0x72, 0xff, 0xc6, 0x67, 0xdc, 0x2a, 0x7b, - 0x91, 0x06, 0xb9, 0x43, 0xd1, 0x52, 0xa9, 0x1a, 0x6e, 0x46, 0x41, 0x79, 0x04, 0x9e, 0xa0, 0x55, 0x68, 0x49, 0xf7, - 0x41, 0x44, 0xc1, 0x17, 0xac, 0xb5, 0x88, 0xd2, 0x32, 0xdc, 0x53, 0x52, 0x44, 0x75, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, - 0x79, 0xcd, 0x12, 0x98, 0xd3, 0x6c, 0x92, 0x66, 0x33, 0xfd, 0xae, 0x58, 0x7b, 0x56, 0x9c, 0x91, 0x4d, 0x9c, 0xad, - 0x7d, 0x2b, 0xfd, 0xbf, 0xb7, 0x66, 0x76, 0x57, 0x06, 0x7b, 0x4d, 0x94, 0x96, 0xd2, 0x57, 0xba, 0x04, 0x35, 0x65, - 0xe6, 0xa6, 0x81, 0xaf, 0xfc, 0xa9, 0x3d, 0xe9, 0x33, 0xd9, 0xeb, 0xf4, 0x4a, 0xab, 0x4f, 0x53, 0x43, 0x4f, 0xfa, - 0x36, 0x94, 0x48, 0x4d, 0x17, 0x71, 0xa8, 0x80, 0x65, 0x08, 0x53, 0x45, 0x47, 0x37, 0x2c, 0x8e, 0xab, 0xd2, 0x4f, - 0xe1, 0xeb, 0xb9, 0xe2, 0xeb, 0x99, 0xe6, 0xeb, 0xc0, 0x29, 0x80, 0xaf, 0xcb, 0xee, 0xaa, 0xe6, 0xd9, 0xc6, 0xee, - 0xcc, 0x24, 0x47, 0xcf, 0x85, 0x25, 0x0d, 0xe3, 0x2d, 0x34, 0x04, 0xa8, 0xd4, 0xbc, 0x3e, 0x38, 0xca, 0x0f, 0x03, - 0x26, 0xa0, 0xf4, 0x62, 0x52, 0xd3, 0x49, 0xf1, 0xc1, 0x41, 0x38, 0x2f, 0x68, 0x49, 0xd9, 0xa7, 0xcf, 0xc1, 0x4f, - 0x67, 0x4c, 0x07, 0x84, 0x98, 0x28, 0xfe, 0x24, 0x25, 0x4a, 0xcf, 0x8e, 0xa9, 0xd9, 0xe5, 0x7a, 0x76, 0xc0, 0xe9, - 0xab, 0xd9, 0x85, 0xf7, 0xf3, 0x7a, 0x31, 0x3d, 0x56, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0xca, 0x59, 0x2b, 0x01, 0x17, - 0xbe, 0x32, 0x51, 0xb2, 0xb2, 0x77, 0xe0, 0x01, 0x26, 0x66, 0xa0, 0xa0, 0x90, 0x93, 0x2e, 0x45, 0xdc, 0xcb, 0x8f, - 0xb9, 0x78, 0x84, 0xa7, 0x5e, 0xb6, 0x3f, 0x4b, 0x67, 0x73, 0xd0, 0xc6, 0xd6, 0x48, 0x7a, 0x4a, 0xd5, 0x80, 0xd5, - 0xfb, 0x62, 0x4b, 0x59, 0xad, 0x8d, 0xd8, 0x8f, 0x35, 0x6a, 0x2a, 0x2d, 0xe6, 0xbd, 0x76, 0xb1, 0x28, 0x8b, 0x4a, - 0xc6, 0xb1, 0xcd, 0xad, 0x72, 0xb6, 0xee, 0x94, 0xd1, 0x2f, 0xde, 0x38, 0x4c, 0xf2, 0x61, 0x06, 0xbc, 0xce, 0x60, - 0x3f, 0x9a, 0xdc, 0xcd, 0xf5, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0xb9, 0xb2, 0xb2, 0xf1, - 0xf3, 0xdd, 0xe6, 0x70, 0xf5, 0x4e, 0x59, 0x8b, 0xa3, 0x0b, 0xfc, 0x7c, 0x53, 0x77, 0x24, 0xcb, 0x59, 0x1a, 0x52, - 0xcf, 0x4e, 0xe7, 0x34, 0xb1, 0x0b, 0xf0, 0xac, 0xaa, 0xc5, 0x0f, 0xb9, 0xb3, 0x7c, 0x57, 0x77, 0xb1, 0x7a, 0xcf, - 0x0b, 0x70, 0x80, 0x7d, 0xbf, 0xe9, 0x7c, 0xfd, 0x8e, 0x66, 0xb9, 0xd0, 0x44, 0x4b, 0xa5, 0xf6, 0xfb, 0x4a, 0x2e, - 0x7d, 0xef, 0xed, 0xac, 0x5f, 0xd9, 0x20, 0x76, 0xc7, 0x7d, 0xe4, 0x1e, 0xda, 0x48, 0xb8, 0x86, 0xbf, 0x56, 0x3b, - 0xfe, 0x27, 0xed, 0x1a, 0x3e, 0x27, 0x3f, 0xd5, 0x3d, 0xc3, 0x0b, 0x4e, 0xce, 0x87, 0xe7, 0xda, 0x64, 0x4e, 0x63, - 0x16, 0xdc, 0x39, 0x76, 0xcc, 0x78, 0x13, 0xc2, 0x6f, 0x36, 0x5e, 0xca, 0x17, 0xe0, 0x55, 0x14, 0x2e, 0xed, 0x42, - 0x1b, 0x7b, 0x98, 0x72, 0x62, 0xef, 0xc7, 0x8c, 0xef, 0xdb, 0x78, 0x42, 0xc6, 0xf0, 0x63, 0x7f, 0xe9, 0xbc, 0xf2, - 0x79, 0xe4, 0x66, 0x7e, 0x12, 0xa6, 0x33, 0x07, 0x35, 0x6c, 0x1b, 0xb9, 0xb9, 0x30, 0x38, 0x9e, 0xa0, 0x62, 0x7f, - 0x8c, 0x9f, 0x73, 0x62, 0x0f, 0xed, 0xc6, 0x04, 0xbf, 0xe0, 0x64, 0xdc, 0xdf, 0x5f, 0x3e, 0xe7, 0xc5, 0x60, 0x8c, - 0x6f, 0x4b, 0xaf, 0x3d, 0xfe, 0x96, 0x38, 0x88, 0x0c, 0x6e, 0x15, 0x34, 0x67, 0xe9, 0x4c, 0x7a, 0xef, 0x6d, 0x84, - 0xdf, 0x8b, 0xd8, 0x4a, 0xc5, 0x6e, 0x54, 0x78, 0x65, 0x8f, 0xd8, 0xa9, 0xf0, 0x11, 0xd8, 0x07, 0x07, 0x46, 0x59, - 0xa9, 0x2b, 0xe0, 0x73, 0x4e, 0x6a, 0x16, 0x39, 0x7e, 0x25, 0xa2, 0x34, 0xe7, 0xdc, 0x49, 0x90, 0xee, 0xc6, 0xd1, - 0xbe, 0x68, 0xb5, 0x37, 0x93, 0x91, 0x74, 0x31, 0xb8, 0x8c, 0xd3, 0xcc, 0xe7, 0x69, 0x76, 0x81, 0x4c, 0xfd, 0x03, - 0xff, 0x85, 0x8c, 0x47, 0xd6, 0x7f, 0xfa, 0xec, 0xc7, 0xc9, 0x8f, 0xd9, 0xc5, 0x18, 0xbf, 0x25, 0xad, 0xbe, 0x33, - 0xf4, 0x9c, 0xbd, 0x66, 0x73, 0xf5, 0x63, 0x6b, 0xf4, 0x77, 0xbf, 0xf9, 0xcb, 0x69, 0xf3, 0x6f, 0x17, 0x68, 0xe5, - 0xfc, 0xd8, 0x1a, 0x8e, 0xd4, 0xd3, 0xe8, 0xef, 0x83, 0x1f, 0xf3, 0x8b, 0x3f, 0xca, 0xc2, 0x7d, 0x84, 0x5a, 0x53, - 0x3c, 0xe7, 0xa4, 0xd5, 0x6c, 0x0e, 0x5a, 0x53, 0x3c, 0xe5, 0xa4, 0x05, 0xff, 0x5e, 0x91, 0x77, 0x74, 0xfa, 0xfc, - 0x76, 0xee, 0x8c, 0x07, 0xab, 0xfd, 0xe5, 0x5f, 0x0a, 0xe8, 0x75, 0xf4, 0xf7, 0x1f, 0x7f, 0xcc, 0xed, 0x2f, 0x06, - 0xa4, 0x75, 0xd1, 0x40, 0x0e, 0x94, 0xfe, 0x91, 0x88, 0xbf, 0xce, 0xd0, 0x1b, 0xfd, 0x5d, 0x41, 0x61, 0x7f, 0xf1, - 0xe3, 0xb8, 0x3f, 0x20, 0x17, 0x2b, 0xc7, 0x5e, 0x7d, 0x81, 0x56, 0x08, 0xad, 0xf6, 0xd1, 0x18, 0xdb, 0x53, 0x1b, - 0xe1, 0x4b, 0x4e, 0x5a, 0x5f, 0xb4, 0xa6, 0xf8, 0x9a, 0x93, 0x96, 0xdd, 0x9a, 0xe2, 0x33, 0x4e, 0x5a, 0x7f, 0x77, - 0x86, 0x9e, 0x74, 0xb2, 0xad, 0x84, 0x7f, 0x63, 0x05, 0x01, 0x0e, 0x3f, 0xa3, 0xfe, 0x8a, 0x33, 0x1e, 0x53, 0xb4, - 0xdf, 0x62, 0xf8, 0x8d, 0x40, 0x93, 0xc3, 0xc1, 0x0b, 0x03, 0xc6, 0x9d, 0xb3, 0xbc, 0x84, 0xc5, 0x06, 0x9a, 0xd9, - 0xf7, 0x20, 0xb2, 0x03, 0x8e, 0x80, 0xdc, 0xe3, 0xf8, 0xda, 0x8f, 0x17, 0x34, 0xf7, 0x68, 0x81, 0x70, 0x4c, 0xde, - 0x70, 0xa7, 0x83, 0xf0, 0x4b, 0x0e, 0x3f, 0xba, 0x08, 0x9f, 0xa9, 0x20, 0x26, 0xec, 0x64, 0x49, 0x54, 0x49, 0x2a, - 0x55, 0x16, 0x1b, 0xe1, 0xf9, 0x96, 0x97, 0x3c, 0x02, 0xf7, 0x02, 0xc2, 0xfb, 0xb5, 0x90, 0x27, 0xbe, 0x21, 0x9a, - 0x24, 0xde, 0x67, 0x94, 0x7e, 0xef, 0xc7, 0x1f, 0x68, 0xe6, 0xdc, 0xe2, 0x4e, 0xf7, 0x09, 0x16, 0x5e, 0xe8, 0xbd, - 0x0e, 0xea, 0x95, 0xf1, 0xaa, 0x0f, 0x5c, 0xc6, 0x09, 0x40, 0xca, 0xd6, 0x9d, 0x31, 0xb0, 0xe2, 0x7b, 0xc9, 0x86, - 0xc7, 0x2a, 0xf3, 0x6f, 0x6c, 0x54, 0x8f, 0x8d, 0xb2, 0xe4, 0xda, 0x8f, 0x59, 0x68, 0x71, 0x3a, 0x9b, 0xc7, 0x3e, - 0xa7, 0x96, 0x9a, 0xaf, 0xe5, 0x43, 0x47, 0x76, 0xa9, 0x33, 0x2c, 0x0c, 0x8b, 0x73, 0xa1, 0x83, 0x4e, 0xb0, 0x57, - 0x1c, 0x88, 0x50, 0x29, 0xbd, 0xe3, 0x59, 0x15, 0x00, 0x5b, 0x8f, 0xf1, 0x35, 0x3b, 0xe0, 0x09, 0xbb, 0x10, 0xf2, - 0x39, 0xc7, 0x19, 0x01, 0x29, 0xda, 0x1d, 0xda, 0xfd, 0xfc, 0x7a, 0x3a, 0xb0, 0x21, 0x3e, 0x93, 0x92, 0xb7, 0xc2, - 0x31, 0x04, 0x15, 0x22, 0xd2, 0xee, 0x45, 0x7d, 0xda, 0x8b, 0x1a, 0x0d, 0xad, 0x44, 0xfb, 0x24, 0x19, 0x45, 0xb2, - 0x79, 0x80, 0x43, 0xbc, 0x20, 0xcd, 0x0e, 0x9e, 0x92, 0xb6, 0x68, 0xd2, 0x9b, 0xf6, 0x7d, 0x35, 0xcc, 0xc1, 0x81, - 0x93, 0xba, 0xb1, 0x9f, 0xf3, 0xaf, 0xc0, 0xda, 0x27, 0x53, 0x1c, 0x92, 0xd4, 0xa5, 0xb7, 0x34, 0x70, 0x7c, 0x84, - 0x43, 0xc5, 0x69, 0x50, 0x0f, 0x4d, 0x89, 0x51, 0x0d, 0xac, 0x08, 0xf2, 0x76, 0x18, 0x8e, 0x3a, 0x17, 0x84, 0x10, - 0x7b, 0xaf, 0xd9, 0xb4, 0x87, 0x29, 0x99, 0x73, 0x0f, 0x4a, 0x0c, 0x5d, 0x99, 0x4c, 0xa1, 0xa8, 0x6b, 0x14, 0x39, - 0x67, 0xdc, 0xe5, 0x34, 0xe7, 0x0e, 0x14, 0x83, 0xfd, 0x9f, 0x6b, 0xc2, 0xb6, 0xfb, 0x2d, 0xbb, 0x01, 0xa5, 0x82, - 0x38, 0x11, 0x4e, 0xc9, 0x15, 0xf2, 0xc2, 0xd1, 0xe1, 0x85, 0x29, 0x00, 0x44, 0x21, 0x0c, 0x7e, 0x35, 0x0c, 0x47, - 0x6d, 0x31, 0xf8, 0xc0, 0x1e, 0x3a, 0x29, 0xc9, 0xa5, 0x86, 0x36, 0xcc, 0xbd, 0xb7, 0x62, 0xaa, 0xc8, 0x53, 0xc0, - 0xe9, 0x15, 0x20, 0xcd, 0xae, 0xe7, 0x2c, 0xcc, 0x49, 0x34, 0x61, 0x30, 0x85, 0x05, 0x1c, 0x10, 0xa8, 0x8f, 0x53, - 0x02, 0x23, 0x56, 0xcd, 0xae, 0x3c, 0xf5, 0xfc, 0x85, 0xfd, 0xc5, 0xf0, 0x9a, 0x7b, 0x97, 0x5c, 0x0e, 0x7f, 0xcd, - 0x57, 0x2b, 0xf8, 0xf7, 0x92, 0x0f, 0x53, 0x72, 0x25, 0x8a, 0xe6, 0xaa, 0x68, 0x0a, 0x45, 0x6f, 0x3d, 0x00, 0x15, - 0xe7, 0xa5, 0x96, 0x25, 0xd7, 0xe4, 0x92, 0x08, 0xd8, 0x0f, 0x0e, 0x92, 0x51, 0xd4, 0xe8, 0x5c, 0x80, 0x8b, 0x3f, - 0xe3, 0xf9, 0xf7, 0x8c, 0x47, 0x8e, 0xdd, 0x1a, 0xd8, 0x68, 0x68, 0x5b, 0xb0, 0xb4, 0xbd, 0xac, 0x41, 0x24, 0x86, - 0xfd, 0xc6, 0x0b, 0xee, 0x2d, 0x06, 0xa4, 0x3d, 0x74, 0x98, 0x64, 0xe1, 0x01, 0xc2, 0xbe, 0x62, 0x9c, 0x6d, 0xbc, - 0x40, 0x0d, 0xca, 0x1b, 0xfa, 0x79, 0x81, 0x1a, 0x93, 0xc6, 0x25, 0xf2, 0xfc, 0xc6, 0xa4, 0xe1, 0x2c, 0x08, 0x21, - 0xcd, 0x6e, 0xd9, 0x4c, 0x8b, 0xbf, 0x08, 0x79, 0x97, 0xda, 0xdb, 0x39, 0x12, 0xdb, 0x21, 0x6b, 0x38, 0xc9, 0x88, - 0x5e, 0xac, 0x56, 0x76, 0x7f, 0x38, 0xb0, 0x51, 0xc3, 0xd1, 0x84, 0xd6, 0xd2, 0x94, 0x86, 0x10, 0x66, 0x17, 0x85, - 0x8a, 0x26, 0xbd, 0xae, 0x45, 0x8e, 0x96, 0xd5, 0x66, 0x37, 0x78, 0x00, 0x2d, 0x4a, 0x43, 0x46, 0x2a, 0xac, 0x73, - 0x98, 0xa6, 0x26, 0xe6, 0x8c, 0xb4, 0x71, 0x4a, 0xb4, 0xf3, 0x3a, 0x22, 0xbc, 0x22, 0x78, 0x9f, 0x54, 0xd5, 0xf1, - 0x28, 0xc0, 0xe1, 0x05, 0x79, 0x26, 0x0d, 0x92, 0x9e, 0x76, 0x8d, 0xd3, 0x98, 0xbc, 0x5e, 0x8b, 0xe0, 0x06, 0x10, - 0x5e, 0xb9, 0x71, 0x83, 0x45, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcd, - 0x62, 0x50, 0xd2, 0xba, 0x7a, 0x67, 0x2c, 0x36, 0x5e, 0x4f, 0xc9, 0x42, 0xea, 0x4f, 0x22, 0x60, 0xdb, 0x9b, 0x2a, - 0xc3, 0xd8, 0x41, 0x78, 0xa1, 0x22, 0xb9, 0x8e, 0xeb, 0xba, 0x53, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, - 0x8f, 0x9c, 0x9c, 0xdc, 0xb8, 0x09, 0xbd, 0x15, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0xf5, 0xa3, 0x9e, 0x60, - 0x37, 0xb9, 0x9b, 0xa4, 0x21, 0x05, 0xf4, 0x40, 0xec, 0x5e, 0x15, 0x45, 0x7e, 0x6e, 0x86, 0xa8, 0x2a, 0xf8, 0x46, - 0xa6, 0xf7, 0x7a, 0x0a, 0x2e, 0x5f, 0xa1, 0x6c, 0x95, 0x95, 0xa5, 0x1f, 0x1c, 0x21, 0x36, 0x71, 0xa6, 0x2e, 0x84, - 0xf6, 0x04, 0x09, 0x51, 0xb0, 0xe5, 0xa6, 0x26, 0x51, 0x4d, 0xca, 0x3e, 0x2f, 0x49, 0x38, 0x4a, 0x1b, 0x0d, 0xe1, - 0x86, 0x5e, 0x48, 0x92, 0x98, 0x22, 0x7c, 0x59, 0xee, 0x2d, 0x5d, 0xef, 0x3b, 0x52, 0x1f, 0xc9, 0xb9, 0xac, 0xbb, - 0x73, 0x1b, 0x90, 0x26, 0x01, 0x9e, 0x42, 0xee, 0x4c, 0x10, 0x3e, 0x25, 0x2d, 0x67, 0xe4, 0x0e, 0xff, 0x74, 0x81, - 0x86, 0x8e, 0xfb, 0x47, 0xd4, 0x92, 0x8c, 0xe3, 0x12, 0xf5, 0x7c, 0x39, 0xc4, 0x52, 0x84, 0x30, 0x3b, 0x58, 0x78, - 0x12, 0xbd, 0x0c, 0x27, 0xfe, 0x8c, 0x7a, 0xa7, 0xb0, 0xc7, 0x35, 0xdd, 0x7c, 0x87, 0x81, 0x8e, 0xbc, 0x53, 0xc5, - 0x49, 0x5c, 0x7b, 0xf8, 0x15, 0x2f, 0x9f, 0x86, 0xf6, 0xf0, 0x97, 0xea, 0xe9, 0x4f, 0xf6, 0xf0, 0x4b, 0xee, 0xfd, - 0x52, 0x28, 0x67, 0x77, 0x6d, 0x88, 0x47, 0x7a, 0x88, 0x42, 0x2e, 0x8c, 0x81, 0xb9, 0x05, 0xda, 0xf4, 0x73, 0x4c, - 0x51, 0xc1, 0x26, 0x25, 0x2b, 0xca, 0x5d, 0xee, 0x4f, 0x01, 0xa5, 0xc6, 0x0a, 0xe4, 0x66, 0x64, 0xbf, 0x9a, 0x30, - 0x10, 0x8a, 0xa6, 0x56, 0x40, 0xe5, 0x74, 0xd0, 0x46, 0xcb, 0x5a, 0x5d, 0xa1, 0x31, 0xd5, 0x23, 0xe9, 0x25, 0x97, - 0xbe, 0x24, 0xed, 0xde, 0x65, 0x7f, 0xda, 0xbb, 0x6c, 0x34, 0x50, 0xae, 0x09, 0x6b, 0x31, 0xba, 0xbc, 0xc0, 0xdf, - 0x82, 0x4f, 0xcf, 0xa4, 0x24, 0x5c, 0x9b, 0x5e, 0x57, 0x4d, 0xaf, 0xd1, 0xc8, 0x0a, 0xd4, 0x33, 0x9a, 0x4e, 0x65, - 0xd3, 0xa2, 0x90, 0x38, 0x59, 0x27, 0xb4, 0x13, 0x24, 0x4a, 0x20, 0x1d, 0x8a, 0x10, 0xf2, 0x9c, 0xa3, 0xad, 0xbd, - 0x42, 0x9f, 0xd0, 0x5c, 0xec, 0x58, 0x60, 0x9e, 0x52, 0x46, 0x38, 0x80, 0x05, 0x68, 0x5a, 0x3a, 0x82, 0x27, 0x78, - 0xd1, 0xe8, 0x08, 0x22, 0x6f, 0x76, 0x7a, 0xf5, 0xbe, 0x1e, 0x57, 0x7d, 0xe1, 0x45, 0x83, 0x4c, 0x4a, 0x2c, 0x15, - 0x59, 0xa3, 0x51, 0xd4, 0xa3, 0x9d, 0x7a, 0xdf, 0xd6, 0xe2, 0x0f, 0xb7, 0xeb, 0x69, 0x19, 0x5a, 0xbe, 0x56, 0x12, - 0x95, 0xb9, 0x2c, 0x49, 0x68, 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, - 0x12, 0xe0, 0x3b, 0xc2, 0xec, 0xc2, 0x19, 0x4e, 0x71, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x4c, 0x27, 0xb4, 0x70, 0xc1, - 0x81, 0x7c, 0xc2, 0x0c, 0x89, 0x94, 0x13, 0xea, 0x5e, 0xee, 0x9f, 0xa5, 0xf7, 0x9a, 0x64, 0x23, 0x76, 0xe1, 0x89, - 0x6a, 0xb1, 0xe2, 0x5b, 0x01, 0x79, 0xef, 0x70, 0x54, 0x06, 0x47, 0x5c, 0xc1, 0xfe, 0x9e, 0xb1, 0x8c, 0x0a, 0x0d, - 0x7c, 0x5f, 0x9b, 0x7d, 0x7e, 0x5d, 0x7d, 0xf4, 0x4d, 0xe7, 0x0d, 0x20, 0x32, 0x00, 0xdf, 0x4e, 0x46, 0x36, 0xaa, - 0x5d, 0xee, 0x9f, 0xbe, 0xd9, 0x66, 0x02, 0xaf, 0x56, 0xca, 0xf8, 0xf5, 0x41, 0xb3, 0xc1, 0x41, 0x05, 0xa9, 0xaf, - 0x7e, 0x78, 0x8e, 0x2f, 0x14, 0xa4, 0xc0, 0x49, 0x80, 0x8a, 0x2e, 0xf7, 0x4f, 0xdf, 0x3b, 0x89, 0x70, 0x2d, 0x21, - 0x6c, 0x4e, 0xdb, 0x49, 0x89, 0x13, 0x11, 0x8a, 0xe4, 0xdc, 0x4b, 0xc6, 0x95, 0x1a, 0xe2, 0xdb, 0x8b, 0xc4, 0x4b, - 0xb0, 0x1f, 0x46, 0xec, 0x82, 0xf8, 0x0a, 0x03, 0xc4, 0x47, 0xd8, 0xaf, 0x99, 0x65, 0x04, 0x16, 0x40, 0x8c, 0x75, - 0x0e, 0x2b, 0xe1, 0x4a, 0xc5, 0x0f, 0x61, 0x5f, 0x8c, 0xca, 0x0b, 0x29, 0x3a, 0x7e, 0xda, 0xc8, 0x4b, 0xab, 0xac, - 0xd1, 0xef, 0xc0, 0x72, 0xd2, 0x0f, 0xaf, 0x55, 0xd7, 0x65, 0xc1, 0x33, 0x9d, 0x40, 0x76, 0xb9, 0x7f, 0xfa, 0x4a, - 0xe5, 0x90, 0xcd, 0x7d, 0xcd, 0xed, 0x37, 0x2c, 0xcc, 0xd3, 0x57, 0x6e, 0xf5, 0x56, 0x54, 0xbe, 0xdc, 0x3f, 0xfd, - 0x76, 0x5b, 0x35, 0x28, 0x2f, 0x16, 0x95, 0x89, 0x2f, 0xe0, 0x5b, 0xd2, 0xd8, 0x5b, 0x2a, 0xd1, 0xe0, 0xb1, 0x02, - 0x0b, 0x71, 0xe4, 0xe5, 0x45, 0xe9, 0x19, 0x79, 0x86, 0x33, 0x22, 0xa2, 0x40, 0xf5, 0x55, 0x53, 0x4a, 0x1e, 0x4b, - 0x93, 0xf3, 0x20, 0x9d, 0xd3, 0x1d, 0xa1, 0xa1, 0x5b, 0xe4, 0xb2, 0x19, 0x24, 0xcf, 0x08, 0xd0, 0x19, 0xde, 0x6b, - 0xa3, 0x5e, 0x5d, 0x78, 0x65, 0x82, 0x48, 0xd3, 0x9a, 0x64, 0xc1, 0x11, 0x69, 0x63, 0x9f, 0xb4, 0x71, 0x40, 0xf2, - 0x51, 0x5b, 0x8a, 0x87, 0x5e, 0x50, 0xf6, 0x2b, 0x85, 0x0c, 0xe4, 0x85, 0x05, 0x72, 0xb7, 0x4a, 0xf1, 0x1b, 0xf6, - 0x02, 0xe1, 0x7a, 0x14, 0x12, 0x3d, 0x14, 0x64, 0xf1, 0xd4, 0x49, 0x71, 0x2a, 0x3a, 0x3e, 0x67, 0x57, 0x31, 0xa4, - 0x96, 0xc0, 0xac, 0x30, 0x47, 0x5e, 0x59, 0xb5, 0xa3, 0xaa, 0x06, 0xae, 0x58, 0xa7, 0x14, 0x07, 0x2e, 0x30, 0x6e, - 0x1c, 0xa8, 0x4c, 0x9c, 0x7c, 0xb3, 0xc9, 0xa3, 0x83, 0x03, 0x47, 0x36, 0xfa, 0x8e, 0x3b, 0xa9, 0x7e, 0x5f, 0x05, - 0xee, 0xbe, 0x93, 0xbc, 0x22, 0x44, 0x02, 0xfe, 0x46, 0xc3, 0xbf, 0x28, 0x20, 0x0a, 0xed, 0x04, 0x75, 0x0c, 0x6a, - 0xe0, 0x85, 0xa6, 0x57, 0x9f, 0x7e, 0xa3, 0x51, 0x06, 0x69, 0xeb, 0xd8, 0xba, 0xc5, 0x59, 0x71, 0xed, 0x94, 0xc9, - 0x3f, 0xed, 0x8d, 0x8c, 0x29, 0x0d, 0x02, 0x62, 0x26, 0xcd, 0x32, 0x3d, 0x19, 0x63, 0x4b, 0x30, 0xa8, 0xf7, 0x95, - 0x4a, 0x5b, 0xc0, 0x22, 0xbf, 0x4a, 0x55, 0xd2, 0xec, 0xac, 0x8b, 0x3c, 0x5d, 0x09, 0x82, 0x52, 0x50, 0xa9, 0x51, - 0x28, 0xf2, 0x7e, 0xba, 0x99, 0x75, 0x89, 0x73, 0xa4, 0x7c, 0x5c, 0x02, 0x0a, 0x81, 0xac, 0x6e, 0x89, 0x94, 0x17, - 0x64, 0xbe, 0x9b, 0xe4, 0x4f, 0x0d, 0x92, 0x7f, 0x4a, 0xa8, 0x41, 0xfe, 0xd2, 0xc3, 0xe1, 0xa6, 0xca, 0xb5, 0x90, - 0xeb, 0x57, 0x67, 0x73, 0x02, 0x3e, 0xb4, 0x3a, 0x46, 0x6b, 0x51, 0xc5, 0x1d, 0x0c, 0xc5, 0xdc, 0x21, 0xc2, 0x0b, - 0x89, 0x75, 0x08, 0xd8, 0xa9, 0x62, 0x6a, 0x30, 0xf4, 0x36, 0x97, 0x9e, 0xc9, 0x01, 0x4f, 0xbf, 0xbd, 0x3f, 0x1c, - 0x7a, 0x36, 0xdf, 0xdc, 0xb9, 0x46, 0xf6, 0x27, 0xcc, 0xda, 0xd8, 0xb8, 0xf5, 0x5c, 0x50, 0x18, 0xbf, 0x0c, 0x63, - 0xd7, 0x99, 0xcf, 0xda, 0x26, 0xd4, 0xf2, 0x0f, 0xa0, 0xed, 0x74, 0x44, 0x0d, 0x6a, 0x74, 0x0b, 0xfc, 0x48, 0xe6, - 0xa0, 0xfa, 0xd9, 0x0e, 0xf6, 0x71, 0x2a, 0x2a, 0xd0, 0x24, 0xdc, 0xfe, 0xfa, 0x69, 0xa1, 0xc8, 0x44, 0x82, 0x86, - 0x96, 0xc0, 0xff, 0x24, 0xc9, 0x03, 0xdd, 0x08, 0xb9, 0x00, 0x08, 0x9a, 0x0b, 0x3c, 0x55, 0x08, 0xb3, 0xed, 0xca, - 0xf9, 0xfe, 0x62, 0x8f, 0x90, 0x79, 0xe5, 0x7c, 0x7c, 0x57, 0xe5, 0x5e, 0x01, 0x59, 0x20, 0x0f, 0x8c, 0xc7, 0xb2, - 0x40, 0x46, 0x2f, 0xcf, 0x74, 0x75, 0x61, 0x40, 0xba, 0x95, 0xbe, 0x6d, 0x44, 0x36, 0x85, 0x57, 0x4e, 0xbe, 0xd7, - 0x68, 0x58, 0x7b, 0xbb, 0x0f, 0x6f, 0x5f, 0x71, 0x01, 0x23, 0x3c, 0xbf, 0x17, 0xb5, 0x75, 0xbf, 0xc5, 0x87, 0xf5, - 0x04, 0x96, 0xb5, 0x45, 0x71, 0x59, 0x92, 0xd3, 0x8c, 0x3f, 0xa5, 0x93, 0x34, 0x83, 0x90, 0x45, 0x89, 0x13, 0x54, - 0xec, 0x1b, 0x6e, 0x3b, 0x31, 0x3f, 0x23, 0x4e, 0xb0, 0x36, 0x41, 0xf1, 0xeb, 0x83, 0x88, 0x59, 0x5f, 0xae, 0xb7, - 0x9a, 0x1f, 0x1c, 0xbc, 0xaf, 0xd0, 0xa4, 0xa0, 0x14, 0x50, 0x18, 0x4c, 0x4b, 0xaa, 0x34, 0x2a, 0x90, 0xbb, 0xef, - 0x94, 0x2e, 0x00, 0xcd, 0x30, 0x4c, 0xde, 0xf3, 0x82, 0xf0, 0x62, 0xba, 0xce, 0xe2, 0x95, 0x6b, 0x82, 0x99, 0x66, - 0x0b, 0x70, 0x78, 0x30, 0xb4, 0xa5, 0xaf, 0x28, 0xaf, 0xd2, 0x61, 0x4b, 0x18, 0xce, 0x00, 0x59, 0x8e, 0x30, 0x42, - 0x0c, 0x0a, 0xdc, 0x6a, 0x94, 0x7c, 0x00, 0xbd, 0x32, 0xc2, 0xb9, 0x1b, 0x41, 0x02, 0x6c, 0x6d, 0xcb, 0x22, 0x84, - 0x65, 0x5e, 0x8e, 0x91, 0x49, 0x70, 0xfa, 0x62, 0x9b, 0x47, 0x59, 0x13, 0x35, 0x15, 0x52, 0x07, 0x6a, 0x64, 0xa8, - 0x6c, 0xe0, 0x5e, 0x3b, 0x4c, 0x29, 0x6e, 0x3a, 0x6c, 0x06, 0x0c, 0xf8, 0x27, 0xee, 0xc8, 0x58, 0x14, 0xc8, 0x8c, - 0xd4, 0x5d, 0x38, 0xb5, 0xa1, 0x7b, 0xa9, 0x68, 0x86, 0x15, 0xe2, 0x22, 0x13, 0x4d, 0xa9, 0x08, 0xeb, 0x9d, 0x55, - 0xbc, 0x74, 0x5f, 0xe6, 0x50, 0x73, 0xcd, 0x05, 0xab, 0x3c, 0x12, 0x63, 0xfa, 0xfb, 0x32, 0x2d, 0xba, 0xac, 0x04, - 0x6a, 0x18, 0xbd, 0xb1, 0x5e, 0x8b, 0x35, 0xa0, 0x05, 0xd0, 0xd7, 0xf2, 0x9c, 0x1b, 0x2b, 0xaa, 0x7d, 0xd8, 0x62, - 0x4c, 0x43, 0xea, 0xbf, 0x83, 0x4c, 0x97, 0xf5, 0x3d, 0xff, 0x42, 0xc8, 0x42, 0x86, 0xf3, 0x1a, 0x63, 0xcf, 0x04, - 0x63, 0x47, 0xa0, 0xa7, 0xe9, 0xd4, 0xef, 0xa1, 0x4a, 0x78, 0x61, 0x4a, 0xca, 0x29, 0x12, 0xfb, 0xb6, 0x0c, 0x96, - 0x1b, 0xbf, 0xd7, 0x56, 0xc3, 0x63, 0x04, 0x92, 0x80, 0xb0, 0xe2, 0xec, 0x19, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xfb, - 0xb4, 0x72, 0x91, 0x54, 0x30, 0x32, 0x88, 0xe7, 0x02, 0xc1, 0xd7, 0x64, 0x28, 0x44, 0xfc, 0x75, 0x6e, 0x76, 0x0e, - 0xae, 0xf6, 0xd3, 0x77, 0x8e, 0xc9, 0xd5, 0xcc, 0xba, 0x65, 0xcc, 0x14, 0xe6, 0xe3, 0x54, 0xf1, 0x96, 0xb7, 0xf7, - 0xe7, 0x77, 0x00, 0xdc, 0x7b, 0x1d, 0x0c, 0xb9, 0x68, 0xa8, 0xc7, 0x25, 0x4b, 0x28, 0x77, 0x5f, 0x0f, 0x55, 0x69, - 0x89, 0xe6, 0x60, 0x3d, 0x5e, 0x99, 0xb2, 0x9c, 0xe4, 0x45, 0x91, 0xd3, 0x2a, 0xba, 0xbf, 0x96, 0x7f, 0x29, 0x84, - 0xcb, 0xa6, 0xb3, 0xfd, 0x6c, 0x4e, 0x38, 0x36, 0x08, 0xf5, 0xed, 0xae, 0xd0, 0x47, 0x05, 0x26, 0xec, 0x6b, 0x25, - 0x14, 0x7f, 0xd9, 0x26, 0x14, 0x71, 0xa6, 0xb6, 0xbc, 0x10, 0x88, 0x9d, 0x07, 0x08, 0x44, 0xe5, 0x64, 0xd7, 0x32, - 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x2f, 0x29, 0xc9, 0x30, 0x53, 0xab, 0x31, 0xe8, 0xae, 0x56, 0x6c, 0xd4, 0x06, - 0x27, 0x92, 0x6d, 0xc3, 0xcf, 0x8e, 0xfc, 0x69, 0x70, 0x62, 0xe9, 0x04, 0x76, 0x58, 0x69, 0xb2, 0x20, 0x17, 0x52, - 0x9c, 0x1d, 0x91, 0x93, 0x25, 0x68, 0x5a, 0x51, 0x90, 0x22, 0x70, 0xc2, 0xca, 0x28, 0x13, 0x40, 0x2c, 0x64, 0x85, - 0x32, 0x20, 0x9d, 0xad, 0xc9, 0x7f, 0xda, 0xbc, 0xfc, 0xb8, 0x26, 0x5a, 0x93, 0x2b, 0x52, 0x7d, 0xa8, 0xa5, 0x1b, - 0x28, 0x08, 0x94, 0x7e, 0xb8, 0x27, 0x4c, 0xd0, 0x4a, 0x94, 0x23, 0x53, 0x0e, 0xe1, 0x36, 0xb8, 0xd0, 0xf6, 0xde, - 0xcb, 0x00, 0xef, 0x16, 0x69, 0x82, 0x53, 0x83, 0xae, 0x5f, 0x10, 0x5e, 0x63, 0x25, 0x11, 0x51, 0x96, 0x12, 0x0e, - 0x04, 0x99, 0x72, 0x92, 0x8d, 0xda, 0x17, 0xa0, 0x80, 0xf6, 0xfc, 0x7e, 0x56, 0x99, 0xc0, 0x7e, 0xa3, 0x81, 0x02, - 0x3d, 0x6a, 0x34, 0x62, 0x0d, 0xff, 0x02, 0x53, 0xec, 0x4b, 0xc3, 0xe4, 0xec, 0xe0, 0xc0, 0x09, 0xaa, 0x71, 0x47, - 0xfe, 0x05, 0xc2, 0xe9, 0x6a, 0xe5, 0x08, 0xb0, 0x02, 0xb4, 0x5a, 0x05, 0x26, 0x58, 0xe2, 0x35, 0x34, 0x9b, 0x0f, - 0x39, 0x99, 0x0b, 0x01, 0x38, 0x07, 0x08, 0x1b, 0xc4, 0x09, 0x94, 0x73, 0x2f, 0x00, 0x67, 0x54, 0x23, 0x1b, 0xf9, - 0x8d, 0xce, 0x85, 0xc1, 0xb8, 0x46, 0xfe, 0x05, 0x09, 0x8a, 0xf4, 0xe0, 0x60, 0x2f, 0x57, 0x22, 0xf2, 0x27, 0x10, - 0x65, 0x3f, 0x09, 0xc9, 0x22, 0x3b, 0x34, 0x57, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0x5a, 0x56, 0x5d, 0xaf, 0x96, - 0x04, 0x51, 0x56, 0xc2, 0x2a, 0x16, 0x3c, 0x04, 0xcb, 0xbe, 0x24, 0xf3, 0xaf, 0x78, 0x99, 0x64, 0xfd, 0xcb, 0xd6, - 0xd4, 0x6a, 0xd7, 0x75, 0xfd, 0x6c, 0x2a, 0x22, 0x19, 0x3a, 0x0a, 0x2b, 0x88, 0xff, 0x50, 0x81, 0x69, 0x0c, 0x3c, - 0x2a, 0xc7, 0xba, 0x20, 0x12, 0x7c, 0xad, 0xda, 0xe8, 0xd3, 0x24, 0x3f, 0x6f, 0xf5, 0x32, 0xa8, 0x0d, 0xf7, 0x6b, - 0x21, 0x39, 0x52, 0x90, 0x48, 0xf2, 0x58, 0xc3, 0xd9, 0x0e, 0x5c, 0xfc, 0xcc, 0xd7, 0x70, 0xb6, 0x1b, 0xb7, 0x1a, - 0x53, 0x5f, 0xee, 0x82, 0xcf, 0xe0, 0x0d, 0x12, 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x78, 0x5d, 0xf7, 0x92, 0xac, 0x14, - 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0xcd, 0x91, 0xe1, 0x12, 0xa8, 0x67, - 0xae, 0x00, 0x39, 0x29, 0x5f, 0xfb, 0xfc, 0xe0, 0x00, 0x6c, 0x03, 0x50, 0xe2, 0xdc, 0xc0, 0x9f, 0xf3, 0x45, 0x06, - 0xaa, 0x54, 0xae, 0x7f, 0x43, 0x31, 0x9c, 0x03, 0x11, 0x65, 0xf0, 0x03, 0x0a, 0xe6, 0x7e, 0x9e, 0xb3, 0x6b, 0x59, - 0xa6, 0x7e, 0xe3, 0x94, 0x68, 0x52, 0xce, 0xa5, 0x4e, 0x98, 0xa1, 0x5e, 0xa6, 0xe8, 0xb4, 0x8e, 0xb6, 0xe7, 0xd7, - 0x34, 0xe1, 0x2f, 0x59, 0xce, 0x69, 0x02, 0xd3, 0xaf, 0x28, 0x0e, 0x66, 0x94, 0x23, 0xd8, 0xb0, 0xb5, 0x56, 0x7e, - 0x18, 0xde, 0xdb, 0x84, 0xd7, 0x75, 0xa0, 0xc8, 0x4f, 0xc2, 0x58, 0x0e, 0x62, 0xa6, 0x33, 0xea, 0x14, 0xce, 0xb2, - 0xa6, 0x99, 0x4e, 0x53, 0x29, 0x1b, 0x82, 0xbb, 0x3b, 0x8c, 0x68, 0x49, 0xa0, 0xa5, 0xe7, 0xbd, 0x5a, 0x0b, 0x04, - 0xbc, 0x77, 0x2c, 0x82, 0x39, 0x13, 0xcc, 0x0d, 0x8e, 0xea, 0xd6, 0xe1, 0xd4, 0x74, 0xf3, 0xdd, 0xd6, 0x43, 0x6d, - 0xdb, 0x84, 0x83, 0xa0, 0x93, 0x47, 0xbb, 0x2d, 0xab, 0x57, 0x5a, 0x72, 0x68, 0x69, 0xc1, 0x1e, 0xca, 0x98, 0xd1, - 0x52, 0x93, 0x17, 0xd2, 0x5b, 0x71, 0xc6, 0xc9, 0x4f, 0x70, 0x6a, 0xe8, 0x05, 0x9f, 0xc5, 0x6b, 0x87, 0x63, 0x7a, - 0xb3, 0x52, 0xfb, 0x9f, 0x71, 0xe7, 0x35, 0x7e, 0x0a, 0x61, 0xdd, 0xaf, 0xab, 0xea, 0x9b, 0xe1, 0xdc, 0xaf, 0x2b, - 0x04, 0x7d, 0xed, 0x6d, 0xd4, 0x33, 0xc2, 0xb8, 0x5d, 0xf7, 0xc4, 0x6d, 0xdb, 0x5a, 0x5b, 0xfa, 0x5e, 0x06, 0x91, - 0x64, 0xa2, 0xa5, 0xd8, 0x0f, 0xb8, 0x4a, 0x53, 0x83, 0x74, 0xb9, 0xba, 0x85, 0x44, 0x55, 0x82, 0xa1, 0xd4, 0xe1, - 0x77, 0x2d, 0x8f, 0x92, 0x31, 0x99, 0xb4, 0x33, 0xde, 0xfa, 0x19, 0xdf, 0x87, 0x5d, 0x96, 0x6e, 0x9c, 0xc4, 0x8b, - 0x08, 0x78, 0xd0, 0x1e, 0x36, 0x84, 0x61, 0x6c, 0xe7, 0xf2, 0x24, 0x90, 0xd9, 0x3f, 0x49, 0xb5, 0xee, 0x56, 0xb7, - 0x32, 0xbe, 0x05, 0xfb, 0x1f, 0xe1, 0x48, 0x1f, 0x8f, 0xa3, 0x8a, 0x03, 0x53, 0x6f, 0x59, 0x94, 0x4e, 0x81, 0x54, - 0x2a, 0x6f, 0x09, 0xc2, 0x69, 0x21, 0xc2, 0xdb, 0xdf, 0xe0, 0x1f, 0x14, 0x4b, 0xbc, 0x2e, 0x39, 0xce, 0xf3, 0x87, - 0x72, 0x44, 0x09, 0x7e, 0x19, 0xbd, 0x07, 0x3a, 0x16, 0x14, 0x5a, 0x68, 0x2a, 0x7a, 0x96, 0xaa, 0x89, 0xec, 0xcc, - 0x4a, 0xc5, 0xb4, 0xcc, 0xa8, 0x11, 0xc3, 0x6c, 0x49, 0xe3, 0xd4, 0x56, 0x36, 0x2f, 0x77, 0x55, 0x6d, 0x5c, 0xb4, - 0x03, 0x8b, 0x55, 0x60, 0x71, 0xb5, 0x72, 0xea, 0xa8, 0x26, 0xcc, 0x88, 0x63, 0x20, 0xcc, 0x8c, 0x84, 0x8a, 0x9a, - 0x66, 0x2d, 0xdb, 0x38, 0x68, 0x3d, 0x9f, 0x48, 0xeb, 0xe6, 0x35, 0x38, 0x4c, 0x17, 0x82, 0x6c, 0x6e, 0xfa, 0x14, - 0xb0, 0x9c, 0x5d, 0x39, 0x90, 0x81, 0xa1, 0xef, 0xcb, 0x4c, 0xd9, 0x2a, 0xa5, 0x75, 0x0b, 0x7e, 0xd1, 0x3d, 0xb9, - 0xb2, 0x0a, 0x75, 0x9b, 0xef, 0x8d, 0x5c, 0xa3, 0x67, 0xe9, 0xae, 0x5c, 0xa3, 0x9a, 0xb6, 0xbb, 0xd7, 0x46, 0xf7, - 0x67, 0xa5, 0xca, 0xb1, 0xb6, 0x57, 0xf9, 0x15, 0xc3, 0x75, 0x80, 0x36, 0x25, 0x9a, 0x35, 0x57, 0x39, 0x2b, 0x8a, - 0xeb, 0xf2, 0x2c, 0x81, 0x48, 0xdd, 0xb9, 0x96, 0xf4, 0xaf, 0xac, 0x46, 0x71, 0x20, 0xd7, 0xf9, 0x86, 0x4c, 0xe3, - 0xf4, 0xca, 0x8f, 0xdf, 0xc3, 0x78, 0xd5, 0xcb, 0x17, 0x77, 0x61, 0xe6, 0x73, 0xaa, 0xb8, 0x4b, 0x05, 0xc3, 0x37, - 0x06, 0x0c, 0xdf, 0x48, 0x3e, 0x5d, 0xb5, 0xc7, 0xcb, 0x97, 0x65, 0x07, 0xde, 0x75, 0xa1, 0x59, 0xc6, 0x84, 0x6f, - 0x1f, 0x63, 0x9d, 0x85, 0x4d, 0x4a, 0x16, 0x36, 0xe1, 0xce, 0x7a, 0x57, 0x8e, 0xf3, 0xc3, 0xf6, 0x5e, 0x36, 0x39, - 0xdb, 0x0f, 0xd5, 0xc6, 0xff, 0xc1, 0xbb, 0xb7, 0x8d, 0xc1, 0xe5, 0x0e, 0xdd, 0x43, 0x91, 0xac, 0x22, 0x41, 0x7e, - 0x01, 0x49, 0x07, 0x9c, 0x0c, 0x8c, 0x23, 0x07, 0x95, 0x9c, 0xd2, 0x79, 0x40, 0x4e, 0xb0, 0xc8, 0x79, 0x3a, 0x53, - 0x7d, 0xe6, 0xea, 0x9c, 0x91, 0x78, 0x09, 0xae, 0x68, 0x11, 0x6b, 0xf7, 0xea, 0x27, 0xb9, 0x96, 0x1f, 0x58, 0x12, - 0x7a, 0x39, 0x56, 0x52, 0x24, 0xf7, 0xb2, 0x82, 0xe8, 0x5c, 0xe3, 0xcd, 0x77, 0x78, 0xc2, 0x12, 0x96, 0x47, 0x34, - 0x73, 0x52, 0xb4, 0xdc, 0x35, 0x58, 0x0a, 0x01, 0x19, 0x39, 0x18, 0xfe, 0x5b, 0x75, 0xe4, 0xcf, 0x85, 0xde, 0xc0, - 0x0f, 0x34, 0xa3, 0x3c, 0x4a, 0x43, 0x48, 0x4b, 0x71, 0xc3, 0xf2, 0x48, 0xd3, 0xc1, 0xc1, 0x9e, 0x63, 0x0b, 0xb7, - 0x04, 0x1c, 0xfe, 0x36, 0xdf, 0xa0, 0xe1, 0x12, 0x4e, 0xe7, 0x54, 0x43, 0x53, 0xb4, 0xa4, 0xeb, 0x07, 0x59, 0xb8, - 0xfb, 0x81, 0xde, 0xe1, 0x04, 0x15, 0x85, 0x27, 0xa1, 0xb6, 0x27, 0x8c, 0xc6, 0xa1, 0x8d, 0x3f, 0xd0, 0x3b, 0xaf, - 0x3c, 0x2f, 0x2e, 0x8e, 0x37, 0x8b, 0x05, 0xb4, 0xd3, 0x9b, 0xc4, 0xc6, 0xd5, 0x20, 0xde, 0xb2, 0xc0, 0x69, 0xc6, - 0xa6, 0x40, 0x9c, 0x7f, 0xa1, 0x77, 0x9e, 0xec, 0x8f, 0x19, 0xa7, 0xf5, 0xd0, 0x52, 0xa3, 0xde, 0x35, 0x8a, 0xcd, - 0x65, 0x50, 0x06, 0xc5, 0x48, 0xb4, 0xbd, 0x20, 0xb5, 0x7a, 0x95, 0x79, 0x88, 0x50, 0xf1, 0xd0, 0xa9, 0xe0, 0xaf, - 0x4d, 0xd1, 0xc6, 0x6b, 0x99, 0xaf, 0x6b, 0x8d, 0x28, 0x34, 0xa8, 0x32, 0x3d, 0x66, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, - 0x82, 0x60, 0x38, 0xc2, 0xbe, 0xe6, 0xaa, 0x53, 0xef, 0x6f, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xaa, 0xda, 0x59, - 0x33, 0x07, 0xf0, 0x0e, 0x09, 0x2d, 0xbe, 0x38, 0x90, 0x59, 0xe8, 0x6c, 0xd1, 0xbf, 0x70, 0xe2, 0x2c, 0xf5, 0x14, - 0xbc, 0xc4, 0xc4, 0x22, 0x2f, 0x80, 0x0a, 0x15, 0x7d, 0xc9, 0x04, 0x40, 0x38, 0xc3, 0xbe, 0x21, 0x35, 0x33, 0x21, - 0x35, 0x5d, 0x03, 0xe3, 0x3b, 0xa4, 0x24, 0x15, 0xc8, 0x10, 0x4a, 0xa4, 0x10, 0x7a, 0x6a, 0x71, 0x15, 0x09, 0x99, - 0x0b, 0x5a, 0x9e, 0x9f, 0x93, 0x6b, 0x9e, 0xd5, 0xc0, 0x72, 0x44, 0x3f, 0xa8, 0xf0, 0x60, 0x4a, 0x54, 0x56, 0x28, - 0xca, 0x63, 0xd9, 0x3a, 0xbd, 0xd5, 0x49, 0x5d, 0x3d, 0x2d, 0xa2, 0x51, 0xe2, 0x44, 0x68, 0x99, 0x38, 0x11, 0xce, - 0x20, 0x1d, 0x31, 0x2d, 0x4a, 0xf8, 0xa9, 0xb9, 0x1a, 0xb5, 0x64, 0xe5, 0xed, 0x67, 0xfc, 0x40, 0x99, 0xe7, 0x90, - 0xa2, 0x89, 0x13, 0xcd, 0x53, 0x12, 0x47, 0x1c, 0xb6, 0x33, 0x96, 0xed, 0x1b, 0x95, 0xa0, 0xa3, 0x00, 0xfb, 0x0b, - 0x77, 0x96, 0xc6, 0x2c, 0xcc, 0xd3, 0xdc, 0xea, 0xcc, 0x9f, 0x0a, 0xf6, 0x55, 0x39, 0xa4, 0x4e, 0x4e, 0xd6, 0x24, - 0xce, 0xfd, 0xa9, 0x96, 0x3f, 0x2f, 0x68, 0x76, 0x77, 0x4e, 0x21, 0xd5, 0x39, 0x85, 0xd3, 0xbe, 0xd5, 0x32, 0x54, - 0x69, 0xea, 0xc3, 0x4c, 0x28, 0x2b, 0x45, 0xfd, 0x14, 0xe0, 0xfa, 0x19, 0xc1, 0x42, 0x44, 0x1b, 0x0d, 0x47, 0x8c, - 0xdc, 0x2d, 0x74, 0xe7, 0xe9, 0x49, 0xda, 0x63, 0xe0, 0x5f, 0xab, 0x30, 0xad, 0x82, 0x05, 0x38, 0x35, 0x4f, 0xa4, - 0x8e, 0xf2, 0x8b, 0x75, 0xaf, 0x0c, 0x14, 0x41, 0xf8, 0x2e, 0xdb, 0x3d, 0xd5, 0x6d, 0x49, 0xb3, 0xbb, 0xa7, 0x5a, - 0x0b, 0xfa, 0x89, 0x84, 0x1f, 0xac, 0xc6, 0x29, 0x8f, 0x2f, 0xb3, 0xa2, 0x40, 0x05, 0x80, 0xf7, 0xe7, 0x9e, 0xe3, - 0xfc, 0x59, 0xa5, 0x0c, 0xba, 0x10, 0x8b, 0x3d, 0x8f, 0x53, 0xcd, 0xc4, 0xab, 0xf1, 0xff, 0xbc, 0x31, 0xfe, 0x9f, - 0x8d, 0x33, 0xa7, 0x60, 0x1a, 0x4d, 0x13, 0x1a, 0x6a, 0xd6, 0x89, 0x24, 0x01, 0x0a, 0xbd, 0x2d, 0xe1, 0xe4, 0xc3, - 0xd8, 0x03, 0x8d, 0x6b, 0x39, 0x49, 0x13, 0xde, 0x9c, 0xf8, 0x33, 0x16, 0xdf, 0x79, 0x0b, 0xd6, 0x9c, 0xa5, 0x49, - 0x9a, 0xcf, 0xfd, 0x80, 0xe2, 0xfc, 0x2e, 0xe7, 0x74, 0xd6, 0x5c, 0x30, 0xfc, 0x82, 0xc6, 0xd7, 0x94, 0xb3, 0xc0, - 0xc7, 0xf6, 0x69, 0xc6, 0xfc, 0xd8, 0x7a, 0xed, 0x67, 0x59, 0x7a, 0x63, 0xe3, 0x77, 0xe9, 0x55, 0xca, 0x53, 0xfc, - 0xe6, 0xf6, 0x6e, 0x4a, 0x13, 0xfc, 0xed, 0xd5, 0x22, 0xe1, 0x0b, 0x9c, 0xfb, 0x49, 0xde, 0xcc, 0x69, 0xc6, 0x26, - 0xbd, 0x20, 0x8d, 0xd3, 0xac, 0x09, 0x19, 0xdb, 0x33, 0xea, 0xc5, 0x6c, 0x1a, 0x71, 0x2b, 0xf4, 0xb3, 0x0f, 0xbd, - 0x66, 0x73, 0x9e, 0xb1, 0x99, 0x9f, 0xdd, 0x35, 0x45, 0x0d, 0xef, 0xf3, 0xf6, 0xa1, 0xff, 0x64, 0x72, 0xd4, 0xe3, - 0x99, 0x9f, 0xe4, 0x0c, 0x96, 0xc9, 0xf3, 0xe3, 0xd8, 0x3a, 0x3c, 0x6e, 0xcf, 0xf2, 0x3d, 0x19, 0xc8, 0xf3, 0x13, - 0x5e, 0x8c, 0xf1, 0x5b, 0x80, 0xdb, 0xbd, 0xe2, 0x09, 0xbe, 0x5a, 0x70, 0x9e, 0x26, 0xcb, 0x60, 0x91, 0xe5, 0x69, - 0xe6, 0xcd, 0x53, 0x96, 0x70, 0x9a, 0xf5, 0xae, 0xd2, 0x2c, 0xa4, 0x59, 0x33, 0xf3, 0x43, 0xb6, 0xc8, 0xbd, 0xa3, - 0xf9, 0x6d, 0x0f, 0x34, 0x8b, 0x69, 0x96, 0x2e, 0x92, 0x50, 0x8d, 0xc5, 0x92, 0x88, 0x66, 0x8c, 0x9b, 0x2f, 0xc4, - 0x25, 0x26, 0x5e, 0xcc, 0x12, 0xea, 0x67, 0xcd, 0x29, 0x34, 0x06, 0xb3, 0xa8, 0x1d, 0xd2, 0x29, 0xce, 0xa6, 0x57, - 0xbe, 0xd3, 0xe9, 0x3e, 0xc6, 0xfa, 0x7f, 0xf7, 0x18, 0x59, 0xed, 0xed, 0xc5, 0x9d, 0x76, 0xfb, 0x0f, 0xa8, 0xb7, - 0x36, 0x8a, 0x00, 0xc8, 0xeb, 0xcc, 0x6f, 0xad, 0x3c, 0x85, 0x8c, 0xb6, 0x6d, 0x2d, 0x7b, 0x73, 0x3f, 0x84, 0x7c, - 0x60, 0xaf, 0x3b, 0xbf, 0x2d, 0x60, 0x76, 0x9e, 0x4c, 0x31, 0x55, 0x93, 0x54, 0x4f, 0xcb, 0x5f, 0x0b, 0xf1, 0xc9, - 0x76, 0x88, 0xbb, 0x1a, 0xe2, 0x0a, 0xeb, 0xcd, 0x70, 0x91, 0x89, 0xd8, 0xaa, 0xd7, 0xc9, 0x25, 0x20, 0x51, 0x7a, - 0x4d, 0x33, 0x0d, 0x87, 0x78, 0xf8, 0xd5, 0x60, 0x74, 0xb7, 0x83, 0x71, 0xf2, 0x31, 0x30, 0xb2, 0x24, 0x5c, 0xd6, - 0xd7, 0xb5, 0x93, 0xd1, 0x59, 0x2f, 0xa2, 0x40, 0x4f, 0x5e, 0x17, 0x7e, 0xdf, 0xb0, 0x90, 0x47, 0xf2, 0xa7, 0x20, - 0xe7, 0x1b, 0xf9, 0xee, 0xb8, 0xdd, 0x96, 0xcf, 0x39, 0xfb, 0x85, 0x7a, 0x1d, 0x17, 0x2a, 0x14, 0x63, 0xfc, 0x43, - 0x79, 0x96, 0xb7, 0xce, 0x3d, 0xf1, 0x9f, 0xcd, 0x43, 0xbe, 0x46, 0x8a, 0x62, 0x75, 0x24, 0x1a, 0x67, 0x5a, 0x56, - 0x4a, 0xe1, 0x03, 0x6e, 0x3b, 0xc1, 0x1d, 0x09, 0x1b, 0x94, 0x87, 0x38, 0xd9, 0xf0, 0xcf, 0x32, 0xef, 0xc2, 0x83, - 0x48, 0x87, 0x91, 0x6a, 0x98, 0xf6, 0xb2, 0x01, 0x69, 0xf7, 0xb2, 0x66, 0x13, 0x39, 0x29, 0x49, 0x46, 0x99, 0x4a, - 0xce, 0x73, 0xd8, 0x30, 0x15, 0xc6, 0x76, 0x8e, 0xbc, 0x14, 0x4e, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0x89, 0xd3, - 0x1a, 0x3f, 0x70, 0x55, 0x01, 0xe7, 0x06, 0x27, 0x4f, 0xf5, 0xd5, 0x2e, 0x89, 0xe6, 0x15, 0x71, 0x1a, 0x08, 0xcc, - 0xb9, 0x73, 0x9f, 0x47, 0xe0, 0xa5, 0x28, 0xc5, 0x4f, 0x95, 0xc2, 0x64, 0xb7, 0x6c, 0x34, 0x4c, 0xca, 0xfc, 0x36, - 0xc8, 0xe3, 0x4b, 0x0a, 0xe8, 0xe5, 0x8e, 0x13, 0x61, 0x31, 0x95, 0xfd, 0x7f, 0xcb, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, - 0x09, 0xe2, 0x45, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xff, 0x6a, 0xd6, 0x12, 0x4d, 0xa0, 0x77, 0x91, 0xcd, 0x03, - 0x15, 0xe1, 0x06, 0x95, 0xf2, 0xb9, 0x29, 0x9e, 0xab, 0xb6, 0xfa, 0x52, 0x09, 0x36, 0x71, 0xa0, 0xa5, 0xbb, 0x48, - 0xd8, 0xcf, 0x0b, 0x7a, 0xc9, 0x42, 0xe3, 0xdc, 0x2e, 0x4d, 0x82, 0x34, 0xa4, 0xdf, 0xbe, 0xfb, 0x0a, 0xb2, 0xdd, - 0xd3, 0x04, 0x48, 0x2c, 0x91, 0xfe, 0x2e, 0x9c, 0x93, 0xc4, 0x0d, 0xe9, 0x35, 0x0b, 0xe8, 0x70, 0xbc, 0xbf, 0xdc, - 0x5a, 0x51, 0xbe, 0x46, 0x45, 0x6b, 0x2c, 0x92, 0xfe, 0x04, 0x94, 0xe3, 0xfd, 0xe5, 0x1d, 0x2f, 0x5a, 0xfb, 0xcb, - 0xc4, 0x0d, 0xd3, 0x99, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xfb, 0x4b, 0x06, 0x3f, 0x78, 0x31, 0x2e, 0xaa, 0x44, 0xd1, - 0x12, 0x22, 0x63, 0x0a, 0x0a, 0x77, 0x1d, 0xe4, 0xfe, 0x94, 0xb2, 0x44, 0x14, 0xdd, 0xd7, 0x33, 0xd5, 0xbd, 0x02, - 0x92, 0xbf, 0x22, 0xd2, 0x60, 0xd6, 0xe6, 0xf2, 0xf5, 0x43, 0xcd, 0x65, 0x9a, 0x70, 0x26, 0xd2, 0xe2, 0x75, 0x38, - 0x27, 0xf2, 0xf3, 0xcb, 0x40, 0x9e, 0x43, 0xcd, 0xab, 0x53, 0x17, 0xbe, 0x40, 0xac, 0xb4, 0x80, 0x69, 0x26, 0x8c, - 0x7d, 0xba, 0xfb, 0xa0, 0x64, 0x72, 0x9f, 0xf1, 0x57, 0x52, 0x55, 0x9e, 0x2e, 0xb2, 0x00, 0x62, 0xbd, 0x4a, 0xa5, - 0xd8, 0xf4, 0x8a, 0xd9, 0x42, 0x7f, 0xb3, 0x31, 0x37, 0x92, 0x6c, 0x39, 0x66, 0xe6, 0x9d, 0x1d, 0x54, 0xc4, 0x13, - 0xe5, 0x59, 0x18, 0xa5, 0x3f, 0xe8, 0x29, 0x81, 0x42, 0x14, 0x8a, 0x7c, 0x51, 0x27, 0x23, 0x83, 0xac, 0xc2, 0x39, - 0x21, 0x84, 0xb9, 0x2c, 0x14, 0x81, 0x3c, 0x50, 0x2c, 0x9a, 0x1d, 0x88, 0x0c, 0xb1, 0xb0, 0xd2, 0xf0, 0x98, 0xc2, - 0xf3, 0x6a, 0xf5, 0x57, 0xee, 0xc8, 0xba, 0xd2, 0xa9, 0x02, 0x3a, 0x18, 0xc3, 0xf2, 0xa5, 0x97, 0xe1, 0xb2, 0x4b, - 0x0f, 0x2a, 0x15, 0xbd, 0x54, 0xa0, 0x4f, 0x22, 0x8b, 0x68, 0x74, 0x9e, 0x4a, 0x15, 0x21, 0x45, 0xd8, 0x7c, 0x5d, - 0x1e, 0xe0, 0xaf, 0xe1, 0xbb, 0xbd, 0xb6, 0x2c, 0xd2, 0x9e, 0x4a, 0xd7, 0x4b, 0xf3, 0x34, 0xe3, 0x8e, 0x13, 0x61, - 0x1f, 0x91, 0x41, 0x24, 0xa8, 0xb6, 0xef, 0x8b, 0x7f, 0x86, 0xcd, 0x8e, 0xd7, 0x29, 0x3d, 0x21, 0xb5, 0x73, 0xd5, - 0x32, 0xcf, 0x4c, 0x9d, 0xcd, 0x05, 0x70, 0x71, 0xf9, 0x5b, 0xce, 0xa7, 0x7a, 0x2e, 0xa7, 0x85, 0x15, 0xe7, 0x92, - 0x52, 0xdf, 0xa9, 0x01, 0x21, 0xe2, 0x6e, 0x3b, 0x86, 0x42, 0x45, 0x35, 0xef, 0x72, 0x17, 0x8f, 0xa5, 0xb6, 0x73, - 0x69, 0x90, 0xf1, 0x98, 0x69, 0x7f, 0x5d, 0x9d, 0xc0, 0x0a, 0x85, 0x11, 0x83, 0x05, 0x6c, 0xab, 0x26, 0x61, 0xb9, - 0x23, 0xc9, 0x56, 0x2a, 0x75, 0xe5, 0x23, 0x95, 0xba, 0xd6, 0xf6, 0x2a, 0x22, 0xeb, 0x71, 0x1b, 0x60, 0xe0, 0x01, - 0xc8, 0xb9, 0x9e, 0x02, 0x30, 0x93, 0x09, 0x15, 0x17, 0xd3, 0x48, 0xd6, 0x82, 0x97, 0x52, 0x8d, 0xf7, 0xec, 0xb7, - 0x6f, 0xce, 0xdf, 0xdb, 0x18, 0xee, 0x33, 0xa3, 0x59, 0xee, 0x2d, 0x6d, 0x95, 0x4c, 0xd8, 0x84, 0xc0, 0xb4, 0xed, - 0xd9, 0xfe, 0x1c, 0xce, 0x66, 0x0b, 0xee, 0xd9, 0xba, 0x6d, 0xde, 0xdc, 0xdc, 0x34, 0xe1, 0xe8, 0x58, 0x73, 0x91, - 0xc5, 0x92, 0xaf, 0x84, 0x76, 0x51, 0x20, 0x97, 0x47, 0x34, 0x29, 0x6f, 0x3c, 0x4a, 0x63, 0xea, 0xc6, 0xe9, 0x54, - 0x1e, 0x7b, 0x5d, 0xf7, 0x43, 0xc4, 0xe3, 0xbe, 0xb8, 0xc9, 0x6b, 0xd0, 0xe7, 0xf2, 0x0e, 0x35, 0x9e, 0xc1, 0xcf, - 0x01, 0x44, 0xa9, 0xfa, 0x2d, 0x1e, 0x89, 0x87, 0x73, 0xd8, 0x36, 0xe2, 0x69, 0x7f, 0xb9, 0x41, 0x64, 0x43, 0xe8, - 0x22, 0x1a, 0xc8, 0xa9, 0xe5, 0xa2, 0xd6, 0xd8, 0x8b, 0xc7, 0xe3, 0xa2, 0xdf, 0x82, 0xbe, 0x5a, 0xba, 0xdf, 0xab, - 0x34, 0xbc, 0xd3, 0xed, 0x4b, 0xc2, 0x83, 0x1b, 0x9d, 0x12, 0x32, 0x80, 0x2e, 0x60, 0xdc, 0x70, 0x20, 0x70, 0xa6, - 0x78, 0xe5, 0xa8, 0x7a, 0x28, 0x2e, 0x2c, 0xe0, 0x8c, 0x05, 0x94, 0x00, 0x5d, 0x42, 0xe7, 0x61, 0xd9, 0x40, 0x6c, - 0x6b, 0x59, 0xb4, 0x0b, 0x40, 0x59, 0xb1, 0xda, 0x2e, 0xd2, 0x9f, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, 0x1f, - 0x23, 0xf8, 0x57, 0x00, 0xde, 0x6f, 0x49, 0x34, 0x8d, 0xcd, 0xdb, 0x65, 0xe4, 0xbd, 0x0f, 0x25, 0x32, 0x47, 0x09, - 0xc7, 0x6f, 0x39, 0xfe, 0x30, 0x16, 0x55, 0xb5, 0x3a, 0x00, 0x7a, 0x2a, 0xa8, 0x4d, 0x6d, 0xad, 0xf7, 0x05, 0x69, - 0x1c, 0xfb, 0xf3, 0x9c, 0x7a, 0xfa, 0x87, 0xd2, 0x0c, 0x40, 0xc1, 0xd8, 0x54, 0xc5, 0x54, 0x82, 0xd3, 0x19, 0x28, - 0x6c, 0x9b, 0x7a, 0xe2, 0xb5, 0x9f, 0x39, 0xcd, 0x66, 0xd0, 0xbc, 0x9a, 0xa2, 0x82, 0x47, 0x4b, 0x53, 0xaf, 0x78, - 0xd4, 0x6e, 0xf7, 0x20, 0x1b, 0xb5, 0xe9, 0xc7, 0x6c, 0x9a, 0x78, 0x31, 0x9d, 0xf0, 0x82, 0xc3, 0x31, 0xc1, 0xa5, - 0x56, 0xe4, 0xdc, 0xee, 0x71, 0x46, 0x67, 0x96, 0x0b, 0x7f, 0xef, 0x1f, 0xb8, 0xe0, 0xa1, 0x97, 0xf0, 0xa8, 0x29, - 0xb2, 0x9e, 0xe1, 0xcc, 0x06, 0x8f, 0x6a, 0xcf, 0x4b, 0x63, 0xa0, 0x80, 0x82, 0x92, 0x5b, 0xf0, 0xcc, 0xe2, 0x11, - 0xe6, 0x99, 0x59, 0x2f, 0x41, 0xcb, 0x8d, 0x19, 0x6c, 0xea, 0x5a, 0x87, 0xa8, 0xc8, 0x85, 0x69, 0xb2, 0x59, 0x59, - 0x2b, 0xac, 0xf5, 0xa7, 0x0d, 0xf4, 0x19, 0xaa, 0x75, 0x21, 0x5d, 0xfb, 0x4b, 0xd9, 0xe2, 0x21, 0xc8, 0xac, 0x29, - 0xfd, 0xd8, 0x6c, 0x81, 0x0a, 0x96, 0xcc, 0x17, 0x7c, 0x24, 0xc2, 0x0a, 0x19, 0x1c, 0x50, 0xb9, 0xc0, 0x46, 0x09, - 0xe0, 0xe0, 0x62, 0x29, 0x81, 0x09, 0xfc, 0x38, 0x70, 0x00, 0x22, 0xab, 0x69, 0x9d, 0x64, 0x74, 0x86, 0x7a, 0x33, - 0x96, 0x34, 0xe5, 0xbb, 0x63, 0x43, 0x31, 0x74, 0x1f, 0xc3, 0x53, 0xe1, 0x8a, 0xde, 0xb0, 0xc8, 0x1e, 0xde, 0x82, - 0xcb, 0xf1, 0x45, 0x51, 0xf4, 0x32, 0xee, 0x8c, 0x5e, 0x39, 0xe8, 0x02, 0x7f, 0x65, 0xdc, 0x8f, 0x63, 0xeb, 0x9d, - 0x64, 0xe3, 0x2e, 0xda, 0x51, 0xc5, 0xdc, 0x0b, 0xa2, 0xda, 0x57, 0x04, 0x2a, 0xbe, 0x70, 0x6c, 0x9a, 0xcf, 0x9b, - 0x92, 0xe5, 0x35, 0x05, 0xc9, 0xda, 0xd0, 0x14, 0x29, 0x5f, 0x39, 0xa5, 0x4b, 0xc1, 0xcd, 0xd4, 0x21, 0x19, 0xe9, - 0xce, 0xb9, 0x28, 0x0f, 0x55, 0xa9, 0x67, 0xf3, 0x18, 0x15, 0xaa, 0xb1, 0x9b, 0xf1, 0x69, 0x9d, 0x35, 0x82, 0x72, - 0x51, 0x5e, 0x22, 0xe8, 0xc7, 0x31, 0x0c, 0x38, 0xd6, 0x1a, 0x89, 0x79, 0xeb, 0xca, 0x88, 0x5f, 0x38, 0xa8, 0x50, - 0xfb, 0xf4, 0xa9, 0x50, 0xea, 0x8d, 0x9b, 0x0b, 0xf7, 0xb8, 0x0e, 0xd7, 0x49, 0x11, 0xcd, 0x20, 0xe1, 0xa0, 0x96, - 0x98, 0xde, 0xab, 0x58, 0x9b, 0x34, 0x09, 0x2c, 0x31, 0x21, 0x62, 0x67, 0x49, 0x68, 0x5b, 0x7f, 0x0a, 0x62, 0x16, - 0x7c, 0x20, 0xf6, 0xfe, 0xd2, 0x41, 0x9b, 0xe7, 0x4e, 0x05, 0x57, 0xd0, 0x7c, 0x1e, 0xd5, 0x43, 0x19, 0x99, 0x6b, - 0xb0, 0x70, 0x79, 0x31, 0x91, 0x3d, 0x00, 0xbd, 0xa9, 0xdf, 0x92, 0xe3, 0x0c, 0xc6, 0xc5, 0x65, 0x75, 0xdf, 0x58, - 0x05, 0x05, 0xa0, 0x59, 0x96, 0x5b, 0x82, 0xa8, 0x88, 0xfd, 0x51, 0x4a, 0xb3, 0x2d, 0xc9, 0xd4, 0x00, 0x4e, 0xae, - 0xf8, 0x9b, 0x6d, 0xfd, 0xa9, 0x2c, 0xa3, 0xa5, 0x4f, 0x49, 0x24, 0xc5, 0x10, 0x1b, 0xc6, 0x02, 0x47, 0x82, 0x1b, - 0x52, 0xee, 0xb3, 0x58, 0x36, 0xe9, 0x69, 0x17, 0xc8, 0xda, 0x8c, 0x56, 0xab, 0xbc, 0x3e, 0x17, 0x56, 0xc7, 0xa0, - 0x98, 0x59, 0xbf, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0xa4, 0x19, 0x9c, 0xad, 0x66, 0x28, 0xdf, 0x59, 0x7f, 0x0a, - 0xc4, 0xb1, 0x2d, 0x00, 0x30, 0x55, 0x00, 0x42, 0xda, 0x80, 0x3c, 0x96, 0xe4, 0xf8, 0x24, 0x75, 0xb9, 0x9f, 0x4d, - 0x29, 0x5f, 0x43, 0xac, 0x2f, 0xb3, 0x84, 0x7b, 0x3a, 0x45, 0x60, 0x03, 0xda, 0xa0, 0x0e, 0x2d, 0x28, 0xd1, 0xc5, - 0x10, 0xf4, 0x60, 0xb2, 0x55, 0x9d, 0x8e, 0x10, 0xc8, 0x5b, 0xb1, 0x38, 0x52, 0xc2, 0xa4, 0x42, 0xc2, 0x48, 0x4e, - 0x60, 0x89, 0xb1, 0x04, 0x88, 0x85, 0x6d, 0x0d, 0x25, 0xe4, 0x34, 0x94, 0x30, 0x93, 0x4c, 0xb4, 0x4a, 0x8b, 0x7e, - 0x4b, 0xd6, 0x96, 0x22, 0x40, 0x56, 0x02, 0x24, 0x88, 0x7d, 0x5a, 0xe1, 0x00, 0x32, 0xcb, 0x4d, 0x3c, 0x84, 0xec, - 0xba, 0x24, 0x36, 0x71, 0x80, 0x6d, 0xd0, 0x8f, 0xfd, 0x2b, 0x1a, 0x0f, 0xf6, 0x97, 0xd9, 0x6a, 0xd5, 0x2e, 0xfa, - 0x2d, 0xf9, 0x68, 0xf5, 0x05, 0xdf, 0x90, 0x97, 0x8e, 0x8a, 0x25, 0x86, 0x53, 0xa1, 0x90, 0x6f, 0xab, 0x13, 0xcd, - 0x3c, 0xd5, 0x41, 0x61, 0x5b, 0x22, 0xc5, 0x45, 0x54, 0x2a, 0xf5, 0xa8, 0xc2, 0xb6, 0x58, 0xb8, 0x59, 0x96, 0x73, - 0x3a, 0x87, 0xd2, 0x68, 0xb5, 0xea, 0x14, 0xb6, 0x35, 0x63, 0x09, 0x3c, 0x65, 0xab, 0x95, 0x38, 0x70, 0x39, 0x63, - 0x89, 0xd3, 0x06, 0xb2, 0xb5, 0xad, 0x99, 0x7f, 0x2b, 0x26, 0xac, 0xdf, 0xf8, 0xb7, 0x4e, 0x47, 0xbd, 0x72, 0x4b, - 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8a, 0xfa, 0x6a, 0x45, 0x43, 0xbc, 0x90, 0x47, 0xc9, 0x88, 0x13, 0x12, 0x7f, 0xfb, - 0x8a, 0x86, 0x7a, 0x45, 0x17, 0x3b, 0x56, 0x74, 0x71, 0xcf, 0x8a, 0x06, 0x6a, 0xf5, 0xac, 0x12, 0x77, 0xe9, 0x6a, - 0xd5, 0x69, 0x57, 0xd8, 0xeb, 0xb7, 0x42, 0x76, 0x0d, 0xab, 0x01, 0xda, 0x21, 0x67, 0x33, 0xba, 0x9d, 0x28, 0xeb, - 0x28, 0xa6, 0x9f, 0x84, 0xc9, 0x0a, 0x0b, 0x59, 0x1d, 0x0b, 0x26, 0x5d, 0x97, 0x51, 0xcf, 0xdf, 0x93, 0xb2, 0x19, - 0xe0, 0x21, 0x07, 0x3c, 0x44, 0xfa, 0x12, 0x52, 0xc7, 0x7e, 0x6f, 0x63, 0xdb, 0xb2, 0x35, 0x59, 0x8f, 0x8b, 0x4b, - 0x90, 0x11, 0x62, 0x7e, 0x0f, 0xa2, 0x45, 0xa8, 0x6d, 0x0f, 0x76, 0xd3, 0x1c, 0x24, 0x28, 0xdc, 0xa4, 0x59, 0x68, - 0x7b, 0xb2, 0xea, 0x27, 0xa1, 0x6a, 0xc6, 0x12, 0x95, 0xee, 0xb6, 0x93, 0xd6, 0xaa, 0xf7, 0x26, 0xc5, 0x75, 0x8f, - 0x8f, 0x65, 0x8d, 0xb9, 0xcf, 0x39, 0xcd, 0x12, 0x45, 0xb9, 0xb6, 0xfd, 0x1f, 0x82, 0x0a, 0xb7, 0xf0, 0x95, 0x40, - 0x2f, 0x80, 0x26, 0x40, 0xa5, 0xe7, 0x2b, 0x9e, 0x2f, 0xc5, 0xd3, 0x5e, 0xa5, 0xe0, 0xde, 0x21, 0xd3, 0xd6, 0x90, - 0x45, 0x60, 0xfa, 0x2c, 0x66, 0x34, 0xbc, 0x14, 0x0c, 0x7a, 0x18, 0x8f, 0x95, 0xc2, 0xba, 0x26, 0xee, 0xaa, 0x06, - 0xd8, 0xfe, 0x71, 0xd1, 0x7d, 0x7c, 0x74, 0x66, 0x63, 0xc9, 0xe3, 0xd3, 0xc9, 0xc4, 0x46, 0x85, 0xf5, 0xb0, 0x66, - 0x9d, 0xa3, 0x1f, 0x17, 0x5f, 0x3e, 0x6f, 0x7f, 0x59, 0x36, 0x4e, 0x80, 0x88, 0x54, 0x86, 0x85, 0x16, 0x55, 0x06, - 0xbc, 0x7a, 0x46, 0x13, 0x3f, 0xd9, 0x3d, 0x9d, 0x91, 0x39, 0x9d, 0x7c, 0x4e, 0x69, 0x08, 0xc4, 0x89, 0x37, 0x4a, - 0x2f, 0x63, 0x7a, 0x4d, 0xf5, 0xe5, 0x8f, 0x5b, 0x06, 0xdb, 0xd2, 0x22, 0x48, 0x17, 0x09, 0x57, 0xa9, 0x26, 0x8a, - 0xd5, 0x1a, 0x53, 0x1a, 0x8b, 0x39, 0x98, 0x26, 0xc4, 0x9d, 0x94, 0x73, 0x75, 0xe9, 0x55, 0x8c, 0xb1, 0x6d, 0x00, - 0xb0, 0x13, 0xb2, 0xe1, 0x8e, 0x72, 0xaf, 0x8d, 0xdb, 0xbb, 0x60, 0xc3, 0x1d, 0xe4, 0xd9, 0xf6, 0x85, 0xc6, 0x93, - 0xf0, 0x16, 0xd7, 0x6e, 0xec, 0xd8, 0x89, 0xaf, 0x8f, 0x62, 0xe0, 0x2a, 0x83, 0xce, 0x12, 0x9a, 0xe7, 0x3b, 0x11, - 0x50, 0x2e, 0x22, 0xb6, 0xab, 0xda, 0xf6, 0x8e, 0x5e, 0x70, 0x1b, 0xc3, 0x0e, 0x13, 0x00, 0x97, 0x31, 0x6b, 0x55, - 0x8b, 0x4e, 0x26, 0x34, 0x28, 0x9d, 0xed, 0x10, 0x7d, 0x9c, 0xb0, 0x98, 0x43, 0x10, 0x4e, 0x44, 0xc7, 0xec, 0xd7, - 0x69, 0x42, 0x6d, 0xa4, 0xf3, 0x69, 0x15, 0xfc, 0x4a, 0xfe, 0x6f, 0x87, 0x47, 0xf6, 0x58, 0x87, 0x45, 0x8d, 0xb2, - 0x5a, 0x69, 0x5f, 0x50, 0xad, 0xbc, 0x8e, 0xc8, 0x54, 0x38, 0x7b, 0x76, 0x6d, 0xa0, 0x87, 0x6d, 0x93, 0x65, 0xe7, - 0xcb, 0xe3, 0x4e, 0xbb, 0xb0, 0xb1, 0x0d, 0xdd, 0x3d, 0x74, 0x97, 0x88, 0x56, 0x87, 0xd0, 0x6a, 0x91, 0x7c, 0x4a, - 0xbb, 0x6e, 0xe7, 0x49, 0xc7, 0xc6, 0xf2, 0x22, 0x07, 0x54, 0x94, 0xcc, 0x20, 0x00, 0xf7, 0xf3, 0x6f, 0x9e, 0x4a, - 0xbd, 0xf3, 0x87, 0xc1, 0xf3, 0xa8, 0xd3, 0xb6, 0xb1, 0x9d, 0xf3, 0x74, 0xfe, 0x09, 0x53, 0x38, 0xb4, 0xb1, 0x1d, - 0xc4, 0x69, 0x4e, 0xcd, 0x39, 0x48, 0x75, 0xf6, 0xb7, 0x4f, 0x42, 0x42, 0x34, 0xcf, 0x68, 0x9e, 0x5b, 0x66, 0xff, - 0x8a, 0x94, 0x3e, 0xc2, 0x30, 0xb7, 0x52, 0x5c, 0x4e, 0xb9, 0xc0, 0x8b, 0xbc, 0x63, 0xc1, 0xa4, 0x2a, 0x59, 0xb6, - 0x41, 0x6c, 0x42, 0x04, 0x94, 0x8c, 0x4d, 0x6a, 0x57, 0x1f, 0x1d, 0x79, 0xcb, 0xd6, 0x93, 0x03, 0xcb, 0xa8, 0xfc, - 0xe6, 0x00, 0xb5, 0x92, 0x19, 0x4b, 0x2e, 0xb7, 0x94, 0xfa, 0xb7, 0x5b, 0x4a, 0x41, 0x65, 0x2b, 0xa1, 0x53, 0xf7, - 0xff, 0x7c, 0x1c, 0xeb, 0x95, 0xe2, 0x63, 0x82, 0x18, 0x0a, 0xe7, 0xe6, 0x47, 0x20, 0x35, 0x96, 0x41, 0xf4, 0xf0, - 0xeb, 0x87, 0x83, 0x92, 0x4f, 0x19, 0xae, 0xec, 0xe5, 0xb7, 0xcd, 0x10, 0x4a, 0x9b, 0x10, 0x41, 0x88, 0x3f, 0x69, - 0xae, 0xf4, 0xf6, 0xe3, 0x04, 0x67, 0x68, 0x55, 0xbf, 0x61, 0xe9, 0xd5, 0x3d, 0x02, 0xeb, 0x6b, 0xbf, 0xa5, 0x58, - 0x29, 0x3e, 0xe5, 0xfa, 0x07, 0x31, 0x9b, 0x55, 0x24, 0xb0, 0x09, 0xa6, 0xd0, 0x78, 0x20, 0x9d, 0xcc, 0xec, 0x44, - 0xaa, 0x3e, 0x97, 0x70, 0x48, 0x16, 0xee, 0x21, 0x59, 0x64, 0xf4, 0x32, 0x4e, 0x6f, 0xd6, 0x2f, 0x56, 0xdb, 0x5d, - 0x39, 0x62, 0xd3, 0xc8, 0x38, 0xf9, 0x46, 0x49, 0xb9, 0x08, 0xf7, 0x0e, 0x50, 0xfc, 0xcb, 0x3f, 0xbb, 0xee, 0xbf, - 0xfc, 0xf3, 0x47, 0xab, 0x42, 0xf7, 0xc5, 0x18, 0xf3, 0xaa, 0xdb, 0xdd, 0xbb, 0x6b, 0xfb, 0x48, 0x75, 0x9c, 0x6f, - 0xaf, 0xb3, 0xb1, 0x08, 0xf0, 0x7e, 0x63, 0x09, 0x36, 0x0a, 0xe5, 0xee, 0xb3, 0x7e, 0x0d, 0x60, 0x30, 0xaf, 0x8f, - 0x42, 0x06, 0x95, 0x7e, 0x13, 0x68, 0x63, 0xe4, 0x3d, 0x68, 0x45, 0x7e, 0x3d, 0x86, 0x3f, 0x36, 0x87, 0xdf, 0x08, - 0xbe, 0xf2, 0x4f, 0xc4, 0xe3, 0x71, 0x99, 0xe2, 0x68, 0x36, 0x85, 0x0b, 0x14, 0x86, 0x1b, 0x25, 0x4a, 0xf1, 0xf0, - 0xda, 0x68, 0x20, 0x0e, 0x68, 0x92, 0x78, 0xfc, 0x0a, 0x6e, 0x4d, 0xea, 0x5f, 0x65, 0xda, 0xc1, 0x7b, 0x8f, 0x70, - 0x80, 0x2e, 0xea, 0xb3, 0x12, 0x9d, 0x6e, 0x48, 0x06, 0x28, 0x05, 0x73, 0x03, 0xc0, 0xc4, 0xf1, 0x58, 0x59, 0x9b, - 0x67, 0xd2, 0x0d, 0xe3, 0xad, 0x93, 0xb6, 0x72, 0xcf, 0xd4, 0x90, 0x8e, 0xad, 0xf7, 0x02, 0x5f, 0xa2, 0x32, 0xad, - 0xac, 0x7b, 0xe1, 0xea, 0x02, 0x3b, 0xa2, 0x64, 0x3f, 0xd7, 0x7e, 0x7c, 0xfd, 0x30, 0xc6, 0xb7, 0x5b, 0xa0, 0xae, - 0xac, 0xd5, 0x3f, 0x5a, 0x25, 0x58, 0x35, 0x57, 0xdb, 0xf4, 0x81, 0x1b, 0x9f, 0xd3, 0xec, 0x32, 0x82, 0x2c, 0xab, - 0xec, 0x23, 0xcc, 0x09, 0x56, 0x1a, 0x53, 0xf1, 0x97, 0x11, 0x75, 0x47, 0xf5, 0x3f, 0x88, 0x53, 0x31, 0x48, 0x91, - 0x84, 0xa1, 0x8c, 0x45, 0xf8, 0xff, 0x7c, 0xeb, 0x3f, 0x0c, 0xdf, 0xba, 0x7f, 0x88, 0xda, 0x01, 0xec, 0x4f, 0x5e, - 0xc8, 0xff, 0xd8, 0xec, 0x2e, 0x17, 0xec, 0xee, 0x57, 0x30, 0xba, 0xfc, 0x1f, 0xc3, 0xe8, 0x84, 0x8d, 0xac, 0x39, - 0x9d, 0xba, 0x78, 0xc7, 0x7c, 0xef, 0xdf, 0xf8, 0x77, 0xd5, 0xbe, 0x8a, 0xc7, 0xa7, 0x37, 0xfe, 0x5d, 0xb5, 0x08, - 0xbb, 0xd9, 0xc5, 0x7a, 0x1f, 0x43, 0xfb, 0xcd, 0x6b, 0xdb, 0xb3, 0xdf, 0x7c, 0xf9, 0xa5, 0x8d, 0xc7, 0x39, 0xe5, - 0x43, 0x28, 0x24, 0xfb, 0xcb, 0xbd, 0xf5, 0x8a, 0xe0, 0x46, 0x81, 0x29, 0x8a, 0x50, 0x1b, 0x64, 0x34, 0x1a, 0xef, - 0x59, 0x7e, 0x99, 0x26, 0x26, 0x34, 0x6f, 0xc1, 0xb2, 0xff, 0x54, 0x70, 0x44, 0x2f, 0x1b, 0xf0, 0x88, 0xd2, 0x75, - 0x80, 0x44, 0x61, 0x0d, 0xa2, 0xea, 0x3e, 0xa2, 0xfb, 0xf9, 0x7f, 0x75, 0xe7, 0x82, 0xbc, 0x4a, 0x24, 0x1a, 0xc6, - 0xe3, 0x4f, 0x11, 0x1f, 0x72, 0xb0, 0xca, 0x63, 0xa7, 0xdd, 0x9d, 0x7e, 0xb1, 0xbf, 0x8c, 0x0e, 0x0e, 0xd8, 0xd0, - 0xc6, 0xe2, 0x12, 0xa8, 0x62, 0x9b, 0x70, 0xc9, 0xe1, 0x4f, 0x06, 0x7f, 0xd2, 0x62, 0x5c, 0x88, 0x7c, 0x3c, 0x46, - 0x77, 0xa4, 0x0c, 0xe5, 0xf4, 0xa3, 0x29, 0x43, 0xfe, 0x83, 0x52, 0x86, 0x72, 0xfa, 0x7b, 0xa7, 0x0c, 0x31, 0x6a, - 0xa4, 0x0c, 0x01, 0x1a, 0x7f, 0x7e, 0x50, 0xe6, 0x89, 0xce, 0x13, 0x48, 0x6f, 0x72, 0xd2, 0x51, 0xde, 0x9a, 0x38, - 0x9d, 0x42, 0xda, 0xc9, 0x3f, 0x3e, 0x8b, 0x24, 0x4e, 0xa7, 0x66, 0x0e, 0x09, 0xdc, 0xce, 0x0e, 0x49, 0x23, 0x38, - 0x23, 0x4b, 0xfb, 0xc7, 0xdb, 0xce, 0xd3, 0x51, 0xa7, 0x77, 0xd8, 0x99, 0xd9, 0x9e, 0x0d, 0xe6, 0x91, 0x28, 0x68, - 0xf7, 0x0e, 0x0f, 0xa1, 0xe0, 0xc6, 0x28, 0xe8, 0x42, 0x01, 0x33, 0x0a, 0x8e, 0xa1, 0x20, 0x30, 0x0a, 0x1e, 0x41, - 0x41, 0x68, 0x14, 0x3c, 0x86, 0x82, 0x6b, 0xbb, 0x18, 0xb1, 0x32, 0x2f, 0xea, 0x31, 0x12, 0x17, 0x39, 0xed, 0x65, - 0xf5, 0x43, 0x6c, 0x11, 0xd1, 0x55, 0x1e, 0x97, 0x07, 0x60, 0x9b, 0x47, 0xfa, 0xbe, 0xa6, 0xf1, 0x67, 0x63, 0x84, - 0x7d, 0x02, 0xe7, 0xd1, 0x31, 0x78, 0x4f, 0x65, 0xcd, 0x43, 0xfd, 0xda, 0xf6, 0xca, 0xe4, 0xa1, 0x36, 0xee, 0xea, - 0xf4, 0x21, 0xcf, 0x46, 0x78, 0x51, 0x56, 0x3e, 0x6e, 0x84, 0xaa, 0x5b, 0xb8, 0x0a, 0xa9, 0xba, 0x87, 0xec, 0x10, - 0x61, 0x79, 0x95, 0xff, 0x33, 0x61, 0xc8, 0xb8, 0x3c, 0x7d, 0xcf, 0x66, 0x54, 0x7f, 0x18, 0x4b, 0x0f, 0x60, 0x89, - 0x04, 0xab, 0x5e, 0x54, 0x5d, 0xde, 0xf9, 0x1d, 0x3e, 0xad, 0xae, 0xbe, 0x7b, 0xcf, 0x89, 0xbc, 0x4b, 0x28, 0xc3, - 0xd2, 0x23, 0x37, 0xc5, 0xdc, 0x9f, 0x7a, 0x90, 0x61, 0x02, 0xc1, 0x2d, 0xef, 0x94, 0x10, 0xd2, 0x1e, 0x2e, 0xbc, - 0xef, 0xf0, 0x4d, 0x44, 0x13, 0xef, 0xb2, 0xe8, 0x95, 0x04, 0x20, 0x13, 0x5c, 0xde, 0xf3, 0xf2, 0xc6, 0x54, 0x41, - 0x15, 0xd5, 0x6b, 0x09, 0x67, 0xb3, 0xa4, 0x9e, 0x1d, 0x39, 0x11, 0x86, 0xf3, 0x7c, 0x12, 0xa7, 0x37, 0xcd, 0x5b, - 0x7b, 0xb0, 0x3d, 0x4f, 0x02, 0x66, 0x57, 0xe6, 0x49, 0xbc, 0x04, 0x60, 0xcb, 0xa7, 0xf7, 0xfe, 0xb4, 0xfc, 0xfd, - 0x8a, 0xe6, 0xb9, 0x3f, 0x55, 0x35, 0x77, 0xe7, 0x45, 0x08, 0x10, 0xcd, 0x9c, 0x08, 0x0d, 0x04, 0x24, 0x2f, 0x00, - 0x46, 0xc0, 0xf9, 0xac, 0x72, 0x19, 0x60, 0xea, 0xf5, 0x34, 0x08, 0x81, 0xab, 0x7a, 0x11, 0xf7, 0xa7, 0x55, 0x41, - 0x7f, 0x9e, 0x51, 0x95, 0x60, 0x01, 0x68, 0x2c, 0xfa, 0x2d, 0x28, 0x90, 0xaf, 0x77, 0xa4, 0x3b, 0x68, 0x4f, 0xf7, - 0xee, 0xa4, 0x07, 0x4b, 0xa7, 0x3b, 0x98, 0x29, 0xba, 0x65, 0x7e, 0xee, 0x66, 0x90, 0xfd, 0xf3, 0x4e, 0x00, 0xff, - 0xa9, 0x10, 0xfe, 0xe7, 0x93, 0xc9, 0xe4, 0xde, 0xf4, 0x87, 0xcf, 0xc3, 0x09, 0xed, 0xd2, 0xe3, 0x1e, 0xa4, 0x6f, - 0x36, 0x55, 0xd0, 0xbc, 0x53, 0x08, 0xdc, 0x2d, 0x1f, 0x56, 0x19, 0xe2, 0xeb, 0x3c, 0x5a, 0x3e, 0x3c, 0x15, 0xa2, - 0x98, 0x67, 0x74, 0x39, 0xf3, 0xb3, 0x29, 0x4b, 0xbc, 0x76, 0xe1, 0x5e, 0xab, 0xdc, 0x81, 0xcf, 0x4f, 0x4e, 0x4e, - 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x59, 0x4e, 0xa3, 0xdd, 0x9e, 0x4c, 0x0a, 0x97, 0xe9, 0x82, - 0xc3, 0x6e, 0x10, 0x1e, 0x76, 0x0b, 0xf7, 0xc6, 0xa8, 0x51, 0xb8, 0x54, 0x3d, 0x65, 0x34, 0xac, 0xe5, 0x80, 0x3e, - 0x6e, 0xb7, 0x0b, 0x57, 0x12, 0xda, 0x12, 0xfc, 0x87, 0xf2, 0xa7, 0xe7, 0x2f, 0xb8, 0x60, 0xee, 0x3d, 0x9f, 0x3b, - 0xa3, 0x99, 0xba, 0x5f, 0x4b, 0x7e, 0x8d, 0xaa, 0x40, 0x17, 0xf8, 0x67, 0x33, 0xca, 0x0f, 0xc4, 0x2c, 0xa2, 0xfb, - 0xbe, 0x4e, 0x02, 0xa8, 0xbd, 0x06, 0xca, 0x12, 0xaf, 0x7f, 0x26, 0x7e, 0x15, 0xfc, 0x07, 0x4e, 0x06, 0x35, 0xe5, - 0x35, 0xb0, 0xc9, 0x2e, 0xf9, 0x91, 0x7d, 0x5c, 0x7e, 0xdc, 0x3d, 0x44, 0x7c, 0x64, 0xbf, 0xbb, 0xf8, 0x48, 0x4c, - 0xf1, 0x21, 0x99, 0xc7, 0x15, 0x27, 0x76, 0x10, 0xd1, 0xe0, 0xc3, 0x55, 0x7a, 0xdb, 0x84, 0x2d, 0x91, 0xd9, 0x42, - 0xb0, 0xec, 0xff, 0xda, 0x94, 0x46, 0xdd, 0x99, 0xf1, 0x2d, 0x2b, 0x21, 0x8a, 0xdf, 0x24, 0xc4, 0x7e, 0xa3, 0x9d, - 0x90, 0xb2, 0x64, 0x32, 0x21, 0xf6, 0x9b, 0xc9, 0xc4, 0xd6, 0xb7, 0x04, 0xf8, 0x9c, 0x8a, 0x5a, 0xaf, 0x6b, 0x25, - 0xa2, 0x16, 0x28, 0x25, 0x55, 0x99, 0x59, 0xa0, 0x72, 0x04, 0xcc, 0x7c, 0x00, 0xf5, 0x26, 0x64, 0x39, 0x6c, 0x35, - 0xf8, 0xc4, 0x56, 0xfd, 0x96, 0xe2, 0xa4, 0xf6, 0x41, 0x89, 0x12, 0xe0, 0x2d, 0x5f, 0xc1, 0x58, 0xbf, 0x22, 0x67, - 0x4a, 0x75, 0xc6, 0xfe, 0xd3, 0xbb, 0xaf, 0x42, 0xe7, 0x8a, 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0xb5, 0xe3, 0xaf, 0x12, - 0x46, 0x42, 0xcc, 0x69, 0x15, 0x3c, 0x9d, 0x4e, 0x63, 0xf8, 0xca, 0xd9, 0xb2, 0x76, 0x73, 0xba, 0x6c, 0x3e, 0xac, - 0xcd, 0xd7, 0x33, 0x1b, 0xaa, 0x7b, 0xc6, 0xc5, 0x47, 0x17, 0xe5, 0xb1, 0xa9, 0x6b, 0xf5, 0xf5, 0x3d, 0xe1, 0xbf, - 0x5c, 0x2a, 0x26, 0xbf, 0x94, 0x87, 0x6d, 0x38, 0x66, 0xa1, 0x6c, 0xce, 0xc2, 0xa2, 0x50, 0xc7, 0x14, 0x43, 0x96, - 0xcf, 0xe1, 0x46, 0x6f, 0xd9, 0x92, 0x7e, 0x8c, 0x85, 0xe7, 0x37, 0x46, 0x20, 0xbe, 0xb6, 0x5c, 0x85, 0x8e, 0xc4, - 0xcb, 0xc8, 0xe6, 0x15, 0x2f, 0x6c, 0x15, 0x20, 0xd5, 0x48, 0xb4, 0x2d, 0x89, 0x4f, 0x99, 0x22, 0x60, 0xcc, 0x10, - 0xa2, 0x94, 0xe5, 0x82, 0xe8, 0x57, 0xba, 0xa0, 0x30, 0x13, 0x4d, 0xc4, 0x1b, 0x89, 0x2d, 0x11, 0xd6, 0xce, 0xe7, - 0x7e, 0x22, 0xd9, 0x28, 0xb1, 0x25, 0x3f, 0xd8, 0x5f, 0x56, 0x2b, 0x5f, 0xd8, 0x1a, 0x6c, 0x49, 0xbc, 0x83, 0x7e, - 0x0b, 0x1a, 0x0c, 0xac, 0x1a, 0xe8, 0xc9, 0x46, 0x34, 0xfc, 0xfe, 0xbc, 0xb4, 0x0f, 0x63, 0x37, 0xbf, 0xc1, 0x6e, - 0x7e, 0x63, 0xfd, 0x71, 0xd9, 0xbc, 0xa1, 0x57, 0x1f, 0x18, 0x6f, 0x72, 0x7f, 0xde, 0x04, 0x4b, 0x4f, 0x44, 0xb1, - 0x14, 0x7b, 0x16, 0xf9, 0xed, 0xf2, 0x92, 0x9f, 0xde, 0x22, 0x87, 0xf4, 0x35, 0x61, 0x7e, 0x78, 0x49, 0x9a, 0xd0, - 0x5e, 0xfd, 0x1c, 0x83, 0x99, 0x0d, 0xa5, 0xb1, 0x75, 0xb1, 0x4c, 0x21, 0xdd, 0x8d, 0xdf, 0x79, 0x6d, 0xc5, 0xd6, - 0xdb, 0x3a, 0xd5, 0xa9, 0xbd, 0xb5, 0xbe, 0xa7, 0x90, 0xdb, 0x10, 0xd2, 0x2b, 0xdb, 0x4c, 0xf9, 0xda, 0x95, 0xb2, - 0xf5, 0xb1, 0xac, 0x7e, 0x88, 0x7d, 0xe9, 0xff, 0x8d, 0xe3, 0x10, 0xeb, 0xc5, 0x22, 0xab, 0xff, 0x21, 0x90, 0x79, - 0xfe, 0x84, 0xd3, 0x0c, 0x3f, 0xa4, 0xe6, 0x95, 0x38, 0x80, 0xbb, 0x04, 0x31, 0xe3, 0x75, 0x4e, 0xe6, 0xb7, 0x0f, - 0xef, 0xfe, 0xfe, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x42, 0x3a, 0xdb, 0xee, 0xc1, 0x46, 0x88, 0xfd, 0x3b, 0x8f, 0x25, - 0x42, 0xe6, 0x5d, 0x41, 0x00, 0xab, 0x37, 0x4f, 0xd5, 0xf1, 0x94, 0x8c, 0xc6, 0xe2, 0xfb, 0xb3, 0x6a, 0x29, 0x0e, - 0x1f, 0xcd, 0x6f, 0xf5, 0x6a, 0x74, 0xd6, 0x8e, 0x9d, 0xfc, 0xae, 0xa7, 0x4b, 0x76, 0x1f, 0x67, 0xa9, 0x9f, 0x90, - 0x38, 0x9e, 0xdf, 0xf6, 0xa4, 0xa0, 0x6d, 0x66, 0x12, 0xaa, 0xf6, 0xfc, 0xd6, 0x3c, 0x5f, 0x53, 0x75, 0x64, 0xb9, - 0x87, 0xb9, 0x45, 0xfd, 0x9c, 0xf6, 0xe0, 0x8b, 0x1b, 0x2c, 0xf0, 0x63, 0x25, 0xcc, 0x67, 0x2c, 0x0c, 0x63, 0xda, - 0xd3, 0xf2, 0xda, 0xea, 0x3c, 0x82, 0xe3, 0x29, 0xe6, 0x92, 0xd5, 0x57, 0xc5, 0x40, 0x5e, 0x89, 0x27, 0xff, 0x2a, - 0x4f, 0x63, 0xf8, 0xdc, 0xd5, 0x56, 0x74, 0xaa, 0x73, 0x1b, 0xed, 0x0a, 0x79, 0xe2, 0x77, 0x7d, 0x2e, 0xc7, 0xed, - 0x3f, 0xf4, 0xc4, 0x82, 0xb7, 0x7b, 0x3c, 0x9d, 0x7b, 0xcd, 0xc3, 0xfa, 0x44, 0xe0, 0x55, 0x39, 0x05, 0xbc, 0x65, - 0x5a, 0x18, 0xa4, 0x95, 0xe4, 0xd3, 0x96, 0xdb, 0x51, 0x65, 0xa2, 0x03, 0xc8, 0xef, 0x2d, 0x8b, 0x8a, 0xfa, 0x64, - 0xfe, 0x31, 0xbb, 0xe5, 0xc9, 0xf6, 0xdd, 0xf2, 0x44, 0xef, 0x96, 0xfb, 0x29, 0xf6, 0xf3, 0x49, 0x07, 0xfe, 0xeb, - 0x55, 0x13, 0xf2, 0xda, 0xd6, 0xe1, 0xfc, 0xd6, 0x02, 0x3d, 0xad, 0xd9, 0x9d, 0xdf, 0xca, 0xd3, 0x45, 0x10, 0x64, - 0x6f, 0xc3, 0x79, 0x1b, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, 0x75, 0x8e, 0xe0, 0x1d, 0xb4, 0x3a, 0xde, - 0x7c, 0xd7, 0xbd, 0x7f, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, 0xe4, 0x72, 0xff, 0xea, 0x8a, 0x86, 0xde, - 0x24, 0x0d, 0x16, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdd, 0xd2, 0x6b, 0xfd, 0xe8, 0xa6, 0xf2, 0xac, 0x93, - 0xee, 0x61, 0x59, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, 0xb4, 0x65, 0x13, 0xfc, 0x9b, 0xac, 0xcd, - 0xd6, 0xc9, 0xfc, 0x56, 0x64, 0xdc, 0x8b, 0x84, 0x4f, 0xc2, 0x81, 0xb9, 0x86, 0xed, 0x93, 0xed, 0xe0, 0x8e, 0xf4, - 0x48, 0x17, 0x5a, 0x28, 0x28, 0xb9, 0x13, 0xd2, 0x89, 0xbf, 0x88, 0xf9, 0xfd, 0xbd, 0xee, 0xa2, 0x8c, 0x8d, 0x5e, - 0xef, 0x61, 0xe8, 0x55, 0xdd, 0x07, 0x72, 0xe9, 0xcf, 0x9f, 0x1c, 0xc1, 0x7f, 0x32, 0x51, 0xf7, 0xae, 0xd2, 0xd5, - 0xa5, 0xdd, 0x0b, 0xba, 0xfa, 0x7e, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, 0x83, - 0xaa, 0x2b, 0x2d, 0xeb, 0x93, 0x6a, 0x7f, 0x5a, 0xe7, 0x0f, 0xac, 0x1b, 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x80, - 0x77, 0xa3, 0xb2, 0xc6, 0xb8, 0xa8, 0xbf, 0x4f, 0xee, 0x4a, 0x13, 0x45, 0xa6, 0xcd, 0x80, 0x95, 0xb2, 0x2f, 0xad, - 0x94, 0x94, 0x92, 0x71, 0x7f, 0x78, 0x3b, 0x8b, 0xad, 0x6b, 0x79, 0x51, 0x00, 0xb1, 0x3b, 0x6e, 0xdb, 0xb6, 0x44, - 0xc2, 0x16, 0x7c, 0xaf, 0xc4, 0x16, 0x1f, 0x76, 0xb7, 0x87, 0xa0, 0x69, 0x5d, 0x4f, 0x85, 0x66, 0xf7, 0xd2, 0xbf, - 0xa3, 0xd9, 0x65, 0xd7, 0xb6, 0xc0, 0x4f, 0xd3, 0x94, 0xb9, 0x6d, 0xa2, 0xcc, 0xea, 0xda, 0xd6, 0xed, 0x2c, 0x4e, - 0x72, 0x62, 0x47, 0x9c, 0xcf, 0x3d, 0xf9, 0xe5, 0xf7, 0x9b, 0x43, 0x37, 0xcd, 0xa6, 0xad, 0x6e, 0xbb, 0xdd, 0x86, - 0xab, 0xcf, 0x6d, 0xeb, 0x9a, 0xd1, 0x9b, 0xa7, 0xe9, 0x2d, 0xb1, 0xdb, 0x56, 0xdb, 0xea, 0x74, 0x4f, 0xac, 0x4e, - 0xf7, 0xc8, 0x7d, 0x74, 0x62, 0x0f, 0x3e, 0xb3, 0xac, 0x7e, 0x48, 0x27, 0x39, 0xfc, 0xb0, 0xac, 0xbe, 0x50, 0xbc, - 0xe4, 0x6f, 0xcb, 0x72, 0x83, 0x38, 0x6f, 0x76, 0xac, 0xa5, 0x7a, 0xb4, 0x2c, 0xb8, 0x4e, 0xc1, 0xb3, 0x3e, 0x9f, - 0x74, 0x27, 0x47, 0x93, 0x27, 0x3d, 0x55, 0x5c, 0x7c, 0x56, 0xab, 0x8e, 0xe5, 0xbf, 0x5d, 0xa3, 0x59, 0xce, 0xb3, - 0xf4, 0x03, 0x55, 0xc9, 0xe3, 0x16, 0x88, 0x9e, 0xad, 0x4d, 0xbb, 0x9b, 0x23, 0x75, 0x4e, 0xae, 0x82, 0x49, 0xb7, - 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0xf6, 0x5b, 0x1a, 0xf4, 0xbe, 0x89, 0xa6, 0x4e, 0x73, 0x1b, 0xa2, 0x3a, 0xb6, - 0x9a, 0xe3, 0x54, 0xcf, 0xaf, 0x0f, 0xa7, 0xf7, 0xb4, 0xae, 0x2a, 0x20, 0xb0, 0xad, 0x90, 0xd8, 0xaf, 0x3a, 0xdd, - 0x13, 0xdc, 0xe9, 0x3c, 0x72, 0x1f, 0x9d, 0x04, 0x6d, 0x7c, 0xe4, 0x1e, 0x35, 0x0f, 0xdd, 0x47, 0xf8, 0xa4, 0x79, - 0x82, 0x4f, 0x5e, 0x9c, 0x04, 0xcd, 0x23, 0xf7, 0x08, 0xb7, 0x9b, 0x27, 0x50, 0xd8, 0x3c, 0x69, 0x9e, 0x5c, 0x37, - 0x8f, 0x4e, 0x82, 0xb6, 0x28, 0xed, 0xba, 0xc7, 0xc7, 0xcd, 0x4e, 0xdb, 0x3d, 0x3e, 0xc6, 0xc7, 0xee, 0xa3, 0x47, - 0xcd, 0xce, 0xa1, 0xfb, 0xe8, 0xd1, 0xcb, 0xe3, 0x13, 0xf7, 0x10, 0xde, 0x1d, 0x1e, 0x06, 0x87, 0x6e, 0xa7, 0xd3, - 0x84, 0x3f, 0xf8, 0xc4, 0xed, 0xca, 0x1f, 0x9d, 0x8e, 0x7b, 0xd8, 0xc1, 0xed, 0xf8, 0xb8, 0xeb, 0x3e, 0x7a, 0x82, - 0xc5, 0x5f, 0x51, 0x0d, 0x8b, 0x3f, 0xd0, 0x0d, 0x7e, 0xe2, 0x76, 0x1f, 0xc9, 0x5f, 0xa2, 0xc3, 0xeb, 0xa3, 0x93, - 0xbf, 0xd9, 0xad, 0x9d, 0x73, 0xe8, 0xc8, 0x39, 0x9c, 0x1c, 0xbb, 0x87, 0x87, 0xf8, 0xa8, 0xe3, 0x9e, 0x1c, 0x46, - 0xcd, 0xa3, 0xae, 0xfb, 0xe8, 0x71, 0xd0, 0xec, 0xb8, 0x8f, 0x1f, 0xe3, 0x76, 0xf3, 0xd0, 0xed, 0xe2, 0x8e, 0x7b, - 0x74, 0x28, 0x7e, 0x1c, 0xba, 0xdd, 0xeb, 0xc7, 0x4f, 0xdc, 0x47, 0xc7, 0xd1, 0x23, 0xf7, 0xe8, 0xbb, 0xa3, 0x13, - 0xb7, 0x7b, 0x18, 0x1d, 0x3e, 0x72, 0xbb, 0x8f, 0xaf, 0x1f, 0xb9, 0x47, 0x51, 0xb3, 0xfb, 0xe8, 0xde, 0x96, 0x9d, - 0xae, 0x0b, 0x38, 0x12, 0xaf, 0xe1, 0x05, 0x56, 0x2f, 0xe0, 0xff, 0x48, 0xb4, 0xfd, 0x37, 0xec, 0x26, 0xdf, 0x6c, - 0xfa, 0xc4, 0x3d, 0x79, 0x1c, 0xc8, 0xea, 0x50, 0xd0, 0xd4, 0x35, 0xa0, 0xc9, 0x75, 0x53, 0x0e, 0x2b, 0xba, 0x6b, - 0xea, 0x8e, 0xf4, 0xff, 0x6a, 0xb0, 0xeb, 0x26, 0x0c, 0x2c, 0xc7, 0xfd, 0x77, 0xed, 0xa7, 0x5c, 0xf2, 0x7e, 0x6b, - 0x2a, 0x49, 0x7f, 0x3a, 0xf8, 0x4c, 0x7e, 0xd7, 0xe0, 0xb3, 0x31, 0xf6, 0x77, 0x39, 0x3e, 0xe2, 0x8f, 0x3b, 0x3e, - 0x22, 0xfa, 0x10, 0xcf, 0x47, 0xfc, 0xbb, 0x7b, 0x3e, 0xfc, 0x75, 0xc7, 0xf9, 0x0d, 0xdf, 0x70, 0x70, 0xac, 0x5b, - 0xc5, 0x2f, 0xb9, 0x33, 0x4a, 0xe1, 0x0b, 0x9a, 0x45, 0xef, 0x86, 0x93, 0x88, 0x9a, 0x7e, 0xa0, 0x14, 0x58, 0xec, - 0x0d, 0x97, 0x3c, 0x36, 0xd8, 0x85, 0x90, 0xf0, 0xe3, 0x08, 0xf9, 0xf2, 0x21, 0xf8, 0x08, 0x7f, 0x77, 0x7c, 0x04, - 0x26, 0x3e, 0x6a, 0xbe, 0x7c, 0xe1, 0x69, 0x10, 0x9e, 0x82, 0x73, 0xf1, 0xec, 0xc0, 0xf1, 0xe1, 0x86, 0xdd, 0xa2, - 0x50, 0x94, 0xdb, 0x32, 0x22, 0xf6, 0xee, 0x53, 0xc2, 0x0e, 0xf2, 0xae, 0x00, 0x62, 0x2b, 0xb7, 0xcc, 0x5c, 0x48, - 0x1d, 0xf5, 0x50, 0x0a, 0xa5, 0xae, 0xdb, 0x76, 0xdb, 0xa5, 0x4b, 0x07, 0xee, 0x87, 0x20, 0xcb, 0x94, 0xfb, 0xf0, - 0xad, 0xf6, 0x38, 0x9d, 0x8a, 0xaf, 0xba, 0xc3, 0x77, 0x74, 0x20, 0x3b, 0x33, 0x90, 0x9f, 0x30, 0x82, 0x50, 0x8f, - 0x72, 0xf4, 0xf8, 0xd9, 0x87, 0x6f, 0xe0, 0x8e, 0x06, 0x1d, 0x95, 0x98, 0x81, 0xb7, 0xe3, 0x15, 0x0d, 0x99, 0xef, - 0xd8, 0xce, 0x3c, 0xa3, 0x13, 0x9a, 0xe5, 0xcd, 0xda, 0xc5, 0x05, 0xe2, 0xce, 0x02, 0x64, 0xeb, 0x8f, 0x82, 0x67, - 0xf0, 0x5d, 0x08, 0x32, 0x52, 0xfe, 0x46, 0x5b, 0x19, 0x60, 0x76, 0x81, 0x75, 0x49, 0x06, 0xb2, 0xb6, 0x52, 0xda, - 0x6c, 0xa9, 0xb5, 0x75, 0xdc, 0xee, 0x31, 0xb2, 0x44, 0x31, 0xdc, 0xb8, 0xff, 0x83, 0xd3, 0x3c, 0x6c, 0xff, 0x01, - 0x19, 0xcd, 0xca, 0x8e, 0x2e, 0x94, 0xbb, 0x2d, 0x29, 0xbf, 0xcb, 0xb4, 0x76, 0xab, 0x84, 0x2d, 0x29, 0xe2, 0x73, - 0x39, 0x77, 0x1b, 0xf5, 0x12, 0x15, 0xe0, 0x97, 0x77, 0x23, 0x4d, 0xd8, 0xd4, 0x31, 0xce, 0xdd, 0x26, 0xf2, 0x46, - 0x7f, 0xb8, 0xb6, 0x17, 0xa1, 0xa2, 0xaa, 0x92, 0xa0, 0xa5, 0x88, 0xb7, 0xb0, 0xc4, 0x4a, 0x56, 0x2b, 0x27, 0x01, - 0x17, 0x39, 0x31, 0x70, 0x0a, 0xcf, 0xa8, 0x86, 0xe4, 0x04, 0x97, 0x00, 0x09, 0x04, 0x93, 0x44, 0xfe, 0x5b, 0x15, - 0xeb, 0x1f, 0xca, 0xf1, 0xe5, 0xc6, 0x7e, 0x32, 0x05, 0x2a, 0xf4, 0x93, 0xe9, 0x86, 0x5b, 0x4d, 0x86, 0x8c, 0xd6, - 0x4a, 0xab, 0xae, 0x2a, 0xf7, 0x59, 0xfe, 0xf4, 0xee, 0xbd, 0xba, 0xfa, 0xd3, 0x06, 0xef, 0xb4, 0x88, 0x70, 0x54, - 0x9f, 0x29, 0x68, 0x90, 0x2f, 0xfa, 0x33, 0xca, 0x7d, 0x99, 0x58, 0x0f, 0xfa, 0x04, 0xdc, 0x17, 0x61, 0x29, 0x6b, - 0x94, 0xd8, 0x42, 0xba, 0x13, 0x79, 0xd8, 0x51, 0x8a, 0x7a, 0x6c, 0xa9, 0x3b, 0x73, 0x9a, 0x62, 0x69, 0x48, 0x07, - 0x4b, 0x7f, 0x4c, 0xe0, 0x8b, 0xa3, 0x53, 0x24, 0x49, 0xed, 0xc1, 0x17, 0xe5, 0x77, 0xbf, 0x77, 0x2d, 0x42, 0xcc, - 0x92, 0x0f, 0xa3, 0x8c, 0xc6, 0xff, 0x44, 0xbe, 0x60, 0x41, 0x9a, 0x7c, 0x71, 0x61, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, - 0x4e, 0xc8, 0x17, 0x20, 0xe3, 0x3d, 0x61, 0x7d, 0x00, 0x23, 0x6c, 0xdc, 0xce, 0x62, 0x2c, 0x34, 0xa6, 0x07, 0x28, - 0x44, 0x12, 0x5c, 0xbb, 0x7b, 0x6c, 0x5b, 0xd2, 0x26, 0x16, 0xbf, 0x07, 0x52, 0x9c, 0x0a, 0x25, 0xc0, 0xea, 0x74, - 0xdd, 0xe3, 0xa8, 0xeb, 0x3e, 0xb9, 0x7e, 0xec, 0x9e, 0x44, 0x9d, 0xc7, 0xd7, 0x4d, 0xf8, 0xb7, 0xeb, 0x3e, 0x89, - 0x9b, 0x5d, 0xf7, 0x09, 0xfc, 0xff, 0xdd, 0x91, 0x7b, 0x1c, 0x35, 0x3b, 0xee, 0xc9, 0xf5, 0xa1, 0x7b, 0xf8, 0xb2, - 0xd3, 0x75, 0x0f, 0xad, 0x8e, 0x25, 0xdb, 0x01, 0xbb, 0x96, 0xdc, 0xf9, 0x8b, 0xb5, 0x0d, 0xb1, 0x25, 0x1c, 0x27, - 0x0f, 0x07, 0xd8, 0xd8, 0x29, 0xbf, 0x2e, 0xac, 0xf6, 0xa7, 0x72, 0xd6, 0x3d, 0xf3, 0x33, 0xf8, 0xc4, 0x5b, 0x7d, - 0xef, 0xd6, 0xde, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x04, 0xec, 0x70, 0x1b, 0x9b, 0x97, 0xce, 0xc0, 0x8d, 0x2d, 0xe2, - 0x8b, 0x18, 0xfa, 0x62, 0xe0, 0xdd, 0xa4, 0x2d, 0x2b, 0xea, 0xcb, 0x87, 0x05, 0xb3, 0x60, 0xe2, 0xdb, 0x43, 0x62, - 0x90, 0xaf, 0xc2, 0x62, 0x7d, 0x7c, 0x38, 0xa3, 0x90, 0xa5, 0xc6, 0xbd, 0x3b, 0xb4, 0x3a, 0x59, 0x17, 0x32, 0xb8, - 0x29, 0xa9, 0x28, 0x34, 0xe8, 0x35, 0x37, 0x6d, 0x85, 0x25, 0xc1, 0x2f, 0x68, 0x3e, 0xb4, 0xa1, 0xc8, 0xf6, 0x6c, - 0xe1, 0xe2, 0xb3, 0xcb, 0xcf, 0xdc, 0x95, 0x84, 0x5d, 0x15, 0x60, 0x71, 0x3a, 0x16, 0x76, 0x2d, 0xe0, 0xc7, 0x46, - 0x07, 0x07, 0x3b, 0xf7, 0x8b, 0x50, 0x20, 0x61, 0xae, 0xd5, 0xd7, 0xb1, 0x4c, 0x56, 0x64, 0x9b, 0x88, 0x2e, 0xfb, - 0x15, 0x28, 0x44, 0x0a, 0x4f, 0x57, 0xd4, 0xe7, 0xae, 0x9f, 0xc8, 0x6c, 0x47, 0x83, 0x61, 0xe1, 0x0e, 0x3d, 0x44, - 0x45, 0xca, 0x7d, 0x99, 0x65, 0x64, 0xee, 0xf3, 0x94, 0xfb, 0xfa, 0x16, 0x09, 0xe3, 0xc2, 0x3c, 0x70, 0xf4, 0x46, - 0xdd, 0xc1, 0x9b, 0xf7, 0xa7, 0x96, 0xdc, 0x9e, 0xfd, 0x56, 0xd4, 0x1d, 0xf4, 0x85, 0xcf, 0x44, 0x9e, 0xa8, 0x26, - 0xf2, 0x44, 0xb5, 0xa5, 0x0e, 0xd1, 0x43, 0x24, 0xad, 0x68, 0xc9, 0x69, 0x0b, 0x9b, 0x41, 0x7a, 0x7b, 0x67, 0x8b, - 0x98, 0x33, 0xf8, 0xba, 0x43, 0x4b, 0x1c, 0xa7, 0x86, 0x05, 0x2b, 0x0f, 0xcc, 0x28, 0xed, 0xf0, 0x8a, 0x27, 0xda, - 0x37, 0x3c, 0x61, 0x31, 0xd5, 0x47, 0x64, 0x54, 0x57, 0xe5, 0x91, 0xae, 0xcd, 0xda, 0xf9, 0xe2, 0x6a, 0xc6, 0xb8, - 0xad, 0x0f, 0x9e, 0x7d, 0xab, 0x1a, 0xf4, 0xc5, 0x50, 0x83, 0x71, 0xa1, 0x9c, 0xd7, 0xfa, 0x3b, 0x76, 0xf5, 0x25, - 0x55, 0xb3, 0x57, 0x12, 0x02, 0x8e, 0x32, 0x47, 0x87, 0x83, 0xd2, 0x5d, 0x6c, 0xbe, 0x2b, 0xfa, 0xad, 0xe8, 0x70, - 0x30, 0xf6, 0xe6, 0xaa, 0xbf, 0x97, 0xe9, 0x74, 0x7b, 0x5f, 0x71, 0x3a, 0x1d, 0x8a, 0x33, 0x7b, 0xf2, 0x72, 0x0b, - 0xad, 0xfc, 0xa6, 0xb1, 0x3d, 0xe8, 0x2b, 0x65, 0xc0, 0x12, 0x81, 0x75, 0xfb, 0xb8, 0xad, 0x8f, 0x01, 0xc6, 0xe9, - 0x14, 0x36, 0xa4, 0x6c, 0x62, 0x0c, 0x52, 0xf3, 0xb8, 0x47, 0x9d, 0x41, 0xdf, 0xb7, 0x04, 0x6f, 0x11, 0xcc, 0x23, - 0xf7, 0x5a, 0xd0, 0x38, 0x4a, 0x67, 0xd4, 0x65, 0x69, 0xeb, 0x86, 0x5e, 0x35, 0xfd, 0x39, 0xab, 0xdc, 0xdb, 0xa0, - 0x74, 0x94, 0x43, 0xa6, 0xda, 0x23, 0xae, 0x0e, 0xc9, 0x76, 0x2b, 0x77, 0xdb, 0x11, 0xd8, 0x3c, 0xda, 0x35, 0x27, - 0x7c, 0x72, 0x06, 0x58, 0xe9, 0xa0, 0xdf, 0xf2, 0xd7, 0x30, 0x22, 0xf8, 0x7d, 0xa1, 0x1c, 0xed, 0x60, 0xd8, 0x00, - 0xbd, 0xd9, 0x96, 0x14, 0x07, 0xda, 0x21, 0xaf, 0x04, 0x75, 0x61, 0x0f, 0xfe, 0xf5, 0x7f, 0xfc, 0x2f, 0xe5, 0x63, - 0xef, 0xb7, 0xa2, 0x8e, 0xee, 0x6b, 0x6d, 0x55, 0x8a, 0x3e, 0x1c, 0xe4, 0xaf, 0x82, 0xc2, 0xf4, 0xb6, 0x39, 0xcd, - 0x58, 0xd8, 0x8c, 0xfc, 0x78, 0x62, 0x0f, 0x76, 0x63, 0xd3, 0x3c, 0x5f, 0xab, 0xa0, 0xae, 0x17, 0x01, 0xbd, 0xfe, - 0xaa, 0x13, 0xa2, 0xfa, 0xa0, 0xa1, 0xd8, 0xda, 0xe6, 0x79, 0xd1, 0x6a, 0xf7, 0xd5, 0xce, 0x8c, 0x26, 0xea, 0xe3, - 0x98, 0x8a, 0x03, 0x26, 0xb5, 0xa3, 0xa2, 0x85, 0x6d, 0x95, 0x41, 0xad, 0xff, 0xfb, 0x3f, 0xff, 0xcb, 0x7f, 0xd3, - 0x8f, 0x10, 0xab, 0xfa, 0xd7, 0xff, 0xfe, 0x9f, 0xff, 0xcf, 0xff, 0xfe, 0xaf, 0x70, 0xbc, 0x50, 0xc5, 0xb3, 0x04, - 0x53, 0xb1, 0xaa, 0x60, 0x96, 0xe4, 0x2e, 0x16, 0x64, 0xe0, 0xcf, 0x58, 0xce, 0x59, 0x50, 0x3f, 0x3c, 0x7a, 0x2e, - 0x06, 0x14, 0x3b, 0x53, 0x41, 0x27, 0x76, 0x78, 0x51, 0x11, 0x54, 0x0d, 0xe5, 0x82, 0x70, 0x8b, 0x7e, 0x0b, 0xf0, - 0xfd, 0xb0, 0xf3, 0xf6, 0x6e, 0xb9, 0x1c, 0x4b, 0x4d, 0x26, 0x50, 0x52, 0x54, 0xe5, 0x16, 0xc4, 0x56, 0x96, 0xf0, - 0xe8, 0x75, 0x8d, 0x62, 0xb1, 0x7a, 0xb5, 0x36, 0xbd, 0x9f, 0x16, 0x39, 0x67, 0x13, 0x40, 0xb9, 0xf4, 0x13, 0x8b, - 0x30, 0x76, 0x13, 0x74, 0xc5, 0xf8, 0xae, 0x10, 0xbd, 0x48, 0x02, 0x3d, 0x3a, 0xf9, 0x43, 0xf1, 0xa7, 0x19, 0x68, - 0x64, 0x96, 0x33, 0xf3, 0x6f, 0x95, 0x79, 0xfe, 0xa8, 0xdd, 0x9e, 0xdf, 0xa2, 0x65, 0x35, 0x02, 0xde, 0x35, 0x98, - 0xa0, 0x63, 0xb3, 0x43, 0x11, 0xff, 0x2e, 0xdd, 0xd8, 0x6d, 0x0b, 0x7c, 0xe1, 0x56, 0xbb, 0x28, 0xfe, 0xb8, 0x14, - 0x9e, 0x54, 0xf6, 0x0b, 0xc4, 0xa9, 0x95, 0xd3, 0xf9, 0x2a, 0x35, 0x27, 0xb7, 0x34, 0x5a, 0x75, 0x65, 0xab, 0xa8, - 0xb3, 0x79, 0x8c, 0xdc, 0x8c, 0xb3, 0x9b, 0x11, 0xf2, 0x23, 0x88, 0x79, 0x47, 0x1d, 0x1c, 0x75, 0x97, 0x65, 0xf7, - 0x9c, 0xa7, 0x33, 0x33, 0xb0, 0x4e, 0x7d, 0x1a, 0xd0, 0x89, 0x76, 0xd6, 0xab, 0xf7, 0x32, 0x68, 0x5e, 0x44, 0x87, - 0x5b, 0xc6, 0x52, 0x20, 0x89, 0x80, 0xba, 0xd5, 0x2e, 0x3e, 0x87, 0x1d, 0xb8, 0x9c, 0xc4, 0xa9, 0xcf, 0x3d, 0x41, - 0xb0, 0x3d, 0x33, 0x3c, 0xef, 0x03, 0x4f, 0x4a, 0x97, 0x06, 0x3c, 0x3d, 0x59, 0x15, 0xdc, 0xe6, 0xf5, 0xc3, 0xfe, - 0x85, 0x2b, 0x9a, 0x9b, 0x5d, 0x49, 0xaf, 0xdb, 0x97, 0x2a, 0xea, 0xfd, 0xae, 0xe6, 0xae, 0x52, 0x02, 0xa9, 0x8b, - 0xb6, 0xbf, 0x97, 0x72, 0x5d, 0xbe, 0xfd, 0x86, 0x3b, 0xb6, 0x00, 0xd3, 0x5e, 0xaf, 0x25, 0x0a, 0xa1, 0xd6, 0x3b, - 0xf2, 0x65, 0x69, 0x32, 0xf9, 0xf3, 0xb9, 0xa8, 0x88, 0x7a, 0xfd, 0x96, 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, - 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, 0x68, 0xea, 0xe0, 0xff, 0x01, 0x0b, 0x95, - 0x29, 0x52, 0xc9, 0x90, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdc, 0x48, 0xb6, 0xd8, 0xb3, + 0xe7, 0x2b, 0x40, 0x34, 0x2f, 0x85, 0x1c, 0x66, 0xa1, 0x16, 0x92, 0x12, 0x85, 0x62, 0x56, 0x0d, 0x45, 0xa9, 0x47, + 0x3d, 0xad, 0x6d, 0x44, 0xa9, 0x7b, 0xa6, 0xd9, 0x1c, 0x12, 0x04, 0xb2, 0x0a, 0xd9, 0x42, 0x01, 0xd5, 0x89, 0x2c, + 0x2e, 0x5d, 0x85, 0x1b, 0xfe, 0x00, 0x47, 0x38, 0xc2, 0x4f, 0x7e, 0x71, 0xf8, 0x3e, 0xf8, 0x23, 0xfc, 0x7c, 0x3f, + 0xc5, 0x3f, 0x60, 0x7f, 0x82, 0xe3, 0xe4, 0x02, 0x24, 0x6a, 0xa1, 0xa8, 0x9e, 0x9e, 0xeb, 0xfb, 0xe0, 0xe8, 0x68, + 0xaa, 0x90, 0xc8, 0xe5, 0xe4, 0xc9, 0x93, 0x67, 0xcf, 0xc4, 0xd1, 0x56, 0x9c, 0x47, 0xe2, 0x6e, 0x4a, 0x9d, 0x44, + 0x4c, 0xd2, 0xc1, 0x91, 0xfe, 0x4b, 0xc3, 0x78, 0x70, 0x94, 0xb2, 0xec, 0x93, 0xc3, 0x69, 0x4a, 0x58, 0x94, 0x67, + 0x4e, 0xc2, 0xe9, 0x88, 0xc4, 0xa1, 0x08, 0x03, 0x36, 0x09, 0xc7, 0xd4, 0x69, 0x0f, 0x8e, 0x26, 0x54, 0x84, 0x4e, + 0x94, 0x84, 0xbc, 0xa0, 0x82, 0x7c, 0xfc, 0xf0, 0x75, 0xeb, 0x70, 0x70, 0x54, 0x44, 0x9c, 0x4d, 0x85, 0x03, 0x5d, + 0x92, 0x49, 0x1e, 0xcf, 0x52, 0x3a, 0x68, 0xb7, 0x6f, 0x6e, 0x6e, 0xfc, 0x9f, 0x8a, 0xdf, 0x45, 0x79, 0x56, 0x08, + 0xe7, 0x39, 0xb9, 0x61, 0x59, 0x9c, 0xdf, 0x60, 0x2e, 0xc8, 0x73, 0xff, 0x34, 0x09, 0xe3, 0xfc, 0xe6, 0x7d, 0x9e, + 0x8b, 0x9d, 0x1d, 0x4f, 0x3d, 0xde, 0x9d, 0x9c, 0x9e, 0x12, 0x42, 0xae, 0x73, 0x16, 0x3b, 0x9d, 0xc5, 0xa2, 0x2e, + 0xf4, 0xb3, 0x50, 0xb0, 0x6b, 0xaa, 0x9a, 0xa0, 0x9d, 0x1d, 0x37, 0x8c, 0xf3, 0xa9, 0xa0, 0xf1, 0xa9, 0xb8, 0x4b, + 0xe9, 0x69, 0x42, 0xa9, 0x28, 0x5c, 0x96, 0x39, 0xcf, 0xf3, 0x68, 0x36, 0xa1, 0x99, 0xf0, 0xa7, 0x3c, 0x17, 0x39, + 0x40, 0xb2, 0xb3, 0xe3, 0x72, 0x3a, 0x4d, 0xc3, 0x88, 0xc2, 0xfb, 0x93, 0xd3, 0xd3, 0xba, 0x45, 0x5d, 0x09, 0x67, + 0x82, 0x9c, 0xde, 0x4d, 0xae, 0xf2, 0xd4, 0x43, 0x38, 0x11, 0x24, 0xa3, 0x37, 0xce, 0xf7, 0x34, 0xfc, 0xf4, 0x3a, + 0x9c, 0xf6, 0xa3, 0x34, 0x2c, 0x0a, 0xe7, 0x58, 0xcc, 0xe5, 0x14, 0xf8, 0x2c, 0x12, 0x39, 0xf7, 0x04, 0xa6, 0x98, + 0xa1, 0x39, 0x1b, 0x79, 0x22, 0x61, 0x85, 0x7f, 0xb1, 0x1d, 0x15, 0xc5, 0x7b, 0x5a, 0xcc, 0x52, 0xb1, 0x4d, 0xb6, + 0x3a, 0x98, 0x6d, 0x11, 0x92, 0x09, 0x24, 0x12, 0x9e, 0xdf, 0x38, 0x2f, 0x38, 0xcf, 0xb9, 0xe7, 0x9e, 0x9c, 0x9e, + 0xaa, 0x1a, 0x0e, 0x2b, 0x9c, 0x2c, 0x17, 0x4e, 0xd5, 0x5f, 0x78, 0x95, 0x52, 0xdf, 0xf9, 0x58, 0x50, 0xe7, 0x72, + 0x96, 0x15, 0xe1, 0x88, 0x9e, 0x9c, 0x9e, 0x5e, 0x3a, 0x39, 0x77, 0x2e, 0xa3, 0xa2, 0xb8, 0x74, 0x58, 0x56, 0x08, + 0x1a, 0xc6, 0xbe, 0x8b, 0xfa, 0x72, 0xb0, 0xa8, 0x28, 0x3e, 0xd0, 0x5b, 0x41, 0x04, 0x96, 0x8f, 0x82, 0xd0, 0x72, + 0x4c, 0x85, 0x53, 0x54, 0xf3, 0xf2, 0xd0, 0x3c, 0xa5, 0xc2, 0x11, 0x44, 0xbe, 0xcf, 0xfb, 0x0a, 0xf7, 0x54, 0x3d, + 0x8a, 0x3e, 0x1b, 0x79, 0x5c, 0xec, 0xec, 0x88, 0x0a, 0xcf, 0x48, 0x4d, 0xcd, 0x61, 0x84, 0x6e, 0x99, 0xb2, 0x9d, + 0x1d, 0xea, 0xa7, 0x34, 0x1b, 0x8b, 0x84, 0x10, 0xd2, 0xed, 0xb3, 0x9d, 0x1d, 0x4f, 0x90, 0x44, 0xf8, 0x63, 0x2a, + 0x3c, 0x8a, 0x10, 0xae, 0x5b, 0xef, 0xec, 0x78, 0x0a, 0x09, 0x39, 0x51, 0x88, 0x6b, 0xe0, 0x18, 0xf9, 0x1a, 0xfb, + 0xa7, 0x77, 0x59, 0xe4, 0xd9, 0xf0, 0x23, 0xcc, 0x76, 0x76, 0x12, 0xe1, 0x17, 0xd0, 0x23, 0x16, 0x08, 0x95, 0x9c, + 0x8a, 0x19, 0xcf, 0x1c, 0x51, 0x8a, 0xfc, 0x54, 0x70, 0x96, 0x8d, 0x3d, 0x34, 0x37, 0x65, 0x56, 0xc3, 0xb2, 0x54, + 0xe0, 0xbe, 0x17, 0x24, 0x23, 0x03, 0x18, 0xf1, 0x58, 0x78, 0xb0, 0x8a, 0xf9, 0xc8, 0xc9, 0x08, 0x71, 0x0b, 0xd9, + 0xd6, 0x1d, 0x66, 0x41, 0xb6, 0xeb, 0xba, 0x58, 0x41, 0x89, 0x33, 0x81, 0xf0, 0x27, 0xe2, 0x65, 0xd8, 0xf7, 0x7d, + 0x81, 0xc8, 0x60, 0x6e, 0xb0, 0x92, 0x59, 0xf3, 0x1c, 0x66, 0x67, 0x9d, 0xf3, 0x40, 0xf8, 0x9c, 0xc6, 0xb3, 0x88, + 0x7a, 0x1e, 0xc3, 0x1c, 0xe7, 0x88, 0x0c, 0xd8, 0xae, 0x57, 0x90, 0x01, 0x2c, 0xf7, 0xd2, 0x5a, 0x13, 0xb2, 0xd5, + 0x41, 0x1a, 0xc6, 0x0a, 0x40, 0xc0, 0xb0, 0x86, 0xa7, 0x20, 0xc4, 0xcd, 0x66, 0x93, 0x2b, 0xca, 0xdd, 0xaa, 0x5a, + 0xbf, 0x41, 0x16, 0xb3, 0x82, 0x3a, 0x51, 0x51, 0x38, 0xa3, 0x59, 0x16, 0x09, 0x96, 0x67, 0x8e, 0xbb, 0x5b, 0xec, + 0xba, 0x8a, 0x1c, 0x2a, 0x6a, 0x70, 0x51, 0x89, 0x3c, 0x8e, 0x76, 0xb3, 0xb3, 0x7c, 0xb7, 0x7b, 0x8e, 0x01, 0x4a, + 0xd4, 0xd7, 0xfd, 0x69, 0x04, 0x50, 0x9c, 0xc1, 0x1c, 0x4b, 0xfc, 0x4c, 0xc0, 0x2c, 0xe5, 0x14, 0xb9, 0x18, 0x66, + 0xfe, 0xea, 0x46, 0x21, 0xc2, 0x9f, 0x84, 0x53, 0x8f, 0x92, 0x01, 0x95, 0xc4, 0x15, 0x66, 0x11, 0xc0, 0xda, 0x58, + 0xb7, 0x21, 0x0d, 0xa8, 0x5f, 0x93, 0x14, 0x0a, 0x84, 0x3f, 0xca, 0xf9, 0x8b, 0x30, 0x4a, 0xa0, 0x5d, 0x45, 0x30, + 0xb1, 0xd9, 0x6f, 0x11, 0xa7, 0xa1, 0xa0, 0x2f, 0x52, 0x0a, 0x4f, 0x9e, 0x2b, 0x5b, 0xba, 0x08, 0x73, 0xf2, 0xdc, + 0x4f, 0x99, 0x78, 0x93, 0x67, 0x11, 0xed, 0x73, 0x8b, 0xba, 0x18, 0xac, 0xfb, 0xb1, 0x10, 0x9c, 0x5d, 0xcd, 0x04, + 0xf5, 0xdc, 0x0c, 0x6a, 0xb8, 0x98, 0x23, 0xcc, 0x7c, 0x41, 0x6f, 0xc5, 0x49, 0x9e, 0x09, 0x9a, 0x09, 0x42, 0x0d, + 0x52, 0x71, 0xe6, 0x87, 0xd3, 0x29, 0xcd, 0xe2, 0x93, 0x84, 0xa5, 0xb1, 0xc7, 0x50, 0x89, 0x4a, 0x1c, 0x09, 0x02, + 0x73, 0x24, 0x83, 0x2c, 0x80, 0x3f, 0x9b, 0x67, 0xe3, 0x09, 0x32, 0x90, 0x9b, 0x82, 0x12, 0xd7, 0xed, 0x8f, 0x72, + 0xee, 0xe9, 0x19, 0x38, 0xf9, 0xc8, 0x11, 0x30, 0xc6, 0xfb, 0x59, 0x4a, 0x0b, 0x44, 0x77, 0x09, 0xab, 0x96, 0x51, + 0x23, 0xf8, 0x3d, 0x50, 0x7c, 0x89, 0xbc, 0x0c, 0x05, 0x59, 0xff, 0x3a, 0xe4, 0xce, 0x0f, 0x7a, 0x47, 0xfd, 0x64, + 0xb8, 0x59, 0x2c, 0xc8, 0x4f, 0xbe, 0xe0, 0xb3, 0x42, 0xd0, 0xf8, 0xc3, 0xdd, 0x94, 0x16, 0xf8, 0xa5, 0x20, 0xb1, + 0x18, 0xc6, 0xc2, 0xa7, 0x93, 0xa9, 0xb8, 0x3b, 0x95, 0x8c, 0x31, 0x70, 0x5d, 0x3c, 0x83, 0x9a, 0x9c, 0x86, 0x11, + 0x30, 0x33, 0x8d, 0xad, 0x77, 0x79, 0x7a, 0x37, 0x62, 0x69, 0x7a, 0x3a, 0x9b, 0x4e, 0x73, 0x2e, 0xb0, 0x10, 0x64, + 0x2e, 0xf2, 0x1a, 0x37, 0xb0, 0x98, 0xf3, 0xe2, 0x86, 0x89, 0x28, 0xf1, 0x04, 0x9a, 0x47, 0x61, 0x41, 0x9d, 0x67, + 0x79, 0x9e, 0xd2, 0x10, 0x66, 0x9d, 0x0d, 0x5f, 0x8a, 0x20, 0x9b, 0xa5, 0x69, 0xff, 0x8a, 0xd3, 0xf0, 0x53, 0x5f, + 0xbe, 0x7e, 0x7b, 0xf5, 0x13, 0x8d, 0x44, 0x20, 0x7f, 0x1f, 0x73, 0x1e, 0xde, 0x41, 0x45, 0x42, 0xa0, 0xda, 0x30, + 0x0b, 0xfe, 0x74, 0xfa, 0xf6, 0x8d, 0xaf, 0x76, 0x09, 0x1b, 0xdd, 0x79, 0x59, 0xb5, 0xf3, 0xb2, 0x12, 0x8f, 0x78, + 0x3e, 0x59, 0x1a, 0x5a, 0xa1, 0x2d, 0xeb, 0x6f, 0x00, 0x81, 0x92, 0x6c, 0x4b, 0x75, 0x6d, 0x43, 0xf0, 0x46, 0x12, + 0x3d, 0xbc, 0x24, 0x66, 0xdc, 0x59, 0x9a, 0x06, 0xaa, 0xd8, 0xcb, 0xd0, 0xfd, 0xd0, 0x0a, 0x7e, 0x37, 0xa7, 0x44, + 0xc2, 0x39, 0x05, 0x11, 0x03, 0x30, 0x46, 0xa1, 0x88, 0x92, 0x39, 0x95, 0x9d, 0x95, 0x06, 0x62, 0x5a, 0x96, 0xf8, + 0x45, 0x45, 0xf0, 0x02, 0x00, 0x91, 0x9c, 0x8a, 0x88, 0xc5, 0x02, 0x26, 0x8c, 0xf0, 0x9f, 0xc8, 0x3c, 0x34, 0xf3, + 0x09, 0xb6, 0x3a, 0x18, 0x36, 0x66, 0xa0, 0xd8, 0x0b, 0x8e, 0xf2, 0xec, 0x9a, 0x72, 0x41, 0x79, 0x20, 0x04, 0xe6, + 0x74, 0x94, 0x02, 0x18, 0x5b, 0x5d, 0x9c, 0x84, 0xc5, 0x49, 0x12, 0x66, 0x63, 0x1a, 0x07, 0x2f, 0x44, 0x89, 0xa9, + 0x20, 0xee, 0x88, 0x65, 0x61, 0xca, 0x7e, 0xa1, 0xb1, 0xab, 0x05, 0xc2, 0x0b, 0x87, 0xde, 0x0a, 0x9a, 0xc5, 0x85, + 0xf3, 0xf2, 0xc3, 0xeb, 0x57, 0x7a, 0x29, 0x1b, 0x32, 0x02, 0xcd, 0x8b, 0xd9, 0x94, 0x72, 0x0f, 0x61, 0x2d, 0x23, + 0x5e, 0x30, 0xc9, 0x1f, 0x5f, 0x87, 0x53, 0x55, 0xc2, 0x8a, 0x8f, 0xd3, 0x38, 0x14, 0xf4, 0x1d, 0xcd, 0x62, 0x96, + 0x8d, 0xc9, 0x56, 0x57, 0x95, 0x27, 0xa1, 0x7e, 0x11, 0x57, 0x45, 0x17, 0xdb, 0x2f, 0x52, 0x39, 0xf3, 0xea, 0x71, + 0xe6, 0xa1, 0xb2, 0x10, 0xa1, 0x60, 0x91, 0x13, 0xc6, 0xf1, 0x37, 0x19, 0x13, 0x4c, 0x02, 0xc8, 0x61, 0x81, 0x80, + 0x4a, 0xa9, 0x92, 0x16, 0x06, 0x70, 0x0f, 0x61, 0xcf, 0xd3, 0x32, 0x20, 0x41, 0x7a, 0xc5, 0x76, 0x76, 0x6a, 0x8e, + 0x3f, 0xa4, 0x81, 0x7a, 0x49, 0xce, 0xce, 0x91, 0x3f, 0x9d, 0x15, 0xb0, 0xd4, 0x66, 0x08, 0x10, 0x30, 0xf9, 0x55, + 0x41, 0xf9, 0x35, 0x8d, 0x2b, 0xf2, 0x28, 0x3c, 0x34, 0x5f, 0x1a, 0x43, 0xef, 0x0c, 0x41, 0xce, 0xce, 0xfb, 0x36, + 0xeb, 0xa6, 0x9a, 0xd4, 0x79, 0x3e, 0xa5, 0x5c, 0x30, 0x5a, 0x54, 0xdc, 0xc4, 0x03, 0x41, 0x5a, 0x71, 0x14, 0x4e, + 0xcc, 0xfc, 0xa6, 0x1e, 0xc3, 0x14, 0x35, 0x78, 0x86, 0x91, 0xb5, 0x2f, 0xae, 0xa5, 0xd0, 0xe0, 0x98, 0x21, 0x2c, + 0x14, 0xa4, 0x1c, 0xa1, 0x12, 0x61, 0x61, 0xc0, 0x55, 0xdc, 0x48, 0x8f, 0x76, 0x07, 0xd2, 0x9a, 0xfc, 0x49, 0x4a, + 0x6b, 0xe0, 0x69, 0xa1, 0xa0, 0x3b, 0x3b, 0x1e, 0xf5, 0x2b, 0xb2, 0x20, 0x5b, 0x5d, 0xbd, 0x46, 0x16, 0xb2, 0x36, + 0x80, 0x0d, 0x03, 0x0b, 0x4c, 0x11, 0xde, 0xa2, 0x7e, 0x96, 0x1f, 0x47, 0x11, 0x2d, 0x8a, 0x9c, 0xef, 0xec, 0x6c, + 0xc9, 0xfa, 0x95, 0x42, 0x01, 0x6b, 0xf8, 0xf6, 0x26, 0xab, 0x21, 0x40, 0xb5, 0x90, 0xd5, 0xa2, 0x41, 0x80, 0xa8, + 0x92, 0x3a, 0x87, 0x3b, 0x34, 0xba, 0x47, 0xe0, 0x5e, 0x5c, 0xb8, 0xbb, 0x02, 0x6b, 0x34, 0x8c, 0xa9, 0x19, 0xfa, + 0xee, 0x39, 0x55, 0xda, 0x95, 0xd4, 0x3d, 0x56, 0x30, 0xa3, 0x76, 0x90, 0x1f, 0xd3, 0x11, 0xcb, 0xac, 0x69, 0x37, + 0x40, 0xc2, 0x02, 0x73, 0x54, 0x5a, 0x0b, 0xba, 0xb6, 0x6b, 0xa9, 0xd6, 0xa8, 0x95, 0x9b, 0x8f, 0xa5, 0x2a, 0x61, + 0x2d, 0xe3, 0x19, 0x3d, 0x2f, 0xb1, 0x44, 0xbd, 0x99, 0x4d, 0x2e, 0x01, 0x3d, 0x13, 0xe7, 0x7d, 0xfd, 0x9e, 0x70, + 0x85, 0x39, 0x4e, 0x7f, 0x9e, 0xd1, 0x42, 0x28, 0x3a, 0xf6, 0x04, 0xce, 0x31, 0x03, 0x7e, 0x9d, 0x67, 0x23, 0x36, + 0x9e, 0x71, 0xd0, 0x78, 0x60, 0x33, 0xd2, 0x6c, 0x36, 0xa1, 0xe6, 0x69, 0x1d, 0x6c, 0x6f, 0xa7, 0x20, 0x13, 0x0b, + 0xa0, 0xe9, 0xfb, 0xc9, 0x09, 0x60, 0x15, 0x68, 0xb1, 0xf8, 0x93, 0xe9, 0xa4, 0x5e, 0xca, 0x4a, 0x4b, 0x5b, 0x5a, + 0x13, 0x2a, 0x90, 0x96, 0xc9, 0x5b, 0x5d, 0x0d, 0xbe, 0x38, 0x27, 0x5b, 0x9d, 0x8a, 0x86, 0x35, 0x56, 0x15, 0x38, + 0x0a, 0x89, 0x6f, 0x55, 0x57, 0x48, 0x8a, 0xf8, 0x06, 0xb9, 0xf8, 0xc9, 0x0a, 0xa5, 0x26, 0xe4, 0x0c, 0x94, 0x0d, + 0x3f, 0x39, 0xdf, 0x44, 0x4e, 0x86, 0x1f, 0x78, 0x62, 0xf5, 0x5d, 0xcd, 0x36, 0xae, 0x9b, 0x6c, 0x63, 0x69, 0x1a, + 0xee, 0xb4, 0x6a, 0xe2, 0x56, 0x54, 0xa6, 0x37, 0x7a, 0xfd, 0x0a, 0x33, 0x09, 0x4c, 0x3d, 0x25, 0xab, 0x8b, 0x37, + 0xe1, 0x84, 0x16, 0x1e, 0x45, 0x78, 0x53, 0x05, 0x45, 0x9e, 0x50, 0xe5, 0xdc, 0x92, 0x9d, 0x1c, 0x64, 0x27, 0x43, + 0x4a, 0x35, 0x6b, 0x6e, 0x38, 0x8e, 0xe9, 0x19, 0x3f, 0xaf, 0x35, 0x3a, 0x6b, 0xf2, 0x52, 0x28, 0x17, 0xa4, 0xb1, + 0xdd, 0x54, 0x99, 0x42, 0x9a, 0xd4, 0x1c, 0x0a, 0x84, 0xb7, 0x3a, 0xcb, 0x2b, 0x69, 0x6a, 0xd5, 0x73, 0x3c, 0x3b, + 0x87, 0x75, 0x90, 0x22, 0xc3, 0x67, 0x85, 0xfc, 0xb7, 0xb1, 0xd3, 0x00, 0x6d, 0xa7, 0x40, 0x18, 0xfe, 0x28, 0x0d, + 0x85, 0xd7, 0x6d, 0x77, 0x40, 0x1d, 0xbd, 0xa6, 0x20, 0x51, 0x10, 0x5a, 0x9d, 0x0a, 0xf5, 0x67, 0x59, 0x91, 0xb0, + 0x91, 0xf0, 0x22, 0x21, 0x59, 0x0a, 0x4d, 0x0b, 0xea, 0x88, 0x86, 0x52, 0x2c, 0xd9, 0x4d, 0x04, 0xc4, 0x56, 0x69, + 0x60, 0xd4, 0x40, 0x2a, 0xd9, 0x16, 0x70, 0x87, 0x5a, 0xa1, 0xae, 0xb9, 0x8c, 0xa9, 0xcd, 0x40, 0x69, 0xec, 0x0e, + 0x55, 0x8f, 0x81, 0x66, 0x06, 0xcc, 0xd2, 0x5b, 0x59, 0x60, 0x73, 0x08, 0x5d, 0x28, 0x7c, 0x91, 0xbf, 0xca, 0x6f, + 0x28, 0x3f, 0x09, 0x01, 0xf8, 0x40, 0x35, 0x2f, 0x95, 0x20, 0x90, 0xfc, 0x5e, 0xf4, 0x0d, 0xbd, 0x5c, 0xc8, 0x89, + 0xbf, 0xe3, 0xf9, 0x84, 0x15, 0x14, 0xd4, 0x35, 0x85, 0xff, 0x0c, 0xf6, 0x99, 0xdc, 0x90, 0x20, 0x6c, 0x68, 0x45, + 0x5f, 0xc7, 0xaf, 0x9a, 0xf4, 0x75, 0xb1, 0xfd, 0x62, 0x6c, 0x18, 0x60, 0x73, 0x1b, 0x23, 0xec, 0x69, 0xa3, 0xc2, + 0x92, 0x73, 0x7e, 0x82, 0xb4, 0x88, 0x5f, 0x2c, 0x84, 0x65, 0xbb, 0x35, 0x14, 0x46, 0xaa, 0xb6, 0x0d, 0x2a, 0xc3, + 0x38, 0x06, 0xd5, 0x8e, 0xe7, 0x69, 0x6a, 0x89, 0x2a, 0xcc, 0xfa, 0x95, 0x70, 0xba, 0xd8, 0x7e, 0x71, 0x7a, 0x9f, + 0x7c, 0x82, 0xf7, 0xb6, 0x88, 0x32, 0x80, 0x66, 0x31, 0xe5, 0x60, 0x4b, 0x5a, 0xab, 0xa5, 0xa5, 0xec, 0x49, 0x9e, + 0x65, 0x34, 0x12, 0x34, 0x06, 0x53, 0x85, 0x11, 0xe1, 0x27, 0x79, 0x21, 0xaa, 0xc2, 0x1a, 0x7a, 0x66, 0x41, 0xcf, + 0xfc, 0x28, 0x4c, 0x53, 0x4f, 0x99, 0x25, 0x93, 0xfc, 0x9a, 0xae, 0x81, 0xba, 0xdf, 0x00, 0xb9, 0xea, 0x86, 0x5a, + 0xdd, 0x50, 0xbf, 0x98, 0xa6, 0x2c, 0xa2, 0x95, 0xe8, 0x3a, 0xf5, 0x59, 0x16, 0xd3, 0x5b, 0xe0, 0x23, 0x68, 0x30, + 0x18, 0x74, 0x70, 0x17, 0x95, 0x0a, 0xe1, 0xf3, 0x15, 0xc4, 0xde, 0x23, 0x34, 0x81, 0xc8, 0xc8, 0x60, 0xbe, 0x96, + 0xad, 0x21, 0x4b, 0x52, 0x32, 0x63, 0x5e, 0x29, 0xee, 0x8c, 0x70, 0x4c, 0x53, 0x2a, 0xa8, 0xe1, 0xe6, 0xa0, 0x44, + 0xab, 0xad, 0xfb, 0xbe, 0xc2, 0x5f, 0x45, 0x4e, 0x66, 0x97, 0x99, 0x35, 0x2f, 0x2a, 0x73, 0xbd, 0x5e, 0x9e, 0x1a, + 0xdb, 0x43, 0xa1, 0x96, 0x27, 0x14, 0x22, 0x8c, 0x12, 0x65, 0xa7, 0x7b, 0x2b, 0x53, 0xaa, 0xfb, 0xd0, 0x9c, 0xbd, + 0xda, 0x44, 0xcf, 0x0c, 0x98, 0xeb, 0x50, 0x70, 0xaa, 0x99, 0x02, 0x05, 0xd3, 0x4f, 0x2d, 0xdb, 0x49, 0x98, 0xa6, + 0x57, 0x61, 0xf4, 0xa9, 0x49, 0xfd, 0x35, 0x19, 0x90, 0x65, 0x6e, 0x6c, 0xbd, 0xb2, 0x58, 0x96, 0x3d, 0x6f, 0xc3, + 0xa5, 0x1b, 0x1b, 0xc5, 0xdb, 0xea, 0xd4, 0x64, 0xdf, 0x5c, 0xe8, 0x8d, 0xd4, 0x2e, 0x21, 0x62, 0x7a, 0x66, 0x1e, + 0x70, 0x81, 0xcf, 0x52, 0x9c, 0xe1, 0x07, 0x9a, 0xee, 0xc0, 0xe0, 0x28, 0x97, 0x00, 0x11, 0x68, 0x5e, 0xc6, 0xac, + 0xd8, 0x8c, 0x81, 0xdf, 0x04, 0xca, 0xe7, 0xd6, 0x08, 0x0f, 0x05, 0xb4, 0xe2, 0x71, 0x5a, 0x6b, 0xae, 0x20, 0xd3, + 0xfa, 0x84, 0x61, 0x34, 0xdf, 0x82, 0xee, 0x22, 0xe9, 0xfd, 0xad, 0x7a, 0x05, 0x5a, 0x19, 0x40, 0xc1, 0xfb, 0xb6, + 0x3a, 0xd1, 0xa0, 0x00, 0xcd, 0x53, 0x99, 0x14, 0xb9, 0x79, 0xc3, 0x82, 0xd4, 0x1a, 0xbb, 0x32, 0xc2, 0x35, 0xcb, + 0x2d, 0x88, 0xe7, 0x79, 0x1c, 0x8c, 0x38, 0xa3, 0xdb, 0xd7, 0x93, 0xe0, 0x2b, 0x93, 0xe0, 0xbe, 0x65, 0x68, 0xa1, + 0x9a, 0x96, 0xad, 0xe6, 0x81, 0x10, 0xc8, 0xae, 0x05, 0xfa, 0xaa, 0x0f, 0x0c, 0x1a, 0x55, 0xfc, 0x36, 0x25, 0x02, + 0x17, 0xda, 0xca, 0xd1, 0xa4, 0x06, 0x1c, 0xa3, 0x6e, 0x92, 0x23, 0xb5, 0x37, 0x1a, 0x26, 0x6f, 0x8e, 0x2d, 0x11, + 0x9f, 0x6a, 0xb3, 0x46, 0x23, 0x89, 0x22, 0xbd, 0x38, 0x0d, 0xad, 0xd8, 0x42, 0x0b, 0xce, 0x09, 0x57, 0x9a, 0xb0, + 0x52, 0x7c, 0x96, 0x91, 0x53, 0xf5, 0xbb, 0x45, 0x48, 0x5e, 0xe3, 0x86, 0xfb, 0x6b, 0x74, 0xab, 0x1c, 0xe1, 0xc8, + 0x28, 0xa5, 0x45, 0x3d, 0x71, 0x42, 0x5c, 0xe3, 0x93, 0x70, 0x87, 0xf3, 0x86, 0x5d, 0x18, 0x58, 0xd5, 0xca, 0x00, + 0x78, 0x6a, 0xb1, 0x0e, 0xdf, 0xeb, 0x88, 0xa6, 0xd1, 0x8f, 0x85, 0xf1, 0xa2, 0x81, 0x71, 0x0b, 0xb5, 0xb9, 0xe2, + 0x5d, 0xf9, 0x39, 0x89, 0x9a, 0x8d, 0x3d, 0x8a, 0x0b, 0xb5, 0x10, 0x2b, 0x58, 0x5c, 0x56, 0x3e, 0x25, 0x11, 0x82, + 0x19, 0xcb, 0x41, 0xbd, 0xb3, 0x25, 0x84, 0x07, 0xc0, 0xb3, 0xc5, 0x62, 0x85, 0xec, 0xd6, 0xea, 0xa0, 0xc8, 0xaf, + 0x2d, 0xc3, 0xc5, 0xe2, 0x85, 0x40, 0x9e, 0xd6, 0x7e, 0x31, 0x45, 0x43, 0xc3, 0x73, 0x8f, 0x5f, 0x41, 0x2d, 0xa9, + 0x8c, 0xd6, 0x25, 0x95, 0xd9, 0xd0, 0xa4, 0xda, 0xe6, 0x42, 0x09, 0x8b, 0x71, 0x9f, 0xac, 0xf0, 0x2f, 0x59, 0xa8, + 0x05, 0x75, 0x3d, 0xe5, 0x13, 0xdd, 0x35, 0x43, 0x08, 0x05, 0x5c, 0x5a, 0x32, 0x5b, 0xeb, 0x8c, 0xcb, 0x9d, 0x1d, + 0x6e, 0x75, 0x74, 0x51, 0x31, 0x8a, 0x9f, 0x3c, 0x10, 0xca, 0xc5, 0x5d, 0x26, 0xb5, 0x97, 0x9f, 0x8c, 0x18, 0x5a, + 0x31, 0x4d, 0x3b, 0x7d, 0xb0, 0xc9, 0xc3, 0x9b, 0x90, 0x09, 0xa7, 0xea, 0x45, 0xd9, 0xe4, 0x1e, 0x45, 0x73, 0xad, + 0x6c, 0xf8, 0x9c, 0x82, 0xfa, 0x08, 0x5c, 0xc1, 0x28, 0xd1, 0x8a, 0xf0, 0xa3, 0x84, 0x82, 0x3f, 0xd8, 0xe8, 0x11, + 0x95, 0x6d, 0xb8, 0xa5, 0xe5, 0x88, 0xee, 0x78, 0x3d, 0xec, 0xe5, 0x72, 0xf3, 0x86, 0x2d, 0x30, 0xa5, 0x7c, 0x94, + 0xf3, 0x89, 0x79, 0x57, 0x2e, 0x3d, 0x6b, 0xde, 0xc8, 0x46, 0xde, 0xda, 0xbe, 0xb5, 0x05, 0xd0, 0x5f, 0x32, 0xbc, + 0x6b, 0x93, 0xbd, 0x21, 0x4c, 0x2b, 0xf9, 0xab, 0xdc, 0x82, 0x86, 0x32, 0xb9, 0x6d, 0xe2, 0x6b, 0x9f, 0x6a, 0x5f, + 0xb9, 0x4d, 0xb6, 0xba, 0xfd, 0xca, 0xee, 0x33, 0xd4, 0xd0, 0x57, 0xee, 0x0d, 0x2d, 0x54, 0xf3, 0x59, 0x1a, 0x6b, + 0x60, 0x19, 0xc2, 0x54, 0xd3, 0xd1, 0x0d, 0x4b, 0xd3, 0xba, 0xf4, 0x4b, 0x38, 0x3b, 0xd7, 0x9c, 0x3d, 0x37, 0x9c, + 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd5, 0x5d, 0xdd, 0x3c, 0x5f, 0xd9, 0x9e, 0xb9, 0xe2, 0xe9, 0x5c, 0xda, 0xd2, 0x30, + 0xde, 0xcc, 0x40, 0x80, 0x2a, 0xdd, 0xeb, 0x93, 0xa7, 0x5d, 0x31, 0x60, 0x04, 0x2a, 0x4f, 0x26, 0xb5, 0xdd, 0x14, + 0x9f, 0x3c, 0x84, 0x79, 0x49, 0x2b, 0xca, 0x3e, 0x7e, 0x01, 0xbe, 0x3a, 0x6b, 0x3a, 0x20, 0xc6, 0x64, 0xf1, 0x17, + 0xa9, 0x51, 0x66, 0x76, 0x4c, 0xcf, 0x8e, 0x9b, 0xd9, 0x01, 0xaf, 0xaf, 0x67, 0x17, 0xdf, 0xcf, 0xed, 0xe5, 0xf4, + 0x58, 0x35, 0xbd, 0x7a, 0xbd, 0x17, 0x0b, 0x6f, 0xa9, 0x04, 0xdc, 0xf8, 0xda, 0x48, 0xe1, 0x55, 0xef, 0xc0, 0x03, + 0x6c, 0xcc, 0x40, 0x41, 0xa9, 0x26, 0x5d, 0x09, 0xb9, 0x57, 0x9f, 0x73, 0xf2, 0x48, 0x6f, 0xbd, 0x6a, 0x7f, 0x92, + 0x4f, 0xa6, 0xa0, 0x8f, 0x2d, 0x91, 0xf4, 0x98, 0xea, 0x01, 0xeb, 0xf7, 0xe5, 0x9a, 0xb2, 0x46, 0x1b, 0xb9, 0x1f, + 0x1b, 0xd4, 0x54, 0xd9, 0xcc, 0x5b, 0x9d, 0x72, 0x56, 0x15, 0x55, 0x8c, 0x63, 0x9d, 0x63, 0xe5, 0x64, 0xd9, 0x2d, + 0x63, 0x5e, 0xbc, 0xf5, 0x98, 0xe2, 0xc3, 0x0c, 0x78, 0x9d, 0xc5, 0x7e, 0x0c, 0xb9, 0xdb, 0xeb, 0x5f, 0xd6, 0xc8, + 0x99, 0x97, 0x4b, 0xe8, 0x9b, 0x97, 0xe5, 0x0b, 0x6d, 0x67, 0xe3, 0x17, 0x9b, 0x0d, 0xe2, 0xfa, 0x9d, 0xb6, 0x17, + 0xcf, 0xce, 0xf1, 0x8b, 0x55, 0xed, 0x91, 0xcc, 0x27, 0x79, 0x4c, 0x03, 0x37, 0x9f, 0xd2, 0xcc, 0x2d, 0xc1, 0xbb, + 0xaa, 0x17, 0x7f, 0x26, 0xbc, 0xf9, 0xfb, 0xa6, 0x9b, 0x35, 0x78, 0x51, 0x82, 0x0b, 0xec, 0x87, 0x55, 0x07, 0xec, + 0x77, 0x94, 0x17, 0x52, 0x17, 0xad, 0xd4, 0xda, 0x1f, 0x6a, 0xc1, 0xf4, 0x43, 0xb0, 0xb1, 0x7e, 0x6d, 0x85, 0xb8, + 0x5d, 0xff, 0xb1, 0xbf, 0xe7, 0x22, 0xe9, 0x1e, 0xfe, 0x56, 0xef, 0xf8, 0x9f, 0x8d, 0x7b, 0xf8, 0x94, 0xfc, 0xdc, + 0xf4, 0x0e, 0x4f, 0x05, 0x39, 0x1d, 0x9e, 0x1a, 0xa3, 0x39, 0x4f, 0x59, 0x74, 0xe7, 0xb9, 0x29, 0x13, 0x2d, 0x08, + 0xc1, 0xb9, 0x78, 0xae, 0x5e, 0x80, 0x5f, 0x51, 0xba, 0xb5, 0x4b, 0x63, 0xee, 0x61, 0x26, 0x88, 0xbb, 0x9d, 0x32, + 0xb1, 0xed, 0xe2, 0x3b, 0x72, 0x09, 0x3f, 0xb6, 0xe7, 0xde, 0xeb, 0x50, 0x24, 0x3e, 0x0f, 0xb3, 0x38, 0x9f, 0x78, + 0x68, 0xd7, 0x75, 0x91, 0x5f, 0x48, 0x93, 0xe3, 0x29, 0x2a, 0xb7, 0x2f, 0xf1, 0xa9, 0x20, 0xee, 0xd0, 0xdd, 0xbd, + 0xc3, 0xaf, 0x05, 0xb9, 0x3c, 0xda, 0x9e, 0x9f, 0x8a, 0x72, 0x70, 0x89, 0x8f, 0x2b, 0xcf, 0x3d, 0x7e, 0x43, 0x3c, + 0x44, 0x06, 0xc7, 0x1a, 0x9a, 0x93, 0x7c, 0xa2, 0x3c, 0xf8, 0x2e, 0xc2, 0xef, 0x65, 0x7c, 0xa5, 0x66, 0x37, 0x3a, + 0xc4, 0xb2, 0x45, 0xdc, 0x5c, 0x7a, 0x09, 0xdc, 0x9d, 0x1d, 0xab, 0xac, 0x52, 0x16, 0xf0, 0x89, 0x20, 0x0d, 0x9b, + 0x1c, 0xbf, 0x92, 0x91, 0x9a, 0x13, 0xe1, 0x65, 0xc8, 0x74, 0xe3, 0x19, 0x77, 0xb4, 0xde, 0x9b, 0xd9, 0x99, 0x72, + 0x32, 0xf8, 0x4c, 0x50, 0x1e, 0x8a, 0x9c, 0x9f, 0x23, 0x5b, 0x01, 0xc1, 0x7f, 0x26, 0x97, 0x67, 0xce, 0x7f, 0xf8, + 0xdd, 0x8f, 0xa3, 0x1f, 0xf9, 0xf9, 0x25, 0xfe, 0x48, 0xda, 0x47, 0xde, 0x30, 0xf0, 0xb6, 0x5a, 0xad, 0xc5, 0x8f, + 0xed, 0xb3, 0xbf, 0x85, 0xad, 0x5f, 0x8e, 0x5b, 0x3f, 0x9c, 0xa3, 0x85, 0xf7, 0x63, 0x7b, 0x78, 0xa6, 0x9f, 0xce, + 0xfe, 0x36, 0xf8, 0xb1, 0x38, 0xff, 0xbd, 0x2a, 0xdc, 0x46, 0xa8, 0x3d, 0xc6, 0x63, 0x41, 0xda, 0xad, 0xd6, 0xa0, + 0x3d, 0xc6, 0x13, 0x41, 0xda, 0xf0, 0xef, 0x0d, 0x79, 0x4f, 0xc7, 0x2f, 0x6e, 0xa7, 0xde, 0xe5, 0x60, 0xb1, 0x3d, + 0xff, 0x73, 0x09, 0xbd, 0x9e, 0xfd, 0xed, 0xc7, 0x1f, 0x0b, 0xf7, 0xd1, 0x80, 0xb4, 0xcf, 0x77, 0x91, 0x07, 0xa5, + 0xbf, 0x27, 0xf2, 0xaf, 0x37, 0x0c, 0xce, 0xfe, 0xa6, 0xa1, 0x70, 0x1f, 0xfd, 0x78, 0x79, 0x34, 0x20, 0xe7, 0x0b, + 0xcf, 0x5d, 0x3c, 0x42, 0x0b, 0x84, 0x16, 0xdb, 0xe8, 0x12, 0xbb, 0x63, 0x17, 0xe1, 0x91, 0x20, 0xed, 0x47, 0xed, + 0x31, 0xbe, 0x10, 0xa4, 0xed, 0xb6, 0xc7, 0xf8, 0xad, 0x20, 0xed, 0xbf, 0x79, 0xc3, 0x40, 0xb9, 0xd9, 0x16, 0xd2, + 0xc3, 0xb1, 0x80, 0x20, 0x47, 0xc8, 0x69, 0xb8, 0x10, 0x4c, 0xa4, 0x14, 0x6d, 0xb7, 0x19, 0xfe, 0x24, 0xd1, 0xe4, + 0x09, 0xf0, 0xc3, 0x80, 0x79, 0xe7, 0xcd, 0x2f, 0x60, 0xb1, 0x81, 0x66, 0xb6, 0x83, 0x0c, 0x2b, 0x57, 0x40, 0x11, + 0x08, 0x7c, 0x1d, 0xa6, 0x33, 0x5a, 0x04, 0xb4, 0x44, 0x38, 0x25, 0x9f, 0x84, 0xd7, 0x45, 0xf8, 0x1b, 0x01, 0x3f, + 0x7a, 0x08, 0x9f, 0xe8, 0x40, 0x26, 0xec, 0x64, 0x45, 0x54, 0x59, 0xae, 0x54, 0x16, 0x17, 0xe1, 0xf1, 0x9a, 0x97, + 0x22, 0x01, 0x07, 0x03, 0xc2, 0xd7, 0x8d, 0xb0, 0x27, 0xbe, 0x25, 0x86, 0x24, 0x3e, 0x70, 0x4a, 0xbf, 0x0f, 0xd3, + 0x4f, 0x94, 0x7b, 0xc7, 0xb8, 0xdb, 0x7b, 0x8a, 0xa5, 0x1f, 0x7a, 0xab, 0x8b, 0xfa, 0x55, 0xcc, 0xea, 0x9d, 0x50, + 0xa1, 0x02, 0x90, 0xb2, 0x4d, 0x77, 0x0c, 0xac, 0xf8, 0x56, 0xb6, 0xe2, 0xb3, 0xe2, 0xe1, 0x8d, 0x8b, 0x9a, 0xf1, + 0x51, 0x96, 0x5d, 0x87, 0x29, 0x8b, 0x1d, 0x41, 0x27, 0xd3, 0x34, 0x14, 0xd4, 0xd1, 0xf3, 0x75, 0x42, 0xe8, 0xc8, + 0xad, 0x74, 0x86, 0xa9, 0x65, 0x73, 0x4e, 0x4d, 0xe0, 0x09, 0xf6, 0x8a, 0x07, 0x51, 0x2a, 0xad, 0x77, 0x3c, 0xaf, + 0x83, 0x60, 0xcb, 0x71, 0xbe, 0x56, 0x17, 0x7c, 0x61, 0xe7, 0x52, 0x3e, 0x83, 0x1e, 0x0d, 0x52, 0xb4, 0x37, 0x74, + 0x8f, 0x8a, 0xeb, 0xf1, 0xc0, 0x85, 0x18, 0x4d, 0x41, 0x3e, 0x4a, 0xd7, 0x10, 0x54, 0x88, 0x48, 0xa7, 0x1f, 0x1d, + 0xd1, 0x7e, 0xb4, 0xbb, 0x6b, 0xb4, 0xe8, 0x90, 0x64, 0x67, 0x91, 0x6a, 0x9e, 0xe0, 0x18, 0xcf, 0x48, 0xab, 0x8b, + 0xa7, 0xa4, 0x23, 0x9b, 0xf4, 0xa7, 0x47, 0xa1, 0x1e, 0x66, 0x67, 0xc7, 0x2b, 0xfc, 0x34, 0x2c, 0xc4, 0x37, 0x60, + 0xef, 0x93, 0x29, 0x8e, 0x49, 0xe1, 0xd3, 0x5b, 0x1a, 0x79, 0x21, 0xc2, 0xb1, 0xe6, 0x34, 0xa8, 0x8f, 0xa6, 0xc4, + 0xaa, 0x06, 0x66, 0x04, 0xf9, 0x38, 0x8c, 0xcf, 0xba, 0xe7, 0x84, 0x10, 0x77, 0xab, 0xd5, 0x72, 0x87, 0x05, 0x19, + 0x8b, 0x00, 0x4a, 0x2c, 0x65, 0x99, 0x4c, 0xa0, 0xa8, 0x67, 0x15, 0x79, 0x6f, 0x85, 0x2f, 0x68, 0x21, 0x3c, 0x28, + 0x06, 0x0f, 0x00, 0x37, 0x84, 0xed, 0x1e, 0xb5, 0xdd, 0x5d, 0x28, 0x95, 0xc4, 0x89, 0x70, 0x41, 0x6e, 0x50, 0x10, + 0x9f, 0xed, 0x9d, 0xdb, 0x02, 0x40, 0x16, 0xc2, 0xe0, 0x37, 0xc3, 0xf8, 0xac, 0x23, 0x07, 0x1f, 0xb8, 0x43, 0xaf, + 0x20, 0x5c, 0x69, 0x68, 0x43, 0x1e, 0x7c, 0x94, 0x53, 0x45, 0x81, 0x06, 0x4e, 0x8f, 0x3b, 0x23, 0xad, 0x5e, 0xe0, + 0xcd, 0xec, 0x49, 0xb4, 0x60, 0x30, 0x8d, 0x05, 0x9c, 0x10, 0xa8, 0x8f, 0x0b, 0x02, 0x23, 0xd6, 0xcd, 0x6e, 0x02, + 0xfd, 0xfc, 0xc8, 0x7d, 0x34, 0xbc, 0x10, 0xc1, 0x48, 0xa8, 0xe1, 0x2f, 0xc4, 0x62, 0x01, 0xff, 0x8e, 0xc4, 0xb0, + 0x20, 0x37, 0xb2, 0x68, 0xac, 0x8b, 0x26, 0x50, 0xf4, 0x31, 0x00, 0x50, 0x31, 0xaf, 0xb4, 0x2c, 0xb5, 0x26, 0x13, + 0x22, 0x61, 0xdf, 0xd9, 0xc9, 0xce, 0xa2, 0xdd, 0xee, 0x39, 0x38, 0xf9, 0xb9, 0x28, 0xbe, 0x67, 0x22, 0xf1, 0xdc, + 0xf6, 0xc0, 0x45, 0x43, 0xd7, 0x81, 0xa5, 0xed, 0xe7, 0xbb, 0x44, 0x61, 0x38, 0xdc, 0x7d, 0x2d, 0x82, 0xd9, 0x80, + 0x74, 0x86, 0x1e, 0x53, 0x2c, 0x3c, 0x41, 0x38, 0xd4, 0x8c, 0xb3, 0x83, 0x67, 0x68, 0x97, 0x89, 0x5d, 0xf3, 0x3c, + 0x43, 0xbb, 0x77, 0xbb, 0x13, 0x14, 0x84, 0xbb, 0x77, 0xbb, 0xde, 0x8c, 0x10, 0xd2, 0xea, 0x55, 0xcd, 0x8c, 0xf8, + 0x8b, 0x50, 0x30, 0x31, 0xfe, 0xce, 0x33, 0xb9, 0x1d, 0xf2, 0x5d, 0x2f, 0x3b, 0xa3, 0xe7, 0x8b, 0x85, 0x7b, 0x34, + 0x1c, 0xb8, 0x68, 0xd7, 0x33, 0x84, 0xd6, 0x36, 0x94, 0x86, 0x10, 0x66, 0xe7, 0xa5, 0x8e, 0x27, 0x3d, 0x6b, 0xc4, + 0x8e, 0xe6, 0xf5, 0x66, 0xb7, 0x78, 0x00, 0x2d, 0x2b, 0x43, 0x46, 0x29, 0xac, 0x53, 0x98, 0xa6, 0x21, 0xe6, 0x9c, + 0x74, 0x70, 0x41, 0x8c, 0xfb, 0x3a, 0x22, 0xa2, 0x26, 0xf8, 0x90, 0xd4, 0xd5, 0xf1, 0x59, 0x82, 0xe3, 0x73, 0xf2, + 0x5c, 0x19, 0x24, 0x7d, 0xe3, 0x1c, 0xa7, 0x29, 0x79, 0xb6, 0x14, 0xc5, 0x4d, 0x20, 0xc0, 0x72, 0xeb, 0x47, 0x33, + 0xce, 0x69, 0x26, 0xde, 0xe4, 0xb1, 0xd6, 0xd3, 0x68, 0x0a, 0xa6, 0x12, 0x84, 0x67, 0x31, 0x28, 0x69, 0x3d, 0xb3, + 0x33, 0x66, 0x2b, 0xaf, 0xa7, 0x64, 0xa6, 0xf4, 0x27, 0x19, 0xb4, 0xed, 0x4f, 0xb5, 0x65, 0xec, 0x21, 0x3c, 0xd3, + 0xd1, 0x5c, 0xcf, 0xf7, 0xfd, 0xa9, 0x1f, 0xc1, 0x6b, 0x18, 0xa0, 0x40, 0xa5, 0xdc, 0x47, 0x1e, 0x27, 0xb7, 0x7e, + 0x46, 0x6f, 0xe5, 0xa8, 0x1e, 0xaa, 0x25, 0xb3, 0xd9, 0x5e, 0x47, 0x51, 0x5f, 0xb2, 0x1b, 0xee, 0x67, 0x79, 0x4c, + 0x01, 0x3d, 0x10, 0xbf, 0xd7, 0x45, 0x49, 0x58, 0xd8, 0x41, 0xaa, 0x1a, 0xbe, 0x33, 0xdb, 0x7f, 0x3d, 0x05, 0xa7, + 0xaf, 0xb4, 0xf4, 0xaa, 0xca, 0xca, 0x13, 0x8e, 0x10, 0x1b, 0x79, 0x53, 0x1f, 0x82, 0x7b, 0x92, 0x84, 0x18, 0xd8, + 0x72, 0x53, 0x9b, 0xa8, 0xee, 0xaa, 0x3e, 0x27, 0x24, 0x3e, 0x2b, 0x76, 0x77, 0xa5, 0x23, 0x7a, 0xa6, 0x48, 0x62, + 0x8a, 0xf0, 0xa4, 0xda, 0x5b, 0xa6, 0xde, 0x3b, 0xd2, 0x1c, 0xc9, 0x9b, 0x34, 0x1d, 0xba, 0xbb, 0x4c, 0x20, 0xe9, + 0x2b, 0x14, 0xde, 0x1d, 0xc2, 0x23, 0xd2, 0xf6, 0xce, 0xfc, 0xe1, 0x1f, 0xce, 0xd1, 0xd0, 0xf3, 0x7f, 0x8f, 0xda, + 0x8a, 0x71, 0x4c, 0x50, 0x3f, 0x54, 0x43, 0xcc, 0x65, 0x14, 0xb3, 0x8b, 0xa5, 0x2f, 0x31, 0xc8, 0x71, 0x16, 0x4e, + 0x68, 0x30, 0x82, 0x3d, 0x6e, 0xe8, 0xe6, 0x1d, 0x06, 0x3a, 0x0a, 0x46, 0x9a, 0x93, 0xf8, 0xee, 0xf0, 0x67, 0x51, + 0x3d, 0x0d, 0xdd, 0xe1, 0xd7, 0xf5, 0xd3, 0x1f, 0xdc, 0xe1, 0x77, 0x22, 0xf8, 0xae, 0xd4, 0xee, 0xee, 0xc6, 0x10, + 0x8f, 0xcd, 0x10, 0xa5, 0x5a, 0x18, 0x0b, 0x73, 0x33, 0xc4, 0x57, 0x1c, 0x1d, 0x53, 0x54, 0xb2, 0x51, 0xc5, 0x8a, + 0xb8, 0x2f, 0xc2, 0x31, 0xa0, 0xd4, 0x5a, 0x01, 0x6e, 0x47, 0xf7, 0xeb, 0x09, 0x03, 0xa1, 0x18, 0x6a, 0x05, 0x54, + 0x4e, 0x07, 0x1d, 0x34, 0x6f, 0xd4, 0x95, 0x1a, 0x53, 0x33, 0x9a, 0x5e, 0x71, 0xe9, 0x09, 0xe9, 0xf4, 0x27, 0x47, + 0xd3, 0xfe, 0x64, 0x77, 0x17, 0x71, 0x43, 0x58, 0xb3, 0xb3, 0xc9, 0x39, 0x7e, 0x03, 0x5e, 0x3d, 0x9b, 0x92, 0x70, + 0x63, 0x7a, 0x3d, 0x3d, 0xbd, 0xdd, 0xdd, 0xbc, 0x44, 0x7d, 0xab, 0xe9, 0x54, 0x35, 0x2d, 0x4b, 0x85, 0x93, 0x65, + 0x42, 0x3b, 0x44, 0xb2, 0x04, 0x52, 0xa2, 0x08, 0x21, 0xa7, 0x02, 0xad, 0xed, 0x15, 0xfa, 0x84, 0xe6, 0x72, 0xc7, + 0x02, 0xf3, 0x54, 0x32, 0xc2, 0x03, 0x2c, 0x40, 0xd3, 0xca, 0x15, 0x7c, 0x87, 0x67, 0xbb, 0x5d, 0x49, 0xe4, 0xad, + 0x6e, 0xbf, 0xd9, 0xd7, 0x93, 0xba, 0x2f, 0x3c, 0xdb, 0x25, 0x77, 0x15, 0x96, 0xca, 0x7c, 0x77, 0xb7, 0x6c, 0xc6, + 0x3b, 0xcd, 0xbe, 0x6d, 0x44, 0x20, 0x8e, 0x97, 0x53, 0x33, 0x8c, 0x7c, 0xad, 0x25, 0x2a, 0xf3, 0x59, 0x96, 0x51, + 0x0e, 0x32, 0x94, 0x08, 0xcc, 0xca, 0xb2, 0x92, 0xeb, 0x6f, 0x41, 0x88, 0x62, 0x4a, 0x32, 0xe0, 0x3b, 0xd2, 0xec, + 0xc2, 0x39, 0x2e, 0x70, 0x24, 0xb9, 0x06, 0x21, 0xe4, 0xc4, 0x24, 0xb5, 0x08, 0xc9, 0x81, 0x42, 0xc2, 0x2c, 0x89, + 0xc4, 0x09, 0xf5, 0x2f, 0xb6, 0x4f, 0xf2, 0x7b, 0x4d, 0xb2, 0x33, 0x76, 0x1e, 0xc8, 0x6a, 0xa9, 0xe6, 0x5b, 0x09, + 0x79, 0xef, 0x09, 0x54, 0x85, 0x47, 0x7c, 0xc9, 0xfe, 0x9e, 0x33, 0x4e, 0xa5, 0x06, 0xbe, 0x6d, 0xcc, 0xbe, 0xb0, + 0xa9, 0x3e, 0x86, 0xb6, 0xf3, 0x06, 0x10, 0x09, 0xf2, 0xd7, 0xcb, 0xc9, 0x4a, 0xb5, 0x8b, 0xed, 0xe3, 0xb7, 0xeb, + 0x4c, 0xe0, 0xc5, 0x42, 0x1b, 0xbf, 0x21, 0x68, 0x36, 0x38, 0xa9, 0x21, 0x0d, 0xf5, 0x8f, 0xc0, 0x0b, 0xa5, 0x82, + 0x94, 0x78, 0x19, 0x50, 0xd1, 0xc5, 0xf6, 0xf1, 0x07, 0x2f, 0x93, 0xae, 0x25, 0x84, 0xed, 0x69, 0x7b, 0x05, 0xf1, + 0x22, 0x42, 0x91, 0x9a, 0x7b, 0xc5, 0xb8, 0x0a, 0x4b, 0x7c, 0x07, 0x91, 0x7c, 0x09, 0xf6, 0xc3, 0x19, 0x3b, 0x27, + 0xa1, 0xc6, 0x00, 0x09, 0x11, 0x0e, 0x1b, 0x66, 0x19, 0x81, 0x05, 0x90, 0x63, 0x9d, 0xc2, 0x4a, 0xf8, 0x4a, 0xf1, + 0x43, 0x38, 0x94, 0xa3, 0x8a, 0x52, 0x89, 0x8e, 0x9f, 0x56, 0x72, 0xd3, 0x6a, 0x6b, 0xf4, 0x3b, 0xb0, 0x9c, 0xcc, + 0xc3, 0x1b, 0xdd, 0x75, 0x55, 0xf0, 0xdc, 0x24, 0x91, 0x5d, 0x6c, 0x1f, 0xbf, 0xd6, 0x79, 0x64, 0xd3, 0xd0, 0x70, + 0xfb, 0x15, 0x0b, 0xf3, 0xf8, 0xb5, 0x5f, 0xbf, 0x95, 0x95, 0x2f, 0xb6, 0x8f, 0x3f, 0xae, 0xab, 0x06, 0xe5, 0xe5, + 0xac, 0x36, 0xf1, 0x25, 0x7c, 0x73, 0x9a, 0x06, 0x73, 0x2d, 0x1a, 0x02, 0x56, 0x62, 0x29, 0x8e, 0x02, 0x5e, 0x56, + 0x9e, 0x91, 0xe7, 0x38, 0x27, 0x32, 0x0e, 0xd4, 0x5c, 0x35, 0xad, 0xe4, 0xb1, 0x3c, 0x3b, 0x8d, 0xf2, 0x29, 0xdd, + 0x10, 0x1c, 0x3a, 0x46, 0x3e, 0x9b, 0x40, 0x02, 0x8d, 0x04, 0x9d, 0xe1, 0xad, 0x0e, 0xea, 0x37, 0x85, 0x57, 0x2e, + 0x89, 0xb4, 0x68, 0x48, 0x16, 0x1c, 0x91, 0x0e, 0x0e, 0x49, 0x07, 0x27, 0x84, 0x9f, 0x75, 0x94, 0x78, 0xe8, 0xd7, + 0xa1, 0x5c, 0x25, 0x64, 0x22, 0x42, 0x48, 0xa2, 0x76, 0xab, 0x12, 0xbf, 0x71, 0x3f, 0x91, 0xae, 0x47, 0x29, 0xd1, + 0x63, 0x65, 0xb4, 0x7a, 0x05, 0x2e, 0x64, 0xc7, 0xa7, 0xec, 0x2a, 0x85, 0xec, 0x12, 0x98, 0x15, 0x16, 0x28, 0xa8, + 0xaa, 0x76, 0x75, 0xd5, 0xc4, 0x97, 0xeb, 0x54, 0xe0, 0xc4, 0x07, 0xc6, 0x8d, 0x13, 0x9d, 0x8c, 0x53, 0xac, 0x36, + 0x79, 0xbc, 0xb3, 0xe3, 0xa9, 0x46, 0xdf, 0x0b, 0xaf, 0x7a, 0x5f, 0x87, 0xee, 0xbe, 0x53, 0xbc, 0x22, 0x46, 0x12, + 0xfe, 0xdd, 0xdd, 0xf0, 0xbc, 0x8c, 0xb6, 0x08, 0xf1, 0x92, 0x26, 0x06, 0x0d, 0xf0, 0x52, 0xd3, 0x6b, 0x4e, 0x7f, + 0x77, 0xb7, 0x0a, 0xd3, 0x36, 0xb1, 0x75, 0x8c, 0xf3, 0xf2, 0xda, 0xab, 0xf2, 0x7f, 0x3a, 0x2b, 0x59, 0x53, 0x06, + 0x04, 0xc4, 0x6c, 0x9a, 0x65, 0x66, 0x32, 0xd6, 0x96, 0x60, 0x50, 0xef, 0x1b, 0x9d, 0xb8, 0x80, 0x65, 0x8e, 0x95, + 0xae, 0x64, 0xd8, 0x59, 0x0f, 0x05, 0xa6, 0x12, 0x84, 0xa5, 0xa0, 0xd2, 0x6e, 0xa9, 0xc9, 0xfb, 0xf5, 0x6a, 0xe6, + 0x25, 0xe6, 0x48, 0xfb, 0xb8, 0x24, 0x14, 0x12, 0x59, 0xbd, 0x0a, 0x29, 0x2f, 0xc9, 0x78, 0x33, 0xc9, 0x1f, 0x5b, + 0x24, 0xff, 0x8c, 0x50, 0x8b, 0xfc, 0x95, 0x87, 0xc3, 0xcf, 0xb5, 0x6b, 0x81, 0x9b, 0x57, 0x27, 0x53, 0x02, 0x3e, + 0xb4, 0x26, 0x46, 0xb9, 0x1d, 0x57, 0xdc, 0xc0, 0x50, 0xec, 0x1d, 0x22, 0xbd, 0x90, 0xd8, 0x04, 0x81, 0xbd, 0x3a, + 0xaa, 0x06, 0x43, 0xaf, 0x73, 0xe9, 0xd9, 0x1c, 0xf0, 0xf8, 0xe3, 0xfd, 0x01, 0xd1, 0x93, 0xe9, 0xea, 0xce, 0xb5, + 0x32, 0x40, 0x61, 0xd6, 0xd6, 0xc6, 0x6d, 0xe6, 0x83, 0xc2, 0xf8, 0x55, 0x20, 0xbb, 0xc9, 0x7c, 0x96, 0x36, 0xa1, + 0x91, 0x7f, 0x00, 0x6d, 0xb7, 0x2b, 0x6b, 0x50, 0xab, 0x5b, 0xe0, 0x47, 0x2a, 0x0f, 0x35, 0xe4, 0x1b, 0xd8, 0xc7, + 0xb1, 0xac, 0x40, 0xb3, 0x78, 0xfd, 0xeb, 0x67, 0xa5, 0x26, 0x13, 0x05, 0x1a, 0x9a, 0x03, 0xff, 0x53, 0x24, 0x0f, + 0x74, 0x23, 0xe5, 0x02, 0x20, 0x68, 0x2c, 0xf1, 0x54, 0x23, 0xcc, 0x75, 0x6b, 0xe7, 0xfb, 0xcb, 0x2d, 0x42, 0xc6, + 0xb5, 0xf3, 0xf1, 0x7d, 0x9d, 0x7d, 0x05, 0x64, 0x81, 0x02, 0x30, 0x1e, 0xab, 0x02, 0x15, 0xbf, 0x3c, 0x31, 0xd5, + 0xa5, 0x01, 0xe9, 0xd7, 0xfa, 0xb6, 0x15, 0xdb, 0x94, 0x5e, 0x39, 0xf5, 0xde, 0xa0, 0x61, 0xe9, 0xed, 0x36, 0xbc, + 0x7d, 0x25, 0x24, 0x8c, 0xf0, 0xfc, 0x41, 0xd6, 0x36, 0xfd, 0x96, 0x9f, 0x96, 0x53, 0x58, 0x96, 0x16, 0xc5, 0x67, + 0x59, 0x41, 0xb9, 0x78, 0x46, 0x47, 0x39, 0x87, 0x90, 0x45, 0x85, 0x13, 0x54, 0x6e, 0x5b, 0x6e, 0x3b, 0x39, 0x3f, + 0x2b, 0x4e, 0xb0, 0x34, 0x41, 0xf9, 0xeb, 0x93, 0x8c, 0x5a, 0x5f, 0x2c, 0xb7, 0x1a, 0xef, 0xec, 0xbc, 0xaf, 0xd1, + 0xa4, 0xa1, 0x94, 0x50, 0x58, 0x4c, 0x4b, 0xa9, 0x34, 0x3a, 0x94, 0xbb, 0xed, 0x55, 0x2e, 0x00, 0xc3, 0x30, 0x6c, + 0xde, 0xf3, 0x92, 0x88, 0x72, 0xbc, 0xcc, 0xe2, 0xb5, 0x6b, 0x82, 0xd9, 0x66, 0x0b, 0x70, 0x78, 0x30, 0xb4, 0x95, + 0xaf, 0x88, 0xd7, 0x29, 0xb1, 0x15, 0x0c, 0x27, 0x80, 0x2c, 0x0f, 0xc2, 0xbd, 0x76, 0xd8, 0x83, 0xaf, 0x33, 0x4a, + 0xde, 0x81, 0x5e, 0x99, 0x60, 0xee, 0x27, 0x90, 0x04, 0xdb, 0xd8, 0xb2, 0x08, 0x61, 0x2e, 0x0d, 0x1a, 0x2b, 0x97, + 0xe0, 0xf8, 0xe5, 0x3a, 0x8f, 0xb2, 0x21, 0x6a, 0x2a, 0xa5, 0x0e, 0xd4, 0xc8, 0x51, 0xd5, 0xc0, 0xbf, 0xf6, 0x98, + 0x56, 0xdc, 0x4c, 0xdc, 0x0c, 0x18, 0xf0, 0x4f, 0xc2, 0x53, 0xb1, 0x28, 0x90, 0x19, 0x85, 0x3f, 0xf3, 0x1a, 0x43, + 0xf7, 0x0b, 0xd9, 0x0c, 0x6b, 0xc4, 0x45, 0x36, 0x9a, 0x0a, 0x19, 0xd7, 0x3b, 0xa9, 0x79, 0xe9, 0xb5, 0xca, 0xa3, + 0x16, 0x86, 0x0b, 0xd6, 0x99, 0x24, 0xd6, 0xf4, 0xaf, 0x55, 0x6a, 0x74, 0x55, 0x09, 0xd4, 0x30, 0x7a, 0xe3, 0x3c, + 0x93, 0x6b, 0x40, 0x4b, 0xa0, 0xaf, 0xf9, 0x89, 0xb0, 0x56, 0xd4, 0xf8, 0xb0, 0xe5, 0x98, 0x96, 0xd4, 0x7f, 0x0f, + 0xb9, 0x2e, 0xcb, 0x7b, 0xfe, 0xa5, 0x94, 0x85, 0x0c, 0xf3, 0x06, 0x63, 0xcf, 0x25, 0x63, 0x47, 0xa0, 0xa7, 0x99, + 0xf4, 0xef, 0xa1, 0x4e, 0x79, 0xd1, 0xb9, 0x8b, 0x9e, 0x26, 0xb1, 0x37, 0x55, 0xb8, 0xdc, 0xfa, 0xbd, 0xb4, 0x1a, + 0x01, 0x23, 0x90, 0x06, 0x84, 0x35, 0x67, 0xcf, 0x11, 0xe6, 0xbb, 0xbb, 0x7d, 0x7e, 0x44, 0x6b, 0x17, 0x49, 0x0d, + 0x23, 0x83, 0x88, 0x2e, 0x10, 0x7c, 0x43, 0x86, 0x72, 0x84, 0xab, 0x3c, 0x74, 0x0e, 0xae, 0xf6, 0xe3, 0xf7, 0x9e, + 0xcd, 0xd5, 0xec, 0xba, 0x55, 0xd0, 0x14, 0xe6, 0xe3, 0xd5, 0xf1, 0x96, 0x77, 0xf7, 0x67, 0x78, 0x00, 0xdc, 0x5b, + 0x5d, 0x0c, 0xd9, 0x68, 0xa8, 0x2f, 0x14, 0x4b, 0xa8, 0x76, 0x5f, 0x1f, 0xd5, 0x89, 0x89, 0xf6, 0x60, 0x7d, 0x51, + 0x9b, 0xb2, 0x82, 0xf0, 0xb2, 0x2c, 0x68, 0x1d, 0xdf, 0x5f, 0xca, 0xc0, 0x94, 0xc2, 0x65, 0xd5, 0xd9, 0x7e, 0x32, + 0x25, 0x02, 0x5b, 0x84, 0xfa, 0x6e, 0x53, 0xe8, 0xa3, 0x06, 0x13, 0xf6, 0xb5, 0x16, 0x8a, 0xdf, 0xad, 0x13, 0x8a, + 0x38, 0xd7, 0x5b, 0x5e, 0x0a, 0xc4, 0xee, 0x03, 0x04, 0xa2, 0x76, 0xb2, 0x1b, 0x99, 0x08, 0xea, 0x48, 0x43, 0x26, + 0xf2, 0xa6, 0x4c, 0xcc, 0x31, 0xd3, 0xab, 0x31, 0xe8, 0x2d, 0x16, 0xec, 0xac, 0x03, 0x4e, 0x24, 0xd7, 0x85, 0x9f, + 0x5d, 0xf5, 0xd3, 0xe2, 0xc4, 0xca, 0x09, 0xec, 0xb1, 0xca, 0x64, 0x41, 0x3e, 0xa4, 0x39, 0x7b, 0x32, 0x2b, 0x4b, + 0xd2, 0xb4, 0xa6, 0x20, 0x4d, 0xe0, 0x84, 0x55, 0x51, 0x26, 0x80, 0x58, 0xca, 0x0a, 0x6d, 0x40, 0x7a, 0x6b, 0xd3, + 0xff, 0x8c, 0x79, 0xf9, 0x79, 0x4d, 0xb4, 0x21, 0x57, 0x94, 0xfa, 0xd0, 0x48, 0x38, 0xd0, 0x10, 0x68, 0xfd, 0x70, + 0x4b, 0x9a, 0xa0, 0xb5, 0x28, 0x47, 0xb6, 0x1c, 0xc2, 0x1d, 0x70, 0xa1, 0x6d, 0xbd, 0x57, 0x01, 0xde, 0x35, 0xd2, + 0x04, 0x17, 0x16, 0x5d, 0xbf, 0x24, 0xa2, 0xc1, 0x4a, 0x22, 0xa2, 0x2d, 0x25, 0x9c, 0x48, 0x32, 0x15, 0x24, 0x3f, + 0xeb, 0x9c, 0x83, 0x02, 0xda, 0x0f, 0x8f, 0xf2, 0xda, 0x04, 0x0e, 0x77, 0x77, 0x51, 0x62, 0x46, 0x8d, 0xce, 0xd8, + 0x6e, 0x78, 0x8e, 0x29, 0x0e, 0x95, 0x61, 0x72, 0xb2, 0xb3, 0xe3, 0x25, 0xf5, 0xb8, 0x67, 0xe1, 0x39, 0xc2, 0xc5, + 0x62, 0xe1, 0x49, 0xb0, 0x12, 0xb4, 0x58, 0x24, 0x36, 0x58, 0xf2, 0x35, 0x34, 0x1b, 0x0f, 0x05, 0x19, 0x4b, 0x01, + 0x38, 0x06, 0x08, 0x77, 0x89, 0x97, 0x68, 0xe7, 0x5e, 0x02, 0xce, 0xa8, 0xdd, 0xfc, 0x2c, 0xdc, 0xed, 0x9e, 0x5b, + 0x8c, 0xeb, 0x2c, 0x3c, 0x27, 0x49, 0x59, 0xec, 0xec, 0x6c, 0x71, 0x2d, 0x22, 0x7f, 0x02, 0x51, 0xf6, 0x93, 0x94, + 0x2c, 0xaa, 0x43, 0x7b, 0x35, 0x96, 0x9d, 0x01, 0x15, 0x45, 0xe9, 0x65, 0x35, 0xf5, 0x1a, 0x59, 0x10, 0x55, 0x25, + 0xac, 0x63, 0xc1, 0x43, 0xb0, 0xec, 0x2b, 0x32, 0xff, 0x59, 0x54, 0x69, 0xd6, 0xdf, 0xad, 0x4d, 0xae, 0xf6, 0x7d, + 0x3f, 0xe4, 0x63, 0x19, 0xc9, 0x30, 0xe9, 0x14, 0x92, 0xf8, 0xf7, 0x34, 0x98, 0xd6, 0xc0, 0x67, 0xd5, 0x58, 0xe7, + 0x44, 0x81, 0x6f, 0x54, 0x1b, 0x73, 0xa2, 0xe4, 0x97, 0xb5, 0x5e, 0x06, 0x05, 0xc9, 0xd7, 0xbf, 0x16, 0x92, 0x7d, + 0x0d, 0x89, 0x22, 0x8f, 0x25, 0x9c, 0x6d, 0xc0, 0xc5, 0x2f, 0x62, 0x09, 0x67, 0x9b, 0x71, 0x5b, 0x31, 0x84, 0x4d, + 0xf0, 0x59, 0xbc, 0x41, 0x01, 0x5a, 0x17, 0x58, 0x50, 0x1e, 0x2c, 0xeb, 0x5e, 0x8a, 0x95, 0x82, 0x30, 0x15, 0xc4, + 0x63, 0xcd, 0x0d, 0x50, 0x6b, 0xa3, 0x96, 0xe1, 0xcb, 0x82, 0x31, 0xb2, 0x5c, 0x02, 0xcd, 0xd4, 0x15, 0x20, 0x27, + 0xed, 0x6b, 0x87, 0x54, 0x84, 0x2d, 0xa5, 0xc4, 0xf9, 0x51, 0x38, 0x15, 0x33, 0x0e, 0xaa, 0x14, 0x37, 0xbf, 0xa1, + 0x18, 0xce, 0x82, 0xc8, 0x32, 0xf8, 0x01, 0x05, 0xd3, 0xb0, 0x28, 0xd8, 0xb5, 0x2a, 0xd3, 0xbf, 0x71, 0x41, 0x0c, + 0x29, 0x73, 0xa5, 0x13, 0xe6, 0xa8, 0x9f, 0x6b, 0x3a, 0x6d, 0xa2, 0xed, 0xc5, 0x35, 0xcd, 0xc4, 0x2b, 0x56, 0x08, + 0x9a, 0xc1, 0xf4, 0x6b, 0x8a, 0x83, 0x19, 0x71, 0x04, 0x1b, 0xb6, 0xd1, 0x2a, 0x8c, 0xe3, 0x7b, 0x9b, 0x88, 0xa6, + 0x0e, 0x94, 0x84, 0x59, 0x9c, 0xaa, 0x41, 0xec, 0x84, 0x46, 0x93, 0xc4, 0x59, 0xd5, 0xb4, 0xf3, 0x69, 0x6a, 0x65, + 0x43, 0x72, 0x77, 0x8f, 0x11, 0x23, 0x09, 0x8c, 0xf4, 0xbc, 0x57, 0x6b, 0x81, 0x80, 0xf7, 0x86, 0x45, 0xb0, 0x67, + 0x82, 0x85, 0xc5, 0x51, 0xfd, 0x26, 0x9c, 0x86, 0x6e, 0xbe, 0x5f, 0x7b, 0xb0, 0x6d, 0x9d, 0x70, 0x90, 0x74, 0xf2, + 0x78, 0xb3, 0x65, 0xf5, 0xda, 0x48, 0x0e, 0x23, 0x2d, 0xd8, 0x43, 0x19, 0x33, 0x9a, 0x1b, 0xf2, 0x42, 0x66, 0x2b, + 0x6e, 0x0b, 0xf2, 0x33, 0x9c, 0x1c, 0x7a, 0x29, 0x26, 0xe9, 0xd2, 0x01, 0x99, 0xfe, 0x76, 0xa5, 0xfd, 0x6f, 0x0b, + 0xef, 0x19, 0x7e, 0x0d, 0x61, 0xdd, 0x6f, 0xeb, 0xea, 0xab, 0xe1, 0xdc, 0x6f, 0x6b, 0x04, 0x7d, 0x1b, 0xac, 0xd4, + 0xb3, 0xc2, 0xb8, 0x3d, 0xff, 0xd0, 0xef, 0xb8, 0x46, 0x5b, 0xfa, 0x41, 0x05, 0x91, 0x54, 0xaa, 0xa5, 0xdc, 0x0f, + 0xb8, 0x4e, 0x54, 0x83, 0x84, 0xb9, 0xa6, 0x85, 0x44, 0x75, 0x8a, 0xa1, 0xd2, 0xe1, 0x37, 0x2d, 0x8f, 0x96, 0x31, + 0xb9, 0xb2, 0x33, 0xde, 0x85, 0x5c, 0x6c, 0xc3, 0x2e, 0x2b, 0x56, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0x0f, 0x1b, + 0xa2, 0x3e, 0x0b, 0x30, 0xe4, 0xea, 0x30, 0x90, 0xdd, 0x3f, 0x29, 0x8c, 0xee, 0xd6, 0xb4, 0x32, 0xde, 0x80, 0xfd, + 0x8f, 0x70, 0x64, 0x8e, 0xc8, 0x51, 0xcd, 0x81, 0x69, 0x30, 0x2f, 0x2b, 0xa7, 0x40, 0xa1, 0x94, 0xb7, 0x0c, 0xe1, + 0xa2, 0x94, 0xe1, 0xed, 0xbf, 0xe0, 0xbf, 0x6a, 0x96, 0x78, 0x51, 0x71, 0x9c, 0x17, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, + 0x2a, 0x7a, 0x0f, 0x74, 0x2c, 0x29, 0xb4, 0x34, 0x54, 0xf4, 0x3c, 0xd7, 0x13, 0xd9, 0x98, 0x97, 0x8a, 0x69, 0x95, + 0x51, 0x23, 0x87, 0x59, 0x93, 0xc8, 0x69, 0xac, 0x6c, 0x51, 0xed, 0xaa, 0xc6, 0xb8, 0x68, 0x03, 0x16, 0xeb, 0xc0, + 0xe2, 0x62, 0xe1, 0x35, 0x51, 0x4d, 0x98, 0x15, 0xc7, 0x40, 0x98, 0x59, 0x09, 0x15, 0x0d, 0xcd, 0x5a, 0xb5, 0xf1, + 0xd0, 0x72, 0x3e, 0x91, 0xd1, 0xcd, 0x1b, 0x70, 0xd8, 0x2e, 0x04, 0xd5, 0xdc, 0xf6, 0x29, 0x60, 0x35, 0xbb, 0x6a, + 0x20, 0x0b, 0x43, 0x3f, 0x54, 0xb9, 0xb2, 0x75, 0x52, 0xeb, 0x1a, 0xfc, 0xa2, 0x7b, 0xb2, 0x65, 0x35, 0xea, 0x56, + 0xdf, 0x5b, 0xb9, 0x46, 0xcf, 0xf3, 0x4d, 0xb9, 0x46, 0x0d, 0x6d, 0x77, 0xab, 0x83, 0xee, 0xcf, 0x4b, 0x55, 0x63, + 0xad, 0xaf, 0xf2, 0x2b, 0x86, 0xeb, 0x02, 0x6d, 0x2a, 0x34, 0x1b, 0xae, 0x72, 0x52, 0x96, 0x17, 0xd5, 0x69, 0x02, + 0x99, 0xba, 0x73, 0xa1, 0xe8, 0x5f, 0x5b, 0x8d, 0xf2, 0x50, 0xae, 0xf7, 0x17, 0x32, 0x4e, 0xf3, 0xab, 0x30, 0xfd, + 0x00, 0xe3, 0xd5, 0x2f, 0x5f, 0xde, 0xc5, 0x3c, 0x14, 0x54, 0x73, 0x97, 0x1a, 0x86, 0xbf, 0x58, 0x30, 0xfc, 0x45, + 0xf1, 0xe9, 0xba, 0x3d, 0x9e, 0xbf, 0xaa, 0x3a, 0x08, 0x2e, 0x4a, 0xc3, 0x32, 0xee, 0xc4, 0xfa, 0x31, 0x96, 0x59, + 0xd8, 0x5d, 0xc5, 0xc2, 0xee, 0x84, 0xb7, 0xdc, 0x95, 0xe7, 0xfd, 0x75, 0x7d, 0x2f, 0xab, 0x9c, 0xed, 0xaf, 0xf5, + 0xc6, 0xff, 0x6b, 0x70, 0x6f, 0x1b, 0x8b, 0xcb, 0xed, 0xf9, 0x7b, 0x32, 0x59, 0x45, 0x81, 0xfc, 0x0a, 0x92, 0x0e, + 0x04, 0x19, 0x58, 0x87, 0x0e, 0x6a, 0x39, 0x65, 0xf2, 0x80, 0xbc, 0x68, 0x56, 0x88, 0x7c, 0xa2, 0xfb, 0x2c, 0xf4, + 0x49, 0x23, 0xf9, 0x12, 0x5c, 0xd1, 0x32, 0xd6, 0x1e, 0x34, 0xcf, 0x72, 0xcd, 0x3f, 0xb1, 0x2c, 0x0e, 0x38, 0xd6, + 0x52, 0xa4, 0x08, 0xf2, 0x92, 0x98, 0x6c, 0xe3, 0xd5, 0x77, 0x78, 0xc4, 0x32, 0x56, 0x24, 0x94, 0x7b, 0x05, 0x9a, + 0x6f, 0x1a, 0xac, 0x80, 0x80, 0x8c, 0x1a, 0x0c, 0xff, 0xa9, 0x3e, 0xf5, 0xe7, 0x43, 0x6f, 0xe0, 0x07, 0x9a, 0x50, + 0x91, 0xe4, 0x31, 0xa4, 0xa5, 0xf8, 0x71, 0x75, 0xa8, 0x69, 0x67, 0x67, 0xcb, 0x73, 0xa5, 0x5b, 0x02, 0x0e, 0x80, + 0xdb, 0x6f, 0xd0, 0x70, 0x0e, 0xe7, 0x73, 0xea, 0xa1, 0x29, 0x9a, 0xd3, 0xe5, 0xa3, 0x2c, 0xc2, 0xff, 0x44, 0xef, + 0x70, 0x86, 0xca, 0x32, 0x50, 0x50, 0xbb, 0x23, 0x46, 0xd3, 0xd8, 0xc5, 0x9f, 0xe8, 0x5d, 0x50, 0x9d, 0x19, 0x97, + 0x47, 0x9c, 0xe5, 0x02, 0xba, 0xf9, 0x4d, 0xe6, 0xe2, 0x7a, 0x90, 0x60, 0x5e, 0xe2, 0x9c, 0xb3, 0x31, 0x10, 0xe7, + 0xb7, 0xf4, 0x2e, 0x50, 0xfd, 0x31, 0xeb, 0xbc, 0x1e, 0x9a, 0x1b, 0xd4, 0xfb, 0x56, 0xb1, 0xbd, 0x0c, 0xda, 0xa0, + 0x38, 0x93, 0x6d, 0xcf, 0x49, 0xa3, 0x5e, 0x6d, 0x1e, 0x22, 0x54, 0x3e, 0x74, 0x2a, 0xf8, 0x5b, 0x5b, 0xb4, 0x89, + 0x46, 0xe6, 0xeb, 0x52, 0x23, 0x0a, 0x0d, 0xea, 0x4c, 0x8f, 0x6d, 0x2f, 0x33, 0xbb, 0x4e, 0x1f, 0x42, 0xb0, 0x1c, + 0x61, 0xdf, 0x0a, 0xdd, 0x69, 0xf0, 0x27, 0x95, 0x10, 0x52, 0x47, 0x92, 0xbe, 0xa9, 0xdb, 0x39, 0xdb, 0x1e, 0xe0, + 0x1d, 0x12, 0x5a, 0x42, 0x79, 0x26, 0xb3, 0x34, 0xd9, 0xa2, 0x7f, 0x16, 0xc4, 0x9b, 0x9b, 0x29, 0x04, 0x99, 0x8d, + 0x45, 0x51, 0x02, 0x15, 0x6a, 0xfa, 0x52, 0x09, 0x80, 0x6c, 0xe4, 0xb1, 0x15, 0xa9, 0x99, 0x4b, 0xa9, 0xe9, 0x5b, + 0x18, 0xdf, 0x20, 0x25, 0xa9, 0x44, 0x86, 0x54, 0x22, 0xa5, 0xd0, 0xd3, 0x8b, 0xab, 0x49, 0xc8, 0x5e, 0xd0, 0xea, + 0x04, 0x9d, 0x5a, 0xf3, 0xbc, 0x01, 0x96, 0x27, 0xfb, 0x41, 0x65, 0x00, 0x53, 0xa2, 0xaa, 0x42, 0x59, 0x1d, 0xcd, + 0x36, 0xe9, 0xad, 0x9e, 0x3c, 0xeb, 0x24, 0xa7, 0x45, 0x0c, 0x4a, 0xbc, 0x08, 0xcd, 0x33, 0x2f, 0xc2, 0x39, 0xa4, + 0x23, 0x16, 0x65, 0x05, 0x3f, 0xb5, 0x57, 0xa3, 0x91, 0xac, 0xbc, 0xfe, 0x94, 0x1f, 0x28, 0xf3, 0x02, 0x52, 0x34, + 0x71, 0x66, 0x78, 0x4a, 0xe6, 0xc9, 0xe3, 0x76, 0xd6, 0xb2, 0xfd, 0x45, 0x27, 0xe8, 0x68, 0xc0, 0xfe, 0x2c, 0xbc, + 0xb9, 0x35, 0x0b, 0xfb, 0x44, 0xb7, 0x3e, 0xf5, 0xa7, 0x83, 0x7d, 0x75, 0x0e, 0xa9, 0xc7, 0xc9, 0x92, 0xc4, 0xb9, + 0x3f, 0xd5, 0xf2, 0xe7, 0x19, 0xe5, 0x77, 0xa7, 0x14, 0x52, 0x9d, 0x73, 0x38, 0xf0, 0x5b, 0x2f, 0x43, 0x9d, 0xa7, + 0x3e, 0xcc, 0xa5, 0xb2, 0x52, 0x36, 0xcf, 0x01, 0x2e, 0x9f, 0x12, 0x2c, 0x65, 0xb4, 0xd1, 0x72, 0xc4, 0xa8, 0xdd, + 0x42, 0x37, 0x9e, 0x9f, 0xa4, 0x7d, 0x06, 0xfe, 0xb5, 0x1a, 0xd3, 0x3a, 0x58, 0x80, 0x0b, 0xfb, 0x4c, 0xea, 0x19, + 0x3f, 0x5f, 0xf6, 0xca, 0x40, 0x11, 0x84, 0xef, 0xf2, 0xcd, 0x53, 0x5d, 0x97, 0x34, 0xbb, 0x79, 0xaa, 0x8d, 0xa0, + 0x9f, 0x4c, 0xf8, 0xc1, 0x7a, 0x9c, 0xea, 0x04, 0x33, 0x2b, 0x4b, 0x54, 0x02, 0x78, 0x7f, 0xec, 0x7b, 0xde, 0x1f, + 0x75, 0xca, 0xa0, 0x0f, 0xb1, 0xd8, 0xd3, 0x34, 0x37, 0x4c, 0xbc, 0x1e, 0xff, 0x8f, 0x2b, 0xe3, 0xff, 0xd1, 0x3a, + 0x75, 0x0a, 0xa6, 0xd1, 0x38, 0xa3, 0xb1, 0x61, 0x9d, 0x48, 0x11, 0xa0, 0xd4, 0xdb, 0x0a, 0x41, 0x3e, 0x5d, 0x06, + 0xa0, 0x71, 0xcd, 0x47, 0x79, 0x26, 0x5a, 0xa3, 0x70, 0xc2, 0xd2, 0xbb, 0x60, 0xc6, 0x5a, 0x93, 0x3c, 0xcb, 0x8b, + 0x69, 0x18, 0x51, 0x5c, 0xdc, 0x15, 0x82, 0x4e, 0x5a, 0x33, 0x86, 0x5f, 0xd2, 0xf4, 0x9a, 0x0a, 0x16, 0x85, 0xd8, + 0x3d, 0xe6, 0x2c, 0x4c, 0x9d, 0x37, 0x21, 0xe7, 0xf9, 0x8d, 0x8b, 0xdf, 0xe7, 0x57, 0xb9, 0xc8, 0xf1, 0xdb, 0xdb, + 0xbb, 0x31, 0xcd, 0xf0, 0xc7, 0xab, 0x59, 0x26, 0x66, 0xb8, 0x08, 0xb3, 0xa2, 0x55, 0x50, 0xce, 0x46, 0xfd, 0x28, + 0x4f, 0x73, 0xde, 0x82, 0x8c, 0xed, 0x09, 0x0d, 0x52, 0x36, 0x4e, 0x84, 0x13, 0x87, 0xfc, 0x53, 0xbf, 0xd5, 0x9a, + 0x72, 0x36, 0x09, 0xf9, 0x5d, 0x4b, 0xd6, 0x08, 0xbe, 0xea, 0xec, 0x85, 0x4f, 0x47, 0xfb, 0x7d, 0xc1, 0xc3, 0xac, + 0x60, 0xb0, 0x4c, 0x41, 0x98, 0xa6, 0xce, 0xde, 0x41, 0x67, 0x52, 0x6c, 0xa9, 0x40, 0x5e, 0x98, 0x89, 0xf2, 0x12, + 0x7f, 0x00, 0xb8, 0xfd, 0x2b, 0x91, 0xe1, 0xab, 0x99, 0x10, 0x79, 0x36, 0x8f, 0x66, 0xbc, 0xc8, 0x79, 0x30, 0xcd, + 0x59, 0x26, 0x28, 0xef, 0x5f, 0xe5, 0x3c, 0xa6, 0xbc, 0xc5, 0xc3, 0x98, 0xcd, 0x8a, 0x60, 0x7f, 0x7a, 0xdb, 0x07, + 0xcd, 0x62, 0xcc, 0xf3, 0x59, 0x16, 0xeb, 0xb1, 0x58, 0x96, 0x50, 0xce, 0x84, 0xfd, 0x42, 0x5e, 0x64, 0x12, 0xa4, + 0x2c, 0xa3, 0x21, 0x6f, 0x8d, 0xa1, 0x31, 0x98, 0x45, 0x9d, 0x98, 0x8e, 0x31, 0x1f, 0x5f, 0x85, 0x5e, 0xb7, 0xf7, + 0x04, 0x9b, 0xff, 0xfd, 0x03, 0xe4, 0x74, 0xd6, 0x17, 0x77, 0x3b, 0x9d, 0x7f, 0x42, 0xfd, 0xa5, 0x51, 0x24, 0x40, + 0x41, 0x77, 0x7a, 0xeb, 0x14, 0x39, 0x64, 0xb4, 0xad, 0x6b, 0xd9, 0x9f, 0x86, 0x31, 0xe4, 0x03, 0x07, 0xbd, 0xe9, + 0x6d, 0x09, 0xb3, 0x0b, 0x54, 0x8a, 0xa9, 0x9e, 0xa4, 0x7e, 0x9a, 0xff, 0x5a, 0x88, 0x0f, 0xd7, 0x43, 0xdc, 0x33, + 0x10, 0xd7, 0x58, 0x6f, 0xc5, 0x33, 0x2e, 0x63, 0xab, 0x41, 0xb7, 0x50, 0x80, 0x24, 0xf9, 0x35, 0xe5, 0x06, 0x0e, + 0xf9, 0xf0, 0xab, 0xc1, 0xe8, 0xad, 0x07, 0xe3, 0xf0, 0x73, 0x60, 0xf0, 0x2c, 0x9e, 0x37, 0xd7, 0xb5, 0xcb, 0xe9, + 0xa4, 0x9f, 0x50, 0xa0, 0xa7, 0xa0, 0x07, 0xbf, 0x6f, 0x58, 0x2c, 0x12, 0xf5, 0x53, 0x92, 0xf3, 0x8d, 0x7a, 0x77, + 0xd0, 0xe9, 0xa8, 0xe7, 0x82, 0xfd, 0x42, 0x83, 0xae, 0x0f, 0x15, 0xca, 0x4b, 0xfc, 0xd7, 0xea, 0x34, 0x6f, 0x93, + 0x7b, 0xe2, 0x3f, 0xda, 0xc7, 0x7c, 0xad, 0x14, 0xc5, 0xfa, 0x50, 0x34, 0xce, 0x8d, 0xac, 0x54, 0xc2, 0x07, 0xdc, + 0x76, 0x92, 0x3b, 0x12, 0x36, 0xa8, 0x8e, 0x71, 0xb2, 0xe1, 0x1f, 0x55, 0xde, 0x45, 0x00, 0x91, 0x0e, 0x2b, 0xd5, + 0xb0, 0xe8, 0xe7, 0x03, 0xd2, 0xe9, 0xe7, 0xad, 0x16, 0xf2, 0x0a, 0x92, 0x9d, 0xe5, 0x3a, 0x39, 0xcf, 0x63, 0xc3, + 0x42, 0x1a, 0xdb, 0x1c, 0x05, 0x05, 0x9c, 0x35, 0x5d, 0x2c, 0x78, 0x9d, 0x90, 0x21, 0x4f, 0x6b, 0xfc, 0x55, 0xe8, + 0x0a, 0x98, 0x5b, 0x9c, 0x3c, 0x34, 0xd7, 0xbb, 0x64, 0x86, 0x57, 0xa4, 0x79, 0x24, 0x31, 0xe7, 0x4f, 0x43, 0x91, + 0x80, 0x97, 0xa2, 0x12, 0x3f, 0x75, 0x0a, 0x93, 0xdb, 0x76, 0xd1, 0x30, 0xab, 0xf2, 0xdb, 0x20, 0x8f, 0x2f, 0x2b, + 0xa1, 0x97, 0x2b, 0x41, 0xa0, 0xc7, 0xba, 0xff, 0x8f, 0xc2, 0x92, 0xd4, 0x99, 0xcf, 0xb2, 0x28, 0x9d, 0xc5, 0xb4, + 0x90, 0x3d, 0xd4, 0xe2, 0x1c, 0xee, 0x86, 0xa8, 0x6a, 0xc9, 0x26, 0xd0, 0xbb, 0xcc, 0xe6, 0x81, 0x8a, 0x70, 0x8b, + 0x4a, 0xf5, 0xdc, 0x92, 0xcf, 0x75, 0xdb, 0x37, 0x75, 0xb2, 0x28, 0xb4, 0xf4, 0x67, 0x19, 0xfb, 0x79, 0x46, 0x2f, + 0x58, 0x6c, 0x9d, 0xdc, 0xa5, 0x59, 0x94, 0xc7, 0xf4, 0xe3, 0xfb, 0x6f, 0x20, 0xdb, 0x3d, 0xcf, 0x80, 0xc4, 0x32, + 0xe5, 0xef, 0xc2, 0x9c, 0x64, 0x7e, 0x4c, 0xaf, 0x59, 0x44, 0x87, 0x97, 0xdb, 0xf3, 0xb5, 0x15, 0xd5, 0x6b, 0x54, + 0xb6, 0x2f, 0xc1, 0x7f, 0xa7, 0xa0, 0xbc, 0xdc, 0x9e, 0x5f, 0x89, 0xb2, 0xbd, 0x3d, 0xcf, 0xfc, 0x38, 0x9f, 0x84, + 0x2c, 0x83, 0xdf, 0xbc, 0xdc, 0x9e, 0x33, 0xf8, 0x21, 0xca, 0xcb, 0xb2, 0x4e, 0x14, 0xad, 0x20, 0xb2, 0xa6, 0xa0, + 0x71, 0xd7, 0x45, 0xfe, 0x4f, 0x39, 0xcb, 0x64, 0xd1, 0x7d, 0x3d, 0x53, 0xd3, 0x2b, 0x20, 0xf9, 0x17, 0xa2, 0x0c, + 0x66, 0x63, 0x2e, 0x5f, 0x3c, 0xd4, 0x5c, 0xa6, 0x99, 0x60, 0x32, 0x2d, 0xde, 0x84, 0x73, 0x92, 0xb0, 0xb8, 0x88, + 0xd4, 0x49, 0xd4, 0xa2, 0x3e, 0x75, 0x11, 0x4a, 0xc4, 0x2a, 0x0b, 0x98, 0x72, 0x69, 0xec, 0xd3, 0xcd, 0x47, 0x25, + 0xb3, 0xfb, 0x8c, 0xbf, 0x8a, 0xaa, 0x8a, 0x7c, 0xc6, 0x23, 0x88, 0xf5, 0x6a, 0x95, 0x62, 0xd5, 0x2b, 0xe6, 0x4a, + 0xfd, 0xcd, 0xc5, 0xc2, 0x4a, 0xb2, 0x15, 0x70, 0xa6, 0xaf, 0xbe, 0xb6, 0x83, 0xca, 0x78, 0xa2, 0x3a, 0x0b, 0xa3, + 0xf5, 0x07, 0x33, 0x25, 0x50, 0x88, 0x62, 0x99, 0x2f, 0xea, 0xe5, 0x64, 0x90, 0xd7, 0x38, 0x27, 0x84, 0x30, 0x9f, + 0xc5, 0x32, 0x90, 0x07, 0x8a, 0x45, 0xab, 0x0b, 0x91, 0x21, 0x16, 0xd7, 0x1a, 0x1e, 0xd3, 0x78, 0x5e, 0x2c, 0xe0, + 0x6c, 0x8a, 0xac, 0xab, 0x9c, 0x2a, 0xa0, 0x83, 0x31, 0xac, 0x5e, 0x06, 0x39, 0xae, 0xba, 0x0c, 0xa0, 0x52, 0xd9, + 0x57, 0xe8, 0x53, 0xc8, 0x22, 0x06, 0x9d, 0xc7, 0x4a, 0x45, 0x28, 0x10, 0xb6, 0x5f, 0x57, 0x47, 0xf8, 0x1b, 0xf8, + 0xee, 0x2c, 0x2d, 0x8b, 0xb2, 0xa7, 0x96, 0x17, 0xcb, 0x2f, 0x72, 0x2e, 0x3c, 0x2f, 0xc2, 0x21, 0x22, 0x83, 0x48, + 0x52, 0xed, 0x51, 0x28, 0xff, 0x19, 0xb6, 0xba, 0x41, 0xb7, 0xf2, 0x84, 0x34, 0x4e, 0x56, 0xab, 0x3c, 0x33, 0x7d, + 0x3a, 0x17, 0xc0, 0xc5, 0xd5, 0x6f, 0x35, 0x9f, 0xfa, 0xb9, 0x9a, 0x16, 0xd6, 0x9c, 0x4b, 0x49, 0x7d, 0xaf, 0x01, + 0x84, 0x8c, 0xbb, 0x6d, 0x18, 0x0a, 0x95, 0xf5, 0xbc, 0xab, 0x5d, 0x7c, 0xa9, 0xb4, 0x9d, 0x0b, 0x8b, 0x8c, 0x2f, + 0x99, 0xf1, 0xd7, 0x35, 0x09, 0xac, 0xd4, 0x18, 0xb1, 0x58, 0xc0, 0xba, 0x6a, 0x0a, 0x96, 0x3b, 0x92, 0xad, 0xa5, + 0x52, 0x5f, 0x3d, 0x52, 0x45, 0x16, 0xeb, 0xab, 0xc8, 0xac, 0xc7, 0x75, 0x80, 0x81, 0x07, 0xa0, 0x10, 0x66, 0x0a, + 0xc0, 0x4c, 0x46, 0x14, 0x8e, 0x24, 0x69, 0xd6, 0x82, 0xe7, 0x4a, 0x8d, 0x0f, 0xdc, 0x77, 0x6f, 0x4f, 0x3f, 0xb8, + 0x18, 0xee, 0x34, 0xa3, 0xbc, 0x08, 0xe6, 0xae, 0x4e, 0x26, 0x6c, 0x41, 0x60, 0xda, 0x0d, 0xdc, 0x70, 0x0a, 0xa7, + 0xb3, 0x25, 0xf7, 0x6c, 0xdf, 0xb6, 0x6e, 0x6e, 0x6e, 0x5a, 0x70, 0x74, 0xac, 0x35, 0xe3, 0xa9, 0xe2, 0x2b, 0xb1, + 0x5b, 0x96, 0xc8, 0x17, 0x09, 0xcd, 0xaa, 0x5b, 0x8f, 0xf2, 0x94, 0xfa, 0x69, 0x3e, 0x56, 0x07, 0x5f, 0x97, 0xfd, + 0x10, 0xe9, 0xe5, 0x91, 0xbc, 0xcd, 0x6b, 0x70, 0x24, 0xd4, 0x3d, 0x6a, 0x82, 0xc3, 0xcf, 0x01, 0x44, 0xa9, 0x8e, + 0xda, 0x22, 0x91, 0x0f, 0xa7, 0xb0, 0x6d, 0xe4, 0xd3, 0xf6, 0x7c, 0x85, 0xc8, 0x86, 0xd0, 0x45, 0x32, 0x50, 0x53, + 0x2b, 0x64, 0xad, 0xcb, 0x20, 0xbd, 0xbc, 0x2c, 0x8f, 0xda, 0xd0, 0x57, 0xdb, 0xf4, 0x7b, 0x95, 0xc7, 0x77, 0xa6, + 0x7d, 0x45, 0x78, 0x70, 0xab, 0x53, 0x46, 0x06, 0xd0, 0x05, 0x8c, 0x1b, 0x0f, 0x24, 0xce, 0x34, 0xaf, 0x3c, 0xab, + 0x1f, 0xca, 0x73, 0x07, 0x38, 0x63, 0x09, 0x25, 0x40, 0x97, 0xd0, 0x79, 0x5c, 0x35, 0x90, 0xdb, 0x5a, 0x15, 0x6d, + 0x02, 0x50, 0x55, 0xac, 0xb7, 0x8b, 0xf2, 0x67, 0xd7, 0x64, 0x61, 0x20, 0x8e, 0x6d, 0xe0, 0x2f, 0x11, 0xfc, 0x2b, + 0x01, 0x3f, 0x6a, 0x2b, 0x34, 0x5d, 0xda, 0xf7, 0xcb, 0xa8, 0x9b, 0x1f, 0x2a, 0x64, 0x9e, 0x15, 0x02, 0x7f, 0x10, + 0xf8, 0xd3, 0xa5, 0xac, 0x6a, 0xd4, 0x01, 0xd0, 0x53, 0x41, 0x6d, 0xea, 0x18, 0xbd, 0x2f, 0xca, 0xd3, 0x34, 0x9c, + 0x16, 0x34, 0x30, 0x3f, 0xb4, 0x66, 0x00, 0x0a, 0xc6, 0xaa, 0x2a, 0xa6, 0x13, 0x9c, 0x4e, 0x40, 0x61, 0x5b, 0xd5, + 0x13, 0xaf, 0x43, 0xee, 0xb5, 0x5a, 0x51, 0xeb, 0x6a, 0x8c, 0x4a, 0x91, 0xcc, 0x6d, 0xbd, 0xe2, 0x71, 0xa7, 0xd3, + 0x87, 0x6c, 0xd4, 0x56, 0x98, 0xb2, 0x71, 0x16, 0xa4, 0x74, 0x24, 0x4a, 0x01, 0xc7, 0x04, 0xe7, 0x46, 0x91, 0xf3, + 0x7b, 0x07, 0x9c, 0x4e, 0x1c, 0x1f, 0xfe, 0xde, 0x3f, 0x70, 0x29, 0xe2, 0x20, 0x13, 0x49, 0x4b, 0x66, 0x3d, 0xc3, + 0x99, 0x0d, 0x91, 0x34, 0x9e, 0xe7, 0xd6, 0x40, 0x11, 0x05, 0x25, 0xb7, 0x14, 0xdc, 0x11, 0x09, 0x16, 0xdc, 0xae, + 0x97, 0xa1, 0xf9, 0xca, 0x0c, 0x56, 0x75, 0xad, 0x3d, 0x54, 0x16, 0xd2, 0x34, 0x59, 0xad, 0x6c, 0x14, 0xd6, 0xe6, + 0xd3, 0x0a, 0xfa, 0x2c, 0xd5, 0xba, 0x54, 0xae, 0xfd, 0xb9, 0x6a, 0xf1, 0x10, 0x64, 0x36, 0x94, 0x7e, 0x6c, 0xb7, + 0x40, 0x25, 0xcb, 0xa6, 0x33, 0x71, 0x26, 0xc3, 0x0a, 0x1c, 0x0e, 0xa8, 0x9c, 0x63, 0xab, 0x04, 0x70, 0x70, 0x3e, + 0x57, 0xc0, 0x44, 0x61, 0x1a, 0x79, 0x00, 0x91, 0xd3, 0x72, 0x0e, 0x39, 0x9d, 0xa0, 0xfe, 0x84, 0x65, 0x2d, 0xf5, + 0xee, 0xc0, 0x52, 0x0c, 0xfd, 0x27, 0xf0, 0x54, 0xfa, 0xb2, 0x37, 0x2c, 0xb3, 0x87, 0xd7, 0xe0, 0xf2, 0xf2, 0xbc, + 0x2c, 0xfb, 0xb9, 0xf0, 0xce, 0xbe, 0xf1, 0xd0, 0x39, 0xfe, 0xc5, 0xba, 0x21, 0xc7, 0x35, 0x3b, 0xc9, 0xc5, 0x3d, + 0xb4, 0xa1, 0x8a, 0xbd, 0x17, 0x64, 0xb5, 0x5f, 0x08, 0x54, 0x7c, 0xe5, 0xb9, 0xb4, 0x98, 0xb6, 0x14, 0xcb, 0x6b, + 0x49, 0x92, 0x75, 0xa1, 0x29, 0xd2, 0xbe, 0x72, 0x4a, 0xe7, 0x92, 0x9b, 0xe9, 0x43, 0x32, 0xca, 0x9d, 0x73, 0x5e, + 0x1d, 0xaa, 0xd2, 0xcf, 0xf6, 0x31, 0x2a, 0xd4, 0x60, 0x37, 0x97, 0xc7, 0x4d, 0xd6, 0x08, 0xca, 0x45, 0x75, 0x91, + 0x60, 0x98, 0xa6, 0x30, 0xe0, 0xa5, 0xd1, 0x48, 0xec, 0x7b, 0x57, 0xce, 0xc4, 0xb9, 0x87, 0x4a, 0xbd, 0x4f, 0x9f, + 0x49, 0xa5, 0xde, 0xba, 0xbd, 0x70, 0x4b, 0x98, 0x70, 0x9d, 0x12, 0xd1, 0x0c, 0x12, 0x0e, 0x1a, 0x89, 0xe9, 0xfd, + 0x9a, 0xb5, 0x29, 0x93, 0xc0, 0x91, 0x13, 0x22, 0x2e, 0xcf, 0x62, 0xd7, 0xf9, 0x43, 0x94, 0xb2, 0xe8, 0x13, 0x71, + 0xb7, 0xe7, 0x1e, 0x5a, 0x3d, 0x77, 0x2a, 0xb9, 0x82, 0xe1, 0xf3, 0xa8, 0x19, 0xca, 0xc8, 0x7d, 0x8b, 0x85, 0xab, + 0xab, 0x89, 0xdc, 0x01, 0xe8, 0x4d, 0x47, 0x6d, 0x35, 0xce, 0xe0, 0xb2, 0xbc, 0xa8, 0xaf, 0x1c, 0xab, 0xa1, 0x00, + 0x34, 0xab, 0x72, 0x47, 0x12, 0x15, 0x71, 0x3f, 0x4b, 0x69, 0xae, 0xa3, 0x98, 0x1a, 0xc0, 0x29, 0x34, 0x7f, 0x73, + 0x9d, 0x3f, 0x54, 0x65, 0xb4, 0xf2, 0x29, 0xc9, 0xa4, 0x18, 0xe2, 0xc2, 0x58, 0xe0, 0x48, 0xf0, 0x63, 0x2a, 0x42, + 0x96, 0xaa, 0x26, 0x7d, 0xe3, 0x02, 0x59, 0x9a, 0xd1, 0x62, 0xc1, 0x9b, 0x73, 0x61, 0x4d, 0x0c, 0xca, 0x99, 0x1d, + 0xb5, 0x6b, 0xb8, 0xe5, 0xcc, 0xe4, 0x9e, 0xb4, 0x83, 0xb3, 0xf5, 0x0c, 0xd5, 0x3b, 0xe7, 0x0f, 0x91, 0x3c, 0xb6, + 0x05, 0x00, 0x16, 0x1a, 0x40, 0x48, 0x1b, 0x50, 0xc7, 0x92, 0xbc, 0x90, 0x14, 0xbe, 0x08, 0xf9, 0x98, 0x8a, 0x25, + 0xc4, 0x86, 0x2a, 0x4b, 0xb8, 0x6f, 0x52, 0x04, 0x56, 0xa0, 0x4d, 0x9a, 0xd0, 0x82, 0x12, 0x5d, 0x0e, 0x41, 0x0f, + 0x26, 0x6b, 0xd5, 0xe9, 0x08, 0x81, 0xbc, 0x95, 0x8b, 0xc3, 0xa5, 0x84, 0x29, 0xa4, 0x84, 0x51, 0x9c, 0xc0, 0x91, + 0x63, 0x49, 0x10, 0x4b, 0xd7, 0x19, 0x2a, 0xc8, 0x69, 0xac, 0x60, 0x26, 0xb9, 0x6c, 0x55, 0x94, 0x47, 0x6d, 0x55, + 0x5b, 0x89, 0x00, 0x55, 0x09, 0x90, 0x20, 0xf7, 0x69, 0x8d, 0x03, 0xc8, 0x2c, 0xb7, 0xf1, 0x10, 0xb3, 0xeb, 0x8a, + 0xd8, 0xe4, 0x01, 0xb6, 0xc1, 0x51, 0x1a, 0x5e, 0xd1, 0x74, 0xb0, 0x3d, 0xcf, 0x17, 0x8b, 0x4e, 0x79, 0xd4, 0x56, + 0x8f, 0xce, 0x91, 0xe4, 0x1b, 0xea, 0xe2, 0x51, 0xb9, 0xc4, 0x70, 0x2a, 0x14, 0xf2, 0x6d, 0x4d, 0xa2, 0x59, 0xa0, + 0x3b, 0x28, 0x5d, 0x47, 0xa6, 0xb8, 0xc8, 0x4a, 0x95, 0x1e, 0x55, 0xba, 0x0e, 0x8b, 0x57, 0xcb, 0x0a, 0x41, 0xa7, + 0x50, 0x1a, 0x2d, 0x16, 0xdd, 0xd2, 0x75, 0x26, 0x2c, 0x83, 0xa7, 0x7c, 0xb1, 0x90, 0x07, 0x2e, 0x27, 0x2c, 0xf3, + 0x3a, 0x40, 0xb6, 0xae, 0x33, 0x09, 0x6f, 0xe5, 0x84, 0xcd, 0x9b, 0xf0, 0xd6, 0xeb, 0xea, 0x57, 0x7e, 0x85, 0x1f, + 0x0e, 0x14, 0x57, 0xaf, 0x68, 0xa8, 0x57, 0x34, 0xc6, 0x33, 0x75, 0x94, 0x8c, 0x78, 0x31, 0x09, 0xd7, 0xaf, 0x68, + 0x6c, 0x56, 0x74, 0xb6, 0x61, 0x45, 0x67, 0xf7, 0xac, 0x68, 0xa2, 0x57, 0xcf, 0xa9, 0x70, 0x57, 0x2c, 0x16, 0xdd, + 0x4e, 0x8d, 0xbd, 0xa3, 0x76, 0xcc, 0xae, 0x61, 0x35, 0x40, 0x3b, 0x14, 0x6c, 0x42, 0xd7, 0x13, 0x65, 0x13, 0xc5, + 0xf4, 0x8b, 0x30, 0x59, 0x63, 0x21, 0x6f, 0x62, 0xc1, 0xa6, 0xeb, 0x2a, 0xea, 0xf9, 0x5b, 0x52, 0x36, 0x03, 0x3c, + 0x70, 0xc0, 0x43, 0x64, 0x2e, 0x22, 0xf5, 0xdc, 0x0f, 0x2e, 0x76, 0x1d, 0xd7, 0x90, 0xf5, 0x65, 0x79, 0x01, 0x32, + 0x42, 0xce, 0xef, 0x41, 0xb4, 0x08, 0xb5, 0xdd, 0xc1, 0x66, 0x9a, 0x83, 0x04, 0x85, 0x9b, 0x9c, 0xc7, 0x6e, 0xa0, + 0xaa, 0x7e, 0x11, 0xaa, 0x26, 0x2c, 0xd3, 0xe9, 0x6e, 0x1b, 0x69, 0xad, 0x7e, 0x6f, 0x53, 0x5c, 0xef, 0xe0, 0x40, + 0xd5, 0x98, 0x86, 0x42, 0x50, 0x9e, 0x69, 0xca, 0x75, 0xdd, 0x7f, 0x17, 0x54, 0xb8, 0x86, 0xaf, 0x24, 0x66, 0x01, + 0x0c, 0x01, 0x6a, 0x3d, 0x5f, 0xf3, 0x7c, 0x25, 0x9e, 0xb6, 0x6a, 0x05, 0xf7, 0x0e, 0xd9, 0xb6, 0x86, 0x2a, 0x02, + 0xd3, 0x67, 0x36, 0xa1, 0xf1, 0x85, 0x64, 0xd0, 0xc3, 0xf4, 0x52, 0x2b, 0xac, 0x4b, 0xe2, 0xae, 0x6e, 0x80, 0xdd, + 0x1f, 0x67, 0xbd, 0x27, 0xfb, 0x27, 0x2e, 0x56, 0x3c, 0x3e, 0x1f, 0x8d, 0x5c, 0x54, 0x3a, 0x0f, 0x6b, 0xd6, 0xdd, + 0xff, 0x71, 0xf6, 0xf5, 0x8b, 0xce, 0xd7, 0x55, 0xe3, 0x0c, 0x88, 0x48, 0x67, 0x58, 0x18, 0x51, 0x65, 0xc1, 0x6b, + 0x66, 0x34, 0x0a, 0xb3, 0xcd, 0xd3, 0x39, 0xb3, 0xa7, 0x53, 0x4c, 0x29, 0x8d, 0x81, 0x38, 0xf1, 0x4a, 0xe9, 0x45, + 0x4a, 0xaf, 0xa9, 0xb9, 0xfe, 0x71, 0xcd, 0x60, 0x6b, 0x5a, 0x44, 0xf9, 0x2c, 0x13, 0x3a, 0xd5, 0x44, 0xb3, 0x5a, + 0x6b, 0x4a, 0x97, 0x72, 0x0e, 0xb6, 0x09, 0x71, 0xa7, 0xe4, 0x5c, 0x53, 0x7a, 0x95, 0x97, 0xd8, 0xb5, 0x00, 0xd8, + 0x08, 0xd9, 0x70, 0x43, 0x79, 0xd0, 0xc1, 0x9d, 0x4d, 0xb0, 0xe1, 0x2e, 0x0a, 0x5c, 0xf7, 0xdc, 0xe0, 0x49, 0x7a, + 0x8b, 0x1b, 0x37, 0x76, 0x6c, 0xc4, 0xd7, 0x67, 0x31, 0x70, 0xc5, 0xa1, 0xb3, 0x8c, 0x16, 0xc5, 0x46, 0x04, 0x54, + 0x8b, 0x88, 0xdd, 0xba, 0xb6, 0xbb, 0xa1, 0x17, 0xdc, 0xc1, 0xb0, 0xc3, 0x24, 0xc0, 0x55, 0xcc, 0x5a, 0xd7, 0xa2, + 0xa3, 0x11, 0x8d, 0x2a, 0x67, 0x3b, 0x44, 0x1f, 0x47, 0x2c, 0x15, 0x10, 0x84, 0x93, 0xd1, 0x31, 0xf7, 0x4d, 0x9e, + 0x51, 0x17, 0x99, 0x7c, 0x5a, 0x0d, 0xbf, 0x96, 0xff, 0xeb, 0xe1, 0x51, 0x3d, 0x36, 0x61, 0xd1, 0xa3, 0x2c, 0x16, + 0xc6, 0x17, 0xd4, 0x28, 0x6f, 0x22, 0x32, 0x97, 0xce, 0x9e, 0x4d, 0x1b, 0xe8, 0x61, 0xdb, 0x64, 0xde, 0xfd, 0xfa, + 0xa0, 0xdb, 0x29, 0x5d, 0xec, 0x42, 0x77, 0x0f, 0xdd, 0x25, 0xb2, 0xd5, 0x1e, 0xb4, 0x9a, 0x65, 0x5f, 0xd2, 0xae, + 0xd7, 0x7d, 0xda, 0x75, 0xb1, 0xba, 0xc8, 0x01, 0x95, 0x15, 0x33, 0x88, 0xc0, 0xfd, 0xfc, 0x77, 0x4f, 0xa5, 0xd9, + 0xf9, 0xc3, 0xe0, 0x79, 0xdc, 0xed, 0xb8, 0xd8, 0x2d, 0x44, 0x3e, 0xfd, 0x82, 0x29, 0xec, 0xb9, 0xd8, 0x8d, 0xd2, + 0xbc, 0xa0, 0xf6, 0x1c, 0x94, 0x3a, 0xfb, 0xf7, 0x4f, 0x42, 0x41, 0x34, 0xe5, 0xb4, 0x28, 0x1c, 0xbb, 0x7f, 0x4d, + 0x4a, 0x9f, 0x61, 0x98, 0x6b, 0x29, 0xae, 0xa0, 0x42, 0xe2, 0x45, 0xdd, 0xb1, 0x60, 0x53, 0x95, 0x2a, 0x5b, 0x21, + 0x36, 0x29, 0x02, 0x2a, 0xc6, 0xa6, 0xb4, 0xab, 0xcf, 0x8e, 0xbc, 0x66, 0xeb, 0xa9, 0x81, 0x55, 0x54, 0x7e, 0x75, + 0x80, 0x46, 0xc9, 0x84, 0x65, 0x17, 0x6b, 0x4a, 0xc3, 0xdb, 0x35, 0xa5, 0xa0, 0xb2, 0x55, 0xd0, 0xe9, 0xfb, 0x7f, + 0x3e, 0x8f, 0xf5, 0x5a, 0xf1, 0xb1, 0x41, 0x8c, 0xa5, 0x73, 0xf3, 0x33, 0x90, 0x5a, 0xcb, 0x20, 0x7b, 0xf8, 0xf5, + 0xc3, 0x41, 0xc9, 0x97, 0x0c, 0x57, 0xf5, 0xf2, 0xf7, 0xcd, 0x10, 0x4a, 0x5b, 0x10, 0x41, 0x48, 0xbf, 0x68, 0xae, + 0xf4, 0xf6, 0xf3, 0x04, 0x67, 0x69, 0x55, 0x7f, 0xc7, 0xd2, 0xeb, 0x7b, 0x04, 0x96, 0xd7, 0x7e, 0x4d, 0xb1, 0x56, + 0x7c, 0xaa, 0xf5, 0x8f, 0x52, 0x36, 0xa9, 0x49, 0x60, 0x15, 0x4c, 0xa9, 0xf1, 0x40, 0x3a, 0x99, 0xdd, 0x89, 0x52, + 0x7d, 0x2e, 0xe0, 0x90, 0x2c, 0xdc, 0x43, 0x32, 0xe3, 0xf4, 0x22, 0xcd, 0x6f, 0x96, 0x6f, 0x56, 0xdb, 0x5c, 0x39, + 0x61, 0xe3, 0xc4, 0x3a, 0xf9, 0x46, 0x49, 0xb5, 0x08, 0xf7, 0x0e, 0x50, 0xfe, 0xeb, 0xbf, 0xf8, 0xfe, 0xbf, 0xfe, + 0xcb, 0x67, 0xab, 0x42, 0xf7, 0xe5, 0x25, 0x16, 0x75, 0xb7, 0x9b, 0x77, 0xd7, 0xfa, 0x91, 0x9a, 0x38, 0x5f, 0x5f, + 0x67, 0x65, 0x11, 0xe0, 0xfd, 0xca, 0x12, 0xac, 0x14, 0xaa, 0xdd, 0xe7, 0xfc, 0x1a, 0xc0, 0x60, 0x5e, 0x9f, 0x85, + 0x0c, 0x2a, 0xfd, 0x5d, 0xa0, 0x5d, 0xa2, 0xe0, 0x41, 0x2b, 0xf2, 0xeb, 0x31, 0xfc, 0xb9, 0x39, 0xfc, 0x9d, 0xe0, + 0x6b, 0xff, 0x44, 0x7a, 0x79, 0x59, 0xa5, 0x38, 0xda, 0x4d, 0xe1, 0x02, 0x85, 0xe1, 0x4a, 0x89, 0x56, 0x3c, 0x82, + 0x0e, 0x1a, 0xc8, 0x03, 0x9a, 0x24, 0xbd, 0x7c, 0x0d, 0xb7, 0x26, 0x1d, 0x5d, 0x71, 0xe3, 0xe0, 0xbd, 0x47, 0x38, + 0x40, 0x17, 0xcd, 0x59, 0xc9, 0x4e, 0x57, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0xe2, 0xf4, 0x52, 0x5b, 0x9b, + 0x27, 0xca, 0x0d, 0x13, 0x2c, 0x93, 0xb6, 0x76, 0xcf, 0x34, 0x90, 0x8e, 0x9d, 0x0f, 0x12, 0x5f, 0xb2, 0x32, 0xad, + 0xad, 0x7b, 0xe9, 0xea, 0x02, 0x3b, 0xa2, 0x62, 0x3f, 0xd7, 0x61, 0x7a, 0xfd, 0x30, 0xc6, 0xb7, 0x59, 0xa0, 0x2e, + 0x9c, 0xc5, 0x3f, 0x5a, 0x25, 0x58, 0xb4, 0x16, 0xeb, 0xf4, 0x81, 0x9b, 0x50, 0x50, 0x7e, 0x91, 0x40, 0x96, 0x15, + 0xff, 0x0c, 0x73, 0x82, 0x95, 0xc6, 0x54, 0xfe, 0x65, 0x44, 0xdf, 0x52, 0xfd, 0x0f, 0xe2, 0x54, 0x0c, 0x52, 0x24, + 0x61, 0x28, 0x6b, 0x11, 0xfe, 0x3f, 0xdf, 0xfa, 0x77, 0xc3, 0xb7, 0xee, 0x1f, 0xa2, 0x71, 0x00, 0xfb, 0x8b, 0x17, + 0xf2, 0xdf, 0x37, 0xbb, 0xe3, 0x92, 0xdd, 0xfd, 0x0a, 0x46, 0xc7, 0xff, 0x31, 0x8c, 0x4e, 0xda, 0xc8, 0x86, 0xd3, + 0xe9, 0x8b, 0x77, 0xec, 0xf7, 0xe1, 0x4d, 0x78, 0x57, 0xef, 0xab, 0xf4, 0xf2, 0xf8, 0x26, 0xbc, 0xab, 0x17, 0x61, + 0x33, 0xbb, 0x58, 0xee, 0x63, 0xe8, 0xbe, 0x7d, 0xe3, 0x06, 0xee, 0xdb, 0xaf, 0xbf, 0x76, 0xf1, 0x65, 0x41, 0xc5, + 0x10, 0x0a, 0xc9, 0xf6, 0x7c, 0x6b, 0xb9, 0x22, 0xb8, 0x51, 0x60, 0x8a, 0x32, 0xd4, 0x86, 0x8b, 0x06, 0x30, 0xac, + 0xb8, 0xc8, 0x33, 0x1b, 0x9a, 0x77, 0x60, 0xd9, 0x7f, 0x29, 0x38, 0xb2, 0x97, 0x15, 0x78, 0x64, 0xe9, 0x32, 0x40, + 0xb2, 0xb0, 0x01, 0x51, 0x7d, 0x1f, 0xd1, 0xfd, 0xfc, 0xbf, 0xbe, 0x73, 0x41, 0x5d, 0x25, 0x12, 0x0d, 0xd3, 0xcb, + 0x2f, 0x11, 0x1f, 0x6a, 0xb0, 0xda, 0x63, 0x67, 0xdc, 0x9d, 0x61, 0xb9, 0x3d, 0x8f, 0x76, 0x76, 0xd8, 0xd0, 0xc5, + 0xf2, 0x12, 0xa8, 0x72, 0x9d, 0x70, 0xe1, 0xf0, 0x27, 0x87, 0x3f, 0x45, 0xcd, 0xa8, 0x59, 0x36, 0xe2, 0x21, 0xa7, + 0xf1, 0x66, 0x26, 0x5d, 0x5d, 0x9e, 0xa4, 0x49, 0x43, 0x65, 0x77, 0x17, 0x17, 0x32, 0xaf, 0x69, 0xc2, 0x40, 0x1f, + 0xdd, 0xb2, 0x3f, 0x11, 0xa4, 0x6f, 0x5b, 0xab, 0xbe, 0x30, 0x60, 0x23, 0x9c, 0x12, 0x5e, 0x25, 0x52, 0xc0, 0x95, + 0x9d, 0x3a, 0xf5, 0x04, 0xbb, 0x48, 0x7a, 0xdd, 0x63, 0x32, 0x90, 0x39, 0x15, 0xdf, 0x64, 0xc2, 0x8b, 0x7d, 0xc1, + 0xd9, 0xc4, 0x43, 0xb8, 0xdb, 0x41, 0xc8, 0x38, 0x1b, 0x62, 0x32, 0xd8, 0x62, 0xc5, 0x9b, 0xf0, 0x8d, 0x17, 0xcb, + 0x5b, 0xbe, 0xe4, 0x77, 0x81, 0xe0, 0x04, 0xe6, 0xb3, 0xd9, 0x68, 0x44, 0xb9, 0x67, 0x4e, 0x17, 0xfe, 0x7e, 0x1f, + 0x0e, 0x30, 0xc3, 0xdb, 0xe7, 0xa1, 0x08, 0xbf, 0x63, 0xf4, 0xc6, 0x2b, 0x50, 0x3f, 0xaf, 0x6f, 0x7e, 0x8c, 0xf1, + 0x4c, 0x26, 0x2e, 0x14, 0x54, 0x7c, 0x93, 0x89, 0xbd, 0x9e, 0x37, 0xfb, 0xfd, 0x3e, 0x8e, 0xe1, 0x3e, 0x0d, 0x93, + 0x32, 0xae, 0x2e, 0x42, 0xf9, 0xc8, 0x32, 0x71, 0xa8, 0xce, 0x78, 0x16, 0x48, 0xbb, 0x0f, 0xab, 0x74, 0x1b, 0x27, + 0xac, 0x3a, 0x8c, 0xc9, 0x20, 0xd9, 0x25, 0xea, 0xc4, 0xa7, 0xbc, 0xc2, 0xf7, 0x24, 0x09, 0xf9, 0x09, 0x9c, 0x26, + 0x07, 0x40, 0xaf, 0x44, 0x1e, 0x7a, 0x49, 0xf5, 0x99, 0x28, 0xaf, 0xfd, 0xe3, 0x6e, 0x7b, 0x8c, 0x65, 0xc6, 0x4d, + 0x5d, 0xd4, 0x86, 0xa2, 0x0b, 0xbb, 0x88, 0xec, 0x6e, 0xb7, 0x31, 0xec, 0xc1, 0xfe, 0x5a, 0x1f, 0xad, 0x59, 0xba, + 0xd6, 0x0d, 0x0f, 0xa7, 0x55, 0xdc, 0xe0, 0x24, 0xe4, 0x9c, 0x51, 0xee, 0x78, 0x2f, 0x7f, 0x41, 0xc1, 0xbf, 0xfe, + 0xcb, 0xfa, 0xf8, 0x81, 0x0e, 0x19, 0x38, 0x90, 0xb9, 0xd2, 0x92, 0xb9, 0xde, 0xc4, 0x8d, 0x54, 0x43, 0xd7, 0x84, + 0x3b, 0xf6, 0x0e, 0x3b, 0x9d, 0x8e, 0x0e, 0x09, 0x74, 0xd5, 0x4f, 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x90, 0x91, 0x6c, + 0xe2, 0xaa, 0x00, 0xe5, 0x61, 0x67, 0x7a, 0xeb, 0x0e, 0x60, 0x3b, 0x68, 0x28, 0xde, 0xd3, 0x29, 0x0d, 0xc5, 0x17, + 0x8d, 0xcf, 0x65, 0x93, 0x6a, 0xf8, 0xae, 0x19, 0xba, 0x1e, 0x77, 0x69, 0xd0, 0x83, 0xe5, 0x41, 0x3f, 0xb0, 0x89, + 0xbc, 0x17, 0x6a, 0xd3, 0xa8, 0xd2, 0x53, 0xdd, 0x18, 0x53, 0xa8, 0x16, 0xae, 0x23, 0x31, 0x9e, 0xe4, 0x69, 0x4c, + 0x39, 0x71, 0xa9, 0x3f, 0xf6, 0x9d, 0xa7, 0x9d, 0x4e, 0x07, 0xb7, 0xf6, 0x0f, 0x3a, 0x1d, 0x7c, 0xf0, 0xb8, 0x83, + 0x5b, 0xf0, 0xc7, 0xf7, 0xfd, 0x25, 0x18, 0xee, 0x8b, 0xda, 0x76, 0x3b, 0x9c, 0x4e, 0x34, 0x80, 0xf7, 0x86, 0x15, + 0xeb, 0x3d, 0x01, 0xb7, 0x57, 0xeb, 0x7d, 0xaf, 0x24, 0x9b, 0xbe, 0x3d, 0x41, 0xe7, 0xba, 0x4a, 0x7f, 0x61, 0x51, + 0x07, 0x4d, 0xa9, 0xba, 0x55, 0xf0, 0x1b, 0x4d, 0x08, 0x81, 0x73, 0x02, 0x57, 0xa3, 0xca, 0x78, 0x29, 0x64, 0x1e, + 0xc1, 0xd7, 0xd7, 0x44, 0xc8, 0x32, 0xf8, 0x30, 0x97, 0x89, 0x9a, 0x1a, 0x46, 0x55, 0x2c, 0x65, 0xf4, 0x3e, 0x52, + 0x61, 0xe9, 0x75, 0x04, 0x71, 0xfe, 0x08, 0xe1, 0xf0, 0x21, 0x0d, 0xf4, 0x0a, 0x42, 0xfd, 0xe4, 0x21, 0xf5, 0x0d, + 0xf6, 0xcf, 0x1f, 0xc9, 0x44, 0xa8, 0xad, 0x68, 0xb1, 0xd8, 0x0a, 0x17, 0x8b, 0xad, 0xe4, 0xe1, 0x33, 0x54, 0xcb, + 0x6b, 0x8e, 0x58, 0xc0, 0xb5, 0xa2, 0x0a, 0xe8, 0x6f, 0xa0, 0x3c, 0x88, 0xb0, 0x02, 0x49, 0x3d, 0x85, 0x58, 0x0f, + 0xa8, 0x1e, 0x93, 0x72, 0x09, 0x29, 0x31, 0x89, 0x94, 0x7d, 0xbe, 0x58, 0x68, 0xe2, 0xc7, 0x33, 0x12, 0x56, 0x45, + 0x5d, 0x17, 0x4f, 0x49, 0x52, 0x3d, 0xba, 0x12, 0xe4, 0xa9, 0xe6, 0x52, 0x35, 0xc4, 0x37, 0x21, 0xcf, 0x6c, 0x80, + 0xdf, 0xe4, 0x8e, 0x1e, 0xd6, 0x99, 0xf2, 0xfc, 0x9a, 0x41, 0xc2, 0xcd, 0xd2, 0xc0, 0x13, 0x02, 0xb7, 0x8a, 0xf5, + 0xed, 0x50, 0xb8, 0xd5, 0xc1, 0x07, 0xc3, 0x67, 0xe1, 0x0a, 0xcb, 0x6a, 0x82, 0x41, 0xac, 0xe7, 0x16, 0xcc, 0xcc, + 0xb4, 0xde, 0x87, 0x37, 0xc1, 0xd4, 0x3c, 0xbc, 0x50, 0xb9, 0x3d, 0xc1, 0xa4, 0x3a, 0xb6, 0xf3, 0x8e, 0xbc, 0x81, + 0xd8, 0x8f, 0x6b, 0xf8, 0x36, 0x5c, 0xe2, 0xa9, 0x78, 0xdc, 0xfb, 0x57, 0xa7, 0x34, 0xe4, 0x51, 0xf2, 0x2e, 0xe4, + 0xe1, 0xa4, 0xe8, 0x8f, 0xcc, 0x15, 0x61, 0x86, 0x02, 0x2e, 0x46, 0x32, 0xbb, 0x2a, 0x8b, 0xee, 0x5c, 0x1c, 0x23, + 0x5c, 0xbf, 0x57, 0x10, 0x28, 0x3f, 0xb7, 0x8b, 0x67, 0xf6, 0x2b, 0x58, 0x67, 0x17, 0x4f, 0x10, 0x56, 0x49, 0x4b, + 0xef, 0x7e, 0xcb, 0x74, 0x25, 0x0c, 0xf9, 0x35, 0xc1, 0xc8, 0xaf, 0x3f, 0xa1, 0x67, 0x12, 0x98, 0x3e, 0x2c, 0x25, + 0x30, 0xad, 0x41, 0xa3, 0xc3, 0x69, 0x31, 0xcd, 0xb3, 0x82, 0xba, 0xf8, 0x03, 0xb4, 0x53, 0xf7, 0x3c, 0xdb, 0x0d, + 0x57, 0x68, 0xae, 0x6a, 0x2a, 0xdf, 0xa8, 0x76, 0x10, 0xd4, 0xf9, 0xf0, 0x97, 0x2a, 0x8e, 0x6f, 0xe2, 0x3b, 0x32, + 0xcb, 0x9d, 0xd1, 0x0d, 0x89, 0xb8, 0x9c, 0x7e, 0x36, 0x11, 0x37, 0x7d, 0x50, 0x22, 0xae, 0xbc, 0x3e, 0xe5, 0x37, + 0x4d, 0xc4, 0x65, 0xd4, 0x4a, 0xc4, 0x05, 0x39, 0xf7, 0xf5, 0x83, 0xf2, 0x39, 0x4d, 0xf6, 0x5d, 0x7e, 0x53, 0x90, + 0xae, 0x8e, 0x81, 0xa4, 0xf9, 0x18, 0x92, 0x39, 0xff, 0xf1, 0xb9, 0x99, 0x69, 0x3e, 0xb6, 0x33, 0x33, 0xe1, 0xab, + 0x27, 0x40, 0x76, 0x38, 0x27, 0x73, 0xf7, 0xc7, 0xdb, 0xee, 0xb3, 0xb3, 0x6e, 0x7f, 0xaf, 0x3b, 0x71, 0x03, 0x17, + 0x9c, 0x8e, 0xb2, 0xa0, 0xd3, 0xdf, 0xdb, 0x83, 0x82, 0x1b, 0xab, 0xa0, 0x07, 0x05, 0xcc, 0x2a, 0x38, 0x80, 0x82, + 0xc8, 0x2a, 0x78, 0x0c, 0x05, 0xb1, 0x55, 0xf0, 0x04, 0x0a, 0xae, 0xdd, 0xf2, 0x8c, 0x55, 0xd9, 0xc6, 0x4f, 0x90, + 0xbc, 0x1e, 0x71, 0x2b, 0x6f, 0x1e, 0x0d, 0x8f, 0x88, 0xa9, 0xf2, 0xa4, 0xba, 0x56, 0xa2, 0xb5, 0x6f, 0x6e, 0x41, + 0xbc, 0xfc, 0xdd, 0x25, 0xb0, 0xd6, 0x08, 0xae, 0x47, 0x80, 0x98, 0xa4, 0xaa, 0xb9, 0x67, 0x5e, 0xbb, 0x41, 0x95, + 0x92, 0xdb, 0xc1, 0x3d, 0x93, 0x94, 0x1b, 0xb8, 0x48, 0xf2, 0x25, 0xf5, 0xe2, 0x60, 0x37, 0xd6, 0xdd, 0xc2, 0x05, + 0x83, 0xf5, 0xed, 0x9e, 0x7b, 0x08, 0x4f, 0x8c, 0x02, 0x44, 0x3d, 0xf8, 0xba, 0xc3, 0x07, 0x36, 0xa1, 0x66, 0xbf, + 0x98, 0x01, 0x1c, 0x99, 0xb6, 0xdc, 0x8f, 0x6a, 0xc5, 0xe8, 0x1d, 0x1e, 0xd5, 0x17, 0xca, 0x7e, 0x20, 0xea, 0x82, + 0xbe, 0x1c, 0xab, 0x30, 0xd7, 0x14, 0x8b, 0x70, 0x1c, 0x40, 0xda, 0x26, 0x64, 0x8c, 0x04, 0x23, 0x42, 0x48, 0x67, + 0x38, 0x0b, 0xde, 0xe1, 0x9b, 0x84, 0x66, 0xc1, 0xa4, 0xec, 0x57, 0xeb, 0xaf, 0xb2, 0x46, 0x3f, 0x54, 0xb7, 0x90, + 0x4b, 0x9a, 0xa8, 0xdf, 0x2a, 0x28, 0x5b, 0x15, 0xed, 0x6c, 0xc8, 0x33, 0xb4, 0x94, 0x9d, 0x51, 0x9a, 0xdf, 0xb4, + 0x40, 0xdc, 0xaf, 0xcd, 0x3d, 0x84, 0xb9, 0x55, 0xb9, 0x87, 0xaf, 0x00, 0xd6, 0xea, 0xe9, 0x43, 0x38, 0xae, 0x7e, + 0xbf, 0xa6, 0x45, 0x11, 0x8e, 0x75, 0xcd, 0xcd, 0xb9, 0x86, 0x12, 0x44, 0x3b, 0xcf, 0xd0, 0x00, 0x01, 0x09, 0x81, + 0x80, 0x10, 0x08, 0xe8, 0xea, 0xfc, 0x40, 0x98, 0x79, 0x33, 0xb5, 0x50, 0xa2, 0xaa, 0x59, 0x24, 0xc2, 0x71, 0x5d, + 0x70, 0x34, 0xe5, 0x54, 0x27, 0x2d, 0x02, 0x16, 0xcb, 0xa3, 0x36, 0x14, 0xa8, 0xd7, 0x1b, 0x52, 0x08, 0x0d, 0x77, + 0xd9, 0x9c, 0x48, 0xe8, 0x98, 0x14, 0x42, 0xfb, 0xd8, 0x4b, 0x75, 0xe6, 0x65, 0x35, 0x71, 0xed, 0xab, 0x6e, 0x04, + 0xff, 0xe9, 0xb4, 0xb8, 0xaf, 0x46, 0xa3, 0xd1, 0xbd, 0x29, 0x85, 0x5f, 0xc5, 0x23, 0xda, 0xa3, 0x07, 0x7d, 0x38, + 0x12, 0xd1, 0xd2, 0x89, 0x68, 0xdd, 0x52, 0xe2, 0x6e, 0xfe, 0xb0, 0xca, 0x90, 0xb3, 0x26, 0x92, 0xf9, 0xc3, 0xd3, + 0x0b, 0xcb, 0x29, 0xa7, 0xf3, 0x49, 0xc8, 0xc7, 0x2c, 0x0b, 0x3a, 0xa5, 0x7f, 0xad, 0xf3, 0xf1, 0xbe, 0x3a, 0x3c, + 0x3c, 0x2c, 0xfd, 0xd8, 0x3c, 0x75, 0xe2, 0xb8, 0xf4, 0xa3, 0x79, 0x35, 0x8d, 0x4e, 0x67, 0x34, 0x2a, 0x7d, 0x66, + 0x0a, 0xf6, 0x7a, 0x51, 0xbc, 0xd7, 0x2b, 0xfd, 0x1b, 0xab, 0x46, 0xe9, 0x53, 0xfd, 0xc4, 0x69, 0xdc, 0x38, 0x57, + 0xf1, 0xa4, 0xd3, 0x29, 0x7d, 0x45, 0x68, 0x73, 0x88, 0xc9, 0xa9, 0x9f, 0x41, 0x38, 0x13, 0x79, 0x79, 0x59, 0x96, + 0xfd, 0x54, 0x78, 0x67, 0xdb, 0xfa, 0xce, 0x4a, 0xf5, 0x91, 0xc7, 0x12, 0x9d, 0xe3, 0xaf, 0xed, 0xcc, 0x39, 0x20, + 0x66, 0x99, 0x31, 0x97, 0x9a, 0xc4, 0xba, 0xc6, 0x6b, 0xa0, 0x2c, 0xf9, 0xfa, 0x6b, 0x92, 0xd6, 0x09, 0x75, 0xc0, + 0xc7, 0xa0, 0xa6, 0xba, 0x5a, 0x3d, 0xdb, 0x24, 0x3d, 0x8a, 0xcf, 0x4b, 0x8f, 0xab, 0x87, 0x08, 0x8f, 0xe2, 0x37, + 0x17, 0x1e, 0x99, 0x2d, 0x3c, 0x14, 0xeb, 0xb8, 0x11, 0xc4, 0x8d, 0x12, 0x1a, 0x7d, 0xba, 0xca, 0x6f, 0x5b, 0xb0, + 0x25, 0xb8, 0x2b, 0xc5, 0xca, 0xf5, 0xaf, 0x3d, 0x26, 0x60, 0x3a, 0xb3, 0xbe, 0x10, 0x29, 0x75, 0xfc, 0xb7, 0x19, + 0x71, 0xdf, 0x9a, 0xc0, 0x9e, 0x2a, 0x19, 0x8d, 0x88, 0xfb, 0x76, 0x34, 0x72, 0xcd, 0xcd, 0x3b, 0xa1, 0xa0, 0xb2, + 0xd6, 0x9b, 0x46, 0x89, 0xac, 0x05, 0x86, 0x7e, 0x5d, 0x66, 0x17, 0xe8, 0xbc, 0x3b, 0x3b, 0xc7, 0x4e, 0xbf, 0x89, + 0x59, 0x01, 0x5b, 0x0d, 0x3e, 0x5c, 0xd9, 0xbc, 0xf9, 0x3f, 0x6b, 0x7c, 0xa6, 0xa9, 0x02, 0x78, 0xcd, 0xb7, 0xa5, + 0x96, 0xaf, 0x9d, 0x1b, 0x53, 0xa3, 0xe2, 0x3f, 0xbb, 0xfb, 0x26, 0xf6, 0x6e, 0x04, 0x2a, 0x59, 0xf1, 0x36, 0x5b, + 0xba, 0x52, 0x42, 0xc1, 0x48, 0x88, 0x3d, 0xad, 0x52, 0xe4, 0xe3, 0x71, 0x2a, 0x4f, 0xaa, 0x34, 0x0c, 0x6e, 0xd5, + 0x7c, 0xd8, 0x98, 0x6f, 0x60, 0x37, 0xd4, 0xdf, 0xee, 0x90, 0x1f, 0x33, 0x56, 0x47, 0x91, 0xaf, 0xf5, 0x57, 0x6d, + 0x65, 0x4c, 0x70, 0xae, 0x79, 0xfc, 0x5c, 0x1d, 0x60, 0x15, 0x98, 0xc5, 0xaa, 0x39, 0x8b, 0xcb, 0x52, 0x1f, 0xfd, + 0x8f, 0x59, 0x31, 0x05, 0xed, 0x49, 0xb5, 0xa4, 0x9f, 0x63, 0xe1, 0xc5, 0x8d, 0x95, 0xdc, 0xd6, 0x58, 0xae, 0xd2, + 0xd8, 0x69, 0x2a, 0x5b, 0xe8, 0x46, 0x94, 0xae, 0x36, 0xd9, 0x0c, 0x12, 0x5d, 0x47, 0xe1, 0x53, 0xa5, 0xdd, 0x59, + 0x33, 0x84, 0xcc, 0x9f, 0x6a, 0x41, 0xcc, 0x2b, 0x53, 0x50, 0xda, 0x56, 0x96, 0x7c, 0xa3, 0xb0, 0x25, 0x53, 0xc5, + 0x8a, 0x69, 0x98, 0x19, 0x63, 0x4e, 0xf1, 0x83, 0xed, 0x79, 0xbd, 0xf2, 0xa5, 0x6b, 0xc0, 0x56, 0xc4, 0x3b, 0x38, + 0x6a, 0x43, 0x83, 0x81, 0xd3, 0x00, 0x3d, 0x5b, 0xc9, 0x30, 0xbb, 0x3f, 0xd7, 0xfb, 0xd3, 0xa5, 0x5f, 0xdc, 0x60, + 0xbf, 0xb8, 0x71, 0x7e, 0x3f, 0x6f, 0xdd, 0xd0, 0xab, 0x4f, 0x4c, 0xb4, 0x44, 0x38, 0x6d, 0x81, 0xf7, 0x54, 0x66, + 0x86, 0x68, 0xf6, 0x2c, 0x75, 0x74, 0x65, 0xfa, 0xf5, 0x67, 0x05, 0xa4, 0x84, 0x4b, 0x33, 0x2a, 0xc8, 0xf2, 0x8c, + 0xf6, 0x9b, 0x67, 0x03, 0xed, 0x0c, 0x63, 0x83, 0xad, 0xf3, 0x79, 0x0e, 0x29, 0xe4, 0xe2, 0x2e, 0xe8, 0x68, 0xb6, + 0xde, 0x31, 0xe9, 0xc3, 0x9d, 0xb5, 0xf5, 0x03, 0x8d, 0xdc, 0x5d, 0x29, 0xbd, 0xf8, 0x6a, 0x1a, 0xf5, 0xa6, 0x34, + 0xe8, 0xcf, 0x9d, 0x94, 0x83, 0x7c, 0x12, 0xf3, 0xbf, 0x75, 0xc4, 0x70, 0xb9, 0x58, 0x9e, 0x94, 0x7b, 0x08, 0x64, + 0x41, 0x38, 0x12, 0x94, 0xe3, 0x87, 0xd4, 0xbc, 0x92, 0x97, 0x5a, 0xcc, 0x41, 0xcc, 0x04, 0xdd, 0xc3, 0xe9, 0xed, + 0xc3, 0xbb, 0xbf, 0x7f, 0xfa, 0xa5, 0xc6, 0x91, 0xb9, 0xe4, 0xd5, 0x75, 0xfb, 0xb0, 0x11, 0xd2, 0xf0, 0x2e, 0x60, + 0x99, 0x94, 0x79, 0x57, 0x90, 0x14, 0xd2, 0x9f, 0xe6, 0xfa, 0xc8, 0x27, 0xa7, 0xa9, 0xfc, 0xae, 0xbb, 0x5e, 0x8a, + 0xbd, 0xc7, 0xd3, 0x5b, 0xb3, 0x1a, 0xdd, 0xa5, 0xa3, 0x9c, 0xbf, 0xe9, 0x89, 0xcd, 0xcd, 0x47, 0x44, 0x9b, 0xa7, + 0x0e, 0x0f, 0xa6, 0xb7, 0x7d, 0x25, 0x68, 0x5b, 0x5c, 0x41, 0xd5, 0x99, 0xde, 0xda, 0x67, 0x56, 0xeb, 0x8e, 0x1c, + 0x7f, 0xaf, 0x70, 0x68, 0x58, 0xd0, 0x3e, 0x7c, 0xc6, 0x8a, 0x45, 0x61, 0xaa, 0x85, 0xf9, 0x84, 0xc5, 0x71, 0x4a, + 0xfb, 0x46, 0x5e, 0x3b, 0xdd, 0xc7, 0x70, 0xe4, 0xd3, 0x5e, 0xb2, 0xe6, 0xaa, 0x58, 0xc8, 0xab, 0xf0, 0x14, 0x5e, + 0x15, 0x79, 0x0a, 0x1f, 0x91, 0x5c, 0x8b, 0x4e, 0x7d, 0x16, 0xb2, 0x53, 0x23, 0x4f, 0xfe, 0x6e, 0xce, 0xe5, 0xa0, + 0xf3, 0x4f, 0x7d, 0xb9, 0xe0, 0x9d, 0xbe, 0xc8, 0xa7, 0x41, 0x6b, 0xaf, 0x39, 0x11, 0x78, 0x55, 0x4d, 0x01, 0xaf, + 0x99, 0x16, 0x06, 0x69, 0xa5, 0xf8, 0xb4, 0xe3, 0x77, 0x75, 0x99, 0xec, 0x00, 0x8c, 0xd0, 0xaa, 0xa8, 0x6c, 0x4e, + 0xe6, 0x1f, 0xb3, 0x5b, 0x9e, 0xae, 0xdf, 0x2d, 0x4f, 0xcd, 0x6e, 0xb9, 0x9f, 0x62, 0xbf, 0x1a, 0x75, 0xe1, 0xbf, + 0x7e, 0x3d, 0xa1, 0xa0, 0xe3, 0xec, 0x4d, 0x6f, 0x1d, 0xd0, 0xd3, 0x5a, 0xbd, 0xe9, 0xad, 0x3a, 0xb1, 0x0b, 0x89, + 0x6b, 0x1d, 0x38, 0xc3, 0x8a, 0x3b, 0x0e, 0x14, 0xc2, 0xff, 0x9d, 0xc6, 0xab, 0xee, 0x3e, 0xbc, 0x83, 0x56, 0x07, + 0xab, 0xef, 0x7a, 0xf7, 0x6f, 0xda, 0x20, 0xcb, 0x85, 0x17, 0x18, 0x6e, 0x8c, 0x7c, 0x11, 0x5e, 0x5d, 0xd1, 0x38, + 0x18, 0xe5, 0xd1, 0xac, 0xf8, 0x67, 0x0d, 0xbf, 0x46, 0xe2, 0xbd, 0x5b, 0x7a, 0xa9, 0x1f, 0xd3, 0x54, 0x9d, 0x1f, + 0x36, 0x3d, 0xcc, 0xab, 0x75, 0x0a, 0x8a, 0x28, 0x4c, 0xa9, 0xd7, 0xf3, 0xf7, 0xd7, 0x6c, 0x82, 0x7f, 0x93, 0xb5, + 0x59, 0x3b, 0x99, 0xbf, 0x17, 0x19, 0xf7, 0x22, 0xe1, 0x8b, 0x70, 0x60, 0xaf, 0x61, 0xe7, 0x70, 0x3d, 0xb8, 0x67, + 0x66, 0xa4, 0x73, 0x23, 0x14, 0xb4, 0xdc, 0x89, 0xe9, 0x28, 0x9c, 0xa5, 0xe2, 0xfe, 0x5e, 0x37, 0x51, 0xc6, 0x4a, + 0xaf, 0xf7, 0x30, 0xf4, 0xba, 0xee, 0x03, 0xb9, 0xf4, 0x57, 0x4f, 0xf7, 0xe1, 0x3f, 0x75, 0xf8, 0xe5, 0xaa, 0xd6, + 0xd5, 0x95, 0xd5, 0x0b, 0xba, 0xfa, 0x75, 0x43, 0x19, 0x57, 0x22, 0x5c, 0xea, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, + 0x83, 0xaa, 0x6b, 0x2d, 0xeb, 0x8b, 0x6a, 0x7f, 0x59, 0xe7, 0x0f, 0xac, 0x1b, 0x29, 0xcd, 0xb5, 0x59, 0x57, 0x7f, + 0xd7, 0x7e, 0xa5, 0xb2, 0xc1, 0xb8, 0xac, 0x7f, 0x4d, 0xae, 0x2a, 0x13, 0x45, 0xa5, 0xa2, 0x82, 0x95, 0x72, 0xad, + 0xac, 0x94, 0x9c, 0x92, 0xcb, 0xa3, 0xe1, 0xed, 0x24, 0x75, 0xae, 0xd5, 0xe5, 0x3b, 0xc4, 0xed, 0xfa, 0x1d, 0xd7, + 0x91, 0x4e, 0x3a, 0xf8, 0x06, 0x98, 0xfb, 0xf1, 0xc3, 0xd7, 0xad, 0x43, 0x77, 0x08, 0x9a, 0xd6, 0xf5, 0x58, 0x6a, + 0x76, 0xaf, 0xc2, 0x3b, 0xca, 0x2f, 0x7a, 0xda, 0x05, 0xaf, 0xf2, 0xc5, 0x65, 0x99, 0xd3, 0x73, 0x9d, 0xdb, 0x49, + 0x9a, 0x15, 0xc4, 0x4d, 0x84, 0x98, 0x06, 0xed, 0xf6, 0xcd, 0xcd, 0x8d, 0x7f, 0xb3, 0xe7, 0xe7, 0x7c, 0xdc, 0xee, + 0x75, 0x3a, 0x1d, 0xf8, 0x9c, 0x88, 0xeb, 0x5c, 0x33, 0x7a, 0xf3, 0x2c, 0xbf, 0x25, 0x6e, 0xc7, 0xe9, 0x38, 0xdd, + 0xde, 0xa1, 0xd3, 0xed, 0xed, 0xfb, 0x8f, 0x0f, 0xdd, 0xc1, 0xef, 0x1c, 0xe7, 0x28, 0xa6, 0xa3, 0x02, 0x7e, 0x38, + 0xce, 0x91, 0x54, 0xbc, 0xd4, 0x6f, 0xc7, 0xf1, 0xa3, 0xb4, 0x68, 0x75, 0x9d, 0xb9, 0x7e, 0x74, 0x1c, 0xb8, 0xa2, + 0x28, 0x70, 0xbe, 0x1a, 0xf5, 0x46, 0xfb, 0xa3, 0xa7, 0x7d, 0x5d, 0x5c, 0xfe, 0xae, 0x51, 0x1d, 0xab, 0x7f, 0x7b, + 0x56, 0xb3, 0x42, 0xf0, 0xfc, 0x13, 0xd5, 0xae, 0x7d, 0x07, 0x44, 0xcf, 0xda, 0xa6, 0xbd, 0xd5, 0x91, 0xba, 0x87, + 0x57, 0xd1, 0xa8, 0x57, 0x57, 0x97, 0x30, 0xb6, 0x2b, 0x20, 0x8f, 0xda, 0x06, 0xf4, 0x23, 0x1b, 0x4d, 0xdd, 0xd6, + 0x3a, 0x44, 0x75, 0x5d, 0x3d, 0xc7, 0xb1, 0x99, 0xdf, 0x11, 0x9c, 0x88, 0x37, 0xba, 0xaa, 0x84, 0xc0, 0x75, 0x62, + 0xe2, 0xbe, 0xee, 0xf6, 0x0e, 0x71, 0xb7, 0xfb, 0xd8, 0x7f, 0x7c, 0x18, 0x75, 0xf0, 0xbe, 0xbf, 0xdf, 0xda, 0xf3, + 0x1f, 0xe3, 0xc3, 0xd6, 0x21, 0x3e, 0x7c, 0x79, 0x18, 0xb5, 0xf6, 0xfd, 0x7d, 0xdc, 0x69, 0x1d, 0x42, 0x61, 0xeb, + 0xb0, 0x75, 0x78, 0xdd, 0xda, 0x3f, 0x8c, 0x3a, 0xb2, 0xb4, 0xe7, 0x1f, 0x1c, 0xb4, 0xba, 0x1d, 0xff, 0xe0, 0x00, + 0x1f, 0xf8, 0x8f, 0x1f, 0xb7, 0xba, 0x7b, 0xfe, 0xe3, 0xc7, 0xaf, 0x0e, 0x0e, 0xfd, 0x3d, 0x78, 0xb7, 0xb7, 0x17, + 0xed, 0xf9, 0xdd, 0x6e, 0x0b, 0xfe, 0xe0, 0x43, 0xbf, 0xa7, 0x7e, 0x74, 0xbb, 0xfe, 0x5e, 0x17, 0x77, 0xd2, 0x83, + 0x9e, 0xff, 0xf8, 0x29, 0x96, 0x7f, 0x65, 0x35, 0x2c, 0xff, 0x40, 0x37, 0xf8, 0xa9, 0xdf, 0x7b, 0xac, 0x7e, 0xc9, + 0x0e, 0xaf, 0xf7, 0x0f, 0x7f, 0x70, 0xdb, 0x1b, 0xe7, 0xd0, 0x55, 0x73, 0x38, 0x3c, 0xf0, 0xf7, 0xf6, 0xf0, 0x7e, + 0xd7, 0x3f, 0xdc, 0x4b, 0x5a, 0xfb, 0x3d, 0xff, 0xf1, 0x93, 0xa8, 0xd5, 0xf5, 0x9f, 0x3c, 0xc1, 0x9d, 0xd6, 0x9e, + 0xdf, 0xc3, 0x5d, 0x7f, 0x7f, 0x4f, 0xfe, 0xd8, 0xf3, 0x7b, 0xd7, 0x4f, 0x9e, 0xfa, 0x8f, 0x0f, 0x92, 0xc7, 0xfe, + 0xfe, 0x77, 0xfb, 0x87, 0x7e, 0x6f, 0x2f, 0xd9, 0x7b, 0xec, 0xf7, 0x9e, 0x5c, 0x3f, 0xf6, 0xf7, 0x93, 0x56, 0xef, + 0xf1, 0xbd, 0x2d, 0xbb, 0x3d, 0x1f, 0x70, 0x24, 0x5f, 0xc3, 0x0b, 0xac, 0x5f, 0xc0, 0xff, 0x89, 0x6c, 0xfb, 0x6f, + 0xd8, 0x4d, 0xb1, 0xda, 0xf4, 0xa9, 0x7f, 0xf8, 0x24, 0x52, 0xd5, 0xa1, 0xa0, 0x65, 0x6a, 0x40, 0x93, 0xeb, 0x96, + 0x1a, 0x56, 0x76, 0xd7, 0x32, 0x1d, 0x99, 0xff, 0xf5, 0x60, 0xd7, 0x2d, 0x18, 0x58, 0x8d, 0xfb, 0xff, 0xb4, 0x9f, + 0x6a, 0xc9, 0x8f, 0xda, 0x63, 0x45, 0xfa, 0xe3, 0xc1, 0xef, 0xd4, 0xb7, 0x82, 0x7e, 0x77, 0x89, 0xc3, 0x4d, 0x8e, + 0x8f, 0xf4, 0xf3, 0x8e, 0x8f, 0x84, 0x3e, 0xc4, 0xf3, 0x91, 0xfe, 0xe6, 0x9e, 0x8f, 0x70, 0xd9, 0x6d, 0x7e, 0x2b, + 0x56, 0x1c, 0x1c, 0xcb, 0x56, 0xf1, 0x37, 0xc2, 0x3b, 0xcb, 0xe1, 0xbb, 0xd4, 0x65, 0xff, 0x56, 0x90, 0x84, 0xda, + 0x7e, 0xa0, 0x1c, 0x58, 0xec, 0xad, 0x50, 0x3c, 0x36, 0xda, 0x84, 0x90, 0xf8, 0xf3, 0x08, 0xf9, 0xfe, 0x21, 0xf8, + 0x88, 0x7f, 0x73, 0x7c, 0x44, 0x36, 0x3e, 0x1a, 0x9e, 0x7c, 0xe9, 0x69, 0x90, 0x9e, 0x82, 0x53, 0xf9, 0xec, 0xc1, + 0x95, 0x1c, 0xbb, 0x6e, 0x9b, 0x5e, 0xcb, 0xc8, 0x9d, 0x0a, 0xae, 0xbf, 0xfc, 0x92, 0xa0, 0x83, 0xba, 0x7f, 0x87, + 0xb8, 0xda, 0x2d, 0x33, 0x95, 0x52, 0x47, 0x3f, 0x54, 0x42, 0xa9, 0xe7, 0x77, 0xfc, 0x4e, 0xe5, 0xd2, 0x81, 0x3b, + 0x97, 0xc8, 0x3c, 0x17, 0x61, 0xb0, 0xd5, 0xc5, 0x69, 0x3e, 0x86, 0x9b, 0x98, 0xe4, 0xb7, 0xe9, 0xe0, 0xc4, 0x43, + 0xa4, 0x3e, 0x0b, 0x08, 0xe9, 0x13, 0xda, 0xd1, 0x13, 0xf2, 0x4f, 0x7f, 0x86, 0x20, 0xa6, 0x89, 0x49, 0x4c, 0xc0, + 0xdb, 0xf1, 0x9a, 0xc6, 0x2c, 0xf4, 0x5c, 0x6f, 0xca, 0xe9, 0x88, 0xf2, 0xa2, 0xd5, 0xb8, 0x0c, 0x48, 0xde, 0x03, + 0x84, 0x5c, 0x0d, 0xe1, 0x88, 0xc3, 0xb7, 0x96, 0xc8, 0x99, 0xf6, 0x37, 0xba, 0xda, 0x00, 0x73, 0x4b, 0x6c, 0x4a, + 0x38, 0xc8, 0xda, 0x5a, 0x69, 0x73, 0x95, 0xd6, 0xd6, 0xf5, 0x7b, 0x07, 0xc8, 0x91, 0xc5, 0xf0, 0x15, 0x9b, 0xbf, + 0x7a, 0xad, 0xbd, 0xce, 0x3f, 0x21, 0xab, 0x59, 0xd5, 0xd1, 0xb9, 0x76, 0xb7, 0x65, 0xd5, 0xb7, 0x0e, 0x97, 0xc2, + 0xae, 0xae, 0xa2, 0x88, 0xaf, 0xd4, 0xdc, 0x5d, 0xd4, 0xcf, 0x74, 0xd2, 0x9c, 0xba, 0x6f, 0x70, 0xc4, 0xc6, 0x9e, + 0x75, 0x97, 0x45, 0xa6, 0xbe, 0x92, 0x03, 0x57, 0xe1, 0x23, 0x54, 0xd6, 0x55, 0x32, 0x34, 0x97, 0xd1, 0x16, 0x96, + 0x39, 0xd9, 0x62, 0xe1, 0x65, 0xe0, 0x22, 0x27, 0x16, 0x4e, 0xe1, 0x19, 0x35, 0x90, 0x9c, 0xe1, 0x0a, 0x20, 0x89, + 0x60, 0x92, 0xa9, 0x7f, 0xeb, 0x62, 0xf3, 0x43, 0x3b, 0xbe, 0xfc, 0x34, 0xcc, 0xc6, 0x40, 0x85, 0x61, 0x36, 0x5e, + 0x71, 0xab, 0xa9, 0x80, 0xd1, 0x52, 0x69, 0xdd, 0x55, 0xed, 0x3e, 0x2b, 0x9e, 0xdd, 0x7d, 0xd0, 0xd7, 0x69, 0xbb, + 0xe0, 0x9d, 0x96, 0xf1, 0x8d, 0xfa, 0xd3, 0x3f, 0xbb, 0xe4, 0xd1, 0xd1, 0x84, 0x8a, 0x50, 0x1d, 0x56, 0x03, 0x7d, + 0x02, 0x72, 0x59, 0x1c, 0x6d, 0x8d, 0xea, 0xa0, 0x3e, 0x51, 0x17, 0x08, 0x28, 0x51, 0x8f, 0x1d, 0x7d, 0x0f, 0x5d, + 0x4b, 0x2e, 0x0d, 0xe9, 0x62, 0xe5, 0x8f, 0x89, 0x42, 0x79, 0x1c, 0x99, 0x64, 0xb9, 0x3b, 0x78, 0x54, 0xe5, 0xba, + 0x6c, 0x5a, 0x84, 0x94, 0x65, 0x9f, 0xce, 0x38, 0x4d, 0xff, 0x99, 0x3c, 0x62, 0x51, 0x9e, 0x3d, 0x3a, 0x77, 0x51, + 0x5f, 0xf8, 0x09, 0xa7, 0x23, 0xf2, 0x08, 0x64, 0x7c, 0x20, 0xad, 0x0f, 0x60, 0x84, 0xbb, 0xb7, 0x93, 0x14, 0x4b, + 0x8d, 0xe9, 0x01, 0x0a, 0x91, 0x02, 0xd7, 0xed, 0x1d, 0xb8, 0x8e, 0xb2, 0x89, 0xe5, 0xef, 0x81, 0x12, 0xa7, 0x52, + 0x09, 0x70, 0xba, 0x3d, 0xff, 0x20, 0xe9, 0xf9, 0x4f, 0xaf, 0x9f, 0xf8, 0x87, 0x49, 0xf7, 0xc9, 0x75, 0x0b, 0xfe, + 0xed, 0xf9, 0x4f, 0xd3, 0x56, 0xcf, 0x7f, 0x0a, 0xff, 0x7f, 0xb7, 0xef, 0x1f, 0x24, 0xad, 0xae, 0x7f, 0x78, 0xbd, + 0xe7, 0xef, 0xbd, 0xea, 0xf6, 0xfc, 0x3d, 0xa7, 0xeb, 0xa8, 0x76, 0xc0, 0xae, 0x15, 0x77, 0x7e, 0xb4, 0xb4, 0x21, + 0xd6, 0x04, 0xe3, 0xd4, 0x81, 0x3b, 0x17, 0xcb, 0x33, 0xd2, 0xf6, 0xfe, 0xd4, 0xce, 0xba, 0xe7, 0x21, 0x87, 0xcf, + 0xa6, 0x36, 0xf7, 0x6e, 0xe3, 0x1d, 0x6e, 0xf0, 0x8b, 0x35, 0x43, 0x4c, 0x65, 0x04, 0xdc, 0xbe, 0xc8, 0x0d, 0x6e, + 0x41, 0x93, 0x5f, 0x99, 0x32, 0x97, 0xed, 0x6f, 0x26, 0x6d, 0x55, 0xd1, 0x5c, 0xe8, 0x2f, 0x99, 0x05, 0x93, 0xdf, + 0xf3, 0x93, 0x83, 0x7c, 0x13, 0x97, 0xcb, 0xe3, 0xc3, 0xb9, 0x3f, 0x9e, 0x5b, 0x77, 0xd9, 0xd1, 0x3a, 0xc8, 0x1f, + 0x33, 0xb8, 0x7d, 0xb0, 0x2c, 0x0d, 0xe8, 0x0d, 0x37, 0x6d, 0x8d, 0x25, 0xc9, 0x2f, 0x68, 0x31, 0x74, 0xa1, 0xc8, + 0x0d, 0x5c, 0xe9, 0xe2, 0x73, 0xab, 0x4f, 0xc7, 0x56, 0x84, 0x5d, 0x17, 0x60, 0x79, 0xe3, 0x04, 0xec, 0x5a, 0xc0, + 0x8f, 0x8b, 0x76, 0x76, 0x36, 0xee, 0x17, 0xa9, 0x40, 0xc2, 0x5c, 0xeb, 0x2f, 0x4e, 0xda, 0xac, 0xc8, 0xb5, 0x11, + 0x5d, 0xf5, 0x2b, 0x51, 0x88, 0x34, 0x9e, 0xae, 0x68, 0x28, 0xfc, 0x30, 0x53, 0x27, 0x08, 0x2c, 0x86, 0x85, 0xbb, + 0x74, 0x0f, 0x95, 0xb9, 0x08, 0x55, 0x52, 0x98, 0xbd, 0xcf, 0x73, 0x11, 0x9a, 0x9b, 0x99, 0x42, 0xd1, 0x38, 0x38, + 0x9f, 0xf4, 0x06, 0x6f, 0x3f, 0x1c, 0x3b, 0x6a, 0x7b, 0x1e, 0xb5, 0x93, 0xde, 0xe0, 0x48, 0xfa, 0x4c, 0x54, 0xd8, + 0x9f, 0xa8, 0xb0, 0xbf, 0xa3, 0x2f, 0xa6, 0x81, 0x48, 0x5a, 0xd9, 0x56, 0xd3, 0x96, 0x36, 0x83, 0xf2, 0xf6, 0x4e, + 0x66, 0xa9, 0x60, 0xf0, 0xc5, 0xa4, 0xb6, 0x8c, 0xf9, 0xcb, 0x1c, 0x02, 0x73, 0x08, 0x55, 0x6b, 0x87, 0x57, 0x22, + 0x33, 0xbe, 0xe1, 0x11, 0x4b, 0xa9, 0x39, 0x76, 0xaa, 0xbb, 0xaa, 0x12, 0x7e, 0x56, 0x6b, 0x17, 0xb3, 0x2b, 0x48, + 0x7a, 0x30, 0xe9, 0x45, 0x1f, 0x75, 0x83, 0x23, 0x39, 0x14, 0x44, 0xee, 0x95, 0x98, 0x36, 0xdf, 0x86, 0x6d, 0x2e, + 0xa9, 0x9e, 0xbd, 0x96, 0x10, 0x70, 0x3d, 0x48, 0xb2, 0x37, 0xa8, 0xdc, 0xc5, 0xf6, 0xbb, 0xf2, 0xa8, 0x9d, 0xec, + 0x0d, 0x2e, 0x83, 0xb1, 0xee, 0xef, 0x55, 0x3e, 0x5e, 0xdf, 0x57, 0x9a, 0x8f, 0x87, 0xf2, 0x1c, 0xbc, 0xba, 0x30, + 0xca, 0x28, 0xbf, 0x79, 0xea, 0x0e, 0x8e, 0xb4, 0x32, 0xe0, 0xc8, 0xb0, 0xba, 0x7b, 0xd0, 0x31, 0x47, 0xeb, 0xd3, + 0x7c, 0x0c, 0x1b, 0x52, 0x35, 0xb1, 0x06, 0x69, 0x78, 0xdc, 0x93, 0xee, 0xe0, 0x28, 0x74, 0x24, 0x6f, 0x91, 0xcc, + 0xa3, 0x08, 0xda, 0xd0, 0x38, 0xc9, 0x27, 0xd4, 0x67, 0x79, 0xfb, 0x86, 0x5e, 0xb5, 0xc2, 0x29, 0xab, 0xdd, 0xdb, + 0xa0, 0x74, 0x54, 0x43, 0xe6, 0x4b, 0x29, 0x56, 0xbd, 0xda, 0xdd, 0xb6, 0x0f, 0x36, 0x8f, 0x71, 0xcd, 0x49, 0x9f, + 0x9c, 0x05, 0x56, 0x3e, 0x38, 0x6a, 0x87, 0x4b, 0x18, 0x91, 0xfc, 0xbe, 0xd4, 0x8e, 0x76, 0x30, 0x6c, 0xae, 0x64, + 0x7e, 0x97, 0x12, 0x07, 0xc6, 0x21, 0xaf, 0x05, 0x75, 0xe9, 0x0e, 0xfe, 0xd7, 0x7f, 0xfb, 0x1f, 0xda, 0xc7, 0x7e, + 0xd4, 0x4e, 0xba, 0xa6, 0xaf, 0xa5, 0x55, 0x29, 0x8f, 0xe0, 0x72, 0x9c, 0x3a, 0x28, 0x4c, 0x6f, 0x5b, 0x63, 0xce, + 0xe2, 0x56, 0x12, 0xa6, 0x23, 0x77, 0xb0, 0x19, 0x9b, 0x2a, 0xff, 0xb0, 0x65, 0xc2, 0xa9, 0xab, 0x45, 0x40, 0xaf, + 0xbf, 0xea, 0xd6, 0x05, 0x93, 0xd2, 0x25, 0xb7, 0xb6, 0x7d, 0x07, 0x43, 0xbd, 0xfb, 0x1a, 0xf7, 0x30, 0x64, 0xfa, + 0x83, 0xd3, 0x9a, 0x03, 0x66, 0x8d, 0xeb, 0x17, 0x4a, 0xd7, 0xa9, 0x82, 0x5a, 0xff, 0xe7, 0xbf, 0xff, 0xa7, 0xff, + 0x62, 0x1e, 0x21, 0x56, 0xf5, 0xbf, 0xfe, 0xeb, 0x7f, 0xfc, 0xdf, 0xff, 0xf3, 0x3f, 0x43, 0xfe, 0x99, 0x8e, 0x67, + 0x49, 0xa6, 0xe2, 0xd4, 0xc1, 0x2c, 0xc5, 0x5d, 0x1c, 0x38, 0xd5, 0x36, 0x61, 0x85, 0x60, 0x51, 0xf3, 0x42, 0x86, + 0x53, 0x39, 0xa0, 0xdc, 0x99, 0x1a, 0x3a, 0xb9, 0xc3, 0xcb, 0x9a, 0xa0, 0x1a, 0x28, 0x97, 0x84, 0x5b, 0x1e, 0xb5, + 0x01, 0xdf, 0x0f, 0xbb, 0xc3, 0xc6, 0xaf, 0x96, 0x63, 0x6e, 0xc8, 0x04, 0x4a, 0xca, 0xba, 0xdc, 0x81, 0xd8, 0xca, + 0x1c, 0x1e, 0x83, 0x9e, 0x55, 0x2c, 0x57, 0xaf, 0xd1, 0xa6, 0xff, 0xd3, 0xac, 0x10, 0x6c, 0x04, 0x28, 0x57, 0x7e, + 0x62, 0x19, 0xc6, 0x6e, 0x81, 0xae, 0x98, 0xde, 0x95, 0xb2, 0x17, 0x45, 0xa0, 0xfb, 0x87, 0xff, 0x54, 0xfe, 0x61, + 0x02, 0x1a, 0x99, 0xe3, 0x4d, 0xc2, 0x5b, 0x6d, 0x9e, 0x3f, 0xee, 0x74, 0xa6, 0xb7, 0x68, 0x5e, 0x8f, 0x80, 0x37, + 0x0d, 0x26, 0xe9, 0xd8, 0xee, 0x50, 0xc6, 0xbf, 0x2b, 0x37, 0x76, 0xc7, 0x01, 0x5f, 0xb8, 0xd3, 0x29, 0xcb, 0xdf, + 0xcf, 0xa5, 0x27, 0x95, 0xfd, 0x02, 0x71, 0x6a, 0xed, 0x74, 0xbe, 0xca, 0xed, 0xc9, 0xcd, 0xad, 0x56, 0x3d, 0xd5, + 0x2a, 0xe9, 0xae, 0x5e, 0xcd, 0x62, 0xc7, 0xd9, 0xed, 0x08, 0xf9, 0x3e, 0xc4, 0xbc, 0x93, 0x2e, 0x4e, 0x7a, 0xf3, + 0xaa, 0x7b, 0x21, 0xf2, 0x89, 0x1d, 0x58, 0xa7, 0x21, 0x8d, 0xe8, 0xc8, 0x38, 0xeb, 0xf5, 0x7b, 0x15, 0x34, 0x2f, + 0x93, 0xbd, 0x35, 0x63, 0x69, 0x90, 0x64, 0x40, 0xdd, 0xe9, 0x94, 0x5f, 0xc1, 0x0e, 0x9c, 0x8f, 0xd2, 0x3c, 0x14, + 0x81, 0x24, 0xd8, 0xbe, 0x1d, 0x9e, 0x0f, 0x81, 0x27, 0xe5, 0x73, 0x0b, 0x9e, 0xbe, 0xaa, 0x0a, 0x6e, 0xf3, 0xe6, + 0x05, 0x3a, 0xa5, 0x2f, 0x9b, 0xdb, 0x5d, 0x29, 0xaf, 0xdb, 0xf7, 0x3a, 0xea, 0xfd, 0xb2, 0xe1, 0xae, 0xd2, 0x02, + 0xa9, 0x87, 0xd6, 0xbf, 0x57, 0x72, 0x5d, 0xbd, 0xfd, 0x8b, 0xf0, 0x5c, 0x09, 0xa6, 0xbb, 0x5c, 0x4b, 0x16, 0x42, + 0xad, 0x97, 0xe4, 0xfb, 0xca, 0x64, 0x0a, 0xa7, 0x53, 0x59, 0x11, 0xf5, 0x8f, 0xda, 0x4a, 0xd3, 0x05, 0xee, 0x21, + 0x53, 0x3a, 0x54, 0x06, 0x85, 0xae, 0xa4, 0xb7, 0x82, 0xfa, 0xa5, 0x73, 0x2b, 0xe0, 0x43, 0xe4, 0x83, 0xff, 0x0b, + 0x64, 0xce, 0x91, 0xa6, 0x21, 0x98, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0xc8, 0x90, 0x11, 0x55, 0xb5, 0x2b, 0x2a, 0x8a, 0xaa, 0x55, 0x0f, 0xd0, 0x7a, 0xc0, 0x36, 0x66, 0x21, 0xff, - 0x0b, 0x0b, 0xa3, 0x01, 0x85, 0xcd, 0xc9, 0x64, 0x39, 0xe4, 0x0c, 0x83, 0xa7, 0x5a, 0x3d, 0x8d, 0x21, 0xe6, 0xfa, - 0x1a, 0xa7, 0xef, 0x35, 0x45, 0xd8, 0xd0, 0xc6, 0x30, 0x0a, 0x7e, 0xe2, 0x70, 0x81, 0x7e, 0xd3, 0x30, 0x8a, 0xf7, - 0x08, 0x8d, 0x7d, 0x92, 0xbb, 0x98, 0x33, 0xdf, 0xfb, 0xfc, 0x16, 0x8f, 0x9c, 0x41, 0x68, 0x88, 0x3d, 0x00, 0xca, - 0xb9, 0x8e, 0x1a, 0xab, 0x60, 0xf5, 0x24, 0xe5, 0x28, 0x3b, 0xbf, 0xca, 0x5f, 0xd9, 0x7d, 0x2e, 0xa7, 0xea, 0x32, - 0x41, 0xe7, 0x1b, 0x9e, 0x44, 0xdb, 0xde, 0x6f, 0x16, 0xa9, 0xda, 0xef, 0xbf, 0xbd, 0x27, 0x46, 0x81, 0x70, 0x53, - 0x66, 0x14, 0x4b, 0xb4, 0x26, 0x10, 0xf3, 0x21, 0x4a, 0xe9, 0xc3, 0xed, 0xb0, 0xff, 0xab, 0x2d, 0xff, 0xfb, 0x34, - 0xd5, 0x70, 0xe3, 0xc3, 0xc8, 0x07, 0x19, 0x24, 0xc3, 0x64, 0x31, 0x73, 0x3d, 0x59, 0x96, 0x9d, 0xcc, 0xc3, 0xc2, - 0x08, 0xa3, 0xc4, 0xc8, 0x7e, 0xd2, 0x65, 0x49, 0x64, 0xf7, 0xcd, 0xab, 0xca, 0x5f, 0x54, 0xdf, 0x32, 0x4d, 0xad, - 0xda, 0xc8, 0xf9, 0x38, 0xb8, 0xd1, 0xa2, 0x3f, 0x6a, 0x2c, 0xa4, 0xa8, 0x53, 0x5e, 0x0e, 0x10, 0x01, 0xd2, 0x16, - 0xf3, 0x90, 0x7e, 0x26, 0xbf, 0xd6, 0x2f, 0xfd, 0xb1, 0xaa, 0x36, 0xe0, 0x19, 0x76, 0xdf, 0xac, 0xc4, 0x3e, 0xea, - 0xb5, 0xdc, 0x95, 0xb8, 0x04, 0x4e, 0xbe, 0x4e, 0xce, 0xe4, 0x7c, 0x20, 0x3a, 0x9d, 0x2e, 0xad, 0x20, 0x81, 0xd4, - 0x2a, 0xc0, 0x47, 0xd8, 0x60, 0x9b, 0x3b, 0x34, 0xb2, 0xff, 0xdf, 0x54, 0x3f, 0xdb, 0x01, 0x18, 0x36, 0xa5, 0xa2, - 0xb2, 0x73, 0x1b, 0x92, 0x3a, 0x88, 0x4b, 0x39, 0xe5, 0xa6, 0x70, 0x51, 0x72, 0xee, 0xbd, 0xef, 0xdd, 0xd5, 0x24, - 0x7c, 0x61, 0x06, 0xc4, 0x7e, 0x24, 0x7d, 0x01, 0x04, 0x69, 0xe6, 0x23, 0x26, 0x85, 0xf4, 0xde, 0x9b, 0x01, 0x38, - 0x03, 0x50, 0x5a, 0x80, 0x94, 0x56, 0x71, 0xcf, 0xa1, 0x48, 0xf9, 0x6f, 0x48, 0x49, 0x5e, 0x87, 0x94, 0xaa, 0x26, - 0xe4, 0xce, 0xa7, 0x8f, 0x55, 0xb9, 0xa9, 0x68, 0xdc, 0xb9, 0x74, 0x6b, 0xa7, 0x43, 0x13, 0xe7, 0xec, 0xce, 0x93, - 0x52, 0xd8, 0x63, 0xa8, 0xb5, 0x3a, 0x6f, 0xfe, 0xb7, 0xba, 0x71, 0x46, 0x11, 0x68, 0x7a, 0xdb, 0x50, 0xad, 0xbf, - 0x56, 0x7a, 0xd7, 0x60, 0x86, 0x10, 0x42, 0x13, 0x1c, 0x37, 0x5f, 0xd3, 0x1d, 0x77, 0x77, 0x16, 0xd9, 0xc4, 0x38, - 0xe3, 0x00, 0xf5, 0x14, 0xa4, 0xa1, 0x63, 0x36, 0xdd, 0xac, 0xc6, 0xb9, 0x8d, 0x3c, 0xdf, 0x08, 0x26, 0x6e, 0x0f, - 0x41, 0xb7, 0x86, 0x03, 0x27, 0xd0, 0xc8, 0xf3, 0x4c, 0xfe, 0xe8, 0x03, 0x9b, 0xe3, 0xd7, 0x37, 0x64, 0xd0, 0xcb, - 0x61, 0xad, 0x05, 0xdc, 0x42, 0xb4, 0xbd, 0x0a, 0xca, 0x46, 0x80, 0x9a, 0x55, 0x5f, 0x0f, 0xd9, 0xfb, 0xc6, 0xfb, - 0x6f, 0x77, 0x9f, 0x0d, 0xb1, 0xd2, 0xbf, 0xa7, 0x58, 0xfe, 0x6b, 0x78, 0x6d, 0xd6, 0x25, 0x6b, 0x1d, 0xac, 0x87, - 0x90, 0xf3, 0x30, 0xf1, 0x10, 0x05, 0x6f, 0x61, 0x8e, 0xe3, 0xc6, 0xe3, 0x99, 0x21, 0x63, 0xcb, 0x45, 0xad, 0x07, - 0x66, 0xce, 0xfe, 0xfd, 0xf8, 0x6c, 0x4b, 0x35, 0x38, 0xc7, 0xc5, 0x46, 0xb4, 0xe9, 0x72, 0x49, 0x39, 0xb5, 0xd9, - 0xe5, 0xc8, 0x52, 0xba, 0xfd, 0x77, 0xd7, 0xa6, 0x8a, 0xfb, 0xec, 0xad, 0x6b, 0x39, 0xfc, 0xbc, 0x93, 0x13, 0x25, - 0x10, 0x51, 0xf1, 0x81, 0x22, 0xe5, 0x4a, 0x1d, 0x95, 0xaf, 0x33, 0x95, 0xa5, 0x5f, 0x7e, 0x85, 0x03, 0x41, 0x3c, - 0x20, 0x7a, 0xe3, 0x76, 0xbd, 0x4e, 0x47, 0x66, 0xcc, 0x2b, 0x62, 0x7e, 0xfb, 0xf9, 0xf9, 0x72, 0x61, 0xc0, 0xd7, - 0x10, 0x77, 0x9a, 0xd6, 0x03, 0xd6, 0xed, 0x1b, 0xf7, 0x5f, 0xcb, 0xd9, 0xe5, 0x7e, 0xcb, 0xb6, 0xb6, 0xfc, 0xb9, - 0xe1, 0x31, 0xbd, 0x50, 0x9d, 0xf2, 0x75, 0x1e, 0x16, 0xdc, 0xb4, 0x5b, 0x83, 0xe4, 0xa1, 0x3d, 0x00, 0x9f, 0xab, - 0x66, 0xc4, 0xb7, 0x1b, 0x55, 0x3a, 0xcf, 0x0b, 0x05, 0x89, 0xdb, 0x39, 0x49, 0xeb, 0xf4, 0x0e, 0x55, 0x66, 0x22, - 0x1a, 0xe1, 0x1f, 0x81, 0xac, 0xdc, 0x38, 0xe2, 0x83, 0xa0, 0xd7, 0x43, 0x82, 0x75, 0x84, 0x6a, 0x6a, 0x1e, 0xa5, - 0x0f, 0xef, 0x8d, 0xf5, 0x73, 0xdd, 0x40, 0xfe, 0x9b, 0x19, 0xa2, 0x4c, 0xf8, 0x61, 0xc8, 0x54, 0xb5, 0xdb, 0x76, - 0x21, 0x01, 0x80, 0x2a, 0xd3, 0x11, 0xb3, 0x9e, 0x79, 0x02, 0x9e, 0x0e, 0xe7, 0x32, 0xda, 0x14, 0x78, 0xab, 0x8f, - 0x77, 0xaf, 0x2f, 0x12, 0x87, 0xcb, 0x41, 0xfc, 0x30, 0xac, 0xdd, 0x8a, 0xab, 0xeb, 0x54, 0xc0, 0x17, 0x3b, 0x05, - 0x59, 0x27, 0x05, 0xd2, 0xb2, 0x6b, 0x96, 0x23, 0xf7, 0x20, 0x6f, 0xd8, 0x20, 0xb3, 0xca, 0x7d, 0x2d, 0xdf, 0x7a, - 0xf3, 0x77, 0x2e, 0x0a, 0xa1, 0xc4, 0x5f, 0x1d, 0xb3, 0xad, 0xb1, 0x40, 0x64, 0x48, 0x7f, 0x0f, 0x14, 0x83, 0x13, - 0xb1, 0xc8, 0x2c, 0xcb, 0x14, 0x96, 0x57, 0xc8, 0xa4, 0x6d, 0x5c, 0xaf, 0xc9, 0xb1, 0x15, 0xbd, 0x6a, 0xf0, 0xf0, - 0xf8, 0x25, 0x99, 0x45, 0x0a, 0x19, 0x96, 0x8f, 0x85, 0x91, 0xf2, 0x24, 0xef, 0x43, 0x97, 0xd3, 0x18, 0x3e, 0xc2, - 0xe9, 0xd3, 0x05, 0xa1, 0x2c, 0xc2, 0x94, 0x23, 0x92, 0xbd, 0x8d, 0x8d, 0x66, 0xc7, 0xac, 0x21, 0x84, 0xc9, 0x9f, - 0xf5, 0xaf, 0x73, 0xfc, 0x2b, 0xa6, 0x34, 0x05, 0xb2, 0x04, 0x1f, 0x7e, 0xa9, 0x08, 0x87, 0x08, 0x36, 0xb6, 0x71, - 0x91, 0x3d, 0x43, 0xca, 0x35, 0x90, 0x00, 0x42, 0x15, 0x18, 0xe3, 0xd9, 0x72, 0xee, 0xf8, 0x8c, 0x97, 0xb7, 0x83, - 0xce, 0x36, 0x0a, 0xcb, 0x17, 0x32, 0x8a, 0xd9, 0xd4, 0x0a, 0x28, 0x2f, 0x73, 0xaa, 0xfb, 0x34, 0x9b, 0xb4, 0xbb, - 0x20, 0xeb, 0x0a, 0x21, 0xdf, 0x1b, 0xa1, 0x1a, 0xa3, 0xdd, 0xe1, 0x17, 0x82, 0x5d, 0x99, 0x69, 0x12, 0x35, 0x55, - 0xf8, 0xfd, 0x2f, 0x07, 0x50, 0xf4, 0x2a, 0x1e, 0x57, 0xfa, 0x07, 0xd9, 0x97, 0x32, 0x97, 0x1c, 0xd6, 0xc7, 0xe0, - 0xa5, 0x3a, 0xaf, 0xa6, 0x36, 0x02, 0x05, 0xc4, 0xa8, 0xad, 0x44, 0xf5, 0x37, 0x6b, 0x1a, 0xb0, 0xa3, 0x8c, 0xf5, - 0xd7, 0xe5, 0x08, 0x87, 0x33, 0xd8, 0xe2, 0xd9, 0x52, 0xfe, 0x5a, 0x6f, 0x24, 0x8c, 0x51, 0x9b, 0xa9, 0xf2, 0x82, - 0xf1, 0xed, 0x41, 0x10, 0xd3, 0x68, 0x77, 0x72, 0x06, 0xdf, 0xc8, 0x1d, 0xf5, 0x07, 0xf1, 0x2a, 0xd7, 0x50, 0x0a, - 0x1a, 0x5f, 0x25, 0x90, 0x5b, 0x1b, 0x24, 0x90, 0x06, 0x4b, 0x11, 0x1a, 0xc7, 0x36, 0xc2, 0x3f, 0x2c, 0x55, 0xc1, - 0xbf, 0x1a, 0xcd, 0xf2, 0xed, 0x47, 0xf1, 0xf9, 0xd2, 0x6f, 0x41, 0x8c, 0xcf, 0x2b, 0xf9, 0xc7, 0x56, 0x3a, 0x97, - 0x96, 0x25, 0x83, 0xda, 0x95, 0x25, 0x35, 0x91, 0x8d, 0xe9, 0xe8, 0x7d, 0xa9, 0xa2, 0x05, 0xc4, 0x5a, 0xff, 0xa2, - 0xfa, 0xde, 0xd0, 0x89, 0x26, 0xed, 0x02, 0x1e, 0x29, 0xe8, 0x0e, 0x1e, 0x4c, 0x4f, 0xaf, 0xd6, 0xe6, 0x2d, 0x51, - 0xd4, 0xfe, 0xde, 0x86, 0x3f, 0x4d, 0x53, 0x17, 0x15, 0xf1, 0x25, 0x7b, 0x7e, 0x60, 0x6d, 0xba, 0xdd, 0xd4, 0xa0, - 0xb8, 0xc9, 0x08, 0xb5, 0x1a, 0xae, 0xde, 0x47, 0xac, 0x56, 0x30, 0x5c, 0x12, 0x9e, 0xaa, 0xd9, 0x56, 0x12, 0xbb, - 0x54, 0x50, 0xd6, 0xc7, 0xcd, 0x5d, 0x62, 0xe1, 0xab, 0xc6, 0x64, 0x13, 0x62, 0xf2, 0x9e, 0x20, 0x77, 0x3b, 0x76, - 0x0c, 0x86, 0x05, 0x0f, 0x3c, 0x20, 0x1e, 0xa8, 0xa5, 0x04, 0x03, 0xe3, 0x72, 0xf2, 0x3f, 0xbc, 0xe1, 0xe9, 0xa1, - 0x37, 0x41, 0x22, 0x20, 0xde, 0xa4, 0x2f, 0xf7, 0x0a, 0x82, 0x15, 0x95, 0x15, 0x80, 0x13, 0x35, 0x90, 0xb0, 0x42, - 0x85, 0x81, 0x43, 0xbd, 0x0e, 0xe9, 0xfc, 0x4d, 0xf3, 0xce, 0x0d, 0x18, 0x64, 0x56, 0x2d, 0xa4, 0x5b, 0xd7, 0xe9, - 0x1d, 0xe0, 0x89, 0x82, 0xeb, 0x53, 0x2b, 0x4b, 0x04, 0xe7, 0xa6, 0x97, 0x71, 0x98, 0x22, 0xf7, 0x69, 0x76, 0x9c, - 0x1e, 0x51, 0xd9, 0xdd, 0xae, 0x89, 0x64, 0x98, 0xfc, 0x09, 0xfa, 0xae, 0xd4, 0xdf, 0xe4, 0x54, 0x1b, 0x28, 0x0d, - 0xab, 0xe3, 0xdf, 0xb2, 0x8e, 0x22, 0xc1, 0x1f, 0xc4, 0xdc, 0x40, 0xd8, 0x8b, 0xc1, 0xd4, 0xa5, 0x44, 0x98, 0xd6, - 0x77, 0x05, 0xf6, 0x65, 0x29, 0xc3, 0xc7, 0x86, 0x43, 0xd6, 0xd7, 0x55, 0x9b, 0x1a, 0xe1, 0xeb, 0x09, 0xf9, 0xbc, - 0x77, 0xb2, 0xbe, 0x6e, 0x03, 0x79, 0xac, 0x1c, 0xa6, 0x6f, 0xde, 0x3a, 0x99, 0x2a, 0x70, 0xeb, 0xce, 0x73, 0xd2, - 0xdc, 0x9e, 0xa5, 0xee, 0x3b, 0xb8, 0xc7, 0xcd, 0xa7, 0x95, 0xd3, 0x75, 0x27, 0xaa, 0xd8, 0x78, 0x20, 0x2f, 0x24, - 0xf0, 0x5b, 0x59, 0x4a, 0x6b, 0x41, 0x8d, 0xf8, 0x18, 0xb4, 0xa1, 0xf5, 0x90, 0xe7, 0xd7, 0x33, 0xd4, 0x0c, 0x73, - 0x5a, 0x9c, 0x43, 0x3f, 0x2a, 0x6a, 0x33, 0x20, 0x62, 0xa4, 0x36, 0xa3, 0x3c, 0xaf, 0x82, 0xfb, 0xa5, 0xf5, 0x8f, - 0x98, 0x1b, 0xbe, 0xbe, 0xaf, 0x1f, 0x1a, 0xf3, 0x16, 0xaa, 0x8b, 0xb2, 0x4e, 0x99, 0xf9, 0xc9, 0x21, 0x0b, 0x44, - 0x86, 0x3c, 0x2b, 0xea, 0xe3, 0x7b, 0x6d, 0x05, 0x09, 0xe0, 0x1a, 0x01, 0x3b, 0xee, 0x1e, 0xc4, 0xc6, 0x16, 0x21, - 0x82, 0x0a, 0xed, 0x4e, 0x01, 0x1c, 0x54, 0x90, 0x89, 0x1f, 0xc9, 0xb5, 0xd1, 0x20, 0xaf, 0x5f, 0xa2, 0x1f, 0x2e, - 0x5c, 0x0f, 0xc9, 0xfa, 0x70, 0xc8, 0x20, 0x28, 0xe3, 0x6d, 0xe2, 0x40, 0x82, 0x08, 0x4b, 0x00, 0x3a, 0x36, 0xfe, - 0x4a, 0x25, 0xac, 0x24, 0x3a, 0xe2, 0xae, 0xde, 0x2e, 0x4f, 0x6e, 0x3d, 0x1c, 0xfc, 0x61, 0x95, 0x02, 0xc6, 0xf1, - 0x9e, 0x7f, 0x7e, 0xbf, 0x42, 0x91, 0x82, 0x98, 0x15, 0xc2, 0x21, 0xa7, 0x74, 0x99, 0x88, 0x41, 0xd6, 0x3e, 0xae, - 0x51, 0x73, 0x58, 0xc2, 0x86, 0x88, 0x8a, 0x66, 0xbb, 0x50, 0x2d, 0xea, 0x23, 0xc4, 0xe0, 0x67, 0x33, 0x76, 0xe8, - 0x22, 0x51, 0x49, 0x2b, 0x55, 0x1a, 0xd6, 0xc1, 0x7a, 0x8f, 0x5c, 0x29, 0xf0, 0x41, 0x8d, 0xaf, 0xbe, 0x09, 0x44, - 0xb1, 0x7b, 0x44, 0x6d, 0x17, 0x92, 0xc1, 0xcb, 0x7b, 0xe8, 0x4e, 0xf4, 0xcb, 0x1e, 0x85, 0xac, 0x63, 0x0d, 0xed, - 0x29, 0x4f, 0x64, 0x1e, 0x7b, 0x42, 0x03, 0x25, 0x5a, 0xfe, 0xe8, 0x4c, 0xc9, 0x44, 0x38, 0xcf, 0x3c, 0x1f, 0xae, - 0x2e, 0xf3, 0xd1, 0x87, 0xc7, 0x3c, 0xa4, 0x94, 0x58, 0xf8, 0x84, 0x25, 0x07, 0x74, 0xdd, 0x05, 0x49, 0x01, 0xbc, - 0x6b, 0x8a, 0xa5, 0xfb, 0x51, 0x11, 0x0f, 0x27, 0xeb, 0x69, 0xe6, 0x71, 0xb1, 0x57, 0xaa, 0x38, 0x7a, 0x90, 0x5d, - 0xb8, 0x40, 0xdd, 0xdb, 0x40, 0xd0, 0xb1, 0xc0, 0x2c, 0x81, 0x44, 0x88, 0xf4, 0xde, 0x56, 0xe7, 0x42, 0xc8, 0xeb, - 0x24, 0x33, 0x12, 0x81, 0x5a, 0xe5, 0x6c, 0x02, 0x75, 0xe3, 0x91, 0x22, 0x74, 0x92, 0x92, 0x3c, 0xe1, 0x00, 0xd1, - 0xe3, 0x0a, 0xeb, 0x28, 0x38, 0xc4, 0x75, 0x25, 0x65, 0x4e, 0xfe, 0xcb, 0x94, 0x26, 0x26, 0xbb, 0x72, 0x38, 0x24, - 0x02, 0xa4, 0x74, 0x4b, 0xad, 0x06, 0x9f, 0x45, 0xc4, 0x47, 0x02, 0x30, 0x13, 0x91, 0x28, 0xfc, 0x4b, 0xf7, 0xd2, - 0x33, 0x2f, 0x21, 0xa2, 0x31, 0xd3, 0xa4, 0xb3, 0xe4, 0xed, 0x35, 0xe9, 0xf0, 0x71, 0xa3, 0x93, 0xa8, 0x66, 0xed, - 0x2f, 0xa5, 0x8f, 0x89, 0x2b, 0xf7, 0x8f, 0x02, 0x13, 0x31, 0x9a, 0x9c, 0x53, 0xe9, 0x67, 0x69, 0x71, 0x3e, 0x16, - 0x28, 0x35, 0xaa, 0x2d, 0xbe, 0xbe, 0xad, 0xcf, 0x36, 0x44, 0x9d, 0xb3, 0x4b, 0x1c, 0xf0, 0x74, 0xd5, 0x74, 0xca, - 0x6d, 0x81, 0x0f, 0x2d, 0x93, 0x03, 0x52, 0x74, 0xa7, 0x5d, 0xa2, 0xdb, 0xde, 0x87, 0xe4, 0x30, 0x98, 0xad, 0x80, - 0x03, 0x28, 0xa3, 0x6a, 0x31, 0xb2, 0x1c, 0xc8, 0x62, 0xa9, 0xe4, 0x72, 0x01, 0x40, 0x8b, 0xac, 0x2b, 0xa7, 0x0c, - 0x85, 0xca, 0x69, 0x64, 0x09, 0x07, 0xd5, 0xc6, 0x48, 0xe6, 0x5a, 0x7d, 0x65, 0x08, 0x69, 0xd4, 0x5c, 0x03, 0x73, - 0xa0, 0x50, 0xb3, 0x64, 0xdd, 0x45, 0xa9, 0x56, 0xe1, 0xb9, 0x30, 0x40, 0x9e, 0x3f, 0xae, 0x36, 0xeb, 0x2e, 0x3b, - 0x2f, 0x4e, 0xc5, 0x0b, 0x0a, 0x1b, 0x1e, 0x24, 0xbb, 0x12, 0x27, 0x25, 0x08, 0x9c, 0xa2, 0xa6, 0xb1, 0x57, 0xdc, - 0x7f, 0x25, 0x7f, 0x3f, 0xa4, 0x92, 0x74, 0x2a, 0xa3, 0x18, 0xf1, 0xf4, 0xab, 0x2a, 0xeb, 0x1a, 0x6d, 0x80, 0x94, - 0xbf, 0x77, 0xe9, 0xc8, 0x7a, 0xd3, 0x55, 0x46, 0xaf, 0x4c, 0x9d, 0x55, 0xf8, 0x71, 0x3e, 0x19, 0xd3, 0xe9, 0x8b, - 0xb8, 0xaa, 0x13, 0x47, 0x01, 0x45, 0x20, 0xec, 0xf1, 0xe3, 0x2b, 0xe5, 0xd1, 0x5e, 0x09, 0x58, 0xb2, 0x8d, 0xc1, - 0x9a, 0x54, 0x47, 0x4c, 0x48, 0x5a, 0xde, 0x7d, 0x04, 0xc6, 0x4a, 0x15, 0x45, 0x17, 0xe0, 0xc3, 0x07, 0x94, 0x1e, - 0x14, 0x1a, 0xc7, 0x3c, 0xe5, 0x36, 0x64, 0x98, 0x80, 0x81, 0x1e, 0x07, 0x79, 0x76, 0xfc, 0xc9, 0x55, 0x15, 0xea, - 0x40, 0x3f, 0x2c, 0xd9, 0xd9, 0xb2, 0xb0, 0xbc, 0xca, 0x8e, 0xfd, 0xa7, 0x28, 0xba, 0xae, 0x7b, 0x62, 0x09, 0x47, - 0x7a, 0xdf, 0x8a, 0xdc, 0xc4, 0x82, 0xf3, 0xd5, 0x4a, 0x88, 0xe5, 0x09, 0xc3, 0x00, 0x69, 0x39, 0x66, 0xca, 0x40, - 0x0e, 0x1d, 0x81, 0x91, 0x0c, 0x99, 0x56, 0x77, 0xf8, 0xf4, 0x2d, 0x7e, 0xc0, 0x21, 0x93, 0x94, 0x9c, 0x69, 0x72, - 0xdc, 0x8b, 0x62, 0xb0, 0x2b, 0x43, 0x54, 0x40, 0xe3, 0x6a, 0x3a, 0x85, 0x21, 0x59, 0xea, 0x7d, 0xa5, 0x5b, 0x6a, - 0x3d, 0x82, 0xbb, 0xf3, 0x44, 0x0a, 0x76, 0x40, 0xd5, 0xcb, 0xe8, 0x8c, 0x63, 0x01, 0x84, 0xf4, 0x24, 0xc9, 0x5d, - 0x52, 0x0c, 0xb2, 0x89, 0x14, 0x0a, 0xac, 0x2f, 0x3b, 0x8c, 0x69, 0x31, 0x7d, 0x3f, 0x08, 0x9c, 0x2c, 0x75, 0x49, - 0x04, 0xe9, 0xf3, 0x60, 0x77, 0x49, 0xf1, 0x08, 0x95, 0x8f, 0xbd, 0xfb, 0x59, 0x0a, 0x4a, 0x53, 0x9d, 0xe4, 0x09, - 0x82, 0xf6, 0x1c, 0x18, 0x1d, 0x13, 0x30, 0x1f, 0x48, 0x45, 0x7d, 0x38, 0xad, 0x1e, 0x0b, 0xbb, 0x0f, 0x29, 0xee, - 0xcb, 0xec, 0xe5, 0x2f, 0xe6, 0x73, 0xa4, 0x39, 0x33, 0x74, 0x52, 0xa7, 0x90, 0xcc, 0x66, 0xf9, 0xa5, 0x28, 0x91, - 0xe6, 0xbd, 0xb7, 0x87, 0x23, 0xfd, 0x80, 0xdf, 0x17, 0x82, 0x1b, 0xc0, 0x1c, 0x46, 0xf0, 0x55, 0x17, 0xc5, 0x6e, - 0x96, 0x6d, 0x48, 0xa1, 0xb5, 0xa3, 0x19, 0x2e, 0xd9, 0xee, 0x8d, 0x24, 0x66, 0xad, 0xc8, 0x84, 0x7a, 0xaf, 0x74, - 0x64, 0x6a, 0x3f, 0x2c, 0x61, 0x6b, 0xa5, 0x62, 0x7a, 0x1e, 0xc6, 0xb0, 0x0e, 0x32, 0xc8, 0x08, 0x2a, 0x2b, 0x5c, - 0x30, 0xd4, 0x50, 0x9c, 0x94, 0xf3, 0x06, 0x91, 0xec, 0x1c, 0x4c, 0x27, 0xa6, 0xa1, 0x14, 0x8b, 0x18, 0xd3, 0x43, - 0xb7, 0x79, 0x8f, 0x62, 0x12, 0xf4, 0xfb, 0xb2, 0x3b, 0x9e, 0x3c, 0xc0, 0xcc, 0x04, 0x4e, 0x2d, 0x0d, 0xb2, 0x94, - 0xe1, 0x5c, 0xdb, 0x5f, 0xf1, 0xc3, 0x75, 0x1f, 0x7a, 0x40, 0x74, 0xbf, 0x0f, 0xf2, 0xa1, 0x5e, 0xad, 0x31, 0x18, - 0xe4, 0xb0, 0x50, 0xfa, 0xde, 0x34, 0x84, 0x87, 0x1d, 0x18, 0xcd, 0xc1, 0x32, 0x4c, 0x67, 0x59, 0x4b, 0xae, 0x6c, - 0x55, 0x4d, 0xec, 0x82, 0x6e, 0xd4, 0xba, 0x74, 0xa4, 0x9f, 0x44, 0x2a, 0x76, 0x3d, 0xc7, 0xbd, 0x16, 0xb8, 0xdb, - 0xb6, 0xbc, 0x1c, 0x8b, 0x71, 0x32, 0x23, 0xd2, 0xa8, 0x7e, 0x5a, 0x40, 0x76, 0xac, 0x23, 0x0a, 0x9e, 0x26, 0x23, - 0x1c, 0x06, 0xff, 0x83, 0xcd, 0xad, 0x23, 0xbc, 0x78, 0x2d, 0x74, 0x08, 0xad, 0x6d, 0xb8, 0x6d, 0xe9, 0xee, 0x13, - 0x44, 0xff, 0x5d, 0x27, 0x20, 0x33, 0x81, 0x0a, 0x39, 0x51, 0x1d, 0xe5, 0x54, 0xc5, 0x70, 0xd0, 0xe9, 0xd6, 0x34, - 0x56, 0x69, 0x62, 0xdd, 0xc5, 0x87, 0xe8, 0xd3, 0x0e, 0x48, 0x51, 0x5d, 0x01, 0x93, 0x45, 0xf5, 0x9b, 0x10, 0x80, - 0x8a, 0x2d, 0x33, 0x30, 0x31, 0x2f, 0x67, 0x5a, 0xda, 0xff, 0x2a, 0x2e, 0x59, 0xc5, 0xf2, 0x2f, 0x49, 0xe1, 0xf1, - 0x31, 0x4a, 0x19, 0x58, 0x6b, 0x40, 0xd4, 0xb5, 0x5e, 0xee, 0xd5, 0x45, 0xce, 0xb8, 0xa6, 0xe0, 0xc1, 0xd7, 0xee, - 0x57, 0x75, 0xc3, 0x1f, 0x3f, 0x6a, 0x38, 0xf0, 0x05, 0xa9, 0x46, 0x63, 0x01, 0xe9, 0x7e, 0x17, 0xa3, 0xc2, 0x6c, - 0xbf, 0xac, 0x07, 0x49, 0x22, 0x2a, 0x4f, 0x00, 0x7f, 0x5f, 0xaf, 0x42, 0xb7, 0x06, 0x44, 0xdc, 0x42, 0x1e, 0xcf, - 0x7a, 0x9a, 0xe4, 0x8e, 0x30, 0x45, 0xe2, 0xeb, 0xf7, 0x11, 0xa2, 0x32, 0x99, 0xde, 0xfc, 0x33, 0x6b, 0xc4, 0x29, - 0x4b, 0x60, 0x72, 0x0b, 0x4a, 0xea, 0x1c, 0xf2, 0x28, 0x23, 0x7d, 0xaa, 0x5e, 0xf2, 0x9b, 0x34, 0x07, 0x32, 0x69, - 0x83, 0x4c, 0x11, 0x88, 0x4e, 0x0f, 0xd2, 0x28, 0xfa, 0x20, 0x00, 0xee, 0x20, 0x08, 0xb4, 0x04, 0x81, 0x00, 0x3e, - 0xd2, 0x3b, 0x09, 0x34, 0x21, 0x93, 0xfc, 0x1a, 0x96, 0xa7, 0x2a, 0x95, 0xdb, 0xd4, 0x6e, 0x9c, 0x2d, 0x11, 0x9d, - 0x0a, 0x3a, 0x28, 0x66, 0xa1, 0xdf, 0x1b, 0xbf, 0x25, 0x1d, 0x7a, 0x5f, 0xa2, 0xc2, 0xd8, 0xd3, 0x34, 0xf3, 0x2c, - 0x50, 0xb2, 0x50, 0xf7, 0x7b, 0xb8, 0xff, 0x58, 0x10, 0xde, 0x25, 0x14, 0x64, 0x78, 0xa8, 0x67, 0x8a, 0x14, 0xf7, - 0x70, 0x02, 0x27, 0xe5, 0xc7, 0x8a, 0xcc, 0xde, 0xd7, 0xfc, 0x9e, 0xfe, 0x4c, 0xa0, 0x36, 0xe6, 0x0f, 0x5e, 0x3a, - 0xe6, 0x7c, 0x19, 0x17, 0x18, 0x27, 0x11, 0x07, 0x9a, 0xa2, 0xc0, 0x0e, 0x27, 0x7a, 0xde, 0xf1, 0x62, 0x1d, 0xe2, - 0xae, 0xdc, 0x3c, 0xe8, 0xad, 0xa7, 0x3a, 0x64, 0x5c, 0xcf, 0x44, 0xd6, 0xb6, 0xa8, 0xdf, 0x7f, 0xbf, 0xfa, 0x9e, - 0x1e, 0x5f, 0x8e, 0xe7, 0xa4, 0x4e, 0x51, 0x81, 0x66, 0x5a, 0x78, 0x10, 0xfe, 0x31, 0x99, 0x99, 0xc7, 0xc0, 0x07, - 0x26, 0x63, 0x74, 0xcc, 0xc8, 0x83, 0xf5, 0xb7, 0x82, 0xbc, 0xd8, 0x41, 0x7e, 0xa7, 0x90, 0xfc, 0xe4, 0xc3, 0x0c, - 0x69, 0x44, 0x41, 0x50, 0xa5, 0x3e, 0xa0, 0x50, 0x26, 0x96, 0xfd, 0xf7, 0x96, 0xf6, 0x6d, 0x72, 0x60, 0x12, 0xcb, - 0xe3, 0x6c, 0x31, 0x1e, 0xb3, 0x38, 0xe7, 0x40, 0x7f, 0x2c, 0x59, 0x78, 0x2f, 0x3c, 0x1d, 0xf3, 0xb0, 0x36, 0xf3, - 0xce, 0xc6, 0x04, 0xf0, 0x36, 0xd6, 0x96, 0x7e, 0xc7, 0xcd, 0xfa, 0x71, 0xe8, 0xa0, 0x07, 0xad, 0x3d, 0x74, 0xc0, - 0xca, 0xd3, 0x13, 0x28, 0x8a, 0x6d, 0xc1, 0xd7, 0xdb, 0x3b, 0xac, 0x65, 0x14, 0x3b, 0x64, 0xab, 0xf9, 0xba, 0x2d, - 0xad, 0xc7, 0x28, 0xa9, 0xbf, 0x32, 0xeb, 0x83, 0xb1, 0x7b, 0xf8, 0x01, 0xbb, 0xfa, 0xf5, 0xd5, 0xea, 0x1a, 0x1f, - 0xcf, 0xbb, 0x3a, 0x28, 0x7d, 0xf0, 0x2e, 0x2e, 0x99, 0xcb, 0x4a, 0xcd, 0xe3, 0x2e, 0x45, 0xec, 0x0f, 0x82, 0x67, - 0x11, 0xdd, 0xda, 0x41, 0x1a, 0x7c, 0xbf, 0x14, 0xc1, 0x06, 0xab, 0x7a, 0xa5, 0x15, 0x70, 0xa4, 0xe2, 0xce, 0x3e, - 0x51, 0x88, 0x62, 0xb6, 0x37, 0x10, 0xf1, 0xfc, 0x53, 0xfd, 0xf9, 0x3e, 0xc3, 0x57, 0x05, 0x1f, 0x90, 0x41, 0x86, - 0xcd, 0x86, 0x4b, 0xb6, 0xe2, 0xf2, 0x69, 0x18, 0x90, 0x77, 0x03, 0xbf, 0xf5, 0xdc, 0x5f, 0xc3, 0x7d, 0x64, 0xa9, - 0xe5, 0x5f, 0x20, 0x12, 0x51, 0xf8, 0x8d, 0x62, 0x22, 0xb8, 0x27, 0x08, 0x78, 0x52, 0xc9, 0x10, 0x8b, 0x75, 0xa0, - 0x6b, 0x9c, 0x1e, 0x5e, 0x0f, 0xd3, 0x59, 0x5f, 0x78, 0x9c, 0xbb, 0x36, 0xab, 0xbc, 0xca, 0x75, 0xd7, 0xb6, 0xf6, - 0x6c, 0x89, 0xf8, 0x19, 0x49, 0xac, 0x5a, 0xce, 0xcf, 0x28, 0xb6, 0x0f, 0x98, 0xca, 0xbf, 0x0d, 0xba, 0xb8, 0x23, - 0x4d, 0xae, 0x87, 0xdd, 0xfe, 0xc2, 0x56, 0x55, 0x2c, 0x1e, 0x3f, 0x7a, 0xf3, 0x6e, 0xf3, 0xc5, 0xf5, 0x81, 0x6f, - 0x69, 0x72, 0x69, 0x7f, 0x66, 0x36, 0x49, 0x92, 0xee, 0xe7, 0x64, 0x71, 0xa1, 0x8e, 0x7f, 0x3f, 0xf1, 0x49, 0xc7, - 0xc2, 0x98, 0x97, 0x5d, 0x2d, 0x66, 0x4a, 0x2b, 0xf9, 0x3b, 0xdf, 0xdf, 0x7e, 0xff, 0xec, 0x51, 0x8c, 0x6d, 0xc5, - 0xb9, 0x6d, 0x92, 0x24, 0x79, 0x96, 0x6b, 0xe1, 0x7b, 0x34, 0xd4, 0x47, 0xda, 0xe3, 0xc6, 0xcb, 0x7c, 0x89, 0xc2, - 0x6a, 0xd6, 0x3c, 0x63, 0xb6, 0x7e, 0x5e, 0x7e, 0xf7, 0xd8, 0xd9, 0xe4, 0x7a, 0x13, 0xcb, 0x91, 0xf0, 0x2d, 0xbe, - 0x65, 0x0b, 0x66, 0xba, 0x80, 0xe4, 0x2f, 0xe5, 0xee, 0xf1, 0x5d, 0x71, 0xf9, 0xc3, 0xae, 0x17, 0x66, 0x96, 0x73, - 0x2c, 0x31, 0x96, 0x28, 0x1e, 0xb8, 0x39, 0xdf, 0x81, 0x35, 0x69, 0x72, 0xbe, 0xad, 0x78, 0x8d, 0x73, 0x90, 0xfb, - 0x7b, 0xfa, 0x1f, 0x3f, 0x39, 0xda, 0xdc, 0xc5, 0xc7, 0x11, 0x74, 0x41, 0x62, 0xb7, 0x0b, 0xd6, 0x6e, 0x8a, 0x57, - 0x13, 0xc3, 0x4d, 0x54, 0x95, 0x44, 0x3d, 0x31, 0x1b, 0x01, 0x96, 0x4b, 0x5f, 0x0f, 0x38, 0xd0, 0x4d, 0x27, 0xca, - 0x22, 0xff, 0x6b, 0xec, 0x22, 0x65, 0x40, 0xf8, 0x97, 0x52, 0x48, 0x70, 0xaa, 0xb7, 0x24, 0x25, 0xb8, 0xe6, 0x3b, - 0x56, 0xe5, 0xff, 0x0d, 0x64, 0xc2, 0x6c, 0x26, 0xc2, 0x8a, 0xec, 0x7e, 0xf5, 0xdb, 0x33, 0x82, 0xa9, 0xe7, 0x22, - 0x66, 0x6d, 0xf7, 0xec, 0xd3, 0xb0, 0x67, 0x93, 0x37, 0x22, 0x0b, 0x38, 0x67, 0x08, 0x9c, 0x3c, 0xe3, 0xca, 0xe2, - 0xe4, 0x96, 0xe5, 0x37, 0x77, 0xb9, 0x27, 0x7a, 0x21, 0x91, 0x48, 0x31, 0xab, 0x68, 0xe2, 0x58, 0x01, 0x48, 0x5a, - 0x7d, 0xf8, 0x71, 0xd4, 0xf7, 0x1f, 0x58, 0xaf, 0xd5, 0xdb, 0xb8, 0x4e, 0xc7, 0x88, 0xf8, 0x68, 0x38, 0x6e, 0x21, - 0x78, 0xb9, 0x4a, 0x4d, 0xf4, 0x19, 0xb7, 0xe4, 0x15, 0xa3, 0xde, 0x90, 0xee, 0xac, 0xce, 0x7b, 0x3a, 0xb7, 0xf3, - 0x65, 0x9b, 0x28, 0x54, 0x33, 0x34, 0x83, 0x41, 0x81, 0xf8, 0x38, 0x5f, 0xab, 0x91, 0x44, 0xdf, 0x11, 0xea, 0x84, - 0xbf, 0x5d, 0xb2, 0x48, 0x88, 0x69, 0x36, 0x3b, 0xf9, 0x75, 0xee, 0xa2, 0x9a, 0x48, 0xd2, 0x3b, 0xe7, 0x10, 0x64, - 0xfa, 0x39, 0x83, 0x44, 0x0a, 0x27, 0x18, 0x43, 0x19, 0xc5, 0xb5, 0x59, 0x2e, 0x6a, 0xa1, 0x8a, 0xcf, 0xeb, 0xd9, - 0xb0, 0x53, 0x22, 0xd9, 0x4a, 0x14, 0xeb, 0x7c, 0x6d, 0x4f, 0xae, 0xa9, 0xb7, 0x5c, 0x0f, 0x19, 0xc5, 0x75, 0xf2, - 0xfc, 0xaa, 0x56, 0xb1, 0x51, 0x13, 0xf0, 0xa7, 0x94, 0xe2, 0xc0, 0x86, 0xdb, 0xbc, 0x25, 0x52, 0x7a, 0x56, 0xd6, - 0xdf, 0x3a, 0x49, 0x88, 0xef, 0xce, 0x4d, 0x2b, 0x7b, 0x43, 0x84, 0x87, 0x24, 0x81, 0xdc, 0xa8, 0xb5, 0xa6, 0x72, - 0xd7, 0xed, 0x33, 0x5f, 0x15, 0x56, 0x75, 0xfb, 0xd7, 0x6b, 0x37, 0xe0, 0x10, 0xf8, 0x00, 0x02, 0x21, 0xee, 0x25, - 0xb3, 0xcb, 0x61, 0x73, 0x04, 0x09, 0xf4, 0x19, 0xf0, 0x07, 0x2f, 0x5a, 0xa1, 0xe0, 0xad, 0xed, 0xc0, 0x03, 0x00, - 0x40, 0x6e, 0x35, 0x56, 0x3c, 0xdb, 0xc5, 0x7c, 0x47, 0xfe, 0x30, 0x55, 0x6b, 0xbe, 0x6e, 0x75, 0xd7, 0x05, 0x38, - 0x2f, 0x30, 0x9b, 0x7f, 0x2c, 0x55, 0xdb, 0x75, 0xc4, 0x69, 0x1a, 0x14, 0x98, 0xa8, 0xd2, 0xab, 0x4c, 0x95, 0xa4, - 0x56, 0x95, 0xa2, 0xe5, 0x61, 0x4d, 0xbb, 0xfa, 0x3c, 0x3e, 0xe6, 0x83, 0xb5, 0x26, 0x10, 0x5a, 0x07, 0x2f, 0xdd, - 0xdb, 0x9b, 0x96, 0x74, 0x6e, 0xb4, 0x4a, 0x9e, 0x68, 0xf3, 0x55, 0xe9, 0x5d, 0x05, 0xb7, 0x4c, 0xf9, 0x22, 0x23, - 0x0e, 0x61, 0x8d, 0xf0, 0x5f, 0xf5, 0x61, 0x68, 0x5b, 0x28, 0xb2, 0x7f, 0x1e, 0x88, 0xe0, 0xa9, 0x92, 0xbd, 0xcc, - 0x6c, 0xf3, 0x88, 0x0c, 0x61, 0x78, 0xe7, 0x12, 0x17, 0xc4, 0xf2, 0x53, 0x5d, 0x79, 0x66, 0xed, 0xee, 0x4d, 0x64, - 0x8b, 0x6c, 0xbc, 0xe3, 0x41, 0xc7, 0x3c, 0xaf, 0x2b, 0xd8, 0x61, 0xa3, 0xbd, 0x49, 0xb3, 0xc7, 0x79, 0x9b, 0xb2, - 0x8c, 0xd5, 0xc1, 0x0b, 0x59, 0x27, 0xc4, 0x24, 0x2d, 0x2a, 0x45, 0xe0, 0x7c, 0x80, 0xd6, 0x1e, 0x4f, 0x77, 0x3f, - 0x25, 0x7e, 0x6d, 0x2e, 0x2c, 0x36, 0xe8, 0x4b, 0x07, 0xbb, 0x9f, 0x79, 0xc4, 0x86, 0x11, 0x5b, 0x90, 0x7f, 0xdb, - 0x06, 0x10, 0xbb, 0x47, 0x94, 0xb2, 0x1b, 0xd1, 0xa3, 0x54, 0x3f, 0xe1, 0x55, 0x3e, 0x50, 0x81, 0x34, 0x66, 0x48, - 0x69, 0xc5, 0x15, 0x27, 0x92, 0xa0, 0x77, 0xb0, 0x04, 0x49, 0x0e, 0xec, 0x7b, 0x82, 0x88, 0xe8, 0x87, 0x9c, 0x8a, - 0x5c, 0xc5, 0x53, 0xcf, 0xa6, 0xdb, 0x23, 0xa3, 0x24, 0x48, 0xee, 0xf1, 0xa3, 0xe0, 0xbb, 0xbd, 0x89, 0xe2, 0x6e, - 0xf3, 0x44, 0xf0, 0xe6, 0x09, 0x26, 0x82, 0xf3, 0x02, 0xf9, 0x98, 0x5d, 0x3c, 0x81, 0x44, 0x25, 0x42, 0xbf, 0xe4, - 0xec, 0xe8, 0xdf, 0x65, 0xa9, 0xb7, 0xda, 0xeb, 0x50, 0x18, 0xb4, 0x2d, 0xa7, 0xd6, 0x38, 0xee, 0xb0, 0x94, 0x5d, - 0x34, 0x77, 0x59, 0xb2, 0x2c, 0x6b, 0x2f, 0xa3, 0x11, 0x1a, 0xa9, 0x79, 0xf8, 0x5c, 0x6a, 0x59, 0xd1, 0xf1, 0xa2, - 0x16, 0xe1, 0xc0, 0x10, 0x4b, 0xa5, 0xb3, 0x9c, 0x62, 0xb5, 0x5d, 0x18, 0x59, 0x8e, 0x23, 0x97, 0x2b, 0x09, 0x28, - 0x9a, 0x43, 0x44, 0x99, 0x0c, 0x1c, 0x47, 0x0b, 0x53, 0x29, 0x30, 0x66, 0x16, 0x1e, 0xec, 0x7c, 0x9b, 0x91, 0xeb, - 0x68, 0x24, 0x5f, 0xf8, 0x86, 0x14, 0xe3, 0x83, 0xb4, 0xd7, 0xd9, 0x88, 0x64, 0xe4, 0x80, 0x3d, 0x97, 0xa9, 0x08, - 0xab, 0x38, 0xaa, 0x77, 0x73, 0x8d, 0xeb, 0x46, 0x65, 0xe4, 0x8a, 0xf6, 0x3a, 0xb2, 0x58, 0x68, 0xc1, 0x7a, 0x7e, - 0xc9, 0xbc, 0xfb, 0x1c, 0x60, 0x6b, 0xa3, 0xac, 0x76, 0xe9, 0x02, 0xcd, 0xf9, 0x58, 0x53, 0xf8, 0x3b, 0x19, 0x81, - 0xbf, 0x71, 0xc2, 0x4e, 0xb3, 0x9f, 0xf7, 0xae, 0x91, 0x59, 0xf6, 0x32, 0xde, 0x32, 0x8f, 0x4e, 0x1d, 0x27, 0xb7, - 0x4e, 0x13, 0xc3, 0x98, 0x61, 0xc9, 0xf7, 0x07, 0xb8, 0xc4, 0x7c, 0x47, 0x80, 0x9d, 0xdf, 0xf3, 0x5c, 0xd2, 0x4e, - 0xe9, 0x80, 0xb4, 0x64, 0xf3, 0xc4, 0x4d, 0xd6, 0x5b, 0x93, 0x9f, 0x53, 0x8a, 0x95, 0x0b, 0xfe, 0x5a, 0xbf, 0xb2, - 0x9e, 0x94, 0xef, 0xd3, 0xe1, 0xad, 0x37, 0x33, 0xf9, 0xc1, 0x56, 0x98, 0xb0, 0x77, 0x40, 0x07, 0x5f, 0xc7, 0x7a, - 0x0b, 0x1f, 0x1f, 0xd8, 0xd1, 0x92, 0x84, 0x4e, 0x15, 0x5a, 0xd5, 0x51, 0xc8, 0xf8, 0xe8, 0x3e, 0x77, 0x1a, 0x89, - 0x45, 0x52, 0x2c, 0xa0, 0xf3, 0xad, 0xda, 0xfb, 0x27, 0xd4, 0xfc, 0xa8, 0x35, 0x99, 0xa2, 0xe9, 0xcc, 0xa9, 0x73, - 0xf5, 0xd7, 0xd4, 0x97, 0xed, 0x58, 0x07, 0x33, 0x71, 0xfd, 0x2d, 0xba, 0x56, 0x5f, 0x73, 0x9f, 0xa5, 0x20, 0x35, - 0x65, 0xd9, 0xc5, 0x89, 0xea, 0xcc, 0xab, 0x51, 0xa4, 0x53, 0xf1, 0xf1, 0x36, 0x72, 0xc7, 0x8b, 0x91, 0xd8, 0xc2, - 0x3b, 0xf8, 0x0a, 0x4b, 0xa2, 0xde, 0x6f, 0x44, 0x7c, 0x4c, 0xa8, 0x19, 0xbe, 0x43, 0x15, 0x38, 0x6b, 0x81, 0x81, - 0x92, 0x9c, 0xa8, 0xdb, 0x4e, 0xc5, 0xd9, 0x19, 0xbc, 0x34, 0x62, 0x57, 0x24, 0xa1, 0x43, 0x3e, 0x43, 0x7d, 0x05, - 0x1f, 0xed, 0xb3, 0x82, 0x1b, 0x4c, 0x2d, 0xf8, 0xb5, 0x8c, 0x62, 0x66, 0xfa, 0xdc, 0x35, 0xc4, 0x20, 0xfa, 0x9e, - 0x96, 0x66, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, 0x9e, 0x83, 0xf7, 0x02, 0x23, 0x62, 0xba, 0x6c, 0x77, 0x36, 0xbf, - 0x6e, 0x23, 0xc8, 0x12, 0x5d, 0x75, 0x9b, 0xc8, 0x24, 0x06, 0xce, 0xb1, 0x26, 0xc4, 0x87, 0x30, 0x43, 0x90, 0x0b, - 0xdd, 0xeb, 0x64, 0xa4, 0xd2, 0x27, 0x5c, 0xa4, 0xa3, 0x8e, 0x1e, 0xee, 0x66, 0x59, 0xbb, 0x61, 0xd7, 0xac, 0xfe, - 0x77, 0xde, 0xb5, 0xc3, 0xeb, 0xd3, 0xa0, 0xc8, 0x13, 0x6a, 0xb0, 0x40, 0x7a, 0x84, 0xbf, 0xf9, 0xf1, 0x50, 0x22, - 0xd3, 0xaf, 0x8f, 0x53, 0x21, 0x33, 0xce, 0x81, 0x03, 0xc8, 0x74, 0x4a, 0xff, 0xce, 0xbe, 0xac, 0xac, 0x60, 0xa4, - 0x0d, 0x7c, 0x6b, 0x06, 0xdb, 0x39, 0x59, 0x88, 0x8e, 0xd3, 0x6e, 0x86, 0xe8, 0xa1, 0x2d, 0x3b, 0xfd, 0x08, 0xad, - 0x53, 0x92, 0x96, 0xfd, 0x10, 0xc1, 0xca, 0x6a, 0x9f, 0x24, 0xba, 0x97, 0x46, 0xc0, 0xae, 0x5f, 0x65, 0x49, 0x2c, - 0x48, 0xa3, 0xff, 0xcc, 0xbc, 0xd2, 0x8d, 0x08, 0x0f, 0x6b, 0xc8, 0x00, 0x36, 0xc4, 0xea, 0x1e, 0xbb, 0x29, 0x2c, - 0xbc, 0xb5, 0x29, 0xd0, 0x99, 0x66, 0x8e, 0x06, 0x01, 0xdb, 0xcb, 0x7d, 0x8c, 0x34, 0x94, 0x3f, 0x5b, 0x89, 0x2d, - 0x47, 0x9a, 0xe2, 0xa3, 0xff, 0x78, 0x6d, 0x9a, 0x62, 0x91, 0x3a, 0x5f, 0xac, 0x27, 0x99, 0xe0, 0xbf, 0xa9, 0x9e, - 0x13, 0xcf, 0x3e, 0x32, 0xba, 0xef, 0xbf, 0x5e, 0x47, 0x56, 0x9e, 0x4f, 0x1c, 0x5f, 0xb5, 0x32, 0x39, 0x5f, 0xb1, - 0xcd, 0x41, 0x05, 0x6c, 0x7e, 0xe0, 0xe7, 0xac, 0x70, 0x6c, 0xc8, 0x3f, 0x9a, 0xf9, 0x08, 0xe3, 0x6a, 0x85, 0xef, - 0xda, 0x8b, 0x87, 0xb6, 0x62, 0x52, 0x24, 0x2d, 0xa8, 0xa4, 0x81, 0x54, 0x23, 0x2b, 0x12, 0x64, 0x18, 0xb9, 0x40, - 0xaf, 0xf8, 0x14, 0x4f, 0xcc, 0x96, 0x24, 0x3c, 0x14, 0xdd, 0xe2, 0x19, 0xa1, 0x42, 0xf0, 0xdf, 0x07, 0x64, 0x22, - 0x90, 0x04, 0x98, 0xeb, 0x08, 0x75, 0x94, 0xc4, 0x13, 0x9e, 0x1e, 0x24, 0xe8, 0x24, 0xe8, 0xe5, 0x5b, 0x21, 0x22, - 0x2a, 0x5f, 0x7d, 0xdd, 0x24, 0x68, 0x56, 0x82, 0x10, 0xcb, 0x19, 0x4b, 0x22, 0xb8, 0xd6, 0x8c, 0xde, 0xfd, 0x88, - 0x52, 0xdd, 0x6d, 0x48, 0x63, 0xf9, 0x0f, 0x23, 0x52, 0xe5, 0x9b, 0x9f, 0x71, 0x75, 0x19, 0xed, 0x19, 0xb9, 0x0b, - 0x54, 0x68, 0xf6, 0x09, 0x19, 0xfa, 0x18, 0xab, 0x16, 0xd1, 0x07, 0xf3, 0xb6, 0xa1, 0xb8, 0xc5, 0x14, 0x9b, 0xbb, - 0xb5, 0x7e, 0xce, 0x7e, 0xcc, 0x1f, 0x90, 0x50, 0x9e, 0x0a, 0x38, 0xc4, 0xc4, 0x2f, 0xc2, 0x06, 0x7d, 0x38, 0xef, - 0xd5, 0x48, 0x75, 0x7f, 0xbf, 0xed, 0xc3, 0x3c, 0x16, 0xe5, 0x27, 0xd4, 0xf6, 0x0c, 0x28, 0xa8, 0x94, 0x51, 0xa0, - 0xd6, 0x80, 0xb1, 0x0b, 0x4e, 0xe4, 0xfc, 0x34, 0x2c, 0x00, 0xea, 0x2b, 0x56, 0x4d, 0x31, 0x18, 0x23, 0x18, 0xe9, - 0x36, 0xc0, 0x0e, 0xa9, 0xd3, 0xc2, 0xc1, 0xbc, 0xfe, 0xf3, 0xa5, 0x0b, 0x0b, 0x84, 0x82, 0x37, 0xc9, 0xd2, 0x9a, - 0x29, 0xf4, 0x13, 0x04, 0xa6, 0xe0, 0x53, 0x79, 0xd4, 0x93, 0x78, 0xdf, 0x3f, 0x5f, 0x57, 0x89, 0x14, 0xf8, 0xb9, - 0xf0, 0x86, 0x08, 0x2b, 0xa6, 0x88, 0x79, 0xc4, 0x67, 0xd6, 0x92, 0x7d, 0xe1, 0x7d, 0xeb, 0x81, 0x3a, 0x05, 0x3c, - 0x73, 0xdf, 0x27, 0xf7, 0x42, 0xe0, 0x0f, 0x57, 0x1f, 0x3e, 0x99, 0x1f, 0xcd, 0x80, 0x55, 0x3d, 0xb2, 0x98, 0x84, - 0xa9, 0x28, 0xb3, 0x84, 0x20, 0x6e, 0x2a, 0x81, 0x85, 0x61, 0x5c, 0x8d, 0x9b, 0x8f, 0x75, 0xeb, 0x29, 0x13, 0x00, - 0x6a, 0x49, 0x42, 0xf7, 0x0c, 0x65, 0xcc, 0xec, 0xa5, 0x15, 0xa0, 0xdc, 0x73, 0x75, 0xf2, 0x72, 0x68, 0x8f, 0x61, - 0xe0, 0x50, 0xb6, 0x36, 0x98, 0xc6, 0x89, 0xc8, 0x32, 0x10, 0x20, 0x0e, 0xe5, 0xd7, 0xb9, 0xd2, 0xba, 0xea, 0x46, - 0x4c, 0x5d, 0x87, 0x7a, 0x3b, 0x47, 0xc7, 0x42, 0xdc, 0xfb, 0x99, 0x1e, 0x01, 0xb6, 0xd3, 0xf7, 0xf2, 0x03, 0x27, - 0x15, 0x02, 0xaf, 0x84, 0xca, 0x03, 0x89, 0xec, 0x81, 0x76, 0x50, 0x36, 0x00, 0x92, 0xdc, 0x16, 0x57, 0x0a, 0xd2, - 0x16, 0x20, 0x66, 0x36, 0xfe, 0xa7, 0x1f, 0x34, 0x8a, 0x03, 0xf2, 0xbe, 0x0f, 0x92, 0x92, 0xc6, 0xb3, 0x50, 0x6d, - 0x9c, 0x48, 0x11, 0xcc, 0xe0, 0x61, 0x11, 0x34, 0x22, 0x53, 0xa1, 0x73, 0x2b, 0xd8, 0xc6, 0xef, 0x5e, 0x9b, 0x47, - 0xa2, 0xc2, 0xf4, 0x37, 0xff, 0x74, 0x65, 0xdd, 0xa2, 0x48, 0xcb, 0xef, 0x71, 0xdd, 0xc7, 0xf8, 0xff, 0x06, 0x45, - 0x49, 0x92, 0xcd, 0x5e, 0x2a, 0x99, 0xce, 0xd8, 0xf3, 0x2b, 0xad, 0x8f, 0x16, 0xed, 0x81, 0x7d, 0xc3, 0x7b, 0xd0, - 0xdc, 0x03, 0xe1, 0x87, 0x92, 0x56, 0x9b, 0xfa, 0x84, 0xaa, 0x0a, 0x32, 0x24, 0x1a, 0xe3, 0x22, 0xb5, 0xa6, 0x4c, - 0xb5, 0x5b, 0xec, 0x06, 0x90, 0x4c, 0x63, 0x54, 0xd1, 0xe4, 0xbe, 0x79, 0x66, 0xf3, 0xc2, 0x3d, 0x91, 0x46, 0xd3, - 0x05, 0xb9, 0xfc, 0x2c, 0x39, 0xca, 0x94, 0x92, 0x25, 0xb1, 0x0c, 0x87, 0xf3, 0x10, 0x61, 0xae, 0x35, 0x44, 0x54, - 0x2a, 0x8c, 0x37, 0x4c, 0x4a, 0x13, 0x2b, 0xf9, 0x2d, 0x4a, 0x84, 0x45, 0xb0, 0xfa, 0xb4, 0xad, 0x03, 0x5c, 0x9b, - 0x83, 0x72, 0x84, 0x7b, 0xcb, 0x13, 0x6c, 0x6a, 0x9d, 0x07, 0xe7, 0x51, 0xae, 0x8a, 0x43, 0xa1, 0x4e, 0xdb, 0x07, - 0x54, 0xde, 0x44, 0xe8, 0x0c, 0x99, 0xb0, 0x35, 0x1e, 0x63, 0x90, 0x1b, 0x8f, 0x37, 0xd1, 0x0d, 0xcd, 0x87, 0x89, - 0x8a, 0xfa, 0x44, 0x5e, 0x26, 0xa0, 0xaa, 0xde, 0xa4, 0xf7, 0x53, 0xf2, 0xd3, 0x28, 0xa2, 0xc8, 0x9d, 0xe4, 0x84, - 0xca, 0x5a, 0x12, 0x15, 0x05, 0xb6, 0xf0, 0x24, 0x09, 0x09, 0xa0, 0xb8, 0x1b, 0xe3, 0x50, 0x85, 0xfc, 0xae, 0xca, - 0xe1, 0x5d, 0x8f, 0xea, 0xd0, 0xd2, 0x25, 0x90, 0xe4, 0x67, 0x32, 0xe9, 0x8f, 0x79, 0xef, 0x3e, 0x93, 0x87, 0xf7, - 0x23, 0x85, 0xb9, 0x8f, 0xf1, 0x1a, 0x66, 0x21, 0x2e, 0xff, 0xf6, 0xf3, 0xa2, 0x17, 0x1f, 0x25, 0x9d, 0x20, 0x33, - 0x54, 0xae, 0x8d, 0xf7, 0x4d, 0x23, 0x52, 0x55, 0xd4, 0x42, 0x20, 0x9f, 0xdc, 0xfd, 0x7a, 0x06, 0xa5, 0x8c, 0xe6, - 0x72, 0xaa, 0x5e, 0x27, 0xe5, 0x36, 0x7e, 0x18, 0x1a, 0xa2, 0xd7, 0xe5, 0x68, 0x53, 0xc0, 0x12, 0x6d, 0xf3, 0xf0, - 0xcf, 0x07, 0xab, 0xc8, 0x97, 0xe3, 0xa6, 0xd8, 0xa7, 0x8a, 0xc5, 0x9c, 0x7b, 0x7f, 0xb7, 0xc6, 0x03, 0x61, 0x7f, - 0x4a, 0x22, 0x99, 0x08, 0x02, 0x92, 0xb2, 0x05, 0x9e, 0x81, 0x43, 0x29, 0x5d, 0x9a, 0xa8, 0x35, 0x38, 0x94, 0xd4, - 0x9c, 0x7d, 0x4f, 0x2a, 0x9f, 0x3e, 0x2f, 0x11, 0x7e, 0x65, 0x5e, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xc7, - 0x12, 0x2d, 0x80, 0x5a, 0xa8, 0x0b, 0x75, 0x53, 0x01, 0xc1, 0xf8, 0x5a, 0xef, 0x0f, 0x91, 0x51, 0x85, 0xe2, 0x29, - 0x4a, 0xe9, 0x68, 0x97, 0xaf, 0xb8, 0x7d, 0xe9, 0x84, 0x29, 0x7c, 0xc3, 0x11, 0x47, 0xe4, 0x99, 0xee, 0x9b, 0x76, - 0xb9, 0x69, 0x45, 0xff, 0x80, 0x08, 0xf1, 0x6e, 0xbe, 0xd4, 0xb9, 0x31, 0x39, 0x82, 0x2b, 0x82, 0x66, 0x8b, 0x83, - 0xa7, 0xf2, 0x0f, 0xd7, 0x65, 0x21, 0x5d, 0x13, 0xe5, 0x48, 0x22, 0x3f, 0x64, 0x06, 0x5a, 0x01, 0x89, 0x35, 0x61, - 0x44, 0x0e, 0x66, 0x0b, 0x00, 0xbd, 0x36, 0x47, 0xb7, 0xda, 0xa8, 0x2e, 0x5b, 0x00, 0x5b, 0xfa, 0x0a, 0x46, 0x86, - 0x42, 0xe8, 0x88, 0xe1, 0x40, 0x46, 0xd4, 0x27, 0x95, 0x81, 0x2c, 0x3a, 0xc7, 0x02, 0x94, 0x79, 0x9f, 0x82, 0xbc, - 0x71, 0x12, 0x25, 0x24, 0x8d, 0x33, 0xf3, 0x49, 0x9d, 0x9d, 0x94, 0x83, 0xac, 0xa5, 0x90, 0x9e, 0x54, 0x37, 0xa8, - 0x5c, 0x2b, 0x7a, 0x25, 0xf4, 0x50, 0x72, 0x27, 0x36, 0x83, 0xd7, 0x5c, 0x19, 0xc5, 0x2f, 0x2d, 0xff, 0x32, 0xa1, - 0x61, 0x51, 0x9d, 0x40, 0x07, 0x7a, 0x09, 0xad, 0x21, 0xe6, 0xff, 0x5d, 0xb9, 0x77, 0x1d, 0xa4, 0x5b, 0xc7, 0x40, - 0xcb, 0x79, 0xab, 0xd4, 0xb3, 0x50, 0xd1, 0xad, 0xed, 0x99, 0xd4, 0x56, 0x15, 0x07, 0xdb, 0x98, 0x16, 0x64, 0xde, - 0xc1, 0xe7, 0x94, 0x0e, 0xa9, 0x8f, 0xb6, 0x71, 0xcd, 0x15, 0xd9, 0x83, 0xa5, 0xaf, 0xb1, 0x32, 0xa7, 0x0f, 0xc3, - 0x81, 0x17, 0x93, 0xb9, 0xb1, 0xe3, 0x6f, 0x84, 0x55, 0x2b, 0xd5, 0x46, 0xc4, 0xec, 0x10, 0x60, 0xaa, 0x1a, 0x8d, - 0x35, 0xef, 0xc3, 0x64, 0xa1, 0x9f, 0x65, 0xae, 0x00, 0xe5, 0x88, 0x49, 0xbd, 0xb2, 0xec, 0x85, 0xd6, 0x83, 0xef, - 0x97, 0x57, 0x57, 0xb2, 0xec, 0x5a, 0xa7, 0x87, 0xc0, 0x09, 0xe0, 0x4d, 0x41, 0xd5, 0x1a, 0x2f, 0xee, 0xdb, 0x0b, - 0xaf, 0xad, 0x0b, 0x52, 0x12, 0xf0, 0x8e, 0x92, 0xc1, 0x57, 0x9e, 0x06, 0x82, 0xe6, 0x7b, 0xe5, 0x7e, 0x62, 0x46, - 0x24, 0x72, 0xc7, 0xed, 0x19, 0x1f, 0xcf, 0xc3, 0x95, 0xa1, 0xf8, 0x65, 0x6c, 0x4d, 0x6b, 0x81, 0xf9, 0x83, 0x04, - 0x96, 0x13, 0xb5, 0x5b, 0x9f, 0x8b, 0x79, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x23, 0x54, 0x0c, 0x27, 0x81, 0xa2, 0x91, - 0x16, 0x98, 0xc3, 0x58, 0xe7, 0x70, 0x0b, 0x08, 0xa9, 0x53, 0x20, 0xe8, 0x6f, 0x47, 0x02, 0x8c, 0xfc, 0x41, 0x91, - 0x13, 0x4f, 0x9a, 0x9b, 0x35, 0x08, 0xfc, 0x7d, 0x38, 0x54, 0xa7, 0xed, 0xe5, 0x27, 0xdc, 0x81, 0x9b, 0xd8, 0x33, - 0x8e, 0x9f, 0xc5, 0xfd, 0x26, 0x27, 0x91, 0x73, 0x28, 0xaa, 0xf2, 0x39, 0x87, 0xc4, 0x4c, 0x1c, 0xea, 0x70, 0xfb, - 0x20, 0x5d, 0x5b, 0xc0, 0x70, 0x71, 0x98, 0xc6, 0x5e, 0x1d, 0x25, 0x20, 0x95, 0x7c, 0x74, 0x37, 0x9f, 0x7e, 0xf6, - 0x51, 0x3d, 0x88, 0xf6, 0x21, 0xe2, 0x6f, 0x6d, 0x49, 0xa3, 0x50, 0x79, 0x38, 0xb7, 0xbe, 0xa4, 0x86, 0x8f, 0x10, - 0x87, 0x7f, 0x2f, 0x16, 0xc5, 0x40, 0xec, 0x36, 0xb9, 0xe6, 0x82, 0x41, 0xef, 0x24, 0x03, 0xa1, 0xf5, 0x66, 0x98, - 0xca, 0x55, 0xb3, 0x2d, 0xac, 0x4c, 0x3b, 0x83, 0x0f, 0x36, 0xb6, 0xc5, 0x09, 0x08, 0xa2, 0x95, 0x41, 0xb7, 0x84, - 0x09, 0x4b, 0x8c, 0x29, 0xf4, 0x2d, 0x31, 0xcc, 0x79, 0x16, 0x95, 0xc4, 0x02, 0x4c, 0x47, 0x6b, 0xb6, 0xf4, 0x2b, - 0xa6, 0x2b, 0x9d, 0x89, 0xde, 0xb4, 0x41, 0xa6, 0x92, 0x66, 0x16, 0xc0, 0xdf, 0x64, 0x67, 0xd9, 0xe0, 0x1f, 0xd0, - 0xda, 0x95, 0x22, 0x31, 0x21, 0xdd, 0x82, 0x17, 0x95, 0x95, 0x9a, 0x37, 0x2e, 0x94, 0xfb, 0x35, 0xdf, 0xb4, 0xad, - 0x15, 0x82, 0xc3, 0x3a, 0x24, 0x1f, 0x58, 0x80, 0xe5, 0x72, 0x29, 0x2e, 0x55, 0x3b, 0x82, 0xa1, 0xb4, 0x95, 0xe4, - 0xc3, 0x22, 0x43, 0xd2, 0xe3, 0x13, 0x0d, 0x91, 0x90, 0x33, 0x9e, 0xb3, 0x35, 0xe0, 0xe4, 0xee, 0xce, 0x6a, 0xa6, - 0xf5, 0xa7, 0xdd, 0x78, 0xcf, 0x4b, 0x10, 0x93, 0x66, 0x0a, 0xbc, 0x27, 0xbb, 0x81, 0xb4, 0xdb, 0x2c, 0x36, 0xfa, - 0x9b, 0x6e, 0x69, 0x80, 0xee, 0xb6, 0x83, 0x01, 0x0c, 0x8c, 0x30, 0x0b, 0x2e, 0xbc, 0xa0, 0x6b, 0xff, 0xe0, 0x18, - 0xf0, 0x48, 0x81, 0xb3, 0x62, 0x48, 0x19, 0xe2, 0x6e, 0x6c, 0xf3, 0x63, 0xb6, 0x58, 0xbc, 0xfe, 0xfa, 0x3d, 0x32, - 0xa0, 0x2e, 0x70, 0x04, 0x1f, 0x68, 0x19, 0xa9, 0x34, 0x70, 0x4a, 0x2a, 0x3f, 0xda, 0x3b, 0x93, 0x6c, 0x65, 0x6a, - 0x85, 0xb0, 0xaa, 0x06, 0x9b, 0x1a, 0xd0, 0x66, 0x96, 0x96, 0xb6, 0xa5, 0x16, 0x98, 0xdb, 0xde, 0x0b, 0x30, 0xf9, - 0x02, 0x7a, 0xc0, 0xf2, 0x9f, 0xa1, 0x7b, 0x18, 0x4d, 0x2c, 0xe3, 0x5e, 0x10, 0x17, 0x55, 0x10, 0x40, 0x7a, 0x5b, - 0x8f, 0x20, 0x69, 0x5a, 0x63, 0xa2, 0xc3, 0xa2, 0xbb, 0x11, 0xb0, 0x0a, 0x2d, 0x31, 0x02, 0x7b, 0xc8, 0x8d, 0xa9, - 0x58, 0x3a, 0xf2, 0xab, 0x05, 0x16, 0x3e, 0x0f, 0x62, 0x5f, 0x93, 0xae, 0x97, 0xa5, 0x06, 0x62, 0xf2, 0x68, 0xeb, - 0x8d, 0x7e, 0x48, 0x8f, 0x76, 0x5d, 0xe3, 0x7d, 0xd4, 0x44, 0x60, 0x65, 0x2a, 0xb7, 0x87, 0xd9, 0x76, 0xfd, 0xd5, - 0x92, 0x02, 0xd5, 0xcc, 0x59, 0x16, 0xfe, 0xf6, 0xfe, 0x69, 0x3f, 0x01, 0x2e, 0xdf, 0xf1, 0xae, 0xe7, 0x80, 0xb0, - 0x1c, 0x9d, 0x55, 0x72, 0xdd, 0x6e, 0x6b, 0xff, 0x33, 0x3e, 0x34, 0x86, 0x92, 0x61, 0xfb, 0x9f, 0xee, 0x4e, 0xd7, - 0x23, 0x15, 0x0e, 0xa3, 0xc0, 0x51, 0xf8, 0xde, 0x7b, 0xcf, 0xab, 0x95, 0x3a, 0xce, 0xb2, 0x5f, 0xfb, 0xd6, 0xd4, - 0xeb, 0x64, 0x1b, 0xd6, 0x28, 0xbe, 0x1d, 0x23, 0x1b, 0x7b, 0xc1, 0xc8, 0xda, 0x18, 0xab, 0x7b, 0x04, 0x6b, 0x8f, - 0x6b, 0x8a, 0xe1, 0x6e, 0x05, 0xdf, 0x6f, 0xf7, 0xb8, 0x96, 0xd3, 0x39, 0xdd, 0x99, 0x6f, 0xdb, 0x2f, 0x7f, 0x72, - 0x96, 0x16, 0x1e, 0x34, 0x6f, 0xca, 0x65, 0x96, 0x2e, 0xab, 0xe4, 0x5a, 0x20, 0x4f, 0x36, 0x9d, 0x8b, 0x7a, 0xfd, - 0x79, 0xaf, 0x11, 0x66, 0xb0, 0x77, 0x17, 0xf1, 0xf6, 0x3e, 0xba, 0x9b, 0xcb, 0xa9, 0xcf, 0xbb, 0x45, 0x43, 0x08, - 0xe5, 0xe6, 0x95, 0xd3, 0xd6, 0x1b, 0xc7, 0x1c, 0x0f, 0xf8, 0xb0, 0x78, 0xef, 0x90, 0x13, 0x42, 0x6d, 0xf0, 0xeb, - 0x09, 0xee, 0x3e, 0xc4, 0x93, 0x6d, 0x7f, 0x4e, 0xdc, 0xe6, 0x0c, 0x11, 0xb6, 0xc8, 0xc3, 0xd2, 0x94, 0x74, 0x5c, - 0x03, 0x1b, 0xee, 0xce, 0x0a, 0x99, 0xb9, 0xf8, 0x95, 0xfb, 0xc6, 0x2d, 0x1c, 0x7d, 0x4f, 0xc8, 0x21, 0xcb, 0x32, - 0x6d, 0xde, 0x82, 0xbe, 0xb0, 0x99, 0xe5, 0x69, 0x1a, 0x93, 0xe5, 0x0f, 0x23, 0xdc, 0x15, 0x72, 0xd7, 0x5c, 0x45, - 0xcb, 0x69, 0x96, 0x8a, 0xba, 0x67, 0x1c, 0xb7, 0x38, 0xe3, 0x20, 0xbe, 0x07, 0x33, 0xfd, 0x7e, 0x8d, 0x6c, 0x68, - 0x5e, 0xfb, 0x07, 0x9e, 0x65, 0xe0, 0xf4, 0x5f, 0x6d, 0x54, 0xa7, 0x72, 0x9e, 0x03, 0xa0, 0x64, 0x89, 0xfe, 0x74, - 0x1c, 0xd2, 0x86, 0x42, 0x18, 0x15, 0xee, 0xbe, 0xfc, 0x68, 0x6f, 0x79, 0x15, 0x13, 0xd1, 0x1e, 0x3d, 0xe9, 0xce, - 0x08, 0x57, 0xc4, 0x5b, 0x46, 0x03, 0x28, 0xc6, 0x82, 0x0e, 0x14, 0x52, 0x56, 0x7b, 0x34, 0x67, 0x43, 0x9c, 0x79, - 0x9e, 0x54, 0x91, 0x2e, 0x02, 0xd6, 0x77, 0xc5, 0xa1, 0x9e, 0xdc, 0xab, 0xc0, 0xcb, 0xbe, 0x60, 0x1d, 0xea, 0x01, - 0xdc, 0x6f, 0x8a, 0x14, 0x1f, 0x69, 0xeb, 0x97, 0x5c, 0x31, 0xba, 0xb6, 0x4a, 0xc6, 0xfa, 0x6e, 0x8c, 0x68, 0xc4, - 0xe4, 0xaa, 0x26, 0x2c, 0xa7, 0x31, 0x8a, 0x46, 0x81, 0xe4, 0x9c, 0x1a, 0xc7, 0x38, 0x1d, 0x58, 0x4f, 0x22, 0x29, - 0x5d, 0x40, 0xc8, 0x2c, 0xc9, 0xf4, 0xa0, 0x01, 0x96, 0x64, 0xa4, 0x0d, 0x2a, 0xef, 0xa1, 0xa3, 0x71, 0xcf, 0x32, - 0x68, 0xee, 0x50, 0x57, 0x15, 0xae, 0xdd, 0xf2, 0x20, 0x53, 0x31, 0xb7, 0x66, 0x53, 0xfd, 0xb8, 0x1c, 0x44, 0x76, - 0x4d, 0xbb, 0x76, 0xdb, 0x67, 0x03, 0x2a, 0xb8, 0x81, 0x0c, 0x07, 0x29, 0xfb, 0x90, 0xd1, 0x23, 0x72, 0x67, 0x49, - 0xf7, 0xf9, 0x81, 0x42, 0xbf, 0x53, 0x07, 0x04, 0x18, 0xf9, 0x4a, 0x68, 0x87, 0x0d, 0x77, 0xea, 0xd0, 0x79, 0xdb, - 0x63, 0x22, 0x47, 0xe1, 0xf0, 0x2a, 0x49, 0xdf, 0x13, 0x6d, 0x47, 0x37, 0xee, 0xfb, 0xe3, 0x80, 0x9f, 0x94, 0xa6, - 0x88, 0x5a, 0x93, 0xd4, 0xe9, 0x62, 0xb9, 0x25, 0x9a, 0x0c, 0xfd, 0x8d, 0xe2, 0xb3, 0xe0, 0xc2, 0xc3, 0x12, 0xb7, - 0x1b, 0x0a, 0x5c, 0x89, 0xab, 0x72, 0x1f, 0x5f, 0x09, 0x68, 0x5c, 0x27, 0xe8, 0xfa, 0x8c, 0xa3, 0x3a, 0x18, 0x43, - 0x25, 0x66, 0x6f, 0xb0, 0x82, 0xb2, 0xaa, 0x47, 0x1c, 0x63, 0xeb, 0x67, 0x34, 0x37, 0x1e, 0x63, 0xd2, 0xb8, 0x9c, - 0x71, 0x44, 0xfa, 0xc8, 0x8c, 0x54, 0x86, 0x29, 0xbc, 0x3d, 0x72, 0x74, 0xa7, 0x76, 0xd3, 0xe5, 0x82, 0x66, 0x8c, - 0xca, 0xa0, 0x5f, 0xbc, 0x84, 0xd9, 0xc2, 0x12, 0x3c, 0x88, 0xab, 0x8b, 0x73, 0x6b, 0x17, 0x1f, 0x1d, 0x2a, 0xcc, - 0xc7, 0x36, 0x9f, 0x2f, 0x53, 0x45, 0xae, 0x84, 0x61, 0xea, 0xa7, 0xe9, 0xc5, 0x75, 0xa7, 0x92, 0xf6, 0x8b, 0xb0, - 0xfa, 0x9a, 0x19, 0x0f, 0xd8, 0x77, 0xdb, 0x10, 0x6d, 0xbf, 0x2f, 0x59, 0xaf, 0x2b, 0x53, 0x69, 0x7f, 0x6c, 0xee, - 0xd6, 0x64, 0xb7, 0xdb, 0x69, 0xdf, 0xa1, 0x13, 0x65, 0x90, 0xff, 0xfe, 0xcd, 0x7e, 0xe5, 0x4b, 0x4b, 0xfd, 0xa9, - 0xd0, 0x58, 0x1e, 0xb9, 0xf9, 0xb5, 0x1b, 0x55, 0x1d, 0x36, 0x94, 0xbb, 0x4e, 0xc7, 0xc8, 0x9d, 0x7d, 0x35, 0xd1, - 0xc4, 0x37, 0x4f, 0xf7, 0x73, 0xb1, 0xdc, 0x5f, 0x7d, 0xb4, 0xb7, 0x8f, 0xa4, 0x5c, 0xa4, 0x7c, 0xc9, 0x5e, 0xf3, - 0x94, 0xed, 0x22, 0x95, 0x11, 0xa0, 0x8c, 0xde, 0x48, 0x6f, 0x12, 0x9a, 0x26, 0xa9, 0x46, 0xfe, 0xe4, 0xf7, 0xf0, - 0xad, 0xba, 0x7b, 0xfd, 0x93, 0xa5, 0xbd, 0x13, 0x22, 0x1e, 0x00, 0xfe, 0x5b, 0xbe, 0xfd, 0xa9, 0xd8, 0xcd, 0x5c, - 0x56, 0x5b, 0x3e, 0xf0, 0xad, 0xb0, 0xaf, 0x8c, 0x87, 0x7e, 0x25, 0x55, 0x94, 0x7e, 0x95, 0x70, 0x89, 0x91, 0xb1, - 0xc9, 0x47, 0x75, 0xd3, 0x7a, 0xdc, 0x7b, 0x7d, 0x47, 0x00, 0x45, 0xf8, 0xc7, 0xc2, 0x18, 0xef, 0x21, 0x51, 0x38, - 0x15, 0x62, 0x98, 0x96, 0x9a, 0xca, 0x01, 0xd8, 0x34, 0xfa, 0x35, 0x8a, 0x53, 0xa9, 0xc8, 0x8f, 0xdf, 0x1f, 0x59, - 0xf9, 0xcd, 0x6d, 0xfe, 0xff, 0xdb, 0xcf, 0xde, 0x23, 0x14, 0x5a, 0x40, 0xd2, 0x7d, 0x14, 0xc9, 0x27, 0x11, 0xa8, - 0xb4, 0x72, 0x58, 0x8d, 0xb5, 0x1d, 0x24, 0x5a, 0x35, 0xad, 0xea, 0xc3, 0x17, 0x8f, 0xa1, 0xa7, 0x68, 0xa6, 0x14, - 0x51, 0xa9, 0xf2, 0x06, 0x09, 0xa1, 0x9e, 0xc6, 0xa7, 0x89, 0x4a, 0x85, 0xfc, 0x72, 0xb3, 0xfe, 0xe9, 0x8e, 0x49, - 0x10, 0x96, 0x73, 0x60, 0x88, 0xf4, 0x90, 0x3c, 0xa0, 0xc2, 0xee, 0x7c, 0x4c, 0xa3, 0x3a, 0xa5, 0x4f, 0x47, 0xf0, - 0x76, 0xaa, 0x69, 0xbb, 0x56, 0x5e, 0xcb, 0x2e, 0x91, 0x50, 0x82, 0xfb, 0x48, 0x33, 0x87, 0x0e, 0x1a, 0xa5, 0xa3, - 0xfb, 0xde, 0x3f, 0x09, 0x19, 0xba, 0xc0, 0xd0, 0xfb, 0xed, 0x03, 0x3f, 0xb6, 0xd5, 0xa0, 0xc7, 0x70, 0xd1, 0xb6, - 0xe8, 0x55, 0x5f, 0x16, 0x5d, 0x26, 0xb7, 0x97, 0xa2, 0x01, 0x92, 0x64, 0x7a, 0x16, 0x44, 0xe6, 0x7e, 0x21, 0x67, - 0x1d, 0xcf, 0x4f, 0x71, 0x2f, 0x1e, 0x53, 0x25, 0xa3, 0x1b, 0xfe, 0xea, 0x34, 0xf2, 0xbd, 0x89, 0xc4, 0xc7, 0x24, - 0x16, 0x92, 0x6d, 0x8c, 0xa0, 0xd7, 0x62, 0x78, 0x6e, 0x2c, 0xfd, 0x8d, 0x28, 0x50, 0x1a, 0x04, 0x58, 0x3a, 0x8f, - 0x94, 0x81, 0x2b, 0x36, 0xca, 0xdf, 0x6d, 0x68, 0x98, 0x52, 0x9b, 0x07, 0x44, 0xde, 0x65, 0xbf, 0x28, 0x32, 0xde, - 0x40, 0x24, 0x08, 0x46, 0x2a, 0xb8, 0x09, 0x52, 0xd0, 0x98, 0x2e, 0x30, 0x5b, 0x40, 0xb6, 0x38, 0x6e, 0x80, 0xcb, - 0x57, 0x8a, 0xe9, 0x52, 0xf5, 0xce, 0xe6, 0xaa, 0xe2, 0xc7, 0xf0, 0xbe, 0x5b, 0xeb, 0x20, 0x3e, 0x38, 0x11, 0x74, - 0x45, 0x69, 0xd2, 0xd3, 0x47, 0x26, 0xc9, 0x5a, 0x94, 0x2d, 0x46, 0x0f, 0x1a, 0x06, 0x2a, 0x2a, 0xac, 0x36, 0xd6, - 0x28, 0xf6, 0x2b, 0xba, 0x20, 0x8c, 0xc2, 0x17, 0xed, 0xc6, 0xc8, 0x7b, 0x97, 0x66, 0x5e, 0xbb, 0x1b, 0x47, 0xad, - 0xc8, 0x8b, 0x63, 0x5e, 0x73, 0x14, 0xd9, 0x1d, 0x26, 0x79, 0xfc, 0x55, 0x11, 0x05, 0xc3, 0x64, 0x64, 0x7b, 0xec, - 0xdb, 0x22, 0x33, 0x11, 0x22, 0xb6, 0x7e, 0xeb, 0x9d, 0x7d, 0x1b, 0x85, 0xb8, 0xe7, 0x23, 0xe1, 0xfe, 0x92, 0xe4, - 0x2a, 0xe0, 0x65, 0x5e, 0x73, 0xe8, 0x37, 0xe6, 0xd4, 0x50, 0xa9, 0xd1, 0x10, 0xf0, 0x2b, 0x95, 0x78, 0x40, 0x26, - 0xa8, 0x9c, 0xd8, 0x75, 0x1f, 0x5c, 0x46, 0x40, 0x87, 0xcb, 0xda, 0x68, 0xe6, 0xd3, 0xf7, 0xc8, 0xb5, 0x9d, 0xd6, - 0x47, 0x1a, 0x51, 0xe0, 0xe5, 0x56, 0x65, 0x70, 0xa0, 0x4f, 0xa5, 0xac, 0xbc, 0x20, 0x8a, 0x4e, 0xb4, 0x15, 0x1c, - 0x16, 0xb7, 0xc1, 0xbf, 0x47, 0x58, 0x2c, 0xb9, 0xe7, 0xb8, 0x01, 0xc8, 0x39, 0x8b, 0xc8, 0x46, 0x05, 0xf1, 0xef, - 0x00, 0x3b, 0x32, 0xe6, 0x1a, 0xc9, 0xb2, 0x86, 0xa9, 0x88, 0xb6, 0xf7, 0x11, 0x91, 0x6e, 0x87, 0x0b, 0x73, 0x8a, - 0x5e, 0x8c, 0x6f, 0x9b, 0x55, 0xb4, 0xe0, 0x01, 0xaa, 0xe0, 0xf3, 0x59, 0x70, 0x88, 0x95, 0x5f, 0xe1, 0xbe, 0xd9, - 0x10, 0x4d, 0xe0, 0x3c, 0x99, 0x07, 0x9d, 0x8b, 0x76, 0x22, 0xd7, 0xcf, 0x15, 0xb9, 0x97, 0xe4, 0x1b, 0x58, 0xaf, - 0x2c, 0xdd, 0x37, 0x8b, 0x79, 0x1a, 0x58, 0x81, 0x7e, 0x58, 0x84, 0x34, 0x70, 0x56, 0x99, 0xce, 0x3a, 0x7a, 0xaa, - 0x79, 0x22, 0x10, 0x12, 0xc0, 0x02, 0x03, 0x29, 0xfd, 0x35, 0xec, 0xde, 0x47, 0xa0, 0x11, 0xec, 0x14, 0x98, 0x61, - 0xde, 0x4f, 0x24, 0x0d, 0x6d, 0x53, 0xf5, 0x23, 0x1d, 0xd8, 0xbd, 0xb2, 0x57, 0xd8, 0x40, 0x07, 0xcb, 0xdf, 0xe7, - 0xdc, 0xf0, 0xd2, 0xdd, 0x7c, 0xfb, 0x57, 0x89, 0xd4, 0x72, 0x6d, 0xb5, 0xc0, 0xbf, 0x13, 0xeb, 0x73, 0x21, 0xc8, - 0x3e, 0xef, 0xcb, 0x08, 0x2b, 0x6a, 0x1c, 0x35, 0x9f, 0xb5, 0x17, 0xb5, 0xfc, 0x59, 0x09, 0x08, 0xce, 0xbd, 0x25, - 0xf1, 0x6e, 0x08, 0x1e, 0x77, 0x2e, 0xc9, 0xde, 0xd0, 0xe3, 0x49, 0x1f, 0xb2, 0xf2, 0xb1, 0x83, 0xd9, 0x42, 0x26, - 0xf3, 0x1d, 0x2a, 0x8a, 0x03, 0xf1, 0x46, 0x29, 0x3c, 0xc7, 0xdf, 0xcd, 0xd2, 0x04, 0x29, 0x79, 0xa5, 0xbf, 0x15, - 0x6f, 0x8c, 0x30, 0x1f, 0x63, 0x03, 0x07, 0xa3, 0x00, 0x91, 0xbf, 0x45, 0x83, 0x2a, 0x94, 0x70, 0xb4, 0x10, 0xa7, - 0xa1, 0xea, 0x25, 0x62, 0xdf, 0x95, 0x0f, 0xd5, 0xec, 0xab, 0x7e, 0xa2, 0x4e, 0xd7, 0x99, 0xb5, 0x37, 0x08, 0x85, - 0x6e, 0xb3, 0x5b, 0x6f, 0x32, 0x86, 0x2c, 0xda, 0x86, 0xd3, 0xf1, 0xf8, 0xfb, 0x73, 0xb3, 0x7c, 0xac, 0xd3, 0xec, - 0x5f, 0x2e, 0x0f, 0x48, 0xb5, 0xea, 0x8e, 0x7d, 0x3f, 0x2b, 0xfb, 0xc9, 0x7f, 0x1f, 0x53, 0x5d, 0xc6, 0xd3, 0xbd, - 0x12, 0x80, 0x8f, 0x45, 0x94, 0xa7, 0x17, 0x11, 0x9a, 0xab, 0xf9, 0x4e, 0xfd, 0x95, 0x3c, 0xe2, 0xab, 0xd7, 0xee, - 0x1f, 0xf9, 0xa0, 0x96, 0xd3, 0x55, 0x01, 0x19, 0x32, 0xe2, 0x71, 0xff, 0x55, 0xc8, 0x68, 0xd5, 0x5c, 0x5f, 0xcc, - 0x51, 0xf4, 0xdc, 0xf9, 0x7b, 0xd3, 0x90, 0x4d, 0x2f, 0x45, 0x4f, 0x98, 0x0f, 0xd4, 0xc8, 0x6d, 0x20, 0xe8, 0x26, - 0xdc, 0xe0, 0x74, 0x47, 0xaa, 0x4e, 0x56, 0x8c, 0x2e, 0x17, 0xbf, 0x4f, 0xcf, 0x22, 0xa5, 0xbe, 0x4c, 0x2d, 0x14, - 0xaa, 0x7d, 0x1f, 0x6a, 0x47, 0xc7, 0x55, 0x21, 0x6f, 0x82, 0x07, 0xc5, 0xd9, 0x12, 0x16, 0x6d, 0x54, 0x4e, 0x14, - 0x48, 0x32, 0xac, 0x16, 0x19, 0x37, 0x9f, 0x94, 0xac, 0x21, 0x43, 0x9d, 0x99, 0x23, 0xd0, 0x1c, 0x62, 0xa7, 0x62, - 0x28, 0xe9, 0xfd, 0x65, 0x06, 0x0a, 0x33, 0x44, 0xfb, 0x81, 0x01, 0x7a, 0xe5, 0x3e, 0x9a, 0x5b, 0xe6, 0xe4, 0x62, - 0x5c, 0x76, 0x09, 0xc4, 0x33, 0x8c, 0xbd, 0x6f, 0x91, 0x08, 0xda, 0xc9, 0x3b, 0x2a, 0x0d, 0xbe, 0x98, 0xee, 0x98, - 0x40, 0x72, 0x42, 0xce, 0x99, 0x31, 0x7d, 0xc5, 0x7f, 0xcd, 0xf5, 0xe4, 0xe4, 0x4d, 0x52, 0x1e, 0x57, 0x8f, 0xf0, - 0xdb, 0xb5, 0xf6, 0x2d, 0x72, 0x1f, 0x8c, 0x34, 0x55, 0x4b, 0x7e, 0x5b, 0x2a, 0xc8, 0x12, 0x16, 0x6e, 0xac, 0x7e, - 0xea, 0xca, 0x2e, 0x64, 0xb7, 0xba, 0xf0, 0xdc, 0x36, 0x2f, 0x6b, 0xf4, 0xfb, 0x66, 0xef, 0xa1, 0xbd, 0x75, 0x05, - 0xea, 0x55, 0x6d, 0x40, 0xa5, 0xce, 0xfd, 0xd1, 0xfc, 0xf6, 0x12, 0xf4, 0x4a, 0x7d, 0xf9, 0x78, 0xf0, 0x2b, 0x6a, - 0x2c, 0x62, 0xfa, 0x5b, 0xf5, 0xb7, 0x70, 0xf2, 0x84, 0x7b, 0xab, 0x5d, 0x63, 0x5d, 0x45, 0x03, 0xa1, 0xb9, 0x7b, - 0xed, 0xf9, 0xf0, 0xbe, 0x57, 0x6d, 0x75, 0x0d, 0x50, 0xbd, 0xe3, 0x9f, 0xe1, 0x5b, 0x08, 0xa7, 0x51, 0xe8, 0xee, - 0xa7, 0x16, 0x50, 0xd0, 0xe1, 0x34, 0x55, 0x01, 0x0e, 0x51, 0x5f, 0x03, 0xb4, 0xe4, 0xa7, 0xfa, 0x45, 0x42, 0xf5, - 0xf4, 0xf0, 0xe6, 0xec, 0xd3, 0xb5, 0xec, 0x90, 0x66, 0xab, 0x6d, 0xf4, 0xd3, 0xef, 0x3b, 0x87, 0xa5, 0xec, 0xa3, - 0x4a, 0xe8, 0xad, 0x8b, 0x25, 0x9e, 0x39, 0x13, 0x07, 0xcf, 0x7f, 0xe9, 0x70, 0xed, 0x9e, 0xd8, 0x72, 0xba, 0x3e, - 0xa4, 0x3d, 0x97, 0x69, 0xe4, 0x04, 0xa6, 0x34, 0x3d, 0x49, 0x64, 0x05, 0x63, 0x6a, 0x79, 0x20, 0xa3, 0xa5, 0x65, - 0x3c, 0x6f, 0x5d, 0x1a, 0x4c, 0x79, 0xfd, 0xd0, 0x54, 0x7b, 0x6e, 0x93, 0x6d, 0x1d, 0xb0, 0x5e, 0x8e, 0x53, 0xf3, - 0x1f, 0x2e, 0xa1, 0x46, 0x13, 0x0b, 0x65, 0xc4, 0xda, 0x61, 0x5e, 0x58, 0x25, 0xd4, 0xb4, 0xa5, 0x54, 0x59, 0x54, - 0x39, 0xfb, 0x5c, 0xde, 0xaf, 0x1e, 0xa1, 0x83, 0xc1, 0x84, 0x04, 0xab, 0x53, 0x7d, 0xf1, 0x34, 0x28, 0x7a, 0x25, - 0x9e, 0xdf, 0x94, 0x2e, 0x37, 0x24, 0xf5, 0xb2, 0x4a, 0xe4, 0x2f, 0x55, 0xea, 0x85, 0xf5, 0x84, 0x60, 0x5e, 0x34, - 0xd3, 0x47, 0x98, 0x5b, 0xa7, 0x91, 0xd3, 0x53, 0xa9, 0x7a, 0xa3, 0xcd, 0x02, 0x21, 0x80, 0xc7, 0xa6, 0xeb, 0x76, - 0x8a, 0xe1, 0xd7, 0xfe, 0xb0, 0x3e, 0x66, 0x15, 0x6c, 0xba, 0xf6, 0x14, 0xc2, 0xc0, 0x75, 0xbd, 0x87, 0x37, 0x65, - 0xd3, 0x59, 0xad, 0xc6, 0x89, 0x38, 0x51, 0x29, 0x76, 0x7d, 0x27, 0x26, 0x33, 0x7a, 0xcf, 0xd0, 0x1f, 0x68, 0x8e, - 0x29, 0x21, 0x01, 0x50, 0x93, 0x1e, 0x3e, 0xff, 0x2d, 0xdd, 0xe5, 0xb6, 0x28, 0x86, 0x8a, 0x0d, 0xc2, 0xea, 0x6b, - 0x1d, 0x37, 0xc3, 0xbf, 0xe0, 0x97, 0x0f, 0xc1, 0x27, 0x24, 0x80, 0x2a, 0x0a, 0xfc, 0x83, 0xc1, 0x04, 0xda, 0x25, - 0xa7, 0x64, 0xed, 0x41, 0x73, 0x2b, 0xb1, 0xe2, 0x31, 0x10, 0x43, 0x7c, 0xfa, 0x20, 0x14, 0x31, 0x76, 0x43, 0xbb, - 0x3c, 0xec, 0xf8, 0x8a, 0xe5, 0x52, 0x99, 0x8f, 0xd5, 0x62, 0x49, 0xfa, 0x51, 0xf8, 0x45, 0xb1, 0x13, 0x02, 0x39, - 0x41, 0x35, 0x47, 0x7f, 0xde, 0x12, 0xc4, 0x9c, 0x9a, 0x5d, 0x7b, 0x6a, 0x02, 0xae, 0xe7, 0x30, 0x85, 0x1f, 0x65, - 0x6e, 0x7d, 0x88, 0xa7, 0x28, 0x9d, 0x4b, 0xc0, 0x3b, 0xb9, 0x2f, 0x3c, 0xd8, 0xba, 0xd4, 0x9d, 0x00, 0x1f, 0x12, - 0x88, 0x5a, 0x99, 0x3c, 0x99, 0xf8, 0x68, 0x51, 0x30, 0xe7, 0x33, 0x86, 0x9f, 0x34, 0x49, 0x29, 0xdc, 0x21, 0x3a, - 0x9b, 0x15, 0x4a, 0x3a, 0xa6, 0xd8, 0x0c, 0x90, 0x41, 0x00, 0x04, 0x96, 0x55, 0xfe, 0x40, 0xec, 0x72, 0x15, 0x16, - 0x1a, 0xb1, 0x52, 0x14, 0x84, 0x54, 0xdb, 0x81, 0x69, 0xd7, 0x75, 0xab, 0xc0, 0xb7, 0x4e, 0x38, 0x0d, 0xd7, 0x58, - 0x9e, 0x94, 0x94, 0xcc, 0xb0, 0x32, 0x14, 0x70, 0x6e, 0x25, 0xb2, 0x99, 0xaf, 0x8e, 0x04, 0x4e, 0xfe, 0x15, 0x0c, - 0x72, 0x5f, 0xca, 0xae, 0x1c, 0x80, 0xf3, 0xa9, 0x25, 0x2e, 0xed, 0xeb, 0xb9, 0x70, 0xeb, 0x24, 0x55, 0x9d, 0xad, - 0xf6, 0x60, 0x31, 0x2e, 0xba, 0xb4, 0xdb, 0x92, 0x14, 0x14, 0xe8, 0xbe, 0x78, 0x3a, 0x4d, 0x52, 0x67, 0x3a, 0x49, - 0x79, 0x2c, 0x66, 0x30, 0xb2, 0x44, 0x4b, 0xd5, 0x09, 0xf7, 0x9a, 0x86, 0x9d, 0xe5, 0x7f, 0x0a, 0x8d, 0xd4, 0x64, - 0x33, 0x9d, 0x6e, 0xba, 0x7b, 0xdf, 0xa7, 0x60, 0x31, 0xc0, 0xcf, 0xa2, 0x8a, 0x7c, 0x3a, 0x2b, 0xbb, 0x41, 0x00, - 0x52, 0x04, 0x7a, 0x88, 0xc7, 0xd3, 0xb8, 0x2b, 0x19, 0xd3, 0x04, 0xe6, 0x5b, 0x04, 0xd0, 0xd4, 0x21, 0x51, 0xc0, - 0xc6, 0xbc, 0x0d, 0x35, 0xde, 0x17, 0xd7, 0x77, 0x1e, 0xf3, 0x52, 0x0c, 0x72, 0x40, 0x6e, 0xfb, 0xce, 0x15, 0x40, - 0x38, 0x83, 0x0b, 0xc4, 0x1e, 0xda, 0x09, 0x8c, 0x63, 0xf7, 0xf9, 0x91, 0x48, 0x15, 0x27, 0xcc, 0x77, 0x8a, 0xcc, - 0x1e, 0x9e, 0x1a, 0xef, 0xd1, 0x27, 0xe5, 0x34, 0x1a, 0x3f, 0x48, 0x98, 0xdf, 0xd8, 0x8c, 0x9e, 0xeb, 0xea, 0x69, - 0xce, 0x47, 0x41, 0x74, 0x58, 0xe4, 0xde, 0xff, 0xe9, 0x00, 0x39, 0x31, 0xbe, 0x6e, 0x99, 0x28, 0x39, 0x13, 0x52, - 0x87, 0x5a, 0xd6, 0xfb, 0xd4, 0x44, 0xa5, 0x06, 0x9d, 0xdc, 0xf2, 0x1d, 0x29, 0xa2, 0x2a, 0x8b, 0x1d, 0x5f, 0xeb, - 0x1e, 0x2a, 0xe9, 0xc6, 0x55, 0x5d, 0x74, 0x5a, 0x0d, 0x4d, 0x9e, 0x6a, 0xe9, 0x29, 0x84, 0x9f, 0xfb, 0xb4, 0xa6, - 0x2d, 0x60, 0x3d, 0xff, 0xa1, 0xd0, 0x6c, 0x7e, 0x88, 0xf0, 0x60, 0xf5, 0x19, 0x4d, 0x68, 0xe1, 0xc9, 0x40, 0x76, - 0x1d, 0x70, 0x6c, 0x46, 0xf2, 0xb2, 0x2f, 0x11, 0x74, 0x2d, 0xcc, 0x32, 0x56, 0x8f, 0xb8, 0x51, 0xf6, 0x72, 0xd2, - 0x1e, 0xe9, 0x3c, 0x43, 0x06, 0xed, 0x4f, 0x1d, 0xf7, 0xf0, 0x04, 0x4e, 0x24, 0xf3, 0x30, 0xc6, 0x16, 0x91, 0xf3, - 0x1e, 0xcf, 0x58, 0x07, 0xea, 0xd1, 0x72, 0x8b, 0x78, 0x60, 0xec, 0xd9, 0x2e, 0x82, 0xd2, 0xd0, 0x82, 0x1d, 0xf6, - 0x81, 0x43, 0x20, 0x92, 0x85, 0x6e, 0x2f, 0x59, 0xef, 0x89, 0x54, 0x90, 0x7c, 0xef, 0xa4, 0x8c, 0x0a, 0x70, 0x0d, - 0x2b, 0x1c, 0x31, 0xe6, 0x99, 0xe3, 0x64, 0x30, 0xeb, 0x1e, 0x0a, 0xa5, 0xa1, 0x73, 0xf0, 0xc9, 0x5e, 0x8b, 0x9f, - 0x3f, 0x38, 0x21, 0x87, 0x08, 0x36, 0xf6, 0x12, 0x5d, 0xaa, 0x52, 0x50, 0x29, 0xc3, 0x40, 0xf3, 0xbc, 0xb5, 0x30, - 0x29, 0x48, 0x85, 0x07, 0x98, 0xf1, 0xf1, 0xe8, 0x0f, 0x6d, 0xce, 0xd5, 0x33, 0x64, 0x0e, 0xec, 0xb0, 0x64, 0x1f, - 0xe3, 0x82, 0x22, 0x48, 0xd4, 0x10, 0x26, 0xfa, 0x24, 0x57, 0x0f, 0x8a, 0xf4, 0x09, 0x45, 0xaf, 0x89, 0xd3, 0xd3, - 0x81, 0x09, 0x74, 0xce, 0x93, 0x16, 0xa2, 0x1e, 0x14, 0x95, 0xf3, 0x83, 0xdc, 0xbd, 0x50, 0x19, 0x77, 0x70, 0x92, - 0x4b, 0x4a, 0xd7, 0x36, 0xf3, 0xfe, 0x46, 0xdb, 0xdb, 0xf3, 0x96, 0x54, 0x07, 0x9d, 0x24, 0x31, 0x87, 0x0a, 0xbc, - 0x42, 0x40, 0x42, 0xeb, 0xbb, 0x19, 0x1d, 0xdd, 0x83, 0xde, 0x84, 0xe9, 0x55, 0x45, 0x05, 0xc8, 0xbf, 0xf7, 0x2a, - 0x1a, 0x39, 0x47, 0xea, 0xea, 0xda, 0x91, 0xba, 0xb4, 0xbb, 0xfc, 0x49, 0xa1, 0x42, 0x3e, 0x10, 0x9a, 0x1f, 0x94, - 0x9d, 0x92, 0xbe, 0x26, 0xcc, 0x75, 0x35, 0xaf, 0x09, 0x36, 0xe0, 0xb3, 0x21, 0xc7, 0x91, 0xba, 0xf1, 0x83, 0x9a, - 0x01, 0xae, 0xdc, 0xa8, 0x87, 0x95, 0xdc, 0x77, 0x2e, 0x7e, 0xb1, 0x1f, 0x34, 0x33, 0x1f, 0xe3, 0x89, 0xae, 0x7a, - 0xdc, 0xcc, 0xd8, 0x83, 0xce, 0x0f, 0xa6, 0x4e, 0xd0, 0x6d, 0x93, 0x21, 0xc4, 0x3e, 0x4d, 0xf7, 0x90, 0xe7, 0xce, - 0x8f, 0x1e, 0x4c, 0xd0, 0xb9, 0x29, 0x08, 0xad, 0x9a, 0x14, 0xe8, 0xca, 0x2e, 0x79, 0x09, 0x3f, 0xbd, 0x7a, 0x45, - 0x97, 0x76, 0xd3, 0x5b, 0xf9, 0xe3, 0x26, 0x2c, 0x03, 0x7a, 0x17, 0xdf, 0x3b, 0xd4, 0xa7, 0x4c, 0xc7, 0x3d, 0xab, - 0xdd, 0x4b, 0x7e, 0xaa, 0x39, 0x8d, 0x9f, 0xb1, 0x5a, 0xa2, 0xf3, 0xc3, 0x79, 0x40, 0x70, 0x85, 0x10, 0x57, 0xfd, - 0xc0, 0x9b, 0xbd, 0x88, 0x52, 0xa6, 0x6a, 0x8b, 0xee, 0x4f, 0xfa, 0xc0, 0x2e, 0xe1, 0xf0, 0xb2, 0x6e, 0x8e, 0x13, - 0xf1, 0xdd, 0x58, 0x00, 0x26, 0x0c, 0xea, 0xea, 0xb7, 0x10, 0x30, 0x21, 0xba, 0xf3, 0xe4, 0x67, 0xfc, 0xbf, 0x21, - 0xe6, 0x3b, 0x45, 0xf8, 0xea, 0x78, 0xc1, 0xc9, 0xe9, 0xe4, 0x25, 0x2c, 0x81, 0x6f, 0x77, 0x18, 0x19, 0x22, 0x63, - 0x42, 0xa0, 0x19, 0xf3, 0x17, 0x69, 0x98, 0x4b, 0xe0, 0x2d, 0x0e, 0x81, 0xa3, 0xb8, 0x25, 0xfe, 0x64, 0x83, 0xbb, - 0xf7, 0xf9, 0xa6, 0x0f, 0xb1, 0xa6, 0xca, 0x2e, 0x41, 0xb9, 0xab, 0x78, 0xec, 0x66, 0x14, 0x68, 0x8c, 0xc2, 0x7e, - 0x83, 0x62, 0xa0, 0x45, 0xb7, 0x0e, 0x44, 0x14, 0xfa, 0x67, 0x55, 0xd1, 0xf9, 0x68, 0xa9, 0x88, 0x1d, 0xb2, 0x03, - 0x38, 0x01, 0xb2, 0x8b, 0x38, 0x19, 0x53, 0x97, 0x3b, 0x8a, 0x42, 0x03, 0x01, 0xce, 0xf0, 0x17, 0x3b, 0x9c, 0xf1, - 0x1f, 0xac, 0x03, 0x9b, 0x1c, 0x10, 0xd4, 0x06, 0xeb, 0x62, 0x8b, 0x53, 0x3c, 0x91, 0xfa, 0xc6, 0xec, 0xed, 0x79, - 0x3d, 0x1d, 0xf0, 0x1e, 0xdf, 0x55, 0xa9, 0x68, 0x21, 0x05, 0x5b, 0xf8, 0xb6, 0x1b, 0x32, 0x56, 0x0a, 0xab, 0xa0, - 0x77, 0xe7, 0x41, 0xd5, 0x9f, 0x4a, 0xa3, 0xfa, 0xbf, 0xba, 0x3b, 0xeb, 0xba, 0x05, 0x0f, 0xed, 0x92, 0xee, 0x82, - 0x2c, 0x59, 0xaa, 0x87, 0xad, 0xbe, 0xd9, 0x4d, 0x05, 0x05, 0xa9, 0x1d, 0x72, 0x7d, 0xeb, 0xff, 0xac, 0xc1, 0x81, - 0xac, 0xad, 0xda, 0x88, 0x03, 0xe1, 0x1d, 0x27, 0xc4, 0x57, 0x8f, 0xea, 0xae, 0x2e, 0x12, 0x54, 0x4d, 0xf9, 0xb8, - 0xc4, 0xfc, 0x32, 0x5e, 0xe5, 0x8d, 0x49, 0xaf, 0x2b, 0xbb, 0xef, 0x75, 0x39, 0x91, 0xb7, 0x93, 0xf9, 0x53, 0x10, - 0xdf, 0xd1, 0xcc, 0x00, 0x27, 0x27, 0xa5, 0x6c, 0x3d, 0xfb, 0x58, 0xdc, 0xe7, 0x38, 0x21, 0x92, 0x56, 0x19, 0x46, - 0x77, 0x7e, 0xe9, 0x0c, 0x6f, 0xdf, 0x80, 0xc2, 0xdb, 0x27, 0x4f, 0x80, 0x85, 0xd7, 0x94, 0x35, 0x8e, 0xb4, 0x28, - 0x24, 0x86, 0x61, 0x28, 0x05, 0xa2, 0x89, 0xd3, 0x6d, 0xa3, 0xbc, 0x09, 0xd0, 0x5b, 0xa1, 0x3f, 0x34, 0xf6, 0x88, - 0x9c, 0xb3, 0x7a, 0x79, 0x24, 0x97, 0xcc, 0x9f, 0xa8, 0x63, 0xfc, 0xc4, 0x0f, 0xfd, 0x93, 0x07, 0xf7, 0xba, 0x69, - 0x03, 0x38, 0xa4, 0x82, 0x9c, 0xc8, 0xf3, 0xb6, 0xbd, 0xaa, 0x8b, 0x26, 0x84, 0x3c, 0xe4, 0x56, 0x80, 0x87, 0x3c, - 0x3f, 0x9f, 0xeb, 0xa3, 0x10, 0x86, 0x43, 0x73, 0x05, 0x9c, 0x10, 0xd4, 0xc0, 0xbe, 0x81, 0x71, 0xe4, 0x46, 0x9e, - 0xdb, 0xd4, 0x17, 0x3d, 0x4e, 0xde, 0xed, 0x20, 0xa0, 0x0d, 0xfd, 0xf0, 0xbc, 0x3e, 0x75, 0xf5, 0xa3, 0xed, 0xf5, - 0x89, 0xdf, 0xc7, 0x68, 0x04, 0xe5, 0xcd, 0x5f, 0x61, 0x9f, 0x48, 0x5c, 0x81, 0x2d, 0xcd, 0x71, 0x36, 0x29, 0x9f, - 0xd5, 0x69, 0x53, 0xa1, 0x9e, 0x7c, 0x91, 0x63, 0x92, 0xdc, 0x57, 0x37, 0xd5, 0xc9, 0x42, 0x44, 0x1c, 0xf9, 0x9d, - 0x71, 0x87, 0xc1, 0xfc, 0x3c, 0xc9, 0xcd, 0x85, 0x2e, 0xb9, 0x3e, 0x4d, 0x2a, 0x68, 0xa0, 0xa2, 0x25, 0x79, 0x2f, - 0x3c, 0xe6, 0xad, 0xd0, 0xe4, 0x73, 0x61, 0x99, 0x2f, 0x85, 0xeb, 0x7c, 0x5d, 0x3f, 0x80, 0xef, 0x11, 0x37, 0xaa, - 0x56, 0x63, 0x3f, 0xf6, 0xe4, 0xbb, 0x96, 0x98, 0xf3, 0xaf, 0x34, 0xd6, 0xbc, 0x4d, 0x77, 0x89, 0x15, 0xcc, 0x68, - 0x36, 0x6d, 0x2c, 0x6e, 0x0c, 0x31, 0x15, 0xae, 0x49, 0xef, 0x70, 0x8d, 0xca, 0xf4, 0xec, 0x34, 0x22, 0x10, 0xbd, - 0x20, 0x6b, 0x0a, 0xb2, 0xb3, 0x95, 0x55, 0xb8, 0xb7, 0xd0, 0xb8, 0x58, 0xb8, 0x74, 0x7a, 0x1d, 0xbc, 0x42, 0xf5, - 0xfd, 0x76, 0x3d, 0x72, 0x89, 0xf2, 0xda, 0x94, 0xb4, 0xe1, 0x23, 0x27, 0x98, 0x63, 0xb1, 0x27, 0x28, 0xa1, 0xc8, - 0x50, 0xda, 0x12, 0xf0, 0x5c, 0x38, 0xe0, 0x1b, 0x31, 0x54, 0xeb, 0x7b, 0x5e, 0xa1, 0x27, 0x14, 0x39, 0x3e, 0x2a, - 0x77, 0x55, 0xc5, 0x49, 0x55, 0xba, 0xe6, 0x13, 0x5c, 0xbf, 0x1f, 0xbd, 0x8f, 0x88, 0x62, 0xed, 0x2b, 0xfb, 0xc2, - 0xbf, 0xb7, 0xc5, 0xea, 0xb2, 0x4f, 0x99, 0x80, 0x90, 0x5c, 0xde, 0xf2, 0x13, 0xc5, 0x1e, 0x39, 0x83, 0xef, 0x89, - 0xb0, 0x16, 0x93, 0x1c, 0xa4, 0xe3, 0x45, 0xc4, 0x0f, 0xa0, 0x03, 0x5b, 0xbe, 0x33, 0xcd, 0x29, 0xe2, 0x71, 0x25, - 0xbe, 0xef, 0x27, 0x83, 0x12, 0x2b, 0xb1, 0xca, 0xd9, 0x4f, 0xaa, 0x3a, 0x09, 0xe6, 0x7e, 0xf4, 0x1d, 0x8f, 0x1b, - 0xc1, 0xc1, 0xd4, 0xf1, 0x22, 0x64, 0x40, 0xe0, 0x17, 0xa0, 0x52, 0xe9, 0x01, 0xf1, 0x01, 0xa2, 0x6f, 0x40, 0x85, - 0x40, 0x78, 0x19, 0x94, 0xef, 0x51, 0x55, 0x9d, 0xda, 0x97, 0x73, 0x57, 0xde, 0x11, 0x94, 0x60, 0x1a, 0xde, 0xd1, - 0x48, 0x12, 0x94, 0x07, 0x1a, 0xed, 0x4e, 0x8e, 0xf8, 0xe0, 0x87, 0x37, 0x1d, 0x4d, 0x97, 0x2f, 0x31, 0x13, 0xed, - 0xd5, 0x9b, 0xf2, 0xe2, 0x5f, 0x83, 0x4c, 0x7c, 0xc9, 0x51, 0x20, 0x3e, 0xca, 0x93, 0xf5, 0xa6, 0xa4, 0x57, 0x17, - 0x4b, 0xbc, 0xff, 0x42, 0x39, 0xc2, 0xef, 0x16, 0x54, 0x0b, 0x30, 0xc7, 0xfe, 0xfc, 0xd0, 0xb6, 0x12, 0x3a, 0xc4, - 0x9a, 0xb7, 0xae, 0x04, 0xfe, 0x91, 0x9d, 0xb1, 0xbd, 0x0e, 0xc1, 0x7d, 0xdd, 0x9d, 0xcf, 0x0c, 0x33, 0xd9, 0xbc, - 0x52, 0x5c, 0x5e, 0x5a, 0x5e, 0x46, 0xe5, 0xb9, 0x27, 0xb9, 0xbe, 0x7e, 0x27, 0xf1, 0x9b, 0x4d, 0xed, 0xe2, 0xf2, - 0x5b, 0x4b, 0xdf, 0x98, 0x9a, 0x59, 0x26, 0xe0, 0x7e, 0xa7, 0xd7, 0x78, 0xa0, 0xd6, 0xed, 0x68, 0x6c, 0x33, 0x9b, - 0x13, 0xc6, 0x10, 0xe9, 0x6e, 0x3b, 0x53, 0x7b, 0xaa, 0xe0, 0xb7, 0x25, 0x45, 0xb2, 0x98, 0xd1, 0xd8, 0x22, 0x8e, - 0x54, 0x6f, 0xe5, 0x71, 0xcf, 0x7f, 0x67, 0xfa, 0x21, 0x43, 0xe3, 0x0c, 0x7f, 0xa0, 0x10, 0x01, 0x74, 0x23, 0x90, - 0xbb, 0xf0, 0xf5, 0x9e, 0x7f, 0x51, 0x21, 0x00, 0x40, 0x6d, 0x06, 0xa6, 0xbd, 0x18, 0xe7, 0x3a, 0x51, 0x1b, 0x72, - 0x8a, 0xee, 0xa6, 0xff, 0x1c, 0xbe, 0xd7, 0xdd, 0x89, 0x85, 0x56, 0x54, 0x7f, 0xf3, 0x43, 0x1b, 0xf0, 0x27, 0x75, - 0x9a, 0x62, 0x11, 0xba, 0xd8, 0xb8, 0xbc, 0x41, 0x9e, 0xa2, 0x35, 0x4a, 0x07, 0x55, 0x7e, 0x56, 0xd8, 0x1c, 0xbf, - 0xb7, 0x7f, 0xc6, 0x15, 0x78, 0x6b, 0x27, 0x55, 0xcf, 0x8d, 0xae, 0x0d, 0x00, 0x7d, 0x53, 0xdf, 0x0b, 0x4d, 0x66, - 0xde, 0xa8, 0xd2, 0xeb, 0xf7, 0x7b, 0xf2, 0x44, 0xfb, 0x10, 0x78, 0x02, 0x1a, 0x4e, 0x80, 0xd0, 0x95, 0x7c, 0x32, - 0x1f, 0x60, 0x03, 0x49, 0xa9, 0x38, 0xb0, 0xd3, 0x10, 0x7a, 0xa0, 0x63, 0x39, 0x61, 0x98, 0xc8, 0xe4, 0xc4, 0x71, - 0xc3, 0xff, 0x08, 0x2b, 0x42, 0x3f, 0xfa, 0x7f, 0xc6, 0x22, 0xae, 0x86, 0x73, 0x04, 0x31, 0x6a, 0xde, 0xc8, 0x02, - 0x14, 0xfc, 0xd7, 0xa9, 0xa7, 0x93, 0x13, 0xd9, 0x1c, 0xe7, 0x8c, 0x5a, 0xc6, 0x14, 0x21, 0xf2, 0x20, 0xc4, 0xf8, - 0x15, 0x9b, 0x58, 0x46, 0xd0, 0xf4, 0x43, 0x45, 0xef, 0x06, 0xb5, 0x95, 0x8c, 0xb8, 0x59, 0x3b, 0xb1, 0x03, 0xd7, - 0xde, 0x23, 0x01, 0x03, 0x79, 0xd3, 0x92, 0xed, 0x9b, 0xd2, 0xd5, 0xf8, 0xb0, 0x3f, 0x4e, 0xc6, 0xeb, 0x49, 0x16, - 0xf8, 0x27, 0xcd, 0x6e, 0x76, 0x86, 0xe4, 0x30, 0x49, 0xaa, 0x3c, 0x10, 0x09, 0xbc, 0xeb, 0x16, 0x43, 0x6a, 0x2c, - 0x6d, 0xb5, 0x4c, 0x14, 0xd6, 0x66, 0xc5, 0xc0, 0x91, 0x4d, 0x58, 0x17, 0x21, 0x06, 0x75, 0xb8, 0x2e, 0x4e, 0x01, - 0xd5, 0x09, 0xc2, 0x1c, 0x2a, 0xcc, 0x3a, 0x04, 0x9d, 0x32, 0x70, 0xd0, 0x31, 0xde, 0xd5, 0x83, 0xdf, 0x37, 0xce, - 0x88, 0x27, 0xc7, 0x4d, 0x83, 0xcb, 0xb9, 0xb1, 0x1c, 0x39, 0x37, 0xc2, 0xcb, 0xc0, 0xe9, 0x76, 0xbd, 0x21, 0xd5, - 0x36, 0x9c, 0x55, 0x45, 0x15, 0xad, 0xf2, 0x59, 0x75, 0x12, 0xd3, 0x56, 0xaf, 0xd9, 0x04, 0x51, 0x77, 0xe7, 0xb9, - 0x61, 0x2d, 0x83, 0x86, 0x11, 0x25, 0x21, 0x56, 0xef, 0x03, 0xfd, 0x89, 0x3d, 0xf8, 0xa2, 0x6a, 0x0f, 0x04, 0xba, - 0xd3, 0x60, 0x61, 0xc7, 0xcf, 0x00, 0x1c, 0x6e, 0xc6, 0x31, 0x8e, 0x41, 0xfb, 0xd2, 0x8a, 0x42, 0xaf, 0x96, 0x44, - 0xe0, 0x0c, 0xb3, 0xfc, 0x1f, 0xdf, 0xe2, 0xb5, 0xe8, 0xb5, 0xeb, 0xd0, 0xb9, 0xfa, 0x24, 0x36, 0x75, 0x6d, 0x9a, - 0xf8, 0xe8, 0xba, 0x81, 0x4b, 0x2f, 0xf0, 0x00, 0xee, 0x89, 0x17, 0x5d, 0x81, 0xc0, 0xf3, 0x4f, 0x26, 0x4a, 0xf7, - 0x70, 0x80, 0x39, 0x53, 0xdc, 0x18, 0x4e, 0xb9, 0x94, 0x1c, 0x43, 0xd3, 0xc2, 0x12, 0x18, 0x39, 0x40, 0x7f, 0x31, - 0xae, 0x30, 0x49, 0xba, 0xa4, 0x45, 0x47, 0xd1, 0x43, 0x2e, 0xc9, 0x3a, 0xa7, 0x5f, 0x64, 0x7e, 0xac, 0xae, 0xb1, - 0x51, 0x1c, 0x6b, 0x85, 0xcc, 0x3f, 0x44, 0x34, 0xea, 0x37, 0xe7, 0x05, 0x4c, 0xec, 0x8b, 0x83, 0x39, 0xbf, 0xf7, - 0xb7, 0xd6, 0xf2, 0xfa, 0xe3, 0xc9, 0xa6, 0xa7, 0x8c, 0x06, 0xc0, 0x18, 0x7e, 0xc2, 0xf1, 0x20, 0xa5, 0xd7, 0x57, - 0xa4, 0x82, 0xf7, 0x4d, 0xf1, 0x69, 0x5f, 0xc8, 0x4c, 0x4a, 0xf4, 0x8f, 0x41, 0x2c, 0x7d, 0x36, 0xad, 0x26, 0xd3, - 0x1f, 0xd0, 0xe6, 0x68, 0x0c, 0xe2, 0x51, 0x73, 0x78, 0x8b, 0x45, 0x75, 0xf5, 0x0c, 0x3f, 0xa1, 0xcc, 0x2d, 0x99, - 0x0f, 0xd9, 0x3e, 0x42, 0x5f, 0x8c, 0x25, 0x66, 0x1a, 0x9f, 0x27, 0x3f, 0x77, 0x91, 0x6b, 0xab, 0x37, 0x37, 0xf2, - 0xdf, 0xd4, 0x52, 0xa4, 0x36, 0xaa, 0x08, 0xfe, 0xfa, 0x13, 0xfa, 0x6a, 0x67, 0xde, 0xa4, 0x00, 0x9d, 0x2f, 0x09, - 0xfa, 0xd9, 0x80, 0x2a, 0x52, 0x04, 0x0d, 0xf8, 0xce, 0x16, 0xda, 0xa5, 0x32, 0x1d, 0x73, 0xfa, 0x5a, 0xde, 0xdf, - 0x84, 0x15, 0xdc, 0x1d, 0x6a, 0x1b, 0x92, 0xac, 0x46, 0x7e, 0x3d, 0xc6, 0x8a, 0xad, 0xef, 0x5d, 0x65, 0x38, 0xed, - 0xff, 0x18, 0x07, 0x01, 0xc8, 0x5b, 0xc5, 0xdd, 0x92, 0xd6, 0x69, 0xbd, 0x93, 0x74, 0xa5, 0x18, 0xd2, 0xca, 0xd5, - 0xfd, 0xee, 0xfb, 0xff, 0x30, 0x45, 0x63, 0x4a, 0x9f, 0xd8, 0x08, 0xed, 0x2a, 0x40, 0x92, 0x03, 0xa2, 0x87, 0x07, - 0x2d, 0x1d, 0x7f, 0x08, 0x45, 0x0b, 0x16, 0xbe, 0x05, 0x7d, 0xc3, 0x20, 0xda, 0x1e, 0xc1, 0x01, 0xbc, 0x0b, 0x97, - 0x7f, 0xf8, 0xa5, 0x71, 0x0d, 0x91, 0xdc, 0x7c, 0x4f, 0x6a, 0xea, 0xea, 0xcd, 0xbb, 0xe9, 0x5f, 0x42, 0xd6, 0x4d, - 0xfd, 0xe9, 0xaf, 0xd3, 0xb6, 0x2f, 0xbc, 0x9e, 0x14, 0x89, 0x66, 0x1c, 0x7f, 0x7b, 0x62, 0xe3, 0x8d, 0x31, 0xba, - 0x3e, 0x8a, 0x9e, 0x56, 0xcf, 0xde, 0x7a, 0xe9, 0x41, 0x2f, 0x4e, 0x08, 0x1e, 0xe3, 0x8f, 0x60, 0xc2, 0x6b, 0xfe, - 0x94, 0x50, 0xc7, 0xdf, 0x7a, 0x84, 0x7f, 0x36, 0x53, 0x18, 0x09, 0x15, 0x7e, 0xc7, 0x23, 0x8b, 0xca, 0xc5, 0xa5, - 0x24, 0x03, 0x42, 0x5c, 0x03, 0x60, 0x78, 0x2f, 0x9f, 0x02, 0x44, 0x62, 0xe3, 0xef, 0xe4, 0xde, 0x56, 0x78, 0x38, - 0xf7, 0xee, 0x50, 0x8e, 0xc5, 0xf2, 0x21, 0x65, 0xa6, 0x8f, 0xf8, 0x6d, 0xa4, 0x6e, 0x05, 0x75, 0x97, 0xe3, 0x97, - 0x0d, 0xc4, 0x7c, 0x00, 0xee, 0xef, 0xe1, 0xcd, 0x94, 0x57, 0x3f, 0x88, 0x6b, 0x00, 0xe4, 0xcf, 0x9d, 0x28, 0x99, - 0xd6, 0x1f, 0xed, 0x37, 0x74, 0x32, 0x10, 0x41, 0x82, 0x5a, 0x0b, 0x6a, 0x09, 0xb6, 0xc9, 0xee, 0x4d, 0x08, 0xbb, - 0xb5, 0xde, 0xcc, 0x77, 0xec, 0xc0, 0xce, 0x17, 0x7c, 0xc2, 0xf9, 0xb2, 0xf6, 0xa2, 0x9e, 0x1b, 0x19, 0xfe, 0x1d, - 0xf1, 0x0c, 0xfb, 0x05, 0xf3, 0xda, 0xb3, 0x9b, 0x9b, 0xf4, 0x3a, 0x5d, 0x0f, 0x4b, 0x5a, 0xa3, 0x7e, 0xc3, 0x8a, - 0x47, 0xb7, 0xd3, 0xa9, 0xd5, 0x6d, 0xb3, 0xaf, 0xd3, 0xef, 0x22, 0x96, 0x09, 0x34, 0x3f, 0xf1, 0xd6, 0x07, 0xa4, - 0xbe, 0xfd, 0x34, 0xb2, 0x9d, 0x5f, 0xfc, 0xf0, 0x0d, 0x86, 0xd3, 0x9f, 0x1c, 0xe1, 0xae, 0x0c, 0x7e, 0x66, 0x07, - 0xaa, 0x03, 0x25, 0x9f, 0xdd, 0x32, 0xc2, 0x60, 0x1c, 0x3e, 0xf0, 0x0c, 0x2b, 0xf8, 0x64, 0x7f, 0x15, 0xde, 0xc1, - 0xea, 0x1f, 0x5e, 0xf0, 0x5a, 0x5a, 0x23, 0xd5, 0x02, 0xdb, 0x85, 0x50, 0x42, 0xd9, 0x21, 0x35, 0x6e, 0xd4, 0xf6, - 0xef, 0x5c, 0x30, 0xd9, 0x22, 0xe1, 0xa6, 0x91, 0xe3, 0x57, 0x76, 0x9e, 0xb9, 0x72, 0x3c, 0xdf, 0x70, 0x33, 0xab, - 0xa0, 0x6f, 0x41, 0x19, 0x16, 0x56, 0x5f, 0x3a, 0xbe, 0x68, 0x88, 0xfe, 0x65, 0xf1, 0x0b, 0xc7, 0x51, 0xfe, 0x98, - 0xa3, 0x06, 0xee, 0xfc, 0x32, 0xaa, 0x88, 0x92, 0x3c, 0x66, 0x83, 0x03, 0xbd, 0xa3, 0xd1, 0x3c, 0xa1, 0x53, 0x2b, - 0x34, 0x80, 0x72, 0x0f, 0x1d, 0xfd, 0x80, 0xf5, 0xd4, 0x7e, 0xc3, 0x36, 0x1e, 0xe3, 0xf2, 0xaf, 0xe3, 0x4e, 0x46, - 0x9c, 0x92, 0x62, 0x7e, 0xcb, 0x33, 0x83, 0xf5, 0x82, 0x25, 0x5e, 0x25, 0x61, 0x07, 0xa4, 0xa8, 0xdf, 0xb1, 0xe7, - 0x7f, 0xe7, 0x7b, 0x1d, 0x60, 0xbe, 0x2d, 0xe8, 0xc9, 0xac, 0x01, 0xbf, 0xf5, 0x02, 0x6a, 0x2f, 0xe8, 0x2d, 0xa7, - 0xc5, 0x76, 0x55, 0x0d, 0x70, 0x02, 0x23, 0xa8, 0x99, 0x27, 0xf1, 0xe5, 0xde, 0xda, 0xff, 0x52, 0x71, 0x6a, 0xc0, - 0xc7, 0xc7, 0xeb, 0x07, 0xcc, 0x43, 0x87, 0x1c, 0xe5, 0x19, 0xef, 0x80, 0xcf, 0x1e, 0x1f, 0xf3, 0x1c, 0xb0, 0x63, - 0xf2, 0x7f, 0xe1, 0x61, 0xa9, 0xb3, 0xe7, 0x78, 0xf8, 0x12, 0x76, 0x8b, 0x93, 0x3d, 0xdc, 0x4d, 0xf2, 0x30, 0xde, - 0x24, 0xde, 0x06, 0x4f, 0x74, 0x63, 0xe0, 0x6a, 0xf0, 0xe3, 0x14, 0xeb, 0x3b, 0xde, 0xea, 0xe3, 0xf7, 0x7a, 0x7d, - 0x62, 0x5f, 0x35, 0x78, 0xbe, 0xff, 0x8d, 0x8f, 0xc6, 0x2d, 0xe3, 0x7f, 0xd5, 0x9a, 0xe7, 0x17, 0xa4, 0xaf, 0x63, - 0xf7, 0x74, 0x24, 0xdb, 0xea, 0xb1, 0x20, 0x67, 0x3a, 0x46, 0x47, 0x3a, 0x4e, 0xcb, 0x9f, 0xe2, 0xfa, 0x94, 0x9f, - 0x7c, 0xaf, 0xaf, 0x4f, 0x3c, 0xa9, 0xd4, 0xc6, 0xf3, 0x69, 0xb4, 0x01, 0x47, 0x0b, 0xe8, 0x4f, 0xab, 0x69, 0x6b, - 0x43, 0x12, 0x6f, 0x60, 0xb2, 0x4b, 0x71, 0x68, 0x56, 0xec, 0x96, 0xed, 0x4c, 0x3d, 0xd0, 0x9f, 0x77, 0xad, 0x07, - 0xe7, 0x85, 0xb9, 0xb1, 0x67, 0x05, 0x6e, 0x98, 0xac, 0xd4, 0x0e, 0xd2, 0x20, 0x1a, 0x11, 0x4b, 0x16, 0x88, 0x8e, - 0xfc, 0xda, 0x6b, 0x8f, 0x4d, 0xc5, 0xd9, 0xfd, 0x1a, 0x43, 0x97, 0x92, 0x01, 0x70, 0xb9, 0x2c, 0xec, 0xd4, 0xeb, - 0xed, 0x00, 0x0d, 0x02, 0x14, 0x07, 0x55, 0xce, 0x4c, 0xa0, 0x6c, 0x16, 0xf8, 0x1c, 0xe8, 0x55, 0x80, 0x3d, 0xe8, - 0xc2, 0xd1, 0xb9, 0x21, 0x5e, 0xe0, 0x9c, 0xd9, 0x2b, 0x03, 0x42, 0x89, 0x92, 0x5f, 0x34, 0xbc, 0x2d, 0xc6, 0x1c, - 0x7d, 0xd8, 0x08, 0x6b, 0x46, 0xa7, 0xaa, 0xe3, 0xda, 0x5b, 0xa5, 0xe3, 0xe6, 0xc1, 0xf1, 0x3d, 0x48, 0x90, 0x63, - 0x90, 0xc6, 0xfa, 0x3d, 0x7f, 0xb7, 0x3c, 0x95, 0x19, 0x58, 0x65, 0xc7, 0xfc, 0x7e, 0xc8, 0xad, 0x18, 0x79, 0x33, - 0x99, 0x28, 0x4b, 0x78, 0x90, 0x2b, 0xbc, 0xaf, 0xe2, 0x3f, 0x17, 0x91, 0xec, 0x24, 0x3f, 0xd2, 0x47, 0x42, 0xf5, - 0x8c, 0xf0, 0xcb, 0x27, 0xaa, 0xfe, 0x28, 0x66, 0xc3, 0x50, 0xec, 0xc6, 0x6a, 0x36, 0x0e, 0x73, 0x2e, 0xe7, 0x8d, - 0x36, 0xc4, 0x5b, 0x27, 0xb5, 0x89, 0xb4, 0xc1, 0x15, 0x7e, 0xb3, 0x00, 0x74, 0xc5, 0xf2, 0x40, 0x21, 0x90, 0x23, - 0xb4, 0xb7, 0x15, 0x2d, 0xf1, 0x29, 0x07, 0xbf, 0x60, 0x07, 0x3b, 0x84, 0x66, 0xbf, 0xcc, 0x43, 0x6b, 0x34, 0x6d, - 0x64, 0xd2, 0x61, 0xe7, 0x12, 0xc8, 0xd4, 0x02, 0x23, 0xd4, 0x38, 0xcb, 0xa1, 0xb0, 0x2a, 0xb8, 0x6f, 0xb4, 0x72, - 0x2e, 0x5c, 0xb7, 0x94, 0x4f, 0x86, 0x05, 0x3e, 0xc1, 0x16, 0x3e, 0x63, 0xc2, 0xee, 0x0b, 0xba, 0x39, 0x24, 0x52, - 0x48, 0x15, 0x25, 0x8d, 0xc9, 0xa0, 0x42, 0xe9, 0xb8, 0x8a, 0x5a, 0xa7, 0x81, 0xee, 0x31, 0x21, 0xa6, 0xa7, 0x20, - 0x16, 0x47, 0x6e, 0x5f, 0xfd, 0x11, 0xcf, 0xcf, 0x9b, 0x1f, 0xfb, 0x18, 0x27, 0x1a, 0x8b, 0xc7, 0x91, 0x3a, 0x3f, - 0x42, 0x65, 0xb8, 0xbc, 0x39, 0xed, 0x2e, 0xec, 0x35, 0x75, 0xd9, 0x29, 0x92, 0x12, 0x21, 0xa6, 0xb2, 0x5c, 0xe0, - 0x70, 0xdf, 0xeb, 0x9a, 0x54, 0xec, 0x08, 0xbc, 0x2e, 0xc4, 0x2f, 0x85, 0x7b, 0x6b, 0xf8, 0xbd, 0x62, 0xb7, 0x5a, - 0x3b, 0xdf, 0xb6, 0xb9, 0x33, 0x8f, 0xfc, 0xc0, 0xe1, 0xcc, 0xc9, 0x4c, 0xf4, 0x8b, 0xb0, 0xc4, 0xba, 0x23, 0xc7, - 0xd2, 0x90, 0xe0, 0xc4, 0x33, 0x54, 0xd9, 0x54, 0x43, 0xf7, 0x3b, 0x2f, 0x14, 0x71, 0x53, 0x72, 0xb4, 0x9b, 0x80, - 0x5c, 0xae, 0xe9, 0x52, 0xcb, 0xa8, 0x1c, 0x92, 0x84, 0xe7, 0x39, 0x90, 0xe7, 0x84, 0x62, 0xf5, 0xb3, 0xac, 0x33, - 0xe2, 0xbc, 0x81, 0x52, 0x3e, 0x12, 0x49, 0x78, 0xa6, 0xa6, 0xe7, 0x66, 0xe2, 0x4f, 0xd4, 0x5f, 0x89, 0xb3, 0x37, - 0x19, 0x1e, 0x8e, 0xe3, 0x0a, 0xc3, 0x35, 0xfc, 0x87, 0xd0, 0xa3, 0x07, 0xfe, 0xb9, 0x19, 0xc3, 0x20, 0x24, 0x99, - 0x51, 0x28, 0xc2, 0xa4, 0xf4, 0xea, 0xba, 0x6b, 0x1a, 0xe3, 0x44, 0xc7, 0xbd, 0x07, 0x9f, 0xab, 0x77, 0x13, 0xa4, - 0x84, 0xc4, 0x31, 0xa5, 0x0c, 0xca, 0xb5, 0xa8, 0xf0, 0xe0, 0xa9, 0xf6, 0xf5, 0x8f, 0x99, 0x5b, 0x51, 0x74, 0xf9, - 0x0a, 0xd9, 0x48, 0x00, 0x46, 0x4f, 0x06, 0x58, 0x0f, 0xcb, 0x0c, 0x76, 0x22, 0x21, 0xbe, 0x0a, 0x87, 0x2c, 0xad, - 0x3a, 0xca, 0x00, 0xb0, 0xd9, 0x6d, 0x04, 0xa3, 0x0f, 0x58, 0x75, 0x86, 0x5a, 0xd1, 0xdf, 0xb2, 0xa8, 0x5a, 0x69, - 0xdd, 0x48, 0x79, 0x35, 0x8d, 0x3e, 0xd1, 0x91, 0x0b, 0x3e, 0x97, 0x75, 0xbb, 0x20, 0x29, 0x49, 0x8c, 0x36, 0xb4, - 0xd0, 0x6f, 0x6b, 0x48, 0x57, 0xff, 0xf9, 0xe9, 0x7e, 0x28, 0xa2, 0x28, 0xad, 0x8b, 0x41, 0x72, 0x14, 0x94, 0xfe, - 0x87, 0x50, 0x07, 0x70, 0x36, 0x2d, 0xea, 0x27, 0x51, 0xc7, 0xed, 0x06, 0x1a, 0xf1, 0xe5, 0x07, 0xd8, 0xd9, 0x3a, - 0xba, 0xdb, 0xd6, 0xba, 0xd3, 0x24, 0x9a, 0x5c, 0x34, 0xa3, 0xca, 0x59, 0x23, 0xc7, 0x87, 0x41, 0x76, 0x16, 0xb9, - 0x4c, 0x46, 0x38, 0x77, 0x7b, 0x5d, 0xb0, 0x61, 0x12, 0x65, 0xc5, 0xff, 0x7c, 0x15, 0xa2, 0xbb, 0x94, 0x8b, 0x7e, - 0x00, 0x5b, 0xf2, 0xb2, 0xe3, 0x64, 0xd5, 0x20, 0x20, 0x5a, 0x09, 0x58, 0xce, 0xfc, 0xa2, 0x30, 0x8d, 0xd3, 0x77, - 0x5d, 0xba, 0x98, 0xc6, 0x90, 0xb5, 0x6e, 0x3e, 0xf0, 0x6f, 0x54, 0xb9, 0xc7, 0xb5, 0x26, 0xb8, 0x25, 0xa4, 0x77, - 0xe1, 0x0e, 0xf0, 0x6a, 0x53, 0xc7, 0x6e, 0xd7, 0x21, 0x10, 0x12, 0x08, 0x95, 0x2e, 0x24, 0xa8, 0x42, 0xdd, 0xce, - 0x84, 0x35, 0xd5, 0x23, 0xbc, 0x70, 0x62, 0xec, 0x2f, 0x57, 0x25, 0x37, 0x02, 0x07, 0x50, 0x34, 0x9b, 0x2f, 0x84, - 0xcd, 0xe4, 0xa8, 0x57, 0x8d, 0x6a, 0x47, 0xf0, 0x15, 0x3b, 0x1e, 0xfc, 0xd9, 0x67, 0x12, 0x31, 0x66, 0xe8, 0xc2, - 0x86, 0xdc, 0xf2, 0x33, 0x5d, 0x30, 0x6f, 0x0e, 0xda, 0xe9, 0x69, 0xed, 0xa3, 0xa0, 0x42, 0x75, 0x7e, 0xaa, 0x17, - 0x66, 0x12, 0xf2, 0x1c, 0x8b, 0x17, 0x83, 0xe6, 0xb9, 0xb1, 0x7e, 0x1f, 0x1d, 0xf2, 0xff, 0xd7, 0x0a, 0x18, 0x39, - 0xbb, 0x95, 0xee, 0x99, 0x52, 0xa6, 0xe4, 0xbb, 0xc5, 0xfc, 0xca, 0xc4, 0x70, 0xb5, 0x9c, 0x1a, 0xc1, 0x71, 0x9c, - 0xe6, 0xf1, 0x11, 0x26, 0x83, 0xa8, 0xbe, 0xc6, 0x56, 0x7c, 0xe8, 0xca, 0x90, 0x85, 0x7b, 0xbf, 0x4a, 0x54, 0x7a, - 0x87, 0xa3, 0xa7, 0xda, 0x9a, 0x51, 0xb5, 0x04, 0xea, 0xeb, 0x46, 0xad, 0xa8, 0xd5, 0x82, 0x72, 0x2a, 0x98, 0x57, - 0x98, 0xf2, 0xc4, 0x56, 0xe7, 0xff, 0x2d, 0x2b, 0xe1, 0xcf, 0x0d, 0xff, 0x8b, 0xbf, 0x10, 0x4e, 0x58, 0xb1, 0xa4, - 0xc2, 0x8f, 0x57, 0x07, 0x03, 0xb0, 0xf0, 0xdf, 0x87, 0xdd, 0xe8, 0x6f, 0x63, 0xb9, 0x80, 0xd4, 0xfd, 0xe8, 0x29, - 0x96, 0x4e, 0x11, 0x42, 0x2c, 0xe5, 0x45, 0xcf, 0x54, 0x52, 0x8b, 0x33, 0x2f, 0x1a, 0x00, 0x98, 0xf7, 0x60, 0xcd, - 0x7d, 0x71, 0x9c, 0x24, 0x41, 0xcd, 0x2a, 0xa0, 0x9a, 0x72, 0x3d, 0x27, 0xcc, 0xaf, 0x38, 0xf5, 0xa7, 0xac, 0xe9, - 0x99, 0x53, 0x50, 0xb7, 0xe7, 0x27, 0x69, 0x8c, 0x82, 0x66, 0xac, 0x18, 0xa7, 0xb2, 0x9d, 0xa4, 0xbf, 0x58, 0xbb, - 0xdc, 0xdd, 0x25, 0xca, 0xa4, 0xcb, 0xb3, 0x36, 0xe3, 0xbf, 0x92, 0x4a, 0x69, 0xc5, 0xee, 0xd4, 0xa9, 0xd1, 0x71, - 0x6e, 0x09, 0x6a, 0x34, 0x84, 0xe0, 0xcb, 0x40, 0x7a, 0xc8, 0x79, 0x59, 0x3a, 0xca, 0x73, 0xe0, 0x3c, 0x94, 0xed, - 0xc9, 0x83, 0x19, 0x68, 0x8f, 0xfe, 0x36, 0x8c, 0xa6, 0x96, 0xcc, 0xdf, 0xb9, 0x6a, 0xc3, 0x0e, 0xd1, 0xd0, 0x22, - 0x98, 0xae, 0x36, 0xc7, 0xed, 0x80, 0xf7, 0x72, 0x29, 0xb9, 0x3a, 0xd7, 0xae, 0xcf, 0x92, 0xe7, 0x67, 0xef, 0xc3, - 0x56, 0xd2, 0x6d, 0xfa, 0x4f, 0xde, 0x4e, 0x6d, 0x72, 0x7d, 0x9b, 0x56, 0xba, 0x2c, 0x9b, 0x20, 0x4a, 0x33, 0x34, - 0x71, 0xfe, 0x30, 0xdf, 0x4e, 0xfd, 0x13, 0xc1, 0x72, 0xc6, 0xa6, 0xec, 0xc7, 0xf9, 0xaa, 0x14, 0x66, 0xaa, 0x90, - 0x40, 0xda, 0x14, 0x7d, 0x49, 0x8d, 0x0b, 0x73, 0x3a, 0xbc, 0xa7, 0x93, 0x5c, 0x40, 0xfa, 0x34, 0x42, 0xe8, 0x63, - 0x27, 0x34, 0xe7, 0x68, 0xe4, 0xcd, 0x7f, 0x32, 0xf3, 0x5d, 0xf8, 0x41, 0x34, 0x68, 0xf8, 0x1d, 0x6f, 0x86, 0xda, - 0x76, 0xfa, 0x6a, 0x6f, 0xd3, 0x3c, 0x04, 0xb5, 0x6f, 0x34, 0x09, 0x1a, 0xf8, 0x7a, 0xf6, 0x03, 0x3e, 0xd9, 0x6c, - 0xaa, 0xa9, 0xf6, 0xc3, 0xaf, 0x26, 0xec, 0x90, 0x2a, 0xcb, 0xd0, 0x0c, 0x12, 0x06, 0xed, 0x0a, 0xdf, 0xd3, 0x25, - 0x4c, 0x02}; + 0x1b, 0x20, 0x98, 0x51, 0xd4, 0x8d, 0x56, 0x4b, 0xe5, 0xa2, 0xa8, 0x56, 0xa5, 0x80, 0x56, 0x05, 0xd9, 0x90, 0x89, + 0x0d, 0xfb, 0x77, 0x53, 0xb6, 0xa6, 0x94, 0xb5, 0x35, 0x4d, 0x09, 0x86, 0xa5, 0xbd, 0xe9, 0xf6, 0x5f, 0xc7, 0xd8, + 0xa5, 0xc5, 0x13, 0x67, 0x4e, 0x5c, 0xc8, 0x0a, 0xc3, 0x73, 0x8e, 0xd0, 0xd8, 0x27, 0xb9, 0xf7, 0xbe, 0x4d, 0xff, + 0xbf, 0x7e, 0x63, 0x35, 0x27, 0x95, 0x6f, 0x03, 0x48, 0x26, 0x74, 0x17, 0xcd, 0xb2, 0x2d, 0xa7, 0x0f, 0x84, 0x3d, + 0xe0, 0x49, 0x6c, 0xc9, 0x1d, 0x8d, 0x59, 0x62, 0xf2, 0xff, 0xf3, 0xfc, 0xac, 0xa5, 0xdf, 0x7d, 0x2e, 0x27, 0x83, + 0xa2, 0x56, 0xbd, 0xe9, 0x4a, 0xfd, 0xe5, 0xd8, 0xf8, 0x85, 0x59, 0x77, 0xcf, 0x9c, 0x10, 0x52, 0x98, 0xd0, 0xb6, + 0xf3, 0x17, 0x88, 0xa0, 0xb2, 0xd3, 0xfe, 0xbf, 0xda, 0xfa, 0x8a, 0xbb, 0x92, 0xc8, 0xa5, 0xcf, 0x29, 0xfc, 0x3e, + 0x57, 0x36, 0x86, 0x9e, 0x5e, 0x9e, 0x90, 0xd5, 0xfb, 0x32, 0x3b, 0x78, 0xb0, 0x3f, 0xa8, 0xc0, 0xa7, 0x29, 0x9b, + 0x63, 0xab, 0x96, 0x3f, 0xf2, 0xeb, 0x24, 0x98, 0x30, 0x9c, 0x28, 0xec, 0x20, 0x99, 0x71, 0xca, 0x01, 0x6b, 0xf3, + 0xb6, 0x34, 0x69, 0x05, 0x17, 0xb8, 0x27, 0x2e, 0xd6, 0xc1, 0xcc, 0x73, 0xbe, 0x59, 0xba, 0xac, 0x5a, 0xff, 0x07, + 0x35, 0x91, 0x76, 0x74, 0xc7, 0x0e, 0x72, 0x8d, 0x9d, 0x71, 0xfc, 0x41, 0xf6, 0xdf, 0x9b, 0x6a, 0x95, 0x36, 0x40, + 0xb3, 0xbb, 0xe7, 0x7c, 0x6a, 0x5c, 0x6a, 0x9c, 0x32, 0x88, 0x2b, 0x9d, 0xf3, 0x49, 0x70, 0x41, 0xc8, 0x7e, 0xef, + 0xfd, 0xff, 0x86, 0xed, 0x30, 0x44, 0x77, 0x13, 0x3b, 0x70, 0x94, 0x08, 0x92, 0x58, 0xfa, 0x12, 0xad, 0xe4, 0xff, + 0xff, 0x0d, 0x80, 0xdd, 0x00, 0xa5, 0x05, 0x29, 0x69, 0x8b, 0xe2, 0x70, 0xab, 0x68, 0xd6, 0x19, 0xce, 0xac, 0x3d, + 0xe3, 0x75, 0x53, 0x75, 0xd6, 0x45, 0x36, 0x4a, 0x8c, 0xcf, 0xae, 0x72, 0x1b, 0x85, 0xc6, 0xa6, 0x97, 0x5d, 0x78, + 0xe9, 0x39, 0x15, 0x55, 0xca, 0xed, 0x59, 0x9b, 0x06, 0x63, 0xd8, 0x32, 0x74, 0xf8, 0xac, 0x3a, 0xeb, 0xd9, 0x94, + 0x1b, 0xc2, 0x2d, 0x27, 0xc4, 0xba, 0x6d, 0xa4, 0xda, 0xe1, 0x38, 0xe9, 0x72, 0xee, 0x62, 0xa6, 0x10, 0x42, 0x03, + 0xc1, 0xfb, 0xe3, 0xc6, 0xf4, 0xc2, 0xdd, 0x9c, 0x44, 0x30, 0x31, 0xb6, 0x38, 0x40, 0x3a, 0x05, 0x7e, 0xe8, 0x50, + 0xa7, 0x9b, 0x52, 0x9c, 0x27, 0xe8, 0xf4, 0x37, 0x82, 0x69, 0xb6, 0x87, 0xa0, 0x1c, 0xc3, 0x81, 0x0d, 0x68, 0x64, + 0x79, 0xe6, 0xea, 0xdd, 0x07, 0x36, 0x5e, 0xd7, 0x2f, 0xc8, 0xa0, 0xc7, 0xbb, 0xdd, 0x1c, 0x70, 0x93, 0x92, 0x73, + 0xd7, 0x28, 0x1b, 0x41, 0xd7, 0xac, 0x5a, 0x08, 0xf2, 0x77, 0xfd, 0xf3, 0xb7, 0x37, 0x07, 0x1a, 0x93, 0xe8, 0x1f, + 0x52, 0xd3, 0x52, 0xc2, 0xb3, 0xa0, 0x4b, 0xda, 0x5e, 0xc0, 0xe1, 0x8b, 0x90, 0x87, 0x9e, 0x87, 0x5d, 0xf0, 0x5a, + 0x6b, 0xdd, 0x4e, 0x73, 0x3c, 0x33, 0x66, 0x6c, 0xb9, 0x48, 0xf5, 0x40, 0xcd, 0xf4, 0xce, 0xe1, 0xa0, 0x4b, 0x55, + 0x38, 0xab, 0xce, 0x49, 0xb4, 0xe9, 0x76, 0x89, 0x91, 0x3b, 0x5d, 0x7e, 0x9c, 0x52, 0xba, 0xf9, 0xbb, 0xad, 0x9a, + 0x84, 0x7b, 0x7a, 0x8b, 0x5f, 0xe3, 0xe1, 0x4f, 0x3b, 0x2f, 0xc2, 0x0a, 0x8a, 0x88, 0x78, 0xa4, 0x48, 0xb9, 0x3c, + 0x58, 0x4d, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0xc1, 0x48, 0x01, 0x2b, 0x1a, 0xe7, 0x08, 0xe7, 0x65, 0x7e, 0x9c, + 0x8c, 0x79, 0x59, 0xc4, 0xa7, 0x87, 0xc3, 0x79, 0xe7, 0x0e, 0xd7, 0x9d, 0x9b, 0xbd, 0x59, 0x0f, 0xa6, 0x6e, 0x5f, + 0x7f, 0x17, 0xf2, 0x6e, 0x58, 0x4f, 0xc1, 0xd6, 0x96, 0x5f, 0xbb, 0x5e, 0xf1, 0x0b, 0x35, 0x97, 0xae, 0xeb, 0xf5, + 0x80, 0x9b, 0xa6, 0x09, 0x32, 0x16, 0xda, 0x03, 0xfa, 0x73, 0x55, 0xc9, 0xfa, 0xf3, 0x20, 0x13, 0xca, 0x29, 0xfb, + 0x2e, 0xb8, 0xed, 0xba, 0xc4, 0xb1, 0x78, 0x42, 0xa6, 0x9a, 0xc8, 0x37, 0xf8, 0x8f, 0x80, 0x5a, 0x1e, 0x6c, 0xf0, + 0x28, 0xe4, 0x21, 0x30, 0xae, 0x23, 0x8a, 0xaa, 0xe6, 0x91, 0x50, 0xfd, 0xd6, 0xef, 0xd6, 0x20, 0x83, 0xfc, 0x5b, + 0xa3, 0x31, 0xda, 0x60, 0x08, 0x92, 0x99, 0xbb, 0x4d, 0xb2, 0x0b, 0x80, 0xc0, 0x54, 0x1d, 0x49, 0x69, 0x99, 0x47, + 0xe4, 0xe9, 0x78, 0x8e, 0x91, 0xf9, 0xc0, 0x7b, 0x1c, 0x16, 0xd3, 0x8d, 0xb8, 0xe1, 0x76, 0x00, 0x43, 0xc8, 0xdd, + 0x82, 0xa9, 0x6b, 0xca, 0x20, 0x19, 0xec, 0x14, 0x94, 0x34, 0x29, 0x90, 0x9c, 0x5d, 0xd3, 0x1c, 0x15, 0x01, 0x79, + 0xdd, 0xb5, 0xd3, 0xb1, 0x6f, 0x6b, 0xbc, 0xc5, 0x9b, 0xbf, 0xb3, 0x8e, 0x46, 0xc4, 0xf8, 0xbb, 0x6b, 0xe7, 0x92, + 0x8b, 0xb5, 0x02, 0xa4, 0x93, 0x70, 0xd7, 0x6b, 0xbf, 0x51, 0x3a, 0x6d, 0x9b, 0x39, 0x6c, 0x3f, 0x62, 0x26, 0xed, + 0xdc, 0x7a, 0x8f, 0x73, 0x9d, 0xaa, 0x98, 0x6d, 0x0e, 0x8f, 0x9f, 0x53, 0x24, 0x2a, 0xa9, 0x87, 0xed, 0xb7, 0x51, + 0x02, 0xfb, 0x5e, 0x6e, 0x3a, 0x4f, 0x98, 0xe9, 0x13, 0x9c, 0xf2, 0x8c, 0x58, 0x16, 0x30, 0xe5, 0x02, 0xf1, 0xde, + 0xc6, 0x4a, 0xb3, 0x4d, 0xd0, 0x10, 0xcc, 0xe4, 0x4f, 0xa5, 0x6b, 0x1b, 0xff, 0xb2, 0x88, 0x21, 0xd6, 0x41, 0x82, + 0x0f, 0x3f, 0x57, 0x0d, 0xa1, 0x94, 0xb0, 0x70, 0x9d, 0x8f, 0xef, 0x2a, 0x40, 0xca, 0x29, 0x90, 0x40, 0x42, 0x05, + 0xd4, 0xb9, 0x73, 0x46, 0xb0, 0xed, 0x27, 0x3c, 0xbf, 0x0f, 0xf2, 0x76, 0xb2, 0xc8, 0xf2, 0x5a, 0x64, 0x2b, 0x87, + 0x3b, 0x01, 0xf6, 0x7d, 0x9b, 0xea, 0x01, 0xf3, 0xd1, 0xef, 0x76, 0xb4, 0x39, 0x81, 0x85, 0xdb, 0x7a, 0x30, 0xdb, + 0x78, 0x5e, 0xfa, 0x17, 0x82, 0x5e, 0xf9, 0x1e, 0x44, 0xd3, 0x96, 0xa8, 0xc2, 0x7f, 0x7f, 0xfd, 0x9a, 0x40, 0xdc, + 0xb5, 0xe2, 0xd6, 0xff, 0xf0, 0xee, 0x26, 0x37, 0x44, 0x61, 0x3d, 0x70, 0x5d, 0xaa, 0xd3, 0xa5, 0x5a, 0x5f, 0x83, + 0x00, 0x34, 0x6e, 0x25, 0xd8, 0xdf, 0x14, 0x01, 0xb1, 0xfb, 0xd5, 0xf1, 0xaf, 0xdb, 0x11, 0x42, 0x82, 0xd4, 0xd9, + 0xce, 0x19, 0xf6, 0xbb, 0xf4, 0x41, 0x9b, 0x2d, 0x6a, 0x0a, 0xb3, 0x3f, 0x30, 0xbe, 0x26, 0x50, 0x28, 0x33, 0x9e, + 0x17, 0x99, 0xc4, 0x9d, 0xdc, 0xe1, 0x7a, 0x70, 0x5d, 0xe5, 0x2a, 0x7c, 0x24, 0xd6, 0x2a, 0x91, 0x3c, 0x73, 0xed, + 0x02, 0x7d, 0xb0, 0xe8, 0xc0, 0xae, 0x91, 0x11, 0xfe, 0xf3, 0xa8, 0x0a, 0x5e, 0x39, 0x9a, 0x95, 0x35, 0x5f, 0x8d, + 0x17, 0xbd, 0x05, 0x57, 0x7c, 0xde, 0xa9, 0x87, 0xce, 0xcc, 0xdb, 0xd1, 0xcf, 0x25, 0x83, 0xe4, 0xca, 0x62, 0x12, + 0x0a, 0x75, 0xea, 0x88, 0x32, 0x8b, 0x16, 0x18, 0x9b, 0xf9, 0xcb, 0x17, 0xcf, 0x82, 0x4e, 0x88, 0xb4, 0x9d, 0xca, + 0xce, 0x86, 0x67, 0xfc, 0x60, 0x87, 0x7a, 0x91, 0x9d, 0x4f, 0x48, 0x04, 0x0a, 0xdf, 0xba, 0xed, 0xd9, 0x7f, 0xca, + 0x43, 0xcb, 0x17, 0x5d, 0xfb, 0x93, 0x27, 0xd9, 0xed, 0x36, 0x12, 0xc5, 0x6d, 0x92, 0x90, 0xd8, 0x70, 0xd3, 0x7d, + 0x5c, 0xd6, 0x0a, 0x89, 0x4b, 0x34, 0xd7, 0x4a, 0x3b, 0xa5, 0x63, 0xec, 0xd2, 0x48, 0x59, 0xbb, 0x3d, 0x3e, 0x8b, + 0x1b, 0x7d, 0x15, 0x57, 0x20, 0x43, 0x4c, 0xd5, 0x13, 0xea, 0x9e, 0xc4, 0x35, 0x60, 0x58, 0x70, 0x64, 0x45, 0x73, + 0x21, 0x51, 0x09, 0x09, 0x86, 0xe9, 0xb4, 0x1f, 0x78, 0x29, 0xea, 0x6d, 0x10, 0x07, 0x88, 0x37, 0xf0, 0xf2, 0xfc, + 0x0a, 0x84, 0x15, 0xb5, 0x15, 0x80, 0x13, 0x55, 0x90, 0xf0, 0x15, 0x0a, 0x0c, 0x0a, 0xd4, 0x6b, 0x50, 0x04, 0x7b, + 0x44, 0xef, 0x04, 0x60, 0x90, 0x5b, 0xcd, 0x18, 0xde, 0xb6, 0x46, 0x6f, 0x03, 0x8e, 0xd9, 0xd8, 0x36, 0xcd, 0xa4, + 0x48, 0x61, 0x70, 0x7a, 0x89, 0xc5, 0x14, 0x75, 0xa3, 0xe6, 0xca, 0x92, 0xd8, 0x55, 0xdd, 0xdd, 0x9a, 0x22, 0x8d, + 0x7c, 0x58, 0x0f, 0xd1, 0x77, 0x67, 0xda, 0xe3, 0x02, 0x70, 0x0a, 0xb5, 0x61, 0xe5, 0xf6, 0x25, 0x8f, 0xb5, 0x50, + 0xf0, 0xf7, 0xbc, 0x6e, 0x20, 0xee, 0x45, 0x77, 0xea, 0x72, 0x22, 0x8c, 0xe3, 0x27, 0x03, 0xfb, 0xa9, 0x31, 0xc2, + 0x3d, 0xe4, 0x91, 0xb5, 0xb3, 0xa1, 0x0a, 0x8d, 0x70, 0x3d, 0x24, 0x9f, 0xf7, 0x97, 0xb4, 0xaf, 0x31, 0xd2, 0x71, + 0x71, 0x3e, 0xbc, 0x78, 0x63, 0x30, 0x15, 0xe0, 0x16, 0xad, 0xe7, 0xa0, 0xd9, 0x5a, 0xc6, 0x32, 0x7b, 0x70, 0xc8, + 0x8e, 0xe3, 0xda, 0xe9, 0xda, 0x22, 0xac, 0xda, 0x78, 0x20, 0x31, 0x24, 0xf0, 0x9b, 0x25, 0x86, 0x94, 0xc0, 0x4a, + 0x7c, 0xf4, 0xda, 0x40, 0x08, 0x5c, 0xbf, 0xe6, 0x20, 0x25, 0x98, 0xe5, 0xcb, 0x5f, 0xd2, 0x90, 0x8a, 0x5c, 0x0d, + 0x08, 0x19, 0xa9, 0xcf, 0x28, 0xcf, 0xac, 0xe0, 0x41, 0x71, 0xfc, 0x23, 0x46, 0x87, 0xcf, 0x9f, 0xed, 0x87, 0xc6, + 0xbe, 0x85, 0xf2, 0xa2, 0xac, 0x54, 0x66, 0x8e, 0x72, 0x42, 0x82, 0x22, 0x4b, 0x9e, 0x22, 0xb6, 0xf1, 0x15, 0x2b, + 0x41, 0x05, 0xf0, 0x8d, 0x40, 0xc6, 0xbb, 0x53, 0xc1, 0xb1, 0x89, 0x14, 0x01, 0x86, 0x76, 0x3b, 0x81, 0x84, 0xc0, + 0x20, 0x13, 0x47, 0x92, 0xab, 0xa3, 0x41, 0x62, 0x7f, 0x32, 0x8f, 0x5d, 0x38, 0x23, 0x92, 0xb5, 0x10, 0x24, 0x18, + 0x69, 0xbc, 0x57, 0x46, 0x9a, 0x80, 0xb0, 0x36, 0x40, 0xc7, 0xca, 0x3f, 0x83, 0x15, 0x96, 0x23, 0x30, 0x37, 0x2b, + 0xb8, 0x4b, 0xf3, 0x12, 0x42, 0xf4, 0x87, 0x95, 0x0a, 0xe8, 0xc7, 0x43, 0x7f, 0xce, 0x26, 0x28, 0x52, 0x10, 0xb4, + 0x42, 0x3c, 0xe4, 0x98, 0x4e, 0x14, 0x31, 0x70, 0xfa, 0xc7, 0x3d, 0x2c, 0xf6, 0x03, 0xb1, 0x60, 0x45, 0x45, 0x63, + 0x92, 0xbd, 0x14, 0xf5, 0x31, 0x62, 0xf0, 0x87, 0x19, 0x3b, 0x74, 0x9a, 0xa8, 0xa4, 0x97, 0x2a, 0x15, 0xeb, 0x60, + 0x5d, 0xa8, 0xac, 0x04, 0xe9, 0xd4, 0xe4, 0xe2, 0x1b, 0xa0, 0x28, 0x78, 0x27, 0x5e, 0x75, 0x06, 0x29, 0xbc, 0xd4, + 0x41, 0x2f, 0x40, 0xbf, 0x6c, 0x51, 0xe8, 0x19, 0x57, 0xe7, 0xde, 0xa4, 0x89, 0x2c, 0x61, 0x4f, 0xe8, 0xa0, 0x44, + 0xcb, 0x3f, 0xb8, 0xb0, 0x7a, 0x45, 0x08, 0x8e, 0x3d, 0x1f, 0xfe, 0xff, 0x69, 0x40, 0xfa, 0xf0, 0xa8, 0x87, 0x14, + 0x92, 0x08, 0x9f, 0xb0, 0xe5, 0x80, 0xae, 0x3b, 0x20, 0x29, 0x80, 0x77, 0x95, 0x31, 0x2d, 0x8f, 0x0b, 0xe2, 0xee, + 0x64, 0x4d, 0xcd, 0xd8, 0x2f, 0x13, 0xd0, 0xa9, 0xe0, 0xb8, 0x7a, 0xd7, 0x84, 0x35, 0xef, 0x6d, 0xa4, 0xe8, 0x58, + 0x60, 0x96, 0x40, 0x22, 0x44, 0x7a, 0x7f, 0x16, 0xe7, 0x42, 0xcc, 0xeb, 0x24, 0xb3, 0xdf, 0x72, 0x6a, 0x15, 0xa3, + 0x09, 0x14, 0x8e, 0x63, 0x59, 0xde, 0x93, 0x94, 0xe4, 0x09, 0x8f, 0x11, 0x8e, 0x57, 0x58, 0x47, 0xc1, 0x34, 0xa9, + 0x29, 0x29, 0x71, 0xf8, 0x5f, 0xa6, 0x34, 0x31, 0xd8, 0x95, 0xe8, 0x50, 0x11, 0x20, 0xa5, 0x59, 0x6a, 0x31, 0xf8, + 0x3c, 0x22, 0x1e, 0x0b, 0x80, 0x44, 0x44, 0xa2, 0xf0, 0x2f, 0x5d, 0xc9, 0xcf, 0x3c, 0x85, 0x88, 0xca, 0x4c, 0x83, + 0xce, 0xa2, 0xf7, 0xd5, 0x51, 0x4f, 0xd2, 0x6f, 0x74, 0x18, 0xd5, 0x2c, 0xff, 0x52, 0xf8, 0x90, 0xb8, 0xe1, 0xfe, + 0x59, 0x40, 0xa4, 0x7a, 0x93, 0x53, 0x2a, 0xed, 0x2c, 0xbd, 0xfc, 0xed, 0x0b, 0x14, 0x1b, 0x15, 0xc3, 0xf5, 0x63, + 0x7d, 0xb4, 0x21, 0xea, 0x9c, 0x1b, 0xe2, 0x80, 0x27, 0xac, 0x66, 0x4e, 0xe7, 0x8a, 0xbe, 0xb8, 0x4c, 0x1e, 0x13, + 0x53, 0x73, 0x9a, 0xde, 0xea, 0xe9, 0xb3, 0x48, 0x0e, 0x53, 0x67, 0x2b, 0x30, 0x05, 0x94, 0x61, 0xc5, 0x18, 0x59, + 0x0e, 0x24, 0xb1, 0x58, 0x72, 0xb9, 0x00, 0xa0, 0x45, 0xd6, 0x95, 0x63, 0x86, 0x42, 0xe5, 0x34, 0x32, 0x87, 0x83, + 0x8a, 0x63, 0xa4, 0x5d, 0xa9, 0x3e, 0x33, 0x84, 0x34, 0xea, 0xae, 0x01, 0x46, 0x14, 0x72, 0x96, 0xed, 0xbb, 0x28, + 0xe6, 0x22, 0x3c, 0x11, 0x06, 0xc8, 0xf3, 0x87, 0xd9, 0x66, 0xdd, 0x41, 0xe3, 0xc5, 0xc1, 0x78, 0x41, 0x65, 0xc3, + 0x48, 0xb2, 0x2c, 0x71, 0x50, 0x82, 0xc0, 0x29, 0x02, 0x8d, 0x7d, 0xfa, 0xd6, 0xa9, 0xfc, 0xfd, 0x32, 0x13, 0x89, + 0x87, 0x32, 0x8a, 0x11, 0x8f, 0x2f, 0xaa, 0xac, 0xab, 0x5b, 0x0e, 0x31, 0x7f, 0x78, 0xdb, 0xd8, 0x7e, 0xd3, 0x95, + 0x46, 0xcf, 0x0f, 0x9d, 0x15, 0x92, 0x66, 0x1c, 0xcd, 0xe9, 0xf4, 0x27, 0x71, 0x55, 0x53, 0x6c, 0x04, 0x14, 0x81, + 0xb0, 0xc7, 0x9b, 0x77, 0x4a, 0xa3, 0xbd, 0x13, 0xb0, 0x64, 0x1d, 0x83, 0x3d, 0xa9, 0xf6, 0x98, 0x90, 0xb4, 0xbc, + 0xff, 0x08, 0xcc, 0x95, 0x0a, 0x92, 0x4f, 0xc1, 0x87, 0x23, 0x94, 0x16, 0x14, 0xa2, 0x83, 0x4f, 0xba, 0x0d, 0x99, + 0x26, 0x60, 0xa2, 0x27, 0x41, 0x9e, 0x6d, 0xde, 0xb8, 0xa8, 0x42, 0x08, 0xe0, 0x81, 0xc9, 0xa6, 0x6f, 0xb2, 0xa4, + 0x55, 0xf6, 0xec, 0x3f, 0x87, 0x51, 0x96, 0xe5, 0x12, 0x9a, 0x04, 0xe9, 0x3d, 0x23, 0x72, 0xdb, 0x16, 0x9c, 0x9f, + 0xc5, 0x0a, 0xc9, 0xac, 0x2d, 0x0d, 0x69, 0x39, 0x84, 0x31, 0x28, 0x87, 0x8e, 0x08, 0xbe, 0x0c, 0x19, 0x56, 0x13, + 0x92, 0xe1, 0x5b, 0xfc, 0x07, 0x87, 0x4c, 0x52, 0x72, 0xa4, 0xc9, 0x7e, 0x2f, 0x06, 0x93, 0x5d, 0xe9, 0xa2, 0x02, + 0x1e, 0x66, 0xd3, 0x41, 0x0c, 0xc9, 0x56, 0xef, 0x29, 0xcd, 0x52, 0xcb, 0x11, 0xdc, 0x9d, 0x07, 0x52, 0xb0, 0x0d, + 0xaa, 0x9e, 0x47, 0x67, 0x1c, 0x2d, 0x00, 0xca, 0x5c, 0x92, 0xdc, 0x27, 0xc5, 0x20, 0x9b, 0x48, 0xa1, 0x80, 0x3d, + 0x65, 0x34, 0x86, 0x25, 0xb4, 0xfd, 0x71, 0x84, 0xc1, 0xd2, 0x90, 0x48, 0x91, 0x3e, 0x75, 0x62, 0xa7, 0x14, 0x8f, + 0x50, 0xf9, 0xd8, 0xba, 0x77, 0x50, 0x90, 0x40, 0x75, 0x92, 0x27, 0x08, 0xda, 0x73, 0xa0, 0x77, 0x4c, 0xc0, 0x7c, + 0x24, 0x19, 0xf1, 0xe3, 0x78, 0xbb, 0x62, 0x61, 0xf7, 0x21, 0xc5, 0x9d, 0x99, 0xdd, 0xfc, 0xc5, 0x7c, 0x8e, 0x34, + 0x67, 0x86, 0x4e, 0xea, 0x14, 0x92, 0xd9, 0x38, 0x27, 0xfa, 0x0b, 0xd2, 0xbc, 0x77, 0x11, 0x1d, 0xf1, 0x18, 0x7e, + 0x9f, 0x08, 0xae, 0x8f, 0xe7, 0x30, 0x82, 0xaf, 0xba, 0x28, 0x76, 0xb3, 0xde, 0x8a, 0x14, 0x5a, 0x3b, 0x19, 0xe2, + 0x82, 0xed, 0x3e, 0x18, 0x28, 0xa5, 0x24, 0xa2, 0xe9, 0xf7, 0x4a, 0x43, 0xc6, 0xa6, 0x41, 0x32, 0x63, 0x2b, 0x05, + 0x7a, 0x56, 0x8b, 0x38, 0x95, 0xd8, 0x91, 0x12, 0x74, 0x56, 0x38, 0x67, 0xa8, 0x01, 0x18, 0xed, 0xbc, 0xce, 0x1a, + 0x2c, 0x1d, 0x0c, 0x27, 0xae, 0xa1, 0x64, 0x8b, 0x3c, 0xc6, 0x87, 0x6e, 0xf6, 0x9e, 0xe5, 0x35, 0x40, 0xc1, 0x8f, + 0x8b, 0x20, 0xca, 0x03, 0xd4, 0x8c, 0xe0, 0xd8, 0x34, 0xab, 0x9e, 0xa4, 0x0d, 0xe7, 0x26, 0xbd, 0x19, 0x41, 0x5c, + 0xf6, 0x89, 0x8a, 0xc6, 0xff, 0x7e, 0x1c, 0x99, 0x7e, 0xb5, 0xea, 0x81, 0x94, 0x73, 0x16, 0x4a, 0xe3, 0x1b, 0x34, + 0xe2, 0x91, 0x07, 0xf6, 0xbb, 0xc6, 0x36, 0x4c, 0xa7, 0xa4, 0xa5, 0xc2, 0x7c, 0x55, 0x0d, 0xec, 0x80, 0x70, 0xd4, + 0xb2, 0x74, 0xac, 0x5f, 0x1e, 0x54, 0xf4, 0x7a, 0x9e, 0x7f, 0xb5, 0x7c, 0x6f, 0xd3, 0x02, 0x64, 0x67, 0x0c, 0x07, + 0x33, 0x26, 0x8d, 0x0a, 0xa8, 0x05, 0x64, 0xca, 0x3a, 0xa4, 0xe2, 0x69, 0x52, 0xc2, 0x91, 0x0d, 0x38, 0x1a, 0xb7, + 0x8d, 0xf4, 0x92, 0xf5, 0xd0, 0x01, 0xca, 0xac, 0xc3, 0x17, 0xb7, 0xad, 0xc7, 0x48, 0x35, 0xe0, 0x35, 0x00, 0x9c, + 0x14, 0xa9, 0x90, 0x12, 0x15, 0x52, 0x0e, 0x55, 0x4c, 0x07, 0x9d, 0x72, 0x4d, 0x9d, 0x95, 0x66, 0xe6, 0x5d, 0xdc, + 0xc1, 0x9f, 0x1e, 0x21, 0x84, 0x75, 0x19, 0x08, 0x16, 0xc5, 0x6f, 0x40, 0x10, 0x31, 0x59, 0x33, 0x7d, 0x23, 0x03, + 0x73, 0xbc, 0xa4, 0xe9, 0x57, 0x71, 0xc0, 0x2c, 0x96, 0x5e, 0x25, 0x26, 0xf1, 0x91, 0x51, 0x48, 0xdf, 0x58, 0x02, + 0xa2, 0x6e, 0x66, 0x79, 0x7e, 0xb5, 0xde, 0x33, 0x2e, 0x29, 0xf8, 0x98, 0x6f, 0xf7, 0xa3, 0xc2, 0xe1, 0xdb, 0x23, + 0x87, 0x03, 0x67, 0x90, 0x8a, 0x34, 0x66, 0x90, 0x53, 0xf0, 0xa2, 0x57, 0x98, 0xf1, 0xc7, 0x5c, 0xc9, 0x12, 0x51, + 0x78, 0x1b, 0xf0, 0xf7, 0x2c, 0x45, 0xe8, 0xf6, 0x80, 0xf0, 0x5d, 0xc8, 0xf8, 0xac, 0x84, 0x49, 0xfe, 0x08, 0x63, + 0x24, 0xb9, 0x7c, 0x1f, 0x6e, 0x2a, 0x93, 0xf1, 0xcd, 0x6f, 0x59, 0x14, 0xa8, 0x2c, 0x83, 0x69, 0x6a, 0x50, 0x52, + 0xe7, 0x00, 0x21, 0x8f, 0x9c, 0x57, 0xf5, 0xcc, 0xd4, 0x49, 0x23, 0xd2, 0x46, 0x1f, 0x64, 0x8a, 0x40, 0x74, 0x7a, + 0x10, 0x46, 0x1e, 0x08, 0x01, 0xf0, 0x1c, 0x02, 0x40, 0x4b, 0xe0, 0x0c, 0xe0, 0x98, 0xee, 0xc9, 0xa0, 0x11, 0x1a, + 0xf5, 0x9f, 0xed, 0x49, 0x54, 0xa4, 0x72, 0x1b, 0xdb, 0x0f, 0x7b, 0x8b, 0x44, 0xa3, 0x82, 0x1a, 0x8a, 0x29, 0xe2, + 0x6b, 0xfd, 0x4d, 0xe2, 0xae, 0xf7, 0xc9, 0x33, 0x8c, 0x2d, 0x4d, 0x23, 0x4d, 0x0b, 0x54, 0x3c, 0x75, 0x5f, 0xb0, + 0xb5, 0x27, 0x08, 0x69, 0x12, 0x8a, 0x32, 0x8c, 0xea, 0x9a, 0x2a, 0xc5, 0x2d, 0x1c, 0xc1, 0x51, 0xfa, 0xee, 0x44, + 0xdc, 0xfb, 0xc8, 0xf1, 0xe9, 0xcf, 0x08, 0x6a, 0x7d, 0x7e, 0xf4, 0xb6, 0xc9, 0xe9, 0x97, 0x61, 0x85, 0xbe, 0x12, + 0x11, 0xd1, 0x10, 0x06, 0x76, 0x38, 0xd0, 0x93, 0x86, 0x17, 0x63, 0x17, 0x77, 0x34, 0xd1, 0x83, 0x33, 0xf6, 0x54, + 0x86, 0xf4, 0xed, 0x99, 0xc8, 0xda, 0x16, 0xf5, 0xfa, 0xef, 0xe2, 0x4b, 0x78, 0x72, 0x3e, 0x1e, 0x93, 0x3a, 0x45, + 0x05, 0x9c, 0xa8, 0x55, 0xbd, 0x95, 0xc7, 0x60, 0x66, 0x1e, 0x7d, 0x2b, 0x26, 0x63, 0x9c, 0x9a, 0x91, 0x91, 0xb5, + 0x0b, 0x41, 0x5e, 0xec, 0x20, 0xbf, 0x53, 0x48, 0x7e, 0x74, 0x27, 0x03, 0x1a, 0x51, 0x10, 0x54, 0x8e, 0x1f, 0x28, + 0x94, 0x81, 0xb1, 0x7c, 0x6e, 0x6b, 0x3f, 0x21, 0xf6, 0x8c, 0x62, 0x19, 0xcf, 0x36, 0xe3, 0x39, 0x2f, 0x7f, 0xb1, + 0xa7, 0x41, 0x96, 0xd8, 0x7c, 0x26, 0x9e, 0x8e, 0x78, 0x68, 0x9b, 0x79, 0x41, 0xed, 0x04, 0xf0, 0x5e, 0x6a, 0x97, + 0xe6, 0x7a, 0xaa, 0xf5, 0x87, 0x91, 0xf6, 0x3e, 0x08, 0x52, 0x3e, 0x4f, 0xc2, 0xca, 0x43, 0x14, 0x28, 0xaa, 0x6d, + 0xc1, 0xf3, 0x93, 0x3d, 0xa7, 0x3c, 0x8a, 0x25, 0xb2, 0x59, 0x14, 0xd9, 0xd7, 0xac, 0xab, 0x3c, 0xa5, 0xfe, 0xc9, + 0xa8, 0x0f, 0xfe, 0x4d, 0x11, 0x1f, 0x71, 0xc3, 0x7f, 0x17, 0xab, 0xaa, 0xdf, 0xb4, 0x37, 0x5a, 0x28, 0x7d, 0x01, + 0x2f, 0x2e, 0x8a, 0xcb, 0xad, 0x5f, 0x3e, 0xf6, 0x52, 0x84, 0x26, 0x12, 0xe6, 0x16, 0x71, 0x6a, 0x3b, 0x28, 0x26, + 0xdf, 0xcf, 0x05, 0x74, 0x8a, 0x59, 0x71, 0xeb, 0x17, 0x35, 0x16, 0x1c, 0xde, 0x39, 0xe0, 0xa2, 0xf1, 0x64, 0x36, + 0x17, 0x42, 0xd1, 0x73, 0x50, 0xf5, 0x7b, 0xfb, 0x41, 0x32, 0x1b, 0xae, 0xdf, 0x38, 0x85, 0x13, 0x8b, 0x85, 0x9e, + 0x39, 0x87, 0xbf, 0x57, 0x9b, 0x1b, 0x2f, 0x65, 0xbd, 0xbe, 0x35, 0x7b, 0x7f, 0x8f, 0x9e, 0x53, 0xc6, 0xb6, 0xff, + 0x31, 0x44, 0xc2, 0x13, 0xbf, 0x5e, 0x84, 0x22, 0x5c, 0x13, 0x02, 0x1e, 0x54, 0xd2, 0xcd, 0x62, 0x55, 0x74, 0x9e, + 0xd3, 0x83, 0x77, 0x6b, 0xe1, 0xac, 0x30, 0x9c, 0xc6, 0x8e, 0xd3, 0x2e, 0xaf, 0xe8, 0xa9, 0x97, 0xb6, 0xfa, 0xa9, + 0x8b, 0xc3, 0x5b, 0x24, 0xae, 0x68, 0x39, 0x3e, 0x23, 0xd7, 0x7d, 0xd1, 0x54, 0xfe, 0x49, 0xd0, 0xf3, 0x32, 0xf8, + 0xbc, 0xc4, 0x55, 0x64, 0x6f, 0xbf, 0x6f, 0x57, 0x66, 0xb8, 0x5d, 0x79, 0xe7, 0x66, 0x77, 0xbf, 0xa3, 0xaa, 0xc6, + 0x9d, 0xe9, 0x6c, 0xe4, 0x1f, 0x96, 0x91, 0xd6, 0xd3, 0x2e, 0xdf, 0xfe, 0xaf, 0xd1, 0xef, 0x1f, 0xb7, 0x9e, 0xff, + 0xd2, 0x94, 0x32, 0x9f, 0xea, 0xb6, 0xe3, 0xa9, 0xe5, 0x72, 0x37, 0x56, 0xaf, 0xaf, 0x3f, 0xf9, 0x8c, 0x28, 0x3f, + 0x61, 0x12, 0x6c, 0x47, 0xeb, 0x32, 0xca, 0x95, 0x70, 0x8d, 0x66, 0xf6, 0xab, 0xed, 0x71, 0xfd, 0xb0, 0x9c, 0x66, + 0xf1, 0xea, 0xa3, 0xe4, 0x71, 0xb3, 0xb5, 0xbb, 0x5d, 0xcd, 0x4b, 0x9b, 0x57, 0x0b, 0x4a, 0x63, 0xc2, 0xd7, 0xf6, + 0x23, 0x5b, 0x30, 0xde, 0x04, 0x24, 0x7f, 0x20, 0x6a, 0xbe, 0xab, 0x37, 0x7d, 0x5b, 0x4d, 0xa9, 0x98, 0xe6, 0x34, + 0x11, 0x4d, 0x33, 0xaa, 0x21, 0x4e, 0x8a, 0x30, 0x0e, 0xb6, 0x33, 0xcf, 0x4f, 0x18, 0xe0, 0x9c, 0xca, 0x5d, 0x4c, + 0xfc, 0xcb, 0x4f, 0x53, 0x6d, 0xee, 0x34, 0xcb, 0x11, 0x4c, 0x8e, 0x62, 0x77, 0x72, 0xd8, 0x6e, 0xa0, 0x59, 0xde, + 0xe2, 0x0d, 0x55, 0xa5, 0x94, 0xe7, 0x62, 0x26, 0x81, 0xa2, 0x52, 0x33, 0xe8, 0x70, 0xa0, 0x9b, 0xb9, 0xd9, 0x4f, + 0x87, 0xff, 0x1e, 0xbb, 0x88, 0xe1, 0x14, 0xfe, 0xb9, 0x18, 0x84, 0x50, 0xd8, 0xb7, 0x90, 0x6a, 0xc2, 0x91, 0xb2, + 0xe1, 0x3b, 0x56, 0xe2, 0xef, 0x38, 0x33, 0x61, 0x34, 0x13, 0x61, 0x45, 0xd3, 0x7c, 0x06, 0xdc, 0xe3, 0x82, 0xb1, + 0x27, 0xc2, 0x6f, 0x6d, 0xb7, 0xec, 0xd4, 0xf5, 0xd9, 0xd0, 0x39, 0xc9, 0x02, 0x8e, 0x1b, 0x02, 0x07, 0xd0, 0xb8, + 0x33, 0x2f, 0xb2, 0xb5, 0xae, 0x57, 0x1f, 0x62, 0x2e, 0xba, 0x15, 0x69, 0x32, 0x7e, 0xab, 0xe8, 0xd2, 0xdd, 0x05, + 0x20, 0x69, 0xf5, 0xee, 0xc7, 0x5e, 0x3f, 0x38, 0x72, 0xf3, 0x56, 0xef, 0x65, 0x18, 0x1e, 0x6b, 0xf2, 0x91, 0x86, + 0xed, 0xe4, 0x86, 0x97, 0x2b, 0xd5, 0x44, 0x9b, 0x71, 0x5b, 0x5e, 0xb1, 0xd6, 0x1b, 0xd2, 0x95, 0xdd, 0x79, 0xa8, + 0x72, 0x1b, 0x2f, 0x5b, 0x84, 0xc1, 0x5c, 0x9c, 0xcd, 0xe4, 0x17, 0x48, 0xf4, 0xf5, 0xcd, 0x5c, 0xbe, 0x03, 0xce, + 0x1e, 0xa1, 0x4e, 0xf8, 0xeb, 0x55, 0x4f, 0xa6, 0x31, 0x89, 0x13, 0x9b, 0xf0, 0x70, 0xba, 0x52, 0x2c, 0x14, 0x02, + 0xef, 0xa6, 0x87, 0x20, 0xd1, 0xcf, 0x98, 0x52, 0x99, 0x74, 0x0f, 0x4d, 0x1a, 0x63, 0x5c, 0x9a, 0x65, 0xa3, 0x2e, + 0x2d, 0xe2, 0xa7, 0xcd, 0x35, 0xd3, 0x9a, 0x2d, 0x8d, 0x8a, 0x2a, 0xdb, 0xdc, 0xaf, 0x6a, 0x6f, 0xab, 0x7a, 0xf7, + 0x10, 0x64, 0xb0, 0x73, 0xe5, 0xf9, 0x45, 0x59, 0x69, 0xc6, 0x60, 0xf0, 0x94, 0x6f, 0xc4, 0x02, 0x19, 0xb7, 0x79, + 0x77, 0x98, 0xf8, 0xca, 0xa4, 0xbf, 0x76, 0x0d, 0x34, 0xe6, 0xee, 0x4f, 0xd6, 0xe9, 0xca, 0x1a, 0x23, 0x6e, 0x5b, + 0x2d, 0xe1, 0x02, 0x27, 0x9e, 0x42, 0xb9, 0xe9, 0xf6, 0x9d, 0x2f, 0x0b, 0x93, 0x9a, 0xbc, 0xe0, 0xf5, 0x1b, 0x10, + 0x05, 0xb3, 0x00, 0x01, 0x11, 0xf7, 0xa2, 0xd8, 0x74, 0xc4, 0x22, 0x06, 0x09, 0xf4, 0x06, 0x42, 0xe0, 0x0c, 0x7f, + 0x50, 0xd0, 0xb5, 0x1d, 0x18, 0x01, 0x00, 0xe4, 0x66, 0x43, 0xea, 0xa5, 0x52, 0xb9, 0x27, 0xa2, 0x6a, 0xa8, 0x56, + 0x97, 0x74, 0xd7, 0x5c, 0x97, 0xc0, 0x79, 0x9d, 0xb5, 0xf9, 0x53, 0x09, 0xcb, 0xba, 0x21, 0xce, 0x65, 0x85, 0x02, + 0x13, 0x15, 0xcd, 0x99, 0xa7, 0x82, 0xc0, 0x5a, 0x95, 0xac, 0xf1, 0x2c, 0x85, 0xdd, 0xfd, 0x59, 0xcd, 0xdd, 0x80, + 0xd3, 0xd8, 0x41, 0x98, 0x19, 0xf0, 0xb6, 0x7d, 0xbc, 0x61, 0xec, 0xed, 0xca, 0x59, 0xf0, 0xc8, 0x24, 0x5f, 0x96, + 0xee, 0x7e, 0x82, 0x1b, 0x2b, 0xfd, 0x94, 0x3e, 0x87, 0xb0, 0x24, 0xfc, 0x77, 0x85, 0xe0, 0xba, 0x34, 0xbe, 0xab, + 0x9e, 0x0b, 0x22, 0x78, 0xba, 0x64, 0x6f, 0x13, 0x79, 0x5f, 0x91, 0x13, 0x49, 0xf7, 0xce, 0x1a, 0x1f, 0x89, 0xe5, + 0xe7, 0xda, 0xf8, 0xbb, 0xa7, 0xfa, 0xca, 0x2a, 0x27, 0x91, 0x8d, 0xcf, 0xe5, 0x80, 0x65, 0x9e, 0xf7, 0x29, 0xd4, + 0x58, 0xa0, 0xc7, 0x30, 0x7b, 0xdc, 0xb0, 0x88, 0x9f, 0xc1, 0x16, 0xee, 0x94, 0x9a, 0xc6, 0xb4, 0x92, 0xac, 0x52, + 0x04, 0xce, 0xa7, 0xe0, 0x72, 0xce, 0xd3, 0xed, 0x86, 0xc4, 0x2f, 0xed, 0xa3, 0xb8, 0x0e, 0xfa, 0x69, 0x29, 0x36, + 0x7f, 0xfa, 0x8a, 0x16, 0x92, 0xd8, 0x82, 0xce, 0xcb, 0x16, 0x22, 0x60, 0x2f, 0x3e, 0xa5, 0xec, 0xb6, 0xff, 0x28, + 0xd5, 0x0c, 0x78, 0x95, 0x0f, 0x94, 0xa1, 0x18, 0x33, 0xa4, 0xb4, 0xe2, 0xaa, 0x13, 0x49, 0xd0, 0xdb, 0x3c, 0x15, + 0x02, 0xa7, 0xb0, 0x0f, 0xa5, 0x64, 0xa2, 0x1f, 0xb0, 0xcc, 0x72, 0x97, 0xbe, 0xe4, 0x9a, 0xf5, 0x76, 0xd7, 0x28, + 0x09, 0xcc, 0x04, 0xf9, 0x59, 0xf0, 0x89, 0xdb, 0x9e, 0xdc, 0x2d, 0xb9, 0x22, 0x30, 0x7f, 0x92, 0x89, 0xe0, 0xd8, + 0x40, 0x3e, 0x93, 0x8b, 0x27, 0x91, 0xa8, 0xa4, 0xd0, 0x2e, 0x39, 0x3a, 0x7a, 0xd7, 0x49, 0x6a, 0x15, 0x6b, 0x1d, + 0x0a, 0x1d, 0xb7, 0x71, 0x53, 0x59, 0xc7, 0x73, 0x12, 0xa3, 0xf6, 0xe8, 0x2e, 0x49, 0xdb, 0xec, 0xee, 0x54, 0x1a, + 0xa1, 0x92, 0xea, 0x0a, 0x19, 0x4b, 0x33, 0x92, 0x38, 0x3f, 0xb1, 0x45, 0x88, 0x18, 0x90, 0x58, 0x3a, 0xcb, 0x21, + 0x56, 0xdd, 0xa7, 0x0d, 0xcb, 0x71, 0xe8, 0x94, 0x25, 0x01, 0x45, 0xb3, 0x34, 0x46, 0x07, 0x03, 0xc7, 0xd1, 0x1c, + 0x55, 0x0a, 0x8c, 0x99, 0x97, 0x39, 0xec, 0x7c, 0x95, 0xa1, 0x73, 0x69, 0xa4, 0xd9, 0xf0, 0x75, 0x31, 0xb5, 0x47, + 0xa9, 0xce, 0xb5, 0x11, 0xc9, 0xc8, 0x41, 0x7b, 0x2e, 0x53, 0x11, 0x56, 0x71, 0x51, 0xee, 0xc6, 0x92, 0x59, 0x17, + 0x62, 0x9c, 0x8c, 0xf6, 0x6a, 0xb2, 0x68, 0x55, 0x40, 0x39, 0xbe, 0x64, 0xda, 0x03, 0x2e, 0x59, 0xdb, 0x7e, 0x29, + 0x27, 0x75, 0x81, 0xe6, 0x7c, 0xac, 0x2b, 0xfc, 0x8d, 0x2c, 0x80, 0x31, 0x3b, 0xf2, 0xa5, 0xdd, 0x6e, 0xfe, 0x25, + 0x27, 0xdb, 0x5f, 0xc6, 0x39, 0xf3, 0x98, 0x2b, 0x61, 0xec, 0x5a, 0x4d, 0xf4, 0x64, 0x86, 0x1a, 0x9f, 0x13, 0x70, + 0xc9, 0xeb, 0x27, 0x03, 0xec, 0x8c, 0xc7, 0xb9, 0xa4, 0x9d, 0xd2, 0xa5, 0xd2, 0x52, 0x9c, 0xc6, 0xdc, 0x64, 0x2d, + 0xab, 0xdd, 0x3f, 0x0f, 0xb1, 0x5c, 0xc1, 0xbe, 0xf5, 0x91, 0x75, 0x1f, 0xdf, 0x97, 0x29, 0x6f, 0xbd, 0x9a, 0xd1, + 0xaf, 0xb6, 0xc2, 0x84, 0xbd, 0xa3, 0x6b, 0x0c, 0x93, 0x1d, 0x6b, 0x15, 0xa4, 0x3d, 0xb2, 0xa3, 0x45, 0x32, 0x1e, + 0x4e, 0x68, 0x55, 0x7b, 0x21, 0x43, 0x1e, 0x7e, 0x6e, 0x34, 0x12, 0x8b, 0xa4, 0x58, 0x40, 0xe7, 0x7b, 0x54, 0x57, + 0x4b, 0x8a, 0xe9, 0x49, 0x6b, 0x32, 0x78, 0xd4, 0x99, 0x53, 0xe7, 0xca, 0x2f, 0x2c, 0xf7, 0x55, 0x53, 0x06, 0x03, + 0x71, 0xfd, 0x09, 0xea, 0xae, 0xec, 0x71, 0x2e, 0x31, 0x81, 0x9a, 0xb2, 0x68, 0xe2, 0x48, 0x32, 0xf9, 0xe5, 0xcb, + 0x4c, 0x9b, 0xec, 0xc3, 0x55, 0x24, 0x82, 0x17, 0x23, 0xb1, 0x85, 0xdf, 0xe9, 0x02, 0xcb, 0xa2, 0x3e, 0x6c, 0x1a, + 0x73, 0xe3, 0x28, 0x19, 0xae, 0x50, 0x04, 0x8e, 0x5a, 0x60, 0xa0, 0x24, 0x27, 0x6a, 0xb2, 0x66, 0x76, 0x9e, 0x0e, + 0x5e, 0x5c, 0x68, 0x1d, 0xdf, 0x11, 0x3a, 0xa4, 0x33, 0x94, 0x57, 0xf0, 0xcd, 0xbe, 0xcb, 0x5c, 0x60, 0xaa, 0x25, + 0x7d, 0x8c, 0x5e, 0x33, 0x7d, 0xec, 0x1a, 0xbc, 0x10, 0x3d, 0xb7, 0x96, 0x67, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, + 0x1e, 0x87, 0x77, 0x07, 0x59, 0xb1, 0x88, 0x6c, 0x77, 0x2e, 0x2e, 0x5b, 0x14, 0xe8, 0x14, 0x27, 0xeb, 0x36, 0xa8, + 0xd7, 0xa0, 0x29, 0xe7, 0x58, 0xa5, 0x31, 0x3b, 0x30, 0x43, 0x90, 0x0b, 0x1d, 0xb6, 0x44, 0xa9, 0xf4, 0x23, 0x4e, + 0x04, 0x1b, 0xac, 0xee, 0xcc, 0x66, 0x59, 0xb3, 0xc3, 0x9e, 0x93, 0xfa, 0x9f, 0x78, 0xd7, 0xb6, 0x9c, 0xd7, 0xc2, + 0x48, 0x13, 0xb2, 0xb1, 0x40, 0x7a, 0x94, 0xbf, 0xf9, 0xdb, 0x87, 0x7c, 0x61, 0xfa, 0xf5, 0xb0, 0x2a, 0x64, 0xc6, + 0x4e, 0xe0, 0x00, 0x32, 0x41, 0x06, 0x1f, 0x29, 0x3d, 0x93, 0x82, 0x91, 0xd6, 0xf7, 0xc2, 0x0c, 0xb6, 0x63, 0xb2, + 0x10, 0x1d, 0xab, 0xdd, 0x0c, 0x20, 0x87, 0x36, 0xb6, 0x7c, 0x0d, 0xa5, 0x55, 0x92, 0x96, 0x72, 0x71, 0x40, 0x61, + 0xd5, 0x5b, 0x71, 0xd3, 0x4b, 0xfb, 0x08, 0x4d, 0xbf, 0x4b, 0x06, 0xca, 0x94, 0x80, 0xf6, 0x33, 0xf3, 0x4a, 0x07, + 0x11, 0x1e, 0xa6, 0x34, 0x01, 0xd8, 0x10, 0x2b, 0x5b, 0xec, 0xad, 0xc5, 0xc2, 0x7b, 0xd2, 0x02, 0xd6, 0x34, 0x73, + 0xd8, 0x09, 0x58, 0x5f, 0xee, 0x26, 0x62, 0x53, 0xfe, 0x6c, 0x25, 0xd6, 0x1c, 0x71, 0x11, 0x1f, 0xbd, 0x5f, 0xd7, + 0xa7, 0x29, 0x16, 0xa9, 0x73, 0x6f, 0x3d, 0xc9, 0x00, 0xff, 0xbc, 0x78, 0x0e, 0x9c, 0xde, 0x25, 0xdf, 0xf7, 0xcf, + 0xd6, 0x92, 0xc5, 0xd5, 0xc0, 0xf1, 0x55, 0x2b, 0x93, 0xd3, 0x15, 0x2d, 0x05, 0x65, 0xb0, 0xf9, 0xbe, 0x77, 0x49, + 0x21, 0x6e, 0xa0, 0x3c, 0x9a, 0xf9, 0x08, 0xe3, 0xca, 0x2b, 0x7c, 0x4a, 0x8d, 0x78, 0x68, 0x26, 0x2c, 0x10, 0x49, + 0xad, 0x44, 0xc5, 0x82, 0x54, 0x55, 0x4f, 0x5f, 0x90, 0xa1, 0xe7, 0x02, 0x3e, 0xeb, 0x53, 0x3c, 0x38, 0x5b, 0x3b, + 0x0e, 0xa2, 0x68, 0x2b, 0x7e, 0x56, 0xa8, 0x10, 0xfc, 0x57, 0x81, 0x1a, 0x29, 0x32, 0x02, 0xcc, 0xf5, 0x84, 0xba, + 0x3f, 0x90, 0x27, 0x3c, 0x3f, 0xa5, 0x82, 0xa5, 0x42, 0x4e, 0xea, 0x94, 0x88, 0x28, 0xff, 0xca, 0xcb, 0x26, 0x41, + 0xb3, 0x9c, 0xd2, 0x98, 0x7c, 0xc4, 0x92, 0x08, 0xae, 0x66, 0x4d, 0x3e, 0xfd, 0x88, 0x52, 0xdd, 0xcb, 0x0c, 0xd7, + 0xa6, 0x04, 0x0d, 0x85, 0x6f, 0x3c, 0xe0, 0xe8, 0xd3, 0xed, 0x74, 0x42, 0x6e, 0x4b, 0x19, 0x9c, 0x7c, 0x44, 0x87, + 0xb9, 0xf5, 0xd5, 0x4c, 0xd0, 0xdc, 0x98, 0xb7, 0x0d, 0xc5, 0x2d, 0x21, 0xdb, 0xec, 0xd7, 0xbb, 0x35, 0xf9, 0x3a, + 0xfd, 0xe0, 0x92, 0xa6, 0x4c, 0xe8, 0x62, 0xe2, 0x17, 0x61, 0x86, 0x36, 0xdc, 0xf0, 0xe5, 0x8b, 0xed, 0xe5, 0x70, + 0x1c, 0x20, 0x73, 0x2c, 0xca, 0xef, 0xa8, 0xed, 0x19, 0x50, 0x50, 0x8e, 0xd1, 0x55, 0x6b, 0xc0, 0xd8, 0x8e, 0xad, + 0x75, 0x5f, 0x9e, 0x64, 0x0d, 0x50, 0x4f, 0xb5, 0x72, 0x8a, 0xc1, 0xd8, 0x87, 0x96, 0x6e, 0x03, 0x6c, 0x90, 0x3a, + 0x2c, 0x1c, 0x4c, 0xeb, 0x1f, 0x2d, 0x5e, 0x68, 0x01, 0x22, 0x6f, 0x92, 0xa5, 0x35, 0xde, 0x13, 0x7f, 0x07, 0xd7, + 0x14, 0x7c, 0x8f, 0xe3, 0x07, 0x89, 0xf7, 0x3c, 0xbb, 0xac, 0x28, 0x2a, 0x61, 0x9e, 0x0b, 0x6f, 0x88, 0xb0, 0x62, + 0x82, 0x98, 0x63, 0x1e, 0x72, 0x42, 0xf6, 0x85, 0x5b, 0xd6, 0xb6, 0x3a, 0x04, 0x3c, 0xbc, 0xef, 0xfb, 0xe9, 0x85, + 0x80, 0xa2, 0x2b, 0x3b, 0x77, 0x9c, 0x47, 0x33, 0x60, 0x35, 0x43, 0xbe, 0xc5, 0x76, 0x98, 0x8a, 0x32, 0x4a, 0x08, + 0xe2, 0x06, 0x2b, 0xb0, 0x30, 0xf4, 0xac, 0x71, 0xf5, 0x89, 0xd3, 0x7a, 0xca, 0x00, 0x80, 0x52, 0xda, 0xa1, 0x7b, + 0x86, 0x32, 0x61, 0xf4, 0xd2, 0x2a, 0x50, 0x6e, 0xb9, 0x3a, 0x78, 0xd9, 0xb9, 0xc7, 0x30, 0xb0, 0x33, 0x5b, 0xeb, + 0x4c, 0xe3, 0x40, 0x64, 0x19, 0x08, 0x10, 0x87, 0xba, 0x48, 0x95, 0x86, 0xa2, 0xeb, 0x00, 0xaf, 0x45, 0x7d, 0x92, + 0x61, 0x61, 0x21, 0xee, 0x56, 0xa2, 0x63, 0xc0, 0x34, 0x5e, 0xe3, 0xed, 0x42, 0x2a, 0x04, 0x5e, 0x09, 0x91, 0x07, + 0x12, 0xd9, 0x03, 0xed, 0xa0, 0x6c, 0x00, 0x24, 0xb9, 0x13, 0x5c, 0x29, 0x48, 0x6b, 0x09, 0xe5, 0x64, 0xff, 0x4f, + 0x54, 0x1a, 0x65, 0x02, 0xf2, 0x99, 0x6b, 0x89, 0x49, 0xe3, 0x25, 0x30, 0x17, 0x0e, 0x24, 0x1f, 0x66, 0xb0, 0x93, + 0x05, 0x8d, 0xc8, 0x94, 0xe9, 0xdc, 0x0a, 0xb6, 0xf1, 0xea, 0x4d, 0xd2, 0x48, 0x54, 0x98, 0xfe, 0xe6, 0x57, 0x97, + 0x4f, 0x5d, 0x18, 0x61, 0xf9, 0x5b, 0x2e, 0xfb, 0x1c, 0xf9, 0x4d, 0x18, 0x25, 0xed, 0x6c, 0xf8, 0x52, 0xc9, 0x74, + 0xdc, 0x9e, 0x9f, 0x69, 0x6d, 0xb4, 0x78, 0x0f, 0xf2, 0x05, 0xef, 0x41, 0x75, 0x47, 0x92, 0xec, 0x73, 0x5a, 0x93, + 0xd4, 0x35, 0xaa, 0xca, 0x70, 0x90, 0x68, 0x8c, 0x8b, 0xd4, 0x9a, 0x98, 0x53, 0xb3, 0x78, 0x1a, 0x40, 0x32, 0x8d, + 0xfd, 0x8c, 0x2a, 0x0f, 0x2c, 0x27, 0x36, 0x2f, 0xa6, 0x27, 0xd2, 0x68, 0xba, 0x20, 0x97, 0x9f, 0x52, 0xef, 0x66, + 0x4a, 0xd1, 0xb2, 0x58, 0x86, 0xc3, 0xd9, 0x41, 0x98, 0x23, 0x5d, 0xbe, 0x9a, 0xeb, 0xa3, 0x2f, 0x19, 0x26, 0xa5, + 0x4b, 0x57, 0xf2, 0x67, 0x94, 0x2c, 0x5f, 0x08, 0xab, 0x0f, 0xdb, 0x26, 0x08, 0x64, 0xd4, 0xa0, 0x1c, 0xe1, 0xd6, + 0xf2, 0x00, 0x1b, 0x1b, 0xf2, 0xe0, 0xec, 0xa6, 0x2a, 0x7b, 0x64, 0x9a, 0xb3, 0xa9, 0xa0, 0xf2, 0x46, 0xa3, 0x85, + 0x66, 0x26, 0x9b, 0xaf, 0x2e, 0xbe, 0x4a, 0x90, 0x1b, 0xa7, 0x83, 0xd5, 0x52, 0x7d, 0x68, 0x42, 0x56, 0x1f, 0xc8, + 0xcb, 0xa4, 0xa8, 0xaa, 0x85, 0x22, 0xed, 0x94, 0xfc, 0x34, 0x9a, 0xba, 0xeb, 0x4e, 0x72, 0x42, 0x65, 0x35, 0x89, + 0x8a, 0x02, 0x5b, 0x78, 0x59, 0x08, 0x15, 0x40, 0x71, 0xb7, 0xfb, 0xa1, 0x02, 0xe5, 0xcf, 0x45, 0x0e, 0xee, 0x78, + 0xaf, 0x0e, 0x4c, 0xcb, 0x00, 0x92, 0xfc, 0x4c, 0x26, 0xbd, 0x69, 0xdc, 0xbb, 0x87, 0xf2, 0xf0, 0x59, 0x54, 0x62, + 0xee, 0x43, 0x7e, 0x15, 0x03, 0x8d, 0x59, 0x02, 0xee, 0xb7, 0xcb, 0x5e, 0x7c, 0x94, 0x74, 0x82, 0xcc, 0x50, 0xb9, + 0x36, 0xde, 0x37, 0xf5, 0x48, 0x85, 0x91, 0x4b, 0x81, 0x7c, 0x70, 0xf7, 0xfb, 0x3d, 0x40, 0x31, 0xfe, 0xa2, 0x7d, + 0xf1, 0x3a, 0x29, 0x37, 0x31, 0x04, 0x24, 0x7a, 0x5d, 0x8e, 0x36, 0x08, 0xc8, 0xd1, 0x24, 0x41, 0x7e, 0x3c, 0x9e, + 0x49, 0xbe, 0xec, 0x38, 0xc5, 0x36, 0x95, 0x25, 0xa6, 0xdc, 0xfb, 0xe5, 0x2a, 0x0f, 0x84, 0xfd, 0x39, 0x91, 0x46, + 0xa4, 0x00, 0x30, 0xcc, 0x16, 0x78, 0x04, 0x0e, 0x34, 0xf1, 0xe2, 0x44, 0xad, 0xc2, 0x81, 0x86, 0xcd, 0xd9, 0x8b, + 0x98, 0x54, 0x64, 0xcc, 0x3e, 0x7e, 0x65, 0x5c, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xe7, 0xb2, 0x4a, 0x00, + 0xb5, 0x10, 0x0a, 0xa1, 0xc1, 0x20, 0xc1, 0xf8, 0x46, 0xef, 0x4f, 0xa8, 0x47, 0x14, 0x8a, 0x57, 0xab, 0xc5, 0x44, + 0xbb, 0x7c, 0xc7, 0x2d, 0x4c, 0x97, 0x8c, 0x41, 0x75, 0xaf, 0xd8, 0x23, 0x2f, 0x5e, 0xad, 0xca, 0xed, 0xd8, 0xa9, + 0xea, 0xd6, 0x18, 0xa1, 0xee, 0xe6, 0xb5, 0xce, 0x8d, 0x69, 0x22, 0xb8, 0x2c, 0x68, 0xb6, 0x38, 0xf4, 0x74, 0xfe, + 0xe1, 0xca, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0x27, 0x89, 0x60, 0xa8, 0x51, 0x5e, 0x08, 0x23, 0x52, 0xff, + 0xce, 0x90, 0x7b, 0x96, 0xa2, 0x53, 0x6d, 0x54, 0x97, 0x2d, 0x80, 0x2d, 0x7d, 0x0d, 0x23, 0x43, 0x21, 0x74, 0xc4, + 0x30, 0xd2, 0x2e, 0xf5, 0x51, 0x66, 0x48, 0x16, 0x5d, 0x57, 0x45, 0x90, 0x79, 0xd7, 0x4e, 0xde, 0x24, 0x89, 0x12, + 0x6a, 0xe8, 0x67, 0xe6, 0x93, 0x3a, 0x3b, 0x89, 0x53, 0x5a, 0x4b, 0xa1, 0xe6, 0xa4, 0xba, 0x8e, 0xe9, 0x3b, 0x55, + 0x29, 0xa1, 0x27, 0x8c, 0xdd, 0x7b, 0x33, 0x78, 0xd5, 0xc6, 0x18, 0x9f, 0x6b, 0xfe, 0x79, 0xd2, 0x0e, 0xe3, 0xd0, + 0x03, 0xd4, 0x02, 0x39, 0x85, 0xd6, 0x80, 0xcc, 0xff, 0xdd, 0xd9, 0xd9, 0x9e, 0x10, 0xb6, 0x4d, 0x82, 0x96, 0xcb, + 0xad, 0x5c, 0x4f, 0x42, 0x59, 0x37, 0x4f, 0x5a, 0xe7, 0x24, 0xb1, 0x38, 0xd8, 0x22, 0x39, 0x52, 0xe6, 0x13, 0x7c, + 0xce, 0x79, 0x42, 0xea, 0x07, 0x5b, 0xf8, 0xce, 0xc6, 0x77, 0x15, 0x21, 0xf7, 0x3d, 0x36, 0x2f, 0x63, 0x08, 0x11, + 0x89, 0xc9, 0xdc, 0xab, 0x23, 0x1f, 0x44, 0x91, 0x0b, 0x55, 0x7b, 0xc4, 0x3c, 0x21, 0xc0, 0x54, 0xb5, 0x1f, 0x9c, + 0xf6, 0xe5, 0x42, 0xf6, 0xb7, 0x58, 0x19, 0xa0, 0x9c, 0x33, 0xa9, 0x97, 0xff, 0xf9, 0x52, 0xeb, 0xfe, 0xf7, 0x0b, + 0xac, 0xcb, 0x6d, 0x3b, 0xdf, 0xe9, 0x01, 0x60, 0x00, 0x78, 0x5d, 0x50, 0xb5, 0xca, 0x8b, 0x5d, 0x7d, 0x51, 0x6f, + 0x9b, 0x20, 0x24, 0x01, 0xef, 0x2a, 0xe9, 0xff, 0x3e, 0xd3, 0x40, 0xd0, 0x7c, 0x93, 0xec, 0x8f, 0x6c, 0x10, 0x89, + 0x3c, 0xf5, 0xa4, 0xc5, 0xc7, 0x3b, 0xe1, 0xdd, 0xc1, 0xf8, 0x65, 0x6c, 0x5d, 0xd1, 0x3d, 0xf3, 0x07, 0x09, 0x2c, + 0x07, 0x6a, 0xb7, 0x1e, 0xbd, 0x71, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x33, 0x98, 0x12, 0x07, 0x81, 0xa2, 0x91, 0x16, + 0xe0, 0x49, 0x4c, 0x13, 0x4c, 0x0b, 0x08, 0xa9, 0x53, 0x40, 0x62, 0xbe, 0x1d, 0x96, 0x23, 0x78, 0x95, 0x22, 0x27, + 0x9e, 0x38, 0x37, 0xab, 0x0a, 0xe8, 0x3e, 0x44, 0xd5, 0xfc, 0x74, 0xf3, 0x06, 0x77, 0xe0, 0x26, 0xf6, 0x8d, 0xe3, + 0x0f, 0x71, 0xbf, 0xa1, 0x81, 0xe4, 0x1c, 0x12, 0x8b, 0xbc, 0xe6, 0x61, 0x3c, 0x93, 0x84, 0x3a, 0xdc, 0x42, 0x48, + 0xe7, 0x17, 0x30, 0x98, 0x17, 0x4c, 0x63, 0xab, 0xce, 0x22, 0x20, 0xe4, 0x3c, 0xbe, 0x1d, 0xc7, 0xb7, 0x1e, 0xac, + 0x07, 0xd1, 0x5e, 0x44, 0xfc, 0xad, 0x2d, 0x6a, 0x14, 0x2a, 0x0f, 0xa7, 0xd6, 0xd7, 0xd4, 0x70, 0x0c, 0x71, 0xf8, + 0x57, 0x90, 0x48, 0x09, 0x64, 0xb7, 0xed, 0x6b, 0x2e, 0xe8, 0xf4, 0x6e, 0xa7, 0x23, 0xb4, 0xd6, 0x0c, 0x2a, 0x73, + 0xd5, 0xac, 0xc1, 0xca, 0xb4, 0xd3, 0xff, 0x61, 0x73, 0x5b, 0x92, 0x80, 0x20, 0x5a, 0xe9, 0xf7, 0x55, 0x98, 0xb0, + 0xc4, 0x18, 0x03, 0x1e, 0x09, 0x32, 0xe7, 0x29, 0x44, 0x12, 0x0b, 0x30, 0x1c, 0xad, 0xd5, 0xc5, 0x7f, 0x56, 0xdc, + 0xfa, 0xd1, 0xe8, 0x4d, 0x9b, 0x64, 0xca, 0xcd, 0xaa, 0x05, 0xf0, 0xc7, 0x59, 0x65, 0xd9, 0xd6, 0x33, 0x40, 0xca, + 0x93, 0x2c, 0x09, 0x2e, 0xdd, 0x82, 0x93, 0xf2, 0x49, 0x4a, 0x9b, 0xe4, 0xca, 0xfd, 0xc2, 0x55, 0xf6, 0x3d, 0x53, + 0x04, 0x87, 0xf5, 0x4c, 0x73, 0x60, 0x01, 0x16, 0xcc, 0xa5, 0x74, 0xb1, 0xda, 0x19, 0x12, 0x09, 0x56, 0x92, 0x0f, + 0xcb, 0x0c, 0x49, 0x8f, 0x6f, 0xab, 0x8b, 0x84, 0x9c, 0xf1, 0xbc, 0xad, 0x01, 0x07, 0x78, 0x77, 0x2e, 0x46, 0x5a, + 0xef, 0xb0, 0x23, 0xef, 0x9d, 0x92, 0x52, 0x52, 0x35, 0x05, 0xe4, 0xd1, 0x86, 0x20, 0xed, 0x36, 0xc5, 0xa0, 0xbf, + 0x19, 0x2c, 0x8d, 0x7b, 0xcf, 0x25, 0x46, 0x0a, 0xa4, 0xda, 0x99, 0x3e, 0x70, 0xe1, 0x2f, 0xc8, 0xa9, 0xf9, 0xe0, + 0x9d, 0x6d, 0xd8, 0x4f, 0x4b, 0x0e, 0x08, 0xc5, 0xc5, 0x5d, 0x7f, 0xd4, 0x27, 0xb6, 0x58, 0x1c, 0x5c, 0xbe, 0x51, + 0xf6, 0xa8, 0x09, 0xec, 0xc1, 0x07, 0x5a, 0x46, 0x2a, 0x0d, 0x0a, 0x25, 0xc5, 0xbb, 0x73, 0x63, 0xda, 0x5b, 0x9b, + 0x5a, 0x56, 0x58, 0x55, 0x83, 0x55, 0xf5, 0xb1, 0xc4, 0xd2, 0xd2, 0xb6, 0xd8, 0x02, 0x73, 0xdd, 0x7b, 0x01, 0x26, + 0x5f, 0xc7, 0x47, 0x4c, 0x4b, 0x89, 0xee, 0x41, 0xa2, 0x2f, 0xe3, 0x30, 0x80, 0x8b, 0x2a, 0x08, 0x20, 0xbd, 0xae, + 0xe3, 0x48, 0x6c, 0xd6, 0x98, 0xe8, 0xb0, 0x68, 0xd3, 0x08, 0x54, 0x84, 0x1a, 0x18, 0x01, 0x2d, 0xe4, 0xca, 0x54, + 0x2c, 0x9d, 0xf9, 0xec, 0x02, 0x4b, 0x9f, 0xfb, 0x69, 0x5b, 0xdb, 0x5d, 0x31, 0x4b, 0x15, 0x24, 0xa5, 0x51, 0xd7, + 0x1b, 0x7d, 0xbb, 0x76, 0x67, 0x5d, 0xe3, 0x3d, 0x6e, 0xa4, 0x68, 0x6d, 0x2a, 0xd7, 0x47, 0xc9, 0x76, 0xfb, 0xdd, + 0xd2, 0x02, 0xd5, 0xcc, 0x59, 0x5a, 0x3b, 0x45, 0xf6, 0x3b, 0x0a, 0x70, 0xf9, 0x8e, 0x37, 0x18, 0x03, 0x64, 0x39, + 0xd2, 0xc6, 0xdc, 0x9a, 0x7c, 0xe4, 0x1e, 0x68, 0xe7, 0xdf, 0xbf, 0x4a, 0x82, 0xad, 0x3f, 0x2d, 0xc6, 0x65, 0xf0, + 0xcc, 0x61, 0x14, 0x38, 0x0a, 0x1f, 0xbd, 0x47, 0x5e, 0xad, 0x94, 0x31, 0xad, 0xcd, 0xe9, 0x4b, 0x23, 0x0d, 0x3e, + 0xd8, 0x86, 0xb5, 0x48, 0xae, 0xc7, 0xc8, 0xc6, 0x5e, 0xb7, 0xb0, 0x16, 0xc6, 0xe2, 0x8e, 0x21, 0xe5, 0x53, 0x49, + 0x09, 0xdc, 0xad, 0xe0, 0xe9, 0xc9, 0x9f, 0x52, 0x3e, 0x95, 0xd3, 0x4d, 0xae, 0xb3, 0x2f, 0x7f, 0x77, 0x4e, 0x17, + 0x1e, 0x34, 0x02, 0xfb, 0x32, 0x4b, 0x97, 0x55, 0x72, 0x2d, 0x90, 0x97, 0x6e, 0x3c, 0x17, 0xe5, 0xfa, 0xeb, 0x6e, + 0x23, 0x4c, 0x60, 0x9f, 0x2e, 0xf9, 0xdb, 0x7b, 0xf0, 0x7e, 0x2e, 0xe7, 0xf5, 0xb9, 0xb7, 0xa8, 0x93, 0x42, 0xbe, + 0xf9, 0xe4, 0x8b, 0x5d, 0x71, 0x9c, 0x10, 0x1f, 0xe8, 0x43, 0xe3, 0xbd, 0x5f, 0x8b, 0x04, 0xc4, 0x0a, 0xbf, 0x24, + 0x40, 0x44, 0x06, 0x70, 0xbc, 0xf3, 0xcf, 0xb1, 0xdb, 0x2c, 0x8d, 0x11, 0xdb, 0xe4, 0x61, 0x69, 0x4a, 0xda, 0xce, + 0x83, 0x0d, 0xf7, 0x67, 0x85, 0x52, 0x9c, 0x00, 0xcb, 0x33, 0xed, 0xb4, 0x8b, 0xbd, 0x08, 0xae, 0x69, 0x9b, 0x79, + 0xf5, 0x16, 0xf4, 0x84, 0xed, 0x2c, 0xcf, 0x63, 0x7b, 0xcb, 0xcf, 0xea, 0x20, 0xc2, 0x90, 0xbb, 0xe2, 0x4c, 0x5a, + 0x26, 0x90, 0x2a, 0xa6, 0x7d, 0xe3, 0xb8, 0xcd, 0x19, 0x3b, 0xf1, 0x02, 0xd1, 0x3f, 0x4e, 0x35, 0x2a, 0x9a, 0x4f, + 0xcd, 0x07, 0x8e, 0x34, 0x30, 0xf1, 0xab, 0x8d, 0xca, 0x54, 0x8e, 0x75, 0x00, 0x94, 0x2c, 0xd1, 0x9f, 0xb6, 0x28, + 0xad, 0x2b, 0x84, 0x51, 0xe1, 0x76, 0xf9, 0xf7, 0xf7, 0x36, 0xad, 0x62, 0x22, 0xda, 0xa3, 0x2b, 0xcd, 0xd9, 0x87, + 0x13, 0xf1, 0x96, 0x61, 0x07, 0x8a, 0x31, 0xa3, 0x03, 0x99, 0x94, 0xd5, 0x1e, 0x8d, 0x55, 0xe9, 0x46, 0x9e, 0x27, + 0x45, 0xa4, 0xbd, 0x80, 0xf5, 0xbd, 0xe0, 0x90, 0x8f, 0xef, 0x95, 0x21, 0x79, 0x5f, 0x77, 0x04, 0xe5, 0x00, 0xee, + 0x37, 0x4c, 0x1a, 0x7c, 0xf0, 0xcd, 0x5f, 0x72, 0xc5, 0xe8, 0xea, 0x95, 0x53, 0x36, 0xcd, 0xd8, 0x97, 0x1c, 0x26, + 0x57, 0xb8, 0x90, 0xed, 0xd3, 0x18, 0x79, 0xa3, 0x40, 0x72, 0x8e, 0x8d, 0x43, 0x3e, 0x6d, 0x58, 0x6f, 0x47, 0x52, + 0xba, 0x80, 0x90, 0xa9, 0x40, 0xd3, 0x83, 0x3a, 0x58, 0x92, 0x91, 0xd6, 0xa9, 0xbc, 0x8b, 0x8e, 0xfa, 0x3d, 0xeb, + 0x41, 0x73, 0xa5, 0xac, 0x0a, 0x84, 0x9b, 0xe5, 0xe5, 0x44, 0xc5, 0xb2, 0x3d, 0x9b, 0xca, 0xc7, 0xe5, 0x20, 0xb2, + 0x69, 0xda, 0xf9, 0xdb, 0xbe, 0x94, 0x22, 0x82, 0x07, 0xd4, 0x43, 0x08, 0xa1, 0xb4, 0x21, 0x03, 0x3d, 0xf2, 0x74, + 0x0d, 0xef, 0xf4, 0x03, 0x85, 0x7e, 0x3b, 0x0b, 0x82, 0xe0, 0xf8, 0x4a, 0xe8, 0x64, 0xcb, 0x9d, 0xda, 0x75, 0xde, + 0x63, 0x9f, 0xc8, 0x5e, 0x38, 0x79, 0xe5, 0xd2, 0xb4, 0x44, 0xdb, 0xd5, 0x8d, 0x3b, 0xff, 0xd8, 0xe1, 0x27, 0xa5, + 0x29, 0xa2, 0xd6, 0x24, 0x75, 0x3a, 0x58, 0x6e, 0x89, 0xa2, 0x45, 0x83, 0x83, 0x08, 0x74, 0x9c, 0x9c, 0x17, 0x71, + 0xdb, 0x0d, 0x05, 0xbe, 0xe4, 0x93, 0x70, 0x8f, 0x32, 0x16, 0xd0, 0x38, 0x52, 0xd0, 0x95, 0x16, 0x47, 0xb5, 0x32, + 0x86, 0x62, 0xcc, 0xde, 0x60, 0x0c, 0x65, 0x05, 0x1a, 0xac, 0x63, 0xeb, 0x45, 0xba, 0x1b, 0xa7, 0xbc, 0x86, 0x66, + 0x40, 0xe3, 0x7e, 0xea, 0x6b, 0x66, 0x84, 0x30, 0x34, 0xe1, 0xed, 0xd1, 0x3b, 0x77, 0x6c, 0x7f, 0xa5, 0xbe, 0x20, + 0x0c, 0x85, 0x18, 0xb0, 0x8b, 0x47, 0x31, 0x5b, 0x58, 0x22, 0x01, 0x71, 0xe5, 0x3e, 0x38, 0x30, 0xcb, 0xf2, 0xe0, + 0x1d, 0xa2, 0x42, 0x7b, 0x6c, 0xe3, 0xa6, 0x78, 0x4a, 0xc8, 0x15, 0x18, 0xc6, 0xfe, 0x32, 0x7d, 0x34, 0xf2, 0x54, + 0xd2, 0x7f, 0x11, 0x5a, 0x3f, 0x7b, 0xa4, 0x5b, 0x2c, 0xbb, 0xad, 0x0b, 0x6e, 0xdf, 0xea, 0x9f, 0xa5, 0xae, 0x4c, + 0xa4, 0xff, 0xb1, 0xb1, 0x6e, 0x75, 0xd9, 0x77, 0xfd, 0xfe, 0x43, 0x27, 0xea, 0x20, 0xff, 0xf4, 0x75, 0xdd, 0xe2, + 0x10, 0x8a, 0x27, 0x1f, 0xda, 0x43, 0x03, 0xf1, 0x31, 0xcd, 0x9a, 0x4b, 0x72, 0xde, 0xd0, 0xd0, 0x3f, 0x2b, 0x5c, + 0xfb, 0x51, 0x1f, 0x7a, 0x5c, 0xcc, 0x7f, 0x4e, 0xbe, 0xc3, 0xdd, 0xe8, 0xa3, 0x0b, 0x8f, 0xe4, 0x5c, 0x24, 0x8f, + 0xc9, 0x9e, 0xfe, 0xd8, 0x76, 0x91, 0xd2, 0x08, 0x50, 0x47, 0xaf, 0x9b, 0x96, 0xa6, 0x6b, 0x92, 0xd2, 0x3c, 0x28, + 0x5f, 0xe0, 0xaa, 0x1f, 0xbd, 0x5f, 0xdb, 0x43, 0x21, 0x9f, 0xd8, 0x5e, 0x2e, 0x49, 0xb7, 0xa7, 0x0f, 0x6f, 0x33, + 0xad, 0xce, 0x48, 0x8d, 0x5b, 0xd8, 0x97, 0xdb, 0xa3, 0xd0, 0x81, 0x32, 0x4a, 0xaf, 0x48, 0xbc, 0xc4, 0x38, 0xb9, + 0xc9, 0x0f, 0x4a, 0xcd, 0xb1, 0x7d, 0x1c, 0x79, 0x83, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0xde, 0x83, 0xa1, 0x72, + 0x2a, 0x58, 0x31, 0x2d, 0xe9, 0x89, 0x01, 0xb0, 0x69, 0xf4, 0x4b, 0xa8, 0xb6, 0x3b, 0x81, 0x4e, 0x6f, 0x9a, 0x54, + 0xdb, 0xc4, 0xff, 0xbe, 0x6f, 0xf4, 0x28, 0x59, 0x4a, 0x01, 0x59, 0xf7, 0xfd, 0x64, 0x6c, 0x12, 0x40, 0xa5, 0x79, + 0x96, 0xd5, 0x44, 0xdd, 0x81, 0xa1, 0x57, 0x33, 0x93, 0x3c, 0x7f, 0x8b, 0x0b, 0x3d, 0xee, 0x66, 0x4a, 0x0e, 0x95, + 0x22, 0x6f, 0x91, 0x08, 0xf5, 0x15, 0x7c, 0x1f, 0x49, 0x54, 0xcc, 0x2f, 0xe9, 0xec, 0x71, 0x68, 0xbc, 0x20, 0xd4, + 0x6f, 0xc0, 0x10, 0xf9, 0x21, 0x3a, 0x08, 0x81, 0xdd, 0xb9, 0x5c, 0x41, 0x72, 0x55, 0xdf, 0xcf, 0xa0, 0xee, 0x18, + 0xfd, 0x76, 0x55, 0xbf, 0x76, 0x0f, 0x86, 0x8c, 0x12, 0xbc, 0x46, 0xba, 0x39, 0x74, 0xd0, 0xa8, 0x1d, 0x3d, 0xd3, + 0x53, 0xe5, 0xa3, 0x0b, 0x14, 0x7d, 0xd8, 0x52, 0xe3, 0x89, 0x37, 0x52, 0xd0, 0x73, 0x71, 0xc0, 0x1b, 0xc3, 0x5e, + 0xd5, 0x81, 0xd1, 0x31, 0x7c, 0x7e, 0x29, 0x32, 0x20, 0x49, 0xaa, 0xa7, 0x45, 0xc4, 0x72, 0x28, 0x67, 0x6d, 0xe6, + 0x0e, 0xfa, 0x5e, 0x9c, 0x62, 0x86, 0xef, 0x6e, 0xf8, 0x8b, 0xbf, 0x19, 0x5f, 0xda, 0xe5, 0xda, 0x93, 0x6e, 0x51, + 0x1a, 0xac, 0xdb, 0xfa, 0x0e, 0x7a, 0x33, 0x12, 0x5d, 0xd0, 0xf4, 0xc7, 0x02, 0x11, 0x87, 0x94, 0x88, 0xa6, 0x69, + 0xe8, 0x94, 0x81, 0x23, 0x36, 0xe2, 0x7f, 0xb0, 0xa2, 0x41, 0x50, 0x6a, 0x1e, 0x58, 0x12, 0x2f, 0x07, 0x39, 0x92, + 0xf2, 0x06, 0x42, 0x41, 0x50, 0x53, 0xc1, 0x59, 0x90, 0xd2, 0x8d, 0x69, 0x87, 0xc8, 0x15, 0xb9, 0xae, 0x8f, 0x1b, + 0xf4, 0xe5, 0x2b, 0x39, 0x31, 0xa9, 0x32, 0x72, 0x6b, 0xaa, 0x62, 0xc7, 0xe0, 0x1d, 0xe7, 0xd6, 0x81, 0x7b, 0x83, + 0x22, 0x68, 0x8a, 0x92, 0xa5, 0x97, 0x39, 0x2f, 0x42, 0x5b, 0xe4, 0xba, 0x1e, 0x3d, 0xa8, 0x18, 0x28, 0xa9, 0xb0, + 0xd8, 0x90, 0x56, 0xf4, 0xa7, 0xce, 0x3b, 0x8c, 0xc2, 0x95, 0x76, 0x65, 0xe4, 0xe1, 0x3d, 0x1e, 0x47, 0xef, 0x26, + 0x51, 0x2c, 0xf2, 0x5c, 0x9d, 0xd7, 0x2c, 0xc8, 0xba, 0x9d, 0x26, 0x79, 0xbe, 0x1b, 0xce, 0xa2, 0x62, 0x52, 0xb2, + 0x95, 0x24, 0xaf, 0x59, 0x28, 0x8c, 0xd8, 0xfa, 0xcd, 0xa3, 0x20, 0xf9, 0x2c, 0xba, 0xbd, 0x1f, 0x09, 0xaf, 0x17, + 0x49, 0x66, 0x11, 0xcf, 0xf3, 0x2c, 0xb5, 0x6c, 0xcc, 0xa9, 0x50, 0xa9, 0xce, 0x10, 0xf8, 0x2b, 0x69, 0x7a, 0x53, + 0x26, 0x28, 0xdc, 0xb6, 0xe9, 0x3e, 0x98, 0x8c, 0x88, 0x0e, 0xdf, 0xb9, 0xd1, 0xcc, 0xc7, 0x6f, 0x94, 0x81, 0x1d, + 0xd6, 0xda, 0xd0, 0x76, 0x81, 0x97, 0x5b, 0x95, 0xc1, 0x9e, 0x46, 0x95, 0x32, 0xf2, 0x82, 0xa8, 0x3a, 0xd1, 0x56, + 0x70, 0xe8, 0x87, 0x0d, 0xfe, 0x3d, 0xc2, 0x70, 0xc9, 0x3d, 0xbb, 0x0d, 0x40, 0x0e, 0x59, 0x44, 0x3a, 0x2a, 0xa0, + 0x47, 0x9f, 0xae, 0x66, 0xcc, 0x15, 0xdc, 0x65, 0x0d, 0x82, 0x3b, 0xda, 0x3e, 0xc3, 0x40, 0xd2, 0x1d, 0x2e, 0xb4, + 0x29, 0x7a, 0xd4, 0xdf, 0x36, 0x4b, 0x67, 0xc1, 0x9b, 0x54, 0xc1, 0xcf, 0xb4, 0xe0, 0x84, 0xb7, 0xfd, 0x1e, 0xef, + 0x1b, 0xad, 0xb1, 0x6d, 0x86, 0xc7, 0xc6, 0xbc, 0x3b, 0xc8, 0x1a, 0xab, 0x8b, 0xc5, 0x35, 0x41, 0x2e, 0x25, 0xf9, + 0x88, 0xeb, 0xe5, 0x69, 0x19, 0x7c, 0xaa, 0x9e, 0x2a, 0x56, 0xa0, 0x1c, 0x16, 0x21, 0x14, 0x4c, 0xb3, 0x87, 0xb1, + 0x0e, 0x1f, 0x23, 0x31, 0x28, 0x24, 0x84, 0x05, 0x16, 0xa5, 0xee, 0xc7, 0x42, 0xa7, 0xd2, 0x40, 0x50, 0x42, 0x85, + 0x02, 0x23, 0xce, 0x7b, 0x2d, 0xbd, 0x86, 0xb6, 0xa9, 0x8c, 0x1e, 0x06, 0xbb, 0x58, 0xf6, 0x0e, 0x99, 0xc2, 0x92, + 0x2d, 0x0f, 0x21, 0x37, 0xdc, 0xd8, 0xa7, 0xef, 0xdb, 0xb5, 0x8a, 0x55, 0x33, 0xba, 0x9a, 0xfa, 0xdf, 0x11, 0xa1, + 0x71, 0x00, 0xd9, 0xc7, 0x6b, 0xe9, 0x60, 0x45, 0x8c, 0x9d, 0xe6, 0x23, 0xf5, 0xa2, 0x9c, 0x3f, 0x9b, 0x02, 0x82, + 0x6d, 0x6f, 0xed, 0x58, 0x37, 0x40, 0xe2, 0x76, 0x8e, 0xc9, 0x5e, 0x5d, 0xe2, 0x49, 0xef, 0x83, 0xf2, 0xb9, 0x75, + 0xdb, 0x25, 0x81, 0xcc, 0x17, 0xac, 0x28, 0x06, 0x24, 0x2b, 0x25, 0x78, 0xce, 0x7f, 0x6b, 0x1d, 0x54, 0x90, 0x90, + 0xe7, 0x83, 0x46, 0xb2, 0x32, 0xea, 0xf9, 0x98, 0x08, 0x1c, 0xd4, 0x02, 0x44, 0x63, 0x70, 0x06, 0x25, 0x28, 0x5b, + 0xc6, 0x3e, 0x1c, 0xce, 0x69, 0xf2, 0x12, 0xa1, 0x29, 0xca, 0x87, 0x2c, 0xf6, 0x57, 0x3f, 0x51, 0xa8, 0x9b, 0x1b, + 0xb9, 0x11, 0x1d, 0x0a, 0x5d, 0xbd, 0x6b, 0x6f, 0x32, 0x82, 0x34, 0xda, 0xba, 0xb9, 0x9e, 0x3d, 0x3f, 0xeb, 0xe1, + 0x63, 0x73, 0xba, 0x1e, 0x2e, 0x6f, 0x4a, 0xb5, 0x22, 0x42, 0xfb, 0x7f, 0x56, 0x96, 0x93, 0xff, 0x2c, 0xfa, 0x8b, + 0xcf, 0x8a, 0xfe, 0x94, 0x02, 0x49, 0x5d, 0x44, 0x5c, 0x5c, 0xb3, 0xd1, 0x5c, 0x29, 0x37, 0x6c, 0xaf, 0x9c, 0x27, + 0xbe, 0x72, 0x2e, 0x7f, 0x08, 0x07, 0xd5, 0x4e, 0x38, 0x0b, 0xe0, 0xa4, 0x8c, 0xb8, 0x1c, 0x3c, 0x8b, 0x01, 0xad, + 0xe2, 0x8a, 0x5a, 0x1d, 0x39, 0xcf, 0x1d, 0x6f, 0x1b, 0x6a, 0x2e, 0xea, 0xa1, 0x10, 0xe7, 0x03, 0x31, 0x32, 0x1b, + 0x88, 0xba, 0x09, 0x33, 0xd8, 0xdf, 0x91, 0xb2, 0x93, 0xe5, 0xa2, 0x4b, 0x6d, 0xf7, 0xc4, 0x51, 0xa4, 0xa4, 0x97, + 0xa9, 0xad, 0x40, 0x45, 0xaa, 0x24, 0x75, 0x74, 0x44, 0x14, 0xc2, 0x26, 0x58, 0x50, 0x3c, 0x6a, 0xc2, 0xa8, 0x4d, + 0xc2, 0xed, 0x00, 0x49, 0x8a, 0xd5, 0x28, 0xe3, 0xba, 0xa3, 0x12, 0x34, 0x24, 0xd4, 0x99, 0xa3, 0x03, 0x1a, 0x35, + 0x09, 0x25, 0x43, 0x49, 0xf3, 0x2f, 0x53, 0xd3, 0x98, 0x21, 0xea, 0x0f, 0x8c, 0xd0, 0x3b, 0xb7, 0x21, 0xe0, 0x96, + 0xf9, 0xad, 0x56, 0x2e, 0x8b, 0x04, 0xe2, 0x53, 0xc6, 0x3e, 0x50, 0xad, 0x11, 0xb5, 0x93, 0x2f, 0x54, 0x3a, 0x7c, + 0x09, 0xc5, 0x31, 0xd1, 0xc9, 0x09, 0x67, 0xcf, 0x4c, 0x28, 0x2b, 0xfe, 0x4d, 0xa6, 0xcd, 0x90, 0xb6, 0xf4, 0x41, + 0x8f, 0x4e, 0x24, 0xe1, 0x1c, 0xcb, 0x16, 0xb9, 0xaf, 0x46, 0xba, 0xaa, 0x25, 0x09, 0x43, 0x05, 0x99, 0xcb, 0xc2, + 0xf5, 0x49, 0x78, 0xed, 0x1e, 0x92, 0xf6, 0xb3, 0x0e, 0x2c, 0xb7, 0xcd, 0x4b, 0xec, 0xc2, 0x59, 0xef, 0x41, 0xb4, + 0xf7, 0x4c, 0x08, 0x7c, 0x16, 0xeb, 0x13, 0x29, 0x74, 0xff, 0x60, 0x12, 0x86, 0x84, 0xcf, 0xe0, 0xe1, 0x72, 0xf4, + 0x23, 0x45, 0x57, 0x24, 0x94, 0xb7, 0x6a, 0x5d, 0x12, 0x12, 0x85, 0x7b, 0x8b, 0x45, 0x63, 0x5d, 0x44, 0x43, 0xa1, + 0xb9, 0x78, 0xed, 0x49, 0xf5, 0xbe, 0x17, 0x75, 0x75, 0x8c, 0x50, 0xbd, 0xe0, 0x9f, 0xc1, 0x4f, 0x48, 0x42, 0xa7, + 0xd0, 0xdd, 0x36, 0x2d, 0x20, 0xb3, 0xc3, 0x69, 0x88, 0x02, 0x1e, 0xa2, 0x2a, 0x02, 0xb4, 0x98, 0x36, 0x97, 0x43, + 0x0a, 0xd5, 0xf3, 0x13, 0x9d, 0x7c, 0x40, 0xdd, 0x03, 0x99, 0xb2, 0xed, 0xb4, 0x7c, 0xba, 0x57, 0x38, 0x2c, 0xb5, + 0xbf, 0x89, 0x84, 0x92, 0x99, 0x58, 0x42, 0xdb, 0x98, 0x24, 0x7c, 0xfe, 0x75, 0xeb, 0x4a, 0xc4, 0xf8, 0x90, 0xbe, + 0x1c, 0xc9, 0xb8, 0xc2, 0x3b, 0x95, 0x9c, 0x40, 0xc4, 0xa6, 0xb7, 0x47, 0x21, 0x21, 0x65, 0x6a, 0x7c, 0x20, 0xa5, + 0xa5, 0x77, 0x7b, 0xda, 0x7c, 0x2a, 0x85, 0x1f, 0xaf, 0x3a, 0xd9, 0x73, 0x75, 0xb0, 0x75, 0x94, 0xf6, 0x98, 0x4c, + 0xf6, 0x1f, 0xfa, 0x98, 0xa2, 0x89, 0x81, 0x32, 0x62, 0xec, 0x30, 0x0f, 0xac, 0x12, 0x62, 0xda, 0x50, 0xaa, 0x2c, + 0x25, 0x39, 0x07, 0x0c, 0x3f, 0x4e, 0x1e, 0xa1, 0x80, 0xc1, 0xc4, 0x04, 0x2b, 0xc3, 0xe5, 0x62, 0x69, 0x50, 0x97, + 0x4a, 0x3c, 0x79, 0x2a, 0x4d, 0xae, 0xa7, 0xb1, 0xc4, 0x55, 0x22, 0x81, 0x49, 0x0d, 0x3d, 0x02, 0x18, 0x8f, 0xd4, + 0x8b, 0x6c, 0xfa, 0x0c, 0x9c, 0x96, 0xbe, 0x73, 0x7a, 0xca, 0x24, 0x6f, 0xb4, 0x59, 0x20, 0x98, 0xf0, 0xd8, 0x30, + 0x74, 0x47, 0x95, 0x7c, 0xb4, 0x4f, 0xac, 0xcf, 0x99, 0x45, 0x19, 0x8f, 0x3d, 0x05, 0x18, 0x38, 0xad, 0xf7, 0xe8, + 0x47, 0xd9, 0x74, 0x56, 0x93, 0x71, 0x22, 0x4f, 0x54, 0x52, 0x65, 0xd9, 0x89, 0x49, 0x8d, 0x1e, 0xaa, 0x65, 0x4f, + 0x76, 0x4c, 0x81, 0x04, 0x50, 0x4d, 0x72, 0xf8, 0x19, 0xb8, 0x74, 0x16, 0xda, 0x22, 0x95, 0x24, 0x6c, 0x00, 0xab, + 0xcf, 0x69, 0xdc, 0x38, 0xff, 0xba, 0x8f, 0x02, 0xa8, 0x57, 0x42, 0x4c, 0x54, 0xd0, 0x0a, 0xfb, 0xa0, 0x32, 0x81, + 0x76, 0xcb, 0x29, 0x69, 0x3b, 0xca, 0x48, 0x72, 0x15, 0xd7, 0x81, 0x18, 0xdc, 0xd3, 0x03, 0xb1, 0x88, 0xae, 0x1b, + 0xd8, 0x74, 0x60, 0xc7, 0x6f, 0x8c, 0x97, 0x6a, 0x7b, 0xac, 0xea, 0x4a, 0x92, 0x8f, 0x92, 0x4d, 0xaa, 0x9d, 0x00, + 0xe4, 0x48, 0xa8, 0x5a, 0xe4, 0xa7, 0x4d, 0x29, 0xa5, 0xb5, 0x61, 0xf7, 0x9e, 0x9a, 0x90, 0xeb, 0x55, 0x3d, 0x85, + 0x8f, 0x63, 0x64, 0x0e, 0xf1, 0x18, 0x67, 0x67, 0x88, 0x78, 0xc7, 0x95, 0x85, 0xfb, 0xdb, 0x22, 0xf5, 0x5c, 0x4a, + 0x52, 0x7b, 0x90, 0x4b, 0xb9, 0x4c, 0x3e, 0x98, 0xe6, 0xd2, 0x22, 0x30, 0xe7, 0x45, 0x25, 0x8e, 0x2e, 0x29, 0xc1, + 0x1d, 0x9a, 0x5e, 0x67, 0x39, 0x08, 0x2d, 0x53, 0xcc, 0x06, 0x48, 0x21, 0x20, 0x02, 0xe3, 0x2a, 0x5f, 0xb0, 0x77, + 0xb9, 0x8a, 0x0b, 0x8d, 0x60, 0x29, 0x32, 0x43, 0xaa, 0xed, 0xc4, 0xb4, 0xfb, 0xca, 0x59, 0xf4, 0xd3, 0x72, 0x39, + 0xd2, 0x71, 0x4d, 0x9c, 0x97, 0x92, 0xbc, 0x19, 0x46, 0x86, 0xce, 0x5b, 0x53, 0x6c, 0x75, 0x36, 0xf3, 0xd9, 0x90, + 0x40, 0x48, 0xc0, 0x82, 0x42, 0x2e, 0x4b, 0xd9, 0x99, 0xc7, 0xb4, 0xc7, 0xe3, 0xcc, 0xe8, 0xfe, 0xfa, 0x7d, 0x3d, + 0x9d, 0x96, 0x05, 0x55, 0x79, 0xb8, 0xed, 0x0e, 0x96, 0xc7, 0x41, 0x97, 0x76, 0x59, 0x4c, 0x15, 0xbf, 0x92, 0xec, + 0x27, 0x0d, 0x2f, 0xa3, 0x61, 0xae, 0x79, 0x49, 0xf5, 0x52, 0xcc, 0x70, 0x64, 0x91, 0xe6, 0xab, 0x23, 0xf6, 0xb3, + 0x33, 0xad, 0xad, 0xfc, 0xfb, 0x91, 0x59, 0x3b, 0xda, 0x5e, 0x49, 0x7d, 0xa5, 0x8f, 0x7e, 0xee, 0x83, 0xc5, 0x04, + 0x7f, 0x56, 0x28, 0x17, 0x7a, 0x52, 0x58, 0xa1, 0xfe, 0xb3, 0xae, 0x65, 0x7f, 0x6c, 0x82, 0x0f, 0xed, 0x83, 0x0f, + 0x98, 0x26, 0x34, 0x3f, 0x32, 0xc0, 0xa6, 0x8a, 0x09, 0xcb, 0xb7, 0x15, 0xb6, 0x21, 0xc5, 0xfb, 0xe7, 0x75, 0xcb, + 0x63, 0x9e, 0x8a, 0x29, 0x2f, 0x90, 0x5b, 0xfe, 0x2c, 0x20, 0x12, 0x75, 0x06, 0xd7, 0x43, 0x3e, 0x81, 0x6e, 0xec, + 0x3c, 0x3c, 0x12, 0xb9, 0xe2, 0x36, 0xc3, 0x9d, 0xc2, 0xb7, 0x87, 0xc7, 0xca, 0xbb, 0xb4, 0x52, 0x48, 0xa3, 0xfa, + 0x83, 0x36, 0xc3, 0x1b, 0xab, 0xd1, 0x43, 0x5d, 0x2d, 0x09, 0x61, 0x11, 0x84, 0x87, 0x45, 0xe8, 0xfd, 0x9f, 0xae, + 0x54, 0x48, 0x4c, 0x4e, 0x5b, 0x46, 0x72, 0x0e, 0x84, 0x54, 0xa0, 0x96, 0xe9, 0x3e, 0x65, 0x51, 0xa9, 0xdb, 0x42, + 0x6e, 0xfc, 0x96, 0x7c, 0x44, 0x15, 0x16, 0x3b, 0xbf, 0xd6, 0xdd, 0x27, 0xd2, 0x75, 0x57, 0xd4, 0x85, 0x56, 0x53, + 0x96, 0xa7, 0x68, 0x7a, 0x0e, 0xc4, 0xee, 0x71, 0x95, 0xfc, 0x9e, 0x40, 0x3a, 0xff, 0xb1, 0xe0, 0xef, 0xef, 0x15, + 0x49, 0xa2, 0xf5, 0x45, 0xe3, 0x51, 0xeb, 0x8b, 0x3d, 0x75, 0x68, 0x80, 0xd3, 0x05, 0x24, 0x8f, 0xaf, 0x02, 0x74, + 0x0d, 0x66, 0xe9, 0xaa, 0x63, 0x8e, 0x9b, 0xee, 0x7c, 0xd9, 0x16, 0x69, 0x3d, 0x43, 0x00, 0xed, 0x0d, 0x19, 0x77, + 0xff, 0x21, 0x4e, 0xb4, 0x67, 0x61, 0x82, 0x2e, 0x22, 0xe9, 0x3d, 0xec, 0x28, 0xb9, 0xd5, 0x9c, 0xe5, 0x0e, 0xdd, + 0x81, 0xae, 0x67, 0xbd, 0x88, 0x4a, 0x43, 0x0e, 0x76, 0x52, 0x6a, 0x08, 0x20, 0xda, 0x83, 0x6e, 0x2f, 0x4e, 0xee, + 0xed, 0x62, 0xc5, 0x7a, 0xdb, 0x0e, 0x4d, 0x2c, 0x54, 0x85, 0x2b, 0xac, 0x31, 0xe6, 0x96, 0xe3, 0xf6, 0x70, 0xd6, + 0x39, 0x16, 0x4a, 0xa3, 0xc1, 0xc0, 0xb7, 0xaf, 0xf3, 0xe3, 0x78, 0x61, 0x8f, 0x1c, 0x80, 0xd0, 0xb1, 0x17, 0x65, + 0x52, 0x05, 0x8a, 0x63, 0x19, 0x02, 0x2d, 0xda, 0xad, 0x59, 0xa5, 0x20, 0x17, 0x1e, 0x50, 0x8b, 0x8f, 0x17, 0xfe, + 0xb3, 0xcd, 0xb9, 0xd0, 0x42, 0xe6, 0xa8, 0x9d, 0x96, 0xec, 0x53, 0xbd, 0xa0, 0x00, 0x89, 0x32, 0xc2, 0xb6, 0x56, + 0x32, 0xf5, 0x71, 0x0a, 0x36, 0x21, 0xfb, 0x35, 0x49, 0x72, 0x3a, 0x32, 0x81, 0xd6, 0x79, 0xbb, 0x91, 0xa8, 0x0b, + 0x51, 0xe5, 0xc6, 0xa8, 0x0f, 0x7b, 0x46, 0xc7, 0x13, 0x8c, 0xe4, 0x98, 0xd2, 0xb1, 0xce, 0xbc, 0x7b, 0xab, 0x3d, + 0x76, 0xa7, 0x4d, 0x2b, 0x53, 0x9a, 0x29, 0x88, 0x39, 0x94, 0x49, 0x12, 0x04, 0x24, 0xb6, 0xbe, 0xbb, 0xce, 0x51, + 0x2d, 0xe8, 0x0e, 0x4c, 0x9f, 0x19, 0x8d, 0x02, 0x09, 0xf8, 0x6e, 0x39, 0x23, 0xe7, 0x90, 0xc2, 0xba, 0xb6, 0x50, + 0x91, 0x76, 0x97, 0x57, 0x82, 0x0a, 0xe7, 0x82, 0xd0, 0xec, 0xa0, 0xe0, 0xd4, 0xee, 0x77, 0x9b, 0xa1, 0xae, 0x3a, + 0xfa, 0x80, 0x1b, 0xb0, 0xd9, 0x10, 0xe2, 0x48, 0xdc, 0x78, 0xa1, 0x6c, 0x80, 0x13, 0x37, 0x2a, 0x61, 0x75, 0x62, + 0x7b, 0x72, 0xf4, 0xa3, 0x0b, 0xb5, 0xcc, 0x27, 0x58, 0xa2, 0x8b, 0x9e, 0x57, 0xb6, 0xdd, 0x5e, 0xe6, 0xdb, 0x6a, + 0x5e, 0xa0, 0xd8, 0x26, 0x21, 0xc4, 0x32, 0x4d, 0xe7, 0x98, 0xe7, 0xc2, 0x8f, 0x0e, 0x26, 0xc8, 0x3c, 0x94, 0x82, + 0x56, 0xf5, 0x0a, 0x34, 0x65, 0x97, 0xac, 0x84, 0x7b, 0xb7, 0xbe, 0xc9, 0xa4, 0x5d, 0xb4, 0x56, 0xde, 0x5d, 0x3d, + 0x6d, 0x40, 0xf7, 0xdc, 0xfb, 0x94, 0xfe, 0x25, 0xd0, 0x71, 0xc9, 0x6a, 0xf7, 0xbc, 0x9f, 0x52, 0x4e, 0xe3, 0x9a, + 0x28, 0x25, 0x0a, 0x3f, 0x1c, 0x06, 0xc4, 0xcc, 0x10, 0xe2, 0x8f, 0x7e, 0xe0, 0xcd, 0x5e, 0xec, 0x52, 0xa6, 0x4a, + 0x8b, 0xe2, 0x4f, 0x7a, 0x3f, 0x65, 0xc2, 0xc9, 0x7d, 0xd1, 0x3f, 0x37, 0xc4, 0x77, 0xa2, 0x01, 0x26, 0x62, 0x50, + 0x47, 0xbf, 0x45, 0x60, 0x3d, 0xa2, 0x23, 0x4b, 0xde, 0x2c, 0xff, 0x5d, 0xd6, 0xde, 0x9f, 0x76, 0x16, 0xaf, 0x2d, + 0xa9, 0xc1, 0x46, 0xb7, 0x1b, 0xc3, 0xda, 0xb0, 0xed, 0x29, 0x15, 0x20, 0x32, 0x7a, 0x04, 0xaa, 0x31, 0x5f, 0xcd, + 0x12, 0x14, 0x03, 0x1f, 0x71, 0x02, 0x1c, 0xb9, 0xad, 0x93, 0x95, 0x14, 0xee, 0xde, 0xfa, 0xb6, 0xd7, 0xc4, 0xbe, + 0xb2, 0x4b, 0x58, 0xee, 0xc8, 0x1d, 0xbb, 0xe9, 0x04, 0xaa, 0xa3, 0xb0, 0x57, 0x30, 0xac, 0x68, 0xd1, 0xb5, 0x03, + 0x11, 0x85, 0xde, 0x4e, 0x54, 0x14, 0x3e, 0x66, 0x58, 0x51, 0xd9, 0xd9, 0x01, 0x8c, 0x00, 0xfe, 0x45, 0x1c, 0x9e, + 0xd8, 0xe5, 0xa9, 0x66, 0x31, 0x83, 0x00, 0x63, 0xf8, 0xca, 0x06, 0x67, 0xc6, 0x0b, 0xcb, 0xc0, 0x26, 0x07, 0x80, + 0x5a, 0x47, 0x51, 0x6f, 0x71, 0x8a, 0x0f, 0x53, 0xdf, 0x18, 0xbc, 0xbd, 0x54, 0x4e, 0x47, 0xbc, 0x87, 0xdd, 0x95, + 0x8a, 0x1a, 0x52, 0xb0, 0x85, 0x6f, 0xbb, 0x21, 0x60, 0xa5, 0x30, 0x09, 0xfa, 0x50, 0x4e, 0x9b, 0xcb, 0x93, 0xcf, + 0x54, 0xff, 0x57, 0x4f, 0xc9, 0x54, 0x2c, 0x78, 0xd9, 0x49, 0x4f, 0x67, 0x9c, 0x96, 0xa5, 0xb2, 0xcf, 0xfd, 0xd3, + 0x4e, 0x12, 0x28, 0xf0, 0xed, 0x10, 0xf0, 0xec, 0xff, 0x2c, 0xda, 0xa8, 0x48, 0xad, 0x9a, 0x68, 0xa3, 0xa5, 0x75, + 0xec, 0x11, 0xff, 0x7e, 0x94, 0x76, 0x75, 0xe0, 0xa1, 0xaa, 0xcf, 0x27, 0x79, 0xe6, 0xbf, 0xe2, 0x49, 0xde, 0x10, + 0x75, 0x3b, 0xb1, 0xfb, 0x26, 0xa7, 0x4b, 0x79, 0x3b, 0x99, 0x57, 0x41, 0x7c, 0x47, 0x53, 0x03, 0xb3, 0x39, 0x29, + 0x71, 0xeb, 0xa5, 0xa2, 0xde, 0xe2, 0xc8, 0x23, 0x3a, 0x48, 0x32, 0x8c, 0xe6, 0xfc, 0xdc, 0x4e, 0xfc, 0x78, 0x2e, + 0x58, 0xfc, 0xb8, 0xbf, 0x2f, 0x30, 0x1c, 0x7d, 0x70, 0x12, 0x67, 0xda, 0xd5, 0x18, 0x29, 0x86, 0xaa, 0x14, 0x70, + 0x26, 0x36, 0xb7, 0xed, 0x47, 0x00, 0xe8, 0x3d, 0x70, 0xdc, 0xfb, 0x6e, 0xc1, 0xd9, 0xb3, 0xba, 0xb9, 0x90, 0x49, + 0xe6, 0x15, 0x65, 0x8c, 0x2b, 0x5e, 0xf4, 0x95, 0x2b, 0xf7, 0x3a, 0xc9, 0x03, 0x18, 0x52, 0x41, 0x4e, 0xe4, 0x9d, + 0x96, 0xba, 0xa2, 0xce, 0x42, 0xc8, 0x42, 0xce, 0x05, 0xb8, 0xca, 0xf3, 0xa7, 0xb3, 0x32, 0x8b, 0xe9, 0xdd, 0x5a, + 0xeb, 0x04, 0x08, 0x41, 0xf5, 0x95, 0x0c, 0xc6, 0xa1, 0x27, 0x79, 0x9f, 0x0a, 0x89, 0xb5, 0xe1, 0x1d, 0xb3, 0x1e, + 0x73, 0xf0, 0xc7, 0x84, 0xda, 0x4e, 0xa9, 0x07, 0xf9, 0x46, 0x6a, 0xd3, 0x7b, 0xc6, 0xe3, 0xf6, 0x0d, 0xb7, 0xd3, + 0x04, 0x09, 0x8a, 0x6b, 0x02, 0x2d, 0x97, 0x71, 0x0b, 0x60, 0xa9, 0x33, 0x45, 0xc3, 0x5b, 0xea, 0x7e, 0x62, 0x01, + 0x6b, 0xde, 0xad, 0x8c, 0x27, 0x0e, 0x73, 0xb2, 0x3d, 0x58, 0xbf, 0x2d, 0x86, 0x56, 0xa2, 0x0a, 0x07, 0x2b, 0x7b, + 0xde, 0x6d, 0x3b, 0xfe, 0x60, 0xcf, 0x65, 0x46, 0x84, 0x61, 0x1f, 0x38, 0x0a, 0x53, 0xec, 0xf2, 0x2a, 0x5b, 0x23, + 0x47, 0x18, 0x4e, 0xbe, 0xde, 0xa8, 0x81, 0xe5, 0xc4, 0xce, 0x69, 0xf6, 0x6f, 0xe8, 0x89, 0x40, 0xc6, 0x53, 0x7f, + 0xfc, 0xcc, 0x0c, 0xf5, 0xe0, 0x21, 0xdb, 0xed, 0xd2, 0xd7, 0xd6, 0x76, 0xb9, 0xb6, 0xad, 0x71, 0x8b, 0x68, 0x39, + 0x94, 0xd8, 0xb5, 0x46, 0x2c, 0xdd, 0xa1, 0x0b, 0x1f, 0xd8, 0x02, 0x37, 0xaa, 0x42, 0xe4, 0x2e, 0x37, 0x53, 0x89, + 0x35, 0x14, 0x80, 0xab, 0x9d, 0x17, 0x66, 0xd4, 0x27, 0x92, 0xf1, 0x15, 0x7b, 0x64, 0xa9, 0xf9, 0xa9, 0xcf, 0x3c, + 0xb0, 0x17, 0x8d, 0x42, 0xdf, 0xa4, 0x39, 0xcd, 0x8b, 0xf6, 0x83, 0xec, 0x16, 0xf9, 0x09, 0x42, 0x2b, 0xe1, 0x7c, + 0x7e, 0xd9, 0x7e, 0xd1, 0x2e, 0x66, 0x39, 0xe2, 0x61, 0x7f, 0x53, 0x4f, 0x2b, 0xbd, 0x8f, 0x77, 0x04, 0x0b, 0xb7, + 0x1d, 0x08, 0x26, 0x92, 0x3e, 0x12, 0xf2, 0xf0, 0x9d, 0xf8, 0xff, 0x6b, 0x43, 0xa0, 0x0d, 0x5b, 0x31, 0x5b, 0x1c, + 0x7e, 0x6a, 0x0a, 0xde, 0x41, 0x33, 0x4f, 0xa3, 0xb6, 0xb2, 0xce, 0xaa, 0xda, 0x2c, 0xe0, 0x15, 0x2f, 0x3f, 0x65, + 0x78, 0x81, 0x93, 0x71, 0x8e, 0x64, 0x78, 0x3f, 0x0f, 0x10, 0x25, 0x04, 0x24, 0xc4, 0xe9, 0x75, 0xf7, 0x60, 0x70, + 0x07, 0x6d, 0x7c, 0x09, 0x0a, 0xeb, 0xf9, 0x6c, 0x3c, 0x8f, 0xd9, 0x9b, 0xfc, 0x33, 0xba, 0x9e, 0xe8, 0x34, 0xae, + 0x54, 0x5b, 0xad, 0x5f, 0xbd, 0xf0, 0xdb, 0x43, 0xcd, 0x37, 0xf7, 0x93, 0xfb, 0x6c, 0x92, 0xad, 0x7c, 0xa8, 0x54, + 0x59, 0xde, 0x0d, 0x68, 0x31, 0x44, 0x65, 0x39, 0x4c, 0xa3, 0xdd, 0x86, 0xa3, 0xc3, 0x96, 0xdb, 0x49, 0xad, 0x9d, + 0x80, 0xec, 0xa0, 0x69, 0x51, 0x89, 0x17, 0x56, 0x90, 0x71, 0x9f, 0x72, 0x37, 0xa2, 0xa0, 0x20, 0xba, 0xc9, 0x52, + 0x9d, 0x61, 0x6a, 0x6c, 0x38, 0xf5, 0x80, 0xb2, 0xa0, 0xff, 0x75, 0x60, 0x28, 0x32, 0xa3, 0xb6, 0x30, 0x3f, 0xa6, + 0xca, 0xc9, 0x1f, 0xb7, 0x9c, 0xca, 0xc4, 0xaa, 0x57, 0xe8, 0xd5, 0xeb, 0x7d, 0x6e, 0x9a, 0x4e, 0x0c, 0x14, 0x1f, + 0x70, 0x35, 0x27, 0x58, 0x4d, 0xe4, 0x8b, 0x78, 0xb9, 0xca, 0x9c, 0x7d, 0x00, 0x7e, 0xd1, 0x75, 0x0b, 0x87, 0x69, + 0x79, 0xdb, 0xec, 0x8f, 0xe8, 0xec, 0x4a, 0xf2, 0x62, 0xc9, 0x16, 0x7c, 0x8c, 0x06, 0x70, 0x64, 0x0f, 0xaa, 0xc6, + 0x29, 0xc0, 0x22, 0x91, 0xd8, 0xc2, 0x52, 0x5a, 0x0f, 0xca, 0x05, 0x31, 0xb5, 0x8c, 0xe9, 0x36, 0x7a, 0x3c, 0x2d, + 0x23, 0x40, 0x0b, 0xb5, 0xb5, 0xc2, 0x3b, 0x8a, 0x29, 0x2a, 0x9b, 0x0b, 0xb9, 0x0a, 0x6c, 0xff, 0x9a, 0x52, 0x29, + 0x17, 0xb1, 0xdb, 0xa4, 0xb4, 0x43, 0xfd, 0x87, 0x7e, 0xc5, 0x6a, 0xc9, 0x09, 0x89, 0xd1, 0x47, 0x2e, 0x2e, 0x09, + 0x69, 0x45, 0xa6, 0x39, 0x5c, 0x33, 0x24, 0xf8, 0x73, 0x5a, 0x6b, 0x2f, 0xc5, 0x91, 0x31, 0x67, 0xee, 0x9b, 0xe2, + 0xda, 0x69, 0xab, 0xbf, 0xd8, 0x19, 0x57, 0x02, 0x82, 0xe1, 0xfc, 0x32, 0x97, 0x43, 0x77, 0xee, 0xbd, 0xb4, 0xe7, + 0xbc, 0xcc, 0x10, 0xc1, 0x4c, 0x20, 0xe4, 0x49, 0xe9, 0x5c, 0x74, 0x7d, 0x3a, 0x75, 0x24, 0xb1, 0xb6, 0x3e, 0x65, + 0xc6, 0x64, 0xc2, 0x64, 0x28, 0x28, 0xee, 0x19, 0xbf, 0x3f, 0x81, 0x8c, 0xa0, 0x86, 0xa0, 0xa0, 0xba, 0xee, 0xf1, + 0xf4, 0x65, 0x35, 0xf8, 0xf5, 0xb2, 0x42, 0x49, 0xe8, 0xb8, 0xf4, 0xdf, 0xe6, 0xb2, 0xcb, 0x92, 0x83, 0xbd, 0xbd, + 0x37, 0x30, 0xce, 0xa6, 0xd1, 0x93, 0x9d, 0x98, 0x72, 0xb7, 0x9d, 0xa0, 0x52, 0xf2, 0x9a, 0x52, 0x51, 0xb8, 0xd5, + 0x4b, 0xb4, 0x9e, 0x79, 0xe5, 0x70, 0x97, 0x78, 0x43, 0x59, 0xbc, 0x63, 0xc3, 0x4e, 0xf9, 0xcf, 0x8f, 0x6d, 0xf9, + 0xb2, 0x8d, 0x07, 0x7b, 0xba, 0x3f, 0x09, 0xfa, 0xce, 0xb8, 0xdf, 0x31, 0xf2, 0x57, 0x5f, 0x7c, 0x57, 0x93, 0xbf, + 0xf4, 0x9b, 0xb5, 0x1e, 0xf3, 0xba, 0x87, 0xdf, 0xef, 0xd3, 0x29, 0x7b, 0xe0, 0x6d, 0xe8, 0x9f, 0x47, 0xab, 0x75, + 0x05, 0xe4, 0x43, 0x87, 0xce, 0x7f, 0xe6, 0xfd, 0x33, 0x9f, 0xb9, 0xf4, 0xa7, 0xa3, 0x85, 0xd8, 0x1d, 0xf3, 0x37, + 0x06, 0x6f, 0x1b, 0xb1, 0x7b, 0x29, 0x76, 0x5f, 0xf4, 0x9a, 0x33, 0x0f, 0x53, 0x16, 0x5e, 0x41, 0xd0, 0x52, 0x79, + 0x57, 0xf8, 0x9c, 0xb7, 0x85, 0x6d, 0x3e, 0x14, 0x1e, 0xf2, 0xb1, 0xf0, 0x98, 0x4f, 0x6b, 0x4f, 0x4a, 0xb6, 0xd8, + 0xe3, 0xb8, 0x9a, 0xa8, 0x4a, 0x14, 0x7a, 0xf4, 0xc3, 0xc3, 0xa7, 0x52, 0x2a, 0x6b, 0x7c, 0xe3, 0x99, 0x67, 0x05, + 0x1b, 0x94, 0x10, 0x2b, 0xc3, 0x9b, 0x3a, 0x79, 0x75, 0x52, 0x12, 0x09, 0xf5, 0xcc, 0x5a, 0xd5, 0x41, 0x57, 0x49, + 0x59, 0x70, 0xb7, 0xdc, 0x86, 0x62, 0x7b, 0xb2, 0xb8, 0x8c, 0x5a, 0x43, 0xbd, 0xb7, 0x92, 0x19, 0xbd, 0x46, 0xa8, + 0xac, 0xbd, 0xbd, 0x4f, 0x47, 0x28, 0x2d, 0x27, 0x54, 0x25, 0xee, 0x67, 0x68, 0x15, 0x71, 0x86, 0x2d, 0x41, 0xde, + 0x7f, 0x06, 0x4c, 0x5a, 0x38, 0x6a, 0x5d, 0xae, 0xf7, 0x84, 0xd5, 0xe8, 0xd6, 0x12, 0xe9, 0x8b, 0x3c, 0x9a, 0xba, + 0xee, 0xaa, 0xc0, 0xcd, 0x89, 0x33, 0xf4, 0x1a, 0xf9, 0xed, 0xf0, 0xd8, 0x1a, 0xbb, 0xdc, 0xaa, 0xf9, 0x72, 0xfd, + 0xeb, 0xec, 0x3b, 0x2e, 0xc5, 0x84, 0x01, 0xea, 0x39, 0x0a, 0x91, 0x45, 0x0d, 0x17, 0xfc, 0x4a, 0x40, 0x5a, 0x6c, + 0x85, 0x1f, 0xbd, 0xaf, 0x61, 0x72, 0x81, 0x07, 0xa6, 0xbb, 0x75, 0x74, 0x96, 0x9f, 0xdc, 0xff, 0xf0, 0x9b, 0xff, + 0x19, 0x91, 0x13, 0x34, 0x16, 0x99, 0xfe, 0xb3, 0x9d, 0x1c, 0xc5, 0xa4, 0xb9, 0x74, 0x4b, 0xee, 0x6f, 0xc8, 0x60, + 0xea, 0x7d, 0x0d, 0x25, 0x20, 0xf0, 0x00, 0xa4, 0x94, 0x45, 0x75, 0x26, 0x04, 0xd7, 0xe3, 0x85, 0x45, 0x11, 0x5d, + 0x86, 0xf5, 0x10, 0x37, 0xa7, 0x63, 0x73, 0x53, 0x0d, 0xfe, 0x81, 0x98, 0x04, 0xd5, 0xf0, 0x4b, 0x4a, 0xda, 0xe8, + 0x46, 0x48, 0x29, 0x4c, 0xfb, 0x9d, 0x09, 0xfd, 0xe4, 0x47, 0x1f, 0xfa, 0xc2, 0xe7, 0x3e, 0x66, 0x42, 0xdc, 0x52, + 0xd1, 0xfc, 0x6d, 0xe0, 0x35, 0xb3, 0xfd, 0x6e, 0x85, 0x3f, 0xc8, 0xa7, 0xe3, 0xbd, 0x5f, 0x75, 0xbd, 0xb5, 0x39, + 0x75, 0x43, 0x3d, 0xe2, 0xef, 0x11, 0x44, 0x0d, 0x1f, 0x4b, 0xaf, 0xdd, 0x83, 0x84, 0x73, 0xec, 0x62, 0xb8, 0x2a, + 0xd7, 0xc1, 0xc7, 0x79, 0x99, 0xe7, 0xc6, 0x6c, 0x1a, 0xc1, 0x7d, 0xe1, 0x83, 0xcf, 0x38, 0x33, 0x9a, 0x7d, 0xc6, + 0xb2, 0x6d, 0xad, 0x54, 0x3a, 0xe5, 0xda, 0x52, 0xfb, 0x7e, 0x8d, 0xe2, 0x57, 0x58, 0xdb, 0xa6, 0x5d, 0xdb, 0xf4, + 0x4c, 0xd5, 0x78, 0x1d, 0x81, 0x67, 0xc9, 0x1f, 0xc7, 0x56, 0x58, 0xdf, 0xa2, 0x31, 0x0b, 0x6c, 0x4e, 0x6c, 0x97, + 0xa3, 0x97, 0xbf, 0x18, 0xdb, 0xc7, 0xd0, 0x4b, 0x2d, 0x62, 0x8a, 0x90, 0xbe, 0xac, 0xd2, 0xad, 0xa4, 0x89, 0x1e, + 0xdf, 0x43, 0xa8, 0xc2, 0x7e, 0xef, 0x39, 0x08, 0xd0, 0xd8, 0x6b, 0x2e, 0x28, 0x3a, 0xd7, 0xe9, 0x4a, 0x20, 0x74, + 0xe1, 0xf7, 0xa1, 0x7d, 0x53, 0x74, 0xaa, 0x83, 0xb4, 0x0c, 0x54, 0x13, 0x79, 0xf5, 0x3d, 0xb9, 0x1c, 0xe4, 0x2a, + 0xc3, 0x43, 0x8f, 0x0e, 0xdf, 0xe4, 0xe1, 0xd2, 0xc2, 0x4e, 0x24, 0x7e, 0xf3, 0x33, 0xb7, 0x62, 0xde, 0x6f, 0x47, + 0x47, 0x8b, 0x70, 0x50, 0x59, 0xcb, 0x5b, 0x64, 0x3a, 0x54, 0x40, 0x1a, 0xa8, 0xce, 0x12, 0x89, 0xe5, 0xfc, 0x57, + 0xfa, 0xd1, 0x6d, 0x88, 0x1f, 0xdd, 0x54, 0xf4, 0xfa, 0xb8, 0xb7, 0x02, 0xd0, 0x8d, 0xea, 0x33, 0x50, 0x65, 0xe6, + 0x5c, 0x94, 0xbe, 0xbf, 0xc5, 0xfe, 0xbe, 0x76, 0x11, 0x7d, 0xef, 0xb4, 0x7e, 0x76, 0x42, 0x56, 0xce, 0x3f, 0x7d, + 0x84, 0x8d, 0x0a, 0xea, 0xff, 0x81, 0x6b, 0xda, 0xd7, 0x81, 0x4e, 0x9c, 0x5f, 0xca, 0x44, 0x7a, 0x2e, 0x89, 0xcb, + 0x8c, 0x4f, 0x30, 0x0b, 0x24, 0xed, 0xf8, 0xa3, 0x8b, 0xe2, 0x2a, 0x9c, 0xfb, 0x8c, 0x75, 0x9a, 0x37, 0x4e, 0xad, + 0x0d, 0xf6, 0xeb, 0x1b, 0xdd, 0x64, 0x44, 0xd6, 0xb9, 0x39, 0xc3, 0x9a, 0xd1, 0x47, 0x88, 0xe4, 0x16, 0x4d, 0xa8, + 0x8e, 0x19, 0x2c, 0x0f, 0x7a, 0xf0, 0x9b, 0x74, 0xde, 0x6d, 0xc4, 0x96, 0x99, 0x81, 0x47, 0x23, 0xb6, 0xe1, 0x51, + 0x84, 0x0c, 0x32, 0x70, 0xce, 0x77, 0xd2, 0xfd, 0x50, 0x90, 0x8c, 0x0f, 0x8e, 0xcf, 0x1d, 0xdc, 0x74, 0x2f, 0x0b, + 0x64, 0xa5, 0x1e, 0x43, 0x73, 0xb3, 0x20, 0x6a, 0xb3, 0x4d, 0x79, 0x83, 0x2f, 0xf8, 0xd2, 0xf5, 0x8a, 0x54, 0x57, + 0xda, 0x6a, 0xe9, 0x29, 0x2c, 0xcd, 0x82, 0x81, 0x6c, 0x69, 0xb1, 0x2c, 0x62, 0x0c, 0xd2, 0x70, 0x9d, 0x4d, 0x11, + 0x4a, 0x13, 0x84, 0x3a, 0x14, 0x98, 0x12, 0x05, 0x3a, 0x05, 0xe0, 0xa0, 0x9c, 0xd0, 0x5e, 0x07, 0xbf, 0xa7, 0xeb, + 0x65, 0xd6, 0x7e, 0x7f, 0x6f, 0x38, 0x5f, 0x6f, 0x87, 0x67, 0xec, 0xf5, 0xe4, 0xbf, 0x38, 0x83, 0xfc, 0x9a, 0xe6, + 0xe6, 0xaa, 0x67, 0x2c, 0x17, 0x49, 0xb4, 0x3a, 0x7f, 0xf9, 0x26, 0x53, 0x8f, 0x7e, 0xd0, 0xd5, 0x7a, 0xea, 0x6e, + 0xb2, 0x37, 0x8c, 0x0f, 0xd4, 0x7a, 0x19, 0x4b, 0x8c, 0xd5, 0xaa, 0xe8, 0xff, 0xeb, 0x5a, 0xf8, 0x2a, 0x69, 0x0f, + 0x54, 0x17, 0xe2, 0xfe, 0x4a, 0x8f, 0xcf, 0x08, 0x0e, 0x17, 0x6d, 0x17, 0x27, 0x74, 0xa5, 0xd6, 0xa2, 0x42, 0xb7, + 0x86, 0x19, 0x62, 0xaf, 0x2d, 0xf1, 0x2f, 0xfd, 0x24, 0x4b, 0xd1, 0x77, 0xc7, 0xd0, 0xb9, 0xfc, 0xe1, 0x70, 0x75, + 0xac, 0x9a, 0xe6, 0xa7, 0x77, 0xe3, 0xec, 0xf7, 0x30, 0xb7, 0x7e, 0x57, 0xac, 0xe8, 0x08, 0x05, 0x9e, 0xac, 0x4c, + 0xe8, 0xf5, 0xe5, 0x85, 0x32, 0x93, 0xcd, 0x27, 0xcc, 0x40, 0x4f, 0xde, 0x31, 0xd0, 0x8d, 0x53, 0xed, 0x23, 0x67, + 0xc5, 0xff, 0x2c, 0x47, 0x6d, 0xb6, 0x3b, 0x4c, 0x54, 0xef, 0xf6, 0x8e, 0xdc, 0x07, 0xe8, 0x33, 0xe8, 0x23, 0x53, + 0x01, 0xea, 0xb8, 0x55, 0xc5, 0xb0, 0x99, 0xa4, 0xdd, 0x7d, 0x63, 0x7d, 0xac, 0x97, 0x99, 0x63, 0x9f, 0xd8, 0x02, + 0x10, 0xc7, 0x1f, 0x94, 0x55, 0x81, 0xaf, 0xcf, 0xdf, 0xe2, 0x6d, 0xba, 0xcf, 0x68, 0x08, 0x4c, 0x98, 0xa7, 0x3f, + 0x19, 0xa5, 0xf4, 0xfd, 0xe9, 0x89, 0xd2, 0x6b, 0x83, 0x7b, 0x9a, 0x3d, 0x5d, 0x30, 0x9e, 0xfe, 0x43, 0x50, 0x6b, + 0xef, 0xfd, 0x95, 0x5b, 0xeb, 0x3b, 0x48, 0xb3, 0x33, 0xfa, 0xc1, 0x69, 0x0e, 0x72, 0x2c, 0x4a, 0xab, 0xc7, 0xf9, + 0x11, 0xcd, 0x5c, 0x08, 0xf0, 0x21, 0x2b, 0x0e, 0xfa, 0xe7, 0x18, 0x63, 0xae, 0xe0, 0xc7, 0xe8, 0x8f, 0x0e, 0x42, + 0x6d, 0xe5, 0xd3, 0x7d, 0xf1, 0x77, 0x6a, 0xcd, 0x51, 0xeb, 0x59, 0x15, 0xaa, 0xbe, 0x93, 0xb2, 0xda, 0x64, 0x6b, + 0x05, 0xd0, 0xf8, 0x92, 0xe2, 0xfb, 0x3a, 0x24, 0x04, 0x55, 0x48, 0xc0, 0x2d, 0xab, 0xa4, 0x4b, 0xda, 0x2f, 0x39, + 0xbc, 0x91, 0xde, 0x43, 0xd8, 0x88, 0xbb, 0x8d, 0x5d, 0x1f, 0xd2, 0x9f, 0x29, 0xf2, 0x9b, 0x28, 0x63, 0x6c, 0xbd, + 0x71, 0x99, 0x91, 0x03, 0xff, 0x77, 0x37, 0x08, 0x44, 0x3e, 0x2a, 0x98, 0x25, 0xb5, 0xd3, 0x18, 0x62, 0x69, 0x4a, + 0x31, 0xfa, 0x95, 0xcb, 0xfb, 0xb3, 0xf9, 0xff, 0x61, 0x02, 0x93, 0xf1, 0x9f, 0x44, 0x07, 0xed, 0x2a, 0x42, 0xda, + 0x47, 0x44, 0x17, 0x0f, 0x9a, 0x3f, 0x7e, 0x3b, 0x54, 0x0e, 0xb6, 0xb6, 0x05, 0x55, 0xc6, 0x20, 0xf2, 0x1e, 0xc1, + 0x59, 0x43, 0x07, 0x26, 0x7f, 0xc7, 0xb5, 0xe5, 0x14, 0xa2, 0x7d, 0xf5, 0x5d, 0x49, 0xa9, 0x2b, 0x9f, 0x3e, 0xf4, + 0x7f, 0xd3, 0x00, 0x98, 0xd4, 0xa8, 0xbc, 0x4e, 0x5b, 0xbe, 0xf0, 0x7d, 0xd9, 0x54, 0x64, 0xe3, 0xf8, 0xe8, 0x8a, + 0x8e, 0xb7, 0xc6, 0xb8, 0x5f, 0x44, 0x49, 0xab, 0x6b, 0x3f, 0xdd, 0xb4, 0xa0, 0x1b, 0x47, 0x44, 0x8f, 0xf1, 0x2e, + 0xe6, 0xb6, 0x37, 0xaf, 0x12, 0xeb, 0xf8, 0xa8, 0x4d, 0xed, 0x68, 0x33, 0x85, 0x07, 0x76, 0xc0, 0x63, 0x78, 0x6a, + 0xf9, 0x78, 0xb8, 0xe1, 0x10, 0x44, 0xb0, 0x41, 0x02, 0x8c, 0xa4, 0x24, 0x31, 0x65, 0x49, 0xec, 0x71, 0x38, 0xae, + 0xb4, 0x15, 0x3e, 0x9d, 0x4a, 0x77, 0xc8, 0x1f, 0x6a, 0xbc, 0x4f, 0xaa, 0xe1, 0xb1, 0xcf, 0x38, 0x89, 0x5b, 0x89, + 0xfa, 0x51, 0x1e, 0xc4, 0x56, 0xb0, 0xcf, 0x02, 0x5c, 0x55, 0x84, 0xb3, 0x35, 0x0f, 0x1c, 0xc0, 0x06, 0x09, 0x4c, + 0x29, 0xe2, 0x28, 0x8e, 0xef, 0x7e, 0xd2, 0x4f, 0xfc, 0xdc, 0x8a, 0x65, 0x31, 0x2b, 0x48, 0xf2, 0xfe, 0x73, 0x78, + 0x24, 0x4f, 0xcb, 0x9b, 0x24, 0xd9, 0x64, 0xfe, 0x7e, 0x7c, 0x61, 0x4f, 0x2c, 0x7c, 0xc1, 0x0a, 0xa7, 0x3b, 0xb2, + 0xf4, 0x32, 0x6a, 0x5d, 0xfc, 0x05, 0x4e, 0xb0, 0xbf, 0x4d, 0xef, 0x5d, 0x79, 0x75, 0xbf, 0xea, 0x7d, 0x5f, 0xae, + 0x49, 0xed, 0x97, 0x1b, 0x2d, 0x1e, 0x3f, 0x4f, 0x27, 0x5a, 0xb7, 0x8c, 0x3e, 0xf4, 0xbf, 0x79, 0x76, 0x87, 0x20, + 0xfb, 0x49, 0xd6, 0xde, 0x27, 0xb1, 0xed, 0x07, 0x28, 0x72, 0xdd, 0xdc, 0xaf, 0x10, 0x4e, 0xbf, 0xb3, 0xc0, 0x4b, + 0x09, 0x7e, 0x66, 0x83, 0xaa, 0xc7, 0x6a, 0x39, 0xb9, 0xda, 0xc1, 0xa0, 0x1c, 0x2e, 0x78, 0x02, 0xd6, 0x59, 0xcc, + 0x0c, 0x4a, 0xba, 0xa3, 0xd6, 0xdf, 0x3d, 0xc5, 0xf7, 0xda, 0x66, 0x36, 0x26, 0x22, 0xb9, 0x51, 0xf6, 0xb0, 0x74, + 0x11, 0xce, 0xf2, 0x9d, 0xf3, 0xf1, 0xf7, 0x46, 0xc8, 0x19, 0x56, 0xf9, 0x2e, 0x91, 0x93, 0xcf, 0xf8, 0x94, 0x0d, + 0x57, 0x97, 0x1b, 0x2d, 0x36, 0x88, 0x56, 0xf4, 0x95, 0x38, 0x20, 0x51, 0xb4, 0x5b, 0x3c, 0xef, 0x65, 0x48, 0xfe, + 0x36, 0xb9, 0xc6, 0x01, 0x46, 0x2e, 0xb3, 0x9c, 0xc1, 0x17, 0xd7, 0x8c, 0x81, 0xea, 0x57, 0xd3, 0xfb, 0x60, 0x91, + 0x92, 0x51, 0x69, 0x9e, 0xd1, 0xa8, 0x65, 0x2e, 0xc1, 0xf8, 0x0a, 0x0d, 0xfd, 0x88, 0x7d, 0xfa, 0x7c, 0x23, 0x72, + 0x77, 0x0c, 0xeb, 0x3f, 0x8a, 0xef, 0x01, 0x72, 0xec, 0x0d, 0xea, 0x06, 0xd9, 0xb0, 0x48, 0x6a, 0x44, 0xe3, 0x12, + 0xab, 0x74, 0x41, 0x36, 0xb0, 0x7b, 0x61, 0xef, 0x7f, 0xc7, 0x7f, 0xa6, 0x12, 0x09, 0x43, 0x84, 0x2f, 0x36, 0x32, + 0xe8, 0x06, 0x17, 0xc1, 0xf4, 0x19, 0xe1, 0x41, 0x92, 0xa8, 0xbb, 0x62, 0x2c, 0xf0, 0x04, 0x4a, 0x50, 0x32, 0xcf, + 0xe2, 0xea, 0x0e, 0xfa, 0xff, 0xa5, 0x18, 0xd5, 0xe7, 0xed, 0xf2, 0xa6, 0x12, 0xf5, 0xd0, 0x21, 0xc7, 0x79, 0xc1, + 0x17, 0x60, 0xb3, 0x27, 0x4b, 0x5e, 0x02, 0x31, 0x4c, 0xfe, 0x2b, 0x2c, 0x2c, 0x7d, 0x8a, 0xe5, 0x74, 0xf8, 0x97, + 0x6b, 0x16, 0x7b, 0x7b, 0xb8, 0xe9, 0x84, 0x61, 0x7c, 0x4a, 0xf3, 0x05, 0xbd, 0x5d, 0x37, 0x35, 0x6c, 0xe5, 0xc7, + 0x55, 0x16, 0x4f, 0x9d, 0xfb, 0xe5, 0x9b, 0xbc, 0xb8, 0xb4, 0x67, 0x53, 0x75, 0x7e, 0xf0, 0xdc, 0x17, 0xe3, 0x96, + 0xf1, 0xdf, 0xe8, 0x88, 0x97, 0x5f, 0xbc, 0xaf, 0x48, 0xc4, 0xcc, 0x83, 0xcd, 0x7d, 0x5d, 0x90, 0xd3, 0x2f, 0xd1, + 0x3c, 0x2c, 0x57, 0x94, 0x5e, 0x65, 0x76, 0xd5, 0x0f, 0xdf, 0xe4, 0xd9, 0xa5, 0x97, 0x1d, 0xb4, 0xda, 0x7c, 0xaa, + 0x6d, 0xc0, 0xda, 0x02, 0xfa, 0x2f, 0x4b, 0xb5, 0xd9, 0x86, 0x34, 0x5e, 0xa8, 0x7c, 0x57, 0x1d, 0x51, 0x03, 0xfb, + 0x23, 0x3b, 0x6c, 0x78, 0xa0, 0xff, 0x36, 0xbd, 0x9e, 0x3a, 0xb5, 0xaa, 0xb6, 0x3b, 0x09, 0x70, 0xc6, 0x64, 0xad, + 0x62, 0x8c, 0x04, 0xd1, 0x5d, 0x7a, 0xb3, 0x6d, 0x7c, 0x68, 0xda, 0x52, 0xc1, 0xf7, 0xfd, 0x89, 0x61, 0x8a, 0x7b, + 0xda, 0x70, 0xf1, 0x2c, 0x14, 0xf8, 0x9d, 0xb1, 0x43, 0x4f, 0xf4, 0x00, 0x5d, 0x1f, 0x64, 0xb3, 0x58, 0xb6, 0x4b, + 0x20, 0xcf, 0x33, 0xf8, 0xd9, 0x22, 0x96, 0x45, 0xfa, 0x66, 0x46, 0xf7, 0x8f, 0x9a, 0x20, 0x90, 0xb3, 0xa2, 0x2f, + 0x26, 0x05, 0x25, 0x72, 0x54, 0x53, 0x1f, 0xed, 0x4b, 0x9d, 0xa3, 0x2f, 0x36, 0xc2, 0x1a, 0x4a, 0x20, 0xea, 0x0c, + 0xf9, 0xad, 0x52, 0x70, 0xf3, 0xc4, 0x72, 0x81, 0x06, 0x03, 0x25, 0x5c, 0xce, 0x5f, 0xfc, 0x0f, 0xd9, 0x5a, 0xeb, + 0x02, 0x69, 0x65, 0xc3, 0xfc, 0xaa, 0xca, 0xad, 0xe8, 0xe6, 0x3b, 0x34, 0x35, 0xbd, 0x7a, 0x22, 0x54, 0x78, 0xaf, + 0xdc, 0x3f, 0xab, 0xc8, 0xb8, 0x8e, 0x73, 0x48, 0x73, 0x10, 0xc5, 0x33, 0x29, 0x1b, 0x1a, 0x34, 0x53, 0x0e, 0xb2, + 0xaf, 0x32, 0x40, 0xa2, 0xac, 0xea, 0x28, 0xb6, 0xb8, 0xdc, 0xd0, 0x76, 0x89, 0xdb, 0x96, 0x52, 0x9b, 0x48, 0x5b, + 0xbc, 0xc2, 0x23, 0x4b, 0x88, 0x2e, 0x3b, 0x00, 0x85, 0x48, 0x8e, 0xac, 0x7b, 0xae, 0x48, 0xd1, 0xca, 0xed, 0xdb, + 0xb0, 0xe3, 0x3a, 0x42, 0xeb, 0xae, 0xe6, 0xaa, 0x35, 0x6a, 0x34, 0x32, 0xc9, 0xb0, 0x71, 0x6d, 0xf0, 0xaa, 0x04, + 0x35, 0xd4, 0xd8, 0xc6, 0xa1, 0x4c, 0xff, 0xf3, 0xcc, 0x17, 0x33, 0x67, 0x5a, 0x5f, 0xf2, 0xfd, 0x24, 0xb6, 0x48, + 0x45, 0xc3, 0x7e, 0xc6, 0xbe, 0x89, 0x0c, 0x41, 0x8b, 0x8e, 0x58, 0xf5, 0xa9, 0x58, 0xcd, 0x75, 0x32, 0x28, 0x50, + 0x6a, 0xde, 0x38, 0x6d, 0xae, 0x57, 0xe5, 0xdc, 0x23, 0xae, 0x8c, 0x81, 0xdd, 0x9c, 0xdc, 0xb6, 0xf2, 0xbb, 0x99, + 0x9f, 0x36, 0xce, 0x2b, 0x45, 0x86, 0x33, 0xb6, 0x73, 0x52, 0x9f, 0x17, 0x48, 0x0c, 0x97, 0x16, 0xf3, 0x87, 0x0b, + 0x4a, 0x4d, 0x1d, 0x16, 0x8a, 0x24, 0xa7, 0xa5, 0xa9, 0xc0, 0x6f, 0x3f, 0xbc, 0xf6, 0xca, 0x2c, 0x15, 0x0b, 0x02, + 0x2f, 0x14, 0xf3, 0xe7, 0xc2, 0x0e, 0x16, 0xef, 0x33, 0xa1, 0x83, 0x49, 0x9f, 0xf2, 0xdc, 0xe6, 0x26, 0xef, 0xe5, + 0x85, 0xc3, 0xe4, 0xc5, 0x86, 0xe8, 0x67, 0x11, 0x8d, 0x7e, 0x3a, 0xe8, 0x5c, 0x5b, 0xa8, 0x70, 0xe2, 0x09, 0x92, + 0x6c, 0x4a, 0xa1, 0x7b, 0xcd, 0x23, 0x45, 0x52, 0x83, 0x1c, 0xed, 0x7e, 0x27, 0x17, 0xe3, 0xa4, 0xd5, 0x38, 0x2a, + 0xab, 0x24, 0xe1, 0xf3, 0x83, 0xe4, 0x36, 0xa1, 0x44, 0xf9, 0x2c, 0xd2, 0x8c, 0x24, 0x6b, 0xdc, 0x6b, 0x2b, 0xb8, + 0x46, 0xcc, 0xad, 0x0a, 0x06, 0x9b, 0xfd, 0x44, 0xfa, 0xd5, 0x76, 0xf0, 0x26, 0xc5, 0x83, 0x44, 0x09, 0x86, 0x8b, + 0x73, 0xfa, 0xa1, 0x45, 0x47, 0x7e, 0x9d, 0x8d, 0x30, 0x08, 0x0e, 0xa1, 0x14, 0x2a, 0x6b, 0x29, 0x68, 0xe8, 0xbf, + 0x27, 0x6b, 0x87, 0x14, 0x48, 0x04, 0x7c, 0x4e, 0xde, 0x4d, 0x98, 0x12, 0x9c, 0x3c, 0x95, 0x9c, 0x10, 0xae, 0x2a, + 0x16, 0x6f, 0x4a, 0xee, 0x40, 0x79, 0x0c, 0xdc, 0x8a, 0xa0, 0x0b, 0xaa, 0x13, 0x51, 0x2a, 0x70, 0xf4, 0xf6, 0x29, + 0xba, 0xbb, 0x8b, 0x33, 0x58, 0x88, 0x04, 0xf7, 0x2a, 0xb3, 0x4e, 0x6a, 0xc9, 0x51, 0x46, 0x21, 0x9b, 0xcd, 0x46, + 0x34, 0xfa, 0x84, 0x2b, 0x60, 0xe2, 0x49, 0xfc, 0x1f, 0x51, 0x55, 0x13, 0xad, 0xbb, 0xa1, 0xbb, 0x2e, 0x49, 0x1f, + 0x9a, 0x8e, 0x61, 0x5a, 0x5c, 0xb7, 0x13, 0x92, 0x3a, 0xd3, 0x7e, 0x1b, 0x06, 0xcf, 0x6f, 0xce, 0x57, 0x9b, 0x3f, + 0xde, 0x6e, 0xad, 0x44, 0x51, 0xe4, 0x82, 0xc9, 0xc0, 0x91, 0x11, 0x72, 0xd5, 0x45, 0xdd, 0xf1, 0xb0, 0x35, 0x2d, + 0x92, 0xdc, 0xe9, 0xb8, 0xdd, 0x40, 0x35, 0xbe, 0xfc, 0xc6, 0x75, 0x9b, 0xcd, 0x10, 0xf2, 0x76, 0x7f, 0xf0, 0x34, + 0x39, 0x10, 0x55, 0xe5, 0x5f, 0x4a, 0xd6, 0x0f, 0x03, 0x4f, 0x4a, 0x72, 0xe8, 0xa9, 0x30, 0xee, 0xc9, 0xca, 0x44, + 0x87, 0x89, 0x45, 0x24, 0xff, 0x2f, 0x7f, 0x04, 0x4b, 0x4c, 0x71, 0x2d, 0x15, 0xd8, 0x62, 0x7e, 0x58, 0xdd, 0x5b, + 0x19, 0x03, 0x22, 0x97, 0x00, 0x12, 0x21, 0x6f, 0xc8, 0xd7, 0x49, 0xf2, 0xae, 0x70, 0xed, 0x54, 0xaf, 0x79, 0x62, + 0xe6, 0x91, 0xdf, 0xf9, 0x89, 0x79, 0x9c, 0x6a, 0x82, 0x59, 0x82, 0x2b, 0x26, 0x2e, 0x00, 0xaf, 0xf4, 0x17, 0x55, + 0x6e, 0x0a, 0x04, 0x82, 0xb3, 0xaf, 0xd2, 0x9f, 0x14, 0x54, 0x21, 0x6e, 0x47, 0x42, 0x9b, 0x6a, 0x11, 0x9e, 0xd9, + 0x33, 0x0e, 0x2e, 0x36, 0x39, 0x22, 0x03, 0x03, 0x90, 0xe5, 0xa9, 0xd7, 0xc2, 0x3e, 0x9f, 0xf9, 0x37, 0xda, 0x5e, + 0x5b, 0x65, 0x2b, 0x16, 0x3c, 0x78, 0xed, 0xd5, 0x77, 0xb3, 0x4a, 0xd9, 0x2a, 0xb7, 0xfc, 0x86, 0xce, 0xf0, 0x3e, + 0x83, 0x36, 0xd1, 0xf7, 0x1e, 0x0d, 0x56, 0x28, 0xcd, 0x4f, 0x09, 0x93, 0xb0, 0x10, 0xe6, 0x98, 0x6d, 0x27, 0x54, + 0xcf, 0x99, 0xf5, 0xab, 0x14, 0x55, 0xfe, 0x91, 0x63, 0xdc, 0x75, 0xea, 0x5c, 0x98, 0x67, 0xf2, 0x99, 0x92, 0x6c, + 0x58, 0x03, 0xe3, 0x86, 0xe1, 0xdb, 0xfc, 0x8b, 0x9e, 0x0c, 0xed, 0x51, 0xbf, 0xef, 0xd0, 0xf6, 0x30, 0xaa, 0xd3, + 0xad, 0x10, 0x17, 0x5d, 0x18, 0x82, 0x70, 0xf7, 0x29, 0x2f, 0x48, 0xeb, 0xb0, 0xf6, 0x54, 0xa3, 0xc3, 0xa0, 0xc6, + 0x40, 0x9d, 0x16, 0x83, 0xe5, 0xb4, 0x54, 0x50, 0x36, 0x05, 0x33, 0xd5, 0x06, 0x6e, 0xd8, 0x9a, 0xfb, 0x7f, 0xf9, + 0x1f, 0x21, 0xbc, 0x3f, 0xf0, 0x87, 0xf1, 0xbf, 0x97, 0x48, 0x8e, 0x98, 0xb0, 0xa4, 0x92, 0xbb, 0x77, 0x01, 0xe3, + 0x4f, 0xa1, 0xbf, 0x86, 0xf6, 0xa1, 0x1d, 0x43, 0x7b, 0x20, 0xca, 0xe0, 0xfe, 0x6a, 0x29, 0xc6, 0x4e, 0x01, 0x21, + 0xc6, 0xf2, 0xa2, 0x04, 0x2a, 0x29, 0xc5, 0x81, 0x17, 0x15, 0x00, 0xce, 0xbb, 0x40, 0xc7, 0xa6, 0xd8, 0xf6, 0x92, + 0x20, 0x06, 0x15, 0x10, 0x4d, 0x89, 0x9c, 0x93, 0xb4, 0xaf, 0x38, 0xf1, 0x1e, 0x73, 0x72, 0x62, 0x1f, 0xd4, 0xf5, + 0xf9, 0x86, 0xcb, 0xb1, 0x40, 0xd7, 0x15, 0x63, 0x53, 0xb6, 0xa3, 0xcb, 0x8b, 0xd5, 0xcb, 0x5b, 0x31, 0x89, 0x02, + 0xe9, 0xd2, 0x46, 0x5e, 0x90, 0x8f, 0xb8, 0x3d, 0x5b, 0x96, 0x65, 0xf3, 0xa2, 0x65, 0x9c, 0xaf, 0x0c, 0x90, 0x0d, + 0x50, 0xb4, 0xa5, 0x2f, 0x2c, 0xe4, 0xb0, 0x2c, 0x0d, 0xe5, 0x36, 0x70, 0xae, 0xca, 0xf6, 0xe6, 0x4d, 0x82, 0x34, + 0x3f, 0xe4, 0x75, 0xac, 0x4d, 0x2d, 0xb5, 0xff, 0x6e, 0xab, 0x36, 0xec, 0x68, 0x14, 0xcd, 0x81, 0xe9, 0xa8, 0x73, + 0x98, 0x8f, 0x39, 0x17, 0xe4, 0x59, 0xd4, 0xb6, 0x76, 0xbd, 0x95, 0x3c, 0xbf, 0xf1, 0x2a, 0xce, 0x05, 0x0f, 0xab, + 0x3f, 0x3e, 0xb6, 0xd4, 0xc6, 0xf5, 0x2d, 0xbe, 0xf1, 0x07, 0x7f, 0x0f, 0xa2, 0x54, 0x43, 0x0d, 0xe7, 0x2f, 0x27, + 0xe7, 0xb5, 0x7d, 0x02, 0x2c, 0xa7, 0xad, 0xca, 0x7e, 0x9d, 0x57, 0xb1, 0x30, 0x13, 0x99, 0xef, 0xd2, 0x9a, 0xe8, + 0x4b, 0x4d, 0x16, 0x99, 0xd3, 0xf1, 0x37, 0x6d, 0xf8, 0xed, 0xd2, 0x9b, 0x11, 0x42, 0xc9, 0x8c, 0xd0, 0x8c, 0xa3, + 0x9a, 0x37, 0xff, 0xa1, 0xe5, 0xfb, 0xb2, 0x43, 0x0a, 0xee, 0x78, 0x4b, 0x56, 0x43, 0x79, 0x3b, 0x5d, 0x9b, 0x8f, + 0xbc, 0x2c, 0x40, 0xed, 0xa9, 0x54, 0x82, 0x04, 0x7e, 0x4f, 0x1f, 0x9a, 0x87, 0xcd, 0xa6, 0xaa, 0xbd, 0x5e, 0x1f, + 0x1a, 0x13, 0x61, 0x2a, 0x8f, 0x60, 0x71, 0xb9, 0x51, 0x68, 0x67, 0xf8, 0x95, 0xce, 0xb9, 0x19}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 7bf86f6e8b..b230f2a906 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,7608 +10,7677 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x69, 0x7b, 0x1b, 0x37, 0xb2, 0x30, 0xfa, - 0xf9, 0xde, 0x5f, 0x21, 0xf5, 0x71, 0x34, 0x0d, 0x11, 0x6c, 0x91, 0xd4, 0x62, 0xb9, 0x29, 0x88, 0xd7, 0xeb, 0xd8, - 0x59, 0x6c, 0xc7, 0xb2, 0x9d, 0x49, 0x18, 0x1e, 0x07, 0xec, 0x06, 0x49, 0xc4, 0x4d, 0x80, 0x69, 0x80, 0x96, 0x14, - 0x92, 0xff, 0xfd, 0x3e, 0x85, 0xa5, 0x1b, 0x4d, 0xd2, 0x9e, 0x39, 0xef, 0x5d, 0x9e, 0xf7, 0xe4, 0x8c, 0xc5, 0xc6, - 0x8e, 0x42, 0xa1, 0x50, 0x55, 0xa8, 0x2a, 0x5c, 0x1d, 0xe6, 0x32, 0xd3, 0xf7, 0x0b, 0x76, 0x30, 0xd3, 0xf3, 0xe2, - 0xfa, 0xca, 0xfd, 0xcb, 0x68, 0x7e, 0x7d, 0x55, 0x70, 0xf1, 0xf9, 0xa0, 0x64, 0x05, 0xe1, 0x99, 0x14, 0x07, 0xb3, - 0x92, 0x4d, 0x48, 0x4e, 0x35, 0x4d, 0xf9, 0x9c, 0x4e, 0xd9, 0xc1, 0xc9, 0xf5, 0xd5, 0x9c, 0x69, 0x7a, 0x90, 0xcd, - 0x68, 0xa9, 0x98, 0x26, 0x1f, 0xde, 0xbf, 0x68, 0x5f, 0x5e, 0x5f, 0xa9, 0xac, 0xe4, 0x0b, 0x7d, 0x00, 0x4d, 0x92, - 0xb9, 0xcc, 0x97, 0x05, 0xbb, 0x3e, 0x39, 0xb9, 0xbd, 0xbd, 0x4d, 0xfe, 0x54, 0xff, 0xe7, 0x17, 0x5a, 0x1e, 0xfc, - 0xb3, 0x24, 0x6f, 0xc6, 0x7f, 0xb2, 0x4c, 0x27, 0x39, 0x9b, 0x70, 0xc1, 0xde, 0x96, 0x72, 0xc1, 0x4a, 0x7d, 0xdf, - 0x87, 0xcc, 0x9f, 0x4b, 0x12, 0x73, 0xac, 0x31, 0x43, 0xe4, 0x5a, 0x1f, 0x70, 0x71, 0xc0, 0x07, 0xff, 0x2c, 0x4d, - 0xca, 0x8a, 0x89, 0xe5, 0x9c, 0x95, 0x74, 0x5c, 0xb0, 0xf4, 0xb0, 0x83, 0x33, 0x29, 0x26, 0x7c, 0xba, 0xac, 0xbe, - 0x6f, 0x4b, 0xae, 0xfd, 0xef, 0x2f, 0xb4, 0x58, 0xb2, 0x94, 0x6d, 0x50, 0xca, 0x87, 0x7a, 0x44, 0x98, 0x69, 0xf9, - 0x73, 0xdd, 0x70, 0xfc, 0xb3, 0x69, 0xf2, 0x7e, 0xc1, 0xe4, 0xe4, 0x40, 0x1f, 0x92, 0x48, 0xdd, 0xcf, 0xc7, 0xb2, - 0x88, 0x06, 0xba, 0x15, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0xf5, 0x33, 0x29, 0x94, 0x3e, 0x10, 0x9c, 0xdc, 0x72, 0x91, - 0xcb, 0x5b, 0x7c, 0x2b, 0x88, 0xe0, 0xc9, 0xcd, 0x8c, 0xe6, 0xf2, 0xf6, 0x9d, 0x94, 0xfa, 0xe8, 0x28, 0x76, 0xdf, - 0xf7, 0x4f, 0x6f, 0x6e, 0x08, 0x21, 0x5f, 0x24, 0xcf, 0x0f, 0x3a, 0xeb, 0x75, 0x90, 0x9a, 0x08, 0xaa, 0xf9, 0x17, - 0x66, 0x2b, 0xa1, 0xa3, 0xa3, 0x88, 0xe6, 0x72, 0xa1, 0x59, 0x7e, 0xa3, 0xef, 0x0b, 0x76, 0x33, 0x63, 0x4c, 0xab, - 0x88, 0x8b, 0x83, 0x67, 0x32, 0x5b, 0xce, 0x99, 0xd0, 0xc9, 0xa2, 0x94, 0x5a, 0xc2, 0xc0, 0x8e, 0x8e, 0xa2, 0x92, - 0x2d, 0x0a, 0x9a, 0x31, 0xc8, 0x7f, 0x7a, 0x73, 0x53, 0xd7, 0xa8, 0x0b, 0xe1, 0xcf, 0x82, 0xdc, 0x98, 0xa1, 0xc7, - 0x08, 0xff, 0x22, 0x88, 0x60, 0xb7, 0x07, 0xbf, 0x30, 0xfa, 0xf9, 0x27, 0xba, 0xe8, 0x67, 0x05, 0x55, 0xea, 0xe0, - 0xb5, 0x5c, 0x99, 0x69, 0x94, 0xcb, 0x4c, 0xcb, 0x32, 0xd6, 0x98, 0x61, 0x81, 0x56, 0x7c, 0x12, 0xeb, 0x19, 0x57, - 0xc9, 0xa7, 0x07, 0x99, 0x52, 0xef, 0x98, 0x5a, 0x16, 0xfa, 0x01, 0x39, 0xec, 0x60, 0x71, 0x48, 0xc8, 0x67, 0x81, - 0xf4, 0xac, 0x94, 0xb7, 0x07, 0xcf, 0xcb, 0x52, 0x96, 0x71, 0xf4, 0xf4, 0xe6, 0xc6, 0x96, 0x38, 0xe0, 0xea, 0x40, - 0x48, 0x7d, 0x50, 0xb5, 0x07, 0xd0, 0x4e, 0x0e, 0x3e, 0x28, 0x76, 0xf0, 0xc7, 0x52, 0x28, 0x3a, 0x61, 0x4f, 0x6f, - 0x6e, 0xfe, 0x38, 0x90, 0xe5, 0xc1, 0x1f, 0x99, 0x52, 0x7f, 0x1c, 0x70, 0xa1, 0x34, 0xa3, 0x79, 0x12, 0xa1, 0xbe, - 0xe9, 0x2c, 0x53, 0xea, 0x3d, 0xbb, 0xd3, 0x44, 0x63, 0xf3, 0xa9, 0x09, 0xdb, 0x4c, 0x99, 0x3e, 0x50, 0xd5, 0xbc, - 0x62, 0xb4, 0x2a, 0x98, 0x3e, 0xd0, 0xc4, 0xe4, 0x4b, 0x07, 0x7f, 0x66, 0x3f, 0x75, 0x9f, 0x4f, 0xe2, 0x5b, 0x71, - 0x74, 0xa4, 0x2b, 0x40, 0xa3, 0x95, 0x5b, 0x21, 0xc2, 0x0e, 0x7d, 0xda, 0xd1, 0x11, 0x4b, 0x0a, 0x26, 0xa6, 0x7a, - 0x46, 0x08, 0xe9, 0xf6, 0xc5, 0xd1, 0x51, 0xac, 0xc9, 0x2f, 0x22, 0x99, 0x32, 0x1d, 0x33, 0x84, 0x70, 0x5d, 0xfb, - 0xe8, 0x28, 0xb6, 0x40, 0x90, 0x44, 0x1b, 0xc0, 0x35, 0x60, 0x8c, 0x12, 0x07, 0xfd, 0x9b, 0x7b, 0x91, 0xc5, 0xe1, - 0xf8, 0x11, 0x16, 0x47, 0x47, 0xbf, 0x88, 0x44, 0x41, 0x8b, 0x58, 0x23, 0xb4, 0x29, 0x99, 0x5e, 0x96, 0xe2, 0x40, - 0x6f, 0xb4, 0xbc, 0xd1, 0x25, 0x17, 0xd3, 0x18, 0xad, 0x7c, 0x5a, 0x50, 0x71, 0xb3, 0xb1, 0xc3, 0xfd, 0xad, 0x24, - 0x9c, 0x5c, 0x43, 0x8f, 0xaf, 0x65, 0xec, 0x70, 0x90, 0x13, 0x12, 0x29, 0x53, 0x37, 0x1a, 0xf0, 0x94, 0xb7, 0xa2, - 0x08, 0xdb, 0x51, 0xe2, 0xcf, 0x02, 0x61, 0xa1, 0x01, 0x75, 0x93, 0x24, 0xd1, 0x88, 0x5c, 0xaf, 0x3c, 0x58, 0x78, - 0x30, 0xd1, 0x01, 0x1f, 0x76, 0x46, 0xa9, 0x4e, 0x4a, 0x96, 0x2f, 0x33, 0x16, 0xc7, 0x02, 0x2b, 0x2c, 0x11, 0xb9, - 0x16, 0xad, 0xb8, 0x24, 0xd7, 0xb0, 0xde, 0x65, 0x73, 0xb1, 0x09, 0x39, 0xec, 0x20, 0x37, 0xc8, 0xd2, 0x8f, 0x10, - 0x40, 0xec, 0x06, 0x54, 0x12, 0x12, 0x89, 0xe5, 0x7c, 0xcc, 0xca, 0xa8, 0x2a, 0xd6, 0x6f, 0xe0, 0xc5, 0x52, 0xb1, - 0x83, 0x4c, 0xa9, 0x83, 0xc9, 0x52, 0x64, 0x9a, 0x4b, 0x71, 0x10, 0xb5, 0xca, 0x56, 0x64, 0xf1, 0xa1, 0x42, 0x87, - 0x08, 0x6d, 0x50, 0xac, 0x50, 0x8b, 0x0f, 0x65, 0xab, 0x3b, 0xc2, 0x30, 0x4a, 0xd4, 0x77, 0xed, 0x39, 0x08, 0x30, - 0xcc, 0x61, 0x92, 0x1b, 0xfc, 0xbd, 0xdd, 0xf9, 0x30, 0xc5, 0x5b, 0x31, 0xe0, 0xc9, 0xee, 0x4e, 0x21, 0x3a, 0x99, - 0xd3, 0x45, 0xcc, 0xc8, 0x35, 0x33, 0xd8, 0x45, 0x45, 0x06, 0x63, 0x6d, 0x2c, 0xdc, 0x80, 0xa5, 0x2c, 0xa9, 0x71, - 0x0a, 0xa5, 0x3a, 0x99, 0xc8, 0xf2, 0x39, 0xcd, 0x66, 0x50, 0xaf, 0xc2, 0x98, 0xdc, 0x6f, 0xb8, 0xac, 0x64, 0x54, - 0xb3, 0xe7, 0x05, 0x83, 0xaf, 0x38, 0x32, 0x35, 0x23, 0x84, 0x15, 0x6c, 0xf5, 0x82, 0xeb, 0xd7, 0x52, 0x64, 0xac, - 0xaf, 0x02, 0xfc, 0x32, 0x2b, 0xff, 0x58, 0xeb, 0x92, 0x8f, 0x97, 0x9a, 0xc5, 0x91, 0x80, 0x12, 0x11, 0x56, 0x08, - 0x8b, 0x44, 0xb3, 0x3b, 0xfd, 0x54, 0x0a, 0xcd, 0x84, 0x26, 0xcc, 0x43, 0x15, 0xf3, 0x84, 0x2e, 0x16, 0x4c, 0xe4, - 0x4f, 0x67, 0xbc, 0xc8, 0x63, 0x81, 0x36, 0x68, 0x83, 0x7f, 0x15, 0x04, 0x26, 0x49, 0xae, 0x79, 0x0a, 0xff, 0x7c, - 0x7d, 0x3a, 0xb1, 0x26, 0xd7, 0x66, 0x5b, 0x30, 0x12, 0x45, 0xfd, 0x89, 0x2c, 0x63, 0x37, 0x85, 0x03, 0x20, 0x5d, - 0xd0, 0xc7, 0xbb, 0x65, 0xc1, 0x14, 0x62, 0x2d, 0x22, 0xaa, 0x75, 0x74, 0x10, 0xfe, 0xad, 0x8c, 0x19, 0x2c, 0x00, - 0x47, 0x29, 0x37, 0x24, 0xf0, 0x47, 0xee, 0x36, 0x55, 0x5e, 0x11, 0xb5, 0xbf, 0x04, 0xc9, 0x79, 0xa2, 0xcb, 0xa5, - 0xd2, 0x2c, 0x7f, 0x7f, 0xbf, 0x60, 0x0a, 0x6b, 0x4a, 0xfe, 0x12, 0x83, 0xbf, 0x44, 0xc2, 0xe6, 0x0b, 0x7d, 0x7f, - 0x63, 0xa8, 0x79, 0x1a, 0x45, 0xf8, 0x5f, 0xa6, 0x68, 0xc9, 0x68, 0x06, 0x24, 0xcd, 0x81, 0xec, 0xad, 0x2c, 0xee, - 0x27, 0xbc, 0x28, 0x6e, 0x96, 0x8b, 0x85, 0x2c, 0x35, 0xd6, 0x82, 0xac, 0xb4, 0xac, 0xe1, 0x03, 0x2b, 0xba, 0x52, - 0xb7, 0x5c, 0x67, 0xb3, 0x58, 0xa3, 0x55, 0x46, 0x15, 0x3b, 0x78, 0x22, 0x65, 0xc1, 0xa8, 0x48, 0x39, 0xe1, 0x03, - 0x4d, 0x53, 0xb1, 0x2c, 0x8a, 0xfe, 0xb8, 0x64, 0xf4, 0x73, 0xdf, 0x64, 0xdb, 0xc3, 0x21, 0x35, 0xbf, 0x1f, 0x97, - 0x25, 0xbd, 0x87, 0x82, 0x84, 0x40, 0xb1, 0x01, 0x4f, 0xbf, 0xbf, 0x79, 0xf3, 0x3a, 0xb1, 0x7b, 0x85, 0x4f, 0xee, - 0x63, 0x5e, 0xed, 0x3f, 0xbe, 0xc1, 0x93, 0x52, 0xce, 0xb7, 0xba, 0xb6, 0xa0, 0xe3, 0xfd, 0xaf, 0x0c, 0x81, 0x11, - 0x7e, 0x68, 0x9b, 0x0e, 0x47, 0xf0, 0xda, 0x60, 0x3e, 0x64, 0x12, 0xd7, 0x2f, 0xfc, 0x93, 0xda, 0xe4, 0x98, 0xa3, - 0x6f, 0x8f, 0x56, 0x97, 0xf7, 0x2b, 0x46, 0xcc, 0x38, 0x17, 0x70, 0x30, 0xc2, 0x18, 0x33, 0xaa, 0xb3, 0xd9, 0x8a, - 0x99, 0xc6, 0x36, 0x7e, 0xc4, 0x6c, 0xb3, 0xc1, 0x7f, 0x4b, 0x8f, 0xf5, 0xfa, 0x90, 0x10, 0x6e, 0xe8, 0x15, 0xd1, - 0xeb, 0x35, 0x27, 0x84, 0x23, 0xfc, 0x8e, 0x93, 0x15, 0xf5, 0x13, 0x82, 0x93, 0x0d, 0xb6, 0x67, 0x6a, 0xa9, 0x0c, - 0x9c, 0x80, 0x5f, 0x58, 0xa9, 0x59, 0x99, 0x6a, 0x81, 0x4b, 0x36, 0x29, 0x60, 0x1c, 0x87, 0x5d, 0x3c, 0xa3, 0xea, - 0xe9, 0x8c, 0x8a, 0x29, 0xcb, 0xd3, 0xbf, 0xe5, 0x06, 0x33, 0x41, 0xa2, 0x09, 0x17, 0xb4, 0xe0, 0x7f, 0xb3, 0x3c, - 0x72, 0xe7, 0xc2, 0x47, 0x7d, 0xc0, 0xee, 0x34, 0x13, 0xb9, 0x3a, 0x78, 0xf9, 0xfe, 0xa7, 0x1f, 0xdd, 0x62, 0x36, - 0xce, 0x0a, 0xb4, 0x52, 0xcb, 0x05, 0x2b, 0x63, 0x84, 0xdd, 0x59, 0xf1, 0x9c, 0x1b, 0x3a, 0xf9, 0x13, 0x5d, 0xd8, - 0x14, 0xae, 0x3e, 0x2c, 0x72, 0xaa, 0xd9, 0x5b, 0x26, 0x72, 0x2e, 0xa6, 0xe4, 0xb0, 0x6b, 0xd3, 0x67, 0xd4, 0x65, - 0xe4, 0x55, 0xd2, 0xa7, 0x07, 0xcf, 0x0b, 0x33, 0xf7, 0xea, 0x73, 0x19, 0xa3, 0x8d, 0xd2, 0x54, 0xf3, 0xec, 0x80, - 0xe6, 0xf9, 0x2b, 0xc1, 0x35, 0x37, 0x23, 0x2c, 0x61, 0x89, 0x00, 0x57, 0x99, 0x3d, 0x35, 0xfc, 0xc8, 0x63, 0x84, - 0xe3, 0xd8, 0x9d, 0x05, 0x33, 0xe4, 0xd6, 0xec, 0xe8, 0xa8, 0xa6, 0xfc, 0x03, 0x96, 0xda, 0x4c, 0x32, 0x1c, 0xa1, - 0x64, 0xb1, 0x54, 0xb0, 0xd8, 0xbe, 0x0b, 0x38, 0x68, 0xe4, 0x58, 0xb1, 0xf2, 0x0b, 0xcb, 0x2b, 0x04, 0x51, 0x31, - 0x5a, 0x6d, 0xf5, 0xe1, 0xb6, 0x87, 0x26, 0xc3, 0x51, 0x3f, 0x24, 0xe1, 0xcc, 0x21, 0xbb, 0xe5, 0x54, 0x38, 0x53, - 0x15, 0x51, 0x89, 0xe1, 0x40, 0xad, 0x08, 0x8b, 0x22, 0x7e, 0x7e, 0x8b, 0x58, 0x00, 0x0f, 0x11, 0x52, 0x0e, 0x7f, - 0xe6, 0x3e, 0xff, 0x62, 0x0e, 0x0f, 0x85, 0x05, 0xc2, 0xda, 0x8e, 0x54, 0x21, 0xb4, 0x41, 0x58, 0xfb, 0xe1, 0x5a, - 0xa2, 0xe4, 0xf9, 0x22, 0x38, 0xb5, 0xc9, 0x3b, 0x6e, 0x8e, 0x6d, 0xa0, 0x6d, 0x54, 0xb3, 0xa3, 0xa3, 0x98, 0x25, - 0x15, 0x62, 0x90, 0xc3, 0xae, 0x5b, 0xa4, 0x00, 0x5a, 0x5f, 0x19, 0x37, 0xf4, 0x6c, 0x18, 0x9c, 0x43, 0x96, 0x08, - 0xf9, 0x38, 0xcb, 0x98, 0x52, 0xb2, 0x3c, 0x3a, 0x3a, 0x34, 0xe5, 0x2b, 0xce, 0x02, 0x16, 0xf1, 0xcd, 0xad, 0xa8, - 0x87, 0x80, 0xea, 0xd3, 0xd6, 0xf3, 0x4d, 0xa4, 0xe6, 0x9b, 0x3c, 0x13, 0x92, 0x46, 0x9f, 0x3e, 0x45, 0x2d, 0x8d, - 0x1d, 0x1c, 0xa6, 0xcc, 0x77, 0x7d, 0xff, 0x8c, 0x59, 0xb6, 0xd0, 0x30, 0x21, 0x3b, 0xa0, 0xd9, 0xcb, 0x0f, 0xc6, - 0xcd, 0x21, 0x61, 0x8d, 0x15, 0xda, 0x04, 0x2b, 0xba, 0xb7, 0x69, 0xc3, 0xdf, 0xd8, 0xa5, 0x5b, 0x4d, 0x0d, 0x4f, - 0x11, 0xac, 0xe3, 0x90, 0x8d, 0x36, 0xd8, 0xc0, 0xde, 0xcf, 0x46, 0x9a, 0x81, 0x0e, 0xf5, 0xa8, 0xef, 0xf2, 0x89, - 0xb2, 0x90, 0x2b, 0xd9, 0x5f, 0x4b, 0xa6, 0xb4, 0x45, 0xe4, 0x58, 0x63, 0x89, 0xe1, 0x8c, 0xda, 0x66, 0x3a, 0x1b, - 0x2c, 0xe9, 0xbe, 0xb1, 0xbd, 0x59, 0xc0, 0xd9, 0xa8, 0x00, 0xa9, 0xbf, 0x8d, 0x4f, 0x30, 0x56, 0x8d, 0xd6, 0xeb, - 0x77, 0xdc, 0xb7, 0x52, 0xaf, 0x65, 0xc5, 0xaf, 0x6d, 0x2d, 0x0a, 0x13, 0xc8, 0x1d, 0xce, 0x87, 0x5d, 0x37, 0x7e, - 0x31, 0x22, 0x87, 0x9d, 0x0a, 0x8b, 0x1d, 0x58, 0xed, 0x78, 0x2c, 0x14, 0xdf, 0xd8, 0xa6, 0x90, 0x39, 0xeb, 0x1b, - 0xf8, 0x92, 0xcc, 0x76, 0x70, 0x75, 0x46, 0x86, 0xc0, 0x75, 0x24, 0xb3, 0xd1, 0xd7, 0xf0, 0xc9, 0x53, 0x84, 0x58, - 0xef, 0xe6, 0xd5, 0x84, 0xe3, 0x4b, 0x93, 0x70, 0x6c, 0x4d, 0x23, 0x5a, 0x54, 0x55, 0xa2, 0x0a, 0xcd, 0xdc, 0x56, - 0xaf, 0xb3, 0xb0, 0x30, 0x83, 0xa9, 0xa7, 0x14, 0x34, 0xf1, 0x9a, 0xce, 0x99, 0x8a, 0x19, 0xc2, 0x5f, 0x2b, 0x60, - 0xf1, 0x13, 0x8a, 0x8c, 0x82, 0x33, 0x54, 0xc1, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, 0xcd, 0x2d, 0xa7, 0x30, 0x1b, - 0xaa, 0x51, 0xcd, 0xdb, 0x05, 0x93, 0x37, 0x87, 0xb3, 0x43, 0x70, 0x0f, 0x3f, 0x9b, 0x66, 0x81, 0x66, 0x58, 0x08, - 0x85, 0xf0, 0x61, 0x67, 0x7b, 0x25, 0x7d, 0xa9, 0x7a, 0x8e, 0xc3, 0x11, 0xac, 0x83, 0x39, 0x36, 0x12, 0xae, 0xcc, - 0xdf, 0xc6, 0x56, 0x03, 0xb0, 0xdd, 0x00, 0x66, 0x24, 0x93, 0x82, 0xea, 0xb8, 0x7b, 0xd2, 0x01, 0xc6, 0xf4, 0x0b, - 0x83, 0x53, 0x05, 0xa1, 0xdd, 0xa9, 0xb0, 0x64, 0x29, 0xd4, 0x8c, 0x4f, 0x74, 0xfc, 0xab, 0x30, 0x44, 0x85, 0x15, - 0x8a, 0x81, 0x84, 0x13, 0xb0, 0xc7, 0x86, 0xe0, 0xfc, 0x2a, 0xa0, 0x9f, 0x7e, 0x75, 0x10, 0xb9, 0x91, 0x1a, 0xc2, - 0x05, 0xe4, 0xa1, 0x66, 0xad, 0x6b, 0x32, 0x53, 0x31, 0x6e, 0xc0, 0x3d, 0x76, 0x07, 0xb6, 0xc5, 0xd4, 0x51, 0x03, - 0x11, 0x70, 0xb0, 0x22, 0x0d, 0x49, 0x84, 0x4b, 0xd4, 0x89, 0x96, 0x3f, 0xca, 0x5b, 0x56, 0x3e, 0xa5, 0x30, 0xf8, - 0xd4, 0x56, 0xdf, 0xd8, 0xa3, 0xc0, 0x50, 0x7c, 0xdd, 0xf7, 0xf8, 0xf2, 0xc9, 0x4c, 0xfc, 0x6d, 0x29, 0xe7, 0x5c, - 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x15, 0x7e, 0x3d, 0xfe, 0xb1, 0x89, - 0x5f, 0x9f, 0x1e, 0x3c, 0x9f, 0x7a, 0x0a, 0xd8, 0xdc, 0xc7, 0x08, 0xc7, 0x4e, 0xbc, 0x08, 0x4e, 0xba, 0x64, 0x86, - 0xdc, 0x31, 0xbf, 0x5e, 0xeb, 0x40, 0x8c, 0x6b, 0x70, 0x8e, 0xcc, 0x6e, 0x1b, 0xb4, 0xa1, 0x79, 0x0e, 0x2c, 0x5e, - 0x29, 0x8b, 0x22, 0x38, 0xac, 0xb0, 0xe8, 0x57, 0xc7, 0xd3, 0xa7, 0x07, 0xcf, 0x6f, 0xbe, 0x75, 0x42, 0x41, 0x7e, - 0x78, 0x48, 0xf9, 0x81, 0x8a, 0x9c, 0x95, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xa7, 0x52, 0x08, 0x96, 0x69, - 0x96, 0x83, 0xd0, 0x22, 0x88, 0x4e, 0x66, 0x52, 0xe9, 0x2a, 0xb1, 0x1e, 0xbd, 0x08, 0x85, 0xd0, 0x24, 0xa3, 0x45, - 0x11, 0x5b, 0x01, 0x65, 0x2e, 0xbf, 0xb0, 0x3d, 0xa3, 0xee, 0x37, 0x86, 0x5c, 0x35, 0xc3, 0x82, 0x66, 0x58, 0xa2, - 0x16, 0x05, 0xcf, 0x58, 0x75, 0x78, 0xdd, 0x24, 0x5c, 0xe4, 0xec, 0x0e, 0xe8, 0x08, 0xba, 0xbe, 0xbe, 0xee, 0xe0, - 0x2e, 0xda, 0x58, 0x80, 0xaf, 0x76, 0x00, 0xfb, 0x8d, 0x63, 0xd3, 0x0a, 0xe2, 0xab, 0xbd, 0x64, 0x0d, 0x05, 0x67, - 0x25, 0xf7, 0x82, 0x96, 0x25, 0xcf, 0x08, 0xe7, 0xac, 0x60, 0x9a, 0x79, 0x72, 0x0e, 0xcc, 0xb4, 0xdd, 0xba, 0xef, - 0x2a, 0xf8, 0x55, 0xe8, 0xe4, 0x77, 0x99, 0x5f, 0x73, 0x55, 0x89, 0xee, 0xf5, 0xf2, 0xd4, 0xd0, 0x1e, 0x68, 0xbb, - 0x3c, 0x54, 0x6b, 0x9a, 0xcd, 0xac, 0xc4, 0x1e, 0xef, 0x4c, 0xa9, 0x6e, 0xc3, 0x91, 0xf6, 0x6a, 0x13, 0x7d, 0x5f, - 0xba, 0x61, 0xee, 0x03, 0xc1, 0x8d, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x4f, 0x69, 0x51, 0x8c, 0x69, 0xf6, - 0xb9, 0x89, 0xfd, 0x35, 0x1a, 0x90, 0x6d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, 0xd2, 0x8d, 0x8d, - 0x12, 0x1f, 0x76, 0x6a, 0xb4, 0x6f, 0x2e, 0xf4, 0x57, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, 0x40, 0x05, 0xfe, - 0x2d, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xcd, 0xd6, 0x40, 0x34, 0x5a, 0x6d, 0x72, 0xae, 0xbe, 0x0e, - 0x81, 0xff, 0x57, 0x46, 0xf9, 0x2c, 0xe8, 0xe1, 0x3f, 0x1d, 0x68, 0x45, 0xe3, 0x1c, 0xe3, 0x5c, 0x8d, 0xcc, 0x31, - 0x14, 0x9e, 0xd0, 0xfc, 0x00, 0xcc, 0x8b, 0xc1, 0xf7, 0x37, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, 0xd5, 0x0f, 0x19, - 0x8a, 0x06, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x1b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, 0xee, 0x68, 0x6e, - 0x49, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9e, 0x85, 0xda, 0x99, 0x85, 0x4a, 0x02, 0x69, 0x0b, 0xd5, - 0xc8, 0x1c, 0x54, 0x4f, 0xb5, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x22, 0xb8, 0x05, 0xd1, 0xb8, - 0x74, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x75, 0x15, 0x89, 0xec, 0xe6, 0x68, 0xc8, 0xbe, 0x12, 0x97, 0x68, 0x8b, - 0xbf, 0xdf, 0x6c, 0x1c, 0x94, 0x18, 0x72, 0xab, 0xd3, 0x60, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, 0x33, 0x6c, 0x59, - 0x9f, 0x6d, 0xe0, 0x54, 0xed, 0x1e, 0x12, 0x22, 0x6b, 0xd8, 0x34, 0x98, 0x4a, 0xcf, 0x5d, 0x49, 0x84, 0xa9, 0x67, - 0x4b, 0xcb, 0x7a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0x0d, 0x56, 0x0d, 0xe1, 0x30, 0x0d, 0x8a, 0x6d, 0x52, 0x20, - 0xaa, 0xe5, 0x3e, 0x78, 0xef, 0xc3, 0x9a, 0x46, 0x3b, 0x01, 0xc4, 0xcb, 0x06, 0xc4, 0x03, 0xd0, 0x4a, 0x4b, 0xbc, - 0xe4, 0x88, 0xd0, 0x66, 0xe5, 0x98, 0xe1, 0xd2, 0x2e, 0xc4, 0x0e, 0x14, 0xb7, 0xd9, 0x4f, 0x83, 0x85, 0x20, 0xcb, - 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xf5, 0x7a, 0x07, 0xed, 0xf6, 0x72, 0xa1, 0x28, 0xa9, 0xa5, - 0xc3, 0xf5, 0xfa, 0x6f, 0x89, 0x62, 0xc7, 0xff, 0x62, 0x86, 0x06, 0x9e, 0xe8, 0x3e, 0xfe, 0x11, 0x4a, 0x19, 0x76, - 0xb4, 0x4e, 0xa9, 0x04, 0x87, 0x26, 0xd6, 0x36, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xe9, 0x0e, 0x01, 0x33, 0x89, 0xee, - 0xa4, 0xae, 0xa7, 0xfc, 0xd4, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xe1, 0x3e, 0xf9, 0xf2, 0xe8, 0x48, - 0x05, 0x0d, 0x7d, 0xaa, 0x28, 0xc5, 0x9f, 0x31, 0x9c, 0xca, 0xea, 0x5e, 0x18, 0xf6, 0xe5, 0x4f, 0x7f, 0x0e, 0xed, - 0x48, 0xa7, 0x9d, 0x3e, 0x08, 0xe6, 0xf4, 0x96, 0x72, 0x7d, 0x50, 0xb5, 0x62, 0x05, 0xf3, 0x98, 0xa1, 0x95, 0xe3, - 0x36, 0x92, 0x92, 0x01, 0xff, 0x08, 0x64, 0xc1, 0x73, 0xd1, 0x16, 0xf1, 0xb3, 0x19, 0x03, 0x55, 0xb6, 0x67, 0x24, - 0x2a, 0xf1, 0xf0, 0xd0, 0x1d, 0x24, 0xae, 0xe1, 0xfd, 0x63, 0xdf, 0x6c, 0x57, 0x6f, 0x48, 0x03, 0x0b, 0x56, 0x4e, - 0x64, 0x39, 0xf7, 0x79, 0x9b, 0xad, 0x6f, 0x47, 0x1c, 0xf9, 0x24, 0xde, 0xdb, 0xb6, 0x13, 0x01, 0xfa, 0x5b, 0xb2, - 0x77, 0x2d, 0xb5, 0x37, 0x4e, 0xd3, 0xea, 0x00, 0xb6, 0x0a, 0x42, 0x8f, 0x99, 0x2a, 0x94, 0xf2, 0x9d, 0x7a, 0xb5, - 0x6f, 0x75, 0x27, 0x87, 0xdd, 0x7e, 0x25, 0xf9, 0x79, 0x6c, 0xe8, 0x5b, 0x1d, 0x87, 0x3b, 0x55, 0xe5, 0xb2, 0xc8, - 0xdd, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x2d, 0x2f, 0x8a, 0x3a, 0xf5, 0x7f, 0x42, 0xda, 0x95, 0x23, 0xed, 0xd2, - 0x93, 0x76, 0x20, 0x15, 0x40, 0xda, 0x6d, 0x73, 0x75, 0x75, 0xb9, 0xb3, 0x3d, 0xa5, 0x25, 0xea, 0xca, 0x88, 0xd3, - 0xd0, 0xdf, 0xd2, 0x8f, 0x00, 0x55, 0xcc, 0xd7, 0xe7, 0xd8, 0xe9, 0x63, 0x40, 0x0c, 0xb4, 0x3a, 0x4d, 0x16, 0x6a, - 0x2a, 0x3e, 0xc7, 0x08, 0xab, 0x0d, 0xab, 0x30, 0xfb, 0xf1, 0x73, 0x50, 0xda, 0x05, 0xd3, 0x81, 0x73, 0xcc, 0x24, - 0xff, 0x8f, 0xf8, 0x28, 0x3f, 0x3b, 0xe1, 0x66, 0xa7, 0xfc, 0xec, 0x80, 0xd6, 0xd7, 0xb3, 0xcb, 0xbf, 0x4d, 0xed, - 0xcd, 0xf4, 0x44, 0x35, 0xbd, 0x7a, 0xbd, 0xd7, 0xeb, 0x78, 0x2b, 0x05, 0x34, 0xfa, 0x4e, 0x4a, 0x29, 0xab, 0xd6, - 0x81, 0x06, 0x84, 0x90, 0x81, 0x84, 0x8d, 0x9d, 0x74, 0x75, 0xca, 0xfd, 0xf8, 0xef, 0xf4, 0x3c, 0x46, 0x71, 0x6f, - 0xeb, 0x3f, 0x95, 0xf3, 0x05, 0x30, 0x64, 0x5b, 0x28, 0x3d, 0x65, 0xae, 0xc3, 0x3a, 0x7f, 0xb3, 0x27, 0xad, 0x51, - 0xc7, 0xec, 0xc7, 0x06, 0x36, 0x55, 0x52, 0xf3, 0x61, 0x67, 0xb3, 0xac, 0x92, 0x2a, 0xc2, 0xb1, 0x4f, 0xb7, 0xf2, - 0x74, 0x5b, 0x33, 0xe3, 0x33, 0xde, 0xc4, 0xc2, 0xd2, 0x61, 0x01, 0xb4, 0x2e, 0x20, 0x3f, 0x1e, 0xdd, 0xc3, 0xf5, - 0xdf, 0xd4, 0xc0, 0x59, 0x6d, 0xb6, 0xc0, 0xb7, 0xda, 0x6c, 0x3e, 0x6a, 0x27, 0x69, 0xe3, 0x8f, 0x7b, 0xe4, 0xde, - 0x0a, 0x7a, 0x75, 0xa6, 0x93, 0x19, 0x87, 0x23, 0x48, 0xdb, 0x61, 0x21, 0xc9, 0x6a, 0x2e, 0x73, 0x96, 0x46, 0x72, - 0xc1, 0x44, 0xb4, 0x01, 0x3d, 0xab, 0x43, 0x80, 0x7f, 0x89, 0x78, 0xf5, 0xae, 0xa9, 0x6f, 0x4d, 0x3f, 0xea, 0x0d, - 0xa8, 0xc2, 0x7e, 0xe4, 0x7b, 0x94, 0xb1, 0x1f, 0x59, 0xa9, 0x0c, 0x4f, 0x5a, 0xb1, 0xb7, 0x3f, 0xf2, 0xfa, 0x80, - 0xfa, 0x91, 0xa7, 0x5f, 0xaf, 0x52, 0x0b, 0x24, 0x51, 0x37, 0xb9, 0x48, 0x4e, 0x23, 0x64, 0x34, 0xc6, 0x2f, 0xbc, - 0xc6, 0x78, 0x59, 0x69, 0x8c, 0x5f, 0x6a, 0xb2, 0xdc, 0xd2, 0x18, 0xff, 0x20, 0xc8, 0x4b, 0x3d, 0x78, 0xe9, 0xb5, - 0xe9, 0x6f, 0x65, 0xc1, 0xb3, 0xfb, 0x38, 0x2a, 0xb8, 0x6e, 0xc3, 0x6d, 0x62, 0x84, 0x57, 0x36, 0x03, 0x54, 0x8d, - 0x46, 0xdf, 0xbd, 0xf1, 0xf2, 0x1f, 0x16, 0x82, 0x44, 0x0f, 0x0a, 0xae, 0x1f, 0x44, 0x78, 0xa6, 0xc9, 0x1f, 0xf0, - 0xeb, 0xc1, 0x2a, 0xfe, 0x89, 0xea, 0x59, 0x52, 0x52, 0x91, 0xcb, 0x79, 0x8c, 0x5a, 0x51, 0x84, 0x12, 0x65, 0x84, - 0x90, 0x47, 0x68, 0xf3, 0xe0, 0x0f, 0xfc, 0xa7, 0x24, 0xd1, 0x20, 0x6a, 0xcd, 0x34, 0x66, 0x94, 0xfc, 0x71, 0xf5, - 0x60, 0xf5, 0xa7, 0xdc, 0x5c, 0xff, 0x81, 0x9f, 0xeb, 0x4a, 0xad, 0x8f, 0xef, 0x18, 0x89, 0x11, 0xb9, 0x7e, 0xee, - 0x87, 0xf4, 0x54, 0xce, 0xad, 0x82, 0x3f, 0x42, 0xf8, 0x0b, 0xe8, 0x75, 0xaf, 0x79, 0x4d, 0x84, 0xdc, 0x1d, 0xcc, - 0x21, 0x89, 0xa4, 0x51, 0x1e, 0x44, 0x47, 0x47, 0x41, 0x5a, 0xc5, 0x42, 0xe0, 0x27, 0x92, 0x34, 0x44, 0x75, 0xcc, - 0x29, 0xb4, 0xf4, 0x44, 0xc6, 0x1c, 0xf9, 0x66, 0x62, 0xaf, 0xa9, 0x76, 0x3b, 0x96, 0x0f, 0xad, 0xee, 0x21, 0xe1, - 0x9a, 0x95, 0x54, 0xcb, 0x72, 0x84, 0x42, 0xb6, 0x04, 0xbf, 0xe6, 0xe4, 0x8f, 0xe1, 0xc1, 0xff, 0xf1, 0x7f, 0xfe, - 0x3e, 0xf9, 0xbd, 0x1c, 0xfd, 0x81, 0x05, 0x23, 0x27, 0x57, 0xf1, 0x20, 0x8d, 0x0f, 0xdb, 0xed, 0xf5, 0xef, 0x27, - 0xc3, 0xff, 0xa6, 0xed, 0xbf, 0x1f, 0xb7, 0x7f, 0x1b, 0xa1, 0x75, 0xfc, 0xfb, 0xc9, 0x60, 0xe8, 0xbe, 0x86, 0xff, - 0x7d, 0xfd, 0xbb, 0x1a, 0x1d, 0xdb, 0xc4, 0x07, 0x08, 0x9d, 0x4c, 0xf1, 0x3f, 0x05, 0x39, 0x69, 0xb7, 0xaf, 0x4f, - 0xa6, 0xf8, 0x67, 0x41, 0x4e, 0xe0, 0xef, 0xbd, 0x26, 0xef, 0xd8, 0xf4, 0xf9, 0xdd, 0x22, 0xfe, 0xe3, 0x7a, 0xfd, - 0x60, 0xf5, 0x9a, 0x6f, 0xa0, 0xdd, 0xe1, 0x7f, 0xff, 0xfe, 0xbb, 0x8a, 0xfe, 0x71, 0x4d, 0x4e, 0x46, 0x2d, 0x14, - 0x9b, 0xe4, 0x63, 0x62, 0xff, 0xc4, 0x83, 0x74, 0xf8, 0xdf, 0x6e, 0x28, 0xd1, 0x3f, 0x7e, 0xff, 0xe3, 0xea, 0x9a, - 0x8c, 0xd6, 0x71, 0xb4, 0xfe, 0x07, 0x5a, 0x23, 0xb4, 0x7e, 0x80, 0xfe, 0xc0, 0xd1, 0x34, 0x42, 0xf8, 0x37, 0x41, - 0x4e, 0xfe, 0x71, 0x32, 0xc5, 0xdf, 0x0b, 0x72, 0x12, 0x9d, 0x4c, 0xf1, 0x47, 0x49, 0x4e, 0xfe, 0x3b, 0x1e, 0xa4, - 0x56, 0x09, 0xb7, 0x36, 0xea, 0x8f, 0x35, 0xdc, 0x84, 0xd0, 0x92, 0xd1, 0xb5, 0xe6, 0xba, 0x60, 0xe8, 0xc1, 0x09, - 0xc7, 0x2f, 0x25, 0x00, 0x2b, 0xd6, 0xa0, 0xa4, 0x31, 0x97, 0xb0, 0xab, 0x4f, 0xb0, 0xf0, 0x80, 0x41, 0x0f, 0x52, - 0x8e, 0xad, 0x9e, 0x40, 0xa5, 0xda, 0xde, 0xde, 0x2a, 0xb8, 0xbe, 0xc5, 0x37, 0xe4, 0xa5, 0x8c, 0xbb, 0x08, 0x0b, - 0x0a, 0x3f, 0x7a, 0x08, 0x7f, 0xd0, 0xee, 0xc2, 0x13, 0xb6, 0xb9, 0xc5, 0x30, 0x21, 0x2d, 0x3f, 0x13, 0x21, 0xfc, - 0x7c, 0x4f, 0xa6, 0x9e, 0x81, 0xfa, 0x01, 0x61, 0xad, 0xc2, 0xeb, 0x51, 0xfc, 0x54, 0x93, 0x0a, 0x39, 0xde, 0x97, - 0x8c, 0xfd, 0x42, 0x8b, 0xcf, 0xac, 0x8c, 0x9f, 0x6b, 0xdc, 0xed, 0x3d, 0xc2, 0x46, 0x55, 0x7d, 0xd8, 0x45, 0xfd, - 0xea, 0x76, 0xeb, 0x83, 0xb4, 0xf7, 0x09, 0x70, 0x0a, 0x37, 0xf5, 0x35, 0xb0, 0xf6, 0x87, 0x7c, 0x47, 0xa9, 0x55, - 0xd2, 0xdb, 0x08, 0x35, 0xaf, 0x52, 0xb9, 0xf8, 0x42, 0x0b, 0x9e, 0x1f, 0x68, 0x36, 0x5f, 0x14, 0x54, 0xb3, 0x03, - 0x37, 0xe7, 0x03, 0x0a, 0x0d, 0x45, 0x15, 0x4f, 0xf1, 0x83, 0xa8, 0x37, 0xed, 0x0f, 0x22, 0xa9, 0xf7, 0x4e, 0x0c, - 0xf7, 0x59, 0x8e, 0x2f, 0x51, 0xb4, 0xba, 0x2e, 0xdb, 0xbe, 0x11, 0x6c, 0x77, 0x41, 0x59, 0x36, 0x32, 0xe7, 0xb7, - 0xc2, 0x70, 0xbf, 0x49, 0x48, 0x6f, 0x10, 0x5d, 0xa9, 0x2f, 0xd3, 0xeb, 0x08, 0x6e, 0x72, 0x4a, 0x22, 0x98, 0x51, - 0x1e, 0x41, 0x09, 0x4a, 0x3a, 0x7d, 0x7a, 0xc5, 0xfa, 0xb4, 0xd5, 0xf2, 0x6c, 0x76, 0x46, 0xf8, 0x90, 0xda, 0xfa, - 0x05, 0x9e, 0xe1, 0x9c, 0xb4, 0xbb, 0x78, 0x49, 0x3a, 0xa6, 0x4a, 0x7f, 0x79, 0x95, 0xb9, 0x7e, 0x8e, 0x8e, 0xe2, - 0x32, 0x29, 0xa8, 0xd2, 0xaf, 0x40, 0x23, 0x40, 0x96, 0x78, 0x46, 0xca, 0x84, 0xdd, 0xb1, 0x2c, 0xce, 0x10, 0x9e, - 0x39, 0x1a, 0x84, 0xfa, 0x68, 0x49, 0x82, 0x62, 0x20, 0x67, 0x10, 0xc1, 0x06, 0xb3, 0x61, 0x77, 0x44, 0x08, 0x89, - 0x0e, 0xdb, 0xed, 0x68, 0x50, 0x92, 0x7f, 0x8a, 0x14, 0x52, 0x02, 0x76, 0x9a, 0xfc, 0x0c, 0x49, 0xbd, 0x20, 0x29, - 0xfe, 0x28, 0x13, 0xcd, 0x94, 0x8e, 0x21, 0x19, 0x94, 0x04, 0xca, 0x63, 0x78, 0x74, 0x75, 0x12, 0xb5, 0x20, 0xd5, - 0xa0, 0x28, 0xc2, 0x25, 0xb9, 0xd7, 0x28, 0x9d, 0x0d, 0x4f, 0x47, 0xe1, 0x19, 0x61, 0x53, 0xa1, 0xff, 0x7b, 0x3d, - 0x98, 0x0d, 0x3b, 0xa6, 0xff, 0xeb, 0x68, 0x10, 0x97, 0x44, 0x59, 0x36, 0x6e, 0xa0, 0x52, 0xc1, 0xcc, 0x7c, 0x51, - 0xea, 0x06, 0xe8, 0xfa, 0xce, 0x49, 0xbb, 0x97, 0xc6, 0x79, 0x38, 0x93, 0x36, 0x74, 0xe8, 0x40, 0x81, 0x0b, 0x02, - 0xe5, 0x71, 0x49, 0xa0, 0xd3, 0xba, 0xda, 0xbd, 0x4e, 0x5d, 0xc2, 0x3f, 0xa2, 0x7f, 0x0c, 0xbe, 0x17, 0xe9, 0x6f, - 0xc2, 0x8e, 0xe0, 0x7b, 0xb1, 0x5e, 0xc3, 0xdf, 0xdf, 0xc4, 0x00, 0x86, 0x65, 0xd2, 0xfe, 0xe9, 0xd2, 0x7e, 0x86, - 0x34, 0xc1, 0x52, 0x33, 0x60, 0xac, 0x2a, 0x7e, 0xcc, 0x2e, 0xce, 0x84, 0xd8, 0x19, 0x1c, 0x1d, 0xf1, 0x21, 0x6d, - 0x75, 0x47, 0x70, 0x23, 0x50, 0x6a, 0xf5, 0x0b, 0xd7, 0xb3, 0x38, 0x3a, 0xb9, 0x8e, 0xd0, 0x20, 0x3a, 0x80, 0x55, - 0xee, 0xcb, 0x16, 0x71, 0xb0, 0xce, 0x5a, 0x8c, 0xa6, 0xf9, 0x35, 0xe9, 0x0c, 0x62, 0x61, 0x89, 0x7c, 0x81, 0x70, - 0xe6, 0x68, 0x6a, 0x07, 0xe7, 0xa8, 0x25, 0x44, 0xcb, 0x7f, 0xe7, 0xa8, 0x35, 0xd3, 0xad, 0x09, 0x4a, 0x33, 0xf8, - 0x1b, 0xe7, 0x84, 0x90, 0x76, 0xaf, 0xaa, 0xe8, 0x0f, 0x4b, 0x8a, 0xd2, 0x89, 0x57, 0x8f, 0x0e, 0xcd, 0xe6, 0x90, - 0xad, 0x98, 0x0f, 0xd9, 0x68, 0xbd, 0x8e, 0xae, 0x06, 0xd7, 0x11, 0x6a, 0xc5, 0x1e, 0xed, 0x4e, 0x3c, 0xde, 0x21, - 0x84, 0xc5, 0x68, 0xe3, 0x6e, 0xa0, 0x6e, 0x59, 0xe3, 0xb6, 0x69, 0x55, 0xef, 0xff, 0x80, 0x2c, 0xb0, 0x4d, 0x25, - 0xf7, 0x58, 0xfe, 0x76, 0x01, 0x53, 0xf5, 0xb8, 0x2d, 0x49, 0x07, 0x97, 0xc4, 0xab, 0xbb, 0x29, 0xd1, 0x35, 0xfe, - 0x67, 0xa4, 0x2e, 0x8e, 0x87, 0x05, 0x9e, 0x8d, 0x88, 0xa2, 0x46, 0x7e, 0xe9, 0x7b, 0x65, 0x3a, 0x2b, 0xc8, 0x2d, - 0xdb, 0xba, 0xff, 0x2d, 0xe0, 0x4e, 0xe6, 0xa9, 0x4e, 0xb2, 0x65, 0x59, 0x32, 0xa1, 0x5f, 0xcb, 0xdc, 0x31, 0x76, - 0xac, 0x00, 0xd9, 0x0a, 0x2e, 0x76, 0x31, 0x70, 0x75, 0x3d, 0xbf, 0x53, 0xf2, 0x9d, 0xec, 0x25, 0xc9, 0x2d, 0xc3, - 0x65, 0xae, 0x7b, 0xfb, 0x4b, 0x27, 0x4a, 0xc7, 0x08, 0xe7, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x99, 0x64, 0x90, - 0x0d, 0x1d, 0x28, 0xb4, 0x31, 0xfb, 0x2a, 0x56, 0xe4, 0xa9, 0x4e, 0x04, 0xbb, 0x33, 0xdd, 0xc6, 0xa8, 0x3e, 0xc4, - 0xfd, 0x7e, 0xbb, 0xa2, 0x7d, 0x43, 0x80, 0x54, 0x22, 0x64, 0xce, 0x00, 0x42, 0x70, 0xf7, 0xef, 0x92, 0x66, 0x54, - 0x85, 0x37, 0x5b, 0xf5, 0x00, 0x87, 0xa1, 0xca, 0x7b, 0x09, 0x7a, 0x62, 0xc3, 0x9e, 0x55, 0x85, 0xad, 0xf2, 0x1c, - 0x21, 0x3e, 0x89, 0x97, 0x09, 0xdc, 0x08, 0x1a, 0x4c, 0x12, 0x02, 0xad, 0xd7, 0xcb, 0x10, 0xb7, 0x66, 0xb5, 0x62, - 0x7a, 0x42, 0x66, 0xc3, 0xb2, 0xd5, 0x32, 0xca, 0xeb, 0xdc, 0xe2, 0xc5, 0x12, 0xe1, 0x49, 0xb5, 0xd7, 0x7c, 0xb9, - 0x05, 0x69, 0x76, 0x15, 0x4f, 0x9a, 0x4a, 0xe0, 0x96, 0x10, 0xc8, 0xe8, 0x17, 0x35, 0xb4, 0x8e, 0xa7, 0xe4, 0x24, - 0x1e, 0x26, 0x83, 0xff, 0x6b, 0x84, 0x06, 0x71, 0x72, 0x8c, 0x4e, 0x2c, 0x2d, 0x99, 0xa0, 0x7e, 0x66, 0xfb, 0x58, - 0x99, 0xdb, 0xcf, 0x2e, 0x36, 0x0a, 0xc8, 0x54, 0x62, 0x41, 0xe7, 0x2c, 0x9d, 0xc2, 0xae, 0xf7, 0xc8, 0xb3, 0xc0, - 0x80, 0x4c, 0xe9, 0xd4, 0xd1, 0x96, 0x24, 0x1a, 0x94, 0xb4, 0xfa, 0x1a, 0x44, 0x83, 0xac, 0xfe, 0xfa, 0xbf, 0xa2, - 0x41, 0x41, 0xd3, 0xa7, 0x7c, 0xe3, 0x94, 0xe4, 0x8d, 0x3e, 0x2e, 0x7c, 0x1f, 0x1b, 0xbb, 0x38, 0x01, 0xf0, 0x72, - 0xb4, 0xab, 0x1d, 0x59, 0xa2, 0x0d, 0x9f, 0x54, 0xd4, 0x49, 0x25, 0x9a, 0x4e, 0x01, 0xaa, 0xc1, 0x22, 0xa8, 0xd0, - 0x36, 0x20, 0x98, 0x32, 0x60, 0x8b, 0x47, 0x5a, 0x80, 0xe6, 0xf2, 0xba, 0x83, 0x56, 0x8d, 0xc2, 0x8e, 0xb3, 0x6a, - 0xde, 0xc5, 0x57, 0xc4, 0x7b, 0x02, 0x54, 0xf9, 0x6a, 0xd9, 0x9f, 0xb4, 0x5a, 0x48, 0x79, 0xfc, 0xca, 0x87, 0x93, - 0x11, 0xbe, 0x03, 0x14, 0xc2, 0x0d, 0x8c, 0xc2, 0x8d, 0x39, 0xf6, 0xdc, 0x1c, 0x5b, 0x2d, 0xb9, 0x41, 0xfd, 0xa0, - 0xf2, 0xd2, 0x55, 0xde, 0x6c, 0x2c, 0x64, 0xb6, 0x31, 0xee, 0x12, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, 0xfc, 0x29, - 0xd1, 0xde, 0x66, 0xa1, 0x51, 0xa8, 0x6e, 0x76, 0x2f, 0x50, 0x54, 0x7b, 0x7a, 0xc4, 0x00, 0x0b, 0xa8, 0x5a, 0xa9, - 0x91, 0x67, 0x1a, 0xe7, 0xad, 0xae, 0x41, 0xf7, 0x76, 0xb7, 0xdf, 0x6c, 0xec, 0x61, 0xdd, 0x18, 0xce, 0x5b, 0x64, - 0x56, 0xef, 0xf0, 0x8d, 0x6c, 0xb5, 0x36, 0xcd, 0xfb, 0x52, 0xbf, 0x89, 0x1b, 0xf7, 0x17, 0xcf, 0x77, 0x4c, 0x3c, - 0xfc, 0xe9, 0x5b, 0x9f, 0xb7, 0x22, 0xe1, 0x42, 0xb0, 0x12, 0x4e, 0x58, 0xa2, 0xb1, 0xd8, 0x6c, 0xaa, 0x53, 0xff, - 0x17, 0x6d, 0x6d, 0xc6, 0x08, 0x07, 0x3a, 0x64, 0xa4, 0x36, 0x2c, 0x71, 0x89, 0xa9, 0xa1, 0x22, 0x84, 0x90, 0x0f, - 0xda, 0x9b, 0xc7, 0x68, 0x43, 0x92, 0x32, 0x12, 0x9c, 0xdd, 0xb1, 0x22, 0x2c, 0xf9, 0xf4, 0xe0, 0xa9, 0xfc, 0xa6, - 0x48, 0x37, 0x14, 0xa3, 0xd4, 0x14, 0x2b, 0x1c, 0x21, 0x2b, 0xc8, 0x17, 0x90, 0x73, 0xaa, 0x0b, 0x96, 0xc4, 0x10, - 0xc4, 0x67, 0xbc, 0x64, 0x86, 0x71, 0x7f, 0xe0, 0xe5, 0xc6, 0xac, 0xc9, 0x69, 0x66, 0xa1, 0xf6, 0x07, 0xa0, 0x59, - 0x80, 0x72, 0x48, 0x92, 0x9d, 0x62, 0x9f, 0x1e, 0x3c, 0x7e, 0xb3, 0x4f, 0x86, 0x5e, 0xaf, 0x9d, 0xf4, 0x9c, 0x01, - 0xeb, 0x83, 0x8b, 0x7a, 0xa8, 0x99, 0xfb, 0x91, 0xc6, 0x99, 0x61, 0xa2, 0x8a, 0x98, 0x03, 0x32, 0x7d, 0x7a, 0xf0, - 0xf8, 0x7d, 0xcc, 0x8d, 0x6e, 0x0a, 0xe1, 0x70, 0xde, 0x71, 0x49, 0x62, 0x4a, 0x18, 0xb2, 0x93, 0xaf, 0xe8, 0x58, - 0x19, 0x9c, 0xee, 0x29, 0x35, 0x99, 0x20, 0x76, 0x0c, 0xc5, 0x88, 0x64, 0x0e, 0x04, 0x24, 0x43, 0x38, 0x6b, 0xc8, - 0x75, 0xc4, 0xac, 0x81, 0xe9, 0xec, 0x06, 0x16, 0x23, 0xb1, 0xec, 0x21, 0xc2, 0x99, 0xe9, 0x56, 0x6f, 0xec, 0x71, - 0x22, 0xe9, 0xb6, 0xa1, 0x5b, 0x2d, 0xcf, 0x7e, 0x04, 0xc1, 0xcb, 0x7f, 0xbc, 0x76, 0x6d, 0x57, 0x09, 0xcf, 0xbc, - 0x45, 0xda, 0xa7, 0x07, 0x8f, 0x7f, 0x72, 0x46, 0x69, 0x0b, 0xea, 0xc9, 0xff, 0x8e, 0x8c, 0xfa, 0xf8, 0xa7, 0xa4, - 0xce, 0x35, 0x85, 0x3f, 0x3d, 0x78, 0xfc, 0x61, 0x5f, 0x31, 0x48, 0xdf, 0x2c, 0x6b, 0x25, 0x81, 0x19, 0xdf, 0x8a, - 0x15, 0xe9, 0xca, 0x9d, 0x15, 0xa9, 0xd8, 0x60, 0x73, 0x42, 0xa5, 0x6a, 0x53, 0xe9, 0x56, 0x9e, 0x61, 0x49, 0xcc, - 0x55, 0x52, 0x73, 0xd9, 0x1c, 0x1a, 0x73, 0x29, 0x6e, 0x32, 0xb9, 0x60, 0x5f, 0xb9, 0x5f, 0x7a, 0xae, 0x51, 0xc2, - 0xe7, 0x60, 0x88, 0x63, 0xc6, 0x2e, 0xf0, 0x61, 0x07, 0xf5, 0xb7, 0xce, 0x33, 0x69, 0x10, 0xb5, 0x6c, 0x1e, 0x36, - 0x98, 0x92, 0x0e, 0xce, 0x48, 0x07, 0x17, 0x44, 0x0d, 0x3b, 0xf6, 0xc4, 0xe8, 0x17, 0x55, 0xd3, 0xf6, 0xdc, 0x81, - 0xed, 0x5e, 0xd8, 0x7d, 0x6b, 0x0f, 0xe5, 0x59, 0xbf, 0x30, 0xfa, 0x4b, 0x73, 0xd0, 0xcf, 0x0c, 0x6a, 0xbc, 0x62, - 0x71, 0x89, 0x4b, 0xd3, 0xf2, 0x0d, 0x1f, 0x17, 0x60, 0xa7, 0x02, 0x33, 0xc3, 0x1a, 0xa5, 0x55, 0xd9, 0xae, 0x2b, - 0x5b, 0x24, 0x66, 0xad, 0x4a, 0x5c, 0x24, 0x40, 0xca, 0x71, 0xe1, 0xec, 0x7a, 0xd4, 0x6e, 0x95, 0x8b, 0xa3, 0xa3, - 0xd8, 0x56, 0x9a, 0xd1, 0xb8, 0xf4, 0xf9, 0xf5, 0x0d, 0xe0, 0x47, 0x4b, 0x35, 0x66, 0xc8, 0x4c, 0xa0, 0xd5, 0xca, - 0x46, 0x1b, 0x7a, 0x48, 0x48, 0x5c, 0x34, 0xa1, 0xe8, 0x47, 0x6f, 0x98, 0xc1, 0x2d, 0x00, 0xb4, 0x5a, 0xd5, 0x75, - 0xef, 0x16, 0xc4, 0x9e, 0x6b, 0x2c, 0x37, 0x5f, 0xe2, 0xca, 0x9a, 0xa8, 0xb3, 0x63, 0x87, 0xe5, 0x47, 0x81, 0x44, - 0x88, 0xbb, 0xc2, 0xcf, 0x27, 0xd8, 0x1a, 0x02, 0xca, 0xbd, 0x72, 0x36, 0x10, 0xd8, 0x58, 0x6d, 0xb9, 0x42, 0x9e, - 0xb4, 0xf5, 0x50, 0xea, 0x0b, 0xc1, 0x05, 0x17, 0x14, 0x6a, 0x6d, 0x1c, 0x96, 0xbf, 0x62, 0xbb, 0xe6, 0x9c, 0x58, - 0x21, 0xa7, 0x2d, 0x33, 0xc3, 0x30, 0x00, 0xeb, 0x55, 0x80, 0x79, 0x49, 0x9e, 0x7f, 0x1d, 0xf5, 0x1f, 0x07, 0xa8, - 0xff, 0x84, 0xb0, 0x60, 0x1b, 0x58, 0x5d, 0x49, 0x22, 0x9d, 0x82, 0x42, 0xf9, 0xac, 0xa7, 0x0b, 0x02, 0xda, 0xb8, - 0x26, 0x54, 0x1b, 0x57, 0x94, 0x5f, 0xa1, 0x2c, 0xe1, 0x4e, 0x31, 0xfa, 0x4c, 0xec, 0xef, 0x93, 0xe3, 0xfa, 0x82, - 0x0e, 0xba, 0xde, 0xa7, 0x1c, 0x0c, 0x49, 0xe1, 0xe3, 0x0f, 0xdf, 0xbe, 0x5b, 0x7d, 0xba, 0xd8, 0xdd, 0xc1, 0x81, - 0x59, 0x29, 0xcc, 0x3a, 0xd8, 0xc0, 0x4d, 0x23, 0x53, 0xe8, 0xbf, 0xba, 0x13, 0x6f, 0x52, 0xa1, 0xad, 0xcd, 0xe8, - 0x8f, 0x43, 0x18, 0x6d, 0xb7, 0x6b, 0x4a, 0xb0, 0xa0, 0x59, 0xa0, 0x4b, 0xd6, 0xb8, 0x95, 0x96, 0x5f, 0x21, 0x23, - 0x8f, 0x4d, 0x01, 0x26, 0xf2, 0xfd, 0xd9, 0x4f, 0x36, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xca, 0x10, 0x42, 0x8b, 0xf7, - 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0x3d, 0x37, 0x90, 0xaa, 0x41, 0x16, 0x45, 0xb5, 0x22, 0xff, 0xe5, 0x21, 0x21, - 0xcf, 0x6b, 0x45, 0xe6, 0xbb, 0xda, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x25, 0xd8, 0xcb, 0xd0, 0x0f, - 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x73, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0xad, 0xdc, - 0x07, 0x90, 0xcb, 0xa9, 0x19, 0x24, 0x7c, 0xbf, 0x37, 0xa5, 0x7d, 0xbb, 0x9b, 0xcf, 0xdb, 0x16, 0x31, 0x5b, 0xeb, - 0x92, 0x70, 0xa1, 0x58, 0xa9, 0x9f, 0xb0, 0x89, 0x2c, 0xe1, 0xfe, 0xa3, 0x02, 0x0b, 0xda, 0x3c, 0x08, 0x74, 0x80, - 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xd6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0xd3, 0x76, 0xad, 0xe7, 0x47, 0x47, - 0x5f, 0x58, 0x0d, 0x28, 0x37, 0x4c, 0x33, 0x8c, 0x80, 0x78, 0x59, 0x2e, 0xc7, 0xdd, 0x0c, 0x3f, 0x88, 0x6b, 0x95, - 0x81, 0x27, 0x1c, 0x21, 0x11, 0x7a, 0x49, 0xf4, 0x66, 0xba, 0x4d, 0xef, 0x9d, 0x36, 0x43, 0x84, 0x62, 0x0d, 0x90, - 0x7b, 0x90, 0xcb, 0xad, 0x92, 0x49, 0xd5, 0xb6, 0xb6, 0xd5, 0x20, 0x9e, 0x02, 0xb8, 0x62, 0x23, 0xa4, 0x04, 0x68, - 0xb8, 0x5f, 0x68, 0xf9, 0x20, 0x81, 0xfd, 0xc7, 0x2a, 0x01, 0x91, 0x16, 0x35, 0x36, 0x2e, 0x42, 0xd8, 0x9a, 0xfa, - 0x04, 0xc6, 0x09, 0x8f, 0x5f, 0xee, 0xd3, 0x50, 0x7b, 0xd4, 0x66, 0xe6, 0x0c, 0x82, 0x12, 0x12, 0x55, 0x15, 0x92, - 0x2f, 0xb1, 0x70, 0xdc, 0x9c, 0xbf, 0x87, 0x03, 0x52, 0x2c, 0x69, 0x6c, 0xef, 0xb6, 0xe0, 0xf8, 0x28, 0x93, 0x65, - 0xdc, 0xe8, 0xba, 0x5f, 0x9a, 0x6a, 0xd8, 0x81, 0x8e, 0x86, 0x70, 0x2a, 0xcd, 0x3d, 0xe1, 0xd3, 0x9a, 0xa4, 0x6a, - 0x67, 0x01, 0xe5, 0x89, 0x61, 0x6d, 0x9a, 0x12, 0xcc, 0x5f, 0x3b, 0xf3, 0xb5, 0xea, 0x98, 0x60, 0x66, 0x18, 0xb7, - 0x76, 0x15, 0xd8, 0x06, 0x70, 0x6c, 0xf5, 0x44, 0x06, 0x8b, 0xea, 0x95, 0xe2, 0xa6, 0xd3, 0x80, 0x09, 0x78, 0x07, - 0xd6, 0x33, 0xdb, 0x5b, 0xff, 0xa5, 0x39, 0x18, 0x05, 0x56, 0x0d, 0x02, 0x2f, 0x0d, 0x81, 0x47, 0xc0, 0xb8, 0x79, - 0xd3, 0xf2, 0x81, 0x33, 0xa2, 0x11, 0xfe, 0xc4, 0x73, 0x78, 0x66, 0x59, 0xee, 0x9d, 0x8f, 0xad, 0x15, 0x49, 0x05, - 0x01, 0xdb, 0x22, 0xec, 0x88, 0xbc, 0x44, 0x58, 0xb5, 0x5a, 0x7d, 0x75, 0xc5, 0x6a, 0xad, 0x4a, 0x3d, 0x4c, 0x01, - 0xb7, 0xc4, 0x80, 0xf7, 0x8d, 0x13, 0x15, 0x0c, 0x09, 0xbc, 0xf5, 0xb7, 0x02, 0xf5, 0xfd, 0xe3, 0x77, 0x71, 0x48, - 0xdf, 0xc2, 0xb2, 0xd5, 0x45, 0x2c, 0x4c, 0x29, 0xae, 0xef, 0x70, 0xde, 0x7e, 0xdb, 0x6c, 0x04, 0xc6, 0x7d, 0xd8, - 0xc5, 0x60, 0xe3, 0x86, 0xfa, 0xda, 0x92, 0x86, 0x6a, 0x13, 0xf6, 0x51, 0x6d, 0xef, 0x18, 0x76, 0xd6, 0xd7, 0xb5, - 0xb4, 0xab, 0x89, 0xda, 0x6c, 0x14, 0xab, 0x8d, 0x06, 0xb6, 0x0c, 0x3b, 0xcd, 0x31, 0xb3, 0xab, 0xc0, 0x7f, 0xba, - 0x20, 0x1a, 0x07, 0xc8, 0xfa, 0xf6, 0x6b, 0xd7, 0x29, 0xf5, 0x30, 0x61, 0x7b, 0xbb, 0xf3, 0xf1, 0x29, 0xdf, 0x77, - 0x3e, 0x62, 0xe9, 0xb6, 0xbe, 0x39, 0x1b, 0xbb, 0xff, 0xc1, 0xd9, 0xe8, 0xd4, 0xf6, 0xfe, 0x78, 0x04, 0xee, 0xa4, - 0x71, 0x3c, 0x36, 0xd7, 0x94, 0x48, 0x2c, 0xdc, 0x72, 0x5c, 0xf7, 0xd6, 0x6b, 0x31, 0xec, 0x80, 0xda, 0x29, 0x8a, - 0xe0, 0x67, 0xd7, 0xfe, 0x0c, 0x48, 0xb2, 0xd5, 0x21, 0xc7, 0xa2, 0x12, 0x65, 0x50, 0x02, 0x06, 0xd4, 0xb1, 0xb1, - 0xf5, 0x32, 0x88, 0xed, 0x70, 0xc8, 0x61, 0x39, 0x11, 0xd5, 0xd5, 0x15, 0x8c, 0xd8, 0x1c, 0x1b, 0x4e, 0xc0, 0x8c, - 0xf7, 0x5a, 0x15, 0x7a, 0xf1, 0xf3, 0xdf, 0x33, 0xa7, 0x8d, 0x23, 0xc6, 0x72, 0x12, 0x0d, 0x2b, 0x06, 0x37, 0x02, - 0xc7, 0x30, 0x1e, 0x1a, 0x09, 0xb5, 0x3e, 0xd5, 0x51, 0xe3, 0x48, 0xc2, 0x1d, 0x50, 0xbb, 0x1d, 0x9a, 0x73, 0x69, - 0xbd, 0xde, 0x7b, 0xb0, 0xe0, 0x32, 0xc0, 0xed, 0x97, 0x44, 0x37, 0x48, 0x0a, 0x25, 0x4e, 0x82, 0xc2, 0x85, 0x41, - 0x55, 0x4d, 0xe4, 0xb0, 0x33, 0x02, 0x9e, 0xb4, 0x9f, 0x5d, 0xc9, 0x5a, 0x48, 0xce, 0x5a, 0x2d, 0x54, 0x54, 0x1d, - 0xd3, 0xa1, 0x68, 0x65, 0x23, 0xcc, 0x70, 0x66, 0x05, 0x16, 0x38, 0xbd, 0xe2, 0xa2, 0xee, 0x7a, 0x98, 0x8d, 0x10, - 0x2e, 0xd7, 0xeb, 0xd8, 0x0e, 0xad, 0x40, 0xeb, 0x75, 0x11, 0x0e, 0xcd, 0xe4, 0x43, 0xc5, 0xe7, 0x03, 0x4d, 0x9e, - 0x9b, 0xf3, 0xf0, 0x39, 0x0c, 0xb2, 0x45, 0xe2, 0xc2, 0xa9, 0x04, 0x0b, 0xd0, 0x5c, 0xb5, 0xe4, 0x30, 0x6b, 0x75, - 0x47, 0x01, 0x0d, 0x1b, 0x66, 0x23, 0x52, 0x6c, 0xc0, 0x72, 0x56, 0xb9, 0x03, 0xf3, 0x4f, 0x38, 0xd8, 0xfe, 0x34, - 0xe7, 0x8c, 0x6d, 0x30, 0x5c, 0x93, 0x6d, 0x95, 0x41, 0x85, 0x57, 0x6e, 0x71, 0x7d, 0xb9, 0x86, 0x81, 0x45, 0x55, - 0x08, 0xbb, 0x6b, 0xe6, 0x01, 0x08, 0xff, 0x15, 0xb6, 0x97, 0xb4, 0x32, 0xe2, 0xde, 0x42, 0x7c, 0x6f, 0xbb, 0x9d, - 0x24, 0x09, 0x2d, 0xa7, 0xe6, 0x4a, 0xc4, 0xdf, 0xf0, 0x9a, 0x3d, 0x70, 0xea, 0xc6, 0x19, 0xf4, 0x3c, 0xac, 0x3a, - 0x1b, 0x11, 0x3b, 0x7e, 0xcf, 0xec, 0x78, 0xc7, 0x15, 0x4a, 0xf7, 0xeb, 0x22, 0xec, 0x60, 0xb2, 0xff, 0xe5, 0xc1, - 0x9c, 0xb9, 0xc1, 0x58, 0x34, 0xd9, 0x82, 0xdb, 0x57, 0xe0, 0x41, 0xe9, 0x16, 0xdc, 0xbe, 0x0e, 0x5f, 0x0f, 0xad, - 0xe2, 0xab, 0x03, 0x0c, 0xc8, 0x84, 0x1d, 0x69, 0x9d, 0x10, 0x0c, 0xf3, 0x7c, 0x9b, 0x23, 0xb3, 0x64, 0x15, 0x0e, - 0x57, 0x4d, 0x62, 0xb1, 0xb5, 0x17, 0x6a, 0x26, 0x35, 0x10, 0x8c, 0x45, 0xfa, 0x1c, 0x85, 0x4a, 0x83, 0xa6, 0x71, - 0x0c, 0x60, 0x95, 0xd3, 0xd6, 0x3f, 0x3f, 0x3a, 0x02, 0xa1, 0x01, 0x58, 0xbb, 0x24, 0xa3, 0x0b, 0xbd, 0x2c, 0x81, - 0xbf, 0x52, 0xfe, 0x37, 0x24, 0x83, 0xdb, 0x89, 0x49, 0x83, 0x1f, 0x90, 0xb0, 0xa0, 0x4a, 0xf1, 0x2f, 0x36, 0xcd, - 0xfd, 0xc6, 0x25, 0xf1, 0x18, 0xad, 0x2c, 0xa7, 0x28, 0x51, 0x5f, 0x3a, 0x74, 0x6d, 0x42, 0xee, 0xf9, 0x17, 0x26, - 0xf4, 0x8f, 0x5c, 0x69, 0x26, 0x00, 0x00, 0x35, 0xe2, 0xc1, 0x94, 0x14, 0x82, 0xad, 0xdb, 0xa8, 0x45, 0xf3, 0xfc, - 0x9b, 0x55, 0x74, 0x93, 0x2d, 0x9a, 0x51, 0x91, 0x17, 0xb6, 0x93, 0xd0, 0x66, 0xd2, 0xdb, 0x89, 0x56, 0x25, 0x43, - 0x8b, 0x9d, 0x9a, 0xfd, 0x30, 0xb4, 0x3e, 0x16, 0xc4, 0x9f, 0x0b, 0xfe, 0x2c, 0xfd, 0x26, 0x1f, 0x03, 0x57, 0xea, - 0x5f, 0x59, 0x85, 0x70, 0x26, 0x58, 0x07, 0xe4, 0x35, 0x69, 0x8e, 0xd3, 0xa3, 0xce, 0x6c, 0x47, 0xb9, 0x50, 0x19, - 0x85, 0x6d, 0x9d, 0x14, 0x06, 0x53, 0x2e, 0xbe, 0x2e, 0x71, 0xfd, 0xe4, 0x8f, 0x11, 0x7f, 0x74, 0x88, 0xff, 0x94, - 0x4a, 0xa3, 0x55, 0x85, 0x60, 0xc8, 0xef, 0x48, 0xa6, 0xe0, 0x2a, 0xb6, 0xe0, 0xfa, 0xa5, 0x9e, 0x17, 0x5b, 0x9e, - 0x38, 0x7d, 0xa6, 0x2a, 0xe8, 0xa8, 0xf8, 0x96, 0xe1, 0x57, 0x0c, 0xee, 0x8d, 0x5f, 0xf0, 0xa0, 0xca, 0xee, 0x7d, - 0xf1, 0x8b, 0xe0, 0xbe, 0xf8, 0x05, 0x4f, 0x77, 0x8b, 0x06, 0xf7, 0xc4, 0xbd, 0xe4, 0x32, 0xe9, 0x44, 0x9e, 0x8f, - 0xca, 0x69, 0xed, 0x5f, 0x69, 0xb7, 0x06, 0xae, 0x6d, 0xe2, 0xc0, 0x38, 0xaf, 0x29, 0x42, 0x31, 0x67, 0xce, 0x68, - 0x39, 0xfc, 0xaf, 0xad, 0x93, 0x3b, 0x79, 0xa4, 0x95, 0x42, 0xde, 0xd2, 0x52, 0x3f, 0x80, 0x0d, 0x57, 0xee, 0xf8, - 0x00, 0x52, 0x02, 0xca, 0xb6, 0xff, 0xac, 0x8b, 0x40, 0x1c, 0x57, 0xd6, 0xf9, 0x28, 0x6c, 0x9f, 0x94, 0x15, 0x57, - 0xd7, 0x14, 0x42, 0xee, 0x8c, 0x96, 0x00, 0x61, 0xea, 0x5d, 0xf3, 0x98, 0xa3, 0xc9, 0x2c, 0x5d, 0x6d, 0x2a, 0xd5, - 0x41, 0x69, 0xb9, 0x3a, 0x8e, 0x70, 0xb9, 0x31, 0x37, 0xe8, 0x7f, 0x73, 0xfc, 0x27, 0x77, 0x34, 0xf2, 0xfb, 0x8a, - 0x02, 0x7d, 0xdc, 0xef, 0x6b, 0xb3, 0x87, 0x44, 0xda, 0x39, 0x54, 0x96, 0x02, 0x80, 0xd5, 0x06, 0x5f, 0x37, 0x1e, - 0xa7, 0x9e, 0x49, 0x37, 0x9b, 0xaf, 0x1a, 0xc2, 0x62, 0x56, 0x59, 0xf0, 0x98, 0x6e, 0xf6, 0x58, 0x8e, 0x7a, 0x59, - 0x5c, 0x57, 0x7b, 0xac, 0xd1, 0x2f, 0xfa, 0x0a, 0x28, 0x6b, 0x43, 0xb4, 0xf5, 0x3a, 0x6e, 0xc2, 0x9b, 0x88, 0xe0, - 0x1a, 0x04, 0x61, 0x11, 0x18, 0x70, 0x34, 0x18, 0x6f, 0x5b, 0x27, 0x46, 0xdb, 0xf6, 0x4b, 0x9e, 0x75, 0x6f, 0x8c, - 0x23, 0x54, 0x34, 0xd8, 0xea, 0xa1, 0xe6, 0x01, 0xdb, 0xd9, 0x55, 0x1d, 0x05, 0x10, 0xca, 0xa9, 0x37, 0xce, 0xad, - 0xad, 0x68, 0xf7, 0xc0, 0x17, 0x7d, 0xc3, 0x3c, 0xd7, 0x81, 0x6e, 0x37, 0x3f, 0xb0, 0x6d, 0x7a, 0x26, 0xbf, 0x66, - 0xdb, 0xd4, 0xe0, 0x84, 0x0f, 0x3b, 0xe8, 0xdb, 0x86, 0xb0, 0xb6, 0xaf, 0xfd, 0x45, 0xfe, 0x17, 0xba, 0xeb, 0x02, - 0x7a, 0x5a, 0x30, 0x7b, 0x1a, 0xf3, 0x41, 0x6f, 0x36, 0xdf, 0x57, 0xfe, 0x0b, 0xc6, 0x56, 0xe8, 0x7b, 0xbb, 0x0b, - 0x9c, 0x58, 0x69, 0x1c, 0x82, 0xe3, 0xbf, 0x39, 0x99, 0x16, 0x72, 0x4c, 0x8b, 0xf7, 0xd0, 0x63, 0x9d, 0xfb, 0xf2, - 0x3e, 0x2f, 0xa9, 0x66, 0x8e, 0xd6, 0xd4, 0xa3, 0xf8, 0x9b, 0x07, 0xc3, 0xf8, 0x9b, 0x5b, 0xca, 0x5d, 0xb7, 0x80, - 0x57, 0x3f, 0x56, 0x4d, 0xa4, 0xdf, 0x6f, 0x3c, 0xed, 0xe0, 0x6a, 0x7f, 0x2f, 0xdb, 0x24, 0x8d, 0x57, 0x24, 0x8d, - 0xab, 0x78, 0xbb, 0xa9, 0x38, 0xfe, 0xf3, 0x2b, 0x83, 0xdd, 0x25, 0x73, 0x7f, 0x06, 0x64, 0xee, 0x4f, 0x9e, 0x7e, - 0xb3, 0x56, 0x40, 0xf1, 0x4e, 0x93, 0x53, 0x63, 0x19, 0x63, 0x47, 0xfd, 0x4e, 0x83, 0x41, 0x83, 0x26, 0xd7, 0x81, - 0xb7, 0x43, 0x7d, 0x7a, 0x79, 0xfb, 0xa3, 0x38, 0x5b, 0x2a, 0x2d, 0xe7, 0xae, 0x51, 0xe5, 0x7c, 0x9c, 0x4c, 0x26, - 0x28, 0xb0, 0xcd, 0x1d, 0x7e, 0xda, 0x74, 0x23, 0x5b, 0x7d, 0xe6, 0x22, 0x4f, 0x15, 0x76, 0x67, 0x8b, 0x4a, 0xe5, - 0x86, 0x78, 0x33, 0xe7, 0xdd, 0x3c, 0x3c, 0xe1, 0x82, 0xab, 0x19, 0x2b, 0xe3, 0x12, 0xad, 0xbe, 0xd6, 0x59, 0x09, - 0xb7, 0x39, 0xb6, 0x33, 0xbc, 0xac, 0x2c, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xce, 0xf4, 0x4c, 0xe6, 0x60, - 0xf8, 0x92, 0xe4, 0x95, 0x3b, 0xd5, 0xd1, 0xd1, 0x61, 0x1c, 0x19, 0xfd, 0x05, 0xf8, 0xa0, 0x87, 0x39, 0x68, 0xb0, - 0x02, 0xc7, 0xa0, 0xba, 0x6b, 0x86, 0x56, 0x6c, 0xdb, 0x87, 0x46, 0x27, 0x9f, 0xd9, 0x3d, 0xe6, 0x68, 0xb3, 0x49, - 0xed, 0xa8, 0xa3, 0x09, 0x67, 0x45, 0x1e, 0xe1, 0xcf, 0xec, 0x3e, 0xad, 0xdc, 0xd6, 0x8d, 0x97, 0xb5, 0x59, 0xc4, - 0x48, 0xde, 0x8a, 0x08, 0xd7, 0x9d, 0xa4, 0xab, 0x0d, 0x96, 0x25, 0x9f, 0x02, 0x8e, 0xfe, 0xc0, 0xee, 0x53, 0xd7, - 0x5e, 0xe0, 0x2a, 0x88, 0x56, 0x1e, 0xf4, 0x49, 0x90, 0x1c, 0x2e, 0x83, 0x13, 0x38, 0x86, 0xa6, 0xee, 0x88, 0x34, - 0xca, 0xd5, 0x22, 0x24, 0x42, 0x9b, 0xff, 0x74, 0x2a, 0x78, 0x12, 0x9e, 0x73, 0xba, 0x61, 0x71, 0xbb, 0x55, 0x89, - 0x41, 0x85, 0xda, 0x82, 0xe4, 0xd7, 0x98, 0xfb, 0xdd, 0xe7, 0xbc, 0x1f, 0x02, 0x9d, 0xd9, 0x84, 0xba, 0x46, 0xd3, - 0xa5, 0xf9, 0x85, 0xea, 0x3b, 0xa8, 0xb9, 0xae, 0x2b, 0x1e, 0xfc, 0x1a, 0x03, 0xe0, 0xc1, 0x5a, 0x86, 0x1a, 0x87, - 0xd0, 0x8d, 0x37, 0x53, 0x5d, 0x50, 0x12, 0xaf, 0xfc, 0x1c, 0x52, 0x1e, 0x82, 0x51, 0x6f, 0x00, 0x0d, 0x1d, 0x82, - 0x59, 0xcb, 0x43, 0x3e, 0x89, 0xc5, 0xce, 0x19, 0x2a, 0xcd, 0x19, 0x9a, 0x04, 0x20, 0xff, 0xca, 0x99, 0xc9, 0x0c, - 0x34, 0x0c, 0x6f, 0x69, 0x0e, 0x40, 0xb7, 0xba, 0x0e, 0x87, 0xc2, 0x15, 0xad, 0x9c, 0xf7, 0xec, 0xa2, 0xcb, 0xc6, - 0xb0, 0x62, 0xd3, 0x0e, 0xda, 0xa4, 0x30, 0x25, 0x66, 0x0b, 0x6c, 0xbc, 0xde, 0x87, 0x7b, 0xbb, 0xda, 0xb8, 0x4c, - 0xfc, 0xb4, 0x88, 0x87, 0x49, 0x4c, 0xd1, 0x8a, 0xc7, 0x14, 0x4b, 0xb0, 0x83, 0x2c, 0x37, 0xd5, 0xf8, 0x59, 0xb8, - 0x1c, 0x0d, 0x2b, 0xe9, 0xfd, 0x0e, 0x86, 0xc0, 0xe5, 0x6b, 0xb0, 0x0d, 0xc5, 0xbc, 0x22, 0x2c, 0xb1, 0xf1, 0xf4, - 0x0b, 0xd6, 0x6d, 0x6a, 0x17, 0xc4, 0xaf, 0xc0, 0x82, 0xc6, 0xab, 0x60, 0x16, 0xa1, 0x53, 0xb9, 0x73, 0x38, 0x74, - 0xd7, 0x84, 0xb5, 0xf1, 0x6a, 0xac, 0xc8, 0xd6, 0xd1, 0xf3, 0x6d, 0x1b, 0xcf, 0xbf, 0x96, 0xac, 0xbc, 0xbf, 0x61, - 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5e, 0x86, 0xda, 0x40, 0x7e, 0x20, 0x0d, 0xeb, 0xb2, 0xc1, 0xdf, 0x8c, 0x8a, - 0xb1, 0x31, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x55, 0xd7, 0x4d, 0xd6, 0x37, 0xb1, 0x12, 0x6a, 0x48, - 0xbb, 0xbb, 0x05, 0x5c, 0x86, 0xfe, 0xb0, 0x43, 0x35, 0xda, 0x56, 0xdd, 0x40, 0x12, 0x5c, 0xfb, 0xc9, 0xaf, 0x4f, - 0x75, 0x9f, 0xb5, 0xee, 0xd7, 0xa7, 0xda, 0xb8, 0x2c, 0x34, 0x86, 0x44, 0xd8, 0xf5, 0x53, 0xf9, 0x4f, 0x8b, 0xcd, - 0x06, 0x6d, 0x60, 0x78, 0x4f, 0x78, 0x3f, 0x8e, 0x9f, 0x78, 0x0b, 0xc5, 0x04, 0x2e, 0x72, 0x6f, 0x0a, 0xe9, 0x09, - 0x79, 0x3d, 0x82, 0x27, 0x7c, 0x67, 0x08, 0x4f, 0x78, 0xe0, 0xf4, 0x0a, 0x52, 0xd3, 0x54, 0xb0, 0xdc, 0xd3, 0x4f, - 0x64, 0x91, 0xd0, 0xf0, 0x71, 0x6f, 0x38, 0x11, 0xfa, 0x8f, 0x14, 0xf8, 0x2f, 0x3c, 0x5e, 0x6a, 0x2d, 0x05, 0xe6, - 0x62, 0xb1, 0xd4, 0x58, 0x99, 0xd1, 0xaf, 0x26, 0x52, 0xe8, 0xf6, 0x84, 0xce, 0x79, 0x71, 0x9f, 0x2e, 0x79, 0x7b, - 0x2e, 0x85, 0x54, 0x0b, 0x9a, 0x31, 0xac, 0xee, 0x95, 0x66, 0xf3, 0xf6, 0x92, 0xe3, 0x97, 0xac, 0xf8, 0xc2, 0x34, - 0xcf, 0x28, 0x7e, 0x27, 0xc7, 0x52, 0x4b, 0xfc, 0xe6, 0xee, 0x7e, 0xca, 0x04, 0xfe, 0x30, 0x5e, 0x0a, 0xbd, 0xc4, - 0x8a, 0x0a, 0xd5, 0x56, 0xac, 0xe4, 0x93, 0x7e, 0xbb, 0xbd, 0x28, 0xf9, 0x9c, 0x96, 0xf7, 0xed, 0x4c, 0x16, 0xb2, - 0x4c, 0xff, 0xab, 0x73, 0x4a, 0x1f, 0x4d, 0xce, 0xfa, 0xba, 0xa4, 0x42, 0x71, 0x58, 0x98, 0x94, 0x16, 0xc5, 0xc1, - 0xe9, 0x79, 0x67, 0xae, 0x0e, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xf3, 0x07, 0xfe, 0x45, 0xc2, 0x28, 0x93, 0xb1, 0x16, - 0x6e, 0x90, 0xab, 0x6c, 0x59, 0x2a, 0x59, 0xa6, 0x0b, 0xc9, 0x85, 0x66, 0x65, 0x7f, 0x2c, 0xcb, 0x9c, 0x95, 0xed, - 0x92, 0xe6, 0x7c, 0xa9, 0xd2, 0xb3, 0xc5, 0x5d, 0xbf, 0xd9, 0x83, 0xcd, 0x4f, 0x85, 0x14, 0xac, 0x0f, 0xfc, 0xc6, - 0xb4, 0x94, 0x4b, 0x91, 0xbb, 0x61, 0x2c, 0x85, 0x62, 0xba, 0xbf, 0xa0, 0x39, 0xd8, 0x01, 0xa7, 0x97, 0x8b, 0xbb, - 0xbe, 0x99, 0xf5, 0x2d, 0xe3, 0xd3, 0x99, 0x4e, 0xcf, 0x3b, 0x1d, 0xfb, 0xad, 0xf8, 0xdf, 0x2c, 0xed, 0xf6, 0x92, - 0xde, 0xf9, 0xe2, 0x0e, 0x38, 0x78, 0xcd, 0xca, 0x36, 0xc0, 0x02, 0x2a, 0x75, 0x93, 0xce, 0xa3, 0xd3, 0x87, 0x90, - 0x01, 0x36, 0x0e, 0x6d, 0x33, 0x21, 0x30, 0x76, 0x4f, 0x97, 0x8b, 0x05, 0x2b, 0xc1, 0x8b, 0xbe, 0x3f, 0xa7, 0xe5, - 0x94, 0x8b, 0x76, 0x69, 0x1a, 0x6d, 0x5f, 0x2e, 0xee, 0x36, 0x30, 0x9f, 0xd4, 0x9a, 0xad, 0xba, 0x69, 0xb9, 0xaf, - 0x55, 0x30, 0x44, 0x13, 0x93, 0x26, 0x2d, 0xa7, 0x63, 0x1a, 0x77, 0x7b, 0x0f, 0xb1, 0xff, 0x5f, 0xd2, 0x43, 0x01, - 0xd8, 0xda, 0xf9, 0xb2, 0x34, 0xb7, 0xa8, 0x69, 0x57, 0xd9, 0x66, 0x67, 0xf2, 0x0b, 0x2b, 0x7d, 0xab, 0xe6, 0x63, - 0xb5, 0x33, 0xef, 0xff, 0x51, 0xa3, 0xd4, 0xb6, 0xf5, 0x4a, 0xdd, 0x00, 0x8d, 0xde, 0x6d, 0xec, 0xbf, 0x7a, 0x97, - 0xf4, 0xe1, 0xd9, 0xb9, 0x87, 0xfb, 0x64, 0x32, 0x69, 0x00, 0xdd, 0x43, 0xb7, 0xdb, 0x59, 0xdc, 0x1d, 0xf4, 0x3a, - 0x1e, 0xc6, 0x16, 0xa6, 0x17, 0x8b, 0xbb, 0x3d, 0x2b, 0x18, 0x60, 0xc5, 0x76, 0x6f, 0x07, 0xc9, 0xa9, 0x3a, 0x60, - 0x54, 0xb1, 0xcd, 0x1f, 0x78, 0x4e, 0x01, 0x37, 0x0c, 0xd2, 0x0e, 0x8d, 0x9c, 0x0a, 0x2b, 0x30, 0x5a, 0xdd, 0xf2, - 0x5c, 0xcf, 0xd2, 0x6e, 0xa7, 0xf3, 0x5d, 0x8d, 0x49, 0xfd, 0x99, 0x5d, 0xd2, 0x6e, 0xc9, 0xe6, 0x0d, 0xfc, 0x1a, - 0xd3, 0x6a, 0x17, 0xac, 0x16, 0xd2, 0x75, 0x5a, 0xb2, 0xc2, 0x44, 0xb9, 0xd9, 0xb8, 0xad, 0xb0, 0x33, 0x65, 0x2e, - 0x66, 0xac, 0xe4, 0xba, 0xdf, 0xfc, 0xaa, 0x3b, 0xde, 0x9d, 0xd3, 0xc6, 0xca, 0xc7, 0x2b, 0x5b, 0xc3, 0x5d, 0xc6, - 0x3e, 0x85, 0x8f, 0x5d, 0xac, 0xfc, 0x42, 0xcb, 0x78, 0x6b, 0xc3, 0xe0, 0xb0, 0x06, 0xda, 0x04, 0x73, 0x2e, 0xc1, - 0x54, 0x74, 0x84, 0xbf, 0x02, 0x85, 0x8c, 0x16, 0x59, 0x0c, 0x23, 0x3a, 0x68, 0x1f, 0x9c, 0x96, 0x6c, 0x8e, 0x3c, - 0x20, 0x92, 0x87, 0xe7, 0x25, 0x9b, 0x6f, 0x12, 0x53, 0x7d, 0x65, 0x50, 0x97, 0x16, 0x7c, 0x2a, 0xd2, 0x8c, 0xc1, - 0xb6, 0xda, 0x24, 0x4c, 0x68, 0xae, 0xef, 0xdb, 0xa5, 0xbc, 0x5d, 0xe5, 0x5c, 0x2d, 0x0a, 0x7a, 0x9f, 0x4e, 0x0a, - 0x76, 0xd7, 0x37, 0xa5, 0xda, 0x5c, 0xb3, 0xb9, 0x72, 0x65, 0xfb, 0x90, 0xde, 0xce, 0xad, 0x39, 0x07, 0x40, 0x4f, - 0xde, 0x6e, 0xef, 0x6b, 0xbf, 0x68, 0x6d, 0xb9, 0xd4, 0x07, 0x1d, 0xd5, 0x9f, 0x73, 0xd1, 0x76, 0x03, 0x39, 0x03, - 0x8c, 0xd8, 0x85, 0x7c, 0xd0, 0x7f, 0xc2, 0xee, 0x16, 0x54, 0xe4, 0x2c, 0x5f, 0x05, 0xd5, 0x7a, 0x50, 0x2f, 0x2c, - 0x95, 0x0a, 0x3d, 0x6b, 0x1b, 0x1b, 0xb4, 0xb8, 0x27, 0xd0, 0x57, 0x50, 0xfe, 0x51, 0x07, 0xdb, 0xff, 0x4f, 0xba, - 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xbe, 0x0d, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, 0x5a, 0x38, 0x88, - 0xcc, 0x79, 0x9e, 0x17, 0x8d, 0x11, 0x5d, 0x07, 0x9d, 0x75, 0xd1, 0x0a, 0xe6, 0x9f, 0x76, 0x0e, 0x3a, 0x07, 0x66, - 0x2e, 0x6e, 0x1b, 0x9c, 0x9d, 0x3d, 0x3c, 0x7d, 0xc4, 0xfa, 0x05, 0x17, 0xac, 0x31, 0xd5, 0x6f, 0x82, 0x3a, 0x6c, - 0xb8, 0xe7, 0x1a, 0xee, 0x1e, 0x74, 0x0f, 0xce, 0x3a, 0xdf, 0x79, 0x2a, 0x52, 0xb0, 0x89, 0xb6, 0xfb, 0xa6, 0x41, - 0x56, 0x2e, 0x7d, 0xd3, 0xb7, 0x25, 0x5d, 0xa4, 0x42, 0xc2, 0x9f, 0x3e, 0x6c, 0xfe, 0x49, 0x21, 0x6f, 0xd3, 0x19, - 0xcf, 0x73, 0x26, 0x6c, 0x81, 0x2a, 0x91, 0x15, 0x05, 0x5f, 0x28, 0x6e, 0x57, 0xc3, 0xe1, 0xee, 0xf9, 0x16, 0x54, - 0xc3, 0x01, 0x9d, 0x06, 0x03, 0x3a, 0xaf, 0x07, 0x54, 0xf7, 0x1f, 0x8e, 0xb0, 0xb7, 0x35, 0x57, 0x53, 0xaa, 0xdf, - 0xc0, 0xa4, 0x3f, 0x97, 0x4a, 0x03, 0xcc, 0xbd, 0xf1, 0x88, 0x39, 0x5d, 0xda, 0x63, 0xa6, 0x6f, 0x19, 0x13, 0x5f, - 0x1f, 0xc4, 0x75, 0x2a, 0x45, 0x71, 0x6f, 0x3f, 0x57, 0x61, 0x97, 0x74, 0xa9, 0xe5, 0x26, 0x19, 0x73, 0x41, 0xcb, - 0xfb, 0x4f, 0x8a, 0x09, 0x25, 0xcb, 0x4f, 0x72, 0x32, 0x59, 0x7d, 0x8d, 0xe4, 0x3d, 0x44, 0x9b, 0x44, 0x71, 0x31, - 0x2d, 0x98, 0x25, 0x70, 0x06, 0x11, 0xdc, 0x21, 0x63, 0xdb, 0x35, 0x4d, 0x36, 0x06, 0xbd, 0x49, 0xb2, 0x82, 0xcf, - 0xa9, 0x66, 0x06, 0xce, 0x01, 0xa9, 0x71, 0x93, 0xb7, 0x54, 0xae, 0x73, 0x60, 0xff, 0xd4, 0xa5, 0x61, 0x1b, 0x05, - 0x85, 0x7d, 0x93, 0x5c, 0x18, 0xfc, 0x30, 0xe0, 0x30, 0xbb, 0xc8, 0xac, 0x9e, 0x59, 0xbb, 0x00, 0x76, 0x30, 0xbb, - 0x46, 0x53, 0xd7, 0x8e, 0x2e, 0xd9, 0x16, 0xcf, 0x3b, 0xdf, 0x35, 0x73, 0x0b, 0x3a, 0x66, 0xc5, 0xca, 0x6e, 0x54, - 0x0f, 0x5c, 0xb7, 0x55, 0xc3, 0x65, 0x0e, 0x48, 0x86, 0x01, 0xd1, 0x28, 0x4d, 0xdb, 0xb7, 0x6c, 0xfc, 0x99, 0x6b, - 0xbb, 0x65, 0xda, 0xea, 0x16, 0x9c, 0x8a, 0xcc, 0x98, 0x16, 0xac, 0x5c, 0x79, 0x42, 0xde, 0x69, 0x10, 0xd0, 0x1b, - 0x61, 0x0e, 0x68, 0x4d, 0xc7, 0x6d, 0x08, 0xb1, 0xc6, 0xca, 0xd5, 0xbe, 0xc9, 0xcd, 0xe9, 0x9d, 0x43, 0xb1, 0x47, - 0x9d, 0xef, 0x1a, 0x87, 0xec, 0x59, 0xa7, 0xe3, 0x8f, 0x88, 0xb6, 0xad, 0x91, 0x76, 0x93, 0x73, 0x36, 0xaf, 0x12, - 0xb5, 0x5c, 0xa4, 0x8d, 0x84, 0xb1, 0xd4, 0x5a, 0xce, 0x6d, 0xda, 0x1e, 0x6a, 0xd4, 0x24, 0xbd, 0xdd, 0xde, 0xe2, - 0xee, 0xc0, 0xfc, 0xd3, 0x39, 0xe8, 0xec, 0x92, 0xda, 0x5d, 0xac, 0x38, 0x45, 0x1e, 0x8f, 0xa1, 0xe3, 0x2e, 0x9b, - 0xf7, 0x97, 0x0a, 0x8e, 0x7b, 0x03, 0x71, 0x73, 0xa2, 0x6d, 0xcc, 0x64, 0x01, 0xb0, 0x94, 0x0b, 0x38, 0x5d, 0xed, - 0x61, 0x07, 0x7d, 0x28, 0x09, 0xe6, 0xf0, 0x7b, 0x1b, 0x6d, 0x0e, 0xab, 0x73, 0x50, 0x0f, 0x0c, 0xfe, 0xd9, 0xfc, - 0x51, 0xf3, 0xe7, 0xcf, 0x58, 0x20, 0x1f, 0xf1, 0x56, 0x72, 0xbe, 0xee, 0x38, 0x99, 0x28, 0xd7, 0xb5, 0xa8, 0x66, - 0x3c, 0x4a, 0xe6, 0xf4, 0xce, 0xba, 0x96, 0xcc, 0xb9, 0x00, 0xc3, 0x35, 0x84, 0x75, 0x60, 0xe2, 0x3f, 0x0b, 0x1b, - 0xca, 0x75, 0x0c, 0x0d, 0x1f, 0xf7, 0x92, 0xf3, 0x73, 0x84, 0x3b, 0xb8, 0x77, 0x7e, 0x1e, 0xc8, 0x64, 0x13, 0xbd, - 0xaf, 0xe8, 0xbe, 0x92, 0x72, 0x4f, 0xc9, 0x13, 0xd3, 0xe8, 0x49, 0xb7, 0xd3, 0xc1, 0xc6, 0x7d, 0xbe, 0x2a, 0x2c, - 0xd4, 0x9e, 0x66, 0xbb, 0x9d, 0x0e, 0x34, 0x0b, 0x7f, 0xdc, 0xbc, 0x7e, 0x20, 0xab, 0x4e, 0xda, 0xc1, 0xdd, 0xb4, - 0x8b, 0x7b, 0x69, 0x0f, 0x9f, 0xa6, 0xa7, 0xf8, 0x2c, 0x3d, 0xc3, 0xe7, 0xe9, 0x39, 0xbe, 0x48, 0x2f, 0xf0, 0xc3, - 0xf4, 0x21, 0xbe, 0x4c, 0x2f, 0xf1, 0xa3, 0xf4, 0x11, 0x7e, 0x9c, 0x76, 0x3b, 0xf8, 0x49, 0xda, 0xed, 0xe2, 0xa7, - 0x69, 0xb7, 0x87, 0x9f, 0xa5, 0xdd, 0x53, 0xfc, 0x3c, 0xed, 0x9e, 0xe1, 0x17, 0x69, 0xf7, 0x1c, 0x53, 0xc8, 0x1d, - 0x43, 0x6e, 0x06, 0xb9, 0x39, 0xe4, 0x32, 0xc8, 0x9d, 0xa4, 0xdd, 0xf3, 0x0d, 0x56, 0x36, 0xe4, 0x46, 0xd4, 0xe9, - 0xf6, 0x4e, 0xcf, 0xce, 0x2f, 0x1e, 0x5e, 0x3e, 0x7a, 0xfc, 0xe4, 0xe9, 0xb3, 0xe7, 0x2f, 0xa2, 0x11, 0xfe, 0x64, - 0x3c, 0x5f, 0x94, 0x18, 0xf2, 0xa3, 0xee, 0xf9, 0x08, 0xdf, 0xfb, 0xcf, 0x98, 0x1f, 0xf5, 0xce, 0x3a, 0xe8, 0xfa, - 0xfa, 0x6c, 0xd4, 0xaa, 0x72, 0x9f, 0x18, 0x87, 0x9b, 0x3a, 0x8b, 0x10, 0x12, 0x43, 0x0e, 0xc2, 0x77, 0xd6, 0x81, - 0x86, 0xc5, 0x3c, 0x29, 0xd1, 0xd1, 0x91, 0xf9, 0x31, 0xf5, 0x3f, 0xc6, 0xfe, 0x07, 0x0d, 0x16, 0xe9, 0x0b, 0x8d, - 0x9d, 0xc7, 0xb5, 0xae, 0xfc, 0x1d, 0x2a, 0x53, 0xa2, 0x03, 0xee, 0x8c, 0xfa, 0xff, 0x2b, 0xb2, 0x46, 0x3b, 0xe4, - 0xcc, 0x2a, 0xc6, 0xce, 0x07, 0x8c, 0xac, 0xca, 0xb4, 0x77, 0x7e, 0x7e, 0xf4, 0xc3, 0x90, 0x0f, 0xbb, 0xa3, 0xd1, - 0x71, 0xf7, 0x21, 0x9e, 0x56, 0x09, 0x3d, 0x9b, 0x30, 0xae, 0x12, 0x4e, 0x6d, 0x02, 0x4d, 0x6d, 0x6d, 0x48, 0x3a, - 0x33, 0x49, 0x50, 0x62, 0x93, 0x9a, 0xb6, 0x1f, 0xda, 0xb6, 0x1f, 0x81, 0x35, 0x99, 0x69, 0xde, 0x35, 0x7d, 0x75, - 0x75, 0xb6, 0x76, 0x8d, 0xe2, 0x69, 0xea, 0x5a, 0xf3, 0x89, 0x67, 0xa3, 0x11, 0x1e, 0x9b, 0xc4, 0xf3, 0x3a, 0xf1, - 0x62, 0x34, 0x72, 0x5d, 0x3d, 0x32, 0x5d, 0x3d, 0xac, 0xb3, 0x2e, 0x47, 0x23, 0xd3, 0x25, 0x72, 0xb1, 0x03, 0x94, - 0x3e, 0xb8, 0xad, 0xf4, 0x37, 0xfc, 0xaa, 0x77, 0x7e, 0x3e, 0x00, 0x0c, 0x33, 0x36, 0xc1, 0x1e, 0x46, 0x9f, 0x03, - 0x18, 0xdd, 0xc1, 0xef, 0xc1, 0x27, 0x9a, 0xde, 0xd3, 0x0a, 0x48, 0x83, 0xe8, 0xbf, 0xa2, 0x96, 0x36, 0x30, 0x37, - 0x7f, 0xa6, 0xf6, 0xcf, 0x18, 0xb5, 0x6e, 0x29, 0x80, 0x1b, 0x34, 0x52, 0x5e, 0xa5, 0x6c, 0x7a, 0xbc, 0xa1, 0xe0, - 0xe2, 0x33, 0x53, 0x05, 0x1d, 0xac, 0x67, 0xb7, 0xe3, 0xf5, 0x4c, 0x7d, 0x41, 0xbf, 0xc7, 0xbf, 0xab, 0xe3, 0x78, - 0xd8, 0x6e, 0x25, 0xec, 0xf7, 0x1c, 0x7c, 0x89, 0x06, 0x69, 0xce, 0xa6, 0x68, 0x30, 0xfc, 0x5d, 0xe1, 0x51, 0x2b, - 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0xd0, 0x00, 0x0d, 0x7e, 0x57, 0xc7, 0xbf, 0xa3, - 0x07, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x87, 0x1f, 0x3a, 0xae, 0xb6, 0x30, 0xc3, 0xdd, 0x36, 0x83, 0x60, - 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe2, 0x27, 0xa7, 0x1d, 0xf4, 0x5d, 0xb7, 0x07, 0xca, 0x95, 0xb6, 0x38, 0xde, - 0xdd, 0xf4, 0x65, 0xfb, 0x14, 0x3f, 0x6a, 0x97, 0xb8, 0x8b, 0x70, 0xbb, 0xeb, 0xb5, 0xde, 0x43, 0x15, 0x77, 0x10, - 0x56, 0xf1, 0x25, 0xfc, 0x73, 0x86, 0x46, 0xf5, 0x86, 0xfc, 0x89, 0x6e, 0xf7, 0x0e, 0x7e, 0xb3, 0x24, 0x56, 0x2d, - 0x7e, 0x72, 0xd1, 0x41, 0xdf, 0x5d, 0x98, 0x8e, 0xd8, 0xb1, 0xde, 0xd3, 0x95, 0xc4, 0x67, 0x6d, 0x09, 0x1d, 0x75, - 0xaa, 0x7e, 0x44, 0x7c, 0x8e, 0xb0, 0x88, 0x4f, 0xe1, 0x9f, 0x6e, 0xd8, 0xcf, 0xd3, 0x9d, 0x7e, 0xcc, 0xbc, 0xbb, - 0x38, 0x39, 0xb7, 0x6e, 0xb8, 0xca, 0xde, 0x89, 0xb7, 0xd8, 0x75, 0xd7, 0x5c, 0xe6, 0x75, 0x4f, 0xe0, 0x03, 0x61, - 0x7d, 0x4c, 0x14, 0x66, 0xc7, 0xe0, 0xbf, 0x0b, 0x66, 0x2b, 0xea, 0xea, 0xb4, 0xaf, 0x5a, 0x2d, 0x24, 0x86, 0x6a, - 0x74, 0x4c, 0xba, 0x6d, 0xdd, 0x66, 0x18, 0x7e, 0xb7, 0x48, 0x15, 0x14, 0x4e, 0xd4, 0xbd, 0xbe, 0x71, 0xbd, 0xda, - 0x9b, 0x7f, 0x8f, 0x1d, 0x84, 0x10, 0x35, 0x88, 0x75, 0x9b, 0xa1, 0x13, 0xd1, 0x8a, 0xf5, 0x15, 0x1b, 0x5c, 0xa4, - 0x1d, 0x64, 0xb0, 0x53, 0x0d, 0x62, 0xd6, 0xe6, 0x90, 0xde, 0x4b, 0x63, 0xde, 0xd6, 0xf0, 0xeb, 0x2c, 0x80, 0x96, - 0x00, 0xbc, 0xab, 0xbd, 0x91, 0xca, 0x93, 0xde, 0xf9, 0x39, 0x16, 0x84, 0x27, 0x53, 0xf3, 0x4b, 0x11, 0x9e, 0x8c, - 0xcd, 0x2f, 0x49, 0x2a, 0x78, 0xd9, 0xde, 0x71, 0x49, 0x82, 0x55, 0x35, 0x29, 0x14, 0x16, 0xb4, 0x44, 0x27, 0x3d, - 0x6f, 0x16, 0x80, 0x67, 0x7e, 0x0e, 0xa0, 0x06, 0x29, 0x8d, 0x45, 0xa8, 0x6c, 0x97, 0xb8, 0x20, 0xf4, 0x3a, 0x39, - 0x1f, 0xcc, 0x4e, 0xe2, 0x5e, 0x5b, 0xb6, 0x4b, 0x94, 0xce, 0x4e, 0x4c, 0x4d, 0x9c, 0x91, 0x37, 0xd4, 0xb6, 0x86, - 0x67, 0x70, 0x97, 0x9b, 0x91, 0xec, 0xf8, 0xa2, 0xd3, 0x4a, 0xce, 0x11, 0x1e, 0x66, 0xeb, 0x0e, 0x2e, 0xd6, 0xeb, - 0x0e, 0xa6, 0xe1, 0x32, 0x08, 0x0f, 0x90, 0x4a, 0x53, 0xb7, 0x1d, 0x9b, 0x67, 0xc0, 0x63, 0x0d, 0x76, 0x09, 0x1a, - 0xbc, 0x7d, 0x34, 0xf8, 0x21, 0xa5, 0xdc, 0x5d, 0x08, 0x22, 0x13, 0x9d, 0x70, 0x12, 0xea, 0xee, 0xde, 0x08, 0xbf, - 0xae, 0xde, 0xb2, 0x54, 0xc4, 0xbf, 0x4a, 0x6c, 0xd3, 0xea, 0x62, 0x0f, 0xe8, 0x6e, 0xb1, 0xa7, 0x74, 0xa7, 0xd8, - 0xdb, 0x3d, 0xc5, 0x7e, 0xda, 0x2d, 0xf6, 0x97, 0x0c, 0x34, 0x8d, 0xfc, 0xbb, 0xd3, 0x8b, 0x4e, 0xeb, 0x14, 0x90, - 0xf5, 0xf4, 0xa2, 0x53, 0x17, 0x7a, 0x4c, 0xeb, 0xb5, 0xd2, 0xe4, 0x86, 0x5a, 0x5f, 0x0b, 0xee, 0x9d, 0xbe, 0xcd, - 0xc2, 0x59, 0x97, 0xf3, 0xca, 0xbf, 0x7c, 0x78, 0x0e, 0xb6, 0x2c, 0xc2, 0x50, 0x3b, 0x3d, 0xbc, 0x18, 0x0d, 0x66, - 0x2c, 0x6e, 0x41, 0x2a, 0x4a, 0x27, 0xda, 0xfd, 0x42, 0xd5, 0x95, 0xf6, 0x5f, 0x12, 0x92, 0x7a, 0x23, 0x84, 0x25, - 0x69, 0xe9, 0xe1, 0xe9, 0xc8, 0x9c, 0x77, 0x25, 0xfc, 0x3e, 0x33, 0xbf, 0x2b, 0x85, 0x92, 0x73, 0xc8, 0x98, 0xdd, - 0x8e, 0xa3, 0x81, 0x20, 0x0f, 0x68, 0x6c, 0x6c, 0xec, 0x51, 0x5a, 0x65, 0xa8, 0x2f, 0x90, 0xf1, 0xb6, 0xca, 0x10, - 0xe4, 0x8d, 0x70, 0xbf, 0xf1, 0xaa, 0x4c, 0xc1, 0xde, 0x06, 0x4f, 0x53, 0xb0, 0xb5, 0xc1, 0xe3, 0x54, 0x80, 0x3f, - 0x08, 0x4d, 0x59, 0x60, 0xc5, 0xff, 0xdc, 0x69, 0xf0, 0xcc, 0xad, 0x33, 0x31, 0x58, 0xda, 0x67, 0x70, 0x52, 0xfc, - 0x25, 0x63, 0xf8, 0xdb, 0xd2, 0x08, 0x33, 0x68, 0x93, 0x21, 0xcc, 0x93, 0x92, 0x40, 0x1a, 0xe6, 0xc9, 0x94, 0x30, - 0x68, 0x92, 0x27, 0x63, 0xc2, 0x86, 0xbd, 0x00, 0x4d, 0x5e, 0x19, 0xd8, 0x01, 0x70, 0x78, 0xf3, 0x22, 0x5f, 0xdb, - 0xc6, 0xc1, 0x42, 0x00, 0x9a, 0x10, 0x04, 0x62, 0x2e, 0x0c, 0xc1, 0x6c, 0x44, 0xd9, 0x9f, 0xbd, 0x3a, 0xfc, 0x25, - 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x00, 0x59, 0x8d, 0x1f, 0xac, 0xd8, 0x06, 0x1f, 0x3c, 0x58, 0x89, 0xcd, 0x77, 0xf0, - 0x47, 0xd9, 0x3f, 0xc0, 0x3c, 0x24, 0x14, 0x6d, 0xd0, 0x1f, 0x29, 0x14, 0xdb, 0x53, 0x0a, 0xfd, 0xe1, 0xdd, 0x01, - 0x15, 0x59, 0xdd, 0xa5, 0x51, 0x4e, 0xcb, 0xcf, 0x11, 0xfe, 0x2d, 0x8d, 0x0a, 0xe0, 0x16, 0x23, 0xfc, 0x6b, 0x1a, - 0x95, 0x2c, 0xc2, 0xff, 0x4a, 0xa3, 0x71, 0xb1, 0x8c, 0xf0, 0x2f, 0x69, 0x34, 0x2d, 0x23, 0xfc, 0x11, 0x94, 0xb5, - 0x39, 0x5f, 0xce, 0x23, 0xfc, 0x21, 0x8d, 0x94, 0xf1, 0x86, 0xc0, 0x8f, 0xd3, 0x88, 0xb1, 0x08, 0xbf, 0x4f, 0x23, - 0x59, 0x44, 0xf8, 0x26, 0x8d, 0x64, 0x19, 0xe1, 0x27, 0x69, 0x54, 0xd2, 0x08, 0x3f, 0x4d, 0x23, 0x28, 0x34, 0x8d, - 0xf0, 0xb3, 0x34, 0x82, 0x96, 0x55, 0x84, 0xdf, 0xa5, 0x11, 0x17, 0x11, 0xfe, 0x39, 0x8d, 0xf4, 0xb2, 0xfc, 0x6b, - 0x29, 0xb9, 0x8a, 0xf0, 0xf3, 0x34, 0x9a, 0xf1, 0x08, 0xbf, 0x4d, 0xa3, 0x52, 0x46, 0xf8, 0x4d, 0x1a, 0xd1, 0x22, - 0xc2, 0xaf, 0xd3, 0xa8, 0x60, 0x11, 0xfe, 0x29, 0x8d, 0x72, 0x16, 0xe1, 0x1f, 0xd3, 0xe8, 0x9e, 0x15, 0x85, 0x8c, - 0xf0, 0x8b, 0x34, 0x62, 0x22, 0xc2, 0x3f, 0xa4, 0x51, 0x36, 0x8b, 0xf0, 0x3f, 0xd3, 0x88, 0x96, 0x9f, 0x55, 0x84, - 0x5f, 0xa6, 0x11, 0xa3, 0x11, 0x7e, 0x65, 0x3b, 0x9a, 0x46, 0xf8, 0xfb, 0x34, 0xba, 0x9d, 0x45, 0x1b, 0x2c, 0x15, - 0x59, 0xbd, 0xe1, 0x19, 0xfb, 0x17, 0x4b, 0xa3, 0x49, 0x67, 0x72, 0x39, 0x99, 0x44, 0x98, 0x0a, 0xcd, 0xff, 0x5a, - 0xb2, 0xdb, 0xe7, 0x1a, 0x12, 0x29, 0x1b, 0xe7, 0x0f, 0x23, 0x4c, 0xff, 0x5a, 0xd2, 0x34, 0x9a, 0x4c, 0x4c, 0x81, - 0xbf, 0x96, 0x74, 0x4e, 0xcb, 0x77, 0x2c, 0x8d, 0x1e, 0x4e, 0x26, 0x93, 0xfc, 0x2c, 0xc2, 0xf4, 0xef, 0xe5, 0xaf, - 0xa6, 0x05, 0x53, 0x60, 0xcc, 0xf8, 0x14, 0xea, 0x9e, 0x4f, 0xce, 0xf3, 0x2c, 0xc2, 0x63, 0xae, 0xfe, 0x5a, 0xc2, - 0xf7, 0x84, 0x9d, 0x65, 0x67, 0x11, 0x1e, 0x17, 0x34, 0xfb, 0x9c, 0x46, 0x1d, 0xf3, 0x4b, 0xfc, 0xc0, 0xf2, 0x37, - 0x73, 0x69, 0xae, 0x32, 0x26, 0x6c, 0x9c, 0xe5, 0x11, 0x36, 0x83, 0x99, 0xc0, 0xdf, 0x2f, 0xfc, 0x3d, 0xd3, 0x69, - 0x74, 0x49, 0x7b, 0x63, 0xd6, 0x8b, 0xf0, 0xf8, 0xed, 0xad, 0x48, 0x23, 0x7a, 0xde, 0xa3, 0x3d, 0x1a, 0xe1, 0xf1, - 0xb2, 0x2c, 0xee, 0x6f, 0xa5, 0xcc, 0x01, 0x08, 0xe3, 0xcb, 0xcb, 0x87, 0x11, 0xce, 0xe8, 0x4f, 0x1a, 0x6a, 0x9f, - 0x4f, 0x1e, 0x31, 0xda, 0x89, 0xf0, 0x0f, 0xb4, 0xd4, 0xbf, 0x2e, 0x95, 0x1b, 0x68, 0x07, 0x52, 0x64, 0xf6, 0x1e, - 0xd4, 0xfc, 0x51, 0xde, 0xbb, 0x78, 0xd4, 0x65, 0x11, 0xce, 0x6e, 0xde, 0x40, 0x6f, 0x0f, 0x27, 0xe7, 0x1d, 0xf8, - 0x10, 0x20, 0x97, 0xb2, 0x12, 0x1a, 0xb9, 0x38, 0x7b, 0x74, 0xce, 0x72, 0x93, 0xa8, 0x78, 0xf1, 0xd9, 0xcc, 0xfe, - 0x12, 0xe6, 0x93, 0x95, 0x7c, 0xae, 0xa4, 0x48, 0xa3, 0x3c, 0xeb, 0x9e, 0x9d, 0x42, 0xc2, 0x3d, 0x15, 0x1e, 0x38, - 0x77, 0x50, 0xf5, 0x72, 0x1c, 0xe1, 0x3b, 0x9b, 0x7a, 0x39, 0x36, 0x1f, 0xd3, 0xf7, 0x3f, 0x89, 0xb7, 0x79, 0x1a, - 0x8d, 0x2f, 0x2f, 0x2f, 0x3a, 0x90, 0xf0, 0x0b, 0xbd, 0x4f, 0x23, 0xfa, 0x08, 0xfe, 0x83, 0xec, 0x5f, 0x5f, 0x40, - 0x87, 0x30, 0xc2, 0xbb, 0xe9, 0xaf, 0x61, 0xce, 0xe7, 0x19, 0xfd, 0xcc, 0xd3, 0x68, 0x9c, 0x8f, 0x1f, 0x5e, 0x40, - 0xbd, 0x39, 0x9d, 0xbe, 0xd0, 0x14, 0xda, 0xed, 0x74, 0x4c, 0xcb, 0xef, 0xf9, 0x17, 0x66, 0xaa, 0x9f, 0x9f, 0x5f, - 0x8c, 0x7b, 0x30, 0x82, 0x1b, 0x50, 0xa8, 0xc0, 0x78, 0x2e, 0x33, 0xd3, 0xe0, 0x4d, 0xf6, 0x3c, 0x4f, 0xa3, 0x47, - 0x8f, 0x4e, 0x7b, 0x59, 0x16, 0xe1, 0xbb, 0x5f, 0x73, 0x5b, 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x47, 0x8f, - 0x2e, 0x1e, 0x52, 0xf8, 0x7e, 0x69, 0xda, 0xba, 0x9c, 0x8c, 0xb3, 0x4b, 0x68, 0xeb, 0x03, 0x4c, 0xe7, 0xec, 0xf2, - 0x34, 0x37, 0x7d, 0x7d, 0x30, 0xa3, 0xee, 0x4d, 0xce, 0x26, 0x67, 0x26, 0xd3, 0x0c, 0xb5, 0xfa, 0xfc, 0x99, 0xa5, - 0x51, 0xc6, 0xf2, 0x6e, 0x84, 0xef, 0xdc, 0xc2, 0x3d, 0x3a, 0xeb, 0x74, 0xf2, 0xd3, 0x08, 0xe7, 0x8f, 0x17, 0x8b, - 0x77, 0x06, 0x82, 0xdd, 0xb3, 0x47, 0xf6, 0x5b, 0x7d, 0xbe, 0x87, 0xa6, 0xc7, 0x06, 0x68, 0x39, 0x9f, 0x9b, 0x96, - 0x2f, 0x1e, 0xc1, 0x7f, 0xe6, 0xdb, 0x34, 0x5d, 0x7d, 0xcb, 0x7c, 0x6a, 0x17, 0xa5, 0xcb, 0x1e, 0x75, 0xa0, 0xc6, - 0x84, 0xff, 0x3a, 0x2e, 0x39, 0xa0, 0xd1, 0xb8, 0x07, 0xff, 0x17, 0xe1, 0x49, 0x71, 0xf3, 0xc6, 0xe1, 0xec, 0x64, - 0x42, 0x27, 0x9d, 0x08, 0x4f, 0xe4, 0xaf, 0x4a, 0xff, 0xf2, 0x58, 0xa4, 0x51, 0xaf, 0x77, 0x39, 0x36, 0x65, 0x96, - 0x3f, 0x28, 0x6e, 0xf0, 0xb8, 0x63, 0x5a, 0x99, 0xd2, 0x77, 0x6a, 0x7c, 0x23, 0x61, 0x25, 0xe1, 0xbf, 0x08, 0x4f, - 0x41, 0x0b, 0xe7, 0x5a, 0xb9, 0xb4, 0xdb, 0x61, 0xfa, 0xde, 0xa0, 0x66, 0xfe, 0x10, 0xe0, 0xe5, 0x97, 0x31, 0xa7, - 0xf4, 0xbc, 0xd7, 0x89, 0xb0, 0x19, 0xf5, 0x65, 0x07, 0xfe, 0x8b, 0xb0, 0x85, 0x9c, 0x81, 0xeb, 0xf4, 0xd7, 0x17, - 0x3f, 0xde, 0xa6, 0x11, 0xcd, 0x27, 0x13, 0x58, 0x12, 0x33, 0x19, 0x5f, 0x6c, 0x26, 0x05, 0xbb, 0xff, 0xe9, 0xd6, - 0x6d, 0x17, 0x93, 0xa0, 0x1d, 0x74, 0x2e, 0x1e, 0x8d, 0xcf, 0x22, 0xfc, 0x2e, 0xe7, 0x54, 0xc0, 0x2a, 0x65, 0xf9, - 0x79, 0x76, 0x9e, 0x99, 0x84, 0xa9, 0x4c, 0xa3, 0x33, 0x58, 0xf2, 0x5e, 0x84, 0xf9, 0x97, 0x9b, 0x7b, 0x8b, 0x6e, - 0x50, 0xdb, 0x21, 0xc8, 0xa4, 0xc3, 0x2e, 0x2e, 0xb3, 0x08, 0x17, 0xf4, 0xcb, 0x8b, 0x9f, 0xca, 0x34, 0x62, 0x17, - 0xec, 0x62, 0x42, 0xfd, 0xf7, 0xbf, 0xd4, 0xcc, 0xd4, 0xe8, 0x4c, 0xce, 0x21, 0xe9, 0x56, 0x98, 0xb1, 0x3e, 0xcc, - 0x26, 0x06, 0x43, 0x5e, 0xcf, 0xa5, 0xc8, 0x9e, 0x4f, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, 0x1b, 0x40, 0x9b, - 0xe6, 0xf9, 0x25, 0xbb, 0x88, 0xf0, 0x6f, 0x76, 0x97, 0xb8, 0x09, 0xfc, 0x66, 0x31, 0x9b, 0xb9, 0xdd, 0xfe, 0x9b, - 0x05, 0x0a, 0xcc, 0x77, 0x42, 0x27, 0x34, 0xef, 0x45, 0xf8, 0x37, 0x03, 0x97, 0xfc, 0x14, 0xfe, 0x83, 0x02, 0xd0, - 0xd9, 0xa3, 0x0e, 0x63, 0x8f, 0x3a, 0xe6, 0x2b, 0xcc, 0x73, 0x33, 0x1f, 0x5f, 0x64, 0xdd, 0x08, 0xff, 0xe6, 0xd0, - 0x71, 0x32, 0xa1, 0x1d, 0x40, 0xc7, 0xdf, 0x1c, 0x3a, 0xf6, 0x3a, 0xe3, 0x1e, 0x35, 0xdf, 0x16, 0x6b, 0x2e, 0x1f, - 0x66, 0x0c, 0x26, 0xf7, 0x9b, 0x45, 0xc8, 0x87, 0x0f, 0x2f, 0x2f, 0x1f, 0x3d, 0x82, 0x4f, 0xd3, 0x76, 0xf5, 0xa9, - 0xf4, 0xe3, 0xc2, 0x20, 0x59, 0x27, 0x3b, 0x03, 0x3a, 0xf9, 0x9b, 0x19, 0xe3, 0x64, 0x32, 0x61, 0x9d, 0x08, 0x17, - 0x7c, 0xce, 0x2c, 0x26, 0xd8, 0xdf, 0xa6, 0xa3, 0xd3, 0x5e, 0x96, 0x9f, 0xf6, 0x22, 0x5c, 0xbc, 0x7b, 0x61, 0x66, - 0xd3, 0x81, 0xd9, 0xfb, 0x2d, 0xe7, 0xb1, 0x66, 0x4e, 0xdf, 0xc2, 0x20, 0x61, 0xa5, 0xa1, 0xf2, 0xc7, 0x80, 0x1e, - 0x5e, 0x5c, 0x64, 0x39, 0x0c, 0xf4, 0x23, 0x74, 0x0b, 0x60, 0xfc, 0x68, 0x37, 0xdf, 0x98, 0x9e, 0x9f, 0xc3, 0x74, - 0x3f, 0x2e, 0x96, 0xe5, 0xe2, 0x75, 0x1a, 0x3d, 0x3a, 0x7d, 0xd8, 0xc9, 0xc7, 0x11, 0xfe, 0xe8, 0x26, 0x78, 0x9a, - 0x8d, 0x4f, 0x1f, 0x76, 0x23, 0xfc, 0xd1, 0xec, 0xb7, 0x87, 0xe3, 0x8b, 0x4b, 0x38, 0x37, 0x3e, 0xaa, 0x45, 0xf9, - 0x6e, 0x6a, 0x0a, 0x4c, 0xe8, 0x23, 0x68, 0xf6, 0x67, 0xb3, 0x1b, 0xf3, 0x2e, 0x6c, 0xe4, 0x8f, 0x66, 0x93, 0x19, - 0x3c, 0x79, 0xd8, 0x3d, 0xbf, 0x3c, 0x8f, 0xf0, 0x9c, 0xe7, 0x02, 0x08, 0xbc, 0xd9, 0x28, 0x8f, 0xba, 0x8f, 0x1e, - 0x76, 0x22, 0x3c, 0x7f, 0xa7, 0xb3, 0x5f, 0xe9, 0xdc, 0x50, 0xe3, 0x09, 0xc0, 0x6c, 0xce, 0x95, 0xbe, 0x7f, 0xab, - 0x1c, 0x3d, 0x66, 0xdd, 0x08, 0xcf, 0x65, 0x96, 0x51, 0xf5, 0xce, 0x26, 0x8c, 0xcf, 0x23, 0x2c, 0xe8, 0x17, 0xfa, - 0xa7, 0xf4, 0x9b, 0x29, 0x67, 0x34, 0x37, 0x69, 0x06, 0x87, 0x23, 0xfc, 0x3e, 0x87, 0xcb, 0xc8, 0x34, 0x9a, 0xe4, - 0x93, 0x73, 0x00, 0x0f, 0x10, 0x20, 0x8b, 0xdd, 0x00, 0x0d, 0xf8, 0xca, 0x9f, 0x8c, 0xd3, 0xe8, 0x62, 0x7c, 0xc9, - 0x7a, 0xa7, 0x11, 0xae, 0xa8, 0x11, 0x3d, 0x87, 0x7c, 0xf3, 0xf9, 0xab, 0xd9, 0x52, 0x67, 0x36, 0xc1, 0x00, 0x28, - 0xa7, 0x0f, 0x3b, 0xf9, 0x45, 0x84, 0x17, 0x6f, 0x98, 0xdf, 0x63, 0x8c, 0xb1, 0x4b, 0x80, 0x25, 0x24, 0x19, 0x04, - 0xba, 0x9c, 0x8c, 0x1f, 0x5d, 0x9a, 0x6f, 0x00, 0x03, 0x9d, 0x30, 0x06, 0x40, 0x5a, 0xbc, 0x61, 0x15, 0x20, 0xf2, - 0xf1, 0xc3, 0x0e, 0xd0, 0x97, 0x05, 0x5d, 0xd0, 0x7b, 0x7a, 0xfb, 0x7c, 0x61, 0xe6, 0x34, 0xc9, 0xcf, 0x23, 0xbc, - 0x78, 0xf9, 0xc3, 0x62, 0x39, 0x99, 0x98, 0x09, 0xd1, 0xf1, 0xa3, 0x08, 0x2f, 0x58, 0xb9, 0x84, 0x35, 0xba, 0x3c, - 0x3f, 0x9d, 0x44, 0xd8, 0xa1, 0x61, 0xd6, 0xc9, 0xc6, 0x70, 0xdb, 0xba, 0x9c, 0xa7, 0x51, 0x9e, 0xd3, 0x4e, 0x0e, - 0x77, 0xaf, 0xf2, 0xf6, 0xa7, 0xd2, 0xa2, 0x11, 0x33, 0xf8, 0xe0, 0xd6, 0x10, 0xe6, 0x0b, 0xf0, 0xf8, 0x75, 0xcc, - 0xb2, 0x8c, 0xba, 0xc4, 0x8b, 0x8b, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd5, 0xfd, 0xb8, 0x94, - 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xf6, 0xfe, 0x8d, 0xa1, 0xab, 0xdd, 0x8b, 0x47, 0xb0, 0x00, 0x8a, 0xe6, - 0xf9, 0x6b, 0x7b, 0xb8, 0x5d, 0x8e, 0xcf, 0xce, 0xbb, 0xa7, 0x11, 0xf6, 0x1b, 0x81, 0x5e, 0x76, 0x1e, 0xf6, 0xa0, - 0x84, 0xc8, 0xef, 0x6d, 0x89, 0xc9, 0x19, 0x3d, 0xbb, 0xe8, 0x44, 0xd8, 0x6f, 0x0d, 0x76, 0x39, 0x3e, 0x7f, 0x08, - 0x9f, 0x6a, 0xc6, 0x8a, 0xc2, 0xe0, 0xf7, 0x39, 0xc0, 0x45, 0xf1, 0x17, 0x82, 0xa6, 0x11, 0xed, 0x9c, 0xf7, 0x7a, - 0x39, 0x7c, 0x16, 0x5f, 0x58, 0x99, 0x46, 0x59, 0x07, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, 0x38, 0xc2, 0x06, 0xef, - 0x2e, 0xe8, 0xb9, 0xd9, 0xfb, 0x6e, 0x57, 0x75, 0x2e, 0x3b, 0xb0, 0x61, 0xdd, 0xa6, 0x72, 0x5f, 0x4a, 0xc8, 0x5b, - 0x47, 0x62, 0x69, 0x84, 0x03, 0x04, 0x9d, 0x3c, 0x9c, 0x44, 0xd8, 0xef, 0xb8, 0xb3, 0x8b, 0xcb, 0x1e, 0x90, 0x32, - 0x0d, 0x84, 0x22, 0xef, 0x8d, 0xcf, 0x80, 0x34, 0x69, 0xf6, 0xc6, 0xe2, 0x49, 0x84, 0xf5, 0x73, 0xa5, 0x5f, 0xa7, - 0x51, 0x7e, 0x39, 0x9e, 0xe4, 0x97, 0x11, 0xd6, 0x72, 0x4e, 0xb5, 0x34, 0x14, 0xf0, 0xf4, 0xec, 0x61, 0x84, 0x0d, - 0x9a, 0x77, 0x58, 0x27, 0xef, 0x44, 0xd8, 0x1d, 0x25, 0x8c, 0x5d, 0xf6, 0x60, 0x5a, 0xdf, 0xbf, 0xd4, 0x80, 0xcb, - 0x39, 0x1b, 0x9f, 0x46, 0xb8, 0xa2, 0xf7, 0x86, 0x10, 0xc1, 0x97, 0x9a, 0xcb, 0xcf, 0x8e, 0xf5, 0x00, 0x52, 0xe7, - 0x37, 0x3c, 0x2c, 0xc3, 0x8f, 0xb7, 0x16, 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x6d, 0xf4, 0x33, 0x1a, 0x7b, 0xb6, 0x9d, - 0x93, 0xd5, 0x06, 0x57, 0x41, 0x5e, 0x3f, 0xb3, 0x7b, 0x15, 0x4b, 0x65, 0x38, 0xd9, 0x20, 0x45, 0x29, 0xe4, 0xdd, - 0x1a, 0x9c, 0xe7, 0x2a, 0x08, 0x92, 0x82, 0x74, 0xfa, 0xe2, 0xca, 0x7b, 0xd3, 0xf6, 0x05, 0x84, 0x7e, 0x80, 0xf4, - 0x92, 0x50, 0xa2, 0x21, 0x42, 0x8e, 0x15, 0x26, 0xbd, 0x93, 0x81, 0x91, 0x29, 0xa5, 0x75, 0x5b, 0xa0, 0x84, 0xfa, - 0xd8, 0xf8, 0xb1, 0xc4, 0x0a, 0xa2, 0x47, 0xa1, 0xbe, 0x24, 0x26, 0xd2, 0xf5, 0x2b, 0xa1, 0x63, 0xa9, 0x86, 0xe5, - 0x08, 0x77, 0x2f, 0x10, 0x86, 0x18, 0x12, 0x64, 0x28, 0xaf, 0xaf, 0xbb, 0x17, 0x47, 0x46, 0xe8, 0xbb, 0xbe, 0xbe, - 0xb4, 0x3f, 0xe0, 0xdf, 0x51, 0x1d, 0xb7, 0x1b, 0xc6, 0xf7, 0x91, 0xd5, 0x73, 0x7c, 0x6f, 0xf8, 0xeb, 0x8f, 0x6c, - 0xbd, 0x8e, 0x3f, 0x32, 0x02, 0x33, 0xc6, 0x1f, 0x59, 0x62, 0xee, 0x48, 0xac, 0x87, 0x10, 0x19, 0x82, 0xe6, 0xac, - 0x83, 0x21, 0x9a, 0xbc, 0xe7, 0xbc, 0x3f, 0xb2, 0x21, 0x6f, 0x7a, 0x97, 0xd7, 0x21, 0x9c, 0x8f, 0x8e, 0x56, 0x65, - 0xaa, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xeb, 0x20, 0xfa, 0x67, 0x03, 0x90, 0x52, 0x8c, 0xb2, - 0xc5, 0xf1, 0xd4, 0x3f, 0x82, 0xda, 0x03, 0xb4, 0x93, 0x83, 0x5a, 0xd9, 0x51, 0xe9, 0x2a, 0xf6, 0x2a, 0x30, 0xf6, - 0x26, 0x3a, 0x6d, 0xc7, 0xc9, 0x7f, 0xa2, 0xee, 0x78, 0xd7, 0x10, 0xcb, 0x7e, 0xdc, 0x2b, 0x96, 0xc1, 0x4a, 0x1a, - 0xd1, 0xec, 0xd0, 0xc6, 0x23, 0xd1, 0xc3, 0x87, 0x46, 0x30, 0xab, 0x83, 0xe4, 0xb5, 0x20, 0xa9, 0x0f, 0x52, 0xc8, - 0xa5, 0x91, 0xd2, 0x4a, 0x94, 0xe6, 0x3a, 0x2e, 0x41, 0x43, 0xe9, 0x15, 0x94, 0x55, 0x2c, 0xd7, 0x96, 0x01, 0x88, - 0xb2, 0x32, 0x9a, 0x95, 0xd5, 0xce, 0x41, 0x74, 0x01, 0x4d, 0x98, 0x91, 0x58, 0xa0, 0x01, 0x61, 0x1a, 0x10, 0xae, - 0x32, 0x88, 0x33, 0x2e, 0xfb, 0xcc, 0x64, 0x2b, 0x93, 0xad, 0xaa, 0x6c, 0xe9, 0xb3, 0xad, 0x90, 0x28, 0x4d, 0xb6, - 0xac, 0xb2, 0x41, 0x66, 0xc3, 0xd3, 0x54, 0xe1, 0x71, 0x2a, 0xad, 0xa8, 0x56, 0xcb, 0x56, 0x2f, 0x68, 0xa8, 0xcd, - 0x3d, 0x3a, 0x8a, 0x2b, 0x39, 0xc9, 0xa8, 0x89, 0x1f, 0xac, 0x78, 0x52, 0x1a, 0x19, 0x88, 0x27, 0x53, 0xf7, 0x77, - 0xbc, 0xd9, 0x96, 0x95, 0xca, 0xe9, 0xf8, 0x2b, 0x25, 0xd1, 0x1f, 0x5e, 0x89, 0xfa, 0x91, 0x9b, 0x28, 0x40, 0x57, - 0x24, 0xe9, 0x74, 0x4e, 0xbb, 0xa7, 0x9d, 0xcb, 0x01, 0x3f, 0xee, 0xf6, 0x92, 0x47, 0xbd, 0xd4, 0x28, 0x22, 0x16, - 0xf2, 0x16, 0x14, 0x30, 0x27, 0xbd, 0xe4, 0x0c, 0x1d, 0x77, 0x93, 0xce, 0xf9, 0x79, 0x1b, 0xfe, 0xc1, 0x4f, 0x74, - 0x55, 0xed, 0xac, 0x73, 0x76, 0x3e, 0xe0, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x82, 0x82, 0xe8, 0xc4, 0x54, 0xc2, 0x50, - 0xbf, 0x5e, 0xde, 0xd7, 0x3b, 0x7a, 0x9e, 0x27, 0x3a, 0x96, 0x56, 0x15, 0x07, 0x50, 0xf5, 0x5f, 0x53, 0x03, 0x44, - 0xff, 0x35, 0xae, 0x22, 0xf5, 0xae, 0x4a, 0x10, 0xb5, 0x3f, 0xf2, 0x58, 0xb4, 0xd8, 0x71, 0x6c, 0xf3, 0x35, 0xd4, - 0x6d, 0x43, 0xf4, 0x3c, 0x3c, 0x75, 0xb9, 0x2a, 0xcc, 0x9d, 0x22, 0xd4, 0x56, 0x90, 0x3b, 0x76, 0xb9, 0x32, 0xcc, - 0x1d, 0x23, 0xd4, 0x96, 0x90, 0x4b, 0x53, 0x9e, 0x50, 0xc8, 0xd1, 0x09, 0x6d, 0x1b, 0x48, 0xd6, 0x8b, 0xf2, 0x92, - 0xf9, 0x61, 0xf3, 0x09, 0x2c, 0x8f, 0x21, 0x28, 0x4e, 0x90, 0x16, 0xf0, 0xc2, 0x4a, 0xa5, 0xcd, 0xe9, 0xe0, 0x4a, - 0x8d, 0x03, 0x19, 0x2d, 0xf8, 0xe7, 0x98, 0x99, 0x67, 0x37, 0x3a, 0x83, 0xd3, 0x8b, 0x4e, 0xda, 0x05, 0x57, 0x71, - 0x90, 0xb5, 0x85, 0x95, 0xb5, 0x85, 0x97, 0xb5, 0x85, 0x97, 0xb5, 0x41, 0x80, 0x0f, 0xfa, 0xfe, 0x97, 0x6c, 0x98, - 0xdf, 0xf0, 0xca, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, 0xaa, 0x51, 0xaa, 0x5a, - 0xfd, 0xb9, 0x2a, 0xd3, 0x0e, 0x9e, 0xa6, 0xa0, 0xe5, 0xee, 0x60, 0x6a, 0x36, 0xb7, 0xa7, 0x0a, 0xdb, 0x51, 0x7c, - 0x06, 0x5e, 0x9d, 0x7c, 0x4d, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa6, 0xdc, 0xd2, 0x0c, 0x6e, 0x69, 0x06, 0xb7, 0x34, - 0x03, 0x1a, 0xc1, 0x55, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x86, 0xa7, 0x23, 0x08, 0x62, 0x18, 0x6b, 0x62, - 0x46, 0xbd, 0xd5, 0x79, 0x17, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1a, 0xf3, 0xdf, 0x0d, 0xb4, - 0x4f, 0xe0, 0x45, 0x9d, 0xc7, 0x3a, 0xee, 0x80, 0xe9, 0x4a, 0x54, 0x46, 0x03, 0x43, 0x16, 0x52, 0xa3, 0xb3, 0x71, - 0x26, 0xe9, 0x9f, 0xb7, 0x3c, 0x81, 0x2d, 0x25, 0x08, 0xdf, 0x91, 0xf8, 0xcc, 0xea, 0xd0, 0x04, 0x95, 0xc5, 0xad, - 0x33, 0x97, 0xb3, 0x47, 0x42, 0x1f, 0xcc, 0xe6, 0x7d, 0xcc, 0xab, 0x81, 0x20, 0x25, 0xc4, 0x7c, 0x4c, 0x4d, 0xa2, - 0x8b, 0xda, 0x0c, 0x4e, 0xcc, 0xe4, 0x0b, 0x35, 0x2e, 0x3d, 0xef, 0xed, 0x9f, 0xbf, 0x69, 0xe0, 0xf3, 0x58, 0x4e, - 0xc7, 0xde, 0x55, 0xf8, 0x93, 0x89, 0x6d, 0x44, 0x0e, 0x0f, 0xad, 0x45, 0xbb, 0xf9, 0xda, 0x36, 0x69, 0x37, 0x89, - 0x26, 0x1b, 0x76, 0xa8, 0x5f, 0xa3, 0x7f, 0x79, 0x8f, 0xbd, 0x72, 0x3a, 0x46, 0x01, 0xcd, 0x36, 0x60, 0x95, 0x35, - 0xb0, 0x94, 0xab, 0x57, 0x39, 0x72, 0x42, 0xef, 0x66, 0xcc, 0x9b, 0x72, 0x3a, 0xde, 0xfb, 0xf4, 0x8a, 0xed, 0x71, - 0xf0, 0x82, 0x06, 0x3d, 0x78, 0xd5, 0xf6, 0x8c, 0xdd, 0x7d, 0xab, 0xce, 0xe7, 0xbd, 0x75, 0x54, 0xf1, 0xad, 0x3a, - 0xaf, 0xf6, 0xd5, 0x99, 0xf3, 0xbb, 0xd8, 0xef, 0x1d, 0x1d, 0xa8, 0xb1, 0x8d, 0x99, 0xd4, 0x74, 0x0c, 0xb1, 0xf2, - 0xe1, 0xaf, 0x8d, 0x68, 0xd3, 0xf7, 0x24, 0x1c, 0x56, 0x41, 0x0e, 0x92, 0xf3, 0x94, 0x61, 0x4a, 0x7a, 0xc7, 0xa5, - 0x89, 0x69, 0x23, 0x12, 0xda, 0x56, 0x09, 0xc5, 0x05, 0x89, 0x63, 0x7a, 0x9c, 0x41, 0x64, 0x9e, 0xee, 0x80, 0xa6, - 0x31, 0x6d, 0x65, 0xe8, 0x24, 0xee, 0xb6, 0xe8, 0x71, 0x86, 0x50, 0xab, 0x0b, 0x3a, 0x53, 0x49, 0xba, 0xed, 0x02, - 0x62, 0x75, 0x1a, 0x52, 0x5c, 0x1c, 0x8b, 0xa4, 0x6c, 0xc9, 0x63, 0x95, 0x94, 0xad, 0xe4, 0x1c, 0x8b, 0x64, 0x5a, - 0x25, 0x4f, 0x4d, 0xf2, 0xd4, 0x26, 0x8f, 0xab, 0xe4, 0xb1, 0x49, 0x1e, 0xdb, 0x64, 0x4a, 0xca, 0x63, 0x91, 0xd0, - 0x56, 0xdc, 0x6d, 0x97, 0xe8, 0x18, 0x46, 0xe0, 0x47, 0x4f, 0x44, 0x18, 0x22, 0x7d, 0x63, 0x6c, 0x8c, 0x16, 0xb2, - 0x70, 0x41, 0x4b, 0x6b, 0x20, 0x55, 0x8e, 0x5f, 0x50, 0xe7, 0x75, 0x00, 0x26, 0xac, 0xed, 0x1f, 0x1f, 0x92, 0x6f, - 0x93, 0x15, 0x52, 0x04, 0x8e, 0x6d, 0x60, 0x8b, 0xff, 0xd9, 0xb9, 0xf3, 0x00, 0x54, 0x37, 0xb4, 0x58, 0xcc, 0xe8, - 0x8e, 0xf7, 0x70, 0x39, 0x1d, 0xbb, 0x9d, 0x55, 0x35, 0xc3, 0x68, 0x69, 0x43, 0x5d, 0x37, 0xfd, 0x3c, 0x01, 0xd4, - 0xde, 0xb7, 0x34, 0xa1, 0x46, 0x49, 0x6e, 0x6b, 0x4c, 0x4b, 0x76, 0xaf, 0x32, 0x5a, 0xb0, 0xb8, 0x3e, 0x80, 0xeb, - 0x61, 0x32, 0xf2, 0x0c, 0x3c, 0x02, 0xca, 0xe3, 0xe4, 0xb4, 0xa5, 0x93, 0xe9, 0x71, 0x72, 0xfe, 0xa8, 0xa5, 0x93, - 0xf1, 0x71, 0xd2, 0xed, 0xd6, 0x38, 0x9b, 0x94, 0x44, 0x27, 0x53, 0xa2, 0x41, 0x63, 0x68, 0x1b, 0x95, 0x0b, 0x0a, - 0x26, 0x6e, 0xff, 0xc1, 0x30, 0x5a, 0x6e, 0x18, 0x82, 0x4d, 0x6d, 0xd4, 0xcf, 0x9d, 0x31, 0x84, 0xdd, 0xf4, 0xce, - 0xcf, 0xdb, 0x3a, 0x29, 0xb1, 0xb6, 0x2b, 0xd9, 0xd6, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x6d, 0x9d, 0x8c, 0x6d, 0x53, - 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0x97, 0x2c, 0x80, 0x7c, 0xcf, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, 0xf8, 0xad, 0x72, - 0x6d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xbb, 0x75, 0x93, 0xec, 0xdf, 0x97, 0xad, 0x9a, 0x2d, - 0xa5, 0x6e, 0x16, 0x7c, 0xde, 0xc0, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x7f, 0x52, 0x12, 0x43, 0x6c, 0x3f, 0x73, 0x0a, - 0x71, 0xe2, 0xf5, 0xc8, 0x90, 0xc4, 0x5b, 0xad, 0x0d, 0x8a, 0x83, 0xf3, 0xf6, 0x55, 0x48, 0x55, 0x77, 0x02, 0xfe, - 0x11, 0x12, 0x2d, 0x85, 0x35, 0x09, 0xcd, 0xa3, 0x9a, 0x16, 0xbf, 0x73, 0xda, 0xdd, 0xc6, 0x01, 0x71, 0x74, 0xb4, - 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xed, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, 0x98, 0x07, 0x88, - 0xe2, 0x43, 0x6f, 0x3d, 0x34, 0x14, 0x7e, 0x58, 0xc7, 0x1d, 0x74, 0x39, 0xed, 0x0b, 0x93, 0x61, 0xfa, 0x1a, 0x05, - 0x63, 0x7b, 0x10, 0x4e, 0xa8, 0xb2, 0x95, 0xfc, 0xb7, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, 0x46, 0xff, 0x0c, - 0x2d, 0x93, 0x6b, 0xd8, 0x38, 0x9f, 0xf4, 0xf5, 0xba, 0xf1, 0x3c, 0x91, 0x7d, 0x04, 0x07, 0x1d, 0x1d, 0x71, 0xf5, - 0x02, 0x8c, 0xa9, 0x59, 0xdc, 0x0a, 0x0f, 0xdf, 0xbf, 0x1a, 0xa7, 0xf5, 0x9f, 0xe6, 0x5c, 0x4d, 0x83, 0x83, 0xee, - 0x71, 0x23, 0x7f, 0xef, 0x4a, 0x0c, 0x74, 0xca, 0xdd, 0x5a, 0x3f, 0xa9, 0x4d, 0xd5, 0x77, 0x1e, 0xca, 0x3a, 0x3a, - 0xe2, 0x75, 0xb8, 0xaa, 0xe8, 0xbb, 0x08, 0x0d, 0x8c, 0x0c, 0xf2, 0xa2, 0x90, 0x14, 0x6e, 0x44, 0xe1, 0x8a, 0x21, - 0x6d, 0xf1, 0x13, 0x8d, 0x7f, 0x90, 0xff, 0x8f, 0x1a, 0x39, 0xd6, 0x69, 0x8b, 0x07, 0x02, 0x58, 0xc8, 0x0a, 0xd5, - 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1d, 0xe6, 0x74, 0xb1, 0x28, 0xee, 0xcd, 0x5b, 0x61, 0x01, 0x47, - 0x55, 0x5f, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x04, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xea, 0x72, 0x5b, 0x20, - 0x90, 0xcc, 0x14, 0x91, 0xed, 0x6e, 0x5f, 0x5d, 0x83, 0x5c, 0xd6, 0x6e, 0x23, 0xed, 0x82, 0x97, 0x63, 0x0e, 0x32, - 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, 0x0c, 0x68, 0x84, - 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xd2, 0x77, 0xfc, 0x95, 0x96, 0xca, 0xa1, 0x1a, 0x8d, 0x70, 0x69, - 0x9e, 0xc7, 0xa8, 0xe6, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, 0x33, 0x72, 0x6d, - 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbf, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x63, 0x2e, 0x0a, 0x9d, 0xbc, 0xc9, 0xae, 0x44, - 0xbf, 0xd5, 0x62, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, 0xc5, 0x6c, 0x04, - 0x3e, 0x08, 0x0d, 0xde, 0x48, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xaa, 0x9f, 0x2a, 0x94, - 0x6c, 0x6d, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x57, 0xef, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, 0x9b, 0x60, 0x00, - 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8a, 0x13, 0x60, 0x6f, 0x6e, - 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x82, 0x1c, 0x3d, 0x22, 0xd0, 0xb9, 0xfd, 0x59, 0xd3, 0x85, 0x5a, - 0x26, 0xae, 0xc6, 0xf8, 0xcf, 0xe0, 0x36, 0x6f, 0x18, 0x7d, 0xfa, 0x64, 0x36, 0xf9, 0xa7, 0x4f, 0x11, 0x0e, 0x8d, - 0xeb, 0xa3, 0x80, 0x17, 0x8c, 0x46, 0x55, 0x68, 0x2d, 0xb3, 0xf1, 0xdb, 0xdd, 0xba, 0xb1, 0x8f, 0xb4, 0xc6, 0x3b, - 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x90, 0x03, 0xbc, 0xd9, 0x90, 0x8f, 0xfa, 0x0f, 0x62, 0x85, 0x8e, 0x8e, - 0x1e, 0xc4, 0x12, 0x0d, 0x6e, 0x98, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x21, 0x37, 0xc3, 0x97, 0x01, 0x02, 0xdc, 0xb0, - 0x6d, 0xc9, 0xe6, 0x9d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0x3e, 0x08, 0xa1, - 0xdd, 0x67, 0x84, 0x01, 0x0b, 0x5f, 0xf9, 0x0a, 0xb2, 0x64, 0xce, 0xca, 0x29, 0x2b, 0xd7, 0xeb, 0x8f, 0xd4, 0xfa, - 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xfd, 0x56, 0x8b, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x47, 0xf8, 0xf0, 0x41, 0x5c, 0x22, - 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0xd6, 0x58, 0x97, 0x12, 0x55, 0x8d, 0x14, 0xa4, 0x83, 0x67, 0x24, - 0xab, 0xd6, 0xe8, 0x6a, 0xd6, 0x6f, 0xb5, 0x0a, 0x24, 0xe3, 0x6c, 0x58, 0x8c, 0x30, 0xc7, 0x25, 0x5c, 0xa6, 0xee, - 0xae, 0xc3, 0x82, 0x35, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x49, 0x37, 0xe1, 0xee, 0xa6, 0x01, 0x91, - 0xd8, 0x07, 0x64, 0x61, 0x81, 0xac, 0x3c, 0x90, 0x85, 0x01, 0xb2, 0x42, 0x83, 0x05, 0x04, 0x6d, 0x52, 0x28, 0xdd, - 0xa1, 0xe8, 0xcd, 0xf0, 0xa2, 0xce, 0x75, 0x05, 0x73, 0x13, 0xe1, 0xc2, 0x2d, 0x07, 0xb8, 0xb1, 0xb8, 0xb9, 0x2b, - 0xb2, 0x8a, 0x22, 0x13, 0x69, 0x17, 0xdf, 0x99, 0x3f, 0xc9, 0x1d, 0xbe, 0xb7, 0x3f, 0xee, 0x03, 0x65, 0xd2, 0x87, - 0x86, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xf9, 0xee, 0x9c, 0xb2, 0xe1, - 0x30, 0x44, 0x8b, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xfb, 0xef, 0x11, 0x1a, 0x08, 0x88, 0x66, 0xe4, 0x4e, 0xb6, 0x76, - 0x17, 0xb5, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0xd4, 0x51, 0xd6, 0x1a, - 0xc3, 0x30, 0x83, 0xaa, 0xc3, 0x7f, 0x5c, 0xaf, 0xb6, 0x83, 0x2d, 0x19, 0xa8, 0x0a, 0x13, 0xe9, 0x06, 0xd9, 0x87, - 0xd8, 0x18, 0x61, 0x47, 0x47, 0x6c, 0x28, 0x46, 0xc1, 0xcb, 0x6a, 0xb5, 0x05, 0x89, 0x0e, 0x17, 0x2e, 0xce, 0x20, - 0xda, 0xfd, 0x7a, 0x6d, 0xff, 0x92, 0x5f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0x67, 0xac, 0xd8, 0x2f, 0x8b, 0x25, - 0x5a, 0x7e, 0x00, 0xcb, 0x3e, 0x17, 0xbb, 0x90, 0xbb, 0xa9, 0x76, 0x2b, 0x17, 0x1c, 0xa3, 0x51, 0x08, 0x22, 0x07, - 0xd7, 0x47, 0x1a, 0x5e, 0xe8, 0x30, 0xaf, 0x11, 0x01, 0xb8, 0x50, 0x55, 0x20, 0x57, 0x38, 0x52, 0x12, 0xb0, 0xf4, - 0x36, 0x74, 0x12, 0x7e, 0x34, 0xa9, 0xa4, 0x63, 0x21, 0x01, 0x0a, 0x1c, 0x99, 0xcb, 0x79, 0x13, 0xa8, 0x9f, 0xa1, - 0x3d, 0x44, 0x2e, 0x30, 0xa1, 0x69, 0xca, 0x96, 0x2e, 0xa2, 0x56, 0x34, 0x97, 0x4b, 0xc5, 0x96, 0x0b, 0x38, 0xdf, - 0xab, 0xb4, 0xac, 0xe0, 0xd9, 0xe7, 0x66, 0x0a, 0x18, 0x44, 0xde, 0xe9, 0x39, 0x13, 0xcb, 0xc8, 0xcd, 0xf3, 0xb5, - 0x15, 0xf7, 0xdf, 0xbe, 0xc2, 0x1f, 0x49, 0xef, 0xf8, 0x35, 0xfe, 0x8b, 0x92, 0x8f, 0xad, 0xd7, 0x78, 0xca, 0x89, - 0xe5, 0x0d, 0x92, 0xb7, 0x6f, 0x6e, 0x5e, 0xbd, 0x7f, 0xf5, 0xf1, 0xf9, 0xa7, 0x57, 0xaf, 0x5f, 0xbc, 0x7a, 0xfd, - 0xea, 0xfd, 0xaf, 0xf8, 0x5f, 0x94, 0xbc, 0x3e, 0xe9, 0x5e, 0x76, 0xf0, 0x07, 0xf2, 0xfa, 0xa4, 0x87, 0xef, 0x34, - 0x79, 0x7d, 0x72, 0x86, 0x67, 0x8a, 0xbc, 0x3e, 0xee, 0x9d, 0x9c, 0xe2, 0xa5, 0xb6, 0x4d, 0x16, 0x72, 0xda, 0xed, - 0xe0, 0xbf, 0xdc, 0x17, 0x88, 0xf7, 0x81, 0x1b, 0x0e, 0xdb, 0x32, 0x7e, 0x30, 0x65, 0xe8, 0x58, 0x19, 0x43, 0x94, - 0xab, 0x00, 0x9d, 0x72, 0x15, 0xa2, 0x93, 0x0d, 0x25, 0x0d, 0x36, 0x8c, 0x80, 0x56, 0x9c, 0xb8, 0x76, 0xf8, 0x49, - 0x97, 0x9d, 0x02, 0x7d, 0xe2, 0x95, 0x70, 0x5c, 0xa9, 0x70, 0xba, 0x4e, 0x8b, 0x31, 0x29, 0xa4, 0x2c, 0xe3, 0x25, - 0x30, 0x02, 0x46, 0x6b, 0xc1, 0x4f, 0xaa, 0x98, 0x55, 0xe2, 0x8a, 0x74, 0x07, 0xdd, 0x54, 0x5c, 0x91, 0xde, 0xa0, - 0x07, 0x7f, 0xce, 0x07, 0xe7, 0x69, 0xb7, 0x83, 0x8e, 0x83, 0x71, 0xfc, 0xd0, 0x40, 0xeb, 0xe1, 0x08, 0xbb, 0x2e, - 0xd4, 0x5f, 0xa5, 0xf6, 0x2a, 0x3d, 0xe1, 0xd4, 0xb1, 0xdd, 0xbe, 0xb8, 0x62, 0x46, 0x0f, 0xcb, 0xbf, 0x03, 0xd4, - 0x36, 0x6e, 0x35, 0xd5, 0xc6, 0x71, 0xbf, 0xf8, 0x89, 0x40, 0x8d, 0xc0, 0x38, 0x31, 0x5b, 0x77, 0x10, 0x30, 0x8d, - 0x26, 0x1b, 0xcc, 0x81, 0x12, 0x25, 0x4b, 0xed, 0x83, 0xfb, 0xab, 0xb6, 0x44, 0xc9, 0x42, 0x2e, 0xe2, 0x86, 0xaa, - 0xe1, 0xa7, 0xc0, 0xcc, 0xf1, 0x90, 0xab, 0xd7, 0xf4, 0x75, 0xdc, 0xe0, 0x79, 0x42, 0xd6, 0x2e, 0xdc, 0x16, 0xff, - 0x74, 0x56, 0x14, 0x0d, 0x70, 0x55, 0x80, 0xf5, 0xa3, 0x6a, 0xeb, 0x2b, 0x78, 0xc5, 0x90, 0xb5, 0xf4, 0x35, 0x09, - 0xa8, 0xe7, 0xcf, 0x95, 0x19, 0x57, 0xa5, 0x8c, 0xf6, 0x8a, 0x68, 0x63, 0x16, 0xe4, 0x15, 0xd1, 0x57, 0xca, 0x00, - 0x41, 0x12, 0x3e, 0x14, 0x23, 0x38, 0xf0, 0xed, 0x00, 0xa5, 0xa1, 0x73, 0xa0, 0x56, 0xaa, 0xcd, 0x84, 0xcc, 0xa7, - 0x09, 0xd1, 0x00, 0x9a, 0xa7, 0x5a, 0x05, 0x65, 0x3e, 0xb1, 0x44, 0xc1, 0xd0, 0x7f, 0x0b, 0x37, 0xc0, 0x71, 0x6c, - 0x50, 0x31, 0xb4, 0xab, 0x11, 0xcd, 0xfc, 0xee, 0x65, 0xe7, 0xe4, 0x75, 0x90, 0xbf, 0x54, 0xde, 0xde, 0xe3, 0xcf, - 0x80, 0x92, 0xdb, 0xa0, 0x62, 0x5d, 0xec, 0xe3, 0xc1, 0xf5, 0x43, 0x80, 0x1c, 0x6b, 0x74, 0x62, 0x1e, 0x74, 0xec, - 0x23, 0x7d, 0x4c, 0xba, 0x1d, 0x08, 0xe2, 0xb6, 0x87, 0xf2, 0xfd, 0xbc, 0x05, 0x53, 0x9d, 0xdc, 0xb5, 0x81, 0x56, - 0xc3, 0x1b, 0x4f, 0xf7, 0x6d, 0x9e, 0xdc, 0x63, 0x15, 0xe0, 0x0c, 0x3b, 0x66, 0x2d, 0x71, 0x2c, 0x90, 0x0b, 0x7e, - 0x6b, 0x37, 0x80, 0xa6, 0xa2, 0x67, 0xdf, 0x1a, 0xf4, 0xc6, 0x51, 0x57, 0xed, 0xe4, 0xfc, 0xf8, 0xf5, 0xd1, 0x51, - 0x2c, 0x5b, 0xe4, 0x23, 0xc2, 0x2b, 0x0a, 0x36, 0xdb, 0xe0, 0x7b, 0xc7, 0x2d, 0x13, 0x9f, 0xaa, 0x80, 0x3a, 0x4e, - 0x54, 0xe3, 0x58, 0xab, 0x3b, 0xab, 0x76, 0x83, 0x1f, 0x53, 0x0f, 0xb5, 0x82, 0x34, 0x3b, 0xba, 0x5e, 0x03, 0xca, - 0x0d, 0x47, 0x39, 0xd8, 0x96, 0xad, 0xbf, 0x28, 0xfa, 0xee, 0x63, 0xfb, 0x75, 0x30, 0xe1, 0x86, 0x69, 0xd2, 0xc7, - 0xd6, 0x47, 0xf4, 0xdd, 0xc7, 0xc0, 0xd5, 0x91, 0xd7, 0xec, 0x89, 0xe7, 0x46, 0x7e, 0xb6, 0x5c, 0xe9, 0xcf, 0x20, - 0xd9, 0x97, 0xe4, 0x67, 0xc0, 0x72, 0x4a, 0x7e, 0x8e, 0x65, 0x1b, 0x42, 0x40, 0x92, 0x9f, 0xe3, 0x12, 0x7e, 0x14, - 0xe4, 0xe7, 0x18, 0xb0, 0x1d, 0xcf, 0xcc, 0x8f, 0xb2, 0x02, 0x06, 0xb8, 0xd7, 0x49, 0xeb, 0x65, 0x57, 0xae, 0xd7, - 0xe2, 0xe8, 0x48, 0xda, 0x5f, 0xf4, 0x3a, 0x3b, 0x3a, 0x2a, 0xae, 0x66, 0x75, 0xdf, 0x5c, 0xef, 0xa3, 0x2f, 0x06, - 0xa1, 0x70, 0x60, 0x9a, 0xc6, 0xc3, 0x19, 0x7f, 0xdf, 0xa0, 0xac, 0xd0, 0x40, 0xfb, 0xb4, 0xf7, 0xf0, 0xe2, 0x12, - 0xc3, 0xbf, 0x0f, 0x83, 0x82, 0x3a, 0xf3, 0x13, 0x23, 0x5d, 0xd6, 0xbe, 0xa8, 0xeb, 0x5c, 0x07, 0xf8, 0x8c, 0x19, - 0x6a, 0x8b, 0xa3, 0x23, 0x7e, 0x15, 0xe0, 0x32, 0x66, 0xa8, 0x15, 0x58, 0xec, 0x3d, 0xae, 0xec, 0xc9, 0x0c, 0xd7, - 0x04, 0x8f, 0xfb, 0xf2, 0x61, 0x39, 0xba, 0xd2, 0x8e, 0x9a, 0x84, 0x21, 0xc0, 0x15, 0xe9, 0xb8, 0x4d, 0xd6, 0x17, - 0x6d, 0x75, 0xdd, 0xed, 0x23, 0x49, 0x54, 0x4b, 0x5c, 0x5f, 0x77, 0x31, 0xa8, 0xe4, 0x07, 0x8a, 0xc8, 0x54, 0x10, - 0xef, 0xa6, 0xb8, 0x2a, 0x64, 0xaa, 0xf0, 0x8c, 0xa7, 0xc2, 0xcb, 0xd9, 0x6f, 0xbc, 0xf5, 0xb4, 0x71, 0x1c, 0x35, - 0x3d, 0x33, 0x2c, 0x06, 0xaa, 0x72, 0x78, 0x84, 0x4d, 0xaa, 0x46, 0xf0, 0x76, 0x62, 0x85, 0x79, 0xcc, 0x7a, 0xf9, - 0x31, 0x88, 0x4d, 0xad, 0x5a, 0x5d, 0xc8, 0x84, 0xcf, 0x4d, 0xaa, 0x60, 0xa0, 0xa6, 0xf0, 0x15, 0x84, 0x3d, 0xcc, - 0x6a, 0xc3, 0x6c, 0xdf, 0x30, 0x14, 0x10, 0x50, 0xe0, 0x9a, 0xb0, 0x40, 0x82, 0xe7, 0x59, 0x83, 0x70, 0x34, 0xc9, - 0x85, 0x9d, 0xdc, 0x95, 0x82, 0xee, 0xc4, 0xe8, 0x4a, 0xf7, 0x91, 0x68, 0xb5, 0x1c, 0xb7, 0x7d, 0x2d, 0xcc, 0x20, - 0xda, 0xdd, 0xd1, 0x35, 0xeb, 0x23, 0xd5, 0x6e, 0x57, 0x06, 0x90, 0xd7, 0x9d, 0xf5, 0x5a, 0x5d, 0xf9, 0x46, 0x06, - 0xfe, 0x1c, 0x37, 0x7c, 0x97, 0x17, 0x3c, 0x7f, 0x93, 0x64, 0x18, 0x01, 0x55, 0x05, 0x3e, 0x5b, 0x2e, 0x22, 0x1c, - 0x99, 0x67, 0xf5, 0xe0, 0xaf, 0x79, 0x0e, 0x2d, 0xc2, 0x91, 0x7b, 0x69, 0x2f, 0x1a, 0xd5, 0x83, 0x15, 0x59, 0x15, - 0x24, 0x9e, 0x27, 0x9f, 0x80, 0x71, 0xd0, 0x7f, 0x2a, 0xb4, 0xaa, 0x7f, 0x27, 0x85, 0x0b, 0x97, 0xa2, 0xfc, 0xe3, - 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, 0x8d, 0xd7, 0x27, 0xbb, 0xee, - 0xd1, 0xf3, 0x55, 0xd5, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0xbf, 0xc9, 0xbd, 0x2f, 0x20, 0x47, 0x9f, 0xa4, 0x78, - 0x46, 0x35, 0x8d, 0x5a, 0x0f, 0x8c, 0xe1, 0x9b, 0x95, 0xb3, 0xfa, 0x5f, 0x1b, 0x07, 0xfb, 0x8f, 0xba, 0x87, 0x00, - 0x16, 0x8d, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, 0x3c, 0xfc, 0x18, 0x29, 0xb8, - 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x86, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, 0xe3, 0xef, 0x06, 0x85, 0x5c, - 0xf7, 0x42, 0x35, 0x89, 0x69, 0xdd, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xea, 0xde, 0x8d, 0x84, 0x52, 0xbf, - 0x6b, 0x67, 0xde, 0x26, 0x6d, 0x77, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, 0xbc, 0x87, 0x55, 0xd0, 0xae, - 0x6b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xaf, 0xdc, 0xcb, 0x74, 0x7c, 0x28, 0x47, 0x9b, 0xea, 0x9d, 0xba, - 0x00, 0x0f, 0xea, 0x91, 0xaa, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x0d, 0xfd, 0x10, 0xff, 0x1b, 0x0e, 0xf8, 0x1a, - 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0x7e, 0x2f, 0x43, 0x47, 0xdd, 0xa6, 0x4e, 0xc5, - 0xfa, 0xc2, 0x36, 0x15, 0x2b, 0x55, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, 0x59, 0xf7, 0xe8, 0xd4, 0x63, - 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x17, 0x25, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x0c, 0x5f, 0x55, 0x1e, 0xc2, 0x3d, - 0x61, 0xc5, 0x73, 0x56, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, 0x3a, 0x16, 0x26, 0xb6, 0x84, - 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, - 0x66, 0x41, 0x5f, 0xfb, 0xfa, 0x10, 0xf5, 0x94, 0x07, 0xb1, 0xd1, 0xf7, 0xbe, 0xe7, 0x73, 0x26, 0x97, 0xf0, 0x78, - 0x13, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, 0x0b, 0x40, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x2b, - 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0x83, 0x08, 0xbc, 0x88, 0x40, 0x84, 0x22, 0x24, 0x62, 0x22, 0x8f, - 0x06, 0x91, 0x71, 0xc9, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, 0xdc, 0x11, 0x9e, 0xaa, 0x9a, 0x88, 0x85, 0x35, 0x75, 0x50, - 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa4, 0x57, 0x83, 0x90, 0x66, 0xdb, 0x82, 0xb2, 0xde, 0x52, 0x17, 0x60, 0x49, 0x8c, - 0xe9, 0x2d, 0x4f, 0x3e, 0x01, 0x37, 0xc7, 0x72, 0x57, 0x74, 0xc5, 0x6f, 0x40, 0x3d, 0x9d, 0x96, 0xf8, 0x93, 0x61, - 0xd8, 0xf2, 0x94, 0x6e, 0x08, 0xc7, 0x19, 0x29, 0x13, 0x7a, 0x07, 0xb1, 0x35, 0xe6, 0x5c, 0xa4, 0x05, 0x9e, 0xd3, - 0xbb, 0x74, 0x86, 0xe7, 0x5c, 0x3c, 0xb3, 0xcb, 0x9e, 0xe6, 0x90, 0xe4, 0x3f, 0x96, 0x1b, 0x62, 0x9e, 0x06, 0xfb, - 0xa0, 0x58, 0xf9, 0x04, 0x78, 0x15, 0x15, 0xa3, 0x7e, 0x6e, 0x6c, 0xca, 0xb9, 0xae, 0x8d, 0xd7, 0xdf, 0xe8, 0x98, - 0xe2, 0x0c, 0x17, 0x28, 0x29, 0x24, 0x66, 0x03, 0x91, 0xbe, 0x81, 0xb8, 0xda, 0x19, 0xb6, 0xcf, 0x8a, 0xf1, 0x3b, - 0x56, 0xbc, 0x90, 0xe5, 0x47, 0xb3, 0xe5, 0x0b, 0x04, 0x85, 0xc0, 0x45, 0x45, 0xb4, 0xe1, 0x76, 0x6f, 0x39, 0x90, - 0x75, 0x53, 0xf4, 0xce, 0x36, 0xe5, 0x86, 0x38, 0x83, 0x80, 0xc4, 0xc9, 0x8c, 0xb7, 0xba, 0x98, 0x0d, 0x3a, 0xdf, - 0x68, 0x74, 0x86, 0xaa, 0x92, 0x08, 0xc3, 0x5a, 0xb5, 0x55, 0x2a, 0x89, 0x68, 0x2b, 0x27, 0xe1, 0xad, 0x0c, 0xb0, - 0x53, 0x85, 0x33, 0xb9, 0x14, 0x3a, 0x95, 0x01, 0xde, 0x64, 0xf5, 0xe6, 0x5a, 0xdd, 0x59, 0x88, 0x69, 0x7c, 0x6f, - 0x7f, 0x30, 0xfc, 0xc9, 0xa8, 0xf8, 0xdf, 0x81, 0x61, 0x8f, 0x4a, 0x05, 0xc0, 0x0f, 0x0c, 0x67, 0x01, 0x72, 0x96, - 0x9f, 0xbc, 0x03, 0xf0, 0x59, 0x16, 0xf2, 0x1e, 0x52, 0x99, 0x49, 0xbd, 0x87, 0x54, 0x06, 0xa9, 0xc6, 0xa3, 0xfe, - 0x50, 0xd4, 0xca, 0xa2, 0xb0, 0x41, 0xa2, 0x70, 0xa5, 0x0e, 0x96, 0x44, 0x24, 0xd0, 0xae, 0x11, 0xe5, 0xe6, 0x5c, - 0x40, 0x68, 0x45, 0x68, 0xdc, 0x7e, 0xd3, 0x3b, 0xf8, 0xbe, 0xb7, 0xf9, 0xcc, 0xe7, 0xdf, 0xdb, 0x7c, 0xd3, 0x91, - 0xc7, 0xf8, 0xe6, 0x6d, 0xa7, 0xb1, 0x8c, 0x97, 0x0e, 0x6b, 0x3f, 0x54, 0x0f, 0xd9, 0x74, 0xcc, 0x83, 0xe1, 0xa4, - 0x8b, 0xe7, 0x01, 0x52, 0xb6, 0x6b, 0x1e, 0xae, 0x87, 0xbb, 0x9d, 0xe3, 0x98, 0xb7, 0x49, 0x17, 0xa1, 0x63, 0x27, - 0x5c, 0x89, 0xd8, 0x48, 0x4e, 0xc7, 0x1f, 0x4f, 0xe0, 0xee, 0x65, 0xac, 0xb6, 0x7c, 0xa5, 0x6c, 0xb5, 0x76, 0xb7, - 0x73, 0xcc, 0xf7, 0x56, 0x69, 0x75, 0xf1, 0x9c, 0x91, 0x15, 0x78, 0xa0, 0xd1, 0xd2, 0xaa, 0x1a, 0xc0, 0x65, 0xf5, - 0x95, 0xf8, 0x79, 0x49, 0x73, 0xf3, 0x7d, 0x6c, 0x53, 0xde, 0x2c, 0xb5, 0x4f, 0x6a, 0x73, 0x18, 0x44, 0x0f, 0xb9, - 0x92, 0x41, 0x4e, 0xcc, 0x4f, 0x48, 0x72, 0x8e, 0xae, 0xba, 0x83, 0xe4, 0xfc, 0x98, 0x1f, 0xf3, 0x14, 0x78, 0xd8, - 0xb8, 0xed, 0x2b, 0xb4, 0xbb, 0xbe, 0xce, 0xd3, 0xe5, 0x98, 0x67, 0xae, 0xf9, 0xba, 0x83, 0x2a, 0xd5, 0xce, 0x11, - 0xb2, 0x00, 0xc5, 0x7c, 0x2f, 0x41, 0x76, 0xb3, 0x9b, 0x63, 0x9e, 0x42, 0x3f, 0x50, 0xab, 0x67, 0x6b, 0x55, 0x83, - 0xfb, 0x79, 0x09, 0x08, 0xe6, 0x3b, 0x6a, 0xcc, 0xc5, 0xa6, 0xb7, 0xe3, 0xba, 0xb3, 0x63, 0x5e, 0x8f, 0x30, 0x2c, - 0xb3, 0xdb, 0x9f, 0x9f, 0x5a, 0xdd, 0xe5, 0x71, 0x00, 0x91, 0x9f, 0x97, 0x5c, 0x84, 0x9d, 0x86, 0xdd, 0xba, 0x9c, - 0xb0, 0xd3, 0xe6, 0x2c, 0x83, 0x22, 0xbb, 0xbd, 0xee, 0xcc, 0xb4, 0x39, 0xdb, 0x1b, 0x70, 0x24, 0x84, 0x49, 0x99, - 0x95, 0xce, 0xa4, 0x8a, 0xf9, 0xf1, 0x07, 0xe4, 0x5a, 0x7f, 0xb3, 0xd4, 0x3e, 0xbf, 0x42, 0x04, 0xc8, 0xae, 0xbb, - 0xae, 0xaa, 0x43, 0x1f, 0x55, 0x13, 0xaf, 0x8f, 0x79, 0xb0, 0x72, 0xcf, 0xef, 0x16, 0x32, 0xf5, 0xf8, 0x3a, 0xe8, - 0xa4, 0x3b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, 0xbb, 0xbd, 0x83, 0x92, 0xe1, 0xc4, 0x7d, 0xe9, - 0x0f, 0xcc, 0x5e, 0x37, 0xf0, 0xab, 0xe4, 0x1c, 0xa6, 0xbe, 0xdd, 0xc3, 0x71, 0x0f, 0xfa, 0x30, 0x70, 0xd8, 0x6e, - 0xd0, 0x67, 0xd6, 0x10, 0x79, 0xca, 0x4b, 0x8b, 0x67, 0xd7, 0xa4, 0x3b, 0xe0, 0xa9, 0xdb, 0x4c, 0x46, 0x34, 0xea, - 0xb6, 0x79, 0x30, 0x33, 0xc0, 0x2f, 0x57, 0x36, 0x2c, 0xe2, 0xd7, 0x29, 0x80, 0x92, 0x2f, 0x56, 0xaf, 0x4f, 0x0d, - 0xaf, 0x66, 0xc3, 0xe9, 0x76, 0xba, 0x5f, 0x37, 0xb8, 0xdd, 0xf5, 0xf0, 0x84, 0x87, 0x68, 0x2c, 0x5a, 0xfb, 0x89, - 0xcf, 0x81, 0x03, 0x4a, 0x3a, 0x0f, 0xcf, 0xc1, 0x85, 0xb2, 0x82, 0xe5, 0x6e, 0xb9, 0xf1, 0x4e, 0x39, 0x0b, 0x47, - 0x5b, 0x32, 0xe0, 0x0e, 0xb6, 0x21, 0x0a, 0x1d, 0x1c, 0xf7, 0x70, 0xd2, 0xed, 0xf6, 0xce, 0x71, 0x72, 0x76, 0x0e, - 0x03, 0x6d, 0x25, 0xe7, 0xc7, 0x63, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x4f, 0x20, 0x68, 0x55, 0x28, 0x5e, - 0xf3, 0xe3, 0x38, 0xee, 0x26, 0x0f, 0x3b, 0xdd, 0xf3, 0xcb, 0x16, 0x00, 0xa8, 0xed, 0x3e, 0x5c, 0x8d, 0x37, 0x4b, - 0xdd, 0xac, 0x52, 0x21, 0x7c, 0xb3, 0x5a, 0xcb, 0x57, 0x6b, 0x75, 0x37, 0xf5, 0x14, 0x7c, 0x55, 0x27, 0x9c, 0xdb, - 0x22, 0x5e, 0x69, 0x13, 0x6e, 0x8b, 0xd8, 0x0e, 0x24, 0x06, 0xe9, 0x3c, 0x39, 0xef, 0x9d, 0x23, 0x3b, 0x16, 0xed, - 0xf0, 0xa3, 0xda, 0x27, 0x3b, 0x45, 0x5a, 0x1a, 0x90, 0xa4, 0x9a, 0x9d, 0x5c, 0x82, 0x44, 0xcd, 0xc9, 0x75, 0xb7, - 0x3d, 0x67, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0xac, 0x56, 0xc1, 0x25, 0x05, 0x80, 0xb8, 0x02, 0xe3, 0xa2, 0x87, - 0xe7, 0x83, 0x87, 0xc9, 0xf9, 0x45, 0xcf, 0x12, 0x3d, 0x7e, 0xd5, 0x6b, 0xa4, 0x99, 0xa9, 0x27, 0xe7, 0x26, 0x0d, - 0xba, 0x4e, 0x1e, 0x9e, 0x43, 0x19, 0x97, 0x12, 0x96, 0x82, 0x60, 0x1b, 0x75, 0x31, 0x88, 0xb0, 0x91, 0x36, 0x72, - 0x2f, 0x1a, 0xd9, 0x97, 0x67, 0xa7, 0x0f, 0xcf, 0x43, 0xa8, 0x55, 0xb3, 0x30, 0x0b, 0xed, 0x26, 0xe2, 0x67, 0x07, - 0x4b, 0x8b, 0x8e, 0x93, 0xf3, 0x74, 0x67, 0x82, 0x76, 0xd3, 0x1c, 0x1b, 0x1c, 0x08, 0x14, 0x8e, 0xcf, 0x85, 0xd3, - 0x97, 0x04, 0xf7, 0x63, 0xb5, 0xa1, 0x49, 0xa8, 0x70, 0xf6, 0xf7, 0x94, 0xc1, 0x7b, 0x9a, 0xe1, 0x55, 0xe5, 0x53, - 0x2a, 0xbe, 0x50, 0xf5, 0x96, 0x42, 0x04, 0x11, 0x31, 0x8a, 0x5c, 0x7c, 0xf3, 0x66, 0xee, 0x3f, 0xc1, 0x45, 0x98, - 0x09, 0xb8, 0xd0, 0xf4, 0x4a, 0xd0, 0x9a, 0x17, 0xf8, 0x14, 0x3a, 0xd4, 0x9a, 0x61, 0x0d, 0x78, 0xea, 0x4c, 0x0a, - 0x42, 0xdd, 0xd6, 0x4b, 0xfe, 0xad, 0x72, 0x49, 0x75, 0x95, 0x9d, 0x9c, 0xa3, 0xc4, 0x5d, 0x96, 0x27, 0x5d, 0x94, - 0x04, 0x26, 0x24, 0xee, 0x48, 0x2e, 0x32, 0x32, 0x8c, 0xee, 0x22, 0x1c, 0xdd, 0x47, 0x38, 0xb2, 0x3e, 0xcc, 0xbf, - 0x80, 0x1f, 0x77, 0x84, 0x23, 0xeb, 0xca, 0x1c, 0xe1, 0x48, 0x33, 0x01, 0x81, 0xc5, 0xa2, 0x11, 0x9e, 0x41, 0x69, - 0xe3, 0x59, 0x5d, 0x95, 0x7e, 0xea, 0xbf, 0x2a, 0xd7, 0x6b, 0x9b, 0x12, 0x48, 0x99, 0xb9, 0xd9, 0xa1, 0xf6, 0x61, - 0xec, 0x88, 0x7a, 0x66, 0x3d, 0xc2, 0x20, 0x80, 0xd0, 0x7b, 0xff, 0xb0, 0x5e, 0x1d, 0x93, 0x84, 0x9d, 0xc2, 0x4a, - 0x83, 0x2b, 0x7a, 0x14, 0x9e, 0x61, 0x11, 0x9e, 0x08, 0x5f, 0x18, 0xc4, 0x0a, 0xff, 0xbb, 0x90, 0x72, 0xe1, 0x7f, - 0x6b, 0x59, 0xfd, 0x82, 0xe7, 0x58, 0x9c, 0x45, 0x0b, 0x58, 0x6e, 0xd9, 0x10, 0x48, 0x63, 0xd6, 0x1c, 0xc1, 0xa7, - 0x89, 0x0b, 0x53, 0x07, 0x12, 0xe1, 0x27, 0x23, 0x50, 0x79, 0xf9, 0xf0, 0x93, 0x0d, 0x99, 0x64, 0x3e, 0x21, 0x66, - 0x1a, 0x84, 0x45, 0x96, 0x70, 0xa1, 0x31, 0x2d, 0x99, 0x52, 0x91, 0x8d, 0x25, 0x18, 0x49, 0xe1, 0x1f, 0x87, 0xf4, - 0x29, 0x13, 0x11, 0x99, 0x0e, 0x9b, 0xb3, 0xb5, 0xe2, 0x70, 0x21, 0x4b, 0x95, 0xda, 0x97, 0x62, 0x3c, 0x18, 0x17, - 0xd5, 0x33, 0x8c, 0xe9, 0x2c, 0xdb, 0x60, 0x7b, 0x87, 0x5d, 0x15, 0x72, 0x57, 0xda, 0x61, 0xa9, 0x22, 0xdb, 0x7c, - 0x6d, 0x42, 0xaa, 0x31, 0xa3, 0x60, 0xa2, 0xf5, 0x80, 0xea, 0xc0, 0x1d, 0x50, 0xd8, 0x06, 0xa5, 0x49, 0x57, 0x55, - 0xc9, 0x74, 0x55, 0x2d, 0xc3, 0x59, 0xa7, 0xb3, 0xd9, 0xe0, 0x92, 0x99, 0x40, 0x2e, 0x7b, 0x4b, 0x40, 0xbe, 0x9a, - 0xc9, 0xdb, 0x20, 0x57, 0xa5, 0xd5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, 0x5f, 0xb8, 0xe2, 0x00, - 0x4f, 0x37, 0xbb, 0xb1, 0x94, 0x05, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x3c, 0x67, 0xfb, 0xdb, 0x04, - 0x33, 0xe6, 0xff, 0xac, 0x45, 0x8f, 0x40, 0x96, 0xdd, 0x33, 0xa8, 0x03, 0x8b, 0xb8, 0x86, 0x0e, 0x42, 0x19, 0x7c, - 0x19, 0xe2, 0x66, 0x41, 0xef, 0xe5, 0x52, 0x03, 0x5c, 0x96, 0x5a, 0xbe, 0x75, 0xe1, 0x10, 0x0e, 0x3b, 0xd8, 0x47, - 0x46, 0x58, 0x41, 0xc8, 0x80, 0x0e, 0xb6, 0x11, 0x31, 0x3a, 0xd8, 0x05, 0x2a, 0xe8, 0x60, 0x13, 0x9e, 0xa2, 0xb3, - 0xa9, 0x62, 0x9b, 0xdd, 0x57, 0x4f, 0x6a, 0xd6, 0x9b, 0x60, 0xe2, 0xa4, 0x43, 0x4d, 0x74, 0x70, 0x7b, 0xc8, 0x08, - 0x6f, 0x7d, 0x7f, 0xf3, 0xe6, 0xb5, 0x8b, 0x5c, 0xcd, 0x27, 0xe0, 0xb2, 0xe9, 0x54, 0x63, 0xf7, 0x36, 0xc4, 0x7c, - 0xad, 0x28, 0xb5, 0xc2, 0xa9, 0x09, 0xf6, 0x29, 0x74, 0x91, 0xd8, 0xcb, 0x8b, 0x17, 0xb2, 0x9c, 0x53, 0x7b, 0x63, - 0x84, 0xef, 0x95, 0x7b, 0x7c, 0xde, 0xbc, 0x6f, 0x53, 0x4f, 0xf2, 0xfd, 0xf6, 0x55, 0xc4, 0x24, 0x33, 0xf2, 0x2b, - 0x68, 0x03, 0x4c, 0x65, 0x3f, 0x70, 0x56, 0x12, 0x17, 0xff, 0x3f, 0x20, 0x2f, 0xef, 0x2c, 0x75, 0x89, 0xa2, 0x16, - 0x37, 0xf8, 0xc9, 0xca, 0x5a, 0xc7, 0xc5, 0xcd, 0xfb, 0x91, 0xa4, 0xe3, 0xc4, 0x8b, 0xa8, 0x13, 0x35, 0xdf, 0xde, - 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0x29, 0x24, 0x88, 0x1e, 0xd5, 0x33, 0x7f, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, - 0xdd, 0xf5, 0x74, 0xb6, 0xa8, 0xd5, 0x89, 0xd5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, 0x0e, 0x12, 0x59, - 0xa5, 0x3d, 0xf4, 0xb9, 0xa8, 0x1f, 0x17, 0x57, 0x5d, 0xd6, 0x3e, 0x5b, 0xaf, 0x8b, 0xeb, 0x2e, 0xeb, 0x9e, 0xdb, - 0x67, 0xf7, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x13, 0x9e, 0x45, 0xa0, 0x9d, 0x5d, 0x64, 0x26, 0x9c, 0x82, 0x97, 0xa6, - 0xc9, 0x52, 0xd7, 0x7d, 0x49, 0x30, 0x2e, 0x25, 0x56, 0x8f, 0x5f, 0xa2, 0x41, 0x37, 0xdd, 0x75, 0x95, 0x6e, 0x77, - 0x8f, 0x83, 0x0b, 0x97, 0x12, 0xe1, 0x1e, 0x84, 0x3c, 0x00, 0xfd, 0xee, 0x4a, 0x80, 0x69, 0x10, 0xa0, 0xb2, 0x02, - 0x91, 0x96, 0xcf, 0x97, 0xf3, 0x17, 0x25, 0x35, 0xcb, 0xf0, 0x8c, 0x4f, 0xb9, 0x56, 0x29, 0x05, 0xe9, 0x76, 0x5f, - 0xfa, 0x66, 0xbf, 0x04, 0x95, 0x35, 0xe2, 0xef, 0x26, 0x9a, 0x67, 0x9f, 0x95, 0x5b, 0x38, 0x84, 0xcd, 0xca, 0x0a, - 0x9c, 0xa1, 0x0d, 0x2e, 0xe4, 0x94, 0x96, 0x5c, 0xcf, 0xe6, 0xff, 0xd1, 0xea, 0xb0, 0xa1, 0x1e, 0x99, 0x0b, 0x2b, - 0x00, 0x09, 0x15, 0xf9, 0x7a, 0xcd, 0x4f, 0xbe, 0x7d, 0x9f, 0xe4, 0x7d, 0xc2, 0xbb, 0xb8, 0x87, 0x4f, 0xf1, 0x39, - 0xee, 0x76, 0x70, 0xf7, 0x1c, 0xae, 0xee, 0xb3, 0x62, 0x99, 0x33, 0x15, 0xc3, 0xfb, 0x6b, 0xfa, 0x3a, 0xb9, 0x3c, - 0xae, 0x5f, 0x1d, 0x28, 0x13, 0x87, 0x2e, 0x41, 0xf0, 0x7b, 0x17, 0x35, 0x30, 0x8a, 0xc2, 0x90, 0x75, 0x8b, 0x50, - 0x75, 0x52, 0xe9, 0x17, 0xae, 0x4f, 0x07, 0x60, 0xcf, 0x6d, 0x57, 0xb6, 0x0d, 0x66, 0xdf, 0xf6, 0x67, 0x5a, 0xff, - 0x6c, 0xeb, 0x0a, 0x31, 0x3c, 0xf4, 0x6a, 0xf4, 0x40, 0xd7, 0xa4, 0x7b, 0x74, 0x04, 0x56, 0x47, 0xc1, 0x6c, 0xb8, - 0x8d, 0x7e, 0xc0, 0xdb, 0x8d, 0x34, 0x08, 0x56, 0x00, 0xc6, 0x9d, 0x0f, 0x38, 0x59, 0x59, 0xd8, 0x6a, 0xa0, 0xc2, - 0xac, 0x0c, 0xe3, 0xea, 0x85, 0xa4, 0xc2, 0x08, 0xd1, 0x70, 0x84, 0xb9, 0x60, 0x28, 0x87, 0x1d, 0x2c, 0x27, 0x13, - 0xc5, 0x34, 0x1c, 0x1d, 0x25, 0xfb, 0xc2, 0x4a, 0x65, 0x4e, 0x91, 0x31, 0x9b, 0x72, 0xf1, 0x58, 0xff, 0xc6, 0x4a, - 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, 0x2a, 0x46, 0x38, 0x2b, 0xf8, 0x02, 0xaa, 0x4e, 0x4b, 0x70, 0xfa, 0x81, - 0xbf, 0x3c, 0x4f, 0xc3, 0x36, 0x81, 0x7c, 0xfd, 0x62, 0x63, 0xba, 0xe0, 0xbc, 0xa4, 0xb7, 0x6f, 0xc4, 0x53, 0xd8, - 0x51, 0x8f, 0x4b, 0x46, 0x21, 0x1b, 0x92, 0xde, 0x43, 0x53, 0xf0, 0x01, 0x6d, 0xfe, 0x68, 0x00, 0x97, 0x5e, 0x9a, - 0x0f, 0x5b, 0xd1, 0xc7, 0x6e, 0x4c, 0xaa, 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xeb, 0x4c, 0x1b, 0x85, 0xaa, 0x9a, 0xc2, - 0x06, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x72, 0xaa, 0x66, 0xe9, 0x70, 0x64, 0xfe, 0xbe, 0xb1, 0x25, 0x3b, 0xd8, 0x45, - 0x9c, 0xd9, 0x60, 0xf3, 0x70, 0x6a, 0x50, 0xbe, 0x8b, 0xe1, 0x1e, 0x16, 0x5e, 0xef, 0x6c, 0x90, 0xcf, 0x33, 0x4f, - 0x36, 0xcf, 0x36, 0x1b, 0x33, 0x10, 0x95, 0x82, 0x1e, 0xe8, 0x9d, 0xdf, 0x36, 0x1d, 0xd8, 0x1e, 0xd5, 0xd7, 0x79, - 0x07, 0xcf, 0x39, 0x3c, 0x46, 0xea, 0xdb, 0xbb, 0xd1, 0xa5, 0xfc, 0xec, 0x40, 0xd2, 0x09, 0x52, 0xec, 0x74, 0x82, - 0xce, 0x4e, 0x71, 0x30, 0x72, 0xa0, 0xe7, 0x37, 0x9f, 0x2d, 0xac, 0xfd, 0xef, 0xb7, 0x55, 0x41, 0x13, 0x4f, 0xa7, - 0x9a, 0x50, 0xe6, 0xcf, 0xcf, 0x07, 0x3c, 0xa9, 0x51, 0xc1, 0xbd, 0xe2, 0x05, 0x7b, 0xda, 0x06, 0xfa, 0x9c, 0xd3, - 0x3f, 0xed, 0x0f, 0x1b, 0xc3, 0xa7, 0xd2, 0xb2, 0x65, 0xa5, 0x54, 0xea, 0xb1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, - 0x3f, 0x42, 0x17, 0xc0, 0xeb, 0xe7, 0xa5, 0x5c, 0x18, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, - 0x1c, 0xd4, 0xff, 0x74, 0x80, 0xfd, 0x8d, 0xaa, 0x92, 0x7e, 0xbc, 0x3d, 0x7b, 0xfc, 0x97, 0x12, 0xa2, 0xc6, 0x5b, - 0x3c, 0x4c, 0x1c, 0x3a, 0x55, 0xac, 0x59, 0xf5, 0x73, 0xa7, 0x24, 0x60, 0x58, 0xb3, 0x60, 0xc8, 0xc6, 0xed, 0x14, - 0xb7, 0x99, 0xff, 0x83, 0x0a, 0x06, 0x0b, 0xbe, 0x36, 0x92, 0x9a, 0x65, 0xf1, 0xdb, 0xa7, 0xc9, 0x7f, 0x35, 0x39, - 0xae, 0x43, 0xdd, 0x78, 0x29, 0x74, 0x6c, 0xa2, 0x34, 0x47, 0xe8, 0xe8, 0x68, 0x2b, 0x83, 0x4e, 0x00, 0xf0, 0xc8, - 0xb1, 0x5f, 0x7e, 0xf9, 0x3c, 0x3b, 0x66, 0x34, 0x8f, 0x65, 0x14, 0x32, 0x77, 0x9e, 0x9b, 0xb3, 0x13, 0x79, 0x46, - 0xd5, 0xcc, 0x17, 0x06, 0x38, 0x3e, 0xd9, 0x49, 0x05, 0x7c, 0x8f, 0x36, 0x7b, 0x26, 0xb0, 0xc5, 0x6f, 0xd9, 0x49, - 0xed, 0x2b, 0xe8, 0x17, 0x68, 0xb5, 0x8f, 0xa9, 0xdc, 0x5a, 0xe0, 0x68, 0x7b, 0x22, 0x7b, 0x87, 0xbe, 0x55, 0xa7, - 0x62, 0x3d, 0x5e, 0xed, 0x37, 0xfa, 0x92, 0x62, 0x5f, 0x72, 0x4d, 0xdb, 0xc6, 0xac, 0x7e, 0x2d, 0x58, 0xd7, 0xa6, - 0x4e, 0xf5, 0x35, 0x6f, 0x6d, 0x69, 0x53, 0xd9, 0x25, 0xd9, 0xbb, 0x2d, 0x16, 0x5e, 0x85, 0xb7, 0x5a, 0xd5, 0x45, - 0x28, 0xd8, 0x63, 0x89, 0x51, 0x9f, 0x13, 0xb8, 0x5e, 0x58, 0xaf, 0x63, 0xf8, 0xb3, 0x6f, 0x0c, 0xfb, 0x4c, 0x97, - 0x3e, 0xf0, 0x2d, 0x7e, 0x25, 0x08, 0x58, 0xec, 0xec, 0x20, 0xc1, 0xba, 0xcb, 0x0d, 0x1a, 0x8e, 0x13, 0xff, 0x05, - 0xcf, 0x65, 0x6b, 0xef, 0x72, 0x30, 0xcf, 0xbe, 0xf2, 0xc4, 0x5e, 0xc5, 0x5a, 0x36, 0xa2, 0xdd, 0x6f, 0x49, 0x30, - 0xc4, 0x6e, 0x4a, 0xe7, 0xb8, 0x95, 0x74, 0x51, 0xe4, 0x8a, 0xd5, 0xe8, 0xff, 0xb5, 0x22, 0x99, 0xcd, 0xfc, 0xaf, - 0x8b, 0x8b, 0x0b, 0x97, 0xe2, 0x6c, 0xfe, 0x94, 0xf1, 0x80, 0x33, 0x09, 0xec, 0x0b, 0xcf, 0x98, 0xd1, 0x21, 0xbf, - 0x83, 0xa1, 0x10, 0x41, 0xae, 0x85, 0x63, 0x97, 0xe0, 0xb5, 0x47, 0xa0, 0x3c, 0xc0, 0xfe, 0x3d, 0xdb, 0x2a, 0xe7, - 0x9f, 0x8b, 0xf2, 0xe1, 0x94, 0xab, 0x06, 0xd9, 0x17, 0xf3, 0x39, 0xb4, 0x66, 0x32, 0xf0, 0x42, 0x42, 0x84, 0xed, - 0x6f, 0xc3, 0xd2, 0x3a, 0x4b, 0x19, 0x1c, 0x69, 0xb9, 0xcc, 0x66, 0x56, 0xf3, 0xef, 0x3e, 0x4c, 0x59, 0xf7, 0xd4, - 0x10, 0x44, 0xee, 0x22, 0x2b, 0x17, 0x15, 0x34, 0xfa, 0x47, 0x15, 0x00, 0xf4, 0xe0, 0x35, 0x5b, 0xb2, 0x7f, 0xe0, - 0x83, 0x3a, 0x05, 0x3e, 0x1e, 0x97, 0x9c, 0x16, 0xff, 0xc0, 0x07, 0x75, 0x20, 0x50, 0x70, 0x85, 0x34, 0xb1, 0x34, - 0xb1, 0x79, 0x56, 0x3b, 0x8d, 0x04, 0x50, 0xd0, 0x22, 0x32, 0x07, 0xd9, 0x4b, 0x17, 0xa3, 0x31, 0xe9, 0x61, 0x17, - 0x1c, 0xcc, 0x46, 0x84, 0xb5, 0x81, 0xd4, 0x21, 0x6e, 0x5d, 0x35, 0x1b, 0xf3, 0xf5, 0x64, 0x6b, 0x41, 0x8c, 0x32, - 0x99, 0x5c, 0xbf, 0xe4, 0xf1, 0xce, 0x62, 0xa1, 0xb0, 0x5a, 0xb0, 0x40, 0x8d, 0x2a, 0x75, 0x7a, 0x58, 0x7c, 0xb7, - 0x60, 0x16, 0x14, 0x31, 0x5b, 0xef, 0xf1, 0x1d, 0x57, 0x04, 0xa4, 0x64, 0x97, 0x04, 0x2f, 0xa3, 0x1b, 0x4c, 0x25, - 0xab, 0xb9, 0xcc, 0x99, 0x25, 0xf4, 0x4c, 0xe9, 0x08, 0x9b, 0x3c, 0x05, 0x91, 0xc4, 0x0e, 0x3b, 0xd8, 0xb1, 0x46, - 0xaf, 0x84, 0x17, 0x52, 0xe0, 0x5c, 0x35, 0x4d, 0xcc, 0x29, 0x37, 0xd1, 0xc5, 0x1e, 0xab, 0x05, 0xcb, 0xb4, 0x45, - 0x80, 0x43, 0x87, 0x86, 0x52, 0xbc, 0x34, 0xa0, 0x30, 0x4f, 0x7a, 0xbb, 0x94, 0xa7, 0xb0, 0x78, 0x41, 0x0a, 0x10, - 0x35, 0x2e, 0xa6, 0x55, 0x9d, 0x45, 0xb1, 0x9c, 0x72, 0x51, 0x23, 0x43, 0xc9, 0xd4, 0x42, 0x0a, 0x78, 0x51, 0xa3, - 0x2a, 0x62, 0xe8, 0x50, 0x03, 0xdf, 0x2d, 0x09, 0xab, 0xea, 0x98, 0x63, 0x8a, 0x8b, 0xba, 0x06, 0x30, 0x17, 0x8f, - 0x8d, 0x80, 0xe8, 0xc3, 0xcb, 0xbe, 0x11, 0xef, 0xe5, 0xa2, 0xce, 0xf7, 0x34, 0xce, 0x07, 0xae, 0x77, 0x76, 0xc3, - 0x68, 0x63, 0x1e, 0xbd, 0x0a, 0xb6, 0xef, 0x07, 0x5e, 0x3f, 0x04, 0xb7, 0x31, 0xcf, 0x66, 0x55, 0x59, 0x63, 0x56, - 0xbd, 0x11, 0x51, 0xb7, 0xd7, 0xac, 0x2a, 0x85, 0xad, 0x08, 0x50, 0x29, 0x79, 0xbe, 0x93, 0xff, 0x4a, 0xdb, 0x7c, - 0x7b, 0x0e, 0x55, 0xe1, 0x81, 0x3c, 0x19, 0xaa, 0x7b, 0xc0, 0x65, 0xf5, 0x21, 0x80, 0xc5, 0x8f, 0x4c, 0xfc, 0xe0, - 0x7d, 0x17, 0xc8, 0x9c, 0xa9, 0x58, 0xe2, 0xd5, 0x90, 0x8e, 0x52, 0x2b, 0x0f, 0xa5, 0x12, 0x6c, 0x7b, 0x6e, 0x4b, - 0xae, 0x7d, 0xa0, 0x62, 0x3c, 0x64, 0xa3, 0x74, 0xd5, 0x0c, 0x66, 0x6c, 0xc3, 0x29, 0x7b, 0x73, 0x4e, 0x13, 0xfd, - 0x97, 0x8e, 0x70, 0x41, 0xc0, 0xf6, 0xd8, 0xb3, 0xa7, 0x0f, 0xe2, 0x0c, 0x0d, 0x9a, 0x1c, 0xfe, 0x6a, 0x83, 0x0b, - 0x9c, 0xa1, 0xf4, 0x71, 0x0c, 0x17, 0x58, 0x1b, 0x0c, 0xe0, 0xcb, 0x2c, 0xa9, 0x02, 0x8f, 0xd4, 0xcc, 0x48, 0xac, - 0xee, 0x22, 0x10, 0xad, 0x74, 0x78, 0x3b, 0xce, 0x7c, 0x38, 0x70, 0xc3, 0xbd, 0xbe, 0x30, 0xc2, 0xe1, 0x3c, 0x8b, - 0x1b, 0xe7, 0x0c, 0x27, 0xd7, 0x87, 0xbc, 0x71, 0x62, 0x82, 0xb5, 0x77, 0x78, 0xaa, 0x80, 0x1e, 0x0d, 0x4e, 0x15, - 0x4b, 0x43, 0x20, 0x66, 0x02, 0x78, 0x33, 0x87, 0x47, 0x5b, 0x80, 0xf3, 0xd1, 0x06, 0x07, 0x5f, 0x69, 0xa3, 0xab, - 0x6d, 0x25, 0xca, 0x66, 0x83, 0x87, 0x79, 0x86, 0x97, 0x19, 0x9e, 0x66, 0xa3, 0xf0, 0xb8, 0xc9, 0x42, 0x93, 0xae, - 0xf5, 0xfa, 0x95, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0x68, 0x00, 0x08, 0x9f, 0x42, 0x16, 0xd0, 0x92, 0x81, - 0xfb, 0xdb, 0xb2, 0xaf, 0x85, 0xa3, 0x56, 0xcc, 0x13, 0x4b, 0x46, 0x06, 0xfe, 0x47, 0x95, 0x65, 0x5b, 0x6b, 0x45, - 0x8b, 0xbb, 0x83, 0xa8, 0xe5, 0xdb, 0xab, 0xcf, 0x97, 0x71, 0x65, 0xb6, 0x03, 0x88, 0x62, 0x8d, 0x93, 0x74, 0xb0, - 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcd, 0x03, 0x7a, 0xb1, 0x42, 0x89, 0xe1, - 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x86, 0xc8, 0xfd, 0x29, 0xab, 0x2d, - 0x83, 0x04, 0x11, 0x46, 0xe4, 0xb7, 0xd7, 0xa5, 0xc2, 0x3e, 0xd1, 0x67, 0xff, 0x18, 0x5f, 0x40, 0xb8, 0x79, 0x9b, - 0xd2, 0x72, 0x4c, 0xa7, 0xc0, 0xc6, 0x42, 0x1c, 0xc2, 0x9d, 0x84, 0xf5, 0x7a, 0x38, 0xea, 0x0b, 0x43, 0x9e, 0xdd, - 0x03, 0x82, 0x55, 0x43, 0xfb, 0x1b, 0x80, 0xab, 0x6e, 0x4b, 0xcd, 0xb5, 0xd1, 0xfd, 0x50, 0xf3, 0xc6, 0x19, 0x77, - 0x49, 0xee, 0x99, 0x92, 0xfa, 0x25, 0xf2, 0x86, 0x05, 0xb8, 0x09, 0x5d, 0x85, 0x73, 0xbc, 0xb4, 0x36, 0x9c, 0xe6, - 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x66, 0x23, 0x9c, 0xfb, 0x70, 0xe7, 0x87, 0xef, 0xe2, - 0x1c, 0xa1, 0x92, 0x18, 0x98, 0x5a, 0x97, 0xed, 0xbc, 0xb6, 0xdb, 0x37, 0x99, 0x86, 0x61, 0x30, 0x46, 0xcc, 0x79, - 0x68, 0xc4, 0x5c, 0xb4, 0x5a, 0x68, 0x49, 0x72, 0x30, 0x62, 0x5e, 0x06, 0xad, 0x2d, 0xed, 0x63, 0xa7, 0x41, 0x7b, - 0x4b, 0x84, 0xfa, 0x1c, 0x68, 0x9a, 0x86, 0x67, 0x4d, 0xea, 0x67, 0xe5, 0xfd, 0x23, 0x5b, 0x27, 0x3d, 0x50, 0x24, - 0x4c, 0xae, 0xfd, 0x24, 0xac, 0x6b, 0xb8, 0x1d, 0xf7, 0xc4, 0x8c, 0xdb, 0xd9, 0x36, 0xa8, 0xa1, 0x1c, 0x66, 0xa3, - 0x51, 0x5f, 0x7a, 0x2b, 0x89, 0x0e, 0x9e, 0xd4, 0x0f, 0xa1, 0xd4, 0x8b, 0xf7, 0x45, 0x6f, 0x5f, 0x79, 0x73, 0xff, - 0xbe, 0xea, 0xf6, 0x79, 0x0c, 0x1c, 0xd0, 0x21, 0xdc, 0x0f, 0xd5, 0xf1, 0xc1, 0x4e, 0x7a, 0x10, 0x05, 0x2d, 0xed, - 0x34, 0x04, 0x52, 0x6b, 0x66, 0x17, 0xeb, 0xb6, 0x42, 0xc7, 0x02, 0xc2, 0x90, 0xa9, 0xba, 0xbb, 0x3b, 0x15, 0xa8, - 0x86, 0x38, 0x9c, 0xfa, 0x4f, 0xad, 0x11, 0x6b, 0x1c, 0xf5, 0xf2, 0xc8, 0x18, 0x49, 0xda, 0xe5, 0x83, 0xb7, 0x8f, - 0xc0, 0x4a, 0xc0, 0xc7, 0xa0, 0x36, 0x49, 0xc6, 0x90, 0xe0, 0x1d, 0xcb, 0xb4, 0xe1, 0x43, 0xb8, 0x43, 0x50, 0x9e, - 0xd8, 0xa0, 0xb4, 0xae, 0x92, 0x85, 0x5c, 0xdd, 0xe5, 0x7d, 0x80, 0x9e, 0x77, 0xd5, 0x6f, 0x6c, 0x38, 0xb2, 0x60, - 0x60, 0xd9, 0xce, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x23, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0x78, 0xdd, 0x37, 0xb0, 0x41, - 0xf1, 0x02, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, 0x49, 0xbc, 0x58, 0xaf, - 0x3b, 0xe8, 0xf8, 0x5f, 0xe6, 0x49, 0xea, 0x49, 0xa5, 0x70, 0x9f, 0xd4, 0x0a, 0x77, 0xb0, 0x04, 0x24, 0x93, 0x40, - 0xd7, 0x8e, 0x65, 0xa8, 0x46, 0x87, 0x68, 0xe9, 0xaf, 0x20, 0x76, 0xb6, 0x3b, 0x96, 0x40, 0xcf, 0xbe, 0x53, 0xc0, - 0xea, 0xda, 0xab, 0x12, 0xc8, 0x08, 0xee, 0x7e, 0x13, 0x18, 0x15, 0xa2, 0xf1, 0xf9, 0x33, 0xaf, 0x5a, 0xf0, 0xc4, - 0xf9, 0x73, 0xcd, 0x0d, 0xeb, 0x5e, 0xd2, 0x5b, 0xd3, 0x7c, 0x3c, 0xc1, 0xed, 0x89, 0x05, 0xe7, 0x49, 0x0f, 0x7e, - 0x5a, 0x88, 0x9e, 0xf4, 0xb0, 0x4b, 0xc5, 0x93, 0x0a, 0xc8, 0x21, 0x7a, 0x3a, 0x03, 0x29, 0x60, 0xa5, 0x63, 0xab, - 0x45, 0x9a, 0xa2, 0xf5, 0x7a, 0x7a, 0x45, 0x3a, 0x08, 0xad, 0xd4, 0x2d, 0xd7, 0xd9, 0x0c, 0x7c, 0xa4, 0x41, 0x31, - 0xf0, 0x96, 0xea, 0x59, 0x8c, 0xf0, 0x04, 0xad, 0x72, 0x36, 0xa1, 0xcb, 0x42, 0xa7, 0x6a, 0xc0, 0x13, 0x1b, 0xb8, - 0x97, 0xd9, 0x48, 0x70, 0x27, 0x3d, 0x3c, 0x35, 0xfc, 0xe5, 0x47, 0x63, 0x0e, 0x52, 0x66, 0x26, 0x79, 0x6a, 0x12, - 0x30, 0x4f, 0xb2, 0x42, 0x2a, 0x66, 0x9b, 0xe9, 0x5b, 0xdb, 0x72, 0x08, 0x49, 0x1e, 0xe9, 0x92, 0x1b, 0x2b, 0xca, - 0x28, 0x9d, 0x11, 0x35, 0x50, 0x27, 0xbd, 0x74, 0x8a, 0x79, 0x02, 0x9c, 0xde, 0x7b, 0x19, 0xb3, 0x56, 0x75, 0x2b, - 0x3a, 0x47, 0xc7, 0x33, 0x2c, 0xea, 0x4b, 0xd4, 0x39, 0x3a, 0x9e, 0x22, 0x3c, 0x6f, 0x91, 0x99, 0x02, 0x8f, 0x61, - 0x2e, 0xfe, 0x3f, 0x29, 0xff, 0xd5, 0x61, 0x43, 0x88, 0xe9, 0x77, 0xb0, 0x53, 0x58, 0x1e, 0xa5, 0x05, 0x01, 0xaf, - 0xc5, 0xee, 0x05, 0xce, 0xc8, 0xb4, 0x5d, 0xf8, 0x80, 0x7b, 0xa6, 0x95, 0xd6, 0x9d, 0x46, 0xc7, 0x19, 0xce, 0xb7, - 0x93, 0x62, 0x33, 0xd7, 0x76, 0x91, 0x66, 0x70, 0xbe, 0xd7, 0xa3, 0x70, 0xe5, 0x97, 0xdb, 0x49, 0x61, 0x79, 0x07, - 0xdc, 0x76, 0x8e, 0x45, 0x9b, 0xe2, 0x02, 0xcf, 0xdb, 0xaf, 0xf1, 0xbc, 0xfd, 0xa1, 0xca, 0x68, 0x2d, 0xb1, 0x80, - 0xe0, 0x7d, 0x90, 0x88, 0xe7, 0x75, 0x72, 0x8e, 0x45, 0xcb, 0x94, 0xc7, 0xf3, 0x56, 0x5d, 0xba, 0xbd, 0xc4, 0xa2, - 0x65, 0x4a, 0xb7, 0x3e, 0xe0, 0x79, 0xeb, 0xf5, 0xbf, 0x99, 0x74, 0x94, 0x02, 0xba, 0x2c, 0xd0, 0x2a, 0xb3, 0x43, - 0xbc, 0xf9, 0xf9, 0xdd, 0xfb, 0xee, 0xa7, 0xde, 0xf1, 0x14, 0xfb, 0xf5, 0xcb, 0x0c, 0x8e, 0x65, 0x3a, 0x66, 0x6d, - 0x80, 0x68, 0x86, 0x7b, 0xc7, 0x33, 0xdc, 0x3b, 0xce, 0x5c, 0x53, 0x9b, 0x79, 0x8b, 0xdc, 0xe9, 0x10, 0x8a, 0x3a, - 0x4a, 0x43, 0xf8, 0xf8, 0xc9, 0xa6, 0x53, 0xd4, 0x00, 0x25, 0x3a, 0x9e, 0x36, 0x40, 0x05, 0xdf, 0xcb, 0xc6, 0x77, - 0x5d, 0xaf, 0xc6, 0x20, 0x0b, 0x25, 0x14, 0xae, 0xb9, 0x01, 0x4f, 0x23, 0xc5, 0x40, 0x26, 0x4c, 0xb1, 0x40, 0xf9, - 0x06, 0x28, 0x8c, 0xf2, 0xc4, 0x0c, 0x3d, 0x98, 0x8e, 0x49, 0xfc, 0xff, 0x79, 0x32, 0xd5, 0xd0, 0xab, 0x2d, 0xb3, - 0x33, 0x3d, 0x37, 0x99, 0x70, 0xf8, 0xc0, 0x63, 0xfd, 0x6f, 0x3b, 0x50, 0x6c, 0x40, 0x8a, 0xff, 0x37, 0x1d, 0x5d, - 0x08, 0x46, 0xc8, 0x8a, 0xd2, 0xd2, 0x21, 0xfe, 0xb7, 0x87, 0x15, 0x74, 0x5f, 0xee, 0x74, 0x5f, 0x9a, 0xee, 0xc3, - 0xa6, 0x8d, 0x2a, 0x27, 0xad, 0x2b, 0x59, 0xf2, 0xdf, 0xa4, 0x5b, 0x3b, 0xa0, 0x11, 0x0d, 0x7a, 0x36, 0x0d, 0x1b, - 0x3c, 0xec, 0xa6, 0x7b, 0x90, 0x79, 0xc3, 0xed, 0x0b, 0xa9, 0x70, 0xf8, 0x06, 0x77, 0xaa, 0xd7, 0x1d, 0xf0, 0xde, - 0x54, 0x46, 0x5f, 0x19, 0x87, 0x96, 0x83, 0x74, 0xdb, 0x94, 0xdb, 0x18, 0x4b, 0x27, 0xe7, 0xd8, 0xb8, 0x22, 0x42, - 0xa5, 0xbb, 0x6b, 0x50, 0x8a, 0x4f, 0x74, 0x9b, 0x99, 0xaf, 0x2b, 0x9d, 0x98, 0x4b, 0xa8, 0x96, 0xf9, 0xbc, 0xbf, - 0xd6, 0x89, 0x96, 0x0b, 0x9b, 0x77, 0x7f, 0x05, 0x7d, 0x82, 0x86, 0xb5, 0x15, 0xd8, 0xed, 0x73, 0x67, 0x07, 0x19, - 0x1c, 0x82, 0xe1, 0x01, 0xe4, 0x48, 0x8b, 0xed, 0x03, 0x9b, 0xd6, 0xb0, 0xeb, 0xa2, 0x5d, 0x25, 0xda, 0x56, 0xdb, - 0x26, 0xd7, 0xee, 0x61, 0xbe, 0x08, 0x79, 0x0a, 0x51, 0x5a, 0xfd, 0xf8, 0x1e, 0x76, 0xe3, 0x4b, 0x83, 0x91, 0x68, - 0x2a, 0x99, 0x2a, 0xe8, 0x27, 0x77, 0x98, 0x25, 0xf7, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0x97, 0x3f, 0xaa, - 0x25, 0x39, 0xb0, 0xec, 0x6f, 0xb1, 0xe4, 0x0e, 0xcc, 0x13, 0xab, 0x6a, 0x12, 0xeb, 0xe4, 0x3e, 0x58, 0x44, 0x69, - 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0x61, 0x50, 0x95, 0xd2, 0xae, 0xb3, 0xb4, - 0xd1, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9e, 0xc6, 0x6d, 0xc0, 0x35, 0xfd, 0xbb, 0x49, 0x24, 0x63, 0xf6, 0x37, - 0x67, 0xe5, 0xd3, 0x65, 0x69, 0x30, 0x4d, 0x0c, 0x74, 0x92, 0x2d, 0xba, 0x60, 0xaa, 0x97, 0x2d, 0x7a, 0x77, 0xd8, - 0x7d, 0xdf, 0xdb, 0xef, 0x7b, 0x2c, 0x06, 0xcc, 0x64, 0xa4, 0xcc, 0x14, 0xf3, 0xdf, 0xf7, 0xf6, 0xfb, 0x1e, 0xef, - 0x0e, 0xe6, 0xb3, 0xbf, 0x50, 0xac, 0xd8, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x1a, 0x59, 0x26, 0x08, 0x6c, - 0x23, 0x01, 0xe2, 0x7c, 0xbe, 0x8a, 0x6b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xeb, 0x54, 0xe0, 0x31, 0x41, - 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd2, 0x93, 0x24, 0xc0, 0xab, 0x1a, 0x95, 0xb7, - 0x29, 0x52, 0x7d, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x42, 0x15, 0x03, 0x58, 0x55, 0x25, 0x7d, 0x02, 0x69, 0xe6, 0x87, - 0x9e, 0x9a, 0xdb, 0xc8, 0x63, 0xdf, 0xf9, 0xfd, 0xcc, 0xf4, 0xac, 0x94, 0xcb, 0xe9, 0x0c, 0x7c, 0x68, 0x81, 0x65, - 0x28, 0x4d, 0xbd, 0xda, 0xd6, 0xbf, 0x21, 0xb9, 0x09, 0xa0, 0x70, 0xba, 0x2d, 0x13, 0x9a, 0xe9, 0x25, 0x2d, 0x8c, - 0x25, 0x29, 0x17, 0xd3, 0x27, 0xf2, 0xee, 0x47, 0xc0, 0x6e, 0x4a, 0x74, 0x6b, 0x4f, 0xde, 0x3b, 0xd8, 0x01, 0x38, - 0x23, 0x6c, 0x5f, 0xc5, 0xc7, 0x0a, 0x74, 0xfe, 0xb8, 0x20, 0x6c, 0x5f, 0xd5, 0x67, 0xcc, 0x66, 0xcf, 0xc8, 0xd6, - 0x70, 0x07, 0x71, 0xd6, 0x2a, 0xd0, 0x49, 0x2f, 0x2d, 0xfa, 0x9e, 0x18, 0x58, 0x80, 0x06, 0xc0, 0xdd, 0xd9, 0x9e, - 0xd5, 0xdd, 0x0d, 0x01, 0xbd, 0x4b, 0x26, 0xed, 0x75, 0xb9, 0x49, 0x59, 0xaf, 0x7b, 0x35, 0x15, 0x2c, 0xf1, 0x2c, - 0xd8, 0x0b, 0xd4, 0x7e, 0xed, 0xa1, 0x38, 0x3f, 0x65, 0xdb, 0xa6, 0xe7, 0x55, 0xdf, 0xfd, 0x3d, 0x8b, 0x8c, 0x6d, - 0xda, 0xbb, 0x3d, 0x44, 0xc2, 0x72, 0xc2, 0x3a, 0xe0, 0x84, 0xeb, 0xda, 0x01, 0x01, 0xfa, 0x14, 0x88, 0xdc, 0x58, - 0x92, 0xd5, 0xa6, 0x36, 0xba, 0x0f, 0xfc, 0x6e, 0x29, 0x91, 0x6e, 0xb4, 0x15, 0xc1, 0xf4, 0x09, 0x46, 0x4d, 0x67, - 0x9e, 0xa6, 0x6e, 0xbc, 0xba, 0xbc, 0x2d, 0xda, 0xfa, 0x37, 0xa0, 0xb1, 0xd9, 0x1e, 0x26, 0x86, 0x32, 0x88, 0x81, - 0xde, 0x47, 0xbc, 0xdf, 0x6a, 0x65, 0x08, 0x14, 0x32, 0xd9, 0x08, 0xcb, 0xc4, 0x6b, 0xd1, 0x8f, 0x8e, 0x0c, 0x3c, - 0xea, 0x04, 0x84, 0x29, 0x08, 0x21, 0x61, 0xd7, 0x06, 0x61, 0xc3, 0xe5, 0x6a, 0xe4, 0xc2, 0x46, 0x6a, 0x0c, 0x1d, - 0xfc, 0xbf, 0xc2, 0x65, 0x6b, 0x66, 0x56, 0x8b, 0x62, 0x70, 0xb3, 0x30, 0x60, 0x91, 0x20, 0x3d, 0xda, 0x6c, 0x0f, - 0xc5, 0xfd, 0xb9, 0xd8, 0x6c, 0x08, 0x48, 0x2c, 0x60, 0x82, 0xa2, 0xe5, 0xdc, 0x18, 0x63, 0x95, 0xd4, 0x5a, 0xd6, - 0x86, 0xc4, 0x1c, 0x04, 0x8c, 0x0e, 0xd7, 0x7d, 0x75, 0x97, 0x32, 0x7c, 0x9f, 0x0a, 0x7c, 0x0b, 0x9e, 0x34, 0xa9, - 0xc4, 0xee, 0xf1, 0x82, 0x72, 0x43, 0x74, 0xdf, 0xb3, 0xb7, 0x25, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xff, - 0xea, 0x82, 0xef, 0x16, 0x7e, 0x0d, 0xd6, 0xcf, 0xc1, 0x49, 0x8a, 0x45, 0x4b, 0xb6, 0x4b, 0x77, 0x64, 0x40, 0xb9, - 0x9a, 0x5f, 0x0e, 0x53, 0x77, 0x8a, 0xe1, 0xc6, 0xc7, 0x6b, 0xfc, 0x61, 0xab, 0xdd, 0x96, 0xaa, 0x8a, 0xdb, 0xbd, - 0x29, 0x5a, 0xb2, 0x6e, 0x7a, 0x4f, 0xe6, 0x56, 0x4a, 0xf3, 0xeb, 0x03, 0xee, 0xec, 0xb4, 0xef, 0xa7, 0xf9, 0xce, - 0xa3, 0x73, 0xdd, 0xb4, 0x4f, 0x6d, 0x14, 0xc1, 0xc1, 0xcf, 0x0e, 0x6e, 0xef, 0x0c, 0x38, 0x80, 0x9f, 0xbf, 0xa3, - 0x79, 0x93, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc7, 0xbf, 0xe7, 0xad, 0x78, 0x90, 0xfe, 0x9e, 0xfc, 0x9e, 0xb7, - 0xd0, 0x00, 0xc5, 0x8b, 0xbb, 0x35, 0x9b, 0xaf, 0x21, 0xd8, 0xda, 0x83, 0x13, 0xfc, 0x20, 0x2c, 0xc9, 0x35, 0x2d, - 0x78, 0xb6, 0x76, 0x0f, 0x02, 0xae, 0xdd, 0xab, 0x44, 0x6b, 0xf3, 0xc6, 0xd5, 0x3a, 0x96, 0xe3, 0x02, 0x02, 0x0b, - 0xc7, 0x07, 0xed, 0xc1, 0xb0, 0xd3, 0x7e, 0x34, 0xb2, 0xff, 0x9a, 0x08, 0xf7, 0xa8, 0x11, 0xb1, 0xed, 0xed, 0xd6, - 0xd6, 0x8f, 0xc1, 0xb0, 0x03, 0x42, 0x81, 0x83, 0x5c, 0xfa, 0x26, 0x43, 0xd6, 0xf7, 0x64, 0xbd, 0x66, 0x2e, 0x9a, - 0xb5, 0xd3, 0xe0, 0x57, 0xb1, 0x99, 0x8e, 0xbb, 0x49, 0xaf, 0xef, 0xc5, 0x58, 0xd2, 0x82, 0x48, 0xd3, 0x98, 0x41, - 0x20, 0xa9, 0x95, 0xe1, 0xb0, 0x16, 0x77, 0x51, 0x5a, 0xdf, 0x1f, 0x41, 0xca, 0x77, 0x51, 0xca, 0x4f, 0x08, 0x04, - 0xd0, 0xb6, 0xcc, 0x51, 0xd5, 0x90, 0xf7, 0x5d, 0x7a, 0x6c, 0x9c, 0x19, 0x5a, 0x7c, 0xbd, 0xee, 0xd4, 0xc3, 0x54, - 0x65, 0x73, 0x98, 0xab, 0x0d, 0x16, 0xe4, 0x01, 0xe8, 0x9a, 0x15, 0x11, 0x83, 0xd0, 0x55, 0x1e, 0xde, 0x43, 0xc6, - 0x92, 0x80, 0x93, 0xfe, 0x40, 0x0c, 0x4a, 0x72, 0xfd, 0x38, 0x06, 0x1f, 0x33, 0xcc, 0x87, 0x7a, 0x58, 0x8e, 0x46, - 0x28, 0x75, 0x4e, 0x67, 0xa9, 0x89, 0xb8, 0x12, 0xf8, 0x25, 0x97, 0xe0, 0x97, 0xac, 0x10, 0x1b, 0x96, 0x23, 0xf2, - 0x38, 0x8b, 0x25, 0x38, 0xe5, 0xef, 0xf1, 0x79, 0x7c, 0x1e, 0x1a, 0x98, 0x9a, 0x61, 0x99, 0x8b, 0x6c, 0xb0, 0x98, - 0xb3, 0x96, 0x40, 0x70, 0x33, 0xe0, 0x2e, 0xb5, 0x21, 0xd1, 0x58, 0x03, 0x45, 0x77, 0x51, 0x68, 0x66, 0xf4, 0x6a, - 0xa7, 0x8d, 0x61, 0xe4, 0xf0, 0xc2, 0x5c, 0xc3, 0x58, 0x04, 0x32, 0x97, 0xab, 0x1e, 0xfb, 0xab, 0x0f, 0x9b, 0x15, - 0x06, 0xaf, 0xc8, 0x74, 0xe8, 0x8e, 0x63, 0xc6, 0x57, 0x7b, 0xe2, 0x18, 0x82, 0x4c, 0x2c, 0x95, 0x6e, 0x39, 0x26, - 0xae, 0xa2, 0xcf, 0xc4, 0x90, 0xed, 0x96, 0x67, 0xe6, 0x42, 0x37, 0xdb, 0x7f, 0x39, 0xb7, 0x73, 0x4e, 0xb8, 0xd1, - 0x4a, 0x1a, 0x6d, 0xd4, 0x0b, 0x43, 0x55, 0x5d, 0x30, 0xbf, 0xc7, 0x4e, 0x4b, 0x8b, 0x9d, 0xab, 0x77, 0x3f, 0x7c, - 0x9d, 0xaf, 0x8a, 0xbf, 0xc5, 0xea, 0xd0, 0x8a, 0x0c, 0x77, 0x3b, 0xc8, 0x9b, 0x33, 0x3d, 0xf6, 0x8a, 0x5c, 0xa8, - 0x0e, 0x7f, 0x51, 0x5f, 0x98, 0x07, 0x3b, 0xa3, 0x96, 0xf0, 0xe8, 0xf7, 0x20, 0x03, 0xe5, 0x1f, 0x4c, 0x4c, 0x16, - 0x2c, 0xb9, 0xa5, 0xa5, 0x88, 0xff, 0xf1, 0x4a, 0x98, 0x58, 0x55, 0x07, 0x30, 0x90, 0x03, 0x53, 0xf1, 0x00, 0x6e, - 0x4d, 0xf8, 0x84, 0xb3, 0x3c, 0x3d, 0x88, 0xfe, 0xd1, 0x12, 0xad, 0x7f, 0x44, 0xff, 0x00, 0x77, 0x67, 0xf7, 0x3a, - 0x64, 0x15, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0xae, 0x54, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x36, 0x8b, - 0x1f, 0x3b, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, - 0xfa, 0xea, 0x71, 0xa5, 0x82, 0x86, 0x83, 0xd0, 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xca, 0xa7, 0xd3, 0x9d, 0x49, - 0x64, 0x9c, 0xc5, 0xf0, 0xee, 0x41, 0x10, 0x48, 0x80, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, 0x3a, 0xea, 0xa5, 0x24, - 0x10, 0x80, 0xbe, 0xf2, 0x1e, 0x94, 0x57, 0x65, 0xbf, 0xd5, 0x92, 0xa0, 0x85, 0xa5, 0xe6, 0x5a, 0x15, 0xd3, 0xc3, - 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, 0x10, 0xac, 0xb2, 0x83, - 0xf2, 0xef, 0x62, 0x8a, 0x6c, 0xfe, 0x90, 0x7d, 0x47, 0x5d, 0x87, 0x23, 0x57, 0xb0, 0xee, 0xa5, 0x8a, 0x82, 0x01, - 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0xf5, 0xdc, 0x9e, 0x35, 0xfd, 0x86, - 0x8c, 0xb3, 0x8f, 0x30, 0xce, 0x3e, 0x0a, 0xbc, 0x58, 0x24, 0xf9, 0x41, 0xc6, 0x1a, 0xc7, 0xaa, 0x2d, 0xd0, 0x49, - 0x0f, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0xa3, 0x23, 0xea, 0x2c, 0xee, 0x69, 0x2b, 0xf3, 0xde, 0x9e, 0x50, - 0xbb, 0x8c, 0x05, 0x6e, 0x37, 0xcc, 0xb4, 0xa0, 0xb5, 0xd2, 0x38, 0x8f, 0x87, 0x11, 0x19, 0x1b, 0xf1, 0x13, 0xb6, - 0xac, 0xa9, 0x9a, 0x37, 0xd0, 0x1c, 0x35, 0x82, 0xdc, 0xbc, 0x32, 0xde, 0xaa, 0x64, 0x18, 0x45, 0x23, 0xcb, 0xa9, - 0x10, 0x43, 0x32, 0x86, 0x9d, 0x51, 0x70, 0xab, 0xbd, 0x5e, 0x73, 0x8f, 0xf8, 0xa2, 0xe1, 0xad, 0x66, 0x6e, 0x01, - 0xb2, 0x32, 0x8e, 0xaa, 0x7b, 0x93, 0x08, 0xbc, 0x6f, 0xab, 0x08, 0x69, 0xab, 0xa1, 0x7d, 0xba, 0xb2, 0x52, 0x6c, - 0xbe, 0xa7, 0xd3, 0x51, 0x1a, 0xd9, 0x11, 0x45, 0xf8, 0x53, 0x05, 0x49, 0xb8, 0x4a, 0xfa, 0xa4, 0x32, 0xb9, 0x60, - 0x2a, 0xe5, 0xf8, 0x53, 0x29, 0xa5, 0xbe, 0xb1, 0x5f, 0x12, 0xd7, 0x77, 0x32, 0x02, 0x7f, 0x9a, 0x32, 0xfd, 0x9e, - 0x96, 0x53, 0x06, 0x7e, 0x45, 0xfe, 0x76, 0x2c, 0xa5, 0xe4, 0xfa, 0x95, 0x88, 0x87, 0x14, 0xc3, 0xbb, 0xab, 0x23, - 0xac, 0x4d, 0x08, 0x94, 0x0a, 0x17, 0xe1, 0x82, 0xe8, 0x6d, 0x29, 0xef, 0xee, 0xe3, 0x12, 0x3b, 0x07, 0xc0, 0xca, - 0x69, 0x12, 0xe0, 0x5f, 0x3d, 0xe6, 0x63, 0x35, 0xe6, 0xd4, 0xe8, 0xfa, 0xdd, 0xef, 0xe4, 0x13, 0xd0, 0xdb, 0xca, - 0x51, 0x70, 0xd8, 0x19, 0x41, 0x2e, 0xdc, 0x85, 0xc1, 0xc5, 0x57, 0x58, 0xbb, 0x2c, 0x8d, 0x37, 0x16, 0x40, 0xef, - 0x49, 0x06, 0x16, 0x6c, 0x98, 0x63, 0x0a, 0x8f, 0xd6, 0x4e, 0x99, 0x0e, 0xa2, 0x82, 0x3c, 0xab, 0x9e, 0x25, 0x6d, - 0xd4, 0x7e, 0xc7, 0x26, 0x70, 0x87, 0x91, 0x7c, 0xbd, 0x70, 0xe2, 0xc0, 0x03, 0x32, 0x4d, 0x66, 0x9b, 0x7d, 0xeb, - 0x23, 0x8f, 0xbc, 0x99, 0xc4, 0xfb, 0x5a, 0x0a, 0xf3, 0xcd, 0x8a, 0x6e, 0x30, 0x84, 0xa2, 0x08, 0xfb, 0xbd, 0x55, - 0x31, 0x45, 0xb5, 0x41, 0x1b, 0x34, 0x2c, 0x6f, 0xc5, 0x0f, 0x70, 0xc6, 0xd0, 0x66, 0x21, 0x7b, 0x47, 0x67, 0x1d, - 0xce, 0x1c, 0x66, 0xcc, 0x08, 0x8c, 0x4a, 0xcb, 0x92, 0x4e, 0xc1, 0xd1, 0xb9, 0xfe, 0x20, 0x2a, 0xae, 0x8f, 0x15, - 0x80, 0x27, 0x99, 0xc1, 0x3f, 0xc5, 0x36, 0x58, 0x0f, 0x3b, 0x0d, 0xc3, 0xd4, 0x1f, 0xf4, 0xae, 0x6b, 0xf9, 0x2a, - 0xc4, 0x91, 0x2e, 0x86, 0xd0, 0x3a, 0x77, 0xf7, 0x80, 0x22, 0x2e, 0xe8, 0x45, 0xaa, 0xf1, 0x27, 0xb5, 0x1c, 0x9b, - 0xf5, 0x35, 0xae, 0x63, 0xda, 0x20, 0x8a, 0x75, 0xd7, 0xc4, 0x9f, 0xea, 0x57, 0x60, 0x55, 0x0a, 0xac, 0x33, 0x28, - 0x3f, 0x54, 0x75, 0xd9, 0x90, 0x4a, 0x72, 0x6d, 0x3a, 0x95, 0xa6, 0xd3, 0x1a, 0xa1, 0x5c, 0x7a, 0x52, 0xdd, 0xbf, - 0x42, 0x08, 0x03, 0x53, 0x66, 0x0f, 0x56, 0xa9, 0x1d, 0xac, 0x82, 0x57, 0x2f, 0xb6, 0xb0, 0x4a, 0xc2, 0xf1, 0x5c, - 0xa1, 0x51, 0x59, 0xe3, 0x90, 0x21, 0x7d, 0x21, 0x16, 0x41, 0x02, 0x60, 0xd1, 0x8f, 0x99, 0xcb, 0xfb, 0x16, 0x0e, - 0x85, 0x3d, 0xc9, 0x24, 0x9c, 0x6e, 0x42, 0x0b, 0x78, 0x1e, 0x58, 0x0d, 0x3c, 0x42, 0xcc, 0x4c, 0xfc, 0x27, 0x78, - 0x16, 0xfa, 0xdb, 0xcf, 0xd1, 0x3a, 0x0b, 0xf2, 0xf4, 0xdf, 0xa2, 0x24, 0x34, 0xf6, 0x3f, 0xc7, 0x43, 0x87, 0x84, - 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe3, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0x36, 0xa1, 0x07, 0x80, 0x25, 0x14, - 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x54, 0xf7, 0xb7, 0x1d, 0x2f, - 0xa5, 0x35, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf5, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, 0xfb, 0xc2, 0x9f, 0x1c, - 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xca, 0xc5, 0x61, 0xdb, 0x41, 0xf7, 0x02, 0x73, - 0x75, 0x53, 0x67, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0xaa, 0x0a, 0x2e, 0x40, 0xbc, - 0x1f, 0x08, 0x93, 0x53, 0x45, 0x03, 0x78, 0x9f, 0x55, 0x8f, 0x4e, 0x0d, 0x38, 0xb8, 0x8c, 0x1b, 0x36, 0xf1, 0x99, - 0xf0, 0xa9, 0xc0, 0x4a, 0x5a, 0xe3, 0xd0, 0x88, 0xe6, 0x74, 0x01, 0x66, 0x1b, 0x40, 0xc1, 0xdd, 0xf9, 0xb0, 0xb5, - 0x50, 0xc1, 0x93, 0xbc, 0x8d, 0x17, 0xb4, 0x09, 0x71, 0x26, 0x4d, 0xc1, 0xdd, 0x76, 0x59, 0x06, 0xe6, 0xb7, 0xff, - 0x51, 0x58, 0x24, 0x18, 0x50, 0xa5, 0x49, 0x82, 0xf0, 0x04, 0x95, 0x91, 0x6e, 0xed, 0x66, 0x02, 0xe9, 0x44, 0x84, - 0x37, 0xcc, 0x3f, 0x6e, 0x9d, 0xaf, 0x8e, 0x1a, 0x88, 0x9a, 0x1a, 0xa8, 0x80, 0x1a, 0xc8, 0xe6, 0xf6, 0x2f, 0x61, - 0x21, 0x6c, 0x84, 0x2a, 0x11, 0x04, 0x44, 0x58, 0x68, 0xc3, 0x07, 0x94, 0x49, 0x08, 0x79, 0x03, 0xa8, 0x98, 0x92, - 0x77, 0x60, 0x34, 0x0e, 0xaf, 0xf7, 0x80, 0xfb, 0xa5, 0x65, 0x18, 0x3c, 0xa7, 0x60, 0xf2, 0x5f, 0xf8, 0x7c, 0xa8, - 0x5e, 0xad, 0x0e, 0x42, 0xf8, 0x19, 0xc4, 0x8a, 0x70, 0xfc, 0xc5, 0x0f, 0x40, 0x36, 0x15, 0x96, 0x47, 0x47, 0x12, - 0x04, 0x7e, 0x88, 0x22, 0x1c, 0xf0, 0x0c, 0xef, 0xb2, 0x2d, 0xa2, 0xe7, 0x67, 0xa5, 0xea, 0x59, 0xc9, 0x60, 0x56, - 0xa5, 0xa7, 0x71, 0x74, 0x43, 0x18, 0x08, 0x2e, 0xd4, 0xee, 0x1b, 0x84, 0x40, 0xd9, 0x72, 0x6b, 0xe8, 0xd2, 0x73, - 0x30, 0x1f, 0x8d, 0xa3, 0x77, 0x0c, 0x1e, 0x16, 0x36, 0xee, 0x28, 0x4c, 0xb3, 0x4c, 0x1b, 0xe6, 0xb1, 0x15, 0x38, - 0xa9, 0x53, 0x94, 0xfc, 0x29, 0xb9, 0x88, 0xa3, 0xf6, 0x75, 0x84, 0x5a, 0xf0, 0x6f, 0x8b, 0xa3, 0x3e, 0x4d, 0x68, - 0x9e, 0xfb, 0xe0, 0x37, 0x19, 0x31, 0x9b, 0x6c, 0xbd, 0x16, 0x35, 0x41, 0x4f, 0xec, 0x06, 0x03, 0x56, 0xe2, 0x19, - 0xb0, 0x0f, 0x96, 0x83, 0x25, 0xef, 0x45, 0xac, 0xfc, 0x29, 0x85, 0xc1, 0xea, 0x39, 0x43, 0x08, 0x67, 0x01, 0x93, - 0xf2, 0x3f, 0x9f, 0x69, 0xb8, 0x7e, 0x7e, 0xbe, 0x8e, 0x11, 0x91, 0x3e, 0x88, 0x5c, 0x83, 0x1d, 0x11, 0x41, 0xd8, - 0x32, 0x3d, 0x74, 0x65, 0xbe, 0xf3, 0xd6, 0xd5, 0x23, 0x1b, 0x2e, 0x0e, 0x0c, 0xa8, 0x51, 0x60, 0xb4, 0x82, 0x0b, - 0x52, 0x0d, 0x1c, 0x94, 0x10, 0x9a, 0x95, 0xf1, 0x8c, 0x5c, 0x43, 0x24, 0xbc, 0x0c, 0xf5, 0xc1, 0xb0, 0x20, 0x90, - 0xa0, 0x66, 0x20, 0x41, 0x65, 0xbe, 0x76, 0x0e, 0xb3, 0x2e, 0xcc, 0x6c, 0x67, 0xa8, 0xef, 0x82, 0xfc, 0xfc, 0xa0, - 0xe3, 0x1c, 0x58, 0xda, 0xa3, 0xa3, 0x12, 0x22, 0x88, 0x01, 0x05, 0xaf, 0x24, 0xc0, 0x40, 0x03, 0x5e, 0x6e, 0x69, - 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x2a, 0xc8, 0xc5, 0xeb, 0x7a, 0x4f, 0x13, 0x42, 0x0e, 0x3b, 0x03, - 0x9d, 0xee, 0x46, 0x48, 0x1c, 0xfc, 0xaa, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xeb, 0x8d, 0xf9, 0x77, 0x43, 0x8f, 0x58, - 0x4f, 0x42, 0xba, 0x20, 0x5d, 0x9e, 0x4f, 0x7b, 0x0d, 0x57, 0xac, 0xd2, 0xc8, 0xc1, 0x25, 0xe8, 0xb3, 0x01, 0x01, - 0x4a, 0x54, 0x99, 0x4a, 0xd0, 0x32, 0x2e, 0x93, 0x8a, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, 0xd6, 0x2b, 0x41, 0xb7, 0xd6, - 0x00, 0x78, 0x67, 0x66, 0xff, 0x54, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, 0x1c, 0x76, 0x2b, 0x76, 0x5d, - 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0x5e, 0xec, 0xf2, 0x09, 0x10, 0xa2, 0xb6, 0x62, - 0x1a, 0xb1, 0x84, 0x21, 0xeb, 0xc6, 0x90, 0x8d, 0x36, 0x14, 0x9e, 0x4a, 0xe4, 0xc0, 0x25, 0x9a, 0x20, 0xf9, 0x8e, - 0x4b, 0x70, 0x08, 0x2f, 0x3c, 0xc2, 0x7f, 0x01, 0x16, 0xa9, 0xc4, 0x0c, 0xcb, 0xf5, 0x1a, 0xea, 0x79, 0xbc, 0xcf, - 0xb6, 0x83, 0x93, 0xca, 0xad, 0xb1, 0x4b, 0x3b, 0xf1, 0xb8, 0x6a, 0x42, 0xe2, 0x0c, 0xfa, 0xf5, 0x15, 0xd1, 0xe0, - 0xb0, 0x9b, 0xbe, 0xf2, 0xef, 0x95, 0xb9, 0x1d, 0x88, 0x0d, 0xeb, 0x0d, 0x56, 0x1f, 0x40, 0xcb, 0xff, 0xcc, 0xfc, - 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, 0x5e, 0xc4, 0x3e, 0xeb, 0x23, 0x46, 0x1a, 0x8b, 0xbb, 0x47, 0x88, 0xff, 0x73, - 0x27, 0x8a, 0x01, 0x4f, 0x6a, 0xfe, 0x39, 0x46, 0x7d, 0x08, 0x45, 0x6d, 0x3d, 0x6c, 0x80, 0xd2, 0xae, 0x36, 0xb5, - 0x18, 0x19, 0x12, 0xc8, 0x77, 0x2e, 0xbc, 0xa0, 0x39, 0x89, 0x14, 0xc8, 0xc9, 0x75, 0x17, 0x4f, 0xb2, 0x2d, 0x61, - 0xae, 0xbf, 0x83, 0x63, 0xe6, 0x6a, 0x23, 0x2b, 0xe3, 0xf7, 0xc0, 0xce, 0x70, 0x23, 0x59, 0x3a, 0xf0, 0xa9, 0x06, - 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0xd0, 0xe0, 0xbd, 0x7d, 0x64, 0x0e, 0x7e, 0xa7, 0x81, 0xf8, 0x98, 0x39, 0x1d, - 0xc9, 0x56, 0xa8, 0x35, 0x67, 0xc7, 0xcb, 0xb6, 0x23, 0x0c, 0x0a, 0x1b, 0xbd, 0xaf, 0x46, 0x56, 0xb1, 0xb7, 0x53, - 0x11, 0xcc, 0xe9, 0x56, 0xd5, 0xce, 0xa9, 0xdc, 0x32, 0xaa, 0x95, 0xa6, 0x01, 0x22, 0x5c, 0xf9, 0x44, 0xf2, 0x31, - 0x33, 0xe1, 0x1f, 0x0c, 0xc6, 0x35, 0x23, 0x85, 0x7f, 0xdc, 0x17, 0x3b, 0x64, 0x37, 0x3a, 0xdc, 0x56, 0xd0, 0xbc, - 0x50, 0xc1, 0x03, 0x8e, 0x4a, 0x96, 0x10, 0x29, 0x72, 0x7d, 0xa8, 0x1a, 0xa6, 0x6c, 0x9f, 0x22, 0x84, 0x90, 0xf6, - 0x38, 0xeb, 0x86, 0xd6, 0x0c, 0x3d, 0x52, 0x3b, 0x4d, 0xee, 0xd0, 0x5c, 0x17, 0xa0, 0xc2, 0x08, 0xa4, 0xab, 0xcf, - 0xec, 0x3e, 0x95, 0x10, 0xbd, 0x7c, 0xe3, 0x42, 0x18, 0x3b, 0x2b, 0x4b, 0x5c, 0x9a, 0x51, 0xdb, 0x30, 0xba, 0x6e, - 0x63, 0x38, 0x1b, 0x18, 0x33, 0x0d, 0x4a, 0x3a, 0x10, 0xea, 0xba, 0x4f, 0xaf, 0x32, 0x13, 0xe8, 0xb1, 0x20, 0xb4, - 0xc5, 0xf0, 0x8c, 0x68, 0xb0, 0x6c, 0x2a, 0xc1, 0x82, 0x6f, 0x55, 0xa6, 0xd6, 0x66, 0x93, 0xc5, 0xbf, 0xea, 0xd8, - 0x3c, 0xed, 0x57, 0xd4, 0xcc, 0x73, 0xe9, 0xa3, 0x23, 0x64, 0x3e, 0x1e, 0xdd, 0xf3, 0xb7, 0x37, 0xaf, 0x7e, 0x7c, - 0xf3, 0x7a, 0xbd, 0xee, 0xb2, 0x76, 0xf7, 0x0c, 0xff, 0x53, 0x57, 0xf1, 0x60, 0xab, 0x28, 0x40, 0x47, 0x47, 0x87, - 0xdc, 0xb8, 0xf0, 0x7c, 0xe6, 0x0b, 0x88, 0x1b, 0xa4, 0x47, 0xb8, 0x28, 0xab, 0x98, 0x20, 0x77, 0xd1, 0x20, 0xba, - 0x8f, 0x40, 0x09, 0x55, 0x93, 0xbf, 0x5f, 0xb6, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, - 0xa5, 0xb8, 0x24, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, 0x44, 0xc5, 0x25, 0x90, 0x44, - 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0x17, 0xce, 0x5d, 0xaa, 0x40, 0x83, 0x4e, - 0x5a, 0xe0, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xef, 0x4f, 0x07, 0x71, 0x5c, 0xe0, 0x25, 0x11, 0xc7, 0xfe, 0x59, - 0xc4, 0xd5, 0xa2, 0x64, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x97, 0xca, 0xe4, 0xae, 0x9d, 0x1f, 0xc7, 0x65, 0x72, - 0xd7, 0x56, 0xc9, 0x1d, 0xc2, 0xf7, 0xa9, 0x4c, 0xee, 0x6d, 0xca, 0x7d, 0x5b, 0xc1, 0xcd, 0x17, 0x16, 0x70, 0x28, - 0xda, 0xa2, 0xad, 0xe5, 0x76, 0x51, 0x9b, 0xe2, 0x8a, 0x86, 0xd1, 0x14, 0xf7, 0x6c, 0xfc, 0x30, 0x7c, 0x09, 0xae, - 0x4c, 0x9a, 0xc8, 0x3f, 0x41, 0xfa, 0xe9, 0xd4, 0x06, 0xee, 0x33, 0xd2, 0xe9, 0xcf, 0xae, 0x44, 0xbb, 0xdb, 0x6f, - 0xb5, 0x66, 0xb0, 0x77, 0x33, 0x52, 0xf8, 0x62, 0xb3, 0x96, 0x89, 0xaf, 0x73, 0x98, 0xad, 0xd7, 0x87, 0x05, 0x32, - 0x1b, 0x6e, 0xca, 0x62, 0x3d, 0x9c, 0x8d, 0x70, 0x07, 0x7f, 0xc8, 0x10, 0x5a, 0xb1, 0xe1, 0x6c, 0x44, 0xd8, 0x70, - 0xd6, 0xea, 0x8e, 0xac, 0xa1, 0x9d, 0xd9, 0x8a, 0x1b, 0x08, 0xa1, 0x39, 0x1b, 0x9d, 0x98, 0x92, 0xd2, 0xe5, 0xdb, - 0x2f, 0x5a, 0x07, 0xf4, 0x53, 0x8d, 0xe0, 0x65, 0x12, 0xf7, 0xa0, 0x2f, 0x7a, 0x65, 0x9f, 0x6e, 0x2d, 0xc9, 0xe9, - 0x49, 0xed, 0x6a, 0x4f, 0x11, 0x36, 0x3d, 0xa9, 0xe3, 0xf2, 0xd8, 0x34, 0xe3, 0xba, 0x94, 0xee, 0x3b, 0xd4, 0x8c, - 0xfc, 0xe5, 0x60, 0x01, 0x08, 0x52, 0xc3, 0xa3, 0x28, 0x5d, 0x38, 0xa5, 0x10, 0x2e, 0x0e, 0x2a, 0x3b, 0x30, 0x29, - 0x48, 0xa7, 0x5f, 0x18, 0x4b, 0xff, 0xc2, 0x45, 0x34, 0xa5, 0x98, 0x92, 0xcc, 0x97, 0x2c, 0x0c, 0x58, 0xe8, 0x36, - 0xe5, 0x99, 0x81, 0x5e, 0x69, 0x84, 0x73, 0x02, 0xf1, 0x90, 0xfa, 0xa5, 0x31, 0xf0, 0x8a, 0x67, 0xed, 0x72, 0xc8, - 0x46, 0xe8, 0xe4, 0x14, 0xd3, 0xe1, 0x1f, 0xd9, 0xa2, 0x0b, 0x8f, 0x05, 0xfe, 0x31, 0x22, 0xb3, 0xb6, 0xac, 0x12, - 0x04, 0x24, 0xe4, 0x6d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x86, 0x6c, 0xd4, 0x9e, 0x55, 0x15, 0x7b, - 0xbe, 0x62, 0x4b, 0x56, 0x09, 0xb6, 0x62, 0xcb, 0x55, 0x0c, 0x5f, 0x67, 0x30, 0x20, 0x08, 0x01, 0xc0, 0x00, 0x00, - 0x1a, 0x05, 0xd1, 0x7c, 0xb1, 0x22, 0x7e, 0xb3, 0xdb, 0x7b, 0xfc, 0x0e, 0x58, 0xa0, 0x35, 0xf6, 0xff, 0x3e, 0x94, - 0x01, 0x7b, 0xca, 0xd2, 0xc4, 0xcc, 0x2d, 0xad, 0x8a, 0x0e, 0xa0, 0x52, 0x21, 0x4c, 0x69, 0x20, 0x73, 0x98, 0x19, - 0xa8, 0x05, 0x5a, 0x83, 0x62, 0xa8, 0x47, 0xed, 0x0c, 0x8e, 0x18, 0x78, 0x87, 0x86, 0xcc, 0x8c, 0x31, 0x61, 0x5c, - 0xc0, 0x14, 0x33, 0x03, 0x9e, 0x59, 0xda, 0xd9, 0x48, 0x23, 0xcb, 0x0d, 0x8a, 0xc1, 0x5f, 0x3a, 0x56, 0xc3, 0xb2, - 0xdd, 0x1d, 0xa1, 0x43, 0x42, 0xec, 0xc7, 0x08, 0x36, 0x99, 0x4b, 0x6d, 0x99, 0xef, 0x93, 0x5e, 0x6a, 0x3f, 0xe1, - 0xcf, 0x68, 0x63, 0x76, 0x00, 0xe8, 0xc8, 0xb0, 0x59, 0x7f, 0xd9, 0x50, 0x79, 0xfd, 0xba, 0x37, 0x4a, 0xe5, 0xbe, - 0x77, 0xa7, 0x03, 0xd5, 0x44, 0xe8, 0xad, 0x87, 0xab, 0x87, 0x7a, 0x08, 0x98, 0x31, 0x98, 0x5b, 0x66, 0xf4, 0xad, - 0x10, 0xc9, 0x25, 0x91, 0xc0, 0x92, 0x60, 0x4a, 0x18, 0xec, 0xad, 0xa3, 0x23, 0x53, 0x8d, 0xb5, 0xe0, 0x79, 0x52, - 0x04, 0x82, 0x81, 0x8f, 0xa0, 0x0c, 0x68, 0xa2, 0xcc, 0x6d, 0x38, 0xf9, 0x95, 0xb9, 0x5f, 0xb8, 0xba, 0x7d, 0x2c, - 0x9d, 0xb6, 0xd5, 0x5c, 0x8f, 0x57, 0x05, 0xee, 0xab, 0x7b, 0x49, 0xab, 0xe0, 0x46, 0xf6, 0x26, 0x4f, 0x99, 0xbb, - 0x75, 0x5f, 0xaa, 0xb7, 0xbf, 0x99, 0x5e, 0xd5, 0x4c, 0x6f, 0xb7, 0x99, 0x30, 0xae, 0xe4, 0xd7, 0xac, 0x22, 0xcd, - 0xc9, 0x9a, 0xa8, 0x05, 0x15, 0xff, 0xa4, 0x0b, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x41, 0xae, 0x0f, - 0x0b, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, 0x00, 0x2f, 0xaf, 0xaa, 0xc7, 0x07, 0xb8, 0x14, 0x3f, 0xc9, 0xdc, 0x45, - 0x39, 0x15, 0x52, 0x4b, 0xc1, 0x22, 0x64, 0x50, 0xd5, 0xc5, 0xc0, 0x5e, 0xd9, 0xbd, 0x27, 0x06, 0x7c, 0x58, 0x47, - 0xcc, 0x1b, 0x99, 0xe7, 0x3e, 0xbe, 0xa5, 0x29, 0x76, 0x6a, 0xe2, 0x8c, 0xfc, 0x92, 0xc5, 0x05, 0xc8, 0x66, 0xc3, - 0xfa, 0xb5, 0xdf, 0x56, 0x17, 0x97, 0xed, 0x58, 0x0c, 0xcc, 0x13, 0x27, 0xdf, 0x95, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, - 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, 0xe8, 0xe4, 0xce, 0xa6, 0xdd, 0x87, 0x69, 0xf7, 0x26, 0xad, 0x07, 0xe5, - 0x80, 0x34, 0xbb, 0x32, 0xbd, 0x7b, 0xff, 0x7d, 0x0f, 0x2f, 0xdd, 0x6e, 0x20, 0x12, 0xf7, 0xe2, 0x89, 0x31, 0x86, - 0x78, 0x0b, 0x36, 0xa2, 0xea, 0xe8, 0xe8, 0x07, 0xe7, 0x7d, 0x5b, 0xcb, 0xb2, 0x5f, 0x0b, 0x07, 0xb6, 0xc5, 0x54, - 0xba, 0xbc, 0x5c, 0x66, 0x4b, 0xb0, 0xeb, 0x3c, 0xfc, 0x4a, 0x3c, 0x7c, 0x11, 0x32, 0x2d, 0xd6, 0x55, 0xfc, 0xb5, - 0xcc, 0x2b, 0x0f, 0x51, 0x0d, 0x11, 0x48, 0x6b, 0xeb, 0xd2, 0xd0, 0x74, 0xf4, 0x66, 0x46, 0x73, 0x79, 0xfb, 0x4e, - 0x4a, 0x3d, 0xb2, 0x2f, 0x72, 0xeb, 0x04, 0x1e, 0x2d, 0x6c, 0x30, 0x34, 0xf7, 0x95, 0x77, 0x92, 0x0d, 0x88, 0xda, - 0x1c, 0x77, 0x28, 0x89, 0xc4, 0xa2, 0xbe, 0x0b, 0xe1, 0x70, 0x17, 0x82, 0x79, 0x15, 0xb4, 0x0d, 0x62, 0xb7, 0xbb, - 0xa0, 0x6d, 0xe0, 0xd4, 0x6d, 0x03, 0xb7, 0x07, 0x83, 0x85, 0xbd, 0x0f, 0x2f, 0xc7, 0x72, 0x2c, 0x1c, 0x7f, 0xf0, - 0xd6, 0x3e, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3e, 0x73, 0x20, 0x48, 0x9c, 0xe1, 0xe8, 0x47, 0xce, 0x6e, 0xad, 0xe5, - 0xf0, 0x7c, 0xb1, 0xd4, 0x2c, 0x37, 0x77, 0xd4, 0xa0, 0xe2, 0x6b, 0xfa, 0x79, 0xfd, 0x9c, 0x35, 0x74, 0xe3, 0x6f, - 0x21, 0x8c, 0x84, 0x53, 0x76, 0x18, 0x85, 0x84, 0x0d, 0x66, 0x55, 0xc5, 0x6b, 0xfb, 0x0d, 0xe2, 0x3d, 0x68, 0x13, - 0x4e, 0xb0, 0x6c, 0x5c, 0x50, 0x45, 0xd8, 0xc6, 0x1b, 0x0b, 0xa2, 0x3c, 0x3c, 0xd8, 0x31, 0x9a, 0x5e, 0x6d, 0x20, - 0xd0, 0xf1, 0x20, 0x6a, 0x47, 0x2d, 0x96, 0xba, 0xa0, 0xcc, 0x3e, 0xc2, 0xb8, 0xba, 0x3a, 0x33, 0x71, 0xda, 0x2b, - 0xbd, 0xfa, 0x6f, 0x19, 0x18, 0xe0, 0x0b, 0xf0, 0x12, 0x0b, 0xa3, 0xbb, 0x0e, 0x75, 0x0b, 0xea, 0xcb, 0x16, 0x1b, - 0xa1, 0xf5, 0xba, 0x53, 0x3d, 0x03, 0xe5, 0xae, 0xb9, 0x84, 0xbd, 0xe6, 0x12, 0xee, 0x9a, 0x4b, 0xf8, 0x6b, 0x2e, - 0x61, 0xae, 0xb9, 0x84, 0xbf, 0xe6, 0xf2, 0x20, 0xfc, 0x3e, 0x88, 0xe3, 0x18, 0x73, 0x88, 0xab, 0xa8, 0x6d, 0x64, - 0x3c, 0xb8, 0xf0, 0x3c, 0x64, 0x89, 0xaa, 0x96, 0x3f, 0x8c, 0x21, 0x57, 0x6c, 0xdb, 0x4a, 0x18, 0xb7, 0x29, 0xa6, - 0x20, 0x72, 0xfa, 0xd1, 0x51, 0xed, 0xee, 0x3c, 0xec, 0x8c, 0x52, 0x8e, 0x57, 0xd6, 0x89, 0xf6, 0x5f, 0xa0, 0x93, - 0x37, 0xbf, 0x7e, 0x4d, 0xe5, 0x86, 0x08, 0x67, 0x72, 0x7f, 0xd8, 0xf5, 0x94, 0xe2, 0xfb, 0xcc, 0x84, 0x27, 0xe7, - 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0x7f, 0xb3, 0xf7, 0xae, 0xcb, 0x6d, 0x23, 0x59, 0xba, 0xe8, 0xab, - 0x48, 0x0c, 0x9b, 0x05, 0x98, 0x49, 0x8a, 0xf2, 0xde, 0x33, 0x11, 0x07, 0x54, 0x9a, 0x61, 0xcb, 0xe5, 0x2e, 0x77, - 0xf9, 0xd6, 0xb6, 0xab, 0xba, 0xaa, 0x19, 0x3c, 0x2a, 0x08, 0x48, 0x12, 0x70, 0x81, 0x00, 0x0b, 0x00, 0x25, 0xd2, - 0x24, 0xde, 0x7d, 0xc7, 0x5a, 0x2b, 0xaf, 0x20, 0x28, 0xbb, 0x67, 0xf6, 0xfc, 0x3a, 0xe7, 0x8f, 0x2d, 0x26, 0x12, - 0x89, 0xbc, 0xe7, 0xca, 0x75, 0xf9, 0xbe, 0x88, 0x17, 0xb4, 0xde, 0x55, 0x28, 0x3c, 0xaa, 0xa2, 0x94, 0x5b, 0xc9, - 0x75, 0x06, 0x41, 0xec, 0xe8, 0x85, 0xe1, 0x4f, 0x20, 0x84, 0x20, 0xc2, 0x84, 0xdf, 0x86, 0x19, 0x6d, 0x67, 0x91, - 0x4e, 0xfa, 0x7d, 0x98, 0xe1, 0x06, 0x56, 0xf2, 0x73, 0xd5, 0x67, 0xfb, 0x6d, 0x10, 0xb2, 0x5d, 0x10, 0xb1, 0xdb, - 0x62, 0x1b, 0x94, 0xd6, 0x91, 0xf8, 0x49, 0x19, 0xfe, 0x16, 0x5e, 0x2f, 0x0f, 0x21, 0xde, 0xa7, 0x97, 0xe6, 0x67, - 0x69, 0x2b, 0x0a, 0x70, 0x1f, 0xa1, 0x47, 0x75, 0x20, 0xd8, 0x09, 0x4f, 0x78, 0x00, 0x27, 0xab, 0x59, 0xc5, 0x3f, - 0xa4, 0x20, 0x4e, 0x14, 0x1c, 0x02, 0xae, 0xb6, 0x9f, 0xd2, 0xaf, 0x60, 0xf8, 0xd2, 0xc1, 0x96, 0xc3, 0xdb, 0x62, - 0xdb, 0x63, 0x25, 0x7f, 0x04, 0xec, 0x5b, 0x3d, 0x19, 0xab, 0xdb, 0x03, 0x67, 0x5d, 0x4a, 0xd1, 0xf1, 0xa6, 0x38, - 0xbc, 0x3d, 0x9f, 0xed, 0xb7, 0x41, 0xc4, 0x76, 0x41, 0x86, 0xb5, 0x4e, 0x1a, 0x8e, 0x83, 0x21, 0x7c, 0x16, 0x23, - 0xec, 0xff, 0xa2, 0x1e, 0x78, 0x09, 0xa9, 0xa1, 0xc0, 0xc5, 0x60, 0xc3, 0xd1, 0xda, 0x2e, 0xd3, 0xc0, 0x4d, 0x0d, - 0x7a, 0x7d, 0x4f, 0x21, 0xca, 0x0b, 0x46, 0x73, 0x23, 0x58, 0x37, 0x86, 0x5c, 0x1c, 0x8e, 0x9b, 0xc5, 0x90, 0x97, - 0x34, 0x9d, 0x06, 0xa1, 0x74, 0x67, 0x59, 0x43, 0x12, 0x65, 0x1f, 0x84, 0xda, 0xb5, 0x65, 0xbf, 0x0d, 0x6c, 0x5f, - 0xfe, 0x68, 0x18, 0xfb, 0x17, 0x8b, 0x27, 0x42, 0xba, 0x88, 0xe7, 0x20, 0x88, 0xda, 0xcf, 0xb3, 0xe1, 0xc6, 0xbf, - 0x58, 0x3f, 0x11, 0xca, 0x6f, 0x3c, 0xb7, 0xe5, 0x10, 0x91, 0xb5, 0xf0, 0x85, 0xf1, 0xf0, 0xe0, 0xca, 0xd0, 0x76, - 0x38, 0x08, 0xfd, 0xb7, 0x59, 0x23, 0xb8, 0xb1, 0xa1, 0x7d, 0xbe, 0xf0, 0x61, 0x6b, 0xa3, 0xb1, 0xa6, 0x98, 0x6e, - 0xa1, 0x7f, 0x93, 0xd9, 0xd2, 0x9e, 0x46, 0x25, 0x2f, 0x4e, 0x4d, 0x23, 0x16, 0xc2, 0x80, 0xa1, 0x9f, 0xcc, 0x23, - 0x50, 0xcd, 0x1d, 0x8f, 0x40, 0x26, 0x1f, 0xe8, 0xc1, 0x9a, 0xd4, 0xaa, 0xbf, 0x86, 0x99, 0xfc, 0x3f, 0x52, 0x61, - 0x31, 0xba, 0xdb, 0x86, 0x99, 0xfa, 0x23, 0x92, 0x7f, 0xb0, 0x9c, 0xef, 0x52, 0x2f, 0xd4, 0x7e, 0x2c, 0xac, 0xc0, - 0xa0, 0x44, 0xd5, 0x80, 0x1e, 0x88, 0xa0, 0x2a, 0x83, 0x34, 0xc3, 0xea, 0x1c, 0xf4, 0xbb, 0xa7, 0x55, 0x47, 0x72, - 0x48, 0x6b, 0x35, 0xa4, 0x82, 0xa9, 0x52, 0x83, 0xfc, 0x70, 0x58, 0xa6, 0x4c, 0x97, 0x01, 0x97, 0xf4, 0x65, 0xaa, - 0x94, 0xc2, 0x7f, 0x21, 0x00, 0x9d, 0x83, 0x7b, 0x7c, 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, - 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, 0xb9, 0x4c, 0x21, 0x82, 0xaa, 0x84, 0xfa, 0x56, 0xa6, 0x41, - 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, 0x11, 0xd7, 0x33, 0xc2, 0x9a, - 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, 0x8d, 0xab, 0x4a, 0x55, 0x77, - 0x73, 0x6a, 0x29, 0x2d, 0xda, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, 0xe4, 0x08, 0x26, 0x90, 0x24, - 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, - 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0xff, 0x25, 0x8c, 0x34, 0x99, 0xb1, 0x92, 0x45, - 0xb6, 0xab, 0x53, 0xe2, 0x3c, 0x4e, 0x60, 0x7b, 0x34, 0xbd, 0xe5, 0xfb, 0x0c, 0xa2, 0x82, 0x40, 0xc1, 0x8c, 0xf9, - 0xb2, 0x8b, 0xa7, 0xbe, 0xcf, 0x2c, 0x53, 0xf7, 0xe1, 0x60, 0xcc, 0xd8, 0x7e, 0xbf, 0x9f, 0xf7, 0xfb, 0x6a, 0xbe, - 0xf5, 0xfb, 0xc9, 0x33, 0xf3, 0xb7, 0x07, 0x0c, 0x0a, 0x72, 0x22, 0x9a, 0x0a, 0x11, 0xfc, 0x43, 0xf2, 0x04, 0xc9, - 0xe8, 0x8e, 0xfb, 0xdc, 0x72, 0xb6, 0xac, 0x8e, 0x40, 0x30, 0x0f, 0x87, 0x4b, 0x05, 0x76, 0x2d, 0x51, 0x24, 0x64, - 0xf9, 0x4f, 0xc0, 0x78, 0xe6, 0x3e, 0xc0, 0x92, 0x01, 0x08, 0x5b, 0xe5, 0xe9, 0x7a, 0xcf, 0x57, 0xc1, 0x3b, 0x1d, - 0xef, 0x1a, 0x2b, 0x32, 0x10, 0xb7, 0xc0, 0x46, 0xac, 0xb5, 0x07, 0xe4, 0x4c, 0x01, 0x8e, 0x17, 0x87, 0xc3, 0xb9, - 0xfc, 0xa5, 0x9b, 0xad, 0x13, 0xa8, 0x14, 0xb8, 0x3d, 0x3a, 0x39, 0xf8, 0x1f, 0x40, 0x33, 0x28, 0x87, 0x79, 0xbd, - 0xfd, 0x83, 0x39, 0xf9, 0xe9, 0x29, 0xfe, 0x09, 0x0f, 0xd1, 0xe9, 0xb7, 0x7b, 0xf3, 0x07, 0x45, 0xe5, 0xe1, 0xa0, - 0x16, 0xff, 0x39, 0xe7, 0x15, 0xfc, 0xc2, 0x37, 0x81, 0xd9, 0x64, 0xea, 0x9d, 0x7c, 0x93, 0xe7, 0x4c, 0xbd, 0xc6, - 0x2b, 0x26, 0xdf, 0xe1, 0x70, 0x2e, 0x46, 0xf5, 0x76, 0xe4, 0x44, 0x3b, 0xe5, 0x18, 0x07, 0x83, 0xff, 0x22, 0xda, - 0x26, 0x04, 0x18, 0xca, 0xe1, 0xc8, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, - 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, 0x88, 0x53, 0x9c, 0x80, 0x08, - 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x08, 0xc1, 0x90, 0x6f, 0x24, 0xe0, 0xae, 0xd7, 0xab, 0x31, 0xbe, - 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, 0x81, 0x67, 0xcb, 0xde, 0x44, - 0xb9, 0xdb, 0xf0, 0xb4, 0x9f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, - 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, - 0xc6, 0xbf, 0xd3, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0x27, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, - 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, - 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0xb3, 0xf1, 0x14, 0xfe, 0x07, - 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, 0xb6, 0xb6, 0xa3, 0x3f, 0x76, 0x10, 0xe9, 0xb8, 0x27, - 0x17, 0xea, 0x4b, 0x48, 0x25, 0x17, 0xea, 0x06, 0x62, 0x17, 0x6a, 0xbc, 0xe3, 0x22, 0xd6, 0xfa, 0xdb, 0x1a, 0x05, - 0x2b, 0x01, 0x67, 0xda, 0x5b, 0x30, 0xd8, 0xc0, 0xba, 0x65, 0x19, 0xfc, 0x0d, 0xd7, 0x34, 0x81, 0x1b, 0x16, 0x59, - 0xef, 0x0d, 0xb6, 0xd2, 0x5b, 0x70, 0xb4, 0x4c, 0x9c, 0x4b, 0x49, 0x52, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, - 0xdd, 0xdf, 0x8a, 0xfa, 0x5e, 0x88, 0x3c, 0x58, 0xa5, 0x2c, 0x2a, 0x56, 0x20, 0xb3, 0x07, 0xff, 0x0a, 0x19, 0x39, - 0xca, 0x81, 0xa3, 0xd0, 0x3f, 0x9a, 0x40, 0xe7, 0xa9, 0x23, 0x9d, 0x47, 0x82, 0xad, 0xd4, 0x43, 0x61, 0xe5, 0x05, - 0x44, 0x07, 0xdb, 0x31, 0xb7, 0xf2, 0x24, 0x54, 0x6c, 0xca, 0x44, 0x1e, 0x07, 0xb5, 0x04, 0x8c, 0x15, 0x04, 0x73, - 0x96, 0x4b, 0x17, 0xa4, 0xaa, 0xd1, 0xc3, 0x22, 0x73, 0x3f, 0x16, 0x94, 0xff, 0xb1, 0xca, 0x09, 0xd7, 0x97, 0x21, - 0xc0, 0xd1, 0x3e, 0x06, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x78, 0x27, 0x33, 0x67, 0x53, 0xdb, 0x4b, 0x90, 0xb1, 0x1d, - 0x7e, 0x85, 0xd0, 0x6a, 0xa1, 0xc8, 0xa2, 0xe1, 0x82, 0xe9, 0xf6, 0x94, 0x56, 0xdd, 0xc3, 0x86, 0x27, 0xa5, 0x87, - 0x4a, 0x7d, 0x1b, 0x13, 0x58, 0x56, 0x29, 0xc3, 0xb7, 0x13, 0xaa, 0x4e, 0x0c, 0x2a, 0xd6, 0x0d, 0x5b, 0xc0, 0x21, - 0x16, 0x93, 0xc6, 0x3a, 0x1b, 0xf0, 0x88, 0x25, 0xf0, 0xcf, 0x86, 0x8f, 0xd9, 0x82, 0x47, 0x93, 0xcd, 0xd5, 0xa2, - 0xdf, 0x2f, 0xbd, 0xd0, 0xab, 0x67, 0xd9, 0xe3, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, - 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x31, 0xbc, 0xf6, 0x98, 0x47, 0x6a, 0x49, 0x25, 0x57, 0x19, 0xec, - 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, - 0x83, 0x8e, 0xfc, 0xdb, 0x1d, 0x52, 0xea, 0x26, 0x03, 0xb0, 0x1b, 0x0d, 0x70, 0xc8, 0x54, 0x2f, 0x45, 0x56, 0x2f, - 0x65, 0xaa, 0x97, 0x64, 0xe5, 0x12, 0x2c, 0x24, 0xa6, 0xca, 0x6d, 0x64, 0xe5, 0x16, 0x0d, 0xd7, 0xc3, 0xc1, 0xd6, - 0x8a, 0xcb, 0x66, 0x09, 0xf7, 0x85, 0x15, 0x05, 0xfe, 0xdf, 0xb2, 0x1b, 0x76, 0x27, 0x8f, 0x81, 0x6b, 0x74, 0x4c, - 0x82, 0x0b, 0xc4, 0x1d, 0xbb, 0x05, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, - 0xad, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x96, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x7b, 0xfc, - 0x71, 0xbe, 0x3c, 0x1c, 0x76, 0x9e, 0x51, 0xef, 0xbd, 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xdb, 0x2b, 0x1e, 0x4f, - 0x06, 0x83, 0xb7, 0xfe, 0x0d, 0xaf, 0x67, 0x6f, 0x41, 0x3b, 0x70, 0x7e, 0x23, 0x75, 0xcd, 0xde, 0x2d, 0xcf, 0xbc, - 0x1b, 0x1c, 0x9b, 0x5b, 0x38, 0x7a, 0xfb, 0x7d, 0x6f, 0xc9, 0x23, 0xef, 0x96, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, - 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0xb7, 0xc1, 0x7b, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, - 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, - 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xbf, 0x65, 0x77, 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, - 0x50, 0xea, 0xda, 0x32, 0xac, 0xb4, 0xae, 0x7c, 0x08, 0x1c, 0x0e, 0xc8, 0x4f, 0x4b, 0xc4, 0x41, 0x68, 0xdd, 0x64, - 0x35, 0x57, 0x94, 0x73, 0xa1, 0x0d, 0x33, 0x2f, 0x07, 0x16, 0xb3, 0x94, 0x42, 0x63, 0x01, 0x80, 0x60, 0x52, 0x68, - 0xed, 0xbd, 0x0c, 0x20, 0x27, 0x68, 0xf8, 0x63, 0x73, 0x55, 0x96, 0xb5, 0x6c, 0x49, 0x88, 0xb2, 0x5d, 0x0f, 0x2f, - 0x11, 0x32, 0xad, 0xdf, 0x3f, 0x27, 0x92, 0xb5, 0x49, 0x75, 0x55, 0xa3, 0x25, 0xa0, 0x22, 0x4b, 0xc0, 0xc4, 0xaf, - 0x34, 0x9f, 0x00, 0x3c, 0xe9, 0x78, 0x50, 0x3d, 0xe6, 0x35, 0x13, 0x44, 0xb6, 0x51, 0xf9, 0x93, 0xe2, 0x19, 0x92, - 0x11, 0x14, 0x8f, 0x6b, 0x95, 0xb1, 0x30, 0xcc, 0x03, 0x05, 0xe4, 0xdd, 0xbb, 0x53, 0xdf, 0xda, 0x1f, 0x3b, 0xf6, - 0x6c, 0xad, 0x42, 0x2d, 0xd4, 0x14, 0x2e, 0x39, 0x44, 0x57, 0xa0, 0x81, 0x22, 0x92, 0xf1, 0xe4, 0xf5, 0xe0, 0x72, - 0x12, 0x5d, 0x71, 0x81, 0xce, 0xf8, 0xfa, 0xa6, 0x9b, 0xce, 0xa2, 0xc7, 0xd5, 0x7c, 0x42, 0x4a, 0xb2, 0xc3, 0x21, - 0x1b, 0x55, 0x75, 0xb1, 0x9e, 0x86, 0xf2, 0xa7, 0x87, 0xe0, 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x98, 0x2a, - 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x71, 0x25, 0xf7, 0x3d, 0x20, 0xad, 0xe5, 0x25, 0x97, 0xef, 0x47, 0x88, 0x31, 0xe2, - 0x07, 0x5e, 0xc9, 0x23, 0x16, 0xaa, 0x29, 0x5c, 0xf3, 0x08, 0x41, 0xde, 0x32, 0x1d, 0xfc, 0xad, 0x27, 0x4e, 0xf7, - 0x27, 0x4a, 0xbb, 0xf8, 0xc2, 0xa2, 0xee, 0x39, 0xd2, 0x0d, 0xc8, 0xc1, 0x86, 0xe9, 0xa2, 0x20, 0xdb, 0x94, 0x46, - 0xd0, 0x46, 0xcb, 0x81, 0x0d, 0xa7, 0x52, 0x1b, 0xce, 0x5c, 0x43, 0x70, 0x9f, 0x9f, 0xa7, 0xa3, 0x1b, 0xf8, 0x90, - 0xea, 0xf6, 0x12, 0x3f, 0x1f, 0x36, 0x1c, 0xc9, 0xec, 0x88, 0xcf, 0x6c, 0x22, 0xe9, 0xa4, 0xce, 0x15, 0xb0, 0xdb, - 0xd9, 0x35, 0xc8, 0x11, 0x33, 0xf7, 0x15, 0xaa, 0x6f, 0xd1, 0x80, 0x2b, 0x63, 0xed, 0x6b, 0x92, 0xb1, 0xf0, 0xaa, - 0x9c, 0x86, 0x03, 0x80, 0xa1, 0xcb, 0xe8, 0x6b, 0x8b, 0x4d, 0x96, 0xbd, 0x29, 0x20, 0x08, 0xa2, 0x24, 0x1e, 0x1f, - 0xf0, 0xbe, 0xac, 0x86, 0x1a, 0x25, 0x1f, 0xcb, 0x4e, 0xe0, 0xeb, 0x25, 0xfa, 0xbb, 0x31, 0x97, 0x18, 0xf0, 0xba, - 0x6a, 0x0b, 0x0a, 0xe7, 0xf9, 0xe1, 0x70, 0x9e, 0x8f, 0x8c, 0x67, 0x19, 0xa8, 0x56, 0xa6, 0x75, 0xb0, 0x31, 0xf3, - 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xbe, 0xf2, 0x74, 0xa7, 0xfa, - 0x6c, 0x7f, 0x63, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, - 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, 0x9d, 0xc6, 0x36, 0x3c, 0xb6, 0xb0, 0x1a, 0xbd, - 0x35, 0x5b, 0xb2, 0x15, 0xbb, 0x55, 0x75, 0xba, 0xe1, 0xe1, 0x74, 0x78, 0x19, 0xe0, 0xea, 0x5b, 0x9f, 0x73, 0xbe, - 0xa4, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, 0xd6, 0x8f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0x7e, 0x43, 0xeb, 0x4f, - 0xcc, 0x96, 0x26, 0x79, 0x39, 0xe0, 0x37, 0x93, 0xf5, 0xe3, 0x08, 0x5e, 0x7d, 0x0c, 0x56, 0x8c, 0xcc, 0x99, 0x65, - 0xeb, 0xc7, 0x11, 0x8e, 0xd9, 0xf2, 0x71, 0x44, 0xa3, 0xb6, 0x92, 0xfb, 0xd2, 0x6d, 0x03, 0xc2, 0xca, 0x2d, 0x8b, - 0xe1, 0x35, 0x10, 0xcf, 0xb4, 0x91, 0x74, 0x2d, 0x0d, 0xbd, 0x31, 0x0f, 0xa7, 0x71, 0xb0, 0xa6, 0x56, 0xc8, 0x33, - 0x43, 0xcc, 0xe2, 0xc7, 0xd1, 0x9c, 0xad, 0xb0, 0x22, 0x1b, 0x1e, 0x0f, 0x2e, 0x27, 0x9b, 0x2b, 0xbe, 0x06, 0xf2, - 0xb3, 0xc9, 0xc6, 0x6c, 0x51, 0xb7, 0x5c, 0xcc, 0x36, 0x8f, 0xa3, 0xf9, 0x64, 0x05, 0x3d, 0x6b, 0x0f, 0x98, 0xf7, - 0x0a, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x25, 0x5b, 0x5f, 0x06, 0xb7, 0x6c, 0x3d, - 0x06, 0x22, 0x0e, 0xea, 0x77, 0x6f, 0x03, 0x8b, 0x2f, 0x62, 0xeb, 0x4b, 0x93, 0xb6, 0x79, 0x1c, 0x31, 0x77, 0x70, - 0x1a, 0xb8, 0x60, 0x2d, 0x32, 0x6f, 0xc5, 0xe0, 0x12, 0xb2, 0xf0, 0x62, 0xb6, 0x19, 0x5e, 0xb2, 0xf5, 0x08, 0xa7, - 0x7a, 0xe2, 0xb3, 0x25, 0xbf, 0x65, 0x09, 0x5f, 0x35, 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, - 0xcc, 0x9c, 0xf7, 0x16, 0x46, 0xe5, 0xbe, 0x05, 0x07, 0x14, 0xa4, 0x6d, 0x80, 0x20, 0x89, 0x67, 0x77, 0x1d, 0xae, - 0x3f, 0x49, 0x61, 0xc0, 0x4d, 0x60, 0x06, 0x0c, 0x4c, 0x3f, 0x83, 0x1f, 0x56, 0xba, 0x44, 0x88, 0xb3, 0x9f, 0x52, - 0x92, 0xcc, 0xf3, 0xf7, 0x22, 0xcd, 0xdd, 0xc2, 0x75, 0x0a, 0xb3, 0xa2, 0x40, 0xf5, 0x53, 0x52, 0x1a, 0x58, 0xa8, - 0x44, 0xa6, 0x52, 0xf0, 0xcb, 0xe6, 0x3c, 0xca, 0x8e, 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, - 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, - 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, - 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xad, 0x33, 0x07, 0x69, 0x4b, 0xf3, 0x5d, 0x13, 0x3f, 0x87, 0x05, 0x5c, 0x44, 0x0b, - 0x5b, 0xc3, 0xa3, 0x2a, 0x56, 0xee, 0x4d, 0x9e, 0x23, 0x9c, 0xd1, 0xa5, 0x4c, 0x00, 0x5c, 0xef, 0x97, 0x61, 0xad, - 0xf0, 0x8a, 0x9a, 0x9b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, - 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, - 0x0b, 0x40, 0x4d, 0x3f, 0xd5, 0x62, 0x5d, 0x05, 0xa5, 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, - 0x26, 0x4a, 0xe4, 0xfc, 0xb8, 0x29, 0xc5, 0xa2, 0x14, 0x55, 0xd2, 0x6e, 0x28, 0x78, 0x44, 0xb8, 0x0d, 0x1a, 0x33, - 0xb7, 0x27, 0xba, 0x68, 0x45, 0x28, 0xc7, 0x66, 0x1d, 0x23, 0x8d, 0x32, 0x3b, 0xd9, 0x75, 0xb2, 0xd0, 0x7e, 0x5f, - 0xe5, 0x90, 0x75, 0xc0, 0x1a, 0xc9, 0xd7, 0x6b, 0x0e, 0xdd, 0x36, 0xca, 0x8b, 0x7b, 0xcf, 0x57, 0x70, 0x9a, 0xe3, - 0x89, 0xdd, 0xf5, 0xba, 0x53, 0x24, 0xe2, 0x15, 0x4e, 0xaa, 0x7c, 0x24, 0x0b, 0xc7, 0x9d, 0x3b, 0xad, 0xc5, 0xaa, - 0x72, 0x59, 0x4f, 0x2d, 0x8e, 0x08, 0x7c, 0x2a, 0x8f, 0xf6, 0x42, 0xdb, 0xa2, 0x58, 0x08, 0xa3, 0x47, 0x27, 0xfc, - 0xa4, 0x04, 0xd6, 0xd7, 0xe1, 0xb0, 0xf4, 0x23, 0x8e, 0x7e, 0xa7, 0xd1, 0xe8, 0x86, 0x90, 0x86, 0xa7, 0x5e, 0x34, - 0xba, 0xa9, 0x8b, 0x3a, 0xcc, 0x9e, 0xe5, 0x7a, 0xa0, 0x30, 0x8c, 0x40, 0xfd, 0xe0, 0x2a, 0x83, 0xcf, 0x22, 0x44, - 0xcd, 0x03, 0xd3, 0x6c, 0x08, 0x47, 0x5d, 0xe0, 0xa1, 0x15, 0xb4, 0x98, 0x99, 0x8f, 0x42, 0x0c, 0x1f, 0xd2, 0xc5, - 0xf9, 0x13, 0xb2, 0xf2, 0x01, 0x76, 0x87, 0xee, 0x42, 0x39, 0x67, 0x2a, 0x06, 0xf8, 0x51, 0x40, 0x3e, 0x4a, 0xc0, - 0xcd, 0x00, 0xd9, 0x23, 0x4b, 0x00, 0xb1, 0x62, 0x74, 0x34, 0xf9, 0xdc, 0xf7, 0x22, 0x05, 0xef, 0xec, 0xb3, 0x5c, - 0x4d, 0x18, 0x0a, 0x9f, 0x18, 0xe8, 0xe6, 0x37, 0x7e, 0x7b, 0xde, 0x82, 0x91, 0x5d, 0x92, 0xe2, 0xb5, 0x66, 0xb8, - 0xdf, 0x80, 0xdb, 0x11, 0x50, 0xd6, 0x54, 0xc7, 0x24, 0xdb, 0x34, 0x44, 0x32, 0x60, 0x46, 0x8c, 0x08, 0x2a, 0xcb, - 0x85, 0xff, 0xdd, 0xcb, 0xa2, 0xc0, 0x01, 0x5c, 0xcd, 0x64, 0xf0, 0xda, 0x85, 0x51, 0x01, 0x70, 0x4e, 0x43, 0xa7, - 0xb4, 0x57, 0x55, 0x87, 0x64, 0xd5, 0xfc, 0x60, 0x36, 0x6f, 0x1a, 0x26, 0x46, 0x04, 0xd1, 0x45, 0x38, 0xc1, 0xf4, - 0x8a, 0xf4, 0xb5, 0x92, 0xd3, 0xd1, 0xaa, 0xa3, 0xb5, 0xc4, 0xc4, 0x5c, 0x51, 0xfc, 0x35, 0xe0, 0x71, 0x83, 0x57, - 0x27, 0x69, 0x3a, 0x51, 0x3d, 0x7a, 0xfc, 0x3a, 0x4d, 0x27, 0x25, 0xee, 0x0a, 0xbf, 0x01, 0x17, 0xcd, 0x36, 0x1f, - 0xfa, 0xf1, 0x0b, 0x8a, 0xb8, 0xa8, 0xc1, 0x95, 0x77, 0xaa, 0xaf, 0x54, 0x1f, 0x41, 0x2d, 0x3c, 0x31, 0xb2, 0x16, - 0x9e, 0x5c, 0xb2, 0xd6, 0x82, 0x60, 0x66, 0x73, 0xe0, 0x42, 0x7e, 0xa5, 0x14, 0xf1, 0x26, 0x12, 0x6a, 0x31, 0x68, - 0x3d, 0x66, 0xce, 0xaa, 0xd1, 0x8d, 0xca, 0x8c, 0xd0, 0xbe, 0xad, 0x45, 0xe7, 0x37, 0xf2, 0x53, 0x9e, 0xda, 0x97, - 0xed, 0x71, 0x3e, 0xde, 0xa3, 0xbb, 0xea, 0x2c, 0x33, 0x29, 0xe3, 0x93, 0x59, 0x82, 0xc2, 0x5d, 0x82, 0x0d, 0x48, - 0xb2, 0xdf, 0xea, 0x00, 0x19, 0xb5, 0xd7, 0x7e, 0xd7, 0x59, 0xbe, 0xba, 0xd9, 0x1a, 0x8a, 0x4a, 0xad, 0x24, 0xc5, - 0x41, 0x86, 0xeb, 0xb6, 0xf2, 0xe1, 0xe2, 0x02, 0x7a, 0xc6, 0x48, 0x64, 0x9e, 0x3f, 0x91, 0x2f, 0xc1, 0x39, 0xe3, - 0xac, 0x10, 0x98, 0x30, 0x56, 0xef, 0x5a, 0x4b, 0xa5, 0x21, 0xc5, 0xd8, 0xd1, 0x28, 0xcb, 0x2a, 0x4b, 0x97, 0xd9, - 0x5a, 0xc2, 0x96, 0x55, 0xe4, 0x16, 0xb6, 0xce, 0x64, 0x35, 0x1f, 0x55, 0xdc, 0x41, 0xf9, 0x66, 0xcb, 0x8c, 0xef, - 0x25, 0xb2, 0x77, 0x1b, 0x28, 0xe1, 0xd9, 0xe8, 0x3f, 0x90, 0x7e, 0x9b, 0x61, 0x9c, 0x72, 0x5b, 0x49, 0x0b, 0x70, - 0xfa, 0x87, 0xc3, 0xa3, 0x0a, 0x83, 0x06, 0x47, 0x18, 0x47, 0xd6, 0xef, 0xdf, 0x54, 0x5e, 0x8d, 0x89, 0x3a, 0x3e, - 0xab, 0xdf, 0xaf, 0xe8, 0xe1, 0xb4, 0x1a, 0xad, 0xd2, 0x2d, 0xb2, 0x13, 0xda, 0x58, 0xf9, 0x41, 0xad, 0x80, 0xd9, - 0x5b, 0x9f, 0x4f, 0x07, 0xa0, 0x63, 0x01, 0x12, 0xcd, 0x66, 0x22, 0x31, 0x27, 0xdd, 0x93, 0xf0, 0xf8, 0xc0, 0x02, - 0x07, 0x98, 0x8a, 0xff, 0x53, 0x78, 0x33, 0xb0, 0x41, 0xa3, 0x44, 0x5f, 0xa3, 0xab, 0xda, 0xdc, 0xe8, 0x78, 0xe9, - 0x29, 0x24, 0xb2, 0x82, 0x55, 0x73, 0x5f, 0x6e, 0xe0, 0xb4, 0x87, 0x9a, 0x43, 0x65, 0x01, 0xfe, 0xf6, 0x0b, 0x30, - 0x78, 0x64, 0x50, 0xd8, 0x6e, 0x2d, 0xb4, 0x37, 0x66, 0xa9, 0x86, 0x8a, 0x70, 0xd0, 0xf9, 0x4a, 0xcc, 0xea, 0x11, - 0xfd, 0x3d, 0x3f, 0x1c, 0x56, 0x04, 0x06, 0x1c, 0x96, 0x32, 0x13, 0x2d, 0x14, 0x4b, 0xeb, 0x6c, 0x46, 0x75, 0xe0, - 0x81, 0x89, 0x39, 0x0b, 0x77, 0x00, 0xda, 0xa4, 0x56, 0x81, 0x5e, 0x45, 0xf4, 0x13, 0xf7, 0x6b, 0xfb, 0xf5, 0x7a, - 0x64, 0x96, 0x8e, 0xdc, 0x18, 0x0b, 0x00, 0x0e, 0x3c, 0xaf, 0x49, 0x9e, 0x93, 0xaf, 0xa1, 0xdd, 0x93, 0x0b, 0xf9, - 0x13, 0x94, 0x2d, 0x3c, 0x57, 0x4d, 0x2b, 0x8b, 0x15, 0x57, 0xd5, 0xab, 0x0b, 0x5e, 0x99, 0x4c, 0xab, 0xb4, 0x12, - 0x95, 0x12, 0x0c, 0xa8, 0x4b, 0xbc, 0xd6, 0x34, 0xa3, 0xd4, 0x46, 0x9d, 0x89, 0x1a, 0xb0, 0xc1, 0x7e, 0xaa, 0x36, - 0x3a, 0x39, 0x97, 0xcf, 0x2f, 0x8d, 0xc3, 0xa7, 0x5d, 0xbd, 0x99, 0xa9, 0x1c, 0xf8, 0x6b, 0xe5, 0x43, 0xab, 0xc7, - 0x40, 0x07, 0xe4, 0xf4, 0xc7, 0xb0, 0x98, 0xd8, 0x1d, 0x9a, 0xb7, 0xbb, 0xcb, 0xea, 0x22, 0xbd, 0xd3, 0x94, 0xcc, - 0xea, 0x2d, 0x9f, 0x59, 0x3d, 0x3a, 0xe0, 0xc5, 0x43, 0xbd, 0x57, 0x98, 0x49, 0x04, 0x17, 0x43, 0x35, 0x89, 0xec, - 0x0e, 0xb4, 0xe6, 0x51, 0xc5, 0x04, 0xf8, 0x41, 0xa9, 0x35, 0xbd, 0xb7, 0xbb, 0x42, 0x9d, 0x52, 0x78, 0xdc, 0x5a, - 0xf2, 0x03, 0x73, 0xa7, 0x5d, 0xeb, 0x7c, 0x3c, 0xbf, 0xf4, 0xfd, 0x46, 0x9e, 0xd0, 0x66, 0x67, 0x72, 0xfa, 0x27, - 0x6f, 0xf5, 0x0f, 0x53, 0x7d, 0x0b, 0xdd, 0x09, 0xfa, 0x0c, 0x5d, 0x55, 0xdd, 0x95, 0xd8, 0xc2, 0x50, 0x4f, 0x2c, - 0xf2, 0x42, 0x9e, 0xb4, 0xc6, 0x8e, 0x83, 0xbd, 0x01, 0x4e, 0xfc, 0xf2, 0x70, 0x10, 0x57, 0xb9, 0xcf, 0xce, 0xbb, - 0x46, 0x56, 0x0e, 0x60, 0x05, 0x51, 0x30, 0x6e, 0xcd, 0xc7, 0x36, 0x48, 0x97, 0xb8, 0x1a, 0x1f, 0xbf, 0xa1, 0x58, - 0x26, 0x9b, 0x88, 0x8b, 0x8b, 0xfc, 0xf1, 0x53, 0x20, 0x2d, 0xeb, 0xf7, 0xa3, 0x67, 0x97, 0xd3, 0xa7, 0xc3, 0x28, - 0x00, 0xc7, 0x2e, 0x7b, 0x79, 0x19, 0xf3, 0xd5, 0x25, 0xb3, 0x4c, 0x61, 0x91, 0x6f, 0x06, 0x54, 0x97, 0xac, 0x96, - 0xae, 0x57, 0x80, 0xa5, 0xcb, 0x6f, 0xee, 0xc3, 0xd4, 0x80, 0x46, 0xd6, 0xdc, 0x9d, 0xe6, 0x5a, 0xa0, 0xd4, 0xf3, - 0x7e, 0x66, 0xc8, 0xd7, 0x65, 0xd0, 0x15, 0xa4, 0x7b, 0x1e, 0x91, 0x5e, 0xee, 0xa5, 0xd3, 0xfd, 0xbe, 0x14, 0x60, - 0xa9, 0x2f, 0xc5, 0x17, 0x50, 0x58, 0x34, 0xbe, 0x11, 0xa0, 0xad, 0xa1, 0x9a, 0xf6, 0x4a, 0x51, 0xf5, 0x82, 0x5e, - 0x29, 0xbe, 0xf4, 0xf4, 0x50, 0x99, 0x2f, 0x4b, 0x47, 0xff, 0x13, 0x6a, 0x2e, 0x38, 0x21, 0x66, 0x62, 0x0e, 0xa0, - 0x12, 0xb4, 0xf1, 0xdd, 0x1e, 0x6d, 0x7c, 0xaa, 0x57, 0x71, 0xd3, 0xe7, 0xb5, 0xb5, 0xcc, 0x09, 0x61, 0xd3, 0xbd, - 0x04, 0xa8, 0xc8, 0x2b, 0xe1, 0x11, 0x2c, 0xbf, 0xfc, 0x21, 0x4f, 0x57, 0x88, 0xd6, 0x71, 0xcf, 0x32, 0x97, 0xc6, - 0xfe, 0x95, 0xc1, 0xf4, 0xf5, 0xed, 0xb6, 0xc8, 0x4f, 0x4d, 0x4c, 0x58, 0x8f, 0x15, 0x7d, 0xf3, 0x2e, 0x5c, 0x09, - 0x14, 0x38, 0x94, 0x48, 0x6c, 0x53, 0x85, 0x22, 0x1e, 0x24, 0x7d, 0xba, 0x68, 0x7d, 0x1a, 0x60, 0x6a, 0x2d, 0x07, - 0xe6, 0x10, 0xae, 0xe2, 0xc2, 0x47, 0x4f, 0xdf, 0x62, 0x16, 0xce, 0x27, 0xde, 0x47, 0xaf, 0x18, 0x99, 0x8f, 0xfb, - 0xa8, 0x54, 0xd2, 0x3f, 0x0f, 0x87, 0x59, 0x35, 0xf7, 0x1d, 0xfa, 0x48, 0x0f, 0x55, 0x2e, 0x28, 0x7b, 0x63, 0x4c, - 0x22, 0x50, 0x1a, 0xe3, 0x7d, 0x1c, 0x1c, 0xe7, 0x7d, 0x1a, 0x40, 0x6a, 0x9f, 0x78, 0x4f, 0x4a, 0x0e, 0xcf, 0x39, - 0xe6, 0x84, 0xd2, 0x8a, 0x80, 0x09, 0x3d, 0x43, 0xb9, 0xee, 0x94, 0x82, 0x49, 0x0e, 0x09, 0x86, 0xbf, 0x6a, 0xde, - 0xc4, 0x0a, 0x84, 0x5d, 0x33, 0xaf, 0x46, 0x8f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x1e, - 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, - 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, - 0xfd, 0x06, 0xc7, 0x7c, 0x56, 0x72, 0xd7, 0x3b, 0x9c, 0x85, 0x96, 0x90, 0x27, 0x77, 0x0c, 0xd2, 0x34, 0x96, 0x46, - 0xc0, 0x89, 0x48, 0xb6, 0xb1, 0x14, 0x8e, 0x00, 0x02, 0x02, 0xdd, 0x94, 0x19, 0xc6, 0x74, 0x30, 0xf2, 0x3c, 0xea, - 0x19, 0xef, 0x55, 0x78, 0x0a, 0x69, 0xb2, 0x7d, 0x3d, 0x7f, 0x6f, 0x04, 0x59, 0xb9, 0xe5, 0x1c, 0x0f, 0x8b, 0x6f, - 0x9c, 0x7d, 0x95, 0x93, 0xa7, 0x98, 0x65, 0xa4, 0x77, 0x8a, 0x79, 0x01, 0x7f, 0x2a, 0x4b, 0x7d, 0x8e, 0xd2, 0x5b, - 0xe6, 0x93, 0x55, 0x24, 0x5d, 0x78, 0x9b, 0x7e, 0x3f, 0x1e, 0xa9, 0x43, 0xcd, 0xdf, 0xc7, 0x23, 0x79, 0x86, 0x6d, - 0x58, 0xc2, 0x42, 0xab, 0x60, 0x0c, 0x20, 0x89, 0x8d, 0x88, 0x06, 0xa3, 0xbd, 0x39, 0x1c, 0xce, 0x37, 0xe6, 0x2c, - 0xd9, 0x83, 0xeb, 0x2b, 0x4f, 0xcc, 0x3b, 0xf0, 0x65, 0x1e, 0x13, 0x44, 0x6c, 0xe6, 0x6d, 0x58, 0x0d, 0x1e, 0xec, - 0xe0, 0xfa, 0x88, 0x2d, 0x8a, 0xb5, 0x8e, 0xa5, 0xb2, 0x0e, 0x4e, 0xeb, 0xd8, 0x34, 0x23, 0xa5, 0xc8, 0x3e, 0xc7, - 0xfe, 0xde, 0x0d, 0xae, 0xae, 0x8d, 0x41, 0xad, 0x71, 0x87, 0xb9, 0x73, 0x2a, 0xa0, 0x1e, 0xd3, 0x15, 0x54, 0xcf, - 0x2a, 0xf2, 0xe5, 0xb7, 0x76, 0x0e, 0x08, 0x1a, 0x81, 0xc0, 0x45, 0x03, 0x25, 0xd3, 0xa5, 0x9c, 0x77, 0x01, 0x21, - 0xbe, 0x4b, 0x41, 0x9f, 0xce, 0x60, 0x13, 0x9b, 0x4f, 0x20, 0x16, 0x4d, 0xf7, 0xb9, 0xd6, 0xcc, 0x17, 0x23, 0xda, - 0x99, 0x75, 0xb7, 0xc8, 0xad, 0x16, 0x22, 0x19, 0x3d, 0xdb, 0x4c, 0xb8, 0xeb, 0x50, 0xce, 0x48, 0xc0, 0x04, 0xad, - 0xad, 0x94, 0x7c, 0xae, 0x7b, 0x9d, 0xa0, 0x3d, 0x90, 0xb4, 0xee, 0xdf, 0x2c, 0x3a, 0xa3, 0xe4, 0xe4, 0x7a, 0x93, - 0x33, 0x48, 0xc1, 0x82, 0xed, 0x65, 0x4e, 0xb8, 0x01, 0x3e, 0xb2, 0x59, 0x72, 0x9a, 0x06, 0x79, 0x2c, 0x0c, 0xd2, - 0x47, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, - 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, - 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, 0x98, 0x07, 0xb6, 0xb6, 0x71, 0x4d, 0x60, 0xa0, 0x53, 0xfb, 0x5a, 0x94, 0x73, - 0xac, 0x22, 0x7a, 0x9f, 0x7f, 0xa8, 0xec, 0xe9, 0x83, 0x08, 0x1b, 0x15, 0x68, 0x2c, 0x25, 0xc6, 0x46, 0x8e, 0x7f, - 0x4b, 0x94, 0x0d, 0x19, 0x02, 0x42, 0x48, 0x1b, 0x39, 0xfd, 0xb0, 0xbe, 0x7c, 0x97, 0x69, 0xff, 0x4f, 0x12, 0xbf, - 0x0d, 0xf6, 0x72, 0xea, 0x4f, 0x3d, 0xe2, 0xf1, 0x5a, 0xa3, 0xc7, 0x94, 0x74, 0x1b, 0xe4, 0xa9, 0xf2, 0x14, 0x24, - 0x13, 0xc6, 0x02, 0x82, 0x45, 0xb9, 0xe0, 0x39, 0xaf, 0xb8, 0x84, 0xfb, 0xa8, 0x65, 0x45, 0x84, 0xaa, 0x44, 0x4e, - 0x9f, 0xaf, 0x80, 0x67, 0x02, 0x02, 0x1d, 0x63, 0xa4, 0x51, 0x05, 0x5f, 0x02, 0x63, 0x1d, 0x28, 0x3b, 0xcd, 0x48, - 0x70, 0xd9, 0xfd, 0x84, 0x44, 0xa9, 0x2f, 0x49, 0x49, 0xfa, 0x56, 0xd4, 0x78, 0x25, 0x56, 0x11, 0x09, 0x64, 0xa8, - 0x21, 0x62, 0x55, 0x3d, 0x75, 0xaf, 0x8a, 0xc9, 0x60, 0x50, 0xf9, 0x72, 0x7a, 0xe2, 0x0d, 0x0d, 0x95, 0x77, 0x5d, - 0xd1, 0x4e, 0xcf, 0xb5, 0x52, 0xde, 0x42, 0x5a, 0x82, 0xa6, 0x61, 0xa4, 0x39, 0x94, 0xba, 0x92, 0xee, 0xc6, 0x20, - 0xbe, 0x64, 0xa2, 0x67, 0x3b, 0xb5, 0xa3, 0xb4, 0x25, 0xed, 0x21, 0xa4, 0xe7, 0x2e, 0xf9, 0x98, 0x85, 0x5c, 0xdd, - 0x29, 0x27, 0xe5, 0x55, 0x88, 0x4e, 0xee, 0x7b, 0x0c, 0x89, 0x40, 0x9f, 0x73, 0x0c, 0xeb, 0xa2, 0xa1, 0xce, 0x61, - 0x85, 0x98, 0x2d, 0x94, 0x30, 0x5f, 0x32, 0x9e, 0x4a, 0x06, 0x0d, 0x80, 0x0c, 0xf8, 0xe2, 0x65, 0x60, 0xf9, 0x2b, - 0x88, 0x1f, 0x6d, 0x7c, 0x38, 0xfc, 0x55, 0x53, 0x88, 0xed, 0x5f, 0xb0, 0x19, 0xc2, 0xa3, 0x7a, 0xc0, 0x33, 0xdf, - 0xc4, 0x09, 0x5a, 0x01, 0x49, 0x99, 0x1d, 0x4d, 0x64, 0xaf, 0x7a, 0x08, 0xa7, 0xb2, 0x02, 0x75, 0x94, 0x75, 0x56, - 0xc2, 0x8f, 0x30, 0xd5, 0xad, 0xc4, 0x5a, 0xa0, 0xcd, 0xd5, 0x8a, 0xb5, 0x00, 0x0e, 0xfc, 0x1c, 0x82, 0x27, 0xf2, - 0x39, 0xb8, 0x18, 0x14, 0xe0, 0x73, 0x00, 0xbc, 0xc8, 0x5d, 0x78, 0x30, 0x0f, 0x2c, 0xab, 0x11, 0x86, 0xa3, 0x8a, - 0x58, 0xbf, 0x66, 0x3b, 0xf2, 0x81, 0xdb, 0x31, 0x3e, 0xd7, 0x1e, 0x4b, 0x96, 0x83, 0x51, 0xe6, 0x5e, 0x2d, 0xd1, - 0xf3, 0x26, 0x8d, 0x9b, 0xd1, 0xa3, 0x7d, 0x2d, 0xff, 0x17, 0xf4, 0x32, 0xe8, 0x6f, 0xe1, 0x96, 0xd7, 0xfc, 0x61, - 0xb9, 0x70, 0x9a, 0x5e, 0x41, 0xa4, 0x8c, 0x1a, 0x91, 0x31, 0x84, 0x4d, 0xaa, 0x9b, 0xdb, 0xa4, 0xba, 0x10, 0xf0, - 0x74, 0x44, 0xaa, 0x6b, 0x21, 0x6d, 0xe4, 0xd3, 0x3a, 0x90, 0xb1, 0x48, 0xef, 0x7e, 0xfc, 0xdb, 0xf3, 0xcf, 0xaf, - 0x7f, 0xfd, 0xf1, 0xe6, 0xf5, 0xbb, 0x57, 0xaf, 0xdf, 0xbd, 0xfe, 0xfc, 0x3b, 0x41, 0x78, 0x4c, 0x85, 0xca, 0xf0, - 0xe1, 0xfd, 0xa7, 0xd7, 0x4e, 0x06, 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, - 0x4e, 0xc9, 0x1c, 0x33, 0x31, 0xc7, 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x85, - 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, 0x91, 0x49, 0xf3, 0xe5, 0xaf, 0x04, 0xb1, 0x4f, 0x2b, 0x29, 0xf7, 0xd5, 0xb6, - 0xe6, 0xf9, 0xf6, 0x7e, 0x2f, 0xe1, 0xfc, 0xe7, 0xd2, 0x88, 0x5a, 0x80, 0x03, 0xf0, 0x39, 0xfc, 0x71, 0xa5, 0x2d, - 0x69, 0x32, 0x8b, 0xf6, 0x33, 0x86, 0xa0, 0x4b, 0x03, 0x69, 0x62, 0x8f, 0xbc, 0xd4, 0x27, 0x0b, 0x09, 0xdc, 0x11, - 0xc3, 0xa7, 0x15, 0x41, 0xaf, 0x18, 0x51, 0x5c, 0x72, 0x85, 0x4a, 0x29, 0xf9, 0x37, 0xca, 0x2e, 0x2a, 0xe4, 0xac, - 0x60, 0x77, 0x8a, 0x1c, 0x19, 0x3f, 0x08, 0x26, 0xbe, 0x1c, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, - 0xff, 0x33, 0xc3, 0xc0, 0xfe, 0x1c, 0x7c, 0x5e, 0x1d, 0xe6, 0xe5, 0x8d, 0x3e, 0xe5, 0x16, 0x7c, 0x3c, 0x59, 0x5c, - 0x81, 0xc1, 0x7e, 0xa1, 0x9a, 0xbb, 0xe6, 0xf5, 0x6c, 0x31, 0x67, 0xfb, 0x59, 0x34, 0x0f, 0x96, 0x6c, 0x96, 0xcd, - 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0xb7, - 0x99, 0x07, 0xbc, 0xc7, 0x4b, 0x9f, 0x6d, 0x40, 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x75, 0xe5, 0x6d, - 0x58, 0xc9, 0xce, 0xc7, 0x2c, 0xc7, 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x4b, 0xf5, 0x6c, 0xa2, 0xec, - 0x66, 0x9b, 0xd1, 0xcd, 0x5d, 0x5a, 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x0d, 0x7e, - 0xc9, 0x9a, 0x38, 0xff, 0x4c, 0xdb, 0x76, 0x55, 0x62, 0x2b, 0x68, 0x51, 0x64, 0xb5, 0xc2, 0x03, 0x73, 0xfe, 0x0c, - 0x16, 0x30, 0xf6, 0x1c, 0xe7, 0xbc, 0xf6, 0x47, 0xc8, 0x78, 0xef, 0x00, 0xa0, 0x65, 0x8e, 0x03, 0x3c, 0x62, 0xc5, - 0x28, 0x1a, 0xbc, 0xf3, 0x4b, 0x65, 0xb5, 0xd2, 0x9c, 0x84, 0xb6, 0x11, 0xab, 0x96, 0x23, 0x55, 0x33, 0x22, 0x7d, - 0x90, 0x9e, 0xf7, 0x3d, 0xa2, 0x1a, 0xec, 0xc9, 0xbc, 0x0e, 0xec, 0xd3, 0xfb, 0xd6, 0xaa, 0xee, 0xfc, 0x9e, 0x2a, - 0x5d, 0x72, 0x64, 0xcb, 0x4f, 0x97, 0xe1, 0xbd, 0xfa, 0x53, 0x72, 0x7d, 0x28, 0x70, 0x84, 0x87, 0x2a, 0xe0, 0x7c, - 0xbd, 0x12, 0xed, 0x4e, 0x84, 0x5d, 0xb9, 0x04, 0x84, 0xf8, 0x92, 0xa6, 0x39, 0x1e, 0x47, 0x34, 0x11, 0x61, 0x13, - 0xa3, 0xbf, 0xb0, 0xfb, 0x50, 0x62, 0x39, 0xcf, 0x35, 0x28, 0xb9, 0x64, 0xf0, 0x9e, 0xb4, 0xd7, 0xa0, 0x59, 0x5e, - 0x95, 0x9a, 0x4c, 0xe4, 0xa0, 0x7c, 0x38, 0x14, 0xb0, 0x97, 0x1a, 0x3f, 0x4d, 0xf8, 0x09, 0xcb, 0x5b, 0x7b, 0x6b, - 0x4a, 0x51, 0x49, 0x03, 0x54, 0xe0, 0x63, 0x06, 0xff, 0xbb, 0x33, 0xc4, 0x82, 0x29, 0x3a, 0x7e, 0x38, 0x13, 0x73, - 0xeb, 0xb9, 0x55, 0xd6, 0x51, 0xb6, 0x46, 0x39, 0x01, 0xff, 0x9e, 0xea, 0x38, 0x49, 0x84, 0x53, 0xef, 0x11, 0x17, - 0x75, 0x2f, 0x87, 0xa8, 0x1b, 0xf6, 0xb9, 0xd2, 0xc1, 0x96, 0xd3, 0x34, 0x38, 0x12, 0xbf, 0x52, 0x9f, 0x3d, 0xca, - 0x2c, 0x1e, 0x75, 0x64, 0x23, 0x4a, 0xd2, 0x38, 0x16, 0x39, 0x6c, 0xef, 0x37, 0x72, 0xff, 0xef, 0xf7, 0x21, 0x9c, - 0xb4, 0x0a, 0xe2, 0xd2, 0x13, 0x88, 0x08, 0x47, 0x87, 0x1f, 0x11, 0x9e, 0x48, 0x55, 0xe1, 0x87, 0xfa, 0xc4, 0x8d, - 0xd9, 0xbd, 0x30, 0x47, 0xf5, 0x16, 0x60, 0x18, 0xeb, 0xad, 0x45, 0x48, 0xa2, 0x95, 0x66, 0xb4, 0xf5, 0x80, 0x18, - 0xf1, 0x7e, 0x6d, 0x91, 0xc1, 0x58, 0x5b, 0x12, 0x09, 0xe0, 0x4b, 0x12, 0x32, 0xb4, 0x6d, 0x04, 0x66, 0x0c, 0x6f, - 0x67, 0xc5, 0xa5, 0xeb, 0xb0, 0xcd, 0x39, 0x7c, 0x21, 0x37, 0x9a, 0x75, 0x44, 0x69, 0x82, 0x90, 0x7f, 0xc0, 0xc9, - 0x42, 0x61, 0x34, 0x2f, 0x8f, 0xd2, 0x49, 0x62, 0x7d, 0xdf, 0x55, 0x2a, 0xd8, 0x6c, 0x3e, 0xa1, 0xbe, 0xec, 0x28, - 0xf9, 0x1a, 0x9c, 0x74, 0x9c, 0x64, 0x91, 0x83, 0xa8, 0x45, 0xe5, 0x7c, 0x4a, 0xc2, 0xd2, 0xae, 0x4e, 0xb5, 0x59, - 0xaf, 0x8b, 0xb2, 0xae, 0x5e, 0x8a, 0x48, 0xd1, 0xfb, 0xa8, 0x47, 0x8f, 0x24, 0xa4, 0x42, 0xab, 0x52, 0xbb, 0x3c, - 0x02, 0xb7, 0x4d, 0xad, 0xd8, 0x96, 0x4b, 0x58, 0xa2, 0xc6, 0x7f, 0x86, 0x3e, 0xca, 0xc5, 0xbd, 0x0c, 0xd0, 0xe8, - 0x78, 0x6a, 0xde, 0x7a, 0xe0, 0x95, 0xa3, 0xfc, 0xd2, 0x6a, 0x93, 0x7e, 0x05, 0x64, 0x46, 0xfb, 0x47, 0x4b, 0x09, - 0x64, 0x06, 0x66, 0xd2, 0xd2, 0x90, 0xc8, 0x51, 0xcc, 0xd2, 0xfc, 0x4f, 0x5c, 0xb1, 0x15, 0x22, 0x0d, 0xab, 0xb9, - 0xc7, 0x7f, 0xac, 0xbc, 0x5a, 0xae, 0x65, 0xa6, 0xb9, 0x59, 0xe2, 0x58, 0xb1, 0xb8, 0xa8, 0xd7, 0x95, 0xc8, 0x02, - 0x21, 0x8e, 0x30, 0x8d, 0xf5, 0xd4, 0x1b, 0xa5, 0xd5, 0x07, 0x24, 0x94, 0xf9, 0x11, 0x7b, 0x3b, 0xf6, 0x7a, 0x90, - 0x85, 0x38, 0xb6, 0x1c, 0x6c, 0xb6, 0xde, 0xe7, 0x32, 0x15, 0xf1, 0x59, 0x5d, 0x9c, 0x6d, 0x2a, 0x71, 0x56, 0x27, - 0xe2, 0xec, 0x07, 0xc8, 0xf9, 0xc3, 0x19, 0x15, 0x7d, 0x76, 0x9f, 0xd6, 0x49, 0xb1, 0xa9, 0xe9, 0xc9, 0x2b, 0x2c, - 0xe3, 0x87, 0x33, 0xe2, 0xaa, 0x39, 0xa3, 0x91, 0x8c, 0x47, 0x67, 0x1f, 0x32, 0x20, 0x79, 0x3d, 0x4b, 0x57, 0x30, - 0x78, 0x67, 0x61, 0x1e, 0x9f, 0x95, 0x62, 0x09, 0x16, 0xa7, 0xb2, 0xf3, 0x3d, 0xc8, 0xb0, 0x0a, 0xff, 0x14, 0x67, - 0x00, 0xed, 0x7a, 0x96, 0xd6, 0x67, 0x69, 0x75, 0x96, 0x17, 0xf5, 0x99, 0x92, 0xc2, 0x21, 0x8c, 0x1f, 0xde, 0xd3, - 0x57, 0x76, 0x79, 0x9b, 0xc5, 0x5d, 0x16, 0xf9, 0x53, 0xf4, 0x2a, 0x22, 0x26, 0x8d, 0x4a, 0x78, 0xed, 0xfe, 0xb6, - 0xb9, 0x7f, 0x78, 0xdd, 0xd8, 0xfd, 0xec, 0x8e, 0x11, 0x5d, 0x50, 0x8f, 0x57, 0x92, 0x52, 0x41, 0x01, 0x81, 0x13, - 0xcd, 0x1a, 0x0f, 0xee, 0x38, 0xe0, 0xd5, 0xc0, 0x16, 0x6c, 0xed, 0xf3, 0x67, 0xb1, 0x0c, 0xd3, 0xde, 0x04, 0xf8, - 0x57, 0xd9, 0x9b, 0xae, 0x83, 0x05, 0xde, 0xb7, 0x90, 0x6d, 0xe8, 0xf5, 0x4b, 0xfe, 0xdc, 0xcb, 0xd5, 0xdf, 0xec, - 0x9f, 0x00, 0x84, 0x01, 0x31, 0xab, 0x3e, 0x9a, 0xb8, 0x77, 0x56, 0x96, 0x9d, 0x93, 0x65, 0xd7, 0x43, 0xbf, 0x26, - 0x31, 0x2a, 0xad, 0x2c, 0xa5, 0x93, 0xa5, 0x84, 0x2c, 0xe0, 0x13, 0xa3, 0xa9, 0x8d, 0x00, 0xc2, 0x76, 0x94, 0xca, - 0x17, 0x2a, 0x2f, 0xa2, 0x70, 0x4e, 0xf0, 0x3c, 0x11, 0xa3, 0x3b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0x6d, - 0xb1, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xab, 0xa2, 0x7c, 0x1d, 0x93, 0x4f, 0xc1, 0xee, 0xe4, 0xe3, 0x12, 0x1e, 0x97, - 0x27, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf2, 0x31, 0xf8, 0x1e, 0xc9, 0x79, 0xdd, 0xf5, 0x38, 0x41, 0x6e, 0x21, 0xdd, - 0xdf, 0x8e, 0x49, 0x80, 0xe6, 0x35, 0x2c, 0x47, 0x4d, 0xc5, 0x35, 0x33, 0x63, 0x3c, 0x6f, 0xf4, 0xfe, 0xd8, 0xf1, - 0x96, 0x29, 0x14, 0xb3, 0x98, 0xd7, 0xf0, 0x7b, 0x56, 0x05, 0xea, 0xae, 0xb7, 0x49, 0x6e, 0x99, 0xd5, 0x73, 0xb4, - 0xfb, 0xbe, 0xaf, 0x13, 0x41, 0xed, 0xef, 0xb0, 0xe7, 0x99, 0xf5, 0xae, 0x8a, 0x81, 0x4b, 0x95, 0xec, 0x90, 0xa9, - 0x6a, 0x7a, 0xa0, 0x52, 0x1a, 0x3c, 0xbd, 0xb4, 0x2e, 0x5f, 0x2a, 0x6d, 0xe4, 0x99, 0xe6, 0x37, 0x80, 0x17, 0x53, - 0x97, 0xc5, 0xee, 0x9b, 0xfb, 0x0a, 0x6e, 0xe3, 0xfd, 0xfe, 0xba, 0xf2, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, - 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x3a, 0x11, 0xd1, 0x9f, 0xed, 0x72, 0x9d, 0xb9, 0x0e, 0x18, 0x51, 0xc4, 0x6f, - 0xe3, 0xd1, 0x1f, 0xa0, 0xb8, 0x36, 0xf6, 0x80, 0xb0, 0x0e, 0x09, 0x7d, 0x46, 0x00, 0x52, 0x8f, 0x3e, 0x4a, 0xee, - 0x41, 0xb3, 0xa2, 0xb9, 0x63, 0xf2, 0x73, 0x7d, 0xa5, 0xf4, 0xf7, 0xeb, 0xca, 0x23, 0x73, 0x4a, 0xdb, 0x4c, 0x63, - 0xb5, 0xa6, 0x12, 0x08, 0xaf, 0xa8, 0x64, 0x15, 0x3e, 0x9b, 0x37, 0xa2, 0xdf, 0x97, 0x47, 0x78, 0x5a, 0xfd, 0xb8, - 0xc5, 0xf8, 0x56, 0x40, 0x34, 0x12, 0xa0, 0x60, 0x05, 0x98, 0x17, 0xd9, 0xcc, 0xee, 0xe3, 0x80, 0x2a, 0x25, 0x9a, - 0xc6, 0xd9, 0x3c, 0xbf, 0xa7, 0x37, 0x65, 0x07, 0x9d, 0x3a, 0x55, 0xe0, 0x82, 0xab, 0x92, 0xf1, 0xca, 0x7a, 0x22, - 0x9f, 0xdf, 0xdc, 0x6e, 0xd2, 0x2c, 0x7e, 0x5f, 0xfe, 0x82, 0x63, 0xab, 0xeb, 0xf0, 0xc0, 0xd4, 0xe9, 0xda, 0x79, - 0xa4, 0xb5, 0x17, 0x02, 0x22, 0xda, 0x35, 0xd4, 0x7a, 0x61, 0xa1, 0x47, 0x7a, 0x22, 0x9c, 0x93, 0x44, 0x4d, 0x3b, - 0xd0, 0xd2, 0x08, 0x7d, 0x7d, 0xcd, 0xe9, 0x2f, 0x0c, 0xd6, 0x3e, 0x1f, 0x33, 0x20, 0x2b, 0xd1, 0x8f, 0xd5, 0x43, - 0x63, 0x33, 0x87, 0x9e, 0xb5, 0x2a, 0xcf, 0xbc, 0xea, 0x70, 0x40, 0x7c, 0x18, 0xfd, 0x25, 0xbf, 0xdf, 0x7f, 0x49, - 0xf3, 0x8f, 0x09, 0x35, 0x7e, 0xb6, 0x19, 0xa0, 0x6b, 0xdf, 0x95, 0x07, 0xa2, 0x9e, 0x6b, 0x95, 0x20, 0xc4, 0x1b, - 0xc4, 0x44, 0x33, 0x62, 0x0e, 0x4e, 0x3b, 0xd4, 0xfc, 0x93, 0xd4, 0x80, 0x10, 0x25, 0x5e, 0xc7, 0x94, 0x05, 0x39, - 0x6d, 0xe2, 0x48, 0x3f, 0x0a, 0x27, 0xf2, 0xa3, 0xa8, 0x8a, 0xec, 0x0e, 0x2e, 0x18, 0x4c, 0xbd, 0xa7, 0xfd, 0x12, - 0xfd, 0x96, 0x70, 0xe4, 0x1c, 0xad, 0x0a, 0x41, 0xe4, 0x84, 0xb0, 0xd6, 0x10, 0x26, 0x88, 0x0d, 0xe2, 0x65, 0xdf, - 0x25, 0x19, 0x8e, 0x14, 0x5c, 0xd6, 0xb1, 0x63, 0xcc, 0xd5, 0x51, 0xf5, 0x1a, 0xc0, 0x78, 0xe5, 0x08, 0x9a, 0x8d, - 0x22, 0xbb, 0x84, 0xa8, 0x22, 0xc7, 0x13, 0x50, 0x3b, 0x28, 0x8d, 0xcd, 0xf4, 0x7c, 0x1c, 0xe4, 0xa3, 0x9b, 0x0a, - 0x75, 0x4e, 0x2c, 0xe3, 0x35, 0x00, 0x6b, 0xe7, 0xaa, 0x9f, 0x67, 0x35, 0x78, 0xd2, 0x10, 0x9f, 0x8f, 0xd1, 0xf6, - 0xca, 0xe6, 0xa0, 0xda, 0x4e, 0x67, 0xe5, 0x15, 0xd3, 0xe5, 0xc0, 0xb8, 0x6f, 0x78, 0x45, 0x71, 0x86, 0x1f, 0x3d, - 0xd8, 0xe2, 0xfc, 0xe9, 0x86, 0xda, 0x8f, 0xb9, 0x51, 0x0f, 0x03, 0xad, 0x05, 0x6f, 0x0a, 0x62, 0xfd, 0x7d, 0xd4, - 0x91, 0xed, 0xbd, 0x16, 0x19, 0x4d, 0x3e, 0xfb, 0xf9, 0x87, 0x32, 0x5d, 0xa5, 0x70, 0x5f, 0x72, 0xb2, 0x68, 0xe6, - 0x21, 0xb0, 0x37, 0xc4, 0x70, 0x7d, 0x54, 0x78, 0x44, 0x59, 0xbf, 0x0f, 0xbf, 0xaf, 0x32, 0x30, 0xc5, 0xc0, 0x75, - 0x85, 0x60, 0x3c, 0x04, 0x82, 0x78, 0x98, 0x46, 0x27, 0x83, 0x1a, 0xb4, 0xe1, 0x1b, 0x80, 0xcc, 0x00, 0x8f, 0xcc, - 0x85, 0x47, 0xc0, 0x5d, 0xe0, 0xda, 0x93, 0xf1, 0xd8, 0x9f, 0x98, 0x86, 0x46, 0x4d, 0x69, 0xa6, 0xe7, 0xc6, 0x6f, - 0x3a, 0xaa, 0xe5, 0xda, 0xf9, 0x8f, 0x2f, 0xf9, 0x0d, 0x7a, 0x41, 0xcb, 0xcb, 0x7d, 0xa4, 0x2e, 0xf7, 0x19, 0xc5, - 0x65, 0x22, 0x39, 0x2c, 0x88, 0x65, 0x09, 0x07, 0x1e, 0xa3, 0x92, 0xc5, 0x96, 0x1e, 0xab, 0xa2, 0xe5, 0x8b, 0x72, - 0x83, 0x74, 0xe8, 0x84, 0x60, 0x89, 0x0a, 0x82, 0x25, 0x30, 0x2e, 0x62, 0xcd, 0x37, 0x83, 0x9c, 0xc5, 0xb3, 0xcd, - 0x9c, 0x23, 0x61, 0x5d, 0x72, 0x38, 0x14, 0x12, 0x6c, 0x26, 0x9b, 0xad, 0xe7, 0x6c, 0xed, 0x33, 0x50, 0x02, 0x94, - 0x32, 0x4d, 0x50, 0x9a, 0x56, 0x6c, 0xc5, 0x4d, 0x6b, 0xb0, 0x5a, 0x4d, 0xd9, 0xaa, 0xa6, 0xec, 0x9c, 0xa6, 0x1c, - 0x55, 0x50, 0x72, 0x42, 0x29, 0xca, 0x30, 0x80, 0x11, 0x9b, 0x44, 0x57, 0x19, 0xfa, 0x78, 0x27, 0x3c, 0x82, 0x2a, - 0x22, 0xf2, 0x09, 0x43, 0x08, 0x4c, 0x44, 0x71, 0xa1, 0x0a, 0xc5, 0x00, 0x19, 0x91, 0x40, 0x30, 0x51, 0xa9, 0x53, - 0x60, 0x3e, 0x9a, 0x2a, 0x86, 0x4d, 0x7b, 0xa2, 0x7c, 0x4f, 0x1d, 0xf7, 0x28, 0xdb, 0xfc, 0x2c, 0x76, 0x41, 0x88, - 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa1, 0xe6, - 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, 0x9e, 0x0c, 0x72, 0xb6, 0x00, 0x0f, 0xda, 0x39, 0xcb, - 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0xef, 0xb5, 0xb7, 0x00, 0xf9, 0x69, 0x63, 0x37, 0x0a, 0x13, 0x23, 0x48, 0xd4, 0xed, - 0xca, 0x40, 0x7e, 0xf8, 0x80, 0xd3, 0xf1, 0xd8, 0x53, 0xc6, 0xdc, 0xca, 0xf4, 0x32, 0x9d, 0x2b, 0xf9, 0x46, 0xee, - 0xa5, 0x0f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, 0x9f, 0x60, 0xbb, 0xf0, 0xda, 0x20, 0x61, 0x46, 0x80, - 0x2d, 0x8e, 0x8f, 0x91, 0x12, 0x18, 0xc2, 0x71, 0x96, 0x02, 0x30, 0x8d, 0xbe, 0xcc, 0x56, 0xf6, 0x65, 0x56, 0x6b, - 0xb6, 0x54, 0x4e, 0xf7, 0xce, 0xad, 0xdb, 0xf9, 0x5c, 0x02, 0x80, 0x49, 0x9d, 0x03, 0x71, 0x66, 0x82, 0x5d, 0x9a, - 0x44, 0x96, 0x8f, 0x61, 0xbe, 0x14, 0xaf, 0xca, 0x62, 0xa5, 0xba, 0xa2, 0xed, 0x33, 0x93, 0xcf, 0x48, 0x27, 0xa1, - 0x02, 0x0a, 0x0a, 0xb9, 0xd6, 0xa7, 0xef, 0xc2, 0x77, 0x41, 0xa1, 0x81, 0xd9, 0x2a, 0xdc, 0xd3, 0x64, 0x8d, 0xd4, - 0x1b, 0x55, 0xbf, 0x4f, 0xae, 0x81, 0x54, 0x67, 0x0e, 0x2d, 0x7b, 0x5e, 0x61, 0x80, 0xd8, 0x51, 0x9f, 0x91, 0x50, - 0x07, 0x52, 0x0f, 0x18, 0x42, 0xb4, 0x4d, 0x1f, 0x7f, 0x32, 0x24, 0xba, 0x00, 0x5b, 0x88, 0x36, 0xf0, 0xe3, 0x4f, - 0xb0, 0xcf, 0x82, 0xf0, 0x98, 0xe6, 0x6f, 0x21, 0xe9, 0xd8, 0xc0, 0x69, 0xf5, 0x29, 0xf8, 0x20, 0xc9, 0xc1, 0x44, - 0x1d, 0xbc, 0xdc, 0x5f, 0xfa, 0x7d, 0xd8, 0xb2, 0x73, 0x29, 0xd5, 0xb1, 0x52, 0x6f, 0xdb, 0xda, 0x0f, 0xa2, 0x2d, - 0x38, 0x42, 0xb0, 0x76, 0x86, 0x88, 0x60, 0x66, 0x10, 0x61, 0xd7, 0x42, 0xdd, 0xed, 0x29, 0xb5, 0x2c, 0xea, 0x6d, - 0x4f, 0x29, 0x75, 0x1b, 0x86, 0xef, 0x26, 0x98, 0x29, 0x6e, 0xf8, 0xa7, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0xf1, 0xb4, - 0x7b, 0xfe, 0x7e, 0xc1, 0xab, 0xd9, 0x46, 0x99, 0x30, 0x97, 0x7c, 0x31, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x17, - 0x6f, 0xa1, 0xe6, 0x83, 0x7f, 0x38, 0x24, 0x10, 0x6f, 0x14, 0x5f, 0x2d, 0x1b, 0xb9, 0x75, 0x4d, 0x36, 0x57, 0x25, - 0xa0, 0x7e, 0x9f, 0xaf, 0x71, 0xbf, 0xc5, 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, - 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0x37, 0xbc, 0x1c, 0x5e, 0x4e, 0x36, 0x64, 0xd2, 0xdd, 0xf8, 0xc8, 0x9d, 0x05, - 0xaa, 0xde, 0xef, 0x28, 0x4e, 0x1a, 0x24, 0x1a, 0x7b, 0x0d, 0x3e, 0xcf, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x21, 0xf9, - 0x4a, 0x0f, 0x60, 0xae, 0x42, 0x09, 0x10, 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x35, 0xd7, - 0xab, 0xe9, 0x8b, 0x57, 0xa2, 0x79, 0x1f, 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0xb7, 0xef, 0xef, 0x44, - 0xb9, 0xc8, 0xc0, 0x92, 0xad, 0xc2, 0x29, 0x2e, 0x1b, 0x75, 0x46, 0x3c, 0xcf, 0x63, 0x05, 0xd0, 0xf1, 0x90, 0x00, - 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, - 0xf9, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, 0xaa, 0x28, 0xe9, 0x53, 0xc5, 0x2c, 0x97, 0x83, 0x09, 0xec, 0xea, 0x44, - 0x86, 0x5a, 0x41, 0xde, 0xaa, 0x2b, 0x6f, 0x65, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x81, 0x9b, 0x8e, 0x35, 0x62, 0xe0, - 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0xde, 0x00, 0xc3, 0x10, 0xbf, 0xcb, 0xbc, 0xe7, 0x9e, 0x23, 0x55, 0x41, 0x32, - 0xdb, 0x66, 0x9e, 0xba, 0x88, 0xea, 0x2b, 0xa7, 0x96, 0xce, 0x9c, 0x7e, 0x04, 0xf0, 0x1e, 0x53, 0x93, 0x86, 0x7c, - 0x84, 0xdb, 0x52, 0x7c, 0xbd, 0x55, 0xd7, 0x78, 0x69, 0x74, 0xee, 0x5e, 0xbe, 0x74, 0xa7, 0x41, 0x3f, 0x05, 0x41, - 0x39, 0x9f, 0x97, 0x02, 0xf6, 0x94, 0xd9, 0x5c, 0xaf, 0x56, 0xad, 0xd0, 0x3a, 0x1c, 0xc6, 0xda, 0x51, 0x48, 0xab, - 0xb3, 0x80, 0xad, 0x46, 0x3a, 0x25, 0x40, 0x08, 0x8e, 0xd3, 0xb0, 0x13, 0x8c, 0xbb, 0x74, 0x1a, 0x91, 0xf5, 0x4a, - 0x49, 0xba, 0x30, 0x83, 0xe4, 0x9f, 0xe4, 0xf5, 0x0c, 0x68, 0x09, 0xe0, 0x50, 0xc4, 0x12, 0x1e, 0x4e, 0x92, 0x2b, - 0x80, 0x4e, 0x87, 0x83, 0x4a, 0x43, 0x73, 0x56, 0xb3, 0x64, 0x3e, 0x89, 0xa5, 0xaa, 0xf2, 0x70, 0xf0, 0x94, 0x9b, - 0x41, 0xbf, 0x9f, 0x4d, 0x4b, 0xe5, 0x02, 0x10, 0xc4, 0xba, 0x30, 0x40, 0x3c, 0xd2, 0xc2, 0x93, 0x45, 0x9f, 0x92, - 0xf8, 0xe5, 0x2c, 0x99, 0x9b, 0x6c, 0x78, 0x07, 0x46, 0xb0, 0x19, 0xd7, 0x25, 0x65, 0xda, 0xa3, 0xf2, 0x7b, 0x46, - 0x4f, 0x6d, 0x5f, 0x6b, 0xb5, 0x45, 0xac, 0xeb, 0xe0, 0xaa, 0x44, 0x3d, 0xc5, 0x07, 0x25, 0x09, 0xde, 0x2f, 0x9d, - 0x9b, 0x91, 0xf2, 0xb5, 0xc8, 0xfd, 0xa0, 0x9d, 0xa9, 0x95, 0x03, 0x47, 0x20, 0xc7, 0x2a, 0x2a, 0x79, 0xbd, 0xeb, - 0x10, 0x3c, 0xba, 0x2b, 0x15, 0x28, 0x07, 0x3f, 0x03, 0x31, 0xba, 0xbe, 0xea, 0xac, 0xa1, 0x66, 0x1a, 0x55, 0x1e, - 0x41, 0xa7, 0x0e, 0xe0, 0x49, 0xc1, 0x4b, 0xad, 0x7e, 0x3c, 0x1c, 0x3c, 0xf3, 0x83, 0xbf, 0xcf, 0xf4, 0x2d, 0xc4, - 0x44, 0x39, 0xd5, 0x08, 0x89, 0x2b, 0x25, 0x89, 0xf8, 0x78, 0xd1, 0xb2, 0x62, 0x54, 0x86, 0xf7, 0xbc, 0x52, 0xe5, - 0xab, 0x53, 0x95, 0x17, 0x23, 0x6d, 0x4b, 0xe0, 0x35, 0xf9, 0x87, 0xc8, 0x35, 0x6f, 0x7d, 0xdd, 0x55, 0x86, 0x5e, - 0xcb, 0x0a, 0x74, 0x04, 0x5b, 0x59, 0x4a, 0x0e, 0xf8, 0xa4, 0xba, 0xab, 0x56, 0xad, 0xcf, 0x29, 0xdb, 0x08, 0x37, - 0xf9, 0x75, 0xec, 0xe0, 0x48, 0xf9, 0x0d, 0x9e, 0x0b, 0x60, 0xaf, 0x01, 0x7b, 0x73, 0xce, 0x8a, 0xe6, 0xc1, 0x21, - 0x6d, 0x0b, 0x34, 0x32, 0x73, 0x3b, 0x57, 0xf7, 0x6d, 0x79, 0x94, 0xc6, 0x10, 0x99, 0xf6, 0xc0, 0x74, 0xb0, 0x19, - 0xe5, 0xbf, 0xa7, 0xfc, 0x56, 0xe1, 0x18, 0xf8, 0x76, 0xea, 0x1d, 0x40, 0xd5, 0xd3, 0x06, 0x19, 0x6b, 0x86, 0xa1, - 0x95, 0x5d, 0x2e, 0x85, 0x96, 0xa0, 0xa5, 0x6e, 0x82, 0xe0, 0xfc, 0x88, 0x28, 0x47, 0x00, 0xba, 0x48, 0x01, 0x13, - 0xfc, 0x94, 0xb6, 0xbb, 0xdf, 0x5f, 0xa7, 0x1e, 0xb9, 0x77, 0x85, 0xca, 0x66, 0xf9, 0x99, 0x60, 0xec, 0x27, 0x1a, - 0x33, 0xe8, 0xe8, 0x8a, 0x9c, 0xf0, 0xac, 0xd5, 0x61, 0x5d, 0x37, 0x65, 0x50, 0x16, 0xc7, 0xbc, 0x9a, 0xce, 0xfe, - 0x78, 0xb4, 0xaf, 0x1b, 0x64, 0x21, 0xff, 0x83, 0xf5, 0x90, 0x0c, 0xba, 0x07, 0xa1, 0x10, 0xbd, 0x79, 0x30, 0xc3, - 0xff, 0xd8, 0x86, 0x67, 0xdf, 0x71, 0xa3, 0x4e, 0x00, 0x73, 0xc4, 0xf5, 0xd2, 0x53, 0xb4, 0xf5, 0x70, 0x0b, 0x64, - 0x6b, 0xbc, 0xbc, 0xb5, 0xd7, 0x40, 0x4e, 0x71, 0xfc, 0x4b, 0x9e, 0xa9, 0x95, 0x0d, 0x7e, 0x7a, 0xca, 0x76, 0xe0, - 0xe1, 0x45, 0x08, 0x28, 0x86, 0x65, 0xe3, 0x97, 0x96, 0xe3, 0x8c, 0xfe, 0x9b, 0x47, 0x0c, 0x83, 0x45, 0xe4, 0xc7, - 0x17, 0xa5, 0x10, 0x5f, 0x85, 0xf7, 0xb9, 0xf2, 0x96, 0xe4, 0x94, 0xb9, 0xd4, 0xc3, 0xe8, 0xba, 0x24, 0x7d, 0x97, - 0x7c, 0x6c, 0x0d, 0xdb, 0x1f, 0xda, 0xfd, 0x66, 0x88, 0x20, 0x84, 0x72, 0xfc, 0x9c, 0xd1, 0x09, 0x8d, 0x0f, 0xab, - 0xd9, 0xe9, 0xf5, 0x7b, 0xe7, 0x78, 0xc1, 0xd6, 0x68, 0x80, 0xc7, 0x43, 0x17, 0xf3, 0x44, 0x0d, 0x9d, 0xae, 0x6b, - 0xe7, 0xe0, 0x81, 0x41, 0x96, 0x27, 0xdf, 0x31, 0x2c, 0xb1, 0x3f, 0x89, 0x78, 0xd2, 0x56, 0x6d, 0x6c, 0x8e, 0x54, - 0x1b, 0x35, 0x03, 0x3f, 0x78, 0x05, 0x05, 0x46, 0x17, 0xa4, 0x5b, 0x30, 0x0e, 0x47, 0x00, 0xb2, 0x62, 0x1c, 0x8f, - 0x0c, 0x26, 0x30, 0xa4, 0x1b, 0x8a, 0x02, 0xf0, 0xf0, 0x38, 0x1e, 0x84, 0x0c, 0x20, 0x5d, 0xf0, 0xd0, 0xb0, 0x4d, - 0x42, 0xca, 0xcf, 0xf3, 0xbc, 0x56, 0x43, 0xe8, 0x3b, 0x0b, 0xd5, 0xb1, 0x1f, 0x69, 0xaf, 0x58, 0xd7, 0xaa, 0x74, - 0x64, 0xab, 0x03, 0xf4, 0x0d, 0x19, 0xf8, 0xd6, 0xb1, 0x05, 0x40, 0xb4, 0xc4, 0xef, 0xa9, 0x57, 0xfb, 0x32, 0x66, - 0x85, 0x7a, 0xfd, 0xc6, 0xb4, 0xeb, 0xa5, 0xb4, 0x28, 0xa0, 0xe2, 0xb6, 0x55, 0xdb, 0x23, 0x39, 0xff, 0xe1, 0x5d, - 0x47, 0x3b, 0x3e, 0x3b, 0x35, 0xb6, 0x84, 0x32, 0xb7, 0x78, 0x22, 0xab, 0xa3, 0x2d, 0xd5, 0xa9, 0x3e, 0xe0, 0x52, - 0x93, 0xea, 0xcc, 0xc0, 0xf0, 0x1a, 0x01, 0xca, 0x2d, 0x44, 0xd2, 0x38, 0xec, 0x9d, 0x4f, 0x06, 0x05, 0x73, 0x8b, - 0x04, 0x24, 0xb0, 0x8d, 0xad, 0x5d, 0x34, 0xd7, 0xaf, 0xdf, 0x53, 0xaf, 0x6a, 0x53, 0xd5, 0x83, 0x37, 0x5e, 0xe0, - 0xec, 0x9d, 0xd6, 0x02, 0x02, 0x28, 0x6c, 0x2d, 0xcb, 0xc1, 0xb9, 0xdb, 0x55, 0x2d, 0x15, 0x65, 0xd4, 0xef, 0x9f, - 0xff, 0x9e, 0xa2, 0x22, 0xf6, 0x54, 0x71, 0xca, 0xfa, 0xed, 0x96, 0x79, 0x53, 0x59, 0xf2, 0x06, 0x55, 0xb4, 0x56, - 0x47, 0x4d, 0xe5, 0xba, 0xb9, 0x6a, 0xc9, 0x04, 0x31, 0xba, 0x4f, 0xd7, 0x3a, 0x77, 0xea, 0xbd, 0x57, 0x71, 0xc4, - 0x40, 0x70, 0xd3, 0x3d, 0x3e, 0x38, 0x08, 0x8d, 0x8a, 0x72, 0xc1, 0x8d, 0xd2, 0xaa, 0x92, 0x52, 0xc8, 0x5b, 0x15, - 0xcd, 0x99, 0x3e, 0x02, 0x20, 0x02, 0xac, 0x12, 0xf5, 0xbf, 0xf9, 0xd2, 0x18, 0x0f, 0x1e, 0xf8, 0x9a, 0x5c, 0xc7, - 0xd6, 0xfb, 0xa7, 0x35, 0xd2, 0x6a, 0xe3, 0x98, 0xd4, 0xaa, 0x97, 0xad, 0xe2, 0x65, 0xf7, 0x3a, 0x15, 0x83, 0xe7, - 0xff, 0x73, 0x1f, 0xa0, 0x46, 0xb4, 0x94, 0xc1, 0xad, 0xab, 0x01, 0x1a, 0x1f, 0x8e, 0x85, 0x6f, 0xfc, 0x90, 0x71, - 0x3e, 0x98, 0xa1, 0xa3, 0xda, 0x1c, 0x1c, 0x10, 0x1c, 0xd5, 0x3d, 0x1a, 0x13, 0x66, 0xe1, 0xdc, 0x83, 0x40, 0xf5, - 0x89, 0xfb, 0x8c, 0x6b, 0x2f, 0x68, 0x13, 0xf8, 0x64, 0x5d, 0xd7, 0x14, 0x01, 0x2e, 0x62, 0x63, 0x22, 0x86, 0xb8, - 0x6c, 0x12, 0xa9, 0x6f, 0xc6, 0xa0, 0x00, 0x28, 0x9e, 0x55, 0x24, 0x97, 0xde, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, - 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, - 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, - 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, 0x19, 0x7f, 0x46, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, - 0x9e, 0xc3, 0x67, 0xbc, 0x9c, 0x84, 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, - 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, - 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, - 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, - 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, - 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, - 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, - 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x9b, 0x22, 0x87, 0xc5, 0xf8, 0x61, 0x83, - 0x91, 0xc6, 0x6a, 0x0d, 0x86, 0xe5, 0x12, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, - 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, - 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x22, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, - 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, - 0x9d, 0xe4, 0xed, 0x12, 0x8e, 0xba, 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, - 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, 0xf7, 0xa1, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, - 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, - 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, - 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, - 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0x67, 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, - 0xf3, 0x9a, 0x5d, 0x3f, 0x11, 0x6c, 0xc7, 0x76, 0x4f, 0x10, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, - 0x2f, 0x2c, 0xf9, 0x02, 0xc0, 0x03, 0x59, 0x0c, 0x28, 0x3e, 0x0b, 0xef, 0x17, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, - 0xbd, 0x77, 0x94, 0x7a, 0x03, 0x7f, 0x0e, 0x28, 0x7d, 0x92, 0x73, 0x6f, 0x39, 0xbc, 0xf5, 0x2f, 0x9e, 0x82, 0xf3, - 0xc4, 0x6a, 0x78, 0x03, 0x7f, 0x15, 0x7c, 0xe8, 0x2d, 0x07, 0x98, 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, - 0x85, 0xc4, 0xd8, 0x87, 0xdf, 0x82, 0x9c, 0xe1, 0x1f, 0xbf, 0x6b, 0x0c, 0xd6, 0xdf, 0x82, 0x42, 0xa3, 0xb1, 0x96, - 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x01, 0xdf, - 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, - 0x1d, 0x69, 0xbf, 0x2b, 0xd7, 0x60, 0xc7, 0xeb, 0xe4, 0xc8, 0x52, 0x78, 0xd6, 0x61, 0xe7, 0xa5, 0x53, 0xa2, 0xc3, - 0x30, 0xde, 0x6d, 0xd5, 0x33, 0x86, 0xf2, 0xdc, 0x60, 0x4c, 0x17, 0x3c, 0xe2, 0xcf, 0x06, 0xb9, 0x0c, 0x8d, 0x79, - 0x84, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, - 0x1a, 0xfc, 0x5e, 0x7b, 0x39, 0xf0, 0x1e, 0x44, 0x7e, 0x23, 0x5d, 0xca, 0x25, 0x36, 0x3a, 0x71, 0x2c, 0x0b, 0xed, - 0x3c, 0xae, 0xbf, 0x8e, 0x41, 0xfd, 0x5e, 0xe9, 0x37, 0x28, 0x67, 0x7f, 0x94, 0xac, 0xd3, 0xc6, 0x13, 0xe3, 0x5f, - 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, 0x5f, 0xa7, 0x65, 0xb4, 0x59, 0x2d, 0x44, 0x29, - 0xf2, 0x48, 0x9c, 0x7c, 0x2d, 0xb2, 0x73, 0xf9, 0xce, 0xa7, 0xd0, 0x2f, 0x00, 0x2d, 0xfb, 0x04, 0x19, 0xfd, 0x2b, - 0x13, 0x7c, 0xf8, 0xab, 0x76, 0xae, 0xcd, 0xf9, 0x78, 0x92, 0x5f, 0x59, 0x7b, 0xb7, 0xe3, 0x45, 0x62, 0x14, 0x63, - 0xb9, 0xaf, 0xba, 0x59, 0x39, 0x51, 0xc9, 0x81, 0x91, 0xae, 0xc9, 0x5e, 0xae, 0x64, 0xdd, 0x4e, 0xb7, 0x12, 0x88, - 0xa8, 0x02, 0xef, 0x31, 0xae, 0x62, 0x1f, 0xc1, 0x74, 0xdd, 0x71, 0x19, 0xed, 0x78, 0xcf, 0x78, 0x75, 0xa2, 0xac, - 0xe0, 0x76, 0x23, 0xda, 0x13, 0x3a, 0xfa, 0x69, 0x52, 0x5b, 0x16, 0x0e, 0x40, 0xee, 0x12, 0xc6, 0xb2, 0x21, 0x58, - 0x31, 0x28, 0x7d, 0xbd, 0xa6, 0x64, 0x59, 0x80, 0x45, 0x67, 0x97, 0x11, 0x88, 0x61, 0xdd, 0x34, 0x27, 0x74, 0xbc, - 0x74, 0x71, 0xde, 0x6b, 0x15, 0x29, 0x78, 0x46, 0x8b, 0x8e, 0xb9, 0xe9, 0x48, 0x37, 0x46, 0x7b, 0xfb, 0xc2, 0x20, - 0xa4, 0x78, 0xfe, 0xc0, 0x56, 0xeb, 0xe2, 0x22, 0xf1, 0x0a, 0x99, 0x68, 0x41, 0x2c, 0x45, 0x60, 0xc6, 0x0b, 0x4d, - 0x23, 0x4c, 0x50, 0xa6, 0x04, 0x8b, 0xd6, 0xe8, 0xd0, 0xfe, 0xb0, 0x84, 0xdd, 0x63, 0x8c, 0x00, 0x81, 0x2a, 0xd3, - 0x8b, 0xb0, 0x35, 0x61, 0x36, 0x75, 0xb1, 0x01, 0xda, 0x2a, 0x86, 0x06, 0x61, 0x6d, 0x88, 0xf9, 0x98, 0xe6, 0xcb, - 0x7f, 0x62, 0x31, 0xb6, 0x27, 0x10, 0xdb, 0xbb, 0x5d, 0x93, 0x30, 0xdd, 0x6b, 0x71, 0x63, 0xbd, 0xdc, 0x9e, 0x72, - 0x4c, 0xed, 0x58, 0x1b, 0xb5, 0x63, 0x2d, 0xf4, 0x8e, 0xb5, 0xd6, 0x3b, 0xd6, 0xb2, 0xe1, 0x1f, 0x32, 0x2f, 0x66, - 0x09, 0xe8, 0x77, 0x57, 0x5c, 0x35, 0x08, 0x9a, 0xb1, 0x61, 0xb7, 0xf0, 0x5b, 0x62, 0xed, 0x96, 0xfe, 0xc5, 0x82, - 0xdd, 0x98, 0x3e, 0xd0, 0xad, 0x03, 0x2c, 0x23, 0x6a, 0xf2, 0x1d, 0xf2, 0x6e, 0x3a, 0x2b, 0x0a, 0xb7, 0x27, 0x76, - 0xe3, 0xb3, 0x6b, 0xf3, 0xe6, 0xdd, 0x93, 0x08, 0x72, 0xef, 0xb8, 0x77, 0x37, 0xbc, 0xf6, 0x2f, 0x74, 0x0b, 0xe4, - 0x64, 0x96, 0x33, 0x90, 0x3a, 0xe2, 0x33, 0x44, 0x2b, 0x7b, 0xca, 0x77, 0x42, 0xee, 0x6c, 0xeb, 0x27, 0x77, 0xee, - 0xb6, 0xb6, 0x7c, 0x72, 0xc7, 0xaa, 0x11, 0xc5, 0x8a, 0xd3, 0x14, 0x09, 0xb3, 0x68, 0x03, 0x3c, 0xf5, 0xf2, 0xfd, - 0x8e, 0x1d, 0x73, 0xb8, 0x7b, 0xd2, 0xd1, 0xf1, 0x72, 0x0e, 0xd8, 0xdd, 0x7f, 0xb4, 0x09, 0x1b, 0x2b, 0x5d, 0xab, - 0xd0, 0xe1, 0xee, 0x49, 0xa6, 0xf1, 0x1c, 0x8e, 0xe4, 0xd3, 0xb1, 0xc6, 0x06, 0x41, 0x5d, 0x9f, 0x33, 0xa8, 0x1d, - 0xbb, 0xaf, 0x09, 0xbb, 0xec, 0x98, 0xd7, 0xba, 0xe6, 0xed, 0x95, 0xa7, 0x62, 0x43, 0x40, 0x87, 0xaf, 0xd5, 0x0d, - 0xf2, 0x2f, 0x81, 0x53, 0x04, 0x80, 0x1c, 0x8e, 0x97, 0x3c, 0xf6, 0x7d, 0x9a, 0xa5, 0xf5, 0x0e, 0xb5, 0x16, 0x95, - 0x65, 0x19, 0xd6, 0xde, 0x0f, 0x5a, 0x31, 0x2c, 0x35, 0xfd, 0xd3, 0x71, 0xe0, 0x76, 0xb6, 0x5b, 0x19, 0xbb, 0x8c, - 0x27, 0xc5, 0xc5, 0xaf, 0xa7, 0x85, 0x72, 0xed, 0xe6, 0x6d, 0xfc, 0xa6, 0xd5, 0x92, 0xa5, 0xb5, 0x1e, 0xf2, 0xd2, - 0xb2, 0x88, 0x40, 0x00, 0xc3, 0x91, 0xb2, 0x8b, 0x25, 0xdc, 0x23, 0xac, 0xee, 0x41, 0x28, 0x99, 0x17, 0x2e, 0x9e, - 0xb2, 0x18, 0x12, 0x01, 0xb6, 0x3b, 0x54, 0x6c, 0x0b, 0x17, 0x4f, 0xd9, 0x86, 0x17, 0xfd, 0x7e, 0xa6, 0x3a, 0x85, - 0xac, 0x3b, 0x0b, 0xbe, 0x51, 0xcd, 0xb1, 0x86, 0x9a, 0xad, 0x4d, 0xb2, 0x35, 0xce, 0x6d, 0xc5, 0xc7, 0xb2, 0xad, - 0xf8, 0x58, 0x59, 0xeb, 0xd2, 0xbd, 0xde, 0xa3, 0xba, 0x00, 0xb6, 0xfe, 0xdb, 0xe3, 0x95, 0xeb, 0xf9, 0x8c, 0x00, - 0xbe, 0x6e, 0xf8, 0x78, 0x72, 0x83, 0x5e, 0x25, 0x37, 0xfe, 0xed, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x37, 0x00, 0x5d, - 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x37, 0x73, - 0xb6, 0x03, 0xa7, 0x82, 0x64, 0x60, 0x2f, 0x2b, 0xb6, 0x0b, 0x62, 0x3b, 0xe1, 0x77, 0x02, 0xa6, 0x7c, 0x0e, 0x41, - 0x5c, 0xc1, 0x2d, 0xc4, 0xe1, 0xc9, 0x3f, 0x07, 0x77, 0xad, 0xcd, 0xfa, 0x8e, 0x59, 0x9d, 0x13, 0xac, 0x99, 0xd5, - 0x83, 0xc1, 0xa2, 0x99, 0xac, 0xfa, 0x7d, 0x6f, 0xa7, 0x1d, 0x9f, 0x96, 0x52, 0x27, 0x76, 0x5a, 0xab, 0x75, 0xc3, - 0xae, 0xa5, 0xd6, 0xc5, 0x18, 0x7a, 0x80, 0xf8, 0xe9, 0x76, 0xc0, 0xef, 0x3a, 0xd6, 0x96, 0x77, 0xcd, 0x6e, 0xd8, - 0x0e, 0x2e, 0x41, 0x4d, 0x7b, 0xd9, 0x9f, 0x54, 0x2e, 0x68, 0xc7, 0x2e, 0x89, 0x87, 0x33, 0x66, 0x95, 0x32, 0xb3, - 0x4e, 0xaa, 0x2b, 0xd1, 0x19, 0xd3, 0x59, 0xeb, 0xf9, 0x5c, 0xcd, 0x27, 0x85, 0x06, 0xf5, 0x3b, 0x27, 0x3e, 0xa2, - 0xa2, 0xf3, 0x04, 0xb6, 0x96, 0x15, 0xc4, 0x6a, 0x9f, 0x83, 0xb5, 0x56, 0xbb, 0xf4, 0x7b, 0xf9, 0x80, 0xdb, 0x94, - 0xc3, 0x3a, 0x30, 0xa8, 0x39, 0xb1, 0xa2, 0x1e, 0xb2, 0x1d, 0xe3, 0xe6, 0xa7, 0x97, 0x3f, 0x38, 0x61, 0xc9, 0x8a, - 0xd5, 0xfe, 0xf4, 0xd7, 0x27, 0x9e, 0xfe, 0x4e, 0xed, 0x5f, 0x08, 0x3f, 0x18, 0xff, 0xbb, 0x76, 0x5f, 0x6b, 0x31, - 0x2a, 0x5b, 0xe5, 0x08, 0x8d, 0xbb, 0x95, 0x34, 0x59, 0x7e, 0x16, 0x9e, 0xb0, 0x16, 0x3c, 0xcb, 0xf5, 0x12, 0xcd, - 0x0a, 0x58, 0x61, 0x2d, 0x93, 0x70, 0x85, 0xb1, 0x5a, 0xda, 0xea, 0x5b, 0x34, 0xcd, 0xf1, 0xe1, 0x5c, 0x1b, 0x94, - 0x29, 0x67, 0x67, 0xc4, 0x6a, 0xb8, 0x0c, 0x4b, 0x13, 0x8a, 0x90, 0xdd, 0xdb, 0xc1, 0x8d, 0x9d, 0xb2, 0x94, 0x32, - 0x9c, 0x63, 0x30, 0xe1, 0x91, 0x18, 0x55, 0xf9, 0xfe, 0xbe, 0xa4, 0xc8, 0x69, 0x5b, 0x0e, 0xaa, 0x10, 0xf6, 0x91, - 0x44, 0x09, 0xdc, 0x8a, 0xb4, 0x50, 0xa4, 0x2c, 0xfe, 0x76, 0x80, 0x2e, 0xf0, 0x02, 0xea, 0x6a, 0xd4, 0xed, 0x0f, - 0x47, 0x3c, 0x7c, 0x60, 0xea, 0x03, 0x23, 0x96, 0x04, 0x6a, 0x7b, 0x9e, 0xa5, 0x4b, 0x50, 0xe1, 0xf7, 0x70, 0x35, - 0x11, 0xfb, 0xb9, 0x25, 0x45, 0x45, 0x36, 0xd2, 0x1b, 0x5a, 0x83, 0x47, 0x68, 0x4d, 0x79, 0xe1, 0xa4, 0xda, 0xa4, - 0xf3, 0x8e, 0x90, 0x63, 0xf5, 0xad, 0x25, 0x8c, 0x76, 0x45, 0x2f, 0xee, 0x1d, 0xbd, 0xe7, 0xe9, 0xaa, 0xe7, 0xfe, - 0xc4, 0x15, 0xf3, 0xe4, 0x36, 0x02, 0x75, 0x2b, 0xa8, 0x6e, 0xef, 0x55, 0x82, 0x05, 0x4b, 0xda, 0x7d, 0xfc, 0x76, - 0xd6, 0x0e, 0x44, 0x65, 0xac, 0xd2, 0xb7, 0x24, 0x61, 0x4f, 0x0c, 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, - 0x75, 0xcc, 0x52, 0xf4, 0xdc, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x37, - 0xc4, 0x97, 0x23, 0x3c, 0xaa, 0x6e, 0x81, 0xe3, 0xf4, 0x1d, 0xc0, 0x3f, 0x1c, 0x2e, 0x41, 0x13, 0x10, 0x0b, 0xd6, - 0x4b, 0xe3, 0x1e, 0xeb, 0xc5, 0xc5, 0x66, 0x99, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, - 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, - 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, - 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, - 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, - 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0xff, 0x31, 0x7e, 0xdc, 0x33, - 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, 0xaf, 0xff, 0x84, 0x00, 0x38, 0x3c, 0x9b, 0x7a, 0x97, 0x63, 0xc8, 0x2a, 0xcb, - 0x08, 0x24, 0x3f, 0x31, 0xf8, 0xf2, 0x05, 0x40, 0xd5, 0x67, 0xba, 0x56, 0x93, 0xa3, 0xf6, 0x98, 0x43, 0x57, 0x0c, - 0x00, 0xdb, 0xb0, 0x44, 0x55, 0x2d, 0x6c, 0xc2, 0xe2, 0xf6, 0x33, 0x8c, 0xe6, 0xb2, 0xe9, 0x05, 0x0d, 0xd4, 0x23, - 0x04, 0xbf, 0xb4, 0x1e, 0x5a, 0x6b, 0x99, 0x72, 0xe8, 0xda, 0x28, 0xaa, 0x6c, 0xa8, 0x4b, 0x58, 0xad, 0x45, 0x54, - 0x13, 0x45, 0xca, 0x25, 0xa3, 0x28, 0x96, 0x2a, 0xd8, 0x67, 0x62, 0x09, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0x7e, - 0x09, 0x08, 0x6b, 0x61, 0x2d, 0xa4, 0x33, 0xa8, 0xbd, 0xd3, 0x8f, 0x94, 0xbf, 0xbc, 0x90, 0xdb, 0xb9, 0x85, 0x22, - 0xdc, 0x9e, 0x83, 0xf2, 0xa6, 0xae, 0x4a, 0x45, 0x34, 0x5a, 0x02, 0xa5, 0xcc, 0x09, 0x22, 0x0b, 0x10, 0xc0, 0x71, - 0x03, 0x81, 0xcf, 0x6b, 0x7c, 0x02, 0x8d, 0x42, 0x20, 0x3f, 0xb0, 0x0a, 0xd7, 0x1e, 0xd2, 0x52, 0x6b, 0x44, 0x94, - 0x88, 0x1f, 0x5d, 0x3d, 0xc7, 0xf6, 0xd5, 0xd3, 0x58, 0x5b, 0x4a, 0x13, 0xc4, 0x4f, 0x2c, 0xb6, 0x10, 0x13, 0x44, - 0x75, 0x88, 0x8e, 0x60, 0x39, 0x21, 0x44, 0xe1, 0x4f, 0xa1, 0x9f, 0x1a, 0xf8, 0x4b, 0xb6, 0x28, 0xf2, 0x9a, 0x60, - 0x31, 0x2b, 0x06, 0x68, 0x55, 0x04, 0x9e, 0xe9, 0x6c, 0xa9, 0xcc, 0x69, 0x1e, 0x1d, 0xd9, 0xc1, 0x79, 0xd7, 0xc1, - 0x5e, 0xfa, 0x32, 0x76, 0xb2, 0x6c, 0x1a, 0xb5, 0xb1, 0x21, 0x12, 0x5e, 0x91, 0x5f, 0x67, 0xa9, 0x71, 0x8e, 0xcc, - 0xe5, 0xfa, 0xae, 0x8b, 0xe5, 0x92, 0xb6, 0x09, 0xab, 0x10, 0xa1, 0x6e, 0x1b, 0x2a, 0x97, 0xc2, 0x6c, 0x6c, 0x9a, - 0x06, 0xf8, 0x42, 0x51, 0xa9, 0x54, 0xa5, 0xb6, 0x52, 0xc9, 0x09, 0xef, 0xfa, 0xa6, 0x16, 0xa9, 0x2b, 0x82, 0x6d, - 0xcc, 0x50, 0x0f, 0xe5, 0x46, 0x8d, 0x7d, 0xdb, 0xb1, 0x4a, 0xef, 0x30, 0x41, 0xce, 0xc8, 0x8b, 0x1c, 0x5c, 0x94, - 0x14, 0x64, 0xae, 0x86, 0x30, 0x7f, 0xd0, 0xf0, 0x69, 0x61, 0xb9, 0x87, 0x12, 0x30, 0x3b, 0x6a, 0x78, 0x18, 0x21, - 0x10, 0x71, 0xa9, 0xec, 0x2b, 0x26, 0x7e, 0x4f, 0xc1, 0x2c, 0x99, 0xd0, 0xbd, 0x88, 0x45, 0x11, 0xda, 0xf8, 0x24, - 0x49, 0xa6, 0x9e, 0xa6, 0xe0, 0x46, 0x2e, 0xc3, 0x1c, 0x8d, 0xd0, 0x92, 0x8f, 0x1c, 0x48, 0x5f, 0xcb, 0xa9, 0x04, - 0x1f, 0x51, 0xa7, 0x80, 0xe3, 0xf9, 0x79, 0x61, 0xfd, 0x64, 0xb9, 0xc4, 0x5c, 0xd6, 0xe6, 0xbf, 0xec, 0xe8, 0x18, - 0xec, 0xf2, 0x34, 0x71, 0x5c, 0xfd, 0x47, 0x55, 0x52, 0xdc, 0xbf, 0x49, 0x73, 0x40, 0x11, 0xcc, 0xec, 0x29, 0xc6, - 0xc7, 0x3e, 0xcb, 0x14, 0xf0, 0xb7, 0xeb, 0xad, 0x25, 0x13, 0xbb, 0xa4, 0xdd, 0x5c, 0x19, 0xbf, 0xd4, 0x86, 0x1d, - 0x07, 0xe7, 0x06, 0xa0, 0x38, 0x6b, 0x74, 0x58, 0x5e, 0xeb, 0xb6, 0x55, 0xa1, 0x02, 0xb5, 0xfe, 0xf7, 0x6e, 0x61, - 0xca, 0xdb, 0xbc, 0x54, 0xde, 0xe6, 0xa1, 0x09, 0x10, 0x88, 0xcc, 0x90, 0x67, 0x4d, 0xc7, 0x24, 0x71, 0xef, 0x48, - 0x49, 0xfb, 0x8e, 0x14, 0x3f, 0x78, 0x47, 0x42, 0xbe, 0x25, 0x74, 0x64, 0x5f, 0x70, 0x72, 0x02, 0x65, 0x06, 0x7b, - 0x79, 0xcd, 0x64, 0xff, 0x80, 0xf6, 0xc2, 0xb9, 0x2c, 0xaf, 0xf8, 0x5b, 0xe1, 0xad, 0xfd, 0xe9, 0xfa, 0xb4, 0xab, - 0xea, 0xed, 0x37, 0x66, 0xe6, 0xe1, 0x50, 0x1c, 0x0e, 0x95, 0x09, 0xda, 0xbd, 0xe1, 0x62, 0x90, 0xb3, 0x3b, 0x37, - 0x3e, 0xfe, 0x9a, 0xa3, 0x88, 0xad, 0x94, 0x47, 0xd2, 0x85, 0x4a, 0x0c, 0x2f, 0x0d, 0x3c, 0xcc, 0x8e, 0x8f, 0x27, - 0xbb, 0xab, 0xbb, 0xc9, 0x60, 0xb0, 0x53, 0x7d, 0xbb, 0xe5, 0xf5, 0x6c, 0x37, 0x67, 0xf7, 0xfc, 0x76, 0xba, 0x0d, - 0xf6, 0x0d, 0x6c, 0xbb, 0xbb, 0x2b, 0x71, 0x38, 0xec, 0x9e, 0xf1, 0x1b, 0x7f, 0x7f, 0x8f, 0x80, 0xce, 0xfc, 0x7c, - 0xdc, 0xc6, 0xf8, 0x79, 0xdb, 0x76, 0xd5, 0xda, 0x01, 0x3c, 0xfd, 0x6b, 0xef, 0xed, 0x6c, 0x31, 0xf7, 0xd9, 0x07, - 0x7e, 0x0f, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, 0x7c, 0x0b, 0x0e, 0xe4, 0x3b, 0x9f, 0x7d, 0xe6, - 0xf7, 0xb3, 0xc5, 0x9c, 0x17, 0x87, 0xc3, 0xfb, 0x69, 0x88, 0x64, 0x4d, 0x61, 0x45, 0x2c, 0x29, 0x9e, 0x1f, 0x84, - 0xc7, 0xef, 0x45, 0x64, 0x88, 0xb4, 0xdc, 0xbb, 0x43, 0xf6, 0x96, 0x45, 0x7e, 0x00, 0x1f, 0x64, 0x3b, 0x7f, 0x22, - 0x6b, 0x4a, 0xf7, 0x8b, 0x0f, 0xfe, 0xe1, 0x40, 0x7f, 0x7d, 0xf6, 0x0f, 0x87, 0xf7, 0xec, 0x1e, 0xc1, 0xd1, 0xf9, - 0x0e, 0xfa, 0x47, 0xdf, 0x3a, 0xa0, 0x2a, 0xc3, 0xeb, 0xd9, 0x66, 0xee, 0x3f, 0x5b, 0xb1, 0x25, 0x70, 0xa1, 0x28, - 0x2f, 0xb4, 0xb7, 0xec, 0x1e, 0xbd, 0xce, 0xc8, 0x89, 0x68, 0xb6, 0x9b, 0xfb, 0x2c, 0xc6, 0xe7, 0xea, 0xbe, 0x98, - 0x7c, 0xf3, 0xbe, 0xb8, 0x63, 0xdb, 0xee, 0xfb, 0xa2, 0x7c, 0xd3, 0x5d, 0x3f, 0x5b, 0xb6, 0x63, 0xf7, 0x30, 0xc3, - 0xae, 0xf9, 0xdb, 0xe6, 0xd8, 0x31, 0xf6, 0x9b, 0x37, 0x46, 0x00, 0x65, 0xb6, 0x60, 0xb1, 0xe0, 0xa0, 0x54, 0xab, - 0xb6, 0x25, 0x91, 0x57, 0x3a, 0x50, 0x6d, 0x46, 0x70, 0x5f, 0x2d, 0xe4, 0xcc, 0x33, 0x03, 0x7d, 0x5b, 0x21, 0x5a, - 0x38, 0x6c, 0xc0, 0xdf, 0x68, 0xeb, 0x18, 0xc3, 0x34, 0xab, 0x99, 0xb6, 0x45, 0x5d, 0x7e, 0xdf, 0x7b, 0x26, 0xbf, - 0x91, 0x81, 0x2d, 0x44, 0x52, 0x38, 0x8e, 0x2f, 0x9e, 0x9e, 0xf0, 0x5f, 0xb5, 0x3c, 0x6a, 0xb5, 0x5f, 0x28, 0xf5, - 0xe9, 0x35, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, - 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0x56, 0xa9, 0x14, 0x68, 0xe1, 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x16, 0x66, 0x29, - 0xef, 0xb1, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, 0x44, 0x58, 0xbd, 0x65, 0x9c, 0x5f, 0x36, 0xaa, 0x70, - 0x5b, 0x80, 0xa2, 0x08, 0xca, 0x60, 0x4f, 0x72, 0xdb, 0x8d, 0x92, 0x66, 0xa3, 0xb0, 0x16, 0xcb, 0xa2, 0xdc, 0xf5, - 0x1a, 0x76, 0x83, 0x17, 0x54, 0xfd, 0x84, 0xb0, 0x2d, 0x7b, 0xd6, 0xa1, 0x5c, 0xa4, 0xff, 0x96, 0xa5, 0xe7, 0xfb, - 0xad, 0x39, 0xff, 0xd3, 0x57, 0xf4, 0x51, 0xf9, 0xef, 0x5f, 0xd2, 0x4f, 0x06, 0xcb, 0xc8, 0x29, 0xf5, 0x53, 0x34, - 0xba, 0x4d, 0x73, 0xc2, 0xd8, 0xf2, 0xf5, 0xd3, 0xef, 0x90, 0x29, 0x48, 0x0e, 0xa5, 0x54, 0xe5, 0x64, 0x0f, 0x7d, - 0xe1, 0x75, 0x1f, 0x66, 0x82, 0x01, 0x08, 0xaf, 0xd1, 0xa6, 0x9a, 0x30, 0x89, 0x07, 0x57, 0xf0, 0x7f, 0x23, 0x88, - 0x41, 0xfb, 0x44, 0x51, 0xc7, 0xb6, 0x91, 0xae, 0xdb, 0xce, 0x41, 0x72, 0xa7, 0xae, 0xfc, 0x51, 0x39, 0xf9, 0x77, - 0x34, 0x44, 0x5e, 0x71, 0x85, 0x58, 0x59, 0x70, 0x89, 0xc5, 0x50, 0x91, 0x02, 0x5c, 0x43, 0x10, 0x29, 0x8b, 0x92, - 0xc2, 0x2d, 0x07, 0x55, 0x11, 0x80, 0x71, 0xb5, 0x3a, 0xea, 0x44, 0xf8, 0xb8, 0xb5, 0x16, 0x21, 0x58, 0xd1, 0xa8, - 0x95, 0xb5, 0x02, 0x5f, 0x90, 0xbe, 0x74, 0x28, 0x88, 0xe9, 0x51, 0x48, 0x55, 0xe9, 0x50, 0x20, 0xcd, 0xa1, 0xe2, - 0x1b, 0x83, 0x8d, 0xa2, 0x22, 0x3d, 0x7f, 0x69, 0x52, 0x72, 0x69, 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, - 0x14, 0xd3, 0x02, 0xf9, 0x46, 0x8f, 0x1f, 0x04, 0x97, 0xf0, 0x6e, 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, - 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, 0x9f, 0x58, 0x02, 0xdb, 0xd1, 0x3a, 0x3a, 0xd2, - 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x8e, 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xf6, - 0x5a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, - 0xfe, 0x70, 0xf4, 0x1f, 0x4f, 0xde, 0x4d, 0x08, 0x55, 0x67, 0xc3, 0xd6, 0x3a, 0xce, 0xe5, 0x7f, 0xfd, 0xe7, 0x98, - 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, - 0x5f, 0x68, 0x9d, 0x30, 0x31, 0xb2, 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0xa5, 0xca, 0x2c, 0x20, 0xf3, 0x20, 0x9f, 0xac, - 0x8d, 0x06, 0x73, 0xc5, 0xeb, 0xd9, 0x7a, 0x2e, 0x95, 0xcf, 0x60, 0xca, 0x59, 0x0c, 0x4e, 0x96, 0xc2, 0xee, 0x48, - 0xa0, 0x68, 0xcd, 0xd0, 0xb5, 0x3f, 0xc5, 0x56, 0xbd, 0x4c, 0xab, 0x1a, 0xe0, 0x01, 0x21, 0x06, 0x86, 0xda, 0xab, - 0x85, 0x87, 0xd6, 0x02, 0x58, 0xfb, 0xa3, 0xd2, 0x0f, 0xc6, 0x93, 0x05, 0xbf, 0x41, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, - 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x1b, 0xbe, 0xf1, 0x95, 0x0f, 0xc6, 0x35, - 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, 0xee, 0x84, 0xbe, 0xfa, 0x46, 0x0b, 0xc7, 0xdf, - 0x38, 0x23, 0xd7, 0x6c, 0xd5, 0x21, 0x47, 0x34, 0x93, 0x0e, 0x21, 0x62, 0xc5, 0xd6, 0xec, 0x9a, 0x54, 0xce, 0x9d, - 0x43, 0x76, 0xfa, 0x08, 0x55, 0x7a, 0xad, 0x87, 0xb7, 0x13, 0xa5, 0xbb, 0x3d, 0xde, 0x4d, 0xbe, 0x67, 0x13, 0x11, - 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xaf, 0x6f, 0x49, - 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x70, 0xc8, 0x41, 0xa3, 0xdc, 0xfc, 0xe9, 0x15, 0xea, 0x34, 0x07, 0xe6, - 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xe3, 0x23, 0xfd, 0xbf, 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, - 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa5, 0x8e, 0x82, 0x8b, 0xbc, 0xa3, 0x16, 0xb2, 0x67, 0xd9, 0xb8, 0x51, 0xcd, 0xfb, - 0xff, 0xb5, 0x32, 0xff, 0x5f, 0xd3, 0xca, 0x30, 0x25, 0x3b, 0x96, 0x6a, 0xe6, 0x81, 0x56, 0x31, 0xcc, 0xde, 0x90, - 0x84, 0xc8, 0x70, 0x69, 0xc0, 0x8f, 0x2a, 0xd8, 0xc7, 0x69, 0xb5, 0xce, 0xc2, 0x1d, 0x2a, 0x51, 0x6f, 0xc5, 0x32, - 0xcd, 0x9f, 0xd7, 0xff, 0x12, 0x65, 0x01, 0x53, 0x7b, 0x59, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, - 0x63, 0x1b, 0xdf, 0xc8, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0xba, 0x90, 0x9c, 0xcb, 0xca, 0xe2, - 0x1e, 0xa1, 0x9b, 0x7f, 0x2c, 0xcb, 0xa2, 0xf4, 0x7a, 0x9f, 0x93, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, - 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, - 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, - 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x2a, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, - 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xab, 0x1c, - 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, - 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x58, 0xb4, 0x92, - 0xb0, 0x6f, 0xdf, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0xf3, 0x8c, 0x23, 0x49, 0x94, 0x08, 0x5e, - 0xe5, 0x8d, 0x19, 0x87, 0x1f, 0xdb, 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, - 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, - 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x37, 0x12, 0x97, - 0x10, 0x2f, 0xf3, 0xd5, 0x54, 0x44, 0xc1, 0xfb, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, - 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, - 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, - 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, - 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0x37, 0x42, 0x75, 0xb0, 0x2d, - 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, - 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, - 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, 0xf8, 0x8f, 0x99, 0x87, 0x69, 0x35, 0x2b, 0xc1, 0x9c, 0x6f, 0xa0, 0x12, 0xe3, - 0xc9, 0xe2, 0x8a, 0x6f, 0x5c, 0xac, 0xc4, 0x64, 0xb6, 0x98, 0x4f, 0xd6, 0x92, 0x6a, 0x2e, 0xf7, 0xd6, 0x2c, 0x63, - 0x0b, 0xd8, 0x3f, 0x0c, 0x0c, 0xa5, 0x03, 0x3b, 0x9a, 0x6a, 0xda, 0x24, 0xc0, 0x64, 0x3a, 0xe7, 0x7c, 0x78, 0x89, - 0x68, 0xb2, 0x3a, 0x75, 0x27, 0x53, 0xd5, 0x0e, 0xae, 0xc9, 0x99, 0x9c, 0x1e, 0xa9, 0xa7, 0x5a, 0xf7, 0x92, 0x8f, - 0xb6, 0xc3, 0x6a, 0xb4, 0xf5, 0x03, 0x70, 0xeb, 0x14, 0x76, 0xfa, 0x6e, 0x58, 0x8d, 0x76, 0xbe, 0x86, 0xdd, 0x25, - 0x85, 0x40, 0xf5, 0x57, 0x59, 0x93, 0xb9, 0x78, 0x5d, 0xdc, 0x7b, 0x05, 0x7b, 0xea, 0x0f, 0xf4, 0xaf, 0x92, 0x3d, - 0xf5, 0x6d, 0x26, 0xd7, 0xbf, 0xd2, 0xae, 0xd1, 0x98, 0xe9, 0x78, 0xed, 0x0a, 0xac, 0xd0, 0x00, 0xf9, 0x05, 0x3b, - 0xda, 0xeb, 0x1c, 0x04, 0x02, 0x74, 0x2f, 0xc1, 0x51, 0x14, 0x10, 0x35, 0xad, 0x2a, 0x8f, 0x4e, 0xf7, 0xfe, 0x1e, - 0xdf, 0x08, 0x01, 0x9b, 0x3c, 0xb5, 0xee, 0x2d, 0x63, 0xff, 0x70, 0x80, 0x10, 0x7a, 0x39, 0xfd, 0x46, 0x5b, 0x56, - 0x8f, 0x76, 0x2c, 0xf7, 0x0d, 0xa3, 0x9e, 0x82, 0x31, 0x0c, 0x5d, 0x58, 0xc5, 0x48, 0x9e, 0x01, 0x59, 0xe3, 0x37, - 0x88, 0x2e, 0x60, 0xd1, 0xeb, 0xbd, 0x3c, 0xa2, 0x41, 0x04, 0x54, 0x7a, 0x4d, 0x1a, 0x8b, 0x7c, 0xae, 0x0a, 0xd1, - 0x7b, 0x6f, 0xed, 0xbc, 0x99, 0x91, 0x2c, 0x93, 0x46, 0xaa, 0xdd, 0xca, 0x62, 0x5d, 0x79, 0xb3, 0x13, 0xd2, 0xc5, - 0x1c, 0x43, 0x65, 0xf0, 0x38, 0x00, 0xa5, 0xe7, 0x3f, 0x42, 0xaf, 0x64, 0xc8, 0x34, 0x4b, 0x34, 0xb3, 0xbb, 0xc6, - 0x9f, 0xac, 0x52, 0x2f, 0x46, 0xc4, 0x6c, 0x60, 0x0b, 0x71, 0x5b, 0x54, 0xba, 0x2d, 0x0a, 0x65, 0x8b, 0x22, 0x7d, - 0xa8, 0x9d, 0xe9, 0xce, 0x2c, 0x7c, 0x56, 0x99, 0xf6, 0x7d, 0xce, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, - 0x40, 0x85, 0x90, 0xbf, 0x46, 0x44, 0x24, 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, - 0x46, 0x79, 0xc1, 0x93, 0xa3, 0x01, 0xa9, 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xb8, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, - 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, - 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, - 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, - 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, 0xe9, 0xd9, 0xdf, 0x52, 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, - 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x59, 0xbb, 0x5c, - 0xd5, 0xbd, 0xae, 0x60, 0x01, 0x4b, 0x70, 0xb7, 0x5e, 0x9a, 0xff, 0x86, 0xdd, 0xdf, 0x0b, 0x7a, 0x69, 0xfe, 0x3b, - 0xfd, 0x49, 0x01, 0x1c, 0x80, 0xc6, 0xd4, 0x6e, 0x81, 0x87, 0x18, 0x2a, 0x28, 0xdc, 0xcd, 0xca, 0xb9, 0x57, 0x03, - 0x1c, 0x26, 0xe9, 0x1b, 0x5a, 0xbd, 0xd2, 0x62, 0xd7, 0xcb, 0x64, 0xaf, 0x00, 0x0f, 0x55, 0xc8, 0xc3, 0xc3, 0x21, - 0xea, 0x18, 0x76, 0x50, 0x47, 0xc0, 0xb0, 0x87, 0xd0, 0xd8, 0x02, 0xcf, 0xc7, 0x37, 0x19, 0xdf, 0x0b, 0x50, 0x1b, - 0x21, 0x3c, 0x5e, 0x2d, 0xca, 0x10, 0x5b, 0xf6, 0x1a, 0xa9, 0xa4, 0xde, 0x08, 0x44, 0x19, 0xad, 0x02, 0xda, 0x6a, - 0x8f, 0x59, 0x1a, 0x3f, 0x41, 0xa8, 0x58, 0xea, 0x63, 0x08, 0x0d, 0x1c, 0x7e, 0x87, 0x03, 0x48, 0xf0, 0x25, 0xd7, - 0x64, 0x73, 0xaf, 0xf3, 0x3b, 0xda, 0xe7, 0x0f, 0x87, 0xf3, 0x4b, 0x04, 0xa5, 0x4b, 0xe1, 0x23, 0x95, 0x88, 0xea, - 0x29, 0x6e, 0x4a, 0xc8, 0x66, 0xc9, 0x4a, 0x3f, 0xf8, 0x4d, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, - 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, - 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, - 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, - 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, - 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, - 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, - 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, - 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, - 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, - 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, - 0xe0, 0xcf, 0xc4, 0x68, 0x5d, 0x10, 0x20, 0xb2, 0xd9, 0xbe, 0x3e, 0x56, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, - 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0x48, 0xbc, 0xfd, 0x69, 0x90, 0x9d, - 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, - 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, - 0x47, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, - 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, - 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, - 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, - 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, 0x46, 0x69, 0xf5, 0x93, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, - 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xe5, 0x34, 0xd8, 0x61, 0xa2, - 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, - 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, - 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, - 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x5d, 0x8b, - 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0x2f, 0x8a, 0xed, 0xdb, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x27, - 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, - 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, 0x1c, 0xc7, 0x9f, 0xa0, 0x82, 0xe0, 0xbf, 0x00, 0xb3, 0x18, 0x20, 0x4f, - 0x67, 0x21, 0xe1, 0x14, 0xc2, 0xc5, 0x2a, 0xeb, 0xf7, 0xe5, 0x2f, 0xea, 0xa2, 0x8b, 0x4c, 0xd6, 0x7d, 0x12, 0x8e, - 0xcc, 0x58, 0x4e, 0xbd, 0x90, 0x3c, 0xef, 0x79, 0x32, 0x4d, 0x9e, 0xe4, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x5d, 0x98, - 0x66, 0x60, 0x95, 0x26, 0xe5, 0x47, 0x28, 0x7d, 0xf1, 0x79, 0xe5, 0x07, 0x3a, 0x7b, 0x6e, 0x92, 0xe1, 0xcd, 0xaa, - 0xf5, 0x26, 0xb5, 0xae, 0x8b, 0x07, 0xfc, 0xab, 0x33, 0xd8, 0x38, 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, - 0xc6, 0x9f, 0x65, 0xb8, 0x2e, 0x55, 0x1b, 0x7d, 0x14, 0xa2, 0x73, 0xc8, 0x54, 0x80, 0x42, 0x91, 0xf6, 0x0f, 0x4a, - 0xad, 0x4c, 0x2a, 0x6d, 0x24, 0x80, 0xee, 0x61, 0xd2, 0x60, 0x8b, 0xa1, 0x8c, 0xa5, 0x49, 0x94, 0x3b, 0x0d, 0xe2, - 0xca, 0x7e, 0xac, 0x24, 0x0e, 0x2d, 0x8b, 0xe4, 0xdf, 0xbb, 0x9e, 0xbe, 0x42, 0xea, 0x4e, 0x16, 0xc8, 0x8c, 0xf1, - 0x3c, 0x8f, 0x3f, 0x03, 0x61, 0x36, 0x68, 0xa3, 0xa2, 0x10, 0x42, 0x36, 0x88, 0x41, 0xe3, 0x79, 0x1e, 0xbf, 0x50, - 0x34, 0x1e, 0xf2, 0x51, 0xe4, 0xab, 0xbf, 0x4a, 0xfd, 0x57, 0xe8, 0x33, 0x13, 0x3c, 0x42, 0x35, 0xd1, 0xbf, 0x7b, - 0x3e, 0xbb, 0x03, 0xb5, 0x61, 0x14, 0x66, 0xa6, 0xfc, 0xca, 0x37, 0xc5, 0xd9, 0xeb, 0xaf, 0xe8, 0x2a, 0xdb, 0xba, - 0x1f, 0xbd, 0x3a, 0x22, 0xb0, 0x36, 0x46, 0x57, 0xdc, 0x18, 0x40, 0x0e, 0x93, 0xf7, 0x2b, 0x4a, 0xcb, 0x21, 0x0d, - 0x42, 0x07, 0x0d, 0x41, 0xaf, 0x24, 0xfa, 0x40, 0x62, 0x11, 0x63, 0x78, 0x21, 0x9e, 0x91, 0x9a, 0x4c, 0x34, 0xc4, - 0x2b, 0x62, 0x3f, 0x44, 0x4b, 0x4e, 0x4d, 0x74, 0x23, 0x4c, 0x31, 0x90, 0xd8, 0x19, 0x24, 0x27, 0x49, 0xad, 0xfc, - 0xe2, 0x99, 0x24, 0x2c, 0xb1, 0xf3, 0x10, 0x83, 0x49, 0x2d, 0xdd, 0xe9, 0x4d, 0x95, 0xbe, 0x1c, 0x69, 0x39, 0x68, - 0x1f, 0x80, 0x5d, 0x4a, 0x7a, 0xff, 0xa4, 0x50, 0xc4, 0x87, 0x30, 0x8e, 0x21, 0x7c, 0x8b, 0xa8, 0xae, 0xc0, 0xb9, - 0x56, 0xa0, 0xb1, 0x1a, 0x78, 0x68, 0x66, 0xd5, 0x7c, 0xc8, 0xe9, 0xa7, 0xd2, 0xf2, 0xc7, 0x88, 0xc6, 0x46, 0xeb, - 0xe6, 0x70, 0xd8, 0xd3, 0xaa, 0x97, 0xce, 0x41, 0x97, 0xcd, 0x24, 0x26, 0x6e, 0x20, 0x5d, 0x3f, 0xfa, 0xcd, 0x84, - 0xbd, 0x88, 0x0a, 0xb9, 0x14, 0x82, 0x82, 0x56, 0x07, 0x02, 0x87, 0xc2, 0x5b, 0x94, 0xf9, 0x22, 0xa6, 0x0d, 0x84, - 0xc1, 0xe7, 0x07, 0xf2, 0xf3, 0x4d, 0x41, 0x2a, 0x76, 0xac, 0x6b, 0xbf, 0xbf, 0x28, 0x3d, 0xc0, 0x93, 0x33, 0x49, - 0x9e, 0x36, 0x43, 0x58, 0x11, 0x40, 0x63, 0x56, 0x93, 0xc5, 0x09, 0x57, 0xe6, 0xf0, 0x55, 0xe5, 0x95, 0x2c, 0x65, - 0xea, 0x3c, 0xd5, 0x0b, 0x20, 0xea, 0x78, 0x83, 0x56, 0xa4, 0x7e, 0x85, 0xce, 0x5e, 0xb3, 0x12, 0x32, 0x1e, 0x9e, - 0x73, 0x9e, 0x8e, 0xee, 0x59, 0xc2, 0x23, 0xfc, 0x2b, 0x99, 0xe8, 0xc3, 0xef, 0x9e, 0xc3, 0xcd, 0x38, 0xe1, 0x91, - 0xdb, 0xec, 0x7d, 0x15, 0xae, 0xe0, 0x66, 0x5a, 0x00, 0x92, 0x5b, 0x90, 0x34, 0x01, 0x25, 0x24, 0x32, 0x21, 0xb3, - 0xa6, 0xe4, 0x8b, 0x96, 0xb6, 0xc1, 0x1a, 0x26, 0x9d, 0x07, 0xbc, 0x68, 0xf5, 0xd1, 0x6a, 0xa2, 0x5d, 0x66, 0xf9, - 0x7c, 0x88, 0x33, 0x54, 0x73, 0xdc, 0x9d, 0xc1, 0xcf, 0x01, 0xaf, 0x58, 0xd5, 0xa4, 0xa3, 0xdd, 0x80, 0x0b, 0x4f, - 0xae, 0xf3, 0x74, 0xb4, 0xc5, 0x5f, 0x72, 0x7f, 0x00, 0xe8, 0x60, 0xea, 0x12, 0xf8, 0x53, 0xb5, 0xd5, 0x54, 0xea, - 0xd7, 0xd6, 0x7e, 0x5d, 0x77, 0x56, 0x2b, 0xf7, 0xac, 0xcb, 0xd0, 0x1e, 0x19, 0x72, 0xc6, 0x0c, 0xf8, 0x73, 0xc6, - 0x92, 0x3f, 0x67, 0xac, 0xf8, 0x73, 0xc6, 0x8d, 0x91, 0x01, 0x94, 0xe0, 0x5e, 0xf2, 0x67, 0x7b, 0xc4, 0x0c, 0xb1, - 0x1a, 0x54, 0x02, 0x2b, 0x4b, 0x39, 0xf7, 0x91, 0x53, 0x4c, 0x39, 0x65, 0x78, 0xe9, 0x74, 0xe6, 0x0e, 0xe4, 0x3c, - 0x98, 0xb9, 0xc3, 0x64, 0xaf, 0xcf, 0x8d, 0x38, 0x96, 0xc6, 0xa4, 0xa8, 0x20, 0x9d, 0xd3, 0xe1, 0xe6, 0xd5, 0x71, - 0x9e, 0xb0, 0x8c, 0x8f, 0xdb, 0x67, 0x0a, 0x84, 0xd8, 0xe2, 0x19, 0x12, 0x29, 0x55, 0xb3, 0xdc, 0xe6, 0x0f, 0x87, - 0x7a, 0x74, 0xaf, 0x77, 0x7a, 0xf8, 0x95, 0xb0, 0x5f, 0x33, 0xcf, 0x3e, 0x41, 0x00, 0x93, 0x44, 0x9e, 0x49, 0x38, - 0xfa, 0xb1, 0x1c, 0xfd, 0x4d, 0xc3, 0xbf, 0x64, 0xa8, 0xee, 0x0e, 0x81, 0x89, 0x2d, 0x3b, 0x70, 0x08, 0x4e, 0x57, - 0x95, 0x48, 0xc0, 0xc1, 0x66, 0xc3, 0x22, 0xbd, 0xc7, 0x43, 0x9c, 0x0f, 0x0a, 0x1f, 0xa1, 0x61, 0x46, 0xef, 0xf7, - 0x37, 0xc2, 0xab, 0x64, 0x2b, 0x0f, 0x87, 0xc4, 0xba, 0x0b, 0x3b, 0xfa, 0x38, 0xda, 0xa3, 0x84, 0xda, 0x8f, 0x6a, - 0xbd, 0xa9, 0xd4, 0x83, 0xdc, 0xec, 0x42, 0x62, 0x50, 0xb1, 0x54, 0x9f, 0x5e, 0xa9, 0x3e, 0xd4, 0xac, 0xf3, 0xbb, - 0x3a, 0xee, 0x53, 0x31, 0x5a, 0xcb, 0x09, 0x01, 0xae, 0x83, 0x44, 0xa3, 0x03, 0x60, 0x9c, 0x6d, 0xb6, 0xbc, 0xd4, - 0xd6, 0x89, 0xd2, 0x71, 0x9c, 0xeb, 0xe3, 0xf8, 0x70, 0x90, 0x62, 0xc6, 0xe5, 0x91, 0x98, 0x71, 0xd9, 0x00, 0xbc, - 0x59, 0xe7, 0x41, 0x7d, 0x38, 0x5c, 0xd2, 0xa5, 0xc8, 0x74, 0xb6, 0x51, 0x7e, 0xd6, 0xa3, 0xfb, 0x27, 0x09, 0x9a, - 0x7b, 0x2b, 0xec, 0xbd, 0x48, 0xb6, 0x67, 0xb2, 0x4e, 0xbd, 0x8c, 0x7c, 0x7a, 0xe1, 0x9e, 0x5d, 0x72, 0xf5, 0xc3, - 0xea, 0xeb, 0xe9, 0x6f, 0xc2, 0x8b, 0x58, 0x45, 0xbb, 0x75, 0xc9, 0x84, 0xbd, 0xa5, 0x54, 0xd2, 0x2a, 0x2f, 0x9f, - 0x6e, 0xfc, 0x00, 0x33, 0xd3, 0x9e, 0x3e, 0xc8, 0x46, 0x54, 0x7f, 0x56, 0xa2, 0x56, 0x86, 0xc9, 0xc2, 0x79, 0xc9, - 0xd4, 0x93, 0x01, 0x8f, 0x59, 0xc9, 0x23, 0xd9, 0xe9, 0x8d, 0x41, 0x10, 0xc0, 0x3a, 0x27, 0xad, 0x3a, 0xe3, 0x68, - 0xb4, 0xaa, 0x5c, 0x9c, 0xae, 0x72, 0x81, 0xe1, 0x76, 0x6b, 0xb6, 0x51, 0x75, 0x96, 0x9b, 0x5a, 0xa5, 0x7c, 0x07, - 0xf0, 0xb1, 0xac, 0x72, 0x41, 0xc7, 0x94, 0xa9, 0xf3, 0x06, 0x82, 0xb1, 0x55, 0x8d, 0x0b, 0xa7, 0xc6, 0x05, 0x8f, - 0xa8, 0xdd, 0x4d, 0x53, 0x8f, 0xb6, 0xc0, 0x52, 0x3a, 0xda, 0xf1, 0x12, 0x55, 0x0a, 0x3f, 0x0b, 0xbe, 0x0f, 0xe3, - 0xf8, 0x45, 0xb1, 0x55, 0x07, 0xe2, 0x6d, 0xb1, 0x45, 0xda, 0x17, 0xf9, 0x17, 0xe2, 0x80, 0xd7, 0xba, 0xa6, 0xbc, - 0xb6, 0xe6, 0x34, 0xb0, 0x35, 0x8c, 0x94, 0x14, 0xce, 0xcd, 0x9f, 0x87, 0x03, 0xad, 0xec, 0x5a, 0xdd, 0x15, 0x6a, - 0x3d, 0xe6, 0xb0, 0x61, 0xdf, 0x64, 0xe1, 0x4e, 0x94, 0xe0, 0xc8, 0x25, 0xff, 0x3a, 0x1c, 0xb4, 0xca, 0x52, 0x1d, - 0xe9, 0xb3, 0xfd, 0xd7, 0x60, 0xcc, 0xd0, 0xa5, 0x09, 0x58, 0x36, 0x46, 0xf2, 0xaf, 0xa6, 0x99, 0x37, 0x4c, 0xd6, - 0x4c, 0xe1, 0x38, 0x34, 0x8c, 0x90, 0x06, 0x74, 0x1b, 0xd4, 0x86, 0x27, 0xf3, 0x4d, 0x55, 0x7e, 0x75, 0x47, 0xaa, - 0xfd, 0x60, 0x78, 0x39, 0x11, 0xe7, 0x74, 0x49, 0x52, 0x4f, 0x25, 0x94, 0x84, 0x60, 0x97, 0x3e, 0x90, 0x13, 0x2b, - 0x20, 0x6b, 0x19, 0xcb, 0x6f, 0xf5, 0x80, 0xd0, 0x7f, 0xda, 0xad, 0x17, 0xfa, 0x4f, 0xd3, 0x6c, 0xa1, 0xae, 0x3f, - 0x4c, 0xee, 0x3b, 0x7a, 0xfd, 0xc1, 0xe1, 0x9d, 0xba, 0xaa, 0xb8, 0x8a, 0x47, 0xb5, 0x61, 0x92, 0x1b, 0x65, 0xe1, - 0xae, 0xd8, 0xd4, 0x6a, 0x79, 0x3a, 0x0e, 0x23, 0x30, 0x23, 0x28, 0x40, 0xd6, 0x75, 0x1b, 0x11, 0xc3, 0x4a, 0x2e, - 0x13, 0xf2, 0x09, 0x01, 0x59, 0x94, 0x1a, 0xe7, 0xe3, 0x16, 0xa8, 0x44, 0x30, 0x38, 0x0d, 0xad, 0x55, 0x37, 0xf9, - 0x49, 0x65, 0x63, 0x4b, 0x20, 0x87, 0x24, 0x93, 0xc5, 0x72, 0x74, 0x2b, 0x16, 0x45, 0x29, 0xde, 0x60, 0x3d, 0x5c, - 0xb3, 0x85, 0xfb, 0x0c, 0x08, 0xed, 0x27, 0x4a, 0x7b, 0x13, 0x69, 0x82, 0xee, 0x25, 0x5b, 0x01, 0xc8, 0x00, 0x8a, - 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, 0x9f, 0x2e, 0x83, 0xe5, 0xe0, 0x12, 0xb5, 0xd2, - 0x97, 0x2c, 0x6e, 0x61, 0x50, 0xed, 0xcd, 0x12, 0x0e, 0x6a, 0x66, 0xad, 0x8d, 0x40, 0x30, 0xd9, 0x43, 0x41, 0xc5, - 0x5c, 0xc1, 0x3e, 0x28, 0x58, 0x4b, 0x5e, 0x07, 0x87, 0x5b, 0xfb, 0xb2, 0x52, 0x5c, 0x3c, 0xbd, 0x48, 0x5a, 0x17, - 0x96, 0xf2, 0xe2, 0x69, 0x03, 0x06, 0x97, 0x23, 0x6c, 0x2a, 0x30, 0x49, 0x00, 0xe8, 0x56, 0x44, 0x11, 0x2f, 0x4a, - 0x61, 0xdb, 0xca, 0x67, 0x4e, 0xd8, 0x60, 0xc3, 0xee, 0xe1, 0x5e, 0x19, 0x94, 0x0c, 0x2e, 0xc4, 0xb8, 0xdd, 0xec, - 0x02, 0x5c, 0xc1, 0x50, 0x18, 0x5b, 0xf3, 0x77, 0x99, 0x17, 0x29, 0x01, 0x37, 0x43, 0x94, 0xaf, 0x0d, 0x9c, 0x4c, - 0x7a, 0x72, 0x2d, 0x58, 0x0c, 0x58, 0xd0, 0xe0, 0x3b, 0x6a, 0xfd, 0x9d, 0xc9, 0xbf, 0xf1, 0xf4, 0xd0, 0x0f, 0x5e, - 0x64, 0xde, 0xc2, 0x67, 0xef, 0x2a, 0x19, 0xad, 0x49, 0xa2, 0xbc, 0x7a, 0xb8, 0x00, 0xb9, 0x61, 0x31, 0xba, 0x67, - 0x0b, 0x10, 0x27, 0x16, 0xa3, 0x84, 0x32, 0xba, 0xc2, 0xbd, 0xca, 0x6c, 0x99, 0x08, 0xa4, 0x38, 0xb0, 0x90, 0x72, - 0x6f, 0xb1, 0x0e, 0x16, 0xb8, 0x3f, 0x91, 0x5c, 0x40, 0xc9, 0x03, 0x28, 0x57, 0x0a, 0x08, 0xf8, 0x74, 0x00, 0xe5, - 0x4b, 0x79, 0x11, 0xfe, 0xc4, 0x89, 0x1a, 0x2c, 0x46, 0xf7, 0x0d, 0xfb, 0xc9, 0x0b, 0x2d, 0xfb, 0xc3, 0x52, 0x6b, - 0x1a, 0x56, 0x7c, 0x09, 0xd3, 0x62, 0xe2, 0xf6, 0xe5, 0xca, 0xae, 0x8a, 0xcf, 0x56, 0xea, 0xec, 0xa6, 0x86, 0x24, - 0xec, 0x1b, 0xb2, 0x0a, 0x70, 0xb0, 0x2a, 0xe2, 0x9e, 0x75, 0xb9, 0x0f, 0xa3, 0xbf, 0x36, 0x69, 0x29, 0x2c, 0x54, - 0x49, 0x7f, 0xdf, 0x94, 0x02, 0xa9, 0x4c, 0x74, 0xa2, 0x85, 0xe0, 0x0a, 0x0c, 0x02, 0x77, 0x22, 0xaf, 0x01, 0x30, - 0x06, 0x5c, 0x0a, 0x94, 0x65, 0x5b, 0x42, 0x48, 0x75, 0x3f, 0x03, 0xb5, 0x9d, 0xb8, 0x4b, 0x23, 0xb2, 0x16, 0xa2, - 0xaf, 0x82, 0x31, 0x73, 0x5e, 0x4a, 0xb7, 0xd8, 0x74, 0xb5, 0x59, 0x7d, 0x42, 0xe7, 0xd2, 0x96, 0x9b, 0x9f, 0xb0, - 0xc5, 0x5a, 0x81, 0xb2, 0x09, 0x49, 0xdb, 0x39, 0xcf, 0x51, 0x36, 0xa1, 0xa5, 0xbd, 0xa7, 0x1e, 0x15, 0xaa, 0x93, - 0xad, 0x97, 0xaa, 0xa9, 0x45, 0x58, 0x2d, 0x2e, 0x2a, 0x3f, 0x00, 0xdd, 0x54, 0x5a, 0x3d, 0xaf, 0x6b, 0x34, 0x85, - 0x5a, 0x2d, 0x1c, 0x37, 0xda, 0xd9, 0x74, 0x91, 0x2e, 0x11, 0x67, 0x55, 0xda, 0xa1, 0x7f, 0xca, 0xb4, 0xeb, 0x65, - 0x47, 0xbf, 0x19, 0x57, 0x17, 0xb8, 0x10, 0x1b, 0xf0, 0x39, 0xf7, 0x97, 0xd7, 0x7b, 0x1a, 0xf7, 0xfc, 0xc3, 0x01, - 0xd9, 0x93, 0xda, 0x1f, 0xaa, 0x8f, 0x5d, 0xc1, 0x90, 0x85, 0x51, 0xea, 0x2f, 0x52, 0xde, 0x7b, 0x84, 0xe3, 0xfe, - 0xa5, 0xea, 0xb1, 0x5f, 0x32, 0xbe, 0xaf, 0x8b, 0x4d, 0x94, 0x50, 0x54, 0x43, 0x6f, 0x55, 0x6c, 0x2a, 0x11, 0x17, - 0xf7, 0x79, 0x8f, 0x61, 0x32, 0x8c, 0x85, 0x4c, 0x85, 0x3f, 0x65, 0x2a, 0x78, 0x84, 0x50, 0xe2, 0x66, 0xdd, 0x23, - 0xed, 0x26, 0xc4, 0x29, 0xd5, 0xa2, 0x94, 0xc9, 0xf8, 0xb7, 0x7e, 0x02, 0xe5, 0x39, 0x45, 0xcb, 0xf4, 0xa3, 0xc2, - 0x65, 0xfa, 0x66, 0x7d, 0x5c, 0x7a, 0x26, 0x42, 0x9d, 0xb9, 0xd8, 0xd4, 0x3a, 0x1d, 0x63, 0xa7, 0x74, 0x6a, 0xc3, - 0xbe, 0x56, 0x8a, 0xcb, 0x8a, 0xc2, 0xbf, 0x91, 0xc8, 0xaa, 0x67, 0xc4, 0xf1, 0x7f, 0x66, 0xed, 0x33, 0xac, 0x02, - 0xbf, 0x0c, 0xe4, 0xfd, 0x02, 0xe0, 0xe3, 0xba, 0x2e, 0xd3, 0xdb, 0x0d, 0xd0, 0x86, 0xd0, 0xf0, 0xf7, 0x7c, 0x64, - 0xc0, 0x74, 0x1f, 0xe1, 0x0c, 0xe9, 0xa1, 0xce, 0x39, 0x9d, 0x95, 0xe9, 0x9c, 0xab, 0xb0, 0x96, 0x60, 0x2f, 0x27, - 0x4d, 0x2e, 0xd7, 0x25, 0xa8, 0x99, 0xc0, 0xed, 0x43, 0x7b, 0x44, 0x08, 0xb5, 0x29, 0xab, 0xe9, 0x25, 0xd4, 0xbc, - 0x93, 0xd3, 0x8e, 0x26, 0x25, 0xb8, 0x6a, 0xe8, 0xac, 0x5c, 0xff, 0x75, 0x38, 0xf4, 0x6e, 0xb3, 0x22, 0xfa, 0xb3, - 0x87, 0xfe, 0x8e, 0xdb, 0x4f, 0xe9, 0x57, 0x88, 0x96, 0xb1, 0xfe, 0x86, 0x0c, 0xe8, 0x78, 0x32, 0xbc, 0x2d, 0xb6, - 0x3d, 0xf6, 0x15, 0x35, 0x58, 0xfa, 0xfa, 0xf1, 0x09, 0x24, 0x54, 0x5d, 0xfb, 0xc2, 0xe2, 0x09, 0xf3, 0x94, 0x68, - 0x5b, 0xf8, 0x10, 0x16, 0xfa, 0x15, 0x22, 0x23, 0x21, 0xdc, 0x54, 0x76, 0x8f, 0x92, 0x76, 0xa1, 0x2f, 0x7d, 0x2d, - 0xfb, 0xca, 0x77, 0x2e, 0x00, 0x56, 0xf6, 0xa9, 0x0d, 0xf7, 0xa4, 0x3f, 0xa5, 0xfa, 0xb0, 0xfd, 0x2d, 0x59, 0x40, - 0xa1, 0x85, 0xf5, 0x54, 0xce, 0xce, 0x65, 0xc9, 0xf3, 0x6c, 0xba, 0x5f, 0xc3, 0x1e, 0x75, 0x87, 0x5e, 0x53, 0xc1, - 0xf9, 0xa5, 0x19, 0xbd, 0xdf, 0x0d, 0x85, 0xea, 0xa8, 0x73, 0x07, 0x59, 0x96, 0xd6, 0x25, 0xe7, 0x2f, 0x2b, 0x77, - 0x14, 0xe6, 0x77, 0x21, 0x78, 0x86, 0x75, 0xef, 0x2e, 0xce, 0x7b, 0xbf, 0xb5, 0xe6, 0xc8, 0x2f, 0xd9, 0x2c, 0x45, - 0x2c, 0x92, 0x39, 0x58, 0xfd, 0xd0, 0xcf, 0x63, 0xbf, 0x0d, 0x72, 0x38, 0x6e, 0x1a, 0xd0, 0x61, 0x43, 0x66, 0xed, - 0x4b, 0x04, 0x4e, 0x35, 0x82, 0x34, 0x35, 0x41, 0xcd, 0xf2, 0x10, 0x89, 0xed, 0x52, 0xb6, 0x0d, 0x72, 0xdd, 0x05, - 0xd3, 0x1c, 0x69, 0xcf, 0xe0, 0x7d, 0x93, 0x26, 0xa9, 0xd0, 0x2c, 0xba, 0x58, 0xc9, 0xf8, 0x77, 0xa4, 0xcd, 0x94, - 0xec, 0xb1, 0x35, 0xf0, 0x5e, 0x82, 0x72, 0x32, 0x4c, 0x31, 0x7c, 0xc7, 0xd7, 0x3b, 0x8f, 0x2e, 0xe2, 0xe7, 0x63, - 0xb6, 0x49, 0xd9, 0x11, 0x4c, 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xfd, 0x6d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, - 0x33, 0x69, 0x73, 0x85, 0x6e, 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, - 0xe2, 0x77, 0x60, 0x0e, 0x63, 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, - 0x02, 0x8c, 0xbe, 0xda, 0x16, 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, - 0xd0, 0xf9, 0x7d, 0x73, 0x5b, 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xed, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, - 0xad, 0x71, 0x9a, 0xf9, 0xdf, 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x5f, 0x20, 0x7a, 0x5f, - 0xb7, 0x72, 0x55, 0x6a, 0x37, 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, - 0x39, 0xff, 0x52, 0xf5, 0xfb, 0xde, 0x17, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, - 0x6d, 0x4a, 0xd8, 0x90, 0xdb, 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x0f, 0x39, 0xdf, - 0xaf, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, - 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x85, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, - 0x5a, 0x82, 0x76, 0xc1, 0xa6, 0xb0, 0xbf, 0x3f, 0x38, 0xe4, 0xfd, 0xfe, 0xc7, 0xdc, 0x6b, 0xf1, 0xba, 0x1b, 0xb8, - 0xcb, 0xd2, 0x43, 0x08, 0x60, 0x2d, 0x03, 0x65, 0x1c, 0x61, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, - 0x65, 0x57, 0x4e, 0x32, 0x0d, 0x30, 0xa3, 0x9a, 0xc2, 0x4c, 0x80, 0x91, 0xfa, 0x88, 0x75, 0xd3, 0xd3, 0x2a, 0xb4, - 0x7c, 0x0d, 0xc1, 0xba, 0xc8, 0x32, 0x8e, 0x62, 0x26, 0x00, 0xd8, 0x7c, 0x04, 0xf9, 0x8a, 0xae, 0x0e, 0x49, 0x2b, - 0x55, 0xde, 0xaf, 0x33, 0x22, 0xa3, 0x49, 0x88, 0xe6, 0xb7, 0xf0, 0xc0, 0xbe, 0x6d, 0x66, 0x54, 0xa9, 0x67, 0x54, - 0xe5, 0x33, 0x1c, 0x96, 0xc2, 0x31, 0xe2, 0xff, 0x9c, 0xaa, 0x1e, 0x11, 0xe8, 0x55, 0x99, 0x56, 0x51, 0x91, 0xe7, - 0x22, 0x42, 0x84, 0x6a, 0xe9, 0x1c, 0x0e, 0xfd, 0xd8, 0xef, 0xe3, 0x40, 0x98, 0x17, 0xeb, 0xe4, 0x81, 0xae, 0xac, - 0x69, 0xad, 0xa4, 0xc0, 0xa9, 0xa8, 0x11, 0x22, 0x84, 0xf7, 0x1b, 0xf0, 0xac, 0xa6, 0xbe, 0xdf, 0x58, 0x26, 0xba, - 0xdf, 0x33, 0xa0, 0xfc, 0x01, 0xf9, 0xba, 0x92, 0xe2, 0x8c, 0x48, 0x1e, 0x12, 0x67, 0x1c, 0x80, 0x98, 0x6f, 0x4b, - 0x34, 0x1a, 0xfb, 0x1f, 0x90, 0x60, 0xa8, 0x7e, 0xb0, 0xd3, 0x4d, 0xbd, 0x7f, 0x66, 0x12, 0x47, 0xd1, 0xa7, 0x6d, - 0xf2, 0x58, 0xb2, 0x34, 0x5a, 0x38, 0x7a, 0x8f, 0x18, 0xc6, 0xe1, 0x74, 0x3e, 0x26, 0xd9, 0xc6, 0x64, 0x15, 0x40, - 0x3a, 0x99, 0xa9, 0x63, 0x4a, 0x1d, 0x8d, 0x73, 0xbd, 0xa0, 0x0a, 0x3d, 0xd6, 0x25, 0xcf, 0xc1, 0x7a, 0xf2, 0xda, - 0x2b, 0xfd, 0xa9, 0x90, 0x73, 0xd8, 0x48, 0x04, 0x85, 0x1f, 0xe0, 0x6a, 0xb0, 0x52, 0xc0, 0x60, 0xea, 0x5b, 0xf8, - 0x9a, 0x78, 0x8e, 0x82, 0x47, 0x61, 0x17, 0x63, 0x6b, 0xe5, 0x3b, 0x9f, 0x14, 0x94, 0x7b, 0x56, 0xcc, 0x79, 0x05, - 0x9c, 0xcb, 0xa0, 0x10, 0xa6, 0xe3, 0x59, 0xfe, 0xcf, 0x24, 0xaf, 0x27, 0x36, 0x04, 0xc8, 0xe0, 0x4f, 0x89, 0xd3, - 0xd2, 0x1d, 0xba, 0xf3, 0xd0, 0xb3, 0x88, 0xc3, 0x46, 0x8f, 0xd6, 0x65, 0xb1, 0x4d, 0x51, 0x2f, 0x61, 0x7e, 0x20, - 0x3f, 0x6f, 0xc9, 0xf7, 0x21, 0x8a, 0xb7, 0xc1, 0xcf, 0x19, 0x8b, 0x05, 0xfe, 0xf5, 0xb7, 0x8c, 0xd1, 0x44, 0x0b, - 0xfe, 0x9e, 0x35, 0x48, 0x54, 0x0c, 0x58, 0x11, 0xc0, 0x65, 0xaa, 0x3e, 0x7c, 0x4a, 0x8c, 0xb7, 0x66, 0xc3, 0x03, - 0xdf, 0xac, 0x40, 0xa7, 0x3e, 0x77, 0x57, 0xb6, 0xa7, 0xab, 0x91, 0xaa, 0x6a, 0xfc, 0x9c, 0xaa, 0x6a, 0xfc, 0x9c, - 0x52, 0x35, 0xfe, 0xca, 0x28, 0x7e, 0xa7, 0xf2, 0x19, 0x32, 0x27, 0x9b, 0x98, 0xa4, 0xd3, 0xf7, 0x86, 0x13, 0xbb, - 0xec, 0xb7, 0x6e, 0x13, 0x69, 0x66, 0x22, 0x85, 0xdc, 0x1b, 0x80, 0x9a, 0x89, 0x1f, 0x73, 0xc3, 0x29, 0x71, 0x7e, - 0xee, 0xe1, 0x8a, 0x4d, 0xab, 0x6b, 0x5a, 0xb0, 0xc0, 0xe6, 0x65, 0x96, 0x67, 0x9a, 0xc0, 0xb6, 0x29, 0xb3, 0xbe, - 0xc9, 0x3d, 0x80, 0x60, 0x26, 0x35, 0x01, 0x20, 0x2d, 0x44, 0xa5, 0x10, 0xf9, 0x35, 0xce, 0xea, 0x73, 0xde, 0xdb, - 0xe4, 0x31, 0x91, 0x56, 0xf7, 0xfa, 0xfd, 0xf4, 0x2c, 0xcd, 0x29, 0xa8, 0xe1, 0x38, 0xeb, 0xf4, 0xa7, 0x2c, 0x10, - 0x89, 0x5c, 0xa5, 0xff, 0x70, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, 0x0b, - 0x04, 0x77, 0x72, 0xec, 0x27, 0xab, 0x52, 0x1e, 0x19, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, 0xfa, - 0x83, 0xd4, 0xd3, 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, 0x87, - 0xfb, 0xdc, 0x92, 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, 0xfb, - 0x7d, 0xf5, 0xf7, 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, 0xb9, - 0x8d, 0xa3, 0xad, 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, 0x2b, - 0x23, 0x2d, 0x3c, 0x7f, 0x8a, 0xbf, 0x6e, 0xea, 0x02, 0xc3, 0x33, 0x68, 0x8d, 0x56, 0x10, 0x4c, 0xf0, 0x8f, 0x0e, - 0xd4, 0x4b, 0x2b, 0xed, 0x23, 0xe8, 0x56, 0xa0, 0x07, 0x8d, 0x7d, 0x20, 0x69, 0x5f, 0x48, 0xd4, 0xed, 0xad, 0x4e, - 0xa3, 0x3f, 0x2b, 0x96, 0xf3, 0x0a, 0x26, 0x87, 0x1b, 0xfa, 0xb4, 0x0a, 0xb7, 0x9f, 0xe1, 0xe9, 0x1b, 0xa0, 0xdc, - 0x3a, 0x1c, 0x72, 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x29, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x4b, 0xd0, 0xde, - 0x05, 0xe8, 0x80, 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, 0x9e, - 0xe5, 0xb3, 0x4a, 0xe3, 0xb3, 0x27, 0x5e, 0xcd, 0x32, 0x70, 0x16, 0xb8, 0xa8, 0x7c, 0x96, 0x69, 0xd5, 0x53, 0x91, - 0xa0, 0xcf, 0x2b, 0x39, 0xc1, 0x95, 0xe0, 0x64, 0x03, 0xf2, 0x0b, 0x90, 0xa4, 0x29, 0x65, 0x4d, 0xf9, 0xec, 0x92, - 0x6e, 0xc8, 0xe8, 0x39, 0xef, 0x79, 0xd1, 0x30, 0xf4, 0x2f, 0xbc, 0x12, 0xc2, 0x37, 0x71, 0xdb, 0x46, 0x29, 0xec, - 0x6f, 0x02, 0x8b, 0x4f, 0xd8, 0x6b, 0x6f, 0xe1, 0x4f, 0xc7, 0x41, 0x38, 0x44, 0x6e, 0xa8, 0x98, 0x03, 0x7b, 0x1a, - 0xb0, 0xd8, 0xc4, 0x57, 0x9b, 0x49, 0x3c, 0x18, 0xf8, 0x3a, 0x63, 0x31, 0x8b, 0x81, 0x06, 0x39, 0x1e, 0x5c, 0xce, - 0xf5, 0x09, 0xa1, 0x1f, 0x46, 0x54, 0x8e, 0x0a, 0x74, 0x0e, 0xa2, 0xc1, 0x02, 0xf0, 0xd4, 0x5b, 0xd9, 0x20, 0xc9, - 0xd0, 0x40, 0x27, 0xae, 0x35, 0x49, 0x75, 0x38, 0xa1, 0x75, 0xa0, 0xe3, 0xea, 0x0d, 0x74, 0x3e, 0xae, 0x7b, 0x1f, - 0xaf, 0x86, 0x37, 0x54, 0xfa, 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0xf0, 0x66, 0x15, 0x6e, 0xdf, - 0xc8, 0x07, 0x8e, 0x3b, 0x2a, 0x69, 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0xc7, 0x94, 0xa3, 0xc3, 0x38, 0x92, - 0x43, 0xac, 0x5a, 0x71, 0x21, 0xbd, 0x11, 0x7c, 0xbb, 0x50, 0x8c, 0x65, 0x63, 0x97, 0x86, 0xa2, 0xf0, 0x67, 0x00, - 0x3b, 0xd4, 0xfe, 0x4a, 0x25, 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, - 0x89, 0x3f, 0x32, 0x63, 0x1d, 0x35, 0x5d, 0x5f, 0xb0, 0x1c, 0x59, 0x92, 0x6e, 0x67, 0x12, 0xcb, 0x89, 0x24, 0xb5, - 0xdd, 0x47, 0xc4, 0x60, 0xe0, 0x83, 0x8d, 0x98, 0x66, 0x22, 0x1c, 0xf1, 0xa8, 0x44, 0x16, 0x5d, 0x7e, 0x1b, 0x61, - 0xd2, 0xf6, 0x65, 0x45, 0xb6, 0x20, 0x98, 0x9e, 0x44, 0x1f, 0x24, 0x29, 0xa7, 0x22, 0x91, 0x66, 0x84, 0x00, 0x3f, - 0x9e, 0x94, 0x57, 0xfa, 0x73, 0xd0, 0xb4, 0x12, 0xbc, 0x64, 0x90, 0x3c, 0x12, 0x3f, 0x93, 0x82, 0x59, 0x8c, 0x55, - 0x83, 0x01, 0x96, 0x53, 0x3d, 0x71, 0x4c, 0xd2, 0x7f, 0xeb, 0x74, 0xc2, 0x7e, 0xee, 0xe5, 0xb6, 0x96, 0x37, 0xcd, - 0xbd, 0xe7, 0x5e, 0xc5, 0x52, 0x0d, 0xcb, 0xa0, 0xff, 0x9a, 0x68, 0x17, 0x6c, 0x6d, 0x19, 0x13, 0x56, 0xfd, 0x00, - 0xd2, 0x1e, 0xe9, 0xf2, 0xaa, 0x61, 0xce, 0x04, 0x8f, 0x2e, 0xac, 0x79, 0x10, 0x5d, 0x08, 0x1f, 0xb9, 0xec, 0x26, - 0xc9, 0xd5, 0x78, 0xe2, 0x87, 0x83, 0x81, 0x02, 0xa0, 0xa5, 0x75, 0x52, 0x0c, 0xc2, 0x27, 0x42, 0x0e, 0xa4, 0xd1, - 0x51, 0x15, 0x60, 0xb1, 0xcc, 0xae, 0xca, 0x49, 0x36, 0x18, 0xf8, 0x20, 0x36, 0x26, 0x76, 0x43, 0xb3, 0xb9, 0xcf, - 0x4e, 0x14, 0x64, 0xb5, 0x39, 0x6a, 0xcd, 0x74, 0x0b, 0x0c, 0x00, 0x06, 0x11, 0xc1, 0x72, 0x9f, 0x1a, 0xf9, 0x88, - 0x3a, 0x3d, 0x85, 0x11, 0x10, 0xfc, 0x72, 0x22, 0x10, 0xb9, 0x48, 0xa0, 0x1e, 0x60, 0x26, 0xc0, 0x8c, 0x2a, 0x86, - 0x97, 0xc0, 0x2e, 0x9e, 0x9b, 0x57, 0x0c, 0xfa, 0x17, 0x89, 0xd9, 0x89, 0xa6, 0x12, 0x47, 0x63, 0xe4, 0x54, 0x1a, - 0x23, 0x03, 0x62, 0x17, 0xc7, 0xbf, 0xa7, 0xf4, 0x28, 0x48, 0xd9, 0x8b, 0xca, 0x10, 0x87, 0xa3, 0xf8, 0x0a, 0x56, - 0x8d, 0xc3, 0xa1, 0x36, 0xaf, 0xa7, 0xb3, 0x7a, 0x3e, 0x10, 0x01, 0xfc, 0x37, 0x14, 0xec, 0x57, 0x4d, 0x45, 0x6e, - 0x90, 0x3a, 0x0f, 0x87, 0x14, 0xe4, 0x53, 0xdd, 0xe4, 0x9f, 0x2a, 0x77, 0x3f, 0x9d, 0xcd, 0xad, 0x39, 0x7a, 0x51, - 0xe3, 0xba, 0xb5, 0xba, 0xa1, 0x90, 0x68, 0x4d, 0x93, 0xe2, 0xaa, 0x9a, 0x14, 0x03, 0x9e, 0xfb, 0x42, 0x75, 0xb1, - 0x35, 0x82, 0x85, 0x3f, 0xb7, 0x40, 0x98, 0xf4, 0xb7, 0x92, 0x0e, 0xa9, 0x1a, 0x77, 0x6d, 0xb5, 0xdb, 0x56, 0x36, - 0xa4, 0x68, 0x3e, 0xbc, 0x84, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0x7a, 0x23, 0xf2, 0x98, - 0x7e, 0x85, 0xfc, 0x52, 0x0c, 0xff, 0x53, 0xba, 0x37, 0xa7, 0x36, 0xc8, 0x01, 0x6c, 0xf7, 0x1e, 0x6e, 0xc7, 0xe8, - 0x81, 0x0c, 0xde, 0x08, 0x39, 0xe7, 0xfc, 0x72, 0x6a, 0xcd, 0x98, 0x68, 0x58, 0xb0, 0x72, 0x18, 0xf9, 0x01, 0x32, - 0x5e, 0x4e, 0x81, 0x95, 0xfd, 0xa8, 0x88, 0x4b, 0x7f, 0x18, 0xf9, 0x17, 0x4f, 0x83, 0x8c, 0x7b, 0xd1, 0xb0, 0xe3, - 0x0b, 0xb0, 0x57, 0x5f, 0x3c, 0x65, 0xd1, 0x80, 0x57, 0x57, 0xf5, 0x34, 0x0b, 0x86, 0x19, 0x8b, 0xae, 0x8a, 0x21, - 0xf8, 0xd0, 0x3e, 0x2b, 0x07, 0xa1, 0xef, 0x9b, 0x9d, 0x43, 0x77, 0x43, 0x2c, 0x8f, 0xb0, 0x9f, 0xc0, 0x6d, 0x57, - 0x4b, 0xcc, 0x60, 0xb2, 0x59, 0x46, 0xcc, 0x60, 0xcb, 0x5f, 0x3c, 0x35, 0x5c, 0x42, 0xd5, 0x33, 0xa9, 0xd9, 0x28, - 0xd0, 0x9c, 0x5c, 0xa1, 0x39, 0x59, 0x09, 0xb5, 0xe4, 0x93, 0x0a, 0x27, 0xec, 0x7c, 0x92, 0x2b, 0xbb, 0xd1, 0x18, - 0x03, 0x17, 0xad, 0xb9, 0x1d, 0x0a, 0x23, 0x33, 0x9d, 0xa5, 0x68, 0xc0, 0xc2, 0x33, 0x71, 0x4a, 0x63, 0x40, 0xfb, - 0x72, 0x60, 0x69, 0x43, 0x7e, 0x91, 0x33, 0x03, 0x6d, 0x43, 0x4a, 0xa3, 0x66, 0xe0, 0xcf, 0xd4, 0x84, 0xf9, 0x0d, - 0xac, 0x44, 0x10, 0xd5, 0x05, 0x98, 0x24, 0x39, 0x19, 0x8d, 0x94, 0x95, 0x48, 0xce, 0x01, 0xef, 0x23, 0x78, 0xb2, - 0x88, 0x6d, 0xed, 0x4f, 0xe9, 0x7f, 0x75, 0xf8, 0x5c, 0xfa, 0x4f, 0x04, 0xb0, 0x90, 0x4b, 0x83, 0xc8, 0x40, 0xe1, - 0x90, 0x5a, 0x86, 0xf7, 0xc4, 0xf1, 0x0c, 0x7c, 0x05, 0x17, 0x68, 0x0a, 0xe8, 0x0f, 0x6a, 0x46, 0x11, 0x59, 0xf8, - 0xab, 0x67, 0x37, 0x75, 0xa1, 0xe7, 0x99, 0xf3, 0x1a, 0x34, 0x33, 0x10, 0xd2, 0xe3, 0x54, 0xbd, 0x0d, 0x89, 0xce, - 0xcb, 0x6b, 0xfd, 0x32, 0x21, 0x92, 0x95, 0x91, 0xa7, 0xef, 0x73, 0x30, 0x8f, 0x28, 0x42, 0x07, 0x57, 0xe6, 0xe1, - 0x70, 0x2e, 0x28, 0x7c, 0x47, 0x79, 0x3e, 0xe0, 0x34, 0xcb, 0x12, 0xd0, 0x06, 0xb2, 0xdc, 0x94, 0xb9, 0x4c, 0x5a, - 0xa6, 0xee, 0x3d, 0x58, 0x09, 0x2a, 0x74, 0x73, 0x0a, 0x0a, 0x65, 0x24, 0x28, 0xa5, 0xd5, 0x20, 0x94, 0xea, 0xb0, - 0x08, 0x22, 0x87, 0x2c, 0x04, 0xdc, 0x4c, 0x45, 0xa3, 0x25, 0x0d, 0x8f, 0x70, 0x6e, 0xa0, 0x10, 0x80, 0xc4, 0x9e, - 0x2a, 0xca, 0xb8, 0x1c, 0x02, 0x3e, 0x4a, 0x38, 0xc4, 0x59, 0x93, 0xb6, 0x3c, 0x07, 0x71, 0x2c, 0x17, 0x7c, 0x59, - 0x21, 0x18, 0x44, 0xe8, 0x33, 0xe4, 0x4f, 0x96, 0xf3, 0xef, 0xd6, 0x61, 0xda, 0x11, 0x3e, 0xec, 0x6a, 0x37, 0x5c, - 0xcc, 0x6e, 0xe7, 0x13, 0x88, 0x6f, 0xb9, 0x9d, 0x1f, 0x63, 0x88, 0xdc, 0xf8, 0x83, 0xe5, 0x50, 0x72, 0x45, 0xa1, - 0xcb, 0x7a, 0x44, 0x8a, 0xec, 0xe9, 0x9a, 0x23, 0x08, 0x0e, 0xb4, 0x6a, 0x90, 0xa1, 0x91, 0xf8, 0xe2, 0x29, 0x64, - 0x0d, 0xd6, 0xfc, 0x45, 0x45, 0xce, 0xea, 0xfe, 0x64, 0x03, 0xd5, 0x24, 0x93, 0xb5, 0xa2, 0x72, 0xfe, 0x76, 0x55, - 0x16, 0x27, 0xab, 0x32, 0x5c, 0x0d, 0xba, 0xaa, 0xb2, 0xe0, 0x48, 0x6d, 0x80, 0xd6, 0x74, 0x85, 0x18, 0x0a, 0x59, - 0x83, 0x85, 0x55, 0x95, 0x35, 0xf5, 0x09, 0x04, 0xfa, 0x00, 0xcb, 0xa8, 0xd9, 0x4f, 0x87, 0xbf, 0x04, 0xbf, 0xa8, - 0x90, 0xa5, 0x3a, 0xad, 0x33, 0xf1, 0x5b, 0xb0, 0x60, 0xf8, 0xc7, 0xef, 0xc1, 0x1a, 0xb0, 0x04, 0xc8, 0x72, 0xb7, - 0xb1, 0xd1, 0x7a, 0xe5, 0x15, 0xe2, 0x5d, 0xad, 0x2f, 0xfa, 0xad, 0xdb, 0x44, 0xad, 0x00, 0x23, 0x14, 0x5a, 0x04, - 0xd8, 0xea, 0x81, 0x7b, 0x0a, 0x7e, 0x20, 0x86, 0x73, 0x4d, 0x5a, 0x53, 0x27, 0xbc, 0xce, 0xc6, 0x91, 0x88, 0xea, - 0x2d, 0x5c, 0xdc, 0xeb, 0xad, 0xc5, 0xdf, 0xa8, 0x40, 0x00, 0x64, 0x31, 0xc5, 0xda, 0x79, 0x43, 0x7a, 0x65, 0xd8, - 0x49, 0xe8, 0xbd, 0x61, 0x27, 0x90, 0x17, 0x87, 0x9d, 0x42, 0x97, 0x68, 0x3b, 0x45, 0x6a, 0xa2, 0xed, 0xa4, 0x9b, - 0x55, 0x58, 0x42, 0xf0, 0xab, 0xf6, 0xd6, 0x51, 0xb6, 0x2f, 0xb2, 0x84, 0x69, 0x0b, 0x18, 0xe5, 0x56, 0x7d, 0xe6, - 0x14, 0xb1, 0x52, 0xf6, 0x4e, 0x27, 0x55, 0xee, 0x22, 0x9f, 0x5b, 0x4d, 0x91, 0xc9, 0x2f, 0x8e, 0x5b, 0x24, 0x9f, - 0xbc, 0x69, 0x37, 0x4c, 0xa6, 0x7f, 0x3c, 0xfa, 0x02, 0xba, 0x22, 0x3b, 0x7d, 0x02, 0x01, 0x99, 0x0a, 0xaa, 0xd5, - 0xad, 0x62, 0x9a, 0xb7, 0xab, 0xec, 0xf6, 0x42, 0x89, 0xe1, 0x74, 0x76, 0x12, 0x1e, 0x6d, 0x86, 0x0c, 0x1c, 0x82, - 0x40, 0x21, 0x54, 0x14, 0xc3, 0x23, 0x50, 0x6b, 0x24, 0x1f, 0xe0, 0x47, 0xbb, 0x53, 0x41, 0xa4, 0x76, 0x53, 0x71, - 0xe3, 0xe4, 0xa6, 0xeb, 0xa5, 0x40, 0xad, 0x53, 0xb2, 0x02, 0x28, 0x21, 0xea, 0xcf, 0x62, 0x5b, 0x5f, 0xc3, 0x15, - 0x9b, 0xef, 0x1b, 0x45, 0x4f, 0xae, 0x4f, 0x51, 0xb7, 0xe2, 0xea, 0x34, 0x6d, 0x35, 0xc7, 0x8e, 0x33, 0xe4, 0xe0, - 0x59, 0x41, 0xb0, 0x1d, 0x95, 0x28, 0xdf, 0xb6, 0x9b, 0x8e, 0x89, 0xad, 0xfe, 0xb9, 0xa9, 0x36, 0x4b, 0xa8, 0x88, - 0x88, 0x8f, 0xb2, 0x9b, 0x27, 0xed, 0x77, 0xb0, 0xc7, 0x5a, 0x0d, 0x22, 0xfb, 0x0c, 0xae, 0x72, 0x9d, 0x16, 0xb9, - 0x2d, 0x83, 0xf3, 0x0f, 0xaf, 0x76, 0x15, 0x36, 0x39, 0xd6, 0xd5, 0xd5, 0x4c, 0x75, 0x52, 0xb1, 0x81, 0xb1, 0xa6, - 0xb5, 0x54, 0xf3, 0x18, 0x92, 0xee, 0xca, 0xe2, 0xac, 0x4a, 0xba, 0xe9, 0xb9, 0x71, 0xa6, 0x10, 0x03, 0x67, 0xab, - 0xd1, 0x72, 0x86, 0x21, 0xba, 0x3e, 0xcc, 0x12, 0xbf, 0xd5, 0x53, 0xee, 0xf3, 0x70, 0xeb, 0x77, 0xf5, 0x82, 0x93, - 0xc9, 0x7e, 0x72, 0x9c, 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x29, 0xea, 0x5f, 0x2a, - 0x00, 0x1a, 0xdc, 0xe4, 0xb1, 0x44, 0xa9, 0xdf, 0xab, 0xea, 0x07, 0x35, 0x53, 0x35, 0x0d, 0x04, 0x73, 0x2a, 0x05, - 0xfc, 0xe1, 0x76, 0xe1, 0x8a, 0x47, 0xdc, 0xb0, 0x30, 0xfe, 0xe5, 0xd5, 0xec, 0x54, 0x50, 0x19, 0xb8, 0x19, 0xff, - 0xe5, 0x09, 0x76, 0x0a, 0x6b, 0x05, 0x64, 0x85, 0xbf, 0xbc, 0xfc, 0x81, 0xf7, 0x2b, 0xfe, 0x97, 0x57, 0x3d, 0xf0, - 0x3e, 0xe2, 0xbc, 0xfc, 0x85, 0xa4, 0x4e, 0x88, 0xea, 0xf2, 0x17, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x25, 0x29, 0x7c, - 0x82, 0x2f, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, - 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, - 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, 0xb7, 0x61, 0x1d, 0x25, 0x69, 0xbe, 0x94, 0xd1, 0x47, 0x32, - 0xec, 0x48, 0x5f, 0x49, 0x89, 0xf6, 0x5a, 0x85, 0xe5, 0x68, 0xf6, 0xeb, 0x92, 0x03, 0xe5, 0x75, 0x2b, 0x28, 0x5f, - 0x35, 0x01, 0xf4, 0x4a, 0xb5, 0xcf, 0x40, 0x2b, 0x28, 0x2c, 0x95, 0x07, 0x2b, 0x71, 0x2e, 0xfa, 0xac, 0x38, 0x1c, - 0xd4, 0xc5, 0x90, 0x50, 0xa0, 0x4a, 0x9c, 0x84, 0x46, 0x3c, 0x87, 0x0b, 0xa1, 0x78, 0x96, 0x63, 0x6c, 0x45, 0x0e, - 0x1c, 0xc8, 0xf0, 0x03, 0x02, 0xef, 0x65, 0xff, 0x0a, 0x06, 0xc3, 0x04, 0x37, 0x32, 0xea, 0xe4, 0x9c, 0xfd, 0x85, - 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, - 0x9d, 0xf4, 0xcf, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, - 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, - 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, - 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, - 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, - 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, 0x28, 0x07, 0xfb, 0x97, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, - 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, 0x71, 0x50, 0xb1, 0x65, 0x19, 0x46, 0xc0, 0xa0, 0x8e, 0xfd, - 0x8f, 0x3e, 0x9b, 0x36, 0x64, 0x1f, 0x00, 0x2a, 0x57, 0x21, 0x60, 0x0f, 0xc0, 0x89, 0x46, 0xb8, 0x01, 0x6e, 0x35, - 0x5a, 0xd2, 0x41, 0xdd, 0x16, 0x0c, 0x44, 0x4b, 0xd8, 0xc8, 0xdb, 0xae, 0x4e, 0xdf, 0x10, 0x3e, 0xd4, 0x4e, 0x4a, - 0x87, 0xf2, 0x37, 0xcf, 0xd9, 0x7f, 0xef, 0xb0, 0xa6, 0xa6, 0x7c, 0x02, 0xcc, 0x9c, 0x95, 0xc8, 0x2b, 0x84, 0x4e, - 0x91, 0xdf, 0xab, 0xba, 0x12, 0xc3, 0x45, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, - 0xc8, 0x49, 0xaa, 0xcd, 0x47, 0xd6, 0x0a, 0x4a, 0xd4, 0x35, 0x0a, 0x1c, 0x9f, 0x72, 0xed, 0xfe, 0xdf, 0x39, 0x13, - 0xd4, 0x6c, 0xa3, 0xba, 0xbf, 0xd4, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, - 0x9c, 0x2c, 0x45, 0xa0, 0x97, 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x72, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x8b, - 0x4d, 0x9a, 0xc5, 0x72, 0x35, 0xdb, 0xc3, 0x44, 0x59, 0xac, 0x87, 0x08, 0x72, 0x66, 0xea, 0x60, 0xbf, 0xa7, 0x19, - 0xcd, 0xc2, 0x2b, 0x53, 0x82, 0x4b, 0x71, 0x15, 0x15, 0x39, 0xf8, 0x1c, 0xe2, 0x0b, 0x9f, 0x0b, 0xb9, 0x41, 0x44, - 0xd3, 0x9f, 0x24, 0xaa, 0x1d, 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, - 0x6b, 0x85, 0xe0, 0xfe, 0xc6, 0x16, 0x1b, 0x55, 0x9e, 0xe8, 0xc1, 0xa7, 0x58, 0xff, 0x93, 0x05, 0x94, 0xea, 0xbe, - 0x0d, 0x4e, 0xc5, 0xa3, 0x70, 0x53, 0x17, 0x9f, 0x10, 0x5a, 0xa0, 0x1c, 0x55, 0xc5, 0xa6, 0x8c, 0x88, 0x13, 0x76, - 0x53, 0x17, 0x3d, 0xcd, 0x81, 0x2e, 0xe7, 0x75, 0x22, 0x4f, 0x84, 0x76, 0x0b, 0xba, 0xa7, 0x39, 0x56, 0xe2, 0xb9, - 0x2c, 0x1d, 0x64, 0x9d, 0x48, 0x13, 0x2a, 0x77, 0x75, 0xd5, 0x51, 0xa9, 0xd4, 0x0d, 0xaf, 0x52, 0xcd, 0xf8, 0xbb, - 0x30, 0x7f, 0x62, 0xd9, 0xaf, 0x5a, 0xbf, 0xd5, 0x6a, 0x6f, 0xac, 0x1e, 0x95, 0xac, 0x39, 0xce, 0x26, 0x24, 0xa5, - 0x4f, 0xd8, 0x6e, 0x26, 0x5d, 0xeb, 0xc0, 0x93, 0xe0, 0x72, 0xe8, 0x09, 0xa8, 0x18, 0x34, 0xf1, 0x76, 0x17, 0xa8, - 0x47, 0xe0, 0x19, 0x28, 0x9f, 0xa8, 0x75, 0xc0, 0xcf, 0x6b, 0x2d, 0x4f, 0x19, 0x61, 0x58, 0xed, 0x2c, 0x5a, 0x0e, - 0xce, 0x3b, 0x45, 0xe0, 0xda, 0x95, 0xc0, 0xf3, 0xa1, 0x7a, 0x2f, 0x04, 0x0c, 0xf7, 0xcf, 0x85, 0xca, 0x66, 0x37, - 0xc3, 0x79, 0xd4, 0x38, 0x3d, 0xd0, 0xde, 0x76, 0xad, 0x87, 0x7a, 0xd7, 0xed, 0xdc, 0x56, 0xba, 0xf7, 0x6b, 0x27, - 0x93, 0x2e, 0xa0, 0xb5, 0xf9, 0xec, 0x3b, 0xbb, 0xd2, 0xba, 0xe9, 0x39, 0x7b, 0xb0, 0x75, 0x4b, 0x74, 0x2e, 0x88, - 0x26, 0xbf, 0x1f, 0x78, 0xd6, 0xb6, 0xa3, 0xdf, 0xa6, 0x1d, 0xdb, 0xdc, 0x43, 0xdd, 0x2b, 0xa8, 0xf5, 0x86, 0xe6, - 0xfd, 0x33, 0xd7, 0xb6, 0xe3, 0xab, 0x5f, 0xd7, 0x1d, 0xae, 0xf3, 0x26, 0x38, 0x6e, 0xba, 0xb6, 0xd5, 0xce, 0x7e, - 0xee, 0xee, 0xad, 0x9b, 0x28, 0xcc, 0xb2, 0x9f, 0x8a, 0xe2, 0xcf, 0x4a, 0xdf, 0x11, 0xe8, 0xe8, 0xce, 0x8b, 0x3a, - 0x5d, 0xec, 0x3e, 0x10, 0xc6, 0x93, 0x57, 0x1f, 0x11, 0xdd, 0xfa, 0x3e, 0x73, 0xbf, 0x02, 0xdc, 0x08, 0xee, 0x20, - 0xda, 0xbb, 0xa5, 0x3e, 0xa9, 0xd5, 0xd7, 0x7a, 0xed, 0x3c, 0x3d, 0xbf, 0xe9, 0xdc, 0x7e, 0xf7, 0xcd, 0xd1, 0xd6, - 0x7b, 0x5c, 0x58, 0x2b, 0x4b, 0x4f, 0x55, 0xc1, 0xde, 0x2c, 0x4f, 0x55, 0xc1, 0xe4, 0x81, 0xd7, 0xec, 0x17, 0x34, - 0xb8, 0xd2, 0xd1, 0xc6, 0x7b, 0xa2, 0x06, 0x6e, 0x51, 0x58, 0x3a, 0xfc, 0x92, 0x9b, 0xc9, 0x35, 0xee, 0x2f, 0x15, - 0xb9, 0xd8, 0x77, 0xce, 0xe8, 0xce, 0xcc, 0xba, 0x57, 0x15, 0xae, 0x16, 0xe4, 0xea, 0xc0, 0xd6, 0xb2, 0x8b, 0xc3, - 0x0d, 0x8b, 0x28, 0x40, 0x20, 0xa6, 0x57, 0x6a, 0xed, 0x8f, 0x68, 0x10, 0xf2, 0xc1, 0xc0, 0x2f, 0x30, 0x58, 0x15, - 0x28, 0x7c, 0xa0, 0x48, 0xfe, 0xd2, 0x13, 0xb0, 0x8b, 0x67, 0x80, 0x6e, 0xc5, 0x66, 0xc5, 0x08, 0x11, 0x32, 0x59, - 0xce, 0x6a, 0x3a, 0x83, 0x7c, 0xea, 0x8b, 0xef, 0x6c, 0xd5, 0xe9, 0xbc, 0xad, 0xa9, 0x72, 0xea, 0x50, 0xe8, 0xee, - 0xa6, 0xee, 0xdc, 0xba, 0xc8, 0x53, 0x87, 0x90, 0x2b, 0x15, 0x2b, 0x31, 0x0d, 0x35, 0x4f, 0xd2, 0x8c, 0xfa, 0xab, - 0xbd, 0xdf, 0x6b, 0x14, 0x4e, 0xf9, 0xd3, 0x31, 0xa8, 0xc2, 0x55, 0x0d, 0x71, 0x2c, 0x55, 0xf1, 0xc8, 0x06, 0x81, - 0xe6, 0xd5, 0xad, 0x4a, 0x9a, 0x90, 0xc9, 0x8d, 0xf0, 0xa9, 0x49, 0x29, 0x4f, 0xd3, 0x26, 0xad, 0x14, 0xa9, 0x83, - 0x0f, 0xea, 0x54, 0xe3, 0xb9, 0x59, 0x3d, 0x03, 0x30, 0xe3, 0xfc, 0x8a, 0x5f, 0x2a, 0x2e, 0xa3, 0xb6, 0x32, 0x93, - 0xf6, 0x27, 0x47, 0x63, 0xa3, 0x2e, 0xa7, 0x8d, 0x32, 0xc2, 0x4a, 0x69, 0x4e, 0x8a, 0xe5, 0x78, 0xfe, 0x01, 0x83, - 0x35, 0x4f, 0x60, 0x07, 0x13, 0x95, 0xf2, 0x3e, 0x02, 0xe2, 0xeb, 0x24, 0x5d, 0x26, 0x90, 0x22, 0xfd, 0x4b, 0x17, - 0x3c, 0x75, 0x18, 0x1b, 0x88, 0x31, 0x2b, 0x66, 0x46, 0xff, 0x83, 0xbb, 0xa4, 0x3f, 0x09, 0x01, 0x70, 0x13, 0x4d, - 0xa1, 0x53, 0xe7, 0xc9, 0x45, 0x1e, 0x2c, 0x2e, 0x3c, 0xb4, 0x62, 0xc4, 0x83, 0xff, 0x7c, 0x16, 0x22, 0x88, 0x39, - 0xa6, 0x78, 0xfa, 0x85, 0xd1, 0x7f, 0x04, 0x97, 0x18, 0x41, 0xe8, 0xee, 0x9d, 0xc3, 0x10, 0x6e, 0xf6, 0x20, 0x83, - 0xfa, 0x43, 0x1d, 0x12, 0x35, 0xfc, 0xa5, 0xf2, 0xa0, 0xff, 0xeb, 0x4c, 0x58, 0x6a, 0x3f, 0x3d, 0x1d, 0x40, 0x05, - 0xef, 0x2b, 0xde, 0x46, 0xc4, 0xf7, 0x89, 0x9f, 0xc4, 0x83, 0xcd, 0x93, 0x0d, 0x58, 0xeb, 0x3e, 0xe4, 0xc6, 0xba, - 0x4a, 0xd8, 0x40, 0xc0, 0xd7, 0x98, 0xd6, 0x9e, 0xd7, 0x6e, 0xf7, 0xe0, 0x3f, 0xfd, 0x8b, 0x90, 0x01, 0x13, 0xa7, - 0xef, 0x33, 0x27, 0x6b, 0x74, 0x91, 0xc9, 0xf4, 0xa1, 0x93, 0xbe, 0xd1, 0xe9, 0xbe, 0x13, 0xfe, 0x51, 0x31, 0x8b, - 0x0f, 0xb7, 0xf4, 0x95, 0x26, 0xc5, 0x1d, 0xb0, 0xb2, 0x79, 0x50, 0x10, 0xea, 0x5c, 0x44, 0xdf, 0x98, 0xf2, 0x2d, - 0xa1, 0x66, 0xdf, 0x58, 0x52, 0x4a, 0xf7, 0x1a, 0x7a, 0x95, 0xd6, 0xfa, 0x6d, 0x94, 0x60, 0x4c, 0x74, 0x3c, 0x79, - 0x19, 0x8f, 0x95, 0xf7, 0xf1, 0xb8, 0x91, 0x0a, 0x79, 0x00, 0x22, 0x50, 0x31, 0xfe, 0x74, 0xe5, 0xc9, 0x49, 0x2f, - 0x8c, 0x57, 0xa1, 0x14, 0x14, 0x06, 0x74, 0x05, 0x52, 0xc0, 0xa3, 0xf6, 0x44, 0x67, 0x61, 0x97, 0x70, 0x8f, 0x6e, - 0x02, 0xc6, 0xfa, 0xfc, 0x0b, 0xa0, 0xb9, 0x0b, 0x77, 0x78, 0x31, 0x40, 0x6d, 0xea, 0xd5, 0xdd, 0xc7, 0xb5, 0x3a, - 0x87, 0x43, 0x70, 0xb0, 0x1a, 0x44, 0x70, 0x3a, 0x9f, 0x3a, 0x9a, 0x65, 0x01, 0x2a, 0x27, 0xcb, 0x8d, 0xbc, 0x79, - 0xb4, 0xe8, 0xd5, 0x7d, 0x6f, 0x91, 0x96, 0x55, 0x1d, 0x64, 0x2c, 0x0b, 0x2b, 0xc0, 0xd5, 0xa1, 0xf5, 0x83, 0x70, - 0x59, 0x38, 0x7f, 0x20, 0x04, 0xb1, 0x7b, 0xb5, 0x2d, 0x78, 0xae, 0xe6, 0xf0, 0x93, 0xa7, 0x6c, 0xcd, 0x25, 0xea, - 0xa4, 0x33, 0x11, 0x80, 0xd8, 0x53, 0xb3, 0x8a, 0xae, 0x81, 0xa4, 0x4e, 0xb3, 0x8a, 0xae, 0xa9, 0xd9, 0xc6, 0x38, - 0x90, 0x8f, 0x56, 0x29, 0x60, 0xdf, 0x4d, 0xc7, 0xc1, 0xea, 0x49, 0x2c, 0xaf, 0x43, 0xcb, 0x27, 0x1b, 0xe5, 0x33, - 0xa8, 0x5b, 0x6d, 0x8c, 0x89, 0xed, 0xe6, 0xcb, 0xb9, 0x7e, 0x3b, 0x58, 0xf8, 0x76, 0xd0, 0x9c, 0x53, 0xf6, 0x52, - 0x97, 0xbd, 0xb2, 0xcb, 0xa6, 0x9e, 0x3b, 0x2a, 0x5a, 0x8d, 0x01, 0xbd, 0x81, 0x05, 0xeb, 0x73, 0x91, 0x66, 0xab, - 0x52, 0x95, 0x80, 0x17, 0xc6, 0x8a, 0x2d, 0xfd, 0x46, 0x66, 0x48, 0xc2, 0x3c, 0xce, 0xc4, 0x5b, 0xba, 0xd7, 0xc2, - 0xe4, 0x38, 0x16, 0xc9, 0x94, 0xd0, 0x29, 0xdd, 0xd9, 0x86, 0xce, 0x55, 0x18, 0x45, 0xb4, 0x56, 0x52, 0x69, 0x24, - 0x30, 0x35, 0x03, 0x94, 0xcc, 0x15, 0x38, 0xa5, 0xcb, 0xfd, 0xef, 0x48, 0x8c, 0x33, 0x5f, 0x94, 0xcc, 0x80, 0x6e, - 0xf9, 0x75, 0xb1, 0x6e, 0xa5, 0xc8, 0x08, 0xf3, 0xe6, 0xb8, 0xbd, 0xae, 0x0f, 0x81, 0x5c, 0x2d, 0x7b, 0x14, 0x8d, - 0x83, 0x42, 0x87, 0x4b, 0x95, 0x00, 0xfb, 0x22, 0xf1, 0x33, 0xc2, 0x96, 0xf6, 0x40, 0x6e, 0x8f, 0xce, 0x84, 0x39, - 0xe7, 0xa4, 0x2c, 0x3b, 0x97, 0x66, 0x70, 0x39, 0x71, 0x25, 0xb8, 0x48, 0x6f, 0xdb, 0xd3, 0xa4, 0xa5, 0xed, 0x63, - 0xc3, 0x39, 0x1a, 0xda, 0x06, 0xdd, 0xb1, 0x3f, 0x34, 0x17, 0x8b, 0xd8, 0xba, 0x58, 0x0c, 0x3b, 0xb3, 0x1f, 0x2d, - 0x16, 0x20, 0x07, 0x80, 0xa3, 0x6e, 0xc3, 0xc7, 0x6c, 0x01, 0x9c, 0x56, 0xd3, 0x6c, 0xea, 0x6d, 0x78, 0xf5, 0x44, - 0xf5, 0xf4, 0x82, 0xe7, 0x4f, 0x84, 0x19, 0x8b, 0x0d, 0xcf, 0x9f, 0x58, 0x47, 0x4e, 0xf5, 0x44, 0x28, 0xd1, 0xba, - 0x80, 0x66, 0xe0, 0x35, 0x05, 0x8c, 0x58, 0x32, 0x99, 0x52, 0x45, 0x1e, 0xf7, 0xa6, 0x1b, 0x35, 0x78, 0x41, 0xe1, - 0x10, 0x48, 0xe9, 0xf4, 0x8b, 0xa7, 0x4c, 0xbf, 0x77, 0xf1, 0xb4, 0x43, 0xd6, 0x36, 0x4c, 0x97, 0x9b, 0x61, 0x32, - 0x28, 0xfd, 0x27, 0x66, 0x62, 0x5c, 0x58, 0x93, 0x04, 0x10, 0xff, 0xc6, 0x7e, 0x87, 0x14, 0x6e, 0xde, 0x5f, 0x0c, - 0xe3, 0x07, 0xde, 0x8f, 0x91, 0x3d, 0x49, 0x33, 0xc4, 0x9a, 0x49, 0x85, 0xdc, 0x7d, 0xb5, 0xfe, 0x31, 0xb1, 0x9b, - 0xec, 0x81, 0x05, 0x20, 0xb6, 0xa6, 0xad, 0x6e, 0x79, 0xbf, 0xef, 0x99, 0x22, 0xc0, 0x0f, 0xca, 0x3f, 0xba, 0x33, - 0x24, 0x83, 0xb2, 0xeb, 0x86, 0x10, 0x0f, 0xca, 0xa6, 0x69, 0xaf, 0xb7, 0xbd, 0x33, 0x8f, 0xd5, 0x75, 0xda, 0x59, - 0x5c, 0x2d, 0x32, 0x48, 0xab, 0x0f, 0xd9, 0x71, 0x66, 0x9f, 0x1d, 0x2d, 0x95, 0xee, 0xf7, 0x21, 0x22, 0xee, 0x28, - 0x6b, 0xfb, 0xed, 0x16, 0x5c, 0xc3, 0xd1, 0x20, 0x74, 0x65, 0x6f, 0x97, 0xd1, 0xc6, 0x85, 0x38, 0xee, 0x99, 0xce, - 0x17, 0x7c, 0x79, 0x94, 0x76, 0x1e, 0x9c, 0xea, 0x89, 0x3e, 0x37, 0xdd, 0x55, 0x26, 0xd7, 0x3a, 0xac, 0xc6, 0xa0, - 0x36, 0x0b, 0x5b, 0xb8, 0x0b, 0xdb, 0xe8, 0xa0, 0xb5, 0x2f, 0x0b, 0xfe, 0x29, 0x03, 0xf0, 0xa5, 0x67, 0xcb, 0xb6, - 0xd7, 0xa4, 0xd5, 0x2b, 0x19, 0x85, 0xd8, 0xd2, 0xf6, 0xea, 0xd3, 0x51, 0x3e, 0x6e, 0x4e, 0x28, 0x2e, 0xe4, 0x28, - 0x3f, 0x78, 0x0d, 0x51, 0xd7, 0xba, 0x8e, 0x8b, 0x45, 0x87, 0x1b, 0x57, 0xdd, 0x76, 0xe3, 0x7a, 0x8d, 0x78, 0x6b, - 0xb4, 0x49, 0xa1, 0x56, 0xc6, 0x8e, 0xe0, 0x65, 0xf9, 0x70, 0xc8, 0xc4, 0x70, 0x28, 0x21, 0x53, 0x1f, 0xba, 0x37, - 0x34, 0xed, 0xf3, 0xd3, 0xd6, 0x8f, 0x58, 0x6a, 0x1c, 0xc5, 0x86, 0x77, 0xfa, 0xce, 0x63, 0x6b, 0x5c, 0xc9, 0x97, - 0xc1, 0x6c, 0x57, 0x50, 0x6d, 0x8d, 0x37, 0xec, 0xe5, 0xfc, 0xa7, 0x4a, 0x2a, 0xf9, 0xdb, 0x9f, 0xe1, 0x1a, 0xde, - 0xda, 0xd2, 0x41, 0x53, 0xcd, 0x72, 0x96, 0xeb, 0x7b, 0xc1, 0xf1, 0xc7, 0xdd, 0x2b, 0x82, 0xc1, 0xef, 0xe9, 0x28, - 0xc8, 0xc5, 0x52, 0xad, 0x01, 0x05, 0xe9, 0xc8, 0x8e, 0xa9, 0x2c, 0x30, 0x0c, 0xe0, 0x0d, 0x19, 0x20, 0x8f, 0x29, - 0xdc, 0x0d, 0x15, 0x5e, 0xf8, 0x6b, 0x45, 0x76, 0x09, 0x6c, 0x6b, 0xc6, 0xc7, 0x0c, 0x77, 0x10, 0xf2, 0x8f, 0x60, - 0x4b, 0xb6, 0x62, 0xb7, 0xec, 0x86, 0x21, 0xd9, 0x38, 0x0e, 0x63, 0xcc, 0xc7, 0x93, 0xf8, 0x4a, 0x4c, 0xe2, 0x01, - 0x8f, 0xd0, 0x31, 0x62, 0xcd, 0xeb, 0x59, 0x2c, 0x07, 0x90, 0x2d, 0xb9, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, - 0x55, 0x61, 0x70, 0xb1, 0x63, 0x9f, 0x91, 0x48, 0xc6, 0x21, 0x58, 0xb4, 0xaa, 0x81, 0x85, 0x89, 0xdd, 0xf2, 0x62, - 0xb6, 0x9a, 0xe3, 0x3f, 0x87, 0x03, 0x02, 0x60, 0x07, 0xfb, 0x86, 0x2d, 0x23, 0x44, 0x7a, 0xbb, 0xe1, 0x4b, 0xcb, - 0xd3, 0x85, 0xdd, 0xf1, 0x6b, 0x3e, 0x66, 0xe7, 0xaf, 0x3d, 0x88, 0x9c, 0x3d, 0xff, 0x08, 0x68, 0x88, 0x77, 0xfc, - 0x36, 0xf5, 0x2a, 0x76, 0x4b, 0x14, 0x84, 0xb7, 0xe0, 0x0c, 0x74, 0x07, 0x11, 0xb0, 0xd7, 0xfc, 0x06, 0x63, 0xc5, - 0xce, 0xd2, 0x85, 0x87, 0x19, 0xa1, 0xf6, 0x74, 0xbe, 0xac, 0xd5, 0x24, 0xdc, 0x5c, 0x2d, 0x26, 0x83, 0xc1, 0xc6, - 0xdf, 0xf1, 0x35, 0xf0, 0xc1, 0x9c, 0xbf, 0xf6, 0x76, 0x54, 0x2e, 0xfc, 0xe7, 0x75, 0x96, 0xbc, 0xf3, 0xd9, 0xf5, - 0x80, 0xdf, 0x00, 0xde, 0x12, 0x3a, 0x70, 0xdd, 0xf9, 0x4c, 0xe2, 0xb5, 0x5d, 0xeb, 0x6b, 0x04, 0x12, 0xf9, 0x02, - 0x30, 0x62, 0x62, 0x7e, 0x5f, 0x43, 0x04, 0x46, 0x0c, 0xbe, 0xad, 0xda, 0x23, 0x7e, 0xcb, 0x0d, 0xe0, 0x57, 0xe6, - 0xb3, 0x7b, 0x1e, 0xea, 0x9f, 0x89, 0xcf, 0xde, 0xf2, 0xf7, 0xfc, 0x99, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, - 0xd7, 0x43, 0x29, 0x4f, 0x87, 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xbe, 0xf5, 0x80, 0x35, 0x29, 0xc4, 0xbf, - 0x80, 0x6f, 0x47, 0x09, 0x9b, 0x6f, 0xbd, 0xad, 0xaf, 0xe5, 0xcd, 0xb7, 0xde, 0xbd, 0x4f, 0x51, 0x80, 0x55, 0x50, - 0xca, 0x02, 0xab, 0x20, 0x6c, 0xb4, 0x11, 0xc6, 0xc0, 0xd5, 0xbb, 0xc6, 0x50, 0xd7, 0x73, 0xc4, 0xb6, 0x95, 0xbe, - 0x0b, 0xdf, 0x41, 0x06, 0x7c, 0xf0, 0xaa, 0x28, 0x89, 0x3e, 0xa7, 0xa6, 0x48, 0x5a, 0xf7, 0xdc, 0x6f, 0xad, 0x3b, - 0x5a, 0x53, 0xea, 0x23, 0x57, 0xe3, 0xc3, 0xa1, 0x7e, 0x26, 0xb4, 0x48, 0x30, 0x05, 0x8d, 0x6b, 0xd0, 0x16, 0x20, - 0xe8, 0xf3, 0x00, 0x59, 0x4b, 0x8a, 0x05, 0xdf, 0xfe, 0x0a, 0x31, 0x78, 0x65, 0x7a, 0xe7, 0x72, 0x95, 0x91, 0xb0, - 0xbd, 0xf0, 0xcb, 0x61, 0xed, 0x4f, 0x9c, 0x5a, 0x58, 0x5a, 0xcd, 0x41, 0xfd, 0xc4, 0x96, 0xe3, 0x54, 0xd5, 0xfe, - 0x2e, 0x49, 0xaa, 0x5d, 0xa5, 0xe5, 0xf4, 0xce, 0xbe, 0xe9, 0x32, 0xc1, 0xc6, 0x7e, 0x40, 0xd5, 0x91, 0xd5, 0xb0, - 0xfb, 0x42, 0x7d, 0xd1, 0x53, 0x32, 0xa1, 0xf9, 0xa8, 0xa2, 0x79, 0x76, 0xbf, 0xd9, 0x51, 0xff, 0xe9, 0xe5, 0x50, - 0x04, 0x48, 0x56, 0x69, 0xb1, 0x14, 0x39, 0x1b, 0xfb, 0xf1, 0x30, 0xc9, 0x54, 0x78, 0x41, 0x3a, 0xba, 0xfb, 0x8d, - 0xfb, 0x5b, 0x6e, 0x20, 0x2b, 0xb4, 0x6a, 0x83, 0xb1, 0x52, 0xb4, 0x0c, 0xd6, 0x57, 0xe3, 0x7e, 0x5f, 0x5c, 0x8d, - 0xa7, 0x22, 0xa8, 0x81, 0xb8, 0x48, 0x3c, 0x1b, 0x4f, 0x6b, 0x62, 0x49, 0xed, 0x0a, 0x8c, 0xd1, 0xe3, 0xaa, 0xa8, - 0x7d, 0xea, 0x67, 0x10, 0x8a, 0x54, 0x6b, 0xe6, 0x58, 0xe3, 0xc6, 0x88, 0xb8, 0xc3, 0xca, 0xb5, 0x53, 0x7b, 0x1d, - 0x80, 0xe5, 0xd5, 0xb8, 0x20, 0x2c, 0x92, 0x63, 0xe7, 0x02, 0x56, 0xa3, 0x21, 0xd5, 0x6e, 0xb8, 0xf5, 0xb2, 0xf3, - 0x9b, 0x6f, 0x12, 0x5b, 0x1b, 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, - 0x23, 0x4e, 0x5c, 0xc0, 0x72, 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0x54, 0xad, 0x74, 0xb8, 0x93, 0x09, 0xc4, - 0xfd, 0xea, 0xbe, 0xee, 0x95, 0xe0, 0x27, 0x21, 0xaf, 0xdf, 0xf2, 0x0e, 0x00, 0x2b, 0x3e, 0xe4, 0xc5, 0xb4, 0x70, - 0xb4, 0x2e, 0x83, 0x32, 0x40, 0x84, 0x66, 0x00, 0x74, 0x72, 0x75, 0x10, 0xa5, 0x81, 0x2b, 0xee, 0x10, 0xe1, 0xa7, - 0xd1, 0x93, 0xfc, 0x59, 0xf8, 0xa4, 0x9a, 0x86, 0x17, 0x79, 0x10, 0x5d, 0x54, 0x41, 0xf4, 0xa4, 0xba, 0x0a, 0x9f, - 0xe4, 0xd3, 0xe8, 0x22, 0x0f, 0xc2, 0x8b, 0xaa, 0xb1, 0xef, 0xda, 0xdd, 0x3d, 0x21, 0x6f, 0xbb, 0xfa, 0x23, 0xe7, - 0xca, 0x9e, 0x32, 0x3d, 0x3f, 0xaf, 0xf5, 0x4a, 0xed, 0x36, 0xd7, 0x6b, 0xd4, 0x4c, 0x7d, 0x94, 0xfd, 0xcd, 0x36, - 0x16, 0x1e, 0xcd, 0x21, 0xf4, 0x19, 0x69, 0x31, 0xf7, 0x38, 0xd7, 0x9b, 0x3d, 0x29, 0x0c, 0x8c, 0x98, 0x54, 0x32, - 0x72, 0x7a, 0x81, 0x8b, 0x50, 0x85, 0x18, 0xd6, 0xd2, 0xd5, 0x3e, 0xeb, 0xd2, 0x1b, 0xa8, 0x6b, 0x8a, 0x7d, 0x0d, - 0x19, 0x78, 0xd1, 0xf4, 0x32, 0x18, 0x03, 0x72, 0x04, 0xde, 0xf1, 0xd9, 0x02, 0x0e, 0xcc, 0x35, 0x40, 0xdf, 0x3c, - 0xe8, 0xeb, 0xb2, 0xe4, 0x6b, 0xd5, 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0x7c, 0x79, 0xf1, 0x94, 0xdd, 0x72, - 0x8d, 0x8a, 0xf2, 0x42, 0x2f, 0xd6, 0x3b, 0xe0, 0xaa, 0x7b, 0x01, 0xb7, 0x59, 0x3c, 0x76, 0xe5, 0x01, 0xcb, 0xb6, - 0xec, 0x9e, 0xbd, 0x65, 0xef, 0xd9, 0x07, 0xf6, 0x99, 0x7d, 0x65, 0x35, 0x42, 0x94, 0x97, 0x4a, 0xca, 0xf3, 0x6f, - 0xf8, 0xad, 0xb4, 0x3d, 0x4a, 0x58, 0xb2, 0x7b, 0xdb, 0x4e, 0x33, 0xdc, 0xb0, 0xf7, 0xfc, 0x66, 0xb8, 0x62, 0x9f, - 0x21, 0x1b, 0x0a, 0xc5, 0x83, 0x15, 0xab, 0xe1, 0x0a, 0x4b, 0x19, 0xf4, 0x69, 0x58, 0x5a, 0xc2, 0xa2, 0x29, 0x14, - 0xa5, 0xe8, 0xcf, 0xbc, 0x26, 0xec, 0xb4, 0x1a, 0x0b, 0x91, 0x1f, 0x1a, 0xae, 0xd8, 0x3d, 0xbf, 0x19, 0xac, 0xd8, - 0x7b, 0x6d, 0x23, 0x1a, 0x6c, 0xdc, 0xe2, 0x08, 0xcc, 0x4a, 0x17, 0x26, 0x05, 0xea, 0xad, 0x7d, 0x13, 0xdc, 0xb0, - 0xb7, 0x58, 0xbf, 0x0f, 0x58, 0x34, 0xca, 0xfc, 0x83, 0x15, 0xfb, 0xca, 0x25, 0x86, 0x9a, 0x5b, 0x9e, 0x74, 0x0c, - 0xd5, 0x05, 0xd2, 0x15, 0xe1, 0x03, 0xa7, 0x17, 0xd9, 0x57, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb1, 0x2d, 0xd6, 0xee, - 0xad, 0x31, 0x6e, 0x59, 0xd5, 0x93, 0xa0, 0xc0, 0x28, 0xab, 0x94, 0x96, 0x8b, 0x23, 0x96, 0x4d, 0x1d, 0x35, 0xa8, - 0x0d, 0x03, 0xfa, 0x60, 0xf4, 0x1f, 0xbe, 0x7e, 0xf7, 0x91, 0x57, 0xea, 0x9b, 0xef, 0x0b, 0xc7, 0xbb, 0xb2, 0x44, - 0xef, 0xca, 0xdf, 0x78, 0x39, 0x7b, 0x31, 0x9f, 0xe8, 0x5a, 0xd2, 0x26, 0x43, 0xee, 0xa6, 0xb3, 0x17, 0x1d, 0xfe, - 0x96, 0xbf, 0xf9, 0x7e, 0x63, 0xf5, 0xb1, 0xfa, 0xae, 0xee, 0xde, 0xfb, 0xc1, 0xa6, 0x71, 0x2a, 0xbe, 0x3b, 0x5d, - 0x71, 0x6c, 0x67, 0xad, 0xbd, 0x33, 0xff, 0x87, 0x6b, 0xbd, 0xc5, 0xb1, 0x7b, 0xcb, 0xb7, 0xc3, 0x8d, 0x3d, 0x0c, - 0xf2, 0xfb, 0xca, 0x2f, 0xbf, 0xe6, 0xcf, 0xbd, 0x4e, 0x49, 0x16, 0x50, 0x8d, 0xde, 0x18, 0x69, 0xe8, 0x92, 0x99, - 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, - 0x8d, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, 0xd8, 0x4b, 0xf2, 0x85, 0xcf, 0xde, 0x09, 0x77, 0x95, - 0xbe, 0xf0, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, - 0x11, 0xfc, 0x1d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0xbf, 0xd4, 0xea, 0xe7, 0x7b, 0x19, 0x9b, 0x03, 0x6f, 0x42, - 0x2b, 0xe8, 0xcd, 0xdb, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0x4d, 0x7d, 0x94, - 0x4e, 0xe5, 0x4d, 0xae, 0x79, 0x22, 0x2d, 0xcc, 0x77, 0x10, 0x0e, 0x7c, 0x6d, 0xc3, 0x14, 0xec, 0x38, 0x6e, 0x06, - 0xd7, 0x0c, 0x20, 0x24, 0xb3, 0xe9, 0x96, 0xbf, 0xe5, 0x1f, 0xf8, 0x57, 0xbe, 0x0b, 0xee, 0xf9, 0x7b, 0xfe, 0x99, - 0xd7, 0x35, 0xdf, 0xb1, 0x85, 0x84, 0x3c, 0xad, 0xb7, 0x97, 0xc1, 0x96, 0xd5, 0xbb, 0xcb, 0xe0, 0x9e, 0xd5, 0xdb, - 0xa7, 0xc1, 0x5b, 0x56, 0xef, 0x9e, 0x06, 0xef, 0xd9, 0xf6, 0x32, 0xf8, 0xc0, 0x76, 0x97, 0xc1, 0x67, 0xb6, 0x7d, - 0x1a, 0x7c, 0x65, 0xbb, 0xa7, 0x41, 0xad, 0x90, 0x1e, 0xbe, 0x0a, 0xc9, 0x74, 0xf2, 0xb5, 0x66, 0x86, 0x55, 0x37, - 0xf8, 0x22, 0xac, 0x5f, 0x54, 0xcb, 0xe0, 0x4b, 0xcd, 0x74, 0x9b, 0x03, 0x21, 0x98, 0x6e, 0x71, 0x70, 0x4b, 0x4f, - 0x4c, 0xbb, 0x82, 0x54, 0xb0, 0xae, 0x96, 0x06, 0x37, 0x75, 0xd3, 0x3a, 0x99, 0x1d, 0xef, 0xc4, 0xb8, 0xc3, 0x3b, - 0xf1, 0x86, 0x2d, 0x9a, 0x4e, 0x57, 0x9d, 0xd3, 0xe7, 0x81, 0x3e, 0x02, 0xf4, 0xde, 0x5f, 0x49, 0x0f, 0x9a, 0xa2, - 0xe1, 0xb9, 0xd2, 0x1d, 0xb7, 0xf6, 0xfb, 0xd0, 0xda, 0xef, 0x99, 0x54, 0xa4, 0x45, 0x2c, 0x2a, 0x8b, 0xaa, 0x42, - 0x3e, 0xf1, 0x20, 0xd3, 0x5a, 0xb5, 0x84, 0x91, 0x3a, 0x13, 0x30, 0xe9, 0x0b, 0x3a, 0x0c, 0x72, 0xb2, 0x2b, 0xb0, - 0x05, 0xdf, 0x0c, 0x12, 0xb6, 0xe6, 0xf1, 0x74, 0x98, 0x04, 0x0b, 0xb6, 0xe4, 0xc3, 0x6e, 0xb1, 0x60, 0xa5, 0xc2, - 0x98, 0xf4, 0xf5, 0xe9, 0x68, 0x77, 0xe7, 0xbd, 0x55, 0x1a, 0xc7, 0x99, 0x40, 0x9d, 0x5b, 0xa5, 0xb7, 0xf9, 0xad, - 0xb3, 0xab, 0xaf, 0xd5, 0x2e, 0x0f, 0x02, 0xc3, 0x6f, 0x40, 0xb4, 0x43, 0xbc, 0x77, 0x50, 0x63, 0xa4, 0x5b, 0x32, - 0xeb, 0xbe, 0xb2, 0xf7, 0xf5, 0xad, 0xd9, 0xaa, 0xff, 0xdd, 0x22, 0x68, 0x2f, 0x97, 0xbd, 0xff, 0xc6, 0xbc, 0xfa, - 0x7b, 0xc7, 0xab, 0x1b, 0x7f, 0x72, 0xcf, 0xdf, 0x60, 0x74, 0x02, 0x26, 0xb2, 0x1d, 0x7f, 0x33, 0xda, 0x36, 0x4e, - 0x79, 0x72, 0x2f, 0xff, 0xbf, 0x52, 0xa0, 0xbd, 0x9b, 0x57, 0xf6, 0xa6, 0xb8, 0xe5, 0x1d, 0x7b, 0xf9, 0xc2, 0xda, - 0x13, 0x0d, 0x42, 0xc9, 0x1b, 0xee, 0x06, 0x45, 0xc3, 0x9e, 0xf8, 0x82, 0x57, 0xb3, 0x37, 0xf3, 0xc9, 0x96, 0x1f, - 0xef, 0x88, 0x6f, 0x3a, 0x76, 0xc4, 0x17, 0xfe, 0x60, 0xd1, 0x7c, 0xab, 0x57, 0x3b, 0x77, 0x72, 0xa7, 0xd2, 0x3b, - 0x7e, 0xbc, 0x8f, 0x0f, 0xff, 0xed, 0x4a, 0xef, 0xbe, 0xbb, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, - 0x6b, 0x8d, 0xe1, 0x66, 0x46, 0xc1, 0x08, 0xd3, 0x16, 0xa6, 0x69, 0x10, 0x59, 0x8a, 0x45, 0x48, 0xd4, 0x28, 0x9d, - 0x13, 0x7d, 0x16, 0x74, 0x0a, 0xba, 0xb8, 0xd1, 0xdf, 0xf2, 0x31, 0xbb, 0x31, 0x2e, 0x9b, 0xb7, 0x57, 0x37, 0x93, - 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf1, 0x70, 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x8e, 0xd6, 0xd3, 0x44, 0x35, 0xbe, 0x78, - 0x48, 0x02, 0xbb, 0xf5, 0xfd, 0x89, 0x45, 0x04, 0x6b, 0xdf, 0x38, 0x6f, 0xfd, 0x81, 0x34, 0x4b, 0xcb, 0xad, 0xfd, - 0xfd, 0xc3, 0x1a, 0x8a, 0x5b, 0x10, 0x32, 0xde, 0xdb, 0x2a, 0x87, 0xcf, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, - 0xf0, 0xcd, 0x44, 0x9d, 0x4b, 0x9f, 0x2f, 0x9e, 0xb2, 0xdf, 0xf8, 0x1b, 0x79, 0xa6, 0xbc, 0x13, 0x72, 0xda, 0x7e, - 0x42, 0x12, 0x27, 0x3a, 0x2a, 0xbe, 0xba, 0x89, 0x04, 0x0a, 0x01, 0xbb, 0xc2, 0xd7, 0x9a, 0xdf, 0x4f, 0xca, 0xa9, - 0xb7, 0x03, 0x92, 0x57, 0x6e, 0x2b, 0xa2, 0x6f, 0x39, 0xe7, 0x37, 0xc3, 0xcb, 0xe9, 0xd7, 0x6e, 0xdf, 0x1e, 0x15, - 0xd6, 0xa6, 0x22, 0xde, 0x6e, 0x31, 0x08, 0xeb, 0x64, 0x66, 0x99, 0x4b, 0xbe, 0xf4, 0xb5, 0x36, 0x73, 0x8f, 0xe9, - 0x1d, 0x67, 0x9a, 0x21, 0xa3, 0x2f, 0x30, 0x33, 0x1d, 0x0e, 0xcb, 0x73, 0x2c, 0x8f, 0x0f, 0x3f, 0x3f, 0xf9, 0x30, - 0xf8, 0x80, 0x21, 0x5c, 0x56, 0x58, 0xc8, 0x57, 0x3e, 0xcc, 0xea, 0xd6, 0xb5, 0xe3, 0xe2, 0xe9, 0xf0, 0x05, 0xe4, - 0x0d, 0xba, 0x1e, 0x9a, 0x22, 0x5a, 0xe5, 0x77, 0x14, 0x7d, 0xa2, 0xe4, 0xa0, 0xe3, 0x09, 0xd4, 0x0e, 0xb9, 0x70, - 0xbf, 0x3e, 0xe1, 0xa0, 0xe8, 0xc0, 0x52, 0xfb, 0xfd, 0xf3, 0x37, 0x44, 0x28, 0x0d, 0xe3, 0xfd, 0x22, 0x8c, 0xfe, - 0x8c, 0xcb, 0x62, 0x0d, 0x47, 0xec, 0x00, 0x3e, 0xf7, 0x44, 0x5f, 0xc3, 0x96, 0xbe, 0xef, 0x07, 0xde, 0x96, 0xbf, - 0x65, 0x5f, 0xb9, 0x77, 0x39, 0xfc, 0xec, 0x3f, 0xf9, 0x00, 0xf2, 0x13, 0xe2, 0xa4, 0x60, 0x48, 0x6c, 0x47, 0x31, - 0x6a, 0x1d, 0x7e, 0xa9, 0x21, 0x56, 0xeb, 0x0d, 0x52, 0x77, 0x41, 0xfa, 0x07, 0x85, 0xec, 0x27, 0x04, 0x56, 0x93, - 0xf4, 0x29, 0x30, 0x89, 0x6f, 0x6b, 0x48, 0x20, 0x4d, 0x0b, 0xc4, 0xe0, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x87, 0x5f, - 0x48, 0xfe, 0xbb, 0xa9, 0xf9, 0x18, 0xfe, 0x86, 0xa1, 0x99, 0x54, 0xf7, 0x69, 0x1d, 0x25, 0x5e, 0x0d, 0xa7, 0x5e, - 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, 0x4e, 0x6e, 0x4b, 0x11, 0xfe, 0x39, 0xc1, 0x67, - 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, 0x65, 0xaf, 0x06, 0x37, 0xf5, 0x90, 0xdf, 0xd6, - 0xee, 0xfb, 0x72, 0x4e, 0xd0, 0x23, 0xfb, 0x01, 0xcd, 0xc1, 0x40, 0xcd, 0x40, 0xca, 0x10, 0xdc, 0xc2, 0xa5, 0xdf, - 0x53, 0x05, 0xf9, 0xf2, 0x7b, 0x5f, 0x84, 0x0c, 0x5c, 0xb9, 0x21, 0x4c, 0xb9, 0x54, 0x48, 0x81, 0xe3, 0xb6, 0x1e, - 0x7c, 0xd1, 0xe8, 0x24, 0x12, 0x7c, 0x4a, 0x40, 0x92, 0xb4, 0x3c, 0x90, 0x34, 0x62, 0x3a, 0x10, 0x17, 0x4a, 0xd3, - 0xac, 0xa4, 0x88, 0x43, 0xec, 0xaa, 0xd7, 0x48, 0x78, 0x16, 0xbc, 0x67, 0xb0, 0x76, 0xa4, 0x68, 0xf1, 0xd5, 0x98, - 0x8e, 0x75, 0xd8, 0xd0, 0x52, 0x16, 0xf7, 0x9b, 0xa4, 0x4e, 0x23, 0x71, 0xe5, 0x9d, 0x90, 0x3f, 0xff, 0xa9, 0x44, - 0x20, 0xbd, 0xab, 0x81, 0x18, 0x04, 0x3f, 0x40, 0xff, 0x01, 0x8b, 0x1c, 0x04, 0xa5, 0xba, 0x0c, 0xf3, 0x2a, 0xa3, - 0x02, 0x67, 0x3b, 0xb6, 0x9d, 0x33, 0x55, 0xb7, 0xe0, 0x8b, 0x30, 0x0c, 0x69, 0x67, 0xab, 0xe6, 0xe4, 0x56, 0x6f, - 0xa0, 0x9e, 0x49, 0x1c, 0xa9, 0xa5, 0x38, 0xd2, 0xd6, 0xdc, 0xa7, 0x0b, 0xaf, 0x5b, 0x5e, 0xd0, 0x70, 0x01, 0x7a, - 0x51, 0xba, 0xeb, 0x7c, 0x42, 0xa1, 0xcb, 0x6a, 0x5c, 0x0d, 0x45, 0x1d, 0xca, 0x31, 0xd6, 0xfe, 0x5c, 0xc9, 0xf3, - 0x3b, 0xb0, 0x1e, 0xa1, 0xe1, 0xab, 0x52, 0x07, 0xb1, 0xfd, 0x44, 0xef, 0x3a, 0x95, 0xfa, 0x1b, 0x00, 0x06, 0x4e, - 0x1d, 0x0f, 0xf5, 0x51, 0x3b, 0x85, 0x6c, 0xe7, 0xde, 0x12, 0xa3, 0x72, 0x25, 0x3c, 0x55, 0x5a, 0x9e, 0x52, 0x56, - 0x7d, 0x2d, 0xb8, 0x95, 0xdd, 0x67, 0x03, 0xc8, 0x68, 0x83, 0x02, 0x79, 0x46, 0x6d, 0x8d, 0x07, 0xa9, 0xa6, 0x59, - 0xe2, 0x18, 0x3e, 0x28, 0xd2, 0xac, 0x02, 0x8b, 0x97, 0xb9, 0x64, 0x0e, 0x0a, 0x96, 0xeb, 0xcd, 0x66, 0x9a, 0xa9, - 0xbe, 0xc8, 0xed, 0x8d, 0xc6, 0xcb, 0xf4, 0xdf, 0x2c, 0x19, 0xf0, 0xe8, 0xe2, 0xa9, 0x1f, 0x40, 0x9a, 0xa4, 0x78, - 0x80, 0x24, 0xd8, 0x1e, 0xec, 0x62, 0x87, 0x61, 0xab, 0x58, 0xd9, 0x93, 0xa7, 0xcb, 0x1d, 0x9a, 0x72, 0x09, 0x2e, - 0x39, 0x31, 0x97, 0x53, 0xdf, 0x97, 0xac, 0x37, 0x14, 0xa7, 0x6c, 0x9a, 0x80, 0x92, 0x40, 0xbb, 0x05, 0xff, 0x85, - 0x4f, 0x0d, 0x9d, 0x16, 0x60, 0xa9, 0xed, 0x06, 0xfc, 0x17, 0xfa, 0xc5, 0x76, 0x17, 0xf5, 0x03, 0xf3, 0x60, 0x6f, - 0x16, 0x57, 0xc6, 0x80, 0x93, 0xc4, 0x95, 0xe6, 0x91, 0xeb, 0x07, 0x45, 0x9f, 0x2e, 0x6b, 0x07, 0xce, 0x14, 0x17, - 0x56, 0xa9, 0x4d, 0xd2, 0x6b, 0xbf, 0xa5, 0x26, 0xde, 0x44, 0x49, 0x55, 0xd8, 0x0e, 0x69, 0xff, 0x92, 0x72, 0xa6, - 0x8a, 0x3b, 0x44, 0x4f, 0x76, 0x13, 0x57, 0x81, 0x17, 0x56, 0x15, 0x1b, 0xa1, 0x36, 0x23, 0xcb, 0x09, 0x9c, 0xee, - 0xb1, 0xba, 0xe0, 0x63, 0xbb, 0x9a, 0x5d, 0xb0, 0x92, 0xad, 0x99, 0x74, 0x9f, 0xb7, 0x63, 0x2e, 0xe4, 0x95, 0x5e, - 0x16, 0xad, 0x80, 0xf6, 0x20, 0x70, 0xf8, 0x85, 0xa6, 0x7b, 0xf4, 0x6c, 0xb3, 0x4d, 0x6d, 0x36, 0xb6, 0x16, 0x21, - 0x64, 0x20, 0x1a, 0xfa, 0x42, 0xce, 0x28, 0xf2, 0x55, 0x5a, 0xae, 0xd5, 0xc6, 0x2a, 0xe3, 0x05, 0x26, 0x82, 0x0c, - 0x67, 0xe1, 0x1d, 0x7a, 0x5a, 0x8f, 0x34, 0xc5, 0x24, 0x38, 0xe9, 0xe2, 0x2f, 0xc0, 0x86, 0xf2, 0x24, 0x37, 0x07, - 0xe4, 0x00, 0x2a, 0x97, 0xa2, 0x54, 0xca, 0xe0, 0x37, 0xea, 0x8e, 0x6c, 0xab, 0xfe, 0x3b, 0x0d, 0x64, 0x70, 0x07, - 0xfa, 0xb6, 0x17, 0x5a, 0x3b, 0xda, 0xb9, 0xb2, 0x35, 0x6d, 0x8b, 0x34, 0x8f, 0x91, 0xc5, 0x06, 0x90, 0x4f, 0xa4, - 0x73, 0x20, 0xf2, 0x9a, 0x68, 0xbc, 0xb3, 0x67, 0x7c, 0x3c, 0x15, 0x0f, 0xc9, 0x7b, 0x95, 0xef, 0x9b, 0x7b, 0x7d, - 0x30, 0xc6, 0xbe, 0x05, 0x65, 0xe2, 0x83, 0xd5, 0xd6, 0xba, 0xc4, 0x7a, 0xab, 0x34, 0x89, 0x6e, 0xb8, 0x82, 0x8e, - 0x23, 0x71, 0x83, 0x18, 0x1c, 0x33, 0x5e, 0x5b, 0x65, 0xe9, 0x2b, 0x2c, 0x73, 0x1d, 0xb3, 0x64, 0xc8, 0xa4, 0xce, - 0x13, 0x05, 0x4f, 0x7e, 0x9e, 0x90, 0x8c, 0x88, 0x9a, 0x6d, 0x39, 0x4a, 0xb9, 0x69, 0x01, 0x97, 0x19, 0x19, 0xc0, - 0x37, 0x69, 0x02, 0x50, 0x2e, 0x5f, 0x82, 0x54, 0x1a, 0x22, 0xb8, 0x66, 0x7b, 0xc9, 0xe8, 0xd6, 0xd1, 0x3a, 0xa8, - 0x92, 0xcc, 0x1d, 0x9c, 0xdb, 0x59, 0xa4, 0xd4, 0x9b, 0x8f, 0x30, 0xec, 0xe4, 0x43, 0x58, 0x27, 0xf8, 0x6d, 0x40, - 0x4d, 0xfa, 0x5c, 0x78, 0xd1, 0x08, 0xd0, 0xd4, 0x77, 0xaa, 0x8c, 0xcf, 0x85, 0x97, 0x8d, 0xb6, 0x2c, 0xa3, 0x14, - 0xaa, 0x0b, 0x66, 0xb7, 0xa6, 0x0b, 0x31, 0xaf, 0xaa, 0x81, 0x36, 0xc8, 0xed, 0x3a, 0x66, 0x40, 0xa3, 0xb6, 0x2b, - 0x8f, 0x2c, 0xc0, 0xad, 0x99, 0x08, 0x8c, 0x9c, 0x7f, 0x9f, 0x5f, 0xab, 0x70, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, - 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xa7, 0xf4, 0xfb, 0x69, 0x03, 0xaa, - 0x12, 0x61, 0x22, 0xee, 0xf5, 0x1b, 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x48, - 0x10, 0x59, 0x1a, 0x9b, 0x7b, 0xc9, 0x96, 0x6a, 0xa9, 0x74, 0x8c, 0x2a, 0x23, 0x6a, 0xe9, 0x6c, 0x8e, 0x15, 0x23, - 0xed, 0x1c, 0x94, 0x0c, 0xc8, 0xb4, 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x89, 0xc9, 0x08, 0x2b, 0xdb, 0xf2, 0x76, - 0x93, 0xaa, 0xe9, 0x9c, 0xdc, 0xdc, 0x2a, 0xe5, 0xe6, 0x56, 0xf0, 0xfc, 0x1b, 0xba, 0xe5, 0x92, 0x6b, 0x2f, 0xb3, - 0x69, 0xa1, 0x74, 0xcb, 0xb8, 0x06, 0x5b, 0xfb, 0x26, 0x90, 0x65, 0x3e, 0x50, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x37, - 0xc8, 0x56, 0xc4, 0xa8, 0x53, 0x16, 0x8c, 0xbf, 0xdd, 0xd1, 0x03, 0x19, 0xa8, 0xaa, 0x6a, 0xe3, 0xe0, 0xce, 0x4a, - 0x7f, 0x58, 0x5e, 0x3c, 0x65, 0x89, 0x95, 0x4e, 0x2e, 0x54, 0xa1, 0x3f, 0x08, 0xd1, 0x4d, 0x65, 0xc3, 0xc1, 0xa1, - 0x2e, 0xb6, 0x32, 0x20, 0xf4, 0x30, 0xbd, 0xb7, 0xb1, 0x92, 0xe5, 0xae, 0x29, 0x5f, 0xcc, 0x78, 0xc2, 0x71, 0xf4, - 0xe5, 0x6a, 0x11, 0xd6, 0x6a, 0x91, 0x9d, 0x00, 0x0f, 0xad, 0xd5, 0x52, 0xc8, 0xd5, 0x22, 0x9c, 0x99, 0x2e, 0xd4, - 0x4c, 0xcf, 0x40, 0x01, 0x29, 0xd4, 0x2c, 0x4f, 0x00, 0x16, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, - 0xfe, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, 0x2d, 0x77, 0xa3, 0xd3, 0x88, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0xa9, - 0xfa, 0xfd, 0xb4, 0x44, 0xac, 0x1e, 0x03, 0x23, 0x28, 0x87, 0xca, 0xd1, 0x7e, 0x59, 0x58, 0x92, 0x25, 0x61, 0x49, - 0xee, 0xd5, 0x38, 0x97, 0x96, 0x8b, 0x57, 0x49, 0x20, 0x12, 0x19, 0x2f, 0xa5, 0x09, 0x3e, 0xe1, 0xe5, 0xc8, 0x48, - 0xcd, 0x93, 0x9b, 0xd4, 0xcb, 0x59, 0xc6, 0xc6, 0x88, 0x61, 0x14, 0xfa, 0x4d, 0xd5, 0xef, 0xe7, 0xa5, 0x97, 0x53, - 0x3b, 0x3f, 0x83, 0xeb, 0xe5, 0xa9, 0xb3, 0xc8, 0x11, 0xf2, 0x6a, 0x24, 0x15, 0x96, 0xd7, 0x4a, 0x3d, 0x7d, 0x09, - 0x3e, 0xa8, 0xbb, 0x37, 0x0a, 0x80, 0xb8, 0xc8, 0xa5, 0x7f, 0x6d, 0x09, 0x97, 0xa6, 0xdc, 0xc0, 0xa0, 0x87, 0x3c, - 0x27, 0x21, 0x54, 0x82, 0x90, 0x14, 0xd6, 0x8d, 0xfb, 0xe2, 0xe9, 0xc4, 0x75, 0x67, 0xb1, 0x81, 0x09, 0x0e, 0x07, - 0x40, 0x3c, 0x98, 0x7a, 0xd1, 0x80, 0x97, 0x6a, 0xce, 0x7c, 0xf4, 0x72, 0x82, 0xc9, 0x00, 0x55, 0xc5, 0xc0, 0x29, - 0xeb, 0x89, 0x7c, 0x64, 0xdc, 0xcc, 0x7c, 0x3f, 0xc0, 0x77, 0xeb, 0x42, 0xa2, 0x3f, 0x28, 0x80, 0x82, 0x4c, 0x01, - 0x14, 0x24, 0x06, 0xa0, 0x20, 0x36, 0x00, 0x05, 0x9b, 0x86, 0x2f, 0xa5, 0x0e, 0x37, 0x02, 0xba, 0x08, 0x1f, 0x7a, - 0x16, 0x36, 0x56, 0x28, 0x9e, 0x8d, 0xd9, 0x98, 0x15, 0x6a, 0xe7, 0xc9, 0xe5, 0x54, 0xec, 0x2c, 0xc6, 0xba, 0x8a, - 0xac, 0x13, 0x2f, 0x24, 0x14, 0x39, 0xe7, 0x46, 0xa2, 0xee, 0x7e, 0xee, 0xbd, 0x24, 0x63, 0xc9, 0xbc, 0xa1, 0x51, - 0x83, 0x79, 0xd9, 0x75, 0x00, 0xd3, 0x92, 0x6f, 0x0b, 0x1a, 0x4c, 0xa7, 0xca, 0x23, 0xd2, 0x24, 0xa8, 0x9d, 0xcb, - 0xa4, 0xc8, 0x09, 0x61, 0x12, 0xf4, 0x4a, 0xf0, 0x1b, 0x89, 0xf2, 0xff, 0x4d, 0x27, 0x78, 0x80, 0x63, 0xa2, 0x55, - 0xf2, 0x15, 0x0c, 0x98, 0x39, 0x7f, 0x2e, 0x9d, 0xb2, 0x11, 0x8a, 0xb1, 0x4c, 0xe3, 0xd1, 0x57, 0x36, 0x44, 0x68, - 0xab, 0xe7, 0x68, 0x62, 0x82, 0x3a, 0xc0, 0x23, 0xfa, 0x6b, 0xf4, 0xd5, 0x50, 0xa8, 0x74, 0x35, 0x52, 0xd7, 0xec, - 0x9c, 0xf3, 0x77, 0xb5, 0xe1, 0x44, 0xc6, 0xb4, 0x29, 0xf0, 0x0d, 0x08, 0xe4, 0x1b, 0x08, 0x00, 0x57, 0x4d, 0x67, - 0xf6, 0x0a, 0xe0, 0x1c, 0x08, 0xe0, 0x71, 0xde, 0xf1, 0xf8, 0x81, 0xfe, 0x2a, 0x8e, 0x7b, 0xa7, 0x69, 0xd8, 0xfe, - 0x2b, 0x30, 0x16, 0x43, 0x39, 0x9e, 0xef, 0x14, 0x24, 0x7b, 0x94, 0xb2, 0x74, 0xd5, 0x44, 0x76, 0x28, 0xd6, 0xa7, - 0x39, 0x65, 0x2c, 0x6d, 0xcb, 0x31, 0xda, 0x78, 0xfd, 0x10, 0x8f, 0x6f, 0x6e, 0xf4, 0xe4, 0x83, 0x1e, 0xdc, 0xde, - 0x5e, 0xbf, 0xec, 0x31, 0x9b, 0x6f, 0xc5, 0xe2, 0x59, 0x11, 0x27, 0x4e, 0xeb, 0x90, 0x03, 0x1c, 0xe4, 0x24, 0x04, - 0xd2, 0x31, 0x2e, 0xb5, 0xe8, 0xa0, 0x66, 0x39, 0xaf, 0x81, 0x65, 0x16, 0x41, 0x36, 0x40, 0x54, 0xd3, 0x54, 0xac, - 0x86, 0x07, 0xa5, 0x6a, 0x4e, 0xa9, 0xd4, 0xbe, 0xe1, 0x6c, 0x75, 0xfa, 0xc4, 0xaa, 0x4d, 0xb8, 0xf5, 0x6f, 0xb5, - 0x27, 0x68, 0x2b, 0x69, 0x20, 0xd4, 0xf3, 0x65, 0xba, 0xa4, 0x28, 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, - 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, - 0xc9, 0x3f, 0x84, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, - 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, - 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, 0x9a, 0xa7, 0xd5, 0x07, 0xf5, 0xf7, 0xfb, 0x05, - 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, 0x68, 0x09, 0xe0, 0x98, 0xa5, 0x3d, 0x14, 0xb2, - 0x60, 0x82, 0x35, 0x54, 0xe5, 0x29, 0x9f, 0xbd, 0x7c, 0x72, 0x03, 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, - 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, - 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, - 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, - 0xb6, 0x02, 0xc4, 0xc0, 0x52, 0x87, 0x24, 0xab, 0x8e, 0xed, 0xf7, 0x5f, 0x8d, 0x0c, 0x6f, 0x3a, 0x22, 0xc2, 0xe8, - 0xdf, 0x15, 0x08, 0x50, 0xb0, 0xcc, 0x6c, 0x67, 0x26, 0x5d, 0xed, 0x59, 0x3d, 0x6f, 0x36, 0x79, 0x57, 0xef, 0x58, - 0x4d, 0xcb, 0xa9, 0x69, 0x95, 0xd5, 0xb4, 0x49, 0x0e, 0x35, 0x13, 0xfd, 0xbe, 0xc6, 0x47, 0xcd, 0xe7, 0x80, 0xcb, - 0x86, 0xc9, 0xaf, 0x66, 0xd5, 0xbc, 0xdf, 0xf7, 0xe4, 0x23, 0xf8, 0x85, 0xc4, 0x65, 0x6e, 0x8d, 0xe5, 0xd3, 0xd7, - 0xc4, 0x67, 0x66, 0x10, 0x8f, 0x56, 0x47, 0x50, 0x5f, 0x9f, 0x84, 0xd7, 0x31, 0x57, 0xd8, 0x4c, 0x4c, 0x5f, 0xc1, - 0xe0, 0x79, 0xc2, 0x07, 0x6f, 0x39, 0xfa, 0x1b, 0xe9, 0xcc, 0x14, 0x2c, 0xe4, 0xdc, 0x9f, 0xbc, 0x42, 0xe8, 0x64, - 0x44, 0x7a, 0xd0, 0xe9, 0x04, 0x0d, 0xd9, 0xef, 0xdf, 0x42, 0x67, 0xb6, 0x52, 0x29, 0x5b, 0x15, 0x95, 0xe9, 0xba, - 0x2e, 0xca, 0x0a, 0x3a, 0x96, 0x7e, 0xde, 0x0a, 0x99, 0x59, 0x3f, 0xb3, 0x90, 0x9f, 0x6e, 0x25, 0xd6, 0x94, 0x6d, - 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, - 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, 0xf4, 0xa5, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, - 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, 0x39, 0x79, 0x05, 0xe0, 0x74, 0x88, 0x88, 0x5b, - 0x91, 0xa0, 0x63, 0xd5, 0xf0, 0xc6, 0xc2, 0x3d, 0xed, 0xa5, 0x71, 0x2f, 0xcd, 0xcf, 0xd2, 0x7e, 0xdf, 0x00, 0x68, - 0xa6, 0x88, 0x0c, 0x8f, 0x33, 0x72, 0x97, 0xb4, 0x10, 0x4c, 0x69, 0xff, 0xd5, 0x18, 0x12, 0x04, 0x02, 0xfe, 0x0f, - 0xe1, 0x7d, 0x00, 0xb4, 0x4d, 0xda, 0x80, 0xab, 0x1e, 0xd3, 0x81, 0xd9, 0x92, 0xb3, 0x55, 0x67, 0x03, 0x50, 0x4e, - 0x95, 0xd6, 0x53, 0x1e, 0xd7, 0x14, 0x11, 0xa9, 0xb2, 0x50, 0xbf, 0xb1, 0x9e, 0x4c, 0x56, 0xb9, 0xc8, 0x90, 0xa3, - 0x32, 0xbd, 0xab, 0x19, 0x21, 0x76, 0xe9, 0xe7, 0x37, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0x80, 0xb4, 0x9d, - 0xb5, 0xab, 0x6a, 0x97, 0xe3, 0xd6, 0x6e, 0x0e, 0x48, 0xbe, 0xde, 0x68, 0x34, 0xd2, 0x7e, 0x72, 0x02, 0x86, 0xaa, - 0xa7, 0x96, 0x42, 0x8f, 0xd5, 0x0a, 0x5b, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x6b, 0xf3, 0xd1, - 0x87, 0x4b, 0x65, 0xed, 0x3a, 0xe2, 0xeb, 0x3f, 0xca, 0x6a, 0x7d, 0xcf, 0xbb, 0xaa, 0x09, 0xf8, 0xa2, 0x8a, 0x2d, - 0xfd, 0x8e, 0xf7, 0x64, 0xef, 0xe2, 0x6b, 0x9f, 0xb0, 0x4b, 0xbe, 0xe7, 0x2d, 0xea, 0x3c, 0x5f, 0xf9, 0xba, 0x51, - 0xa5, 0xdb, 0x7b, 0xc9, 0x0d, 0xae, 0xbd, 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7a, - 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, 0x1a, 0xfa, 0xd0, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, - 0x87, 0xde, 0x92, 0x93, 0x43, 0x82, 0xc1, 0xa9, 0x31, 0x7f, 0x78, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x89, 0xc9, - 0x7c, 0x7a, 0x4c, 0x3b, 0x0a, 0x30, 0xa3, 0x4a, 0x6f, 0x9f, 0x1e, 0xd8, 0x8e, 0x97, 0xf5, 0xd0, 0xd2, 0xbb, 0x27, - 0x47, 0xb7, 0xe3, 0x55, 0x35, 0xbe, 0x94, 0x43, 0x9e, 0xe7, 0xb3, 0xd1, 0x68, 0x24, 0x0c, 0x3a, 0x77, 0xa5, 0x37, - 0xb0, 0x02, 0x19, 0x5c, 0x54, 0x1f, 0xca, 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, - 0x63, 0x1c, 0x70, 0x4e, 0x0a, 0x25, 0x47, 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, - 0x1a, 0x21, 0x1f, 0x82, 0x9f, 0x3c, 0x50, 0x8b, 0x3f, 0xd3, 0x82, 0xd8, 0x43, 0x9f, 0x2a, 0xa5, 0x43, 0xbc, 0x2a, - 0x20, 0x44, 0x18, 0xf0, 0x06, 0xda, 0x41, 0x09, 0x0e, 0x3b, 0xdc, 0x23, 0x44, 0x88, 0x7e, 0xe9, 0xe5, 0x33, 0x19, - 0xae, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x88, 0x95, 0x3e, 0x03, 0x17, 0x4c, 0x40, 0x3d, 0xc5, 0xa7, 0xe8, 0x5f, 0x6f, - 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x80, 0x8a, 0xe8, 0xd9, 0xcf, 0xc7, 0x00, 0xde, 0xd9, 0xb5, 0x19, 0x69, 0x2f, 0x7f, - 0x03, 0x0c, 0x2b, 0x25, 0x89, 0x76, 0x4e, 0x89, 0xc0, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x93, - 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, 0x01, 0x8f, 0x0e, 0x40, 0xe5, 0x4a, 0x41, 0xee, 0x35, 0x47, 0x72, 0xc7, - 0x0f, 0xbd, 0x1f, 0x06, 0xf5, 0xe0, 0x87, 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0x7e, - 0x18, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, 0x8b, 0xdc, 0x6a, 0xa2, 0xc6, 0x4d, 0x78, 0x97, 0x48, 0x1a, 0xa2, 0x6d, - 0xe7, 0x11, 0x71, 0x03, 0x20, 0x59, 0x7c, 0x36, 0x6f, 0x28, 0xea, 0xdd, 0x84, 0x6f, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, - 0x75, 0x9e, 0xd6, 0x3d, 0x1d, 0x2a, 0x83, 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0x2f, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, - 0x48, 0xb9, 0x51, 0x25, 0xea, 0xb7, 0x58, 0xcd, 0x7a, 0x88, 0xc8, 0x9d, 0x65, 0xc6, 0xde, 0x5e, 0xf0, 0x4a, 0xce, - 0xaa, 0xd8, 0x2e, 0xc7, 0x57, 0x84, 0xb5, 0x95, 0x04, 0xe8, 0x68, 0x3d, 0xd6, 0xa6, 0x18, 0xf9, 0x95, 0x42, 0x02, - 0x2e, 0x3a, 0xb6, 0x16, 0x8a, 0x8d, 0x17, 0xa0, 0x2f, 0xd9, 0x99, 0x06, 0x58, 0x6f, 0xf4, 0x2a, 0xe2, 0xb6, 0x7c, - 0xa0, 0xc2, 0x9b, 0xdc, 0x54, 0x99, 0x95, 0xcd, 0x4d, 0xbb, 0x9f, 0x2a, 0x5e, 0x21, 0x6e, 0xbd, 0x51, 0x7b, 0x14, - 0xa0, 0xf6, 0xd0, 0x42, 0x19, 0xa0, 0x4b, 0xd3, 0x0c, 0x00, 0x19, 0x00, 0x64, 0xaa, 0x88, 0xcf, 0x04, 0xa8, 0xb4, - 0xd5, 0x8d, 0x02, 0x27, 0xd2, 0x4b, 0x60, 0x5c, 0x60, 0xa5, 0x8f, 0x6c, 0x64, 0xb0, 0xd8, 0x22, 0xc0, 0x2d, 0x47, - 0xfa, 0x30, 0x0d, 0x27, 0xdb, 0x68, 0x0e, 0x93, 0x34, 0xbf, 0x0b, 0xb3, 0x54, 0x42, 0x4b, 0xbc, 0x96, 0x35, 0x46, - 0x2c, 0x20, 0x7d, 0x9f, 0xbe, 0x29, 0xb2, 0x98, 0x20, 0xe1, 0xac, 0xa7, 0x0e, 0xa0, 0x9a, 0x9c, 0x6b, 0x4d, 0xab, - 0x67, 0xb5, 0xc9, 0x43, 0x16, 0xe8, 0xec, 0xc1, 0x98, 0xd4, 0x72, 0x43, 0x8f, 0xec, 0xaf, 0x1c, 0xcf, 0x08, 0xdf, - 0xf5, 0x0c, 0xa7, 0xfe, 0xfb, 0x54, 0x03, 0x29, 0x53, 0x02, 0x08, 0x32, 0x38, 0x9a, 0x10, 0xca, 0xd3, 0x31, 0x99, - 0xda, 0xfc, 0x08, 0x84, 0x23, 0x82, 0x57, 0xf0, 0xdc, 0xd0, 0xba, 0xe5, 0xc6, 0xce, 0x22, 0x4f, 0x13, 0x40, 0x16, - 0x2f, 0xf8, 0x1d, 0x20, 0x73, 0xea, 0x55, 0x21, 0x7b, 0xf6, 0x5c, 0x4c, 0x67, 0xf3, 0xe0, 0xcf, 0x84, 0xf6, 0x2f, - 0x26, 0xfc, 0xa6, 0xbb, 0x4a, 0xae, 0x4c, 0xad, 0x7b, 0x13, 0x3d, 0xe6, 0x72, 0xa7, 0x4f, 0x2b, 0x8e, 0x11, 0xcf, - 0x60, 0x15, 0x90, 0x73, 0x36, 0xe4, 0xcf, 0xce, 0x01, 0xbb, 0x65, 0x25, 0xbc, 0x88, 0x3f, 0x0b, 0x65, 0xb5, 0x00, - 0xf9, 0x91, 0xf3, 0xc8, 0xfc, 0xf2, 0xd5, 0x76, 0x28, 0xe7, 0x14, 0x45, 0xb4, 0x9c, 0x9a, 0x96, 0x14, 0xb2, 0x43, - 0x4f, 0xc1, 0x64, 0x6a, 0xcb, 0xdf, 0x77, 0x89, 0x4b, 0xf2, 0xcd, 0x24, 0xb2, 0xaf, 0x03, 0xac, 0x59, 0xab, 0xee, - 0xa1, 0x1b, 0x82, 0x01, 0x22, 0x23, 0x94, 0xd9, 0x5c, 0xdf, 0xad, 0x07, 0x03, 0x05, 0xf3, 0x2b, 0xe8, 0xa6, 0x45, - 0xa7, 0x38, 0x40, 0xce, 0x5a, 0xd7, 0xa8, 0x54, 0x15, 0x87, 0x0e, 0xf3, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, - 0x52, 0xa3, 0xae, 0x82, 0x45, 0x4a, 0x45, 0x14, 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, - 0x88, 0x41, 0x0a, 0x88, 0x53, 0x7e, 0x05, 0x68, 0xa2, 0x8b, 0x28, 0xcc, 0x5e, 0xc7, 0x55, 0x50, 0x5b, 0x4d, 0xbf, - 0x77, 0x20, 0x63, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, 0x46, 0x3f, 0x8c, 0xc2, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, - 0xe6, 0x95, 0x3f, 0xe1, 0x15, 0x5d, 0x6e, 0x6d, 0xca, 0x15, 0x8d, 0x0b, 0x7f, 0x8d, 0xe0, 0xf0, 0xa9, 0xa3, 0xd8, - 0x6e, 0x53, 0xe5, 0xd4, 0xc6, 0x60, 0x10, 0xc2, 0x7d, 0x2b, 0xe3, 0xf7, 0x89, 0x97, 0xcf, 0xa2, 0x39, 0x28, 0x4a, - 0x33, 0xcd, 0x17, 0x52, 0x48, 0x37, 0x01, 0xfa, 0x68, 0x10, 0x6a, 0x75, 0xe5, 0xa7, 0xc4, 0x4b, 0xd5, 0xb4, 0x36, - 0x4f, 0xb1, 0x46, 0x81, 0x98, 0x45, 0xf3, 0x86, 0x65, 0x74, 0x48, 0xaa, 0xcb, 0xa5, 0x69, 0xc6, 0x27, 0xab, 0x19, - 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0xf4, 0x09, 0x2e, 0x80, 0x3f, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, - 0x04, 0x31, 0x62, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x32, 0x64, 0x92, 0x90, 0xa7, 0x0f, - 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xbf, 0x72, 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0xe0, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, - 0x15, 0x9c, 0x5f, 0x12, 0xfc, 0xae, 0xfa, 0x11, 0x66, 0x19, 0x54, 0x01, 0x19, 0x7f, 0x2c, 0x14, 0xf5, 0xbc, 0xc5, - 0xec, 0x3e, 0x52, 0x17, 0x94, 0x59, 0x3a, 0xb7, 0x38, 0x41, 0xc0, 0x79, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, - 0x69, 0x46, 0x81, 0xea, 0x08, 0xf0, 0xd9, 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0x91, 0x85, 0xfa, 0x9b, 0x6f, 0xe5, 0xac, - 0x21, 0x79, 0x20, 0xd5, 0xdc, 0xc7, 0x70, 0x6a, 0xdc, 0xe0, 0x4b, 0x37, 0xbd, 0xa9, 0xe0, 0x35, 0x21, 0x73, 0xdf, - 0xa0, 0xb5, 0xef, 0x06, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, - 0x5f, 0xbb, 0xf8, 0xc5, 0x29, 0xd2, 0xb3, 0xe8, 0x02, 0x03, 0x5d, 0x90, 0x79, 0xe3, 0x9f, 0x15, 0xac, 0x5c, 0x40, - 0xef, 0xa5, 0x62, 0x25, 0x27, 0xdb, 0x4e, 0xfd, 0x51, 0x2a, 0xfb, 0xed, 0x99, 0x35, 0x81, 0xdf, 0x27, 0xf6, 0x4b, - 0x64, 0xf2, 0x4d, 0x8f, 0x4d, 0xbe, 0x32, 0x2c, 0x3a, 0xb5, 0x0c, 0xce, 0xe9, 0x91, 0xc1, 0xb9, 0xb7, 0xb3, 0x6a, - 0x13, 0xc2, 0x50, 0x90, 0x04, 0x9a, 0x2e, 0x3c, 0xac, 0x9b, 0xfe, 0xfc, 0xa4, 0x45, 0xb5, 0x55, 0xfb, 0xd6, 0xfd, - 0x38, 0xc4, 0x2e, 0x7e, 0x9f, 0x78, 0x86, 0x88, 0xd4, 0x07, 0x3a, 0x30, 0x19, 0x3c, 0x71, 0xd9, 0xef, 0x43, 0x61, - 0xb3, 0xf1, 0x7c, 0x54, 0x17, 0x6f, 0x8a, 0x7b, 0x40, 0x75, 0xa8, 0xc0, 0x2e, 0x87, 0x32, 0x94, 0x11, 0x9b, 0xda, - 0x72, 0xcf, 0x1f, 0xd7, 0x61, 0x0e, 0xf2, 0x8e, 0x86, 0xc7, 0x39, 0x03, 0x31, 0x0c, 0xbe, 0xfe, 0xc3, 0xa3, 0x7d, - 0xda, 0xfc, 0x70, 0x06, 0xdf, 0x1d, 0x9d, 0x7d, 0x40, 0xba, 0x9b, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x38, 0xfb, - 0x01, 0x52, 0x7f, 0x38, 0x2b, 0xca, 0xb3, 0x1f, 0x54, 0x65, 0x7e, 0x38, 0xa3, 0x05, 0x37, 0xfa, 0xc3, 0x9a, 0x78, - 0xbf, 0x57, 0x9a, 0x01, 0x6d, 0x01, 0x91, 0x59, 0x5a, 0xfd, 0x08, 0x4a, 0x44, 0xc5, 0x8f, 0x2a, 0xa3, 0x5a, 0xad, - 0x1d, 0xe7, 0x51, 0xa2, 0x91, 0xb2, 0x69, 0x42, 0xe2, 0x6a, 0x09, 0xeb, 0x50, 0xcf, 0x4e, 0x9b, 0x6f, 0xc7, 0x79, - 0xa0, 0x0e, 0x88, 0x9c, 0x3f, 0xcb, 0x47, 0x5b, 0xfa, 0x1a, 0x7c, 0xeb, 0x70, 0xc8, 0x47, 0x3b, 0xf3, 0xd3, 0x27, - 0x6b, 0xa5, 0x8c, 0x3b, 0x52, 0xe4, 0x42, 0xc8, 0x19, 0xb7, 0xed, 0x31, 0xe0, 0x00, 0xf0, 0x0f, 0x07, 0xfa, 0xbd, - 0x93, 0xbf, 0xd5, 0x6e, 0x69, 0xd5, 0xf3, 0x43, 0x8b, 0x3b, 0xe3, 0x75, 0x6d, 0x88, 0xda, 0xf6, 0x12, 0x5b, 0x7a, - 0xdf, 0x34, 0xa8, 0x29, 0xa2, 0x9f, 0xb0, 0x9a, 0x58, 0xc5, 0x61, 0x41, 0x4a, 0x48, 0x62, 0x38, 0x46, 0x3b, 0xf4, - 0x38, 0x5d, 0x2c, 0x3d, 0xb9, 0xef, 0xf0, 0x72, 0xeb, 0xfb, 0x80, 0xa4, 0x55, 0x38, 0x7f, 0xe4, 0x85, 0x06, 0x1e, - 0xbd, 0xc8, 0xab, 0x22, 0x13, 0x23, 0x41, 0xa3, 0xfc, 0x9a, 0xc4, 0x99, 0x33, 0xac, 0xc5, 0x99, 0x02, 0x0b, 0x0b, - 0x09, 0xdd, 0xbb, 0x28, 0x29, 0x3d, 0x38, 0x7b, 0xb4, 0x2f, 0x9b, 0x3f, 0x08, 0x1e, 0x62, 0x74, 0x03, 0x8c, 0x38, - 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0x5e, 0xe6, 0x05, 0x84, 0x68, 0x9e, 0x49, 0xc5, 0x6a, 0x79, - 0x06, 0x8c, 0x79, 0x22, 0x3e, 0x0b, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xf5, 0x36, 0x9e, 0x7b, 0x40, 0xf1, 0xfd, - 0x28, 0x01, 0x2e, 0x77, 0x9f, 0xbd, 0x52, 0xae, 0xa9, 0xa4, 0x47, 0x9e, 0x43, 0xb4, 0xe4, 0x75, 0x02, 0x14, 0xcf, - 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, - 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, - 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0xad, 0xcc, 0xbd, 0x10, 0x86, 0x2a, 0xe1, 0xde, 0xeb, 0x7a, 0x16, 0xca, 0x4d, 0xd1, - 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, 0xdf, 0x26, 0x5e, 0x0c, 0x86, 0xeb, 0x05, 0x2f, - 0x67, 0x1b, 0xb3, 0x10, 0x0e, 0x87, 0xcd, 0xa4, 0x98, 0x2d, 0x20, 0xcc, 0x75, 0x31, 0x3f, 0x1c, 0xba, 0x5a, 0xb6, - 0x16, 0x1e, 0x3c, 0x54, 0x2d, 0xdc, 0x34, 0x2c, 0x87, 0x9f, 0xc9, 0x2c, 0xc6, 0xf6, 0x35, 0x3e, 0xb3, 0x3f, 0x5f, - 0x74, 0xcf, 0x12, 0x24, 0xdf, 0x58, 0x03, 0xed, 0xd8, 0xac, 0xdd, 0xe1, 0x6a, 0x04, 0x24, 0xa5, 0xbb, 0xd1, 0xdf, - 0x95, 0x9d, 0x3c, 0x25, 0xc8, 0x1d, 0xad, 0xc0, 0x7e, 0xf7, 0x8d, 0x3f, 0xd1, 0x62, 0x0f, 0xda, 0x6d, 0x6c, 0x09, - 0x51, 0x4d, 0x7b, 0x2e, 0x57, 0x8a, 0xa5, 0x79, 0x2b, 0x6d, 0xf4, 0x7c, 0x58, 0x9f, 0xfb, 0x46, 0x0e, 0x14, 0x8c, - 0x11, 0x4f, 0xad, 0x83, 0x68, 0x36, 0x07, 0x1a, 0x0c, 0x34, 0x8f, 0xf0, 0xd4, 0x42, 0x07, 0x65, 0xd6, 0x86, 0xfd, - 0x3c, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, 0x31, 0xc5, 0xf6, 0xf8, 0x57, 0xa5, 0xa8, 0xf0, - 0xd8, 0x8e, 0xb8, 0xd6, 0x3e, 0x89, 0xda, 0x50, 0x39, 0xfc, 0x4b, 0xd8, 0x47, 0xd8, 0x5f, 0x68, 0x82, 0x30, 0xd8, - 0xf5, 0x67, 0x02, 0x21, 0x62, 0x21, 0x5e, 0xf0, 0xaf, 0x4a, 0x52, 0xd1, 0x09, 0x9f, 0xed, 0x4a, 0xe0, 0xad, 0xc3, - 0x80, 0x3e, 0x21, 0x3f, 0x13, 0x09, 0x43, 0x33, 0xa1, 0x77, 0xf4, 0xdf, 0x89, 0x9d, 0x6c, 0x92, 0x5b, 0x21, 0x1f, - 0x48, 0x2a, 0x09, 0x26, 0x58, 0x79, 0xa1, 0xfc, 0xd1, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x3c, 0xf1, - 0x0c, 0xfe, 0x1e, 0xc8, 0x18, 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x67, 0xeb, - 0x2c, 0xac, 0x17, 0x45, 0xb9, 0x6a, 0x45, 0x8a, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x22, 0x1f, - 0x3c, 0x02, 0x60, 0x3c, 0xca, 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x27, 0xca, 0x80, 0x47, 0x58, - 0x06, 0xe6, 0x69, 0x97, 0xa1, 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0x4e, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, - 0x31, 0x34, 0x75, 0xe5, 0x91, 0xf5, 0x92, 0x13, 0xf6, 0x64, 0x37, 0x90, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0x5d, 0xcb, - 0x12, 0xe5, 0xa2, 0x5b, 0x46, 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0xb4, 0x6f, 0x8f, - 0x14, 0xbd, 0x60, 0xd0, 0x3e, 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, - 0x7c, 0x07, 0x33, 0xe3, 0x6c, 0xf6, 0x87, 0xde, 0xdc, 0x1e, 0xed, 0xeb, 0xe6, 0x0f, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, - 0x13, 0x9f, 0x2b, 0x16, 0x2a, 0xab, 0x10, 0x2b, 0x48, 0xfb, 0x5f, 0xc2, 0xfb, 0x03, 0xde, 0x1a, 0xa1, 0x59, 0x19, - 0x0f, 0xf3, 0xd1, 0xa3, 0xbd, 0x68, 0xfe, 0xe8, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0x7f, 0x1c, 0x25, 0xcd, 0xd9, - 0xc3, 0x35, 0x92, 0x3a, 0xc0, 0x87, 0xeb, 0x33, 0x7c, 0xa0, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0x1f, - 0xad, 0xe7, 0xf4, 0xf1, 0x63, 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xbc, 0x19, - 0xd2, 0xbb, 0x6e, 0x95, 0xd4, 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, - 0x9b, 0xd5, 0x9c, 0x00, 0x11, 0x01, 0xad, 0x55, 0xde, 0x07, 0x8e, 0xf9, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x73, - 0xa5, 0xbd, 0x92, 0x02, 0xfa, 0x39, 0xc8, 0xdc, 0x3e, 0xba, 0xe5, 0xaa, 0x65, 0x9e, 0x4b, 0x5b, 0x0e, 0x58, 0xb4, - 0x10, 0xa8, 0xd9, 0xb9, 0x74, 0x38, 0x50, 0x10, 0xea, 0x4a, 0x54, 0x11, 0x57, 0x47, 0xd1, 0x42, 0xd4, 0x6a, 0xd5, - 0x2e, 0x27, 0x9b, 0x0a, 0xd9, 0x92, 0x08, 0x32, 0x4a, 0x31, 0x74, 0xe9, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0x03, 0x34, - 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0xc0, 0x69, 0x0e, 0x31, 0x7f, 0x7e, - 0xd7, 0x83, 0x0a, 0x1e, 0x74, 0xa4, 0xbf, 0xae, 0x67, 0x05, 0x9e, 0xb9, 0x27, 0x9e, 0xbf, 0x3a, 0x91, 0x5e, 0xe4, - 0xf0, 0x40, 0xd3, 0x20, 0x66, 0xfc, 0x79, 0x59, 0x86, 0xbb, 0xd1, 0xa2, 0x2c, 0x56, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, - 0x8a, 0x81, 0xc4, 0x8c, 0x99, 0xd1, 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, - 0xeb, 0x02, 0xb0, 0x1c, 0xb2, 0x06, 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0xb2, 0xa3, 0xb8, 0x01, 0xf4, 0xb3, - 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, 0x9d, 0x4c, 0xa6, 0x48, 0x2e, 0xdf, 0x86, 0xbd, 0x62, 0x45, 0x3e, 0x6f, 0xe4, - 0xf6, 0xf0, 0x2e, 0x5c, 0x89, 0x58, 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0xfb, 0x47, 0x55, - 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, 0xdb, 0xab, 0x6d, 0x25, 0x28, 0x81, 0x0f, 0xf6, 0x43, 0x29, 0x16, 0xe9, 0x56, - 0x00, 0xae, 0x03, 0xff, 0x4d, 0x22, 0x12, 0xba, 0x3b, 0x0f, 0x51, 0xac, 0x91, 0xf7, 0x0d, 0xa2, 0xb1, 0xbf, 0x04, - 0x39, 0x0d, 0xc8, 0x44, 0x8a, 0x91, 0x2c, 0x18, 0xf8, 0x00, 0x72, 0xbe, 0x06, 0x93, 0xdc, 0x34, 0xf7, 0xfc, 0x20, - 0xd7, 0x1d, 0x4c, 0xfb, 0xa0, 0x7b, 0x71, 0xad, 0x59, 0x0e, 0x5e, 0x31, 0x11, 0xff, 0xb9, 0xf6, 0x4a, 0x96, 0xb3, - 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, - 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, - 0x41, 0xe8, 0xe7, 0x1a, 0x90, 0x36, 0x98, 0xa4, 0x49, 0xa8, 0x7c, 0x70, 0x41, 0x37, 0xcc, 0xcb, 0x95, 0xcb, 0x55, - 0x93, 0xaa, 0xe5, 0x97, 0x23, 0xea, 0xbb, 0x5a, 0x72, 0xa9, 0x36, 0x9f, 0x1a, 0x65, 0x8d, 0x20, 0x93, 0xa3, 0xf4, - 0xfb, 0x94, 0x0b, 0xb7, 0x32, 0x26, 0xeb, 0xc3, 0xc1, 0x2b, 0xb8, 0xa9, 0xf1, 0xeb, 0x9c, 0x08, 0x45, 0xed, 0x21, - 0x11, 0xb6, 0x76, 0x2b, 0x74, 0xef, 0x71, 0xa3, 0x34, 0x8f, 0xb2, 0x4d, 0x2c, 0x2a, 0xaf, 0x97, 0x80, 0xb5, 0xb8, - 0x07, 0xbc, 0xa8, 0xb4, 0xf4, 0x2b, 0x56, 0x00, 0x7a, 0x80, 0x14, 0x36, 0x5e, 0x23, 0x03, 0xd6, 0x23, 0x2f, 0xf5, - 0xfb, 0x7d, 0x63, 0xca, 0x7f, 0x7f, 0x9f, 0x03, 0x49, 0xa1, 0x28, 0xeb, 0x1d, 0x4c, 0x20, 0xb8, 0x76, 0x92, 0xf6, - 0xac, 0xe6, 0xcf, 0xd6, 0xb5, 0x07, 0xfc, 0x56, 0xbe, 0x45, 0x62, 0xf5, 0xd2, 0xbe, 0xd8, 0xec, 0xd3, 0xea, 0x93, - 0xd1, 0x38, 0x08, 0x96, 0x56, 0xaf, 0xb5, 0xca, 0x21, 0x6f, 0x78, 0x01, 0x22, 0x95, 0x75, 0x75, 0xad, 0x9c, 0xab, - 0x6b, 0xc1, 0x91, 0x4b, 0xb6, 0xe4, 0x39, 0xfc, 0x17, 0x72, 0xaf, 0x3c, 0x1c, 0x0a, 0xbf, 0xdf, 0x4f, 0x67, 0xa4, - 0x95, 0x05, 0xf6, 0xb4, 0x75, 0xed, 0x85, 0xfe, 0xe1, 0xf0, 0x1a, 0xbc, 0x46, 0xfc, 0xc3, 0xa1, 0xec, 0xf7, 0x3f, - 0x9a, 0x9b, 0xcc, 0xf9, 0x58, 0x29, 0x65, 0x2f, 0x51, 0xe9, 0xfe, 0x39, 0xe1, 0xbd, 0xff, 0x3d, 0xfa, 0xdf, 0xa3, - 0xcb, 0x9e, 0x0a, 0x01, 0x4b, 0xf8, 0x0c, 0x6f, 0xe8, 0x4c, 0x5d, 0xce, 0x99, 0x74, 0x77, 0x57, 0x7e, 0xe8, 0x3d, - 0x0d, 0x15, 0xdf, 0x9b, 0x9b, 0x36, 0xfe, 0x5c, 0x1d, 0x69, 0x12, 0x3a, 0x2e, 0xfa, 0x87, 0xc3, 0x9b, 0x44, 0xeb, - 0xd3, 0x52, 0xa5, 0x4f, 0x53, 0x38, 0x4a, 0x86, 0xdc, 0xcd, 0x2d, 0x4c, 0x07, 0xf6, 0xe3, 0xe6, 0xab, 0xe4, 0xc5, - 0x59, 0x0a, 0xd7, 0xde, 0x7c, 0x96, 0xce, 0xa7, 0x60, 0x5d, 0x19, 0xe6, 0xb3, 0x7a, 0x1e, 0x40, 0xea, 0x10, 0xd2, - 0xac, 0x69, 0xf8, 0x8f, 0xca, 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0x81, 0x8b, 0x52, 0x47, 0xfa, 0xa4, 0x8d, 0xa6, 0x4b, - 0x2a, 0xf9, 0x8f, 0x22, 0x8f, 0x31, 0x66, 0xe3, 0x25, 0xf1, 0x7e, 0x16, 0xf9, 0x75, 0x01, 0xd8, 0x45, 0x00, 0x86, - 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0x63, 0xf2, 0xfd, 0x1f, 0xd3, 0xa5, 0x7d, 0x28, 0x8b, 0x65, 0x29, 0xaa, 0xea, 0xa8, - 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, - 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0x17, 0xbb, 0xd7, 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, - 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, - 0xaf, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, - 0xfe, 0x4c, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, 0xb2, 0xbc, 0x3a, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, - 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x33, 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, - 0x9b, 0x79, 0xe2, 0x19, 0xd0, 0x31, 0x3f, 0x43, 0x57, 0xc5, 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, - 0xf1, 0xce, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, - 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, - 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xab, 0xb3, 0x07, 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, - 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, - 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, - 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, - 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, - 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xa1, 0xb6, 0x2c, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, - 0x17, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, - 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xeb, 0x97, 0x67, 0x3f, 0xf4, - 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xce, 0x56, 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, - 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, - 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, - 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x69, 0x02, 0xa1, 0x16, 0xcc, - 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, - 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, - 0xfd, 0x48, 0x05, 0xe5, 0x24, 0xf4, 0x8b, 0x42, 0xbf, 0x34, 0x1c, 0x65, 0xcc, 0xbf, 0x84, 0x9a, 0x23, 0xa0, 0xde, - 0xf2, 0x50, 0xd1, 0x05, 0xe0, 0x72, 0x8e, 0x98, 0x71, 0xde, 0xe3, 0x2e, 0x30, 0xe7, 0xff, 0xe1, 0xed, 0x4b, 0xbc, - 0xdb, 0xb6, 0xb1, 0x7e, 0xff, 0x15, 0x8b, 0x2f, 0x55, 0x89, 0x08, 0x92, 0x25, 0x27, 0xe9, 0x4c, 0x29, 0xc3, 0xfa, - 0xdc, 0x2c, 0x6d, 0x3a, 0xcd, 0xd2, 0x24, 0x5d, 0x66, 0xf4, 0xf4, 0xb9, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, - 0x29, 0x2f, 0x91, 0xf8, 0xbf, 0xbf, 0x73, 0x2f, 0x56, 0x52, 0x94, 0x93, 0x99, 0xf7, 0xbd, 0x77, 0x72, 0x4e, 0x2c, - 0x82, 0x20, 0x76, 0x5c, 0x5c, 0xdc, 0xe5, 0x77, 0x4d, 0x08, 0x0a, 0x73, 0x1d, 0x2c, 0x0c, 0x00, 0xbd, 0x6b, 0x8f, - 0xb6, 0x9c, 0x74, 0x09, 0x16, 0xcf, 0x0d, 0x2c, 0x5e, 0x5d, 0x2c, 0xaa, 0x2b, 0xae, 0xe5, 0x16, 0x36, 0xa5, 0xac, - 0x62, 0x08, 0x20, 0xd0, 0x8c, 0x19, 0x76, 0xcb, 0x5d, 0x8e, 0x64, 0x5d, 0x14, 0x5c, 0xec, 0x04, 0x86, 0x6e, 0xc6, - 0x25, 0x33, 0x07, 0x57, 0x33, 0xac, 0x93, 0x8a, 0x02, 0xec, 0xea, 0x02, 0x64, 0x2f, 0x0c, 0x75, 0xdd, 0xcc, 0x96, - 0xeb, 0xc0, 0xd7, 0xa5, 0x0b, 0x5f, 0x52, 0xf0, 0x72, 0x25, 0x45, 0x99, 0x5d, 0xf3, 0x9f, 0xec, 0xcb, 0x66, 0x2c, - 0x29, 0xb4, 0x23, 0x7d, 0xd5, 0xee, 0x8e, 0x16, 0xe3, 0xd8, 0x72, 0x7c, 0x4b, 0xa5, 0x5b, 0x3d, 0xaa, 0x5e, 0x08, - 0x6d, 0x9d, 0x6b, 0x99, 0xa5, 0x29, 0x17, 0x2f, 0x45, 0x9a, 0x25, 0x5e, 0x72, 0xac, 0x63, 0x55, 0xbb, 0x20, 0x58, - 0x2e, 0x4c, 0xf2, 0xb3, 0xac, 0xc4, 0xd8, 0xc1, 0x8d, 0x46, 0xb5, 0xa2, 0x4e, 0x99, 0x18, 0x18, 0xf2, 0x1d, 0x06, - 0xdf, 0x66, 0x32, 0x01, 0x86, 0x1f, 0x13, 0xf5, 0x25, 0x3d, 0x85, 0x80, 0x0f, 0x2a, 0x34, 0xf7, 0x33, 0x8e, 0xe0, - 0xd7, 0x56, 0x65, 0x0e, 0x4c, 0xb6, 0x56, 0x41, 0x22, 0xee, 0x5d, 0x36, 0xd7, 0x8b, 0x68, 0xa1, 0xee, 0x42, 0xbd, - 0x78, 0xbb, 0xed, 0x25, 0x8a, 0x0e, 0x38, 0xf9, 0x69, 0xf0, 0x22, 0xce, 0x72, 0x9e, 0x1e, 0x54, 0xf2, 0x40, 0x6d, - 0xa8, 0x03, 0xe5, 0xcc, 0x01, 0x3b, 0xef, 0xeb, 0xea, 0x40, 0xaf, 0xe9, 0x03, 0xdd, 0xce, 0x03, 0xb8, 0x60, 0xe0, - 0xce, 0xbd, 0xcc, 0xae, 0xb9, 0x38, 0x00, 0x65, 0xa0, 0x35, 0x1e, 0xa8, 0xcb, 0x6a, 0xa4, 0x26, 0x46, 0xc7, 0xb0, - 0x4e, 0xf4, 0xc1, 0x1c, 0xd0, 0x9f, 0x21, 0xac, 0x7d, 0xeb, 0xed, 0x4a, 0x1f, 0xb4, 0x01, 0x7d, 0xb7, 0x34, 0x7d, - 0xd0, 0x81, 0xe3, 0x55, 0x74, 0xe0, 0xc6, 0x90, 0x6a, 0xd0, 0x56, 0x23, 0xab, 0x40, 0xf1, 0x86, 0xb7, 0x78, 0x77, - 0xae, 0x25, 0x1b, 0xef, 0x25, 0x62, 0x7c, 0x65, 0xa2, 0x8a, 0x33, 0x71, 0xea, 0xa5, 0xf2, 0x5a, 0x3b, 0xc9, 0x08, - 0xe3, 0x5b, 0x56, 0x52, 0x7f, 0x87, 0x98, 0x5b, 0xa4, 0x39, 0x0c, 0x5e, 0x86, 0x15, 0x99, 0xf1, 0x7e, 0x5f, 0xce, - 0x64, 0x54, 0xce, 0xc4, 0x61, 0x19, 0x29, 0xb0, 0xb6, 0x7d, 0x22, 0xa0, 0x7b, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0xba, - 0x4f, 0xf8, 0x73, 0x9f, 0xd4, 0xa7, 0x53, 0xe8, 0x53, 0x68, 0xeb, 0x15, 0x57, 0x10, 0xaf, 0xea, 0xc6, 0xc8, 0x36, - 0x2a, 0x68, 0xf1, 0x58, 0x9e, 0xd5, 0x86, 0xb1, 0x39, 0xb5, 0xfe, 0xf5, 0x66, 0x83, 0x29, 0x9b, 0x0b, 0xb5, 0x0a, - 0x43, 0x12, 0x7d, 0x2c, 0xbd, 0x48, 0x22, 0x16, 0x36, 0xab, 0xb5, 0xf9, 0x4d, 0x18, 0x90, 0x4c, 0xa4, 0xb8, 0x9f, - 0x2d, 0x71, 0xee, 0xe2, 0xf1, 0xbc, 0xea, 0x6b, 0x2d, 0x2d, 0x32, 0x6d, 0xbe, 0xd5, 0x97, 0x21, 0x4d, 0x45, 0x0d, - 0x69, 0xd4, 0x99, 0x41, 0xf7, 0xed, 0xf2, 0x96, 0xd5, 0x08, 0x13, 0xe0, 0x95, 0xce, 0xa0, 0x1b, 0x8d, 0x07, 0x62, - 0x59, 0x8d, 0x8a, 0xb5, 0x10, 0x08, 0x3c, 0x0c, 0x39, 0x66, 0x96, 0x90, 0x64, 0x9f, 0xf8, 0x77, 0x2a, 0xce, 0x42, - 0x11, 0xdf, 0x18, 0x64, 0xef, 0xca, 0xba, 0x76, 0xd7, 0x91, 0x9f, 0x13, 0x0b, 0xab, 0xfd, 0x87, 0xe6, 0x51, 0x6b, - 0x9c, 0x05, 0xb4, 0x35, 0xad, 0x6e, 0x38, 0xdc, 0xa3, 0x3a, 0x16, 0xa5, 0xc1, 0x26, 0xf6, 0xc8, 0x72, 0xd1, 0x3a, - 0x66, 0xd0, 0x80, 0xfe, 0x36, 0xbb, 0x5a, 0x5f, 0x21, 0x80, 0x5b, 0x89, 0xac, 0x93, 0x54, 0xfe, 0x25, 0xed, 0x51, - 0xd7, 0xf6, 0x54, 0xfe, 0xb7, 0x6d, 0xaa, 0x1c, 0x5a, 0x4c, 0x79, 0xec, 0xe6, 0x2c, 0x50, 0x1d, 0x09, 0xa2, 0x40, - 0x6d, 0xbd, 0x60, 0xea, 0x9d, 0x32, 0x45, 0x07, 0x08, 0x74, 0x61, 0xce, 0xb0, 0x2f, 0x38, 0x62, 0xcc, 0x52, 0x89, - 0xc1, 0xd4, 0xc7, 0x18, 0xd5, 0xb4, 0x56, 0x80, 0xae, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0xd4, 0x68, 0xa8, 0x35, 0x92, - 0x42, 0xd1, 0x44, 0x85, 0x22, 0x4b, 0x0b, 0x1d, 0x57, 0xa1, 0x93, 0x48, 0x58, 0x02, 0x1a, 0x26, 0x44, 0x27, 0x15, - 0x78, 0x6b, 0x00, 0x67, 0x3e, 0x2e, 0xca, 0x75, 0xa1, 0x0d, 0xe6, 0x7e, 0x88, 0xaf, 0xf9, 0xcb, 0x67, 0xce, 0xa8, - 0xbe, 0x65, 0xad, 0xef, 0x69, 0x41, 0x7e, 0x08, 0x39, 0x45, 0x07, 0x26, 0x76, 0xb2, 0x41, 0x63, 0x8c, 0xb2, 0xd6, - 0x51, 0x2f, 0xde, 0xe8, 0x50, 0x2c, 0xda, 0x04, 0xef, 0x1e, 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, - 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, 0x7a, 0x24, 0xc2, 0x4e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, - 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x8c, - 0x82, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, - 0x7e, 0x18, 0xf8, 0x0e, 0x8d, 0x81, 0xad, 0x75, 0x80, 0x86, 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, - 0x67, 0x46, 0xcb, 0x99, 0x45, 0x63, 0xd0, 0xb7, 0xd1, 0x14, 0xc5, 0x39, 0xf9, 0x2c, 0x28, 0xe2, 0x34, 0x8b, 0x73, - 0xf0, 0xdb, 0x8c, 0x0b, 0xcc, 0x98, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x68, 0xbb, 0x73, 0x95, 0x5a, 0xd7, 0x20, 0x20, - 0xfb, 0x01, 0xac, 0x5e, 0x1a, 0x3a, 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x62, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, - 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, - 0x8f, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, 0x31, 0xf6, 0x8f, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, - 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, - 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, - 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, 0x58, 0x87, 0x9b, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, - 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, - 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, 0x14, 0x36, 0xc5, 0x76, 0xab, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, - 0x51, 0xfc, 0x07, 0xf7, 0xc2, 0x4e, 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x0f, 0x0e, 0x17, 0x89, 0xef, 0xa4, - 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x8e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, - 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, - 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, - 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, - 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, 0x71, 0xac, 0x89, 0x6a, 0xc1, 0xf7, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, - 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, - 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, - 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, - 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, - 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0xfb, 0x87, 0x84, 0xaa, 0xb8, 0x37, 0xbc, - 0x1d, 0xf7, 0xc6, 0x09, 0xbf, 0xe6, 0x62, 0xa1, 0x43, 0xb5, 0x98, 0x4b, 0x96, 0xdf, 0x5a, 0xef, 0x96, 0x24, 0xb5, - 0x02, 0xda, 0x67, 0x59, 0x50, 0x13, 0x01, 0x20, 0x7f, 0xf8, 0x0b, 0x84, 0xce, 0xf0, 0xb7, 0xc7, 0xe0, 0x8a, 0x14, - 0xee, 0x1d, 0x02, 0x61, 0x4d, 0x37, 0x77, 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x3d, 0xfd, 0x36, 0x93, 0xbb, - 0xba, 0x6e, 0x8f, 0x2c, 0xc3, 0x47, 0xb8, 0x52, 0x00, 0x37, 0x13, 0xfe, 0x62, 0x98, 0x49, 0xf5, 0x09, 0x60, 0xaa, - 0xe9, 0xe0, 0x3e, 0x41, 0x60, 0x00, 0x95, 0x68, 0x31, 0xba, 0x56, 0x8e, 0x68, 0x06, 0x6e, 0x4d, 0xb7, 0xc2, 0x78, - 0xeb, 0x41, 0x0b, 0x3d, 0xd3, 0x70, 0xe2, 0x3f, 0x68, 0xe6, 0x55, 0x01, 0x01, 0xb4, 0x32, 0x82, 0xb7, 0xd6, 0x47, - 0x73, 0x84, 0xf8, 0x84, 0x25, 0xd1, 0x84, 0xc5, 0x33, 0xc5, 0x8f, 0x09, 0xdd, 0x34, 0xb5, 0x4d, 0x1f, 0x90, 0xfe, - 0xe2, 0x9a, 0xf5, 0x53, 0x96, 0xb5, 0x6f, 0x0f, 0x15, 0x2f, 0xa6, 0xcd, 0x38, 0x88, 0x89, 0x2a, 0xc6, 0xff, 0x82, - 0xfb, 0x52, 0x2b, 0x40, 0x64, 0xee, 0xaa, 0xa7, 0xdf, 0x6f, 0x66, 0xcb, 0x81, 0x50, 0xf9, 0x9d, 0x41, 0xd2, 0xa7, - 0x43, 0xfb, 0x81, 0x4d, 0xa2, 0xb6, 0xd0, 0xf3, 0xc7, 0xa5, 0x6e, 0xe2, 0xe5, 0xb5, 0xa9, 0x11, 0xad, 0x90, 0xa1, - 0xb2, 0x75, 0xc0, 0xfa, 0xfe, 0x21, 0xdc, 0x5d, 0xd4, 0x34, 0xd4, 0xba, 0xe7, 0xae, 0x45, 0xc1, 0x89, 0x3f, 0xc0, - 0x58, 0x5c, 0x48, 0x6a, 0x1d, 0x8f, 0x49, 0x3f, 0x5a, 0xc8, 0xe4, 0x46, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x5c, - 0x80, 0xcb, 0xb6, 0xbf, 0xa2, 0x52, 0x97, 0x72, 0x7b, 0x45, 0x69, 0x7a, 0x48, 0xdb, 0xab, 0x38, 0x6f, 0x0b, 0x2e, - 0xf8, 0x17, 0x0a, 0x2e, 0xac, 0x83, 0x75, 0xc7, 0x9d, 0xb2, 0x27, 0x3c, 0x51, 0xa6, 0xb5, 0xc1, 0x5d, 0x37, 0x18, - 0x13, 0x63, 0xbf, 0xbb, 0xe4, 0xc9, 0x47, 0x64, 0xc1, 0xbf, 0xcb, 0x04, 0x78, 0x26, 0xbb, 0x57, 0x2a, 0xff, 0x0f, - 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xb9, 0x92, - 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0xbd, 0x04, - 0x6e, 0xba, 0xbf, 0x36, 0x33, 0x73, 0xba, 0x56, 0xa2, 0xe9, 0xd2, 0xd8, 0x5a, 0x96, 0x2a, 0x8c, 0xf7, 0xbd, 0x27, - 0xd9, 0x34, 0x3f, 0x5e, 0x4e, 0x73, 0x4b, 0xdd, 0x36, 0x6e, 0xd9, 0x00, 0x1a, 0x62, 0xd7, 0xda, 0xca, 0x01, 0x2f, - 0xb7, 0x07, 0xd1, 0x7c, 0xad, 0x08, 0x3d, 0x55, 0x22, 0xf4, 0x69, 0xda, 0xec, 0x83, 0x5d, 0x55, 0xeb, 0x46, 0xc8, - 0xa3, 0x41, 0xaa, 0x19, 0xf9, 0x37, 0xd7, 0xbc, 0xb8, 0xc8, 0xe5, 0x0d, 0xc0, 0x21, 0x93, 0xda, 0x28, 0x2c, 0xaf, - 0xc0, 0x9d, 0x1f, 0x1d, 0xc7, 0x99, 0x18, 0xe5, 0x18, 0xb7, 0x15, 0x91, 0x92, 0x75, 0xe2, 0x0c, 0xf0, 0x90, 0xfd, - 0x49, 0xd3, 0xa1, 0x5d, 0x0b, 0x0c, 0xef, 0x0b, 0xdc, 0x55, 0xce, 0x4e, 0x36, 0xb9, 0x5d, 0xf4, 0xcd, 0x19, 0xd6, - 0x1d, 0x29, 0xad, 0x8d, 0x45, 0xd7, 0x1d, 0xac, 0x35, 0x83, 0xb6, 0x08, 0x25, 0x1f, 0x72, 0x27, 0xed, 0xa7, 0x80, - 0x06, 0x67, 0x59, 0x7a, 0x6b, 0xad, 0xf2, 0x37, 0x5a, 0x88, 0x13, 0xc5, 0xd4, 0x89, 0x6f, 0xa2, 0x44, 0x9f, 0x9f, - 0x89, 0x71, 0x03, 0x81, 0xd4, 0x1f, 0x30, 0xbe, 0x46, 0x11, 0x26, 0x70, 0x1d, 0x88, 0x62, 0x7b, 0xa2, 0x36, 0x96, - 0x23, 0xe8, 0x84, 0x10, 0xef, 0xa0, 0x0c, 0x63, 0x75, 0x71, 0xa0, 0x0d, 0x96, 0xbe, 0x6e, 0xad, 0x73, 0x43, 0x28, - 0x8c, 0x13, 0x98, 0x62, 0x90, 0xd4, 0x59, 0x67, 0x99, 0xa0, 0xca, 0x8e, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, - 0x53, 0x7c, 0xdd, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x5a, 0x8b, 0xdc, 0xe0, 0xcf, 0x5b, 0x22, 0x2c, 0x02, 0x67, 0xad, - 0xc9, 0x57, 0x8d, 0x70, 0x60, 0x4a, 0x32, 0x0d, 0x7b, 0xb9, 0xb2, 0xe9, 0xde, 0x6e, 0x7b, 0xbd, 0xbd, 0x22, 0xae, - 0x1e, 0x63, 0x95, 0x77, 0x33, 0xb7, 0x77, 0xaa, 0xb5, 0xd8, 0xbd, 0x69, 0xfb, 0x29, 0x76, 0xd4, 0x5a, 0xbb, 0xdd, - 0x70, 0x42, 0x0d, 0xf9, 0x56, 0x54, 0x69, 0x75, 0xba, 0x31, 0x68, 0x87, 0xd0, 0xd6, 0x22, 0x83, 0x1b, 0xe5, 0x33, - 0x27, 0x74, 0x52, 0x21, 0x57, 0x9d, 0xba, 0x60, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0x23, 0x41, 0xd1, 0xe6, 0x3c, 0x2a, - 0x69, 0x22, 0xd7, 0xa2, 0x8a, 0x64, 0x8d, 0x7a, 0x51, 0xab, 0x31, 0x40, 0x40, 0xa6, 0xb3, 0xa6, 0x07, 0x55, 0x30, - 0x1b, 0xca, 0x48, 0x4e, 0x5f, 0x80, 0xa5, 0x3d, 0x72, 0xac, 0xf5, 0xbe, 0x3a, 0x5b, 0x7c, 0xab, 0x27, 0x04, 0x53, - 0x98, 0x3d, 0x10, 0x11, 0xae, 0x69, 0x0c, 0x39, 0xed, 0x12, 0x97, 0x35, 0xdd, 0x12, 0xf6, 0x70, 0xbb, 0x92, 0x9d, - 0xb8, 0x79, 0xd2, 0xdc, 0x5c, 0xc1, 0x4e, 0x8a, 0xf9, 0x18, 0xb4, 0x5f, 0x52, 0x5d, 0xbb, 0x34, 0xb7, 0x1e, 0x0f, - 0x02, 0x1a, 0x0c, 0x0a, 0xc3, 0xbf, 0x4e, 0x8c, 0x87, 0x27, 0x0d, 0x08, 0x92, 0x72, 0x11, 0x8e, 0x7d, 0x23, 0xfa, - 0xc9, 0x54, 0x1e, 0x73, 0xb4, 0x78, 0x87, 0x56, 0xe7, 0x10, 0xd0, 0x4b, 0x84, 0x92, 0x18, 0x55, 0xa1, 0x11, 0x41, - 0x79, 0x5a, 0xfe, 0x52, 0x55, 0x87, 0x80, 0x42, 0xda, 0x57, 0x14, 0xca, 0x36, 0x89, 0xa1, 0x19, 0x7e, 0x39, 0x9f, - 0x2c, 0xf4, 0x0c, 0x0c, 0xe4, 0xfc, 0x68, 0xa1, 0x67, 0x61, 0x20, 0xe7, 0x8f, 0x16, 0xb5, 0x5b, 0x07, 0x9a, 0x80, - 0x78, 0x2e, 0x1c, 0x9d, 0x94, 0x56, 0x65, 0x0b, 0xe8, 0xe6, 0x3e, 0x82, 0xfe, 0x0f, 0x7b, 0x08, 0x3a, 0xb9, 0xd0, - 0x8e, 0xdc, 0x80, 0xb6, 0x43, 0x12, 0xd8, 0x2b, 0x26, 0x15, 0x26, 0x16, 0xd1, 0x31, 0x1b, 0x83, 0x21, 0xb6, 0xfa, - 0xe0, 0x98, 0x8d, 0xa7, 0x3e, 0x09, 0x02, 0x46, 0xf7, 0x07, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, 0x93, 0x8d, 0x40, - 0x37, 0x7d, 0x77, 0x37, 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, 0xd5, 0x6b, 0x88, - 0x1b, 0xf2, 0x2b, 0xa3, 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, 0xea, 0xd6, 0xb3, - 0x01, 0x19, 0x66, 0x7a, 0xcb, 0x64, 0x7d, 0x0f, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, 0xf7, 0x0f, 0xbe, - 0xc9, 0xf8, 0x99, 0xc3, 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, - 0xc9, 0xe7, 0x59, 0x28, 0x6f, 0xbc, 0xa6, 0xff, 0x51, 0xe9, 0xcd, 0x0e, 0x87, 0x9c, 0xae, 0x60, 0xc5, 0xcd, 0xaa, - 0xd0, 0xf0, 0xb3, 0xc8, 0x1b, 0x47, 0xbc, 0x26, 0x51, 0xd5, 0x7d, 0xde, 0xdb, 0x88, 0xa5, 0x1d, 0xe3, 0x00, 0xe0, - 0x44, 0xad, 0x1a, 0x76, 0xa5, 0x71, 0xad, 0x0e, 0x62, 0x44, 0x4a, 0xd8, 0x2a, 0x71, 0x24, 0x94, 0xbf, 0x01, 0x08, - 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x7b, 0xd8, 0x0f, 0x5d, 0xa0, 0x69, 0x4e, 0xa9, 0x66, 0x00, 0x90, 0x04, 0xfc, - 0xd1, 0xd3, 0x4d, 0x43, 0x65, 0x9b, 0xe7, 0xa1, 0x65, 0x75, 0x05, 0xf7, 0xf4, 0xd4, 0x95, 0x0c, 0x8c, 0xab, 0x3a, - 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x55, 0xe4, 0x3b, 0x9b, 0xd4, 0x34, 0x0b, 0x20, 0x45, 0xe3, 0xd2, 0x17, 0x7a, 0x3a, - 0x01, 0x5a, 0xaf, 0x2d, 0x15, 0xed, 0xf7, 0x51, 0x8c, 0x1a, 0x17, 0x0a, 0xac, 0xc2, 0x04, 0x85, 0x43, 0x84, 0x11, - 0x42, 0x7f, 0x2e, 0xc3, 0x8d, 0x2f, 0xc8, 0x20, 0x1a, 0xae, 0x45, 0x87, 0x22, 0x72, 0xbc, 0x68, 0x5b, 0xaa, 0x6a, - 0x4e, 0x9a, 0xb6, 0x04, 0xde, 0x44, 0x06, 0x6c, 0xe7, 0x9f, 0x36, 0x44, 0xae, 0xc2, 0x05, 0x0c, 0xdf, 0x11, 0xd7, - 0x82, 0xe8, 0xa6, 0x36, 0xf5, 0x36, 0xec, 0x10, 0x1d, 0x4d, 0xf1, 0xe8, 0x90, 0x7b, 0xee, 0x9e, 0xdb, 0x22, 0xbe, - 0xf9, 0x0c, 0xb9, 0x6b, 0x3a, 0x7b, 0x29, 0xc2, 0xa0, 0x6e, 0xd9, 0x40, 0xb1, 0x8e, 0x9d, 0xa0, 0x00, 0x03, 0xb8, - 0x7c, 0x02, 0x3a, 0x36, 0x18, 0x54, 0x04, 0x9f, 0x14, 0xb6, 0x4d, 0x83, 0xfc, 0x11, 0xef, 0x86, 0x0e, 0xaf, 0x2d, - 0x79, 0x20, 0x5e, 0x61, 0x9f, 0x29, 0x61, 0xff, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, - 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, - 0x51, 0xe5, 0xb1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, - 0xb4, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x1d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, - 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, - 0x94, 0x9f, 0xb0, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x02, 0x5a, 0x67, 0x26, 0xae, - 0xf1, 0x69, 0xfb, 0x0a, 0x5a, 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, - 0xa9, 0x64, 0x9f, 0x96, 0xd6, 0x61, 0xdf, 0x2e, 0x14, 0x5a, 0x68, 0xe2, 0x57, 0x19, 0xe2, 0xa7, 0xae, 0x33, 0xff, - 0x36, 0xed, 0x53, 0x83, 0x58, 0x38, 0x12, 0x83, 0x88, 0x5f, 0x9c, 0x2a, 0xdb, 0x09, 0xa1, 0x62, 0xe3, 0xa1, 0x6b, - 0xdd, 0x38, 0x92, 0x2a, 0x0c, 0xa5, 0xd0, 0x78, 0x6a, 0xb8, 0xef, 0x85, 0x0e, 0x5f, 0x87, 0x59, 0xdc, 0x66, 0x8d, - 0xa4, 0xc6, 0x38, 0x15, 0x26, 0x4e, 0xa5, 0x5c, 0x45, 0x02, 0x03, 0xe5, 0xd9, 0xc2, 0x20, 0xc0, 0x24, 0x26, 0x19, - 0x5b, 0x0b, 0x61, 0xc2, 0xd8, 0xb9, 0xc2, 0x34, 0x75, 0x91, 0xfa, 0xcd, 0xc0, 0x64, 0x41, 0x43, 0x7e, 0x8f, 0x46, - 0x6b, 0xaa, 0xa6, 0x00, 0xc3, 0x38, 0x4a, 0x35, 0xfe, 0x2d, 0x42, 0x6d, 0x86, 0x01, 0x80, 0x6d, 0xde, 0xca, 0x4c, - 0x54, 0x2f, 0x05, 0x42, 0xa0, 0x39, 0xfb, 0xa9, 0xb8, 0xda, 0x99, 0x05, 0xa3, 0x68, 0xb7, 0x57, 0x3e, 0x1f, 0x38, - 0xa1, 0x3c, 0x55, 0x17, 0xa8, 0x17, 0xb2, 0x78, 0x25, 0x53, 0xde, 0x0a, 0x91, 0x79, 0x20, 0xd9, 0x4f, 0xf9, 0x08, - 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, - 0xf0, 0x6b, 0x88, 0x33, 0xb6, 0x73, 0x12, 0x6e, 0xf6, 0xf3, 0xc0, 0x10, 0xa5, 0x5c, 0xb4, 0x44, 0xc3, 0xd6, 0x8e, - 0xd7, 0x93, 0x6b, 0xc2, 0x7d, 0xd8, 0x88, 0x35, 0x19, 0x63, 0x5c, 0x9b, 0x1b, 0x59, 0x3f, 0x5a, 0xe0, 0xc1, 0x98, - 0xb2, 0xfe, 0x04, 0x32, 0xad, 0xa4, 0xac, 0xf3, 0x85, 0x11, 0x33, 0xa9, 0x44, 0xef, 0xf6, 0x8d, 0xcf, 0xea, 0x2e, - 0xa2, 0x7e, 0x6b, 0xbf, 0x27, 0xf5, 0x70, 0xe7, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, - 0x37, 0x4d, 0x8a, 0x38, 0x3d, 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, - 0x24, 0x49, 0xd6, 0xd2, 0xd8, 0x8a, 0x5d, 0x1a, 0xa4, 0x67, 0x6f, 0xc4, 0xa5, 0x17, 0x15, 0x1a, 0xd2, 0x52, 0xef, - 0x2c, 0x54, 0x32, 0x7f, 0xc5, 0x7f, 0x06, 0xb5, 0x02, 0x1d, 0x6d, 0x52, 0x8c, 0xa7, 0xc0, 0x88, 0xef, 0x06, 0xb3, - 0xba, 0x87, 0xb8, 0x68, 0x82, 0x52, 0xef, 0x88, 0x1d, 0x3f, 0x37, 0x79, 0x78, 0x17, 0x72, 0xce, 0xe0, 0xd3, 0xfb, - 0x59, 0xa2, 0xd6, 0x3a, 0x12, 0x23, 0x35, 0x03, 0x68, 0x3a, 0x28, 0x73, 0x1e, 0x8b, 0x60, 0xd6, 0x33, 0x89, 0x51, - 0x8f, 0xeb, 0x5f, 0xa0, 0xa1, 0xf6, 0x9b, 0x95, 0xe5, 0x59, 0x75, 0xf7, 0x25, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, - 0x75, 0x25, 0x2f, 0x2f, 0x55, 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, - 0x37, 0x8b, 0xbb, 0x59, 0x46, 0x03, 0x61, 0x6d, 0xe7, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, - 0x00, 0x10, 0xe9, 0x41, 0x14, 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xee, 0xe3, 0x28, 0x0b, 0xa5, 0x97, 0xb3, 0x8c, 0x9f, - 0x36, 0x8d, 0xb5, 0xce, 0x0a, 0x65, 0x68, 0x6d, 0x74, 0xa7, 0xab, 0x0c, 0xb1, 0xfd, 0x24, 0xce, 0x16, 0xe0, 0xfe, - 0x98, 0xa1, 0xd0, 0xd0, 0x59, 0x46, 0x9a, 0x68, 0xf8, 0xae, 0x3d, 0x83, 0x8c, 0xe2, 0x64, 0x9d, 0x57, 0xd2, 0x8d, - 0x3e, 0x6b, 0x23, 0x61, 0xee, 0x21, 0xfa, 0x55, 0x0c, 0x1e, 0xe5, 0x3e, 0xaf, 0x8d, 0x4e, 0xa6, 0x65, 0xa4, 0xdd, - 0xf9, 0x49, 0xbd, 0xcc, 0x52, 0xad, 0xc3, 0xf6, 0x19, 0xf6, 0xd6, 0x98, 0xf4, 0x26, 0xa4, 0x86, 0x91, 0xf8, 0x7c, - 0x46, 0x8d, 0x10, 0xd0, 0x96, 0xe3, 0xef, 0xf0, 0x19, 0x86, 0xa6, 0xc0, 0x52, 0xc5, 0x2d, 0xec, 0x86, 0xaf, 0xf9, - 0x64, 0xd5, 0x02, 0x10, 0xcc, 0xca, 0xd7, 0xbb, 0x78, 0x25, 0xd4, 0x67, 0xda, 0x0c, 0x00, 0x59, 0x50, 0xca, 0x1d, - 0x3f, 0xa5, 0xd2, 0xc1, 0x12, 0x45, 0xdb, 0xcb, 0xe9, 0x1b, 0x1d, 0x1b, 0xdf, 0xa7, 0xe7, 0x02, 0xb6, 0x0b, 0xf9, - 0xad, 0xbd, 0x7a, 0x89, 0x8a, 0xd4, 0xb6, 0x59, 0xf7, 0xf0, 0xe5, 0x06, 0x4d, 0xc2, 0x08, 0xca, 0x94, 0x29, 0x80, - 0xc1, 0x4d, 0x35, 0x0a, 0x26, 0xad, 0x46, 0xc2, 0x96, 0x7a, 0x92, 0xe5, 0xa6, 0x0f, 0x4e, 0xb5, 0x47, 0xd0, 0x73, - 0xab, 0x9c, 0x2f, 0x5a, 0xf6, 0x6b, 0x05, 0x47, 0x27, 0x57, 0x43, 0xd4, 0xcc, 0x7b, 0x6d, 0x47, 0x86, 0x94, 0xcb, - 0x30, 0x10, 0x4c, 0x39, 0xe6, 0xe9, 0xb1, 0xf5, 0x8c, 0x88, 0xee, 0x39, 0xfb, 0x4c, 0xb7, 0xea, 0x4a, 0x02, 0xa2, - 0xe3, 0x37, 0x8f, 0x5f, 0x5e, 0xc5, 0x97, 0x06, 0x45, 0xa9, 0x61, 0x11, 0xa3, 0x4c, 0xfb, 0x2a, 0x09, 0x83, 0xf7, - 0xcb, 0xbb, 0x9f, 0x54, 0x96, 0xda, 0xef, 0xc1, 0xc6, 0x8a, 0xaa, 0x7e, 0x29, 0x79, 0xd1, 0x14, 0x60, 0xed, 0xb3, - 0x44, 0x81, 0xdc, 0xef, 0x6c, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, 0x6d, 0xc9, 0x8e, - 0xac, 0x44, 0xce, 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x0d, 0xaa, 0x52, 0xf1, 0x7b, 0x23, 0x82, 0x53, - 0xc7, 0xaa, 0xc2, 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, 0xfd, 0xce, 0x0a, - 0x6a, 0x7e, 0xff, 0xd3, 0x18, 0xf2, 0x35, 0xa5, 0xa0, 0x92, 0x80, 0x9d, 0x41, 0xa3, 0xa7, 0x4a, 0x18, 0x48, 0x41, - 0xf0, 0x04, 0x28, 0x5f, 0x44, 0x8d, 0xd5, 0x6e, 0x5f, 0x9d, 0x1a, 0xa3, 0x2d, 0x20, 0xb4, 0x90, 0x1e, 0x5d, 0xf6, - 0x71, 0x1b, 0xeb, 0x40, 0xe2, 0xc1, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, 0x42, 0xf3, 0xfb, 0x46, 0x03, 0x5e, 0xd3, - 0x0a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xce, 0x0e, 0x29, 0x88, 0xd8, 0xa0, 0x85, 0x7d, 0x7b, 0x3e, 0x34, 0xfb, 0x7a, - 0x9e, 0x2c, 0x48, 0x4d, 0xa5, 0xfb, 0xdc, 0x2d, 0x21, 0x6b, 0xd5, 0xa1, 0xac, 0x3c, 0xc0, 0xf1, 0x42, 0xc9, 0xfc, - 0x1d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x63, 0xc4, 0x02, 0x96, 0x04, 0xed, 0xf5, 0x40, 0xfd, 0x32, 0x08, 0x15, 0xce, - 0xf4, 0x44, 0xe2, 0x53, 0xca, 0xd5, 0xa7, 0x05, 0xa9, 0xa7, 0x05, 0x73, 0xa0, 0x97, 0xbe, 0x95, 0x5f, 0xd9, 0xf8, - 0x68, 0x77, 0xef, 0x9a, 0x0b, 0xeb, 0x18, 0xe2, 0x62, 0x0b, 0xbf, 0x39, 0x35, 0x05, 0x60, 0xc3, 0x53, 0x5d, 0x96, - 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, - 0xf2, 0xb6, 0xfb, 0x9e, 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xc3, 0xfe, 0x55, 0xf2, 0x7f, 0x55, 0xc9, - 0x7e, 0xab, 0xcc, 0xba, 0x2d, 0xde, 0xef, 0x3a, 0x6e, 0x39, 0x46, 0x83, 0xc0, 0x9a, 0x02, 0x03, 0xe9, 0x49, 0x63, - 0x9a, 0xe8, 0xe8, 0xca, 0x8c, 0x19, 0x3c, 0xba, 0x00, 0xcd, 0x61, 0x3a, 0xcf, 0x63, 0x00, 0x0e, 0xf0, 0x8f, 0x3c, - 0x42, 0xfd, 0xd3, 0x79, 0x1e, 0x9c, 0x05, 0x83, 0x72, 0x10, 0xe8, 0x4f, 0x5c, 0x73, 0x82, 0x05, 0xe8, 0xdc, 0x62, - 0x06, 0x71, 0x27, 0xad, 0x99, 0x43, 0x7c, 0x9c, 0x4c, 0x07, 0x83, 0x98, 0x6c, 0x00, 0xa4, 0x2f, 0x5e, 0x58, 0xe7, - 0xa0, 0x42, 0x2f, 0xc8, 0x56, 0xdd, 0x45, 0xb3, 0x62, 0xaf, 0xda, 0x69, 0xde, 0xef, 0xe7, 0xf3, 0x72, 0x10, 0x34, - 0x2a, 0x2c, 0x8c, 0xf7, 0x1f, 0x6d, 0x7e, 0x69, 0x74, 0xd2, 0x04, 0x23, 0xd6, 0x9e, 0xa2, 0x7a, 0xc5, 0xd3, 0x8c, - 0x36, 0x6e, 0xc7, 0x4a, 0xf9, 0x02, 0xa2, 0x78, 0x60, 0xc8, 0x5a, 0x79, 0x77, 0x0e, 0x5e, 0x97, 0x1b, 0x6f, 0x8e, - 0x28, 0xc0, 0x6e, 0x0a, 0xe3, 0xa4, 0xe6, 0xa2, 0x8b, 0x9a, 0x78, 0x06, 0x3b, 0x5d, 0xbd, 0x95, 0x68, 0x35, 0xde, - 0x8b, 0x77, 0xcd, 0xc6, 0x5f, 0xcb, 0x03, 0x5d, 0xe6, 0xc1, 0x05, 0x20, 0xce, 0x1e, 0xc4, 0xd5, 0x01, 0x96, 0x7a, - 0x10, 0x0c, 0x2c, 0x72, 0x48, 0xbb, 0x5a, 0x3d, 0x14, 0x91, 0x3a, 0x8f, 0xc1, 0x80, 0xc9, 0x34, 0xa4, 0x26, 0xd3, - 0x5e, 0xac, 0x20, 0x6d, 0xac, 0xb5, 0x80, 0x36, 0x1c, 0x16, 0x3b, 0x76, 0xc3, 0xee, 0x74, 0xeb, 0x50, 0x28, 0x61, - 0x20, 0xeb, 0xba, 0x79, 0xa8, 0x35, 0x3c, 0x11, 0xf4, 0xa0, 0x1a, 0xed, 0xa7, 0x87, 0xf2, 0xa4, 0x3d, 0x16, 0xe0, - 0xa2, 0x87, 0x2f, 0x9f, 0x0b, 0xbc, 0x68, 0xef, 0x20, 0xcf, 0x99, 0x4f, 0x95, 0x0f, 0x62, 0xc3, 0x2d, 0xc3, 0x87, - 0xf6, 0xf1, 0xad, 0x40, 0x26, 0x75, 0x47, 0x53, 0x5b, 0xbb, 0xa3, 0x71, 0x4c, 0xa0, 0xdf, 0x94, 0xa3, 0x94, 0x89, - 0xa9, 0x65, 0xc9, 0x4e, 0x7a, 0xb9, 0xf2, 0x86, 0x4a, 0xd9, 0xc9, 0xb2, 0xcd, 0xf9, 0xa5, 0x8d, 0x84, 0x7e, 0x5f, - 0xbb, 0x03, 0xe1, 0x1b, 0xb5, 0xde, 0x90, 0x97, 0x0d, 0x11, 0xcb, 0x21, 0x66, 0xe0, 0x78, 0x21, 0x95, 0x6b, 0x77, - 0xd1, 0x54, 0xd5, 0xed, 0x6c, 0xe5, 0x82, 0x96, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x3a, 0xbd, 0x9e, 0x4a, 0xdc, 0xf7, - 0x51, 0x6c, 0x3f, 0x02, 0xb6, 0xb1, 0x71, 0x34, 0x36, 0x6e, 0x11, 0x1b, 0x7c, 0x15, 0x55, 0xb4, 0xe0, 0x00, 0xc1, - 0xdd, 0x96, 0xd4, 0xd2, 0xcc, 0x21, 0xee, 0x2b, 0x1e, 0xa0, 0x7d, 0x17, 0x47, 0x9c, 0x0a, 0xb0, 0xad, 0x6b, 0x9d, - 0xb3, 0x5a, 0x0e, 0xd8, 0x4c, 0xf4, 0xfc, 0xd3, 0xaa, 0x91, 0x88, 0x61, 0x95, 0x8d, 0x94, 0x15, 0xda, 0xbd, 0xd2, - 0x25, 0x5c, 0x7c, 0x01, 0x5e, 0xb6, 0xf7, 0x2b, 0xbb, 0xcf, 0x96, 0xd8, 0x3f, 0xcc, 0xab, 0x26, 0x78, 0xe4, 0x35, - 0xde, 0xde, 0xc3, 0xc4, 0x97, 0x4a, 0x21, 0xbc, 0x4a, 0x69, 0x28, 0x01, 0x18, 0x24, 0x41, 0x0d, 0x57, 0xda, 0x36, - 0x83, 0x54, 0xc6, 0xb0, 0xbb, 0xd5, 0x5b, 0xfd, 0x9f, 0x56, 0xe1, 0xa2, 0x92, 0xc5, 0x98, 0x04, 0x3a, 0xa7, 0x5a, - 0x6e, 0x02, 0x0b, 0x9e, 0xed, 0x92, 0x23, 0x50, 0xd8, 0x09, 0xe0, 0x86, 0x12, 0xf6, 0x4f, 0xbc, 0x0d, 0xe5, 0xec, - 0xb5, 0x95, 0x3c, 0xb9, 0x7d, 0x49, 0x05, 0x4d, 0xc8, 0x54, 0xd8, 0xfd, 0xdb, 0xda, 0xb0, 0xcf, 0x42, 0x39, 0x92, - 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0x32, 0x36, 0x9f, 0x49, 0xbf, 0xaf, 0xde, 0x3f, 0xcd, 0xb3, 0xe4, - 0xe3, 0xce, 0x7b, 0xc3, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x5a, 0x57, 0xc5, 0x70, 0xa9, 0x5d, 0x8c, 0x1b, 0x24, - 0x23, 0xde, 0x4b, 0x1d, 0x62, 0xc4, 0xf8, 0x22, 0x3b, 0x24, 0x25, 0xa7, 0xcb, 0xba, 0xb3, 0xe7, 0x5a, 0x34, 0x83, - 0xc6, 0x70, 0x3b, 0xde, 0x4b, 0x7a, 0x05, 0xa8, 0x00, 0xd1, 0x3d, 0x0b, 0x5c, 0xc3, 0x9b, 0x4b, 0xa2, 0xb1, 0xa5, - 0xa7, 0x2d, 0xd1, 0xc0, 0x5e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x18, 0x16, 0x00, 0xd4, 0x6a, - 0x90, 0x5e, 0xe9, 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, - 0x03, 0xfa, 0xb2, 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x87, 0xa5, - 0x49, 0x02, 0x41, 0x09, 0xca, 0x37, 0xe8, 0xbf, 0x4a, 0xcf, 0xc7, 0xf2, 0x47, 0xef, 0x50, 0xfa, 0x21, 0x2c, 0x40, - 0xa6, 0xa8, 0x2b, 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, - 0x59, 0x86, 0x38, 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, - 0x4a, 0x20, 0xca, 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, - 0xa4, 0x99, 0x5d, 0x87, 0x11, 0xa9, 0x76, 0x92, 0xcc, 0x97, 0x3f, 0xca, 0x4c, 0x78, 0xdf, 0xc0, 0x63, 0xb3, 0x59, - 0x36, 0xc5, 0x7c, 0xa1, 0x82, 0x39, 0xb8, 0x4f, 0x54, 0x5c, 0x8a, 0xca, 0x7f, 0xc2, 0x2e, 0x78, 0x31, 0x1e, 0xbc, - 0x5e, 0x23, 0xc0, 0x7e, 0xe5, 0x3f, 0x79, 0x63, 0xf6, 0xa7, 0x75, 0xe3, 0xcb, 0x4c, 0xc4, 0x07, 0x3e, 0xba, 0xa5, - 0x7c, 0x74, 0xe7, 0x65, 0xfa, 0xae, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x9d, 0x44, 0xd9, - 0xa8, 0xe2, 0x02, 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x84, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, - 0x61, 0x99, 0xa9, 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x37, 0x49, 0xf4, 0xe7, 0xd2, 0x43, 0x52, 0x33, 0x53, - 0xb6, 0xa9, 0x1d, 0xa1, 0x36, 0xbe, 0x8e, 0x74, 0xa3, 0x2d, 0x00, 0xe0, 0x9e, 0x2d, 0xd2, 0x48, 0x32, 0x31, 0x9c, - 0xd4, 0x8c, 0x9b, 0xf4, 0x02, 0x53, 0xe3, 0x9a, 0x55, 0x34, 0x71, 0x16, 0x32, 0xa0, 0xf7, 0xa7, 0xb9, 0x7e, 0xce, - 0xe0, 0xfe, 0x83, 0xd6, 0xc0, 0xe5, 0x71, 0xd1, 0xef, 0xcb, 0xe3, 0x62, 0xbb, 0x2d, 0x4f, 0xe2, 0x7e, 0x5f, 0x9e, - 0xc4, 0x86, 0x7f, 0x50, 0x8a, 0x6d, 0x63, 0x6e, 0x90, 0xd0, 0x5c, 0x42, 0xd4, 0xa2, 0x11, 0xfc, 0xa1, 0x59, 0xce, - 0x45, 0x94, 0x1f, 0x27, 0xfd, 0x7e, 0x6f, 0x39, 0x13, 0x83, 0x7c, 0x98, 0x44, 0xf9, 0x30, 0xf1, 0x9c, 0x10, 0x7f, - 0xf5, 0x9c, 0x10, 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, - 0xab, 0x5a, 0x12, 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0x7d, 0xb7, 0x04, 0x9e, 0x28, 0xe7, - 0xd5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x4d, 0x4d, 0x2f, 0xe8, 0x8a, - 0x5e, 0x22, 0x3f, 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, - 0xc2, 0xf5, 0x2c, 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x55, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x66, 0x10, 0xde, - 0x2f, 0x9d, 0x85, 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, - 0x97, 0x74, 0x45, 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, - 0x55, 0xe1, 0x5d, 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x68, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, - 0x66, 0x64, 0x24, 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, - 0xdc, 0xfd, 0x92, 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, - 0x38, 0xb0, 0x07, 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x25, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, - 0xc4, 0x2b, 0x70, 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, - 0x2b, 0x95, 0x7e, 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, - 0x17, 0xa3, 0x3b, 0x02, 0x16, 0x5e, 0xe3, 0xe9, 0xfa, 0x98, 0xc5, 0xd3, 0xc1, 0x60, 0x8d, 0x54, 0x5d, 0xe5, 0x5e, - 0x93, 0x05, 0xbd, 0xc0, 0x89, 0x20, 0xc0, 0xd0, 0x67, 0x62, 0x6d, 0x68, 0xf8, 0x53, 0x06, 0x1f, 0xdf, 0xb1, 0x8b, - 0xd1, 0x1d, 0xbd, 0x65, 0x4f, 0xb7, 0xe3, 0x29, 0x30, 0x53, 0xab, 0x59, 0x78, 0x77, 0x7c, 0x39, 0xbb, 0x64, 0x77, - 0xd1, 0xdd, 0x09, 0x34, 0xf4, 0x8a, 0xdd, 0x21, 0xe0, 0x52, 0xfa, 0x70, 0x39, 0x78, 0x4a, 0x0e, 0x07, 0x83, 0x94, - 0x44, 0xe1, 0x75, 0xe8, 0xb5, 0xf2, 0x29, 0xbd, 0x23, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, - 0xee, 0xea, 0xeb, 0xd0, 0xdb, 0xcd, 0x89, 0xe8, 0x04, 0x31, 0x42, 0x5f, 0x03, 0x47, 0xb3, 0x5c, 0x98, 0x09, 0x78, - 0x32, 0x17, 0x19, 0x2d, 0x0a, 0xcd, 0x40, 0x9c, 0x95, 0x80, 0x58, 0x12, 0x75, 0xbf, 0xd9, 0xe8, 0x0c, 0x96, 0x73, - 0xbf, 0xdf, 0xab, 0x0c, 0x3d, 0x40, 0xe4, 0xcc, 0x4e, 0x7a, 0xd0, 0xf3, 0xe9, 0x01, 0x7e, 0xa2, 0x57, 0x0d, 0xe2, - 0x64, 0xfe, 0xb0, 0x8c, 0x7e, 0xf5, 0xe8, 0xc3, 0x2f, 0xdd, 0x94, 0xa7, 0xcc, 0xff, 0x7d, 0xca, 0x23, 0xf3, 0xe8, - 0x55, 0xe5, 0x81, 0xe0, 0x79, 0x6b, 0x52, 0x69, 0x24, 0xaa, 0xd1, 0xd9, 0x2a, 0x06, 0x6d, 0x24, 0x6a, 0x1b, 0xf4, - 0x13, 0x5a, 0x58, 0x41, 0x84, 0x9c, 0xa3, 0x67, 0x60, 0x90, 0x0a, 0xa1, 0x72, 0xd4, 0xa2, 0x44, 0x43, 0x90, 0x5c, - 0x96, 0x5c, 0x85, 0xcf, 0x21, 0x54, 0x9d, 0x3e, 0xce, 0x44, 0xd8, 0xd0, 0xe3, 0xd0, 0x07, 0x80, 0xff, 0xe7, 0x0e, - 0xb9, 0x28, 0xf9, 0x25, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb0, 0x44, 0x34, 0x43, 0xdb, 0x20, 0xf6, 0x63, 0x49, 0xb0, - 0x1e, 0x49, 0xe3, 0x51, 0x69, 0x8e, 0x08, 0x3f, 0x8a, 0x8f, 0xa2, 0xa7, 0xb1, 0x21, 0x91, 0x1c, 0x49, 0x24, 0x1f, - 0x00, 0xe1, 0x24, 0xe8, 0x2f, 0xee, 0x9a, 0xec, 0x5a, 0x48, 0x0c, 0xfa, 0xd3, 0x92, 0x69, 0xd9, 0xbd, 0xea, 0xb1, - 0xaf, 0x08, 0x72, 0xc7, 0xf4, 0xef, 0x5e, 0x1f, 0xfe, 0x5a, 0xe2, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0x99, 0x37, - 0xb8, 0x91, 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, 0xf1, - 0x9c, 0xca, 0xf5, 0xca, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, 0x57, - 0xd2, 0x72, 0xf4, 0x94, 0x72, 0xd5, 0x4c, 0xb9, 0x58, 0xe7, 0xf9, 0x4f, 0x3b, 0xa9, 0x38, 0xc5, 0xcd, 0x14, 0xa4, - 0x4a, 0x2d, 0x17, 0x50, 0x3d, 0x47, 0x2d, 0x77, 0x4b, 0xb3, 0x03, 0x9c, 0xdb, 0xa6, 0xfa, 0x58, 0x99, 0x5d, 0x78, - 0xc9, 0x8d, 0xfb, 0x93, 0x29, 0xc3, 0x82, 0x51, 0x68, 0xb3, 0xea, 0x4a, 0xdb, 0x17, 0x5a, 0xa7, 0x61, 0xb8, 0xf2, - 0xe3, 0x05, 0xa4, 0x0b, 0x18, 0xc7, 0x8b, 0x92, 0x89, 0x71, 0x7b, 0xf4, 0x56, 0x10, 0x5f, 0xb2, 0x15, 0x48, 0xbf, - 0xdf, 0x13, 0xde, 0xae, 0xeb, 0x68, 0xbb, 0x27, 0x4e, 0x19, 0x95, 0xab, 0x58, 0x7c, 0x1f, 0xaf, 0x0c, 0x64, 0xb2, - 0x3a, 0x1e, 0x1b, 0x63, 0x3a, 0xfd, 0x3e, 0x09, 0xfd, 0x42, 0x28, 0xf8, 0xac, 0x97, 0x56, 0x9e, 0xdc, 0x1e, 0x96, - 0x71, 0x8d, 0x5e, 0x89, 0x2b, 0xdd, 0x37, 0x23, 0x85, 0xd4, 0x23, 0x5f, 0x35, 0x05, 0xf4, 0x66, 0xec, 0x9b, 0xa9, - 0x30, 0x6f, 0x7b, 0xc6, 0x5c, 0x21, 0x58, 0xa9, 0xb2, 0xdb, 0x77, 0x6a, 0x4c, 0xc5, 0x0c, 0xa6, 0xd8, 0x76, 0x16, - 0x93, 0x6e, 0xe5, 0x9f, 0x76, 0xee, 0xd3, 0xbc, 0xc3, 0x5d, 0x51, 0xbf, 0x05, 0x2e, 0x34, 0x2b, 0xca, 0xaa, 0x2d, - 0x1b, 0xb6, 0x8d, 0x37, 0xb2, 0x50, 0x6c, 0x80, 0x65, 0xcf, 0x7d, 0x0b, 0x0f, 0x10, 0x37, 0xe1, 0x9e, 0x5d, 0xd4, - 0x70, 0x63, 0xf8, 0xb2, 0x92, 0x7c, 0x57, 0x1a, 0x73, 0xe9, 0x53, 0xa5, 0x89, 0xe1, 0x64, 0x31, 0xe2, 0x22, 0x5d, - 0xd4, 0x99, 0x5d, 0x0b, 0x9f, 0xf1, 0x32, 0x9c, 0xf3, 0x85, 0xd1, 0x4d, 0xe9, 0xd2, 0x0b, 0x96, 0xe8, 0x4e, 0x6f, - 0x56, 0x1a, 0x2b, 0x25, 0xe2, 0xd6, 0x2c, 0x13, 0x28, 0x4b, 0x59, 0x2b, 0xe1, 0x4d, 0xd1, 0xb2, 0x95, 0x34, 0xf2, - 0x9e, 0x39, 0xb8, 0x8f, 0xfd, 0x82, 0x98, 0xc8, 0x26, 0x30, 0x29, 0x1a, 0x3a, 0xa0, 0x5d, 0x75, 0xe1, 0x9b, 0x51, - 0x0f, 0x06, 0xb9, 0x25, 0x89, 0x58, 0x41, 0x8a, 0x15, 0xac, 0x6b, 0x56, 0xcc, 0xf3, 0x05, 0xbd, 0x60, 0x72, 0x9e, - 0x2e, 0xe8, 0x8a, 0xc9, 0xf9, 0x1a, 0x6f, 0x42, 0x17, 0x70, 0x42, 0x92, 0x4d, 0xac, 0x14, 0xb0, 0x17, 0x78, 0x79, - 0xc3, 0x33, 0x55, 0xd3, 0xb2, 0x4b, 0xc5, 0x01, 0xc6, 0xe7, 0x65, 0x18, 0x96, 0xc3, 0x0b, 0xb0, 0x96, 0x38, 0x0c, - 0x57, 0x73, 0xbe, 0x50, 0xbf, 0x21, 0xea, 0x7c, 0x12, 0x2a, 0x76, 0xc1, 0xee, 0x05, 0x32, 0xbd, 0x9a, 0xf3, 0x85, - 0x1a, 0x09, 0x5d, 0xf0, 0x95, 0x35, 0x36, 0x89, 0x3d, 0x41, 0xcb, 0x2c, 0x9e, 0x8f, 0x17, 0x51, 0x5c, 0xc3, 0x32, - 0x7c, 0xaf, 0x66, 0xa6, 0x25, 0xff, 0x49, 0xd4, 0x86, 0x26, 0xfa, 0x06, 0xab, 0xc8, 0x1f, 0x1e, 0x1f, 0x5d, 0x02, - 0x19, 0x3b, 0xbb, 0x92, 0x99, 0x0f, 0x7d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0a, 0x12, 0x65, 0xe0, 0xee, - 0xd5, 0x2c, 0x19, 0x6b, 0x11, 0xbe, 0x7b, 0x54, 0x14, 0x7d, 0x26, 0x4d, 0x03, 0xba, 0x8f, 0x04, 0x73, 0xa0, 0xf7, - 0x0a, 0x1d, 0x2e, 0xab, 0x6d, 0x26, 0xe0, 0x2f, 0x12, 0xe4, 0xb7, 0x42, 0xaf, 0x6a, 0x0c, 0xaa, 0x68, 0x17, 0xb1, - 0xf4, 0xef, 0x23, 0x7e, 0x94, 0xcd, 0xdf, 0xcd, 0x3d, 0x5e, 0x49, 0x18, 0xfc, 0x90, 0x9a, 0x4d, 0x32, 0x6f, 0xaf, - 0xd8, 0x7b, 0xe8, 0xa8, 0x47, 0xad, 0xf1, 0xbe, 0x7a, 0xc1, 0x29, 0xc4, 0x28, 0xa1, 0xe8, 0x24, 0x18, 0xc0, 0xed, - 0x12, 0x52, 0xdc, 0x0d, 0x76, 0xd3, 0xbc, 0xe6, 0x45, 0xc1, 0xf9, 0xba, 0xaa, 0x02, 0x3f, 0xa0, 0xe1, 0x7c, 0xb1, - 0x1b, 0xc2, 0x70, 0x4c, 0x5b, 0xd7, 0x30, 0x08, 0x33, 0x86, 0x91, 0x10, 0xbc, 0xfe, 0x45, 0x8f, 0x68, 0x12, 0xaf, - 0xbe, 0xe3, 0x9f, 0x32, 0x5e, 0x28, 0x22, 0x0d, 0x22, 0xa4, 0x6e, 0xe2, 0x1b, 0x99, 0x26, 0x05, 0x14, 0x02, 0x8c, - 0x02, 0x2a, 0xb1, 0xa1, 0xa9, 0xf8, 0x5b, 0x2d, 0x3e, 0xf8, 0xa9, 0xe9, 0x78, 0x34, 0xae, 0x5b, 0x9d, 0x51, 0x41, - 0x67, 0xa0, 0x47, 0xad, 0xa8, 0xa7, 0x41, 0x2b, 0xc1, 0x34, 0xd2, 0xbc, 0x75, 0x0f, 0x81, 0x57, 0xa6, 0xc5, 0x3b, - 0x0f, 0xe8, 0xe6, 0xcc, 0x07, 0x4f, 0x1e, 0xd3, 0x33, 0x87, 0x9e, 0x5c, 0xb1, 0x93, 0xaa, 0x87, 0xda, 0x7b, 0x33, - 0x42, 0x41, 0xbf, 0x8f, 0x29, 0xd0, 0x8d, 0xa0, 0xf6, 0xae, 0xee, 0x95, 0xdc, 0xe5, 0xf0, 0x1d, 0x67, 0xb9, 0x01, - 0x2c, 0x15, 0x59, 0x2b, 0xf0, 0x28, 0x40, 0x5d, 0x2a, 0x43, 0xd8, 0x62, 0x0e, 0x87, 0xca, 0x6e, 0xd5, 0x6a, 0x28, - 0xc9, 0x71, 0x39, 0x02, 0x87, 0xd0, 0x75, 0x39, 0x28, 0x47, 0xcb, 0xac, 0x7a, 0x87, 0xbf, 0x35, 0xeb, 0x90, 0x64, - 0xfb, 0x58, 0x07, 0x6e, 0x59, 0x87, 0xe9, 0x47, 0x83, 0x14, 0x80, 0x26, 0x1b, 0x81, 0x4b, 0x00, 0xde, 0xdb, 0x7f, - 0x44, 0xa8, 0x95, 0xe9, 0x5e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, - 0x91, 0xce, 0x49, 0x9d, 0x89, 0x77, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x77, 0x78, 0x9b, - 0xd5, 0x52, 0x1b, 0x3d, 0x50, 0x00, 0xbf, 0x1b, 0xdc, 0x21, 0xc8, 0x57, 0x63, 0xb8, 0x56, 0xf2, 0x26, 0xe4, 0xc3, - 0x82, 0x1e, 0x91, 0x81, 0x7d, 0x16, 0xc3, 0x98, 0x1e, 0x91, 0x63, 0xfb, 0x2c, 0xdd, 0x00, 0x0e, 0xa4, 0x1e, 0x55, - 0x7a, 0x04, 0x0d, 0xfa, 0xdd, 0xb6, 0xc8, 0x1d, 0x80, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0xde, - 0x9b, 0xeb, 0x0e, 0x73, 0x81, 0x30, 0x07, 0x03, 0x0e, 0xe2, 0x36, 0x08, 0xcd, 0x01, 0xb3, 0xb9, 0x8d, 0x04, 0xbd, - 0xb3, 0x86, 0x99, 0x1d, 0xfd, 0xe1, 0x56, 0x82, 0x6f, 0xb2, 0xd6, 0xa8, 0xf3, 0xe2, 0x10, 0x08, 0x82, 0x37, 0x85, - 0xaa, 0xf6, 0xaa, 0x07, 0x36, 0xde, 0xaa, 0x1f, 0xdb, 0xed, 0x78, 0x2a, 0xdc, 0xb5, 0x5f, 0x50, 0x38, 0xf9, 0x94, - 0xfc, 0xeb, 0x9d, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, - 0x3c, 0x52, 0xf4, 0x6f, 0xaf, 0xac, 0x7c, 0x6a, 0xa7, 0x7f, 0xbb, 0x35, 0xeb, 0xf3, 0x78, 0x34, 0xd9, 0x6e, 0x7b, - 0x71, 0xa5, 0x3d, 0xd6, 0xf4, 0x82, 0x40, 0xe7, 0x7a, 0x72, 0x78, 0x04, 0x51, 0x11, 0x9a, 0x71, 0x37, 0xcb, 0x86, - 0x44, 0xc6, 0x8f, 0xd3, 0x59, 0x36, 0x04, 0x3b, 0xdc, 0x8b, 0x4a, 0x5c, 0x8e, 0x5a, 0x1b, 0x9c, 0xde, 0x25, 0x21, - 0x84, 0x72, 0xc0, 0xca, 0x6e, 0xd5, 0x9f, 0x3b, 0x65, 0x26, 0xa4, 0x26, 0xab, 0xdb, 0x29, 0xdd, 0xc3, 0x34, 0x3f, - 0x30, 0x23, 0x38, 0xe0, 0xde, 0xfe, 0xaa, 0x3f, 0x86, 0x49, 0xa6, 0xc9, 0x29, 0x92, 0x5f, 0xa4, 0xa7, 0x90, 0xb4, - 0x43, 0x4f, 0x15, 0x01, 0x9c, 0x50, 0xfb, 0x31, 0xfc, 0x86, 0x71, 0xff, 0xae, 0xf9, 0xda, 0x4d, 0x45, 0xf4, 0x98, - 0x62, 0x99, 0x9a, 0x9c, 0x26, 0x59, 0x91, 0x40, 0xd4, 0x46, 0xd5, 0x8c, 0xe8, 0x91, 0x8b, 0xf9, 0xa8, 0x08, 0x9f, - 0x57, 0xeb, 0xff, 0x0c, 0xe1, 0x33, 0x0a, 0x37, 0x80, 0xcb, 0x2b, 0x2e, 0xcf, 0xc3, 0x27, 0x8f, 0xe9, 0xc1, 0xe4, - 0x9b, 0x23, 0x7a, 0x70, 0xf4, 0xe8, 0x09, 0x01, 0x58, 0xb4, 0xcb, 0xf3, 0xf0, 0xe8, 0xc9, 0x13, 0x7a, 0xf0, 0xed, - 0xb7, 0xf4, 0x60, 0xf2, 0xe8, 0xa8, 0x91, 0x36, 0x79, 0xf2, 0x2d, 0x3d, 0xf8, 0xe6, 0x71, 0x23, 0xed, 0x68, 0xfc, - 0x84, 0x1e, 0xfc, 0xfd, 0x1b, 0x93, 0xf6, 0x37, 0xc8, 0xf6, 0xed, 0x11, 0xfe, 0x67, 0xd2, 0x26, 0x4f, 0x1e, 0xd1, - 0x83, 0xc9, 0x18, 0x2a, 0x79, 0xe2, 0x2a, 0x19, 0x4f, 0xe0, 0xe3, 0x47, 0xf0, 0xdf, 0xdf, 0x08, 0x6c, 0x02, 0xc9, - 0x72, 0x81, 0xfa, 0x33, 0x14, 0x71, 0xa2, 0x6a, 0x22, 0xe1, 0x21, 0x66, 0x56, 0xdf, 0xc4, 0x61, 0x40, 0x5c, 0x3a, - 0x14, 0x44, 0x0f, 0xc6, 0xa3, 0x27, 0x24, 0xf0, 0xe1, 0xe9, 0x3e, 0xfa, 0x20, 0x63, 0xb9, 0x98, 0x67, 0x5f, 0xe5, - 0x26, 0xb6, 0x82, 0x07, 0x60, 0xf5, 0xde, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x8a, 0xcb, 0xdd, 0x5c, 0xff, 0x68, 0x01, - 0xca, 0xfb, 0xab, 0x96, 0x7d, 0x2c, 0x54, 0xe8, 0xb4, 0xd6, 0xe8, 0xb3, 0xf7, 0x98, 0x3e, 0x18, 0x78, 0x37, 0xec, - 0xef, 0x77, 0xca, 0x69, 0x7d, 0xa3, 0x51, 0xa8, 0x51, 0x79, 0x48, 0xd8, 0x09, 0x14, 0x3d, 0x18, 0x00, 0x4f, 0xe0, - 0xe1, 0xbe, 0xfd, 0x9b, 0x65, 0xbc, 0xef, 0x28, 0xe3, 0x5f, 0x28, 0x43, 0x40, 0xa3, 0x1e, 0x66, 0x37, 0x3d, 0x6c, - 0x74, 0xab, 0x97, 0x2c, 0xd5, 0xc9, 0xd4, 0xf4, 0x0c, 0xf6, 0xb5, 0xae, 0xe5, 0x81, 0x11, 0x45, 0xcb, 0x8b, 0x83, - 0x94, 0xcf, 0x2a, 0xf6, 0xfd, 0x12, 0xd5, 0x5b, 0x51, 0xe3, 0x8d, 0xcc, 0x66, 0x15, 0xfb, 0xd9, 0xbc, 0x01, 0x6e, - 0x86, 0xfd, 0x43, 0x3d, 0xf9, 0x81, 0x33, 0x32, 0x69, 0xdb, 0xa3, 0x4c, 0x8c, 0x00, 0x2b, 0x20, 0x03, 0x07, 0x1e, - 0x00, 0x1d, 0xf4, 0x47, 0x7b, 0xbb, 0x55, 0x29, 0xcd, 0x3e, 0x5b, 0x18, 0x40, 0xc3, 0xbc, 0x4d, 0x3c, 0x54, 0xb3, - 0x86, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0x76, 0x0a, 0x43, 0x08, 0xc1, 0x2a, 0x65, 0x00, 0x38, 0x10, 0x60, 0x30, - 0xd6, 0x32, 0xa0, 0x66, 0xcb, 0x47, 0x1b, 0xae, 0xd4, 0x93, 0xc0, 0x19, 0x5c, 0xc8, 0x22, 0xe1, 0x6f, 0xb4, 0xd8, - 0x1f, 0xad, 0x1f, 0x7d, 0xdf, 0x1e, 0x0f, 0xd6, 0xbe, 0xc7, 0x47, 0xfa, 0xb3, 0xc6, 0x75, 0x60, 0xd3, 0xf2, 0x8d, - 0x17, 0xb5, 0x95, 0x78, 0x94, 0xc0, 0x1b, 0x98, 0x88, 0x14, 0x06, 0xa9, 0x16, 0x38, 0x06, 0xe5, 0x8d, 0x85, 0x58, - 0xaa, 0xae, 0x6e, 0xe8, 0x96, 0x0c, 0xc1, 0xc3, 0xed, 0xc7, 0xa5, 0x0a, 0x1c, 0xd5, 0xef, 0x67, 0xd2, 0x77, 0x7b, - 0x32, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0xe1, 0xe0, 0xbf, 0x49, 0x5d, 0x1b, 0xbb, 0xfb, 0x94, 0x59, 0x96, 0x85, 0x9d, - 0x84, 0x5a, 0xee, 0x51, 0x79, 0x90, 0x7c, 0x21, 0x87, 0x48, 0x16, 0x18, 0x85, 0x82, 0x0c, 0x27, 0x54, 0x8c, 0xd6, - 0xa2, 0x5c, 0x66, 0x17, 0x55, 0xb8, 0x51, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, 0x48, 0x48, 0x94, 0x95, 0xaf, - 0xe3, 0xd7, 0x21, 0x82, 0xd5, 0x71, 0x6d, 0x0b, 0xc5, 0xbd, 0xfd, 0x99, 0xa5, 0x5d, 0xfc, 0x91, 0x71, 0x01, 0x75, - 0xb1, 0x98, 0x86, 0x13, 0xab, 0xdf, 0x71, 0x5f, 0x58, 0x4d, 0x0f, 0x40, 0x7d, 0x97, 0x4a, 0x8c, 0xa0, 0xbe, 0x32, - 0xf6, 0xb1, 0x3d, 0xc6, 0xe4, 0x0c, 0x62, 0x0d, 0xeb, 0xbb, 0x9d, 0xea, 0x1b, 0x61, 0x27, 0x00, 0xdc, 0x08, 0xad, - 0xd1, 0x91, 0x49, 0xaa, 0x10, 0xcf, 0x4b, 0x15, 0xbe, 0x35, 0x23, 0x74, 0x0c, 0xde, 0x54, 0xb6, 0x91, 0x42, 0xfa, - 0x82, 0x41, 0x73, 0x6c, 0xeb, 0x28, 0xac, 0xb6, 0xb2, 0xec, 0x04, 0xe0, 0x06, 0xb2, 0x63, 0x73, 0xf1, 0x9c, 0x55, - 0xf3, 0x6c, 0x11, 0x99, 0xa0, 0x80, 0x4b, 0x61, 0x19, 0xb4, 0xd7, 0x7b, 0x64, 0x3b, 0x0e, 0xa1, 0x1b, 0xee, 0x23, - 0x18, 0x4f, 0xbb, 0x29, 0x58, 0x41, 0x34, 0x42, 0x3c, 0xcc, 0x98, 0xc5, 0xf7, 0x4a, 0x53, 0x9e, 0xaa, 0x96, 0x40, - 0xe0, 0x28, 0x84, 0xba, 0xd8, 0x35, 0x4a, 0x70, 0x99, 0x1a, 0xc1, 0x0c, 0x76, 0xec, 0x48, 0x6d, 0x97, 0x9c, 0xd3, - 0xa1, 0x9a, 0xd2, 0x52, 0x4f, 0xa9, 0xf6, 0x35, 0x14, 0xf3, 0x12, 0x3d, 0xf4, 0xc0, 0xf5, 0x40, 0x3b, 0xe4, 0x95, - 0x74, 0x62, 0x22, 0xe8, 0xb4, 0xda, 0x84, 0x9d, 0x1b, 0xe9, 0x96, 0xd5, 0xc8, 0x3b, 0x86, 0x66, 0x47, 0xbc, 0xf4, - 0x03, 0x75, 0x01, 0x44, 0xc8, 0xde, 0x16, 0x99, 0xd9, 0x67, 0x59, 0xf9, 0x02, 0xca, 0xe2, 0x88, 0xad, 0x2b, 0xe0, - 0x5a, 0x0a, 0x26, 0x97, 0x3c, 0xca, 0x52, 0x44, 0x04, 0x3c, 0x55, 0xda, 0xf5, 0x9d, 0x96, 0x10, 0x2a, 0x52, 0x20, - 0x6e, 0x2e, 0x8a, 0x73, 0x6d, 0x03, 0x59, 0x00, 0x7d, 0xfb, 0x29, 0xbb, 0xf2, 0xc2, 0xc1, 0x6e, 0xae, 0x32, 0xf1, - 0x8c, 0x5f, 0x64, 0x82, 0xa7, 0x08, 0x76, 0x75, 0x6b, 0x1e, 0xb8, 0x63, 0xdb, 0xc0, 0xf2, 0xed, 0x3b, 0x58, 0x30, - 0x65, 0xa8, 0x95, 0x12, 0x99, 0x88, 0x04, 0x64, 0xf6, 0x99, 0xbb, 0x57, 0x99, 0x78, 0x15, 0xdf, 0x82, 0x37, 0x45, - 0x83, 0x9f, 0x1e, 0x9d, 0xe3, 0x97, 0x88, 0x24, 0x0a, 0x31, 0x6c, 0x31, 0x22, 0x16, 0x22, 0xc7, 0x8e, 0x09, 0xe5, - 0x4a, 0xd0, 0xda, 0x1a, 0x02, 0x2f, 0xfe, 0xb4, 0xea, 0xde, 0x55, 0x26, 0x8c, 0x7d, 0xc6, 0x55, 0x7c, 0xcb, 0x4a, - 0x05, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xab, 0x4c, 0x18, 0x01, 0xc9, 0x55, 0x7c, 0x4b, 0x9b, 0x32, 0x0e, - 0x6d, 0x45, 0xe7, 0xc5, 0xf9, 0xdd, 0x1d, 0x7e, 0x89, 0xa1, 0x56, 0xc6, 0xfd, 0x3e, 0x48, 0xcc, 0xa4, 0x6d, 0xca, - 0x4c, 0x46, 0x52, 0xa3, 0x85, 0x54, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x5a, 0x46, 0xd4, 0x7e, 0x15, 0x8a, 0xd9, - 0x38, 0x9a, 0x10, 0x3a, 0xe9, 0x58, 0xef, 0xa6, 0xb5, 0x90, 0x69, 0xf4, 0x24, 0xf2, 0x7c, 0x3a, 0x0b, 0x56, 0x4d, - 0x8b, 0x63, 0xc6, 0xa7, 0xc5, 0x60, 0x40, 0xb4, 0x4b, 0xe1, 0x06, 0xeb, 0x01, 0x53, 0x1a, 0x17, 0x6f, 0xcd, 0xb4, - 0xfa, 0x85, 0x54, 0x21, 0xe9, 0x3d, 0x03, 0x12, 0x21, 0x5d, 0xb0, 0x5b, 0x90, 0x28, 0x7a, 0xfe, 0x77, 0x6a, 0x0b, - 0xee, 0x7a, 0x30, 0x36, 0xa3, 0xfb, 0x7a, 0xc6, 0x7f, 0xa8, 0x6d, 0x41, 0xd4, 0xa7, 0x92, 0xf5, 0x3a, 0x12, 0x55, - 0xc8, 0x45, 0xf8, 0xd9, 0xd1, 0x10, 0x43, 0x54, 0x7b, 0x2c, 0x10, 0xeb, 0xab, 0x73, 0x5e, 0xe0, 0xf4, 0x33, 0x77, - 0xb9, 0x82, 0x6d, 0x41, 0x2b, 0x43, 0xa3, 0x5e, 0xc7, 0xaf, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0x3e, 0x43, 0x21, 0x6b, - 0x1e, 0x86, 0xd5, 0xb0, 0x3d, 0x88, 0xe4, 0xb0, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, - 0xad, 0xfc, 0xed, 0x18, 0x5c, 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, - 0xb0, 0x2a, 0x65, 0x92, 0x0f, 0xbf, 0x5e, 0xc8, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, - 0xb0, 0xee, 0x93, 0xf7, 0xf5, 0xc3, 0xce, 0x9e, 0x80, 0x51, 0xac, 0xca, 0xd1, 0x14, 0x52, 0x6a, 0x1f, 0x94, 0xfa, - 0x63, 0xb8, 0x14, 0x9a, 0x63, 0xb7, 0x80, 0x49, 0xc0, 0x3e, 0x43, 0xaa, 0xc7, 0xb4, 0x63, 0x9f, 0xa3, 0x0d, 0x2c, - 0x09, 0x38, 0xfc, 0x23, 0x21, 0x6b, 0xff, 0xea, 0x5e, 0xa6, 0xcd, 0x90, 0x2d, 0xf3, 0x05, 0xf0, 0xf9, 0xb0, 0x6b, - 0xa3, 0x12, 0x65, 0x13, 0x91, 0xa4, 0xb0, 0xe5, 0x31, 0x48, 0x7b, 0x14, 0xd3, 0x55, 0xc1, 0x93, 0x0c, 0xa5, 0x14, - 0x89, 0xf6, 0x09, 0xce, 0xe1, 0x0d, 0xee, 0x47, 0x15, 0x10, 0x5e, 0x85, 0x9c, 0x8e, 0x52, 0xaa, 0x2d, 0x60, 0x14, - 0xf5, 0x00, 0x51, 0x5e, 0x06, 0x72, 0xbc, 0xed, 0x76, 0x42, 0x57, 0x6c, 0x39, 0x9c, 0x50, 0x24, 0x25, 0x97, 0x58, - 0xee, 0x15, 0xe8, 0x3c, 0xce, 0x59, 0xef, 0x25, 0x60, 0x11, 0x9c, 0xc1, 0xdf, 0x98, 0xd0, 0x6b, 0xf8, 0x9b, 0x13, - 0xfa, 0x94, 0x85, 0x57, 0xc3, 0x4b, 0x72, 0x18, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0xb4, 0x0c, 0x55, 0xe2, - 0xea, 0xf0, 0x82, 0x3c, 0xbc, 0xa0, 0xb7, 0xf4, 0x86, 0xbe, 0xa2, 0x6f, 0x80, 0xf0, 0xdf, 0x1d, 0x4f, 0xf8, 0x70, - 0xf2, 0xb8, 0xdf, 0xef, 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, - 0x7a, 0x31, 0x7d, 0xa3, 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xbc, 0x23, 0x43, 0x7c, 0xbc, 0xc8, 0xa5, 0x2c, - 0xc2, 0xcb, 0xc3, 0x3b, 0x42, 0xdf, 0x9c, 0x80, 0xde, 0x14, 0xeb, 0x7b, 0xf3, 0xf0, 0x4e, 0xd7, 0x46, 0xe8, 0xcb, - 0x30, 0x81, 0x6d, 0x72, 0xcb, 0xec, 0x5d, 0x7b, 0x32, 0x86, 0x58, 0x26, 0x77, 0x5e, 0x79, 0x77, 0x0f, 0x6f, 0xc9, - 0xe1, 0x2d, 0x78, 0x8a, 0x5a, 0xf2, 0x37, 0x0b, 0x6f, 0x58, 0xab, 0x86, 0x87, 0x77, 0xf4, 0x55, 0xab, 0x11, 0x0f, - 0xef, 0x48, 0x14, 0xde, 0xb0, 0x4b, 0xfa, 0x8a, 0x5d, 0x11, 0x7a, 0xde, 0xef, 0x9f, 0xf5, 0xfb, 0xb2, 0xdf, 0xff, - 0x3e, 0x0e, 0xc3, 0x78, 0x58, 0x90, 0x43, 0x49, 0xef, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, - 0x59, 0x95, 0xb7, 0xca, 0x75, 0x47, 0xc1, 0x5a, 0xe1, 0x8e, 0xa9, 0xa7, 0x37, 0xf4, 0x86, 0x15, 0xf4, 0x15, 0x8b, - 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, 0x15, 0xd1, 0x0d, 0x7d, 0xc5, 0xce, 0x66, 0x71, 0xf4, 0x8a, 0xbe, 0x61, 0xf9, - 0x70, 0x02, 0x79, 0x5f, 0x0d, 0x6f, 0xc8, 0xe1, 0x1b, 0x12, 0x85, 0x6f, 0xf4, 0xef, 0x3b, 0x7a, 0xc9, 0xc3, 0x37, - 0xd4, 0xab, 0xe6, 0x0d, 0x31, 0xd5, 0x37, 0x6a, 0x7f, 0x43, 0x22, 0x7f, 0x30, 0xdf, 0x58, 0x7b, 0x9a, 0xb7, 0x8e, - 0x36, 0xae, 0xcb, 0xf0, 0x8e, 0xd0, 0x75, 0x19, 0xde, 0x10, 0x32, 0x6d, 0x8e, 0x1d, 0x0c, 0xe8, 0xec, 0x6d, 0x94, - 0x10, 0x7a, 0xe3, 0x97, 0x7a, 0x83, 0x63, 0x68, 0x46, 0x48, 0xf7, 0x13, 0xd3, 0x70, 0x1d, 0x7c, 0xd0, 0x60, 0x1d, - 0xe7, 0xfd, 0x7e, 0xb8, 0xee, 0xf7, 0x21, 0xd2, 0x7d, 0x31, 0x33, 0xb1, 0xdd, 0x1c, 0xd9, 0xa4, 0x37, 0xa0, 0xfd, - 0xff, 0x30, 0x18, 0x40, 0x67, 0xbc, 0x92, 0xc2, 0x9b, 0xc1, 0x87, 0x87, 0x77, 0x44, 0xd5, 0x51, 0xd0, 0x52, 0x86, - 0x05, 0x7d, 0x4a, 0x33, 0x00, 0xfc, 0xfa, 0x30, 0x18, 0x90, 0xc8, 0x7c, 0x46, 0xa6, 0x1f, 0x8e, 0xdf, 0x4c, 0x07, - 0x83, 0x0f, 0x66, 0x9b, 0x7c, 0x62, 0x7b, 0x4a, 0x81, 0xf5, 0x77, 0xd6, 0xef, 0x7f, 0x3a, 0x89, 0xc9, 0x79, 0xc1, - 0xe3, 0x8f, 0xd3, 0x66, 0x5b, 0x3e, 0xb9, 0xa8, 0x6a, 0x67, 0xfd, 0xfe, 0xba, 0xdf, 0x7f, 0x05, 0xd8, 0x45, 0x33, - 0xe7, 0xeb, 0x09, 0xd2, 0x96, 0xb9, 0xa3, 0x48, 0x9a, 0xe4, 0xd0, 0x18, 0xda, 0x16, 0xab, 0xb6, 0xcd, 0x3a, 0x32, - 0xb0, 0x38, 0x6a, 0x56, 0x14, 0xd7, 0x24, 0x0a, 0x7b, 0x67, 0xdb, 0xed, 0x2b, 0xc6, 0x58, 0x4c, 0x40, 0xfa, 0xe1, - 0xbf, 0x7e, 0x55, 0x37, 0x62, 0x88, 0x95, 0x4a, 0x7c, 0xb7, 0x59, 0xda, 0x43, 0x20, 0xe2, 0xb0, 0xe9, 0xdf, 0x99, - 0x7b, 0xb9, 0xa8, 0x1d, 0xdf, 0xfa, 0x2f, 0x00, 0x21, 0x92, 0x2c, 0xe4, 0x33, 0x1c, 0x83, 0x32, 0x03, 0x20, 0xf3, - 0x48, 0xcd, 0xbc, 0x04, 0x10, 0x60, 0xb2, 0xdd, 0x8e, 0xc6, 0xe3, 0x09, 0x2d, 0xd8, 0xe8, 0x6f, 0x4f, 0x1e, 0x56, - 0x0f, 0xc3, 0x20, 0x18, 0x64, 0xa4, 0xa5, 0xa7, 0xb0, 0x8b, 0xb5, 0x3a, 0x04, 0x23, 0x78, 0xcd, 0x3e, 0x5e, 0x67, - 0x5f, 0xcc, 0x3e, 0x22, 0x61, 0x6d, 0x30, 0x8e, 0x5c, 0xa4, 0x2d, 0xbd, 0xdd, 0x1e, 0x06, 0x93, 0x8b, 0xf4, 0x33, - 0x6c, 0xa7, 0xcf, 0xbf, 0x79, 0x30, 0x9e, 0x70, 0x30, 0xba, 0x8b, 0x82, 0x3e, 0xd3, 0xb6, 0xdb, 0xca, 0xbf, 0x04, - 0xbe, 0xc6, 0x54, 0xd0, 0xb1, 0x59, 0x16, 0x6e, 0x50, 0x11, 0x75, 0xb4, 0x0c, 0xaa, 0x5a, 0xd9, 0xce, 0x01, 0xb5, - 0xc4, 0xaa, 0x4c, 0xdc, 0x02, 0xc3, 0x90, 0xa1, 0x2e, 0xf7, 0xb4, 0xfa, 0x17, 0x2f, 0xa4, 0x81, 0xcf, 0x70, 0x22, - 0x42, 0x8f, 0x5b, 0xe3, 0x3e, 0xb7, 0x26, 0x3e, 0xc3, 0xad, 0x95, 0x48, 0x62, 0x0d, 0x2c, 0xa9, 0xb9, 0x1c, 0x25, - 0xec, 0xa4, 0x64, 0x7c, 0x56, 0x46, 0x09, 0x8d, 0xe1, 0x41, 0x32, 0x31, 0x93, 0x51, 0x82, 0xf6, 0x89, 0x2e, 0xc2, - 0xe0, 0x5f, 0x80, 0xd9, 0x4f, 0x73, 0xf8, 0x2b, 0xc9, 0x34, 0x39, 0x86, 0x80, 0x10, 0xc7, 0xe3, 0x59, 0x1c, 0x8e, - 0x49, 0x94, 0x9c, 0xc0, 0x13, 0xfc, 0x57, 0x84, 0x63, 0x52, 0xeb, 0x3b, 0x8c, 0x54, 0x97, 0xdb, 0x84, 0x01, 0x5c, - 0xd9, 0x78, 0x36, 0x89, 0xac, 0x74, 0x57, 0x3e, 0x1c, 0x8d, 0x9f, 0x90, 0x69, 0x1c, 0xca, 0x41, 0x42, 0x28, 0x78, - 0xf7, 0x86, 0xe5, 0x30, 0xd1, 0xf0, 0x6c, 0xc0, 0xe6, 0x95, 0x8e, 0xcd, 0x93, 0x70, 0x02, 0xc2, 0x30, 0x21, 0xc7, - 0xba, 0x07, 0x29, 0x45, 0x9f, 0xe7, 0xd8, 0x4f, 0x7d, 0x04, 0x61, 0x76, 0xd4, 0x52, 0xf1, 0x15, 0x00, 0x5d, 0xe2, - 0xe0, 0x50, 0x7b, 0xe6, 0x8b, 0x59, 0x58, 0x7a, 0x54, 0xca, 0x54, 0x77, 0x28, 0x1a, 0x94, 0xdf, 0x34, 0xe8, 0x50, - 0x90, 0xc1, 0x84, 0x96, 0x27, 0x13, 0xfe, 0x08, 0x02, 0x78, 0x34, 0x22, 0x7e, 0x29, 0x9c, 0x18, 0x08, 0xaf, 0x82, - 0x0c, 0x54, 0x5a, 0xab, 0xc6, 0x8c, 0x6c, 0xc5, 0x07, 0x10, 0x26, 0xe5, 0xe0, 0x46, 0xae, 0xf3, 0x14, 0xa2, 0x82, - 0xad, 0xf3, 0xea, 0xe0, 0x12, 0x2c, 0xd9, 0xe3, 0x0a, 0xe2, 0x84, 0xad, 0x57, 0x80, 0x9d, 0xfb, 0x60, 0x53, 0xd6, - 0x07, 0xea, 0xbb, 0x03, 0x6c, 0x39, 0xbc, 0xaa, 0xe4, 0xc1, 0x64, 0x3c, 0x1e, 0x8f, 0xfe, 0x80, 0xa3, 0x03, 0x08, - 0x2d, 0x89, 0x0c, 0x9f, 0x0c, 0xd0, 0xb8, 0xeb, 0x8a, 0x7b, 0xe3, 0x42, 0x51, 0x56, 0x3a, 0x99, 0x10, 0x10, 0x3f, - 0x9b, 0xbe, 0xc1, 0xbe, 0xe2, 0x3a, 0xfe, 0xc9, 0xee, 0x27, 0x66, 0x45, 0xab, 0x95, 0x3a, 0x7a, 0xfb, 0xe6, 0xfd, - 0xcb, 0x0f, 0x2f, 0x7f, 0x7d, 0x7e, 0xf6, 0xf2, 0xf5, 0x8b, 0x97, 0xaf, 0x5f, 0x7e, 0xf8, 0xe7, 0x3d, 0x0c, 0xb6, - 0x6f, 0x2b, 0x62, 0xc7, 0xde, 0xbb, 0xc7, 0x78, 0xb5, 0xf8, 0xc2, 0xd9, 0x23, 0x77, 0x8b, 0x05, 0xd8, 0x04, 0xc3, - 0x2d, 0x08, 0xaa, 0x19, 0x8d, 0x4a, 0xdf, 0x13, 0x90, 0xd1, 0xa8, 0x90, 0x8d, 0x87, 0x15, 0x5b, 0x21, 0x17, 0xef, - 0x18, 0x0e, 0x3e, 0xb2, 0xbf, 0x15, 0x67, 0xc2, 0xed, 0x68, 0x6b, 0x56, 0x04, 0x7c, 0xbe, 0xd6, 0xa2, 0xf2, 0xb8, - 0x10, 0xb5, 0xb7, 0xed, 0x73, 0x48, 0xa8, 0x47, 0xe4, 0x3a, 0x78, 0xdf, 0x06, 0xd9, 0xe3, 0x23, 0xef, 0x49, 0x79, - 0x86, 0xfa, 0x1c, 0x0d, 0x1f, 0x35, 0x9e, 0xd1, 0x89, 0xb9, 0x36, 0x3a, 0xd4, 0xb3, 0x02, 0xf6, 0xb7, 0x12, 0x63, - 0xd3, 0x82, 0x95, 0x29, 0x62, 0x7d, 0x38, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x67, 0x38, 0x7e, 0x94, 0x6a, 0x02, 0x69, - 0x51, 0xa0, 0x74, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0xc2, 0xfc, 0x0c, 0x1b, 0x04, 0xd0, 0x5e, 0x76, 0x2c, 0x09, 0x34, - 0x8b, 0xd7, 0xba, 0xfe, 0x79, 0xf9, 0x32, 0xd1, 0xce, 0x17, 0xdf, 0x42, 0x88, 0x61, 0xff, 0x8a, 0xd0, 0x98, 0x70, - 0x37, 0xc9, 0xee, 0xd2, 0x62, 0xee, 0x55, 0x57, 0x31, 0x1e, 0x77, 0x7b, 0xae, 0x14, 0xcd, 0x5b, 0x17, 0xd8, 0x03, - 0x35, 0xaf, 0xe3, 0x25, 0x0b, 0x01, 0x9b, 0xf1, 0xd0, 0x2e, 0x12, 0xe7, 0xf7, 0x4e, 0x27, 0xe4, 0xf0, 0x68, 0xca, - 0x87, 0xac, 0xa4, 0x62, 0xc0, 0xca, 0x7a, 0x87, 0x9a, 0xf3, 0x36, 0x21, 0x17, 0xbb, 0x34, 0x5c, 0x0c, 0xf9, 0x7d, - 0x97, 0xa4, 0x0f, 0xbc, 0xe1, 0x50, 0x6d, 0x9b, 0x8b, 0x21, 0x4d, 0x39, 0xdd, 0xa5, 0x32, 0x20, 0x44, 0xba, 0x8a, - 0x2b, 0x52, 0xeb, 0xa3, 0x2a, 0x75, 0x92, 0x8e, 0xeb, 0x6c, 0xf3, 0x99, 0x4b, 0xb6, 0xba, 0x5d, 0xfb, 0xd7, 0xea, - 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x9f, 0x88, 0x6a, 0x62, 0x20, 0xba, 0x80, 0x0a, 0xfe, 0x09, 0x5e, 0x9e, 0x3c, 0xd2, - 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0x6f, 0xcc, 0x62, 0x6b, 0x89, 0x73, 0x56, 0xf9, 0xce, 0xf2, 0xaa, 0x6c, - 0x85, 0xae, 0x23, 0xd8, 0xbf, 0xc2, 0x8e, 0xbe, 0x7b, 0xdb, 0x00, 0x88, 0x52, 0x58, 0xb9, 0xb3, 0x5f, 0x78, 0x67, - 0xbf, 0xb0, 0x67, 0xbf, 0xdd, 0x04, 0xca, 0x87, 0x15, 0x5a, 0xf6, 0x42, 0x8a, 0xca, 0x34, 0x79, 0xdc, 0xd4, 0x65, - 0x21, 0x2d, 0xe6, 0x87, 0x96, 0x76, 0x3d, 0x1e, 0x53, 0x89, 0xea, 0x91, 0x1f, 0xb0, 0x55, 0x87, 0x25, 0xb9, 0xff, - 0x9e, 0xf9, 0x3f, 0x7b, 0x83, 0xdc, 0x77, 0xb7, 0xfb, 0xbf, 0xb9, 0xd0, 0xc1, 0x6d, 0x2d, 0x15, 0x9e, 0xba, 0x3a, - 0x2e, 0xf0, 0xae, 0x96, 0xde, 0x7f, 0x57, 0x7b, 0x90, 0xe9, 0x65, 0x57, 0x01, 0x6a, 0x90, 0x58, 0x5f, 0xf1, 0x22, - 0x4b, 0x6a, 0xab, 0xd0, 0x78, 0xc3, 0x21, 0xb4, 0x87, 0x77, 0x70, 0x81, 0x1c, 0x96, 0x10, 0xfa, 0xb1, 0x32, 0x02, - 0x40, 0x9f, 0xc5, 0x7e, 0xc3, 0xc3, 0x8c, 0x0c, 0x7c, 0x89, 0x9f, 0x94, 0xbe, 0xb8, 0xf8, 0x70, 0x27, 0x33, 0x41, - 0xaf, 0x12, 0x17, 0x35, 0x57, 0xb6, 0x63, 0x7e, 0xf8, 0x5f, 0x60, 0x34, 0x08, 0xaf, 0x2d, 0xd9, 0xa1, 0xe8, 0x98, - 0xe5, 0x0a, 0x8e, 0xda, 0xd2, 0x95, 0x29, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x0d, 0xc8, 0xbe, 0x90, - 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0x77, - 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0xf5, 0x01, 0xea, 0x6b, 0x6c, 0x49, 0xb2, 0xa9, 0xd8, 0x5f, 0x60, 0x16, 0x0b, 0xc4, - 0xd1, 0xc1, 0x2f, 0xce, 0x17, 0x00, 0xb2, 0x0c, 0xcb, 0x4c, 0x0b, 0x8b, 0x64, 0xaa, 0x7c, 0x64, 0x0b, 0x26, 0x8f, - 0xc7, 0x33, 0xbf, 0xe7, 0x8e, 0xc1, 0x21, 0x24, 0x9a, 0x58, 0xe3, 0x17, 0x3f, 0x0b, 0xc6, 0x71, 0x28, 0x4f, 0x64, - 0xe3, 0xbb, 0x92, 0x44, 0x63, 0x63, 0xaa, 0xac, 0xaf, 0x12, 0xd5, 0x30, 0x21, 0x0f, 0x0b, 0x72, 0x58, 0xd0, 0xa5, - 0x3f, 0x96, 0x98, 0x7e, 0x18, 0x1f, 0x4e, 0xc6, 0xe4, 0x61, 0xfc, 0x70, 0x62, 0xe0, 0x86, 0xfd, 0x1c, 0xf9, 0x70, - 0x49, 0x0e, 0x9b, 0x55, 0x82, 0x29, 0xaa, 0xe9, 0x99, 0x5f, 0x49, 0x32, 0x58, 0x0e, 0xd2, 0x87, 0xad, 0xbc, 0x58, - 0xab, 0x1e, 0xef, 0xf5, 0x31, 0x9f, 0x12, 0xd1, 0xb8, 0x31, 0xac, 0xe9, 0x55, 0xfc, 0xa7, 0x2c, 0x22, 0x29, 0x01, - 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x84, 0x4d, 0xc6, 0xb3, 0x94, - 0xa5, 0xc7, 0x93, 0x27, 0xb3, 0xc9, 0x93, 0xe8, 0x68, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8d, 0xc1, 0xc5, 0x0e, - 0x7e, 0xb3, 0x23, 0x18, 0xba, 0x13, 0x64, 0x09, 0x0b, 0x68, 0xda, 0x97, 0x35, 0x49, 0x0f, 0xe7, 0x85, 0xea, 0x49, - 0x7c, 0x4b, 0xd7, 0x9e, 0x83, 0x8b, 0xdf, 0xc2, 0x0b, 0xd7, 0xc2, 0x8b, 0xdd, 0x16, 0x0a, 0x4d, 0xb6, 0x63, 0xf9, - 0xff, 0xe3, 0x86, 0xb1, 0xef, 0x2e, 0x61, 0x16, 0xd7, 0x75, 0x36, 0x5a, 0x15, 0xb2, 0x92, 0x70, 0x9b, 0x50, 0xa2, - 0xb0, 0x51, 0xbc, 0x5a, 0xe5, 0xda, 0x45, 0x6c, 0x5e, 0x51, 0x00, 0x77, 0x81, 0x38, 0xc5, 0xc0, 0x42, 0x1b, 0x03, - 0xb9, 0x4f, 0xbc, 0x90, 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0xcf, 0x10, 0x8c, 0x51, 0xc5, 0xc9, 0x78, 0xa6, 0xb0, - 0x2e, 0x3e, 0x27, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x7b, 0x34, 0x83, 0x9e, 0x20, 0x72, 0x1e, 0x71, 0xf6, 0x64, 0xf2, - 0x32, 0x70, 0x3f, 0x83, 0x95, 0xfe, 0xba, 0xdb, 0x8c, 0xb5, 0xed, 0xd1, 0xbd, 0x30, 0x42, 0xd1, 0x4f, 0xf8, 0xce, - 0xd4, 0x0b, 0xb8, 0x84, 0x6a, 0x60, 0xd7, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, 0xf4, 0xfb, 0xbd, 0x3f, 0x0d, - 0x34, 0x69, 0xc9, 0x8b, 0x57, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x1f, 0x2b, 0xfb, 0x4c, 0xc7, 0x64, - 0xe6, 0x3f, 0x0e, 0x27, 0x24, 0x6a, 0xbe, 0x26, 0x9f, 0x39, 0x4d, 0x3f, 0x73, 0x45, 0xfb, 0x0f, 0x64, 0xe6, 0x86, - 0x43, 0x86, 0xfa, 0x4b, 0xc7, 0x3c, 0x19, 0xbd, 0x4e, 0xcc, 0x4e, 0x04, 0xab, 0x66, 0x10, 0x85, 0xbd, 0x80, 0x07, - 0x75, 0x2d, 0x8b, 0xa7, 0x30, 0xfb, 0xa0, 0x46, 0x14, 0xc7, 0x6c, 0x3c, 0x0b, 0x65, 0x38, 0x01, 0xfb, 0xde, 0xc9, - 0x18, 0xee, 0x03, 0x32, 0xfc, 0x58, 0x85, 0xd8, 0x39, 0x48, 0xfb, 0x58, 0xa1, 0x62, 0x02, 0x20, 0x02, 0x21, 0x6f, - 0xbf, 0x2f, 0x55, 0x12, 0xbe, 0x2e, 0x31, 0xa5, 0x50, 0x1f, 0xfc, 0x27, 0x52, 0x75, 0xc7, 0xf4, 0xab, 0xf5, 0xe3, - 0xcf, 0x84, 0xe2, 0xd3, 0x5d, 0x4a, 0x7c, 0x0b, 0xc1, 0x9d, 0x0b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0x76, 0x3f, 0xbf, - 0x2b, 0xf6, 0xf3, 0xbb, 0xe2, 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, - 0xf4, 0x9f, 0xf3, 0x89, 0x7b, 0x79, 0xea, 0xab, 0x4c, 0x4c, 0xf7, 0x30, 0xcd, 0x3e, 0x41, 0x41, 0x58, 0xc5, 0x5d, - 0x7a, 0xb2, 0xae, 0xec, 0xad, 0x95, 0x0c, 0x31, 0xcf, 0x3d, 0xac, 0x51, 0x58, 0x79, 0x40, 0xf7, 0xa8, 0xda, 0x20, - 0x4e, 0x04, 0x0f, 0x63, 0x66, 0xa5, 0xef, 0xdb, 0xad, 0x51, 0x61, 0xde, 0xcb, 0x45, 0x41, 0x76, 0xf3, 0xf1, 0x6c, - 0x1c, 0x85, 0xd8, 0x80, 0xff, 0x98, 0xb1, 0x6a, 0xc8, 0xe6, 0x3b, 0x19, 0xa9, 0x1d, 0x93, 0xa7, 0xc9, 0x2e, 0xe9, - 0x1d, 0xf0, 0x0e, 0xf9, 0x79, 0xfd, 0x31, 0x8c, 0xa5, 0xe1, 0xb7, 0xe4, 0x65, 0x5c, 0x64, 0xd5, 0xf2, 0x2a, 0x4b, - 0x90, 0xe9, 0x82, 0x17, 0x5f, 0xcc, 0x74, 0x79, 0x1f, 0xeb, 0x03, 0xc6, 0x53, 0x8a, 0xd7, 0x0d, 0x51, 0xfa, 0xba, - 0xe5, 0x59, 0xa1, 0x2e, 0x4f, 0x2a, 0x66, 0x7b, 0x56, 0x82, 0xd3, 0x29, 0x98, 0xe0, 0xeb, 0x9f, 0xae, 0xf7, 0x09, - 0xe0, 0x82, 0x42, 0xcd, 0x69, 0x21, 0x57, 0x06, 0xcb, 0xc9, 0x42, 0x77, 0x02, 0x66, 0xa8, 0x14, 0x78, 0x81, 0x82, - 0xbf, 0x68, 0x60, 0x44, 0x5f, 0xb8, 0xdf, 0x64, 0x60, 0x90, 0x2e, 0xcd, 0x89, 0x30, 0x76, 0xdc, 0x4e, 0x9c, 0xb6, - 0xa2, 0x9c, 0x71, 0xf6, 0x4e, 0x5d, 0x29, 0xc0, 0x00, 0x6f, 0x73, 0x13, 0x9d, 0x25, 0xe8, 0xb5, 0xa0, 0x74, 0xde, - 0xc0, 0xdd, 0x2c, 0x23, 0x23, 0x5c, 0x7c, 0x58, 0x79, 0x2c, 0xb8, 0x67, 0xbf, 0x90, 0x58, 0x5b, 0x3f, 0x30, 0x66, - 0xf3, 0x82, 0x05, 0x0a, 0x15, 0x28, 0xb0, 0x9c, 0x69, 0x4b, 0xd3, 0x6a, 0xc8, 0x0f, 0x8f, 0xd0, 0xda, 0xb4, 0x1a, - 0xf0, 0xc3, 0xa3, 0x3a, 0xca, 0x8e, 0x21, 0xcb, 0x89, 0x9f, 0x41, 0xbd, 0xae, 0x23, 0x93, 0x62, 0xb2, 0xfb, 0xf5, - 0xa5, 0xfe, 0xa8, 0x6e, 0xc0, 0xf5, 0x03, 0x10, 0xc0, 0x06, 0xe0, 0x10, 0xa8, 0x06, 0x4b, 0x23, 0x82, 0x45, 0x99, - 0x42, 0xfb, 0x1a, 0x7a, 0x6f, 0x34, 0xfc, 0x17, 0xb8, 0x8b, 0xc8, 0x95, 0xff, 0x09, 0x02, 0x7f, 0x45, 0x99, 0x56, - 0xa6, 0xf8, 0x9f, 0x68, 0xf5, 0x0a, 0xe5, 0xac, 0x69, 0xcd, 0x07, 0xd1, 0x9a, 0x08, 0xd5, 0x8c, 0x21, 0xf8, 0xb7, - 0xb2, 0x4c, 0x5b, 0xaa, 0x2a, 0xf5, 0xa1, 0xf1, 0x5a, 0x2b, 0x9c, 0xe5, 0xe3, 0xc8, 0x7b, 0x8d, 0xa1, 0x63, 0x13, - 0x67, 0x29, 0xa7, 0x52, 0x67, 0xaf, 0x0f, 0x65, 0xe4, 0x00, 0xa7, 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x72, 0x9a, 0x38, - 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x03, 0xc2, 0xa2, 0x6c, 0x28, 0x6d, 0x01, 0x26, 0x39, 0x21, 0x64, 0x8a, 0xa1, - 0x28, 0xf2, 0x91, 0xee, 0x87, 0xf5, 0x66, 0x75, 0x5f, 0xbc, 0xd5, 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0x8b, 0xf8, - 0x26, 0x13, 0x97, 0xe0, 0x31, 0x3c, 0x80, 0x2f, 0xc1, 0x4d, 0x2e, 0x65, 0xbf, 0x57, 0x61, 0x8e, 0x6b, 0x0b, 0x18, - 0x34, 0x58, 0x3d, 0x88, 0x0e, 0x97, 0xd2, 0x66, 0x57, 0x01, 0x62, 0x63, 0x0a, 0xb1, 0x2c, 0xd8, 0xda, 0xb2, 0x67, - 0x3f, 0xab, 0xa6, 0xa1, 0x75, 0xc2, 0xa9, 0xb8, 0xcc, 0x21, 0x8a, 0xca, 0x20, 0x06, 0x77, 0x24, 0x8f, 0xcf, 0x7b, - 0x2b, 0xc2, 0x0b, 0x02, 0x6e, 0x65, 0x89, 0x0c, 0x57, 0x74, 0x39, 0xba, 0xa5, 0xeb, 0xd1, 0x0d, 0x1d, 0xd3, 0xc9, - 0xdf, 0xc7, 0x68, 0x91, 0xad, 0x52, 0xef, 0xe8, 0x7a, 0xb4, 0xa4, 0xdf, 0x8e, 0xe9, 0xd1, 0xdf, 0xc6, 0x64, 0x9a, - 0xe3, 0x61, 0x42, 0x2f, 0xc0, 0xb1, 0x8b, 0xd4, 0xe8, 0xa9, 0xe9, 0x1b, 0x1c, 0x56, 0xa3, 0x7c, 0xc8, 0x47, 0x39, - 0xe5, 0xa3, 0x62, 0x58, 0x8d, 0xc0, 0xd3, 0xb1, 0x1a, 0xf2, 0x51, 0x45, 0xf9, 0xe8, 0x7c, 0x58, 0x8d, 0xce, 0x49, - 0xb3, 0xe9, 0x2f, 0x2b, 0x7e, 0x55, 0xb2, 0x35, 0x6c, 0x0b, 0x58, 0xbe, 0x6e, 0x95, 0xe5, 0xa9, 0xbf, 0xaa, 0xcd, - 0xc9, 0x6c, 0x39, 0x7b, 0x7b, 0xdd, 0xe5, 0xc4, 0xe2, 0x71, 0xdb, 0x74, 0xb8, 0xfa, 0x72, 0xa2, 0x4e, 0x7a, 0x85, - 0xfc, 0x30, 0x9e, 0x0a, 0x75, 0x0e, 0x81, 0x99, 0xc4, 0x2c, 0x8c, 0x19, 0x36, 0x53, 0xa7, 0x81, 0x02, 0x27, 0x1b, - 0x79, 0x2e, 0x8a, 0xd9, 0x28, 0xa7, 0xf0, 0x3e, 0x26, 0x24, 0x12, 0x70, 0x56, 0x9d, 0x54, 0xa3, 0x02, 0x62, 0x8e, - 0xb0, 0x10, 0x1f, 0xa1, 0x5f, 0xea, 0x23, 0x0f, 0x09, 0x3c, 0xc3, 0xbe, 0x16, 0x83, 0x18, 0x8e, 0x78, 0x5b, 0x59, - 0x35, 0x0b, 0x13, 0xa8, 0xac, 0x1a, 0x96, 0xa6, 0xb2, 0x82, 0x66, 0xa3, 0xca, 0xaf, 0xac, 0xc2, 0x31, 0x4a, 0x08, - 0x89, 0x4a, 0x5d, 0x19, 0xa8, 0x4f, 0x12, 0x16, 0x96, 0xba, 0xb2, 0x73, 0xf5, 0xd1, 0xb9, 0x5f, 0xd9, 0x39, 0xb8, - 0x90, 0x0e, 0x12, 0xff, 0x2a, 0xb5, 0x4c, 0xdb, 0xd7, 0xc1, 0xc6, 0xaa, 0xa2, 0x1b, 0x7e, 0x5b, 0x15, 0x71, 0x54, - 0x52, 0x17, 0x03, 0x1a, 0x17, 0x46, 0x24, 0xa9, 0x5e, 0xa3, 0xe0, 0x0f, 0x09, 0xa2, 0xd2, 0x18, 0xbc, 0x3a, 0x93, - 0xae, 0x95, 0x5a, 0x51, 0x31, 0x28, 0x07, 0x05, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, 0x19, 0x22, 0x2a, 0x43, 0x79, - 0x83, 0x5f, 0x30, 0x78, 0x32, 0xbb, 0x4c, 0xc3, 0x64, 0x74, 0x47, 0xe3, 0xd1, 0x12, 0xe1, 0x60, 0xd8, 0x45, 0xaa, - 0xf0, 0xd6, 0x57, 0x90, 0x7e, 0x4b, 0xe3, 0xd1, 0x0d, 0x4d, 0xad, 0xcd, 0xa9, 0x81, 0xba, 0xea, 0x8d, 0xe9, 0x6d, - 0x04, 0xaf, 0xef, 0xa2, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x97, 0x22, 0x4a, 0x29, 0x22, 0x10, 0xae, 0x11, 0x39, - 0x70, 0xa9, 0xd1, 0x06, 0xd7, 0x03, 0x28, 0x43, 0xc3, 0x05, 0x2e, 0x07, 0xf1, 0x68, 0xe9, 0x91, 0xa9, 0x54, 0x5f, - 0x64, 0x11, 0x3e, 0xda, 0xd9, 0x68, 0x29, 0x9e, 0x11, 0x0b, 0xe3, 0x0a, 0x86, 0x50, 0x17, 0x56, 0x9a, 0x82, 0xa4, - 0x0b, 0x1c, 0xd9, 0x0b, 0xe3, 0x2a, 0xdc, 0x80, 0x69, 0xd1, 0x1d, 0x98, 0x47, 0x81, 0xc2, 0xc1, 0x25, 0x48, 0x3f, - 0xa1, 0x6c, 0xe7, 0x28, 0x4d, 0x0e, 0x6f, 0x82, 0xd6, 0x3b, 0x13, 0x84, 0xb4, 0xab, 0x9b, 0x6c, 0x49, 0xdf, 0x60, - 0x7b, 0x87, 0x4e, 0x45, 0x05, 0xd5, 0xe7, 0x16, 0x4c, 0x96, 0x6c, 0x10, 0xb6, 0x84, 0xe9, 0x99, 0x5e, 0x03, 0xf6, - 0xf4, 0xe1, 0xd1, 0xce, 0x7c, 0x17, 0xb3, 0xd7, 0x87, 0x65, 0x34, 0x56, 0x16, 0xbc, 0xb9, 0x25, 0x76, 0x4b, 0x36, - 0x9e, 0x2e, 0x8f, 0xcb, 0xe9, 0x12, 0x89, 0x9d, 0xa1, 0x5b, 0x8c, 0xcf, 0x97, 0x0b, 0x9a, 0xe0, 0xd9, 0xc6, 0xaa, - 0xf9, 0xd2, 0xa0, 0xa5, 0xa4, 0x0c, 0xd7, 0xdb, 0x12, 0xfd, 0xff, 0xd5, 0xc5, 0x2f, 0x05, 0x78, 0x09, 0xc6, 0x02, - 0x40, 0xb8, 0x07, 0xd3, 0x82, 0xd4, 0x46, 0xd9, 0x48, 0xd3, 0x30, 0xc5, 0x45, 0x60, 0x52, 0xfa, 0xfd, 0x30, 0x67, - 0x29, 0xf1, 0xa0, 0x43, 0xed, 0x28, 0x5d, 0xa4, 0xbe, 0x10, 0x04, 0x78, 0x24, 0x75, 0x8e, 0x4d, 0xfe, 0x3e, 0x9e, - 0x05, 0x6a, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xe9, 0xb8, 0x9d, 0xae, 0x88, 0xd5, 0xee, 0x31, - 0x0b, 0x71, 0x92, 0x30, 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, - 0x04, 0x91, 0x5a, 0x6d, 0x19, 0x97, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, - 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0x57, 0xcd, 0x59, - 0xd7, 0x50, 0x9a, 0xb8, 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, - 0x82, 0x09, 0x3a, 0x9a, 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x5e, 0x26, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, - 0x0f, 0xaa, 0x93, 0x75, 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, - 0xc7, 0x03, 0x78, 0xcd, 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, - 0x6d, 0xc6, 0xa6, 0x4d, 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, - 0x29, 0x70, 0x32, 0x9b, 0xdb, 0x68, 0x49, 0xef, 0xa2, 0x94, 0xde, 0x44, 0x6b, 0xba, 0x8c, 0x2e, 0x8c, 0x89, 0x71, - 0x52, 0xc3, 0x39, 0x00, 0xad, 0x02, 0x48, 0x3c, 0xf5, 0xeb, 0x1d, 0x4f, 0xaa, 0x70, 0x49, 0x53, 0x70, 0x1b, 0xf6, - 0xed, 0x33, 0xcf, 0x7d, 0x89, 0xd4, 0x06, 0x31, 0xd6, 0xac, 0xa1, 0xe2, 0xc6, 0x5b, 0xf7, 0x91, 0xa8, 0x61, 0xe7, - 0xba, 0xd8, 0x44, 0xd5, 0x70, 0x32, 0x2d, 0x01, 0xb1, 0xb5, 0x1c, 0x0e, 0xdd, 0x11, 0xb2, 0x7b, 0xfc, 0xe8, 0x40, - 0xcf, 0x3d, 0x69, 0xb1, 0x6d, 0x5b, 0xfe, 0xc0, 0x10, 0xa6, 0xf4, 0xf3, 0x47, 0x3e, 0x20, 0x56, 0x5c, 0xc1, 0xd9, - 0x08, 0xd4, 0xd1, 0x0a, 0x9d, 0x7e, 0xaf, 0xc2, 0x42, 0x1f, 0xe0, 0x9b, 0xdb, 0x28, 0xa1, 0x77, 0x51, 0xee, 0x91, - 0xb5, 0x65, 0xcd, 0xe4, 0xf4, 0x2c, 0x0b, 0x79, 0xfb, 0x40, 0x2f, 0x17, 0x00, 0xa2, 0x35, 0x88, 0x7d, 0xa9, 0xeb, - 0x11, 0x38, 0x0d, 0xa1, 0x49, 0x68, 0x04, 0x57, 0x15, 0x84, 0x11, 0x70, 0x25, 0xe1, 0x6f, 0x30, 0x51, 0x81, 0x2f, - 0xc0, 0x45, 0x26, 0x4d, 0x73, 0x1e, 0xd4, 0xfe, 0x48, 0xbe, 0x2a, 0xda, 0xde, 0xae, 0x30, 0x9a, 0x60, 0xec, 0x89, - 0xf6, 0x79, 0xa4, 0x1c, 0xc5, 0x45, 0x12, 0x66, 0xa3, 0x5b, 0x75, 0x9e, 0xd3, 0x6c, 0x74, 0xa7, 0x7f, 0x55, 0x74, - 0x4c, 0x7f, 0xd5, 0x01, 0x6d, 0x94, 0xf4, 0xad, 0xe3, 0x6c, 0x40, 0xeb, 0xc5, 0xd2, 0xf8, 0x5f, 0xcb, 0xd1, 0x2d, - 0x95, 0xa3, 0x3b, 0xdf, 0x92, 0x6a, 0x32, 0x2d, 0x8e, 0x05, 0x1a, 0x52, 0x75, 0x7e, 0x5f, 0x00, 0x3f, 0x57, 0x1a, - 0xdf, 0x69, 0xf3, 0xbd, 0xd7, 0xfe, 0xb3, 0x4e, 0x9e, 0x40, 0xb1, 0x44, 0x05, 0xab, 0x46, 0x60, 0xc7, 0xbe, 0xce, - 0xe3, 0xc2, 0x8c, 0x52, 0x4c, 0xad, 0x49, 0x3f, 0x06, 0xae, 0x98, 0xf6, 0x0a, 0x70, 0xb5, 0x04, 0x27, 0x01, 0x88, - 0xa1, 0x09, 0x7b, 0x76, 0x0c, 0x51, 0xcf, 0x8d, 0x63, 0x94, 0x6c, 0xb8, 0x07, 0xc4, 0x5a, 0xe6, 0xad, 0x5c, 0x02, - 0x12, 0x78, 0xeb, 0x61, 0x52, 0x00, 0xc6, 0x60, 0xb9, 0x24, 0x3a, 0x8f, 0x87, 0x3e, 0xa1, 0x5e, 0x68, 0xd4, 0x09, - 0xd9, 0xd8, 0x12, 0x38, 0xfe, 0xb0, 0x3e, 0x04, 0x82, 0x57, 0x79, 0xae, 0xbf, 0xd2, 0xba, 0xfe, 0x52, 0xe9, 0xb9, - 0x63, 0xb9, 0xae, 0xdf, 0xb5, 0xa9, 0xd1, 0x0b, 0xb0, 0xf0, 0xdd, 0x28, 0xf3, 0x48, 0x6e, 0x11, 0x52, 0x15, 0x58, - 0xa9, 0x5b, 0x48, 0x30, 0xff, 0x4a, 0xce, 0x56, 0x65, 0xbe, 0x7a, 0xe4, 0x5e, 0x39, 0x9b, 0x9e, 0xfe, 0x86, 0x04, - 0xed, 0xae, 0x23, 0xcd, 0xe3, 0x2d, 0x3a, 0x7c, 0x76, 0xad, 0x25, 0xe6, 0x4e, 0xa2, 0xe2, 0xf9, 0x14, 0xb0, 0xd5, - 0xb3, 0xec, 0x4a, 0xf9, 0x58, 0xed, 0xe2, 0xf8, 0x99, 0xf3, 0x27, 0xa9, 0xc2, 0xb5, 0x68, 0x28, 0x41, 0xc0, 0x9b, - 0xc3, 0xd8, 0x15, 0xaa, 0x80, 0x86, 0xe6, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x34, 0x01, 0xd3, 0x52, 0x1e, 0x1d, 0xe0, - 0xd0, 0xe4, 0x51, 0xbb, 0x69, 0x58, 0x19, 0xba, 0xd6, 0xe8, 0x73, 0x5b, 0xe9, 0x8c, 0x37, 0x1b, 0x7e, 0x78, 0x34, - 0xa8, 0xf0, 0x27, 0x69, 0x8e, 0x46, 0x3b, 0x37, 0xdc, 0x69, 0x04, 0x66, 0xae, 0xe4, 0x8a, 0xec, 0x8e, 0x92, 0x97, - 0xdf, 0xd3, 0x0b, 0x0b, 0xe8, 0xcf, 0x7f, 0x2e, 0x26, 0x9c, 0xb4, 0xc4, 0x84, 0x68, 0xe9, 0xa0, 0x45, 0x07, 0x3b, - 0xca, 0x2b, 0xfb, 0x12, 0x2f, 0x9d, 0xe3, 0x7f, 0x5f, 0x8f, 0xb5, 0xab, 0x40, 0x68, 0x75, 0xf2, 0xb0, 0x3d, 0x59, - 0x20, 0x6a, 0x40, 0x35, 0xbb, 0x2a, 0x47, 0x99, 0x76, 0x56, 0x64, 0xd3, 0x90, 0xb9, 0xee, 0x66, 0x69, 0xd8, 0x4c, - 0x76, 0x2c, 0x2c, 0x33, 0x0c, 0xd6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x9a, 0xca, 0x33, 0x9f, 0xcd, - 0x32, 0xe2, 0x05, 0x3a, 0xe7, 0x54, 0x2c, 0x9a, 0xd2, 0xb1, 0x72, 0xbb, 0x2d, 0xd1, 0x58, 0xa2, 0x8c, 0x82, 0xa0, - 0xb6, 0x41, 0xd8, 0x75, 0xe9, 0x9e, 0xf4, 0x69, 0x17, 0x9f, 0x56, 0xa0, 0xef, 0xf1, 0x3e, 0x03, 0x89, 0xa9, 0x27, - 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x24, 0xd5, 0xf8, 0xfc, 0x4a, 0x76, 0xd6, 0xbc, 0x5b, 0x8d, 0x29, 0xfe, - 0x23, 0x75, 0xfb, 0xce, 0x65, 0x68, 0xa2, 0xbf, 0x96, 0x07, 0x2d, 0x85, 0x05, 0xc7, 0x6d, 0xe3, 0xaf, 0xdf, 0x66, - 0x0e, 0x31, 0x2c, 0x5d, 0x0e, 0x6f, 0x42, 0x87, 0xee, 0xae, 0xb2, 0x33, 0xd7, 0x47, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, - 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0xaf, 0x87, 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, - 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0x76, 0xf0, 0x73, 0x58, 0x3d, 0xe4, 0x83, 0x7f, 0xe1, 0x38, - 0xc3, 0xe8, 0x67, 0xca, 0xd0, 0xe7, 0x45, 0x21, 0xaf, 0x54, 0xa7, 0x7c, 0xa1, 0x5b, 0xcb, 0xd4, 0xfb, 0x75, 0xfc, - 0xba, 0x15, 0x20, 0xc6, 0xeb, 0x8a, 0x95, 0xe2, 0x0d, 0xad, 0x30, 0xae, 0x81, 0xdb, 0xe4, 0x50, 0x4b, 0xb5, 0x40, - 0xd4, 0xe5, 0x27, 0x0f, 0x79, 0x64, 0xd4, 0x99, 0xf0, 0xdd, 0x43, 0xee, 0x4b, 0xd7, 0x76, 0x9b, 0xf8, 0xb9, 0xa6, - 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0xee, 0x6f, 0x9e, 0xcd, 0xcf, 0x23, 0xf3, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, 0xb8, - 0xec, 0x18, 0xee, 0x7b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x2e, 0x70, 0x81, 0xbb, 0xc2, 0x80, - 0x21, 0xae, 0x69, 0xc9, 0x9d, 0xb6, 0xb2, 0xf5, 0x91, 0xb7, 0x51, 0x21, 0x58, 0xd7, 0x1d, 0x37, 0x49, 0x0e, 0xc1, - 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0x65, 0x20, 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x50, 0xab, 0x7b, - 0x0d, 0xaf, 0x72, 0x17, 0x79, 0xd6, 0x6f, 0xe6, 0xa5, 0x61, 0x5f, 0xf0, 0x5a, 0x0a, 0x0e, 0x8d, 0xed, 0x56, 0xb8, - 0xc5, 0xe2, 0x1d, 0xad, 0x56, 0xd6, 0xda, 0x6a, 0xaf, 0x95, 0x8a, 0xee, 0x5f, 0x73, 0x9c, 0x38, 0x4b, 0x61, 0xfb, - 0xe1, 0xfd, 0x05, 0xbb, 0x26, 0x80, 0x41, 0x8b, 0xc9, 0x02, 0x25, 0xa8, 0x64, 0xad, 0x6a, 0xb7, 0x53, 0xe2, 0x97, - 0xfb, 0x45, 0x97, 0xd9, 0xce, 0xe3, 0xd7, 0x4d, 0xda, 0x67, 0x3e, 0x47, 0x3f, 0xcc, 0xef, 0xac, 0x93, 0x92, 0x33, - 0x8c, 0x6b, 0xf9, 0xff, 0x55, 0xf4, 0xb2, 0xc8, 0xd2, 0x68, 0x63, 0x78, 0x30, 0x1b, 0x6a, 0xd3, 0x87, 0xc6, 0xa8, - 0xdc, 0xb2, 0x51, 0x44, 0xb4, 0xba, 0x05, 0xc1, 0x8c, 0xe2, 0xbe, 0x44, 0x9b, 0x57, 0xaa, 0x2c, 0xbc, 0xc3, 0x67, - 0x36, 0x7a, 0xc3, 0xf6, 0x84, 0x50, 0xbe, 0x7b, 0x5a, 0x98, 0x55, 0x4b, 0x45, 0x83, 0xed, 0x12, 0xde, 0xc5, 0xa8, - 0xd2, 0x4f, 0x98, 0x6c, 0x59, 0x30, 0xd5, 0xff, 0xef, 0x8b, 0x2c, 0x6d, 0x53, 0x74, 0x60, 0x3a, 0x9b, 0x3e, 0x9d, - 0x74, 0x83, 0xeb, 0x0c, 0x58, 0x44, 0xb0, 0xa5, 0xc2, 0xf1, 0x28, 0xb5, 0x1b, 0x24, 0x4c, 0x04, 0x37, 0x51, 0x2f, - 0x3b, 0x5a, 0xa6, 0x64, 0x55, 0xc0, 0xf3, 0x2b, 0x57, 0x99, 0x8e, 0xa3, 0xa1, 0xdf, 0x3f, 0x4f, 0x4d, 0xe8, 0x57, - 0xea, 0xa5, 0x2a, 0xce, 0xc3, 0xa8, 0x3a, 0x54, 0x18, 0xa3, 0x25, 0x4d, 0xe1, 0x18, 0xcc, 0x2e, 0xc2, 0x14, 0x2f, - 0x67, 0x9b, 0x84, 0x7d, 0xc1, 0x40, 0x2e, 0xb5, 0x41, 0xbd, 0xa6, 0x44, 0x6b, 0xd6, 0xde, 0xcc, 0x29, 0xa1, 0x17, - 0xac, 0xf4, 0xef, 0x42, 0x6b, 0x10, 0x28, 0xca, 0x66, 0xca, 0xf4, 0x4c, 0xb7, 0xf3, 0x82, 0x26, 0xb4, 0xa0, 0x2b, - 0x52, 0x83, 0xbe, 0xd7, 0xc9, 0xd9, 0xd1, 0xc9, 0xce, 0xcc, 0x7a, 0xcc, 0x8a, 0xe1, 0x64, 0x1a, 0xc3, 0x35, 0x2d, - 0x76, 0xd7, 0xb4, 0x65, 0xf3, 0xc6, 0xd5, 0xd8, 0x38, 0x0d, 0xda, 0x05, 0xd2, 0x36, 0xcd, 0xed, 0xa7, 0x1e, 0xb7, - 0xbf, 0xae, 0xd9, 0x72, 0xda, 0x5b, 0x6f, 0xb7, 0xbd, 0x14, 0x6c, 0x44, 0x3d, 0x3e, 0x7e, 0xad, 0xa4, 0xeb, 0x96, - 0xcb, 0x4f, 0xe1, 0xd9, 0xe3, 0xeb, 0x97, 0x3e, 0xb8, 0x1c, 0xad, 0xda, 0xdc, 0xfd, 0x72, 0x17, 0x59, 0xee, 0x8b, - 0x86, 0x96, 0xeb, 0x19, 0x6a, 0x92, 0x67, 0xa3, 0xbd, 0x43, 0x2d, 0x58, 0xce, 0xba, 0x09, 0x4f, 0x0c, 0x76, 0xec, - 0x55, 0x63, 0x73, 0x54, 0xe6, 0x92, 0xd5, 0x20, 0x81, 0x3e, 0xc9, 0x33, 0x4d, 0xff, 0x20, 0xc3, 0x7c, 0x74, 0x4b, - 0x73, 0xc0, 0x15, 0xab, 0xec, 0x25, 0x83, 0xd4, 0x55, 0x7b, 0x89, 0x2b, 0x5f, 0xe1, 0x90, 0x6c, 0xf0, 0xc9, 0x30, - 0x55, 0x9f, 0x5d, 0xf2, 0xe0, 0xff, 0x6d, 0xd5, 0x2a, 0x3d, 0x37, 0xc9, 0x0d, 0xc7, 0xbf, 0x4e, 0xda, 0x3e, 0x26, - 0x06, 0x09, 0x78, 0x6a, 0x17, 0x43, 0x35, 0xaa, 0x8a, 0x58, 0x94, 0xb9, 0x89, 0x39, 0xb6, 0xb7, 0x6b, 0xe8, 0xa0, - 0x0c, 0x7e, 0xdd, 0xf0, 0x89, 0xb9, 0x03, 0x5b, 0x81, 0x8e, 0x4e, 0x34, 0x97, 0x61, 0x66, 0x2e, 0xc3, 0xb4, 0x6b, - 0xab, 0xc0, 0xf0, 0xaa, 0xad, 0x92, 0x28, 0x57, 0xa3, 0x1e, 0x37, 0xb3, 0xd4, 0xec, 0x45, 0xde, 0xbd, 0x26, 0x3d, - 0x89, 0x3f, 0x5d, 0x7a, 0xf2, 0x7a, 0x18, 0x10, 0xf9, 0x25, 0x4b, 0xc3, 0x35, 0x0a, 0x82, 0x53, 0xab, 0x1d, 0x48, - 0xf3, 0x11, 0x20, 0xf3, 0xe3, 0x34, 0x7c, 0xa7, 0xc5, 0x39, 0x64, 0xa3, 0x34, 0x4e, 0x6c, 0x69, 0xd4, 0x43, 0x70, - 0xe7, 0xbd, 0xe2, 0x31, 0x04, 0x3e, 0xfc, 0x80, 0x9b, 0x41, 0x45, 0xb7, 0x25, 0x26, 0x4a, 0x9b, 0x47, 0xdd, 0xf2, - 0x51, 0x43, 0xa8, 0x64, 0x65, 0x78, 0x09, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x39, 0x81, 0xcc, 0xb0, 0x38, 0x3c, 0x1a, - 0xa6, 0x4a, 0x50, 0x34, 0x94, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xc5, 0x20, 0xd5, 0x95, 0xa9, 0x17, - 0x83, 0x54, 0xdf, 0xaa, 0x48, 0x7d, 0x96, 0x85, 0x15, 0xd5, 0x2d, 0xa2, 0x63, 0x3a, 0x94, 0x74, 0x69, 0x76, 0x6a, - 0xae, 0xa5, 0x17, 0x6a, 0x39, 0x3e, 0xd5, 0x69, 0x30, 0x8a, 0xef, 0x5d, 0x8a, 0x7e, 0xab, 0xf6, 0xb3, 0xff, 0x16, - 0x53, 0x6a, 0xc4, 0xa6, 0xf6, 0x16, 0x31, 0xac, 0xda, 0x0f, 0x59, 0x95, 0x83, 0x76, 0x17, 0x94, 0x8d, 0x95, 0x71, - 0x9e, 0x6f, 0x04, 0x33, 0x07, 0x6d, 0x63, 0xd5, 0xf4, 0xa1, 0x37, 0x62, 0xd4, 0xde, 0x98, 0x6a, 0xdc, 0x13, 0xf8, - 0x69, 0x83, 0xa6, 0x7b, 0x91, 0xe7, 0xa8, 0x47, 0xde, 0xfd, 0xcf, 0x1c, 0xd9, 0x99, 0x7c, 0x16, 0xcb, 0xa4, 0x6e, - 0x1f, 0x93, 0x60, 0xa1, 0xea, 0x18, 0x5d, 0xb8, 0x91, 0x29, 0xed, 0xe7, 0xce, 0xf4, 0x23, 0x9e, 0xc9, 0xfd, 0x76, - 0x68, 0xd4, 0x97, 0x86, 0xb5, 0xa4, 0x88, 0xfa, 0x82, 0xde, 0x9a, 0xea, 0xe8, 0x88, 0x7a, 0x1d, 0x81, 0xd5, 0x15, - 0x6d, 0x50, 0x03, 0x30, 0x19, 0xd7, 0xb6, 0x36, 0x9f, 0x83, 0xa9, 0xad, 0xaa, 0xe0, 0x09, 0xdd, 0x15, 0x4a, 0xf7, - 0x26, 0x75, 0xdd, 0x1a, 0x62, 0x0b, 0x18, 0x10, 0xb8, 0xd1, 0x53, 0xd3, 0x1f, 0x34, 0x51, 0x01, 0x68, 0xd0, 0xb8, - 0x9d, 0xe9, 0x1c, 0x89, 0x7e, 0xa7, 0x36, 0x6d, 0x33, 0xd5, 0xab, 0xca, 0x07, 0x50, 0xf1, 0x67, 0xe9, 0xec, 0xc2, - 0x8c, 0x58, 0x00, 0xe3, 0x1e, 0x38, 0x53, 0xbd, 0xd3, 0x0c, 0xac, 0x27, 0xf2, 0x3c, 0x2b, 0x79, 0x22, 0x05, 0xcc, - 0x88, 0xbc, 0xba, 0x92, 0x02, 0x86, 0x41, 0x0d, 0x00, 0x5a, 0x34, 0x97, 0xd1, 0x84, 0x3f, 0xaa, 0xe9, 0xbe, 0x3c, - 0xfc, 0x91, 0xce, 0xf5, 0xcd, 0xb8, 0x06, 0x43, 0xe5, 0x75, 0xc5, 0x77, 0x32, 0x7d, 0xc3, 0x1f, 0x7b, 0x99, 0x96, - 0x72, 0x5d, 0xec, 0x64, 0x79, 0xf4, 0x0d, 0x7f, 0xa2, 0xf3, 0x1c, 0x3d, 0xae, 0x69, 0x1a, 0xdf, 0xed, 0x64, 0xf9, - 0xfb, 0x37, 0x8f, 0x6d, 0x9e, 0x47, 0xe3, 0x9a, 0xde, 0x70, 0xfe, 0xd1, 0x65, 0x9a, 0xe8, 0xaa, 0xc6, 0x8f, 0xff, - 0x6e, 0x73, 0x3d, 0xae, 0xe9, 0x95, 0x14, 0xd5, 0x72, 0xa7, 0xa8, 0xa3, 0x6f, 0x8e, 0xfe, 0xce, 0xbf, 0x31, 0xdd, - 0x3b, 0xaa, 0xe9, 0x5f, 0xeb, 0xb8, 0xa8, 0x78, 0xb1, 0x53, 0xdc, 0xdf, 0xfe, 0xfe, 0xf7, 0xc7, 0x36, 0xe3, 0xe3, - 0x9a, 0xde, 0xf1, 0xb8, 0xa3, 0xed, 0x93, 0x27, 0x8f, 0xf9, 0xdf, 0xea, 0x9a, 0xfe, 0xc6, 0xfc, 0xe0, 0xa8, 0xa7, - 0x99, 0xa7, 0x87, 0xcf, 0x65, 0x13, 0x35, 0x60, 0xe8, 0xa1, 0x01, 0x2c, 0xa5, 0x55, 0xd3, 0xec, 0xf1, 0xca, 0x05, - 0xb7, 0xef, 0xb3, 0x38, 0x8d, 0x57, 0x70, 0x10, 0x6c, 0xd0, 0x38, 0xab, 0x00, 0x4e, 0x15, 0x78, 0xcf, 0xa8, 0xa4, - 0x59, 0x29, 0x7f, 0xe3, 0xfc, 0x23, 0x0c, 0x1a, 0x42, 0xda, 0xa8, 0xc8, 0x40, 0x6f, 0x56, 0x3a, 0xb2, 0x11, 0xfa, - 0x6f, 0x36, 0xe3, 0xe0, 0xf8, 0x30, 0x7a, 0xfd, 0x7e, 0x58, 0x30, 0x11, 0x16, 0x84, 0xd0, 0x3f, 0xc3, 0x02, 0x1c, - 0x4a, 0x0a, 0xe6, 0xe5, 0x33, 0xbe, 0xe7, 0xda, 0x28, 0x2c, 0x04, 0xd1, 0x5d, 0x64, 0x1f, 0x50, 0xf5, 0xe8, 0x3b, - 0x74, 0x43, 0xbc, 0xac, 0xb0, 0x60, 0x68, 0x55, 0x03, 0x33, 0x04, 0xc5, 0xbf, 0xe2, 0xa1, 0x04, 0x9f, 0x78, 0x80, - 0x8f, 0x1e, 0x93, 0x19, 0x57, 0xd7, 0xda, 0x37, 0x17, 0x61, 0x41, 0x03, 0xdd, 0x76, 0x08, 0x3a, 0x10, 0xf9, 0x2f, - 0xc0, 0x53, 0x60, 0xe0, 0xc3, 0xc2, 0xae, 0x3b, 0xf0, 0x7c, 0x7e, 0x33, 0xac, 0xa3, 0x0b, 0x3f, 0xfa, 0x9b, 0x75, - 0x61, 0xcf, 0xc8, 0x54, 0x1e, 0x97, 0xc3, 0xc9, 0x74, 0x30, 0x90, 0x2e, 0x8e, 0xdb, 0x69, 0x36, 0xff, 0x6d, 0x2e, - 0x17, 0x0b, 0xd4, 0x7d, 0xe3, 0xbc, 0xce, 0xf4, 0xdf, 0x48, 0x3b, 0x1f, 0xbc, 0x3a, 0xfd, 0xfd, 0xec, 0xfd, 0xe9, - 0x0b, 0x70, 0x3e, 0xf8, 0xf0, 0xfc, 0xfb, 0xe7, 0xef, 0x54, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, 0x93, 0xfa, 0x84, - 0x7c, 0x58, 0x91, 0xc3, 0x30, 0x7e, 0x58, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, 0x51, 0xdb, 0xdf, - 0xe5, 0x70, 0xe2, 0x81, 0x59, 0xdc, 0x36, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x79, 0xe2, 0xf5, 0x83, 0x93, - 0xa9, 0x74, 0x6c, 0x61, 0xc1, 0xa0, 0x6c, 0x68, 0xd3, 0x69, 0x36, 0x2f, 0x16, 0xb6, 0x5d, 0x6e, 0x81, 0x8c, 0xd2, - 0xec, 0xe2, 0x22, 0x54, 0xd0, 0xd5, 0x27, 0xa0, 0x01, 0x30, 0x8d, 0x2a, 0x5c, 0x8b, 0xf8, 0xcc, 0x2f, 0x3f, 0x1a, - 0x7b, 0xcd, 0xbb, 0x46, 0xdd, 0x93, 0x69, 0x56, 0xd5, 0x18, 0xd0, 0xc1, 0x84, 0x72, 0x37, 0xe8, 0x26, 0x98, 0x8c, - 0x6a, 0xcb, 0x6f, 0xf3, 0x6a, 0x61, 0x9a, 0xe3, 0x86, 0xa1, 0xf2, 0x4a, 0xbe, 0x90, 0x0d, 0x44, 0x06, 0x92, 0x61, - 0xd8, 0xa3, 0x31, 0x8a, 0xd4, 0x0f, 0x76, 0xbd, 0xe3, 0x37, 0xb9, 0x84, 0x68, 0x8a, 0x19, 0x48, 0xe7, 0x4f, 0x85, - 0x72, 0x2e, 0x97, 0x8c, 0xcf, 0xc5, 0xe2, 0x04, 0xdc, 0xce, 0xe7, 0x62, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, 0x95, - 0x80, 0xdd, 0x8b, 0x83, 0xf0, 0xed, 0x84, 0x36, 0xb0, 0x1b, 0x48, 0xb2, 0x41, 0x69, 0x57, 0x1a, 0xa2, 0xdc, 0x29, - 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xaa, 0x79, 0xd5, 0xf6, 0x64, 0x33, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x93, 0xd3, 0xf8, - 0x98, 0x15, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x0a, 0x42, 0x12, 0xc6, 0xe7, 0xf1, 0x82, 0x26, - 0x28, 0x25, 0x08, 0x21, 0xe4, 0xc7, 0x08, 0x6d, 0x73, 0x60, 0xc9, 0xdb, 0xed, 0xe7, 0xe9, 0xe7, 0x76, 0x0c, 0x97, - 0x51, 0x11, 0xba, 0x41, 0x67, 0x0d, 0xff, 0x46, 0x54, 0xd0, 0x18, 0x2b, 0x86, 0x20, 0xe0, 0x05, 0x46, 0x25, 0x2c, - 0x48, 0xcc, 0x2a, 0x88, 0x22, 0x50, 0xce, 0xe3, 0x05, 0x2b, 0x68, 0xd3, 0xe6, 0x34, 0xd6, 0x26, 0x41, 0x3d, 0x87, - 0xa5, 0x76, 0x20, 0x95, 0x0a, 0xb1, 0xc7, 0x67, 0x22, 0xba, 0xd1, 0x86, 0x06, 0x80, 0x02, 0xa5, 0xe4, 0xe2, 0x37, - 0x5f, 0xee, 0xe1, 0xa6, 0xa0, 0xff, 0xd9, 0xc6, 0x44, 0x3b, 0xcb, 0xd5, 0xa1, 0x37, 0x5f, 0xd0, 0x38, 0xcf, 0x21, - 0x14, 0x9b, 0x41, 0x20, 0x17, 0x59, 0x05, 0x11, 0x2d, 0xee, 0x02, 0x13, 0x12, 0x0e, 0xda, 0xf4, 0x0b, 0xa4, 0x36, - 0xc4, 0xe4, 0xca, 0x13, 0x03, 0xbb, 0xad, 0x12, 0x04, 0x1c, 0xe9, 0x79, 0xf6, 0xa9, 0x89, 0xb1, 0xa6, 0xa9, 0x99, - 0x89, 0xb7, 0xa1, 0x10, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xc5, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, 0x9d, 0x8b, - 0x33, 0xaf, 0x66, 0x1e, 0x91, 0x53, 0x4f, 0x73, 0x44, 0xbf, 0xe4, 0x61, 0x35, 0xd2, 0xc9, 0x18, 0x2b, 0x89, 0x83, - 0xde, 0x06, 0x0b, 0xe6, 0x84, 0xae, 0x78, 0x68, 0xf9, 0xf8, 0x17, 0xc8, 0x64, 0x94, 0xd4, 0x58, 0xd1, 0x95, 0x16, - 0x23, 0xce, 0x6b, 0x98, 0xa5, 0xc9, 0x8a, 0x2e, 0x16, 0x9a, 0x34, 0x0b, 0x65, 0x1a, 0xe0, 0x13, 0x68, 0x31, 0x72, - 0x0f, 0x35, 0x6d, 0x20, 0x34, 0xec, 0x0e, 0x01, 0x1f, 0xb9, 0x87, 0x0e, 0xff, 0x3f, 0xcf, 0x2e, 0x10, 0x69, 0xef, - 0xd2, 0x44, 0xc6, 0x23, 0x75, 0x03, 0x07, 0xc5, 0xf8, 0xd8, 0x37, 0x13, 0xbf, 0x70, 0x46, 0xef, 0x93, 0xca, 0x77, - 0xf8, 0x60, 0xf9, 0xe3, 0x4d, 0xcd, 0xac, 0x8c, 0x60, 0x3d, 0x6c, 0xb7, 0xb8, 0x20, 0xda, 0x2e, 0x80, 0xd4, 0x33, - 0x5e, 0x2d, 0x7c, 0xe3, 0xd5, 0x78, 0x8f, 0xf1, 0xaa, 0xb3, 0xc2, 0x0a, 0x73, 0xb2, 0x41, 0x7d, 0x96, 0x92, 0xe7, - 0xe7, 0x28, 0x13, 0x6c, 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, - 0x0e, 0x23, 0x81, 0xaa, 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, - 0x03, 0xa1, 0xa1, 0xb1, 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xed, 0xb6, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, - 0xac, 0x46, 0x13, 0xe0, 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, - 0x49, 0x66, 0x65, 0x34, 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, - 0xba, 0xcc, 0x92, 0xcc, 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, - 0x90, 0x1f, 0x40, 0x19, 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, - 0x64, 0x57, 0xbc, 0xac, 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0x6c, 0x9f, 0xdb, 0x1e, 0x15, 0xe6, 0xd5, 0xeb, 0xe7, - 0xdf, 0x9f, 0x36, 0x5e, 0xed, 0x22, 0x8e, 0x86, 0x60, 0x5b, 0x31, 0xc6, 0xe8, 0x2d, 0x3e, 0x0d, 0x26, 0xca, 0x35, - 0x02, 0xbd, 0x4b, 0x41, 0xbf, 0xfd, 0xa5, 0x9e, 0x80, 0x57, 0x5c, 0x2f, 0xbf, 0xe4, 0x23, 0x60, 0x89, 0x0a, 0x3d, - 0x2b, 0xcc, 0xcd, 0xca, 0x6c, 0x6f, 0xb7, 0x22, 0x33, 0xed, 0x4a, 0x23, 0x03, 0xf1, 0x6a, 0x3b, 0x8c, 0x85, 0x4b, - 0xd7, 0x74, 0x3b, 0xd8, 0xd5, 0xd2, 0xb3, 0x44, 0xde, 0x6e, 0x4b, 0xe8, 0x90, 0x1d, 0x70, 0xef, 0x65, 0x7c, 0x0b, - 0x2f, 0x4b, 0xaf, 0x9b, 0xcd, 0xe0, 0x09, 0x60, 0x26, 0x5c, 0x38, 0xcb, 0xe2, 0x98, 0x65, 0x49, 0xa8, 0x62, 0x73, - 0x35, 0x44, 0xde, 0x8a, 0xd0, 0x9a, 0xfd, 0x15, 0x8a, 0x11, 0xd8, 0x9d, 0xbc, 0xff, 0x98, 0xad, 0x66, 0x6b, 0x40, - 0xcd, 0xbf, 0xca, 0x04, 0xd0, 0x5c, 0xbb, 0x16, 0x6c, 0x53, 0x68, 0x73, 0x5d, 0x3f, 0x8d, 0x57, 0x71, 0x02, 0xaa, - 0x1b, 0xf0, 0x16, 0xb9, 0xd5, 0xa2, 0x2b, 0x83, 0x2e, 0x4a, 0xef, 0x29, 0xc7, 0x92, 0x42, 0x47, 0xdf, 0x7b, 0x42, - 0x9d, 0x7b, 0x06, 0x70, 0x49, 0xa3, 0xe6, 0xa9, 0x96, 0x32, 0x16, 0x00, 0x0b, 0x1d, 0xcc, 0x14, 0xd9, 0x8a, 0xae, - 0x0d, 0x26, 0x05, 0xbc, 0x35, 0xc0, 0x1f, 0x22, 0xab, 0xd4, 0x5d, 0xb1, 0x0c, 0x4b, 0xcf, 0xfe, 0xba, 0xdf, 0x8f, - 0x3d, 0xfb, 0xeb, 0x95, 0xa6, 0x75, 0x71, 0xbb, 0x01, 0xa4, 0xc6, 0x00, 0x22, 0xa7, 0x7a, 0x20, 0x4c, 0x44, 0xb1, - 0xa6, 0xef, 0xdf, 0xa9, 0xc9, 0xa2, 0x40, 0xe8, 0x77, 0xea, 0xf5, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd8, 0xc9, 0x40, - 0x9b, 0x7d, 0x40, 0x40, 0x54, 0x3f, 0x23, 0x9b, 0x2f, 0x94, 0x73, 0xb1, 0x0a, 0x1f, 0x3e, 0xa6, 0x10, 0x50, 0xb8, - 0xa3, 0x46, 0xe7, 0x6d, 0x88, 0x04, 0xca, 0x0a, 0x45, 0xac, 0x79, 0xb1, 0x96, 0x84, 0xcc, 0xc7, 0x0b, 0x14, 0x5c, - 0x39, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x32, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, 0x07, 0x72, - 0xdc, 0xc9, 0xd4, 0xd8, 0x53, 0x8d, 0x1a, 0x04, 0x93, 0x11, 0x04, 0x86, 0x1b, 0x7e, 0xc1, 0xc7, 0x47, 0x0b, 0x02, - 0x2a, 0x32, 0x6b, 0x16, 0x62, 0x5e, 0x1c, 0x3f, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x93, 0x29, 0x67, 0x70, 0x88, 0xd2, - 0x31, 0xc8, 0x68, 0x05, 0xfc, 0x16, 0xea, 0x77, 0xeb, 0xc4, 0xf7, 0xa1, 0x5f, 0x05, 0xbd, 0x88, 0x81, 0xe1, 0x88, - 0x26, 0x87, 0x21, 0x1f, 0x4c, 0x06, 0xa0, 0x2d, 0xf1, 0x76, 0x5f, 0x4b, 0x2b, 0x6e, 0x4e, 0x97, 0x4e, 0xf7, 0x4f, - 0xda, 0x04, 0x49, 0xa4, 0x92, 0x95, 0x8a, 0x18, 0x40, 0x28, 0x4b, 0xb5, 0x4d, 0xd6, 0x60, 0x59, 0x61, 0x96, 0x34, - 0x37, 0x28, 0x89, 0xbb, 0x9b, 0x81, 0x63, 0xd4, 0xac, 0xd3, 0xb0, 0x6c, 0xb9, 0x51, 0x03, 0x7c, 0x4e, 0xc2, 0x0a, - 0x7b, 0xc3, 0x99, 0x49, 0xef, 0x4c, 0x87, 0xab, 0x63, 0xce, 0x5e, 0x71, 0x04, 0xe3, 0x48, 0xf0, 0xc6, 0x43, 0x97, - 0x4c, 0x43, 0x45, 0xa6, 0x8c, 0x83, 0x69, 0x0f, 0x70, 0xef, 0x39, 0x18, 0x87, 0xb1, 0x41, 0x65, 0x49, 0x7d, 0xea, - 0xdd, 0x85, 0x40, 0x90, 0xd6, 0x7a, 0x99, 0xcf, 0xf0, 0xf4, 0x8c, 0x50, 0xf6, 0x87, 0x1c, 0xbe, 0x00, 0x3b, 0x0a, - 0x72, 0x32, 0xe1, 0x4f, 0x1e, 0xee, 0x06, 0xaa, 0xe2, 0x83, 0xe0, 0x20, 0x16, 0xe9, 0x41, 0x30, 0x10, 0xf0, 0xab, - 0xe0, 0x07, 0x95, 0x94, 0x07, 0x17, 0x71, 0x71, 0x10, 0xaf, 0xe2, 0xa2, 0x3a, 0xb8, 0xc9, 0xaa, 0xe5, 0x81, 0xe9, - 0x10, 0x40, 0xf3, 0x06, 0x83, 0x78, 0x10, 0x1c, 0x04, 0x83, 0xc2, 0x4c, 0xed, 0x8a, 0x95, 0x8d, 0xe3, 0xcc, 0x84, - 0x28, 0x0b, 0x9a, 0x01, 0xc2, 0x1a, 0xa7, 0x01, 0xf0, 0xa9, 0x6b, 0x96, 0xd2, 0x0b, 0x0c, 0x37, 0x20, 0xa6, 0x6b, - 0xe8, 0x03, 0xf0, 0xc8, 0x6b, 0x1a, 0xc3, 0x12, 0xb8, 0x18, 0x0c, 0xc8, 0x05, 0x44, 0x2e, 0x58, 0x53, 0x1b, 0xc4, - 0x21, 0x5c, 0x2b, 0x3b, 0xed, 0x5d, 0x60, 0xa6, 0xed, 0x16, 0x10, 0x95, 0x27, 0xa4, 0xdf, 0xb7, 0xdf, 0x50, 0xff, - 0x82, 0xbd, 0x04, 0xfb, 0xab, 0xa2, 0x0a, 0x73, 0xa9, 0x34, 0xdf, 0x97, 0xec, 0x64, 0xa0, 0x22, 0x0e, 0xef, 0x38, - 0x52, 0xb4, 0x51, 0xb9, 0x2c, 0x7b, 0xb2, 0x6c, 0xf8, 0x4a, 0x5c, 0x71, 0xe7, 0xc7, 0x55, 0x49, 0x99, 0x57, 0xd9, - 0x4a, 0xb1, 0x7f, 0x33, 0xae, 0xb9, 0x3f, 0xb0, 0xfe, 0x6c, 0xbe, 0x82, 0x6b, 0xab, 0xf7, 0xae, 0xc9, 0x35, 0x22, - 0x67, 0x09, 0xe5, 0x92, 0xda, 0xe6, 0xe1, 0x2d, 0x7d, 0x9f, 0x5f, 0x7d, 0x9b, 0xe9, 0x34, 0x3e, 0xab, 0xb0, 0x70, - 0x21, 0x5a, 0x11, 0x1c, 0x1a, 0x72, 0xd1, 0x3c, 0x02, 0xcc, 0xb5, 0xcf, 0x56, 0x50, 0x90, 0xfa, 0xac, 0x42, 0xef, - 0x56, 0x48, 0x78, 0xa1, 0xd9, 0xa5, 0xfb, 0x81, 0x94, 0x71, 0x7b, 0x68, 0x09, 0x93, 0x96, 0x17, 0xe1, 0xbd, 0xd7, - 0xdc, 0xe4, 0x9e, 0x85, 0x18, 0xbd, 0xc8, 0xb3, 0x13, 0x30, 0xd6, 0x5d, 0xb2, 0xb3, 0xe1, 0x89, 0xdf, 0xf0, 0x9c, - 0xb5, 0x68, 0x34, 0x5d, 0xb2, 0xa4, 0xdf, 0x8f, 0xc1, 0xc4, 0x3b, 0x65, 0x39, 0xfc, 0xca, 0x17, 0x74, 0xcd, 0x00, - 0x53, 0x8c, 0x5e, 0x40, 0x42, 0x8a, 0x48, 0x24, 0x6b, 0x75, 0x92, 0x7c, 0xa6, 0xbb, 0x00, 0x8c, 0x7e, 0x31, 0x4b, - 0xa3, 0xe5, 0x5e, 0x33, 0x0b, 0x24, 0xcf, 0xd0, 0x77, 0x1d, 0x6c, 0x6f, 0xec, 0x83, 0x94, 0xf3, 0x63, 0x31, 0x1d, - 0x0c, 0x38, 0xd1, 0x70, 0xe3, 0xa5, 0x12, 0xd7, 0xea, 0x16, 0x77, 0x0c, 0x63, 0xa9, 0x6f, 0x8b, 0x18, 0x1c, 0xb0, - 0x8b, 0x56, 0x76, 0xfb, 0x00, 0xfb, 0xca, 0xf1, 0x2e, 0x55, 0x76, 0xa7, 0xc7, 0x4c, 0x73, 0xd9, 0x6a, 0xd2, 0x49, - 0xc5, 0x7e, 0x22, 0xdf, 0xe4, 0x0e, 0xba, 0x5c, 0x8e, 0x35, 0x6f, 0x39, 0x00, 0x15, 0xfd, 0x48, 0x51, 0xdd, 0x2f, - 0x70, 0x84, 0xb9, 0xb7, 0x6e, 0xf3, 0xc9, 0xa1, 0x29, 0x70, 0x88, 0x3c, 0x69, 0xa3, 0x29, 0xa0, 0x7b, 0x17, 0x0f, - 0xbb, 0xfa, 0x6d, 0xe9, 0x2e, 0x50, 0xa2, 0x9d, 0x8a, 0x1b, 0x7e, 0x4c, 0xd4, 0xe9, 0x4c, 0x1b, 0x42, 0xff, 0xca, - 0x88, 0xfb, 0x4b, 0xe3, 0x2a, 0xde, 0xf4, 0x2e, 0x9f, 0x71, 0xa8, 0xb3, 0x1b, 0x42, 0x01, 0xb8, 0x6a, 0x4f, 0xa7, - 0x6e, 0x0c, 0xe9, 0x95, 0x12, 0xdd, 0x06, 0x07, 0xdb, 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, - 0x43, 0x39, 0x88, 0x1f, 0x16, 0x74, 0x19, 0x89, 0x87, 0xc5, 0x20, 0x7e, 0x28, 0xeb, 0x7a, 0xf7, 0x5c, 0xd9, 0xdf, - 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x09, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0xf0, 0x44, 0xb6, 0x96, 0x3e, - 0x74, 0x6e, 0xf7, 0xb1, 0x65, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0xd9, 0xe6, 0xd1, 0x87, 0x53, 0x20, - 0xa1, 0xdb, 0x6d, 0xb3, 0xae, 0xd6, 0x80, 0x62, 0x1a, 0x8e, 0xf9, 0x61, 0x31, 0xba, 0xf1, 0xdd, 0xf5, 0x0f, 0x8b, - 0xd1, 0x92, 0x0c, 0x27, 0x66, 0xf2, 0xe3, 0x93, 0xf1, 0x2c, 0x8e, 0x26, 0x75, 0xc7, 0x69, 0xa1, 0xf1, 0x4f, 0xbd, - 0x5b, 0x28, 0x02, 0xa7, 0x62, 0x04, 0x47, 0x4e, 0x85, 0x72, 0x52, 0x6a, 0x60, 0xf8, 0x1f, 0x54, 0x3b, 0xda, 0xb4, - 0x57, 0x71, 0x95, 0x2c, 0x33, 0x71, 0xa9, 0xc3, 0x87, 0xeb, 0xe8, 0xe2, 0x36, 0xa0, 0x9d, 0x77, 0x99, 0x76, 0xfc, - 0x3a, 0x69, 0xd0, 0x13, 0x57, 0x33, 0x03, 0x6e, 0xdd, 0x8f, 0xd0, 0x0c, 0x81, 0xd1, 0xf2, 0xfc, 0x2d, 0x62, 0x6e, - 0xff, 0xaa, 0x6c, 0x7e, 0x15, 0xed, 0x73, 0x64, 0xa4, 0x6c, 0x93, 0x91, 0x0a, 0x8c, 0x30, 0xa5, 0x48, 0xe2, 0x2a, - 0x84, 0x40, 0xf6, 0x5f, 0x52, 0x5c, 0x8b, 0xa5, 0xf7, 0x1a, 0x84, 0x09, 0xb6, 0x0b, 0xda, 0xaf, 0x6e, 0xe7, 0xb6, - 0xd2, 0x62, 0x8f, 0xd4, 0xf7, 0xb9, 0xb3, 0x5d, 0xd1, 0xe4, 0xef, 0xcb, 0x06, 0xb4, 0x01, 0x44, 0xb9, 0xaf, 0x8f, - 0x4a, 0xe0, 0x64, 0xc4, 0x0d, 0x25, 0x46, 0x2f, 0xe8, 0xea, 0x44, 0xee, 0xd9, 0xa9, 0x79, 0x53, 0x31, 0x53, 0x71, - 0xe5, 0x9b, 0x3d, 0xf3, 0x1f, 0x0c, 0x05, 0x2d, 0xc1, 0xc0, 0xdb, 0x9c, 0xf1, 0xe8, 0x40, 0x77, 0x63, 0x74, 0x5a, - 0xb0, 0x59, 0x50, 0x97, 0x75, 0xd3, 0xc6, 0x83, 0x46, 0x1c, 0x14, 0xc5, 0xaa, 0x50, 0x23, 0xe1, 0x89, 0x40, 0xc0, - 0x94, 0x5d, 0xf1, 0xc8, 0x08, 0x6a, 0x7a, 0x13, 0x0a, 0x1b, 0x0a, 0xfe, 0x2a, 0x51, 0x4d, 0x6f, 0x42, 0x9b, 0x4c, - 0x9c, 0x66, 0x10, 0xc1, 0x8c, 0xd8, 0xee, 0xb7, 0x80, 0x36, 0xb7, 0x66, 0xb4, 0xa9, 0x6b, 0xab, 0xad, 0x42, 0x2e, - 0x29, 0x52, 0x96, 0xff, 0x4e, 0x4d, 0x05, 0x25, 0xb5, 0x5c, 0xf4, 0x26, 0x4d, 0x17, 0x3d, 0x9e, 0x19, 0x49, 0xa0, - 0x72, 0xcb, 0x1d, 0xa3, 0x3f, 0x84, 0x05, 0x1e, 0x31, 0x71, 0x62, 0xc1, 0xdc, 0xea, 0x84, 0x65, 0x73, 0xb1, 0x18, - 0xad, 0x24, 0x84, 0x0d, 0x3e, 0x66, 0xd9, 0xbc, 0xd4, 0x0f, 0xa1, 0x2f, 0x2c, 0x7d, 0x03, 0x76, 0xb1, 0xc1, 0x4a, - 0x96, 0x01, 0xf8, 0x5e, 0xd0, 0xcd, 0x4a, 0x96, 0x91, 0x54, 0xdd, 0x8f, 0x6b, 0x2c, 0x41, 0xa5, 0x15, 0x2a, 0x2d, - 0xa9, 0xb1, 0x20, 0xf0, 0x55, 0xd5, 0xe5, 0x43, 0xb2, 0xab, 0x40, 0x3d, 0x75, 0xd4, 0x80, 0x53, 0xa0, 0xaa, 0xc0, - 0x82, 0x24, 0xa8, 0x0c, 0x5d, 0x15, 0x98, 0x56, 0x60, 0x9a, 0xa9, 0xc2, 0x45, 0x99, 0x1d, 0x4a, 0xb3, 0x5e, 0xf2, - 0x59, 0x3c, 0x08, 0x93, 0x61, 0x4c, 0x1e, 0x22, 0xd4, 0xfe, 0x61, 0x1e, 0xc5, 0x5a, 0x2e, 0x79, 0xe9, 0xfc, 0xe2, - 0x6f, 0x3e, 0x63, 0xaf, 0x7b, 0x86, 0xc1, 0x02, 0x9c, 0xa5, 0xed, 0x55, 0x26, 0xde, 0xca, 0x56, 0x70, 0x1c, 0xcc, - 0xa2, 0x1c, 0x56, 0x3d, 0x39, 0xa2, 0xb9, 0xc8, 0xb5, 0x77, 0x11, 0x22, 0x07, 0x99, 0x3d, 0x06, 0xd8, 0x8d, 0xf0, - 0x75, 0x68, 0x6d, 0x6e, 0x75, 0x85, 0xf8, 0x1b, 0x25, 0x12, 0x3f, 0x49, 0xf9, 0x71, 0xbd, 0x52, 0xb9, 0x2a, 0x83, - 0xc7, 0xaa, 0x9b, 0xc1, 0x33, 0xed, 0x7b, 0xac, 0xfd, 0x5b, 0xdb, 0xcd, 0xf1, 0xde, 0x83, 0x07, 0xad, 0xff, 0xad, - 0x27, 0x21, 0xb4, 0x57, 0x4e, 0x52, 0x77, 0xd4, 0xe8, 0x99, 0xc9, 0x1a, 0x51, 0x09, 0x53, 0xbb, 0x53, 0x39, 0x06, - 0x6a, 0x3a, 0x80, 0x6b, 0x89, 0x9a, 0xa0, 0x27, 0x05, 0x1b, 0xc3, 0x11, 0x67, 0x71, 0xd0, 0x8e, 0x63, 0x14, 0x2f, - 0xe7, 0x4a, 0xbc, 0x9c, 0x9f, 0x30, 0x0e, 0xd0, 0x5a, 0x80, 0x54, 0xaf, 0x61, 0x3f, 0x73, 0x05, 0x0b, 0x6c, 0xee, - 0x7c, 0x47, 0x16, 0xc8, 0x10, 0x27, 0x9b, 0xe3, 0x64, 0x8f, 0x6b, 0x3d, 0xf7, 0x02, 0x1f, 0x27, 0xf5, 0xc2, 0xab, - 0xab, 0x6c, 0xd7, 0xb5, 0x64, 0xe5, 0xbc, 0x18, 0x4c, 0x20, 0x28, 0x4b, 0x39, 0x2f, 0x86, 0x93, 0x05, 0xcd, 0xe1, - 0xc7, 0xa2, 0x81, 0x0e, 0xb1, 0x1c, 0x24, 0x70, 0xe9, 0xec, 0x31, 0xe0, 0x0d, 0xa5, 0x16, 0x77, 0x63, 0x1d, 0x39, - 0xd6, 0x51, 0x1c, 0x86, 0x31, 0xe0, 0xca, 0x3a, 0x81, 0xf7, 0xfe, 0xeb, 0x63, 0x13, 0x90, 0x55, 0xbb, 0xc2, 0xab, - 0x51, 0xee, 0xba, 0xd2, 0xe8, 0x4b, 0x4a, 0x4f, 0x78, 0xc1, 0x53, 0xc9, 0x76, 0xdb, 0x33, 0x70, 0xb6, 0xc4, 0x43, - 0xe2, 0x1d, 0x23, 0x7a, 0x31, 0x6d, 0x64, 0xe6, 0x04, 0xce, 0x6c, 0x77, 0xd9, 0xc6, 0xfc, 0xd8, 0x01, 0x0e, 0x16, - 0x41, 0x48, 0xdc, 0x10, 0x86, 0x89, 0x9d, 0x94, 0x43, 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, - 0xd2, 0xda, 0x36, 0x71, 0x0f, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, - 0x0c, 0x40, 0xd3, 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, - 0xfe, 0x9d, 0xe6, 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, - 0x13, 0xb7, 0xdb, 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, - 0x18, 0x30, 0x97, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, - 0xcc, 0x03, 0x99, 0x02, 0xe2, 0xf9, 0xc7, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd5, 0xf1, 0x8d, 0xe8, 0x7b, - 0xfb, 0xe2, 0x92, 0x57, 0x6f, 0x6e, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, - 0x1d, 0x14, 0x59, 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xaf, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, - 0x09, 0x53, 0x80, 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, - 0x31, 0x80, 0xc2, 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa6, 0x3a, 0x03, 0x2d, 0xeb, - 0x69, 0x01, 0xa2, 0x3a, 0x88, 0xb6, 0x0a, 0x84, 0x39, 0xa5, 0x65, 0x46, 0x97, 0x82, 0xa6, 0x82, 0x26, 0x19, 0xbd, - 0xe0, 0x4a, 0x54, 0x7c, 0x21, 0x98, 0xa2, 0xed, 0x86, 0xb0, 0xff, 0xd8, 0xa0, 0xeb, 0xad, 0x58, 0x6b, 0x68, 0x77, - 0x82, 0x8c, 0xd0, 0x7c, 0xa1, 0x83, 0x90, 0xa1, 0x72, 0x12, 0xf1, 0xe1, 0x35, 0x5e, 0x81, 0x4b, 0xa6, 0xd9, 0x68, - 0x19, 0x97, 0x61, 0x60, 0xbf, 0x0a, 0x2c, 0x26, 0x07, 0x26, 0xbd, 0x5f, 0x9f, 0x3f, 0x95, 0x57, 0x2b, 0x29, 0xb8, - 0xa8, 0x14, 0x44, 0xbf, 0xc1, 0x7d, 0x37, 0x71, 0xd5, 0x59, 0xb3, 0x56, 0x7a, 0xdf, 0xb7, 0x3e, 0x6b, 0xe3, 0xbe, - 0x30, 0x38, 0x06, 0x3b, 0x1f, 0x11, 0x03, 0x69, 0x50, 0xe9, 0x16, 0x87, 0x26, 0x40, 0x97, 0x0e, 0x29, 0x64, 0xc9, - 0x54, 0xa6, 0x4a, 0x50, 0xf1, 0x8d, 0xdf, 0x49, 0x59, 0x8d, 0xfe, 0x5a, 0xf3, 0xe2, 0xee, 0x3d, 0xcf, 0x39, 0x8e, - 0x51, 0x90, 0xc4, 0xe2, 0x3a, 0x2e, 0x03, 0xe2, 0x5b, 0x5e, 0x05, 0x47, 0xa9, 0x09, 0x1b, 0xb3, 0x53, 0x35, 0x6a, - 0xbd, 0x0a, 0xf4, 0x95, 0x51, 0xbe, 0x31, 0x18, 0x9a, 0x88, 0x2a, 0xe8, 0x7b, 0xad, 0xee, 0x69, 0x75, 0xc3, 0x02, - 0xe2, 0xcf, 0x95, 0x5e, 0xa8, 0xf5, 0xba, 0x19, 0x73, 0xc3, 0x44, 0x08, 0x1a, 0x3d, 0xaa, 0x17, 0x0e, 0x3f, 0x7f, - 0xa3, 0x2c, 0x89, 0xe0, 0xc5, 0x26, 0x5d, 0x17, 0x26, 0x96, 0x06, 0xd5, 0x01, 0x73, 0xa3, 0x4d, 0xce, 0x2f, 0x41, - 0xf4, 0xe7, 0xac, 0x88, 0x26, 0x75, 0x4d, 0x15, 0x82, 0x61, 0xb4, 0xb9, 0x6d, 0xa4, 0xd3, 0x3b, 0xf0, 0x72, 0x33, - 0xd6, 0x48, 0xda, 0xd3, 0xb1, 0xa6, 0x05, 0x2f, 0x57, 0x52, 0x94, 0x10, 0xdd, 0xb9, 0x37, 0xa6, 0x57, 0x71, 0x26, - 0xaa, 0x38, 0x13, 0xa7, 0xe5, 0x8a, 0x27, 0xd5, 0x3b, 0xa8, 0x50, 0x1b, 0xe3, 0x60, 0xeb, 0xd5, 0xa8, 0xab, 0x70, - 0xc8, 0x2f, 0x2f, 0x9e, 0xdf, 0xae, 0x62, 0x91, 0xc2, 0xa8, 0xd7, 0xfb, 0x5e, 0x34, 0xa7, 0x63, 0x15, 0x17, 0x5c, - 0x98, 0xa8, 0xc5, 0xb4, 0x62, 0x01, 0xd7, 0x19, 0x03, 0xca, 0x55, 0xec, 0xce, 0x4c, 0xc5, 0x32, 0x8c, 0xcb, 0xf2, - 0xa7, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x06, 0x4e, 0x8b, 0x99, 0x01, 0x01, 0xb9, 0xcb, 0x0d, 0x2e, 0x02, 0x0b, 0x8e, - 0x1e, 0x8f, 0x57, 0xb7, 0x01, 0xf5, 0xde, 0x48, 0x75, 0x3d, 0x64, 0xc1, 0x78, 0xf4, 0x24, 0x70, 0xc8, 0x21, 0xfe, - 0x47, 0x8f, 0x8f, 0xf6, 0x7f, 0x33, 0x09, 0x48, 0x3d, 0x05, 0x55, 0x85, 0x51, 0x88, 0xc2, 0xb4, 0xbf, 0x5a, 0xab, - 0x5b, 0xee, 0x9b, 0xf3, 0x92, 0x17, 0xd7, 0x10, 0xad, 0x9d, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, - 0xab, 0xaa, 0xc8, 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, - 0x58, 0xd4, 0xa4, 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, - 0x4a, 0x8c, 0x35, 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, - 0xb7, 0x53, 0xd5, 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xea, 0x60, - 0x78, 0x00, 0xc9, 0x64, 0xfa, 0x69, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, - 0x3d, 0xef, 0xff, 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, - 0xcf, 0x50, 0xad, 0xef, 0xd3, 0xa2, 0x88, 0xef, 0x6a, 0x88, 0x6c, 0x2a, 0x9c, 0x77, 0x0d, 0xf5, 0xc8, 0x02, 0x3d, - 0x22, 0xd3, 0x0b, 0xc1, 0xe0, 0x9b, 0x77, 0x55, 0x18, 0xf0, 0x72, 0x35, 0xe4, 0xa2, 0xca, 0xaa, 0xbb, 0x21, 0xe6, - 0x09, 0xf0, 0x53, 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x89, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, - 0xe2, 0x63, 0xaa, 0xba, 0x31, 0xf9, 0x86, 0xea, 0xbe, 0x4d, 0xbe, 0x01, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, - 0x8c, 0xc6, 0xf4, 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf1, 0x76, 0xf6, 0xd1, - 0x68, 0xf4, 0xa6, 0xa0, 0xa3, 0xd1, 0xe8, 0x63, 0x56, 0x13, 0xba, 0x12, 0x1d, 0xef, 0xdf, 0x71, 0x7a, 0x2e, 0xd3, - 0xbb, 0x28, 0x08, 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0xaf, 0xd2, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, - 0x6d, 0x44, 0x48, 0x26, 0x42, 0x1f, 0xec, 0xf4, 0x6c, 0x34, 0x1a, 0xbd, 0x4a, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x14, - 0xcd, 0x29, 0x9c, 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, - 0x8b, 0x87, 0x87, 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, - 0xb1, 0xf5, 0x2d, 0xfa, 0xea, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x14, 0x80, - 0x17, 0x67, 0x23, 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, - 0xc7, 0xd3, 0xf2, 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x15, 0x44, 0x25, 0x3b, 0x7a, 0x32, - 0x55, 0x70, 0xc7, 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x76, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, - 0x72, 0x19, 0x83, 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, - 0x4c, 0x1e, 0x96, 0x54, 0x7e, 0x35, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0x7a, 0xf9, - 0xa4, 0xec, 0x70, 0xfe, 0xbf, 0x4b, 0xba, 0x18, 0x1c, 0xba, 0xa1, 0x79, 0xa0, 0xdd, 0x79, 0x2b, 0x64, 0x1c, 0xab, - 0xf0, 0x4d, 0x4a, 0xac, 0x31, 0x2e, 0x67, 0x27, 0x1b, 0xd3, 0x9d, 0x51, 0x55, 0x64, 0x57, 0x21, 0xd1, 0xbd, 0x72, - 0x20, 0xa1, 0x41, 0x94, 0x8d, 0x70, 0xfd, 0x80, 0xf5, 0x8c, 0xd7, 0xc9, 0x6b, 0x5e, 0x54, 0x59, 0xa2, 0xde, 0x5f, - 0x37, 0xde, 0xd7, 0xb5, 0x09, 0xa8, 0xfa, 0xb6, 0x60, 0x30, 0xcf, 0x0f, 0x0a, 0x00, 0x31, 0x45, 0x1a, 0xe0, 0x13, - 0xcc, 0x20, 0xa8, 0x5d, 0x33, 0xaf, 0x1a, 0xc1, 0x37, 0xe0, 0xab, 0xb7, 0x05, 0x60, 0x90, 0x84, 0x20, 0x45, 0x86, - 0xd0, 0x40, 0x20, 0xd0, 0x30, 0xe4, 0x02, 0x83, 0x9f, 0x78, 0x71, 0x24, 0x95, 0x53, 0x22, 0x0f, 0x03, 0xfc, 0x11, - 0x50, 0x15, 0x80, 0xc4, 0x78, 0x1c, 0xc2, 0x0b, 0xf5, 0xcb, 0xbd, 0x51, 0x7b, 0x84, 0x3d, 0x4d, 0x43, 0x08, 0x36, - 0x84, 0x0f, 0x01, 0x2c, 0x29, 0x42, 0x1f, 0x20, 0x97, 0x11, 0x06, 0x17, 0x79, 0xb6, 0xd2, 0x49, 0xd5, 0xa8, 0xa3, - 0xf9, 0x50, 0x6a, 0x47, 0x72, 0x40, 0xbd, 0xf4, 0x18, 0xd3, 0x0b, 0x95, 0xae, 0x8a, 0x72, 0x46, 0x39, 0x6f, 0xf5, - 0xc4, 0xb8, 0xb0, 0x85, 0x1c, 0x22, 0xe1, 0xbc, 0x2d, 0x54, 0x28, 0x1c, 0xbe, 0x00, 0x30, 0x30, 0x90, 0x76, 0xec, - 0xc6, 0xbb, 0x51, 0xd9, 0xcf, 0x38, 0x3b, 0xfc, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, - 0xfb, 0x93, 0x3c, 0x7c, 0x70, 0x48, 0x5f, 0x70, 0xcb, 0xa5, 0xc1, 0xc2, 0x6f, 0x04, 0xfb, 0x51, 0x2b, 0x21, 0x88, - 0x02, 0xbc, 0x61, 0xb9, 0xd5, 0x38, 0x01, 0xc0, 0xc3, 0xe0, 0xbf, 0x02, 0x34, 0x9a, 0x72, 0x17, 0x2f, 0xd0, 0x97, - 0xa8, 0xdf, 0x27, 0x8f, 0x1a, 0x06, 0x83, 0x20, 0xae, 0x51, 0x31, 0x61, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x90, 0x6d, - 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0x84, 0xe1, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xb1, 0xad, 0xe4, 0x2a, 0x44, - 0xac, 0x40, 0xfd, 0x2b, 0x67, 0x10, 0x7b, 0xf3, 0x3a, 0x03, 0x9f, 0x0e, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x14, 0xdc, - 0xf9, 0x0a, 0x7e, 0x91, 0x81, 0x9b, 0xb7, 0x88, 0x51, 0xe0, 0x60, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, 0xd7, - 0xb8, 0xd3, 0x79, 0x6d, 0xd4, 0x10, 0xa8, 0x23, 0x07, 0xf5, 0x83, 0x1e, 0x82, 0xa1, 0x1a, 0x82, 0xa2, 0xa3, 0x2d, - 0xae, 0x5e, 0x5b, 0x4f, 0x61, 0x7a, 0xab, 0xea, 0x2b, 0x46, 0x7f, 0xca, 0x4c, 0x60, 0x21, 0xed, 0x9a, 0x63, 0x5d, - 0x73, 0x8c, 0xb4, 0xa7, 0xdf, 0x17, 0x0d, 0xf2, 0xd3, 0x59, 0x78, 0x10, 0xa8, 0x52, 0xe5, 0x4e, 0x59, 0x94, 0xdb, - 0xd2, 0xbc, 0x31, 0xac, 0x69, 0x9e, 0xd9, 0x38, 0x37, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xc1, 0x13, 0x4b, 0xc5, 0xda, - 0x20, 0xdc, 0x91, 0x49, 0x18, 0x5d, 0x81, 0xec, 0x32, 0x3c, 0xe3, 0x04, 0xf9, 0x54, 0x60, 0x1f, 0x54, 0xb5, 0x5e, - 0x4e, 0x78, 0x6c, 0xe4, 0xcb, 0x46, 0xd0, 0x20, 0x2f, 0x29, 0xea, 0x4d, 0xdc, 0x8e, 0x3d, 0x6d, 0x21, 0x57, 0x6e, - 0xea, 0x69, 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, - 0xcc, 0x70, 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, - 0x13, 0xf9, 0xea, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, - 0xf5, 0xa2, 0x84, 0x0a, 0xd8, 0x6e, 0x2b, 0x41, 0xf0, 0xef, 0xc7, 0x6c, 0x86, 0x7f, 0xb3, 0x7e, 0xbf, 0x17, 0xe2, - 0x2f, 0x8e, 0xc1, 0x8c, 0xe6, 0x62, 0xc1, 0x3e, 0x82, 0x8c, 0x89, 0x44, 0x98, 0xaa, 0x8c, 0x01, 0x59, 0x05, 0x16, - 0x81, 0xe6, 0x03, 0x95, 0x0b, 0x33, 0xd9, 0xcb, 0x9c, 0x6b, 0xc8, 0xf3, 0xd6, 0x38, 0x65, 0xa3, 0x2c, 0x51, 0xae, - 0x1c, 0xd9, 0x28, 0xce, 0xb3, 0xb8, 0xe4, 0xe5, 0x76, 0xab, 0x0f, 0xc7, 0xa4, 0xe0, 0xc0, 0xae, 0x2b, 0x2a, 0x55, - 0xb2, 0x8e, 0x54, 0x0f, 0xbc, 0x34, 0x2c, 0x70, 0x9f, 0xf2, 0x79, 0x61, 0x68, 0xc4, 0x01, 0x08, 0x33, 0x98, 0xba, - 0xa5, 0xf7, 0xc2, 0x02, 0x9a, 0x57, 0x12, 0xb2, 0xc1, 0x54, 0xcf, 0xc2, 0x37, 0x66, 0x62, 0x5e, 0x2c, 0x20, 0xac, - 0x4e, 0xb1, 0xd0, 0xcc, 0x26, 0x4d, 0x58, 0x0c, 0xb0, 0x79, 0x31, 0x99, 0x42, 0x7c, 0x77, 0x55, 0x4e, 0xbc, 0x30, - 0xf7, 0xed, 0xc4, 0x21, 0x87, 0xc0, 0xab, 0xda, 0xa0, 0xab, 0xd9, 0x86, 0xa3, 0x8e, 0x94, 0x13, 0x93, 0xdf, 0x4f, - 0x15, 0x84, 0xb8, 0x13, 0x47, 0xc2, 0xe5, 0xcd, 0x76, 0xe1, 0x65, 0x07, 0x82, 0x8e, 0x1a, 0x9c, 0xf2, 0x33, 0x83, - 0xa3, 0x31, 0x49, 0x37, 0xde, 0x09, 0x52, 0x84, 0x31, 0xd9, 0x48, 0x76, 0x2e, 0x43, 0x31, 0x8f, 0x17, 0xa0, 0xbc, - 0x8c, 0x17, 0x60, 0x69, 0x64, 0x0c, 0x52, 0x41, 0x7e, 0xc7, 0xbd, 0x50, 0x58, 0x14, 0x57, 0x88, 0xf4, 0xac, 0x7e, - 0x4f, 0x8b, 0x76, 0x28, 0x10, 0x14, 0x77, 0x28, 0xf3, 0xe4, 0xac, 0xc7, 0x02, 0x89, 0x0d, 0x01, 0xe3, 0x2b, 0x9d, - 0xa6, 0x5a, 0xeb, 0xde, 0xd8, 0xe8, 0x55, 0xd3, 0x6c, 0x24, 0x64, 0x75, 0x76, 0x01, 0x22, 0x25, 0x1f, 0x1d, 0x1f, - 0xf9, 0x45, 0xdc, 0x59, 0xe6, 0xad, 0x6d, 0x51, 0xc9, 0x4e, 0x36, 0x00, 0x5a, 0xa8, 0xa3, 0x67, 0x29, 0xb9, 0x4d, - 0x49, 0x6a, 0xb7, 0x29, 0x60, 0x25, 0xf9, 0x0b, 0x18, 0x82, 0xaf, 0x1d, 0x08, 0xa7, 0x63, 0x85, 0x78, 0x4d, 0x53, - 0x44, 0x9a, 0x0c, 0x4b, 0x8a, 0x63, 0x5b, 0x22, 0x0a, 0xaa, 0x2d, 0xcb, 0x0e, 0x86, 0x89, 0x12, 0xfc, 0x2c, 0xf5, - 0x28, 0x51, 0x10, 0x50, 0x3d, 0xe4, 0x20, 0xc1, 0xb6, 0x0d, 0x84, 0x07, 0xe4, 0x11, 0xbd, 0xb1, 0xfe, 0x3e, 0xeb, - 0x3c, 0xbb, 0xd0, 0x3c, 0x97, 0xeb, 0x5d, 0x61, 0xc6, 0x08, 0x4f, 0x32, 0x13, 0x36, 0xc0, 0x3b, 0xcf, 0x8c, 0xda, - 0xa6, 0xe7, 0xe1, 0xb5, 0x3d, 0xc7, 0x08, 0x7d, 0x7b, 0x06, 0xdd, 0x04, 0xf3, 0xea, 0xb0, 0x59, 0xaf, 0x14, 0xa4, - 0x86, 0xa9, 0x45, 0x13, 0xb3, 0x9e, 0x35, 0x28, 0xdf, 0x6e, 0x7b, 0x7a, 0xae, 0xf6, 0xcf, 0xdd, 0x76, 0xdb, 0xc3, - 0x6e, 0x3d, 0x4b, 0xbb, 0xad, 0xe2, 0x2b, 0xf5, 0x41, 0x7b, 0xfc, 0xb9, 0x1b, 0x7f, 0x6e, 0x90, 0x4d, 0x4a, 0x47, - 0x33, 0x6d, 0x7d, 0x10, 0x1e, 0x38, 0xbd, 0x6b, 0x34, 0xe9, 0xfb, 0x2c, 0x94, 0x74, 0x25, 0x1a, 0xd5, 0x99, 0x10, - 0x66, 0xac, 0xba, 0x7f, 0xfd, 0xdf, 0xbf, 0x0a, 0xf0, 0x88, 0x53, 0x3b, 0x7b, 0x6f, 0x83, 0x8a, 0x46, 0x5b, 0x38, - 0x52, 0x84, 0x1e, 0x90, 0x84, 0x7d, 0x2d, 0x6b, 0x71, 0x9b, 0xef, 0xb3, 0xfb, 0xe9, 0xd3, 0x87, 0xd4, 0xf7, 0x42, - 0x70, 0xcb, 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, - 0xbd, 0xf2, 0x3d, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0x7d, 0x9f, 0xcd, 0xb3, 0xc5, 0x76, 0x1b, 0xe2, 0xdf, - 0xae, 0x16, 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0x7f, 0x2d, 0x1a, 0x4e, - 0x13, 0xcf, 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, - 0xc0, 0x15, 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x4f, 0x96, 0xb6, 0x55, 0xc5, - 0x9d, 0xb7, 0xa4, 0x39, 0xae, 0x03, 0xe7, 0xeb, 0x60, 0x86, 0xd8, 0x94, 0x5d, 0x2d, 0x90, 0xfb, 0xe5, 0x35, 0xed, - 0x8d, 0xeb, 0x04, 0x66, 0x6d, 0x53, 0x5b, 0xc6, 0xcf, 0x96, 0xfe, 0x4e, 0x0f, 0xae, 0x32, 0x06, 0x9b, 0x1b, 0x2b, - 0x0d, 0xbb, 0x6f, 0x3c, 0x5f, 0x0a, 0x08, 0x4f, 0xe7, 0xd3, 0xe3, 0xf7, 0x99, 0x47, 0x8f, 0x81, 0xe8, 0x98, 0x8f, - 0x4a, 0xf7, 0x91, 0xdd, 0xbd, 0x7e, 0x40, 0xc0, 0x79, 0xd5, 0x2e, 0x68, 0x5e, 0x2e, 0x20, 0xb0, 0xaa, 0x57, 0x5e, - 0x61, 0xf9, 0xcc, 0x98, 0x5d, 0x02, 0x19, 0x2a, 0x08, 0x04, 0xee, 0xee, 0x3a, 0x17, 0x62, 0xd5, 0x61, 0x65, 0x4e, - 0x93, 0xb0, 0x93, 0x10, 0xcd, 0x5b, 0x83, 0x59, 0xf0, 0x5f, 0xc1, 0xa0, 0x1c, 0x04, 0x51, 0x10, 0x05, 0x01, 0x19, - 0x14, 0xf0, 0x0b, 0x71, 0xd7, 0x08, 0xc6, 0x6c, 0x81, 0x0e, 0x3f, 0xe0, 0xcc, 0x67, 0x44, 0x5e, 0xfa, 0x61, 0x3d, - 0xbd, 0x01, 0x38, 0x97, 0x32, 0xe7, 0x31, 0xfa, 0x9c, 0x3c, 0xe0, 0x2c, 0x23, 0xf4, 0x81, 0x77, 0x2a, 0xbf, 0xe5, - 0x8d, 0x60, 0x7f, 0xbb, 0xc3, 0xf6, 0x02, 0xe4, 0x15, 0xbd, 0x31, 0x7d, 0xc0, 0x49, 0x94, 0x35, 0x9c, 0xa9, 0x39, - 0xf4, 0xac, 0xb2, 0xac, 0x15, 0x35, 0xe4, 0x06, 0xc5, 0xdc, 0xc8, 0x32, 0x39, 0x99, 0xb6, 0x9a, 0x53, 0x81, 0xeb, - 0xce, 0xae, 0x17, 0x90, 0x1c, 0x0a, 0xcd, 0xd2, 0xd9, 0x70, 0xde, 0xb6, 0x65, 0xcf, 0x5a, 0xa7, 0x90, 0xd7, 0x10, - 0x15, 0x0d, 0xd2, 0x11, 0x50, 0x43, 0x2b, 0x2e, 0x2b, 0x70, 0x61, 0x36, 0xed, 0xe1, 0xa6, 0x3d, 0xa6, 0x19, 0x3f, - 0x41, 0xcc, 0x3c, 0x8e, 0x2d, 0x03, 0x3b, 0x12, 0x87, 0xef, 0xe3, 0x7c, 0x81, 0x76, 0xe9, 0xad, 0xab, 0xc5, 0x23, - 0xac, 0x3d, 0x6f, 0x85, 0x84, 0x00, 0xf1, 0x69, 0x2a, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, - 0x6a, 0xd8, 0x49, 0x73, 0x6b, 0xb6, 0xc4, 0x5e, 0x51, 0x78, 0x0c, 0xcc, 0xa9, 0xf9, 0xcf, 0x20, 0xa0, 0x78, 0xee, - 0x86, 0x60, 0x6f, 0xca, 0x4e, 0x36, 0x45, 0xbf, 0xff, 0xac, 0xc0, 0x07, 0x94, 0x0b, 0x83, 0x98, 0x5b, 0xc7, 0xf1, - 0x30, 0xec, 0x93, 0xfa, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x47, 0x58, 0x2a, 0x43, 0x58, 0xb8, 0x62, 0xa4, 0x83, 0x38, - 0xa8, 0x49, 0xe7, 0x60, 0x55, 0x2e, 0xf8, 0x72, 0xaf, 0xf7, 0x1a, 0x60, 0xd2, 0x33, 0x6f, 0x58, 0x5e, 0x78, 0x80, - 0x68, 0xbd, 0x1e, 0x2e, 0x14, 0x8f, 0x4c, 0x34, 0xd0, 0x38, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, 0x56, 0x32, 0x1a, - 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0xec, 0x77, 0x9f, 0x5a, 0x28, 0x9e, 0x32, 0x4e, 0x79, 0x0a, 0x96, 0xef, 0x86, 0xd2, - 0xcd, 0x17, 0x74, 0xc5, 0x45, 0xaa, 0x7e, 0x7a, 0xe8, 0x9b, 0x0d, 0xe2, 0x9a, 0x35, 0x75, 0x38, 0x76, 0xf8, 0x21, - 0x00, 0xa6, 0x7d, 0x98, 0xb9, 0x74, 0x0d, 0xd3, 0x0b, 0xe2, 0xd9, 0xb8, 0xe0, 0xa1, 0xcb, 0x03, 0xd8, 0x87, 0xe6, - 0x90, 0xc4, 0x4f, 0xe1, 0xe7, 0xcc, 0xa4, 0x75, 0x7c, 0x86, 0xb3, 0x19, 0x95, 0xea, 0x46, 0xd0, 0x7e, 0x0d, 0x89, - 0xc4, 0x20, 0x3d, 0x37, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x96, 0xde, 0xf9, 0x34, 0x08, 0xb0, 0xbe, 0xb1, - 0x18, 0x00, 0x50, 0xc5, 0x1f, 0xa8, 0xba, 0x32, 0x57, 0x14, 0xd3, 0x30, 0x95, 0x68, 0xef, 0x38, 0xae, 0xa3, 0xc6, - 0x75, 0x58, 0xb0, 0xd2, 0xda, 0x36, 0xbb, 0xb7, 0x10, 0x7f, 0x44, 0x97, 0x80, 0x6a, 0x41, 0xdc, 0x09, 0xe0, 0x43, - 0x23, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x00, 0x78, 0xc3, 0xf3, 0x30, 0x84, 0x3f, 0xb0, 0x70, 0x60, 0x59, 0xaa, - 0x7e, 0x2e, 0xa7, 0x31, 0x9c, 0xbb, 0xb9, 0xda, 0xe1, 0xb3, 0x25, 0x28, 0x36, 0xd5, 0x9c, 0x9a, 0xcb, 0x57, 0xde, - 0xd8, 0xef, 0x31, 0xc1, 0x3c, 0x66, 0xb6, 0xe1, 0xb7, 0x9e, 0x6e, 0xeb, 0x1b, 0xec, 0x06, 0x4e, 0xda, 0x0b, 0xa7, - 0xbd, 0xd8, 0x2e, 0x0d, 0xe4, 0x5f, 0xdd, 0x10, 0x22, 0x7c, 0xd0, 0xc4, 0x22, 0x6b, 0xc8, 0x74, 0x2c, 0x56, 0x88, - 0x6a, 0x53, 0xf1, 0x54, 0x1b, 0x08, 0x94, 0x53, 0x75, 0x61, 0x6a, 0xa5, 0x32, 0x61, 0x10, 0x77, 0x4a, 0x58, 0x54, - 0x19, 0x60, 0x18, 0x54, 0x48, 0x71, 0x6d, 0x3d, 0x7f, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0x2f, 0xf2, 0xf8, - 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0x39, 0x6a, 0xa9, 0x34, 0x8c, 0xe0, 0x04, 0xa2, 0x24, 0xd7, 0x7b, 0x72, 0x4e, - 0x1c, 0x27, 0xd7, 0x6e, 0xde, 0x6c, 0x27, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0x49, 0x6a, 0x4f, - 0x01, 0x6f, 0xd3, 0x3b, 0x4a, 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, - 0x83, 0x80, 0xd3, 0x9e, 0x6e, 0xac, 0x55, 0x24, 0x9b, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0xb5, 0xbb, 0x6d, - 0x55, 0xb6, 0x50, 0x30, 0x0f, 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x17, 0xa4, 0xd0, 0x2b, - 0x47, 0xab, 0x9a, 0x77, 0x25, 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xfb, 0x5a, 0xd6, 0x58, 0x5c, 0x39, 0x21, - 0x85, 0x4d, 0xf8, 0xd2, 0x52, 0x2c, 0xcc, 0x62, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x8c, 0x36, - 0x58, 0x37, 0xdb, 0xed, 0x87, 0x22, 0x9c, 0x67, 0x0b, 0x2a, 0x47, 0x59, 0x8a, 0x90, 0x6a, 0xc6, 0x63, 0xd9, 0x76, - 0xc1, 0x4c, 0x0c, 0x75, 0xed, 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, - 0x1e, 0xee, 0xdf, 0xa5, 0x10, 0xd3, 0xce, 0xac, 0xbb, 0x5f, 0x77, 0x6e, 0x88, 0xdf, 0x41, 0x60, 0x85, 0x92, 0x7d, - 0x28, 0x46, 0xe7, 0x99, 0x48, 0x71, 0xa7, 0xaa, 0x28, 0xc1, 0x6a, 0x1d, 0x34, 0x5b, 0x6e, 0xef, 0xc5, 0x96, 0x28, - 0x40, 0x9c, 0x67, 0xa1, 0x19, 0xcf, 0xca, 0x59, 0xce, 0x64, 0x14, 0x1b, 0x12, 0x95, 0x5e, 0x94, 0x78, 0x9f, 0xa7, - 0x31, 0x3d, 0x74, 0x6b, 0x10, 0x5c, 0x57, 0x77, 0x36, 0xd2, 0x7c, 0x41, 0x88, 0x9a, 0x00, 0x09, 0x1b, 0xd5, 0x9c, - 0x5a, 0x97, 0xe2, 0x7e, 0x56, 0xf9, 0x4e, 0x1f, 0xc4, 0x97, 0x02, 0x78, 0x58, 0x6f, 0x7b, 0x5f, 0x09, 0x8f, 0xb5, - 0xc1, 0xb7, 0xdb, 0xed, 0xa5, 0x98, 0x07, 0x81, 0xc7, 0x68, 0xfe, 0xa0, 0x24, 0xe6, 0xbd, 0x31, 0x85, 0x15, 0xef, - 0xbb, 0xf8, 0x75, 0x93, 0x5a, 0x6b, 0x91, 0xbb, 0xc3, 0xf5, 0x01, 0xcf, 0x53, 0xe2, 0x68, 0x47, 0xe5, 0x54, 0x5a, - 0xdb, 0x01, 0xec, 0x8a, 0xc0, 0x40, 0xd9, 0xbf, 0xa4, 0x6c, 0x03, 0xe6, 0x89, 0x60, 0x7d, 0x84, 0x7e, 0x5b, 0x4a, - 0x7f, 0x32, 0x46, 0xe3, 0x1e, 0xb9, 0xae, 0xa2, 0x23, 0xae, 0xa3, 0xd9, 0xf3, 0xe8, 0x6f, 0x4f, 0xc6, 0xb4, 0x88, - 0x45, 0x2a, 0xaf, 0x40, 0x05, 0x01, 0xca, 0x10, 0x74, 0x84, 0xd0, 0xd4, 0x00, 0x34, 0x08, 0x6e, 0x00, 0x7e, 0xeb, - 0x74, 0xa2, 0xb4, 0x35, 0xf9, 0x18, 0xad, 0xaa, 0xc8, 0x59, 0x1b, 0xda, 0x4d, 0x25, 0x87, 0xe4, 0x61, 0x09, 0xf8, - 0x96, 0xd8, 0x2c, 0x65, 0x83, 0xa2, 0x36, 0x9b, 0x7a, 0xad, 0xd8, 0x91, 0xdb, 0x46, 0xd1, 0x66, 0x2d, 0x6a, 0xbb, - 0x91, 0xf9, 0x62, 0x7a, 0x6b, 0x85, 0x81, 0x53, 0xd3, 0x9a, 0x9b, 0x1d, 0x28, 0x39, 0x5b, 0x9f, 0xc9, 0x4d, 0x80, - 0x38, 0xc0, 0x70, 0xdd, 0xce, 0x6f, 0x16, 0x84, 0xde, 0xb2, 0x5b, 0x2b, 0x56, 0xbd, 0xb1, 0x72, 0x11, 0x93, 0x76, - 0x33, 0x98, 0xc0, 0x65, 0x9c, 0x15, 0xf6, 0x85, 0x56, 0x37, 0x14, 0x1d, 0x6d, 0x93, 0xf6, 0xf3, 0x8e, 0x76, 0xc3, - 0x05, 0xdf, 0x8a, 0x75, 0x9c, 0x5b, 0xd6, 0x54, 0xa1, 0x69, 0x07, 0x7a, 0x3b, 0x04, 0x34, 0x67, 0x63, 0xba, 0xa4, - 0x29, 0x5e, 0xa0, 0xe9, 0x1a, 0xcc, 0x74, 0x2e, 0xa0, 0xaf, 0xdd, 0x3e, 0xda, 0x17, 0xaa, 0x27, 0xc2, 0x5b, 0xa2, - 0xe0, 0xdb, 0x92, 0x82, 0x97, 0x5a, 0xce, 0x63, 0x33, 0x87, 0x80, 0x4f, 0xa3, 0x4a, 0xf4, 0x4e, 0x8a, 0x4b, 0xd0, - 0x66, 0xc2, 0x11, 0x68, 0xaa, 0x46, 0x6c, 0xe5, 0x00, 0xb7, 0x17, 0x4f, 0x03, 0x42, 0x41, 0xaa, 0xbb, 0xb6, 0x2b, - 0xf2, 0x96, 0x9d, 0x6c, 0x6e, 0xc1, 0x4c, 0xb8, 0x5a, 0x97, 0xad, 0xaf, 0x6c, 0xb2, 0xfb, 0xb8, 0x26, 0xd8, 0x76, - 0x6f, 0x83, 0x84, 0xb7, 0xf4, 0x86, 0x6c, 0x6e, 0xfa, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xee, 0xd0, 0x6d, 0x67, 0x87, - 0x6e, 0xbd, 0x76, 0x9e, 0x5b, 0x3d, 0x9f, 0xf2, 0x0e, 0xf9, 0x80, 0x26, 0x6b, 0x74, 0x15, 0xdf, 0xc1, 0xa6, 0x8e, - 0x2a, 0xaa, 0x2a, 0x8f, 0x12, 0x0a, 0x2a, 0xf1, 0x8c, 0x97, 0xef, 0x39, 0xc6, 0x7a, 0xd5, 0x4f, 0x6f, 0x35, 0xaf, - 0xb6, 0x36, 0x6b, 0xb3, 0x5c, 0x9f, 0x83, 0x85, 0xc4, 0x39, 0x8f, 0xae, 0x34, 0x2d, 0xb9, 0xf4, 0xa1, 0x34, 0x71, - 0x54, 0x82, 0x8b, 0x38, 0xcb, 0x41, 0x8d, 0x7b, 0xd1, 0xec, 0x7f, 0xa8, 0x6d, 0xc7, 0x96, 0x8d, 0x33, 0xf7, 0x3a, - 0x24, 0x9b, 0xff, 0xb1, 0x81, 0x7a, 0x1a, 0x62, 0x84, 0x58, 0xb3, 0xa0, 0xdf, 0x30, 0x88, 0x15, 0x1a, 0x94, 0xeb, - 0x24, 0xe1, 0x65, 0x19, 0x18, 0xa5, 0xd6, 0x9a, 0xad, 0xcd, 0x79, 0xf6, 0x96, 0x9d, 0xbc, 0xed, 0x31, 0x76, 0x4b, - 0x68, 0xa2, 0x75, 0x42, 0xa6, 0xc6, 0xc8, 0xd3, 0x02, 0xe9, 0x0e, 0x45, 0xd9, 0x45, 0xf8, 0x06, 0x85, 0x2c, 0xed, - 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0x42, 0x89, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xc0, 0x18, 0x9a, 0x1d, - 0x90, 0xcd, 0x92, 0xbd, 0xa2, 0x67, 0xd6, 0x24, 0x08, 0x5e, 0xbf, 0x51, 0x89, 0x66, 0x94, 0x15, 0xd1, 0x55, 0x46, - 0x3f, 0x77, 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, - 0x6a, 0x6c, 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, - 0xbc, 0xa5, 0xe0, 0x2f, 0xf6, 0x96, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb2, 0x93, - 0xcd, 0xdb, 0xf0, 0x55, 0x63, 0xe6, 0xee, 0x42, 0xbc, 0x54, 0x25, 0x3d, 0x6f, 0x9e, 0xcc, 0x40, 0xac, 0xac, 0xd6, - 0xfc, 0x96, 0x59, 0x7d, 0x02, 0x10, 0xa9, 0x5b, 0xeb, 0x60, 0x8b, 0x1f, 0x9b, 0x2e, 0x93, 0x4d, 0xca, 0xda, 0x4c, - 0x94, 0x52, 0x91, 0x34, 0x17, 0x01, 0xf4, 0x1b, 0x86, 0xa3, 0x06, 0xb8, 0x73, 0x3d, 0xf6, 0x66, 0x68, 0xbc, 0x31, - 0x35, 0xf4, 0x6c, 0xa3, 0x97, 0xb7, 0xa3, 0x10, 0x66, 0x2c, 0xa2, 0x5b, 0x77, 0x2c, 0x86, 0xaf, 0xe8, 0x1b, 0xa8, - 0xf0, 0x69, 0x88, 0xd1, 0x85, 0x49, 0x5d, 0x4f, 0xd7, 0x6a, 0x2b, 0xdd, 0x10, 0x9a, 0x63, 0x54, 0x23, 0xaf, 0x6d, - 0x77, 0xd4, 0x08, 0xed, 0x09, 0xe5, 0xe1, 0x2d, 0xad, 0xe8, 0x8d, 0x65, 0x11, 0x9c, 0xfc, 0xd8, 0xcb, 0x4f, 0xe8, - 0xb9, 0x27, 0x30, 0x29, 0xda, 0x1a, 0xc0, 0x5f, 0x50, 0x3f, 0x9c, 0xd5, 0x53, 0x2b, 0xe5, 0xf0, 0x14, 0xbe, 0x64, - 0x03, 0x72, 0x05, 0xbd, 0x58, 0x63, 0x76, 0x12, 0x83, 0x0e, 0x6a, 0x67, 0x77, 0x78, 0x93, 0x52, 0x86, 0x68, 0x8d, - 0xe8, 0x20, 0xaf, 0x7e, 0x03, 0x4d, 0x1f, 0xa4, 0x85, 0x29, 0x5d, 0xa3, 0x80, 0x07, 0xf4, 0x4d, 0xfd, 0x7e, 0x8e, - 0xcf, 0xb5, 0x67, 0x99, 0xa6, 0x2c, 0x90, 0x09, 0x5d, 0x7a, 0x71, 0xbb, 0x40, 0xda, 0xec, 0x58, 0x05, 0x60, 0x45, - 0x12, 0x68, 0x44, 0x02, 0x96, 0x4b, 0x9e, 0xb8, 0x6c, 0x83, 0x06, 0x35, 0x51, 0x49, 0x21, 0x4b, 0x24, 0x81, 0x1f, - 0x46, 0x50, 0xa6, 0x28, 0x06, 0x71, 0xaf, 0x5e, 0x5e, 0x71, 0x4d, 0x0d, 0x58, 0x53, 0x04, 0x13, 0xac, 0xd3, 0x29, - 0x10, 0x5b, 0xb1, 0x5e, 0x81, 0x27, 0xaa, 0xbb, 0x48, 0x22, 0x4b, 0x80, 0x06, 0x7a, 0xbe, 0x74, 0xda, 0x2d, 0x6f, - 0x4f, 0xb4, 0x54, 0xb1, 0xb9, 0xf7, 0x62, 0x61, 0xb9, 0xc7, 0xca, 0xdf, 0x0e, 0xb4, 0x17, 0x56, 0x3b, 0x22, 0x6a, - 0xb0, 0x3a, 0x6c, 0xdb, 0xf9, 0xa1, 0x34, 0x54, 0xf7, 0xca, 0x31, 0x01, 0x15, 0x5d, 0xc5, 0xd5, 0x32, 0xca, 0x46, - 0xf0, 0x67, 0xbb, 0x0d, 0x0e, 0x03, 0xb0, 0x08, 0xfd, 0xe5, 0xdd, 0x4f, 0x11, 0x86, 0xab, 0xfa, 0xe5, 0xdd, 0x4f, - 0xdb, 0xed, 0x93, 0xf1, 0xd8, 0x70, 0x05, 0x4e, 0xad, 0x03, 0xfc, 0x81, 0x61, 0x1b, 0xec, 0x92, 0xdd, 0x6e, 0x9f, - 0x00, 0x07, 0xa1, 0xd8, 0x06, 0xb3, 0x8b, 0x95, 0x63, 0x9b, 0x62, 0x35, 0xf4, 0x8e, 0x04, 0xec, 0xbe, 0x1d, 0x96, - 0x62, 0x97, 0xfa, 0xa8, 0x90, 0x94, 0x7a, 0xd1, 0x3f, 0xef, 0x14, 0x58, 0x52, 0x30, 0xe5, 0x0d, 0x96, 0x55, 0xb5, - 0x2a, 0xa3, 0xc3, 0xc3, 0x78, 0x95, 0x8d, 0xca, 0x0c, 0xb6, 0x79, 0x79, 0x7d, 0x09, 0x00, 0x13, 0x01, 0x6d, 0xbc, - 0x5b, 0x8b, 0xcc, 0xbc, 0x58, 0xd0, 0x65, 0x86, 0x6b, 0x12, 0xcc, 0x0e, 0x72, 0x6e, 0x75, 0x93, 0x53, 0x62, 0x1f, - 0xc0, 0x06, 0x73, 0xbb, 0x6d, 0xf0, 0x0b, 0x27, 0xa3, 0x27, 0xb3, 0x65, 0xa6, 0x0d, 0x5c, 0xb9, 0xd9, 0xff, 0x24, - 0xf2, 0xd2, 0x50, 0xf1, 0x49, 0xa6, 0xcf, 0x33, 0xe0, 0xf3, 0xd8, 0x27, 0x11, 0xfa, 0x2c, 0x57, 0xa3, 0x35, 0xc0, - 0xc6, 0x66, 0x17, 0x77, 0xa3, 0x94, 0x43, 0x84, 0x8e, 0xc0, 0xaa, 0x6b, 0x96, 0x19, 0xf1, 0x6d, 0x2a, 0x6e, 0x5b, - 0xaa, 0xb0, 0x4f, 0xc2, 0x73, 0xde, 0xe1, 0xc6, 0x71, 0xa8, 0x37, 0x89, 0xc2, 0xe7, 0x28, 0x44, 0xe5, 0x68, 0x5c, - 0xe8, 0xe4, 0x6b, 0x99, 0xc7, 0x84, 0x62, 0x0e, 0xf7, 0xee, 0x9f, 0xa9, 0x33, 0x97, 0xf1, 0x85, 0x7b, 0xcf, 0x7d, - 0x99, 0xc9, 0xb5, 0x04, 0x90, 0x28, 0x55, 0xfb, 0xcf, 0x9f, 0x91, 0x1a, 0xff, 0x95, 0x6a, 0x0d, 0x40, 0xef, 0x67, - 0xa8, 0xc9, 0x11, 0x04, 0x6c, 0xc5, 0xd4, 0x8f, 0x2e, 0x60, 0x25, 0xf3, 0x3f, 0xa1, 0x6e, 0x47, 0xb0, 0x8d, 0x8a, - 0x27, 0x14, 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0xee, 0x22, 0x5e, 0x4f, 0xb1, 0x24, 0x66, 0x23, 0x86, - 0xfd, 0xdc, 0xec, 0xc2, 0xbb, 0xa2, 0x61, 0x12, 0x4f, 0x4b, 0x7f, 0x5b, 0x79, 0x9b, 0xc9, 0x32, 0xce, 0xc8, 0x94, - 0x2b, 0x04, 0x73, 0xab, 0xef, 0x31, 0x27, 0xf8, 0xe3, 0xa3, 0xc7, 0x84, 0x5e, 0xcb, 0x69, 0x89, 0x20, 0x7d, 0x22, - 0xb5, 0xae, 0xab, 0xd8, 0xaf, 0x29, 0x44, 0xb5, 0x10, 0x0c, 0x42, 0x99, 0x9a, 0xf6, 0x29, 0xbe, 0xcf, 0x96, 0xfd, - 0xc9, 0x94, 0x2d, 0xc9, 0x46, 0x40, 0xc7, 0xa4, 0xf3, 0x7e, 0xf5, 0xf6, 0xec, 0xcc, 0xfb, 0x0d, 0x9a, 0x70, 0x50, - 0xdd, 0x40, 0xbb, 0x0a, 0x32, 0x8d, 0x51, 0x6c, 0x16, 0x63, 0xed, 0xd6, 0x44, 0x04, 0x41, 0xb8, 0xcb, 0x59, 0xd8, - 0x6e, 0x27, 0xc4, 0xdb, 0x40, 0x02, 0x05, 0xae, 0x6d, 0x94, 0x93, 0x90, 0xa8, 0x0b, 0x99, 0x39, 0x26, 0x24, 0x0b, - 0xf4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0xb7, 0x4f, 0x01, 0x7d, 0x51, 0xb0, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x6f, 0x36, - 0xa0, 0x1f, 0xa5, 0x7a, 0x04, 0x8f, 0x69, 0x60, 0xb9, 0xe8, 0xeb, 0x82, 0x21, 0xcc, 0xd2, 0xef, 0x29, 0x9b, 0x7c, - 0xf3, 0x77, 0x37, 0xbf, 0xe7, 0x5a, 0xcc, 0x0e, 0x42, 0x71, 0x7b, 0x3d, 0x01, 0xe2, 0x57, 0xf1, 0x2b, 0xb0, 0x36, - 0xd7, 0x12, 0x6f, 0x4f, 0xf2, 0x20, 0x7c, 0x39, 0xba, 0xfd, 0xa4, 0x34, 0x9f, 0x40, 0xd0, 0x1e, 0x27, 0x29, 0x77, - 0xdf, 0xbd, 0x97, 0xae, 0x22, 0x18, 0x2d, 0x40, 0xf0, 0xdb, 0x5b, 0xc9, 0x59, 0x53, 0xf8, 0x8f, 0x75, 0xbe, 0xc0, - 0x58, 0x2a, 0xf2, 0x3d, 0x4e, 0x7f, 0x13, 0x1c, 0xdc, 0xbf, 0x95, 0x59, 0x43, 0xa2, 0x73, 0xf5, 0x11, 0xd0, 0xff, - 0xb1, 0x1e, 0xbf, 0x53, 0x94, 0xf4, 0x25, 0x71, 0x8e, 0xf0, 0x4d, 0xbc, 0x44, 0xd3, 0xc5, 0xde, 0xb8, 0xa6, 0x9f, - 0x0a, 0xf3, 0x42, 0x2b, 0x38, 0xec, 0x5b, 0xa3, 0xf0, 0xc0, 0x33, 0xef, 0x3b, 0xd1, 0x10, 0x74, 0xff, 0x03, 0xf7, - 0xc6, 0x77, 0x82, 0x65, 0x78, 0x53, 0xce, 0x32, 0x73, 0x87, 0xbb, 0xc9, 0x44, 0x2a, 0x6f, 0x18, 0x0b, 0xd6, 0x42, - 0x99, 0xf3, 0xa6, 0xc1, 0x6c, 0x53, 0x47, 0x2a, 0xd9, 0x7d, 0xff, 0x67, 0xe3, 0x84, 0xcd, 0x06, 0xc1, 0xfb, 0x4a, - 0x16, 0xf1, 0x25, 0x0f, 0xa6, 0x5a, 0x45, 0x91, 0x81, 0x5d, 0x21, 0x20, 0xe5, 0x38, 0xed, 0x1d, 0x3c, 0x59, 0x6a, - 0x66, 0x42, 0x7e, 0x5b, 0x9d, 0x05, 0xbc, 0x35, 0xa3, 0x79, 0x5a, 0xc1, 0x2e, 0xf3, 0x95, 0x14, 0xdf, 0xb5, 0x24, - 0xd9, 0x58, 0x7f, 0x43, 0x86, 0x6d, 0xe5, 0x33, 0xe7, 0x80, 0xb9, 0xf3, 0x51, 0xaa, 0xa0, 0x7f, 0x3d, 0xc6, 0x6e, - 0x24, 0x12, 0x01, 0xe1, 0x2c, 0x26, 0xee, 0x84, 0x09, 0x87, 0xe9, 0x02, 0x05, 0xc5, 0x18, 0x28, 0xe8, 0xbd, 0x0c, - 0x39, 0x3d, 0xe5, 0x83, 0xa4, 0x31, 0x5b, 0x7f, 0xaa, 0x12, 0xe9, 0x8d, 0x24, 0xf4, 0x0c, 0x7e, 0x8f, 0x5b, 0x3c, - 0x50, 0x23, 0x58, 0xa7, 0xbb, 0x39, 0x1d, 0xbe, 0x2e, 0xc8, 0xf0, 0x77, 0xf0, 0x76, 0x8b, 0xed, 0x65, 0x39, 0x81, - 0xc5, 0x1d, 0x7b, 0xc5, 0xd3, 0x5c, 0xb5, 0x38, 0x21, 0x1e, 0xb1, 0xc8, 0x7d, 0x62, 0x01, 0x23, 0x6a, 0x18, 0x8d, - 0x1f, 0xdf, 0xbf, 0x79, 0xad, 0x31, 0xac, 0x72, 0xff, 0x03, 0x18, 0x51, 0x2d, 0x6d, 0xb7, 0x03, 0xbe, 0x1c, 0xa1, - 0x01, 0x7b, 0xea, 0x06, 0xbb, 0xdf, 0x37, 0x69, 0x27, 0xa5, 0x97, 0xcd, 0x89, 0x41, 0x77, 0x94, 0x36, 0x4b, 0x65, - 0x60, 0xdc, 0x55, 0x38, 0x9a, 0x13, 0x1b, 0xb1, 0xaa, 0xf7, 0x61, 0xb8, 0xa4, 0xb1, 0x95, 0x95, 0xdb, 0xdd, 0x84, - 0x23, 0x9b, 0x00, 0xd7, 0xa7, 0xa0, 0xbd, 0x9a, 0x73, 0xd0, 0x82, 0x12, 0x05, 0x8e, 0x68, 0xbb, 0x0d, 0x21, 0x22, - 0x49, 0x31, 0x9c, 0xcc, 0xc2, 0x62, 0x38, 0x54, 0x03, 0x5f, 0x10, 0x12, 0x7d, 0x2a, 0xe6, 0xd9, 0x42, 0x21, 0x18, - 0xf9, 0x3b, 0xe9, 0xd7, 0x42, 0x71, 0xca, 0xbd, 0xef, 0x04, 0xd9, 0xfc, 0x23, 0xc5, 0x18, 0x8c, 0x4e, 0xb3, 0x99, - 0x81, 0x84, 0xf5, 0xb4, 0x22, 0x6a, 0x1d, 0xd9, 0xd9, 0x00, 0x55, 0x2c, 0x9a, 0x06, 0x83, 0xba, 0xc5, 0x13, 0xeb, - 0x19, 0xbd, 0x07, 0x95, 0x20, 0xaa, 0x05, 0xbb, 0x31, 0x5c, 0x6b, 0xaf, 0x45, 0x28, 0x29, 0x27, 0x4d, 0x66, 0xc6, - 0x8a, 0x06, 0x0b, 0x10, 0x92, 0xc6, 0x65, 0xf5, 0x4a, 0xa6, 0xd9, 0x45, 0x06, 0x08, 0x12, 0xce, 0x9f, 0x50, 0x36, - 0xde, 0x3c, 0x55, 0xf3, 0xd2, 0x95, 0x38, 0xb3, 0xb0, 0x27, 0x5d, 0x6f, 0x69, 0x41, 0xa2, 0x02, 0x68, 0x94, 0xaf, - 0xe5, 0xf9, 0x7e, 0xc7, 0x2a, 0x64, 0xf7, 0xc3, 0xa9, 0xb2, 0x1d, 0xe2, 0x27, 0xac, 0x22, 0xde, 0x69, 0x5d, 0x29, - 0x91, 0x46, 0x47, 0xdb, 0x80, 0x18, 0xb6, 0xec, 0x5b, 0xd4, 0xf0, 0x41, 0xd8, 0x45, 0x27, 0xf9, 0x41, 0x4f, 0xf1, - 0xd8, 0x1a, 0x48, 0xfa, 0x5a, 0x04, 0x5f, 0xa3, 0x23, 0x9d, 0x28, 0xd3, 0x48, 0x4c, 0x21, 0xd1, 0xaf, 0x17, 0x5a, - 0x63, 0x19, 0x65, 0x5f, 0x91, 0xff, 0xb3, 0xee, 0xde, 0x77, 0x62, 0xbb, 0x85, 0x49, 0xf6, 0x3c, 0xd0, 0x60, 0x53, - 0xa3, 0x56, 0x08, 0x67, 0xe7, 0xb4, 0x42, 0xed, 0x58, 0x2f, 0x2c, 0x81, 0x3c, 0x80, 0xad, 0x48, 0x83, 0x32, 0x48, - 0xf6, 0xa9, 0x98, 0x8b, 0x85, 0x13, 0xe5, 0x48, 0x85, 0x7f, 0x26, 0x47, 0x29, 0x87, 0xab, 0x58, 0x58, 0x30, 0xe4, - 0x57, 0x47, 0x17, 0x85, 0xbc, 0x02, 0x49, 0x89, 0x61, 0xa8, 0x2c, 0xaf, 0x8b, 0xab, 0xb6, 0x24, 0xb4, 0x77, 0x06, - 0xa0, 0x34, 0x05, 0x08, 0x5e, 0x1a, 0x35, 0xc4, 0x6c, 0xa3, 0x76, 0x57, 0xb4, 0x97, 0x1c, 0x50, 0xa7, 0xbb, 0x76, - 0xeb, 0x4d, 0xd9, 0xaa, 0x5b, 0x71, 0xe1, 0x9f, 0x50, 0xfa, 0x29, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, - 0x59, 0x76, 0x71, 0x87, 0x4b, 0xbf, 0x6a, 0x8c, 0x5f, 0xbf, 0xdf, 0x53, 0x0b, 0xa1, 0x91, 0x0a, 0xcc, 0xb7, 0xcf, - 0x4c, 0x55, 0x46, 0x53, 0x6a, 0x2f, 0xc1, 0x95, 0xb3, 0x1f, 0x41, 0x45, 0x5c, 0x57, 0xa4, 0x36, 0x35, 0x40, 0x07, - 0x5e, 0x56, 0xb8, 0x95, 0x05, 0x78, 0xec, 0x04, 0x64, 0xbb, 0xe5, 0x61, 0xa0, 0x0f, 0x9d, 0xc0, 0xdf, 0x92, 0xaf, - 0x90, 0x59, 0xb3, 0x8f, 0xff, 0xd2, 0x82, 0x7f, 0x6c, 0xc1, 0x4f, 0x28, 0xee, 0xb4, 0x32, 0xff, 0x56, 0x5a, 0xb7, - 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0xd1, 0x04, 0x8f, 0x52, 0xd9, 0x3f, 0x48, 0xf8, - 0x60, 0xd6, 0x78, 0x62, 0x8d, 0x27, 0xc3, 0xe9, 0x56, 0x1a, 0x96, 0x01, 0x85, 0x7e, 0x5e, 0xe6, 0x8a, 0xea, 0xe7, - 0x9f, 0xd7, 0x7c, 0xcd, 0x9b, 0x2d, 0xb6, 0x49, 0xf7, 0x34, 0xd8, 0xcb, 0xa3, 0x29, 0x85, 0x93, 0xa8, 0x73, 0x23, - 0x51, 0x17, 0x35, 0xcb, 0x50, 0x9d, 0xe0, 0xd5, 0x3c, 0xd5, 0xc3, 0xde, 0x4c, 0x44, 0x6b, 0x25, 0x65, 0x89, 0x01, - 0x6b, 0x1d, 0x79, 0x48, 0xee, 0xd6, 0x3a, 0xee, 0x34, 0xd4, 0xa5, 0x29, 0xd4, 0x04, 0x2b, 0x5c, 0x80, 0x23, 0xe8, - 0x5d, 0x11, 0x72, 0xb8, 0xa6, 0x2a, 0xfd, 0x82, 0xa6, 0xe4, 0x89, 0xa7, 0xa8, 0xd5, 0x8a, 0x74, 0xfb, 0x51, 0x8e, - 0xdd, 0xf0, 0x8d, 0x13, 0x72, 0x62, 0x84, 0xfe, 0xee, 0x58, 0xca, 0x19, 0x5a, 0x3c, 0xa8, 0x13, 0xac, 0x97, 0xb7, - 0x14, 0x28, 0xe6, 0xe8, 0xb2, 0xea, 0x9a, 0x97, 0x68, 0xfb, 0xb2, 0xec, 0xf7, 0x73, 0x5b, 0x4f, 0xca, 0x4e, 0x36, - 0x4b, 0xb3, 0x0f, 0x51, 0x31, 0x85, 0xbb, 0x3e, 0xd1, 0xfc, 0x55, 0xa8, 0xaf, 0xda, 0x32, 0xe7, 0x23, 0x8e, 0x38, - 0x21, 0x39, 0xa9, 0xff, 0xa5, 0xa6, 0x5e, 0x89, 0xfb, 0x55, 0x25, 0xbf, 0x0a, 0x63, 0xc5, 0x68, 0x89, 0x21, 0x8a, - 0xb4, 0x7b, 0x63, 0xfa, 0xb2, 0x00, 0xf8, 0x2b, 0xc1, 0x3e, 0xa5, 0xa1, 0x56, 0x7e, 0x8b, 0xb6, 0x80, 0x7f, 0xa3, - 0xb8, 0x01, 0xab, 0xc0, 0x00, 0xa3, 0xc9, 0xf6, 0x9c, 0x26, 0x70, 0xc0, 0x09, 0xad, 0xa2, 0xa0, 0xc2, 0x0c, 0x0d, - 0xb5, 0x85, 0xd1, 0x57, 0x28, 0xe3, 0x56, 0x99, 0xbd, 0x1b, 0x63, 0xa7, 0x05, 0x5e, 0xc3, 0xbf, 0xd1, 0x0b, 0xc5, - 0x6c, 0xd4, 0x41, 0x7a, 0x74, 0x12, 0xd3, 0x1f, 0xb7, 0x70, 0x72, 0xb3, 0x70, 0x96, 0x35, 0x4b, 0xa0, 0x3b, 0x70, - 0x41, 0x8c, 0xfb, 0xfd, 0x1c, 0x8e, 0x4c, 0x33, 0xf2, 0x05, 0xcb, 0x69, 0xcc, 0x96, 0x54, 0x7b, 0x1e, 0x5e, 0x56, - 0x61, 0x4e, 0x97, 0x56, 0xc6, 0x9b, 0x32, 0x50, 0x19, 0x6d, 0xb7, 0x21, 0xfc, 0xe9, 0xb6, 0x76, 0x49, 0xe7, 0x4b, - 0xc8, 0x00, 0x7f, 0x40, 0x22, 0x8a, 0x58, 0xe0, 0xff, 0x56, 0xe3, 0x94, 0x9e, 0x28, 0xad, 0x59, 0x42, 0xd7, 0x4c, - 0xd7, 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0xb6, 0xdb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, - 0x02, 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0x2f, - 0x1f, 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xfc, 0x31, 0x0d, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0x47, - 0x00, 0xae, 0xe7, 0x2b, 0x88, 0x02, 0xb7, 0x86, 0xb8, 0xf0, 0xd0, 0xa0, 0xb7, 0x85, 0xbc, 0xca, 0x4a, 0x1e, 0xe2, - 0x3d, 0xc1, 0xd3, 0x8c, 0xee, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, 0xbf, 0xfe, 0x55, 0x84, - 0x73, 0x88, 0xde, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xb9, 0x3c, 0xdb, 0xab, 0xb7, 0x70, 0xba, 0xe9, 0xeb, 0x5b, - 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0x78, 0x47, 0xe2, 0x1a, 0x68, 0xac, 0xdb, 0x9a, - 0x9d, 0xf6, 0x28, 0x1e, 0x13, 0x99, 0x19, 0x8b, 0x14, 0x63, 0xee, 0xd6, 0x69, 0x51, 0xb4, 0x41, 0x33, 0x84, 0xdd, - 0xbb, 0x4e, 0xb6, 0x6e, 0x45, 0x9c, 0xdf, 0x6f, 0xfb, 0x02, 0xa3, 0x61, 0xcc, 0xb5, 0x7b, 0xbe, 0xa1, 0xdb, 0xda, - 0x8d, 0x8c, 0x46, 0x82, 0xcc, 0xd4, 0x81, 0x28, 0x6b, 0x6b, 0xc0, 0xf6, 0x96, 0xeb, 0x4d, 0x0b, 0xfc, 0xbc, 0x89, - 0xc1, 0xdb, 0xb3, 0xc6, 0x29, 0xad, 0xaf, 0x71, 0xcd, 0x71, 0x55, 0x88, 0xa8, 0x2d, 0x52, 0x00, 0x0c, 0x3b, 0x5f, - 0xe0, 0xce, 0xac, 0x30, 0x98, 0x13, 0x96, 0x4a, 0x76, 0x2a, 0xd7, 0x9f, 0xc3, 0x16, 0x07, 0xa9, 0x7c, 0xe9, 0xf5, - 0xf7, 0x5f, 0xbe, 0xf8, 0x02, 0xdd, 0xf6, 0x9c, 0x1f, 0x41, 0x90, 0x09, 0x74, 0x50, 0x53, 0xaa, 0xc7, 0x1f, 0x0a, - 0xa0, 0xf6, 0x30, 0x0f, 0x3f, 0x14, 0x4c, 0xc4, 0xd7, 0xd9, 0x65, 0x5c, 0xc9, 0x62, 0x74, 0xcd, 0x45, 0x2a, 0x0b, - 0x2b, 0x35, 0x0e, 0x4e, 0x57, 0xab, 0x9c, 0x07, 0x60, 0x2a, 0x6f, 0x19, 0x65, 0x27, 0x97, 0xd4, 0x83, 0xab, 0xe5, - 0xe9, 0x95, 0x16, 0x9d, 0x97, 0xd7, 0x97, 0x41, 0x84, 0xbf, 0xce, 0xcd, 0x8f, 0xab, 0xb8, 0xfc, 0x18, 0x44, 0xd6, - 0xa6, 0xce, 0xfc, 0x40, 0xa9, 0x3c, 0xf8, 0x3b, 0x81, 0x4c, 0xf7, 0x87, 0x02, 0x2c, 0xb3, 0x6d, 0xc5, 0xc7, 0x31, - 0xd6, 0x3a, 0x9c, 0x90, 0x99, 0x2a, 0xd1, 0x7b, 0x97, 0xac, 0x0b, 0xb0, 0xf6, 0x53, 0xd8, 0xce, 0x2a, 0xd7, 0x0c, - 0x2b, 0x53, 0x15, 0x19, 0x82, 0xb6, 0x66, 0x87, 0xa1, 0x75, 0xa2, 0x99, 0xa3, 0xb7, 0x80, 0x7e, 0x20, 0x87, 0x97, - 0x54, 0xae, 0x99, 0xe7, 0x63, 0xd3, 0x78, 0xfd, 0xe0, 0xf0, 0xd2, 0x13, 0x28, 0xd9, 0x3b, 0x39, 0x0a, 0x13, 0xc1, - 0xd3, 0xd8, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x1d, 0x34, 0x19, 0x8f, 0xa9, 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0x6c, - 0x9b, 0x3d, 0xac, 0x1e, 0x72, 0x72, 0xc8, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xcb, - 0xb5, 0x8d, 0x10, 0xaf, 0x9c, 0x1d, 0x9d, 0x97, 0x74, 0xeb, 0x9b, 0xd2, 0xd0, 0x6b, 0x09, 0xc0, 0x7c, 0xda, 0x80, - 0xbf, 0x60, 0x72, 0x3d, 0xaa, 0x78, 0x59, 0x81, 0x84, 0x05, 0x45, 0x78, 0x53, 0xec, 0x4d, 0xe1, 0x6e, 0x9c, 0x9e, - 0xc3, 0x0e, 0x5c, 0x4c, 0xd1, 0x1d, 0x27, 0x26, 0xb3, 0xd2, 0x68, 0x45, 0x23, 0xfd, 0xcb, 0xf5, 0x25, 0xd6, 0x7d, - 0xd1, 0xca, 0x3c, 0x9b, 0x53, 0x61, 0xd3, 0xbb, 0xca, 0xa5, 0x13, 0xf5, 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, - 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x51, 0x81, 0x84, 0x0c, 0x0c, 0x5f, 0x83, 0xb5, 0x28, 0xb9, 0xb1, 0x82, 0xf5, 0xee, - 0xf9, 0x3a, 0x41, 0x48, 0xc1, 0x03, 0x37, 0x41, 0xbf, 0xb4, 0x6e, 0xde, 0x8e, 0x12, 0x65, 0x10, 0x9f, 0x5c, 0x3b, - 0xe5, 0x20, 0x81, 0x00, 0x1c, 0x58, 0x15, 0x92, 0x44, 0x81, 0xce, 0x83, 0xab, 0x19, 0x47, 0xb0, 0x79, 0xe5, 0xcc, - 0xc5, 0x0d, 0xe0, 0xbc, 0xf2, 0xe7, 0xb2, 0xc1, 0x96, 0xf5, 0x88, 0x2a, 0x73, 0xc6, 0x29, 0x06, 0x75, 0xb2, 0x04, - 0x7d, 0x65, 0x29, 0xed, 0x25, 0x68, 0x1a, 0xaf, 0xd8, 0x4a, 0xf9, 0x00, 0xd0, 0x73, 0xb6, 0x52, 0xc6, 0xfe, 0xf8, - 0xf5, 0x19, 0x5b, 0x69, 0x69, 0xf0, 0xf4, 0x6a, 0x76, 0x3e, 0x3b, 0x1b, 0xb0, 0xa3, 0x28, 0xd4, 0x06, 0x0c, 0x81, - 0x8b, 0x4c, 0x10, 0x0c, 0x42, 0x8d, 0xff, 0x32, 0x50, 0x01, 0xc2, 0x88, 0xc7, 0x63, 0x23, 0x8e, 0x58, 0x38, 0x1e, - 0x62, 0x30, 0xb0, 0xe6, 0x0b, 0x12, 0x10, 0x6a, 0x4a, 0x43, 0x5f, 0xcf, 0x70, 0x38, 0x39, 0x98, 0x40, 0x2a, 0x66, - 0x66, 0xaa, 0x30, 0x36, 0x26, 0x11, 0xc4, 0x7f, 0xed, 0xac, 0x17, 0xca, 0xed, 0xae, 0xd1, 0x40, 0xd0, 0x0c, 0xbe, - 0xa8, 0xe2, 0xc9, 0xc1, 0xb0, 0xab, 0x62, 0x1c, 0x85, 0x6b, 0xa3, 0x7c, 0x3b, 0x3b, 0x06, 0x30, 0xdf, 0xb3, 0xa1, - 0x2f, 0x97, 0x38, 0x3b, 0x7c, 0x4c, 0x1e, 0x3e, 0x26, 0xf4, 0x8c, 0x9d, 0x7d, 0xf5, 0x98, 0x9e, 0x29, 0x72, 0x72, - 0x30, 0x89, 0xae, 0x99, 0xc5, 0xc0, 0x39, 0x52, 0x4d, 0xa0, 0x97, 0xa3, 0xb5, 0x50, 0x0b, 0x4c, 0x3b, 0x34, 0x85, - 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x75, 0xbb, 0xe9, 0xd7, 0xed, 0xb6, 0x7a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, 0x6e, 0x31, - 0x93, 0xbf, 0x8f, 0x0f, 0xdc, 0x1c, 0x60, 0x7d, 0xf7, 0x8f, 0x89, 0x69, 0xd2, 0xce, 0xa8, 0xf8, 0x35, 0x3d, 0xc2, - 0x3e, 0x34, 0x8b, 0xec, 0xe8, 0xc3, 0xf0, 0xdf, 0xea, 0x44, 0x7d, 0xf6, 0xd5, 0x11, 0x90, 0x23, 0x90, 0x81, 0x62, - 0x89, 0x60, 0x86, 0x03, 0x4d, 0x01, 0x05, 0x99, 0x1e, 0x77, 0xaa, 0x87, 0x5f, 0x8d, 0x9a, 0x9a, 0x91, 0x6b, 0x98, - 0x1a, 0x6c, 0x0b, 0x7e, 0xa0, 0xba, 0xa1, 0xbf, 0xd1, 0x68, 0x4f, 0xda, 0xc9, 0xcc, 0xbc, 0xa4, 0x36, 0xce, 0xdd, - 0x35, 0x04, 0x74, 0x76, 0x70, 0x8b, 0x92, 0x7d, 0x7d, 0x7c, 0x79, 0x80, 0xab, 0x08, 0x50, 0xc3, 0x58, 0xf0, 0xf5, - 0xe0, 0x52, 0x6f, 0xee, 0x83, 0x80, 0x0c, 0xbe, 0x0e, 0x4e, 0xbe, 0x1e, 0xc8, 0x41, 0x70, 0x7c, 0x78, 0x79, 0x12, - 0x38, 0xe3, 0x7e, 0x08, 0x79, 0xa9, 0x2a, 0x8a, 0x99, 0x30, 0x55, 0x24, 0xb6, 0xf6, 0xdc, 0xd6, 0xab, 0x8c, 0xcf, - 0x68, 0x3a, 0xb5, 0x48, 0xe8, 0x61, 0xca, 0x62, 0xf3, 0x3b, 0x98, 0xf0, 0xab, 0x20, 0x72, 0x41, 0x61, 0x67, 0x79, - 0x14, 0xd3, 0x25, 0xbb, 0x15, 0x61, 0x4a, 0x93, 0xc3, 0x9c, 0x90, 0x28, 0x5c, 0x2a, 0x30, 0x41, 0xf5, 0x3a, 0x81, - 0xb8, 0xb6, 0xee, 0xf3, 0x5b, 0x11, 0x2e, 0x69, 0x7e, 0x98, 0x90, 0x56, 0x11, 0x2e, 0x42, 0xcd, 0xa6, 0xa6, 0x17, - 0x2c, 0x5c, 0xd1, 0x4b, 0x34, 0xd5, 0x5c, 0x87, 0x97, 0xc0, 0xe5, 0xad, 0xe7, 0xab, 0x05, 0xbb, 0x6c, 0x48, 0xdf, - 0x0c, 0x5f, 0x7c, 0x61, 0x7d, 0xf2, 0x80, 0x87, 0x74, 0x7e, 0x78, 0x29, 0xd8, 0x00, 0x5c, 0x67, 0xfc, 0xe6, 0x3b, - 0x79, 0xab, 0xe7, 0xa5, 0x3d, 0xc5, 0x38, 0x33, 0xed, 0xc4, 0xa4, 0x9d, 0x90, 0xfb, 0xf7, 0x6d, 0xdf, 0xbd, 0x78, - 0xad, 0x5c, 0x56, 0x2d, 0x43, 0x12, 0xaf, 0x95, 0xeb, 0x34, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, - 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, 0x65, 0xa1, 0x70, 0xec, 0x5f, 0x65, 0x2c, 0x5e, 0x37, 0x90, 0x81, - 0x91, 0x7b, 0x7b, 0x95, 0x31, 0x2f, 0x06, 0x6d, 0xbe, 0xf6, 0x42, 0xf7, 0x79, 0xe9, 0xcb, 0x16, 0xef, 0xe5, 0x94, - 0x1a, 0x46, 0x22, 0x7a, 0x30, 0x56, 0x66, 0x94, 0x2a, 0x51, 0x6b, 0xd0, 0x88, 0x60, 0x63, 0x17, 0x0c, 0x14, 0x9c, - 0x50, 0xb9, 0xa7, 0xce, 0xf6, 0xed, 0x94, 0x4a, 0x0f, 0x68, 0x97, 0x1a, 0x55, 0xb9, 0x5b, 0x66, 0x92, 0x55, 0x83, - 0x60, 0xf4, 0x67, 0x29, 0xc5, 0x0c, 0xef, 0x8c, 0x2c, 0x98, 0x82, 0x95, 0xa0, 0xaa, 0x65, 0x58, 0x0e, 0x39, 0x6a, - 0xf1, 0x8c, 0x4f, 0xaa, 0xd4, 0x3f, 0x3a, 0x82, 0x06, 0xa7, 0xeb, 0x56, 0xd0, 0xe0, 0xc7, 0xe3, 0xc7, 0x7a, 0xa0, - 0xd7, 0x6b, 0xed, 0x78, 0xe8, 0xf3, 0xdb, 0x88, 0x37, 0xae, 0x7b, 0x4f, 0xb5, 0x56, 0xa1, 0x0c, 0xb4, 0x58, 0x51, - 0xb9, 0x52, 0x4b, 0xba, 0xdf, 0x45, 0x00, 0x2c, 0x62, 0x63, 0x36, 0xde, 0xb5, 0xcd, 0x0a, 0x41, 0xa3, 0xcb, 0x4e, - 0x36, 0xf1, 0x80, 0x25, 0xba, 0xb5, 0x83, 0x09, 0x8d, 0x4f, 0x58, 0xd9, 0xef, 0xe7, 0x27, 0x40, 0x4f, 0xb5, 0x11, - 0x53, 0x01, 0x47, 0xfe, 0x97, 0x56, 0x64, 0x8a, 0x02, 0x9b, 0x35, 0x75, 0xb7, 0xc6, 0x32, 0x12, 0x7d, 0x99, 0xd2, - 0xe5, 0x09, 0xcf, 0x80, 0xe9, 0x62, 0xdd, 0x72, 0x5c, 0xd9, 0x55, 0x1c, 0x79, 0x2a, 0x2c, 0x2b, 0xce, 0xab, 0x70, - 0xbc, 0xf5, 0xf8, 0x06, 0x87, 0x86, 0x4d, 0x5b, 0xf9, 0x43, 0x08, 0x0b, 0xe1, 0x55, 0x06, 0xb7, 0x11, 0x6d, 0x27, - 0x81, 0xca, 0x1b, 0x73, 0x9d, 0x50, 0x36, 0xb7, 0x17, 0x6b, 0xcf, 0x20, 0x9d, 0x98, 0x03, 0xa5, 0x1a, 0x41, 0x6b, - 0x34, 0x0b, 0xaa, 0x46, 0x3c, 0x72, 0xe6, 0x5f, 0xce, 0x20, 0x56, 0xcb, 0x97, 0x34, 0x95, 0xa2, 0x01, 0x18, 0x17, - 0xc0, 0xe5, 0xe9, 0x97, 0x77, 0x3f, 0xbd, 0xe7, 0x71, 0x91, 0x2c, 0xdf, 0xc6, 0x45, 0x7c, 0x55, 0x86, 0x1b, 0x35, - 0x46, 0x71, 0x4d, 0xa6, 0x62, 0xc0, 0xa4, 0x59, 0x49, 0xcd, 0x5d, 0xa9, 0x09, 0x31, 0xd6, 0x99, 0xac, 0xcb, 0x4a, - 0x5e, 0x35, 0x2a, 0x5d, 0x17, 0x19, 0x7e, 0xdc, 0xf2, 0x39, 0x3d, 0x04, 0x60, 0x53, 0xe3, 0x42, 0x1a, 0x49, 0x5d, - 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, 0xba, 0x5e, 0xb2, 0x27, 0xe3, 0x47, 0xd3, 0x57, 0x59, 0x98, 0x0d, - 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8d, 0xc7, 0x64, - 0xd3, 0x16, 0x0f, 0xf0, 0x30, 0x5d, 0x87, 0x05, 0x99, 0xe9, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, 0x2a, 0x00, 0x64, 0x4b, - 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0x93, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, 0x37, 0xf3, 0xd2, 0xf7, - 0x28, 0x92, 0xc6, 0x65, 0x69, 0xa7, 0x52, 0xa9, 0xf6, 0xcc, 0xcc, 0x75, 0x0d, 0x62, 0x52, 0x84, 0xba, 0xee, 0xd2, - 0xab, 0x7b, 0xb7, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, 0xba, 0x22, 0x6a, 0x7a, - 0xb9, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xeb, 0x35, 0x05, 0xa5, 0x60, 0xb4, 0x5a, 0x7b, 0x0b, 0xf7, 0xa9, 0x6c, - 0x5c, 0x58, 0x32, 0xbd, 0x5a, 0x94, 0x94, 0x50, 0xdd, 0x54, 0x8c, 0x94, 0x30, 0x52, 0x1a, 0x9e, 0xca, 0xf7, 0x02, - 0x8f, 0xf3, 0x3c, 0x88, 0x5a, 0x5e, 0x60, 0xa7, 0x15, 0x39, 0x05, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, - 0x05, 0xea, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, 0xbf, 0x15, 0x2c, 0xf0, 0xf8, 0xd6, 0x2b, 0xdc, 0x46, 0xbf, 0x15, - 0x3e, 0x2d, 0x7d, 0x23, 0x7d, 0x57, 0x17, 0x4f, 0xda, 0x9b, 0x8d, 0x92, 0x65, 0x96, 0xa7, 0xaf, 0x65, 0xca, 0x41, - 0x64, 0x86, 0xd6, 0xa0, 0xec, 0x44, 0x34, 0x6e, 0x78, 0x60, 0xc4, 0xd8, 0xb8, 0xf1, 0xfd, 0x98, 0x81, 0x6c, 0x18, - 0xac, 0xbe, 0x59, 0x2a, 0x93, 0x35, 0x20, 0x6c, 0x68, 0xf9, 0x89, 0xc6, 0xdb, 0x08, 0xf5, 0xf5, 0x0b, 0xdc, 0xe6, - 0x4a, 0xdf, 0xe7, 0xfc, 0xc7, 0x8c, 0xfe, 0x88, 0xc0, 0x2f, 0xf1, 0x0a, 0xe4, 0x1e, 0x4f, 0xa1, 0x6e, 0x84, 0xed, - 0xe5, 0x18, 0x2c, 0x09, 0xd1, 0x51, 0x44, 0xc5, 0x02, 0x05, 0x4d, 0x61, 0x10, 0x45, 0xd4, 0x05, 0x73, 0x78, 0x9e, - 0xcb, 0xe4, 0xe3, 0xd4, 0xf8, 0xcc, 0x0f, 0x63, 0x8c, 0x21, 0x1d, 0x0c, 0xc2, 0x6a, 0x16, 0x0c, 0xc7, 0xa3, 0xc9, - 0xd1, 0x13, 0x38, 0xb7, 0x83, 0x71, 0x40, 0x06, 0x41, 0x5d, 0xae, 0x62, 0x41, 0xcb, 0xeb, 0x4b, 0x5b, 0x06, 0x7e, - 0x5c, 0x07, 0x83, 0xdf, 0x0a, 0x4f, 0xf1, 0x0e, 0x9a, 0x93, 0x3b, 0x19, 0x06, 0x01, 0xbd, 0x5c, 0x13, 0x90, 0x94, - 0xf5, 0x34, 0x3f, 0xa9, 0x0f, 0x37, 0xa6, 0xb4, 0x7f, 0xe6, 0xf0, 0x82, 0xc3, 0x0e, 0x09, 0x14, 0x48, 0xe3, 0x69, - 0x36, 0x7a, 0xa9, 0x14, 0xb9, 0x6f, 0x0b, 0x0e, 0x77, 0xe6, 0x9e, 0x33, 0x3d, 0x72, 0x0a, 0x89, 0x66, 0x16, 0x70, - 0x23, 0x7f, 0x29, 0xae, 0xe3, 0x3c, 0x4b, 0x0f, 0x9a, 0x6f, 0x0e, 0xca, 0x3b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, 0x58, - 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xc7, 0xcc, 0x64, 0xc6, 0x23, 0xf0, 0x08, - 0x6c, 0xfa, 0x40, 0x16, 0x77, 0xce, 0x25, 0xc9, 0xdf, 0x4c, 0xa5, 0xbd, 0xea, 0x95, 0x3b, 0x05, 0x59, 0xaf, 0xb6, - 0x72, 0xd7, 0xad, 0xcf, 0xbe, 0xe9, 0xf0, 0x0a, 0x3c, 0x93, 0xe0, 0x16, 0xd9, 0xef, 0x37, 0x05, 0x95, 0xc2, 0xa8, - 0x88, 0x77, 0x92, 0x6b, 0xf4, 0x6f, 0xf7, 0xc6, 0x46, 0x91, 0xdc, 0xf2, 0xfe, 0x01, 0xd4, 0x99, 0xbc, 0x2b, 0x6e, - 0xe7, 0x10, 0xb5, 0x75, 0x37, 0x1e, 0x78, 0x6f, 0xd0, 0x2e, 0x6b, 0x8e, 0x60, 0xcb, 0x8b, 0x83, 0x0c, 0xc6, 0x02, - 0x67, 0x65, 0xa4, 0xd4, 0xb8, 0x56, 0x46, 0x03, 0x6a, 0x93, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, - 0x99, 0xc6, 0xdb, 0x40, 0xec, 0xb7, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, - 0xd7, 0xc6, 0xd4, 0x40, 0x43, 0x0f, 0xa2, 0x46, 0x2a, 0xe2, 0xec, 0xe4, 0x29, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, - 0xca, 0x8e, 0x17, 0x13, 0x82, 0x27, 0xef, 0xf3, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x45, 0x8a, 0x86, 0x50, 0x89, 0x14, - 0xd1, 0x6b, 0x88, 0x2f, 0x58, 0xe2, 0xef, 0x32, 0x7a, 0x97, 0xd2, 0x38, 0x4d, 0x31, 0xfd, 0x59, 0x01, 0x3f, 0x9f, - 0x02, 0xca, 0x25, 0xee, 0x84, 0xe8, 0x4c, 0x82, 0xbd, 0x1a, 0x44, 0xf7, 0xaa, 0x38, 0x60, 0x8a, 0x46, 0xb7, 0x82, - 0x22, 0x66, 0x1d, 0x66, 0xff, 0xa5, 0x40, 0xa1, 0x90, 0x2a, 0xe6, 0x57, 0x61, 0x1f, 0xa2, 0x6a, 0x0d, 0xe5, 0x9c, - 0xbe, 0x7d, 0x69, 0x86, 0x34, 0xba, 0x95, 0x54, 0x6f, 0x6d, 0x3c, 0xb6, 0x10, 0xa5, 0x27, 0xba, 0x5a, 0xd3, 0xb3, - 0x78, 0x95, 0x45, 0x1b, 0xc0, 0x9f, 0x78, 0xfb, 0xf2, 0xa9, 0xb2, 0x30, 0x79, 0x99, 0x81, 0xe2, 0xe0, 0xf4, 0xed, - 0xcb, 0x57, 0x32, 0x5d, 0xe7, 0x3c, 0xba, 0x93, 0x48, 0x5a, 0x4f, 0xdf, 0xbe, 0xfc, 0x19, 0xcd, 0xbd, 0xde, 0x15, - 0xf0, 0xfe, 0x05, 0xf0, 0x96, 0x51, 0xb2, 0x86, 0x3e, 0xa9, 0xdf, 0xf9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xff, - 0x4c, 0x6b, 0x4f, 0x5a, 0xf5, 0x57, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, - 0x41, 0xf4, 0xf5, 0xc1, 0xed, 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0x0e, 0x0f, 0x6f, 0x6e, 0x6e, - 0x46, 0x37, 0x8f, 0x46, 0xb2, 0xb8, 0x3c, 0x9c, 0x7c, 0xfb, 0xed, 0xb7, 0x87, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, - 0x5e, 0x11, 0x3e, 0x60, 0x01, 0x22, 0x76, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, - 0xce, 0xd7, 0xc7, 0xe5, 0xf5, 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0xa3, 0xf1, 0x78, 0x7c, 0x08, 0x12, 0xa8, 0xaf, 0x07, - 0x7c, 0x10, 0x9c, 0x04, 0x83, 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x49, 0xe0, 0x19, 0xd8, 0x36, 0x58, 0x44, 0x07, - 0xe2, 0x12, 0x1c, 0x5e, 0xd2, 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0xa3, 0x27, 0x7e, 0xda, 0xff, - 0x52, 0x69, 0x8f, 0xfc, 0xb4, 0x63, 0x4c, 0x7b, 0xf4, 0xd4, 0x4f, 0x3b, 0x51, 0x69, 0xcf, 0xfd, 0xb4, 0xff, 0x5d, - 0x0e, 0x20, 0xf5, 0xc0, 0xb7, 0xfe, 0x3b, 0xf3, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, - 0xb8, 0xbd, 0xca, 0x69, 0x30, 0xc0, 0xf6, 0x7a, 0x46, 0x1e, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, - 0x60, 0x21, 0x83, 0xaf, 0x03, 0xf2, 0xb5, 0x3e, 0xd2, 0xae, 0x05, 0xdb, 0x04, 0x2e, 0x34, 0xeb, 0xd0, 0x06, 0x4c, - 0xf3, 0xa5, 0x71, 0x35, 0xfd, 0xbd, 0xe8, 0xce, 0x86, 0xb7, 0x44, 0xe5, 0xa6, 0x1b, 0xd4, 0xf4, 0x01, 0x78, 0x27, - 0x40, 0xa3, 0xa2, 0xe0, 0x3a, 0x2e, 0xc2, 0xe1, 0xb0, 0xbc, 0xbe, 0x24, 0x60, 0x97, 0xb9, 0xe2, 0x71, 0x15, 0x05, - 0x42, 0x0e, 0xd5, 0xcf, 0x40, 0x45, 0x02, 0x0b, 0x10, 0xca, 0x08, 0xfe, 0x0b, 0x6a, 0xfa, 0x56, 0xb2, 0x4d, 0x30, - 0xbc, 0xe1, 0xe7, 0x1f, 0xb3, 0x6a, 0xa8, 0x44, 0x8b, 0xd7, 0x82, 0xc2, 0x0f, 0xf8, 0xeb, 0xaa, 0x8e, 0x7e, 0x07, - 0x37, 0xee, 0xa6, 0x86, 0xfd, 0xad, 0xf4, 0x1c, 0xda, 0xe4, 0x3c, 0x5b, 0x4c, 0x5b, 0x07, 0xfa, 0x03, 0x49, 0xaa, - 0x79, 0x36, 0x08, 0x86, 0xc1, 0x80, 0x2f, 0xd8, 0x03, 0x39, 0xe7, 0x9e, 0xf9, 0xd4, 0xa9, 0xf4, 0xa7, 0x79, 0x96, - 0x0d, 0xc0, 0x37, 0x05, 0xf9, 0x91, 0xc3, 0xff, 0x9e, 0x0f, 0x51, 0x78, 0x38, 0x78, 0x70, 0x48, 0x66, 0xc1, 0xea, - 0x16, 0x3d, 0x3a, 0xa3, 0x20, 0x13, 0x4b, 0x5e, 0x64, 0x95, 0xb7, 0x54, 0x6e, 0xd7, 0x6d, 0x2f, 0x8f, 0xbd, 0x67, - 0xf3, 0x2a, 0x16, 0x81, 0x3a, 0xe7, 0x40, 0xf1, 0x86, 0xb2, 0xa7, 0xb2, 0x29, 0x21, 0xd5, 0x86, 0xbc, 0x61, 0x39, - 0x60, 0xc1, 0x71, 0x6f, 0x38, 0x3c, 0x08, 0x06, 0x4e, 0x9d, 0x3b, 0x08, 0x0e, 0x86, 0xc3, 0x93, 0xc0, 0xdd, 0x87, - 0xb2, 0x91, 0xbb, 0x33, 0xd2, 0x82, 0xfd, 0x55, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, - 0x00, 0xe8, 0x23, 0x25, 0x01, 0x33, 0xb0, 0x32, 0x03, 0x08, 0x55, 0x4e, 0x63, 0x76, 0x07, 0xcc, 0x23, 0x70, 0xcc, - 0x0a, 0x26, 0x0b, 0x10, 0x4b, 0x02, 0x9c, 0xbb, 0x20, 0x8a, 0x75, 0x21, 0xa7, 0x10, 0x04, 0x00, 0x7f, 0x12, 0x53, - 0x0a, 0x26, 0xe9, 0xd8, 0x8d, 0x20, 0x88, 0xe3, 0xb3, 0x6b, 0xd1, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, - 0x10, 0x03, 0xc3, 0x07, 0xf7, 0x73, 0x50, 0x7a, 0x58, 0xbd, 0x13, 0x72, 0xc1, 0x77, 0xdc, 0xb1, 0x50, 0xd7, 0x70, - 0xf5, 0x84, 0x83, 0xe0, 0x8e, 0x6b, 0x16, 0x60, 0x54, 0x15, 0xeb, 0xb2, 0xe2, 0xe9, 0x87, 0xbb, 0x15, 0xc4, 0x02, - 0xc4, 0x01, 0x7d, 0x2b, 0xf3, 0x2c, 0xb9, 0x0b, 0x9d, 0x3d, 0xd7, 0x46, 0xa5, 0xff, 0xf0, 0xe1, 0xd5, 0x4f, 0x11, - 0x88, 0x1c, 0x6b, 0x43, 0xe9, 0xef, 0x38, 0x9e, 0x4d, 0x7e, 0xc4, 0x2b, 0x7f, 0x63, 0xdf, 0x71, 0x7b, 0x7a, 0xf4, - 0xfb, 0x50, 0x37, 0xbd, 0xe3, 0xb3, 0x3b, 0x3e, 0x72, 0xc5, 0xa1, 0xba, 0xc2, 0x7d, 0xfd, 0x71, 0xed, 0x1b, 0x21, - 0xdd, 0x3f, 0xcf, 0x94, 0x37, 0xe6, 0x47, 0x3b, 0x18, 0x06, 0xc1, 0x54, 0x0b, 0x25, 0x21, 0x0a, 0x09, 0x53, 0x02, - 0x86, 0xe8, 0x40, 0x2f, 0xab, 0x29, 0x72, 0x6e, 0x6a, 0x64, 0xe1, 0xfd, 0x80, 0x69, 0xa1, 0x43, 0x23, 0x87, 0xf2, - 0x83, 0xc3, 0x09, 0x63, 0x16, 0x7e, 0xab, 0x84, 0xe9, 0x57, 0x8b, 0xca, 0x39, 0x88, 0x1e, 0x80, 0x31, 0xae, 0xe0, - 0x05, 0x74, 0x85, 0xdd, 0xac, 0x55, 0x94, 0x10, 0x04, 0xd3, 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, 0xaa, - 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, 0x06, 0x7e, 0xc9, 0x7e, 0x29, 0xd0, 0xb3, 0x7c, 0x2a, - 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0xb8, 0x7e, 0x3c, - 0x7d, 0x25, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, 0xc5, 0x44, 0xc1, 0x3e, 0x42, 0xbf, 0xda, 0x36, 0xfa, - 0xec, 0x76, 0xad, 0x37, 0x83, 0x12, 0x1d, 0xf3, 0x1a, 0x05, 0xd7, 0x4a, 0xa1, 0x60, 0xb4, 0xb7, 0xf1, 0x67, 0x38, - 0x72, 0xab, 0xdb, 0x43, 0xef, 0xb7, 0x2a, 0xbe, 0x7c, 0x8d, 0xbe, 0x9d, 0xf6, 0xe7, 0xa8, 0x92, 0xbf, 0xac, 0x56, - 0xe0, 0x43, 0x05, 0x91, 0x56, 0x2c, 0x4e, 0x2f, 0xd4, 0xf3, 0xfe, 0xed, 0xe9, 0x6b, 0xf0, 0xa3, 0xc4, 0xdf, 0xbf, - 0x7e, 0x1f, 0xd4, 0x64, 0x1a, 0xcf, 0x0a, 0xf3, 0xa1, 0xcd, 0x01, 0xa1, 0x5a, 0x5c, 0x9a, 0x7d, 0x3f, 0x8b, 0x9b, - 0xec, 0xbb, 0x66, 0xeb, 0x69, 0xd1, 0x44, 0x92, 0x32, 0xdc, 0x3e, 0x18, 0x10, 0xe8, 0x03, 0x44, 0x71, 0xf6, 0x05, - 0x8d, 0x21, 0xcd, 0x67, 0xf6, 0xfd, 0x08, 0x81, 0x2f, 0x77, 0x42, 0xaa, 0x71, 0x85, 0x45, 0xa3, 0x87, 0x7c, 0xc6, - 0x23, 0x65, 0x58, 0xf4, 0x0e, 0x13, 0x88, 0x33, 0x9c, 0x56, 0xef, 0x11, 0x03, 0x1a, 0xef, 0x06, 0x5a, 0xf6, 0x10, - 0x65, 0xd4, 0x65, 0x6f, 0x58, 0x7c, 0xbf, 0x5f, 0x87, 0x99, 0xb5, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x1b, 0x80, 0x53, - 0x8e, 0x2c, 0x5f, 0x65, 0x36, 0xba, 0x5a, 0x62, 0x7a, 0x13, 0x41, 0x6c, 0x22, 0x9d, 0x0e, 0x6b, 0x57, 0xa7, 0xea, - 0x5d, 0xed, 0x7c, 0x26, 0x7a, 0x15, 0x68, 0xe5, 0xda, 0xf6, 0x78, 0x08, 0xff, 0xa9, 0xa5, 0x15, 0x36, 0xc2, 0x9e, - 0x8b, 0x2f, 0x3c, 0xc7, 0xe6, 0x04, 0x34, 0xb8, 0x92, 0x29, 0x00, 0x67, 0x69, 0x35, 0x1a, 0x35, 0xc2, 0x3e, 0x2b, - 0xe7, 0x73, 0xd8, 0x5a, 0x88, 0xa7, 0x05, 0xe0, 0xc0, 0x4d, 0x4c, 0x4e, 0xde, 0x8d, 0xc9, 0x39, 0xfd, 0xa8, 0xe0, - 0xbe, 0x83, 0xb3, 0x72, 0x19, 0xa7, 0xf2, 0x06, 0xb0, 0x29, 0x03, 0x3f, 0x15, 0x4b, 0xf5, 0x12, 0x92, 0x25, 0x4f, - 0x3e, 0xa2, 0xd5, 0x46, 0x1a, 0x00, 0x57, 0x39, 0x35, 0x96, 0x7b, 0x0a, 0x34, 0xd5, 0x95, 0xa2, 0x12, 0xe2, 0xaa, - 0x8a, 0x93, 0xe5, 0x7b, 0x4c, 0x0d, 0x37, 0xd0, 0x8b, 0x28, 0x90, 0x2b, 0x2e, 0x80, 0xa4, 0xe7, 0xec, 0x5f, 0x99, - 0xc6, 0x5e, 0x7f, 0x23, 0x51, 0xc0, 0xa4, 0x51, 0x94, 0xb1, 0x52, 0xf6, 0x52, 0x9a, 0xe8, 0x77, 0x41, 0x50, 0xbb, - 0x97, 0x7f, 0x41, 0xdd, 0x4f, 0xa1, 0x15, 0x61, 0x03, 0xbc, 0x50, 0x83, 0x1f, 0xa6, 0x76, 0xc9, 0x79, 0x40, 0x86, - 0xce, 0xfb, 0xac, 0xb6, 0x5b, 0xfd, 0xe9, 0x12, 0xb0, 0x5e, 0x53, 0xe3, 0x53, 0x18, 0x26, 0xc4, 0xc4, 0x4a, 0xb6, - 0xca, 0x4a, 0xbb, 0xa1, 0x4c, 0x3b, 0xe9, 0x92, 0x79, 0x2d, 0x9c, 0xe6, 0x3d, 0xc6, 0x96, 0x23, 0x95, 0xbb, 0xdf, - 0x0f, 0xcd, 0x4f, 0x96, 0xd3, 0x37, 0x3a, 0x84, 0xb5, 0x37, 0x1e, 0x34, 0x27, 0x5a, 0x5d, 0xd5, 0xd1, 0x0f, 0xe8, - 0x00, 0xcc, 0xb4, 0x45, 0xa8, 0x74, 0xc1, 0xb7, 0x7d, 0x25, 0x2a, 0x2e, 0x49, 0x58, 0x2a, 0x09, 0xec, 0xec, 0xa6, - 0x64, 0x67, 0x13, 0x10, 0xcf, 0x70, 0xd7, 0xd3, 0x62, 0x27, 0xa4, 0x09, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x55, - 0x97, 0x90, 0x8d, 0x31, 0x74, 0xf1, 0x2f, 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x09, 0x0a, 0x55, 0xee, 0xb6, - 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, 0x37, 0xea, 0x66, 0xd4, 0x54, 0x75, 0xea, 0x25, 0xf8, 0x38, 0xcd, 0xba, - 0x0a, 0x32, 0x0b, 0xbb, 0x2a, 0xd6, 0x3c, 0xd0, 0xb1, 0xba, 0x94, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x23, 0x63, - 0x6c, 0x61, 0x0d, 0x47, 0xda, 0x1e, 0x37, 0x3d, 0x41, 0xe8, 0x27, 0x6c, 0x28, 0x81, 0x9b, 0xce, 0xf6, 0xd4, 0x34, - 0xf3, 0x01, 0x11, 0x87, 0x01, 0x05, 0x92, 0x8d, 0x43, 0x9a, 0x23, 0x7d, 0x41, 0xd2, 0x84, 0x81, 0xb2, 0x15, 0xcf, - 0x09, 0xb2, 0xa2, 0xd0, 0xb3, 0x75, 0x55, 0x43, 0xfc, 0x5c, 0x86, 0x39, 0x5a, 0x72, 0x2a, 0x3c, 0x4d, 0x90, 0x89, - 0xed, 0x69, 0x9b, 0x99, 0x0c, 0x47, 0xc9, 0x02, 0xf3, 0x2b, 0x88, 0x12, 0x77, 0xa6, 0x59, 0x95, 0x83, 0x71, 0x01, - 0x0b, 0xb4, 0xf2, 0x3d, 0xa8, 0x1b, 0x6b, 0x68, 0xa3, 0x61, 0x99, 0xdd, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, - 0x29, 0x96, 0x97, 0x29, 0x44, 0x7b, 0x21, 0xf3, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x18, 0x12, 0xd6, 0x51, 0xf6, 0xa4, - 0x4d, 0x0d, 0xa0, 0xa7, 0x5e, 0x00, 0xf8, 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf7, 0x57, 0x05, 0xe3, 0xd2, 0x0d, 0x82, - 0x14, 0xbd, 0x49, 0xc1, 0x9c, 0xd7, 0xa3, 0xa4, 0xde, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, - 0x93, 0x57, 0x52, 0x13, 0x9b, 0x30, 0xc1, 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x36, 0x0d, 0x93, 0x36, - 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0x09, 0x81, 0xca, 0x5e, 0xe2, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0x1b, - 0x0d, 0x4c, 0xdc, 0xea, 0xca, 0xd6, 0x61, 0x42, 0xc3, 0x25, 0xd5, 0xce, 0x4e, 0x2a, 0xf9, 0xa2, 0xbd, 0x2e, 0x2f, - 0x6c, 0x1f, 0x74, 0x2c, 0xb5, 0xae, 0xe1, 0x81, 0xe6, 0x35, 0xbb, 0xb8, 0x62, 0x9a, 0x26, 0x1a, 0xeb, 0x21, 0x65, - 0xc9, 0xb1, 0xae, 0xa7, 0x2b, 0x5c, 0x2d, 0x33, 0x0d, 0x74, 0x2f, 0xf1, 0x42, 0x0f, 0xf8, 0xe0, 0xe1, 0x8a, 0x44, - 0x17, 0xd8, 0x6c, 0xb6, 0xaa, 0xc9, 0x34, 0xdf, 0x97, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, - 0x69, 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, - 0xe8, 0xde, 0xf9, 0x22, 0x75, 0xf3, 0x0b, 0xb0, 0x8d, 0xda, 0x18, 0xd3, 0x2c, 0xb1, 0x0e, 0x13, 0x65, 0x61, 0x8d, - 0x2c, 0xe4, 0x12, 0x7c, 0x30, 0x77, 0x9b, 0x3a, 0x7d, 0xde, 0x41, 0x84, 0xfd, 0x2e, 0x7a, 0x3c, 0xc2, 0x58, 0xb1, - 0x06, 0x89, 0x61, 0x15, 0xd6, 0xb4, 0xb9, 0x1c, 0xa2, 0x9c, 0x9a, 0x25, 0x13, 0x2d, 0xa9, 0x4f, 0x29, 0xa2, 0x14, - 0xcc, 0x8d, 0xa7, 0x65, 0xc3, 0x94, 0x10, 0x21, 0x2b, 0xa4, 0x03, 0xaa, 0xb5, 0xd0, 0x52, 0x4d, 0x10, 0xf0, 0xd0, - 0xcb, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0xc8, 0x70, 0x23, 0x8e, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x74, 0xb7, 0x97, - 0x17, 0x56, 0x9f, 0x96, 0x6d, 0x75, 0x10, 0xd7, 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, - 0x67, 0x11, 0xfa, 0x76, 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0x48, 0xeb, 0x35, 0x15, 0x03, 0xd4, 0xce, 0x63, 0x17, - 0xb1, 0x4a, 0x77, 0x0b, 0x51, 0xde, 0xa8, 0xac, 0xdf, 0xaf, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0xfe, 0x6a, - 0xbd, 0x07, 0x02, 0xfd, 0xe9, 0xfa, 0xb3, 0x10, 0xe8, 0xcf, 0xb2, 0x2f, 0x81, 0x40, 0x7f, 0xba, 0xfe, 0x9f, 0x86, - 0x40, 0x7f, 0xb5, 0xf6, 0x20, 0xd0, 0xd5, 0x60, 0xfc, 0xa3, 0x60, 0xc1, 0x9b, 0xd7, 0x01, 0x7d, 0x26, 0x59, 0xf0, - 0xe6, 0xc5, 0x0b, 0x4f, 0x98, 0xfe, 0x83, 0xd0, 0x48, 0xfe, 0x46, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, - 0x3e, 0x50, 0x51, 0x06, 0x40, 0xf4, 0xe5, 0x6f, 0x59, 0xb5, 0x0c, 0x83, 0xc3, 0x80, 0xcc, 0x1c, 0x24, 0xe8, 0x70, - 0xd2, 0xb8, 0xbd, 0xfd, 0x22, 0x1a, 0x42, 0x1d, 0x1b, 0x79, 0x00, 0xbe, 0xf2, 0x44, 0xf6, 0xfe, 0x0d, 0x11, 0x3f, - 0x99, 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x0f, 0xd6, 0x9e, - 0x6d, 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, - 0xe5, 0xbf, 0xbc, 0x7b, 0x69, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, - 0xfe, 0x78, 0xb0, 0xe9, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x93, - 0xd5, 0x87, 0x0f, 0x36, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x53, 0xc2, 0x0f, 0x5e, 0xff, - 0xe1, 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, - 0xa8, 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, - 0x9d, 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, - 0x2e, 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xbb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, - 0x79, 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0x7c, 0xff, 0x45, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, - 0x2e, 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, - 0x95, 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0xc9, 0x84, - 0x5d, 0x5e, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc6, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, - 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x0a, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x41, 0x9d, 0x95, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x7b, 0x7f, 0x1a, 0xb9, 0xb2, 0x28, 0xfa, + 0xf7, 0x3d, 0x9f, 0xc2, 0xee, 0x9d, 0xf1, 0xb4, 0x8c, 0x68, 0x03, 0x36, 0x8e, 0xd3, 0x58, 0xe6, 0xe4, 0x39, 0xc9, + 0x3c, 0x92, 0x4c, 0x9c, 0x64, 0x26, 0xc3, 0xb0, 0x33, 0xa2, 0x11, 0xa0, 0xa4, 0x91, 0x98, 0x96, 0x88, 0xed, 0x01, + 0xbe, 0xfb, 0xfd, 0x95, 0x1e, 0xdd, 0x6a, 0x20, 0x59, 0x6b, 0x9d, 0x7b, 0xce, 0xfd, 0x9d, 0x3d, 0x7b, 0xc5, 0xb4, + 0xde, 0x2a, 0x95, 0x4a, 0x55, 0xa5, 0xaa, 0xd2, 0xe5, 0xe1, 0x58, 0x66, 0xfa, 0x6e, 0xc1, 0x0e, 0x66, 0x7a, 0x9e, + 0x5f, 0x5d, 0xba, 0x7f, 0x19, 0x1d, 0x5f, 0x5d, 0xe6, 0x5c, 0x7c, 0x3e, 0x28, 0x58, 0x4e, 0x78, 0x26, 0xc5, 0xc1, + 0xac, 0x60, 0x13, 0x32, 0xa6, 0x9a, 0xa6, 0x7c, 0x4e, 0xa7, 0xec, 0xe0, 0xe4, 0xea, 0x72, 0xce, 0x34, 0x3d, 0xc8, + 0x66, 0xb4, 0x50, 0x4c, 0x93, 0x77, 0x6f, 0x9f, 0x35, 0x2f, 0xae, 0x2e, 0x55, 0x56, 0xf0, 0x85, 0x3e, 0x80, 0x26, + 0xc9, 0x5c, 0x8e, 0x97, 0x39, 0xbb, 0x3a, 0x39, 0xb9, 0xb9, 0xb9, 0x49, 0x3e, 0xa9, 0xff, 0xf1, 0x85, 0x16, 0x07, + 0xbf, 0x16, 0xe4, 0xd5, 0xe8, 0x13, 0xcb, 0x74, 0x32, 0x66, 0x13, 0x2e, 0xd8, 0xeb, 0x42, 0x2e, 0x58, 0xa1, 0xef, + 0x7a, 0x90, 0xf9, 0x47, 0x41, 0x62, 0x8e, 0x35, 0x66, 0x88, 0x5c, 0xe9, 0x03, 0x2e, 0x0e, 0x78, 0xff, 0xd7, 0xc2, + 0xa4, 0xac, 0x98, 0x58, 0xce, 0x59, 0x41, 0x47, 0x39, 0x4b, 0x0f, 0x5b, 0x38, 0x93, 0x62, 0xc2, 0xa7, 0xcb, 0xf2, + 0xfb, 0xa6, 0xe0, 0xda, 0xff, 0xfe, 0x42, 0xf3, 0x25, 0x4b, 0xd9, 0x06, 0xa5, 0x7c, 0xa0, 0x87, 0x84, 0x99, 0x96, + 0x3f, 0x57, 0x0d, 0xc7, 0x7f, 0x98, 0x26, 0xef, 0x16, 0x4c, 0x4e, 0x0e, 0xf4, 0x21, 0x89, 0xd4, 0xdd, 0x7c, 0x24, + 0xf3, 0xa8, 0xaf, 0x1b, 0x51, 0x94, 0x42, 0x19, 0xcc, 0x50, 0x2f, 0x93, 0x42, 0xe9, 0x03, 0xc1, 0xc9, 0x0d, 0x17, + 0x63, 0x79, 0x83, 0x3f, 0x0b, 0x22, 0x78, 0x72, 0x3d, 0xa3, 0x63, 0x79, 0xf3, 0x46, 0x4a, 0x7d, 0x74, 0x14, 0xbb, + 0xef, 0xbb, 0xc7, 0xd7, 0xd7, 0x84, 0x90, 0x2f, 0x92, 0x8f, 0x0f, 0x5a, 0xeb, 0x75, 0x90, 0x9a, 0x08, 0xaa, 0xf9, + 0x17, 0x66, 0x2b, 0xa1, 0xa3, 0xa3, 0x88, 0x8e, 0xe5, 0x42, 0xb3, 0xf1, 0xb5, 0xbe, 0xcb, 0xd9, 0xf5, 0x8c, 0x31, + 0xad, 0x22, 0x2e, 0x0e, 0x9e, 0xc8, 0x6c, 0x39, 0x67, 0x42, 0x27, 0x8b, 0x42, 0x6a, 0x09, 0x03, 0x3b, 0x3a, 0x8a, + 0x0a, 0xb6, 0xc8, 0x69, 0xc6, 0x20, 0xff, 0xf1, 0xf5, 0x75, 0x55, 0xa3, 0x2a, 0x84, 0xaf, 0x05, 0xb9, 0x36, 0x43, + 0x8f, 0x11, 0xfe, 0x4d, 0x10, 0xc1, 0x6e, 0x0e, 0x7e, 0x63, 0xf4, 0xf3, 0x2f, 0x74, 0xd1, 0xcb, 0x72, 0xaa, 0xd4, + 0xc1, 0x4b, 0xb9, 0x32, 0xd3, 0x28, 0x96, 0x99, 0x96, 0x45, 0xac, 0x31, 0xc3, 0x02, 0xad, 0xf8, 0x24, 0xd6, 0x33, + 0xae, 0x92, 0x8f, 0xf7, 0x32, 0xa5, 0xde, 0x30, 0xb5, 0xcc, 0xf5, 0x3d, 0x72, 0xd8, 0xc2, 0xe2, 0x90, 0x90, 0x6b, + 0x81, 0xf4, 0xac, 0x90, 0x37, 0x07, 0x4f, 0x8b, 0x42, 0x16, 0x71, 0xf4, 0xf8, 0xfa, 0xda, 0x96, 0x38, 0xe0, 0xea, + 0x40, 0x48, 0x7d, 0x50, 0xb6, 0x07, 0xd0, 0x4e, 0x0e, 0xde, 0x29, 0x76, 0xf0, 0xd7, 0x52, 0x28, 0x3a, 0x61, 0x8f, + 0xaf, 0xaf, 0xff, 0x3a, 0x90, 0xc5, 0xc1, 0x5f, 0x99, 0x52, 0x7f, 0x1d, 0x70, 0xa1, 0x34, 0xa3, 0xe3, 0x24, 0x42, + 0x3d, 0xd3, 0x59, 0xa6, 0xd4, 0x5b, 0x76, 0xab, 0x89, 0xc6, 0xe6, 0x53, 0x13, 0xb6, 0x99, 0x32, 0x7d, 0xa0, 0xca, + 0x79, 0xc5, 0x68, 0x95, 0x33, 0x7d, 0xa0, 0x89, 0xc9, 0x97, 0x0e, 0xfe, 0xcc, 0x7e, 0xea, 0x1e, 0x9f, 0xc4, 0x9f, + 0xc5, 0xd1, 0x91, 0x2e, 0x01, 0x8d, 0x56, 0x6e, 0x85, 0x08, 0x3b, 0xf4, 0x69, 0x47, 0x47, 0x2c, 0xc9, 0x99, 0x98, + 0xea, 0x19, 0x21, 0xa4, 0xdd, 0x13, 0x47, 0x47, 0xb1, 0x26, 0xbf, 0x89, 0x64, 0xca, 0x74, 0xcc, 0x10, 0xc2, 0x55, + 0xed, 0xa3, 0xa3, 0xd8, 0x02, 0x41, 0x12, 0x6d, 0x00, 0x57, 0x83, 0x31, 0x4a, 0x1c, 0xf4, 0xaf, 0xef, 0x44, 0x16, + 0x87, 0xe3, 0x47, 0x58, 0x1c, 0x1d, 0xfd, 0x26, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xa6, 0x60, 0x7a, 0x59, 0x88, + 0x03, 0xbd, 0xd1, 0xf2, 0x5a, 0x17, 0x5c, 0x4c, 0x63, 0xb4, 0xf2, 0x69, 0x41, 0xc5, 0xcd, 0xc6, 0x0e, 0xf7, 0xc7, + 0x82, 0x70, 0x72, 0x05, 0x3d, 0xbe, 0x94, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xcf, 0x53, 0xde, + 0x88, 0x22, 0x6c, 0x47, 0x89, 0xaf, 0x05, 0xc2, 0x42, 0x03, 0xea, 0x26, 0x49, 0xa2, 0x11, 0xb9, 0x5a, 0x79, 0xb0, + 0xf0, 0x60, 0xa2, 0x7d, 0x3e, 0x68, 0x0d, 0x53, 0x9d, 0x14, 0x6c, 0xbc, 0xcc, 0x58, 0x1c, 0x0b, 0xac, 0xb0, 0x44, + 0xe4, 0x4a, 0x34, 0xe2, 0x82, 0x5c, 0xc1, 0x7a, 0x17, 0xf5, 0xc5, 0x26, 0xe4, 0xb0, 0x85, 0xdc, 0x20, 0x0b, 0x3f, + 0x42, 0x00, 0xb1, 0x1b, 0x50, 0x41, 0x48, 0x24, 0x96, 0xf3, 0x11, 0x2b, 0xa2, 0xb2, 0x58, 0xaf, 0x86, 0x17, 0x4b, + 0xc5, 0x0e, 0x32, 0xa5, 0x0e, 0x26, 0x4b, 0x91, 0x69, 0x2e, 0xc5, 0x41, 0xd4, 0x28, 0x1a, 0x91, 0xc5, 0x87, 0x12, + 0x1d, 0x22, 0xb4, 0x41, 0xb1, 0x42, 0x0d, 0x3e, 0x90, 0x8d, 0xf6, 0x10, 0xc3, 0x28, 0x51, 0xcf, 0xb5, 0xe7, 0x20, + 0xc0, 0x30, 0x87, 0x49, 0x6e, 0xb0, 0xa6, 0x66, 0x83, 0xc2, 0x14, 0x3f, 0x8b, 0x3e, 0x4f, 0x76, 0x77, 0x0a, 0xd1, + 0xc9, 0x9c, 0x2e, 0x62, 0x46, 0xae, 0x98, 0xc1, 0x2e, 0x2a, 0x32, 0x18, 0x6b, 0x6d, 0xe1, 0xfa, 0x2c, 0x65, 0x49, + 0x85, 0x53, 0x28, 0xd5, 0xc9, 0x44, 0x16, 0x4f, 0x69, 0x36, 0x83, 0x7a, 0x25, 0xc6, 0x8c, 0xfd, 0x86, 0xcb, 0x0a, + 0x46, 0x35, 0x7b, 0x9a, 0x33, 0xf8, 0x8a, 0x23, 0x53, 0x33, 0x42, 0x58, 0xc1, 0x56, 0xcf, 0xb9, 0x7e, 0x29, 0x45, + 0xc6, 0x7a, 0x2a, 0xc0, 0x2f, 0xb3, 0xf2, 0x0f, 0xb5, 0x2e, 0xf8, 0x68, 0xa9, 0x59, 0x1c, 0x09, 0x28, 0x11, 0x61, + 0x85, 0xb0, 0x48, 0x34, 0xbb, 0xd5, 0x8f, 0xa5, 0xd0, 0x4c, 0x68, 0xc2, 0x3c, 0x54, 0x31, 0x4f, 0xe8, 0x62, 0xc1, + 0xc4, 0xf8, 0xf1, 0x8c, 0xe7, 0xe3, 0x58, 0xa0, 0x0d, 0xda, 0xe0, 0x0f, 0x82, 0xc0, 0x24, 0xc9, 0x15, 0x4f, 0xe1, + 0x9f, 0xaf, 0x4f, 0x27, 0xd6, 0xe4, 0xca, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x37, 0x91, 0x45, 0xec, 0xa6, 0x70, 0x00, + 0xa4, 0x0b, 0xfa, 0x78, 0xb3, 0xcc, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0x3f, 0x16, 0x31, 0x83, + 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe1, 0x6e, 0x53, 0x8d, 0x4b, 0xa2, 0xf6, 0xb7, 0x20, 0x63, 0x9e, 0xe8, + 0x62, 0xa9, 0x34, 0x1b, 0xbf, 0xbd, 0x5b, 0x30, 0x85, 0x19, 0x25, 0x7f, 0x8b, 0xfe, 0xdf, 0x22, 0x61, 0xf3, 0x85, + 0xbe, 0xbb, 0x36, 0xd4, 0x3c, 0x8d, 0x22, 0xfc, 0xbb, 0x29, 0x5a, 0x30, 0x9a, 0x01, 0x49, 0x73, 0x20, 0x7b, 0x2d, + 0xf3, 0xbb, 0x09, 0xcf, 0xf3, 0xeb, 0xe5, 0x62, 0x21, 0x0b, 0x8d, 0x99, 0x20, 0x2b, 0x2d, 0x2b, 0xf8, 0xc0, 0x8a, + 0xae, 0xd4, 0x0d, 0xd7, 0xd9, 0x2c, 0xd6, 0x68, 0x95, 0x51, 0xc5, 0x0e, 0x1e, 0x49, 0x99, 0x33, 0x2a, 0x52, 0x4e, + 0x78, 0x9f, 0xd1, 0x54, 0x2c, 0xf3, 0xbc, 0x37, 0x2a, 0x18, 0xfd, 0xdc, 0x33, 0xd9, 0xf6, 0x70, 0x48, 0xcd, 0xef, + 0x87, 0x45, 0x41, 0xef, 0xa0, 0x20, 0x21, 0x50, 0xac, 0xcf, 0xd3, 0x1f, 0xaf, 0x5f, 0xbd, 0x4c, 0xec, 0x5e, 0xe1, + 0x93, 0xbb, 0x98, 0x97, 0xfb, 0x8f, 0x6f, 0xf0, 0xa4, 0x90, 0xf3, 0xad, 0xae, 0x2d, 0xe8, 0x78, 0xef, 0x2b, 0x43, + 0x60, 0x84, 0x1f, 0xda, 0xa6, 0xc3, 0x11, 0xbc, 0x34, 0x98, 0x0f, 0x99, 0xc4, 0xf5, 0x0b, 0xff, 0xa4, 0x36, 0x39, + 0xe6, 0xe8, 0xdb, 0xa3, 0xd5, 0xc5, 0xdd, 0x8a, 0x11, 0x33, 0xce, 0x05, 0x1c, 0x8c, 0x30, 0xc6, 0x8c, 0xea, 0x6c, + 0xb6, 0x62, 0xa6, 0xb1, 0x8d, 0x1f, 0x31, 0xdb, 0x6c, 0xf0, 0x3f, 0xd2, 0x63, 0xbd, 0x3e, 0x24, 0x84, 0x1b, 0x7a, + 0x45, 0xf4, 0x7a, 0xcd, 0x09, 0xe1, 0x08, 0x3f, 0xe3, 0x64, 0x45, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, 0x5a, + 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x18, 0xa8, 0xc0, 0x05, 0x9b, 0xe4, 0x30, 0x8e, 0xc3, 0x36, 0x9e, 0x51, + 0xf5, 0x78, 0x46, 0xc5, 0x94, 0x8d, 0xd3, 0x7f, 0xe4, 0x06, 0x0b, 0x41, 0xa2, 0x09, 0x17, 0x34, 0xe7, 0xff, 0xb0, + 0x71, 0xe4, 0xce, 0x85, 0xf7, 0xfa, 0x80, 0xdd, 0x6a, 0x26, 0xc6, 0xea, 0xe0, 0xf9, 0xdb, 0x5f, 0x7e, 0x76, 0x8b, + 0x59, 0x3b, 0x2b, 0xd0, 0x4a, 0x2d, 0x17, 0xac, 0x88, 0x11, 0x76, 0x67, 0xc5, 0x53, 0x6e, 0xe8, 0xe4, 0x2f, 0x74, + 0x61, 0x53, 0xb8, 0x7a, 0xb7, 0x18, 0x53, 0xcd, 0x5e, 0x33, 0x31, 0xe6, 0x62, 0x4a, 0x0e, 0xdb, 0x36, 0x7d, 0x46, + 0x5d, 0xc6, 0xb8, 0x4c, 0xfa, 0x78, 0xef, 0x69, 0x6e, 0xe6, 0x5e, 0x7e, 0x2e, 0x63, 0xb4, 0x51, 0x9a, 0x6a, 0x9e, + 0x1d, 0xd0, 0xf1, 0xf8, 0x85, 0xe0, 0x9a, 0x9b, 0x11, 0x16, 0xb0, 0x44, 0x80, 0xab, 0xcc, 0x9e, 0x1a, 0x7e, 0xe4, + 0x31, 0xc2, 0x71, 0xec, 0xce, 0x82, 0x19, 0x72, 0x6b, 0x76, 0x74, 0x54, 0x51, 0xfe, 0x3e, 0x4b, 0x6d, 0x26, 0x19, + 0x0c, 0x51, 0xb2, 0x58, 0x2a, 0x58, 0x6c, 0xdf, 0x05, 0x1c, 0x34, 0x72, 0xa4, 0x58, 0xf1, 0x85, 0x8d, 0x4b, 0x04, + 0x51, 0x31, 0x5a, 0x6d, 0xf5, 0xe1, 0xb6, 0x87, 0x26, 0x83, 0x61, 0x2f, 0x24, 0xe1, 0xcc, 0x21, 0xbb, 0xe5, 0x54, + 0x38, 0x53, 0x25, 0x51, 0x89, 0xe1, 0x40, 0x2d, 0x09, 0x8b, 0x22, 0x7e, 0x7e, 0x8b, 0x58, 0x00, 0x0f, 0x11, 0x52, + 0x0e, 0x7f, 0xe6, 0x3e, 0xfd, 0x62, 0x0e, 0x0f, 0x85, 0x05, 0xc2, 0xda, 0x8e, 0x54, 0x21, 0xb4, 0x41, 0x58, 0xfb, + 0xe1, 0x5a, 0xa2, 0xe4, 0xf9, 0x22, 0x38, 0xb5, 0xc9, 0x33, 0x6e, 0x8e, 0x6d, 0xa0, 0x6d, 0x54, 0xb3, 0xa3, 0xa3, + 0x98, 0x25, 0x25, 0x62, 0x90, 0xc3, 0xb6, 0x5b, 0xa4, 0x00, 0x5a, 0x5f, 0x19, 0x37, 0xf4, 0x6c, 0x18, 0x9c, 0x43, + 0x96, 0x08, 0xf9, 0x30, 0xcb, 0x98, 0x52, 0xb2, 0x38, 0x3a, 0x3a, 0x34, 0xe5, 0x4b, 0xce, 0x02, 0x16, 0xf1, 0xd5, + 0x8d, 0xa8, 0x86, 0x80, 0xaa, 0xd3, 0xd6, 0xf3, 0x4d, 0xa4, 0xe2, 0x9b, 0x3c, 0x13, 0x92, 0x46, 0x1f, 0x3f, 0x46, + 0x0d, 0x8d, 0x1d, 0x1c, 0xa6, 0xcc, 0x77, 0x7d, 0xf7, 0x84, 0x59, 0xb6, 0xd0, 0x30, 0x21, 0x3b, 0xa0, 0xd9, 0xcb, + 0x0f, 0xc6, 0xf5, 0x21, 0x61, 0x8d, 0x15, 0xda, 0x04, 0x2b, 0xba, 0xb7, 0x69, 0xc3, 0xdf, 0xd8, 0xa5, 0x5b, 0x4d, + 0x0d, 0x4f, 0x11, 0xac, 0xe3, 0x80, 0x0d, 0x37, 0xd8, 0xc0, 0xde, 0xcf, 0x46, 0x9a, 0x81, 0x0e, 0xf4, 0xb0, 0xe7, + 0xf2, 0x89, 0xb2, 0x90, 0x2b, 0xd8, 0xdf, 0x4b, 0xa6, 0xb4, 0x45, 0xe4, 0x58, 0x63, 0x89, 0xe1, 0x8c, 0xda, 0x66, + 0x3a, 0x6b, 0x2c, 0xe9, 0xbe, 0xb1, 0xbd, 0x5a, 0xc0, 0xd9, 0xa8, 0x00, 0xa9, 0xbf, 0x8d, 0x4f, 0x30, 0x56, 0x8d, + 0xd6, 0xeb, 0x67, 0xdc, 0xb7, 0x52, 0xad, 0x65, 0xc9, 0xaf, 0x6d, 0x2d, 0x8a, 0x10, 0xc8, 0x1d, 0xce, 0x87, 0x6d, + 0x3b, 0x7e, 0x21, 0x86, 0xe4, 0xb0, 0x55, 0x62, 0xb1, 0x03, 0xab, 0x1d, 0x8f, 0x85, 0xe2, 0x2b, 0xdb, 0x14, 0x32, + 0x67, 0x7d, 0x0d, 0x5f, 0x92, 0xd9, 0x0e, 0xae, 0xce, 0xc8, 0x00, 0xb8, 0x8e, 0x64, 0x36, 0xfc, 0x1a, 0x3e, 0x79, + 0x8a, 0x10, 0xeb, 0xdd, 0xbc, 0x8a, 0x70, 0x7c, 0xa9, 0x13, 0x8e, 0xad, 0x69, 0x44, 0x8b, 0xb2, 0x4a, 0x54, 0xa2, + 0x99, 0xdb, 0xea, 0x55, 0x16, 0x16, 0x66, 0x30, 0xd5, 0x94, 0x82, 0x26, 0x5e, 0xd2, 0x39, 0x53, 0x31, 0x43, 0xf8, + 0x6b, 0x05, 0x2c, 0x7e, 0x42, 0x91, 0x61, 0x70, 0x86, 0x2a, 0x38, 0x43, 0x81, 0xdd, 0x05, 0x26, 0xad, 0xbe, 0xe5, + 0x14, 0x66, 0x03, 0x35, 0xac, 0x78, 0xbb, 0x60, 0xf2, 0xe6, 0x70, 0x76, 0x08, 0xee, 0xe1, 0x67, 0xd3, 0x2c, 0xd0, + 0x0c, 0x0b, 0xa1, 0x10, 0x3e, 0x6c, 0x6d, 0xaf, 0xa4, 0x2f, 0x55, 0xcd, 0x71, 0x30, 0x84, 0x75, 0x30, 0xc7, 0x46, + 0xc2, 0x95, 0xf9, 0x5b, 0xdb, 0x6a, 0x00, 0xb6, 0x6b, 0xc0, 0x8c, 0x64, 0x92, 0x53, 0x1d, 0xb7, 0x4f, 0x5a, 0xc0, + 0x98, 0x7e, 0x61, 0x70, 0xaa, 0x20, 0xb4, 0x3b, 0x15, 0x96, 0x2c, 0x85, 0x9a, 0xf1, 0x89, 0x8e, 0x3f, 0x08, 0x43, + 0x54, 0x58, 0xae, 0x18, 0x48, 0x38, 0x01, 0x7b, 0x6c, 0x08, 0xce, 0x07, 0x01, 0xfd, 0xf4, 0xca, 0x83, 0xc8, 0x8d, + 0xd4, 0x10, 0x2e, 0x20, 0x0f, 0x15, 0x6b, 0x5d, 0x91, 0x99, 0x92, 0x71, 0x03, 0xee, 0xb1, 0xdd, 0xb7, 0x2d, 0xa6, + 0x8e, 0x1a, 0x88, 0x80, 0x83, 0x15, 0x69, 0x48, 0x22, 0x5c, 0xa2, 0x4e, 0xb4, 0xfc, 0x59, 0xde, 0xb0, 0xe2, 0x31, + 0x85, 0xc1, 0xa7, 0xb6, 0xfa, 0xc6, 0x1e, 0x05, 0x86, 0xe2, 0xeb, 0x9e, 0xc7, 0x97, 0x8f, 0x66, 0xe2, 0xaf, 0x0b, + 0x39, 0xe7, 0x8a, 0x01, 0xdf, 0x66, 0xe1, 0x2f, 0x60, 0xa3, 0x99, 0x1d, 0x09, 0xc7, 0x0d, 0x2b, 0xf1, 0xeb, 0xe1, + 0xcf, 0x75, 0xfc, 0xfa, 0x78, 0xef, 0xe9, 0xd4, 0x53, 0xc0, 0xfa, 0x3e, 0x46, 0x38, 0x76, 0xe2, 0x45, 0x70, 0xd2, + 0x25, 0x33, 0xe4, 0x8e, 0xf9, 0xf5, 0x5a, 0x07, 0x62, 0x5c, 0x8d, 0x73, 0x64, 0x76, 0xdb, 0xa0, 0x0d, 0x1d, 0x8f, + 0x81, 0xc5, 0x2b, 0x64, 0x9e, 0x07, 0x87, 0x15, 0x16, 0xbd, 0xf2, 0x78, 0xfa, 0x78, 0xef, 0xe9, 0xf5, 0xb7, 0x4e, + 0x28, 0xc8, 0x0f, 0x0f, 0x29, 0x3f, 0x50, 0x31, 0x66, 0x05, 0xc8, 0x95, 0xc1, 0x6a, 0xb9, 0x73, 0xf6, 0xb1, 0x14, + 0x82, 0x65, 0x9a, 0x8d, 0x41, 0x68, 0x11, 0x44, 0x27, 0x33, 0xa9, 0x74, 0x99, 0x58, 0x8d, 0x5e, 0x84, 0x42, 0x68, + 0x92, 0xd1, 0x3c, 0x8f, 0xad, 0x80, 0x32, 0x97, 0x5f, 0xd8, 0x9e, 0x51, 0xf7, 0x6a, 0x43, 0x2e, 0x9b, 0x61, 0x41, + 0x33, 0x2c, 0x51, 0x8b, 0x9c, 0x67, 0xac, 0x3c, 0xbc, 0xae, 0x13, 0x2e, 0xc6, 0xec, 0x16, 0xe8, 0x08, 0xba, 0xba, + 0xba, 0x6a, 0xe1, 0x36, 0xda, 0x58, 0x80, 0xaf, 0x76, 0x00, 0xfb, 0x8d, 0x63, 0xd3, 0x0a, 0xe2, 0xab, 0x7d, 0xf4, + 0x80, 0xa1, 0xe0, 0xac, 0xe4, 0x5e, 0xd0, 0xb2, 0xe4, 0x19, 0xe1, 0x31, 0xcb, 0x99, 0x66, 0x9e, 0x9c, 0x03, 0x33, + 0x6d, 0xb7, 0xee, 0x9b, 0x12, 0x7e, 0x25, 0x3a, 0xf9, 0x5d, 0xe6, 0xd7, 0x5c, 0x95, 0xa2, 0x7b, 0xb5, 0x3c, 0x15, + 0xb4, 0xfb, 0xda, 0x2e, 0x0f, 0xd5, 0x9a, 0x66, 0x33, 0x2b, 0xb1, 0xc7, 0x3b, 0x53, 0xaa, 0xda, 0x70, 0xa4, 0xbd, + 0xdc, 0x44, 0x9a, 0xba, 0x61, 0xee, 0x03, 0xc1, 0xb5, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x8f, 0x69, 0x9e, + 0x8f, 0x68, 0xf6, 0xb9, 0x8e, 0xfd, 0x15, 0x1a, 0x90, 0x6d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, + 0xd2, 0xb5, 0x8d, 0x12, 0x1f, 0xb6, 0x2a, 0xb4, 0xaf, 0x2f, 0xf4, 0x57, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, + 0x40, 0x05, 0xfe, 0x25, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xcd, 0xd6, 0x40, 0x34, 0x5a, 0x6d, 0xc6, + 0x5c, 0x7d, 0x1d, 0x02, 0xff, 0x5b, 0x46, 0xf9, 0x24, 0xe8, 0xe1, 0xdf, 0x1d, 0x68, 0x49, 0xe3, 0x1c, 0xe3, 0x5c, + 0x8e, 0xcc, 0x31, 0x14, 0x9e, 0xd0, 0xfc, 0x04, 0xcc, 0x8b, 0xc1, 0xf7, 0x57, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, + 0xd5, 0x0b, 0x19, 0x8a, 0x1a, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x6b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, + 0xee, 0x68, 0x6e, 0x41, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9a, 0x85, 0xda, 0x99, 0x85, 0x4a, 0x02, + 0x69, 0x0b, 0x55, 0xc8, 0x1c, 0x54, 0x4f, 0x99, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x24, 0xb8, + 0x39, 0xd1, 0xb8, 0x70, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x55, 0x15, 0x89, 0xec, 0xe6, 0xa8, 0xc9, 0xbe, 0x12, + 0x17, 0x68, 0x8b, 0xbf, 0xdf, 0x6c, 0x1c, 0x94, 0x18, 0x72, 0xab, 0x53, 0x63, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, + 0x33, 0x6c, 0x59, 0x9f, 0x6d, 0xe0, 0x94, 0xed, 0x1e, 0x12, 0x22, 0x2b, 0xd8, 0xd4, 0x98, 0x4a, 0xcf, 0x5d, 0x49, + 0x84, 0xa9, 0x67, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0xf5, 0x57, 0x35, 0xe1, 0x30, 0x0d, 0x8a, + 0x6d, 0x52, 0x20, 0xaa, 0xc5, 0x3e, 0x78, 0xef, 0xc3, 0x9a, 0x5a, 0x3b, 0x01, 0xc4, 0x8b, 0x1a, 0xc4, 0x03, 0xd0, + 0x4a, 0x4b, 0xbc, 0xe4, 0x90, 0xd0, 0x7a, 0xe5, 0x98, 0xe1, 0xc2, 0x2e, 0xc4, 0x0e, 0x14, 0xb7, 0xd9, 0x4f, 0x83, + 0x85, 0x20, 0xcb, 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xf5, 0x7a, 0x07, 0xed, 0xf6, 0x72, 0xa1, + 0x28, 0xa9, 0xa4, 0xc3, 0xf5, 0xfa, 0x1f, 0x89, 0x62, 0xc7, 0xff, 0x62, 0x86, 0xfa, 0x9e, 0xe8, 0x3e, 0xfc, 0x19, + 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x0e, 0x01, + 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xe1, 0x3e, 0xf9, + 0xf2, 0xe8, 0x48, 0x05, 0x0d, 0x7d, 0x2c, 0x29, 0xc5, 0xa7, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xc9, + 0x9f, 0x43, 0x3b, 0xd2, 0x69, 0xab, 0x07, 0x82, 0x39, 0xbd, 0xa1, 0x5c, 0x1f, 0x94, 0xad, 0x58, 0xc1, 0x3c, 0x66, + 0x68, 0xe5, 0xb8, 0x8d, 0xa4, 0x60, 0xc0, 0x3f, 0x02, 0x59, 0xf0, 0x5c, 0xb4, 0x45, 0xfc, 0x6c, 0xc6, 0x40, 0x95, + 0xed, 0x19, 0x89, 0x92, 0xea, 0x1f, 0xba, 0x83, 0xc4, 0x35, 0xbc, 0x7f, 0xec, 0x9b, 0xed, 0xea, 0x35, 0x69, 0x60, + 0xc1, 0x8a, 0x89, 0x2c, 0xe6, 0x3e, 0x6f, 0xb3, 0xf5, 0xed, 0x88, 0x23, 0x9f, 0xc4, 0x7b, 0xdb, 0x76, 0x22, 0x40, + 0x6f, 0x4b, 0xf6, 0xae, 0xa4, 0xf6, 0xda, 0x69, 0x5a, 0x1e, 0xc0, 0x56, 0x41, 0xe8, 0x31, 0x53, 0x85, 0x52, 0xbe, + 0x53, 0xaf, 0xf6, 0xac, 0xee, 0xe4, 0xb0, 0xdd, 0x2b, 0x25, 0x3f, 0x8f, 0x0d, 0x3d, 0xab, 0xe3, 0x70, 0xa7, 0xaa, + 0x5c, 0xe6, 0x63, 0x37, 0x58, 0x81, 0x30, 0x73, 0x78, 0x74, 0xc3, 0xf3, 0xbc, 0x4a, 0xfd, 0x4f, 0x48, 0xbb, 0x72, + 0xa4, 0x5d, 0x7a, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x6d, 0xae, 0xaa, 0x2e, 0x77, 0xb6, 0xa7, 0xb4, 0x44, 0x5d, + 0x19, 0x71, 0x1a, 0xfa, 0x5b, 0xfa, 0x11, 0xa0, 0x92, 0xf9, 0xfa, 0x1c, 0x3b, 0x7d, 0x0c, 0x88, 0x81, 0x56, 0xa7, + 0xc9, 0x42, 0x4d, 0xc5, 0xe7, 0x18, 0x61, 0xb5, 0x61, 0x25, 0x66, 0x3f, 0x7c, 0x0a, 0x4a, 0xbb, 0x60, 0x3a, 0x70, + 0x8e, 0x99, 0xe4, 0xff, 0x88, 0x8f, 0xf2, 0xb3, 0x13, 0x6e, 0x76, 0xca, 0xcf, 0x0e, 0x68, 0x7d, 0x35, 0xbb, 0xf1, + 0xb7, 0xa9, 0xbd, 0x99, 0x9e, 0x28, 0xa7, 0x57, 0xad, 0xf7, 0x7a, 0x1d, 0x6f, 0xa5, 0x80, 0x46, 0xdf, 0x49, 0x29, + 0x45, 0xd9, 0x3a, 0xd0, 0x80, 0x10, 0x32, 0x90, 0xb0, 0xb1, 0x93, 0x2e, 0x4f, 0xb9, 0x9f, 0xff, 0x95, 0x9e, 0xc7, + 0x28, 0xee, 0x6d, 0xfd, 0xc7, 0x72, 0xbe, 0x00, 0x86, 0x6c, 0x0b, 0xa5, 0xa7, 0xcc, 0x75, 0x58, 0xe5, 0x6f, 0xf6, + 0xa4, 0xd5, 0xea, 0x98, 0xfd, 0x58, 0xc3, 0xa6, 0x52, 0x6a, 0x3e, 0x6c, 0x6d, 0x96, 0x65, 0x52, 0x49, 0x38, 0xf6, + 0xe9, 0x56, 0x1e, 0x6f, 0x6b, 0x66, 0x7c, 0xc6, 0xab, 0x58, 0x58, 0x3a, 0x2c, 0x80, 0xd6, 0x05, 0xe4, 0xc7, 0xa3, + 0x7b, 0xb8, 0xfe, 0x9b, 0x0a, 0x38, 0xab, 0xcd, 0x16, 0xf8, 0x56, 0x9b, 0xcd, 0x7b, 0xed, 0x24, 0x6d, 0xfc, 0x7e, + 0x8f, 0xdc, 0x5b, 0x42, 0xaf, 0xca, 0x74, 0x32, 0xe3, 0x60, 0x08, 0x69, 0x3b, 0x2c, 0x24, 0x59, 0xcd, 0xe5, 0x98, + 0xa5, 0x91, 0x5c, 0x30, 0x11, 0x6d, 0x40, 0xcf, 0xea, 0x10, 0xe0, 0x77, 0x11, 0xaf, 0xde, 0xd4, 0xf5, 0xad, 0xe9, + 0x7b, 0xbd, 0x01, 0x55, 0xd8, 0x1b, 0xbe, 0x47, 0x19, 0xfb, 0x9e, 0x15, 0xca, 0xf0, 0xa4, 0x25, 0x7b, 0xfb, 0x86, + 0x57, 0x07, 0xd4, 0x1b, 0x9e, 0x7e, 0xbd, 0x4a, 0x25, 0x90, 0x44, 0xed, 0xe4, 0x3c, 0x39, 0x8d, 0x90, 0xd1, 0x18, + 0xbf, 0xf4, 0x1a, 0xe3, 0x65, 0xa9, 0x31, 0x7e, 0xae, 0xc9, 0x72, 0x4b, 0x63, 0xfc, 0x93, 0x20, 0xcf, 0x75, 0xff, + 0xb9, 0xd7, 0xa6, 0xbf, 0x96, 0x39, 0xcf, 0xee, 0xe2, 0x28, 0xe7, 0xba, 0x09, 0xb7, 0x89, 0x11, 0x5e, 0xd9, 0x0c, + 0x50, 0x35, 0x1a, 0x7d, 0xf7, 0xc6, 0xcb, 0x7f, 0x58, 0x09, 0x12, 0xdd, 0xcb, 0xb9, 0xbe, 0x17, 0xe1, 0x99, 0x26, + 0x7f, 0xc1, 0xaf, 0x7b, 0xab, 0xf8, 0x17, 0xaa, 0x67, 0x49, 0x41, 0xc5, 0x58, 0xce, 0x63, 0xd4, 0x88, 0x22, 0x94, + 0x28, 0x23, 0x84, 0x3c, 0x40, 0x9b, 0x7b, 0x7f, 0xe1, 0x4f, 0x92, 0x44, 0xfd, 0xa8, 0x31, 0xd3, 0x98, 0x53, 0xf2, + 0xd7, 0xe5, 0xbd, 0xd5, 0x27, 0xb9, 0xb9, 0xfa, 0x0b, 0x3f, 0xd5, 0xa5, 0x5a, 0x1f, 0xdf, 0x32, 0x12, 0x23, 0x72, + 0xf5, 0xd4, 0x0f, 0xe9, 0xb1, 0x9c, 0x5b, 0x05, 0x7f, 0x84, 0xf0, 0x17, 0xd0, 0xeb, 0x5e, 0xf1, 0x8a, 0x08, 0xb9, + 0x3b, 0x98, 0x43, 0x12, 0x49, 0xa3, 0x3c, 0x88, 0x8e, 0x8e, 0x82, 0xb4, 0x92, 0x85, 0xc0, 0x8f, 0x24, 0xa9, 0x89, + 0xea, 0x58, 0x50, 0x68, 0xe9, 0x91, 0x8c, 0x39, 0xf2, 0xcd, 0xc4, 0x5e, 0x53, 0xed, 0x76, 0x2c, 0x1f, 0x58, 0xdd, + 0x43, 0xc2, 0x35, 0x2b, 0xa8, 0x96, 0xc5, 0x10, 0x85, 0x6c, 0x09, 0xfe, 0x87, 0x93, 0xbf, 0x06, 0x07, 0xff, 0xcf, + 0xff, 0xf8, 0x73, 0xf2, 0x67, 0x31, 0xfc, 0x0b, 0x0b, 0x46, 0x4e, 0x2e, 0xe3, 0x7e, 0x1a, 0x1f, 0x36, 0x9b, 0xeb, + 0x3f, 0x4f, 0x06, 0xff, 0x4d, 0x9b, 0xff, 0x3c, 0x6c, 0xfe, 0x31, 0x44, 0xeb, 0xf8, 0xcf, 0x93, 0xfe, 0xc0, 0x7d, + 0x0d, 0xfe, 0xfb, 0xea, 0x4f, 0x35, 0x3c, 0xb6, 0x89, 0xf7, 0x10, 0x3a, 0x99, 0xe2, 0x1f, 0x04, 0x39, 0x69, 0x36, + 0xaf, 0x4e, 0xa6, 0xf8, 0x57, 0x41, 0x4e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd8, 0xf4, 0xe9, 0xed, 0x22, 0xfe, 0xeb, + 0x6a, 0x7d, 0x6f, 0xf5, 0x0f, 0xdf, 0x40, 0xbb, 0x83, 0xff, 0xfe, 0xf3, 0x4f, 0x15, 0x7d, 0x7f, 0x45, 0x4e, 0x86, + 0x0d, 0x14, 0x9b, 0xe4, 0x63, 0x62, 0xff, 0xc4, 0xfd, 0x74, 0xf0, 0xdf, 0x6e, 0x28, 0xd1, 0xf7, 0x7f, 0xfe, 0x75, + 0x79, 0x45, 0x86, 0xeb, 0x38, 0x5a, 0x7f, 0x8f, 0xd6, 0x08, 0xad, 0xef, 0xa1, 0xbf, 0x70, 0x34, 0x8d, 0x10, 0xfe, + 0x43, 0x90, 0x93, 0xef, 0x4f, 0xa6, 0xf8, 0x47, 0x41, 0x4e, 0xa2, 0x93, 0x29, 0x7e, 0x2f, 0xc9, 0xc9, 0x7f, 0xc7, + 0xfd, 0xd4, 0x2a, 0xe1, 0xd6, 0x46, 0xfd, 0xb1, 0x86, 0x9b, 0x10, 0x5a, 0x30, 0xba, 0xd6, 0x5c, 0xe7, 0x0c, 0xdd, + 0x3b, 0xe1, 0xf8, 0xb9, 0x04, 0x60, 0xc5, 0x1a, 0x94, 0x34, 0xe6, 0x12, 0x76, 0xf5, 0x11, 0x16, 0x1e, 0x30, 0xe8, + 0x5e, 0xca, 0xb1, 0xd5, 0x13, 0xa8, 0x54, 0xdb, 0xdb, 0x5b, 0x05, 0xd7, 0xb7, 0xf8, 0x9a, 0x3c, 0x97, 0x71, 0x1b, + 0x61, 0x45, 0xe1, 0x47, 0x07, 0xe1, 0x77, 0xda, 0x5d, 0x78, 0xc2, 0x36, 0xb7, 0x18, 0x26, 0xa4, 0xe5, 0x67, 0x22, + 0x84, 0x9f, 0xee, 0xc9, 0xd4, 0x33, 0x50, 0x3f, 0x20, 0xac, 0x55, 0x78, 0x3d, 0x8a, 0x1f, 0x6b, 0x52, 0x22, 0xc7, + 0xdb, 0x82, 0xb1, 0xdf, 0x68, 0xfe, 0x99, 0x15, 0xf1, 0x53, 0x8d, 0xdb, 0x9d, 0x07, 0xd8, 0xa8, 0xaa, 0x0f, 0xdb, + 0xa8, 0x57, 0xde, 0x6e, 0xbd, 0x93, 0xf6, 0x3e, 0x01, 0x4e, 0xe1, 0xba, 0xbe, 0x06, 0xd6, 0xfe, 0x90, 0xef, 0x28, + 0xb5, 0x0a, 0x7a, 0x13, 0xa1, 0xfa, 0x55, 0x2a, 0x17, 0x5f, 0x68, 0xce, 0xc7, 0x07, 0x9a, 0xcd, 0x17, 0x39, 0xd5, + 0xec, 0xc0, 0xcd, 0xf9, 0x80, 0x42, 0x43, 0x51, 0xc9, 0x53, 0xfc, 0x24, 0xaa, 0x4d, 0xfb, 0x93, 0x48, 0xaa, 0xbd, + 0x13, 0xc3, 0x7d, 0x96, 0xe3, 0x4b, 0x64, 0x75, 0x5d, 0xb6, 0x7d, 0x23, 0xd8, 0x6c, 0x83, 0xb2, 0x6c, 0x68, 0xce, + 0x6f, 0x85, 0xe1, 0x7e, 0x93, 0x90, 0x4e, 0x3f, 0xba, 0x54, 0x5f, 0xa6, 0x57, 0x11, 0xdc, 0xe4, 0x14, 0x44, 0x30, + 0xa3, 0x3c, 0x82, 0x12, 0x94, 0xb4, 0x7a, 0xf4, 0x92, 0xf5, 0x68, 0xa3, 0xe1, 0xd9, 0xec, 0x8c, 0xf0, 0x01, 0xb5, + 0xf5, 0x73, 0x3c, 0xc3, 0x63, 0xd2, 0x6c, 0xe3, 0x25, 0x69, 0x99, 0x2a, 0xbd, 0xe5, 0x65, 0xe6, 0xfa, 0x39, 0x3a, + 0x8a, 0x8b, 0x24, 0xa7, 0x4a, 0xbf, 0x00, 0x8d, 0x00, 0x59, 0xe2, 0x19, 0x29, 0x12, 0x76, 0xcb, 0xb2, 0x38, 0x43, + 0x78, 0xe6, 0x68, 0x10, 0xea, 0xa1, 0x25, 0x09, 0x8a, 0x81, 0x9c, 0x41, 0x04, 0xeb, 0xcf, 0x06, 0xed, 0x21, 0x21, + 0x24, 0x3a, 0x6c, 0x36, 0xa3, 0x7e, 0x41, 0x7e, 0x10, 0x29, 0xa4, 0x04, 0xec, 0x34, 0xf9, 0x15, 0x92, 0x3a, 0x41, + 0x52, 0xfc, 0x5e, 0x26, 0x9a, 0x29, 0x1d, 0x43, 0x32, 0x28, 0x09, 0x94, 0xc7, 0xf0, 0xe8, 0xf2, 0x24, 0x6a, 0x40, + 0xaa, 0x41, 0x51, 0x84, 0x0b, 0x72, 0xa7, 0x51, 0x3a, 0x1b, 0x9c, 0x0e, 0xc3, 0x33, 0xc2, 0xa6, 0x42, 0xff, 0x77, + 0xba, 0x3f, 0x1b, 0xb4, 0x4c, 0xff, 0x57, 0x51, 0x3f, 0x2e, 0x88, 0xb2, 0x6c, 0x5c, 0x5f, 0xa5, 0x82, 0x99, 0xf9, + 0xa2, 0xd4, 0x0d, 0xd0, 0xf5, 0x3d, 0x26, 0xcd, 0x4e, 0x1a, 0x8f, 0xc3, 0x99, 0x34, 0xa1, 0x43, 0x07, 0x0a, 0x9c, + 0x13, 0x28, 0x8f, 0x0b, 0x02, 0x9d, 0x56, 0xd5, 0xee, 0x74, 0xea, 0x12, 0xbe, 0x8f, 0xbe, 0xef, 0xff, 0x28, 0xd2, + 0x3f, 0x84, 0x1d, 0xc1, 0x8f, 0x62, 0xbd, 0x86, 0xbf, 0x7f, 0x88, 0x3e, 0x0c, 0xcb, 0xa4, 0xfd, 0xe0, 0xd2, 0x7e, + 0x85, 0x34, 0xc1, 0x52, 0x33, 0x60, 0xac, 0x4a, 0x7e, 0xcc, 0x2e, 0xce, 0x84, 0xd8, 0x19, 0x1c, 0x1d, 0xf1, 0x01, + 0x6d, 0xb4, 0x87, 0x70, 0x23, 0x50, 0x68, 0xf5, 0x1b, 0xd7, 0xb3, 0x38, 0x3a, 0xb9, 0x8a, 0x50, 0x3f, 0x3a, 0x80, + 0x55, 0xee, 0xc9, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9c, 0xa6, 0xe3, 0x2b, 0xd2, 0xea, 0xc7, 0xc2, 0x12, 0xf9, 0x1c, + 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa3, 0x86, 0x12, 0x0d, 0xff, 0x3d, 0x46, 0x8d, 0x99, 0x6e, 0x4c, 0x50, 0x9a, + 0xc1, 0xdf, 0x78, 0x4c, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x9d, 0x78, 0xf5, 0xe8, 0xc0, 0x6c, + 0x0e, 0xd9, 0x88, 0xf9, 0x80, 0x0d, 0xd7, 0xeb, 0xe8, 0xb2, 0x7f, 0x15, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc4, 0xe3, + 0x1d, 0x42, 0x58, 0x0c, 0x37, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x56, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0xdb, + 0x94, 0x72, 0x8f, 0xe5, 0x6f, 0x17, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, + 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0x78, 0x90, 0xe3, 0xd9, 0x90, 0x48, 0x6a, 0xe4, 0x97, 0x9e, 0x57, 0xa6, 0xb3, 0x9c, + 0xdc, 0xb0, 0xad, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x16, 0x05, 0x13, 0xfa, 0xa5, 0x1c, 0x3b, + 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x78, 0x27, 0x7b, 0x49, 0xc6, + 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xbd, 0xa5, 0x13, 0xa5, 0x63, 0x84, 0xc7, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x99, + 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x31, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, + 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa4, 0x3d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x98, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, + 0xcd, 0xa8, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0x0e, 0x42, 0x95, 0xf7, 0x12, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, + 0xe5, 0x39, 0x42, 0x7c, 0x12, 0x2f, 0x13, 0xb8, 0x11, 0x34, 0x98, 0xa4, 0x04, 0x5a, 0xaf, 0x97, 0x21, 0x6e, 0xcd, + 0x2a, 0xc5, 0xf4, 0x84, 0xcc, 0x06, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x63, 0x8b, 0x17, 0x4b, 0x84, 0x27, 0xe5, 0x5e, + 0xf3, 0xe5, 0x16, 0xa4, 0xde, 0x55, 0x3c, 0xa9, 0x2b, 0x81, 0x1b, 0x4a, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, + 0x92, 0x93, 0x78, 0x90, 0xf4, 0xff, 0xe7, 0x10, 0xf5, 0xe3, 0xe4, 0x18, 0x9d, 0x58, 0x5a, 0x32, 0x41, 0xbd, 0xcc, + 0xf6, 0xb1, 0x32, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x59, 0x3a, 0x85, 0x5d, 0xef, 0x91, + 0x67, 0x81, 0x01, 0x99, 0xd2, 0xa9, 0xa3, 0x2d, 0x49, 0xd4, 0xa7, 0xb4, 0xfc, 0xea, 0x47, 0xfd, 0xbc, 0xfa, 0xfa, + 0x9f, 0x51, 0x7f, 0x46, 0xd3, 0xc7, 0x7c, 0xe3, 0x94, 0xe4, 0xb5, 0x3e, 0xce, 0x7d, 0x1f, 0x1b, 0xbb, 0x38, 0x01, + 0xf0, 0xc6, 0x68, 0x57, 0x3b, 0xb2, 0x44, 0x1b, 0x3e, 0x29, 0xa9, 0x93, 0x4a, 0x34, 0x9d, 0x02, 0x54, 0x83, 0x45, + 0x50, 0xa1, 0x6d, 0x40, 0x30, 0x65, 0xc0, 0x16, 0x8f, 0xb4, 0x00, 0xcd, 0xe5, 0x55, 0x0b, 0xad, 0x6a, 0x85, 0x1d, + 0x67, 0x55, 0xbf, 0x8b, 0x2f, 0x89, 0xf7, 0x04, 0xa8, 0xf2, 0xe5, 0xb2, 0x37, 0x69, 0x34, 0x90, 0xf2, 0xf8, 0x35, + 0x1e, 0x4c, 0x86, 0xf8, 0x16, 0x50, 0x08, 0xd7, 0x30, 0x0a, 0xd7, 0xe6, 0xd8, 0x71, 0x73, 0x6c, 0x34, 0xe4, 0x06, + 0xf5, 0x82, 0xca, 0x4b, 0x57, 0x79, 0xb3, 0xb1, 0x90, 0xd9, 0xc6, 0xb8, 0x0b, 0x64, 0x52, 0xc0, 0x10, 0x8c, 0x10, + 0xf2, 0x49, 0xa2, 0xbd, 0xcd, 0x42, 0xa3, 0x50, 0xdd, 0xec, 0x5e, 0xa0, 0xa8, 0xf6, 0xf4, 0x88, 0x01, 0x16, 0x50, + 0xb5, 0x54, 0x23, 0xcf, 0x34, 0x1e, 0x37, 0xda, 0x06, 0xdd, 0x9b, 0xed, 0x5e, 0xbd, 0xb1, 0xfb, 0x55, 0x63, 0x78, + 0xdc, 0x20, 0xb3, 0x6a, 0x87, 0x6f, 0x64, 0xa3, 0xb1, 0xa9, 0xdf, 0x97, 0xfa, 0x4d, 0x5c, 0xbb, 0xbf, 0x78, 0xba, + 0x63, 0xe2, 0xe1, 0x4f, 0xdf, 0xea, 0xbc, 0x15, 0x09, 0x17, 0x82, 0x15, 0x70, 0xc2, 0x12, 0x8d, 0xc5, 0x66, 0x53, + 0x9e, 0xfa, 0xbf, 0x69, 0x6b, 0x33, 0x46, 0x38, 0xd0, 0x21, 0x23, 0xb5, 0x61, 0x89, 0x0b, 0x4c, 0x0d, 0x15, 0x21, + 0x84, 0xbc, 0xd3, 0xde, 0x3c, 0x46, 0x1b, 0x92, 0x94, 0x91, 0xe0, 0xec, 0x8e, 0x15, 0x61, 0xc9, 0xc7, 0x7b, 0x8f, + 0xe5, 0x37, 0x45, 0xba, 0x81, 0x18, 0xa6, 0xa6, 0x58, 0xee, 0x08, 0x59, 0x4e, 0xbe, 0x80, 0x9c, 0x53, 0x5e, 0xb0, + 0x24, 0x86, 0x20, 0x3e, 0xe1, 0x05, 0x33, 0x8c, 0xfb, 0x3d, 0x2f, 0x37, 0x66, 0x75, 0x4e, 0x33, 0x0b, 0xb5, 0x3f, + 0x00, 0xcd, 0x1c, 0x94, 0x43, 0x92, 0xec, 0x14, 0xfb, 0x78, 0xef, 0xe1, 0xab, 0x7d, 0x32, 0xf4, 0x7a, 0xed, 0xa4, + 0xe7, 0x0c, 0x58, 0x1f, 0x9c, 0x57, 0x43, 0xcd, 0xdc, 0x8f, 0x34, 0xce, 0x0c, 0x13, 0x95, 0xc7, 0x1c, 0x90, 0xe9, + 0xe3, 0xbd, 0x87, 0x6f, 0x63, 0x6e, 0x74, 0x53, 0x08, 0x87, 0xf3, 0x8e, 0x0b, 0x12, 0x53, 0xc2, 0x90, 0x9d, 0x7c, + 0x49, 0xc7, 0x8a, 0xe0, 0x74, 0x4f, 0xa9, 0xc9, 0x04, 0xb1, 0x63, 0x20, 0x86, 0x24, 0x73, 0x20, 0x20, 0x19, 0xc2, + 0x59, 0x4d, 0xae, 0x23, 0x66, 0x0d, 0x4c, 0x67, 0xd7, 0xb0, 0x18, 0x89, 0x65, 0x0f, 0x11, 0xce, 0x4c, 0xb7, 0x7a, + 0x63, 0x8f, 0x93, 0x82, 0x6e, 0x1b, 0xba, 0x55, 0xf2, 0xec, 0x7b, 0x10, 0xbc, 0xfc, 0xc7, 0x4b, 0xd7, 0x76, 0x99, + 0xf0, 0xc4, 0x5b, 0xa4, 0x7d, 0xbc, 0xf7, 0xf0, 0x17, 0x67, 0x94, 0xb6, 0xa0, 0x9e, 0xfc, 0xef, 0xc8, 0xa8, 0x0f, + 0x7f, 0x49, 0xaa, 0x5c, 0x53, 0xf8, 0xe3, 0xbd, 0x87, 0xef, 0xf6, 0x15, 0x83, 0xf4, 0xcd, 0xb2, 0x52, 0x12, 0x98, + 0xf1, 0xad, 0x58, 0x9e, 0xae, 0xdc, 0x59, 0x91, 0x8a, 0x0d, 0x36, 0x27, 0x54, 0xaa, 0x36, 0xa5, 0x6e, 0xe5, 0x09, + 0x96, 0xc4, 0x5c, 0x25, 0xd5, 0x97, 0xcd, 0xa1, 0x31, 0x97, 0xe2, 0x3a, 0x93, 0x0b, 0xf6, 0x95, 0xfb, 0xa5, 0xa7, + 0x1a, 0x25, 0x7c, 0x0e, 0x86, 0x38, 0x66, 0xec, 0x02, 0x1f, 0xb6, 0x50, 0x6f, 0xeb, 0x3c, 0x93, 0x06, 0x51, 0x8b, + 0xfa, 0x61, 0x83, 0x29, 0x69, 0xe1, 0x8c, 0xb4, 0x70, 0x4e, 0xd4, 0xa0, 0x65, 0x4f, 0x8c, 0x5e, 0x5e, 0x36, 0x6d, + 0xcf, 0x1d, 0xd8, 0xee, 0xb9, 0xdd, 0xb7, 0xf6, 0x50, 0x9e, 0xf5, 0x72, 0xa3, 0xbf, 0x34, 0x07, 0xfd, 0xcc, 0xa0, + 0xc6, 0x0b, 0x16, 0x17, 0xb8, 0x30, 0x2d, 0x5f, 0xf3, 0x51, 0x0e, 0x76, 0x2a, 0x30, 0x33, 0xac, 0x51, 0x5a, 0x96, + 0x6d, 0xbb, 0xb2, 0x79, 0x62, 0xd6, 0xaa, 0xc0, 0x79, 0x02, 0xa4, 0x1c, 0xe7, 0xce, 0xae, 0x47, 0xed, 0x56, 0x39, + 0x3f, 0x3a, 0x8a, 0x6d, 0xa5, 0x31, 0x8d, 0x0b, 0x9f, 0x5f, 0xdd, 0x00, 0xbe, 0xb7, 0x54, 0x63, 0x86, 0xcc, 0x04, + 0x1a, 0x8d, 0x6c, 0xb8, 0xa1, 0x87, 0x84, 0xc4, 0x79, 0x1d, 0x8a, 0x7e, 0xf4, 0x86, 0x19, 0xdc, 0x02, 0x40, 0xa3, + 0x51, 0x5e, 0xf7, 0x6e, 0x41, 0xec, 0xa9, 0xc6, 0x72, 0xf3, 0x25, 0x2e, 0xad, 0x89, 0x5a, 0x3b, 0x76, 0x58, 0x7e, + 0x14, 0x48, 0x84, 0xb8, 0x2b, 0xfc, 0x7c, 0x82, 0xad, 0x21, 0xa0, 0xdc, 0x0b, 0x67, 0x03, 0x81, 0x8d, 0xd5, 0x96, + 0x2b, 0xe4, 0x49, 0x5b, 0x07, 0xa5, 0xbe, 0x10, 0x5c, 0x70, 0x41, 0xa1, 0xc6, 0xc6, 0x61, 0xf9, 0x0b, 0xb6, 0x6b, + 0xce, 0x89, 0x15, 0x72, 0xda, 0x32, 0x33, 0x0c, 0x03, 0xb0, 0x4e, 0x09, 0x98, 0xe7, 0xe4, 0xe9, 0xd7, 0x51, 0xff, + 0x61, 0x80, 0xfa, 0x8f, 0x08, 0x0b, 0xb6, 0x81, 0xd5, 0x95, 0x24, 0xd2, 0x29, 0x28, 0x94, 0xcf, 0x7a, 0xbc, 0x20, + 0xa0, 0x8d, 0xab, 0x43, 0xb5, 0x76, 0x45, 0xf9, 0x15, 0xca, 0x12, 0xee, 0x14, 0xa3, 0xcf, 0xc4, 0xfe, 0x3e, 0x39, + 0xae, 0x2e, 0xe8, 0xa0, 0xeb, 0x7d, 0xca, 0xc1, 0x90, 0x14, 0x3e, 0x7c, 0xf7, 0xed, 0xbb, 0xd5, 0xc7, 0x8b, 0xdd, + 0x1d, 0x1c, 0x98, 0x95, 0xc2, 0xac, 0x83, 0x0d, 0x5c, 0x37, 0x32, 0x85, 0xfe, 0xcb, 0x3b, 0xf1, 0x3a, 0x15, 0xda, + 0xda, 0x8c, 0xfe, 0x38, 0x84, 0xd1, 0xb6, 0xdb, 0xa6, 0x04, 0x0b, 0x9a, 0x05, 0xba, 0x64, 0x8d, 0x5b, 0x69, 0xf1, + 0x15, 0x32, 0xf2, 0xd0, 0x14, 0x60, 0x62, 0xbc, 0x3f, 0xfb, 0xd1, 0xc6, 0xe1, 0x89, 0x1d, 0x1a, 0x5a, 0x19, 0x42, + 0x68, 0xf1, 0x1e, 0x30, 0xc7, 0x1e, 0x11, 0x00, 0xa2, 0xa7, 0x06, 0x52, 0x15, 0xc8, 0xa2, 0xa8, 0x52, 0xe4, 0x3f, + 0x3f, 0x24, 0xe4, 0x69, 0xa5, 0xc8, 0x7c, 0x53, 0x19, 0x73, 0x01, 0x62, 0xa0, 0x14, 0x2e, 0x12, 0xca, 0x04, 0x7b, + 0x19, 0xfa, 0x4e, 0xfb, 0xf2, 0x46, 0xda, 0x4c, 0x2a, 0x6e, 0x3c, 0xb8, 0x29, 0x35, 0x2a, 0x3e, 0x9b, 0xef, 0x21, + 0xb1, 0x95, 0x7b, 0x0f, 0x72, 0x05, 0x35, 0x83, 0x84, 0xef, 0xb7, 0xa6, 0xb4, 0x6f, 0x77, 0xf3, 0x79, 0xdb, 0x22, + 0x66, 0x6b, 0x5d, 0x12, 0x2e, 0x14, 0x2b, 0xf4, 0x23, 0x36, 0x91, 0x05, 0xdc, 0x7f, 0x94, 0x60, 0x41, 0x9b, 0x7b, + 0x81, 0x0e, 0xd0, 0x4c, 0x30, 0xb8, 0x74, 0xd8, 0x9a, 0xa1, 0xf9, 0xf5, 0xd9, 0xdc, 0x81, 0x7f, 0xdc, 0xae, 0xf5, + 0xf4, 0xe8, 0xe8, 0x0b, 0xab, 0x00, 0xe5, 0x86, 0x69, 0x86, 0x11, 0x10, 0x2f, 0xcb, 0xe5, 0xb8, 0x9b, 0xe1, 0x7b, + 0x71, 0xa5, 0x32, 0xf0, 0x84, 0x23, 0x24, 0x42, 0xcf, 0x89, 0xde, 0x4c, 0xb7, 0xe9, 0xbd, 0xd3, 0x66, 0x88, 0x50, + 0xac, 0x01, 0x72, 0x0f, 0x72, 0xb9, 0x55, 0x32, 0xa9, 0xca, 0xd6, 0xb6, 0x1c, 0xc4, 0x63, 0x00, 0x57, 0x6c, 0x84, + 0x94, 0x00, 0x0d, 0xf7, 0x0b, 0x2d, 0xef, 0x24, 0xb0, 0xff, 0x58, 0x25, 0x20, 0xd2, 0xa2, 0xda, 0xc6, 0x45, 0x08, + 0x5b, 0x53, 0x9f, 0xc0, 0x38, 0xe1, 0xe1, 0xf3, 0x7d, 0x1a, 0x6a, 0x8f, 0xda, 0xcc, 0x9c, 0x41, 0x50, 0x42, 0xa2, + 0xb2, 0x42, 0xf2, 0x25, 0x16, 0x8e, 0x9b, 0xf3, 0xf7, 0x70, 0x40, 0x8a, 0x0b, 0x1a, 0xdb, 0xbb, 0x2d, 0x38, 0x3e, + 0x8a, 0x64, 0x19, 0xd7, 0xba, 0xee, 0x15, 0xa6, 0x1a, 0x76, 0xa0, 0xa3, 0x21, 0x9c, 0x0a, 0x73, 0x4f, 0xf8, 0xb8, + 0x22, 0xa9, 0xda, 0x59, 0x40, 0x79, 0x62, 0x58, 0x99, 0xa6, 0x04, 0xf3, 0xd7, 0xce, 0x7c, 0xad, 0x3c, 0x26, 0x98, + 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x01, 0x1c, 0x5b, 0x3d, 0x92, 0xc1, 0xa2, 0x7a, 0xa5, 0xb8, 0xe9, 0x34, 0x60, + 0x02, 0xde, 0x80, 0xf5, 0xcc, 0xf6, 0xd6, 0x7f, 0x6e, 0x0e, 0x46, 0x81, 0x55, 0x8d, 0xc0, 0x4b, 0x43, 0xe0, 0x11, + 0x30, 0x6e, 0xde, 0xb4, 0xbc, 0xef, 0x8c, 0x68, 0x84, 0x3f, 0xf1, 0x1c, 0x9e, 0x59, 0x96, 0x7b, 0xe7, 0x63, 0x6b, + 0x45, 0x52, 0x41, 0xc0, 0xb6, 0x08, 0x3b, 0x22, 0x2f, 0x11, 0x56, 0x8d, 0x46, 0x4f, 0x5d, 0xb2, 0x4a, 0xab, 0x52, + 0x0d, 0x53, 0xc0, 0x2d, 0x31, 0xe0, 0x7d, 0xed, 0x44, 0x05, 0x43, 0x02, 0x6f, 0xfd, 0xad, 0x40, 0x7d, 0xff, 0xf0, + 0x4d, 0x1c, 0xd2, 0xb7, 0xb0, 0x6c, 0x79, 0x11, 0x0b, 0x53, 0x8a, 0xab, 0x3b, 0x9c, 0xd7, 0xdf, 0x36, 0x1b, 0x81, + 0x71, 0x1f, 0xb6, 0x31, 0xd8, 0xb8, 0xa1, 0x9e, 0xb6, 0xa4, 0xa1, 0xdc, 0x84, 0x3d, 0x54, 0xd9, 0x3b, 0x86, 0x9d, + 0xf5, 0x74, 0x25, 0xed, 0x6a, 0xa2, 0x36, 0x1b, 0xc5, 0x2a, 0xa3, 0x81, 0x2d, 0xc3, 0x4e, 0x73, 0xcc, 0xec, 0x2a, + 0xf0, 0x1f, 0x2f, 0x88, 0xc6, 0x01, 0xb2, 0xbe, 0xfe, 0xda, 0x75, 0x4a, 0x35, 0x4c, 0xd8, 0xde, 0xee, 0x7c, 0x7c, + 0xcc, 0xf7, 0x9d, 0x8f, 0x58, 0xba, 0xad, 0x6f, 0xce, 0xc6, 0xf6, 0xbf, 0x71, 0x36, 0x3a, 0xb5, 0xbd, 0x3f, 0x1e, + 0x81, 0x3b, 0xa9, 0x1d, 0x8f, 0xf5, 0x35, 0x25, 0x12, 0x0b, 0xb7, 0x1c, 0x57, 0x9d, 0xf5, 0x5a, 0x0c, 0x5a, 0xa0, + 0x76, 0x8a, 0x22, 0xf8, 0xd9, 0xb6, 0x3f, 0x03, 0x92, 0x6c, 0x75, 0xc8, 0xb1, 0x28, 0x45, 0x19, 0x94, 0x80, 0x01, + 0x75, 0x6c, 0x6c, 0xbd, 0x0c, 0x62, 0x3b, 0x1c, 0x72, 0x58, 0x4e, 0x44, 0x79, 0x75, 0x05, 0x23, 0x36, 0xc7, 0x86, + 0x13, 0x30, 0xe3, 0xbd, 0x56, 0x85, 0x5e, 0xfc, 0xfc, 0xd7, 0xcc, 0x69, 0xed, 0x88, 0xb1, 0x9c, 0x44, 0xcd, 0x8a, + 0xc1, 0x8d, 0xc0, 0x31, 0x8c, 0x87, 0x46, 0x42, 0xad, 0x4e, 0x75, 0x54, 0x3b, 0x92, 0x70, 0x0b, 0xd4, 0x6e, 0x87, + 0xe6, 0x5c, 0x5a, 0xaf, 0xf7, 0x1e, 0x2c, 0xb8, 0x08, 0x70, 0xfb, 0x39, 0xd1, 0x35, 0x92, 0x42, 0x89, 0x93, 0xa0, + 0x70, 0x6e, 0x50, 0x55, 0x13, 0x39, 0x68, 0x0d, 0x81, 0x27, 0xed, 0x65, 0x97, 0xb2, 0x12, 0x92, 0xb3, 0x46, 0x03, + 0xe5, 0x65, 0xc7, 0x74, 0x20, 0x1a, 0xd9, 0x10, 0x33, 0x9c, 0x59, 0x81, 0x05, 0x4e, 0xaf, 0x38, 0xaf, 0xba, 0x1e, + 0x64, 0x43, 0x84, 0x8b, 0xf5, 0x3a, 0xb6, 0x43, 0xcb, 0xd1, 0x7a, 0x9d, 0x87, 0x43, 0x33, 0xf9, 0x50, 0xf1, 0x69, + 0x5f, 0x93, 0xa7, 0xe6, 0x3c, 0x7c, 0x0a, 0x83, 0x6c, 0x90, 0x38, 0x77, 0x2a, 0xc1, 0x1c, 0x34, 0x57, 0x0d, 0x39, + 0xc8, 0x1a, 0xed, 0x61, 0x40, 0xc3, 0x06, 0xd9, 0x90, 0xe4, 0x1b, 0xb0, 0x9c, 0x55, 0xee, 0xc0, 0xfc, 0x04, 0x07, + 0xdb, 0x27, 0x73, 0xce, 0xd8, 0x06, 0xc3, 0x35, 0xd9, 0x56, 0x19, 0x94, 0x78, 0xe5, 0x16, 0xd7, 0x97, 0xab, 0x19, + 0x58, 0x94, 0x85, 0xb0, 0xbb, 0x66, 0xee, 0x83, 0xf0, 0x5f, 0x62, 0x3b, 0xa5, 0xa5, 0x11, 0xf7, 0x16, 0xe2, 0x7b, + 0xdb, 0xed, 0x24, 0x49, 0x68, 0x31, 0x35, 0x57, 0x22, 0xfe, 0x86, 0xd7, 0xec, 0x81, 0x53, 0x37, 0xce, 0xa0, 0xe7, + 0x41, 0xd9, 0xd9, 0x90, 0xd8, 0xf1, 0x7b, 0x66, 0xc7, 0x3b, 0xae, 0x64, 0x74, 0xbf, 0x2e, 0xc2, 0x0e, 0x26, 0xff, + 0x5f, 0x1e, 0xcc, 0x99, 0x1b, 0x8c, 0x45, 0x93, 0x2d, 0xb8, 0x7d, 0x05, 0x1e, 0x19, 0xdd, 0x82, 0xdb, 0xd7, 0xe1, + 0xeb, 0xa1, 0x35, 0xfb, 0xea, 0x00, 0x03, 0x32, 0x61, 0x47, 0x5a, 0x25, 0x04, 0xc3, 0xec, 0x6e, 0x73, 0x64, 0x96, + 0xac, 0xc2, 0xe1, 0xaa, 0x49, 0x2c, 0xb6, 0xf6, 0x42, 0xc5, 0xa4, 0x06, 0x82, 0xb1, 0x48, 0x9f, 0xa2, 0x50, 0x69, + 0x50, 0x37, 0x8e, 0x01, 0xac, 0x72, 0xda, 0xfa, 0xa7, 0x47, 0x47, 0x20, 0x34, 0x00, 0x6b, 0x97, 0x64, 0x74, 0xa1, + 0x97, 0x05, 0xf0, 0x57, 0xca, 0xff, 0x86, 0x64, 0x70, 0x3b, 0x31, 0x69, 0xf0, 0x03, 0x12, 0x16, 0x54, 0x29, 0xfe, + 0xc5, 0xa6, 0xb9, 0xdf, 0xb8, 0x20, 0x1e, 0xa3, 0x95, 0xe5, 0x14, 0x25, 0xea, 0x49, 0x87, 0xae, 0x75, 0xc8, 0x3d, + 0xfd, 0xc2, 0x84, 0xfe, 0x99, 0x2b, 0xcd, 0x04, 0x00, 0xa0, 0x42, 0x3c, 0x98, 0x92, 0x42, 0xb0, 0x75, 0x6b, 0xb5, + 0xe8, 0x78, 0xfc, 0xcd, 0x2a, 0xba, 0xce, 0x16, 0xcd, 0xa8, 0x18, 0xe7, 0xb6, 0x93, 0xd0, 0x66, 0xd2, 0xdb, 0x89, + 0x96, 0x25, 0x43, 0x8b, 0x9d, 0x8a, 0xfd, 0x30, 0xb4, 0x3e, 0x16, 0xc4, 0x9f, 0x0b, 0xfe, 0x2c, 0xfd, 0x26, 0x1f, + 0x03, 0x57, 0xea, 0x5f, 0x59, 0x85, 0x70, 0x26, 0x58, 0x07, 0xe4, 0x35, 0xa9, 0x8f, 0xd3, 0xa3, 0xce, 0x78, 0x47, + 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9d, 0x14, 0x06, 0x53, 0xce, 0xbf, 0x2e, 0x71, 0xfd, 0xe2, 0x8f, 0x11, 0x7f, 0x74, + 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x55, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xa6, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, + 0xe7, 0x5b, 0x9e, 0x38, 0x3d, 0xa6, 0x4a, 0xe8, 0xa8, 0xf8, 0x86, 0xe1, 0x17, 0x0c, 0xee, 0x8d, 0x5f, 0xf2, 0xa0, + 0xca, 0xee, 0x7d, 0xf1, 0xcb, 0xe0, 0xbe, 0xf8, 0x25, 0x4f, 0x77, 0x8b, 0x06, 0xf7, 0xc4, 0x9d, 0xe4, 0x22, 0x69, + 0x45, 0x9e, 0x8f, 0x5a, 0xd2, 0xca, 0xbf, 0xd2, 0x6e, 0x0d, 0x5c, 0xd9, 0xc4, 0x81, 0x71, 0x5e, 0x5d, 0x84, 0x62, + 0xce, 0x9c, 0xd1, 0x72, 0xf8, 0x5f, 0x5b, 0x27, 0x77, 0xf2, 0x48, 0x2b, 0x85, 0xbc, 0xa6, 0x85, 0xbe, 0x07, 0x1b, + 0xae, 0xd8, 0xf1, 0x01, 0xa4, 0x04, 0x94, 0x6d, 0xff, 0x5e, 0x17, 0x81, 0x38, 0xae, 0xac, 0xf3, 0x51, 0xd8, 0x3e, + 0x29, 0x4a, 0xae, 0xae, 0x2e, 0x84, 0xdc, 0x1a, 0x2d, 0x01, 0xc2, 0xd4, 0xbb, 0xe6, 0x31, 0x47, 0x93, 0x59, 0xba, + 0xda, 0x94, 0xaa, 0x83, 0xc2, 0x72, 0x75, 0x1c, 0xe1, 0x62, 0x63, 0x6e, 0xd0, 0x3f, 0x71, 0xfc, 0x88, 0x3b, 0x1a, + 0xf9, 0x63, 0x49, 0x81, 0xde, 0xef, 0xf7, 0xb5, 0xd9, 0x43, 0x22, 0xed, 0x1c, 0x4a, 0x4b, 0x01, 0xc0, 0x6a, 0x83, + 0xaf, 0x1b, 0x8f, 0x53, 0x4f, 0xa4, 0x9b, 0xcd, 0x57, 0x0d, 0x61, 0x31, 0x2b, 0x2d, 0x78, 0x4c, 0x37, 0x7b, 0x2c, + 0x47, 0xbd, 0x2c, 0xae, 0xcb, 0x3d, 0x56, 0xeb, 0x17, 0x7d, 0x05, 0x94, 0x95, 0x21, 0xda, 0x7a, 0x1d, 0xd7, 0xe1, + 0x4d, 0x44, 0x70, 0x0d, 0x82, 0xb0, 0x08, 0x0c, 0x38, 0x6a, 0x8c, 0xb7, 0xad, 0x13, 0xa3, 0x6d, 0xfb, 0x25, 0xcf, + 0xba, 0xd7, 0xc6, 0x11, 0x2a, 0x1a, 0x6c, 0xf5, 0x50, 0xf3, 0x80, 0xed, 0xec, 0xca, 0x8e, 0x02, 0x08, 0x2d, 0x4b, + 0xe3, 0xdc, 0xca, 0x8a, 0x76, 0x0f, 0x7c, 0xd1, 0x37, 0xcc, 0x73, 0x1d, 0xe8, 0x76, 0xf3, 0x03, 0xdb, 0xa6, 0x27, + 0xf2, 0x6b, 0xb6, 0x4d, 0x35, 0x4e, 0xf8, 0xb0, 0x85, 0xbe, 0x6d, 0x08, 0x6b, 0xfb, 0xda, 0x5f, 0xe4, 0x7f, 0xa1, + 0xbb, 0x36, 0xa0, 0xa7, 0x05, 0xb3, 0xa7, 0x31, 0xef, 0xf4, 0x66, 0xf3, 0x63, 0xe9, 0xbf, 0x60, 0x6c, 0x85, 0x7e, + 0xb4, 0xbb, 0xc0, 0x89, 0x95, 0xc6, 0x21, 0x38, 0xfe, 0xc4, 0xc9, 0x34, 0x97, 0x23, 0x9a, 0xbf, 0x85, 0x1e, 0xab, + 0xdc, 0xe7, 0x77, 0xe3, 0x82, 0x6a, 0xe6, 0x68, 0x4d, 0x35, 0x8a, 0x4f, 0x3c, 0x18, 0xc6, 0x27, 0x6e, 0x29, 0x77, + 0xd5, 0x02, 0x5e, 0xfd, 0x5c, 0x36, 0x91, 0xfe, 0xb8, 0xf1, 0xb4, 0x83, 0xab, 0xfd, 0xbd, 0x6c, 0x93, 0x34, 0x5e, + 0x92, 0x34, 0xae, 0xe2, 0xed, 0xa6, 0xe2, 0xf8, 0xd1, 0x57, 0x06, 0xbb, 0x4b, 0xe6, 0x1e, 0x05, 0x64, 0xee, 0x11, + 0x4f, 0xbf, 0x59, 0x2b, 0xa0, 0x78, 0xa7, 0xc9, 0xa9, 0xb1, 0x8c, 0xb1, 0xa3, 0x7e, 0xa3, 0xc1, 0xa0, 0x41, 0x93, + 0xab, 0xc0, 0xdb, 0xa1, 0x3a, 0xbd, 0xbc, 0xfd, 0x51, 0x9c, 0x2d, 0x95, 0x96, 0x73, 0xd7, 0xa8, 0x72, 0x3e, 0x4e, + 0x26, 0x13, 0x14, 0xd8, 0xe6, 0x0e, 0x3f, 0xad, 0xbb, 0x91, 0xad, 0x3e, 0x73, 0x31, 0x4e, 0x15, 0x76, 0x67, 0x8b, + 0x4a, 0xe5, 0x86, 0x78, 0x33, 0xe7, 0xdd, 0x3c, 0x3c, 0xe1, 0x82, 0xab, 0x19, 0x2b, 0xe2, 0x02, 0xad, 0xbe, 0xd6, + 0x59, 0x01, 0xb7, 0x39, 0xb6, 0x33, 0x3c, 0x29, 0x2d, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xce, 0xf4, 0x4c, + 0x8e, 0xc1, 0xf0, 0x25, 0x19, 0x97, 0xee, 0x54, 0x47, 0x47, 0x87, 0x71, 0x64, 0xf4, 0x17, 0xe0, 0x83, 0x1e, 0xe6, + 0xa0, 0xfe, 0x0a, 0x1c, 0x83, 0xaa, 0xae, 0x19, 0x5a, 0xb1, 0x6d, 0x1f, 0x1a, 0x9d, 0x7c, 0x66, 0x77, 0x98, 0xa3, + 0xcd, 0x26, 0xb5, 0xa3, 0x8e, 0x26, 0x9c, 0xe5, 0xe3, 0x08, 0x7f, 0x66, 0x77, 0x69, 0xe9, 0xb6, 0x6e, 0xbc, 0xac, + 0xcd, 0x22, 0x46, 0xf2, 0x46, 0x44, 0xb8, 0xea, 0x24, 0x5d, 0x6d, 0xb0, 0x2c, 0xf8, 0x14, 0x70, 0xf4, 0x27, 0x76, + 0x97, 0xba, 0xf6, 0x02, 0x57, 0x41, 0xb4, 0xf2, 0xa0, 0x4f, 0x82, 0xe4, 0x70, 0x19, 0x9c, 0xc0, 0x31, 0x30, 0x75, + 0x87, 0xa4, 0x56, 0xae, 0x12, 0x21, 0x11, 0xda, 0xfc, 0xbb, 0x53, 0xc1, 0x8b, 0xf0, 0x9c, 0xd3, 0x35, 0x8b, 0xdb, + 0xad, 0x4a, 0x0c, 0x2a, 0x54, 0x16, 0x24, 0x1f, 0x62, 0xee, 0x77, 0x9f, 0xf3, 0x7e, 0x08, 0x74, 0x66, 0x0b, 0xea, + 0x1a, 0x4d, 0x27, 0xe6, 0x17, 0xaa, 0xee, 0xa0, 0xe6, 0xba, 0xaa, 0x78, 0xf0, 0x21, 0x06, 0xc0, 0x83, 0xb5, 0x0c, + 0x35, 0x0e, 0xa1, 0x1b, 0x6f, 0xa6, 0x3a, 0xa5, 0x24, 0x5e, 0xf9, 0x39, 0xa4, 0x3c, 0x04, 0xa3, 0xde, 0x00, 0x1a, + 0x3a, 0x04, 0xb3, 0x96, 0x87, 0x7c, 0x12, 0x8b, 0x9d, 0x33, 0x54, 0x9a, 0x33, 0x34, 0x09, 0x40, 0xfe, 0x95, 0x33, + 0x93, 0x19, 0x68, 0x18, 0xde, 0xd2, 0x1c, 0x80, 0x6e, 0x75, 0x1d, 0x0e, 0x85, 0x2b, 0x5a, 0x3a, 0xef, 0xd9, 0x45, + 0x97, 0xb5, 0x61, 0xc5, 0xa6, 0x1d, 0xb4, 0x49, 0x61, 0x4a, 0xcc, 0x16, 0xd8, 0x78, 0xbd, 0x0f, 0xf7, 0x76, 0xb5, + 0x71, 0x91, 0xf8, 0x69, 0x11, 0x0f, 0x93, 0x98, 0xa2, 0x15, 0x8f, 0x29, 0x96, 0x60, 0x07, 0x59, 0x6c, 0xca, 0xf1, + 0xb3, 0x70, 0x39, 0x6a, 0x56, 0xd2, 0xfb, 0x1d, 0x0c, 0x81, 0xcb, 0xd7, 0x60, 0x1b, 0x8a, 0x79, 0x49, 0x58, 0x62, + 0xe3, 0xe9, 0x17, 0xac, 0xdb, 0xdc, 0x2e, 0x88, 0x5f, 0x81, 0x29, 0x8d, 0x57, 0xc1, 0x2c, 0x42, 0xa7, 0x72, 0xe7, + 0x70, 0xe8, 0xae, 0x09, 0x2b, 0xe3, 0xd5, 0x58, 0x91, 0xad, 0xa3, 0xe7, 0xdb, 0x36, 0x9e, 0x7f, 0x2f, 0x59, 0x71, + 0x77, 0xcd, 0xc0, 0xc6, 0x5a, 0x82, 0xbb, 0x71, 0xb5, 0x0c, 0x95, 0x81, 0x7c, 0x5f, 0x1a, 0xd6, 0x65, 0x83, 0xbf, + 0x19, 0x15, 0x63, 0x63, 0xee, 0x29, 0x03, 0x6d, 0x8d, 0xdd, 0x2e, 0xec, 0xab, 0xae, 0x9b, 0xac, 0x67, 0x62, 0x25, + 0x54, 0x90, 0x76, 0x77, 0x0b, 0xb8, 0x08, 0xfd, 0x61, 0x07, 0x6a, 0xb8, 0xad, 0xba, 0x81, 0x24, 0xb8, 0xf6, 0x93, + 0x5f, 0x9f, 0xea, 0x3e, 0x6b, 0xdd, 0xaf, 0x4f, 0xb5, 0x76, 0x59, 0x68, 0x0c, 0x89, 0xb0, 0xeb, 0xa7, 0xf4, 0x9f, + 0x16, 0x9b, 0x0d, 0xda, 0xc0, 0xf0, 0xde, 0xf3, 0x5e, 0x1c, 0xbf, 0xf7, 0x16, 0x8a, 0x09, 0x5c, 0xe4, 0x5e, 0xe7, + 0xd2, 0x13, 0xf2, 0x6a, 0x04, 0xef, 0xf9, 0xce, 0x10, 0xde, 0xf3, 0xc0, 0xe9, 0x15, 0xa4, 0xa6, 0xa9, 0x60, 0x63, + 0x4f, 0x3f, 0x91, 0x45, 0x42, 0xc3, 0xc7, 0xdd, 0xe3, 0x44, 0xe8, 0xbf, 0x52, 0xe0, 0xbf, 0xf0, 0x68, 0xa9, 0xb5, + 0x14, 0x98, 0x8b, 0xc5, 0x52, 0x63, 0x65, 0x46, 0xbf, 0x9a, 0x48, 0xa1, 0x9b, 0x13, 0x3a, 0xe7, 0xf9, 0x5d, 0xba, + 0xe4, 0xcd, 0xb9, 0x14, 0x52, 0x2d, 0x68, 0xc6, 0xb0, 0xba, 0x53, 0x9a, 0xcd, 0x9b, 0x4b, 0x8e, 0x9f, 0xb3, 0xfc, + 0x0b, 0xd3, 0x3c, 0xa3, 0xf8, 0x8d, 0x1c, 0x49, 0x2d, 0xf1, 0xab, 0xdb, 0xbb, 0x29, 0x13, 0xf8, 0xdd, 0x68, 0x29, + 0xf4, 0x12, 0x2b, 0x2a, 0x54, 0x53, 0xb1, 0x82, 0x4f, 0x7a, 0xcd, 0xe6, 0xa2, 0xe0, 0x73, 0x5a, 0xdc, 0x35, 0x33, + 0x99, 0xcb, 0x22, 0xfd, 0xaf, 0xd6, 0x29, 0x7d, 0x30, 0x39, 0xeb, 0xe9, 0x82, 0x0a, 0xc5, 0x61, 0x61, 0x52, 0x9a, + 0xe7, 0x07, 0xa7, 0xdd, 0xd6, 0x5c, 0x1d, 0xda, 0x0b, 0x3f, 0x2a, 0xf4, 0xe6, 0x2f, 0xfc, 0x9b, 0x84, 0x51, 0x26, + 0x23, 0x2d, 0xdc, 0x20, 0x57, 0xd9, 0xb2, 0x50, 0xb2, 0x48, 0x17, 0x92, 0x0b, 0xcd, 0x8a, 0xde, 0x48, 0x16, 0x63, + 0x56, 0x34, 0x0b, 0x3a, 0xe6, 0x4b, 0x95, 0x9e, 0x2d, 0x6e, 0x7b, 0xf5, 0x1e, 0x6c, 0x7e, 0x2a, 0xa4, 0x60, 0x3d, + 0xe0, 0x37, 0xa6, 0x85, 0x5c, 0x8a, 0xb1, 0x1b, 0xc6, 0x52, 0x28, 0xa6, 0x7b, 0x0b, 0x3a, 0x06, 0x3b, 0xe0, 0xf4, + 0x62, 0x71, 0xdb, 0x33, 0xb3, 0xbe, 0x61, 0x7c, 0x3a, 0xd3, 0x69, 0xb7, 0xd5, 0xb2, 0xdf, 0x8a, 0xff, 0xc3, 0xd2, + 0x76, 0x27, 0xe9, 0x74, 0x17, 0xb7, 0xc0, 0xc1, 0x6b, 0x56, 0x34, 0x01, 0x16, 0x50, 0xa9, 0x9d, 0xb4, 0x1e, 0x9c, + 0xde, 0x87, 0x0c, 0xb0, 0x71, 0x68, 0x9a, 0x09, 0x81, 0xb1, 0x7b, 0xba, 0x5c, 0x2c, 0x58, 0x01, 0x5e, 0xf4, 0xbd, + 0x39, 0x2d, 0xa6, 0x5c, 0x34, 0x0b, 0xd3, 0x68, 0xf3, 0x62, 0x71, 0xbb, 0x81, 0xf9, 0xa4, 0xd6, 0x6c, 0xd5, 0x4d, + 0xcb, 0x7d, 0xad, 0x82, 0x21, 0x9a, 0x98, 0x34, 0x69, 0x31, 0x1d, 0xd1, 0xb8, 0xdd, 0xb9, 0x8f, 0xfd, 0xff, 0x92, + 0x0e, 0x0a, 0xc0, 0xd6, 0x1c, 0x2f, 0x0b, 0x73, 0x8b, 0x9a, 0xb6, 0x95, 0x6d, 0x76, 0x26, 0xbf, 0xb0, 0xc2, 0xb7, + 0x6a, 0x3e, 0x56, 0x3b, 0xf3, 0xfe, 0x8f, 0x1a, 0xa5, 0xb6, 0xad, 0x17, 0xea, 0x1a, 0x68, 0xf4, 0x6e, 0x63, 0xff, + 0xd5, 0xb9, 0xa0, 0xf7, 0xcf, 0xba, 0x1e, 0xee, 0x93, 0xc9, 0xa4, 0x06, 0x74, 0x0f, 0xdd, 0x76, 0x6b, 0x71, 0x7b, + 0xd0, 0x69, 0x79, 0x18, 0x5b, 0x98, 0x9e, 0x2f, 0x6e, 0xf7, 0xac, 0x60, 0x80, 0x15, 0xdb, 0xbd, 0x1d, 0x24, 0xa7, + 0xea, 0x80, 0x51, 0xc5, 0x36, 0x7f, 0xe1, 0x11, 0x05, 0xdc, 0x30, 0x48, 0x3b, 0x30, 0x72, 0x2a, 0xac, 0xc0, 0x70, + 0x75, 0xc3, 0xc7, 0x7a, 0x96, 0xb6, 0x5b, 0xad, 0xef, 0x2a, 0x4c, 0xea, 0xcd, 0xec, 0x92, 0xb6, 0x0b, 0x36, 0xaf, + 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0x76, + 0xa6, 0xcc, 0xc5, 0x8c, 0x15, 0x5c, 0xf7, 0xea, 0x5f, 0x55, 0xc7, 0xbb, 0x73, 0xda, 0x58, 0xf9, 0x78, 0x65, 0x6b, + 0xb8, 0xcb, 0xd8, 0xc7, 0xf0, 0xb1, 0x8b, 0x95, 0x5f, 0x68, 0x11, 0x6f, 0x6d, 0x18, 0x1c, 0xd6, 0x40, 0x9b, 0x60, + 0xce, 0x05, 0x98, 0x8a, 0x0e, 0xf1, 0x57, 0xa0, 0x90, 0xd1, 0x3c, 0x8b, 0x61, 0x44, 0x07, 0xcd, 0x83, 0xd3, 0x82, + 0xcd, 0x91, 0x07, 0x44, 0x72, 0xbf, 0x5b, 0xb0, 0xf9, 0x26, 0x31, 0xd5, 0x57, 0x06, 0x75, 0x69, 0xce, 0xa7, 0x22, + 0xcd, 0x18, 0x6c, 0xab, 0x4d, 0xc2, 0x84, 0xe6, 0xfa, 0xae, 0x59, 0xc8, 0x9b, 0xd5, 0x98, 0xab, 0x45, 0x4e, 0xef, + 0xd2, 0x49, 0xce, 0x6e, 0x7b, 0xa6, 0x54, 0x93, 0x6b, 0x36, 0x57, 0xae, 0x6c, 0x0f, 0xd2, 0x9b, 0x63, 0x6b, 0xce, + 0x01, 0xd0, 0x93, 0x37, 0xdb, 0xfb, 0xda, 0x2f, 0x5a, 0x53, 0x2e, 0xf5, 0x41, 0x4b, 0xf5, 0xe6, 0x5c, 0x34, 0xdd, + 0x40, 0xce, 0x00, 0x23, 0x76, 0x21, 0x1f, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, 0x36, 0x5e, 0x05, 0xd5, 0x3a, + 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x1b, 0xb4, 0xb8, 0x23, 0xd0, 0x57, 0x50, 0xfe, 0x41, 0x0b, 0xdb, + 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xae, 0x09, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, + 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, 0x2b, 0x98, 0x7f, 0xda, 0x3a, + 0x68, 0x1d, 0x98, 0xb9, 0xb8, 0x6d, 0x70, 0x76, 0x76, 0xff, 0xf4, 0x01, 0xeb, 0xe5, 0x5c, 0xb0, 0xda, 0x54, 0xbf, + 0x09, 0xea, 0xb0, 0xe1, 0x8e, 0x6b, 0xb8, 0x7d, 0xd0, 0x3e, 0x38, 0x6b, 0x7d, 0xe7, 0xa9, 0x48, 0xce, 0x26, 0xda, + 0xee, 0x9b, 0x1a, 0x59, 0xb9, 0xf0, 0x4d, 0xdf, 0x14, 0x74, 0x91, 0x0a, 0x09, 0x7f, 0x7a, 0xb0, 0xf9, 0x27, 0xb9, + 0xbc, 0x49, 0x67, 0x7c, 0x3c, 0x06, 0x17, 0x2e, 0x28, 0x50, 0x26, 0xb2, 0x3c, 0xe7, 0x0b, 0xc5, 0xed, 0x6a, 0x38, + 0xdc, 0xed, 0x6e, 0x41, 0x35, 0x1c, 0xd0, 0x69, 0x30, 0xa0, 0x6e, 0x35, 0xa0, 0xaa, 0xff, 0x70, 0x84, 0x9d, 0xad, + 0xb9, 0x9a, 0x52, 0xbd, 0x1a, 0x26, 0x7d, 0x5a, 0x2a, 0x0d, 0x30, 0xf7, 0xc6, 0x23, 0xe6, 0x74, 0x69, 0x8e, 0x98, + 0xbe, 0x61, 0x4c, 0x7c, 0x7d, 0x10, 0x57, 0xa9, 0x14, 0xf9, 0x9d, 0xfd, 0x5c, 0x85, 0x5d, 0xd2, 0xa5, 0x96, 0x9b, + 0x64, 0xc4, 0x05, 0x2d, 0xee, 0x3e, 0x2a, 0x26, 0x94, 0x2c, 0x3e, 0xca, 0xc9, 0x64, 0xf5, 0x35, 0x92, 0x77, 0x1f, + 0x6d, 0x12, 0xc5, 0xc5, 0x34, 0x67, 0x96, 0xc0, 0x19, 0x44, 0x70, 0x87, 0x8c, 0x6d, 0xd7, 0x34, 0x59, 0x1b, 0xf4, + 0x26, 0xc9, 0x72, 0x3e, 0xa7, 0x9a, 0x19, 0x38, 0x07, 0xa4, 0xc6, 0x4d, 0xde, 0x52, 0xb9, 0xd6, 0x81, 0xfd, 0x53, + 0x95, 0x86, 0x6d, 0x14, 0x14, 0xf6, 0x4d, 0x72, 0x61, 0xf0, 0xc3, 0x80, 0xc3, 0xec, 0x22, 0xb3, 0x7a, 0x66, 0xed, + 0x02, 0xd8, 0xc1, 0xec, 0x6a, 0x4d, 0x5d, 0x39, 0xba, 0x64, 0x5b, 0xec, 0xb6, 0xbe, 0xab, 0xe7, 0xe6, 0x74, 0xc4, + 0xf2, 0x95, 0xdd, 0xa8, 0x1e, 0xb8, 0x6e, 0xab, 0x86, 0xcb, 0x1c, 0x90, 0x0c, 0x03, 0xa2, 0x61, 0x9a, 0x36, 0x6f, + 0xd8, 0xe8, 0x33, 0xd7, 0x76, 0xcb, 0x34, 0xd5, 0x0d, 0x38, 0x15, 0x99, 0x31, 0x2d, 0x58, 0xb1, 0xf2, 0x84, 0xbc, + 0x55, 0x23, 0xa0, 0xbf, 0x08, 0x73, 0x40, 0x6b, 0x3a, 0x6a, 0x42, 0x88, 0x35, 0x56, 0xac, 0xf6, 0x4d, 0x6e, 0x4e, + 0x6f, 0x1d, 0x8a, 0x3d, 0x68, 0x7d, 0x57, 0x3b, 0x64, 0xcf, 0x5a, 0x2d, 0x7f, 0x44, 0x34, 0x6d, 0x8d, 0xb4, 0x9d, + 0x74, 0xd9, 0xbc, 0x4c, 0xd4, 0x72, 0x91, 0xd6, 0x12, 0x46, 0x52, 0x6b, 0x39, 0xb7, 0x69, 0x7b, 0xa8, 0x51, 0x9d, + 0xf4, 0xb6, 0x3b, 0x8b, 0xdb, 0x03, 0xf3, 0x4f, 0xeb, 0xa0, 0xb5, 0x4b, 0x6a, 0x77, 0xb1, 0xe2, 0x14, 0x79, 0x3c, + 0x86, 0x8e, 0xdb, 0x6c, 0xde, 0x5b, 0x2a, 0x38, 0xee, 0x0d, 0xc4, 0xcd, 0x89, 0xb6, 0x31, 0x93, 0x05, 0xc0, 0x52, + 0x2e, 0xe0, 0x74, 0xb5, 0x87, 0x1d, 0xf4, 0xa1, 0x24, 0x98, 0xc3, 0xef, 0x6d, 0xb4, 0x3e, 0xac, 0xd6, 0x41, 0x35, + 0x30, 0xf8, 0x67, 0xf3, 0x57, 0xc5, 0x9f, 0x3f, 0x61, 0x81, 0x7c, 0xc4, 0x1b, 0x49, 0x77, 0xdd, 0x72, 0x32, 0xd1, + 0x58, 0x57, 0xa2, 0x9a, 0xf1, 0x28, 0x99, 0xd3, 0x5b, 0xeb, 0x5a, 0x32, 0xe7, 0x02, 0x0c, 0xd7, 0x10, 0xd6, 0x81, + 0x89, 0xff, 0x2c, 0x6c, 0x68, 0xac, 0x63, 0x68, 0xf8, 0xb8, 0x93, 0x74, 0xbb, 0x08, 0xb7, 0x70, 0xa7, 0xdb, 0x0d, + 0x64, 0xb2, 0x89, 0xde, 0x57, 0x74, 0x5f, 0x49, 0xb9, 0xa7, 0xe4, 0x89, 0x69, 0xf4, 0xa4, 0xdd, 0x6a, 0x61, 0xe3, + 0x3e, 0x5f, 0x16, 0x16, 0x6a, 0x4f, 0xb3, 0xed, 0x56, 0x0b, 0x9a, 0x85, 0x3f, 0x6e, 0x5e, 0x3f, 0x91, 0x55, 0x2b, + 0x6d, 0xe1, 0x76, 0xda, 0xc6, 0x9d, 0xb4, 0x83, 0x4f, 0xd3, 0x53, 0x7c, 0x96, 0x9e, 0xe1, 0x6e, 0xda, 0xc5, 0xe7, + 0xe9, 0x39, 0xbe, 0x9f, 0xde, 0xc7, 0x17, 0xe9, 0x05, 0x7e, 0x90, 0x3e, 0xc0, 0x0f, 0xd3, 0x76, 0x0b, 0x3f, 0x4a, + 0xdb, 0x6d, 0xfc, 0x38, 0x6d, 0x77, 0xf0, 0x93, 0xb4, 0x7d, 0x8a, 0x9f, 0xa6, 0xed, 0x33, 0xfc, 0x2c, 0x6d, 0x77, + 0x31, 0x85, 0xdc, 0x11, 0xe4, 0x66, 0x90, 0x3b, 0x86, 0x5c, 0x06, 0xb9, 0x93, 0xb4, 0xdd, 0xdd, 0x60, 0x69, 0x43, + 0x6e, 0x44, 0xad, 0x76, 0xe7, 0xf4, 0xac, 0x7b, 0x7e, 0xff, 0xe2, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x7d, 0x16, + 0x0d, 0xf1, 0x9d, 0xf1, 0x7c, 0x91, 0x62, 0xc0, 0x8f, 0xda, 0xdd, 0x21, 0xbe, 0xf5, 0x9f, 0x31, 0x3f, 0xea, 0x9c, + 0xb5, 0xd0, 0xd5, 0xd5, 0xd9, 0xb0, 0x51, 0xe6, 0x3e, 0x32, 0x0e, 0x37, 0x55, 0x16, 0x21, 0x24, 0x86, 0x1c, 0x84, + 0xbf, 0x58, 0x07, 0x1a, 0x16, 0xf3, 0xa4, 0x40, 0x47, 0x47, 0xe6, 0xc7, 0xd4, 0xff, 0x18, 0xf9, 0x1f, 0x34, 0x58, + 0xa4, 0x1b, 0x1a, 0x3b, 0x8f, 0x6b, 0x5d, 0xfa, 0x3b, 0x94, 0xa6, 0x44, 0x07, 0xdc, 0x19, 0xf5, 0xff, 0x57, 0x64, + 0x8d, 0x76, 0xc8, 0x99, 0x55, 0x8c, 0x75, 0xfb, 0x8c, 0xac, 0x8a, 0xb4, 0xd3, 0xed, 0x1e, 0xfd, 0x34, 0xe0, 0x83, + 0xf6, 0x70, 0x78, 0xdc, 0xbe, 0x8f, 0xa7, 0x65, 0x42, 0xc7, 0x26, 0x8c, 0xca, 0x84, 0x53, 0x9b, 0x40, 0x53, 0x5b, + 0x1b, 0x92, 0xce, 0x4c, 0x12, 0x94, 0xd8, 0xa4, 0xa6, 0xed, 0xfb, 0xb6, 0xed, 0x07, 0x60, 0x4d, 0x66, 0x9a, 0x77, + 0x4d, 0x5f, 0x5e, 0x9e, 0xad, 0x5d, 0xa3, 0x78, 0x9a, 0xba, 0xd6, 0x7c, 0xe2, 0xd9, 0x70, 0x88, 0x47, 0x26, 0xb1, + 0x5b, 0x25, 0x9e, 0x0f, 0x87, 0xae, 0xab, 0x07, 0xa6, 0xab, 0xfb, 0x55, 0xd6, 0xc5, 0x70, 0x68, 0xba, 0x44, 0x2e, + 0x76, 0x80, 0xd2, 0x07, 0x9f, 0x4b, 0xfd, 0x0d, 0xbf, 0xec, 0x74, 0xbb, 0x7d, 0xc0, 0x30, 0x63, 0x13, 0xec, 0x61, + 0x74, 0x1d, 0xc0, 0xe8, 0x0b, 0xfc, 0xee, 0xdf, 0xd1, 0xf4, 0x96, 0x96, 0x40, 0xea, 0x47, 0xff, 0x15, 0x35, 0xb4, + 0x81, 0xb9, 0xf9, 0x33, 0xb5, 0x7f, 0x46, 0xa8, 0xf1, 0x99, 0x02, 0xb8, 0x41, 0x23, 0xe5, 0x55, 0xca, 0xa6, 0xc7, + 0x5f, 0x28, 0xb8, 0xf8, 0xcc, 0x54, 0x4e, 0xfb, 0xeb, 0xd9, 0xcd, 0x68, 0x3d, 0x53, 0x5f, 0xd0, 0x9f, 0xf1, 0x9f, + 0xea, 0x38, 0x1e, 0x34, 0x1b, 0x09, 0xfb, 0x73, 0x0c, 0xbe, 0x44, 0xfd, 0x74, 0xcc, 0xa6, 0xa8, 0x3f, 0xf8, 0x53, + 0xe1, 0x61, 0x23, 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0x50, 0x1f, 0xf5, 0xff, 0x54, + 0xc7, 0x7f, 0xa2, 0x7b, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x85, 0x1f, 0x3a, 0x2e, 0xb7, 0x30, 0xc3, 0xed, + 0x26, 0x83, 0x60, 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe0, 0x27, 0xa7, 0x2d, 0xf4, 0x5d, 0xbb, 0x03, 0xca, 0x95, + 0xa6, 0x38, 0xde, 0xdd, 0xf4, 0x45, 0xf3, 0x14, 0x3f, 0x68, 0x16, 0xb8, 0x8d, 0x70, 0xb3, 0xed, 0xb5, 0xde, 0x03, + 0x15, 0xb7, 0x10, 0x56, 0xf1, 0x05, 0xfc, 0x73, 0x86, 0x86, 0xd5, 0x86, 0x7c, 0x4c, 0xb7, 0x7b, 0x07, 0xbf, 0x59, + 0x12, 0xab, 0x06, 0x3f, 0x39, 0x6f, 0xa1, 0xef, 0xce, 0x4d, 0x47, 0xec, 0x58, 0xef, 0xe9, 0x4a, 0xe2, 0xb3, 0xa6, + 0x84, 0x8e, 0x5a, 0x65, 0x3f, 0x22, 0xee, 0x22, 0x2c, 0xe2, 0x53, 0xf8, 0xa7, 0x1d, 0xf6, 0x73, 0x6f, 0xa7, 0x1f, + 0x33, 0xef, 0x36, 0x4e, 0xba, 0xd6, 0x0d, 0x57, 0xd9, 0x3b, 0xf1, 0x06, 0xbb, 0x6a, 0x9b, 0xcb, 0xbc, 0xf6, 0x09, + 0x7c, 0x20, 0xac, 0x8f, 0x89, 0xc2, 0xec, 0x18, 0xfc, 0x77, 0xc1, 0x6c, 0x45, 0x5d, 0x9e, 0xf6, 0x54, 0xa3, 0x81, + 0xc4, 0x40, 0x0d, 0x8f, 0x49, 0xbb, 0xa9, 0x9b, 0x0c, 0xc3, 0xef, 0x06, 0x29, 0x83, 0xc2, 0x89, 0xaa, 0xd7, 0x57, + 0xae, 0x57, 0x7b, 0xf3, 0xef, 0xb1, 0x83, 0x10, 0xa2, 0xfa, 0xb1, 0x6e, 0x32, 0x74, 0x22, 0x1a, 0xb1, 0xbe, 0x64, + 0xfd, 0xf3, 0xb4, 0x85, 0x0c, 0x76, 0xaa, 0x7e, 0xcc, 0x9a, 0x1c, 0xd2, 0x3b, 0x69, 0xcc, 0x9b, 0x1a, 0x7e, 0x9d, + 0x05, 0xd0, 0x12, 0x80, 0x77, 0x95, 0x37, 0x52, 0x71, 0xd2, 0xe9, 0x76, 0xb1, 0x20, 0x3c, 0x99, 0x9a, 0x5f, 0x8a, + 0xf0, 0x64, 0x64, 0x7e, 0x49, 0x52, 0xc2, 0xcb, 0xf6, 0x8e, 0x0b, 0x12, 0xac, 0xaa, 0x49, 0xa1, 0xb0, 0xa0, 0x05, + 0x3a, 0xe9, 0x78, 0xb3, 0x00, 0x3c, 0xf3, 0x73, 0x00, 0x35, 0x48, 0x61, 0x2c, 0x42, 0x65, 0xb3, 0xc0, 0x39, 0xa1, + 0x57, 0x49, 0xb7, 0x3f, 0x3b, 0x89, 0x3b, 0x4d, 0xd9, 0x2c, 0x50, 0x3a, 0x3b, 0x31, 0x35, 0x71, 0x46, 0x5e, 0x51, + 0xdb, 0x1a, 0x9e, 0xc1, 0x5d, 0x6e, 0x46, 0xb2, 0xe3, 0xf3, 0x56, 0x23, 0xe9, 0x22, 0x3c, 0xc8, 0xd6, 0x2d, 0x9c, + 0xaf, 0xd7, 0x2d, 0x4c, 0xc3, 0x65, 0x10, 0x1e, 0x20, 0xa5, 0xa6, 0x6e, 0x3b, 0x36, 0x4f, 0x9f, 0xc7, 0x1a, 0xec, + 0x12, 0x34, 0x78, 0xfb, 0x68, 0xf0, 0x43, 0x4a, 0xb9, 0xbb, 0x10, 0x44, 0x26, 0x3a, 0xe1, 0x24, 0xd4, 0xdd, 0xbd, + 0x12, 0x7e, 0x5d, 0xdd, 0xc8, 0xef, 0x89, 0xf8, 0x83, 0xc4, 0x36, 0xad, 0x2a, 0xf6, 0x9a, 0xee, 0x16, 0xbb, 0x47, + 0x77, 0x8a, 0x3d, 0xdc, 0x53, 0xec, 0xf1, 0x6e, 0xb1, 0xbf, 0x65, 0xa0, 0x69, 0xe4, 0xdf, 0x9d, 0x9e, 0xb7, 0x1a, + 0xa7, 0x80, 0xac, 0xa7, 0xe7, 0xad, 0xaa, 0xd0, 0x53, 0x5a, 0xad, 0x95, 0x26, 0xbf, 0x50, 0xeb, 0x6b, 0xc1, 0xbd, + 0xd3, 0xb7, 0x59, 0x38, 0xeb, 0x72, 0x5e, 0xfa, 0x97, 0x0f, 0xba, 0x60, 0xcb, 0x22, 0x0c, 0xb5, 0xd3, 0x83, 0xf3, + 0x61, 0x7f, 0xc6, 0xe2, 0x06, 0xa4, 0xa2, 0x74, 0xa2, 0xdd, 0x2f, 0x54, 0x5e, 0x69, 0xff, 0x2d, 0x21, 0xa9, 0x33, + 0x44, 0x58, 0x92, 0x86, 0x1e, 0x9c, 0x0e, 0xcd, 0x79, 0x57, 0xc0, 0xef, 0x33, 0xf3, 0xbb, 0x54, 0x28, 0x39, 0x87, + 0x8c, 0xd9, 0xcd, 0x28, 0xea, 0x0b, 0xf2, 0x9a, 0xc6, 0xc6, 0xc6, 0x1e, 0xa5, 0x65, 0x86, 0xfa, 0x02, 0x19, 0x0f, + 0xcb, 0x0c, 0x41, 0x5e, 0x09, 0xf7, 0x1b, 0xaf, 0x8a, 0x14, 0xec, 0x6d, 0xf0, 0x34, 0x05, 0x5b, 0x1b, 0x3c, 0x4a, + 0x05, 0xf8, 0x83, 0xd0, 0x94, 0x05, 0x56, 0xfc, 0x2f, 0x9c, 0x06, 0xcf, 0xdc, 0x3a, 0x13, 0x83, 0xa5, 0x3d, 0x06, + 0x27, 0xc5, 0xdf, 0x32, 0x86, 0xbf, 0x0d, 0x8d, 0x30, 0x83, 0x36, 0x19, 0xc2, 0x3c, 0x29, 0x08, 0xa4, 0x61, 0x9e, + 0x4c, 0x09, 0x83, 0x26, 0x79, 0x32, 0x22, 0x6c, 0xd0, 0x09, 0xd0, 0xe4, 0x89, 0x81, 0x1d, 0x00, 0x87, 0xd7, 0x2f, + 0xf2, 0xb5, 0x6d, 0x1c, 0x2c, 0x04, 0xa0, 0x09, 0x41, 0x20, 0xe6, 0xc2, 0x00, 0xcc, 0x46, 0x94, 0xfd, 0xd9, 0xa9, + 0xc2, 0x5f, 0xf2, 0x84, 0x1a, 0xea, 0xfd, 0x17, 0x90, 0xd5, 0xf8, 0xde, 0x8a, 0x6d, 0xf0, 0xc1, 0xbd, 0x95, 0xd8, + 0x7c, 0x07, 0x7f, 0x94, 0xfd, 0x03, 0xcc, 0x43, 0x42, 0xd1, 0x06, 0xfd, 0x95, 0x42, 0xb1, 0x3d, 0xa5, 0xd0, 0x5f, + 0x8e, 0x44, 0x2b, 0x45, 0x56, 0xb7, 0x69, 0x34, 0xa6, 0xc5, 0xe7, 0x08, 0xff, 0x91, 0x46, 0x39, 0x70, 0x8b, 0x11, + 0xfe, 0x90, 0x46, 0x05, 0x8b, 0xf0, 0xef, 0x69, 0x34, 0xca, 0x97, 0x11, 0xfe, 0x2d, 0x8d, 0xa6, 0x45, 0x84, 0xdf, + 0x83, 0xb2, 0x76, 0xcc, 0x97, 0xf3, 0x08, 0xbf, 0x4b, 0x23, 0x65, 0xbc, 0x21, 0xf0, 0xc3, 0x34, 0x62, 0x2c, 0xc2, + 0x6f, 0xd3, 0x48, 0xe6, 0x11, 0xbe, 0x4e, 0x23, 0x59, 0x44, 0xf8, 0x51, 0x1a, 0x15, 0x34, 0xc2, 0x8f, 0xd3, 0x08, + 0x0a, 0x4d, 0x23, 0xfc, 0x24, 0x8d, 0xa0, 0x65, 0x15, 0xe1, 0x37, 0x69, 0xc4, 0x45, 0x84, 0x7f, 0x4d, 0x23, 0xbd, + 0x2c, 0xfe, 0x5e, 0x4a, 0xae, 0x22, 0xfc, 0x34, 0x8d, 0x66, 0x3c, 0xc2, 0xaf, 0xd3, 0xa8, 0x90, 0x11, 0x7e, 0x95, + 0x46, 0x34, 0x8f, 0xf0, 0xcb, 0x34, 0xca, 0x59, 0x84, 0x7f, 0x49, 0xa3, 0x31, 0x8b, 0xf0, 0xcf, 0x69, 0x74, 0xc7, + 0xf2, 0x5c, 0x46, 0xf8, 0x59, 0x1a, 0x31, 0x11, 0xe1, 0x9f, 0xd2, 0x28, 0x9b, 0x45, 0xf8, 0x87, 0x34, 0xa2, 0xc5, + 0x67, 0x15, 0xe1, 0xe7, 0x69, 0xc4, 0x68, 0x84, 0x5f, 0xd8, 0x8e, 0xa6, 0x11, 0xfe, 0x31, 0x8d, 0x6e, 0x66, 0xd1, + 0x06, 0x4b, 0x45, 0x56, 0xaf, 0x78, 0xc6, 0x7e, 0x67, 0x69, 0x34, 0x69, 0x4d, 0x2e, 0x26, 0x93, 0x08, 0x53, 0xa1, + 0xf9, 0xdf, 0x4b, 0x76, 0xf3, 0x54, 0x43, 0x22, 0x65, 0xa3, 0xf1, 0xfd, 0x08, 0xd3, 0xbf, 0x97, 0x34, 0x8d, 0x26, + 0x13, 0x53, 0xe0, 0xef, 0x25, 0x9d, 0xd3, 0xe2, 0x0d, 0x4b, 0xa3, 0xfb, 0x93, 0xc9, 0x64, 0x7c, 0x16, 0x61, 0xfa, + 0xcf, 0xf2, 0x83, 0x69, 0xc1, 0x14, 0x18, 0x31, 0x3e, 0x85, 0xba, 0xdd, 0x49, 0x77, 0x9c, 0x45, 0x78, 0xc4, 0xd5, + 0xdf, 0x4b, 0xf8, 0x9e, 0xb0, 0xb3, 0xec, 0x2c, 0xc2, 0xa3, 0x9c, 0x66, 0x9f, 0xd3, 0xa8, 0x65, 0x7e, 0x89, 0x9f, + 0xd8, 0xf8, 0xd5, 0x5c, 0x9a, 0xab, 0x8c, 0x09, 0x1b, 0x65, 0xe3, 0x08, 0x9b, 0xc1, 0x4c, 0xe0, 0xef, 0x17, 0xfe, + 0x96, 0xe9, 0x34, 0xba, 0xa0, 0x9d, 0x11, 0xeb, 0x44, 0x78, 0xf4, 0xfa, 0x46, 0xa4, 0x11, 0xed, 0x76, 0x68, 0x87, + 0x46, 0x78, 0xb4, 0x2c, 0xf2, 0xbb, 0x1b, 0x29, 0xc7, 0x00, 0x84, 0xd1, 0xc5, 0xc5, 0xfd, 0x08, 0x67, 0xf4, 0x17, + 0x0d, 0xb5, 0xbb, 0x93, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x13, 0x2d, 0xf4, 0x87, 0xa5, 0x72, 0x03, 0x6d, 0x41, 0x8a, + 0xcc, 0xde, 0x82, 0x9a, 0x3f, 0x1a, 0x77, 0xce, 0x1f, 0xb4, 0x59, 0x84, 0xb3, 0xeb, 0x57, 0xd0, 0xdb, 0xfd, 0x49, + 0xb7, 0x05, 0x1f, 0x02, 0xe4, 0x52, 0x56, 0x40, 0x23, 0xe7, 0x67, 0x0f, 0xba, 0x6c, 0x6c, 0x12, 0x15, 0xcf, 0x3f, + 0x9b, 0xd9, 0x5f, 0xc0, 0x7c, 0xb2, 0x82, 0xcf, 0x95, 0x14, 0x69, 0x34, 0xce, 0xda, 0x67, 0xa7, 0x90, 0x70, 0x47, + 0x85, 0x07, 0xce, 0x2d, 0x54, 0xbd, 0x18, 0x45, 0xf8, 0xd6, 0xa6, 0x5e, 0x8c, 0xcc, 0xc7, 0xf4, 0xed, 0x2f, 0xe2, + 0xf5, 0x38, 0x8d, 0x46, 0x17, 0x17, 0xe7, 0x2d, 0x48, 0xf8, 0x8d, 0xde, 0xa5, 0x11, 0x7d, 0x00, 0xff, 0x41, 0xf6, + 0x87, 0x67, 0xd0, 0x21, 0x8c, 0xf0, 0x76, 0xfa, 0x21, 0xcc, 0xf9, 0x3c, 0xa3, 0x9f, 0x79, 0x1a, 0x8d, 0xc6, 0xa3, + 0xfb, 0xe7, 0x50, 0x6f, 0x4e, 0xa7, 0xcf, 0x34, 0x85, 0x76, 0x5b, 0x2d, 0xd3, 0xf2, 0x5b, 0xfe, 0x85, 0x99, 0xea, + 0xdd, 0xee, 0xf9, 0xa8, 0x03, 0x23, 0xb8, 0x06, 0x85, 0x0a, 0x8c, 0xe7, 0x22, 0x33, 0x0d, 0x5e, 0x67, 0x4f, 0xc7, + 0x69, 0xf4, 0xe0, 0xc1, 0x69, 0x27, 0xcb, 0x22, 0x7c, 0xfb, 0x61, 0x6c, 0x6b, 0x9b, 0x3c, 0x05, 0xb0, 0x4f, 0x23, + 0xf6, 0xe0, 0xc1, 0xf9, 0x7d, 0x0a, 0xdf, 0xcf, 0x4d, 0x5b, 0x17, 0x93, 0x51, 0x76, 0x01, 0x6d, 0xbd, 0x83, 0xe9, + 0x9c, 0x5d, 0x9c, 0x8e, 0x4d, 0x5f, 0xef, 0xcc, 0xa8, 0x3b, 0x93, 0xb3, 0xc9, 0x99, 0xc9, 0x34, 0x43, 0x2d, 0x3f, + 0x7f, 0x65, 0x69, 0x94, 0xb1, 0x71, 0x3b, 0xc2, 0xb7, 0x6e, 0xe1, 0x1e, 0x9c, 0xb5, 0x5a, 0xe3, 0xd3, 0x08, 0x8f, + 0x1f, 0x2e, 0x16, 0x6f, 0x0c, 0x04, 0xdb, 0x67, 0x0f, 0xec, 0xb7, 0xfa, 0x7c, 0x07, 0x4d, 0x8f, 0x0c, 0xd0, 0xc6, + 0x7c, 0x6e, 0x5a, 0x3e, 0x7f, 0x00, 0xff, 0x99, 0x6f, 0xd3, 0x74, 0xf9, 0x2d, 0xc7, 0x53, 0xbb, 0x28, 0x6d, 0xf6, + 0xa0, 0x05, 0x35, 0x26, 0xfc, 0xc3, 0xa8, 0xe0, 0x80, 0x46, 0xa3, 0x0e, 0xfc, 0x5f, 0x84, 0x27, 0xf9, 0xf5, 0x2b, + 0x87, 0xb3, 0x93, 0x09, 0x9d, 0xb4, 0x22, 0x3c, 0x91, 0x1f, 0x94, 0xfe, 0xed, 0xa1, 0x48, 0xa3, 0x4e, 0xe7, 0x62, + 0x64, 0xca, 0x2c, 0x7f, 0x52, 0xdc, 0xe0, 0x71, 0xcb, 0xb4, 0x32, 0xa5, 0x6f, 0xd4, 0xe8, 0x5a, 0xc2, 0x4a, 0xc2, + 0x7f, 0x11, 0x9e, 0x82, 0x16, 0xce, 0xb5, 0x72, 0x61, 0xb7, 0xc3, 0xf4, 0xad, 0x41, 0xcd, 0xf1, 0x7d, 0x80, 0x97, + 0x5f, 0xc6, 0x31, 0xa5, 0xdd, 0x4e, 0x2b, 0xc2, 0x66, 0xd4, 0x17, 0x2d, 0xf8, 0x2f, 0xc2, 0x16, 0x72, 0x06, 0xae, + 0xd3, 0x0f, 0xcf, 0x7e, 0xbe, 0x49, 0x23, 0x3a, 0x9e, 0x4c, 0x60, 0x49, 0xcc, 0x64, 0x7c, 0xb1, 0x99, 0x14, 0xec, + 0xee, 0x97, 0x1b, 0xb7, 0x5d, 0x4c, 0x82, 0x76, 0xd0, 0x39, 0x7f, 0x30, 0x3a, 0x8b, 0xf0, 0x9b, 0x31, 0xa7, 0x02, + 0x56, 0x29, 0x1b, 0x77, 0xb3, 0x6e, 0x66, 0x12, 0xa6, 0x32, 0x8d, 0xce, 0x60, 0xc9, 0x3b, 0x11, 0xe6, 0x5f, 0xae, + 0xef, 0x2c, 0xba, 0x41, 0x6d, 0x87, 0x20, 0x93, 0x16, 0x3b, 0xbf, 0xc8, 0x22, 0x9c, 0xd3, 0x2f, 0xcf, 0x7e, 0x29, + 0xd2, 0x88, 0x9d, 0xb3, 0xf3, 0x09, 0xf5, 0xdf, 0xbf, 0xab, 0x99, 0xa9, 0xd1, 0x9a, 0x74, 0x21, 0xe9, 0x46, 0x98, + 0xb1, 0xde, 0xcf, 0x26, 0x06, 0x43, 0x5e, 0xce, 0xa5, 0xc8, 0x9e, 0x4e, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, + 0x07, 0x40, 0x9b, 0x8e, 0xc7, 0x17, 0xec, 0x3c, 0xc2, 0x7f, 0xd8, 0x5d, 0xe2, 0x26, 0xf0, 0x87, 0xc5, 0x6c, 0xe6, + 0x76, 0xfb, 0x1f, 0x16, 0x28, 0x30, 0xdf, 0x09, 0x9d, 0xd0, 0x71, 0x27, 0xc2, 0x7f, 0x18, 0xb8, 0x8c, 0x4f, 0xe1, + 0x3f, 0x28, 0x00, 0x9d, 0x3d, 0x68, 0x31, 0xf6, 0xa0, 0x65, 0xbe, 0xc2, 0x3c, 0x37, 0xf3, 0xd1, 0x79, 0xd6, 0x8e, + 0xf0, 0x1f, 0x0e, 0x1d, 0x27, 0x13, 0xda, 0x02, 0x74, 0xfc, 0xc3, 0xa1, 0x63, 0xa7, 0x35, 0xea, 0x50, 0xf3, 0x6d, + 0xb1, 0xe6, 0xe2, 0x7e, 0xc6, 0x60, 0x72, 0x7f, 0x58, 0x84, 0xbc, 0x7f, 0xff, 0xe2, 0xe2, 0xc1, 0x03, 0xf8, 0x34, + 0x6d, 0x97, 0x9f, 0x4a, 0x3f, 0xcc, 0x0d, 0x92, 0xb5, 0xb2, 0x33, 0xa0, 0x93, 0x7f, 0x98, 0x31, 0x4e, 0x26, 0x13, + 0xd6, 0x8a, 0x70, 0xce, 0xe7, 0xcc, 0x62, 0x82, 0xfd, 0x6d, 0x3a, 0x3a, 0xed, 0x64, 0xe3, 0xd3, 0x4e, 0x84, 0xf3, + 0x37, 0xcf, 0xcc, 0x6c, 0x5a, 0x30, 0x7b, 0xbf, 0xe5, 0x3c, 0xd6, 0xcc, 0xe9, 0x6b, 0x18, 0x24, 0xac, 0x34, 0x54, + 0x7e, 0x1f, 0xd0, 0xc3, 0xf3, 0xf3, 0x6c, 0x0c, 0x03, 0x7d, 0x0f, 0xdd, 0x02, 0x18, 0xdf, 0xdb, 0xcd, 0x37, 0xa2, + 0xdd, 0x2e, 0x4c, 0xf7, 0xfd, 0x62, 0x59, 0x2c, 0x5e, 0xa6, 0xd1, 0x83, 0xd3, 0xfb, 0xad, 0xf1, 0x28, 0xc2, 0xef, + 0xdd, 0x04, 0x4f, 0xb3, 0xd1, 0xe9, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, 0x7f, 0x74, 0x7e, 0x01, 0xe7, 0xc6, + 0x7b, 0xb5, 0x28, 0xde, 0x4c, 0x4d, 0x81, 0x09, 0x7d, 0x00, 0xcd, 0xfe, 0x6a, 0x76, 0xe3, 0xb8, 0x0d, 0x1b, 0xf9, + 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0xbb, 0x17, 0xdd, 0x08, 0xcf, 0xf9, 0x58, 0x00, 0x81, 0x37, 0x1b, 0xe5, + 0x41, 0xfb, 0xc1, 0xfd, 0x56, 0x84, 0xe7, 0x6f, 0x74, 0xf6, 0x81, 0xce, 0x0d, 0x35, 0x9e, 0x00, 0xcc, 0xe6, 0x5c, + 0xe9, 0xbb, 0xd7, 0xca, 0xd1, 0x63, 0xd6, 0x8e, 0xf0, 0x5c, 0x66, 0x19, 0x55, 0x6f, 0x6c, 0xc2, 0xa8, 0x1b, 0x61, + 0x41, 0xbf, 0xd0, 0x4f, 0xd2, 0x6f, 0xa6, 0x31, 0xa3, 0x63, 0x93, 0x66, 0x70, 0x38, 0xc2, 0x6f, 0xc7, 0x70, 0x19, + 0x99, 0x46, 0x93, 0xf1, 0xa4, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb1, 0x1b, 0xa0, 0x01, 0x5f, 0xe3, 0x47, 0xa3, 0x34, + 0x3a, 0x1f, 0x5d, 0xb0, 0xce, 0x69, 0x84, 0x4b, 0x6a, 0x44, 0xbb, 0x90, 0x6f, 0x3e, 0x3f, 0x98, 0x2d, 0x75, 0x66, + 0x13, 0x0c, 0x80, 0xc6, 0xf4, 0x7e, 0x6b, 0x7c, 0x1e, 0xe1, 0xc5, 0x2b, 0xe6, 0xf7, 0x18, 0x63, 0xec, 0x02, 0x60, + 0x09, 0x49, 0x06, 0x81, 0x2e, 0x26, 0xa3, 0x07, 0x17, 0xe6, 0x1b, 0xc0, 0x40, 0x27, 0x8c, 0x01, 0x90, 0x16, 0xaf, + 0x58, 0x09, 0x88, 0xf1, 0xe8, 0x7e, 0x0b, 0xe8, 0xcb, 0x82, 0x2e, 0xe8, 0x1d, 0xbd, 0x79, 0xba, 0x30, 0x73, 0x9a, + 0x8c, 0xbb, 0x11, 0x5e, 0x3c, 0xff, 0x69, 0xb1, 0x9c, 0x4c, 0xcc, 0x84, 0xe8, 0xe8, 0x41, 0x84, 0x17, 0xac, 0x58, + 0xc2, 0x1a, 0x5d, 0x74, 0x4f, 0x27, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, 0x11, 0xdc, 0xb6, 0x2e, 0xe7, 0x69, 0x34, + 0x1e, 0xd3, 0xd6, 0x18, 0xee, 0x5e, 0xe5, 0xcd, 0x2f, 0x85, 0x45, 0x23, 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, + 0xe0, 0xf1, 0x61, 0xc4, 0xb2, 0x8c, 0xba, 0xc4, 0xf3, 0xf3, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0xaf, + 0xd5, 0xdd, 0xa8, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xfa, 0xee, 0x95, 0xa1, 0xab, 0xed, 0xf3, 0x07, + 0xb0, 0x00, 0x8a, 0x8e, 0xc7, 0x2f, 0xed, 0xe1, 0x76, 0x31, 0x3a, 0xeb, 0xb6, 0x4f, 0x23, 0xec, 0x37, 0x02, 0xbd, + 0x68, 0xdd, 0xef, 0x40, 0x09, 0x31, 0xbe, 0xb3, 0x25, 0x26, 0x67, 0xf4, 0xec, 0xbc, 0x15, 0x61, 0xbf, 0x35, 0xd8, + 0xc5, 0xa8, 0x7b, 0x1f, 0x3e, 0xd5, 0x8c, 0xe5, 0xb9, 0xc1, 0xef, 0x2e, 0xc0, 0x45, 0xf1, 0x67, 0x82, 0xa6, 0x11, + 0x6d, 0x75, 0x3b, 0x9d, 0x31, 0x7c, 0xe6, 0x5f, 0x58, 0x91, 0x46, 0x59, 0x0b, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, + 0x28, 0xc2, 0x06, 0xef, 0xce, 0x69, 0xd7, 0xec, 0x7d, 0xb7, 0xab, 0x5a, 0x17, 0x2d, 0xd8, 0xb0, 0x6e, 0x53, 0xb9, + 0x2f, 0x25, 0xe4, 0x8d, 0x23, 0xb1, 0x34, 0xc2, 0x01, 0x82, 0x4e, 0xee, 0x4f, 0x22, 0xec, 0x77, 0xdc, 0xd9, 0xf9, + 0x45, 0x07, 0x48, 0x99, 0x06, 0x42, 0x31, 0xee, 0x8c, 0xce, 0x80, 0x34, 0x69, 0xf6, 0xca, 0xe2, 0x49, 0x84, 0xf5, + 0x53, 0xa5, 0x5f, 0xa6, 0xd1, 0xf8, 0x62, 0x34, 0x19, 0x5f, 0x44, 0x58, 0xcb, 0x39, 0xd5, 0xd2, 0x50, 0xc0, 0xd3, + 0xb3, 0xfb, 0x11, 0x36, 0x68, 0xde, 0x62, 0xad, 0x71, 0x2b, 0xc2, 0xee, 0x28, 0x61, 0xec, 0xa2, 0x03, 0xd3, 0xfa, + 0xf1, 0xb9, 0x06, 0x5c, 0x1e, 0xb3, 0xd1, 0x69, 0x84, 0x4b, 0x7a, 0x6f, 0x08, 0x11, 0x7c, 0xa9, 0xb9, 0xfc, 0xec, + 0x58, 0x0f, 0x20, 0x75, 0x7e, 0xc3, 0xc3, 0x32, 0xfc, 0x7c, 0x63, 0xd1, 0x88, 0x9a, 0x2d, 0x1e, 0xdc, 0x46, 0xbf, + 0xa5, 0xb1, 0x67, 0xdb, 0x39, 0x59, 0x6d, 0x70, 0x19, 0xe4, 0xf5, 0x33, 0xbb, 0x53, 0xb1, 0x54, 0x86, 0x93, 0x0d, + 0x52, 0x94, 0x42, 0xde, 0xad, 0xc1, 0x79, 0xae, 0x82, 0x20, 0x29, 0x48, 0xab, 0x27, 0x2e, 0xbd, 0x37, 0x6d, 0x4f, + 0x40, 0xe8, 0x07, 0x48, 0x2f, 0x08, 0x25, 0x1a, 0x22, 0xe4, 0x58, 0x61, 0xd2, 0x3b, 0x19, 0x18, 0x99, 0x52, 0x5a, + 0xb7, 0x05, 0x4a, 0xa8, 0x8f, 0x8d, 0x1f, 0x4b, 0xac, 0x20, 0x7a, 0x14, 0xea, 0x49, 0x62, 0x22, 0x5d, 0xbf, 0x10, + 0x3a, 0x96, 0x6a, 0x50, 0x0c, 0x71, 0xfb, 0x1c, 0x61, 0x88, 0x21, 0x41, 0x06, 0xf2, 0xea, 0xaa, 0x7d, 0x7e, 0x64, + 0x84, 0xbe, 0xab, 0xab, 0x0b, 0xfb, 0x03, 0xfe, 0x1d, 0x56, 0x71, 0xbb, 0x61, 0x7c, 0xef, 0x59, 0x35, 0xc7, 0x9f, + 0x0d, 0x7f, 0xfd, 0x9e, 0xad, 0xd7, 0xf1, 0x7b, 0x46, 0x60, 0xc6, 0xf8, 0x3d, 0x4b, 0xcc, 0x1d, 0x89, 0xf5, 0x10, + 0x22, 0x03, 0xd0, 0x9c, 0xb5, 0x30, 0x44, 0x93, 0xf7, 0x9c, 0xf7, 0x7b, 0x36, 0xe0, 0x75, 0xef, 0xf2, 0x2a, 0x84, + 0xf3, 0xd1, 0xd1, 0xaa, 0x48, 0xb5, 0x15, 0x13, 0xb4, 0x15, 0x13, 0xb4, 0x15, 0x13, 0x74, 0x15, 0x44, 0xff, 0xac, + 0x0f, 0x52, 0x8a, 0x51, 0xb6, 0x38, 0x9e, 0xfa, 0x0d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, + 0x62, 0xaf, 0x02, 0x63, 0x6f, 0xa2, 0xd3, 0x76, 0x9c, 0xfc, 0x3b, 0xea, 0x8e, 0x67, 0x35, 0xb1, 0xec, 0xcd, 0x5e, + 0xb1, 0x0c, 0x56, 0xd2, 0x88, 0x66, 0x87, 0x36, 0x1e, 0x89, 0x1e, 0xdc, 0x37, 0x82, 0x59, 0x15, 0x24, 0xaf, 0x01, + 0x49, 0x3d, 0x90, 0x42, 0x2e, 0x8c, 0x94, 0x56, 0xa0, 0x74, 0xac, 0xe3, 0x02, 0x34, 0x94, 0x5e, 0x41, 0x59, 0xc6, + 0x72, 0x6d, 0x18, 0x80, 0x28, 0x2b, 0xa3, 0x59, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0x8c, 0xc4, 0x02, 0x0d, + 0x08, 0xd3, 0x80, 0x70, 0x95, 0x41, 0x9c, 0x71, 0xd9, 0x67, 0x26, 0x5b, 0x99, 0x6c, 0x55, 0x66, 0x4b, 0x9f, 0x6d, + 0x85, 0x44, 0x69, 0xb2, 0x65, 0x99, 0x0d, 0x32, 0x1b, 0x9e, 0xa6, 0x0a, 0x8f, 0x52, 0x69, 0x45, 0xb5, 0x4a, 0xb6, + 0x7a, 0x49, 0x43, 0x6d, 0xee, 0xd1, 0x51, 0x5c, 0xca, 0x49, 0x46, 0x4d, 0x7c, 0x6f, 0xc5, 0x93, 0xc2, 0xc8, 0x40, + 0x3c, 0x99, 0xba, 0xbf, 0xa3, 0xcd, 0xb6, 0xac, 0x54, 0x4c, 0x47, 0x5f, 0x29, 0x89, 0xfe, 0xf2, 0x4a, 0xd4, 0xe7, + 0xdc, 0x44, 0x01, 0xba, 0x24, 0x49, 0xab, 0x75, 0xda, 0x3e, 0x6d, 0x5d, 0xf4, 0xf9, 0x71, 0xbb, 0x93, 0x3c, 0xe8, + 0xa4, 0x46, 0x11, 0xb1, 0x90, 0x37, 0xa0, 0x80, 0x39, 0xe9, 0x24, 0x67, 0xe8, 0xb8, 0x9d, 0xb4, 0xba, 0xdd, 0x26, + 0xfc, 0x83, 0x1f, 0xe9, 0xb2, 0xda, 0x59, 0xeb, 0xac, 0xdb, 0xe7, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x80, 0x82, 0xe8, + 0xc4, 0x54, 0xc2, 0x50, 0xbf, 0x5a, 0xde, 0x7f, 0x76, 0xf4, 0x3c, 0x8f, 0x74, 0x2c, 0xad, 0x2a, 0x0e, 0xa0, 0xea, + 0xbf, 0xa6, 0x06, 0x88, 0xfe, 0x6b, 0x54, 0x46, 0xea, 0x5d, 0x15, 0x20, 0x6a, 0x3f, 0xe7, 0xb1, 0x68, 0xb0, 0xe3, + 0xd8, 0xe6, 0x6b, 0xa8, 0xdb, 0x84, 0xe8, 0x79, 0x78, 0xea, 0x72, 0x55, 0x98, 0x3b, 0x45, 0xa8, 0xa9, 0x20, 0x77, + 0xe4, 0x72, 0x65, 0x98, 0x3b, 0x42, 0xa8, 0x29, 0x21, 0x97, 0xa6, 0x3c, 0xa1, 0x90, 0xa3, 0x13, 0xda, 0x34, 0x90, + 0xac, 0x16, 0xe5, 0x39, 0xf3, 0xc3, 0xe6, 0x13, 0x58, 0x1e, 0x43, 0x50, 0x9c, 0x20, 0x2d, 0xe0, 0x85, 0x95, 0x52, + 0x9b, 0xd3, 0xc2, 0xa5, 0x1a, 0x07, 0x32, 0x1a, 0xf0, 0xcf, 0x31, 0x33, 0xcf, 0x6e, 0xb4, 0xfa, 0xa7, 0xe7, 0xad, + 0xb4, 0x0d, 0xae, 0xe2, 0x20, 0x6b, 0x0b, 0x2b, 0x6b, 0x0b, 0x2f, 0x6b, 0x0b, 0x2f, 0x6b, 0x83, 0x00, 0x1f, 0xf4, + 0xfd, 0xbb, 0xac, 0x99, 0xdf, 0xf0, 0xd2, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, + 0xac, 0x51, 0xa8, 0x4a, 0xfd, 0xb9, 0x2a, 0xd2, 0x16, 0x9e, 0xa6, 0xa0, 0xe5, 0x6e, 0x61, 0x6a, 0x36, 0xb7, 0xa7, + 0x0a, 0xdb, 0x51, 0x7c, 0xfa, 0x5e, 0x9d, 0x7c, 0x45, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa4, 0xdc, 0xd2, 0x0c, 0x6e, + 0x69, 0x06, 0xb7, 0x34, 0x03, 0x1a, 0xc1, 0x65, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x06, 0xa7, 0x43, 0x08, + 0x62, 0x18, 0x6b, 0x62, 0x46, 0xbd, 0xd5, 0x79, 0x1b, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1c, + 0xf3, 0xa7, 0x1a, 0xda, 0x27, 0xf0, 0xa2, 0xce, 0x43, 0x1d, 0xb7, 0xc0, 0x74, 0x25, 0x2a, 0xa2, 0xbe, 0x21, 0x0b, + 0xa9, 0xd1, 0xd9, 0x38, 0x93, 0xf4, 0xcf, 0x5b, 0x9e, 0xc0, 0x96, 0x12, 0x84, 0xef, 0x48, 0x7c, 0x66, 0x55, 0x68, + 0x82, 0xd2, 0xe2, 0xd6, 0x99, 0xcb, 0xd9, 0x23, 0xa1, 0x07, 0x66, 0xf3, 0x3e, 0xe6, 0x55, 0x5f, 0x90, 0x02, 0x62, + 0x3e, 0xa6, 0x26, 0xd1, 0x45, 0x6d, 0x06, 0x27, 0x66, 0x72, 0x43, 0x8d, 0x4b, 0xcf, 0xcf, 0xf6, 0xcf, 0x27, 0x1a, + 0xf8, 0x3c, 0x16, 0xd3, 0x91, 0x77, 0x15, 0xfe, 0x68, 0x62, 0x1b, 0x91, 0xc3, 0x43, 0x6b, 0xd1, 0x6e, 0xbe, 0xb6, + 0x4d, 0xda, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x77, 0xef, 0xb1, 0x57, 0x4c, 0x47, 0x28, 0xa0, 0xd9, + 0x06, 0xac, 0xb2, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x47, 0x4e, 0xe8, 0xdd, 0x8c, 0x79, 0x53, 0x4c, 0x47, 0x7b, 0x9f, + 0x5e, 0xb1, 0x3d, 0xf6, 0x5f, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb1, 0xdb, 0x6f, 0xd5, 0xb9, 0xde, 0x5b, 0x47, + 0xe5, 0xdf, 0xaa, 0xf3, 0x64, 0x5f, 0x9d, 0x39, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, 0x81, 0x1a, 0xdb, 0x98, 0x49, 0x4d, + 0x47, 0x10, 0x2b, 0x1f, 0xfe, 0xda, 0x88, 0x36, 0x3d, 0x4f, 0xc2, 0x61, 0x15, 0x64, 0x3f, 0xe9, 0xa6, 0x0c, 0x53, + 0xd2, 0x39, 0x2e, 0x4c, 0x4c, 0x1b, 0x91, 0xd0, 0xa6, 0x4a, 0x28, 0xce, 0x49, 0x1c, 0xd3, 0xe3, 0x0c, 0x22, 0xf3, + 0xb4, 0xfb, 0x34, 0x8d, 0x69, 0x23, 0x43, 0x27, 0x71, 0xbb, 0x41, 0x8f, 0x33, 0x84, 0x1a, 0x6d, 0xd0, 0x99, 0x4a, + 0xd2, 0x6e, 0xe6, 0x10, 0xab, 0xd3, 0x90, 0xe2, 0xfc, 0x58, 0x24, 0x45, 0x43, 0x1e, 0xab, 0xa4, 0x68, 0x24, 0x5d, + 0x2c, 0x92, 0x69, 0x99, 0x3c, 0x35, 0xc9, 0x53, 0x9b, 0x3c, 0x2a, 0x93, 0x47, 0x26, 0x79, 0x64, 0x93, 0x29, 0x29, + 0x8e, 0x45, 0x42, 0x1b, 0x71, 0xbb, 0x59, 0xa0, 0x63, 0x18, 0x81, 0x1f, 0x3d, 0x11, 0x61, 0x88, 0xf4, 0x8d, 0xb1, + 0x31, 0x5a, 0xc8, 0xdc, 0x05, 0x2d, 0xad, 0x80, 0x54, 0x3a, 0x7e, 0x41, 0x9d, 0x7f, 0x02, 0x30, 0x61, 0x6d, 0xff, + 0xf8, 0x90, 0x7c, 0x9b, 0x2c, 0x97, 0x22, 0x70, 0x6c, 0x03, 0x5b, 0xfc, 0xcf, 0xce, 0x9d, 0x07, 0xa0, 0xba, 0xa1, + 0xf9, 0x62, 0x46, 0x77, 0xbc, 0x87, 0x8b, 0xe9, 0xc8, 0xed, 0xac, 0xb2, 0x19, 0x46, 0x0b, 0x1b, 0xea, 0xba, 0xee, + 0xe7, 0x09, 0xa0, 0xf6, 0xbe, 0xa5, 0x09, 0x35, 0x4a, 0x72, 0x5b, 0x63, 0x5a, 0xb0, 0x3b, 0x95, 0xd1, 0x9c, 0xc5, + 0xd5, 0x01, 0x5c, 0x0d, 0x93, 0x91, 0x27, 0xe0, 0x11, 0x50, 0x1c, 0x27, 0xa7, 0x0d, 0x9d, 0x4c, 0x8f, 0x93, 0xee, + 0x83, 0x86, 0x4e, 0x46, 0xc7, 0x49, 0xbb, 0x5d, 0xe1, 0x6c, 0x52, 0x10, 0x9d, 0x4c, 0x89, 0x06, 0x8d, 0xa1, 0x6d, + 0x54, 0x2e, 0x28, 0x98, 0xb8, 0xfd, 0x1b, 0xc3, 0x68, 0xb8, 0x61, 0x08, 0x36, 0xb5, 0x51, 0x3f, 0x77, 0xc6, 0x10, + 0x76, 0xd3, 0xe9, 0x76, 0x9b, 0x3a, 0x29, 0xb0, 0xb6, 0x2b, 0xd9, 0xd4, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x4d, 0x9d, + 0x8c, 0x6c, 0x53, 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0xe7, 0x2c, 0x80, 0x7c, 0xc7, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, + 0xf8, 0xad, 0x72, 0x4d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xdb, 0x55, 0x93, 0xec, 0x5f, 0x97, + 0x2d, 0x9b, 0x2d, 0xa4, 0xae, 0x17, 0x7c, 0x51, 0xc3, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x8f, 0x28, 0x89, 0x21, 0xb6, + 0x9f, 0x39, 0x85, 0x38, 0xf1, 0x7a, 0x64, 0x48, 0xe2, 0x8d, 0xc6, 0x06, 0xc5, 0xc1, 0x79, 0xfb, 0x22, 0xa4, 0xaa, + 0x3b, 0x01, 0xff, 0x08, 0x89, 0x96, 0xc2, 0x9a, 0x84, 0x8e, 0xa3, 0x8a, 0x16, 0xbf, 0x71, 0xda, 0xdd, 0xda, 0x01, + 0x71, 0x74, 0xb4, 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xec, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, + 0x98, 0x07, 0x88, 0xe2, 0x43, 0x6f, 0xdd, 0x37, 0x14, 0x7e, 0x50, 0xc5, 0x1d, 0x74, 0x39, 0xcd, 0x73, 0x93, 0x61, + 0xfa, 0x1a, 0x06, 0x63, 0x7b, 0x15, 0x4e, 0xa8, 0xb4, 0x95, 0xfc, 0x97, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, + 0x46, 0x3f, 0x85, 0x96, 0xc9, 0x15, 0x6c, 0x9c, 0x4f, 0xfa, 0x7a, 0x5d, 0x7b, 0x9e, 0xc8, 0x3e, 0x82, 0x83, 0x8e, + 0x8e, 0xb8, 0x7a, 0x06, 0xc6, 0xd4, 0x2c, 0x6e, 0x84, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x93, 0x39, 0x57, 0xd3, + 0xe0, 0xa0, 0x7b, 0x58, 0xcb, 0xdf, 0xbb, 0x12, 0x7d, 0x9d, 0x72, 0xb7, 0xd6, 0xef, 0x2b, 0x53, 0xf5, 0x9d, 0x87, + 0xb2, 0x8e, 0x8e, 0x78, 0x15, 0xae, 0x2a, 0xfa, 0x2e, 0x42, 0x7d, 0x23, 0x83, 0x3c, 0xcb, 0x25, 0x85, 0x1b, 0x51, + 0xb8, 0x62, 0x48, 0x1b, 0xfc, 0x44, 0xe3, 0x9f, 0xe4, 0xff, 0xa7, 0x46, 0x8e, 0x75, 0xda, 0xe0, 0x81, 0xb9, 0x41, + 0xc8, 0x0a, 0x55, 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1e, 0xe6, 0x74, 0xb1, 0xc8, 0xef, 0xcc, 0x5b, + 0x61, 0x01, 0x47, 0x55, 0x5d, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x00, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xf2, + 0x72, 0x5b, 0x20, 0x90, 0xcc, 0x14, 0x91, 0xcd, 0x76, 0x4f, 0x5d, 0x81, 0x5c, 0xd6, 0x6c, 0x22, 0xed, 0x82, 0x97, + 0x63, 0x0e, 0x32, 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, + 0x0c, 0x68, 0x84, 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xc2, 0x77, 0xfc, 0x95, 0x96, 0x8a, 0x81, 0x1a, + 0x0e, 0x71, 0x61, 0x9e, 0xc7, 0x28, 0xe7, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, + 0x33, 0x72, 0x6d, 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbd, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x65, 0x2e, 0x0a, 0x9d, 0xbc, + 0xc9, 0x2e, 0x45, 0xaf, 0xd1, 0x60, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, + 0xc5, 0x6c, 0x04, 0x3e, 0x08, 0x0d, 0x5e, 0x4b, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xb2, + 0x9f, 0x32, 0x94, 0x6c, 0x65, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x53, 0xed, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, + 0x9b, 0x60, 0x00, 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8c, 0x13, + 0x60, 0x6f, 0x6e, 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x80, 0x1c, 0x3d, 0x24, 0xd0, 0xb9, 0xfd, 0x59, + 0xd1, 0x85, 0x4a, 0x26, 0x2e, 0xc7, 0xf8, 0x43, 0x70, 0x9b, 0x37, 0x88, 0x3e, 0x7e, 0x34, 0x9b, 0xfc, 0xe3, 0xc7, + 0x08, 0x87, 0xc6, 0xf5, 0x51, 0xc0, 0x0b, 0x46, 0xc3, 0x32, 0xb4, 0x96, 0xd9, 0xf8, 0xcd, 0x76, 0x80, 0x76, 0xb4, + 0xc2, 0x3b, 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x80, 0x03, 0xbc, 0xd9, 0x80, 0x0f, 0x7b, 0xaf, 0x62, 0x85, + 0x8e, 0x8e, 0x5e, 0xc5, 0x12, 0xf5, 0xaf, 0x99, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x01, 0x37, 0xc3, 0x97, 0x01, 0x02, + 0x5c, 0xb3, 0x6d, 0xc9, 0xe6, 0x8d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0xbe, + 0x0a, 0xa1, 0xdd, 0x63, 0x84, 0x01, 0x0b, 0x5f, 0xfa, 0x0a, 0xb2, 0x64, 0xce, 0x8a, 0x29, 0x2b, 0xd6, 0xeb, 0xe7, + 0xd4, 0xfa, 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xbd, 0x46, 0x83, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x87, 0xf8, 0xf0, 0x55, + 0x5c, 0x20, 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0x56, 0x5b, 0x97, 0x02, 0x95, 0x8d, 0xe4, 0xa4, 0x85, + 0x67, 0x24, 0x2b, 0xd7, 0xe8, 0x72, 0xd6, 0x6b, 0x34, 0x72, 0x24, 0xe3, 0x6c, 0x90, 0x0f, 0x31, 0xc7, 0x05, 0x5c, + 0xa6, 0xee, 0xae, 0xc3, 0x82, 0xd5, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x47, 0x37, 0x01, 0x30, 0xde, + 0xd1, 0x80, 0x48, 0xec, 0x03, 0xb2, 0xb0, 0x40, 0x56, 0x1e, 0xc8, 0xc2, 0x00, 0x59, 0xa1, 0xfe, 0x02, 0x82, 0x36, + 0x29, 0x94, 0xee, 0x50, 0xf4, 0x7a, 0x78, 0x51, 0xe7, 0xba, 0x82, 0xb9, 0x89, 0x70, 0xe1, 0x96, 0x03, 0xdc, 0x58, + 0xdc, 0xdc, 0x15, 0x59, 0x45, 0x91, 0x89, 0xb4, 0x8b, 0x6f, 0xcd, 0x9f, 0xe4, 0x16, 0xdf, 0xd9, 0x1f, 0x77, 0x81, + 0x32, 0xe9, 0xb7, 0x9a, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xfe, 0xee, + 0x9c, 0xb2, 0xe1, 0x30, 0x44, 0x83, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xe7, 0x9f, 0x11, 0xea, 0x0b, 0x88, 0x66, 0xe4, + 0x4e, 0xb6, 0x66, 0x1b, 0x35, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0x54, + 0x36, 0x1e, 0xb5, 0x61, 0x98, 0x41, 0x55, 0xe1, 0x3f, 0xae, 0x56, 0xdb, 0xc1, 0x96, 0x0c, 0x54, 0x85, 0x89, 0x74, + 0x83, 0xec, 0x43, 0x6c, 0x8c, 0xb0, 0xa3, 0x23, 0x36, 0x10, 0xc3, 0xe0, 0x65, 0xb5, 0xaa, 0x75, 0x1d, 0x2e, 0x5c, + 0x9c, 0x41, 0xb4, 0xfb, 0xf5, 0xda, 0xfe, 0x25, 0x1f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0xb7, 0xf1, 0x62, 0xbf, + 0x2c, 0x96, 0x68, 0xf9, 0x0e, 0x2c, 0xfb, 0x5c, 0xec, 0x42, 0xee, 0xa6, 0xda, 0xf6, 0x50, 0x5f, 0x18, 0x8d, 0x42, + 0x10, 0x39, 0xb8, 0x3a, 0xd2, 0xf0, 0x42, 0x87, 0x79, 0xb5, 0x08, 0xc0, 0xb9, 0x2a, 0x03, 0xb9, 0xc2, 0x91, 0x92, + 0x80, 0xa5, 0xb7, 0xa1, 0x93, 0xf0, 0xa3, 0x4e, 0x25, 0x1d, 0x0b, 0x09, 0x50, 0xe0, 0xc8, 0x5c, 0xce, 0x9b, 0x40, + 0xfd, 0x0c, 0xed, 0x21, 0x72, 0xd5, 0x2a, 0xff, 0x5d, 0x97, 0x2d, 0x5d, 0x44, 0xad, 0x68, 0x2e, 0x97, 0x8a, 0x2d, + 0x17, 0x70, 0xbe, 0x97, 0x69, 0x59, 0xce, 0xb3, 0xcf, 0xf5, 0x14, 0x30, 0x88, 0xbc, 0xd5, 0x73, 0x26, 0x96, 0x91, + 0x9b, 0xe7, 0x4b, 0x2b, 0xee, 0xbf, 0x7e, 0x81, 0xdf, 0x93, 0xce, 0xf1, 0x4b, 0xfc, 0x3b, 0x25, 0xef, 0x1b, 0x2f, + 0xf1, 0x94, 0x13, 0xcb, 0x1b, 0x24, 0xaf, 0x5f, 0x5d, 0xbf, 0x78, 0xfb, 0xe2, 0xfd, 0xd3, 0x8f, 0x2f, 0x5e, 0x3e, + 0x7b, 0xf1, 0xf2, 0xc5, 0xdb, 0x0f, 0xf8, 0x27, 0x4a, 0x5e, 0x9e, 0xb4, 0x2f, 0x5a, 0xf8, 0x1d, 0x79, 0x79, 0xd2, + 0xc1, 0xb7, 0x9a, 0xbc, 0x3c, 0x39, 0xc3, 0x33, 0x45, 0x5e, 0x1e, 0x77, 0x4e, 0x4e, 0xf1, 0x52, 0xdb, 0x26, 0x73, + 0x39, 0x6d, 0xb7, 0xf0, 0xdf, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x53, 0xb6, 0x65, 0xfc, 0x60, 0xca, 0xd0, 0x91, + 0x32, 0x86, 0x28, 0x97, 0x01, 0x3a, 0x8d, 0x55, 0xdd, 0xb4, 0x01, 0x42, 0x49, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, + 0xae, 0x1d, 0x7e, 0xd2, 0x66, 0xa7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd3, 0x62, 0x4c, 0x72, + 0x29, 0x8b, 0x78, 0x09, 0x8c, 0x80, 0xd1, 0x5a, 0xf0, 0x93, 0x32, 0x66, 0x95, 0xb8, 0x24, 0xed, 0x7e, 0x3b, 0x15, + 0x97, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x9b, 0xb6, 0x5b, 0xe8, 0x38, 0x18, 0xc7, 0x0f, 0x35, 0xb4, 0x1e, + 0x0c, 0xb1, 0xeb, 0x42, 0xfd, 0x5d, 0x68, 0xaf, 0xd2, 0x13, 0x4e, 0x1d, 0xdb, 0xee, 0x89, 0x4b, 0x66, 0xf4, 0xb0, + 0xfc, 0x3b, 0x40, 0x6d, 0xe3, 0x56, 0x53, 0x6e, 0x1c, 0xf7, 0x8b, 0x9f, 0x08, 0x54, 0x0b, 0x8c, 0x13, 0xb3, 0x75, + 0x0b, 0x01, 0xd3, 0x68, 0xb2, 0xc1, 0x1c, 0x28, 0x51, 0xb2, 0xd0, 0x3e, 0xb8, 0xbf, 0x6a, 0x4a, 0x94, 0x2c, 0xe4, + 0x22, 0xae, 0xa9, 0x1a, 0x7e, 0x09, 0xcc, 0x1c, 0x0f, 0xb9, 0x7a, 0x49, 0x5f, 0xc6, 0x35, 0x9e, 0x27, 0x64, 0xed, + 0xc2, 0x6d, 0xf1, 0xab, 0xb3, 0xa2, 0xa8, 0x81, 0xab, 0x04, 0xac, 0x1f, 0x55, 0x53, 0x5f, 0xc2, 0x2b, 0x86, 0xac, + 0xa1, 0xaf, 0x48, 0x40, 0x3d, 0x7f, 0x2d, 0xcd, 0xb8, 0x4a, 0x65, 0xb4, 0x57, 0x44, 0x1b, 0xb3, 0x20, 0xaf, 0x88, + 0xbe, 0x54, 0x06, 0x08, 0x92, 0xf0, 0x81, 0x18, 0xc2, 0x81, 0x6f, 0x07, 0x28, 0x0d, 0x9d, 0x03, 0xb5, 0x52, 0x65, + 0x26, 0x64, 0x3e, 0x4d, 0x88, 0x06, 0xd0, 0x3c, 0x55, 0x2a, 0x28, 0xf3, 0x89, 0x25, 0x0a, 0x86, 0xfe, 0x47, 0xb8, + 0x01, 0x8e, 0x63, 0x83, 0x8a, 0xa1, 0x5d, 0x8d, 0xa8, 0xe7, 0xb7, 0x2f, 0x5a, 0x27, 0x2f, 0x83, 0xfc, 0xa5, 0xf2, + 0xf6, 0x1e, 0x9f, 0x02, 0x4a, 0x6e, 0x83, 0x8a, 0xb5, 0xb1, 0x8f, 0x07, 0xd7, 0x0b, 0x01, 0x72, 0xac, 0xd1, 0x89, + 0x79, 0xd0, 0xb1, 0x87, 0xf4, 0x31, 0x69, 0xb7, 0x20, 0x88, 0xdb, 0x1e, 0xca, 0xf7, 0xc7, 0x16, 0x4c, 0x75, 0x72, + 0xdb, 0x04, 0x5a, 0x0d, 0x6f, 0x3c, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, 0x33, 0xec, 0x98, 0x35, 0xc4, 0xb1, + 0x40, 0x2e, 0xf8, 0xad, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0x6b, 0xd0, 0x1b, 0x47, 0x5d, 0x36, 0x93, 0xee, 0xf1, + 0xcb, 0xa3, 0xa3, 0x58, 0x36, 0xc8, 0x7b, 0x84, 0x57, 0x14, 0x6c, 0xb6, 0xc1, 0xf7, 0x8e, 0x5b, 0x26, 0x3e, 0x55, + 0x01, 0x75, 0x9c, 0xa8, 0xda, 0xb1, 0x56, 0x75, 0x56, 0xee, 0x06, 0x3f, 0xa6, 0x0e, 0x6a, 0x04, 0x69, 0x76, 0x74, + 0x9d, 0x10, 0xca, 0x3f, 0xd6, 0x1c, 0xe5, 0x60, 0x5b, 0x36, 0x7e, 0xa7, 0xe8, 0xbb, 0xf7, 0xcd, 0x97, 0x01, 0x1e, + 0xd4, 0x4c, 0x93, 0xde, 0x37, 0xde, 0xa3, 0xef, 0xde, 0x07, 0xae, 0x8e, 0xbc, 0x62, 0x4f, 0x3c, 0x37, 0xf2, 0xab, + 0xe5, 0x4a, 0x7f, 0x05, 0xc9, 0xbe, 0x20, 0xbf, 0x02, 0x96, 0x53, 0xf2, 0x6b, 0x2c, 0x9b, 0x10, 0x02, 0x92, 0xfc, + 0x1a, 0x17, 0xf0, 0x23, 0x27, 0xbf, 0xc6, 0x80, 0xed, 0x78, 0x66, 0x7e, 0x14, 0x25, 0x30, 0xc0, 0xbd, 0x4e, 0x5a, + 0x2f, 0xbb, 0x62, 0xbd, 0x16, 0x47, 0x47, 0xd2, 0xfe, 0xa2, 0x57, 0xd9, 0xd1, 0x51, 0x7e, 0x39, 0xab, 0xfa, 0xe6, + 0x7a, 0x1f, 0x7d, 0x31, 0x08, 0x85, 0x03, 0xd3, 0x34, 0x1e, 0xce, 0x58, 0x67, 0x21, 0xe2, 0x40, 0x03, 0xcd, 0xd3, + 0xce, 0xfd, 0xf3, 0x0b, 0x0c, 0xff, 0xde, 0x0f, 0x0a, 0x82, 0x0e, 0xdf, 0x4e, 0x8c, 0xb4, 0x59, 0xf3, 0xbc, 0xaa, + 0x73, 0x15, 0xe0, 0x33, 0x66, 0xa8, 0x29, 0x8e, 0x8e, 0xf8, 0x65, 0x80, 0xcb, 0x98, 0xa1, 0x46, 0x60, 0xb1, 0xf7, + 0xb4, 0xb4, 0x27, 0x33, 0x5c, 0x13, 0x3c, 0xee, 0xcb, 0x07, 0xc5, 0xf0, 0x52, 0x3b, 0x6a, 0x12, 0x86, 0x00, 0x57, + 0xa4, 0xe5, 0x36, 0x59, 0x4f, 0x34, 0xd5, 0x55, 0xbb, 0x87, 0x24, 0x51, 0x0d, 0x71, 0x75, 0xd5, 0xc6, 0xa0, 0x92, + 0xef, 0x2b, 0x22, 0x53, 0x41, 0xbc, 0x9b, 0xe2, 0x2a, 0x97, 0xa9, 0xc2, 0x33, 0x9e, 0x0a, 0x2f, 0x67, 0xdf, 0xf3, + 0xd6, 0xd3, 0xc6, 0x71, 0xd4, 0xf4, 0xcc, 0xb0, 0xe8, 0xab, 0xd2, 0xe1, 0x11, 0x36, 0xa9, 0x1a, 0xc2, 0xdb, 0x89, + 0x25, 0xe6, 0x31, 0xeb, 0xe5, 0xc7, 0x20, 0x36, 0xb5, 0x6a, 0xb4, 0x21, 0x13, 0x3e, 0x37, 0xa9, 0x82, 0x81, 0x9a, + 0xc2, 0x97, 0x60, 0x64, 0x95, 0x55, 0x86, 0xd9, 0xbe, 0x61, 0x28, 0x20, 0xa0, 0xc0, 0x15, 0x61, 0x81, 0x04, 0x2f, + 0xb2, 0x1a, 0xe1, 0xa8, 0x93, 0x0b, 0x3b, 0xb9, 0x4b, 0x05, 0xdd, 0x89, 0xe1, 0xa5, 0xee, 0x21, 0xd1, 0x68, 0x38, + 0x6e, 0xfb, 0x4a, 0x98, 0x41, 0x34, 0xdb, 0xc3, 0x2b, 0xd6, 0x43, 0xaa, 0xd9, 0x2c, 0x0d, 0x20, 0xaf, 0x5a, 0xeb, + 0xb5, 0xba, 0xf4, 0x8d, 0xf4, 0xfd, 0x39, 0x6e, 0xf8, 0x2e, 0x2f, 0x78, 0xfe, 0x21, 0xc9, 0x20, 0x02, 0xaa, 0x0a, + 0x7c, 0xb6, 0x5c, 0x44, 0x38, 0x32, 0xcf, 0xea, 0xc1, 0x5f, 0xf3, 0x1c, 0x5a, 0x84, 0x23, 0xf7, 0xd2, 0x5e, 0x34, + 0xac, 0x06, 0xab, 0xb2, 0x32, 0x48, 0x3c, 0x4f, 0x3e, 0x02, 0xe3, 0xa0, 0x3f, 0x29, 0xb4, 0xaa, 0x7e, 0x27, 0xb9, + 0x0b, 0x97, 0xa2, 0xfc, 0xe3, 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, + 0x8d, 0xd7, 0x27, 0xdb, 0xee, 0xd1, 0xf3, 0x55, 0xd9, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0x7f, 0xc8, 0xbd, 0x2f, + 0x20, 0x47, 0x1f, 0xa5, 0x78, 0x42, 0x35, 0x8d, 0x1a, 0xaf, 0x8d, 0xe1, 0x9b, 0x95, 0xb3, 0x7a, 0x5f, 0x1b, 0x07, + 0xfb, 0xb7, 0xba, 0x87, 0x00, 0x16, 0xb5, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, + 0x3c, 0xfc, 0x18, 0x29, 0xb8, 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x9a, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, + 0xe3, 0xef, 0x06, 0x85, 0x5c, 0xf7, 0x42, 0xd5, 0x89, 0x69, 0xd5, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xaa, + 0xde, 0x8d, 0x84, 0x52, 0xbd, 0x6b, 0x67, 0xde, 0x26, 0x6d, 0xb6, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, + 0xbc, 0x87, 0x65, 0xd0, 0xae, 0x2b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xad, 0xdc, 0xcb, 0x74, 0x7c, 0x20, + 0x87, 0x9b, 0xf2, 0x9d, 0xba, 0x00, 0x0f, 0x02, 0xa7, 0x80, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x35, 0xfd, 0x10, + 0xff, 0x07, 0x0e, 0xf8, 0x0a, 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0xfe, 0x28, 0x43, + 0x47, 0xdd, 0xba, 0x4e, 0xc5, 0xfa, 0xc2, 0xd6, 0x15, 0x2b, 0x65, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, + 0x59, 0xf7, 0xe8, 0xd4, 0x43, 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x67, 0x05, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x08, + 0x5f, 0x55, 0x1e, 0xc0, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, + 0x3a, 0x16, 0x26, 0xb6, 0x84, 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, + 0xb0, 0xa2, 0xf0, 0xd2, 0xa9, 0xc8, 0x82, 0xbe, 0xf6, 0xf5, 0x21, 0xaa, 0x29, 0xf7, 0x63, 0xa3, 0xef, 0x7d, 0xcb, + 0xe7, 0x4c, 0x2e, 0xe1, 0xf1, 0x26, 0xcc, 0x88, 0x62, 0xda, 0x7f, 0x03, 0x05, 0x81, 0x17, 0x80, 0x78, 0x88, 0x8f, + 0xc0, 0x57, 0x79, 0x5a, 0x47, 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0xfd, 0x08, 0xbc, 0x88, 0x40, 0x84, + 0x22, 0x24, 0x62, 0x62, 0x1c, 0xf5, 0x23, 0xe3, 0x92, 0x15, 0x81, 0xd5, 0x18, 0x28, 0xb9, 0x23, 0x3c, 0x55, 0x15, + 0x11, 0x0b, 0x6b, 0xea, 0xa0, 0x12, 0x4b, 0x8d, 0x99, 0xf6, 0x49, 0xa7, 0x02, 0x61, 0x96, 0x6d, 0x0b, 0xca, 0x7a, + 0x4b, 0x5d, 0x80, 0x25, 0x31, 0xa6, 0xb7, 0x3c, 0xf9, 0x08, 0xdc, 0x1c, 0x1b, 0xbb, 0xa2, 0x2b, 0x7e, 0x0d, 0xea, + 0xe9, 0xb4, 0xc0, 0x1f, 0x0d, 0xc3, 0x36, 0x4e, 0xe9, 0x86, 0x70, 0x9c, 0x91, 0x22, 0xa1, 0xb7, 0x10, 0x5b, 0x63, + 0xce, 0x45, 0x9a, 0xe3, 0x39, 0xbd, 0x4d, 0x67, 0x78, 0xce, 0xc5, 0x13, 0xbb, 0xec, 0xe9, 0x18, 0x92, 0xfc, 0xc7, + 0x72, 0x43, 0xcc, 0xd3, 0x60, 0xef, 0x14, 0x2b, 0x1e, 0x01, 0xaf, 0xa2, 0x62, 0xd4, 0x1b, 0x1b, 0x9b, 0x72, 0xae, + 0x2b, 0xe3, 0xf5, 0x7b, 0x3a, 0xa6, 0x38, 0xc3, 0x39, 0x4a, 0x72, 0x89, 0x59, 0x5f, 0xa4, 0xf7, 0x20, 0xae, 0x76, + 0x86, 0xed, 0xb3, 0x62, 0xfc, 0x96, 0xe5, 0xcf, 0x64, 0xf1, 0xde, 0x6c, 0xf9, 0x1c, 0x41, 0x21, 0x70, 0x51, 0x11, + 0x4d, 0xb8, 0xdd, 0x5b, 0xf6, 0x65, 0xd5, 0x14, 0xbd, 0xb5, 0x4d, 0xb9, 0x21, 0xce, 0x20, 0x20, 0x71, 0x32, 0xe3, + 0x8d, 0x36, 0x66, 0xfd, 0xd6, 0x37, 0x1a, 0x9d, 0xa1, 0xb2, 0x24, 0xc2, 0xb0, 0x56, 0x4d, 0x95, 0x4a, 0x22, 0x9a, + 0xca, 0x49, 0x78, 0x2b, 0x03, 0xec, 0x54, 0xe1, 0x4c, 0x2e, 0x85, 0x4e, 0x65, 0x80, 0x37, 0x79, 0xb5, 0xb9, 0x56, + 0xb7, 0x16, 0x62, 0x1a, 0xdf, 0xd9, 0x1f, 0x0c, 0x7f, 0x34, 0x2a, 0xfe, 0x37, 0x60, 0xd8, 0xa3, 0x52, 0x01, 0xf0, + 0x03, 0xc3, 0x59, 0x80, 0x9c, 0xe5, 0x27, 0x6f, 0x01, 0x7c, 0x96, 0x85, 0xbc, 0x83, 0x54, 0x66, 0x52, 0xef, 0x20, + 0x95, 0x41, 0xaa, 0xf1, 0xa8, 0x3f, 0x14, 0x95, 0xb2, 0x28, 0x6c, 0x90, 0x28, 0x5c, 0xaa, 0x83, 0x25, 0x11, 0x09, + 0xb4, 0x6b, 0x44, 0xb9, 0x39, 0x17, 0x10, 0x5a, 0x11, 0x1a, 0xb7, 0xdf, 0xf4, 0x16, 0xbe, 0xef, 0x6c, 0x3e, 0xf3, + 0xf9, 0x77, 0x36, 0xdf, 0x74, 0xe4, 0x31, 0xbe, 0x7e, 0xdb, 0x69, 0x2c, 0xe3, 0xa5, 0xc3, 0xda, 0x77, 0xe5, 0x43, + 0x36, 0x2d, 0xf3, 0x60, 0x38, 0x69, 0xe3, 0x79, 0x80, 0x94, 0xcd, 0x8a, 0x87, 0xeb, 0xe0, 0x76, 0xeb, 0x38, 0xe6, + 0x4d, 0xd2, 0x46, 0xe8, 0xd8, 0x09, 0x57, 0x22, 0x36, 0x92, 0xd3, 0xf1, 0xfb, 0x13, 0xb8, 0x7b, 0x19, 0xa9, 0x2d, + 0x5f, 0x29, 0x5b, 0xad, 0xd9, 0x6e, 0x1d, 0xf3, 0xbd, 0x55, 0x1a, 0x6d, 0x3c, 0x67, 0x64, 0x05, 0x1e, 0x68, 0xb4, + 0xb0, 0xaa, 0x06, 0x70, 0x59, 0x7d, 0x21, 0x7e, 0x5d, 0xd2, 0xb1, 0xf9, 0x3e, 0xb6, 0x29, 0xaf, 0x96, 0xda, 0x27, + 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x5c, 0xc9, 0x20, 0x27, 0xe6, 0x27, 0x24, 0xe9, 0xa2, 0xcb, 0x76, 0x3f, 0xe9, 0x1e, + 0xf3, 0x63, 0x9e, 0x02, 0x0f, 0x1b, 0x37, 0x7d, 0x85, 0x66, 0xdb, 0xd7, 0x79, 0xbc, 0x1c, 0xf1, 0xcc, 0x35, 0x5f, + 0x75, 0x50, 0xa6, 0xda, 0x39, 0x42, 0x16, 0xa0, 0x98, 0xef, 0x25, 0xc8, 0xae, 0x77, 0x73, 0xcc, 0x53, 0xe8, 0x07, + 0x6a, 0x75, 0x6c, 0xad, 0x72, 0x70, 0xbf, 0x2e, 0x01, 0xc1, 0x7c, 0x47, 0xb5, 0xb9, 0xd8, 0xf4, 0x66, 0x5c, 0x75, + 0x76, 0xcc, 0xab, 0x11, 0x86, 0x65, 0x76, 0xfb, 0xf3, 0x53, 0xab, 0xba, 0x3c, 0x0e, 0x20, 0xf2, 0xeb, 0x92, 0x8b, + 0xb0, 0xd3, 0xb0, 0x5b, 0x97, 0x13, 0x76, 0x5a, 0x9f, 0x65, 0x50, 0x64, 0xb7, 0xd7, 0x9d, 0x99, 0xd6, 0x67, 0x7b, + 0x0d, 0x8e, 0x84, 0x30, 0x29, 0xb3, 0xd2, 0x99, 0x54, 0x31, 0x3f, 0x7e, 0x87, 0x5c, 0xeb, 0xaf, 0x96, 0xda, 0xe7, + 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xe5, 0x31, 0x0f, 0x56, 0xee, 0xe9, 0xed, + 0x42, 0xa6, 0x1e, 0x5f, 0xfb, 0xad, 0x74, 0x07, 0x39, 0x81, 0x78, 0xb8, 0xee, 0xc2, 0xb2, 0x20, 0x67, 0x37, 0x77, + 0x50, 0x32, 0x9c, 0xb8, 0x2f, 0xfd, 0x8e, 0xd9, 0xeb, 0x06, 0x7e, 0x99, 0x74, 0x61, 0xea, 0xdb, 0x3d, 0x1c, 0x77, + 0xa0, 0x0f, 0x03, 0x87, 0xed, 0x06, 0x7d, 0x66, 0x05, 0x91, 0xc7, 0xbc, 0xb0, 0x78, 0x76, 0x45, 0xda, 0x7d, 0x9e, + 0xba, 0xcd, 0x64, 0x44, 0xa3, 0x76, 0x93, 0x07, 0x33, 0x03, 0xfc, 0x72, 0x65, 0xc3, 0x22, 0x7e, 0x9d, 0x02, 0x28, + 0xf9, 0x62, 0xd5, 0xfa, 0x54, 0xf0, 0xaa, 0x37, 0x9c, 0x6e, 0xa7, 0xfb, 0x75, 0x83, 0xdb, 0x5d, 0x0f, 0x4f, 0x78, + 0x88, 0xc6, 0xa2, 0xb5, 0x9f, 0xf8, 0x1c, 0x38, 0xa0, 0xa4, 0x75, 0xbf, 0x0b, 0x2e, 0x94, 0x25, 0x2c, 0x77, 0xcb, + 0x8d, 0x76, 0xca, 0x59, 0x38, 0xda, 0x92, 0x01, 0x77, 0xb0, 0x0d, 0x51, 0xe8, 0xe0, 0xb8, 0x83, 0x93, 0x76, 0xbb, + 0xd3, 0xc5, 0xc9, 0x59, 0x17, 0x06, 0xda, 0x48, 0xba, 0xc7, 0x23, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x8f, + 0x20, 0x68, 0x55, 0x28, 0x5e, 0xf3, 0xe3, 0x38, 0x6e, 0x27, 0xf7, 0x5b, 0xed, 0xee, 0x45, 0x03, 0x00, 0xd4, 0x74, + 0x1f, 0xae, 0xc6, 0xab, 0xa5, 0xae, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xab, 0x35, 0xda, 0x9b, 0x6a, 0x0a, + 0xbe, 0xaa, 0x13, 0xce, 0x6d, 0x11, 0xaf, 0xb4, 0x09, 0xb7, 0x45, 0x6c, 0x07, 0x12, 0x83, 0x74, 0x9e, 0x74, 0x3b, + 0x5d, 0x64, 0xc7, 0xa2, 0x1d, 0x7e, 0x94, 0xfb, 0x64, 0xa7, 0x48, 0x43, 0x03, 0x92, 0x94, 0xb3, 0x93, 0x4b, 0x90, + 0xa8, 0x39, 0xb9, 0x6a, 0x37, 0xe7, 0x2c, 0xf1, 0x13, 0x30, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xb8, 0xa4, 0x00, 0x10, + 0x97, 0x60, 0x5c, 0x74, 0xbf, 0xdb, 0xbf, 0x9f, 0x74, 0xcf, 0x3b, 0x96, 0xe8, 0xf1, 0xcb, 0x4e, 0x2d, 0xcd, 0x4c, + 0x3d, 0xe9, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0xdf, 0x85, 0x32, 0x2e, 0x25, 0x2c, 0x05, 0xc1, 0x36, 0xaa, 0x62, 0x10, + 0x61, 0x23, 0xad, 0xe5, 0x9e, 0xd7, 0xb2, 0x2f, 0xce, 0x4e, 0xef, 0x77, 0x43, 0xa8, 0x95, 0xb3, 0x30, 0x0b, 0xed, + 0x26, 0xe2, 0x67, 0x07, 0x4b, 0x8b, 0x8e, 0x93, 0x6e, 0xba, 0x33, 0x41, 0xbb, 0x69, 0x8e, 0x0d, 0x0e, 0x04, 0x0a, + 0xc7, 0x17, 0xc2, 0xe9, 0x4b, 0x82, 0xfb, 0xb1, 0xca, 0xd0, 0x24, 0x54, 0x38, 0xfb, 0x7b, 0xca, 0xe0, 0x3d, 0xcd, + 0xf0, 0xaa, 0xf2, 0x31, 0x15, 0x5f, 0xa8, 0x7a, 0x4d, 0x21, 0x82, 0x88, 0x18, 0x46, 0x2e, 0xbe, 0x79, 0x3d, 0xf7, + 0x07, 0x70, 0x11, 0x66, 0x02, 0x2e, 0x34, 0xbd, 0x12, 0xb4, 0xe2, 0x05, 0x3e, 0x86, 0x0e, 0xb5, 0x66, 0x58, 0x7d, + 0x9e, 0x3a, 0x93, 0x82, 0x50, 0xb7, 0xf5, 0x8e, 0x7f, 0xab, 0x5c, 0x52, 0x5e, 0x65, 0x27, 0x5d, 0x94, 0xb8, 0xcb, + 0xf2, 0xa4, 0x8d, 0x92, 0xc0, 0x84, 0xc4, 0x1d, 0xc9, 0xb3, 0x8c, 0x0c, 0xa2, 0xdb, 0x08, 0x47, 0x77, 0x11, 0x8e, + 0xac, 0x0f, 0xf3, 0x6f, 0xe0, 0xc7, 0x1d, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, 0xd2, 0x4c, 0x40, 0x60, 0xb1, 0x68, + 0x88, 0xc7, 0x50, 0xda, 0x78, 0x56, 0x97, 0xa5, 0x1f, 0xfb, 0xaf, 0xd2, 0xf5, 0xda, 0xa6, 0x04, 0x52, 0xe6, 0xd2, + 0xec, 0x50, 0xfb, 0x30, 0x76, 0x44, 0x3d, 0xb3, 0x1e, 0x61, 0x10, 0x40, 0xe8, 0x9d, 0x7f, 0x58, 0xaf, 0x8a, 0x49, + 0xc2, 0x4e, 0x61, 0xa5, 0xc1, 0x15, 0x3d, 0x0a, 0xcf, 0xb0, 0x08, 0x4f, 0x84, 0x2f, 0x0c, 0x62, 0x85, 0xff, 0x9d, + 0x4b, 0xb9, 0xf0, 0xbf, 0xb5, 0x2c, 0x7f, 0xc1, 0x73, 0x2c, 0xce, 0xa2, 0x05, 0x2c, 0xb7, 0x6c, 0x08, 0xa4, 0x11, + 0xab, 0x8f, 0xe0, 0xe3, 0xc4, 0x85, 0xa9, 0x03, 0x89, 0xf0, 0xa3, 0x11, 0xa8, 0xbc, 0x7c, 0xf8, 0xd1, 0x86, 0x4c, + 0x32, 0x9f, 0x10, 0x33, 0x0d, 0xc2, 0x22, 0x4b, 0xb8, 0xd0, 0x98, 0x16, 0x4c, 0xa9, 0xc8, 0xc6, 0x12, 0x8c, 0xa4, + 0xf0, 0x8f, 0x43, 0xfa, 0x94, 0x89, 0x88, 0x4c, 0x87, 0xf5, 0xd9, 0x5a, 0x71, 0x38, 0x97, 0x85, 0x4a, 0xed, 0x4b, + 0x31, 0x1e, 0x8c, 0x8b, 0xf2, 0x19, 0xc6, 0x74, 0x9c, 0x6d, 0xb0, 0xbd, 0xc3, 0x2e, 0x0b, 0xb9, 0x2b, 0xed, 0xb0, + 0xd4, 0x2c, 0xdb, 0x7c, 0x6d, 0x42, 0xaa, 0x36, 0xa3, 0x60, 0xa2, 0xd5, 0x80, 0xaa, 0xc0, 0x1d, 0x50, 0xd8, 0x06, + 0xa5, 0x49, 0x57, 0x65, 0xc9, 0x74, 0x55, 0x2e, 0xc3, 0x59, 0xab, 0xb5, 0xd9, 0xe0, 0x82, 0x99, 0x40, 0x2e, 0x7b, + 0x4b, 0x40, 0xbe, 0x9a, 0xc9, 0x9b, 0x20, 0x57, 0xa5, 0xe5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, + 0x5f, 0xb8, 0xe2, 0x00, 0x4f, 0x37, 0xbb, 0x91, 0x94, 0x39, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x7c, + 0xcc, 0xf6, 0xb7, 0x09, 0x66, 0xcc, 0xff, 0x5e, 0x8b, 0x1e, 0x81, 0x2c, 0xbb, 0x67, 0x50, 0x07, 0x16, 0x71, 0x0d, + 0x1d, 0x84, 0x32, 0xf8, 0x24, 0xc4, 0xcd, 0x9c, 0xde, 0xc9, 0xa5, 0x06, 0xb8, 0x2c, 0xb5, 0x7c, 0xed, 0xc2, 0x21, + 0x1c, 0xb6, 0xb0, 0x8f, 0x8c, 0xb0, 0x82, 0x90, 0x01, 0x2d, 0x6c, 0x23, 0x62, 0xb4, 0xb0, 0x0b, 0x54, 0xd0, 0xc2, + 0x26, 0x3c, 0x45, 0x6b, 0x53, 0xc6, 0x36, 0xbb, 0x2b, 0x9f, 0xd4, 0xac, 0x36, 0xc1, 0xc2, 0x49, 0x87, 0x9a, 0xe8, + 0xe0, 0xf6, 0x90, 0x11, 0xde, 0xf8, 0xf1, 0xfa, 0xd5, 0x4b, 0x17, 0xb9, 0x9a, 0x4f, 0xc0, 0x65, 0xd3, 0xa9, 0xc6, + 0xee, 0x6c, 0x88, 0xf9, 0x4a, 0x51, 0x6a, 0x85, 0x53, 0x13, 0xec, 0x53, 0xe8, 0x3c, 0xb1, 0x97, 0x17, 0xcf, 0x64, + 0x31, 0xa7, 0xf6, 0xc6, 0x08, 0xdf, 0x29, 0xf7, 0xf8, 0xbc, 0x79, 0xdf, 0xa6, 0x9a, 0xe4, 0xdb, 0xed, 0xab, 0x88, + 0x45, 0x66, 0xe4, 0x57, 0xd0, 0x06, 0x98, 0xca, 0x7e, 0xe0, 0xac, 0x20, 0x2e, 0xfe, 0x7f, 0x40, 0x5e, 0xde, 0x58, + 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, + 0xd5, 0xdf, 0xde, 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0xc9, 0x25, 0x88, 0x1e, 0xe5, 0x33, 0x7f, 0x1c, 0x44, 0x13, + 0x7f, 0xf7, 0x7c, 0xd5, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, + 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x17, 0xe7, 0x97, 0x6d, 0xd6, 0x3c, 0x5b, 0xaf, 0xf3, 0xab, 0x36, + 0x6b, 0x77, 0xed, 0xb3, 0x7b, 0x91, 0xca, 0x80, 0xe6, 0xf2, 0x09, 0xcf, 0x22, 0xd0, 0xce, 0x4e, 0x33, 0x13, 0x4e, + 0x61, 0xe3, 0x15, 0x3f, 0x4b, 0x5d, 0xf5, 0x25, 0xc1, 0xb8, 0x94, 0x58, 0x3d, 0x7e, 0x81, 0xfa, 0xed, 0x74, 0xd7, + 0x55, 0xba, 0xd9, 0x3e, 0x0e, 0x2e, 0x5c, 0x0a, 0x84, 0x3b, 0x10, 0xf2, 0x00, 0xf4, 0xbb, 0x2b, 0x01, 0xa6, 0x41, + 0x80, 0xca, 0x0a, 0x44, 0x5a, 0x3e, 0x5f, 0xce, 0x9f, 0x15, 0xd4, 0x2c, 0xc3, 0x13, 0x3e, 0xe5, 0x5a, 0xa5, 0x14, + 0xa4, 0xdb, 0x7d, 0xe9, 0x9b, 0xfd, 0x12, 0x54, 0x56, 0x8b, 0xbf, 0x9b, 0x68, 0x9e, 0x7d, 0x56, 0x6e, 0xe1, 0x10, + 0x36, 0x2b, 0x2b, 0x70, 0x86, 0x36, 0x38, 0x97, 0x53, 0x5a, 0x70, 0x3d, 0x9b, 0xff, 0x5b, 0xab, 0xc3, 0x06, 0x7a, + 0x68, 0x2e, 0xac, 0x00, 0x24, 0x54, 0x8c, 0xd7, 0x6b, 0x7e, 0xf2, 0xed, 0xfb, 0x24, 0xef, 0x13, 0xde, 0xc6, 0x1d, + 0x7c, 0x8a, 0xbb, 0xb8, 0xdd, 0xc2, 0xed, 0x2e, 0x5c, 0xdd, 0x67, 0xf9, 0x72, 0xcc, 0x54, 0x0c, 0xef, 0xaf, 0xe9, + 0xab, 0xe4, 0xe2, 0xb8, 0x7a, 0x75, 0xa0, 0x48, 0x1c, 0xba, 0x04, 0xc1, 0xef, 0x5d, 0xd4, 0xc0, 0x28, 0x0a, 0x43, + 0xd6, 0x4d, 0x43, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x3a, 0xed, 0x83, 0x3d, 0xb7, 0x5d, 0xd9, 0x26, 0x98, 0x7d, 0xdb, + 0x9f, 0x69, 0xf5, 0xb3, 0xa9, 0x4b, 0xc4, 0xf0, 0xd0, 0xab, 0xd0, 0x03, 0x5d, 0x91, 0xf6, 0xd1, 0x11, 0x58, 0x1d, + 0x05, 0xb3, 0xe1, 0x36, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, 0x18, 0x77, 0xbe, 0xe2, 0x64, 0x65, 0x61, + 0xab, 0x81, 0x0a, 0xb3, 0x22, 0x8c, 0xab, 0x17, 0x92, 0x0a, 0x23, 0x44, 0xc3, 0x11, 0xe6, 0x82, 0xa1, 0x1c, 0xb6, + 0xb0, 0x9c, 0x4c, 0x14, 0xd3, 0x70, 0x74, 0x14, 0xec, 0x0b, 0x2b, 0x94, 0x39, 0x45, 0x46, 0x6c, 0xca, 0xc5, 0x43, + 0xfd, 0x07, 0x2b, 0xa4, 0xf9, 0x34, 0x1a, 0x8c, 0x34, 0x32, 0xab, 0x18, 0xe1, 0x2c, 0xe7, 0x0b, 0xa8, 0x3a, 0x2d, + 0xc0, 0xe9, 0x07, 0xfe, 0xf2, 0x71, 0x1a, 0xb6, 0x09, 0xe4, 0xeb, 0x37, 0x1b, 0xd3, 0x05, 0x8f, 0x0b, 0x7a, 0xf3, + 0x4a, 0x3c, 0x86, 0x1d, 0xf5, 0xb0, 0x60, 0x14, 0xb2, 0x21, 0xe9, 0x2d, 0x34, 0x05, 0x1f, 0xd0, 0xe6, 0xcf, 0x06, + 0x70, 0xe9, 0x85, 0xf9, 0xb0, 0x15, 0x7d, 0xec, 0xc6, 0xa4, 0x6c, 0xcb, 0x64, 0x9a, 0x53, 0xba, 0xca, 0xb4, 0x51, + 0xa8, 0xca, 0x29, 0x6c, 0xb0, 0x8b, 0x7a, 0x12, 0x0e, 0x66, 0x4c, 0xd5, 0x2c, 0x1d, 0x0c, 0xcd, 0xdf, 0x57, 0xb6, + 0x64, 0x0b, 0xbb, 0x88, 0x33, 0x1b, 0x6c, 0x1e, 0x4e, 0x0d, 0xca, 0xb7, 0x31, 0xdc, 0xc3, 0xc2, 0xeb, 0x9d, 0x35, + 0xf2, 0x79, 0xe6, 0xc9, 0xe6, 0xd9, 0x66, 0x63, 0x06, 0xa2, 0x52, 0xd0, 0x03, 0xbd, 0xf1, 0xdb, 0xa6, 0x05, 0xdb, + 0xa3, 0xfc, 0xea, 0xb6, 0xf0, 0x9c, 0xc3, 0x63, 0xa4, 0xbe, 0xbd, 0x6b, 0x5d, 0xc8, 0xcf, 0x0e, 0x24, 0xad, 0x20, + 0xc5, 0x4e, 0x27, 0xe8, 0xec, 0x14, 0x07, 0x23, 0x07, 0x7a, 0x7e, 0xfd, 0xd9, 0xc2, 0xda, 0xff, 0x7e, 0x5d, 0x16, + 0x34, 0xf1, 0x74, 0xca, 0x09, 0x65, 0xfe, 0xfc, 0x7c, 0xc5, 0x93, 0x0a, 0x15, 0xdc, 0x2b, 0x5e, 0xb0, 0xa7, 0x6d, + 0xa0, 0xcf, 0x39, 0xfd, 0x64, 0x7f, 0xd8, 0x18, 0x3e, 0xa5, 0x96, 0x2d, 0x2b, 0xa4, 0x52, 0x0f, 0x6d, 0x9a, 0x3d, + 0x7a, 0xe0, 0x88, 0xfc, 0x19, 0xba, 0x00, 0x5e, 0x7f, 0x5c, 0xc8, 0x85, 0x41, 0x04, 0xf7, 0xdb, 0x8d, 0xdb, 0xf8, + 0x0a, 0x80, 0xb7, 0xc3, 0x41, 0xf5, 0x4f, 0x0b, 0xd8, 0xdf, 0xa8, 0x2c, 0xe9, 0xc7, 0xdb, 0xb1, 0xc7, 0x7f, 0x21, + 0x21, 0x6a, 0xbc, 0xc5, 0xc3, 0xc4, 0xa1, 0x53, 0xc9, 0x9a, 0x95, 0x3f, 0x77, 0x4a, 0x02, 0x86, 0xd5, 0x0b, 0x86, + 0x6c, 0xdc, 0x4e, 0x71, 0x9b, 0xf9, 0x1f, 0x54, 0x30, 0x58, 0xf0, 0xb5, 0x91, 0x54, 0x2c, 0x8b, 0xdf, 0x3e, 0x75, + 0xfe, 0xab, 0xce, 0x71, 0x1d, 0xea, 0xda, 0x4b, 0xa1, 0x23, 0x13, 0xa5, 0x39, 0x42, 0x47, 0x47, 0x5b, 0x19, 0x74, + 0x02, 0x80, 0x47, 0x8e, 0xfd, 0xf2, 0xcb, 0xe7, 0xd9, 0x31, 0xa3, 0x79, 0x2c, 0xa2, 0x90, 0xb9, 0xf3, 0xdc, 0x9c, + 0x9d, 0xc8, 0x13, 0xaa, 0x66, 0xbe, 0x30, 0xc0, 0xf1, 0xd1, 0x4e, 0x2a, 0xe0, 0x7b, 0xb4, 0xd9, 0x33, 0x81, 0x2d, + 0x7e, 0xcb, 0x4e, 0x6a, 0x5f, 0x41, 0xbf, 0x40, 0xab, 0x7d, 0x4c, 0xe5, 0xd6, 0x02, 0x47, 0xdb, 0x13, 0xd9, 0x3b, + 0xf4, 0xad, 0x3a, 0x25, 0xeb, 0xf1, 0x62, 0xbf, 0xd1, 0x57, 0x21, 0xf6, 0x25, 0x57, 0xb4, 0x6d, 0xc4, 0xaa, 0xd7, + 0x82, 0x75, 0x65, 0xea, 0x54, 0x5d, 0xf3, 0x56, 0x96, 0x36, 0xa5, 0x5d, 0x92, 0xbd, 0xdb, 0x62, 0xe1, 0x55, 0x78, + 0xa3, 0x51, 0x5e, 0x84, 0x82, 0x3d, 0x96, 0x18, 0xf6, 0x38, 0x81, 0xeb, 0x85, 0xf5, 0x3a, 0x86, 0x3f, 0xfb, 0xc6, + 0xb0, 0xcf, 0x74, 0xe9, 0x37, 0xbe, 0xc5, 0xaf, 0x04, 0x01, 0x8b, 0x9d, 0x1d, 0x24, 0x58, 0x77, 0xb9, 0x41, 0xc3, + 0x71, 0xe2, 0xbf, 0xe0, 0xb9, 0x6c, 0xed, 0x5d, 0x0e, 0x46, 0xd9, 0x57, 0x9e, 0xd8, 0x2b, 0x59, 0xcb, 0x5a, 0xb4, + 0xfb, 0x2d, 0x09, 0x86, 0xd8, 0x4d, 0xe9, 0x1c, 0xb7, 0x92, 0x36, 0x8a, 0x5c, 0xb1, 0x0a, 0xfd, 0xbf, 0x56, 0x24, + 0xb3, 0x99, 0xff, 0x75, 0x7e, 0x7e, 0xee, 0x52, 0x9c, 0xcd, 0x9f, 0x32, 0x1e, 0x70, 0x26, 0x81, 0x7d, 0xe1, 0x19, + 0x33, 0x3a, 0xe4, 0x37, 0x30, 0x14, 0x22, 0xc8, 0x95, 0x70, 0xec, 0x12, 0xbc, 0xf6, 0x08, 0x94, 0x07, 0xd8, 0xbf, + 0x27, 0x5b, 0xe5, 0xfc, 0x73, 0x51, 0x3e, 0x9c, 0x72, 0xd9, 0x20, 0xfb, 0x62, 0x3e, 0x07, 0xd6, 0x4c, 0x06, 0x5e, + 0x48, 0x88, 0xb0, 0xfd, 0x6d, 0x58, 0x5a, 0x67, 0x29, 0x83, 0x23, 0x2d, 0x97, 0xd9, 0xcc, 0x6a, 0xfe, 0xdd, 0x87, + 0x29, 0xeb, 0x9e, 0x1a, 0x82, 0xc8, 0x5d, 0x64, 0xe5, 0xa2, 0x82, 0x46, 0xdf, 0x97, 0x01, 0x40, 0x0f, 0x5e, 0xb2, + 0x25, 0xfb, 0x1e, 0x1f, 0x54, 0x29, 0xf0, 0xf1, 0xb0, 0xe0, 0x34, 0xff, 0x1e, 0x1f, 0x54, 0x81, 0x40, 0xc1, 0x15, + 0xd2, 0xc4, 0xd2, 0xc4, 0xe6, 0x59, 0xed, 0x34, 0x12, 0x40, 0x41, 0xf3, 0xc8, 0x1c, 0x64, 0xcf, 0x5d, 0x8c, 0xc6, + 0xa4, 0x83, 0x5d, 0x70, 0x30, 0x1b, 0x11, 0xd6, 0x06, 0x52, 0x87, 0xb8, 0x75, 0xe5, 0x6c, 0xcc, 0xd7, 0xa3, 0xad, + 0x05, 0x31, 0xca, 0x64, 0x72, 0xf5, 0x8e, 0xc7, 0x3b, 0x8b, 0x85, 0xc2, 0x6a, 0xc1, 0x02, 0xd5, 0xaa, 0x54, 0xe9, + 0x61, 0xf1, 0xdd, 0x82, 0x59, 0x50, 0xc4, 0x6c, 0xbd, 0x87, 0xb7, 0x5c, 0x11, 0x90, 0x92, 0x5d, 0x12, 0xbc, 0x8c, + 0x6e, 0x30, 0x95, 0xac, 0xe6, 0x72, 0xcc, 0x2c, 0xa1, 0x67, 0x4a, 0x47, 0xd8, 0xe4, 0x29, 0x88, 0x24, 0x76, 0xd8, + 0xc2, 0x8e, 0x35, 0x7a, 0x21, 0xbc, 0x90, 0x02, 0xe7, 0xaa, 0x69, 0x62, 0x4e, 0xb9, 0x89, 0x2e, 0xf6, 0x50, 0x2d, + 0x58, 0xa6, 0x2d, 0x02, 0x1c, 0x3a, 0x34, 0x94, 0xe2, 0xb9, 0x01, 0x85, 0x79, 0xd2, 0xdb, 0xa5, 0x3c, 0x86, 0xc5, + 0x0b, 0x52, 0x80, 0xa8, 0x71, 0x31, 0x2d, 0xeb, 0x2c, 0xf2, 0xe5, 0x94, 0x8b, 0x0a, 0x19, 0x0a, 0xa6, 0x16, 0x52, + 0xc0, 0x8b, 0x1a, 0x65, 0x11, 0x43, 0x87, 0x6a, 0xf8, 0x6e, 0x49, 0x58, 0x59, 0xc7, 0x1c, 0x53, 0x5c, 0x54, 0x35, + 0x80, 0xb9, 0x78, 0x68, 0x04, 0x44, 0x1f, 0x5e, 0xf6, 0x95, 0x78, 0x2b, 0x17, 0x55, 0xbe, 0xa7, 0x71, 0x3e, 0x70, + 0xbd, 0xb3, 0x1b, 0x46, 0x1b, 0xf3, 0xe8, 0x55, 0xb0, 0x7d, 0x7f, 0xe3, 0xd5, 0x43, 0x70, 0x1b, 0xf3, 0x6c, 0x56, + 0x99, 0x35, 0x62, 0xe5, 0x1b, 0x11, 0x55, 0x7b, 0xf5, 0xaa, 0x85, 0xb0, 0x15, 0x01, 0x2a, 0x05, 0x1f, 0xef, 0xe4, + 0xbf, 0xd0, 0x36, 0xdf, 0x9e, 0x43, 0x65, 0x78, 0x20, 0x4f, 0x86, 0xaa, 0x1e, 0x70, 0x51, 0x7e, 0x08, 0x60, 0xf1, + 0x23, 0x13, 0x3f, 0x78, 0xdf, 0x05, 0x32, 0x67, 0x2a, 0x96, 0x78, 0x35, 0xa0, 0xc3, 0xd4, 0xca, 0x43, 0xa9, 0x04, + 0xdb, 0x9e, 0x9b, 0x82, 0x6b, 0x1f, 0xa8, 0x18, 0x0f, 0xd8, 0x30, 0x5d, 0xd5, 0x83, 0x19, 0xdb, 0x70, 0xca, 0xde, + 0x9c, 0xd3, 0x44, 0xff, 0xa5, 0x43, 0x9c, 0x13, 0xb0, 0x3d, 0x2e, 0x99, 0xfb, 0x38, 0x43, 0xfd, 0x3a, 0x87, 0xbf, + 0xda, 0xe0, 0x1c, 0x67, 0x28, 0x7d, 0x18, 0xc3, 0x05, 0xd6, 0x06, 0x03, 0xf8, 0x32, 0x4b, 0xaa, 0xc0, 0x23, 0x35, + 0x33, 0x12, 0xab, 0xbb, 0x08, 0x44, 0x2b, 0x1d, 0xde, 0x8e, 0x33, 0x1f, 0x0e, 0xdc, 0x70, 0xaf, 0xcf, 0x8c, 0x70, + 0x38, 0xca, 0xe2, 0xda, 0x39, 0xc3, 0xc9, 0xd5, 0x21, 0xaf, 0x9d, 0x98, 0x60, 0xed, 0x1d, 0x9e, 0x2a, 0xa0, 0x47, + 0x83, 0x53, 0xc5, 0xd2, 0x10, 0x88, 0x99, 0x00, 0xde, 0xcc, 0xe1, 0xd1, 0x16, 0xe0, 0x7c, 0xb4, 0xc1, 0xc1, 0x57, + 0x5a, 0xeb, 0x6a, 0x5b, 0x89, 0xb2, 0xd9, 0xe0, 0xc1, 0x32, 0xc3, 0x93, 0x0c, 0xcf, 0xb3, 0x61, 0x70, 0xdc, 0x7c, + 0xcc, 0x42, 0x93, 0xae, 0xf5, 0xfa, 0x85, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0xa8, 0x0f, 0x08, 0x9f, 0x42, + 0x16, 0xd0, 0x92, 0xbe, 0xfb, 0xdb, 0xb0, 0xaf, 0x85, 0xa3, 0x46, 0xcc, 0x13, 0x4b, 0x46, 0xfa, 0xfe, 0x47, 0x99, + 0x65, 0x5b, 0x6b, 0x44, 0x8b, 0xdb, 0x83, 0xa8, 0xe1, 0xdb, 0xab, 0xce, 0x97, 0x51, 0x69, 0xb6, 0x03, 0x88, 0x62, + 0x8d, 0x93, 0x74, 0xb0, 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcc, 0x03, 0x7a, + 0xb1, 0x42, 0x89, 0xe1, 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x9a, 0xc8, + 0x7d, 0x97, 0x55, 0x96, 0x41, 0x82, 0x08, 0x23, 0xf2, 0xdb, 0xeb, 0x52, 0x61, 0x9f, 0xe8, 0xb3, 0x7f, 0x8c, 0x2f, + 0x20, 0xdc, 0xbc, 0x4d, 0x69, 0x31, 0xa2, 0x53, 0x60, 0x63, 0x21, 0x0e, 0xe1, 0x4e, 0xc2, 0x7a, 0x3d, 0x18, 0xf6, + 0x84, 0x21, 0xcf, 0xee, 0x01, 0xc1, 0xb2, 0xa1, 0xfd, 0x0d, 0xc0, 0x55, 0xb7, 0xa5, 0xe6, 0xda, 0xe8, 0x7e, 0xa8, + 0x79, 0xe3, 0x8c, 0xbb, 0x24, 0xf7, 0x4c, 0x49, 0xf5, 0x12, 0x79, 0xcd, 0x02, 0xdc, 0x84, 0xae, 0xc2, 0x63, 0xbc, + 0xb4, 0x36, 0x9c, 0xe6, 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x64, 0x43, 0x3c, 0xf6, 0xe1, + 0xce, 0x0f, 0xdf, 0xc4, 0x63, 0x84, 0x0a, 0x62, 0x60, 0x6a, 0x5d, 0xb6, 0xc7, 0x95, 0xdd, 0xbe, 0xc9, 0x34, 0x0c, + 0x83, 0x31, 0x62, 0x1e, 0x87, 0x46, 0xcc, 0x79, 0xa3, 0x81, 0x96, 0x64, 0x0c, 0x46, 0xcc, 0xcb, 0xa0, 0xb5, 0xa5, + 0x7d, 0xec, 0x34, 0x68, 0x6f, 0x89, 0x50, 0x8f, 0x03, 0x4d, 0xd3, 0xf0, 0xac, 0x49, 0xf5, 0xac, 0xbc, 0x7f, 0x64, + 0xeb, 0xa4, 0x03, 0x8a, 0x84, 0xc9, 0x95, 0x9f, 0x84, 0x75, 0x0d, 0xb7, 0xe3, 0x9e, 0x98, 0x71, 0x3b, 0xdb, 0x06, + 0x35, 0x90, 0x83, 0x6c, 0x38, 0xec, 0x49, 0x6f, 0x25, 0xd1, 0xc2, 0x93, 0xea, 0x21, 0x94, 0x6a, 0xf1, 0xbe, 0xe8, + 0xed, 0x2b, 0x6f, 0xee, 0xdf, 0x57, 0xdd, 0x3e, 0x8f, 0x81, 0x03, 0x3a, 0x84, 0xfb, 0xa1, 0x2a, 0x3e, 0xd8, 0x49, + 0x07, 0xa2, 0xa0, 0xa5, 0xad, 0x9a, 0x40, 0x6a, 0xcd, 0xec, 0x62, 0xdd, 0x54, 0xe8, 0x58, 0x40, 0x18, 0x32, 0x55, + 0x75, 0x77, 0xab, 0x02, 0xd5, 0x10, 0x87, 0x53, 0xff, 0xb1, 0x35, 0x62, 0x8d, 0xa3, 0xce, 0x38, 0x32, 0x46, 0x92, + 0x76, 0xf9, 0xe0, 0xed, 0x23, 0xb0, 0x12, 0xf0, 0x31, 0xa8, 0x4d, 0x92, 0x31, 0x24, 0x78, 0xc3, 0x32, 0x6d, 0xf8, + 0x10, 0xee, 0x10, 0x94, 0x27, 0x36, 0x28, 0xad, 0xab, 0x64, 0x21, 0x17, 0x74, 0x19, 0xa0, 0xe7, 0x97, 0xf2, 0x37, + 0x36, 0x1c, 0x59, 0x00, 0x87, 0x6c, 0x67, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2f, 0x85, 0x4e, 0x4c, 0xbc, + 0xee, 0x6b, 0xd8, 0xa0, 0x78, 0x01, 0x0e, 0x82, 0x4e, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x35, 0xc9, 0x06, 0xb7, 0xe6, + 0x24, 0x5e, 0xac, 0xd7, 0x2d, 0x74, 0xfc, 0x93, 0x79, 0x92, 0x7a, 0x52, 0x2a, 0xdc, 0x27, 0x95, 0xc2, 0x1d, 0x2c, + 0x01, 0xc9, 0x24, 0xd0, 0xb5, 0x63, 0x19, 0xaa, 0xd1, 0x21, 0x5a, 0xfa, 0x0b, 0x88, 0x9d, 0xed, 0x8e, 0x25, 0xd0, + 0xb3, 0xef, 0x14, 0xb0, 0xba, 0xf6, 0xb2, 0x04, 0x32, 0x82, 0xbb, 0xdf, 0x04, 0x46, 0x85, 0x68, 0x7c, 0xfe, 0xcc, + 0xab, 0x16, 0x3c, 0x71, 0xfe, 0x5c, 0x73, 0xc3, 0xba, 0x17, 0xf4, 0xc6, 0x34, 0x1f, 0x4f, 0x70, 0x73, 0x62, 0xc1, + 0x79, 0xd2, 0x81, 0x9f, 0x16, 0xa2, 0x27, 0x1d, 0xec, 0x52, 0xf1, 0xa4, 0x04, 0x72, 0x88, 0x9e, 0xce, 0x40, 0x0a, + 0x58, 0xe9, 0xd8, 0x6a, 0x91, 0xa6, 0x68, 0xbd, 0x9e, 0x5e, 0x92, 0x16, 0x42, 0x2b, 0x75, 0xc3, 0x75, 0x36, 0x03, + 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa6, 0x7a, 0x16, 0x23, 0x3c, 0x41, 0xab, 0x31, 0x9b, 0xd0, 0x65, 0xae, 0x53, 0xd5, + 0xe7, 0x89, 0x0d, 0xdc, 0xcb, 0x6c, 0x24, 0xb8, 0x93, 0x0e, 0x9e, 0x1a, 0xfe, 0xf2, 0xbd, 0x31, 0x07, 0x29, 0x32, + 0x93, 0x3c, 0x35, 0x09, 0x98, 0x27, 0x59, 0x2e, 0x15, 0xb3, 0xcd, 0xf4, 0xac, 0x6d, 0x39, 0x84, 0x24, 0x8f, 0x74, + 0xc1, 0x8d, 0x15, 0x65, 0x94, 0xce, 0x88, 0xea, 0xab, 0x93, 0x4e, 0x3a, 0xc5, 0x3c, 0x01, 0x4e, 0xef, 0xad, 0x8c, + 0x59, 0xa3, 0xbc, 0x15, 0x9d, 0xa3, 0xe3, 0x19, 0x16, 0xd5, 0x25, 0xea, 0x1c, 0x1d, 0x4f, 0x11, 0x9e, 0x37, 0xc8, + 0x4c, 0x81, 0xc7, 0x30, 0x17, 0xff, 0x47, 0xca, 0x7f, 0x75, 0xd8, 0x10, 0x62, 0xfa, 0x0d, 0xec, 0x14, 0x36, 0x8e, + 0xd2, 0x9c, 0x80, 0xd7, 0x62, 0xfb, 0x1c, 0x67, 0x64, 0xda, 0xcc, 0x7d, 0xc0, 0x3d, 0xd3, 0x4a, 0xe3, 0x56, 0xa3, + 0xe3, 0x0c, 0x8f, 0xb7, 0x93, 0x62, 0x33, 0xd7, 0x66, 0x9e, 0x66, 0x70, 0xbe, 0x57, 0xa3, 0x70, 0xe5, 0x97, 0xdb, + 0x49, 0x61, 0x79, 0x07, 0xdc, 0xe6, 0x18, 0x8b, 0x26, 0xc5, 0x39, 0x9e, 0x37, 0x5f, 0xe2, 0x79, 0xf3, 0x5d, 0x99, + 0xd1, 0x58, 0x62, 0x01, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xab, 0xe4, 0x31, 0x16, 0x0d, 0x53, 0x1e, 0xcf, 0x1b, 0x55, + 0xe9, 0xe6, 0x12, 0x8b, 0x86, 0x29, 0xdd, 0x78, 0x87, 0xe7, 0x8d, 0x97, 0xff, 0x62, 0xd2, 0x51, 0x0a, 0xe8, 0xb2, + 0x40, 0xab, 0xcc, 0x0e, 0xf1, 0xfa, 0xd7, 0x37, 0x6f, 0xdb, 0x1f, 0x3b, 0xc7, 0x53, 0xec, 0xd7, 0x2f, 0x33, 0x38, + 0x96, 0xe9, 0x98, 0x35, 0x01, 0xa2, 0x19, 0xee, 0x1c, 0xcf, 0x70, 0xe7, 0x38, 0x73, 0x4d, 0x6d, 0xe6, 0x0d, 0x72, + 0xab, 0x43, 0x28, 0xea, 0x28, 0x0d, 0xe1, 0xe3, 0x27, 0x9b, 0x4e, 0x51, 0x0d, 0x94, 0xe8, 0x78, 0x5a, 0x03, 0x15, + 0x7c, 0x2f, 0x6b, 0xdf, 0x55, 0xbd, 0x0a, 0x83, 0x2c, 0x94, 0x50, 0xb8, 0xe6, 0x06, 0x3c, 0xb5, 0x14, 0x03, 0x99, + 0x30, 0xc5, 0x02, 0xe5, 0x1b, 0xa0, 0x30, 0xca, 0x13, 0x33, 0xf4, 0x60, 0x3a, 0x26, 0xf1, 0xff, 0xe7, 0xc9, 0x94, + 0x43, 0x2f, 0xb7, 0xcc, 0xce, 0xf4, 0xdc, 0x64, 0xc2, 0xe1, 0x03, 0x8f, 0xf5, 0x7f, 0xed, 0x40, 0xb1, 0x01, 0x29, + 0xfe, 0xbf, 0x74, 0x74, 0x21, 0x18, 0x21, 0x2b, 0x4a, 0x0b, 0x87, 0xf8, 0xdf, 0x1e, 0x56, 0xd0, 0x7d, 0xb1, 0xd3, + 0x7d, 0x61, 0xba, 0x0f, 0x9b, 0x36, 0xaa, 0x9c, 0xb4, 0xaa, 0x64, 0xc9, 0x7f, 0x9d, 0x6e, 0xed, 0x80, 0x46, 0xd4, + 0xe8, 0xd9, 0x34, 0x6c, 0xf0, 0xb0, 0x9d, 0xee, 0x41, 0xe6, 0x0d, 0xb7, 0x2f, 0xa4, 0xc2, 0xe1, 0x1b, 0xdc, 0xa9, + 0x5e, 0xb5, 0xc0, 0x7b, 0x53, 0x19, 0x7d, 0x65, 0x1c, 0x5a, 0x0e, 0xd2, 0x6d, 0x53, 0x6e, 0x63, 0x2c, 0x9d, 0x74, + 0xb1, 0x71, 0x45, 0x84, 0x4a, 0xb7, 0x57, 0xa0, 0x14, 0x9f, 0xe8, 0x26, 0x33, 0x5f, 0x97, 0x3a, 0x31, 0x97, 0x50, + 0x0d, 0xf3, 0x79, 0x77, 0xa5, 0x13, 0x2d, 0x17, 0x36, 0xef, 0xee, 0x12, 0xfa, 0x04, 0x0d, 0x6b, 0x23, 0xb0, 0xdb, + 0xe7, 0xce, 0x0e, 0x32, 0x38, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, + 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x11, 0xf2, 0x14, 0xa2, 0xb0, 0xfa, 0xf1, 0x3d, 0xec, 0xc6, + 0x4d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, + 0x13, 0x97, 0x3f, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, + 0x2e, 0x58, 0x44, 0x69, 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0xa1, 0x5f, 0x96, + 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9a, 0xc6, 0xe7, 0x80, 0x6b, 0xfa, 0x57, 0x93, + 0x48, 0x46, 0xec, 0x1f, 0xce, 0x8a, 0xc7, 0xcb, 0xc2, 0x60, 0x9a, 0xe8, 0xeb, 0x24, 0x5b, 0xb4, 0xc1, 0x54, 0x2f, + 0x5b, 0x74, 0x6e, 0xb1, 0xfb, 0xbe, 0xb3, 0xdf, 0x77, 0x58, 0xf4, 0x99, 0xc9, 0x48, 0x99, 0x29, 0xe6, 0xbf, 0xef, + 0xec, 0xf7, 0x1d, 0xde, 0x1d, 0xcc, 0xb5, 0xbf, 0x50, 0x2c, 0xd9, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x6a, + 0x59, 0x26, 0x08, 0x6c, 0x2d, 0x01, 0xe2, 0x7c, 0xbe, 0x88, 0x2b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xab, + 0x54, 0xe0, 0x31, 0x41, 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd4, 0x93, 0x24, 0xc0, + 0xab, 0x1a, 0x95, 0xb7, 0x29, 0x52, 0x7e, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x44, 0x15, 0x03, 0x58, 0x95, 0x25, 0x7d, + 0x02, 0xa9, 0xe7, 0x07, 0x13, 0xfd, 0x65, 0x1b, 0x79, 0xec, 0x3b, 0xbf, 0x9f, 0x99, 0x9e, 0x15, 0x72, 0x39, 0x9d, + 0x81, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, + 0x33, 0xbd, 0xa4, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xfa, 0x48, 0xde, 0xfe, 0x0c, 0xd8, 0x4d, 0x89, 0x6e, 0xec, 0xc9, + 0x7b, 0x03, 0x3b, 0x00, 0x67, 0x84, 0xed, 0xab, 0xf8, 0x50, 0x81, 0xce, 0x1f, 0xe7, 0x84, 0xed, 0xab, 0xfa, 0x84, + 0xd9, 0xec, 0x19, 0xd9, 0x1a, 0x6e, 0x3f, 0xce, 0x1a, 0x39, 0x3a, 0xe9, 0xa4, 0x79, 0xcf, 0x13, 0x03, 0x0b, 0xd0, + 0x00, 0xb8, 0x3b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0xa0, 0x77, 0xc9, 0xa4, 0xbd, 0x2e, 0x37, 0x29, 0xeb, 0x75, 0xa7, + 0xa2, 0x82, 0x05, 0x9e, 0x05, 0x7b, 0x81, 0xda, 0xaf, 0x3d, 0x14, 0xe7, 0x71, 0xb6, 0x6d, 0x7a, 0x5e, 0xf6, 0xdd, + 0xdb, 0xb3, 0xc8, 0xd8, 0xa6, 0xbd, 0xd9, 0x43, 0x24, 0x2c, 0x27, 0xac, 0x03, 0x4e, 0xb8, 0xaa, 0x1d, 0x10, 0xa0, + 0x8f, 0x81, 0xc8, 0x8d, 0x25, 0x59, 0x6d, 0x2a, 0xa3, 0xfb, 0xc0, 0xef, 0x96, 0x12, 0xe9, 0x46, 0x5b, 0x12, 0x4c, + 0x9f, 0x60, 0xd4, 0x74, 0xe6, 0x69, 0xea, 0xda, 0xab, 0xcb, 0xdb, 0xa2, 0xad, 0x7f, 0x03, 0x1a, 0x9b, 0xed, 0x61, + 0x62, 0x28, 0x83, 0x18, 0xe8, 0x7d, 0xc4, 0x7b, 0x8d, 0x46, 0x86, 0x40, 0x21, 0x93, 0x0d, 0xb1, 0x4c, 0xbc, 0x16, + 0xfd, 0xe8, 0xc8, 0xc0, 0xa3, 0x4a, 0x40, 0x98, 0x82, 0x10, 0x12, 0x76, 0x6d, 0x10, 0x36, 0x5c, 0xae, 0x5a, 0x2e, + 0x6c, 0xa4, 0xda, 0xd0, 0xc1, 0xff, 0x2b, 0x5c, 0xb6, 0x7a, 0x66, 0xb9, 0x28, 0x06, 0x37, 0x73, 0x03, 0x16, 0x09, + 0xd2, 0xa3, 0xcd, 0xf6, 0x50, 0xdc, 0x9f, 0x8b, 0xcd, 0x86, 0x80, 0xc4, 0x1c, 0x26, 0x28, 0x1a, 0xce, 0x8d, 0x31, + 0x56, 0x49, 0xa5, 0x65, 0xad, 0x49, 0xcc, 0x41, 0xc0, 0xe8, 0x70, 0xdd, 0x57, 0xb7, 0x29, 0xc3, 0x77, 0xa9, 0xc0, + 0x37, 0xe0, 0x49, 0x93, 0x4a, 0xec, 0x1e, 0x2f, 0x28, 0x36, 0x44, 0xf7, 0x3c, 0x7b, 0x5b, 0xc0, 0x3a, 0x9b, 0x3d, + 0x22, 0x82, 0xdf, 0xd5, 0xaf, 0x36, 0xf8, 0x6e, 0xe1, 0x97, 0x60, 0xfd, 0x1c, 0x9c, 0xa4, 0x58, 0x34, 0x64, 0xb3, + 0x70, 0x47, 0x06, 0x94, 0xab, 0xf8, 0xe5, 0x30, 0x75, 0xa7, 0x18, 0xae, 0x7d, 0xbc, 0xc4, 0xef, 0xb6, 0xda, 0x6d, + 0xa8, 0xb2, 0xb8, 0xdd, 0x9b, 0xa2, 0x21, 0xab, 0xa6, 0xf7, 0x64, 0x6e, 0xa5, 0xd4, 0xbf, 0xde, 0xe1, 0xd6, 0x4e, + 0xfb, 0x7e, 0x9a, 0x6f, 0x3c, 0x3a, 0x57, 0x4d, 0xfb, 0xd4, 0x5a, 0x11, 0x1c, 0xfc, 0x6c, 0xe1, 0xe6, 0xce, 0x80, + 0x03, 0xf8, 0xf9, 0x3b, 0x9a, 0x57, 0x19, 0x44, 0xa7, 0xb7, 0x9a, 0xf1, 0x75, 0xfc, 0xe7, 0xb8, 0x11, 0xf7, 0xd3, + 0x3f, 0x93, 0x3f, 0xc7, 0x0d, 0xd4, 0x47, 0xf1, 0xe2, 0x76, 0xcd, 0xe6, 0x6b, 0x08, 0xb6, 0x76, 0xef, 0x04, 0xbf, + 0x0e, 0x4b, 0x72, 0x4d, 0x73, 0x9e, 0xad, 0xdd, 0x83, 0x80, 0x6b, 0xf7, 0x2a, 0xd1, 0xda, 0xbc, 0x71, 0xb5, 0x8e, + 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, 0x3d, 0xaa, + 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, 0xf5, 0x3d, + 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, 0x96, 0x34, + 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, 0xf2, 0x5d, + 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, 0x06, 0x5f, + 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, 0x87, 0xae, + 0xf2, 0xf0, 0x1e, 0x32, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, 0x61, 0x3e, + 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, 0x64, 0x85, + 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, 0x0c, 0xcb, + 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, 0xba, 0x8d, + 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, 0xf5, 0xd8, + 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, 0x64, 0x62, + 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, 0xee, 0xdc, + 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, 0x2d, 0x76, + 0xae, 0xde, 0xbd, 0xf0, 0x75, 0xbe, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, 0xce, 0xf4, + 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xec, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, 0x0c, 0x94, + 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, 0x20, 0x07, + 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, 0xdf, 0x83, + 0xbb, 0xb3, 0x7b, 0x1d, 0xb2, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, 0x39, 0xbc, + 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, 0x5a, 0xcc, + 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, 0x4b, 0xe9, + 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, + 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, 0xa5, 0xe6, + 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, + 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, 0xb0, 0xea, + 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0x81, 0xd1, + 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, 0x71, 0xac, + 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, 0x36, 0x32, + 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, 0xdb, 0x3c, + 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, 0x92, 0x41, + 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, 0x8b, 0x9a, + 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, 0x06, 0xf6, + 0xe9, 0xca, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, 0x2a, 0xe9, + 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, 0x08, 0xfc, + 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, 0x1e, 0x50, + 0x0c, 0xef, 0xae, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, 0x8b, 0x0b, + 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, 0xbf, 0x93, + 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, 0xa2, 0x30, + 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x5a, 0x3b, 0x65, 0x3a, 0x88, 0x0a, 0xf2, + 0xa4, 0x7c, 0x96, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, 0xc8, 0x34, + 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, 0x10, 0x8a, + 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, 0xeb, 0x85, + 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, 0xea, 0x83, + 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, 0x7f, 0xd2, + 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, 0xa9, 0xc6, + 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, 0x81, 0x55, + 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, 0x84, 0x72, + 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, 0xd8, 0xc2, + 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, 0x6f, 0x32, + 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x3c, 0xb0, 0xea, 0x7b, 0x84, 0x98, + 0x99, 0xf8, 0x4f, 0xf0, 0x2c, 0xf4, 0xb7, 0x9f, 0xa3, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, 0xec, 0x3f, + 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0xd6, 0xa1, + 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x94, + 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, + 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, 0x61, 0xdb, + 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0x28, + 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, 0x70, 0x19, + 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, 0x00, 0x05, + 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0x4f, 0xf2, 0xd6, 0x5e, 0xd0, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, 0xdb, 0x45, + 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, 0x95, 0x9b, + 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, 0x35, 0x90, + 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, 0x10, 0xf2, + 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, 0xc1, 0xe4, + 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, 0x6c, 0x2a, + 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, 0x4a, 0x55, + 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, 0xb2, 0xe5, + 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0x2c, 0x6c, 0xc2, 0xed, 0x30, 0xcd, 0x32, 0x6d, + 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, 0xdf, 0x06, + 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, 0x62, 0x37, + 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, + 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, + 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, 0x03, 0x6a, + 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, 0x2f, 0x43, + 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, 0x33, 0xd4, + 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, + 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, 0xd5, 0x9e, + 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xab, 0x8d, + 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, 0xc8, 0xc1, + 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, + 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, + 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, 0xd8, 0xe5, + 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, 0xc8, 0x81, + 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xeb, + 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, + 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, + 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, 0x6a, 0x8b, + 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, + 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0xaa, + 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, 0x70, 0x23, + 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, 0xfc, 0x4e, + 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, 0x7a, 0x5f, + 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, 0x03, 0x44, + 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, 0xc8, 0x6e, + 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, 0x4c, 0xd9, + 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, 0x2e, 0x40, + 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, 0xb8, 0x30, + 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, 0x5e, 0x66, + 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, 0xad, 0xcd, + 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, 0x47, 0xf7, + 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, 0x1e, 0x6c, + 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, 0x45, 0x19, + 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, + 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, + 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0xe5, 0xce, + 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, 0x9c, 0xe3, + 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, 0xe4, 0xb6, + 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, 0xa6, 0x82, + 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, 0xef, 0x3d, + 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, 0x5a, 0xbd, + 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, 0x75, 0x0e, + 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, 0x84, 0x56, + 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, 0xce, 0x86, + 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, 0x8b, 0x5e, + 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, 0xcd, 0xb8, + 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, 0x29, 0x84, + 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, 0x24, 0xf3, + 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, 0xc2, 0x18, + 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, 0x02, 0xff, + 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x06, + 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, 0xf0, 0x93, + 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, + 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, + 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, 0xc0, 0x3b, + 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, 0xae, 0x9f, + 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, + 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, + 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, 0x87, 0x80, + 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, 0x3a, 0x3a, + 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, 0x93, 0x0f, + 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, 0x5a, 0x05, + 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, 0xcd, 0x84, + 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, 0xed, 0xbd, + 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, 0x1f, 0x1f, + 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, 0xf6, 0xca, + 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, 0x67, 0xe4, + 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, 0x9c, 0x7c, + 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, 0x76, 0x17, + 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, 0xbb, 0x81, + 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, 0x25, 0xcb, + 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, 0xf8, 0xcf, + 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, 0x86, 0xa6, + 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, 0x1a, 0x43, + 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, 0x77, 0x21, + 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, 0xd8, 0xfb, + 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, 0x82, 0xc4, + 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, 0x7c, 0x75, + 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, 0xac, 0xaa, + 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, 0xe5, 0xe1, + 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, 0x11, 0xc6, + 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, 0xdd, 0x75, + 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, 0x35, 0x97, + 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, 0xa0, 0x51, + 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, 0xb1, 0x7c, + 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, 0x72, 0xbc, + 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, 0x5d, 0x52, + 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0xff, 0xb2, 0xf7, 0xae, 0xcb, 0x6d, + 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, 0xa8, 0x32, + 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, 0xe0, 0x06, + 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, 0xfd, 0x3a, + 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0x2f, 0xe2, 0x05, 0xad, 0x77, 0x15, 0x0a, 0x8f, + 0xaa, 0x28, 0xe5, 0x56, 0x72, 0x9d, 0x41, 0x10, 0x3b, 0x7a, 0x61, 0xf8, 0x13, 0x08, 0x21, 0x88, 0x30, 0xe1, 0xb7, + 0x61, 0x46, 0xdb, 0x59, 0xa4, 0x93, 0x7e, 0x1f, 0x66, 0xb8, 0x81, 0x95, 0xfc, 0x5c, 0xf5, 0xd9, 0x7e, 0x1b, 0x84, + 0x6c, 0x17, 0x44, 0xec, 0xa6, 0xd8, 0x06, 0xa5, 0x75, 0x24, 0x7e, 0x54, 0x86, 0xbf, 0xa5, 0xd7, 0xcb, 0x43, 0x88, + 0xf7, 0xe9, 0xa5, 0xf9, 0x59, 0xda, 0x8a, 0x02, 0xdc, 0x47, 0xe8, 0x51, 0x1d, 0x08, 0x76, 0xc2, 0x13, 0x1e, 0xc0, + 0xc9, 0x6a, 0x56, 0xf1, 0xf7, 0x29, 0x88, 0x13, 0x05, 0x87, 0x80, 0xab, 0xed, 0xc7, 0xf4, 0x2b, 0x18, 0xbe, 0x74, + 0xb0, 0xe5, 0xf0, 0xa6, 0xd8, 0xf6, 0x58, 0xc9, 0xdf, 0x01, 0xfb, 0x56, 0x4f, 0xc6, 0xea, 0xf6, 0xc0, 0x59, 0x97, + 0x52, 0x74, 0xbc, 0x29, 0x0e, 0x6f, 0xcf, 0x67, 0xfb, 0x6d, 0x10, 0xb1, 0x5d, 0x90, 0x61, 0xad, 0x93, 0x86, 0xe3, + 0x60, 0x08, 0x9f, 0xc5, 0x08, 0xfb, 0xbf, 0xac, 0x07, 0x5e, 0x42, 0x6a, 0x28, 0x70, 0x31, 0xd8, 0x70, 0xb4, 0xb6, + 0xcb, 0x34, 0x70, 0x53, 0x83, 0x5e, 0xdf, 0x53, 0x88, 0xf2, 0x92, 0xd1, 0xdc, 0x08, 0xd6, 0x8d, 0x21, 0x17, 0x87, + 0xe3, 0x66, 0x39, 0xe4, 0x25, 0x4d, 0xa7, 0x41, 0x28, 0xdd, 0x59, 0xd6, 0x90, 0x44, 0xd9, 0x07, 0xa1, 0x76, 0x6d, + 0xd9, 0x6f, 0x03, 0xdb, 0x97, 0x3f, 0x1a, 0xc6, 0xfe, 0xc5, 0xf2, 0xb1, 0x90, 0x2e, 0xe2, 0x39, 0x08, 0xa2, 0xf6, + 0xf3, 0x6c, 0xb8, 0xf1, 0x2f, 0xd6, 0x8f, 0x85, 0xf2, 0x1b, 0xcf, 0x6d, 0x39, 0x24, 0xcd, 0x5a, 0xf8, 0xc2, 0x38, + 0x25, 0xb8, 0x32, 0xb4, 0x1d, 0x0e, 0x42, 0xff, 0x6d, 0xd6, 0x08, 0x6e, 0x6c, 0x68, 0x9f, 0x2f, 0x7c, 0xd8, 0xda, + 0x68, 0xac, 0x29, 0xa6, 0x5b, 0xe8, 0xdf, 0x64, 0xb6, 0xb4, 0xa7, 0x51, 0xc9, 0x8b, 0x53, 0xd3, 0x88, 0x85, 0x30, + 0x60, 0xe8, 0x27, 0xf3, 0x0e, 0x54, 0x73, 0xc7, 0x23, 0x90, 0xc9, 0x07, 0x7a, 0xb0, 0x26, 0xb5, 0xea, 0xaf, 0x61, + 0x26, 0xff, 0x8f, 0x54, 0x58, 0x8c, 0xee, 0xb6, 0x61, 0xa6, 0xfe, 0x88, 0xe4, 0x1f, 0x2c, 0xe7, 0xbb, 0xd4, 0x0b, + 0xb5, 0x1f, 0x0b, 0x2b, 0x30, 0x28, 0x51, 0x35, 0xa0, 0x07, 0x22, 0xa8, 0xca, 0x20, 0xcd, 0xb0, 0x3a, 0x07, 0xfd, + 0xee, 0x69, 0xd5, 0x91, 0x1c, 0xd2, 0x5a, 0x0d, 0xa9, 0x60, 0xaa, 0xd4, 0x20, 0x3f, 0x1c, 0x6e, 0x53, 0xa6, 0xcb, + 0x80, 0x4b, 0xfa, 0x6d, 0xaa, 0x94, 0xc2, 0x5f, 0x10, 0x80, 0xce, 0xc1, 0x3d, 0xbe, 0x1c, 0x03, 0x69, 0x86, 0x85, + 0xdf, 0x9a, 0x1d, 0x5f, 0x93, 0x70, 0x9b, 0x04, 0x17, 0x03, 0x9c, 0xa3, 0xab, 0xb0, 0xbc, 0x4d, 0x21, 0x82, 0xaa, + 0x84, 0xfa, 0x56, 0xa6, 0x41, 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, + 0x11, 0xd7, 0x33, 0xc2, 0x9a, 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, + 0x8d, 0xab, 0x4a, 0x55, 0x77, 0x73, 0x6a, 0x29, 0x2d, 0xdb, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, + 0xe4, 0x08, 0x26, 0x90, 0x24, 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, + 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0x7f, 0x11, 0x46, + 0x9a, 0xcc, 0x58, 0xc9, 0x22, 0xdb, 0xd5, 0x29, 0x71, 0x1e, 0x27, 0xb0, 0x3d, 0x9a, 0xde, 0xf2, 0x7d, 0x06, 0x51, + 0x41, 0xa0, 0x60, 0xc6, 0x7c, 0xd9, 0xc5, 0x13, 0xdf, 0x67, 0x96, 0xa9, 0xfb, 0x70, 0x30, 0x66, 0x6c, 0xbf, 0xdf, + 0xcf, 0xfb, 0x7d, 0x35, 0xdf, 0xfa, 0xfd, 0xe4, 0xa9, 0xf9, 0xdb, 0x03, 0x06, 0x05, 0x39, 0x11, 0x4d, 0x85, 0x08, + 0xfe, 0x21, 0x79, 0x8c, 0x64, 0x74, 0xc7, 0x7d, 0x6e, 0x79, 0x7e, 0x56, 0x47, 0x20, 0x98, 0x87, 0xc3, 0xa5, 0x02, + 0xbb, 0x96, 0x28, 0x12, 0xb2, 0xfc, 0xc7, 0x60, 0x3c, 0x73, 0x1f, 0x60, 0xc9, 0x00, 0x84, 0xad, 0xf2, 0x74, 0xbd, + 0xe7, 0xab, 0xe0, 0x9d, 0x8e, 0x77, 0x8d, 0x15, 0x19, 0x88, 0x5b, 0x60, 0x23, 0xd6, 0xda, 0x03, 0x72, 0xa6, 0x00, + 0xc7, 0x8b, 0xc3, 0xe1, 0x5c, 0xfe, 0xd2, 0xcd, 0xd6, 0x09, 0x54, 0x0a, 0xdc, 0x1e, 0x9d, 0x1c, 0xfc, 0x0f, 0xa0, + 0x19, 0x94, 0xc3, 0xbc, 0xde, 0xfe, 0xc1, 0x9c, 0xfc, 0xf4, 0x14, 0xff, 0x84, 0x87, 0xe8, 0xf4, 0xdb, 0xbd, 0xf9, + 0x83, 0xa2, 0xf2, 0x70, 0x50, 0x8b, 0xff, 0x9c, 0xf3, 0x0a, 0x7e, 0xe1, 0x9b, 0xc0, 0x6c, 0x32, 0xf5, 0x4e, 0xbe, + 0xc9, 0x73, 0xa6, 0x5e, 0xe3, 0x15, 0x93, 0xef, 0x70, 0x38, 0x17, 0xa3, 0x7a, 0x3b, 0x72, 0xa2, 0x9d, 0x72, 0x8c, + 0x83, 0xc1, 0x7f, 0x11, 0x6d, 0x13, 0x02, 0x0c, 0xe5, 0x12, 0xcd, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, + 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, + 0x88, 0x53, 0x9c, 0x80, 0x08, 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x04, 0xc1, 0x90, 0xaf, 0x25, 0xe0, + 0xae, 0xd7, 0xab, 0x31, 0xbe, 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, + 0x81, 0x67, 0xcb, 0xde, 0x44, 0xb9, 0xdb, 0xf0, 0xb4, 0x1f, 0x5b, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, + 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, + 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0x67, 0xd6, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0xc7, 0x0a, 0x1f, + 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x22, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, + 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, + 0xd3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0x0b, 0x3b, 0xb7, 0x63, 0xd7, 0xc5, 0x0f, 0xe2, 0x6d, 0x6d, 0x47, 0x7f, + 0xec, 0x20, 0xd2, 0x71, 0x4f, 0x2e, 0xd4, 0x97, 0x90, 0x4a, 0x2e, 0xd4, 0x0d, 0xc4, 0x2e, 0xd4, 0x78, 0xc7, 0x45, + 0xac, 0xf5, 0x37, 0x35, 0x0a, 0x56, 0x02, 0xce, 0xb4, 0x37, 0x60, 0xb0, 0x81, 0x75, 0xcb, 0x32, 0xf8, 0x1b, 0xae, + 0x69, 0x02, 0x37, 0x2c, 0xb2, 0xde, 0x1b, 0x6c, 0xa5, 0x37, 0xe0, 0x68, 0x99, 0x38, 0x97, 0x92, 0xa4, 0x6c, 0x91, + 0x71, 0xf5, 0x28, 0xa4, 0x6a, 0xba, 0xbf, 0x11, 0xf5, 0xbd, 0x10, 0x79, 0xb0, 0x4a, 0x59, 0x54, 0xac, 0x40, 0x66, + 0x0f, 0xfe, 0x1e, 0x32, 0x72, 0x94, 0x03, 0x47, 0xa1, 0x7f, 0x36, 0x81, 0xce, 0x23, 0x22, 0x9d, 0x47, 0x82, 0xad, + 0xd4, 0x43, 0x61, 0xe5, 0x05, 0x44, 0x07, 0xab, 0x23, 0xde, 0x54, 0x9e, 0x84, 0x8a, 0x4d, 0x99, 0xc8, 0xe3, 0xa0, + 0x96, 0x80, 0xb1, 0x82, 0x60, 0xce, 0x72, 0xe9, 0x82, 0x54, 0x35, 0x7a, 0x58, 0x64, 0xee, 0x1f, 0x04, 0xe5, 0xff, + 0x41, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x7f, 0x00, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x8c, 0x2e, 0x99, 0xb3, + 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, 0xc1, 0x74, 0x7b, 0x4a, 0xab, + 0xee, 0x61, 0xc3, 0x93, 0xd2, 0x43, 0xa5, 0xbe, 0x8d, 0x09, 0x2c, 0xab, 0x94, 0xe1, 0xdb, 0x09, 0x55, 0x27, 0x06, + 0x15, 0xeb, 0x86, 0x2d, 0xe1, 0x10, 0x8b, 0x49, 0x63, 0x9d, 0x0d, 0x78, 0xc4, 0x12, 0xf8, 0x67, 0xc3, 0xc7, 0x6c, + 0xc9, 0xa3, 0xc9, 0xe6, 0x6a, 0xd9, 0xef, 0x97, 0x5e, 0xe8, 0xd5, 0xb3, 0xec, 0x87, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, + 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x07, 0x78, 0xed, 0x07, 0x1e, + 0xa9, 0x25, 0x95, 0x5c, 0x65, 0xb0, 0xbf, 0x0f, 0x78, 0xe4, 0xb3, 0xce, 0x4f, 0xcb, 0xa6, 0x4b, 0xf7, 0x33, 0xab, + 0x03, 0x22, 0xdd, 0x01, 0x36, 0xde, 0x36, 0xe8, 0xc8, 0xbf, 0xdd, 0x21, 0xa5, 0x6e, 0x32, 0x00, 0xbb, 0xd1, 0x00, + 0x87, 0x4c, 0xf5, 0x52, 0x64, 0xf5, 0x52, 0xa6, 0x7a, 0x49, 0x56, 0x2e, 0xc1, 0x42, 0x62, 0xaa, 0xdc, 0x46, 0x56, + 0x6e, 0xd9, 0x70, 0x3d, 0x1c, 0x6c, 0xad, 0xb8, 0x6c, 0x6e, 0xe1, 0xbe, 0xb0, 0xa2, 0xc0, 0xff, 0x1b, 0xb6, 0x60, + 0x77, 0xf2, 0x18, 0xb8, 0x46, 0xc7, 0xa4, 0xc8, 0xab, 0xd8, 0x1d, 0xbb, 0x01, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, + 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, 0x8d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x6e, + 0x0f, 0x87, 0x6b, 0xcf, 0x67, 0xf7, 0xf8, 0xe3, 0xfc, 0xf6, 0x70, 0xd8, 0x79, 0x46, 0xbd, 0xf7, 0x86, 0x27, 0xec, + 0x11, 0x4f, 0x26, 0x6f, 0xae, 0x78, 0x3c, 0x19, 0x0c, 0xde, 0xf8, 0x0b, 0x5e, 0xcf, 0xde, 0x80, 0x76, 0xe0, 0x7c, + 0x21, 0x75, 0xcd, 0xde, 0x0d, 0xcf, 0xbc, 0x05, 0x8e, 0xcd, 0x0d, 0x1c, 0xbd, 0xfd, 0xbe, 0x77, 0xcb, 0x23, 0xef, + 0x86, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0x37, 0xc1, + 0x23, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x1b, 0xd5, + 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x88, 0xbf, 0x61, 0x77, 0xdc, 0xb0, 0xcd, + 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x50, 0xea, 0xda, 0x82, 0x64, 0x6e, 0x5d, 0xf9, 0x10, 0x38, 0x1c, 0x90, + 0x9f, 0x6e, 0x11, 0x07, 0xa1, 0x75, 0x93, 0xd5, 0x5c, 0x51, 0xce, 0x85, 0x36, 0xca, 0xbc, 0x1c, 0x58, 0xcc, 0x52, + 0x0a, 0x8d, 0x05, 0x00, 0x82, 0x49, 0xa1, 0xb5, 0xf7, 0x32, 0x80, 0x9c, 0xa0, 0xe1, 0x8f, 0xcd, 0x55, 0x49, 0xd6, + 0xb2, 0x25, 0x21, 0xca, 0x76, 0x3d, 0xbc, 0x44, 0xc8, 0xb4, 0x7e, 0xff, 0x9c, 0x48, 0xd6, 0x26, 0xd5, 0x55, 0x8d, + 0x96, 0x80, 0x8a, 0x2c, 0x01, 0x13, 0xbf, 0xd2, 0x7c, 0x02, 0xf0, 0xa4, 0xe3, 0x41, 0xf5, 0x03, 0xaf, 0x99, 0x20, + 0xb2, 0x8d, 0xca, 0x9f, 0x14, 0x4f, 0x91, 0x8c, 0xa0, 0xf8, 0xa1, 0x56, 0x19, 0x0b, 0xc3, 0x3c, 0x50, 0x40, 0xde, + 0xbd, 0x3b, 0xf5, 0x2d, 0xda, 0x9a, 0x8e, 0x3d, 0x5b, 0xab, 0x50, 0x0b, 0x35, 0x85, 0x4b, 0x0e, 0xd1, 0x15, 0x68, + 0xa0, 0x88, 0x64, 0x3c, 0x79, 0x3d, 0xb8, 0x9c, 0x44, 0x57, 0x5c, 0xa0, 0x33, 0xbe, 0xbe, 0xe9, 0xa6, 0xb3, 0xe8, + 0x87, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, 0xf0, 0xf5, + 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0xfe, 0x81, 0x2a, 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x87, 0x4a, 0xee, 0x7b, 0x40, 0x5a, + 0xcb, 0x4b, 0x2e, 0xdf, 0x8f, 0x10, 0x63, 0xc4, 0x0f, 0xbc, 0x92, 0x47, 0x2c, 0x54, 0x53, 0xb8, 0xe6, 0x11, 0x82, + 0xbc, 0x65, 0x3a, 0xf8, 0x5b, 0x4f, 0x9c, 0xee, 0x4f, 0x94, 0x76, 0xf1, 0x85, 0xc5, 0xb4, 0x72, 0xa4, 0x1b, 0x90, + 0x83, 0x0d, 0xd3, 0x45, 0x41, 0xb6, 0x29, 0x8d, 0xa0, 0x8d, 0x96, 0x03, 0x1b, 0x4e, 0xa5, 0x36, 0x9c, 0xb9, 0x86, + 0xe0, 0x3e, 0x3f, 0x4f, 0x47, 0x0b, 0xf8, 0x90, 0xea, 0xf6, 0x12, 0x3f, 0x0f, 0x1b, 0x2d, 0x90, 0xd9, 0x11, 0x9f, + 0xd9, 0x44, 0xd2, 0x49, 0x9d, 0x2b, 0x60, 0xb7, 0xb3, 0x6b, 0x90, 0x23, 0x66, 0xee, 0x2b, 0x54, 0xdf, 0xa2, 0x01, + 0x57, 0xc6, 0xda, 0xd7, 0x24, 0x63, 0xe1, 0x55, 0x39, 0x0d, 0x07, 0x00, 0x43, 0x97, 0xd1, 0xd7, 0x96, 0x9b, 0x2c, + 0x7b, 0x5d, 0x40, 0x10, 0x44, 0x49, 0x3c, 0x3e, 0xe0, 0x7d, 0x59, 0x0d, 0x35, 0x4a, 0x3e, 0x96, 0x1d, 0xc3, 0xd7, + 0x4b, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, 0x1f, 0x19, 0xcf, + 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x60, 0x69, 0xe6, 0x8b, 0x85, 0xbf, 0xd8, 0x39, 0x89, 0x88, 0x82, 0xc0, 0x8e, 0x84, + 0x07, 0x91, 0xfa, 0x51, 0xe5, 0xe9, 0x4e, 0xf5, 0xd9, 0x7e, 0x61, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, + 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, + 0x9d, 0xc6, 0x36, 0x3c, 0x36, 0x62, 0xd9, 0xd2, 0x5b, 0xb3, 0x5b, 0xb6, 0x62, 0x37, 0xaa, 0x4e, 0x0b, 0x1e, 0x4e, + 0x87, 0x97, 0x01, 0xae, 0xbe, 0xf5, 0x39, 0xe7, 0xb7, 0x74, 0x82, 0xad, 0x07, 0x3c, 0x9a, 0x88, 0xd9, 0xfa, 0x87, + 0x48, 0x2d, 0x9e, 0xf5, 0x90, 0x2f, 0x68, 0xfd, 0x89, 0xd9, 0xad, 0x49, 0xbe, 0x1d, 0xf0, 0xc5, 0x64, 0xfd, 0x43, + 0x04, 0xaf, 0xfe, 0x00, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0x1f, 0x22, 0x1c, 0xb3, 0xdb, 0x1f, 0x22, 0x1a, 0xb5, + 0x95, 0xdc, 0x97, 0x6e, 0x1a, 0x10, 0x56, 0x6e, 0x58, 0x0c, 0xaf, 0x81, 0x78, 0xa6, 0x8d, 0xa4, 0x6b, 0x69, 0xe8, + 0x8d, 0x79, 0x38, 0x8d, 0x83, 0x35, 0xb5, 0x42, 0x9e, 0x19, 0x62, 0x16, 0xff, 0x10, 0xcd, 0xd9, 0x0a, 0x2b, 0xb2, + 0xe1, 0xf1, 0xe0, 0x72, 0xb2, 0xb9, 0xe2, 0x6b, 0x20, 0x3f, 0x9b, 0x6c, 0xcc, 0x16, 0x75, 0xc3, 0xc5, 0x6c, 0xf3, + 0x43, 0x34, 0x9f, 0xac, 0xa0, 0x67, 0xed, 0x01, 0xf3, 0x5e, 0x82, 0x08, 0x25, 0x21, 0x35, 0xe5, 0xa6, 0xd7, 0x63, + 0xeb, 0x71, 0x70, 0xcb, 0xd6, 0x97, 0xc1, 0x0d, 0x5b, 0x8f, 0x81, 0x88, 0x83, 0xfa, 0xdd, 0xdb, 0xc0, 0xe2, 0x8b, + 0xd8, 0xfa, 0xd2, 0xa4, 0x6d, 0x7e, 0x88, 0x98, 0x3b, 0x38, 0x0d, 0x5c, 0xb0, 0xd6, 0x99, 0xb7, 0x62, 0x70, 0x09, + 0x59, 0x7a, 0x31, 0xdb, 0x0c, 0x2f, 0xd9, 0x7a, 0x84, 0x53, 0x3d, 0xf1, 0xd9, 0x2d, 0xbf, 0x61, 0x09, 0x5f, 0x35, + 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, 0x0a, 0x65, 0xb1, 0x30, 0x2a, 0xf7, 0x2d, 0x38, 0xa0, + 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0xeb, 0x70, 0xfd, 0x51, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, 0x60, 0xfa, + 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0xbf, 0x17, 0x69, 0xee, 0x16, 0xae, 0x53, + 0x98, 0x15, 0x05, 0xaa, 0x9f, 0x92, 0xd2, 0xc0, 0x42, 0x25, 0x32, 0x95, 0x82, 0x5f, 0xd6, 0x4e, 0xbb, 0xce, 0x8e, + 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, + 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, + 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xdd, 0x66, 0x0e, 0xd2, + 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0xb6, 0x86, 0x47, 0x55, 0xac, 0xdc, 0x9b, 0x3c, 0x47, + 0x38, 0xa3, 0x4b, 0x99, 0x00, 0xb8, 0xde, 0x2f, 0xc2, 0x5a, 0xe1, 0x15, 0x35, 0x8b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, + 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, + 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, 0x0b, 0x40, 0x4d, 0x3f, 0xd6, 0x62, 0x5d, 0x05, 0xa5, + 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, 0x26, 0x4a, 0xe4, 0xfc, 0x58, 0x94, 0x62, 0x59, 0x8a, + 0x2a, 0x69, 0x37, 0x14, 0x3c, 0x22, 0xdc, 0x06, 0x8d, 0x99, 0xdb, 0x13, 0x5d, 0xb4, 0x22, 0x94, 0x63, 0xb3, 0x8e, + 0x91, 0x46, 0x99, 0x9d, 0xec, 0x3a, 0x59, 0x68, 0xbf, 0xaf, 0x72, 0xc8, 0x3a, 0x60, 0x8d, 0xe4, 0xeb, 0x35, 0x87, + 0x6e, 0x1b, 0xe5, 0xc5, 0xbd, 0xe7, 0x2b, 0x38, 0xcd, 0xf1, 0xc4, 0xee, 0x7a, 0xdd, 0x29, 0x12, 0xf1, 0x0a, 0x27, + 0x55, 0x3e, 0x92, 0x85, 0xe3, 0xce, 0x9d, 0xd6, 0x62, 0x55, 0xb9, 0xac, 0xa7, 0x16, 0x47, 0x04, 0x3e, 0x95, 0x47, + 0x7b, 0xa1, 0x6d, 0x51, 0x2c, 0x84, 0xd1, 0xa3, 0x13, 0x7e, 0x52, 0x02, 0xeb, 0xeb, 0x70, 0x58, 0xfa, 0x11, 0x47, + 0xbf, 0xd3, 0x68, 0xb4, 0x20, 0xa4, 0xe1, 0xa9, 0x17, 0x8d, 0x16, 0x75, 0x51, 0x87, 0xd9, 0xd3, 0x5c, 0x0f, 0x14, + 0x86, 0x11, 0xa8, 0x1f, 0x5c, 0x65, 0xf0, 0x59, 0x84, 0xa8, 0x79, 0x60, 0x9a, 0x0d, 0xe1, 0xa8, 0x0b, 0x3c, 0xb4, + 0x82, 0x16, 0x33, 0xf3, 0x51, 0x88, 0xe1, 0x43, 0xba, 0x38, 0x7f, 0x42, 0x56, 0x3e, 0xc0, 0xee, 0xd0, 0x5d, 0x28, + 0xe7, 0x4c, 0xc5, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, 0x8c, 0x8e, + 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x96, 0xab, 0x09, 0x43, 0xe1, 0x13, 0x03, 0xdd, 0xfc, 0xc6, 0x6f, + 0xcf, 0x5b, 0x30, 0xb2, 0x4b, 0x52, 0xbc, 0xd6, 0x0c, 0xf7, 0x1b, 0x70, 0x3b, 0x02, 0xca, 0x9a, 0xea, 0x98, 0x64, + 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x7b, 0x59, 0x14, 0x38, 0x80, 0xab, 0x99, + 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0xf6, 0xaa, 0xea, 0x90, 0xac, 0x9a, 0x1f, 0xcc, 0xe6, + 0x4d, 0xc3, 0xc4, 0x88, 0x20, 0xba, 0x08, 0x27, 0x98, 0x5e, 0x91, 0xbe, 0x56, 0x72, 0x3a, 0x5a, 0x75, 0xb4, 0x96, + 0x98, 0x98, 0x2b, 0x8a, 0xbf, 0x06, 0x3c, 0x6e, 0xf0, 0xea, 0x24, 0x4d, 0x27, 0xaa, 0x47, 0x8f, 0x5f, 0xa7, 0xe9, + 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7e, 0x41, 0x11, 0x17, 0x35, 0xb8, 0xf2, 0x4e, + 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, 0x0e, 0x5c, + 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x44, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xcc, 0x59, 0x35, 0x5a, 0xa8, 0xcc, 0x08, 0xed, + 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xe3, 0x3d, 0xba, 0xab, 0xce, 0x32, 0x93, + 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xad, 0x0e, 0x90, 0x51, 0x7b, 0xed, 0x77, 0x9d, + 0xe5, 0xab, 0x9b, 0xad, 0xa1, 0xa8, 0xd4, 0x4a, 0x52, 0x1c, 0x64, 0xb8, 0x6e, 0x2b, 0x1f, 0x2e, 0x2e, 0xa0, 0x67, + 0x8c, 0x44, 0xe6, 0xf9, 0x13, 0xf9, 0x12, 0x9c, 0x33, 0xce, 0x0a, 0x81, 0x09, 0x63, 0xf5, 0xae, 0xb5, 0x54, 0x1a, + 0x52, 0x8c, 0x1d, 0x8d, 0xb2, 0xac, 0xb2, 0x74, 0x99, 0xad, 0x25, 0x6c, 0x59, 0x45, 0x6e, 0x61, 0xb7, 0x99, 0xac, + 0xe6, 0xbb, 0x8a, 0x3b, 0x28, 0xdf, 0x6c, 0x95, 0xf1, 0xbd, 0x44, 0xf6, 0x6e, 0x03, 0x25, 0x3c, 0x1d, 0xfd, 0x05, + 0xe9, 0xb7, 0x19, 0xc6, 0x29, 0xb7, 0x95, 0xb4, 0x00, 0xa7, 0x7f, 0x38, 0xbc, 0xab, 0x30, 0x68, 0x70, 0x84, 0x71, + 0x64, 0xfd, 0xfe, 0xa2, 0xf2, 0x6a, 0x4c, 0xd4, 0xf1, 0x59, 0xfd, 0x7e, 0x45, 0x0f, 0xa7, 0xd5, 0x68, 0x95, 0x6e, + 0x91, 0x9d, 0xd0, 0xc6, 0xca, 0x0f, 0x6a, 0x05, 0xcc, 0xde, 0xfa, 0x7c, 0x3a, 0x00, 0x1d, 0x0b, 0x90, 0x68, 0x36, + 0x13, 0x89, 0x39, 0xe9, 0x9e, 0x84, 0xc7, 0x07, 0x16, 0x38, 0xc0, 0x54, 0xfc, 0x5f, 0xc2, 0x9b, 0x81, 0x0d, 0x1a, + 0x25, 0xfa, 0x1a, 0x5d, 0xd5, 0xe6, 0x46, 0xc7, 0x4b, 0x4f, 0x21, 0x91, 0x15, 0xac, 0x9a, 0xfb, 0x72, 0x03, 0xa7, + 0x3d, 0xd4, 0x1c, 0x2a, 0x4b, 0xf0, 0xb7, 0x5f, 0xe6, 0x87, 0xc3, 0x2a, 0x83, 0xc2, 0x76, 0x6b, 0xa1, 0xbd, 0x31, + 0x4b, 0x35, 0x54, 0x84, 0x83, 0xce, 0x57, 0x62, 0x56, 0x8f, 0xe8, 0xef, 0xf9, 0xe1, 0xb0, 0x22, 0x30, 0xe0, 0xb0, + 0x94, 0x99, 0x68, 0xa1, 0x58, 0x5a, 0x67, 0x33, 0xaa, 0x03, 0x0f, 0x4c, 0xcc, 0x59, 0xb8, 0x03, 0xd0, 0x26, 0xb5, + 0x0a, 0xf4, 0x2a, 0xa2, 0x9f, 0xb8, 0x5f, 0xdb, 0xaf, 0xd7, 0x23, 0xb3, 0x74, 0xe4, 0xc6, 0x58, 0x00, 0x70, 0xe0, + 0x79, 0x4d, 0xf2, 0x9c, 0x7c, 0x0d, 0xed, 0x9e, 0x5c, 0xc8, 0x9f, 0xa0, 0x6c, 0xe1, 0xb9, 0x6a, 0x5a, 0x59, 0xac, + 0xb8, 0xaa, 0x5e, 0x5d, 0xf0, 0xca, 0x64, 0x5a, 0xa5, 0x95, 0xa8, 0x94, 0x60, 0x40, 0x5d, 0xe2, 0xb5, 0xa6, 0x19, + 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x7e, 0x69, 0x1c, 0x3e, 0xed, + 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0x2b, 0x1f, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, 0xc5, 0xc4, 0xee, + 0xd0, 0xbc, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, 0x01, 0x2f, 0x1e, + 0xea, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x2a, 0x26, 0xc0, 0x0f, 0x4a, + 0xad, 0xe9, 0xbd, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, 0xe7, 0xe3, 0xf9, + 0xa5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x79, 0xab, 0x7f, 0x98, 0xea, 0x5b, 0xe8, 0x4e, 0xd0, + 0x67, 0xe8, 0xaa, 0xea, 0xae, 0xc4, 0x16, 0x86, 0x7a, 0x62, 0x91, 0x17, 0xf2, 0xa4, 0x35, 0x76, 0x1c, 0xec, 0x0d, + 0x70, 0xe2, 0x97, 0x87, 0x83, 0xb8, 0xca, 0x7d, 0x76, 0xde, 0x35, 0xb2, 0x72, 0x00, 0x2b, 0x88, 0x82, 0x71, 0x6b, + 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xd5, 0xf8, 0xf8, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0xe4, 0x3f, 0x3c, 0x01, + 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7a, 0x39, 0x7d, 0x32, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, 0x31, 0x5f, 0x5d, + 0x32, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, 0xe6, 0x3e, 0x4c, + 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, 0x5d, 0x41, 0xba, + 0xe7, 0x11, 0xe9, 0xe5, 0x5e, 0x3a, 0xdd, 0xef, 0x4b, 0x01, 0x96, 0xfa, 0x52, 0x7c, 0x06, 0x85, 0x45, 0xe3, 0x1b, + 0x01, 0xda, 0x1a, 0xaa, 0x69, 0xaf, 0x14, 0x55, 0x2f, 0xe8, 0x95, 0xe2, 0x73, 0x4f, 0x0f, 0x95, 0xf9, 0xb2, 0x74, + 0xf4, 0x3f, 0xa1, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xe2, 0x68, 0xe3, 0x53, 0xbd, + 0x8a, 0x9b, 0x3e, 0xaf, 0xad, 0x65, 0x4e, 0x08, 0x9b, 0xee, 0x25, 0x40, 0x45, 0x5e, 0x09, 0x8f, 0x60, 0xf9, 0xe5, + 0x0f, 0x79, 0xba, 0x42, 0xb4, 0x8e, 0x7b, 0x96, 0xb9, 0x34, 0xf6, 0x2f, 0x0d, 0xa6, 0xaf, 0x6f, 0xb7, 0x45, 0x7e, + 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0xb7, 0xe1, 0x4a, 0xa0, 0xc0, 0xa1, 0x44, 0x62, 0x9b, 0x2a, 0x14, 0xf1, + 0x20, 0xe9, 0xd3, 0x45, 0xeb, 0xd3, 0x00, 0x53, 0x6b, 0x39, 0x30, 0x87, 0x70, 0x15, 0x17, 0x3e, 0x7a, 0xfa, 0x16, + 0xb3, 0x70, 0x3e, 0xf1, 0x3e, 0x78, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x38, 0xcc, 0xaa, 0xb9, + 0xef, 0xd0, 0x47, 0x7a, 0xa8, 0x72, 0x41, 0xd9, 0x1b, 0x63, 0x12, 0x81, 0xd2, 0x18, 0xef, 0xe3, 0xe0, 0x38, 0xef, + 0xd3, 0x00, 0x52, 0xfb, 0xc4, 0x3b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0x55, 0x7c, 0x9b, 0xa1, + 0x5c, 0x77, 0x4a, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x99, 0x57, 0xa3, 0x47, + 0x55, 0x12, 0x96, 0x22, 0xee, 0xf7, 0x77, 0x99, 0x67, 0xd8, 0x1b, 0x1e, 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, + 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, + 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, 0xfd, 0x06, 0xc7, 0x7c, 0x70, 0x1f, 0x71, + 0xbc, 0xc3, 0x59, 0x68, 0x09, 0x79, 0x72, 0xc7, 0x20, 0x4d, 0x63, 0x69, 0x04, 0x9c, 0x88, 0x64, 0x1b, 0x4b, 0xe1, + 0x08, 0x20, 0x20, 0xd0, 0x4d, 0x99, 0x61, 0x4c, 0x07, 0x23, 0xcf, 0xa3, 0x9e, 0xf1, 0x5e, 0x85, 0xa7, 0x90, 0x26, + 0xdb, 0xd7, 0xf3, 0xf7, 0x46, 0x90, 0x95, 0x5b, 0xce, 0xf1, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, 0x79, 0x8a, 0x59, + 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0xe7, 0x28, 0xbd, 0x65, 0x3e, 0x59, 0x45, 0xd2, 0xa5, 0xb7, + 0xe9, 0xf7, 0xe3, 0x91, 0x3a, 0xd4, 0xfc, 0x7d, 0x3c, 0x92, 0x67, 0xd8, 0x86, 0x25, 0x2c, 0xb4, 0x0a, 0xc6, 0x00, + 0x92, 0xd8, 0x88, 0x68, 0x30, 0xda, 0x9b, 0xc3, 0xe1, 0x7c, 0x63, 0xce, 0x92, 0x3d, 0xb8, 0xbe, 0xf2, 0xc4, 0xbc, + 0x03, 0x5f, 0xe6, 0x31, 0x41, 0xc4, 0x66, 0xde, 0x86, 0xd5, 0xe0, 0xc1, 0x0e, 0xae, 0x8f, 0xd8, 0xa2, 0x58, 0xeb, + 0x58, 0x2a, 0xeb, 0xe0, 0xb4, 0x8e, 0x4d, 0x33, 0x52, 0x8a, 0xec, 0x73, 0xec, 0xef, 0xdd, 0xe0, 0xea, 0xda, 0x18, + 0xd4, 0x1a, 0x77, 0x98, 0x3b, 0xa7, 0x02, 0xea, 0x31, 0x5d, 0x41, 0xf5, 0xac, 0x22, 0x5f, 0x7e, 0x6b, 0xe7, 0x80, + 0xa0, 0x11, 0x08, 0x5c, 0x34, 0xfe, 0x77, 0x5d, 0xca, 0x79, 0x17, 0x10, 0xe2, 0xbb, 0x14, 0xf4, 0xe9, 0x0c, 0x36, + 0xb1, 0xf9, 0x04, 0x62, 0xd1, 0x74, 0x9f, 0x6b, 0xcd, 0x7c, 0x31, 0xa2, 0x9d, 0x59, 0x77, 0x8b, 0xdc, 0x6a, 0x21, + 0x92, 0xd1, 0xb3, 0xcd, 0x84, 0xdb, 0x0e, 0xe5, 0x8c, 0x04, 0x4c, 0xd0, 0xda, 0x4a, 0xc9, 0xe7, 0xba, 0xd7, 0x09, + 0xda, 0x03, 0x49, 0xeb, 0xfe, 0xcd, 0xa2, 0x33, 0x4a, 0x4e, 0xae, 0x37, 0x39, 0x83, 0x14, 0x2c, 0xd8, 0x5e, 0xe6, + 0x84, 0x1b, 0xe0, 0x23, 0x9b, 0x25, 0xa7, 0x69, 0x90, 0xc7, 0x42, 0xd7, 0xec, 0x7d, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, + 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, + 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, + 0x98, 0x07, 0xee, 0x6c, 0xe3, 0x9a, 0xc0, 0x40, 0xa7, 0xf6, 0xb5, 0x28, 0xe7, 0x58, 0x45, 0xf4, 0x3e, 0x7f, 0x5f, + 0xd9, 0xd3, 0x07, 0x11, 0x36, 0x2a, 0xd0, 0x58, 0x4a, 0x8c, 0x8d, 0x1c, 0xff, 0x96, 0x28, 0x1b, 0x32, 0x04, 0x84, + 0x90, 0x36, 0x72, 0xfa, 0x61, 0x07, 0xad, 0x64, 0xda, 0xff, 0x93, 0xc4, 0x6f, 0x83, 0xbd, 0x9c, 0xfa, 0x53, 0x8f, + 0x78, 0xbc, 0xd6, 0xe8, 0x31, 0x25, 0xdd, 0x06, 0x79, 0xaa, 0x3c, 0x05, 0xc9, 0x84, 0xb1, 0x84, 0x60, 0x51, 0x2e, + 0x78, 0xce, 0x2b, 0x2e, 0xe1, 0x3e, 0x6a, 0x59, 0x11, 0xa1, 0x2a, 0x91, 0xd3, 0xe7, 0x2b, 0xe0, 0x99, 0x80, 0x40, + 0xc7, 0x18, 0x69, 0x54, 0xc1, 0x97, 0xc0, 0x58, 0x48, 0xca, 0x4e, 0x33, 0x12, 0x5c, 0x76, 0x3f, 0x22, 0x51, 0xea, + 0x0b, 0x52, 0x92, 0xbe, 0x11, 0x35, 0x5e, 0x89, 0x55, 0x44, 0x02, 0x19, 0x6a, 0x88, 0x58, 0x55, 0x4f, 0xdd, 0xab, + 0x62, 0x32, 0x18, 0x54, 0xbe, 0x9c, 0x9e, 0x78, 0x43, 0x43, 0xe5, 0x5d, 0x57, 0xb4, 0xd3, 0x33, 0xad, 0x94, 0xb7, + 0x90, 0x96, 0xa0, 0x69, 0x18, 0x69, 0x0e, 0xa5, 0xae, 0xa4, 0xbb, 0x31, 0x88, 0x2f, 0x99, 0xe8, 0xd9, 0x4e, 0xed, + 0x28, 0x6d, 0x49, 0x7b, 0x08, 0xe9, 0xb9, 0x4b, 0x3e, 0x66, 0x21, 0x57, 0x77, 0xca, 0x49, 0x79, 0x15, 0xa2, 0x93, + 0xfb, 0x1e, 0x43, 0x22, 0xd0, 0xe7, 0x1c, 0xc3, 0xba, 0x68, 0xa8, 0x73, 0x58, 0x21, 0x66, 0x0b, 0x25, 0xcc, 0x97, + 0x8c, 0xa7, 0x92, 0x41, 0x03, 0x20, 0x03, 0x3e, 0x7b, 0x19, 0x58, 0xfe, 0x0a, 0xe2, 0x47, 0x1b, 0x1f, 0x0e, 0x5f, + 0x6a, 0x0a, 0xb1, 0xfd, 0x02, 0x9b, 0x21, 0x3c, 0xaa, 0x07, 0x3c, 0xf3, 0x4d, 0x9c, 0xa0, 0xe5, 0x88, 0x93, 0xd9, + 0xd1, 0x44, 0xf6, 0xaa, 0x87, 0x70, 0x2a, 0x2b, 0x50, 0x47, 0x59, 0x67, 0x25, 0xfc, 0x08, 0x53, 0xdd, 0x4a, 0xac, + 0x05, 0xda, 0x5c, 0xad, 0x58, 0x0b, 0xe0, 0xc0, 0xcf, 0x21, 0x78, 0x22, 0x9f, 0x83, 0x8b, 0x41, 0x01, 0x3e, 0x07, + 0xc0, 0x8b, 0xdc, 0xd1, 0xb9, 0x3f, 0x3d, 0xb0, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, + 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x4e, 0x98, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x8f, + 0xf6, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0x87, 0xe5, 0x35, 0x60, 0x7a, 0x05, 0x91, + 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x6e, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x11, 0xa9, 0xae, 0x85, 0xb4, + 0x91, 0x4f, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfd, 0xe9, 0x6f, 0xcf, 0x3e, 0xbd, 0xfa, 0xf5, 0xa7, 0xc5, 0xab, 0xb7, + 0x2f, 0x5f, 0xbd, 0x7d, 0xf5, 0xe9, 0x77, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xfd, 0xbb, 0x8f, 0xaf, 0x9c, 0x0c, + 0x36, 0xcc, 0x58, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0x92, 0x39, 0x66, 0x62, 0x8e, + 0xb1, 0x77, 0x02, 0x93, 0x2d, 0xf0, 0x1d, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x37, 0xe0, + 0x22, 0x93, 0xe6, 0xb7, 0xbf, 0x12, 0xc4, 0x3e, 0xad, 0xa4, 0xdc, 0x57, 0xdb, 0x9a, 0xe7, 0xdb, 0xfb, 0xbd, 0x84, + 0xf3, 0x9f, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0xe7, 0xf0, 0xc7, 0x95, 0xb6, 0xa4, 0xc9, 0x2c, 0xda, 0xcf, 0x18, + 0x82, 0x2e, 0x0d, 0x3e, 0x88, 0x3d, 0xf2, 0x52, 0x9f, 0x2c, 0x24, 0x70, 0x47, 0x0c, 0x9f, 0x56, 0x04, 0xbd, 0x62, + 0x44, 0x71, 0xc9, 0x15, 0x2a, 0xa5, 0xe4, 0xdf, 0x28, 0xbb, 0xa8, 0x90, 0xb3, 0x82, 0xdd, 0x29, 0x72, 0x64, 0xfc, + 0x20, 0x98, 0xf8, 0x72, 0x70, 0xff, 0x25, 0xde, 0xe1, 0x4c, 0x71, 0x24, 0x27, 0xfc, 0x63, 0x86, 0x81, 0xfd, 0x39, + 0xf8, 0xbc, 0x3a, 0xcc, 0xcb, 0x1b, 0x7d, 0xca, 0x2d, 0xf9, 0x78, 0xb2, 0xbc, 0x02, 0x83, 0xfd, 0x52, 0x35, 0x77, + 0xcd, 0xeb, 0xd9, 0x72, 0xce, 0xf6, 0xb3, 0x68, 0x1e, 0xdc, 0xb2, 0x59, 0x36, 0x0f, 0x56, 0x0d, 0x5f, 0xb3, 0x1b, + 0xbe, 0xb6, 0xaa, 0xb6, 0xb6, 0xab, 0x36, 0xd9, 0xf0, 0x1b, 0x90, 0x10, 0xae, 0xc1, 0x2f, 0x39, 0x61, 0xb7, 0x3e, + 0xdb, 0x80, 0x44, 0xbb, 0x62, 0x1b, 0xb8, 0x88, 0xad, 0xf9, 0xab, 0xca, 0xdb, 0xb0, 0x92, 0x9d, 0x8f, 0x59, 0x8e, + 0xf3, 0xcf, 0x87, 0x07, 0xb4, 0x17, 0xea, 0x67, 0x97, 0xea, 0xd9, 0x44, 0xd9, 0xcd, 0x36, 0xa3, 0xc5, 0x5d, 0x5a, + 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x4d, 0x9c, 0xdf, 0xd3, 0xb6, + 0x5d, 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x9c, 0x3f, 0x85, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, + 0xfd, 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xfc, 0x52, 0x59, + 0xad, 0x34, 0x27, 0xa1, 0x6d, 0xc4, 0xaa, 0xe5, 0x48, 0xd5, 0x8c, 0x48, 0x1f, 0xa4, 0xe7, 0x7d, 0x8f, 0xa8, 0x06, + 0x7b, 0x32, 0xaf, 0x03, 0xfb, 0xf4, 0xae, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, + 0x78, 0xaf, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xa1, 0x0a, 0x38, 0x5f, 0xaf, 0x44, 0xbb, 0x13, 0x61, 0x57, + 0x2e, 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, + 0xce, 0x73, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xa5, 0x26, 0x13, 0x39, 0x28, 0x1f, + 0x0e, 0x05, 0xec, 0xa5, 0xc6, 0x4f, 0x13, 0x7e, 0xc2, 0xf2, 0xd6, 0xde, 0x9a, 0x52, 0x54, 0xd2, 0x00, 0x15, 0xf8, + 0x98, 0xc1, 0xff, 0xee, 0x0c, 0xb1, 0x60, 0x8a, 0x8e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x94, 0xad, + 0xd1, 0x4e, 0xc0, 0xa9, 0x8e, 0x93, 0x44, 0x38, 0xf5, 0x1e, 0x71, 0x51, 0xf7, 0x72, 0x88, 0xba, 0x61, 0x9f, 0x2a, + 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, 0x7b, 0x2b, 0x88, 0x20, 0x45, 0x36, 0xa2, 0x24, 0x8d, + 0x63, 0x91, 0xc3, 0xf6, 0xbe, 0x90, 0xfb, 0x7f, 0xbf, 0x0f, 0xe1, 0xa4, 0x55, 0x10, 0x97, 0x9e, 0x40, 0x44, 0x38, + 0x3a, 0xfc, 0x88, 0xf0, 0x44, 0xaa, 0x0a, 0xdf, 0xd7, 0x27, 0x6e, 0xcc, 0xee, 0x85, 0x39, 0xaa, 0xb7, 0x00, 0xc3, + 0x58, 0x6f, 0x2d, 0x42, 0x12, 0xad, 0x34, 0xa3, 0xad, 0x07, 0xc4, 0x88, 0x77, 0x6b, 0x8b, 0x0c, 0xc6, 0xda, 0x92, + 0x48, 0x00, 0xbf, 0x25, 0x21, 0x43, 0xdb, 0x46, 0x60, 0xc6, 0xf0, 0x76, 0x56, 0x5c, 0xba, 0x0e, 0xdb, 0x9c, 0xc3, + 0x17, 0xb2, 0xd0, 0xac, 0x23, 0x4a, 0x13, 0x84, 0xfc, 0x03, 0x4e, 0x16, 0x0a, 0xa3, 0x79, 0x71, 0x94, 0x4e, 0x12, + 0xeb, 0xbb, 0xae, 0x52, 0xc1, 0x66, 0xf3, 0x11, 0xf5, 0x65, 0x47, 0xc9, 0xd7, 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, + 0x44, 0x2d, 0x2a, 0xe7, 0x63, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xcd, 0x7a, 0x5d, 0x94, 0x75, 0xf5, 0x42, 0x44, 0x8a, + 0xde, 0x47, 0x3d, 0x7a, 0x24, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe5, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, + 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0xee, 0x65, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x03, 0xaf, 0x1c, 0xe5, + 0x97, 0x56, 0x9b, 0xf4, 0x2b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, + 0x62, 0x96, 0xe6, 0x7f, 0xe2, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x53, 0xe5, 0xd5, 0x72, 0x2d, 0x33, + 0xcd, 0xcd, 0x12, 0xc7, 0x8a, 0xc5, 0x45, 0xbd, 0xae, 0x44, 0x16, 0x08, 0x71, 0x84, 0x69, 0xac, 0xa7, 0xde, 0x28, + 0xad, 0xde, 0x23, 0xa1, 0xcc, 0x4f, 0xd8, 0xdb, 0xb1, 0xd7, 0x83, 0x2c, 0xc4, 0xb1, 0xe5, 0x60, 0xb3, 0xf5, 0x3e, + 0x95, 0xa9, 0x88, 0xcf, 0xea, 0xe2, 0x6c, 0x53, 0x89, 0xb3, 0x3a, 0x11, 0x67, 0x3f, 0x42, 0xce, 0x1f, 0xcf, 0xa8, + 0xe8, 0xb3, 0xfb, 0xb4, 0x4e, 0x8a, 0x4d, 0x4d, 0x4f, 0x5e, 0x62, 0x19, 0x3f, 0x9e, 0x11, 0x57, 0xcd, 0x19, 0x8d, + 0x64, 0x3c, 0x3a, 0x7b, 0x9f, 0x01, 0xc9, 0xeb, 0x59, 0xba, 0x82, 0xc1, 0x3b, 0x0b, 0xf3, 0xf8, 0xac, 0x14, 0xb7, + 0x60, 0x71, 0x2a, 0x3b, 0xdf, 0x83, 0x0c, 0xab, 0xf0, 0x4f, 0x71, 0x06, 0xd0, 0xae, 0x67, 0x69, 0x7d, 0x96, 0x56, + 0x67, 0x79, 0x51, 0x9f, 0x29, 0x29, 0x1c, 0xc2, 0xf8, 0xe1, 0x3d, 0x7d, 0x65, 0x97, 0xb7, 0x59, 0xdc, 0x65, 0x91, + 0x3f, 0x45, 0xaf, 0x22, 0x62, 0xd2, 0xa8, 0x84, 0xd7, 0xee, 0x6f, 0x9b, 0xfb, 0x87, 0xd7, 0x8d, 0xdd, 0xcf, 0xee, + 0x18, 0xd1, 0x05, 0xf5, 0x78, 0x25, 0x29, 0x15, 0x14, 0x10, 0x38, 0xd1, 0xac, 0xf1, 0xe0, 0x8e, 0x03, 0x5e, 0x0d, + 0x6c, 0xc9, 0xd6, 0x3e, 0x7f, 0x1a, 0xcb, 0x30, 0xed, 0x4d, 0x80, 0x7f, 0x95, 0xbd, 0xe9, 0x3a, 0x58, 0xe2, 0x7d, + 0x0b, 0xd9, 0x86, 0x5e, 0xbd, 0xe0, 0xcf, 0xbc, 0x5c, 0xfd, 0xcd, 0x7e, 0x07, 0x20, 0x0c, 0x88, 0x59, 0xf5, 0xd1, + 0xc4, 0xbd, 0xb3, 0xb2, 0xec, 0x9c, 0x2c, 0xbb, 0x1e, 0xfa, 0x35, 0x89, 0x51, 0x69, 0x65, 0x29, 0x9d, 0x2c, 0x25, + 0x64, 0x01, 0x9f, 0x18, 0x4d, 0x6d, 0x04, 0x10, 0xb6, 0xa3, 0x54, 0xbe, 0x50, 0x79, 0x11, 0x85, 0x73, 0x82, 0xe7, + 0x89, 0x18, 0xdd, 0x59, 0xc9, 0x80, 0xe1, 0x10, 0x82, 0x39, 0x68, 0x8b, 0xbd, 0xa1, 0x9b, 0x88, 0xbf, 0x5e, 0x16, + 0xe5, 0xab, 0x98, 0x7c, 0x0a, 0x76, 0x27, 0x1f, 0x97, 0xf0, 0xb8, 0x3c, 0xf9, 0x38, 0x44, 0x8f, 0x84, 0x93, 0x8f, + 0xc1, 0xf7, 0x48, 0xce, 0xeb, 0xae, 0xc7, 0x09, 0x72, 0x0b, 0xe9, 0xfe, 0x76, 0x4c, 0x02, 0x34, 0xaf, 0x61, 0x39, + 0x6a, 0x2a, 0xae, 0x99, 0x19, 0xe3, 0x79, 0xa3, 0xf7, 0xc7, 0x8e, 0xb7, 0x4c, 0xa1, 0x98, 0xc5, 0xbc, 0x86, 0xdf, + 0xb3, 0x2a, 0x50, 0x77, 0xbd, 0x4d, 0x72, 0xcb, 0xac, 0x9e, 0xa3, 0xdd, 0xf7, 0x5d, 0x9d, 0x08, 0x6a, 0x7f, 0x87, + 0x3d, 0xcf, 0xac, 0x77, 0x55, 0x0c, 0x5c, 0xaa, 0x64, 0x87, 0x4c, 0x55, 0xd3, 0x03, 0x95, 0xd2, 0xe0, 0xe9, 0xa5, + 0x75, 0xf9, 0x52, 0x69, 0x23, 0xcf, 0x34, 0xbf, 0x01, 0xbc, 0x98, 0xba, 0x2c, 0x76, 0xdf, 0xdc, 0x57, 0x70, 0x1b, + 0xef, 0xf7, 0xd7, 0x95, 0x67, 0x7e, 0xe2, 0x02, 0xb0, 0x37, 0x15, 0x5a, 0x27, 0x50, 0x6a, 0x58, 0x87, 0xd7, 0x89, + 0x88, 0xfe, 0x6c, 0x97, 0xeb, 0xcc, 0x75, 0xc0, 0x88, 0x22, 0x7e, 0x1b, 0x8f, 0xfe, 0x00, 0xc5, 0xb5, 0xb1, 0x07, + 0x84, 0x75, 0x48, 0xe8, 0x33, 0x02, 0x90, 0x7a, 0xf4, 0x51, 0xf2, 0x27, 0x68, 0x56, 0x34, 0x77, 0x4c, 0x7e, 0xae, + 0xaf, 0x94, 0xfe, 0x7e, 0x5d, 0x79, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0x54, 0x02, 0xe1, 0x15, 0x95, 0xac, + 0xc2, 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x9f, 0xb6, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0xc2, 0xef, + 0xf7, 0x2b, 0x80, 0x79, 0x91, 0xcd, 0xec, 0x3e, 0x0e, 0xa8, 0x52, 0xa2, 0x69, 0x9c, 0xcd, 0xf3, 0x7b, 0x7a, 0x53, + 0x76, 0xd0, 0xa9, 0x53, 0x05, 0x2e, 0xb8, 0x2a, 0x19, 0xaf, 0xac, 0x27, 0xf2, 0xf9, 0xcd, 0xcd, 0x26, 0xcd, 0xe2, + 0x77, 0xe5, 0x2f, 0x38, 0xb6, 0xba, 0x0e, 0x0f, 0x4c, 0x9d, 0xae, 0x9d, 0x47, 0x5a, 0x7b, 0x21, 0x20, 0xa2, 0x5d, + 0x43, 0xad, 0x17, 0x16, 0x7a, 0xa4, 0x27, 0xc2, 0x39, 0x49, 0xd4, 0xb4, 0x03, 0x2d, 0x8d, 0xd0, 0xd7, 0xd7, 0x9c, + 0xfe, 0xc2, 0x60, 0xed, 0xf3, 0x31, 0x03, 0xb2, 0x12, 0xfd, 0x58, 0x3d, 0x34, 0x36, 0x73, 0xe8, 0x59, 0xab, 0xf2, + 0xcc, 0xab, 0x0e, 0x07, 0xc4, 0x87, 0xd1, 0x5f, 0xf2, 0xfb, 0xfd, 0x17, 0x34, 0xff, 0x98, 0x50, 0xe3, 0x67, 0x9b, + 0x01, 0xba, 0xf6, 0x5d, 0x79, 0x20, 0xea, 0xb9, 0x56, 0x09, 0x42, 0xbc, 0x41, 0x4c, 0x34, 0x23, 0xe6, 0xe0, 0xb4, + 0x43, 0xcd, 0x3f, 0x49, 0x0d, 0x08, 0x51, 0xe2, 0x75, 0x4c, 0x59, 0x90, 0xd3, 0x26, 0x8e, 0xf4, 0xa3, 0x70, 0x22, + 0x3f, 0x88, 0xaa, 0xc8, 0xee, 0xe0, 0x82, 0xc1, 0xd4, 0x7b, 0xda, 0x2f, 0xd1, 0x6f, 0x09, 0x47, 0xce, 0xd1, 0xaa, + 0x10, 0x44, 0x4e, 0x08, 0x6b, 0x0d, 0x61, 0x82, 0xd8, 0x20, 0x5e, 0xf6, 0x5d, 0x92, 0xe1, 0x48, 0xc1, 0x65, 0x1d, + 0x3b, 0xc6, 0x5c, 0x1d, 0x55, 0xaf, 0x01, 0x8c, 0x57, 0x8e, 0xa0, 0xd9, 0x28, 0xb2, 0x4b, 0x88, 0x2a, 0x72, 0x3c, + 0x01, 0xb5, 0x83, 0xd2, 0xd8, 0x4c, 0xcf, 0xc7, 0x41, 0x3e, 0x5a, 0x54, 0xa8, 0x73, 0x62, 0x19, 0xaf, 0x01, 0x58, + 0x3b, 0x57, 0xfd, 0x3c, 0xab, 0xc1, 0x93, 0x86, 0xf8, 0x7c, 0x8c, 0xb6, 0x57, 0x36, 0x07, 0xd5, 0x76, 0x3a, 0x2b, + 0xaf, 0x98, 0x2e, 0x07, 0xc6, 0x7d, 0xc3, 0x2b, 0x8a, 0x33, 0xfc, 0xe0, 0xc1, 0x16, 0xe7, 0x4f, 0x37, 0xd4, 0x7e, + 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0xbb, 0x8e, 0x6c, 0xef, 0xb4, 0xc8, 0x68, 0xf2, + 0xd9, 0xcf, 0xdf, 0x97, 0xe9, 0x2a, 0x85, 0xfb, 0x92, 0x93, 0x45, 0x33, 0x0f, 0x81, 0xbd, 0x21, 0x86, 0xeb, 0xa3, + 0xc2, 0x23, 0xca, 0xfa, 0x7d, 0xf8, 0x7d, 0x95, 0x81, 0x29, 0x06, 0xae, 0x2b, 0x04, 0xe3, 0x21, 0x10, 0xc4, 0xc3, + 0x34, 0x3a, 0x19, 0xd4, 0xa0, 0x0d, 0xdf, 0x00, 0x64, 0x06, 0x78, 0x64, 0x2e, 0x3d, 0x02, 0xee, 0x02, 0xd7, 0x9e, + 0x8c, 0xc7, 0xfe, 0xc4, 0x34, 0x34, 0x6a, 0x4a, 0x33, 0x3d, 0x37, 0x7e, 0xd3, 0x51, 0x2d, 0xd7, 0xce, 0x7f, 0x7c, + 0xc9, 0x6f, 0xd0, 0x0b, 0x5a, 0x5e, 0xee, 0x23, 0x75, 0xb9, 0xcf, 0x28, 0x2e, 0x13, 0xc9, 0x61, 0x41, 0x2c, 0x4b, + 0x38, 0xf0, 0x18, 0x95, 0x2c, 0xb6, 0xf4, 0x58, 0x15, 0x2d, 0x5f, 0x94, 0x1b, 0xa4, 0x43, 0x27, 0x04, 0x4b, 0x54, + 0x10, 0x2c, 0x81, 0x71, 0x11, 0x6b, 0xbe, 0x19, 0xe4, 0x2c, 0x9e, 0x6d, 0xe6, 0x1c, 0x09, 0xeb, 0x92, 0xc3, 0xa1, + 0x90, 0x60, 0x33, 0xd9, 0x6c, 0x3d, 0x67, 0x6b, 0x9f, 0x81, 0x12, 0xa0, 0x94, 0x69, 0x82, 0xd2, 0xb4, 0x62, 0x2b, + 0x6e, 0x5a, 0x83, 0xd5, 0x6a, 0xca, 0x56, 0x35, 0x65, 0xe7, 0x34, 0xe5, 0xa8, 0x82, 0x92, 0x13, 0x4a, 0x51, 0x86, + 0x01, 0x8c, 0xd8, 0x24, 0xba, 0xca, 0xd0, 0xc7, 0x3b, 0xe1, 0x11, 0x54, 0x11, 0x91, 0x4f, 0x18, 0x42, 0x60, 0x22, + 0x8a, 0x0b, 0x55, 0x28, 0x06, 0xc8, 0x88, 0x04, 0x82, 0x89, 0x4a, 0x9d, 0x02, 0xf3, 0xd1, 0x54, 0x31, 0x6c, 0xda, + 0x13, 0xe5, 0x7b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0x1f, 0x62, 0x17, 0x84, 0xc8, 0xdd, 0xb8, 0x53, 0x3f, 0x23, 0xde, + 0xdb, 0x1d, 0x61, 0xfc, 0x64, 0xc7, 0x2d, 0xc2, 0x15, 0xc1, 0x96, 0x6a, 0x0e, 0xb1, 0x98, 0x57, 0x93, 0x04, 0xb5, + 0x2c, 0x89, 0xbf, 0xe1, 0xc9, 0x20, 0x67, 0x4b, 0xf0, 0xa0, 0x9d, 0xb3, 0x0c, 0xf0, 0x57, 0xac, 0x16, 0xfd, 0x5e, + 0x7b, 0x4b, 0x90, 0x9f, 0x36, 0x76, 0xa3, 0x30, 0x31, 0x82, 0x44, 0xdd, 0xae, 0x0c, 0xe4, 0x87, 0xf7, 0x38, 0x1d, + 0x8f, 0x3d, 0x65, 0xcc, 0xad, 0x4c, 0x2f, 0xd3, 0xb9, 0x92, 0x6f, 0xe4, 0x5e, 0xfa, 0xd0, 0x4b, 0xb0, 0x73, 0xc0, + 0x1b, 0x48, 0x1b, 0xf8, 0x11, 0xb6, 0x0b, 0xaf, 0x0d, 0x12, 0x66, 0x04, 0xd8, 0xe2, 0xf8, 0x18, 0x29, 0x81, 0x21, + 0x1c, 0x67, 0x29, 0x00, 0xd3, 0xe8, 0xcb, 0x6c, 0x65, 0x5f, 0x66, 0xb5, 0x66, 0x4b, 0xe5, 0x74, 0xef, 0xdc, 0xba, + 0x9d, 0xcf, 0x24, 0x00, 0x98, 0xd4, 0x39, 0x10, 0x67, 0x26, 0xd8, 0xa5, 0x49, 0x64, 0xf9, 0x10, 0xe6, 0xb7, 0xe2, + 0x65, 0x59, 0xac, 0x54, 0x57, 0xb4, 0x7d, 0x66, 0xf2, 0x19, 0xe9, 0x24, 0x54, 0x40, 0x41, 0x21, 0xd7, 0xfa, 0xf4, + 0x6d, 0xf8, 0x36, 0x28, 0x34, 0x30, 0x5b, 0x85, 0x7b, 0x9a, 0xac, 0x91, 0x7a, 0xa3, 0xea, 0xf7, 0xc9, 0x35, 0x90, + 0xea, 0xcc, 0xa1, 0x65, 0xcf, 0x2a, 0x0c, 0x10, 0x3b, 0xea, 0x33, 0x12, 0xea, 0x40, 0xea, 0x01, 0x43, 0x88, 0xb6, + 0xe9, 0xe3, 0x4f, 0x86, 0x44, 0x17, 0x60, 0x0b, 0xd1, 0x06, 0x7e, 0xfc, 0x09, 0xf6, 0x59, 0x10, 0x1e, 0xd3, 0xfc, + 0x0d, 0x24, 0x1d, 0x1b, 0x38, 0xad, 0x3e, 0x05, 0x1f, 0x24, 0x39, 0x98, 0xa8, 0x83, 0x97, 0xfb, 0x4b, 0xbf, 0x0f, + 0x5b, 0x76, 0x2e, 0xa5, 0x3a, 0x56, 0xea, 0x6d, 0x5b, 0xfb, 0x41, 0xb4, 0x05, 0x47, 0x16, 0xf1, 0xf7, 0x19, 0x22, + 0x82, 0x99, 0x41, 0x84, 0x5d, 0x0b, 0x75, 0xb7, 0xa7, 0xd4, 0xb2, 0xa8, 0xb7, 0x3d, 0xa5, 0xd4, 0x6d, 0x18, 0xbe, + 0x9b, 0x60, 0xa6, 0xb8, 0xe1, 0x6f, 0x32, 0x2f, 0xd4, 0x1b, 0x8f, 0x71, 0x8c, 0x5f, 0x7b, 0xfe, 0x7e, 0xc9, 0xab, + 0xd9, 0x46, 0x99, 0x30, 0x6f, 0xf9, 0x72, 0x16, 0xca, 0xae, 0x96, 0xc6, 0x9d, 0xcf, 0xde, 0x52, 0xcd, 0x07, 0xff, + 0x70, 0x48, 0x20, 0xde, 0x28, 0xbe, 0xba, 0x6d, 0xe4, 0xd6, 0x35, 0xd9, 0x5c, 0x95, 0x80, 0xfa, 0x7d, 0xbe, 0xc6, + 0xfd, 0x16, 0xeb, 0xdf, 0x3d, 0x0d, 0x32, 0x56, 0x33, 0x5c, 0x31, 0x85, 0x4f, 0x01, 0x60, 0x70, 0x38, 0x15, 0xa4, + 0x05, 0xde, 0xf0, 0x72, 0x78, 0x39, 0xd9, 0x90, 0x49, 0x77, 0xe3, 0x23, 0x77, 0x16, 0xa8, 0x7a, 0xbf, 0xa3, 0x38, + 0x69, 0x90, 0x68, 0xec, 0x35, 0xf8, 0x2c, 0xcb, 0x28, 0x17, 0x4d, 0xdc, 0x87, 0xe4, 0x2b, 0x3d, 0x80, 0xb9, 0x0a, + 0x25, 0x40, 0xf4, 0x1b, 0xcb, 0x62, 0x23, 0xda, 0x16, 0x1b, 0x58, 0x4a, 0xd5, 0x5c, 0xaf, 0xa6, 0xcf, 0x5e, 0x89, + 0xe6, 0x7d, 0x34, 0xe3, 0x94, 0x46, 0x03, 0x8e, 0xd3, 0x28, 0xdc, 0xbe, 0xbb, 0x13, 0xe5, 0x32, 0x03, 0x4b, 0xb6, + 0x0a, 0xa7, 0xb8, 0x6c, 0xd4, 0x19, 0xf1, 0x2c, 0x8f, 0x15, 0x40, 0xc7, 0x43, 0x02, 0xa0, 0xba, 0x20, 0xa0, 0x22, + 0x5a, 0x4a, 0x6f, 0x85, 0x16, 0x0b, 0xf5, 0x86, 0xa3, 0x14, 0xfe, 0x48, 0x7f, 0x1e, 0xe4, 0x53, 0x00, 0x62, 0xd7, + 0xc7, 0xd1, 0xcb, 0xa2, 0xa4, 0x4f, 0x15, 0xb3, 0x5c, 0x0e, 0x26, 0xb0, 0xab, 0x13, 0x19, 0x6a, 0x05, 0x79, 0xab, + 0xae, 0xbc, 0x95, 0xc9, 0xdb, 0x18, 0xa7, 0xe4, 0x07, 0x6e, 0x3a, 0xd6, 0x88, 0x81, 0x57, 0x9e, 0xd6, 0x69, 0x82, + 0x34, 0xb9, 0x00, 0x86, 0x21, 0x7e, 0x9f, 0x79, 0xcf, 0x3c, 0x47, 0xaa, 0x82, 0x64, 0x76, 0x97, 0x79, 0xea, 0x22, + 0xaa, 0xaf, 0x9c, 0x5a, 0x3a, 0x73, 0xfa, 0x11, 0xc0, 0x7b, 0x4c, 0x4d, 0x1a, 0xf2, 0x11, 0x6e, 0x4b, 0xf1, 0xf5, + 0x56, 0x5d, 0xe3, 0xa5, 0xd1, 0xb9, 0x7b, 0xf9, 0xd2, 0x9d, 0x06, 0xfd, 0x14, 0x04, 0xe5, 0x7c, 0x56, 0x0a, 0xd8, + 0x53, 0x66, 0x73, 0xbd, 0x5a, 0xb5, 0x42, 0xeb, 0x70, 0x18, 0x6b, 0x47, 0x21, 0xad, 0xce, 0x02, 0xb6, 0x1a, 0xe9, + 0x94, 0x00, 0x21, 0x38, 0x4e, 0xc3, 0x4e, 0x30, 0xee, 0xd2, 0x69, 0x44, 0xd6, 0x2b, 0x25, 0xe9, 0xc2, 0x0c, 0x92, + 0x7f, 0x92, 0xd7, 0x33, 0xa0, 0x25, 0x80, 0x43, 0x11, 0x4b, 0x78, 0x38, 0x49, 0xae, 0x00, 0x3a, 0x1d, 0x0e, 0x2a, + 0x0d, 0xcd, 0x59, 0xcd, 0x92, 0xf9, 0x24, 0x96, 0xaa, 0xca, 0xc3, 0xc1, 0x53, 0x6e, 0x06, 0xfd, 0x7e, 0x36, 0x2d, + 0x95, 0x0b, 0x40, 0x10, 0xeb, 0xc2, 0x00, 0xf1, 0x48, 0x0b, 0x4f, 0x16, 0x7d, 0x4a, 0xe2, 0x97, 0xb3, 0x64, 0x6e, + 0xb2, 0xe1, 0x1d, 0x18, 0xc1, 0x66, 0x5c, 0x97, 0x94, 0x69, 0x8f, 0xca, 0xef, 0x19, 0x3d, 0xb5, 0x7d, 0xad, 0xd5, + 0x16, 0xb1, 0xae, 0x83, 0xab, 0x12, 0xf5, 0x14, 0x1f, 0x94, 0x24, 0x78, 0xbf, 0x70, 0x6e, 0x46, 0xca, 0xd7, 0x22, + 0xf7, 0x83, 0x76, 0xa6, 0x56, 0x0e, 0x1c, 0x81, 0x1c, 0xab, 0xa8, 0xe4, 0xf5, 0xae, 0x43, 0xf0, 0xe8, 0xae, 0x54, + 0xa0, 0x1c, 0xfc, 0x14, 0xc4, 0xe8, 0xfa, 0xaa, 0xb3, 0x86, 0x9a, 0x69, 0x54, 0x79, 0x04, 0x9d, 0x3a, 0x80, 0x27, + 0x05, 0x2f, 0xb5, 0xfa, 0xf1, 0x70, 0xf0, 0xcc, 0x0f, 0xfe, 0x2e, 0xd3, 0xb7, 0x10, 0x13, 0xe5, 0x54, 0x23, 0x24, + 0xae, 0x94, 0x24, 0xe2, 0xe3, 0x45, 0xcb, 0x8a, 0x51, 0x19, 0xde, 0xf3, 0x4a, 0x95, 0xaf, 0x4e, 0x55, 0x5e, 0x8c, + 0xb4, 0x2d, 0x81, 0xd7, 0xe4, 0x1f, 0x22, 0xd7, 0xbc, 0xf5, 0x75, 0x57, 0x19, 0xfa, 0x48, 0x56, 0xa0, 0x23, 0xd8, + 0xca, 0x52, 0x72, 0xc0, 0x27, 0xd5, 0x5d, 0xb5, 0x6a, 0x7d, 0x4e, 0xd9, 0x46, 0xb8, 0xc9, 0xaf, 0x63, 0x07, 0x47, + 0xca, 0x6f, 0xf0, 0x5c, 0x00, 0x7b, 0x0d, 0xd8, 0x9b, 0x73, 0x56, 0x34, 0x0f, 0x0e, 0x69, 0x5b, 0xa0, 0x91, 0x99, + 0xdb, 0xb9, 0xba, 0x6f, 0xcb, 0xa3, 0x34, 0x86, 0xc8, 0xb4, 0x07, 0xa6, 0x83, 0xcd, 0x28, 0xff, 0x3d, 0xe5, 0xb7, + 0x0a, 0xc7, 0xc0, 0xb7, 0x53, 0xef, 0x00, 0xaa, 0x9e, 0x36, 0xc8, 0x58, 0x33, 0x0c, 0xad, 0xec, 0x72, 0x29, 0xb4, + 0x04, 0x2d, 0x75, 0x13, 0x04, 0xe7, 0x47, 0x44, 0x39, 0x02, 0xd0, 0x45, 0x0a, 0x98, 0xe0, 0xa7, 0xb4, 0xdd, 0xfd, + 0xfe, 0x3a, 0xf5, 0xc8, 0xbd, 0x2b, 0xd4, 0x28, 0xa1, 0x04, 0x63, 0x3f, 0xd1, 0x98, 0x41, 0x47, 0x57, 0xe4, 0x84, + 0x67, 0xad, 0x0e, 0xeb, 0xba, 0x29, 0x83, 0xb2, 0x38, 0xe6, 0xd5, 0x74, 0xf6, 0xc7, 0xa3, 0x7d, 0xdd, 0x20, 0x0b, + 0xf9, 0x1f, 0xac, 0x87, 0x64, 0xd0, 0x3d, 0x08, 0x85, 0xe8, 0xcd, 0x83, 0x19, 0xfe, 0xc7, 0x36, 0x3c, 0xfb, 0x8e, + 0x1b, 0x75, 0x82, 0x98, 0x23, 0x8e, 0x97, 0x9e, 0xa2, 0xad, 0x87, 0x5b, 0x20, 0x5b, 0xe3, 0xe5, 0xad, 0xbd, 0x06, + 0x72, 0x8a, 0xe3, 0xbf, 0xe5, 0x99, 0x5a, 0xd9, 0xe0, 0xa7, 0xa7, 0x6c, 0x07, 0x1e, 0x5e, 0x84, 0x80, 0x62, 0x58, + 0x36, 0xfe, 0xd6, 0x72, 0x9c, 0xd1, 0x7f, 0xf3, 0x88, 0x61, 0xb0, 0x88, 0xfc, 0xf8, 0xb2, 0x14, 0xe2, 0xab, 0xf0, + 0x3e, 0x55, 0xde, 0x2d, 0x39, 0x65, 0xde, 0xea, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x4b, 0x3e, 0xb6, 0x86, 0xed, 0x0f, + 0xed, 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0xd5, 0xec, 0xf4, 0xfa, 0xbd, 0x73, + 0xbc, 0x60, 0x6b, 0x34, 0xc0, 0xe3, 0xa1, 0x8b, 0x79, 0xa2, 0x86, 0x4e, 0xd7, 0xb5, 0x73, 0xf0, 0xc0, 0x20, 0xcb, + 0x93, 0xef, 0x18, 0x96, 0xd8, 0x9f, 0x44, 0x3c, 0x69, 0xab, 0x36, 0x36, 0x47, 0xaa, 0x8d, 0x9a, 0x81, 0x1f, 0xbc, + 0x82, 0x02, 0xa3, 0x0b, 0xd2, 0x02, 0x8c, 0xc3, 0x11, 0x80, 0xac, 0x18, 0xc7, 0x23, 0x83, 0x09, 0x0c, 0xe9, 0x86, + 0xa2, 0x00, 0x3c, 0x3c, 0x8e, 0x07, 0x21, 0x03, 0x48, 0x17, 0x3c, 0x34, 0x6c, 0x93, 0x90, 0xf2, 0xf3, 0x3c, 0xaf, + 0xd5, 0x10, 0xfa, 0xce, 0x42, 0x75, 0xec, 0x47, 0xda, 0x2b, 0xd6, 0xb5, 0x2a, 0x1d, 0xd9, 0xea, 0x00, 0x7d, 0x43, + 0x06, 0xbe, 0x75, 0x6c, 0x01, 0x10, 0x2d, 0xf1, 0x25, 0xf5, 0x6a, 0x5f, 0xc6, 0xac, 0x50, 0xaf, 0x2f, 0x4c, 0xbb, + 0x5e, 0x48, 0x8b, 0x02, 0x2a, 0x6e, 0x5b, 0xb5, 0x3d, 0x92, 0xf3, 0x1f, 0xde, 0x75, 0xb4, 0xe3, 0xb3, 0x53, 0x63, + 0x4b, 0x28, 0x73, 0x8b, 0x27, 0xb2, 0x3a, 0xda, 0x52, 0x9d, 0xea, 0x03, 0x2e, 0x35, 0xa9, 0xce, 0x0c, 0x0c, 0xaf, + 0x11, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xde, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xd8, 0xda, + 0x45, 0x73, 0xfd, 0xfa, 0x92, 0x7a, 0x55, 0x9b, 0xaa, 0x1e, 0xbc, 0xf1, 0x02, 0x67, 0xef, 0xb4, 0x16, 0x10, 0x40, + 0x61, 0x6b, 0x59, 0x0e, 0xce, 0xdd, 0xae, 0x6a, 0xa9, 0x28, 0xa3, 0x7e, 0xff, 0xfc, 0x4b, 0x8a, 0x8a, 0xd8, 0x53, + 0xc5, 0x29, 0xeb, 0xb7, 0x5b, 0xe6, 0xa2, 0xb2, 0xe4, 0x0d, 0xaa, 0x68, 0xad, 0x8e, 0x9a, 0xca, 0x75, 0x73, 0xd5, + 0x92, 0x09, 0x62, 0x74, 0x9f, 0xae, 0x75, 0xee, 0xd4, 0x7b, 0xaf, 0xe2, 0x88, 0x81, 0xe0, 0xa6, 0x7b, 0x7c, 0x70, + 0x10, 0x1a, 0x15, 0xe5, 0x82, 0x1b, 0xa5, 0x55, 0x25, 0xa5, 0x90, 0xb7, 0x2a, 0x9a, 0x33, 0x7d, 0x04, 0x40, 0x04, + 0x58, 0x25, 0xea, 0xff, 0xf0, 0xa5, 0x31, 0x1e, 0x3c, 0xf0, 0x35, 0xb9, 0x8e, 0xad, 0xf7, 0x4f, 0x6b, 0xa4, 0xd5, + 0xc6, 0x31, 0xa9, 0x55, 0x2f, 0x5b, 0xc5, 0xcb, 0xee, 0x75, 0x2a, 0x06, 0xcf, 0xff, 0xe7, 0x3e, 0x40, 0x8d, 0x68, + 0x29, 0x83, 0x5b, 0x57, 0x03, 0x34, 0x3e, 0x1c, 0x0b, 0xdf, 0xf8, 0x21, 0xe3, 0x7c, 0x30, 0x43, 0x47, 0xb5, 0x39, + 0x38, 0x20, 0x38, 0xaa, 0x7b, 0x34, 0x26, 0xcc, 0xc2, 0xb9, 0x07, 0x81, 0xea, 0x13, 0xf7, 0x19, 0xd7, 0x5e, 0xd0, + 0x26, 0xf0, 0xc9, 0xba, 0xae, 0x29, 0x02, 0x5c, 0xc4, 0xc6, 0x44, 0x0c, 0x71, 0xd9, 0x24, 0x52, 0xdf, 0x8c, 0x41, + 0x01, 0x50, 0x3c, 0xad, 0x48, 0x2e, 0x5d, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, + 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, + 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, + 0x19, 0x7f, 0x4a, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, 0x9e, 0xc3, 0xa7, 0xbc, 0x9c, 0x84, + 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, + 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, + 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, + 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, + 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, + 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, + 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, + 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0x7c, 0xbf, 0xc1, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0xf2, + 0x16, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, + 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, + 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x24, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, + 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, 0x99, 0xe4, 0xed, 0x12, 0x8e, 0xba, + 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, + 0xf7, 0xbe, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, + 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, + 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, + 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0xa7, + 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, 0xf3, 0x9a, 0x5d, 0x3f, 0x16, 0x6c, + 0xc7, 0x76, 0x8f, 0x11, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, 0x2f, 0xdc, 0xf2, 0x25, 0x80, 0x07, + 0xb2, 0x18, 0x50, 0x7c, 0x96, 0xde, 0x2f, 0x2c, 0x01, 0x35, 0xf9, 0x0d, 0x5f, 0x7b, 0x6f, 0x29, 0x75, 0x01, 0x7f, + 0x0e, 0x28, 0x7d, 0x92, 0x73, 0xef, 0x76, 0x78, 0xe3, 0x5f, 0x3c, 0x01, 0xe7, 0x89, 0xd5, 0x70, 0x01, 0x7f, 0x15, + 0x7c, 0xe8, 0xdd, 0x0e, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x35, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x05, + 0x39, 0xc3, 0x3f, 0x7e, 0xd7, 0x18, 0xac, 0xbf, 0x05, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0xce, 0x04, + 0xd8, 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xb3, 0x16, 0xf4, 0xe7, 0x03, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, + 0xf9, 0x01, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x53, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x57, 0xae, 0xc1, + 0x8e, 0xd7, 0xc9, 0x91, 0xa5, 0xf0, 0xac, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, + 0xe5, 0xb9, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0e, 0x72, 0x19, 0x1a, 0xf3, 0x0e, 0xd9, 0x30, 0x94, 0x0f, 0x2d, + 0x32, 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xbd, 0xf6, 0x72, 0xe0, + 0x3d, 0x88, 0xfc, 0x46, 0xba, 0x94, 0x4b, 0x6c, 0x74, 0xe2, 0x58, 0x16, 0xda, 0x79, 0x5c, 0x7f, 0x1d, 0x83, 0xfa, + 0xbd, 0xd2, 0x6f, 0x50, 0xce, 0xfe, 0x20, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xbf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, + 0xfe, 0x3f, 0x63, 0x0a, 0xa5, 0xbf, 0x4e, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, + 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x57, 0x26, 0xf8, 0xf0, 0x57, 0xed, 0x5c, + 0x9b, 0xf3, 0xf1, 0x24, 0xbf, 0xb2, 0xf6, 0x6e, 0xc7, 0x8b, 0xc4, 0x28, 0xc6, 0x72, 0x5f, 0x75, 0xb3, 0x72, 0xa2, + 0x92, 0x03, 0x23, 0x5d, 0x93, 0xbd, 0x5c, 0xc9, 0xba, 0x9d, 0x6e, 0x25, 0x10, 0x51, 0x05, 0xde, 0x63, 0x5c, 0xc5, + 0x3e, 0x82, 0xe9, 0xba, 0xe3, 0x32, 0xda, 0xf1, 0x9e, 0xf1, 0xea, 0x44, 0x59, 0xc1, 0xed, 0x46, 0xb4, 0x27, 0x74, + 0xf4, 0xd3, 0xa4, 0xb6, 0x2c, 0x1c, 0x80, 0xdc, 0x25, 0x8c, 0x65, 0x43, 0xb0, 0x62, 0x50, 0xfa, 0x7a, 0x4d, 0xc9, + 0xb2, 0x00, 0x8b, 0xce, 0x2e, 0x23, 0x10, 0xc3, 0xba, 0x69, 0x4e, 0xe8, 0x78, 0xe9, 0xe2, 0xbc, 0xd7, 0x2a, 0x52, + 0xf0, 0x8c, 0x16, 0x1d, 0x73, 0xd3, 0x91, 0x6e, 0x8c, 0xf6, 0xf6, 0xb9, 0x41, 0x48, 0xf1, 0xfc, 0x81, 0xad, 0xd6, + 0xc5, 0x45, 0xe2, 0x15, 0x32, 0xd1, 0x82, 0x58, 0x8a, 0xc0, 0x8c, 0x17, 0x9a, 0x46, 0x98, 0xa0, 0x4c, 0x09, 0x16, + 0xad, 0xd1, 0xa1, 0xfd, 0x61, 0x09, 0xbb, 0xc7, 0x18, 0x01, 0x02, 0x55, 0xa6, 0x5f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, + 0xc5, 0x06, 0x68, 0xab, 0x18, 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x43, 0x9a, 0xdf, 0xfe, 0x0b, 0x8b, 0xb1, 0x3d, 0x81, + 0xd8, 0xde, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xa8, 0x1d, + 0x6b, 0xa9, 0x77, 0xac, 0xb5, 0xde, 0xb1, 0x6e, 0x1b, 0xfe, 0x2c, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, + 0x83, 0xa0, 0x19, 0x1b, 0x76, 0x03, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, + 0x60, 0x19, 0x51, 0x93, 0xef, 0x90, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0x77, + 0x8f, 0x23, 0xc8, 0xbd, 0xe3, 0xde, 0xdd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, + 0x4f, 0x10, 0xad, 0xec, 0x29, 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x1f, 0xdf, 0xb9, 0xdb, 0xda, 0xed, 0xe3, 0x3b, 0x56, + 0x8d, 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xe3, + 0x8e, 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0x8f, 0x33, 0x8d, + 0xe7, 0x70, 0x24, 0x9f, 0x8e, 0x35, 0x36, 0x08, 0xea, 0xfa, 0x9c, 0x41, 0xed, 0xd8, 0x7d, 0x4d, 0xd8, 0x65, 0xc7, + 0xbc, 0xd6, 0x35, 0x6f, 0xaf, 0x3c, 0x15, 0x1b, 0x02, 0x3a, 0x7c, 0xad, 0x6e, 0x90, 0x7f, 0x09, 0x9c, 0x22, 0x00, + 0xe4, 0x70, 0xbc, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0x77, 0xa8, 0xb5, 0xa8, 0x2c, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, + 0x8a, 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2e, 0x2e, 0x7e, 0x3d, 0x2d, + 0x94, 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x8e, + 0x94, 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf1, 0x84, 0xc5, 0x90, 0x08, 0xb0, 0xdd, + 0xa1, 0x62, 0x5b, 0xb8, 0x78, 0xc2, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, + 0x8e, 0x35, 0xd4, 0x6c, 0x6d, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x6e, 0xdb, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, + 0xeb, 0x3d, 0xaa, 0x0b, 0x60, 0xeb, 0xbf, 0x39, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, + 0x7a, 0x95, 0x2c, 0xfc, 0x9b, 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, + 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, + 0x97, 0x15, 0xdb, 0x05, 0xb1, 0x9d, 0xf0, 0x3b, 0x01, 0x53, 0x3e, 0x83, 0x20, 0xae, 0xe0, 0x06, 0xe2, 0xf0, 0xe4, + 0x9f, 0x83, 0xbb, 0xd6, 0x66, 0x7d, 0xc7, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, + 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, 0xb7, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, + 0x40, 0xfc, 0x74, 0x33, 0xe0, 0x77, 0x1d, 0x6b, 0xcb, 0xbb, 0x66, 0x0b, 0xb6, 0x83, 0x4b, 0x50, 0xd3, 0x5e, 0xf6, + 0x27, 0x95, 0x0b, 0xda, 0xb1, 0x4b, 0xe2, 0xe1, 0x8c, 0x59, 0xa5, 0xcc, 0xac, 0x93, 0xea, 0x4a, 0x74, 0xc6, 0x74, + 0xd6, 0x7a, 0x3e, 0x57, 0xf3, 0x49, 0xa1, 0x41, 0xfd, 0xce, 0x89, 0x8f, 0xa8, 0xe8, 0x3c, 0x81, 0xad, 0x65, 0x05, + 0xb1, 0xda, 0xe7, 0x60, 0xad, 0xd5, 0x2e, 0xfd, 0x5e, 0x3e, 0xe0, 0x36, 0xe5, 0xb0, 0x0e, 0x0c, 0x6a, 0x4e, 0xac, + 0xa8, 0x87, 0x6c, 0xc7, 0xb8, 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xf5, 0xb1, 0xa7, + 0xbf, 0x53, 0xfb, 0x17, 0xc2, 0x0f, 0xc6, 0xff, 0xa9, 0xdd, 0xd7, 0x5a, 0x8c, 0xca, 0x56, 0x39, 0x42, 0xe3, 0x6e, + 0x25, 0x4d, 0x96, 0x9f, 0x84, 0x27, 0xac, 0x05, 0xcf, 0x72, 0xbd, 0x44, 0xb3, 0x02, 0x56, 0x58, 0xcb, 0x24, 0x5c, + 0x61, 0xac, 0x96, 0xb6, 0xfa, 0x16, 0x4d, 0x73, 0x7c, 0x38, 0xd7, 0x06, 0x65, 0xca, 0xd9, 0x19, 0xb1, 0x1a, 0x2e, + 0xc3, 0xd2, 0x84, 0x22, 0x64, 0xf7, 0x76, 0x70, 0x63, 0xa7, 0x2c, 0xa5, 0x0c, 0xe7, 0x18, 0x4c, 0x78, 0x24, 0x46, + 0x55, 0xbe, 0xbf, 0x2f, 0x29, 0x72, 0xda, 0x96, 0x83, 0x2a, 0x84, 0x7d, 0x24, 0x51, 0x02, 0xb7, 0x22, 0x2d, 0x14, + 0x29, 0x8b, 0xbf, 0x1d, 0xa0, 0x0b, 0xbc, 0x80, 0xba, 0x1a, 0x75, 0xfb, 0xc3, 0x11, 0x0f, 0x1f, 0x98, 0xfa, 0xc0, + 0x88, 0x25, 0x81, 0xda, 0x9e, 0x65, 0xe9, 0x2d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, + 0x1b, 0xe9, 0x0d, 0xad, 0xc1, 0x23, 0xb4, 0xa6, 0x3c, 0x77, 0x52, 0x6d, 0xd2, 0x79, 0x47, 0xc8, 0xb1, 0xfa, 0xd6, + 0x12, 0x46, 0xbb, 0xa2, 0x17, 0xf7, 0x8e, 0xde, 0xf3, 0x74, 0xd5, 0x73, 0x7f, 0xe2, 0x8a, 0x79, 0x72, 0x1b, 0x81, + 0xba, 0x15, 0x54, 0xb7, 0x77, 0x2a, 0xc1, 0x82, 0x25, 0xed, 0x3e, 0x7e, 0x3b, 0x6b, 0x07, 0xa2, 0x32, 0x56, 0xe9, + 0x5b, 0x92, 0xb0, 0x27, 0x06, 0x9d, 0x42, 0x55, 0x6e, 0x77, 0x47, 0x5b, 0xe0, 0x3a, 0x66, 0x29, 0x7a, 0x66, 0x8b, + 0xdc, 0x2d, 0xff, 0xee, 0xb9, 0x22, 0x67, 0xbf, 0x04, 0x04, 0xa7, 0xe6, 0x1b, 0xe2, 0xcb, 0x11, 0x1e, 0x55, 0xb7, + 0xc0, 0x71, 0xfa, 0x0e, 0xe0, 0x1f, 0x0e, 0x97, 0xa0, 0x09, 0x88, 0x05, 0xeb, 0xa5, 0x71, 0x8f, 0xf5, 0xe2, 0x62, + 0x73, 0x9b, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, + 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, + 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, + 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, + 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, + 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0x7f, 0x19, 0xff, 0xd0, 0x33, 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, + 0xaf, 0xbf, 0x42, 0x00, 0x1c, 0x9e, 0x4d, 0xbd, 0xcb, 0x31, 0x64, 0x95, 0x65, 0x04, 0x92, 0x9f, 0x18, 0x7c, 0xf9, + 0x02, 0xa0, 0xea, 0x33, 0x5d, 0xab, 0xc9, 0x51, 0x7b, 0xcc, 0xa1, 0x2b, 0x06, 0x80, 0x6d, 0x58, 0xa2, 0xaa, 0x16, + 0x36, 0x61, 0x71, 0xfb, 0x19, 0x46, 0x73, 0xd9, 0xf4, 0x82, 0x06, 0xea, 0x11, 0x82, 0x5f, 0x5a, 0x0f, 0xad, 0xb5, + 0x4c, 0x39, 0x74, 0x6d, 0x14, 0x55, 0x36, 0xd4, 0x25, 0xac, 0xd6, 0x22, 0xaa, 0x89, 0x22, 0xe5, 0x92, 0x51, 0x14, + 0x4b, 0x15, 0xec, 0x33, 0x71, 0x0b, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x16, 0x10, 0xd6, 0xc2, 0x5a, 0x48, + 0x67, 0x50, 0x7b, 0xa7, 0x1f, 0x29, 0x7f, 0x79, 0x21, 0xb7, 0x73, 0x0b, 0x45, 0xb8, 0x3d, 0x07, 0xe5, 0x4d, 0x5d, + 0x95, 0x8a, 0x68, 0xb4, 0x04, 0x4a, 0x99, 0x13, 0x44, 0x16, 0x20, 0x80, 0xe3, 0x06, 0x02, 0x9f, 0xd7, 0xf8, 0x04, + 0x1a, 0x85, 0x40, 0x7e, 0x60, 0x15, 0xae, 0x3d, 0xa4, 0xa5, 0xd6, 0x88, 0x28, 0x11, 0x3f, 0xba, 0x7a, 0x8e, 0xed, + 0xab, 0xa7, 0xb1, 0xb6, 0x94, 0x26, 0x88, 0x9f, 0x58, 0x6c, 0x21, 0x26, 0x88, 0xea, 0x10, 0x1d, 0xc1, 0x72, 0x42, + 0x88, 0xc2, 0x9f, 0x42, 0x3f, 0x35, 0xf0, 0x97, 0x6c, 0x59, 0xe4, 0x35, 0xc1, 0x62, 0x56, 0x0c, 0xd0, 0xaa, 0x08, + 0x3c, 0xd3, 0xd9, 0x52, 0x99, 0xd3, 0x3c, 0x3a, 0xb2, 0x83, 0xf3, 0xae, 0x83, 0xbd, 0xf4, 0x65, 0xec, 0x64, 0xd9, + 0x34, 0x6a, 0x63, 0x43, 0x24, 0xbc, 0x22, 0xbf, 0xce, 0x52, 0xe3, 0x1c, 0x99, 0xcb, 0xf5, 0x5d, 0x17, 0xb7, 0xb7, + 0xb4, 0x4d, 0x58, 0x85, 0x08, 0x75, 0xdb, 0x50, 0xb9, 0x14, 0x66, 0x63, 0xd3, 0x34, 0xc0, 0x17, 0x8a, 0x4a, 0xa5, + 0x2a, 0xb5, 0x95, 0x4a, 0x4e, 0x78, 0xd7, 0x37, 0xb5, 0x48, 0x5d, 0x11, 0x6c, 0x63, 0x86, 0x7a, 0x28, 0x37, 0x6a, + 0xec, 0xdb, 0x8e, 0x55, 0x7a, 0x87, 0x09, 0x72, 0x46, 0x5e, 0xe4, 0xe0, 0xa2, 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, + 0x83, 0x86, 0x4f, 0x0b, 0xcb, 0x3d, 0x94, 0x80, 0xd9, 0x51, 0xc3, 0xa3, 0x08, 0x81, 0x88, 0x4b, 0x65, 0x5f, 0x31, + 0xf1, 0x7b, 0x0a, 0x66, 0xc9, 0x84, 0xee, 0x45, 0x2c, 0x8b, 0xd0, 0xc6, 0x27, 0x49, 0x32, 0xf5, 0x34, 0x05, 0x37, + 0x72, 0x19, 0xe6, 0x68, 0x84, 0x96, 0x7c, 0xe4, 0x40, 0xfa, 0x5a, 0x4e, 0x25, 0xf8, 0x88, 0x3a, 0x05, 0x1c, 0xcf, + 0xcf, 0x0b, 0xeb, 0x27, 0xcb, 0x25, 0xe6, 0xb2, 0x36, 0xff, 0x65, 0x47, 0xc7, 0x60, 0x97, 0xa7, 0x89, 0xe3, 0xea, + 0x3f, 0xaa, 0x92, 0xe2, 0xfe, 0x75, 0x9a, 0x03, 0x8a, 0x60, 0x66, 0x4f, 0x31, 0x3e, 0xf6, 0x59, 0xa6, 0x80, 0xbf, + 0x5d, 0x6f, 0x2d, 0x99, 0xd8, 0x25, 0xed, 0xe6, 0xca, 0xf8, 0xa5, 0x36, 0xec, 0x38, 0x38, 0x37, 0x00, 0xc5, 0x59, + 0xa3, 0xc3, 0xf2, 0x5a, 0xb7, 0xad, 0x0a, 0x15, 0xa8, 0xf5, 0x7f, 0x76, 0x0b, 0x53, 0xde, 0xe6, 0xa5, 0xf2, 0x36, + 0x0f, 0x4d, 0x80, 0x40, 0x64, 0x86, 0x3c, 0x6b, 0x3a, 0x26, 0x89, 0x7b, 0x47, 0x4a, 0xda, 0x77, 0xa4, 0xf8, 0xc1, + 0x3b, 0x12, 0xf2, 0x2d, 0xa1, 0x23, 0xfb, 0x92, 0x93, 0x13, 0x28, 0x33, 0xd8, 0xcb, 0x6b, 0x26, 0xfb, 0x07, 0xb4, + 0x17, 0xce, 0x65, 0x79, 0xc5, 0xdf, 0x08, 0x6f, 0xed, 0x4f, 0xd7, 0xa7, 0x5d, 0x55, 0x6f, 0xbe, 0x31, 0x33, 0x0f, + 0x87, 0xe2, 0x70, 0xa8, 0x4c, 0xd0, 0xee, 0x82, 0x8b, 0x41, 0xce, 0xee, 0xdc, 0xf8, 0xf8, 0x6b, 0x8e, 0x22, 0xb6, + 0x52, 0x1e, 0x49, 0x17, 0x2a, 0x31, 0xbc, 0x34, 0xf0, 0x30, 0x3b, 0x3e, 0x9e, 0xec, 0xae, 0xee, 0x26, 0x83, 0xc1, + 0x4e, 0xf5, 0xed, 0x96, 0xd7, 0xb3, 0xdd, 0x9c, 0xdd, 0xf3, 0x9b, 0xe9, 0x36, 0xd8, 0x37, 0xb0, 0xed, 0xee, 0xae, + 0xc4, 0xe1, 0xb0, 0x7b, 0xca, 0x17, 0xfe, 0xfe, 0x1e, 0x01, 0x9d, 0xf9, 0xf9, 0xb8, 0x8d, 0xf1, 0xf3, 0xa6, 0xed, + 0xaa, 0xb5, 0x03, 0x78, 0xfa, 0x57, 0xde, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0xf7, 0xfc, 0x1e, 0xfc, 0xf3, 0x71, 0x93, + 0x44, 0xea, 0x13, 0xed, 0x32, 0xf9, 0x06, 0x1c, 0xc8, 0x77, 0x3e, 0xfb, 0xc4, 0xef, 0x67, 0xcb, 0x39, 0x2f, 0x0e, + 0x87, 0x47, 0xd3, 0x10, 0xc9, 0x9a, 0xc2, 0x8a, 0x58, 0x52, 0x3c, 0x3f, 0x08, 0x8f, 0xdf, 0x8b, 0xc8, 0x10, 0x69, + 0xb9, 0x77, 0x87, 0xec, 0x0d, 0x8b, 0xfc, 0x00, 0x3e, 0xc8, 0x76, 0xfe, 0x44, 0xd6, 0x94, 0xee, 0x17, 0xef, 0xfd, + 0xc3, 0x81, 0xfe, 0xfa, 0xe4, 0x1f, 0x0e, 0x8f, 0xd8, 0x3d, 0x82, 0xa3, 0xf3, 0x1d, 0xf4, 0x8f, 0xbe, 0x75, 0x40, + 0x55, 0x86, 0xd7, 0xb3, 0xcd, 0xdc, 0x7f, 0xba, 0x62, 0xb7, 0xc0, 0x85, 0xa2, 0xbc, 0xd0, 0xde, 0xb0, 0x7b, 0xf4, + 0x3a, 0x23, 0x27, 0xa2, 0xd9, 0x6e, 0xee, 0xb3, 0x18, 0x9f, 0xab, 0xfb, 0x62, 0xf2, 0xcd, 0xfb, 0xe2, 0x8e, 0x6d, + 0xbb, 0xef, 0x8b, 0xf2, 0x4d, 0x77, 0xfd, 0x6c, 0xd9, 0x8e, 0xdd, 0xc3, 0x0c, 0xbb, 0xe6, 0x6f, 0x9a, 0x63, 0xc7, + 0xd8, 0x6f, 0xde, 0x18, 0x01, 0x94, 0xd9, 0x82, 0xc5, 0x82, 0x83, 0x52, 0xad, 0xda, 0x96, 0x44, 0x5e, 0xe9, 0x40, + 0xb5, 0x19, 0xc1, 0x7d, 0xb5, 0x90, 0x33, 0xcf, 0x0c, 0xf4, 0x6d, 0x85, 0x68, 0xe1, 0xb0, 0x01, 0x7f, 0xa3, 0xad, + 0x63, 0x0c, 0xd3, 0xac, 0x66, 0xda, 0x16, 0x75, 0xf9, 0x7d, 0xef, 0x99, 0xfc, 0x46, 0x06, 0xb6, 0x10, 0x49, 0xe1, + 0x38, 0xbe, 0x78, 0x72, 0xc2, 0x7f, 0xd5, 0xf2, 0xa8, 0xd5, 0x7e, 0xa1, 0xd4, 0xa7, 0xd7, 0x74, 0x44, 0x13, 0xf7, + 0xa2, 0x2d, 0xc3, 0x1a, 0x65, 0x4d, 0x2d, 0x1d, 0x86, 0x71, 0x0d, 0xfb, 0xf2, 0xc0, 0xa1, 0xef, 0x80, 0x40, 0x5b, + 0xa5, 0x52, 0xa0, 0x85, 0x63, 0x18, 0x85, 0x59, 0x48, 0x79, 0x58, 0x98, 0xa5, 0xbc, 0xc7, 0x02, 0x2d, 0x6e, 0xd5, + 0x3d, 0xa6, 0xb6, 0x5b, 0x10, 0x61, 0xf5, 0x96, 0x71, 0x7e, 0xd9, 0xa8, 0xc2, 0x6d, 0x01, 0x8a, 0x22, 0x28, 0x83, + 0x3d, 0xc9, 0x6d, 0x0b, 0x25, 0xcd, 0x46, 0x61, 0x2d, 0x6e, 0x8b, 0x72, 0xd7, 0x6b, 0xd8, 0x02, 0x2f, 0xa8, 0xfa, + 0x09, 0x61, 0x5b, 0xf6, 0xac, 0x43, 0xb9, 0x48, 0xff, 0x23, 0x4b, 0xcf, 0xf7, 0x5b, 0x73, 0xfe, 0xa7, 0xaf, 0xe8, + 0xa3, 0xf2, 0x3f, 0xbf, 0xa4, 0x9f, 0x0c, 0x96, 0x91, 0x53, 0xea, 0x97, 0x68, 0x74, 0x93, 0xe6, 0x84, 0xb1, 0xe5, + 0xeb, 0xa7, 0xdf, 0x21, 0x53, 0x90, 0x1c, 0x4a, 0xa9, 0xca, 0xc9, 0x1e, 0xfa, 0xc2, 0xeb, 0x3e, 0xcc, 0x04, 0x03, + 0x10, 0x5e, 0xa3, 0x4d, 0x35, 0x61, 0x12, 0x0f, 0xae, 0xe0, 0xff, 0x46, 0x10, 0x83, 0xf6, 0x89, 0xa2, 0x8e, 0x6d, + 0x23, 0x5d, 0xb7, 0x9d, 0x83, 0xe4, 0x4e, 0x5d, 0xf9, 0xa3, 0x72, 0xf2, 0x9f, 0x68, 0x88, 0xbc, 0xe2, 0x0a, 0xb1, + 0xb2, 0xe0, 0x12, 0x8b, 0xa1, 0x22, 0x05, 0xb8, 0x86, 0x20, 0x52, 0x16, 0x25, 0x85, 0x5b, 0x0e, 0xaa, 0x22, 0x00, + 0xe3, 0x6a, 0x75, 0xd4, 0x89, 0xf0, 0x71, 0x6b, 0x2d, 0x42, 0xb0, 0xa2, 0x51, 0x2b, 0x6b, 0x05, 0xbe, 0x20, 0x7d, + 0xe9, 0x50, 0x10, 0xd3, 0xa3, 0x90, 0xaa, 0xd2, 0xa1, 0x40, 0x9a, 0x43, 0xc5, 0x37, 0x06, 0x1b, 0x45, 0x45, 0x7a, + 0xfe, 0xd2, 0xa4, 0xe4, 0xd2, 0x98, 0xf1, 0x5e, 0x94, 0x91, 0xc8, 0xeb, 0xf0, 0x56, 0x4c, 0x0b, 0xe4, 0x1b, 0x3d, + 0x7e, 0x10, 0x5c, 0xc2, 0xbb, 0x21, 0xf7, 0x0a, 0xb0, 0x25, 0x60, 0x07, 0xb8, 0x57, 0x66, 0x94, 0xeb, 0xb4, 0xae, + 0xdf, 0x5a, 0x0f, 0xc5, 0x30, 0x7c, 0x6c, 0x09, 0x6c, 0x47, 0xeb, 0xe8, 0x48, 0x0f, 0x1f, 0xfe, 0xd7, 0x55, 0xcd, + 0x51, 0xa7, 0x72, 0x39, 0x3b, 0x9e, 0xb0, 0x14, 0x31, 0x83, 0xee, 0xaf, 0xdb, 0x6b, 0x01, 0x74, 0xbb, 0x2c, 0xe6, + 0xd9, 0x68, 0x27, 0xff, 0x96, 0x6e, 0xac, 0x28, 0x6d, 0xe2, 0x5d, 0xd6, 0x1b, 0xfb, 0xc3, 0xd1, 0x5f, 0x1e, 0xbf, + 0x9d, 0x10, 0xaa, 0xce, 0x86, 0xad, 0x75, 0x9c, 0xcb, 0xff, 0xfa, 0xeb, 0x98, 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, + 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, 0x5f, 0x6a, 0x9d, 0x30, 0x31, 0xb2, + 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0x5b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x3e, 0x59, 0x1b, 0x0d, 0xe6, 0x8a, 0xd7, 0xb3, + 0xf5, 0x5c, 0x2a, 0x9f, 0xc1, 0x94, 0xb3, 0x1c, 0x9c, 0x2c, 0x85, 0xdd, 0x91, 0x40, 0xd1, 0x9a, 0xa1, 0x6b, 0x7f, + 0x8a, 0xad, 0x7a, 0x91, 0x56, 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf6, + 0x47, 0xa5, 0x1f, 0x8c, 0x27, 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, + 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x05, 0xdf, 0xf8, 0xca, 0x07, 0xe3, 0x1a, 0xb5, 0xd5, 0xa0, 0xa0, 0x76, 0x74, + 0xcb, 0x63, 0x47, 0xef, 0x7c, 0x77, 0x42, 0x5f, 0xbd, 0xd0, 0xc2, 0xf1, 0x37, 0xce, 0xc8, 0x35, 0x5b, 0x75, 0xc8, + 0x11, 0xcd, 0xa4, 0x43, 0x88, 0x58, 0xb1, 0x35, 0xbb, 0x26, 0x95, 0x73, 0xe7, 0x90, 0x9d, 0x3e, 0x42, 0x95, 0x5e, + 0xeb, 0xe1, 0xed, 0x44, 0xe9, 0x6e, 0x8f, 0x77, 0x93, 0xef, 0xd9, 0x44, 0xc4, 0x60, 0x40, 0x1b, 0x84, 0x33, 0xb2, + 0x0e, 0x91, 0x4a, 0x07, 0x08, 0x81, 0x63, 0x02, 0x9a, 0xfe, 0xfb, 0x5b, 0x12, 0x05, 0x1c, 0x69, 0x23, 0x64, 0x2d, + 0x3b, 0x1c, 0x72, 0xd0, 0x28, 0x37, 0x7f, 0x7a, 0x85, 0x3a, 0xcd, 0x81, 0x79, 0xba, 0x84, 0x3d, 0x07, 0x8f, 0xf4, + 0xe2, 0xf8, 0x48, 0xff, 0xef, 0x68, 0xa2, 0xc6, 0xff, 0xb9, 0x26, 0x4a, 0x69, 0x91, 0x1c, 0xd5, 0xd2, 0x77, 0xa9, + 0xa3, 0xe0, 0x22, 0xef, 0xa8, 0x85, 0xec, 0x59, 0x36, 0x6e, 0x54, 0xf3, 0xfe, 0x7f, 0xad, 0xcc, 0xff, 0xd7, 0xb4, + 0x32, 0x4c, 0xc9, 0x8e, 0xa5, 0x9a, 0x79, 0xa0, 0x55, 0x0c, 0xb3, 0xd7, 0x24, 0x21, 0x32, 0x5c, 0x1a, 0xf0, 0xa3, + 0x0a, 0xf6, 0x71, 0x5a, 0xad, 0xb3, 0x70, 0x87, 0x4a, 0xd4, 0x1b, 0x71, 0x9b, 0xe6, 0xcf, 0xea, 0x7f, 0x8b, 0xb2, + 0x80, 0xa9, 0x7d, 0x5b, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, 0x63, 0x1b, 0x5f, 0xcb, 0xf1, 0xb4, + 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0x96, 0x92, 0x9c, 0xcb, 0xca, 0xe2, 0x1e, 0xa1, 0x9b, 0x7f, 0x2a, 0xcb, + 0xa2, 0xf4, 0x7a, 0x9f, 0x92, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, + 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, + 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, + 0x36, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, + 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xdb, 0x1c, 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, + 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, + 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x5c, 0xb6, 0x92, 0xb0, 0x6f, 0xdf, 0xb5, 0x53, 0x45, + 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0x4f, 0x19, 0x47, 0x92, 0x28, 0x11, 0xbc, 0xcd, 0x1b, 0x33, 0x0e, 0xaf, 0xda, + 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, + 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, + 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x0b, 0x89, 0x4b, 0x88, 0x97, 0xf9, 0x6a, 0x9a, 0x46, + 0xc1, 0xa3, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, + 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, + 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, + 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, + 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0xd7, 0x42, 0x75, 0xb0, 0x2d, 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, + 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, + 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, + 0xf8, 0xab, 0xcc, 0xc3, 0xb4, 0x9a, 0x95, 0x60, 0xce, 0x37, 0x50, 0x89, 0xf1, 0x64, 0x79, 0xc5, 0x37, 0x2e, 0x56, + 0x62, 0x32, 0x5b, 0xce, 0x27, 0x6b, 0x49, 0x35, 0x97, 0x7b, 0x6b, 0x96, 0xb1, 0x25, 0xec, 0x1f, 0x06, 0xf9, 0xd1, + 0x81, 0x1d, 0x4d, 0x35, 0x6d, 0x12, 0x60, 0x32, 0x9d, 0x73, 0x3e, 0xbc, 0x44, 0x34, 0x59, 0x9d, 0xba, 0x93, 0xa9, + 0x6a, 0x07, 0xd7, 0xe4, 0x4c, 0x4e, 0x8f, 0xd4, 0x53, 0xad, 0x7b, 0xc9, 0x47, 0xdb, 0x61, 0x35, 0xda, 0xfa, 0x01, + 0xb8, 0x75, 0x0a, 0x3b, 0x7d, 0x37, 0xac, 0x46, 0x3b, 0x5f, 0xc3, 0xee, 0x92, 0x42, 0xa0, 0xfa, 0x52, 0xd6, 0x64, + 0x2e, 0x5e, 0x17, 0xf7, 0x5e, 0xc1, 0x9e, 0xf8, 0x03, 0xfd, 0xab, 0x64, 0x4f, 0x7c, 0x9b, 0xc9, 0xf5, 0xb7, 0xb4, + 0x6b, 0x34, 0x66, 0x3a, 0x5e, 0xbb, 0x02, 0x2b, 0x34, 0x40, 0x7e, 0xc1, 0x8e, 0xf6, 0x2a, 0x07, 0x81, 0x00, 0xdd, + 0x4b, 0x70, 0x14, 0x05, 0x44, 0x4d, 0xab, 0xca, 0xa3, 0xd3, 0xbd, 0xbf, 0xc7, 0x37, 0x42, 0xc0, 0x26, 0x4f, 0xad, + 0x7b, 0xcb, 0xd8, 0x3f, 0x1c, 0x20, 0x84, 0x5e, 0x4e, 0xbf, 0xd1, 0x96, 0xd5, 0xa3, 0x1d, 0xcb, 0x7d, 0xc3, 0xa8, + 0xa7, 0x60, 0x0c, 0x43, 0x17, 0x56, 0x31, 0x92, 0x67, 0x40, 0xd6, 0xf8, 0x0d, 0xa2, 0x0b, 0x58, 0xf4, 0x7a, 0x9f, + 0x8e, 0x68, 0x10, 0x01, 0x95, 0x5e, 0x73, 0xd4, 0x22, 0x9f, 0xab, 0x42, 0xf4, 0xde, 0x5b, 0x3b, 0x6f, 0x66, 0x24, + 0xcb, 0xa4, 0x91, 0x6a, 0xb7, 0xb2, 0x58, 0x57, 0xde, 0xec, 0x84, 0x74, 0x31, 0xc7, 0x50, 0x19, 0x3c, 0x0e, 0x40, + 0xe9, 0xf9, 0xef, 0xd0, 0x2b, 0x19, 0x32, 0xcd, 0x12, 0xcd, 0xec, 0xae, 0xf1, 0x27, 0xab, 0xd4, 0x8b, 0x11, 0x31, + 0x1b, 0xd8, 0x42, 0xdc, 0x16, 0x95, 0x6e, 0x8b, 0x42, 0xd9, 0xa2, 0x48, 0x1f, 0x6a, 0x67, 0xba, 0x33, 0x0b, 0x9f, + 0x55, 0xd6, 0x4a, 0xc9, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, 0x40, 0x85, 0x90, 0xbf, 0x40, 0x44, 0x24, + 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, 0x46, 0x79, 0xc9, 0x93, 0xa3, 0x01, 0xa9, + 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xba, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, + 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, + 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, + 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, + 0xe9, 0xd9, 0x7f, 0xa4, 0x6e, 0xcf, 0xca, 0xc9, 0x5e, 0x74, 0x4e, 0xf6, 0xe9, 0x6c, 0x1e, 0x08, 0x2e, 0x77, 0xee, + 0xf3, 0x7c, 0xaa, 0xa7, 0x5d, 0xe5, 0x07, 0xad, 0x21, 0xb2, 0xc6, 0xae, 0xea, 0x5e, 0x57, 0xb0, 0x80, 0x25, 0xb8, + 0x5b, 0x2f, 0xcd, 0x7f, 0xc3, 0xee, 0xef, 0x05, 0xbd, 0x34, 0xff, 0x9d, 0xfe, 0xa4, 0x00, 0x0e, 0x40, 0x63, 0x6a, + 0xb7, 0xc0, 0x43, 0x0c, 0x15, 0x14, 0xee, 0x66, 0xe5, 0xdc, 0xab, 0x01, 0x0e, 0x93, 0xf4, 0x0d, 0xad, 0x5e, 0x69, + 0xb1, 0xeb, 0x65, 0xb2, 0x57, 0x80, 0x87, 0x2a, 0xe4, 0xe1, 0xe1, 0x10, 0x75, 0x0c, 0x3b, 0xa8, 0x23, 0x60, 0xd8, + 0x43, 0x68, 0x6c, 0x81, 0xe7, 0xe3, 0x87, 0x8c, 0xef, 0x05, 0xa8, 0x8d, 0x10, 0x1e, 0xaf, 0x16, 0x65, 0x88, 0x2d, + 0x7b, 0x85, 0x54, 0x52, 0xaf, 0x05, 0xa2, 0x8c, 0x56, 0x01, 0x6d, 0xb5, 0xc7, 0x2c, 0x8d, 0x1f, 0x21, 0x54, 0x2c, + 0xf5, 0x31, 0x84, 0x06, 0x0e, 0xbf, 0xc3, 0x01, 0x24, 0xf8, 0x92, 0x6b, 0xb2, 0xb9, 0x57, 0xf9, 0x1d, 0xed, 0xf3, + 0x87, 0xc3, 0xf9, 0x25, 0x82, 0xd2, 0xa5, 0xf0, 0x91, 0x4a, 0x44, 0xf5, 0x14, 0x37, 0x25, 0x64, 0xb3, 0x64, 0xa5, + 0x1f, 0xfc, 0x43, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, + 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, + 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, + 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, + 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, + 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, + 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, + 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, + 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, + 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, + 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, 0xe0, 0x4f, 0xc5, 0x68, 0x5d, 0x10, 0x20, + 0xb2, 0xd9, 0xbe, 0x3e, 0x54, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, + 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0xbd, 0xbd, 0xfd, 0x69, 0x90, 0x9d, 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, + 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, + 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0x4b, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, + 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, + 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, + 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, + 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, + 0x46, 0x69, 0xf5, 0xb3, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, + 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xeb, 0x34, 0xd8, 0x61, 0xa2, 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, + 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, + 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, + 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, + 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x6b, 0x8b, 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0xcf, + 0x8b, 0xed, 0x9b, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x67, 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, + 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, + 0x1c, 0xc7, 0x1f, 0xa1, 0x82, 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, + 0x59, 0xbf, 0x2f, 0x7f, 0x51, 0x17, 0x5d, 0x64, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, + 0xcf, 0x93, 0x69, 0xf2, 0x38, 0x0f, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc2, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, + 0xe9, 0x8b, 0xcf, 0x2b, 0x3f, 0xd0, 0xd9, 0x73, 0x93, 0x0c, 0x6f, 0x56, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, + 0x9f, 0x9d, 0xc1, 0xc6, 0xb9, 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x34, 0xc3, 0x75, 0xa9, 0xda, + 0xe8, 0xa3, 0x10, 0x9d, 0x43, 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x65, 0x52, 0x69, 0x23, 0x01, 0x74, + 0x0f, 0x93, 0x06, 0x5b, 0x0c, 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0x43, 0x25, 0x71, 0x68, 0x59, + 0x24, 0xff, 0xde, 0xf5, 0xf4, 0x15, 0x52, 0x77, 0xb2, 0x40, 0x66, 0x8c, 0x67, 0x79, 0xfc, 0x09, 0x08, 0xb3, 0x41, + 0x1b, 0x15, 0x85, 0x10, 0xb2, 0x41, 0x0c, 0x1a, 0xcf, 0xf2, 0xf8, 0xb9, 0xa2, 0xf1, 0x90, 0x8f, 0x22, 0x5f, 0xfd, + 0x55, 0xea, 0xbf, 0x42, 0x9f, 0x99, 0xe0, 0x11, 0xaa, 0x89, 0xfe, 0xdd, 0xf3, 0xd9, 0x1d, 0xa8, 0x0d, 0xa3, 0x30, + 0x33, 0xe5, 0x57, 0xbe, 0x29, 0xce, 0x5e, 0x7f, 0x45, 0x57, 0xd9, 0xd6, 0xfd, 0xe8, 0xe5, 0x11, 0x81, 0xb5, 0x31, + 0xba, 0xe2, 0xc6, 0x00, 0x72, 0x98, 0xbc, 0x5f, 0x51, 0x5a, 0x0e, 0x69, 0x10, 0x3a, 0x68, 0x08, 0xa3, 0x25, 0xd1, + 0x07, 0x12, 0x8b, 0x18, 0xc3, 0x0b, 0xf1, 0x8c, 0xd4, 0x64, 0xa2, 0x21, 0x5e, 0x11, 0xfb, 0x21, 0x5a, 0x72, 0x6a, + 0xa2, 0x1b, 0x61, 0x8a, 0x81, 0xc4, 0xce, 0x20, 0x39, 0x49, 0x6a, 0xe5, 0x17, 0xcf, 0x24, 0x61, 0x89, 0x9d, 0x87, + 0x18, 0x4c, 0x6a, 0xe9, 0x4e, 0x6f, 0xaa, 0xf4, 0xfc, 0x48, 0xcb, 0x41, 0xfb, 0x00, 0xec, 0x52, 0xd2, 0xfb, 0x27, + 0x85, 0x22, 0xde, 0x87, 0x71, 0x0c, 0xe1, 0x5b, 0x44, 0x75, 0x05, 0xce, 0xb5, 0x02, 0x8d, 0xd5, 0xc0, 0x43, 0x33, + 0xab, 0xe6, 0x43, 0x4e, 0x3f, 0x95, 0x96, 0x3f, 0x46, 0x34, 0x36, 0x5a, 0x37, 0x87, 0xc3, 0x9e, 0x56, 0xbd, 0x74, + 0x0e, 0xba, 0x6c, 0x26, 0x31, 0x71, 0x03, 0xe9, 0xfa, 0xd1, 0x6f, 0x26, 0xec, 0x45, 0x54, 0xc8, 0xa5, 0x10, 0x14, + 0xb4, 0x3a, 0x10, 0x38, 0x14, 0xde, 0xa2, 0xcc, 0x17, 0x31, 0x6d, 0x20, 0x0c, 0x3e, 0x3f, 0x90, 0x9f, 0x6f, 0x0a, + 0x52, 0xb1, 0x63, 0x5d, 0xfb, 0xfd, 0x65, 0xe9, 0x01, 0x9e, 0x9c, 0x49, 0xf2, 0xb4, 0x19, 0xc2, 0x8a, 0x00, 0x1a, + 0xb3, 0x9a, 0x2c, 0x4e, 0xb8, 0x32, 0x87, 0x2f, 0x2b, 0xaf, 0x64, 0x29, 0x53, 0xe7, 0xa9, 0x5e, 0x00, 0x51, 0xc7, + 0x1b, 0xb4, 0x22, 0xf5, 0x2b, 0x74, 0xf6, 0x9a, 0x95, 0x90, 0xf1, 0xf0, 0x9c, 0xf3, 0x74, 0x74, 0xcf, 0x12, 0x1e, + 0xe1, 0x5f, 0xc9, 0x44, 0x1f, 0x7e, 0xf7, 0x1c, 0x6e, 0xc6, 0x09, 0x8f, 0xdc, 0x66, 0xef, 0xab, 0x70, 0x05, 0x37, + 0xd3, 0x02, 0x90, 0xdc, 0x82, 0xa4, 0x09, 0x28, 0x21, 0x91, 0x09, 0x99, 0x35, 0x25, 0x7f, 0x6d, 0x69, 0x1b, 0xac, + 0x61, 0xd2, 0x79, 0xc0, 0x8b, 0x56, 0x1f, 0xad, 0x26, 0xda, 0x65, 0x96, 0xcf, 0x87, 0x38, 0x43, 0x35, 0xc7, 0xdd, + 0x19, 0xfc, 0x1c, 0xf0, 0x8a, 0x55, 0x4d, 0x3a, 0xda, 0x0d, 0xb8, 0xf0, 0xe4, 0x3a, 0x4f, 0x47, 0x5b, 0xfc, 0x25, + 0xf7, 0x07, 0x80, 0x0e, 0xa6, 0x2e, 0x81, 0x3f, 0x55, 0x5b, 0x4d, 0xa5, 0x7e, 0x6e, 0xed, 0xd7, 0x75, 0x67, 0xb5, + 0x72, 0xcf, 0xba, 0x0c, 0xed, 0x91, 0x21, 0x67, 0xcc, 0x80, 0x3f, 0x67, 0x2c, 0xf9, 0x73, 0xc6, 0x8a, 0x3f, 0x67, + 0xdc, 0x18, 0x19, 0x40, 0x09, 0xee, 0x25, 0x7f, 0xba, 0x47, 0xcc, 0x10, 0xab, 0x41, 0x25, 0xb0, 0xb2, 0x94, 0x73, + 0x1f, 0x39, 0xc5, 0x94, 0x53, 0x86, 0x97, 0x4e, 0x67, 0xee, 0x40, 0xce, 0x83, 0x99, 0x3b, 0x4c, 0xf6, 0xfa, 0xdc, + 0x88, 0x63, 0x69, 0x4c, 0x8a, 0x0a, 0xd2, 0x39, 0x1d, 0x6e, 0x5e, 0x1d, 0xe7, 0x09, 0xcb, 0xf8, 0xb8, 0x7d, 0xa6, + 0x40, 0x88, 0x2d, 0x9e, 0x21, 0x91, 0x52, 0x35, 0xcb, 0x6d, 0xfe, 0x70, 0xa8, 0x47, 0xf7, 0x7a, 0xa7, 0x87, 0x5f, + 0x09, 0xfb, 0x39, 0xf3, 0xec, 0x13, 0x04, 0x30, 0x49, 0xe4, 0x99, 0x84, 0xa3, 0x1f, 0xcb, 0xd1, 0xdf, 0x34, 0xfc, + 0x79, 0x86, 0xea, 0xee, 0x10, 0x98, 0xd8, 0xb2, 0x03, 0x87, 0xe0, 0x74, 0x55, 0x89, 0x04, 0x1c, 0x6c, 0x36, 0x2c, + 0xd2, 0x7b, 0x3c, 0xc4, 0xf9, 0xa0, 0xf0, 0x11, 0x1a, 0x66, 0xf4, 0x7e, 0x7f, 0x23, 0xbc, 0x4a, 0xb6, 0xf2, 0x70, + 0x48, 0x2c, 0x0d, 0x90, 0xa3, 0x8f, 0xa3, 0x3d, 0x4a, 0xa8, 0xfd, 0xa8, 0xd6, 0x9b, 0x4a, 0x3d, 0xc8, 0xcd, 0x2e, + 0x24, 0x06, 0x15, 0x4b, 0xf5, 0xe9, 0x95, 0xea, 0x43, 0xcd, 0x92, 0x43, 0xaa, 0xe3, 0x3e, 0x15, 0xa3, 0xb5, 0x9c, + 0x10, 0xe0, 0x3a, 0x48, 0x34, 0x3a, 0x00, 0xc6, 0xd9, 0x66, 0xcb, 0x4b, 0x6d, 0x9d, 0x28, 0x1d, 0xc7, 0xb9, 0x3e, + 0x8e, 0x0f, 0x07, 0x29, 0x66, 0x5c, 0x1e, 0x89, 0x19, 0x97, 0x0d, 0xc0, 0x9b, 0x75, 0x1e, 0xd4, 0x87, 0xc3, 0x25, + 0x5d, 0x8a, 0x4c, 0x67, 0x1b, 0xe5, 0x67, 0x3d, 0xba, 0x7f, 0x9c, 0xa0, 0xb9, 0xb7, 0xc2, 0xde, 0x8b, 0x64, 0x7b, + 0x26, 0xeb, 0xd4, 0xcb, 0xc8, 0xa7, 0x17, 0xee, 0xd9, 0x25, 0x57, 0x3f, 0xac, 0xbe, 0x9e, 0xfe, 0x26, 0xbc, 0x88, + 0x55, 0xb4, 0x5b, 0x97, 0x4c, 0xd8, 0x5b, 0x4a, 0x25, 0xad, 0xf2, 0xf2, 0xe9, 0xc6, 0x0f, 0x30, 0x33, 0xed, 0xe9, + 0x83, 0x6c, 0x44, 0xf5, 0x67, 0x25, 0x6a, 0x65, 0x98, 0x2c, 0x9c, 0x97, 0x4c, 0x3d, 0x19, 0xf0, 0x98, 0x95, 0x3c, + 0x92, 0x9d, 0xde, 0x18, 0x04, 0x01, 0xac, 0x73, 0xd2, 0xaa, 0x33, 0x8e, 0x46, 0xab, 0xca, 0xc5, 0xe9, 0x2a, 0x17, + 0x18, 0x6e, 0xb7, 0x66, 0x1b, 0x55, 0x67, 0xb9, 0xa9, 0x55, 0xca, 0x77, 0x00, 0x1f, 0xcb, 0x2a, 0x17, 0x74, 0x4c, + 0x99, 0x3a, 0x6f, 0x20, 0x18, 0x5b, 0xd5, 0xb8, 0x70, 0x6a, 0x5c, 0xf0, 0x88, 0xda, 0xdd, 0x34, 0xf5, 0x68, 0x0b, + 0x2c, 0xa5, 0xa3, 0x1d, 0x2f, 0x51, 0xa5, 0xf0, 0x0f, 0xc1, 0xf7, 0x61, 0x1c, 0x3f, 0x2f, 0xb6, 0xea, 0x40, 0xbc, + 0x29, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, + 0x92, 0xc2, 0xb9, 0xf9, 0xf3, 0x70, 0xa0, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, + 0xee, 0x44, 0x09, 0x8e, 0x5c, 0xf2, 0xaf, 0xc3, 0x41, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0xdb, 0x7f, 0x0d, 0xc6, 0x0c, + 0x5d, 0x9a, 0x80, 0x65, 0x63, 0x24, 0xff, 0x6a, 0x9a, 0x79, 0xc3, 0x64, 0xcd, 0x14, 0x8e, 0x43, 0xc3, 0x08, 0x69, + 0x40, 0xb7, 0x41, 0x6d, 0x78, 0x32, 0xdf, 0x54, 0xe5, 0x57, 0x77, 0xa4, 0xda, 0x0f, 0x86, 0x97, 0x13, 0x71, 0x4e, + 0x97, 0x24, 0xf5, 0x54, 0x42, 0x49, 0x08, 0x76, 0xe9, 0x03, 0x39, 0xb1, 0x02, 0xb2, 0x96, 0xb1, 0xfc, 0x56, 0x0f, + 0x08, 0xfd, 0xa7, 0xdd, 0x7a, 0xa1, 0xff, 0x34, 0xcd, 0x16, 0xea, 0xfa, 0xc3, 0xe4, 0xbe, 0xa3, 0xd7, 0x1f, 0x1c, + 0xde, 0xa9, 0xab, 0x8a, 0xab, 0x78, 0x54, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8a, 0x4d, 0xad, 0x96, 0xa7, 0xe3, + 0x30, 0x02, 0x33, 0x82, 0x02, 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xac, 0xe4, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, + 0x71, 0x3e, 0x6e, 0x81, 0x4a, 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0x9f, 0x55, 0x36, 0x76, 0x0b, 0xe4, 0x90, + 0x64, 0xb2, 0xb8, 0x1d, 0xdd, 0x88, 0x65, 0x51, 0x8a, 0xd7, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, + 0x89, 0xd2, 0xde, 0x44, 0x9a, 0xa0, 0xfb, 0x96, 0xad, 0x00, 0x64, 0x00, 0x45, 0x5d, 0xed, 0xd6, 0xe7, 0xfc, 0x1c, + 0x49, 0x33, 0x1c, 0x46, 0xb7, 0x4f, 0x6f, 0x83, 0xdb, 0xc1, 0x25, 0x6a, 0xa5, 0x2f, 0x59, 0xdc, 0xc2, 0xa0, 0xda, + 0x9b, 0x25, 0x1c, 0xd4, 0xcc, 0x5a, 0x1b, 0x81, 0x60, 0xb2, 0x87, 0x82, 0x8a, 0xb9, 0x82, 0x7d, 0x50, 0xb0, 0x96, + 0xbc, 0x0e, 0x0e, 0xb7, 0xf6, 0x65, 0xa5, 0xb8, 0x78, 0x72, 0x91, 0xb4, 0x2e, 0x2c, 0xe5, 0xc5, 0x93, 0x06, 0x0c, + 0x2e, 0x47, 0xd8, 0x54, 0x60, 0x92, 0x00, 0xd0, 0xad, 0x88, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, + 0xc1, 0x86, 0xdd, 0xc3, 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, + 0xe6, 0x5f, 0x33, 0x2f, 0x52, 0x02, 0x6e, 0x86, 0x28, 0x5f, 0x1b, 0x38, 0x99, 0xf4, 0xe4, 0x5a, 0xb2, 0x18, 0xb0, + 0xa0, 0xc1, 0x77, 0xd4, 0xfa, 0x3b, 0x93, 0x7f, 0xe3, 0xe9, 0xa1, 0x1f, 0xfc, 0x9a, 0x79, 0x4b, 0x9f, 0xbd, 0xad, + 0x64, 0xb4, 0x26, 0x89, 0xf2, 0xea, 0xe1, 0x12, 0xe4, 0x86, 0xe5, 0xe8, 0x9e, 0x2d, 0x41, 0x9c, 0x58, 0x8e, 0x12, + 0xca, 0xe8, 0x0a, 0xf7, 0x2a, 0xb3, 0x65, 0x22, 0x90, 0xe2, 0xc0, 0x52, 0xca, 0xbd, 0xc5, 0x3a, 0x58, 0xe2, 0xfe, + 0x44, 0x72, 0x01, 0x25, 0x0f, 0xa0, 0x5c, 0x29, 0x20, 0xe0, 0xd3, 0x01, 0x94, 0x2f, 0xe5, 0x45, 0xf8, 0x13, 0x27, + 0x6a, 0xb0, 0x1c, 0xdd, 0x37, 0xec, 0x67, 0x2f, 0xb4, 0xec, 0x0f, 0xb7, 0x5a, 0xd3, 0xb0, 0xe2, 0xb7, 0x30, 0x2d, + 0x26, 0x6e, 0x5f, 0xae, 0xec, 0xaa, 0xf8, 0x6c, 0xa5, 0xce, 0x6e, 0x6a, 0x48, 0xc2, 0xbe, 0x21, 0xab, 0x00, 0x07, + 0xab, 0x22, 0xee, 0x59, 0x97, 0xfb, 0x30, 0xfa, 0xb2, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, + 0x65, 0xa2, 0x13, 0x2d, 0x04, 0x57, 0x60, 0x10, 0xb8, 0x13, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, + 0x12, 0x42, 0xaa, 0xfb, 0x19, 0xa8, 0xed, 0xc4, 0x5d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, + 0xba, 0xc5, 0xa6, 0xab, 0xcd, 0xea, 0x23, 0x3a, 0x97, 0xb6, 0xdc, 0xfc, 0x84, 0x2d, 0xd6, 0x0a, 0x94, 0x4d, 0x48, + 0xda, 0xce, 0x79, 0x8e, 0xb2, 0x09, 0x2d, 0xed, 0x3d, 0xf5, 0xa8, 0x50, 0x9d, 0x6c, 0xbd, 0x54, 0x4d, 0x2d, 0xc2, + 0x6a, 0x71, 0x51, 0xf9, 0x01, 0xe8, 0xa6, 0xd2, 0xea, 0x59, 0x5d, 0xa3, 0x29, 0xd4, 0x6a, 0xe1, 0xb8, 0xd1, 0xce, + 0xa6, 0xcb, 0xf4, 0x16, 0x71, 0x56, 0xa5, 0x1d, 0xfa, 0x97, 0x4c, 0xbb, 0x5e, 0x76, 0xf4, 0x9b, 0x71, 0x75, 0x81, + 0x0b, 0xb1, 0x01, 0x9f, 0x73, 0x7f, 0x79, 0xbd, 0x27, 0x71, 0xcf, 0x3f, 0x1c, 0x90, 0x3d, 0xa9, 0xfd, 0xa1, 0xfa, + 0xd8, 0x15, 0x0c, 0x59, 0x18, 0xa5, 0xfe, 0x22, 0xe5, 0xbd, 0x47, 0x38, 0xee, 0x9f, 0xab, 0x1e, 0xfb, 0x57, 0xc6, + 0xf7, 0x75, 0xb1, 0x89, 0x12, 0x8a, 0x6a, 0xe8, 0xad, 0x8a, 0x4d, 0x25, 0xe2, 0xe2, 0x3e, 0xef, 0x31, 0x4c, 0x86, + 0xb1, 0x90, 0xa9, 0xf0, 0xa7, 0x4c, 0x05, 0x8f, 0x10, 0x4a, 0xdc, 0xac, 0x7b, 0xa4, 0xdd, 0x84, 0x38, 0xa5, 0x5a, + 0x94, 0x32, 0x19, 0xff, 0xd6, 0x4f, 0xa0, 0x3c, 0xa7, 0x68, 0x99, 0x7e, 0x54, 0xb8, 0x4c, 0xdf, 0xac, 0x8f, 0x4b, + 0xcf, 0x44, 0xa8, 0x33, 0x17, 0x9b, 0x5a, 0xa7, 0x63, 0xec, 0x94, 0x4e, 0x6d, 0xd8, 0xd7, 0x4a, 0x71, 0x59, 0x51, + 0xf8, 0x37, 0x12, 0x59, 0xf5, 0x8c, 0x38, 0xfe, 0x7b, 0xd6, 0x3e, 0xc3, 0x2a, 0xf0, 0xcb, 0x40, 0xde, 0x2f, 0x00, + 0x3e, 0xae, 0xeb, 0x32, 0xbd, 0xd9, 0x00, 0x6d, 0x08, 0x0d, 0x7f, 0xcf, 0x47, 0x06, 0x4c, 0xf7, 0x11, 0xce, 0x90, + 0x1e, 0xea, 0x9c, 0xd3, 0x59, 0x99, 0xce, 0xb9, 0x0a, 0x6b, 0x09, 0xf6, 0x72, 0xd2, 0xe4, 0x72, 0x5d, 0x82, 0x9a, + 0x09, 0xdc, 0x3e, 0xb4, 0x47, 0x84, 0x50, 0x9b, 0xb2, 0x9a, 0x5e, 0x42, 0xcd, 0x3b, 0x39, 0xed, 0x68, 0x52, 0x82, + 0xab, 0x86, 0xce, 0xca, 0xf5, 0x5f, 0x87, 0x43, 0xef, 0x26, 0x2b, 0xa2, 0x3f, 0x7b, 0xe8, 0xef, 0xb8, 0xfd, 0x98, + 0x7e, 0x85, 0x68, 0x19, 0xeb, 0x6f, 0xc8, 0x80, 0x8e, 0x27, 0xc3, 0x9b, 0x62, 0xdb, 0x63, 0x5f, 0x51, 0x83, 0xa5, + 0xaf, 0x1f, 0x1f, 0x41, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0x5f, + 0x21, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, 0xd7, 0xb2, 0xaf, 0x7c, 0xe7, 0x02, 0x60, + 0x65, 0x9f, 0xd8, 0x70, 0x4f, 0xfa, 0x53, 0xaa, 0x0f, 0xdb, 0xdf, 0x92, 0x05, 0x14, 0x5a, 0x58, 0x4f, 0xe5, 0xec, + 0xbc, 0x2d, 0x79, 0x95, 0x4d, 0xf7, 0x6b, 0xd8, 0xa3, 0xee, 0xd0, 0x6b, 0x2a, 0x38, 0xbf, 0x34, 0xa3, 0xf7, 0xc5, + 0x50, 0xa8, 0x8e, 0x3a, 0x77, 0x90, 0xdb, 0xd2, 0xba, 0xe4, 0xfc, 0x66, 0xe5, 0x8e, 0xc2, 0xfc, 0x2e, 0x04, 0xcf, + 0xb0, 0xee, 0xdd, 0xc5, 0x79, 0xef, 0x1f, 0xad, 0x39, 0xf2, 0xaf, 0x6c, 0x96, 0x22, 0x16, 0xc9, 0x1c, 0xac, 0x7e, + 0xe8, 0xe7, 0xb1, 0xdf, 0x06, 0x39, 0x1c, 0x37, 0x0d, 0xe8, 0xb0, 0x21, 0xb3, 0xf6, 0x25, 0x02, 0xa7, 0x1a, 0x41, + 0x9a, 0x9a, 0xa0, 0x66, 0x79, 0x88, 0xc4, 0x76, 0x29, 0xdb, 0x06, 0xb9, 0xee, 0x82, 0x69, 0x8e, 0xb4, 0x67, 0xf0, + 0xbe, 0x49, 0x93, 0x54, 0x68, 0x16, 0x8d, 0xae, 0x64, 0xfc, 0x3b, 0xd2, 0x66, 0x4a, 0xf6, 0xd8, 0x1a, 0x78, 0x2f, + 0x41, 0x39, 0x19, 0xa6, 0x18, 0xbe, 0xe3, 0xeb, 0x9d, 0x47, 0x17, 0xf1, 0xb7, 0x63, 0xb6, 0x49, 0xd9, 0x11, 0x4c, + 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xdd, 0x4d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, 0x53, 0x69, 0x73, 0x85, 0x6e, + 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, 0xe2, 0xb7, 0x60, 0x0e, 0x63, + 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, 0x02, 0x8c, 0xbe, 0xda, 0x16, + 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, 0xd0, 0xf9, 0x7d, 0x73, 0x53, + 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xf3, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, 0xad, 0x71, 0x9a, 0xf9, 0xdf, + 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x9f, 0x21, 0x7a, 0x5f, 0xb7, 0x72, 0x55, 0x6a, 0x37, + 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, 0x39, 0xff, 0x5c, 0xf5, 0xfb, + 0xde, 0x67, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, 0x6d, 0x4a, 0xd8, 0x90, 0xdb, + 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x6f, 0x39, 0xdf, 0xaf, 0x85, 0xbc, 0x59, 0xc9, + 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, + 0xfe, 0x8e, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, 0x5a, 0x82, 0x76, 0xc1, 0xa6, + 0xb0, 0x3a, 0x79, 0x68, 0xc8, 0xfb, 0xfd, 0x97, 0xb9, 0xd7, 0xe2, 0x75, 0x37, 0x70, 0x97, 0xa5, 0x87, 0x10, 0xc0, + 0x5a, 0x06, 0xca, 0x38, 0xc2, 0xa4, 0x8b, 0xbc, 0x46, 0xd9, 0x74, 0x22, 0xf0, 0x31, 0xcb, 0xae, 0x9c, 0x64, 0x1a, + 0x60, 0x46, 0x35, 0x85, 0x99, 0x00, 0x23, 0xf5, 0x01, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, + 0x65, 0x1c, 0xc5, 0x4c, 0x00, 0xb0, 0xf9, 0x00, 0xf2, 0x15, 0x5d, 0x1d, 0x92, 0x56, 0xaa, 0xbc, 0x5f, 0x67, 0x44, + 0x46, 0x93, 0x10, 0xcd, 0x6f, 0xe1, 0x81, 0x7d, 0xdb, 0xcc, 0xa8, 0x52, 0xcf, 0xa8, 0xca, 0x67, 0x38, 0x2c, 0x85, + 0x63, 0xc4, 0xff, 0x5b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, + 0x73, 0x38, 0xf4, 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0x14, 0x0f, 0x75, 0x65, 0x4d, 0x6b, 0x25, 0x05, 0x4e, 0x45, + 0x8d, 0x10, 0x21, 0xbc, 0x7f, 0x00, 0xcf, 0x6a, 0xea, 0xfb, 0x8d, 0x65, 0xa2, 0xfb, 0x92, 0x01, 0xe5, 0x0f, 0xc8, + 0xd7, 0x95, 0x14, 0x67, 0xd2, 0xe4, 0x21, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xb6, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, + 0x86, 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x3d, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xc7, 0x92, 0xa5, 0xd1, 0xc2, + 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x31, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, 0xea, + 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x0e, 0xd6, 0x93, 0x57, 0x5e, 0xe9, 0x4f, 0x85, 0x9c, 0xc3, + 0x46, 0x22, 0x28, 0xfc, 0x00, 0x57, 0x83, 0x95, 0x02, 0x06, 0x53, 0xdf, 0xc2, 0xd7, 0xc4, 0x73, 0x14, 0x3c, 0x0a, + 0xbb, 0x18, 0x5b, 0x2b, 0xdf, 0xf9, 0xa4, 0xa0, 0xdc, 0xb3, 0x62, 0xce, 0x2b, 0xe0, 0x5c, 0x06, 0x85, 0x30, 0x1d, + 0xcf, 0xf2, 0x7f, 0x26, 0x79, 0x3d, 0xb1, 0x21, 0x40, 0x06, 0x7f, 0x4a, 0x9c, 0x96, 0xee, 0xd0, 0x9d, 0x87, 0x9e, + 0x45, 0x1c, 0x36, 0x7a, 0xb4, 0x2e, 0x8b, 0x6d, 0x8a, 0x7a, 0x09, 0xf3, 0x03, 0xf9, 0x79, 0x4b, 0xbe, 0x0f, 0x51, + 0xbc, 0x0d, 0xfe, 0x96, 0xb1, 0x58, 0xe0, 0x5f, 0xff, 0xcc, 0x18, 0x4d, 0xb4, 0xa0, 0x4e, 0x1a, 0x24, 0x2a, 0x16, + 0xc9, 0x04, 0x60, 0x1d, 0xb9, 0xfa, 0xf0, 0x29, 0x31, 0xde, 0x9a, 0x0d, 0x0f, 0x7c, 0xb3, 0x02, 0x9d, 0xfa, 0xdc, + 0x5d, 0xd9, 0x9e, 0xae, 0x46, 0xaa, 0xaa, 0xf1, 0xb7, 0x54, 0x55, 0xe3, 0x6f, 0x29, 0x55, 0xe3, 0xb7, 0x8c, 0xe2, + 0x77, 0x2a, 0x9f, 0x21, 0x73, 0xb2, 0x89, 0x49, 0x3a, 0x7d, 0x6f, 0x38, 0xb1, 0xcb, 0x7e, 0xeb, 0x36, 0x91, 0x67, + 0x26, 0x52, 0xc8, 0xbd, 0x01, 0xa8, 0x99, 0xf8, 0x32, 0x37, 0x9c, 0x12, 0xe7, 0xe7, 0x1e, 0xae, 0xd8, 0xb4, 0xba, + 0xa6, 0x05, 0x0b, 0x6c, 0x5e, 0x66, 0x79, 0xe6, 0x09, 0x6c, 0x9b, 0x32, 0xeb, 0x87, 0xdc, 0x03, 0x08, 0x66, 0x52, + 0x13, 0x00, 0xd2, 0x42, 0x54, 0x0a, 0x91, 0x5f, 0xe3, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, + 0xdf, 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0x7f, 0xc9, 0x82, 0x34, 0x91, 0xab, 0xf4, 0x9f, 0x6e, + 0x90, 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, + 0x55, 0xca, 0x23, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0xbf, 0x97, 0x7a, 0x1a, 0xdd, 0x17, + 0x7b, 0x30, 0x06, 0xef, 0x00, 0xf0, 0x4c, 0x87, 0x06, 0x48, 0xdf, 0x33, 0xf2, 0x70, 0x9f, 0x5b, 0xf2, 0x93, 0xca, + 0xda, 0x24, 0x61, 0x45, 0xb1, 0x19, 0xc6, 0x08, 0x25, 0xe3, 0x34, 0xb6, 0x7e, 0xbf, 0xaf, 0xfe, 0xde, 0x61, 0x14, + 0x15, 0x15, 0x77, 0x8c, 0x46, 0x65, 0x55, 0x8f, 0xb6, 0x83, 0xc3, 0xe1, 0x3c, 0xb7, 0x71, 0xb4, 0xf5, 0x0a, 0xd8, + 0x5b, 0xa1, 0x52, 0xf6, 0x4a, 0x84, 0xe5, 0x87, 0x2b, 0xbf, 0xdf, 0x87, 0x7f, 0x65, 0xa4, 0x85, 0xe7, 0x4f, 0xf1, + 0xd7, 0xa2, 0x2e, 0x30, 0x3c, 0x83, 0xd6, 0x68, 0x05, 0xc1, 0x04, 0xff, 0xec, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x80, + 0x6e, 0x05, 0x7a, 0xd0, 0x70, 0x12, 0x27, 0xed, 0x0b, 0x89, 0xba, 0xbd, 0xd5, 0x69, 0xf4, 0x67, 0xc5, 0x72, 0x5e, + 0xc0, 0xe4, 0x70, 0x43, 0x9f, 0x56, 0xe1, 0xf6, 0x13, 0x3c, 0x7d, 0x0d, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, + 0xb8, 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x08, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, + 0x57, 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xaa, 0x56, 0xda, 0x59, + 0x94, 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x65, 0x82, 0x3e, 0xaf, 0xe4, 0x04, + 0x57, 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0xd3, 0x4b, 0xba, 0x21, 0xa3, 0xe7, 0xbc, + 0xe7, 0x45, 0xc3, 0xd0, 0xbf, 0xf0, 0x4a, 0x08, 0xdf, 0xc4, 0x6d, 0x1b, 0xa5, 0xb0, 0xbf, 0x09, 0x2c, 0x3e, 0x61, + 0xaf, 0xbc, 0xa5, 0x3f, 0x1d, 0x07, 0xe1, 0x10, 0xb9, 0xa1, 0x62, 0x0e, 0xec, 0x69, 0xc0, 0x62, 0x13, 0x5f, 0x6d, + 0x26, 0xf1, 0x60, 0xe0, 0xeb, 0x8c, 0xc5, 0x2c, 0x06, 0x1a, 0xe4, 0x78, 0x70, 0x39, 0xd7, 0x27, 0x84, 0x7e, 0x18, + 0x51, 0x39, 0x2a, 0xd0, 0x39, 0x88, 0x06, 0x4b, 0xc0, 0x53, 0x6f, 0x65, 0x83, 0x24, 0xe3, 0x18, 0x92, 0xb8, 0xd6, + 0x24, 0xd5, 0xe1, 0x84, 0xd6, 0x81, 0x8e, 0xab, 0x0b, 0xe8, 0x7c, 0x5c, 0xf7, 0x3e, 0x5e, 0x0d, 0x17, 0x54, 0xfa, + 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0x70, 0xb1, 0x0a, 0xb7, 0xaf, 0xe5, 0x03, 0xc7, 0x1d, 0x95, + 0x34, 0x04, 0x06, 0x6f, 0x0f, 0xdd, 0xcd, 0x8c, 0x77, 0xc8, 0xd1, 0x61, 0x9c, 0xc9, 0x21, 0x56, 0xad, 0xb8, 0x90, + 0xde, 0x08, 0xbe, 0x5d, 0x28, 0xc6, 0xb2, 0xb1, 0x4b, 0x43, 0x51, 0xf8, 0x37, 0x00, 0x3b, 0xd4, 0xfe, 0x4a, 0x25, + 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, 0x89, 0x3f, 0xb2, 0xc6, 0xba, + 0xe9, 0xfa, 0x82, 0xa9, 0x6a, 0x98, 0x74, 0x3b, 0x93, 0x58, 0x4e, 0x24, 0xa9, 0xed, 0x3e, 0x22, 0x06, 0x03, 0x1f, + 0x6c, 0xc4, 0x34, 0x13, 0xe1, 0x88, 0x47, 0x25, 0xb2, 0xe8, 0xf2, 0xdb, 0x88, 0x92, 0xb6, 0x2f, 0x2b, 0xb2, 0x05, + 0xc1, 0xf4, 0x24, 0xfa, 0x20, 0x49, 0x39, 0x15, 0x89, 0x34, 0x23, 0x04, 0xf8, 0xf1, 0xa4, 0xbc, 0xd2, 0x9f, 0x83, + 0xa6, 0x95, 0xe0, 0x25, 0x83, 0xe4, 0x91, 0xf8, 0x99, 0x14, 0xcc, 0x62, 0xac, 0x1a, 0x0c, 0xb0, 0x9c, 0xea, 0xb1, + 0x63, 0x92, 0xfe, 0x5b, 0xa7, 0x13, 0xf6, 0x33, 0x2f, 0xb7, 0xb5, 0xbc, 0x69, 0xee, 0x3d, 0xf3, 0x2a, 0x96, 0x6a, + 0x58, 0x06, 0xfd, 0xd7, 0x44, 0xbb, 0x60, 0x6b, 0xcb, 0x98, 0xb0, 0xea, 0x07, 0x90, 0xf6, 0x48, 0x97, 0x57, 0x0d, + 0x73, 0x26, 0x78, 0x74, 0x61, 0xcd, 0x83, 0xe8, 0x42, 0xf8, 0xc8, 0x65, 0x37, 0x49, 0xae, 0xc6, 0x13, 0x3f, 0x1c, + 0x0c, 0x14, 0x00, 0x2d, 0xad, 0x93, 0x62, 0x10, 0x3e, 0x16, 0x72, 0x20, 0x8d, 0x8e, 0xaa, 0x00, 0x8b, 0x65, 0x76, + 0x55, 0x4e, 0xb2, 0xc1, 0xc0, 0x07, 0xb1, 0x31, 0xb1, 0x1b, 0x9a, 0xcd, 0x7d, 0x76, 0xa2, 0x20, 0xab, 0xcd, 0x59, + 0x6b, 0xa6, 0x5b, 0x60, 0x00, 0x30, 0x88, 0x08, 0x96, 0xfb, 0xc4, 0xc8, 0x47, 0xd4, 0xe9, 0x29, 0x8c, 0x80, 0xe0, + 0x97, 0x13, 0x81, 0xc8, 0x45, 0x02, 0xf5, 0x00, 0x33, 0x01, 0x66, 0x54, 0x31, 0xbc, 0x04, 0x76, 0xf1, 0xdc, 0xbc, + 0x62, 0xd0, 0xbf, 0x68, 0x97, 0x48, 0x34, 0x95, 0x38, 0x1a, 0x23, 0xa7, 0xd2, 0x18, 0x19, 0x10, 0xbb, 0x38, 0xfe, + 0x3d, 0xa5, 0x47, 0x41, 0xca, 0x9e, 0x57, 0x86, 0x38, 0x1c, 0xc5, 0x57, 0xb0, 0x6a, 0x1c, 0x0e, 0xb5, 0x79, 0x3d, + 0x9d, 0xd5, 0xf3, 0x81, 0x08, 0xe0, 0xbf, 0xa1, 0x60, 0xbf, 0x6a, 0x2a, 0x72, 0x83, 0xd4, 0x79, 0x38, 0xa4, 0x20, + 0x9f, 0x1a, 0xab, 0x6c, 0xe5, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0x2f, 0x6a, 0x5c, 0xb7, 0x56, 0x37, 0x14, 0x12, + 0xad, 0x69, 0x52, 0x5c, 0x55, 0x93, 0x62, 0xc0, 0x73, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, 0xe7, 0x16, 0x08, + 0x93, 0xfe, 0x56, 0xdc, 0x21, 0x55, 0xe3, 0xae, 0xad, 0x76, 0xdb, 0xca, 0x86, 0x14, 0xcd, 0x87, 0x97, 0xb0, 0x4b, + 0xa7, 0x88, 0xb6, 0x5d, 0x12, 0x7c, 0x01, 0x5a, 0x56, 0x17, 0x22, 0x8f, 0xe9, 0x57, 0xc8, 0x2f, 0xc5, 0xf0, 0xaf, + 0xd2, 0xbd, 0x39, 0xb5, 0x41, 0x0e, 0x60, 0xbb, 0xf7, 0x70, 0x3b, 0x46, 0x0f, 0x64, 0xf0, 0x46, 0xc8, 0x39, 0xe7, + 0x97, 0x53, 0x6b, 0xc6, 0x44, 0xc3, 0x82, 0x95, 0xc3, 0xc8, 0x0f, 0x90, 0xf1, 0x72, 0x0a, 0xac, 0xec, 0x47, 0x45, + 0x5c, 0xfa, 0xc3, 0xc8, 0xbf, 0x78, 0x12, 0x64, 0xdc, 0x8b, 0x86, 0x1d, 0x5f, 0x80, 0xbd, 0xfa, 0xe2, 0x09, 0x8b, + 0x06, 0xbc, 0xba, 0xaa, 0xa7, 0x59, 0x30, 0xcc, 0x58, 0x74, 0x55, 0x0c, 0xc1, 0x87, 0xf6, 0x69, 0x39, 0x08, 0x7d, + 0xdf, 0xec, 0x1c, 0xc6, 0x98, 0x2c, 0x8f, 0xb0, 0x9f, 0xc1, 0x6d, 0x57, 0x4b, 0xcc, 0x60, 0xb2, 0xb9, 0x8d, 0x98, + 0xc1, 0x96, 0xbf, 0x78, 0x62, 0xb8, 0x84, 0xaa, 0xa7, 0x52, 0xb3, 0x51, 0xa0, 0x39, 0xb9, 0x42, 0x73, 0xb2, 0x12, + 0x6a, 0xc9, 0x27, 0x15, 0x4e, 0xd8, 0xf9, 0x24, 0x57, 0x76, 0xa3, 0x31, 0x06, 0x2e, 0xda, 0x5b, 0x93, 0x30, 0x32, + 0xd3, 0x59, 0x8a, 0x06, 0x2c, 0x3c, 0x13, 0xa7, 0x34, 0x06, 0xb4, 0x2f, 0x07, 0x96, 0x36, 0xe4, 0x17, 0x39, 0x33, + 0xd0, 0x36, 0xa4, 0x34, 0x6a, 0x06, 0xfe, 0x4c, 0x4d, 0x98, 0xdf, 0xc0, 0x4a, 0x04, 0x51, 0x5d, 0x80, 0x49, 0x92, + 0x93, 0xd1, 0x48, 0x59, 0x89, 0xe4, 0x1c, 0xf0, 0x3e, 0x80, 0x27, 0x8b, 0xd8, 0xd6, 0xfe, 0x94, 0xfe, 0x57, 0x87, + 0xcf, 0xa5, 0xff, 0x58, 0x00, 0x0b, 0xb9, 0x34, 0x88, 0x0c, 0x14, 0x0e, 0xa9, 0xe5, 0x18, 0x93, 0x38, 0x9e, 0x81, + 0x2f, 0xe1, 0x02, 0x4d, 0x01, 0xfd, 0x41, 0xcd, 0x28, 0x22, 0x0b, 0x7f, 0xf5, 0xec, 0xa6, 0xae, 0xf5, 0x3c, 0x73, + 0x5e, 0x83, 0x66, 0x06, 0x42, 0x7a, 0x9c, 0xaa, 0xb7, 0x21, 0xd1, 0x79, 0xf9, 0x56, 0xbf, 0x4c, 0x88, 0x64, 0x61, + 0xe4, 0xe9, 0xfb, 0x1c, 0xcc, 0x23, 0x8a, 0xd0, 0xc1, 0x95, 0x79, 0x38, 0x9c, 0x0b, 0x0a, 0xdf, 0x51, 0x9e, 0x0f, + 0x38, 0xcd, 0x92, 0x04, 0xb4, 0x81, 0x2c, 0x37, 0x65, 0xae, 0x92, 0x96, 0xa9, 0x7b, 0x0f, 0x56, 0x82, 0x0a, 0xdd, + 0x9c, 0x82, 0x42, 0x19, 0x09, 0x4a, 0x69, 0x35, 0x08, 0xa5, 0x3a, 0x2c, 0x82, 0xc8, 0x21, 0x0b, 0x01, 0x37, 0x53, + 0xd1, 0x68, 0x49, 0xc3, 0x23, 0x9c, 0x1b, 0x28, 0x04, 0x20, 0xb1, 0xa7, 0x8a, 0x32, 0x2e, 0x87, 0x80, 0x8f, 0x12, + 0x0e, 0x71, 0xd6, 0xa4, 0x2d, 0xcf, 0x41, 0x1c, 0xcb, 0x25, 0xbf, 0xad, 0x10, 0x0c, 0x22, 0xf4, 0x19, 0xf2, 0x27, + 0xcb, 0xf9, 0x77, 0xe3, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0x9b, 0xf9, 0x04, 0xe2, 0x5b, 0x6e, + 0xe6, 0xc7, 0x18, 0x22, 0x0b, 0x7f, 0x70, 0x3b, 0x94, 0x5c, 0x51, 0xe8, 0xb2, 0x1e, 0x91, 0x22, 0x7b, 0xba, 0xe6, + 0x08, 0x82, 0x03, 0xad, 0x1a, 0x64, 0x68, 0x24, 0xbe, 0x78, 0x02, 0x59, 0x83, 0x35, 0x7f, 0x5e, 0x91, 0xb3, 0xba, + 0x3f, 0xd9, 0x40, 0x35, 0xc9, 0x64, 0xad, 0xa8, 0x9c, 0xbf, 0x5d, 0x95, 0xe5, 0xc9, 0xaa, 0x0c, 0x57, 0x83, 0xae, + 0xaa, 0x2c, 0x39, 0x52, 0x1b, 0xa0, 0x35, 0x5d, 0x21, 0x86, 0x42, 0xd6, 0x60, 0x69, 0x55, 0x65, 0x4d, 0x7d, 0x02, + 0x81, 0x3e, 0xc0, 0x32, 0x6a, 0xf6, 0xd3, 0xe1, 0x2f, 0xc1, 0x2f, 0x2a, 0x64, 0xa9, 0x4e, 0xeb, 0x4c, 0xfc, 0x16, + 0x2c, 0x19, 0xfe, 0xf1, 0x7b, 0xb0, 0x06, 0x2c, 0x01, 0xb2, 0xdc, 0x6d, 0x6c, 0xb4, 0x5e, 0x15, 0x3f, 0x57, 0xeb, + 0x8b, 0x7e, 0xeb, 0x36, 0x51, 0x2b, 0xc0, 0x08, 0x85, 0x16, 0x01, 0xb6, 0x7a, 0xe0, 0x9e, 0x82, 0x1f, 0x88, 0xe1, + 0x5c, 0x93, 0xd6, 0xd4, 0x09, 0xaf, 0xb3, 0x71, 0x24, 0xa2, 0x7a, 0x0b, 0x17, 0xf7, 0x7a, 0x6b, 0xf1, 0x37, 0x2a, + 0x10, 0x00, 0x59, 0x4c, 0xb1, 0x76, 0xde, 0x90, 0x5e, 0x19, 0x76, 0x12, 0x7a, 0x6f, 0xd8, 0x09, 0xe4, 0xc5, 0x61, + 0xa7, 0xd0, 0x25, 0xda, 0x4e, 0x91, 0x9a, 0x68, 0x3b, 0x69, 0xb1, 0x0a, 0x4b, 0x08, 0x7e, 0xd5, 0xde, 0x3a, 0xca, + 0xf6, 0x45, 0x96, 0x30, 0x6d, 0x01, 0xa3, 0xdc, 0xaa, 0xcf, 0x9c, 0x22, 0x56, 0xca, 0xde, 0xe9, 0xa4, 0xca, 0x5d, + 0xe4, 0x53, 0xab, 0x29, 0x32, 0xf9, 0xf9, 0x71, 0x8b, 0xe4, 0x93, 0xd7, 0xed, 0x86, 0xc9, 0xf4, 0x0f, 0x47, 0x5f, + 0x40, 0x57, 0x64, 0xa7, 0x4f, 0x20, 0x20, 0x53, 0x41, 0xb5, 0xba, 0x55, 0x4c, 0xf3, 0x76, 0x95, 0xdd, 0x5e, 0x28, + 0x31, 0x9c, 0xce, 0x4e, 0xc2, 0xa3, 0xcd, 0x90, 0x81, 0x43, 0x10, 0x28, 0x84, 0x8a, 0x62, 0x78, 0x04, 0x6a, 0x8d, + 0xe4, 0x03, 0xfc, 0x68, 0x77, 0x2a, 0x88, 0xd4, 0x6e, 0x2a, 0x6e, 0x9c, 0xdc, 0x74, 0xbd, 0x14, 0xa8, 0x75, 0x4a, + 0x56, 0x00, 0x25, 0x44, 0xfd, 0x49, 0x6c, 0xeb, 0x6b, 0xb8, 0x62, 0xf3, 0x7d, 0xa3, 0xe8, 0xc9, 0xf5, 0x29, 0xea, + 0x56, 0x5c, 0x9d, 0xa6, 0xad, 0xe6, 0xd8, 0x71, 0x86, 0x1c, 0x3c, 0x2b, 0x08, 0xb6, 0xa3, 0x12, 0xe5, 0x9b, 0x76, + 0xd3, 0x31, 0xb1, 0xd5, 0x3f, 0x8b, 0x6a, 0x73, 0x0b, 0x15, 0x11, 0xf1, 0x51, 0x76, 0xf3, 0xa4, 0xfd, 0x0e, 0xf6, + 0x58, 0xab, 0x41, 0x64, 0x9f, 0xc1, 0x55, 0xae, 0xd3, 0x22, 0xb7, 0x65, 0x70, 0xfe, 0xe1, 0xd5, 0xae, 0xc2, 0x26, + 0xc7, 0xba, 0xba, 0x9a, 0xa9, 0x4e, 0x2a, 0x36, 0x30, 0xd6, 0xb4, 0x96, 0x6a, 0x1e, 0x43, 0xd2, 0x5d, 0x59, 0x9c, + 0x55, 0x49, 0x37, 0x3d, 0x37, 0xce, 0x14, 0x62, 0xe0, 0x6c, 0x35, 0x5a, 0xce, 0x30, 0x44, 0xd7, 0x87, 0x59, 0xe2, + 0xb7, 0x7a, 0xca, 0x7d, 0x1e, 0x6e, 0xfd, 0xae, 0x5e, 0x70, 0x32, 0xd9, 0x4f, 0x8e, 0x73, 0xb7, 0x8b, 0xb4, 0x9f, + 0xf8, 0x36, 0xcc, 0xbf, 0xbe, 0x41, 0xdc, 0x8a, 0xfa, 0x97, 0x0a, 0x80, 0x06, 0x37, 0x79, 0x2c, 0x51, 0xea, 0xf7, + 0xaa, 0xfa, 0x41, 0xcd, 0x54, 0x4d, 0x03, 0xc1, 0x9c, 0x4a, 0x01, 0x7f, 0xb8, 0x5d, 0xb8, 0xe2, 0x11, 0x37, 0x2c, + 0x8c, 0x5f, 0xbc, 0x9a, 0x9d, 0x0a, 0x2a, 0x03, 0x37, 0xe3, 0x2f, 0x9e, 0x60, 0xa7, 0xb0, 0x56, 0x40, 0x56, 0xf8, + 0xe2, 0xe5, 0x0f, 0xbc, 0x5f, 0xf1, 0x2f, 0x5e, 0xf5, 0xc0, 0xfb, 0x88, 0xf3, 0xf2, 0x05, 0x49, 0x9d, 0x10, 0xd5, + 0xe5, 0x0b, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x05, 0x29, 0x7c, 0x82, 0xcf, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, + 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, + 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, + 0x37, 0x61, 0x1d, 0x25, 0x69, 0x7e, 0x2b, 0xa3, 0x8f, 0x64, 0xd8, 0x91, 0xbe, 0x92, 0x12, 0xed, 0xb5, 0x0a, 0xcb, + 0xd1, 0xec, 0xd7, 0x25, 0x07, 0xca, 0xeb, 0x56, 0x50, 0xbe, 0x6a, 0x02, 0xe8, 0x95, 0x6a, 0x9f, 0x81, 0x56, 0x50, + 0x58, 0x2a, 0x0f, 0x56, 0xe2, 0x5c, 0xf4, 0x59, 0x71, 0x38, 0xa8, 0x8b, 0x21, 0xa1, 0x40, 0x95, 0x38, 0x09, 0x8d, + 0x78, 0x0e, 0x17, 0x42, 0xf1, 0x34, 0xc7, 0xd8, 0x8a, 0x1c, 0x38, 0x90, 0xe1, 0x07, 0x04, 0xde, 0xcb, 0xfe, 0x15, + 0x0c, 0x86, 0x09, 0x6e, 0x64, 0xd4, 0xc9, 0x39, 0xfb, 0x82, 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, + 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, 0x9d, 0xf4, 0x4f, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, + 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, + 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, + 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, + 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, + 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, + 0x28, 0x07, 0xfb, 0x17, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, + 0x71, 0x50, 0xb1, 0xdb, 0x32, 0x8c, 0x80, 0x41, 0x1d, 0xfb, 0x1f, 0x7d, 0x36, 0x6d, 0xc8, 0x3e, 0x00, 0x54, 0xae, + 0x42, 0xc0, 0x1e, 0x80, 0x13, 0x8d, 0x70, 0x03, 0xdc, 0x6a, 0xb4, 0xa4, 0x83, 0xba, 0x2d, 0x18, 0x88, 0x96, 0xb0, + 0x91, 0xb7, 0x5d, 0x9d, 0xbe, 0x21, 0x7c, 0xa8, 0x9d, 0x94, 0x0e, 0xe5, 0x6f, 0x9e, 0xb3, 0xff, 0xd9, 0x61, 0x4d, + 0x4d, 0xf9, 0x08, 0x98, 0x39, 0x2b, 0x91, 0x57, 0x08, 0x9d, 0x22, 0xbf, 0x57, 0x75, 0x25, 0x86, 0xcb, 0x5a, 0x94, + 0x9d, 0xd9, 0xad, 0x13, 0xbd, 0x73, 0x0a, 0x6a, 0xa9, 0x6c, 0x90, 0x93, 0x54, 0x9b, 0x8f, 0xac, 0x15, 0x94, 0xa8, + 0x6b, 0x14, 0x38, 0x3e, 0xe5, 0xda, 0xfd, 0xbf, 0x73, 0x26, 0xa8, 0xd9, 0x46, 0x75, 0x7f, 0xa1, 0x9f, 0xaa, 0x9a, + 0xc4, 0x02, 0x5c, 0x4e, 0xd2, 0xbc, 0xe3, 0x11, 0x56, 0xff, 0x38, 0x59, 0x8a, 0x40, 0x9f, 0x22, 0xda, 0x95, 0x80, + 0x04, 0xed, 0xe4, 0x2c, 0x54, 0x04, 0x0a, 0xf4, 0xf5, 0xe7, 0x9b, 0x34, 0x8b, 0xe5, 0x6a, 0xb6, 0x87, 0x89, 0xb2, + 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x57, 0xa6, 0x04, 0x97, 0xe2, 0x2a, 0x2a, + 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0x4b, 0x54, 0x3b, 0x52, 0x20, 0x87, 0x92, + 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0xd7, 0x0a, 0xc1, 0xfd, 0xb5, 0x2d, 0x36, 0xaa, 0x3c, + 0xd1, 0x83, 0x4f, 0xb1, 0xfe, 0x27, 0x0b, 0x28, 0xd5, 0x7d, 0x1b, 0x9c, 0x8a, 0x47, 0xe1, 0xa6, 0x2e, 0x3e, 0x22, + 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, 0x9d, 0x3a, 0x0c, 0x1c, + 0x50, 0x13, 0x25, 0xa2, 0xd8, 0x2d, 0xe8, 0x9e, 0xe6, 0x58, 0x89, 0x67, 0xb2, 0x74, 0x90, 0x75, 0x22, 0x4d, 0xa8, + 0xdc, 0xd5, 0x55, 0x47, 0xa5, 0x52, 0x37, 0xbc, 0x4c, 0x35, 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x6c, 0xfd, + 0x56, 0xab, 0xbd, 0xb1, 0x7a, 0x54, 0xb2, 0xe6, 0x38, 0x9b, 0x90, 0x94, 0x3e, 0x61, 0xbb, 0x99, 0x74, 0xad, 0x03, + 0x4f, 0x82, 0xcb, 0xa1, 0x27, 0xa0, 0x62, 0xd0, 0xc4, 0xdb, 0x5d, 0xa0, 0x1e, 0x81, 0x67, 0xa0, 0x7c, 0xa2, 0xd6, + 0x01, 0x3f, 0xaf, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x38, 0xef, 0x14, 0x81, 0x6b, 0x57, 0x02, + 0xcf, 0x87, 0xea, 0xbd, 0x10, 0x30, 0xdc, 0x3f, 0x15, 0x2a, 0x9b, 0xdd, 0x0c, 0xe7, 0x51, 0xe3, 0xf4, 0x40, 0x7b, + 0xdb, 0xb5, 0x1e, 0xea, 0x5d, 0xb7, 0x73, 0x5b, 0xe9, 0xde, 0xaf, 0x9d, 0x4c, 0xba, 0x80, 0xd6, 0xe6, 0xb3, 0xef, + 0xec, 0x4a, 0xeb, 0xa6, 0xe7, 0xec, 0xc1, 0xd6, 0x2d, 0xd1, 0xb9, 0x20, 0x9a, 0xfc, 0x7e, 0xe0, 0x59, 0xdb, 0x8e, + 0x7e, 0x9b, 0x76, 0x6c, 0x73, 0x0f, 0x75, 0xaf, 0xa0, 0xd6, 0x1b, 0x9a, 0xf7, 0xcf, 0x5c, 0xdb, 0x8e, 0xaf, 0x7e, + 0x5d, 0x77, 0xb8, 0xce, 0x9b, 0xe0, 0xb8, 0xe9, 0xda, 0x56, 0x3b, 0xfb, 0xb9, 0xbb, 0xb7, 0x16, 0x51, 0x98, 0x65, + 0x3f, 0x17, 0xc5, 0x9f, 0x95, 0xbe, 0x23, 0xd0, 0xd1, 0x9d, 0x17, 0x75, 0xba, 0xdc, 0xbd, 0x27, 0x8c, 0x27, 0xaf, + 0x3e, 0x22, 0xba, 0xf5, 0x7d, 0xe6, 0x7e, 0x05, 0xb8, 0x11, 0xdc, 0x41, 0xb4, 0x77, 0x4b, 0x7d, 0x52, 0xab, 0xaf, + 0xf5, 0xda, 0x79, 0x7a, 0x7e, 0xd3, 0xb9, 0xfd, 0xee, 0x9b, 0xa3, 0xad, 0xf7, 0xb8, 0xb0, 0x56, 0x96, 0x9e, 0xaa, + 0x82, 0xbd, 0x59, 0x9e, 0xaa, 0x82, 0xc9, 0x03, 0xaf, 0xd9, 0x2f, 0x68, 0x70, 0xa5, 0xa3, 0x8d, 0xf7, 0x44, 0x0d, + 0xdc, 0xa2, 0xb0, 0x74, 0xf8, 0x25, 0x37, 0x93, 0x6b, 0xdc, 0x5f, 0x2a, 0x72, 0xb1, 0xef, 0x9c, 0xd1, 0x9d, 0x99, + 0x75, 0xaf, 0x2a, 0x5c, 0x2d, 0xc8, 0xd5, 0x81, 0xad, 0x65, 0x17, 0x87, 0x1b, 0x16, 0x51, 0x80, 0x40, 0x4c, 0xaf, + 0xd4, 0xda, 0x1f, 0xd1, 0x20, 0xe4, 0x83, 0x81, 0x5f, 0x60, 0xb0, 0x2a, 0x50, 0xf8, 0x40, 0x91, 0xfc, 0x85, 0x27, + 0x60, 0x17, 0xcf, 0x00, 0xdd, 0x8a, 0xcd, 0x8a, 0x11, 0x22, 0x64, 0xb2, 0x9c, 0xd5, 0x74, 0x06, 0xf9, 0xd4, 0x17, + 0xdf, 0xd9, 0xaa, 0xd3, 0x79, 0x5b, 0x53, 0xe5, 0xd4, 0xa1, 0xd0, 0xdd, 0x4d, 0xdd, 0xb9, 0x75, 0x91, 0xa7, 0x0e, + 0x21, 0x57, 0x2a, 0x56, 0x62, 0x1a, 0x6a, 0x9e, 0xa4, 0x19, 0xf5, 0x57, 0x7b, 0xbf, 0xd7, 0x28, 0x9c, 0xf2, 0xa7, + 0x63, 0x50, 0x85, 0xab, 0x1a, 0xe2, 0x58, 0xaa, 0xe2, 0x91, 0x0d, 0x02, 0xcd, 0xab, 0x5b, 0x95, 0x34, 0x21, 0x93, + 0x1b, 0xe1, 0x53, 0x93, 0x52, 0x9e, 0xa6, 0x4d, 0x5a, 0x29, 0x52, 0x07, 0x1f, 0xd4, 0xa9, 0xc6, 0x73, 0xb3, 0x7a, + 0x0a, 0x60, 0xc6, 0xf9, 0x15, 0xbf, 0x54, 0x5c, 0x46, 0x6d, 0x65, 0x26, 0xed, 0x4f, 0x8e, 0xc6, 0x46, 0x5d, 0x4e, + 0x95, 0x79, 0xc5, 0xa0, 0x4f, 0xbf, 0xd6, 0xe7, 0x1f, 0x30, 0x58, 0xf3, 0x04, 0x76, 0x30, 0x51, 0x29, 0xef, 0x23, + 0x20, 0xbe, 0x4e, 0xd2, 0xdb, 0x04, 0x52, 0xa4, 0x7f, 0xe9, 0x92, 0xa7, 0x0e, 0x63, 0x03, 0x31, 0x66, 0xc5, 0xcc, + 0xe8, 0x7f, 0x70, 0x97, 0xf4, 0x27, 0x21, 0x00, 0x6e, 0xa2, 0x29, 0x74, 0xea, 0x3c, 0xb9, 0xc8, 0x83, 0xe5, 0x85, + 0x87, 0x56, 0x8c, 0x78, 0xf0, 0xd7, 0xa7, 0x21, 0x82, 0x98, 0x63, 0x8a, 0xa7, 0x5f, 0x18, 0xfd, 0x25, 0xb8, 0xc4, + 0x08, 0x42, 0x77, 0xef, 0x1c, 0x86, 0x70, 0xb3, 0x07, 0x19, 0xd4, 0x1f, 0xea, 0x90, 0xa8, 0xe1, 0x2f, 0x95, 0x07, + 0xfd, 0x5f, 0x67, 0xc2, 0x52, 0xfb, 0xe9, 0xe9, 0x00, 0x2a, 0x78, 0x5f, 0xf1, 0x36, 0x22, 0xbe, 0x4f, 0xfc, 0x38, + 0x1e, 0x6c, 0x1e, 0x6f, 0xc0, 0x5a, 0xf7, 0x2c, 0x37, 0xd6, 0x55, 0xc2, 0x06, 0x02, 0xbe, 0xc6, 0xb4, 0xf6, 0xbc, + 0x76, 0xbb, 0x07, 0x7f, 0xf5, 0x2f, 0x42, 0x06, 0x4c, 0x9c, 0xbe, 0xcf, 0x9c, 0xac, 0xd1, 0x45, 0x26, 0xd3, 0x87, + 0x4e, 0xfa, 0x46, 0xa7, 0xfb, 0x4e, 0xf8, 0x47, 0xc5, 0x2c, 0x3e, 0xdc, 0xd2, 0x57, 0x9a, 0x14, 0x77, 0xc0, 0xca, + 0xe6, 0x41, 0x41, 0xa8, 0x73, 0x11, 0x7d, 0x63, 0xca, 0xb7, 0x84, 0x9a, 0x7d, 0x63, 0x49, 0x29, 0xdd, 0x6b, 0xe8, + 0x65, 0x5a, 0xeb, 0xb7, 0x51, 0x82, 0x31, 0xd1, 0xf1, 0xe4, 0x65, 0x3c, 0x56, 0xde, 0xc7, 0xe3, 0x46, 0x2a, 0xe4, + 0x01, 0x88, 0x40, 0xc5, 0xf8, 0xd3, 0x95, 0x27, 0x27, 0xbd, 0x30, 0x5e, 0x85, 0x52, 0x50, 0x18, 0xd0, 0x15, 0x48, + 0x01, 0x8f, 0xda, 0x13, 0x9d, 0x85, 0x5d, 0xc2, 0x3d, 0xba, 0x09, 0x18, 0xeb, 0xf3, 0x2f, 0x80, 0xe6, 0x2e, 0xdc, + 0xe1, 0xc5, 0x00, 0xb5, 0xa9, 0x57, 0x77, 0x1f, 0xd7, 0xea, 0x1c, 0x0e, 0xc1, 0xc1, 0x6a, 0x10, 0xc1, 0xe9, 0x7c, + 0xea, 0x68, 0x96, 0x05, 0xa8, 0x9c, 0x2c, 0x37, 0xf2, 0xe6, 0xd1, 0xa2, 0x57, 0xf7, 0xbd, 0x65, 0x5a, 0x56, 0x75, + 0x90, 0xb1, 0x2c, 0xac, 0x00, 0x57, 0x87, 0xd6, 0x0f, 0xc2, 0x65, 0xe1, 0xfc, 0x81, 0x10, 0xc4, 0xee, 0xd5, 0xb6, + 0xe4, 0xb9, 0x9a, 0xc3, 0x8f, 0x9f, 0xb0, 0x35, 0x97, 0xa8, 0x93, 0xce, 0x44, 0x00, 0x62, 0x4f, 0xcd, 0x2a, 0xba, + 0x06, 0x92, 0x3a, 0xcd, 0x2a, 0xba, 0xa6, 0x66, 0x1b, 0xe3, 0x40, 0x3e, 0x5a, 0xa5, 0x80, 0x7d, 0x37, 0x1d, 0x07, + 0xab, 0xc7, 0xb1, 0xbc, 0x0e, 0xdd, 0x3e, 0xde, 0x28, 0x9f, 0x41, 0xdd, 0x6a, 0x63, 0x4c, 0x6c, 0x37, 0x5f, 0xce, + 0xf5, 0x9b, 0xc1, 0xd2, 0xb7, 0x83, 0xe6, 0x9c, 0xb2, 0x6f, 0x75, 0xd9, 0x2b, 0xbb, 0x6c, 0xea, 0xb9, 0xa3, 0xa2, + 0xd5, 0x18, 0xd0, 0x1b, 0x58, 0xb0, 0x3e, 0x17, 0x69, 0xb6, 0x2a, 0x55, 0x09, 0x78, 0x61, 0xac, 0xd8, 0xad, 0xdf, + 0xc8, 0x0c, 0x49, 0x98, 0xc7, 0x99, 0x78, 0x43, 0xf7, 0x5a, 0x98, 0x1c, 0xc7, 0x22, 0x99, 0x12, 0x3a, 0xa5, 0x3b, + 0xdb, 0xd0, 0xb9, 0x0a, 0xa3, 0x88, 0xd6, 0x4a, 0x2a, 0x8d, 0x04, 0xa6, 0x66, 0x80, 0x92, 0xb9, 0x02, 0xa7, 0x74, + 0xb9, 0xff, 0x1d, 0x89, 0x71, 0xe6, 0x8b, 0x92, 0x19, 0xd0, 0x2d, 0xbf, 0x2e, 0xd6, 0xad, 0x14, 0x19, 0x61, 0xde, + 0x1c, 0xb7, 0xd7, 0xf5, 0x21, 0x90, 0xab, 0x65, 0x8f, 0xa2, 0x71, 0x50, 0xe8, 0x70, 0xa9, 0x12, 0x60, 0x5f, 0x24, + 0x7e, 0x46, 0xd8, 0xd2, 0x1e, 0xc8, 0xed, 0xd1, 0x99, 0x30, 0xe7, 0x9c, 0x94, 0x65, 0xe7, 0xd2, 0x0c, 0x2e, 0x27, + 0xae, 0x04, 0x17, 0xe9, 0x6d, 0x7b, 0x9a, 0xb4, 0xb4, 0x7d, 0x6c, 0x38, 0x47, 0x43, 0xdb, 0xa0, 0x3b, 0xf6, 0x87, + 0xe6, 0x62, 0x11, 0x5b, 0x17, 0x8b, 0x61, 0x67, 0xf6, 0xa3, 0xc5, 0x02, 0xe4, 0x00, 0x70, 0xd4, 0x6d, 0xf8, 0x98, + 0x2d, 0x81, 0xd3, 0x6a, 0x9a, 0x4d, 0xbd, 0x0d, 0xaf, 0x1e, 0xab, 0x9e, 0x5e, 0xf2, 0xfc, 0xb1, 0x30, 0x63, 0xb1, + 0xe1, 0xf9, 0x63, 0xeb, 0xc8, 0xa9, 0x1e, 0x0b, 0x25, 0x5a, 0x17, 0xd0, 0x0c, 0xbc, 0xa6, 0x80, 0x11, 0x4b, 0x26, + 0x53, 0xaa, 0xc8, 0xe3, 0xde, 0x74, 0xa3, 0x06, 0x2f, 0x28, 0x1c, 0x02, 0x29, 0x9d, 0x7e, 0xf1, 0x84, 0xe9, 0xf7, + 0x2e, 0x9e, 0x74, 0xc8, 0xda, 0x86, 0xe9, 0x72, 0x33, 0x4c, 0x06, 0xa5, 0xff, 0xd8, 0x4c, 0x8c, 0x0b, 0x6b, 0x92, + 0x00, 0xe2, 0xdf, 0xd8, 0xef, 0x90, 0xc2, 0xcd, 0xfb, 0xcb, 0x61, 0xfc, 0xc0, 0xfb, 0x31, 0xb2, 0x27, 0x69, 0x86, + 0x58, 0x33, 0xa9, 0x90, 0xbb, 0xaf, 0xd6, 0x3f, 0x26, 0x76, 0x93, 0x3d, 0xb0, 0x00, 0xc4, 0xd6, 0xb4, 0xd5, 0x2d, + 0xef, 0xf7, 0x3d, 0x53, 0x04, 0xf8, 0x41, 0xf9, 0x47, 0x77, 0x86, 0x64, 0x50, 0x76, 0xdd, 0x10, 0xe2, 0x41, 0xd9, + 0x34, 0xed, 0xf5, 0xb6, 0x77, 0xe6, 0xb1, 0xba, 0x4e, 0x3b, 0x8b, 0xab, 0x45, 0x06, 0x69, 0xf5, 0x21, 0x3b, 0xce, + 0xec, 0xb3, 0xa3, 0xa5, 0xd2, 0xfd, 0x3e, 0x44, 0xc4, 0x1d, 0x65, 0x6d, 0xbf, 0xdd, 0x82, 0x6b, 0x38, 0x1a, 0x84, + 0xae, 0xec, 0xed, 0x32, 0xda, 0xb8, 0x10, 0xc7, 0x3d, 0xd3, 0xf9, 0x82, 0x2f, 0x8f, 0xd2, 0xce, 0x83, 0x53, 0x3d, + 0xd1, 0xe7, 0xa6, 0xbb, 0xca, 0xe4, 0x5a, 0x87, 0xd5, 0x18, 0xd4, 0x66, 0x61, 0x0b, 0x77, 0x61, 0x1b, 0x1d, 0xb4, + 0xf6, 0x65, 0xc1, 0x3f, 0x65, 0x00, 0xbe, 0xf4, 0x6c, 0xd9, 0xf6, 0x9a, 0xb4, 0x7a, 0x29, 0xa3, 0x10, 0x5b, 0xda, + 0x5e, 0x7d, 0x3a, 0xca, 0xc7, 0xcd, 0x09, 0xc5, 0x85, 0x1c, 0xe5, 0x07, 0xaf, 0x21, 0xea, 0x5a, 0xd7, 0x71, 0xb1, + 0xe8, 0x70, 0xe3, 0xaa, 0xdb, 0x6e, 0x5c, 0xaf, 0x10, 0x6f, 0x8d, 0x36, 0x29, 0xd4, 0xca, 0xd8, 0x11, 0xbc, 0x2c, + 0x1f, 0x0e, 0x99, 0x18, 0x0e, 0x25, 0x64, 0xea, 0x43, 0xf7, 0x86, 0xa6, 0x7d, 0x7e, 0xda, 0xfa, 0x11, 0x4b, 0x8d, + 0xa3, 0xd8, 0xf0, 0x4e, 0xdf, 0x79, 0x6c, 0x8d, 0x2b, 0xf9, 0x32, 0x98, 0xed, 0x0a, 0xaa, 0xad, 0xf1, 0x86, 0xbd, + 0x9c, 0xff, 0x5c, 0x49, 0x25, 0x7f, 0xfb, 0x33, 0x5c, 0xc3, 0x5b, 0x5b, 0x3a, 0x68, 0xaa, 0x59, 0xce, 0x72, 0x7d, + 0x2f, 0x38, 0xfe, 0xb8, 0x7b, 0x45, 0x30, 0xf8, 0x3d, 0x1d, 0x05, 0xb9, 0x58, 0xaa, 0x35, 0xa0, 0x20, 0x1d, 0xd9, + 0x31, 0x95, 0x05, 0x86, 0x01, 0xbc, 0x21, 0x03, 0xe4, 0x31, 0x85, 0xbb, 0xa1, 0xc2, 0x0b, 0x7f, 0xad, 0xc8, 0x2e, + 0x81, 0x6d, 0xcd, 0xf8, 0x98, 0xe1, 0x0e, 0x42, 0xfe, 0x11, 0xec, 0x96, 0xad, 0xd8, 0x0d, 0x5b, 0x30, 0x24, 0x1b, + 0xc7, 0x61, 0x8c, 0xf9, 0x78, 0x12, 0x5f, 0x89, 0x49, 0x3c, 0xe0, 0x11, 0x3a, 0x46, 0xac, 0x79, 0x3d, 0x8b, 0xe5, + 0x00, 0xb2, 0x5b, 0xae, 0x74, 0x40, 0x08, 0x8d, 0x0d, 0x2d, 0x79, 0x59, 0x18, 0x5c, 0xec, 0xd8, 0x67, 0x24, 0x92, + 0x71, 0x08, 0x16, 0xad, 0x6a, 0x60, 0x61, 0x62, 0x37, 0xbc, 0x98, 0xad, 0xe6, 0xf8, 0xcf, 0xe1, 0x80, 0x00, 0xd8, + 0xc1, 0xbe, 0x61, 0xb7, 0x11, 0x22, 0xbd, 0x2d, 0xf8, 0xad, 0xe5, 0xe9, 0xc2, 0xee, 0xf8, 0x35, 0x1f, 0xb3, 0xf3, + 0x57, 0x1e, 0x44, 0xce, 0x9e, 0x7f, 0x00, 0x34, 0xc4, 0x3b, 0x7e, 0x93, 0x7a, 0x15, 0xbb, 0x21, 0x0a, 0xc2, 0x1b, + 0x70, 0x06, 0xba, 0x83, 0x08, 0xd8, 0x6b, 0xbe, 0xc0, 0x58, 0xb1, 0xb3, 0x74, 0xe9, 0x61, 0x46, 0xa8, 0x3d, 0x9d, + 0x2f, 0x6b, 0x35, 0x09, 0x37, 0x57, 0xcb, 0xc9, 0x60, 0xb0, 0xf1, 0x77, 0x7c, 0x0d, 0x7c, 0x30, 0xe7, 0xaf, 0xbc, + 0x1d, 0x95, 0x0b, 0xff, 0x79, 0x9d, 0x25, 0xef, 0x7c, 0x76, 0x3d, 0xe0, 0x0b, 0xc0, 0x5b, 0x42, 0x07, 0xae, 0x3b, + 0x9f, 0x49, 0xbc, 0xb6, 0x6b, 0x7d, 0x8d, 0x40, 0x22, 0x5f, 0x00, 0x46, 0x4c, 0xcc, 0xef, 0x6b, 0x88, 0xc0, 0xd8, + 0x80, 0x6f, 0xab, 0xf6, 0x88, 0xdf, 0x72, 0x03, 0xf8, 0x95, 0xf9, 0xec, 0x9e, 0x87, 0xfa, 0x67, 0xe2, 0xb3, 0x37, + 0xfc, 0x11, 0x7f, 0xea, 0x49, 0x49, 0xba, 0x9c, 0x3d, 0x9a, 0xc3, 0xf5, 0x50, 0xca, 0xd3, 0x21, 0xfd, 0x6c, 0x0c, + 0x06, 0x10, 0x0a, 0x99, 0x6f, 0x3c, 0x60, 0x4d, 0x0a, 0xf1, 0x2f, 0xe0, 0xdb, 0x51, 0xc2, 0xe6, 0x1b, 0x6f, 0xeb, + 0x6b, 0x79, 0xf3, 0x8d, 0x77, 0xef, 0x53, 0x14, 0x60, 0x15, 0x94, 0xb2, 0xc0, 0x2a, 0x08, 0x1b, 0x6d, 0x84, 0x31, + 0x70, 0xf5, 0xae, 0x31, 0xd4, 0xf5, 0x1c, 0xb1, 0x6d, 0xa5, 0x6f, 0xc3, 0xb7, 0x90, 0x01, 0x1f, 0xbc, 0x2c, 0x4a, + 0xa2, 0xcf, 0xa9, 0x29, 0x92, 0xd6, 0x3d, 0xf7, 0x5b, 0xeb, 0x8e, 0xd6, 0x94, 0xfa, 0xc8, 0xd5, 0xf8, 0x70, 0xa8, + 0x9f, 0x0a, 0x2d, 0x12, 0x4c, 0x41, 0xe3, 0x1a, 0xb4, 0x05, 0x08, 0xfa, 0x3c, 0x40, 0xd6, 0x92, 0x62, 0xc1, 0xb7, + 0xbf, 0x42, 0x0c, 0x5e, 0x99, 0xde, 0xb9, 0x5c, 0x65, 0x24, 0x6c, 0x2f, 0xfc, 0x72, 0x58, 0xfb, 0x13, 0xa7, 0x16, + 0x96, 0x56, 0x73, 0x50, 0x3f, 0xb6, 0xe5, 0x38, 0x5d, 0xb5, 0xc8, 0xeb, 0x50, 0x5a, 0x4e, 0xef, 0xec, 0x9b, 0x2e, + 0x13, 0x6c, 0xec, 0x07, 0x54, 0x1d, 0x59, 0x0d, 0xbb, 0x2f, 0xd4, 0x17, 0x3d, 0x25, 0x13, 0x9a, 0x8f, 0x2a, 0x9a, + 0xe7, 0xd6, 0x37, 0x8f, 0xeb, 0x3f, 0xbd, 0x1c, 0x8a, 0x00, 0xc9, 0x2a, 0x2d, 0x96, 0x22, 0x67, 0x63, 0x3f, 0x1e, + 0x26, 0x99, 0x0a, 0x2f, 0x48, 0x47, 0x77, 0xbf, 0x71, 0x7f, 0xcb, 0x0d, 0x64, 0x85, 0x56, 0x6d, 0x30, 0x56, 0x8a, + 0x96, 0xc1, 0xfa, 0x6a, 0xdc, 0xef, 0x8b, 0xab, 0xf1, 0x54, 0x04, 0x35, 0x10, 0x17, 0x89, 0xa7, 0xe3, 0x69, 0x4d, + 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x14, 0x42, 0x91, 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, + 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, 0x75, 0x72, 0xec, 0x5c, 0xc0, + 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x65, 0x62, 0x6b, 0x23, 0xdc, 0x52, 0x40, 0x19, 0xe5, + 0x37, 0x96, 0x13, 0x76, 0xa7, 0x7a, 0x47, 0xaa, 0x76, 0xc4, 0x89, 0x0b, 0x58, 0x6e, 0x78, 0x6a, 0xf5, 0x4d, 0x0c, + 0x4e, 0x84, 0xaa, 0x95, 0x0e, 0x77, 0x32, 0x81, 0xb8, 0x5f, 0xdd, 0xd7, 0xbd, 0x12, 0xfc, 0x24, 0xe4, 0xf5, 0x5b, + 0xde, 0x01, 0x60, 0xc5, 0x87, 0xbc, 0x98, 0x16, 0x8e, 0xd6, 0x65, 0x50, 0x06, 0x88, 0xd0, 0x0c, 0x80, 0x4e, 0xae, + 0x0e, 0xa2, 0x34, 0x70, 0xc5, 0x1d, 0x22, 0xfc, 0x34, 0x7a, 0x9c, 0x3f, 0x0d, 0x1f, 0x57, 0xd3, 0xf0, 0x22, 0x0f, + 0xa2, 0x8b, 0x2a, 0x88, 0x1e, 0x57, 0x57, 0xe1, 0xe3, 0x7c, 0x1a, 0x5d, 0xe4, 0x41, 0x78, 0x51, 0x35, 0xf6, 0x5d, + 0xbb, 0xbb, 0x27, 0xe4, 0x6d, 0x57, 0x7f, 0xe4, 0x5c, 0xd9, 0x53, 0xa6, 0xe7, 0xe7, 0xb5, 0x5e, 0xa9, 0xdd, 0xe6, + 0x7a, 0x8d, 0x9a, 0xa9, 0x8f, 0xb2, 0xbf, 0xd9, 0xc6, 0xc2, 0xa3, 0x39, 0x84, 0x3e, 0x23, 0x2d, 0xe6, 0x1e, 0xe7, + 0x7a, 0xb3, 0x27, 0x85, 0x81, 0x11, 0x93, 0x4a, 0x46, 0x4e, 0x2f, 0x70, 0x11, 0xaa, 0x10, 0xc3, 0x5a, 0xba, 0xda, + 0x67, 0x5d, 0x7a, 0x03, 0x75, 0x4d, 0xb1, 0xaf, 0x21, 0x03, 0x2f, 0x9a, 0x5e, 0x06, 0x63, 0x40, 0x8e, 0xc0, 0x3b, + 0x3e, 0x5b, 0xc2, 0x81, 0xb9, 0x06, 0xe8, 0x9b, 0x07, 0x7d, 0x5d, 0x6e, 0xf9, 0x5a, 0xf5, 0xcd, 0x74, 0x3d, 0x52, + 0xca, 0x8f, 0x15, 0xbf, 0xbd, 0x78, 0xc2, 0x6e, 0xb8, 0x46, 0x45, 0x79, 0xae, 0x17, 0xeb, 0x1d, 0x70, 0xd5, 0x3d, + 0x87, 0xdb, 0x2c, 0x1e, 0xbb, 0xf2, 0x80, 0x65, 0x5b, 0x76, 0xcf, 0xde, 0xb0, 0x47, 0xec, 0x3d, 0xfb, 0xc4, 0xbe, + 0xb2, 0x1a, 0x21, 0xca, 0x4b, 0x25, 0xe5, 0xf9, 0x0b, 0x7e, 0x23, 0x6d, 0x8f, 0x12, 0x96, 0xec, 0xde, 0xb6, 0xd3, + 0x0c, 0x37, 0xec, 0x11, 0x5f, 0x0c, 0x57, 0xec, 0x13, 0x64, 0x43, 0xa1, 0x78, 0xb0, 0x62, 0x35, 0x5c, 0x61, 0x29, + 0x83, 0x3e, 0x0d, 0x4b, 0x4b, 0x58, 0x34, 0x85, 0xa2, 0x14, 0xfd, 0x89, 0xd7, 0x84, 0x9d, 0x56, 0x63, 0x21, 0xf2, + 0x43, 0xc3, 0x15, 0xbb, 0xe7, 0x8b, 0xc1, 0x8a, 0x3d, 0xd2, 0x36, 0xa2, 0xc1, 0xc6, 0x2d, 0x8e, 0xc0, 0xac, 0x74, + 0x61, 0x52, 0xa0, 0xde, 0xda, 0x37, 0xc1, 0x0d, 0x7b, 0x83, 0xf5, 0x7b, 0x8f, 0x45, 0xa3, 0xcc, 0x3f, 0x58, 0xb1, + 0xaf, 0x5c, 0x62, 0xa8, 0xb9, 0xe5, 0x49, 0xc7, 0x50, 0x5d, 0x20, 0x5d, 0x11, 0xde, 0x73, 0x7a, 0x91, 0x7d, 0xc5, + 0x32, 0xe8, 0x2b, 0xc3, 0x15, 0xdb, 0x62, 0xed, 0xde, 0x18, 0xe3, 0x96, 0x55, 0x3d, 0x09, 0x0a, 0x8c, 0xb2, 0x4a, + 0x69, 0xb9, 0x38, 0x62, 0xd9, 0xd4, 0x51, 0x83, 0xda, 0x30, 0xa0, 0x0f, 0x46, 0x7f, 0xf1, 0xf5, 0xbb, 0xef, 0xbc, + 0x52, 0xdf, 0x7c, 0x9f, 0x3b, 0xde, 0x95, 0x25, 0x7a, 0x57, 0xfe, 0xc6, 0xcb, 0xd9, 0xf3, 0xf9, 0x44, 0xd7, 0x92, + 0x36, 0x19, 0x72, 0x37, 0x9d, 0x3d, 0xef, 0xf0, 0xb7, 0xfc, 0xcd, 0xf7, 0x1b, 0xab, 0x8f, 0xd5, 0x77, 0x75, 0xf7, + 0xde, 0x0f, 0x36, 0x8d, 0x53, 0xf1, 0xdd, 0xe9, 0x8a, 0x63, 0x3b, 0x6b, 0xed, 0x9d, 0xf9, 0x3f, 0x5c, 0xeb, 0x2d, + 0x8e, 0xdd, 0x1b, 0xbe, 0x1d, 0x6e, 0xec, 0x61, 0x90, 0xdf, 0x97, 0x8a, 0xe3, 0xac, 0xe6, 0xcf, 0xbc, 0x4e, 0x49, + 0x16, 0x50, 0x8d, 0x5e, 0x1b, 0x69, 0xe8, 0x92, 0x99, 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, + 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, 0xb5, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, + 0xd8, 0x4b, 0xf2, 0xb9, 0xcf, 0xde, 0x0a, 0x77, 0x95, 0x3e, 0xf7, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, + 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, 0x16, 0xfc, 0x2d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0x3f, + 0xd7, 0xea, 0xe7, 0x3b, 0x19, 0x9b, 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0x9b, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, + 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0xd7, 0x3c, 0x96, 0x16, 0xe6, 0x3b, 0x08, + 0x07, 0xbe, 0xb6, 0x61, 0x0a, 0x76, 0x1c, 0x37, 0x83, 0x6b, 0x06, 0x10, 0x92, 0xd9, 0x74, 0xcb, 0xdf, 0xf0, 0xf7, + 0xfc, 0x2b, 0xdf, 0x05, 0xf7, 0xfc, 0x11, 0xff, 0xc4, 0xeb, 0x9a, 0xef, 0xd8, 0x52, 0x42, 0x9e, 0xd6, 0xdb, 0xcb, + 0x60, 0xcb, 0xea, 0xdd, 0x65, 0x70, 0xcf, 0xea, 0xed, 0x93, 0xe0, 0x0d, 0xab, 0x77, 0x4f, 0x82, 0x47, 0x6c, 0x7b, + 0x19, 0xbc, 0x67, 0xbb, 0xcb, 0xe0, 0x13, 0xdb, 0x3e, 0x09, 0xbe, 0xb2, 0xdd, 0x93, 0xa0, 0x56, 0x48, 0x0f, 0x5f, + 0x85, 0x64, 0x3a, 0xf9, 0x5a, 0x33, 0xc3, 0xaa, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, 0x65, 0xf0, 0xb9, 0x66, 0xba, + 0xcd, 0x81, 0x10, 0x4c, 0xb7, 0x38, 0xb8, 0xa1, 0x27, 0xa6, 0x5d, 0x41, 0x2a, 0x58, 0x57, 0x4b, 0x83, 0x45, 0xdd, + 0xb4, 0x4e, 0x66, 0xc7, 0x3b, 0x31, 0xee, 0xf0, 0x4e, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, 0xaa, 0x73, 0xfa, 0x3c, 0xd0, + 0x47, 0x80, 0xde, 0xfb, 0x2b, 0xe9, 0x41, 0x53, 0x34, 0x3c, 0x57, 0xba, 0xe3, 0xd6, 0x7e, 0x1f, 0x5a, 0xfb, 0x3d, + 0x93, 0x8a, 0xb4, 0x88, 0x45, 0x65, 0x51, 0x55, 0xc8, 0x27, 0x1e, 0x64, 0x5a, 0xab, 0x96, 0x30, 0x52, 0x67, 0x02, + 0x26, 0x7d, 0x41, 0x87, 0x41, 0x4e, 0x76, 0x05, 0xb6, 0xe4, 0x9b, 0x41, 0xc2, 0xd6, 0x3c, 0x9e, 0x0e, 0x93, 0x60, + 0xc9, 0x6e, 0xf9, 0xb0, 0x5b, 0x2c, 0x58, 0xa9, 0x30, 0x26, 0x7d, 0x7d, 0x3a, 0xda, 0xdd, 0x79, 0x6f, 0x95, 0xc6, + 0x71, 0x26, 0x50, 0xe7, 0x56, 0xe9, 0x6d, 0x7e, 0xeb, 0xec, 0xea, 0x6b, 0xb5, 0xcb, 0x83, 0xc0, 0xf0, 0x1b, 0x10, + 0xed, 0x10, 0xef, 0x1d, 0xd4, 0x18, 0xe9, 0x96, 0xcc, 0xba, 0xaf, 0xec, 0x7d, 0x7d, 0x6b, 0xb6, 0xea, 0xff, 0xb4, + 0x08, 0xda, 0xcb, 0x65, 0xef, 0xbf, 0x36, 0xaf, 0xfe, 0xde, 0xf1, 0xea, 0xc6, 0x9f, 0xdc, 0xf3, 0xd7, 0x18, 0x9d, + 0x80, 0x89, 0x6c, 0xc7, 0x5f, 0x8f, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xcb, 0xff, 0xaf, 0x14, 0x68, 0xef, 0xe6, 0x95, + 0xbd, 0x29, 0x6e, 0x79, 0xc7, 0x5e, 0xbe, 0xb4, 0xf6, 0x44, 0x83, 0x50, 0xf2, 0x9a, 0xbb, 0x41, 0xd1, 0xb0, 0x27, + 0x3e, 0xe7, 0xd5, 0xec, 0xf5, 0x7c, 0xb2, 0xe5, 0xc7, 0x3b, 0xe2, 0xeb, 0x8e, 0x1d, 0xf1, 0xb9, 0x3f, 0x58, 0x36, + 0xdf, 0xea, 0xd5, 0xce, 0x9d, 0xdc, 0xa9, 0xf4, 0x8e, 0x1f, 0xef, 0xe3, 0xc3, 0xff, 0xb8, 0xd2, 0xbb, 0xef, 0xae, + 0xb4, 0x5d, 0xe5, 0xee, 0xce, 0x37, 0x1d, 0xdf, 0xc8, 0x5a, 0x63, 0xb8, 0x99, 0x51, 0x30, 0xc2, 0xb4, 0x85, 0x69, + 0x1a, 0x44, 0x96, 0x62, 0x11, 0x12, 0x35, 0x4a, 0xe7, 0x44, 0x9f, 0x05, 0x9d, 0x82, 0x2e, 0x6e, 0xf4, 0x37, 0x7c, + 0xcc, 0x16, 0xc6, 0x65, 0xf3, 0xe6, 0x6a, 0x31, 0x19, 0x0c, 0x6e, 0xfc, 0xfd, 0x1d, 0x0f, 0x67, 0x37, 0x73, 0x76, + 0xcd, 0xef, 0x68, 0x3d, 0x4d, 0x54, 0xe3, 0x8b, 0x87, 0x24, 0xb0, 0x1b, 0xdf, 0x9f, 0x58, 0x44, 0xb0, 0xf6, 0x8d, + 0xf3, 0xc6, 0x1f, 0x48, 0xb3, 0xb4, 0xdc, 0xda, 0x1f, 0x3d, 0xac, 0xa1, 0xb8, 0x01, 0x21, 0xe3, 0x91, 0xad, 0x72, + 0xf8, 0xc4, 0x3f, 0x78, 0xd7, 0xfe, 0xf4, 0x5a, 0x07, 0xdf, 0x4c, 0xd4, 0xb9, 0xf4, 0xe9, 0xe2, 0x09, 0xfb, 0x8d, + 0xbf, 0x96, 0x67, 0xca, 0x5b, 0x21, 0xa7, 0xed, 0x47, 0x24, 0x71, 0xa2, 0xa3, 0xe2, 0xab, 0x9b, 0x48, 0xa0, 0x10, + 0xb0, 0x2b, 0x7c, 0xad, 0xf9, 0xfd, 0xa4, 0x9c, 0x7a, 0x3b, 0x20, 0x79, 0xe5, 0xb6, 0x22, 0xfa, 0x86, 0x73, 0xbe, + 0x18, 0x5e, 0x4e, 0xbf, 0x76, 0xfb, 0xf6, 0xa8, 0xb0, 0x36, 0x15, 0xf1, 0x76, 0x83, 0x41, 0x58, 0x27, 0x33, 0xcb, + 0x5c, 0xf2, 0xa5, 0xaf, 0xb5, 0x99, 0x7b, 0x4c, 0xef, 0x38, 0xd3, 0x0c, 0x19, 0x7d, 0x81, 0x99, 0xe9, 0x70, 0xb8, + 0x3d, 0xc7, 0xf2, 0xf8, 0xf0, 0xd3, 0xe3, 0xf7, 0x83, 0xf7, 0x18, 0xc2, 0x65, 0x85, 0x85, 0x7c, 0xe5, 0xc3, 0xac, + 0x6e, 0x5d, 0x3b, 0x2e, 0x9e, 0x0c, 0x9f, 0x43, 0xde, 0xa0, 0xeb, 0xa1, 0x29, 0xa2, 0x55, 0x7e, 0x47, 0xd1, 0x27, + 0x4a, 0x0e, 0x3a, 0x9e, 0x40, 0xed, 0x90, 0x0b, 0xf7, 0xeb, 0x63, 0x0e, 0x8a, 0x0e, 0x2c, 0xb5, 0xdf, 0x3f, 0x7f, + 0x4d, 0x84, 0xd2, 0x30, 0xde, 0xcf, 0xc3, 0xe8, 0xcf, 0xb8, 0x2c, 0xd6, 0x70, 0xc4, 0x0e, 0xe0, 0x73, 0x8f, 0xf5, + 0x35, 0xec, 0xd6, 0xf7, 0xfd, 0xc0, 0xdb, 0xf2, 0x37, 0xec, 0x2b, 0xf7, 0x2e, 0x87, 0x9f, 0xfc, 0xc7, 0xef, 0x41, + 0x7e, 0x42, 0x9c, 0x14, 0x0c, 0x89, 0xed, 0x28, 0x46, 0xad, 0xc3, 0xcf, 0x35, 0xc4, 0x6a, 0xbd, 0x46, 0xea, 0x2e, + 0x48, 0x7f, 0xaf, 0x90, 0xfd, 0x84, 0xc0, 0x6a, 0x92, 0x3e, 0x05, 0x26, 0xf1, 0x4d, 0x0d, 0x09, 0xa4, 0x69, 0x81, + 0x18, 0x1c, 0x28, 0x3e, 0x15, 0xfc, 0xeb, 0xf0, 0x33, 0xc9, 0x7f, 0x8b, 0x9a, 0x8f, 0xe1, 0x6f, 0x18, 0x9a, 0x49, + 0x75, 0x9f, 0xd6, 0x10, 0x11, 0x0d, 0xa7, 0x5e, 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, + 0x4c, 0x6e, 0x4a, 0x11, 0xfe, 0x39, 0xc1, 0x67, 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, + 0x65, 0xaf, 0x06, 0x8b, 0x7a, 0xc8, 0x6f, 0x6a, 0xf7, 0x7d, 0x39, 0x27, 0xe8, 0x91, 0xfd, 0x80, 0xe6, 0x60, 0xa0, + 0x66, 0x20, 0x65, 0x08, 0x6e, 0xe0, 0xd2, 0xef, 0xa9, 0x82, 0x7c, 0xf9, 0xbd, 0xcf, 0x42, 0x06, 0xae, 0x2c, 0x08, + 0x53, 0x2e, 0x15, 0x52, 0xe0, 0xb8, 0xa9, 0x07, 0x9f, 0x35, 0x3a, 0x89, 0x04, 0x9f, 0x12, 0x90, 0x24, 0x2d, 0x0f, + 0x24, 0x8d, 0x98, 0x0e, 0xc4, 0x85, 0xd2, 0x34, 0x2b, 0x29, 0xe2, 0x10, 0xbb, 0xea, 0x35, 0x12, 0x9e, 0x05, 0x8f, + 0x18, 0xac, 0x1d, 0x29, 0x5a, 0x7c, 0x35, 0xa6, 0x63, 0x1d, 0x36, 0x74, 0x2b, 0x8b, 0xfb, 0x4d, 0x52, 0xa7, 0x91, + 0xb8, 0xf2, 0x56, 0xc8, 0x9f, 0xff, 0x52, 0x22, 0x90, 0xde, 0xd5, 0x40, 0x0c, 0x82, 0x1f, 0xa0, 0xff, 0x80, 0x45, + 0x0e, 0x82, 0x52, 0x5d, 0x86, 0x79, 0x95, 0x51, 0x81, 0xb3, 0x1d, 0xdb, 0xce, 0x99, 0xaa, 0x5b, 0xf0, 0x59, 0x18, + 0x86, 0xb4, 0xb3, 0x55, 0x73, 0x72, 0xab, 0x37, 0x50, 0xcf, 0x24, 0x8e, 0xd4, 0x52, 0x1c, 0x69, 0x6b, 0xee, 0xd3, + 0xa5, 0xd7, 0x2d, 0x2f, 0x68, 0xb8, 0x00, 0xbd, 0x28, 0xdd, 0x75, 0x3e, 0xa1, 0xd0, 0x65, 0x35, 0xae, 0x86, 0xa2, + 0x0e, 0xe5, 0x18, 0x6b, 0x7f, 0xae, 0xe4, 0xf9, 0x1d, 0x58, 0x8f, 0xd0, 0xf0, 0x55, 0xa9, 0x83, 0xd8, 0x7e, 0xa2, + 0x77, 0x9d, 0x4a, 0xfd, 0x0d, 0x00, 0x03, 0xa7, 0x8e, 0x87, 0xfa, 0xa8, 0x9d, 0x42, 0xb6, 0x73, 0x6f, 0x89, 0x51, + 0xb9, 0x12, 0x9e, 0x2a, 0x2d, 0x4f, 0x29, 0xab, 0xbe, 0x16, 0xdc, 0xca, 0xee, 0xb3, 0x01, 0x64, 0xb4, 0x41, 0x81, + 0x3c, 0xa3, 0xb6, 0xc6, 0x83, 0x54, 0xd3, 0x2c, 0x71, 0x0c, 0x1f, 0x14, 0x69, 0x56, 0x81, 0xc5, 0xcb, 0x5c, 0x32, + 0x07, 0x05, 0xcb, 0xf5, 0x66, 0x33, 0xcd, 0x54, 0x5f, 0xe4, 0xf6, 0x46, 0xe3, 0x65, 0xfa, 0x6f, 0x96, 0x0c, 0x78, + 0x74, 0xf1, 0xc4, 0x0f, 0x20, 0x4d, 0x52, 0x3c, 0x40, 0x12, 0x6c, 0x0f, 0x76, 0xb1, 0xc3, 0xb0, 0x55, 0xac, 0xec, + 0xc9, 0xd3, 0xe5, 0x0e, 0x4d, 0xb9, 0x04, 0x97, 0x9c, 0x98, 0xcb, 0xa9, 0xef, 0x4b, 0xd6, 0x1b, 0x8a, 0x53, 0x36, + 0x4d, 0x40, 0x49, 0xa0, 0xdd, 0x82, 0xff, 0xc2, 0xa7, 0x86, 0x4e, 0x0b, 0xb0, 0xd4, 0x76, 0x03, 0xfe, 0x0b, 0xfd, + 0x62, 0xbb, 0x8b, 0xfa, 0x81, 0x79, 0xb0, 0x37, 0x8b, 0x2b, 0x63, 0xc0, 0x49, 0xe2, 0x4a, 0xf3, 0xc8, 0xf5, 0x83, + 0xa2, 0x4f, 0x97, 0xb5, 0x03, 0x67, 0x8a, 0x0b, 0xab, 0xd4, 0x26, 0xe9, 0xb5, 0xdf, 0x52, 0x13, 0x6f, 0xa2, 0xa4, + 0x2a, 0x6c, 0x87, 0xb4, 0x7f, 0x49, 0x39, 0x53, 0xc5, 0x1d, 0xa2, 0x27, 0xbb, 0x89, 0xab, 0xc0, 0x0b, 0xab, 0x8a, + 0x8d, 0x50, 0x9b, 0x91, 0xe5, 0x04, 0x4e, 0xf7, 0x58, 0x5d, 0xf0, 0xb1, 0x5d, 0xcd, 0x2e, 0x58, 0xc9, 0xd6, 0x4c, + 0xba, 0xcf, 0xdb, 0x31, 0x17, 0xf2, 0x4a, 0x2f, 0x8b, 0x56, 0x40, 0x7b, 0x10, 0x38, 0xfc, 0x5c, 0xd3, 0x3d, 0x7a, + 0xb6, 0xd9, 0xa6, 0x36, 0x1b, 0x5b, 0x8b, 0x10, 0x32, 0x10, 0x0d, 0x7d, 0x21, 0x67, 0x14, 0xf9, 0x2a, 0x2d, 0xd7, + 0x6a, 0x63, 0x95, 0xf1, 0x02, 0x13, 0x41, 0x86, 0xb3, 0xf0, 0x0e, 0x3d, 0xad, 0x47, 0x9a, 0x62, 0x12, 0x9c, 0x74, + 0xf1, 0x17, 0x60, 0x43, 0x79, 0x92, 0x9b, 0x03, 0x72, 0x00, 0x95, 0x4b, 0x51, 0x2a, 0x65, 0xf0, 0x6b, 0x75, 0x47, + 0xb6, 0x55, 0xff, 0x9d, 0x06, 0x32, 0xb8, 0x03, 0x7d, 0xdb, 0x0b, 0xad, 0x1d, 0xed, 0x5c, 0xd9, 0x9a, 0xb6, 0x65, + 0x9a, 0xc7, 0xc8, 0x62, 0x03, 0xc8, 0x27, 0xd2, 0x39, 0x10, 0x79, 0x4d, 0x34, 0xde, 0xd9, 0x53, 0x3e, 0x9e, 0x8a, + 0x87, 0xe4, 0xbd, 0xca, 0xf7, 0xcd, 0xbd, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x32, 0xf1, 0xc1, 0x6a, 0x6b, 0x5d, 0x62, + 0xbd, 0x55, 0x9a, 0x44, 0x37, 0x5c, 0x41, 0xc7, 0x91, 0xb8, 0x41, 0x0c, 0x8e, 0x19, 0xaf, 0xad, 0xb2, 0xf4, 0x15, + 0x96, 0xb9, 0x8e, 0x59, 0x32, 0x64, 0x52, 0xe7, 0x89, 0x82, 0x27, 0x3f, 0x4f, 0x48, 0x46, 0x44, 0xcd, 0xb6, 0x1c, + 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0xe0, 0x9b, 0x34, 0x01, 0x28, 0x97, 0x2f, 0x41, 0x2a, 0x0d, 0x11, 0x5c, + 0xb3, 0xbd, 0x64, 0x74, 0xe3, 0x68, 0x1d, 0x54, 0x49, 0xe6, 0x0e, 0xce, 0xed, 0x2c, 0x52, 0xea, 0xcd, 0x47, 0x18, + 0x76, 0xf2, 0x3e, 0xac, 0x13, 0xfc, 0x36, 0xa0, 0x26, 0x7d, 0x2a, 0xbc, 0x68, 0x04, 0x68, 0xea, 0x3b, 0x55, 0xc6, + 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, 0x98, 0x57, 0xd5, 0x40, 0x1b, + 0xe4, 0x76, 0x1d, 0x33, 0xa0, 0x51, 0xdb, 0x95, 0x47, 0x16, 0xe0, 0xd6, 0x4c, 0x04, 0x46, 0xce, 0xbf, 0xcb, 0xaf, + 0x55, 0x38, 0x4f, 0xbf, 0x1f, 0x7a, 0xfb, 0x6d, 0x10, 0x8d, 0xb6, 0x97, 0x6c, 0x17, 0x44, 0xa3, 0xdd, 0x65, 0xc3, + 0xe8, 0xf7, 0x13, 0xfa, 0xfd, 0xa4, 0x01, 0x55, 0x89, 0x30, 0x11, 0xf7, 0xfa, 0x8d, 0x5a, 0xbe, 0x52, 0xeb, 0x77, + 0x6a, 0xf9, 0x52, 0x0d, 0x6f, 0xed, 0x49, 0x24, 0x88, 0x2c, 0x8d, 0xcd, 0xbd, 0x64, 0x4b, 0xb5, 0x54, 0x3a, 0x46, + 0x95, 0x11, 0xb5, 0x74, 0x36, 0xc7, 0x8a, 0x91, 0x76, 0x0e, 0x4a, 0x06, 0x64, 0x5a, 0x5c, 0xd5, 0x98, 0x6e, 0x56, + 0xb4, 0xc4, 0x64, 0x84, 0x95, 0x6d, 0x79, 0xbb, 0x49, 0xd5, 0x74, 0x4e, 0x6e, 0x6e, 0x95, 0x72, 0x73, 0x2b, 0x78, + 0xfe, 0x0d, 0xdd, 0x72, 0xc9, 0xb5, 0x97, 0xd9, 0xb4, 0x50, 0xba, 0x65, 0x5c, 0x83, 0xad, 0x7d, 0x13, 0xc8, 0x32, + 0x1f, 0x28, 0x6a, 0x6c, 0x2f, 0x1a, 0xe5, 0x1b, 0x64, 0x2b, 0x62, 0xd4, 0x29, 0x0b, 0xc6, 0xdf, 0xee, 0xe8, 0x81, + 0x0c, 0x54, 0x55, 0xb5, 0x71, 0x70, 0x67, 0xa5, 0x3f, 0x2c, 0x2f, 0x9e, 0xb0, 0xc4, 0x4a, 0x27, 0x17, 0xaa, 0xd0, + 0x1f, 0x84, 0xe8, 0xa6, 0xb2, 0xe1, 0xe0, 0x50, 0x17, 0x5b, 0x19, 0x10, 0x7a, 0x98, 0xde, 0xdb, 0x58, 0xc9, 0x72, + 0xd7, 0x94, 0x2f, 0x66, 0x3c, 0xe1, 0x38, 0xfa, 0x72, 0xb5, 0x08, 0x6b, 0xb5, 0xc8, 0x4e, 0x80, 0x87, 0xd6, 0x6a, + 0x29, 0xe4, 0x6a, 0x11, 0xce, 0x4c, 0x17, 0x6a, 0xa6, 0x67, 0xa0, 0x80, 0x14, 0x6a, 0x96, 0x27, 0x00, 0x0b, 0x2f, + 0xcc, 0x0c, 0x17, 0x66, 0x86, 0xe3, 0x90, 0x1a, 0xff, 0x07, 0xbd, 0xd7, 0xb9, 0xe7, 0x96, 0xbb, 0xd1, 0x69, 0xc4, + 0xb7, 0xa3, 0x0d, 0xe6, 0xf8, 0x20, 0x9c, 0x54, 0xfd, 0x7e, 0x5a, 0x22, 0x56, 0x8f, 0x81, 0x11, 0x94, 0x43, 0xe5, + 0x68, 0xbf, 0x2c, 0x2c, 0xc9, 0x92, 0xb0, 0x24, 0xf7, 0x6a, 0x9c, 0x4b, 0xcb, 0xc5, 0xab, 0x24, 0x10, 0x89, 0x8c, + 0x97, 0xd2, 0x04, 0x9f, 0xf0, 0x72, 0x64, 0xa4, 0xe6, 0xc9, 0x22, 0xf5, 0x72, 0x96, 0xb1, 0x31, 0x62, 0x18, 0x85, + 0x7e, 0x53, 0xf5, 0xfb, 0x79, 0xe9, 0xe5, 0xd4, 0xce, 0x4f, 0xe0, 0x7a, 0x79, 0xea, 0x2c, 0x72, 0x84, 0xbc, 0x1a, + 0x49, 0x85, 0xe5, 0xb5, 0x52, 0x4f, 0x5f, 0x82, 0x0f, 0xea, 0xee, 0x8d, 0x02, 0x20, 0x2e, 0x72, 0xe9, 0x5f, 0x5b, + 0xc2, 0xa5, 0x29, 0x37, 0x30, 0xe8, 0x21, 0xcf, 0x49, 0x08, 0x95, 0x20, 0x24, 0x85, 0x75, 0xe3, 0xbe, 0x78, 0x32, + 0x71, 0xdd, 0x59, 0x6c, 0x60, 0x82, 0xc3, 0x01, 0x10, 0x0f, 0xa6, 0x5e, 0x34, 0xe0, 0xa5, 0x9a, 0x33, 0x1f, 0xbc, + 0x9c, 0x60, 0x32, 0x40, 0x55, 0x31, 0x70, 0xca, 0x7a, 0x2c, 0x1f, 0x19, 0x37, 0x33, 0xdf, 0x0f, 0xf0, 0xdd, 0xba, + 0x90, 0xe8, 0x0f, 0x0a, 0xa0, 0x20, 0x53, 0x00, 0x05, 0x89, 0x01, 0x28, 0x88, 0x0d, 0x40, 0xc1, 0xa6, 0xe1, 0x2b, + 0xa9, 0xc3, 0x8d, 0x80, 0x2e, 0xc2, 0x87, 0x9e, 0x85, 0x8d, 0x15, 0x8a, 0x67, 0x63, 0x36, 0x66, 0x85, 0xda, 0x79, + 0x72, 0x39, 0x15, 0x3b, 0x8b, 0xb1, 0xae, 0x22, 0xb7, 0x89, 0x17, 0x12, 0x8a, 0x9c, 0x73, 0x23, 0x51, 0x77, 0x3f, + 0xf7, 0x5e, 0x92, 0xb1, 0x64, 0xde, 0xd0, 0xa8, 0xc1, 0xbc, 0xec, 0x3a, 0x80, 0x69, 0xc9, 0xb7, 0x05, 0x0d, 0xa6, + 0x53, 0xe5, 0x11, 0x69, 0x12, 0xd4, 0xce, 0x65, 0x52, 0xe4, 0x84, 0x30, 0x09, 0x7a, 0x25, 0xf8, 0x8d, 0x44, 0xf9, + 0xff, 0xa6, 0x13, 0x3c, 0xc0, 0x31, 0xd1, 0x2a, 0xf9, 0x0a, 0x06, 0xcc, 0x9c, 0x3f, 0x93, 0x4e, 0xd9, 0x08, 0xc5, + 0x58, 0xa6, 0xf1, 0xe8, 0x2b, 0x1b, 0x22, 0xb4, 0xd5, 0x33, 0x34, 0x31, 0x41, 0x1d, 0xe0, 0x11, 0xfd, 0x35, 0xfa, + 0x6a, 0x28, 0x54, 0xba, 0x1a, 0xa9, 0x6b, 0x76, 0xce, 0xf9, 0xdb, 0xda, 0x70, 0x22, 0x63, 0xda, 0x14, 0xf8, 0x06, + 0x04, 0xf2, 0x0d, 0x04, 0x80, 0xab, 0xa6, 0x33, 0x7b, 0x05, 0x70, 0x0e, 0x04, 0xf0, 0x38, 0xef, 0x78, 0xfc, 0x40, + 0x7f, 0x15, 0xc7, 0xbd, 0xd3, 0x34, 0x6c, 0xff, 0x15, 0x18, 0x8b, 0xa1, 0x1c, 0xcf, 0x77, 0x0a, 0x92, 0x3d, 0x4a, + 0x59, 0xba, 0x6a, 0x22, 0x3b, 0x14, 0xeb, 0xd3, 0x9c, 0x32, 0x96, 0xb6, 0xe5, 0x18, 0x6d, 0xbc, 0x7e, 0x88, 0xc7, + 0x37, 0x37, 0x7a, 0xf2, 0x41, 0x0f, 0x6e, 0x6f, 0xaf, 0x5e, 0xf4, 0x98, 0xcd, 0xb7, 0x62, 0xf1, 0xac, 0x88, 0x13, + 0xa7, 0x75, 0xc8, 0x01, 0x0e, 0x72, 0x12, 0x02, 0xe9, 0x18, 0x97, 0x5a, 0x74, 0x50, 0xb3, 0x9c, 0xd7, 0xc0, 0x32, + 0x8b, 0x20, 0x1b, 0x20, 0xaa, 0x69, 0x2a, 0x56, 0xc3, 0x83, 0x52, 0x35, 0xa7, 0x54, 0x6a, 0xdf, 0x70, 0xb6, 0x3a, + 0x7d, 0x62, 0xd5, 0x26, 0xdc, 0xfa, 0xb7, 0xda, 0x13, 0xb4, 0x95, 0x34, 0x10, 0xea, 0xf9, 0x22, 0xbd, 0xa5, 0x28, + 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, + 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, 0xc9, 0x3f, 0x85, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, + 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, + 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, + 0x9a, 0xa7, 0xd5, 0x7b, 0xf5, 0xf7, 0xbb, 0x25, 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, + 0xe8, 0x16, 0xc0, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x04, 0x6b, 0xa8, 0xca, 0x53, 0x3e, 0x7b, 0xf9, 0x64, 0x07, + 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, + 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, + 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, + 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, 0x76, 0x03, 0x88, 0x81, 0xa5, 0x0e, 0x49, 0x56, 0x1d, 0xdb, 0xef, + 0xbf, 0x1c, 0x19, 0xde, 0x74, 0x44, 0x84, 0xd1, 0xbf, 0x2b, 0x10, 0xa0, 0x60, 0x99, 0xd9, 0xce, 0x4c, 0xba, 0xda, + 0xb3, 0x7a, 0xde, 0x6c, 0xf2, 0xae, 0xde, 0xb1, 0x9a, 0x96, 0x53, 0xd3, 0x2a, 0xab, 0x69, 0x93, 0x1c, 0x6a, 0x26, + 0xfa, 0x7d, 0x8d, 0x8f, 0x9a, 0xcf, 0x01, 0x97, 0x0d, 0x93, 0x5f, 0xce, 0xaa, 0x79, 0xbf, 0xef, 0xc9, 0x47, 0xf0, + 0x0b, 0x89, 0xcb, 0xdc, 0x1a, 0xcb, 0xa7, 0xaf, 0x88, 0xcf, 0xcc, 0x20, 0x1e, 0xdd, 0x1c, 0x41, 0x7d, 0x7d, 0x14, + 0x5e, 0xc7, 0x5c, 0x61, 0x33, 0x31, 0x7d, 0x09, 0x83, 0xe7, 0x09, 0x1f, 0xbc, 0xe5, 0xe8, 0x6f, 0xa4, 0x33, 0x53, + 0xb0, 0x90, 0x73, 0x7f, 0xf2, 0x12, 0xa1, 0x93, 0x11, 0xe9, 0x41, 0xa7, 0x13, 0x34, 0x64, 0xbf, 0xbf, 0x80, 0xce, + 0x6c, 0xa5, 0x52, 0xb6, 0x2a, 0x2a, 0xd3, 0x75, 0x5d, 0x94, 0x15, 0x74, 0x2c, 0xfd, 0xbc, 0x11, 0x32, 0xb3, 0x7e, + 0x66, 0x21, 0x3f, 0x2d, 0x24, 0xd6, 0x94, 0x6d, 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, + 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, + 0xf4, 0xb9, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, + 0x39, 0x79, 0x09, 0xe0, 0x74, 0x88, 0x88, 0x5b, 0x91, 0xa0, 0x63, 0xd5, 0x70, 0x67, 0xe1, 0x9e, 0xf6, 0xd2, 0xb8, + 0x97, 0xe6, 0x67, 0x69, 0xbf, 0x6f, 0x00, 0x34, 0x53, 0x44, 0x86, 0xc7, 0x19, 0xb9, 0x4d, 0x5a, 0x08, 0xa6, 0xb4, + 0xff, 0x6a, 0x0c, 0x09, 0x02, 0x01, 0xff, 0xa7, 0xf0, 0xde, 0x03, 0xda, 0x26, 0x6d, 0xc0, 0x55, 0x8f, 0xe9, 0xc0, + 0x6c, 0xc9, 0xd9, 0xaa, 0xb3, 0x01, 0x28, 0xa7, 0x4a, 0xeb, 0x29, 0x8f, 0x6b, 0x8a, 0x88, 0x54, 0x59, 0xa8, 0xdf, + 0x58, 0x4f, 0x26, 0xab, 0x5c, 0x64, 0xc8, 0x51, 0x99, 0xde, 0xd6, 0x8c, 0x10, 0xbb, 0xf4, 0xf3, 0x05, 0x2c, 0xd9, + 0xf8, 0x03, 0x4e, 0xde, 0x12, 0x20, 0x6d, 0x67, 0xed, 0xaa, 0xda, 0xe5, 0xb8, 0xb5, 0x9b, 0x03, 0x92, 0xaf, 0x37, + 0x1a, 0x8d, 0xb4, 0x9f, 0x9c, 0x80, 0xa1, 0xea, 0xa9, 0xa5, 0xd0, 0x63, 0xb5, 0xc2, 0xd6, 0xed, 0xc8, 0x65, 0x96, + 0x0c, 0xe6, 0x0b, 0xe3, 0xf8, 0xda, 0x7c, 0xf4, 0xe1, 0x52, 0x59, 0xbb, 0x8e, 0xf8, 0xfa, 0x4f, 0xb2, 0x5a, 0xdf, + 0xf3, 0xae, 0x6a, 0x02, 0xbe, 0xa8, 0x62, 0x4b, 0xbf, 0xe3, 0x3d, 0xd9, 0xbb, 0xf8, 0xda, 0x47, 0xec, 0x92, 0xef, + 0x79, 0x8b, 0x3a, 0xcf, 0x57, 0xbe, 0x6e, 0x54, 0xe9, 0xf6, 0x5e, 0xb2, 0xc0, 0xb5, 0x77, 0xd4, 0x34, 0xd6, 0x33, + 0x3f, 0x7a, 0x58, 0x84, 0x6c, 0xe7, 0x43, 0xef, 0xab, 0xe6, 0xe9, 0x59, 0x43, 0x6f, 0x52, 0x43, 0x1f, 0x7a, 0x51, + 0xb6, 0x4f, 0x4d, 0x23, 0x7a, 0x0d, 0x1b, 0xfa, 0xd0, 0x5b, 0x72, 0x72, 0x48, 0x30, 0x38, 0x35, 0xe6, 0x0f, 0x0f, + 0xa7, 0x33, 0xfc, 0x1d, 0x03, 0x2a, 0x31, 0x99, 0x4f, 0x8f, 0x69, 0x47, 0x01, 0x66, 0x54, 0xe9, 0xed, 0xd3, 0x03, + 0xdb, 0xf1, 0xb2, 0x1e, 0x5a, 0x7a, 0xf7, 0xe4, 0xe8, 0x76, 0xbc, 0xaa, 0xc6, 0x97, 0x72, 0xc8, 0xf3, 0x7c, 0x36, + 0x1a, 0x8d, 0x84, 0x41, 0xe7, 0xae, 0xf4, 0x06, 0x56, 0x20, 0x83, 0x8b, 0xea, 0x43, 0xb9, 0xf4, 0x76, 0xea, 0xd0, + 0xae, 0xfc, 0x49, 0x7e, 0x38, 0x14, 0x23, 0x73, 0x8c, 0x03, 0xce, 0x49, 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, + 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x15, 0x91, 0x57, 0x23, 0xe4, 0x43, 0xf0, 0xb3, 0x07, 0x6a, 0xf1, 0xa7, 0x5a, 0x10, + 0x7b, 0xe8, 0x53, 0xa5, 0x74, 0x88, 0x57, 0x05, 0x84, 0x08, 0x03, 0xde, 0x40, 0x3b, 0x28, 0xc1, 0x61, 0x87, 0x7b, + 0x8f, 0x08, 0xd1, 0x2f, 0xbc, 0x7c, 0x26, 0xc3, 0x95, 0x7b, 0x83, 0x6a, 0xce, 0x00, 0xb1, 0xd2, 0x67, 0xe0, 0x82, + 0x09, 0xa8, 0xa7, 0xf8, 0x14, 0xfd, 0xeb, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, 0x50, 0x11, 0x3d, 0xfb, 0xf9, 0x18, + 0xc0, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xe5, 0x6f, 0x80, 0x61, 0xa5, 0x24, 0xd1, 0xce, 0x29, 0x11, 0xb8, 0xf3, 0x91, + 0x2d, 0xfd, 0x28, 0x05, 0x62, 0xee, 0x78, 0x92, 0xc8, 0x1e, 0x6c, 0xe4, 0x04, 0x6e, 0x31, 0xe0, 0xd1, 0x01, 0xa8, + 0x5c, 0x29, 0xc8, 0xbd, 0xe6, 0x48, 0xee, 0xf8, 0xb1, 0xf7, 0xe3, 0xa0, 0x1e, 0xfc, 0xd8, 0x3b, 0x4b, 0x49, 0xee, + 0x08, 0xcf, 0xd4, 0x94, 0x10, 0xf1, 0xd9, 0x8f, 0x83, 0x7c, 0x80, 0x67, 0x89, 0x16, 0x69, 0x91, 0x5b, 0x4d, 0xd4, + 0xb8, 0x09, 0x6f, 0x13, 0x49, 0x43, 0x74, 0xd7, 0x79, 0x44, 0x2c, 0x00, 0x24, 0x8b, 0xcf, 0xe6, 0x0d, 0x45, 0xbd, + 0x9b, 0xf0, 0x2d, 0xba, 0xcb, 0x62, 0xbf, 0xbf, 0xca, 0xd3, 0xba, 0xa7, 0x43, 0x65, 0xf0, 0x05, 0xa9, 0x26, 0xc0, + 0xa3, 0xfd, 0x85, 0x39, 0x5e, 0xbd, 0xda, 0x1c, 0x29, 0x0b, 0x55, 0xa2, 0x7e, 0x8b, 0xd5, 0xac, 0x87, 0x88, 0xdc, + 0x59, 0x66, 0xec, 0xed, 0x05, 0xaf, 0xe4, 0xac, 0x8a, 0xed, 0x72, 0x7c, 0x45, 0x58, 0x5b, 0x49, 0x80, 0x8e, 0xd6, + 0x63, 0x6d, 0x8a, 0x91, 0x5f, 0x29, 0x24, 0xe0, 0xa2, 0x63, 0x6b, 0xa1, 0xd8, 0x78, 0x01, 0xfa, 0x92, 0x9d, 0x69, + 0x80, 0xf5, 0x46, 0xaf, 0x22, 0x6e, 0xcb, 0x07, 0x2a, 0xbc, 0xc9, 0x4d, 0x95, 0x59, 0xd9, 0x2c, 0xda, 0xfd, 0x54, + 0xf1, 0x0a, 0x71, 0xeb, 0x8d, 0xda, 0xa3, 0x00, 0xb5, 0x87, 0x16, 0xca, 0x00, 0x5d, 0x9a, 0x66, 0x00, 0xc8, 0x00, + 0x20, 0x53, 0x45, 0x7c, 0x26, 0x40, 0xa5, 0xad, 0x6e, 0x14, 0x38, 0x91, 0x5e, 0x00, 0xe3, 0x02, 0x2b, 0x7d, 0x64, + 0x23, 0x83, 0xc5, 0x16, 0x01, 0x6e, 0x39, 0xd2, 0x87, 0x69, 0x38, 0xd9, 0x46, 0x73, 0x98, 0xa4, 0xf9, 0x5d, 0x98, + 0xa5, 0x12, 0x5a, 0xe2, 0x95, 0xac, 0x31, 0x62, 0x01, 0xe9, 0xfb, 0xf4, 0xa2, 0xc8, 0x62, 0x82, 0x84, 0xb3, 0x9e, + 0x3a, 0x80, 0x6a, 0x72, 0xae, 0x35, 0xad, 0x9e, 0xd5, 0x26, 0x0f, 0x59, 0xa0, 0xb3, 0x07, 0x63, 0x52, 0xcb, 0x0d, + 0x3d, 0xb2, 0xbf, 0x72, 0x3c, 0x23, 0x7c, 0xd7, 0x33, 0x9c, 0xfa, 0xef, 0x63, 0x0d, 0xa4, 0x4c, 0x09, 0x20, 0xc8, + 0xe0, 0x68, 0x42, 0x28, 0x4f, 0xc7, 0x64, 0x6a, 0xf3, 0x23, 0x10, 0x8e, 0x08, 0x5e, 0xc1, 0x73, 0x43, 0xeb, 0x96, + 0x1b, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x59, 0xbc, 0xe0, 0xf7, 0x80, 0xcc, 0xa9, 0x57, 0x85, 0xec, 0xd9, 0x73, 0x31, + 0x9d, 0xcd, 0x83, 0x8f, 0x09, 0xed, 0x5f, 0x4c, 0xf8, 0x4d, 0x77, 0x95, 0x5c, 0x99, 0x5a, 0xf7, 0x26, 0x7a, 0xcc, + 0xe5, 0x4e, 0x9f, 0x56, 0x1c, 0x23, 0x9e, 0xc1, 0x2a, 0x20, 0xe7, 0x6c, 0xc8, 0x9f, 0x9e, 0x03, 0x76, 0xcb, 0x4a, + 0x78, 0x11, 0x7f, 0x1a, 0xca, 0x6a, 0x01, 0xf2, 0x23, 0xe7, 0x91, 0xf9, 0xe5, 0xab, 0xed, 0x50, 0xce, 0x29, 0x8a, + 0x68, 0x39, 0x35, 0x2d, 0x29, 0x64, 0x87, 0x9e, 0x82, 0xc9, 0xd4, 0x96, 0xbf, 0xef, 0x13, 0x97, 0xe4, 0x9b, 0x49, + 0x64, 0x5f, 0x07, 0x58, 0xb3, 0x56, 0xdd, 0x43, 0x37, 0x04, 0x03, 0x44, 0x46, 0x28, 0xb3, 0xb9, 0xbe, 0x5b, 0x0f, + 0x06, 0x0a, 0xe6, 0x57, 0xd0, 0x4d, 0x8b, 0x4e, 0x71, 0x80, 0x9c, 0xb5, 0xae, 0x51, 0xa9, 0x2a, 0x0e, 0x1d, 0xe6, + 0xdd, 0xb2, 0x2a, 0xbb, 0x2c, 0xbd, 0x10, 0xa4, 0x46, 0x5d, 0x05, 0x8b, 0x94, 0x8a, 0x28, 0xde, 0x93, 0x5f, 0x03, + 0x13, 0xcf, 0xac, 0x1c, 0xa5, 0xf1, 0x1c, 0x10, 0x83, 0x14, 0x10, 0xa7, 0xfc, 0x0a, 0xd0, 0x44, 0x17, 0x51, 0x98, + 0xbd, 0x8a, 0xab, 0xa0, 0xb6, 0x9a, 0xfe, 0xa7, 0x03, 0x19, 0x7b, 0x5e, 0xf7, 0xfb, 0x29, 0x31, 0xfa, 0x61, 0x14, + 0x06, 0xfe, 0x3d, 0x9e, 0xee, 0x9b, 0x20, 0x35, 0xaf, 0x7c, 0x84, 0x57, 0x74, 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, + 0xfc, 0x35, 0x82, 0xc3, 0xa7, 0x8e, 0x62, 0xbb, 0x4d, 0x95, 0x53, 0x1b, 0x83, 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xff, + 0x99, 0x78, 0xf9, 0x2c, 0x9a, 0x83, 0xa2, 0x34, 0xd3, 0x7c, 0x21, 0x85, 0x74, 0x13, 0xa0, 0x8f, 0x06, 0xa1, 0x56, + 0x57, 0xbe, 0x49, 0xbc, 0x54, 0x4d, 0x6b, 0xf3, 0x14, 0x6b, 0x14, 0x88, 0x59, 0x34, 0x6f, 0x58, 0x46, 0x87, 0xa4, + 0xba, 0x5c, 0x9a, 0x66, 0xbc, 0xb1, 0x9a, 0xa1, 0x5a, 0x71, 0xd4, 0x04, 0x35, 0x4a, 0x1f, 0xe1, 0x02, 0xf8, 0x0f, + 0xba, 0xe3, 0xa8, 0x46, 0x91, 0xa2, 0x01, 0x9f, 0x20, 0x46, 0xac, 0xd9, 0x3c, 0x61, 0xad, 0xa9, 0x6b, 0x46, 0xbf, + 0x2f, 0x43, 0x86, 0x4c, 0x12, 0xf2, 0xf4, 0xe1, 0x72, 0xfd, 0x40, 0xaa, 0x0b, 0xe0, 0x57, 0xae, 0xd8, 0xac, 0xd7, + 0x9b, 0x03, 0x5c, 0x2f, 0xac, 0x5f, 0xd8, 0xb8, 0x82, 0xf3, 0x4b, 0x82, 0xdf, 0x55, 0x3f, 0xc2, 0x2c, 0x83, 0x2a, + 0x20, 0xe3, 0x8f, 0x05, 0x55, 0x9c, 0xbb, 0x98, 0xd4, 0x2f, 0x47, 0xea, 0x82, 0x32, 0x4b, 0xe7, 0x16, 0x27, 0x08, + 0x38, 0x0f, 0xab, 0x27, 0x90, 0xec, 0xcb, 0xc7, 0x3e, 0xcd, 0x28, 0x50, 0x1d, 0x01, 0x3e, 0x9b, 0xf5, 0x43, 0xd8, + 0x3f, 0x20, 0xb2, 0x50, 0x7f, 0xf3, 0x5a, 0xce, 0x1a, 0x92, 0x07, 0x52, 0xcd, 0x7d, 0x0c, 0xa7, 0xc6, 0x02, 0x5f, + 0x5a, 0xf4, 0xa6, 0x82, 0xd7, 0x84, 0xcc, 0xbd, 0x40, 0x6b, 0xdf, 0x02, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, + 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, 0x3f, 0x72, 0xf1, 0x8b, 0x53, 0xa4, 0x67, 0xd1, 0x05, 0x06, 0xba, + 0x20, 0xf3, 0xc6, 0xbf, 0x2a, 0x58, 0xb9, 0x80, 0xde, 0x4b, 0xc5, 0x4a, 0x4e, 0xb6, 0x9d, 0xfa, 0xa3, 0x54, 0xf6, + 0xdb, 0x33, 0x6b, 0x02, 0xbf, 0x4b, 0xec, 0x97, 0xc8, 0xe4, 0x9b, 0x1e, 0x9b, 0x7c, 0x65, 0x58, 0x74, 0x6a, 0x19, + 0x9c, 0xd3, 0x23, 0x83, 0x73, 0x6f, 0x67, 0xd5, 0x26, 0x82, 0xa1, 0x20, 0x09, 0x34, 0x5d, 0x7a, 0x58, 0x37, 0xfd, + 0xf9, 0x49, 0x8b, 0x6a, 0xab, 0xf6, 0xad, 0xfb, 0x71, 0x88, 0x5d, 0xfc, 0x2e, 0xf1, 0x0c, 0x11, 0xa9, 0x0f, 0x74, + 0x60, 0x32, 0x78, 0xe2, 0xb2, 0xdf, 0x87, 0xc2, 0x66, 0xe3, 0xf9, 0xa8, 0x2e, 0x5e, 0x17, 0xf7, 0x80, 0xea, 0x50, + 0x81, 0x5d, 0x0e, 0x65, 0x28, 0x23, 0x36, 0xb5, 0xe5, 0x9e, 0x3f, 0xae, 0xc3, 0x1c, 0xe4, 0x1d, 0x0d, 0x8f, 0x73, + 0x06, 0x62, 0x18, 0x7c, 0xfd, 0xc7, 0x47, 0xfb, 0xb4, 0xf9, 0xf1, 0x0c, 0xbe, 0x3b, 0x3a, 0x7b, 0x8f, 0x74, 0x37, + 0x67, 0xeb, 0xb2, 0xb8, 0x4b, 0x63, 0x71, 0xf6, 0x23, 0xa4, 0xfe, 0x78, 0x56, 0x94, 0x67, 0x3f, 0xaa, 0xca, 0xfc, + 0x78, 0x46, 0x0b, 0x6e, 0xf4, 0x87, 0x35, 0xf1, 0x7e, 0xaf, 0x34, 0x03, 0xda, 0x12, 0x22, 0xb3, 0xb4, 0xfa, 0x11, + 0x94, 0x88, 0x8a, 0x1f, 0x55, 0x46, 0xb5, 0x5a, 0x3b, 0xce, 0xfb, 0x44, 0x23, 0x65, 0xd3, 0x84, 0xc4, 0xd5, 0x12, + 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xdf, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x39, 0x7f, 0x9a, 0x8f, 0xb6, 0xf4, 0x35, 0xf8, + 0xd6, 0xe1, 0x90, 0x8f, 0x76, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x77, 0x24, 0x7b, 0x07, 0x6b, 0x0b, 0x9c, 0x20, + 0xc0, 0x01, 0xe0, 0x1f, 0x0e, 0xf4, 0x7b, 0x27, 0x7f, 0xab, 0xdd, 0xd2, 0xaa, 0xe7, 0xb3, 0x16, 0x77, 0xc6, 0xab, + 0xda, 0x10, 0xb5, 0xed, 0x25, 0xb6, 0xf4, 0xbe, 0x69, 0x50, 0x53, 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x8a, 0xc3, 0x82, + 0x94, 0x90, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0x58, 0x7a, 0x72, 0xdf, 0xe1, 0xe5, 0xd6, 0xf7, 0x01, 0x49, + 0xab, 0x70, 0xfe, 0xce, 0x0b, 0x0d, 0x3c, 0x7a, 0x91, 0x57, 0x45, 0x26, 0x46, 0x82, 0x46, 0xf9, 0x15, 0x89, 0x33, + 0x67, 0x58, 0x8b, 0x33, 0x05, 0x16, 0x16, 0x12, 0x24, 0x78, 0x51, 0x52, 0x7a, 0x70, 0xf6, 0x68, 0x5f, 0x36, 0x7f, + 0x10, 0x3c, 0xc4, 0x68, 0x01, 0x8c, 0x38, 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0xba, 0xcd, 0x0b, + 0x08, 0xd1, 0x3c, 0x93, 0x8a, 0xd5, 0xf2, 0x0c, 0x18, 0xf3, 0x44, 0x7c, 0x16, 0x56, 0x72, 0x1a, 0x54, 0x1d, 0xc5, + 0xaa, 0x6d, 0x3c, 0xca, 0x3d, 0xa0, 0xf8, 0x7e, 0x9f, 0x00, 0x97, 0xbb, 0xcf, 0x5e, 0x2a, 0xd7, 0x54, 0xd2, 0x23, + 0xcf, 0x21, 0x5a, 0xf2, 0x51, 0x02, 0x14, 0xcf, 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, + 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, + 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0x2d, 0xcc, 0xbd, 0x10, 0x86, 0x2a, + 0xe1, 0xde, 0xab, 0x7a, 0x16, 0xca, 0x4d, 0xd1, 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, + 0xaf, 0x13, 0x2f, 0x06, 0xc3, 0xf5, 0x92, 0x97, 0xb3, 0x8d, 0x59, 0x08, 0x87, 0xc3, 0x66, 0x52, 0xcc, 0x96, 0x10, + 0xe6, 0xba, 0x9c, 0x1f, 0x0e, 0x5d, 0x2d, 0x5b, 0x0b, 0x0f, 0x1e, 0xaa, 0x16, 0x6e, 0x1a, 0x96, 0xc3, 0xcf, 0x64, + 0x16, 0x63, 0xfb, 0x1a, 0x9f, 0xd9, 0x9f, 0x2f, 0xba, 0x67, 0x09, 0x92, 0x6f, 0xac, 0x81, 0x76, 0x6c, 0xd6, 0xee, + 0x70, 0x35, 0x02, 0x92, 0xd2, 0xdd, 0xe8, 0x1c, 0xcb, 0x4e, 0x9e, 0x12, 0xe4, 0x8e, 0x56, 0x60, 0xbf, 0xfb, 0xc6, + 0x9f, 0x68, 0xb1, 0x07, 0xed, 0x36, 0xb6, 0x84, 0xa8, 0xa6, 0x3d, 0x97, 0x2b, 0xc5, 0xd2, 0x0d, 0x96, 0x36, 0x7a, + 0x3e, 0xac, 0xcf, 0x7d, 0x23, 0x07, 0x0a, 0xc6, 0x88, 0xa7, 0xd6, 0x41, 0x34, 0x9b, 0x03, 0x0d, 0x06, 0x9a, 0x47, + 0x78, 0x6a, 0xa1, 0x83, 0x32, 0x6b, 0xc3, 0xfe, 0x29, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, + 0x31, 0xc5, 0xf6, 0xf8, 0xa5, 0x52, 0x54, 0x78, 0x6c, 0x47, 0x5c, 0x6b, 0x1f, 0x45, 0x6d, 0xa8, 0x1c, 0xfe, 0x2d, + 0xec, 0x23, 0xec, 0x0b, 0x9a, 0x20, 0x0c, 0x76, 0xfd, 0x99, 0x40, 0x88, 0x58, 0x88, 0x17, 0xfc, 0x52, 0x49, 0x2a, + 0x3a, 0xe1, 0xb3, 0x5d, 0x09, 0xbc, 0x75, 0x18, 0xd0, 0x27, 0xe4, 0x67, 0x22, 0x61, 0x68, 0x26, 0xf4, 0x8e, 0xfe, + 0x3b, 0xb1, 0x93, 0x4d, 0x72, 0x2b, 0xe4, 0x03, 0x49, 0x25, 0xc1, 0x04, 0x2b, 0x2f, 0x94, 0xaf, 0xdc, 0x0b, 0xa5, + 0xd6, 0x5a, 0xd0, 0xfa, 0xe5, 0x3f, 0x25, 0x9e, 0xc1, 0xdf, 0x03, 0x19, 0x83, 0x6e, 0x23, 0xaa, 0x49, 0x8e, 0xe9, + 0xa3, 0x74, 0x9e, 0x81, 0x0a, 0xe8, 0x6c, 0x9d, 0x85, 0xf5, 0xb2, 0x28, 0x57, 0xad, 0x48, 0x51, 0x59, 0xfa, 0x48, + 0x3d, 0xc6, 0xbc, 0x30, 0x4f, 0x4e, 0xe4, 0x83, 0x47, 0x00, 0x8c, 0x47, 0x79, 0x5a, 0x75, 0x94, 0xd6, 0x0f, 0x2c, + 0x03, 0x46, 0xe0, 0x44, 0x19, 0xf0, 0x08, 0xcb, 0xc0, 0x3c, 0xed, 0x32, 0xd4, 0x20, 0xd6, 0xa8, 0xba, 0x52, 0x1b, + 0xcc, 0x89, 0xa2, 0xe4, 0x53, 0x2c, 0xad, 0x30, 0x86, 0xa6, 0xae, 0x3c, 0xb2, 0x5e, 0x72, 0xc2, 0x9e, 0xec, 0x06, + 0xd2, 0x2d, 0x6c, 0x14, 0xce, 0xa0, 0x6b, 0x59, 0xa2, 0x5c, 0x74, 0xcb, 0x88, 0x32, 0x11, 0x52, 0x3f, 0x7b, 0x38, + 0xd3, 0x6a, 0xbf, 0xb1, 0x93, 0xf6, 0xed, 0x91, 0xa2, 0x17, 0x0c, 0xda, 0xa7, 0x3d, 0x52, 0xea, 0x59, 0x23, 0x97, + 0x81, 0x2d, 0x5d, 0xaa, 0x7a, 0xfe, 0x1b, 0x94, 0xef, 0x60, 0x66, 0x9c, 0xcd, 0xfe, 0xd0, 0x9b, 0xdb, 0xa3, 0x7d, + 0xdd, 0xfc, 0xc1, 0x7a, 0x3d, 0xd8, 0x1a, 0x64, 0xe2, 0x33, 0xc5, 0x42, 0x65, 0x15, 0x62, 0x05, 0x69, 0xff, 0x5b, + 0x78, 0x7f, 0xc0, 0x5b, 0x23, 0x34, 0x2b, 0xe3, 0x61, 0x3e, 0x7a, 0xb4, 0x17, 0xcd, 0x1f, 0x9d, 0x65, 0x5b, 0xb9, + 0x2a, 0x99, 0xed, 0x8f, 0xa3, 0xa4, 0x39, 0x7b, 0xb8, 0x46, 0x52, 0x07, 0xf8, 0x70, 0x7d, 0x86, 0x0f, 0x54, 0x42, + 0xa9, 0x05, 0x55, 0x0d, 0x5a, 0x1f, 0xfb, 0xa3, 0xf5, 0x9c, 0x3e, 0x7e, 0x2c, 0xa7, 0x5b, 0x52, 0x84, 0xf1, 0x03, + 0x83, 0x29, 0x3b, 0x71, 0xea, 0x92, 0x37, 0x43, 0x7a, 0xd7, 0xad, 0x92, 0xba, 0xec, 0x51, 0x22, 0x08, 0x75, 0xb0, + 0x7e, 0xb1, 0x1f, 0xc2, 0xcc, 0x16, 0xfd, 0x61, 0xb3, 0x9a, 0x13, 0x20, 0x22, 0xa0, 0xb5, 0xca, 0xfb, 0xc0, 0x31, + 0x5f, 0x98, 0x35, 0x37, 0xa4, 0x5b, 0x6f, 0xae, 0xb4, 0x57, 0x52, 0x40, 0x3f, 0x07, 0x99, 0xdb, 0x47, 0xb7, 0x5c, + 0xb5, 0xcc, 0x73, 0x69, 0xcb, 0x01, 0x8b, 0x16, 0x02, 0x35, 0x3b, 0x97, 0x0e, 0x07, 0x0a, 0x42, 0x5d, 0x89, 0x2a, + 0xe2, 0xea, 0x28, 0x5a, 0x88, 0x5a, 0xad, 0xda, 0xe5, 0x64, 0x53, 0x21, 0x5b, 0x12, 0x41, 0x46, 0xc9, 0x5e, 0x09, + 0xf5, 0x51, 0xae, 0xf6, 0x4c, 0xc3, 0x01, 0x9a, 0x80, 0x4d, 0x1b, 0xfc, 0x2d, 0x70, 0x2f, 0x83, 0x33, 0xd3, 0x3e, + 0x0d, 0x23, 0xe0, 0x34, 0x87, 0x98, 0x3f, 0xbf, 0xeb, 0x41, 0x05, 0x0f, 0x3a, 0xd2, 0x5f, 0xd5, 0xb3, 0x02, 0xcf, + 0xdc, 0x13, 0xcf, 0x5f, 0x9e, 0x48, 0x2f, 0x73, 0x78, 0xa0, 0x69, 0x10, 0x33, 0xfe, 0xac, 0x2c, 0xc3, 0xdd, 0x68, + 0x59, 0x16, 0x2b, 0x2f, 0xd2, 0xfb, 0x78, 0x26, 0xc5, 0x40, 0x62, 0xc6, 0xcc, 0xe8, 0x2a, 0xd6, 0x71, 0x0e, 0xe3, + 0xde, 0x9e, 0x84, 0x15, 0xda, 0x3f, 0x4b, 0xec, 0x75, 0x01, 0x58, 0x0e, 0x59, 0x83, 0x56, 0x78, 0xa7, 0xdb, 0xdb, + 0x3d, 0x2e, 0xd9, 0x51, 0xdc, 0x00, 0xfa, 0x59, 0x0d, 0x2d, 0x13, 0xd4, 0x32, 0xeb, 0x4e, 0x26, 0x53, 0x24, 0x97, + 0x6f, 0xc3, 0x5e, 0xb2, 0x32, 0x9f, 0x37, 0x72, 0x7b, 0x78, 0x1b, 0xae, 0x44, 0xac, 0x2d, 0xe8, 0xa4, 0x23, 0xe3, + 0x70, 0x2f, 0x34, 0x37, 0xd2, 0xfd, 0xa3, 0x2a, 0x09, 0x4b, 0x11, 0xc3, 0x2d, 0x90, 0xed, 0xd5, 0xb6, 0x12, 0x94, + 0xc0, 0x07, 0xfb, 0xbe, 0x14, 0xcb, 0x74, 0x2b, 0x00, 0xd7, 0x81, 0xff, 0x26, 0x11, 0x09, 0xdd, 0x9d, 0x87, 0x28, + 0xd6, 0xc8, 0xfb, 0x06, 0xd1, 0xd8, 0x3f, 0x81, 0x9c, 0x06, 0x64, 0x22, 0xc5, 0x48, 0x16, 0x0c, 0x7c, 0x00, 0x39, + 0x5f, 0x83, 0x49, 0x6e, 0x9a, 0x7b, 0x7e, 0x90, 0xeb, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, 0xb8, 0xd6, 0x2c, 0x07, 0xaf, + 0x98, 0x88, 0xff, 0xa3, 0xf6, 0x4a, 0x96, 0xb3, 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, + 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, + 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, 0x41, 0xe8, 0x1f, 0x35, 0x20, 0x6d, 0x30, 0x49, 0x93, 0x50, 0xf9, + 0xe0, 0x82, 0x6e, 0x18, 0x9b, 0x2b, 0x97, 0xab, 0x26, 0x55, 0xcb, 0x2f, 0x47, 0xd4, 0x77, 0xb5, 0xe4, 0x52, 0x6d, + 0x3e, 0x35, 0xca, 0x1a, 0x41, 0x26, 0x47, 0xe9, 0xf7, 0x29, 0x17, 0x6e, 0x65, 0x4c, 0xd6, 0x87, 0x83, 0x57, 0x70, + 0x53, 0xe3, 0x17, 0x39, 0x11, 0x8a, 0xda, 0x43, 0x22, 0x6c, 0xed, 0x56, 0xe8, 0xde, 0xe3, 0x46, 0x69, 0x1e, 0x65, + 0x9b, 0x58, 0x54, 0x5e, 0x2f, 0x01, 0x6b, 0x71, 0x0f, 0x78, 0x51, 0x69, 0xe9, 0x57, 0xac, 0x00, 0xf4, 0x00, 0x29, + 0x6c, 0xbc, 0x40, 0x06, 0xac, 0x77, 0x5e, 0xea, 0xf7, 0xfb, 0xc6, 0x94, 0xff, 0xee, 0x3e, 0x07, 0x92, 0x42, 0x51, + 0xd6, 0x3b, 0x98, 0x40, 0x70, 0xed, 0x24, 0xed, 0x59, 0xcd, 0x9f, 0xae, 0x6b, 0x0f, 0xf8, 0xad, 0x7c, 0x8b, 0xc4, + 0xea, 0x93, 0x7d, 0xb1, 0xd9, 0xa7, 0xd5, 0x47, 0xa3, 0x71, 0x10, 0x2c, 0xad, 0x5e, 0x69, 0x95, 0x43, 0xde, 0xf0, + 0x02, 0x44, 0x2a, 0xeb, 0xea, 0x5a, 0x39, 0x57, 0xd7, 0x82, 0x23, 0x97, 0x6c, 0xc9, 0x73, 0xf8, 0x2f, 0xe4, 0x5e, + 0x79, 0x38, 0x14, 0x7e, 0xbf, 0x9f, 0xce, 0x48, 0x2b, 0x0b, 0xec, 0x69, 0xeb, 0xda, 0x0b, 0xfd, 0xc3, 0xe1, 0x05, + 0x78, 0x8d, 0xf8, 0x87, 0x43, 0xd9, 0xef, 0x7f, 0x30, 0x37, 0x99, 0xf3, 0xb1, 0x52, 0xca, 0x5e, 0xa2, 0xd2, 0xfd, + 0x75, 0xc2, 0x7b, 0xff, 0x7b, 0xf4, 0xbf, 0x47, 0x97, 0x3d, 0xd9, 0xf5, 0x1f, 0x12, 0x3e, 0xc3, 0x1b, 0x3a, 0x53, + 0x97, 0x73, 0x26, 0xdd, 0xdd, 0x95, 0x1f, 0x7a, 0x4f, 0x43, 0xc5, 0xf7, 0xe6, 0xa6, 0x8d, 0xff, 0xa8, 0x8e, 0x34, + 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x43, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0x1c, 0x25, 0x43, 0xee, 0xe6, + 0x16, 0xa6, 0x03, 0xfb, 0x71, 0xf3, 0x55, 0xf2, 0xe2, 0x2c, 0x85, 0x6b, 0x6f, 0x3e, 0x4b, 0xe7, 0x53, 0xb0, 0xae, + 0x0c, 0xf3, 0x59, 0x3d, 0x0f, 0x20, 0x75, 0x08, 0x69, 0xd6, 0x34, 0xfc, 0x67, 0xe5, 0x0a, 0xde, 0xda, 0xe3, 0xdd, + 0xc0, 0x45, 0xa9, 0x23, 0x7d, 0xd2, 0x46, 0xd3, 0x25, 0x95, 0xfc, 0x07, 0x91, 0xc7, 0x18, 0xb3, 0xf1, 0x82, 0x78, + 0x3f, 0x8b, 0xfc, 0xba, 0x00, 0xec, 0x22, 0x00, 0x43, 0x4e, 0xe7, 0x8e, 0x24, 0xfe, 0x32, 0xf9, 0xfe, 0x8f, 0xe9, + 0xd2, 0xde, 0x97, 0xc5, 0x6d, 0x29, 0xaa, 0xea, 0xa8, 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, + 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0xe7, 0xbb, 0x57, + 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, + 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, 0xef, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, + 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, 0xfe, 0x54, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, + 0xb2, 0xbc, 0x3d, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x53, + 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, 0x9b, 0x79, 0xe2, 0x29, 0xd0, 0x31, 0x3f, 0x45, 0x57, 0xc5, + 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, 0xf1, 0xd5, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, + 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, + 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xb3, 0xb3, 0x07, + 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, + 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, + 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, + 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, + 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xc1, 0xb6, + 0xff, 0x2a, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, 0x37, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, + 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, + 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xab, 0x17, 0x67, 0x3f, 0xf6, 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xcf, 0x56, + 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, + 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, + 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, + 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x79, 0x02, 0xa1, 0x16, 0xcc, 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, + 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, + 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, 0xfd, 0x48, 0x05, 0xe5, 0xfc, 0x1f, 0xde, 0xde, 0x85, + 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, + 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, + 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, + 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0xec, 0xa5, 0x7a, 0x52, 0xae, 0x5f, 0x16, 0x8e, 0x32, + 0x65, 0x3f, 0xc4, 0x36, 0x46, 0x40, 0x75, 0xcb, 0x62, 0x13, 0x2e, 0x00, 0xb7, 0x73, 0x42, 0x9d, 0xf1, 0x1e, 0x6b, + 0x02, 0x73, 0x9a, 0x10, 0x14, 0xe6, 0x3a, 0x58, 0x18, 0x00, 0x7a, 0xd7, 0x1e, 0x6d, 0x39, 0xe9, 0x12, 0x2c, 0x9e, + 0x1b, 0x58, 0xbc, 0xba, 0x58, 0x54, 0x57, 0x5c, 0xcb, 0x2d, 0x6c, 0x4a, 0x59, 0xc5, 0x10, 0x40, 0xa0, 0x19, 0x33, + 0xec, 0x96, 0xbb, 0x1c, 0xc9, 0xba, 0x28, 0xb8, 0xd8, 0x0b, 0x0c, 0xdd, 0x8c, 0x4b, 0x66, 0x0e, 0xae, 0x66, 0x58, + 0x27, 0x15, 0x05, 0xd8, 0xd5, 0x05, 0xc8, 0x5e, 0x18, 0xea, 0xba, 0x99, 0x2d, 0xd7, 0x81, 0xaf, 0x4b, 0x17, 0xbe, + 0xa4, 0xe0, 0xe5, 0x4a, 0x8a, 0x32, 0xbb, 0xe6, 0x3f, 0xd9, 0x97, 0xcd, 0x58, 0x52, 0x68, 0x47, 0xfa, 0xba, 0xdd, + 0x1d, 0x2d, 0xc6, 0xb1, 0xe5, 0xf8, 0x96, 0x4a, 0xd7, 0x7a, 0x54, 0xbd, 0x10, 0xda, 0x3a, 0xd7, 0x32, 0x4b, 0x53, + 0x2e, 0x5e, 0x89, 0x34, 0x4b, 0xbc, 0xe4, 0x58, 0xc7, 0xaa, 0x76, 0x41, 0xb0, 0x5c, 0x98, 0xe4, 0x67, 0x59, 0x89, + 0xb1, 0x83, 0x1b, 0x8d, 0x6a, 0x45, 0x9d, 0x32, 0x31, 0x30, 0xe4, 0x7b, 0x0c, 0xbe, 0xcd, 0x8a, 0x04, 0x18, 0x7e, + 0x4c, 0xd4, 0x97, 0xf4, 0x14, 0x02, 0x3e, 0xa8, 0xd0, 0xdc, 0xcf, 0x38, 0x82, 0x5f, 0x5b, 0x95, 0x39, 0x30, 0xd9, + 0x5a, 0x05, 0x89, 0xb8, 0x77, 0xd9, 0x5c, 0x2f, 0xa2, 0x85, 0xba, 0x0b, 0xf5, 0xe2, 0xdd, 0xae, 0x97, 0x28, 0x3a, + 0xe0, 0xe4, 0xa7, 0xc1, 0x8b, 0x38, 0xcb, 0x79, 0x7a, 0x50, 0xc9, 0x03, 0xb5, 0xa1, 0x0e, 0x94, 0x33, 0x07, 0xec, + 0xbc, 0x6f, 0xab, 0x03, 0xbd, 0xa6, 0x0f, 0x74, 0x3b, 0x0f, 0xe0, 0x82, 0x81, 0x3b, 0xf7, 0x32, 0xbb, 0xe6, 0xe2, + 0x00, 0x94, 0x81, 0xd6, 0x78, 0xa0, 0x2e, 0xab, 0x91, 0x9a, 0x18, 0x1d, 0xc3, 0x3a, 0xd1, 0x07, 0x73, 0x40, 0x7f, + 0x86, 0xb0, 0xf6, 0xad, 0xb7, 0x2b, 0x7d, 0xd0, 0x06, 0xf4, 0xc5, 0xd2, 0xf4, 0x41, 0x07, 0x8e, 0x57, 0xd1, 0x81, + 0x1b, 0x43, 0xaa, 0x41, 0x5b, 0x8d, 0xac, 0x02, 0xc5, 0x1b, 0xde, 0xe2, 0xdd, 0xbb, 0x96, 0x6c, 0xbd, 0x97, 0x88, + 0xf1, 0x95, 0x89, 0x2a, 0xce, 0xc4, 0xa9, 0x97, 0xca, 0x6b, 0xed, 0x24, 0x23, 0x8c, 0x6f, 0x59, 0x49, 0xfd, 0x1d, + 0x62, 0x6e, 0x91, 0xe6, 0x30, 0x78, 0x15, 0x56, 0x64, 0xc6, 0xfb, 0x7d, 0x39, 0x93, 0x51, 0x39, 0x13, 0x87, 0x65, + 0xa4, 0xc0, 0xda, 0xee, 0x12, 0x01, 0xdd, 0x2b, 0x01, 0xf2, 0x05, 0x40, 0xd5, 0x7d, 0xc2, 0x9f, 0xfb, 0xa4, 0x3e, + 0x9d, 0x42, 0x9f, 0x42, 0x5b, 0xaf, 0xb8, 0x82, 0x78, 0x55, 0x37, 0x46, 0xb6, 0x51, 0x41, 0x8b, 0xc7, 0xf2, 0xac, + 0x36, 0x8c, 0xcd, 0xa9, 0xf5, 0xaf, 0x37, 0x1b, 0x4c, 0xd9, 0x5c, 0xa8, 0x55, 0x18, 0x92, 0xe8, 0x53, 0xe9, 0x45, + 0x12, 0xb1, 0xb0, 0x59, 0xad, 0xcd, 0x6f, 0xc2, 0x80, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, + 0x55, 0x5f, 0x6b, 0x69, 0x91, 0x69, 0xf3, 0xad, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, + 0x97, 0xb7, 0xac, 0x46, 0x98, 0x00, 0xaf, 0x74, 0x06, 0xdd, 0x68, 0x3c, 0x10, 0xcb, 0x6a, 0x54, 0xac, 0x85, 0x40, + 0xe0, 0x61, 0xc8, 0x31, 0xb3, 0x84, 0x24, 0xfb, 0xcc, 0x7f, 0x50, 0x71, 0x16, 0x8a, 0xf8, 0xc6, 0x20, 0x7b, 0x57, + 0xd6, 0xb5, 0xbb, 0x8e, 0xfc, 0x9c, 0x58, 0x58, 0xed, 0x3f, 0x34, 0x8f, 0x5a, 0xe3, 0x2c, 0xa0, 0xad, 0x69, 0x75, + 0xc3, 0xe1, 0x1e, 0xd5, 0xb1, 0x28, 0x0d, 0x36, 0xb1, 0x47, 0x96, 0x8b, 0xd6, 0x31, 0x83, 0x06, 0xf4, 0xb7, 0xd9, + 0xd5, 0xfa, 0x0a, 0x01, 0xdc, 0x4a, 0x64, 0x9d, 0xa4, 0xf2, 0x2f, 0x69, 0x8f, 0xba, 0xb6, 0xa7, 0xf2, 0xbf, 0x6d, + 0x53, 0xe5, 0xd0, 0x62, 0xca, 0x63, 0x37, 0x67, 0x81, 0xea, 0x48, 0x10, 0x05, 0x6a, 0xeb, 0x05, 0x53, 0xef, 0x94, + 0x29, 0x3a, 0x40, 0xa0, 0x0b, 0x73, 0x86, 0x7d, 0xc5, 0x11, 0x63, 0x96, 0x4a, 0x0c, 0xa6, 0x3e, 0xc6, 0xa8, 0xa6, + 0xb5, 0x02, 0x74, 0xfd, 0x74, 0x0b, 0x7f, 0xa2, 0xa2, 0x46, 0x43, 0xad, 0x91, 0x14, 0x8a, 0x26, 0x2a, 0x14, 0x59, + 0x5a, 0xe8, 0xb8, 0x0a, 0x9d, 0x44, 0xc2, 0x12, 0xd0, 0x30, 0x21, 0x3a, 0xa9, 0xc0, 0x5b, 0x03, 0x38, 0xf3, 0x71, + 0x51, 0xae, 0x0b, 0x6d, 0x30, 0xf7, 0x32, 0xbe, 0xe6, 0xaf, 0x9e, 0x39, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa7, 0x05, + 0x79, 0x19, 0x72, 0x8a, 0x0e, 0x4c, 0xec, 0x64, 0x8b, 0xc6, 0x18, 0x65, 0xad, 0xa3, 0x5e, 0xbc, 0xd5, 0xa1, 0x58, + 0xb4, 0x09, 0xde, 0x3d, 0x9e, 0x22, 0xda, 0xf0, 0x50, 0x18, 0xab, 0x6a, 0x7c, 0x2a, 0x59, 0x4b, 0x0f, 0x56, 0xf0, + 0x74, 0x9d, 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xc5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, + 0x2b, 0xf8, 0x7c, 0x81, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, 0xb8, 0x19, 0x05, 0x75, 0x74, 0x15, 0xaf, 0x1a, + 0x2a, 0x12, 0x3e, 0x2f, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, 0x95, 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0x03, + 0x5b, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, 0x99, 0x77, 0xcf, 0x8c, 0x96, 0x33, 0x8b, 0xc6, + 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x59, 0x50, 0xc4, 0x69, 0x16, 0xe7, 0xe0, 0xb7, 0x19, 0x17, 0x98, 0x31, + 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0xd0, 0x76, 0xe7, 0x2a, 0xb5, 0xae, 0x41, 0x40, 0xf6, 0x12, 0xac, 0x5e, 0x1a, 0x3a, + 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x12, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, + 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x6e, 0xf7, 0xcf, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, + 0x31, 0xf6, 0xcf, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, + 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, + 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, + 0x58, 0x87, 0xdb, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, + 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, + 0x14, 0xb6, 0xc5, 0x6e, 0xa7, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, 0x51, 0xfc, 0x27, 0xf7, 0xc2, 0x4e, + 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x4f, 0x0e, 0x17, 0x89, 0x1f, 0xa4, 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, + 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x9e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, + 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, + 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, + 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, + 0x71, 0xac, 0x89, 0x6a, 0xc1, 0x8f, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, + 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, + 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, + 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, + 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, + 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0x77, 0x0f, 0x09, 0x55, 0x71, 0x6f, 0x78, 0x3b, 0xee, 0x8d, 0x13, 0x7e, 0xcd, + 0xc5, 0x42, 0x87, 0x6a, 0x31, 0x97, 0x2c, 0xbf, 0xb5, 0xde, 0x2d, 0x49, 0x6a, 0x05, 0xb4, 0xcf, 0xb2, 0xa0, 0x26, + 0x02, 0x40, 0xfe, 0xf0, 0x17, 0x08, 0x9d, 0xe1, 0x6f, 0x8f, 0xc1, 0x15, 0x29, 0xbc, 0x73, 0x08, 0x84, 0x35, 0xdd, + 0xdc, 0xab, 0x0d, 0xf8, 0x62, 0xdc, 0x9f, 0x31, 0xf5, 0xf4, 0xdb, 0x4c, 0xee, 0xeb, 0xba, 0x3d, 0xb2, 0x0c, 0x1f, + 0xe1, 0x4a, 0x01, 0xdc, 0x4c, 0xf8, 0x8b, 0x61, 0x26, 0xd5, 0x27, 0x80, 0xa9, 0xa6, 0x83, 0xfb, 0x04, 0x81, 0x01, + 0x54, 0xa2, 0xc5, 0xe8, 0x5a, 0x39, 0xa2, 0x19, 0xb8, 0x35, 0xdd, 0x0a, 0xe3, 0xad, 0x07, 0x2d, 0xf4, 0x4c, 0xc3, + 0x89, 0xff, 0xa0, 0x99, 0x57, 0x05, 0x04, 0xd0, 0xca, 0x08, 0xde, 0x5a, 0x9f, 0xcc, 0x11, 0xe2, 0x13, 0x96, 0x44, + 0x13, 0x16, 0xcf, 0x14, 0x3f, 0x26, 0x74, 0xdb, 0xd4, 0x36, 0x7d, 0x44, 0xfa, 0x8b, 0x6b, 0xd6, 0x4f, 0x59, 0xd6, + 0xbe, 0x3d, 0x54, 0xbc, 0x98, 0x36, 0xe3, 0x20, 0x26, 0xaa, 0x18, 0xff, 0x0b, 0xee, 0x4b, 0xad, 0x00, 0x91, 0xb9, + 0xab, 0x9e, 0x7e, 0xbf, 0x99, 0x2d, 0x07, 0x42, 0xe5, 0x77, 0x06, 0x49, 0x9f, 0x0e, 0xed, 0x07, 0x36, 0x89, 0xda, + 0x42, 0xcf, 0x1f, 0x97, 0xba, 0x89, 0x97, 0xd7, 0xa6, 0x46, 0xb4, 0x42, 0x86, 0xca, 0xd6, 0x01, 0xeb, 0xfb, 0x65, + 0xb8, 0xbf, 0xa8, 0x69, 0xa8, 0x75, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x7f, 0x80, 0xb1, 0xb8, 0x90, 0xd4, 0x3a, 0x1e, + 0x93, 0x7e, 0xb4, 0x90, 0xc9, 0x8d, 0xba, 0x3a, 0x39, 0x53, 0xcc, 0x13, 0xb8, 0x00, 0x97, 0x6d, 0x7f, 0x45, 0xa5, + 0x2e, 0xe5, 0xf6, 0x8a, 0xd2, 0xf4, 0x90, 0xb6, 0x57, 0x71, 0xde, 0x16, 0x5c, 0xf0, 0xaf, 0x14, 0x5c, 0x58, 0x07, + 0xeb, 0x8e, 0x3b, 0x65, 0x4f, 0x78, 0xa2, 0x4c, 0x6b, 0x83, 0xbb, 0x6e, 0x30, 0x26, 0xc6, 0x7e, 0x77, 0xc9, 0x93, + 0x4f, 0xc8, 0x82, 0xff, 0x90, 0x09, 0xf0, 0x4c, 0x76, 0xaf, 0x54, 0xfe, 0x97, 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, + 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xbd, 0x92, 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, + 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0x3b, 0x09, 0xdc, 0xf4, 0xee, 0xda, 0xcc, 0xcc, + 0xe9, 0x5a, 0x89, 0xa6, 0x4b, 0x63, 0x6b, 0x59, 0xaa, 0x30, 0xde, 0xef, 0x3c, 0xc9, 0xa6, 0xf9, 0xf1, 0x72, 0x9a, + 0x5b, 0xea, 0xb6, 0x75, 0xcb, 0x06, 0xd0, 0x10, 0xbb, 0xd6, 0x56, 0x0e, 0x78, 0xb9, 0x3d, 0x88, 0xe6, 0x6b, 0x45, + 0xe8, 0xa9, 0x12, 0xa1, 0x4f, 0xd3, 0x66, 0x1f, 0xec, 0xaa, 0x5a, 0x37, 0x42, 0x1e, 0x0d, 0x52, 0xcd, 0xc8, 0xbf, + 0xbd, 0xe6, 0xc5, 0x45, 0x2e, 0x6f, 0x00, 0x0e, 0x99, 0xd4, 0x46, 0x61, 0x79, 0x05, 0xee, 0xfc, 0xe8, 0x38, 0xce, + 0xc4, 0x28, 0xc7, 0xb8, 0xad, 0x88, 0x94, 0xac, 0x13, 0x67, 0x80, 0x87, 0xec, 0x4f, 0x9a, 0x0e, 0xed, 0x5a, 0x60, + 0x78, 0x5f, 0xe0, 0xae, 0x72, 0x76, 0xb2, 0xcd, 0xed, 0xa2, 0x6f, 0xce, 0xb0, 0xee, 0x48, 0x69, 0x6d, 0x2c, 0xba, + 0xee, 0x60, 0xad, 0x19, 0xb4, 0x45, 0x28, 0xf9, 0x90, 0x3b, 0x69, 0x3f, 0x07, 0x34, 0x38, 0xcb, 0xd2, 0x5b, 0x6b, + 0x95, 0xbf, 0xd5, 0x42, 0x9c, 0x28, 0xa6, 0x4e, 0x7c, 0x13, 0x25, 0xfa, 0xfc, 0x4c, 0x8c, 0x1b, 0x08, 0xa4, 0xbe, + 0xc4, 0xf8, 0x1a, 0x45, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xed, 0x89, 0xda, 0x58, 0x8e, 0xa0, 0x13, 0x42, 0xbc, 0x83, + 0x32, 0x8c, 0xd5, 0xc5, 0x81, 0x36, 0x58, 0xfa, 0xba, 0xb5, 0xce, 0x0d, 0xa1, 0x30, 0x4e, 0x60, 0x8a, 0x41, 0x52, + 0x67, 0x9d, 0x65, 0x82, 0x2a, 0x3b, 0x26, 0x9d, 0xf7, 0x01, 0xba, 0xbf, 0x16, 0x4d, 0xf1, 0x75, 0xe7, 0x0e, 0xba, + 0x8b, 0xeb, 0xd7, 0x5a, 0xe4, 0x06, 0x7f, 0xde, 0x12, 0x61, 0x11, 0x38, 0x6b, 0x4d, 0xbe, 0x6a, 0x84, 0x03, 0x53, + 0x92, 0x69, 0xd8, 0xcb, 0x95, 0x4d, 0xf7, 0x6e, 0xd7, 0xeb, 0xdd, 0x29, 0xe2, 0xea, 0x31, 0x56, 0x79, 0x37, 0x73, + 0x7b, 0xa7, 0x5a, 0x8b, 0xfd, 0x9b, 0xb6, 0x9f, 0x62, 0x47, 0xad, 0xb5, 0xdb, 0x0d, 0x27, 0xd4, 0x90, 0x6f, 0x45, + 0x95, 0x56, 0xa7, 0x1b, 0x83, 0x76, 0x08, 0x6d, 0x2d, 0x32, 0xb8, 0x51, 0x3e, 0x73, 0x42, 0x27, 0x15, 0x72, 0xd5, + 0xa9, 0x0b, 0xb6, 0x57, 0xbc, 0x5a, 0xca, 0x34, 0x12, 0x14, 0x6d, 0xce, 0xa3, 0x92, 0x26, 0x72, 0x2d, 0xaa, 0x48, + 0xd6, 0xa8, 0x17, 0xb5, 0x1a, 0x03, 0x04, 0x64, 0x3a, 0x6b, 0x7a, 0x50, 0x05, 0xb3, 0xa1, 0x8c, 0xe4, 0xf4, 0x0d, + 0x58, 0xda, 0x23, 0xc7, 0x5a, 0xdf, 0x55, 0x67, 0x8b, 0x6f, 0xf5, 0x84, 0x60, 0x0a, 0xb3, 0x07, 0x22, 0xc2, 0x35, + 0x8d, 0x21, 0xa7, 0x5d, 0xe2, 0xb2, 0xa6, 0x5b, 0xc2, 0x1d, 0xdc, 0xae, 0x64, 0x27, 0x6e, 0x9e, 0x34, 0x37, 0x57, + 0xb0, 0x93, 0x62, 0x3e, 0x06, 0xed, 0x97, 0x54, 0xd7, 0x2e, 0xcd, 0xad, 0xc7, 0x83, 0x80, 0x06, 0x83, 0xc2, 0xf0, + 0xaf, 0x13, 0xe3, 0xe1, 0x49, 0x03, 0x82, 0xa4, 0x5c, 0x84, 0x63, 0xdf, 0x88, 0x7e, 0x32, 0x95, 0xc7, 0x1c, 0x2d, + 0xde, 0xa1, 0xd5, 0x39, 0x04, 0xf4, 0x12, 0xa1, 0x24, 0x46, 0x55, 0x68, 0x44, 0x50, 0x9e, 0x96, 0xbf, 0x54, 0xd5, + 0x21, 0xa0, 0x90, 0xf6, 0x15, 0x85, 0xb2, 0x4d, 0x62, 0x68, 0x86, 0x5f, 0xce, 0x27, 0x0b, 0x3d, 0x03, 0x03, 0x39, + 0x3f, 0x5a, 0xe8, 0x59, 0x18, 0xc8, 0xf9, 0xa3, 0x45, 0xed, 0xd6, 0x81, 0x26, 0x20, 0x9e, 0x0b, 0x47, 0x27, 0xa5, + 0x55, 0xd9, 0x02, 0xba, 0xbd, 0x8f, 0xa0, 0xff, 0xd3, 0x1e, 0x82, 0x4e, 0x2e, 0xb4, 0x27, 0x37, 0xa0, 0xed, 0x90, + 0x04, 0xf6, 0x8a, 0x49, 0x85, 0x89, 0x45, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0xad, 0x3e, 0x38, 0x66, 0xe3, 0xa9, 0x4f, + 0x82, 0x80, 0xd1, 0x7d, 0x69, 0xc0, 0xc1, 0x6f, 0xf1, 0x2a, 0x7d, 0xb2, 0x15, 0xe8, 0xa6, 0xef, 0xee, 0x86, 0xde, + 0xc5, 0x15, 0x9c, 0xaa, 0xdd, 0x3d, 0x09, 0xdd, 0x64, 0xda, 0xb1, 0x7a, 0x0d, 0x71, 0x43, 0x7e, 0x65, 0x34, 0x1a, + 0xd9, 0x94, 0x90, 0x10, 0xc3, 0x39, 0x34, 0x73, 0x5a, 0x2e, 0x5f, 0xdd, 0x7a, 0xb6, 0x20, 0xc3, 0x4c, 0x6f, 0x99, + 0xac, 0xef, 0xa1, 0xac, 0x7a, 0x0c, 0xed, 0xd0, 0x7b, 0xe4, 0xf8, 0xfe, 0xc1, 0x37, 0x19, 0xbf, 0x70, 0xb8, 0xf6, + 0x70, 0x2e, 0x7c, 0x97, 0x35, 0x23, 0x73, 0xe8, 0x3c, 0xfb, 0x38, 0xde, 0xc3, 0x38, 0xf9, 0x32, 0x0b, 0xe5, 0x8d, + 0xd7, 0xf4, 0xbf, 0x55, 0x7a, 0xb3, 0xc3, 0x21, 0xa7, 0x2b, 0x58, 0x71, 0xb3, 0x2a, 0x34, 0xfc, 0x2c, 0xf2, 0xc6, + 0x11, 0xaf, 0x49, 0x54, 0x75, 0x9f, 0xf7, 0x36, 0x62, 0x69, 0xc7, 0x38, 0x00, 0x38, 0x51, 0xab, 0x86, 0x7d, 0x69, + 0x5c, 0xab, 0x83, 0x18, 0x91, 0x12, 0xb6, 0x4a, 0x1c, 0x09, 0xe5, 0x6f, 0x00, 0xc2, 0x62, 0x28, 0x8e, 0xb7, 0x86, + 0xf5, 0x1e, 0xf6, 0x43, 0x17, 0x68, 0x9a, 0x53, 0xaa, 0x19, 0x00, 0x24, 0x01, 0x7f, 0xf4, 0x74, 0xd3, 0x50, 0xd9, + 0xe6, 0x79, 0x68, 0x59, 0x5d, 0xc1, 0x3d, 0x3d, 0x75, 0x25, 0x03, 0xe3, 0xaa, 0x8e, 0xbd, 0xed, 0xdd, 0xed, 0xd1, + 0x2a, 0xf2, 0xbd, 0x4d, 0x6a, 0x9a, 0x05, 0x90, 0xa2, 0x71, 0xe9, 0x0b, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, + 0xf6, 0xfb, 0x28, 0x46, 0x8d, 0x0b, 0x05, 0x56, 0x61, 0x82, 0xc2, 0x21, 0xc2, 0x08, 0xa1, 0x3f, 0x97, 0xe1, 0xd6, + 0x17, 0x64, 0x10, 0x0d, 0xd7, 0xa2, 0x43, 0x11, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, + 0x22, 0x03, 0xb6, 0xf3, 0x4f, 0x1b, 0x22, 0x57, 0xe1, 0x02, 0x86, 0xef, 0x89, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, + 0x1b, 0x76, 0x88, 0x8e, 0xa6, 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x81, 0xdc, 0x35, 0x9d, + 0xbd, 0x14, 0x61, 0x50, 0xb7, 0x6c, 0xa0, 0x58, 0xc7, 0x4e, 0x50, 0x80, 0x01, 0x5c, 0x3e, 0x03, 0x1d, 0x1b, 0x0c, + 0x2a, 0x82, 0x4f, 0x0a, 0xdb, 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0x2f, + 0x94, 0x70, 0xf7, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf3, 0x5c, 0x6b, 0x4a, + 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, 0x51, 0xe5, 0xb1, 0x44, 0x91, + 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, 0xb4, 0xcb, 0x96, 0xb9, 0x04, + 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x3d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x47, 0x4d, + 0xbf, 0x7a, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x9f, 0xb0, 0xf1, 0x74, + 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x0a, 0x5a, 0x67, 0x26, 0xae, 0xf1, 0x69, 0xfb, 0x0a, 0x5a, + 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, 0xa9, 0x64, 0x7f, 0x2e, 0xad, + 0xc3, 0xbe, 0x5d, 0x28, 0xb4, 0xd0, 0xc4, 0xaf, 0x32, 0xc4, 0x4f, 0x5d, 0x67, 0xfe, 0x63, 0xda, 0xa7, 0x06, 0xb1, + 0x70, 0x24, 0x06, 0x11, 0xbf, 0x38, 0x55, 0xb6, 0x13, 0x42, 0xc5, 0xc6, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0x18, + 0x4a, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, 0x0b, 0x1d, 0xbe, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, + 0x9c, 0x4a, 0xb9, 0x8a, 0x04, 0x06, 0xca, 0xb3, 0x85, 0x41, 0x80, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0x84, 0xb1, + 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, + 0x71, 0x94, 0x6a, 0xfc, 0x47, 0x84, 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x09, 0x84, 0x40, + 0x73, 0xf6, 0x53, 0x71, 0xb5, 0x37, 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xaa, 0x2e, 0x50, + 0x2f, 0x64, 0xf1, 0x5a, 0xa6, 0xbc, 0x15, 0x22, 0xf3, 0x40, 0xb2, 0xf7, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, + 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x88, 0x33, 0xb6, + 0x77, 0x12, 0x6e, 0xef, 0xe6, 0x81, 0x21, 0x4a, 0xb9, 0x68, 0x89, 0x86, 0xad, 0x1d, 0xaf, 0x27, 0xd7, 0x84, 0xfb, + 0xb0, 0x11, 0x6b, 0x32, 0xc6, 0xb8, 0x36, 0x37, 0xb2, 0x7e, 0xb4, 0xc0, 0x83, 0x31, 0x65, 0xfd, 0x09, 0x64, 0x5a, + 0x49, 0x59, 0xe7, 0x0b, 0x23, 0x66, 0x52, 0x89, 0xde, 0xed, 0x1b, 0x9f, 0xd5, 0x5d, 0x44, 0xfd, 0xd6, 0x7e, 0x4f, + 0xea, 0x61, 0xe3, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, 0x37, 0x4d, 0x8a, 0x38, 0x3d, + 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, 0x24, 0x49, 0xd6, 0xd2, 0xd8, + 0x8a, 0x5d, 0x1a, 0xa4, 0xe7, 0xce, 0x88, 0x4b, 0x2f, 0x2a, 0x34, 0xa4, 0xa5, 0xde, 0x59, 0xa8, 0x64, 0xfe, 0x8a, + 0xff, 0x0c, 0x6a, 0x05, 0x3a, 0xda, 0xa4, 0x18, 0x4f, 0x81, 0x11, 0xdf, 0x0f, 0x66, 0x75, 0x0f, 0x71, 0xd1, 0x04, + 0xa5, 0xde, 0x13, 0x3b, 0x7e, 0x69, 0xf2, 0xf0, 0x2e, 0xe4, 0x9c, 0xc1, 0xa7, 0xf7, 0xb3, 0x44, 0xad, 0x75, 0x24, + 0x46, 0x6a, 0x06, 0xd0, 0x74, 0x50, 0xe6, 0x3c, 0x16, 0xc1, 0xac, 0x67, 0x12, 0xa3, 0x1e, 0xd7, 0xbf, 0x40, 0x43, + 0xed, 0x37, 0x2b, 0xcb, 0xb3, 0x6a, 0xf3, 0x35, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, 0x75, 0x25, 0x2f, 0x2f, 0x55, + 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, 0x37, 0x8b, 0xbb, 0x59, 0x46, + 0x03, 0x61, 0x6d, 0xef, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, 0x00, 0x10, 0xe9, 0x41, 0x14, + 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xde, 0xc5, 0x51, 0x16, 0x4a, 0x2f, 0x67, 0x19, 0x3f, 0x6d, 0x1a, 0x6b, 0x9d, 0x15, + 0xca, 0xd0, 0xda, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, 0x49, 0x9c, 0x2d, 0xc0, 0xfd, 0x31, 0x43, 0xa1, 0xa1, 0xb3, + 0x8c, 0x34, 0xd1, 0xf0, 0x5d, 0x77, 0x0c, 0x32, 0x8a, 0x93, 0x75, 0x5e, 0x49, 0xb7, 0xfa, 0xac, 0x8d, 0x84, 0xb9, + 0x87, 0xe8, 0x57, 0x31, 0x78, 0x94, 0xfb, 0xbc, 0x36, 0x3a, 0x99, 0x96, 0x91, 0x76, 0xe7, 0x27, 0xf5, 0x32, 0x4b, + 0xb5, 0x0e, 0xdb, 0x67, 0xd8, 0x5b, 0x63, 0xd2, 0x9b, 0x90, 0x1a, 0x46, 0xe2, 0xcb, 0x19, 0x35, 0x42, 0x40, 0x5b, + 0x8e, 0xbf, 0xc7, 0x67, 0x18, 0x9a, 0x02, 0x4b, 0x15, 0xb7, 0xb0, 0x1b, 0xbe, 0xe6, 0x93, 0x55, 0x0b, 0x40, 0x30, + 0x2b, 0x5f, 0xef, 0xe2, 0x95, 0x50, 0x9f, 0x69, 0x33, 0x00, 0x64, 0x41, 0x29, 0x77, 0xfc, 0x94, 0x4a, 0x07, 0x4b, + 0x14, 0x6d, 0x2f, 0xa7, 0x6f, 0x74, 0x6c, 0x7c, 0x9f, 0x9e, 0x0b, 0xd8, 0x2e, 0xe4, 0xb7, 0xee, 0xd4, 0x4b, 0x54, + 0xa4, 0xb6, 0xcd, 0xba, 0x87, 0x2f, 0x37, 0x68, 0x12, 0x46, 0x50, 0xa6, 0x4c, 0x01, 0x0c, 0x6e, 0xaa, 0x51, 0x30, + 0x69, 0x35, 0x12, 0xb6, 0xd4, 0x93, 0x2c, 0x37, 0x7d, 0x70, 0xaa, 0x3b, 0x04, 0x3d, 0xb7, 0xca, 0xf9, 0xa2, 0x65, + 0xbf, 0x56, 0x70, 0x74, 0x72, 0x35, 0x44, 0xcd, 0xbc, 0xd7, 0x76, 0x64, 0x48, 0xb9, 0x0c, 0x03, 0xc1, 0x94, 0x63, + 0x9e, 0x1e, 0x5b, 0xcf, 0x88, 0xe8, 0x9e, 0xb3, 0xcf, 0x74, 0xab, 0xae, 0x24, 0x20, 0x3a, 0x7e, 0xf7, 0xf8, 0xd5, + 0x55, 0x7c, 0x69, 0x50, 0x94, 0x1a, 0x16, 0x31, 0xca, 0xb4, 0xaf, 0x92, 0x30, 0x78, 0xbf, 0xbc, 0xff, 0x49, 0x65, + 0xa9, 0xfd, 0x1e, 0x6c, 0xad, 0xa8, 0xea, 0x97, 0x92, 0x17, 0x4d, 0x01, 0xd6, 0x5d, 0x96, 0x28, 0x90, 0xfb, 0xbd, + 0x4d, 0x33, 0xdf, 0x44, 0x8d, 0x9b, 0x0d, 0xeb, 0x8d, 0xeb, 0x76, 0xa9, 0x2d, 0xd9, 0x91, 0x95, 0xc8, 0x99, 0xc5, + 0x60, 0xc6, 0x8f, 0x0a, 0x83, 0xd2, 0xb0, 0x45, 0x55, 0x2a, 0x7e, 0x6f, 0x44, 0x70, 0xea, 0x58, 0x55, 0x18, 0xd3, + 0x80, 0xd9, 0x56, 0xd4, 0x1a, 0xd4, 0x41, 0x29, 0x6d, 0x4d, 0x40, 0xb6, 0x7f, 0xb1, 0x82, 0x9a, 0xdf, 0xff, 0x36, + 0x86, 0x7c, 0x4d, 0x29, 0xa8, 0x24, 0x60, 0x67, 0xd0, 0xe8, 0xa9, 0x12, 0x06, 0x52, 0x10, 0x3c, 0x01, 0xca, 0x17, + 0x51, 0x63, 0xb5, 0xdf, 0x57, 0xa7, 0xc6, 0x68, 0x0b, 0x08, 0x2d, 0xa4, 0x47, 0x97, 0x7d, 0xdc, 0xd6, 0x3a, 0x90, + 0x78, 0x70, 0x82, 0xed, 0x5c, 0x5d, 0xa3, 0x91, 0xd0, 0xfc, 0xbe, 0xd1, 0x80, 0xd7, 0xb4, 0x02, 0x85, 0x7a, 0x8e, + 0xa3, 0xa1, 0xb3, 0x43, 0x0a, 0x22, 0x36, 0x68, 0x61, 0xdf, 0x1d, 0x1f, 0x9a, 0x7d, 0x3d, 0x4f, 0x16, 0xa4, 0xa6, + 0xd2, 0x7d, 0xee, 0x96, 0x90, 0xb5, 0xea, 0x50, 0x56, 0x1e, 0xe0, 0x78, 0xa1, 0x64, 0xfe, 0x0e, 0x93, 0x1a, 0xa5, + 0x31, 0xa1, 0x31, 0x62, 0x01, 0x4b, 0x82, 0xf6, 0x7a, 0xa0, 0x7e, 0x19, 0x84, 0x0a, 0x67, 0x7a, 0x22, 0xf1, 0x29, + 0xe5, 0xea, 0xd3, 0x82, 0xd4, 0xd3, 0x82, 0x39, 0xd0, 0x4b, 0xdf, 0xca, 0xaf, 0x6c, 0x7c, 0xb4, 0xbf, 0x77, 0xcd, + 0x85, 0x75, 0x0c, 0x71, 0xb1, 0x85, 0xdf, 0x9c, 0x9a, 0x02, 0xb0, 0xe1, 0xa9, 0x2e, 0xcb, 0x37, 0x6a, 0x22, 0xb3, + 0x38, 0x24, 0x11, 0x48, 0xb6, 0x9b, 0x9b, 0xdb, 0x08, 0xb6, 0xbd, 0x85, 0xda, 0x50, 0x7f, 0x79, 0xdb, 0xfd, 0x8e, + 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xf2, 0xee, 0x55, 0xf2, 0x7f, 0x55, 0xc9, 0xdd, 0x56, 0x99, 0x75, + 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, 0x35, 0x05, 0x06, 0xd2, 0x93, 0xc6, 0x34, 0xd1, 0xd1, 0x95, + 0x19, 0x33, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, 0xc7, 0x00, 0x1c, 0xe0, 0x1f, 0x79, 0x84, 0xfa, 0xa7, 0xf3, + 0x3c, 0x38, 0x0b, 0x06, 0xe5, 0x20, 0xd0, 0x9f, 0xb8, 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0xe2, 0x4e, 0x5a, + 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, 0x02, 0x48, 0x5f, 0xbc, 0xb0, 0xce, 0x41, 0x85, 0x5e, 0x90, + 0xad, 0xba, 0x8b, 0x66, 0xc5, 0x5e, 0xb5, 0xd3, 0xbc, 0xdf, 0xcf, 0xe7, 0xe5, 0x20, 0x68, 0x54, 0x58, 0x18, 0xef, + 0x3f, 0xda, 0xfc, 0xd2, 0xe8, 0xa4, 0x09, 0x46, 0xac, 0x3d, 0x45, 0xf5, 0x8a, 0xa7, 0x19, 0x6d, 0xdc, 0x8e, 0x95, + 0xf2, 0x05, 0x44, 0xf1, 0xc0, 0x90, 0xb5, 0xf2, 0xee, 0x1d, 0xbc, 0x2e, 0x37, 0xde, 0x1c, 0x51, 0x80, 0xdd, 0x14, + 0xc6, 0x49, 0xcd, 0x45, 0x17, 0x35, 0xf1, 0x0c, 0x76, 0xba, 0x7a, 0x2b, 0xd1, 0x6a, 0xbc, 0x17, 0xef, 0x9b, 0x8d, + 0xbf, 0x91, 0x07, 0xba, 0xcc, 0x83, 0x0b, 0x40, 0x9c, 0x3d, 0x88, 0xab, 0x03, 0x2c, 0xf5, 0x20, 0x18, 0x58, 0xe4, + 0x90, 0x76, 0xb5, 0x7a, 0x28, 0x22, 0x75, 0x1e, 0x83, 0x01, 0x93, 0x69, 0x48, 0x4d, 0xa6, 0xbd, 0x58, 0x41, 0xda, + 0x58, 0x6b, 0x01, 0x6d, 0x38, 0x2c, 0xf6, 0xec, 0x86, 0xdd, 0xe9, 0xd6, 0xa1, 0x50, 0xc2, 0x40, 0xd6, 0x75, 0xf3, + 0x50, 0x6b, 0x78, 0x22, 0xe8, 0x41, 0x35, 0xda, 0x4f, 0x0f, 0xe5, 0x49, 0x7b, 0x2c, 0xc0, 0x45, 0x0f, 0x5f, 0x3e, + 0x17, 0x78, 0xd1, 0xde, 0x43, 0x9e, 0x33, 0x9f, 0x2a, 0x1f, 0xc4, 0x86, 0x5b, 0x86, 0x0f, 0xed, 0xe3, 0x5b, 0x81, + 0x4c, 0xea, 0x8e, 0xa6, 0xb6, 0x76, 0x47, 0xe3, 0x98, 0x40, 0xbf, 0x29, 0x47, 0x29, 0x13, 0x53, 0xcb, 0x92, 0x9d, + 0xf4, 0x72, 0xe5, 0x0d, 0x95, 0xb2, 0x93, 0x65, 0x9b, 0xf3, 0x4b, 0x1b, 0x09, 0xfd, 0xbe, 0x76, 0x07, 0xc2, 0x37, + 0x6a, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, 0xf1, 0x42, 0x2a, 0xd7, 0xee, 0xa2, 0xa9, 0xaa, 0xdb, + 0xdb, 0xca, 0x05, 0x2d, 0xf1, 0x56, 0x0a, 0xac, 0x22, 0x75, 0x7a, 0x3d, 0x95, 0x78, 0xd7, 0x47, 0xb1, 0xfd, 0x08, + 0xd8, 0xc6, 0xc6, 0xd1, 0xd8, 0xb8, 0x45, 0x6c, 0xf1, 0x55, 0x54, 0xd1, 0x82, 0x03, 0x04, 0x77, 0x5b, 0x52, 0x4b, + 0x33, 0x87, 0xb8, 0xaf, 0x78, 0x80, 0xf6, 0x5d, 0x1c, 0xce, 0xa4, 0x02, 0x6c, 0xeb, 0x5a, 0xe7, 0xac, 0x96, 0x03, + 0x36, 0x13, 0x3d, 0xff, 0xb4, 0x6a, 0x24, 0x62, 0x58, 0x65, 0x23, 0x65, 0x85, 0x76, 0xaf, 0x74, 0x09, 0x17, 0x5f, + 0x80, 0x97, 0xed, 0xbb, 0x95, 0xdd, 0x67, 0x4b, 0xec, 0x1f, 0xe6, 0x55, 0x13, 0x3c, 0xf2, 0x1a, 0x6f, 0xef, 0x61, + 0xe2, 0x6b, 0xa5, 0x10, 0x5e, 0xa5, 0x34, 0x94, 0x00, 0x0c, 0x92, 0xa0, 0x86, 0x2b, 0x6d, 0x9b, 0x41, 0x2a, 0x63, + 0xd8, 0xfd, 0xea, 0xad, 0xfe, 0x4f, 0xab, 0x70, 0x51, 0xc9, 0x62, 0x4c, 0x02, 0x9d, 0x53, 0x2d, 0x37, 0x81, 0x05, + 0xcf, 0xf6, 0xc9, 0x11, 0x28, 0xec, 0x04, 0x70, 0x43, 0x09, 0xfb, 0x0b, 0x6f, 0x43, 0x39, 0xfb, 0x6c, 0x25, 0x4f, + 0x6e, 0x5f, 0x52, 0x41, 0x13, 0x32, 0x15, 0x76, 0xff, 0xb6, 0x36, 0xec, 0xb3, 0x50, 0x8e, 0xa4, 0xc0, 0xc5, 0x41, + 0xe7, 0x00, 0xf6, 0x07, 0xb9, 0x8c, 0xcd, 0x67, 0xd2, 0xef, 0xab, 0xf7, 0x4f, 0xf3, 0x2c, 0xf9, 0xb4, 0xf7, 0xde, + 0xf0, 0x34, 0x4b, 0x06, 0x54, 0x22, 0xa6, 0xd6, 0x55, 0x31, 0x5c, 0x6a, 0x17, 0xe3, 0x06, 0xc9, 0x88, 0xef, 0xa4, + 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x3d, 0x92, 0x92, 0xd3, 0x65, 0xdd, 0xd9, 0x73, 0x2d, 0x9a, 0x41, 0x63, 0xb8, 0x3d, + 0xef, 0x25, 0xbd, 0x02, 0x54, 0x80, 0xe8, 0x9e, 0x05, 0xae, 0xe1, 0xcd, 0x25, 0xd1, 0xd8, 0xd2, 0xd3, 0x96, 0x68, + 0xe0, 0x4e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x14, 0x16, 0x00, 0xd4, 0x6a, 0x90, 0x5e, 0xe9, + 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, 0x03, 0xfa, 0xaa, + 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x4f, 0x4b, 0x93, 0x04, 0x82, + 0x12, 0x94, 0x6f, 0xd0, 0xdf, 0x4b, 0xcf, 0xc7, 0xf2, 0x1f, 0xde, 0xa1, 0xf4, 0x32, 0x2c, 0x40, 0xa6, 0xa8, 0x2b, + 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, 0x59, 0x86, 0x38, + 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, 0x4a, 0x20, 0xca, + 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, 0xa4, 0x99, 0x5d, + 0x87, 0x11, 0xa9, 0xf6, 0x92, 0xcc, 0x97, 0xff, 0x90, 0x99, 0xf0, 0xbe, 0x81, 0xc7, 0x66, 0xb3, 0x6c, 0x8a, 0xf9, + 0x42, 0x05, 0x73, 0x70, 0x9f, 0xa8, 0xb8, 0x14, 0x95, 0xff, 0x84, 0x5d, 0xf0, 0x62, 0x3c, 0x78, 0xbd, 0x46, 0x80, + 0xfd, 0xca, 0x7f, 0xf2, 0xc6, 0xec, 0x07, 0xeb, 0xc6, 0x97, 0x99, 0x88, 0x0f, 0x7c, 0x74, 0x4b, 0xf9, 0x68, 0xe3, + 0x65, 0xfa, 0xb5, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x93, 0x44, 0xd9, 0xa8, 0xe2, 0x02, + 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x82, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, 0x61, 0x99, 0xa9, + 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x9f, 0x92, 0xe8, 0x87, 0xa5, 0x07, 0x22, 0x67, 0xa6, 0x6c, 0x5b, 0x3b, + 0x42, 0x6d, 0x7c, 0x1d, 0xe9, 0x56, 0x5b, 0x00, 0xc0, 0x3d, 0x5b, 0xa4, 0x91, 0x64, 0x62, 0x38, 0xa9, 0x19, 0x37, + 0xe9, 0x05, 0xa6, 0xc6, 0x35, 0xab, 0x68, 0xe2, 0x2c, 0x64, 0x40, 0xef, 0x4f, 0x73, 0xfd, 0x9c, 0xc1, 0xfd, 0x07, + 0xad, 0x81, 0xcb, 0xe3, 0xa2, 0xdf, 0x97, 0xc7, 0xc5, 0x6e, 0x57, 0x9e, 0xc4, 0xfd, 0xbe, 0x3c, 0x89, 0x0d, 0xff, + 0xa0, 0x14, 0xdb, 0xc6, 0xdc, 0x20, 0xa1, 0xb9, 0x84, 0xa8, 0x45, 0x23, 0xf8, 0x43, 0xb3, 0x9c, 0x8b, 0x28, 0x3f, + 0x4e, 0xfa, 0xfd, 0xde, 0x72, 0x26, 0x06, 0xf9, 0x30, 0x89, 0xf2, 0x61, 0xe2, 0x39, 0x21, 0xbe, 0xf4, 0x9c, 0x10, + 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, 0xab, 0x5a, 0x12, + 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0xfd, 0xba, 0x04, 0x9e, 0x28, 0xe7, 0xd5, 0x16, 0x18, + 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x6d, 0x4d, 0x2f, 0xe8, 0x8a, 0x5e, 0x22, 0x3f, + 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, 0xc2, 0xf5, 0x2c, + 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x53, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x65, 0x10, 0xde, 0x2f, 0x9d, 0x85, + 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, 0x97, 0x74, 0x45, + 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, 0x55, 0xe1, 0x5d, + 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x69, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, 0x66, 0x64, 0x24, + 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, 0xdc, 0xfd, 0x92, + 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, 0x38, 0xb0, 0x07, + 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x23, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, 0xc4, 0x2b, 0x70, + 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, 0x2b, 0x95, 0x7e, + 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, 0x17, 0xa3, 0x0d, + 0x01, 0x0b, 0xaf, 0xf1, 0x74, 0x7d, 0xcc, 0xe2, 0xe9, 0x60, 0xb0, 0x46, 0xaa, 0xae, 0x72, 0xaf, 0xc9, 0x82, 0x5e, + 0xe0, 0x44, 0x10, 0x60, 0xe8, 0x33, 0xb1, 0x36, 0x34, 0xfc, 0x29, 0x83, 0x8f, 0x37, 0xec, 0x62, 0xb4, 0xa1, 0xb7, + 0xec, 0xe9, 0x6e, 0x3c, 0x05, 0x66, 0x6a, 0x35, 0x0b, 0x37, 0xc7, 0x97, 0xb3, 0x4b, 0xb6, 0x89, 0x36, 0x27, 0xd0, + 0xd0, 0x2b, 0xb6, 0x41, 0xc0, 0xa5, 0xf4, 0xe1, 0x72, 0xf0, 0x94, 0x1c, 0x0e, 0x06, 0x29, 0x89, 0xc2, 0xeb, 0xd0, + 0x6b, 0xe5, 0x53, 0xba, 0x21, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, 0x36, 0xf5, 0x75, 0xe8, + 0xed, 0xe6, 0x5c, 0x74, 0x82, 0x18, 0xa1, 0xaf, 0x81, 0xa3, 0x59, 0x2e, 0xcc, 0x04, 0x3c, 0x99, 0x8b, 0x8c, 0x16, + 0x85, 0x66, 0x20, 0xce, 0x4a, 0x40, 0x2c, 0x89, 0xba, 0xdf, 0x6c, 0x74, 0x06, 0xcb, 0xb9, 0xdf, 0xef, 0x55, 0x86, + 0x1e, 0x20, 0x72, 0x66, 0x27, 0x3d, 0xe8, 0xf9, 0xf4, 0x00, 0x3f, 0xd1, 0xab, 0x06, 0x71, 0x32, 0x7f, 0x59, 0x46, + 0x2f, 0x3d, 0xfa, 0xf0, 0x5b, 0x37, 0xe5, 0x91, 0xf9, 0x7f, 0x4e, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x79, 0x40, 0x6c, + 0xde, 0x9a, 0x54, 0x1a, 0x89, 0x6a, 0x74, 0xb6, 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xfd, 0x84, 0x16, 0x56, 0x10, + 0x21, 0xe7, 0xe8, 0x19, 0x18, 0xa4, 0x42, 0xa8, 0x1c, 0xb5, 0x28, 0xd1, 0x10, 0x24, 0x97, 0x25, 0x57, 0xe1, 0x73, + 0x08, 0x55, 0xa7, 0x8f, 0x33, 0x11, 0x36, 0xf4, 0x38, 0xf4, 0x01, 0xe0, 0xff, 0xda, 0x23, 0x17, 0x25, 0xbf, 0xc4, + 0xb3, 0xb9, 0x4d, 0x30, 0x0a, 0x96, 0x8b, 0x66, 0x68, 0x1b, 0xc4, 0x7e, 0x2c, 0x09, 0xd6, 0x23, 0x69, 0x3c, 0x2a, + 0xcd, 0x11, 0xe1, 0x47, 0xf1, 0x51, 0xf4, 0x34, 0x36, 0x24, 0x92, 0x23, 0x89, 0xe4, 0x03, 0x20, 0x9c, 0x04, 0xfd, + 0xc5, 0x5d, 0x93, 0x5d, 0x0b, 0xb5, 0xd7, 0xef, 0xc1, 0xbf, 0x96, 0x4c, 0xcb, 0xee, 0x55, 0x8f, 0x7d, 0x45, 0x90, + 0x07, 0x13, 0xe0, 0xf5, 0xe1, 0x5f, 0x4b, 0x9c, 0x41, 0xeb, 0xf9, 0xa2, 0x3a, 0x33, 0xf3, 0x06, 0x37, 0xf2, 0xba, + 0xac, 0x5d, 0x97, 0x2f, 0xf8, 0x01, 0xbf, 0xad, 0xb8, 0x48, 0xcb, 0x83, 0x9f, 0xab, 0x36, 0x9e, 0x53, 0xb9, 0x5e, + 0xb9, 0x38, 0x2b, 0xca, 0x38, 0xd5, 0x93, 0xba, 0x18, 0x6b, 0xd8, 0x86, 0xdf, 0x23, 0xea, 0x4a, 0x5a, 0x8e, 0x9e, + 0x52, 0xae, 0x9a, 0x29, 0x17, 0xeb, 0x3c, 0xff, 0x69, 0x2f, 0x15, 0xa7, 0xb8, 0x99, 0x82, 0x54, 0xa9, 0xe5, 0x02, + 0xaa, 0xe7, 0xa8, 0xe5, 0x6e, 0x69, 0x76, 0x80, 0x73, 0xdb, 0x54, 0x1f, 0x2b, 0xb3, 0x0b, 0x2f, 0xb9, 0x71, 0x7f, + 0x32, 0x65, 0x58, 0x30, 0x0a, 0x6d, 0x56, 0x5d, 0x69, 0xfb, 0x42, 0xeb, 0x34, 0x0c, 0x57, 0x7e, 0xbc, 0x80, 0x74, + 0x01, 0xe3, 0x78, 0x51, 0x32, 0x31, 0x6e, 0x8f, 0xde, 0x0a, 0xe2, 0x6b, 0xb6, 0x02, 0xe9, 0xf7, 0x7b, 0xc2, 0xdb, + 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, 0x72, 0x15, 0x8b, 0x1f, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, + 0x4c, 0xa7, 0x3f, 0x27, 0xa1, 0x5f, 0x08, 0x05, 0x9f, 0xf5, 0xd2, 0xca, 0x93, 0xdb, 0xc3, 0x32, 0xae, 0xd1, 0x2b, + 0x71, 0xa5, 0xfb, 0x66, 0xa4, 0x90, 0x7a, 0xe4, 0xab, 0xa6, 0x80, 0xde, 0x8c, 0x7d, 0x33, 0x15, 0xe6, 0xed, 0x8e, + 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, + 0xa7, 0x9d, 0xfb, 0x75, 0xde, 0xe1, 0xae, 0xa8, 0xdf, 0x02, 0x17, 0x9a, 0x15, 0x65, 0xd5, 0x96, 0x0d, 0xdb, 0xc6, + 0x1b, 0x59, 0x28, 0x36, 0xc0, 0xb2, 0xe7, 0xbe, 0x85, 0x07, 0x88, 0x9b, 0x70, 0xcf, 0x2e, 0x6a, 0xb8, 0x31, 0x7c, + 0x5d, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, + 0x85, 0x2f, 0x78, 0x19, 0xce, 0xf9, 0xc2, 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0xd3, 0x21, 0x53, 0xe8, 0x76, 0xa5, 0xb1, + 0x52, 0x22, 0x6e, 0xcd, 0x32, 0x81, 0xb2, 0x94, 0xb5, 0x12, 0xde, 0x14, 0x2d, 0x5b, 0x49, 0x23, 0xef, 0x99, 0x83, + 0xfb, 0xd8, 0x6f, 0x88, 0x89, 0x6c, 0x02, 0x93, 0xa2, 0xa1, 0x03, 0xda, 0x55, 0x17, 0xbe, 0x19, 0xf5, 0x60, 0x90, + 0x5b, 0x92, 0x88, 0x15, 0xa4, 0x58, 0xc1, 0xba, 0x66, 0xc5, 0x3c, 0x5f, 0xd0, 0x0b, 0x26, 0xe7, 0xe9, 0x82, 0xae, + 0x98, 0x9c, 0xaf, 0xf1, 0x26, 0x74, 0x01, 0x27, 0x24, 0xd9, 0xc6, 0x4a, 0x01, 0x7b, 0x81, 0x97, 0x37, 0x3c, 0x53, + 0x35, 0x2d, 0xbb, 0x54, 0x1c, 0x60, 0x7c, 0x5e, 0x86, 0x61, 0x39, 0xbc, 0x00, 0x6b, 0x89, 0xc3, 0x70, 0x35, 0xe7, + 0x0b, 0xf5, 0x1b, 0xa2, 0xce, 0x27, 0xa1, 0x62, 0x17, 0xec, 0x5e, 0x20, 0xd3, 0xab, 0x39, 0x5f, 0xa8, 0x91, 0xd0, + 0x05, 0x5f, 0x59, 0x63, 0x93, 0xd8, 0x13, 0xb4, 0xcc, 0xe2, 0xf9, 0x78, 0x11, 0xc5, 0x35, 0x2c, 0xc3, 0x0f, 0x6a, + 0x66, 0x5a, 0xf2, 0x9f, 0x5c, 0x6d, 0x68, 0xa2, 0x6f, 0xb0, 0x8a, 0xfc, 0xe1, 0xf1, 0xd1, 0x25, 0x90, 0xb1, 0xb3, + 0x2b, 0x99, 0xf9, 0xd0, 0xf7, 0x91, 0xc1, 0x3d, 0x37, 0xe5, 0x8c, 0xab, 0x20, 0x51, 0x06, 0xee, 0x5e, 0xcd, 0x92, + 0xb1, 0x16, 0xe1, 0xfb, 0x47, 0x45, 0xd1, 0x67, 0xd2, 0x34, 0xa0, 0xfb, 0x48, 0x30, 0x07, 0x7a, 0xaf, 0xd0, 0xe1, + 0xb2, 0xda, 0x66, 0x02, 0xfe, 0x22, 0x41, 0x7e, 0x2b, 0xf4, 0xaa, 0xc6, 0xa0, 0x8a, 0x76, 0x11, 0x4b, 0xff, 0x3e, + 0xe2, 0x47, 0xd9, 0xfc, 0xa7, 0xb9, 0xc7, 0x2b, 0x09, 0x83, 0x1f, 0x52, 0xb3, 0x49, 0xe6, 0xed, 0x15, 0xfb, 0x0e, + 0x3a, 0xea, 0x51, 0x6b, 0xbc, 0xaf, 0x5e, 0x70, 0x0a, 0x31, 0x4a, 0x28, 0x3a, 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, + 0x77, 0x83, 0xdd, 0x36, 0xaf, 0x79, 0x51, 0x70, 0xbe, 0xae, 0xaa, 0xc0, 0x0f, 0x68, 0x38, 0x5f, 0xec, 0x87, 0x30, + 0x1c, 0xd3, 0xd6, 0x35, 0x0c, 0xc2, 0x8c, 0x61, 0x24, 0x04, 0xaf, 0x7f, 0xd1, 0x23, 0x9a, 0xc4, 0xab, 0x1f, 0xf8, + 0xe7, 0x8c, 0x17, 0x8a, 0x48, 0x83, 0x08, 0xa9, 0x9b, 0xf8, 0x46, 0xa6, 0x49, 0x01, 0x85, 0x00, 0xa3, 0x80, 0x4a, + 0x6c, 0x68, 0x2a, 0xfe, 0x56, 0x8b, 0x0f, 0x7e, 0x6a, 0x3a, 0x1e, 0x8d, 0xeb, 0x56, 0x67, 0x54, 0xd0, 0x19, 0xe8, + 0x51, 0x2b, 0xea, 0x69, 0xd0, 0x4a, 0x30, 0x8d, 0x34, 0x6f, 0xdd, 0x43, 0xe0, 0x95, 0x69, 0xf1, 0xce, 0x03, 0xba, + 0x3d, 0xf3, 0xc1, 0x93, 0xc7, 0xf4, 0xcc, 0xa1, 0x27, 0x57, 0xec, 0xa4, 0xea, 0xa1, 0xf6, 0xde, 0x8c, 0x50, 0xd0, + 0xef, 0x63, 0x0a, 0x74, 0x23, 0xa8, 0xbd, 0xab, 0x7b, 0x25, 0xf7, 0x39, 0x7c, 0xc7, 0x59, 0x6e, 0x01, 0x4b, 0x45, + 0xd6, 0x0a, 0x3c, 0x0a, 0x50, 0x97, 0xca, 0x10, 0xb6, 0x98, 0xc3, 0xa1, 0xb2, 0x5b, 0xb5, 0x1a, 0x4a, 0x72, 0x5c, + 0x8e, 0xc0, 0x21, 0x74, 0x5d, 0x0e, 0xca, 0xd1, 0x32, 0xab, 0xde, 0xe3, 0x6f, 0xcd, 0x3a, 0x24, 0xd9, 0x5d, 0xac, + 0x03, 0xb7, 0xac, 0xc3, 0xf4, 0x93, 0x41, 0x0a, 0x40, 0x93, 0x8d, 0xc0, 0x25, 0x00, 0xef, 0xed, 0x3f, 0x22, 0xd4, + 0xca, 0xf4, 0x4e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, 0x91, 0xce, + 0x49, 0x9d, 0x89, 0xf7, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x1b, 0xbc, 0xcd, 0x6a, 0xa9, + 0x8d, 0x1e, 0x28, 0x80, 0xdf, 0x0d, 0x36, 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x47, + 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x47, 0xe4, 0xd8, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x41, + 0x83, 0xfe, 0x65, 0x5b, 0xe4, 0x0e, 0x40, 0x69, 0x14, 0x31, 0x50, 0x25, 0x88, 0xa8, 0xc5, 0xbf, 0xef, 0xcd, 0xb5, + 0xc1, 0x5c, 0x20, 0xcc, 0xc1, 0x80, 0x83, 0xb8, 0x0d, 0x42, 0x73, 0xc0, 0x6c, 0x6f, 0x23, 0x41, 0x37, 0xd6, 0x30, + 0xb3, 0xa3, 0x3f, 0xdc, 0x4a, 0xf0, 0x4d, 0xd6, 0x1a, 0x75, 0x5e, 0x1c, 0x02, 0x41, 0xf0, 0xa6, 0x50, 0xd5, 0x5e, + 0xf5, 0xc0, 0xc6, 0x5b, 0xf5, 0x63, 0xb7, 0x1b, 0x4f, 0x85, 0xbb, 0xf6, 0x0b, 0x0a, 0x27, 0x9f, 0x92, 0x7f, 0xbd, + 0x37, 0x19, 0x1c, 0x18, 0x19, 0xbe, 0xf4, 0xf6, 0x2f, 0x7c, 0xad, 0xa5, 0x7b, 0x62, 0x50, 0x92, 0x87, 0x47, 0x8a, + 0xfe, 0xdd, 0x29, 0x2b, 0x9f, 0xda, 0xe9, 0xdf, 0xed, 0xcc, 0xfa, 0x3c, 0x1e, 0x4d, 0x76, 0xbb, 0x5e, 0x5c, 0x69, + 0x8f, 0x35, 0xbd, 0x20, 0xd0, 0xb9, 0x9e, 0x1c, 0x1e, 0x41, 0x54, 0x84, 0x66, 0xdc, 0xcd, 0xb2, 0x21, 0x91, 0xf1, + 0xe3, 0x74, 0x96, 0x0d, 0xc1, 0x0e, 0xf7, 0xa2, 0x12, 0x97, 0xa3, 0xd6, 0x06, 0xa7, 0xb7, 0x49, 0x08, 0xa1, 0x1c, + 0xb0, 0xb2, 0x5b, 0xf5, 0x67, 0xa3, 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x07, 0x66, 0x04, + 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xa7, 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0xf6, 0xe8, 0xa9, + 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, 0xdf, 0x30, 0xee, 0x3f, 0x34, 0x5f, 0xbb, 0xa9, 0x88, 0x1e, 0x53, 0x2c, 0x53, + 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x72, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, + 0x9f, 0x21, 0x7c, 0x46, 0xb2, 0x0b, 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xe4, 0x31, 0x3d, 0x98, 0x7c, 0x77, 0x44, + 0x0f, 0x8e, 0x1e, 0x3d, 0x21, 0x00, 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3d, 0x79, 0x42, 0x0f, 0xbe, 0xff, 0x9e, 0x1e, + 0x4c, 0x1e, 0x1d, 0x35, 0xd2, 0x26, 0x4f, 0xbe, 0xa7, 0x07, 0xdf, 0x3d, 0x6e, 0xa4, 0x1d, 0x8d, 0x9f, 0xd0, 0x83, + 0xbf, 0x7f, 0x67, 0xd2, 0xfe, 0x06, 0xd9, 0xbe, 0x3f, 0xc2, 0xff, 0x4c, 0xda, 0xe4, 0xc9, 0x23, 0x7a, 0x30, 0x19, + 0x43, 0x25, 0x4f, 0x5c, 0x25, 0xe3, 0x09, 0x7c, 0xfc, 0x08, 0xfe, 0xfb, 0x1b, 0x81, 0x4d, 0x20, 0xd9, 0x52, 0xa0, + 0xfe, 0x0c, 0x45, 0x9c, 0xa8, 0x9a, 0x48, 0x78, 0x88, 0x99, 0xd5, 0x37, 0x71, 0x18, 0x10, 0x97, 0x0e, 0x05, 0xd1, + 0x83, 0xf1, 0xe8, 0x09, 0x09, 0x7c, 0x78, 0xba, 0x4f, 0x3e, 0xc8, 0xd8, 0x52, 0xcc, 0xb3, 0x6f, 0x96, 0x26, 0xb6, + 0x82, 0x07, 0x60, 0xf5, 0xc1, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x86, 0xcb, 0xfd, 0x5c, 0x3f, 0xb6, 0x00, 0xe5, 0xfd, + 0x55, 0xcb, 0x3e, 0x15, 0x2a, 0x74, 0x5a, 0x6b, 0xf4, 0xd9, 0x07, 0x4c, 0x1f, 0x0c, 0xbc, 0x1b, 0xf6, 0xcf, 0x7b, + 0xe5, 0xb4, 0xbe, 0xd1, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x65, 0xfc, + 0xfe, 0x1f, 0x96, 0xf1, 0xa1, 0xa3, 0x8c, 0x7f, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, + 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x07, 0x46, 0x14, 0x2d, 0x2f, 0x0e, 0x52, 0x3e, + 0xab, 0xd8, 0xcf, 0x4b, 0x54, 0x6f, 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x77, 0xf3, 0x06, 0xb8, 0x19, 0xf6, + 0xa3, 0x7a, 0xf2, 0x03, 0x67, 0x64, 0xd2, 0xb6, 0x47, 0x99, 0x18, 0x01, 0x56, 0x40, 0x06, 0x0e, 0x3c, 0x00, 0x3a, + 0xe8, 0x8f, 0xf6, 0x6e, 0xa7, 0x52, 0x9a, 0x7d, 0xb6, 0x30, 0x80, 0x86, 0x79, 0x9b, 0xb8, 0xb2, 0xab, 0xd4, 0x97, + 0x97, 0xa0, 0x70, 0xab, 0x59, 0xde, 0x5e, 0x61, 0x2a, 0x6e, 0x4f, 0xca, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, + 0x40, 0xcd, 0x96, 0x8f, 0xb6, 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0xdf, 0x6a, 0xb1, 0x3f, 0x5a, + 0x3f, 0xfa, 0xbe, 0x3d, 0x1e, 0xac, 0x7d, 0x8f, 0x8f, 0xf4, 0x67, 0x8d, 0xeb, 0xc0, 0xb6, 0xe5, 0x1b, 0x2f, 0x6a, + 0x2b, 0xf1, 0x28, 0x81, 0x37, 0x30, 0x11, 0x29, 0x0c, 0x52, 0x2d, 0x70, 0x0c, 0xca, 0x1b, 0x0b, 0xb1, 0x54, 0x5d, + 0xdd, 0xd0, 0x2d, 0x19, 0x82, 0x87, 0x5b, 0x95, 0xaa, 0xc0, 0x51, 0xfd, 0x7e, 0x26, 0x7d, 0xb7, 0x27, 0x63, 0x47, + 0x8e, 0x53, 0x3f, 0x15, 0x0e, 0xfe, 0x9b, 0xd4, 0xb5, 0x7e, 0x99, 0xa5, 0xcc, 0xb2, 0x2c, 0xec, 0x24, 0xd4, 0x72, + 0x8f, 0xca, 0x83, 0xe4, 0x0b, 0x39, 0x44, 0xb2, 0xc0, 0x28, 0x14, 0x64, 0x38, 0xa1, 0x62, 0xb4, 0x16, 0xe5, 0x32, + 0xbb, 0xa8, 0xc2, 0xad, 0x52, 0x28, 0x73, 0x8a, 0xbe, 0xdd, 0xe0, 0x40, 0x42, 0xa2, 0xac, 0x7c, 0x13, 0xbf, 0x09, + 0x11, 0xac, 0x8e, 0x6b, 0x5b, 0x28, 0xee, 0xed, 0x4f, 0x91, 0x76, 0xf1, 0x47, 0xc6, 0x05, 0xd4, 0xc5, 0x62, 0x1a, + 0x4e, 0x6c, 0xec, 0x03, 0xf7, 0x85, 0xd5, 0xf4, 0x00, 0xd4, 0x77, 0xa9, 0xc4, 0x08, 0xea, 0x2b, 0x63, 0x1f, 0xdb, + 0x63, 0x4c, 0xce, 0x20, 0xd6, 0xb0, 0x2e, 0x5b, 0xf5, 0x8d, 0xb0, 0x13, 0x00, 0x6e, 0x84, 0xd6, 0xe8, 0xc8, 0x24, + 0x55, 0x88, 0xe7, 0xa5, 0x0a, 0xdf, 0x9a, 0x11, 0x3a, 0x06, 0x6f, 0x2a, 0xd7, 0x48, 0xe9, 0x0b, 0x06, 0xcd, 0xb1, + 0xad, 0xa3, 0xb0, 0xda, 0xca, 0xb2, 0x13, 0x80, 0x1b, 0xc8, 0x8e, 0xcd, 0xc5, 0x73, 0x56, 0xcd, 0xb3, 0x45, 0x64, + 0x82, 0x02, 0xa6, 0xc2, 0x32, 0x68, 0x6f, 0xee, 0x90, 0xed, 0x38, 0x84, 0x6e, 0xb8, 0x8f, 0x60, 0x3c, 0xed, 0xa6, + 0x60, 0x05, 0xd1, 0x08, 0xf1, 0x30, 0x63, 0x16, 0xdf, 0x2b, 0x4d, 0x79, 0xaa, 0x5a, 0x02, 0x81, 0xa3, 0x10, 0xea, + 0x62, 0xdf, 0x28, 0xc1, 0x65, 0x6a, 0x04, 0x33, 0xd8, 0xb3, 0x23, 0xb5, 0x5d, 0x72, 0x4e, 0x87, 0x6a, 0x4a, 0x4b, + 0x3d, 0xa5, 0xda, 0xd7, 0x50, 0xcc, 0x4b, 0xf4, 0xd0, 0x03, 0xd7, 0x03, 0xed, 0x90, 0x57, 0xd2, 0x89, 0x89, 0xa0, + 0xd3, 0x6a, 0x13, 0x76, 0x6e, 0xa4, 0x5b, 0x56, 0x23, 0xef, 0x18, 0x9a, 0x1d, 0xf1, 0xca, 0x0f, 0xd4, 0x05, 0x10, + 0x21, 0x77, 0xb6, 0xc8, 0x10, 0x67, 0x96, 0x95, 0x2f, 0xa0, 0x2c, 0x8e, 0xd8, 0xba, 0x02, 0xae, 0xa5, 0x60, 0x72, + 0xc9, 0x23, 0x91, 0x22, 0x22, 0xe0, 0xa9, 0xd2, 0xae, 0xef, 0xb5, 0x84, 0xd0, 0x32, 0x05, 0xe2, 0xe6, 0xa2, 0x38, + 0xd7, 0x36, 0x90, 0x05, 0xd0, 0xb7, 0x9f, 0xb2, 0x2b, 0x2f, 0x1c, 0xec, 0xf6, 0x2a, 0x13, 0xcf, 0xf8, 0x45, 0x26, + 0x78, 0x8a, 0x60, 0x57, 0xb7, 0xe6, 0x81, 0x3b, 0xb6, 0x0d, 0x2c, 0xdf, 0x7e, 0x80, 0x05, 0x53, 0x86, 0x5a, 0x29, + 0x91, 0x89, 0x48, 0x40, 0x66, 0x9f, 0xb9, 0x7b, 0x9d, 0x89, 0xd7, 0xf1, 0x2d, 0x78, 0x53, 0x34, 0xf8, 0xe9, 0xd1, + 0x39, 0x7e, 0x89, 0x48, 0xa2, 0x10, 0xc3, 0x16, 0x23, 0x62, 0x21, 0x72, 0xec, 0x98, 0x50, 0xae, 0x04, 0xad, 0xad, + 0x21, 0xf0, 0xe2, 0x4f, 0xab, 0xee, 0x5d, 0x65, 0xc2, 0xd8, 0x67, 0x5c, 0xc5, 0xb7, 0xac, 0x54, 0x60, 0x16, 0x18, + 0xe7, 0xbe, 0x2d, 0x25, 0xb9, 0xca, 0x84, 0x11, 0x90, 0x5c, 0xc5, 0xb7, 0xb4, 0x29, 0xe3, 0xd0, 0x56, 0x74, 0x5e, + 0x9c, 0xdf, 0xfd, 0xe1, 0x97, 0x18, 0x6a, 0x65, 0xdc, 0xef, 0x83, 0xc4, 0x4c, 0xda, 0xa6, 0xcc, 0x64, 0x24, 0x35, + 0x5a, 0x48, 0x45, 0xf9, 0x60, 0x42, 0xf6, 0x57, 0xaa, 0x65, 0x44, 0xed, 0x57, 0xa1, 0x98, 0x8d, 0xa3, 0x09, 0xa1, + 0x93, 0x8e, 0xf5, 0x6e, 0x5a, 0x0b, 0x99, 0x46, 0x4f, 0x22, 0xcf, 0xa7, 0xb3, 0x60, 0xd5, 0xb4, 0x38, 0x66, 0x7c, + 0x5a, 0x0c, 0x06, 0x44, 0xbb, 0x14, 0x6e, 0xb1, 0x1e, 0x30, 0xa5, 0x71, 0xf1, 0xd6, 0x4c, 0xab, 0x5f, 0x48, 0x15, + 0x92, 0xde, 0x33, 0x20, 0x11, 0xd2, 0x05, 0xbb, 0x05, 0x89, 0xa2, 0xe7, 0x7f, 0xa7, 0xb6, 0xe0, 0xbe, 0x07, 0x63, + 0x33, 0xba, 0xaf, 0x67, 0xfc, 0x87, 0xda, 0x16, 0x44, 0x7d, 0x2a, 0x59, 0xaf, 0x23, 0x51, 0x85, 0x5c, 0x84, 0x9f, + 0x1d, 0x0d, 0x31, 0x44, 0xb5, 0xc7, 0x02, 0xb1, 0xbe, 0x3a, 0xe7, 0x05, 0x4e, 0x3f, 0x73, 0x97, 0x2b, 0xd8, 0x16, + 0xb4, 0x32, 0x34, 0xea, 0x4d, 0xfc, 0x26, 0xb2, 0x97, 0x05, 0x5d, 0xe4, 0x33, 0x14, 0xb2, 0xe6, 0x61, 0x58, 0x0d, + 0xdb, 0x83, 0x48, 0x0e, 0xdb, 0x93, 0xd0, 0x68, 0x0c, 0x2c, 0x90, 0x3d, 0x1a, 0x81, 0x8b, 0xd0, 0xca, 0xdf, 0x8e, + 0xc1, 0x85, 0xcb, 0x22, 0xb2, 0x0c, 0x75, 0xfc, 0xa6, 0x76, 0x13, 0x54, 0xaf, 0xd0, 0x69, 0x0a, 0xab, 0x52, 0x26, + 0xf9, 0xf0, 0xeb, 0x85, 0x2c, 0x30, 0x93, 0xd7, 0x65, 0x8f, 0xbe, 0xb6, 0xdb, 0x3b, 0x30, 0x05, 0xeb, 0x3e, 0x79, + 0x5f, 0x3f, 0xec, 0xec, 0x09, 0x18, 0xc5, 0xaa, 0x1c, 0x4d, 0x21, 0xa5, 0xf6, 0x41, 0xa9, 0x3f, 0x85, 0xa9, 0xd0, + 0x1c, 0xbb, 0x05, 0x4c, 0x02, 0xf6, 0x19, 0x52, 0x3d, 0xa6, 0x1d, 0xfb, 0x1c, 0x6d, 0x61, 0x49, 0xc0, 0xe1, 0x1f, + 0x09, 0x59, 0xfb, 0x57, 0x77, 0x99, 0x36, 0x43, 0xb6, 0xcc, 0x17, 0xc0, 0xe7, 0xc3, 0xae, 0x8d, 0x4a, 0x94, 0x4d, + 0x44, 0x92, 0xc2, 0x96, 0xc7, 0x20, 0xed, 0x51, 0x4c, 0x57, 0x05, 0x4f, 0x32, 0x94, 0x52, 0x24, 0xda, 0x27, 0x38, + 0x87, 0x37, 0xb8, 0x1f, 0x55, 0x40, 0x78, 0x15, 0x72, 0x3a, 0x4a, 0xa9, 0xb6, 0x80, 0x51, 0xd4, 0x03, 0x44, 0x79, + 0x19, 0xc8, 0xf1, 0x76, 0xbb, 0x09, 0x5d, 0xb1, 0xe5, 0x70, 0x42, 0x91, 0x94, 0x5c, 0x62, 0xb9, 0x57, 0xa0, 0xf3, + 0x38, 0x67, 0xbd, 0x57, 0x80, 0x45, 0x70, 0x06, 0x7f, 0x63, 0x42, 0xaf, 0xe1, 0x6f, 0x4e, 0xe8, 0x53, 0x16, 0x5e, + 0x0d, 0x2f, 0xc9, 0x61, 0x98, 0x0e, 0x26, 0x4a, 0x30, 0xb6, 0x61, 0x69, 0x19, 0xaa, 0xc4, 0xd5, 0xe1, 0x05, 0x79, + 0x78, 0x41, 0x6f, 0xe9, 0x0d, 0x7d, 0x4d, 0x1f, 0x00, 0xe1, 0xdf, 0x1c, 0x4f, 0xf8, 0x70, 0xf2, 0xb8, 0xdf, 0xef, + 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, 0x7a, 0x31, 0x7d, 0xa0, + 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xdc, 0x90, 0x21, 0x3e, 0x5e, 0xe4, 0x52, 0x16, 0xe1, 0xe5, 0xe1, 0x86, + 0xd0, 0x07, 0x27, 0xa0, 0x37, 0xc5, 0xfa, 0x1e, 0x3c, 0xdc, 0xe8, 0xda, 0x08, 0x7d, 0x15, 0x26, 0xb0, 0x4d, 0x6e, + 0x99, 0xbd, 0x6b, 0x4f, 0xc6, 0x10, 0xcb, 0x64, 0xe3, 0x95, 0xb7, 0x79, 0x78, 0x4b, 0x0e, 0x6f, 0xc1, 0x53, 0xd4, + 0x92, 0xbf, 0x59, 0x78, 0xc3, 0x5a, 0x35, 0x3c, 0xdc, 0xd0, 0xd7, 0xad, 0x46, 0x3c, 0xdc, 0x90, 0x28, 0xbc, 0x61, + 0x97, 0xf4, 0x35, 0xbb, 0x22, 0xf4, 0xbc, 0xdf, 0x3f, 0xeb, 0xf7, 0x65, 0xbf, 0xff, 0x73, 0x1c, 0x86, 0xf1, 0xb0, + 0x20, 0x87, 0x92, 0x6e, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, 0x59, 0x95, 0xb7, 0xca, 0xb5, + 0xa1, 0x60, 0xad, 0xb0, 0x61, 0xea, 0xe9, 0x01, 0xbd, 0x61, 0x05, 0x7d, 0xcd, 0x62, 0x12, 0x5d, 0x43, 0x2b, 0xce, + 0x67, 0x45, 0x74, 0x43, 0x5f, 0xb3, 0xb3, 0x59, 0x1c, 0xbd, 0xa6, 0x0f, 0x58, 0x3e, 0x9c, 0x40, 0xde, 0xd7, 0xc3, + 0x1b, 0x72, 0xf8, 0x80, 0x44, 0xe1, 0x03, 0xfd, 0x7b, 0x43, 0x2f, 0x79, 0xf8, 0x80, 0x7a, 0xd5, 0x3c, 0x20, 0xa6, + 0xfa, 0x46, 0xed, 0x0f, 0x48, 0xe4, 0x0f, 0xe6, 0x03, 0x6b, 0x4f, 0xf3, 0xce, 0xd1, 0xc6, 0x75, 0x19, 0x6e, 0x08, + 0x5d, 0x97, 0xe1, 0x0d, 0x21, 0xd3, 0xe6, 0xd8, 0xc1, 0x80, 0xce, 0xde, 0x45, 0x09, 0xa1, 0x37, 0x7e, 0xa9, 0x37, + 0x38, 0x86, 0x66, 0x84, 0x74, 0x3f, 0x31, 0x0d, 0xd7, 0xc1, 0x47, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, + 0x1f, 0x22, 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0x8f, 0x83, 0x01, 0x74, 0xc6, + 0x2b, 0x29, 0xbc, 0x19, 0x7c, 0x7c, 0xb8, 0x21, 0xaa, 0x8e, 0x82, 0x96, 0x32, 0x2c, 0xe8, 0x53, 0x9a, 0x01, 0xe0, + 0xd7, 0xc7, 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0xfd, 0x78, 0xfc, 0x60, 0x3a, 0x18, 0x7c, 0x34, 0xdb, 0xe4, 0x33, + 0xbb, 0xa3, 0x14, 0x58, 0x7f, 0x67, 0xfd, 0xfe, 0xe7, 0x93, 0x98, 0x9c, 0x17, 0x3c, 0xfe, 0x34, 0x6d, 0xb6, 0xe5, + 0xb3, 0x8b, 0xaa, 0x76, 0xd6, 0xef, 0xaf, 0xfb, 0xfd, 0xd7, 0x80, 0x5d, 0x34, 0x73, 0xbe, 0x9e, 0x20, 0x6d, 0x99, + 0x3b, 0x8a, 0xa4, 0x49, 0x0e, 0x8d, 0xa1, 0x6d, 0xb1, 0x6a, 0xdb, 0xac, 0x23, 0x03, 0x8b, 0xa3, 0x66, 0x45, 0x71, + 0x4d, 0xa2, 0xb0, 0x77, 0xb6, 0xdb, 0xbd, 0x66, 0x8c, 0xc5, 0x04, 0xa4, 0x1f, 0xfe, 0xeb, 0xd7, 0x75, 0x23, 0x86, + 0x58, 0xa9, 0xc4, 0x77, 0xdb, 0xa5, 0x3d, 0x04, 0x22, 0x0e, 0x9b, 0xfe, 0xbd, 0xb9, 0x97, 0x8b, 0xda, 0xf1, 0xad, + 0xbf, 0x03, 0x08, 0x91, 0x64, 0x21, 0x9f, 0xe1, 0x18, 0x94, 0x19, 0x00, 0x99, 0x47, 0x6a, 0xe6, 0x25, 0x80, 0x00, + 0x93, 0xdd, 0x6e, 0x34, 0x1e, 0x4f, 0x68, 0xc1, 0x46, 0x7f, 0x7b, 0xf2, 0xb0, 0x7a, 0x18, 0x06, 0xc1, 0x20, 0x23, + 0x2d, 0x3d, 0x85, 0x5d, 0xac, 0xd5, 0x21, 0x18, 0xc1, 0x6b, 0xf6, 0xf1, 0x3a, 0xfb, 0x6a, 0xf6, 0x11, 0x09, 0x6b, + 0x83, 0x71, 0xe4, 0x22, 0x6d, 0xe9, 0xed, 0xee, 0x60, 0x30, 0xb9, 0x48, 0xbf, 0xc0, 0x76, 0xfa, 0xfc, 0x9b, 0x07, + 0xe3, 0x09, 0x07, 0xa3, 0xbb, 0x28, 0xe8, 0x33, 0x6d, 0xb7, 0xab, 0xfc, 0x4b, 0xe0, 0x1b, 0x4c, 0x05, 0x1d, 0x9b, + 0x65, 0xe1, 0x06, 0x15, 0x51, 0x47, 0xcb, 0xa0, 0xaa, 0x95, 0xed, 0x1c, 0x50, 0x4b, 0xac, 0xca, 0xc4, 0x2d, 0x30, + 0x0c, 0x19, 0xea, 0x72, 0x4f, 0xab, 0xdf, 0x79, 0x21, 0x0d, 0x7c, 0x86, 0x13, 0x11, 0x7a, 0xdc, 0x1a, 0xf7, 0xb9, + 0x35, 0xf1, 0x05, 0x6e, 0xad, 0x44, 0x12, 0x6b, 0x60, 0x49, 0xcd, 0xe5, 0x28, 0x61, 0x27, 0x25, 0xe3, 0xb3, 0x32, + 0x4a, 0x68, 0x0c, 0x0f, 0x92, 0x89, 0x99, 0x8c, 0x12, 0xb4, 0x4f, 0x74, 0x11, 0x06, 0xff, 0x02, 0xcc, 0x7e, 0x9a, + 0xc3, 0x5f, 0x49, 0xa6, 0xc9, 0x31, 0x04, 0x84, 0x38, 0x1e, 0xcf, 0xe2, 0x70, 0x4c, 0xa2, 0xe4, 0x04, 0x9e, 0xe0, + 0xbf, 0x22, 0x1c, 0x93, 0x5a, 0xdf, 0x61, 0xa4, 0xba, 0xdc, 0x26, 0x0c, 0xe0, 0xca, 0xc6, 0xb3, 0x49, 0x64, 0xa5, + 0xbb, 0xf2, 0xe1, 0x68, 0xfc, 0x84, 0x4c, 0xe3, 0x50, 0x0e, 0x12, 0x42, 0xc1, 0xbb, 0x37, 0x2c, 0x87, 0x89, 0x86, + 0x67, 0x03, 0x36, 0xaf, 0x74, 0x6c, 0x9e, 0x84, 0x13, 0x10, 0x86, 0x09, 0x39, 0xd6, 0x3b, 0x90, 0x52, 0xf4, 0x79, + 0x8e, 0xfd, 0xd4, 0x47, 0x10, 0x66, 0x47, 0x2d, 0x15, 0x5f, 0x01, 0xd0, 0x25, 0x0e, 0x0e, 0xb5, 0x67, 0xbe, 0x98, + 0x85, 0xa5, 0x47, 0xa5, 0x4c, 0x75, 0x87, 0xa2, 0x41, 0xf9, 0x4d, 0x83, 0x0e, 0x05, 0x19, 0x4c, 0x68, 0x79, 0x32, + 0xe1, 0x8f, 0x20, 0x80, 0x47, 0x23, 0xe2, 0x97, 0xc2, 0x89, 0x81, 0xf0, 0x2a, 0xc8, 0x40, 0xa5, 0xb5, 0x6a, 0xcc, + 0xc8, 0x56, 0x7c, 0x00, 0x61, 0x52, 0x0e, 0x6e, 0xe4, 0x3a, 0x4f, 0x21, 0x2a, 0xd8, 0x3a, 0xaf, 0x0e, 0x2e, 0xc1, + 0x92, 0x3d, 0xae, 0x20, 0x4e, 0xd8, 0x7a, 0x05, 0xd8, 0xb9, 0x0f, 0xb6, 0x65, 0x7d, 0xa0, 0xbe, 0x3b, 0xc0, 0x96, + 0xc3, 0xab, 0x4a, 0x1e, 0x4c, 0xc6, 0xe3, 0xf1, 0xe8, 0x0f, 0x38, 0x3a, 0x80, 0xd0, 0x92, 0xc8, 0xf0, 0xc9, 0x00, + 0x8d, 0xbb, 0xae, 0xb8, 0x37, 0x2e, 0x14, 0x65, 0xa5, 0x93, 0x09, 0x01, 0xf1, 0xb3, 0xe9, 0x1b, 0xec, 0x2b, 0xae, + 0xe3, 0x9f, 0xec, 0x7f, 0x62, 0x56, 0xb4, 0x5a, 0xa9, 0xa3, 0x77, 0x6f, 0x3f, 0xbc, 0xfa, 0xf8, 0xea, 0xd7, 0xe7, + 0x67, 0xaf, 0xde, 0xbc, 0x78, 0xf5, 0xe6, 0xd5, 0xc7, 0x7f, 0xdf, 0xc3, 0x60, 0xfb, 0xb6, 0x22, 0x76, 0xec, 0xbd, + 0x7b, 0x8c, 0x57, 0x8b, 0x2f, 0x9c, 0x3d, 0x72, 0xb7, 0x58, 0x80, 0x4d, 0x30, 0xdc, 0x82, 0xa0, 0x9a, 0xd1, 0xa8, + 0xf4, 0x3d, 0x01, 0x19, 0x8d, 0x0a, 0xd9, 0x78, 0x58, 0xb1, 0x15, 0x72, 0xf1, 0x8e, 0xe1, 0xe0, 0x23, 0xfb, 0x5b, + 0x71, 0x26, 0xdc, 0x8e, 0xb6, 0x66, 0x45, 0xc0, 0xe7, 0x6b, 0x2d, 0x2a, 0x8f, 0x0b, 0x51, 0x7b, 0xdb, 0x3e, 0x87, + 0x84, 0x7a, 0x44, 0xae, 0x83, 0xf7, 0x6d, 0x90, 0x3d, 0x3e, 0xf2, 0x9e, 0x94, 0x67, 0xa8, 0xcf, 0xd1, 0xf0, 0x51, + 0xe3, 0x19, 0x9d, 0x98, 0x6b, 0xa3, 0x43, 0x3d, 0x2b, 0x60, 0x7f, 0x2b, 0x31, 0x36, 0x98, 0x43, 0xa7, 0x88, 0xf5, + 0xe1, 0x74, 0xbf, 0xfb, 0x37, 0xa3, 0x9f, 0xe1, 0xf8, 0x51, 0xaa, 0x09, 0xa4, 0x45, 0x81, 0xd2, 0x95, 0x21, 0xb7, + 0x3d, 0x0b, 0x0b, 0xf3, 0x33, 0x6c, 0x10, 0x40, 0x7b, 0xd9, 0xb1, 0x24, 0xd0, 0x2c, 0x5e, 0xeb, 0xfa, 0xe7, 0xe5, + 0xcb, 0x44, 0x3b, 0x5f, 0x7c, 0x0b, 0x21, 0x86, 0xfd, 0x2b, 0x42, 0x63, 0xc2, 0xdd, 0x24, 0xbb, 0x4b, 0x8b, 0xb9, + 0x57, 0x5d, 0xc5, 0x78, 0xdc, 0xdd, 0x71, 0xa5, 0x68, 0xde, 0xba, 0xc0, 0x1e, 0xa8, 0x79, 0x1d, 0x2f, 0x59, 0x08, + 0xd8, 0x8c, 0x87, 0x76, 0x91, 0x38, 0xbf, 0x77, 0x3a, 0x21, 0x87, 0x47, 0x53, 0x3e, 0x64, 0x25, 0x15, 0x03, 0x56, + 0xd6, 0x7b, 0xd4, 0x9c, 0xb7, 0x09, 0xb9, 0xd8, 0xa7, 0xe1, 0x62, 0xc8, 0xef, 0xbb, 0x24, 0x7d, 0xe4, 0x0d, 0x87, + 0x6a, 0xdb, 0x5c, 0x0c, 0x69, 0xca, 0xe9, 0x3e, 0x95, 0x01, 0x21, 0xd2, 0x55, 0x5c, 0x91, 0x5a, 0x1f, 0x55, 0x6b, + 0x27, 0xe9, 0xb8, 0xce, 0xb6, 0x5f, 0xb8, 0x64, 0xab, 0xdb, 0xb5, 0x7f, 0xad, 0x6e, 0x5f, 0x98, 0x81, 0xfc, 0xfd, + 0x89, 0xa8, 0x26, 0x06, 0xa2, 0x0b, 0xa8, 0xe0, 0x9f, 0xe0, 0xe5, 0xc9, 0x23, 0xad, 0x00, 0xbd, 0xeb, 0xec, 0xe8, + 0xda, 0xe3, 0x8d, 0x59, 0x6c, 0x2d, 0x71, 0xce, 0x2a, 0xdf, 0x59, 0x5e, 0x95, 0xad, 0xd0, 0x75, 0x04, 0xfb, 0x3d, + 0xec, 0xe8, 0xbb, 0xb7, 0x0d, 0x80, 0x28, 0x85, 0x95, 0x3b, 0xfb, 0x85, 0x77, 0xf6, 0x0b, 0x7b, 0xf6, 0xdb, 0x4d, + 0xa0, 0x7c, 0x58, 0xa1, 0x65, 0x2f, 0xa4, 0xa8, 0x4c, 0x93, 0xc7, 0x4d, 0x5d, 0x16, 0xd2, 0x62, 0x7e, 0x68, 0x69, + 0xd7, 0xe3, 0x31, 0x95, 0xa8, 0x1e, 0x79, 0x89, 0xad, 0x3a, 0x2c, 0xc9, 0xfd, 0xf7, 0xcc, 0xff, 0xd9, 0x1b, 0xe4, + 0x5d, 0x77, 0xbb, 0xff, 0x9b, 0x0b, 0x1d, 0xdc, 0xd6, 0xd6, 0xc2, 0x53, 0x57, 0xc7, 0x05, 0xde, 0xd5, 0xd6, 0xf7, + 0xdf, 0xd5, 0xde, 0x66, 0x7a, 0xd9, 0x55, 0x80, 0x1a, 0x24, 0xd6, 0x57, 0xbc, 0xc8, 0x92, 0xda, 0x2a, 0x34, 0x1e, + 0x70, 0x08, 0xed, 0xe1, 0x1d, 0x5c, 0x20, 0x87, 0x25, 0x84, 0x7e, 0xaa, 0x8c, 0x00, 0xd0, 0x67, 0xb1, 0x1f, 0xf0, + 0x30, 0x23, 0x03, 0x5f, 0xe2, 0x27, 0xa5, 0x2f, 0x2e, 0x3e, 0xdc, 0xcb, 0x4c, 0xd0, 0xab, 0xc4, 0x66, 0x2f, 0x64, + 0x3b, 0xe6, 0x87, 0xff, 0x05, 0x46, 0x83, 0xf0, 0xda, 0x92, 0x1d, 0x8a, 0x8e, 0x59, 0xae, 0xe0, 0xa8, 0x2d, 0xbd, + 0x32, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x01, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, + 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0xf7, 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0x45, + 0xfe, 0x85, 0xfa, 0x1a, 0x5b, 0x92, 0x6c, 0x2b, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, + 0x2d, 0xa1, 0x0d, 0x95, 0x41, 0x4f, 0x2e, 0x52, 0xe5, 0x23, 0x5b, 0x30, 0x79, 0x3c, 0x9e, 0xf9, 0x3d, 0x77, 0x0c, + 0x0e, 0x21, 0xd1, 0xc4, 0x1a, 0xbf, 0xf8, 0x59, 0x30, 0x8e, 0x43, 0x79, 0x22, 0x1b, 0xdf, 0x95, 0x24, 0x1a, 0x1b, + 0x53, 0x65, 0x7d, 0x95, 0xa8, 0x86, 0x09, 0x79, 0x58, 0x90, 0xc3, 0x82, 0x2e, 0xfd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, + 0x70, 0x32, 0x26, 0x0f, 0xe3, 0x87, 0x13, 0x03, 0x37, 0xec, 0xe7, 0xc8, 0x87, 0x4b, 0x72, 0xd8, 0xac, 0x12, 0x4c, + 0x51, 0x4d, 0xcf, 0xfc, 0x4a, 0x92, 0xc1, 0x72, 0x90, 0x3e, 0x6c, 0xe5, 0xc5, 0x5a, 0xf5, 0x78, 0xaf, 0x8f, 0xf9, + 0x94, 0x88, 0xc6, 0x8d, 0x61, 0x4d, 0xaf, 0xe2, 0x3f, 0x65, 0x11, 0x49, 0x09, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, + 0xb2, 0x24, 0x16, 0x69, 0x94, 0xd6, 0x84, 0xa6, 0x27, 0x6c, 0x32, 0x9e, 0xa5, 0x2c, 0x3d, 0x9e, 0x3c, 0x99, 0x4d, + 0x9e, 0x44, 0x47, 0xe3, 0x28, 0x1d, 0x0c, 0x20, 0xf9, 0x68, 0x0c, 0x2e, 0x76, 0xf0, 0x9b, 0x1d, 0xc1, 0xd0, 0x9d, + 0x20, 0x4b, 0x58, 0x40, 0xd3, 0xbe, 0xae, 0x49, 0x7a, 0x38, 0x2f, 0x54, 0x4f, 0xe2, 0x5b, 0xba, 0xf6, 0x1c, 0x5c, + 0xfc, 0x16, 0x5e, 0xb8, 0x16, 0x5e, 0xec, 0xb7, 0x50, 0x68, 0xb2, 0x1d, 0xcb, 0xff, 0x3f, 0x6e, 0x18, 0x77, 0xdd, + 0x25, 0xcc, 0xe2, 0xba, 0xce, 0x46, 0xab, 0x42, 0x56, 0x12, 0x6e, 0x13, 0x4a, 0x14, 0x36, 0x8a, 0x57, 0xab, 0x5c, + 0xbb, 0x88, 0xcd, 0x2b, 0x0a, 0xe0, 0x2e, 0x10, 0xa7, 0x18, 0x58, 0x68, 0x63, 0x20, 0xf7, 0x99, 0x17, 0x92, 0x59, + 0xb5, 0x8f, 0xb9, 0x47, 0xfe, 0x19, 0x82, 0x31, 0xaa, 0x38, 0x19, 0xcf, 0x14, 0xd6, 0xc5, 0x97, 0xe4, 0xbd, 0xff, + 0xc1, 0x51, 0x64, 0x8f, 0x66, 0xd0, 0x13, 0x44, 0xce, 0x23, 0xce, 0x9e, 0x4c, 0x5e, 0x06, 0xee, 0x67, 0xb0, 0xd2, + 0x5f, 0x77, 0x9b, 0xb1, 0xb6, 0x3d, 0xba, 0x17, 0x46, 0x28, 0xfa, 0x19, 0xdf, 0x99, 0x7a, 0x01, 0x97, 0x50, 0x0d, + 0xec, 0xfa, 0xf2, 0x92, 0x97, 0x00, 0x22, 0x94, 0x89, 0x7e, 0xbf, 0xf7, 0xa7, 0x81, 0x26, 0x2d, 0x79, 0xf1, 0x3a, + 0x13, 0xd6, 0x19, 0x07, 0x9a, 0x0a, 0xd4, 0xff, 0x53, 0x65, 0x9f, 0xe9, 0x98, 0xcc, 0xfc, 0xc7, 0xe1, 0x84, 0x44, + 0xcd, 0xd7, 0xe4, 0x0b, 0xa7, 0xe9, 0x17, 0xae, 0x68, 0xff, 0x0d, 0x99, 0xb9, 0xe1, 0x90, 0xa1, 0xfe, 0xd2, 0x31, + 0x4f, 0x46, 0xaf, 0x13, 0xb3, 0x13, 0xc1, 0xaa, 0x19, 0x44, 0x61, 0x2f, 0xe0, 0x41, 0x5d, 0xcb, 0xe2, 0x29, 0xcc, + 0x3e, 0xa8, 0x11, 0xc5, 0x31, 0x1b, 0xcf, 0x42, 0x19, 0x4e, 0xc0, 0xbe, 0x77, 0x32, 0x86, 0xfb, 0x80, 0x0c, 0x3f, + 0x55, 0x21, 0x76, 0x0e, 0xd2, 0x3e, 0x55, 0xa8, 0x98, 0x00, 0x88, 0x40, 0xc8, 0xdb, 0xef, 0x4b, 0x95, 0x84, 0xaf, + 0x4b, 0x4c, 0x29, 0xd4, 0x07, 0xff, 0x1d, 0xa9, 0xba, 0x63, 0xfa, 0xd5, 0xfa, 0xf1, 0x67, 0x42, 0xf1, 0xe9, 0x2e, + 0x25, 0xbe, 0x85, 0xe0, 0xce, 0x31, 0xe8, 0x20, 0x2a, 0x34, 0x63, 0xbb, 0x9f, 0xdf, 0x15, 0x77, 0xf3, 0xbb, 0xe2, + 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, 0xf4, 0xdf, 0xe7, 0x13, 0xef, + 0xe4, 0xa9, 0xaf, 0x32, 0x31, 0xbd, 0x83, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd3, 0x93, 0x75, 0x65, 0x6f, + 0xad, 0x64, 0x88, 0x79, 0xee, 0x61, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, + 0x2b, 0x7d, 0xdf, 0xed, 0x8c, 0x0a, 0xf3, 0x5e, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, + 0xb7, 0x19, 0xab, 0x86, 0x6c, 0xbe, 0x93, 0x91, 0xda, 0x33, 0x79, 0x9a, 0xec, 0x93, 0xde, 0x01, 0xef, 0x90, 0x9f, + 0xd7, 0x9f, 0xc2, 0x58, 0x1a, 0x7e, 0x4b, 0x5e, 0xc6, 0x45, 0x56, 0x2d, 0xaf, 0xb2, 0x04, 0x99, 0x2e, 0x78, 0xf1, + 0xd5, 0x4c, 0x97, 0xf7, 0xb1, 0x3e, 0x60, 0x3c, 0xa5, 0x78, 0xdd, 0x10, 0xa5, 0x5f, 0xb4, 0x3c, 0x2b, 0xd4, 0xe5, + 0x49, 0xc5, 0x6c, 0xcf, 0x4a, 0x70, 0x3a, 0x05, 0x13, 0x7c, 0xfd, 0xd3, 0xf5, 0x3e, 0x01, 0x5c, 0x50, 0xa8, 0x39, + 0x2d, 0xe4, 0xca, 0x60, 0x39, 0x59, 0xe8, 0x4e, 0xc0, 0x0c, 0x95, 0x02, 0x2f, 0x50, 0xf0, 0x17, 0x0d, 0x8c, 0xe8, + 0x0b, 0xf7, 0x9b, 0x0c, 0x0c, 0xd2, 0xa5, 0x39, 0x11, 0xc6, 0x8e, 0xdb, 0x49, 0xd2, 0x56, 0x94, 0x33, 0xce, 0xde, + 0xab, 0x2b, 0x05, 0x18, 0xe0, 0x6d, 0x6f, 0xa2, 0x4d, 0x82, 0x5e, 0x0b, 0x4a, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0x32, + 0xc2, 0xc5, 0x87, 0x95, 0xc7, 0x82, 0x7b, 0xf6, 0x0b, 0x89, 0xb5, 0xf5, 0x03, 0x63, 0x36, 0x2f, 0x58, 0xa0, 0x50, + 0x81, 0x02, 0xcb, 0x99, 0xb6, 0x34, 0xad, 0x86, 0xfc, 0xf0, 0x08, 0xad, 0x4d, 0xab, 0x01, 0x3f, 0x3c, 0xaa, 0xa3, + 0xec, 0x18, 0xb2, 0x9c, 0xf8, 0x19, 0xd4, 0xeb, 0x3a, 0x32, 0x29, 0x26, 0xbb, 0x57, 0x5f, 0x9e, 0xfa, 0xa3, 0xba, + 0x05, 0xd7, 0x0f, 0x40, 0x00, 0x1b, 0x80, 0x43, 0xa0, 0x1a, 0x2c, 0x8d, 0x08, 0x16, 0x65, 0x0a, 0xed, 0x6b, 0xe8, + 0xbd, 0xd1, 0xf0, 0x5f, 0xe0, 0x2e, 0x22, 0x57, 0xfe, 0x27, 0x08, 0xfc, 0x15, 0x65, 0x5a, 0x99, 0xe2, 0x7f, 0xa2, + 0xd5, 0x2b, 0x94, 0xb3, 0xa6, 0x35, 0x1f, 0x44, 0x6b, 0x22, 0x54, 0x33, 0x86, 0xe0, 0xdf, 0xca, 0x32, 0x6d, 0xa9, + 0xaa, 0xd4, 0x87, 0xc6, 0x6b, 0xad, 0x70, 0x96, 0x8f, 0x23, 0xef, 0x35, 0x86, 0x8e, 0x4d, 0x9c, 0xa5, 0x9c, 0x4a, + 0x9d, 0xbd, 0x39, 0x94, 0x91, 0x03, 0x9c, 0x4e, 0xd8, 0x78, 0x9a, 0x1c, 0xcb, 0x69, 0xe2, 0x20, 0xf3, 0x73, 0x86, + 0x91, 0x55, 0x0d, 0x08, 0x8b, 0xb2, 0xa1, 0xb4, 0x05, 0x98, 0xe4, 0x84, 0x90, 0x29, 0x86, 0xa2, 0xc8, 0x47, 0xba, + 0x1f, 0xd6, 0x9b, 0xd5, 0x7d, 0xf1, 0x4e, 0x03, 0x9c, 0x86, 0x09, 0x04, 0x02, 0x2f, 0xe2, 0x9b, 0x4c, 0x5c, 0x82, + 0xc7, 0xf0, 0x00, 0xbe, 0x04, 0x37, 0xb9, 0x94, 0xfd, 0xab, 0x0a, 0x73, 0x5c, 0x5b, 0xc0, 0xa0, 0xc1, 0xea, 0x41, + 0x74, 0xb8, 0x94, 0x36, 0xbb, 0x0a, 0x10, 0x1b, 0x53, 0x88, 0x65, 0xc1, 0xd6, 0x96, 0x3d, 0xfb, 0x59, 0x35, 0x0d, + 0xad, 0x13, 0x4e, 0xc5, 0x65, 0x0e, 0x51, 0x54, 0x06, 0x31, 0xb8, 0x23, 0x79, 0x7c, 0xde, 0xa9, 0x08, 0x2f, 0x08, + 0xb8, 0x95, 0x25, 0x32, 0x5c, 0xd1, 0xe5, 0xe8, 0x96, 0xae, 0x47, 0x37, 0x74, 0x4c, 0x27, 0x7f, 0x1f, 0xa3, 0x45, + 0xb6, 0x4a, 0xdd, 0xd0, 0xf5, 0x68, 0x49, 0xbf, 0x1f, 0xd3, 0xa3, 0xbf, 0x8d, 0xc9, 0x74, 0x89, 0x87, 0x09, 0xbd, + 0x00, 0xc7, 0x2e, 0x52, 0xa3, 0xa7, 0xa6, 0x6f, 0x70, 0x58, 0x8d, 0xf2, 0x21, 0x1f, 0xe5, 0x94, 0x8f, 0x8a, 0x61, + 0x35, 0x02, 0x4f, 0xc7, 0x6a, 0xc8, 0x47, 0x15, 0xe5, 0xa3, 0xf3, 0x61, 0x35, 0x3a, 0x27, 0xcd, 0xa6, 0xbf, 0xaa, + 0xf8, 0x55, 0xc9, 0x2e, 0x60, 0x5b, 0xc0, 0xf2, 0x75, 0xab, 0x6c, 0x99, 0xfa, 0xab, 0xda, 0x9c, 0xcc, 0x96, 0xb3, + 0xb7, 0xd7, 0x5d, 0x4e, 0x2c, 0x1e, 0xb7, 0x4d, 0x87, 0xab, 0x2f, 0x27, 0xea, 0xa4, 0x57, 0xc8, 0x0f, 0xe3, 0xa9, + 0x50, 0xe7, 0x10, 0x98, 0x49, 0xcc, 0xc2, 0x98, 0x61, 0x33, 0x75, 0x1a, 0x28, 0x70, 0xb2, 0x91, 0xe7, 0xa2, 0x98, + 0x8d, 0x72, 0x0a, 0xef, 0x63, 0x42, 0x22, 0x01, 0x67, 0xd5, 0x49, 0x35, 0x2a, 0x20, 0xe6, 0x08, 0x0b, 0xf1, 0x11, + 0xfa, 0xa5, 0x3e, 0xf2, 0x90, 0xc0, 0x33, 0xec, 0x6b, 0x31, 0x88, 0xe1, 0x88, 0xb7, 0x95, 0x55, 0xb3, 0x30, 0x81, + 0xca, 0xaa, 0x61, 0x69, 0x2a, 0x2b, 0x68, 0x36, 0xaa, 0xfc, 0xca, 0x2a, 0x1c, 0xa3, 0x84, 0x90, 0xa8, 0xd4, 0x95, + 0x81, 0xfa, 0x24, 0x61, 0x61, 0xa9, 0x2b, 0x3b, 0x57, 0x1f, 0x9d, 0xfb, 0x95, 0x9d, 0x83, 0x0b, 0xe9, 0x20, 0xf1, + 0xaf, 0x52, 0x69, 0xda, 0xbe, 0x0e, 0x36, 0x56, 0x15, 0xdd, 0xf2, 0xdb, 0xaa, 0x88, 0xa3, 0x92, 0xba, 0x18, 0xd0, + 0xb8, 0x30, 0x22, 0x49, 0xf5, 0x1a, 0x05, 0x7f, 0x48, 0x10, 0x95, 0xc6, 0xe0, 0xd5, 0x99, 0x74, 0xad, 0xd4, 0x8a, + 0x8a, 0x41, 0x39, 0x28, 0xe0, 0xfe, 0x94, 0xb7, 0x16, 0xd2, 0xcf, 0x10, 0x51, 0x19, 0xca, 0x1b, 0xfc, 0x82, 0xc1, + 0x93, 0xd9, 0x55, 0x1a, 0x26, 0xa3, 0x0d, 0x8d, 0x47, 0x4b, 0x84, 0x83, 0x61, 0xab, 0x54, 0xe1, 0xad, 0x5f, 0x42, + 0xfa, 0x2d, 0x8d, 0x47, 0x37, 0x34, 0xb5, 0x36, 0xa7, 0x06, 0xea, 0xaa, 0x37, 0xa6, 0xb7, 0x11, 0xbc, 0xde, 0x44, + 0x4b, 0x0a, 0x5b, 0xe9, 0x34, 0xcf, 0x2e, 0x45, 0x94, 0x52, 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa3, 0x0d, + 0xae, 0x07, 0x50, 0x86, 0x86, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, 0xd2, 0x23, 0x53, 0x6b, 0x7d, 0x91, 0x45, 0xf8, 0x68, + 0x67, 0xa3, 0xa5, 0x78, 0x46, 0x2c, 0x8c, 0x2b, 0x18, 0x42, 0x5d, 0x58, 0x69, 0x0a, 0x92, 0x2e, 0x70, 0x64, 0x2f, + 0x8c, 0xab, 0x70, 0x0b, 0xa6, 0x45, 0x1b, 0x30, 0x8f, 0x02, 0x85, 0x83, 0x4b, 0x90, 0x7e, 0x42, 0xd9, 0xce, 0x51, + 0x9a, 0x1c, 0xde, 0x04, 0x5d, 0xec, 0x4d, 0x10, 0xd2, 0xae, 0x6e, 0xb2, 0x25, 0x7d, 0x83, 0xed, 0x3d, 0x3a, 0x15, + 0x15, 0x54, 0x9f, 0x5b, 0x30, 0x59, 0xb2, 0x41, 0xd8, 0x12, 0xa6, 0x67, 0xfa, 0x02, 0xb0, 0xa7, 0x0f, 0x8f, 0xf6, + 0xe6, 0xbb, 0x98, 0xbd, 0x39, 0x2c, 0xa3, 0xb1, 0xb2, 0xe0, 0xcd, 0x2d, 0xb1, 0x5b, 0xb2, 0xf1, 0x74, 0x79, 0x5c, + 0x4e, 0x97, 0x48, 0xec, 0x0c, 0xdd, 0x62, 0x7c, 0xbe, 0x5c, 0xd0, 0x04, 0xcf, 0x36, 0x56, 0xcd, 0x97, 0x06, 0x2d, + 0x25, 0x65, 0xb8, 0xde, 0x96, 0xe8, 0xff, 0xaf, 0x2e, 0x7e, 0x29, 0xc0, 0x4b, 0x30, 0x16, 0x00, 0xc2, 0x3d, 0x98, + 0x16, 0xa4, 0x36, 0xca, 0xc6, 0x3a, 0x0d, 0x53, 0x5c, 0x04, 0x26, 0xa5, 0xdf, 0x0f, 0x73, 0x96, 0x12, 0x0f, 0x3a, + 0xd4, 0x8e, 0xd2, 0xaa, 0x61, 0x33, 0x07, 0x3c, 0x92, 0x3a, 0xc7, 0x26, 0x7f, 0x1f, 0xcf, 0x02, 0x35, 0x10, 0x41, + 0x94, 0x1d, 0xe3, 0x23, 0x06, 0x2e, 0x8a, 0x74, 0xdc, 0x4e, 0x57, 0xc4, 0xe5, 0xfe, 0x31, 0x0b, 0x71, 0x92, 0x30, + 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, 0x04, 0x91, 0x5a, 0x6d, + 0x19, 0x57, 0x5d, 0x65, 0x7c, 0x0f, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, 0x9b, 0x28, 0xe4, 0x27, + 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0xef, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0xe7, 0xcd, 0x59, 0xd7, 0x50, 0x9a, 0xb8, + 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, 0x82, 0x09, 0x3a, 0x9a, + 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x9e, 0x25, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, 0x0f, 0xaa, 0x93, 0x75, + 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xcd, + 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, + 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, 0x01, 0x70, 0x32, 0xdb, + 0xdb, 0x68, 0x49, 0x37, 0x51, 0x4a, 0x6f, 0xa2, 0x35, 0x5d, 0x46, 0x17, 0xc6, 0xc4, 0x38, 0xa9, 0xe1, 0x1c, 0x80, + 0x56, 0x01, 0x24, 0x9e, 0xfa, 0xf5, 0x9e, 0x27, 0x55, 0xb8, 0xa4, 0x29, 0xb8, 0x0d, 0xfb, 0xf6, 0x99, 0x67, 0xbe, + 0x44, 0x6a, 0x8b, 0x18, 0x6b, 0xd6, 0x50, 0x71, 0xeb, 0xad, 0xfb, 0x48, 0xd4, 0xb0, 0x73, 0x5d, 0x6c, 0xa2, 0x6a, + 0x38, 0x99, 0x96, 0x80, 0xd8, 0x5a, 0x0e, 0x87, 0xee, 0x08, 0xd9, 0x3f, 0x7e, 0x74, 0xa0, 0xe7, 0x9e, 0xb4, 0xd8, + 0xb6, 0x2d, 0x7f, 0x60, 0x08, 0x53, 0xfa, 0xe5, 0x23, 0x1f, 0x10, 0x2b, 0xce, 0xe1, 0x6c, 0x04, 0xea, 0x68, 0x85, + 0x4e, 0xff, 0xaa, 0xc2, 0x42, 0x1f, 0xe0, 0xdb, 0xdb, 0x28, 0xa1, 0x9b, 0x28, 0xf7, 0xc8, 0xda, 0xb2, 0x66, 0x72, + 0x7a, 0x96, 0x85, 0xbc, 0x7d, 0xa0, 0x97, 0x0b, 0x00, 0xd1, 0x1a, 0xc4, 0xbe, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, + 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xb8, 0x92, 0xf0, 0x37, 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, + 0x39, 0x0f, 0x6a, 0x7f, 0x24, 0x5f, 0x17, 0x6d, 0x6f, 0x57, 0x18, 0x4d, 0x30, 0xf6, 0x44, 0xfb, 0x3c, 0x52, 0x8e, + 0xe2, 0x22, 0x09, 0xb3, 0xd1, 0xad, 0x3a, 0xcf, 0x69, 0x36, 0xda, 0xe8, 0x5f, 0x15, 0x1d, 0xd3, 0x5f, 0x75, 0x40, + 0x1b, 0x25, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0x34, 0xfe, 0xd7, 0x72, 0x74, 0x4b, 0xe5, 0x68, 0xe3, 0x5b, + 0x52, 0x4d, 0xa6, 0xc5, 0xb1, 0x40, 0x43, 0xaa, 0xce, 0xef, 0x0b, 0xe0, 0xe7, 0x4a, 0xe3, 0x3b, 0x6d, 0xbe, 0xf7, + 0xda, 0xbf, 0xe9, 0xe4, 0x09, 0x14, 0x4b, 0x54, 0xb0, 0x6a, 0x04, 0x76, 0xec, 0xeb, 0x3c, 0x2e, 0xcc, 0x28, 0xc5, + 0xd4, 0x9a, 0xf4, 0x63, 0xe0, 0x8a, 0x69, 0xaf, 0x00, 0x57, 0x4b, 0x70, 0x12, 0x80, 0x18, 0x9a, 0xb0, 0x67, 0xc7, + 0x10, 0xf5, 0xdc, 0x38, 0x46, 0xc9, 0x86, 0x7b, 0x40, 0xac, 0x65, 0xde, 0xca, 0x25, 0x20, 0x81, 0xb7, 0x1e, 0x26, + 0x05, 0x60, 0x0c, 0x96, 0x4b, 0xa2, 0xf3, 0x78, 0xe8, 0x13, 0xea, 0x85, 0x46, 0x9d, 0x90, 0x8d, 0x2d, 0x81, 0xe3, + 0x0f, 0xeb, 0x43, 0x20, 0x78, 0x95, 0xe7, 0xfa, 0x2b, 0xad, 0xeb, 0x2f, 0x95, 0x9e, 0x3b, 0x96, 0x17, 0xb5, 0xba, + 0x4d, 0x8d, 0x5e, 0x80, 0x85, 0xef, 0x56, 0x99, 0x47, 0x72, 0x8b, 0x90, 0xaa, 0xc0, 0x4a, 0xdd, 0x42, 0x82, 0xf9, + 0x57, 0x72, 0xb6, 0x2a, 0xf3, 0xd5, 0x23, 0xf7, 0xca, 0xd9, 0xf4, 0xf4, 0x37, 0x24, 0x68, 0x9b, 0x8e, 0x34, 0x8f, + 0xb7, 0xe8, 0xf0, 0xd9, 0xb5, 0x96, 0x98, 0x7b, 0x89, 0x8a, 0xe7, 0x53, 0xc0, 0x56, 0xcf, 0xb2, 0x2b, 0xe5, 0x63, + 0xb5, 0x8f, 0xe3, 0x67, 0xce, 0x9f, 0xa4, 0x0a, 0x2f, 0x44, 0x43, 0x09, 0x02, 0xde, 0x1c, 0xc6, 0xae, 0x50, 0x05, + 0x34, 0x34, 0x37, 0x70, 0x9c, 0xab, 0x61, 0xa5, 0x09, 0x98, 0x96, 0xf2, 0xe8, 0x00, 0x87, 0x26, 0x8f, 0xda, 0x4d, + 0xc3, 0xca, 0xd0, 0xb5, 0x46, 0x9f, 0xdb, 0x4a, 0x67, 0xbc, 0xd9, 0xf0, 0xc3, 0xa3, 0x41, 0x85, 0x3f, 0x49, 0x73, + 0x34, 0xda, 0xb9, 0xe1, 0x4e, 0x23, 0x30, 0x73, 0x25, 0x57, 0x64, 0x7f, 0x94, 0xbc, 0xfc, 0x9e, 0x5e, 0x58, 0x40, + 0x7f, 0xfe, 0xfb, 0x62, 0xc2, 0x49, 0x4b, 0x4c, 0x88, 0x96, 0x0e, 0x5a, 0x74, 0xb0, 0xa7, 0xbc, 0xb2, 0x2f, 0xf1, + 0xd2, 0x39, 0xfe, 0xcf, 0xf5, 0x58, 0xfb, 0x0a, 0x84, 0x56, 0x27, 0x0f, 0xdb, 0x93, 0x05, 0xa2, 0x06, 0x54, 0xb3, + 0xab, 0x72, 0x94, 0x69, 0x67, 0x45, 0xb6, 0x0d, 0x99, 0xeb, 0x7e, 0x96, 0x86, 0xcd, 0x64, 0xc7, 0xc2, 0x32, 0xc3, + 0x60, 0xed, 0x54, 0xd1, 0xe7, 0xa0, 0xe5, 0x47, 0xf0, 0xac, 0xa9, 0x3c, 0xf3, 0xd9, 0x2c, 0x23, 0x5e, 0xa0, 0x73, + 0x4e, 0xc5, 0xa2, 0x29, 0x1d, 0x2b, 0x77, 0xbb, 0x12, 0x8d, 0x25, 0xca, 0x28, 0x08, 0x6a, 0x1b, 0x84, 0x5d, 0x97, + 0xee, 0x49, 0x9f, 0xf6, 0xf1, 0x69, 0x05, 0xfa, 0x1e, 0xdf, 0x65, 0x20, 0x31, 0xf5, 0x24, 0x0f, 0x55, 0xa3, 0x39, + 0x3a, 0x79, 0x96, 0xa7, 0x1a, 0x9f, 0x5f, 0xc9, 0xce, 0x9a, 0x77, 0xab, 0x31, 0xc5, 0x7f, 0xa4, 0x6e, 0xdf, 0xb9, + 0x0c, 0x4d, 0xf4, 0xd7, 0xf2, 0xa0, 0xa5, 0xb0, 0xe0, 0xb8, 0x6d, 0xfc, 0xf5, 0xdb, 0xcc, 0x21, 0x86, 0xa5, 0xcb, + 0xe1, 0x4d, 0xe8, 0xd0, 0xdd, 0x55, 0xf6, 0xe6, 0xfa, 0x88, 0x3a, 0x75, 0xb1, 0x6e, 0x03, 0x4a, 0x96, 0xbc, 0x5b, + 0xa7, 0x27, 0x56, 0xfa, 0xf5, 0x30, 0xdc, 0x9b, 0x47, 0xcd, 0xee, 0xee, 0x76, 0x13, 0xd2, 0xb6, 0x0f, 0xc6, 0xfb, + 0x12, 0x16, 0xe2, 0xbc, 0xc3, 0x0e, 0x7e, 0x0e, 0xab, 0x87, 0x7c, 0xf0, 0x3b, 0x8e, 0x33, 0x8c, 0x7e, 0xa6, 0x0c, + 0x7d, 0x5e, 0x14, 0xf2, 0x4a, 0x75, 0xca, 0x17, 0xba, 0xb5, 0x4c, 0xbd, 0xdf, 0xc4, 0x6f, 0x5a, 0x01, 0x62, 0xbc, + 0xae, 0x58, 0x29, 0xde, 0xd0, 0x0a, 0xe3, 0x1a, 0xb8, 0x4d, 0x0e, 0xb5, 0x54, 0x0b, 0x44, 0x5d, 0x7e, 0xf2, 0x90, + 0x47, 0x46, 0x9d, 0x09, 0xdf, 0x3d, 0xe4, 0xbe, 0x74, 0x6d, 0xbf, 0x89, 0x5f, 0x6a, 0xda, 0xe1, 0xfe, 0x40, 0x77, + 0xb4, 0xee, 0xfe, 0xe6, 0xd9, 0xfc, 0x3c, 0x32, 0x5f, 0x0c, 0xb0, 0x59, 0xfb, 0x8c, 0xcb, 0x9e, 0xe1, 0xbe, 0x37, + 0x3d, 0x18, 0x0b, 0x08, 0x24, 0x66, 0xe8, 0x65, 0xe0, 0x02, 0x17, 0xb8, 0x2b, 0x0c, 0x18, 0xe2, 0x9a, 0x96, 0xdc, + 0x6a, 0x2b, 0x5b, 0x1f, 0x79, 0x1b, 0x15, 0x82, 0x75, 0xdd, 0x71, 0x93, 0xe4, 0x10, 0x9c, 0xb0, 0xe5, 0xde, 0xd7, + 0x5e, 0x3b, 0xc3, 0x5f, 0x06, 0xc2, 0xb9, 0x25, 0x7a, 0x46, 0x6d, 0x0f, 0xb5, 0xba, 0xd7, 0xf0, 0x2a, 0x9b, 0xc8, + 0xb3, 0x7e, 0x33, 0x2f, 0x0d, 0xfb, 0x82, 0xd7, 0x52, 0x70, 0x68, 0x6c, 0xb7, 0xc2, 0x2d, 0x16, 0xef, 0x68, 0xb5, + 0xb2, 0xd6, 0x56, 0x7b, 0xad, 0x54, 0xf4, 0xee, 0x35, 0xc7, 0x89, 0xb3, 0x14, 0xb6, 0x1f, 0xde, 0x5f, 0xb0, 0x6b, + 0x02, 0x18, 0xb4, 0x98, 0x2c, 0x50, 0x82, 0x4a, 0xd6, 0xaa, 0x76, 0x3b, 0x25, 0x7e, 0xb9, 0x5f, 0x75, 0x99, 0xed, + 0x3c, 0x7e, 0xdd, 0xa4, 0x7d, 0xe1, 0x73, 0xf4, 0xc3, 0xfc, 0xc1, 0x3a, 0x29, 0x39, 0xc3, 0xb8, 0x96, 0xff, 0x5f, + 0x45, 0x2f, 0x8b, 0x2c, 0x8d, 0xb6, 0x86, 0x07, 0xb3, 0xa1, 0x36, 0x7d, 0x68, 0x8c, 0xca, 0x2d, 0x1b, 0x45, 0x44, + 0xab, 0x5b, 0x10, 0xcc, 0x28, 0xee, 0x4b, 0xb4, 0x79, 0xa5, 0xca, 0xc2, 0x3b, 0x7c, 0x61, 0xa3, 0x37, 0x6c, 0x4f, + 0x08, 0xe5, 0xfb, 0xa7, 0x85, 0x59, 0xb5, 0x54, 0x34, 0xd8, 0x2e, 0xe1, 0x5d, 0x8c, 0x2a, 0xfd, 0x84, 0xc9, 0x96, + 0x05, 0x53, 0xfd, 0xff, 0xb1, 0xc8, 0xd2, 0x36, 0x45, 0x07, 0xa6, 0xb3, 0xe9, 0xd3, 0x49, 0xb7, 0xb8, 0xce, 0x80, + 0x45, 0x04, 0x5b, 0x2a, 0x1c, 0x8f, 0x52, 0xbb, 0x41, 0xc2, 0x44, 0x70, 0x13, 0xf5, 0xb2, 0xa3, 0x65, 0x4a, 0x56, + 0x05, 0x3c, 0xbf, 0x72, 0x95, 0xe9, 0x38, 0x1a, 0xfa, 0xfd, 0xb3, 0xd4, 0x84, 0x7e, 0xa5, 0x5e, 0xaa, 0xe2, 0x3c, + 0x8c, 0xaa, 0x43, 0x85, 0x31, 0x5a, 0xd2, 0x14, 0x8e, 0xc1, 0xec, 0x22, 0x4c, 0xf1, 0x72, 0xb6, 0x4d, 0xd8, 0x57, + 0x0c, 0xe4, 0x52, 0x1b, 0xd4, 0x6b, 0x4a, 0xb4, 0x66, 0xed, 0xcd, 0x9c, 0x12, 0x7a, 0xc1, 0x4a, 0xff, 0x2e, 0xb4, + 0x06, 0x81, 0xa2, 0x6c, 0xa6, 0x4c, 0x37, 0xba, 0x9d, 0x17, 0x34, 0xa1, 0x05, 0x5d, 0x91, 0x1a, 0xf4, 0xbd, 0x4e, + 0xce, 0x8e, 0x4e, 0x76, 0x66, 0xd6, 0x63, 0x56, 0x0c, 0x27, 0xd3, 0x18, 0xae, 0x69, 0xb1, 0xbb, 0xa6, 0x2d, 0x9b, + 0x37, 0xae, 0xc6, 0xc6, 0x69, 0xd0, 0x2e, 0x90, 0xb6, 0x69, 0x6e, 0x3f, 0xf5, 0xb8, 0xfd, 0x75, 0xcd, 0x96, 0xd3, + 0xde, 0x7a, 0xb7, 0xeb, 0xa5, 0x60, 0x23, 0xea, 0xf1, 0xf1, 0x6b, 0x25, 0x5d, 0xb7, 0x5c, 0x7e, 0x0a, 0xcf, 0x1e, + 0x5f, 0xbf, 0xf4, 0xc1, 0xe5, 0x68, 0xd5, 0xe6, 0xee, 0x97, 0xfb, 0xc8, 0x72, 0x5f, 0x35, 0xb4, 0x5c, 0xcf, 0x50, + 0x93, 0x3c, 0x1b, 0xed, 0x1d, 0x6a, 0xc1, 0x72, 0xd6, 0x4d, 0x78, 0x62, 0xb0, 0x63, 0xaf, 0x1a, 0x9b, 0xa3, 0x32, + 0x97, 0xac, 0x06, 0x09, 0xf4, 0x49, 0x9e, 0x69, 0xfa, 0x47, 0x19, 0xe6, 0xa3, 0x5b, 0x9a, 0x03, 0xae, 0x58, 0x65, + 0x2f, 0x19, 0xa4, 0xae, 0xda, 0x4b, 0x5c, 0xf9, 0x0a, 0x87, 0x64, 0x8b, 0x4f, 0x86, 0xa9, 0xfa, 0xe2, 0x92, 0x07, + 0xff, 0x6f, 0xab, 0x56, 0xe9, 0xb9, 0x49, 0x6e, 0x38, 0xfe, 0x75, 0xd2, 0xf6, 0x31, 0x31, 0x48, 0xc0, 0x53, 0xbb, + 0x18, 0xaa, 0x51, 0x55, 0xc4, 0xa2, 0xcc, 0x4d, 0xcc, 0xb1, 0x3b, 0xbb, 0x86, 0x0e, 0xca, 0xe0, 0xd7, 0x0d, 0x9f, + 0x98, 0x3b, 0xb0, 0x15, 0xe8, 0xe8, 0x44, 0x73, 0x19, 0x66, 0xe6, 0x32, 0x4c, 0xbb, 0xb6, 0x0a, 0x0c, 0xaf, 0xda, + 0x2a, 0x89, 0x72, 0x35, 0xea, 0x71, 0x33, 0x4b, 0xcd, 0x5e, 0xe4, 0xdd, 0x6b, 0xd2, 0x93, 0xf8, 0xd3, 0xa5, 0x27, + 0xaf, 0x87, 0x01, 0x91, 0x5f, 0xb3, 0x34, 0x5c, 0xa3, 0x20, 0x38, 0xb5, 0xda, 0x81, 0x34, 0x1f, 0x01, 0x32, 0x3f, + 0x4e, 0xc3, 0x0f, 0x5a, 0x9c, 0x43, 0xb6, 0x4a, 0xe3, 0xc4, 0x96, 0x46, 0x3d, 0x04, 0x77, 0xde, 0x2b, 0x1e, 0x43, + 0xe0, 0xc3, 0x8f, 0xb8, 0x19, 0x54, 0x74, 0x5b, 0x62, 0xa2, 0xb4, 0x79, 0xd4, 0x2d, 0x1f, 0x35, 0x84, 0x4a, 0x56, + 0x86, 0x97, 0x40, 0x7b, 0xf7, 0x04, 0x46, 0x95, 0x13, 0xc8, 0x0c, 0x8b, 0xc3, 0xa3, 0x61, 0xaa, 0x04, 0x45, 0x43, + 0x39, 0x5c, 0xa2, 0x1c, 0x10, 0x93, 0x40, 0x60, 0x54, 0x0c, 0x52, 0x5d, 0x99, 0x7a, 0x31, 0x48, 0xf5, 0xad, 0x8a, + 0xd4, 0x67, 0x59, 0x58, 0x51, 0xdd, 0x22, 0x3a, 0xa6, 0x43, 0x49, 0x97, 0x66, 0xa7, 0xe6, 0x5a, 0x7a, 0xa1, 0x96, + 0xe3, 0x53, 0x9d, 0x06, 0xa3, 0xf8, 0xc1, 0xa5, 0xe8, 0xb7, 0x6a, 0x3f, 0xfb, 0x6f, 0x31, 0xa5, 0x46, 0x6c, 0x6a, + 0x6f, 0x11, 0xc3, 0xaa, 0xfd, 0x98, 0x55, 0x39, 0x68, 0x77, 0x41, 0xd9, 0x58, 0x19, 0xe7, 0xf9, 0x46, 0x30, 0x73, + 0xd0, 0x36, 0x56, 0x4d, 0x1f, 0x7a, 0x23, 0x46, 0xed, 0x8d, 0xa9, 0xc6, 0x3d, 0x81, 0x9f, 0x36, 0x68, 0xba, 0x17, + 0x79, 0x8e, 0x7a, 0xe4, 0xdd, 0xff, 0xcc, 0x91, 0x9d, 0xc9, 0x17, 0xb1, 0x4c, 0xea, 0xf6, 0x31, 0x09, 0x16, 0xaa, + 0x8e, 0xd1, 0x85, 0x1b, 0x99, 0xd2, 0x7e, 0xee, 0x4d, 0x3f, 0xe2, 0x99, 0xdc, 0x6f, 0x87, 0x46, 0x7d, 0x69, 0x58, + 0x4b, 0x8a, 0xa8, 0x2f, 0xe8, 0xad, 0xa9, 0x8e, 0x8e, 0xa8, 0xd7, 0x11, 0x58, 0x5d, 0xd1, 0x16, 0x35, 0x00, 0x93, + 0x71, 0x6d, 0x6b, 0xf3, 0x39, 0x98, 0xda, 0xaa, 0x0a, 0x9e, 0xd0, 0x7d, 0xa1, 0x74, 0x6f, 0x52, 0xd7, 0xad, 0x21, + 0xb6, 0x80, 0x01, 0x81, 0x1b, 0x3d, 0x35, 0xfd, 0x41, 0x13, 0x15, 0x80, 0x06, 0x8d, 0xdb, 0x99, 0xce, 0x91, 0xe8, + 0x77, 0x6a, 0xd3, 0x36, 0x53, 0xbd, 0xaa, 0x7c, 0x00, 0x15, 0x7f, 0x96, 0xce, 0x2e, 0xcc, 0x88, 0x05, 0x30, 0xee, + 0x81, 0x33, 0xd5, 0x3b, 0xcd, 0xc0, 0x7a, 0x22, 0xcf, 0xb3, 0x92, 0x27, 0x52, 0xc0, 0x8c, 0xc8, 0xab, 0x2b, 0x29, + 0x60, 0x18, 0xd4, 0x00, 0xa0, 0x45, 0x73, 0x19, 0x4d, 0xf8, 0xa3, 0x9a, 0xde, 0x95, 0x87, 0x3f, 0xd2, 0xb9, 0xbe, + 0x1b, 0xd7, 0x60, 0xa8, 0xbc, 0xae, 0xf8, 0x5e, 0xa6, 0xef, 0xf8, 0x63, 0x2f, 0xd3, 0x52, 0xae, 0x8b, 0xbd, 0x2c, + 0x8f, 0xbe, 0xe3, 0x4f, 0x74, 0x9e, 0xa3, 0xc7, 0x35, 0x4d, 0xe3, 0xcd, 0x5e, 0x96, 0xbf, 0x7f, 0xf7, 0xd8, 0xe6, + 0x79, 0x34, 0xae, 0xe9, 0x0d, 0xe7, 0x9f, 0x5c, 0xa6, 0x89, 0xae, 0x6a, 0xfc, 0xf8, 0xef, 0x36, 0xd7, 0xe3, 0x9a, + 0x5e, 0x49, 0x51, 0x2d, 0xf7, 0x8a, 0x3a, 0xfa, 0xee, 0xe8, 0xef, 0xfc, 0x3b, 0xd3, 0xbd, 0xa3, 0x9a, 0xfe, 0xb5, + 0x8e, 0x8b, 0x8a, 0x17, 0x7b, 0xc5, 0xfd, 0xed, 0xef, 0x7f, 0x7f, 0x6c, 0x33, 0x3e, 0xae, 0xe9, 0x86, 0xc7, 0x1d, + 0x6d, 0x9f, 0x3c, 0x79, 0xcc, 0xff, 0x56, 0xd7, 0xf4, 0x37, 0xe6, 0x07, 0x47, 0x3d, 0xcd, 0x3c, 0x3d, 0x7c, 0x2e, + 0x9b, 0xa8, 0x01, 0x43, 0x0f, 0x0d, 0x60, 0x29, 0xad, 0x9a, 0xe6, 0x0e, 0xaf, 0x5c, 0x70, 0xfb, 0x3e, 0x8b, 0xd3, + 0x78, 0x05, 0x07, 0xc1, 0x16, 0x8d, 0xb3, 0x0a, 0xe0, 0x54, 0x81, 0xf7, 0x8c, 0x4a, 0x9a, 0x95, 0xf2, 0x37, 0xce, + 0x3f, 0xc1, 0xa0, 0x21, 0xa4, 0x8d, 0x8a, 0x0c, 0xf4, 0x76, 0xa5, 0x23, 0x1b, 0xa1, 0xff, 0x66, 0x33, 0x0e, 0x8e, + 0x0f, 0xa3, 0xd7, 0xef, 0x87, 0x05, 0x13, 0x61, 0x41, 0x08, 0xfd, 0x33, 0x2c, 0xc0, 0xa1, 0xa4, 0x60, 0x5e, 0x3e, + 0xe3, 0x7b, 0xae, 0x8d, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xf6, 0x01, 0x55, 0x8f, 0xbe, 0x43, 0x37, 0xc4, 0xcb, 0x0a, + 0x0b, 0x86, 0x56, 0x35, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x4a, 0xf0, 0x89, 0x07, 0xf8, 0xe8, 0x31, 0x99, 0x71, + 0x75, 0xad, 0x7d, 0x7b, 0x11, 0x16, 0x34, 0xd0, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xff, 0x02, 0x3c, 0x05, 0x06, 0x3e, + 0x2c, 0xec, 0xba, 0x03, 0xcf, 0xe7, 0x37, 0xc3, 0x3a, 0xba, 0xf0, 0xa3, 0xbf, 0x59, 0x17, 0xf6, 0x8c, 0x4c, 0xe5, + 0x71, 0x39, 0x9c, 0x4c, 0x07, 0x03, 0xe9, 0xe2, 0xb8, 0x9d, 0x66, 0xf3, 0xdf, 0xe6, 0x72, 0xb1, 0x40, 0xdd, 0x37, + 0xce, 0xeb, 0x4c, 0xff, 0x8d, 0xb4, 0xf3, 0xc1, 0xeb, 0xd3, 0x7f, 0x9d, 0x7d, 0x38, 0x7d, 0x01, 0xce, 0x07, 0x1f, + 0x9f, 0xff, 0xf8, 0xfc, 0xbd, 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0x72, 0x18, + 0xc6, 0x0f, 0x0b, 0x65, 0xf4, 0x40, 0x8e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, + 0x8b, 0xeb, 0x86, 0x08, 0xd7, 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x4f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, + 0x18, 0x94, 0x0d, 0x6d, 0x3a, 0xcd, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, + 0xba, 0xfa, 0x04, 0x34, 0x00, 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0x37, 0xa8, + 0x7b, 0x32, 0xcd, 0xaa, 0x1a, 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x6d, 0x5e, + 0x2d, 0x4c, 0x73, 0xdc, 0x30, 0x54, 0x5e, 0xc9, 0x17, 0xb2, 0x81, 0xc8, 0x40, 0x32, 0x0c, 0x7b, 0x34, 0x46, 0x91, + 0xfa, 0xc1, 0xbe, 0x77, 0xfc, 0x36, 0x97, 0x10, 0x4d, 0x31, 0x03, 0xe9, 0xfc, 0x73, 0xa1, 0x9c, 0xcb, 0x25, 0xe3, + 0x73, 0xb1, 0x38, 0x01, 0xb7, 0xf3, 0xb9, 0x58, 0x44, 0x18, 0x94, 0x2f, 0x83, 0x58, 0x25, 0x60, 0xf7, 0xe2, 0xa0, + 0x47, 0x3a, 0xa1, 0x0d, 0xec, 0x06, 0x92, 0x6c, 0x50, 0xda, 0x95, 0x86, 0x28, 0x77, 0xca, 0xa3, 0x0d, 0x22, 0x0f, + 0xb1, 0x6a, 0x5e, 0xb5, 0x3d, 0xd9, 0xcc, 0xc5, 0x04, 0x57, 0x59, 0xcc, 0xe4, 0x34, 0x3e, 0x66, 0xc5, 0x34, 0x86, + 0x52, 0xe2, 0x34, 0x0d, 0x63, 0x3a, 0xa1, 0x82, 0x90, 0x84, 0xf1, 0x79, 0xbc, 0xa0, 0x09, 0x4a, 0x09, 0x42, 0x08, + 0xf9, 0x31, 0x42, 0xdb, 0x1c, 0x58, 0xf2, 0x76, 0xfb, 0x79, 0x2a, 0xbe, 0x3d, 0xc3, 0x65, 0x54, 0x84, 0x6e, 0xd1, + 0x59, 0xc3, 0xbf, 0x11, 0x15, 0x34, 0xc6, 0x8a, 0x21, 0x08, 0x78, 0x81, 0x51, 0x09, 0x0b, 0x12, 0xb3, 0x0a, 0xa2, + 0x08, 0x94, 0xf3, 0x78, 0xc1, 0x0a, 0xda, 0xb4, 0x39, 0x8d, 0xb5, 0x49, 0x50, 0xcf, 0x61, 0xa9, 0x1d, 0x48, 0xa5, + 0x42, 0xec, 0xf1, 0x99, 0x88, 0x3e, 0x69, 0x43, 0x03, 0x40, 0x81, 0x52, 0x72, 0xf1, 0x9b, 0xaf, 0xf7, 0x70, 0x53, + 0xd0, 0xff, 0x6c, 0x6b, 0xa2, 0x9d, 0xe5, 0xea, 0xd0, 0x9b, 0x2f, 0x68, 0x9c, 0xe7, 0x10, 0x8a, 0xcd, 0x20, 0x90, + 0x8b, 0xac, 0x82, 0x88, 0x16, 0x9b, 0xc0, 0x84, 0x84, 0x83, 0x36, 0xfd, 0x02, 0xa9, 0x0d, 0x31, 0xb9, 0xf2, 0xc4, + 0xc0, 0x6e, 0xab, 0x04, 0x01, 0x47, 0x7a, 0x9e, 0x7d, 0x6e, 0x62, 0xac, 0x69, 0x6a, 0x66, 0xe2, 0x6d, 0x28, 0x44, + 0x83, 0x16, 0x44, 0x33, 0x78, 0xff, 0x5c, 0x71, 0xbc, 0xea, 0xc0, 0x0f, 0x78, 0xe7, 0xe2, 0xcc, 0xab, 0x99, 0x47, + 0xe4, 0xd4, 0xe7, 0x39, 0xa2, 0x5f, 0xf2, 0xb0, 0x1a, 0xe9, 0x64, 0x8c, 0x95, 0xc4, 0x41, 0x6f, 0x83, 0x05, 0x73, + 0x42, 0x57, 0x3c, 0xb4, 0x7c, 0xfc, 0x0b, 0x64, 0x32, 0x4a, 0x6a, 0xac, 0xe8, 0x4a, 0x8b, 0x11, 0xe7, 0x35, 0xcc, + 0xd2, 0x64, 0x45, 0x17, 0x0b, 0x4d, 0x9a, 0x85, 0x32, 0x0d, 0xf0, 0x09, 0xb4, 0x18, 0xb9, 0x87, 0x9a, 0x36, 0x10, + 0x1a, 0xf6, 0x87, 0x80, 0x8f, 0xdc, 0x43, 0x87, 0xff, 0x9f, 0x67, 0x17, 0x88, 0xb4, 0x77, 0x69, 0x22, 0xe3, 0x91, + 0xba, 0x81, 0x83, 0x62, 0x7c, 0xec, 0x9b, 0x89, 0x5f, 0x39, 0xa3, 0xf7, 0x49, 0xe5, 0x3b, 0x7c, 0xb0, 0xfc, 0xf1, + 0xa6, 0x66, 0x56, 0x46, 0xb0, 0x1e, 0x76, 0x3b, 0x5c, 0x10, 0x6d, 0x17, 0x40, 0xea, 0x19, 0xaf, 0x16, 0xbe, 0xf1, + 0x6a, 0x7c, 0x87, 0xf1, 0xaa, 0xb3, 0xfa, 0x0a, 0x73, 0xb2, 0x45, 0x7d, 0x96, 0x92, 0xe7, 0xe7, 0x28, 0x13, 0x6c, + 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, 0x0e, 0x23, 0x81, 0xaa, + 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, 0x03, 0xa1, 0xa1, 0xb1, + 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xdd, 0xae, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, 0xac, 0x46, 0x13, 0xe0, + 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, 0x49, 0x66, 0x65, 0x34, + 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, 0xba, 0xcc, 0x92, 0xcc, + 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, 0x90, 0x1f, 0x40, 0x19, + 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, 0x66, 0x57, 0xbc, 0xac, + 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0xec, 0x2e, 0xb7, 0x3d, 0x2a, 0xcc, 0xab, 0x37, 0xcf, 0x7f, 0x3c, 0x6d, 0xbc, + 0xda, 0x47, 0x1c, 0x0d, 0xc1, 0xb6, 0x62, 0x8c, 0xd1, 0x5b, 0x7c, 0x1a, 0x4c, 0x94, 0x6b, 0x04, 0x7a, 0x97, 0x82, + 0x7e, 0xfb, 0x6b, 0x3d, 0x01, 0xaf, 0xb8, 0x5e, 0x7e, 0xc9, 0x27, 0xc0, 0x12, 0x15, 0x7a, 0x56, 0x98, 0x9b, 0x95, + 0xd9, 0x9d, 0xdd, 0x8a, 0xcc, 0xb4, 0x2b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, 0x16, 0x2e, 0x5d, 0xd3, 0xed, 0x60, + 0x57, 0x4b, 0xcf, 0x12, 0x79, 0xb7, 0x2b, 0xa1, 0x43, 0x76, 0xc0, 0xbd, 0x97, 0xf1, 0x2d, 0xbc, 0x2c, 0xbd, 0x6e, + 0x36, 0x83, 0x27, 0x80, 0x99, 0x70, 0xe1, 0x2c, 0x8b, 0x63, 0x26, 0x92, 0x50, 0xc5, 0xe6, 0x6a, 0x88, 0xbc, 0x15, + 0xa1, 0x35, 0xfb, 0x2b, 0x14, 0x23, 0xb0, 0x3b, 0xf9, 0xf0, 0x29, 0x5b, 0xcd, 0xd6, 0x80, 0x9a, 0x7f, 0x95, 0x09, + 0xa0, 0xb9, 0x76, 0x2d, 0xd8, 0xa6, 0xd0, 0xe6, 0xba, 0x7e, 0x1a, 0xaf, 0xe2, 0x04, 0x54, 0x37, 0xe0, 0x2d, 0x72, + 0xad, 0x45, 0x57, 0x06, 0x5d, 0x94, 0xde, 0x53, 0x8e, 0x25, 0x85, 0x8e, 0xbe, 0xf7, 0x84, 0x3a, 0xf7, 0x0c, 0xe0, + 0x92, 0x46, 0xcd, 0x53, 0x2d, 0x65, 0x2c, 0x00, 0x16, 0x3a, 0x98, 0x29, 0xb2, 0x15, 0xdd, 0x18, 0x4c, 0x0a, 0x78, + 0x6b, 0x80, 0x3f, 0x44, 0x56, 0xa9, 0xbb, 0x62, 0x19, 0x96, 0x9e, 0xfd, 0x75, 0xbf, 0x1f, 0x7b, 0xf6, 0xd7, 0x2b, + 0x4d, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x8d, 0x01, 0x44, 0x4e, 0xf5, 0x40, 0x98, 0x88, 0x62, 0x4d, 0xdf, 0xbf, 0x53, + 0x93, 0x45, 0x81, 0xd0, 0xef, 0xd5, 0xeb, 0x49, 0x49, 0x40, 0xa7, 0x56, 0xb1, 0x93, 0x81, 0x36, 0xfb, 0x80, 0x80, + 0xa8, 0x7e, 0x46, 0x36, 0x5f, 0x28, 0xe7, 0x62, 0x15, 0x3e, 0x7c, 0x4c, 0x21, 0xa0, 0x70, 0x47, 0x8d, 0xce, 0xdb, + 0x10, 0x09, 0x94, 0x15, 0x8a, 0x58, 0xf3, 0x62, 0x2d, 0x09, 0x99, 0x8f, 0x17, 0x28, 0xb8, 0x72, 0xc0, 0xae, 0x9c, + 0x4d, 0x86, 0x65, 0xc4, 0x59, 0x78, 0xf7, 0x37, 0x93, 0x05, 0x41, 0xcd, 0x95, 0x1f, 0xc8, 0x71, 0x2f, 0x53, 0x63, + 0x4f, 0x35, 0x6a, 0x10, 0x4c, 0x46, 0x10, 0x18, 0x6e, 0xf8, 0x15, 0x1f, 0x1f, 0x2d, 0x08, 0xa8, 0xc8, 0xac, 0x59, + 0x88, 0x79, 0x71, 0xfc, 0x08, 0x50, 0x63, 0x46, 0x47, 0x4f, 0xa6, 0x9c, 0xc1, 0x21, 0x4a, 0xc7, 0x20, 0xa3, 0x15, + 0xf0, 0x5b, 0xa8, 0xdf, 0xad, 0x13, 0xdf, 0x87, 0x7e, 0x15, 0xf4, 0x22, 0x06, 0x86, 0x23, 0x9a, 0x1c, 0x86, 0x7c, + 0x30, 0x19, 0x80, 0xb6, 0xc4, 0xdb, 0x7d, 0x2d, 0xad, 0xb8, 0x39, 0x5d, 0x3a, 0xdd, 0x3f, 0x69, 0x13, 0x24, 0x91, + 0x4a, 0x56, 0x2a, 0x62, 0x00, 0xa1, 0x2c, 0xd5, 0x36, 0x59, 0x83, 0x65, 0x85, 0x59, 0xd2, 0xdc, 0xa0, 0x24, 0xee, + 0x6f, 0x06, 0x8e, 0x51, 0xb3, 0x4e, 0xc3, 0xb2, 0xe5, 0x46, 0x0d, 0xf0, 0x39, 0x09, 0x2b, 0xec, 0x0d, 0x67, 0x26, + 0xbd, 0x33, 0x1d, 0xae, 0x8e, 0x39, 0x7b, 0xcd, 0x11, 0x8c, 0x23, 0xc1, 0x1b, 0x0f, 0x5d, 0x32, 0x0d, 0x15, 0x99, + 0x32, 0x0e, 0xa6, 0x3d, 0xc0, 0xbd, 0xe7, 0x60, 0x1c, 0xc6, 0x06, 0x95, 0x25, 0xf5, 0xa9, 0x77, 0x17, 0x02, 0x41, + 0x5a, 0xeb, 0x65, 0x3e, 0xc3, 0xd3, 0x33, 0x42, 0xd9, 0x1f, 0x72, 0xf8, 0x02, 0xec, 0x28, 0xc8, 0xc9, 0x84, 0x3f, + 0x79, 0xb8, 0x1f, 0xa8, 0x8a, 0x0f, 0x82, 0x83, 0x58, 0xa4, 0x07, 0xc1, 0x40, 0xc0, 0xaf, 0x82, 0x1f, 0x54, 0x52, + 0x1e, 0x5c, 0xc4, 0xc5, 0x41, 0xbc, 0x8a, 0x8b, 0xea, 0xe0, 0x26, 0xab, 0x96, 0x07, 0xa6, 0x43, 0x00, 0xcd, 0x1b, + 0x0c, 0xe2, 0x41, 0x70, 0x10, 0x0c, 0x0a, 0x33, 0xb5, 0x2b, 0x56, 0x36, 0x8e, 0x33, 0x13, 0xa2, 0x2c, 0x68, 0x06, + 0x08, 0x6b, 0x9c, 0x06, 0xc0, 0xa7, 0xae, 0x59, 0x4a, 0x2f, 0x30, 0xdc, 0x80, 0x98, 0xae, 0xa1, 0x0f, 0xc0, 0x23, + 0xaf, 0x69, 0x0c, 0x4b, 0xe0, 0x62, 0x30, 0x20, 0x17, 0x10, 0xb9, 0x60, 0x4d, 0x6d, 0x10, 0x87, 0x70, 0xad, 0xec, + 0xb4, 0xf7, 0x81, 0x99, 0x76, 0x3b, 0x40, 0x54, 0x9e, 0x90, 0x7e, 0xdf, 0x7e, 0x43, 0xfd, 0x0b, 0xf6, 0x12, 0xec, + 0xaf, 0x8a, 0x2a, 0xcc, 0xa5, 0xd2, 0x7c, 0x5f, 0xb2, 0x93, 0x81, 0x8a, 0x38, 0xbc, 0xe7, 0x48, 0xd1, 0x46, 0xe5, + 0xb2, 0xec, 0xc9, 0xb2, 0xe1, 0x2b, 0x71, 0xc5, 0x9d, 0x1f, 0x57, 0x25, 0x65, 0x5e, 0x65, 0x2b, 0xc5, 0xfe, 0xcd, + 0xb8, 0xe6, 0xfe, 0xc0, 0xfa, 0xb3, 0xf9, 0x0a, 0xae, 0xad, 0xde, 0xbb, 0x26, 0xd7, 0x88, 0x9c, 0x25, 0x94, 0x4b, + 0x6a, 0x9b, 0x87, 0xb7, 0xf4, 0x7d, 0x7e, 0xf5, 0x6d, 0xa6, 0xd3, 0xf8, 0xac, 0xc2, 0xc2, 0x85, 0x68, 0x45, 0x70, + 0x68, 0xc8, 0x45, 0xf3, 0x08, 0x30, 0xd7, 0x3e, 0x5b, 0x41, 0x41, 0xea, 0xb3, 0x0a, 0xbd, 0x5b, 0x21, 0xe1, 0x85, + 0x66, 0x97, 0xee, 0x07, 0x52, 0xc6, 0xed, 0xa1, 0x25, 0x4c, 0x5a, 0x5e, 0x84, 0xf7, 0x5e, 0x73, 0x93, 0x7b, 0x16, + 0x62, 0xf4, 0x22, 0xcf, 0x4e, 0xc0, 0x58, 0x77, 0xc9, 0xce, 0x86, 0x27, 0x7e, 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, + 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x01, + 0x09, 0x29, 0x22, 0x91, 0xac, 0xd5, 0x49, 0xf2, 0x85, 0xee, 0x02, 0x30, 0xfa, 0xc5, 0x2c, 0x8d, 0x96, 0x77, 0x9a, + 0x59, 0x20, 0x79, 0x86, 0xbe, 0xeb, 0x60, 0x7b, 0x63, 0x1f, 0xa4, 0x9c, 0x1f, 0x8b, 0xe9, 0x60, 0xc0, 0x89, 0x86, + 0x1b, 0x2f, 0x95, 0xb8, 0x56, 0xb7, 0xb8, 0x63, 0x18, 0x4b, 0x7d, 0x5b, 0xc4, 0xe0, 0x80, 0x5d, 0xb4, 0xb2, 0xdb, + 0x07, 0xd8, 0x57, 0x8e, 0x77, 0xa9, 0xb2, 0x3b, 0x3d, 0x66, 0x9a, 0xcb, 0x56, 0x93, 0x4e, 0x2a, 0xee, 0x26, 0xf2, + 0x4d, 0xee, 0xa0, 0xcb, 0xe5, 0x58, 0xf3, 0x96, 0x03, 0x50, 0xd1, 0x8f, 0x14, 0xd5, 0xfd, 0x0a, 0x47, 0x98, 0x7b, + 0xeb, 0x36, 0x9f, 0x1c, 0x9a, 0x02, 0x87, 0xc8, 0x93, 0x36, 0x9a, 0x02, 0xba, 0x77, 0xf1, 0xb0, 0xab, 0xdf, 0x96, + 0xee, 0x02, 0x25, 0xda, 0xab, 0xb8, 0xe1, 0xc7, 0x44, 0x9d, 0xce, 0xb4, 0x21, 0xf4, 0xaf, 0x8c, 0xb8, 0xbf, 0x34, + 0xae, 0xe2, 0x4d, 0xef, 0xf2, 0x19, 0x87, 0x3a, 0xbb, 0x21, 0x14, 0x80, 0xab, 0xf6, 0x74, 0xea, 0xc6, 0x90, 0x5e, + 0x29, 0xd1, 0x6d, 0x70, 0xb0, 0x3b, 0x7d, 0xc6, 0x51, 0xf4, 0x63, 0xd4, 0xc8, 0x37, 0x91, 0x78, 0x28, 0x07, 0xf1, + 0xc3, 0x82, 0x2e, 0x23, 0xf1, 0xb0, 0x18, 0xc4, 0x0f, 0x65, 0x5d, 0xef, 0x9f, 0x2b, 0x77, 0xf7, 0x11, 0x79, 0xd6, + 0xbd, 0xbd, 0x54, 0xc2, 0xc6, 0xc0, 0xb3, 0x6b, 0x01, 0xe1, 0x14, 0x3c, 0x91, 0xad, 0xa5, 0x0f, 0x9d, 0xdb, 0x7d, + 0x6c, 0x99, 0x24, 0x08, 0x7a, 0xde, 0x66, 0x93, 0x28, 0x76, 0xb6, 0x79, 0xf4, 0xe1, 0x14, 0x48, 0xe8, 0x76, 0xdb, + 0xac, 0xab, 0x35, 0xa0, 0x98, 0x86, 0x63, 0x7e, 0x58, 0x8c, 0x6e, 0x7c, 0x77, 0xfd, 0xc3, 0x62, 0xb4, 0x24, 0xc3, + 0x89, 0x99, 0xfc, 0xf8, 0x64, 0x3c, 0x8b, 0xa3, 0x49, 0xdd, 0x71, 0x5a, 0x68, 0xfc, 0x53, 0xef, 0x16, 0x8a, 0xc0, + 0xa9, 0x18, 0xc1, 0x91, 0x53, 0xa1, 0x9c, 0x94, 0x1a, 0x18, 0xfe, 0x07, 0xd5, 0x9e, 0x36, 0xed, 0x75, 0x5c, 0x25, + 0xcb, 0x4c, 0x5c, 0xea, 0xf0, 0xe1, 0x3a, 0xba, 0xb8, 0x0d, 0x68, 0xe7, 0x5d, 0xa6, 0x1d, 0xbf, 0x4e, 0x1a, 0xf4, + 0xc4, 0xd5, 0xcc, 0x80, 0x5b, 0xf7, 0x23, 0x34, 0x43, 0x60, 0xb4, 0x3c, 0x7f, 0x87, 0x98, 0xdb, 0xbf, 0x2a, 0x9b, + 0x5f, 0x45, 0xfb, 0x1c, 0x19, 0x29, 0xdb, 0x64, 0xa4, 0x02, 0x23, 0x4c, 0x29, 0x92, 0xb8, 0x0a, 0x21, 0x90, 0xfd, + 0xd7, 0x14, 0xd7, 0x62, 0xe9, 0xbd, 0x06, 0x61, 0x82, 0xed, 0x82, 0xf6, 0xab, 0xdb, 0xbb, 0xad, 0xb4, 0xd8, 0x23, + 0xf5, 0x7d, 0xee, 0x6c, 0x57, 0x34, 0xf9, 0xfb, 0xba, 0x01, 0x6d, 0x00, 0x51, 0xde, 0xd5, 0x47, 0x25, 0x70, 0x32, + 0xe2, 0x86, 0x12, 0xa3, 0x17, 0x74, 0x75, 0x22, 0xf7, 0xec, 0xd4, 0xbc, 0xa9, 0x98, 0xa9, 0xb8, 0xf2, 0xcd, 0x9e, + 0xf9, 0x0f, 0x86, 0x82, 0x4a, 0x30, 0xf0, 0x36, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, 0x18, 0x9d, 0x16, 0x6c, 0x16, 0xd4, + 0x65, 0xdd, 0xb4, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb1, 0x2a, 0xd4, 0x48, 0x78, 0x22, 0x10, 0x30, 0x65, 0x57, 0x3c, + 0x32, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x4a, 0x54, 0xd3, 0x9b, 0xd0, 0x26, 0x13, 0xa7, 0x19, 0x44, + 0x30, 0x23, 0xb6, 0xfb, 0x2d, 0xa0, 0xcd, 0xad, 0x19, 0x6d, 0xeb, 0xda, 0x6a, 0xab, 0x90, 0x4b, 0x8a, 0x94, 0xe5, + 0xbf, 0x53, 0x53, 0x41, 0x49, 0x2d, 0x17, 0xbd, 0x49, 0xd3, 0x45, 0x8f, 0x67, 0x46, 0x12, 0xa8, 0xdc, 0x72, 0xc7, + 0xe8, 0x0f, 0x61, 0x81, 0x47, 0x4c, 0x9c, 0x58, 0x30, 0xb7, 0x3a, 0x61, 0xd9, 0x5c, 0x2c, 0x46, 0x2b, 0x09, 0x61, + 0x83, 0x8f, 0x59, 0x36, 0x2f, 0xf5, 0x43, 0xe8, 0x0b, 0x4b, 0x1f, 0x80, 0x5d, 0x6c, 0xb0, 0x92, 0x65, 0x00, 0xbe, + 0x17, 0x74, 0xbb, 0x92, 0x65, 0x24, 0x55, 0xf7, 0xe3, 0x1a, 0x4b, 0x50, 0x69, 0x85, 0x4a, 0x4b, 0x6a, 0x2c, 0x08, + 0x7c, 0x55, 0x75, 0xf9, 0x90, 0xec, 0x2a, 0x50, 0x4f, 0x1d, 0x35, 0xe0, 0x14, 0xa8, 0x2a, 0xb0, 0x20, 0x09, 0x2a, + 0x43, 0x57, 0x05, 0xa6, 0x15, 0x98, 0x66, 0xaa, 0x70, 0x51, 0x66, 0x87, 0xd2, 0xac, 0x97, 0x7c, 0x16, 0x0f, 0xc2, + 0x64, 0x18, 0x93, 0x87, 0x08, 0xb5, 0x7f, 0x98, 0x47, 0xb1, 0x96, 0x4b, 0x5e, 0x3a, 0xbf, 0xf8, 0x9b, 0x2f, 0xd8, + 0xeb, 0x9e, 0x61, 0xb0, 0x00, 0x67, 0x69, 0x7b, 0x95, 0x89, 0x77, 0xb2, 0x15, 0x1c, 0x07, 0xb3, 0x28, 0x87, 0x55, + 0x4f, 0x8e, 0x68, 0x2e, 0x72, 0xed, 0x5d, 0x84, 0xc8, 0x41, 0x66, 0x8f, 0x01, 0x76, 0x23, 0x7c, 0x1d, 0x5a, 0x9b, + 0x5b, 0x5d, 0x21, 0xfe, 0x46, 0x89, 0xc4, 0x4f, 0x52, 0x7e, 0x5a, 0xaf, 0x54, 0xae, 0xca, 0xe0, 0xb1, 0xea, 0x66, + 0xf0, 0x4c, 0xfb, 0x1e, 0x6b, 0xff, 0xd6, 0x76, 0x73, 0xbc, 0xf7, 0xe0, 0x41, 0xeb, 0x7f, 0xeb, 0x49, 0x08, 0xed, + 0x95, 0x93, 0xd4, 0x1d, 0x35, 0x7a, 0x66, 0xb2, 0x46, 0x54, 0xc2, 0xd4, 0xee, 0x54, 0x8e, 0x81, 0x9a, 0x0e, 0xe0, + 0x5a, 0xa2, 0x26, 0xe8, 0x49, 0xc1, 0xc6, 0x70, 0xc4, 0x59, 0x1c, 0xb4, 0xe3, 0x18, 0xc5, 0xcb, 0xb9, 0x12, 0x2f, + 0xe7, 0x27, 0x8c, 0x03, 0xb4, 0x16, 0x20, 0xd5, 0x6b, 0xd8, 0xcf, 0x5c, 0xc1, 0x02, 0x9b, 0x3b, 0xdf, 0x91, 0x05, + 0x32, 0xc4, 0xc9, 0xe6, 0x38, 0xd9, 0xe3, 0x5a, 0xcf, 0xbd, 0xc0, 0xc7, 0x49, 0xbd, 0xf0, 0xea, 0x2a, 0xdb, 0x75, + 0x2d, 0x59, 0x39, 0x2f, 0x06, 0x13, 0x08, 0xca, 0x52, 0xce, 0x8b, 0xe1, 0x64, 0x41, 0x73, 0xf8, 0xb1, 0x68, 0xa0, + 0x43, 0x2c, 0x07, 0x09, 0x5c, 0x3a, 0x7b, 0x0c, 0x78, 0x43, 0xa9, 0xc5, 0xdd, 0x58, 0x47, 0x8e, 0x75, 0x14, 0x87, + 0x61, 0x0c, 0xb8, 0xb2, 0x4e, 0xe0, 0x7d, 0xf7, 0xf5, 0xb1, 0x09, 0xc8, 0xaa, 0x5d, 0xe1, 0xd5, 0x28, 0x77, 0x5d, + 0x69, 0xf4, 0x25, 0xa5, 0x27, 0xbc, 0xe0, 0xa9, 0x64, 0xb7, 0xeb, 0x19, 0x38, 0x5b, 0xe2, 0x21, 0xf1, 0x8e, 0x11, + 0xbd, 0x98, 0x36, 0x32, 0x73, 0x02, 0x67, 0xb6, 0xbb, 0x6c, 0x63, 0x7e, 0xec, 0x00, 0x07, 0x8b, 0x20, 0x24, 0x6e, + 0x08, 0xc3, 0xc4, 0x4e, 0xca, 0xa1, 0x16, 0xc2, 0x75, 0x2d, 0xbc, 0x8e, 0xd3, 0x32, 0x06, 0x17, 0x69, 0x6d, 0x9b, + 0x78, 0x07, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, 0x0c, 0x40, 0xd3, + 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, 0xfe, 0xbd, 0xe6, + 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, 0x13, 0xb7, 0xdb, + 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, 0x18, 0x30, 0x97, + 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, 0xcc, 0x03, 0x99, + 0x02, 0xe2, 0xf9, 0x87, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd3, 0xf1, 0x8d, 0xe8, 0x6b, 0xfb, 0xe2, 0x92, + 0x57, 0x6f, 0x6f, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, 0x1d, 0x14, 0x59, + 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xad, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, 0x09, 0x53, 0x80, + 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, 0x31, 0x80, 0xc2, + 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa4, 0x3a, 0x03, 0x2d, 0xeb, 0x69, 0x01, 0xa2, + 0x3a, 0x88, 0xb6, 0x0a, 0x51, 0xa1, 0x53, 0x5a, 0x66, 0x34, 0x15, 0x74, 0x2d, 0x68, 0x92, 0xd1, 0x0b, 0xae, 0x44, + 0xc5, 0x2b, 0xc1, 0x14, 0x6d, 0x37, 0x84, 0xfd, 0x1f, 0x0d, 0xba, 0xde, 0x8a, 0xb5, 0x86, 0x76, 0x27, 0xc8, 0x08, + 0xcd, 0x17, 0x3a, 0x08, 0x19, 0x2a, 0x27, 0xa1, 0x6b, 0x95, 0xc6, 0x2b, 0x70, 0xc9, 0x34, 0x1b, 0x2d, 0xe3, 0x32, + 0x0c, 0xec, 0x57, 0x81, 0xc5, 0xe4, 0xc0, 0xa4, 0x0f, 0xeb, 0xf3, 0xa7, 0xf2, 0x6a, 0x25, 0x05, 0x17, 0x95, 0x82, + 0xe8, 0x37, 0xb8, 0xef, 0x26, 0xae, 0x3a, 0x6b, 0xd6, 0x4a, 0xef, 0xfb, 0xd6, 0x67, 0x6d, 0xdc, 0x17, 0x06, 0xc7, + 0x60, 0xef, 0x23, 0x62, 0x20, 0x0d, 0x2a, 0xdd, 0xe2, 0xd0, 0x04, 0xe8, 0xd2, 0x21, 0x85, 0x2c, 0x99, 0xca, 0x54, + 0x09, 0x2a, 0xbe, 0xf1, 0x7b, 0x29, 0xab, 0xd1, 0x5f, 0x6b, 0x5e, 0x6c, 0x3e, 0xf0, 0x9c, 0xe3, 0x18, 0x05, 0x49, + 0x2c, 0xae, 0xe3, 0x32, 0x20, 0xbe, 0xe5, 0x55, 0x70, 0x94, 0x9a, 0xb0, 0x31, 0x7b, 0x55, 0xa3, 0xd6, 0xab, 0x40, + 0x5f, 0x19, 0xe5, 0x1b, 0x83, 0xa1, 0x89, 0xa8, 0x82, 0xbe, 0xd7, 0xea, 0x9e, 0x56, 0x37, 0x2c, 0x20, 0xfe, 0x5c, + 0xe9, 0x85, 0x5a, 0xaf, 0x9b, 0x31, 0x37, 0x4c, 0x84, 0xa0, 0xd1, 0xa3, 0x7a, 0xe1, 0xf0, 0xf3, 0xb7, 0xca, 0x92, + 0x08, 0x5e, 0x6c, 0xd3, 0x75, 0x61, 0x62, 0x69, 0x50, 0x1d, 0x30, 0x37, 0xda, 0xe6, 0xfc, 0x12, 0x44, 0x7f, 0xce, + 0x8a, 0x68, 0x52, 0xd7, 0x54, 0x21, 0x18, 0x46, 0xdb, 0xdb, 0x46, 0x3a, 0xdd, 0x80, 0x97, 0x9b, 0xb1, 0x46, 0xd2, + 0x9e, 0x8e, 0x35, 0x2d, 0x78, 0xb9, 0x92, 0xa2, 0x84, 0xe8, 0xce, 0xbd, 0x31, 0xbd, 0x8a, 0x33, 0x51, 0xc5, 0x99, + 0x38, 0x2d, 0x57, 0x3c, 0xa9, 0xde, 0x43, 0x85, 0xda, 0x18, 0x07, 0x5b, 0xaf, 0x46, 0x5d, 0x85, 0x43, 0x7e, 0x75, + 0xf1, 0xfc, 0x76, 0x15, 0x8b, 0x14, 0x46, 0xbd, 0xbe, 0xeb, 0x45, 0x73, 0x3a, 0x56, 0x71, 0xc1, 0x85, 0x89, 0x5a, + 0x4c, 0x2b, 0x16, 0x70, 0x9d, 0x31, 0xa0, 0x5c, 0xc5, 0xee, 0xcc, 0x54, 0x2c, 0xc3, 0xb8, 0x2c, 0x7f, 0xca, 0x4a, + 0xbc, 0x03, 0x40, 0x6b, 0xe0, 0xb4, 0x98, 0x19, 0x10, 0x90, 0x4d, 0x6e, 0x70, 0x11, 0x58, 0x70, 0xf4, 0x78, 0xbc, + 0xba, 0x0d, 0xa8, 0xf7, 0x46, 0xaa, 0xeb, 0x21, 0x0b, 0xc6, 0xa3, 0x27, 0x81, 0x43, 0x0e, 0xf1, 0x3f, 0x7a, 0x7c, + 0x74, 0xf7, 0x37, 0x93, 0x80, 0xd4, 0x53, 0x50, 0x55, 0x18, 0x85, 0x28, 0x4c, 0xfb, 0xeb, 0xb5, 0xba, 0xe5, 0xbe, + 0x3d, 0x2f, 0x79, 0x71, 0x0d, 0xfb, 0x92, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, 0xab, 0xaa, 0xc8, + 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, 0x58, 0xd4, 0xa4, + 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, 0x4a, 0x8c, 0x35, + 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, 0xb7, 0x53, 0xd5, + 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xe6, 0x60, 0x78, 0x00, 0xc9, + 0x64, 0xfa, 0x79, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, 0x3d, 0x1f, 0xfe, + 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, 0xef, 0x50, 0xad, + 0xef, 0xd3, 0xa2, 0x88, 0x37, 0x35, 0x59, 0xd0, 0x95, 0x70, 0xde, 0x35, 0xd4, 0x23, 0x0b, 0xf4, 0x88, 0x4c, 0x57, + 0x82, 0xc1, 0x37, 0xef, 0xab, 0x30, 0xe0, 0xe5, 0x6a, 0xc8, 0x45, 0x95, 0x55, 0x9b, 0x21, 0xe6, 0x09, 0xf0, 0x53, + 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x99, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, 0xe2, 0x63, 0xaa, + 0xba, 0x31, 0xf9, 0x8e, 0xea, 0xbe, 0x4d, 0xbe, 0x03, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, 0x8c, 0xc6, 0xf4, + 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf3, 0x76, 0xf6, 0xd1, 0x68, 0xf4, 0xa0, + 0xa0, 0xa3, 0xd1, 0xe8, 0x53, 0x56, 0x13, 0x7a, 0x29, 0x3a, 0xde, 0xbf, 0xe7, 0xf4, 0x5c, 0xa6, 0x9b, 0x28, 0x08, + 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0x4f, 0xd3, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, 0x6d, 0x44, 0x48, + 0x26, 0x42, 0xdf, 0xee, 0xf5, 0x6c, 0x34, 0x1a, 0x3d, 0x4d, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x00, 0xcd, 0x29, 0x9c, + 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x35, 0x9c, 0xcd, 0xc7, 0xc3, 0xef, 0x47, 0x8b, 0x87, 0x87, + 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, 0xb1, 0xf5, 0x2d, + 0xfa, 0xe6, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x12, 0x80, 0x17, 0x67, 0x23, + 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, 0xc7, 0xd3, 0xf2, + 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x13, 0x44, 0x25, 0x3b, 0x7a, 0x32, 0x55, 0x70, 0xc7, + 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x7e, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, 0x72, 0x19, 0x83, + 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, 0x4c, 0x1e, 0x96, + 0x54, 0x7e, 0x33, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0xaa, 0x57, 0x6f, 0x53, 0x76, + 0x38, 0xff, 0x3f, 0x25, 0x5d, 0x0c, 0x0e, 0xdd, 0xd0, 0xbc, 0xd3, 0xee, 0xbc, 0x15, 0x32, 0x8e, 0x55, 0xf8, 0x36, + 0x25, 0xd6, 0x18, 0x97, 0xb3, 0x93, 0xad, 0xe9, 0xce, 0xa8, 0x2a, 0xb2, 0xab, 0x90, 0xe8, 0x5e, 0x39, 0x90, 0xd0, + 0x20, 0xca, 0x46, 0xb8, 0x7e, 0xc0, 0x7a, 0xc6, 0xeb, 0xe4, 0x35, 0x2f, 0xaa, 0x2c, 0x51, 0xef, 0xaf, 0x1b, 0xef, + 0xeb, 0xda, 0x04, 0x54, 0x7d, 0x57, 0x30, 0x98, 0xe7, 0xb7, 0x05, 0x80, 0x98, 0x22, 0x0d, 0xf0, 0x09, 0x66, 0x10, + 0xd4, 0xae, 0x99, 0x57, 0x8d, 0xe0, 0x1b, 0xf0, 0xd5, 0xbb, 0x02, 0x30, 0x48, 0x42, 0x90, 0x22, 0x43, 0x68, 0x20, + 0x10, 0x68, 0x18, 0x72, 0x81, 0xc1, 0x4f, 0xbc, 0x38, 0x92, 0xca, 0x29, 0x91, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0a, + 0x40, 0x62, 0x3c, 0x0e, 0xe1, 0x85, 0xfa, 0xe5, 0xde, 0xa8, 0x3d, 0xc2, 0x1e, 0xa4, 0x21, 0x04, 0x1b, 0xc2, 0x87, + 0x00, 0x96, 0x14, 0xa1, 0xef, 0x90, 0xcb, 0x08, 0x83, 0x8b, 0x3c, 0x5b, 0xe9, 0xa4, 0x6a, 0xd4, 0xd1, 0x7c, 0x28, + 0xb5, 0x23, 0x39, 0xa0, 0x5e, 0x7a, 0x8c, 0xe9, 0x85, 0x4a, 0x57, 0x45, 0x39, 0xa3, 0x9c, 0x53, 0x3d, 0x31, 0x2e, + 0x6c, 0x21, 0x87, 0x48, 0x38, 0xef, 0x0a, 0x15, 0x0a, 0x87, 0x2f, 0x00, 0x0c, 0x0c, 0xa4, 0x1d, 0xfb, 0xf1, 0x6e, + 0x54, 0xf6, 0x33, 0xce, 0x0e, 0xff, 0x6b, 0x1e, 0x0f, 0x3f, 0x8f, 0x87, 0xdf, 0x2f, 0x06, 0xe1, 0xd0, 0xfe, 0x24, + 0x0f, 0x1f, 0x1c, 0xd2, 0x17, 0xdc, 0x72, 0x69, 0xb0, 0xf0, 0x1b, 0xc1, 0x7e, 0xd4, 0x4a, 0x08, 0xa2, 0x00, 0x6f, + 0x58, 0x6e, 0x35, 0x4e, 0x00, 0xf0, 0x30, 0xf8, 0xdf, 0x01, 0x1a, 0x4d, 0xb9, 0x8b, 0x17, 0xe8, 0x4b, 0xd4, 0xef, + 0x93, 0x47, 0x0d, 0x83, 0x41, 0x10, 0xd7, 0xa8, 0x98, 0x30, 0x44, 0x97, 0x31, 0x51, 0x30, 0xc8, 0x36, 0xfb, 0x6e, + 0xd7, 0x6b, 0x4b, 0xc2, 0xf0, 0x4b, 0x3f, 0xd3, 0xc4, 0xcc, 0x3b, 0xdc, 0xd8, 0x56, 0x72, 0x15, 0x22, 0x56, 0xa0, + 0xfe, 0x95, 0x33, 0x88, 0xbd, 0x79, 0x9d, 0x81, 0x4f, 0x87, 0xfd, 0x62, 0x3c, 0x03, 0x36, 0x0a, 0xee, 0x7c, 0x05, + 0xbf, 0xc8, 0xc0, 0xcd, 0x5b, 0xc4, 0x28, 0x70, 0xb0, 0x4b, 0xa2, 0xdf, 0xef, 0xe5, 0x59, 0x98, 0x6b, 0xdc, 0xe9, + 0xbc, 0x36, 0x6a, 0x08, 0xd4, 0x91, 0x83, 0xfa, 0x41, 0x0f, 0xc1, 0x50, 0x0d, 0x41, 0xd1, 0xd1, 0x16, 0x57, 0xaf, + 0xad, 0xa7, 0x30, 0xbd, 0x55, 0xf5, 0x15, 0xa3, 0x3f, 0x65, 0x26, 0xb0, 0x90, 0x76, 0xcd, 0xb1, 0xae, 0x39, 0x46, + 0xda, 0xd3, 0xef, 0x8b, 0x06, 0xf9, 0xe9, 0x2c, 0x3c, 0x08, 0x54, 0xa9, 0x72, 0xaf, 0x2c, 0xca, 0x6d, 0x69, 0xde, + 0x18, 0xd6, 0x34, 0xcf, 0x6c, 0x9c, 0x9b, 0x59, 0xaf, 0x17, 0x86, 0xe8, 0xe0, 0x89, 0xa5, 0x62, 0x6d, 0x10, 0xee, + 0xc8, 0x24, 0x8c, 0xae, 0x40, 0x76, 0x19, 0x9e, 0x71, 0x82, 0x7c, 0x2a, 0xb0, 0x0f, 0xaa, 0x5a, 0x2f, 0x27, 0x3c, + 0x36, 0xf2, 0x65, 0x23, 0x68, 0x90, 0x97, 0x14, 0xf5, 0x26, 0x6e, 0xc7, 0x3e, 0x6f, 0x21, 0x57, 0x6e, 0xeb, 0x69, + 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, 0xcc, 0x70, + 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, 0x13, 0xf9, + 0xe6, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, 0xf5, 0xa2, + 0x84, 0x0a, 0xd8, 0x6e, 0x97, 0x82, 0xe0, 0xdf, 0x4f, 0xd9, 0x0c, 0xff, 0x66, 0xfd, 0x7e, 0x2f, 0xc4, 0x5f, 0x1c, + 0x83, 0x19, 0xcd, 0xc5, 0x82, 0x7d, 0x02, 0x19, 0x13, 0x89, 0x30, 0x55, 0x19, 0x03, 0xb2, 0x0a, 0x2c, 0x02, 0xcd, + 0x07, 0x2a, 0x17, 0x66, 0xb2, 0x97, 0x39, 0xd7, 0x90, 0x57, 0xad, 0x71, 0xca, 0x46, 0x59, 0xa2, 0x5c, 0x39, 0xb2, + 0x51, 0x9c, 0x67, 0x71, 0xc9, 0xcb, 0xdd, 0x4e, 0x1f, 0x8e, 0x49, 0xc1, 0x81, 0x5d, 0x57, 0x54, 0xaa, 0x64, 0x1d, + 0xa9, 0x1e, 0x78, 0x69, 0x58, 0xe0, 0x3e, 0xe5, 0xf3, 0xc2, 0xd0, 0x88, 0x03, 0x10, 0x66, 0x30, 0x75, 0x4b, 0xef, + 0x85, 0x05, 0x34, 0xaf, 0x24, 0x64, 0x8b, 0xa9, 0x9e, 0x85, 0x6f, 0xcc, 0xc4, 0xbc, 0x58, 0x40, 0x58, 0x9d, 0x62, + 0xa1, 0x99, 0x4d, 0x9a, 0xb0, 0x18, 0x60, 0xf3, 0x62, 0x32, 0x85, 0xf8, 0xee, 0xaa, 0x9c, 0x78, 0x61, 0xee, 0xdb, + 0x89, 0x43, 0x0e, 0x81, 0x57, 0xb5, 0x41, 0x57, 0xb3, 0x0d, 0x47, 0x1d, 0x29, 0x27, 0x26, 0xbf, 0x9f, 0x2a, 0x08, + 0x71, 0x27, 0x8e, 0x84, 0xcb, 0x9b, 0xed, 0xc2, 0xb3, 0x0e, 0x04, 0x1d, 0x35, 0x38, 0xe5, 0x17, 0x06, 0x47, 0x63, + 0x92, 0x6e, 0xbd, 0x13, 0xa4, 0x08, 0x63, 0xb2, 0x95, 0xec, 0x5c, 0x86, 0x62, 0x1e, 0x2f, 0x40, 0x79, 0x19, 0x2f, + 0xc0, 0xd2, 0xc8, 0x18, 0xa4, 0x82, 0xfc, 0x8e, 0x7b, 0xa1, 0xb0, 0x28, 0xae, 0x10, 0xe9, 0x59, 0xfd, 0x9e, 0x16, + 0xed, 0x50, 0x20, 0x28, 0xee, 0x50, 0xe6, 0xc9, 0x59, 0x8f, 0x05, 0x12, 0x1b, 0x02, 0xc6, 0x57, 0x3a, 0x4d, 0xb5, + 0xd6, 0xbd, 0x31, 0xf3, 0xc0, 0xa7, 0xd9, 0x48, 0xc8, 0xea, 0xec, 0x02, 0x44, 0x4a, 0x3e, 0x3a, 0x3e, 0xf2, 0x8b, + 0xb8, 0xb3, 0xcc, 0x5b, 0xdb, 0xa2, 0x92, 0x9d, 0x6c, 0x01, 0xb4, 0x50, 0x47, 0xcf, 0x52, 0x72, 0x9b, 0x92, 0xd4, + 0x6e, 0x53, 0xc0, 0x4a, 0xf2, 0x17, 0x30, 0x04, 0x5f, 0x3b, 0x10, 0x4e, 0xc7, 0x0a, 0xf1, 0x9a, 0xa6, 0x88, 0x34, + 0x19, 0x96, 0x14, 0xc7, 0xb6, 0x44, 0x14, 0x54, 0x5b, 0x96, 0x1d, 0x0c, 0x13, 0x25, 0xf8, 0x63, 0xea, 0x51, 0xa2, + 0x20, 0xa0, 0x7a, 0xc8, 0x41, 0x82, 0x6d, 0x1b, 0x08, 0x0f, 0xc8, 0x23, 0x7a, 0x63, 0xfd, 0x73, 0xd6, 0x79, 0x76, + 0xa1, 0x79, 0x2e, 0xd7, 0xbb, 0xc2, 0x8c, 0x11, 0x9e, 0x64, 0x26, 0x6c, 0x80, 0x77, 0x9e, 0x19, 0xb5, 0x4d, 0xcf, + 0xc3, 0x6b, 0x7b, 0x8e, 0x11, 0xfa, 0xee, 0x18, 0x74, 0x13, 0xcc, 0xab, 0xc3, 0x66, 0xbd, 0x52, 0x90, 0x1a, 0xa6, + 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0xa0, 0x7c, 0xb7, 0xeb, 0xe9, 0xb9, 0xba, 0x7b, 0xee, 0x76, 0xbb, 0x1e, 0x76, 0xeb, + 0x63, 0xda, 0x6d, 0x15, 0x5f, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, 0x6c, 0x52, 0x3a, 0x9a, 0x69, + 0xeb, 0x83, 0xf0, 0xc0, 0xe9, 0xa6, 0xd1, 0xa4, 0x9f, 0xb3, 0x50, 0xd2, 0x4b, 0xd1, 0xa8, 0xae, 0x76, 0x26, 0xa6, + 0xf7, 0xae, 0xff, 0xfb, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xd9, 0xa0, 0xa2, 0xd1, 0x16, 0x8e, 0x14, 0xa1, + 0x07, 0x24, 0xe1, 0xae, 0x96, 0xb5, 0xb8, 0xcd, 0x0f, 0xd9, 0xfd, 0xf4, 0xe9, 0xa7, 0xd4, 0xf7, 0x42, 0x70, 0xcb, + 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, 0xbd, 0xf2, + 0x03, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0xfd, 0x90, 0xcd, 0xb3, 0xc5, 0x6e, 0x17, 0xe2, 0xdf, 0xae, 0x16, + 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0xff, 0x2c, 0x1a, 0x4e, 0x13, 0xcf, + 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, 0xc0, 0x15, + 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x7b, 0x4b, 0xdb, 0xaa, 0x62, 0xe3, 0x2d, + 0x69, 0x8e, 0xeb, 0xc0, 0xf9, 0x3a, 0xd8, 0x80, 0x77, 0xba, 0xec, 0x6a, 0x81, 0xdc, 0x2f, 0xaf, 0x69, 0x6f, 0x5c, + 0x27, 0x30, 0x6b, 0xdb, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x17, 0x7a, 0x70, 0x95, 0x31, 0xd8, 0xdc, 0x58, 0x69, 0xd8, + 0x7d, 0xe3, 0xf9, 0x52, 0x40, 0x78, 0x3a, 0x9f, 0x1e, 0x7f, 0xc8, 0x3c, 0x7a, 0x0c, 0x44, 0xc7, 0x7c, 0x54, 0xba, + 0x8f, 0xec, 0xee, 0xf5, 0x03, 0x02, 0xce, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x55, 0xbd, 0xf2, 0x0a, 0xcb, + 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0x20, 0x70, 0x77, 0xd7, 0xb9, 0x10, 0xab, 0x0e, 0x2b, 0x73, 0x9a, 0x84, + 0x9d, 0x84, 0x68, 0xde, 0x1a, 0xcc, 0x82, 0xff, 0x1d, 0x0c, 0xca, 0x41, 0x10, 0x05, 0x51, 0x10, 0x90, 0x41, 0x01, + 0xbf, 0x10, 0x77, 0x8d, 0x60, 0xcc, 0x16, 0xe8, 0xf0, 0x5b, 0xce, 0x7c, 0x46, 0xe4, 0x95, 0x1f, 0xd6, 0xd3, 0x1b, + 0x80, 0x73, 0x29, 0x73, 0x1e, 0xa3, 0xcf, 0xc9, 0x5b, 0xce, 0x32, 0x42, 0xdf, 0x7a, 0xa7, 0xf2, 0x3b, 0xde, 0x08, + 0xf6, 0xb7, 0x3f, 0x6c, 0x2f, 0x40, 0x5e, 0xd1, 0x1b, 0xd3, 0xb7, 0x9c, 0x44, 0x59, 0xc3, 0x99, 0x9a, 0x43, 0xcf, + 0x2a, 0xcb, 0x5a, 0x51, 0x43, 0x6e, 0x50, 0xcc, 0x8d, 0x2c, 0x93, 0x93, 0x69, 0xab, 0x39, 0x15, 0xb8, 0xee, 0xec, + 0x7a, 0x01, 0xc9, 0xa1, 0xd0, 0x2c, 0x9d, 0x0d, 0xe7, 0xed, 0x0e, 0xc5, 0xd6, 0x29, 0xe4, 0x35, 0x44, 0x45, 0x83, + 0x74, 0x04, 0xd4, 0xd0, 0x8a, 0xcb, 0x0a, 0x5c, 0x98, 0x4d, 0x7b, 0xb8, 0x69, 0x8f, 0x69, 0xc6, 0x7b, 0x88, 0x99, + 0xc7, 0xb1, 0x65, 0x60, 0x47, 0xe2, 0x90, 0x9e, 0x9c, 0x2f, 0xd0, 0x3e, 0xbd, 0x75, 0xb5, 0x78, 0x84, 0xb5, 0xe7, + 0xad, 0x90, 0x10, 0x20, 0x3e, 0x4d, 0xa5, 0xbb, 0x5d, 0x10, 0xc0, 0x00, 0xf7, 0xfb, 0x3d, 0xe0, 0x5a, 0x0d, 0x3b, + 0x69, 0x6e, 0xcd, 0x96, 0xd8, 0x2b, 0x0a, 0x8f, 0x81, 0x39, 0x35, 0xff, 0x19, 0x04, 0x14, 0xcf, 0xdd, 0x10, 0xec, + 0x4d, 0xd9, 0xc9, 0xb6, 0xe8, 0xf7, 0x9f, 0x15, 0xf8, 0x80, 0x72, 0x61, 0x10, 0x73, 0xeb, 0x38, 0x1e, 0x86, 0x7d, + 0x52, 0x1f, 0xe2, 0x58, 0xe4, 0x59, 0xe8, 0x08, 0x4b, 0x65, 0x08, 0x0b, 0x57, 0x8c, 0x74, 0x10, 0x07, 0x35, 0xe9, + 0x1c, 0xac, 0xca, 0x05, 0x5f, 0xee, 0xf5, 0x3e, 0x03, 0x4c, 0x7a, 0xe6, 0x0d, 0xcb, 0x1b, 0x0f, 0x10, 0xad, 0xd7, + 0xc3, 0x85, 0xe2, 0x91, 0x89, 0x06, 0x1a, 0x27, 0xbe, 0xb4, 0xec, 0xfa, 0x4c, 0xcb, 0x4a, 0x46, 0xa3, 0x51, 0x55, + 0x2b, 0xc9, 0x87, 0xfd, 0xee, 0xcf, 0x16, 0x8a, 0xa7, 0x8c, 0x53, 0x9e, 0x82, 0xe5, 0xbb, 0xa1, 0x74, 0xf3, 0x05, + 0x5d, 0x71, 0x91, 0xaa, 0x9f, 0x1e, 0xfa, 0x66, 0x83, 0xb8, 0x66, 0x4d, 0x1d, 0x8e, 0x1d, 0x7e, 0x08, 0x80, 0x69, + 0x1f, 0x66, 0x2e, 0x5d, 0xc3, 0xf4, 0x82, 0x78, 0x36, 0x2e, 0x78, 0xe8, 0xf2, 0x00, 0xf6, 0xa1, 0x39, 0x24, 0xf1, + 0x53, 0xf8, 0x39, 0x33, 0x69, 0x1d, 0x9f, 0xe1, 0x6c, 0x46, 0xa5, 0xba, 0x11, 0xb4, 0x5f, 0x43, 0x22, 0x31, 0x48, + 0xcf, 0x0d, 0x86, 0xa2, 0x75, 0xb7, 0x81, 0x2b, 0xbf, 0xa5, 0x77, 0x3e, 0x0d, 0x02, 0xac, 0x6f, 0x2c, 0x06, 0x00, + 0x54, 0xf1, 0x07, 0xaa, 0xae, 0xcc, 0x15, 0xc5, 0x34, 0x4c, 0x25, 0xda, 0x3b, 0x8e, 0xeb, 0xa8, 0x71, 0x1d, 0x16, + 0xac, 0xb4, 0xb6, 0xcd, 0xee, 0x2d, 0x2d, 0x6c, 0x09, 0xa8, 0x16, 0xc4, 0x9d, 0x00, 0x3e, 0x34, 0x52, 0x1d, 0x08, + 0xb2, 0xfb, 0xe0, 0x00, 0x80, 0x37, 0x3c, 0x0f, 0x43, 0xf8, 0x03, 0x0b, 0x07, 0x96, 0xa5, 0xea, 0xe7, 0x72, 0x1a, + 0xc3, 0xb9, 0x9b, 0xab, 0x1d, 0x3e, 0x5b, 0x82, 0x62, 0x53, 0xcd, 0xa9, 0xb9, 0x7c, 0xe5, 0x8d, 0xfd, 0x1e, 0x13, + 0xcc, 0x63, 0x66, 0x1b, 0x7e, 0xeb, 0xe9, 0xb6, 0xbe, 0xc1, 0x6e, 0xe0, 0xa4, 0xbd, 0x70, 0xda, 0x8b, 0xed, 0xd2, + 0x40, 0xfe, 0xd5, 0x0d, 0x21, 0xc2, 0x47, 0x4d, 0x2c, 0xb2, 0x86, 0x4c, 0xc7, 0x62, 0x85, 0xa8, 0x36, 0x15, 0x4f, + 0xb5, 0x81, 0x40, 0x39, 0x55, 0x17, 0xa6, 0x56, 0x2a, 0x13, 0x06, 0x71, 0xa7, 0x84, 0x45, 0x95, 0x01, 0x86, 0x41, + 0x85, 0x14, 0xd7, 0xd6, 0xf3, 0x03, 0x2e, 0xdf, 0xcc, 0xb4, 0xd9, 0x7e, 0xfa, 0x22, 0x8f, 0x2f, 0x77, 0xbb, 0xb0, + 0xfb, 0x05, 0x98, 0xa3, 0x96, 0x4a, 0xc3, 0x08, 0x4e, 0x20, 0x4a, 0x72, 0x7d, 0x47, 0xce, 0x89, 0xe3, 0xe4, 0xda, + 0xcd, 0x9b, 0xed, 0xa5, 0x18, 0x81, 0x05, 0x9c, 0xb8, 0x48, 0x07, 0x5a, 0x2a, 0x49, 0xed, 0x29, 0xe0, 0x6d, 0x7a, + 0x47, 0xa9, 0xf0, 0x6a, 0xa1, 0x49, 0x48, 0xe5, 0xee, 0x25, 0x76, 0xd4, 0x80, 0x73, 0x52, 0x77, 0x10, 0x70, 0xda, + 0xd3, 0x8d, 0xb5, 0x8a, 0x64, 0x93, 0xe0, 0xbd, 0xd2, 0x43, 0x97, 0x68, 0xa7, 0x76, 0xb7, 0xad, 0xca, 0x16, 0x0a, + 0xe6, 0x41, 0xce, 0x12, 0x75, 0x3c, 0xa0, 0xd0, 0x45, 0x1d, 0x0d, 0xf9, 0x82, 0x14, 0x7a, 0xe5, 0x68, 0x55, 0xf3, + 0xbe, 0x64, 0xa0, 0x54, 0xab, 0x20, 0xaf, 0x89, 0x75, 0x5f, 0xcb, 0x1a, 0x8b, 0x2b, 0x27, 0xa4, 0xb0, 0x09, 0x5f, + 0x5b, 0x8a, 0x85, 0x59, 0xec, 0x8d, 0xa9, 0x2f, 0x5c, 0x22, 0xb4, 0xdd, 0x6d, 0x88, 0xd1, 0x06, 0xeb, 0x66, 0xb7, + 0xfb, 0x58, 0x84, 0xf3, 0x6c, 0x41, 0xe5, 0x28, 0x4b, 0x11, 0x52, 0xcd, 0x78, 0x2c, 0xdb, 0x2e, 0x98, 0x89, 0xa1, + 0xae, 0x3d, 0x5e, 0x92, 0x29, 0xd6, 0x26, 0xc9, 0x51, 0x7c, 0x2e, 0x0b, 0xb5, 0xd6, 0x08, 0xc1, 0xc3, 0xfd, 0xd7, + 0x14, 0x62, 0xda, 0x99, 0x75, 0xf7, 0x72, 0xef, 0x86, 0xf8, 0x2b, 0x04, 0x56, 0x28, 0xd9, 0xc7, 0x62, 0x74, 0x9e, + 0x41, 0x30, 0x58, 0x90, 0x35, 0x63, 0x94, 0x60, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, 0x4b, 0x14, 0x20, 0xce, + 0xb3, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x67, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x4a, 0xbc, 0xcf, 0xd3, 0x98, 0x1e, + 0xba, 0x35, 0x08, 0xae, 0xab, 0x7b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, 0x6a, 0x4e, 0xad, 0x2b, + 0x71, 0x3f, 0xab, 0xbc, 0xd1, 0x07, 0xf1, 0x95, 0x00, 0x1e, 0xd6, 0xdb, 0xde, 0xe7, 0xc2, 0x63, 0x6d, 0xf0, 0xed, + 0x6e, 0x77, 0x25, 0xe6, 0x41, 0xe0, 0x31, 0x9a, 0xbf, 0x28, 0x89, 0x79, 0x6f, 0x4c, 0x61, 0xc5, 0xfb, 0x2e, 0x7e, + 0xdd, 0xa4, 0xd6, 0x5a, 0xe4, 0xee, 0x71, 0x7d, 0xc0, 0xf3, 0x94, 0x38, 0xda, 0x51, 0x39, 0x95, 0xd6, 0x76, 0x00, + 0xbb, 0x22, 0x30, 0x50, 0xf6, 0x6f, 0x29, 0xdb, 0x82, 0x79, 0x22, 0x58, 0x1f, 0xa1, 0xdf, 0x96, 0xd2, 0x9f, 0x8c, + 0xd1, 0xb8, 0x47, 0xae, 0xab, 0xe8, 0x88, 0xeb, 0x68, 0xf6, 0x3c, 0xfa, 0xdb, 0x93, 0x31, 0x2d, 0x62, 0x91, 0xca, + 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x1d, 0x21, 0x34, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, 0x7f, 0x77, 0x3a, 0x51, + 0xda, 0x9a, 0x7c, 0x8c, 0x56, 0x55, 0xe4, 0xac, 0x0d, 0xed, 0xa6, 0x92, 0x43, 0xf2, 0xb0, 0x04, 0x7c, 0x4b, 0x6c, + 0x96, 0xb2, 0x41, 0x51, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, 0xb5, 0xdd, 0xc8, 0x7c, + 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x1e, 0x94, 0x9c, 0xad, 0xcf, 0xe4, 0x26, 0x40, 0x1c, 0x60, + 0xb8, 0x6e, 0xe7, 0x37, 0x0b, 0x42, 0x6f, 0xd9, 0xad, 0x15, 0xab, 0xde, 0x58, 0xb9, 0x88, 0x49, 0xbb, 0x19, 0x4c, + 0xe0, 0x32, 0xce, 0x0a, 0xfb, 0x42, 0xab, 0x1b, 0x8a, 0x8e, 0xb6, 0x49, 0xfb, 0x79, 0x47, 0xbb, 0xe1, 0x82, 0x6f, + 0xc5, 0x3a, 0xce, 0x2d, 0x6b, 0xaa, 0xd0, 0xb4, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, 0x5d, 0xd2, 0x14, 0x2f, + 0xd0, 0x74, 0x0d, 0x66, 0x3a, 0x17, 0xd0, 0xd7, 0x6e, 0x1f, 0xed, 0x0b, 0xd5, 0x13, 0xe1, 0x2d, 0x51, 0xf0, 0x6d, + 0x49, 0xc1, 0x4b, 0x2d, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0xa7, 0x51, 0x25, 0x7a, 0x27, 0xc5, 0x25, 0x68, 0x33, 0xe1, + 0x08, 0x34, 0x55, 0x23, 0xb6, 0x72, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, 0xdb, 0x15, 0x79, 0xcb, + 0x4e, 0xb6, 0xb7, 0x60, 0x26, 0x5c, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, 0x6c, 0xbb, 0x87, 0x1a, + 0x1b, 0xde, 0xd2, 0x1b, 0xb2, 0xbd, 0xe9, 0xf7, 0x43, 0xe8, 0x0f, 0xa1, 0xba, 0x43, 0xb7, 0x9d, 0x1d, 0xba, 0xf5, + 0xda, 0x79, 0x6e, 0xf5, 0x7c, 0xca, 0x3b, 0xe4, 0x23, 0x9a, 0xac, 0xd1, 0x55, 0xbc, 0x81, 0x4d, 0x1d, 0x55, 0x54, + 0x55, 0x1e, 0x25, 0x14, 0x54, 0xe2, 0x19, 0x2f, 0x3f, 0x70, 0x8c, 0xf5, 0xaa, 0x9f, 0xde, 0x69, 0x5e, 0x6d, 0x6d, + 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x0b, 0x89, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x83, 0xaa, 0xe2, 0xa8, 0x04, + 0x17, 0x71, 0x96, 0x83, 0x1a, 0xf7, 0xa2, 0xd9, 0xff, 0x50, 0xdb, 0x8e, 0x2d, 0x1b, 0x67, 0xee, 0x75, 0x48, 0xb6, + 0xff, 0x63, 0x03, 0xf5, 0x34, 0xc4, 0x08, 0xb1, 0x66, 0x41, 0x3f, 0x60, 0x10, 0x2b, 0x34, 0x28, 0xd7, 0x49, 0xc2, + 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x1d, 0x3b, 0x79, 0xd7, 0x63, 0xec, 0x96, 0xd0, 0x44, + 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x01, 0x0a, 0x59, 0xda, 0xfb, 0xdc, + 0x9c, 0xc8, 0xea, 0x1b, 0x6d, 0x84, 0x12, 0xa9, 0x44, 0x90, 0x8d, 0xdf, 0x20, 0x80, 0x31, 0x34, 0x3b, 0x20, 0xdb, + 0x25, 0x7b, 0x4d, 0xcf, 0xac, 0x49, 0x10, 0xbc, 0x7e, 0xa0, 0x12, 0xcd, 0x28, 0x2b, 0xa2, 0xab, 0x8c, 0x7e, 0x36, + 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, 0x6a, 0x6c, + 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, 0xbc, 0xa5, + 0xe0, 0x2f, 0xf6, 0x8e, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb1, 0x93, 0xed, 0xbb, + 0xf0, 0x75, 0x63, 0xe6, 0x36, 0x21, 0x5e, 0xaa, 0x92, 0x9e, 0x37, 0x4f, 0x66, 0x20, 0x56, 0x56, 0x6b, 0x7e, 0xcb, + 0xac, 0x3e, 0x01, 0x88, 0xd4, 0xad, 0x75, 0xb0, 0xc5, 0x8f, 0x4d, 0x97, 0xc9, 0x36, 0x65, 0x6d, 0x26, 0x4a, 0xa9, + 0x48, 0x9a, 0x8b, 0x00, 0xfa, 0x0d, 0xc3, 0x51, 0x03, 0xdc, 0xb9, 0x1e, 0x7b, 0x33, 0x34, 0xde, 0x98, 0x1a, 0x7a, + 0xb6, 0xd5, 0xcb, 0xdb, 0x51, 0x08, 0x33, 0x16, 0xd1, 0xad, 0x3b, 0x16, 0xc3, 0xd7, 0xf4, 0x01, 0x54, 0xf8, 0x34, + 0xc4, 0xe8, 0xc2, 0xa4, 0xae, 0xa7, 0x6b, 0xb5, 0x95, 0x6e, 0x08, 0xcd, 0x31, 0xaa, 0x91, 0xd7, 0xb6, 0x0d, 0x35, + 0x42, 0x7b, 0x42, 0x79, 0x78, 0x4b, 0x2b, 0x7a, 0x63, 0x59, 0x04, 0x27, 0x3f, 0xf6, 0xf2, 0x13, 0x7a, 0xee, 0x06, + 0xed, 0xa7, 0xa2, 0xad, 0x01, 0xfc, 0x0d, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, 0xe1, 0x4b, 0xb6, 0x20, + 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0xf6, 0x76, 0x87, 0x37, 0x29, 0x65, 0x88, 0xd6, 0x88, 0x0e, + 0xf2, 0xea, 0xdf, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, 0xdf, 0xcf, 0xf1, 0xb9, + 0xf6, 0x2c, 0xd3, 0x94, 0x05, 0x32, 0xa1, 0x4b, 0x57, 0x1a, 0x88, 0xca, 0xb7, 0x8e, 0x55, 0x00, 0x56, 0x24, 0x81, + 0x46, 0x24, 0x60, 0xb9, 0xe4, 0x89, 0xcb, 0xb6, 0x68, 0x50, 0x13, 0x95, 0x14, 0xb2, 0x44, 0x12, 0xf8, 0x61, 0x04, + 0x65, 0x8a, 0x62, 0x10, 0xf7, 0xea, 0xe5, 0x15, 0xd7, 0xd4, 0x80, 0x35, 0x45, 0x30, 0xc1, 0x3a, 0x9d, 0x02, 0xb1, + 0x15, 0xeb, 0x15, 0x78, 0xa2, 0xba, 0x8b, 0x24, 0xb2, 0x04, 0x68, 0xa0, 0xe7, 0x4b, 0xa7, 0xdd, 0xf2, 0xf6, 0x44, + 0x4b, 0x15, 0x9b, 0x7b, 0x2f, 0x16, 0x96, 0x7b, 0xac, 0xfc, 0xed, 0x40, 0x7b, 0x61, 0xb5, 0x27, 0xa2, 0x06, 0xab, + 0xc3, 0xb6, 0x9d, 0x1f, 0x4a, 0x43, 0x75, 0xaf, 0x1c, 0x13, 0x50, 0xd1, 0x55, 0x5c, 0x2d, 0xa3, 0x6c, 0x04, 0x7f, + 0x76, 0xbb, 0xe0, 0x30, 0x00, 0x8b, 0xd0, 0x5f, 0xde, 0xff, 0x14, 0x61, 0xb8, 0xaa, 0x5f, 0xde, 0xff, 0xb4, 0xdb, + 0x3d, 0x19, 0x8f, 0x0d, 0x57, 0xe0, 0xd4, 0x3a, 0xc0, 0x1f, 0x18, 0xb6, 0xc1, 0x2e, 0xd9, 0xdd, 0xee, 0x09, 0x70, + 0x10, 0x8a, 0x6d, 0x30, 0xbb, 0x58, 0x39, 0xb6, 0x29, 0x56, 0x43, 0xef, 0x48, 0xc0, 0xee, 0xdb, 0x63, 0x29, 0xf6, + 0xa9, 0x8f, 0x0a, 0x49, 0xa9, 0x17, 0xfd, 0xf3, 0x4e, 0x81, 0x25, 0x05, 0x53, 0xde, 0x60, 0x59, 0x55, 0xab, 0x32, + 0x3a, 0x3c, 0x8c, 0x57, 0xd9, 0xa8, 0xcc, 0x60, 0x9b, 0x97, 0xd7, 0x97, 0x00, 0x30, 0x11, 0xd0, 0xc6, 0xbb, 0xb5, + 0xc8, 0xcc, 0x8b, 0x05, 0x5d, 0x66, 0xb8, 0x26, 0xc1, 0xec, 0x20, 0xe7, 0x56, 0x37, 0x39, 0x25, 0xf6, 0x01, 0x6c, + 0x30, 0x77, 0xbb, 0x06, 0xbf, 0x70, 0x32, 0x7a, 0x32, 0x5b, 0x66, 0xda, 0xc0, 0x95, 0x9b, 0xfd, 0x4f, 0x22, 0x2f, + 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x3c, 0x03, 0x3e, 0x8f, 0xfd, 0x29, 0x42, 0x9f, 0xe5, 0x6a, 0xb4, 0x06, 0xd8, 0xd8, + 0xec, 0x62, 0x33, 0x4a, 0x39, 0x44, 0xe8, 0x08, 0xac, 0xba, 0x66, 0x99, 0x11, 0xdf, 0xa6, 0xe2, 0xb6, 0xa5, 0x0a, + 0xfb, 0x53, 0x78, 0xce, 0x3b, 0xdc, 0x38, 0x0e, 0xf5, 0x26, 0x51, 0xf8, 0x1c, 0x85, 0xa8, 0x1c, 0x8d, 0x0b, 0x9d, + 0x7c, 0x2d, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x95, 0x3a, 0x73, 0x19, 0x5f, 0xb8, 0xf7, 0xdc, 0x97, 0x99, + 0x5c, 0x4b, 0x00, 0x89, 0x52, 0xb5, 0xff, 0xfe, 0x05, 0xa9, 0xf1, 0xbf, 0x52, 0xad, 0x01, 0xe8, 0xfd, 0x0e, 0x35, + 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0xd1, 0x05, 0xac, 0x64, 0xfe, 0x27, 0xd4, 0xed, 0x08, 0xb6, 0x55, 0xf1, 0x84, + 0xa2, 0x8a, 0x16, 0x3c, 0x5d, 0x8b, 0x34, 0x16, 0xc9, 0x26, 0xe2, 0xf5, 0x14, 0x4b, 0x62, 0x36, 0x62, 0xd8, 0xef, + 0xcd, 0x2e, 0xbc, 0x2f, 0x1a, 0x26, 0xf1, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, 0x8c, 0x4c, 0xb9, 0x42, + 0x30, 0xb7, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3e, 0x7a, 0x4c, 0xe8, 0xb5, 0x9c, 0x96, 0x08, 0xd2, 0x27, 0x52, 0xeb, + 0xba, 0x8a, 0xfd, 0x9a, 0x42, 0x54, 0x0b, 0xc1, 0x20, 0x94, 0xa9, 0x69, 0x9f, 0xe2, 0xfb, 0x6c, 0xd9, 0x7f, 0x9a, + 0xb2, 0x25, 0xd9, 0x0a, 0xe8, 0x98, 0x74, 0xde, 0xaf, 0xde, 0x9e, 0x9d, 0x79, 0xbf, 0x41, 0x13, 0x0e, 0xaa, 0x1b, + 0x68, 0x57, 0x41, 0xa6, 0x31, 0x8a, 0xcd, 0x62, 0xac, 0xdd, 0x9a, 0x88, 0x20, 0x08, 0x77, 0x39, 0x0b, 0xdb, 0xed, + 0x84, 0x78, 0x1b, 0x48, 0xa0, 0xc0, 0xb5, 0x8d, 0x72, 0x12, 0x12, 0x75, 0x21, 0x33, 0xc7, 0x84, 0x64, 0x81, 0x5e, + 0x63, 0x47, 0x01, 0x3d, 0xe5, 0xf6, 0x29, 0xa0, 0x2f, 0x0a, 0x76, 0xca, 0x07, 0xc1, 0x10, 0xe3, 0xcd, 0x06, 0xf4, + 0x93, 0x54, 0x8f, 0xe0, 0x31, 0x0d, 0x2c, 0x17, 0x7d, 0x53, 0x30, 0x84, 0x59, 0xfa, 0x67, 0xca, 0x26, 0xdf, 0xfd, + 0xdd, 0xcd, 0xef, 0x99, 0x16, 0xb3, 0x83, 0x50, 0xdc, 0x5e, 0x4f, 0x80, 0xf8, 0x55, 0xfc, 0x0a, 0xac, 0xcd, 0xb5, + 0xc4, 0xdb, 0x93, 0x3c, 0x08, 0x5f, 0x8e, 0x6e, 0x3f, 0x29, 0xcd, 0x27, 0x10, 0xb4, 0xc7, 0x49, 0xca, 0xdd, 0x77, + 0x1f, 0xa4, 0xab, 0x08, 0x46, 0x0b, 0x10, 0xfc, 0xee, 0xac, 0x64, 0xd3, 0x14, 0xfe, 0x63, 0x9d, 0x2f, 0x30, 0x96, + 0x8a, 0xfc, 0x80, 0xd3, 0xdf, 0x04, 0x07, 0xf7, 0x6f, 0x65, 0xd6, 0x90, 0xe8, 0x4c, 0x7d, 0x04, 0xf4, 0x7f, 0xac, + 0xc7, 0xef, 0x14, 0x25, 0x7d, 0x49, 0x9c, 0x23, 0x7c, 0x13, 0x2f, 0xd1, 0x74, 0xb1, 0x37, 0xae, 0xe9, 0xe7, 0xc2, + 0xbc, 0xd0, 0x0a, 0x0e, 0xfb, 0xd6, 0x28, 0x3c, 0xf0, 0xcc, 0xfb, 0x55, 0x34, 0x04, 0xdd, 0x3f, 0xe2, 0xde, 0xf8, + 0x55, 0xb0, 0x0c, 0x6f, 0xca, 0x59, 0x66, 0xee, 0x70, 0x37, 0x99, 0x48, 0xe5, 0x0d, 0x63, 0xc1, 0x5a, 0x28, 0x73, + 0xde, 0x34, 0x98, 0x6d, 0xeb, 0x48, 0x25, 0xbb, 0xef, 0xff, 0x6c, 0x9c, 0xb0, 0xd9, 0x20, 0xf8, 0x50, 0xc9, 0x22, + 0xbe, 0xe4, 0xc1, 0x54, 0xab, 0x28, 0x32, 0xb0, 0x2b, 0x04, 0xa4, 0x1c, 0xa7, 0xbd, 0x83, 0x27, 0x4b, 0xcd, 0x4c, + 0xc8, 0x6f, 0xab, 0xb3, 0x80, 0xb7, 0x66, 0x34, 0x4f, 0x2b, 0xd8, 0x65, 0xbe, 0x92, 0xe2, 0x87, 0x96, 0x24, 0x1b, + 0xeb, 0x6f, 0xc8, 0xb0, 0xad, 0x7c, 0xe6, 0x0c, 0x30, 0x77, 0x3e, 0x49, 0x15, 0xf4, 0xaf, 0xc7, 0xd8, 0x8d, 0x44, + 0x22, 0x20, 0x9c, 0xc5, 0xc4, 0xad, 0x30, 0xe1, 0x30, 0x5d, 0xa0, 0xa0, 0x18, 0x03, 0x05, 0x7d, 0x90, 0x21, 0xa7, + 0xa7, 0x7c, 0x90, 0x34, 0x66, 0xeb, 0x07, 0x55, 0x22, 0xbd, 0x91, 0x84, 0x6e, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, + 0x82, 0x75, 0xba, 0x9b, 0xd3, 0xe1, 0x9b, 0x82, 0x0c, 0xff, 0x09, 0xde, 0x6e, 0xb1, 0xbd, 0x2c, 0x27, 0xb0, 0xb8, + 0x63, 0xaf, 0x78, 0x9a, 0xab, 0x16, 0x27, 0xc4, 0x23, 0x16, 0xb9, 0x4f, 0x2c, 0x60, 0x44, 0x0d, 0xa3, 0xf1, 0x8f, + 0x0f, 0x6f, 0xdf, 0x68, 0x0c, 0xab, 0xdc, 0xff, 0x00, 0x46, 0x54, 0x4b, 0xdb, 0xed, 0x80, 0x2f, 0x47, 0x68, 0xc0, + 0x9e, 0xba, 0xc1, 0xee, 0xf7, 0x4d, 0xda, 0x49, 0xe9, 0x65, 0x73, 0x62, 0xd0, 0x3d, 0xa5, 0xcd, 0x52, 0x19, 0x18, + 0x77, 0x15, 0x8e, 0xe6, 0xc4, 0x46, 0xac, 0xea, 0x7d, 0x18, 0x2e, 0x69, 0x6c, 0x65, 0xe5, 0x76, 0x37, 0xe1, 0xc8, + 0x26, 0xc0, 0xf5, 0x29, 0x68, 0xaf, 0xe6, 0x1c, 0xb4, 0xa0, 0x44, 0x81, 0x23, 0xda, 0xed, 0x42, 0x88, 0x48, 0x52, + 0x0c, 0x27, 0xb3, 0xb0, 0x18, 0x0e, 0xd5, 0xc0, 0x17, 0x84, 0x44, 0x9f, 0x8b, 0x79, 0xb6, 0x50, 0x08, 0x46, 0xfe, + 0x4e, 0xfa, 0xb5, 0x50, 0x9c, 0x72, 0xef, 0x57, 0x41, 0xb6, 0x3f, 0xa6, 0x18, 0x83, 0xd1, 0x69, 0x36, 0x33, 0x90, + 0xb0, 0x9e, 0x56, 0x44, 0xad, 0x23, 0x3b, 0x1b, 0xa0, 0x8a, 0x45, 0xd3, 0x60, 0x50, 0xb7, 0x78, 0x62, 0x3d, 0xa3, + 0xf7, 0xa0, 0x12, 0x44, 0xb5, 0x60, 0x37, 0x86, 0x6b, 0xed, 0xb3, 0x08, 0x25, 0xe5, 0xa4, 0xc9, 0xcc, 0x58, 0xd1, + 0x60, 0x01, 0x42, 0xd2, 0xb8, 0xac, 0x5e, 0xcb, 0x34, 0xbb, 0xc8, 0x00, 0x41, 0xc2, 0xf9, 0x13, 0xca, 0xc6, 0x9b, + 0xa7, 0x6a, 0x5e, 0xba, 0x12, 0x67, 0x16, 0xf6, 0xa4, 0xeb, 0x2d, 0x2d, 0x48, 0x54, 0x00, 0x8d, 0xf2, 0xb5, 0x3c, + 0x3f, 0xef, 0x59, 0x85, 0xec, 0x7f, 0x38, 0x55, 0xb6, 0x43, 0xfc, 0x84, 0x55, 0xc4, 0x3b, 0xad, 0x2b, 0x25, 0xd2, + 0xe8, 0x68, 0x1b, 0x10, 0xc3, 0x96, 0x7d, 0x8b, 0x1a, 0x3e, 0x08, 0xbb, 0xe8, 0x24, 0x3f, 0xe8, 0x29, 0x1e, 0x5b, + 0x03, 0x49, 0x5f, 0x8b, 0xe0, 0x6b, 0x74, 0xa4, 0x13, 0x65, 0x1a, 0x89, 0x29, 0x24, 0xfa, 0xf5, 0x42, 0x6b, 0x2c, + 0xa3, 0xec, 0x2b, 0xf2, 0x7f, 0xd7, 0xdd, 0xfb, 0x55, 0xec, 0x76, 0x30, 0xc9, 0x9e, 0x07, 0x1a, 0x6c, 0x6a, 0xd4, + 0x0a, 0xe1, 0xec, 0x9c, 0x56, 0xa8, 0x1d, 0xeb, 0x85, 0x25, 0x90, 0x07, 0xb0, 0x15, 0x69, 0x50, 0x06, 0xc9, 0x3e, + 0x17, 0x73, 0xb1, 0x70, 0xa2, 0x1c, 0xa9, 0xf0, 0xcf, 0xe4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x0b, 0x86, 0xfc, 0xea, + 0xe8, 0xa2, 0x90, 0x57, 0x20, 0x29, 0x31, 0x0c, 0x95, 0xe5, 0x75, 0x71, 0xd5, 0x96, 0x84, 0xf6, 0x36, 0x00, 0x4a, + 0x53, 0x80, 0xe0, 0xa5, 0x51, 0x43, 0xcc, 0xb6, 0x6a, 0x77, 0x45, 0x77, 0x92, 0x03, 0xea, 0x74, 0xd7, 0x6e, 0xbd, + 0x29, 0x5b, 0x75, 0x2b, 0x2e, 0xfc, 0x01, 0x4a, 0x3f, 0xe5, 0x83, 0xc2, 0xa7, 0x12, 0xb8, 0xf1, 0xd5, 0x26, 0xcb, + 0x2e, 0x36, 0xb8, 0xf4, 0xab, 0xc6, 0xf8, 0xf5, 0xfb, 0x3d, 0xb5, 0x10, 0x1a, 0xa9, 0xc0, 0x7c, 0xfb, 0xcc, 0x54, + 0x65, 0x34, 0xa5, 0xf6, 0x12, 0x5c, 0x39, 0xfb, 0x11, 0x54, 0xc4, 0x75, 0x45, 0x6a, 0x53, 0x03, 0x74, 0xe0, 0x65, + 0x85, 0x5b, 0x59, 0x80, 0xc7, 0x4e, 0x40, 0x76, 0x3b, 0x1e, 0x06, 0xfa, 0xd0, 0x09, 0xfc, 0x2d, 0xf9, 0x1a, 0x99, + 0x35, 0xfb, 0xf8, 0x0f, 0x2d, 0xf8, 0xc7, 0x16, 0xfc, 0x84, 0xe2, 0x4e, 0x2b, 0xf3, 0x6f, 0xa5, 0x75, 0x8b, 0xfb, + 0xf7, 0x32, 0x4d, 0x28, 0x2a, 0x13, 0x6a, 0xbf, 0xd2, 0x6a, 0x6d, 0xd4, 0x18, 0x98, 0xfd, 0xa3, 0x84, 0x0f, 0x66, + 0x8d, 0x27, 0xd6, 0x78, 0x32, 0x9c, 0x6e, 0xa5, 0x61, 0x19, 0x50, 0xe8, 0xe7, 0x65, 0xae, 0xa8, 0x7e, 0xfe, 0x79, + 0xcd, 0xd7, 0xbc, 0xd9, 0x62, 0x9b, 0x74, 0x4f, 0x83, 0xbd, 0x3c, 0x9a, 0x52, 0x38, 0x89, 0x3a, 0x37, 0x12, 0x75, + 0x51, 0xb3, 0x0c, 0xd5, 0x09, 0x5e, 0xcd, 0x53, 0x3d, 0xec, 0xcd, 0x44, 0xb4, 0x56, 0x52, 0x96, 0x18, 0xb0, 0xd6, + 0x91, 0x87, 0xe4, 0x6e, 0xad, 0xe3, 0x4e, 0x43, 0x5d, 0x9a, 0x42, 0x4d, 0xb0, 0xc2, 0x05, 0x38, 0x82, 0xde, 0x17, + 0x21, 0x87, 0x6b, 0xaa, 0xd2, 0x2f, 0x68, 0x4a, 0x9e, 0x78, 0x8a, 0x5a, 0xad, 0x48, 0xb7, 0x1f, 0xe5, 0xd8, 0x0d, + 0xdf, 0x38, 0x21, 0x27, 0x46, 0xe8, 0xef, 0x8e, 0xa5, 0x9c, 0xa1, 0xc5, 0x83, 0x3a, 0xc1, 0x7a, 0x79, 0x4b, 0x81, + 0x62, 0x8e, 0x2e, 0xab, 0xae, 0x79, 0x85, 0xb6, 0x2f, 0xcb, 0x7e, 0x3f, 0xb7, 0xf5, 0xa4, 0xec, 0x64, 0xbb, 0x34, + 0xfb, 0x10, 0x15, 0x53, 0xb8, 0xeb, 0x13, 0xcd, 0x5f, 0x85, 0xfa, 0xaa, 0x2d, 0x73, 0x3e, 0xe2, 0x88, 0x13, 0x92, + 0x93, 0xfa, 0x1f, 0x6a, 0xea, 0x95, 0xb8, 0x5f, 0x55, 0xf2, 0x52, 0x18, 0x2b, 0x46, 0x4b, 0x0c, 0x51, 0xa4, 0xdd, + 0x1b, 0xd3, 0x57, 0x05, 0xc0, 0x5f, 0x09, 0xf6, 0x67, 0x1a, 0x6a, 0xe5, 0xb7, 0x68, 0x0b, 0xf8, 0xb7, 0x8a, 0x1b, + 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, 0x2a, 0xcc, 0xd0, 0x50, 0x5b, + 0x18, 0x7d, 0x8d, 0x32, 0x6e, 0x95, 0xd9, 0xbb, 0x31, 0x76, 0x5a, 0xe0, 0x35, 0xfc, 0x1b, 0xbd, 0x50, 0xcc, 0x46, + 0x1d, 0xa4, 0x47, 0x27, 0x31, 0xfd, 0x71, 0x0b, 0x27, 0x37, 0x0b, 0x67, 0x59, 0xb3, 0x04, 0xba, 0x03, 0x17, 0xc4, + 0xb8, 0xdf, 0xcf, 0xe1, 0xc8, 0x34, 0x23, 0x5f, 0xb0, 0x9c, 0xc6, 0x6c, 0x49, 0xb5, 0xe7, 0xe1, 0x65, 0x15, 0xe6, + 0x74, 0x69, 0x65, 0xbc, 0x29, 0x03, 0x95, 0xd1, 0x6e, 0x17, 0xc2, 0x9f, 0x6e, 0x6b, 0x97, 0x74, 0xbe, 0x84, 0x0c, + 0xf0, 0x07, 0x24, 0xa2, 0x88, 0x05, 0xfe, 0x1f, 0x35, 0x4e, 0xe9, 0x89, 0xd2, 0x9a, 0x25, 0x10, 0x3c, 0x4e, 0xd5, + 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0x76, 0xbb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, 0x02, + 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0xaf, 0x1f, + 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xac, 0xd6, 0x61, 0x62, 0x8a, 0x44, 0x85, 0xe8, 0xec, 0x25, 0xc8, 0x72, 0x04, 0xe0, + 0x7a, 0xbe, 0x96, 0x35, 0xe5, 0x6b, 0x88, 0x0b, 0x0f, 0x0d, 0x7a, 0x57, 0xc8, 0xab, 0xac, 0xe4, 0x21, 0xde, 0x13, + 0x3c, 0xcd, 0xe8, 0xdd, 0x06, 0x1f, 0xda, 0xda, 0xa3, 0x27, 0xc8, 0xd6, 0x53, 0xee, 0xd7, 0x2f, 0x45, 0x38, 0x87, + 0xe8, 0x9d, 0x0b, 0xaa, 0xd5, 0xd5, 0x0e, 0x90, 0xcb, 0xb3, 0xbd, 0x7a, 0x07, 0xa7, 0x9b, 0xbe, 0xbe, 0x55, 0xa1, + 0x33, 0x07, 0x90, 0xf6, 0x90, 0xac, 0x6b, 0xae, 0x77, 0x80, 0x3b, 0x12, 0xb3, 0x35, 0xd0, 0x58, 0xb7, 0x35, 0x3b, + 0xed, 0x51, 0x3c, 0x26, 0x32, 0x33, 0x16, 0x29, 0xc6, 0xdc, 0xad, 0xd3, 0xa2, 0x68, 0x8b, 0x66, 0x08, 0xfb, 0x77, + 0x1d, 0xb1, 0x6e, 0x45, 0x9c, 0xbf, 0xdb, 0xf6, 0x05, 0x46, 0xc3, 0x98, 0x6b, 0xf7, 0x3c, 0x43, 0x37, 0x6c, 0xb0, + 0x8d, 0x24, 0x88, 0x48, 0x90, 0x99, 0x3a, 0x10, 0x65, 0x6d, 0x0d, 0xd8, 0xde, 0x71, 0xbd, 0x69, 0x81, 0x9f, 0x37, + 0x31, 0x78, 0x7b, 0xd6, 0x38, 0xa5, 0xf5, 0x35, 0xae, 0x39, 0xae, 0x0a, 0x11, 0xb5, 0x45, 0x0a, 0x80, 0x61, 0xe7, + 0x0b, 0xdc, 0x99, 0x15, 0x06, 0x73, 0xc2, 0x52, 0xc9, 0x5e, 0xe5, 0xfa, 0x73, 0xd8, 0xe2, 0x20, 0x95, 0x2f, 0xbd, + 0xfe, 0xfe, 0xc3, 0x17, 0x5f, 0xa0, 0xdb, 0x9e, 0xf3, 0x23, 0x08, 0x32, 0x81, 0x0e, 0x6a, 0x4a, 0xf5, 0xf8, 0xb2, + 0x00, 0x6a, 0x0f, 0xf3, 0xf0, 0xb2, 0x60, 0x22, 0xbe, 0xce, 0x2e, 0xe3, 0x4a, 0x16, 0xa3, 0x6b, 0x2e, 0x52, 0x59, + 0x58, 0xa9, 0x71, 0x70, 0xba, 0x5a, 0xe5, 0x3c, 0x00, 0x53, 0x79, 0xcb, 0x28, 0x3b, 0x21, 0xa3, 0x1e, 0x5c, 0x2d, + 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, 0x5c, 0xc5, 0xe5, 0xa7, 0x20, 0xb2, + 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0xdf, 0x09, 0x64, 0xba, 0x2f, 0x0b, 0xb0, 0xcc, 0xb6, 0x15, 0x1f, 0xc7, + 0x58, 0xeb, 0x70, 0x42, 0x66, 0xaa, 0x44, 0xef, 0x5d, 0xb2, 0x2e, 0xc0, 0xda, 0x4f, 0x61, 0x3b, 0xab, 0x5c, 0x33, + 0xac, 0x4c, 0x55, 0x64, 0x0c, 0xe0, 0xd7, 0xec, 0x30, 0xb4, 0x4e, 0x34, 0x73, 0xf4, 0x16, 0xd0, 0x0f, 0xe4, 0xf0, + 0x92, 0x16, 0x6b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0x38, 0xbc, 0x74, 0x0b, 0xf6, 0xda, 0xde, 0xc9, 0x51, 0x98, + 0x08, 0x9e, 0xc6, 0x66, 0x7c, 0x91, 0x67, 0x05, 0xec, 0xa0, 0xc9, 0x78, 0x4c, 0xbd, 0xa5, 0xd5, 0xba, 0x39, 0x3a, + 0x64, 0xdb, 0xec, 0x61, 0xf5, 0x90, 0x93, 0x43, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, 0xba, + 0x2f, 0xd7, 0x36, 0x42, 0xbc, 0x72, 0x76, 0x74, 0x5e, 0xd2, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xf3, 0x69, + 0x03, 0xfe, 0x82, 0x15, 0xeb, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, 0xe3, + 0xf4, 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x95, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, 0xb1, + 0xee, 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x9b, 0xde, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, 0x20, + 0x20, 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0x62, 0x24, 0x64, 0x60, 0xf8, 0x1a, 0xac, 0x45, 0xc9, 0x8d, 0x15, 0xac, + 0x77, 0xcf, 0xd7, 0x09, 0x42, 0x0a, 0x1e, 0xb8, 0x09, 0xfa, 0xa5, 0x75, 0xf3, 0x76, 0x94, 0x28, 0x83, 0xf8, 0xe4, + 0xda, 0x29, 0x07, 0x09, 0x04, 0xe0, 0xc0, 0xaa, 0x90, 0x24, 0x0a, 0x74, 0x1e, 0x5c, 0xcd, 0x38, 0x82, 0xcd, 0x2b, + 0x67, 0x2e, 0x6e, 0x00, 0xe7, 0x95, 0x3f, 0x97, 0x0d, 0xb6, 0xac, 0x47, 0x54, 0x99, 0x33, 0x4e, 0x31, 0xa8, 0x93, + 0x25, 0xe8, 0x2b, 0x4b, 0x69, 0x2f, 0x41, 0xd3, 0x78, 0xc5, 0x56, 0xca, 0x07, 0x80, 0x9e, 0xb3, 0x95, 0x32, 0xf6, + 0xc7, 0xaf, 0xcf, 0xd8, 0x4a, 0x4b, 0x83, 0xa7, 0x57, 0xb3, 0xf3, 0xd9, 0xd9, 0x80, 0x1d, 0x45, 0xa1, 0x36, 0x60, + 0x08, 0x5c, 0x64, 0x82, 0x60, 0x10, 0x6a, 0xfc, 0x97, 0x81, 0x0a, 0x10, 0x46, 0x3c, 0x1e, 0x1b, 0x71, 0xc4, 0xc2, + 0xf1, 0x10, 0x83, 0x81, 0x35, 0x5f, 0x90, 0x80, 0x50, 0x53, 0x1a, 0xfa, 0x7a, 0x86, 0xc3, 0xc9, 0xc1, 0x04, 0x52, + 0x31, 0x33, 0x53, 0x85, 0xb1, 0x31, 0x89, 0x20, 0xfe, 0x6b, 0x67, 0xbd, 0x50, 0x6e, 0x77, 0x8d, 0x06, 0x82, 0x66, + 0xf0, 0x55, 0x15, 0x4f, 0x0e, 0x86, 0x5d, 0x15, 0xe3, 0x28, 0x5c, 0x1b, 0xe5, 0xdb, 0xd9, 0x31, 0x80, 0xf9, 0x9e, + 0x0d, 0x7d, 0xb9, 0xc4, 0xd9, 0xe1, 0x63, 0xf2, 0xf0, 0x31, 0xa1, 0x67, 0xec, 0xec, 0x9b, 0xc7, 0xf4, 0x4c, 0x91, + 0x93, 0x83, 0x49, 0x74, 0xcd, 0x2c, 0x06, 0xce, 0x91, 0x6a, 0x02, 0xbd, 0x1c, 0xad, 0x85, 0x5a, 0x60, 0xda, 0xa1, + 0x29, 0xfc, 0x7e, 0x7c, 0x10, 0x0c, 0xae, 0xdb, 0x4d, 0xbf, 0x6e, 0xb7, 0xd5, 0xf3, 0xea, 0x3a, 0x38, 0x8a, 0xf6, + 0x8b, 0x99, 0xfc, 0x7d, 0x7c, 0xe0, 0xe6, 0x00, 0xeb, 0xbb, 0x7f, 0x4c, 0x4c, 0x93, 0xf6, 0x46, 0xc5, 0xaf, 0xe9, + 0x11, 0xf6, 0xa1, 0x59, 0x64, 0x47, 0x1f, 0x86, 0xff, 0x51, 0x27, 0xea, 0xb3, 0x6f, 0x8e, 0x80, 0x1c, 0x81, 0x0c, + 0x14, 0x4b, 0x04, 0x33, 0x1c, 0x68, 0x0a, 0x28, 0xc8, 0xf4, 0xb8, 0x53, 0x3d, 0xfc, 0x6a, 0xd4, 0xd4, 0x8c, 0x5c, + 0xc3, 0xd4, 0x60, 0x5b, 0xf0, 0x03, 0xd5, 0x0d, 0xfd, 0x8d, 0x46, 0x7b, 0xd2, 0x4e, 0x66, 0xe6, 0x25, 0xb5, 0x71, + 0xee, 0xae, 0x21, 0xa0, 0xb3, 0x83, 0x5b, 0x94, 0xec, 0xdb, 0xe3, 0xcb, 0x03, 0x5c, 0x45, 0x80, 0x1a, 0xc6, 0x82, + 0x6f, 0x07, 0x97, 0x7a, 0x73, 0x1f, 0x04, 0x64, 0xf0, 0x6d, 0x70, 0xf2, 0xed, 0x40, 0x0e, 0x82, 0xe3, 0xc3, 0xcb, + 0x93, 0xc0, 0x19, 0xf7, 0x43, 0xc8, 0x4b, 0x55, 0x51, 0xcc, 0x84, 0xa9, 0x22, 0xb1, 0xb5, 0xe7, 0xb6, 0x5e, 0x65, + 0x7c, 0x46, 0xd3, 0xa9, 0x45, 0x42, 0x0f, 0x53, 0x16, 0x9b, 0xdf, 0xc1, 0x84, 0x5f, 0x05, 0x91, 0x0b, 0x0a, 0x3b, + 0xcb, 0xa3, 0x98, 0x2e, 0xd9, 0xb5, 0x08, 0x53, 0x9a, 0x1c, 0xe6, 0x84, 0x44, 0xe1, 0x52, 0x81, 0x09, 0xaa, 0xd7, + 0x09, 0xc4, 0xb5, 0x75, 0x9f, 0x5f, 0x8b, 0x70, 0x49, 0xf3, 0xc3, 0x84, 0xb4, 0x8a, 0x70, 0x11, 0x6a, 0xb6, 0x35, + 0xbd, 0x60, 0xe1, 0x8a, 0x5e, 0x02, 0x33, 0x15, 0xaf, 0xc3, 0x4b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, 0x36, + 0xa4, 0x6f, 0x86, 0x2f, 0xbe, 0xb0, 0x3e, 0x79, 0xc0, 0x43, 0x3a, 0x3f, 0xbc, 0x14, 0x6c, 0x00, 0xae, 0x33, 0x7e, + 0xf3, 0x83, 0xbc, 0xd5, 0xf3, 0xd2, 0x9e, 0x62, 0x9c, 0x99, 0x76, 0x62, 0xd2, 0x4e, 0xc8, 0xfd, 0xfb, 0xb6, 0xef, + 0x5e, 0xbc, 0x56, 0x2e, 0xab, 0x96, 0x21, 0x49, 0xd6, 0xca, 0x75, 0x1a, 0x25, 0xa7, 0x56, 0xe0, 0xc9, 0x2e, 0x78, + 0x95, 0x2c, 0xfd, 0x83, 0xca, 0x5a, 0x0d, 0xd8, 0x63, 0xc4, 0xb2, 0x50, 0x38, 0xf6, 0xaf, 0x33, 0x96, 0xac, 0x7d, + 0x81, 0x46, 0x8e, 0xdc, 0xdb, 0xeb, 0x8c, 0x79, 0x31, 0x68, 0x97, 0x6b, 0x2f, 0x74, 0x9f, 0x97, 0x9e, 0xb6, 0x78, + 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0x83, 0xb1, 0x32, 0xa3, 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0x60, + 0xa0, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, 0x7a, 0x40, 0xbb, 0xd4, 0xa8, 0xca, 0xdd, 0x32, 0x93, + 0xac, 0x1a, 0x04, 0xa3, 0x3f, 0x4b, 0x29, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, 0x55, 0x2d, 0xc3, 0x72, + 0xc8, 0x51, 0x8b, 0x67, 0x7c, 0x52, 0xa5, 0xfe, 0xd1, 0x11, 0x34, 0x78, 0xbd, 0x6e, 0x05, 0x0d, 0x7e, 0x3c, 0x7e, + 0xac, 0x07, 0xfa, 0x62, 0xad, 0x1d, 0x0f, 0x7d, 0x7e, 0x1b, 0xf1, 0xc6, 0x75, 0xef, 0xa9, 0xd6, 0x2a, 0x94, 0x81, + 0x16, 0x2b, 0x2a, 0x57, 0x6a, 0x49, 0xef, 0x76, 0x11, 0x00, 0x8b, 0xd8, 0x98, 0x8d, 0xf7, 0x6d, 0xb3, 0x42, 0xd0, + 0xe8, 0xc2, 0x52, 0x1c, 0xb0, 0x44, 0xb7, 0x76, 0x30, 0xa1, 0xf1, 0x09, 0x2b, 0xfb, 0xfd, 0xfc, 0x04, 0xe8, 0xa9, + 0x36, 0x62, 0x2a, 0xe0, 0xc8, 0xff, 0xda, 0x8a, 0x4c, 0x51, 0x60, 0xb3, 0xa6, 0xee, 0xd6, 0x58, 0x46, 0xa2, 0x2f, + 0x53, 0xba, 0x3c, 0xe1, 0x19, 0x30, 0xad, 0xd6, 0x2d, 0xc7, 0x95, 0x7d, 0xc5, 0x91, 0xa7, 0xc2, 0xb2, 0xe2, 0xbc, + 0x0a, 0xc7, 0x5b, 0x8f, 0x6f, 0x70, 0x68, 0xd8, 0xb4, 0x4b, 0x7f, 0x08, 0x61, 0x21, 0xbc, 0xce, 0xe0, 0x36, 0xa2, + 0xed, 0x24, 0x50, 0x79, 0x63, 0xae, 0x13, 0xca, 0xe6, 0x76, 0xb5, 0xf6, 0x0c, 0xd2, 0x89, 0x39, 0x50, 0xaa, 0x11, + 0xb4, 0x46, 0xb3, 0xa0, 0x6a, 0xc4, 0x23, 0x67, 0xfe, 0xe5, 0x0c, 0x62, 0xb5, 0x7c, 0x49, 0x53, 0x29, 0x1a, 0x80, + 0x71, 0x01, 0x5c, 0x9e, 0x7e, 0x79, 0xff, 0xd3, 0x07, 0x1e, 0x17, 0xc9, 0xf2, 0x5d, 0x5c, 0xc4, 0x57, 0x65, 0xb8, + 0x55, 0x63, 0x14, 0xd7, 0x64, 0x2a, 0x06, 0x4c, 0x9a, 0x95, 0xd4, 0xdc, 0x95, 0x9a, 0x10, 0x63, 0x9d, 0xc9, 0xba, + 0xac, 0xe4, 0x55, 0xa3, 0xd2, 0x75, 0x91, 0xe1, 0xc7, 0x2d, 0x9f, 0xd3, 0x43, 0x00, 0x36, 0x35, 0x2e, 0xa4, 0x91, + 0xd4, 0x85, 0x18, 0x73, 0x11, 0xaf, 0xeb, 0xe3, 0x71, 0xa3, 0xeb, 0x25, 0x7b, 0x32, 0x7e, 0x34, 0x7d, 0x9d, 0x85, + 0xd9, 0x40, 0x90, 0x51, 0xb5, 0xe4, 0xa2, 0x65, 0xca, 0xa9, 0x4c, 0x02, 0xd0, 0xc7, 0xb3, 0xc7, 0xd8, 0xd1, 0x78, + 0x4c, 0xb6, 0x6d, 0xf1, 0x00, 0x0f, 0xd7, 0xeb, 0xb0, 0x20, 0x33, 0x5d, 0x47, 0x14, 0x08, 0x7e, 0x5b, 0x05, 0x80, + 0x6c, 0x69, 0xab, 0x32, 0x5c, 0x1a, 0x7b, 0x32, 0x9e, 0x50, 0x89, 0xdd, 0x0e, 0x49, 0xed, 0x55, 0xe8, 0x66, 0x5e, + 0xfa, 0x1e, 0x45, 0xd2, 0xb8, 0x2c, 0xed, 0x55, 0x2a, 0xd5, 0x9e, 0x99, 0xb9, 0xae, 0x41, 0x4c, 0x8a, 0x50, 0xd7, + 0x5d, 0x7a, 0x75, 0xef, 0x37, 0xd7, 0x9a, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xc9, 0x5b, 0xcc, 0x5b, 0x57, 0x44, + 0x4d, 0xaf, 0xd6, 0x60, 0x56, 0x8c, 0xb2, 0xa5, 0xe8, 0x62, 0x4d, 0x41, 0x29, 0x18, 0x5d, 0xae, 0xbd, 0x85, 0xfb, + 0x54, 0x36, 0x2e, 0x2c, 0x99, 0x5e, 0x2d, 0x4a, 0x4a, 0xa8, 0x6e, 0x2a, 0x46, 0x4a, 0x18, 0x29, 0x0d, 0x4f, 0xe5, + 0x7b, 0x81, 0xc7, 0x79, 0x1e, 0x44, 0x2d, 0x2f, 0xb0, 0xd3, 0x8a, 0x9c, 0x82, 0xa3, 0x97, 0xc9, 0x69, 0x28, 0x70, + 0x25, 0x14, 0xa8, 0xeb, 0x50, 0xdd, 0x6f, 0x70, 0xf3, 0xff, 0x56, 0xb0, 0xc0, 0xe3, 0x5b, 0xcf, 0x71, 0x1b, 0xfd, + 0x56, 0xf8, 0xb4, 0xf4, 0x81, 0xf4, 0x5d, 0x5d, 0x3c, 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x91, 0x29, + 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x13, 0xd1, 0xb8, 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0x57, 0x41, 0x20, 0x47, + 0x40, 0xee, 0xe7, 0x2c, 0x95, 0xc9, 0x1a, 0x10, 0x36, 0xb4, 0xfc, 0x44, 0xe3, 0x6d, 0x84, 0xfa, 0xfa, 0x05, 0x6e, + 0x73, 0xa5, 0xef, 0x73, 0x5e, 0x09, 0x5a, 0x09, 0x00, 0x7e, 0x89, 0x57, 0x20, 0xf7, 0x78, 0x0a, 0x75, 0x23, 0x6c, + 0x2f, 0xc7, 0x60, 0x49, 0x88, 0x8e, 0x22, 0x2a, 0x16, 0x28, 0x68, 0x0a, 0x83, 0x28, 0xa2, 0x2e, 0x98, 0xc3, 0xf3, + 0x5c, 0x26, 0x9f, 0xa6, 0xc6, 0x67, 0x7e, 0x18, 0x63, 0x0c, 0xe9, 0x60, 0x10, 0x56, 0xb3, 0x60, 0x38, 0x1e, 0x4d, + 0x8e, 0x9e, 0xc0, 0xb9, 0x1d, 0x8c, 0x03, 0x32, 0x08, 0xea, 0x72, 0x15, 0x0b, 0x5a, 0x5e, 0x5f, 0xda, 0x32, 0xf0, + 0xe3, 0x3a, 0x18, 0xfc, 0x56, 0xb8, 0x51, 0xf9, 0x37, 0x68, 0x4e, 0x36, 0x32, 0x0c, 0x02, 0x7a, 0xb5, 0x26, 0x20, + 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, + 0xd3, 0x6c, 0xf4, 0x4a, 0x29, 0x72, 0xdf, 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, + 0xe0, 0x46, 0xfe, 0x4a, 0x5c, 0xc7, 0x79, 0x96, 0x1e, 0x34, 0xdf, 0x1c, 0x94, 0x1b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, + 0x58, 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xcf, 0xcc, 0x64, 0xc6, 0x23, 0xf0, + 0x08, 0x6c, 0xfa, 0x40, 0x16, 0x1b, 0xe7, 0x92, 0xe4, 0x6f, 0xa6, 0xd2, 0x5e, 0xf5, 0xca, 0xbd, 0x82, 0xac, 0x57, + 0x5b, 0xb9, 0xef, 0xd6, 0x67, 0xdf, 0x74, 0x78, 0x05, 0x9e, 0x49, 0x70, 0x8b, 0xec, 0xf7, 0x9b, 0x82, 0x4a, 0x61, + 0x54, 0xc4, 0x7b, 0xc9, 0x35, 0xfa, 0xb7, 0x7b, 0x63, 0xa3, 0x48, 0x6e, 0x79, 0xff, 0x00, 0xea, 0x4c, 0xde, 0x15, + 0xb7, 0x73, 0x88, 0xda, 0xba, 0x1b, 0x0f, 0xbc, 0x37, 0x68, 0x97, 0x35, 0x47, 0xb0, 0xe5, 0xc5, 0x41, 0x06, 0x63, + 0x81, 0xb3, 0x32, 0x52, 0x6a, 0x5c, 0x43, 0x6a, 0xc1, 0x27, 0x79, 0x7a, 0x07, 0x59, 0xea, 0x49, 0x50, 0xe4, 0x78, + 0x16, 0x43, 0xa6, 0xf1, 0x36, 0x10, 0xfb, 0xad, 0x0c, 0x41, 0x9a, 0xb6, 0xdb, 0x35, 0x47, 0xa0, 0xec, 0x1e, 0x98, + 0x92, 0xd4, 0xb5, 0x31, 0x35, 0xd0, 0xd0, 0x83, 0xa8, 0x91, 0x8a, 0x38, 0x3b, 0x79, 0x0a, 0x3a, 0x44, 0xf0, 0xfd, + 0x4e, 0xb3, 0xb2, 0xe3, 0xc5, 0x84, 0xe0, 0xc9, 0xfb, 0xfc, 0x36, 0x2b, 0xab, 0x32, 0x7a, 0x93, 0xa2, 0x21, 0x54, + 0x22, 0x45, 0xf4, 0x19, 0xe2, 0x0b, 0x96, 0xf8, 0xbb, 0x8c, 0x5e, 0xa4, 0x34, 0x4e, 0x53, 0x4c, 0x7f, 0x56, 0xc0, + 0xcf, 0xa7, 0x80, 0x72, 0x89, 0x3b, 0x21, 0x3a, 0x93, 0x60, 0xaf, 0x06, 0xd1, 0xbd, 0x2a, 0x0e, 0x98, 0xa2, 0xd1, + 0xb5, 0xa0, 0x88, 0x59, 0x87, 0xd9, 0x7f, 0x29, 0x50, 0x28, 0xa4, 0x8a, 0x79, 0x29, 0xec, 0x43, 0xc4, 0xd7, 0x50, + 0xce, 0xe9, 0xbb, 0x57, 0x66, 0x48, 0xa3, 0x5b, 0x49, 0xf5, 0xd6, 0xc6, 0x63, 0x0b, 0x51, 0x7a, 0xa2, 0xf3, 0x35, + 0x3d, 0x8b, 0x57, 0x59, 0xb4, 0x05, 0xfc, 0x89, 0x77, 0xaf, 0x9e, 0x2a, 0x0b, 0x93, 0x57, 0x19, 0x28, 0x0e, 0x4e, + 0xdf, 0xbd, 0x7a, 0x2d, 0xd3, 0x75, 0xce, 0xa3, 0x8d, 0x44, 0xd2, 0x7a, 0xfa, 0xee, 0xd5, 0xcf, 0x68, 0xee, 0xf5, + 0xbe, 0x80, 0xf7, 0x2f, 0x80, 0xb7, 0x8c, 0xf2, 0x35, 0xf4, 0x49, 0xfd, 0x5e, 0xae, 0xb1, 0x53, 0x5e, 0xad, 0x65, + 0xf4, 0x57, 0x5a, 0x7b, 0xd2, 0xaa, 0xbf, 0x0a, 0x9f, 0xda, 0x79, 0x02, 0x9e, 0xdb, 0x3c, 0x13, 0x9f, 0x22, 0x2b, + 0xda, 0x09, 0xa2, 0x6f, 0x0f, 0x6e, 0xaf, 0x72, 0x51, 0x46, 0xf8, 0x82, 0xa1, 0x5d, 0x50, 0x74, 0x78, 0x78, 0x73, + 0x73, 0x33, 0xba, 0x79, 0x34, 0x92, 0xc5, 0xe5, 0xe1, 0xe4, 0xfb, 0xef, 0xbf, 0x3f, 0xc4, 0xb7, 0xc1, 0xb7, 0x6d, + 0xb7, 0xf7, 0x8a, 0xf0, 0x01, 0x0b, 0x10, 0xb1, 0xfb, 0x5b, 0xb8, 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x6d, 0xf0, 0xad, + 0x3e, 0x74, 0xbe, 0x3d, 0x2e, 0xaf, 0x2f, 0x55, 0xf9, 0x5d, 0x25, 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, + 0x3b, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0x29, 0xaf, 0x2f, 0x4f, 0x02, 0xcf, 0xe4, 0xb5, 0xc1, 0x22, + 0x3a, 0x10, 0x97, 0xe0, 0xf0, 0x92, 0x06, 0xdf, 0x06, 0xc4, 0xa5, 0x7c, 0x03, 0x29, 0xdf, 0x1c, 0x3d, 0xf1, 0xd3, + 0xfe, 0x97, 0x4a, 0x7b, 0xe4, 0xa7, 0x1d, 0x63, 0xda, 0xa3, 0xa7, 0x7e, 0xda, 0x89, 0x4a, 0x7b, 0xee, 0xa7, 0xfd, + 0x9f, 0x72, 0x00, 0xa9, 0x07, 0xbe, 0xf5, 0xdf, 0xc6, 0x6b, 0x0d, 0x9e, 0x42, 0x51, 0x76, 0x15, 0x5f, 0x72, 0x68, + 0xf4, 0xe0, 0xf6, 0x2a, 0xa7, 0xc1, 0x00, 0xdb, 0xeb, 0x19, 0x79, 0x78, 0x1f, 0x7c, 0xbb, 0x2e, 0xf2, 0x30, 0xf8, + 0x76, 0x80, 0x85, 0x0c, 0xbe, 0x0d, 0xc8, 0xb7, 0xc6, 0x40, 0x46, 0xb0, 0x6d, 0xe0, 0x42, 0xb3, 0x0e, 0x6d, 0xc0, + 0x34, 0x5f, 0x1a, 0x57, 0xd3, 0x7f, 0x15, 0xdd, 0xd9, 0xf0, 0x96, 0xa8, 0xdc, 0x74, 0x83, 0x9a, 0xbe, 0x05, 0xef, + 0x04, 0x68, 0x54, 0x14, 0x5c, 0xc7, 0x45, 0x38, 0x1c, 0x96, 0xd7, 0x97, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa2, + 0x40, 0xc8, 0xa1, 0xfa, 0x19, 0xa8, 0x48, 0x60, 0x01, 0x42, 0x19, 0xc1, 0x7f, 0x41, 0x4d, 0xdf, 0x49, 0xb6, 0x0d, + 0x86, 0x37, 0xfc, 0xfc, 0x53, 0x56, 0x0d, 0x95, 0x68, 0xf1, 0x46, 0x50, 0xf8, 0x01, 0x7f, 0x5d, 0xd5, 0xd1, 0xbf, + 0xc0, 0x8d, 0xbb, 0xa9, 0x61, 0x7f, 0x27, 0x3d, 0x87, 0x36, 0x39, 0xcf, 0x16, 0xd3, 0xd6, 0x81, 0xfe, 0x56, 0x92, + 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, 0xe0, 0x0b, 0xf6, 0x56, 0xce, 0xb9, 0x67, 0x3e, 0x75, 0x2a, 0xfd, 0x69, 0x9e, + 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, 0xe4, 0xf0, 0xbf, 0xe6, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0x1c, 0x92, 0x59, 0xb0, + 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xeb, 0x75, 0xdb, 0xcb, 0xe3, 0xce, + 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, + 0x1c, 0xb0, 0xe0, 0xb8, 0x37, 0x1c, 0x1e, 0x04, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x07, 0xc3, 0xe1, 0x49, 0xe0, 0xee, + 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, 0xc1, 0xfe, 0x2a, 0xc2, 0x92, 0x82, 0x78, 0x4c, 0x6a, 0xf1, 0x97, 0x06, 0x97, + 0x19, 0x00, 0xf4, 0x91, 0x92, 0x80, 0x19, 0x58, 0x99, 0x01, 0x84, 0x2a, 0xa7, 0x31, 0xbb, 0x05, 0xe6, 0x11, 0x38, + 0x66, 0x05, 0x93, 0x05, 0x88, 0x25, 0x01, 0xce, 0x5d, 0x10, 0xc5, 0xba, 0x90, 0x53, 0x08, 0x02, 0x80, 0x3f, 0x89, + 0x29, 0x05, 0x93, 0x74, 0xec, 0x46, 0x10, 0xc4, 0xf1, 0xd9, 0x8d, 0x68, 0x4d, 0xce, 0x12, 0x1d, 0xcc, 0x48, 0x02, + 0x6c, 0x88, 0x81, 0xe1, 0x83, 0xfb, 0x39, 0x28, 0x3d, 0xac, 0xde, 0x09, 0xb9, 0xe0, 0x0d, 0x77, 0x2c, 0xd4, 0x0d, + 0x5c, 0x3d, 0xe1, 0x20, 0xd8, 0x70, 0xcd, 0x02, 0x8c, 0xaa, 0x62, 0x5d, 0x56, 0x3c, 0xfd, 0xb8, 0x59, 0x41, 0x2c, + 0x40, 0x1c, 0xd0, 0x77, 0x32, 0xcf, 0x92, 0x4d, 0xe8, 0xec, 0xb9, 0xb6, 0x2a, 0xfd, 0xe5, 0xc7, 0xd7, 0x3f, 0x45, + 0x20, 0x72, 0xac, 0x0d, 0xa5, 0xdf, 0x70, 0x3c, 0x9b, 0xfc, 0x88, 0x57, 0xfe, 0xc6, 0xde, 0x70, 0x7b, 0x7a, 0xf4, + 0xfb, 0x50, 0x37, 0xdd, 0xf0, 0xd9, 0x86, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0xf0, 0xec, 0xb2, 0xd6, 0xbe, 0x11, 0xd2, + 0xfd, 0xf3, 0x4c, 0x79, 0x63, 0x7e, 0xb4, 0x83, 0x61, 0x10, 0x4c, 0xb5, 0x50, 0x12, 0xa2, 0x90, 0x30, 0x25, 0x60, + 0x88, 0x0e, 0xf4, 0xb2, 0x9a, 0x22, 0xe7, 0xa6, 0x46, 0x16, 0xde, 0x0f, 0x98, 0x16, 0x3a, 0x34, 0x72, 0x28, 0x3f, + 0x38, 0x9c, 0x30, 0x66, 0xe1, 0xb7, 0x4a, 0x98, 0x7e, 0xb5, 0xa8, 0x9c, 0x83, 0xe8, 0x01, 0x18, 0xe3, 0x0a, 0x5e, + 0x40, 0x57, 0xd8, 0xa7, 0xb5, 0x8a, 0x12, 0x82, 0x60, 0x7a, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, + 0xab, 0x72, 0x96, 0x2a, 0xea, 0x32, 0x94, 0x95, 0xb1, 0xc2, 0xc0, 0x2f, 0xd9, 0x2f, 0x05, 0x7a, 0x96, 0x4f, 0x45, + 0x17, 0xbc, 0x10, 0x4a, 0xb0, 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xd7, 0x8f, 0xa7, + 0xaf, 0x65, 0xca, 0xb5, 0x09, 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x07, 0xe8, 0x57, 0xdb, 0x46, 0x9f, + 0x5d, 0xaf, 0xf5, 0x66, 0x50, 0xa2, 0x63, 0x5e, 0xa3, 0xe0, 0x5a, 0x29, 0x14, 0x8c, 0xf6, 0x36, 0xfe, 0x02, 0x47, + 0x6e, 0x75, 0x7b, 0xe8, 0xfd, 0x56, 0xc5, 0x97, 0x6f, 0xd0, 0xb7, 0xd3, 0xfe, 0x1c, 0x55, 0xf2, 0x97, 0xd5, 0x0a, + 0x7c, 0xa8, 0x20, 0xd2, 0x8a, 0xc5, 0xe9, 0x85, 0x7a, 0x3e, 0xbc, 0x3b, 0x7d, 0x03, 0x7e, 0x94, 0xf8, 0xfb, 0xd7, + 0x1f, 0x83, 0x9a, 0x4c, 0xe3, 0x59, 0x61, 0x3e, 0xb4, 0x39, 0x20, 0x54, 0x8b, 0x4b, 0xb3, 0xef, 0x67, 0x71, 0x93, + 0x7d, 0xd7, 0x6c, 0x3d, 0x2d, 0x9a, 0x48, 0x52, 0x86, 0xdb, 0x07, 0x03, 0x02, 0x7d, 0x80, 0x28, 0xce, 0xbe, 0xa0, + 0x31, 0xa4, 0xf9, 0xcc, 0xbe, 0x1f, 0x21, 0xf0, 0xd5, 0x5e, 0x48, 0x35, 0xae, 0xb0, 0x68, 0xf4, 0x90, 0xcf, 0x78, + 0xa4, 0x0c, 0x8b, 0xde, 0x63, 0x02, 0x71, 0x86, 0xd3, 0xea, 0x3d, 0x62, 0x40, 0xe3, 0xdd, 0x40, 0xcb, 0x1e, 0xa2, + 0x8c, 0xba, 0xec, 0x0d, 0x8b, 0xef, 0xd7, 0xeb, 0x30, 0xb3, 0x96, 0x97, 0x43, 0xf8, 0x1b, 0x68, 0x03, 0x70, 0xca, + 0x91, 0xe5, 0xab, 0xcc, 0x46, 0x57, 0x4b, 0x4c, 0x6f, 0x22, 0x88, 0x4d, 0xa4, 0xd3, 0x61, 0xed, 0xea, 0x54, 0xbd, + 0xab, 0x9d, 0xcf, 0x44, 0xaf, 0x02, 0xad, 0x5c, 0xdb, 0x1e, 0x0f, 0xe1, 0x3f, 0xb5, 0xb4, 0xc2, 0x46, 0xd8, 0x73, + 0xf1, 0x85, 0xe7, 0xd8, 0x9c, 0x80, 0x06, 0x57, 0x32, 0x05, 0xe0, 0x2c, 0xad, 0x46, 0xa3, 0x46, 0xd8, 0x67, 0xe5, + 0x7c, 0x0e, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x1c, 0xb8, 0x89, 0xc9, 0xc9, 0xbb, 0x31, 0x39, 0xa7, 0x9f, 0x14, 0xdc, + 0x77, 0x70, 0x56, 0x2e, 0xe3, 0x54, 0xde, 0x00, 0x36, 0x65, 0xe0, 0xa7, 0x62, 0xa9, 0x5e, 0x42, 0xb2, 0xe4, 0xc9, + 0x27, 0xb4, 0xda, 0x48, 0x03, 0xe0, 0x2a, 0xa7, 0xc6, 0x72, 0x4f, 0x81, 0xa6, 0xba, 0x52, 0x54, 0x42, 0x5c, 0x55, + 0x71, 0xb2, 0xfc, 0x80, 0xa9, 0xe1, 0x16, 0x7a, 0x11, 0x05, 0x72, 0xc5, 0x05, 0x90, 0xf4, 0x9c, 0xfd, 0x23, 0xd3, + 0xd8, 0xeb, 0x0f, 0x24, 0x0a, 0x98, 0x34, 0x8a, 0x32, 0x56, 0xca, 0x5e, 0x49, 0x13, 0xfd, 0x2e, 0x08, 0x6a, 0xf7, + 0xf2, 0x2f, 0xa8, 0xfb, 0x29, 0xb4, 0x22, 0x6c, 0x80, 0x17, 0x6a, 0xf0, 0xc3, 0xd4, 0x2e, 0x39, 0x0f, 0xc8, 0xd0, + 0x79, 0x9f, 0xd5, 0x76, 0xab, 0x3f, 0x5d, 0x02, 0xd6, 0x6b, 0x6a, 0x7c, 0x0a, 0xc3, 0x84, 0x98, 0x58, 0xc9, 0x56, + 0x59, 0x69, 0x37, 0x94, 0x69, 0x27, 0x5d, 0x32, 0xaf, 0x85, 0xd3, 0xbc, 0xc7, 0xd8, 0x72, 0xa4, 0x72, 0xf7, 0xfb, + 0xa1, 0xf9, 0xc9, 0x72, 0xfa, 0x40, 0x87, 0xb0, 0xf6, 0xc6, 0x83, 0xe6, 0x44, 0xab, 0xab, 0x3a, 0xfa, 0x01, 0x1d, + 0x80, 0x99, 0xb6, 0x08, 0x95, 0x2e, 0xf8, 0xb6, 0xaf, 0x44, 0xc5, 0x25, 0x09, 0x4b, 0x25, 0x81, 0x9d, 0xdd, 0x94, + 0xec, 0x6c, 0x03, 0xe2, 0x19, 0xee, 0x7a, 0x5a, 0xec, 0x84, 0x34, 0xe1, 0x2d, 0x0e, 0x12, 0x10, 0x75, 0xa8, 0xea, + 0x12, 0xb2, 0x35, 0x86, 0x2e, 0xfe, 0x45, 0x29, 0x4c, 0x58, 0xcb, 0xa4, 0x2a, 0x31, 0x41, 0xa1, 0xca, 0xfd, 0x16, + 0x81, 0x25, 0x0a, 0x76, 0x00, 0x7b, 0xef, 0x46, 0xdd, 0x8c, 0x9a, 0xaa, 0x4e, 0xbd, 0x04, 0x1f, 0xa7, 0x59, 0x57, + 0x41, 0x66, 0x61, 0x57, 0xc5, 0x9a, 0x07, 0x3a, 0x56, 0x97, 0x32, 0x26, 0xee, 0xd2, 0x22, 0x43, 0x7c, 0x64, 0x8c, + 0x2d, 0xac, 0xe1, 0x48, 0xdb, 0xe3, 0xa6, 0x27, 0x08, 0xfd, 0x84, 0x0d, 0x25, 0x70, 0xd3, 0xd9, 0x9e, 0x9a, 0x66, + 0x3e, 0x20, 0xe2, 0x30, 0xa0, 0x40, 0xb2, 0x71, 0x48, 0x73, 0xa4, 0x2f, 0x48, 0x9a, 0x30, 0x50, 0xb6, 0xe2, 0x39, + 0x41, 0x56, 0x14, 0x7a, 0xb6, 0xae, 0x6a, 0x88, 0x9f, 0xcb, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xa7, 0x09, 0x32, 0xb1, + 0x3b, 0xda, 0x66, 0x26, 0xc3, 0x51, 0xb2, 0xc0, 0xfc, 0x0a, 0xa2, 0xc4, 0x9d, 0x69, 0x56, 0xe5, 0x60, 0x5c, 0xc0, + 0x02, 0xad, 0x7c, 0x0f, 0xea, 0xc6, 0x1a, 0xda, 0x6a, 0x58, 0x66, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, + 0x8a, 0xe5, 0x65, 0x0a, 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x5e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, + 0x53, 0x03, 0xe8, 0xa9, 0x17, 0x00, 0xbe, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xb8, 0x74, 0x83, 0x20, + 0x45, 0x6f, 0x52, 0x30, 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, + 0xe4, 0x95, 0xd4, 0xc4, 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdb, 0x9d, 0xa6, 0x61, 0xd2, 0x66, + 0x1b, 0x52, 0x90, 0x56, 0x98, 0x38, 0x21, 0x50, 0xd9, 0x2b, 0xdc, 0x2f, 0xd8, 0x4e, 0x9a, 0x82, 0x07, 0x61, 0xa3, + 0x81, 0x89, 0x5b, 0x5d, 0x02, 0x8c, 0x66, 0xc2, 0x25, 0xd5, 0xce, 0x4e, 0x5a, 0x58, 0xdf, 0x5e, 0x97, 0x17, 0xb6, + 0x0f, 0x3a, 0x96, 0x5a, 0xd7, 0xf0, 0x40, 0xf3, 0x9a, 0x5d, 0x5c, 0x31, 0x4d, 0x13, 0x8d, 0xf5, 0x90, 0xb2, 0xe4, + 0x58, 0xd7, 0xd3, 0x15, 0xae, 0x96, 0x99, 0x06, 0xba, 0x97, 0x78, 0xa1, 0x07, 0x7c, 0xf0, 0x70, 0x45, 0xa2, 0x0b, + 0x6c, 0x36, 0x5b, 0xd5, 0x64, 0x9a, 0xdf, 0x95, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, 0x69, + 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, 0xe8, + 0x9d, 0xf3, 0x45, 0xea, 0xe6, 0x17, 0x60, 0x1b, 0xb5, 0xb5, 0xa6, 0x59, 0xeb, 0x30, 0x51, 0x16, 0xd6, 0xc8, 0x42, + 0x2e, 0xc1, 0x07, 0x73, 0xbf, 0xa9, 0xd3, 0xe7, 0x1d, 0x44, 0xd8, 0xef, 0xa2, 0xc7, 0x23, 0x8c, 0x15, 0x6b, 0x90, + 0x18, 0x56, 0x61, 0x4d, 0x9b, 0xcb, 0x21, 0xca, 0xa9, 0x59, 0x32, 0xd1, 0x92, 0xfa, 0x94, 0x22, 0x4a, 0xc1, 0xdc, + 0x78, 0x5a, 0x36, 0x4c, 0x09, 0x11, 0xb2, 0x42, 0x3a, 0xa0, 0x5a, 0x0b, 0x2d, 0xd5, 0x04, 0x01, 0x0f, 0xbd, 0x2c, + 0x34, 0xa6, 0x20, 0xfa, 0x88, 0x0c, 0x37, 0xe2, 0xc8, 0xe8, 0xfe, 0x18, 0xc5, 0x04, 0x42, 0x77, 0x7b, 0x79, 0x61, + 0xf5, 0x69, 0xd9, 0x56, 0x07, 0x71, 0x8d, 0x69, 0x72, 0x07, 0x41, 0x8d, 0x51, 0xd0, 0xe6, 0x74, 0xa3, 0xff, 0x2e, + 0x42, 0xdf, 0x2e, 0x1c, 0xbb, 0x51, 0x10, 0x09, 0x11, 0x69, 0xbd, 0xa6, 0x62, 0x80, 0xda, 0x79, 0xec, 0x22, 0x56, + 0xe9, 0x6e, 0x21, 0xca, 0x1b, 0x95, 0xf5, 0xeb, 0x75, 0x48, 0x76, 0x3b, 0x2c, 0x0b, 0x7c, 0xd9, 0x9f, 0xae, 0xef, + 0x80, 0x40, 0x7f, 0xb0, 0xfe, 0x22, 0x04, 0xfa, 0xb3, 0xec, 0x6b, 0x20, 0xd0, 0x1f, 0xac, 0xff, 0xa7, 0x21, 0xd0, + 0x9f, 0xae, 0x3d, 0x08, 0x74, 0x35, 0x18, 0xff, 0x2c, 0x58, 0xf0, 0xf6, 0x4d, 0x40, 0x9f, 0x49, 0x16, 0xbc, 0x7d, + 0xf1, 0xc2, 0x13, 0xa6, 0x7f, 0xcc, 0x34, 0x92, 0xbf, 0x91, 0x05, 0x23, 0x6e, 0x0b, 0xbc, 0x42, 0xad, 0x93, 0x0f, + 0x54, 0x94, 0x01, 0x10, 0x7d, 0xf9, 0x5b, 0x56, 0x2d, 0xc3, 0xe0, 0x30, 0x20, 0x33, 0x07, 0x09, 0x3a, 0x9c, 0x34, + 0x6e, 0x6f, 0xbf, 0x88, 0x86, 0x50, 0xc7, 0x46, 0x1e, 0x80, 0xaf, 0x5c, 0xae, 0xb7, 0xfe, 0x0d, 0x11, 0x3f, 0x99, + 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x3f, 0x16, 0x9e, 0x6d, + 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, 0xe5, + 0xbf, 0xbc, 0x7f, 0x65, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, 0xfe, + 0x78, 0xb0, 0xed, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x9b, 0xd5, + 0x87, 0x0f, 0xb6, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x5b, 0xc2, 0x0f, 0x5e, 0xff, 0xe1, + 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, 0xa8, + 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, 0x9d, + 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, 0x2e, + 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xfb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, 0x79, + 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0xfc, 0xf8, 0x55, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, 0x2e, + 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, 0x95, + 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0x49, 0x87, 0x5d, + 0x3e, 0x5d, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc5, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, + 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x09, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x45, 0x9d, 0x95, 0xe0, 0x49, 0xe5, 0x71, 0xe2, 0x2a, 0x16, 0x40, 0x46, 0x4d, 0x34, 0x80, 0x8e, 0x1c, 0x34, 0xb4, 0x7b, 0x4d, 0x3b, 0x96, 0x1b, 0x95, 0x45, 0x06, 0x96, 0xb0, 0xcf, 0xa1, 0x74, 0x40, 0x6c, 0x87, 0x70, 0x21, 0x70, 0xf5, 0xc4, 0xab, 0x51, 0x03, 0xb1, 0x87, 0x96, 0xbe, 0xbb, 0x90, 0x62, 0xb5, 0x0c, 0xda, 0x65, 0x63, 0x98, 0xf0, 0x7a, 0x8d, 0x2e, 0xc3, 0xa0, 0xf8, 0x2f, 0xdc, 0xa2, 0x44, 0x5c, 0xa4, 0x2c, 0x55, 0x46, 0x67, 0x3d, 0x94, 0x85, 0xe1, 0xb3, 0xa7, - 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0x8d, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, - 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0xdd, 0xc2, 0xc0, 0x5d, 0xe8, 0xb2, - 0x5a, 0x93, 0xb8, 0xf7, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, + 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0xad, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, + 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0x66, 0x61, 0xe0, 0x2e, 0x74, 0x59, + 0xad, 0x49, 0xbc, 0xf3, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, 0x6a, 0x7f, 0xab, 0x7d, 0xe2, 0x9e, 0x6d, 0xd7, 0x68, 0xd3, 0xcf, 0xa1, 0x5d, 0x23, 0x35, 0x4b, 0xa9, 0xe0, 0x7f, - 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0xd4, 0x87, 0x91, 0x26, 0xd1, 0x0a, 0x09, 0x4a, 0x51, 0xdf, - 0xd6, 0x0b, 0xd5, 0x06, 0x42, 0xd4, 0x6d, 0x31, 0x4d, 0x9f, 0x23, 0x68, 0x3b, 0x48, 0x49, 0x70, 0x6f, 0xd9, 0x98, - 0x5f, 0x5d, 0xcb, 0x67, 0x0e, 0xdd, 0x59, 0xcc, 0x3e, 0x97, 0x61, 0x30, 0x88, 0x3e, 0x97, 0x85, 0x4d, 0xee, 0x59, - 0xa5, 0x2a, 0xcb, 0xb1, 0xb1, 0xbd, 0x9c, 0xa2, 0x29, 0x4b, 0xf8, 0x76, 0x1d, 0x36, 0xd7, 0x3e, 0xc5, 0xd9, 0xa7, - 0x9b, 0x2b, 0x5e, 0x2d, 0x65, 0x1a, 0x05, 0xdf, 0x3f, 0xff, 0x10, 0x18, 0xd5, 0x75, 0xa1, 0x41, 0x8b, 0xb4, 0x36, - 0x27, 0x97, 0x97, 0x20, 0xcb, 0xec, 0x15, 0x23, 0xf9, 0x71, 0x27, 0xca, 0xe7, 0x1f, 0x3f, 0x7c, 0xf8, 0xf0, 0xf6, - 0x00, 0x15, 0x3e, 0xbd, 0x83, 0xf7, 0x0a, 0x3d, 0xe0, 0xe0, 0xc1, 0xa6, 0xd0, 0x2a, 0xf6, 0xfa, 0x0f, 0x7b, 0x56, - 0x15, 0x2d, 0x05, 0xb9, 0x01, 0x05, 0xf4, 0xaa, 0x68, 0x0d, 0x6b, 0xe1, 0xb4, 0xd8, 0x7e, 0x66, 0xa5, 0x5d, 0x0a, - 0x50, 0x77, 0xa2, 0x6a, 0x8e, 0x94, 0x5e, 0x1e, 0x22, 0x2d, 0x84, 0xd5, 0x9e, 0xad, 0x56, 0x75, 0x6d, 0x35, 0x59, - 0x54, 0x99, 0xb8, 0x3c, 0xc3, 0xdd, 0xff, 0x45, 0x5b, 0xce, 0xcc, 0xb0, 0xa2, 0x17, 0xed, 0xdd, 0xd6, 0x80, 0x2a, - 0xd3, 0x46, 0xb9, 0x7a, 0x0f, 0x81, 0xc0, 0xac, 0xac, 0xa7, 0xfe, 0xc7, 0xc6, 0x62, 0xc4, 0x4f, 0x53, 0x40, 0x6e, - 0xc0, 0x03, 0xb1, 0x93, 0x78, 0x64, 0xda, 0x77, 0x83, 0x72, 0x93, 0xe3, 0xa4, 0x95, 0x30, 0x1b, 0x4e, 0xa2, 0x09, - 0xb1, 0xf1, 0x25, 0x34, 0x0d, 0xfb, 0x7e, 0xf4, 0xfc, 0xf5, 0x87, 0x97, 0x1f, 0xfe, 0x79, 0xf6, 0xf4, 0xf4, 0xc3, - 0xf3, 0xef, 0xdf, 0xbc, 0x7b, 0xf9, 0xfc, 0x3d, 0x9e, 0x10, 0x1a, 0xb0, 0x32, 0xdc, 0x68, 0xab, 0xe8, 0x66, 0x59, - 0x91, 0xa8, 0x49, 0xb3, 0x29, 0x0a, 0x31, 0x0a, 0x33, 0xdb, 0x22, 0x7f, 0x79, 0xfd, 0xec, 0xf9, 0x8b, 0x97, 0xaf, - 0x9f, 0x3f, 0x6b, 0x7f, 0x3d, 0x9c, 0xd4, 0xa4, 0x76, 0x33, 0xa7, 0x23, 0xa4, 0x70, 0x3b, 0x5e, 0x1d, 0xf4, 0x09, - 0xb5, 0xf2, 0x3e, 0x7d, 0xca, 0x60, 0x45, 0x32, 0x25, 0xa7, 0xc7, 0xdf, 0x1e, 0xfe, 0xaf, 0xda, 0x78, 0xdb, 0x2d, - 0xf0, 0x10, 0x48, 0xc6, 0x94, 0xac, 0x1f, 0x46, 0x35, 0xa3, 0xea, 0x65, 0x24, 0xa8, 0x2d, 0x0d, 0x6c, 0xa0, 0x53, - 0xaa, 0x42, 0x2a, 0x9c, 0x25, 0x71, 0xc5, 0x2f, 0x65, 0x71, 0x17, 0x65, 0xa3, 0x56, 0x0a, 0x6d, 0x2c, 0x80, 0x28, - 0x04, 0xc1, 0x72, 0x23, 0x89, 0xf4, 0x14, 0x01, 0xf0, 0x86, 0xc0, 0x8d, 0xea, 0xdc, 0x45, 0x0b, 0x68, 0x17, 0x4c, - 0x16, 0xdb, 0x6d, 0xc7, 0xa0, 0x75, 0xd2, 0xbe, 0x68, 0x9e, 0x29, 0xa2, 0xb8, 0x00, 0xc6, 0x1c, 0x8e, 0x37, 0x75, - 0x76, 0x31, 0x73, 0xdc, 0x9d, 0xea, 0xa8, 0x9f, 0x60, 0x8d, 0xe8, 0x5e, 0x9b, 0xc0, 0x32, 0xcd, 0xf3, 0x70, 0xdc, - 0xa2, 0xb8, 0x06, 0xe3, 0xb7, 0x95, 0xaa, 0x96, 0x99, 0xc6, 0x56, 0x84, 0x99, 0x82, 0x70, 0x5c, 0x46, 0x74, 0x1b, - 0xe6, 0x60, 0x21, 0xd3, 0x98, 0x5f, 0x33, 0x0e, 0x79, 0x24, 0x0d, 0x4c, 0x1e, 0x98, 0x0c, 0xee, 0xc9, 0xb5, 0x8c, - 0x8a, 0x06, 0xe0, 0xa5, 0x6c, 0x0e, 0xea, 0xf1, 0xff, 0x69, 0xef, 0x69, 0xb7, 0xdb, 0xb6, 0x91, 0xfd, 0xdf, 0xa7, - 0x60, 0x98, 0x6c, 0x4a, 0x26, 0x24, 0x4d, 0x4a, 0x96, 0xad, 0x48, 0x96, 0xdc, 0xe6, 0x6b, 0x9b, 0xd6, 0x6d, 0x7a, - 0x62, 0x37, 0x7b, 0x77, 0x5d, 0x1f, 0x8b, 0x92, 0x20, 0x89, 0x1b, 0x8a, 0xd4, 0x25, 0x29, 0x4b, 0xae, 0xc2, 0x7d, - 0x96, 0x7d, 0x84, 0xfb, 0x0c, 0x7d, 0xb2, 0x7b, 0x66, 0x06, 0x20, 0xc1, 0x0f, 0xc9, 0x72, 0x93, 0xb6, 0x7b, 0xcf, - 0xb9, 0xa7, 0x4d, 0x22, 0x82, 0x00, 0x08, 0x0c, 0x80, 0x99, 0xc1, 0x7c, 0x46, 0xc5, 0x67, 0xd8, 0xc6, 0xa5, 0x2a, - 0x28, 0xb2, 0x2d, 0x56, 0x02, 0xd1, 0xc2, 0xe8, 0x94, 0x3e, 0x6f, 0x25, 0xe1, 0x59, 0xb8, 0x12, 0xe2, 0xe1, 0x93, - 0xa8, 0xa6, 0x10, 0xcf, 0x46, 0xc7, 0x3d, 0x19, 0xd1, 0x0f, 0x27, 0xdd, 0x42, 0x04, 0xd2, 0x1c, 0xc0, 0x19, 0x73, - 0x3a, 0xa0, 0x2b, 0xd3, 0xf5, 0xa3, 0x8d, 0xd8, 0x78, 0xe9, 0xc0, 0xcb, 0x92, 0xbf, 0x16, 0x18, 0x8b, 0x94, 0x83, - 0x5e, 0x8e, 0x35, 0x5a, 0x53, 0x8d, 0xef, 0x8f, 0x9e, 0x57, 0xcb, 0x9d, 0x58, 0xf4, 0xc8, 0x28, 0x17, 0x66, 0x7d, - 0x15, 0xb6, 0x66, 0x23, 0xad, 0x6e, 0x60, 0x24, 0x5e, 0x12, 0x53, 0xc0, 0xf0, 0xcb, 0x88, 0xf1, 0x1f, 0x55, 0x30, - 0x3e, 0x5a, 0xd9, 0x65, 0x08, 0xff, 0xc7, 0xb7, 0xe7, 0x17, 0xa0, 0xbd, 0x72, 0x51, 0xdd, 0xbc, 0x51, 0xb9, 0xa5, - 0x8a, 0x09, 0xfa, 0x20, 0xb5, 0xa3, 0xba, 0x0b, 0xa0, 0xc7, 0x78, 0x2f, 0x38, 0x58, 0x9b, 0xab, 0xd5, 0xca, 0x04, - 0xbb, 0x55, 0x73, 0x19, 0xf9, 0xc4, 0x03, 0x8e, 0xd5, 0x54, 0x20, 0x72, 0x56, 0x42, 0xe4, 0x10, 0xf4, 0x96, 0x67, - 0x4d, 0x39, 0x9f, 0x85, 0xab, 0xaf, 0x7d, 0x5f, 0x16, 0xce, 0x08, 0x56, 0x8d, 0xcb, 0x2b, 0x0a, 0x88, 0x41, 0x03, - 0x1d, 0x93, 0xe5, 0xc5, 0xd7, 0xdc, 0x2a, 0x60, 0x7c, 0x3d, 0xbc, 0xbd, 0xe6, 0x9a, 0x87, 0x2c, 0xea, 0xf0, 0xf9, - 0xe0, 0x64, 0xec, 0xdd, 0x28, 0xc8, 0x4f, 0xf6, 0x54, 0x70, 0xd9, 0xf2, 0xd9, 0x70, 0x99, 0x24, 0x61, 0x60, 0x46, - 0xe1, 0x4a, 0xed, 0x9f, 0xd0, 0x83, 0xa8, 0xe0, 0xd2, 0xa3, 0xaa, 0x7c, 0x35, 0xf2, 0xbd, 0xd1, 0x87, 0x9e, 0xfa, - 0x68, 0xe3, 0xf5, 0xfa, 0x25, 0xae, 0xd1, 0x4e, 0xd5, 0x3e, 0x8c, 0x55, 0xf9, 0xda, 0xf7, 0x4f, 0x0e, 0xa8, 0x45, - 0xff, 0xe4, 0x60, 0xec, 0xdd, 0xf4, 0xa5, 0x04, 0x30, 0x5c, 0x3b, 0xda, 0xe3, 0x81, 0x36, 0x33, 0x7b, 0xb2, 0x18, - 0x23, 0x37, 0x8c, 0x98, 0x96, 0x5f, 0x71, 0x21, 0xa2, 0x0c, 0x8d, 0x57, 0x1b, 0xa1, 0xd0, 0xdc, 0x87, 0x0b, 0xdd, - 0xc7, 0x8f, 0x5a, 0x66, 0x6d, 0x3a, 0x93, 0x42, 0xb1, 0xa1, 0x32, 0x0f, 0xab, 0x18, 0x18, 0x4f, 0x46, 0xd7, 0x44, - 0xc0, 0x38, 0x5f, 0x37, 0x46, 0xa9, 0x81, 0x79, 0x74, 0xdc, 0x05, 0xe8, 0x15, 0xf9, 0x4f, 0xe9, 0xde, 0x3b, 0x82, - 0xdc, 0xd9, 0x12, 0xe2, 0xd6, 0x25, 0xcd, 0x0a, 0x9d, 0x42, 0x1e, 0x0d, 0x10, 0x54, 0x22, 0xf8, 0x1d, 0xd2, 0x76, - 0x68, 0xbe, 0x0e, 0xb9, 0xdb, 0xb2, 0x10, 0x3c, 0x6e, 0x2a, 0xb2, 0xa5, 0x09, 0xb8, 0x9c, 0x16, 0x56, 0xa8, 0x53, - 0x5e, 0x2f, 0x11, 0x1b, 0xf2, 0x41, 0xbc, 0x6d, 0xc9, 0x40, 0x53, 0xa7, 0x25, 0x46, 0x89, 0xce, 0x82, 0xef, 0x9e, - 0xa4, 0x1e, 0x62, 0x86, 0x76, 0x19, 0x1b, 0xe1, 0x55, 0x4e, 0x9b, 0x62, 0x42, 0x94, 0x9d, 0x30, 0xcd, 0xc3, 0x34, - 0xd3, 0xaa, 0xf7, 0x1f, 0x6d, 0x02, 0x24, 0x66, 0x71, 0xaf, 0x5f, 0xdc, 0x07, 0x89, 0x3b, 0x34, 0x69, 0x33, 0xab, - 0xca, 0x57, 0xe3, 0xa1, 0x9f, 0x2d, 0x36, 0x1d, 0x82, 0x99, 0x1b, 0x8c, 0x7d, 0x76, 0xe1, 0x0e, 0xbf, 0xc1, 0x3a, - 0x2f, 0x87, 0xfe, 0x0b, 0xa8, 0x90, 0xaa, 0xfd, 0x47, 0x1b, 0x22, 0xd7, 0x75, 0x08, 0x3b, 0xa5, 0x2d, 0x50, 0xfe, - 0x0e, 0x4f, 0xac, 0xc4, 0x22, 0x6a, 0x8d, 0x83, 0x25, 0x12, 0x4b, 0x18, 0xb5, 0x38, 0x32, 0x9e, 0xd8, 0x07, 0xf6, - 0xa6, 0xc2, 0x4f, 0x2d, 0x8c, 0x2b, 0x14, 0x27, 0x58, 0xde, 0x99, 0xf2, 0x60, 0x89, 0x94, 0xbe, 0x0b, 0x57, 0x62, - 0xa4, 0x1c, 0x00, 0x14, 0x88, 0xf2, 0xf4, 0x7c, 0x70, 0x22, 0x2b, 0x7f, 0x50, 0x42, 0x4e, 0xfd, 0xc2, 0xaf, 0x54, - 0x55, 0xf2, 0x34, 0x4f, 0x8b, 0xb5, 0xda, 0x3f, 0x39, 0x90, 0x6b, 0xf7, 0x07, 0x9d, 0x57, 0xd2, 0xe4, 0xb0, 0x57, - 0x71, 0x3b, 0xbe, 0xcc, 0x1f, 0xd2, 0x2b, 0x05, 0xee, 0xc2, 0x29, 0x94, 0x00, 0x8c, 0x8a, 0x4d, 0x2a, 0xe4, 0x07, - 0x12, 0x23, 0xe6, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0xa1, 0xde, 0xc9, 0x96, 0x90, 0xec, 0x2f, 0x45, 0x6f, 0x03, - 0xfe, 0x6f, 0x0e, 0x12, 0x94, 0x67, 0xb3, 0x20, 0x0e, 0x23, 0x15, 0xa6, 0x59, 0xce, 0x8e, 0xa4, 0x48, 0x59, 0xd9, - 0x70, 0xc2, 0xb5, 0x64, 0x15, 0x00, 0x76, 0x50, 0x6e, 0x2a, 0xcd, 0x7b, 0xa0, 0xe7, 0x3f, 0x14, 0x3e, 0x99, 0x12, - 0xd2, 0xca, 0x06, 0xb8, 0x3d, 0xeb, 0xd4, 0xe5, 0x5b, 0xcf, 0xf8, 0x5b, 0x68, 0xcc, 0x5d, 0x63, 0xe8, 0x1a, 0xe7, - 0xc1, 0x55, 0x5a, 0xbb, 0x78, 0x59, 0xc6, 0x38, 0x83, 0x75, 0x35, 0x88, 0xb3, 0x54, 0xbc, 0x57, 0x78, 0x16, 0xb7, - 0x0c, 0xb9, 0x70, 0xa3, 0x29, 0x13, 0x89, 0xda, 0xc4, 0x5b, 0x21, 0x21, 0xd0, 0x25, 0xb0, 0x40, 0x10, 0xb2, 0x07, - 0xdc, 0x80, 0xce, 0xb3, 0x46, 0x49, 0xe4, 0x7f, 0xc7, 0x6e, 0xe1, 0x3a, 0x19, 0x27, 0xe1, 0x02, 0x24, 0x53, 0xee, - 0x94, 0x6b, 0x1a, 0x0c, 0x60, 0x6a, 0xf6, 0xf9, 0xdc, 0xc7, 0x8f, 0x4c, 0xca, 0x1d, 0x96, 0x84, 0xd3, 0xa9, 0xcf, - 0x34, 0x29, 0xc7, 0x58, 0xf6, 0x99, 0xd3, 0x07, 0xb6, 0x88, 0x4f, 0xad, 0xa7, 0xdb, 0x0e, 0x56, 0xce, 0x01, 0x0a, - 0x9d, 0x3e, 0x20, 0x2e, 0x32, 0xa1, 0x42, 0x26, 0x5c, 0x13, 0xe7, 0x22, 0x3f, 0xb8, 0xe6, 0x38, 0x5c, 0x0e, 0x7d, - 0x66, 0xe2, 0x69, 0x80, 0x4f, 0x6e, 0x86, 0xcb, 0xe1, 0xd0, 0xa7, 0xa4, 0x60, 0x10, 0x65, 0x2d, 0x8c, 0x51, 0xfa, - 0x99, 0xea, 0x5d, 0xe4, 0xd4, 0x92, 0xf2, 0xf0, 0xc1, 0x32, 0x12, 0x6e, 0x0b, 0xf4, 0x81, 0x04, 0x24, 0x9d, 0xd5, - 0x33, 0xdd, 0x53, 0xe1, 0x96, 0xc2, 0x62, 0xb5, 0x5b, 0xc3, 0xd2, 0xf5, 0x2e, 0xd5, 0x73, 0x84, 0xb0, 0xe2, 0x06, - 0x63, 0xe5, 0x05, 0xed, 0x5d, 0xd5, 0x50, 0xc9, 0xc0, 0x8b, 0xe7, 0x90, 0x53, 0x0d, 0xf5, 0xa5, 0xe7, 0x4e, 0x83, - 0x30, 0x4e, 0xbc, 0x91, 0x7a, 0xd5, 0x7d, 0xe9, 0x69, 0x97, 0xf3, 0x44, 0xd3, 0xaf, 0x8c, 0xbf, 0xca, 0xd9, 0xbe, - 0x04, 0xa6, 0xc4, 0x64, 0x5f, 0x5b, 0xea, 0xc8, 0xa7, 0x67, 0x57, 0x3d, 0x81, 0x91, 0xb1, 0xce, 0x5f, 0x7b, 0x50, - 0xab, 0x94, 0x37, 0x0c, 0x13, 0x42, 0x42, 0xde, 0xb0, 0xbf, 0xea, 0x5d, 0x12, 0xb5, 0x7c, 0xbd, 0xdc, 0x20, 0xd3, - 0x90, 0xe4, 0xc4, 0x17, 0x43, 0xdd, 0x0b, 0xff, 0x50, 0x7a, 0x7e, 0x20, 0xfb, 0x36, 0x14, 0xc8, 0xf8, 0xe0, 0xeb, - 0x22, 0x07, 0xf2, 0x68, 0x93, 0xa4, 0x60, 0x58, 0x18, 0x84, 0x89, 0x02, 0xf1, 0xdb, 0xe0, 0x83, 0x83, 0xb2, 0x2d, - 0x34, 0xef, 0x55, 0xd3, 0x53, 0x8e, 0x05, 0x9e, 0x23, 0x2d, 0x45, 0xf9, 0x24, 0x84, 0x9b, 0x80, 0x50, 0xa4, 0x85, - 0x68, 0x4d, 0xdc, 0x03, 0x0f, 0x96, 0xaf, 0xc0, 0xbf, 0x49, 0x78, 0xbf, 0x48, 0xcf, 0x1f, 0x6d, 0xe2, 0x53, 0x41, - 0xd4, 0xdf, 0xc4, 0xb8, 0x96, 0xc0, 0xae, 0x70, 0x2a, 0x9f, 0xaa, 0xca, 0xa9, 0xa0, 0x44, 0x58, 0xb7, 0x80, 0x5e, - 0x35, 0xc1, 0xee, 0x46, 0x22, 0x32, 0x3e, 0x4f, 0x3f, 0x2e, 0x18, 0xb0, 0xd2, 0xd1, 0x83, 0x90, 0x4c, 0x19, 0x6f, - 0x95, 0x80, 0x5d, 0x35, 0x12, 0x0c, 0xc0, 0x5c, 0x9c, 0x47, 0x18, 0xa4, 0xd7, 0xc0, 0x48, 0x42, 0x9c, 0x32, 0x31, - 0x47, 0x23, 0x94, 0x53, 0xc5, 0x79, 0xc1, 0x62, 0x99, 0x60, 0xfc, 0x79, 0x18, 0x00, 0x4b, 0x55, 0x05, 0x2f, 0x89, - 0x80, 0xeb, 0xf3, 0xcb, 0x4f, 0xaa, 0x2a, 0xde, 0xb8, 0x5a, 0xc6, 0xe5, 0x31, 0x80, 0xe3, 0x70, 0x1a, 0xa8, 0xbd, - 0x81, 0xc7, 0x88, 0x4f, 0x63, 0x64, 0xe4, 0xc9, 0x5b, 0xb4, 0x11, 0x5a, 0x39, 0xd4, 0x20, 0x90, 0x11, 0xf5, 0xd3, - 0xd5, 0xfc, 0xda, 0xc9, 0x42, 0x4c, 0xea, 0xc2, 0x34, 0x07, 0x20, 0x89, 0x3c, 0x05, 0xd8, 0xf5, 0x1e, 0x6d, 0xdc, - 0xcc, 0x80, 0x4e, 0xbd, 0x50, 0xc9, 0x7a, 0x6e, 0x80, 0x60, 0x18, 0xa4, 0xd7, 0xb9, 0x3b, 0x6b, 0x3e, 0x5f, 0xd8, - 0x92, 0x54, 0xae, 0xa0, 0x3d, 0x5b, 0x8f, 0x5b, 0xad, 0x2d, 0x22, 0x6f, 0xee, 0x46, 0xb7, 0x64, 0xe4, 0x66, 0xc8, - 0x96, 0x70, 0xba, 0xaa, 0x10, 0x3d, 0x20, 0x00, 0x10, 0x69, 0x50, 0x95, 0xaf, 0xb2, 0x32, 0xc6, 0x67, 0x9b, 0x59, - 0xfa, 0xc0, 0xb7, 0xae, 0xd5, 0xa7, 0xcc, 0x22, 0x29, 0x23, 0x35, 0xe9, 0x6a, 0xf1, 0x96, 0xe9, 0xc5, 0xc5, 0xe9, - 0x05, 0xc5, 0x8d, 0x86, 0x93, 0x21, 0x4a, 0x41, 0xe3, 0xc6, 0x99, 0x61, 0xaa, 0xcb, 0xfa, 0x15, 0xa5, 0x77, 0x7f, - 0xe8, 0x72, 0x30, 0x58, 0x8e, 0x00, 0x96, 0xa3, 0x46, 0x00, 0xeb, 0x8a, 0x15, 0x01, 0x5e, 0x04, 0xb8, 0x90, 0x08, - 0x39, 0x10, 0xca, 0x82, 0xa9, 0x64, 0x5b, 0x28, 0x82, 0xa3, 0x41, 0x63, 0xa7, 0xa3, 0x11, 0xf5, 0x7a, 0x21, 0xb6, - 0x8a, 0xd2, 0x93, 0x03, 0xaa, 0x4d, 0x44, 0x91, 0x2a, 0x01, 0x18, 0x22, 0x98, 0x61, 0x0e, 0x05, 0x48, 0x03, 0xde, - 0x73, 0xf2, 0x8b, 0x8e, 0x35, 0x47, 0xe5, 0xb3, 0x73, 0x5a, 0x64, 0x78, 0xb0, 0x95, 0xda, 0x3f, 0xc1, 0xc4, 0x9e, - 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xc9, 0x01, 0x3d, 0x2a, 0xa5, 0x13, 0x91, 0x77, 0x22, 0xa4, 0x8e, 0x1d, 0xde, 0xc1, - 0xbd, 0x8e, 0x4a, 0x9c, 0xb0, 0x05, 0x94, 0xba, 0xa9, 0xaa, 0xcc, 0x39, 0x83, 0xc5, 0x63, 0xec, 0x41, 0x00, 0x1e, - 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xee, 0xae, 0x71, 0xe6, 0xe2, 0x8d, 0xbb, 0xd6, 0x1c, 0xfe, 0x2a, 0x3f, 0x6b, 0x71, - 0xf1, 0xac, 0x8d, 0xf8, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x19, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, 0x4c, 0x2c, - 0xee, 0x78, 0xcb, 0xe2, 0x8e, 0x77, 0x2c, 0xae, 0xcf, 0x17, 0x52, 0xc9, 0x40, 0x17, 0xa1, 0xc7, 0x74, 0x06, 0x3c, - 0xce, 0x8f, 0x74, 0xf8, 0x39, 0x43, 0x38, 0x99, 0xb1, 0x0f, 0x16, 0xc3, 0x5b, 0x60, 0x55, 0x07, 0x17, 0x09, 0x10, - 0xd5, 0x89, 0x67, 0xa7, 0x6e, 0x24, 0x49, 0x06, 0x34, 0xbf, 0x3c, 0x5f, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x5b, - 0x66, 0x3a, 0xdb, 0x31, 0xd3, 0x51, 0xe1, 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x94, 0x27, 0x05, 0x7b, 0x10, 0xbc, 0x28, - 0x70, 0xcb, 0x14, 0xf7, 0xe1, 0x76, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x1b, 0xc7, 0xab, 0x30, 0x02, 0x33, 0x04, 0xe8, - 0xe6, 0x7e, 0x5b, 0x6a, 0xee, 0x05, 0x3c, 0xc2, 0xd9, 0xd6, 0xcd, 0x94, 0xbf, 0x97, 0xb7, 0x54, 0xa3, 0xd5, 0xa2, - 0x1a, 0x0b, 0x37, 0x49, 0x58, 0x84, 0x40, 0x77, 0x21, 0x15, 0xc6, 0x7f, 0xc8, 0x36, 0xab, 0xc1, 0x21, 0xbe, 0x84, - 0xd5, 0x11, 0x43, 0x2f, 0x80, 0x05, 0x23, 0xbd, 0x63, 0xa0, 0x6f, 0xa4, 0x68, 0xa9, 0x51, 0x06, 0xf8, 0x1f, 0xf0, - 0xb8, 0x6a, 0x91, 0xe4, 0xcf, 0xeb, 0x1c, 0xe9, 0xd6, 0xc2, 0x1d, 0x9f, 0x83, 0xb5, 0x8b, 0xd6, 0x30, 0xc0, 0x73, - 0x45, 0x8e, 0x8d, 0x1a, 0x11, 0x4f, 0x38, 0xca, 0x91, 0x24, 0x62, 0x49, 0x6e, 0x17, 0x0c, 0x21, 0x05, 0x5c, 0x73, - 0x72, 0xb5, 0x69, 0xa4, 0x07, 0x53, 0x4f, 0xaf, 0x60, 0x4d, 0x40, 0x6d, 0x7e, 0xaf, 0x9f, 0x09, 0xdd, 0x7c, 0xc3, - 0x39, 0xd2, 0x41, 0x1d, 0x7a, 0x09, 0x49, 0xcf, 0x6d, 0x71, 0x99, 0x1e, 0x44, 0x40, 0xb5, 0x40, 0x79, 0xf8, 0x78, - 0x8a, 0xbf, 0x9c, 0xab, 0xf4, 0xf1, 0x10, 0x7f, 0x35, 0xae, 0x32, 0x55, 0x55, 0x49, 0x8a, 0x20, 0xcd, 0x59, 0xed, - 0x17, 0xf6, 0x13, 0x19, 0x65, 0xdf, 0x63, 0xdb, 0xf0, 0x05, 0x7e, 0xf8, 0x68, 0x13, 0x43, 0x18, 0x02, 0x79, 0x0e, - 0x81, 0x15, 0xe9, 0x69, 0x6d, 0xf9, 0x74, 0x4b, 0xf9, 0x50, 0xff, 0x83, 0x09, 0x3f, 0xee, 0x92, 0x30, 0xa7, 0x29, - 0x45, 0x19, 0xc8, 0xf5, 0xd0, 0x0b, 0xdc, 0xe8, 0xf6, 0x9a, 0x6e, 0x21, 0x9a, 0x24, 0xe4, 0x7d, 0x90, 0x0b, 0x07, - 0x6e, 0x8b, 0x36, 0x20, 0x89, 0xa4, 0xa0, 0xba, 0xe5, 0x84, 0xbe, 0xf7, 0x5d, 0x24, 0xf1, 0x77, 0x85, 0x6b, 0x2c, - 0x5f, 0x90, 0xc2, 0x87, 0xae, 0x1f, 0x6d, 0x34, 0x56, 0xed, 0xa6, 0x34, 0xdb, 0x12, 0x03, 0x09, 0xcb, 0x83, 0x57, - 0xe2, 0xf9, 0xd8, 0xeb, 0xa0, 0x91, 0xc7, 0x30, 0x5c, 0x9b, 0x8f, 0x36, 0xc9, 0xa9, 0x3a, 0x77, 0xa3, 0x0f, 0x6c, - 0x6c, 0x8e, 0xbc, 0x68, 0xe4, 0x03, 0xf3, 0x38, 0xf4, 0xdd, 0xe0, 0x03, 0x7f, 0x34, 0xc3, 0x65, 0x82, 0x66, 0x5b, - 0x77, 0xde, 0xa0, 0x05, 0x4c, 0x48, 0x90, 0x88, 0x5c, 0x6d, 0x0d, 0x14, 0x94, 0xf3, 0x81, 0xb8, 0xd6, 0xe7, 0x8c, - 0x62, 0x5e, 0xcb, 0x00, 0xaf, 0x03, 0xb0, 0x24, 0x83, 0x30, 0x0e, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, 0xf2, 0x54, 0x49, - 0x8f, 0x96, 0xe5, 0x21, 0xbe, 0xc6, 0x1e, 0x7e, 0xfb, 0xe7, 0xa0, 0xe4, 0x3e, 0x9f, 0xcb, 0x7a, 0xf9, 0xb4, 0x19, - 0x42, 0xa9, 0x49, 0xee, 0x83, 0xf7, 0xf8, 0x38, 0x67, 0x30, 0xb7, 0x7f, 0x5a, 0x6e, 0xec, 0xc6, 0xf1, 0x72, 0xce, - 0xc6, 0xa4, 0x0c, 0x3b, 0xcd, 0x07, 0x55, 0xbc, 0x87, 0xc8, 0x03, 0xfb, 0x79, 0xd9, 0x38, 0x3e, 0x7c, 0x01, 0x66, - 0x7c, 0xc0, 0x50, 0x86, 0x93, 0x89, 0x9a, 0x8b, 0x02, 0xee, 0x68, 0xe6, 0x1c, 0xfe, 0xbc, 0x7c, 0xfd, 0xca, 0x7e, - 0x9d, 0x35, 0x0e, 0x80, 0x31, 0x16, 0x36, 0x49, 0x9c, 0x2f, 0x96, 0xc6, 0x2b, 0x66, 0x34, 0x71, 0x83, 0xed, 0xd3, - 0xb9, 0x2c, 0x6c, 0xf1, 0x05, 0x63, 0x63, 0x60, 0xb8, 0x8d, 0x4a, 0xe9, 0xb5, 0xcf, 0x6e, 0x58, 0x66, 0xef, 0x54, - 0xfd, 0x58, 0x4d, 0x0b, 0x0c, 0xc8, 0xca, 0x75, 0x8f, 0x9c, 0xab, 0x93, 0xa6, 0x34, 0xc0, 0x39, 0xf0, 0x99, 0xcb, - 0x47, 0xac, 0x74, 0xa4, 0x06, 0x86, 0x2a, 0x0d, 0x60, 0xeb, 0xc8, 0x4e, 0xb7, 0x94, 0x77, 0x00, 0x51, 0x6f, 0x19, - 0x9b, 0xe1, 0xe8, 0x1d, 0x48, 0x60, 0xc1, 0xe1, 0xe4, 0xc3, 0xc9, 0xd3, 0x72, 0xa9, 0xc9, 0x36, 0x88, 0xd5, 0x89, - 0xda, 0x54, 0x12, 0xd2, 0x08, 0x17, 0x00, 0xf4, 0x85, 0x11, 0xe2, 0xaa, 0xda, 0xb5, 0x51, 0x8a, 0x33, 0x1f, 0x62, - 0x7a, 0xf7, 0x80, 0xc5, 0xf1, 0x56, 0x80, 0x65, 0x8b, 0x6e, 0xa8, 0x79, 0xed, 0x22, 0x3c, 0xf2, 0x72, 0xc3, 0x36, - 0x80, 0x25, 0xc0, 0x09, 0x96, 0xbf, 0x85, 0xe4, 0xe5, 0x7a, 0xce, 0x8d, 0x38, 0xa3, 0xe9, 0x50, 0xe5, 0x06, 0x76, - 0xdb, 0xde, 0xaf, 0x54, 0x3e, 0xa8, 0x02, 0x99, 0xae, 0x1d, 0x9a, 0x56, 0x40, 0xbd, 0x15, 0xa9, 0x12, 0x76, 0x20, - 0xc6, 0x54, 0xc2, 0xaf, 0x6c, 0x32, 0x61, 0xa3, 0x24, 0xd6, 0x85, 0x8c, 0x29, 0x0b, 0xa9, 0x0e, 0x4a, 0xbb, 0x07, - 0x3d, 0xf5, 0x07, 0x08, 0x2c, 0x23, 0x22, 0x0f, 0xf2, 0x01, 0x89, 0x3b, 0x53, 0x3d, 0x98, 0xa8, 0xc7, 0x22, 0x88, - 0xf8, 0x57, 0x40, 0x0a, 0x5d, 0x53, 0x8e, 0x43, 0xe3, 0xf4, 0x27, 0xdf, 0x17, 0x61, 0x66, 0xea, 0xb9, 0x1b, 0x15, - 0xed, 0x3a, 0xbe, 0x1b, 0xe7, 0x75, 0xcb, 0xb1, 0x53, 0xd5, 0x00, 0x87, 0xe6, 0x0f, 0xa5, 0x6d, 0x4c, 0x04, 0xaa, - 0xa7, 0x9e, 0xbd, 0x7d, 0xf1, 0xdd, 0xab, 0x97, 0xfb, 0x62, 0x04, 0xec, 0xb2, 0x09, 0x5d, 0x2e, 0x83, 0x1d, 0x9d, - 0xfe, 0xf4, 0xc3, 0xfd, 0xba, 0x6d, 0x38, 0xcf, 0x1c, 0xd5, 0x20, 0x1b, 0x74, 0x09, 0x2f, 0x8e, 0xc2, 0x1b, 0x16, - 0x7d, 0x32, 0x18, 0xe4, 0xce, 0xeb, 0x87, 0xfb, 0xf6, 0xc7, 0x57, 0x3f, 0xec, 0x3d, 0xd4, 0x23, 0xc7, 0x06, 0xdc, - 0x9e, 0x84, 0x8b, 0x7b, 0xcc, 0xae, 0xa9, 0x1a, 0xea, 0xc8, 0x0f, 0x63, 0xb6, 0x65, 0x04, 0x2f, 0xce, 0xde, 0x9e, - 0x23, 0xb8, 0x72, 0x16, 0x84, 0xba, 0xfa, 0xb4, 0xc9, 0xff, 0xf8, 0xee, 0xd5, 0xf9, 0xb9, 0x6a, 0x60, 0x4a, 0xee, - 0x58, 0xee, 0x9d, 0x6f, 0xe2, 0x3b, 0x28, 0x4e, 0xed, 0x5e, 0x27, 0xaa, 0x46, 0x17, 0xe9, 0xe2, 0x6c, 0xa8, 0xac, - 0xb2, 0xcd, 0x39, 0xb5, 0xe3, 0x5f, 0xa6, 0xdb, 0xef, 0x5e, 0xf3, 0xaa, 0xc1, 0x47, 0xbb, 0x49, 0x6a, 0xa1, 0x64, - 0xee, 0x05, 0xd7, 0x35, 0xa5, 0xee, 0xba, 0xa6, 0x14, 0xae, 0x8f, 0x15, 0xfc, 0xb8, 0x0c, 0xe7, 0x12, 0x3b, 0xc2, - 0xd6, 0x77, 0x83, 0x4b, 0xba, 0xc3, 0x7d, 0xc2, 0xa0, 0x79, 0x4a, 0x95, 0xf2, 0xa8, 0x6b, 0x8a, 0xf9, 0xc5, 0x2b, - 0x83, 0xed, 0xc8, 0x07, 0xcb, 0x7b, 0x26, 0xab, 0x21, 0x8b, 0xac, 0x2a, 0xf7, 0x9b, 0xe9, 0x95, 0x6e, 0x05, 0xd4, - 0x8c, 0x54, 0x37, 0x9c, 0xa6, 0x2c, 0xdc, 0x31, 0x98, 0xb3, 0x9b, 0xc3, 0x30, 0x49, 0xc2, 0x79, 0xc7, 0xb1, 0x17, - 0x6b, 0x55, 0xe9, 0x0a, 0x61, 0x07, 0xb7, 0xb6, 0xef, 0xfc, 0xfa, 0xef, 0x12, 0x9a, 0xa7, 0xf2, 0xeb, 0x84, 0xcd, - 0x17, 0x2c, 0x72, 0x93, 0x65, 0xc4, 0x52, 0xe5, 0xd7, 0xff, 0x79, 0x51, 0xba, 0xd8, 0x77, 0xe5, 0x36, 0xc4, 0xd2, - 0xcb, 0x4d, 0xae, 0xfd, 0x70, 0xf5, 0x20, 0xf7, 0xab, 0xbb, 0xa3, 0xf2, 0xcc, 0x9b, 0xce, 0xb2, 0xda, 0xa7, 0xc9, - 0x8e, 0xb9, 0x89, 0xd1, 0x93, 0x3e, 0x40, 0x39, 0x0b, 0x57, 0x9d, 0x5f, 0xff, 0x9d, 0x09, 0x6c, 0xee, 0xdc, 0x75, - 0xf5, 0x03, 0x2d, 0xae, 0x68, 0x7d, 0x9d, 0xca, 0x12, 0xc3, 0xfb, 0xca, 0x02, 0x57, 0x0a, 0x69, 0x57, 0x56, 0x75, - 0x73, 0x3b, 0xe6, 0xf4, 0x8d, 0x37, 0x9d, 0x7d, 0xea, 0xa4, 0x00, 0xa0, 0x77, 0xce, 0x0a, 0x2a, 0x7d, 0x86, 0x69, - 0x0d, 0x3a, 0xfb, 0x2f, 0xd8, 0x27, 0xce, 0xeb, 0xae, 0x29, 0x7d, 0x8e, 0xd9, 0x70, 0xc9, 0xed, 0xf9, 0x60, 0x90, - 0xa5, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0x69, 0xa5, 0x84, 0xb3, 0x17, 0x1d, 0x5b, 0xa7, 0x90, 0x3d, 0x7b, 0x00, - 0x04, 0x6d, 0xdc, 0x6b, 0xc0, 0xb1, 0x1d, 0x5f, 0x93, 0xab, 0x5a, 0xe5, 0xdb, 0x15, 0x64, 0x0d, 0xa5, 0x98, 0xce, - 0x34, 0xd3, 0x1a, 0x1a, 0xf5, 0xc3, 0x59, 0x45, 0xee, 0x82, 0x94, 0x04, 0x0a, 0x6a, 0x4c, 0x40, 0xe8, 0x52, 0xba, - 0x45, 0xdf, 0xb8, 0xfe, 0xcd, 0x7e, 0x17, 0xaa, 0xed, 0x14, 0x0c, 0x49, 0xf3, 0x9f, 0x47, 0xbc, 0x91, 0x2e, 0xdf, - 0x9b, 0x76, 0xaf, 0xdc, 0x84, 0x45, 0xd7, 0x33, 0xf0, 0xe9, 0x15, 0xd2, 0x03, 0x88, 0x96, 0xbb, 0x0b, 0x29, 0x17, - 0xd8, 0xd2, 0x1a, 0x34, 0x9a, 0x63, 0xb8, 0xdf, 0x86, 0xbb, 0x3f, 0x13, 0xe6, 0xee, 0xbc, 0x02, 0xaf, 0xcb, 0xdf, - 0x0d, 0x7b, 0xef, 0xa2, 0x4c, 0xff, 0x8f, 0xbd, 0xff, 0x13, 0xb1, 0xf7, 0xce, 0xef, 0xfc, 0x96, 0x85, 0xfd, 0x3f, - 0x80, 0xe5, 0x3b, 0xac, 0xf7, 0x8a, 0x63, 0x7a, 0x4d, 0x73, 0x7b, 0x42, 0xb9, 0x2a, 0xe3, 0xd5, 0x8a, 0x82, 0x95, - 0x87, 0x54, 0xe3, 0x96, 0x83, 0x2e, 0x22, 0xfb, 0x1d, 0x47, 0xf9, 0xf7, 0x47, 0xf4, 0x31, 0xe5, 0xa1, 0x92, 0x30, - 0x7d, 0xe7, 0x95, 0x11, 0x17, 0x66, 0xe2, 0xae, 0xdc, 0xdb, 0x7d, 0xf0, 0x8e, 0x18, 0xec, 0xd7, 0x2b, 0xf7, 0xb6, - 0x6e, 0xb0, 0x5b, 0xd1, 0x6b, 0xf9, 0x63, 0xa7, 0xe0, 0xcb, 0xd3, 0x41, 0x47, 0x1e, 0x63, 0x10, 0xb3, 0xe4, 0x14, - 0x0a, 0x7b, 0x8f, 0x36, 0x0f, 0xca, 0x15, 0xd3, 0x01, 0x78, 0x39, 0x4b, 0x03, 0x0f, 0x0b, 0x03, 0xf7, 0xe2, 0xeb, - 0x30, 0xb8, 0xcf, 0xc8, 0x7f, 0x04, 0xe1, 0xcf, 0x6f, 0x1e, 0x3a, 0x7e, 0xae, 0x32, 0x76, 0x2c, 0x2d, 0x0f, 0x1e, - 0x0b, 0xcb, 0xa3, 0xef, 0xd6, 0xcb, 0xea, 0x4b, 0x84, 0x16, 0x69, 0x2c, 0x23, 0x42, 0xab, 0x80, 0x5e, 0x45, 0x01, - 0x1d, 0x97, 0x20, 0xb9, 0x98, 0xa0, 0xf4, 0xd5, 0x36, 0xa7, 0xae, 0x37, 0x77, 0x3b, 0x75, 0x5d, 0xec, 0xe5, 0xd4, - 0xf5, 0xe6, 0xb3, 0x3b, 0x75, 0xbd, 0x92, 0x9d, 0xba, 0xe0, 0x50, 0xbd, 0x62, 0x7b, 0xf9, 0xd0, 0x08, 0x3b, 0xd7, - 0x70, 0x15, 0xf7, 0x1c, 0x2e, 0x6e, 0x8b, 0x47, 0x33, 0x06, 0xfa, 0x0b, 0xbe, 0xff, 0xfd, 0x70, 0x0a, 0xae, 0x2e, - 0xdb, 0x9d, 0x59, 0x3e, 0x97, 0x2b, 0x8b, 0x1f, 0x4e, 0x55, 0x29, 0x45, 0x4b, 0x20, 0x52, 0xb4, 0x40, 0x58, 0x9a, - 0x9f, 0xd7, 0xce, 0xf3, 0x4b, 0xa7, 0xdb, 0x74, 0x20, 0xc4, 0x19, 0x88, 0xa4, 0xb1, 0xc0, 0xee, 0x36, 0x9b, 0x50, - 0xb0, 0x92, 0x0a, 0x1a, 0x50, 0xe0, 0x49, 0x05, 0x2d, 0x28, 0x18, 0x49, 0x05, 0x47, 0x50, 0x30, 0x96, 0x0a, 0x8e, - 0xa1, 0xe0, 0x46, 0x4d, 0x2f, 0x83, 0xcc, 0x65, 0xed, 0x58, 0xbf, 0x2a, 0x64, 0xe7, 0xca, 0xf4, 0x27, 0xa2, 0xca, - 0xb1, 0x21, 0x42, 0x45, 0x9b, 0x87, 0x3a, 0x77, 0x8e, 0x1a, 0x7c, 0x31, 0x80, 0x20, 0x2e, 0xa0, 0x4e, 0x32, 0x40, - 0x19, 0x47, 0x35, 0x9b, 0xe2, 0xb5, 0xda, 0xc9, 0x5c, 0xbc, 0x6c, 0xa3, 0x21, 0x5c, 0xa6, 0x3a, 0xe8, 0xc0, 0x2b, - 0x2a, 0xb7, 0x9e, 0xce, 0xb2, 0xb8, 0x91, 0xcb, 0x5e, 0xee, 0x07, 0xdf, 0x84, 0xe8, 0xf9, 0x60, 0x14, 0xf5, 0x12, - 0x6f, 0xa6, 0x56, 0x12, 0x82, 0x9b, 0xb3, 0x88, 0x97, 0x28, 0x3e, 0xa0, 0xa0, 0x1f, 0x5c, 0xd7, 0xcd, 0x43, 0x5b, - 0xf2, 0x28, 0xab, 0x34, 0xfa, 0x79, 0x16, 0xbc, 0x92, 0x04, 0xac, 0x4b, 0x23, 0x71, 0xa7, 0x9d, 0x99, 0x41, 0xda, - 0xd5, 0xce, 0x14, 0xa2, 0x91, 0x9f, 0x8e, 0x3b, 0x0b, 0x63, 0x35, 0x63, 0x41, 0x67, 0xc2, 0xfd, 0x0f, 0x60, 0xfd, - 0xc9, 0xbc, 0x74, 0xae, 0x0b, 0xbb, 0x68, 0xdc, 0x13, 0xf9, 0x5b, 0x1a, 0xa5, 0x99, 0x6d, 0xa5, 0xdc, 0xa4, 0x57, - 0x93, 0x35, 0xaf, 0x9f, 0xc3, 0x00, 0xf3, 0x25, 0x1b, 0x2e, 0xa7, 0xca, 0x59, 0x38, 0xbd, 0xd3, 0xd8, 0x52, 0x7e, - 0x05, 0xa3, 0x54, 0xc9, 0xc4, 0xc4, 0x14, 0xdb, 0x9b, 0x7f, 0x8b, 0x1e, 0xd3, 0x62, 0xfd, 0x04, 0xc6, 0xa6, 0x24, - 0x84, 0xdc, 0xe0, 0x3b, 0x00, 0x6d, 0xc9, 0x9c, 0xf1, 0x0c, 0xe0, 0x27, 0x3d, 0x5f, 0xb8, 0xd2, 0x78, 0xfa, 0xdf, - 0xb3, 0x38, 0x76, 0xa7, 0xa2, 0x7e, 0x75, 0x9c, 0xe0, 0xd9, 0x9b, 0xc9, 0x98, 0x11, 0x80, 0xa0, 0xad, 0xf4, 0x2a, - 0x46, 0xaa, 0xe0, 0x3b, 0x03, 0xc6, 0xdb, 0xb0, 0x68, 0xb9, 0x45, 0xa7, 0x67, 0xc1, 0xf2, 0x14, 0x8d, 0x2b, 0x01, - 0x89, 0xdc, 0x30, 0xbf, 0x5c, 0x98, 0xb8, 0xd3, 0x72, 0x11, 0xad, 0x75, 0x2a, 0x8f, 0x2d, 0xb3, 0x6d, 0x2c, 0x14, - 0x7e, 0x8a, 0xb1, 0x9e, 0x1f, 0x4e, 0x7f, 0x57, 0x4b, 0xbd, 0x1d, 0x16, 0x96, 0xe7, 0x81, 0x11, 0x24, 0x03, 0x0b, - 0x61, 0xac, 0x58, 0x00, 0xc2, 0x4e, 0x90, 0xcc, 0x4c, 0x8c, 0x29, 0xa3, 0x35, 0x02, 0xdd, 0xb0, 0x70, 0x6d, 0x37, - 0xe5, 0x48, 0x5a, 0x9d, 0x68, 0x3a, 0x74, 0x35, 0xa7, 0x71, 0x6c, 0x88, 0x3f, 0x96, 0xdd, 0xd2, 0x53, 0xec, 0x41, - 0x19, 0x7b, 0x37, 0x9b, 0x49, 0x18, 0x24, 0xe6, 0xc4, 0x9d, 0x7b, 0xfe, 0x6d, 0x67, 0x1e, 0x06, 0x61, 0xbc, 0x70, - 0x47, 0xac, 0x9b, 0x2b, 0x0d, 0xba, 0x18, 0xa3, 0x91, 0x87, 0x09, 0x72, 0xac, 0x46, 0xc4, 0xe6, 0xd4, 0x3a, 0x0b, - 0xc1, 0x38, 0xf1, 0xd9, 0x3a, 0xe5, 0x9f, 0x2f, 0x54, 0xa6, 0xaa, 0xb8, 0xe5, 0xa8, 0x05, 0x48, 0xc0, 0x78, 0x7c, - 0x47, 0x88, 0x6a, 0xdc, 0xe5, 0x57, 0x91, 0x8e, 0xd5, 0x68, 0x45, 0x6c, 0xae, 0x58, 0xad, 0xad, 0x9d, 0x47, 0xe1, - 0xaa, 0x0f, 0xa3, 0xc5, 0xc6, 0x66, 0xcc, 0xfc, 0x09, 0xbe, 0x31, 0x31, 0xa4, 0x84, 0xe8, 0xc7, 0x44, 0x65, 0x03, - 0xf4, 0xc6, 0xe6, 0x5d, 0x78, 0xdd, 0x69, 0x28, 0x76, 0x77, 0xee, 0x05, 0x26, 0x4d, 0xe7, 0xd8, 0x5e, 0x48, 0x7d, - 0xc9, 0xf0, 0xd3, 0x37, 0x58, 0xdd, 0x51, 0xec, 0x2e, 0x08, 0x95, 0x27, 0x7e, 0xb8, 0xea, 0xcc, 0xbc, 0xf1, 0x98, - 0x05, 0x5d, 0x1c, 0x73, 0x56, 0xc8, 0x7c, 0xdf, 0x5b, 0xc4, 0x5e, 0xdc, 0x9d, 0xbb, 0x6b, 0xde, 0xeb, 0xe1, 0xb6, - 0x5e, 0x9b, 0xbc, 0xd7, 0xe6, 0xde, 0xbd, 0x4a, 0xdd, 0x40, 0xf8, 0x0a, 0xea, 0x87, 0x0f, 0xad, 0xa5, 0xd8, 0xa5, - 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x62, 0x9b, 0xb9, 0x1b, 0x4d, 0xbd, 0xa0, 0x63, 0xa7, 0xd6, 0xcd, 0x86, 0x36, 0xc6, - 0xc3, 0x76, 0xbb, 0x9d, 0x5a, 0x63, 0xf1, 0x64, 0x8f, 0xc7, 0xa9, 0x35, 0x12, 0x4f, 0x93, 0x89, 0x6d, 0x4f, 0x26, - 0xa9, 0xe5, 0x89, 0x82, 0x66, 0x63, 0x34, 0x6e, 0x36, 0x52, 0x6b, 0x25, 0xd5, 0x48, 0x2d, 0xc6, 0x9f, 0x22, 0x36, - 0xee, 0xe2, 0x46, 0xe2, 0x8e, 0x50, 0xc7, 0xb6, 0x9d, 0x22, 0x06, 0xb8, 0x2c, 0xe0, 0x26, 0xd4, 0x67, 0x5d, 0x6d, - 0xf6, 0xae, 0xa9, 0xe4, 0x9f, 0x1b, 0x8d, 0x6a, 0xeb, 0x8d, 0xdd, 0xe8, 0xc3, 0x95, 0x22, 0xcd, 0xc2, 0x75, 0xa9, - 0xda, 0x46, 0x80, 0xc1, 0x5c, 0x77, 0x20, 0x56, 0x77, 0x77, 0x18, 0x46, 0x70, 0x66, 0x23, 0x77, 0xec, 0x2d, 0xe3, - 0x8e, 0xd3, 0x58, 0xac, 0x45, 0x11, 0xdf, 0xeb, 0x79, 0x01, 0x9e, 0xbd, 0x4e, 0x1c, 0xfa, 0xde, 0x58, 0x14, 0x6d, - 0x3b, 0x4b, 0x4e, 0x43, 0xef, 0x62, 0xa4, 0x3a, 0x0f, 0xe3, 0x2d, 0xba, 0xbe, 0xaf, 0x58, 0xcd, 0x58, 0x61, 0x6e, - 0x8c, 0x3a, 0x74, 0xc5, 0x8e, 0x09, 0x2e, 0x18, 0x95, 0xce, 0x39, 0x5c, 0xac, 0xb3, 0x3d, 0xef, 0x1c, 0x2d, 0xd6, - 0xe9, 0x57, 0x73, 0x36, 0xf6, 0x5c, 0x45, 0xcb, 0x77, 0x93, 0x63, 0x83, 0x9e, 0x5d, 0xdf, 0x6c, 0xd9, 0xa6, 0xe2, - 0x58, 0x40, 0x4e, 0x83, 0x07, 0xde, 0x7c, 0x11, 0x46, 0x89, 0x1b, 0x24, 0x69, 0x3a, 0xb8, 0x4a, 0xd3, 0xee, 0x85, - 0xa7, 0x5d, 0xfe, 0x5d, 0x23, 0x5a, 0x48, 0x76, 0x29, 0xa9, 0x7e, 0x65, 0xbc, 0x62, 0xb2, 0x0d, 0x2d, 0x90, 0x31, - 0xb4, 0x9f, 0x95, 0x2b, 0x13, 0xbd, 0xad, 0x56, 0x26, 0x20, 0x67, 0xd5, 0xc9, 0x24, 0xb7, 0x58, 0x05, 0x29, 0x10, - 0x54, 0x78, 0xc5, 0x7a, 0x17, 0x92, 0x41, 0x2e, 0x30, 0x3d, 0x58, 0x99, 0x02, 0x0a, 0xbc, 0xdc, 0xc6, 0x7b, 0x5e, - 0xdc, 0xcd, 0x7b, 0xfe, 0x23, 0xd9, 0x87, 0xf7, 0xbc, 0xf8, 0xec, 0xbc, 0xe7, 0xcb, 0x6a, 0x40, 0x81, 0x8b, 0xb0, - 0xa7, 0x66, 0x56, 0x14, 0x40, 0x9a, 0x22, 0x0a, 0xd5, 0xfb, 0x32, 0xf9, 0xad, 0x9e, 0xdd, 0xa2, 0x37, 0x4a, 0x3e, - 0x4f, 0x94, 0x1b, 0xee, 0x5e, 0x6f, 0x83, 0xde, 0x77, 0x91, 0xfc, 0x3c, 0x99, 0xf4, 0x5e, 0x86, 0x52, 0x41, 0xf6, - 0xc4, 0x0d, 0x4c, 0x0b, 0x61, 0x15, 0xe9, 0x4d, 0x66, 0x02, 0x0c, 0x89, 0x27, 0x21, 0x2a, 0x1b, 0xf9, 0x7b, 0x8d, - 0x33, 0x43, 0xfc, 0x6e, 0x71, 0x08, 0x5a, 0xe6, 0xf9, 0x22, 0x62, 0x6f, 0x54, 0xd4, 0xa5, 0x53, 0x96, 0xf0, 0x60, - 0x59, 0xcf, 0x6f, 0xdf, 0x8c, 0xb5, 0x8b, 0x50, 0x4f, 0xbd, 0xf8, 0x6d, 0x39, 0xf2, 0x85, 0x10, 0x7e, 0xc9, 0xd3, - 0x49, 0xb9, 0x31, 0xbd, 0x14, 0xe0, 0x0e, 0x5f, 0x53, 0xf3, 0xd3, 0xc2, 0x4c, 0x3b, 0x72, 0x43, 0x9e, 0xe1, 0xba, - 0x42, 0x8c, 0xb9, 0x87, 0xf8, 0x86, 0x73, 0x79, 0x98, 0xb4, 0x1b, 0x03, 0x86, 0x8d, 0xa9, 0xb9, 0x37, 0x4e, 0x53, - 0xbd, 0x2b, 0x00, 0x21, 0x11, 0x5a, 0x76, 0x17, 0x13, 0x17, 0xe7, 0x57, 0x3f, 0x6e, 0x05, 0x45, 0x26, 0x4e, 0x17, - 0x60, 0x34, 0xc8, 0x0d, 0xa2, 0x38, 0xcc, 0x54, 0x85, 0xc0, 0x47, 0xc6, 0xa4, 0xd2, 0x84, 0xc0, 0xca, 0x4d, 0x36, - 0xc1, 0x2e, 0x2c, 0x48, 0xd5, 0xdb, 0x85, 0x80, 0x83, 0x56, 0x8f, 0x10, 0xde, 0x4f, 0xc8, 0xea, 0x08, 0xed, 0xf0, - 0x3a, 0xf8, 0x90, 0xaa, 0x19, 0xef, 0x87, 0xdb, 0xaf, 0x7f, 0x72, 0x00, 0x0d, 0xfa, 0x25, 0x49, 0xdc, 0x1d, 0xce, - 0x1a, 0xc0, 0x4a, 0xc4, 0x2b, 0xc3, 0x8a, 0x57, 0xca, 0x93, 0x8d, 0x08, 0x8d, 0x99, 0xb8, 0x0b, 0x13, 0x44, 0x3f, - 0x88, 0x7b, 0x39, 0xc6, 0x93, 0xa2, 0x70, 0x76, 0x97, 0x31, 0xe0, 0x46, 0x14, 0x2d, 0x20, 0xfe, 0xe9, 0x8e, 0x96, - 0x51, 0x1c, 0x46, 0x9d, 0x45, 0xe8, 0x05, 0x09, 0x8b, 0x52, 0x04, 0xd5, 0x25, 0xc2, 0x47, 0x80, 0xe7, 0x6a, 0x13, - 0x2e, 0xdc, 0x91, 0x97, 0xdc, 0x76, 0x6c, 0xce, 0x52, 0xd8, 0x5d, 0xce, 0x1d, 0xd8, 0xb5, 0xf5, 0x3b, 0x1c, 0x9a, - 0x4f, 0x91, 0xf1, 0x8b, 0xaa, 0xec, 0x8c, 0xbc, 0xcd, 0xbb, 0xd2, 0x5b, 0x0a, 0x0e, 0x0a, 0xec, 0x87, 0x1b, 0x99, - 0x53, 0xc0, 0xf2, 0xb0, 0xd4, 0xf6, 0x98, 0x4d, 0x0d, 0xc4, 0xda, 0x60, 0x7b, 0x20, 0xfe, 0x58, 0x2d, 0x5d, 0xb1, - 0xeb, 0x8b, 0x81, 0xe3, 0xd1, 0xf7, 0x19, 0x59, 0xc7, 0x85, 0x54, 0xda, 0xc6, 0x3e, 0x35, 0x87, 0x6c, 0x12, 0x46, - 0x8c, 0x12, 0xc9, 0x38, 0xed, 0xc5, 0x7a, 0xff, 0xee, 0x77, 0x4f, 0xbf, 0xbe, 0x9f, 0x20, 0x4c, 0x34, 0xd1, 0x99, - 0x7e, 0x47, 0x6f, 0x55, 0x7a, 0x06, 0xac, 0x21, 0x41, 0x7e, 0x44, 0x9e, 0x90, 0x10, 0x04, 0xa4, 0x36, 0x5e, 0xf7, - 0x22, 0xe4, 0x34, 0x2f, 0x62, 0xbe, 0x9b, 0x78, 0x37, 0x82, 0x67, 0x6c, 0x1e, 0x2d, 0xd6, 0x62, 0x8d, 0x91, 0xe0, - 0xdd, 0x63, 0x91, 0x4a, 0x43, 0x11, 0x8b, 0x54, 0x2e, 0xc6, 0x45, 0xea, 0x56, 0x66, 0x23, 0x42, 0x58, 0x96, 0x28, - 0x7d, 0x6b, 0xb1, 0x96, 0x49, 0x74, 0xde, 0x2c, 0xa3, 0xd4, 0xe5, 0xd8, 0xe3, 0x73, 0x6f, 0x3c, 0xf6, 0x59, 0x5a, - 0x58, 0xe8, 0xe2, 0x5a, 0x4a, 0xc0, 0xc9, 0xe0, 0xe0, 0x0e, 0xe3, 0xd0, 0x5f, 0x26, 0xac, 0x1e, 0x5c, 0x04, 0x9c, - 0x86, 0x9d, 0x03, 0x07, 0x7f, 0x17, 0xc7, 0xda, 0x02, 0x76, 0x1b, 0xb6, 0x89, 0xdd, 0x85, 0x54, 0x43, 0x66, 0xb3, - 0x38, 0x74, 0x78, 0x95, 0x0d, 0xda, 0xa8, 0x99, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0x4b, - 0xb7, 0x92, 0x15, 0xa5, 0xc5, 0xc9, 0xfc, 0x3e, 0x67, 0xec, 0x59, 0xfd, 0x19, 0x7b, 0x26, 0xce, 0xd8, 0xee, 0x9d, - 0xf9, 0x70, 0xe2, 0xc0, 0x7f, 0xdd, 0x7c, 0x42, 0x1d, 0x5b, 0x69, 0x2e, 0xd6, 0x8a, 0xb3, 0x58, 0x2b, 0x66, 0x63, - 0xb1, 0x56, 0xb0, 0x6b, 0xb4, 0x79, 0x35, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf0, 0xca, 0x39, - 0x84, 0x77, 0xd0, 0xaa, 0x55, 0x7d, 0xd7, 0xd8, 0x7d, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0x89, 0x3b, 0x1c, - 0xb2, 0x71, 0x67, 0x12, 0x8e, 0x96, 0xf1, 0xbf, 0xf8, 0xf8, 0x39, 0x10, 0x77, 0x22, 0x82, 0x52, 0x3f, 0xa2, 0x29, - 0x48, 0x0f, 0x6f, 0x98, 0xe8, 0x61, 0x93, 0xad, 0x53, 0x87, 0xf2, 0x22, 0x35, 0xac, 0xc3, 0x9a, 0x4d, 0x5e, 0x0f, - 0xe8, 0xdf, 0x6d, 0x95, 0xb6, 0xa3, 0x98, 0x4f, 0x00, 0xcb, 0x4e, 0x70, 0xdc, 0x1f, 0x1a, 0x7c, 0x35, 0xed, 0x76, - 0xfd, 0x70, 0x2f, 0xc5, 0x97, 0xae, 0x04, 0x51, 0xe1, 0x74, 0x8b, 0xfb, 0xe7, 0xee, 0xee, 0x75, 0xdb, 0x1e, 0xa9, - 0xf4, 0xba, 0x83, 0x20, 0xe4, 0x75, 0xf7, 0xc4, 0xf2, 0x0f, 0x9f, 0x1d, 0xc2, 0x7f, 0xc4, 0xd5, 0xff, 0x23, 0xa9, - 0x63, 0xd4, 0x5f, 0x26, 0x05, 0x46, 0x9d, 0x58, 0x25, 0x64, 0xc4, 0xf7, 0xaf, 0x3f, 0x99, 0xdc, 0xaf, 0xc1, 0xde, - 0xb5, 0xc9, 0x5c, 0xbc, 0x5c, 0xfb, 0x79, 0x18, 0xfa, 0xcc, 0x0d, 0xaa, 0xd5, 0x05, 0x78, 0xc8, 0xf7, 0x2f, 0xe9, - 0x41, 0x23, 0x71, 0x8f, 0x20, 0x4b, 0x45, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x6c, 0xdb, 0x55, 0xe2, 0xdd, 0xdd, 0x57, - 0x89, 0x6f, 0xf7, 0xba, 0x4a, 0xbc, 0xfb, 0xec, 0x57, 0x89, 0xb3, 0xea, 0x55, 0xe2, 0x2c, 0x14, 0x3e, 0x42, 0xc6, - 0xeb, 0x25, 0xff, 0xf9, 0x9e, 0x8c, 0x80, 0xde, 0x85, 0xbd, 0x96, 0x4d, 0xb9, 0x8e, 0x2e, 0x7e, 0xf3, 0xc5, 0x02, - 0x37, 0xe2, 0x3b, 0x34, 0x99, 0xcf, 0xaf, 0x16, 0x1c, 0xb3, 0xe3, 0x77, 0xa4, 0x62, 0x3f, 0x0c, 0xa6, 0x3f, 0x82, - 0x11, 0x18, 0x88, 0x03, 0x23, 0xe9, 0x85, 0x17, 0xff, 0x18, 0x2e, 0x96, 0x8b, 0x37, 0xd0, 0xd7, 0x7b, 0x2f, 0xf6, - 0x86, 0x3e, 0xcb, 0x82, 0x4b, 0x91, 0x89, 0x3f, 0x97, 0xad, 0x83, 0x57, 0x8d, 0xf8, 0xe9, 0xae, 0xc5, 0x4f, 0xf4, - 0xbb, 0xe1, 0xbf, 0xc9, 0x77, 0x40, 0xad, 0xbf, 0x88, 0x08, 0xb5, 0xb1, 0x34, 0xe8, 0xfb, 0x5f, 0x46, 0xce, 0x42, - 0xbd, 0x66, 0x96, 0xc2, 0xa6, 0x73, 0x6b, 0x3f, 0xac, 0xdc, 0xcf, 0xeb, 0xa5, 0x6e, 0x64, 0xb1, 0xb7, 0xab, 0xe2, - 0xfc, 0x79, 0xb8, 0x8c, 0xd9, 0x38, 0x5c, 0x05, 0xaa, 0x11, 0x70, 0x47, 0x04, 0x4a, 0x5f, 0x9c, 0xb5, 0xf9, 0x6f, - 0xc8, 0x73, 0x70, 0x8e, 0x8c, 0x32, 0x84, 0xe8, 0xb1, 0x16, 0x00, 0x43, 0x93, 0x4c, 0xdb, 0x4c, 0x9c, 0xa2, 0x9a, - 0xa5, 0x37, 0x7e, 0xa0, 0x69, 0x61, 0xef, 0x7e, 0x2d, 0x85, 0x39, 0x6a, 0x68, 0x71, 0xa9, 0x70, 0xac, 0x05, 0x42, - 0xb8, 0x28, 0x02, 0x60, 0xd6, 0x2c, 0x1c, 0x7f, 0x43, 0x91, 0xa3, 0xf2, 0xb7, 0x10, 0x8a, 0x28, 0x5d, 0xf2, 0xf5, - 0xe0, 0xe1, 0x20, 0xe9, 0xf1, 0x85, 0x04, 0xc6, 0xb7, 0x37, 0x2c, 0xf2, 0xdd, 0x5b, 0x4d, 0x4f, 0xc3, 0xe0, 0x7b, - 0x00, 0xc0, 0xcb, 0x70, 0x15, 0xc8, 0x15, 0x30, 0x4b, 0x6b, 0xcd, 0x5e, 0xaa, 0x0d, 0x5c, 0x0a, 0x8e, 0xbc, 0xd2, - 0x08, 0x3c, 0x6b, 0xe1, 0x4e, 0xd9, 0x7f, 0x19, 0xf4, 0xef, 0xdf, 0xf5, 0xd4, 0x78, 0x17, 0x66, 0x1f, 0xfa, 0x69, - 0xb1, 0xc7, 0x67, 0x1e, 0x3f, 0x7e, 0xb0, 0x7d, 0xda, 0xda, 0xc8, 0x67, 0x6e, 0x24, 0x46, 0x51, 0xd3, 0x5a, 0xdf, - 0x7a, 0x0a, 0x60, 0x14, 0x17, 0xe1, 0x72, 0x34, 0x43, 0x67, 0x9e, 0xcf, 0x37, 0xdf, 0x04, 0xfa, 0x64, 0xf1, 0xa5, - 0x7d, 0x95, 0x4d, 0xbd, 0x54, 0x94, 0x43, 0x01, 0xbf, 0xff, 0x0a, 0x32, 0x6f, 0xfc, 0x89, 0x60, 0xa8, 0xee, 0x9a, - 0x2c, 0x0e, 0xc8, 0xbd, 0x36, 0x6f, 0xd7, 0x03, 0x57, 0x7d, 0x8a, 0x69, 0x29, 0x94, 0x74, 0xf5, 0x48, 0x26, 0x2d, - 0x03, 0x4d, 0x8e, 0x1f, 0xbf, 0x2d, 0x34, 0xbe, 0xf8, 0x0a, 0xb3, 0xe8, 0x9a, 0xce, 0x9d, 0x29, 0x0d, 0xc6, 0xb1, - 0x55, 0x09, 0xc9, 0x70, 0x13, 0x4b, 0x86, 0xe8, 0xab, 0xfc, 0x6e, 0xee, 0x05, 0x06, 0xa6, 0x7f, 0xab, 0xbe, 0x71, - 0xd7, 0x90, 0x00, 0x09, 0x90, 0x5b, 0xf9, 0x15, 0x14, 0x1a, 0x72, 0x08, 0x01, 0xc8, 0xf1, 0xac, 0xd6, 0x42, 0x42, - 0x68, 0x03, 0x07, 0x5f, 0x28, 0x8a, 0xa2, 0x64, 0xd7, 0x08, 0x25, 0xbb, 0x47, 0x60, 0x39, 0x5e, 0x07, 0x40, 0x5b, - 0x92, 0x2e, 0xd6, 0x54, 0x02, 0x37, 0x03, 0x34, 0xaa, 0x12, 0x05, 0x3c, 0xc6, 0x7f, 0xcb, 0x16, 0x05, 0xe2, 0x42, - 0x0f, 0xf1, 0xd9, 0xdd, 0x08, 0x52, 0x01, 0x75, 0x14, 0xbc, 0xb0, 0xe3, 0x5b, 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, - 0x74, 0x59, 0x7d, 0x30, 0xf8, 0x40, 0xc2, 0x82, 0xa0, 0x75, 0x28, 0xe5, 0x76, 0x32, 0x58, 0x0d, 0x6e, 0xc4, 0x7b, - 0xd1, 0x3a, 0x99, 0xb3, 0x60, 0xa9, 0x62, 0x32, 0x68, 0x0c, 0xce, 0x0f, 0x75, 0x5e, 0x12, 0xb3, 0x05, 0xd8, 0xa6, - 0xbe, 0xe5, 0x8c, 0x68, 0x61, 0xcc, 0x51, 0xaa, 0x6b, 0x8c, 0xb8, 0x57, 0x7c, 0xcc, 0x71, 0x5b, 0x99, 0x42, 0xf0, - 0x25, 0x0d, 0x8b, 0xd8, 0x9c, 0xc7, 0xc1, 0x40, 0x4e, 0x81, 0x02, 0x1e, 0x72, 0x71, 0x91, 0x00, 0xbb, 0xe6, 0x96, - 0x17, 0x2d, 0xd3, 0xc8, 0xb8, 0x25, 0x41, 0x51, 0xa4, 0x57, 0xbb, 0xe1, 0xe3, 0x84, 0x88, 0xc4, 0x5b, 0xfb, 0x19, - 0x55, 0xfa, 0xd9, 0x32, 0xe9, 0x0f, 0xec, 0x96, 0x08, 0x09, 0x81, 0xea, 0x03, 0xbb, 0x05, 0x8b, 0xb1, 0x57, 0x20, - 0x4d, 0x51, 0x77, 0xa0, 0x6b, 0x03, 0x72, 0xfc, 0x8d, 0x20, 0x4a, 0xf5, 0x8e, 0x03, 0x64, 0xa7, 0x3b, 0xb0, 0x38, - 0x82, 0x38, 0x30, 0xe2, 0xae, 0x38, 0xc4, 0xdc, 0x8d, 0x51, 0xab, 0x85, 0xb1, 0x59, 0x73, 0x34, 0xf4, 0x27, 0x8e, - 0x6d, 0x1f, 0x54, 0xea, 0x83, 0x20, 0xbb, 0xae, 0xb6, 0x6e, 0x24, 0x3d, 0xc7, 0x36, 0xbd, 0x27, 0x56, 0xa3, 0x5b, - 0xa1, 0xd1, 0x52, 0x12, 0x89, 0x01, 0x8a, 0xbf, 0xfa, 0x8f, 0x36, 0x5a, 0xe5, 0x40, 0xea, 0x65, 0xb7, 0x40, 0x1c, - 0x5b, 0xca, 0xe5, 0x5f, 0x83, 0x2a, 0xe9, 0xa7, 0x14, 0x16, 0x94, 0xd0, 0x74, 0x00, 0x69, 0x90, 0x34, 0x38, 0x46, - 0x7f, 0x51, 0x9e, 0x2a, 0x1a, 0x1d, 0x1f, 0x5d, 0x1f, 0x74, 0x05, 0x46, 0x11, 0x7e, 0xf3, 0x72, 0x07, 0xa5, 0x2f, - 0xc6, 0x65, 0x0c, 0xc7, 0x13, 0xae, 0xb0, 0x5c, 0xa3, 0xb7, 0x93, 0x5b, 0xc0, 0xfe, 0xb7, 0x90, 0x4f, 0x6b, 0x08, - 0x81, 0x9f, 0xa0, 0x06, 0x24, 0x4d, 0xbb, 0xb3, 0x43, 0x88, 0xd3, 0x27, 0x77, 0x57, 0x24, 0x92, 0xfb, 0x77, 0x86, - 0x44, 0x07, 0x75, 0x68, 0x59, 0x7f, 0xf5, 0xe4, 0xee, 0x9e, 0x5d, 0xb2, 0x60, 0x5c, 0xec, 0xb0, 0x44, 0xbf, 0xf6, - 0xef, 0xae, 0x80, 0x51, 0x20, 0x9b, 0x60, 0x58, 0x83, 0x51, 0xd2, 0x30, 0xc0, 0xcd, 0x4f, 0xc7, 0xcd, 0xdb, 0x8b, - 0x8b, 0xc1, 0x06, 0x14, 0x0a, 0x3c, 0x6b, 0x26, 0x09, 0xc5, 0x21, 0x65, 0x15, 0x86, 0xd5, 0xd0, 0x04, 0x23, 0xba, - 0x75, 0x27, 0x26, 0xc2, 0x87, 0x21, 0x6f, 0xe3, 0xf1, 0x24, 0x14, 0xfb, 0x4a, 0xad, 0xbd, 0xbb, 0xa5, 0xd6, 0xc9, - 0x5d, 0x52, 0x6b, 0x72, 0x19, 0x27, 0x7b, 0xa0, 0xcc, 0x75, 0x5e, 0x30, 0xe7, 0x72, 0xf0, 0x81, 0x82, 0xa8, 0x1b, - 0x3d, 0xcc, 0x45, 0xab, 0x4a, 0x6f, 0xe4, 0x95, 0x80, 0xe2, 0x6f, 0xe9, 0x82, 0x22, 0x14, 0xea, 0xb2, 0x6c, 0xfc, - 0x2c, 0x97, 0x8d, 0xd3, 0xad, 0x26, 0x77, 0x16, 0x16, 0xdc, 0xbf, 0xe4, 0x88, 0x9f, 0xdd, 0x0e, 0x72, 0x87, 0xfc, - 0x7c, 0xa4, 0x92, 0x8b, 0x79, 0x7e, 0xd1, 0x90, 0x02, 0x17, 0x88, 0x5b, 0x46, 0x31, 0x7e, 0x41, 0xb1, 0x6a, 0xee, - 0x61, 0x9e, 0x97, 0x83, 0xd4, 0x1d, 0x87, 0x9c, 0x15, 0xcb, 0xdb, 0xa6, 0xe8, 0x62, 0x2c, 0xbf, 0x96, 0x36, 0x49, - 0xe6, 0x0b, 0x4c, 0x00, 0x16, 0x62, 0xfa, 0x92, 0x5e, 0x3b, 0xb3, 0x81, 0xc0, 0x41, 0xd6, 0x84, 0x2e, 0xb8, 0x5b, - 0x3a, 0x4f, 0x89, 0x12, 0x73, 0xd5, 0xb5, 0x83, 0xd4, 0x9d, 0x34, 0xc1, 0xb2, 0x3c, 0x02, 0x61, 0x7d, 0x25, 0x49, - 0x10, 0x3a, 0xb6, 0x62, 0x77, 0x6b, 0x18, 0x00, 0xa4, 0xff, 0xe5, 0x67, 0xce, 0x0a, 0x80, 0x24, 0x52, 0xb1, 0x65, - 0x9d, 0x3f, 0x1e, 0x62, 0x93, 0xcc, 0xdb, 0xb0, 0x6a, 0xf5, 0x9b, 0x24, 0xef, 0xd9, 0x70, 0x47, 0xe1, 0xa2, 0x38, - 0x9f, 0xd7, 0xe8, 0x88, 0x71, 0xf0, 0x5d, 0x16, 0x2d, 0x03, 0xcc, 0x7f, 0x67, 0x26, 0x91, 0x3b, 0xfa, 0xb0, 0x91, - 0xbe, 0xc7, 0x45, 0xa2, 0x20, 0x2e, 0x2e, 0x2a, 0x15, 0xba, 0x2e, 0xa6, 0x8b, 0x60, 0x1d, 0xab, 0x11, 0x4b, 0x82, - 0x9a, 0xce, 0x43, 0xbb, 0xe9, 0x3e, 0x9b, 0x1c, 0x96, 0xe4, 0xa7, 0x8d, 0x56, 0x51, 0xba, 0x9e, 0x8d, 0x63, 0x1e, - 0xfe, 0xc2, 0x43, 0x2a, 0xfc, 0xf1, 0x9f, 0x8e, 0xf9, 0x37, 0x4b, 0x6b, 0xf4, 0x29, 0x43, 0x80, 0xf6, 0x05, 0xc5, - 0xb4, 0xac, 0xa6, 0xa9, 0x94, 0x6c, 0x1b, 0xd6, 0xc4, 0xf3, 0x7d, 0xd3, 0x07, 0xdb, 0xc6, 0xcd, 0x27, 0x4d, 0x0f, - 0xfb, 0x59, 0x42, 0xa2, 0xa2, 0x4f, 0xe8, 0xa7, 0xb8, 0x53, 0x92, 0xd9, 0x72, 0x3e, 0xdc, 0xc8, 0x82, 0x72, 0x49, - 0x7e, 0x5e, 0x95, 0x99, 0xcb, 0x9f, 0x9d, 0x4c, 0x26, 0x45, 0xa9, 0xb1, 0xad, 0x1c, 0xa2, 0xe4, 0xf7, 0xa1, 0x6d, - 0xdb, 0x65, 0xf8, 0x6e, 0x3b, 0x28, 0x74, 0x30, 0x4c, 0x14, 0xc2, 0xb7, 0xef, 0xde, 0x53, 0x7f, 0xd0, 0x68, 0xa9, - 0xab, 0x6d, 0xe7, 0x91, 0xb6, 0xda, 0x7f, 0xc4, 0x50, 0x10, 0x35, 0xdc, 0x75, 0xfc, 0xab, 0x7b, 0x65, 0x47, 0x4f, - 0xe5, 0x03, 0x7c, 0xbf, 0xc6, 0x77, 0xec, 0xf5, 0x3d, 0x9a, 0x6e, 0xdb, 0xde, 0xa9, 0x95, 0x93, 0xdd, 0x82, 0xcd, - 0x52, 0x97, 0x2c, 0x95, 0xbc, 0x84, 0xcd, 0xe3, 0xce, 0x88, 0xa1, 0x82, 0xd4, 0x92, 0xa8, 0x2d, 0x5a, 0xf5, 0x98, - 0x53, 0xb0, 0xe3, 0x72, 0x04, 0x1e, 0xb6, 0x15, 0x54, 0x56, 0x55, 0x34, 0x6b, 0xe2, 0x23, 0x48, 0xc5, 0x36, 0x55, - 0x85, 0x13, 0x6e, 0xd3, 0x96, 0xfd, 0x97, 0x42, 0x3d, 0x05, 0xb8, 0xd3, 0x8d, 0xb0, 0x36, 0x21, 0xe5, 0x09, 0xfe, - 0x9d, 0x29, 0xe7, 0x9e, 0x2d, 0xd6, 0x45, 0xe3, 0xae, 0x36, 0xa8, 0x9b, 0x72, 0x52, 0x46, 0xa3, 0xae, 0x43, 0x7d, - 0x99, 0x09, 0xd0, 0x44, 0xb6, 0x6e, 0x01, 0x0b, 0x9a, 0x42, 0x5a, 0xde, 0x1a, 0xdd, 0x18, 0x5e, 0x67, 0x61, 0xe7, - 0xe5, 0xf2, 0x7d, 0xfc, 0x05, 0x09, 0x4a, 0x21, 0xea, 0xf9, 0x5f, 0x8c, 0xa7, 0x6d, 0x54, 0xee, 0x15, 0xb6, 0x2a, - 0x9a, 0xca, 0xe0, 0x1e, 0x10, 0x37, 0x52, 0x65, 0x19, 0xf9, 0x26, 0xe5, 0xac, 0xd5, 0xf4, 0x4d, 0x75, 0xde, 0xdb, - 0xbb, 0x77, 0x5a, 0xa0, 0xd7, 0xa8, 0x82, 0x6a, 0x2f, 0xd5, 0x5e, 0x59, 0x87, 0x2d, 0xc6, 0x09, 0x2b, 0x00, 0x8e, - 0x34, 0x0a, 0x1a, 0x0d, 0x29, 0x25, 0xdc, 0x47, 0x93, 0xce, 0xde, 0xca, 0xc8, 0x5a, 0xcc, 0x13, 0xbb, 0xab, 0xaf, - 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xc0, 0x8e, 0x63, 0x27, 0x7c, 0x36, 0x61, 0xc7, 0xc8, 0xe8, 0xca, 0xc1, 0x1d, 0x84, - 0xa7, 0xd4, 0xa4, 0x58, 0xe8, 0x74, 0x4a, 0x51, 0x97, 0xf0, 0x6d, 0xad, 0xf0, 0xfe, 0xa2, 0x20, 0x8d, 0xe7, 0x9e, - 0xa8, 0x0d, 0x7d, 0xaf, 0xda, 0x73, 0x2f, 0xd8, 0xbf, 0xae, 0xbb, 0xde, 0xbb, 0x2e, 0x30, 0x87, 0x7b, 0x57, 0x06, - 0xee, 0x92, 0xac, 0x94, 0x92, 0xde, 0xb7, 0x92, 0xf2, 0x40, 0x8e, 0xa2, 0xa4, 0x62, 0x2b, 0xba, 0xd1, 0xff, 0xb0, - 0xec, 0x0d, 0x4e, 0x4e, 0xd7, 0x73, 0x5f, 0xb9, 0x61, 0x11, 0xe4, 0xef, 0xee, 0xa9, 0x8e, 0x65, 0xab, 0x0a, 0xc6, - 0x04, 0xf2, 0x82, 0x69, 0x4f, 0xfd, 0xe9, 0xe2, 0xb5, 0xd9, 0x56, 0x4f, 0xc1, 0x1c, 0xe3, 0x66, 0x8a, 0x2c, 0xee, - 0x99, 0x7b, 0xcb, 0xa2, 0xeb, 0x86, 0xaa, 0x60, 0x9a, 0x6e, 0x62, 0x6e, 0xb1, 0x4c, 0x69, 0xa8, 0x7b, 0x64, 0x83, - 0x55, 0x6e, 0x3c, 0xb6, 0x7a, 0x1e, 0xae, 0x7b, 0x2a, 0x20, 0x56, 0xa7, 0xd1, 0x56, 0x9c, 0xc6, 0xa1, 0x75, 0xd4, - 0x56, 0xfb, 0x5f, 0x28, 0xca, 0xc9, 0x98, 0x4d, 0xe2, 0x3e, 0x8a, 0x63, 0x4e, 0x90, 0x1f, 0xa4, 0xdf, 0x8a, 0x62, - 0x8d, 0xfc, 0xd8, 0x74, 0x94, 0x0d, 0x7f, 0x54, 0x14, 0x40, 0x46, 0x1d, 0xe5, 0xe1, 0xa4, 0x31, 0x39, 0x9c, 0x3c, - 0xeb, 0xf2, 0xe2, 0xf4, 0x8b, 0x42, 0x75, 0x83, 0xfe, 0x6d, 0x48, 0xcd, 0xe2, 0x24, 0x0a, 0x3f, 0x30, 0xce, 0x4b, - 0x2a, 0x99, 0xa0, 0xa8, 0xdc, 0xb4, 0x51, 0xfd, 0x92, 0xd3, 0x1e, 0x8e, 0x26, 0x8d, 0xbc, 0x3a, 0x8e, 0xf1, 0x20, - 0x1b, 0xe4, 0xc9, 0x81, 0x18, 0xfa, 0x89, 0x0c, 0x26, 0xc7, 0xac, 0x03, 0x94, 0xa3, 0xf2, 0x39, 0x4e, 0xc5, 0xfc, - 0x4e, 0x20, 0xd9, 0x4a, 0xee, 0xd2, 0x10, 0x63, 0xb3, 0x9e, 0xfa, 0xbd, 0xd3, 0x68, 0x1b, 0x8e, 0x73, 0x64, 0x1d, - 0xb5, 0x47, 0xb6, 0x71, 0x68, 0x1d, 0x9a, 0x4d, 0xeb, 0xc8, 0x68, 0x9b, 0x6d, 0xa3, 0xfd, 0x4d, 0x7b, 0x64, 0x1e, - 0x5a, 0x87, 0x86, 0x6d, 0xb6, 0xa1, 0xd0, 0x6c, 0x9b, 0xed, 0x1b, 0xf3, 0xb0, 0x3d, 0xb2, 0xb1, 0xb4, 0x61, 0xb5, - 0x5a, 0xa6, 0x63, 0x5b, 0xad, 0x96, 0xd1, 0xb2, 0x8e, 0x8e, 0x4c, 0xa7, 0x69, 0x1d, 0x1d, 0x9d, 0xb5, 0xda, 0x56, - 0x13, 0xde, 0x35, 0x9b, 0xa3, 0xa6, 0xe5, 0x38, 0x26, 0xfc, 0x65, 0xb4, 0xad, 0x06, 0xfd, 0x70, 0x1c, 0xab, 0xe9, - 0x18, 0xb6, 0xdf, 0x6a, 0x58, 0x47, 0xcf, 0x0c, 0xfc, 0x1b, 0xab, 0x19, 0xf8, 0x17, 0x74, 0x63, 0x3c, 0xb3, 0x1a, - 0x47, 0xf4, 0x0b, 0x3b, 0xbc, 0x39, 0x6c, 0xff, 0x43, 0x3d, 0xd8, 0x3a, 0x07, 0x87, 0xe6, 0xd0, 0x6e, 0x59, 0xcd, - 0xa6, 0x71, 0xe8, 0x58, 0xed, 0xe6, 0xcc, 0x3c, 0x6c, 0x58, 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, - 0x6c, 0x5a, 0x0d, 0xc3, 0xb1, 0x0e, 0x9b, 0xf8, 0xa3, 0x69, 0x35, 0x6e, 0x8e, 0x9f, 0x59, 0x47, 0xad, 0xd9, 0x91, - 0x75, 0xf8, 0xfe, 0xb0, 0x6d, 0x35, 0x9a, 0xb3, 0xe6, 0x91, 0xd5, 0x38, 0xbe, 0x39, 0xb2, 0x0e, 0x67, 0x66, 0xe3, - 0x68, 0x67, 0x4b, 0xa7, 0x61, 0x01, 0x8c, 0xf0, 0x35, 0xbc, 0x30, 0xf8, 0x0b, 0xf8, 0x33, 0xc3, 0xb6, 0x7f, 0x60, - 0x37, 0x71, 0xb5, 0xe9, 0x33, 0xab, 0x7d, 0x3c, 0xa2, 0xea, 0x50, 0x60, 0x8a, 0x1a, 0xd0, 0xe4, 0xc6, 0xa4, 0xcf, - 0x62, 0x77, 0xa6, 0xe8, 0x48, 0xfc, 0xe1, 0x1f, 0xbb, 0x31, 0xe1, 0xc3, 0xf4, 0xdd, 0x3f, 0xb5, 0x9f, 0x6c, 0xc9, - 0x4f, 0x0e, 0xa6, 0xb4, 0xf5, 0xa7, 0xfd, 0x2f, 0x28, 0xb3, 0xf3, 0xc0, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x9f, 0x77, - 0x2b, 0x25, 0x9f, 0x2f, 0xf7, 0x51, 0x4a, 0xfe, 0xf3, 0xb3, 0x2b, 0x25, 0x7f, 0x29, 0xfb, 0xd6, 0xbc, 0x2e, 0x27, - 0xa0, 0xfc, 0x76, 0x53, 0x16, 0x39, 0x04, 0xae, 0x76, 0xf9, 0xc3, 0xf2, 0x0a, 0x82, 0xca, 0xbe, 0x0e, 0x7b, 0xcf, - 0x97, 0x05, 0x83, 0xcf, 0x10, 0x70, 0xec, 0xeb, 0x90, 0x70, 0xec, 0xfb, 0x65, 0x0f, 0xac, 0xcc, 0x38, 0x9b, 0xe3, - 0x8d, 0xcd, 0x99, 0xeb, 0x4f, 0x32, 0x16, 0x09, 0x4a, 0xba, 0x58, 0x0c, 0xce, 0x74, 0x40, 0x9e, 0xe1, 0x26, 0xb3, - 0x9c, 0x07, 0x31, 0x58, 0x04, 0x83, 0x25, 0xc7, 0x24, 0x4a, 0x4b, 0x8d, 0x2d, 0x11, 0x86, 0xf7, 0x9a, 0x7b, 0x59, - 0x6d, 0x7d, 0x8f, 0x06, 0xc0, 0xf5, 0xbd, 0x3b, 0xd5, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, - 0xbd, 0x2f, 0x9a, 0xe1, 0x96, 0x0c, 0xaf, 0xb7, 0x8f, 0x14, 0x46, 0x52, 0x6e, 0xef, 0x14, 0xcd, 0x78, 0xef, 0x9a, - 0x66, 0xcd, 0xe7, 0x0b, 0xcd, 0x77, 0xd8, 0x10, 0x67, 0x1d, 0x97, 0x41, 0xb5, 0x29, 0xf0, 0x69, 0xf5, 0x00, 0xc9, - 0x2f, 0xa8, 0xb9, 0xa1, 0x71, 0xce, 0xa9, 0xda, 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd0, 0xa7, 0x6c, 0x9c, 0xfc, - 0x64, 0x83, 0xf7, 0x0a, 0xef, 0x17, 0xe0, 0x44, 0x39, 0xc7, 0x33, 0x0c, 0x65, 0x38, 0x6f, 0xa4, 0x7e, 0x49, 0x1a, - 0x91, 0xce, 0x9c, 0x4d, 0x95, 0x17, 0xdd, 0xea, 0x96, 0xe0, 0xb0, 0xb9, 0xe0, 0x82, 0xf0, 0xf3, 0xe4, 0x04, 0x90, - 0x92, 0xa3, 0x06, 0xfa, 0x39, 0xec, 0xea, 0x4c, 0xd4, 0x7b, 0x08, 0x9b, 0x98, 0x67, 0x03, 0x50, 0xe4, 0x38, 0x67, - 0x9b, 0x89, 0x1f, 0xba, 0x49, 0x07, 0xd9, 0x34, 0x89, 0xe5, 0x6d, 0xa0, 0xc7, 0x42, 0x77, 0x87, 0x31, 0x9d, 0xdc, - 0x31, 0xef, 0x04, 0x3d, 0x1f, 0x76, 0xd9, 0xdf, 0x65, 0x0e, 0x67, 0x9b, 0x82, 0x39, 0x8a, 0xd3, 0x3a, 0x36, 0x9c, - 0x23, 0xc3, 0x3a, 0x6e, 0xe9, 0xa9, 0x38, 0x70, 0x72, 0x97, 0x05, 0x80, 0x80, 0x03, 0x44, 0x36, 0x4c, 0x2f, 0xf0, - 0x12, 0xcf, 0xf5, 0x53, 0xe0, 0x87, 0x8b, 0x97, 0x94, 0x7f, 0x2e, 0xe3, 0x04, 0xe6, 0x28, 0x98, 0x5e, 0x74, 0xfe, - 0x30, 0x87, 0x2c, 0x59, 0x31, 0x16, 0x6c, 0x31, 0x8c, 0x29, 0xfb, 0x92, 0xfc, 0x7e, 0x96, 0xf5, 0x29, 0x59, 0xad, - 0x0d, 0x93, 0x80, 0xef, 0x0f, 0xe1, 0xf8, 0x90, 0x0e, 0x8c, 0x6f, 0xb6, 0x21, 0xdc, 0x9f, 0xee, 0x46, 0xb8, 0x09, - 0xdb, 0x07, 0xe1, 0xfe, 0xf4, 0xd9, 0x11, 0xee, 0x37, 0x32, 0xc2, 0x2d, 0xf8, 0x0f, 0xe6, 0x1a, 0xa6, 0x73, 0x7c, - 0xd6, 0x20, 0x27, 0xd7, 0x53, 0xf5, 0x80, 0x18, 0x78, 0x55, 0xcf, 0x13, 0xd7, 0xfd, 0xad, 0x90, 0x22, 0x1c, 0x05, - 0xa0, 0x98, 0xef, 0x89, 0xd2, 0x11, 0x7b, 0xe0, 0xea, 0x96, 0xa5, 0x24, 0x66, 0x2b, 0xe5, 0x4d, 0x90, 0xf8, 0xd6, - 0x3b, 0x7e, 0x8f, 0x04, 0x85, 0xee, 0xeb, 0x30, 0x9a, 0xbb, 0x18, 0x77, 0x5c, 0xd5, 0xc1, 0x9d, 0x0e, 0x1e, 0x6c, - 0xf0, 0x0e, 0x1e, 0x85, 0xc1, 0x38, 0xd3, 0x4a, 0xb2, 0xde, 0x25, 0x71, 0xdc, 0xea, 0x2d, 0x73, 0x23, 0xd5, 0xa0, - 0xd7, 0xb0, 0xb8, 0x4f, 0x9a, 0xf6, 0x93, 0xc6, 0xe1, 0x93, 0x23, 0x1b, 0xfe, 0x77, 0x58, 0x33, 0x35, 0x78, 0xc5, - 0x79, 0x18, 0x40, 0x76, 0x63, 0x51, 0x73, 0x5b, 0xb5, 0x15, 0x63, 0x1f, 0xf2, 0x5a, 0xc7, 0xf5, 0x95, 0xc6, 0xee, - 0x6d, 0x5e, 0xa7, 0xb6, 0xc6, 0x2c, 0x5c, 0x4a, 0xc3, 0xaa, 0x19, 0x8d, 0x17, 0x2c, 0x41, 0xce, 0x2e, 0xd5, 0x90, - 0x5f, 0xf3, 0xe9, 0xe6, 0xf3, 0x62, 0xcd, 0xf4, 0x2a, 0x4f, 0xa1, 0x2e, 0x32, 0xe9, 0xdd, 0x09, 0x41, 0xae, 0xa2, - 0xb4, 0x31, 0x11, 0x05, 0xa6, 0x38, 0x82, 0x34, 0x14, 0x59, 0xe2, 0x6b, 0x97, 0x16, 0x28, 0x89, 0x96, 0xc1, 0x48, - 0xc3, 0x9f, 0xee, 0x30, 0xd6, 0xbc, 0x83, 0xc8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xdc, 0xbe, 0x9d, 0xe7, 0x9b, 0x8d, - 0xc5, 0xaa, 0xb8, 0x4f, 0x12, 0x23, 0x42, 0x3d, 0x36, 0x2d, 0xad, 0xd9, 0x73, 0x9f, 0x64, 0x0d, 0x9f, 0x24, 0x46, - 0xf0, 0x14, 0x74, 0x9f, 0x3d, 0xfb, 0xf1, 0x63, 0xaa, 0xf5, 0xa0, 0x27, 0xa6, 0x75, 0x3a, 0xca, 0xc3, 0x55, 0x2b, - 0xee, 0x34, 0xa4, 0x88, 0xd5, 0x9d, 0x91, 0x11, 0x3e, 0x7d, 0xda, 0xef, 0x39, 0x3a, 0xe6, 0x32, 0x4f, 0x45, 0x0c, - 0xd0, 0x00, 0x53, 0xd3, 0x9d, 0xed, 0x67, 0x68, 0xa4, 0xd7, 0xba, 0xd2, 0x2e, 0xe0, 0xce, 0x64, 0x0b, 0x77, 0x04, - 0x8e, 0xbd, 0x20, 0x6d, 0x2d, 0x19, 0x14, 0xb8, 0xc2, 0xe0, 0x47, 0xd4, 0xc9, 0x6e, 0x5d, 0x4d, 0xcb, 0xb6, 0x6c, - 0x35, 0x6b, 0x38, 0xf1, 0xa6, 0xbd, 0x4d, 0x98, 0xb8, 0x90, 0x00, 0xdc, 0x0f, 0xa7, 0xe0, 0x47, 0x97, 0x78, 0x89, - 0x0f, 0xd9, 0xa4, 0xc1, 0xa1, 0x6e, 0x4e, 0xf7, 0xf2, 0x94, 0x7b, 0x37, 0xb8, 0x11, 0x64, 0x2c, 0x8d, 0x6e, 0x85, - 0x2b, 0x2e, 0x46, 0x50, 0xfd, 0x1e, 0x88, 0xa1, 0xa6, 0x6a, 0x20, 0x1b, 0x60, 0x51, 0x6c, 0xca, 0xde, 0x42, 0x1d, - 0x05, 0xda, 0xe8, 0x2a, 0x9f, 0xc4, 0x24, 0x72, 0xe7, 0x90, 0x52, 0x6f, 0x93, 0x1a, 0x1c, 0xd3, 0xaa, 0x1c, 0xd5, - 0x2a, 0xce, 0xb3, 0x23, 0x43, 0x69, 0x38, 0x86, 0x62, 0x03, 0xba, 0x55, 0x53, 0x63, 0x93, 0x5e, 0x75, 0xef, 0x32, - 0x78, 0x20, 0xfc, 0xf2, 0x90, 0xe6, 0x41, 0xa6, 0x0e, 0x5c, 0x95, 0x94, 0x50, 0xe4, 0x7c, 0x4d, 0x4a, 0xa5, 0xe5, - 0x91, 0xd2, 0xf3, 0x82, 0xad, 0x13, 0x1d, 0xb3, 0x2d, 0xf3, 0x2a, 0x9e, 0xbe, 0x41, 0x87, 0x61, 0x2f, 0x50, 0xbc, - 0x8f, 0x1f, 0x35, 0x0f, 0x9c, 0x99, 0x7a, 0x12, 0x7c, 0xe0, 0x59, 0x2f, 0x00, 0xcc, 0xcb, 0xd5, 0xf4, 0x08, 0x2c, - 0xf0, 0x34, 0x84, 0x7f, 0xf3, 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0xbe, 0x1b, 0x4c, 0x01, 0xa5, 0xb9, 0xc1, 0xb4, - 0x62, 0x8e, 0x45, 0x3e, 0xcf, 0xa5, 0xd2, 0xbc, 0xab, 0xdc, 0x54, 0x2a, 0x7e, 0x7e, 0x7b, 0x41, 0xd9, 0xe4, 0x35, - 0x15, 0xa8, 0x1c, 0xba, 0xe8, 0xe6, 0x9a, 0xdc, 0xa7, 0xbd, 0x2f, 0x4f, 0xe6, 0x2c, 0x71, 0x49, 0x0d, 0x04, 0x97, - 0x5f, 0x60, 0x07, 0x14, 0x4e, 0x68, 0x78, 0x54, 0xc2, 0x1e, 0x25, 0xd8, 0x20, 0x3a, 0x61, 0x28, 0x9c, 0x4e, 0x99, - 0x68, 0xf1, 0xd9, 0x73, 0x0c, 0x72, 0x38, 0x18, 0xb9, 0x18, 0x64, 0xbf, 0x17, 0x84, 0x6a, 0xff, 0xcb, 0xcc, 0x37, - 0x73, 0xdb, 0x22, 0xf8, 0x5e, 0xf0, 0xe1, 0x32, 0x62, 0xfe, 0xbf, 0x7a, 0x5f, 0x02, 0xe1, 0xfe, 0xf2, 0x4a, 0xd5, - 0xbb, 0x89, 0x35, 0x8b, 0xd8, 0xa4, 0xf7, 0x25, 0xa6, 0xdd, 0x45, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xae, 0xe7, 0xbe, - 0x81, 0xd7, 0x7b, 0x1a, 0x8b, 0xda, 0x6c, 0xe4, 0xc1, 0x4e, 0x9b, 0x7b, 0x5d, 0xea, 0xfb, 0xfc, 0xb6, 0x0e, 0x37, - 0xc0, 0x4d, 0xe1, 0x8e, 0xed, 0x74, 0xf1, 0xfe, 0x3c, 0xf4, 0xdd, 0xd1, 0x87, 0x2e, 0xbd, 0x29, 0x3c, 0x98, 0x40, - 0xad, 0x47, 0xee, 0xa2, 0x83, 0xe4, 0x55, 0x2e, 0x04, 0xef, 0x69, 0x2a, 0xcd, 0x38, 0xbb, 0xda, 0xbd, 0x8c, 0x5b, - 0x79, 0x83, 0x5f, 0xc6, 0x4f, 0xad, 0x66, 0x5e, 0xc2, 0xc4, 0xa7, 0xf0, 0x21, 0x4d, 0xc5, 0x45, 0x9d, 0xae, 0xa8, - 0x78, 0xb1, 0xb6, 0x9a, 0x8a, 0xd3, 0xfe, 0xa6, 0x75, 0xe3, 0xd8, 0xb3, 0x86, 0x63, 0xb5, 0xdf, 0x3b, 0xed, 0x59, - 0xd3, 0x3a, 0xf6, 0xcd, 0xa6, 0x75, 0x0c, 0x7f, 0xde, 0x1f, 0x5b, 0xed, 0x99, 0xd9, 0xb0, 0x0e, 0xdf, 0x3b, 0x0d, - 0xdf, 0x6c, 0x5b, 0xc7, 0xf0, 0xe7, 0x8c, 0x5a, 0xc1, 0x05, 0x88, 0xee, 0x3b, 0x5f, 0x16, 0xb0, 0x80, 0xf4, 0x3b, - 0xd3, 0xc9, 0x1a, 0x05, 0xf2, 0x56, 0xa3, 0xd7, 0x05, 0x94, 0x41, 0xb9, 0xe6, 0xd0, 0x14, 0xa1, 0xab, 0x05, 0x3d, - 0x46, 0xd9, 0xe5, 0x84, 0x79, 0x9b, 0xf0, 0x43, 0x17, 0x29, 0xbe, 0x6a, 0x8f, 0x11, 0x6f, 0x53, 0x9f, 0xd6, 0x4a, - 0xa4, 0x9f, 0x27, 0x45, 0xf0, 0x4f, 0x0b, 0x0c, 0xca, 0x2a, 0xb2, 0x31, 0x4a, 0x58, 0x09, 0x7c, 0xcf, 0xad, 0x20, - 0x5c, 0xa1, 0x6d, 0xc5, 0x5d, 0x03, 0x47, 0x6f, 0x7e, 0x96, 0xa5, 0xe0, 0xfe, 0xac, 0x7d, 0x4b, 0x49, 0x2f, 0x3f, - 0xa9, 0x1f, 0x4c, 0x07, 0x98, 0x67, 0xf2, 0x83, 0x5c, 0x16, 0x63, 0x2f, 0xca, 0x86, 0x27, 0xa1, 0x68, 0xa7, 0x3e, - 0x1f, 0x98, 0x0e, 0xb9, 0x8a, 0xdf, 0x00, 0x97, 0x7c, 0xe3, 0xfa, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x41, 0x86, 0xf9, - 0x1f, 0x3f, 0xce, 0x07, 0x67, 0x96, 0xc6, 0x7d, 0xe2, 0xb4, 0x80, 0xec, 0xb6, 0x58, 0x73, 0xa7, 0x4d, 0x25, 0xdd, - 0x74, 0x76, 0xf9, 0x56, 0xe7, 0xe9, 0x0f, 0x84, 0xdd, 0x94, 0xb0, 0xd8, 0xd8, 0x6a, 0xd8, 0x59, 0xb1, 0xd7, 0x80, - 0xfc, 0x31, 0xa5, 0xab, 0x8e, 0xaa, 0x77, 0x03, 0x61, 0x7e, 0x10, 0xec, 0xc8, 0xfc, 0xc2, 0xef, 0x62, 0x2a, 0x80, - 0x66, 0xc7, 0x3c, 0xee, 0x70, 0x10, 0xff, 0xb3, 0x27, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x3a, 0xad, 0x05, 0xe7, - 0xbd, 0x8c, 0xae, 0x12, 0x41, 0x65, 0xf1, 0xa9, 0x0a, 0x45, 0x90, 0xc4, 0x1e, 0x70, 0xa3, 0x9a, 0x19, 0x8b, 0x66, - 0xd4, 0x22, 0x2f, 0x30, 0x3c, 0xcc, 0xb2, 0x25, 0x1c, 0x47, 0xf5, 0xc7, 0x8f, 0xb7, 0x12, 0x21, 0x32, 0xce, 0x89, - 0x59, 0x92, 0x65, 0xd6, 0x56, 0x65, 0xfc, 0xa6, 0xca, 0x28, 0x26, 0xeb, 0x17, 0xb1, 0x86, 0xb0, 0x71, 0xa5, 0xbd, - 0x87, 0x3f, 0x87, 0xcc, 0x4d, 0x2c, 0xae, 0x2c, 0xd5, 0x24, 0xe2, 0x6e, 0x38, 0xac, 0x09, 0xd6, 0xad, 0x3c, 0x76, - 0x73, 0x96, 0xa0, 0xf7, 0x6f, 0x4b, 0x1e, 0xd5, 0x01, 0xfa, 0xf8, 0x68, 0xe7, 0xc1, 0xb9, 0xde, 0x26, 0x2e, 0x85, - 0x24, 0x93, 0x49, 0x6e, 0x98, 0xb8, 0x22, 0x59, 0x34, 0xf0, 0xe5, 0xf5, 0x01, 0x59, 0xa4, 0xc8, 0x0f, 0xfd, 0xb7, - 0x17, 0x5f, 0x2b, 0x7c, 0xff, 0x93, 0xb5, 0x00, 0x5e, 0x64, 0x28, 0xe7, 0x5c, 0x8f, 0x72, 0xce, 0x29, 0x3c, 0xbd, - 0xa1, 0x8a, 0xd9, 0x82, 0x09, 0x82, 0x28, 0x80, 0x26, 0x1b, 0x8a, 0xf9, 0xd2, 0x4f, 0xbc, 0x85, 0x1b, 0x25, 0x07, - 0x98, 0x70, 0x0e, 0x90, 0x9c, 0xba, 0x2d, 0x1e, 0x04, 0x99, 0x61, 0x88, 0x90, 0xe1, 0x49, 0x20, 0xec, 0x30, 0x26, - 0x9e, 0x9f, 0x99, 0x61, 0x88, 0x0f, 0xb8, 0xa3, 0x11, 0x5b, 0x24, 0xbd, 0x42, 0x62, 0xbb, 0x70, 0x94, 0xb0, 0xc4, - 0x8c, 0x93, 0x88, 0xb9, 0x73, 0x35, 0x4b, 0x4d, 0x51, 0xed, 0x2f, 0x5e, 0x0e, 0xe7, 0x5e, 0x92, 0xc5, 0x76, 0xa7, - 0x09, 0x82, 0x41, 0x04, 0x0c, 0x11, 0x82, 0xcc, 0x10, 0x08, 0xcf, 0xc2, 0x69, 0x69, 0x47, 0xe5, 0x9c, 0xcb, 0x29, - 0x66, 0x0e, 0xa1, 0x9b, 0x0c, 0x48, 0x8b, 0x47, 0xa1, 0x7f, 0xcd, 0x63, 0x58, 0x64, 0x21, 0xe8, 0xd5, 0xfe, 0x09, - 0xbf, 0xde, 0x2a, 0x18, 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x1b, 0x65, 0x5b, 0x74, 0x8b, 0x03, 0x5e, 0x19, 0x48, 0x13, - 0xf5, 0x8c, 0xe9, 0xad, 0x68, 0x2c, 0x17, 0xc0, 0x08, 0x15, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x73, 0xa7, 0xc4, 0x51, - 0x21, 0xaf, 0xf4, 0xf1, 0xe3, 0xf9, 0xe0, 0xd7, 0x7f, 0x43, 0x0e, 0xae, 0x99, 0x23, 0x62, 0x4a, 0x5c, 0xca, 0xb5, - 0x38, 0xf7, 0x69, 0x0c, 0xd0, 0x58, 0x8a, 0x8d, 0x45, 0x08, 0x20, 0xb1, 0xb5, 0xd2, 0xc1, 0x95, 0x08, 0x0e, 0x0c, - 0xd9, 0xfb, 0x74, 0x11, 0xf9, 0x02, 0x93, 0x41, 0x0f, 0x44, 0x4c, 0x14, 0xe5, 0xe7, 0xf5, 0xf3, 0x63, 0x25, 0x8f, - 0xa9, 0x54, 0x67, 0xd1, 0x43, 0x7b, 0xa8, 0x7f, 0xe2, 0x2a, 0xc8, 0xb4, 0x20, 0xfb, 0x11, 0x77, 0x0e, 0x60, 0x9a, - 0xb3, 0x70, 0xce, 0x2c, 0x2f, 0x3c, 0x58, 0xb1, 0xa1, 0xe9, 0x2e, 0x3c, 0xb2, 0xcb, 0x41, 0xb9, 0x9b, 0x42, 0x9c, - 0x5f, 0x66, 0xee, 0x42, 0xfc, 0x75, 0x9a, 0x83, 0x32, 0x2c, 0x46, 0x83, 0x6e, 0x35, 0x72, 0x3d, 0xe0, 0x21, 0x05, - 0x80, 0x13, 0x70, 0x0c, 0xfb, 0x27, 0x07, 0x6e, 0xbf, 0x18, 0x8e, 0xde, 0x12, 0x69, 0xd5, 0x8a, 0x44, 0xe0, 0x94, - 0xa2, 0xca, 0x8b, 0x00, 0xf2, 0xf9, 0x83, 0x19, 0x4e, 0x26, 0x72, 0x08, 0x79, 0xab, 0x38, 0xbc, 0x0c, 0x68, 0xf9, - 0x96, 0x0e, 0x17, 0xf4, 0xa5, 0xea, 0x27, 0xb2, 0x9f, 0x6a, 0x07, 0x73, 0x47, 0xc0, 0x9c, 0xe1, 0xb8, 0x57, 0x42, - 0xd1, 0x67, 0x10, 0x7b, 0x48, 0x95, 0x38, 0x1e, 0x29, 0x27, 0x3e, 0xda, 0xc2, 0xb9, 0x3c, 0xe8, 0xf5, 0x08, 0xcd, - 0x95, 0xb1, 0x1d, 0x00, 0xb1, 0x26, 0xc5, 0x1c, 0x4c, 0x36, 0x81, 0x86, 0x26, 0xb9, 0xcb, 0x62, 0xa3, 0xf2, 0x74, - 0xaa, 0x63, 0x3c, 0x70, 0xc5, 0xf6, 0x2b, 0x6c, 0x50, 0xd8, 0x78, 0x7c, 0xdd, 0x01, 0xbf, 0x8b, 0x7e, 0x4a, 0x68, - 0x5e, 0xf9, 0x8a, 0x30, 0xba, 0xe9, 0xbb, 0xb7, 0xa1, 0x64, 0xc6, 0xc4, 0x23, 0x9a, 0x9c, 0x61, 0xe9, 0x85, 0xf0, - 0x24, 0xae, 0x1c, 0x34, 0x24, 0x61, 0x90, 0x8a, 0xab, 0x7a, 0xd8, 0x72, 0xfa, 0xeb, 0xb3, 0xbb, 0xce, 0x9a, 0x5c, - 0xb7, 0x38, 0x19, 0x44, 0x9e, 0x69, 0x7e, 0x0e, 0x0b, 0x2f, 0x11, 0x2d, 0xa4, 0x27, 0x07, 0x30, 0x3f, 0x88, 0xc2, - 0x52, 0x60, 0x9c, 0x3c, 0x1d, 0x42, 0xbd, 0xb8, 0x31, 0x99, 0x62, 0xbd, 0x19, 0x0b, 0x9e, 0x0f, 0x2f, 0x96, 0x52, - 0x82, 0x59, 0xa9, 0x4a, 0x95, 0x97, 0xb1, 0xeb, 0x99, 0xc0, 0xbb, 0xf3, 0xd6, 0xbd, 0x5f, 0x62, 0xd2, 0xba, 0xb4, - 0x9b, 0x30, 0x11, 0xe4, 0xe0, 0x2c, 0xd9, 0x12, 0x07, 0x61, 0x5b, 0x15, 0xe2, 0x67, 0x77, 0x54, 0xc8, 0xf7, 0xf1, - 0xae, 0x5a, 0x39, 0xe7, 0x94, 0x55, 0x9b, 0xba, 0x9a, 0xfa, 0x10, 0x77, 0x7c, 0xa5, 0x36, 0x96, 0x42, 0xbd, 0xb3, - 0xa4, 0x07, 0x55, 0x85, 0x2c, 0xde, 0x5d, 0x2c, 0xa8, 0xb2, 0xde, 0x3d, 0x39, 0xa0, 0x6b, 0x69, 0x9f, 0x76, 0x58, - 0xff, 0x04, 0x4c, 0xb9, 0x69, 0xd1, 0xdd, 0xc5, 0x82, 0x2f, 0x29, 0xfd, 0xa2, 0x37, 0x07, 0xb3, 0x64, 0xee, 0xf7, - 0xff, 0x17, 0x99, 0x05, 0x40, 0xf2, 0xa6, 0x72, 0x03, 0x00}; + 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0x34, 0x86, 0x2e, 0x8a, 0x44, 0x2b, 0x24, 0x28, 0x45, 0x7d, + 0x5b, 0x2f, 0x54, 0x1b, 0x08, 0x51, 0xb7, 0xc5, 0x34, 0x7d, 0x8e, 0xa0, 0xed, 0x20, 0x25, 0xc1, 0xbd, 0x65, 0x63, + 0x7e, 0x75, 0x2d, 0x9f, 0x39, 0x74, 0x67, 0x31, 0xfb, 0x52, 0x86, 0xc1, 0x20, 0xfa, 0x52, 0x16, 0x36, 0xb9, 0x67, + 0x95, 0xaa, 0x2c, 0xc7, 0xc6, 0xf6, 0x72, 0x8a, 0xa6, 0x2c, 0xe1, 0xbb, 0x75, 0xd8, 0x5c, 0xfb, 0x14, 0x67, 0x9f, + 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x54, 0xd7, 0x85, 0x06, 0x2d, 0xd2, 0xda, + 0x9c, 0x5c, 0x5e, 0x82, 0x2c, 0xb3, 0x57, 0x8c, 0xe4, 0xa7, 0xbd, 0x28, 0x9f, 0x7f, 0xbc, 0xfc, 0xf8, 0xf1, 0xdd, + 0x01, 0x2a, 0x7c, 0x7a, 0x07, 0x1f, 0x14, 0x7a, 0xc0, 0xc1, 0x83, 0x6d, 0xa1, 0x55, 0xec, 0xf5, 0x1f, 0xf6, 0xac, + 0x2a, 0x5a, 0x0a, 0x72, 0x03, 0x0a, 0xe8, 0x55, 0xd1, 0x1a, 0xd6, 0xc2, 0x69, 0xb1, 0xfd, 0xcc, 0x4a, 0xbb, 0x14, + 0xa0, 0xee, 0x44, 0xd5, 0x1c, 0x29, 0xbd, 0x3c, 0x44, 0x5a, 0x08, 0xab, 0x3b, 0xb6, 0x5a, 0xd5, 0xb5, 0xd5, 0x64, + 0x51, 0x65, 0xe2, 0xf2, 0x0c, 0x77, 0xff, 0x57, 0x6d, 0x39, 0x33, 0xc3, 0x8a, 0x5e, 0xb4, 0x77, 0x5b, 0x03, 0xaa, + 0x4c, 0x1b, 0xe5, 0xea, 0x3d, 0x04, 0x02, 0xb3, 0xb2, 0x9e, 0xfa, 0x1f, 0x1b, 0x8b, 0x11, 0x3f, 0x4d, 0x01, 0xb9, + 0x01, 0x0f, 0xc4, 0x4e, 0xe2, 0x91, 0x69, 0xdf, 0x0d, 0xca, 0x4d, 0x8e, 0x93, 0x56, 0xc2, 0x6c, 0x38, 0x89, 0x26, + 0xc4, 0xc6, 0x97, 0xd0, 0x34, 0xec, 0xc7, 0xd1, 0xf3, 0x37, 0x1f, 0x5f, 0x7d, 0xfc, 0xf7, 0xd9, 0xd3, 0xd3, 0x8f, + 0xcf, 0x7f, 0x7c, 0xfb, 0xfe, 0xd5, 0xf3, 0x0f, 0x78, 0x42, 0x68, 0xc0, 0xca, 0x70, 0xab, 0xad, 0xa2, 0x9b, 0x65, + 0x45, 0xa2, 0x26, 0xcd, 0xa6, 0x28, 0xc4, 0x28, 0xcc, 0x6c, 0x8b, 0xfc, 0xe5, 0xcd, 0xb3, 0xe7, 0x2f, 0x5e, 0xbd, + 0x79, 0xfe, 0xac, 0xfd, 0xf5, 0x70, 0x52, 0x93, 0xda, 0xcd, 0x9c, 0x8e, 0x90, 0xc2, 0xed, 0x78, 0x75, 0xd0, 0x27, + 0xd4, 0xca, 0xfb, 0xf4, 0x29, 0x83, 0x15, 0xc9, 0x94, 0x9c, 0x1e, 0x7f, 0x7b, 0xf8, 0xbf, 0x6a, 0xe3, 0xed, 0x76, + 0xc0, 0x43, 0x20, 0x19, 0x53, 0xb2, 0x7e, 0x18, 0xd5, 0x8c, 0xaa, 0x97, 0x11, 0x44, 0x7a, 0xd1, 0xa5, 0x81, 0x0d, + 0x74, 0x4a, 0x55, 0x48, 0x85, 0xb3, 0x24, 0xae, 0xf8, 0xa5, 0x2c, 0x36, 0x51, 0x36, 0x6a, 0xa5, 0xd0, 0xc6, 0x02, + 0x88, 0x42, 0x10, 0x2c, 0x37, 0x92, 0x48, 0x4f, 0x11, 0x00, 0x6f, 0x08, 0xdc, 0xa8, 0xce, 0x5d, 0xb4, 0x80, 0x76, + 0xc1, 0x64, 0xb1, 0xdb, 0x75, 0x0c, 0x5a, 0x27, 0xed, 0x8b, 0xe6, 0x99, 0x22, 0x8a, 0x0b, 0x60, 0xcc, 0xe1, 0x78, + 0x53, 0x67, 0x17, 0x33, 0xc7, 0xdd, 0xa9, 0x8e, 0xfa, 0x09, 0xd6, 0x88, 0xee, 0xb5, 0x09, 0x2c, 0xd3, 0x3c, 0x0f, + 0xff, 0xbf, 0xf6, 0x9e, 0x36, 0xb9, 0x6d, 0x23, 0xd9, 0xff, 0x39, 0x05, 0x04, 0x7b, 0x6d, 0xc0, 0x06, 0x20, 0x80, + 0x14, 0x25, 0x9a, 0x14, 0xa8, 0xc4, 0xb6, 0x9c, 0x64, 0x57, 0x89, 0x53, 0xb6, 0xe2, 0xfd, 0xd0, 0xaa, 0x44, 0x90, + 0x1c, 0x92, 0x58, 0x83, 0x00, 0x0b, 0x00, 0x45, 0x2a, 0x34, 0xf6, 0x2c, 0x7b, 0x84, 0x77, 0x86, 0x3d, 0xd9, 0xab, + 0xee, 0x9e, 0x01, 0x06, 0x20, 0x48, 0x51, 0xb1, 0x93, 0xdd, 0x57, 0xf5, 0x2a, 0xb1, 0x4d, 0x0c, 0x66, 0x06, 0x3d, + 0x5f, 0xdd, 0x3d, 0xfd, 0x69, 0x57, 0x30, 0xae, 0x88, 0xf1, 0x5b, 0x29, 0xa5, 0x6d, 0xc6, 0x63, 0x2b, 0xc2, 0x4a, + 0x41, 0x3a, 0x2e, 0x21, 0xba, 0xd5, 0x02, 0xb0, 0x90, 0x29, 0xad, 0xaf, 0x98, 0x87, 0xa0, 0x13, 0x89, 0x30, 0x79, + 0x60, 0x32, 0xb8, 0xa5, 0xd6, 0xb4, 0x13, 0x97, 0x02, 0x5e, 0x46, 0xe5, 0x49, 0x3d, 0x8d, 0xcb, 0xcf, 0xb0, 0x8d, + 0x2b, 0x55, 0x50, 0x64, 0x5b, 0xae, 0x04, 0xa2, 0x85, 0xe1, 0x19, 0x7d, 0xde, 0x4a, 0xa3, 0x8b, 0x68, 0x29, 0xc4, + 0xc3, 0xa7, 0x71, 0x4d, 0x21, 0x9e, 0x8d, 0x8e, 0x77, 0x3a, 0xa4, 0x1f, 0x4e, 0xb6, 0x85, 0x08, 0x64, 0xc5, 0x04, + 0xe7, 0xcc, 0x69, 0x9f, 0xae, 0x4c, 0x37, 0x8f, 0xd7, 0x62, 0xe3, 0x65, 0x7d, 0x3f, 0x4f, 0xfe, 0x5a, 0x62, 0x2c, + 0x32, 0x3e, 0xf5, 0x72, 0xac, 0xd1, 0x9a, 0x6a, 0x7c, 0x7f, 0xb8, 0x7e, 0x2d, 0x77, 0x62, 0xd1, 0x23, 0xa3, 0x5c, + 0x98, 0xf5, 0x55, 0xd8, 0x8a, 0x0d, 0xb5, 0x3a, 0xc0, 0x48, 0xbc, 0x24, 0x86, 0x80, 0xe1, 0x97, 0x11, 0xe3, 0x7f, + 0x1b, 0x57, 0x31, 0x3e, 0x5a, 0xd9, 0xe5, 0x08, 0xff, 0xa7, 0xb7, 0xef, 0x2f, 0x41, 0x7b, 0xe5, 0xa1, 0xba, 0x79, + 0xad, 0x72, 0x4b, 0x15, 0x13, 0xf4, 0x41, 0x6a, 0x47, 0xf5, 0xe6, 0x40, 0x8f, 0xf1, 0x5e, 0x70, 0xb8, 0x32, 0x97, + 0xcb, 0xa5, 0x09, 0x76, 0xab, 0xe6, 0x22, 0x0e, 0x88, 0x07, 0x1c, 0xa9, 0x99, 0x40, 0xe4, 0xac, 0x82, 0xc8, 0x21, + 0xe8, 0x2d, 0xcf, 0x9a, 0xf2, 0x7e, 0x1a, 0x2d, 0xbf, 0x09, 0x02, 0x59, 0x38, 0x23, 0x58, 0x35, 0x2e, 0xaf, 0x28, + 0x21, 0x06, 0x0d, 0x74, 0x4c, 0x96, 0x9f, 0xdc, 0x70, 0xab, 0x80, 0xd1, 0xcd, 0xe0, 0xee, 0x86, 0x6b, 0x1e, 0xf2, + 0xa8, 0xc3, 0xef, 0xfb, 0xa7, 0x23, 0xff, 0x56, 0x41, 0x7e, 0xd2, 0x55, 0xc1, 0x65, 0x2b, 0x60, 0x83, 0x45, 0x9a, + 0x46, 0xa1, 0x19, 0x47, 0x4b, 0xb5, 0x77, 0x4a, 0x0f, 0xa2, 0x82, 0x47, 0x8f, 0xaa, 0xf2, 0xf5, 0x30, 0xf0, 0x87, + 0x1f, 0x5d, 0xf5, 0xf1, 0xda, 0x77, 0x7b, 0x15, 0xae, 0xd1, 0xce, 0xd4, 0x1e, 0xc0, 0xaa, 0x7c, 0x13, 0x04, 0xa7, + 0x87, 0xd4, 0xa2, 0x77, 0x7a, 0x38, 0xf2, 0x6f, 0x7b, 0x52, 0x02, 0x18, 0xae, 0x1d, 0x75, 0x79, 0xa0, 0xcd, 0xdc, + 0x9e, 0x2c, 0xc1, 0xc8, 0x0d, 0x43, 0xa6, 0x15, 0x57, 0x5c, 0x88, 0x28, 0x43, 0xf0, 0x6a, 0x43, 0x14, 0x9a, 0x07, + 0x70, 0xa1, 0xfb, 0xf4, 0x49, 0xcb, 0xad, 0x4d, 0xa7, 0x52, 0x28, 0x36, 0x54, 0xe6, 0x61, 0x15, 0x03, 0xe3, 0xc9, + 0xe8, 0x9a, 0x08, 0x18, 0x17, 0xe8, 0xc6, 0x30, 0x33, 0x30, 0x8f, 0x8e, 0x37, 0x07, 0xbd, 0x22, 0xff, 0x29, 0xdd, + 0x7b, 0x87, 0x90, 0x3b, 0x5b, 0x42, 0xdc, 0xba, 0xa4, 0x59, 0xa1, 0x53, 0xc8, 0xa3, 0x01, 0x82, 0x4a, 0x04, 0xbf, + 0x43, 0xda, 0x0e, 0x2d, 0xd0, 0x21, 0x77, 0x5b, 0x1e, 0x82, 0xc7, 0xcb, 0x44, 0xb6, 0x34, 0x31, 0x2f, 0x67, 0xa5, + 0x15, 0xea, 0x54, 0xd7, 0x4b, 0xc4, 0x86, 0x3c, 0x48, 0xb6, 0x2d, 0x19, 0x68, 0xea, 0xb4, 0xd4, 0xa8, 0xd0, 0x59, + 0xf0, 0xdd, 0x93, 0xd4, 0x43, 0xcc, 0xd0, 0xae, 0x12, 0x23, 0xba, 0x2e, 0x68, 0x53, 0x42, 0x88, 0xb2, 0x13, 0x65, + 0x45, 0x98, 0x66, 0x5a, 0xf5, 0xde, 0xe3, 0x75, 0x88, 0xc4, 0x2c, 0x71, 0x7b, 0xe5, 0x7d, 0x90, 0x7a, 0x03, 0x93, + 0x36, 0xb3, 0xaa, 0x7c, 0x3d, 0x1a, 0x04, 0xf9, 0x62, 0xd3, 0x21, 0x98, 0x7a, 0xe1, 0x28, 0x60, 0x97, 0xde, 0xe0, + 0x3b, 0xac, 0xf3, 0x7a, 0x10, 0xbc, 0x82, 0x0a, 0x99, 0xda, 0x7b, 0xbc, 0x26, 0x72, 0x5d, 0x87, 0xb0, 0x33, 0xda, + 0x02, 0xd5, 0xef, 0xf0, 0xc4, 0x4a, 0x2c, 0xa6, 0xd6, 0x08, 0x2c, 0x91, 0x58, 0xc2, 0xa8, 0x65, 0xc8, 0x78, 0x62, + 0x1f, 0xd8, 0x9b, 0x0a, 0x3f, 0xb5, 0x00, 0x57, 0x24, 0x4e, 0xb0, 0xbc, 0x33, 0x65, 0x60, 0x89, 0x94, 0xbe, 0x8b, + 0x96, 0x02, 0x52, 0x3e, 0x01, 0x14, 0x88, 0xf2, 0xec, 0x7d, 0xff, 0x54, 0x56, 0xfe, 0xa0, 0x84, 0x9c, 0xfa, 0x85, + 0x5f, 0x99, 0xaa, 0x14, 0x69, 0x9e, 0xe6, 0x2b, 0xb5, 0x77, 0x7a, 0x28, 0xd7, 0xee, 0xf5, 0x3b, 0xe7, 0xd2, 0xe0, + 0xb0, 0x57, 0x71, 0x3b, 0xbe, 0x2a, 0x1e, 0xb2, 0x6b, 0x05, 0xee, 0xc2, 0x19, 0x94, 0xc0, 0x1c, 0x95, 0x9b, 0x6c, + 0x90, 0x1f, 0x48, 0x8c, 0x58, 0x10, 0x28, 0xda, 0x3d, 0x02, 0x3f, 0x46, 0x7a, 0x27, 0x5f, 0x42, 0xb2, 0xbf, 0x14, + 0xbd, 0xf5, 0xf9, 0xbf, 0xc5, 0x94, 0xa0, 0x3c, 0x9b, 0x85, 0x49, 0x14, 0xab, 0x30, 0xcc, 0x6a, 0x76, 0x24, 0x45, + 0xca, 0xca, 0x86, 0x03, 0xae, 0x25, 0xab, 0x30, 0x61, 0x87, 0xd5, 0xa6, 0xd2, 0xb8, 0xfb, 0x7a, 0xf1, 0x43, 0xe1, + 0x83, 0xa9, 0x20, 0xad, 0x1c, 0xc0, 0xed, 0x59, 0xa7, 0xae, 0x1e, 0xfb, 0xc6, 0x9f, 0x23, 0x63, 0xe0, 0x19, 0x37, + 0x9e, 0xf1, 0x43, 0x78, 0x9d, 0xd5, 0x2e, 0x5e, 0x9e, 0x31, 0xce, 0x60, 0x5d, 0x0d, 0xe2, 0x2c, 0x95, 0xef, 0x15, + 0xbe, 0xc5, 0x2d, 0x43, 0x2e, 0xbd, 0x78, 0xc2, 0x44, 0xa2, 0x36, 0xf1, 0x56, 0x48, 0x08, 0x74, 0x69, 0x5a, 0x20, + 0x08, 0xd9, 0x01, 0x37, 0xa0, 0xf3, 0xad, 0x61, 0x1a, 0x07, 0x7f, 0x62, 0x77, 0x70, 0x9d, 0x4c, 0xd2, 0x68, 0x0e, + 0x92, 0x29, 0x6f, 0xc2, 0x35, 0x0d, 0x06, 0x30, 0x35, 0xfb, 0x7c, 0xee, 0xd3, 0x27, 0x26, 0xe5, 0x0e, 0x4b, 0xa3, + 0xc9, 0x24, 0x60, 0x9a, 0x94, 0x63, 0x2c, 0xff, 0xcc, 0xd9, 0x81, 0x2d, 0xe2, 0x53, 0xeb, 0xd9, 0xb6, 0x83, 0x55, + 0x70, 0x80, 0x42, 0xa7, 0x0f, 0x88, 0x8b, 0x4c, 0xa8, 0x90, 0x09, 0xd7, 0xc4, 0xb9, 0x28, 0x0e, 0xae, 0x39, 0x8a, + 0x16, 0x83, 0x80, 0x99, 0x78, 0x1a, 0xe0, 0x93, 0xeb, 0xc1, 0x62, 0x30, 0x08, 0x28, 0x29, 0x18, 0x44, 0x59, 0x8b, + 0x12, 0x94, 0x7e, 0x66, 0x7a, 0x17, 0x39, 0xb5, 0xb4, 0x0a, 0x3e, 0x58, 0x46, 0xc2, 0x6d, 0x81, 0x3e, 0x90, 0x82, + 0xa4, 0x73, 0xf3, 0x4c, 0xbb, 0x2a, 0xdc, 0x52, 0x58, 0xa2, 0x76, 0x6b, 0x58, 0x3a, 0xf7, 0x4a, 0x7d, 0x8f, 0x33, + 0xac, 0x78, 0xe1, 0x48, 0x79, 0x45, 0x7b, 0x57, 0x35, 0x54, 0x32, 0xf0, 0xe2, 0x39, 0xe4, 0x54, 0x43, 0x7d, 0xed, + 0x7b, 0x93, 0x30, 0x4a, 0x52, 0x7f, 0xa8, 0x5e, 0x77, 0x5f, 0xfb, 0xda, 0xd5, 0x2c, 0xd5, 0xf4, 0x6b, 0xe3, 0x5b, + 0x39, 0xdb, 0x97, 0xc0, 0x94, 0x98, 0xec, 0x6b, 0x4b, 0x1d, 0xf9, 0xf4, 0xec, 0xaa, 0x27, 0x30, 0x32, 0xd6, 0xf9, + 0xd6, 0x85, 0x5a, 0x95, 0xbc, 0x61, 0x98, 0x10, 0x12, 0xf2, 0x86, 0x7d, 0xab, 0x77, 0x49, 0xd4, 0xf2, 0xcd, 0x62, + 0x8d, 0x4c, 0x43, 0x5a, 0x10, 0x5f, 0x0c, 0x75, 0x2f, 0xfc, 0x43, 0xe9, 0xf9, 0x40, 0xf6, 0x6d, 0x28, 0x91, 0xf1, + 0xfe, 0x37, 0x65, 0x0e, 0xe4, 0xf1, 0x3a, 0xcd, 0xc0, 0xb0, 0x30, 0x8c, 0x52, 0x05, 0xe2, 0xb7, 0xc1, 0x07, 0xfb, + 0x55, 0x5b, 0x68, 0xde, 0xab, 0xa6, 0x67, 0x1c, 0x0b, 0xbc, 0x44, 0x5a, 0x8a, 0xf2, 0x49, 0x08, 0x37, 0x01, 0xa1, + 0x48, 0x4b, 0xd1, 0x9a, 0xb8, 0x07, 0x1e, 0x2c, 0x5f, 0x89, 0x7f, 0x93, 0xf0, 0x7e, 0x99, 0x9e, 0x3f, 0x5e, 0x27, + 0x67, 0x82, 0xa8, 0x7f, 0x9f, 0xe0, 0x5a, 0x02, 0xbb, 0xc2, 0xa9, 0x7c, 0xa6, 0x2a, 0x67, 0x82, 0x12, 0x61, 0xdd, + 0x12, 0x7a, 0xd5, 0x04, 0xbb, 0x1b, 0x8b, 0xc8, 0xf8, 0x3c, 0xfd, 0xb8, 0x60, 0xc0, 0x2a, 0x47, 0x0f, 0x42, 0x32, + 0xe5, 0xbc, 0x55, 0x0a, 0x76, 0xd5, 0x48, 0x30, 0x00, 0x73, 0x71, 0x1e, 0xa1, 0x9f, 0xdd, 0x00, 0x23, 0x09, 0x71, + 0xca, 0xc4, 0x18, 0x8d, 0x48, 0x4e, 0x15, 0xe7, 0x87, 0xf3, 0x45, 0x8a, 0xf1, 0xe7, 0x01, 0x00, 0x96, 0xa9, 0x0a, + 0x5e, 0x12, 0x01, 0xd7, 0x17, 0x97, 0x9f, 0x4c, 0x55, 0xfc, 0xd1, 0x66, 0x19, 0x97, 0xc7, 0x00, 0x8e, 0xc3, 0x61, + 0xa0, 0xf6, 0x06, 0x1e, 0x63, 0x3e, 0x8c, 0xa1, 0x51, 0x24, 0x6f, 0xd1, 0x86, 0x68, 0xe5, 0x50, 0x83, 0x40, 0x86, + 0xd4, 0x4f, 0x57, 0x0b, 0x6a, 0x07, 0x0b, 0x31, 0xa9, 0x4b, 0xc3, 0xec, 0x83, 0x24, 0xf2, 0x0c, 0xe6, 0xce, 0x7d, + 0xbc, 0xf6, 0x72, 0x03, 0x3a, 0xf5, 0x52, 0x25, 0xeb, 0xb9, 0x3e, 0x4e, 0x43, 0x3f, 0xbb, 0x29, 0xdc, 0x59, 0x8b, + 0xf1, 0xc2, 0x96, 0xa4, 0x72, 0x05, 0xed, 0xd9, 0x5c, 0x6e, 0xb5, 0x36, 0x8f, 0xfd, 0x99, 0x17, 0xdf, 0x91, 0x91, + 0x9b, 0x21, 0x5b, 0xc2, 0xe9, 0xaa, 0x42, 0xf4, 0x80, 0x26, 0x80, 0x48, 0x83, 0xaa, 0x7c, 0x9d, 0x97, 0x31, 0x3e, + 0xda, 0xdc, 0xd2, 0x07, 0xbe, 0x75, 0xa3, 0x3e, 0x67, 0x16, 0x49, 0x19, 0xa9, 0x49, 0x57, 0x4b, 0xb6, 0x0c, 0x2f, + 0x29, 0x0f, 0x2f, 0x2c, 0x6f, 0x34, 0x1c, 0x0c, 0x51, 0x0a, 0x82, 0x1b, 0x47, 0x86, 0xa9, 0x2e, 0xeb, 0x57, 0x94, + 0xde, 0xfd, 0xae, 0xcb, 0xc1, 0x60, 0x39, 0x42, 0x58, 0x8e, 0x1a, 0x01, 0xac, 0x27, 0x56, 0x04, 0x78, 0x11, 0xe0, + 0x42, 0x62, 0xe4, 0x40, 0x28, 0x0b, 0xa6, 0x92, 0x6f, 0xa1, 0x18, 0x8e, 0x06, 0xc1, 0x4e, 0x47, 0x23, 0x76, 0xdd, + 0x08, 0x5b, 0xc5, 0xd9, 0xe9, 0x21, 0xd5, 0x26, 0xa2, 0x48, 0x95, 0x60, 0x1a, 0x62, 0x18, 0x61, 0x31, 0x0b, 0x90, + 0x06, 0xdc, 0x75, 0x8a, 0x8b, 0x8e, 0x35, 0x43, 0xe5, 0xb3, 0x73, 0x56, 0x66, 0x78, 0xb0, 0x95, 0xda, 0x3b, 0xc5, + 0xc4, 0x9e, 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xe9, 0x21, 0x3d, 0x2a, 0x95, 0x13, 0x51, 0x74, 0x22, 0xa4, 0x8e, 0x1d, + 0xde, 0xc1, 0x83, 0x8e, 0x4a, 0x92, 0xb2, 0x39, 0x94, 0x7a, 0x99, 0xaa, 0xcc, 0x38, 0x83, 0xc5, 0x63, 0xec, 0x41, + 0x00, 0x1e, 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xe6, 0xad, 0x70, 0xe4, 0xe2, 0x8d, 0xb7, 0xd2, 0x1c, 0xfe, 0xaa, 0x38, + 0x6b, 0x49, 0xf9, 0xac, 0x0d, 0xf9, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x29, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, + 0x54, 0x2c, 0xee, 0x68, 0xcb, 0xe2, 0x8e, 0x76, 0x2c, 0x6e, 0xc0, 0x17, 0x52, 0xc9, 0xa7, 0x2e, 0x46, 0x8f, 0xe9, + 0x7c, 0xf2, 0x38, 0x3f, 0xd2, 0xe1, 0xe7, 0x0c, 0xe7, 0xc9, 0x4c, 0x02, 0xb0, 0x18, 0xde, 0x32, 0x57, 0x75, 0xf3, + 0x22, 0x4d, 0xc4, 0xe6, 0xc0, 0xf3, 0x53, 0x37, 0x94, 0x24, 0x03, 0x5a, 0x50, 0x1d, 0x2f, 0xec, 0x52, 0x6c, 0x68, + 0x68, 0xd3, 0x2d, 0x23, 0x9d, 0xee, 0x18, 0xe9, 0xb0, 0x74, 0x74, 0xf9, 0xb0, 0xe9, 0x10, 0xca, 0x83, 0x82, 0x3d, + 0x08, 0x5e, 0x14, 0xb8, 0x65, 0xca, 0xfb, 0x70, 0x3b, 0x8e, 0x95, 0x76, 0xd4, 0xdc, 0x4b, 0x92, 0x65, 0x14, 0x83, + 0x19, 0x02, 0x74, 0xf3, 0xb0, 0x2d, 0x35, 0xf3, 0x43, 0x1e, 0xe1, 0x6c, 0xeb, 0x66, 0x2a, 0xde, 0xcb, 0x5b, 0xaa, + 0xd1, 0x6a, 0x51, 0x8d, 0xb9, 0x97, 0xa6, 0x2c, 0xc6, 0x49, 0xf7, 0x20, 0x15, 0xc6, 0x7f, 0xc9, 0x36, 0xab, 0xc1, + 0x21, 0x81, 0x84, 0xd5, 0x11, 0x43, 0xcf, 0x81, 0x05, 0x23, 0xbd, 0x63, 0xa8, 0xaf, 0xa5, 0x68, 0xa9, 0x71, 0x3e, + 0xf1, 0x3f, 0xe2, 0x71, 0xd5, 0x62, 0xc9, 0x9f, 0xd7, 0x39, 0xd6, 0xad, 0xb9, 0x37, 0x7a, 0x0f, 0xd6, 0x2e, 0x5a, + 0xc3, 0x00, 0xcf, 0x15, 0x39, 0x36, 0x6a, 0x4c, 0x3c, 0xe1, 0xb0, 0x40, 0x92, 0x88, 0x25, 0xb9, 0x5d, 0x30, 0x84, + 0x14, 0xf0, 0xcc, 0xf1, 0xf5, 0xba, 0x91, 0x1d, 0x4e, 0x7c, 0x7d, 0x03, 0x6b, 0x02, 0x6a, 0x0b, 0xdc, 0x5e, 0x2e, + 0x74, 0x0b, 0x0c, 0xe7, 0x58, 0x07, 0x75, 0xe8, 0x15, 0x24, 0x3d, 0xb7, 0xc5, 0x65, 0xba, 0x1f, 0x03, 0xd5, 0x02, + 0xe5, 0xe1, 0x93, 0x09, 0xfe, 0x72, 0xae, 0xb3, 0x27, 0x03, 0xfc, 0xd5, 0xb8, 0xce, 0x55, 0x55, 0x15, 0x29, 0x82, + 0x34, 0x66, 0xb5, 0x57, 0xda, 0x4f, 0x64, 0x94, 0xfd, 0x80, 0x6d, 0xc3, 0x17, 0xf8, 0xd1, 0xe3, 0x75, 0x02, 0x61, + 0x08, 0xe4, 0x31, 0x84, 0x56, 0xac, 0x67, 0xb5, 0xe5, 0x93, 0x2d, 0xe5, 0x03, 0xfd, 0x77, 0x26, 0xfc, 0xb8, 0x4b, + 0xa2, 0x82, 0xa6, 0x94, 0x65, 0x20, 0x37, 0x03, 0x3f, 0xf4, 0xe2, 0xbb, 0x1b, 0xba, 0x85, 0x68, 0x92, 0x90, 0xf7, + 0xa0, 0x10, 0x0e, 0xdc, 0x95, 0x6d, 0x40, 0x52, 0x49, 0x41, 0x75, 0xc7, 0x09, 0xbd, 0xfb, 0xa7, 0x58, 0xe2, 0xef, + 0x4a, 0xd7, 0x58, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3c, 0x5e, 0x6b, 0x6c, 0xb3, 0x9b, 0xca, 0x68, 0x2b, 0x0c, 0x24, + 0x2c, 0x0f, 0x5e, 0x89, 0x67, 0x23, 0xbf, 0x83, 0x46, 0x1e, 0x83, 0x68, 0x65, 0x3e, 0x5e, 0xa7, 0x67, 0xea, 0xcc, + 0x8b, 0x3f, 0xb2, 0x91, 0x39, 0xf4, 0xe3, 0x61, 0x00, 0xcc, 0xe3, 0x20, 0xf0, 0xc2, 0x8f, 0xfc, 0xd1, 0x8c, 0x16, + 0x29, 0x9a, 0x6d, 0xdd, 0x7b, 0x83, 0x16, 0x73, 0x42, 0x82, 0x44, 0xe4, 0x6a, 0x6b, 0x66, 0x41, 0x79, 0xdf, 0x17, + 0xd7, 0xfa, 0x82, 0x51, 0x2c, 0x6a, 0x19, 0xe0, 0x75, 0x00, 0x96, 0x64, 0x10, 0xc6, 0xc1, 0x50, 0x71, 0xbd, 0x54, + 0x43, 0x1e, 0x2a, 0xe9, 0xd1, 0xf2, 0x3c, 0xc4, 0x37, 0xd8, 0xc3, 0xaf, 0xff, 0x1c, 0x94, 0x3c, 0xe4, 0x73, 0x79, + 0x2f, 0x9f, 0x37, 0x42, 0x28, 0x35, 0xc9, 0x7d, 0xf0, 0x01, 0x1f, 0xe7, 0x0c, 0xe6, 0xf6, 0x4f, 0xcb, 0x8d, 0xbd, + 0x24, 0x59, 0xcc, 0xd8, 0x88, 0x94, 0x61, 0x67, 0x05, 0x50, 0xe5, 0x7b, 0x88, 0x0c, 0xd8, 0xdf, 0x17, 0x8d, 0x93, + 0xa3, 0x57, 0x60, 0xc6, 0x07, 0x0c, 0x65, 0x34, 0x1e, 0xab, 0x85, 0x28, 0xe0, 0x9e, 0x66, 0xce, 0xd1, 0xdf, 0x17, + 0x6f, 0xce, 0xed, 0x37, 0x79, 0xe3, 0x10, 0x18, 0x63, 0x61, 0x93, 0xc4, 0xf9, 0x62, 0x09, 0x5e, 0x31, 0xa2, 0xb1, + 0x17, 0x6e, 0x1f, 0xce, 0x55, 0x69, 0x8b, 0xcf, 0x19, 0x1b, 0x01, 0xc3, 0x6d, 0x6c, 0x94, 0xde, 0x04, 0xec, 0x96, + 0xe5, 0xf6, 0x4e, 0x9b, 0x1f, 0xab, 0x69, 0x81, 0x01, 0x59, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0xfa, 0x38, + 0x06, 0x3e, 0x72, 0xf9, 0x88, 0x55, 0x8e, 0x54, 0xdf, 0x50, 0x25, 0x00, 0xb6, 0x42, 0x76, 0xb6, 0xa5, 0xbc, 0x03, + 0x88, 0x7a, 0x0b, 0x6c, 0x86, 0xa3, 0x77, 0x20, 0x81, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0xb6, + 0xcd, 0x58, 0x9d, 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x01, 0x40, 0x5f, 0x18, 0x21, 0xae, 0xaa, 0x5d, 0x1b, 0xa5, + 0x3c, 0xf2, 0x01, 0xa6, 0x77, 0x0f, 0x59, 0x92, 0x6c, 0x9d, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, + 0xa2, 0xdc, 0xb0, 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x99, 0x71, 0x23, 0xce, 0x78, 0x32, + 0x50, 0xb9, 0x81, 0xdd, 0xb6, 0xf7, 0x4b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0xb5, 0xa0, 0x69, 0x25, 0xd4, 0xbb, 0x21, + 0x55, 0xc2, 0x0e, 0x04, 0x4c, 0x15, 0xfc, 0xca, 0xc6, 0x63, 0x36, 0x4c, 0x13, 0x5d, 0xc8, 0x98, 0xf2, 0x90, 0xea, + 0xa0, 0xb4, 0x3b, 0x70, 0xd5, 0x1f, 0x21, 0xb0, 0x8c, 0x88, 0x3c, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xfa, 0x69, 0xa2, + 0x1e, 0xcb, 0x53, 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x9a, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0xa9, + 0xe7, 0x6e, 0x54, 0xb4, 0xeb, 0xf8, 0xae, 0x9d, 0x37, 0x2d, 0xc7, 0xce, 0x54, 0x03, 0x1c, 0x9a, 0x3f, 0x56, 0xb6, + 0x31, 0x11, 0x28, 0x57, 0xbd, 0x78, 0xfb, 0xea, 0x4f, 0xe7, 0xaf, 0xf7, 0xc5, 0x08, 0xd8, 0x65, 0x13, 0xba, 0x5c, + 0x84, 0x3b, 0x3a, 0xfd, 0xf9, 0xc7, 0x87, 0x75, 0xdb, 0x70, 0x5e, 0x38, 0xaa, 0x41, 0x36, 0xe8, 0x12, 0x5e, 0x1c, + 0x46, 0xb7, 0x2c, 0xfe, 0xec, 0x69, 0x90, 0x3b, 0xaf, 0x07, 0xf7, 0xed, 0x4f, 0xe7, 0x3f, 0xee, 0x0d, 0xea, 0xb1, + 0x63, 0x03, 0x6e, 0x4f, 0xa3, 0xf9, 0x03, 0x46, 0xd7, 0x54, 0x0d, 0x75, 0x18, 0x44, 0x09, 0xdb, 0x02, 0xc1, 0xab, + 0x8b, 0xb7, 0xef, 0x71, 0xba, 0x0a, 0x16, 0x84, 0xba, 0xfa, 0xbc, 0xc1, 0xff, 0xf4, 0xee, 0xfc, 0xfd, 0x7b, 0xd5, + 0xc0, 0x94, 0xdc, 0x89, 0xdc, 0x3b, 0xdf, 0xc4, 0xf7, 0x50, 0x9c, 0xda, 0xbd, 0x4e, 0x54, 0x8d, 0x2e, 0xd2, 0xe5, + 0xd1, 0x50, 0xd9, 0xc6, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x7b, 0x8d, 0xab, 0x06, 0x1f, 0xed, 0x26, + 0xa9, 0xa5, 0x92, 0x99, 0x1f, 0xde, 0xd4, 0x94, 0x7a, 0xab, 0x9a, 0x52, 0xb8, 0x3e, 0x6e, 0xe0, 0xc7, 0x45, 0x34, + 0x93, 0xd8, 0x11, 0xb6, 0xba, 0x7f, 0xba, 0xa4, 0x3b, 0xdc, 0x67, 0x00, 0xcd, 0x53, 0xaa, 0x54, 0xa1, 0xae, 0x29, + 0xe6, 0x17, 0xaf, 0x7c, 0x6e, 0x87, 0x01, 0x58, 0xde, 0x33, 0x59, 0x0d, 0x59, 0x66, 0x55, 0xb9, 0xdf, 0x8c, 0x5b, + 0xb9, 0x15, 0x50, 0x33, 0x52, 0xdd, 0x70, 0x9a, 0x32, 0xf7, 0x46, 0x60, 0xce, 0x6e, 0x0e, 0xa2, 0x34, 0x8d, 0x66, + 0x1d, 0xc7, 0x9e, 0xaf, 0x54, 0xa5, 0x2b, 0x84, 0x1d, 0xdc, 0xda, 0xbe, 0xf3, 0xef, 0x7f, 0x55, 0xd0, 0x3c, 0x95, + 0xdf, 0xa4, 0x6c, 0x36, 0x67, 0xb1, 0x97, 0x2e, 0x62, 0x96, 0x29, 0xff, 0xfe, 0x9f, 0x57, 0x95, 0x8b, 0x7d, 0x57, + 0x6e, 0x43, 0x2c, 0xbd, 0xdc, 0xe4, 0x26, 0x88, 0x96, 0x07, 0x85, 0x5f, 0xdd, 0x3d, 0x95, 0xa7, 0xfe, 0x64, 0x9a, + 0xd7, 0x3e, 0x4b, 0x77, 0x8c, 0x4d, 0x40, 0x4f, 0xfa, 0x00, 0xe5, 0x22, 0x5a, 0x76, 0xfe, 0xfd, 0xaf, 0x5c, 0x60, + 0x73, 0xef, 0xae, 0xab, 0x07, 0xb4, 0xbc, 0xa2, 0xf5, 0x75, 0x36, 0x96, 0x18, 0xde, 0x6f, 0x2c, 0xf0, 0x46, 0x21, + 0xed, 0xca, 0x4d, 0xdd, 0xdc, 0x8e, 0x31, 0x7d, 0xe7, 0x4f, 0xa6, 0x9f, 0x3b, 0x28, 0x98, 0xd0, 0x7b, 0x47, 0x05, + 0x95, 0xbe, 0xc0, 0xb0, 0xfa, 0x9d, 0xfd, 0x17, 0xec, 0x33, 0xc7, 0x75, 0xdf, 0x90, 0xbe, 0xc4, 0x68, 0xb8, 0xe4, + 0xf6, 0x7d, 0xbf, 0x9f, 0xa7, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0xd9, 0x46, 0x09, 0x67, 0x2f, 0x3a, 0xb6, 0x4e, + 0x21, 0x7b, 0xf6, 0x98, 0x10, 0xb4, 0x71, 0xaf, 0x99, 0x8e, 0xed, 0xf8, 0x9a, 0x5c, 0xd5, 0x36, 0xbe, 0xbd, 0x81, + 0xac, 0xa1, 0x14, 0xd3, 0x99, 0xe6, 0x5a, 0x43, 0xa3, 0x1e, 0x9c, 0x65, 0xec, 0xcd, 0x49, 0x49, 0xa0, 0xa0, 0xc6, + 0x04, 0x84, 0x2e, 0x95, 0x5b, 0xf4, 0xad, 0x17, 0xdc, 0xee, 0x77, 0xa1, 0xda, 0x4e, 0xc1, 0x90, 0x34, 0xff, 0xe7, + 0x88, 0x37, 0xd2, 0xe5, 0x07, 0xd3, 0xee, 0xa5, 0x97, 0xb2, 0xf8, 0x66, 0x0a, 0x3e, 0xbd, 0x42, 0x7a, 0x00, 0xd1, + 0x72, 0x77, 0x21, 0xe5, 0x12, 0x5b, 0x5a, 0x83, 0x46, 0x0b, 0x0c, 0xf7, 0xeb, 0x70, 0xf7, 0x17, 0xc2, 0xdc, 0x9d, + 0x73, 0xf0, 0xba, 0xfc, 0xcd, 0xb0, 0xf7, 0x2e, 0xca, 0xf4, 0xff, 0xd8, 0xfb, 0xbf, 0x11, 0x7b, 0xef, 0xfc, 0xce, + 0xaf, 0x59, 0xd8, 0xff, 0x03, 0x58, 0xbe, 0xc3, 0xdc, 0x73, 0x8e, 0xe9, 0x35, 0xcd, 0x73, 0x85, 0x72, 0x55, 0xc6, + 0xab, 0x1b, 0x0a, 0x56, 0x1e, 0x52, 0x8d, 0x5b, 0x0e, 0x7a, 0x88, 0xec, 0x77, 0x1c, 0xe5, 0xdf, 0x1e, 0xd1, 0x27, + 0x94, 0x87, 0x4a, 0xc2, 0xf4, 0x9d, 0x73, 0x23, 0x29, 0x8d, 0xc4, 0x5b, 0x7a, 0x77, 0xfb, 0xe0, 0x1d, 0x01, 0xec, + 0x37, 0x4b, 0xef, 0xae, 0x0e, 0xd8, 0xad, 0xe8, 0xb5, 0xfa, 0xb1, 0x33, 0xf0, 0xe5, 0xe9, 0xa0, 0x23, 0x8f, 0xd1, + 0x4f, 0x58, 0x7a, 0x06, 0x85, 0xee, 0xe3, 0xf5, 0x41, 0xb5, 0x62, 0xd6, 0x07, 0x2f, 0x67, 0x09, 0xf0, 0xa8, 0x04, + 0xb8, 0x9f, 0xdc, 0x44, 0xe1, 0x43, 0x20, 0xff, 0x09, 0x84, 0x3f, 0xbf, 0x1a, 0x74, 0xfc, 0xdc, 0x06, 0xec, 0x58, + 0x5a, 0x05, 0x1e, 0x0b, 0xab, 0xd0, 0x77, 0xeb, 0x65, 0xf5, 0x15, 0x42, 0x8b, 0x34, 0x96, 0x11, 0xa1, 0x55, 0x40, + 0xaf, 0xa2, 0x80, 0x8e, 0xab, 0x42, 0x72, 0xfd, 0x70, 0x1c, 0x7b, 0x31, 0x1b, 0x6d, 0xbf, 0x02, 0x94, 0x2c, 0x95, + 0xef, 0xac, 0x64, 0x31, 0x9f, 0x47, 0x71, 0x9a, 0xdc, 0x60, 0x34, 0x96, 0x99, 0x0f, 0x17, 0x0a, 0xc8, 0x1b, 0x96, + 0xc7, 0xe6, 0x3d, 0xaf, 0x93, 0x6f, 0x1b, 0xcc, 0x2d, 0xa7, 0xd4, 0xe0, 0x3e, 0x36, 0x06, 0xf7, 0xd2, 0x99, 0x4a, + 0xfa, 0x8b, 0xa9, 0x95, 0xc6, 0xfe, 0x4c, 0xd3, 0x0d, 0xc7, 0xd6, 0x75, 0x21, 0x5f, 0x99, 0xba, 0xbd, 0x03, 0x8a, + 0x29, 0x3c, 0xd5, 0x21, 0x36, 0x21, 0xfa, 0xad, 0x80, 0xad, 0xdc, 0xcb, 0xc5, 0x78, 0xcc, 0x62, 0x4d, 0x04, 0x5f, + 0x84, 0xe8, 0xaf, 0x64, 0x0c, 0x08, 0xde, 0x8c, 0x1f, 0x7c, 0xb6, 0x84, 0x2c, 0x4f, 0x45, 0xf0, 0x74, 0xf0, 0xe8, + 0x24, 0x13, 0x72, 0xc8, 0x20, 0x97, 0x36, 0x1b, 0xda, 0xe8, 0xd9, 0x91, 0x31, 0x85, 0x90, 0x4b, 0x85, 0x13, 0x3c, + 0x46, 0xf3, 0xf3, 0xc3, 0xb4, 0x8d, 0x5f, 0x80, 0x0e, 0xe0, 0xf0, 0x06, 0x6e, 0xee, 0xfd, 0xa4, 0x0c, 0xf3, 0x0e, + 0xa7, 0x6e, 0x2f, 0x78, 0xee, 0x92, 0x9e, 0x07, 0xed, 0xf6, 0x5e, 0x4d, 0xbd, 0xf8, 0x55, 0x34, 0x62, 0x08, 0xe8, + 0x20, 0x8d, 0xc0, 0x27, 0x53, 0x0a, 0xb6, 0x83, 0xb1, 0x76, 0xcc, 0x52, 0xfc, 0x9d, 0x43, 0x28, 0xba, 0x91, 0x8b, + 0xdc, 0xe7, 0x8f, 0x0f, 0x0d, 0x38, 0x69, 0xf5, 0x2b, 0x2d, 0x16, 0x8d, 0x2f, 0x75, 0xed, 0x2b, 0x79, 0xb7, 0xbe, + 0xf2, 0xe2, 0xd8, 0x67, 0xb1, 0xa2, 0x7d, 0xf7, 0x8b, 0x2e, 0x6f, 0xda, 0x92, 0x42, 0x87, 0x6b, 0x99, 0x15, 0x8c, + 0x39, 0x37, 0xf6, 0x59, 0x30, 0x72, 0xd5, 0x21, 0x35, 0xcc, 0x95, 0x37, 0xcd, 0xb6, 0x6d, 0xdb, 0x5c, 0x61, 0xea, + 0xd0, 0x4f, 0x50, 0x98, 0xc2, 0x4f, 0x78, 0x28, 0x89, 0x17, 0xdb, 0xc4, 0x45, 0x6c, 0x90, 0xb3, 0x5a, 0x08, 0xdf, + 0x51, 0xd4, 0x9e, 0x87, 0xc0, 0xc6, 0xa3, 0xfb, 0x08, 0xd0, 0x1c, 0x01, 0x56, 0x01, 0x53, 0x05, 0xa0, 0xd6, 0x43, + 0x00, 0xba, 0xf4, 0x67, 0x7e, 0x38, 0x49, 0xb6, 0x42, 0x84, 0x6a, 0xd3, 0x12, 0x3c, 0x29, 0xb5, 0x50, 0x15, 0x5c, + 0xc3, 0x69, 0x14, 0x40, 0xb6, 0x21, 0x95, 0x59, 0x13, 0x4b, 0x79, 0x61, 0xdb, 0xb6, 0x61, 0x1e, 0x41, 0x5e, 0xbf, + 0xd6, 0xb1, 0x6d, 0x98, 0xf0, 0x97, 0x65, 0x59, 0x35, 0xf2, 0xd8, 0xee, 0xcc, 0x0f, 0x4d, 0x7a, 0x6c, 0xd8, 0xfb, + 0xc1, 0x7b, 0xaf, 0x55, 0x6f, 0xc2, 0x75, 0x63, 0x83, 0xdc, 0x41, 0x54, 0x1b, 0xb8, 0x49, 0xd9, 0xd6, 0xcd, 0xa2, + 0xb0, 0x4a, 0x3c, 0xea, 0x45, 0x85, 0x18, 0x0d, 0xca, 0x6f, 0x91, 0x2d, 0x8d, 0xab, 0xd9, 0x2a, 0xd4, 0xef, 0x39, + 0x58, 0x1d, 0xe5, 0x55, 0xb4, 0x08, 0x46, 0x68, 0x0e, 0x05, 0xb6, 0xcb, 0x4a, 0x61, 0x15, 0x5a, 0x49, 0x29, 0x05, + 0x19, 0xc3, 0x31, 0x9d, 0xda, 0x7b, 0x24, 0x4e, 0x51, 0xac, 0x3d, 0xc5, 0x29, 0xbe, 0xaa, 0xdb, 0x82, 0xd7, 0x4f, + 0x21, 0x6a, 0xd0, 0x1e, 0x0d, 0xf8, 0xbe, 0x80, 0xfa, 0xc1, 0x3e, 0xf5, 0xc5, 0xba, 0x5d, 0x3f, 0xa5, 0xd0, 0xb2, + 0xde, 0xa7, 0x4f, 0x07, 0xc3, 0x4f, 0x9f, 0x0e, 0x36, 0xf2, 0x71, 0x6c, 0x1f, 0x21, 0x6d, 0x0c, 0xc6, 0x03, 0x89, + 0x40, 0x74, 0x20, 0x02, 0xfa, 0x7b, 0x28, 0xef, 0x78, 0x3c, 0x26, 0x15, 0x3d, 0x0d, 0x0d, 0xfe, 0x41, 0x7a, 0x0c, + 0xb2, 0xca, 0xa4, 0x4c, 0x5d, 0x8f, 0xc4, 0x3c, 0x9f, 0x3e, 0xf1, 0xe3, 0x66, 0x8c, 0xdc, 0x61, 0x5e, 0xe4, 0xa8, + 0xc6, 0xc2, 0x0d, 0xf2, 0x47, 0x15, 0x41, 0x5e, 0x70, 0x8c, 0x59, 0x40, 0xbc, 0xf4, 0xe2, 0x50, 0x06, 0xf8, 0xc7, + 0x48, 0xe1, 0x9f, 0x55, 0x78, 0xdc, 0xd3, 0x51, 0x75, 0x35, 0xc6, 0x2e, 0xd3, 0x16, 0x84, 0x03, 0x85, 0xa5, 0x9b, + 0xd4, 0xc1, 0xa5, 0xc0, 0xf6, 0x98, 0xfc, 0x54, 0x0c, 0x10, 0xbd, 0xa8, 0xf1, 0xe4, 0x8e, 0xc4, 0xb0, 0xde, 0x79, + 0xcb, 0xce, 0x42, 0x3c, 0x9c, 0x93, 0x49, 0x7c, 0x67, 0x9c, 0x7b, 0x27, 0xcf, 0xc9, 0xb7, 0x70, 0xe2, 0x7e, 0x1b, + 0x6b, 0x73, 0x23, 0x35, 0x54, 0x41, 0x46, 0x54, 0xdd, 0x98, 0xd5, 0x85, 0x51, 0xed, 0xce, 0x78, 0x50, 0x19, 0x4d, + 0x6c, 0x85, 0x9b, 0x31, 0xfa, 0x2a, 0x84, 0xc3, 0x3b, 0x0c, 0x93, 0x5c, 0xbc, 0x27, 0x50, 0x6e, 0x78, 0x8e, 0xbd, + 0x91, 0xfc, 0x0a, 0x16, 0x5c, 0x35, 0xc6, 0xba, 0x41, 0x3e, 0x00, 0x93, 0x2f, 0x69, 0xee, 0x4f, 0x91, 0x93, 0x67, + 0x52, 0x50, 0x57, 0xe1, 0x00, 0x70, 0x53, 0x71, 0x00, 0xa8, 0x99, 0x4f, 0x25, 0x66, 0xc9, 0x3c, 0x0a, 0xe1, 0xae, + 0x78, 0x53, 0x78, 0x75, 0xdd, 0x6c, 0x7a, 0x75, 0xd5, 0x34, 0xc5, 0x37, 0xd4, 0x0e, 0x54, 0xd2, 0x97, 0x7f, 0xa9, + 0x58, 0xe8, 0x0b, 0x52, 0x8f, 0xb9, 0xc8, 0xcf, 0xb7, 0xf9, 0x6f, 0x7f, 0x7f, 0xbf, 0xff, 0xf6, 0xc5, 0x5e, 0xfe, + 0xdb, 0xdf, 0x7f, 0x71, 0xff, 0xed, 0x73, 0xd9, 0x7f, 0x1b, 0x48, 0xf0, 0x39, 0xdb, 0xcb, 0x5d, 0x56, 0xb8, 0xb4, + 0x44, 0xcb, 0xc4, 0x75, 0xb8, 0x66, 0x2d, 0x19, 0x4e, 0x19, 0x98, 0x2a, 0x70, 0x56, 0x37, 0x88, 0x26, 0xe0, 0xd5, + 0xba, 0xdd, 0x6f, 0xf5, 0x4b, 0x79, 0xad, 0x06, 0xd1, 0x44, 0x95, 0xb2, 0xb1, 0x85, 0x22, 0x1b, 0x1b, 0x44, 0xa0, + 0xfb, 0xfb, 0xca, 0x79, 0x79, 0xe5, 0x74, 0x9b, 0x0e, 0x44, 0x33, 0x05, 0xed, 0x33, 0x16, 0xd8, 0xdd, 0x66, 0x13, + 0x0a, 0x96, 0x52, 0x41, 0x03, 0x0a, 0x7c, 0xa9, 0xa0, 0x05, 0x05, 0x43, 0xa9, 0xe0, 0x18, 0x0a, 0x46, 0x52, 0xc1, + 0x09, 0x14, 0xdc, 0xaa, 0xd9, 0x55, 0x98, 0x7b, 0xa7, 0x9f, 0xe8, 0xd7, 0xa5, 0x44, 0x9c, 0xb9, 0xa9, 0x84, 0xa8, + 0x72, 0x62, 0x88, 0xac, 0x10, 0xe6, 0x91, 0xce, 0x79, 0xb4, 0xfe, 0x57, 0x7d, 0xc0, 0xbc, 0x60, 0x39, 0x62, 0x80, + 0xdd, 0x0d, 0xd5, 0x6c, 0x8a, 0xd7, 0x6a, 0x27, 0xf7, 0xe6, 0xb6, 0x8d, 0x86, 0xf0, 0x8e, 0xee, 0x60, 0xac, 0x0e, + 0x51, 0xb9, 0xf5, 0x7c, 0x9a, 0x87, 0x88, 0x5e, 0xb8, 0x45, 0xc8, 0x9b, 0x26, 0x24, 0xca, 0xe1, 0xbc, 0x1a, 0xd3, + 0xc0, 0x5e, 0x06, 0x22, 0x9a, 0x88, 0x53, 0x24, 0x3e, 0xa0, 0xa0, 0xcb, 0x7b, 0xd7, 0x2b, 0x78, 0x38, 0x1e, 0x50, + 0x9d, 0xa0, 0x9f, 0xe5, 0x71, 0xaa, 0x49, 0x97, 0xba, 0x30, 0x52, 0x6f, 0xd2, 0x99, 0x1a, 0x64, 0x48, 0xd5, 0x99, + 0x40, 0xe2, 0x91, 0xb3, 0x51, 0x67, 0x6e, 0x2c, 0xa7, 0x2c, 0xec, 0x8c, 0xb9, 0xab, 0x21, 0xac, 0x3f, 0x79, 0x92, + 0xcc, 0x74, 0xe1, 0x02, 0x85, 0x7b, 0xa2, 0x78, 0x4b, 0x50, 0x9a, 0xf9, 0x56, 0x2a, 0xbc, 0x77, 0x34, 0xd9, 0xc8, + 0xea, 0x4b, 0xf8, 0x5a, 0xbc, 0x66, 0x83, 0xc5, 0x44, 0xb9, 0x88, 0x26, 0xf7, 0xfa, 0x55, 0xc8, 0xaf, 0x00, 0x4a, + 0x95, 0xac, 0x49, 0x4d, 0xb1, 0xbd, 0xf9, 0xb7, 0xe8, 0x31, 0x2b, 0xd7, 0x4f, 0x01, 0x36, 0x25, 0x25, 0xb6, 0x01, + 0xbe, 0x03, 0xb3, 0x2d, 0x79, 0x2e, 0x5c, 0xc0, 0xfc, 0x49, 0xcf, 0x97, 0x9e, 0x04, 0x4f, 0xef, 0x07, 0x96, 0x24, + 0xde, 0x84, 0xc9, 0xa8, 0xa5, 0xd4, 0x39, 0x60, 0xc1, 0x5c, 0x9d, 0x8c, 0x13, 0x08, 0x8c, 0xbd, 0xbf, 0xe1, 0x8f, + 0x02, 0x6e, 0xb2, 0xe0, 0xa7, 0x05, 0x8b, 0x56, 0x38, 0x6f, 0xf8, 0x16, 0x2c, 0x4f, 0xd9, 0x8f, 0x02, 0x90, 0xc8, + 0x2d, 0x0b, 0xaa, 0x85, 0xa9, 0x37, 0xa9, 0x16, 0xd1, 0x5a, 0x67, 0x25, 0xb4, 0xa7, 0x97, 0x1e, 0x05, 0x2e, 0xfc, + 0x0c, 0xbb, 0xfc, 0x20, 0x9a, 0xfc, 0xa6, 0x46, 0xf9, 0x3b, 0x9c, 0x29, 0x7e, 0x08, 0x8d, 0x30, 0xed, 0x5b, 0x38, + 0xc7, 0x8a, 0x05, 0x53, 0xd8, 0x09, 0xd3, 0xa9, 0x89, 0xe1, 0xe3, 0xb4, 0x46, 0xa8, 0x1b, 0x16, 0xae, 0xed, 0xba, + 0x1a, 0x34, 0xb3, 0x13, 0x4f, 0x06, 0x9e, 0xe6, 0x34, 0x4e, 0x0c, 0xf1, 0xc7, 0xb2, 0x5b, 0x7a, 0x86, 0x3d, 0x28, + 0x23, 0xff, 0x76, 0x3d, 0x8e, 0xc2, 0xd4, 0x1c, 0x7b, 0x33, 0x3f, 0xb8, 0xeb, 0xcc, 0xa2, 0x30, 0x4a, 0xe6, 0xde, + 0x90, 0x75, 0x25, 0x7e, 0x14, 0xc3, 0x31, 0xf3, 0x88, 0x80, 0x8e, 0xd5, 0x88, 0xd9, 0x8c, 0x5a, 0xe7, 0xd1, 0x96, + 0xc7, 0x01, 0x5b, 0x65, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, 0x96, 0x99, 0x87, 0x72, 0x86, + 0x04, 0x06, 0x5d, 0x2e, 0x75, 0xec, 0x58, 0x8d, 0x56, 0xcc, 0x66, 0x8a, 0xd5, 0xda, 0xda, 0x79, 0x1c, 0x2d, 0x7b, + 0x00, 0x2d, 0x36, 0x36, 0x13, 0x16, 0x8c, 0xf1, 0x8d, 0x89, 0xd1, 0xa3, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, + 0x6c, 0xd6, 0x85, 0xd7, 0x9d, 0x86, 0x62, 0x4b, 0xfc, 0xf4, 0x89, 0x3d, 0x97, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, + 0x75, 0x47, 0xb1, 0xbb, 0xa0, 0x3f, 0x1e, 0x07, 0xd1, 0xb2, 0x33, 0xf5, 0x47, 0x23, 0x16, 0x76, 0x11, 0xe6, 0xbc, + 0x90, 0x05, 0x81, 0x3f, 0x4f, 0xfc, 0xa4, 0x3b, 0xf3, 0x56, 0xbc, 0xd7, 0xa3, 0x6d, 0xbd, 0x36, 0x79, 0xaf, 0xcd, + 0xbd, 0x7b, 0x95, 0xba, 0x81, 0x48, 0x55, 0xd4, 0x0f, 0x07, 0xad, 0xa5, 0xd8, 0x95, 0x71, 0xee, 0xdd, 0xeb, 0x3c, + 0x66, 0xeb, 0x99, 0x17, 0x4f, 0xfc, 0xb0, 0x63, 0x67, 0xd6, 0xed, 0x9a, 0x36, 0xc6, 0xa3, 0x76, 0xbb, 0x9d, 0x59, + 0x23, 0xf1, 0x64, 0x8f, 0x46, 0x99, 0x35, 0x14, 0x4f, 0xe3, 0xb1, 0x6d, 0x8f, 0xc7, 0x99, 0xe5, 0x8b, 0x82, 0x66, + 0x63, 0x38, 0x6a, 0x36, 0x32, 0x6b, 0x29, 0xd5, 0xc8, 0x2c, 0xc6, 0x9f, 0x62, 0x36, 0xea, 0xe2, 0x46, 0xe2, 0x3e, + 0xcf, 0x27, 0xb6, 0x9d, 0x21, 0x06, 0xb8, 0x2a, 0xe1, 0x26, 0x34, 0x5d, 0xb9, 0x5e, 0xef, 0x5d, 0x53, 0x29, 0x3e, + 0x37, 0x1c, 0xd6, 0xd6, 0x1b, 0x79, 0xf1, 0xc7, 0x6b, 0x45, 0x1a, 0x85, 0xe7, 0x51, 0xb5, 0xb5, 0x98, 0x06, 0x73, + 0xd5, 0x81, 0xb4, 0x1c, 0xdd, 0x41, 0x14, 0xc3, 0x99, 0x8d, 0xbd, 0x91, 0xbf, 0x48, 0x3a, 0x4e, 0x63, 0xbe, 0x12, + 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0x3a, 0x49, 0x14, 0xf8, 0x23, 0x51, 0xb4, 0xed, 0x2c, 0x39, 0x0d, 0xbd, + 0x8b, 0xfc, 0xab, 0x8f, 0xa1, 0x95, 0xbd, 0x20, 0x50, 0xac, 0x66, 0xa2, 0x30, 0x2f, 0x41, 0x73, 0x39, 0xc5, 0x4e, + 0x68, 0x5e, 0x30, 0x00, 0xad, 0x73, 0x34, 0x5f, 0xe5, 0x7b, 0xde, 0x39, 0x9e, 0xaf, 0xb2, 0xaf, 0x67, 0x6c, 0xe4, + 0x7b, 0x8a, 0x56, 0xec, 0x26, 0xc7, 0x06, 0x93, 0x3a, 0x7d, 0xbd, 0x65, 0x9b, 0x8a, 0x63, 0x01, 0xe9, 0x8b, 0x0e, + 0xfc, 0x19, 0xc8, 0x61, 0xbc, 0x30, 0xcd, 0xb2, 0xfe, 0x75, 0x96, 0x75, 0x2f, 0x7c, 0xed, 0xea, 0xaf, 0x1a, 0xd1, + 0x42, 0x32, 0x41, 0xcd, 0xf4, 0x6b, 0xe3, 0x9c, 0xc9, 0xee, 0x32, 0x40, 0xc6, 0xd0, 0x55, 0x46, 0xae, 0x4c, 0xf4, + 0x76, 0xb3, 0x32, 0x4d, 0x72, 0x5e, 0x9d, 0xbc, 0x6f, 0xca, 0x55, 0x90, 0x02, 0x41, 0x85, 0x73, 0xe6, 0x5e, 0x48, + 0xbe, 0x37, 0xc0, 0xf4, 0x60, 0x65, 0x8a, 0x1d, 0xf4, 0x7a, 0x1b, 0xef, 0x79, 0x79, 0x3f, 0xef, 0xf9, 0xb7, 0x74, + 0x1f, 0xde, 0xf3, 0xf2, 0x8b, 0xf3, 0x9e, 0xaf, 0x37, 0x63, 0x07, 0x5d, 0x46, 0xae, 0x9a, 0x1b, 0x4c, 0x02, 0x69, + 0x8a, 0x29, 0x2a, 0xff, 0xeb, 0xf4, 0xd7, 0x06, 0x71, 0x11, 0xbd, 0x21, 0x51, 0xe0, 0x7c, 0x2a, 0x88, 0x59, 0xdf, + 0x86, 0xee, 0x9f, 0x62, 0xf9, 0x79, 0x3c, 0x76, 0x5f, 0x47, 0x52, 0x41, 0xfe, 0xc4, 0x7d, 0x49, 0x4a, 0x11, 0x94, + 0xe9, 0x4d, 0xee, 0xed, 0x03, 0x39, 0xa6, 0x21, 0x00, 0x2b, 0xb9, 0x76, 0x8f, 0x72, 0x9f, 0xbb, 0x6e, 0x19, 0x04, + 0x2d, 0x77, 0x72, 0x15, 0x61, 0xb6, 0x36, 0x2c, 0xa3, 0x26, 0x4c, 0xc8, 0x00, 0x5e, 0xde, 0x7d, 0x3f, 0xd2, 0x2e, + 0x23, 0x3d, 0xf3, 0x93, 0xb7, 0xd5, 0x20, 0x57, 0x42, 0xcf, 0x25, 0x0f, 0x27, 0xe3, 0x7e, 0x73, 0x52, 0x2c, 0x5b, + 0x7c, 0x4d, 0xcd, 0xcf, 0x4a, 0x23, 0xed, 0xc8, 0x0d, 0xbb, 0x14, 0xd9, 0x7b, 0x83, 0x18, 0xf3, 0x60, 0x30, 0x6b, + 0xce, 0xe5, 0xad, 0xf1, 0x19, 0x62, 0x83, 0x8e, 0xa8, 0xb9, 0x3f, 0xca, 0x32, 0xbd, 0x2b, 0x26, 0x42, 0x22, 0xb4, + 0xec, 0x3e, 0x26, 0x2e, 0x29, 0x84, 0x40, 0x5c, 0xe2, 0x43, 0xd6, 0xcc, 0x97, 0xe0, 0x1f, 0xc0, 0x6d, 0x9f, 0xf9, + 0x9c, 0xa9, 0x0a, 0x4d, 0x1f, 0xf9, 0x8d, 0x48, 0x03, 0x02, 0x83, 0x76, 0xd9, 0xdb, 0xaa, 0xb4, 0x20, 0x9b, 0x8e, + 0xad, 0x34, 0x39, 0xe8, 0xe0, 0x00, 0x91, 0x7c, 0x85, 0x58, 0x88, 0xd0, 0x0e, 0xaf, 0x83, 0x0f, 0x99, 0x9a, 0xf3, + 0x7e, 0xb8, 0xfd, 0x7a, 0xa7, 0x87, 0xd0, 0xa0, 0x57, 0x51, 0xba, 0xdd, 0xe3, 0x97, 0x09, 0xac, 0x44, 0xb2, 0x34, + 0xac, 0x64, 0xa9, 0x3c, 0x5b, 0x8b, 0x28, 0xd8, 0xa9, 0x37, 0x37, 0x41, 0xcb, 0x83, 0xb8, 0x97, 0x63, 0x3c, 0x29, + 0xe0, 0x76, 0x77, 0x91, 0x00, 0x6e, 0x44, 0x39, 0x0a, 0xe2, 0x9f, 0xee, 0x70, 0x11, 0x27, 0x51, 0xdc, 0x99, 0x47, + 0x7e, 0x98, 0xb2, 0x38, 0x23, 0xc1, 0x0a, 0xce, 0x8f, 0x98, 0x9e, 0xeb, 0x75, 0x34, 0xf7, 0x86, 0x7e, 0x7a, 0xd7, + 0xb1, 0x39, 0x4b, 0x61, 0x77, 0x39, 0x77, 0x60, 0xd7, 0xd6, 0xef, 0xf0, 0xd9, 0x7c, 0x8e, 0x8c, 0x5f, 0xbc, 0xc9, + 0xce, 0xc8, 0xdb, 0xbc, 0x2b, 0xbd, 0xa5, 0x38, 0xe0, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x01, 0x2c, 0x0f, 0x4b, 0x6d, + 0x8f, 0xd8, 0xc4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0xd5, 0xd2, 0x15, 0xbb, 0xbe, 0x18, 0x38, 0x1e, 0x7d, + 0x1f, 0xc8, 0x3a, 0xde, 0x38, 0x65, 0xb1, 0xb1, 0x4f, 0xcd, 0x01, 0x1b, 0x47, 0x31, 0xa3, 0x9c, 0x71, 0x4e, 0x7b, + 0xbe, 0xda, 0xbf, 0xfb, 0xdd, 0xc3, 0xaf, 0xef, 0x27, 0x8c, 0x52, 0x4d, 0x74, 0xa6, 0xdf, 0xd3, 0xdb, 0x26, 0x3d, + 0x03, 0xd6, 0x90, 0x66, 0x7e, 0x48, 0x52, 0x10, 0x88, 0xf7, 0x55, 0x9b, 0x9a, 0x63, 0x1e, 0x71, 0x9a, 0x17, 0xb3, + 0xc0, 0x4b, 0xfd, 0x5b, 0xc1, 0x33, 0x36, 0x8f, 0xe7, 0x2b, 0xb1, 0xc6, 0x48, 0xf0, 0x1e, 0xb0, 0x48, 0x15, 0x50, + 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xba, 0x1b, 0xa3, 0x11, 0xd1, 0xaa, 0x2b, 0x94, 0xbe, 0x35, 0x5f, 0xc9, 0x24, + 0xba, 0x68, 0x96, 0x53, 0xea, 0x6a, 0x9a, 0x91, 0x99, 0x3f, 0x1a, 0x05, 0x2c, 0x2b, 0x2d, 0x74, 0x79, 0x2d, 0xa5, + 0xc9, 0xc9, 0xe7, 0xc1, 0x1b, 0x24, 0x51, 0xb0, 0x48, 0x59, 0xfd, 0x74, 0x09, 0x89, 0x6e, 0x31, 0x39, 0xf8, 0xbb, + 0x0c, 0x6b, 0x0b, 0xd8, 0x6d, 0xd8, 0x26, 0x76, 0x17, 0xb2, 0x0a, 0x9a, 0xcd, 0x32, 0xe8, 0xf0, 0x2a, 0x07, 0xda, + 0xa8, 0x19, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0xcf, 0xac, 0x96, 0x17, 0x65, 0xe5, 0xc1, + 0xfc, 0x36, 0x67, 0xec, 0x45, 0xfd, 0x19, 0x7b, 0x21, 0xce, 0xd8, 0xee, 0x9d, 0xf9, 0x68, 0xec, 0xc0, 0x7f, 0xdd, + 0x62, 0x40, 0x1d, 0x5b, 0x69, 0xce, 0x57, 0x8a, 0x33, 0x5f, 0x29, 0x66, 0x63, 0xbe, 0x52, 0xb0, 0x6b, 0x74, 0x6f, + 0x31, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf4, 0xca, 0x39, 0x82, 0x77, 0xd0, 0xaa, 0xb5, 0xf9, + 0xae, 0xb1, 0xfb, 0xa8, 0xd3, 0x59, 0x12, 0x48, 0x5b, 0xb7, 0x52, 0x6f, 0x30, 0x00, 0x51, 0x66, 0x34, 0x5c, 0x24, + 0xff, 0xe4, 0xf0, 0xf3, 0x49, 0xdc, 0x89, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0x28, 0xbc, 0x65, 0xa2, 0x87, 0x75, + 0xbe, 0x4e, 0x1d, 0x4a, 0x81, 0xd8, 0xb0, 0x8e, 0x6a, 0x36, 0x79, 0xfd, 0x44, 0xff, 0x66, 0xab, 0xb4, 0x1d, 0xc5, + 0x7c, 0xc6, 0xb4, 0xec, 0x9c, 0x8e, 0x87, 0xcf, 0x06, 0x5f, 0x4d, 0xbb, 0x5d, 0x0f, 0xee, 0x95, 0xf8, 0xd2, 0xb5, + 0x20, 0x2a, 0x9c, 0x6e, 0xf1, 0x50, 0x1c, 0xbb, 0x7b, 0xdd, 0xb6, 0x47, 0x36, 0x7a, 0xdd, 0x41, 0x10, 0x8a, 0xba, + 0x7b, 0x62, 0xf9, 0x47, 0x2f, 0x8e, 0xe0, 0x3f, 0xe2, 0xea, 0xff, 0x96, 0xd6, 0x31, 0xea, 0xaf, 0xd3, 0x12, 0xa3, + 0x4e, 0xac, 0x12, 0x32, 0xe2, 0xfb, 0xd7, 0x1f, 0x8f, 0x1f, 0xd6, 0x60, 0xef, 0xda, 0xe4, 0x19, 0x56, 0xad, 0xfd, + 0x32, 0x8a, 0x02, 0xe6, 0x85, 0x9b, 0xd5, 0xc5, 0xf4, 0x90, 0x9b, 0x7f, 0xea, 0x42, 0x23, 0x71, 0x8f, 0x20, 0xa7, + 0x04, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x62, 0xdb, 0x55, 0xe2, 0xdd, 0xfd, 0x57, 0x89, 0x3f, 0xee, 0x75, 0x95, 0x78, + 0xf7, 0xc5, 0xaf, 0x12, 0x17, 0x9b, 0x57, 0x89, 0x8b, 0x48, 0xb8, 0x03, 0x1b, 0x6f, 0x16, 0xfc, 0xe7, 0x07, 0xb2, + 0xf7, 0x7d, 0x17, 0xb9, 0x2d, 0x9b, 0xd2, 0x1a, 0x5e, 0xfe, 0xea, 0x8b, 0x05, 0x6e, 0xc4, 0x77, 0xe8, 0x1d, 0x57, + 0x5c, 0x2d, 0x38, 0x66, 0xc7, 0xef, 0x48, 0xc5, 0x41, 0x14, 0x4e, 0x7e, 0x02, 0x7b, 0x6f, 0x10, 0x07, 0xc6, 0xd2, + 0x0b, 0x3f, 0xf9, 0x29, 0x9a, 0x2f, 0xe6, 0xa8, 0xa8, 0xfa, 0xe0, 0x27, 0xfe, 0x20, 0x60, 0x79, 0x1c, 0x49, 0xd2, + 0xba, 0x72, 0xd9, 0x3a, 0x28, 0x5e, 0xc5, 0x4f, 0x6f, 0x25, 0x7e, 0xa2, 0x8b, 0x2d, 0xff, 0x4d, 0x6e, 0x82, 0x6a, + 0xfd, 0x45, 0x44, 0x58, 0x88, 0x49, 0x40, 0x3f, 0xfc, 0x32, 0x72, 0x11, 0xe9, 0x35, 0xa3, 0x14, 0xee, 0x1b, 0x5b, + 0xfb, 0x61, 0xd5, 0x7e, 0xde, 0x2c, 0x74, 0x23, 0x4f, 0xb3, 0xb1, 0x29, 0xce, 0x9f, 0x45, 0x8b, 0x84, 0x8d, 0xa2, + 0x65, 0xa8, 0x1a, 0x21, 0xd7, 0xab, 0x46, 0x28, 0x53, 0xcf, 0xdb, 0x94, 0x15, 0x8e, 0xaa, 0x35, 0x87, 0x39, 0x34, + 0x49, 0x83, 0x6d, 0xe2, 0x10, 0x55, 0x11, 0xb2, 0xa9, 0x7b, 0xa0, 0x69, 0x91, 0xfb, 0xb0, 0x96, 0xc2, 0xf3, 0x24, + 0xb2, 0xb8, 0x54, 0x38, 0xd1, 0x42, 0x21, 0x5c, 0x14, 0xb1, 0xae, 0x6b, 0x16, 0x8e, 0xbf, 0xa1, 0x20, 0x91, 0xc5, + 0x5b, 0xd0, 0x55, 0x65, 0x0b, 0xbe, 0x1e, 0x3c, 0xf2, 0x33, 0x3d, 0xbe, 0x92, 0xa6, 0xf1, 0xed, 0x2d, 0x8b, 0x03, + 0xef, 0x4e, 0xd3, 0xb3, 0x28, 0xfc, 0x01, 0x26, 0xe0, 0x75, 0xb4, 0x0c, 0xe5, 0x0a, 0x98, 0x90, 0xbd, 0x66, 0x2f, + 0xd5, 0xc6, 0x28, 0x87, 0x98, 0x1d, 0x12, 0x04, 0xbe, 0x35, 0xf7, 0x26, 0xec, 0x2f, 0x06, 0xfd, 0xfb, 0x57, 0x3d, + 0x33, 0xde, 0x45, 0xf9, 0x87, 0x7e, 0x9e, 0xef, 0xf1, 0x99, 0x27, 0x4f, 0x0e, 0xb6, 0x0f, 0x5b, 0x1b, 0x06, 0xcc, + 0x8b, 0x05, 0x14, 0x35, 0xad, 0xf5, 0xad, 0xa7, 0x00, 0xa0, 0xb8, 0x8c, 0x16, 0xc3, 0x29, 0xfa, 0xed, 0x7e, 0xb9, + 0xf1, 0xa6, 0xd0, 0x27, 0x4b, 0xae, 0xec, 0xeb, 0x7c, 0xe8, 0x95, 0xa2, 0x62, 0x16, 0xf0, 0xfb, 0xe7, 0x90, 0x64, + 0xeb, 0x3f, 0x38, 0x0d, 0x9b, 0xbb, 0x26, 0x0f, 0xf9, 0xf5, 0xa0, 0xcd, 0xdb, 0xf5, 0x21, 0x2a, 0x0f, 0x85, 0xaf, + 0x16, 0x4a, 0xba, 0x7a, 0x24, 0x93, 0x55, 0x27, 0x4d, 0x4e, 0x15, 0xb3, 0x2d, 0x0b, 0x8e, 0xf8, 0x0a, 0xb3, 0x4a, + 0x56, 0x23, 0x06, 0xe3, 0xd8, 0xaa, 0x82, 0x64, 0xb8, 0x37, 0x05, 0x43, 0xf4, 0x55, 0x7d, 0x37, 0xf3, 0x43, 0x03, + 0x33, 0xbd, 0x6e, 0xbe, 0xf1, 0x56, 0x90, 0xeb, 0x10, 0x90, 0x5b, 0xf5, 0x15, 0x14, 0x1a, 0x72, 0xb4, 0x20, 0x6f, + 0x34, 0xd2, 0xd4, 0xda, 0x99, 0x10, 0xda, 0xc0, 0xfe, 0x57, 0x8a, 0xa2, 0x28, 0xf9, 0x35, 0x42, 0xc9, 0xef, 0x11, + 0x58, 0x8e, 0xd7, 0x01, 0xd0, 0x96, 0x64, 0xf3, 0x15, 0x95, 0xc0, 0xcd, 0x00, 0xed, 0xa7, 0x45, 0x01, 0x4f, 0xe7, + 0x03, 0xc6, 0x2d, 0x54, 0x20, 0x2e, 0xf4, 0xa0, 0xfa, 0xf6, 0x62, 0xc8, 0xfa, 0xd7, 0x51, 0xf0, 0xc2, 0x8e, 0x6f, + 0xb9, 0x24, 0x58, 0xb1, 0xe9, 0xb1, 0xdf, 0x65, 0xf5, 0x79, 0x5f, 0x42, 0x09, 0x0b, 0x82, 0xd6, 0xa1, 0x92, 0xc6, + 0xd1, 0x60, 0x35, 0xb8, 0x11, 0xef, 0x45, 0xab, 0x74, 0xc6, 0xc2, 0x85, 0x6a, 0x80, 0xd5, 0x09, 0xe6, 0xe1, 0x81, + 0x3a, 0xaf, 0x89, 0xd9, 0x02, 0x6c, 0x53, 0xdf, 0x72, 0x4a, 0xb4, 0x50, 0x98, 0xaa, 0x78, 0xc6, 0x90, 0x07, 0xc0, + 0x49, 0x38, 0x6e, 0xab, 0x52, 0x08, 0xbe, 0xa4, 0x51, 0x19, 0x9b, 0xf3, 0x90, 0x57, 0xc8, 0x29, 0x90, 0x8d, 0x18, + 0x17, 0x17, 0x89, 0x69, 0xd7, 0xbc, 0xea, 0xa2, 0xe5, 0x1a, 0x19, 0xaf, 0x22, 0x28, 0x8a, 0xf5, 0xcd, 0x6e, 0x38, + 0x9c, 0x90, 0x7c, 0x60, 0x6b, 0x3f, 0xc3, 0x8d, 0x7e, 0xb6, 0x0c, 0xfa, 0x23, 0xbb, 0x23, 0x42, 0x42, 0x53, 0xf5, + 0x91, 0xdd, 0x81, 0x71, 0xf8, 0x39, 0x48, 0x53, 0xd4, 0x1d, 0xe8, 0xda, 0x80, 0x74, 0xbe, 0x43, 0x48, 0x48, 0xb1, + 0xe3, 0x00, 0xd9, 0xd9, 0x0e, 0x2c, 0x8e, 0x53, 0x1c, 0x1a, 0x49, 0x57, 0x1c, 0x62, 0x1e, 0xb1, 0x40, 0xab, 0x9d, + 0x63, 0xb3, 0xe6, 0x68, 0xe8, 0xcf, 0x1c, 0xdb, 0x3e, 0xdc, 0xa8, 0x0f, 0x82, 0xec, 0xba, 0xda, 0xba, 0x91, 0xba, + 0x8e, 0x6d, 0xfa, 0xcf, 0xac, 0x46, 0x77, 0x83, 0x46, 0x4b, 0xf9, 0xa2, 0xfa, 0x28, 0xfe, 0xea, 0x3d, 0x5e, 0x6b, + 0x1b, 0x07, 0x52, 0xaf, 0x46, 0x00, 0x40, 0xd8, 0x32, 0x2e, 0xff, 0xea, 0x6f, 0x92, 0x7e, 0xca, 0x56, 0x45, 0xb9, + 0xcb, 0xfb, 0x90, 0xf1, 0x50, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x7e, 0x57, 0x60, + 0x14, 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0x6e, 0x35, 0x56, 0x68, 0xf4, 0x76, 0x72, + 0x0b, 0xd8, 0xff, 0x16, 0xf2, 0x69, 0x0d, 0x20, 0xc6, 0x23, 0xd4, 0x80, 0xfc, 0xa8, 0xf7, 0x76, 0x08, 0x21, 0x79, + 0xe5, 0xee, 0xca, 0x44, 0x72, 0xff, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x9e, 0xdc, 0x3d, 0xb0, 0x4b, + 0x16, 0x8e, 0xca, 0x1d, 0x56, 0xe8, 0xd7, 0xfe, 0xdd, 0x95, 0x30, 0x0a, 0x24, 0x0e, 0x8e, 0x6a, 0x30, 0x4a, 0x16, + 0x85, 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x7b, 0x71, 0x31, 0xd8, 0x80, 0xb2, 0x7e, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0x64, + 0xa7, 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0xb7, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x6f, 0x6a, + 0x5f, 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, + 0x98, 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x6a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, + 0xb7, 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x51, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, + 0xbf, 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, + 0x24, 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, + 0x6f, 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, + 0xe7, 0x36, 0x10, 0x08, 0x64, 0x4d, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x13, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, + 0x49, 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x25, 0x09, 0x42, 0xc7, 0x56, 0xec, 0x6e, 0x0d, 0x03, 0x80, 0xf4, + 0xbf, 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xdd, + 0xfc, 0x26, 0xc9, 0x7b, 0xd6, 0x3c, 0x26, 0x48, 0x59, 0x9c, 0xcf, 0x6b, 0x74, 0x04, 0x1c, 0x7c, 0x97, 0xc5, 0x8b, + 0x10, 0x53, 0xdd, 0x9a, 0x69, 0xec, 0x0d, 0x3f, 0xae, 0xa5, 0xef, 0x71, 0x91, 0x28, 0x88, 0x8b, 0xcb, 0x4a, 0x85, + 0xae, 0x87, 0x99, 0xa1, 0x58, 0xc7, 0x6a, 0x24, 0x92, 0xa0, 0xa6, 0xf3, 0xc8, 0x6e, 0x7a, 0x2f, 0xc6, 0x47, 0x15, + 0xf9, 0x69, 0xa3, 0x55, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa2, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, + 0x66, 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x8d, 0x92, 0x6d, 0x60, 0x8d, 0xfd, + 0x20, 0x30, 0x03, 0x70, 0x63, 0x58, 0x7f, 0xd6, 0xf0, 0xb0, 0x9f, 0x05, 0xe4, 0x24, 0xfc, 0x8c, 0x7e, 0xca, 0x3b, + 0x25, 0x9d, 0x2e, 0x66, 0x83, 0xb5, 0x2c, 0x28, 0x97, 0xe4, 0xe7, 0x9b, 0x32, 0x73, 0xf9, 0xb3, 0xe3, 0xf1, 0xb8, + 0x2c, 0x35, 0xb6, 0x95, 0x23, 0x94, 0xfc, 0x3e, 0xb2, 0x6d, 0xbb, 0x3a, 0xbf, 0xdb, 0x0e, 0x0a, 0x1d, 0x0c, 0x13, + 0x85, 0xf0, 0xed, 0xfb, 0xf7, 0xd4, 0xef, 0x04, 0x2d, 0x75, 0xb5, 0xed, 0x3c, 0xd2, 0x56, 0xfb, 0xaf, 0x00, 0x05, + 0x51, 0xc3, 0x7d, 0xc7, 0x7f, 0x73, 0xaf, 0xec, 0xe8, 0xa9, 0x7a, 0x80, 0x1f, 0xd6, 0xf8, 0x9e, 0xbd, 0xbe, 0x47, + 0xd3, 0x6d, 0xdb, 0x3b, 0xb3, 0x0a, 0xb2, 0x5b, 0xb2, 0x59, 0xea, 0x92, 0xa5, 0x92, 0x9f, 0xb2, 0x59, 0xd2, 0x19, + 0x32, 0x54, 0x90, 0x5a, 0x12, 0xb5, 0x45, 0xab, 0x1e, 0x73, 0x02, 0x76, 0x5c, 0x8e, 0xc0, 0xc3, 0xb6, 0x82, 0xca, + 0xaa, 0x0d, 0xcd, 0x9a, 0xf8, 0x08, 0x52, 0xb1, 0xf5, 0xa6, 0xc2, 0x09, 0xb7, 0x69, 0xcb, 0xfe, 0x43, 0xa9, 0x9e, + 0x02, 0xdc, 0xe9, 0x5a, 0x58, 0x9b, 0x90, 0xf2, 0x04, 0xff, 0xce, 0x95, 0x73, 0x2f, 0xe6, 0xab, 0xb2, 0x71, 0x57, + 0x1b, 0xd4, 0x4d, 0x05, 0x29, 0x23, 0xa8, 0xeb, 0x50, 0x5f, 0x6e, 0x02, 0x34, 0x96, 0xad, 0x5b, 0xc0, 0x82, 0x46, + 0x4c, 0x41, 0x45, 0x47, 0x98, 0x83, 0x8a, 0xd7, 0x59, 0xd8, 0x79, 0x85, 0x7c, 0x1f, 0x7f, 0x41, 0x2e, 0x72, 0x48, + 0x70, 0xf2, 0x07, 0xe3, 0x79, 0x1b, 0x95, 0x7b, 0xa5, 0xad, 0x8a, 0xa6, 0x32, 0xb8, 0x07, 0xc4, 0x8d, 0x54, 0x59, + 0xc4, 0x81, 0x49, 0xe9, 0xe9, 0x35, 0x7d, 0xbd, 0x39, 0xee, 0xed, 0xdd, 0x3b, 0x2d, 0xd0, 0x6b, 0x6c, 0x4e, 0xd5, + 0x5e, 0xaa, 0xbd, 0xaa, 0x0e, 0x5b, 0xc0, 0x09, 0x2b, 0x00, 0x3e, 0xb3, 0x0a, 0x1a, 0x0d, 0x29, 0x15, 0xdc, 0x47, + 0x83, 0xce, 0xdf, 0xca, 0xc8, 0x5a, 0x8c, 0x13, 0xbb, 0xab, 0xaf, 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xcc, 0x1d, 0xc7, + 0x4e, 0xf8, 0x6c, 0xc2, 0x8e, 0x91, 0xd1, 0x95, 0x83, 0x3b, 0x08, 0x4f, 0xa9, 0x49, 0x69, 0x4f, 0xe8, 0x94, 0xa2, + 0x2e, 0xe1, 0x8f, 0xb5, 0xc2, 0xfb, 0xcb, 0x92, 0x34, 0x9e, 0x07, 0x9d, 0x68, 0xe8, 0x7b, 0xd5, 0x9e, 0xf9, 0xe1, + 0xfe, 0x75, 0xbd, 0xd5, 0xde, 0x75, 0x81, 0x39, 0xdc, 0xbb, 0x32, 0x70, 0x97, 0x58, 0xf9, 0x32, 0x75, 0xff, 0x28, + 0x29, 0x0f, 0xe4, 0x80, 0x89, 0x2a, 0xb6, 0xa2, 0x1b, 0xfd, 0x8f, 0x0b, 0xb7, 0x7f, 0x7a, 0xb6, 0x9a, 0x05, 0xca, + 0x2d, 0x8b, 0x13, 0x48, 0x28, 0xa1, 0x3a, 0x96, 0xad, 0x2a, 0x68, 0xd0, 0xef, 0x87, 0x13, 0x57, 0xfd, 0xf9, 0xf2, + 0x8d, 0xd9, 0x56, 0xcf, 0xc0, 0x1c, 0xe3, 0x76, 0x82, 0x2c, 0xee, 0x85, 0x77, 0xc7, 0xe2, 0x9b, 0x06, 0xf7, 0xf8, + 0x21, 0xe6, 0x16, 0xcb, 0x94, 0x86, 0xba, 0x47, 0xe2, 0x77, 0xe5, 0xd6, 0x67, 0xcb, 0x97, 0xd1, 0xca, 0x55, 0x01, + 0xb1, 0x3a, 0x8d, 0xb6, 0xe2, 0x34, 0x8e, 0xac, 0xe3, 0xb6, 0xda, 0xfb, 0x4a, 0x51, 0x4e, 0x47, 0x6c, 0x9c, 0xf4, + 0x50, 0x1c, 0x73, 0x8a, 0xfc, 0x20, 0xfd, 0x56, 0x14, 0x6b, 0x18, 0x24, 0xa6, 0xa3, 0xac, 0xf9, 0xa3, 0xa2, 0x00, + 0x32, 0xea, 0x28, 0x8f, 0xc6, 0x8d, 0xf1, 0xd1, 0xf8, 0x45, 0x97, 0x17, 0x67, 0x5f, 0x95, 0xaa, 0x1b, 0xf4, 0x6f, + 0x43, 0x6a, 0x96, 0xa4, 0x71, 0xf4, 0x91, 0x71, 0x5e, 0x52, 0xc9, 0x05, 0x45, 0xd5, 0xa6, 0x8d, 0xcd, 0x2f, 0x39, + 0xed, 0xc1, 0x70, 0xdc, 0x28, 0xaa, 0x23, 0x8c, 0x87, 0x39, 0x90, 0xa7, 0x87, 0x02, 0xf4, 0x53, 0x79, 0x9a, 0x1c, + 0xb3, 0x6e, 0xa2, 0x1c, 0x95, 0x8f, 0x71, 0x22, 0xc6, 0x77, 0x0a, 0x79, 0xd5, 0x0a, 0xef, 0xc5, 0x04, 0x9b, 0xb9, + 0xea, 0x0f, 0x4e, 0xa3, 0x6d, 0x38, 0xce, 0xb1, 0x75, 0xdc, 0x1e, 0xda, 0xc6, 0x91, 0x75, 0x64, 0x36, 0xad, 0x63, + 0xa3, 0x6d, 0xb6, 0x8d, 0xf6, 0x77, 0xed, 0xa1, 0x79, 0x64, 0x1d, 0x19, 0xb6, 0xd9, 0x86, 0x42, 0xb3, 0x6d, 0xb6, + 0x6f, 0xcd, 0xa3, 0xf6, 0xd0, 0xc6, 0xd2, 0x86, 0xd5, 0x6a, 0x99, 0x8e, 0x6d, 0xb5, 0x5a, 0x46, 0xcb, 0x3a, 0x3e, + 0x36, 0x9d, 0xa6, 0x75, 0x7c, 0x7c, 0xd1, 0x6a, 0x5b, 0x4d, 0x78, 0xd7, 0x6c, 0x0e, 0x9b, 0x96, 0xe3, 0x98, 0xf0, + 0x97, 0xd1, 0xb6, 0x1a, 0xf4, 0xc3, 0x71, 0xac, 0xa6, 0x63, 0xd8, 0x41, 0xab, 0x61, 0x1d, 0xbf, 0x30, 0xf0, 0x6f, + 0xac, 0x66, 0xe0, 0x5f, 0xd0, 0x8d, 0xf1, 0xc2, 0x6a, 0x1c, 0xd3, 0x2f, 0xec, 0xf0, 0xf6, 0xa8, 0xfd, 0x37, 0xf5, + 0x70, 0xeb, 0x18, 0x1c, 0x1a, 0x43, 0xbb, 0x65, 0x35, 0x9b, 0xc6, 0x91, 0x63, 0xb5, 0x9b, 0x53, 0xf3, 0xa8, 0x61, + 0x1d, 0x9f, 0x0c, 0x4d, 0xc7, 0x3a, 0x39, 0x31, 0x6c, 0xb3, 0x69, 0x35, 0x0c, 0xc7, 0x3a, 0x6a, 0xe2, 0x8f, 0xa6, + 0xd5, 0xb8, 0x3d, 0x79, 0x61, 0x1d, 0xb7, 0xa6, 0xc7, 0xd6, 0xd1, 0x87, 0xa3, 0xb6, 0xd5, 0x68, 0x4e, 0x9b, 0xc7, + 0x56, 0xe3, 0xe4, 0xf6, 0xd8, 0x3a, 0x9a, 0x9a, 0x8d, 0xe3, 0x9d, 0x2d, 0x9d, 0x86, 0x05, 0x73, 0x84, 0xaf, 0xe1, + 0x85, 0xc1, 0x5f, 0xc0, 0x9f, 0x29, 0xb6, 0xfd, 0x1d, 0xbb, 0x49, 0x36, 0x9b, 0xbe, 0xb0, 0xda, 0x27, 0x43, 0xaa, + 0x0e, 0x05, 0xa6, 0xa8, 0x01, 0x4d, 0x6e, 0x4d, 0xfa, 0x2c, 0x76, 0x67, 0x8a, 0x8e, 0xc4, 0x1f, 0xfe, 0xb1, 0x5b, + 0x13, 0x3e, 0x4c, 0xdf, 0xfd, 0x8f, 0xf6, 0x93, 0x2f, 0xf9, 0xe9, 0xe1, 0x84, 0xb6, 0xfe, 0xa4, 0xf7, 0xd5, 0x29, + 0x1c, 0xee, 0x5e, 0xdf, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x1f, 0xf7, 0x2b, 0x25, 0x5f, 0x2e, 0xf6, 0x51, 0x4a, 0xfe, + 0xe3, 0x8b, 0x2b, 0x25, 0x7f, 0xa9, 0xfa, 0xd6, 0xbc, 0xa9, 0xe6, 0x9a, 0xfe, 0xe3, 0xba, 0x2a, 0x72, 0x48, 0x3c, + 0xed, 0xea, 0xc7, 0xc5, 0x35, 0xc4, 0x8f, 0x7f, 0x13, 0xb9, 0x2f, 0x17, 0x25, 0x83, 0xcf, 0x08, 0x70, 0xec, 0x9b, + 0x88, 0x70, 0xec, 0x87, 0x85, 0x0b, 0x56, 0x66, 0x9c, 0xcd, 0xf1, 0x47, 0xe6, 0xd4, 0x0b, 0xc6, 0x39, 0x8b, 0x04, + 0x25, 0x5d, 0x2c, 0x06, 0xbf, 0x79, 0x20, 0xcf, 0x70, 0x93, 0x59, 0xcc, 0xc2, 0x04, 0x2c, 0x82, 0xc1, 0x92, 0x63, + 0x1c, 0x67, 0x95, 0xc6, 0x96, 0x88, 0xb8, 0x7f, 0xc3, 0x3d, 0x8a, 0xb7, 0xbe, 0x47, 0x03, 0xe0, 0xfa, 0xde, 0x9d, + 0xcd, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, 0xbd, 0x2f, 0x9b, 0xe1, 0x56, 0x0c, 0xaf, 0xb7, + 0x43, 0x0a, 0x90, 0x54, 0xdb, 0x3b, 0x65, 0x33, 0xde, 0xfb, 0x86, 0x59, 0xf3, 0xf9, 0x52, 0xf3, 0x1d, 0x36, 0xc4, + 0x79, 0xc7, 0xd5, 0xa9, 0x5a, 0x97, 0xf8, 0xb4, 0xfa, 0x09, 0x29, 0x2e, 0xa8, 0x85, 0xa1, 0x71, 0xc1, 0xa9, 0xda, + 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd4, 0xa7, 0x6c, 0x9c, 0xfc, 0x6c, 0x8d, 0xf7, 0x0a, 0xff, 0x17, 0xe0, 0x44, + 0x39, 0xc7, 0x33, 0x88, 0xe4, 0x79, 0x5e, 0x4b, 0xfd, 0x92, 0x34, 0x22, 0x9b, 0x3a, 0xeb, 0x4d, 0x5e, 0x74, 0xab, + 0x5b, 0x82, 0xc3, 0x66, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x13, 0x40, 0x46, 0x8e, 0x1a, 0xe8, 0xe7, 0xb0, 0xab, 0x33, + 0x51, 0xef, 0x11, 0x6c, 0x62, 0xee, 0x09, 0xa8, 0xc8, 0x21, 0x4d, 0xd7, 0xe3, 0x20, 0xf2, 0xd2, 0x0e, 0xb2, 0x69, + 0x12, 0xcb, 0xdb, 0x40, 0x8f, 0x85, 0xee, 0x0e, 0x63, 0x3a, 0xb9, 0x63, 0xde, 0x09, 0x7a, 0x3e, 0xec, 0xb2, 0xbf, + 0xcb, 0x1d, 0xce, 0xd6, 0x25, 0x73, 0x14, 0xa7, 0x75, 0x62, 0x38, 0xc7, 0x86, 0x75, 0xd2, 0xd2, 0x33, 0x71, 0xe0, + 0xe4, 0x2e, 0x4b, 0x13, 0x02, 0x0e, 0x10, 0x39, 0x98, 0x7e, 0xe8, 0xa7, 0xbe, 0x17, 0x64, 0xc0, 0x0f, 0x97, 0x2f, + 0x29, 0xff, 0x58, 0x24, 0x29, 0x8c, 0x51, 0x30, 0xbd, 0xe8, 0xfc, 0x61, 0x0e, 0x58, 0xba, 0x64, 0x2c, 0xdc, 0x62, + 0x18, 0x53, 0xf5, 0x25, 0xf9, 0xed, 0x2c, 0xeb, 0x33, 0xb2, 0x5a, 0x1b, 0xa4, 0x21, 0xdf, 0x1f, 0xc2, 0xf1, 0x21, + 0xeb, 0x1b, 0xdf, 0x6d, 0x43, 0xb8, 0x3f, 0xdf, 0x8f, 0x70, 0x53, 0xb6, 0x0f, 0xc2, 0xfd, 0xf9, 0x8b, 0x23, 0xdc, + 0xef, 0x64, 0x84, 0x5b, 0xf2, 0x1f, 0x2c, 0x34, 0x4c, 0xef, 0xf1, 0x59, 0x03, 0x17, 0xd9, 0xe7, 0xea, 0x21, 0x31, + 0xf0, 0xaa, 0x5e, 0xe4, 0xa8, 0xfd, 0xf3, 0x42, 0xb6, 0xa0, 0x46, 0x01, 0x28, 0xa6, 0x76, 0xf4, 0xd1, 0x75, 0xd9, + 0x07, 0x57, 0x37, 0x11, 0x86, 0x01, 0xfa, 0xfc, 0x3e, 0x4c, 0x03, 0xeb, 0x1d, 0xbf, 0x47, 0x82, 0x42, 0xf7, 0x4d, + 0x14, 0xcf, 0x3c, 0x4c, 0x31, 0xa2, 0xea, 0xe0, 0x4e, 0x07, 0x0f, 0x36, 0x04, 0x02, 0x19, 0x46, 0xe1, 0x28, 0xd7, + 0x4a, 0x32, 0xf7, 0x8a, 0x38, 0x6e, 0xf5, 0x8e, 0x79, 0xb1, 0x6a, 0xd0, 0x6b, 0x58, 0xdc, 0x67, 0x4d, 0xfb, 0x59, + 0xe3, 0xe8, 0xd9, 0xb1, 0x0d, 0xff, 0x3b, 0xac, 0x99, 0x19, 0xbc, 0xe2, 0x2c, 0x0a, 0xd3, 0x69, 0x51, 0x73, 0x5b, + 0xb5, 0x25, 0x63, 0x1f, 0x8b, 0x5a, 0x27, 0xf5, 0x95, 0x46, 0xde, 0x5d, 0x51, 0xa7, 0xb6, 0xc6, 0x34, 0x5a, 0x48, + 0x60, 0xd5, 0x40, 0xe3, 0x87, 0x0b, 0x90, 0xb3, 0x4b, 0x35, 0xe4, 0xd7, 0x7c, 0xb8, 0xc5, 0xb8, 0x58, 0x33, 0xbb, + 0x16, 0x39, 0x14, 0xd4, 0xae, 0x48, 0x9a, 0x7b, 0xef, 0x0c, 0x72, 0x15, 0xa5, 0x8d, 0x39, 0xa7, 0x30, 0x9b, 0x21, + 0x64, 0x9c, 0x62, 0x62, 0x81, 0x3c, 0x5a, 0xa0, 0x34, 0x5e, 0x84, 0x43, 0x0d, 0x7f, 0x7a, 0x83, 0x44, 0xf3, 0x0f, + 0x63, 0x8b, 0x7f, 0x58, 0xc7, 0x55, 0xf3, 0x7a, 0x76, 0x91, 0x5a, 0x3e, 0x11, 0xab, 0xe2, 0x3d, 0x4b, 0x8d, 0x18, + 0xf5, 0xd8, 0xb4, 0xb4, 0xa6, 0xeb, 0x3d, 0xcb, 0x1b, 0x3e, 0x4b, 0x8d, 0xf0, 0x39, 0xe8, 0x3e, 0x5d, 0xfb, 0xc9, + 0x13, 0xaa, 0x75, 0xe0, 0x8a, 0x61, 0x9d, 0x0d, 0x8b, 0xcc, 0x14, 0x8a, 0x37, 0x89, 0x28, 0x39, 0x45, 0x67, 0x68, + 0x44, 0xcf, 0x9f, 0xf7, 0x5c, 0x47, 0x1f, 0xc4, 0xcc, 0xfb, 0x98, 0x89, 0x70, 0xdf, 0x21, 0x66, 0xa1, 0xbd, 0xd8, + 0xcf, 0xd0, 0x48, 0xaf, 0x75, 0xa5, 0x9d, 0xc3, 0x9d, 0xc9, 0x16, 0xee, 0x08, 0x1c, 0x7b, 0x41, 0x86, 0x7a, 0x32, + 0x28, 0xf0, 0x84, 0xc1, 0x8f, 0xa8, 0x93, 0xdf, 0xba, 0x9a, 0x96, 0x6d, 0xd9, 0x6a, 0xde, 0x70, 0xec, 0x4f, 0xdc, + 0x75, 0x94, 0x7a, 0x9d, 0x03, 0xc7, 0x08, 0xa2, 0x09, 0xf8, 0xd1, 0xa5, 0x7e, 0x1a, 0xb0, 0x8e, 0xaa, 0x82, 0x43, + 0xdd, 0x8c, 0xee, 0xe5, 0x19, 0xf7, 0x6e, 0xf0, 0x62, 0x48, 0x4e, 0x1e, 0xdf, 0x09, 0x57, 0x5c, 0x0c, 0x96, 0xfe, + 0x03, 0x10, 0x43, 0x4d, 0xd5, 0x40, 0x36, 0xc0, 0xe2, 0xc4, 0x94, 0xbd, 0x85, 0x3a, 0x0a, 0xb4, 0xd1, 0x55, 0x3e, + 0x88, 0x71, 0xec, 0xcd, 0x20, 0x7b, 0xee, 0x3a, 0x33, 0x38, 0xa6, 0x55, 0x39, 0xaa, 0x55, 0x9c, 0x17, 0xc7, 0x86, + 0xd2, 0x70, 0x0c, 0xc5, 0x06, 0x74, 0xab, 0x66, 0xc6, 0x3a, 0xbb, 0xee, 0xde, 0x67, 0xf0, 0x40, 0xf8, 0xe5, 0x11, + 0x8d, 0x83, 0x4c, 0x1d, 0xb8, 0x2a, 0x29, 0xa5, 0x24, 0x39, 0x9a, 0x94, 0x35, 0xd3, 0x27, 0xa5, 0xe7, 0x25, 0x5b, + 0xa5, 0x3a, 0x68, 0x8e, 0x44, 0x15, 0x5f, 0x5f, 0xa3, 0xc3, 0xb0, 0x1f, 0x2a, 0xfe, 0xa7, 0x4f, 0x9a, 0x0f, 0xce, + 0x4c, 0xae, 0x34, 0x3f, 0xf0, 0xac, 0x97, 0x26, 0xcc, 0x2f, 0xd4, 0xf4, 0x38, 0x59, 0xe0, 0x69, 0x08, 0xff, 0x16, + 0xc5, 0xe2, 0x07, 0x37, 0x93, 0xb0, 0x02, 0x2f, 0x9c, 0x00, 0x4a, 0xf3, 0xc2, 0xc9, 0x86, 0x39, 0x16, 0xf9, 0x3c, + 0x57, 0x4a, 0x8b, 0xae, 0x0a, 0x53, 0xa9, 0xe4, 0xe5, 0xdd, 0xa5, 0x37, 0xf9, 0xd1, 0x9b, 0x31, 0x4d, 0x05, 0x2a, + 0x87, 0x2e, 0xba, 0x85, 0x26, 0xf7, 0xb9, 0xfb, 0xf4, 0x74, 0xc6, 0x52, 0x8f, 0xd4, 0x40, 0x70, 0xf9, 0x05, 0x76, + 0x40, 0xe1, 0x84, 0x86, 0x07, 0xbc, 0x70, 0x29, 0x97, 0x16, 0xd1, 0x09, 0x43, 0xe1, 0x74, 0xca, 0x44, 0x8b, 0x4f, + 0xd7, 0x31, 0xc8, 0xe1, 0x60, 0xe8, 0x61, 0x3e, 0x1d, 0x37, 0x8c, 0xd4, 0xde, 0xd3, 0xdc, 0x37, 0x73, 0xdb, 0x22, + 0x04, 0x7e, 0xf8, 0xf1, 0x2a, 0x66, 0xc1, 0x3f, 0xdd, 0xa7, 0x40, 0xb8, 0x9f, 0x5e, 0xab, 0x7a, 0x37, 0xb5, 0xa6, + 0x31, 0x1b, 0xbb, 0x4f, 0xe1, 0x42, 0xda, 0x41, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xaf, 0x66, 0x81, 0x81, 0xd7, 0x7b, + 0x82, 0x45, 0x6d, 0x36, 0x8a, 0xb8, 0xe6, 0xcd, 0xbd, 0x2e, 0xf5, 0x3d, 0x7e, 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, + 0xc7, 0x76, 0xba, 0x78, 0x7f, 0x1e, 0x04, 0xde, 0xf0, 0x63, 0x97, 0xde, 0x94, 0x1e, 0x4c, 0xa0, 0xd6, 0x43, 0x6f, + 0xde, 0x41, 0xf2, 0x2a, 0x17, 0x82, 0xf7, 0x34, 0x95, 0xe6, 0x9c, 0x5d, 0xed, 0x5e, 0xc6, 0xad, 0xbc, 0xc6, 0x2f, + 0xe3, 0xa7, 0x96, 0x53, 0x3f, 0x65, 0xe2, 0x53, 0xf8, 0x90, 0x65, 0xe2, 0xa2, 0x4e, 0x57, 0x54, 0xbc, 0x58, 0x5b, + 0x4d, 0xc5, 0x69, 0x7f, 0xd7, 0xba, 0x75, 0xec, 0x69, 0xc3, 0xb1, 0xda, 0x1f, 0x9c, 0xf6, 0xb4, 0x69, 0x9d, 0x04, + 0x66, 0xd3, 0x3a, 0x81, 0x3f, 0x1f, 0x4e, 0xac, 0xf6, 0xd4, 0x6c, 0x58, 0x47, 0x1f, 0x9c, 0x46, 0x60, 0xb6, 0xad, + 0x13, 0xf8, 0x73, 0x41, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, + 0x89, 0xbc, 0xd5, 0xe8, 0x75, 0xe7, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0xbb, 0x5a, 0xe8, 0x32, 0x4a, 0x24, 0x2b, + 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0x59, 0x7b, 0x8c, 0x78, 0x9b, 0xfa, 0x0c, 0x96, 0xba, 0xc8, 0x05, 0x8c, + 0xcf, 0x3f, 0xcf, 0x31, 0xfe, 0xba, 0x48, 0xbc, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x89, 0xb6, 0x15, + 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xfc, 0xd6, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, + 0x21, 0x67, 0x9f, 0x1c, 0xf9, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xfa, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, + 0x7c, 0xeb, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x20, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, + 0x9d, 0x16, 0x90, 0xdd, 0x16, 0x6b, 0xee, 0xb4, 0xa9, 0xa4, 0x9b, 0xce, 0x2e, 0xdf, 0xea, 0x22, 0xd3, 0x91, 0xb0, + 0x9b, 0x12, 0x16, 0x1b, 0x5b, 0x0d, 0x3b, 0x37, 0xec, 0x35, 0x20, 0x55, 0x5c, 0xe5, 0xaa, 0xa3, 0xea, 0xdd, 0x50, + 0x98, 0x1f, 0x84, 0x3b, 0x92, 0xbc, 0xf1, 0xbb, 0x98, 0x0a, 0x53, 0xb3, 0x63, 0x1c, 0xf7, 0x38, 0x88, 0xff, 0xa7, + 0x07, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x39, 0xad, 0x25, 0xe7, 0xbd, 0x9c, 0xae, 0x12, 0x41, 0x65, 0xc9, 0x99, + 0x0a, 0x45, 0x6a, 0x47, 0x45, 0xc7, 0x30, 0x35, 0x37, 0x16, 0xcd, 0xa9, 0x45, 0x51, 0x60, 0xf8, 0x98, 0x50, 0x53, + 0x38, 0x8e, 0xea, 0x4f, 0x9e, 0x6c, 0x25, 0x42, 0x64, 0x9c, 0x93, 0xb0, 0x54, 0x30, 0xe8, 0x9a, 0x2a, 0xe3, 0x37, + 0x55, 0x46, 0x31, 0x79, 0xbf, 0x88, 0x35, 0x84, 0x8d, 0x2b, 0xed, 0x3d, 0xfc, 0x39, 0x60, 0x5e, 0x6a, 0x71, 0x65, + 0xa9, 0x26, 0x11, 0x77, 0xc3, 0x61, 0x4d, 0xb0, 0x6e, 0xe5, 0x69, 0x1a, 0x78, 0x1a, 0x94, 0xc7, 0xeb, 0x3f, 0x2f, + 0x78, 0x54, 0x07, 0xe8, 0xe3, 0x93, 0x5d, 0xc4, 0xe1, 0x7c, 0x9b, 0x7a, 0x14, 0x07, 0x4d, 0x26, 0xb9, 0x51, 0xea, + 0x91, 0x3d, 0x87, 0x8f, 0xa1, 0x6b, 0xea, 0x23, 0x72, 0x49, 0x91, 0x1f, 0x7a, 0x6f, 0x2f, 0xbf, 0x51, 0xf8, 0xfe, + 0x27, 0x6b, 0x01, 0xbc, 0xc8, 0x50, 0xbc, 0x19, 0x97, 0xe2, 0xcd, 0x28, 0x3c, 0x93, 0x31, 0xe4, 0x5c, 0xcd, 0x0e, + 0x69, 0x06, 0x51, 0x00, 0x4d, 0x36, 0x14, 0xb3, 0x45, 0x90, 0xfa, 0x73, 0x2f, 0x4e, 0x0f, 0x31, 0xd8, 0x0c, 0x06, + 0xaf, 0xd9, 0x16, 0x0f, 0x82, 0xcc, 0x30, 0x44, 0x76, 0x90, 0x34, 0x14, 0x76, 0x18, 0x63, 0x3f, 0xc8, 0xcd, 0x30, + 0xc4, 0x07, 0xbc, 0xe1, 0x90, 0xcd, 0x53, 0xb7, 0x14, 0xd4, 0x26, 0x1a, 0xa6, 0x2c, 0x35, 0x93, 0x34, 0x66, 0xde, + 0x4c, 0xcd, 0x83, 0x5c, 0x6d, 0xf6, 0x97, 0x2c, 0x06, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, + 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0x2f, 0xa2, 0x49, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x19, 0x26, 0x09, 0xa3, 0x9b, + 0x0c, 0x48, 0x8b, 0x87, 0x51, 0x70, 0xc3, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xde, 0x29, 0xbf, 0xde, 0x2a, 0x18, + 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x06, 0x6d, 0x5b, 0x74, 0x8b, 0x43, 0x5e, 0x19, 0x48, 0x13, 0xf5, 0x8c, 0x99, 0x2c, + 0x09, 0x96, 0x4b, 0x60, 0x84, 0x4a, 0x06, 0x33, 0x53, 0xa7, 0x97, 0xbb, 0x53, 0x22, 0x54, 0xc8, 0x2b, 0x7d, 0xfa, + 0xf4, 0xbe, 0xff, 0xef, 0x7f, 0x41, 0xba, 0xcd, 0xa9, 0x23, 0x62, 0x4a, 0x5c, 0xc9, 0xb5, 0x38, 0xf7, 0x69, 0xf4, + 0xd1, 0x58, 0x8a, 0x8d, 0x44, 0xb4, 0x3f, 0xb1, 0xb5, 0xb2, 0xfe, 0xb5, 0x88, 0x53, 0x07, 0x89, 0x7a, 0x75, 0x11, + 0xf9, 0xa2, 0x0f, 0xcb, 0xdb, 0x17, 0x31, 0x51, 0x94, 0xbf, 0xaf, 0x5e, 0x9e, 0x28, 0x45, 0xf8, 0xc4, 0x3a, 0x8b, + 0x1e, 0xda, 0x43, 0xbd, 0x53, 0x4f, 0x41, 0xa6, 0x05, 0xd9, 0x8f, 0xa4, 0x73, 0x08, 0xc3, 0x9c, 0x46, 0x33, 0x66, + 0xf9, 0xd1, 0xe1, 0x92, 0x0d, 0x4c, 0x6f, 0xee, 0x93, 0x5d, 0x0e, 0xca, 0xdd, 0x14, 0xe2, 0xfc, 0x72, 0x73, 0x17, + 0xe2, 0xaf, 0xb3, 0x62, 0x2a, 0xa3, 0x4a, 0x20, 0xb4, 0x46, 0xa1, 0x07, 0x3c, 0xe2, 0x41, 0xc6, 0x44, 0xcd, 0xde, + 0xe9, 0xa1, 0xd7, 0x2b, 0x67, 0x9e, 0xb1, 0x44, 0x06, 0xd5, 0x32, 0x11, 0x38, 0xa3, 0x04, 0x32, 0x22, 0x57, 0x4c, + 0xf1, 0x60, 0x46, 0xe3, 0xb1, 0x9c, 0x2d, 0xc6, 0x2a, 0x83, 0x97, 0x4f, 0x5a, 0xb1, 0xa5, 0xa3, 0x39, 0x7d, 0x69, + 0xf3, 0x13, 0xf9, 0x4f, 0xb5, 0x83, 0x69, 0xa2, 0x60, 0xcc, 0x70, 0xdc, 0x37, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, + 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x85, 0x73, 0x39, 0x70, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0x58, + 0x93, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x9b, 0x30, 0x1e, 0x7a, 0x62, + 0xfb, 0x95, 0x36, 0x28, 0x6c, 0x3c, 0xbe, 0xee, 0x80, 0xdf, 0x45, 0x3f, 0x15, 0x34, 0xaf, 0x7c, 0x4d, 0x18, 0xdd, + 0x0c, 0xbc, 0xbb, 0x48, 0x32, 0x63, 0xe2, 0x11, 0x4d, 0x2e, 0xb0, 0xf4, 0x52, 0x78, 0x12, 0x6f, 0x1c, 0x34, 0x24, + 0x61, 0x90, 0x75, 0x73, 0xf3, 0xb0, 0x15, 0xf4, 0x37, 0x60, 0xf7, 0x9d, 0x35, 0xb9, 0x6e, 0x79, 0x30, 0x88, 0x3c, + 0xb3, 0xe2, 0x1c, 0x96, 0x5e, 0x22, 0x5a, 0xc8, 0x4e, 0x0f, 0x61, 0x7c, 0x10, 0x85, 0xa5, 0xc4, 0x38, 0xf9, 0x3a, + 0x84, 0x7a, 0xf1, 0x12, 0x32, 0xc5, 0xfa, 0x7e, 0x24, 0x78, 0x3e, 0xbc, 0x58, 0x4a, 0xb9, 0xe4, 0xa5, 0x2a, 0x9b, + 0xbc, 0x8c, 0x5d, 0xcf, 0x04, 0xde, 0x9f, 0xa2, 0xf6, 0xc3, 0x02, 0xf3, 0xd3, 0x66, 0xdd, 0x94, 0x89, 0x20, 0x07, + 0x17, 0xe9, 0x96, 0x38, 0x08, 0xdb, 0xaa, 0x10, 0x3f, 0xbb, 0xa3, 0x42, 0xb1, 0x8f, 0x77, 0xd5, 0x2a, 0x38, 0xa7, + 0xa2, 0x9a, 0xa7, 0xa9, 0x8f, 0x70, 0xc7, 0x6f, 0xd4, 0xc6, 0x52, 0x8c, 0xce, 0x90, 0xba, 0x50, 0x55, 0xc8, 0xe2, + 0xbd, 0xf9, 0x9c, 0x2a, 0xeb, 0xdd, 0xd3, 0x43, 0xba, 0x96, 0xf6, 0x68, 0x87, 0xf5, 0x4e, 0xc1, 0x94, 0x9b, 0x16, + 0xdd, 0x9b, 0xcf, 0xf9, 0x92, 0xd2, 0x2f, 0x7a, 0x73, 0x38, 0x4d, 0x67, 0x41, 0xef, 0x7f, 0x01, 0xb9, 0x4b, 0x40, + 0x75, 0x91, 0x7a, 0x03, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0xa5, 0x72, 0x53, 0x82, 0x27, 0x1b, 0xbc, 0x80, 0x75, 0x03, 0x48, 0xa5, 0xee, 0x7f, 0x2b, 0x0f, 0x47, 0x11, - 0x6c, 0x9c, 0x30, 0x00, 0xbc, 0x78, 0xe3, 0x55, 0x06, 0x02, 0xe7, 0x01, 0x48, 0x39, 0xae, 0xfd, 0x5e, 0x40, 0x55, - 0x4d, 0x39, 0x3a, 0x86, 0x68, 0xb0, 0x4b, 0x00, 0x54, 0x6c, 0xdf, 0xed, 0x57, 0x28, 0x4a, 0x70, 0x44, 0x0e, 0x0a, - 0x69, 0x65, 0x69, 0xd3, 0x0b, 0x32, 0x81, 0x19, 0x99, 0x45, 0x41, 0x5c, 0x10, 0x08, 0x62, 0xa3, 0x51, 0x83, 0xcd, - 0x39, 0x4f, 0x9c, 0xe3, 0x34, 0x65, 0x23, 0x09, 0xb7, 0x1c, 0x9c, 0x0d, 0xdd, 0x8c, 0x40, 0x15, 0x18, 0xc2, 0xe1, - 0x0d, 0x6d, 0x41, 0xba, 0xf2, 0xe0, 0xce, 0x7b, 0x72, 0x4e, 0x34, 0xfe, 0x50, 0x23, 0x59, 0xda, 0x96, 0x63, 0x22, - 0x70, 0xf0, 0x6a, 0xb7, 0x8c, 0x88, 0x6e, 0x48, 0x1a, 0xf6, 0x45, 0xf5, 0xa0, 0xf6, 0x37, 0xf1, 0x4b, 0x22, 0x1c, - 0x2f, 0x73, 0x23, 0x8a, 0x31, 0x70, 0x24, 0x71, 0x67, 0x77, 0x29, 0xa1, 0x7d, 0xad, 0xb1, 0x07, 0x6b, 0x81, 0x56, - 0x9e, 0x58, 0x49, 0x4c, 0x4f, 0x54, 0x3f, 0x88, 0x99, 0x48, 0x93, 0x67, 0x63, 0xed, 0x72, 0xc1, 0x0d, 0x75, 0x3e, - 0x51, 0xff, 0x97, 0xe7, 0x7b, 0xc9, 0x07, 0xd3, 0x4d, 0xf1, 0x33, 0xbf, 0xf5, 0x5a, 0xc7, 0x8d, 0x5a, 0x44, 0x59, - 0xb7, 0xb4, 0xf1, 0x5d, 0x70, 0x1b, 0xcf, 0xdd, 0x66, 0xb5, 0xe0, 0x04, 0x41, 0x10, 0xcb, 0x00, 0xc7, 0x98, 0xa8, - 0x1f, 0x22, 0x6d, 0x84, 0x78, 0xf1, 0x7e, 0x44, 0xdf, 0xfe, 0x4b, 0xb5, 0xff, 0xfa, 0x0d, 0x7b, 0xb6, 0x6e, 0xaf, - 0x4d, 0xcf, 0xbc, 0x4d, 0x53, 0x8c, 0xb3, 0xd8, 0x7b, 0x56, 0xdb, 0x59, 0x59, 0x2a, 0x19, 0xc6, 0x3d, 0xe4, 0x45, - 0x0c, 0x01, 0x1c, 0x00, 0x1d, 0x49, 0xee, 0xa7, 0x7d, 0x9b, 0xf6, 0x9d, 0xee, 0xf3, 0xd8, 0xd6, 0x6f, 0xdb, 0x09, - 0xa9, 0x7d, 0xca, 0xc5, 0xdf, 0x31, 0x02, 0x2b, 0x31, 0x12, 0x63, 0x89, 0x96, 0xfb, 0x2a, 0x67, 0xfd, 0x79, 0x2e, - 0x37, 0x57, 0x8c, 0x46, 0x4e, 0x9e, 0x5a, 0x22, 0xb3, 0x00, 0xef, 0xa9, 0xfe, 0x18, 0x84, 0x77, 0xd9, 0xac, 0xb6, - 0xa9, 0xf6, 0x87, 0xa4, 0x14, 0x52, 0x85, 0x5d, 0x44, 0xc8, 0x19, 0x21, 0xb6, 0x92, 0xef, 0x97, 0xf6, 0x7b, 0x7f, - 0xe6, 0xfb, 0xf5, 0x0d, 0xc7, 0xb9, 0x19, 0x8e, 0x76, 0x1d, 0x86, 0x94, 0x3a, 0x29, 0xb5, 0x39, 0xb2, 0x18, 0x16, - 0x5e, 0x64, 0x69, 0x9f, 0x24, 0x5c, 0xc7, 0xff, 0x7a, 0x5f, 0x57, 0x5f, 0xbf, 0x76, 0x17, 0x2b, 0xce, 0x1d, 0x1d, - 0x29, 0x4b, 0xd8, 0xe7, 0x15, 0x37, 0x3d, 0x19, 0xc2, 0x23, 0xbc, 0x42, 0x91, 0xcc, 0x23, 0xa5, 0x72, 0x19, 0xc7, - 0xea, 0x18, 0xed, 0x1a, 0xd9, 0xa5, 0x56, 0x88, 0x8c, 0xd5, 0xf0, 0xff, 0xf5, 0x35, 0xad, 0xaf, 0x5f, 0x89, 0xb0, - 0xca, 0x5c, 0xea, 0x40, 0xa1, 0x99, 0xfd, 0x3d, 0x92, 0x9c, 0x65, 0xd9, 0x3d, 0x15, 0x82, 0x96, 0x69, 0x1b, 0x2f, - 0xe0, 0x00, 0x7a, 0xcd, 0xba, 0xf7, 0xbe, 0xaa, 0xfe, 0xfb, 0xe7, 0x0b, 0xa1, 0x3b, 0x44, 0x1b, 0xb8, 0xdc, 0x1d, - 0x26, 0x4b, 0x33, 0x6b, 0xaa, 0xe9, 0xce, 0xd8, 0x14, 0x05, 0x4a, 0x4c, 0x25, 0xca, 0x8f, 0x80, 0x95, 0x49, 0x4b, - 0x5d, 0x55, 0x94, 0xce, 0x7e, 0x48, 0x05, 0x65, 0x53, 0x36, 0x34, 0xc3, 0xb6, 0x75, 0xea, 0xfb, 0x93, 0xcc, 0xf7, - 0x13, 0x5e, 0x90, 0x8d, 0x0d, 0xcd, 0xb7, 0x2f, 0x4f, 0xd7, 0x71, 0x23, 0x2d, 0xb0, 0xc4, 0x22, 0xbd, 0x6f, 0x90, - 0x13, 0xa5, 0x12, 0xf3, 0x3f, 0xdc, 0x72, 0xe2, 0x12, 0x88, 0xd6, 0x66, 0x6f, 0x0b, 0xf1, 0x8a, 0x2f, 0x12, 0x3d, - 0x1f, 0x44, 0x3c, 0x4d, 0x2d, 0x5f, 0x6f, 0xfb, 0x25, 0x5f, 0xa5, 0x73, 0x29, 0x2f, 0xa5, 0x58, 0x49, 0x37, 0x57, - 0xba, 0xc0, 0xbb, 0xb7, 0xa9, 0x44, 0x69, 0x3a, 0xb0, 0x81, 0x1c, 0x8a, 0xa4, 0x8c, 0x2d, 0x50, 0xd8, 0x7b, 0x7f, - 0x3f, 0xfb, 0xaf, 0x5f, 0x9d, 0x5a, 0x9c, 0x39, 0x0c, 0x22, 0xde, 0x77, 0x34, 0xb0, 0x8f, 0xc7, 0x5b, 0xad, 0x1b, - 0x35, 0xc6, 0xec, 0xd2, 0xe0, 0x25, 0x51, 0xdb, 0xd3, 0x70, 0xcc, 0x65, 0x55, 0x7d, 0x8a, 0x0a, 0x8d, 0x18, 0x42, - 0x97, 0x67, 0xbf, 0xcf, 0x64, 0x1f, 0xd3, 0x0d, 0xcc, 0x60, 0xd8, 0xc8, 0x73, 0x82, 0x71, 0xbd, 0x10, 0xd1, 0xd6, - 0x60, 0xa9, 0xda, 0x8a, 0x21, 0x49, 0x97, 0xed, 0x91, 0x5d, 0x78, 0x51, 0xf6, 0x07, 0x7f, 0xeb, 0x3c, 0x3c, 0x12, - 0x95, 0x0f, 0x0f, 0xc9, 0x07, 0xd4, 0xea, 0x1b, 0x7e, 0xdf, 0xd7, 0xa6, 0x7b, 0x97, 0xc9, 0x61, 0x2b, 0xf1, 0x2f, - 0x8d, 0x52, 0x01, 0x68, 0x0b, 0xe0, 0x51, 0x80, 0x2e, 0x45, 0x3d, 0x35, 0x58, 0xfe, 0xff, 0xde, 0x4a, 0xcb, 0xed, - 0x8f, 0xb4, 0x20, 0xda, 0x01, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xca, 0x02, 0x5b, 0x0d, 0x90, 0xec, 0x71, - 0x66, 0x25, 0xad, 0xb5, 0xd8, 0x54, 0x5c, 0xf3, 0x2e, 0xf3, 0xbb, 0xe8, 0x8c, 0x1f, 0x86, 0x15, 0x26, 0xb3, 0x91, - 0xae, 0x9a, 0x65, 0x1b, 0x59, 0x4e, 0x03, 0x80, 0xe0, 0x7d, 0xef, 0xff, 0x28, 0xfc, 0xff, 0x23, 0x8b, 0xf3, 0x23, - 0xb2, 0x40, 0x45, 0x66, 0x15, 0xe7, 0x64, 0x15, 0x30, 0xa3, 0x2a, 0x90, 0x33, 0x2a, 0x80, 0x7d, 0x74, 0x40, 0x8e, - 0x13, 0xbd, 0xa6, 0xe9, 0x8e, 0x86, 0x94, 0xf7, 0x3b, 0x2d, 0x56, 0x6c, 0xca, 0xfb, 0xdd, 0x0e, 0x94, 0x35, 0x4b, - 0x69, 0xa5, 0xa3, 0xff, 0xd5, 0x99, 0xeb, 0x3f, 0xd6, 0x5d, 0x11, 0x26, 0x5f, 0x27, 0xdd, 0x30, 0x6c, 0xf1, 0xff, - 0x92, 0x41, 0x72, 0x1a, 0x60, 0x39, 0x28, 0x17, 0xe5, 0x94, 0xec, 0x32, 0x8d, 0x1d, 0xbb, 0xad, 0xc4, 0xc3, 0xc6, - 0x63, 0x5f, 0xd5, 0x1f, 0xc3, 0xef, 0xe1, 0x68, 0x41, 0x98, 0x3a, 0xd3, 0x34, 0xfd, 0x77, 0xfb, 0x63, 0xd9, 0xf7, - 0x3a, 0x3d, 0xe7, 0xe8, 0xef, 0xac, 0x42, 0x08, 0x24, 0x04, 0x14, 0x84, 0x60, 0xdd, 0xd9, 0x46, 0xb5, 0x2a, 0x5d, - 0x6d, 0xdd, 0x71, 0xd5, 0xaa, 0x69, 0xbe, 0x86, 0x3f, 0x04, 0x08, 0x81, 0x99, 0xbb, 0xc7, 0x70, 0x76, 0x39, 0x03, - 0x11, 0x09, 0xd1, 0x7f, 0x8f, 0x53, 0xca, 0x99, 0xd2, 0x83, 0xb4, 0x05, 0x42, 0xa4, 0xc6, 0x6b, 0x7b, 0xfd, 0xfd, - 0xf3, 0x78, 0xb9, 0x45, 0x74, 0x52, 0xdf, 0x2b, 0xd0, 0x1e, 0xa1, 0xed, 0x1f, 0x89, 0xa7, 0x3c, 0xe4, 0x11, 0xaf, - 0x04, 0x8b, 0x4d, 0xd2, 0xd5, 0x70, 0x9f, 0x00, 0x57, 0xf8, 0x16, 0x97, 0xb6, 0x76, 0x97, 0x9b, 0xac, 0xc5, 0x35, - 0x13, 0x6c, 0xee, 0x2c, 0x26, 0xce, 0x2d, 0x0e, 0x10, 0x4e, 0xc7, 0x88, 0xb6, 0xe0, 0x32, 0xd0, 0x1c, 0xe7, 0x0e, - 0x7e, 0xf9, 0xbc, 0x10, 0x4c, 0xa3, 0x3d, 0x94, 0x6c, 0xc7, 0x28, 0xc4, 0x14, 0x44, 0x9e, 0x17, 0xce, 0xde, 0x7d, - 0x60, 0x72, 0x3f, 0xa5, 0x62, 0x30, 0x0b, 0xa3, 0x27, 0x2c, 0x19, 0x68, 0x5a, 0x2f, 0xf9, 0x15, 0x80, 0x77, 0xf8, - 0x2e, 0x9c, 0xb0, 0x08, 0x94, 0xf1, 0xed, 0x17, 0xdc, 0x67, 0x18, 0x3f, 0x0b, 0xd3, 0xce, 0x0a, 0x75, 0xf0, 0x40, - 0xe0, 0xfd, 0xba, 0xf1, 0x8c, 0x5f, 0x28, 0x37, 0xec, 0x96, 0x61, 0xe6, 0x91, 0xce, 0x2f, 0xa7, 0xe8, 0x0a, 0x49, - 0x95, 0x0b, 0x62, 0xcf, 0x3d, 0x2e, 0xcd, 0xf9, 0x8f, 0x68, 0x79, 0x19, 0xb8, 0xa3, 0x37, 0x81, 0x98, 0xfa, 0x7b, - 0xeb, 0xaa, 0xd9, 0xde, 0x69, 0x11, 0x00, 0x48, 0xae, 0x5d, 0x1c, 0x66, 0xb4, 0x2d, 0xae, 0xaf, 0xe5, 0xd5, 0x6e, - 0xbc, 0x95, 0x7a, 0x98, 0xa0, 0x21, 0xd9, 0x30, 0x83, 0x33, 0xdb, 0x7f, 0x78, 0xf9, 0xf6, 0xda, 0x62, 0x5c, 0x46, - 0xcd, 0xfe, 0x3a, 0xad, 0x6d, 0xe8, 0x48, 0x1b, 0x90, 0xc3, 0x5d, 0xe9, 0xfa, 0x90, 0x52, 0x50, 0xd8, 0xb0, 0xc9, - 0xe0, 0xb9, 0xe8, 0x8e, 0xfb, 0x98, 0xd4, 0x12, 0x93, 0x75, 0x39, 0xe7, 0xd2, 0x00, 0xb3, 0x99, 0xbd, 0xbd, 0x76, - 0xa5, 0x01, 0x77, 0xf8, 0x71, 0xb7, 0x3f, 0x32, 0xb9, 0x17, 0x4d, 0xfc, 0x62, 0xc6, 0xe5, 0x71, 0x08, 0xec, 0xed, - 0x8f, 0xb4, 0xaf, 0x16, 0x34, 0x9b, 0x5b, 0x3f, 0xe6, 0x1b, 0x5f, 0x76, 0xd7, 0xa3, 0x08, 0x1a, 0x9a, 0x7c, 0x69, - 0xd0, 0xbc, 0x68, 0x7a, 0xf5, 0x19, 0xb5, 0x42, 0x7d, 0xe3, 0x27, 0x52, 0x78, 0xec, 0x26, 0xf1, 0xd7, 0x2e, 0xb7, - 0xef, 0x7e, 0xf7, 0x38, 0x78, 0xf4, 0x45, 0x0c, 0x2f, 0xdf, 0x5e, 0x3f, 0x6e, 0x9e, 0xe1, 0x39, 0xa3, 0x3a, 0x6c, - 0x86, 0x84, 0xa1, 0xe6, 0xf7, 0x5f, 0x32, 0xcc, 0xbe, 0x2c, 0x7b, 0x32, 0xab, 0xcb, 0x7f, 0xee, 0xeb, 0x23, 0x3e, - 0xa8, 0x5d, 0x3e, 0xe3, 0xd7, 0x3f, 0x10, 0x9e, 0xfe, 0x8b, 0xa4, 0x87, 0x75, 0x87, 0xf6, 0x67, 0x7d, 0x33, 0x7e, - 0xec, 0xaa, 0xb0, 0xef, 0xc3, 0x7c, 0x43, 0x68, 0x7b, 0x1e, 0x53, 0xd3, 0x2b, 0x51, 0xc1, 0x44, 0x1c, 0x07, 0x21, - 0x18, 0xb5, 0x75, 0x7a, 0x6b, 0x06, 0xe7, 0xf6, 0x0c, 0xc6, 0xec, 0xb6, 0x5a, 0x2c, 0x6d, 0x08, 0x6f, 0xe6, 0xc3, - 0xae, 0x8f, 0x0b, 0xf4, 0x17, 0x58, 0x8c, 0x21, 0xed, 0xfa, 0xfe, 0x4a, 0x5f, 0xad, 0x2c, 0xcb, 0x00, 0x40, 0x60, - 0xa8, 0x67, 0xc3, 0xd1, 0xb3, 0x44, 0xc6, 0x3c, 0x9b, 0xcf, 0x0d, 0xe9, 0x32, 0xf4, 0xc8, 0xf5, 0x4d, 0xb7, 0x06, - 0x0d, 0x2f, 0x16, 0x6c, 0xc0, 0x57, 0x2b, 0x05, 0xeb, 0x15, 0x16, 0xe4, 0xce, 0x59, 0x71, 0x7f, 0x0f, 0xa5, 0x66, - 0x4d, 0xc4, 0x72, 0xdc, 0x4a, 0x0e, 0xf2, 0xbe, 0x8f, 0x30, 0xd2, 0xd8, 0xd7, 0xf6, 0xd6, 0x8b, 0xeb, 0x3b, 0xa8, - 0x08, 0x7b, 0x28, 0xf7, 0xb2, 0x4a, 0x41, 0x6c, 0xef, 0x18, 0xd2, 0xb3, 0x7c, 0xdc, 0xd7, 0xd7, 0x6e, 0xe6, 0x84, - 0x0f, 0x46, 0x23, 0x43, 0x19, 0x37, 0xd6, 0xe4, 0x89, 0xd8, 0x8f, 0xab, 0x94, 0xe6, 0x31, 0xca, 0x0f, 0x3a, 0xf2, - 0x42, 0x8c, 0xc6, 0xa4, 0x17, 0xec, 0x3b, 0x59, 0x0a, 0x8d, 0xe3, 0xbc, 0x24, 0x1e, 0x6b, 0x71, 0x44, 0x0a, 0x68, - 0x14, 0x1f, 0xc8, 0x66, 0x46, 0x24, 0x40, 0xd5, 0x22, 0xed, 0x2c, 0x9c, 0x44, 0x2d, 0x4e, 0xb4, 0xc1, 0x7b, 0xbf, - 0xdf, 0x71, 0xe7, 0xa4, 0x84, 0x8b, 0x2f, 0x2e, 0xdb, 0x9e, 0x26, 0xe4, 0xe1, 0x97, 0x72, 0xb2, 0xe6, 0x89, 0x9e, - 0x92, 0x5b, 0x1e, 0xb1, 0xa9, 0xb0, 0x4c, 0xc6, 0x42, 0x0f, 0x14, 0x87, 0x6e, 0x99, 0x57, 0xf1, 0x8e, 0x2f, 0x9f, - 0xe1, 0x6a, 0xf7, 0x9b, 0xef, 0x2d, 0x5f, 0xcb, 0xcc, 0x57, 0xeb, 0x1e, 0xd0, 0xf8, 0xe0, 0x04, 0x9e, 0xb2, 0xbb, - 0x6f, 0xbc, 0x9b, 0xbc, 0x06, 0x78, 0xf9, 0xdc, 0x2f, 0x51, 0xbe, 0xa8, 0xfd, 0x86, 0xe8, 0x35, 0x80, 0xc0, 0x03, - 0x91, 0x6c, 0xc5, 0xd4, 0x5b, 0x4e, 0x64, 0x72, 0xff, 0x3e, 0xc3, 0x36, 0x7c, 0xf2, 0x6e, 0x1d, 0xaa, 0xa4, 0xb1, - 0x12, 0x9e, 0x49, 0xeb, 0x77, 0xaa, 0xf6, 0x39, 0x12, 0x18, 0x7b, 0x15, 0xcc, 0xb0, 0x3b, 0x86, 0x98, 0x9d, 0xa4, - 0x70, 0xdc, 0x17, 0x1b, 0x2c, 0xf3, 0x9b, 0x99, 0x43, 0xb7, 0x34, 0x3e, 0x86, 0x3b, 0x19, 0xab, 0xb4, 0x4d, 0xa5, - 0x71, 0xd7, 0xf8, 0x1b, 0x82, 0xc0, 0x55, 0x87, 0xda, 0xa3, 0x49, 0xbf, 0x64, 0x5f, 0x70, 0x1d, 0x9c, 0x09, 0x7a, - 0x59, 0x0e, 0x56, 0xb8, 0x54, 0x83, 0xe5, 0xad, 0x8f, 0x00, 0x02, 0x61, 0x5b, 0x10, 0xc2, 0x06, 0xdb, 0x6b, 0xe9, - 0x58, 0x8d, 0x9c, 0xb1, 0x79, 0xff, 0xf1, 0x66, 0x89, 0x1e, 0xca, 0x16, 0x4e, 0x53, 0x7d, 0x29, 0x6b, 0xb5, 0xdf, - 0xbb, 0x7f, 0xbe, 0xef, 0x00, 0x07, 0x09, 0xc3, 0x0b, 0x3a, 0x38, 0xfe, 0x1a, 0xbd, 0x15, 0x8b, 0x60, 0x61, 0xb4, - 0x6d, 0x7d, 0xf6, 0xed, 0xa1, 0x78, 0x66, 0x41, 0x7c, 0x33, 0x6b, 0xb7, 0xae, 0x2a, 0x8e, 0xb0, 0x55, 0xc3, 0x26, - 0x84, 0xd6, 0x10, 0x01, 0x98, 0xfa, 0x4b, 0x8d, 0x7c, 0xb7, 0x0d, 0xab, 0x4e, 0x45, 0x14, 0xdb, 0xaa, 0x10, 0x47, - 0x50, 0xc9, 0xc1, 0xa0, 0x8a, 0x42, 0x17, 0x76, 0x0f, 0x7e, 0xe2, 0x64, 0x5c, 0x50, 0xdc, 0x54, 0x3c, 0x7a, 0x7e, - 0x0b, 0x94, 0x81, 0xa9, 0xbf, 0x5c, 0x69, 0xef, 0x0f, 0x90, 0x3e, 0xd8, 0xc3, 0x4e, 0xc9, 0xe7, 0x2a, 0x9e, 0xd0, - 0x77, 0x27, 0x34, 0x81, 0xe1, 0xe1, 0xd8, 0x9b, 0xc4, 0x07, 0x12, 0xf0, 0xa0, 0x60, 0x41, 0xbe, 0xbf, 0x13, 0xea, - 0xa6, 0x4f, 0x03, 0x02, 0x88, 0xaf, 0xaa, 0xe3, 0x70, 0x84, 0x60, 0x45, 0x1d, 0x0b, 0xec, 0x89, 0x8a, 0x53, 0x72, - 0x44, 0x86, 0x71, 0x82, 0xfa, 0x06, 0xe8, 0xe6, 0x53, 0xa5, 0xfc, 0x0b, 0xb7, 0x9b, 0x44, 0xe2, 0x59, 0xdf, 0x2a, - 0xda, 0x65, 0xa4, 0x48, 0xe0, 0x8d, 0x58, 0x47, 0x95, 0x42, 0xe9, 0x06, 0xcb, 0x94, 0x22, 0x4e, 0xd3, 0xe0, 0xfa, - 0xd2, 0x4b, 0xbd, 0xd6, 0x4e, 0x2d, 0xfd, 0x7a, 0xdd, 0x04, 0xfa, 0x1a, 0x0f, 0x59, 0xf0, 0xa5, 0xfa, 0xa9, 0x26, - 0xb0, 0x1b, 0x68, 0x3b, 0x97, 0xda, 0x9f, 0xa1, 0x71, 0xb2, 0xa1, 0x7d, 0x2d, 0x6f, 0x21, 0x80, 0x29, 0xdc, 0xa0, - 0xb6, 0xbc, 0x48, 0xa6, 0x76, 0x22, 0x66, 0x7f, 0x6c, 0x22, 0x99, 0x20, 0xaf, 0x1c, 0x6c, 0x68, 0x1f, 0xda, 0xc2, - 0xf3, 0xa0, 0x04, 0xc3, 0xcf, 0x5a, 0xca, 0xc0, 0x8a, 0xb0, 0xad, 0xed, 0xd7, 0xc7, 0xb0, 0x09, 0xa6, 0x0c, 0x82, - 0x50, 0x7f, 0x09, 0xda, 0x69, 0x30, 0x79, 0xd4, 0x63, 0xc6, 0x3e, 0x9b, 0x39, 0xdf, 0x83, 0x1e, 0xa5, 0x92, 0x85, - 0x20, 0x39, 0x0c, 0xf4, 0xd7, 0x62, 0x62, 0x1c, 0xa1, 0x42, 0x22, 0xb4, 0x5b, 0x25, 0x03, 0xf7, 0x1f, 0x54, 0x0c, - 0x11, 0x76, 0x54, 0x9d, 0x4b, 0xb3, 0x6b, 0x54, 0x31, 0x50, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x23, 0x84, 0xd3, 0xa6, - 0xf6, 0xce, 0x5d, 0x24, 0xd2, 0x53, 0x29, 0x62, 0xb1, 0x71, 0x56, 0xba, 0xd4, 0x0c, 0x6b, 0x61, 0x2c, 0x27, 0x46, - 0xd0, 0x38, 0x73, 0x47, 0x54, 0xc7, 0xb7, 0xac, 0x61, 0x04, 0xb8, 0x47, 0xec, 0xb6, 0x07, 0xad, 0x00, 0xb9, 0x26, - 0x69, 0xa0, 0xa0, 0xbd, 0x31, 0x21, 0x8b, 0x02, 0x19, 0x19, 0x93, 0xe8, 0x46, 0x50, 0x72, 0xf7, 0x75, 0x24, 0x8f, - 0x01, 0x76, 0xe5, 0x64, 0x3d, 0x43, 0x24, 0xc4, 0xf1, 0xa6, 0x56, 0x04, 0x81, 0xb1, 0x0c, 0xb0, 0x63, 0xe9, 0xa8, - 0xe4, 0x5c, 0xdc, 0xa0, 0xa7, 0xaa, 0x99, 0x5f, 0xd8, 0xf5, 0x19, 0x8a, 0x34, 0xa2, 0x5d, 0x40, 0x40, 0xce, 0x5c, - 0x75, 0x1d, 0x18, 0x39, 0x48, 0x5c, 0xa3, 0x3b, 0xad, 0x90, 0x51, 0x44, 0x3e, 0x2e, 0x86, 0xe5, 0x05, 0xe4, 0x46, - 0x5c, 0x6c, 0x94, 0x65, 0xc8, 0x45, 0x1f, 0xb9, 0x0d, 0xde, 0xb9, 0xd1, 0x93, 0xae, 0x13, 0x96, 0x00, 0xac, 0xc7, - 0xb2, 0x98, 0x70, 0xab, 0xa6, 0x67, 0xbf, 0x01, 0x9a, 0x04, 0x5e, 0x3b, 0xea, 0x1c, 0xe2, 0xf8, 0x42, 0x8d, 0x6c, - 0xf0, 0x6f, 0x6a, 0x94, 0xb0, 0xb6, 0x0d, 0x2b, 0x67, 0x9c, 0x56, 0x51, 0xec, 0xb1, 0xf2, 0x4c, 0xc4, 0xfc, 0x05, - 0xa3, 0xe8, 0x34, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x85, 0x88, 0x3d, 0x02, 0x4d, 0x81, 0x7d, - 0x6f, 0x28, 0x4c, 0xeb, 0x23, 0xc9, 0x49, 0xda, 0x53, 0x74, 0x36, 0x67, 0xc3, 0x0c, 0xb1, 0x8b, 0x80, 0x6e, 0xcf, - 0xb9, 0x0e, 0x57, 0xf6, 0x45, 0x29, 0x3c, 0x25, 0x33, 0x6a, 0x09, 0x26, 0xc2, 0x64, 0x78, 0x95, 0x5d, 0x20, 0xf2, - 0xde, 0xa6, 0x99, 0x49, 0xef, 0xe9, 0x95, 0xfb, 0x13, 0x40, 0x1e, 0xf7, 0xe4, 0x7d, 0xa6, 0x29, 0xc3, 0x15, 0x0e, - 0x41, 0x6d, 0x57, 0xcc, 0x63, 0xb9, 0x4d, 0xad, 0x4a, 0x6e, 0x38, 0xe0, 0x62, 0x21, 0x35, 0xee, 0xee, 0x6a, 0x73, - 0x42, 0x03, 0x48, 0x55, 0x4b, 0x67, 0x83, 0xe7, 0x80, 0xe2, 0x3d, 0x01, 0x44, 0x22, 0x1a, 0x85, 0xef, 0xfc, 0x28, - 0x47, 0xe7, 0x24, 0x21, 0x14, 0xe6, 0xea, 0x76, 0x5e, 0x7e, 0xa6, 0x94, 0x59, 0x6e, 0x38, 0x3a, 0x00, 0xd8, 0xa2, - 0x7d, 0x51, 0xf8, 0x3c, 0x02, 0xf9, 0xff, 0xa4, 0xb0, 0xf1, 0xad, 0x69, 0xc7, 0x54, 0xf5, 0x6c, 0x56, 0xe7, 0x61, - 0x81, 0xe7, 0x38, 0x65, 0x82, 0xe7, 0xdf, 0x56, 0x77, 0x43, 0xd4, 0xf9, 0xa7, 0xd8, 0x01, 0x5b, 0x6d, 0xb3, 0xbb, - 0x1d, 0xbc, 0xae, 0x16, 0x27, 0x87, 0x4c, 0xaa, 0xce, 0xf6, 0xc1, 0x37, 0xfb, 0xe9, 0x5f, 0x4e, 0x7e, 0x33, 0xc6, - 0x02, 0xc8, 0xab, 0x82, 0xaa, 0xc8, 0xc8, 0x74, 0x40, 0x89, 0x57, 0x86, 0xcf, 0xc5, 0x00, 0x2d, 0x32, 0xaf, 0x5a, - 0x09, 0x14, 0x9a, 0xd5, 0x88, 0xf2, 0x06, 0x10, 0x64, 0x2b, 0xd4, 0x5c, 0xa3, 0xe0, 0x08, 0x79, 0xd2, 0x62, 0x63, - 0xde, 0xb0, 0x52, 0x8b, 0x66, 0x99, 0xb6, 0xa6, 0xc8, 0x22, 0xb0, 0x38, 0x20, 0xae, 0xbf, 0xa0, 0x75, 0x36, 0x30, - 0x95, 0xe7, 0x83, 0x11, 0x06, 0xd8, 0x0d, 0x37, 0x92, 0x4d, 0x8c, 0xbd, 0x12, 0x8a, 0x9c, 0x06, 0xd2, 0xd8, 0x8f, - 0xef, 0xae, 0xe5, 0xed, 0xae, 0x25, 0xa6, 0xbe, 0x3c, 0x9c, 0x18, 0x4d, 0x0c, 0x2d, 0xed, 0x86, 0xa5, 0x87, 0xa8, - 0x9f, 0x9d, 0xcc, 0x4c, 0x39, 0x5b, 0x7b, 0x0c, 0x0f, 0x5d, 0xe7, 0x92, 0xbc, 0x7f, 0x36, 0x03, 0x01, 0xf9, 0xad, - 0xc0, 0x1a, 0xd0, 0x26, 0x11, 0x45, 0x20, 0x1c, 0xe4, 0xf4, 0x2d, 0x71, 0xf4, 0x37, 0x03, 0x4b, 0x76, 0x3d, 0xd4, - 0x2d, 0x75, 0x8b, 0xb1, 0xac, 0x95, 0x95, 0x53, 0x50, 0x71, 0xe9, 0x99, 0x8c, 0x79, 0x20, 0xd9, 0xa0, 0x6a, 0xb0, - 0x92, 0x7d, 0xde, 0x2e, 0x1c, 0xa8, 0xa4, 0x90, 0xbd, 0x9f, 0x06, 0x79, 0x71, 0x7a, 0x91, 0xac, 0x56, 0x62, 0x8c, - 0x47, 0xa9, 0xb6, 0xb9, 0x0e, 0x88, 0xab, 0x0e, 0x6d, 0xe0, 0xc5, 0x85, 0xed, 0x76, 0xbb, 0x66, 0xab, 0x80, 0xac, - 0x95, 0x4e, 0xe4, 0x66, 0x16, 0x9d, 0xef, 0x2d, 0x22, 0x9d, 0xb5, 0xe5, 0x21, 0x2f, 0xe7, 0xb1, 0x0d, 0xb2, 0xe8, - 0x96, 0xf0, 0xc2, 0x98, 0xb0, 0x81, 0xe5, 0xee, 0xdb, 0xf8, 0x82, 0x43, 0x21, 0x29, 0xd3, 0xd3, 0x4c, 0xbb, 0x37, - 0xc4, 0x7c, 0x57, 0x4d, 0xb4, 0xc2, 0x16, 0xcc, 0x75, 0xf0, 0x8b, 0x64, 0xb5, 0x97, 0xa2, 0x5a, 0x3a, 0x1f, 0x66, - 0xef, 0xd2, 0x91, 0xda, 0xcb, 0x00, 0xd5, 0x4e, 0x63, 0x33, 0x8e, 0x73, 0x02, 0xfa, 0x28, 0x98, 0x59, 0xe1, 0x25, - 0x20, 0xbb, 0x48, 0x61, 0x85, 0x95, 0xba, 0xcd, 0x18, 0x96, 0x52, 0xf7, 0xc3, 0x44, 0x67, 0x19, 0x62, 0xe3, 0x49, - 0x5f, 0x1a, 0x7b, 0x34, 0x8a, 0x47, 0xa8, 0x22, 0xaa, 0xdd, 0x1f, 0x21, 0x4c, 0x48, 0x75, 0x86, 0x27, 0x30, 0xed, - 0xf9, 0x08, 0x1d, 0x17, 0x30, 0xbf, 0x98, 0x85, 0x76, 0xfb, 0x7a, 0x8b, 0x58, 0x78, 0xf5, 0x21, 0xc5, 0x35, 0xa5, - 0xb7, 0xf2, 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x58, 0xa1, 0x68, 0x34, 0x1f, - 0xee, 0x36, 0x03, 0x6c, 0x86, 0xa0, 0x44, 0x42, 0x71, 0x63, 0x98, 0xc5, 0x30, 0x63, 0x0d, 0x4c, 0xee, 0x16, 0xdd, - 0x9c, 0x64, 0xcd, 0x9d, 0x4c, 0x72, 0xe6, 0xbb, 0x9f, 0x18, 0xe5, 0xc6, 0x31, 0xc5, 0x5e, 0xc7, 0x57, 0x35, 0x59, - 0x5d, 0xab, 0xe9, 0x2d, 0xae, 0x9c, 0x10, 0xb4, 0xce, 0xe2, 0x3e, 0xad, 0x5d, 0x62, 0x02, 0xd8, 0x0a, 0xec, 0x4e, - 0x55, 0x24, 0x15, 0xf4, 0xa1, 0x31, 0xcc, 0x1d, 0x0c, 0x27, 0xb6, 0xa1, 0x92, 0xb5, 0x1c, 0x1d, 0xc4, 0xb6, 0x7f, - 0x1f, 0xe4, 0x0c, 0xe8, 0xf8, 0xed, 0x64, 0x4c, 0x85, 0x40, 0xcd, 0x22, 0xad, 0x2e, 0x43, 0xba, 0x14, 0xe2, 0x5a, - 0x59, 0x5e, 0x08, 0x92, 0xbc, 0x4f, 0xcc, 0x25, 0xca, 0xdb, 0x61, 0xea, 0x35, 0xac, 0xcb, 0x0e, 0x48, 0xa3, 0x17, - 0xaa, 0xf2, 0x1b, 0x16, 0xe1, 0x48, 0x13, 0x26, 0x6b, 0x67, 0x20, 0xe6, 0x35, 0x6a, 0x33, 0x45, 0xc6, 0xaa, 0x03, - 0x47, 0xa0, 0x1c, 0x9d, 0x97, 0x8d, 0xf5, 0x53, 0xb3, 0x46, 0x6f, 0x28, 0x0c, 0x6c, 0xcf, 0x73, 0x49, 0x19, 0x48, - 0x63, 0x2c, 0x84, 0x1b, 0x93, 0x4e, 0x15, 0xd4, 0x03, 0xd9, 0xb3, 0xbe, 0xc0, 0x78, 0x96, 0x98, 0xf0, 0x9d, 0x03, - 0x8e, 0xe7, 0xcb, 0x48, 0x2f, 0x5d, 0x13, 0xad, 0x68, 0x65, 0x21, 0xfe, 0xec, 0x64, 0xd6, 0x96, 0xb9, 0x0e, 0x7c, - 0x05, 0xa0, 0x3a, 0x99, 0x0a, 0x2a, 0x51, 0x25, 0x95, 0x50, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x6a, 0xac, 0xbc, 0x71, - 0xef, 0x46, 0x86, 0x3f, 0x7b, 0x03, 0x4b, 0xeb, 0xae, 0xf0, 0xc1, 0xd9, 0x5f, 0x65, 0x90, 0x22, 0xed, 0x99, 0xb1, - 0x1b, 0x1b, 0xf3, 0xcc, 0x91, 0xd7, 0xd7, 0x8e, 0x89, 0xff, 0x5d, 0xb8, 0x63, 0x92, 0xdd, 0x7b, 0x14, 0x32, 0xb6, - 0xe5, 0x80, 0xa8, 0xdb, 0x3a, 0x0e, 0x47, 0x6a, 0xf8, 0x93, 0x9c, 0xe2, 0x3f, 0xae, 0x82, 0xa8, 0x5d, 0x69, 0x21, - 0xf9, 0x48, 0xcf, 0x21, 0x6b, 0x30, 0x9a, 0x34, 0x26, 0x30, 0xde, 0x03, 0xa3, 0x4c, 0x88, 0x89, 0x18, 0xdd, 0x84, - 0x09, 0x67, 0x9e, 0x01, 0xfe, 0xd2, 0x94, 0x85, 0x6d, 0x11, 0xb0, 0xdb, 0xc5, 0x6c, 0x2f, 0x3a, 0x4c, 0x18, 0xe4, - 0xdd, 0xe5, 0x0b, 0xf9, 0x47, 0xe2, 0x61, 0x73, 0xd9, 0xdf, 0xf2, 0x52, 0x44, 0x89, 0x2a, 0x42, 0x98, 0x06, 0x09, - 0x0d, 0x75, 0x56, 0x14, 0x69, 0xcc, 0x10, 0x6b, 0x98, 0xe3, 0x27, 0x1b, 0x45, 0x48, 0x85, 0x50, 0x28, 0x02, 0xd1, - 0x19, 0x22, 0x8c, 0x9c, 0x27, 0x0c, 0xf0, 0xae, 0x01, 0xd0, 0x12, 0xb4, 0x63, 0xc8, 0x96, 0x5b, 0x27, 0x84, 0x16, - 0x73, 0x89, 0xdf, 0xe7, 0x52, 0xca, 0x52, 0x7d, 0xad, 0x2e, 0x0b, 0xee, 0x25, 0x57, 0x2a, 0x6e, 0xa0, 0xe8, 0x28, - 0x9e, 0x86, 0x0f, 0x4c, 0x4d, 0x1f, 0xa5, 0x53, 0x1b, 0x6b, 0x9a, 0x27, 0xce, 0x39, 0xb2, 0x1f, 0xa8, 0xbb, 0xb9, - 0x3b, 0x41, 0xdc, 0xa9, 0x2a, 0xa1, 0x2c, 0xc3, 0x4d, 0xb7, 0x4c, 0x97, 0x92, 0x1a, 0x2e, 0xda, 0x92, 0xfc, 0xb6, - 0x29, 0x3e, 0x78, 0xc3, 0xf1, 0xe9, 0x7d, 0xc1, 0xec, 0x36, 0x3f, 0x7e, 0x32, 0x37, 0x02, 0xb3, 0xe0, 0xd1, 0xcd, - 0xc3, 0x1b, 0x36, 0x50, 0xc0, 0x8e, 0x04, 0x86, 0xae, 0x78, 0xa3, 0x35, 0xf1, 0x48, 0x63, 0x3d, 0x38, 0x78, 0x4f, - 0x79, 0x18, 0xb7, 0xa4, 0x8b, 0xac, 0xeb, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0x87, 0xa7, 0xa7, 0x93, 0x3e, 0x69, 0x53, - 0x54, 0x5c, 0x91, 0xce, 0xcd, 0x47, 0x7f, 0x11, 0x2c, 0xcc, 0x63, 0xec, 0x9c, 0xc9, 0x38, 0x47, 0x67, 0xcc, 0xc6, - 0xc1, 0x0e, 0xc6, 0x8b, 0x7d, 0xcb, 0xef, 0x14, 0xc9, 0x2f, 0x65, 0x05, 0x68, 0x44, 0x21, 0xa8, 0xd3, 0x6e, 0x51, - 0x28, 0x81, 0x43, 0xff, 0xab, 0xac, 0xed, 0x7b, 0xe4, 0xe7, 0xb2, 0x8b, 0x25, 0x82, 0xd8, 0x8d, 0xcd, 0xea, 0x5c, - 0xdc, 0xad, 0x46, 0x36, 0xad, 0x5b, 0x48, 0xa8, 0x3f, 0xcc, 0xcc, 0xb3, 0x67, 0x7e, 0x35, 0x22, 0x78, 0x93, 0x6f, - 0x86, 0xf5, 0xcd, 0x98, 0xeb, 0xbf, 0x4a, 0xfa, 0x73, 0x25, 0x31, 0x8e, 0xdf, 0xc8, 0x80, 0xac, 0x39, 0x90, 0x05, - 0xa5, 0xe2, 0x56, 0x3e, 0xca, 0xe3, 0x3d, 0x7e, 0x14, 0x28, 0xa2, 0xc9, 0x94, 0x51, 0x72, 0x2d, 0x14, 0xf9, 0xc8, - 0xdb, 0xb3, 0xbb, 0x37, 0x9e, 0x8e, 0x1a, 0x2f, 0x37, 0x7f, 0xa0, 0xb7, 0x65, 0xab, 0x1b, 0x3f, 0x98, 0xbd, 0x2d, - 0xff, 0xf9, 0x88, 0x3a, 0x5d, 0x17, 0x19, 0xcf, 0x43, 0xbd, 0x85, 0x6c, 0x1a, 0xa9, 0x16, 0xdd, 0x46, 0x40, 0x37, - 0xe2, 0x98, 0x77, 0xdc, 0x6d, 0xc0, 0x17, 0xc0, 0xbb, 0x84, 0x81, 0x78, 0xff, 0xa0, 0xe7, 0xa6, 0xc9, 0xcb, 0xb3, - 0x29, 0x17, 0x77, 0x5e, 0xd9, 0xed, 0x1e, 0x80, 0xce, 0x4f, 0xab, 0x7f, 0xbc, 0xcf, 0xe1, 0x17, 0x3f, 0xf9, 0x67, - 0x95, 0x50, 0x41, 0xba, 0x6f, 0x8c, 0xab, 0xbc, 0x9c, 0xf5, 0xee, 0x7e, 0xd6, 0x6e, 0xbb, 0xe3, 0x49, 0x0d, 0xed, - 0xbf, 0x92, 0xef, 0x8a, 0x74, 0x1b, 0x65, 0xfc, 0x4b, 0xb0, 0xf8, 0x92, 0x85, 0xde, 0x0f, 0x40, 0xdc, 0x14, 0x69, - 0x0f, 0xe9, 0x6a, 0xc6, 0x0f, 0xe3, 0xdd, 0x68, 0xc7, 0xad, 0xab, 0x5d, 0x12, 0x2e, 0x6a, 0xc4, 0xfd, 0xbc, 0x76, - 0x33, 0xd7, 0x7b, 0x4c, 0xab, 0x69, 0x97, 0x7f, 0xe6, 0x20, 0xbc, 0xb4, 0x90, 0xb2, 0x36, 0xbd, 0xb6, 0x45, 0xe9, - 0x5a, 0x60, 0xf9, 0xcb, 0x59, 0x9b, 0x6e, 0x55, 0x68, 0xda, 0xa5, 0xca, 0xd7, 0xf8, 0x37, 0x4e, 0xc5, 0x2e, 0xe7, - 0x8f, 0xfe, 0x73, 0xf2, 0xf6, 0xf0, 0xd7, 0x92, 0x77, 0xcc, 0x45, 0x6e, 0xce, 0xdc, 0xdf, 0xc2, 0x15, 0x59, 0x16, - 0x17, 0xf9, 0xfc, 0xff, 0x95, 0x7b, 0xfc, 0xd7, 0xe1, 0xf9, 0xb9, 0x26, 0x64, 0x76, 0x54, 0xf3, 0x4a, 0x6a, 0x5e, - 0xfe, 0xdf, 0xe7, 0xc5, 0xd3, 0xab, 0x07, 0xa4, 0xc1, 0xf0, 0x8d, 0xd9, 0x66, 0x96, 0x95, 0xd1, 0xc2, 0x21, 0x1e, - 0xc3, 0xfb, 0x26, 0xaf, 0x41, 0x90, 0x37, 0x5d, 0x96, 0xd3, 0xe0, 0x6e, 0x2a, 0xc9, 0xec, 0x4a, 0x39, 0x2c, 0x6e, - 0xfd, 0x78, 0x59, 0x96, 0xcd, 0x65, 0x4f, 0xf3, 0x4d, 0xed, 0x85, 0xfc, 0xd3, 0x97, 0x54, 0xba, 0x04, 0xe7, 0x8f, - 0x7c, 0xbc, 0x5c, 0xfc, 0x9c, 0x8d, 0xcb, 0x8f, 0x09, 0x21, 0x0e, 0x69, 0x22, 0x4d, 0x03, 0xda, 0x31, 0x98, 0x0f, - 0x71, 0x6e, 0xb6, 0x39, 0xcc, 0x0d, 0xdf, 0xe3, 0x05, 0x60, 0x67, 0x1e, 0x5f, 0xd5, 0x8b, 0x81, 0x38, 0x1d, 0x87, - 0x40, 0x8e, 0x47, 0xff, 0xb7, 0x8e, 0x7e, 0xe8, 0x22, 0xbd, 0xc8, 0x2d, 0xdf, 0xba, 0x87, 0x95, 0xe6, 0xc6, 0xd1, - 0x68, 0xe4, 0x88, 0x6d, 0x76, 0x17, 0x81, 0x8f, 0xb1, 0xe8, 0xe4, 0xe0, 0x2d, 0xe2, 0xa5, 0x7e, 0x97, 0x98, 0x07, - 0x57, 0xf9, 0x77, 0x62, 0xf1, 0xa5, 0x38, 0xde, 0xdd, 0x3b, 0x02, 0xe0, 0xf5, 0xc4, 0x2b, 0x07, 0xa7, 0x65, 0x38, - 0x85, 0xa4, 0x4e, 0x54, 0xd6, 0x4a, 0x75, 0xcf, 0xbe, 0x8f, 0x17, 0x93, 0x08, 0xbc, 0x3f, 0xde, 0xf7, 0x09, 0x3b, - 0x5d, 0xa4, 0xe7, 0x78, 0xaf, 0x8c, 0x40, 0x80, 0x22, 0x0a, 0x90, 0x06, 0xf9, 0xa8, 0x6e, 0x91, 0xbf, 0xc0, 0x50, - 0xdf, 0x39, 0x5c, 0x7d, 0xae, 0x28, 0x90, 0x1e, 0xae, 0xd6, 0xc5, 0x7d, 0x0a, 0x50, 0x12, 0xdb, 0x84, 0x80, 0xed, - 0x3f, 0xbd, 0x6f, 0x07, 0xb6, 0xde, 0xa4, 0x5d, 0xcf, 0x20, 0x77, 0x6a, 0x62, 0xf7, 0x19, 0x46, 0xc6, 0x0b, 0xcf, - 0x0b, 0x9d, 0xf0, 0x28, 0xc7, 0x44, 0xaf, 0xa8, 0xac, 0xac, 0xe3, 0xce, 0x7c, 0xb0, 0xb2, 0xff, 0x5c, 0x42, 0x21, - 0x4c, 0x37, 0xe9, 0xcb, 0x2a, 0xa1, 0x4a, 0xf3, 0x0a, 0x6e, 0x65, 0x4c, 0x46, 0x2f, 0xa1, 0xce, 0xf8, 0x5d, 0x53, - 0x64, 0x8a, 0xb1, 0x0c, 0x98, 0xe9, 0x6f, 0xa6, 0x9c, 0x09, 0x00, 0xce, 0xe2, 0x32, 0x80, 0x04, 0xaa, 0xbe, 0xaa, - 0x95, 0x6f, 0x69, 0xc6, 0x29, 0x59, 0x47, 0xd9, 0x79, 0xae, 0x95, 0x52, 0x1e, 0x5f, 0x36, 0xb0, 0xe1, 0x4c, 0xc3, - 0x82, 0x2b, 0xf9, 0x64, 0xbb, 0x2f, 0x57, 0x73, 0x5d, 0xd6, 0xc3, 0x09, 0x30, 0xfb, 0xfd, 0x00, 0xfa, 0x96, 0x72, - 0xc5, 0x46, 0xd9, 0xcb, 0x3f, 0xf4, 0x06, 0x6b, 0xd0, 0xf0, 0xa1, 0x87, 0x29, 0x37, 0xbe, 0x50, 0xd4, 0x7f, 0x08, - 0x9c, 0x15, 0x23, 0x97, 0x6a, 0x4d, 0xa1, 0x97, 0x18, 0xa1, 0x9f, 0x65, 0x50, 0xb5, 0x7a, 0x63, 0x2a, 0x2a, 0x95, - 0xaf, 0xef, 0xb9, 0xc3, 0x95, 0xe5, 0xc0, 0x9d, 0xf9, 0xe4, 0x14, 0x90, 0x02, 0x44, 0x41, 0xac, 0x54, 0x7e, 0x1e, - 0x66, 0x9b, 0x90, 0xca, 0x20, 0x99, 0xbe, 0x50, 0x64, 0xdd, 0x37, 0xfa, 0x0b, 0x2b, 0xb6, 0xea, 0x25, 0x74, 0x0f, - 0x76, 0x78, 0xcf, 0x7d, 0x9b, 0xf7, 0x67, 0xcb, 0x59, 0xf5, 0xb4, 0xf4, 0xd6, 0x73, 0xb7, 0x6b, 0xe0, 0x52, 0xe7, - 0x00, 0x20, 0x2d, 0x97, 0x3a, 0x7f, 0xdf, 0xc4, 0xdd, 0xac, 0x36, 0x7e, 0x76, 0x51, 0x46, 0x47, 0x8f, 0x5b, 0xe9, - 0xe9, 0x91, 0x75, 0x61, 0x95, 0x74, 0x78, 0xdf, 0x44, 0xe0, 0xcb, 0x1f, 0xc3, 0xb0, 0x7a, 0x61, 0x7a, 0x6e, 0x50, - 0x9c, 0x09, 0x9b, 0x93, 0x7d, 0xf6, 0xce, 0xcd, 0x5b, 0x0d, 0x1f, 0xa2, 0x37, 0xe1, 0x73, 0x87, 0x7d, 0x2e, 0x02, - 0xe8, 0x36, 0x6b, 0x7e, 0xc6, 0x41, 0xd1, 0x2a, 0x54, 0x8b, 0x97, 0x25, 0xb0, 0x29, 0x59, 0xee, 0xe7, 0x78, 0x11, - 0x6c, 0x0a, 0xed, 0x8b, 0x20, 0x2f, 0x67, 0x54, 0xa1, 0x17, 0xd2, 0xbb, 0x0a, 0x5c, 0xb9, 0x15, 0x7c, 0x7f, 0xc5, - 0x60, 0x75, 0xd5, 0xb6, 0x14, 0x1f, 0xce, 0x18, 0xfd, 0xae, 0x02, 0xe6, 0xab, 0xaf, 0x98, 0xd9, 0xd0, 0xa7, 0x3d, - 0x0f, 0xab, 0xfb, 0xfe, 0xb5, 0xe5, 0x0b, 0x82, 0xef, 0xdf, 0x4c, 0x4d, 0xbb, 0x38, 0x9c, 0x12, 0x1b, 0x81, 0xb9, - 0x47, 0x88, 0xc3, 0x10, 0x69, 0x50, 0x77, 0x90, 0x6f, 0xef, 0x96, 0x24, 0x21, 0x4f, 0xd6, 0xbf, 0x78, 0xfc, 0xee, - 0x4c, 0x7a, 0x22, 0xbd, 0xf8, 0xe1, 0xe3, 0x75, 0x22, 0x2c, 0xdb, 0x0b, 0x35, 0xd9, 0xc1, 0xe3, 0x94, 0x5b, 0x79, - 0x80, 0x66, 0x0d, 0x5d, 0x74, 0xdb, 0x87, 0x74, 0x5c, 0x9c, 0x5f, 0x63, 0xe8, 0xfb, 0x06, 0xde, 0xcd, 0x0c, 0x0d, - 0x79, 0xcf, 0xd8, 0x5d, 0xf5, 0x81, 0x0a, 0x2b, 0xc9, 0x4b, 0xb9, 0x57, 0xf6, 0x5c, 0x74, 0xb5, 0x61, 0xe2, 0x1c, - 0x50, 0x7f, 0xb3, 0xcf, 0xcb, 0xae, 0x8a, 0x0f, 0xf8, 0x7a, 0xa5, 0x81, 0xaf, 0xeb, 0x0c, 0x35, 0x02, 0x3a, 0x48, - 0x91, 0x25, 0xe0, 0x33, 0xcc, 0xa8, 0x49, 0x38, 0xcd, 0xf4, 0x96, 0xf2, 0x3c, 0xca, 0x60, 0x51, 0x53, 0xba, 0xd0, - 0xe5, 0xdb, 0xae, 0x16, 0x73, 0x7a, 0x17, 0x13, 0xed, 0x52, 0xf3, 0xde, 0x7e, 0x00, 0x70, 0xb5, 0xdb, 0x90, 0x70, - 0x91, 0x7e, 0x14, 0xf7, 0xad, 0xf3, 0x63, 0xea, 0xeb, 0xe2, 0xe2, 0x11, 0x64, 0x2a, 0x98, 0x04, 0xb9, 0xe9, 0x73, - 0xfd, 0x17, 0x34, 0x31, 0x21, 0x3f, 0xf9, 0xb3, 0x04, 0x5f, 0xda, 0xb5, 0x5d, 0x0c, 0xc1, 0x47, 0x6a, 0x8d, 0xde, - 0x2d, 0x05, 0x64, 0x61, 0x3f, 0xec, 0x3d, 0xd7, 0x14, 0x64, 0xc7, 0x21, 0x69, 0x00, 0x7d, 0xdf, 0xa4, 0xe3, 0x17, - 0x16, 0xc6, 0x22, 0x91, 0x9a, 0xde, 0xc2, 0x76, 0x99, 0x6c, 0xa7, 0xaf, 0x6e, 0x6f, 0x19, 0x5f, 0x5d, 0xec, 0x7a, - 0x0a, 0xeb, 0x06, 0xb0, 0xc3, 0x46, 0x1b, 0x6f, 0xba, 0x80, 0xc3, 0x6d, 0x76, 0xc6, 0x94, 0x7a, 0x57, 0xdc, 0x24, - 0x0e, 0x03, 0xc1, 0x10, 0xf5, 0x22, 0x99, 0x45, 0xf9, 0x3d, 0xf5, 0x26, 0x1c, 0xf5, 0x90, 0xf6, 0x0f, 0x6e, 0xbe, - 0xff, 0x8f, 0x2a, 0x3d, 0x38, 0x1b, 0x06, 0x7e, 0xb2, 0x7b, 0x40, 0xf2, 0xd4, 0x54, 0xf4, 0x80, 0x26, 0x5b, 0x9e, - 0x04, 0xe2, 0xa6, 0x73, 0xed, 0xc3, 0xfe, 0x31, 0xe5, 0x1b, 0x02, 0x6a, 0x9e, 0x18, 0xa1, 0xda, 0x7a, 0xe4, 0x2f, - 0x6b, 0xa5, 0x37, 0xd6, 0x10, 0xcf, 0xaf, 0x08, 0xde, 0xaf, 0x5e, 0x1c, 0x7e, 0x2d, 0x69, 0xa0, 0xdc, 0x2e, 0x67, - 0xe9, 0xbf, 0xeb, 0x0a, 0x17, 0x02, 0x0f, 0xc9, 0xa7, 0x11, 0x92, 0x2b, 0x0b, 0x7c, 0xfc, 0xe2, 0x50, 0xe7, 0xd3, - 0xf7, 0xba, 0xf1, 0x59, 0xdd, 0x10, 0x85, 0x9c, 0x1f, 0xa0, 0xaa, 0x0d, 0x31, 0x46, 0x08, 0x17, 0x7c, 0xf4, 0xd1, - 0x65, 0x59, 0xa3, 0x25, 0x20, 0xed, 0xca, 0xe5, 0x8f, 0x17, 0x06, 0x5e, 0x2b, 0x7e, 0xcb, 0x61, 0x5e, 0xa6, 0x43, - 0x7c, 0xa5, 0xb1, 0x7d, 0x2d, 0x1d, 0x32, 0xd7, 0xd1, 0xa8, 0x08, 0x55, 0x15, 0xa9, 0xe7, 0xe2, 0xa3, 0xf5, 0xbb, - 0x6e, 0xe4, 0x33, 0x83, 0xc5, 0xa5, 0x65, 0x63, 0xc7, 0x49, 0x75, 0xc9, 0x33, 0x3c, 0x40, 0x67, 0xb0, 0xcf, 0xd9, - 0x76, 0xf1, 0x67, 0x95, 0xac, 0xe1, 0x00, 0x23, 0xb0, 0x07, 0x43, 0xae, 0x4a, 0x12, 0x64, 0x30, 0x36, 0x25, 0x97, - 0xa1, 0xe4, 0x7d, 0xbd, 0xb1, 0x59, 0x8e, 0xf2, 0xa0, 0xd0, 0x91, 0xe1, 0x8a, 0xff, 0xa9, 0xb7, 0x8a, 0x34, 0xbd, - 0xfc, 0xdc, 0x38, 0x5b, 0xe7, 0x74, 0xb3, 0x3b, 0xb2, 0xc3, 0x87, 0x51, 0x6e, 0x21, 0x4e, 0xa6, 0x79, 0x18, 0x09, - 0xac, 0x64, 0x6e, 0x9e, 0x0e, 0x80, 0xf8, 0x26, 0x33, 0x5a, 0xb7, 0xe4, 0x7f, 0xf2, 0xb5, 0xae, 0x23, 0x44, 0xb4, - 0xb1, 0xbe, 0xab, 0xe8, 0x0c, 0x12, 0x27, 0xb9, 0x41, 0x31, 0x9e, 0xaa, 0x98, 0x31, 0xc8, 0x96, 0xaa, 0x4e, 0xf2, - 0xfb, 0x4f, 0xbe, 0x4b, 0xa1, 0x37, 0xbd, 0x3d, 0x37, 0xeb, 0xb6, 0x93, 0xe5, 0x88, 0x1a, 0x29, 0x33, 0xbb, 0x31, - 0xe8, 0xa6, 0xa0, 0x10, 0x29, 0x29, 0xcf, 0x14, 0xe9, 0x18, 0x0e, 0xf7, 0xda, 0x1f, 0xe1, 0x89, 0xed, 0x58, 0xc2, - 0xda, 0x66, 0x81, 0x47, 0x80, 0xc0, 0x47, 0xfd, 0x16, 0x41, 0x34, 0xd5, 0x15, 0x15, 0x6a, 0x79, 0x63, 0x77, 0x76, - 0x74, 0x7b, 0x5a, 0x5b, 0xd0, 0x3e, 0x83, 0x3f, 0x15, 0x14, 0xdc, 0x76, 0xad, 0xe7, 0x64, 0x64, 0x45, 0xea, 0x42, - 0x30, 0x02, 0x32, 0xeb, 0x9f, 0x21, 0xe3, 0x53, 0x13, 0xa2, 0xee, 0x2f, 0x1b, 0x43, 0x8e, 0x84, 0x40, 0x80, 0xf0, - 0xb2, 0x7c, 0x96, 0xf0, 0x49, 0xa0, 0x08, 0x50, 0xf5, 0xb8, 0xf4, 0xca, 0x72, 0xa9, 0xd1, 0xf0, 0xa8, 0xd5, 0x80, - 0x6d, 0xbb, 0x40, 0xed, 0x80, 0x05, 0xd6, 0x4e, 0x61, 0x9d, 0x13, 0x52, 0x75, 0x29, 0x16, 0xdd, 0xaa, 0x2e, 0x52, - 0x9e, 0xcd, 0xeb, 0x4c, 0x11, 0x36, 0xad, 0x7f, 0xad, 0x7c, 0x99, 0x80, 0x68, 0x9b, 0xbf, 0x04, 0x6e, 0x8e, 0xcd, - 0xfe, 0x8f, 0x36, 0x13, 0xd3, 0x3a, 0xf5, 0x2a, 0x02, 0x94, 0x9d, 0x2a, 0xf1, 0x1a, 0x65, 0x0c, 0x4a, 0x50, 0xe7, - 0xc7, 0x5e, 0xa2, 0x82, 0x5c, 0x25, 0x7d, 0x31, 0x50, 0x80, 0x30, 0x5e, 0x3a, 0xe2, 0xa5, 0xab, 0xbc, 0xd8, 0x56, - 0xeb, 0x9c, 0x60, 0xec, 0xcd, 0xec, 0x05, 0xa4, 0x3e, 0x5d, 0xee, 0x24, 0x47, 0xd3, 0xc5, 0xb5, 0xcb, 0xab, 0x78, - 0xc8, 0x74, 0x59, 0x7c, 0x4c, 0x83, 0xa7, 0x2a, 0xe7, 0x89, 0x15, 0xc2, 0xff, 0xb6, 0x8c, 0x1b, 0xaf, 0x94, 0x69, - 0x81, 0x10, 0x6b, 0x49, 0x14, 0x38, 0xdf, 0x0c, 0x92, 0x87, 0xe5, 0x51, 0x69, 0x9a, 0xc7, 0xfe, 0xda, 0xd0, 0xec, - 0x49, 0xf6, 0x40, 0x92, 0x0f, 0xdb, 0xbe, 0x4b, 0x82, 0xb9, 0xef, 0x27, 0x1d, 0xc3, 0x44, 0x61, 0x1f, 0x34, 0xe4, - 0x71, 0xd5, 0x02, 0x08, 0x46, 0xee, 0x57, 0x5f, 0xcb, 0xdd, 0xb6, 0xed, 0x36, 0x08, 0x3e, 0xc7, 0x42, 0xc4, 0x5f, - 0x0c, 0x49, 0xf0, 0xed, 0xd5, 0x0b, 0x2a, 0x17, 0xab, 0x75, 0xc8, 0xbc, 0x3c, 0x25, 0xd9, 0xce, 0x93, 0xae, 0xef, - 0x9e, 0xf7, 0xfc, 0x8a, 0x88, 0xd3, 0x15, 0xcd, 0x4c, 0x9c, 0x23, 0xe9, 0xa8, 0xc4, 0x0b, 0xee, 0x0e, 0xea, 0xec, - 0xfd, 0x9c, 0xe2, 0x14, 0x93, 0xe6, 0x16, 0x15, 0x42, 0x17, 0x12, 0xba, 0xd6, 0xb9, 0x7c, 0x5d, 0x58, 0xbb, 0x79, - 0xa2, 0xf4, 0xfe, 0xa5, 0x99, 0x51, 0x54, 0xea, 0xe7, 0x62, 0x09, 0x24, 0x13, 0x72, 0xa2, 0xdf, 0xd8, 0xea, 0xa4, - 0xbb, 0x87, 0x6f, 0x6a, 0xa3, 0xc5, 0x3c, 0x88, 0x73, 0xc0, 0xca, 0x97, 0x61, 0x6f, 0x1b, 0x93, 0xe2, 0xf6, 0xd7, - 0x25, 0x64, 0xb5, 0xdd, 0x1f, 0x4a, 0x7f, 0xce, 0x05, 0x2e, 0xd1, 0x98, 0x18, 0x31, 0xc3, 0x2f, 0x44, 0x5a, 0xa3, - 0x44, 0xce, 0x3d, 0xce, 0x6d, 0x42, 0xfe, 0x2b, 0x53, 0x6f, 0xa4, 0xbb, 0x42, 0xc8, 0xff, 0xf3, 0x3c, 0xe2, 0x8e, - 0xe9, 0xe6, 0xde, 0xde, 0xc9, 0x30, 0x72, 0x0e, 0xcc, 0xda, 0x6e, 0xca, 0x2c, 0xdc, 0x45, 0x7a, 0x8b, 0x19, 0xd3, - 0xec, 0x10, 0xbc, 0x0c, 0x9d, 0x74, 0x52, 0x7c, 0xea, 0x00, 0xa1, 0xea, 0x08, 0x60, 0x4a, 0x16, 0xfa, 0x17, 0x28, - 0x5d, 0xbd, 0x58, 0xa6, 0x96, 0x4a, 0xcd, 0x75, 0x27, 0x16, 0x3f, 0xa1, 0xc0, 0x20, 0x7e, 0x71, 0xab, 0x35, 0x9d, - 0x1d, 0x52, 0x44, 0xa2, 0x27, 0xfd, 0x18, 0x1e, 0x63, 0xe5, 0x31, 0xeb, 0xa1, 0x50, 0x13, 0x5c, 0xef, 0x64, 0xd5, - 0xb3, 0x92, 0x20, 0x8d, 0x74, 0x0f, 0xb0, 0x37, 0x4f, 0xed, 0x51, 0xa2, 0x15, 0x02, 0x2f, 0x91, 0xc6, 0x0c, 0x89, - 0xf6, 0x21, 0xf6, 0x90, 0x98, 0x00, 0x6f, 0x0a, 0x26, 0xd8, 0x52, 0x68, 0x3b, 0x07, 0xce, 0x3b, 0x0a, 0x58, 0x9b, - 0x6b, 0xd4, 0x60, 0xe6, 0x91, 0x23, 0x26, 0xe2, 0x38, 0xfb, 0x5d, 0xd4, 0x21, 0x81, 0xe4, 0x10, 0xed, 0x9c, 0x6a, - 0x1a, 0xb4, 0x38, 0x73, 0x5e, 0x23, 0x57, 0x08, 0xc7, 0xa7, 0xa0, 0x8c, 0x23, 0xd8, 0x70, 0x7d, 0xcc, 0x25, 0xeb, - 0xb2, 0x22, 0x0a, 0x9b, 0x3b, 0x4b, 0xde, 0xaf, 0xe3, 0xf7, 0xa6, 0xb0, 0x92, 0x65, 0xe1, 0x9b, 0xa6, 0xd4, 0x33, - 0xe5, 0x73, 0x2f, 0xac, 0x4a, 0x7a, 0x76, 0x00, 0xf7, 0x88, 0xff, 0xc1, 0xe5, 0x66, 0xe4, 0xa7, 0x94, 0x82, 0x1a, - 0xf0, 0x47, 0x13, 0xda, 0x95, 0x0a, 0x8a, 0xc5, 0xc0, 0x48, 0xd3, 0x69, 0x5b, 0xa8, 0x97, 0x1a, 0x36, 0x30, 0xcc, - 0x63, 0xb2, 0x50, 0xe8, 0xd4, 0xfe, 0x86, 0xe7, 0xf3, 0x88, 0x46, 0xde, 0x4c, 0x1b, 0x64, 0xf9, 0x1d, 0xba, 0xd7, - 0x2a, 0x27, 0xf3, 0x6d, 0x05, 0x10, 0x3f, 0xf3, 0xb2, 0x60, 0x34, 0x54, 0x34, 0x29, 0x66, 0x30, 0x5c, 0x9a, 0x3f, - 0x71, 0x15, 0xa0, 0xc7, 0xf4, 0xd5, 0xda, 0xa2, 0x3a, 0xef, 0x40, 0xc4, 0x74, 0x1f, 0x94, 0x2a, 0x52, 0x5f, 0xe9, - 0x66, 0xab, 0xe3, 0x1c, 0xfc, 0xb1, 0xaa, 0xae, 0x20, 0xd1, 0x6e, 0x79, 0x34, 0xa6, 0xd1, 0xb1, 0x2f, 0x0e, 0xd9, - 0xb1, 0xc7, 0xf3, 0x0e, 0x45, 0xc8, 0xfd, 0xd9, 0x37, 0xa6, 0xf8, 0x24, 0x23, 0x69, 0x04, 0xfa, 0x0a, 0x84, 0xab, - 0x7e, 0xee, 0xae, 0xa8, 0xb0, 0xd5, 0xc8, 0x66, 0x41, 0x19, 0x86, 0xa8, 0xa6, 0xa7, 0x68, 0x1c, 0x78, 0x56, 0x90, - 0x88, 0x09, 0x01, 0x4a, 0xd8, 0xb5, 0x44, 0x0f, 0xfd, 0x1f, 0x66, 0x56, 0xbf, 0xf2, 0x86, 0xad, 0x4c, 0xeb, 0x00, - 0x52, 0x04, 0x84, 0x54, 0xca, 0xd5, 0xfd, 0x83, 0xb9, 0x70, 0x3c, 0x4a, 0x4c, 0x26, 0x3f, 0xcf, 0x3e, 0x80, 0x37, - 0x33, 0xbd, 0x3c, 0xf2, 0x13, 0x69, 0x62, 0x93, 0x7a, 0x4c, 0x6b, 0xa4, 0x76, 0xbb, 0x03, 0x5c, 0xad, 0xd2, 0x0b, - 0x53, 0xff, 0xa2, 0x08, 0x46, 0xff, 0x4a, 0x07, 0x69, 0xdd, 0xcb, 0x9c, 0x4b, 0xb0, 0x29, 0x7a, 0xdb, 0x06, 0x30, - 0xed, 0xdb, 0x52, 0x75, 0x23, 0x41, 0x8a, 0x6d, 0x53, 0xf8, 0xee, 0xf0, 0x12, 0x11, 0x8b, 0x33, 0x16, 0xab, 0xd5, - 0x1d, 0x2d, 0xe6, 0xc1, 0xf7, 0x53, 0x47, 0x10, 0xf6, 0xaf, 0xb0, 0x09, 0x6c, 0x3c, 0x40, 0x16, 0x7b, 0x90, 0x8e, - 0x58, 0xa9, 0xa6, 0x39, 0x8f, 0x56, 0x81, 0x95, 0xaa, 0x2c, 0xde, 0xc7, 0x95, 0xb4, 0xfb, 0x5a, 0x26, 0x0e, 0xa8, - 0xce, 0x21, 0xfc, 0xd6, 0xa2, 0x6f, 0x25, 0x64, 0x5e, 0xd7, 0x38, 0x02, 0xd4, 0x95, 0xb8, 0x12, 0x37, 0x0a, 0x92, - 0x91, 0x1f, 0x34, 0x93, 0x13, 0x74, 0x34, 0xf9, 0xf8, 0x81, 0x06, 0x1e, 0xba, 0xe7, 0x6f, 0xd4, 0x50, 0xec, 0xdb, - 0x55, 0x74, 0x28, 0xb4, 0x26, 0xd9, 0x7f, 0xf6, 0x9d, 0x69, 0xcd, 0x69, 0x46, 0x3d, 0x35, 0xc1, 0x9d, 0x7a, 0x5b, - 0x17, 0x5b, 0xa6, 0x71, 0xe4, 0x2e, 0xcc, 0x9c, 0xf1, 0xb5, 0xbd, 0x81, 0x38, 0xdf, 0x0b, 0x89, 0x9b, 0xe9, 0x88, - 0x29, 0xfd, 0xa4, 0x31, 0x02, 0x6a, 0x14, 0x1d, 0x6c, 0x64, 0xda, 0xb7, 0x02, 0x39, 0x9b, 0xa0, 0xa3, 0x2a, 0xa8, - 0xb6, 0x98, 0x99, 0xa5, 0x71, 0x6a, 0xa4, 0x05, 0x05, 0x2b, 0x8d, 0x41, 0x61, 0xa5, 0x2a, 0xc9, 0x5e, 0x94, 0x58, - 0x7a, 0x9e, 0xb3, 0xd0, 0xa1, 0x6c, 0x3a, 0x7c, 0x5a, 0x0b, 0x97, 0x84, 0xd1, 0xd6, 0xc2, 0x30, 0x6d, 0xb6, 0xd2, - 0xb6, 0xb2, 0xa2, 0x12, 0x2a, 0xb9, 0xbe, 0xa8, 0x24, 0x69, 0x1e, 0x61, 0x1c, 0x4f, 0x65, 0x76, 0x43, 0xf9, 0x0a, - 0x5b, 0xb7, 0xf1, 0xa1, 0xf0, 0x6f, 0x42, 0xc9, 0x6c, 0xc8, 0x80, 0x0c, 0x54, 0x12, 0xac, 0xe2, 0xf4, 0xf3, 0xe5, - 0x35, 0x67, 0x11, 0x97, 0x39, 0xf0, 0x6a, 0xea, 0xb5, 0x76, 0x1c, 0x4a, 0x7c, 0xed, 0xe4, 0x3f, 0xd3, 0xe4, 0xcf, - 0x12, 0x0e, 0xd7, 0xb9, 0xb2, 0xe2, 0x74, 0x58, 0xd0, 0x8f, 0xd8, 0xab, 0xcf, 0xd7, 0x4b, 0x62, 0xcb, 0xa3, 0x48, - 0xdd, 0x2b, 0x6d, 0xef, 0x3d, 0x1b, 0xa9, 0xd0, 0xac, 0xdd, 0x7d, 0xdf, 0x49, 0x5a, 0x65, 0x6a, 0xb5, 0x8b, 0x7b, - 0xd8, 0x40, 0x68, 0x6b, 0x52, 0x22, 0xee, 0xdd, 0xa4, 0x0c, 0x2f, 0x6d, 0x16, 0x40, 0xb5, 0x26, 0x14, 0xdf, 0x8d, - 0xeb, 0x44, 0xee, 0xc3, 0x33, 0x99, 0xbf, 0xdd, 0x7d, 0x30, 0xda, 0x0d, 0xec, 0x8a, 0xd0, 0x0f, 0xa2, 0x2d, 0x58, - 0x75, 0xe9, 0x8d, 0xba, 0xc0, 0x64, 0x51, 0xea, 0x60, 0xa4, 0x82, 0x2c, 0x5e, 0xb9, 0x03, 0xbb, 0x8e, 0x47, 0x10, - 0x40, 0x7f, 0xe3, 0xb8, 0xc5, 0x6d, 0x22, 0x15, 0xc1, 0x5d, 0x76, 0x9c, 0x54, 0x69, 0xbd, 0xcd, 0x8e, 0x63, 0xc1, - 0xd8, 0x52, 0xc8, 0xcc, 0x2a, 0x08, 0x5a, 0x09, 0xb4, 0xbe, 0x4a, 0x76, 0xba, 0x0c, 0xb3, 0x56, 0x14, 0xb0, 0x0f, - 0x2a, 0x39, 0xeb, 0x0f, 0x4a, 0x51, 0x5d, 0xc1, 0xf7, 0x71, 0x78, 0xfa, 0xdd, 0xc0, 0x01, 0x8b, 0xa1, 0x15, 0x82, - 0x23, 0xf6, 0x48, 0x87, 0x2d, 0xbd, 0xa9, 0x77, 0x7c, 0xae, 0xc2, 0x79, 0xf3, 0x58, 0xff, 0x07, 0xa9, 0x3e, 0xef, - 0xeb, 0x17, 0x38, 0xc1, 0x2f, 0x5e, 0x54, 0x8f, 0x77, 0xfc, 0xff, 0x06, 0x43, 0x54, 0x1d, 0xa6, 0xb6, 0xf8, 0x73, - 0x82, 0x74, 0x26, 0x0d, 0x7b, 0xb8, 0xbe, 0x92, 0x76, 0xbe, 0xa0, 0x1a, 0x7a, 0x64, 0x63, 0xb5, 0x1e, 0x94, 0x20, - 0x52, 0xde, 0xbb, 0x7d, 0x36, 0x2f, 0x25, 0xa5, 0x1a, 0xd1, 0x42, 0x4d, 0x7c, 0xb3, 0xe6, 0x4d, 0xb2, 0x16, 0x24, - 0xb1, 0xed, 0x59, 0x3b, 0xb2, 0x85, 0xf8, 0xfd, 0x5b, 0x8c, 0x26, 0x07, 0xf1, 0xde, 0xec, 0xba, 0x0c, 0xba, 0xd5, - 0xb3, 0xb4, 0x84, 0x55, 0x1b, 0xa8, 0x6a, 0xaa, 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0xf5, 0xeb, 0x4a, 0x3a, 0xa7, - 0xb4, 0x10, 0x6a, 0x19, 0xf7, 0x44, 0xb2, 0x88, 0xf8, 0x58, 0x05, 0x3f, 0x29, 0xcc, 0xa9, 0xbb, 0x68, 0x44, 0x16, - 0xa3, 0x57, 0x6e, 0xc3, 0x69, 0xab, 0xa5, 0x4a, 0x40, 0xac, 0xdf, 0xb5, 0x1a, 0x67, 0xb3, 0xc2, 0x89, 0xa1, 0xef, - 0xff, 0xc4, 0x55, 0xe1, 0x4b, 0x10, 0xc6, 0xf1, 0x99, 0x24, 0x4b, 0xf1, 0x19, 0xaf, 0x3c, 0xf0, 0x0e, 0xac, 0xe8, - 0x6e, 0x5f, 0xf1, 0xfb, 0x4f, 0x57, 0x61, 0x85, 0x66, 0x59, 0x51, 0x6e, 0x5d, 0x63, 0x49, 0xdd, 0x23, 0xc7, 0x79, - 0x71, 0x0f, 0x70, 0x26, 0x34, 0xa3, 0x22, 0x4c, 0x69, 0x24, 0x2d, 0x3f, 0x53, 0x5b, 0xb1, 0xf4, 0x09, 0xc5, 0x12, - 0x01, 0x32, 0xf8, 0xfe, 0x93, 0x44, 0x57, 0x1e, 0xeb, 0x00, 0xff, 0xa8, 0x58, 0xb9, 0x2c, 0x66, 0x85, 0x86, 0xba, - 0x00, 0xc9, 0xfa, 0xea, 0x4a, 0xd6, 0xec, 0x6c, 0x43, 0x04, 0x95, 0xba, 0xeb, 0x20, 0x40, 0x6c, 0xd7, 0x08, 0x7c, - 0xf9, 0xd7, 0x68, 0x58, 0x6f, 0x65, 0x41, 0x1d, 0x36, 0xd9, 0x05, 0x01, 0xd1, 0xbd, 0xe8, 0x97, 0x9e, 0x1b, 0xff, - 0xd8, 0xf8, 0x64, 0x63, 0xf9, 0xf0, 0x33, 0x72, 0x2d, 0xaa, 0x87, 0xcc, 0x16, 0x80, 0x98, 0x8d, 0x34, 0x1b, 0x27, - 0xba, 0x6a, 0xef, 0x7b, 0x8d, 0xb2, 0x4d, 0x86, 0xed, 0x12, 0xb3, 0x78, 0xb0, 0xa8, 0x31, 0x65, 0x64, 0x63, 0x8f, - 0x7b, 0xe5, 0xc1, 0x5d, 0xf6, 0x41, 0x04, 0x9d, 0xcb, 0x76, 0xcc, 0xb4, 0x76, 0x38, 0xaf, 0x1a, 0xbb, 0x42, 0x66, - 0x05, 0x9b, 0xc4, 0x41, 0x00, 0xd9, 0x65, 0xdd, 0x05, 0x53, 0xce, 0x69, 0x71, 0xc3, 0x62, 0x0f, 0x36, 0x50, 0x16, - 0x3a, 0xb0, 0x25, 0xd4, 0x50, 0x0a, 0xd3, 0x58, 0x7a, 0xe0, 0x6c, 0x05, 0xe6, 0x5a, 0x8f, 0x63, 0x5d, 0xb3, 0x4e, - 0xd1, 0xa5, 0x02, 0xd2, 0xe2, 0xe8, 0xf9, 0x4d, 0x1f, 0xd2, 0xbe, 0xdb, 0xda, 0xf0, 0xbd, 0x6e, 0xbc, 0x26, 0xc3, - 0x4a, 0x79, 0x12, 0xed, 0x55, 0xfd, 0xf6, 0x02, 0xa3, 0x5a, 0xf8, 0xcc, 0xe5, 0x4b, 0x25, 0xff, 0x6e, 0x0d, 0x03, - 0xcd, 0x17, 0x0a, 0x5f, 0xf5, 0x04, 0x32, 0x2d, 0x69, 0x51, 0xf0, 0xce, 0xf8, 0x69, 0xb3, 0x05, 0xe3, 0xfe, 0xcd, - 0x4d, 0xc5, 0xb8, 0xfe, 0xed, 0x4d, 0xd3, 0xaf, 0x86, 0xc0, 0x6f, 0x14, 0x24, 0xdd, 0x87, 0xed, 0x11, 0x04, 0x88, - 0x7b, 0xab, 0x5c, 0x36, 0xb9, 0x7e, 0xf3, 0xb8, 0xa1, 0xaf, 0x6e, 0xf9, 0xc7, 0x1d, 0xe0, 0x59, 0x92, 0x93, 0xad, - 0x2d, 0x8b, 0x47, 0xce, 0xec, 0xee, 0x65, 0x1c, 0xff, 0x00, 0x38, 0x85, 0xd5, 0xad, 0xfc, 0xe9, 0xfd, 0xcc, 0x9e, - 0x52, 0x73, 0xbd, 0xf5, 0xe7, 0xab, 0x5f, 0xb9, 0x6d, 0x1e, 0xab, 0x53, 0xc3, 0xc6, 0x4d, 0x63, 0x49, 0x66, 0x4b, - 0x30, 0x33, 0x07, 0x29, 0x9c, 0xaf, 0xd5, 0xe7, 0x8c, 0xa3, 0xb8, 0xce, 0x09, 0x23, 0x6c, 0x63, 0x90, 0x1f, 0xbf, - 0x24, 0x96, 0x92, 0xf9, 0xc7, 0xed, 0xca, 0x18, 0x26, 0x91, 0x6e, 0x4f, 0xbd, 0x97, 0xa9, 0xce, 0x29, 0xdb, 0x63, - 0x1e, 0x9b, 0xe0, 0x67, 0xd5, 0x23, 0xd0, 0x0a, 0xfc, 0x0b, 0x02, 0xb6, 0xbb, 0x2c, 0xb3, 0x07, 0x9a, 0x37, 0xff, - 0x03, 0x78, 0x23, 0x3a, 0x65, 0x61, 0x27, 0xbb, 0xbe, 0xf9, 0x5d, 0x87, 0xc3, 0x95, 0x61, 0x89, 0x1b, 0xc6, 0x30, - 0x60, 0x1c, 0xba, 0xb5, 0xb5, 0x27, 0xb5, 0x1b, 0x1c, 0xa4, 0x8a, 0xf7, 0x50, 0x8a, 0x75, 0x34, 0x2f, 0x2c, 0xff, - 0x28, 0x07, 0xca, 0x0a, 0x03, 0xf2, 0x60, 0xd8, 0xf9, 0x98, 0x35, 0x52, 0x0d, 0x5d, 0xba, 0x8e, 0x2b, 0xad, 0xb1, - 0x21, 0x1f, 0x33, 0xec, 0x7e, 0xef, 0x1c, 0x05, 0xed, 0xe9, 0x7a, 0xcb, 0x81, 0x33, 0xac, 0xbd, 0x2f, 0xe3, 0x3c, - 0xf5, 0x72, 0xc1, 0xce, 0xd4, 0xd0, 0x9f, 0xf7, 0x9b, 0xac, 0xa6, 0x60, 0xa3, 0x23, 0xa8, 0xd3, 0x4f, 0x2e, 0x4a, - 0x5c, 0x65, 0x46, 0xd6, 0xfd, 0x96, 0x54, 0x67, 0x82, 0x83, 0xac, 0x2b, 0x94, 0xdf, 0xc5, 0x99, 0xd0, 0x87, 0x26, - 0x35, 0x8b, 0x64, 0xe3, 0x7d, 0x94, 0x1e, 0x18, 0x22, 0x0b, 0x3d, 0x6e, 0xd6, 0x9e, 0xaf, 0x19, 0x27, 0xb1, 0xfc, - 0xd7, 0x85, 0xd3, 0x76, 0xab, 0xf6, 0x08, 0x06, 0x81, 0xe7, 0x5f, 0x45, 0xcc, 0xb6, 0x1a, 0xd6, 0x9d, 0x99, 0xa9, - 0xaa, 0x97, 0xeb, 0xd5, 0xdc, 0x5a, 0x8f, 0x09, 0x15, 0x54, 0x5e, 0xaa, 0xae, 0x32, 0x26, 0x32, 0xf2, 0x63, 0x41, - 0x39, 0xba, 0xba, 0xcd, 0x73, 0xde, 0xa3, 0x3d, 0x8b, 0xdc, 0x0c, 0x80, 0x91, 0x4e, 0xc8, 0x30, 0xe1, 0x16, 0x66, - 0x3a, 0xb2, 0x5a, 0x55, 0x16, 0xf0, 0x51, 0xc3, 0x17, 0x1d, 0xb4, 0xc0, 0xe4, 0xd5, 0x13, 0x87, 0xb3, 0x42, 0x8c, - 0x14, 0xf7, 0xb1, 0x9f, 0x10, 0xf3, 0xc7, 0x69, 0x26, 0xa6, 0x6a, 0xd6, 0x3e, 0xef, 0x7e, 0x07, 0x42, 0x13, 0x43, - 0x74, 0x58, 0x44, 0xaf, 0x43, 0x01, 0x9b, 0xe4, 0xb5, 0x55, 0xb5, 0xc8, 0xf0, 0xeb, 0x81, 0xc6, 0x32, 0x06, 0x21, - 0xcc, 0x25, 0x30, 0xab, 0xfd, 0x74, 0xdb, 0x05, 0x65, 0xa3, 0x48, 0x2b, 0x9c, 0xac, 0x57, 0xac, 0x35, 0xb1, 0x16, - 0x96, 0xe3, 0xa2, 0x43, 0x71, 0x15, 0x1a, 0xb1, 0x8a, 0xa8, 0x75, 0x89, 0x9f, 0xec, 0x14, 0x8d, 0x82, 0xb8, 0x6c, - 0x09, 0x22, 0x6a, 0x72, 0x72, 0xd7, 0x43, 0xea, 0x13, 0x2b, 0xa4, 0x29, 0x41, 0xf8, 0xce, 0x13, 0x94, 0x31, 0x02, - 0xb7, 0x55, 0x6a, 0x8c, 0x0d, 0x25, 0x99, 0x83, 0xc1, 0xf0, 0xcd, 0x04, 0x27, 0x7a, 0x09, 0x65, 0x46, 0xab, 0xe4, - 0x3e, 0x66, 0x4c, 0x63, 0x29, 0x27, 0x33, 0xa3, 0x6f, 0x58, 0xf8, 0xb3, 0x74, 0x21, 0xe7, 0xce, 0x5d, 0x5d, 0x9e, - 0xa9, 0xaf, 0xc8, 0xf3, 0xb9, 0x2d, 0x5c, 0x4b, 0xc6, 0x50, 0x7b, 0xd4, 0x94, 0xad, 0x78, 0xc3, 0x48, 0xaa, 0x71, - 0xfc, 0xaa, 0x97, 0x22, 0xac, 0xbb, 0x62, 0x78, 0xbd, 0xdd, 0x65, 0xe6, 0xda, 0x16, 0xd3, 0x5f, 0xcb, 0xfb, 0x19, - 0x5a, 0x0f, 0x7c, 0x35, 0x74, 0x73, 0x58, 0xf3, 0xfb, 0xa2, 0xdc, 0x23, 0x2c, 0xb7, 0x7f, 0x27, 0xc6, 0xed, 0xeb, - 0x5b, 0x30, 0x58, 0xc8, 0xe7, 0x66, 0x29, 0x6e, 0xb0, 0x7a, 0x90, 0x2e, 0x28, 0x1c, 0x89, 0xa9, 0x5c, 0xbd, 0x6c, - 0xc5, 0x4d, 0xed, 0x76, 0x9b, 0xb1, 0x4e, 0xa4, 0x56, 0xbe, 0x41, 0xb1, 0x6f, 0x7c, 0x81, 0xed, 0x8f, 0x30, 0xb4, - 0xeb, 0x15, 0xe7, 0xb6, 0xfa, 0xb7, 0xbc, 0xe3, 0xf7, 0xfd, 0x61, 0x13, 0x3a, 0xfe, 0x74, 0x7b, 0xe8, 0x86, 0x07, - 0xd2, 0x77, 0x69, 0x5f, 0x76, 0xa5, 0xa8, 0xbf, 0xe4, 0xc0, 0xa9, 0xf3, 0x63, 0x74, 0x5b, 0xf5, 0xa6, 0xde, 0xc7, - 0x11, 0x5e, 0x2a, 0xff, 0xc3, 0xda, 0xe2, 0x3e, 0xcd, 0x47, 0x7b, 0xde, 0x7a, 0xf2, 0xab, 0xdb, 0x74, 0x17, 0x56, - 0x35, 0x7f, 0x2b, 0x53, 0x1a, 0x2f, 0xce, 0x39, 0x60, 0xf6, 0x4f, 0xd4, 0x64, 0x0f, 0x91, 0xa9, 0xe4, 0x38, 0xae, - 0x62, 0x51, 0xeb, 0x49, 0xa1, 0x11, 0x79, 0xc3, 0xd5, 0x9e, 0x47, 0x83, 0x90, 0xd8, 0x01, 0x22, 0x3f, 0x16, 0x85, - 0xa1, 0x23, 0x16, 0x91, 0x76, 0x8d, 0xcf, 0x8b, 0xfa, 0x08, 0x85, 0x58, 0x4d, 0x84, 0x87, 0x05, 0x79, 0x1f, 0x01, - 0x54, 0xda, 0x4b, 0x5a, 0x5b, 0xe9, 0x20, 0xdb, 0x57, 0x82, 0x64, 0x72, 0x60, 0x24, 0xbd, 0x83, 0xd8, 0xce, 0x79, - 0x15, 0x2e, 0xbf, 0x98, 0x9b, 0x42, 0xee, 0xba, 0xca, 0x97, 0x3e, 0x69, 0x6c, 0x72, 0x80, 0xa3, 0xc2, 0xda, 0x57, - 0x4e, 0xc7, 0x41, 0x1f, 0xc4, 0x5e, 0xfe, 0x77, 0x16, 0xb8, 0x64, 0xdd, 0x05, 0xac, 0x97, 0xbe, 0xcf, 0xc3, 0x84, - 0x12, 0x6a, 0xd2, 0xb2, 0x44, 0x17, 0x36, 0x28, 0x55, 0xda, 0x6f, 0x21, 0xe2, 0xb0, 0xc5, 0x97, 0xdc, 0xa6, 0x51, - 0xb7, 0x52, 0xae, 0x6f, 0xe7, 0x94, 0x43, 0xeb, 0x8d, 0x1d, 0xc3, 0xd6, 0x62, 0xbc, 0x70, 0x18, 0x14, 0xa2, 0xa1, - 0xc6, 0x25, 0xcd, 0x57, 0x50, 0x6b, 0xe4, 0x8e, 0x45, 0x4b, 0x32, 0x9c, 0x3e, 0x6e, 0x39, 0x58, 0xa6, 0x81, 0x18, - 0xce, 0xa7, 0x9e, 0xbc, 0x26, 0xf9, 0x40, 0xc1, 0x0d, 0x9a, 0x65, 0x55, 0xd8, 0x1d, 0xd0, 0xbc, 0x0e, 0x1a, 0xad, - 0xa4, 0xc9, 0xa8, 0x4a, 0xba, 0x9f, 0xa6, 0xf8, 0x5d, 0xc6, 0xba, 0x57, 0x94, 0x12, 0xc6, 0xa8, 0xfe, 0xd0, 0x28, - 0x25, 0x07, 0x37, 0xd9, 0xb2, 0x27, 0xd4, 0x25, 0x62, 0xa2, 0x3c, 0x4f, 0xa1, 0x2b, 0xb4, 0x32, 0x72, 0xa8, 0xae, - 0x78, 0x83, 0x2c, 0x0e, 0x76, 0x96, 0x22, 0x99, 0x0f, 0x3a, 0x52, 0xef, 0x13, 0x4d, 0x21, 0x9c, 0xab, 0x64, 0x74, - 0xe3, 0xee, 0x94, 0x1e, 0x24, 0x70, 0xe2, 0x42, 0x47, 0xdb, 0xa1, 0xd7, 0x02, 0x76, 0xa3, 0x12, 0x7a, 0x8a, 0xdf, - 0xe9, 0xf3, 0x2c, 0x78, 0x3b, 0x12, 0xdb, 0x46, 0x31, 0xe6, 0xa8, 0x3a, 0xf5, 0x07, 0x6b, 0xdb, 0x71, 0xdf, 0x64, - 0xc3, 0x2f, 0x26, 0x7f, 0xd4, 0x41, 0x70, 0xcc, 0x3b, 0x59, 0x0e, 0x04, 0x32, 0x80, 0x4a, 0x27, 0x86, 0xf7, 0xc5, - 0x2e, 0x07, 0x85, 0x5f, 0xf5, 0x32, 0x57, 0xda, 0x96, 0x88, 0x8b, 0x8a, 0x83, 0x6f, 0x70, 0x3d, 0xa6, 0x7a, 0x2f, - 0x1d, 0x02, 0xe3, 0x1b, 0xa9, 0x70, 0x73, 0xdf, 0x0a, 0x03, 0x1d, 0x08, 0xca, 0xd9, 0xa8, 0x51, 0xa7, 0x3e, 0x5f, - 0x2d, 0xc8, 0x0b, 0x3c, 0x56, 0x8a, 0x63, 0xd7, 0x75, 0x2f, 0x3c, 0x96, 0x62, 0x3f, 0xa8, 0x50, 0xfe, 0xe7, 0x08, - 0x50, 0x89, 0x00, 0x46, 0xad, 0xd8, 0xca, 0xee, 0x7f, 0x31, 0x5d, 0xa6, 0xba, 0xa4, 0x48, 0xfd, 0x95, 0xe5, 0x24, - 0x7f, 0xe4, 0x61, 0x8f, 0xca, 0xc6, 0x83, 0x2d, 0x46, 0x81, 0x03, 0x78, 0x98, 0xa4, 0xf0, 0x56, 0xc6, 0x78, 0x5d, - 0xc5, 0x5a, 0x23, 0x15, 0x82, 0x64, 0x66, 0xb7, 0x8d, 0x7c, 0x91, 0x9f, 0x26, 0x41, 0x13, 0x3f, 0xa7, 0xde, 0x2b, - 0x4c, 0x3b, 0x76, 0xd6, 0x12, 0x05, 0xf4, 0xf2, 0x0e, 0xa1, 0x43, 0x56, 0xf1, 0xe5, 0xd4, 0x9a, 0x45, 0x40, 0x62, - 0x71, 0x6d, 0x7c, 0x4d, 0xb3, 0x7d, 0x9e, 0xc5, 0x08, 0xcb, 0x2f, 0xa8, 0x82, 0xcb, 0x14, 0xa8, 0x95, 0xda, 0xb3, - 0xee, 0x30, 0xd8, 0xa1, 0x2c, 0x63, 0x7a, 0x11, 0xb2, 0x28, 0xd2, 0xc4, 0x5a, 0xed, 0x62, 0x34, 0x20, 0xc1, 0x25, - 0x4c, 0x54, 0x28, 0x23, 0xcb, 0x18, 0x90, 0xe6, 0x96, 0xb5, 0x7d, 0x91, 0x51, 0x41, 0xbd, 0xfd, 0xcf, 0xac, 0xf6, - 0x3d, 0x2c, 0xd2, 0xf6, 0x4a, 0xba, 0x7e, 0xff, 0xdb, 0x4d, 0xe8, 0xf2, 0x45, 0xdf, 0x3d, 0x7c, 0xc5, 0x9a, 0xed, - 0x0d, 0x7c, 0xe9, 0xc3, 0xa0, 0x49, 0x99, 0x1c, 0x0a, 0x03, 0xcd, 0x32, 0x6e, 0x44, 0x6b, 0x07, 0x3c, 0xb2, 0xc3, - 0xb2, 0x89, 0xbc, 0xce, 0x6b, 0xaa, 0x67, 0x57, 0xa4, 0x61, 0x96, 0x26, 0xc5, 0x05, 0xa0, 0xb7, 0xbe, 0xd2, 0x35, - 0x55, 0x23, 0x4b, 0x60, 0x82, 0x62, 0x10, 0x6f, 0x4e, 0x65, 0x97, 0x36, 0xba, 0xf0, 0x28, 0x6f, 0x62, 0xac, 0x1f, - 0xb1, 0xdd, 0x01, 0x81, 0x4a, 0xd5, 0x02, 0x75, 0x2f, 0x0c, 0xe6, 0xe4, 0xaa, 0xa3, 0xda, 0xca, 0x48, 0x90, 0x4d, - 0xc3, 0x36, 0xbf, 0xd0, 0x70, 0x47, 0xc9, 0x26, 0x41, 0x52, 0xc8, 0x26, 0x63, 0xce, 0x8b, 0xda, 0xbd, 0x22, 0x66, - 0xa2, 0x4f, 0x1e, 0xdb, 0x39, 0xc8, 0x74, 0xb7, 0xcf, 0xe9, 0x63, 0x95, 0xc0, 0xe1, 0x9e, 0x46, 0x31, 0x3b, 0x5a, - 0xe1, 0xcf, 0x0b, 0xda, 0x9a, 0x61, 0xec, 0x21, 0x5c, 0xbd, 0x95, 0x12, 0x48, 0xdc, 0x8b, 0x2a, 0x38, 0xdb, 0x90, - 0xf4, 0xdb, 0xd1, 0x67, 0x4a, 0x8e, 0xe4, 0xca, 0x7e, 0x41, 0x5b, 0x27, 0x4e, 0x7c, 0x04, 0xe7, 0xed, 0xd6, 0x0b, - 0x43, 0x4f, 0x5b, 0xba, 0x0b, 0x5f, 0x16, 0xf7, 0x72, 0x75, 0x46, 0x3d, 0xb8, 0x8e, 0x4b, 0xb5, 0x20, 0x11, 0x2c, - 0x5a, 0xe7, 0x22, 0x5d, 0xe0, 0xe5, 0x78, 0xe4, 0xfc, 0x54, 0xc4, 0xae, 0xa0, 0x85, 0xf8, 0x90, 0x89, 0x8a, 0xf5, - 0xd6, 0xd1, 0x9f, 0xb8, 0x27, 0xd2, 0x20, 0xb7, 0xeb, 0xd1, 0x8e, 0xec, 0xe1, 0x47, 0xb5, 0xe4, 0x8a, 0xc2, 0x5e, - 0x25, 0x3b, 0xdf, 0xf5, 0x1a, 0x33, 0xeb, 0x9b, 0x65, 0x1f, 0x42, 0xb0, 0x80, 0xec, 0x14, 0xdf, 0xcb, 0x0b, 0xc8, - 0xbf, 0xc8, 0x58, 0x66, 0x31, 0x30, 0x93, 0x61, 0xc3, 0xe0, 0x1f, 0xb4, 0xa8, 0xd4, 0xcb, 0xe9, 0x38, 0xb8, 0x23, - 0x8e, 0x86, 0x43, 0x32, 0x55, 0x25, 0xdd, 0x3f, 0x18, 0x65, 0x5d, 0x0a, 0x27, 0x98, 0x64, 0xda, 0xfe, 0x15, 0xb4, - 0xda, 0x35, 0xef, 0x48, 0x72, 0x22, 0x3b, 0x53, 0xbb, 0xa6, 0x71, 0x43, 0xeb, 0x96, 0xce, 0x1d, 0xbd, 0x7b, 0x06, - 0x0f, 0xac, 0xbc, 0xe2, 0x6d, 0x49, 0xe2, 0x9d, 0x40, 0x85, 0x77, 0x03, 0x55, 0xde, 0x0b, 0xb4, 0xf1, 0xbe, 0xa4, - 0x9d, 0x0f, 0x02, 0x19, 0x5b, 0x88, 0xb9, 0xd5, 0x5c, 0x37, 0xb7, 0x9e, 0x8b, 0xb5, 0x7e, 0x30, 0x48, 0xb5, 0x1b, - 0xff, 0x9c, 0x3c, 0xfb, 0x52, 0xb7, 0xdd, 0x8e, 0xfb, 0xf9, 0xfe, 0x69, 0xb4, 0xb7, 0x3f, 0x99, 0x42, 0xe7, 0x45, - 0x12, 0x69, 0x7c, 0xee, 0xf5, 0x30, 0x04, 0xeb, 0xdc, 0x18, 0x7d, 0xdd, 0x05, 0x0d, 0xe5, 0x2e, 0x6c, 0x97, 0x7f, - 0xee, 0xfd, 0xc7, 0x93, 0x5f, 0x15, 0xf5, 0xd8, 0xfa, 0x50, 0x9a, 0xc5, 0x65, 0x00, 0xae, 0x3b, 0xd1, 0x78, 0xe5, - 0x82, 0x37, 0x86, 0xfe, 0xcc, 0x92, 0x96, 0x98, 0x47, 0x44, 0x3d, 0xd1, 0x12, 0xd7, 0x94, 0x49, 0x9f, 0x87, 0x2e, - 0xb1, 0xe4, 0xc8, 0x0d, 0xfb, 0x5b, 0xff, 0x85, 0x86, 0x3b, 0xad, 0xc6, 0x54, 0x8e, 0xfd, 0xfd, 0xb5, 0x81, 0xea, - 0x72, 0x28, 0xcd, 0xa6, 0x0f, 0x09, 0x13, 0xf5, 0x71, 0x0c, 0x77, 0x6e, 0x0c, 0x17, 0x78, 0x79, 0xb5, 0xa0, 0x5b, - 0x6d, 0xc0, 0x00, 0xcf, 0x79, 0x03, 0x50, 0xc9, 0x08, 0xfc, 0x0b, 0xde, 0xaf, 0x5a, 0x94, 0xe1, 0x8b, 0xd1, 0xef, - 0xce, 0xaf, 0xb6, 0x1f, 0x88, 0x13, 0x1e, 0x2d, 0x56, 0xe8, 0x9a, 0x99, 0xff, 0xb0, 0xc2, 0x7a, 0x8e, 0xbd, 0x9b, - 0xaf, 0x72, 0xde, 0xda, 0x0b, 0xe8, 0xed, 0xae, 0x40, 0x88, 0x40, 0xa3, 0xab, 0xc3, 0x59, 0xdf, 0xe6, 0x8f, 0x1f, - 0x52, 0x36, 0x13, 0x06, 0xe0, 0xd3, 0xca, 0x87, 0x7f, 0x37, 0x7f, 0x53, 0xbc, 0x48, 0xe1, 0x7e, 0xfd, 0xbe, 0x2a, - 0xc2, 0x7f, 0x61, 0x60, 0x7c, 0xc7, 0xc9, 0x05, 0x79, 0x6c, 0xde, 0xae, 0x2c, 0xef, 0xd0, 0xba, 0x68, 0xb1, 0xaf, - 0xcd, 0x13, 0x75, 0xf3, 0xf9, 0x27, 0xaa, 0x39, 0xb7, 0xab, 0xc7, 0xeb, 0xe6, 0xf7, 0xbb, 0xa9, 0x39, 0x7f, 0xc8, - 0x5f, 0xdd, 0x3f, 0x3a, 0xba, 0x6a, 0x38, 0x18, 0x5d, 0x7f, 0x9d, 0x65, 0xbb, 0x61, 0xfe, 0x7e, 0xd1, 0xca, 0x51, - 0x62, 0x95, 0x9a, 0xe5, 0x0f, 0x7b, 0x1f, 0xf3, 0x69, 0x5a, 0xd7, 0xbb, 0x5f, 0xbf, 0xc0, 0xfc, 0x0f, 0x71, 0x23, - 0xda, 0xc3, 0xe3, 0x3f, 0x1b, 0xff, 0xb4, 0x59, 0x73, 0x12, 0x7a, 0x32, 0xd6, 0x2a, 0x88, 0x1a, 0xe3, 0xe9, 0xf9, - 0xc8, 0x90, 0xc6, 0x7f, 0x7a, 0x52, 0x4e, 0x98, 0xe5, 0xc4, 0xd2, 0x7d, 0x4b, 0x78, 0x28, 0x15, 0xe5, 0x46, 0x71, - 0x3c, 0x26, 0xfc, 0xaf, 0x3d, 0xb9, 0x2d, 0x56, 0x29, 0x33, 0x80, 0xfb, 0xa1, 0xe6, 0xfb, 0xc5, 0x75, 0x32, 0x08, - 0xd2, 0x84, 0x89, 0x19, 0x83, 0x31, 0x51, 0x4e, 0xdd, 0x50, 0x08, 0xbe, 0x91, 0x53, 0x8a, 0x9c, 0x5a, 0xba, 0x3f, - 0x11, 0x1e, 0x0e, 0xcf, 0xee, 0x86, 0xa3, 0xdd, 0xcf, 0x1f, 0xb8, 0x9d, 0xe4, 0xd4, 0x98, 0x2f, 0x4f, 0x8d, 0xc6, - 0x9e, 0x01, 0x73, 0xba, 0x40, 0xa7, 0xd5, 0x33, 0xa4, 0xfd, 0x62, 0x20, 0x18, 0xba, 0xf2, 0xd0, 0x76, 0xf1, 0x6d, - 0x8b, 0xcb, 0x8f, 0x0d, 0x7a, 0xcd, 0xb0, 0x1a, 0xfc, 0x53, 0x03, 0xd6, 0x18, 0x13, 0x71, 0x8c, 0x09, 0x4c, 0xf9, - 0x96, 0x66, 0xdd, 0x92, 0x1d, 0x6c, 0xec, 0x29, 0xe5, 0x31, 0x52, 0x32, 0x87, 0xbc, 0x6c, 0xda, 0x98, 0x1b, 0x3c, - 0x2b, 0x9f, 0xe7, 0x76, 0xd2, 0x8e, 0xd0, 0x48, 0xc8, 0xf7, 0xac, 0xd8, 0xa4, 0xe8, 0xcc, 0x21, 0xee, 0x6c, 0x9d, - 0xcd, 0x31, 0x3e, 0x71, 0x44, 0x94, 0xdd, 0x7b, 0xd1, 0xd1, 0xbe, 0xd2, 0x17, 0xe4, 0x6c, 0x2e, 0xbf, 0xcd, 0x31, - 0xcf, 0xf2, 0xe8, 0x91, 0xf4, 0x42, 0xdf, 0x4b, 0x33, 0x8e, 0xc7, 0xbc, 0x6a, 0x69, 0x9e, 0xdd, 0x83, 0x78, 0x46, - 0x21, 0x68, 0x33, 0x4c, 0x7f, 0x7c, 0x33, 0x9f, 0x22, 0x75, 0x2f, 0xe3, 0x5e, 0x36, 0x0d, 0xe8, 0xb0, 0xa1, 0x03, - 0xaa, 0x42, 0x82, 0xa9, 0x55, 0xe8, 0x77, 0x2b, 0x2e, 0xb3, 0x55, 0x5a, 0xbc, 0x45, 0x73, 0x77, 0x65, 0x12, 0x97, - 0x11, 0xfa, 0xdd, 0xf5, 0x45, 0xb2, 0x3e, 0x03, 0xc6, 0x2d, 0x36, 0x14, 0xb3, 0xff, 0x58, 0xea, 0xf1, 0x89, 0x96, - 0x91, 0x81, 0x7d, 0x7d, 0x79, 0xee, 0xae, 0xb5, 0x67, 0x1b, 0x15, 0xb1, 0x31, 0xc5, 0xdc, 0xdc, 0xfa, 0x79, 0xb6, - 0x22, 0x99, 0xdc, 0x36, 0xe1, 0x0c, 0x98, 0xa3, 0x6b, 0xb8, 0x2b, 0x88, 0x71, 0x16, 0x40, 0x43, 0xe1, 0x6c, 0xdf, - 0x84, 0xcb, 0x0b, 0x49, 0x6c, 0x8c, 0x12, 0x7d, 0xe9, 0x7f, 0x77, 0x7e, 0x6a, 0xd0, 0x0f, 0x92, 0xd0, 0x73, 0xef, - 0xd1, 0xe9, 0xf6, 0xa7, 0xf9, 0x54, 0xfd, 0xac, 0xb5, 0x8d, 0x2f, 0xa0, 0x4f, 0x7d, 0x68, 0x79, 0xfb, 0x98, 0x51, - 0x80, 0x95, 0x94, 0xe2, 0x6b, 0x47, 0x75, 0x4c, 0xfd, 0x2d, 0x62, 0xea, 0xf8, 0x8d, 0x91, 0x47, 0xdd, 0xce, 0xa5, - 0x8f, 0x79, 0x33, 0xed, 0xb4, 0x67, 0x09, 0x38, 0xc7, 0x7b, 0xb1, 0xa5, 0x27, 0xbd, 0xee, 0x0b, 0x0e, 0x6c, 0x76, - 0x15, 0xf3, 0x36, 0xd7, 0xd0, 0x66, 0xed, 0xe6, 0xef, 0x6a, 0xec, 0x95, 0xf5, 0x56, 0x0f, 0x92, 0xad, 0xbe, 0xcc, - 0xf3, 0xf3, 0x6b, 0x7e, 0x5b, 0x2a, 0x95, 0xb8, 0x53, 0xc6, 0x77, 0xde, 0xff, 0xbe, 0x86, 0xea, 0xd4, 0x53, 0x46, - 0x29, 0xcc, 0x08, 0xcb, 0x27, 0xcf, 0xd3, 0xf2, 0x97, 0x5d, 0xd6, 0x67, 0x3b, 0x6f, 0xc1, 0xd1, 0xe5, 0xc0, 0x71, - 0x62, 0x16, 0x81, 0xef, 0xf1, 0x15, 0x84, 0xf2, 0xe5, 0x14, 0xb0, 0x25, 0xff, 0xc6, 0x84, 0xe4, 0x96, 0x67, 0x2d, - 0x49, 0x6d, 0x24, 0x16, 0x62, 0x38, 0x71, 0xda, 0xf5, 0x01, 0x20, 0xde, 0x22, 0x02, 0xf2, 0x49, 0xe6, 0x7e, 0xb0, - 0xa0, 0x17, 0xc3, 0x02, 0x7b, 0xbe, 0x14, 0x15, 0xbd, 0xe0, 0x1f, 0x32, 0x68, 0xd5, 0x4a, 0x66, 0x0a, 0x0f, 0x52, - 0x50, 0x72, 0xe2, 0xb1, 0xf8, 0x44, 0x08, 0x6d, 0x74, 0x16, 0xca, 0x30, 0x27, 0x6e, 0x79, 0x9a, 0x83, 0xab, 0xcb, - 0xac, 0xf5, 0x62, 0xec, 0xdd, 0x61, 0xe7, 0x11, 0x32, 0xdc, 0x1f, 0xae, 0xcb, 0xda, 0x92, 0xb6, 0x04, 0xb4, 0xd6, - 0x4e, 0x80, 0x3e, 0xea, 0xd2, 0x2d, 0x77, 0x5d, 0x02, 0x0b, 0xa7, 0xec, 0xee, 0x02, 0xec, 0x82, 0x64, 0xc6, 0xf9, - 0x19, 0xec, 0xdc, 0xe3, 0x0f, 0xf0, 0xfd, 0x0c, 0xda, 0x02, 0x7c, 0x3b, 0x83, 0xf5, 0xeb, 0x08, 0x7c, 0x3d, 0x03, - 0x73, 0x00, 0x67, 0x67, 0xf0, 0x57, 0xf1, 0x7b, 0xe9, 0xe9, 0x19, 0xf8, 0x97, 0x0a, 0x5f, 0xd8, 0x8d, 0x35, 0x84, - 0x13, 0xd6, 0xbc, 0x16, 0x8e, 0xe1, 0x80, 0xd7, 0xac, 0x5d, 0x61, 0x0f, 0xbf, 0x23, 0x63, 0xb0, 0x8f, 0xd8, 0x23, - 0x6f, 0x70, 0xc4, 0xec, 0x0e, 0x87, 0x97, 0x86, 0x77, 0xfb, 0xff, 0xb1, 0xb1, 0x3c, 0x4c, 0xd8, 0x7e, 0x8b, 0xbf, - 0x54, 0x42, 0x85, 0xcf, 0xff, 0x53, 0xbd, 0x80, 0xe9, 0x19, 0xd4, 0x05, 0xf8, 0x74, 0x06, 0xdb, 0x02, 0x7c, 0x3c, - 0x83, 0xdb, 0x52, 0xd7, 0x0d, 0x70, 0x70, 0x06, 0x7a, 0x07, 0x3e, 0x9c, 0xc1, 0xe6, 0x1b, 0x78, 0x73, 0x06, 0xea, - 0xf8, 0xed, 0x81, 0xb7, 0x67, 0xa0, 0x57, 0xe0, 0x9d, 0x67, 0x60, 0xe0, 0xfd, 0xdf, 0x38, 0x7f, 0x83, 0x91, 0x53, - 0x76, 0x9f, 0xe5, 0x2b, 0x46, 0xd3, 0x0f, 0xc9, 0x63, 0x27, 0xce, 0x2c, 0xc0, 0x67, 0xfb, 0x6f, 0xa4, 0xe9, 0x26, - 0x5b, 0x6c, 0x02, 0x29, 0x5c, 0x55, 0x66, 0x0c, 0x8c, 0xff, 0x23, 0x7e, 0x66, 0x0e, 0x86, 0x46, 0x12, 0x1b, 0xd9, - 0xc0, 0xaa, 0xed, 0xf9, 0x3f, 0xb6, 0x09, 0xbb, 0x5b, 0x45, 0xb6, 0x73, 0xef, 0xf1, 0xe3, 0xa3, 0xfb, 0xca, 0xa6, - 0xb1, 0x48, 0x03, 0xaa, 0xba, 0x80, 0x8e, 0x94, 0x52, 0x0b, 0xe6, 0x6e, 0xf5, 0x4f, 0x84, 0x6f, 0x2e, 0x78, 0x84, - 0xd9, 0xad, 0x34, 0x52, 0x80, 0x94, 0x99, 0xfe, 0x27, 0x57, 0x7b, 0xa4, 0x2c, 0x3d, 0xcb, 0xa2, 0xf2, 0xa9, 0xf7, - 0xc9, 0xcb, 0xe4, 0x98, 0x65, 0x2e, 0xd4, 0x38, 0xf4, 0xf3, 0x14, 0x02, 0xca, 0x21, 0x25, 0xdc, 0x9e, 0x86, 0x97, - 0x8c, 0xe1, 0x5b, 0x72, 0xeb, 0x05, 0xf6, 0x9e, 0x60, 0xc8, 0xed, 0x98, 0x02, 0xab, 0x98, 0xa9, 0x0d, 0xfa, 0x08, - 0xc4, 0x71, 0x53, 0x6a, 0xfc, 0x35, 0xfa, 0xf0, 0x76, 0xb1, 0xab, 0xe3, 0x60, 0x50, 0xf5, 0x3b, 0x0d, 0x8f, 0x88, - 0x4a, 0xca, 0x21, 0x8b, 0x16, 0x59, 0xb2, 0xfd, 0x85, 0x03, 0x4a, 0xd0, 0x44, 0xbb, 0xd2, 0xf2, 0x9a, 0x14, 0xbc, - 0x1c, 0x5d, 0x30, 0x19, 0x8e, 0x67, 0xf0, 0x0c, 0x52, 0x7f, 0xce, 0x1b, 0x5e, 0x01, 0xda, 0xe0, 0x93, 0xee, 0xd7, - 0x75, 0xc7, 0x17, 0x7a, 0x47, 0x69, 0xc6, 0x15, 0x3e, 0x8b, 0xdf, 0x30, 0xcb, 0x5c, 0xff, 0x46, 0x90, 0x66, 0x7b, - 0xeb, 0x69, 0x0b, 0x60, 0xfe, 0x01, 0xdb, 0xb3, 0x97, 0x33, 0x5c, 0x6c, 0xed, 0x51, 0x54, 0x2b, 0x2d, 0x38, 0xe8, - 0x6e, 0x33, 0xe0, 0x6e, 0x31, 0xb8, 0x67, 0x47, 0x7b, 0x25, 0x14, 0x4e, 0x44, 0xab, 0x0c, 0x45, 0x76, 0x00, 0xdf, - 0xb1, 0xb1, 0x25, 0x1a, 0xe9, 0xf4, 0xa0, 0x6f, 0xd0, 0xb6, 0x44, 0x10, 0xb6, 0x6e, 0xb7, 0x88, 0x81, 0xec, 0x55, - 0xe2, 0x7f, 0x5f, 0xee, 0x65, 0xd4, 0xd2, 0x4c, 0xdf, 0xe3, 0x3b, 0xe6, 0xa7, 0xb4, 0x50, 0x9f, 0x24, 0x65, 0xec, - 0x34, 0xfe, 0xe9, 0xcf, 0x90, 0xe7, 0x78, 0xd5, 0x55, 0x00, 0x14, 0xdc, 0xd0, 0x28, 0xfe, 0x90, 0xcf, 0x9a, 0xb0, - 0x70, 0x19, 0x79, 0x5c, 0x30, 0xc0, 0x2c, 0x73, 0xdc, 0xc4, 0xd8, 0x70, 0x71, 0x58, 0x70, 0x98, 0x99, 0x74, 0x99, - 0xd1, 0xeb, 0x62, 0x5c, 0x8a, 0xd6, 0x7d, 0x35, 0x35, 0x7e, 0x93, 0x19, 0xa1, 0x0f, 0x4f, 0xc3, 0x80, 0x5d, 0xc4, - 0xd8, 0xbf, 0x6b, 0x70, 0x55, 0x30, 0xb6, 0x55, 0x83, 0x15, 0xa5, 0x66, 0x95, 0xbf, 0x7c, 0x76, 0xd4, 0x1f, 0xde, - 0xe4, 0xd6, 0x33, 0x06, 0x0c, 0xfb, 0x82, 0x09, 0x6d, 0xca, 0xdf, 0x1b, 0x93, 0x88, 0x5e, 0x70, 0x6e, 0x7c, 0x4a, - 0x16, 0x6e, 0x9a, 0x61, 0x2a, 0x76, 0xd0, 0x24, 0x75, 0x08, 0xb1, 0x89, 0xbf, 0x7d, 0xf2, 0xe4, 0x39, 0xa4, 0x7c, - 0x4e, 0x44, 0x92, 0x68, 0x75, 0x47, 0xf1, 0x6c, 0xe2, 0x8a, 0x67, 0x41, 0x54, 0x72, 0x03, 0xc0, 0x11, 0xe8, 0xd2, - 0x74, 0xf8, 0xdd, 0x7e, 0xdc, 0x6b, 0x03, 0xcc, 0x36, 0xd6, 0xdd, 0xc7, 0xa1, 0x31, 0xe5, 0x19, 0xdd, 0x0f, 0x7a, - 0xe5, 0x39, 0x78, 0x9a, 0x5f, 0xa6, 0x24, 0x43, 0x86, 0xd5, 0xcc, 0xa1, 0xc3, 0x75, 0x54, 0xe5, 0x1a, 0xb4, 0xe0, - 0x63, 0xaa, 0xd4, 0xc8, 0x9b, 0xf7, 0x87, 0xeb, 0x82, 0xe4, 0x68, 0x07, 0xb4, 0xf6, 0x7a, 0x98, 0x5d, 0x08, 0x0c, - 0x52, 0x48, 0xb8, 0x63, 0x5b, 0x7b, 0x7f, 0xa7, 0x87, 0xeb, 0xed, 0x4b, 0x94, 0x5b, 0x6f, 0x7d, 0x60, 0x96, 0xfe, - 0xa4, 0xb3, 0x2b, 0xc3, 0x8e, 0xbf, 0x5a, 0x93, 0x0f, 0x6f, 0x6a, 0x6d, 0xa4, 0x64, 0xfa, 0xea, 0x82, 0x1f, 0x27, - 0x8c, 0x09, 0x9e, 0x81, 0x98, 0x10, 0xd5, 0xe9, 0x7a, 0x49, 0x22, 0x8a, 0xad, 0x09, 0x91, 0x52, 0x24, 0x11, 0xc9, - 0x49, 0xba, 0xab, 0x9b, 0xe2, 0x93, 0xd3, 0x13, 0x69, 0xe6, 0x0e, 0x0c, 0x60, 0xa9, 0x4f, 0xcf, 0xe6, 0x2c, 0x7f, - 0x23, 0x10, 0x7e, 0x94, 0x02, 0x96, 0xd6, 0x60, 0xf2, 0x80, 0xbd, 0xa4, 0x7e, 0xa6, 0xea, 0x2e, 0x9a, 0x14, 0xc9, - 0xa3, 0x67, 0x80, 0xad, 0x9c, 0x72, 0x84, 0x2a, 0xd3, 0x4c, 0x48, 0x8e, 0x73, 0x6b, 0x32, 0x27, 0x21, 0x94, 0x9c, - 0x99, 0x7b, 0xc4, 0xf2, 0x29, 0xfc, 0xb2, 0x29, 0x6f, 0x7a, 0x27, 0x5b, 0x8a, 0x75, 0x35, 0x84, 0xe1, 0xc4, 0x80, - 0xdf, 0x42, 0xec, 0xf5, 0xd6, 0x91, 0x34, 0xc8, 0x79, 0xf2, 0x8c, 0x23, 0x6c, 0x5c, 0x62, 0xa3, 0x6f, 0x36, 0x4a, - 0x12, 0x72, 0x40, 0x26, 0xbb, 0x50, 0x72, 0x72, 0x07, 0xef, 0xc1, 0xc7, 0x36, 0xdd, 0x9f, 0xff, 0xca, 0x13, 0xad, - 0x6a, 0x63, 0x60, 0xd5, 0xd7, 0x03, 0x59, 0x99, 0x7c, 0x25, 0x40, 0x5b, 0xc0, 0x85, 0xe4, 0x6f, 0x7f, 0xc5, 0x71, - 0x88, 0xaf, 0x32, 0xc8, 0x60, 0xd4, 0xe2, 0x8b, 0xc8, 0x3e, 0xb5, 0x62, 0xe3, 0xef, 0x94, 0xe6, 0x0a, 0x56, 0xb5, - 0x2f, 0x41, 0x64, 0x71, 0x68, 0xba, 0x4f, 0x73, 0xb0, 0x46, 0xad, 0x3f, 0x52, 0xe4, 0x6c, 0x8a, 0xd6, 0x1f, 0x4a, - 0x68, 0x24, 0x2b, 0xde, 0xea, 0x8b, 0x4b, 0xea, 0x2c, 0xaa, 0xa7, 0xa7, 0xc4, 0xa2, 0x62, 0x37, 0x6f, 0x6f, 0x71, - 0x4d, 0xd6, 0x2d, 0xb8, 0x1c, 0x59, 0x19, 0xbe, 0x5d, 0xe9, 0x6c, 0xca, 0xf3, 0x7b, 0x7a, 0x36, 0xb6, 0x60, 0x1f, - 0x7c, 0x6b, 0x53, 0x49, 0x73, 0x61, 0xc5, 0xaf, 0xf2, 0x70, 0x85, 0xdf, 0x90, 0xa0, 0x50, 0x85, 0x3f, 0xbd, 0x48, - 0x8e, 0x8b, 0xef, 0x88, 0x3d, 0x68, 0x5b, 0x83, 0x86, 0xb3, 0x08, 0x33, 0x21, 0x21, 0xe1, 0x00, 0x64, 0xf2, 0x61, - 0xdc, 0x2a, 0xa9, 0x25, 0xb6, 0xa4, 0x97, 0x23, 0x31, 0xe0, 0xf2, 0x5b, 0xb7, 0xc9, 0x4a, 0x57, 0x4f, 0xc1, 0x24, - 0x6e, 0x60, 0x05, 0x53, 0x8f, 0xe3, 0x1b, 0xa5, 0xb3, 0xd2, 0x12, 0x89, 0x04, 0x63, 0x21, 0x44, 0x7d, 0x3f, 0xf5, - 0x26, 0x33, 0x64, 0x45, 0x23, 0x8d, 0x48, 0xd3, 0x4d, 0x30, 0x03, 0x31, 0x81, 0xc2, 0x3c, 0xe6, 0xd6, 0x08, 0x11, - 0x66, 0x98, 0x6e, 0x22, 0x5d, 0xeb, 0x06, 0xcb, 0xf1, 0xfe, 0xa9, 0x1e, 0x8d, 0x79, 0xec, 0x06, 0xb5, 0xb6, 0x91, - 0x86, 0x31, 0x9e, 0xae, 0x10, 0x42, 0xb7, 0x10, 0xc5, 0xc3, 0x9a, 0xb5, 0x9a, 0xc6, 0x7e, 0x74, 0x6d, 0xf7, 0x20, - 0x00, 0xce, 0x63, 0x98, 0x5e, 0x06, 0x51, 0xd2, 0x2b, 0x13, 0x32, 0x1e, 0x91, 0x66, 0xe4, 0xc9, 0x15, 0xad, 0x22, - 0xad, 0xc1, 0xc2, 0xaa, 0x12, 0xc9, 0x9f, 0xa0, 0x52, 0x08, 0x49, 0xfa, 0x9e, 0xe6, 0xc3, 0xa3, 0xa5, 0x32, 0x56, - 0xbc, 0xa7, 0xef, 0xf3, 0xdb, 0xd5, 0x7c, 0x8d, 0x48, 0x98, 0x27, 0x40, 0x7c, 0x5d, 0xc0, 0x71, 0x5e, 0x95, 0x7c, - 0x0a, 0x12, 0x03, 0x03, 0xa1, 0x10, 0x6a, 0xbf, 0xc7, 0x99, 0xbb, 0x2a, 0x2b, 0x85, 0x20, 0x79, 0xb8, 0x15, 0xc5, - 0xcd, 0x48, 0xa5, 0xb1, 0x22, 0x48, 0xc6, 0x77, 0xf3, 0xa5, 0xaf, 0x25, 0x7b, 0xeb, 0x41, 0x26, 0x13, 0xc4, 0x59, - 0xfc, 0x7f, 0x96, 0x37, 0xcd, 0x7e, 0xbf, 0xf8, 0x52, 0x13, 0x23, 0x45, 0xb2, 0x97, 0x6a, 0xf2, 0xf4, 0x2f, 0x53, - 0x96, 0x01, 0x87, 0x44, 0x4b, 0x5f, 0xa1, 0x09, 0x0e, 0xb4, 0x21, 0xb3, 0x59, 0x80, 0x50, 0x48, 0x69, 0x31, 0xda, - 0x5d, 0xa4, 0x3a, 0xcb, 0xea, 0x98, 0x9d, 0x35, 0x33, 0x2c, 0x2a, 0xfd, 0x10, 0xb3, 0xa7, 0x61, 0xa6, 0x37, 0x59, - 0xf1, 0x8f, 0xd9, 0x4d, 0xca, 0xaf, 0xd9, 0x4d, 0x51, 0x06, 0x45, 0x1e, 0x1c, 0xe4, 0x90, 0x0b, 0xee, 0x26, 0x36, - 0x12, 0x75, 0x0f, 0x96, 0x0d, 0x93, 0x8b, 0x13, 0xbb, 0x24, 0x90, 0xb4, 0xc1, 0xe3, 0xbd, 0xde, 0x47, 0xf8, 0x90, - 0x0a, 0xf3, 0x7c, 0xfc, 0x21, 0x93, 0x93, 0xc9, 0x85, 0xcb, 0xea, 0x07, 0x66, 0x77, 0x41, 0xa2, 0x07, 0xe6, 0xc7, - 0xee, 0xd8, 0x49, 0x94, 0x82, 0x4c, 0xe6, 0x7a, 0x8b, 0xb4, 0xc7, 0xf4, 0xb1, 0x59, 0x75, 0xbf, 0x8c, 0xea, 0xfe, - 0xa0, 0xe8, 0x15, 0x8e, 0xb0, 0xf7, 0xa3, 0x72, 0x12, 0x68, 0xea, 0x29, 0x77, 0x6d, 0xe0, 0xde, 0xab, 0x58, 0x98, - 0xbc, 0x99, 0xe5, 0x1b, 0xcf, 0xb6, 0x2f, 0x52, 0xe7, 0xd9, 0x3a, 0x6a, 0x76, 0x1f, 0x97, 0x95, 0x64, 0x89, 0x73, - 0x81, 0x32, 0x46, 0xa0, 0x9a, 0x86, 0xe7, 0xae, 0x0b, 0x9b, 0x49, 0x69, 0x38, 0x8d, 0x9e, 0x50, 0x35, 0x48, 0x9d, - 0x53, 0x8a, 0x46, 0xb3, 0xf8, 0x2e, 0xe5, 0x9c, 0xe7, 0x4c, 0x38, 0x00, 0xa5, 0x94, 0x4b, 0x25, 0xcb, 0xf6, 0xf1, - 0x98, 0x0a, 0x7e, 0x67, 0xa2, 0xf0, 0x47, 0x17, 0x78, 0xe4, 0xba, 0xee, 0x6e, 0x08, 0x63, 0xe5, 0x0a, 0x3a, 0x83, - 0xf3, 0x3a, 0xf6, 0x8b, 0xce, 0x30, 0x19, 0x9e, 0xc1, 0xa8, 0x9e, 0xe5, 0x0c, 0xef, 0x57, 0x71, 0x5b, 0x56, 0x9e, - 0xbf, 0x73, 0x5d, 0x6b, 0xf3, 0x03, 0xce, 0x50, 0x53, 0x0f, 0x73, 0xa5, 0xc6, 0xf9, 0x9a, 0x01, 0x77, 0xaf, 0xe5, - 0x39, 0x58, 0x51, 0x61, 0xc1, 0x16, 0xcc, 0xb0, 0x01, 0xaa, 0x8b, 0xfc, 0x28, 0xa9, 0x60, 0x85, 0x0b, 0xaf, 0x57, - 0xfb, 0xeb, 0xaa, 0x0f, 0xa8, 0xa1, 0xcc, 0x3d, 0xae, 0xf0, 0x90, 0xfa, 0x0a, 0xbb, 0x12, 0x23, 0xbb, 0x05, 0xd7, - 0x78, 0xdc, 0xf6, 0xe6, 0xb5, 0x78, 0x2c, 0x9a, 0x9d, 0xf6, 0x23, 0xc6, 0x26, 0x16, 0xcf, 0xc2, 0x42, 0x27, 0xc9, - 0x99, 0xef, 0xbc, 0x57, 0x8a, 0xf2, 0xfc, 0x81, 0xb1, 0x9f, 0x25, 0x91, 0x20, 0x94, 0xd4, 0xf6, 0x4f, 0x08, 0xad, - 0x61, 0xaa, 0xa5, 0x34, 0x17, 0xd1, 0xe7, 0x1a, 0x0c, 0x98, 0x12, 0x66, 0x39, 0x8d, 0xca, 0x6b, 0x5b, 0xb6, 0x63, - 0xde, 0xf9, 0x53, 0xa9, 0x05, 0x91, 0xcc, 0x8f, 0xd1, 0x88, 0x60, 0x43, 0x4c, 0x90, 0x79, 0x33, 0x9f, 0x96, 0xd3, - 0x92, 0xcf, 0xbb, 0xf9, 0xc3, 0xe2, 0x81, 0xca, 0x6d, 0xf5, 0xb9, 0xa6, 0x33, 0x94, 0x87, 0xba, 0x7a, 0x53, 0x5d, - 0xa3, 0xbb, 0x39, 0xf4, 0x5d, 0x59, 0xe9, 0xbd, 0xf9, 0xef, 0x77, 0x67, 0xc9, 0x7b, 0xc0, 0xf4, 0xa2, 0x6a, 0xb4, - 0x9f, 0x00, 0x9e, 0xe5, 0xd2, 0xc1, 0xff, 0x54, 0xa4, 0x26, 0x57, 0xd1, 0x04, 0xf4, 0xdd, 0xcc, 0x0d, 0x48, 0x5b, - 0xd9, 0x74, 0x06, 0x8d, 0xa1, 0xe6, 0xa8, 0x5e, 0x19, 0xf1, 0xe7, 0xf2, 0xaf, 0x57, 0x18, 0x18, 0xd6, 0x32, 0x33, - 0x16, 0x21, 0x83, 0x59, 0x9a, 0xd8, 0xe4, 0x9d, 0xe6, 0xf4, 0xe7, 0x76, 0xed, 0xe6, 0xab, 0xdd, 0x7b, 0x0b, 0xb2, - 0xc0, 0x09, 0x86, 0x93, 0x4f, 0x1c, 0x2a, 0x8a, 0xcb, 0xb7, 0x75, 0x3d, 0xfd, 0xd7, 0xed, 0xdb, 0xd0, 0xfb, 0xe6, - 0xac, 0x98, 0xd4, 0xb4, 0xec, 0x1e, 0x4d, 0x0b, 0x30, 0x7f, 0x2a, 0x6e, 0xbf, 0xec, 0xf9, 0x36, 0x8e, 0x16, 0x47, - 0x07, 0xe3, 0x67, 0xf7, 0xd7, 0x3b, 0x06, 0xc0, 0xe3, 0xcf, 0x29, 0xa9, 0xa6, 0x39, 0x5d, 0xfc, 0x70, 0xca, 0xa1, - 0xc6, 0x39, 0x39, 0x4f, 0x81, 0x3c, 0x6c, 0xb7, 0xcd, 0xc3, 0x71, 0x53, 0x45, 0x4c, 0x67, 0x8e, 0xa0, 0x37, 0xe9, - 0x2b, 0x8a, 0x30, 0x53, 0xe1, 0xc2, 0xf4, 0x53, 0x96, 0xb2, 0xd4, 0xe8, 0x74, 0x91, 0x55, 0x39, 0x60, 0xe9, 0xdb, - 0x89, 0x6f, 0x3c, 0x22, 0x4d, 0xb1, 0xc1, 0xd8, 0x3a, 0xe4, 0x04, 0xb1, 0x0c, 0x1f, 0x8e, 0xe5, 0xed, 0x25, 0x5e, - 0xe2, 0x39, 0x56, 0xd7, 0xc9, 0x37, 0x6f, 0x82, 0x13, 0x63, 0x7b, 0x1e, 0x6e, 0xb0, 0xd1, 0x46, 0x3e, 0xe4, 0x46, - 0x33, 0x14, 0xb8, 0xaa, 0xc4, 0xac, 0x02, 0x7d, 0x41, 0x97, 0x83, 0xe7, 0xe6, 0x5d, 0x5b, 0x05, 0x6d, 0x02, 0x37, - 0x39, 0x83, 0xa3, 0x76, 0xa7, 0x36, 0x98, 0x7e, 0x3c, 0x17, 0xa4, 0xa7, 0xbe, 0x73, 0x1f, 0x52, 0xbe, 0xb1, 0x40, - 0x35, 0x62, 0x44, 0x0d, 0x1c, 0xe0, 0x65, 0x9f, 0x87, 0xe6, 0x0d, 0x95, 0xbd, 0x57, 0x0b, 0x08, 0xa3, 0x29, 0xe4, - 0xae, 0x00, 0xec, 0x84, 0x21, 0x42, 0x83, 0xa3, 0x13, 0x00, 0x2b, 0xdc, 0xc5, 0xa7, 0xe8, 0x7f, 0x63, 0xbf, 0xbe, - 0x57, 0x71, 0xae, 0xdf, 0x22, 0x4a, 0xd3, 0x14, 0xf9, 0xa3, 0x66, 0x0d, 0x41, 0xa8, 0xb7, 0xe1, 0x66, 0xe9, 0xcf, - 0x7e, 0x80, 0x73, 0x03, 0x6b, 0x2c, 0x89, 0xe1, 0x03, 0x13, 0x4e, 0xd1, 0x86, 0x2b, 0xea, 0xdb, 0x69, 0xb1, 0x70, - 0xee, 0xdf, 0xa8, 0xa8, 0xf7, 0xea, 0xfb, 0xa9, 0xac, 0x7c, 0x22, 0x23, 0x40, 0x9a, 0x9b, 0xa1, 0x23, 0x73, 0x5f, - 0x37, 0x6b, 0xb7, 0x9e, 0xf0, 0x64, 0xb2, 0xf6, 0x20, 0xfd, 0x1e, 0x2f, 0xe5, 0xbf, 0xdf, 0x19, 0xcf, 0xa3, 0x7e, - 0xa3, 0x81, 0x15, 0x45, 0xab, 0x76, 0x34, 0xb1, 0xbe, 0x05, 0x0c, 0x41, 0x20, 0x95, 0x52, 0x3c, 0x21, 0xbf, 0x04, - 0xa3, 0xd2, 0xad, 0xc8, 0xac, 0xcd, 0x09, 0xc3, 0xc2, 0xd3, 0x2d, 0xd0, 0x2b, 0x6e, 0x28, 0xdc, 0x6b, 0x3d, 0xa2, - 0xee, 0x53, 0xe9, 0xbe, 0xce, 0xf8, 0x83, 0xd5, 0x17, 0xa9, 0xde, 0xbe, 0xe7, 0xb7, 0xe5, 0xda, 0xdd, 0xe9, 0x7f, - 0x7d, 0xc8, 0xe7, 0xf6, 0xb4, 0xef, 0xf6, 0x3e, 0x6e, 0xd7, 0x48, 0x3f, 0x5e, 0xb6, 0xf5, 0x29, 0xd6, 0xb5, 0x5b, - 0x54, 0xd9, 0x34, 0x69, 0xb5, 0x89, 0xa7, 0x6c, 0xfc, 0x1b, 0xa2, 0x62, 0x73, 0x88, 0x23, 0xf3, 0xc8, 0xa4, 0x72, - 0xce, 0xcf, 0x7f, 0x59, 0xd8, 0xc3, 0xa9, 0x07, 0x5b, 0x39, 0x97, 0xc6, 0x5a, 0xb1, 0x51, 0x21, 0x52, 0x70, 0xc9, - 0xd6, 0xb8, 0xbb, 0xb0, 0xa4, 0xb1, 0x06, 0x6c, 0xc0, 0x50, 0xb6, 0x83, 0x42, 0x6a, 0xc9, 0xde, 0xd9, 0xf1, 0x7a, - 0x3b, 0x46, 0x7f, 0xb0, 0x95, 0x51, 0xbd, 0xed, 0xc8, 0x52, 0xcb, 0x9a, 0xd7, 0x82, 0x96, 0x39, 0xcf, 0x05, 0x9e, - 0x85, 0x32, 0xfd, 0x42, 0x58, 0x17, 0x52, 0x46, 0xeb, 0x80, 0x14, 0xcc, 0x1a, 0x77, 0x5e, 0x94, 0xa5, 0xfd, 0x55, - 0xbd, 0xb8, 0xd3, 0x55, 0x05, 0xba, 0xad, 0x18, 0x95, 0x78, 0xcb, 0x4f, 0x59, 0x95, 0xd0, 0x26, 0x45, 0x2d, 0xdf, - 0x55, 0xe9, 0xf1, 0xda, 0x59, 0x60, 0xb1, 0x8c, 0x14, 0xb3, 0xf1, 0xc0, 0xe8, 0x67, 0x22, 0xfd, 0x40, 0x7f, 0xaa, - 0x4c, 0x41, 0xb0, 0x71, 0xea, 0x92, 0x7f, 0x8f, 0x04, 0x8a, 0x10, 0x4d, 0xce, 0x05, 0x5a, 0xfa, 0x97, 0x26, 0x1e, - 0x15, 0xe5, 0xe4, 0x0a, 0x46, 0x2b, 0xc3, 0xa3, 0xfc, 0x69, 0xae, 0x2b, 0xf4, 0x3c, 0x51, 0xfb, 0x25, 0xbb, 0xfd, - 0x62, 0xe3, 0x68, 0x5b, 0xcc, 0x6b, 0x1c, 0xd9, 0x3b, 0xf6, 0x58, 0x29, 0x45, 0x6e, 0x9f, 0x7a, 0x60, 0xad, 0x4b, - 0x39, 0xee, 0xea, 0xe1, 0x25, 0xdc, 0x9b, 0xbe, 0x91, 0x83, 0xb2, 0xb8, 0x98, 0xb7, 0xfa, 0x91, 0xfe, 0x10, 0xaf, - 0x28, 0x62, 0xd7, 0x12, 0xf6, 0xe9, 0x25, 0xcd, 0xd7, 0xb4, 0xc8, 0x90, 0xe8, 0xf8, 0x4d, 0x1b, 0xe5, 0x8d, 0x61, - 0xd5, 0x39, 0xb8, 0xdf, 0x29, 0x79, 0x82, 0x9a, 0xc3, 0xcc, 0xb0, 0xb1, 0xba, 0x9a, 0xb7, 0x71, 0x72, 0x4f, 0xab, - 0x0a, 0xf7, 0x5c, 0x40, 0x7b, 0x9b, 0xe5, 0x5b, 0x50, 0x1f, 0x73, 0xd4, 0xba, 0xfd, 0xb4, 0x49, 0xca, 0x99, 0x17, - 0xde, 0xd7, 0xa1, 0xa1, 0xfb, 0x2a, 0x9d, 0xdb, 0x18, 0x19, 0xa7, 0x83, 0xaa, 0x4b, 0x06, 0xe3, 0xfe, 0xd1, 0xba, - 0x61, 0xf1, 0x54, 0x6d, 0xad, 0x95, 0xb3, 0xba, 0x95, 0xfe, 0x79, 0x52, 0xc3, 0xda, 0xe5, 0xbc, 0x1e, 0x06, 0x17, - 0xa7, 0x6a, 0xfe, 0xa9, 0x09, 0x96, 0x19, 0x9c, 0xc3, 0xa6, 0x0c, 0xb9, 0x10, 0xc7, 0x87, 0x79, 0x4f, 0xbd, 0xd4, - 0xda, 0x38, 0x47, 0xc2, 0x22, 0xea, 0xb7, 0x82, 0xa7, 0xb9, 0x7c, 0x63, 0xae, 0x7b, 0xd0, 0xd8, 0x26, 0xc3, 0xbf, - 0x2f, 0xe8, 0x5f, 0x7e, 0x19, 0xbe, 0x42, 0x42, 0x94, 0xb4, 0x97, 0x1c, 0xcd, 0x73, 0xed, 0x51, 0xd8, 0x73, 0x60, - 0x21, 0x5e, 0x71, 0x6f, 0x20, 0x7f, 0xa4, 0x5f, 0xfa, 0xe4, 0x14, 0x87, 0x28, 0xa2, 0x81, 0x70, 0xfe, 0x6d, 0x50, - 0x97, 0xd8, 0xf3, 0x89, 0x74, 0x36, 0x68, 0x1c, 0xd8, 0x0d, 0x10, 0x7a, 0x89, 0x4d, 0xd8, 0x4f, 0x54, 0x1b, 0x0c, - 0xe6, 0xd4, 0x34, 0x3d, 0x36, 0x76, 0x6b, 0x08, 0x14, 0xdf, 0x8d, 0xd1, 0xe6, 0x4e, 0x81, 0xd6, 0xcb, 0xa7, 0x9c, - 0x55, 0x59, 0x75, 0x01, 0x2e, 0x0b, 0xaa, 0xe5, 0x90, 0xab, 0x9f, 0xe8, 0x4e, 0x05, 0xa4, 0x4d, 0xec, 0x7f, 0xc6, - 0xf9, 0xc0, 0xde, 0x1b, 0x3f, 0x38, 0xa2, 0xf5, 0xd9, 0x86, 0x2e, 0x84, 0x59, 0xab, 0x43, 0x4a, 0x59, 0x24, 0x72, - 0xdb, 0x6a, 0x7d, 0x1e, 0x2b, 0xa6, 0xf0, 0xe0, 0xdf, 0x9f, 0x44, 0x1a, 0xd6, 0xaa, 0xe8, 0x22, 0x1a, 0xce, 0xb6, - 0x28, 0xcc, 0xeb, 0xf5, 0x20, 0x7f, 0x35, 0xe5, 0x64, 0x03, 0x77, 0x93, 0x51, 0x3a, 0x7b, 0x91, 0x4a, 0x1c, 0x37, - 0x5d, 0x6e, 0x3b, 0xee, 0x48, 0xb7, 0xd8, 0xed, 0x21, 0xa9, 0x5c, 0x16, 0x6a, 0x6f, 0xda, 0xa0, 0x07, 0x8c, 0xa5, - 0xb7, 0x40, 0x8a, 0x6d, 0x19, 0x20, 0x7b, 0xf8, 0x85, 0xa2, 0x84, 0xa8, 0x8b, 0xb9, 0xc0, 0x78, 0x03, 0x01, 0x51, - 0xf6, 0x3c, 0x0b, 0xb6, 0xb5, 0x3c, 0x9a, 0x23, 0x53, 0x9a, 0xa6, 0xaa, 0x3d, 0x87, 0x5c, 0xd2, 0xc5, 0x94, 0x1b, - 0xed, 0x65, 0xfd, 0x70, 0x19, 0x41, 0xd0, 0xfd, 0x96, 0x67, 0xd5, 0xe8, 0x25, 0x10, 0x96, 0x2b, 0x28, 0x4f, 0xa6, - 0xfb, 0x45, 0x53, 0x9c, 0x79, 0x1a, 0xa4, 0x9a, 0x1b, 0x9e, 0x36, 0x13, 0x16, 0x4e, 0x7c, 0x9b, 0x24, 0xfd, 0x51, - 0x2d, 0xaf, 0xb5, 0xf0, 0x81, 0x7a, 0x70, 0xdb, 0xf0, 0x72, 0x34, 0xef, 0x57, 0x5b, 0x9a, 0x53, 0x7e, 0x99, 0x34, - 0xab, 0x9b, 0x72, 0xcc, 0x6d, 0xcc, 0x7a, 0x89, 0x34, 0xda, 0x94, 0xb7, 0xb1, 0x51, 0x32, 0xab, 0xa4, 0x25, 0x72, - 0xfa, 0x1b, 0x4b, 0xa4, 0x86, 0xc9, 0xa5, 0xc8, 0xc5, 0x5f, 0xc9, 0x42, 0xda, 0x7a, 0x6b, 0x74, 0x27, 0x06, 0x4a, - 0xd7, 0x79, 0x8f, 0x5b, 0xc2, 0xb3, 0x5f, 0x02, 0x40, 0xb3, 0x2a, 0x6f, 0x90, 0x72, 0xb1, 0x0a, 0x67, 0x7e, 0xb6, - 0x45, 0x6f, 0x7b, 0x0e, 0xab, 0x55, 0x42, 0xbf, 0x6f, 0x75, 0x05, 0xdc, 0xc0, 0x3e, 0x0f, 0xeb, 0x83, 0x5d, 0x18, - 0xd5, 0x6b, 0x25, 0x84, 0xd5, 0x04, 0x85, 0xb0, 0x72, 0x25, 0xd9, 0x83, 0x28, 0x42, 0x0f, 0xdc, 0x1d, 0x52, 0x9b, - 0x89, 0x78, 0xbe, 0x86, 0xf0, 0xcf, 0x31, 0x7b, 0xa8, 0xe8, 0x92, 0x01, 0x0a, 0xea, 0x47, 0x40, 0x29, 0x64, 0x04, - 0x10, 0x90, 0x90, 0x17, 0x21, 0x98, 0x7a, 0x42, 0xe9, 0x26, 0x38, 0xd2, 0xff, 0xd1, 0x0b, 0x95, 0x95, 0x30, 0x23, - 0x3e, 0xa3, 0x60, 0x14, 0x06, 0x1c, 0xdf, 0x9d, 0x50, 0x78, 0xd4, 0x3c, 0x55, 0x43, 0x7e, 0x7d, 0x78, 0x4f, 0x2f, - 0xb6, 0xd1, 0xbe, 0x50, 0x1f, 0x40, 0x97, 0xba, 0xca, 0x0b, 0x3a, 0x0d, 0x52, 0x45, 0x03, 0x14, 0x21, 0xbc, 0x74, - 0x43, 0x31, 0xc0, 0x0c, 0x8d, 0xcd, 0xc9, 0xc8, 0x8a, 0x2e, 0x6e, 0xba, 0x19, 0x88, 0xbc, 0x70, 0x8e, 0x8d, 0xea, - 0x78, 0xfa, 0x4f, 0xd5, 0xdc, 0x4c, 0x83, 0xb4, 0xc6, 0xd9, 0xd4, 0xa9, 0xcd, 0x10, 0x33, 0x11, 0x71, 0x51, 0xad, - 0x4b, 0xee, 0x25, 0x34, 0x87, 0x5d, 0x78, 0xef, 0x13, 0x6f, 0x29, 0xa5, 0x70, 0x66, 0x75, 0xb6, 0xdb, 0x02, 0x2d, - 0xe9, 0x3c, 0x7b, 0xea, 0x1d, 0x2e, 0x32, 0x15, 0x11, 0xfe, 0x6c, 0x63, 0x32, 0x51, 0x8a, 0xf4, 0x0c, 0xb5, 0x5c, - 0x70, 0x94, 0xec, 0x2a, 0x64, 0xfa, 0x2f, 0x9c, 0xb2, 0x03, 0xd0, 0xb6, 0x9b, 0xf0, 0x6e, 0x72, 0xc7, 0x37, 0xde, - 0xdf, 0xab, 0xbd, 0x2b, 0x36, 0xb5, 0x6b, 0x1c, 0x62, 0x7a, 0xf7, 0x14, 0x7b, 0x40, 0xa0, 0xa2, 0xc5, 0x12, 0x1a, - 0x7b, 0x6e, 0x5e, 0x1e, 0x8f, 0x93, 0x15, 0x25, 0x67, 0x9f, 0xeb, 0x8b, 0x85, 0x6d, 0x3a, 0xf1, 0xd2, 0xed, 0x95, - 0xc3, 0x02, 0x3d, 0x8c, 0x40, 0x38, 0x85, 0x19, 0x4d, 0x80, 0x4e, 0x8f, 0x3b, 0x23, 0x41, 0x39, 0xf5, 0x15, 0x03, - 0x26, 0x90, 0xc7, 0x6a, 0xdc, 0x14, 0x2e, 0x21, 0x67, 0x7b, 0xac, 0x88, 0x91, 0x06, 0x63, 0xfb, 0x3a, 0x28, 0x1c, - 0xa0, 0x13, 0x67, 0x7b, 0xa0, 0xae, 0x13, 0xef, 0x15, 0x79, 0x4d, 0xac, 0x35, 0xde, 0xb7, 0xa6, 0x38, 0x9d, 0x94, - 0xaf, 0x25, 0x9a, 0x23, 0x9a, 0xd3, 0x16, 0xf9, 0x03, 0x58, 0x79, 0xac, 0xbf, 0xb2, 0xba, 0x2f, 0x67, 0xac, 0xbf, - 0x30, 0xb2, 0xe4, 0x36, 0x42, 0x37, 0x1c, 0xac, 0x55, 0x10, 0xed, 0xc1, 0xd6, 0x62, 0xed, 0x08, 0xcb, 0x66, 0x6f, - 0x6b, 0x01, 0xee, 0xb4, 0xe7, 0x22, 0x0a, 0x17, 0x2b, 0xf0, 0x9e, 0xae, 0x21, 0xaf, 0xc4, 0x19, 0xfd, 0x23, 0x9c, - 0x98, 0x83, 0x04, 0xb1, 0x81, 0x1e, 0x95, 0xf5, 0x1f, 0x86, 0xc8, 0xe8, 0x74, 0x33, 0x1a, 0xbb, 0x7c, 0x69, 0xb4, - 0x6a, 0x05, 0x30, 0xa8, 0x6f, 0xf3, 0x78, 0x58, 0xc6, 0x8b, 0x39, 0x0e, 0x6d, 0x6b, 0xdf, 0x78, 0x94, 0x59, 0x78, - 0xff, 0x09, 0x4c, 0x6b, 0xb8, 0x2d, 0xf2, 0x7f, 0x2f, 0xcb, 0x4b, 0x79, 0xb6, 0x2b, 0xe7, 0xe9, 0xbd, 0xdf, 0xab, - 0x3c, 0xbb, 0x3b, 0xbd, 0xb7, 0xd8, 0xe4, 0x81, 0x71, 0x31, 0x47, 0xc0, 0x69, 0xeb, 0xc3, 0xbb, 0xef, 0x5e, 0x1f, - 0xbc, 0xa7, 0x2f, 0x7a, 0xcb, 0x6f, 0x64, 0xd3, 0x87, 0xe1, 0x14, 0x4f, 0xf1, 0xf3, 0x25, 0xef, 0x5a, 0xff, 0x35, - 0xdb, 0x6c, 0xce, 0x6b, 0xef, 0x94, 0xeb, 0x16, 0x57, 0x0d, 0xed, 0xcf, 0xdb, 0x6a, 0x0a, 0x9c, 0x6c, 0x02, 0x45, - 0x7c, 0xdd, 0x15, 0xa7, 0xac, 0x34, 0x80, 0x40, 0xb8, 0x3e, 0xfd, 0x9b, 0x6f, 0x8c, 0x52, 0xd9, 0xe0, 0xed, 0xa7, - 0xe5, 0x27, 0xa3, 0xc3, 0x23, 0x82, 0x0b, 0xd9, 0x7a, 0xa4, 0x7f, 0xe7, 0xe9, 0xce, 0xd7, 0xf3, 0x3c, 0xaa, 0x41, - 0x05, 0x64, 0xa9, 0xc6, 0x99, 0x0d, 0xe2, 0x98, 0xbb, 0xcd, 0x55, 0x4b, 0xc2, 0x37, 0x0b, 0x16, 0xdd, 0x75, 0xc0, - 0x91, 0x17, 0xcc, 0x31, 0x44, 0x70, 0xf8, 0xde, 0x32, 0xca, 0x77, 0xdc, 0x89, 0x1d, 0x0f, 0xc2, 0x22, 0x2c, 0xcf, - 0x5a, 0xd1, 0xb0, 0xfa, 0x81, 0x37, 0x7b, 0xf9, 0xff, 0xda, 0x50, 0xad, 0x17, 0x51, 0x95, 0x6c, 0x2d, 0x04, 0x58, - 0x17, 0xdb, 0x3c, 0x7e, 0x8a, 0x37, 0x76, 0xad, 0x91, 0xc4, 0xc3, 0x73, 0xf7, 0xd3, 0x3d, 0x41, 0x39, 0xce, 0xcf, - 0x3b, 0xbc, 0x46, 0x74, 0x06, 0xf1, 0x11, 0x78, 0x2f, 0xd7, 0x36, 0x28, 0xf8, 0xff, 0xfc, 0x57, 0x97, 0xb1, 0x5a, - 0xd6, 0x03, 0x56, 0x37, 0xfc, 0xb4, 0x0d, 0xde, 0xba, 0xbf, 0x9d, 0x6f, 0xe8, 0xd3, 0xb8, 0xde, 0x63, 0xad, 0xde, - 0x59, 0x97, 0xd6, 0x8c, 0x4e, 0xc2, 0x32, 0x8b, 0xb9, 0x12, 0xb2, 0x9e, 0x6b, 0xf3, 0x48, 0x86, 0x0f, 0x6b, 0xdb, - 0x96, 0x92, 0x83, 0x36, 0x0e, 0x4d, 0xb9, 0xa4, 0x42, 0xda, 0x54, 0x46, 0xff, 0x66, 0xaa, 0x28, 0x99, 0xf5, 0x74, - 0xf6, 0x2c, 0xba, 0x61, 0xa1, 0x4f, 0x81, 0x0c, 0x3c, 0xaf, 0x83, 0xaa, 0x25, 0x69, 0x2a, 0x44, 0x46, 0xa8, 0xa6, - 0x01, 0x6a, 0x9f, 0x54, 0x35, 0x14, 0x9e, 0xeb, 0x39, 0x1d, 0xfc, 0xc2, 0x47, 0x22, 0x48, 0x46, 0x12, 0x47, 0x0d, - 0x32, 0x65, 0x6f, 0xd7, 0xba, 0x57, 0xd7, 0xe9, 0xa9, 0xd3, 0x9c, 0x6d, 0x3e, 0xf2, 0xbf, 0x72, 0x73, 0x52, 0x2c, - 0xb6, 0x11, 0x88, 0x0b, 0x79, 0x8b, 0x29, 0xdb, 0x63, 0xc3, 0x30, 0xa8, 0xe3, 0xd7, 0x9b, 0x36, 0x6e, 0xa3, 0x04, - 0x11, 0xad, 0xe3, 0x93, 0x66, 0x8d, 0x8b, 0xaf, 0x5b, 0xe6, 0x9b, 0xcb, 0xaf, 0xd7, 0x38, 0xaa, 0xf5, 0xd9, 0x4e, - 0x95, 0x9b, 0x6b, 0x71, 0x54, 0x9b, 0xc6, 0x24, 0x3d, 0x21, 0x5b, 0x5e, 0xa0, 0x4d, 0xb9, 0xc9, 0x78, 0x83, 0xd2, - 0x40, 0xea, 0x05, 0xf3, 0x70, 0xb4, 0x33, 0x4f, 0xc7, 0xb7, 0x13, 0x2b, 0x67, 0x13, 0x5d, 0xda, 0x4d, 0xad, 0x85, - 0xf0, 0x78, 0x31, 0xe6, 0x35, 0x87, 0x7c, 0x56, 0x71, 0xe6, 0x7a, 0x1e, 0x4a, 0x8a, 0x30, 0xe1, 0xda, 0x2c, 0xd1, - 0x9b, 0x9b, 0x10, 0x16, 0x4b, 0x4e, 0x17, 0x08, 0x1d, 0x24, 0xcd, 0x77, 0xb4, 0xcf, 0x57, 0x7a, 0x78, 0x7e, 0x7f, - 0x4a, 0xb4, 0xdd, 0x3c, 0xe9, 0xec, 0xf3, 0xbb, 0x67, 0x1a, 0x75, 0xab, 0x54, 0xdb, 0x2a, 0x8a, 0x59, 0x23, 0x01, - 0x57, 0xeb, 0x08, 0xf4, 0xaa, 0x96, 0x3d, 0xd4, 0xd2, 0x47, 0xdd, 0xd5, 0x51, 0xab, 0xe7, 0xa2, 0xd6, 0x3e, 0x95, - 0x2e, 0xcf, 0x37, 0x8d, 0xc2, 0x90, 0x8b, 0xa2, 0x18, 0xa5, 0xa7, 0xdd, 0xb5, 0xf9, 0x32, 0x37, 0xa0, 0x99, 0x7b, - 0x07, 0xb5, 0x3c, 0x0f, 0xa8, 0xe7, 0xc6, 0xff, 0xa9, 0xd8, 0xf2, 0x18, 0x11, 0xaa, 0x3c, 0x9b, 0xa7, 0x15, 0x88, - 0xea, 0xda, 0x92, 0x6f, 0x8c, 0x64, 0xff, 0xf0, 0x8f, 0x7a, 0x3f, 0x4e, 0x4e, 0xe5, 0xef, 0xc0, 0x1d, 0x7d, 0x10, - 0xf7, 0x90, 0xc2, 0x55, 0xbc, 0xe6, 0x2e, 0xb7, 0xc8, 0x34, 0xf8, 0xff, 0xf8, 0xa5, 0x1b, 0x60, 0xe7, 0x78, 0x39, - 0x89, 0xe8, 0x5d, 0x09, 0x4a, 0xda, 0x94, 0xe1, 0x9a, 0x13, 0x0c, 0xf0, 0x7b, 0xdd, 0x31, 0xe5, 0xbc, 0xb1, 0x1c, - 0xc5, 0x52, 0x03, 0x3e, 0x54, 0xf9, 0x84, 0xf6, 0x8f, 0xed, 0x25, 0xbb, 0xba, 0x3c, 0xb6, 0x8d, 0xb3, 0xd4, 0xa6, - 0x65, 0xfb, 0x48, 0x34, 0x82, 0xea, 0x25, 0x81, 0x25, 0xb5, 0xcb, 0xaf, 0x6c, 0xab, 0x50, 0x36, 0x9b, 0xe0, 0xb2, - 0xf6, 0xe6, 0xae, 0x2c, 0x46, 0x9a, 0x65, 0xec, 0x3b, 0xcc, 0x76, 0x63, 0xed, 0xf4, 0x08, 0x09, 0xd5, 0xd3, 0x8a, - 0x65, 0xe9, 0x0b, 0xb1, 0xa7, 0x9f, 0x8f, 0xfa, 0xa9, 0x3d, 0x05, 0x00, 0x30, 0x5a, 0xef, 0x51, 0xc9, 0x0e, 0xae, - 0xdb, 0x20, 0xc0, 0x07, 0x7a, 0x7d, 0x03, 0xa0, 0x39, 0x9e, 0xdd, 0x16, 0x2c, 0xc5, 0x4f, 0xe2, 0x23, 0xf3, 0xb0, - 0xb3, 0x0c, 0x26, 0x70, 0x6b, 0xd6, 0x01, 0xa7, 0x6b, 0x37, 0x36, 0x6d, 0x9c, 0xac, 0xb3, 0xe9, 0xeb, 0x72, 0x0a, - 0x88, 0xe7, 0x6e, 0xdc, 0x1e, 0xa6, 0x8d, 0xab, 0x3b, 0x86, 0xf4, 0x29, 0x5a, 0xd6, 0x1d, 0x3f, 0x23, 0x0a, 0xab, - 0x22, 0xcb, 0x72, 0x86, 0xbd, 0x62, 0x9a, 0xa8, 0x79, 0xcb, 0xad, 0x82, 0x9c, 0x15, 0x60, 0xed, 0xf5, 0x7a, 0x40, - 0x38, 0xb5, 0x1e, 0x7c, 0xfb, 0x3f, 0x75, 0xd4, 0x77, 0xeb, 0xb8, 0x0b, 0xe7, 0x46, 0x0b, 0xcf, 0x53, 0x88, 0xb2, - 0x3c, 0x20, 0xb3, 0xe5, 0xaf, 0xff, 0xf2, 0x94, 0x7c, 0xd2, 0xee, 0xf6, 0x6f, 0xe8, 0xd6, 0x4f, 0x00, 0xc7, 0x36, - 0x3b, 0x40, 0x37, 0x48, 0x75, 0x83, 0x08, 0xda, 0xef, 0x19, 0xe8, 0x66, 0xa0, 0x8c, 0x8a, 0x89, 0xcf, 0x1b, 0xdd, - 0x55, 0x00, 0xfa, 0xfe, 0x9c, 0x6d, 0x71, 0xee, 0xb3, 0x20, 0x6f, 0xc1, 0xaa, 0xd9, 0x1f, 0x05, 0x86, 0x6b, 0xfb, - 0x81, 0x33, 0x08, 0xea, 0x5a, 0x07, 0x4a, 0xbb, 0xdc, 0x3e, 0x5a, 0x01, 0x88, 0x58, 0x58, 0x13, 0x36, 0x51, 0xfd, - 0x97, 0x48, 0x97, 0x34, 0x24, 0x61, 0xa6, 0xfa, 0x89, 0xd8, 0xb3, 0x96, 0x18, 0x56, 0x7a, 0x80, 0x4d, 0x9c, 0x07, - 0x74, 0x83, 0x28, 0x5e, 0x87, 0x06, 0xff, 0x4e, 0x58, 0x90, 0xf7, 0x94, 0xfa, 0xcc, 0x50, 0xd5, 0xa5, 0xb0, 0xe6, - 0x51, 0xaa, 0xc1, 0xf0, 0x1c, 0xda, 0x00, 0x6b, 0x29, 0x6a, 0x6e, 0xbb, 0x24, 0x95, 0x20, 0xf1, 0xc6, 0xd4, 0x77, - 0x33, 0xe0, 0xdd, 0xac, 0x0c, 0xa0, 0x40, 0x52, 0x5f, 0x50, 0xf4, 0xe6, 0xd1, 0x77, 0x6b, 0xc2, 0xb3, 0xd3, 0xdd, - 0x88, 0x49, 0xb2, 0xae, 0xb6, 0x10, 0x11, 0x8b, 0x68, 0xdb, 0x56, 0x85, 0xa1, 0x03, 0x99, 0xe8, 0x51, 0x95, 0xa4, - 0x04, 0xff, 0xcd, 0xd8, 0x2e, 0x46, 0xd4, 0x30, 0xa0, 0xa0, 0x60, 0x6f, 0x8f, 0xdb, 0x85, 0x2f, 0x6f, 0x69, 0xcc, - 0x2d, 0x05, 0x5e, 0x85, 0xc6, 0xc3, 0x3a, 0x90, 0x2b, 0xa2, 0x41, 0xe7, 0x5c, 0x3b, 0xe3, 0xe4, 0xb8, 0x99, 0xf9, - 0x12, 0xcf, 0x9f, 0x5b, 0xfb, 0x7d, 0xa5, 0x14, 0xf9, 0x37, 0x28, 0x24, 0x9c, 0x5a, 0x55, 0xa3, 0xaa, 0x0f, 0x60, - 0x4d, 0xd7, 0x04, 0x77, 0xc6, 0xb3, 0x4f, 0x08, 0x24, 0x3f, 0xe5, 0x52, 0x67, 0x93, 0x36, 0x02, 0xa3, 0x2f, 0xc1, - 0xe4, 0x85, 0xe9, 0x6a, 0x01, 0x71, 0x78, 0xa0, 0x3f, 0x26, 0x8a, 0xe4, 0xa9, 0x22, 0x0a, 0x6a, 0x78, 0xaa, 0x32, - 0x5f, 0x2f, 0xf5, 0x3a, 0xb9, 0xd1, 0xd9, 0x13, 0x8f, 0x69, 0x9b, 0x9a, 0x21, 0x9b, 0xc9, 0x8b, 0xfb, 0xe1, 0xba, - 0x7b, 0x75, 0x1f, 0x14, 0x12, 0x27, 0x37, 0x0d, 0x90, 0xb7, 0xea, 0x44, 0x9e, 0x16, 0x24, 0x80, 0xe5, 0xd2, 0x34, - 0x6b, 0xbf, 0x3c, 0x9a, 0x20, 0x84, 0xcf, 0x86, 0xbd, 0x71, 0x5c, 0x34, 0x4d, 0x27, 0x06, 0x0e, 0x97, 0x37, 0x39, - 0x9e, 0x19, 0x99, 0xad, 0x3b, 0xdf, 0x34, 0x26, 0x1a, 0xba, 0x6a, 0x57, 0x86, 0xc9, 0x1b, 0xa7, 0x5b, 0xee, 0xd4, - 0xee, 0x42, 0x19, 0x5c, 0xa4, 0xcb, 0xa6, 0x6c, 0x04, 0x20, 0xba, 0x76, 0x68, 0x94, 0x27, 0x47, 0x61, 0x42, 0x73, - 0x5b, 0x83, 0x17, 0x40, 0xdb, 0x3f, 0xea, 0x46, 0xa9, 0x17, 0x22, 0x2b, 0x3c, 0xfe, 0x68, 0x23, 0xd7, 0xcb, 0xad, - 0x53, 0xe5, 0xe5, 0x3a, 0x6a, 0xe7, 0xe5, 0xd6, 0xad, 0x66, 0xa5, 0xa9, 0x4d, 0xd8, 0x08, 0x6c, 0x2f, 0xbd, 0xe4, - 0x19, 0x7a, 0xfa, 0x19, 0x7a, 0xc6, 0x36, 0x2f, 0x44, 0x4c, 0xd9, 0xfa, 0x95, 0x57, 0xa4, 0x75, 0x60, 0xff, 0xb3, - 0x7f, 0xdf, 0x40, 0x64, 0x2a, 0x56, 0xbb, 0x4a, 0xc4, 0x14, 0xc8, 0x5a, 0xa1, 0x7e, 0x64, 0x1f, 0xb4, 0xff, 0xda, - 0xfb, 0xed, 0x7d, 0x6e, 0x2a, 0x9a, 0x0c, 0xf8, 0xfd, 0x09, 0x33, 0xcd, 0x31, 0xc4, 0x12, 0x33, 0xba, 0x1f, 0x5d, - 0x47, 0x0e, 0xa6, 0xdf, 0x95, 0x12, 0xff, 0xc9, 0x5d, 0x6d, 0xb7, 0x9c, 0x89, 0x38, 0x22, 0xee, 0x76, 0x40, 0x37, - 0x41, 0x7c, 0x7d, 0xfc, 0xb2, 0x06, 0x97, 0xb9, 0xda, 0x17, 0x59, 0xc8, 0xf0, 0xfa, 0x83, 0x87, 0xec, 0x33, 0xef, - 0xb2, 0x53, 0x73, 0x86, 0x6b, 0x0b, 0xd7, 0x83, 0xe2, 0xcd, 0xcc, 0xaf, 0x03, 0x2f, 0x2a, 0xee, 0x54, 0x67, 0x2f, - 0xaa, 0xf1, 0x10, 0x1a, 0xcf, 0x02, 0xf7, 0x68, 0x9d, 0xd2, 0xbf, 0x66, 0x21, 0x3e, 0x9b, 0xbc, 0xb1, 0x99, 0xc7, - 0xdc, 0xcd, 0x1c, 0x82, 0x94, 0x9f, 0xe4, 0x52, 0x85, 0x91, 0x85, 0x74, 0xd3, 0x92, 0x55, 0xc2, 0x5b, 0xbc, 0x33, - 0x8f, 0xbb, 0x3f, 0x97, 0x78, 0x07, 0xf5, 0x8a, 0xf0, 0x22, 0xb3, 0x27, 0xd7, 0x31, 0x0c, 0xcc, 0x12, 0x2e, 0x64, - 0x0e, 0x8d, 0xd4, 0xdb, 0x5b, 0x3c, 0x71, 0x41, 0xf5, 0x63, 0x78, 0xe7, 0x5d, 0x76, 0x59, 0xc9, 0xed, 0xe1, 0x63, - 0x3d, 0x39, 0x4b, 0xdc, 0x0b, 0x66, 0xce, 0xad, 0xc7, 0x7d, 0x75, 0x26, 0x69, 0x76, 0xe4, 0x22, 0x41, 0x63, 0x01, - 0x2b, 0x31, 0x94, 0x9e, 0xde, 0x71, 0x3c, 0xbb, 0x23, 0xc0, 0x0f, 0x8e, 0xf5, 0x6d, 0x4d, 0xd9, 0x78, 0x72, 0x76, - 0xbd, 0x0d, 0xdc, 0x97, 0x5d, 0xf7, 0x2e, 0x46, 0xa9, 0xba, 0xa1, 0x89, 0x6b, 0x33, 0x10, 0xd8, 0xdd, 0x54, 0x3c, - 0x85, 0xa3, 0xe9, 0xc6, 0xf7, 0x4d, 0x5d, 0x9b, 0x8e, 0x02, 0xd2, 0x2e, 0x01, 0xad, 0x6d, 0xbf, 0xb8, 0xa1, 0x7b, - 0x04, 0xc3, 0x26, 0xc4, 0xc8, 0xe6, 0x6a, 0x3f, 0xac, 0xc7, 0x76, 0xdc, 0xd0, 0x51, 0x67, 0x19, 0x3e, 0x73, 0xd9, - 0x01, 0x7d, 0x26, 0x2f, 0xf4, 0x5d, 0x6c, 0x88, 0x4e, 0xb0, 0xee, 0xd8, 0xe0, 0x93, 0x80, 0x38, 0xbf, 0xf1, 0x0e, - 0x17, 0x70, 0xb9, 0xc0, 0x12, 0xc0, 0xfa, 0xec, 0xc4, 0xe0, 0x99, 0xbe, 0x8b, 0x5d, 0xc7, 0xb9, 0x27, 0xdc, 0x55, - 0x28, 0x05, 0x2e, 0xcd, 0x4f, 0x21, 0x4f, 0x5e, 0xe8, 0x5e, 0x3f, 0x9f, 0x25, 0xa6, 0xee, 0x62, 0x6b, 0x7d, 0xd8, - 0x94, 0x0a, 0x98, 0xfb, 0x94, 0x4e, 0xad, 0x83, 0xe2, 0xed, 0x13, 0x5a, 0x20, 0x0c, 0x63, 0x7b, 0xff, 0xaa, 0x89, - 0x61, 0x3c, 0x8d, 0x67, 0x0e, 0x82, 0x81, 0x11, 0x61, 0x80, 0x2f, 0xf1, 0x5e, 0x4e, 0x48, 0x9e, 0xa0, 0x99, 0x7d, - 0x36, 0x52, 0xec, 0x5d, 0x9e, 0xf4, 0xf5, 0xee, 0x4c, 0x66, 0x8f, 0x0f, 0xef, 0x02, 0x5a, 0xef, 0xc6, 0x4b, 0x0d, - 0x8f, 0x65, 0xed, 0x72, 0x25, 0x96, 0x42, 0xbc, 0x76, 0xd1, 0xfa, 0x6f, 0xda, 0xe4, 0xb0, 0x45, 0x33, 0x18, 0xf9, - 0x4e, 0x5f, 0x9a, 0x63, 0x79, 0x47, 0x5e, 0xd8, 0x48, 0x35, 0x80, 0xe2, 0xca, 0x20, 0xc3, 0x90, 0xb5, 0x77, 0x58, - 0x44, 0x41, 0x61, 0xe8, 0x8a, 0x47, 0x7d, 0x4a, 0x44, 0x9d, 0x04, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xae, 0x0c, 0x4e, - 0x01, 0xb5, 0xe2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x1a, 0x76, 0x26, 0xee, 0x2a, 0xb0, 0x3c, 0xe5, 0x83, 0x5d, 0x5c, - 0x60, 0xe2, 0xbf, 0xee, 0xf5, 0x89, 0x81, 0x23, 0xdd, 0x8d, 0xb0, 0x05, 0x30, 0x0d, 0x76, 0xe5, 0x95, 0xbc, 0xe4, - 0xa9, 0xd7, 0x10, 0x9c, 0x5c, 0x6d, 0x5e, 0x9f, 0xcc, 0xfa, 0x12, 0x84, 0x52, 0xaa, 0x11, 0x76, 0x0b, 0xec, 0xda, - 0x72, 0xb6, 0xae, 0x4e, 0x26, 0x6a, 0xdb, 0xc8, 0xb8, 0x61, 0x3f, 0x63, 0xed, 0x22, 0x76, 0x7d, 0xbc, 0xd8, 0x85, - 0x6c, 0x2a, 0x76, 0x2e, 0x4c, 0x8a, 0x9c, 0x41, 0x07, 0x0e, 0xb5, 0xc3, 0x19, 0x31, 0xd3, 0xed, 0x74, 0xc9, 0x76, - 0xfa, 0xe0, 0x9d, 0x76, 0x4e, 0x05, 0x74, 0x06, 0xe3, 0xec, 0xd4, 0x4e, 0x1a, 0xa1, 0x0b, 0x8c, 0xef, 0x4a, 0xe8, - 0x17, 0xb3, 0x54, 0xc3, 0x6b, 0xd6, 0x80, 0xb4, 0x92, 0x0a, 0xe6, 0xd9, 0x8a, 0x2d, 0x29, 0xdc, 0xe6, 0xc5, 0xd6, - 0xe2, 0x7f, 0xe9, 0x47, 0xba, 0x2e, 0x0f, 0x88, 0x20, 0x1b, 0x88, 0xd2, 0x49, 0xf0, 0x9f, 0xc5, 0x0c, 0x7f, 0x6e, - 0x60, 0xf4, 0x32, 0xb3, 0x78, 0x9a, 0xe5, 0xa8, 0x19, 0xdf, 0x19, 0xfe, 0x54, 0x46, 0xf2, 0x93, 0x2c, 0x27, 0xf0, - 0xbe, 0x0e, 0x01, 0x8e, 0x4c, 0xed, 0xe7, 0x2c, 0x67, 0xbc, 0x82, 0x96, 0x8d, 0xa2, 0x43, 0x14, 0xf5, 0xba, 0x7e, - 0xee, 0xc3, 0xe2, 0x9c, 0x50, 0x82, 0x91, 0x4d, 0x2f, 0xa1, 0x10, 0xa2, 0xf7, 0xcd, 0xb1, 0x18, 0x99, 0xbf, 0x28, - 0xe1, 0x04, 0x0b, 0x39, 0xd0, 0xbd, 0x2a, 0x20, 0x1d, 0x9f, 0x08, 0x0d, 0x13, 0x73, 0xb6, 0x91, 0xa9, 0xce, 0x26, - 0x16, 0xd2, 0x59, 0x71, 0xcd, 0xb1, 0x94, 0x56, 0x73, 0xe5, 0x75, 0x19, 0x75, 0x27, 0xe5, 0x97, 0xd0, 0xf4, 0x7a, - 0xcb, 0x59, 0x8c, 0x2a, 0xfc, 0xa7, 0xc3, 0x84, 0x6f, 0xd0, 0x2e, 0x2c, 0x67, 0x1d, 0x22, 0x54, 0xc1, 0x03, 0x5d, - 0x93, 0xbe, 0x8e, 0x56, 0xc3, 0x08, 0xcd, 0xdd, 0x0a, 0x0a, 0x84, 0xb4, 0x3f, 0xb0, 0xa8, 0x6d, 0xac, 0x9a, 0xb3, - 0x77, 0x47, 0x3b, 0x58, 0x35, 0x98, 0x9f, 0x1c, 0x05, 0xac, 0xba, 0x91, 0x70, 0xb1, 0xfc, 0x95, 0xc3, 0x43, 0x56, - 0x70, 0xf3, 0x01, 0xdc, 0x7e, 0x00, 0xe3, 0x98, 0xf1, 0x91, 0x3d, 0x69, 0x01, 0xc3, 0x99, 0xeb, 0x01, 0xef, 0x8d, - 0x53, 0x6f, 0xa4, 0xd1, 0x81, 0xa3, 0xab, 0xe5, 0x25, 0x7e, 0x28, 0x22, 0xc3, 0xaf, 0x49, 0x54, 0xd7, 0x34, 0x83, - 0x3c, 0x95, 0xd2, 0xe4, 0xd8, 0x1d, 0x50, 0x00, 0x7b, 0x1f, 0xe8, 0x98, 0xb6, 0x31, 0x93, 0xeb, 0x29, 0xba, 0x24, - 0xcd, 0xeb, 0x79, 0x68, 0x3f, 0x62, 0x9d, 0x11, 0x50, 0x8e, 0xed, 0x01, 0xf3, 0x5d, 0x03, 0x54, 0x2d, 0xcc, 0xf9, - 0x6f, 0x6a, 0x6b, 0x73, 0xe8, 0x58, 0x3d, 0x20, 0x2c, 0xf9, 0xf5, 0x51, 0x0b, 0xf2, 0xfb, 0x58, 0xe1, 0xb0, 0x45, - 0xfb, 0x62, 0x47, 0xaa, 0x0e, 0x6a, 0x85, 0xc1, 0x45, 0xa5, 0xca, 0xd4, 0x11, 0xc3, 0x0b, 0xb2, 0x49, 0x28, 0x14, - 0x1a, 0xc7, 0x13, 0x1b, 0xd0, 0xec, 0x8f, 0x58, 0x4a, 0xbb, 0x4b, 0x7e, 0xcd, 0x04, 0x91, 0xe6, 0xa5, 0xbf, 0xdb, - 0xe1, 0xa2, 0x0e, 0x17, 0xaf, 0x79, 0xa3, 0xe7, 0xb4, 0x09, 0xcd, 0x16, 0x63, 0xbc, 0x52, 0x6d, 0x82, 0xec, 0x4e, - 0xf3, 0xe8, 0x68, 0xc7, 0x16, 0x85, 0x24, 0x64, 0x7f, 0x79, 0x6d, 0x26, 0x47, 0x15, 0xfd, 0xbb, 0xc8, 0x59, 0x96, - 0x12, 0xe2, 0x1d, 0xf8, 0x45, 0x4f, 0xb9, 0x92, 0x46, 0xa7, 0xba, 0x23, 0xba, 0xa0, 0xa8, 0x7f, 0x76, 0x34, 0x0c, - 0xb3, 0x3c, 0x19, 0x54, 0xc1, 0x01, 0x8c, 0xd9, 0xe8, 0xa3, 0xeb, 0x85, 0x4b, 0x31, 0x98, 0xf2, 0xb0, 0x6a, 0xb3, - 0xb6, 0x61, 0xea, 0xc6, 0xb8, 0x30, 0x5c, 0x33, 0xb6, 0x31, 0x01, 0x18, 0xdb, 0x34, 0xdb, 0x4c, 0x9b, 0xfe, 0xfe, - 0xa9, 0xb0, 0x7a, 0x48, 0x24, 0x22, 0x90, 0x0f, 0xa2, 0x0f, 0x06, 0xa4, 0x7f, 0x5d, 0xa4, 0x60, 0x74, 0xa9, 0x15, - 0x3f, 0x89, 0x15, 0x1d, 0xf0, 0x9b, 0x8d, 0x77, 0x68, 0x18, 0x73, 0xde, 0x29, 0xc6, 0x5c, 0x9e, 0x82, 0x1d, 0x76, - 0x0e, 0xc2, 0x93, 0x2a, 0x46, 0xdb, 0x93, 0x58, 0x41, 0xd3, 0xf3, 0x05, 0xac, 0x6f, 0x12, 0x56, 0x63, 0x98, 0x56, - 0x33, 0x37, 0xc5, 0x5d, 0x2e, 0x3c, 0x66, 0x4d, 0xd6, 0x82, 0xf8, 0x20, 0x10, 0x59, 0x26, 0x41, 0x04, 0x3d, 0x16, - 0xde, 0x93, 0x99, 0x57, 0xc8, 0xd2, 0x0d, 0xba, 0x8c, 0x8c, 0xfb, 0xc0, 0x86, 0xfa, 0x41, 0xfd, 0xa0, 0x85, 0x74, - 0xa1, 0xf9, 0x6b, 0x54, 0xd5, 0x32, 0xcf, 0x71, 0xa3, 0x1c, 0x5a, 0x72, 0x6e, 0x8e, 0x40, 0x0b, 0x81, 0x50, 0x7b, - 0x35, 0x37, 0xc0, 0x58, 0x7e, 0x08, 0x87, 0x9c, 0x03, 0x40, 0x67, 0x31, 0xe1, 0xf1, 0x6d, 0x1b, 0x20, 0xb5, 0x71, - 0xf4, 0xa4, 0x6e, 0xed, 0xa6, 0xc9, 0x10, 0x41, 0x24, 0xbe, 0x1d, 0x03, 0xeb, 0xe7, 0xf9, 0x77, 0x11, 0x9d, 0x60, - 0xe8, 0xc7, 0xe2, 0x2e, 0x7f, 0x34, 0xf4, 0x54, 0x7f, 0x3e, 0x55, 0x4f, 0x62, 0xc4, 0x52, 0xc4, 0x8f, 0x79, 0x6d, - 0x2e, 0xa0, 0x14, 0xa5, 0xd9, 0x04, 0x46, 0x39, 0xd2, 0xe3, 0x4a, 0x92, 0x47, 0xa2, 0x81, 0x18, 0x44, 0xa3, 0xe2, - 0x9b, 0x2b, 0x5d, 0x3b, 0x87, 0xab, 0x78, 0xe5, 0xb1, 0xae, 0x97, 0xc7, 0xeb, 0x99, 0x9d, 0x7a, 0x2f, 0x07, 0xeb, - 0xd4, 0x3b, 0x2f, 0x44, 0x4b, 0x57, 0xc4, 0xe8, 0xf4, 0x13, 0x51, 0xab, 0x76, 0xbd, 0x6b, 0x04, 0x22, 0x09, 0x97, - 0xff, 0x19, 0x02, 0xb5, 0xf0, 0xe1, 0xd2, 0xb3, 0xc3, 0x62, 0x6e, 0x74, 0xf9, 0xa6, 0x19, 0x94, 0x02, 0x1e, 0xd4, - 0xea, 0xb8, 0x86, 0xe8, 0xdc, 0x56, 0xf2, 0x82, 0xd4, 0x7f, 0x12, 0xab, 0xa0, 0xe0, 0xbd, 0x95, 0xee, 0x79, 0x91, - 0x6a, 0xb8, 0xa9, 0x72, 0x07, 0xe8, 0xb5, 0xa8, 0x62, 0x4d, 0x83, 0x17, 0x76, 0xa6, 0x24, 0xf2, 0x81, 0x97, 0x10, - 0xa1, 0xfb, 0x4e, 0xcc, 0x1a, 0xa6, 0xad, 0x66, 0x67, 0xec, 0x46, 0x0f, 0xa1, 0x47, 0x31, 0x59, 0x5e, 0x2d, 0x21, - 0xe0, 0xb3, 0xdf, 0x46, 0xb3, 0xf7, 0x36, 0x25, 0x19, 0x17, 0xfe, 0x6d, 0x02, 0x4b, 0x6e, 0x71, 0x87, 0x41, 0x0c, - 0xd6, 0x1f, 0x09, 0x1e, 0x98, 0x83, 0xed, 0xa1, 0xb0, 0xac, 0x9e, 0xcd, 0x33, 0x0f, 0xb4, 0x8f, 0x51, 0x94, 0xd1, - 0x04, 0xf0, 0xc9, 0x7a, 0x47, 0x02, 0x80, 0x6c, 0x5d, 0xa1, 0x46, 0x9f, 0x74, 0x65, 0xdd, 0x55, 0x77, 0xc3, 0x52, - 0x19, 0xba, 0x1b, 0x59, 0x4b, 0x01, 0x1d, 0x8a, 0x53, 0x96, 0x59, 0xf4, 0xc6, 0x07, 0x55, 0x14, 0xf9, 0x3e, 0xb1, - 0x2d, 0x61, 0xea, 0xdb, 0x9b, 0x44, 0x17, 0x85, 0x44, 0x01, 0x61, 0x92, 0x9c, 0x78, 0x5f, 0x20, 0x71, 0xb6, 0x5e, - 0x22, 0x6a, 0xc2, 0xe5, 0x67, 0xf7, 0xca, 0x04, 0x1e, 0xb4, 0xf5, 0xac, 0xec, 0x02, 0x97, 0xd7, 0x17, 0x43, 0x10, - 0x05, 0x72, 0x0a, 0x62, 0x72, 0x09, 0x8a, 0x0f, 0xe6, 0x7a, 0x02, 0x4e, 0x91, 0xef, 0xa5, 0xe6, 0x7d, 0xe3, 0x00, - 0x1c, 0x85, 0x10, 0x8b, 0x91, 0x08, 0x08, 0xc9, 0x26, 0xc0, 0xa5, 0x15, 0x68, 0xf7, 0x17, 0x7b, 0xed, 0x0b, 0xf7, - 0x8f, 0xd8, 0xad, 0x30, 0x17, 0xb2, 0x30, 0x5a, 0x11, 0xdd, 0x4b, 0x02, 0x67, 0x87, 0x3a, 0xbf, 0x65, 0x96, 0xc6, - 0xb7, 0xee, 0xe7, 0xa0, 0x94, 0x80, 0xb0, 0xff, 0xc9, 0x38, 0x10, 0x00, 0x73, 0x69, 0x25, 0x6d, 0x89, 0x78, 0xf6, - 0x42, 0x9a, 0x0d, 0xfd, 0xc6, 0x86, 0x37, 0x0f, 0x15, 0x60, 0x49, 0xad, 0x5e, 0x30, 0x97, 0x55, 0xce, 0x68, 0x0d, - 0x4a, 0x78, 0xdb, 0x42, 0x57, 0xcf, 0x56, 0xbf, 0x17, 0xd5, 0x8f, 0xfb, 0xe1, 0x5b, 0xd5, 0x6d, 0x4f, 0xaa, 0x33, - 0xc9, 0x60, 0xf2, 0x54, 0xad, 0xa7, 0x59, 0x70, 0xf7, 0x7e, 0xa7, 0x00, 0x64, 0xa1, 0xf1, 0x76, 0xd6, 0xd9, 0xdc, - 0x1e, 0xfa, 0xc0, 0xfe, 0x80, 0x0b, 0x8a, 0x3f, 0x24, 0x1d, 0xdf, 0x27, 0x11, 0x11, 0x59, 0xdb, 0xb1, 0xcb, 0x5b, - 0xdb, 0x36, 0xad, 0x99, 0x97, 0x3e, 0x56, 0xdf, 0xfc, 0xf6, 0x96, 0xbc, 0x17, 0x25, 0x27, 0xe9, 0x0b, 0x56, 0xb7, - 0x68, 0x7b, 0xc8, 0xd3, 0x81, 0x09, 0x74, 0xeb, 0xbc, 0xf1, 0x4e, 0x31, 0xd2, 0xd4, 0x11, 0x47, 0x99, 0x8d, 0x0c, - 0x9e, 0xe9, 0x59, 0x1f, 0x1d, 0x28, 0x9e, 0x61, 0xba, 0x26, 0x62, 0x9f, 0xb8, 0xec, 0x0a, 0x3c, 0x21, 0x3a, 0x3e, - 0x82, 0x69, 0x43, 0xde, 0xaf, 0xc2, 0xfb, 0xe2, 0x58, 0xfc, 0x60, 0x31, 0x89, 0x7c, 0x90, 0x03, 0xbc, 0x0f, 0x6c, - 0x59, 0x61, 0x64, 0xe0, 0x73, 0xb6, 0x3b, 0x8e, 0x17, 0x80, 0x11, 0x0f, 0xb9, 0x47, 0x77, 0x7c, 0x0f, 0x02, 0xc7, - 0x33, 0xd5, 0x62, 0xe7, 0xb0, 0x04, 0x01, 0x90, 0x19, 0x2c, 0x8e, 0x8b, 0xd1, 0x28, 0x4a, 0x09, 0x78, 0x26, 0xa7, - 0x6e, 0xd5, 0x10, 0xcb, 0xec, 0x9b, 0x80, 0x72, 0xe9, 0x5a, 0x48, 0xc1, 0xad, 0xfa, 0xc6, 0x98, 0x90, 0x6e, 0x1b, - 0x0d, 0xb6, 0xf0, 0xaf, 0x05, 0xb1, 0xa4, 0x41, 0x5d, 0x93, 0xf7, 0x61, 0xb6, 0x50, 0xda, 0x9b, 0xae, 0xe3, 0xd4, - 0x25, 0x92, 0xb8, 0xb6, 0xc4, 0x48, 0x20, 0x98, 0x59, 0x87, 0x22, 0x8b, 0x21, 0xf6, 0xb1, 0xda, 0x02, 0x80, 0x27, - 0x10, 0x1d, 0x39, 0x66, 0xef, 0x11, 0xc5, 0xfd, 0x0b, 0xf8, 0x65, 0xf9, 0x03, 0x19, 0x7f, 0x7b, 0x3e, 0xce, 0x8e, - 0x28, 0xfa, 0x77, 0x12, 0x4f, 0x55, 0x2c, 0x81, 0x34, 0xb6, 0x03, 0x2c, 0x5d, 0x81, 0x5c, 0x06, 0x8e, 0x11, 0xeb, - 0x67, 0xd6, 0x27, 0xe0, 0xc7, 0x01, 0x16, 0x1d, 0xbf, 0x0e, 0x95, 0x5d, 0x4a, 0xe5, 0x6f, 0x95, 0x5b, 0x99, 0x31, - 0x38, 0x17, 0xba, 0x3b, 0x49, 0x53, 0xaf, 0xee, 0x6d, 0x43, 0x7d, 0x93, 0xa4, 0x7d, 0x6b, 0x09, 0x03, 0xee, 0xeb, - 0x24, 0x8d, 0xa1, 0xd0, 0x27, 0xcb, 0xe3, 0x26, 0xa9, 0x89, 0xa1, 0x37, 0x45, 0xbc, 0x9b, 0x6a, 0x8f, 0xd4, 0xee, - 0x4b, 0xd3, 0x2e, 0x02, 0xb3, 0xa4, 0xb1, 0x68, 0x32, 0xfc, 0x08, 0x58, 0x1c, 0x8a, 0x14, 0x23, 0x72, 0x19, 0x80, - 0xb0, 0x61, 0x07, 0x77, 0x52, 0x3d, 0xa6, 0xd9, 0x13, 0xf0, 0xd2, 0xa6, 0x78, 0xef, 0xaa, 0xc5, 0x84, 0x32, 0x61, - 0xf2, 0xe0, 0xad, 0xdd, 0x5c, 0x30, 0x53, 0x2a, 0x49, 0x20, 0x9b, 0xb2, 0x90, 0x2b, 0xf8, 0xd9, 0x8b, 0xbf, 0x7f, - 0x50, 0x54, 0x3a, 0x02, 0xee, 0x78, 0xd9, 0xfd, 0xb9, 0x11, 0xff, 0x64, 0x88, 0x47, 0x46, 0x66, 0xf8, 0x2f, 0x49, - 0xd6, 0xf8, 0x04, 0x32, 0x09, 0x2f, 0x69, 0x0f, 0xd2, 0x25, 0x3c, 0x52, 0xeb, 0x60, 0x96, 0x47, 0x1b, 0x9a, 0xc8, - 0xdf, 0x84, 0xc2, 0xaa, 0xab, 0x0c, 0x2c, 0xce, 0x32, 0xe4, 0xe7, 0x52, 0x73, 0x0c, 0xc0, 0x6f, 0x02, 0xf0, 0x86, - 0x86, 0x49, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x34, 0xe9, 0x3a, 0x55, 0x5d, 0x90, 0x1d, 0x65, 0xd0, 0x2e, 0x0c, 0x89, - 0x80, 0x9e, 0xef, 0x6d, 0xf1, 0xa0, 0x79, 0x7a, 0x93, 0x1f, 0x10, 0xf8, 0xd8, 0x4f, 0xa3, 0x55, 0x75, 0xa0, 0xd6, - 0xe8, 0x19, 0x41, 0x4f, 0x33, 0xe0, 0x36, 0x2e, 0x87, 0xb0, 0x8d, 0x63, 0x58, 0x98, 0xf1, 0x62, 0x18, 0x2f, 0x86, - 0x5c, 0x79, 0x7b, 0x0a, 0xb1, 0x80, 0xdd, 0x80, 0xd4, 0x2c, 0x27, 0x64, 0x27, 0x52, 0xf6, 0x20, 0x50, 0x10, 0xa1, - 0xfc, 0xe6, 0x65, 0xfc, 0x1b, 0x21, 0x28, 0x08, 0xb0, 0x82, 0x68, 0xd5, 0x81, 0x64, 0x6b, 0x13, 0x39, 0xad, 0x25, - 0x55, 0x71, 0x7e, 0x29, 0xc3, 0xe4, 0x77, 0xfd, 0xf9, 0x75, 0x1b, 0x6d, 0x18, 0xc3, 0x53, 0x73, 0xcd, 0x46, 0x93, - 0xe1, 0x53, 0x66, 0x7f, 0x21, 0xc4, 0xc1, 0x21, 0xbf, 0x15, 0xc3, 0x7a, 0x28, 0x6d, 0x18, 0x3c, 0xea, 0x5c, 0x5a, - 0x45, 0xa5, 0xbd, 0x61, 0x27, 0x1a, 0xc6, 0xde, 0xf2, 0xe7, 0x3b, 0x81, 0x8f, 0x81, 0x2b, 0x0c, 0x10, 0xf4, 0x7f, - 0xfb, 0x5b, 0xef, 0x00, 0xff, 0x31, 0xa2, 0xc8, 0x81, 0xdb, 0x0a, 0x83, 0x8c, 0x6d, 0xb3, 0xed, 0x36, 0xfa, 0x98, - 0x6b, 0x3d, 0xf1, 0x42, 0x27, 0x0b, 0xe3, 0xdd, 0x1f, 0x41, 0x19, 0xe6, 0x45, 0x12, 0xe7, 0x45, 0x54, 0xe9, 0xc3, - 0xa2, 0xaa, 0x22, 0xdd, 0x3f, 0x00, 0x30, 0x0a, 0xe7, 0xd3, 0xef, 0xdf, 0x10, 0xaf, 0xec, 0xc6, 0xf7, 0x6a, 0x24, - 0x9f, 0x13, 0xe2, 0xf5, 0xdc, 0x77, 0xb8, 0x03, 0xb3, 0x5f, 0x21, 0x98, 0xb9, 0x9c, 0x4c, 0x06, 0xd7, 0xf4, 0x1b, - 0x05, 0x72, 0xfc, 0xd8, 0x0d, 0x1d, 0xd8, 0x4c, 0xa7, 0xf6, 0x96, 0xef, 0x07, 0xf8, 0xcc, 0x19, 0xcd, 0xea, 0xcd, - 0x8f, 0xbe, 0x6c, 0x50, 0x16, 0xe1, 0x8f, 0x63, 0x72, 0x20, 0x75, 0x95, 0x2e, 0x21, 0xe0, 0x59, 0x9f, 0x34, 0xd0, - 0x10, 0x4e, 0x6d, 0x44, 0x7e, 0x7f, 0x1b, 0x22, 0x7c, 0x67, 0x4f, 0x39, 0xea, 0x44, 0x8f, 0xa8, 0x27, 0x64, 0xb6, - 0xdd, 0xd6, 0x07, 0x64, 0x59, 0xb0, 0xf9, 0x06, 0xce, 0x53, 0xd3, 0x92, 0xc3, 0x4f, 0xfd, 0xb9, 0x09, 0x55, 0xa4, - 0xec, 0x77, 0xf0, 0x26, 0xc9, 0xc8, 0xa8, 0x50, 0xfe, 0x37, 0x59, 0x6f, 0x51, 0x32, 0xe2, 0x4b, 0x62, 0x2a, 0x98, - 0x3e, 0xf2, 0x98, 0xcd, 0x48, 0x4a, 0x5d, 0x6b, 0x25, 0x0f, 0xbe, 0x87, 0x42, 0xe3, 0xf4, 0x06, 0x21, 0xd8, 0x60, - 0x5a, 0x41, 0x3c, 0x5a, 0x31, 0xca, 0x1a, 0x4f, 0x26, 0xef, 0xb7, 0x52, 0x13, 0x7a, 0x7c, 0x5b, 0x25, 0x8b, 0x27, - 0x73, 0x47, 0xca, 0x47, 0x12, 0x47, 0xda, 0x28, 0x68, 0xf1, 0xa6, 0xe3, 0xfd, 0xac, 0x33, 0x22, 0x05, 0xbd, 0x9c, - 0x1b, 0x91, 0xf2, 0xcb, 0x1b, 0x66, 0xdf, 0x1e, 0x5c, 0x1e, 0x3c, 0x3e, 0x16, 0x45, 0x4e, 0x81, 0xbb, 0x75, 0x0d, - 0x2f, 0xfb, 0xa2, 0x2b, 0x61, 0x28, 0xa7, 0x94, 0x07, 0x85, 0xc2, 0xc8, 0x16, 0x48, 0x43, 0x7e, 0x12, 0xf9, 0xfb, - 0x61, 0x3e, 0x63, 0xf8, 0xba, 0xf4, 0x49, 0xca, 0x4a, 0x62, 0x7f, 0x22, 0xd2, 0x64, 0xe2, 0x8d, 0x79, 0xbf, 0xff, - 0x63, 0xf6, 0x62, 0x3f, 0x54, 0x19, 0x33, 0x77, 0x93, 0xc8, 0x42, 0x1d, 0x94, 0xf2, 0x15, 0x4e, 0x3b, 0xfc, 0xff, - 0x46, 0xa2, 0xed, 0x42, 0x0f, 0x6f, 0x0f, 0x3c, 0x14, 0xad, 0x49, 0x62, 0xdb, 0x7b, 0xba, 0x04, 0x2b, 0x54, 0xdb, - 0xf8, 0x72, 0x1a, 0x79, 0x56, 0xf4, 0x6a, 0x77, 0xc5, 0x70, 0xef, 0xa0, 0xbe, 0xc9, 0xaa, 0xfd, 0xd4, 0x64, 0x1a, - 0x58, 0x81, 0xc0, 0x77, 0x41, 0x6e, 0x1d, 0x27, 0xae, 0xd7, 0xda, 0xdf, 0xad, 0x36, 0x61, 0xb5, 0xa1, 0x6e, 0x41, - 0x64, 0x5e, 0x30, 0xb0, 0x2c, 0x9a, 0x27, 0x11, 0x14, 0xc3, 0x32, 0x18, 0x72, 0xa6, 0x64, 0x81, 0xf3, 0x56, 0x40, - 0x1e, 0xdd, 0x2b, 0x38, 0x21, 0x61, 0xb4, 0x8e, 0x35, 0x1b, 0xf9, 0x22, 0x14, 0xf9, 0xaa, 0x6d, 0x36, 0x2e, 0xc5, - 0x3d, 0x4d, 0x6a, 0x15, 0xd0, 0x5c, 0x56, 0x30, 0x85, 0xf6, 0x8d, 0x42, 0xe2, 0x4c, 0x23, 0x79, 0xfe, 0x92, 0xee, - 0xc7, 0xb1, 0x41, 0x17, 0xf9, 0x2b, 0x0d, 0xdb, 0xce, 0xb5, 0xbe, 0xfb, 0xa0, 0x00, 0x5f, 0xa8, 0x23, 0xf3, 0x29, - 0xed, 0x2f, 0xab, 0xd6, 0x0d, 0x5f, 0xa8, 0xe5, 0x17, 0x13, 0xfd, 0xa5, 0x92, 0x66, 0x7f, 0x5f, 0x5a, 0xa0, 0x94, - 0xa7, 0x59, 0xae, 0x9a, 0x5a, 0x3e, 0xf2, 0x3f, 0xcd, 0x93, 0x09, 0x99, 0xd0, 0x39, 0x2c, 0x1f, 0x15, 0x69, 0x76, - 0x9f, 0x3f, 0x70, 0xff, 0x86, 0x57, 0xca, 0xde, 0x13, 0xe7, 0x31, 0xbd, 0xa7, 0xc4, 0xe6, 0xcc, 0x03, 0x0c, 0xb2, - 0x22, 0x4e, 0x6d, 0xab, 0xd9, 0x3b, 0x92, 0x39, 0x56, 0xdd, 0x65, 0x72, 0xc2, 0x64, 0xe8, 0xae, 0xe2, 0x83, 0x46, - 0xd8, 0xcd, 0xf7, 0x89, 0x0f, 0x2c, 0x82, 0x66, 0x94, 0xee, 0x6a, 0xb7, 0x7f, 0x2c, 0x57, 0xb1, 0x48, 0xa4, 0xc8, - 0x56, 0xd4, 0x6a, 0x9f, 0xe8, 0x21, 0x7f, 0x2b, 0xf9, 0xf9, 0x3f, 0x95, 0x88, 0x1b, 0x87, 0xd3, 0x7f, 0x4e, 0x54, - 0x10, 0x06, 0xb5, 0x43, 0x46, 0xb2, 0x84, 0x0a, 0x14, 0xc6, 0xce, 0x04, 0xdb, 0x5f, 0xb0, 0x1e, 0x60, 0x91, 0x48, - 0x22, 0x69, 0x28, 0x8f, 0x2c, 0x11, 0xa8, 0x12, 0xdf, 0x53, 0x97, 0xcd, 0x0f, 0x51, 0xb4, 0x71, 0x7d, 0x1e, 0x10, - 0x2a, 0xd3, 0x96, 0x2b, 0xe7, 0xb4, 0x72, 0xe5, 0x5e, 0x90, 0x18, 0x49, 0x24, 0x38, 0x82, 0xda, 0xa8, 0x21, 0x7c, - 0x48, 0x4a, 0x2f, 0x9d, 0x54, 0xde, 0xb5, 0xb8, 0x26, 0x8f, 0x02, 0x88, 0x4d, 0xc6, 0xf8, 0xf5, 0xe5, 0xaa, 0xdd, - 0x78, 0xba, 0x6c, 0xc4, 0xe2, 0x77, 0x0a, 0x38, 0x41, 0xba, 0xaf, 0x28, 0xa0, 0x37, 0x60, 0x55, 0x07, 0x7c, 0xfb, - 0x04, 0x8e, 0x4a, 0x07, 0x8a, 0xe9, 0xc8, 0xa1, 0x22, 0xbf, 0x03, 0xae, 0xdd, 0xad, 0x88, 0xf0, 0xed, 0xf2, 0x35, - 0x2b, 0x6a, 0x09, 0x41, 0xad, 0x35, 0x89, 0x66, 0xb6, 0x08, 0xc5, 0xc6, 0xbd, 0x80, 0xcb, 0x73, 0x28, 0xfa, 0xf0, - 0x12, 0x17, 0x71, 0xe0, 0xfd, 0xc5, 0x4b, 0x9b, 0x27, 0xd3, 0x29, 0xfd, 0xd6, 0x77, 0x74, 0xf0, 0xe8, 0xe5, 0xc3, - 0xb2, 0x48, 0x27, 0x29, 0x78, 0xc4, 0x20, 0x08, 0x93, 0xf4, 0x89, 0x47, 0x4c, 0x76, 0x9a, 0x77, 0x1e, 0xdc, 0xc5, - 0x05, 0xb2, 0x1f, 0x46, 0xf0, 0x10, 0xd9, 0x5e, 0x9a, 0x38, 0xa0, 0x3d, 0xb7, 0x75, 0x76, 0x32, 0x6e, 0x9e, 0x78, - 0x2f, 0x5a, 0xf0, 0x2a, 0xe6, 0x7d, 0xe2, 0x11, 0xc6, 0x0c, 0x7e, 0xee, 0x12, 0x92, 0x1c, 0x6b, 0xa9, 0xe0, 0x28, - 0xe8, 0x81, 0x7c, 0x31, 0x92, 0x51, 0x9a, 0xd1, 0xb7, 0x3f, 0x9b, 0xbb, 0x1d, 0xed, 0xaa, 0xdb, 0x6c, 0x83, 0x8b, - 0xae, 0x8c, 0x5f, 0xcf, 0x7d, 0xd9, 0xb1, 0xa3, 0x2b, 0x37, 0x0e, 0xd8, 0x96, 0xd1, 0x9b, 0x2e, 0xb1, 0x58, 0x69, - 0x0d, 0xa9, 0x20, 0xf6, 0x65, 0x4e, 0xe0, 0xd2, 0x4a, 0x73, 0x52, 0xb0, 0x06, 0xef, 0x32, 0x3d, 0x59, 0xad, 0xbe, - 0x7b, 0x29, 0xeb, 0xe1, 0x19, 0x7f, 0xdb, 0x0b, 0xd5, 0xc8, 0xc5, 0xef, 0xa7, 0x1c, 0x64, 0x1d, 0x5d, 0x64, 0xc8, - 0xa4, 0x2f, 0xd0, 0xde, 0x37, 0x59, 0x04, 0x36, 0xe1, 0x80, 0xdc, 0xbb, 0x95, 0xda, 0xc0, 0x65, 0xbc, 0xb1, 0x89, - 0xe8, 0x69, 0x2c, 0xc2, 0x69, 0x2f, 0xec, 0xc1, 0xdf, 0xd1, 0xcd, 0x34, 0xe7, 0xa9, 0xbc, 0x74, 0xdf, 0xde, 0xbb, - 0x74, 0xbf, 0x48, 0xbe, 0xc7, 0xee, 0xf3, 0xc5, 0xfb, 0x45, 0x1d, 0xde, 0x1c, 0xd8, 0x3f, 0x33, 0xbc, 0xb4, 0x47, - 0xcd, 0xcd, 0xdb, 0x9a, 0x7d, 0x2d, 0xf6, 0x5b, 0x87, 0x37, 0x5d, 0x44, 0x99, 0x9d, 0x33, 0x1a, 0x5b, 0xf3, 0x6b, - 0xbc, 0x7e, 0xfc, 0xf1, 0x67, 0xfe, 0x59, 0xce, 0x0b, 0x86, 0x61, 0x8d, 0x9f, 0x77, 0x59, 0x0f, 0xab, 0xb6, 0x7e, - 0x2c, 0xf0, 0xd1, 0xdc, 0xbc, 0xa3, 0xda, 0xb8, 0xb7, 0x48, 0x1f, 0xad, 0xdc, 0x35, 0x9f, 0x3c, 0x32, 0xb8, 0xf0, - 0x23, 0xf3, 0xf9, 0xa8, 0x1f, 0x41, 0xc8, 0xe5, 0x4f, 0xde, 0x45, 0x62, 0xfa, 0xc7, 0xd6, 0x2b, 0xb1, 0x88, 0x7d, - 0xaa, 0x81, 0x70, 0x37, 0x5e, 0xa4, 0x45, 0xd9, 0x77, 0xf4, 0x0b, 0x7b, 0x4c, 0x56, 0xef, 0x40, 0x04, 0x0a, 0x5a, - 0x9f, 0x9d, 0x24, 0x12, 0x3f, 0x44, 0xff, 0xe4, 0x8f, 0xa8, 0xd3, 0x4e, 0xb4, 0xff, 0xd8, 0x4e, 0xf8, 0xff, 0xa7, - 0x6b, 0x5b, 0xf5, 0x96, 0x0d, 0xf0, 0xd6, 0xff, 0x05, 0xa2, 0x0d, 0x6d, 0xaf, 0x04, 0xe9, 0xa1, 0x8b, 0x88, 0xfc, - 0xd9, 0xad, 0x66, 0x59, 0x61, 0xf5, 0x32, 0x57, 0x2c, 0xe3, 0x09, 0x9d, 0x93, 0x0b, 0x8d, 0x93, 0x34, 0x4d, 0x19, - 0xbc, 0x67, 0xd2, 0xec, 0x75, 0x2d, 0x43, 0xef, 0x36, 0x67, 0x8f, 0xd0, 0x49, 0x3a, 0xce, 0x92, 0x8a, 0x45, 0xb4, - 0x6e, 0x57, 0x6d, 0x9e, 0xad, 0x47, 0x70, 0x06, 0x07, 0x67, 0x59, 0x40, 0xef, 0xc1, 0x52, 0xdb, 0x9d, 0x1b, 0x3b, - 0x4c, 0xf7, 0x2f, 0x2d, 0x87, 0x23, 0x82, 0xc6, 0xde, 0x2c, 0xb7, 0xed, 0x8f, 0x4a, 0x0a, 0x15, 0xf1, 0xe6, 0xc0, - 0x40, 0x2f, 0x7e, 0x3d, 0x91, 0x65, 0xd0, 0x75, 0x2f, 0x5f, 0x0b, 0x61, 0x59, 0xab, 0xb9, 0x76, 0x18, 0x9f, 0x0b, - 0xab, 0x20, 0xb4, 0x0b, 0x21, 0xce, 0x5e, 0xe8, 0x3a, 0x01, 0x4d, 0x8c, 0x78, 0x8b, 0x0b, 0x09, 0x36, 0x39, 0x28, - 0x54, 0x50, 0x3a, 0x3e, 0xd2, 0xee, 0x41, 0x10, 0x7a, 0x2e, 0xc6, 0x0a, 0xc8, 0xb1, 0xdc, 0x4e, 0x65, 0x22, 0x9a, - 0x24, 0x04, 0xae, 0xf2, 0x43, 0xf8, 0x8c, 0x64, 0xbc, 0x9c, 0xda, 0x45, 0x58, 0x77, 0x9b, 0xaa, 0xcd, 0x41, 0xef, - 0xfe, 0x27, 0xac, 0x42, 0x17, 0x45, 0xd1, 0x7a, 0xd6, 0x59, 0x9e, 0x47, 0xcc, 0x03, 0xb3, 0x49, 0x81, 0x46, 0x11, - 0x8a, 0xd0, 0xbf, 0x27, 0xf6, 0xd0, 0x88, 0x2a, 0xa3, 0xba, 0x60, 0x31, 0xac, 0x30, 0x57, 0x4e, 0x4b, 0x69, 0xa7, - 0x2c, 0x77, 0xa3, 0x1d, 0xe0, 0xc7, 0x57, 0xff, 0x6c, 0x43, 0xff, 0x72, 0xe9, 0x63, 0xdb, 0x8b, 0x2d, 0x36, 0xbf, - 0x7e, 0x3e, 0x4b, 0xef, 0x0e, 0x4f, 0xa3, 0xd8, 0x82, 0x9a, 0x40, 0x25, 0x13, 0x85, 0x52, 0xf3, 0xba, 0xe0, 0x10, - 0xb4, 0x50, 0xfc, 0x68, 0x54, 0xd4, 0xfb, 0x79, 0x35, 0x01, 0x05, 0x09, 0x20, 0x1c, 0x4b, 0x1a, 0x69, 0x97, 0xd8, - 0x82, 0x48, 0xeb, 0xb3, 0xf2, 0x6e, 0x84, 0xd7, 0x36, 0x68, 0x8a, 0xe0, 0x90, 0x25, 0xd3, 0xc2, 0xb0, 0x22, 0x83, - 0x04, 0x18, 0xb7, 0x11, 0xd2, 0x8b, 0xe4, 0x1f, 0x50, 0x02, 0xf0, 0x2a, 0xa2, 0xbd, 0x51, 0x99, 0x88, 0xe4, 0xa5, - 0xac, 0x51, 0x0a, 0x4b, 0x00, 0x02, 0xff, 0x32, 0xbf, 0x22, 0x58, 0x22, 0xd5, 0x58, 0xa3, 0x35, 0x9d, 0x11, 0xa8, - 0xad, 0x7e, 0x07, 0x44, 0x98, 0xd7, 0xd8, 0xcd, 0x68, 0x7e, 0x43, 0xb3, 0x24, 0xc6, 0xb8, 0x6a, 0x6f, 0x3e, 0xe7, - 0x72, 0xbb, 0xe6, 0xb2, 0xdf, 0x5a, 0x0f, 0xec, 0x4d, 0xba, 0xcf, 0x3a, 0xf3, 0xc0, 0xc7, 0xa7, 0x15, 0xce, 0xeb, - 0x25, 0x99, 0x95, 0xc7, 0x47, 0x5f, 0xf7, 0xae, 0xb5, 0x50, 0x73, 0xf3, 0xbe, 0x3e, 0xdc, 0xbc, 0x77, 0x6d, 0x85, - 0x1f, 0xfc, 0x5f, 0xc6, 0xf1, 0xb4, 0x46, 0x56, 0xfe, 0x5a, 0x15, 0xd5, 0x36, 0x62, 0x98, 0x78, 0x3b, 0x65, 0x08, - 0xe4, 0xa9, 0xda, 0x83, 0xdd, 0x49, 0x54, 0xda, 0x6f, 0x2a, 0x52, 0xb7, 0x9d, 0x0b, 0x45, 0x67, 0xa2, 0x4d, 0x72, - 0xc2, 0x33, 0x9e, 0x6f, 0x8e, 0x30, 0x89, 0xa4, 0xe5, 0x3a, 0x53, 0x37, 0xdc, 0xfd, 0x5c, 0xae, 0x3f, 0x6e, 0x1a, - 0xd0, 0x21, 0x8b, 0x8f, 0xfb, 0x90, 0x51, 0x10, 0x34, 0xbc, 0x6c, 0x96, 0x09, 0x79, 0xac, 0x13, 0xeb, 0x6a, 0xf7, - 0x65, 0x8a, 0xba, 0x3f, 0xd7, 0x2f, 0xc4, 0xb1, 0xb7, 0xc3, 0x24, 0xb1, 0xb1, 0x64, 0x9a, 0xb5, 0x46, 0x1a, 0x79, - 0x70, 0x7a, 0x6a, 0x7b, 0xe6, 0x65, 0x67, 0xf5, 0xd6, 0xcc, 0x03, 0x1d, 0x70, 0x12, 0x69, 0x0b, 0xe6, 0x64, 0x5e, - 0xcc, 0xcf, 0x4f, 0x07, 0xe9, 0xc6, 0xfd, 0x5c, 0x8d, 0xed, 0x88, 0xc7, 0xa4, 0x27, 0x09, 0xfc, 0x44, 0x09, 0xbe, - 0x25, 0x91, 0x06, 0xe0, 0xe5, 0xeb, 0xcb, 0x11, 0x64, 0xb6, 0x0a, 0x48, 0x4c, 0xb6, 0xf5, 0xeb, 0x4f, 0x01, 0x83, - 0xce, 0x56, 0x20, 0x01, 0x43, 0xf1, 0x33, 0x68, 0xbd, 0xc6, 0x97, 0x1a, 0x24, 0x29, 0x31, 0x3e, 0x99, 0xe1, 0xe6, - 0x93, 0x28, 0xf0, 0xf0, 0x5b, 0x47, 0xb6, 0xd9, 0x0e, 0x65, 0x9c, 0x41, 0xf5, 0x98, 0xd6, 0xc3, 0x29, 0x33, 0xe3, - 0xf9, 0x4c, 0x7a, 0x1c, 0x7f, 0xab, 0x80, 0xbc, 0x0f, 0xcc, 0xdb, 0xa0, 0x6c, 0x82, 0x70, 0x02, 0x83, 0xcb, 0xb9, - 0x17, 0x9b, 0x40, 0x5c, 0xbf, 0x84, 0x35, 0xa6, 0x93, 0x3c, 0x9f, 0xab, 0xc3, 0x0f, 0xe3, 0xb7, 0x1e, 0xb9, 0x37, - 0xbd, 0x57, 0x8c, 0x4b, 0xd3, 0x7a, 0xc1, 0x30, 0xbb, 0x52, 0x6c, 0x80, 0x5a, 0x05, 0x33, 0x5b, 0x32, 0x6e, 0xa5, - 0x45, 0x16, 0x38, 0x6e, 0x7a, 0xef, 0xd4, 0xec, 0xae, 0xad, 0x07, 0xa4, 0x4f, 0x34, 0x44, 0x8c, 0x4f, 0x55, 0xe0, - 0x12, 0x75, 0xfc, 0x1e, 0x7f, 0x7a, 0xcf, 0x5f, 0xc3, 0x38, 0x15, 0x6f, 0xb6, 0xf1, 0x22, 0x63, 0x2b, 0xcb, 0xf3, - 0xf7, 0xf1, 0x9e, 0x43, 0x4b, 0x6b, 0x3f, 0x8c, 0x31, 0x58, 0xc9, 0x67, 0x0a, 0xf5, 0x84, 0x1d, 0xff, 0x22, 0x91, - 0xfe, 0xd9, 0x5a, 0xfa, 0x5b, 0xfc, 0x33, 0xc2, 0xff, 0x31, 0x0c, 0x95, 0xe6, 0xcb, 0x3f, 0xa2, 0xfe, 0x23, 0xbe, - 0x50, 0x56, 0x7a, 0x91, 0x73, 0x4f, 0xb5, 0xd9, 0x98, 0x8f, 0xf6, 0x26, 0x4e, 0x0a, 0x18, 0xc5, 0x99, 0x89, 0x82, - 0x38, 0xcf, 0xd5, 0xf9, 0x48, 0xf2, 0xb7, 0x9a, 0xb8, 0xf0, 0xcb, 0xf1, 0xd1, 0xf0, 0xf1, 0xdc, 0xa7, 0xe7, 0xfd, - 0x1e, 0x52, 0xb9, 0x2f, 0x12, 0xd5, 0xb6, 0xb2, 0x7d, 0xf2, 0xf7, 0x5d, 0xe7, 0x8e, 0x08, 0xac, 0x3f, 0x0f, 0x3e, - 0xb3, 0x8c, 0x3f, 0x19, 0x5e, 0xa6, 0x29, 0x5a, 0x33, 0x16, 0x5f, 0xe8, 0x33, 0xad, 0x8d, 0xdf, 0xb8, 0x55, 0x65, - 0x9b, 0x1a, 0x50, 0x9b, 0x6e, 0x82, 0xc4, 0xa4, 0x82, 0x06, 0x65, 0x9d, 0xfb, 0xf4, 0x07, 0x44, 0x1b, 0x12, 0x8a, - 0x7e, 0xfc, 0x43, 0x21, 0xe8, 0x2e, 0x41, 0x02, 0x90, 0xc4, 0x30, 0x33, 0x7e, 0x29, 0x48, 0x07, 0x34, 0x3c, 0xd4, - 0xdb, 0xcb, 0xc6, 0x56, 0x7d, 0x0e, 0x39, 0xfe, 0x6d, 0x74, 0x7f, 0x60, 0xf5, 0xd0, 0x80, 0x8a, 0xe3, 0x70, 0xf9, - 0x7f, 0xf4, 0x86, 0x30, 0x8a, 0x7a, 0x48, 0xa8, 0x2e, 0x16, 0x8d, 0x7f, 0x3a, 0x4a, 0xca, 0x19, 0x4a, 0x96, 0x72, - 0x1e, 0x15, 0x03, 0xcf, 0x82, 0xa0, 0xba, 0xa2, 0xc7, 0x26, 0xcf, 0xc5, 0xb3, 0x82, 0x43, 0xfe, 0x4f, 0xb0, 0xec, - 0x32, 0xc4, 0x64, 0x8c, 0xf8, 0xce, 0x4f, 0x10, 0x96, 0x64, 0x35, 0x6c, 0xcc, 0x1e, 0xc2, 0xed, 0x47, 0x6f, 0xa0, - 0x21, 0xdc, 0x7c, 0x7c, 0x80, 0x04, 0x7c, 0xe3, 0xcd, 0xea, 0x6a, 0x54, 0xbe, 0x30, 0xa7, 0x5d, 0x41, 0xdc, 0x18, - 0x02, 0x10, 0x89, 0xe0, 0x54, 0x52, 0x80, 0xfa, 0x26, 0x69, 0x8b, 0x80, 0xc5, 0x84, 0x6b, 0x43, 0x72, 0xd0, 0x8e, - 0x8b, 0xc9, 0x99, 0x72, 0x28, 0x73, 0xea, 0x28, 0x05, 0xe4, 0x24, 0x8f, 0x0e, 0x64, 0xd6, 0xed, 0xa5, 0x64, 0x7c, - 0x95, 0x8d, 0x76, 0xd9, 0x42, 0xf5, 0x49, 0x84, 0x99, 0x44, 0x8c, 0x54, 0xf0, 0x24, 0x67, 0x65, 0x82, 0x7e, 0xd1, - 0x2e, 0xa6, 0x36, 0xe2, 0xe1, 0xde, 0x66, 0x46, 0xec, 0x22, 0xd0, 0xe0, 0xca, 0x21, 0x79, 0xc5, 0xab, 0x90, 0x41, - 0x90, 0x09, 0x0b, 0x84, 0x05, 0x5c, 0x68, 0xf7, 0x7d, 0xe2, 0x78, 0xd8, 0xef, 0x47, 0xc1, 0x25, 0xe7, 0xf5, 0x86, - 0x5d, 0x82, 0x3b, 0xaf, 0x7a, 0x7d, 0x5d, 0x5b, 0x87, 0x8f, 0x9f, 0x33, 0x22, 0x05, 0x96, 0x41, 0xde, 0xe0, 0xe5, - 0x41, 0x18, 0xf8, 0x81, 0x3d, 0x82, 0x97, 0xa9, 0xb3, 0x2f, 0xc2, 0x90, 0x60, 0xd6, 0x93, 0x1a, 0xd2, 0x96, 0x05, - 0x57, 0xa7, 0xd3, 0x36, 0xdb, 0x51, 0xa0, 0x46, 0xa9, 0xde, 0x17, 0x86, 0x32, 0x25, 0x5a, 0x65, 0x13, 0xd8, 0x21, - 0x10, 0x2d, 0x5b, 0x11, 0xbe, 0xc5, 0xdc, 0x84, 0x05, 0x3a, 0xe9, 0xb4, 0xcd, 0x76, 0xb4, 0x08, 0xdf, 0x80, 0x4e, - 0x2e, 0x26, 0x5c, 0x4c, 0xb9, 0xf4, 0x84, 0xbc, 0x3a, 0xa9, 0x40, 0x89, 0x09, 0x78, 0x28, 0x23, 0xc3, 0x7c, 0x9a, - 0xf2, 0xa5, 0x27, 0xbf, 0x89, 0x59, 0xb4, 0x5f, 0xe6, 0x3c, 0x0d, 0xd2, 0x06, 0x13, 0x1b, 0xa4, 0xa6, 0xd5, 0x49, - 0x12, 0xdf, 0x1f, 0x5a, 0xc0, 0x0c, 0x4a, 0x73, 0x7c, 0x6e, 0x63, 0x52, 0x4a, 0x45, 0xc8, 0xb8, 0x5e, 0x1e, 0xf5, - 0xec, 0x7c, 0x18, 0x09, 0x6a, 0x76, 0x13, 0x7e, 0xb6, 0x17, 0x8d, 0x96, 0x8a, 0x97, 0x93, 0x50, 0xc2, 0x08, 0x89, - 0x95, 0x80, 0x04, 0x79, 0x93, 0xd9, 0x00, 0xe5, 0x4f, 0xca, 0x95, 0xfb, 0x4a, 0xc6, 0x63, 0x87, 0x70, 0xc0, 0xcf, - 0x1c, 0x03, 0x47, 0x19, 0x35, 0xfa, 0x47, 0xf3, 0xc1, 0x61, 0x74, 0xea, 0x12, 0x86, 0x09, 0xc8, 0x72, 0x89, 0x35, - 0xca, 0xf8, 0x30, 0x40, 0xf5, 0xba, 0x1f, 0x26, 0x1b, 0xfc, 0x11, 0x4d, 0x78, 0x24, 0x1b, 0xe6, 0xb0, 0xab, 0x16, - 0x9a, 0x18, 0xe4, 0x01, 0xe4, 0x16, 0x55, 0x46, 0x8e, 0xcc, 0xe9, 0x3d, 0xaa, 0x1c, 0xad, 0xd0, 0xf7, 0x11, 0xb0, - 0x94, 0xea, 0xd9, 0xb5, 0x34, 0x55, 0x00, 0x4b, 0x68, 0x25, 0x50, 0xb6, 0x31, 0x9b, 0x7c, 0x6f, 0xd9, 0xde, 0xb8, - 0xcc, 0x46, 0xfe, 0x22, 0x8d, 0x58, 0xc3, 0x96, 0x80, 0x73, 0xf5, 0x81, 0xd0, 0x76, 0xb2, 0x07, 0x10, 0xa2, 0xa4, - 0x17, 0x99, 0xbb, 0x32, 0x41, 0x6e, 0x5e, 0xf3, 0x89, 0x36, 0xcb, 0x00, 0x5b, 0x0d, 0xc1, 0x9d, 0xe7, 0xc2, 0x37, - 0xa9, 0x39, 0x29, 0xb8, 0xe0, 0xe7, 0xfb, 0x2b, 0x44, 0x15, 0x5e, 0xe4, 0xba, 0x1b, 0xae, 0x45, 0x3c, 0x37, 0xe6, - 0x5f, 0xab, 0xc6, 0x8b, 0x45, 0x19, 0x96, 0xca, 0xbf, 0xa1, 0xc9, 0x16, 0xb2, 0x6f, 0xa9, 0xa4, 0xf1, 0x6f, 0x09, - 0x7b, 0xe2, 0x83, 0xd1, 0x88, 0x32, 0xdc, 0xc0, 0x9a, 0xf8, 0xc8, 0xbc, 0x8a, 0x5e, 0x1c, 0x0f, 0x08, 0x0e, 0x02, - 0x94, 0x81, 0x93, 0x10, 0x06, 0xe2, 0x73, 0x8c, 0x35, 0x5f, 0xb3, 0x1e, 0x73, 0xde, 0xf4, 0x26, 0xcf, 0x35, 0xbf, - 0xe0, 0x35, 0xa0, 0x02, 0xda, 0xc3, 0x8e, 0x1e, 0xcb, 0x60, 0x42, 0x33, 0x1e, 0x42, 0x3e, 0x7d, 0xf0, 0xdb, 0xfc, - 0x8c, 0xc1, 0x2c, 0x0a, 0x09, 0x32, 0x9c, 0xae, 0xba, 0x99, 0xa1, 0xd5, 0x26, 0xf0, 0x7f, 0xbf, 0xbb, 0x19, 0x35, - 0x44, 0xde, 0x8b, 0x90, 0xe9, 0x06, 0x32, 0xda, 0x62, 0x1a, 0x36, 0xcd, 0x34, 0x5b, 0x0d, 0x86, 0xea, 0xa3, 0xa6, - 0xaf, 0xf1, 0xda, 0x6b, 0x1d, 0x95, 0x43, 0xa7, 0x36, 0x30, 0xbc, 0xe7, 0xbf, 0x77, 0x0f, 0x05, 0x79, 0x91, 0x14, - 0x72, 0x3b, 0x1d, 0x22, 0xc3, 0x4d, 0xec, 0x58, 0xf7, 0xfa, 0x9f, 0x31, 0xe3, 0xe4, 0x33, 0x93, 0x39, 0x81, 0x4d, - 0x53, 0x53, 0xb4, 0xa0, 0x9f, 0x36, 0x4b, 0x73, 0xa7, 0xac, 0xf5, 0x5a, 0xf0, 0x4b, 0xab, 0xd4, 0x38, 0x64, 0x55, - 0xc3, 0xcb, 0x0b, 0x5d, 0x3c, 0xf1, 0x82, 0xbf, 0x0c, 0x4c, 0xb8, 0xf1, 0x53, 0x2b, 0xea, 0xea, 0xe2, 0x85, 0xbe, - 0xef, 0x3e, 0x4b, 0x79, 0x48, 0xb4, 0x45, 0x16, 0x1a, 0xb2, 0xb9, 0xc9, 0x8b, 0x99, 0x2f, 0x36, 0xa3, 0x82, 0xcf, - 0x57, 0x68, 0x20, 0x1b, 0x1c, 0xb6, 0xd5, 0x35, 0xbe, 0xf0, 0xbc, 0x4b, 0xa4, 0x32, 0x72, 0xb1, 0x17, 0x1c, 0xc2, - 0x61, 0xb9, 0xb4, 0x98, 0xb5, 0x7a, 0xfe, 0x0e, 0x9d, 0xf1, 0x14, 0xa7, 0x90, 0xa8, 0x94, 0x8b, 0x4f, 0xcc, 0xfe, - 0xac, 0xef, 0xf7, 0x39, 0xc3, 0xfb, 0x03, 0xc9, 0x67, 0xfd, 0x63, 0x5f, 0x6d, 0x82, 0xbd, 0x93, 0xb7, 0x4a, 0xfb, - 0xda, 0x86, 0x65, 0xec, 0x23, 0x05, 0x04, 0x7f, 0x53, 0x38, 0x35, 0xf4, 0x08, 0x53, 0xd2, 0x72, 0x2f, 0xf2, 0xdb, - 0x8a, 0x68, 0x89, 0x06, 0xde, 0xe2, 0xb8, 0x48, 0x9f, 0xb6, 0xe5, 0x5d, 0xb6, 0xd4, 0xf1, 0xd0, 0xad, 0x8c, 0x25, - 0xd1, 0xa8, 0xd2, 0xf4, 0x41, 0xf4, 0xdc, 0xd9, 0x92, 0xe8, 0xed, 0xce, 0x68, 0xf6, 0x24, 0x1f, 0x13, 0xea, 0x1a, - 0x71, 0xab, 0x9e, 0xb7, 0xd8, 0xd7, 0xd4, 0xec, 0x86, 0x5e, 0xa8, 0x19, 0x2a, 0x21, 0xab, 0xd1, 0x17, 0x6a, 0xfd, - 0x28, 0x42, 0x92, 0xec, 0xf1, 0xeb, 0x9a, 0x5f, 0x3e, 0xdf, 0x48, 0x85, 0x72, 0x75, 0x51, 0x51, 0xa0, 0xf9, 0x79, - 0x9a, 0x78, 0x82, 0x72, 0x5e, 0x4b, 0x5f, 0x7d, 0x6a, 0x00, 0x2a, 0x42, 0x72, 0x6b, 0x87, 0x86, 0x34, 0xb4, 0xcc, - 0xcd, 0xb3, 0x79, 0x16, 0x8a, 0x00, 0xdd, 0x33, 0x4f, 0x3c, 0x75, 0x31, 0x6e, 0xf6, 0x82, 0x41, 0xc5, 0xce, 0x13, - 0x93, 0x01, 0x70, 0x92, 0x3a, 0x88, 0x46, 0xb0, 0xb7, 0x3b, 0xcd, 0x3e, 0xe6, 0xe2, 0x19, 0xb8, 0x10, 0xd6, 0xd3, - 0xf2, 0xda, 0xb3, 0x68, 0xd7, 0x33, 0xa4, 0x49, 0xb7, 0x6f, 0x57, 0xe3, 0xd1, 0x05, 0x77, 0x64, 0xd2, 0x48, 0x68, - 0xa9, 0x86, 0x42, 0xae, 0x52, 0xb9, 0xa3, 0xee, 0xac, 0x99, 0x52, 0x6e, 0xa2, 0x70, 0x2b, 0x73, 0xd9, 0xba, 0x8c, - 0xe5, 0x1c, 0x61, 0x85, 0xad, 0xcc, 0x12, 0xcf, 0x02, 0xfc, 0x08, 0x0c, 0xa2, 0x52, 0x95, 0x67, 0xa2, 0x08, 0x49, - 0xdd, 0x60, 0x81, 0x89, 0xec, 0x7d, 0xbf, 0x85, 0x02, 0x0f, 0xbe, 0xf2, 0x11, 0xa3, 0x48, 0x14, 0x02, 0x02, 0x68, - 0x30, 0xd0, 0x02, 0xaa, 0x59, 0x3a, 0xa8, 0x86, 0x0f, 0xa1, 0xf3, 0x22, 0x9e, 0x98, 0x24, 0x19, 0xf4, 0x6f, 0xff, - 0x43, 0x81, 0x98, 0xf4, 0x01, 0x92, 0x2a, 0x13, 0x80, 0x1b, 0x16, 0x8f, 0xd3, 0x68, 0x2e, 0x5b, 0x91, 0x2b, 0x3d, - 0x8e, 0x7c, 0x6e, 0x8b, 0x7a, 0xc1, 0xca, 0x4b, 0x48, 0x69, 0xc7, 0xf0, 0xb2, 0xd7, 0xa5, 0xc2, 0xcf, 0x5e, 0xf3, - 0x0b, 0x26, 0x17, 0xc6, 0x21, 0x29, 0x17, 0xca, 0x10, 0xd6, 0x03, 0x00, 0x99, 0x77, 0x03, 0xd5, 0x9b, 0x84, 0x87, - 0xad, 0xb2, 0x39, 0x14, 0x0c, 0xc1, 0xc1, 0xbd, 0xf3, 0x39, 0x21, 0x89, 0x79, 0x0c, 0x43, 0x00, 0x27, 0x71, 0x4a, - 0x68, 0x33, 0x97, 0x71, 0xa6, 0x4e, 0x4f, 0xb2, 0xeb, 0x40, 0xdc, 0xda, 0x12, 0x42, 0xb1, 0x97, 0x75, 0x62, 0xc8, - 0x92, 0xaa, 0xc7, 0xa4, 0xdc, 0x8c, 0x60, 0xd7, 0xfe, 0x14, 0x4f, 0x75, 0x18, 0x8a, 0x9b, 0x19, 0x18, 0x89, 0x99, - 0x90, 0x9c, 0x0d, 0x92, 0xe4, 0x99, 0x74, 0x59, 0x5b, 0x93, 0xba, 0xce, 0xdf, 0x32, 0x84, 0x47, 0x24, 0xe3, 0xfc, - 0x2a, 0x0f, 0x75, 0xc7, 0x95, 0x4d, 0xaa, 0x2c, 0x4f, 0x4f, 0xbe, 0xeb, 0x5e, 0xd7, 0x98, 0x1a, 0xde, 0x03, 0x6a, - 0x64, 0x71, 0xe8, 0x36, 0xe7, 0x63, 0x67, 0x82, 0x9f, 0xbb, 0x3c, 0x50, 0x17, 0x0f, 0x3b, 0x92, 0xd0, 0xcf, 0x37, - 0x78, 0x5d, 0x68, 0x74, 0xc6, 0x80, 0x9c, 0x24, 0xe7, 0xe2, 0x52, 0x0b, 0xd4, 0x58, 0xf0, 0xd5, 0x8e, 0xa4, 0x6e, - 0x23, 0x0f, 0x7c, 0x23, 0x2e, 0x84, 0x2e, 0x72, 0xdb, 0x74, 0x8d, 0xfc, 0x9c, 0xde, 0xad, 0x5a, 0xe0, 0x49, 0x7e, - 0xfd, 0x7b, 0x55, 0x7a, 0x42, 0xaf, 0x2a, 0x71, 0x16, 0x9f, 0xb8, 0x44, 0x37, 0xd3, 0x3c, 0x82, 0x93, 0xba, 0x6a, - 0xca, 0x00, 0xbd, 0x2e, 0xbc, 0x1d, 0x68, 0x12, 0x09, 0xbc, 0x30, 0xdd, 0x25, 0xae, 0xa4, 0x03, 0xe1, 0x41, 0xb1, - 0x87, 0x09, 0x26, 0x42, 0xa3, 0xcc, 0x86, 0x03, 0xc0, 0xcf, 0x21, 0xde, 0x8d, 0xf9, 0xab, 0x61, 0x59, 0x55, 0x0b, - 0x82, 0x3b, 0x65, 0x01, 0xd9, 0xcb, 0xc8, 0x80, 0x02, 0xea, 0x84, 0x2c, 0x28, 0x6d, 0xd4, 0xd8, 0x21, 0x67, 0x83, - 0x15, 0xaa, 0xe6, 0x01, 0xc7, 0x26, 0xdd, 0xda, 0xa7, 0x16, 0x62, 0x44, 0x83, 0x6a, 0x72, 0xfe, 0x3a, 0x40, 0x42, - 0xf9, 0x0c, 0x29, 0x70, 0xa4, 0x5f, 0x32, 0xff, 0x06, 0x4c, 0x7a, 0xa7, 0x20, 0xe8, 0x97, 0x21, 0xe3, 0x7e, 0xa9, - 0x23, 0x50, 0x5a, 0xc6, 0xf6, 0x0f, 0xc5, 0xf1, 0x0d, 0x67, 0x4c, 0xcf, 0xc9, 0xd7, 0x36, 0x9a, 0x3f, 0xaf, 0xd4, - 0x22, 0xc4, 0x4b, 0x42, 0x2a, 0x0c, 0x00, 0xbf, 0xb7, 0x92, 0xce, 0x63, 0xf0, 0xee, 0x01, 0xc7, 0x59, 0xad, 0x09, - 0xa5, 0x67, 0x40, 0xbe, 0xc5, 0xbf, 0x31, 0x4d, 0x07, 0x05, 0x70, 0x6a, 0x45, 0xde, 0xbb, 0xbb, 0xbb, 0x75, 0x28, - 0x18, 0xfa, 0x3a, 0x4c, 0x59, 0xbf, 0xe0, 0x28, 0x1b, 0xc8, 0x6d, 0xbb, 0xdd, 0x6d, 0x55, 0xd2, 0xce, 0x24, 0xc3, - 0x23, 0x89, 0x41, 0x2a, 0x8d, 0xfc, 0xac, 0x2b, 0xab, 0xcb, 0x2c, 0x8e, 0x14, 0x17, 0x80, 0xee, 0x78, 0x86, 0xcd, - 0x1b, 0x5b, 0xf5, 0x81, 0x77, 0x20, 0xcd, 0x75, 0x02, 0x00, 0xbc, 0xf0, 0x54, 0x31, 0xe1, 0x8e, 0xb9, 0xca, 0x4e, - 0xa2, 0x9e, 0x4c, 0x34, 0x07, 0xe7, 0xf9, 0xa8, 0x42, 0x3e, 0xe9, 0x0e, 0x2b, 0x3e, 0x2f, 0x02, 0xe2, 0x71, 0x9c, - 0x54, 0x06, 0x43, 0xa2, 0xe0, 0xa7, 0x22, 0xec, 0x78, 0xba, 0x70, 0x9e, 0xdc, 0x55, 0xe9, 0xce, 0x01, 0xaa, 0x21, - 0x01, 0xab, 0x82, 0x6d, 0xd8, 0xbc, 0xcc, 0x49, 0x5c, 0xb6, 0x33, 0x86, 0x64, 0x1d, 0x0e, 0x6a, 0xe1, 0x63, 0xaf, - 0xf4, 0x43, 0x52, 0x28, 0xc4, 0xb9, 0x08, 0xe7, 0x59, 0x48, 0x9e, 0x0e, 0x90, 0x19, 0x79, 0x39, 0x79, 0xaf, 0xdd, - 0xd9, 0xae, 0x5b, 0x82, 0x48, 0xb7, 0x78, 0x6b, 0xac, 0xa7, 0xe3, 0x95, 0x4d, 0xc7, 0x54, 0x05, 0x92, 0x4d, 0xa4, - 0x82, 0x2a, 0xa5, 0xc1, 0xca, 0xd3, 0x01, 0x50, 0x30, 0x37, 0xfc, 0xad, 0x71, 0x4f, 0xcb, 0x84, 0x61, 0x73, 0x34, - 0xd8, 0x24, 0x0e, 0xee, 0x07, 0x83, 0x4e, 0x21, 0x6e, 0xd4, 0x2e, 0x70, 0x0d, 0x36, 0xd1, 0xcc, 0xc4, 0x1e, 0xff, - 0x5e, 0x7e, 0x10, 0x59, 0x65, 0x57, 0x25, 0xcd, 0x44, 0xa2, 0x5c, 0xba, 0x08, 0xc9, 0x5e, 0xfd, 0x3b, 0xfd, 0x56, - 0xe8, 0x74, 0xa0, 0x00, 0x74, 0x1c, 0x29, 0x24, 0xc4, 0x4c, 0x93, 0xee, 0x89, 0xe7, 0xf7, 0x5f, 0x7f, 0xfd, 0xdd, - 0xd6, 0xd6, 0x7c, 0x15, 0xbc, 0xf3, 0x79, 0xd1, 0x84, 0xed, 0xce, 0x52, 0xea, 0xfa, 0x1d, 0x58, 0x00, 0x3b, 0xdb, - 0x78, 0x26, 0x86, 0xb7, 0x4d, 0xf4, 0xa0, 0x0b, 0xf2, 0xc2, 0xf1, 0xa3, 0xf6, 0x87, 0x8f, 0xb8, 0x55, 0x16, 0xe8, - 0xbd, 0xba, 0x33, 0x8b, 0x40, 0xcc, 0x00, 0x2a, 0x20, 0xaf, 0xa0, 0xab, 0x18, 0x82, 0xe0, 0x97, 0x06, 0x49, 0x87, - 0x13, 0xce, 0x04, 0x7c, 0x36, 0x08, 0xba, 0xf3, 0xb7, 0xc3, 0x8e, 0xee, 0x44, 0xbc, 0x77, 0xe8, 0xe2, 0xd7, 0x76, - 0xea, 0x90, 0x29, 0x4f, 0x2f, 0x8d, 0xae, 0xec, 0x42, 0x73, 0xbd, 0xd3, 0xa7, 0x12, 0xe2, 0x63, 0x36, 0x46, 0x2e, - 0x28, 0x5e, 0xc1, 0x40, 0xf3, 0x60, 0x93, 0x7c, 0xb1, 0xf5, 0x3a, 0xb8, 0x1f, 0x37, 0x8f, 0x14, 0xfb, 0x05, 0xd5, - 0x0f, 0xb8, 0x61, 0x17, 0x52, 0xcb, 0xc7, 0x05, 0xc6, 0xca, 0x38, 0x28, 0x7f, 0x4e, 0xbb, 0xd3, 0x0b, 0xbf, 0x58, - 0x14, 0x15, 0x53, 0x12, 0xbf, 0x4d, 0xc2, 0xa4, 0x71, 0xaf, 0x5b, 0xd3, 0xe3, 0xf4, 0xbc, 0x20, 0x9c, 0x3b, 0xb9, - 0x7b, 0xfe, 0x4b, 0xb4, 0x3e, 0x9b, 0xe3, 0x76, 0xd7, 0xad, 0xe9, 0x77, 0x83, 0xa5, 0x4a, 0x93, 0x6e, 0x69, 0xec, - 0x5c, 0xbd, 0x09, 0x97, 0x75, 0x11, 0x89, 0xee, 0xcf, 0x7a, 0x2c, 0xa8, 0xd4, 0x33, 0x33, 0x7f, 0x0a, 0xa2, 0x86, - 0xb8, 0xde, 0xea, 0xe2, 0xbd, 0x5e, 0x7c, 0x4b, 0x8e, 0xbd, 0x74, 0x95, 0x64, 0x30, 0xa8, 0x0e, 0x5d, 0x0d, 0x8b, - 0xe4, 0x88, 0xa8, 0x5f, 0x31, 0x09, 0x98, 0xf5, 0x9c, 0x8f, 0xae, 0xd7, 0xa2, 0x79, 0xfa, 0xd6, 0x13, 0xa1, 0x7f, - 0xae, 0xc3, 0xed, 0xfb, 0x04, 0xae, 0xb6, 0xad, 0x63, 0x19, 0x8d, 0xe2, 0xcb, 0x46, 0x22, 0x66, 0x61, 0x47, 0xa2, - 0x4f, 0xff, 0x80, 0x48, 0xa2, 0xfc, 0xa4, 0xa5, 0x07, 0x49, 0x25, 0xdb, 0x6f, 0xf8, 0x70, 0x1f, 0xb5, 0x10, 0x68, - 0x6f, 0xff, 0x28, 0x52, 0x35, 0xbd, 0x4c, 0x24, 0xb1, 0xea, 0x40, 0xbd, 0xa6, 0xd4, 0xe7, 0x3e, 0xff, 0x7c, 0xfb, - 0x1d, 0x25, 0x64, 0x9a, 0x28, 0x59, 0xce, 0x18, 0x40, 0xae, 0xb1, 0xbb, 0x92, 0x90, 0x35, 0xbc, 0x4c, 0x4a, 0xef, - 0xc3, 0xcf, 0x67, 0xeb, 0xd0, 0x77, 0xff, 0x94, 0xc6, 0x65, 0xc1, 0x39, 0xf3, 0x66, 0xfe, 0x98, 0x9e, 0x06, 0x82, - 0x35, 0xaf, 0xb1, 0x77, 0x97, 0xeb, 0xcb, 0xd2, 0xe9, 0xa2, 0x5d, 0x3a, 0x5d, 0xb4, 0xda, 0x1b, 0xe6, 0xdf, 0xac, - 0x63, 0x0e, 0xbc, 0x5a, 0xb6, 0x0d, 0xa6, 0x12, 0x3c, 0xb5, 0xe5, 0x3f, 0x3a, 0x03, 0x57, 0x1e, 0x90, 0x1a, 0x6d, - 0xa0, 0x4f, 0x65, 0x10, 0x74, 0x73, 0xc3, 0x82, 0xa6, 0xab, 0x32, 0x23, 0xcd, 0x7c, 0x24, 0x5d, 0xf0, 0x39, 0x8d, - 0x39, 0xd8, 0xa7, 0xa9, 0xf2, 0x32, 0x14, 0x33, 0x7e, 0x56, 0xda, 0x82, 0xa6, 0x43, 0xe1, 0x47, 0x5c, 0xa6, 0x06, - 0xf4, 0xa2, 0xf3, 0x6b, 0x98, 0xc7, 0x59, 0xfa, 0x9b, 0xa7, 0x18, 0xe3, 0xf3, 0x86, 0x4c, 0xe1, 0xb8, 0xeb, 0x5e, - 0xa2, 0x80, 0x9f, 0x13, 0x1a, 0xcb, 0xf8, 0xbd, 0x18, 0xb4, 0x2f, 0xd2, 0x6d, 0x2e, 0x02, 0xa7, 0x02, 0xe4, 0x0f, - 0x09, 0xe3, 0x40, 0xd1, 0xd1, 0x5e, 0x63, 0xdf, 0x29, 0x55, 0xa6, 0xcf, 0x3d, 0xad, 0xd1, 0x13, 0xa5, 0x4c, 0x3f, - 0x19, 0x63, 0xcc, 0xba, 0xc8, 0xb1, 0xa5, 0xf9, 0xc0, 0x20, 0x93, 0x7c, 0xe1, 0x22, 0xa7, 0xc7, 0x9c, 0x3a, 0x0b, - 0x74, 0xab, 0x50, 0x6b, 0x0f, 0x96, 0x3f, 0xa0, 0x72, 0x60, 0xa8, 0x28, 0xfb, 0x71, 0x8a, 0x2d, 0xe2, 0x43, 0xfb, - 0x0d, 0xb7, 0x90, 0xb8, 0xed, 0x45, 0x26, 0x82, 0x54, 0x83, 0xa2, 0x58, 0xdb, 0x24, 0x23, 0xb9, 0xa1, 0x8a, 0xc1, - 0x46, 0x2d, 0x9f, 0x3e, 0x83, 0xd3, 0xe5, 0xd3, 0xd3, 0x9c, 0x5a, 0xb4, 0x25, 0x33, 0xf5, 0x8c, 0xc4, 0xd2, 0x15, - 0x76, 0xf1, 0xf2, 0x6b, 0xbc, 0xa1, 0x7d, 0xcc, 0x40, 0x22, 0x29, 0xbd, 0x6a, 0x1a, 0xc4, 0x0c, 0x36, 0x90, 0x46, - 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x4e, 0x40, 0x00, 0x46, 0x0f, 0x3f, 0x7a, 0x43, 0xe9, 0xb4, 0xd9, 0xed, 0x76, 0x56, - 0x26, 0x50, 0x74, 0xcd, 0x27, 0x63, 0x92, 0x37, 0x84, 0x9d, 0xc5, 0x2d, 0x79, 0x2a, 0x84, 0x31, 0x78, 0x79, 0x66, - 0x6c, 0x31, 0x7f, 0x7e, 0x3d, 0xd6, 0x2f, 0x0c, 0x25, 0x51, 0x52, 0xc8, 0xbe, 0xd4, 0x2d, 0x33, 0x1c, 0x59, 0x9c, - 0xe6, 0xe4, 0xd2, 0x83, 0x33, 0xf5, 0x18, 0x78, 0x0e, 0x04, 0xf2, 0xfa, 0x0e, 0xfb, 0xed, 0xc0, 0x09, 0x47, 0xfc, - 0x14, 0xf3, 0xf1, 0x4f, 0xd5, 0x42, 0xf6, 0xcc, 0xea, 0xbc, 0x53, 0x16, 0xbb, 0x2a, 0x54, 0x51, 0x67, 0x0a, 0x2a, - 0xf8, 0xad, 0x43, 0x04, 0x6d, 0xfb, 0x49, 0x92, 0x21, 0x12, 0x55, 0x81, 0xfa, 0x6c, 0x26, 0x92, 0x60, 0x2e, 0xc0, - 0x92, 0xe5, 0x0d, 0xe7, 0xbc, 0xf6, 0xb7, 0xae, 0x49, 0xe6, 0x0d, 0x70, 0xd1, 0x7c, 0xda, 0xe9, 0xe9, 0x3a, 0xf2, - 0xad, 0x87, 0xa9, 0x75, 0xa8, 0x05, 0xb3, 0x84, 0x8b, 0x59, 0xb9, 0x89, 0x7d, 0x79, 0x1b, 0xa8, 0x99, 0x1c, 0x84, - 0xca, 0x9f, 0x98, 0x9c, 0x52, 0x1b, 0xa9, 0x90, 0xb5, 0x87, 0xcc, 0x49, 0x07, 0x21, 0xdc, 0x86, 0xf4, 0xdb, 0xf9, - 0x65, 0x87, 0x4c, 0xf6, 0xa3, 0x2d, 0x0c, 0xe9, 0xff, 0x7a, 0x85, 0x49, 0x68, 0x30, 0x42, 0xb8, 0x9f, 0x04, 0x08, - 0xf7, 0xa2, 0x53, 0x16, 0xe1, 0xc2, 0x9d, 0x47, 0x61, 0xbf, 0x77, 0x36, 0x54, 0x86, 0x05, 0xe7, 0x07, 0xcd, 0xcf, - 0x71, 0x10, 0x8e, 0xf5, 0x9a, 0x3c, 0x30, 0x7e, 0xfc, 0x91, 0xbd, 0x40, 0xc0, 0x7c, 0x37, 0x11, 0xb4, 0xea, 0x14, - 0x28, 0x0b, 0xd6, 0x38, 0x18, 0x48, 0x0a, 0x16, 0xfb, 0x46, 0xaa, 0x7a, 0x9b, 0xb2, 0x2d, 0x9f, 0xe5, 0x49, 0xc7, - 0xe9, 0x5f, 0xd6, 0x7a, 0x9b, 0x10, 0x62, 0x5f, 0xf4, 0xb9, 0xf2, 0x01, 0x4a, 0xb4, 0xda, 0xe7, 0xff, 0x25, 0xb8, - 0xf5, 0xf5, 0xdf, 0x79, 0x35, 0xd3, 0x46, 0x8a, 0x59, 0x14, 0x5e, 0x7b, 0xa9, 0xac, 0x19, 0x9f, 0x90, 0xad, 0x66, - 0x4d, 0x36, 0x4e, 0x05, 0xc5, 0x4d, 0x5d, 0x0b, 0xb6, 0x98, 0x96, 0x6c, 0xde, 0x16, 0x93, 0x78, 0x63, 0x7e, 0x49, - 0xcb, 0xb1, 0x39, 0x17, 0xda, 0x8a, 0x41, 0xa3, 0x8e, 0x87, 0x8d, 0x9e, 0x13, 0x9d, 0x32, 0x5d, 0xaf, 0x1c, 0x37, - 0x55, 0xb5, 0xbf, 0x04, 0x0e, 0x9d, 0xda, 0x0a, 0x91, 0x56, 0xcb, 0x51, 0x43, 0x9e, 0x61, 0x59, 0x2b, 0x03, 0xe1, - 0x3a, 0x90, 0x76, 0xe7, 0xaf, 0xb3, 0xe4, 0x59, 0x70, 0xcb, 0x12, 0x8f, 0xf0, 0xa5, 0x66, 0x72, 0x8b, 0xe4, 0x15, - 0x93, 0x28, 0x0f, 0xe5, 0xc1, 0xee, 0xfc, 0x7c, 0xa2, 0xbd, 0x92, 0x2c, 0xe7, 0x33, 0xcd, 0x0b, 0x10, 0x42, 0xa6, - 0x6b, 0x09, 0x6d, 0xd9, 0x0b, 0xf6, 0xc4, 0xb8, 0x7a, 0x4a, 0x92, 0xf9, 0x25, 0x38, 0xf8, 0xeb, 0x7e, 0x9b, 0xa5, - 0x35, 0xf8, 0xdb, 0xbb, 0xc5, 0x4c, 0x6c, 0x2f, 0xb4, 0x19, 0xa9, 0x90, 0x7d, 0xff, 0xd7, 0x81, 0x78, 0x13, 0x98, - 0x1f, 0xea, 0xa8, 0x71, 0x74, 0x4f, 0x35, 0xfe, 0x2f, 0x1c, 0x36, 0x5a, 0x7a, 0xed, 0x68, 0xae, 0x91, 0x80, 0xc9, - 0x91, 0x7b, 0x55, 0xdf, 0x8b, 0x82, 0xbd, 0xe1, 0x81, 0x40, 0x59, 0xcd, 0xfe, 0x7e, 0xfd, 0x20, 0x00, 0x70, 0xa5, - 0x67, 0x1d, 0xaf, 0xe5, 0x67, 0xdb, 0x6d, 0x6c, 0xc0, 0xe5, 0x5a, 0xc1, 0x7f, 0x15, 0x47, 0xe8, 0xaf, 0xcd, 0x24, - 0x87, 0xed, 0xba, 0x1e, 0x0a, 0x3a, 0x64, 0xcc, 0x29, 0x06, 0x71, 0x3d, 0xf9, 0x92, 0xf5, 0x3a, 0x30, 0x6f, 0x82, - 0xda, 0xfc, 0x62, 0xef, 0xc5, 0x5e, 0x65, 0xd2, 0xa0, 0x29, 0x82, 0xff, 0x02, 0xf5, 0x01, 0xfe, 0xf4, 0x82, 0xb0, - 0x28, 0x7e, 0x50, 0x1c, 0xce, 0xb0, 0xc0, 0x66, 0x56, 0x1a, 0x5a, 0x07, 0xc6, 0x8f, 0x19, 0x3d, 0xf5, 0x09, 0xc6, - 0xa1, 0xc8, 0xd9, 0x39, 0x38, 0xc9, 0x51, 0xaa, 0x95, 0xfb, 0xfb, 0x4d, 0x9e, 0x84, 0x49, 0x4b, 0x3b, 0xf7, 0x27, - 0x68, 0x1f, 0xab, 0x3f, 0xff, 0xc7, 0xb1, 0x9b, 0x31, 0x2c, 0xa3, 0x76, 0x13, 0xbf, 0x3f, 0x81, 0x1b, 0x35, 0x4f, - 0xa9, 0xdb, 0xbd, 0x33, 0x7f, 0xd7, 0xb7, 0xf6, 0xf8, 0x69, 0xa0, 0x34, 0x86, 0xb1, 0x00, 0xb1, 0x98, 0xc6, 0x4b, - 0x63, 0x79, 0x07, 0x33, 0x37, 0x6c, 0xa3, 0x6f, 0x66, 0x7c, 0xeb, 0xe7, 0x0c, 0x41, 0x03, 0x62, 0xd4, 0x74, 0x69, - 0x45, 0xa5, 0xdf, 0xa5, 0xb8, 0xf3, 0x26, 0x14, 0x68, 0x9e, 0xfb, 0x1c, 0x0a, 0xa7, 0xa3, 0x48, 0x25, 0x25, 0xc0, - 0x3a, 0x59, 0x7e, 0xd6, 0x2e, 0xe2, 0xfd, 0x85, 0xd0, 0x25, 0xbc, 0xae, 0x53, 0xc4, 0xaf, 0xc5, 0x70, 0x33, 0x4d, - 0x37, 0x1b, 0xa8, 0x2f, 0xcb, 0x2e, 0x9d, 0x83, 0x23, 0xf8, 0x6a, 0x8d, 0x54, 0x44, 0xce, 0x50, 0x5f, 0x24, 0xd6, - 0x70, 0xe8, 0x23, 0x0e, 0xd6, 0xa5, 0xea, 0x80, 0x26, 0xdf, 0xac, 0x76, 0xd9, 0x69, 0xa3, 0x39, 0x4d, 0x4d, 0x31, - 0x83, 0x18, 0x0e, 0x3e, 0x89, 0xd0, 0xd9, 0xb4, 0x8f, 0x9b, 0xac, 0x89, 0x33, 0x34, 0x0d, 0xd7, 0x31, 0x5a, 0x55, - 0xc2, 0xac, 0xb2, 0x8d, 0xc7, 0x53, 0xda, 0x55, 0xeb, 0x9e, 0x08, 0x3b, 0xe7, 0xd2, 0x51, 0xab, 0x09, 0xda, 0x26, - 0x22, 0x85, 0xe2, 0xb0, 0xd5, 0x84, 0xbe, 0x3b, 0xac, 0x58, 0x61, 0xc5, 0xdb, 0x25, 0xf5, 0x3a, 0x66, 0x1c, 0xae, - 0x84, 0xc5, 0x1c, 0x60, 0xe0, 0x97, 0xb1, 0xf2, 0x81, 0x9a, 0xe4, 0x54, 0x7a, 0x48, 0x79, 0x97, 0x52, 0x9d, 0xcc, - 0x63, 0xff, 0xe2, 0xee, 0xf5, 0xa5, 0xf9, 0xe2, 0x6e, 0x32, 0xde, 0x42, 0x98, 0x3a, 0x6d, 0xa0, 0x2e, 0x6b, 0x3b, - 0x22, 0x74, 0xb9, 0x4f, 0xb4, 0x18, 0xef, 0x29, 0x74, 0x97, 0x93, 0xce, 0x09, 0xd5, 0x7f, 0x0a, 0x44, 0xf9, 0x88, - 0x32, 0xc8, 0xdd, 0x9d, 0x8a, 0x5d, 0xc9, 0xd3, 0x9d, 0x24, 0x3e, 0x56, 0xdf, 0x30, 0x32, 0x68, 0x6d, 0x9d, 0xa8, - 0xf6, 0x9d, 0xf5, 0x3e, 0x41, 0x8c, 0x75, 0x4b, 0x2c, 0xcb, 0xb7, 0xcb, 0x1d, 0xd2, 0x80, 0x38, 0xb7, 0x97, 0x61, - 0x5d, 0xce, 0xd1, 0x08, 0xf3, 0x65, 0x2c, 0x25, 0x24, 0x20, 0x92, 0x3e, 0x4e, 0x48, 0x97, 0xe2, 0xef, 0xba, 0xc3, - 0x65, 0x79, 0x12, 0xc2, 0x7c, 0xf4, 0x32, 0x66, 0x52, 0x97, 0xe0, 0x6b, 0xbc, 0xc9, 0x2f, 0x09, 0xb8, 0x24, 0x9a, - 0x5e, 0x5f, 0x71, 0xaa, 0x4b, 0xd5, 0xdb, 0x16, 0x14, 0xa7, 0xe9, 0x57, 0x2d, 0xc9, 0x2d, 0xf1, 0x99, 0xb1, 0x60, - 0x10, 0xa8, 0x43, 0x45, 0x2f, 0x03, 0x15, 0x63, 0x2c, 0x22, 0x4e, 0x97, 0x5f, 0x32, 0xa9, 0xae, 0x74, 0xa8, 0xda, - 0xb3, 0xf7, 0x17, 0x4f, 0x76, 0x78, 0x34, 0x7d, 0xfa, 0xe3, 0xeb, 0x41, 0x0f, 0xaa, 0xa0, 0x53, 0xb8, 0xdd, 0xd9, - 0xc0, 0x50, 0x28, 0x40, 0x56, 0x76, 0x2e, 0xcb, 0x00, 0xea, 0x4c, 0x4d, 0x49, 0x77, 0x7d, 0xdd, 0x9b, 0x44, 0x7a, - 0xd9, 0x30, 0xe3, 0xe7, 0xd0, 0x92, 0x9f, 0x4d, 0xf3, 0xcb, 0x1d, 0x6d, 0x63, 0x39, 0xe2, 0x29, 0xb0, 0xb1, 0x30, - 0x78, 0x0f, 0x29, 0x6e, 0xc2, 0x20, 0x43, 0x0e, 0x92, 0xbc, 0xd2, 0x96, 0xe5, 0xb9, 0x96, 0x92, 0x0d, 0x33, 0x7e, - 0x4f, 0x8a, 0x02, 0xe5, 0x77, 0x89, 0xb7, 0x71, 0x43, 0x00, 0x4e, 0x50, 0xda, 0x1c, 0x39, 0x56, 0x71, 0x2b, 0xbf, - 0x31, 0x78, 0x11, 0x81, 0x9e, 0x29, 0x1c, 0xe3, 0xf9, 0xc3, 0x7e, 0x1c, 0x21, 0x48, 0x05, 0x3f, 0xac, 0xd4, 0x66, - 0x47, 0x2f, 0xfd, 0xd7, 0xac, 0xa6, 0x47, 0x46, 0xba, 0xdb, 0x24, 0x6a, 0xcb, 0x4e, 0x54, 0x80, 0x19, 0x44, 0x63, - 0xe0, 0x82, 0x3b, 0xc6, 0x34, 0x1f, 0xfe, 0xdb, 0x4f, 0xac, 0x3d, 0xcc, 0xdf, 0xce, 0x78, 0xe5, 0xc9, 0x4b, 0x64, - 0x81, 0x9a, 0x8f, 0x5d, 0x5f, 0x5e, 0xc6, 0x77, 0xeb, 0x3e, 0x9e, 0xba, 0x05, 0x59, 0x40, 0x80, 0x81, 0xf8, 0x99, - 0x33, 0xd1, 0x1b, 0xc2, 0x9d, 0xd4, 0xc4, 0xd3, 0x5a, 0xcd, 0x6f, 0xf2, 0xf6, 0xda, 0x45, 0x0d, 0xc9, 0x5b, 0x67, - 0xed, 0x66, 0x55, 0x7a, 0x6c, 0x4d, 0xf2, 0xfd, 0x9a, 0x49, 0x96, 0xfa, 0x5f, 0xc3, 0xad, 0xb1, 0x7d, 0xbb, 0x0a, - 0xcb, 0x3a, 0xcc, 0x5f, 0x5e, 0x5f, 0x72, 0x1c, 0xe7, 0xbc, 0xf8, 0x8d, 0x35, 0xb6, 0xf0, 0xe6, 0x64, 0x4b, 0xc2, - 0x65, 0x6a, 0x35, 0xf7, 0xac, 0x56, 0xb5, 0x67, 0x49, 0xc8, 0xcd, 0x5e, 0xf6, 0x00, 0x9d, 0xbf, 0x37, 0xe9, 0x73, - 0xfc, 0x5e, 0x67, 0xcd, 0xe9, 0x7b, 0x83, 0x34, 0xd7, 0x9f, 0x22, 0xb2, 0x78, 0x66, 0x9d, 0x3c, 0xaa, 0xec, 0x15, - 0x93, 0x69, 0x3e, 0x26, 0xe4, 0x0a, 0x61, 0x58, 0x55, 0xbb, 0x3e, 0x3d, 0xa1, 0xe2, 0x86, 0x03, 0xc8, 0x6d, 0x7c, - 0x3e, 0xc8, 0x0d, 0xfe, 0x5e, 0xd9, 0x59, 0x0e, 0x3a, 0x0b, 0x6d, 0x7e, 0xec, 0xa1, 0xee, 0xc7, 0xe1, 0x61, 0x08, - 0xae, 0xcc, 0xde, 0x9c, 0xaa, 0x5f, 0x03, 0xd2, 0xea, 0x9c, 0xdb, 0xae, 0x20, 0x17, 0x7b, 0xfd, 0x4a, 0xb9, 0x37, - 0x0a, 0x44, 0x63, 0x43, 0x49, 0xea, 0x2c, 0xf2, 0xdd, 0x90, 0x3a, 0xb9, 0xdb, 0xce, 0xe8, 0x68, 0x7d, 0xe2, 0x23, - 0xfe, 0x54, 0x0d, 0x55, 0x98, 0xaf, 0xe7, 0x36, 0xcb, 0x7a, 0x80, 0xc6, 0x11, 0x69, 0x56, 0xd7, 0x9b, 0x92, 0x5e, - 0xad, 0x88, 0x4c, 0x68, 0x0c, 0xbe, 0xc9, 0xe0, 0x20, 0x1f, 0x57, 0x42, 0x2f, 0x92, 0x6e, 0xca, 0x27, 0xfb, 0x5f, - 0x45, 0x7b, 0x31, 0x07, 0x10, 0xfb, 0x16, 0x5d, 0x60, 0xb6, 0x56, 0x60, 0x8f, 0xd0, 0x1c, 0x2f, 0x11, 0xbd, 0xac, - 0x2c, 0x54, 0x5c, 0x58, 0x13, 0xd6, 0x7a, 0x9f, 0xb5, 0xc2, 0x69, 0xee, 0xfc, 0x53, 0x5d, 0x84, 0x50, 0xe2, 0x53, - 0x99, 0xd5, 0x80, 0x62, 0xa8, 0x81, 0x64, 0x3f, 0x39, 0xbf, 0xf2, 0x59, 0x64, 0x06, 0xe4, 0x6b, 0xb7, 0xe3, 0x83, - 0x3b, 0x1e, 0x8c, 0x3b, 0xbe, 0x6d, 0x3f, 0xb5, 0xd6, 0x9b, 0x49, 0x56, 0x4d, 0x33, 0x73, 0xde, 0x05, 0x86, 0x1d, - 0x0e, 0x2e, 0xcf, 0xce, 0xe7, 0x2e, 0x68, 0xda, 0x13, 0x96, 0xa9, 0x45, 0x73, 0x1b, 0xf0, 0xe4, 0x23, 0x7a, 0x4a, - 0x23, 0x39, 0xbb, 0xc3, 0x7b, 0x20, 0x77, 0x28, 0x7d, 0x6a, 0x25, 0x5f, 0xb0, 0x62, 0xc1, 0x79, 0xb3, 0x20, 0x16, - 0xcb, 0xa6, 0xea, 0x25, 0x48, 0x3a, 0xc4, 0xf9, 0x6c, 0x70, 0x9d, 0x4a, 0xa1, 0x1b, 0xfc, 0x7f, 0x89, 0x91, 0x1c, - 0xb6, 0xa2, 0x20, 0x98, 0x3a, 0x27, 0x41, 0x25, 0x62, 0xff, 0x46, 0x86, 0x0e, 0xfe, 0x0c, 0xaa, 0x94, 0x7d, 0x44, - 0x97, 0x3e, 0xbb, 0x37, 0xc1, 0x89, 0xd8, 0xee, 0x19, 0xe9, 0x7c, 0x48, 0x68, 0x7f, 0x7e, 0xfe, 0xcd, 0x65, 0x1f, - 0x19, 0x62, 0xbe, 0xae, 0xdd, 0x9b, 0xf7, 0x20, 0xd5, 0xb3, 0x3f, 0x47, 0x2c, 0x86, 0xb3, 0xcc, 0x84, 0xe7, 0x51, - 0x4c, 0xaf, 0xdd, 0x37, 0x78, 0x12, 0x48, 0x18, 0x43, 0xd0, 0x3e, 0x5c, 0xe1, 0x9b, 0xaf, 0x22, 0x26, 0x6b, 0x48, - 0xf8, 0xf8, 0xac, 0xf8, 0xad, 0xb3, 0x17, 0xb5, 0xb8, 0x61, 0x68, 0xa6, 0x8e, 0xd3, 0x3c, 0x6f, 0xc1, 0x7d, 0x9e, - 0xda, 0x73, 0xa2, 0xd2, 0x68, 0x9d, 0xe7, 0xeb, 0x37, 0x61, 0x56, 0x2d, 0xdd, 0xe6, 0xef, 0xc2, 0xd8, 0x56, 0xa8, - 0x22, 0xff, 0xbc, 0x8b, 0xb0, 0x1f, 0x71, 0x1a, 0x68, 0x24, 0xbf, 0x6a, 0x4b, 0xbe, 0xf2, 0x4e, 0xc2, 0x2c, 0xcc, - 0x4d, 0xac, 0x8b, 0x8d, 0x32, 0x3f, 0x8b, 0xc9, 0xcf, 0x54, 0xe4, 0x63, 0xe3, 0x8a, 0xae, 0xf6, 0x09, 0xf1, 0xf0, - 0x68, 0x7d, 0x18, 0x77, 0xcb, 0x62, 0x6d, 0x56, 0xe6, 0x8b, 0xb2, 0x2b, 0xb5, 0xcf, 0xd3, 0x17, 0xfc, 0x68, 0xb1, - 0x3e, 0xd8, 0xb9, 0x97, 0x08, 0xc8, 0xa0, 0x5a, 0x96, 0xb6, 0x43, 0xe4, 0xe1, 0xe5, 0x26, 0x2f, 0x79, 0x9b, 0x27, - 0x2a, 0x4a, 0xdb, 0x21, 0xf0, 0xdd, 0x7d, 0x9d, 0x1c, 0xd0, 0x25, 0xcc, 0xd3, 0x15, 0x40, 0x6b, 0xc0, 0x42, 0x6e, - 0x56, 0x27, 0xf6, 0x5c, 0x95, 0x6c, 0xda, 0xdb, 0x35, 0xf9, 0x73, 0x07, 0x94, 0x13, 0x6e, 0xec, 0xcb, 0xc8, 0xb0, - 0x5c, 0x95, 0x6e, 0x84, 0xcf, 0xfa, 0xc8, 0x9d, 0x67, 0x1f, 0xf0, 0xc3, 0x6f, 0xc9, 0x3d, 0xfa, 0xeb, 0x3c, 0x32, - 0x2d, 0xdf, 0x16, 0x34, 0x6a, 0x1c, 0xa2, 0xf1, 0x56, 0x12, 0x10, 0x15, 0x55, 0x03, 0x1e, 0x53, 0x7e, 0x16, 0x2c, - 0x8f, 0x64, 0x94, 0x1d, 0xf2, 0xa5, 0xb6, 0xfb, 0xb1, 0x35, 0xf1, 0xcf, 0xac, 0x43, 0xab, 0xac, 0x4f, 0x86, 0x2f, - 0xb5, 0xdd, 0xde, 0x7b, 0xa1, 0x80, 0x08, 0xb0, 0x87, 0xc1, 0xe7, 0xd8, 0x5a, 0x2d, 0xf8, 0xfc, 0xf8, 0xf9, 0x81, - 0x3b, 0x56, 0xcc, 0x79, 0xdf, 0xf5, 0x5d, 0x80, 0x92, 0xcc, 0x08, 0x03, 0x3b, 0x66, 0x37, 0xc6, 0x90, 0xc4, 0x49, - 0xa3, 0x71, 0x1f, 0xc4, 0x09, 0xbd, 0x35, 0xec, 0x00, 0x70, 0x89, 0x3c, 0x19, 0x2e, 0x53, 0x48, 0x97, 0xc8, 0x87, - 0xe9, 0x7b, 0x5c, 0x91, 0x45, 0x02, 0x7c, 0xc3, 0x6b, 0x25, 0xdb, 0x26, 0x58, 0x41, 0x8b, 0x62, 0x0e, 0x64, 0x3a, - 0x4b, 0x15, 0xdf, 0x30, 0xe2, 0x9c, 0x3f, 0x74, 0x9b, 0x37, 0x17, 0x33, 0x5e, 0x3f, 0x9f, 0xfa, 0xb4, 0x97, 0x09, - 0xed, 0x68, 0x4e, 0x33, 0x30, 0xa0, 0xe8, 0x57, 0xc5, 0xe6, 0x4f, 0xb0, 0x44, 0xc9, 0x3f, 0xda, 0xc8, 0xce, 0x9f, - 0x10, 0xfa, 0x88, 0x24, 0x60, 0xa2, 0xb1, 0xfd, 0x74, 0x4e, 0xd1, 0xdb, 0xaa, 0x86, 0xae, 0x08, 0x0b, 0xef, 0x83, - 0x1d, 0x5b, 0xb8, 0x36, 0x43, 0xd1, 0x38, 0xa2, 0x1e, 0x98, 0xf7, 0x65, 0xc7, 0x69, 0xbe, 0x6f, 0x6c, 0x10, 0xa4, - 0x3e, 0x6f, 0x45, 0x26, 0x07, 0x24, 0x25, 0x36, 0xb0, 0xf0, 0xb8, 0x79, 0xba, 0xac, 0x4b, 0xbe, 0x77, 0x59, 0x9d, - 0xba, 0xa2, 0xb1, 0x85, 0x12, 0x67, 0x2c, 0x1a, 0x8c, 0x29, 0x11, 0x49, 0xe6, 0x42, 0xb0, 0x46, 0xc3, 0xdf, 0x7c, - 0x22, 0x68, 0x3e, 0xe1, 0xb1, 0xf7, 0x09, 0x77, 0x32, 0x99, 0xde, 0x50, 0x13, 0x65, 0x3b, 0x7a, 0xf7, 0xf3, 0x81, - 0xd2, 0x4e, 0x73, 0x3e, 0x96, 0x31, 0x73, 0xc9, 0x02, 0x94, 0x99, 0x08, 0x11, 0x90, 0x43, 0x8f, 0x3b, 0xc9, 0x22, - 0x41, 0xaf, 0xf1, 0x15, 0x26, 0x52, 0xd3, 0x91, 0xd9, 0xeb, 0x6a, 0x22, 0x1a, 0x8f, 0x1c, 0x29, 0xf0, 0x62, 0xbc, - 0xc9, 0xa8, 0x4b, 0xb1, 0x5a, 0xbc, 0x61, 0x92, 0x29, 0x7e, 0xf2, 0xd7, 0xf6, 0x27, 0x27, 0xe4, 0xbd, 0x9e, 0x5a, - 0xa1, 0xdf, 0xf3, 0xc6, 0xd6, 0xa5, 0xa0, 0xdd, 0xff, 0x6c, 0xc9, 0x28, 0xda, 0x98, 0x56, 0xcf, 0xe2, 0x4b, 0xfd, - 0xa2, 0x97, 0xc8, 0xe5, 0x4d, 0x1e, 0xdb, 0x87, 0x11, 0xa3, 0xd0, 0x5a, 0x85, 0xd9, 0x7b, 0x8f, 0x62, 0x63, 0xef, - 0xb5, 0x42, 0x34, 0xce, 0x21, 0xba, 0x84, 0xcb, 0x8d, 0x97, 0xc8, 0x24, 0x3e, 0x39, 0xe3, 0x2c, 0xf3, 0x6f, 0xa9, - 0x48, 0x58, 0xce, 0x32, 0x8f, 0xd1, 0xc3, 0xde, 0x54, 0x25, 0x9b, 0x02, 0x4e, 0x51, 0xd6, 0x8a, 0xb8, 0x99, 0xce, - 0x77, 0xad, 0x40, 0x6b, 0xe2, 0x67, 0x30, 0x8a, 0xc9, 0x6a, 0xf2, 0xe6, 0xd5, 0x7f, 0x73, 0xe2, 0x5f, 0x54, 0x33, - 0xfe, 0x50, 0xc6, 0xf8, 0x97, 0x8b, 0x75, 0x58, 0xf9, 0x7d, 0x73, 0x28, 0x09, 0x70, 0x8d, 0x93, 0x4a, 0x7c, 0xad, - 0x70, 0x8e, 0x00, 0xfa, 0xae, 0xbb, 0x24, 0xd4, 0x0b, 0x8e, 0x06, 0x1d, 0x16, 0x23, 0x58, 0x1c, 0x13, 0x7d, 0x74, - 0xff, 0x77, 0xc5, 0x00, 0x2d, 0x46, 0x23, 0xd7, 0x5f, 0xcf, 0xc5, 0xb1, 0x22, 0xc9, 0x26, 0x57, 0x58, 0x88, 0x11, - 0x02, 0x08, 0xb9, 0x48, 0x02, 0x1d, 0xe7, 0x07, 0x9f, 0x8a, 0x17, 0x8d, 0x48, 0x01, 0x68, 0x48, 0xfb, 0x6b, 0x80, - 0xc0, 0x21, 0x98, 0x23, 0x41, 0x30, 0x92, 0x67, 0x01, 0x91, 0x13, 0xb2, 0x77, 0xa2, 0x42, 0x84, 0x59, 0x1d, 0xec, - 0x7a, 0x83, 0xba, 0x80, 0x2d, 0x9a, 0xe7, 0x48, 0x50, 0x54, 0x21, 0x22, 0x2c, 0x2b, 0x36, 0x57, 0xaf, 0xd6, 0xbc, - 0x47, 0x85, 0x17, 0x85, 0x2e, 0x99, 0x3e, 0xcd, 0x2e, 0xa1, 0xcc, 0x2f, 0xc0, 0xbf, 0x16, 0x75, 0x60, 0xcf, 0xbb, - 0x0e, 0x1d, 0x5b, 0x71, 0x72, 0x2a, 0x2e, 0x7f, 0xce, 0x39, 0x00, 0x4a, 0x7a, 0xd6, 0x21, 0x86, 0x06, 0x9d, 0xeb, - 0x96, 0x6b, 0xd2, 0x00, 0x0c, 0x97, 0x8c, 0x57, 0x86, 0xda, 0xd6, 0xb3, 0xeb, 0x17, 0x7f, 0x46, 0x66, 0x8e, 0x0e, - 0x4d, 0xbc, 0x88, 0x12, 0x77, 0x59, 0x5c, 0x02, 0x15, 0xaf, 0xf3, 0x51, 0xad, 0x6b, 0xe5, 0x95, 0xed, 0x1a, 0x87, - 0x0b, 0x1a, 0x82, 0x2d, 0xbc, 0x6a, 0xc0, 0x75, 0xb8, 0xac, 0x8b, 0xc0, 0x8f, 0x9e, 0x16, 0x05, 0xca, 0xdb, 0xb5, - 0x20, 0x0d, 0x3d, 0xd9, 0x89, 0xca, 0xa7, 0x69, 0xe9, 0xef, 0xcd, 0x7a, 0xf9, 0x8e, 0x16, 0x53, 0x8e, 0x43, 0x85, - 0x3f, 0x03, 0xc2, 0xa6, 0xb8, 0x1b, 0x14, 0x0d, 0xe5, 0xc5, 0x0d, 0x84, 0x72, 0x3a, 0x3b, 0x7c, 0xdb, 0x69, 0x56, - 0x11, 0xc4, 0xbc, 0x1f, 0xfd, 0xa7, 0x5c, 0x56, 0x60, 0xe9, 0x74, 0xec, 0x71, 0x93, 0x39, 0x47, 0x79, 0xde, 0xf6, - 0x8d, 0xd4, 0xa9, 0x45, 0x48, 0x55, 0xbc, 0x5a, 0xf4, 0x55, 0xba, 0xf7, 0x69, 0x83, 0x99, 0xb7, 0x59, 0xb1, 0x07, - 0xd9, 0x8a, 0x8d, 0x68, 0x96, 0xbc, 0xee, 0x31, 0x25, 0xd5, 0x47, 0x4c, 0x1c, 0xa0, 0x5b, 0xde, 0x2f, 0x1e, 0xc3, - 0x54, 0xaf, 0x30, 0x62, 0xb5, 0xd9, 0x5f, 0x00, 0x73, 0x6f, 0xdc, 0xcf, 0x35, 0x7b, 0xe6, 0x53, 0x29, 0xa4, 0x58, - 0x85, 0xf0, 0xba, 0x2a, 0x33, 0x38, 0xf9, 0x14, 0x82, 0x21, 0x7f, 0xf9, 0x31, 0xf3, 0xeb, 0x55, 0xf7, 0x87, 0x19, - 0xcf, 0xea, 0x7b, 0x3a, 0x60, 0x6f, 0xa8, 0x0d, 0xaf, 0x7b, 0x0a, 0x71, 0x45, 0x98, 0xdd, 0xb3, 0x53, 0x60, 0xcd, - 0x64, 0x70, 0xdf, 0xb1, 0x29, 0xea, 0x09, 0xfc, 0x28, 0x9c, 0x37, 0x0b, 0xe6, 0x6f, 0x79, 0xc5, 0x68, 0xde, 0x4c, - 0x91, 0x74, 0xe1, 0xc1, 0x88, 0x4f, 0x19, 0x97, 0x28, 0x5b, 0xfa, 0x90, 0x7e, 0x87, 0x78, 0x23, 0xc7, 0x9b, 0xb5, - 0xf4, 0x8d, 0xe2, 0xb0, 0xd5, 0x64, 0x1b, 0x12, 0xa6, 0x00, 0x68, 0x91, 0xf3, 0x11, 0x30, 0x5d, 0xaf, 0xd9, 0x8a, - 0xb2, 0x0d, 0x61, 0x91, 0x86, 0x86, 0x50, 0x34, 0xac, 0x17, 0x4c, 0x4d, 0x8a, 0xbb, 0x43, 0x23, 0x26, 0xc6, 0x73, - 0xc6, 0xf2, 0x0b, 0xf2, 0xd3, 0xa2, 0x4c, 0x5b, 0x63, 0x2f, 0xae, 0xcc, 0x0a, 0x26, 0x1e, 0x34, 0x13, 0x20, 0x09, - 0xe0, 0xd5, 0x2a, 0xea, 0x8c, 0xf3, 0x54, 0x62, 0x73, 0x7f, 0xe3, 0x09, 0x19, 0x20, 0xd0, 0x29, 0x69, 0xa2, 0xa3, - 0xab, 0xf5, 0x41, 0x8a, 0xbd, 0x00, 0x94, 0x9d, 0xb0, 0xc1, 0x32, 0x86, 0x06, 0x58, 0xd7, 0x66, 0x73, 0x8a, 0x6b, - 0xd9, 0x53, 0x27, 0xb3, 0x36, 0xf2, 0x34, 0x7f, 0xb8, 0xb4, 0x30, 0x22, 0xc6, 0x45, 0xcd, 0x27, 0xe2, 0xab, 0x29, - 0x46, 0xa0, 0xf5, 0x04, 0xe4, 0xf5, 0x70, 0xca, 0xdb, 0x75, 0x8d, 0x71, 0xe9, 0x9a, 0x64, 0xf2, 0xa2, 0xc0, 0xa9, - 0x2f, 0x93, 0x7f, 0x19, 0x7f, 0x02, 0x9b, 0x78, 0x4e, 0x27, 0x3e, 0x4e, 0xb6, 0x3a, 0x51, 0x54, 0x40, 0x54, 0x8b, - 0xf0, 0x4a, 0x7a, 0x11, 0x92, 0x9a, 0xf1, 0x32, 0x10, 0xea, 0x78, 0xa3, 0x01, 0xc9, 0xfb, 0xba, 0x12, 0x5e, 0x5b, - 0xbe, 0x5c, 0x84, 0xbc, 0xd9, 0x0e, 0x6b, 0x77, 0x3e, 0x9d, 0x6e, 0x6f, 0x56, 0xc8, 0x0d, 0x50, 0x3a, 0x19, 0xae, - 0x82, 0xbe, 0xa1, 0xd9, 0x91, 0x3c, 0xa1, 0x23, 0x5f, 0x66, 0x65, 0x4c, 0xc2, 0xe2, 0x74, 0x43, 0x8e, 0x4a, 0x5e, - 0x29, 0xed, 0x2e, 0x64, 0x4f, 0x71, 0xaa, 0x3b, 0x58, 0x0f, 0x44, 0xe5, 0x10, 0x53, 0x6a, 0x14, 0x9e, 0xc4, 0xad, - 0x1c, 0x59, 0xfb, 0xb0, 0x4e, 0x2e, 0xbc, 0x8a, 0x33, 0x1d, 0xd2, 0xb6, 0xb5, 0xb9, 0xdb, 0x6c, 0x54, 0xa4, 0xcb, - 0x12, 0x69, 0xef, 0xed, 0xfa, 0x65, 0xd5, 0xa3, 0x49, 0x8a, 0xd2, 0xf7, 0x25, 0x8e, 0x2f, 0xeb, 0xa8, 0x7b, 0x3b, - 0x89, 0x25, 0x7c, 0x64, 0x99, 0x38, 0x05, 0x77, 0xc0, 0x58, 0x65, 0x27, 0xa2, 0x16, 0x48, 0xea, 0xbf, 0xf4, 0xb2, - 0x9e, 0x82, 0x14, 0xef, 0x96, 0xf5, 0x7a, 0x86, 0xc4, 0x7c, 0xc9, 0x18, 0xad, 0xc1, 0x00, 0x55, 0xd0, 0xf3, 0xd5, - 0x73, 0x40, 0xe0, 0x99, 0x4d, 0x2f, 0xbf, 0x13, 0x45, 0x9c, 0xdd, 0x65, 0x85, 0x26, 0x5a, 0x3c, 0xcb, 0x1e, 0x16, - 0xd8, 0x57, 0x0a, 0xf2, 0xec, 0xea, 0x25, 0x85, 0x96, 0x4d, 0x18, 0xf3, 0x1b, 0xa6, 0xbe, 0x02, 0xfb, 0xf2, 0x5a, - 0x99, 0x74, 0x56, 0x77, 0xb5, 0xc6, 0x02, 0xcf, 0x8b, 0x2a, 0x48, 0xa2, 0xde, 0x86, 0x99, 0x95, 0x89, 0x53, 0x3e, - 0xaa, 0x0a, 0x96, 0xb3, 0xf3, 0xdd, 0x94, 0xd0, 0xe8, 0xd1, 0x7f, 0xd5, 0x35, 0x09, 0xaa, 0xf4, 0xc8, 0x8c, 0x63, - 0x70, 0x11, 0x2d, 0xf4, 0xb3, 0x76, 0x5d, 0x54, 0x74, 0x7e, 0xcd, 0x62, 0x5a, 0x5f, 0x97, 0x92, 0x36, 0x3a, 0x2b, - 0xa4, 0xc4, 0xa2, 0x31, 0xcf, 0x2a, 0x64, 0xfb, 0xbd, 0xab, 0xad, 0xd5, 0x06, 0xc2, 0x4d, 0x26, 0x25, 0x48, 0x4a, - 0xc2, 0x3f, 0x94, 0x67, 0x5b, 0x46, 0x34, 0x2a, 0xad, 0x91, 0x2e, 0xaa, 0xd6, 0x9c, 0xb7, 0xa2, 0x30, 0x7f, 0xc2, - 0xe2, 0xbc, 0x46, 0xde, 0x08, 0x85, 0x00, 0xe1, 0x22, 0xfc, 0x39, 0x80, 0xfb, 0x3b, 0x96, 0x15, 0x0f, 0xab, 0xe9, - 0x29, 0xaf, 0xd4, 0x36, 0x8e, 0xc0, 0x01, 0x79, 0x8b, 0x93, 0xc1, 0x05, 0x92, 0x11, 0x26, 0x7e, 0x85, 0x68, 0x83, - 0xa5, 0x62, 0x52, 0x5a, 0x7c, 0xae, 0x6c, 0x42, 0xa7, 0x4f, 0xcb, 0x8a, 0xb9, 0xfa, 0x80, 0x3e, 0x5b, 0x55, 0x76, - 0xbe, 0x76, 0x0c, 0x43, 0x7e, 0x32, 0x5b, 0xe4, 0x49, 0xc9, 0xef, 0xc0, 0x98, 0x96, 0x37, 0x49, 0x6e, 0x53, 0x0d, - 0xfa, 0x58, 0x55, 0xf8, 0xea, 0x3d, 0xe7, 0x22, 0x3e, 0x98, 0xab, 0x11, 0xe9, 0x57, 0x83, 0xa9, 0x7f, 0xad, 0xdf, - 0xa7, 0x92, 0xe8, 0xd8, 0xe9, 0xba, 0xd0, 0xbc, 0x83, 0x4b, 0x2a, 0x2a, 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0x94, - 0x91, 0xda, 0xd7, 0x12, 0x59, 0x9b, 0x95, 0x3b, 0xd9, 0x7e, 0xb4, 0x9a, 0xcd, 0x30, 0xe5, 0xa5, 0xf5, 0xae, 0xac, - 0x2b, 0x3f, 0xe8, 0xca, 0x0e, 0xe9, 0x83, 0x7a, 0x22, 0x97, 0x4d, 0xe1, 0xe7, 0x5b, 0x9b, 0x03, 0x94, 0xfa, 0x5f, - 0x68, 0x5c, 0x86, 0xb3, 0x81, 0x4d, 0xe8, 0xea, 0x40, 0x7c, 0x50, 0xe6, 0x92, 0x6c, 0x5f, 0xf0, 0x84, 0xba, 0xee, - 0x82, 0x79, 0xd6, 0x15, 0x8b, 0xa2, 0xff, 0xf8, 0x9e, 0x85, 0xf7, 0xf4, 0xc9, 0xb0, 0xf2, 0x80, 0x7a, 0x79, 0xac, - 0xe5, 0xb2, 0x0e, 0x4c, 0x56, 0x12, 0x53, 0x4d, 0x58, 0xd5, 0x2d, 0xcd, 0x61, 0xeb, 0x8c, 0xe6, 0x34, 0xdd, 0x24, - 0xdf, 0x1f, 0x28, 0x9c, 0x44, 0x86, 0xbf, 0x5a, 0xdb, 0x81, 0x81, 0x06, 0x89, 0xea, 0x02, 0x54, 0x4a, 0xdc, 0x2f, - 0x54, 0x6b, 0x52, 0x95, 0x65, 0x07, 0x0a, 0x4b, 0xbe, 0x51, 0xd5, 0x2d, 0xbf, 0x5d, 0x94, 0xa8, 0x60, 0x94, 0xff, - 0xa9, 0x75, 0x59, 0x40, 0xb4, 0x1d, 0x5c, 0xeb, 0xb1, 0x57, 0x3e, 0xed, 0x62, 0x38, 0xde, 0x61, 0x57, 0xbf, 0xd3, - 0xea, 0x1c, 0xd5, 0x85, 0xa5, 0xc4, 0xb9, 0x57, 0xc8, 0x73, 0xb6, 0xb3, 0x9f, 0xf3, 0xf6, 0xa2, 0x83, 0x32, 0x7e, - 0xb9, 0x35, 0xcc, 0x6c, 0x16, 0xae, 0x8a, 0x80, 0x19, 0x7d, 0x75, 0x25, 0x00, 0xb0, 0x80, 0x29, 0x61, 0x61, 0xc4, - 0x8e, 0xa3, 0x3c, 0x73, 0x4c, 0x65, 0x9f, 0x7b, 0x46, 0xd7, 0x37, 0x27, 0xee, 0x91, 0xcb, 0x1d, 0xb4, 0x5a, 0x89, - 0xe3, 0x64, 0x61, 0x2d, 0x5f, 0x74, 0x05, 0xa6, 0x09, 0x49, 0x97, 0x5f, 0xcd, 0x81, 0x54, 0xad, 0xee, 0xc4, 0x3c, - 0x67, 0x13, 0x40, 0x6f, 0xdf, 0x35, 0x01, 0x8f, 0xc9, 0xf1, 0xcd, 0xe8, 0xde, 0x02, 0x33, 0xd2, 0xf5, 0x85, 0xd0, - 0x77, 0x2b, 0x99, 0xaf, 0x5b, 0xa3, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xe3, 0x12, 0xdb, 0xd0, 0xd2, 0x5d, 0x2f, - 0x82, 0x18, 0x08, 0x44, 0x72, 0x63, 0x14, 0x78, 0x7f, 0x76, 0xae, 0x7b, 0x31, 0x64, 0x29, 0x68, 0x46, 0x0f, 0x5e, - 0xb0, 0x5d, 0x26, 0x24, 0x13, 0xf9, 0x0e, 0x0d, 0x81, 0x95, 0xb9, 0x13, 0xfd, 0x08, 0xf0, 0xaa, 0xb8, 0xb5, 0xdf, - 0x27, 0xfa, 0xbd, 0xea, 0x43, 0x71, 0xe9, 0xb5, 0x82, 0xca, 0x6a, 0x24, 0xde, 0x0c, 0x3a, 0xe0, 0xd1, 0xe5, 0xa7, - 0x4a, 0x8c, 0x66, 0x10, 0x3c, 0x40, 0x14, 0x11, 0x65, 0xf6, 0x95, 0xdc, 0x16, 0x77, 0x87, 0x53, 0x40, 0x20, 0x63, - 0xd6, 0x65, 0x17, 0xc3, 0x44, 0x60, 0x89, 0xf9, 0x66, 0x7c, 0x31, 0x82, 0x1f, 0xdb, 0x7d, 0x54, 0xce, 0x45, 0xb9, - 0x06, 0x63, 0x1b, 0xf3, 0x99, 0x15, 0x7b, 0x82, 0x6f, 0x34, 0xd2, 0xd1, 0xcb, 0x18, 0xca, 0x25, 0xca, 0xc1, 0x4a, - 0xf7, 0x09, 0xf4, 0x60, 0x45, 0x15, 0x20, 0xce, 0x6e, 0x9c, 0x71, 0x6a, 0xc0, 0x2c, 0xb9, 0x21, 0x2d, 0x68, 0x72, - 0xea, 0xf0, 0x6b, 0x3a, 0x7a, 0x0e, 0x30, 0x29, 0xee, 0xc9, 0xcb, 0xe1, 0xd4, 0xb4, 0xd6, 0xd3, 0x5a, 0x7f, 0x03, - 0x0d, 0xb1, 0xa0, 0x2d, 0x6a, 0x67, 0x6f, 0xc0, 0xcc, 0x17, 0x6c, 0x1b, 0x6a, 0x8d, 0x3f, 0xec, 0x87, 0x16, 0x76, - 0x92, 0xe1, 0x34, 0x88, 0x24, 0xce, 0xc1, 0x34, 0x0a, 0xf1, 0x87, 0x56, 0x97, 0x15, 0xab, 0xf2, 0xc4, 0x6f, 0xdd, - 0x5f, 0x2b, 0xa5, 0xd1, 0xe7, 0x9f, 0xc5, 0xc2, 0x19, 0x99, 0xd8, 0xaf, 0xf6, 0xc2, 0xc2, 0xa2, 0xb2, 0x03, 0x57, - 0x35, 0x1a, 0x9e, 0x25, 0x2f, 0x85, 0xa7, 0x1c, 0x56, 0x68, 0x99, 0x09, 0x3f, 0x8f, 0xf3, 0x6a, 0xec, 0xcd, 0xa8, - 0x46, 0xb5, 0x62, 0x0a, 0xea, 0xf4, 0xe8, 0x40, 0xb8, 0x4c, 0x01, 0x56, 0xd9, 0x02, 0xd4, 0x9f, 0x5f, 0xe7, 0x1e, - 0x7d, 0x1a, 0x06, 0x2f, 0xca, 0x31, 0xd6, 0x20, 0xe8, 0x1d, 0x44, 0x21, 0x46, 0x47, 0xd2, 0x37, 0x29, 0xbd, 0xf9, - 0x23, 0x8f, 0xf1, 0x0d, 0xf1, 0x77, 0xc1, 0xce, 0xb7, 0xdc, 0xe7, 0xce, 0xe2, 0x35, 0x66, 0xcd, 0x75, 0xb4, 0x0e, - 0x43, 0xdd, 0x25, 0x30, 0x0d, 0x41, 0xc3, 0x44, 0x13, 0x04, 0x63, 0xc9, 0x73, 0xba, 0x36, 0x9a, 0xa0, 0xf4, 0x42, - 0x12, 0xfc, 0xbf, 0x4a, 0x78, 0x39, 0xa7, 0x72, 0x3a, 0x8a, 0x5a, 0xf0, 0x10, 0x5c, 0x55, 0x43, 0x2d, 0x50, 0x27, - 0x0f, 0x4f, 0xa1, 0x25, 0x63, 0x05, 0x9e, 0x63, 0x9f, 0x9b, 0x34, 0xc0, 0x78, 0x24, 0xf3, 0xb0, 0x61, 0xc2, 0x15, - 0x7a, 0xb6, 0x98, 0x33, 0x3b, 0xe6, 0x6d, 0x85, 0x91, 0xbd, 0x19, 0x97, 0x78, 0xf6, 0x3a, 0x16, 0xb3, 0xed, 0x71, - 0x68, 0x31, 0x37, 0x0f, 0x1c, 0xb5, 0x58, 0x9b, 0x08, 0x0a, 0x7d, 0x03, 0x5b, 0x80, 0xc1, 0x4e, 0xce, 0xaa, 0x51, - 0x42, 0xb2, 0xe6, 0x16, 0x40, 0x9e, 0xe9, 0x28, 0x84, 0x54, 0x36, 0xfc, 0xc4, 0x5a, 0xf2, 0x77, 0x60, 0xe7, 0xfc, - 0xcd, 0xc3, 0x40, 0x88, 0xda, 0x46, 0x68, 0x02, 0xfa, 0xea, 0xb5, 0x96, 0x10, 0x20, 0x0c, 0x82, 0x2b, 0xfa, 0xcb, - 0x9e, 0x84, 0x6e, 0x2e, 0xaf, 0xcb, 0x7b, 0x42, 0xd4, 0x75, 0xb0, 0x1e, 0x91, 0xf1, 0xdc, 0x15, 0xfe, 0xab, 0xde, - 0x0f, 0x12, 0x25, 0x14, 0x4b, 0x45, 0xf2, 0x23, 0xaa, 0x23, 0xc6, 0x11, 0xda, 0xd1, 0x49, 0x3e, 0x76, 0x85, 0x81, - 0x38, 0x54, 0x5b, 0x66, 0x7a, 0x7e, 0xc4, 0x56, 0x33, 0xf6, 0x28, 0xb8, 0x9e, 0x2c, 0x35, 0xbc, 0x40, 0x94, 0xae, - 0x7f, 0x04, 0x34, 0x93, 0xff, 0x98, 0xd9, 0xe6, 0xa9, 0xd9, 0x47, 0x45, 0xdf, 0x64, 0x76, 0x8e, 0x2c, 0x38, 0x8a, - 0xc2, 0x2b, 0x21, 0xf0, 0x52, 0x47, 0x3c, 0x35, 0x52, 0xc4, 0x3c, 0x64, 0x9a, 0x82, 0x5c, 0x0f, 0xe8, 0x0b, 0x4d, - 0x8e, 0xaa, 0x2e, 0xc7, 0xf4, 0x40, 0x81, 0x58, 0x1d, 0xdb, 0x11, 0xe2, 0xe2, 0x36, 0x11, 0xc3, 0x69, 0xd5, 0x65, - 0x0f, 0x49, 0xad, 0xf3, 0x74, 0xcc, 0x14, 0xe4, 0xc0, 0x4d, 0x58, 0xfd, 0xce, 0x71, 0x68, 0x17, 0x05, 0xb7, 0x6f, - 0xa9, 0x44, 0xb2, 0x51, 0xa6, 0xfb, 0x32, 0xfc, 0x20, 0x9a, 0x45, 0x03, 0xc8, 0x06, 0x7c, 0xa5, 0x3f, 0x8c, 0xa2, - 0xeb, 0x3b, 0xbf, 0xcc, 0x9a, 0x29, 0x5b, 0xbf, 0xdb, 0x30, 0xdb, 0x3a, 0x1e, 0x28, 0xb4, 0xa6, 0x85, 0x46, 0x9b, - 0xfa, 0xac, 0xf0, 0xad, 0x75, 0x02, 0x31, 0x39, 0xb9, 0xd9, 0xc8, 0x63, 0xb0, 0x8e, 0xb0, 0xee, 0x31, 0x36, 0x27, - 0xf1, 0x2f, 0xb5, 0x99, 0x0b, 0xc2, 0x33, 0x2b, 0x59, 0xf0, 0x0f, 0xba, 0x19, 0x6c, 0x39, 0x6f, 0xc2, 0xbf, 0xb1, - 0xa6, 0x09, 0x93, 0x35, 0x69, 0x05, 0xe5, 0x90, 0xd4, 0x6e, 0x68, 0xb4, 0x4e, 0x5e, 0xb6, 0x28, 0x10, 0x52, 0x13, - 0xcf, 0x45, 0x75, 0x27, 0xa3, 0xa5, 0x17, 0xe9, 0xc6, 0xde, 0x37, 0x3f, 0x87, 0xcf, 0xb4, 0xc2, 0x8b, 0x15, 0xc2, - 0x80, 0xfe, 0x64, 0x58, 0xdf, 0xab, 0xa4, 0xdd, 0x57, 0xed, 0x64, 0xd1, 0xda, 0x98, 0xaf, 0x02, 0x26, 0xd6, 0x3d, - 0xc5, 0xbc, 0x5c, 0x9d, 0xf4, 0xf7, 0xae, 0xc5, 0x16, 0xc6, 0x23, 0x99, 0x47, 0x72, 0x4a, 0xf8, 0x63, 0x40, 0xe3, - 0xdf, 0x50, 0x46, 0x0d, 0x0c, 0x34, 0x58, 0x3d, 0x1a, 0xca, 0x75, 0x00, 0x0e, 0x31, 0x34, 0x11, 0xc9, 0x40, 0x3b, - 0x81, 0x3b, 0x9a, 0x09, 0x52, 0x4f, 0x5b, 0x82, 0x4d, 0x3c, 0x47, 0x37, 0x31, 0x39, 0x19, 0xbb, 0x00, 0x57, 0xe0, - 0x96, 0xf5, 0x0c, 0xdb, 0x6e, 0xb3, 0x5d, 0x84, 0x94, 0x9a, 0x0a, 0xb6, 0xf0, 0x58, 0x6b, 0x02, 0x78, 0x4a, 0x35, - 0xd1, 0xa2, 0x21, 0xd5, 0x97, 0x4e, 0xc0, 0x7e, 0x71, 0xd2, 0x98, 0x5b, 0xd3, 0x58, 0x59, 0x3e, 0x0d, 0xbc, 0xd4, - 0x64, 0x4d, 0xac, 0xd0, 0x67, 0x9c, 0x72, 0x04, 0xe2, 0x1d, 0x7e, 0x73, 0x79, 0x33, 0x49, 0x6f, 0x0b, 0xfd, 0xd8, - 0x64, 0x80, 0x61, 0xe4, 0x1c, 0xe1, 0x17, 0x33, 0xec, 0x6c, 0xc3, 0xf9, 0xe7, 0x04, 0xc9, 0x78, 0x51, 0xf8, 0x57, - 0xe3, 0x05, 0xe9, 0xa8, 0x26, 0x21, 0xfe, 0x81, 0xe8, 0xd7, 0x0b, 0xce, 0xa0, 0x81, 0x36, 0xfb, 0x72, 0x59, 0xb3, - 0xb0, 0x2a, 0x68, 0xb4, 0xcf, 0xcd, 0x57, 0xb3, 0xe5, 0xdb, 0xeb, 0x7f, 0x94, 0xeb, 0x9e, 0x73, 0x1c, 0xb9, 0xd7, - 0x1c, 0x97, 0xbd, 0x2c, 0xf9, 0x41, 0x4b, 0xeb, 0x9d, 0x72, 0xda, 0xca, 0x45, 0x57, 0x50, 0xc2, 0x3f, 0xf6, 0x4f, - 0x8a, 0x64, 0xe7, 0x11, 0x2c, 0x89, 0x72, 0xb9, 0xe6, 0xe2, 0x8d, 0xd5, 0xbd, 0xbd, 0x13, 0x2c, 0x0c, 0x6e, 0xfc, - 0x82, 0x3c, 0x41, 0x92, 0xf2, 0x43, 0xf9, 0x5d, 0x0a, 0x71, 0xb6, 0x9d, 0xd5, 0x75, 0xb4, 0x8a, 0x78, 0xec, 0x5d, - 0x0e, 0x17, 0x76, 0x88, 0xd2, 0xe5, 0x83, 0x8b, 0xab, 0x59, 0x6b, 0x99, 0x2a, 0x93, 0x74, 0xc6, 0x33, 0x16, 0x70, - 0x9c, 0xc9, 0x32, 0x44, 0xd0, 0x33, 0x48, 0xc4, 0xe8, 0x7b, 0x17, 0x2c, 0x46, 0xc3, 0xd6, 0xea, 0xdb, 0x44, 0xd0, - 0x16, 0x14, 0xcd, 0x22, 0x7a, 0x31, 0x32, 0x15, 0x5e, 0x67, 0x13, 0x5a, 0xae, 0x64, 0x5e, 0x42, 0xab, 0x21, 0x6b, - 0x58, 0x94, 0xfb, 0x34, 0xf1, 0x83, 0x79, 0x3e, 0xb7, 0x50, 0x5b, 0x19, 0xab, 0x9f, 0x70, 0x66, 0xa9, 0x73, 0x41, - 0xb3, 0x5f, 0xd3, 0x5c, 0x81, 0xe7, 0xc9, 0xe6, 0xcb, 0x6f, 0xc4, 0xfa, 0x78, 0xca, 0xcf, 0xa0, 0xca, 0xdb, 0x84, - 0x25, 0xec, 0xcf, 0xa9, 0x52, 0x3c, 0xb2, 0xe1, 0x96, 0x55, 0x4b, 0x51, 0x1d, 0x8b, 0x24, 0x8a, 0x8c, 0x9d, 0x0c, - 0x67, 0xe8, 0x85, 0xc4, 0xb3, 0x59, 0x83, 0x09, 0x93, 0xf3, 0x2c, 0xde, 0x29, 0xcc, 0x95, 0x48, 0x12, 0x8b, 0x34, - 0x42, 0x91, 0xf6, 0x2d, 0xb9, 0x4c, 0xf2, 0x53, 0x93, 0xdb, 0x91, 0x50, 0xe5, 0x15, 0xfe, 0x1a, 0x70, 0x49, 0x88, - 0x54, 0xa0, 0x12, 0x9f, 0xfb, 0x8e, 0x58, 0xa2, 0x49, 0x15, 0xa5, 0x28, 0xa8, 0x97, 0xe9, 0x5f, 0x31, 0x2f, 0x4d, - 0x69, 0xec, 0x8e, 0xc0, 0xdd, 0x77, 0x19, 0x2b, 0x89, 0x3b, 0x8e, 0x99, 0x4c, 0x6b, 0x01, 0xd8, 0xa3, 0xcb, 0x4d, - 0xde, 0xe5, 0x80, 0xcb, 0xe3, 0xe3, 0x16, 0x40, 0xb0, 0x87, 0x05, 0xfc, 0xb5, 0x9d, 0x4b, 0x1d, 0x67, 0x24, 0x22, - 0x16, 0x9c, 0x21, 0x8b, 0x27, 0x6f, 0x00, 0x48, 0xce, 0xef, 0xe2, 0xe7, 0x05, 0x6d, 0x07, 0x40, 0x15, 0x8e, 0x0a, - 0x40, 0xec, 0x90, 0x60, 0xd0, 0x85, 0x77, 0xb2, 0xaf, 0x5a, 0xb3, 0xe3, 0xed, 0x05, 0x75, 0x1b, 0xcd, 0x3c, 0xd2, - 0x93, 0x92, 0x08, 0xe2, 0x0c, 0xb3, 0x1f, 0x04, 0x25, 0xaa, 0x57, 0xf5, 0x84, 0x30, 0x3a, 0x5b, 0x92, 0xc5, 0x4d, - 0x83, 0x80, 0xb4, 0x8f, 0x10, 0x33, 0xd9, 0x2e, 0xe5, 0x98, 0x7c, 0xed, 0x19, 0xe7, 0xac, 0x39, 0x43, 0x28, 0x1a, - 0xd8, 0xad, 0x25, 0x10, 0xeb, 0x1c, 0xca, 0x68, 0x28, 0x4d, 0xf9, 0x85, 0x1c, 0x41, 0xad, 0x63, 0xaf, 0x4c, 0x86, - 0x76, 0x1b, 0xdc, 0xfd, 0x80, 0x14, 0x29, 0xdc, 0xa3, 0x81, 0x65, 0x93, 0xd5, 0xe2, 0x92, 0x59, 0xbc, 0xe5, 0x91, - 0x62, 0x25, 0xb3, 0x1f, 0x04, 0xc3, 0x0b, 0xac, 0xe1, 0x62, 0x91, 0x8e, 0x12, 0xb2, 0x0a, 0x2e, 0x8b, 0xf5, 0xfe, - 0xec, 0xd6, 0x5d, 0x37, 0x05, 0xb9, 0xcd, 0xc9, 0x98, 0x29, 0xc7, 0xe3, 0x0a, 0xd2, 0x86, 0x5c, 0x1e, 0x07, 0x69, - 0xa4, 0xa9, 0x50, 0x3a, 0xb3, 0x7e, 0xba, 0x3f, 0xd5, 0xe3, 0xc5, 0x5c, 0x9d, 0x2c, 0x20, 0xa0, 0x8d, 0x3b, 0x70, - 0xca, 0x2a, 0x2c, 0x09, 0x87, 0x24, 0x6c, 0x78, 0x00, 0xa6, 0x5a, 0x3f, 0x8a, 0x4a, 0xfc, 0xbb, 0x64, 0x13, 0x41, - 0xa5, 0xe7, 0x06, 0xe7, 0x67, 0x69, 0x3c, 0x19, 0x85, 0x9f, 0xc4, 0x14, 0xce, 0x38, 0xcc, 0x11, 0xa2, 0xb2, 0x44, - 0xbf, 0x41, 0x89, 0xe7, 0x7e, 0x5a, 0xf2, 0x7f, 0xb6, 0x71, 0xfe, 0xa0, 0x8c, 0xe6, 0xd9, 0xb2, 0xe9, 0xb3, 0x05, - 0xc3, 0xde, 0x96, 0xb4, 0xb5, 0xee, 0x2c, 0x8a, 0xff, 0x8d, 0xea, 0xf0, 0xe9, 0x0e, 0x93, 0x58, 0x0f, 0x5c, 0x49, - 0xf0, 0xa9, 0x39, 0xe1, 0xd3, 0x9d, 0x3a, 0xe1, 0x87, 0x84, 0x88, 0x77, 0x8c, 0x8c, 0xb6, 0xc6, 0xd4, 0x6c, 0x05, - 0x8b, 0x4b, 0x2f, 0x2a, 0x82, 0x9d, 0x64, 0xd8, 0x94, 0x77, 0xbf, 0xe3, 0x95, 0x66, 0x07, 0x09, 0xe1, 0x45, 0xaa, - 0xed, 0x5c, 0xa3, 0xc5, 0x9c, 0x16, 0x50, 0x4a, 0x2a, 0x25, 0xd1, 0x6c, 0x1a, 0xc7, 0x6a, 0x81, 0x9f, 0x17, 0x24, - 0xb9, 0x55, 0xac, 0xfb, 0xb5, 0x33, 0x9c, 0xa8, 0x92, 0x9a, 0x92, 0x9a, 0xba, 0xb4, 0xa4, 0xc7, 0x60, 0xfe, 0xb7, - 0xc6, 0x44, 0xca, 0x35, 0x2e, 0x3c, 0xf0, 0x84, 0x32, 0x7e, 0x3d, 0x54, 0x3b, 0x59, 0x85, 0x33, 0xaf, 0xef, 0x2f, - 0xc3, 0xa1, 0xce, 0x85, 0x33, 0x0e, 0xdd, 0x70, 0x39, 0xb6, 0xdd, 0x6f, 0xed, 0xfc, 0x05, 0xfc, 0x45, 0x50, 0x2c, - 0x49, 0xa4, 0x66, 0xee, 0xfc, 0xa0, 0xec, 0xd4, 0x61, 0xee, 0x50, 0xa3, 0x95, 0xf1, 0xd4, 0x38, 0xd7, 0xd7, 0x58, - 0xa6, 0x37, 0x6a, 0x52, 0x45, 0x58, 0xd3, 0x40, 0x0d, 0x0f, 0xe9, 0x3c, 0x0b, 0x7a, 0x6a, 0x65, 0xfb, 0x74, 0xd0, - 0x07, 0x09, 0xcf, 0xa9, 0x80, 0x38, 0x13, 0x45, 0x2e, 0xbe, 0xf6, 0xfe, 0x32, 0xef, 0x57, 0x70, 0xb0, 0x41, 0xc9, - 0x5c, 0x3c, 0xb3, 0x38, 0x47, 0xcf, 0x0c, 0xe7, 0xf4, 0x99, 0xb5, 0xb3, 0x1d, 0xf6, 0x73, 0x29, 0x76, 0x25, 0xb0, - 0x28, 0x49, 0xca, 0x74, 0x5c, 0xb9, 0x3a, 0x9c, 0x3b, 0x0b, 0xe7, 0x91, 0xa9, 0x3a, 0xc5, 0x60, 0x52, 0xa6, 0xb4, - 0x7a, 0x62, 0x5b, 0x62, 0x6c, 0x99, 0x40, 0xb0, 0x4b, 0xbf, 0xae, 0xdc, 0xf6, 0x8b, 0xbb, 0x24, 0x85, 0xda, 0xd2, - 0xda, 0xf4, 0x24, 0x0a, 0x59, 0xf3, 0x4b, 0x1b, 0x4f, 0x89, 0xbd, 0xf3, 0x63, 0x15, 0x1d, 0xa4, 0x4b, 0x71, 0xac, - 0xdd, 0x89, 0x80, 0xcb, 0xb5, 0xa1, 0xfc, 0xb4, 0x35, 0x10, 0xd9, 0xf3, 0x16, 0xc9, 0xca, 0x1f, 0xca, 0xb0, 0x3c, - 0x21, 0x84, 0x89, 0xc0, 0xca, 0x58, 0x28, 0xad, 0x24, 0xb0, 0x0a, 0x7c, 0x94, 0xaa, 0xc5, 0xec, 0xb4, 0xf8, 0x3e, - 0x84, 0x6c, 0x8e, 0x9b, 0xd0, 0x9d, 0x00, 0xf2, 0x7a, 0x06, 0xd3, 0x55, 0x88, 0x02, 0xcd, 0x0c, 0x20, 0xe1, 0x87, - 0xec, 0xf6, 0x05, 0xcc, 0x1f, 0xd3, 0xb5, 0x5b, 0xb5, 0x72, 0x17, 0xed, 0x74, 0x2e, 0x89, 0x55, 0x9a, 0x6a, 0x52, - 0x5c, 0x94, 0x64, 0x21, 0xb1, 0x68, 0xe0, 0x95, 0x2b, 0x56, 0x9d, 0xfb, 0xc0, 0x6f, 0xd8, 0x36, 0x9e, 0xaf, 0xfa, - 0x31, 0xae, 0x40, 0xd5, 0xa8, 0x86, 0x1d, 0x7e, 0x00, 0xa6, 0xa6, 0x17, 0x09, 0x62, 0xb1, 0x59, 0xec, 0xce, 0x40, - 0x47, 0xf6, 0x51, 0xf1, 0xa4, 0x4c, 0x25, 0x0b, 0x54, 0x72, 0x8d, 0x14, 0x56, 0x5b, 0xb3, 0xa8, 0x4d, 0xc4, 0x7b, - 0xee, 0xd0, 0xba, 0x8a, 0xcb, 0x4c, 0x11, 0x7b, 0xa8, 0xe8, 0x33, 0x7a, 0xee, 0xc3, 0x2d, 0xbe, 0x87, 0x14, 0xc1, - 0x96, 0x8a, 0x91, 0x29, 0x09, 0xed, 0xc9, 0x0a, 0xa5, 0xc9, 0x12, 0x3c, 0x34, 0x50, 0x85, 0x0d, 0xf9, 0x0c, 0x07, - 0x6c, 0x3f, 0xa6, 0xf0, 0x64, 0x81, 0x12, 0x73, 0xa8, 0x76, 0x73, 0xf0, 0x5d, 0xed, 0x80, 0x77, 0x64, 0xcc, 0xcb, - 0xe4, 0x26, 0x17, 0xde, 0x91, 0xae, 0xbf, 0x1f, 0x07, 0x3b, 0x44, 0x18, 0xea, 0xa6, 0x80, 0xf4, 0xbc, 0x97, 0x0b, - 0x45, 0x89, 0x6f, 0xad, 0x18, 0xa8, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd4, 0x03, 0x3f, 0x21, 0xc8, 0x01, - 0x95, 0xd1, 0xa7, 0x2b, 0xda, 0xe2, 0xfa, 0xf3, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, 0x1d, 0x30, 0x8d, 0xfa, 0x68, - 0x68, 0xf7, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x17, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, 0xec, 0xd8, 0x3c, 0xba, 0xe1, - 0xdb, 0xf5, 0xc9, 0x80, 0xa1, 0x65, 0xd6, 0xdb, 0xa7, 0xab, 0x8f, 0xc6, 0xe7, 0x9a, 0x1a, 0x15, 0xc7, 0x45, 0x32, - 0x64, 0xaa, 0xa8, 0xf3, 0xc9, 0x26, 0x2a, 0x62, 0x6d, 0x2e, 0xfb, 0xce, 0x87, 0x31, 0xe8, 0xb1, 0x45, 0x95, 0x11, - 0xd7, 0x8e, 0xd9, 0xaf, 0x2f, 0xd6, 0xe5, 0x78, 0x9c, 0xd3, 0x07, 0x12, 0xa6, 0xed, 0x24, 0x42, 0xdd, 0x89, 0xf2, - 0x4d, 0x53, 0x9a, 0x05, 0x61, 0x3f, 0x58, 0xa4, 0x63, 0x0d, 0x9b, 0x6f, 0xc6, 0x6c, 0x6e, 0xa0, 0xba, 0xf2, 0x03, - 0xd4, 0x81, 0xb8, 0x18, 0x70, 0xf1, 0x0e, 0x8c, 0x39, 0xf3, 0xef, 0xb8, 0xbf, 0x2a, 0xa5, 0x34, 0xea, 0xf8, 0xb2, - 0xd4, 0xc8, 0xf6, 0x7e, 0xd9, 0x7f, 0x65, 0xf6, 0x21, 0xdf, 0x15, 0xa8, 0x50, 0x85, 0x34, 0x34, 0x89, 0x7a, 0xed, - 0x00, 0xb1, 0x9d, 0x8d, 0x26, 0x6a, 0xc5, 0x22, 0x52, 0x1e, 0x01, 0x0e, 0xe5, 0xf0, 0x5e, 0xb7, 0x0d, 0x23, 0xbe, - 0xbd, 0x4a, 0x3d, 0xd3, 0x96, 0x68, 0x1d, 0x0c, 0xf1, 0x2e, 0x5a, 0x4d, 0xe2, 0xcc, 0x0c, 0xe9, 0xd8, 0x99, 0xba, - 0x5f, 0xa2, 0xe8, 0x5d, 0x16, 0xd8, 0x6a, 0xae, 0xb6, 0x7e, 0x67, 0x45, 0x1f, 0xc2, 0x6a, 0xd9, 0xea, 0x7b, 0x31, - 0xd3, 0xd8, 0x4c, 0x9c, 0x20, 0x16, 0x40, 0xb3, 0x77, 0xee, 0x12, 0xc5, 0x98, 0xd9, 0x70, 0x59, 0xcc, 0x12, 0x29, - 0xc2, 0x0e, 0xe8, 0x24, 0x1a, 0x30, 0x31, 0xa7, 0x38, 0x36, 0x62, 0xdf, 0x27, 0xad, 0x6c, 0xe2, 0x4a, 0x28, 0x83, - 0x32, 0x69, 0xdd, 0x4e, 0xbf, 0x4c, 0x7c, 0xef, 0x5b, 0x40, 0xd3, 0x29, 0x73, 0x02, 0x7b, 0xce, 0x11, 0xe2, 0x0b, - 0x10, 0xe4, 0x56, 0x25, 0xef, 0x01, 0x96, 0xea, 0x9c, 0xa5, 0xeb, 0x53, 0x6f, 0x6c, 0x4b, 0xea, 0x89, 0xc3, 0xcc, - 0xf1, 0x3c, 0x2a, 0xbd, 0x02, 0xed, 0xe7, 0xbd, 0xef, 0xad, 0x6a, 0x9b, 0xf8, 0xeb, 0xf5, 0x01, 0x25, 0x46, 0xb3, - 0xb1, 0xa5, 0x9e, 0x6a, 0x69, 0xbe, 0xa9, 0x83, 0x9b, 0x10, 0xa2, 0x73, 0x5b, 0xb1, 0x66, 0xcd, 0xda, 0x91, 0x65, - 0xf4, 0xaf, 0x60, 0x85, 0x6f, 0x60, 0x2d, 0x2e, 0x01, 0xcd, 0xdf, 0x18, 0xdf, 0x08, 0x79, 0x5c, 0x7e, 0xa0, 0xf3, - 0x33, 0x46, 0x5d, 0x85, 0xa9, 0x22, 0xe1, 0xe1, 0xa5, 0xd6, 0x6b, 0x2d, 0xe8, 0x98, 0x96, 0x8f, 0x35, 0xf8, 0x42, - 0x4d, 0xab, 0x1d, 0xbc, 0xe5, 0x57, 0x6a, 0xea, 0x42, 0xe7, 0xe7, 0xa9, 0x03, 0x29, 0x5e, 0x7e, 0x45, 0x62, 0x8e, - 0xe5, 0xb7, 0x19, 0xfa, 0xe8, 0x7b, 0xf8, 0x75, 0xc3, 0x0f, 0x3a, 0x2f, 0x50, 0x49, 0x35, 0xce, 0x30, 0x0e, 0xe7, - 0xa7, 0x59, 0x35, 0x62, 0xa6, 0x08, 0x3f, 0x38, 0x75, 0x60, 0xf5, 0xba, 0x96, 0x87, 0x2e, 0x45, 0xa8, 0x02, 0x62, - 0x4f, 0xe3, 0xe7, 0x43, 0x98, 0x2a, 0xa6, 0x22, 0x81, 0x30, 0xa9, 0xd0, 0x9e, 0x92, 0x82, 0xdd, 0x62, 0xd5, 0xae, - 0x7a, 0xb7, 0x62, 0x5e, 0x93, 0x89, 0x80, 0x31, 0xde, 0x81, 0xe6, 0xcd, 0x6c, 0x5b, 0x87, 0xce, 0x89, 0x1d, 0x15, - 0xd8, 0x03, 0x32, 0xf6, 0x0e, 0x77, 0xbf, 0x99, 0x01, 0x27, 0x5c, 0xc3, 0xf4, 0x3c, 0x34, 0x1b, 0xdd, 0x70, 0xe5, - 0x5b, 0xfa, 0x74, 0xe6, 0xc4, 0xd9, 0x02, 0xcd, 0xd7, 0xc8, 0x56, 0xa2, 0xab, 0x9e, 0xa0, 0xee, 0x81, 0x64, 0x6f, - 0xdf, 0x5c, 0xf7, 0x76, 0x77, 0x05, 0x49, 0xa7, 0xbb, 0x19, 0xb0, 0x3b, 0x5c, 0xf0, 0x6e, 0xf5, 0x4c, 0x22, 0x09, - 0x00, 0x90, 0x3d, 0xe9, 0x3e, 0x0a, 0x5b, 0xe8, 0x4e, 0xb7, 0xbf, 0x76, 0x53, 0x59, 0xd0, 0x26, 0x5d, 0x79, 0x0c, - 0x6d, 0x13, 0x46, 0xc4, 0x90, 0x5d, 0x97, 0x91, 0x75, 0x4b, 0x5f, 0x08, 0x17, 0xf0, 0x88, 0x03, 0xb6, 0xc3, 0x76, - 0x41, 0x30, 0x12, 0x90, 0x90, 0x73, 0x21, 0xfe, 0x36, 0x0d, 0x35, 0x2b, 0xb8, 0xdb, 0x6c, 0x88, 0xdd, 0x24, 0xa1, - 0x3f, 0xe8, 0x0a, 0x6f, 0x6e, 0xbd, 0x1c, 0x2b, 0x28, 0xf3, 0xd1, 0x73, 0xb5, 0x9f, 0x35, 0x53, 0x7b, 0x3a, 0x69, - 0x69, 0xc6, 0xbc, 0x54, 0x6a, 0x9e, 0xc8, 0xbb, 0xb9, 0x81, 0x67, 0xe3, 0x99, 0x39, 0xc4, 0x89, 0x2d, 0x4d, 0xeb, - 0x66, 0xcc, 0xd1, 0xee, 0x6c, 0x3e, 0xf6, 0xec, 0xab, 0x9f, 0xcb, 0xbc, 0x54, 0x9f, 0xcd, 0xcd, 0xd2, 0xac, 0x9c, - 0x3f, 0x43, 0x54, 0xd8, 0x56, 0x16, 0x53, 0x4d, 0xe2, 0x18, 0x04, 0x46, 0x8b, 0x6e, 0x6f, 0xa1, 0x19, 0x76, 0x31, - 0x3b, 0xce, 0xa5, 0x59, 0x77, 0x7b, 0x85, 0xe3, 0x97, 0x99, 0xaf, 0x55, 0xed, 0x8d, 0x1b, 0x25, 0x0a, 0x4e, 0x87, - 0x83, 0xf3, 0xb0, 0xfd, 0x4b, 0x91, 0x37, 0x33, 0x8c, 0x25, 0x81, 0x68, 0x2d, 0x5a, 0xb8, 0xca, 0x68, 0xb5, 0x59, - 0x15, 0x21, 0x39, 0xb5, 0x33, 0xff, 0x85, 0x06, 0x90, 0x5a, 0xf0, 0x0a, 0x75, 0x73, 0x81, 0x05, 0xc7, 0xa8, 0xd4, - 0xa1, 0xf1, 0x29, 0xa7, 0x24, 0x43, 0x2a, 0x3a, 0xec, 0x72, 0xa2, 0x75, 0x4e, 0xb6, 0x1c, 0x01, 0x08, 0x94, 0x6a, - 0xc3, 0x06, 0x53, 0x1f, 0x26, 0x99, 0x5b, 0x99, 0x8e, 0x30, 0x53, 0x05, 0xc6, 0xdf, 0xac, 0x16, 0x7b, 0x97, 0x73, - 0x91, 0x24, 0xcc, 0xed, 0x0c, 0x3d, 0x59, 0x80, 0x0e, 0x63, 0x70, 0x7c, 0x3b, 0xf9, 0xa9, 0xfe, 0xb4, 0xba, 0x22, - 0xe3, 0xd4, 0x31, 0x39, 0x7b, 0x6d, 0x07, 0x05, 0x8d, 0xda, 0xee, 0x65, 0x78, 0xcd, 0xb3, 0x02, 0xed, 0xf3, 0xbf, - 0xda, 0xbd, 0xdd, 0xbc, 0xf0, 0xe5, 0xb7, 0x90, 0x15, 0x48, 0x3d, 0xc1, 0x6b, 0x53, 0x19, 0x95, 0x6a, 0xe7, 0x12, - 0x6d, 0xbf, 0x3c, 0x21, 0xc9, 0xb6, 0xf1, 0x6f, 0x91, 0x4b, 0x29, 0x90, 0xfc, 0x7d, 0x6d, 0x24, 0xb2, 0xc5, 0x2c, - 0x49, 0x98, 0xea, 0x35, 0x49, 0x75, 0x1e, 0xd6, 0xb1, 0x9b, 0x8e, 0xff, 0x2c, 0x43, 0xf4, 0x34, 0x12, 0x52, 0xeb, - 0x6d, 0x4d, 0xe6, 0x61, 0x1d, 0xdd, 0xc9, 0x16, 0xcf, 0x79, 0xc4, 0x53, 0x41, 0xc6, 0x6c, 0xb3, 0xee, 0x52, 0x89, - 0x44, 0x2d, 0x58, 0x06, 0xda, 0xed, 0x66, 0x38, 0x45, 0xad, 0x03, 0x14, 0x3b, 0x15, 0x7d, 0x19, 0xba, 0xd2, 0xd4, - 0x67, 0xb2, 0xa1, 0xb0, 0x52, 0x8b, 0xba, 0xbd, 0x94, 0x7a, 0xce, 0x86, 0xae, 0xbc, 0x3c, 0x99, 0x6b, 0xbe, 0x03, - 0xd8, 0x46, 0x1b, 0x4b, 0x37, 0x80, 0x6e, 0x34, 0x03, 0x37, 0x21, 0x03, 0x50, 0xd6, 0x14, 0x2a, 0x37, 0x35, 0xb8, - 0xa4, 0x9e, 0x95, 0x62, 0x0e, 0x48, 0x04, 0x67, 0xec, 0xdb, 0x00, 0x63, 0x7f, 0x8d, 0x9c, 0xc3, 0x55, 0xeb, 0xaa, - 0xad, 0x60, 0x6d, 0x9d, 0x3e, 0x6d, 0x1c, 0xc6, 0x2b, 0xfb, 0x27, 0xe0, 0xbb, 0x78, 0x51, 0x3b, 0x32, 0xfd, 0x2d, - 0x8e, 0x35, 0x84, 0x42, 0xd7, 0x27, 0x86, 0xc2, 0x8c, 0xc1, 0x30, 0xbb, 0xbb, 0x20, 0x4c, 0xaf, 0x2f, 0x05, 0x0c, - 0x0b, 0x37, 0x97, 0x62, 0xc7, 0xf1, 0xf3, 0x07, 0xfb, 0x89, 0x22, 0x1c, 0x9a, 0xa9, 0x10, 0x3e, 0x97, 0xae, 0x8c, - 0x82, 0x9c, 0x99, 0xcc, 0x09, 0x3c, 0xd8, 0x3e, 0x07, 0xd4, 0x28, 0x12, 0x8a, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x4d, - 0xc2, 0x05, 0xe9, 0xcb, 0x71, 0x7d, 0x34, 0xbd, 0x86, 0x29, 0x59, 0x99, 0xb7, 0x48, 0xfc, 0x6c, 0x99, 0xf5, 0x11, - 0xe1, 0x74, 0xaf, 0x6d, 0x60, 0x8b, 0xb5, 0x6d, 0xef, 0xd7, 0x3d, 0xe0, 0xca, 0xc2, 0x81, 0xa1, 0x8d, 0x4c, 0x7d, - 0xb5, 0xa1, 0x97, 0x14, 0x71, 0xfe, 0x15, 0x3d, 0x32, 0x7e, 0x30, 0xf6, 0x7d, 0x07, 0x77, 0x0a, 0xa4, 0xb7, 0x39, - 0xbf, 0x61, 0xa6, 0xf7, 0x60, 0x75, 0x03, 0x35, 0xac, 0xc1, 0xa5, 0x32, 0x4b, 0x8d, 0xf9, 0x17, 0xb7, 0xc4, 0x27, - 0x0b, 0x8e, 0x12, 0x9f, 0x42, 0xe2, 0x1a, 0xae, 0x4f, 0x1f, 0x1f, 0x99, 0xf4, 0x6d, 0x12, 0x8a, 0xec, 0x56, 0x2c, - 0xdb, 0x43, 0xc5, 0x98, 0x1c, 0xee, 0x8a, 0xab, 0x36, 0x38, 0x60, 0x88, 0xd2, 0xd1, 0x10, 0x49, 0x83, 0x26, 0x0e, - 0x24, 0x8c, 0xf7, 0xc5, 0x0c, 0xcb, 0x0d, 0x5d, 0xbc, 0x22, 0x7a, 0x6b, 0xcd, 0xce, 0xa4, 0xec, 0x65, 0x45, 0xbe, - 0x29, 0xd5, 0xe4, 0x63, 0xba, 0x5a, 0x4f, 0x4b, 0xaf, 0x2d, 0xf7, 0x58, 0x00, 0x74, 0xaf, 0x8e, 0x7f, 0xbd, 0xef, - 0x75, 0xd5, 0x67, 0x22, 0xdf, 0xfa, 0x7a, 0x18, 0xbe, 0xdd, 0x7f, 0xa9, 0xa3, 0x38, 0xb8, 0x45, 0xec, 0xdf, 0xfe, - 0x48, 0x59, 0xd4, 0xd6, 0xaa, 0x1f, 0xd4, 0xc1, 0xa1, 0xa7, 0x1e, 0x37, 0x67, 0x61, 0x4d, 0x30, 0xe1, 0x54, 0x81, - 0x73, 0xa6, 0x83, 0xd0, 0xc6, 0xf2, 0x6f, 0x1c, 0xd5, 0xa6, 0x6e, 0xdc, 0xa0, 0x3c, 0xe3, 0xd9, 0x58, 0x19, 0xea, - 0xb2, 0x95, 0x9d, 0xf9, 0xb2, 0xf3, 0x8c, 0x9c, 0xf7, 0xac, 0xa6, 0x5f, 0x1a, 0x0b, 0x7c, 0xa5, 0xe2, 0x08, 0xe1, - 0x67, 0xc0, 0xbb, 0xc4, 0xb1, 0x63, 0x66, 0x7c, 0x0c, 0x4a, 0xbb, 0x5b, 0xd2, 0xe8, 0x30, 0xb2, 0x1d, 0x74, 0x9d, - 0xcb, 0x64, 0x44, 0x50, 0x10, 0x22, 0xe4, 0x30, 0xb4, 0x43, 0x28, 0x67, 0xfb, 0xb1, 0xaa, 0xdc, 0x5e, 0xf4, 0x06, - 0xf3, 0x4a, 0xb6, 0x50, 0x04, 0x4c, 0x09, 0xbe, 0x5f, 0xd5, 0xd4, 0x88, 0x7d, 0xd3, 0xbf, 0x3d, 0x7c, 0x9a, 0x8b, - 0x9a, 0xa0, 0x01, 0xff, 0x3b, 0x96, 0xd5, 0xa0, 0x37, 0x56, 0x5f, 0x68, 0xd9, 0xb7, 0x86, 0x1c, 0x18, 0x55, 0x92, - 0xb6, 0x6e, 0x2f, 0x64, 0x95, 0x39, 0x57, 0xbb, 0x42, 0xf5, 0xa5, 0x47, 0x39, 0x99, 0xa6, 0x00, 0x30, 0x5d, 0x69, - 0x01, 0x71, 0x41, 0x21, 0xb4, 0xe0, 0xb0, 0x9a, 0x85, 0x4c, 0x5f, 0xcf, 0x4e, 0x61, 0xc1, 0x68, 0xbc, 0x30, 0xad, - 0x0d, 0x89, 0x32, 0x33, 0xa7, 0x4c, 0x4a, 0x77, 0xa9, 0xdd, 0x82, 0x3c, 0xf8, 0x2d, 0x2d, 0x1b, 0x80, 0x11, 0x13, - 0xc9, 0x77, 0x61, 0x13, 0x59, 0xfb, 0x7c, 0xce, 0xb8, 0xcd, 0xec, 0x49, 0xdf, 0xd4, 0xf4, 0x64, 0xe3, 0x34, 0x58, - 0x7f, 0x84, 0x9c, 0xe7, 0x6e, 0xa4, 0x6c, 0x6d, 0xe2, 0x96, 0xfb, 0x12, 0x1d, 0x43, 0x9f, 0x68, 0x97, 0x13, 0x76, - 0x40, 0x07, 0xfa, 0x4c, 0x5a, 0xc3, 0x35, 0x10, 0xe5, 0x30, 0x88, 0xa7, 0x72, 0x28, 0xae, 0x97, 0x3d, 0x46, 0x9d, - 0xc6, 0x02, 0x35, 0xb0, 0xc2, 0x17, 0x18, 0x46, 0x55, 0x05, 0x7b, 0xe0, 0x6f, 0x82, 0x9c, 0xae, 0xbe, 0x53, 0x2c, - 0x79, 0xd3, 0x12, 0xd1, 0x2e, 0x98, 0xb0, 0x0e, 0x2a, 0x1e, 0x63, 0xab, 0x49, 0x4a, 0x83, 0xa1, 0xeb, 0xc9, 0x77, - 0x41, 0xc6, 0x66, 0x32, 0xd2, 0xb4, 0x80, 0x3b, 0xcc, 0xed, 0x3c, 0x29, 0xcc, 0x21, 0x96, 0x8d, 0xab, 0xb8, 0x71, - 0xed, 0x6b, 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcd, 0x8b, 0xf6, 0x11, 0xaf, 0x63, 0x89, 0x65, 0xad, 0x9c, - 0xee, 0x30, 0xc2, 0x80, 0x88, 0xfb, 0x48, 0x17, 0xcc, 0x2c, 0xb5, 0xb5, 0xb8, 0x2a, 0x62, 0x59, 0xb6, 0x6b, 0x2c, - 0x06, 0x60, 0x14, 0xd8, 0x1f, 0xce, 0x6b, 0x19, 0x34, 0x7a, 0x3e, 0x7c, 0xba, 0x22, 0xa7, 0x65, 0x6d, 0x86, 0x0d, - 0xcf, 0xa6, 0x03, 0x54, 0xb8, 0x26, 0x56, 0xe7, 0x25, 0xd8, 0x8b, 0xb5, 0xe5, 0xe8, 0xdf, 0xbb, 0xf4, 0x22, 0x9e, - 0x17, 0x84, 0x70, 0x2a, 0x36, 0x5b, 0x1a, 0x20, 0x0e, 0x60, 0x17, 0x53, 0x1d, 0x10, 0x82, 0xba, 0xb3, 0xda, 0x03, - 0xf2, 0xf9, 0x6b, 0x86, 0xbe, 0x8f, 0x84, 0x6f, 0x02, 0x64, 0xa6, 0xa0, 0x3c, 0x51, 0xfb, 0x14, 0x45, 0xf4, 0xe0, - 0x27, 0x5d, 0x65, 0xb3, 0x16, 0x75, 0x12, 0x38, 0x1d, 0x71, 0x72, 0x16, 0xa3, 0x70, 0x5e, 0x3e, 0x13, 0xc0, 0x97, - 0x6b, 0x34, 0x98, 0x16, 0xdb, 0x28, 0x4e, 0xd9, 0x4e, 0xba, 0x5b, 0x03, 0x74, 0xc7, 0xe7, 0x88, 0xc3, 0x41, 0x26, - 0xca, 0xde, 0xae, 0x33, 0x5d, 0x86, 0x75, 0x53, 0x47, 0xbd, 0x9f, 0x28, 0x7c, 0x4a, 0xdd, 0xe3, 0x7d, 0x2e, 0x45, - 0x50, 0x21, 0x54, 0x12, 0xd4, 0x32, 0xa4, 0x3f, 0x6a, 0x79, 0x4e, 0x8d, 0xd4, 0x29, 0x8f, 0xcb, 0x05, 0x49, 0x6a, - 0xfb, 0x3e, 0x7b, 0xb4, 0x2f, 0x4f, 0xe4, 0x8e, 0x1b, 0x38, 0xd1, 0xb5, 0x02, 0x86, 0x4e, 0x73, 0x0f, 0x76, 0xde, - 0x8a, 0x8a, 0x64, 0x22, 0x8a, 0xa1, 0xbd, 0x84, 0xb3, 0x2a, 0xbb, 0x49, 0x42, 0x7f, 0x16, 0x2b, 0x9c, 0xd9, 0xb9, - 0x0c, 0xb5, 0x69, 0x6c, 0x61, 0x90, 0x51, 0x21, 0xb4, 0xdb, 0x98, 0x47, 0x98, 0xdc, 0x45, 0x6e, 0xf0, 0x2b, 0xad, - 0x54, 0x2e, 0x15, 0x92, 0xa6, 0x4b, 0x6f, 0xfd, 0x2f, 0x3b, 0x6a, 0xc5, 0x8d, 0xb7, 0x36, 0xca, 0x35, 0xca, 0xc5, - 0xcc, 0xf9, 0x8f, 0xd8, 0xe3, 0x12, 0x6b, 0xd8, 0x82, 0xcb, 0x86, 0xae, 0x50, 0x59, 0x4a, 0x03, 0x47, 0x1e, 0x88, - 0xa4, 0xee, 0x6b, 0x38, 0xe2, 0x16, 0xd5, 0x9f, 0xec, 0xf5, 0xc1, 0x06, 0xb5, 0x63, 0x36, 0x72, 0xb1, 0x8d, 0x5a, - 0xa1, 0x0b, 0x59, 0x45, 0x0d, 0x5c, 0x92, 0xb7, 0x60, 0x9a, 0x0c, 0xd1, 0x4d, 0x92, 0xb8, 0x7b, 0x3a, 0xc3, 0x2c, - 0x33, 0xbd, 0xe8, 0x7f, 0x56, 0xa2, 0xd2, 0xa1, 0xac, 0xb9, 0x92, 0xc3, 0x59, 0x47, 0xf5, 0xe3, 0xb0, 0x1f, 0xe2, - 0xd8, 0x74, 0x87, 0xe5, 0x80, 0x01, 0xac, 0x3a, 0xcc, 0x91, 0xa2, 0xf1, 0x62, 0xeb, 0xbb, 0x7d, 0xb7, 0x8d, 0x94, - 0xd0, 0xd0, 0x2f, 0x76, 0x08, 0xd8, 0xb7, 0xdf, 0x86, 0x39, 0xe3, 0xb6, 0x36, 0x8e, 0xf6, 0x51, 0x44, 0xda, 0x54, - 0x10, 0xfc, 0x91, 0x34, 0x39, 0xc0, 0x36, 0x5d, 0xca, 0x61, 0x73, 0xe5, 0xde, 0x67, 0x86, 0xc5, 0x94, 0x11, 0x31, - 0xab, 0xf7, 0x54, 0xe8, 0xaf, 0x7f, 0xf7, 0xdf, 0x2d, 0x5a, 0x5a, 0x34, 0xca, 0x8b, 0xf3, 0x72, 0x30, 0xb6, 0xea, - 0xd2, 0x7b, 0xb3, 0x34, 0xd6, 0x01, 0x40, 0xe5, 0xee, 0xfd, 0x45, 0x88, 0xbb, 0xeb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, - 0x93, 0xf2, 0xa9, 0xa7, 0x6c, 0x2c, 0x89, 0x3c, 0x65, 0xd6, 0xce, 0xed, 0x33, 0xbb, 0x09, 0x80, 0xf1, 0xbf, 0x32, - 0x3f, 0x2d, 0x2c, 0xf4, 0x9d, 0x56, 0x72, 0x51, 0xdb, 0x68, 0x67, 0xf4, 0x3e, 0x47, 0x81, 0x39, 0x40, 0x24, 0x27, - 0xe4, 0x3d, 0xbe, 0xa2, 0x78, 0xfc, 0x3f, 0x66, 0xa5, 0x61, 0xe3, 0xc4, 0x8e, 0xf2, 0xed, 0xc7, 0x0d, 0x1b, 0x29, - 0x39, 0x0f, 0x23, 0x23, 0x4c, 0xff, 0x1e, 0x99, 0x38, 0x8d, 0xca, 0xce, 0x3e, 0x2a, 0x88, 0x7a, 0xe2, 0xe3, 0xfb, - 0x73, 0x6c, 0xdd, 0x3f, 0x12, 0x2d, 0x65, 0x10, 0x96, 0x02, 0x38, 0x29, 0xf3, 0x48, 0xc3, 0x02, 0x98, 0xa2, 0x79, - 0x90, 0xf1, 0xc9, 0x69, 0x68, 0xbf, 0x7f, 0xe9, 0xf4, 0x1a, 0xb4, 0xbb, 0xc6, 0x30, 0x91, 0x35, 0x38, 0x77, 0x75, - 0xfb, 0x68, 0xd0, 0xdb, 0x7b, 0xde, 0x7e, 0x34, 0xe9, 0xad, 0xcd, 0x59, 0x43, 0x1b, 0x12, 0xc7, 0x3f, 0x6c, 0xff, - 0xa5, 0x9e, 0x27, 0x7b, 0xb7, 0x9a, 0x49, 0x91, 0x75, 0x39, 0xc4, 0x69, 0xd8, 0x52, 0x24, 0x1e, 0x80, 0xb8, 0xd4, - 0xfe, 0x58, 0xb2, 0xbc, 0xda, 0x83, 0xa2, 0xff, 0xd1, 0xfc, 0x48, 0x6b, 0xb2, 0x0f, 0xbe, 0x4c, 0xa1, 0x6a, 0xf7, - 0x33, 0xba, 0x3b, 0xbf, 0x07, 0x39, 0xb6, 0x59, 0x9a, 0xf8, 0xe2, 0xad, 0xa3, 0xe7, 0x89, 0xb4, 0x16, 0x5a, 0x99, - 0x61, 0x7a, 0xea, 0x1e, 0xc3, 0x52, 0x24, 0x4b, 0xcb, 0xde, 0xf2, 0x35, 0xe7, 0xe9, 0x4c, 0x7f, 0x7c, 0x10, 0xd7, - 0xb7, 0x7d, 0x4a, 0x7c, 0x8a, 0x98, 0x5f, 0xed, 0x13, 0xe0, 0x2c, 0x09, 0x1e, 0x47, 0x44, 0xa0, 0xb3, 0x15, 0xe5, - 0x23, 0x55, 0x75, 0xcd, 0xae, 0xff, 0xd1, 0xca, 0x02, 0x3b, 0x33, 0x1b, 0x77, 0x2b, 0x67, 0xfa, 0xe8, 0x34, 0xcf, - 0x72, 0x43, 0x3b, 0x90, 0x8b, 0x0d, 0x70, 0x60, 0xff, 0xb6, 0x49, 0x30, 0xac, 0x6d, 0xb8, 0x3f, 0x52, 0xbd, 0x31, - 0x4a, 0xfe, 0x46, 0x00, 0x46, 0x51, 0xd1, 0x56, 0xf1, 0xe6, 0x1a, 0xba, 0x90, 0x51, 0xbd, 0x3f, 0x79, 0x0f, 0xdf, - 0xef, 0x43, 0x1f, 0xba, 0x75, 0xd0, 0x5a, 0x70, 0x2a, 0x8b, 0x72, 0x39, 0xda, 0x3c, 0xef, 0x46, 0x5c, 0x7a, 0xf9, - 0x4d, 0x4f, 0x94, 0x7a, 0xfb, 0x6b, 0x07, 0x5b, 0x5a, 0x7e, 0x44, 0xa6, 0x9e, 0x24, 0x0a, 0x39, 0xd6, 0x4e, 0xf0, - 0x6a, 0xe9, 0x48, 0xc5, 0x81, 0xc3, 0xdd, 0x93, 0x91, 0x6f, 0xe6, 0x8c, 0x5d, 0x4b, 0x3a, 0x1e, 0x6c, 0x0c, 0xeb, - 0xe6, 0x6b, 0x29, 0xcd, 0x32, 0xeb, 0xd5, 0x3d, 0x3b, 0x11, 0x5e, 0x70, 0x78, 0x25, 0xb6, 0x29, 0xa4, 0xf9, 0xd5, - 0x44, 0x02, 0x37, 0xaf, 0xf7, 0x05, 0x20, 0x97, 0xb9, 0x74, 0x2e, 0xd8, 0x82, 0x74, 0xc5, 0x7f, 0x8e, 0x2a, 0xd0, - 0x27, 0x3f, 0xb3, 0x4a, 0xd7, 0xfa, 0x4a, 0x59, 0xa5, 0xf2, 0x1c, 0xdf, 0xd1, 0xa4, 0xd8, 0x3b, 0xda, 0x93, 0xd9, - 0x21, 0x1c, 0x8d, 0xc1, 0xcd, 0xfd, 0x46, 0x25, 0x65, 0x16, 0xa7, 0x5e, 0x92, 0xfe, 0x4b, 0xc2, 0x0c, 0x83, 0x84, - 0x04, 0x31, 0xff, 0x47, 0xdc, 0x98, 0xa3, 0x0e, 0x69, 0x0c, 0x4e, 0x64, 0x82, 0xd1, 0x42, 0x21, 0xba, 0x29, 0xcb, - 0x95, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xda, 0x65, 0x8d, 0x34, 0x2f, 0x7d, 0x0f, 0xbb, 0x87, 0x81, 0x14, 0x34, - 0x0a, 0x4b, 0x63, 0x0c, 0xec, 0xec, 0x26, 0x6d, 0x63, 0xb8, 0xd5, 0x1b, 0x68, 0x0a, 0x77, 0xef, 0xe9, 0x1a, 0xfa, - 0x5c, 0x24, 0x12, 0x4b, 0x7a, 0xb4, 0x8b, 0xc9, 0xb5, 0x96, 0xca, 0xb2, 0x5a, 0x8e, 0xdf, 0x4e, 0xf7, 0xb2, 0xbc, - 0x20, 0x68, 0xc8, 0x81, 0x93, 0xa3, 0xc0, 0x29, 0x97, 0x77, 0x32, 0x0d, 0x8e, 0x83, 0xb7, 0x99, 0x85, 0xc4, 0x1f, - 0xe4, 0x6d, 0xe8, 0xc8, 0x9c, 0xfd, 0xa0, 0x4d, 0x7f, 0xd4, 0x54, 0x85, 0x59, 0xd4, 0x43, 0x24, 0x03, 0x93, 0xee, - 0xde, 0x36, 0x06, 0x1d, 0x1f, 0xd7, 0x35, 0x6c, 0xee, 0x23, 0x0c, 0xae, 0x90, 0x08, 0xcd, 0xb1, 0x90, 0x3c, 0x03, - 0x9f, 0xe2, 0x61, 0x93, 0xa7, 0xcc, 0xdd, 0x8e, 0x89, 0xe3, 0xed, 0xe7, 0x9a, 0x26, 0x7b, 0xd9, 0xab, 0x7a, 0xf2, - 0x14, 0xb5, 0x5f, 0xb5, 0x6c, 0x46, 0x5a, 0xae, 0x79, 0x37, 0xf7, 0x30, 0x7a, 0x3e, 0xc5, 0x03, 0x3b, 0x08, 0xdc, - 0x19, 0xb1, 0x38, 0xc6, 0xf9, 0xbd, 0x55, 0x3c, 0x8c, 0xd1, 0x75, 0x19, 0x60, 0xd4, 0x06, 0xa2, 0x0f, 0x82, 0xf8, - 0x3e, 0x3b, 0x60, 0xdd, 0x39, 0xb0, 0x78, 0x63, 0x7a, 0xdc, 0x26, 0xe1, 0xb4, 0xd4, 0x27, 0xe3, 0x43, 0x36, 0x07, - 0x24, 0x54, 0x8a, 0x39, 0x0b, 0x42, 0x34, 0x01, 0x62, 0x0e, 0x29, 0xc9, 0x5e, 0xed, 0x03, 0x28, 0x62, 0x2e, 0x54, - 0x2e, 0x9a, 0x83, 0x1e, 0x10, 0x82, 0x1c, 0x66, 0x6c, 0xff, 0x31, 0x7e, 0x0c, 0x0f, 0x77, 0x58, 0xc8, 0x32, 0xe7, - 0x0d, 0x2e, 0xf2, 0xfd, 0x57, 0xc0, 0x5c, 0xba, 0x7a, 0xab, 0xbe, 0xd3, 0x13, 0xa4, 0xf4, 0x3e, 0x4b, 0x95, 0x5a, - 0x45, 0xee, 0x62, 0x95, 0x10, 0x5e, 0x17, 0x69, 0x34, 0x50, 0xd2, 0xdd, 0xa1, 0x1f, 0x7e, 0x05, 0x11, 0xd3, 0x17, - 0x12, 0xf0, 0x27, 0xf2, 0x03, 0xb1, 0xe0, 0xf5, 0x86, 0xa2, 0x30, 0x20, 0x7a, 0x0c, 0xb5, 0xf0, 0x0c, 0x95, 0x8a, - 0x93, 0xac, 0xe0, 0xee, 0x30, 0x4a, 0xd9, 0x3f, 0x4e, 0xe4, 0xc7, 0xaa, 0x3a, 0x76, 0x69, 0xd3, 0x5d, 0xc5, 0x6f, - 0x4b, 0xf6, 0x02, 0x88, 0x99, 0x2a, 0x3b, 0x53, 0x25, 0x22, 0x5f, 0x17, 0x88, 0xa0, 0x24, 0x3d, 0x4b, 0x76, 0xaf, - 0x86, 0xcf, 0xac, 0x62, 0x47, 0x9c, 0xd9, 0x25, 0x87, 0x80, 0xdf, 0x39, 0x99, 0xd8, 0xf4, 0xc1, 0xde, 0x79, 0xa0, - 0x4d, 0x1f, 0xa4, 0xc5, 0x5f, 0x16, 0x24, 0xf2, 0x0f, 0x5d, 0xf7, 0x16, 0x8c, 0x4d, 0x5a, 0x7f, 0x33, 0xf6, 0x20, - 0x6c, 0x8f, 0xb9, 0x79, 0x3b, 0x72, 0xcd, 0x7c, 0x89, 0x51, 0xee, 0xcd, 0xe9, 0x34, 0x7b, 0x9b, 0x61, 0x57, 0x37, - 0x7a, 0xd0, 0xac, 0x46, 0xfa, 0xe2, 0x27, 0xaa, 0xea, 0xe9, 0x06, 0x50, 0xef, 0xfc, 0xf4, 0xe9, 0xe8, 0xcb, 0x30, - 0x5b, 0x43, 0x72, 0x98, 0x30, 0x2f, 0xaa, 0xb1, 0xe7, 0xfa, 0x0c, 0xc1, 0xac, 0xa4, 0x7d, 0x07, 0x66, 0xe9, 0xb7, - 0x4c, 0x24, 0x87, 0x3e, 0xc5, 0xbe, 0x65, 0x45, 0x30, 0x48, 0xe7, 0xae, 0x46, 0xc5, 0x71, 0x16, 0xfa, 0x68, 0xda, - 0x72, 0x5f, 0xd4, 0xc8, 0x6d, 0x89, 0xd3, 0xe7, 0x72, 0xce, 0x40, 0xd8, 0x2f, 0xee, 0x38, 0xb3, 0xbe, 0xf3, 0x0e, - 0x49, 0x6b, 0x3d, 0x43, 0xbf, 0xa6, 0xf5, 0xd2, 0xad, 0xff, 0x3e, 0xf2, 0x56, 0xa6, 0x1d, 0x56, 0xcb, 0x39, 0x4d, - 0x4f, 0x55, 0xd9, 0x1b, 0x3c, 0x29, 0x03, 0x94, 0x2c, 0xa0, 0xbb, 0xac, 0x2d, 0x77, 0x13, 0xa0, 0xfe, 0x3a, 0xd2, - 0xb5, 0xfe, 0xce, 0x0a, 0x18, 0x14, 0x81, 0xda, 0x7e, 0x95, 0xf3, 0xa4, 0xbd, 0x12, 0x1f, 0x7f, 0xaf, 0x28, 0x36, - 0x5b, 0x9e, 0xbc, 0x15, 0xc8, 0x44, 0x3f, 0x0d, 0xcf, 0x9d, 0x9f, 0xab, 0x59, 0x98, 0x98, 0x4f, 0x97, 0x96, 0xdf, - 0xe3, 0x43, 0x77, 0x01, 0xad, 0xf7, 0x19, 0x21, 0x8d, 0xf9, 0x3f, 0xc7, 0x2c, 0x4b, 0xbc, 0x42, 0xb3, 0x7c, 0x1b, - 0xe0, 0x98, 0x0e, 0x4f, 0x49, 0xe3, 0x39, 0x0e, 0x28, 0x74, 0x83, 0x52, 0x6f, 0x37, 0x43, 0x2d, 0xc9, 0xc3, 0x42, - 0x41, 0x26, 0xfd, 0x88, 0xe6, 0x51, 0x76, 0x24, 0x80, 0x91, 0x69, 0xf5, 0xb7, 0xb9, 0xb6, 0xc8, 0xa3, 0x56, 0xfb, - 0x55, 0xe1, 0x5e, 0x9f, 0x45, 0xa3, 0xff, 0x6e, 0x06, 0x9c, 0x58, 0x1b, 0xb2, 0x37, 0x01, 0xd3, 0x88, 0x62, 0x8a, - 0x82, 0x1f, 0x0b, 0x92, 0x42, 0xa5, 0xe2, 0x5d, 0xd8, 0x22, 0x2c, 0x5c, 0x6a, 0x69, 0x19, 0x6b, 0xe2, 0x79, 0x0b, - 0xd0, 0xd1, 0xfe, 0xeb, 0xe2, 0xbb, 0xec, 0x99, 0xc1, 0x28, 0x29, 0xf7, 0x18, 0x8f, 0x04, 0xf5, 0x38, 0x2b, 0x01, - 0xfb, 0x2d, 0x84, 0xf8, 0x4a, 0x50, 0x93, 0x26, 0x75, 0x17, 0xc1, 0xe9, 0x36, 0x14, 0x70, 0x19, 0xad, 0x35, 0x12, - 0x34, 0x7c, 0x77, 0x92, 0x16, 0xb0, 0x2a, 0x78, 0x2f, 0x71, 0xc9, 0x8f, 0x81, 0x99, 0x8a, 0xee, 0xf0, 0x07, 0xd3, - 0xc7, 0x3b, 0xca, 0xf3, 0xb2, 0xd3, 0xba, 0xf6, 0x6e, 0xc3, 0x20, 0x8c, 0x18, 0x9f, 0x19, 0xe8, 0xc8, 0x5e, 0x0f, - 0xd8, 0x92, 0xc9, 0x18, 0x1b, 0xf0, 0x84, 0x28, 0xc8, 0x68, 0x9d, 0x8f, 0x2c, 0x5f, 0xec, 0xeb, 0x1e, 0x06, 0x27, - 0x64, 0x6c, 0x1c, 0x81, 0x1b, 0x35, 0x20, 0x43, 0xc2, 0x2c, 0xe1, 0xc7, 0x1e, 0xe1, 0x58, 0x3b, 0xf8, 0xaf, 0xb4, - 0x01, 0x05, 0xe4, 0x68, 0x4f, 0x0a, 0x49, 0xe6, 0x31, 0xcc, 0x1a, 0x14, 0x3e, 0x22, 0x43, 0x99, 0x93, 0xff, 0x1c, - 0x4b, 0x8a, 0x0d, 0xc7, 0xb1, 0x18, 0x99, 0x75, 0x1c, 0x7f, 0xea, 0xcc, 0x6f, 0x1b, 0xde, 0x83, 0x2a, 0x7a, 0xba, - 0x0e, 0x1e, 0x42, 0x29, 0x42, 0xb9, 0x99, 0x09, 0xe5, 0x47, 0x58, 0x74, 0x67, 0xb4, 0x01, 0xad, 0x1f, 0xa3, 0x47, - 0xbe, 0x7e, 0x83, 0x93, 0xcb, 0x50, 0x81, 0x75, 0xf1, 0xc3, 0x0f, 0xc4, 0xf4, 0xd9, 0x3b, 0x16, 0x6b, 0xe5, 0x6c, - 0x4e, 0x7d, 0xc9, 0xd0, 0x05, 0x5f, 0xa7, 0xeb, 0x13, 0xef, 0x95, 0x09, 0x52, 0xb3, 0xb0, 0x5a, 0x27, 0x36, 0x91, - 0x49, 0x8b, 0xd3, 0xe4, 0xdd, 0xfc, 0xe5, 0x69, 0x36, 0xf1, 0xca, 0xa5, 0xc0, 0xa4, 0x67, 0x51, 0x25, 0x36, 0x32, - 0xd3, 0x65, 0xc3, 0xbf, 0x1c, 0xe5, 0xf3, 0x6c, 0xa8, 0x67, 0x9e, 0x5f, 0xd0, 0x8d, 0xfb, 0xc3, 0x2c, 0x12, 0x6a, - 0x76, 0x5b, 0xe7, 0xcc, 0x4e, 0xb5, 0xcd, 0x7f, 0xb0, 0x73, 0xfb, 0xd8, 0xf7, 0x99, 0x8f, 0x64, 0x96, 0xae, 0x28, - 0x09, 0xbb, 0xe3, 0x21, 0xe9, 0x14, 0x93, 0x15, 0x67, 0x4e, 0x03, 0xf5, 0x5c, 0x16, 0xe7, 0x35, 0xb9, 0xbb, 0x80, - 0xb7, 0x82, 0x29, 0x03, 0x24, 0xd5, 0xf1, 0x45, 0x70, 0x55, 0x11, 0x38, 0x35, 0xb5, 0x50, 0x45, 0xf1, 0xb8, 0x33, - 0xdb, 0x2d, 0xa0, 0xea, 0xa7, 0x6a, 0x71, 0x69, 0xa4, 0xa2, 0x84, 0x67, 0xb2, 0x15, 0xa6, 0x40, 0xa6, 0x2b, 0x27, - 0xcd, 0x49, 0xac, 0x70, 0xd0, 0xcf, 0x22, 0x27, 0xd9, 0x8b, 0xaa, 0x76, 0xc3, 0x4b, 0x5b, 0x6b, 0x56, 0x18, 0xed, - 0x6c, 0xb5, 0x48, 0x27, 0x52, 0xb1, 0x7d, 0xa8, 0x1e, 0x0a, 0xf7, 0xdd, 0x04, 0x56, 0x6a, 0xa4, 0xb2, 0xfc, 0x75, - 0xa4, 0x86, 0x47, 0xfc, 0xb5, 0x49, 0x07, 0x49, 0xc3, 0x86, 0x1d, 0x6d, 0x6e, 0x9b, 0xcb, 0xa0, 0x58, 0xd6, 0x38, - 0x8c, 0x4a, 0x43, 0xb7, 0x11, 0xf9, 0x0a, 0xe5, 0x91, 0x7d, 0x13, 0x79, 0x43, 0x2c, 0xd9, 0x43, 0xbc, 0x46, 0xc2, - 0x24, 0xa5, 0x8f, 0x62, 0x8b, 0xc6, 0x85, 0xa2, 0x5b, 0xa6, 0xdd, 0xa6, 0x3b, 0x57, 0x49, 0x2e, 0xd3, 0x53, 0xcf, - 0xb3, 0x40, 0x29, 0xac, 0x44, 0x44, 0x42, 0xc8, 0x98, 0x67, 0x6f, 0xfc, 0xd4, 0xf4, 0xdc, 0x23, 0x4a, 0x34, 0xfb, - 0x02, 0xef, 0x85, 0x3e, 0x88, 0x11, 0x1f, 0x9b, 0x90, 0x63, 0xf8, 0xca, 0xe9, 0xf0, 0xbd, 0x6d, 0x4e, 0xfe, 0x68, - 0xe7, 0xe3, 0x89, 0x32, 0x25, 0xaa, 0x76, 0xf1, 0xb4, 0x81, 0xc4, 0x1a, 0x20, 0x9e, 0xa5, 0x63, 0x09, 0x4a, 0xa3, - 0xc7, 0x60, 0xe7, 0xf3, 0x6a, 0x97, 0x85, 0xda, 0xf4, 0x74, 0x97, 0xa5, 0x09, 0x70, 0xc1, 0x8e, 0xd2, 0xdb, 0xc4, - 0xee, 0xee, 0x2f, 0x1c, 0xd0, 0xdd, 0x37, 0x19, 0xd9, 0x68, 0x76, 0xd9, 0x90, 0xb0, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, - 0x25, 0x52, 0x21, 0xde, 0xd8, 0x37, 0x80, 0x99, 0x4c, 0x7b, 0xa6, 0xd1, 0x03, 0x91, 0xe2, 0x37, 0x60, 0x3b, 0x50, - 0x09, 0x0d, 0x32, 0x12, 0xf5, 0x93, 0x08, 0x35, 0x31, 0xee, 0x71, 0xfe, 0xe3, 0x9a, 0x72, 0x74, 0x90, 0x40, 0x8e, - 0x07, 0xbb, 0x67, 0x9d, 0x11, 0xc5, 0x59, 0x4f, 0x5a, 0xd5, 0x3c, 0x73, 0xd1, 0xa1, 0x74, 0x66, 0x1f, 0x28, 0xd1, - 0x13, 0x45, 0x7f, 0xb9, 0x1d, 0xe9, 0x47, 0x80, 0xc1, 0xb0, 0x2b, 0xcc, 0x7f, 0x32, 0x9d, 0x70, 0x41, 0x44, 0x3d, - 0x77, 0x57, 0xbd, 0x1d, 0x16, 0x3b, 0x93, 0xc9, 0xf8, 0xe4, 0x97, 0x81, 0xbb, 0x6f, 0x87, 0x88, 0xb4, 0x89, 0xdb, - 0x18, 0xf9, 0x64, 0x12, 0x30, 0xdb, 0xd5, 0x8d, 0x6a, 0x46, 0x3a, 0x26, 0x11, 0x53, 0xeb, 0x37, 0xf6, 0x79, 0x9b, - 0x5e, 0xbb, 0x07, 0xff, 0xfd, 0x06, 0x4d, 0x90, 0x7a, 0xa6, 0x8a, 0xc5, 0xfb, 0x70, 0xe7, 0xa0, 0xfb, 0xcb, 0xf6, - 0x59, 0x5e, 0xf6, 0xb0, 0x14, 0x32, 0xb4, 0x4a, 0xd4, 0xf9, 0x58, 0x3b, 0x8c, 0x74, 0x7e, 0xa6, 0x61, 0xb9, 0xd6, - 0x7f, 0xaa, 0x3a, 0x98, 0xf5, 0x9b, 0xc1, 0x49, 0x65, 0xb1, 0xa8, 0xa6, 0x92, 0x0b, 0xef, 0xe0, 0x6b, 0x38, 0xb7, - 0x86, 0x7e, 0xed, 0xa6, 0xf2, 0xd4, 0x55, 0xe1, 0xb2, 0xef, 0xa2, 0x9f, 0xb0, 0xa9, 0xbf, 0x8a, 0x41, 0xf9, 0xeb, - 0xe0, 0x14, 0x54, 0x6f, 0xc8, 0x1b, 0x23, 0x75, 0x17, 0xef, 0x17, 0x52, 0x62, 0x72, 0xc4, 0x3f, 0x0a, 0x86, 0x46, - 0x69, 0x5b, 0xaa, 0x63, 0xec, 0x2c, 0x98, 0xec, 0xac, 0x76, 0x5b, 0xff, 0x8e, 0x82, 0x27, 0xda, 0xce, 0xef, 0x7e, - 0x24, 0x35, 0x0f, 0xb0, 0xce, 0xfa, 0xf2, 0x23, 0x70, 0x5e, 0xdb, 0x8f, 0xd4, 0xf3, 0xa1, 0x98, 0x9e, 0x68, 0x7d, - 0xcc, 0xda, 0xf3, 0x6c, 0xc1, 0x9e, 0xef, 0x59, 0x08, 0x35, 0x52, 0x67, 0xfc, 0xc0, 0xcc, 0xef, 0x42, 0x67, 0x3b, - 0xec, 0xb2, 0x63, 0xad, 0x79, 0xbf, 0x32, 0x63, 0xa5, 0xca, 0x7a, 0xe7, 0xd8, 0x91, 0x6b, 0x8d, 0x27, 0x63, 0x18, - 0x48, 0x1a, 0xab, 0x9b, 0xe1, 0xd4, 0x09, 0x95, 0x6f, 0x66, 0x41, 0xc7, 0x4e, 0xa2, 0x9b, 0xe5, 0x22, 0x4a, 0xa4, - 0xc8, 0xdf, 0x06, 0x99, 0x62, 0x38, 0x64, 0xc2, 0xa3, 0xb8, 0x37, 0x41, 0xc2, 0xbc, 0x56, 0x52, 0x26, 0x56, 0x3b, - 0xba, 0x5e, 0xa5, 0x47, 0xc1, 0xc1, 0x9a, 0x2a, 0x69, 0x33, 0x10, 0x75, 0xa9, 0xfb, 0xb0, 0xa6, 0xfb, 0x43, 0xa3, - 0x3a, 0xd8, 0x5f, 0x79, 0x2b, 0xb5, 0x68, 0xfe, 0x45, 0x0d, 0xc7, 0x6a, 0x84, 0xcd, 0x0c, 0x78, 0x1c, 0xfd, 0x1f, - 0x49, 0xa1, 0x43, 0xd7, 0x02, 0xa0, 0xf6, 0xc7, 0xf2, 0x06, 0x45, 0x31, 0x02, 0xb4, 0x1f, 0x56, 0xde, 0x48, 0x7d, - 0xca, 0x1f, 0xcc, 0xae, 0xdb, 0x8e, 0x2c, 0x17, 0xc1, 0x58, 0x93, 0x6d, 0x00, 0x08, 0xcb, 0x17, 0xb0, 0x81, 0x28, - 0x1a, 0x45, 0xd9, 0xd2, 0x3b, 0xec, 0x16, 0x2f, 0x21, 0x5a, 0xf3, 0x98, 0x50, 0xf4, 0x0d, 0xa9, 0xa4, 0xb2, 0xac, - 0xf0, 0xfd, 0xab, 0x0b, 0xe6, 0x5a, 0x18, 0xbd, 0xb5, 0xe7, 0x56, 0xb6, 0xe8, 0xbc, 0xbb, 0xab, 0xe9, 0x9f, 0xda, - 0xd5, 0xf0, 0x91, 0x6d, 0xc0, 0x8c, 0x2c, 0x6c, 0xc9, 0x0f, 0x4f, 0xeb, 0x26, 0x1c, 0xff, 0x28, 0x2a, 0x46, 0x85, - 0x2b, 0x08, 0x16, 0xb5, 0x46, 0x9c, 0x92, 0x7f, 0x1c, 0x00, 0x05, 0xda, 0xc3, 0x92, 0x08, 0x89, 0x51, 0x95, 0xa1, - 0x12, 0xd9, 0x53, 0xf1, 0xab, 0x36, 0x90, 0xc1, 0x24, 0x1c, 0x4a, 0x06, 0x6e, 0x6a, 0xd7, 0x9c, 0x98, 0x9d, 0xb9, - 0xf5, 0x1f, 0xb7, 0x8c, 0xd5, 0x30, 0x61, 0x89, 0xfa, 0x14, 0x66, 0x7a, 0x59, 0xf5, 0x08, 0x8f, 0xa6, 0x85, 0xee, - 0x21, 0x48, 0x2d, 0x8b, 0x84, 0xdf, 0xb3, 0x8e, 0x50, 0x23, 0x98, 0x90, 0xdd, 0xb3, 0x32, 0x0e, 0x21, 0xd7, 0xe9, - 0x71, 0xc6, 0x0b, 0x50, 0xcb, 0x7a, 0x9d, 0xb1, 0xcc, 0x91, 0xd7, 0x82, 0x2e, 0xc9, 0x05, 0xd5, 0x6b, 0x94, 0x0d, - 0x33, 0xae, 0x3f, 0x97, 0x44, 0x23, 0xdf, 0xa0, 0xa1, 0x76, 0xe4, 0x39, 0xf1, 0x79, 0xce, 0xd1, 0x14, 0xc9, 0x1d, - 0x3d, 0x83, 0x56, 0x33, 0x5b, 0x73, 0xd3, 0x9b, 0xaf, 0x36, 0x23, 0x6c, 0x77, 0x3c, 0x4e, 0x99, 0x26, 0x4e, 0x06, - 0xe7, 0x47, 0xa0, 0xcd, 0x9d, 0x96, 0xdc, 0xb8, 0xf8, 0x3f, 0x44, 0x1e, 0xdd, 0x3c, 0x9e, 0x23, 0x98, 0xcb, 0x6d, - 0x8c, 0xe2, 0xe1, 0xe6, 0xd8, 0x05, 0x36, 0xec, 0xff, 0x13, 0x17, 0x5d, 0x13, 0xf1, 0xe2, 0x50, 0x2b, 0x51, 0x09, - 0x71, 0x62, 0x7d, 0xb6, 0x0f, 0xa4, 0xf5, 0x88, 0x84, 0x13, 0x65, 0x9d, 0xcd, 0xc2, 0x38, 0xd6, 0x65, 0xf0, 0xe1, - 0x07, 0x6a, 0x09, 0x41, 0x60, 0x98, 0xbf, 0xc4, 0xfe, 0x04, 0x56, 0x5c, 0x88, 0x42, 0x19, 0xf1, 0xc2, 0xbf, 0xfa, - 0x8c, 0xcf, 0x69, 0x56, 0x56, 0xba, 0xc6, 0xe5, 0xc8, 0x4c, 0xad, 0x61, 0x4e, 0x9e, 0xb0, 0x69, 0x8a, 0x58, 0x4c, - 0xcf, 0x0d, 0x53, 0xcc, 0x08, 0x68, 0x68, 0xce, 0xb9, 0x23, 0x65, 0x4d, 0x82, 0x97, 0x31, 0x29, 0x96, 0x02, 0x74, - 0x85, 0x2e, 0x33, 0xbb, 0xed, 0x0c, 0xe3, 0x60, 0xc8, 0xcd, 0x02, 0x40, 0xb8, 0x12, 0x41, 0x2d, 0x02, 0xcf, 0x8a, - 0x7d, 0x25, 0x32, 0x07, 0x73, 0x91, 0xa3, 0xde, 0xeb, 0xa4, 0xbf, 0x41, 0xc2, 0x25, 0xbc, 0x95, 0x02, 0x27, 0x03, - 0xba, 0x4c, 0xa4, 0x40, 0xf3, 0x12, 0x21, 0xc6, 0x1a, 0x90, 0xd4, 0x36, 0x7e, 0xb9, 0x88, 0x70, 0xcf, 0x07, 0xd9, - 0x70, 0xd6, 0x0d, 0x02, 0x20, 0x8f, 0xf2, 0xfa, 0x3b, 0x8b, 0x74, 0x87, 0x39, 0x01, 0x89, 0x0b, 0x8e, 0x91, 0x13, - 0xda, 0x39, 0x35, 0xd8, 0x32, 0x17, 0xa3, 0x8c, 0xdb, 0x1a, 0x25, 0x4b, 0xe1, 0x6c, 0x23, 0xed, 0x36, 0x72, 0x46, - 0x32, 0x50, 0xeb, 0x32, 0x09, 0x3b, 0x74, 0xed, 0xc9, 0x54, 0x6e, 0x07, 0x78, 0x67, 0xcd, 0x40, 0x9f, 0x6e, 0x3d, - 0x1f, 0xfb, 0x9f, 0x36, 0x57, 0xc9, 0xf4, 0x7d, 0x93, 0x31, 0x62, 0x2e, 0xd1, 0x97, 0x1c, 0x66, 0x9f, 0xf6, 0xfb, - 0x7c, 0x07, 0x8b, 0xf5, 0x55, 0xfc, 0x55, 0xc5, 0x46, 0xfd, 0xd4, 0x7a, 0xc1, 0x24, 0x49, 0x2c, 0xb9, 0x35, 0x28, - 0x29, 0xa8, 0xcc, 0xdb, 0xa8, 0x21, 0x2b, 0xa6, 0xb5, 0x66, 0x3b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, - 0x71, 0xc4, 0x3e, 0x79, 0xc4, 0xc6, 0xdb, 0xdb, 0x0f, 0x9c, 0xa1, 0x63, 0xf2, 0x00, 0x81, 0x42, 0x64, 0x5e, 0xba, - 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xca, 0x7f, 0x66, 0xd7, 0xfa, 0xd0, 0xd8, 0x27, 0xc2, 0xd7, 0xd9, 0xda, - 0xed, 0xd8, 0x87, 0x50, 0xa8, 0x22, 0x5f, 0x48, 0x1d, 0xcc, 0x5c, 0xbc, 0xa9, 0x0c, 0x6e, 0x7a, 0xfb, 0x28, 0x09, - 0x30, 0x39, 0x1b, 0xfd, 0x44, 0xad, 0x08, 0x3e, 0x7b, 0x44, 0xf8, 0x62, 0xbb, 0x2d, 0xa2, 0xe0, 0xca, 0x68, 0xc6, - 0xbb, 0x8c, 0x7e, 0x72, 0xa3, 0xc5, 0x2f, 0xd3, 0xb2, 0x3c, 0x7b, 0x6a, 0x3b, 0x85, 0xf6, 0x71, 0x10, 0xbb, 0x22, - 0x68, 0x6b, 0x63, 0x41, 0x90, 0x35, 0x75, 0xd9, 0xa4, 0x22, 0xc5, 0x6f, 0xad, 0x93, 0xce, 0xeb, 0xc4, 0x33, 0xdb, - 0xe5, 0x3e, 0x24, 0x62, 0x04, 0x6e, 0x8b, 0x6e, 0xb7, 0x41, 0x54, 0x70, 0xe9, 0xe8, 0x64, 0x82, 0x47, 0x5d, 0xe2, - 0xa4, 0xda, 0xf5, 0x76, 0xdc, 0xfe, 0xd9, 0x1c, 0xf6, 0x03, 0x50, 0xe9, 0x3a, 0xd0, 0x7f, 0x4b, 0xaf, 0x64, 0x8e, - 0x3d, 0xec, 0xcd, 0x41, 0x73, 0x0b, 0xf4, 0x53, 0xb5, 0x89, 0xa2, 0xee, 0x0b, 0xfa, 0xcc, 0x38, 0xfe, 0x2f, 0x55, - 0x56, 0x30, 0x14, 0x26, 0x33, 0xd1, 0xac, 0xb6, 0x20, 0x9d, 0x85, 0x41, 0xed, 0x87, 0xb7, 0x1a, 0x39, 0x60, 0x8b, - 0x79, 0xc4, 0xa1, 0x1e, 0x34, 0x82, 0x97, 0x50, 0x20, 0xcc, 0xbd, 0x33, 0x34, 0x06, 0x3d, 0x28, 0x0f, 0x90, 0x81, - 0x62, 0xd0, 0xb2, 0x14, 0x1a, 0xda, 0x84, 0x54, 0xbb, 0xdf, 0x1f, 0xbd, 0x3e, 0xf4, 0x7b, 0x35, 0x8a, 0x68, 0xd4, - 0x3b, 0x07, 0x09, 0x28, 0x7a, 0xc5, 0x81, 0x0c, 0x94, 0x37, 0x4b, 0x62, 0xc4, 0x32, 0x1e, 0x07, 0xb9, 0x3a, 0x78, - 0xbc, 0x52, 0x72, 0x3c, 0x2b, 0x84, 0x1e, 0x03, 0x18, 0xd6, 0x3d, 0x70, 0x2f, 0xbb, 0x15, 0x2c, 0x02, 0x9e, 0xd5, - 0x2b, 0xea, 0xd9, 0x6a, 0x3e, 0xd4, 0xbf, 0x97, 0x17, 0xef, 0xb7, 0xb4, 0x9f, 0x4a, 0xec, 0xb1, 0xac, 0xa9, 0x02, - 0x1f, 0xfe, 0xfc, 0x29, 0xf3, 0xb1, 0x58, 0xa4, 0x4f, 0x9f, 0x5c, 0xc3, 0x09, 0xd1, 0x75, 0xc9, 0xbf, 0x70, 0x71, - 0x6c, 0x53, 0x40, 0x0d, 0xa7, 0x61, 0xe7, 0x8a, 0xf0, 0x38, 0x61, 0x0d, 0x17, 0x45, 0x38, 0xec, 0xe0, 0x60, 0x23, - 0x8c, 0x6e, 0xa8, 0x21, 0x96, 0xf4, 0x4e, 0x7c, 0x3b, 0xc0, 0x25, 0xf8, 0x79, 0xa1, 0x97, 0x49, 0x80, 0xf8, 0x63, - 0x8b, 0xc1, 0x04, 0xb9, 0xc4, 0xda, 0x6c, 0xca, 0x6e, 0xf5, 0x5e, 0x6b, 0xda, 0x79, 0x9a, 0x6e, 0xee, 0xad, 0xd9, - 0x9c, 0xa8, 0x3c, 0x70, 0x92, 0x51, 0x5c, 0x90, 0x1e, 0xd5, 0x33, 0xf9, 0x2f, 0x8e, 0x13, 0x40, 0x66, 0xf1, 0xe0, - 0x5e, 0x09, 0x8c, 0xed, 0x2b, 0x5d, 0x8b, 0xf8, 0x97, 0xc8, 0xf8, 0xd9, 0x68, 0xc6, 0xec, 0x15, 0x96, 0x5c, 0x6d, - 0xa8, 0x0d, 0x07, 0xcc, 0x45, 0x2f, 0x15, 0x9d, 0x63, 0x8c, 0x5a, 0xd8, 0x8c, 0x5f, 0x8c, 0xdd, 0x42, 0xa4, 0x51, - 0x8d, 0xd9, 0xf6, 0x6b, 0x4b, 0x74, 0xdf, 0xe3, 0x89, 0x24, 0x68, 0x5e, 0x12, 0x50, 0x80, 0x5d, 0x4c, 0x30, 0x24, - 0xd7, 0x30, 0x8c, 0x69, 0x86, 0xe7, 0x29, 0xd4, 0xb5, 0x9e, 0x1a, 0x95, 0x97, 0xba, 0xcb, 0xda, 0x5c, 0xb6, 0x9b, - 0x3c, 0xee, 0x51, 0x90, 0x38, 0x6a, 0x9c, 0xa1, 0x61, 0x56, 0x3d, 0x43, 0xca, 0xb0, 0x84, 0x48, 0x2b, 0x2e, 0xf2, - 0xb6, 0x76, 0x99, 0xc2, 0x40, 0xde, 0x89, 0x6e, 0x3a, 0xa7, 0x42, 0x04, 0xbb, 0x8b, 0x8a, 0x84, 0x4d, 0xdb, 0xb2, - 0x89, 0x16, 0x3a, 0xf7, 0x6d, 0x28, 0x74, 0x09, 0xf1, 0x43, 0xb6, 0x17, 0xee, 0x5e, 0x22, 0xf6, 0x10, 0xc6, 0xe6, - 0x88, 0x2d, 0x3e, 0xea, 0x25, 0xad, 0x97, 0x43, 0x42, 0x70, 0xb6, 0x59, 0xfa, 0xfc, 0x77, 0x6c, 0xe8, 0xca, 0xcb, - 0x0d, 0x8d, 0xca, 0x8e, 0xae, 0xaf, 0xae, 0x5a, 0x25, 0x16, 0xa9, 0xc6, 0x1c, 0x72, 0xe2, 0xa1, 0x45, 0xe7, 0x01, - 0x6d, 0xe2, 0xac, 0x9c, 0x11, 0x92, 0x3b, 0x6b, 0x51, 0xe8, 0x1a, 0xec, 0xbd, 0x0b, 0x00, 0x3b, 0x36, 0x99, 0xea, - 0xc5, 0xca, 0x53, 0x92, 0x60, 0xe8, 0x56, 0xe8, 0x9d, 0xaf, 0x72, 0x07, 0x0a, 0x31, 0xac, 0x03, 0x2c, 0x9c, 0x95, - 0xcc, 0x09, 0xdb, 0x87, 0xf5, 0xf8, 0x31, 0xaa, 0x2d, 0x60, 0x7c, 0x08, 0xa1, 0xbe, 0xb7, 0x71, 0x1b, 0x8a, 0x8e, - 0xce, 0x68, 0x72, 0x97, 0x13, 0x64, 0xd0, 0x77, 0xae, 0x94, 0x4c, 0xf1, 0x84, 0xbc, 0x9c, 0x39, 0x52, 0xa8, 0xf2, - 0xa6, 0x55, 0xfa, 0x62, 0xfb, 0xf6, 0x4b, 0x1f, 0x61, 0x5d, 0x23, 0x2e, 0x15, 0x63, 0x3d, 0x20, 0xfb, 0xee, 0x28, - 0x5a, 0xd3, 0x5e, 0x3c, 0x5d, 0x11, 0xcf, 0xf1, 0x26, 0x1c, 0xe1, 0x4f, 0x9f, 0xaf, 0xab, 0xd5, 0x79, 0x40, 0xb9, - 0xf7, 0x66, 0xc1, 0x31, 0xea, 0x1d, 0x97, 0x88, 0x60, 0xd2, 0x39, 0xdd, 0x69, 0x33, 0xa8, 0x26, 0x22, 0x33, 0x7c, - 0xb8, 0xf4, 0xdb, 0xfd, 0xaf, 0x20, 0x58, 0x77, 0x11, 0x2e, 0xdc, 0xd2, 0x20, 0x0e, 0x59, 0x8a, 0x90, 0x76, 0x45, - 0x30, 0xd2, 0x51, 0x41, 0x6c, 0xc5, 0x4e, 0x8a, 0x3c, 0x5f, 0x43, 0x20, 0xe2, 0x1c, 0x5c, 0x3e, 0xb3, 0x0a, 0x2f, - 0xaa, 0xd7, 0x3f, 0x37, 0x48, 0xe9, 0xb2, 0x3a, 0xe8, 0x7f, 0x9d, 0x2c, 0xfc, 0xe4, 0xe0, 0xc0, 0xcb, 0xc8, 0xda, - 0xda, 0xec, 0xb4, 0xa9, 0xde, 0x0a, 0x76, 0xdc, 0xce, 0xf5, 0xbe, 0x7e, 0x03, 0x4a, 0xa3, 0xad, 0xa8, 0xd9, 0x6d, - 0xca, 0x4c, 0x8d, 0xe1, 0x31, 0xab, 0x45, 0x03, 0x5c, 0xb8, 0xc3, 0xfe, 0x64, 0xc0, 0xde, 0xc1, 0x54, 0xf4, 0xbc, - 0x6f, 0xff, 0xec, 0x64, 0x86, 0x84, 0xe9, 0x84, 0x43, 0xee, 0xc0, 0x67, 0x4c, 0x4f, 0x27, 0x7d, 0x2f, 0x10, 0xbf, - 0x8a, 0x24, 0x9b, 0xf0, 0xb7, 0x0a, 0xef, 0x69, 0x64, 0x6c, 0x09, 0x19, 0xdd, 0x16, 0x95, 0x22, 0x52, 0x4b, 0x83, - 0x81, 0x31, 0x8a, 0xf9, 0x94, 0x68, 0x26, 0x96, 0xdd, 0x61, 0x43, 0x62, 0x9f, 0xed, 0x39, 0x7b, 0xbb, 0x98, 0x4d, - 0x09, 0x5a, 0x56, 0x7b, 0xf1, 0x6a, 0x6d, 0xde, 0x2b, 0x8f, 0xae, 0x8f, 0x1b, 0x18, 0xb1, 0x3f, 0xb7, 0xda, 0x5b, - 0xe0, 0x41, 0x07, 0xfc, 0xf3, 0x9d, 0xe2, 0xc5, 0xad, 0xf2, 0x25, 0x04, 0x3f, 0x64, 0x9a, 0x2c, 0x81, 0x32, 0xc8, - 0xc5, 0x96, 0x0b, 0x1e, 0x48, 0x15, 0xb5, 0xdd, 0x7a, 0x8c, 0xd8, 0x3c, 0x9f, 0x7c, 0xda, 0xc1, 0xf0, 0x4c, 0x41, - 0x07, 0xfb, 0x97, 0xed, 0xfd, 0x06, 0x68, 0xdd, 0x64, 0xc8, 0xbf, 0x6b, 0xdd, 0x04, 0x19, 0xc1, 0xc7, 0xaf, 0xb6, - 0xbf, 0xb0, 0xe6, 0xd3, 0xd4, 0x76, 0x8c, 0x96, 0x41, 0xb7, 0xfc, 0x5d, 0x72, 0x0a, 0x71, 0x5d, 0xed, 0x01, 0x7c, - 0xba, 0x8c, 0x01, 0x5f, 0xa2, 0x6f, 0x90, 0x1a, 0x40, 0xe4, 0xb7, 0x1f, 0xf5, 0xe3, 0xa7, 0xe6, 0x66, 0xf5, 0x43, - 0xc7, 0x86, 0x12, 0x31, 0x38, 0xac, 0x42, 0xb6, 0xe3, 0x00, 0xa0, 0xe2, 0x61, 0xe5, 0x88, 0x0e, 0x9a, 0x0f, 0x05, - 0xfb, 0x14, 0x0f, 0x3b, 0x07, 0x5f, 0xd7, 0x45, 0x91, 0x35, 0xa2, 0x24, 0x07, 0x4b, 0x25, 0xdd, 0x2f, 0x8e, 0xd2, - 0x0c, 0xaa, 0xf6, 0x04, 0x71, 0x15, 0x01, 0xc4, 0x63, 0x30, 0xba, 0xaf, 0x4b, 0xbf, 0xe7, 0x8a, 0x05, 0xe0, 0xe7, - 0x14, 0x6e, 0x63, 0x9e, 0x8f, 0x29, 0x80, 0xa0, 0xcf, 0x86, 0x06, 0x73, 0x88, 0x48, 0xc6, 0xe9, 0xec, 0x5a, 0x8c, - 0xf2, 0x32, 0xf2, 0xed, 0x88, 0xad, 0x22, 0x7f, 0xc7, 0x2a, 0x2f, 0x2e, 0xee, 0x85, 0x64, 0x17, 0xab, 0x74, 0x06, - 0x91, 0xda, 0x85, 0x99, 0x8c, 0x46, 0x47, 0xa6, 0xe9, 0x04, 0xd1, 0x5e, 0x2a, 0xa4, 0x64, 0x18, 0xe5, 0x18, 0xc5, - 0x22, 0x8e, 0x9c, 0x83, 0x93, 0x25, 0x0c, 0xc3, 0x92, 0xe0, 0xbf, 0x69, 0x40, 0xd0, 0x2b, 0x95, 0x14, 0xec, 0xa2, - 0x84, 0xb7, 0x43, 0x06, 0x0d, 0x80, 0xa5, 0xc6, 0x3b, 0x24, 0x4f, 0x35, 0xaa, 0x93, 0x73, 0xad, 0xc8, 0x70, 0x2a, - 0x75, 0x21, 0x3b, 0xc6, 0x13, 0x02, 0x89, 0x71, 0xde, 0xf9, 0x3c, 0x0f, 0x1a, 0x20, 0xf6, 0x64, 0x6a, 0x8d, 0xf4, - 0xbc, 0x62, 0x0f, 0x66, 0x5b, 0xda, 0x86, 0x46, 0x33, 0x07, 0x46, 0x02, 0x9b, 0x3f, 0x30, 0x53, 0x15, 0x53, 0xf3, - 0xc8, 0x31, 0x08, 0x43, 0x68, 0xbd, 0x95, 0xd5, 0x01, 0x21, 0xb4, 0x3c, 0x29, 0x93, 0x0c, 0xe2, 0xda, 0xf8, 0x30, - 0xea, 0x1a, 0x1f, 0x34, 0x12, 0xa0, 0x35, 0x73, 0xb5, 0xc5, 0xc7, 0xb3, 0x85, 0xc2, 0x19, 0x4b, 0x46, 0x7f, 0xb6, - 0x35, 0xb5, 0x92, 0xee, 0xe6, 0xee, 0xaf, 0xb0, 0xe5, 0xeb, 0xe4, 0x22, 0xdd, 0x2e, 0x65, 0x5b, 0x50, 0x1e, 0x68, - 0xb7, 0x9b, 0x59, 0xff, 0xfc, 0x37, 0x1f, 0x3f, 0x22, 0x74, 0x91, 0xb0, 0x0b, 0xc9, 0x2d, 0xea, 0xf8, 0x8b, 0x8f, - 0x86, 0x27, 0x63, 0xd8, 0xee, 0x0c, 0xcc, 0x1d, 0xe6, 0x39, 0x86, 0xbd, 0xc7, 0xc7, 0x31, 0x0c, 0x10, 0x93, 0xaf, - 0xa6, 0x0a, 0x13, 0x79, 0x87, 0x81, 0xca, 0x55, 0xaf, 0x1d, 0x20, 0x22, 0xce, 0xd4, 0x3e, 0x89, 0xe6, 0x9f, 0xa9, - 0xc8, 0xfb, 0x67, 0xdb, 0x13, 0x92, 0x20, 0x5f, 0xcf, 0x9a, 0xb8, 0x8e, 0x29, 0xf0, 0x00, 0xdb, 0x97, 0x58, 0x34, - 0x76, 0x97, 0x84, 0xd0, 0x42, 0x17, 0xa1, 0xa4, 0xc1, 0x87, 0x50, 0xf5, 0x6a, 0x95, 0x6c, 0x98, 0x0a, 0x0b, 0xbc, - 0xf8, 0xf4, 0x70, 0x0c, 0xef, 0x8f, 0x07, 0xca, 0x05, 0x85, 0x5c, 0x4e, 0xf0, 0x21, 0x6e, 0x1a, 0x7b, 0x06, 0x52, - 0x90, 0xf6, 0x4d, 0xe1, 0x9a, 0x9f, 0x8c, 0xac, 0x0b, 0x1d, 0x59, 0x4e, 0x4e, 0x4c, 0xf6, 0x24, 0xfc, 0x8b, 0x92, - 0x19, 0x92, 0xbc, 0x1c, 0x9c, 0xda, 0xc0, 0xd7, 0x2e, 0xe9, 0x28, 0xd7, 0xa2, 0x6d, 0xc3, 0xaf, 0x15, 0x27, 0xe8, - 0x94, 0x43, 0x37, 0xc1, 0xcb, 0x5e, 0x7d, 0x4e, 0xcd, 0x8d, 0xef, 0x95, 0xb7, 0x8b, 0xfb, 0xd7, 0xab, 0x01, 0x0e, - 0xbe, 0x40, 0x8e, 0xf7, 0xcc, 0x28, 0xce, 0xbf, 0x1d, 0xc6, 0xab, 0xe5, 0x98, 0x21, 0x30, 0x81, 0x84, 0x4c, 0x23, - 0x62, 0x1b, 0x4e, 0xf0, 0xf1, 0x43, 0x9d, 0xa3, 0x92, 0xd0, 0xd2, 0x8a, 0x83, 0xe3, 0x5c, 0x7f, 0x1b, 0x65, 0x48, - 0x29, 0xcb, 0xa5, 0x8c, 0x30, 0xc4, 0xc4, 0x01, 0x39, 0xdb, 0x95, 0xef, 0xc5, 0xe7, 0xcc, 0x33, 0x0d, 0xa4, 0x77, - 0xf1, 0x80, 0x16, 0x19, 0xf5, 0x07, 0x85, 0x1a, 0x44, 0x9a, 0x18, 0x7c, 0x46, 0x49, 0x20, 0x31, 0xc6, 0x46, 0x08, - 0x94, 0x90, 0x63, 0xeb, 0x07, 0x8b, 0x2a, 0x4c, 0x84, 0x22, 0x80, 0x96, 0x68, 0x79, 0x24, 0x28, 0xc8, 0x0c, 0x69, - 0xa4, 0xc7, 0xdc, 0x2d, 0x1d, 0x98, 0x16, 0x60, 0x4a, 0xc5, 0x23, 0x80, 0x7c, 0x32, 0x86, 0xa9, 0x88, 0x60, 0x70, - 0x57, 0x5e, 0x26, 0x0d, 0x1d, 0xd6, 0x30, 0x17, 0xcd, 0xc5, 0x94, 0x79, 0x19, 0x85, 0x72, 0x82, 0xc9, 0x55, 0x3b, - 0x21, 0xee, 0x0c, 0xa6, 0x75, 0x17, 0xf3, 0x79, 0x80, 0xd0, 0xf6, 0xd6, 0xd9, 0x14, 0x28, 0x33, 0x92, 0xd8, 0x04, - 0x11, 0x91, 0x0c, 0x76, 0x20, 0x0d, 0x45, 0x22, 0x24, 0x84, 0x4a, 0x52, 0xd0, 0x3a, 0x99, 0x13, 0x11, 0x9f, 0x56, - 0x58, 0xec, 0x83, 0xb4, 0x58, 0x22, 0x9b, 0xf7, 0xad, 0x32, 0xcc, 0x0f, 0x04, 0x85, 0x15, 0x8b, 0xac, 0x0a, 0x16, - 0x21, 0x91, 0xb0, 0x7a, 0x9d, 0x30, 0x76, 0x5e, 0x5f, 0x7c, 0x9a, 0x08, 0x4a, 0x9c, 0xd0, 0x91, 0x60, 0x1c, 0xab, - 0xa2, 0x58, 0xc9, 0x9f, 0x14, 0x39, 0xac, 0xd8, 0xf0, 0xe5, 0x55, 0xe9, 0x26, 0x91, 0x7c, 0xc7, 0xae, 0xfa, 0x95, - 0xb0, 0xfb, 0xa1, 0x9e, 0x38, 0xab, 0x44, 0x72, 0x8a, 0x6a, 0xab, 0xfb, 0x4f, 0xcf, 0x57, 0x95, 0x44, 0x79, 0xa1, - 0xa4, 0x0c, 0x7a, 0x8f, 0xdb, 0x62, 0x2f, 0x28, 0x36, 0x69, 0x76, 0xcc, 0xb7, 0xbd, 0x4a, 0xe4, 0x55, 0xc1, 0x94, - 0x2e, 0xc4, 0x12, 0x10, 0x37, 0x83, 0x65, 0x28, 0x6d, 0xcc, 0xf9, 0x07, 0x08, 0x7d, 0xf5, 0x3e, 0x2a, 0xb3, 0x1f, - 0xfd, 0x60, 0x05, 0x4d, 0x5c, 0x3f, 0xb3, 0xe6, 0x7a, 0x93, 0x46, 0x24, 0x30, 0xce, 0x42, 0x2f, 0xc5, 0xbe, 0x1a, - 0x97, 0x33, 0x57, 0x9a, 0x3d, 0xde, 0x8c, 0x56, 0x20, 0x76, 0x95, 0x86, 0x1d, 0x71, 0x3c, 0x07, 0x80, 0x74, 0x1e, - 0x85, 0x23, 0xa9, 0x14, 0xde, 0x6b, 0x81, 0xeb, 0x86, 0x68, 0x4b, 0x3d, 0x1f, 0x19, 0x80, 0x73, 0xb2, 0xc8, 0x4a, - 0xde, 0x84, 0x8c, 0xc4, 0xbf, 0x3c, 0xf3, 0x98, 0x31, 0xf6, 0x5e, 0x55, 0x18, 0x21, 0xcd, 0xaf, 0x5e, 0xa8, 0xb8, - 0x60, 0x63, 0x35, 0x9f, 0x96, 0xa7, 0x3c, 0x90, 0x2a, 0x9f, 0xaf, 0xb4, 0xa9, 0x1f, 0x39, 0x1f, 0x89, 0xb9, 0xb9, - 0x99, 0x93, 0x7a, 0x60, 0x10, 0xb1, 0x71, 0x9f, 0x20, 0xf2, 0x48, 0xf1, 0x67, 0x45, 0x2e, 0xd2, 0x61, 0x05, 0x56, - 0x0a, 0x01, 0x0b, 0x0d, 0x90, 0x56, 0xde, 0x4f, 0xb0, 0xe5, 0xd7, 0x24, 0x1a, 0x52, 0x2f, 0x99, 0x0d, 0xa8, 0x06, - 0xf1, 0x7b, 0x27, 0x9b, 0xcd, 0x9d, 0x9c, 0xce, 0xb7, 0x27, 0x6b, 0x86, 0xc8, 0x11, 0x74, 0xf4, 0xeb, 0xfe, 0x8e, - 0xbd, 0x20, 0x6d, 0x3a, 0x3b, 0xd9, 0x5a, 0x1f, 0x5e, 0x01, 0x93, 0x4e, 0xc5, 0x48, 0x93, 0x1a, 0x95, 0xb0, 0xcc, - 0x94, 0x4d, 0x29, 0xd1, 0x15, 0xd8, 0x4a, 0xc9, 0xc1, 0x96, 0x24, 0x9f, 0x79, 0xf8, 0x98, 0x74, 0xd7, 0x08, 0x17, - 0xe0, 0x18, 0x78, 0x2f, 0x83, 0xd2, 0x79, 0x60, 0xf4, 0x62, 0x10, 0xf3, 0x24, 0x84, 0x37, 0x5c, 0x96, 0xbc, 0x6c, - 0xed, 0xc9, 0x8a, 0x1a, 0xab, 0x6f, 0xdf, 0x7c, 0x3b, 0xe8, 0xca, 0xac, 0xd9, 0xc9, 0xef, 0xe7, 0x26, 0x5f, 0x77, - 0xcd, 0xf7, 0xbc, 0x6d, 0x7f, 0xc7, 0xb5, 0xcb, 0x37, 0x38, 0x2e, 0x18, 0x05, 0x3b, 0x5d, 0xac, 0x4e, 0x1b, 0x74, - 0x5c, 0x2f, 0x61, 0x57, 0x66, 0x04, 0xb4, 0x7b, 0x5f, 0xeb, 0x7f, 0x07, 0x98, 0x99, 0x62, 0x1f, 0x09, 0x22, 0x59, - 0x89, 0x6a, 0xcf, 0xfc, 0x42, 0xed, 0x2f, 0x08, 0x05, 0xf3, 0x35, 0xc8, 0xa3, 0xb7, 0x43, 0xc2, 0x68, 0x99, 0x89, - 0x38, 0xc1, 0x86, 0x05, 0x8f, 0xae, 0xe7, 0x72, 0xb6, 0xc5, 0x0e, 0x8f, 0xad, 0xae, 0xda, 0xdc, 0xab, 0x14, 0xf9, - 0x88, 0xeb, 0xe3, 0x19, 0x7a, 0xdf, 0x99, 0x79, 0xd0, 0xd1, 0x85, 0x48, 0xd8, 0xe2, 0x3a, 0x7e, 0x60, 0xbe, 0x46, - 0xa1, 0x60, 0xae, 0x94, 0xb9, 0xbd, 0x45, 0xdd, 0x4f, 0x75, 0xcf, 0xc9, 0xee, 0xfb, 0x92, 0x6f, 0x7e, 0xa4, 0xbd, - 0x1f, 0x45, 0xb3, 0xc2, 0x13, 0x2b, 0x5c, 0x47, 0xcf, 0xe6, 0x37, 0x1f, 0x33, 0x45, 0x08, 0x61, 0x04, 0xfd, 0xc2, - 0xaf, 0x70, 0x2d, 0xf0, 0x46, 0x99, 0xb6, 0x61, 0x2f, 0xa9, 0xa5, 0x20, 0xae, 0x1d, 0x1e, 0xce, 0xd9, 0xad, 0x35, - 0x59, 0xec, 0x8e, 0xab, 0xbe, 0xd0, 0x28, 0x7f, 0x87, 0x4c, 0x3b, 0x7c, 0xf3, 0x0d, 0xb9, 0x61, 0xaf, 0xa6, 0x4f, - 0x46, 0x68, 0xe2, 0x4e, 0xbd, 0x7e, 0x0a, 0x24, 0xf3, 0x34, 0x01, 0xa2, 0x31, 0xfc, 0xdf, 0x25, 0x7b, 0x34, 0xa6, - 0x13, 0x36, 0xcc, 0x86, 0xac, 0x36, 0x60, 0xec, 0x21, 0x89, 0x1e, 0x7f, 0x45, 0xfe, 0xdf, 0x9a, 0x04, 0xc7, 0x4b, - 0x71, 0x9f, 0x1b, 0xfe, 0xb2, 0x0c, 0xb3, 0x9c, 0xc4, 0x2c, 0xb8, 0x65, 0xc5, 0xab, 0x20, 0x5c, 0xa6, 0x5d, 0x61, - 0x19, 0x96, 0x0b, 0x2c, 0x43, 0x59, 0x7d, 0x11, 0x49, 0x22, 0xed, 0x91, 0x98, 0x9d, 0xce, 0xde, 0x8b, 0x13, 0xb2, - 0xe3, 0x06, 0x4d, 0x8e, 0x2e, 0xb2, 0x31, 0x13, 0x45, 0xed, 0x41, 0x23, 0x83, 0x72, 0x35, 0x78, 0xb9, 0x86, 0x8e, - 0x0c, 0xe1, 0x6a, 0x54, 0xa1, 0x71, 0x21, 0x9d, 0x4f, 0x2f, 0x8f, 0x0c, 0x24, 0x19, 0x34, 0xc5, 0xb0, 0x23, 0x54, - 0xc5, 0xbc, 0x4e, 0xf5, 0x42, 0x6a, 0x85, 0x47, 0xf2, 0x28, 0xc3, 0xf2, 0xd2, 0x22, 0xa3, 0xdd, 0xbe, 0x72, 0x74, - 0x5d, 0x38, 0x8e, 0x9f, 0xc3, 0x64, 0xa1, 0x0e, 0xd7, 0x60, 0x20, 0xdd, 0x4f, 0x1f, 0x79, 0xe9, 0x7f, 0x34, 0x5d, - 0x0d, 0xed, 0xb3, 0x85, 0xf8, 0xea, 0x21, 0x23, 0x8e, 0xaf, 0x5e, 0x58, 0x84, 0xa3, 0xe5, 0x96, 0xe9, 0xe3, 0x98, - 0x6d, 0x1d, 0xaa, 0xdc, 0x1a, 0x8d, 0x67, 0xb5, 0x18, 0x3f, 0xba, 0x0a, 0x1a, 0x82, 0xa6, 0x24, 0x0b, 0xf7, 0x15, - 0x75, 0x41, 0x56, 0x30, 0x19, 0xac, 0xb0, 0xbc, 0x99, 0xdf, 0xa7, 0xb5, 0xa9, 0xb4, 0x7c, 0x24, 0xf8, 0x07, 0x0f, - 0xb1, 0xac, 0x4f, 0x85, 0xdd, 0x12, 0x17, 0x0f, 0x2c, 0xe4, 0x59, 0x2f, 0xdc, 0x68, 0xeb, 0x94, 0xab, 0x72, 0xd9, - 0x2d, 0x5d, 0x78, 0x55, 0xb7, 0xbc, 0x14, 0x82, 0xd7, 0x21, 0xc9, 0x49, 0x6e, 0x42, 0x2c, 0x06, 0x03, 0x6f, 0xe4, - 0xa4, 0xef, 0x14, 0x5c, 0xc8, 0x0d, 0x74, 0xa5, 0xaf, 0x13, 0x4b, 0x01, 0x05, 0xb0, 0x17, 0x1e, 0xd8, 0x78, 0x02, - 0x89, 0x3c, 0xbf, 0x5e, 0xd4, 0x89, 0x0e, 0x07, 0xbf, 0x9f, 0xaf, 0x14, 0x07, 0xf0, 0x5d, 0x82, 0x7c, 0x71, 0xde, - 0x48, 0xf0, 0x0f, 0xb0, 0xc3, 0xd9, 0xb9, 0xbf, 0xc1, 0x5c, 0xc2, 0x92, 0xec, 0x28, 0xe0, 0xb3, 0x02, 0xab, 0x9b, - 0x80, 0x8b, 0x04, 0xc1, 0x41, 0x5b, 0x2c, 0x17, 0x04, 0x87, 0x34, 0x0a, 0x15, 0xf3, 0x21, 0x3f, 0x37, 0x9b, 0x92, - 0x28, 0x92, 0xe1, 0xe7, 0xd7, 0xe0, 0x32, 0x23, 0x9c, 0xe2, 0x63, 0x4d, 0x95, 0x0f, 0x75, 0x5e, 0x8c, 0x74, 0x02, - 0x0c, 0x6f, 0xa6, 0x21, 0xda, 0x3f, 0x46, 0x8d, 0x92, 0xca, 0x3d, 0x0b, 0x97, 0xc6, 0xd9, 0x10, 0x2e, 0xf3, 0x6f, - 0xb2, 0xcc, 0x6b, 0x29, 0x96, 0x57, 0x36, 0x65, 0xc1, 0xf9, 0x1e, 0xd6, 0x71, 0xe4, 0xee, 0xb3, 0x5e, 0x59, 0x72, - 0x88, 0x76, 0xcb, 0x47, 0x67, 0x39, 0xa0, 0x57, 0x71, 0x75, 0xe3, 0x14, 0xc4, 0x91, 0x97, 0x97, 0x91, 0xca, 0x70, - 0x3c, 0x95, 0x04, 0x1c, 0xa9, 0xa7, 0xf8, 0xbf, 0x29, 0xe1, 0x1d, 0x04, 0x83, 0x30, 0x76, 0x0f, 0xf5, 0x2b, 0x40, - 0xd1, 0x16, 0x66, 0x07, 0x37, 0x25, 0x6e, 0xe2, 0xc0, 0x28, 0x47, 0x6f, 0x83, 0xf9, 0xd2, 0x12, 0xb4, 0xc2, 0x6a, - 0x46, 0xa0, 0xd5, 0xe7, 0x71, 0xaf, 0x08, 0xfc, 0xd4, 0x85, 0xe3, 0x79, 0x5e, 0x43, 0x77, 0x68, 0x1a, 0xcb, 0x33, - 0x69, 0x4b, 0xc2, 0x40, 0xd2, 0x2c, 0xb4, 0xf1, 0xe3, 0x73, 0x4d, 0x75, 0x3b, 0x8b, 0xe8, 0x7a, 0xbd, 0x0c, 0xa5, - 0x88, 0x58, 0xb4, 0x70, 0x34, 0x27, 0x1b, 0xd0, 0xe9, 0x3e, 0xd9, 0x98, 0x1a, 0x0e, 0x86, 0x90, 0x18, 0xb9, 0x0d, - 0xe3, 0x9c, 0xd8, 0xf0, 0x84, 0x2a, 0xd5, 0x13, 0x3f, 0x45, 0x5b, 0x89, 0xe0, 0x09, 0x95, 0x46, 0x1e, 0x78, 0x54, - 0xd1, 0x1a, 0x90, 0xc3, 0xc3, 0x47, 0xe0, 0x94, 0x6f, 0x30, 0x56, 0x47, 0x28, 0x50, 0x8e, 0x60, 0x4e, 0x91, 0x1f, - 0xee, 0xf0, 0x21, 0x7c, 0x2d, 0x4f, 0x30, 0x53, 0x6b, 0x2f, 0xc7, 0x5c, 0x0f, 0xb9, 0x1d, 0xf2, 0xb0, 0xff, 0xc4, - 0xcb, 0xc8, 0x46, 0x68, 0xf8, 0x91, 0x5f, 0xf5, 0x58, 0x7f, 0x3d, 0xc0, 0x7c, 0x3a, 0xd9, 0x83, 0x09, 0x67, 0x05, - 0x40, 0xfc, 0xd1, 0x55, 0x70, 0x37, 0x68, 0x58, 0x1f, 0x63, 0x12, 0x66, 0x27, 0x0e, 0x87, 0x6f, 0xa5, 0x02, 0x50, - 0x9e, 0x87, 0x19, 0x89, 0x2c, 0x24, 0xf3, 0xf3, 0x72, 0x8a, 0x6d, 0x51, 0xa6, 0xb6, 0xb4, 0x75, 0x0d, 0x38, 0x91, - 0xc5, 0xcd, 0x24, 0x79, 0x0a, 0x35, 0x2a, 0x22, 0x46, 0xc2, 0x2c, 0xd8, 0x7a, 0x99, 0xb0, 0xc7, 0x6f, 0x8c, 0x61, - 0xd4, 0xa6, 0x8d, 0xf4, 0x86, 0xbd, 0xea, 0x4f, 0xd6, 0xef, 0x11, 0x5b, 0x15, 0xe0, 0xbe, 0xa5, 0x1f, 0xa0, 0x48, - 0xe3, 0x96, 0x76, 0xf2, 0xd3, 0x89, 0x04, 0xfa, 0x87, 0x18, 0x36, 0x89, 0x0d, 0x0a, 0x8e, 0x2f, 0xb5, 0x29, 0xde, - 0x06, 0xce, 0x0c, 0xc5, 0x7a, 0xad, 0x67, 0xe0, 0x44, 0x1b, 0x41, 0x2a, 0x74, 0xcf, 0x58, 0x1e, 0x91, 0xa9, 0xf3, - 0x4f, 0x48, 0xcb, 0x16, 0xa6, 0x25, 0x9f, 0xe4, 0x74, 0x24, 0xd9, 0xf9, 0x29, 0x9a, 0xe4, 0x9d, 0xde, 0x25, 0x52, - 0x7c, 0x7d, 0x19, 0x66, 0x2f, 0xff, 0x84, 0x9a, 0x14, 0x22, 0x1d, 0x5c, 0xdd, 0x30, 0x31, 0xd4, 0x0a, 0x8c, 0xea, - 0x78, 0x9f, 0x8a, 0x4c, 0x1c, 0x0f, 0x6a, 0xe6, 0x45, 0x85, 0xc1, 0x13, 0x4b, 0x70, 0x94, 0xca, 0xae, 0xb6, 0xec, - 0x2d, 0x9c, 0x0c, 0x7e, 0x8a, 0x35, 0x49, 0xd5, 0xf1, 0x82, 0xb6, 0x6a, 0x68, 0x0e, 0x5d, 0x33, 0x6f, 0x66, 0xc7, - 0x63, 0xff, 0x2a, 0x61, 0xd1, 0xc0, 0x9a, 0x0e, 0x88, 0x5e, 0x07, 0xfd, 0x9c, 0x16, 0xdc, 0x2f, 0xbc, 0x0e, 0xbc, - 0x11, 0x83, 0x08, 0x0a, 0x66, 0x28, 0xf1, 0x79, 0xb5, 0x40, 0xc6, 0x86, 0x62, 0x92, 0x54, 0xd2, 0xb1, 0x71, 0x65, - 0x94, 0x8d, 0xcb, 0xf4, 0x72, 0xca, 0xdb, 0x2c, 0xe8, 0x21, 0x6f, 0xe5, 0x2b, 0x88, 0x93, 0xc6, 0x31, 0x22, 0x02, - 0x1c, 0x0f, 0x97, 0x39, 0x87, 0xbc, 0x59, 0x6c, 0x41, 0x4f, 0x09, 0xad, 0xc1, 0xcd, 0xce, 0x59, 0x4f, 0xf9, 0x52, - 0x3c, 0x5d, 0x14, 0x97, 0xdd, 0x6f, 0xa0, 0x00, 0x08, 0x03, 0xff, 0x23, 0x09, 0x7d, 0x56, 0x20, 0x63, 0x8e, 0x07, - 0xc9, 0x91, 0xe5, 0xb1, 0x96, 0x47, 0xa0, 0x85, 0x18, 0xa9, 0xde, 0x86, 0xbf, 0xf3, 0x29, 0x5e, 0x68, 0x07, 0x2b, - 0x77, 0x83, 0x20, 0x48, 0x70, 0x00, 0xfc, 0x85, 0xf7, 0xdd, 0xd0, 0x07, 0xef, 0xb7, 0x7b, 0x87, 0xff, 0xa7, 0x39, - 0xb3, 0x8f, 0x18, 0xdb, 0x7e, 0x88, 0x55, 0xdf, 0x25, 0xff, 0xf1, 0xd0, 0xd0, 0x06, 0xe8, 0xe1, 0x03, 0x1b, 0xce, - 0xde, 0xd3, 0x10, 0x6e, 0xdb, 0xa8, 0x02, 0x96, 0x14, 0x86, 0x48, 0x39, 0xa9, 0xa3, 0xfa, 0x22, 0x95, 0xdc, 0x24, - 0xfe, 0x3c, 0x33, 0x50, 0xfd, 0x83, 0x85, 0x5f, 0x83, 0x2f, 0xbb, 0x07, 0x05, 0x66, 0x62, 0x7d, 0x1a, 0x50, 0xaa, - 0xd4, 0x61, 0x7e, 0xf1, 0xd0, 0xfe, 0x1a, 0xb5, 0xab, 0x6c, 0x78, 0x7f, 0xd1, 0x95, 0x82, 0xb0, 0xc5, 0xe5, 0x21, - 0xd7, 0xe6, 0xde, 0x3e, 0xad, 0x5d, 0xed, 0x03, 0xef, 0x0a, 0x11, 0x60, 0xa7, 0xce, 0xe4, 0xe4, 0x19, 0x9f, 0x9a, - 0x40, 0xe7, 0xec, 0xde, 0xfe, 0x66, 0x03, 0x7e, 0x34, 0xc0, 0x76, 0x57, 0xf7, 0xf6, 0x01, 0x0c, 0xca, 0x65, 0xd4, - 0x50, 0x21, 0x31, 0xc4, 0x4b, 0x2a, 0x48, 0x39, 0x8a, 0xce, 0x87, 0xc8, 0x93, 0x43, 0x4c, 0x1b, 0x09, 0xae, 0xab, - 0xb4, 0x3d, 0x72, 0x12, 0xb4, 0x3c, 0xb2, 0x7b, 0x18, 0xb7, 0x51, 0x71, 0x5c, 0x64, 0x34, 0xf2, 0x0c, 0xee, 0x70, - 0xae, 0x23, 0xf4, 0x68, 0x55, 0x0a, 0x90, 0x26, 0x5c, 0x41, 0xfd, 0x3e, 0x9c, 0x8d, 0xb2, 0x87, 0xaa, 0xe5, 0xd8, - 0x4f, 0xe0, 0x35, 0x45, 0xef, 0xc8, 0x9f, 0x5b, 0x99, 0x15, 0xe1, 0xf2, 0xca, 0x62, 0xb2, 0x10, 0xcc, 0xd1, 0x36, - 0x6e, 0x99, 0x74, 0xf0, 0x0c, 0xf5, 0xfc, 0x50, 0xb5, 0x87, 0x15, 0x5f, 0x10, 0xc9, 0x34, 0xc5, 0x9d, 0xc3, 0xaf, - 0x63, 0x7e, 0x55, 0x38, 0x05, 0x72, 0x37, 0x1d, 0x26, 0xc2, 0x35, 0xdb, 0x4d, 0x90, 0x45, 0x9a, 0x0f, 0x15, 0xba, - 0x7d, 0xd6, 0x51, 0x9f, 0xb9, 0xc4, 0xa8, 0x3d, 0x4a, 0x66, 0x7c, 0xc2, 0x76, 0xbb, 0x91, 0x7e, 0xd1, 0xb5, 0x14, - 0x43, 0x24, 0x95, 0x29, 0xa5, 0x4b, 0x69, 0x89, 0x23, 0xb5, 0x0c, 0x65, 0x1c, 0x4a, 0xe8, 0x14, 0x40, 0xdb, 0x78, - 0xc8, 0x4c, 0x22, 0xed, 0x54, 0xfb, 0xac, 0xca, 0x64, 0x8f, 0xc5, 0x91, 0x30, 0x64, 0xe1, 0x99, 0x60, 0x7d, 0x7f, - 0xae, 0xf9, 0x92, 0x02, 0x55, 0x19, 0xac, 0x3b, 0x06, 0x7f, 0x2c, 0xb4, 0x79, 0x29, 0x2f, 0x85, 0x5e, 0x85, 0xa9, - 0x50, 0x5b, 0xbd, 0xb4, 0x4e, 0x1b, 0x42, 0x05, 0xb2, 0x76, 0x96, 0xe8, 0x51, 0x36, 0x38, 0xc8, 0xf1, 0xbf, 0x0d, - 0x22, 0xdb, 0x1e, 0x04, 0xdb, 0x7b, 0xa6, 0x22, 0xf5, 0xbd, 0xd5, 0x77, 0x9b, 0xf1, 0x89, 0x09, 0x81, 0xcb, 0x80, - 0xab, 0xce, 0xc7, 0x6e, 0x6c, 0xc3, 0x1f, 0x11, 0xe0, 0xef, 0x70, 0xe5, 0xa9, 0xf0, 0x55, 0xfa, 0x5a, 0xd9, 0xca, - 0x2b, 0xef, 0x39, 0x05, 0xb6, 0x6d, 0x7d, 0xa5, 0x09, 0x58, 0x31, 0xd0, 0x8b, 0x80, 0x6f, 0x73, 0xf2, 0x03, 0xf9, - 0xbc, 0x0b, 0xed, 0x99, 0x13, 0xb0, 0x19, 0xec, 0xc1, 0x8e, 0xdd, 0x8d, 0xd1, 0x28, 0x35, 0xe1, 0x57, 0xe6, 0xf6, - 0xa3, 0xaf, 0xa5, 0xff, 0xfc, 0x25, 0x86, 0xe8, 0x25, 0x30, 0x85, 0xf3, 0xd7, 0x11, 0xea, 0x0e, 0x59, 0x52, 0xda, - 0x91, 0x6a, 0x14, 0x5d, 0x54, 0x61, 0x5d, 0x0b, 0xb0, 0x42, 0x63, 0xf5, 0x8d, 0xe1, 0xb5, 0x92, 0x74, 0x14, 0x6b, - 0x2d, 0x86, 0xb7, 0xe9, 0xfc, 0xbe, 0x8a, 0x9d, 0x04, 0x2c, 0x60, 0xbe, 0x4e, 0x70, 0x17, 0x19, 0xec, 0x0e, 0xf7, - 0x6c, 0x3f, 0x27, 0x1a, 0x8e, 0x5c, 0x28, 0x80, 0x0a, 0x6f, 0x17, 0xd2, 0xa4, 0x5f, 0xe7, 0x3f, 0x57, 0xc5, 0x77, - 0x4c, 0x2d, 0x39, 0x4c, 0xf4, 0x52, 0xe3, 0x5f, 0xf7, 0xc6, 0x0f, 0xe5, 0xeb, 0xe5, 0x83, 0xbd, 0x10, 0x6e, 0x79, - 0x8e, 0x95, 0x15, 0x51, 0x0d, 0x71, 0x7f, 0xe8, 0x64, 0x46, 0xb9, 0x9b, 0x6b, 0x92, 0xd5, 0x49, 0x5a, 0x05, 0x4f, - 0x7d, 0x95, 0xf1, 0x67, 0x66, 0x94, 0x7b, 0x6e, 0x2c, 0x43, 0x89, 0x74, 0xe0, 0x8b, 0x86, 0xe6, 0x67, 0xa8, 0x8e, - 0x28, 0x9e, 0xab, 0x01, 0x1b, 0x40, 0x69, 0x5e, 0x0f, 0x03, 0x6b, 0x99, 0xba, 0x30, 0xaa, 0x36, 0xa2, 0xa0, 0x04, - 0x53, 0x48, 0x6b, 0x69, 0x4b, 0x2c, 0x50, 0x51, 0xb3, 0xa8, 0xb1, 0xd1, 0xcf, 0x74, 0x58, 0xe3, 0x66, 0x87, 0x7b, - 0x82, 0x19, 0x41, 0x50, 0x45, 0xb6, 0x3e, 0xb4, 0xaa, 0x46, 0x51, 0x3c, 0xf5, 0x73, 0x40, 0x41, 0xf9, 0x8f, 0x2b, - 0x5f, 0xda, 0xe2, 0xb8, 0x63, 0x35, 0xe0, 0x8b, 0xe2, 0xfd, 0x1e, 0xb9, 0x2a, 0x25, 0x36, 0x71, 0x93, 0x5b, 0x34, - 0x65, 0x04, 0xb1, 0xa7, 0x3f, 0x41, 0x95, 0x14, 0x29, 0x5d, 0xc4, 0x0d, 0xad, 0xb9, 0x38, 0x59, 0xa2, 0x0d, 0xf5, - 0xc0, 0xad, 0x6f, 0x64, 0x68, 0xa2, 0x57, 0xfb, 0xf2, 0x8d, 0x42, 0x0c, 0xc2, 0x92, 0x85, 0xbc, 0x62, 0x62, 0xcc, - 0x60, 0xe0, 0x48, 0xd1, 0xb6, 0x51, 0x2e, 0x46, 0x6f, 0xc4, 0x72, 0x75, 0x9c, 0xef, 0x64, 0x3b, 0x8a, 0x4a, 0x67, - 0xdc, 0x2b, 0xd0, 0xe6, 0xa7, 0x6d, 0xff, 0x86, 0xa7, 0xff, 0xa4, 0x26, 0x5c, 0x8f, 0xd0, 0xb3, 0x08, 0x9f, 0x7a, - 0x40, 0x2c, 0x8f, 0x81, 0x14, 0xa6, 0xe7, 0x2f, 0x52, 0x38, 0x46, 0xd2, 0x8d, 0x25, 0xb1, 0xe4, 0x39, 0x4e, 0xf1, - 0x3d, 0x75, 0xbe, 0xa4, 0x03, 0xea, 0xe8, 0xe4, 0x16, 0x12, 0x68, 0x9a, 0x09, 0xc9, 0xe6, 0x13, 0xda, 0xbc, 0x4c, - 0xcd, 0xba, 0x41, 0xf2, 0x96, 0xa7, 0x96, 0xef, 0x54, 0x2c, 0xe3, 0xfb, 0x21, 0x12, 0x42, 0xd6, 0x2b, 0x6a, 0x96, - 0xfc, 0x82, 0x94, 0xed, 0x02, 0xb4, 0x4b, 0x05, 0x61, 0x71, 0xf6, 0x9a, 0x98, 0xfb, 0x4a, 0xa5, 0x1f, 0xca, 0x6b, - 0xa4, 0x3d, 0x1c, 0x02, 0x00, 0xe3, 0x7e, 0x6f, 0xc2, 0xc4, 0xe8, 0x0c, 0x17, 0x4e, 0xd4, 0x52, 0x21, 0x09, 0xdb, - 0x24, 0x65, 0x76, 0x6f, 0xd6, 0xf1, 0xc3, 0x5f, 0x63, 0x38, 0x37, 0x5a, 0x2b, 0xe1, 0x36, 0xd0, 0x55, 0x67, 0xc8, - 0xab, 0x73, 0xc4, 0xde, 0xdc, 0x29, 0x7f, 0x2e, 0x07, 0xa1, 0xd2, 0x6a, 0x3e, 0x5b, 0x85, 0x5b, 0x30, 0x85, 0x27, - 0x5e, 0x13, 0x6c, 0x30, 0x2f, 0xe1, 0x25, 0xa0, 0xc6, 0x20, 0xe3, 0x23, 0x1f, 0x6c, 0x81, 0x95, 0xd5, 0xf8, 0x73, - 0xec, 0xdf, 0x87, 0xb9, 0xdb, 0xb3, 0x68, 0xe3, 0x7a, 0x31, 0x7d, 0x40, 0x49, 0x26, 0x9c, 0x76, 0xb7, 0x60, 0xdd, - 0xd0, 0x4e, 0x4c, 0xa1, 0x51, 0x31, 0x37, 0x20, 0x75, 0xec, 0xc6, 0xa1, 0xb6, 0xa3, 0xf5, 0xe6, 0x23, 0x8a, 0x06, - 0x71, 0x8e, 0xc8, 0xd6, 0x66, 0xbd, 0xb6, 0xb4, 0x5b, 0x18, 0x40, 0x29, 0x58, 0x4e, 0x09, 0xce, 0xbb, 0x72, 0xd1, - 0x2e, 0x0a, 0xb3, 0x05, 0x90, 0xd2, 0x0d, 0x64, 0xc8, 0x23, 0xea, 0x35, 0x99, 0x63, 0xb7, 0xf4, 0xf8, 0xd9, 0x40, - 0xec, 0x47, 0xbf, 0x24, 0xe3, 0xcc, 0xc0, 0xa4, 0xbd, 0x2f, 0x29, 0x79, 0xa2, 0x9c, 0xbc, 0x6a, 0xe4, 0x30, 0x6c, - 0xe9, 0x1d, 0xcb, 0xc3, 0x8c, 0x1e, 0x82, 0x04, 0x99, 0xf7, 0x8e, 0xe9, 0x12, 0x21, 0xbe, 0x87, 0x85, 0x80, 0x69, - 0xb4, 0xfe, 0xb7, 0xda, 0xe5, 0x53, 0x9f, 0xe7, 0x36, 0xed, 0xad, 0x3b, 0x74, 0xc5, 0x95, 0x4b, 0x6e, 0xfd, 0xa8, - 0x9e, 0xa9, 0xda, 0xa9, 0x7c, 0x6f, 0xb5, 0xec, 0xeb, 0x1c, 0xa4, 0xa1, 0x3d, 0xf2, 0x41, 0xbb, 0xd8, 0x58, 0xb6, - 0xa6, 0x59, 0x34, 0xb3, 0x68, 0xe3, 0x58, 0xd9, 0xc5, 0xb7, 0xc4, 0x23, 0x71, 0xc1, 0xdc, 0xc6, 0xa3, 0x32, 0x12, - 0x3b, 0x3c, 0xa2, 0x2d, 0x7c, 0x23, 0xb4, 0x6d, 0x98, 0x8b, 0x8f, 0x13, 0x70, 0xac, 0x2d, 0x9f, 0x96, 0x63, 0x66, - 0xb5, 0x88, 0x32, 0x59, 0x01, 0x8c, 0x8b, 0xda, 0x71, 0x6f, 0x82, 0xa1, 0x0e, 0xc9, 0xc5, 0x1a, 0x84, 0x30, 0xbd, - 0x16, 0xea, 0xcc, 0xab, 0xfc, 0x8a, 0x6c, 0x6d, 0x2c, 0xc2, 0x42, 0xcb, 0xc6, 0xcc, 0x64, 0x4d, 0x0b, 0x60, 0x8d, - 0xa0, 0xd7, 0x6b, 0xb8, 0x7b, 0x6e, 0xa9, 0xfc, 0x19, 0x1c, 0xb9, 0xf8, 0x18, 0xcc, 0xc7, 0x5e, 0xa5, 0xa4, 0xa9, - 0x87, 0xcf, 0x13, 0xcd, 0x08, 0x8e, 0x5b, 0xe5, 0x0d, 0xb5, 0x67, 0xc3, 0xff, 0x81, 0xaf, 0xe1, 0x73, 0x4e, 0x6e, - 0x85, 0x71, 0x70, 0x66, 0xed, 0x8b, 0x77, 0x75, 0x8c, 0x98, 0x45, 0x8c, 0xf1, 0x25, 0x6b, 0x4a, 0xb9, 0xf9, 0x2c, - 0xd6, 0x47, 0x50, 0x04, 0x96, 0xaf, 0x31, 0x19, 0x21, 0x1c, 0x2c, 0x6e, 0x34, 0x19, 0x62, 0x03, 0xdd, 0x9b, 0x7b, - 0x40, 0x0c, 0x06, 0xe0, 0x21, 0xce, 0x05, 0x59, 0xe8, 0x00, 0xb2, 0xfc, 0x01, 0x12, 0x08, 0x49, 0x60, 0x81, 0x22, - 0x21, 0x23, 0xaf, 0x5a, 0x87, 0x9a, 0x97, 0xb3, 0xcb, 0x0c, 0x17, 0x10, 0x0c, 0x5b, 0xb9, 0x4b, 0xab, 0x51, 0x9b, - 0xed, 0x2d, 0x96, 0x81, 0xde, 0x9e, 0x35, 0x95, 0xa4, 0x48, 0xf9, 0xb5, 0xe9, 0x18, 0xff, 0x78, 0xc8, 0x56, 0x74, - 0xae, 0x18, 0xc3, 0xfd, 0x48, 0x9e, 0xdd, 0xf9, 0xcb, 0xc2, 0x72, 0xb1, 0x1e, 0x4a, 0x3d, 0x34, 0x66, 0x17, 0x0b, - 0x1d, 0xb6, 0x45, 0xc3, 0x22, 0x52, 0xff, 0x24, 0xbc, 0x1e, 0xdc, 0xa3, 0xa8, 0x9c, 0x4c, 0xf0, 0x84, 0xda, 0xb9, - 0xb4, 0x6e, 0x04, 0xde, 0xa5, 0x3c, 0x9f, 0xa6, 0x60, 0x4b, 0xe3, 0x52, 0xa1, 0x94, 0x9d, 0x19, 0xd3, 0xa8, 0x93, - 0xf3, 0xd2, 0x1a, 0xeb, 0x36, 0x69, 0xc1, 0x18, 0x07, 0xa1, 0xfe, 0x74, 0xd6, 0x6f, 0xfe, 0x2d, 0x3f, 0x13, 0x52, - 0x39, 0x97, 0xdc, 0x3f, 0x64, 0x5a, 0xd5, 0xd4, 0x12, 0x68, 0x26, 0xd0, 0x0c, 0x7e, 0x2d, 0x90, 0xcf, 0x43, 0xb8, - 0x67, 0xfa, 0x2c, 0xc4, 0xfd, 0x20, 0x26, 0x1c, 0xb4, 0xf1, 0x86, 0x5e, 0xa3, 0x44, 0xea, 0xbf, 0x25, 0x03, 0x3a, - 0xb9, 0xc5, 0x42, 0xa9, 0x25, 0x89, 0xf3, 0xb5, 0x48, 0x75, 0xe7, 0xfb, 0xb8, 0x8e, 0x72, 0x41, 0x94, 0x74, 0xae, - 0x03, 0xdc, 0x27, 0x94, 0x73, 0x5a, 0x23, 0x6a, 0x24, 0xac, 0xd9, 0x4a, 0xe1, 0xd7, 0xe0, 0x41, 0x20, 0x3a, 0x80, - 0x84, 0xfd, 0xe1, 0xd5, 0xf6, 0x9a, 0xd9, 0xf9, 0xa0, 0x90, 0x05, 0xe2, 0x52, 0xb7, 0xdd, 0x62, 0x27, 0x21, 0x00, - 0xd1, 0x6d, 0x12, 0x0c, 0x14, 0xd4, 0x8e, 0xd3, 0x6f, 0xd0, 0xd0, 0x3b, 0xad, 0xec, 0xdd, 0xdd, 0x84, 0xa2, 0x08, - 0x21, 0x01, 0x12, 0x7b, 0xa0, 0xd2, 0x50, 0x10, 0x45, 0xcb, 0x41, 0x44, 0x28, 0xb1, 0xfb, 0xb8, 0x17, 0xa2, 0x82, - 0x1b, 0xe9, 0x88, 0x34, 0x62, 0xe8, 0x15, 0x6c, 0x88, 0x80, 0x40, 0x95, 0x87, 0x91, 0xc6, 0x2f, 0x09, 0x57, 0xb7, - 0x82, 0x4e, 0xd4, 0xc5, 0x9c, 0xb2, 0xb5, 0xf7, 0x20, 0x86, 0xe7, 0xb6, 0x92, 0x3e, 0x09, 0x42, 0xf4, 0x29, 0x98, - 0x43, 0x99, 0x7f, 0xca, 0x18, 0x63, 0x34, 0x90, 0xb3, 0x7d, 0x11, 0x22, 0x32, 0xb1, 0x9c, 0x51, 0x06, 0xa6, 0xd0, - 0x11, 0xb9, 0x44, 0x86, 0xfe, 0xe4, 0xe6, 0x8b, 0xda, 0x93, 0x1a, 0xc7, 0x75, 0xac, 0x5e, 0xaa, 0x67, 0x0d, 0xb6, - 0xa1, 0xf8, 0x47, 0xf2, 0xd8, 0x1c, 0x26, 0xe5, 0x17, 0x43, 0xd4, 0xe5, 0xec, 0xb0, 0xde, 0x43, 0x16, 0xab, 0xa2, - 0x01, 0x60, 0xb5, 0x5b, 0x61, 0x9d, 0x67, 0xa6, 0x7e, 0xa7, 0xcb, 0x1b, 0x5b, 0x5b, 0xb8, 0x45, 0x5d, 0xa8, 0x86, - 0x82, 0xf2, 0x6a, 0x50, 0x7f, 0xc2, 0xe8, 0x2f, 0x4f, 0x25, 0xe6, 0x19, 0x21, 0x99, 0xa7, 0xee, 0x1d, 0x7f, 0x09, - 0x8f, 0xc3, 0x96, 0x70, 0x75, 0xaa, 0xdb, 0x7f, 0xa9, 0xe2, 0xc9, 0xcc, 0xad, 0x46, 0xbe, 0x71, 0x0b, 0x85, 0x62, - 0x2f, 0x57, 0x23, 0xba, 0x0f, 0xad, 0xb2, 0x5f, 0xf6, 0x91, 0x6c, 0x84, 0x39, 0xcc, 0xe7, 0x63, 0x9f, 0x06, 0x1e, - 0x9f, 0x7b, 0xea, 0x78, 0x3b, 0xc0, 0x4d, 0x81, 0xcd, 0xd6, 0x81, 0xf0, 0x7c, 0x40, 0xf7, 0xd9, 0xa8, 0xc9, 0xba, - 0xd7, 0x45, 0x01, 0x62, 0x0b, 0x83, 0x2b, 0xad, 0x7f, 0xe4, 0x45, 0xd6, 0x17, 0x55, 0xa0, 0xed, 0x97, 0xe9, 0xbe, - 0x28, 0x0c, 0x0d, 0x4f, 0xbb, 0x8d, 0xd8, 0x63, 0x07, 0xcd, 0x92, 0xd6, 0x30, 0x79, 0x25, 0x1d, 0xe4, 0x6f, 0x62, - 0xb2, 0x48, 0x94, 0xbf, 0xfd, 0x35, 0x39, 0xc9, 0x5d, 0x6f, 0x76, 0x7b, 0x29, 0x6a, 0x2a, 0x4c, 0xfd, 0x5d, 0xfb, - 0xb0, 0x52, 0xff, 0x95, 0x7e, 0xb9, 0x0a, 0x75, 0x47, 0xd6, 0x82, 0x44, 0x4e, 0xc3, 0x90, 0x6b, 0x75, 0x58, 0x73, - 0xaa, 0xf3, 0x6c, 0x9d, 0xb5, 0x1d, 0x3e, 0x81, 0x9b, 0x25, 0x67, 0x09, 0x53, 0xf1, 0xa6, 0x26, 0x04, 0x87, 0x81, - 0xa0, 0x30, 0x5c, 0x14, 0x87, 0x48, 0x58, 0xbc, 0xd9, 0xe1, 0x85, 0xd3, 0x65, 0xb0, 0xf1, 0xd5, 0x7e, 0xa1, 0xcc, - 0x33, 0xb6, 0x0b, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x18, 0x35, 0xc0, 0xea, 0x9f, 0xf0, 0xf1, 0x7b, 0x12, 0xb6, 0x1e, - 0x74, 0x49, 0x6a, 0xd9, 0x54, 0x4a, 0x54, 0x5b, 0xc6, 0x35, 0xd6, 0x50, 0x71, 0xed, 0xf0, 0xc8, 0xea, 0x0c, 0xfd, - 0x47, 0xe7, 0x8b, 0xc4, 0x73, 0x48, 0x27, 0x8f, 0x56, 0x82, 0x68, 0x71, 0xcb, 0xba, 0xf5, 0xa1, 0xaf, 0xb9, 0x1c, - 0x85, 0x6d, 0x34, 0x94, 0xd2, 0x45, 0xbc, 0xa4, 0x76, 0x1d, 0x94, 0x81, 0xf4, 0x70, 0x65, 0xa2, 0xb3, 0x0f, 0xd4, - 0xb0, 0xee, 0x40, 0xe3, 0x4d, 0x8f, 0x29, 0xb4, 0xb1, 0xab, 0x16, 0xf3, 0x8a, 0xa9, 0x53, 0x74, 0x4b, 0x6c, 0x09, - 0xec, 0xae, 0xcb, 0xe1, 0xd6, 0xf4, 0x25, 0x10, 0x53, 0x4a, 0xc4, 0xb7, 0x5c, 0x6a, 0xee, 0xba, 0x8e, 0xe2, 0x13, - 0xb6, 0x42, 0x4b, 0xd6, 0xad, 0xc3, 0x6d, 0xac, 0xf5, 0x5a, 0x10, 0x52, 0xff, 0x52, 0x8b, 0x70, 0xf0, 0xea, 0x82, - 0x65, 0x5b, 0x7c, 0x74, 0xc2, 0x86, 0x16, 0x6d, 0x7b, 0x54, 0x41, 0x8b, 0x1d, 0x55, 0xe3, 0xa5, 0xcd, 0x5c, 0xe2, - 0x6a, 0x26, 0xc6, 0x37, 0xf4, 0xdb, 0x14, 0x07, 0x96, 0x9d, 0x15, 0xa0, 0xf1, 0xe0, 0xa4, 0xb7, 0x22, 0x2f, 0x35, - 0x3b, 0xa8, 0x99, 0x51, 0xcb, 0x67, 0x9a, 0x48, 0xeb, 0x05, 0xac, 0x11, 0xda, 0x5a, 0x7e, 0xe0, 0x8a, 0x13, 0x09, - 0xb6, 0x65, 0xfa, 0x7f, 0x98, 0x92, 0x56, 0x62, 0x47, 0x00, 0xcf, 0xb8, 0x8b, 0xfe, 0x81, 0x66, 0x05, 0x30, 0xa6, - 0x60, 0x26, 0x14, 0xf2, 0xb3, 0xe1, 0x08, 0x19, 0xdb, 0x3f, 0x69, 0x1f, 0x5b, 0x76, 0x73, 0x80, 0x00, 0x47, 0x96, - 0x81, 0x71, 0xef, 0x55, 0x2a, 0xda, 0xd3, 0x19, 0x8e, 0x51, 0xd5, 0xd2, 0x9a, 0xfb, 0x95, 0xaa, 0x24, 0x33, 0x60, - 0x37, 0x2f, 0x9a, 0xf6, 0xda, 0x22, 0x97, 0x28, 0xce, 0x90, 0xd5, 0xa9, 0x22, 0xb3, 0x30, 0xd6, 0xae, 0x92, 0x05, - 0x11, 0x1f, 0xfb, 0xc2, 0x19, 0xff, 0xd3, 0x94, 0xa0, 0xfc, 0xb8, 0xaf, 0xe9, 0xa4, 0x42, 0xa5, 0xb0, 0x8f, 0xcb, - 0x69, 0x7c, 0xc5, 0xc0, 0xa4, 0x02, 0x1b, 0x1a, 0xcc, 0x8f, 0x9b, 0x60, 0x50, 0x75, 0x00, 0x8f, 0x6e, 0x1a, 0xc5, - 0x5b, 0x06, 0xdf, 0x94, 0x2e, 0xb4, 0x1c, 0xe5, 0xa8, 0x1c, 0x70, 0xe6, 0xc8, 0xad, 0xc9, 0x4a, 0x04, 0x57, 0xd6, - 0x0e, 0x52, 0x54, 0x60, 0xb8, 0xb3, 0x6a, 0x90, 0xe6, 0xd2, 0x23, 0x25, 0xe3, 0xaf, 0x0b, 0xd0, 0x02, 0x08, 0xc3, - 0xca, 0xbf, 0xdc, 0x2c, 0xe3, 0x15, 0xca, 0x4a, 0xe9, 0x54, 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x7a, 0x3a, 0xe1, - 0x8d, 0xe7, 0x88, 0x73, 0x41, 0x50, 0x3b, 0xd5, 0x7c, 0x6f, 0x30, 0x0c, 0xea, 0xa4, 0x33, 0x40, 0x3e, 0x6a, 0x1a, - 0x4c, 0x78, 0x6d, 0xc9, 0xd1, 0x8b, 0xb8, 0xae, 0xc0, 0x72, 0x62, 0x67, 0x57, 0x09, 0x20, 0x97, 0xd6, 0xc2, 0x0e, - 0x32, 0x30, 0x96, 0xf1, 0xc7, 0x40, 0xee, 0xf8, 0xf4, 0x49, 0x69, 0xd9, 0x23, 0xeb, 0x95, 0x0d, 0x17, 0x9f, 0x7c, - 0x32, 0x7a, 0x83, 0xa5, 0xa2, 0xc9, 0xfd, 0x67, 0x63, 0x41, 0xdf, 0xc9, 0x06, 0x63, 0x2d, 0x3a, 0x07, 0x51, 0xae, - 0x42, 0x3b, 0xf2, 0x55, 0x59, 0x97, 0x05, 0xd9, 0xbe, 0x01, 0x29, 0x3f, 0xa7, 0x15, 0xa1, 0x54, 0x0b, 0x2a, 0x79, - 0x87, 0x55, 0x5c, 0x10, 0x42, 0xa9, 0x01, 0x07, 0x65, 0x08, 0x70, 0x94, 0x71, 0x77, 0xa7, 0x91, 0x00, 0x90, 0x8a, - 0xa1, 0x60, 0xce, 0x5c, 0xd6, 0xde, 0xe2, 0x02, 0x5b, 0x9c, 0x33, 0x73, 0x8d, 0xe1, 0x79, 0x2d, 0xcc, 0xd7, 0x1c, - 0x2b, 0x12, 0xc8, 0xda, 0x72, 0xba, 0x16, 0x5d, 0xaa, 0xa7, 0x47, 0x43, 0x81, 0xcc, 0x4a, 0x72, 0xee, 0xe5, 0xf3, - 0x0a, 0xa1, 0x95, 0xe4, 0xbf, 0x59, 0x62, 0x03, 0xc6, 0x38, 0xb1, 0x7f, 0x7c, 0xa1, 0x42, 0x7e, 0xe4, 0x71, 0xe3, - 0x90, 0x1f, 0x87, 0x13, 0x9c, 0x52, 0x02, 0x06, 0xb5, 0xf6, 0x39, 0x67, 0x7a, 0x63, 0xce, 0x44, 0x4c, 0x9c, 0xf0, - 0xf2, 0x3d, 0x7c, 0x64, 0xc0, 0x28, 0x45, 0xdb, 0x41, 0x45, 0xca, 0xb4, 0x02, 0x48, 0x68, 0xda, 0x1e, 0x5a, 0xaf, - 0xc5, 0xa4, 0xac, 0x98, 0xe2, 0x9a, 0xe6, 0x8a, 0xb7, 0xac, 0x1d, 0x35, 0xb5, 0x6f, 0x3c, 0x93, 0x78, 0x88, 0xe3, - 0xe7, 0x89, 0xaf, 0x13, 0x24, 0x84, 0x48, 0xa9, 0xf0, 0x17, 0x67, 0x5b, 0x3d, 0x7e, 0x49, 0xc5, 0xbd, 0xf0, 0x01, - 0x74, 0x8c, 0xa1, 0x31, 0x9b, 0x0a, 0x71, 0x43, 0x36, 0x43, 0xe2, 0xa8, 0x73, 0x23, 0xd3, 0xdd, 0x66, 0xd5, 0xe1, - 0xc3, 0xc9, 0xf2, 0xd3, 0xec, 0xb1, 0x17, 0x23, 0xc8, 0x60, 0xad, 0xd3, 0x8a, 0xdb, 0xe1, 0xb7, 0xff, 0x5b, 0xae, - 0x48, 0x8f, 0xea, 0xda, 0x22, 0xd1, 0xf9, 0x15, 0x12, 0x4c, 0x8b, 0xa4, 0xc8, 0xea, 0x5d, 0xca, 0x64, 0xdb, 0x2b, - 0x36, 0x5e, 0xcb, 0xe0, 0xb2, 0xb0, 0x38, 0x15, 0xf3, 0xcb, 0x5e, 0x8b, 0xc9, 0xae, 0xaf, 0x8b, 0xaf, 0xca, 0xcc, - 0x39, 0x56, 0x9e, 0x21, 0x8c, 0x85, 0xbd, 0x2e, 0x68, 0x53, 0x5a, 0xd8, 0x74, 0x50, 0x3d, 0x86, 0x29, 0xe3, 0xd1, - 0x6b, 0x47, 0x42, 0x7a, 0xa8, 0x75, 0xff, 0x26, 0xaf, 0xaf, 0xa3, 0xc2, 0x00, 0x10, 0x97, 0x22, 0x2c, 0x3c, 0x9e, - 0xc1, 0xe0, 0x12, 0x83, 0xc2, 0x3b, 0xec, 0xf4, 0xe2, 0x1a, 0xce, 0x3b, 0x37, 0xae, 0xd4, 0x72, 0x8a, 0x2d, 0x1d, - 0x27, 0x5f, 0x48, 0xcf, 0x7a, 0x45, 0x81, 0xbe, 0xa5, 0x66, 0x2d, 0x6e, 0xcd, 0x69, 0x0a, 0xc5, 0x90, 0xb2, 0xab, - 0xf6, 0x74, 0xef, 0xd4, 0xb5, 0x3d, 0x3b, 0x1f, 0xd6, 0x35, 0x45, 0xbb, 0x92, 0xa8, 0xf4, 0x1c, 0x91, 0x18, 0x2b, - 0x86, 0x76, 0xae, 0xad, 0xeb, 0xa2, 0x8e, 0x6a, 0xa8, 0xd6, 0x35, 0x46, 0xaa, 0x6e, 0x29, 0xd5, 0xbf, 0xd4, 0x7a, - 0x5c, 0x7a, 0x6d, 0x30, 0xf4, 0x9e, 0x3c, 0x8a, 0x97, 0x89, 0xba, 0x94, 0xdb, 0x4b, 0x9f, 0xea, 0x75, 0xbb, 0x7d, - 0xeb, 0xbb, 0xff, 0x53, 0xd0, 0xd6, 0xc5, 0x37, 0xf1, 0x3f, 0xc8, 0xff, 0x67, 0x0f, 0x18, 0x5b, 0x7c, 0x7c, 0x38, - 0xae, 0xb4, 0x59, 0x57, 0x36, 0x39, 0x25, 0x8f, 0x9d, 0x6f, 0xfa, 0x8a, 0xa5, 0x83, 0xba, 0xbb, 0x3b, 0x39, 0x0b, - 0x0e, 0x9b, 0x33, 0x47, 0x30, 0x50, 0x94, 0xc9, 0xcd, 0x95, 0xd1, 0xa6, 0xeb, 0x74, 0xa9, 0xc3, 0x2f, 0x4b, 0x93, - 0x90, 0xbd, 0xc6, 0x4b, 0x8c, 0x60, 0x9e, 0x4b, 0x99, 0xd8, 0x02, 0x5e, 0x39, 0x43, 0x51, 0x0f, 0x1d, 0x5b, 0x4a, - 0x30, 0x65, 0xd5, 0x20, 0x3e, 0xcb, 0x14, 0xcf, 0x51, 0x65, 0x1a, 0xd5, 0x73, 0xf7, 0xa6, 0x07, 0x8c, 0xc8, 0xc8, - 0xd9, 0xaf, 0x32, 0xeb, 0x42, 0x07, 0xeb, 0xf6, 0x6c, 0x7f, 0xc4, 0xb3, 0x52, 0x62, 0xc0, 0xbd, 0xb3, 0x01, 0xb1, - 0x43, 0x63, 0x95, 0x43, 0xa1, 0xf8, 0xc7, 0xad, 0x70, 0x99, 0xa8, 0xcf, 0x78, 0xcb, 0x5e, 0xb2, 0xb8, 0x0d, 0xcd, - 0xac, 0x43, 0xbe, 0x33, 0x15, 0x44, 0xec, 0x5d, 0xa7, 0xea, 0x39, 0x42, 0xd6, 0x94, 0x7a, 0xfc, 0x59, 0xa2, 0x2c, - 0x8d, 0xa8, 0xc4, 0xd1, 0xa8, 0x1a, 0x0b, 0xff, 0x77, 0xe6, 0x12, 0xdd, 0xc9, 0xfe, 0x19, 0x61, 0xe6, 0xbe, 0x22, - 0x56, 0x2e, 0xe1, 0x84, 0xe9, 0xd5, 0x36, 0x9d, 0x15, 0x22, 0x28, 0xe0, 0xf3, 0x45, 0xef, 0xcd, 0xa6, 0x2e, 0x04, - 0x8d, 0x77, 0x79, 0xde, 0x85, 0xf9, 0x8c, 0xdc, 0x08, 0xcd, 0x34, 0xac, 0x4d, 0x89, 0x72, 0x10, 0xb8, 0xe8, 0x09, - 0x34, 0xe7, 0x32, 0x30, 0xc1, 0x34, 0x2f, 0xb6, 0x7e, 0xd2, 0xd6, 0x99, 0x1e, 0x48, 0x43, 0x8c, 0x5a, 0x64, 0x9e, - 0xde, 0x95, 0xa6, 0x8f, 0xe9, 0xac, 0xd2, 0x3a, 0x6b, 0x03, 0x2b, 0x7e, 0x40, 0x31, 0x13, 0x41, 0xab, 0x97, 0x24, - 0xa9, 0xa0, 0x39, 0xb4, 0xe8, 0x65, 0xaf, 0x3a, 0x49, 0x41, 0xdd, 0xa9, 0x25, 0xe3, 0x82, 0xb0, 0xaf, 0x6d, 0xf7, - 0x84, 0xcc, 0x51, 0xb4, 0x41, 0x9a, 0x92, 0x4b, 0xbe, 0x47, 0x5c, 0x65, 0x3c, 0xff, 0xbc, 0x50, 0xf8, 0x02, 0x58, - 0x6e, 0x7f, 0x57, 0x96, 0xc3, 0xa2, 0x2e, 0x16, 0xbf, 0x9c, 0x80, 0x35, 0xf2, 0x8f, 0xe1, 0xfe, 0x28, 0x20, 0x1a, - 0x7e, 0x56, 0xb0, 0x3b, 0x68, 0xb3, 0x5f, 0x8c, 0xb3, 0xdd, 0xc7, 0xbd, 0xc5, 0x6e, 0xb8, 0xec, 0xf8, 0xcb, 0x27, - 0xeb, 0xf6, 0xb4, 0x07, 0xae, 0x0d, 0x83, 0xdb, 0x5f, 0x9c, 0xbf, 0xa6, 0xc1, 0xf3, 0x2d, 0x63, 0x37, 0x5b, 0xf9, - 0x90, 0xdf, 0xa3, 0xdc, 0xa9, 0xcb, 0xe5, 0x52, 0xd4, 0x10, 0x90, 0x6a, 0xe6, 0x9c, 0xb8, 0x7e, 0x52, 0x90, 0x16, - 0x68, 0x61, 0x4a, 0x47, 0xb7, 0x24, 0xde, 0x8b, 0x86, 0xac, 0x37, 0x17, 0x60, 0xd3, 0x6d, 0x2f, 0x90, 0x4a, 0x8a, - 0x99, 0x22, 0x2d, 0x26, 0x14, 0x3f, 0xe7, 0xa8, 0x93, 0x3b, 0xb8, 0x2f, 0xa1, 0x4d, 0x64, 0x58, 0x77, 0x93, 0x71, - 0xfe, 0x54, 0xed, 0x09, 0x3d, 0x6e, 0x18, 0xab, 0x43, 0x7e, 0x8b, 0x34, 0xa0, 0xf7, 0xe3, 0x99, 0x14, 0xd9, 0x0f, - 0x83, 0x02, 0xf8, 0xd4, 0x55, 0x40, 0xb5, 0x40, 0xbf, 0xe5, 0xe3, 0x89, 0x4c, 0x19, 0xc4, 0xa8, 0xec, 0x0d, 0xd0, - 0x48, 0x50, 0x64, 0x9b, 0xb2, 0x78, 0x3f, 0x2d, 0x08, 0xe8, 0x43, 0x09, 0x9d, 0xe9, 0x93, 0x0c, 0x11, 0xd5, 0x15, - 0x3c, 0xcc, 0xe9, 0x4e, 0xf8, 0xa6, 0xce, 0x87, 0xcf, 0x9d, 0xb1, 0xe7, 0x2d, 0xed, 0x0a, 0x5b, 0x86, 0x69, 0x68, - 0xa8, 0x82, 0x71, 0xe8, 0x5e, 0xb4, 0xf4, 0x14, 0xb7, 0xa1, 0xe4, 0xe3, 0xf1, 0xe7, 0xf2, 0xcb, 0x44, 0xd4, 0xdf, - 0x26, 0x32, 0xcc, 0x08, 0x7a, 0x66, 0x51, 0x2f, 0xae, 0x70, 0x61, 0x74, 0xba, 0x6a, 0x20, 0x68, 0x79, 0xbf, 0xad, - 0x07, 0xd7, 0xf9, 0x31, 0xdc, 0x38, 0x57, 0x89, 0x36, 0x4e, 0xe3, 0xde, 0x6f, 0x50, 0x5c, 0x2e, 0x71, 0xd0, 0xe5, - 0x05, 0x12, 0xdf, 0x07, 0xd7, 0x76, 0x59, 0xed, 0x6d, 0xaa, 0xf9, 0xcb, 0x7a, 0xe5, 0x0d, 0x09, 0x3b, 0x6f, 0x12, - 0x0e, 0xa4, 0x84, 0x0c, 0x27, 0x1f, 0x91, 0x5c, 0xd8, 0xa0, 0x4b, 0x3e, 0xde, 0xd2, 0xd0, 0x51, 0xc3, 0x8a, 0x68, - 0x17, 0x7e, 0xc3, 0x8f, 0x75, 0x5b, 0x88, 0x20, 0x6e, 0xb0, 0x4c, 0x00, 0xcf, 0x48, 0xe6, 0x44, 0x56, 0x75, 0x98, - 0xc0, 0x34, 0x97, 0x30, 0x0d, 0xec, 0xb6, 0x01, 0x34, 0x3e, 0x99, 0x94, 0xb8, 0x02, 0xdd, 0x2c, 0xd5, 0xce, 0xab, - 0x92, 0x8c, 0xfd, 0x85, 0xa0, 0x9d, 0xeb, 0x0f, 0x8f, 0x32, 0x2f, 0xb7, 0x9b, 0x5d, 0xa4, 0x79, 0x39, 0xc5, 0xd0, - 0x0e, 0x64, 0x76, 0x35, 0x0c, 0x99, 0xba, 0x4b, 0xea, 0x3c, 0x38, 0xa9, 0x2e, 0x0c, 0xc2, 0x21, 0x5c, 0x91, 0xa6, - 0x35, 0x17, 0x84, 0x59, 0x74, 0x6b, 0x0a, 0xef, 0x76, 0xc0, 0xd5, 0x12, 0x01, 0x25, 0x88, 0x38, 0xe9, 0x45, 0x87, - 0x55, 0x3c, 0xb8, 0x1b, 0x75, 0x67, 0x90, 0x96, 0x95, 0x8b, 0x95, 0x62, 0x7c, 0xa1, 0xc5, 0x9d, 0x60, 0x5a, 0x05, - 0xf7, 0x7e, 0x20, 0x46, 0x7b, 0xbe, 0x16, 0x4a, 0x1e, 0x63, 0xa4, 0xa2, 0x3c, 0xfa, 0xf6, 0x43, 0x4a, 0x7e, 0xd4, - 0xf0, 0x58, 0x2b, 0x94, 0x2a, 0x76, 0xea, 0xda, 0x05, 0x9d, 0x95, 0x08, 0xbb, 0x2c, 0x13, 0x2f, 0xa1, 0xdf, 0xd5, - 0xb0, 0xdb, 0x32, 0x1b, 0xbb, 0x40, 0xdc, 0x9e, 0x44, 0x4a, 0xe4, 0x60, 0xad, 0xe1, 0x1d, 0xc9, 0xf3, 0x34, 0x78, - 0x5b, 0x72, 0xeb, 0x97, 0x0c, 0xc5, 0xad, 0xb6, 0x60, 0xf1, 0x43, 0x7a, 0x74, 0x44, 0x01, 0xaa, 0x7f, 0xd3, 0x91, - 0x20, 0x71, 0xcb, 0x8c, 0xdf, 0x55, 0xe5, 0xe6, 0xb9, 0xb9, 0xe1, 0x59, 0x62, 0x55, 0xc4, 0xc2, 0xf9, 0xfb, 0x1a, - 0x20, 0x50, 0x48, 0x67, 0x33, 0xd7, 0x3c, 0x12, 0x75, 0xc5, 0xf5, 0xe0, 0x4e, 0x65, 0x4c, 0xdd, 0xa7, 0x23, 0xd5, - 0x1b, 0xee, 0x6a, 0x6c, 0xa9, 0x25, 0xbc, 0xa9, 0xb0, 0xa5, 0x3b, 0xcd, 0x15, 0x5b, 0x5c, 0xe6, 0x2a, 0xb5, 0x9d, - 0xc0, 0xb4, 0x6b, 0x9d, 0xfe, 0x38, 0x86, 0x1a, 0xca, 0x44, 0xdc, 0x26, 0xea, 0xe0, 0xb2, 0x6c, 0x8a, 0x72, 0x97, - 0x09, 0x4e, 0x92, 0x0d, 0xee, 0x80, 0x48, 0xd5, 0xe2, 0x32, 0xc7, 0x4d, 0x1b, 0x22, 0xc5, 0x77, 0xd2, 0x35, 0x45, - 0x52, 0x9c, 0xa6, 0x17, 0x9e, 0x46, 0x56, 0x6e, 0x76, 0x4a, 0x33, 0xe9, 0x1d, 0x52, 0x64, 0x45, 0x21, 0x71, 0xaf, - 0x22, 0x05, 0x0f, 0xad, 0xfa, 0xb3, 0xcc, 0x29, 0xd9, 0xc1, 0xf4, 0x6e, 0xb9, 0xee, 0xef, 0xc3, 0xc7, 0xf3, 0xf5, - 0x48, 0x44, 0x17, 0xc6, 0x57, 0x4a, 0x48, 0x56, 0x72, 0x90, 0x84, 0xbc, 0xe0, 0x90, 0xce, 0x5e, 0x15, 0x09, 0x38, - 0xd2, 0x2b, 0x17, 0x69, 0x5d, 0xb9, 0x56, 0x05, 0xda, 0xc1, 0x72, 0xca, 0xa8, 0x10, 0x33, 0x63, 0x8d, 0xe2, 0xfd, - 0x38, 0xbc, 0x3b, 0x1e, 0xa4, 0x3b, 0x92, 0x4d, 0xcd, 0x5c, 0x77, 0x28, 0x71, 0x19, 0x2a, 0x38, 0x12, 0x27, 0x2a, - 0x87, 0xe0, 0xe8, 0xcc, 0xf5, 0x1e, 0x0b, 0xeb, 0x0a, 0xe6, 0xcc, 0x79, 0x96, 0x07, 0xab, 0xab, 0xf5, 0x17, 0xee, - 0x7a, 0xfd, 0x7a, 0x22, 0xfa, 0x9d, 0x97, 0x9a, 0x6a, 0x80, 0x87, 0x16, 0xdb, 0x75, 0x3c, 0x8d, 0x29, 0xd0, 0x02, - 0xe9, 0xd5, 0x04, 0x45, 0xc3, 0x27, 0xcd, 0x30, 0x07, 0x3d, 0xd5, 0x37, 0x6f, 0xa3, 0x66, 0xb6, 0x65, 0x9a, 0x56, - 0x18, 0x66, 0x97, 0x06, 0xee, 0x4c, 0x72, 0x0d, 0x31, 0x6c, 0xfd, 0x7a, 0xb6, 0x4d, 0xe4, 0x72, 0xdf, 0xb3, 0x5a, - 0x08, 0xa6, 0xe9, 0x98, 0x23, 0xff, 0x3e, 0xc9, 0x61, 0xc2, 0x71, 0x0c, 0x4a, 0x4f, 0xbc, 0x2c, 0xc5, 0x2c, 0x27, - 0x61, 0x65, 0x5d, 0x5d, 0xc0, 0xf5, 0x64, 0x24, 0x02, 0xf1, 0x28, 0xb5, 0x58, 0x7e, 0x00, 0xd7, 0x54, 0x5e, 0xef, - 0x68, 0x63, 0x0f, 0x04, 0x00, 0xcb, 0xf6, 0xcc, 0x49, 0xaf, 0x1a, 0xf9, 0x2a, 0xa6, 0x90, 0x5c, 0xbe, 0x93, 0x4c, - 0x46, 0x04, 0xfb, 0x2a, 0xbd, 0xbf, 0xa0, 0x1f, 0xd4, 0xde, 0x8e, 0x10, 0xd1, 0x8b, 0x84, 0xfd, 0x72, 0x9b, 0x26, - 0x21, 0x0e, 0x5f, 0x98, 0x88, 0x8d, 0x0b, 0xd8, 0x8a, 0xd0, 0x97, 0xc7, 0x56, 0x26, 0xf3, 0xba, 0xeb, 0xf0, 0xfb, - 0x2d, 0x1f, 0xdc, 0x18, 0xc1, 0x24, 0xb2, 0x25, 0x02, 0x0b, 0x91, 0xca, 0x98, 0x28, 0xbe, 0x08, 0x3f, 0x57, 0xfb, - 0xbe, 0x51, 0x4c, 0x25, 0x9b, 0x3d, 0xdf, 0xf1, 0xee, 0x78, 0xfa, 0xae, 0xf5, 0xeb, 0xac, 0x90, 0x21, 0xd3, 0x5e, - 0xf7, 0x0f, 0x00, 0x3d, 0xf3, 0xa6, 0xbc, 0x9d, 0xcc, 0x77, 0x92, 0x76, 0x95, 0x36, 0xef, 0x34, 0xd1, 0xc0, 0xaf, - 0xbf, 0x11, 0x7a, 0xc5, 0x57, 0x9a, 0x88, 0x7e, 0xd5, 0x0b, 0x36, 0xab, 0xa8, 0x90, 0x67, 0xae, 0xc3, 0x9a, 0xf5, - 0xed, 0x1c, 0x9a, 0xbe, 0x29, 0xa5, 0x39, 0x4f, 0x06, 0x53, 0x87, 0xf4, 0x55, 0x46, 0x75, 0x30, 0xa0, 0xb9, 0x83, - 0x0d, 0xd2, 0xdf, 0x00, 0xcf, 0xb9, 0x83, 0x00, 0x27, 0x8a, 0x24, 0x0d, 0xbf, 0x74, 0xf3, 0x2a, 0x9a, 0x3c, 0x8c, - 0x9a, 0x0c, 0xc5, 0x65, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x43, 0x83, 0xa8, 0xb3, 0xf7, 0x88, 0xdd, 0x5e, 0xda, 0x7b, - 0xf0, 0x9f, 0x3e, 0x50, 0xb2, 0x2e, 0x42, 0xc5, 0x60, 0x42, 0xf9, 0x4b, 0xd9, 0x2f, 0x69, 0xcf, 0x4a, 0x57, 0xe6, - 0x42, 0xc1, 0xbc, 0x36, 0xa8, 0xc6, 0x01, 0x2c, 0xa0, 0xbd, 0x48, 0x40, 0xc5, 0x6e, 0x2b, 0x6c, 0xc8, 0x04, 0xdb, - 0x4f, 0x62, 0x5d, 0x89, 0x1f, 0x0a, 0x70, 0xf8, 0x9b, 0x86, 0x90, 0x84, 0x2c, 0xe6, 0x7e, 0x9d, 0x97, 0x6d, 0x5b, - 0xc7, 0x6d, 0xcc, 0xe6, 0x91, 0xbc, 0x8d, 0xb0, 0x9c, 0xf0, 0xe6, 0x7f, 0x98, 0x07, 0xe2, 0xb2, 0xea, 0x6f, 0x6b, - 0xbb, 0xb4, 0xa3, 0xd7, 0x61, 0x58, 0x89, 0xad, 0x62, 0xf9, 0x87, 0xb9, 0xea, 0xb1, 0x03, 0xb8, 0xbf, 0x87, 0xca, - 0xf0, 0x96, 0xe6, 0x86, 0xb7, 0xe3, 0x79, 0xa9, 0x41, 0xf6, 0x99, 0x8a, 0x24, 0x9c, 0xd2, 0xfd, 0x8a, 0x64, 0x48, - 0x13, 0x89, 0x1e, 0x3d, 0xc9, 0x47, 0x1a, 0x0f, 0xab, 0x94, 0x6d, 0xe8, 0xb0, 0xd9, 0xee, 0xa0, 0xf3, 0xf6, 0xb9, - 0xfb, 0xcb, 0xa9, 0xb7, 0x40, 0xb5, 0x4e, 0x61, 0xf3, 0xd2, 0xc3, 0x16, 0x5b, 0xf7, 0x2c, 0xa6, 0x7e, 0x0a, 0xb2, - 0x72, 0x24, 0x1b, 0x62, 0x22, 0xdd, 0x3b, 0x2d, 0x9e, 0x79, 0x94, 0xc0, 0xdd, 0x4d, 0x7d, 0x73, 0xec, 0xe3, 0x79, - 0xc9, 0x1f, 0xb3, 0x33, 0xdc, 0xf3, 0xa1, 0x97, 0xef, 0x59, 0x91, 0x3b, 0x62, 0xa7, 0xa3, 0x78, 0xc8, 0x45, 0x77, - 0x42, 0x59, 0x09, 0xcb, 0xf9, 0xb9, 0x6a, 0xa5, 0x36, 0x06, 0xa5, 0x42, 0x59, 0x96, 0x7b, 0x9f, 0x6c, 0xdd, 0x41, - 0x42, 0x95, 0xef, 0x41, 0x49, 0xe0, 0xf7, 0x49, 0x04, 0x52, 0xfd, 0xa3, 0x54, 0x21, 0x66, 0xcc, 0x4b, 0x33, 0x2f, - 0xd4, 0x9f, 0x50, 0xca, 0x81, 0x87, 0x80, 0x6f, 0x09, 0xb8, 0x34, 0xb4, 0xf5, 0xdf, 0x6d, 0x18, 0xd3, 0xb2, 0x1f, - 0x6b, 0xf4, 0xf7, 0x14, 0xf8, 0xbd, 0x06, 0xee, 0x89, 0x3a, 0x3f, 0x9d, 0x62, 0xf0, 0x68, 0xa1, 0xd7, 0xb7, 0xd3, - 0x7d, 0xc3, 0xd4, 0x78, 0xe5, 0x42, 0xf1, 0xad, 0x4d, 0xe5, 0x8f, 0xa1, 0x76, 0x5d, 0x0b, 0x4d, 0xf6, 0x42, 0x39, - 0x53, 0x8a, 0xb3, 0xc2, 0x9b, 0x06, 0x43, 0x2b, 0x1e, 0x49, 0xb5, 0xc4, 0x39, 0x7b, 0x8f, 0x5d, 0xc5, 0x09, 0xef, - 0x48, 0x03, 0x05, 0x2a, 0x99, 0x05, 0x47, 0x0c, 0x94, 0xf6, 0x65, 0x7d, 0x99, 0xee, 0xf6, 0x63, 0x2d, 0xee, 0xe0, - 0x78, 0x84, 0xaa, 0x22, 0x5f, 0x21, 0x27, 0x1e, 0x39, 0x90, 0x28, 0xf5, 0xfc, 0x26, 0xaa, 0xd0, 0xfc, 0x74, 0xa2, - 0x68, 0x7f, 0x97, 0x0d, 0xad, 0xe8, 0x3f, 0x1b, 0xfe, 0xec, 0x11, 0x20, 0x8f, 0x73, 0xd2, 0xf7, 0x09, 0xb6, 0x4c, - 0x88, 0xc6, 0xe5, 0xd8, 0xb7, 0x35, 0x78, 0x5e, 0x6a, 0xb4, 0x58, 0xf4, 0x72, 0x21, 0xfb, 0x8d, 0xd9, 0x58, 0x89, - 0x39, 0x73, 0xe1, 0x8d, 0x3b, 0xa1, 0xe1, 0x37, 0x0c, 0xa4, 0xf7, 0xb0, 0x9e, 0x84, 0x99, 0x66, 0x01, 0x28, 0x35, - 0xb4, 0xd0, 0x47, 0x8b, 0x9d, 0xeb, 0x3c, 0x39, 0xde, 0xf0, 0xa6, 0x14, 0x01, 0xe3, 0xeb, 0xfb, 0x1b, 0x42, 0x33, - 0x50, 0x24, 0x25, 0x62, 0x3e, 0x01, 0x8c, 0x62, 0x30, 0x6a, 0xaa, 0xd7, 0xe3, 0x01, 0x9f, 0x60, 0x10, 0x5f, 0x6c, - 0x7d, 0x79, 0x33, 0x6e, 0x20, 0xee, 0x86, 0xb3, 0x94, 0x4f, 0xc9, 0x77, 0x23, 0x01, 0x8c, 0x97, 0x7f, 0x02, 0x54, - 0x17, 0x5a, 0x6d, 0xb0, 0xbf, 0x13, 0xdb, 0x71, 0x7e, 0x01, 0x4d, 0xf0, 0x35, 0xd8, 0x05, 0x3f, 0x8e, 0x7f, 0x28, - 0xac, 0x6e, 0xa4, 0xa5, 0x5e, 0x4e, 0x47, 0x7d, 0xb6, 0x99, 0xf9, 0x00, 0x1b, 0xce, 0x37, 0x0f, 0x1b, 0xe5, 0xfa, - 0x8b, 0x09, 0x03, 0xf3, 0xca, 0x09, 0xa5, 0x9b, 0x23, 0x99, 0x5f, 0x32, 0xac, 0xcd, 0x1a, 0xfa, 0x5c, 0x4e, 0x5c, - 0xf2, 0x2d, 0x90, 0x6b, 0xa4, 0xda, 0x6f, 0xf1, 0xf2, 0x1b, 0xa4, 0x1e, 0x96, 0xef, 0x7f, 0x56, 0x4a, 0x17, 0xb1, - 0xa9, 0xcd, 0x7e, 0xe4, 0xb8, 0x4b, 0x9f, 0xcb, 0x93, 0xcf, 0x90, 0xfd, 0xd9, 0x1c, 0xf2, 0x79, 0x7f, 0xb5, 0x7b, - 0xb7, 0xfc, 0x33, 0x9b, 0xed, 0xc5, 0x66, 0xd7, 0xdb, 0xbb, 0xf9, 0x33, 0xf8, 0x3a, 0xfc, 0x1e, 0xc1, 0x6a, 0x6e, - 0x0f, 0x0a, 0x3e, 0x4c, 0xdf, 0xfc, 0xd7, 0x6f, 0xf6, 0x83, 0x81, 0x66, 0x1f, 0xa2, 0x00, 0x57, 0x88, 0xa8, 0x72, - 0x66, 0x5c, 0xc3, 0xae, 0xb8, 0xc7, 0xf6, 0x38, 0xe5, 0x7c, 0x5f, 0x9b, 0x50, 0x6e, 0xb3, 0x98, 0x36, 0x2b, 0x57, - 0x57, 0x38, 0x13, 0xdd, 0xfa, 0x86, 0x5d, 0x08, 0xc9, 0xf2, 0xed, 0x5d, 0xc0, 0x43, 0x31, 0x2a, 0xec, 0xed, 0xb9, - 0xe7, 0xe5, 0xc0, 0x9f, 0xa1, 0xbc, 0xc6, 0x4b, 0xab, 0xdf, 0xfa, 0x5c, 0xec, 0xa1, 0x0f, 0x78, 0x33, 0x7e, 0x2b, - 0xa8, 0xce, 0x7c, 0x16, 0x9a, 0x2c, 0x2e, 0xc4, 0x97, 0xba, 0xc1, 0x25, 0xf4, 0x32, 0xc7, 0x64, 0x03, 0x5f, 0x3a, - 0x5c, 0x55, 0xc8, 0x3c, 0xb4, 0x64, 0x94, 0x47, 0x6c, 0x39, 0x31, 0x73, 0xb7, 0x9a, 0x64, 0x5a, 0x99, 0x1f, 0xdd, - 0xc8, 0xc1, 0x83, 0x12, 0x92, 0x74, 0x65, 0x08, 0xff, 0x18, 0x27, 0xee, 0x45, 0xb0, 0xf1, 0x5e, 0x58, 0x8b, 0x76, - 0xf5, 0x50, 0x35, 0xeb, 0x26, 0x68, 0xd6, 0xa9, 0x1e, 0xef, 0x84, 0xbf, 0xa7, 0x7f, 0x3c, 0xd3, 0x46, 0xf8, 0xf3, - 0x99, 0x56, 0xc2, 0x1f, 0xa7, 0x8a, 0x09, 0x7f, 0x9e, 0xea, 0xcc, 0xd4, 0xfa, 0xc2, 0xbe, 0x7e, 0x63, 0x5f, 0xdf, - 0xd9, 0x63, 0xa0, 0xf6, 0xd0, 0xde, 0xcb, 0x1c, 0xb4, 0x13, 0x7b, 0x5b, 0x6f, 0xc9, 0x21, 0x9f, 0xcb, 0x2a, 0x4b, - 0x36, 0x3f, 0x37, 0xba, 0xfb, 0x9c, 0xca, 0xc2, 0xe3, 0x01, 0xca, 0x1a, 0x8f, 0xa3, 0xba, 0x16, 0x51, 0x31, 0x67, - 0x96, 0xb4, 0x5e, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x4e, 0x1c, 0x43, 0x0e, 0xaa, 0x86, 0x33, 0x52, 0x99, 0x20, 0x7f, - 0x34, 0xfd, 0xd8, 0x28, 0xf7, 0xa2, 0xf1, 0xc2, 0xdd, 0x3d, 0x53, 0x9e, 0xbf, 0x92, 0x46, 0x44, 0xa6, 0x15, 0xf8, - 0xde, 0xc1, 0x34, 0x2c, 0x66, 0x2d, 0x36, 0x3b, 0x20, 0xb3, 0x23, 0x7a, 0x09, 0x05, 0x42, 0xe8, 0xdb, 0x16, 0xfe, - 0xb3, 0x00, 0xa5, 0x62, 0x57, 0x46, 0x89, 0x78, 0x5c, 0x83, 0xa2, 0xd6, 0x5b, 0xd0, 0x20, 0x76, 0x43, 0x99, 0xee, - 0x88, 0x31, 0x87, 0x97, 0x55, 0x5c, 0x41, 0x56, 0xbf, 0x9c, 0x8b, 0x5f, 0xe7, 0xec, 0xe1, 0xf9, 0x46, 0x40, 0x83, - 0xff, 0xd7, 0x64, 0x3b, 0xe8, 0x4f, 0x68, 0x6b, 0x9c, 0x72, 0x49, 0xa5, 0xfd, 0x42, 0xce, 0xdb, 0x73, 0x5f, 0x67, - 0xd7, 0xb7, 0xce, 0x18, 0xc9, 0xcf, 0x39, 0x04, 0x72, 0x57, 0xed, 0xa7, 0xbb, 0x7d, 0x4c, 0x41, 0x56, 0x5d, 0xf7, - 0x9c, 0x60, 0x9d, 0x9d, 0xa9, 0xd4, 0xcd, 0x94, 0xfc, 0xfc, 0xd5, 0xff, 0xb2, 0xbf, 0x4f, 0xc9, 0x87, 0x7d, 0xad, - 0xd7, 0xfc, 0x72, 0x2c, 0xe7, 0x53, 0xaf, 0xf3, 0xf9, 0xfd, 0x17, 0xe5, 0x74, 0x3d, 0xa4, 0xe9, 0x38, 0xdd, 0xf5, - 0x8f, 0xe9, 0x82, 0x7e, 0xe9, 0x3e, 0x9b, 0xfe, 0x7a, 0x4a, 0x3e, 0xe4, 0x1b, 0xbd, 0x7e, 0x72, 0x97, 0x16, 0xff, - 0xa9, 0xe9, 0x72, 0x64, 0x0b, 0x00, 0xe5, 0xf9, 0x51, 0xb2, 0x39, 0x0e, 0x39, 0xd3, 0x3b, 0xd7, 0x15, 0xb6, 0xa8, - 0x5a, 0x0d, 0x8e, 0x5c, 0xac, 0x40, 0x8b, 0x7c, 0xc2, 0x13, 0xd9, 0xf8, 0x06, 0xec, 0x52, 0x66, 0xef, 0xb1, 0x0a, - 0xa4, 0xdb, 0xe6, 0xd3, 0x6c, 0x26, 0xcf, 0x5f, 0xa3, 0x6d, 0x76, 0x0d, 0xcb, 0x4c, 0xda, 0xd2, 0x54, 0x5c, 0x79, - 0xc0, 0x81, 0x03, 0x14, 0x06, 0xab, 0x91, 0x3a, 0x00, 0x46, 0x4e, 0xef, 0x30, 0xf4, 0xd9, 0x38, 0xce, 0xde, 0x6f, - 0x63, 0xc6, 0x52, 0x78, 0xec, 0xc8, 0xa2, 0x19, 0xed, 0xf0, 0x09, 0x37, 0xfd, 0x69, 0x26, 0xd4, 0x8f, 0x06, 0xe0, - 0xc4, 0x59, 0x36, 0x5d, 0x7f, 0xbb, 0x4f, 0x3c, 0xeb, 0x5a, 0xae, 0xac, 0x3f, 0x94, 0xd0, 0xb5, 0x39, 0x3a, 0x93, - 0xdc, 0x25, 0xa8, 0x30, 0xc2, 0x9c, 0xe1, 0xc5, 0x7b, 0xb3, 0x3a, 0xa5, 0x48, 0x7d, 0xa2, 0xd7, 0x82, 0x90, 0xd1, - 0x7f, 0x32, 0x98, 0xc6, 0x91, 0x1c, 0xb9, 0x3e, 0xf6, 0xef, 0x31, 0x43, 0xdb, 0xcc, 0xa8, 0xb7, 0x1a, 0x3b, 0x20, - 0xd2, 0xc0, 0x2a, 0x59, 0x63, 0x7d, 0x4b, 0xfc, 0x6b, 0x90, 0xeb, 0x34, 0x6b, 0x3c, 0xc3, 0xd9, 0x99, 0xb6, 0x27, - 0x3b, 0xdd, 0xcc, 0xdc, 0xaf, 0xb7, 0x3f, 0x8f, 0xdf, 0xdb, 0xef, 0x87, 0x71, 0xe9, 0x48, 0x0b, 0x72, 0xd3, 0x62, - 0xab, 0x7a, 0x6c, 0x9d, 0x4c, 0xcb, 0x0f, 0xd5, 0x8f, 0x0d, 0x0a, 0xc4, 0x18, 0xe7, 0x35, 0xd2, 0x8c, 0xcf, 0xf2, - 0x36, 0x2e, 0xc8, 0x82, 0x0d, 0x71, 0x3e, 0xdc, 0xde, 0x3e, 0x0a, 0xb2, 0x03, 0x4d, 0x7e, 0xf3, 0x0e, 0xdd, 0xd7, - 0x7e, 0xe7, 0x77, 0xa0, 0x98, 0xf5, 0xed, 0x25, 0xd5, 0x06, 0x75, 0x05, 0x7a, 0x03, 0x2e, 0xbf, 0x68, 0x13, 0xe6, - 0xae, 0xe1, 0xbc, 0xfc, 0x19, 0x0b, 0x49, 0x28, 0x5a, 0x29, 0x38, 0x2c, 0x36, 0xcd, 0x28, 0x4a, 0x8b, 0x75, 0xd1, - 0xaf, 0x6d, 0xc6, 0x9b, 0x6b, 0x37, 0x70, 0x6e, 0x10, 0x64, 0x31, 0x6b, 0x45, 0x3f, 0x46, 0xe4, 0x5d, 0xd6, 0xcc, - 0x56, 0xdb, 0x40, 0x0c, 0x2f, 0x71, 0xcd, 0x5a, 0x6c, 0x77, 0xcf, 0x60, 0x40, 0x8f, 0xf8, 0xe8, 0x1c, 0x82, 0x47, - 0x1e, 0x7a, 0x2c, 0x7e, 0x37, 0xa5, 0xc3, 0x3b, 0xc7, 0x5a, 0x0a, 0x91, 0xe5, 0x64, 0xfa, 0xc7, 0xa9, 0xcd, 0xc8, - 0xd3, 0x11, 0x25, 0x43, 0xa2, 0xfa, 0xc6, 0x3e, 0xfb, 0xd1, 0x20, 0xad, 0x3d, 0x9b, 0x35, 0x8e, 0x17, 0x2c, 0xad, - 0x0f, 0x8e, 0x87, 0x71, 0x1c, 0xa4, 0xa8, 0xa9, 0xac, 0xe2, 0x1f, 0x93, 0x61, 0x91, 0xae, 0xd9, 0x7e, 0x57, 0x06, - 0xaf, 0x84, 0x84, 0xae, 0x5c, 0x7b, 0x2d, 0x40, 0xc7, 0x2e, 0x6b, 0xf9, 0x33, 0xa7, 0x0b, 0x01, 0x2a, 0xbf, 0x08, - 0x93, 0x00, 0x43, 0x24, 0xca, 0x13, 0x79, 0xe1, 0x45, 0xd1, 0x47, 0x30, 0x87, 0x66, 0x58, 0x0d, 0xa6, 0xa9, 0xe8, - 0xaf, 0xd7, 0x99, 0x50, 0xc6, 0x01, 0xbc, 0xc8, 0xed, 0xcd, 0xc7, 0x32, 0x74, 0x28, 0xd2, 0x46, 0xce, 0x3c, 0x33, - 0xa7, 0xbc, 0xa1, 0x3e, 0x14, 0xa1, 0xf8, 0x4f, 0x30, 0x48, 0x72, 0x36, 0x00, 0x85, 0xac, 0x3d, 0x8f, 0x00, 0x60, - 0x49, 0x3f, 0x31, 0x03, 0x6f, 0xf8, 0xa7, 0xb3, 0xf1, 0x65, 0x91, 0xb1, 0x5f, 0xfd, 0x9b, 0x4b, 0xd3, 0x2c, 0xdc, - 0x59, 0xd5, 0xb3, 0x7b, 0x8a, 0x20, 0x0a, 0x24, 0x59, 0x28, 0x27, 0xf6, 0x1e, 0xe2, 0x57, 0x06, 0x98, 0x41, 0x48, - 0x06, 0x48, 0xc2, 0x74, 0xa4, 0x75, 0xe6, 0x27, 0xd7, 0x84, 0xad, 0xde, 0x16, 0x4a, 0xb0, 0x88, 0xce, 0xa3, 0xdb, - 0x2a, 0xcd, 0x5a, 0xba, 0x1f, 0xf6, 0xe6, 0x20, 0xe3, 0xe4, 0xcb, 0xca, 0x79, 0xe2, 0x3c, 0x7f, 0x43, 0x22, 0x7b, - 0x11, 0x51, 0x5e, 0x6e, 0x5d, 0x44, 0x7e, 0x05, 0xa5, 0x62, 0x03, 0xa0, 0x1a, 0x09, 0x53, 0x4d, 0xf1, 0xee, 0x17, - 0x77, 0xc0, 0x28, 0x1f, 0x68, 0x4f, 0x28, 0xee, 0x27, 0x2b, 0x63, 0x3d, 0xcc, 0x83, 0xcc, 0x22, 0x2e, 0x57, 0xa3, - 0xcd, 0x4e, 0x68, 0xa4, 0x5e, 0xd1, 0x04, 0x03, 0x1a, 0x96, 0xe1, 0x74, 0x6a, 0xeb, 0x1f, 0x05, 0xcb, 0x6c, 0xba, - 0x4e, 0xcf, 0x71, 0x29, 0x74, 0x5b, 0xf7, 0x49, 0x21, 0x8e, 0x86, 0xd0, 0xed, 0x28, 0x14, 0x46, 0x3f, 0xab, 0xf0, - 0xa2, 0x3e, 0xeb, 0xd7, 0xa2, 0x33, 0xd6, 0x98, 0xa1, 0xab, 0x2e, 0xbb, 0xa1, 0x00, 0x6c, 0xc4, 0xce, 0x10, 0x05, - 0x72, 0x7b, 0xd5, 0x2e, 0xd7, 0x70, 0x2f, 0x62, 0xf2, 0x1f, 0x5a, 0xef, 0x37, 0xda, 0x4f, 0xe0, 0x8f, 0x92, 0xcc, - 0xad, 0x09, 0xac, 0xa9, 0x9c, 0x97, 0xc4, 0x01, 0xd1, 0xe3, 0x7c, 0x3f, 0x08, 0xfe, 0xa4, 0xb5, 0x78, 0x50, 0x6c, - 0x11, 0xd2, 0x4a, 0xa9, 0x13, 0xf5, 0xda, 0x3a, 0x4d, 0xe4, 0x83, 0xc4, 0xa4, 0x62, 0x42, 0x75, 0x5a, 0xfb, 0x69, - 0x5e, 0xab, 0x59, 0xe0, 0x6d, 0xa2, 0x12, 0xaf, 0x30, 0x9d, 0xdb, 0x25, 0x43, 0xd2, 0x1d, 0xc1, 0xa9, 0x2e, 0x2b, - 0x86, 0xbb, 0xdb, 0xd6, 0xec, 0x17, 0x03, 0x5f, 0xd3, 0x35, 0x1c, 0xe3, 0x2e, 0xe8, 0xdc, 0x18, 0x6f, 0x88, 0xed, - 0xc1, 0xe0, 0x61, 0xf5, 0xe4, 0xec, 0xb4, 0x9a, 0x6e, 0x1a, 0x95, 0xb9, 0xb9, 0xd7, 0xd4, 0xd5, 0x42, 0xbf, 0x4a, - 0x60, 0xf9, 0x6c, 0x94, 0x6f, 0xb1, 0x67, 0xae, 0x51, 0x60, 0x6b, 0x89, 0xbb, 0x65, 0xd9, 0xb1, 0x18, 0xbd, 0x1b, - 0x18, 0x15, 0xd6, 0x2e, 0x62, 0xf0, 0xfc, 0x1c, 0xf6, 0xf6, 0xc4, 0x04, 0x42, 0xfd, 0x9b, 0x7a, 0xb2, 0x80, 0x8b, - 0x59, 0x1a, 0xc9, 0xb0, 0x1e, 0x94, 0xbd, 0x27, 0x5a, 0xfa, 0x88, 0xe7, 0x82, 0x60, 0xdb, 0x76, 0x8a, 0xad, 0x6b, - 0x18, 0x03, 0x1f, 0xba, 0xc6, 0x1d, 0x04, 0xd7, 0xec, 0x56, 0x34, 0xcf, 0xe0, 0x31, 0x88, 0x39, 0x30, 0xc2, 0x7c, - 0x5e, 0xaa, 0xba, 0x7d, 0xa2, 0xb3, 0xff, 0x02, 0x42, 0x31, 0xbb, 0xd5, 0xe5, 0xd6, 0x69, 0xe3, 0x21, 0x43, 0x16, - 0x64, 0x2c, 0x49, 0x8a, 0x8c, 0xfc, 0xa6, 0xa3, 0x2d, 0x63, 0xd1, 0x33, 0x97, 0x71, 0x4b, 0x6a, 0x42, 0xa9, 0xce, - 0xa6, 0x21, 0x51, 0x5e, 0x8f, 0xb0, 0xa8, 0x42, 0xec, 0x36, 0x87, 0x54, 0xce, 0x5c, 0x11, 0x99, 0xe2, 0x49, 0xda, - 0x66, 0x67, 0xb0, 0x46, 0x90, 0xa1, 0x60, 0x82, 0xaa, 0xf6, 0xfd, 0xe8, 0xfe, 0x86, 0x79, 0x30, 0xa6, 0xa9, 0x7a, - 0x78, 0xc3, 0x94, 0x89, 0xf0, 0x24, 0x6d, 0x6f, 0x3b, 0x62, 0xdb, 0xba, 0x8e, 0xf3, 0xec, 0x7b, 0xf2, 0x56, 0x8e, - 0x2c, 0xd9, 0x9a, 0xb2, 0x35, 0x15, 0xfb, 0xa0, 0x16, 0x15, 0x65, 0x28, 0x91, 0x48, 0x60, 0x2b, 0xea, 0xed, 0xa5, - 0x3a, 0x1b, 0x88, 0xf4, 0xca, 0x7a, 0xbf, 0x26, 0xcf, 0xe9, 0xda, 0x4a, 0x29, 0x58, 0x40, 0x21, 0x2c, 0x34, 0xf6, - 0xac, 0xef, 0x7f, 0x9c, 0xd7, 0xb0, 0x1f, 0x7e, 0xcc, 0x88, 0x2d, 0xfc, 0xea, 0xfd, 0x7a, 0x82, 0x01, 0x46, 0xdd, - 0x8b, 0xae, 0x48, 0xdf, 0x1b, 0xfa, 0x1e, 0xe9, 0xbb, 0xaf, 0xef, 0x66, 0x3f, 0xd0, 0x35, 0xd6, 0x86, 0x37, 0xee, - 0xdc, 0x42, 0xeb, 0x88, 0x2f, 0xb1, 0xd4, 0x41, 0x7f, 0x5b, 0x7e, 0x9a, 0xa8, 0xb2, 0x5f, 0x5b, 0x49, 0x29, 0x9b, - 0xbe, 0x24, 0x55, 0x1b, 0xba, 0x8c, 0x90, 0xba, 0x57, 0x82, 0xb7, 0x6f, 0x9d, 0xba, 0xba, 0x2d, 0xe5, 0xa7, 0xe3, - 0x62, 0xfc, 0xf2, 0xaf, 0x0e, 0xf1, 0x52, 0xc6, 0x74, 0xe8, 0xca, 0x3b, 0xef, 0xd9, 0x4a, 0x8d, 0x2b, 0xcc, 0x09, - 0xe7, 0x78, 0xb2, 0x90, 0x31, 0xea, 0xa1, 0xdc, 0xb9, 0x03, 0x2e, 0x23, 0x08, 0x7c, 0x45, 0x57, 0x55, 0x8a, 0x59, - 0xea, 0x3b, 0x06, 0x96, 0xf9, 0x3e, 0xd1, 0xe5, 0xf0, 0xf7, 0x02, 0x09, 0x7d, 0xea, 0xaa, 0x72, 0xed, 0x4a, 0x35, - 0x62, 0x6c, 0x8a, 0x24, 0xe7, 0x64, 0xbd, 0xcb, 0x8b, 0xbc, 0xf0, 0xd7, 0xd3, 0xaa, 0xa6, 0x03, 0x52, 0xcc, 0x4a, - 0x2c, 0xca, 0xa9, 0x58, 0x94, 0x22, 0x62, 0xfb, 0x12, 0x86, 0xca, 0x66, 0x12, 0x88, 0xbc, 0xb7, 0x73, 0x91, 0x58, - 0xbe, 0x02, 0x18, 0xac, 0xaa, 0x0f, 0x84, 0xe4, 0x77, 0x76, 0xd9, 0x25, 0x3f, 0xf6, 0x57, 0x4a, 0x26, 0x93, 0x56, - 0x18, 0x02, 0x77, 0xc4, 0x6f, 0x9f, 0x0e, 0x18, 0x13, 0x9c, 0x33, 0xda, 0x18, 0x30, 0xe7, 0xa6, 0x69, 0x48, 0xaa, - 0x9a, 0xb5, 0xca, 0xdd, 0xbc, 0xc2, 0x4c, 0x48, 0x62, 0xa8, 0xca, 0xcd, 0xf0, 0x6b, 0x3d, 0x52, 0x90, 0xf3, 0xf7, - 0x5c, 0x5d, 0x90, 0x31, 0x2a, 0x67, 0x3a, 0x99, 0x04, 0x5f, 0x07, 0xf0, 0x01, 0x73, 0x2b, 0x3e, 0xf8, 0xc7, 0x59, - 0xca, 0x23, 0x1b, 0xd0, 0x03, 0xb5, 0x43, 0x35, 0x56, 0x2d, 0x25, 0x0a, 0x13, 0x09, 0xa1, 0x0c, 0x3e, 0xe2, 0x33, - 0x99, 0x8b, 0x39, 0xab, 0xfb, 0x5c, 0x2c, 0xdb, 0x0e, 0x24, 0x06, 0x44, 0x99, 0x10, 0x49, 0x4e, 0x6a, 0xdd, 0x50, - 0x61, 0x71, 0x74, 0x69, 0xb1, 0x88, 0x13, 0x24, 0xd3, 0x7a, 0x21, 0xf8, 0x97, 0x1d, 0x5b, 0xc9, 0xf1, 0xa6, 0xff, - 0x66, 0x34, 0x57, 0x23, 0x33, 0xd9, 0x45, 0x6b, 0x5e, 0xf4, 0x8b, 0xb4, 0xe6, 0xf2, 0x21, 0x51, 0xe8, 0x1f, 0x68, - 0xdd, 0x5b, 0xd6, 0x10, 0x29, 0x58, 0xd2, 0x15, 0x7d, 0x45, 0xdb, 0x5d, 0x7a, 0x59, 0xe0, 0x71, 0xf7, 0x31, 0x41, - 0x82, 0xef, 0xb6, 0x8a, 0x97, 0xc0, 0x45, 0xb2, 0xc6, 0x9e, 0xfb, 0x44, 0x16, 0x1d, 0xd3, 0x8d, 0xd2, 0xd5, 0x91, - 0x9d, 0xd3, 0x37, 0x88, 0x92, 0x9c, 0x5d, 0x2b, 0x31, 0xf5, 0x3f, 0x47, 0xdd, 0xe4, 0xa2, 0xb2, 0x67, 0x87, 0x1c, - 0xc4, 0xcd, 0xd4, 0x42, 0x98, 0x92, 0xbd, 0x13, 0xd8, 0x08, 0x91, 0x91, 0x62, 0x52, 0x04, 0x25, 0xf7, 0x92, 0x2f, - 0x89, 0x14, 0xf2, 0x47, 0xa5, 0x86, 0xb6, 0x4c, 0xe9, 0x7f, 0xb4, 0x8e, 0xf0, 0xed, 0x0c, 0x27, 0x49, 0xf9, 0xe4, - 0x05, 0xb7, 0xad, 0xdd, 0x8e, 0xd9, 0x20, 0x09, 0xf7, 0xcf, 0x2c, 0x9f, 0xf5, 0xf6, 0x20, 0xff, 0x50, 0x26, 0x04, - 0x78, 0xeb, 0x9b, 0x5e, 0xd5, 0x2f, 0x01, 0xa3, 0x92, 0x6a, 0x51, 0x79, 0x3b, 0x39, 0x97, 0x38, 0xe5, 0xf2, 0x02, - 0x7e, 0xf9, 0x7e, 0xce, 0x81, 0x79, 0xf8, 0x4a, 0x5b, 0x4d, 0x14, 0xec, 0x87, 0xc3, 0x1e, 0x43, 0xc9, 0x0a, 0x1b, - 0xd9, 0xcd, 0xc6, 0xb8, 0x0b, 0x5d, 0x6b, 0xb3, 0x7e, 0x0a, 0xa9, 0x57, 0x77, 0x9c, 0xde, 0xc5, 0x55, 0x8d, 0x34, - 0xb7, 0x69, 0xc4, 0x51, 0xc9, 0x4c, 0x07, 0x72, 0x87, 0x69, 0x3a, 0x66, 0x6f, 0x23, 0xc1, 0xf2, 0xcd, 0x59, 0x5b, - 0x79, 0x2b, 0xef, 0x49, 0x08, 0x98, 0x70, 0xc0, 0x5c, 0xd1, 0xb0, 0x56, 0x0e, 0x82, 0x39, 0xf6, 0x7b, 0xad, 0x90, - 0x98, 0xaa, 0x48, 0x7a, 0x36, 0xf1, 0xb9, 0x56, 0x6b, 0xcf, 0x1a, 0x09, 0x59, 0x3a, 0x05, 0x8e, 0x35, 0x4f, 0x14, - 0x0c, 0x65, 0x6a, 0x56, 0xcb, 0x3c, 0xe0, 0x2a, 0x7b, 0xae, 0xe5, 0x95, 0x40, 0x0c, 0x1c, 0x14, 0x90, 0x9c, 0xf8, - 0x1e, 0xee, 0x49, 0xec, 0x3b, 0x73, 0x86, 0xc6, 0x4c, 0x86, 0xa8, 0xce, 0x4a, 0x15, 0x58, 0xd7, 0xdb, 0xc0, 0x54, - 0x51, 0x6b, 0x6e, 0xe8, 0x9e, 0x0c, 0xd6, 0xd7, 0x38, 0x3c, 0x10, 0xf6, 0xf8, 0x82, 0xdc, 0x87, 0xbf, 0xcf, 0xca, - 0x63, 0x67, 0x0b, 0x68, 0xc0, 0x7a, 0xf3, 0x1c, 0x39, 0xa2, 0xeb, 0x2d, 0x95, 0x2b, 0x5b, 0xd0, 0x65, 0xaf, 0xe9, - 0xfd, 0xd3, 0x41, 0x75, 0xb9, 0xdc, 0xcc, 0x8c, 0xa8, 0xe2, 0xc9, 0x24, 0x09, 0xfa, 0x10, 0x33, 0x28, 0xa9, 0x79, - 0x2a, 0xeb, 0x88, 0x89, 0x7b, 0xb0, 0xbc, 0x23, 0x13, 0xd3, 0x25, 0x98, 0xe3, 0x9c, 0xad, 0x8b, 0x06, 0x87, 0x1c, - 0x0e, 0x58, 0xa2, 0x4b, 0x1e, 0xdc, 0xfb, 0x56, 0x56, 0x6a, 0xd1, 0x97, 0x63, 0xa9, 0x84, 0xdc, 0x00, 0x36, 0x76, - 0xb4, 0x93, 0x0b, 0xe5, 0xd4, 0x4e, 0x10, 0xec, 0xe4, 0xa6, 0xf6, 0x0e, 0x49, 0x06, 0xc8, 0x1e, 0x08, 0x55, 0x19, - 0xf0, 0x79, 0x5d, 0x11, 0x00, 0x9a, 0xe3, 0x12, 0x89, 0x3f, 0x08, 0xe3, 0xe5, 0x37, 0x8a, 0x41, 0x83, 0xe3, 0x6e, - 0x66, 0x38, 0x78, 0x1d, 0xc0, 0x28, 0x8d, 0x12, 0xf3, 0x23, 0x10, 0xe5, 0x62, 0x7f, 0x95, 0x18, 0x1d, 0x29, 0x44, - 0x38, 0xf4, 0x8b, 0xdd, 0x85, 0xb4, 0xf5, 0x16, 0x6c, 0x65, 0x36, 0x2b, 0xb3, 0x5d, 0x03, 0x68, 0x1f, 0xa9, 0x01, - 0xd0, 0x66, 0xc3, 0x43, 0x3f, 0x37, 0xdd, 0x67, 0x3e, 0x43, 0xf7, 0x8e, 0x22, 0xf0, 0xeb, 0x32, 0x35, 0xdf, 0xc2, - 0x05, 0x4c, 0x33, 0xf5, 0x5e, 0x5e, 0x2d, 0xf7, 0x75, 0xb7, 0x63, 0x20, 0xbc, 0x5c, 0x62, 0x8f, 0xf8, 0x29, 0xab, - 0xe2, 0xa0, 0xc7, 0x1c, 0xbd, 0x46, 0x90, 0x66, 0x66, 0x69, 0xc8, 0x73, 0x0b, 0xe5, 0x33, 0x92, 0x03, 0xf9, 0x98, - 0x2c, 0x0f, 0xd9, 0xcb, 0x70, 0xe5, 0xa1, 0xae, 0x23, 0x24, 0x55, 0x90, 0x7a, 0x02, 0xcf, 0xd5, 0x0c, 0xc2, 0xb2, - 0x8f, 0xe7, 0xc4, 0xdc, 0xf3, 0xb7, 0x29, 0x68, 0xe4, 0x40, 0xa5, 0xf3, 0x93, 0xb2, 0x80, 0xdc, 0x43, 0x1d, 0xa6, - 0x98, 0xf1, 0xa0, 0x97, 0x5d, 0x95, 0x64, 0x38, 0x1a, 0xa1, 0xf1, 0x84, 0x82, 0xe4, 0x05, 0xc1, 0xd1, 0x57, 0x4b, - 0xe5, 0xaf, 0x24, 0xe5, 0x4d, 0x56, 0x96, 0x0d, 0xee, 0x25, 0x5e, 0x64, 0x0d, 0x9c, 0x59, 0xd8, 0xd1, 0xa6, 0xac, - 0x19, 0x13, 0x04, 0x80, 0x0f, 0x87, 0xe0, 0xc8, 0x22, 0x62, 0x59, 0x44, 0x13, 0xc5, 0x38, 0x96, 0x3f, 0x7b, 0xf8, - 0xa6, 0x08, 0xae, 0xd7, 0x91, 0xa0, 0x85, 0xc0, 0x27, 0x0e, 0xc0, 0x33, 0x33, 0x88, 0x78, 0xb6, 0xda, 0x3c, 0x02, - 0x13, 0xa9, 0xb5, 0x1f, 0x8d, 0xf8, 0x84, 0x13, 0xe7, 0xb8, 0x44, 0x1a, 0xb9, 0x5d, 0x8b, 0xc3, 0x21, 0x91, 0x89, - 0x9d, 0x39, 0xf2, 0xb1, 0xf1, 0x5d, 0x91, 0xff, 0x65, 0x16, 0x3d, 0x29, 0x51, 0x73, 0x39, 0x52, 0xbc, 0x69, 0x1b, - 0xa2, 0x55, 0xc6, 0xb5, 0xf4, 0x72, 0x98, 0x30, 0x58, 0xc0, 0xfe, 0xdf, 0x7c, 0x30, 0x1a, 0x8d, 0x95, 0xf3, 0x31, - 0xb8, 0xe2, 0x21, 0x3a, 0x6c, 0x38, 0x6a, 0x7d, 0xdd, 0x34, 0x99, 0x93, 0x0f, 0xfb, 0x6f, 0x7b, 0xb3, 0xeb, 0x6e, - 0x23, 0xea, 0x5c, 0x4a, 0x73, 0xe6, 0x85, 0xd0, 0x87, 0x91, 0xd5, 0x8b, 0x35, 0xe6, 0x84, 0xe6, 0x97, 0x8e, 0xa8, - 0x56, 0x1c, 0x9e, 0x3e, 0x08, 0xc5, 0xcb, 0xd1, 0x3e, 0xc4, 0x01, 0xb1, 0xa1, 0x44, 0xd9, 0x33, 0x95, 0x90, 0xc6, - 0x31, 0xb0, 0x5e, 0x85, 0x83, 0x40, 0xe0, 0xb4, 0x61, 0xbb, 0x66, 0xfd, 0x16, 0x2b, 0x4a, 0xc8, 0x21, 0xd5, 0x64, - 0xd9, 0x8c, 0x1f, 0x62, 0x47, 0x13, 0x94, 0x48, 0x29, 0x5a, 0x36, 0xfd, 0xc3, 0xb6, 0x23, 0x07, 0x2f, 0xa1, 0x21, - 0x71, 0x04, 0x2f, 0xbd, 0xf3, 0x87, 0xfd, 0x37, 0xeb, 0x23, 0xcf, 0x51, 0xbf, 0xe5, 0x21, 0xdf, 0xf2, 0x1c, 0xed, - 0x43, 0x1e, 0xf2, 0x21, 0xcf, 0x11, 0x3f, 0xe4, 0x41, 0xb2, 0x38, 0x4f, 0x5f, 0xdb, 0x7f, 0x0e, 0xc7, 0x4c, 0xa1, - 0x5c, 0x9e, 0x89, 0xad, 0xe4, 0xe8, 0x17, 0x1f, 0x32, 0xee, 0xb3, 0x89, 0x94, 0x3c, 0x21, 0x5e, 0x89, 0x12, 0x97, - 0xac, 0x2c, 0x93, 0x02, 0xf8, 0x34, 0xc4, 0xa7, 0x37, 0xdb, 0x77, 0xfc, 0x23, 0xac, 0x51, 0x74, 0x26, 0xe2, 0xc5, - 0x98, 0x8c, 0xd3, 0x3d, 0x73, 0xeb, 0x85, 0xad, 0x89, 0x90, 0x2c, 0x67, 0x04, 0x6d, 0x08, 0x71, 0xc8, 0x88, 0x91, - 0xcb, 0xf9, 0x64, 0xb4, 0xc4, 0xd0, 0xb7, 0xef, 0xa2, 0xd7, 0xcc, 0xfe, 0x1c, 0x03, 0x48, 0x95, 0xe7, 0x06, 0x64, - 0xe0, 0x18, 0x7b, 0xf5, 0x31, 0xd6, 0xa7, 0xe7, 0x45, 0x15, 0x0d, 0xba, 0x26, 0x87, 0x63, 0x4e, 0x90, 0x64, 0xa4, - 0x7f, 0xc5, 0xba, 0xec, 0x2c, 0x5d, 0x36, 0xaf, 0xc2, 0x3d, 0x61, 0xbe, 0x04, 0xb4, 0x28, 0x21, 0xd5, 0xcc, 0x72, - 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xa4, 0xc9, 0x52, 0x6d, 0x97, 0x85, 0xbb, 0xec, 0xf1, 0x0b, 0xfe, 0xe1, 0x9e, - 0xe6, 0x66, 0x91, 0x41, 0xfb, 0x22, 0x67, 0xf7, 0xde, 0x15, 0xb6, 0xb5, 0x06, 0xf3, 0x13, 0x29, 0xd6, 0x22, 0x7c, - 0x35, 0xa6, 0x17, 0xa4, 0x3d, 0x7c, 0x83, 0x22, 0x1a, 0xdf, 0x67, 0x13, 0x5b, 0x86, 0xf6, 0x96, 0x7c, 0x6d, 0xa9, - 0xc9, 0x66, 0xc5, 0x1a, 0x2c, 0xb9, 0xfd, 0xf6, 0x25, 0xb5, 0x43, 0x97, 0xb9, 0x28, 0xb2, 0x49, 0x75, 0x53, 0xac, - 0x4d, 0x81, 0x2f, 0xc9, 0x56, 0x84, 0x8e, 0x40, 0x51, 0xb9, 0xcb, 0xe2, 0x70, 0xb9, 0xaa, 0xe5, 0xd4, 0x94, 0x10, - 0x69, 0xc8, 0x2a, 0xcc, 0xf4, 0x52, 0x7c, 0xbc, 0x38, 0x14, 0x21, 0xe5, 0x28, 0xa1, 0x33, 0xb5, 0x9c, 0xae, 0x6b, - 0xf5, 0xb7, 0x50, 0xe0, 0xe0, 0x4b, 0x5e, 0x43, 0x2c, 0x61, 0xa9, 0x6a, 0x0e, 0x11, 0x67, 0x9e, 0xdd, 0xd0, 0x95, - 0x87, 0xfd, 0xf7, 0x21, 0x04, 0x79, 0xb1, 0xfd, 0x94, 0xae, 0x5d, 0x9f, 0x91, 0x49, 0x20, 0x91, 0x84, 0x02, 0x80, - 0x03, 0x00, 0xae, 0x7a, 0x05, 0xab, 0x02, 0x93, 0x5e, 0xab, 0xc0, 0xc0, 0x14, 0x3c, 0x41, 0x99, 0xa1, 0x1d, 0xe0, - 0xf2, 0x47, 0xa4, 0xf4, 0xda, 0x21, 0x5b, 0x4c, 0x04, 0x34, 0x94, 0xc0, 0x31, 0xa1, 0xdd, 0x16, 0xe3, 0xe5, 0x25, - 0x0a, 0x2f, 0x89, 0xd2, 0x51, 0xdb, 0x02, 0x34, 0x90, 0x57, 0xb3, 0x2c, 0x9c, 0x96, 0x91, 0xe7, 0x6b, 0x13, 0xde, - 0xf2, 0x76, 0x5d, 0x6e, 0x3f, 0xb2, 0x35, 0x4d, 0x21, 0x1b, 0x82, 0x7d, 0xcf, 0xd6, 0x3d, 0x63, 0xa8, 0x10, 0x6f, - 0xb1, 0x1c, 0x7a, 0xe3, 0xba, 0x56, 0x1b, 0xd2, 0x87, 0x3e, 0x7a, 0x28, 0xba, 0x72, 0x37, 0x8c, 0x04, 0x5a, 0x4b, - 0x04, 0xab, 0xe1, 0x39, 0x03, 0xed, 0x26, 0x2f, 0x25, 0x47, 0x41, 0xaa, 0x02, 0x1f, 0xd2, 0xcd, 0x37, 0x2c, 0x66, - 0xb0, 0xeb, 0x36, 0x0b, 0xe4, 0x6a, 0xa0, 0xf5, 0xf1, 0x3b, 0x0d, 0x7b, 0x7d, 0x02, 0x36, 0x96, 0x2e, 0x57, 0xdb, - 0x2e, 0x8a, 0xa3, 0xe6, 0x8a, 0xe6, 0xae, 0xed, 0x14, 0xfa, 0x73, 0xf1, 0x39, 0xdc, 0x9e, 0x27, 0x8d, 0xef, 0xf3, - 0x13, 0xe1, 0x7b, 0x97, 0x35, 0xde, 0x1b, 0x0d, 0xa8, 0x3f, 0xce, 0xc4, 0x58, 0x8b, 0x1c, 0x15, 0x65, 0xe0, 0xa3, - 0x59, 0x2d, 0xee, 0xa0, 0x29, 0x32, 0xde, 0x6b, 0x04, 0x77, 0x9b, 0x5a, 0x65, 0x70, 0xaf, 0xb5, 0x01, 0x7d, 0x8f, - 0x83, 0xd4, 0xbd, 0x36, 0xda, 0xd9, 0xb9, 0x96, 0xa0, 0x16, 0x23, 0xa3, 0x95, 0x66, 0x63, 0xbb, 0x0d, 0xdd, 0xba, - 0xa5, 0x7e, 0x41, 0x9f, 0xca, 0xc9, 0x81, 0xec, 0xac, 0xae, 0x4a, 0xc5, 0xa4, 0x25, 0x78, 0x8b, 0xeb, 0x7b, 0x65, - 0x4a, 0x64, 0xe0, 0x56, 0x75, 0x99, 0x30, 0x12, 0x07, 0xb0, 0xf8, 0xc8, 0x9d, 0xf1, 0xeb, 0x07, 0xa8, 0x14, 0x1e, - 0x9f, 0x8b, 0x52, 0x78, 0xfc, 0x41, 0xf8, 0x4c, 0x7d, 0x05, 0x91, 0x9a, 0xba, 0xff, 0x32, 0x8f, 0x4a, 0xe5, 0x9b, - 0xbd, 0x6c, 0xec, 0x85, 0x79, 0x1b, 0x40, 0xbe, 0x4d, 0x33, 0x31, 0x98, 0xf9, 0x27, 0x27, 0xba, 0xdb, 0x10, 0x65, - 0x73, 0x0f, 0xd1, 0x7b, 0x45, 0x1d, 0x86, 0x8e, 0xa1, 0x43, 0x91, 0x1a, 0xb7, 0x75, 0x5c, 0x5f, 0xb2, 0x02, 0x9e, - 0xf4, 0xdf, 0x79, 0x7c, 0x52, 0x75, 0xfb, 0x0d, 0x4b, 0x9c, 0x49, 0xa4, 0x92, 0x8a, 0x4d, 0x27, 0xee, 0x2a, 0x35, - 0x59, 0xee, 0xbd, 0xed, 0x90, 0xa0, 0x2d, 0x32, 0xc8, 0x54, 0xef, 0x57, 0x24, 0xce, 0xa1, 0x66, 0x94, 0xa6, 0x82, - 0xa9, 0xac, 0xb2, 0xf2, 0x64, 0xde, 0x9c, 0x7f, 0xc4, 0xa7, 0x34, 0x1e, 0xf0, 0x31, 0x2c, 0x66, 0x23, 0xff, 0x7e, - 0xc4, 0xe8, 0xe8, 0xa6, 0x36, 0xac, 0x52, 0x26, 0x98, 0x56, 0x28, 0xe1, 0x63, 0x05, 0xc1, 0x09, 0x7e, 0x10, 0x4c, - 0x8e, 0x9c, 0x94, 0xac, 0x3c, 0x7e, 0xb3, 0xde, 0x62, 0xf8, 0x38, 0x33, 0xb1, 0xf1, 0x55, 0x9d, 0x69, 0x71, 0x87, - 0xee, 0xae, 0xf0, 0x72, 0xac, 0x4a, 0x86, 0x0b, 0xb2, 0x89, 0xb1, 0x8e, 0xc2, 0x67, 0x24, 0x29, 0x39, 0x91, 0xa7, - 0x74, 0x64, 0x32, 0x13, 0x38, 0x05, 0x67, 0x61, 0xfc, 0xa0, 0x36, 0xae, 0xa4, 0x6f, 0xa1, 0xa7, 0x45, 0xba, 0x3d, - 0x23, 0x0f, 0x76, 0x55, 0xef, 0x51, 0x16, 0x44, 0x19, 0x69, 0x30, 0x42, 0xda, 0xb2, 0xc4, 0xb8, 0x26, 0x62, 0x93, - 0x51, 0x18, 0x65, 0x5a, 0x6b, 0x2d, 0xbb, 0x16, 0x7f, 0x37, 0x54, 0x33, 0x4d, 0xbd, 0x5a, 0x9c, 0xfc, 0xc4, 0x24, - 0xad, 0x19, 0x2e, 0x5b, 0x7c, 0x78, 0xa1, 0xf6, 0xa8, 0x54, 0x07, 0x62, 0x6f, 0x67, 0x14, 0x4a, 0xb7, 0xef, 0x69, - 0x88, 0xa7, 0x46, 0xe7, 0xa5, 0xd3, 0x79, 0x75, 0xaa, 0xba, 0x6f, 0x4c, 0xd4, 0xb6, 0xfb, 0x66, 0x9c, 0xe2, 0x19, - 0xd0, 0x7c, 0x62, 0x04, 0x1d, 0xfa, 0x4f, 0x85, 0x06, 0x61, 0xd1, 0x30, 0xf3, 0xd9, 0x03, 0x18, 0xe9, 0xa6, 0x4c, - 0x6b, 0x46, 0x82, 0x7b, 0x8f, 0x60, 0xe0, 0x31, 0x69, 0x1e, 0xd9, 0x98, 0x4e, 0x18, 0x86, 0xa8, 0xa2, 0x93, 0xb3, - 0xec, 0x73, 0xf3, 0xfb, 0x3d, 0xea, 0xba, 0xdd, 0xb0, 0xa9, 0xe5, 0xbc, 0x87, 0xd3, 0xfb, 0xbf, 0xb9, 0xe8, 0xa4, - 0xbf, 0x9c, 0x5d, 0x5b, 0xe8, 0xc2, 0xe2, 0x7d, 0x1d, 0xf6, 0xbf, 0x91, 0xf9, 0xc8, 0x53, 0xa5, 0x77, 0x18, 0x03, - 0x19, 0x3a, 0xb3, 0x26, 0xca, 0x2f, 0x0c, 0xed, 0x28, 0x24, 0xd9, 0x89, 0xdd, 0x54, 0x4d, 0x90, 0x80, 0x48, 0x8c, - 0xa9, 0xef, 0x1c, 0x0c, 0xb4, 0x53, 0x9d, 0xc5, 0xa4, 0x2d, 0x5f, 0x81, 0x72, 0x5a, 0x06, 0x2c, 0x2f, 0x55, 0x78, - 0x76, 0x1d, 0xd4, 0xd4, 0xc7, 0x09, 0xc5, 0x56, 0x70, 0x3d, 0x64, 0x90, 0xaa, 0x12, 0x42, 0xa7, 0x29, 0x02, 0xbb, - 0x38, 0x36, 0xf1, 0xc7, 0x86, 0xf1, 0x03, 0xac, 0x81, 0xa6, 0xb5, 0xd8, 0xc2, 0x41, 0x52, 0xcc, 0xfc, 0x2d, 0x4d, - 0x8f, 0xab, 0xf4, 0xca, 0x3b, 0x05, 0xd6, 0x26, 0x98, 0xb2, 0x25, 0xb7, 0x6e, 0x2d, 0x42, 0x21, 0x8c, 0x59, 0xd7, - 0x90, 0xca, 0x3b, 0x24, 0x7f, 0x46, 0x16, 0xf0, 0x76, 0xbf, 0x54, 0x48, 0x3d, 0x2b, 0xcc, 0xae, 0x13, 0x74, 0x52, - 0x10, 0x47, 0xba, 0x44, 0xfc, 0xff, 0xca, 0x84, 0x10, 0x7c, 0xda, 0xf0, 0x6d, 0x09, 0x4d, 0x52, 0x9c, 0x5d, 0xb9, - 0x0b, 0x78, 0xec, 0x7a, 0xfd, 0x2c, 0x59, 0xa3, 0xef, 0xf0, 0xd9, 0x20, 0x16, 0xd8, 0x88, 0x9e, 0x9a, 0xd4, 0xb0, - 0xfa, 0xea, 0x95, 0xdd, 0xee, 0x11, 0xf5, 0x8d, 0x62, 0x0a, 0x15, 0xce, 0x7e, 0xf6, 0x94, 0x38, 0xed, 0x4d, 0xd3, - 0x5a, 0x92, 0xf2, 0xbf, 0xe4, 0x8e, 0x20, 0xf1, 0xaf, 0x37, 0x04, 0x05, 0x3c, 0x1b, 0x9e, 0x1a, 0x92, 0xfb, 0xfd, - 0x5b, 0x15, 0xaa, 0xbd, 0x0e, 0x66, 0x82, 0x2e, 0xbc, 0x07, 0x09, 0x8e, 0xfc, 0x20, 0xcb, 0xc6, 0x2f, 0x0a, 0x4b, - 0xdf, 0x98, 0x3b, 0xc4, 0x9e, 0x38, 0xd3, 0x93, 0xe6, 0x51, 0x7e, 0x58, 0xc1, 0x24, 0xdd, 0x21, 0x83, 0x7c, 0x7e, - 0x81, 0xb1, 0x77, 0x84, 0x95, 0x53, 0xb7, 0x7d, 0x79, 0x07, 0xb1, 0xac, 0x74, 0xc9, 0xbd, 0xd4, 0x9a, 0x12, 0x46, - 0x6d, 0x38, 0xcb, 0xab, 0x56, 0xf4, 0xe5, 0x76, 0xb6, 0xd1, 0x27, 0x2a, 0x20, 0x56, 0xdf, 0x33, 0x39, 0x2d, 0x91, - 0x61, 0xff, 0xb4, 0x5e, 0x4d, 0x9e, 0x0e, 0x43, 0x5d, 0x6b, 0x87, 0x54, 0xdb, 0xf5, 0x4e, 0x05, 0x0a, 0x8c, 0x2d, - 0xbd, 0xa5, 0x67, 0xe9, 0x70, 0xcc, 0x35, 0x78, 0xb1, 0x8c, 0xe0, 0x79, 0xea, 0x07, 0x78, 0x5f, 0x2d, 0x8f, 0x25, - 0xee, 0x1d, 0xdd, 0xf8, 0x02, 0x3a, 0x98, 0xce, 0x02, 0x0f, 0xbf, 0x1d, 0xb0, 0x4a, 0x36, 0x26, 0x73, 0xaf, 0x89, - 0x60, 0x40, 0x29, 0xfa, 0x60, 0xdf, 0x8d, 0x55, 0x4a, 0x34, 0x41, 0x3f, 0xb2, 0xd8, 0xa2, 0x5b, 0xdf, 0x56, 0x44, - 0x3c, 0xe3, 0x72, 0x54, 0x43, 0xfc, 0x29, 0x67, 0x2f, 0xb1, 0x4c, 0x18, 0xc9, 0xc2, 0xa0, 0x91, 0xbd, 0xe0, 0x23, - 0x4a, 0xcf, 0x0f, 0x2d, 0xed, 0xbe, 0x5d, 0x0f, 0x3f, 0x12, 0xc1, 0x5a, 0x1d, 0x84, 0x03, 0x15, 0x8a, 0xec, 0xd9, - 0xca, 0xcd, 0xc1, 0x0d, 0x19, 0x01, 0x28, 0x57, 0x40, 0x36, 0x16, 0xfc, 0xee, 0x86, 0xb0, 0xb8, 0x95, 0x8c, 0xcb, - 0xc4, 0x3e, 0x6f, 0x66, 0x22, 0x3d, 0x27, 0x57, 0x11, 0xe0, 0xe6, 0xa0, 0x99, 0x34, 0x8f, 0x2d, 0xb7, 0xa8, 0xb8, - 0x02, 0x6a, 0x42, 0x6d, 0xd1, 0x44, 0x54, 0x08, 0xd0, 0xeb, 0x69, 0x1f, 0x11, 0xb1, 0x4e, 0xc6, 0xc0, 0xb6, 0x2d, - 0x99, 0x54, 0x2a, 0xe3, 0x7a, 0xa7, 0x38, 0xdc, 0xb5, 0xdd, 0xfd, 0xdf, 0x64, 0x66, 0xcf, 0x60, 0x19, 0x5a, 0xac, - 0x65, 0x77, 0x7f, 0x14, 0xfb, 0xe3, 0x80, 0x06, 0x32, 0x3f, 0xd4, 0x41, 0xf2, 0xd7, 0x3a, 0x43, 0x5c, 0x4a, 0x41, - 0xf9, 0x10, 0x57, 0xb2, 0xc8, 0x05, 0xe9, 0x4e, 0xba, 0xca, 0x73, 0x99, 0x93, 0x7b, 0x40, 0x50, 0x1f, 0x08, 0x85, - 0x2c, 0x37, 0x90, 0xc6, 0x1b, 0x9c, 0x38, 0x6f, 0xe2, 0x91, 0x84, 0xb6, 0x9e, 0x49, 0x64, 0xb2, 0x68, 0xc7, 0x32, - 0xf0, 0xc9, 0xaf, 0xdd, 0x4f, 0x3e, 0xc6, 0x66, 0xe3, 0x40, 0x9b, 0xe5, 0xc9, 0x32, 0xcc, 0xaa, 0xad, 0x2a, 0x4e, - 0x58, 0x32, 0x99, 0x26, 0xbc, 0xfe, 0x2b, 0xac, 0xdc, 0x1a, 0xbe, 0x82, 0x0f, 0x66, 0xb6, 0x84, 0x4b, 0x9b, 0x6f, - 0x91, 0xa2, 0xc3, 0x30, 0xdd, 0xe4, 0xf8, 0x18, 0x13, 0xd3, 0xc5, 0x66, 0xc5, 0x30, 0x1a, 0x14, 0x89, 0xb7, 0x9b, - 0xaf, 0xf6, 0xef, 0x13, 0x38, 0x58, 0x2d, 0xc8, 0xd6, 0xee, 0xaf, 0xc1, 0x65, 0x0f, 0x59, 0x49, 0xd5, 0x98, 0x20, - 0xb4, 0x42, 0x1a, 0x43, 0xd4, 0x25, 0xfe, 0x55, 0x5f, 0x1e, 0xd2, 0xf5, 0xd7, 0x32, 0xa3, 0xf8, 0x5e, 0xfe, 0x5e, - 0xf8, 0x8e, 0x7f, 0x60, 0x2a, 0x69, 0xf3, 0x1c, 0xe1, 0xeb, 0xa0, 0x4b, 0x83, 0x84, 0xa8, 0x89, 0x7c, 0x5b, 0x32, - 0x40, 0xcc, 0x7a, 0x88, 0x01, 0xdc, 0x65, 0x75, 0xab, 0x24, 0x21, 0x63, 0xc1, 0x30, 0xd8, 0x16, 0x2b, 0xf3, 0x78, - 0x46, 0xea, 0x1d, 0xc6, 0x22, 0x71, 0x3e, 0x0f, 0x16, 0xec, 0xd4, 0x75, 0x26, 0xa6, 0x8b, 0xff, 0x98, 0x60, 0x81, - 0x25, 0x18, 0x6b, 0x2d, 0xfc, 0x74, 0x55, 0xc0, 0x9d, 0xe1, 0x43, 0x88, 0x02, 0xb7, 0xc9, 0x13, 0x3f, 0xd3, 0x3d, - 0xc5, 0x2e, 0x38, 0x95, 0x7a, 0x45, 0xd6, 0x9f, 0x03, 0xad, 0x5a, 0x73, 0xa9, 0xce, 0xee, 0x5c, 0x0e, 0xc2, 0x54, - 0x8b, 0xc2, 0x84, 0xd7, 0x51, 0xe2, 0xab, 0x6a, 0x39, 0x4d, 0x18, 0x5a, 0xbf, 0x0a, 0xf5, 0x27, 0xb9, 0xa8, 0x28, - 0xe1, 0xc4, 0x4d, 0xd2, 0x4d, 0x05, 0x07, 0xd4, 0xef, 0xed, 0xda, 0x84, 0xb7, 0x5e, 0xf0, 0x1c, 0x58, 0x50, 0xe8, - 0x39, 0x62, 0xf0, 0x8c, 0x91, 0xc1, 0xeb, 0xb2, 0x41, 0x07, 0xbd, 0x4c, 0x7f, 0xdb, 0x7e, 0xa9, 0xb5, 0xe7, 0xbb, - 0x59, 0xe4, 0x1c, 0xe4, 0xd9, 0xaf, 0xa6, 0xef, 0xef, 0x39, 0x13, 0xe3, 0xa2, 0x79, 0xd1, 0xd3, 0xe0, 0xb4, 0xdc, - 0xa0, 0xd9, 0x43, 0xd0, 0x31, 0xc3, 0xf6, 0x33, 0x2d, 0x2f, 0xc6, 0xf4, 0x9d, 0x38, 0xa6, 0x3d, 0xec, 0xfa, 0x99, - 0xb9, 0xa7, 0x17, 0x14, 0x68, 0xef, 0x89, 0xb7, 0x9d, 0xde, 0xe9, 0xea, 0xf3, 0xe5, 0x9a, 0x44, 0xdf, 0xac, 0xcb, - 0x75, 0x0b, 0xd0, 0xf5, 0x32, 0x16, 0x8d, 0x56, 0x65, 0x9f, 0x2b, 0xcf, 0xee, 0xf9, 0xbe, 0x30, 0xfd, 0x2d, 0xdc, - 0x4e, 0x86, 0x4c, 0xd2, 0x52, 0xb5, 0x52, 0x45, 0x93, 0x2e, 0x90, 0x58, 0x33, 0x49, 0xcb, 0x35, 0x1a, 0xcc, 0xf7, - 0xdd, 0xe5, 0xca, 0xf2, 0x27, 0x16, 0xa2, 0x52, 0x2f, 0xdf, 0x12, 0xa9, 0xcf, 0x06, 0x8b, 0x54, 0x84, 0x25, 0xca, - 0x8d, 0x67, 0x00, 0xab, 0x5d, 0x01, 0xd4, 0x9c, 0xa2, 0x97, 0x4b, 0x45, 0xc0, 0xc4, 0xe9, 0xa7, 0xfb, 0xcd, 0x14, - 0x86, 0xeb, 0xab, 0xb3, 0xf2, 0xda, 0x2f, 0x1a, 0xb9, 0xc4, 0x9f, 0x4f, 0x1f, 0x0a, 0x41, 0xa3, 0xee, 0x8a, 0xdf, - 0x5c, 0x48, 0x00, 0xe4, 0x10, 0xaf, 0xd5, 0x40, 0xba, 0x79, 0x4b, 0xba, 0x4e, 0x64, 0x5d, 0xbc, 0x4b, 0x05, 0x5c, - 0x59, 0xef, 0x80, 0x6e, 0x21, 0xdd, 0x6a, 0x89, 0x83, 0x84, 0x6e, 0xf8, 0x50, 0x70, 0x02, 0x25, 0xd8, 0xc9, 0x04, - 0x99, 0xbc, 0x53, 0xde, 0x12, 0x5e, 0x4d, 0x4c, 0x51, 0x10, 0xc9, 0xbd, 0x97, 0x68, 0xb7, 0x28, 0x79, 0x6b, 0xb0, - 0x09, 0xb1, 0xdb, 0x91, 0xc7, 0x7e, 0x72, 0xe4, 0xf5, 0xd2, 0xe6, 0x62, 0xa3, 0x32, 0x75, 0xf2, 0x92, 0xd2, 0x00, - 0xdb, 0x5b, 0x0a, 0x68, 0xe1, 0x2a, 0xa6, 0xba, 0x9c, 0xe6, 0x84, 0x16, 0xd3, 0x80, 0x33, 0x94, 0x1c, 0xfd, 0x4f, - 0x24, 0x1d, 0x6c, 0x1d, 0x7e, 0x72, 0xd1, 0x83, 0x17, 0xac, 0x35, 0xcd, 0x4a, 0x68, 0xb5, 0x27, 0xd8, 0x82, 0xe6, - 0x55, 0xf2, 0xa9, 0x51, 0x00, 0x9b, 0x17, 0x20, 0xab, 0x9f, 0x3e, 0xee, 0xc5, 0x23, 0xe7, 0xa7, 0x1c, 0xdc, 0x9e, - 0xea, 0x5b, 0x2f, 0x2c, 0x3b, 0xcd, 0x4a, 0x8a, 0x28, 0xc2, 0x93, 0xed, 0x85, 0xf8, 0xee, 0xcb, 0x48, 0x2e, 0x2e, - 0x13, 0x30, 0x43, 0x02, 0x22, 0xd8, 0xf7, 0xe4, 0x03, 0xdc, 0xa9, 0x81, 0x30, 0xad, 0xdf, 0x79, 0x10, 0x34, 0xad, - 0x33, 0x07, 0xc4, 0x4c, 0xc3, 0xec, 0xd2, 0x18, 0x70, 0xc3, 0xfb, 0xd7, 0x38, 0x77, 0x83, 0x7f, 0xac, 0xcc, 0x8a, - 0x66, 0xd3, 0xc0, 0xa6, 0x75, 0x43, 0x36, 0xc4, 0x85, 0x55, 0x8a, 0xc6, 0x55, 0xc6, 0x42, 0xd1, 0xe8, 0xd9, 0xab, - 0xcc, 0x52, 0xd9, 0x3f, 0x37, 0xad, 0x3f, 0xf6, 0x36, 0xb5, 0x25, 0x31, 0x6b, 0x29, 0x89, 0x86, 0xab, 0xcc, 0xcc, - 0xb1, 0x02, 0x10, 0x99, 0xe9, 0x43, 0x12, 0xd4, 0xe0, 0xeb, 0xf0, 0x85, 0x15, 0x53, 0xe5, 0x25, 0xbb, 0x1f, 0x32, - 0xfe, 0xf2, 0xd0, 0x41, 0xd1, 0x3b, 0x58, 0x85, 0x6f, 0x19, 0xf5, 0x9e, 0x06, 0x5d, 0xbf, 0xb4, 0x5a, 0x51, 0x97, - 0x9a, 0xe5, 0xe9, 0x67, 0xfc, 0x7e, 0x20, 0x9e, 0xc0, 0xfe, 0x54, 0x9c, 0xb1, 0x7d, 0x94, 0x7b, 0xc9, 0xe0, 0x9e, - 0xf4, 0x49, 0xea, 0x27, 0x34, 0x3a, 0x0a, 0xe7, 0x6d, 0xdd, 0xb7, 0x42, 0x5f, 0xb6, 0x27, 0x36, 0x8e, 0xa4, 0xee, - 0x52, 0xf2, 0x81, 0xb4, 0x75, 0xd0, 0x7d, 0x41, 0x90, 0xf0, 0x2b, 0xcb, 0x29, 0x05, 0x02, 0x13, 0x2e, 0x11, 0x47, - 0x08, 0xbc, 0x2e, 0xdd, 0x58, 0x40, 0x95, 0xe8, 0x03, 0xbb, 0xa5, 0x0d, 0xc1, 0xef, 0x40, 0xf8, 0xc5, 0x4e, 0x68, - 0x26, 0x57, 0x85, 0x9a, 0x99, 0x2a, 0x7b, 0x84, 0x36, 0x41, 0xcb, 0x89, 0xf4, 0xa4, 0x27, 0x0d, 0x26, 0xd0, 0x68, - 0xea, 0x95, 0x4f, 0x87, 0x60, 0xe8, 0x6a, 0x57, 0x5a, 0x1c, 0x58, 0x41, 0xc9, 0x40, 0xc3, 0x7a, 0x75, 0x29, 0x9d, - 0x16, 0x18, 0x03, 0x84, 0xe7, 0x5e, 0x5e, 0x36, 0x47, 0x2c, 0x7f, 0x77, 0x4b, 0x96, 0x1b, 0x1c, 0xf8, 0xd6, 0xc9, - 0xad, 0xe6, 0x92, 0x91, 0x9e, 0x9b, 0xbe, 0xed, 0xac, 0x9d, 0x28, 0x28, 0xab, 0xcd, 0x05, 0x0f, 0x01, 0x6a, 0x9a, - 0x7d, 0xd8, 0x62, 0x0b, 0x02, 0xce, 0x7a, 0x11, 0x12, 0xe4, 0x6d, 0x02, 0xbe, 0x7c, 0x3f, 0xc7, 0xde, 0x13, 0x51, - 0xb9, 0xac, 0xec, 0xc9, 0xe7, 0xb7, 0x8b, 0xaa, 0xbb, 0x25, 0x78, 0x56, 0x20, 0xdc, 0xf9, 0xc3, 0x38, 0xef, 0xeb, - 0xba, 0x57, 0x00, 0x58, 0x91, 0xf0, 0x49, 0x21, 0x07, 0x04, 0xa3, 0x99, 0x5e, 0xd5, 0xfd, 0x6d, 0xce, 0xa8, 0x29, - 0x9e, 0x22, 0x9c, 0x1c, 0x10, 0x7c, 0x67, 0x3a, 0x51, 0x9b, 0x95, 0xd6, 0x6a, 0x47, 0x64, 0x08, 0xa5, 0x6b, 0x8e, - 0xbb, 0x72, 0x03, 0x94, 0xbb, 0x48, 0x60, 0x86, 0x57, 0xb9, 0x2f, 0xc4, 0x87, 0x34, 0xbb, 0x6c, 0x19, 0xbc, 0x20, - 0x4f, 0xbb, 0x8a, 0xe5, 0x2e, 0x93, 0x71, 0x5d, 0x0b, 0x5b, 0xcc, 0x90, 0x43, 0xe6, 0x7e, 0xc6, 0x29, 0x6c, 0xb6, - 0x69, 0x9f, 0x27, 0x46, 0x6e, 0x69, 0xc3, 0x98, 0x08, 0x06, 0x2e, 0xb4, 0x26, 0xf2, 0x45, 0xbb, 0xb6, 0xdd, 0x9c, - 0xa1, 0xbc, 0xfa, 0xc9, 0xe0, 0xc1, 0x37, 0xff, 0xea, 0x8b, 0x27, 0xb3, 0xc7, 0x7d, 0x2e, 0x1e, 0x9f, 0x79, 0xff, - 0x74, 0x3f, 0xef, 0x65, 0xbb, 0xc0, 0xf5, 0x4e, 0x5e, 0x53, 0xe0, 0x74, 0x28, 0x25, 0x71, 0xd2, 0x01, 0x14, 0xc1, - 0x6d, 0x3b, 0x96, 0x87, 0x88, 0x75, 0xa2, 0xa0, 0x0b, 0x55, 0xce, 0x34, 0x33, 0x8e, 0xf3, 0xe5, 0x95, 0xb4, 0x35, - 0xb8, 0xfd, 0x3c, 0xa4, 0x1a, 0x08, 0xbe, 0xd0, 0x85, 0x09, 0x0d, 0x26, 0x23, 0x6e, 0x6b, 0xda, 0x12, 0x8b, 0x25, - 0x2e, 0x10, 0x39, 0x43, 0x01, 0xc8, 0x21, 0xd3, 0x05, 0xa5, 0xfb, 0x64, 0x32, 0x3c, 0x52, 0xde, 0x88, 0xcc, 0xc8, - 0x70, 0x40, 0xb2, 0x63, 0x7d, 0xe7, 0x6a, 0x26, 0xc2, 0x24, 0xec, 0x22, 0x3c, 0xfd, 0x4b, 0x96, 0xa4, 0x7c, 0xcc, - 0xd3, 0x7e, 0xae, 0x98, 0x80, 0x79, 0x45, 0xe9, 0x25, 0x45, 0xe9, 0x42, 0x0d, 0x7d, 0xcb, 0xb1, 0x38, 0xa7, 0x01, - 0x43, 0x61, 0xaa, 0x84, 0x51, 0x16, 0xd3, 0x66, 0x22, 0x0b, 0x68, 0xc1, 0x39, 0x0a, 0x96, 0x2b, 0x02, 0x8f, 0x2a, - 0xb9, 0x2e, 0xe5, 0x37, 0x11, 0x15, 0x5a, 0x8e, 0x1d, 0x70, 0xc3, 0xba, 0x63, 0x90, 0x95, 0x09, 0x4c, 0xbe, 0xad, - 0x4a, 0x32, 0x2f, 0x39, 0x62, 0x11, 0xde, 0x2f, 0xe7, 0xdb, 0x6e, 0xd7, 0x38, 0x80, 0xbb, 0x76, 0x48, 0x15, 0x56, - 0x31, 0x28, 0x10, 0x26, 0x8a, 0x17, 0xa5, 0xf1, 0x07, 0x09, 0xb6, 0x3a, 0x46, 0xb4, 0xb1, 0xf4, 0xa3, 0x95, 0xb8, - 0x29, 0x47, 0xf4, 0xb2, 0x46, 0x2b, 0x45, 0xbd, 0xcb, 0x0a, 0x18, 0x6d, 0x91, 0x49, 0x48, 0x80, 0xf3, 0xd5, 0xb9, - 0x9a, 0x5f, 0x1f, 0x3a, 0x6a, 0xdb, 0x00, 0x59, 0x2a, 0x15, 0xa7, 0x68, 0x31, 0x58, 0x46, 0x82, 0x71, 0x5b, 0xb3, - 0x0a, 0x1c, 0xbf, 0x67, 0xf2, 0x00, 0xfa, 0x2d, 0xda, 0xe5, 0xae, 0x6a, 0x20, 0x7c, 0x94, 0x11, 0x5d, 0xb0, 0xcb, - 0x40, 0xde, 0x84, 0xd4, 0x1b, 0xb4, 0x60, 0x9b, 0xb6, 0x5b, 0xeb, 0xb9, 0xa8, 0x0f, 0x7d, 0x01, 0x9b, 0x74, 0x59, - 0x51, 0xa3, 0xb5, 0xa1, 0x86, 0xc3, 0xd5, 0x86, 0x23, 0xbb, 0x41, 0x4f, 0x13, 0x3a, 0x20, 0xf5, 0xb5, 0x9f, 0xde, - 0xae, 0x2c, 0x00, 0xfe, 0x81, 0xba, 0x48, 0xf4, 0xfb, 0x32, 0xbe, 0x81, 0x06, 0x41, 0x19, 0x40, 0xb0, 0x93, 0xae, - 0xad, 0xf4, 0x1c, 0x0c, 0xc2, 0x9a, 0x51, 0x0b, 0x6f, 0xca, 0x8f, 0x29, 0xc8, 0x10, 0x4e, 0x49, 0x6c, 0xf0, 0xa6, - 0xdb, 0xc3, 0xc2, 0x3e, 0xdc, 0xe1, 0xac, 0x36, 0xa5, 0x3f, 0x21, 0x9a, 0x4c, 0x74, 0x00, 0x76, 0x57, 0x4d, 0x6c, - 0x7c, 0xd8, 0x0f, 0x2b, 0x72, 0x42, 0x75, 0xa8, 0xe8, 0x13, 0x65, 0x62, 0x9b, 0x5f, 0x76, 0x24, 0x79, 0xa1, 0xb4, - 0xc4, 0x17, 0x06, 0xfb, 0xa6, 0x8b, 0xb1, 0x50, 0x71, 0x80, 0xc4, 0x1c, 0x32, 0xa6, 0x3b, 0x6e, 0x11, 0x07, 0xd3, - 0x66, 0xa0, 0xec, 0x6f, 0xd6, 0xdb, 0x81, 0xad, 0x01, 0x28, 0x73, 0xcb, 0x4f, 0xfa, 0x5b, 0x14, 0x47, 0xb0, 0xa8, - 0x5f, 0x47, 0xa0, 0x25, 0xd7, 0xb5, 0x4f, 0xe2, 0x2c, 0x67, 0xe9, 0x91, 0x1b, 0x2e, 0xfa, 0x7d, 0x55, 0x24, 0x13, - 0xa2, 0xe9, 0x50, 0xc7, 0x56, 0x7c, 0xac, 0xa3, 0xd8, 0x2a, 0xdc, 0x80, 0xdf, 0x49, 0x43, 0xc4, 0x08, 0x19, 0xe3, - 0xb4, 0x24, 0xd0, 0xa9, 0xe5, 0x3c, 0x6d, 0x04, 0x6a, 0x6b, 0x52, 0xe6, 0x9e, 0xed, 0x4f, 0xa4, 0x83, 0x92, 0x3c, - 0xb2, 0x02, 0x68, 0xff, 0x56, 0x1f, 0x7d, 0x69, 0xa5, 0x20, 0x48, 0xb3, 0x24, 0x32, 0x38, 0xa3, 0xe3, 0x1c, 0x37, - 0x5e, 0x48, 0x90, 0x2c, 0x1e, 0x4e, 0x42, 0x9f, 0xb4, 0x59, 0x6b, 0xf0, 0xa4, 0xbc, 0x28, 0x37, 0x2e, 0x00, 0x75, - 0x7a, 0xc8, 0x16, 0x0d, 0x73, 0x16, 0xc8, 0x4e, 0xbc, 0x87, 0x18, 0x1e, 0xea, 0x52, 0x69, 0x01, 0x73, 0x7a, 0x86, - 0xa4, 0xb9, 0x2c, 0xb2, 0x1a, 0x17, 0x04, 0xfd, 0x66, 0xf2, 0x23, 0xf4, 0x39, 0x26, 0x4e, 0x97, 0xa7, 0x31, 0x55, - 0x23, 0x71, 0x7a, 0x36, 0xcf, 0xc0, 0x3a, 0x62, 0x8f, 0xec, 0x42, 0x2b, 0x86, 0xe8, 0x57, 0x71, 0x29, 0xe1, 0x30, - 0xcb, 0x0b, 0x41, 0x47, 0xf9, 0xc5, 0xc8, 0xd9, 0x8c, 0x09, 0x2e, 0x7d, 0xe2, 0x86, 0x1f, 0x4a, 0xa9, 0xa1, 0x80, - 0xcd, 0x10, 0x82, 0xf4, 0x57, 0x12, 0x7d, 0xb0, 0xd6, 0xc0, 0xf3, 0x9e, 0x2e, 0x26, 0xdc, 0x6b, 0xc2, 0x8c, 0x87, - 0x48, 0x4d, 0x28, 0x74, 0x22, 0x3a, 0x00, 0x43, 0x58, 0x76, 0xd3, 0xad, 0x25, 0xef, 0xc5, 0x3a, 0x0d, 0x9a, 0x83, - 0xa7, 0x0c, 0xc6, 0x1b, 0xb9, 0x1c, 0x47, 0x8c, 0xd8, 0xd7, 0x3d, 0x21, 0x7b, 0x2f, 0x46, 0x10, 0x21, 0x5f, 0x1c, - 0x90, 0x31, 0x45, 0x3b, 0xd5, 0xb4, 0xa4, 0x6b, 0xf6, 0xd9, 0x22, 0xf4, 0xcd, 0xed, 0x71, 0x46, 0x64, 0x4a, 0xaa, - 0x2f, 0x4c, 0x10, 0x11, 0x7a, 0x3a, 0x48, 0xc1, 0x9c, 0xdd, 0x07, 0xaf, 0x28, 0x02, 0x01, 0xd6, 0xdb, 0x6a, 0x78, - 0x52, 0x9d, 0x4f, 0x81, 0xed, 0xba, 0x90, 0x4e, 0xb3, 0x34, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x37, 0x49, 0x0d, 0x63, - 0xba, 0xa8, 0x7c, 0xc0, 0x1f, 0xd4, 0x47, 0xdc, 0xa2, 0xbf, 0x8a, 0xc7, 0x19, 0xf6, 0x92, 0x86, 0x6e, 0x12, 0xdb, - 0x84, 0xa8, 0xaa, 0xc6, 0xba, 0xe6, 0x66, 0xf4, 0xb8, 0x22, 0x03, 0xd7, 0x48, 0xfd, 0x06, 0xad, 0x83, 0x4a, 0x0b, - 0xeb, 0x59, 0x7c, 0x0a, 0xf2, 0xdc, 0x1a, 0x5b, 0xee, 0x4f, 0x90, 0xc4, 0x8b, 0xd1, 0x69, 0x46, 0x7b, 0x86, 0x97, - 0x19, 0x0e, 0x01, 0xf6, 0x9d, 0xe3, 0xdd, 0xae, 0xdd, 0x6f, 0x49, 0xc6, 0x4e, 0xc2, 0x9f, 0x6d, 0x5d, 0x92, 0x34, - 0x06, 0xd4, 0x94, 0x7f, 0x57, 0x3f, 0xe4, 0xb1, 0x17, 0x50, 0x71, 0x1f, 0x23, 0x5d, 0x2f, 0x34, 0x9f, 0xbe, 0x44, - 0x3b, 0xad, 0xdc, 0x3a, 0xbc, 0x45, 0x26, 0xee, 0x3e, 0xc2, 0x00, 0x73, 0x21, 0x77, 0x47, 0xa0, 0xee, 0xad, 0x5f, - 0x10, 0x6f, 0x8a, 0xba, 0xc2, 0x54, 0x4a, 0xb6, 0x1a, 0xbc, 0x96, 0x98, 0x85, 0x9a, 0xcb, 0x95, 0x46, 0xd8, 0xca, - 0x11, 0xa8, 0x83, 0x8e, 0xa4, 0xad, 0xf5, 0xda, 0xc6, 0xac, 0xf2, 0x54, 0x6e, 0x26, 0x0b, 0xfa, 0x1c, 0x49, 0x99, - 0x33, 0x87, 0xce, 0x8a, 0x42, 0x57, 0x25, 0x61, 0xa9, 0xe5, 0xd6, 0xeb, 0xb3, 0x8e, 0x5f, 0xbc, 0xb7, 0x03, 0x88, - 0x05, 0x7b, 0x56, 0x3b, 0x19, 0x1c, 0x76, 0x5b, 0x5c, 0x56, 0xb9, 0xda, 0xa6, 0x44, 0x59, 0x42, 0x60, 0x2e, 0x59, - 0x7d, 0x0d, 0xd0, 0x53, 0x14, 0x45, 0x1a, 0x74, 0xd5, 0x75, 0x41, 0x42, 0xb8, 0x52, 0xf1, 0x77, 0x17, 0x66, 0xe4, - 0x08, 0x97, 0x88, 0xdc, 0x41, 0x57, 0x4a, 0x7e, 0x3c, 0x21, 0x3d, 0x9d, 0x10, 0x09, 0xbd, 0xbc, 0x31, 0x78, 0x97, - 0x83, 0xc7, 0xfe, 0x2e, 0xe4, 0x0a, 0x1f, 0x12, 0x6c, 0x39, 0x0c, 0xa5, 0xdc, 0x14, 0xe1, 0xbe, 0x2f, 0xd0, 0x49, - 0xb9, 0x8a, 0xe0, 0x20, 0xb5, 0x23, 0x9f, 0xab, 0x23, 0x7f, 0x66, 0x73, 0x0a, 0x97, 0xe6, 0x64, 0xd7, 0x28, 0x42, - 0x99, 0x62, 0xef, 0x79, 0x62, 0x60, 0x4a, 0x12, 0x3e, 0xbb, 0x4e, 0x64, 0xad, 0x75, 0x7f, 0xa7, 0x3d, 0x88, 0x17, - 0x4d, 0xa4, 0xfc, 0x20, 0x36, 0x1f, 0x68, 0x71, 0x5d, 0x5e, 0x63, 0xeb, 0x8e, 0x62, 0x06, 0xa0, 0xb9, 0xc9, 0xba, - 0xad, 0x32, 0xb9, 0xc1, 0x2a, 0x20, 0x4f, 0x67, 0xa1, 0xf1, 0x2c, 0xcd, 0x60, 0x9e, 0x9f, 0x38, 0x2b, 0x46, 0x2a, - 0x04, 0x8a, 0xd2, 0x52, 0x9b, 0xd5, 0x49, 0x5c, 0xc9, 0x8e, 0x3d, 0x6e, 0xd9, 0x42, 0x27, 0x20, 0xd5, 0xe3, 0x04, - 0xb4, 0x0d, 0xde, 0x51, 0x4a, 0x76, 0x67, 0x19, 0x07, 0xdb, 0x85, 0x7f, 0x07, 0x66, 0x1d, 0xea, 0xab, 0x08, 0x2a, - 0xd2, 0x26, 0xb6, 0x6a, 0x4a, 0x91, 0x74, 0x42, 0xeb, 0x62, 0x0b, 0x8a, 0xe2, 0x6a, 0x8f, 0xf8, 0xaa, 0x95, 0xe1, - 0xce, 0xec, 0xb6, 0xc8, 0xe6, 0x0c, 0xf7, 0x64, 0xe0, 0x8c, 0x2d, 0xa1, 0xcd, 0xac, 0x25, 0xf6, 0x71, 0x4f, 0x37, - 0xe9, 0xef, 0xb6, 0x92, 0x66, 0xd0, 0x88, 0xa1, 0xa5, 0x65, 0xf2, 0xef, 0x8d, 0xc9, 0xbc, 0x16, 0x43, 0x63, 0x4e, - 0x31, 0xdd, 0x30, 0x70, 0x8b, 0x2a, 0xb5, 0x19, 0xd7, 0x8a, 0x3e, 0xfd, 0x4e, 0x23, 0x39, 0xa4, 0x00, 0x4d, 0x28, - 0x05, 0x11, 0xc8, 0x97, 0x14, 0x82, 0x3b, 0x25, 0xdb, 0x44, 0x96, 0x5b, 0x89, 0xcb, 0xa2, 0xd3, 0xc3, 0xf1, 0x0f, - 0x27, 0xa0, 0x42, 0x5f, 0xae, 0x58, 0xd0, 0x4f, 0xf4, 0x3e, 0x26, 0xea, 0x58, 0xca, 0xc9, 0xf1, 0xe9, 0xd2, 0x55, - 0x55, 0x01, 0x2d, 0x57, 0xaf, 0x8b, 0x0e, 0xce, 0x35, 0x65, 0x80, 0xd4, 0x63, 0x14, 0xb6, 0x10, 0x26, 0x7f, 0x04, - 0xde, 0x4f, 0xef, 0xe5, 0xb8, 0xed, 0x36, 0x45, 0x8f, 0x74, 0x76, 0xa7, 0x48, 0x4d, 0x2a, 0xd1, 0xca, 0xc9, 0x31, - 0x9e, 0x1e, 0xf2, 0x62, 0x0c, 0xd8, 0x31, 0x71, 0xb3, 0x49, 0x0d, 0x18, 0x13, 0x80, 0x23, 0x33, 0x15, 0xdb, 0x54, - 0x5b, 0x2b, 0x13, 0xa2, 0xb6, 0xe5, 0x7c, 0x59, 0x4b, 0xa7, 0x28, 0xef, 0x60, 0x0e, 0x81, 0x79, 0xee, 0x32, 0x6d, - 0xa0, 0x9a, 0x22, 0xb3, 0xa4, 0x1d, 0xd5, 0xf1, 0x52, 0x6c, 0xbc, 0xf8, 0xa9, 0xc0, 0xbd, 0x91, 0xaa, 0x57, 0x56, - 0x0b, 0x6e, 0xce, 0x94, 0x71, 0xb8, 0xc5, 0x55, 0xe1, 0x24, 0xe2, 0x01, 0x8c, 0x3e, 0x63, 0x31, 0x9c, 0x2f, 0xf6, - 0x23, 0x3e, 0x2c, 0x6a, 0x0a, 0x6f, 0xab, 0xb7, 0x72, 0x5c, 0x86, 0x80, 0xea, 0x11, 0xc4, 0xe9, 0x4e, 0x65, 0xc1, - 0xeb, 0x8c, 0x1c, 0x11, 0xbe, 0x95, 0xe2, 0xa8, 0x64, 0x1c, 0xc4, 0x67, 0xb1, 0xe9, 0xc1, 0x31, 0x2d, 0x3c, 0x63, - 0x22, 0x77, 0xc0, 0x3c, 0xa3, 0xf1, 0x3d, 0x3e, 0x73, 0x43, 0x7c, 0xe7, 0xb5, 0xf7, 0xb6, 0x22, 0x3d, 0x37, 0xb3, - 0xf9, 0xc4, 0x9b, 0x86, 0xa8, 0xf3, 0xe1, 0xad, 0x27, 0x3a, 0xe7, 0x15, 0x2c, 0xe2, 0x50, 0xb8, 0x21, 0xcd, 0xe8, - 0x0b, 0xed, 0x1e, 0xb2, 0x79, 0x6a, 0xba, 0x8b, 0x0b, 0xd8, 0xa3, 0xe9, 0x77, 0x67, 0x04, 0xc4, 0x3e, 0x41, 0xc4, - 0x97, 0x3c, 0xb8, 0xbd, 0x75, 0x2b, 0x6d, 0x75, 0x8c, 0x91, 0x6a, 0xd3, 0xdc, 0x02, 0xbf, 0xdf, 0x97, 0x30, 0x7b, - 0x1c, 0x83, 0x77, 0x0d, 0x02, 0xc4, 0x2f, 0x40, 0x58, 0x35, 0x6d, 0x68, 0xc0, 0x77, 0xf8, 0x32, 0x5b, 0xe6, 0x5e, - 0x23, 0xaa, 0x1e, 0xe6, 0xf2, 0xc5, 0xc9, 0xae, 0x36, 0x22, 0x95, 0xdb, 0x7e, 0xe2, 0xcf, 0x0f, 0x86, 0x25, 0x3d, - 0x47, 0x87, 0x71, 0x20, 0x37, 0xe4, 0xcc, 0x28, 0xb1, 0x09, 0xa7, 0xad, 0x9c, 0x87, 0xc6, 0x3c, 0x15, 0x04, 0x64, - 0xf8, 0xff, 0x7a, 0x38, 0x48, 0xcc, 0x5b, 0x37, 0x28, 0x57, 0xd5, 0x06, 0xd6, 0x64, 0x2f, 0x0e, 0x22, 0xa8, 0xf2, - 0x50, 0xa4, 0x58, 0x5f, 0x74, 0x58, 0x97, 0xc4, 0x42, 0x26, 0x82, 0x51, 0x21, 0x49, 0x90, 0xad, 0xa3, 0x5b, 0xa3, - 0xdc, 0x25, 0xbd, 0x4e, 0x40, 0xcf, 0xf4, 0x32, 0xfe, 0x18, 0xc7, 0xa2, 0xac, 0x25, 0x7f, 0xee, 0x49, 0xb6, 0xcb, - 0xe8, 0xae, 0x66, 0xac, 0x23, 0x22, 0x36, 0xb4, 0x1c, 0x1d, 0xe7, 0x65, 0x51, 0x72, 0xdc, 0xb4, 0x27, 0x70, 0x2c, - 0xbc, 0xb3, 0xa2, 0x68, 0xe6, 0x42, 0xae, 0xe9, 0xab, 0x63, 0x8a, 0xd6, 0xe1, 0x31, 0x7b, 0x6d, 0xdb, 0x12, 0x3d, - 0x5c, 0x8e, 0xf1, 0x52, 0x1a, 0x2a, 0x34, 0x87, 0xda, 0x5a, 0x5d, 0xea, 0x39, 0x2c, 0x63, 0xc5, 0x17, 0x85, 0x52, - 0xee, 0xa2, 0xe1, 0xa9, 0x8b, 0x69, 0x40, 0x37, 0x69, 0x44, 0x3f, 0x91, 0x99, 0x53, 0x8d, 0x3c, 0xe9, 0xc7, 0xbe, - 0x51, 0x85, 0x01, 0xd0, 0xf1, 0x8a, 0x91, 0xec, 0xbe, 0x2f, 0x57, 0x87, 0x12, 0x7c, 0x7a, 0xd6, 0x51, 0x2c, 0xb5, - 0x8e, 0xf7, 0x79, 0x2d, 0xc7, 0x77, 0x37, 0x84, 0xd1, 0xba, 0x3d, 0x30, 0x2b, 0x9c, 0x8b, 0x49, 0x31, 0x6e, 0xd9, - 0x0a, 0x13, 0xe6, 0x11, 0x4a, 0xbc, 0x9b, 0xa2, 0xb1, 0x5f, 0x99, 0x12, 0x9d, 0x17, 0xe1, 0x65, 0x73, 0xc5, 0x42, - 0xa9, 0x7a, 0x71, 0x89, 0xfd, 0xc6, 0xbd, 0xed, 0x39, 0xe4, 0xb9, 0x0c, 0x1b, 0x6f, 0x67, 0x79, 0x7a, 0xc4, 0xe4, - 0xfc, 0x08, 0x9b, 0x79, 0x20, 0x7d, 0x2d, 0x04, 0x18, 0xf5, 0x9e, 0x1c, 0xbf, 0x7c, 0xdf, 0xcb, 0xae, 0x71, 0xbc, - 0x30, 0xd2, 0x38, 0xce, 0x17, 0xe4, 0x29, 0xb1, 0x44, 0x69, 0xe6, 0x8b, 0x7a, 0x94, 0x03, 0xf1, 0xdc, 0x0b, 0x76, - 0x3d, 0x6d, 0xc7, 0xbf, 0x17, 0xee, 0x4a, 0x7a, 0x34, 0xfa, 0x04, 0xbe, 0x1e, 0xfe, 0x73, 0x74, 0x58, 0x90, 0x44, - 0x44, 0x4f, 0xe3, 0x48, 0x4f, 0x6d, 0x59, 0xea, 0x3d, 0x3b, 0xd6, 0x44, 0xbd, 0xf1, 0x3a, 0x23, 0x94, 0xb6, 0xa1, - 0x94, 0xb6, 0x83, 0x32, 0x82, 0x25, 0xb0, 0x69, 0x53, 0x08, 0x51, 0x8d, 0xff, 0x82, 0x9b, 0xa7, 0x08, 0x3f, 0xeb, - 0x44, 0x69, 0x36, 0x53, 0x53, 0x74, 0x67, 0x34, 0x00, 0x6b, 0x79, 0x9f, 0x0d, 0xd0, 0xfa, 0xa1, 0xae, 0xbc, 0xc2, - 0xc0, 0x6a, 0x55, 0x57, 0x02, 0xb5, 0x22, 0x50, 0x82, 0x04, 0x4e, 0x78, 0x2f, 0x22, 0xa2, 0x1b, 0x98, 0x54, 0x7a, - 0xb0, 0x65, 0x3b, 0xb7, 0x0d, 0xbb, 0xd7, 0xd2, 0xe7, 0x87, 0xf7, 0x6a, 0xd2, 0x53, 0x57, 0x76, 0xc7, 0x43, 0xe4, - 0x24, 0x39, 0xbb, 0x07, 0x88, 0xe4, 0x51, 0x32, 0xd8, 0xb9, 0x7b, 0x7b, 0xda, 0xda, 0x1d, 0x62, 0x61, 0x5b, 0xf0, - 0xd3, 0x1d, 0xb1, 0x18, 0xa5, 0xdd, 0xec, 0x93, 0x9f, 0x67, 0x70, 0x58, 0x7a, 0x0b, 0xe0, 0x29, 0xd6, 0xdd, 0x5f, - 0xcd, 0xac, 0xe8, 0x1e, 0xff, 0xe2, 0xa1, 0x2b, 0x0a, 0xe9, 0x88, 0x59, 0xdc, 0xe2, 0xb8, 0x2e, 0x3b, 0xab, 0xbb, - 0x45, 0xce, 0x6d, 0x49, 0x84, 0x4a, 0x09, 0xc9, 0xe5, 0x98, 0x95, 0x1a, 0xdb, 0x23, 0xca, 0xe0, 0xb4, 0xb7, 0x97, - 0x7e, 0x63, 0xde, 0xc2, 0xf4, 0x05, 0xa0, 0x26, 0x60, 0xb9, 0x20, 0x1b, 0xef, 0x3e, 0x00, 0xcc, 0xd2, 0xaa, 0xab, - 0x33, 0x06, 0x17, 0xb7, 0xee, 0x7a, 0xc3, 0x22, 0x33, 0x9a, 0x89, 0xba, 0xc9, 0xdd, 0x11, 0x55, 0x8c, 0x16, 0x26, - 0xdb, 0x2f, 0xa5, 0xe1, 0xd3, 0x6a, 0x44, 0x2b, 0x2d, 0x5a, 0x46, 0x87, 0x5d, 0x5f, 0xc9, 0x51, 0x22, 0xb1, 0x5c, - 0x2c, 0xbb, 0xf2, 0x56, 0x98, 0xf8, 0x31, 0xb1, 0x36, 0x66, 0x44, 0x5a, 0xb2, 0x85, 0xc1, 0x11, 0x49, 0x79, 0xd4, - 0xdd, 0xb2, 0x6a, 0x72, 0x1b, 0x67, 0x2b, 0x3c, 0xdd, 0x52, 0xd4, 0x14, 0xaa, 0x43, 0xb4, 0xdd, 0x07, 0x19, 0x24, - 0xd3, 0x46, 0x91, 0xf3, 0xb9, 0xed, 0xb1, 0x88, 0x3a, 0x5d, 0xd1, 0x69, 0x91, 0x88, 0xb9, 0xdd, 0x53, 0xb4, 0x1d, - 0x25, 0xc9, 0x93, 0x94, 0x4c, 0x27, 0x0e, 0x54, 0xd3, 0x86, 0x5c, 0x4b, 0xef, 0x5f, 0x2b, 0x02, 0x71, 0xf1, 0x1f, - 0xf2, 0xb2, 0xed, 0xbb, 0x03, 0x83, 0x08, 0x3a, 0x98, 0x23, 0x09, 0xcc, 0x4b, 0x2d, 0x1d, 0x94, 0x48, 0x12, 0x91, - 0x9f, 0x34, 0xcc, 0xae, 0x4b, 0xd6, 0xe8, 0x83, 0x56, 0xba, 0x33, 0x99, 0x35, 0x24, 0x52, 0xaf, 0x49, 0x6d, 0x6d, - 0xb1, 0x89, 0x11, 0xcf, 0x7c, 0x67, 0x9d, 0x88, 0x22, 0xf1, 0x20, 0x73, 0x62, 0xa9, 0x3c, 0x5b, 0x44, 0x89, 0xaf, - 0x70, 0xf6, 0xb5, 0x5e, 0xec, 0x4e, 0x8b, 0x2c, 0xe6, 0x87, 0x91, 0x5f, 0x0e, 0x37, 0xbb, 0x15, 0x29, 0xea, 0xad, - 0xf1, 0xe5, 0x05, 0xcd, 0x6c, 0x5c, 0x3b, 0x71, 0xcc, 0x19, 0xd2, 0x48, 0x21, 0x48, 0x48, 0x9f, 0x8e, 0xf0, 0x5a, - 0x04, 0x07, 0x36, 0x6a, 0x7a, 0xc7, 0x9e, 0x67, 0x2b, 0x77, 0x57, 0x43, 0xc3, 0xb6, 0x43, 0x22, 0x48, 0xd0, 0x78, - 0x93, 0x59, 0x33, 0x34, 0x3f, 0xec, 0x3a, 0x6f, 0xcf, 0xf5, 0xf0, 0x8d, 0x62, 0x60, 0x69, 0x13, 0x09, 0xe0, 0x52, - 0x51, 0x95, 0xe6, 0xd6, 0x7e, 0x90, 0x43, 0x36, 0xe2, 0x8b, 0x56, 0xfd, 0x8a, 0x80, 0xee, 0x24, 0x21, 0x21, 0x40, - 0xd3, 0xeb, 0xfa, 0x3e, 0x5c, 0x24, 0x2c, 0x0e, 0x08, 0xdf, 0x55, 0xf0, 0xdf, 0x24, 0x4d, 0xaf, 0x4b, 0x13, 0xfa, - 0xb1, 0x28, 0x97, 0x83, 0x83, 0x2c, 0x10, 0x6f, 0x01, 0xd1, 0x10, 0x04, 0x82, 0x42, 0x58, 0x38, 0xa6, 0x12, 0xfa, - 0x17, 0x5a, 0x43, 0xc1, 0x04, 0x98, 0x8e, 0xc6, 0xb9, 0x34, 0x28, 0xaa, 0xad, 0x74, 0x9a, 0x53, 0x36, 0x5c, 0x34, - 0x0c, 0x32, 0xeb, 0x9f, 0xc2, 0x10, 0xa7, 0x98, 0x26, 0xe3, 0xfe, 0x2e, 0xc1, 0x78, 0xba, 0x6d, 0x3e, 0x51, 0xca, - 0x6a, 0x9f, 0xb5, 0x78, 0x42, 0x2b, 0x9e, 0x57, 0xa2, 0x3e, 0xa7, 0xd7, 0xde, 0x7f, 0xf4, 0x86, 0xef, 0xe0, 0xc9, - 0x47, 0x25, 0x7a, 0x1b, 0x27, 0x96, 0x3b, 0x58, 0x04, 0x58, 0xe4, 0x7d, 0xd7, 0x8c, 0xa4, 0x40, 0x86, 0x3a, 0xc0, - 0x5c, 0x63, 0x6e, 0xfb, 0x48, 0x0d, 0x6d, 0x0f, 0xe5, 0xde, 0xe4, 0xda, 0x34, 0xac, 0x7a, 0x58, 0x60, 0x79, 0x75, - 0xdd, 0xe6, 0xe6, 0x00, 0x79, 0xec, 0x5a, 0x8c, 0x08, 0x72, 0x44, 0x86, 0xe3, 0xc1, 0x6d, 0x42, 0x41, 0x80, 0x02, - 0xaa, 0xa6, 0x9a, 0xd6, 0xe1, 0xfe, 0x9c, 0x0f, 0xe2, 0x50, 0xd7, 0x84, 0xd8, 0xa8, 0x3c, 0x42, 0xaf, 0xb9, 0xef, - 0x13, 0xfd, 0x3e, 0xe5, 0x86, 0xc6, 0x1b, 0x24, 0x40, 0x2e, 0xae, 0xce, 0x93, 0x44, 0xdd, 0x18, 0xab, 0xa3, 0x38, - 0x22, 0x0c, 0x50, 0x98, 0x63, 0x38, 0xdc, 0x4e, 0x05, 0x47, 0x4b, 0x02, 0x6d, 0x2c, 0x55, 0x2f, 0xb7, 0xdf, 0x66, - 0x5d, 0xea, 0x1f, 0x14, 0x0c, 0xa2, 0xd3, 0x43, 0x5e, 0x38, 0x10, 0x32, 0xd6, 0xf7, 0xe1, 0xf2, 0x1e, 0x67, 0xb4, - 0x2e, 0xa3, 0x46, 0x30, 0x06, 0x0f, 0x50, 0xce, 0xaa, 0xc7, 0xd1, 0x2e, 0x20, 0x96, 0x87, 0xf4, 0xa1, 0xc9, 0x8c, - 0x90, 0x2d, 0x72, 0xf9, 0xa5, 0x16, 0xf9, 0xab, 0xd0, 0xb5, 0x78, 0xee, 0x01, 0x9d, 0x5a, 0x70, 0x0c, 0x75, 0x83, - 0xaf, 0xba, 0xe9, 0xaa, 0x96, 0xda, 0x36, 0xc7, 0xc8, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x6c, 0xdf, 0x7b, 0x07, - 0x80, 0x98, 0x02, 0x7a, 0x01, 0xb0, 0x1d, 0x5e, 0x0a, 0x3e, 0xf1, 0xe0, 0xb6, 0x3a, 0xec, 0xd8, 0x99, 0xa4, 0x71, - 0x1e, 0x4d, 0xbd, 0x39, 0xc7, 0x5c, 0xe8, 0x71, 0xec, 0xe7, 0x06, 0xd7, 0x9f, 0xac, 0x18, 0xbe, 0x6d, 0x4d, 0x70, - 0x78, 0xae, 0x72, 0x36, 0x24, 0x11, 0x4b, 0xd6, 0x3d, 0x47, 0x5f, 0x48, 0xe4, 0x69, 0x1b, 0xdf, 0x2f, 0xf4, 0xd5, - 0x39, 0x75, 0x91, 0x9d, 0x63, 0x92, 0x09, 0xf4, 0x60, 0xf2, 0x5e, 0x59, 0x1c, 0x1a, 0xab, 0x94, 0x59, 0xfc, 0xd0, - 0xb9, 0xa6, 0xb7, 0xf7, 0xab, 0x75, 0x29, 0xe5, 0x53, 0xad, 0x72, 0x2b, 0xbf, 0x8d, 0x1d, 0x4d, 0x3b, 0x35, 0xa0, - 0xdd, 0xd6, 0x37, 0x74, 0x1a, 0x45, 0x24, 0xe9, 0xee, 0x82, 0x5b, 0x78, 0x06, 0xd3, 0x18, 0x51, 0xb0, 0xe7, 0x53, - 0xeb, 0xf2, 0xb5, 0x97, 0x95, 0x78, 0x45, 0xbc, 0x2b, 0x06, 0x63, 0xe5, 0x84, 0x0e, 0x16, 0x69, 0x1a, 0x68, 0xe0, - 0x24, 0x49, 0xdc, 0xaa, 0x24, 0x7e, 0x6a, 0xf9, 0x17, 0xd4, 0xdc, 0xa8, 0x3c, 0x15, 0xf1, 0x75, 0x49, 0x98, 0x39, - 0x2e, 0xd5, 0xbd, 0x51, 0x79, 0x50, 0x8e, 0x79, 0xba, 0x66, 0x2c, 0x5a, 0xba, 0x9d, 0x22, 0xf3, 0x64, 0xcf, 0x9b, - 0x9b, 0x11, 0x25, 0x4a, 0x84, 0xea, 0x42, 0xaf, 0x72, 0x6d, 0x16, 0x3a, 0xd2, 0x88, 0x4d, 0x6b, 0x35, 0x9b, 0xd8, - 0xfd, 0x70, 0x0e, 0x52, 0x95, 0x3d, 0xc1, 0x35, 0xf4, 0xbc, 0x13, 0x86, 0xcd, 0xb5, 0xae, 0x43, 0x23, 0x86, 0xcc, - 0x80, 0x99, 0x66, 0x01, 0xa6, 0x40, 0x16, 0x71, 0x5f, 0x0d, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0xf5, 0x7c, 0xab, - 0xad, 0x3a, 0x26, 0xff, 0x32, 0x78, 0x0d, 0x67, 0x00, 0x45, 0x89, 0xe1, 0x44, 0xd3, 0x5e, 0xa9, 0xd5, 0x00, 0x61, - 0x9e, 0x10, 0xa3, 0xb0, 0x82, 0x6d, 0xd1, 0x68, 0xd5, 0x55, 0x30, 0x80, 0x1a, 0xe6, 0xc9, 0x08, 0x8d, 0x22, 0x32, - 0x1a, 0x5f, 0xd8, 0x8d, 0xbc, 0xb2, 0x00, 0xcb, 0x9a, 0xf4, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x8e, 0x12, - 0x72, 0xc3, 0x0d, 0x9a, 0x36, 0xa9, 0x37, 0x1e, 0x07, 0x7c, 0x6b, 0xc6, 0x99, 0x86, 0x76, 0xdb, 0x5a, 0xb9, 0x0f, - 0xec, 0xc0, 0x0d, 0xb7, 0x0d, 0xdf, 0xa9, 0x6a, 0x27, 0xf3, 0xf5, 0xeb, 0xdd, 0xee, 0x12, 0x6b, 0x42, 0x9b, 0x8e, - 0xb2, 0x06, 0xb6, 0x6d, 0x51, 0xcc, 0xc5, 0x48, 0xd7, 0x78, 0xb7, 0xd8, 0x77, 0x20, 0xdb, 0xf7, 0x60, 0xad, 0x92, - 0x90, 0x93, 0xab, 0x74, 0x7e, 0x8d, 0x7e, 0xd2, 0xe9, 0x2a, 0x91, 0x99, 0x5d, 0xe4, 0x77, 0x99, 0xa9, 0xef, 0x65, - 0xaa, 0xc7, 0xb5, 0x56, 0xa4, 0xc0, 0x56, 0xa8, 0x0a, 0xcf, 0x21, 0x30, 0x5d, 0xb2, 0xf2, 0x7f, 0x20, 0xe2, 0x9c, - 0x8c, 0x2b, 0xa1, 0xbd, 0x51, 0x35, 0x03, 0x18, 0x12, 0x8a, 0xa1, 0x89, 0xe5, 0xf4, 0xb8, 0xd4, 0x20, 0xaa, 0x93, - 0x06, 0x90, 0xe5, 0x81, 0x10, 0xf0, 0x13, 0x05, 0xd4, 0x99, 0x99, 0x30, 0xf0, 0x93, 0xc0, 0x59, 0x5a, 0x4d, 0x91, - 0x7e, 0x31, 0xe0, 0x0c, 0x45, 0xdd, 0x90, 0x7e, 0xc5, 0x94, 0xe8, 0x0e, 0xbf, 0x52, 0x68, 0x7d, 0x6a, 0x66, 0x2e, - 0x98, 0x91, 0x4e, 0x1a, 0xf8, 0x15, 0x2e, 0x6a, 0x0b, 0xfe, 0x32, 0xa5, 0x26, 0x33, 0x45, 0x98, 0xc9, 0x01, 0x5c, - 0x2a, 0xb7, 0xc5, 0xb3, 0xaa, 0x26, 0x30, 0xfb, 0x22, 0x65, 0x74, 0xe2, 0x18, 0x75, 0xdf, 0x6e, 0x38, 0x4a, 0x52, - 0xde, 0xfe, 0x7a, 0x95, 0x35, 0xca, 0x0e, 0x99, 0x59, 0xea, 0x2a, 0xfe, 0xd4, 0x24, 0x77, 0xbd, 0x0c, 0x9d, 0x74, - 0x2b, 0xb8, 0x65, 0x94, 0xf3, 0x0c, 0xcb, 0xdd, 0x18, 0xd1, 0x61, 0x73, 0x2f, 0x5d, 0xdf, 0xa5, 0xc9, 0xce, 0xad, - 0x4a, 0x4c, 0x08, 0x29, 0xb4, 0x5f, 0x9f, 0x9d, 0xfb, 0xe3, 0xd5, 0xf6, 0xdb, 0x51, 0xdf, 0x73, 0xe3, 0x7c, 0x3a, - 0xfe, 0xed, 0x72, 0xdb, 0x1d, 0x4c, 0x33, 0x54, 0x61, 0x5a, 0x3a, 0x08, 0xdd, 0x35, 0x0f, 0xd0, 0xbf, 0x24, 0x3e, - 0xf5, 0xfb, 0x0b, 0x2a, 0x1d, 0xd0, 0x26, 0xb3, 0x35, 0x15, 0xb2, 0x38, 0x28, 0xa1, 0x6c, 0xd3, 0x2e, 0x4d, 0x8b, - 0x29, 0x72, 0xa0, 0x6e, 0x21, 0x03, 0x52, 0xb2, 0x70, 0x99, 0x41, 0xe5, 0x57, 0xf1, 0x3a, 0xf1, 0x75, 0x7e, 0xb5, - 0x31, 0x32, 0xa2, 0x70, 0x55, 0xc8, 0x35, 0x7c, 0x47, 0x8b, 0x79, 0x01, 0xed, 0xa4, 0xda, 0x38, 0xf4, 0x55, 0xa3, - 0x8e, 0x49, 0xa0, 0xe3, 0xc3, 0x4f, 0x3e, 0x53, 0x37, 0x98, 0xdd, 0xad, 0x09, 0xf8, 0xb1, 0x39, 0x7b, 0x71, 0xa3, - 0x87, 0x38, 0xb5, 0x96, 0x7d, 0xbc, 0x50, 0xf6, 0xa8, 0x1a, 0x79, 0x6b, 0x8d, 0x83, 0xdc, 0xa4, 0x61, 0x6d, 0x38, - 0x29, 0x14, 0xe0, 0xe1, 0x52, 0x7e, 0x48, 0x0a, 0x97, 0xde, 0xa8, 0x44, 0x98, 0x07, 0xb0, 0x13, 0xb6, 0xd4, 0xbd, - 0x51, 0x49, 0x0b, 0xa8, 0x1e, 0xe9, 0xc9, 0xa0, 0x98, 0xce, 0x89, 0xc4, 0x98, 0xf1, 0x25, 0xdd, 0xf4, 0x43, 0xb4, - 0xba, 0x66, 0xd8, 0xc3, 0xfb, 0x58, 0x90, 0x20, 0x87, 0x04, 0x1b, 0xd7, 0x19, 0x42, 0xec, 0xa4, 0xc2, 0xf7, 0x7c, - 0x55, 0x6c, 0x99, 0x7f, 0x46, 0xa8, 0x6d, 0xeb, 0xbe, 0xed, 0x11, 0xe5, 0xb5, 0xd2, 0xb7, 0xb9, 0xbf, 0xe2, 0x8c, - 0xf1, 0x72, 0x86, 0xc6, 0x23, 0x2f, 0xfb, 0x39, 0xcc, 0xcf, 0x7e, 0x75, 0x03, 0x16, 0x20, 0x71, 0x6c, 0xc1, 0xb1, - 0xa7, 0xe4, 0x68, 0xae, 0x73, 0x3e, 0xb6, 0x11, 0xcc, 0x92, 0x69, 0x40, 0x64, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, - 0x71, 0x91, 0x28, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7c, 0x6f, 0x22, 0xf7, 0x05, 0x2d, 0x46, 0x59, 0xfc, 0xb1, 0xab, - 0xb6, 0xb6, 0x8a, 0x1c, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0xe3, 0x58, 0x15, 0x50, 0xbe, 0xce, 0x95, 0xd6, 0x52, - 0x5d, 0xa0, 0x8b, 0x43, 0xf7, 0x51, 0x8b, 0x8a, 0x6a, 0x35, 0x18, 0xf7, 0x40, 0xd9, 0x6b, 0x98, 0xd0, 0x03, 0x7e, - 0xb6, 0x0e, 0x63, 0x36, 0x78, 0xe7, 0xcd, 0xb1, 0x1a, 0xd3, 0x45, 0xce, 0x7b, 0x0b, 0xa8, 0x75, 0xbb, 0xde, 0x92, - 0x9a, 0x08, 0xad, 0x71, 0x93, 0x71, 0x58, 0x24, 0x7c, 0x17, 0x75, 0x38, 0x41, 0x21, 0x09, 0x20, 0x36, 0xc5, 0x08, - 0x53, 0xd0, 0x9a, 0x71, 0xb1, 0xa1, 0x85, 0xdd, 0x44, 0x77, 0xac, 0xcd, 0x23, 0xca, 0x38, 0xdc, 0xd1, 0x4c, 0x87, - 0xb9, 0xb9, 0x96, 0xe0, 0x7b, 0x89, 0xe8, 0x6d, 0xaa, 0xa6, 0x1d, 0x15, 0x36, 0xb7, 0x69, 0x64, 0xcc, 0x4c, 0x8f, - 0x77, 0x81, 0x76, 0xe3, 0xc9, 0xe8, 0x27, 0x54, 0xf0, 0xe7, 0x73, 0x5f, 0x24, 0x03, 0xf7, 0xd9, 0xe7, 0x01, 0x62, - 0x68, 0x4f, 0x9d, 0xee, 0x37, 0xb5, 0xac, 0x73, 0xc0, 0x14, 0x9b, 0xc4, 0xec, 0x67, 0x1c, 0xf5, 0x87, 0x1d, 0x6d, - 0x1c, 0x24, 0xc5, 0x10, 0x28, 0x1d, 0x7e, 0xdc, 0xd1, 0xca, 0xeb, 0xb6, 0xec, 0xdd, 0xf6, 0x1a, 0x77, 0xe4, 0x63, - 0xaa, 0x07, 0x93, 0x20, 0x49, 0xcb, 0xb1, 0x08, 0xcd, 0x18, 0xbc, 0x45, 0x5a, 0xb0, 0xb6, 0x47, 0x40, 0xcb, 0x5c, - 0x2f, 0x14, 0x7a, 0xe0, 0xe9, 0x3b, 0x73, 0x27, 0x85, 0xc5, 0x58, 0x2e, 0xe9, 0xe0, 0xd9, 0x04, 0xb3, 0x59, 0xd5, - 0x6a, 0x7d, 0x77, 0x68, 0x7b, 0xea, 0x2d, 0x10, 0x76, 0x5e, 0xea, 0x9b, 0x81, 0x23, 0x3f, 0xb3, 0x96, 0xc1, 0x94, - 0x73, 0xbb, 0xc1, 0xbb, 0xfe, 0xe8, 0x6f, 0xca, 0xe0, 0x63, 0x7f, 0x8d, 0xe3, 0xf7, 0x54, 0xdd, 0xb2, 0x74, 0xc2, - 0x74, 0x65, 0x3e, 0x46, 0x2b, 0x35, 0xf7, 0x39, 0x8c, 0xc9, 0x74, 0x80, 0x12, 0x1b, 0xf9, 0xba, 0x0b, 0x07, 0xd4, - 0x2d, 0xa3, 0xf8, 0x8a, 0x5f, 0xd6, 0x6f, 0xf7, 0x25, 0xed, 0x6d, 0xf7, 0x5b, 0x30, 0x53, 0xaf, 0xac, 0x04, 0x8f, - 0x0a, 0x02, 0x3c, 0x04, 0x95, 0xc9, 0xa3, 0xca, 0x12, 0xf0, 0x45, 0xbd, 0x0b, 0x90, 0x88, 0x3c, 0xad, 0x47, 0x79, - 0x09, 0x1b, 0xd5, 0xb0, 0xed, 0x7a, 0x5a, 0x1d, 0x08, 0x89, 0xd1, 0x1c, 0x4f, 0x9b, 0xb5, 0xe6, 0x5a, 0x19, 0x7e, - 0x89, 0x12, 0x17, 0xcf, 0xc6, 0x51, 0xb5, 0x51, 0x20, 0xe4, 0xaa, 0x16, 0x4a, 0xc4, 0xa2, 0xc3, 0x42, 0xa6, 0xf2, - 0x65, 0x65, 0x2c, 0x7b, 0x71, 0xb4, 0x9c, 0xc8, 0xd7, 0xf6, 0xd2, 0xc2, 0x7e, 0x1f, 0x1a, 0x7f, 0xfb, 0x50, 0x61, - 0xca, 0xea, 0xa7, 0x3d, 0x19, 0x71, 0x8d, 0xf5, 0xb1, 0xf5, 0xf6, 0xa1, 0x7f, 0x7c, 0xaf, 0xa6, 0x66, 0xbc, 0xed, - 0x90, 0xee, 0x96, 0x03, 0xb6, 0xc2, 0xdb, 0xc3, 0x96, 0xfc, 0xef, 0xb7, 0x2f, 0x76, 0xec, 0x82, 0xcc, 0x27, 0x2c, - 0x18, 0x91, 0x14, 0x8f, 0x4d, 0x06, 0x50, 0x6e, 0x19, 0xd0, 0x88, 0x60, 0x5f, 0x37, 0x76, 0xe4, 0x6b, 0xcb, 0x1c, - 0x97, 0xe9, 0xb2, 0x1f, 0x20, 0xcb, 0xbe, 0x0c, 0x81, 0x9d, 0xdb, 0x32, 0xe4, 0x80, 0x59, 0x1c, 0xc8, 0xcc, 0x4c, - 0xfb, 0x8f, 0x5a, 0x5e, 0xa1, 0x53, 0x4a, 0xb6, 0x33, 0x1f, 0xd0, 0xad, 0x31, 0xd9, 0xe8, 0x42, 0xb0, 0x2e, 0x74, - 0xb2, 0x23, 0xdc, 0xb8, 0x37, 0xd2, 0x0f, 0x8e, 0x6e, 0x31, 0xa7, 0x81, 0x11, 0xcf, 0xb4, 0x98, 0x16, 0x68, 0xc4, - 0x4f, 0x72, 0x55, 0x2f, 0xf5, 0x40, 0xd6, 0xe9, 0x5a, 0x8c, 0x2e, 0xdf, 0x08, 0x6c, 0xf6, 0x44, 0x9c, 0xcc, 0xa1, - 0xde, 0x21, 0x20, 0x25, 0x5a, 0xa5, 0xef, 0xd6, 0x01, 0xa1, 0x9d, 0x80, 0x65, 0x5a, 0x62, 0xaf, 0x53, 0x32, 0xda, - 0xf7, 0x6f, 0xfc, 0x49, 0x39, 0x0d, 0xd4, 0x52, 0x89, 0xd1, 0x2d, 0x41, 0x41, 0xcc, 0x71, 0x5c, 0x3a, 0x6f, 0x8a, - 0x48, 0xcc, 0x58, 0x7f, 0x71, 0xf4, 0x3d, 0xa3, 0x1f, 0x40, 0xad, 0xa4, 0xa9, 0x70, 0xcc, 0x8d, 0x9a, 0x91, 0x85, - 0xc1, 0x97, 0x11, 0x62, 0xb7, 0xc5, 0x3f, 0x89, 0x3c, 0x9d, 0xa2, 0x15, 0xd0, 0x3d, 0x55, 0x2d, 0xb2, 0x92, 0x56, - 0x39, 0xd4, 0x29, 0xbf, 0x0a, 0x96, 0xc3, 0xe4, 0x58, 0xc6, 0x75, 0x16, 0x43, 0x98, 0x9c, 0xe5, 0x14, 0x4a, 0x6e, - 0x71, 0x0a, 0x5f, 0xb4, 0xcc, 0x2e, 0xc3, 0x1a, 0x2a, 0x20, 0x64, 0x1c, 0x84, 0xc3, 0x4f, 0xfe, 0x54, 0x68, 0x7f, - 0x33, 0x4b, 0x36, 0x7a, 0xf7, 0x51, 0x98, 0xa0, 0x07, 0xe7, 0x56, 0x31, 0x83, 0xc9, 0x10, 0x3d, 0x57, 0xa1, 0x15, - 0xdc, 0x89, 0xe7, 0xb4, 0xc8, 0xa9, 0x7a, 0xc8, 0xa0, 0x55, 0x37, 0xeb, 0x75, 0x5f, 0x47, 0x29, 0x27, 0x42, 0x48, - 0x23, 0x4e, 0x5a, 0x53, 0x35, 0xd5, 0x12, 0x7c, 0x44, 0x49, 0x46, 0x8a, 0x33, 0x03, 0xe4, 0xec, 0xa4, 0xa2, 0x56, - 0x02, 0xe5, 0x19, 0x4e, 0x2a, 0x66, 0x9a, 0x93, 0x18, 0xb0, 0xde, 0x35, 0xde, 0xcf, 0xa6, 0xe9, 0x02, 0x80, 0xea, - 0x4b, 0xc7, 0x48, 0x7d, 0xd6, 0xf1, 0xa4, 0x1e, 0xfa, 0x62, 0xd9, 0xff, 0xa8, 0x9d, 0x3a, 0x30, 0x1a, 0xc4, 0xb8, - 0xda, 0x8f, 0x30, 0x38, 0x37, 0x23, 0x86, 0xcd, 0xfc, 0x81, 0xad, 0x0e, 0xd8, 0x26, 0xaa, 0xb9, 0x48, 0xa2, 0xa5, - 0xe8, 0x79, 0xa6, 0xde, 0x85, 0x1a, 0x0d, 0xd5, 0x53, 0x77, 0x3d, 0xf2, 0xc8, 0x4a, 0xb7, 0x26, 0x32, 0x88, 0x14, - 0x4b, 0xa4, 0x0b, 0xaa, 0xf3, 0x8d, 0xc0, 0xd9, 0x4e, 0x06, 0xa6, 0x30, 0xd6, 0xa3, 0xb8, 0xa5, 0x09, 0xbf, 0x2b, - 0x19, 0xda, 0x29, 0x73, 0x54, 0xc6, 0x21, 0x07, 0xd7, 0xca, 0x3c, 0xf9, 0xf9, 0xb7, 0x3e, 0xa5, 0x11, 0x07, 0x78, - 0x4c, 0x7d, 0x7e, 0x86, 0xeb, 0xeb, 0x6f, 0x92, 0x5f, 0x8a, 0x5b, 0xe9, 0x27, 0x7c, 0x67, 0x89, 0x38, 0xef, 0xc1, - 0xf0, 0xad, 0xea, 0x71, 0x60, 0x11, 0xba, 0x72, 0x2e, 0xea, 0xc1, 0xf9, 0xd3, 0x0b, 0x82, 0x17, 0xe5, 0x80, 0x09, - 0x90, 0xa9, 0xe6, 0xac, 0x7e, 0x4b, 0xe4, 0x40, 0xc6, 0x45, 0x55, 0x9a, 0x3c, 0x81, 0xbc, 0x04, 0x9c, 0x3b, 0xc9, - 0x60, 0x32, 0x64, 0xdd, 0x8f, 0xb7, 0x9d, 0xc4, 0x77, 0xc0, 0xfa, 0x8f, 0x49, 0xc6, 0xb9, 0x06, 0x81, 0x14, 0x2b, - 0x69, 0x27, 0xab, 0xf4, 0x41, 0x81, 0x07, 0x26, 0x99, 0x9c, 0x97, 0x4d, 0x69, 0x33, 0x4f, 0xa0, 0x33, 0xa0, 0x8d, - 0xad, 0x4d, 0x19, 0x9f, 0x56, 0x80, 0x12, 0x12, 0xde, 0xc8, 0xd6, 0x56, 0x67, 0x90, 0xca, 0xaa, 0xf3, 0xcf, 0xf6, - 0x38, 0x53, 0x85, 0xbe, 0xe8, 0xa2, 0x39, 0x37, 0xef, 0x1d, 0x38, 0x1f, 0xd6, 0xe6, 0xe9, 0xcb, 0x9f, 0x12, 0x55, - 0x70, 0xd7, 0xa4, 0x01, 0xaa, 0xba, 0xe5, 0x25, 0x9d, 0xf1, 0x4f, 0xd8, 0x5f, 0x62, 0x09, 0x53, 0x90, 0xb4, 0x3f, - 0x84, 0x8f, 0x90, 0xf6, 0x11, 0xf2, 0x66, 0xfb, 0x3f, 0x4a, 0x99, 0x1c, 0x0f, 0xb6, 0x9a, 0xfd, 0xb0, 0x29, 0xfe, - 0x2d, 0xb2, 0x06, 0xee, 0xab, 0xf5, 0xc3, 0xaa, 0x32, 0x89, 0x3e, 0xae, 0x8d, 0x17, 0x94, 0x31, 0x86, 0xe9, 0x64, - 0xb1, 0xea, 0xba, 0x8c, 0x1b, 0x52, 0x66, 0x65, 0xf0, 0xd1, 0xe1, 0x03, 0x4d, 0x48, 0x2a, 0x74, 0x3e, 0xc5, 0xbc, - 0x34, 0xf3, 0xeb, 0x26, 0x15, 0xe1, 0x0f, 0x65, 0xce, 0x3b, 0x6f, 0x89, 0xba, 0xeb, 0x7d, 0xd5, 0x2f, 0x0f, 0x68, - 0xb4, 0x4d, 0x4f, 0x28, 0x07, 0x67, 0x70, 0x9a, 0x64, 0xf4, 0xcc, 0x44, 0x3c, 0x22, 0x1f, 0xe2, 0xfa, 0x45, 0x68, - 0xa4, 0x97, 0x87, 0x1c, 0x11, 0xbf, 0xcb, 0xe2, 0xee, 0x15, 0xbf, 0xd1, 0x5f, 0x92, 0x0f, 0x4b, 0x3a, 0x4a, 0x62, - 0xad, 0xdd, 0x0f, 0x73, 0x4c, 0xda, 0x40, 0xc5, 0xff, 0x0f, 0x13, 0xaf, 0x29, 0x8b, 0x2c, 0xa3, 0x25, 0xba, 0xaa, - 0x1d, 0x1c, 0xed, 0xc3, 0x22, 0x45, 0xbe, 0xc8, 0x10, 0x52, 0x44, 0xb7, 0x46, 0x79, 0x08, 0xaf, 0x27, 0xff, 0xa8, - 0x2c, 0xfc, 0x61, 0xd5, 0x4d, 0x4f, 0xa7, 0x91, 0x8a, 0x1f, 0xe9, 0xe8, 0xfb, 0x55, 0xdd, 0xde, 0x4f, 0x7b, 0xb3, - 0xd8, 0x43, 0xc0, 0xec, 0x33, 0x0d, 0x91, 0xbd, 0x59, 0xf6, 0x19, 0x86, 0x49, 0xdc, 0xe2, 0x8a, 0xd7, 0xa0, 0xa7, - 0xca, 0x56, 0xee, 0x0d, 0x38, 0xe3, 0x0b, 0x43, 0x07, 0x19, 0x8f, 0x96, 0x2b, 0x8f, 0xdf, 0xf0, 0x00, 0x4e, 0xaa, - 0xb6, 0xdb, 0xa2, 0x2c, 0xed, 0x19, 0x9c, 0x24, 0x8b, 0x78, 0x92, 0x79, 0xf1, 0x65, 0x4a, 0x2f, 0x29, 0xd9, 0x8c, - 0x12, 0xde, 0xd1, 0x17, 0xa2, 0x42, 0x2a, 0xb5, 0x21, 0x5f, 0x95, 0x92, 0x6d, 0x34, 0xa4, 0x52, 0xca, 0x15, 0x57, - 0xe3, 0x72, 0x1a, 0xaf, 0x8c, 0xed, 0x21, 0xbb, 0x85, 0x57, 0xc5, 0xeb, 0x14, 0x21, 0xbd, 0xbe, 0x46, 0x38, 0x71, - 0x53, 0x64, 0x90, 0xf8, 0x70, 0x56, 0xd2, 0xe5, 0xc9, 0x35, 0x58, 0xf3, 0x9c, 0xa3, 0x1c, 0xcc, 0xba, 0x3e, 0x50, - 0xe6, 0x7c, 0x93, 0xf6, 0xa8, 0xc8, 0x57, 0x4e, 0x9d, 0xab, 0x0d, 0xa8, 0xcb, 0x77, 0x02, 0x66, 0xe1, 0x3e, 0x1e, - 0x47, 0x25, 0xe9, 0x8d, 0x32, 0xe2, 0xc3, 0x9d, 0x20, 0xc5, 0x66, 0x9e, 0x8c, 0xc4, 0x3b, 0xda, 0xd8, 0xb9, 0x68, - 0xa4, 0x8f, 0x42, 0x7c, 0x4a, 0x50, 0x43, 0x1a, 0xa3, 0xd9, 0xc5, 0xee, 0x65, 0x90, 0x60, 0x88, 0x2c, 0xd9, 0x82, - 0x20, 0x44, 0x1e, 0x96, 0x31, 0x58, 0x52, 0x1f, 0x4d, 0xad, 0x60, 0x62, 0x99, 0x2b, 0x3f, 0x9c, 0xde, 0xa2, 0x57, - 0xeb, 0x48, 0x86, 0x5c, 0x27, 0xb1, 0x20, 0x6d, 0xc6, 0xcf, 0x75, 0x79, 0xd4, 0xde, 0x02, 0xab, 0xe9, 0x4a, 0xea, - 0x41, 0x63, 0x7a, 0xbc, 0x4e, 0x49, 0xb1, 0xb1, 0xce, 0x3a, 0x55, 0x15, 0xca, 0x7f, 0x9f, 0xad, 0x8a, 0x8b, 0xab, - 0x96, 0x6f, 0x71, 0x54, 0xef, 0x6c, 0x12, 0x02, 0x00, 0x35, 0x3c, 0xa4, 0xfa, 0x01, 0xc6, 0xb0, 0xdc, 0x33, 0xcc, - 0xb2, 0x0f, 0xd7, 0x1b, 0x34, 0x04, 0x6d, 0xc7, 0xe3, 0xc4, 0x16, 0xf9, 0x46, 0x0c, 0x68, 0xa4, 0xd4, 0x04, 0xd8, - 0x66, 0x85, 0x18, 0x3c, 0xeb, 0xf6, 0x27, 0x8a, 0x82, 0xa8, 0xe0, 0x88, 0x01, 0x10, 0x4e, 0x39, 0x2d, 0x3f, 0x2a, - 0xfc, 0xb0, 0x90, 0x60, 0x2a, 0x5e, 0x0e, 0xe4, 0xd3, 0x12, 0x10, 0x14, 0x83, 0xb2, 0x0c, 0x2d, 0x10, 0x82, 0xbe, - 0x99, 0x89, 0x51, 0x07, 0x67, 0x8c, 0xbe, 0x11, 0x31, 0xe0, 0x94, 0x02, 0x10, 0x8f, 0x39, 0x5d, 0x6b, 0x29, 0x5f, - 0x97, 0x2e, 0xfd, 0x8e, 0x9e, 0xca, 0x49, 0xe9, 0x85, 0xb0, 0x4d, 0xaf, 0x62, 0x5e, 0x8b, 0x4a, 0xa2, 0xeb, 0x65, - 0x73, 0x19, 0x1b, 0x9e, 0x2f, 0x5c, 0x9d, 0x56, 0x6f, 0xb6, 0xf0, 0xe1, 0x35, 0x17, 0x1f, 0x3e, 0x24, 0xb7, 0x2d, - 0xa3, 0xe0, 0xc3, 0x4e, 0xc3, 0x36, 0x72, 0x20, 0x08, 0xf0, 0xb7, 0xf5, 0xf5, 0x64, 0x6b, 0xb2, 0x15, 0x2e, 0x48, - 0x0f, 0xfb, 0x06, 0xdf, 0x0e, 0xc1, 0x9f, 0x68, 0xcd, 0x78, 0xcc, 0xd6, 0x3d, 0x34, 0xe4, 0xee, 0x65, 0x8d, 0x5f, - 0x30, 0x41, 0xe7, 0x67, 0x99, 0x79, 0x1f, 0x12, 0x5a, 0xee, 0x4b, 0xda, 0xe8, 0x11, 0xd3, 0x78, 0x14, 0x5d, 0x21, - 0xae, 0xf1, 0x2c, 0x3b, 0x3f, 0x1a, 0x1b, 0xb1, 0x9c, 0x38, 0x62, 0x3b, 0xcd, 0x2e, 0xdb, 0xe4, 0xd2, 0x52, 0x8d, - 0x6f, 0xef, 0x2a, 0x13, 0x8c, 0xaa, 0xa1, 0x7d, 0x5e, 0xd6, 0x67, 0x95, 0xcf, 0xfc, 0xfb, 0xfc, 0xad, 0x8b, 0x2a, - 0xc3, 0x1c, 0xa2, 0x19, 0x5f, 0xe3, 0x67, 0xa8, 0x4b, 0x28, 0xd2, 0x03, 0xf7, 0x7b, 0x99, 0xdd, 0x58, 0x73, 0x26, - 0x3f, 0xc2, 0x77, 0x4a, 0xb2, 0x0b, 0x6c, 0xc7, 0xbf, 0x8d, 0x7a, 0x2a, 0x94, 0x7e, 0xd4, 0x06, 0x16, 0x7f, 0x90, - 0xa4, 0x16, 0x24, 0x43, 0x09, 0x0e, 0xe2, 0xaa, 0x65, 0xef, 0xe9, 0x76, 0x6d, 0xc5, 0x82, 0x70, 0xe9, 0x6c, 0xed, - 0xe5, 0x8d, 0x69, 0x10, 0xe8, 0x44, 0x0b, 0xa3, 0xcd, 0xd9, 0x88, 0x79, 0xbc, 0xa1, 0x6a, 0x98, 0xbe, 0xa1, 0x34, - 0xb4, 0xc6, 0x17, 0xa0, 0x18, 0x26, 0x98, 0x22, 0xc2, 0xde, 0xb4, 0xf7, 0xf8, 0xc5, 0x86, 0xd5, 0x59, 0x50, 0xe3, - 0x55, 0x19, 0x21, 0x13, 0x97, 0x2b, 0x49, 0xf2, 0xe1, 0x3d, 0x81, 0xeb, 0xf8, 0xa7, 0xdd, 0x88, 0x77, 0x3d, 0xbe, - 0x93, 0x87, 0x65, 0x98, 0x98, 0x6e, 0xd1, 0x3a, 0x10, 0x43, 0x1c, 0x5b, 0xa1, 0x90, 0xa5, 0xfe, 0x58, 0xbd, 0x61, - 0x12, 0x8c, 0x9f, 0x1f, 0xac, 0xde, 0xcc, 0x8e, 0xff, 0x88, 0x06, 0x70, 0xee, 0x62, 0x1c, 0x81, 0x11, 0x66, 0x49, - 0x85, 0x1b, 0x65, 0x68, 0xa1, 0x8f, 0x8a, 0xab, 0xa9, 0x72, 0xe0, 0xc8, 0x12, 0xf2, 0x9a, 0xd2, 0xfe, 0x70, 0x3e, - 0xf3, 0xbb, 0x29, 0xf1, 0x33, 0x9d, 0x6e, 0xdf, 0xad, 0x1d, 0x56, 0x30, 0x1d, 0x07, 0xde, 0x1a, 0x29, 0xc8, 0xb1, - 0x14, 0xac, 0x6d, 0x39, 0x93, 0xe2, 0xb8, 0xa9, 0x3d, 0xeb, 0x55, 0x95, 0x9c, 0xd4, 0xfc, 0x6b, 0x9d, 0xac, 0x4d, - 0x3a, 0x73, 0x5b, 0x67, 0xfc, 0x74, 0x82, 0xbb, 0xf9, 0x5e, 0x69, 0x52, 0xf1, 0x3f, 0xcc, 0xaf, 0xb3, 0x64, 0xb5, - 0xf9, 0x78, 0xa1, 0x15, 0xb6, 0x89, 0x64, 0x80, 0xaf, 0xef, 0x34, 0x7d, 0x53, 0x20, 0x21, 0x6c, 0x57, 0xd3, 0xbd, - 0x0f, 0x0d, 0xd0, 0x9c, 0xb2, 0x13, 0xa4, 0xa8, 0x80, 0xd4, 0x9d, 0x58, 0x61, 0x90, 0x63, 0x60, 0x18, 0x3c, 0xf6, - 0x3e, 0xf5, 0x6e, 0x2d, 0x51, 0x57, 0x78, 0x2c, 0x34, 0x76, 0x63, 0xb0, 0x5a, 0x3e, 0x75, 0xe7, 0xff, 0x88, 0x5e, - 0xc1, 0xdf, 0x92, 0xf9, 0x1e, 0xf0, 0x0f, 0x82, 0x5a, 0xb6, 0x5a, 0x54, 0xde, 0x0a, 0xb9, 0x03, 0xfb, 0x78, 0x80, - 0x4f, 0x73, 0xf9, 0x40, 0x62, 0x6f, 0x8f, 0xcd, 0xdc, 0x75, 0x4d, 0xaf, 0xd5, 0x66, 0x6e, 0x75, 0xb4, 0x0c, 0x31, - 0x3a, 0x00, 0x20, 0x65, 0xc0, 0xf8, 0x29, 0xd6, 0x71, 0x67, 0xfc, 0x93, 0x79, 0xd0, 0xe7, 0x74, 0x7f, 0xf7, 0x3e, - 0x84, 0xdf, 0xd2, 0x12, 0xf1, 0x5d, 0xc4, 0xff, 0x1d, 0x5c, 0xf8, 0xd6, 0x31, 0x51, 0x25, 0x65, 0x07, 0x57, 0xe7, - 0xf0, 0x4d, 0xcf, 0x7b, 0x17, 0x57, 0x31, 0x8e, 0xbe, 0x87, 0x65, 0xf1, 0x47, 0x42, 0xa3, 0x29, 0x7c, 0x2d, 0x62, - 0x93, 0x97, 0xd0, 0x70, 0x33, 0x61, 0xb1, 0x8d, 0x2e, 0xcb, 0x1a, 0xc2, 0xeb, 0x7d, 0xa2, 0xb2, 0x8b, 0x27, 0x93, - 0x89, 0xba, 0xbe, 0x64, 0x29, 0xc0, 0xe5, 0xa6, 0x9a, 0xd1, 0x4b, 0xfb, 0x76, 0x8f, 0xba, 0xf4, 0x74, 0xff, 0xc1, - 0x65, 0x04, 0xaf, 0xd3, 0x66, 0xab, 0x3c, 0x37, 0x7d, 0x6a, 0x23, 0x3a, 0xa2, 0x7d, 0x5b, 0x57, 0xea, 0x05, 0x00, - 0x3a, 0xc0, 0x8b, 0xe3, 0x26, 0xba, 0x6a, 0xfa, 0xc7, 0x11, 0x90, 0xd6, 0xfc, 0x1e, 0x9b, 0x55, 0xb9, 0x91, 0x57, - 0x6a, 0x57, 0x09, 0xca, 0x8e, 0xf3, 0xe3, 0xbb, 0xd6, 0x5b, 0x3d, 0xbc, 0x54, 0x50, 0x29, 0xac, 0x6d, 0x7a, 0x6f, - 0xe9, 0xa4, 0xa7, 0x7d, 0x7e, 0x70, 0x5a, 0x50, 0x37, 0x74, 0xa9, 0xf5, 0x65, 0x07, 0x1e, 0xb5, 0x3e, 0x80, 0x9c, - 0xee, 0x60, 0x84, 0x23, 0x7a, 0x7f, 0x25, 0x6d, 0x09, 0xf0, 0x06, 0x68, 0x57, 0x9c, 0x80, 0xb6, 0x1d, 0x77, 0xe3, - 0xe6, 0x5b, 0xf8, 0xb3, 0x47, 0x90, 0x50, 0x5d, 0x75, 0x6e, 0xc9, 0xb4, 0x6b, 0x41, 0x45, 0x48, 0x2a, 0x24, 0x24, - 0x1c, 0x2e, 0x57, 0x97, 0x82, 0x51, 0x12, 0xd0, 0x57, 0x85, 0xc7, 0x43, 0xd9, 0xdb, 0x6e, 0x37, 0xae, 0x95, 0x91, - 0x64, 0x1a, 0xa8, 0x82, 0xc7, 0xd4, 0x1d, 0x72, 0x1f, 0x8f, 0x52, 0xb5, 0x90, 0x1e, 0xeb, 0x1f, 0x10, 0x24, 0x0d, - 0x0a, 0x1e, 0x99, 0x58, 0xdc, 0xd1, 0x40, 0xd4, 0x4a, 0x87, 0x1a, 0x66, 0xf6, 0x8e, 0x0b, 0x2e, 0xe6, 0xa8, 0x34, - 0xec, 0x32, 0xe0, 0x49, 0x66, 0x96, 0x41, 0x9f, 0x20, 0x77, 0x55, 0x3d, 0x15, 0xa6, 0xc3, 0x72, 0xc2, 0x00, 0xf1, - 0x94, 0xfa, 0x95, 0xdb, 0x5c, 0x37, 0xf8, 0x96, 0x24, 0x07, 0x60, 0xc0, 0xae, 0xb7, 0x42, 0xda, 0x2a, 0xdb, 0xa5, - 0xb2, 0xb1, 0x64, 0x25, 0x6c, 0xb8, 0xec, 0x62, 0x15, 0x01, 0xad, 0x20, 0xfa, 0x71, 0x8d, 0x30, 0x92, 0xfe, 0x42, - 0xa6, 0xd9, 0xb0, 0xfd, 0x39, 0xa6, 0xd5, 0x92, 0xdb, 0xb9, 0x25, 0xda, 0x00, 0x0d, 0xf8, 0x31, 0x86, 0xac, 0x25, - 0xb5, 0x26, 0xf6, 0xd6, 0xc5, 0xe4, 0xf9, 0x86, 0xe1, 0x69, 0x63, 0xd6, 0xcb, 0x64, 0xe3, 0xea, 0xc6, 0xa7, 0xb9, - 0x14, 0x1f, 0x0c, 0xba, 0x28, 0x4c, 0xa9, 0x39, 0x56, 0xe4, 0x5f, 0x02, 0xeb, 0xc2, 0x65, 0x42, 0xb2, 0x99, 0xca, - 0x84, 0x80, 0xc6, 0x6e, 0xcf, 0x08, 0x71, 0xf6, 0x03, 0x71, 0x26, 0xef, 0x2b, 0x5a, 0xd4, 0x20, 0x4f, 0x18, 0x8b, - 0x5f, 0xf6, 0xb0, 0xbb, 0x4d, 0xf3, 0xbc, 0x60, 0xcf, 0xb4, 0x62, 0x9d, 0x68, 0x26, 0x5c, 0x4f, 0xc9, 0xea, 0x1a, - 0x21, 0xe9, 0x53, 0xea, 0xf4, 0xc0, 0x8a, 0xa9, 0xbd, 0x53, 0x0a, 0x2c, 0x53, 0x10, 0x86, 0x76, 0xf2, 0xa8, 0x2c, - 0x29, 0xa9, 0x7a, 0x68, 0xbb, 0xb8, 0xa7, 0x50, 0x90, 0x31, 0xe2, 0xea, 0xb1, 0xcf, 0xcf, 0x00, 0x41, 0x79, 0x3a, - 0x83, 0x32, 0x7d, 0x4e, 0xb8, 0x91, 0xe7, 0x0c, 0x2d, 0xf2, 0x62, 0x62, 0x8e, 0x2a, 0x41, 0xd6, 0x48, 0xff, 0x55, - 0x84, 0x5c, 0x68, 0xf0, 0xf0, 0x48, 0x3a, 0x0d, 0xeb, 0x37, 0xc5, 0x0b, 0x0a, 0xce, 0x9f, 0xb2, 0x86, 0x18, 0xe7, - 0x86, 0x90, 0xe0, 0xfe, 0x70, 0x7f, 0xe6, 0x2e, 0x96, 0x11, 0x5a, 0xa5, 0x30, 0x2a, 0x2a, 0x99, 0x79, 0xe1, 0x87, - 0xb0, 0x0d, 0xf3, 0x62, 0x62, 0x50, 0x78, 0xdf, 0xa5, 0xf5, 0x99, 0x70, 0x88, 0xab, 0x6a, 0x8a, 0x79, 0x87, 0x14, - 0x35, 0x18, 0x4a, 0x6e, 0xf1, 0x5c, 0x33, 0x1a, 0x3d, 0xd6, 0x67, 0x46, 0x43, 0x6d, 0x92, 0xfc, 0x6a, 0x4e, 0xb0, - 0xb1, 0xe1, 0xa5, 0x90, 0xaa, 0x45, 0xc7, 0x01, 0xe1, 0x57, 0x1a, 0xc0, 0x5c, 0x68, 0x9a, 0xa7, 0x1d, 0x10, 0xb4, - 0xd2, 0x52, 0x0d, 0xa3, 0xaf, 0x08, 0x1e, 0x22, 0xa9, 0x1b, 0x83, 0x80, 0x8d, 0x60, 0x38, 0x04, 0xb4, 0xc5, 0x2f, - 0x2f, 0x7c, 0xa4, 0x61, 0xaa, 0x76, 0xec, 0x58, 0xce, 0x21, 0xa7, 0xca, 0xe0, 0x11, 0xff, 0x33, 0x11, 0x4c, 0xda, - 0xdc, 0x48, 0xbc, 0xa5, 0xec, 0xa6, 0x8e, 0xd3, 0xcc, 0x41, 0xfe, 0x96, 0x8e, 0xf6, 0x5a, 0xf9, 0xc2, 0x36, 0x99, - 0xb1, 0x57, 0xa3, 0x79, 0x28, 0x00, 0xb5, 0xff, 0x68, 0xdf, 0x65, 0xd1, 0x24, 0x7c, 0x3e, 0xbb, 0xef, 0x06, 0xf5, - 0x10, 0xd9, 0x99, 0x87, 0x62, 0xa5, 0xfb, 0x7a, 0xba, 0x34, 0x12, 0x1d, 0xc2, 0x35, 0xe6, 0x26, 0x9a, 0xed, 0x13, - 0x3d, 0x75, 0x26, 0xfb, 0xf9, 0xe8, 0x12, 0x2f, 0x67, 0x4e, 0x00, 0xd8, 0x23, 0x9e, 0x17, 0xdc, 0x51, 0xe2, 0x30, - 0xb5, 0xa9, 0x9d, 0x60, 0xa7, 0x3b, 0xda, 0xd8, 0xb5, 0x40, 0x29, 0x08, 0xa0, 0xf3, 0x7c, 0xfa, 0x7c, 0xfa, 0x32, - 0x86, 0xed, 0xd8, 0xc1, 0xe4, 0x64, 0x7e, 0xb1, 0x74, 0xcd, 0x6d, 0x91, 0xe9, 0xb0, 0xa4, 0x9b, 0x26, 0xe4, 0xbe, - 0x47, 0xe7, 0x36, 0xcf, 0xfa, 0xd3, 0xee, 0xda, 0x78, 0xa7, 0x21, 0x09, 0x8b, 0x00, 0xe5, 0xc5, 0x2e, 0x71, 0xe2, - 0xc0, 0x0d, 0xe7, 0xfb, 0x82, 0xc5, 0x82, 0x35, 0x12, 0x31, 0x44, 0x01, 0x19, 0x53, 0xff, 0xfc, 0x84, 0xee, 0xfa, - 0x1d, 0x5f, 0x0d, 0xa2, 0xe0, 0x98, 0x34, 0xd4, 0x9d, 0x57, 0x0f, 0xbb, 0x3e, 0xe6, 0x4c, 0x35, 0xc6, 0x7d, 0xee, - 0xfe, 0x80, 0x7d, 0xd7, 0x5a, 0xd3, 0x5c, 0x8f, 0x79, 0x69, 0x3b, 0xc5, 0x73, 0x0e, 0xe7, 0xf1, 0xe1, 0x7e, 0x1e, - 0xfc, 0x66, 0x78, 0x52, 0x29, 0xb6, 0x5d, 0x8e, 0x3c, 0xc9, 0x41, 0xd7, 0xf3, 0x1d, 0xfb, 0x78, 0x8f, 0xe1, 0x1e, - 0x24, 0x81, 0x0f, 0xaa, 0x54, 0x75, 0x96, 0xfb, 0x16, 0x0f, 0xc4, 0x06, 0x41, 0xe1, 0x75, 0x84, 0x78, 0x4d, 0x27, - 0xbf, 0x67, 0x07, 0xd8, 0x80, 0x2b, 0x20, 0x0f, 0xf8, 0x6c, 0xc5, 0x40, 0x5d, 0xc1, 0x90, 0xd9, 0xb7, 0x5b, 0x72, - 0x96, 0x66, 0x05, 0x3a, 0xe9, 0xf6, 0x26, 0x99, 0x5b, 0x0f, 0x34, 0xb0, 0x14, 0x89, 0x7c, 0xc9, 0xef, 0x58, 0x95, - 0x88, 0x45, 0x11, 0x9b, 0x4d, 0x3e, 0xc6, 0x62, 0x09, 0xf5, 0xfa, 0x52, 0xe4, 0x3d, 0x1f, 0x30, 0x67, 0x59, 0xc7, - 0xea, 0x9f, 0xc6, 0xee, 0x6e, 0x17, 0x31, 0xcc, 0xaf, 0x7f, 0xee, 0x81, 0xba, 0x58, 0x9e, 0xa7, 0xea, 0xcc, 0x30, - 0x82, 0xfd, 0x56, 0x2f, 0xb4, 0x1c, 0xb4, 0x31, 0x8f, 0xa9, 0xc9, 0x2d, 0xe9, 0xe3, 0x0b, 0xca, 0x89, 0x0e, 0xd0, - 0xfd, 0x15, 0x4a, 0xf7, 0x43, 0x47, 0x7d, 0xab, 0xfa, 0x7d, 0xe0, 0xa0, 0xea, 0x1c, 0x54, 0x77, 0x9c, 0x24, 0xb6, - 0x2b, 0x8a, 0x63, 0x58, 0x88, 0x6e, 0x0b, 0x76, 0xf8, 0x8c, 0x35, 0xcd, 0x1f, 0xe0, 0x80, 0xbb, 0x9b, 0x8c, 0x29, - 0x92, 0x4c, 0x3a, 0x9b, 0xd4, 0x1e, 0x00, 0xbd, 0x9f, 0xad, 0x73, 0x90, 0xbe, 0x5f, 0x3b, 0x54, 0xfb, 0xf3, 0xf8, - 0x80, 0xf3, 0x7c, 0xd9, 0xc4, 0x5c, 0x91, 0x38, 0x71, 0x85, 0x14, 0x74, 0x86, 0x50, 0xfa, 0x0b, 0x87, 0xbc, 0xcd, - 0xf3, 0xf4, 0xba, 0x99, 0xa8, 0x72, 0x27, 0xbb, 0x74, 0x82, 0x38, 0x78, 0x03, 0x01, 0x1e, 0x97, 0xfd, 0x5e, 0x6a, - 0xda, 0xe6, 0xc9, 0xed, 0x90, 0xd5, 0xea, 0xca, 0x77, 0xda, 0x07, 0x7c, 0x73, 0x93, 0x91, 0xc6, 0xf9, 0x9e, 0x87, - 0x9e, 0xca, 0xbe, 0x91, 0x35, 0x49, 0xed, 0xb7, 0x40, 0xc7, 0x55, 0x49, 0xc7, 0x18, 0x0d, 0x27, 0xf3, 0xe8, 0xbf, - 0x03, 0x31, 0x1c, 0xae, 0xcc, 0xbe, 0xd1, 0x38, 0x52, 0x74, 0xf8, 0xf2, 0xb0, 0x05, 0x47, 0xec, 0x49, 0x7c, 0x2f, - 0x5e, 0xe5, 0x4a, 0x97, 0xe8, 0x04, 0xb8, 0xed, 0x5d, 0x79, 0x63, 0xd3, 0xe5, 0xf3, 0xbf, 0x8f, 0x06, 0xdf, 0x1c, - 0x11, 0x31, 0x05, 0xaa, 0x24, 0xf6, 0xc1, 0xe6, 0x7b, 0x48, 0x68, 0xb2, 0x4b, 0x54, 0x61, 0xe8, 0x81, 0xb7, 0xd9, - 0xc6, 0x2d, 0x1c, 0x71, 0xf5, 0x55, 0x48, 0x80, 0xbd, 0x5c, 0xf7, 0xcc, 0xe8, 0x1e, 0xfc, 0xd4, 0xb4, 0x52, 0x84, - 0xc4, 0x37, 0x17, 0xf7, 0x0d, 0x1b, 0x8d, 0x58, 0xf6, 0x42, 0x66, 0x5d, 0x3c, 0x4a, 0xd1, 0xd3, 0x2a, 0xc3, 0xe9, - 0xa5, 0x3c, 0x27, 0x26, 0xab, 0x2c, 0xc8, 0x86, 0xae, 0x9e, 0xbe, 0xe5, 0xba, 0xf7, 0x56, 0x43, 0xf6, 0x12, 0xdf, - 0xbd, 0x72, 0x17, 0x20, 0xc7, 0xc4, 0xd3, 0x19, 0xd8, 0x05, 0xa9, 0x68, 0xaf, 0x97, 0x15, 0x36, 0x38, 0x56, 0x89, - 0xed, 0x14, 0x7c, 0x20, 0x36, 0x9f, 0x0b, 0x2e, 0x15, 0xa4, 0x2f, 0xc9, 0xfa, 0xfc, 0x2a, 0xc4, 0x1a, 0x98, 0x24, - 0xf0, 0xfe, 0xb3, 0x2c, 0x66, 0xfb, 0x12, 0x07, 0x08, 0x1c, 0x17, 0xef, 0x7b, 0x40, 0xef, 0x6f, 0x39, 0x92, 0x99, - 0x1c, 0xac, 0xc5, 0x7d, 0xc9, 0xcc, 0x08, 0xfe, 0xeb, 0xc7, 0x3b, 0x6b, 0x85, 0x8a, 0x5c, 0x8f, 0x61, 0x42, 0xb1, - 0xfb, 0x6e, 0xe7, 0x38, 0x37, 0x55, 0x82, 0x33, 0xa8, 0xe5, 0xef, 0xef, 0x78, 0x89, 0x86, 0x24, 0xe3, 0x36, 0x80, - 0xba, 0xac, 0x98, 0x74, 0x01, 0x2e, 0xea, 0xad, 0xc8, 0xd8, 0x51, 0xb0, 0xc7, 0x52, 0x6b, 0x76, 0x9c, 0x03, 0xc9, - 0xae, 0x16, 0x1a, 0x6d, 0x89, 0x22, 0xf7, 0x02, 0x62, 0x97, 0xcc, 0xf7, 0x75, 0xc5, 0x91, 0xee, 0x2a, 0x65, 0x4a, - 0x65, 0x4e, 0x39, 0x79, 0x92, 0x52, 0x7f, 0x63, 0xa8, 0x7a, 0xea, 0x0b, 0xec, 0x99, 0xb9, 0x3c, 0x5e, 0xcf, 0x37, - 0x7e, 0x24, 0x78, 0xbf, 0x56, 0x0c, 0x82, 0x58, 0xa1, 0xd9, 0x2e, 0x61, 0x32, 0x50, 0xa3, 0x3c, 0x39, 0x6e, 0x2c, - 0x37, 0x5e, 0xe2, 0x5f, 0x74, 0x95, 0x58, 0x99, 0x9f, 0xf5, 0x05, 0xb9, 0x0e, 0xde, 0xeb, 0x32, 0x2f, 0x49, 0xad, - 0xff, 0xb0, 0x3d, 0x1e, 0x4e, 0xd4, 0xaf, 0x37, 0xcc, 0xf3, 0xbb, 0x81, 0x54, 0x66, 0xdb, 0x51, 0x94, 0x95, 0x19, - 0x51, 0x0e, 0xed, 0x36, 0x01, 0xed, 0xa5, 0x5b, 0x5c, 0x40, 0xdd, 0xd8, 0xa2, 0x4b, 0x88, 0x61, 0xa0, 0xb8, 0x95, - 0x49, 0xa8, 0xce, 0xc6, 0x21, 0x4d, 0x29, 0x64, 0x8f, 0x88, 0xc5, 0x84, 0x85, 0xfa, 0xa7, 0xc3, 0xd3, 0xac, 0x06, - 0x5a, 0xef, 0x91, 0x6a, 0x8e, 0x15, 0xef, 0x1a, 0xaa, 0xb1, 0xb0, 0xd1, 0x2a, 0xff, 0x22, 0xc7, 0x8d, 0x43, 0x94, - 0x37, 0x5d, 0xe8, 0xe8, 0xc2, 0xbf, 0xa6, 0xd2, 0x49, 0x03, 0x2e, 0xce, 0xc5, 0x91, 0x04, 0xfe, 0xdf, 0xba, 0x24, - 0x42, 0xf1, 0x5b, 0xc4, 0x8a, 0x20, 0xbe, 0x36, 0xad, 0xfc, 0x6b, 0x27, 0x7d, 0x4e, 0xbc, 0xa3, 0x5d, 0xa5, 0x9a, - 0x49, 0x78, 0x31, 0x9c, 0xc8, 0x7c, 0x72, 0xe0, 0xc2, 0x57, 0x3e, 0x99, 0xec, 0xfe, 0x48, 0x28, 0x9f, 0xd8, 0xb3, - 0xc9, 0x71, 0x5a, 0x3b, 0xea, 0xfc, 0xe0, 0x97, 0x62, 0x07, 0xf3, 0xb0, 0x68, 0x53, 0x14, 0x8a, 0x5a, 0x1d, 0x8a, - 0x97, 0x45, 0x24, 0x82, 0x26, 0x14, 0xab, 0x87, 0x09, 0xc0, 0xc7, 0x4b, 0x8c, 0x72, 0x9f, 0xb5, 0x75, 0xa4, 0xfa, - 0xde, 0x84, 0x60, 0x65, 0xa0, 0xf6, 0xe8, 0x1c, 0x68, 0x13, 0x9b, 0x7a, 0xcc, 0xf2, 0x52, 0xab, 0x15, 0xee, 0x9a, - 0xd7, 0x71, 0x19, 0x5a, 0x95, 0xfc, 0x13, 0x64, 0x37, 0x9a, 0x53, 0x0c, 0x01, 0x45, 0x5f, 0x6e, 0x26, 0xb8, 0xe5, - 0xbe, 0x3f, 0x60, 0x38, 0x51, 0x9a, 0x15, 0xed, 0x29, 0x7a, 0x29, 0x12, 0xf3, 0x31, 0x96, 0x8e, 0xdf, 0xb3, 0x39, - 0xad, 0x28, 0x7d, 0x76, 0x67, 0xa0, 0xb8, 0x09, 0x74, 0x59, 0x37, 0x35, 0x4e, 0xd8, 0xb3, 0xb4, 0x6c, 0xf7, 0xdc, - 0xca, 0xb1, 0xa2, 0xad, 0x51, 0xc6, 0x4c, 0xaf, 0x34, 0x4b, 0x12, 0x18, 0xfe, 0xb1, 0xd5, 0x38, 0x0a, 0x07, 0xec, - 0x3a, 0xeb, 0xe1, 0x57, 0x68, 0xd8, 0x66, 0xca, 0x3f, 0xd2, 0xe2, 0xb9, 0xf8, 0x64, 0x6a, 0x30, 0xbf, 0x17, 0xa8, - 0x90, 0xb8, 0xf8, 0x4c, 0x34, 0xfd, 0x3e, 0xda, 0x5f, 0x47, 0x05, 0xc8, 0x98, 0x2a, 0x63, 0xe5, 0xff, 0x2b, 0x6d, - 0xd9, 0x6e, 0xc7, 0x71, 0xcd, 0x90, 0xc8, 0xa0, 0xd2, 0xe3, 0x2e, 0xee, 0xe9, 0xd7, 0xd1, 0x7f, 0x89, 0xa8, 0xae, - 0xdc, 0x79, 0x45, 0x5d, 0xf3, 0x5d, 0x52, 0x8b, 0xcc, 0x5e, 0xbf, 0x7b, 0xd5, 0x2a, 0x75, 0x50, 0x63, 0x5b, 0x6c, - 0xbc, 0xae, 0x2d, 0x7e, 0x7d, 0x00, 0xcd, 0xde, 0xe4, 0x37, 0xb3, 0x5d, 0x75, 0x8d, 0xd4, 0xa9, 0xd1, 0xd8, 0x31, - 0x8c, 0xde, 0xde, 0x0c, 0xbb, 0x0d, 0x3e, 0xb6, 0x46, 0x40, 0xab, 0x98, 0xbd, 0xfe, 0xbd, 0x0a, 0x0a, 0x7d, 0xab, - 0x9f, 0xc7, 0xba, 0xc9, 0xb8, 0xfc, 0xa1, 0x82, 0x40, 0x33, 0x4b, 0xe4, 0x51, 0x1e, 0x37, 0x8f, 0xde, 0x7a, 0xe2, - 0xb7, 0x36, 0xcf, 0xdd, 0xe4, 0x9e, 0x7c, 0xda, 0xaf, 0xe2, 0x36, 0x57, 0xf5, 0x2d, 0xe3, 0x2a, 0xe8, 0xb0, 0xdc, - 0x96, 0xaf, 0x0c, 0xbf, 0x57, 0xd0, 0xe1, 0x14, 0xfd, 0xfb, 0xe4, 0x0f, 0x1b, 0xb6, 0x8f, 0xda, 0x94, 0x50, 0x39, - 0x34, 0xbf, 0x51, 0x1f, 0x12, 0x98, 0x22, 0xb3, 0x8b, 0x3a, 0xe7, 0x5c, 0xb4, 0xa3, 0x65, 0x53, 0x6d, 0xad, 0x21, - 0xa1, 0x24, 0x90, 0x6a, 0x09, 0xc6, 0xad, 0xfd, 0x39, 0x69, 0x8f, 0xb8, 0x56, 0x50, 0x0e, 0x9d, 0xa3, 0xcc, 0x6f, - 0x45, 0xc8, 0xe7, 0x39, 0x6c, 0x6f, 0x71, 0xe0, 0x47, 0x10, 0x9f, 0x2b, 0x5a, 0x07, 0xf2, 0xfc, 0x51, 0x56, 0x2e, - 0x67, 0xb5, 0x6f, 0x27, 0x11, 0x33, 0x55, 0x3b, 0xb0, 0xe5, 0x05, 0xaf, 0xcc, 0x16, 0x76, 0xf7, 0xa4, 0x63, 0xbd, - 0xc1, 0xdf, 0x1f, 0x12, 0xd7, 0xa1, 0x1f, 0x79, 0xc9, 0x61, 0x5b, 0xd6, 0x53, 0xea, 0x56, 0xc7, 0x69, 0x37, 0xc5, - 0x62, 0x3b, 0xeb, 0x44, 0x6f, 0x83, 0xed, 0x6a, 0xe7, 0x51, 0x3e, 0x9d, 0x39, 0xc6, 0x35, 0xe9, 0x72, 0x3f, 0xa6, - 0xe9, 0x54, 0x6b, 0x88, 0x96, 0x2d, 0xa5, 0x7b, 0xac, 0x57, 0x2c, 0x60, 0x6b, 0xf6, 0xfe, 0xa1, 0x68, 0xeb, 0xa2, - 0x2d, 0x25, 0x28, 0x66, 0x6a, 0xf3, 0xd6, 0x22, 0x98, 0x3f, 0x92, 0x37, 0xeb, 0xa4, 0xce, 0x44, 0x5b, 0x53, 0x9f, - 0xfc, 0xa3, 0xa9, 0x47, 0xde, 0x17, 0x2c, 0xc5, 0x42, 0x3f, 0xac, 0x77, 0x0b, 0x8c, 0x25, 0xf4, 0x8c, 0xa1, 0x6d, - 0xce, 0xad, 0x23, 0x97, 0x90, 0xe5, 0x30, 0xe5, 0x8a, 0xc3, 0x69, 0x0e, 0x91, 0x25, 0xdd, 0xff, 0x97, 0xb7, 0x5e, - 0xcb, 0x48, 0xaf, 0x4f, 0xe8, 0xb8, 0x53, 0xf8, 0xf3, 0x32, 0x59, 0x40, 0x39, 0xd6, 0x56, 0x7a, 0x5e, 0xd9, 0x17, - 0x91, 0xf9, 0x28, 0x2e, 0xfc, 0x1f, 0xbe, 0xf2, 0x58, 0xfa, 0x9d, 0x75, 0xfd, 0x98, 0xba, 0xe4, 0xaf, 0xb9, 0x8f, - 0x86, 0x4e, 0x5a, 0x08, 0x99, 0xfc, 0x9f, 0x48, 0xca, 0x8e, 0x2c, 0xc2, 0xa3, 0x03, 0x9c, 0xc0, 0xce, 0x9d, 0x6c, - 0x49, 0x2b, 0x21, 0x19, 0x88, 0xae, 0xd1, 0x1c, 0xcd, 0x40, 0x36, 0x69, 0x03, 0x21, 0x3c, 0x6e, 0xce, 0x7d, 0x97, - 0xb9, 0x44, 0xfa, 0x65, 0x1e, 0xcd, 0xd0, 0x3d, 0x33, 0x64, 0xd1, 0x04, 0xa2, 0x23, 0x29, 0xc3, 0x56, 0xdb, 0xee, - 0xaf, 0x26, 0x76, 0x1f, 0x67, 0xd4, 0xb7, 0x07, 0xdc, 0x67, 0x84, 0x94, 0xdb, 0x51, 0x8e, 0x9a, 0x7e, 0xf0, 0x55, - 0x6b, 0x37, 0x87, 0x50, 0x17, 0x33, 0xe4, 0xb2, 0x00, 0x25, 0xbc, 0x58, 0xef, 0xeb, 0xf3, 0x13, 0xfd, 0xf1, 0x97, - 0x89, 0x21, 0xaa, 0x9a, 0x35, 0x69, 0x8a, 0x01, 0xb8, 0x8d, 0x39, 0xdf, 0xed, 0xbc, 0xf3, 0xe1, 0xdc, 0x6c, 0x41, - 0x98, 0xad, 0xa0, 0x18, 0xdd, 0x7c, 0x6c, 0xb0, 0x20, 0x88, 0xd7, 0x9f, 0x28, 0x51, 0xa4, 0x07, 0xf5, 0xc9, 0xd4, - 0x97, 0xb2, 0x90, 0x41, 0x8a, 0x86, 0x45, 0xd1, 0xad, 0x6e, 0x59, 0xd7, 0x05, 0x7f, 0x0a, 0x43, 0x96, 0x6f, 0x60, - 0x78, 0xb2, 0x49, 0xd2, 0xb9, 0x2e, 0x61, 0x8a, 0x27, 0xf3, 0x32, 0x47, 0x2a, 0xf3, 0x3e, 0x43, 0x3b, 0xbd, 0xfd, - 0xe4, 0x1f, 0xd8, 0x0a, 0x87, 0xfa, 0x32, 0x39, 0xf9, 0xdb, 0x07, 0xfe, 0xfe, 0xac, 0x65, 0xc5, 0xd4, 0x72, 0xb5, - 0x98, 0xac, 0xbc, 0x2a, 0x38, 0xa7, 0x24, 0x2a, 0xb8, 0xb4, 0xa2, 0xf3, 0x03, 0x0f, 0x89, 0x6d, 0xfc, 0xa5, 0x40, - 0xe6, 0xe2, 0x91, 0xbd, 0x67, 0x07, 0xb5, 0x46, 0x20, 0x14, 0xc4, 0x2c, 0xaa, 0x05, 0xbe, 0x33, 0x59, 0x37, 0x66, - 0xf6, 0x92, 0x14, 0x68, 0x31, 0x1a, 0x6c, 0xfb, 0xd1, 0x47, 0x43, 0xbc, 0x2a, 0x85, 0x2b, 0xc9, 0xf8, 0xb3, 0x15, - 0xa6, 0x24, 0x0c, 0x59, 0xb9, 0x83, 0xbb, 0x2c, 0x56, 0xae, 0x45, 0x2e, 0x5f, 0xde, 0x7f, 0x9c, 0xaa, 0xda, 0x7b, - 0x44, 0x2c, 0x78, 0xfd, 0x4c, 0x51, 0xd5, 0x1a, 0x50, 0x26, 0xa3, 0x3b, 0xc6, 0x5d, 0x2c, 0xd4, 0x28, 0x6b, 0x66, - 0x57, 0xa0, 0xe6, 0xd8, 0xa6, 0xa2, 0x10, 0xe0, 0x8f, 0xb7, 0x97, 0xca, 0x05, 0x1e, 0xcc, 0x0d, 0x85, 0x28, 0xa3, - 0x2c, 0xdf, 0x99, 0x8c, 0x85, 0xd1, 0x51, 0x2b, 0xc3, 0xbf, 0x89, 0x62, 0xf5, 0xdc, 0xb3, 0xd7, 0xc7, 0x49, 0xaf, - 0x1b, 0x61, 0xa0, 0xa9, 0x2c, 0x9b, 0x6e, 0xdb, 0xd6, 0x6d, 0x85, 0x6f, 0xaa, 0x15, 0xc8, 0x53, 0x80, 0xd6, 0x55, - 0xd8, 0x08, 0x38, 0x83, 0x63, 0xf6, 0x65, 0x80, 0x1e, 0x1a, 0x18, 0xab, 0xbf, 0xb4, 0x62, 0xb8, 0xb5, 0x21, 0xa8, - 0x07, 0xf1, 0xcb, 0x5c, 0x20, 0x64, 0x60, 0x81, 0x1d, 0x8d, 0xdc, 0x89, 0xdf, 0x76, 0x7a, 0x9f, 0x7e, 0xaf, 0x97, - 0x8d, 0xb6, 0x46, 0xc8, 0xac, 0xac, 0xb0, 0xdc, 0xe9, 0xde, 0xe9, 0x21, 0x6a, 0x94, 0x58, 0xe7, 0x2c, 0x34, 0x97, - 0xdd, 0x59, 0x35, 0x08, 0xae, 0x7e, 0x30, 0x28, 0x90, 0x1c, 0x0c, 0xc5, 0x76, 0x19, 0x41, 0xd0, 0x10, 0xd4, 0x47, - 0x79, 0x09, 0xb0, 0x66, 0x90, 0x43, 0x2b, 0xa3, 0xc5, 0xbf, 0xea, 0x8b, 0xfe, 0xd3, 0xff, 0xb1, 0xe8, 0x5d, 0x13, - 0x60, 0xd9, 0x1e, 0xae, 0x67, 0x67, 0x78, 0xc1, 0x0c, 0x1a, 0x15, 0xa3, 0x3d, 0x84, 0x53, 0x73, 0x9a, 0x88, 0x41, - 0x2d, 0x85, 0xd8, 0xfe, 0xc4, 0xa3, 0xe5, 0xe4, 0xc8, 0x43, 0xfe, 0xdb, 0x87, 0x12, 0x16, 0x9d, 0xe6, 0xcb, 0x73, - 0x04, 0x77, 0x05, 0x4e, 0x71, 0x82, 0xd9, 0xc2, 0xfe, 0xc9, 0x97, 0x4f, 0xa5, 0x89, 0x39, 0x74, 0x81, 0xa1, 0xcc, - 0xd5, 0x33, 0x22, 0x6f, 0x17, 0x99, 0xd1, 0xaa, 0x54, 0x09, 0x2d, 0x90, 0x43, 0xa6, 0xfc, 0x3c, 0x66, 0xc1, 0xa8, - 0x61, 0x3f, 0xd7, 0x8d, 0x64, 0x1f, 0x02, 0x33, 0x62, 0x8b, 0xda, 0x5c, 0x14, 0x83, 0x70, 0x85, 0xb8, 0xc9, 0x46, - 0xeb, 0x82, 0x96, 0x9e, 0xd2, 0x2e, 0xa9, 0xc8, 0x4d, 0x3c, 0xee, 0xc7, 0x51, 0xb8, 0xd5, 0xf2, 0x56, 0x8c, 0xde, - 0x83, 0x53, 0x59, 0xef, 0x1f, 0xe3, 0x0f, 0x86, 0x03, 0xc4, 0x51, 0x5c, 0x71, 0x62, 0xf7, 0xc3, 0xc5, 0x5f, 0xce, - 0xdc, 0x9e, 0x02, 0x97, 0x47, 0x6a, 0xf9, 0x72, 0xc5, 0xff, 0x13, 0x1f, 0xdd, 0x85, 0xd4, 0x0c, 0xe5, 0x07, 0xc1, - 0x03, 0x8f, 0xbc, 0x84, 0x8f, 0xfe, 0x0c, 0x3a, 0xfc, 0x6a, 0xe5, 0xb7, 0x53, 0xbf, 0x09, 0xef, 0x2d, 0xdc, 0x5e, - 0x6b, 0xae, 0xd6, 0x35, 0x56, 0x09, 0xe3, 0x0b, 0x6d, 0x3d, 0xfe, 0x92, 0x34, 0x26, 0x8c, 0xb3, 0x73, 0x0e, 0x0b, - 0x8d, 0x20, 0xc1, 0x2c, 0xb8, 0x49, 0x8f, 0x0f, 0x5c, 0xa6, 0x15, 0x51, 0x82, 0x10, 0x92, 0xcc, 0xf7, 0x63, 0xe8, - 0x2a, 0xb1, 0x1d, 0x89, 0x64, 0x54, 0x16, 0x87, 0x46, 0x9c, 0xaa, 0xf8, 0x69, 0x8a, 0x75, 0xc2, 0xa7, 0x9a, 0x81, - 0x87, 0x38, 0x89, 0xbc, 0xef, 0xec, 0xe6, 0x3d, 0x40, 0x2b, 0x0a, 0xd5, 0x0a, 0xfa, 0x2a, 0x9a, 0xb6, 0xfe, 0x7a, - 0x7b, 0x8f, 0x6d, 0x97, 0x3c, 0xa1, 0xd7, 0x73, 0xfc, 0xab, 0xda, 0xd5, 0x5a, 0x39, 0xa5, 0x6b, 0xfd, 0x74, 0xbb, - 0xb0, 0x98, 0x35, 0x7a, 0xbc, 0x98, 0x21, 0x6f, 0x05, 0xde, 0x6a, 0x7c, 0x8a, 0x36, 0x68, 0x82, 0xfb, 0x56, 0x6d, - 0x76, 0xc8, 0x4a, 0xb8, 0xfe, 0xac, 0x9e, 0x54, 0x92, 0x70, 0xa0, 0x31, 0x70, 0x58, 0x74, 0x19, 0xb4, 0x99, 0x3b, - 0x35, 0x70, 0x57, 0x24, 0x87, 0xd6, 0x1f, 0x58, 0xd1, 0x6c, 0xb5, 0x85, 0x0e, 0x34, 0x30, 0x0d, 0x7e, 0x1c, 0x99, - 0x79, 0x2c, 0xff, 0xd0, 0xf3, 0x5f, 0x06, 0x89, 0xae, 0xe3, 0x13, 0xec, 0x43, 0xf2, 0x45, 0x05, 0x4d, 0x87, 0x27, - 0x14, 0x2c, 0x3a, 0xc9, 0xd5, 0x26, 0x77, 0x19, 0x73, 0x28, 0xcb, 0x5d, 0xf5, 0x37, 0x23, 0xd1, 0xe9, 0xab, 0xf7, - 0x7c, 0x47, 0x3a, 0x2d, 0x6c, 0x08, 0x25, 0xce, 0x2f, 0x51, 0x5f, 0x71, 0x70, 0x66, 0xb1, 0x9e, 0xfe, 0xeb, 0xb5, - 0x4e, 0x58, 0x7b, 0xf0, 0x70, 0x58, 0xde, 0xb8, 0x20, 0xbf, 0x30, 0xd2, 0x92, 0x86, 0x01, 0x34, 0x5c, 0xb4, 0x38, - 0x35, 0xcb, 0x39, 0xf0, 0xc8, 0x2b, 0x73, 0xa2, 0x06, 0xaa, 0x3b, 0x7d, 0x1a, 0x1d, 0x94, 0xe0, 0x29, 0x5e, 0x9a, - 0xb2, 0x16, 0xd3, 0xf2, 0xa4, 0xd5, 0x1a, 0x4a, 0xbf, 0xb2, 0x24, 0x5d, 0x2b, 0x7c, 0x3a, 0xd7, 0xb4, 0x6a, 0xa8, - 0xc1, 0xbc, 0x0b, 0x02, 0xac, 0x28, 0x89, 0x5b, 0x9b, 0xe5, 0xdb, 0x6f, 0x7f, 0xd9, 0xe1, 0x18, 0x26, 0x3f, 0x7f, - 0x59, 0xc4, 0x6f, 0x1f, 0x6a, 0x98, 0xc7, 0x3c, 0x10, 0x17, 0x4f, 0x27, 0xfa, 0x39, 0xf5, 0x04, 0xcf, 0xa4, 0x5d, - 0xc4, 0x86, 0xd1, 0x80, 0xf3, 0xb7, 0x75, 0xab, 0x58, 0x58, 0x3b, 0x80, 0x61, 0x2e, 0xe8, 0x6b, 0x00, 0x18, 0x8e, - 0x50, 0x76, 0x21, 0x5a, 0x85, 0xea, 0xbd, 0xd1, 0x20, 0x6d, 0x6c, 0xb5, 0x27, 0x5a, 0x44, 0x10, 0x51, 0xbc, 0x8c, - 0x51, 0x0a, 0x8d, 0x41, 0x5e, 0xe2, 0x52, 0xb5, 0xc2, 0xce, 0xcb, 0x16, 0xfc, 0xb9, 0x70, 0x2a, 0x10, 0x44, 0x4d, - 0x64, 0x16, 0xb2, 0x91, 0x0d, 0x55, 0xda, 0x94, 0xd7, 0x59, 0xad, 0x46, 0x5c, 0xf3, 0xe1, 0xcd, 0x89, 0x05, 0xe4, - 0xec, 0xc0, 0xb6, 0x20, 0x0e, 0xab, 0x66, 0xc8, 0x89, 0x3e, 0xa7, 0x2d, 0xa3, 0xe7, 0x5b, 0xad, 0xb1, 0x53, 0xde, - 0x15, 0xea, 0x7e, 0xce, 0x47, 0x2c, 0x0c, 0x48, 0xed, 0xce, 0xff, 0x27, 0x68, 0x67, 0xdf, 0x97, 0x2b, 0x1d, 0xfe, - 0xe6, 0x6d, 0x31, 0x97, 0xdc, 0x8b, 0xa3, 0xc8, 0x15, 0xc7, 0x54, 0x08, 0x63, 0x5c, 0x84, 0x17, 0xfb, 0xe1, 0x55, - 0x67, 0x50, 0xe7, 0x65, 0x40, 0x43, 0x8e, 0x07, 0xf6, 0xde, 0x83, 0xa0, 0xc5, 0x17, 0x7b, 0x8b, 0xc6, 0x1a, 0x94, - 0x17, 0xc5, 0xb6, 0x0f, 0x20, 0xc3, 0xa6, 0xdc, 0xff, 0x8f, 0x9b, 0x17, 0xb9, 0x4b, 0x36, 0x12, 0x2f, 0x71, 0x29, - 0x5c, 0xb5, 0xf1, 0x77, 0x49, 0x05, 0x9f, 0x36, 0x62, 0x10, 0xcd, 0xb5, 0x93, 0x7f, 0x83, 0x65, 0xcb, 0xea, 0x2e, - 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8f, 0x6f, 0x6e, 0xbc, 0x0a, 0x0b, 0x7b, 0x38, 0x0c, 0x33, 0xde, 0xe3, 0x2e, 0x76, - 0xbd, 0xad, 0xaa, 0xd8, 0x2e, 0x32, 0xe6, 0xa2, 0xa9, 0x35, 0x46, 0x33, 0xb8, 0xb9, 0xa1, 0x85, 0xed, 0xdf, 0x4a, - 0xe8, 0x68, 0xf1, 0xb0, 0x75, 0x17, 0xe2, 0xe5, 0x75, 0xa1, 0x76, 0x14, 0x5c, 0xb2, 0x91, 0x94, 0x2c, 0xc8, 0xb0, - 0xee, 0x3b, 0xce, 0x01, 0x34, 0x85, 0xab, 0x11, 0xb7, 0x6b, 0xd9, 0x7e, 0x2d, 0xfd, 0xcb, 0xf2, 0x71, 0x33, 0xe8, - 0x90, 0x73, 0xa0, 0x10, 0x5f, 0x08, 0xd9, 0x9c, 0x10, 0x9d, 0xb4, 0x6d, 0xf5, 0x5e, 0x84, 0x23, 0xbf, 0x52, 0x64, - 0xea, 0x9f, 0x37, 0x33, 0x4c, 0xb5, 0x1e, 0xc1, 0xc0, 0x0e, 0x09, 0x57, 0xbf, 0xc5, 0xd0, 0xba, 0x65, 0xc0, 0xc6, - 0xaf, 0xe8, 0x6d, 0x3c, 0xab, 0x45, 0x0a, 0xf9, 0x05, 0x51, 0xdf, 0x5a, 0xd1, 0x04, 0xd7, 0xdd, 0x0b, 0x6b, 0x08, - 0xf3, 0x7b, 0x1a, 0x72, 0x0f, 0x6a, 0x03, 0xf9, 0x34, 0xdf, 0xef, 0x52, 0xf3, 0x07, 0x1c, 0xc1, 0x18, 0xe7, 0x1c, - 0xec, 0x9a, 0x7b, 0x6e, 0x8d, 0xa6, 0xaa, 0x6d, 0x03, 0x7b, 0x4b, 0xd7, 0xa3, 0x16, 0x1e, 0xbf, 0xed, 0xde, 0x3a, - 0xcb, 0x0e, 0xe3, 0x4d, 0xb9, 0x80, 0x8a, 0x45, 0x7b, 0xa1, 0xf2, 0x2c, 0x97, 0x31, 0x2e, 0x55, 0x20, 0x4e, 0x60, - 0x41, 0x4a, 0x6a, 0x6e, 0xca, 0x70, 0xcb, 0xd6, 0x65, 0x70, 0x34, 0x21, 0xdd, 0xfa, 0xf3, 0xcc, 0xe7, 0x66, 0x72, - 0x54, 0xd1, 0xa7, 0x08, 0xcc, 0x12, 0x7d, 0x5a, 0xc0, 0x51, 0xa6, 0xaf, 0x4b, 0x11, 0x24, 0xe2, 0xdd, 0xa0, 0xcf, - 0xb5, 0x02, 0x45, 0x21, 0x31, 0xf2, 0x2e, 0x7a, 0xb4, 0x40, 0x3f, 0x78, 0x1a, 0x8c, 0x49, 0x7c, 0xfa, 0xef, 0xb2, - 0x57, 0xf1, 0x29, 0x59, 0xca, 0xfa, 0xde, 0x90, 0x4a, 0xe4, 0x24, 0x0d, 0x91, 0x74, 0x7e, 0xaa, 0xc0, 0xd4, 0x71, - 0xee, 0xcd, 0x5f, 0xa1, 0x1f, 0x7a, 0x2b, 0x26, 0x08, 0xd8, 0x8f, 0x71, 0x11, 0xd7, 0xe5, 0x0b, 0xfb, 0x98, 0x0e, - 0xcc, 0x02, 0xa3, 0xd5, 0x19, 0xf1, 0x40, 0xd2, 0x49, 0xb0, 0x94, 0x5d, 0x33, 0x97, 0x3a, 0x00, 0xe4, 0x6b, 0x93, - 0xcb, 0xde, 0x11, 0xe2, 0x4b, 0x76, 0x7d, 0x47, 0x10, 0x29, 0x53, 0xad, 0xa2, 0x1d, 0xb9, 0x47, 0x9a, 0x08, 0x96, - 0xea, 0x14, 0x2d, 0x6d, 0xb3, 0xed, 0xed, 0xec, 0x78, 0xee, 0xef, 0x72, 0x5f, 0x61, 0x8a, 0x16, 0xd4, 0xdf, 0xc5, - 0x45, 0x52, 0x55, 0x10, 0x21, 0x66, 0x70, 0x83, 0xb3, 0x31, 0xe2, 0x52, 0xa9, 0xe4, 0xcf, 0xf6, 0x40, 0x73, 0xd3, - 0xab, 0xd4, 0x54, 0xb8, 0x1a, 0x0b, 0x9b, 0xd8, 0x52, 0x3b, 0xb0, 0x44, 0x82, 0x07, 0x4f, 0x6f, 0x71, 0x5f, 0x96, - 0xbb, 0x13, 0xc1, 0x69, 0xd1, 0xd2, 0x13, 0x0f, 0xcb, 0x44, 0xbe, 0x93, 0xdd, 0xee, 0x9a, 0x22, 0xcd, 0x1e, 0x37, - 0xe9, 0x0e, 0x47, 0x29, 0x63, 0x55, 0x69, 0xde, 0x81, 0x6b, 0x2e, 0x81, 0x8b, 0x8e, 0x11, 0xad, 0x87, 0x26, 0xf5, - 0x69, 0x00, 0x5a, 0x40, 0xb5, 0x16, 0x39, 0x0e, 0xea, 0x80, 0x89, 0x2b, 0x1a, 0x06, 0x97, 0x00, 0xb1, 0xf3, 0x19, - 0xb2, 0xf3, 0x59, 0xc8, 0xb7, 0x94, 0x9b, 0x6d, 0x90, 0x44, 0xbe, 0x6a, 0x7d, 0x28, 0x36, 0x23, 0xf1, 0xa1, 0xa1, - 0x0f, 0xcf, 0x35, 0xfa, 0xf1, 0xcd, 0x55, 0xbf, 0xe2, 0xad, 0xe3, 0x9c, 0x06, 0x1f, 0x93, 0x74, 0xd1, 0x0a, 0xcf, - 0x65, 0x79, 0xa7, 0x85, 0xa7, 0xf1, 0x14, 0x86, 0x53, 0x65, 0xfd, 0x6a, 0x73, 0xd5, 0xf2, 0xd4, 0x46, 0x51, 0x5f, - 0x49, 0xf1, 0xef, 0xce, 0xc4, 0x6a, 0x89, 0x98, 0x63, 0x52, 0xae, 0x79, 0x5a, 0x4d, 0x4b, 0xc7, 0xff, 0xfc, 0xd0, - 0xf9, 0xa5, 0xec, 0x04, 0xc0, 0x54, 0xc6, 0x18, 0x61, 0xc5, 0x7b, 0x19, 0x35, 0x43, 0xec, 0x25, 0xb3, 0xc3, 0x58, - 0xa3, 0xda, 0x3f, 0xdd, 0x7a, 0x14, 0xb6, 0x25, 0xe9, 0xe1, 0xde, 0x42, 0xf0, 0x85, 0xac, 0xf4, 0xef, 0xb6, 0x8e, - 0xb4, 0xe4, 0xc5, 0x45, 0x8c, 0x92, 0x20, 0x91, 0x8e, 0xa3, 0xb6, 0x56, 0x73, 0x13, 0x16, 0x1a, 0xc6, 0x52, 0x5b, - 0xa7, 0xac, 0x16, 0xb6, 0x14, 0x63, 0x8e, 0x64, 0x3c, 0x32, 0xcf, 0x48, 0xcf, 0x11, 0xde, 0xe5, 0xd6, 0xd1, 0xa0, - 0xea, 0xee, 0xb9, 0xf6, 0xc2, 0x8b, 0xf6, 0x25, 0xe7, 0x9f, 0x5b, 0x49, 0x0d, 0xc5, 0x9d, 0x0c, 0x8d, 0xea, 0x89, - 0xc3, 0xec, 0xda, 0xe4, 0x03, 0x41, 0x13, 0x27, 0x2b, 0x9d, 0xe1, 0xe7, 0xdc, 0xf2, 0x17, 0xc7, 0x53, 0x13, 0xad, - 0x81, 0x6d, 0x47, 0x16, 0x6a, 0x03, 0xfc, 0x06, 0x6f, 0x42, 0xb3, 0x80, 0x96, 0xb0, 0x18, 0xe2, 0xd4, 0xcd, 0x98, - 0x34, 0x49, 0x3a, 0x5d, 0x20, 0xfc, 0x74, 0x9b, 0x99, 0x8e, 0x65, 0x0f, 0x77, 0x39, 0x90, 0xa9, 0xa1, 0x14, 0x8f, - 0xa0, 0xb9, 0x3c, 0x89, 0x6e, 0xc6, 0x54, 0xc2, 0x37, 0x6c, 0x9f, 0xb3, 0xf4, 0x1e, 0xbd, 0x42, 0x9b, 0x9e, 0x05, - 0x2b, 0x8f, 0x1b, 0x41, 0x8b, 0x4c, 0x18, 0x20, 0xbb, 0xe7, 0x00, 0x96, 0x16, 0xdb, 0x8b, 0xa6, 0xa3, 0x23, 0x91, - 0x2d, 0xc6, 0xd6, 0x38, 0xc7, 0xe6, 0x2a, 0xd4, 0x82, 0x9d, 0xe5, 0x25, 0x50, 0x36, 0xb2, 0xc3, 0x3b, 0xc6, 0x9f, - 0xbc, 0x21, 0x01, 0x4c, 0x69, 0xea, 0xd3, 0x2e, 0x7a, 0x15, 0x6c, 0xef, 0xfa, 0x58, 0xc4, 0x81, 0x39, 0x70, 0xc3, - 0x58, 0x1a, 0x3b, 0x53, 0x75, 0xcd, 0x03, 0x5a, 0xa9, 0xaa, 0x2b, 0x06, 0x21, 0x09, 0xc6, 0xbc, 0x3c, 0x15, 0x52, - 0xb3, 0x50, 0x2d, 0xdd, 0x74, 0x6a, 0x9b, 0xa0, 0xb0, 0x38, 0x9e, 0x9a, 0x3d, 0x0c, 0x32, 0x5c, 0xbf, 0x7f, 0x66, - 0x06, 0x48, 0x12, 0xae, 0x04, 0x94, 0xd1, 0xb0, 0xb3, 0x6d, 0xd6, 0x43, 0xbf, 0xdd, 0x24, 0xa2, 0xdd, 0xae, 0x1c, - 0x33, 0xea, 0x83, 0xea, 0x85, 0xe1, 0xf4, 0xce, 0x08, 0x8d, 0x84, 0x04, 0xd8, 0xc8, 0x8f, 0xfa, 0x0b, 0x52, 0xb1, - 0xc4, 0x45, 0xdb, 0x79, 0x61, 0xd6, 0xef, 0xf3, 0x40, 0x66, 0xf0, 0x04, 0x9b, 0xe6, 0x2c, 0x82, 0x6a, 0x24, 0x0b, - 0x12, 0x04, 0x44, 0xd5, 0xb6, 0x4f, 0x55, 0xb5, 0x15, 0x34, 0xce, 0xe3, 0x17, 0x9c, 0x9e, 0x7e, 0x6d, 0x10, 0x54, - 0xe2, 0x5f, 0xd9, 0xbc, 0xc5, 0x6b, 0x60, 0x8b, 0xeb, 0x91, 0xf2, 0x45, 0x5d, 0x96, 0x3f, 0xba, 0xb0, 0x4a, 0xfa, - 0xf7, 0xd6, 0x58, 0x88, 0x2a, 0x7f, 0xba, 0x42, 0x21, 0xa9, 0x3c, 0xba, 0xf3, 0x46, 0xf0, 0x25, 0x3b, 0x89, 0xc6, - 0xa2, 0x9d, 0xf4, 0x84, 0x1d, 0xae, 0x4a, 0x23, 0x88, 0x14, 0xff, 0x62, 0x45, 0x90, 0xb8, 0x2a, 0x5a, 0x76, 0x32, - 0x68, 0x25, 0x7b, 0xa0, 0xce, 0x89, 0x1b, 0xf3, 0x72, 0x6d, 0xca, 0xb7, 0x77, 0x27, 0x3a, 0xc8, 0x1a, 0x93, 0xe0, - 0x51, 0x83, 0x7d, 0xcb, 0x64, 0xbb, 0xec, 0x38, 0xf5, 0xa6, 0xa7, 0xef, 0xb9, 0x19, 0x09, 0x69, 0x09, 0x10, 0xf9, - 0xda, 0x8d, 0xc4, 0xec, 0xd6, 0xe3, 0x6d, 0x47, 0x2c, 0xe6, 0x76, 0x22, 0x4a, 0xa3, 0x8e, 0x6b, 0xf3, 0x10, 0x85, - 0x60, 0x85, 0xb1, 0x44, 0x97, 0x5f, 0x49, 0xe4, 0x16, 0x0b, 0x1b, 0xfb, 0x58, 0x7d, 0xca, 0x61, 0x93, 0x03, 0x84, - 0x70, 0xa9, 0x5b, 0xfd, 0x2b, 0xf4, 0x36, 0x7b, 0x42, 0xbf, 0x62, 0xe4, 0xe0, 0xa1, 0x0c, 0xd6, 0xad, 0x79, 0xd7, - 0x82, 0xc7, 0x2a, 0x2a, 0xf7, 0x61, 0x11, 0x21, 0x14, 0xf7, 0xfb, 0xd1, 0x50, 0xed, 0x5a, 0x62, 0x44, 0xf4, 0x28, - 0x19, 0x48, 0x6d, 0x3a, 0x85, 0x2b, 0x51, 0xc4, 0xe5, 0xa5, 0x1d, 0xcf, 0x67, 0x3b, 0xbb, 0x1b, 0x8d, 0x34, 0xf6, - 0xdd, 0xc0, 0xf1, 0x72, 0x2b, 0xcd, 0x1a, 0x8b, 0xb6, 0xef, 0x67, 0xb7, 0xb6, 0x05, 0xa2, 0x30, 0x62, 0xc4, 0xdc, - 0xb6, 0xf3, 0x09, 0xe9, 0x60, 0x27, 0x9f, 0xb1, 0x8f, 0x0d, 0x8c, 0x67, 0x30, 0x9b, 0xaa, 0xbe, 0xf6, 0xee, 0x67, - 0xf6, 0xbf, 0x0b, 0x6a, 0x23, 0x3f, 0x5f, 0xae, 0x44, 0x08, 0x68, 0x5c, 0xe8, 0x45, 0x86, 0x88, 0x1e, 0x4d, 0xb2, - 0x73, 0xd7, 0xe8, 0x25, 0xf6, 0xba, 0x90, 0x61, 0x87, 0xe3, 0x8f, 0xd6, 0x66, 0x4f, 0x68, 0x8e, 0xbf, 0x9f, 0x5d, - 0x1b, 0xfb, 0x5a, 0x8d, 0x93, 0x2c, 0x58, 0x95, 0x89, 0xd3, 0xf5, 0x7b, 0x8e, 0x28, 0x3e, 0xd3, 0xa9, 0xfb, 0x8e, - 0x36, 0x9e, 0x49, 0xd9, 0x48, 0x2a, 0xdd, 0x48, 0xa0, 0x32, 0x2b, 0x93, 0x77, 0x7b, 0x01, 0x50, 0x6d, 0x04, 0x58, - 0x34, 0x17, 0x9a, 0xa9, 0xec, 0x8b, 0xce, 0xd3, 0x43, 0xa4, 0x1c, 0x0f, 0x6f, 0x8e, 0x96, 0xa1, 0xc5, 0xeb, 0xd3, - 0x9c, 0xfd, 0x9b, 0x5b, 0x0d, 0x1d, 0xed, 0x1d, 0x15, 0x49, 0x73, 0xc1, 0xf4, 0xff, 0x62, 0xc5, 0x34, 0x00, 0x84, - 0x83, 0x06, 0x9c, 0xae, 0x72, 0x83, 0x0b, 0x92, 0x17, 0x98, 0xe6, 0xe2, 0x4c, 0xa0, 0xb5, 0x0d, 0x44, 0x54, 0xb4, - 0xe6, 0x47, 0x97, 0x71, 0xf1, 0x88, 0x76, 0x8e, 0x41, 0x54, 0xd4, 0xdf, 0xf6, 0x99, 0xb4, 0x82, 0xd9, 0xe7, 0x1c, - 0xb8, 0x5e, 0x33, 0x95, 0x12, 0x14, 0x83, 0xed, 0xb6, 0xfd, 0x36, 0x65, 0x10, 0x6a, 0xf4, 0x77, 0x52, 0xa1, 0x03, - 0xa3, 0x20, 0x47, 0x08, 0xe4, 0xdd, 0x1e, 0xf4, 0x59, 0x50, 0xd4, 0x33, 0xe2, 0x80, 0x9d, 0xbf, 0x76, 0x1c, 0xce, - 0x50, 0x7c, 0x9d, 0xfb, 0xf1, 0xdb, 0xba, 0x68, 0x1e, 0xdc, 0xf8, 0x43, 0xff, 0xfe, 0x11, 0x6d, 0x8b, 0xf6, 0x09, - 0x36, 0xc7, 0xcf, 0xe8, 0xf0, 0xb6, 0x19, 0x9c, 0x79, 0x7b, 0x42, 0x23, 0x10, 0x5b, 0x90, 0x3c, 0x17, 0xe8, 0x9c, - 0x43, 0x13, 0x9e, 0x67, 0xcd, 0x4c, 0x7e, 0xfa, 0x26, 0x55, 0xee, 0xa3, 0xec, 0xf8, 0x58, 0x74, 0xbb, 0xc4, 0x33, - 0x94, 0x6e, 0xe7, 0x56, 0x72, 0xdb, 0x87, 0x60, 0xfe, 0xe1, 0xb7, 0xbb, 0xdd, 0x63, 0x65, 0xfe, 0xcf, 0x4f, 0xd6, - 0x44, 0x3f, 0xdb, 0x45, 0xf3, 0xcb, 0x2a, 0x08, 0x0a, 0x5f, 0xee, 0x3a, 0xbd, 0x2c, 0xd0, 0xb8, 0x43, 0xd5, 0xb5, - 0x86, 0xab, 0xb9, 0x9a, 0xb9, 0x67, 0x2e, 0xee, 0x38, 0x9f, 0x91, 0x97, 0xd5, 0xe2, 0x7a, 0x40, 0xbf, 0x7d, 0x35, - 0xe6, 0x3f, 0xbf, 0x84, 0x26, 0xe5, 0xdc, 0xfd, 0x89, 0xf0, 0x7f, 0x83, 0x6b, 0x7a, 0xe7, 0x8e, 0xa2, 0xe0, 0x8c, - 0xeb, 0x9a, 0x61, 0x9b, 0x9c, 0x73, 0xe1, 0xb8, 0x4e, 0x39, 0xf0, 0xea, 0x10, 0x9b, 0x80, 0x30, 0xad, 0x8c, 0x67, - 0x4e, 0x9f, 0x46, 0xf2, 0x67, 0x0c, 0x18, 0x76, 0x1d, 0x82, 0x86, 0x60, 0x40, 0x89, 0xc5, 0xe8, 0xd4, 0x9d, 0x8c, - 0xa9, 0x26, 0x42, 0xd6, 0x80, 0x2d, 0x81, 0x12, 0xad, 0x6f, 0x81, 0x00, 0x5a, 0x3a, 0x81, 0x97, 0x8d, 0x8a, 0x1e, - 0x2d, 0x59, 0xc3, 0xe0, 0x60, 0xfe, 0x47, 0x1c, 0x8e, 0xe0, 0x7c, 0x8b, 0x84, 0xb8, 0x9b, 0x5b, 0x8f, 0xd2, 0xc6, - 0xf4, 0x89, 0xbe, 0x66, 0x1f, 0xf5, 0x14, 0xa4, 0xf9, 0xaf, 0x8b, 0x01, 0x82, 0x61, 0x38, 0x4e, 0x38, 0x5e, 0x25, - 0xf3, 0x0b, 0xa2, 0x76, 0xb1, 0xfe, 0xe5, 0x0c, 0xc6, 0xf6, 0x6f, 0xbc, 0xb6, 0x91, 0xff, 0x7f, 0x83, 0x25, 0xb7, - 0xbf, 0xe4, 0xe6, 0xcb, 0xbf, 0x96, 0xc7, 0x5f, 0xbe, 0xe6, 0x5b, 0xbe, 0x9b, 0x26, 0x78, 0xa7, 0xeb, 0x5e, 0xc9, - 0x50, 0xf3, 0xf3, 0x15, 0x46, 0xb8, 0x86, 0xc1, 0xd1, 0x58, 0x00, 0x1f, 0x2a, 0xda, 0x1c, 0x3d, 0x1b, 0x28, 0x13, - 0xfb, 0x35, 0x1e, 0x51, 0xbd, 0x5e, 0x81, 0x8f, 0x5d, 0x8d, 0x6b, 0x99, 0x5e, 0x26, 0x5a, 0xf3, 0x5c, 0xd9, 0xa5, - 0x86, 0x8a, 0x3b, 0xda, 0x02, 0xbe, 0x41, 0x5f, 0x57, 0xbe, 0xc4, 0x3a, 0xb2, 0xd9, 0x94, 0x27, 0x09, 0x4a, 0x3c, - 0x70, 0xd1, 0xf0, 0xd5, 0x33, 0xdb, 0x62, 0x7d, 0xf8, 0x73, 0xd1, 0x54, 0x13, 0x88, 0x7a, 0x54, 0x63, 0x36, 0x62, - 0xad, 0x55, 0x46, 0xcb, 0xab, 0x61, 0xe8, 0x48, 0xc6, 0xc5, 0xac, 0x32, 0xa1, 0x0c, 0xe8, 0x07, 0x4c, 0xd6, 0x2b, - 0xfa, 0x47, 0x3b, 0x45, 0xbe, 0x54, 0x9f, 0x52, 0xd4, 0xc3, 0xe3, 0x09, 0x8e, 0x53, 0x1f, 0x35, 0xfc, 0xa6, 0x49, - 0x5c, 0x85, 0x6b, 0x38, 0x37, 0x59, 0x73, 0xe6, 0x65, 0x6b, 0x97, 0x3a, 0x98, 0xd3, 0x84, 0xfd, 0x5b, 0xdb, 0x62, - 0xf1, 0x79, 0x12, 0x68, 0xbb, 0x68, 0x26, 0x97, 0xca, 0x5a, 0x10, 0x65, 0xfa, 0xf0, 0x06, 0x12, 0x88, 0xce, 0xb9, - 0x06, 0xea, 0xdb, 0xd4, 0x71, 0x38, 0xb7, 0x68, 0xab, 0x16, 0x2e, 0xad, 0xde, 0x6c, 0xa6, 0x70, 0xc2, 0x67, 0x97, - 0xf6, 0x22, 0x99, 0x68, 0xde, 0xe5, 0x89, 0x64, 0xfa, 0x6e, 0xec, 0xb3, 0x01, 0x71, 0x8b, 0x41, 0xcf, 0xc2, 0x44, - 0x19, 0xae, 0x29, 0xd8, 0x75, 0x95, 0x18, 0xc7, 0x01, 0xe0, 0xec, 0xd3, 0x90, 0x1b, 0x70, 0x78, 0x5d, 0x1b, 0x43, - 0x27, 0xba, 0x5b, 0xf4, 0x4a, 0x0a, 0x42, 0x50, 0xe5, 0xb0, 0xc4, 0xe6, 0x3d, 0xd9, 0x0b, 0xcb, 0x37, 0x78, 0xd8, - 0xb9, 0x53, 0x32, 0xe1, 0x4e, 0xe7, 0x09, 0x53, 0x56, 0xd1, 0x3b, 0xe4, 0x66, 0xc4, 0xeb, 0x0a, 0x8c, 0x29, 0x5c, - 0x01, 0x1b, 0x74, 0x88, 0xba, 0xf1, 0xdb, 0xef, 0x7a, 0xb9, 0xd9, 0xbb, 0x2d, 0x36, 0x33, 0x9e, 0xd1, 0x5a, 0xef, - 0x60, 0xed, 0x2c, 0xbd, 0xb6, 0x33, 0xb2, 0x50, 0x20, 0xc0, 0xc9, 0xdd, 0x66, 0x3d, 0x38, 0x46, 0x34, 0x97, 0xff, - 0x3b, 0x8b, 0x5d, 0x55, 0x4e, 0xbd, 0x31, 0xf4, 0x8a, 0x64, 0xe4, 0x10, 0x80, 0x64, 0x9c, 0x35, 0x1d, 0xa3, 0xd9, - 0xbb, 0xda, 0x76, 0x0e, 0xd3, 0xec, 0xdb, 0x34, 0xd7, 0xef, 0x4f, 0xe6, 0x5e, 0x20, 0x3f, 0x03, 0x37, 0xca, 0xd5, - 0x27, 0x8c, 0x75, 0x0f, 0xb4, 0x34, 0xb3, 0xfa, 0x46, 0x9e, 0xab, 0x19, 0xcb, 0x6d, 0xb0, 0xef, 0x06, 0x15, 0x0f, - 0xb0, 0xa0, 0x3f, 0xc9, 0xcb, 0xf3, 0x77, 0xaa, 0xe6, 0x6e, 0x7a, 0x84, 0x8d, 0x95, 0xcb, 0x70, 0x12, 0x2f, 0x87, - 0xfe, 0x05, 0x47, 0xcf, 0x89, 0xf9, 0x5f, 0x56, 0x24, 0x5d, 0x31, 0xcf, 0x30, 0x99, 0x18, 0xa5, 0x21, 0xc5, 0x19, - 0x2a, 0xe8, 0x7f, 0x58, 0x70, 0xbb, 0x6e, 0xd8, 0x40, 0x8a, 0x7f, 0xe3, 0x3e, 0x3b, 0x9e, 0x7b, 0xab, 0xcc, 0xa4, - 0x97, 0xcd, 0x71, 0x4b, 0xae, 0x6a, 0x5a, 0xcd, 0x7c, 0x56, 0x90, 0x4c, 0xdb, 0xcd, 0x63, 0x5e, 0x19, 0xbf, 0x74, - 0x13, 0xc9, 0x64, 0x4f, 0x67, 0x37, 0x40, 0x6b, 0x07, 0xda, 0xa7, 0xc4, 0xe9, 0x49, 0xa7, 0xab, 0x37, 0x3b, 0xa3, - 0x68, 0x9b, 0x5c, 0xa7, 0x1f, 0x68, 0xbd, 0xa0, 0xa3, 0xdb, 0x59, 0x2b, 0xc9, 0x73, 0x9f, 0xd8, 0x24, 0xc1, 0x4f, - 0xae, 0x63, 0xc1, 0xb1, 0x69, 0x40, 0x3f, 0xce, 0xcb, 0xf3, 0x4d, 0xde, 0x45, 0x06, 0x7c, 0xa6, 0xb0, 0xd9, 0xec, - 0x86, 0x31, 0xc7, 0x86, 0x18, 0x21, 0x48, 0x97, 0xe7, 0xed, 0x69, 0xdd, 0x09, 0x8d, 0xb7, 0x2c, 0x5c, 0x9b, 0x93, - 0x8b, 0xc2, 0xcf, 0xf4, 0xda, 0x34, 0x5c, 0xd0, 0x14, 0xda, 0xe7, 0x7e, 0x9a, 0x84, 0xe9, 0x1e, 0x93, 0xa8, 0x1a, - 0xee, 0xa6, 0x85, 0xfa, 0xb0, 0x50, 0x9e, 0x37, 0xe0, 0x05, 0x2b, 0xdc, 0xf3, 0x39, 0x39, 0x16, 0xf6, 0xe6, 0xbd, - 0xdb, 0x07, 0xb0, 0x5a, 0xcb, 0x3d, 0x66, 0xdc, 0xf1, 0xbe, 0xa3, 0x95, 0xfd, 0xd7, 0xb2, 0xe4, 0x58, 0x87, 0xad, - 0x9a, 0x65, 0xf0, 0x15, 0xa1, 0x39, 0x52, 0x03, 0x4d, 0x7c, 0x40, 0xa0, 0x0a, 0x84, 0x3b, 0x32, 0x6d, 0x67, 0x3c, - 0x65, 0xd4, 0xd1, 0x86, 0xa3, 0xa9, 0x13, 0x3b, 0x1e, 0x9e, 0x14, 0x5b, 0x0c, 0xbf, 0x35, 0xbd, 0x01, 0xcf, 0x7d, - 0x0f, 0xb4, 0xdd, 0xbd, 0x0e, 0x53, 0x7c, 0x65, 0x56, 0xd8, 0xc1, 0xaa, 0xd5, 0x18, 0x84, 0xd8, 0xb4, 0xca, 0xdc, - 0x15, 0x53, 0x02, 0x0c, 0xe7, 0xd4, 0xf8, 0xe2, 0xe0, 0x36, 0x34, 0x72, 0x6f, 0x32, 0x05, 0x4a, 0x1c, 0x5d, 0x0b, - 0x78, 0x92, 0xc6, 0x7c, 0x5a, 0x55, 0xc0, 0xaf, 0x8d, 0x7a, 0x15, 0x06, 0x74, 0xf1, 0x2e, 0x89, 0x1e, 0xf4, 0x90, - 0x22, 0x8e, 0xa7, 0x22, 0x5b, 0x13, 0xc6, 0xba, 0xce, 0xf6, 0xa1, 0x36, 0xf0, 0x7b, 0x45, 0xb5, 0x1f, 0xe0, 0xdd, - 0x06, 0x95, 0x95, 0x77, 0x87, 0xdf, 0x36, 0xb7, 0x24, 0xee, 0x25, 0x87, 0xe2, 0xba, 0xfa, 0x2a, 0x22, 0x03, 0x1e, - 0x94, 0x6a, 0x4d, 0x17, 0xc5, 0xf1, 0x53, 0x0a, 0xc6, 0x32, 0x45, 0x75, 0x32, 0xd3, 0xf6, 0x62, 0x84, 0x68, 0x74, - 0xec, 0x68, 0x73, 0x67, 0xe6, 0xcf, 0x27, 0x44, 0xe4, 0x04, 0xdb, 0xff, 0x54, 0x5e, 0x9c, 0x8d, 0x48, 0x18, 0xec, - 0xdf, 0x36, 0x43, 0x6a, 0x9f, 0xaa, 0x49, 0x9d, 0x86, 0x48, 0xd9, 0x0f, 0x6b, 0x5a, 0xff, 0xbf, 0xf8, 0x5c, 0x18, - 0x0d, 0x44, 0xef, 0xd4, 0x5b, 0x57, 0x4a, 0x60, 0xbb, 0xda, 0xa5, 0xf2, 0x52, 0xfa, 0xbc, 0x6f, 0x75, 0x13, 0x93, - 0xb2, 0xe0, 0x4d, 0xed, 0xcf, 0xd1, 0xfa, 0x49, 0xab, 0x0d, 0xb9, 0x77, 0xfa, 0xd4, 0xe3, 0x10, 0x23, 0x29, 0x27, - 0x88, 0xb1, 0xd4, 0x86, 0x10, 0x81, 0x47, 0x59, 0x83, 0xbb, 0xfe, 0xc9, 0x44, 0x6d, 0x93, 0x06, 0x68, 0x94, 0xe7, - 0x6d, 0xb1, 0xf5, 0xea, 0x4e, 0xe9, 0x8a, 0xdb, 0xe1, 0xca, 0xd6, 0x25, 0x60, 0x3a, 0x31, 0xf8, 0x74, 0x47, 0x77, - 0x0a, 0x78, 0x13, 0xec, 0x26, 0x13, 0xd0, 0x10, 0xc3, 0xd9, 0x7c, 0xf1, 0xcf, 0x96, 0x63, 0x7e, 0xe9, 0x07, 0x6c, - 0x0d, 0x92, 0x06, 0x70, 0x66, 0x00, 0x5b, 0x9f, 0x37, 0x57, 0xaa, 0x6f, 0x0f, 0xff, 0xda, 0x32, 0x7e, 0x47, 0x6e, - 0xf8, 0x7a, 0xdb, 0xd5, 0xc1, 0xf2, 0xc2, 0xb0, 0x43, 0xa0, 0x33, 0xa8, 0x4b, 0x0a, 0x93, 0xde, 0x05, 0xd4, 0xb9, - 0xd7, 0xb8, 0x81, 0x2b, 0x23, 0x84, 0x61, 0xc8, 0x83, 0xca, 0xb9, 0xbd, 0xc2, 0xbd, 0xf5, 0x3d, 0x81, 0x16, 0x20, - 0x3c, 0x54, 0xa1, 0x6d, 0x91, 0x49, 0xe7, 0xde, 0x60, 0xbb, 0x84, 0x75, 0x29, 0xe5, 0x54, 0x6b, 0x4e, 0xd7, 0x21, - 0xf9, 0xb8, 0xad, 0xfa, 0x16, 0x03, 0x72, 0x04, 0xa1, 0xd4, 0x33, 0x64, 0xd7, 0x70, 0x91, 0x5e, 0x6e, 0x8e, 0x74, - 0xca, 0xd7, 0x02, 0x62, 0x9b, 0xba, 0xdb, 0xa2, 0xfb, 0x7c, 0x2b, 0x0f, 0x41, 0x66, 0x9a, 0x4b, 0x40, 0xa2, 0x31, - 0x05, 0xf5, 0xc3, 0x30, 0x29, 0x97, 0xff, 0x5e, 0x23, 0x5e, 0xe7, 0xf1, 0xfa, 0xe7, 0x27, 0xab, 0xea, 0xc3, 0xf6, - 0x07, 0x3f, 0xd0, 0x7b, 0xb1, 0x69, 0xad, 0xde, 0x5e, 0xac, 0xbe, 0x9b, 0x15, 0xd4, 0xcf, 0x2c, 0x99, 0x41, 0x18, - 0x4b, 0x9d, 0x9d, 0xf1, 0x41, 0x5c, 0xf3, 0x1b, 0xb6, 0x5c, 0xde, 0x23, 0xf5, 0x2e, 0x93, 0x34, 0x99, 0xa6, 0xac, - 0x3e, 0xad, 0x4f, 0x3b, 0x45, 0xa0, 0x8d, 0x3a, 0x7a, 0x0d, 0xa7, 0x1c, 0xb8, 0x68, 0xd3, 0xa2, 0xbb, 0xcb, 0x3f, - 0x0b, 0x96, 0x85, 0x6e, 0x7f, 0x5d, 0x0e, 0xd6, 0x0d, 0x9f, 0x57, 0x74, 0x2e, 0x9c, 0xc8, 0xa1, 0x85, 0x05, 0x56, - 0x3b, 0x65, 0x70, 0xa6, 0xde, 0x64, 0x8b, 0x13, 0xdd, 0x44, 0x07, 0x79, 0x65, 0xac, 0xe3, 0xd4, 0x4b, 0xc3, 0x01, - 0xba, 0x66, 0x85, 0xcf, 0xf9, 0xa8, 0xcf, 0xfb, 0x13, 0x3a, 0x53, 0x90, 0xb5, 0xdc, 0x59, 0x14, 0xcb, 0xbb, 0x90, - 0x57, 0x51, 0x7d, 0xb9, 0x18, 0x59, 0x21, 0x94, 0x05, 0x6c, 0x7b, 0x7d, 0x1c, 0x87, 0x22, 0xf7, 0xa4, 0xc4, 0xd3, - 0xce, 0x39, 0x52, 0xee, 0x12, 0xe4, 0xee, 0x8a, 0xc5, 0x69, 0x24, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x86, 0xae, - 0x28, 0x72, 0x8b, 0x21, 0x04, 0x1c, 0x0d, 0x6f, 0x6f, 0xb4, 0x6d, 0xa4, 0x0c, 0x12, 0xc5, 0xce, 0x08, 0xe9, 0x97, - 0xb9, 0xa1, 0x7c, 0xb3, 0x0f, 0xa6, 0x8c, 0x41, 0x04, 0x04, 0x2a, 0xc8, 0x00, 0x2c, 0xfb, 0xca, 0xb9, 0x1a, 0x06, - 0xe3, 0x0c, 0x46, 0x02, 0x2b, 0xa0, 0xd7, 0x45, 0x93, 0x6e, 0xf8, 0x53, 0x78, 0x9a, 0x2a, 0x9e, 0xa6, 0x85, 0xa2, - 0xd1, 0x51, 0x79, 0x36, 0xa5, 0x6b, 0x9e, 0x06, 0x0b, 0x52, 0x4f, 0x9a, 0x1c, 0x36, 0x06, 0xf3, 0x68, 0x24, 0xe1, - 0x9e, 0x9a, 0x8c, 0x62, 0x65, 0x68, 0x1c, 0xfd, 0xb3, 0x3b, 0xc4, 0x39, 0x74, 0x50, 0x0b, 0xde, 0xcc, 0xe8, 0xe1, - 0xcc, 0x0f, 0x41, 0x6a, 0xd8, 0x5c, 0x85, 0xf9, 0x45, 0xa6, 0x4e, 0x75, 0xca, 0x28, 0x4b, 0x8c, 0xb3, 0x60, 0xed, - 0x18, 0x72, 0xa4, 0x7e, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, 0xb6, 0xf4, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, - 0xde, 0xd2, 0xf5, 0x5f, 0xcc, 0x6c, 0xdd, 0x8e, 0x39, 0x7f, 0xe9, 0xe7, 0xbb, 0xe9, 0x43, 0x1f, 0xf3, 0x66, 0xec, - 0x0c, 0x33, 0xba, 0xfe, 0x22, 0x2d, 0x1e, 0x14, 0x0d, 0x8a, 0x7c, 0xa9, 0x31, 0x8e, 0xb4, 0xbf, 0x1f, 0x9a, 0x46, - 0xbb, 0xdb, 0x3b, 0x49, 0x1a, 0x61, 0xcb, 0x11, 0x7a, 0x23, 0x38, 0x76, 0xc5, 0x7f, 0x5c, 0x55, 0xfe, 0x77, 0x4f, - 0xfd, 0xbe, 0x3d, 0x08, 0x5f, 0xd5, 0x4d, 0x1f, 0x46, 0x01, 0x73, 0xd6, 0xba, 0x5d, 0x7d, 0x96, 0x50, 0x43, 0xfa, - 0x6b, 0x82, 0xfa, 0x8d, 0x63, 0xf5, 0x8f, 0x69, 0x4a, 0xfe, 0x62, 0x57, 0xc1, 0xc6, 0x6c, 0xfd, 0x58, 0xd8, 0xa3, - 0x5a, 0x39, 0x3e, 0x77, 0xa7, 0x2d, 0x19, 0xed, 0x49, 0xf9, 0x56, 0x77, 0x78, 0xda, 0x49, 0x59, 0xca, 0xe6, 0x3d, - 0xb5, 0x98, 0x4c, 0x57, 0xdb, 0x4a, 0x1c, 0x91, 0x1e, 0xe4, 0x1b, 0x73, 0x46, 0xe9, 0xf8, 0x7d, 0xe5, 0x8f, 0xbb, - 0x93, 0xd8, 0xcc, 0xd3, 0x93, 0x70, 0x0b, 0xb4, 0x2b, 0xfb, 0x7e, 0x2b, 0xee, 0x3b, 0x29, 0xfe, 0x76, 0xd9, 0xaf, - 0x73, 0x95, 0x02, 0x1e, 0xf7, 0xbe, 0x60, 0xfb, 0xf9, 0x3a, 0x52, 0xd8, 0x8e, 0x14, 0x43, 0xb6, 0xf9, 0xaa, 0x4b, - 0xa2, 0x0a, 0x59, 0xf0, 0x06, 0xf9, 0x20, 0xae, 0x05, 0x20, 0xe7, 0xb4, 0x45, 0x2d, 0xfb, 0x8e, 0x25, 0x51, 0xbe, - 0xab, 0x40, 0x2d, 0x79, 0x76, 0x51, 0xd1, 0xa9, 0x3b, 0xe1, 0xab, 0x53, 0xcf, 0xd2, 0x9c, 0x86, 0xe8, 0x7a, 0x58, - 0xf2, 0x12, 0x95, 0xac, 0x9a, 0xde, 0x4d, 0xf0, 0x2b, 0xf6, 0xda, 0x13, 0x94, 0xbc, 0x23, 0xa5, 0xa1, 0x90, 0x51, - 0xac, 0x41, 0x7d, 0xeb, 0xdc, 0x25, 0x96, 0x74, 0xb4, 0x3c, 0xea, 0x55, 0xf8, 0x62, 0xee, 0xe3, 0xd6, 0x38, 0x2a, - 0xc7, 0x9c, 0x23, 0xd8, 0x93, 0x2a, 0x9d, 0x4c, 0x95, 0x03, 0xc0, 0x9a, 0x66, 0x11, 0x31, 0x48, 0xa9, 0x5d, 0x8e, - 0xbb, 0xf8, 0x16, 0x6c, 0x67, 0x31, 0xc8, 0xd2, 0xd7, 0x36, 0x19, 0x95, 0xce, 0x63, 0x27, 0xba, 0x1f, 0xbb, 0xda, - 0xc0, 0xc3, 0x60, 0x7b, 0xd6, 0x29, 0x57, 0x32, 0x56, 0x1c, 0x65, 0x57, 0x62, 0x6a, 0x79, 0xb6, 0x74, 0xbd, 0x45, - 0x54, 0xac, 0x95, 0x35, 0xbd, 0x0d, 0xd3, 0x53, 0xc1, 0x73, 0x3f, 0x3e, 0x61, 0x71, 0x64, 0xe4, 0x38, 0x93, 0x58, - 0xd5, 0x21, 0xcc, 0x4d, 0x3a, 0x82, 0x27, 0x48, 0x2d, 0x47, 0x32, 0x4f, 0x39, 0xa5, 0x50, 0xa1, 0xff, 0xa5, 0xf1, - 0x08, 0x55, 0x73, 0x75, 0xd3, 0x5b, 0x85, 0xef, 0x10, 0x84, 0xfe, 0x21, 0xba, 0x05, 0xe3, 0x82, 0xf7, 0xef, 0x25, - 0x22, 0xd5, 0x52, 0x28, 0x59, 0x5e, 0x5d, 0xd6, 0x98, 0xa1, 0xcd, 0x3b, 0x4a, 0xc9, 0x50, 0xa0, 0x0a, 0xd3, 0x17, - 0x7c, 0x6e, 0x10, 0x0e, 0xb9, 0x6b, 0x1d, 0x05, 0xb1, 0x22, 0xd8, 0x0d, 0x9d, 0x20, 0xa1, 0xae, 0x0a, 0xb1, 0x2f, - 0xc4, 0x1c, 0x9f, 0xcb, 0xac, 0xd0, 0x03, 0xfe, 0xe4, 0x37, 0xb1, 0xa4, 0xfe, 0x06, 0x46, 0xfe, 0x0d, 0xab, 0xb4, - 0xa1, 0x4f, 0xf9, 0x41, 0xec, 0x73, 0x21, 0x6f, 0x6a, 0xa6, 0xd9, 0x8e, 0xcb, 0x7e, 0xe6, 0xef, 0x4d, 0x78, 0xec, - 0x2d, 0xb1, 0xf3, 0x58, 0x50, 0xb9, 0x8c, 0x21, 0x06, 0xaa, 0x9b, 0xfc, 0x89, 0xd2, 0x3f, 0x9c, 0x4e, 0xfc, 0x66, - 0xbe, 0xb3, 0xb6, 0x3f, 0x5f, 0x85, 0x42, 0xec, 0x75, 0x86, 0x96, 0x30, 0x84, 0xf0, 0x64, 0x3e, 0xbb, 0x30, 0x27, - 0x21, 0x49, 0x45, 0x8b, 0x12, 0xce, 0x70, 0x7f, 0x03, 0x20, 0x03, 0x0d, 0x56, 0xa2, 0x54, 0xd4, 0x8b, 0x3d, 0x82, - 0x49, 0x3e, 0xdb, 0x7a, 0xd8, 0x8b, 0x3c, 0x5a, 0x48, 0xa3, 0x5c, 0xc1, 0x06, 0x30, 0xd5, 0x73, 0x1b, 0x89, 0xc5, - 0x48, 0x2f, 0x5a, 0x4b, 0xbe, 0xd4, 0x12, 0xea, 0x62, 0xe7, 0x61, 0xb0, 0xae, 0x1a, 0x54, 0x76, 0x1e, 0x0b, 0x66, - 0x3a, 0x07, 0x72, 0x5c, 0xa0, 0x51, 0x37, 0x26, 0xc7, 0x14, 0xb3, 0x6a, 0x85, 0x1f, 0xaa, 0x98, 0xb7, 0x74, 0x29, - 0xd8, 0xbc, 0x56, 0x77, 0xc7, 0xbb, 0x86, 0x09, 0x75, 0x68, 0x60, 0x96, 0x24, 0xa8, 0x61, 0x09, 0xeb, 0x0b, 0x3e, - 0x8f, 0xc1, 0x3c, 0x60, 0x9a, 0xb7, 0xd9, 0xed, 0x18, 0xf5, 0x5b, 0x35, 0x9f, 0x7a, 0xab, 0x3c, 0x6f, 0xb9, 0xc3, - 0x2b, 0x35, 0x37, 0xa7, 0xc5, 0x3c, 0x42, 0x44, 0xaf, 0xdb, 0x90, 0xf0, 0x9c, 0xb9, 0x97, 0xb8, 0x90, 0x78, 0xd2, - 0x67, 0x5e, 0x1f, 0x1f, 0x77, 0x22, 0xc7, 0xa8, 0xf4, 0xd6, 0x45, 0xc8, 0xec, 0x83, 0xb2, 0x72, 0x77, 0x78, 0x72, - 0xe9, 0xb4, 0x84, 0x4a, 0xd6, 0xf5, 0x9b, 0x4f, 0x13, 0xa8, 0xc2, 0x60, 0x86, 0xe2, 0x14, 0x9b, 0xea, 0xd1, 0x78, - 0x83, 0x79, 0x04, 0xe3, 0x22, 0x12, 0x6a, 0x30, 0x0f, 0x2e, 0xd1, 0x34, 0x12, 0x31, 0x67, 0xac, 0x6e, 0x07, 0xb0, - 0xe7, 0x4b, 0x4f, 0x31, 0x7b, 0x78, 0x6d, 0x2f, 0x99, 0xe3, 0xf6, 0x25, 0x70, 0x5b, 0xee, 0x4e, 0xb1, 0x9a, 0x3d, - 0x56, 0x49, 0x8d, 0x03, 0xd8, 0x48, 0xa3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, 0x76, 0x7f, 0x82, 0x27, 0x80, 0x63, 0x04, - 0x83, 0x13, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0xb1, 0xf2, 0xcd, 0x27, 0x81, 0x0d, 0x41, 0x64, 0x0a, 0x2b, 0x44, 0x4c, - 0x95, 0x21, 0xfc, 0xbc, 0x8b, 0xb3, 0xaf, 0x2e, 0x13, 0x4d, 0xb5, 0xd1, 0x08, 0xc5, 0x3c, 0xbc, 0x86, 0x9b, 0x79, - 0x60, 0xaa, 0xc7, 0x9a, 0x4e, 0x11, 0xd5, 0x4e, 0x62, 0x6a, 0xf5, 0xac, 0x63, 0xad, 0x5c, 0x6d, 0x8b, 0xc9, 0x27, - 0xea, 0x95, 0x3c, 0x40, 0x23, 0x9a, 0xc9, 0x84, 0x6f, 0x39, 0x33, 0x1f, 0xa6, 0xec, 0x11, 0x7e, 0x1d, 0xc3, 0x87, - 0xc7, 0x8d, 0xc0, 0x28, 0xcf, 0xc9, 0xce, 0x16, 0x32, 0x2e, 0x1c, 0x58, 0xfc, 0x69, 0xc8, 0x98, 0xfb, 0xa2, 0xe8, - 0xa9, 0x4c, 0x2f, 0x26, 0x2f, 0x7f, 0x56, 0xf3, 0x64, 0x1e, 0x08, 0x5b, 0xa3, 0x8a, 0xf4, 0x4b, 0xa3, 0xc5, 0x62, - 0x90, 0x7a, 0x18, 0xc6, 0x40, 0x8a, 0x85, 0x8a, 0x81, 0xa3, 0x4b, 0x75, 0xc0, 0xff, 0x4f, 0x41, 0x8f, 0x21, 0x7b, - 0x46, 0xdb, 0x6d, 0xce, 0xb7, 0xac, 0x27, 0x73, 0x63, 0xdf, 0xd9, 0x76, 0xf2, 0xc6, 0x03, 0x4e, 0x16, 0xfb, 0x85, - 0x59, 0xfc, 0x2e, 0x9f, 0x07, 0x4a, 0xec, 0x25, 0x41, 0x32, 0x0a, 0x90, 0x39, 0x9f, 0x85, 0x87, 0xd0, 0x6b, 0x5e, - 0x09, 0x51, 0xd0, 0x95, 0xe2, 0x4a, 0xa0, 0xf5, 0xe0, 0x34, 0x40, 0xa6, 0xc2, 0x15, 0x04, 0x32, 0x6f, 0x7e, 0x5c, - 0xee, 0x6e, 0x02, 0x69, 0x7b, 0x85, 0x0c, 0x66, 0x6e, 0xf5, 0x12, 0xa9, 0xf3, 0x81, 0x59, 0xbe, 0x64, 0x6f, 0x6c, - 0x59, 0xf7, 0xe0, 0x4c, 0x3f, 0x73, 0x74, 0x1a, 0xb2, 0xb2, 0x16, 0x0a, 0x9b, 0xec, 0xf4, 0x24, 0xaa, 0x2a, 0x45, - 0xf2, 0x8a, 0x72, 0x51, 0x50, 0x54, 0x08, 0xd3, 0xeb, 0x1f, 0x02, 0x42, 0x8e, 0x52, 0x06, 0xed, 0xb1, 0xe5, 0x2b, - 0x8c, 0x08, 0x81, 0x71, 0x21, 0x1a, 0x56, 0x90, 0x29, 0xec, 0xb2, 0x8a, 0x71, 0x9c, 0x9e, 0xa8, 0xba, 0x8b, 0x53, - 0x88, 0x3d, 0xef, 0x86, 0xcc, 0x12, 0x74, 0x6e, 0xb4, 0x35, 0xc6, 0x31, 0xf4, 0x33, 0xd1, 0x3f, 0x82, 0x1b, 0x9d, - 0xc3, 0x1a, 0x15, 0x9c, 0x1a, 0xfb, 0x9c, 0xc5, 0x3b, 0xbe, 0x0a, 0xf7, 0x7b, 0xda, 0x92, 0xde, 0x8e, 0x5d, 0x33, - 0x2b, 0x3f, 0x82, 0x2c, 0xa5, 0x2d, 0x43, 0x12, 0xd5, 0xb5, 0x97, 0x8e, 0x41, 0x53, 0x22, 0xb7, 0x9e, 0xcf, 0xc9, - 0xe8, 0x1b, 0x4c, 0x7e, 0xbc, 0x39, 0xdd, 0x97, 0x84, 0x0e, 0x56, 0x8b, 0x67, 0x2e, 0xbe, 0xc4, 0x26, 0xd0, 0x82, - 0x07, 0x00, 0xce, 0xdf, 0x89, 0xeb, 0xdf, 0x45, 0x0f, 0x0e, 0x63, 0x04, 0xb0, 0x10, 0x6f, 0xc5, 0xb0, 0xf2, 0x36, - 0xa2, 0xb4, 0x02, 0x20, 0xd7, 0xa6, 0x2a, 0xc0, 0x1b, 0x86, 0x6f, 0xb2, 0x64, 0x9f, 0xe3, 0x38, 0xdb, 0xb3, 0x42, - 0xe2, 0x1d, 0xfe, 0x59, 0x1f, 0x5e, 0x99, 0x70, 0x2e, 0xd8, 0x2d, 0x1d, 0xe7, 0x55, 0xdb, 0x88, 0xa4, 0xed, 0x62, - 0x10, 0xe3, 0x0c, 0x12, 0xa9, 0x0f, 0xd2, 0xf7, 0x57, 0x61, 0x21, 0x1a, 0x02, 0xef, 0x8b, 0x0a, 0xec, 0x75, 0x14, - 0x46, 0x93, 0xda, 0x23, 0x1a, 0x41, 0x4f, 0x57, 0x27, 0x24, 0x03, 0x95, 0x42, 0x6c, 0x98, 0x44, 0xfd, 0x4c, 0xb5, - 0xdd, 0x50, 0x7d, 0x53, 0xad, 0xa6, 0x50, 0xe3, 0x13, 0x30, 0x75, 0x28, 0x29, 0x18, 0x73, 0x6d, 0xd8, 0xa7, 0x8f, - 0x1d, 0x51, 0x6b, 0x0d, 0x4e, 0xef, 0x5f, 0x85, 0x81, 0x61, 0xb9, 0xd9, 0x7c, 0xf1, 0x15, 0x76, 0x9d, 0x73, 0x2f, - 0x50, 0x7d, 0x1f, 0xfd, 0x38, 0xae, 0x2e, 0xcb, 0xef, 0x7a, 0x37, 0xb5, 0x10, 0xef, 0xa9, 0xa3, 0x86, 0xfd, 0x94, - 0xc8, 0xf9, 0x2e, 0xc5, 0x7d, 0xdc, 0x51, 0x01, 0xf4, 0x79, 0xc8, 0x48, 0xab, 0x09, 0xc5, 0x05, 0x20, 0x5d, 0xc6, - 0x34, 0x2b, 0x0d, 0x54, 0xa8, 0xd9, 0x68, 0x2f, 0x23, 0xab, 0x0c, 0xc2, 0x41, 0xfb, 0xd5, 0x23, 0x28, 0x96, 0x55, - 0xba, 0xc9, 0x23, 0x80, 0xcd, 0xfa, 0x95, 0xdc, 0xfc, 0x17, 0x01, 0x1b, 0x0c, 0x0b, 0x36, 0x2f, 0xea, 0x25, 0xcf, - 0x79, 0x04, 0x98, 0xe4, 0x8c, 0xeb, 0x41, 0xb4, 0xfe, 0x6b, 0xd3, 0x7c, 0xb0, 0xe5, 0xde, 0x3b, 0x02, 0x49, 0xbd, - 0xac, 0x0d, 0xb0, 0xb2, 0x18, 0x52, 0xef, 0x39, 0x3f, 0x35, 0x32, 0x25, 0x20, 0x20, 0xfe, 0xc2, 0xd7, 0xf5, 0xeb, - 0xb0, 0x5e, 0xab, 0x74, 0xe7, 0x53, 0xd3, 0x5a, 0x15, 0x52, 0x9e, 0xcc, 0x5a, 0x45, 0x3e, 0x71, 0x55, 0x33, 0xc3, - 0xb4, 0x36, 0xaf, 0x4e, 0x4f, 0xfa, 0x0b, 0xca, 0x7d, 0x91, 0x33, 0x00, 0xe1, 0x35, 0x8f, 0x0f, 0x56, 0xef, 0x66, - 0xdf, 0x36, 0xae, 0x56, 0xb6, 0xfb, 0x17, 0x6d, 0x7c, 0x9a, 0xb1, 0x5b, 0xc3, 0x18, 0x54, 0xce, 0xcb, 0xc9, 0x6f, - 0x4a, 0x4a, 0x23, 0x2d, 0xa3, 0xcd, 0xb1, 0xcb, 0xa9, 0xf6, 0xe5, 0xea, 0xdd, 0x1a, 0x84, 0x15, 0x22, 0xb3, 0x07, - 0xcf, 0x08, 0x1f, 0x6f, 0xfd, 0x50, 0x08, 0x55, 0x69, 0xc7, 0x58, 0xde, 0x2c, 0x86, 0xa1, 0xf9, 0x5c, 0x8a, 0xcb, - 0x11, 0xe6, 0x5b, 0xe7, 0xa6, 0x29, 0x64, 0x6d, 0x22, 0xa9, 0xa3, 0xc0, 0xa4, 0xb8, 0x8c, 0x34, 0xe7, 0x5f, 0xc6, - 0x89, 0xe4, 0x5e, 0x29, 0x9f, 0xd4, 0x53, 0xea, 0x2d, 0xd8, 0x08, 0xc2, 0x9f, 0xd4, 0x2d, 0x7b, 0xa1, 0x41, 0xb3, - 0x4d, 0x92, 0xc1, 0xc9, 0xe7, 0x07, 0xbf, 0xc9, 0x5d, 0x7a, 0x0d, 0x91, 0x10, 0x4c, 0xf9, 0xdc, 0x36, 0xdd, 0x64, - 0xac, 0x04, 0xa4, 0xab, 0x1a, 0x6d, 0xd8, 0x4c, 0xd1, 0xf5, 0x79, 0x3f, 0xc8, 0xfb, 0xa1, 0x23, 0xb2, 0x18, 0x5b, - 0x94, 0xf0, 0x0b, 0x47, 0x62, 0x4e, 0xdd, 0x14, 0xa5, 0x35, 0xf4, 0xf6, 0x61, 0x76, 0xbd, 0xdb, 0x6b, 0xb9, 0x24, - 0x1d, 0x4e, 0x2b, 0xd2, 0x2c, 0x00, 0x21, 0xea, 0x14, 0xaa, 0x09, 0x38, 0x50, 0xe6, 0xe5, 0x2f, 0x91, 0x40, 0xca, - 0x0f, 0x70, 0x21, 0xbd, 0xcc, 0xe7, 0x28, 0x82, 0xf3, 0x50, 0xa5, 0x05, 0x17, 0x66, 0x8f, 0x81, 0xdf, 0x75, 0x4d, - 0xbf, 0x05, 0x7f, 0x66, 0x8a, 0x97, 0xc2, 0xc9, 0xf3, 0x72, 0xaf, 0xe1, 0x21, 0x06, 0x1f, 0x9c, 0x55, 0x5f, 0xf4, - 0x72, 0x1a, 0xd7, 0x19, 0xd8, 0xbd, 0xec, 0x81, 0xf9, 0x30, 0xf3, 0x56, 0x00, 0x99, 0xd3, 0xb8, 0xaa, 0xc0, 0x73, - 0x5e, 0xcd, 0xb5, 0x46, 0x39, 0xbd, 0x5f, 0x88, 0x31, 0x0d, 0xa5, 0x62, 0x6b, 0x98, 0x8a, 0x03, 0xc5, 0x45, 0xc9, - 0xbd, 0xac, 0x29, 0x4e, 0x9b, 0xf3, 0x86, 0xa4, 0x7c, 0x47, 0x03, 0x6d, 0x5e, 0xcd, 0x93, 0x7b, 0xfc, 0x8b, 0x7a, - 0xde, 0x7b, 0x1c, 0xbe, 0xbc, 0x99, 0x16, 0x83, 0x9c, 0x0f, 0x90, 0x53, 0x03, 0xc7, 0x6f, 0x4d, 0xf8, 0x63, 0x6e, - 0x69, 0x35, 0xc6, 0x1a, 0x9a, 0xf8, 0xc8, 0x56, 0x00, 0x29, 0xe3, 0x4d, 0x52, 0x2b, 0x7c, 0xa9, 0x43, 0xb1, 0x98, - 0x2c, 0xbf, 0x0b, 0x34, 0xb8, 0xc1, 0xd2, 0x33, 0x1c, 0x52, 0xd4, 0x8b, 0xa2, 0xa5, 0x3f, 0x51, 0x7e, 0x37, 0xee, - 0x3f, 0xed, 0x77, 0x4b, 0x60, 0xee, 0x71, 0x5b, 0x69, 0xb1, 0x91, 0xd0, 0x4d, 0x5b, 0xc9, 0xab, 0x0d, 0x55, 0x77, - 0xe7, 0xae, 0x89, 0xac, 0xe6, 0xba, 0x46, 0xa5, 0x06, 0x61, 0xfc, 0x5e, 0xbb, 0xb1, 0xcd, 0xb4, 0xb5, 0xd2, 0x41, - 0x9f, 0x21, 0xe9, 0xa5, 0xa2, 0xdd, 0xa0, 0x63, 0x4f, 0x4f, 0x68, 0xc7, 0x12, 0xf1, 0x1e, 0x21, 0x71, 0x86, 0x85, - 0x62, 0x5c, 0x98, 0x47, 0xf4, 0x56, 0x7a, 0xc5, 0x61, 0x63, 0xd2, 0xd3, 0x6c, 0x2c, 0xcb, 0x2b, 0x9c, 0xba, 0x2f, - 0x52, 0x40, 0xf1, 0xcf, 0xd1, 0x01, 0xfc, 0x33, 0x5d, 0x83, 0xd6, 0xe0, 0x54, 0x2e, 0x77, 0xf5, 0xba, 0xc4, 0x87, - 0x76, 0xc7, 0x13, 0x09, 0xdd, 0x0e, 0xd1, 0xf8, 0x86, 0xae, 0x70, 0xa3, 0x78, 0x95, 0x51, 0xc7, 0xca, 0xb4, 0x66, - 0xe4, 0xc3, 0x8a, 0xec, 0x5f, 0x20, 0xf2, 0xaa, 0x10, 0x85, 0x20, 0xad, 0x45, 0x34, 0x31, 0xd9, 0x7f, 0x9a, 0xe4, - 0x35, 0xa5, 0x99, 0x6d, 0xf4, 0xa7, 0x4d, 0x4d, 0xdb, 0x11, 0x70, 0xb7, 0x73, 0x13, 0x5d, 0xec, 0xcc, 0xa5, 0xb0, - 0x57, 0x50, 0xda, 0x42, 0xa2, 0x90, 0x75, 0x21, 0x5a, 0x6e, 0x97, 0x5a, 0xf9, 0xad, 0xf2, 0x14, 0x00, 0x10, 0x05, - 0x4d, 0xe8, 0xca, 0x6e, 0xb6, 0x77, 0xc5, 0xd2, 0xd5, 0x43, 0x04, 0x1f, 0x90, 0x12, 0x1c, 0xa0, 0x8b, 0x3c, 0xae, - 0xbb, 0x77, 0xb3, 0x8d, 0xc8, 0x46, 0xb6, 0x68, 0xad, 0x0e, 0xbc, 0x5c, 0xbf, 0xde, 0xe5, 0xff, 0xdf, 0xf7, 0xd8, - 0xfc, 0x05, 0x1c, 0x50, 0xb8, 0x0f, 0x1f, 0x4c, 0x0b, 0x4f, 0x1c, 0x6a, 0xfd, 0xd7, 0x86, 0x12, 0x05, 0x4f, 0xa2, - 0xf1, 0x73, 0xcd, 0x3a, 0x3d, 0x62, 0x14, 0x89, 0x8f, 0xd4, 0x03, 0x89, 0x5a, 0xad, 0x35, 0x3d, 0xae, 0xae, 0xd3, - 0xfa, 0x2f, 0x86, 0x7d, 0xb5, 0xab, 0x18, 0xe2, 0x4e, 0x2f, 0x6e, 0x23, 0x89, 0x42, 0xa1, 0xcf, 0x26, 0x3e, 0x61, - 0xa0, 0xb2, 0xe6, 0x0b, 0x0f, 0x29, 0x96, 0x97, 0xcb, 0xd0, 0x74, 0xa1, 0xc5, 0x6d, 0x81, 0x1a, 0x0f, 0x06, 0x3d, - 0x6b, 0x97, 0x20, 0xcd, 0xae, 0xff, 0x8c, 0x33, 0x9c, 0xb4, 0xd2, 0xea, 0xf3, 0x62, 0x08, 0xd9, 0xc7, 0x3b, 0xa9, - 0x55, 0xa1, 0x8c, 0xb3, 0xc7, 0xaa, 0xac, 0x0d, 0xbf, 0x86, 0x6a, 0x74, 0x8e, 0x55, 0xd4, 0xa6, 0xae, 0xad, 0x76, - 0xc6, 0xa0, 0x54, 0xc7, 0x81, 0x60, 0xd3, 0xd2, 0xc5, 0x20, 0x2d, 0xe2, 0x40, 0x1f, 0x48, 0xf2, 0xb8, 0xa4, 0xf9, - 0x2e, 0x15, 0xf9, 0x72, 0xd1, 0x10, 0x9a, 0xeb, 0xaa, 0xc2, 0x36, 0xe5, 0xb1, 0xa6, 0xa8, 0x8b, 0x9b, 0x1d, 0xeb, - 0xf0, 0x1a, 0x30, 0x8c, 0x17, 0xe0, 0x4a, 0x80, 0x93, 0xf2, 0xd5, 0xa7, 0x06, 0x3b, 0x66, 0x0a, 0x3d, 0x17, 0xfe, - 0xf8, 0xb4, 0x26, 0x13, 0x2b, 0x5e, 0xb5, 0x42, 0x89, 0xab, 0xc4, 0x53, 0x1d, 0x96, 0x4b, 0x37, 0xb1, 0x46, 0xc8, - 0x67, 0xe2, 0xaf, 0xd1, 0x22, 0xec, 0x0d, 0x64, 0x0d, 0xcb, 0x64, 0x32, 0x25, 0x24, 0x4c, 0x90, 0x73, 0xc0, 0x98, - 0x3a, 0xc9, 0x17, 0x97, 0xfe, 0x2c, 0xdc, 0xa1, 0xcf, 0xa6, 0xb5, 0x74, 0xdf, 0x49, 0x85, 0xee, 0x7b, 0x32, 0xe9, - 0x50, 0x4f, 0x1c, 0xc4, 0xcc, 0x14, 0x5c, 0x1d, 0xb7, 0xd8, 0x68, 0x30, 0x38, 0x3a, 0x3b, 0xd6, 0x62, 0x8b, 0x21, - 0x61, 0x03, 0xe6, 0x13, 0xb5, 0x7b, 0x1f, 0x3e, 0x93, 0xf4, 0xcb, 0xd7, 0x4b, 0x84, 0x90, 0xc1, 0xee, 0x44, 0xa9, - 0x19, 0x33, 0xd4, 0x34, 0x33, 0x05, 0xcd, 0xfc, 0xe8, 0x24, 0xd2, 0x1d, 0xde, 0x4c, 0xe8, 0x95, 0x06, 0xb7, 0xee, - 0xa9, 0xbe, 0x5c, 0x91, 0x46, 0x68, 0x8d, 0x39, 0x50, 0xf9, 0x70, 0x5a, 0x17, 0xd7, 0x2b, 0xdb, 0xf5, 0x03, 0x7e, - 0x68, 0xb5, 0x3b, 0x78, 0xd2, 0x20, 0xe3, 0x43, 0x93, 0xe4, 0xbc, 0x06, 0x2b, 0xc0, 0x43, 0x83, 0xa5, 0x68, 0x89, - 0x37, 0x45, 0xcf, 0x26, 0xfb, 0x68, 0xb4, 0x18, 0x8b, 0xb5, 0xfc, 0xfd, 0x9d, 0xa7, 0x7d, 0x21, 0xd5, 0x28, 0x7b, - 0x18, 0xc8, 0xee, 0x13, 0x28, 0x99, 0xa3, 0xd0, 0x9d, 0xcd, 0x50, 0xc5, 0x68, 0x9e, 0x00, 0x63, 0x05, 0xbf, 0xb8, - 0x66, 0x31, 0x9d, 0x33, 0xc7, 0xf9, 0x1a, 0x4e, 0x12, 0x47, 0x4d, 0x9c, 0x5b, 0x4f, 0x04, 0xe5, 0xd5, 0x62, 0x49, - 0xf4, 0x92, 0xa2, 0xa3, 0x8e, 0xd5, 0xf8, 0x8f, 0x89, 0xf5, 0xd4, 0x9c, 0x8e, 0x76, 0x3e, 0x8d, 0x15, 0x54, 0xd2, - 0x02, 0x6a, 0x72, 0x2c, 0xfb, 0x12, 0x0a, 0xdc, 0xff, 0xa7, 0x9a, 0x4a, 0xc5, 0xcb, 0x74, 0xb8, 0x59, 0x73, 0x60, - 0x03, 0xea, 0x08, 0xa0, 0xba, 0x35, 0x23, 0xa3, 0x6f, 0x7c, 0x7f, 0xa1, 0xee, 0xc6, 0x98, 0x03, 0x1d, 0xb4, 0x2d, - 0xfa, 0x1b, 0xe8, 0x91, 0x6c, 0x97, 0x83, 0x78, 0x83, 0xf2, 0x16, 0x4f, 0x02, 0x2f, 0x11, 0x4d, 0xd4, 0x6c, 0xac, - 0xe3, 0xb7, 0xd9, 0x3a, 0x0e, 0xde, 0x3a, 0x00, 0xbf, 0xb0, 0x6c, 0xc6, 0x99, 0x8d, 0xfa, 0x5e, 0x41, 0x0c, 0xf8, - 0x51, 0xec, 0x6c, 0xfc, 0xe9, 0x84, 0xda, 0x93, 0x1d, 0x4e, 0x39, 0x36, 0xca, 0x39, 0x61, 0x7b, 0xa6, 0x12, 0x00, - 0x29, 0x74, 0x51, 0x67, 0xc5, 0xc9, 0x4f, 0xbc, 0x15, 0x3b, 0xe2, 0x31, 0x12, 0x57, 0x88, 0x84, 0xe0, 0x82, 0x2a, - 0xb6, 0x6a, 0xb5, 0xea, 0xdc, 0xfc, 0x4c, 0x86, 0x4d, 0xc6, 0x04, 0x8b, 0x05, 0xbd, 0x7f, 0x46, 0x24, 0x84, 0x69, - 0x43, 0x48, 0x96, 0x26, 0x90, 0x1a, 0x8f, 0x5b, 0xf3, 0x24, 0x6d, 0xba, 0x04, 0x7e, 0x5d, 0x5d, 0x50, 0xa8, 0xb4, - 0xa2, 0xe0, 0xe7, 0x35, 0x1c, 0x7b, 0x8d, 0x30, 0xf6, 0x0c, 0x40, 0x1f, 0x49, 0xa0, 0xcc, 0x48, 0x61, 0x31, 0xb5, - 0xa7, 0x38, 0x82, 0x5a, 0x79, 0xd9, 0xd9, 0xae, 0xef, 0xaa, 0x1e, 0x26, 0xf0, 0x57, 0xcc, 0x81, 0x17, 0x50, 0xe6, - 0x48, 0x73, 0xba, 0x5f, 0xfe, 0x01, 0x20, 0xdc, 0x78, 0xfe, 0x8a, 0x08, 0xe9, 0x50, 0xed, 0x03, 0x74, 0x8d, 0xca, - 0x5e, 0xc5, 0x8c, 0x72, 0xb0, 0xaa, 0x1b, 0xb3, 0x4d, 0xe2, 0xeb, 0xf8, 0xba, 0x06, 0xe6, 0xf7, 0xc4, 0xcf, 0x40, - 0xee, 0x61, 0x64, 0xd9, 0x3a, 0x99, 0xd2, 0x5b, 0x6d, 0xb7, 0xc1, 0x95, 0x12, 0x69, 0xc3, 0x64, 0x59, 0x93, 0x1a, - 0xe8, 0x69, 0x05, 0x16, 0xc1, 0xbf, 0xd1, 0x3b, 0xf6, 0x8d, 0x30, 0x9d, 0x63, 0xdb, 0x35, 0x9c, 0x4d, 0x4a, 0x8f, - 0x73, 0x95, 0x4e, 0x4a, 0x48, 0x4d, 0xc5, 0x97, 0xcc, 0xb8, 0x52, 0x1e, 0x13, 0xce, 0x71, 0x35, 0x18, 0x32, 0x0c, - 0xa9, 0xa0, 0xfe, 0x36, 0x59, 0x4a, 0x53, 0x72, 0x96, 0x08, 0x9f, 0x62, 0xf9, 0x33, 0xaa, 0x25, 0xb7, 0x6d, 0xe0, - 0x98, 0xf6, 0x9a, 0xe5, 0x62, 0xc1, 0x8b, 0xf9, 0x13, 0x04, 0x03, 0x1f, 0x5f, 0x51, 0x4b, 0x9e, 0xcb, 0x83, 0x9d, - 0xc4, 0x48, 0xc6, 0xbf, 0x67, 0xda, 0x0d, 0x91, 0xcb, 0x52, 0x85, 0xc8, 0x4c, 0x7f, 0xe6, 0x61, 0xf5, 0x61, 0x39, - 0xd8, 0x4c, 0x11, 0xd3, 0xbf, 0xdf, 0x3f, 0x35, 0x18, 0xc1, 0x0f, 0x3d, 0x39, 0x6d, 0x46, 0x08, 0x7a, 0x16, 0x1d, - 0x55, 0xd8, 0x23, 0x72, 0xa2, 0x00, 0xc9, 0xb2, 0x47, 0xb1, 0xbe, 0xa4, 0x8e, 0x8e, 0xb1, 0x1e, 0x87, 0x13, 0x56, - 0xf6, 0x1c, 0xc9, 0x73, 0x50, 0x57, 0xcd, 0x92, 0xea, 0xd8, 0x63, 0xc0, 0xea, 0x6f, 0x38, 0x95, 0xae, 0xb9, 0xbb, - 0x41, 0x04, 0x5b, 0x22, 0xed, 0x38, 0x72, 0x09, 0xa0, 0x13, 0x4c, 0x61, 0xc8, 0x79, 0x3e, 0x1e, 0xaa, 0x97, 0xbf, - 0x25, 0x3a, 0x2a, 0x71, 0x43, 0x89, 0x74, 0x4b, 0x94, 0x4e, 0x2f, 0x63, 0xcf, 0xee, 0x96, 0x4a, 0xff, 0xc0, 0x03, - 0x4c, 0xd7, 0x29, 0x04, 0x39, 0xe4, 0x24, 0xe1, 0xad, 0x4c, 0x85, 0xb3, 0x7c, 0xd3, 0x1d, 0xdc, 0xb3, 0x88, 0xf1, - 0x10, 0xee, 0xed, 0x0e, 0xb8, 0x0d, 0x2c, 0x46, 0x8d, 0x66, 0x32, 0x70, 0x31, 0xc5, 0x18, 0x8e, 0x38, 0xa4, 0x9c, - 0x23, 0x96, 0x95, 0x3d, 0xee, 0xe6, 0xec, 0x94, 0x41, 0xb4, 0x88, 0x2e, 0x43, 0x95, 0x36, 0x49, 0x8f, 0x1d, 0xb2, - 0x90, 0xf6, 0x29, 0x9e, 0x11, 0xb6, 0x51, 0xd5, 0x69, 0xa2, 0xef, 0x9e, 0x82, 0xe3, 0x19, 0x3a, 0xc3, 0xae, 0x3d, - 0x3f, 0x51, 0xd8, 0x1b, 0x86, 0x50, 0x7e, 0xc9, 0xaf, 0x32, 0x7f, 0x5d, 0x4d, 0x01, 0xac, 0xd8, 0x86, 0xf9, 0x84, - 0x20, 0xce, 0x5c, 0x71, 0x58, 0xe7, 0xdf, 0x6c, 0x66, 0x2b, 0x37, 0xd6, 0xf0, 0x42, 0xa7, 0x14, 0x6e, 0x1b, 0xfd, - 0x1c, 0xe8, 0xec, 0x8a, 0x84, 0x1f, 0x3d, 0xc7, 0x01, 0x64, 0x23, 0x95, 0x64, 0xae, 0xb8, 0xa7, 0xf6, 0xb7, 0x20, - 0xae, 0x1e, 0xc8, 0xc9, 0xa3, 0x17, 0x24, 0xe8, 0x25, 0xf4, 0xe7, 0xf3, 0xe8, 0x5c, 0xa2, 0x61, 0x6f, 0x94, 0x4f, - 0xde, 0x9f, 0xb1, 0x98, 0x5b, 0xa4, 0xc3, 0xb4, 0x94, 0xbe, 0x87, 0xc9, 0x1c, 0x27, 0x14, 0x49, 0xd5, 0x37, 0x8c, - 0x24, 0x78, 0xf1, 0x4c, 0xa2, 0x73, 0x21, 0x37, 0xe7, 0x34, 0x62, 0xb9, 0x67, 0x95, 0xd5, 0x6b, 0x47, 0x51, 0xde, - 0x71, 0x35, 0x4b, 0xba, 0x49, 0xcd, 0x52, 0xc7, 0x56, 0x15, 0x66, 0x34, 0x32, 0xbe, 0x70, 0xab, 0x17, 0x49, 0x39, - 0x64, 0x83, 0x94, 0x0d, 0x6c, 0x1a, 0x93, 0x85, 0x51, 0x73, 0xb3, 0xf3, 0x45, 0xdc, 0xb1, 0x5d, 0x05, 0xad, 0x52, - 0x25, 0xe9, 0xa0, 0x7e, 0x50, 0xed, 0xfd, 0x40, 0xdb, 0x26, 0xc9, 0xdf, 0xd5, 0xac, 0x8b, 0xef, 0xa1, 0xab, 0x9c, - 0x56, 0x3b, 0x10, 0xe6, 0xa3, 0xa2, 0x1d, 0x03, 0x03, 0x45, 0xf1, 0x60, 0x7b, 0x0a, 0x5d, 0xde, 0x6f, 0x8d, 0x4a, - 0x26, 0x9d, 0x02, 0x9b, 0xb2, 0x2a, 0x98, 0xa6, 0x0a, 0xab, 0xf3, 0x1a, 0xb3, 0xbf, 0x3d, 0x2e, 0x3b, 0x09, 0xec, - 0x25, 0xe3, 0x1e, 0x9f, 0x82, 0xdf, 0x50, 0xbc, 0xc6, 0x1a, 0x72, 0x71, 0x1a, 0x98, 0x49, 0x98, 0x45, 0x69, 0xfd, - 0x76, 0xad, 0x7b, 0xfb, 0xb7, 0x5d, 0x3f, 0xa4, 0xf0, 0x81, 0x1e, 0x27, 0x46, 0xcd, 0xfc, 0xa3, 0xfc, 0x5a, 0x4a, - 0x7c, 0xe9, 0xeb, 0x96, 0xbb, 0xbf, 0x52, 0x27, 0xb1, 0x86, 0x39, 0x0c, 0xad, 0xd8, 0x1a, 0xc9, 0x7e, 0x41, 0x4c, - 0x6f, 0xd7, 0x3b, 0x49, 0xc4, 0x80, 0x73, 0x3d, 0x47, 0x96, 0xf9, 0xcc, 0x15, 0xf4, 0x4c, 0x22, 0x34, 0x4c, 0x57, - 0x33, 0x8e, 0x5a, 0x86, 0x5a, 0x4c, 0x1d, 0xc3, 0x1f, 0x1e, 0x32, 0x19, 0x3b, 0x94, 0xd1, 0x8f, 0x75, 0x7c, 0x9b, - 0x1a, 0xcb, 0x86, 0xaf, 0xa1, 0xdc, 0xb3, 0xcb, 0x3f, 0x3a, 0xd4, 0xe6, 0x71, 0x8f, 0xc7, 0xea, 0x20, 0x5e, 0xad, - 0xf6, 0xec, 0x0d, 0x8a, 0x58, 0x9f, 0xd6, 0xb0, 0x3a, 0xb8, 0xcc, 0xe6, 0xfc, 0x1c, 0x6c, 0x12, 0x5c, 0xbd, 0xd5, - 0xcd, 0x2f, 0x43, 0x74, 0x6b, 0x5c, 0x43, 0x72, 0x7e, 0x76, 0xbe, 0x87, 0x8f, 0xf8, 0xc9, 0xcf, 0xb4, 0x64, 0x9e, - 0xad, 0x13, 0xd8, 0x64, 0xd9, 0xb5, 0x65, 0x7e, 0x94, 0x3b, 0xbc, 0x2f, 0xfe, 0x67, 0x7d, 0x61, 0x03, 0x04, 0x84, - 0xf3, 0x4b, 0xfa, 0xc5, 0xe1, 0x39, 0xdb, 0x20, 0x76, 0xbe, 0xf9, 0xbe, 0x48, 0x73, 0x95, 0x06, 0x77, 0xfe, 0xd8, - 0x19, 0x82, 0x63, 0x04, 0xd8, 0x8b, 0xa0, 0x11, 0x21, 0x99, 0xde, 0x91, 0x52, 0x74, 0xb3, 0xc6, 0x69, 0x25, 0x65, - 0x2d, 0xdc, 0x57, 0xda, 0xd4, 0x5d, 0xb9, 0xbb, 0xa8, 0x88, 0xd9, 0xa5, 0x09, 0x0e, 0x05, 0x16, 0x23, 0x93, 0xb2, - 0x24, 0x85, 0xa6, 0xbc, 0xf8, 0x47, 0x82, 0x1d, 0x01, 0x93, 0x6b, 0xb4, 0x0a, 0xc1, 0x38, 0x9f, 0x77, 0x56, 0xa5, - 0xa7, 0x91, 0x21, 0xa8, 0x1e, 0x79, 0x65, 0x4b, 0x35, 0x8b, 0xa6, 0xa6, 0x7c, 0x97, 0x5a, 0x37, 0x62, 0xd8, 0x7b, - 0xd5, 0x72, 0x82, 0xbc, 0xab, 0xc4, 0xc9, 0x4d, 0x0e, 0xe3, 0x92, 0xf9, 0x1a, 0x41, 0x89, 0x34, 0xb3, 0x77, 0x09, - 0x93, 0x4d, 0xa6, 0x9c, 0xb3, 0x60, 0x5b, 0xc7, 0x20, 0x91, 0x38, 0x96, 0x1d, 0x12, 0x72, 0x95, 0xf6, 0x4d, 0x96, - 0xa2, 0x3a, 0x73, 0x2a, 0x43, 0x3f, 0xed, 0x78, 0x39, 0x47, 0x4c, 0xc7, 0xd9, 0x22, 0x1d, 0x23, 0x06, 0x10, 0xc6, - 0x8c, 0x27, 0x48, 0xd5, 0xbc, 0x94, 0xd1, 0xea, 0xe2, 0x19, 0xae, 0x51, 0x7b, 0x10, 0x98, 0xe8, 0x18, 0xc4, 0xbe, - 0x4e, 0x68, 0x9c, 0x88, 0xe6, 0x44, 0x79, 0xaf, 0xb5, 0xb0, 0xdd, 0x37, 0xb4, 0x2e, 0x99, 0xc2, 0xa5, 0x14, 0x48, - 0x2c, 0xf3, 0xeb, 0x40, 0xf2, 0x42, 0xd3, 0x58, 0xd1, 0x6a, 0x09, 0xc0, 0xd4, 0x16, 0xcf, 0xd3, 0xb7, 0x7c, 0x33, - 0xab, 0xc7, 0xec, 0x33, 0xba, 0x05, 0xb8, 0xf6, 0x29, 0x65, 0x5c, 0x0f, 0x1e, 0x7b, 0xa0, 0x40, 0x03, 0xf4, 0x94, - 0x73, 0xb7, 0xf8, 0x2b, 0xdb, 0x10, 0xaf, 0x43, 0x37, 0xa8, 0x65, 0x89, 0x3e, 0xe7, 0xd7, 0xe2, 0xe2, 0x3f, 0xe5, - 0x2e, 0x08, 0x8c, 0x5c, 0x7c, 0x52, 0xd0, 0xc3, 0x69, 0xa2, 0xcb, 0x84, 0xc7, 0x7b, 0xd4, 0x69, 0x0a, 0xca, 0x0d, - 0xcc, 0xe2, 0x26, 0x8b, 0x26, 0xdd, 0x5d, 0xdb, 0xea, 0xde, 0x1d, 0x8e, 0x35, 0x37, 0x75, 0x88, 0x3d, 0x75, 0x6f, - 0x56, 0x4d, 0x71, 0xf1, 0x6d, 0xdb, 0x64, 0x1a, 0xb6, 0x36, 0x8a, 0x4a, 0x9a, 0xe6, 0x2d, 0x6b, 0x7f, 0x91, 0xed, - 0x34, 0xc0, 0xdb, 0x85, 0x44, 0xd7, 0x7c, 0xb4, 0x04, 0xb1, 0xa5, 0xfc, 0x78, 0x31, 0xe5, 0xb1, 0xa2, 0xc5, 0x19, - 0xd6, 0x4d, 0xaa, 0x4c, 0xf2, 0x0c, 0x1d, 0x4d, 0xa8, 0xf3, 0x7d, 0x1c, 0x56, 0x8d, 0x46, 0xff, 0xbc, 0x4e, 0xcd, - 0x08, 0x93, 0xd0, 0xe8, 0x44, 0x38, 0x73, 0x18, 0x97, 0xc6, 0x88, 0x97, 0x5e, 0x7e, 0xcc, 0x3f, 0x98, 0x53, 0x14, - 0x58, 0x4f, 0x70, 0x5e, 0x0f, 0x6d, 0xe6, 0xc4, 0x21, 0xd0, 0x73, 0x63, 0x94, 0xf5, 0x25, 0xfd, 0xcc, 0x1b, 0x8d, - 0x7d, 0x28, 0xb9, 0x20, 0x08, 0x15, 0x9e, 0x73, 0x1c, 0x32, 0xcc, 0x40, 0x5f, 0x37, 0xd9, 0x02, 0x3f, 0x6b, 0x73, - 0x1e, 0xf6, 0x45, 0xac, 0x2d, 0x47, 0x17, 0x83, 0xaf, 0x9e, 0xd7, 0x31, 0x3f, 0x90, 0xbf, 0x5d, 0x2b, 0xe3, 0x18, - 0x95, 0x68, 0x10, 0xbb, 0x22, 0x6d, 0x0a, 0x80, 0xa8, 0xd4, 0x39, 0x0e, 0xa2, 0x02, 0xc6, 0xda, 0x0f, 0x94, 0x26, - 0x94, 0x91, 0x02, 0x58, 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x23, 0xd9, 0x35, 0xab, 0x8f, 0x91, 0xc5, 0x79, 0xb4, 0xbb, - 0x9a, 0x38, 0x2d, 0xba, 0x7b, 0x71, 0x51, 0x26, 0xc6, 0x3d, 0x2a, 0xda, 0x92, 0xc6, 0xad, 0x01, 0x73, 0x56, 0x74, - 0x6b, 0x32, 0x95, 0xab, 0x3b, 0x76, 0x96, 0xe0, 0xf4, 0xd6, 0x15, 0x58, 0xeb, 0x0e, 0xe6, 0xeb, 0x74, 0x56, 0xdc, - 0x7f, 0xa2, 0x20, 0x4d, 0x23, 0xb0, 0x66, 0x13, 0xa4, 0xfa, 0xd1, 0x92, 0x33, 0x0b, 0x58, 0xa5, 0x49, 0x69, 0x69, - 0x05, 0x0c, 0x3e, 0xdb, 0x88, 0x37, 0x6c, 0xcf, 0x9a, 0x0e, 0xab, 0xd1, 0xf7, 0xbe, 0x53, 0x93, 0xda, 0x23, 0xd3, - 0xdd, 0xf6, 0xe6, 0x14, 0x42, 0xf4, 0x85, 0x29, 0xcd, 0x14, 0x01, 0x70, 0xfe, 0xd3, 0x13, 0xc0, 0xed, 0xdb, 0x83, - 0x60, 0xa9, 0xe4, 0xb9, 0xda, 0x9c, 0xb0, 0x03, 0x22, 0x5b, 0xce, 0x75, 0x47, 0x42, 0x0c, 0x8e, 0x39, 0xa3, 0xa2, - 0x17, 0x24, 0x71, 0x06, 0xad, 0x6c, 0x75, 0x0d, 0xf8, 0xad, 0xc3, 0x81, 0x09, 0x51, 0x8e, 0x60, 0xf0, 0x8e, 0x31, - 0x6c, 0x66, 0x72, 0x9b, 0xd1, 0x40, 0x34, 0x54, 0x43, 0x96, 0x2f, 0x7b, 0xb1, 0x3d, 0xda, 0xd1, 0x7c, 0x60, 0xc9, - 0xfc, 0xe6, 0x13, 0xe1, 0x3e, 0xb6, 0x7b, 0xd8, 0xab, 0xef, 0x85, 0x49, 0x75, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, - 0xb8, 0xae, 0x5e, 0x9a, 0xbd, 0xe9, 0x1f, 0xce, 0xc6, 0x22, 0x07, 0x59, 0x05, 0xfd, 0x79, 0x30, 0x0f, 0x04, 0xd5, - 0xd4, 0x65, 0xb2, 0x08, 0x70, 0xa9, 0x11, 0xa5, 0xd7, 0x3a, 0x23, 0xb0, 0x0d, 0x8c, 0xeb, 0xb1, 0xb9, 0xc2, 0xd3, - 0xf3, 0x59, 0x12, 0x0d, 0x72, 0x28, 0x15, 0x7a, 0xcd, 0xe7, 0xa3, 0x0f, 0x4a, 0xfe, 0xeb, 0xf2, 0xb4, 0xfe, 0x4b, - 0xca, 0x19, 0xa8, 0xa6, 0x9d, 0xca, 0x3f, 0x96, 0x75, 0x10, 0x6f, 0x5b, 0xd7, 0x77, 0xae, 0xe7, 0x3f, 0x4c, 0x48, - 0xa6, 0xce, 0x6d, 0xe8, 0x2c, 0x26, 0x7d, 0xbf, 0x4b, 0xb4, 0x71, 0xb6, 0x22, 0x25, 0x06, 0xaa, 0xf6, 0x05, 0xd9, - 0xa4, 0xde, 0x24, 0xb5, 0xba, 0xf1, 0x91, 0xb6, 0xc8, 0x0a, 0x6e, 0x1a, 0xb2, 0x81, 0xfa, 0x69, 0xef, 0x8e, 0xdd, - 0xbe, 0x3f, 0x99, 0xbb, 0xaf, 0xdd, 0xe6, 0xdf, 0x28, 0xbb, 0xfd, 0xdc, 0x1b, 0x69, 0x36, 0x14, 0x3d, 0x6f, 0xbc, - 0x6c, 0x4b, 0xc6, 0xc1, 0x5b, 0x33, 0x03, 0xc1, 0x61, 0x4e, 0x3e, 0xd6, 0x79, 0x06, 0x24, 0x2d, 0xb3, 0x68, 0x03, - 0x72, 0x8d, 0x4b, 0x1c, 0x50, 0x55, 0xb0, 0xf3, 0x99, 0xa9, 0x36, 0x27, 0x12, 0xd7, 0x3b, 0x59, 0x1e, 0x76, 0x74, - 0x71, 0x87, 0x69, 0x99, 0x6e, 0xe2, 0xc2, 0xd1, 0x0d, 0x3b, 0x25, 0x4d, 0x36, 0x4f, 0x34, 0x9b, 0x4e, 0xbf, 0x4b, - 0xfa, 0xe6, 0x30, 0x90, 0x36, 0x67, 0x3e, 0xdc, 0x74, 0x1e, 0xba, 0xd0, 0x15, 0xee, 0x26, 0x15, 0xa9, 0xb4, 0x9c, - 0x40, 0x55, 0xc7, 0xb6, 0x52, 0x50, 0x94, 0xe2, 0xdf, 0x7c, 0x6f, 0x78, 0x58, 0x15, 0x7c, 0x13, 0x13, 0x49, 0xcc, - 0xd6, 0xaa, 0xf1, 0x85, 0x38, 0xfd, 0x41, 0x99, 0xb7, 0xf3, 0xf9, 0x24, 0x8e, 0x21, 0xff, 0xbd, 0x6a, 0x2a, 0x52, - 0x40, 0x93, 0x38, 0x48, 0xc8, 0xcc, 0xd8, 0x29, 0xfa, 0x78, 0x42, 0xe8, 0x4c, 0x52, 0x3e, 0xb8, 0xcc, 0xc1, 0x2f, - 0xbb, 0x3d, 0xba, 0xad, 0x72, 0x9b, 0x5b, 0x81, 0x3d, 0x55, 0x53, 0xa4, 0x25, 0x85, 0x4c, 0xba, 0x3a, 0x75, 0x6c, - 0x9c, 0xf5, 0xb5, 0xfb, 0x6f, 0x55, 0xc9, 0x9e, 0xbf, 0x3e, 0xe7, 0x6b, 0xe3, 0x90, 0x26, 0x15, 0xff, 0x8e, 0xdb, - 0x75, 0x77, 0x03, 0xc0, 0x9f, 0xb5, 0x4a, 0x89, 0x97, 0xd2, 0x35, 0xdd, 0x57, 0xd1, 0x6e, 0x78, 0xb6, 0xea, 0x27, - 0x4c, 0xd9, 0x9b, 0x91, 0xf2, 0x7e, 0xa2, 0xfe, 0xd2, 0xc3, 0x96, 0xa3, 0x19, 0x70, 0x32, 0xbc, 0xb9, 0x9d, 0x3b, - 0xcc, 0xf9, 0xd7, 0xd8, 0x1a, 0x0e, 0xbb, 0x6f, 0x40, 0x6f, 0x51, 0x1c, 0xb5, 0x6b, 0xa2, 0x64, 0x02, 0x01, 0x13, - 0xc1, 0x81, 0xb8, 0x8f, 0xd5, 0x48, 0x66, 0xed, 0x4b, 0xd8, 0x1d, 0xad, 0x4c, 0x8b, 0x96, 0x6a, 0xcd, 0xa7, 0x42, - 0x99, 0x49, 0x2a, 0x86, 0xd5, 0xc0, 0x9f, 0x5d, 0x39, 0x2d, 0xf8, 0x12, 0x58, 0x5e, 0xee, 0x78, 0x16, 0xb6, 0x0b, - 0x79, 0x7f, 0xfb, 0x60, 0x0d, 0xf8, 0x58, 0x9f, 0xb2, 0xe2, 0xbd, 0xfe, 0x77, 0x61, 0x43, 0x2d, 0x3d, 0xe6, 0xd7, - 0x66, 0xe1, 0x07, 0xe7, 0x35, 0x0e, 0x6e, 0x55, 0xed, 0x54, 0x31, 0x2e, 0x45, 0x14, 0x40, 0x80, 0x57, 0x34, 0x7c, - 0x47, 0x9d, 0xc7, 0xb3, 0xba, 0x44, 0x3f, 0x7e, 0xdf, 0x6d, 0x69, 0x4b, 0x12, 0x10, 0xa5, 0xca, 0x29, 0x72, 0x2b, - 0x27, 0xd7, 0x2c, 0x92, 0xa5, 0x77, 0x66, 0xd3, 0xa8, 0x68, 0x1a, 0x00, 0x48, 0xdf, 0x23, 0xcf, 0x82, 0xe7, 0x50, - 0x6e, 0x25, 0xf1, 0x56, 0xc9, 0x4c, 0x80, 0x89, 0xc2, 0x0f, 0x12, 0x21, 0x0c, 0x88, 0xbc, 0x1b, 0x06, 0x69, 0x6d, - 0x5f, 0xb8, 0x3e, 0x03, 0x58, 0x26, 0xc4, 0x5f, 0xdc, 0x87, 0x5b, 0xe7, 0xd3, 0xc1, 0xc9, 0x8d, 0x1c, 0x22, 0x82, - 0xd9, 0x28, 0xdd, 0x9b, 0x1c, 0x59, 0x65, 0xf7, 0x93, 0xab, 0x56, 0x4f, 0x04, 0x54, 0x5a, 0xbe, 0x57, 0xdc, 0x8c, - 0x38, 0x7f, 0x06, 0xdd, 0x6d, 0x70, 0xe5, 0x2a, 0xe7, 0xb4, 0x53, 0xd9, 0x21, 0xd9, 0xfe, 0xbb, 0x08, 0x5a, 0x94, - 0xcd, 0x14, 0xbe, 0x94, 0x2d, 0x3c, 0xb7, 0xd5, 0x95, 0xdb, 0x00, 0x90, 0x45, 0x62, 0x34, 0x17, 0x0d, 0xef, 0x92, - 0x08, 0xe3, 0xa2, 0xcd, 0x9f, 0xaa, 0x4f, 0xb3, 0x1a, 0x2a, 0xca, 0x46, 0xb5, 0xd9, 0x68, 0x86, 0x0c, 0xc4, 0x13, - 0xf4, 0xf2, 0xab, 0x1d, 0xe0, 0xc7, 0x2a, 0x79, 0xb2, 0x74, 0x1b, 0xf1, 0xb6, 0x3e, 0x49, 0xd4, 0xd3, 0x56, 0xf7, - 0x65, 0x98, 0x2c, 0x68, 0x9e, 0x3e, 0xff, 0xdf, 0x1d, 0xe0, 0x97, 0x90, 0x87, 0x2b, 0x16, 0xbe, 0x53, 0x75, 0x1f, - 0xaf, 0xaa, 0x70, 0xb1, 0x5e, 0x36, 0xe7, 0x83, 0x0e, 0x20, 0x47, 0xaa, 0xfa, 0x7d, 0x0e, 0xd3, 0x90, 0xe5, 0xb7, - 0x46, 0x17, 0x6e, 0x45, 0xc1, 0x81, 0xe7, 0xbd, 0x16, 0x2d, 0xd4, 0xd4, 0x55, 0x46, 0x84, 0x71, 0x4a, 0x50, 0x87, - 0x5b, 0x5d, 0xf0, 0xb4, 0x9b, 0x5b, 0x50, 0x49, 0x9e, 0x77, 0x93, 0x08, 0xe9, 0xc0, 0x7b, 0xb7, 0x52, 0x56, 0xbd, - 0x6e, 0x08, 0xc3, 0x5e, 0x39, 0xbb, 0x0a, 0x95, 0x3a, 0xad, 0xb4, 0x86, 0x1b, 0x5a, 0xb5, 0xa6, 0x68, 0xe0, 0xe4, - 0x94, 0xaa, 0x55, 0x2d, 0x79, 0xd6, 0x74, 0x6e, 0xb2, 0xcd, 0x5c, 0x56, 0x74, 0xdd, 0x21, 0xc3, 0x2b, 0x85, 0x75, - 0x5d, 0x07, 0xd7, 0x70, 0xa2, 0xc1, 0x79, 0xdf, 0x6e, 0x5b, 0x8e, 0x14, 0xd9, 0x2e, 0x56, 0x17, 0xee, 0xe8, 0xf8, - 0x2f, 0x0f, 0x28, 0x3e, 0x1d, 0xb5, 0xe4, 0x51, 0x8c, 0xac, 0xd0, 0x34, 0xb8, 0x06, 0x22, 0xfc, 0x0b, 0xaf, 0x4d, - 0xda, 0x6b, 0x4a, 0x26, 0xd4, 0xad, 0x9b, 0x73, 0x38, 0x48, 0x4b, 0xfc, 0xd2, 0x34, 0x8d, 0xb7, 0x79, 0x7a, 0x1f, - 0x4d, 0x56, 0xb5, 0xb7, 0x88, 0x4d, 0x7a, 0x76, 0x6d, 0x64, 0xb8, 0xc1, 0x84, 0x3c, 0xfe, 0x07, 0x3b, 0x01, 0x3a, - 0x91, 0x92, 0x05, 0x97, 0xe3, 0xca, 0x52, 0x0c, 0xf5, 0x9b, 0x57, 0x26, 0xeb, 0x53, 0x58, 0x64, 0x5e, 0x46, 0xae, - 0x5b, 0x2a, 0x47, 0xc3, 0x0f, 0x7d, 0x92, 0x2a, 0xe2, 0x3c, 0x03, 0x11, 0x78, 0xca, 0x6a, 0xe9, 0x79, 0x8e, 0x59, - 0x1b, 0x47, 0x92, 0xf9, 0x20, 0x24, 0x1f, 0xc6, 0xa5, 0x18, 0x52, 0x6c, 0xdf, 0xd8, 0x52, 0xe5, 0xf8, 0x86, 0x10, - 0x95, 0x13, 0xae, 0xa0, 0x09, 0x63, 0xed, 0x4f, 0x51, 0x51, 0x74, 0x67, 0xb5, 0x24, 0xd8, 0xad, 0x3a, 0x39, 0xa9, - 0xce, 0x34, 0x7f, 0x80, 0xc1, 0xd2, 0x1b, 0x74, 0x74, 0x58, 0x57, 0x63, 0x7e, 0x74, 0xb0, 0xe2, 0xd6, 0x57, 0x36, - 0x99, 0x45, 0xdb, 0x98, 0x71, 0xa6, 0xd4, 0x16, 0xdf, 0x5b, 0x9b, 0x5d, 0x04, 0x66, 0xf7, 0x0a, 0x97, 0x28, 0x22, - 0x67, 0xeb, 0x98, 0x91, 0x54, 0x71, 0xed, 0x10, 0xa9, 0xea, 0x9c, 0xd0, 0xc7, 0x40, 0x8b, 0xcf, 0x38, 0x5d, 0x2d, - 0xc4, 0x36, 0x0e, 0xbb, 0x8e, 0x4c, 0x95, 0xe4, 0x77, 0xd1, 0xe7, 0x7e, 0x2c, 0xc1, 0xe6, 0x02, 0xe2, 0x39, 0xdf, - 0x3b, 0x17, 0x6a, 0x16, 0x76, 0x21, 0xec, 0x60, 0x1a, 0x25, 0xe4, 0x68, 0xbf, 0x56, 0x7e, 0x8e, 0xe0, 0xd5, 0x2b, - 0x3d, 0x93, 0x0d, 0x3f, 0x11, 0xd1, 0xca, 0x52, 0xc2, 0x91, 0x0c, 0xa3, 0xf7, 0x2f, 0xde, 0xdc, 0x70, 0x90, 0xa1, - 0xf0, 0x0c, 0x36, 0x0f, 0x44, 0xc0, 0xed, 0xdd, 0x4f, 0x98, 0xd6, 0x52, 0x29, 0x08, 0xe7, 0x0a, 0x86, 0x04, 0x1b, - 0xe3, 0x52, 0x66, 0x6b, 0x93, 0x35, 0x01, 0x6b, 0xe1, 0x88, 0x3a, 0x68, 0x4c, 0x7a, 0x9e, 0x77, 0x9a, 0xd6, 0x31, - 0xff, 0x29, 0xb8, 0x60, 0xf9, 0x9e, 0x8d, 0xeb, 0x15, 0x04, 0xcd, 0x35, 0xae, 0xb1, 0xa6, 0xbb, 0xe8, 0x41, 0xea, - 0xfd, 0x35, 0x7b, 0xc6, 0x2a, 0x7f, 0xb7, 0xc0, 0x24, 0xd0, 0xa0, 0x50, 0x34, 0xe5, 0x2b, 0xa1, 0x43, 0x88, 0x5e, - 0xcd, 0x1b, 0xff, 0x2a, 0x7a, 0x96, 0x53, 0xcd, 0xe4, 0x76, 0xa3, 0x1a, 0x9a, 0x61, 0xca, 0x14, 0x12, 0xda, 0xc6, - 0x0f, 0x24, 0x5f, 0x76, 0xcb, 0xd4, 0xc2, 0x9c, 0xfd, 0x97, 0x16, 0xc7, 0xb1, 0x85, 0xaa, 0x55, 0x5f, 0x84, 0x39, - 0x4e, 0x4c, 0x5b, 0x77, 0xd9, 0xc8, 0x9d, 0xcd, 0x21, 0xa8, 0xa6, 0x6c, 0x6e, 0xd4, 0xbd, 0x63, 0x3e, 0x32, 0x87, - 0xb7, 0xc8, 0xef, 0x76, 0x64, 0x5e, 0x26, 0x97, 0x7d, 0xfc, 0xac, 0xd7, 0xbf, 0x09, 0x80, 0xc4, 0x36, 0x06, 0x8e, - 0xcd, 0xf3, 0xae, 0xb1, 0x96, 0x1b, 0xd3, 0x45, 0x62, 0x4d, 0x1d, 0x00, 0x0a, 0x9e, 0x72, 0xa0, 0x50, 0x49, 0x53, - 0x12, 0x04, 0xf5, 0x10, 0x72, 0x44, 0x39, 0xbe, 0x5d, 0xc4, 0x5c, 0xd7, 0xab, 0xc9, 0xc6, 0xbf, 0xdc, 0xfa, 0x68, - 0xd5, 0x07, 0xb4, 0xfb, 0x99, 0x8d, 0x7a, 0x58, 0xa4, 0xc6, 0x29, 0x0c, 0xf9, 0x11, 0xe7, 0xb1, 0xa6, 0x41, 0x37, - 0x4e, 0x06, 0x5a, 0x41, 0x2f, 0x15, 0xf8, 0xdf, 0x42, 0x39, 0x63, 0xe5, 0x46, 0x79, 0xa8, 0x58, 0xad, 0x5d, 0xf7, - 0xaf, 0xf8, 0x32, 0x62, 0x12, 0xa6, 0x87, 0x27, 0x60, 0xd6, 0x52, 0xae, 0xe4, 0xe7, 0xf5, 0x36, 0x54, 0x0b, 0x0f, - 0x38, 0xe9, 0xbc, 0xae, 0x3e, 0x07, 0x72, 0x91, 0x35, 0x53, 0x74, 0x68, 0xce, 0xd3, 0xa0, 0x82, 0x09, 0xbf, 0xad, - 0xe7, 0x26, 0x09, 0xba, 0xd4, 0x38, 0x56, 0x1e, 0x76, 0x1f, 0x47, 0xa3, 0xb3, 0x28, 0x27, 0x2e, 0x54, 0x63, 0x97, - 0xe7, 0x59, 0x54, 0x39, 0x2f, 0xf6, 0xa4, 0xab, 0x75, 0x65, 0xad, 0xbd, 0xa5, 0x15, 0xf3, 0xc6, 0x50, 0x4b, 0x52, - 0x73, 0x98, 0xd6, 0x89, 0x34, 0xb3, 0x68, 0x58, 0x99, 0x55, 0x08, 0xde, 0x86, 0xdd, 0x46, 0x88, 0xec, 0x82, 0x83, - 0xb4, 0x10, 0x2f, 0xbd, 0x59, 0x6a, 0x38, 0xc1, 0x53, 0xc8, 0x15, 0xfd, 0xc3, 0x69, 0x61, 0x40, 0x6a, 0x2b, 0x4a, - 0x66, 0xfd, 0xe8, 0xbf, 0xd9, 0x0c, 0xf7, 0x33, 0xd7, 0xca, 0x3b, 0xd4, 0x1f, 0x07, 0xa3, 0xd9, 0x8f, 0x49, 0x9f, - 0x72, 0xde, 0x2e, 0x05, 0x98, 0x2c, 0xc1, 0xb9, 0x17, 0xec, 0xcd, 0x80, 0x96, 0x37, 0x5e, 0x35, 0xb9, 0x21, 0x13, - 0xae, 0x9f, 0x24, 0x71, 0x2e, 0x56, 0x41, 0x7a, 0x09, 0xee, 0xbd, 0x68, 0xa8, 0x95, 0x05, 0xe9, 0xfe, 0x63, 0xb6, - 0xf8, 0x6b, 0x83, 0x91, 0x29, 0x88, 0x4f, 0x9e, 0xb0, 0xb7, 0x24, 0x8d, 0x4f, 0xe0, 0xd6, 0xb1, 0xe1, 0xda, 0xac, - 0x40, 0x1f, 0xfc, 0x79, 0xb2, 0x70, 0x68, 0x0d, 0xfc, 0xe7, 0xbb, 0x7f, 0x19, 0xaa, 0x1e, 0x3c, 0xdb, 0x99, 0x26, - 0xeb, 0x86, 0x9a, 0x48, 0xc3, 0x5f, 0xed, 0x7d, 0x01, 0xb8, 0x08, 0x57, 0x31, 0x03, 0x12, 0xd0, 0x95, 0xae, 0x58, - 0x60, 0x98, 0x02, 0xbb, 0x8c, 0xfe, 0x04, 0xbc, 0xad, 0x5c, 0x63, 0x3a, 0x4c, 0x8a, 0x4d, 0x00, 0xc4, 0x25, 0x01, - 0xf2, 0x96, 0x0e, 0x55, 0x04, 0x3a, 0x38, 0xc4, 0x7a, 0x79, 0x67, 0x12, 0xdf, 0xb9, 0x8f, 0xac, 0xce, 0x81, 0x3f, - 0x0d, 0xc8, 0x76, 0xa1, 0x00, 0x76, 0xcb, 0xbd, 0x5d, 0x87, 0x47, 0x83, 0x0c, 0x29, 0x51, 0x8c, 0x25, 0xf8, 0xf8, - 0x64, 0x1e, 0xf3, 0x98, 0xe7, 0xe3, 0x80, 0x6f, 0xf4, 0x01, 0x54, 0x1c, 0x2a, 0x90, 0xbf, 0x0b, 0x51, 0xa1, 0x2e, - 0xf7, 0xd1, 0x02, 0xc0, 0xe8, 0x13, 0xcc, 0xa1, 0x13, 0xb7, 0xd4, 0x1b, 0x50, 0xe5, 0x7b, 0x90, 0x52, 0x09, 0xfe, - 0x46, 0x26, 0x53, 0xd5, 0x9e, 0x8a, 0x59, 0x55, 0x18, 0x45, 0x24, 0x6c, 0xd4, 0x16, 0xc2, 0x1d, 0x63, 0x46, 0xcd, - 0x8f, 0x9d, 0x79, 0x1c, 0x4b, 0x7b, 0x3d, 0x12, 0x4a, 0x76, 0xc6, 0x7b, 0x0f, 0x4a, 0xe1, 0xe0, 0x2a, 0x80, 0xfb, - 0xb4, 0xfa, 0x9c, 0x4a, 0x8c, 0x99, 0x65, 0xd1, 0xf0, 0x50, 0x7a, 0x93, 0xa8, 0xf1, 0x55, 0x70, 0xfd, 0xcd, 0x40, - 0xbc, 0x8a, 0x3f, 0x7b, 0xdc, 0xf4, 0x71, 0xf5, 0xbf, 0x21, 0xe0, 0xea, 0x2c, 0x5c, 0x39, 0x61, 0x9f, 0x27, 0xc8, - 0xd7, 0x0d, 0xde, 0x2e, 0x5b, 0x4b, 0x34, 0x4f, 0x66, 0xe9, 0x73, 0x67, 0x58, 0xa0, 0xaa, 0xaa, 0xf9, 0x2d, 0x0a, - 0x25, 0x64, 0x91, 0x41, 0x68, 0x48, 0x9a, 0x99, 0x48, 0xed, 0xdc, 0x5b, 0x6e, 0x62, 0x47, 0x1a, 0x78, 0xda, 0xee, - 0x3d, 0xc3, 0xc7, 0x68, 0x30, 0x14, 0xc9, 0x33, 0xb8, 0xf2, 0x06, 0xba, 0x52, 0x49, 0xca, 0xe5, 0x7c, 0x2c, 0xfa, - 0x32, 0xf4, 0x2b, 0xfa, 0x4d, 0x5a, 0x96, 0xc7, 0x5d, 0x24, 0x52, 0xff, 0x57, 0xb9, 0xe6, 0x34, 0xfa, 0xbc, 0x34, - 0xb6, 0x51, 0x31, 0x68, 0x70, 0xdb, 0x14, 0x08, 0x39, 0x53, 0x5a, 0x94, 0x1e, 0x0c, 0x2d, 0x7d, 0xff, 0xc3, 0x55, - 0x58, 0xba, 0xa7, 0xb4, 0x53, 0x9e, 0x5e, 0xf4, 0x52, 0x83, 0x81, 0xf8, 0x77, 0xb2, 0xe4, 0x4d, 0x5f, 0xa9, 0x91, - 0x4c, 0xfc, 0x1f, 0xbc, 0xb4, 0x51, 0x2e, 0x97, 0x3a, 0xa5, 0xd3, 0x0e, 0x8a, 0xa3, 0x2e, 0x39, 0x1e, 0xc5, 0xbe, - 0x65, 0x34, 0x8a, 0x57, 0xca, 0x3e, 0x8b, 0x89, 0x1b, 0xf4, 0x44, 0x34, 0x68, 0xd6, 0x32, 0x80, 0x26, 0x7a, 0x4d, - 0xc9, 0x88, 0x53, 0x77, 0x82, 0x1b, 0x81, 0x32, 0xab, 0x68, 0x43, 0x52, 0x37, 0xbe, 0x31, 0x98, 0x5a, 0x3d, 0xee, - 0x87, 0x21, 0x2a, 0x65, 0x7d, 0xfb, 0x74, 0x44, 0xd5, 0x57, 0xd9, 0xa5, 0xf4, 0xad, 0x62, 0xa3, 0x5d, 0xea, 0x70, - 0xc7, 0x1c, 0xd8, 0xe4, 0x99, 0x41, 0x2d, 0x67, 0x0e, 0x31, 0x3f, 0x3d, 0x8f, 0x36, 0x0e, 0x98, 0x9d, 0x18, 0x62, - 0x8e, 0x3a, 0x57, 0x25, 0x90, 0xc6, 0x60, 0x3a, 0xb1, 0x93, 0x44, 0xea, 0x4b, 0xcb, 0x5e, 0xaf, 0x54, 0x31, 0xa7, - 0x96, 0x96, 0xfd, 0x00, 0x76, 0xf8, 0x4a, 0xcb, 0x4f, 0x54, 0x61, 0x68, 0x76, 0xcb, 0x1a, 0xe1, 0xaf, 0x36, 0xbd, - 0x8e, 0xd7, 0xf1, 0x2a, 0x95, 0xa5, 0x3b, 0x20, 0x86, 0x1c, 0xcc, 0x4e, 0xb0, 0x01, 0x29, 0xa2, 0x65, 0x71, 0xbe, - 0xe6, 0x29, 0x9f, 0x8d, 0x63, 0x89, 0xb5, 0xd1, 0x63, 0xcb, 0xdb, 0xe6, 0xdc, 0xa3, 0x19, 0xa1, 0x22, 0x51, 0x62, - 0xd9, 0xd6, 0xb0, 0xb8, 0x11, 0x0b, 0x4a, 0x88, 0x25, 0xfa, 0x05, 0x3f, 0x23, 0xe2, 0x6a, 0x80, 0xde, 0xa4, 0x76, - 0x06, 0x5d, 0x05, 0x1d, 0x8c, 0xa3, 0x6b, 0xfe, 0x3b, 0x0d, 0x37, 0x85, 0x2e, 0x11, 0xb7, 0x0d, 0x70, 0xc9, 0xc5, - 0x0c, 0x83, 0x3a, 0x85, 0xac, 0x6e, 0xe2, 0x5b, 0x5d, 0xe4, 0x7f, 0x62, 0xf1, 0x27, 0xb8, 0x90, 0x17, 0x97, 0x86, - 0x17, 0xe4, 0xa6, 0xbc, 0xf7, 0x5b, 0xdc, 0xc8, 0x10, 0xad, 0x7c, 0xfa, 0xe8, 0xf2, 0x62, 0x91, 0x66, 0xdc, 0xa9, - 0xe9, 0xad, 0xf1, 0xb9, 0x6e, 0x45, 0x7f, 0x32, 0x9e, 0x9b, 0x71, 0x92, 0x66, 0xe4, 0xa7, 0x7c, 0xc8, 0xef, 0xa1, - 0x54, 0x33, 0x9c, 0x57, 0x73, 0x1d, 0x50, 0xcf, 0x0c, 0x5f, 0x4e, 0x63, 0x1d, 0x98, 0x74, 0x0b, 0xfe, 0xb0, 0x87, - 0x43, 0xd9, 0xb4, 0xb7, 0x4f, 0xde, 0xf0, 0xb9, 0xd5, 0x3d, 0x5d, 0x32, 0x4a, 0x1a, 0x4c, 0x7d, 0x54, 0xb5, 0xdf, - 0x97, 0x68, 0x1c, 0xc4, 0xd3, 0x18, 0x6b, 0x44, 0xff, 0x4b, 0x7c, 0x7c, 0x55, 0x86, 0x37, 0xc0, 0x3c, 0x28, 0x49, - 0x8e, 0xa5, 0x5f, 0x8c, 0x69, 0x84, 0xc8, 0x7b, 0xcc, 0x2f, 0xea, 0xf5, 0x60, 0xe3, 0x32, 0xe4, 0xe2, 0x15, 0xd1, - 0xe3, 0xd9, 0xe2, 0x5b, 0xe8, 0xc2, 0x70, 0x98, 0x9a, 0x00, 0xfe, 0x1f, 0x65, 0x0f, 0xd4, 0x0f, 0xa1, 0x7c, 0x99, - 0x36, 0xb6, 0x9f, 0x6d, 0x9a, 0x65, 0x46, 0xde, 0x9d, 0x27, 0x6b, 0xb6, 0x91, 0xc4, 0xda, 0x34, 0x6a, 0x13, 0x34, - 0x5a, 0xbd, 0xcd, 0xd9, 0x37, 0x36, 0xa6, 0xd1, 0xd0, 0xf7, 0x68, 0xa6, 0xf4, 0xfa, 0x31, 0x7d, 0x71, 0x7d, 0x87, - 0x98, 0x18, 0xf6, 0x9b, 0xd5, 0x3a, 0x24, 0x36, 0xba, 0xdb, 0x71, 0xc6, 0xfa, 0x1e, 0xd1, 0x7d, 0x93, 0xcb, 0x42, - 0x4e, 0x6e, 0x42, 0xa6, 0x12, 0x75, 0xed, 0xdb, 0x6a, 0xd8, 0xde, 0x03, 0x94, 0x51, 0xb3, 0xd4, 0xc0, 0xe8, 0x8b, - 0xd7, 0xe5, 0x0c, 0xc1, 0x35, 0xb7, 0xde, 0xb8, 0x40, 0x64, 0xf0, 0xd1, 0xb4, 0xcc, 0x65, 0x51, 0x03, 0x27, 0x47, - 0xeb, 0x20, 0xfd, 0xf2, 0x20, 0x1e, 0xa9, 0xfa, 0xe2, 0x6d, 0xcd, 0xc0, 0x8a, 0x96, 0xa8, 0x86, 0x0f, 0x7c, 0xbc, - 0x36, 0xce, 0xcb, 0x8c, 0x5f, 0x4e, 0x8e, 0xd2, 0x0d, 0xe3, 0xca, 0xda, 0xee, 0x62, 0x1c, 0xae, 0xba, 0xad, 0x4a, - 0xa6, 0x64, 0xc6, 0xbe, 0x25, 0x99, 0x9f, 0x49, 0xa5, 0xe7, 0x8d, 0x9a, 0x97, 0xb0, 0xd9, 0xf3, 0x67, 0x3a, 0xc5, - 0x95, 0x49, 0x36, 0x0a, 0xdd, 0xff, 0xd1, 0x8d, 0x58, 0x7a, 0x8f, 0x0e, 0x8c, 0x39, 0xb8, 0x7a, 0x4a, 0xcf, 0x43, - 0x5b, 0x0d, 0xef, 0xe9, 0xfb, 0x34, 0x5f, 0x89, 0xcf, 0x7f, 0xe9, 0x86, 0x8d, 0x45, 0x9d, 0xf4, 0x7e, 0xd5, 0x29, - 0x24, 0x0e, 0x6e, 0x45, 0x3b, 0x21, 0x27, 0xf9, 0x09, 0x41, 0x7d, 0xd9, 0xa0, 0xda, 0x00, 0x6c, 0x58, 0xa5, 0xa2, - 0x2e, 0x06, 0x5a, 0x8e, 0x28, 0x5b, 0x0f, 0xfa, 0xda, 0xb4, 0x3d, 0xdd, 0x5f, 0x35, 0xab, 0x6d, 0xeb, 0x65, 0x09, - 0x53, 0x96, 0x4e, 0xdb, 0x85, 0x3a, 0x6d, 0xc9, 0x33, 0xfd, 0x52, 0x17, 0x73, 0xda, 0xc4, 0xc1, 0xcf, 0x95, 0xbf, - 0x87, 0xdb, 0xda, 0x1d, 0xbb, 0xd6, 0xc8, 0x06, 0xc7, 0xed, 0x31, 0xc7, 0xd9, 0x05, 0x22, 0x5a, 0x16, 0xda, 0x1e, - 0xaa, 0x16, 0xa9, 0x3b, 0xf5, 0x9d, 0x09, 0xbb, 0x09, 0x20, 0x54, 0xec, 0x5d, 0x92, 0x3c, 0x7c, 0x96, 0xd9, 0xe8, - 0xc0, 0x6e, 0xb2, 0x52, 0x9b, 0xf8, 0xfa, 0x94, 0x99, 0x96, 0xa2, 0xab, 0x33, 0x6a, 0xe0, 0xce, 0x69, 0x3e, 0x39, - 0x68, 0x26, 0xca, 0x6d, 0x13, 0xd9, 0xf3, 0x91, 0x3a, 0x41, 0x5d, 0xa0, 0x12, 0x35, 0xad, 0x53, 0xcb, 0x08, 0x0a, - 0x37, 0xc9, 0xde, 0x78, 0xa4, 0x9b, 0xb1, 0x62, 0xfb, 0x15, 0xa8, 0x9b, 0xb3, 0x1b, 0x77, 0x60, 0xc8, 0xaa, 0x15, - 0x6a, 0x67, 0x04, 0xc7, 0xd0, 0x7c, 0x2d, 0x29, 0x12, 0x86, 0x95, 0x80, 0x1d, 0x38, 0x52, 0xa4, 0x20, 0xb8, 0xdb, - 0xea, 0xfc, 0x0d, 0x94, 0x1e, 0x51, 0xa2, 0xc2, 0x2b, 0x2a, 0xa7, 0x74, 0x83, 0x5d, 0x3d, 0x17, 0x20, 0x60, 0x0a, - 0x28, 0x36, 0x32, 0x8b, 0xca, 0x76, 0xab, 0x42, 0xf6, 0x72, 0x3d, 0xb8, 0xbc, 0xf9, 0x40, 0xdd, 0xd8, 0xf4, 0xdd, - 0x97, 0x34, 0xe8, 0x84, 0xe2, 0xc1, 0x07, 0xec, 0xb1, 0x15, 0xf1, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, 0xea, 0x4b, - 0xe4, 0x83, 0x69, 0xff, 0xee, 0x97, 0xc3, 0x2a, 0xe0, 0xea, 0x77, 0xba, 0x91, 0x43, 0xc5, 0xbc, 0x1b, 0x10, 0xa2, - 0x90, 0x01, 0x19, 0xd1, 0xd6, 0x7f, 0xb6, 0xf4, 0xb5, 0x44, 0x3b, 0xda, 0xda, 0x27, 0x01, 0xd9, 0x43, 0x6f, 0xb6, - 0xc1, 0x39, 0x19, 0x2c, 0x00, 0x0c, 0xfe, 0x0b, 0xcd, 0x37, 0x89, 0xa5, 0x84, 0x56, 0x45, 0xf0, 0x71, 0x68, 0x66, - 0x6f, 0xcc, 0xa8, 0xfa, 0x34, 0x03, 0xe8, 0x9e, 0x84, 0x50, 0xe6, 0x6c, 0xaf, 0x37, 0x04, 0x75, 0xec, 0x17, 0x8a, - 0xd5, 0x67, 0x70, 0xc3, 0xff, 0xe8, 0xab, 0x5f, 0xe0, 0x5e, 0x45, 0x51, 0x13, 0xbb, 0xa6, 0x68, 0x1c, 0x4a, 0xb8, - 0xc9, 0x85, 0xf5, 0x2e, 0x09, 0x02, 0x8d, 0xfe, 0x2b, 0x35, 0xc5, 0xc8, 0x02, 0xba, 0xb3, 0x85, 0xc0, 0x5a, 0xc1, - 0x48, 0x4a, 0x44, 0x28, 0x65, 0xae, 0x33, 0x8b, 0xb7, 0xec, 0xea, 0x97, 0xb6, 0xc4, 0xea, 0xcd, 0x3b, 0x06, 0x67, - 0xc5, 0xf2, 0xed, 0x79, 0x27, 0x33, 0x2f, 0xb4, 0x2c, 0x10, 0xd5, 0x14, 0xd2, 0x97, 0xbc, 0x85, 0xd1, 0xca, 0x63, - 0xe3, 0x82, 0x69, 0x7d, 0xff, 0x52, 0xaa, 0x6a, 0xe7, 0x45, 0xa8, 0xab, 0x97, 0xd1, 0xc4, 0xc2, 0xad, 0xa5, 0x0c, - 0xec, 0x4a, 0x44, 0xb0, 0x4d, 0x11, 0xc0, 0xe4, 0x6b, 0x20, 0x44, 0x3c, 0xa8, 0x82, 0x52, 0x3d, 0x61, 0x61, 0xdf, - 0xa0, 0xe0, 0xdd, 0x5d, 0x74, 0x8d, 0x6f, 0x81, 0x88, 0xde, 0x96, 0xc0, 0x30, 0x3c, 0x2e, 0x9e, 0x4a, 0x79, 0x53, - 0x12, 0xb0, 0x5d, 0x85, 0xef, 0x45, 0x94, 0x9b, 0xb5, 0x1f, 0x8d, 0x68, 0xab, 0x0d, 0x12, 0xa5, 0x45, 0xf6, 0x1a, - 0x4f, 0x9b, 0xfc, 0xaa, 0x79, 0x67, 0xf7, 0x36, 0x7d, 0xd5, 0x86, 0x30, 0x3c, 0x45, 0x3a, 0x25, 0x6c, 0xbb, 0x48, - 0xc4, 0xfd, 0x1f, 0x67, 0x8a, 0x16, 0xfb, 0x6c, 0x9c, 0x4b, 0xb5, 0xeb, 0x3b, 0x04, 0x8c, 0x9f, 0xd5, 0x43, 0x77, - 0xfd, 0xa9, 0x1c, 0xeb, 0x6f, 0x46, 0x1d, 0x54, 0xe0, 0xe1, 0x6e, 0x96, 0x7e, 0x8d, 0xc6, 0xf7, 0x5a, 0x7c, 0xd9, - 0xfb, 0x8a, 0x00, 0xbc, 0x78, 0x13, 0xef, 0xa2, 0xfd, 0x44, 0x27, 0x70, 0x8c, 0xb0, 0x6d, 0x93, 0x80, 0xb5, 0x8f, - 0x5f, 0x91, 0x14, 0xe4, 0xc8, 0xef, 0x40, 0xfe, 0xb7, 0xc6, 0xdc, 0xf0, 0x1d, 0x15, 0x73, 0x4b, 0x29, 0x5d, 0x25, - 0x4f, 0x4e, 0x61, 0x7b, 0xcc, 0x02, 0xc4, 0x11, 0x38, 0x78, 0x3f, 0xb1, 0x27, 0x7f, 0xba, 0xa0, 0x6e, 0x46, 0x47, - 0x8a, 0x43, 0xb1, 0x9a, 0x9f, 0x1a, 0x1a, 0x29, 0x0f, 0xd3, 0x11, 0x41, 0x4d, 0x68, 0x31, 0x16, 0x8e, 0x2e, 0x49, - 0x00, 0x81, 0x09, 0x50, 0xa7, 0xc8, 0xa2, 0xaf, 0x47, 0x6e, 0xc5, 0xa4, 0x67, 0x5b, 0xb9, 0x74, 0xed, 0x13, 0xde, - 0xd4, 0x9e, 0x81, 0x5b, 0xab, 0xc6, 0x68, 0x75, 0x67, 0x47, 0x65, 0xa5, 0xc7, 0xe4, 0x74, 0x6e, 0xae, 0xc4, 0x72, - 0x4d, 0x71, 0x1f, 0x8e, 0x76, 0x0f, 0xea, 0x1d, 0x51, 0x04, 0x62, 0x4c, 0x94, 0xd9, 0x99, 0x9c, 0xed, 0x37, 0x7a, - 0x00, 0xdf, 0x52, 0x50, 0x2f, 0x98, 0x0f, 0xb8, 0xdc, 0x5b, 0xde, 0x91, 0x79, 0xe0, 0x95, 0x09, 0x47, 0x4d, 0xb9, - 0xf6, 0x66, 0x23, 0xb3, 0x44, 0x4d, 0x78, 0xfe, 0xbf, 0x1a, 0x6a, 0x48, 0x2c, 0x20, 0x93, 0xb1, 0x6f, 0xdf, 0x55, - 0xe4, 0xd3, 0x2c, 0x74, 0xb8, 0xc2, 0x01, 0xd4, 0x71, 0x6a, 0x6a, 0xc0, 0x0d, 0x78, 0xf8, 0x41, 0x42, 0x2b, 0xdf, - 0x25, 0xd4, 0xf8, 0xe7, 0x7e, 0xc6, 0xbe, 0x77, 0x9b, 0x6d, 0x9e, 0xd3, 0x2b, 0xc0, 0xd2, 0xe8, 0xfe, 0x36, 0xe9, - 0x8b, 0x83, 0x06, 0x0c, 0x55, 0x27, 0xaf, 0x16, 0xd3, 0xc6, 0x76, 0xf3, 0xaf, 0xcf, 0xe4, 0xbc, 0xa3, 0xf7, 0xa5, - 0xe7, 0xb6, 0xb9, 0x1f, 0x77, 0x75, 0x57, 0xb1, 0x6e, 0x5e, 0x34, 0xc4, 0x8a, 0x22, 0x2e, 0x3e, 0xac, 0x77, 0xb7, - 0x73, 0xbb, 0x75, 0x24, 0xc5, 0x3b, 0x05, 0x77, 0x4a, 0x4a, 0x75, 0xcf, 0x8c, 0xa1, 0x27, 0xec, 0xbd, 0x6c, 0xdc, - 0xff, 0x72, 0xe9, 0xac, 0xbb, 0xe2, 0xae, 0x72, 0xf0, 0xc6, 0xa4, 0x8b, 0x16, 0xec, 0xfa, 0x45, 0xaf, 0xdf, 0x7c, - 0xa1, 0x7e, 0x5a, 0xd1, 0x2d, 0x4a, 0x28, 0xa0, 0x0d, 0x2d, 0x5f, 0x10, 0xef, 0x84, 0xca, 0x46, 0x77, 0xc2, 0xc9, - 0xd3, 0xe2, 0xbe, 0xfa, 0x4e, 0xc6, 0xe0, 0x2f, 0x90, 0xaf, 0xe6, 0x51, 0xf0, 0xf1, 0x9f, 0xc4, 0x2f, 0x2f, 0x8b, - 0xfa, 0xcd, 0x8b, 0xd7, 0x5e, 0x0b, 0x80, 0x69, 0x9d, 0x1f, 0xf1, 0xe2, 0x7b, 0x4b, 0xe7, 0x41, 0x92, 0x3f, 0x62, - 0x3c, 0xfb, 0x28, 0x4b, 0x80, 0x04, 0x58, 0xa5, 0x7a, 0x67, 0x16, 0xc4, 0xe3, 0xfb, 0x30, 0x11, 0x39, 0x03, 0x09, - 0x1b, 0x14, 0x0a, 0xc2, 0xf8, 0x4e, 0x23, 0xc2, 0x7b, 0x14, 0x31, 0x15, 0x5e, 0x76, 0x7d, 0xbf, 0x4a, 0x71, 0xb0, - 0x02, 0xa3, 0x76, 0xfb, 0x2f, 0x26, 0x53, 0x60, 0x4f, 0x1c, 0x4c, 0xd4, 0x15, 0x4e, 0x78, 0xfc, 0xe1, 0xe4, 0xfe, - 0x25, 0x3d, 0x52, 0x55, 0x87, 0x39, 0x32, 0xbe, 0xb6, 0xaa, 0xea, 0xc5, 0xaf, 0xd0, 0xb6, 0x2f, 0x67, 0xa9, 0xb5, - 0x74, 0xd9, 0xab, 0x81, 0x6c, 0xed, 0x6c, 0xa2, 0xba, 0x3b, 0x59, 0x1e, 0x97, 0x1b, 0xc2, 0x10, 0x88, 0x75, 0xee, - 0xf2, 0xc8, 0x25, 0xdb, 0xc7, 0xc2, 0xc5, 0x29, 0xdb, 0xfc, 0xec, 0x59, 0xfa, 0xcb, 0x42, 0x79, 0xca, 0xb7, 0xde, - 0xc2, 0xdb, 0xaf, 0x89, 0x1e, 0xf4, 0x77, 0xd3, 0x26, 0xca, 0x01, 0xd1, 0x81, 0x83, 0xc6, 0xf7, 0xa7, 0xf7, 0xff, - 0xa8, 0x19, 0x52, 0x3d, 0x6b, 0x49, 0x2b, 0x07, 0x7f, 0x48, 0x9c, 0x2d, 0xcd, 0x61, 0x2a, 0x11, 0x24, 0xe3, 0xda, - 0xf4, 0x32, 0x59, 0x7b, 0xd3, 0x76, 0x97, 0x1d, 0x90, 0xb5, 0xe4, 0x14, 0x88, 0x1a, 0xb9, 0xd7, 0x35, 0xdf, 0x42, - 0xa8, 0x93, 0x58, 0xa6, 0xb6, 0x7b, 0x8d, 0x3a, 0x83, 0xb5, 0x04, 0xd0, 0x20, 0xe6, 0x35, 0xfe, 0x37, 0x43, 0x33, - 0xfe, 0xf6, 0xcd, 0x93, 0x83, 0x1b, 0x46, 0x82, 0xa9, 0xf8, 0x28, 0x80, 0xe1, 0x8c, 0xe0, 0x49, 0xbd, 0xbe, 0xf6, - 0x25, 0x06, 0xfa, 0xa1, 0xa4, 0xea, 0xc5, 0xde, 0xcd, 0xce, 0x2b, 0x70, 0x51, 0xda, 0x3f, 0x50, 0x7c, 0x43, 0x9a, - 0x91, 0x5a, 0xd9, 0xab, 0x7b, 0xef, 0xd4, 0x76, 0xd2, 0x6b, 0xc9, 0x82, 0xe6, 0xc0, 0x4b, 0x06, 0xb7, 0x24, 0x67, - 0x60, 0x79, 0x7f, 0x2e, 0x3d, 0xd9, 0x19, 0xf8, 0x44, 0xea, 0x97, 0xfa, 0x4a, 0xdc, 0x2c, 0x09, 0x65, 0x2c, 0x24, - 0xd5, 0xfd, 0x0a, 0x44, 0xaf, 0xff, 0xe8, 0x46, 0x85, 0x86, 0xbd, 0x3a, 0xdb, 0x31, 0x90, 0x46, 0x8c, 0xf6, 0x2e, - 0xb5, 0xde, 0xee, 0xe9, 0x91, 0x31, 0x7d, 0xde, 0xfb, 0xb9, 0xea, 0xdc, 0x91, 0xd9, 0x86, 0x54, 0xff, 0x54, 0xcc, - 0x5a, 0x52, 0x21, 0xdb, 0x8a, 0xed, 0xb4, 0x02, 0x77, 0x1e, 0x4c, 0xde, 0x1d, 0x98, 0xbb, 0x0f, 0x64, 0x0e, 0x63, - 0xad, 0x2b, 0x55, 0x95, 0x1b, 0x5f, 0xc4, 0xd0, 0xef, 0x03, 0xc9, 0x2c, 0xb2, 0x48, 0xaa, 0xc0, 0x16, 0x6a, 0x23, - 0xef, 0xdd, 0xcf, 0xc5, 0xaa, 0xd3, 0x2f, 0x4d, 0x82, 0x74, 0xff, 0x46, 0xe4, 0x9a, 0x19, 0x79, 0xf3, 0xbe, 0xda, - 0x46, 0x30, 0xac, 0xa3, 0x8d, 0x48, 0xa1, 0x9d, 0x2f, 0x19, 0xfe, 0x33, 0x92, 0x77, 0x62, 0xa6, 0x7f, 0x90, 0xce, - 0xac, 0x1f, 0x84, 0xf1, 0x76, 0xbf, 0x40, 0x73, 0xfe, 0xa1, 0x80, 0x67, 0x2f, 0x14, 0x60, 0x01, 0x69, 0xf4, 0x4a, - 0xea, 0x63, 0x4d, 0x50, 0x4e, 0xb8, 0x32, 0x94, 0x6c, 0x94, 0xd7, 0x52, 0x7b, 0x42, 0xfb, 0xa6, 0x64, 0x03, 0x6c, - 0xe2, 0x3a, 0x76, 0xd1, 0xd4, 0xb1, 0xc0, 0x74, 0xb9, 0x7f, 0x71, 0x6c, 0x0f, 0x52, 0xb9, 0x70, 0x01, 0x5f, 0xe8, - 0x02, 0x77, 0x61, 0x38, 0x40, 0x6b, 0x50, 0xff, 0x71, 0xdc, 0x14, 0xff, 0x50, 0x4a, 0x25, 0xb1, 0xc9, 0x42, 0xa9, - 0x50, 0x7b, 0x88, 0x9f, 0x1b, 0xe5, 0x5a, 0x4f, 0x82, 0x6b, 0xa4, 0x08, 0x08, 0x8e, 0x2b, 0x26, 0x71, 0x35, 0xa5, - 0x21, 0xb8, 0x73, 0xf4, 0x99, 0xd7, 0xf2, 0x2b, 0xa1, 0xec, 0xba, 0xc0, 0x67, 0x60, 0x05, 0x18, 0xec, 0x2f, 0xec, - 0x0b, 0x47, 0x17, 0x2d, 0x67, 0xeb, 0xb3, 0x03, 0x27, 0x40, 0x1e, 0x2b, 0x4f, 0x24, 0x61, 0x6b, 0x72, 0xee, 0x4d, - 0x6e, 0xdf, 0x33, 0x85, 0x68, 0x52, 0x44, 0xd5, 0xe3, 0x17, 0xb8, 0x20, 0x2d, 0xa9, 0x64, 0xa5, 0xa0, 0x55, 0xa8, - 0x40, 0xb4, 0xd1, 0xc6, 0xd5, 0xaa, 0xd3, 0xfb, 0xa7, 0x11, 0x9d, 0x97, 0xc6, 0xda, 0x10, 0x43, 0xe0, 0x88, 0xb5, - 0xf5, 0x53, 0x85, 0x8d, 0x37, 0xc9, 0xba, 0xb8, 0xcf, 0x63, 0xfb, 0x35, 0x43, 0x33, 0x12, 0x6f, 0x2a, 0x6f, 0x9b, - 0xe2, 0x61, 0xc1, 0x1b, 0x27, 0x7a, 0xa1, 0x5f, 0xb0, 0x39, 0xe1, 0xf4, 0xd7, 0x75, 0x97, 0xc9, 0xb1, 0xfa, 0xd8, - 0x43, 0x48, 0xb9, 0x50, 0xa3, 0x42, 0xa4, 0xe7, 0xed, 0xd8, 0x5c, 0xb9, 0xc7, 0xd2, 0xe8, 0x1c, 0xd7, 0xa4, 0x24, - 0xdb, 0xcd, 0xf0, 0xd2, 0xa6, 0x82, 0x38, 0x71, 0x77, 0x3f, 0xa8, 0x05, 0xef, 0xb6, 0x21, 0xad, 0x69, 0xfd, 0xfa, - 0x95, 0x3f, 0xbf, 0x71, 0x56, 0x52, 0x2c, 0x92, 0x45, 0xd4, 0x6c, 0xd7, 0x4f, 0xec, 0xf2, 0x67, 0xd2, 0xfb, 0x2c, - 0xbc, 0xc9, 0xda, 0xbf, 0x1e, 0xe1, 0x4b, 0xae, 0x4d, 0x29, 0x92, 0x29, 0xca, 0xdd, 0xbf, 0x49, 0x90, 0x10, 0x19, - 0xfe, 0x42, 0x00, 0xc6, 0xba, 0xa7, 0x55, 0xf3, 0xd1, 0x59, 0x89, 0xb3, 0x0f, 0xbc, 0x06, 0xe0, 0xa2, 0xe0, 0x0b, - 0xa3, 0x34, 0x5a, 0xb1, 0x18, 0x1c, 0x07, 0x9a, 0xca, 0x07, 0x5c, 0xff, 0x30, 0xa3, 0x42, 0x29, 0x36, 0xd4, 0xf7, - 0x13, 0xa7, 0x65, 0x42, 0x40, 0x23, 0x9d, 0x39, 0xb7, 0x51, 0x2b, 0xf0, 0xed, 0x71, 0x3d, 0x1c, 0xe4, 0x7a, 0xda, - 0x21, 0xf8, 0x34, 0x4d, 0x7e, 0x73, 0xc8, 0xe6, 0xf2, 0xa5, 0xd9, 0xef, 0xa5, 0x1b, 0x26, 0x2f, 0x36, 0xf4, 0x56, - 0xd8, 0x08, 0x03, 0x51, 0x8d, 0x2a, 0x68, 0x24, 0x24, 0x61, 0xa7, 0xbd, 0x26, 0x38, 0x9a, 0xd2, 0x62, 0x2a, 0xfc, - 0xa4, 0xae, 0x4f, 0xc6, 0xd7, 0xa2, 0x31, 0xb5, 0x8e, 0x1b, 0xf1, 0x71, 0x39, 0x9f, 0x01, 0xc8, 0x42, 0xc5, 0x73, - 0x4b, 0xa2, 0xcf, 0x28, 0x38, 0x1e, 0x54, 0x59, 0x31, 0xd2, 0x0e, 0x43, 0x11, 0x72, 0x63, 0xa6, 0x71, 0x1c, 0x17, - 0xfe, 0x82, 0xd3, 0x2a, 0x8d, 0x31, 0xaa, 0xbc, 0xb6, 0xe9, 0xa5, 0xf9, 0x3a, 0xa1, 0x3a, 0x97, 0xf1, 0xd7, 0x93, - 0xef, 0xb9, 0x92, 0x29, 0x40, 0x1e, 0x69, 0xbc, 0x61, 0xef, 0x78, 0x06, 0xbc, 0x99, 0xc1, 0x25, 0x01, 0x48, 0x27, - 0xeb, 0x74, 0x6e, 0xc3, 0x23, 0xd2, 0x09, 0x38, 0x3b, 0xaa, 0xf4, 0xe4, 0xca, 0x4a, 0x32, 0xd6, 0x1d, 0xc6, 0x7c, - 0xc9, 0xc6, 0xa5, 0x8d, 0xb7, 0x53, 0x66, 0x9d, 0xa5, 0xcb, 0x94, 0x88, 0x07, 0x95, 0xa4, 0xf1, 0x32, 0xc0, 0x61, - 0x9a, 0x97, 0x6f, 0xd3, 0x5a, 0x7e, 0xcf, 0x70, 0x93, 0x21, 0x15, 0x4d, 0x56, 0x69, 0x76, 0x01, 0x20, 0xc0, 0xb6, - 0x5d, 0x74, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x8e, 0xec, 0x1d, 0xb5, 0x3b, 0xb3, 0xc7, 0x41, - 0x80, 0x77, 0x75, 0x4b, 0x76, 0x29, 0x13, 0xdf, 0xc4, 0xd0, 0xf5, 0xab, 0x96, 0x00, 0xb8, 0x01, 0x76, 0x59, 0x12, - 0x75, 0x26, 0x73, 0x81, 0x55, 0x79, 0xcc, 0xc3, 0x54, 0xa6, 0x98, 0xaa, 0x05, 0x5b, 0x82, 0x5c, 0x40, 0xb9, 0xbc, - 0x71, 0xb9, 0xae, 0xaf, 0x02, 0x40, 0xd1, 0xc3, 0x38, 0x2a, 0x26, 0x9e, 0x1b, 0xe9, 0x85, 0xbd, 0xaa, 0x40, 0x61, - 0x7c, 0x6a, 0x4b, 0x72, 0x72, 0x29, 0xfd, 0xc9, 0x64, 0xdb, 0x6a, 0xb6, 0xdb, 0xc9, 0x45, 0x42, 0xd7, 0x92, 0xd8, - 0x42, 0x2e, 0xa9, 0xdb, 0xbb, 0x3a, 0xc4, 0xf2, 0x5e, 0x16, 0x30, 0xda, 0x46, 0x67, 0xdd, 0x55, 0x1f, 0xd6, 0x94, - 0x08, 0x27, 0xcb, 0xc6, 0x7c, 0x27, 0xd6, 0x17, 0xa9, 0x35, 0x06, 0x1a, 0x67, 0xde, 0xfa, 0x25, 0x43, 0xcd, 0x04, - 0x9f, 0x54, 0x2f, 0x96, 0xc5, 0x7c, 0xe6, 0x82, 0xa8, 0xd8, 0x2c, 0xee, 0x5f, 0x6d, 0xba, 0xe0, 0x74, 0x4d, 0xda, - 0x0d, 0xa4, 0x1b, 0x58, 0x34, 0xdc, 0x45, 0x84, 0x45, 0xfb, 0x23, 0x9a, 0x15, 0xcb, 0x0a, 0xa3, 0xc7, 0x4f, 0xe6, - 0xd8, 0x53, 0xc1, 0xb1, 0xb4, 0x40, 0xc2, 0x11, 0xbf, 0x79, 0x8d, 0xd5, 0xa2, 0x6e, 0x65, 0x4c, 0x34, 0x96, 0xa6, - 0xfe, 0x61, 0x21, 0x6d, 0xfb, 0x1a, 0xa8, 0xfe, 0x19, 0x7c, 0x12, 0xdb, 0x19, 0x83, 0xbc, 0xb1, 0x0d, 0x6c, 0xe5, - 0x80, 0x3a, 0x09, 0xa5, 0x27, 0x25, 0xe5, 0x6e, 0x2e, 0x50, 0xaa, 0x34, 0xcd, 0x28, 0xf6, 0xbc, 0x4e, 0x34, 0x5d, - 0xd7, 0x08, 0x27, 0x19, 0x39, 0xd1, 0xe7, 0x8d, 0x82, 0xbc, 0xdd, 0xe6, 0xb2, 0x2f, 0x0d, 0x9c, 0x75, 0xe8, 0x36, - 0x9c, 0xc9, 0x28, 0x69, 0x08, 0x09, 0xda, 0x10, 0x66, 0x6d, 0xb2, 0xd5, 0x22, 0xb4, 0x0d, 0x69, 0x51, 0xf0, 0xc3, - 0xee, 0x1b, 0xcc, 0x23, 0xe8, 0xe9, 0x94, 0xf1, 0x87, 0xd3, 0x6f, 0x2e, 0x1f, 0xee, 0x6c, 0x32, 0x27, 0x02, 0x2d, - 0x3a, 0xcf, 0xa7, 0x87, 0xe2, 0x45, 0x81, 0x20, 0x22, 0x68, 0x0e, 0x6f, 0x09, 0x4e, 0x3e, 0x26, 0xf4, 0x5a, 0xf5, - 0x16, 0x75, 0xf8, 0xc4, 0x83, 0xef, 0xda, 0x3e, 0x21, 0x0e, 0x46, 0x6f, 0xda, 0xf2, 0x28, 0xcd, 0x33, 0x09, 0xf5, - 0xd4, 0x15, 0x03, 0x57, 0x95, 0x8c, 0x1c, 0xbf, 0x59, 0x5f, 0x13, 0x62, 0x45, 0xc0, 0x18, 0x52, 0xbd, 0xc5, 0x18, - 0x1c, 0x32, 0xe6, 0xe5, 0x38, 0x18, 0xd7, 0x6c, 0x8a, 0x2c, 0x6b, 0x43, 0xd9, 0x5d, 0xf9, 0xe9, 0x5c, 0x8c, 0x56, - 0xa1, 0x6c, 0x24, 0x9e, 0xe5, 0x51, 0x8a, 0x71, 0x0f, 0xab, 0x9e, 0x46, 0xc4, 0x96, 0x35, 0x75, 0x3e, 0x21, 0xf4, - 0xd9, 0x83, 0x98, 0xb3, 0x0b, 0x53, 0x16, 0x7a, 0x89, 0xa1, 0x2a, 0xbd, 0x0d, 0x98, 0xbe, 0x15, 0x5b, 0x24, 0xda, - 0x8e, 0x44, 0xa2, 0x98, 0xe0, 0x84, 0x38, 0x6c, 0x45, 0x8e, 0x07, 0xab, 0xbd, 0x83, 0xc9, 0xe8, 0x33, 0x4e, 0x0b, - 0xeb, 0x91, 0x98, 0xfd, 0x31, 0x4e, 0x09, 0x03, 0xce, 0xed, 0x4e, 0x4c, 0x79, 0x37, 0x22, 0x1e, 0x7d, 0x20, 0xd7, - 0x6f, 0xa5, 0x45, 0xb0, 0xc7, 0x13, 0x39, 0x52, 0x15, 0xc5, 0x0a, 0x6e, 0x1f, 0x85, 0x0c, 0x4f, 0x5d, 0x38, 0x9a, - 0xb3, 0x61, 0x3c, 0x10, 0x51, 0x6d, 0x5c, 0xd8, 0xb4, 0x96, 0x81, 0x89, 0xc6, 0x8c, 0xd5, 0xe8, 0xe0, 0x02, 0x5e, - 0xe4, 0xfd, 0xef, 0x0b, 0xa6, 0x69, 0x2d, 0x1f, 0x34, 0x83, 0xfe, 0xbb, 0x32, 0xdb, 0x2c, 0x1f, 0xde, 0xd7, 0xcb, - 0x87, 0xfd, 0x44, 0xce, 0xdc, 0xef, 0xaa, 0xb7, 0x9f, 0xfe, 0x69, 0x21, 0x07, 0xf9, 0xb7, 0xbc, 0x0a, 0x83, 0xab, - 0xad, 0xe3, 0x89, 0x1b, 0x5c, 0x4d, 0x5f, 0x3b, 0xe4, 0xb3, 0x2b, 0x6a, 0xdb, 0x70, 0x91, 0x66, 0x3c, 0xb6, 0x3c, - 0x59, 0x83, 0x15, 0x59, 0x54, 0x2b, 0x58, 0x3b, 0xc9, 0x13, 0xdd, 0xf5, 0xd9, 0x25, 0xb8, 0x27, 0x2f, 0x26, 0x32, - 0x65, 0xf6, 0x01, 0xf8, 0x50, 0x22, 0x7f, 0x62, 0xb7, 0xf0, 0xdf, 0x51, 0x05, 0xdd, 0x41, 0xc1, 0x50, 0x6b, 0x49, - 0xd8, 0xe6, 0x0b, 0x25, 0xbf, 0x96, 0x08, 0x7c, 0x51, 0xbd, 0x85, 0x75, 0x43, 0xca, 0x9f, 0x58, 0x6e, 0x4f, 0xa9, - 0x13, 0x4d, 0xa3, 0x3b, 0x79, 0x1a, 0x7e, 0xe9, 0x92, 0xe0, 0xb2, 0x4d, 0xfd, 0xbf, 0xbe, 0xff, 0xaf, 0xd7, 0x09, - 0x26, 0x21, 0xef, 0x20, 0x1e, 0x2e, 0x5f, 0x0c, 0xae, 0x3a, 0xd2, 0xf9, 0x66, 0x1f, 0xbe, 0x89, 0x86, 0xe5, 0x61, - 0xfd, 0xbc, 0xf7, 0x17, 0x5d, 0x7e, 0x6f, 0xa2, 0xef, 0x60, 0xdb, 0xb4, 0xa1, 0xb4, 0x3d, 0xa4, 0x01, 0x4b, 0x8d, - 0x0b, 0x9a, 0x55, 0xf1, 0xd8, 0x14, 0x16, 0xab, 0x7b, 0x7b, 0x4d, 0x9e, 0x72, 0x6c, 0xfd, 0x87, 0xa0, 0x83, 0xcc, - 0xf1, 0x68, 0xb8, 0x2c, 0xcf, 0xd2, 0x2c, 0xd6, 0x31, 0xe8, 0xee, 0x9d, 0x50, 0x7b, 0xb1, 0x18, 0x5a, 0x1b, 0xb5, - 0x45, 0x92, 0x48, 0xe3, 0x5d, 0x5d, 0x6c, 0xea, 0x21, 0x74, 0x69, 0xeb, 0x34, 0x6d, 0x12, 0xc7, 0x38, 0xd9, 0x96, - 0xbd, 0x06, 0xe8, 0x95, 0xbe, 0xe8, 0x2f, 0x58, 0x7a, 0x6d, 0xbf, 0xd6, 0x47, 0x8c, 0x9b, 0x0d, 0xbc, 0x3f, 0x3a, - 0x65, 0xe2, 0xe2, 0xd0, 0xd8, 0xf9, 0x16, 0x27, 0x0e, 0x7b, 0x7e, 0x8d, 0x4b, 0xaa, 0xa9, 0x97, 0x48, 0x1b, 0xc6, - 0x6a, 0x70, 0x62, 0xe9, 0x5f, 0xdb, 0x58, 0x3c, 0x48, 0x8e, 0x48, 0x65, 0x27, 0x33, 0xf5, 0x72, 0xb4, 0xf0, 0xb7, - 0xae, 0xd6, 0xf5, 0x87, 0xf8, 0xe6, 0x1f, 0x88, 0x9d, 0xa8, 0x9d, 0x5e, 0x34, 0x8a, 0x0c, 0x21, 0xd3, 0x53, 0xfc, - 0x8b, 0x5b, 0x28, 0xc3, 0x69, 0xa2, 0xb3, 0x51, 0xee, 0xed, 0x9d, 0x23, 0x3f, 0x24, 0xbc, 0x71, 0xe7, 0x72, 0x59, - 0x61, 0x60, 0xda, 0x01, 0x36, 0x50, 0x41, 0xc6, 0x81, 0xa5, 0xf8, 0x09, 0x66, 0x97, 0x21, 0xca, 0x6e, 0x99, 0x11, - 0x2f, 0x6d, 0xa7, 0xd2, 0x18, 0xb2, 0xf3, 0x22, 0x77, 0xf1, 0x98, 0x38, 0x36, 0x52, 0x1b, 0x9f, 0x14, 0x10, 0x8e, - 0xf5, 0x61, 0xc8, 0xa6, 0xdb, 0x29, 0x79, 0x6a, 0x39, 0x05, 0x9a, 0x47, 0x7e, 0x8f, 0x88, 0x8e, 0xc6, 0xd6, 0x69, - 0x50, 0x7b, 0x16, 0x1f, 0x2d, 0x17, 0xbe, 0x10, 0x2d, 0xef, 0x02, 0x5b, 0x33, 0xe4, 0x05, 0xab, 0xf7, 0x29, 0x10, - 0xe4, 0x36, 0x6c, 0x7f, 0xcf, 0x97, 0xee, 0xef, 0xac, 0x61, 0x88, 0x79, 0xd0, 0x64, 0xcc, 0xd7, 0x1c, 0x56, 0x84, - 0x4d, 0x59, 0xaf, 0x84, 0x7d, 0x1d, 0x9c, 0xba, 0x1e, 0x4e, 0x52, 0xe9, 0xb9, 0x1a, 0xcd, 0xbb, 0x74, 0xa4, 0x34, - 0x65, 0x8a, 0x36, 0xa6, 0x77, 0x7d, 0x4e, 0x36, 0x47, 0x57, 0x74, 0x3c, 0xeb, 0xa0, 0x14, 0x1e, 0x3e, 0xb5, 0xc1, - 0xa9, 0x7b, 0x46, 0x2f, 0xe4, 0xd7, 0x20, 0xbd, 0xa6, 0x45, 0x15, 0xf4, 0x69, 0xf5, 0x83, 0x17, 0x1f, 0xbf, 0x5b, - 0x25, 0xd0, 0xd8, 0xec, 0x93, 0x0d, 0xc1, 0x59, 0x1e, 0x80, 0x1f, 0x16, 0xf8, 0xff, 0x80, 0x3e, 0x20, 0x66, 0x73, - 0xd3, 0xfe, 0x30, 0x87, 0xf2, 0x4d, 0xf3, 0xf5, 0x42, 0x98, 0x16, 0x9d, 0x1f, 0x7c, 0xa8, 0x1b, 0x04, 0xd8, 0x64, - 0xcf, 0xff, 0x2b, 0xc8, 0x01, 0x82, 0x09, 0xe7, 0xef, 0xe3, 0x7a, 0x38, 0xbf, 0xd1, 0xcf, 0x11, 0x99, 0x3b, 0xdc, - 0xcc, 0xde, 0x4d, 0xbb, 0xf4, 0xaa, 0x2c, 0x36, 0x92, 0xd7, 0xc2, 0xa5, 0x8d, 0xcb, 0x69, 0x1b, 0xd1, 0x92, 0x2d, - 0x12, 0x2c, 0x7c, 0x4b, 0x00, 0x70, 0xa4, 0x7b, 0xa8, 0x6d, 0xf3, 0xbf, 0x28, 0xb6, 0x18, 0x2b, 0xb8, 0x9d, 0xd6, - 0xae, 0xae, 0xfd, 0xd0, 0x76, 0x9b, 0x65, 0x0c, 0x30, 0x7a, 0xb0, 0x33, 0x57, 0x19, 0x65, 0xb9, 0x43, 0x9c, 0x3d, - 0x5c, 0x19, 0xb5, 0xcb, 0x98, 0x70, 0x54, 0xeb, 0x66, 0xb5, 0xa7, 0x02, 0x02, 0x35, 0x62, 0xb1, 0x83, 0xae, 0xcc, - 0x8a, 0x48, 0x3a, 0x7b, 0x6f, 0xc6, 0xf0, 0x6e, 0x83, 0xc5, 0x65, 0xcc, 0x88, 0xe4, 0x8d, 0x81, 0x36, 0xb7, 0xe2, - 0xb1, 0x77, 0x7a, 0xf3, 0xe0, 0xfe, 0xf6, 0xe6, 0xf2, 0xe6, 0x76, 0x89, 0xb7, 0x89, 0x2e, 0xd5, 0x1a, 0x99, 0x53, - 0x7b, 0xbe, 0x96, 0x8c, 0x76, 0xc8, 0xf7, 0xb6, 0xd5, 0xba, 0x84, 0x16, 0x49, 0x80, 0x48, 0x2b, 0x24, 0xab, 0xea, - 0x94, 0x01, 0x0e, 0x9d, 0xa6, 0x61, 0xdb, 0xe3, 0x5e, 0x52, 0x28, 0xd8, 0xca, 0x84, 0xa3, 0x3c, 0x3b, 0xf5, 0x54, - 0x23, 0x73, 0xf6, 0x4c, 0x70, 0x5d, 0x2c, 0x24, 0x22, 0xcf, 0xd7, 0x9c, 0x2c, 0x1e, 0x01, 0xcc, 0x9c, 0xdf, 0x4f, - 0xf3, 0x14, 0x97, 0x38, 0x6c, 0xaa, 0x51, 0x46, 0x5f, 0x6f, 0x09, 0xa1, 0xa1, 0x78, 0x39, 0x14, 0xf8, 0x7a, 0xc2, - 0xf5, 0x5d, 0xa4, 0x23, 0x78, 0x42, 0xc7, 0x49, 0xf2, 0x4b, 0x43, 0x66, 0xdf, 0x6f, 0x9a, 0xc9, 0x36, 0xea, 0x8a, - 0xbe, 0x6e, 0xc9, 0x5f, 0x4f, 0xc6, 0x69, 0x6d, 0x70, 0xe9, 0xf8, 0x6f, 0xa0, 0x7b, 0x41, 0x8c, 0x83, 0x85, 0x33, - 0x88, 0xa3, 0xf0, 0x2b, 0xb6, 0x20, 0x2f, 0x3a, 0xef, 0xf9, 0x73, 0x02, 0x70, 0xb9, 0x5b, 0x06, 0x17, 0x26, 0x96, - 0x79, 0xac, 0xcb, 0x18, 0xd9, 0xc9, 0x42, 0x4e, 0x8d, 0xda, 0x57, 0x44, 0xdb, 0x9a, 0x09, 0xec, 0x47, 0x7c, 0x79, - 0x9c, 0x4a, 0x5c, 0x9b, 0x31, 0x8b, 0x8d, 0x18, 0xbc, 0xa9, 0x3c, 0x28, 0x36, 0x98, 0x85, 0xe7, 0xfb, 0xd6, 0x10, - 0x52, 0x6b, 0xd2, 0x61, 0xb0, 0x53, 0x5e, 0xc4, 0x36, 0x70, 0xca, 0x2e, 0x6e, 0xc7, 0x5a, 0x8c, 0x5f, 0xd7, 0x78, - 0xc5, 0x58, 0x47, 0x2d, 0x38, 0xce, 0x7b, 0xcb, 0x61, 0x9b, 0x60, 0x40, 0xff, 0xb1, 0x13, 0x34, 0xf3, 0xca, 0x9d, - 0x6c, 0x1d, 0x10, 0xe4, 0x6c, 0xc8, 0x12, 0x41, 0x0d, 0xbf, 0x26, 0x9b, 0x36, 0x96, 0x17, 0x9d, 0xe3, 0xfb, 0x8c, - 0x69, 0x47, 0xfb, 0x2c, 0x72, 0x11, 0x25, 0xe3, 0x57, 0x12, 0xa4, 0x73, 0x65, 0x37, 0x72, 0x77, 0x23, 0xf2, 0xa0, - 0x4d, 0x49, 0xe8, 0xad, 0x3d, 0x03, 0x37, 0x3c, 0x37, 0x5f, 0xa9, 0x9a, 0xa3, 0x2c, 0x26, 0x02, 0x83, 0x22, 0x8c, - 0x84, 0xf5, 0x57, 0xff, 0x2b, 0x70, 0x50, 0x77, 0x7c, 0x67, 0xbd, 0xa0, 0xe9, 0x01, 0xbb, 0x1b, 0x75, 0x1d, 0x4a, - 0xab, 0x04, 0x05, 0x11, 0x32, 0x17, 0x86, 0x49, 0xdc, 0xbf, 0xef, 0xde, 0xdd, 0xfd, 0xfe, 0x58, 0x94, 0x5d, 0xdd, - 0x2d, 0xf6, 0x63, 0x4b, 0x3e, 0x9b, 0xb1, 0x91, 0xf9, 0x6a, 0xf0, 0x81, 0x8e, 0x49, 0xb7, 0x40, 0xfe, 0x21, 0xb3, - 0xe7, 0x61, 0x9b, 0x41, 0x23, 0xd1, 0xb5, 0x43, 0x32, 0x20, 0x07, 0x3a, 0xe4, 0x93, 0x0d, 0x3c, 0x97, 0x47, 0xdb, - 0xbc, 0xbb, 0xbc, 0xfe, 0x73, 0xb9, 0xf7, 0xa1, 0x2b, 0xea, 0x83, 0xc5, 0x9a, 0x59, 0xfe, 0xce, 0xc9, 0x22, 0x3b, - 0x70, 0xdb, 0xcd, 0x97, 0xe1, 0x14, 0xaf, 0x66, 0xcb, 0x7f, 0xf0, 0xff, 0xdb, 0xe9, 0xc2, 0x9b, 0x3d, 0xe9, 0x44, - 0xe3, 0x98, 0xe3, 0x96, 0xf7, 0xec, 0x4c, 0xbf, 0x6b, 0x33, 0x13, 0xd2, 0x83, 0x51, 0x34, 0xdb, 0x25, 0x9d, 0xc0, - 0xa8, 0x2e, 0x79, 0xb8, 0xb1, 0x4d, 0x29, 0x53, 0x26, 0x33, 0xd2, 0x42, 0x25, 0x73, 0x2b, 0xd4, 0xb9, 0xa0, 0x48, - 0xf3, 0x85, 0x01, 0x12, 0x75, 0x9b, 0xd3, 0xda, 0x95, 0x38, 0xcd, 0xfb, 0xe6, 0xd8, 0xce, 0xc8, 0x16, 0x25, 0xa0, - 0x4d, 0x99, 0x13, 0x9a, 0x4f, 0x9a, 0x42, 0xdd, 0xdd, 0xce, 0x74, 0x46, 0x6f, 0x93, 0x56, 0x75, 0xda, 0xd7, 0x77, - 0xfd, 0x67, 0x6b, 0xe4, 0x3d, 0x4d, 0x5a, 0xdb, 0x82, 0x74, 0x46, 0x72, 0x6a, 0x3a, 0x9f, 0x06, 0xca, 0xd0, 0x16, - 0x1e, 0x67, 0xbe, 0xf5, 0x22, 0x60, 0x4d, 0x96, 0xcc, 0xa6, 0xe8, 0x6d, 0xa9, 0xa8, 0x5b, 0xec, 0xd9, 0xbd, 0x93, - 0xc9, 0xda, 0xde, 0x1e, 0x10, 0x99, 0x62, 0x58, 0x7b, 0x44, 0xd8, 0x2e, 0xa2, 0x77, 0x00, 0xc7, 0x7d, 0xd2, 0x73, - 0xf8, 0xd4, 0xc8, 0xd7, 0x45, 0xf0, 0xa8, 0x94, 0x36, 0x3f, 0x38, 0x7b, 0xd1, 0x1d, 0x1b, 0x8c, 0x97, 0x0e, 0xb7, - 0xa0, 0xe6, 0xba, 0x6c, 0xba, 0xc6, 0xdd, 0xfd, 0xdf, 0xfe, 0xb6, 0xb5, 0xf0, 0x07, 0x8e, 0x0f, 0x32, 0xbb, 0xa1, - 0xbb, 0xb7, 0xfc, 0xa2, 0x8b, 0xb9, 0xf8, 0xb2, 0x9f, 0x66, 0x67, 0x46, 0xb9, 0x29, 0xc8, 0x4e, 0x45, 0xda, 0x63, - 0x12, 0x15, 0x03, 0xd8, 0xd3, 0x4c, 0x96, 0x64, 0x40, 0x0d, 0xab, 0x57, 0xdf, 0xd2, 0xa9, 0x3b, 0x35, 0x67, 0x6a, - 0xcf, 0x34, 0xf6, 0xb9, 0xf0, 0x88, 0xdd, 0x17, 0x6b, 0xd7, 0x69, 0x6b, 0x98, 0x82, 0xd3, 0x8d, 0x2f, 0xfe, 0xf8, - 0xcb, 0x86, 0x40, 0x8d, 0x51, 0xae, 0xf9, 0xaf, 0xb5, 0x03, 0x08, 0xde, 0xdf, 0x45, 0x98, 0x0b, 0xc8, 0xac, 0xba, - 0x7a, 0xaa, 0xf7, 0x23, 0xdb, 0xcd, 0x43, 0x11, 0x3b, 0x67, 0xbb, 0x17, 0x4f, 0x01, 0x14, 0x99, 0x25, 0x85, 0x9c, - 0xab, 0x36, 0xf4, 0xd2, 0x78, 0x97, 0x1e, 0xf6, 0xd3, 0x27, 0x98, 0x93, 0x43, 0x98, 0x3b, 0x08, 0x9a, 0xcd, 0x20, - 0x81, 0x14, 0xb9, 0x20, 0x66, 0x3f, 0x07, 0x47, 0x58, 0x23, 0x95, 0xc1, 0x34, 0x32, 0x46, 0xbb, 0xe7, 0xca, 0x58, - 0x30, 0x4f, 0x7b, 0x5f, 0xe9, 0xe2, 0xae, 0x77, 0xa0, 0x3a, 0x7b, 0x48, 0xca, 0xcd, 0xfa, 0x02, 0x23, 0xa0, 0xd3, - 0x83, 0x56, 0x3f, 0xfd, 0x39, 0x85, 0x6b, 0xd8, 0x2b, 0xbb, 0x8d, 0x95, 0xe8, 0x0e, 0x20, 0x07, 0xe2, 0x12, 0x4e, - 0x59, 0x7b, 0x9e, 0xfa, 0x77, 0xbf, 0xfe, 0x1e, 0xf9, 0x8b, 0xf3, 0x72, 0xe5, 0x87, 0x95, 0x6f, 0x6d, 0x61, 0x0b, - 0x94, 0x5e, 0xe3, 0xde, 0x2e, 0x31, 0x8d, 0x63, 0x69, 0xfa, 0x96, 0xf3, 0x89, 0x5e, 0xe1, 0x89, 0x0d, 0x54, 0x22, - 0x3c, 0xe2, 0x4a, 0x79, 0x68, 0xa3, 0xd9, 0xec, 0xfa, 0x6e, 0xee, 0x02, 0xd7, 0xff, 0xc2, 0x17, 0xd6, 0xfa, 0xed, - 0x7b, 0x1c, 0x26, 0x23, 0x82, 0x37, 0xfa, 0xa3, 0x30, 0x31, 0x42, 0xc9, 0xd9, 0xc9, 0xb0, 0xff, 0x30, 0x3a, 0x7a, - 0xe8, 0x3c, 0xfa, 0x19, 0x13, 0xa5, 0x66, 0x7c, 0xe7, 0x0f, 0x73, 0x39, 0x93, 0xe7, 0x52, 0xb1, 0x40, 0x6b, 0x12, - 0x01, 0x51, 0x31, 0x2a, 0x3a, 0x4c, 0x4e, 0xe3, 0x37, 0x94, 0xe7, 0x0d, 0x0b, 0xe2, 0x22, 0x08, 0x8a, 0x2f, 0x50, - 0xf6, 0x67, 0xd7, 0x0f, 0x5c, 0xdd, 0xb0, 0x63, 0x30, 0x43, 0x3d, 0xd1, 0xd0, 0x6a, 0x42, 0x90, 0xb1, 0xb5, 0x52, - 0x05, 0x01, 0x4a, 0x47, 0x42, 0x8a, 0x41, 0xcd, 0xac, 0xe5, 0x31, 0xe9, 0xaf, 0x5b, 0x06, 0xef, 0x8d, 0x8a, 0xe3, - 0x32, 0x5a, 0xb7, 0x6d, 0xd5, 0x70, 0x6d, 0xca, 0x38, 0x7a, 0x01, 0xa6, 0xc3, 0xce, 0x49, 0x06, 0x1a, 0x46, 0xfc, - 0xaf, 0x81, 0xe1, 0x42, 0x56, 0x9b, 0x6e, 0x17, 0x87, 0x76, 0xed, 0xc6, 0x7c, 0x22, 0xd8, 0x5f, 0x36, 0x4c, 0x23, - 0xcf, 0x7b, 0xfc, 0x32, 0xd8, 0x12, 0xef, 0x59, 0xf8, 0x69, 0x1f, 0x94, 0x9d, 0xaf, 0xc1, 0xca, 0xf8, 0xd9, 0x7c, - 0xbe, 0xfb, 0x72, 0xf5, 0x1d, 0x86, 0x34, 0x17, 0x05, 0x62, 0xcd, 0xeb, 0xe7, 0xf8, 0x54, 0xba, 0x1c, 0x27, 0xc2, - 0xfa, 0x44, 0x34, 0x6e, 0xd6, 0x95, 0x0b, 0x3f, 0xf2, 0xb6, 0xc2, 0x7d, 0xfd, 0x06, 0x3b, 0x28, 0x9f, 0x7c, 0xbf, - 0x1b, 0x0b, 0xc1, 0xd3, 0xa6, 0x24, 0xe4, 0x39, 0xd0, 0x5b, 0xb7, 0x5b, 0x45, 0x4b, 0xbf, 0x96, 0x87, 0x66, 0x99, - 0x87, 0xf3, 0xc9, 0x98, 0x80, 0x88, 0xe0, 0x40, 0xce, 0x42, 0xd1, 0xf4, 0x22, 0x4c, 0xba, 0x08, 0x3e, 0x35, 0x72, - 0x8e, 0x38, 0x9c, 0xc6, 0xfd, 0xae, 0x30, 0xfd, 0x4d, 0x9e, 0x74, 0x19, 0xfb, 0xe9, 0xef, 0xdb, 0x75, 0x11, 0xd2, - 0xef, 0x79, 0x36, 0xfb, 0x2f, 0x34, 0x42, 0xfe, 0x36, 0x8a, 0x8d, 0xc7, 0x28, 0x6f, 0x14, 0x95, 0x08, 0x11, 0xed, - 0x92, 0x48, 0x98, 0xcb, 0xfb, 0x55, 0xc2, 0xc7, 0xaf, 0xe8, 0x85, 0x33, 0xc7, 0x40, 0xa3, 0x8b, 0x1e, 0x4f, 0xd8, - 0xd8, 0xfd, 0x79, 0x1a, 0x63, 0x81, 0x35, 0xc3, 0x9f, 0x05, 0x80, 0x74, 0xda, 0xad, 0x00, 0xd1, 0x86, 0x26, 0xc8, - 0x70, 0x5d, 0xe7, 0x1a, 0xd6, 0x33, 0x87, 0xe0, 0xf3, 0x46, 0xc8, 0x0d, 0xf1, 0x1c, 0x82, 0x82, 0x7b, 0x70, 0x60, - 0x89, 0xe2, 0x9f, 0x59, 0x47, 0x3d, 0x77, 0x98, 0x58, 0xd2, 0x21, 0x0d, 0x89, 0x84, 0x2c, 0xd7, 0xdd, 0xab, 0x51, - 0x01, 0x3e, 0x66, 0xb2, 0x16, 0x54, 0x3c, 0x9b, 0x4d, 0x7e, 0x35, 0xbf, 0x13, 0xa5, 0xd7, 0xd1, 0x91, 0x36, 0x79, - 0x37, 0x58, 0x82, 0xce, 0xdf, 0x19, 0x05, 0x40, 0x2f, 0x55, 0x5a, 0x05, 0x66, 0x42, 0xd8, 0xc4, 0x86, 0xef, 0x18, - 0x26, 0xa3, 0xcd, 0x9c, 0xdf, 0x64, 0x36, 0x0b, 0x13, 0xc8, 0x60, 0x68, 0x15, 0x40, 0x96, 0xed, 0x11, 0xee, 0x52, - 0xda, 0x07, 0xd4, 0xbb, 0xb8, 0xec, 0x73, 0xf4, 0x39, 0x8d, 0x24, 0xec, 0x5e, 0xaa, 0x31, 0x41, 0x5c, 0x45, 0x4b, - 0xcc, 0xb1, 0xb5, 0xe4, 0xd0, 0x42, 0xf4, 0x8e, 0xd0, 0x61, 0x77, 0x97, 0x19, 0x6c, 0x95, 0xd8, 0x7f, 0x78, 0xac, - 0x64, 0x0e, 0x9e, 0xa5, 0x67, 0xc2, 0xd6, 0x88, 0x1d, 0x27, 0x0d, 0x17, 0x24, 0x88, 0x58, 0x08, 0x4f, 0xe7, 0x03, - 0x71, 0x46, 0xb5, 0x88, 0xff, 0xa3, 0xe3, 0x04, 0xfa, 0x4a, 0xa2, 0x88, 0xec, 0x46, 0xa7, 0xfd, 0x1c, 0x0a, 0x18, - 0x89, 0x23, 0x18, 0x85, 0x9f, 0xa1, 0xa4, 0xbb, 0x4c, 0x18, 0xa0, 0x5c, 0x48, 0xec, 0xf0, 0x84, 0x94, 0x98, 0x12, - 0x6a, 0xa4, 0x07, 0x09, 0xc9, 0xcb, 0x22, 0x00, 0x75, 0x08, 0xda, 0xa1, 0xf9, 0x2b, 0x43, 0x03, 0x0f, 0x2e, 0x5f, - 0xa1, 0x24, 0x32, 0x39, 0x8f, 0x51, 0x48, 0x72, 0xeb, 0xbc, 0xcb, 0x96, 0xb4, 0xb0, 0xbf, 0xd5, 0x28, 0xaa, 0x22, - 0x59, 0xdd, 0xcb, 0x1a, 0xe1, 0xd9, 0x9a, 0x49, 0xb0, 0x3e, 0xb9, 0x8e, 0xb5, 0x90, 0x93, 0x09, 0x4c, 0x8b, 0xf6, - 0x6f, 0xab, 0xe4, 0x22, 0xff, 0x4a, 0xcf, 0xe6, 0x85, 0xdf, 0x85, 0xae, 0x7a, 0xa9, 0x3f, 0x93, 0x76, 0xd0, 0x99, - 0x05, 0x47, 0x6a, 0x99, 0x8d, 0x3b, 0xe3, 0xf3, 0xa2, 0x1b, 0xd6, 0x5f, 0x26, 0x55, 0x12, 0xbd, 0xf0, 0x6b, 0x68, - 0x56, 0x61, 0x41, 0xf9, 0x0c, 0x62, 0x5e, 0x23, 0x9a, 0x8d, 0x36, 0x8c, 0x14, 0xe0, 0xc5, 0xe7, 0xe5, 0x39, 0x77, - 0xa0, 0x32, 0x2a, 0xcc, 0xe2, 0x52, 0x49, 0xf0, 0xbd, 0x70, 0xec, 0xd0, 0x3e, 0xd3, 0xa6, 0xc8, 0xde, 0x97, 0x40, - 0x27, 0x8f, 0x68, 0x03, 0x06, 0xee, 0x10, 0x6a, 0x52, 0xa0, 0xb3, 0x71, 0xb8, 0x45, 0xed, 0x2b, 0x33, 0xba, 0x2a, - 0x45, 0xd1, 0x3c, 0xcd, 0x18, 0xa4, 0xba, 0x55, 0x0b, 0x19, 0x19, 0xed, 0xa0, 0xcb, 0xe8, 0xa0, 0x84, 0x8f, 0xe5, - 0xac, 0xf0, 0x78, 0xc8, 0x70, 0x61, 0x92, 0x6c, 0x80, 0x4f, 0x8f, 0xfe, 0xef, 0x0f, 0xce, 0xa9, 0xa5, 0xe3, 0x91, - 0xbc, 0x62, 0x76, 0xc4, 0xd2, 0x4c, 0x41, 0xea, 0x72, 0x92, 0x22, 0x75, 0x8b, 0xa9, 0x65, 0x71, 0xb0, 0x1c, 0x55, - 0x44, 0x9d, 0xde, 0x9e, 0x0a, 0x0a, 0x07, 0x06, 0x2d, 0x8c, 0x34, 0x31, 0xdf, 0x2c, 0x59, 0x7b, 0xa5, 0xe8, 0xde, - 0xc9, 0x08, 0x55, 0xaa, 0x1b, 0x5e, 0xb9, 0x6c, 0xf0, 0xda, 0xdc, 0x7f, 0x90, 0xbf, 0x8b, 0x25, 0xb7, 0x72, 0x0c, - 0x66, 0x23, 0xcc, 0x89, 0xe8, 0xcd, 0x6b, 0x25, 0xe3, 0x6d, 0x5f, 0xcb, 0x70, 0x40, 0xe9, 0x58, 0x9a, 0xa5, 0xab, - 0x66, 0xe7, 0x9a, 0x5f, 0x42, 0x2e, 0xd8, 0x81, 0x98, 0x74, 0x66, 0xad, 0x16, 0xe6, 0xd7, 0x5e, 0x79, 0xe6, 0x48, - 0xcf, 0x49, 0xd0, 0x70, 0xbb, 0xc8, 0x5a, 0x83, 0x58, 0x6f, 0x99, 0xd3, 0x61, 0x4b, 0x5e, 0xbb, 0xb0, 0x29, 0x86, - 0xe1, 0xf8, 0xcc, 0xec, 0x13, 0xcc, 0xf6, 0x4c, 0xb4, 0xc7, 0xfe, 0x67, 0x36, 0x0b, 0x6d, 0x1a, 0x12, 0xae, 0xb8, - 0xf2, 0x41, 0x8a, 0xab, 0x89, 0x3c, 0x9c, 0xc7, 0x8c, 0xde, 0x5c, 0x71, 0x1d, 0x73, 0x7b, 0xb2, 0x17, 0x84, 0x99, - 0x03, 0xfb, 0x6e, 0xfc, 0x30, 0xaa, 0x12, 0x67, 0x52, 0x96, 0x2d, 0xc5, 0x52, 0x0c, 0xf2, 0xbc, 0x0e, 0x71, 0x28, - 0x95, 0x0b, 0x62, 0x57, 0x24, 0xb2, 0xed, 0x59, 0xb2, 0x78, 0xef, 0xfa, 0x69, 0x05, 0xd5, 0x4b, 0x7c, 0x24, 0xbb, - 0x3d, 0x13, 0xda, 0x72, 0x0b, 0xb2, 0x83, 0xae, 0x83, 0x3b, 0xd2, 0xa4, 0x04, 0x6f, 0x8a, 0x32, 0xfa, 0x4b, 0x1d, - 0x29, 0x15, 0x2d, 0xe6, 0x82, 0x99, 0x89, 0x14, 0xb3, 0xb5, 0x4d, 0x42, 0x80, 0x34, 0x49, 0x7b, 0x89, 0x2c, 0x6a, - 0x9e, 0x03, 0x86, 0x6d, 0x61, 0xc8, 0x3d, 0x5f, 0x02, 0x8c, 0xfa, 0x3e, 0x0f, 0x27, 0x73, 0x84, 0x4d, 0xa2, 0xe4, - 0xef, 0xb5, 0xb6, 0x5d, 0xc3, 0xd6, 0xd1, 0x3f, 0x34, 0x84, 0xaf, 0xa6, 0xb2, 0x86, 0x25, 0xcc, 0xaa, 0x10, 0xde, - 0x2a, 0x0d, 0x50, 0xa4, 0x2c, 0xeb, 0xc3, 0x92, 0x80, 0x09, 0x93, 0x82, 0x76, 0x88, 0xe5, 0x2a, 0x8d, 0xd9, 0x69, - 0x11, 0x5b, 0x73, 0x2f, 0x5b, 0x1c, 0x7f, 0xf5, 0xfb, 0x17, 0x47, 0xa4, 0x72, 0x3b, 0x7f, 0xed, 0x20, 0x3b, 0x60, - 0x64, 0xa1, 0x3f, 0x5b, 0x76, 0x74, 0xee, 0xbf, 0x9e, 0xe2, 0x77, 0x09, 0xfc, 0x3d, 0x72, 0x1c, 0x88, 0x87, 0xdc, - 0xb5, 0x9e, 0x0d, 0x54, 0xf7, 0xb8, 0xac, 0xee, 0x7b, 0xe5, 0x1c, 0xa9, 0x70, 0x12, 0x22, 0xdd, 0xe5, 0xb0, 0x04, - 0xab, 0xf7, 0xd7, 0x90, 0x6c, 0x0a, 0xa6, 0x89, 0xc2, 0x46, 0x59, 0xf3, 0xd5, 0x61, 0xb8, 0xd8, 0x60, 0x05, 0x97, - 0x70, 0x30, 0xf4, 0xda, 0x9b, 0x39, 0xbd, 0xd5, 0xec, 0x8e, 0x41, 0x13, 0xd9, 0x74, 0x77, 0x90, 0x8a, 0xed, 0x0d, - 0x09, 0x4f, 0xff, 0x73, 0x23, 0x07, 0x04, 0xc0, 0xd2, 0xac, 0x90, 0x64, 0xf0, 0x55, 0xce, 0x49, 0x26, 0x53, 0x4b, - 0xcd, 0x6e, 0x2b, 0x05, 0x92, 0xbd, 0xf0, 0xdf, 0xa2, 0xba, 0x19, 0xed, 0xa7, 0xe4, 0x0e, 0xfa, 0x26, 0x3b, 0x34, - 0xf0, 0xc6, 0x9c, 0xf6, 0xde, 0xd0, 0xc4, 0xe2, 0x2b, 0x80, 0x88, 0xc3, 0x01, 0x99, 0x78, 0xc6, 0xc2, 0x12, 0x90, - 0x4e, 0xf5, 0x30, 0x88, 0x09, 0x57, 0x91, 0x16, 0x9c, 0x99, 0x7c, 0xf7, 0x0e, 0x53, 0xe4, 0xd3, 0x3e, 0x83, 0xc6, - 0xec, 0xa0, 0x3a, 0x5d, 0x7b, 0x45, 0x87, 0x7e, 0x9d, 0x39, 0x4b, 0x24, 0x3d, 0xe9, 0xcb, 0x8d, 0x63, 0x99, 0x20, - 0x2d, 0x62, 0xca, 0x67, 0x2a, 0xe8, 0x73, 0xa6, 0xb7, 0x7d, 0x13, 0x78, 0x73, 0xd4, 0xb4, 0x32, 0x2a, 0x07, 0xb8, - 0x49, 0xba, 0x29, 0x83, 0x51, 0x91, 0xac, 0x87, 0x01, 0x2a, 0x41, 0x4e, 0x74, 0x1a, 0x1b, 0x6a, 0x8f, 0xc3, 0x20, - 0x71, 0x1b, 0x50, 0xef, 0x35, 0x33, 0x3a, 0x1a, 0xdd, 0xe7, 0xbf, 0xf0, 0xff, 0xc3, 0xf7, 0x7f, 0x16, 0x8d, 0x93, - 0x5e, 0xa8, 0xac, 0xb4, 0x40, 0xaa, 0x19, 0x81, 0x7e, 0x8f, 0x3b, 0xaf, 0xee, 0x61, 0x85, 0xd1, 0xa5, 0x9d, 0xdb, - 0xee, 0xf4, 0xb8, 0x7f, 0x7d, 0x0a, 0x3f, 0x7f, 0xf7, 0x75, 0xcd, 0xaf, 0xf4, 0x5e, 0x9e, 0x29, 0x87, 0xae, 0x71, - 0x23, 0x92, 0x04, 0xc6, 0xab, 0x6b, 0x14, 0x5a, 0x81, 0x2c, 0xbf, 0x40, 0xc1, 0xc7, 0xb7, 0x46, 0xbb, 0x4f, 0xbb, - 0x22, 0xc8, 0x84, 0xbc, 0x55, 0x10, 0xd6, 0x36, 0x1c, 0x0f, 0x6c, 0x16, 0x5d, 0xd0, 0xfb, 0x1d, 0xba, 0x86, 0x9f, - 0x32, 0x5f, 0x5e, 0xcd, 0x05, 0xdf, 0xe0, 0x74, 0x02, 0xba, 0xe5, 0xce, 0x7b, 0x15, 0xd8, 0x21, 0x67, 0xfd, 0xc8, - 0xe8, 0xde, 0x29, 0x64, 0xa3, 0xc4, 0xb4, 0x63, 0xa1, 0xed, 0xda, 0xa9, 0xdb, 0x21, 0x1e, 0xdf, 0x28, 0x05, 0x3c, - 0x3a, 0x6c, 0x6e, 0x9c, 0x34, 0x52, 0xb0, 0x6a, 0x6f, 0x7d, 0x3d, 0xb7, 0xb9, 0x15, 0xcb, 0x07, 0x5b, 0x6f, 0x20, - 0x09, 0xe9, 0xc6, 0x91, 0x33, 0xa5, 0x5e, 0x1b, 0xda, 0xa7, 0xd9, 0xca, 0xcd, 0x4d, 0xd2, 0x71, 0xaf, 0x9e, 0xc6, - 0x09, 0xe3, 0x38, 0x97, 0x54, 0x26, 0x4e, 0x7c, 0x89, 0xf9, 0xf2, 0x44, 0x6c, 0xa6, 0x25, 0x35, 0xba, 0xca, 0x75, - 0x67, 0x4a, 0x14, 0xa4, 0xe8, 0xf9, 0xdb, 0x2c, 0xe1, 0x8a, 0x6b, 0xc2, 0x33, 0x03, 0x35, 0xa1, 0x75, 0xee, 0x5e, - 0x66, 0x78, 0x70, 0x89, 0xfb, 0xe3, 0xc4, 0xbf, 0x50, 0x3d, 0xb1, 0xe5, 0x57, 0x94, 0xb1, 0xf1, 0x66, 0xdd, 0xdd, - 0xbf, 0xa7, 0xc4, 0x7d, 0x7e, 0x2a, 0x8e, 0xa2, 0xf5, 0xf6, 0xfd, 0xe4, 0x2a, 0xd6, 0xf3, 0xa9, 0xe0, 0x1b, 0x45, - 0x00, 0x9c, 0xf4, 0x68, 0x59, 0xee, 0xb4, 0x1a, 0x7c, 0x06, 0x02, 0x22, 0xdf, 0x9d, 0xb3, 0x6b, 0x7f, 0x3c, 0x25, - 0xd3, 0x66, 0x34, 0x97, 0x97, 0x41, 0xb3, 0xaf, 0x11, 0x00, 0xc8, 0x69, 0xcd, 0xc8, 0xc7, 0xf9, 0x10, 0x06, 0x97, - 0xcb, 0x24, 0x73, 0xbb, 0x05, 0x70, 0x01, 0xb9, 0x52, 0xbe, 0x5a, 0x57, 0x31, 0xd4, 0xcc, 0x8b, 0x70, 0x7c, 0xb5, - 0x97, 0x4f, 0xd1, 0x4e, 0x58, 0xda, 0xab, 0xb9, 0x8c, 0x04, 0xd6, 0xab, 0x0e, 0x11, 0x7a, 0xb2, 0x35, 0xf2, 0xf8, - 0x32, 0xf3, 0xdd, 0x96, 0x03, 0x6a, 0x07, 0x96, 0x57, 0x5b, 0xcd, 0x49, 0xd3, 0x6e, 0x79, 0x34, 0xdb, 0x33, 0xaa, - 0xa1, 0x60, 0x39, 0x77, 0xfb, 0x91, 0x1d, 0x67, 0x4b, 0x75, 0x35, 0xb7, 0xfa, 0x82, 0xb0, 0x2d, 0x16, 0xc8, 0xc7, - 0x11, 0xb0, 0xa6, 0x13, 0x5a, 0x92, 0x39, 0x28, 0x4d, 0x3b, 0x0a, 0x40, 0x07, 0xf0, 0x64, 0x1a, 0xf7, 0x94, 0xf4, - 0xdf, 0x81, 0xb7, 0x6b, 0x7d, 0xd2, 0xa1, 0x18, 0x05, 0xcf, 0x3f, 0x9c, 0x01, 0x38, 0xfd, 0xde, 0xda, 0xfb, 0xd9, - 0xbb, 0x35, 0xa0, 0xe6, 0x5a, 0xae, 0x1c, 0xc1, 0x7f, 0x2a, 0x32, 0x65, 0x45, 0xcc, 0xb7, 0x23, 0x54, 0xaa, 0xb0, - 0xdc, 0xab, 0x80, 0xbf, 0xdf, 0x0d, 0xb7, 0xff, 0xaf, 0x8a, 0xc9, 0x3d, 0xfc, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, - 0x6d, 0x58, 0x5b, 0xee, 0x7f, 0x6b, 0xc0, 0xf4, 0xbb, 0x02, 0x35, 0xc1, 0xf6, 0x6f, 0xdf, 0xb9, 0x24, 0x97, 0xf5, - 0xe1, 0xde, 0xc9, 0x4a, 0x0f, 0x53, 0x7a, 0x30, 0xf0, 0x08, 0xff, 0x7f, 0x96, 0x81, 0xec, 0x05, 0x85, 0xc9, 0xc2, - 0xfe, 0xfb, 0x59, 0x2a, 0xa0, 0x9f, 0x12, 0x65, 0x8d, 0x23, 0xde, 0xd6, 0x7e, 0x5a, 0xa3, 0x1f, 0x23, 0xa2, 0x58, - 0xa7, 0x82, 0x7e, 0x55, 0x9f, 0x27, 0x88, 0xef, 0x7d, 0x5c, 0xfa, 0x12, 0x2a, 0x86, 0x07, 0xca, 0xde, 0x5d, 0xc1, - 0xf9, 0x91, 0x6e, 0xc7, 0x45, 0xa1, 0xf9, 0x53, 0xe5, 0x8f, 0xdb, 0x7a, 0xae, 0xf2, 0x7e, 0x45, 0xda, 0x37, 0xb9, - 0xf5, 0x57, 0x51, 0xd2, 0xbd, 0x20, 0x8b, 0x2c, 0x16, 0x77, 0xe7, 0x22, 0xf9, 0xc4, 0xd9, 0x03, 0xdb, 0x39, 0x9b, - 0x47, 0x78, 0x32, 0xa7, 0xb1, 0x48, 0x44, 0x67, 0xe1, 0xf5, 0x40, 0x93, 0x8a, 0x5d, 0x1f, 0xe0, 0xbb, 0x0f, 0xfc, - 0xe4, 0x94, 0x2f, 0x7e, 0xf2, 0x57, 0x3e, 0x46, 0x8f, 0xf5, 0x29, 0x9b, 0x60, 0xf0, 0x4a, 0x97, 0x53, 0x3d, 0x7b, - 0x79, 0x68, 0x48, 0xf4, 0xa6, 0xc6, 0xca, 0x7e, 0xa0, 0x67, 0xab, 0xa9, 0xee, 0x92, 0xb1, 0x42, 0xcb, 0xbb, 0xe2, - 0xf6, 0xd1, 0xba, 0x1a, 0x5f, 0x69, 0xdc, 0x4d, 0xcb, 0xf7, 0x24, 0xea, 0x60, 0x71, 0xf3, 0xe3, 0x4e, 0xbd, 0x6d, - 0x5b, 0xe5, 0xbf, 0x0b, 0xd0, 0x1f, 0x6c, 0xf4, 0x4e, 0xe6, 0x30, 0xa7, 0x57, 0x7e, 0x9e, 0xe3, 0x95, 0xc3, 0x9c, - 0x5d, 0xd9, 0xcd, 0xb9, 0x95, 0xeb, 0x39, 0xff, 0xf0, 0x71, 0x70, 0x93, 0x27, 0xc1, 0x2e, 0x1f, 0x63, 0x88, 0xb3, - 0xb3, 0x0f, 0xc3, 0x2d, 0xe7, 0x8f, 0x11, 0xb7, 0x6d, 0xca, 0x0a, 0x52, 0x4f, 0x7d, 0x3c, 0xf9, 0xf8, 0xde, 0x7a, - 0x97, 0x7e, 0x65, 0xb3, 0xab, 0x3d, 0xad, 0xc6, 0xcb, 0x22, 0x8a, 0xc4, 0x5c, 0x6d, 0xca, 0xfb, 0xad, 0x1b, 0x66, - 0x02, 0x36, 0xed, 0xf9, 0xb6, 0xed, 0xc8, 0xcd, 0x95, 0xea, 0x9f, 0xcf, 0xa8, 0x4b, 0xe6, 0x3b, 0xf2, 0x48, 0x6a, - 0x66, 0xaf, 0xea, 0xcc, 0x3b, 0xd3, 0x44, 0x11, 0x24, 0x08, 0xa2, 0x7c, 0xbe, 0x90, 0xc9, 0xdc, 0xd2, 0x2a, 0x41, - 0xd0, 0xd8, 0x37, 0x60, 0x49, 0x99, 0xac, 0x5b, 0x57, 0xcc, 0x74, 0x06, 0xf2, 0x69, 0x0f, 0x6b, 0xc2, 0x9b, 0xc1, - 0xe1, 0x7c, 0xdd, 0xf5, 0xd9, 0xe5, 0xbd, 0xcf, 0x3d, 0xea, 0xb8, 0xbf, 0x15, 0x37, 0x20, 0x07, 0x73, 0x9f, 0x27, - 0x77, 0x21, 0x6b, 0xac, 0xd3, 0x86, 0x72, 0x4e, 0x75, 0x6d, 0xda, 0x60, 0x88, 0x5e, 0xfd, 0x42, 0x98, 0x48, 0x5b, - 0x3c, 0x9f, 0xd6, 0xd2, 0x37, 0x05, 0x2e, 0x6d, 0x66, 0xd0, 0x69, 0x58, 0x2c, 0x66, 0x12, 0xc2, 0x89, 0x8b, 0x7a, - 0xb4, 0xa9, 0x24, 0x89, 0xf1, 0xb3, 0xfe, 0x5a, 0x2e, 0x23, 0x38, 0x50, 0x0b, 0x4c, 0x5c, 0x17, 0x69, 0xf4, 0x1f, - 0xcc, 0x50, 0x6f, 0x9b, 0xfd, 0xa0, 0xcd, 0x8d, 0x29, 0x7c, 0x85, 0x7e, 0xd2, 0xf4, 0x0a, 0xb5, 0x7b, 0x11, 0x1f, - 0x89, 0x21, 0xf2, 0x01, 0x6c, 0x3b, 0xcc, 0x09, 0xb4, 0x80, 0x73, 0xc4, 0x18, 0x2c, 0x4e, 0x95, 0xea, 0x6c, 0x92, - 0xb7, 0x22, 0x46, 0x5b, 0xb2, 0x1d, 0x6d, 0xd5, 0xb9, 0x1c, 0x5b, 0xb4, 0xb9, 0x91, 0x7d, 0xf3, 0x9f, 0xab, 0x7c, - 0xa3, 0x7d, 0x7f, 0xb5, 0x0a, 0xec, 0x81, 0x91, 0xbf, 0x6b, 0x7f, 0x33, 0x97, 0xb2, 0xec, 0xff, 0x63, 0x72, 0x32, - 0x7b, 0x23, 0x81, 0xf8, 0x95, 0xe7, 0x69, 0x25, 0x9e, 0x84, 0x91, 0xfd, 0x8e, 0x3c, 0xa1, 0xca, 0xb7, 0xd1, 0x96, - 0x96, 0xe5, 0x7e, 0xb7, 0x96, 0x1f, 0x93, 0xe9, 0x5c, 0xbe, 0xf5, 0x84, 0x21, 0xb7, 0xe7, 0x89, 0x78, 0x9f, 0x00, - 0xe7, 0xe6, 0x78, 0x69, 0x9e, 0x7c, 0xe3, 0x91, 0x69, 0xc1, 0x16, 0x80, 0x37, 0x72, 0x76, 0x24, 0xca, 0x49, 0x22, - 0x2d, 0x86, 0x7a, 0xfc, 0xd6, 0xd9, 0xea, 0xef, 0xcd, 0x01, 0x57, 0x00, 0x26, 0x0f, 0xf8, 0x70, 0x24, 0x3f, 0x6e, - 0xdb, 0x09, 0xdb, 0x98, 0x35, 0xc4, 0xe4, 0x61, 0x72, 0x50, 0x7e, 0x15, 0xb4, 0x1a, 0xe9, 0x0b, 0x97, 0x93, 0xcc, - 0x02, 0xe7, 0x90, 0xb8, 0xef, 0x2f, 0x22, 0x9f, 0xfe, 0x5d, 0xe6, 0x4f, 0x0e, 0xce, 0x4c, 0xf1, 0x1f, 0xa3, 0xf1, - 0x40, 0x46, 0xe6, 0x45, 0xfd, 0x53, 0xa3, 0xb5, 0x54, 0x3b, 0x3b, 0x8a, 0x9b, 0x2b, 0x6b, 0x6f, 0xcd, 0x9a, 0x03, - 0xd6, 0x5b, 0x23, 0xf3, 0xc6, 0x32, 0xa2, 0x69, 0x23, 0x7e, 0x09, 0xe7, 0xd5, 0x71, 0x9d, 0x07, 0xe4, 0x37, 0x84, - 0x10, 0xe6, 0xd5, 0x7a, 0xcb, 0x53, 0xb8, 0x5e, 0x2f, 0x75, 0x34, 0xa7, 0xa1, 0xcf, 0x3c, 0x4b, 0x03, 0xcd, 0x80, - 0xe8, 0xd9, 0x79, 0xf5, 0x99, 0xd7, 0x99, 0xb9, 0x18, 0x8f, 0x4e, 0x68, 0xa6, 0x4e, 0xb8, 0xe7, 0x83, 0x19, 0x0b, - 0x14, 0x9b, 0xf8, 0x09, 0x49, 0xe0, 0xf1, 0x93, 0xa3, 0xbc, 0x73, 0x4e, 0xc9, 0xc3, 0x3b, 0x7e, 0x00, 0x0d, 0x40, - 0xe6, 0x1d, 0x24, 0xad, 0xb6, 0xbd, 0xc7, 0x6a, 0x14, 0x09, 0xbe, 0xcc, 0x95, 0xf1, 0xb4, 0xc9, 0x17, 0x6e, 0x36, - 0xb3, 0x7b, 0x57, 0x0f, 0x9e, 0x6f, 0x56, 0xbb, 0xbe, 0xcd, 0x9a, 0xcf, 0x6c, 0xfe, 0xe9, 0xd3, 0x22, 0x2e, 0x67, - 0x94, 0xb9, 0x9e, 0x53, 0xe8, 0x35, 0x23, 0x93, 0x0e, 0xdd, 0x73, 0x89, 0x9d, 0x90, 0x05, 0x4d, 0x6e, 0xe1, 0xa2, - 0x9a, 0x84, 0xfb, 0xda, 0xef, 0x84, 0xd4, 0xa9, 0x5a, 0xd4, 0x1b, 0xa3, 0x27, 0xbb, 0xf8, 0x19, 0x7b, 0xcc, 0x3b, - 0x33, 0x39, 0x91, 0x01, 0x78, 0x51, 0xd9, 0x14, 0x58, 0x9e, 0x35, 0x01, 0x04, 0x65, 0x58, 0x86, 0xd6, 0x12, 0x40, - 0x61, 0x6e, 0xca, 0x07, 0x19, 0xb4, 0xfc, 0x1c, 0x7f, 0x5d, 0x9e, 0x1b, 0x98, 0x37, 0x3e, 0x4e, 0x4e, 0xd0, 0x9c, - 0x14, 0xca, 0x85, 0x88, 0x0f, 0x0a, 0xa0, 0x46, 0x05, 0x9e, 0xd1, 0xbd, 0x0f, 0xf0, 0xdf, 0x0f, 0xfb, 0x75, 0x9d, - 0xf2, 0xef, 0x4f, 0xfe, 0x69, 0xee, 0x3d, 0xf1, 0xaf, 0x4b, 0x49, 0x0a, 0x08, 0x9e, 0xc2, 0xbe, 0xb9, 0xde, 0xbf, - 0x4d, 0xee, 0x55, 0xed, 0x6e, 0x23, 0xa3, 0x3a, 0xb1, 0x30, 0x94, 0xfe, 0x7a, 0xe4, 0xca, 0x37, 0x1f, 0x62, 0xdb, - 0xc3, 0xa6, 0x3f, 0xdc, 0xf7, 0xab, 0x7c, 0x73, 0x21, 0x53, 0xbb, 0x69, 0x45, 0x62, 0x95, 0x62, 0xc0, 0x95, 0x82, - 0x86, 0x39, 0x67, 0x0f, 0xdf, 0xce, 0xd6, 0x46, 0x1a, 0xf1, 0x86, 0xb8, 0x12, 0xab, 0xee, 0x93, 0x50, 0xf9, 0xf6, - 0xfe, 0xf5, 0xd2, 0xb2, 0xf3, 0xb9, 0xf5, 0x0b, 0xc9, 0x00, 0xb3, 0x40, 0xe2, 0x53, 0x71, 0xe4, 0x3e, 0x94, 0x74, - 0x92, 0xa2, 0x78, 0x0c, 0x6d, 0x81, 0x05, 0xa3, 0x21, 0x97, 0xc6, 0x00, 0x59, 0x6a, 0x89, 0x47, 0x5d, 0x4c, 0x2f, - 0xf8, 0xbe, 0xed, 0x06, 0xcd, 0xf7, 0x86, 0x27, 0x1f, 0x7a, 0x6d, 0x62, 0x04, 0xa5, 0x2b, 0xb0, 0xbd, 0xad, 0x18, - 0x91, 0xcb, 0xa5, 0xe4, 0x9f, 0x26, 0x0f, 0x50, 0xb8, 0xef, 0x9e, 0xf8, 0x5c, 0x2c, 0x14, 0xa5, 0xc8, 0x7c, 0x10, - 0x57, 0x83, 0x88, 0x93, 0x06, 0xaa, 0xae, 0x36, 0x76, 0x20, 0xcc, 0xb2, 0x31, 0xa5, 0xc6, 0x0b, 0x1a, 0x10, 0x44, - 0x88, 0x6c, 0x62, 0x05, 0x22, 0xd4, 0xc3, 0xfc, 0x70, 0x43, 0xc7, 0x8a, 0x3a, 0x45, 0x27, 0xa8, 0xa9, 0xb4, 0x86, - 0x34, 0x3d, 0x7a, 0x85, 0x0d, 0x8c, 0x4e, 0x9c, 0x4d, 0x57, 0xe1, 0xbd, 0xe1, 0xce, 0xbe, 0x37, 0x8f, 0x79, 0x2e, - 0xd3, 0x1e, 0x84, 0x4a, 0xc3, 0x58, 0x4f, 0xb7, 0xc4, 0xe9, 0x9e, 0x6d, 0xe6, 0x25, 0xd5, 0x7c, 0x77, 0xb7, 0x67, - 0xed, 0x39, 0x1b, 0x51, 0xbb, 0xad, 0x83, 0xa3, 0xdb, 0x60, 0xac, 0xcf, 0xbb, 0xbb, 0xbc, 0xa0, 0x3d, 0xa9, 0x62, - 0x22, 0x36, 0xd1, 0xa4, 0x01, 0x20, 0xda, 0x51, 0x9a, 0xec, 0xf3, 0x93, 0x9d, 0x1a, 0x08, 0xa5, 0x23, 0x28, 0x6d, - 0x63, 0x33, 0x51, 0x55, 0x6f, 0xf2, 0xb8, 0x8e, 0x9b, 0x30, 0x43, 0x41, 0xcd, 0x7f, 0x3f, 0x0a, 0xb6, 0xdc, 0x19, - 0x98, 0x20, 0xd6, 0x73, 0xdb, 0xd2, 0x5d, 0xc0, 0x03, 0x9c, 0xbe, 0xed, 0xc0, 0x9b, 0x46, 0x7c, 0x1e, 0x1e, 0xa7, - 0xc7, 0xba, 0x17, 0x6e, 0x89, 0x12, 0x23, 0x19, 0x41, 0x06, 0xb9, 0xf6, 0xd8, 0x07, 0x2f, 0x61, 0x91, 0xae, 0x23, - 0xc7, 0x0f, 0xe1, 0x82, 0xc2, 0x84, 0x70, 0x1a, 0xee, 0x5e, 0x14, 0x75, 0x9b, 0xdd, 0xee, 0x89, 0xd1, 0xce, 0x96, - 0xdc, 0xd5, 0x6e, 0x90, 0x79, 0x14, 0xe8, 0xdd, 0x2a, 0x8b, 0xb2, 0xb5, 0x23, 0x1f, 0x36, 0x93, 0x7c, 0x1c, 0x48, - 0xa6, 0xbe, 0xbb, 0x33, 0xb4, 0x3f, 0x90, 0x9d, 0xb6, 0xef, 0x12, 0x5a, 0x1f, 0xa0, 0x9a, 0x56, 0xed, 0xb6, 0x65, - 0xdb, 0xf6, 0x69, 0x19, 0x90, 0x7b, 0xac, 0x7d, 0xe9, 0x46, 0xc6, 0xff, 0xfc, 0x04, 0x23, 0xad, 0x3b, 0xf4, 0x0b, - 0x73, 0x97, 0x9d, 0x46, 0xb6, 0x37, 0x57, 0x4f, 0x51, 0x5a, 0xfb, 0xc0, 0x2c, 0x1a, 0x1f, 0x47, 0x60, 0x7c, 0x06, - 0x4d, 0x84, 0xc1, 0xcf, 0xf0, 0x8b, 0x85, 0x74, 0xb9, 0x22, 0xf7, 0x62, 0x02, 0xe8, 0xdd, 0xe8, 0xcf, 0x9e, 0x41, - 0xb5, 0x54, 0x65, 0x74, 0x9d, 0x14, 0xc5, 0xf4, 0xb7, 0xff, 0x9f, 0xab, 0x81, 0xfa, 0x83, 0x18, 0x85, 0xbe, 0xfc, - 0xe2, 0xe8, 0x5a, 0x57, 0x6c, 0x7a, 0xfe, 0x82, 0xee, 0x03, 0x2e, 0xf1, 0x82, 0x01, 0x3e, 0x8b, 0xc8, 0xdc, 0x24, - 0x73, 0xad, 0xd1, 0x69, 0xec, 0x6d, 0xb0, 0x77, 0x27, 0xff, 0x64, 0x10, 0xf7, 0x0b, 0x68, 0x3b, 0xd3, 0xdd, 0x20, - 0x83, 0x54, 0x9f, 0x13, 0xfd, 0xc3, 0xc0, 0x06, 0xf9, 0xc9, 0xa2, 0x5c, 0x46, 0x38, 0x9f, 0x14, 0x1d, 0x63, 0x15, - 0x62, 0x57, 0x21, 0xf7, 0x8d, 0x74, 0x37, 0x06, 0x76, 0xe8, 0x19, 0x0c, 0xfb, 0xdd, 0x69, 0x53, 0xa9, 0xa0, 0xbd, - 0xaa, 0x46, 0x93, 0xdd, 0x48, 0x6e, 0xed, 0x45, 0x6c, 0xf4, 0x43, 0xc0, 0x10, 0x37, 0x55, 0x8b, 0xdb, 0x01, 0x0b, - 0x87, 0x5d, 0x5c, 0x47, 0x77, 0x04, 0x99, 0x3f, 0x7c, 0x62, 0xc1, 0x15, 0xd9, 0xf9, 0xdf, 0x12, 0x4c, 0xdf, 0x3b, - 0xad, 0xcc, 0xff, 0x53, 0xcc, 0xfe, 0xd0, 0xf3, 0x8a, 0xac, 0x3f, 0x7b, 0xbf, 0x28, 0xba, 0x84, 0xcb, 0x2d, 0x12, - 0xf3, 0x29, 0x34, 0xfd, 0xf5, 0xd6, 0x7c, 0x23, 0x24, 0xee, 0x0f, 0x26, 0x04, 0x9b, 0x94, 0xc5, 0x18, 0x11, 0xfe, - 0xf5, 0xf6, 0xab, 0xf9, 0xd7, 0xa4, 0x25, 0x88, 0xa0, 0xaa, 0xf1, 0x4e, 0x7f, 0xcf, 0x68, 0xf9, 0x01, 0xfe, 0xfd, - 0x81, 0x3f, 0x39, 0xe5, 0xef, 0x9f, 0xfc, 0xd3, 0x2c, 0xbd, 0x25, 0x57, 0xf3, 0x19, 0x72, 0xb0, 0xac, 0x22, 0x01, - 0x2f, 0x5e, 0xcb, 0x91, 0x37, 0x3b, 0x88, 0x07, 0x32, 0xff, 0xea, 0x24, 0x2e, 0xd0, 0x31, 0xf2, 0x21, 0x4f, 0x4b, - 0xf2, 0x82, 0xb1, 0x3b, 0xaa, 0xa5, 0x99, 0xb6, 0xd5, 0xbb, 0x84, 0xda, 0xc5, 0x20, 0x4b, 0x30, 0xdf, 0xff, 0x24, - 0x72, 0x52, 0xd2, 0x98, 0x7f, 0x2b, 0x1f, 0x8f, 0xee, 0x59, 0x1a, 0x98, 0xa2, 0x62, 0xfe, 0xea, 0x45, 0xca, 0x93, - 0xd5, 0x1f, 0xa3, 0x11, 0xf7, 0x8d, 0x99, 0x85, 0xe8, 0x03, 0x3b, 0x43, 0x62, 0xe4, 0xb8, 0x7b, 0x71, 0xd2, 0xf8, - 0xad, 0x4e, 0x90, 0x78, 0xcb, 0x34, 0x48, 0x5f, 0x8b, 0x43, 0xb9, 0x56, 0x8d, 0x4f, 0x3c, 0x58, 0xa4, 0xfd, 0x6d, - 0x77, 0x96, 0xbe, 0xf5, 0xf2, 0xb8, 0x32, 0x7d, 0x99, 0x70, 0x17, 0xc6, 0x22, 0xce, 0x35, 0x56, 0x54, 0x24, 0x46, - 0xe0, 0x10, 0xc5, 0xdb, 0x02, 0x80, 0xd9, 0x28, 0x76, 0x71, 0xfc, 0xc7, 0xef, 0xda, 0xc2, 0x89, 0x44, 0x4b, 0x91, - 0xd4, 0xdc, 0x61, 0x7c, 0xa3, 0xf1, 0x98, 0xc1, 0x78, 0x4f, 0x54, 0xfd, 0xc5, 0xf2, 0x98, 0x95, 0x5a, 0x8f, 0x52, - 0x3c, 0x66, 0x7c, 0x69, 0x34, 0x58, 0x62, 0xcf, 0x43, 0x98, 0xfc, 0x4b, 0xa3, 0xe4, 0xf7, 0x52, 0xec, 0x6a, 0x69, - 0x24, 0xb6, 0x0e, 0xc4, 0x4c, 0x66, 0x71, 0x02, 0xeb, 0x4c, 0x75, 0x4f, 0xce, 0xc6, 0x4b, 0xa5, 0x79, 0x05, 0xad, - 0x0b, 0x7f, 0xa0, 0x9d, 0xe0, 0xd6, 0x5f, 0x3c, 0xbf, 0xe9, 0x56, 0x0e, 0x47, 0xae, 0xd8, 0x6b, 0xfd, 0x3d, 0xde, - 0xee, 0xa9, 0xfa, 0xcb, 0x35, 0xd0, 0x9d, 0x63, 0xb3, 0x49, 0x93, 0xe1, 0x60, 0xe4, 0x13, 0x40, 0x27, 0x48, 0x8e, - 0x66, 0x58, 0xa1, 0xe7, 0x5d, 0x02, 0xb3, 0x5f, 0xf2, 0xe2, 0x10, 0x25, 0x04, 0x7c, 0x6b, 0xb3, 0x98, 0x84, 0xe8, - 0xe1, 0xff, 0xb9, 0x97, 0x7e, 0xbd, 0xb8, 0x5d, 0x8e, 0xb4, 0x05, 0x72, 0xeb, 0x1c, 0x30, 0x0e, 0x7c, 0xb5, 0x31, - 0x50, 0x2e, 0x44, 0x66, 0x44, 0x53, 0x3a, 0x1b, 0x9c, 0x6e, 0x43, 0x3e, 0x5b, 0xf3, 0xf8, 0x46, 0x25, 0x3a, 0xa7, - 0x4e, 0xd2, 0x8c, 0x5b, 0x1b, 0xc4, 0x58, 0x2e, 0x44, 0x43, 0x2c, 0x74, 0x6c, 0x0d, 0x2e, 0x76, 0xdc, 0x0e, 0x8f, - 0xe7, 0xa2, 0x11, 0x3f, 0x92, 0x10, 0x11, 0x9c, 0x8b, 0x99, 0x18, 0xf2, 0xa1, 0x19, 0x01, 0xec, 0xe7, 0x79, 0x7c, - 0x61, 0x1a, 0x66, 0x8f, 0xe0, 0xd9, 0xcb, 0x13, 0xf1, 0x93, 0x46, 0x30, 0x44, 0xc8, 0x86, 0x49, 0x02, 0xd8, 0x63, - 0xb2, 0xd6, 0x6f, 0xdc, 0xda, 0xcb, 0xbe, 0xbf, 0x2c, 0x1b, 0xb7, 0xf3, 0xdf, 0xb1, 0xf8, 0x61, 0x12, 0xf5, 0xea, - 0x9d, 0x08, 0x61, 0x57, 0x8c, 0xde, 0xc9, 0x2a, 0x74, 0x55, 0x44, 0xdf, 0xf7, 0xf0, 0xb1, 0xc6, 0x06, 0xe1, 0x8f, - 0xe1, 0x29, 0x90, 0x37, 0x91, 0xdd, 0xbf, 0x13, 0x5c, 0xdc, 0xf8, 0xd1, 0x9e, 0xc2, 0xce, 0xd8, 0x21, 0x74, 0xa9, - 0x92, 0x49, 0xd1, 0x1d, 0x94, 0x26, 0x9a, 0x6a, 0x78, 0xa1, 0x40, 0x7c, 0x0c, 0x5b, 0x76, 0x35, 0xe3, 0x23, 0xc5, - 0x6f, 0xe3, 0xc5, 0x02, 0xa7, 0x98, 0x60, 0xf4, 0xf0, 0xc0, 0x84, 0xb1, 0x05, 0x6a, 0xf4, 0x10, 0x15, 0x53, 0xce, - 0x63, 0xaa, 0x4b, 0x16, 0x27, 0x7b, 0x65, 0x56, 0x6b, 0xa7, 0x4f, 0x93, 0x54, 0xac, 0x57, 0x58, 0x9e, 0x59, 0xbd, - 0x6a, 0x97, 0x09, 0xf0, 0xc1, 0xff, 0x38, 0x04, 0x26, 0x64, 0x5c, 0x75, 0x6a, 0xfb, 0x30, 0x46, 0x78, 0xf3, 0x3b, - 0xc9, 0x84, 0xb2, 0x49, 0x3e, 0x8c, 0x70, 0x67, 0xf7, 0x44, 0x77, 0x8a, 0x33, 0x26, 0x77, 0x51, 0x0d, 0x83, 0x99, - 0x4e, 0xd0, 0x87, 0xfb, 0x85, 0x39, 0x8f, 0x2b, 0xbc, 0xc7, 0xdf, 0x32, 0xaa, 0x13, 0xe2, 0xf5, 0x45, 0xba, 0x88, - 0x1f, 0x38, 0x05, 0xdb, 0x05, 0x54, 0xc3, 0x08, 0x5c, 0x87, 0xd3, 0xba, 0x23, 0x89, 0xe2, 0x8e, 0x4a, 0x50, 0xdf, - 0x48, 0xf9, 0xbb, 0x63, 0x23, 0x96, 0xa8, 0x1a, 0xe9, 0x2f, 0x4a, 0x79, 0x60, 0x87, 0xf4, 0xa4, 0xd4, 0xe8, 0x98, - 0xa9, 0x53, 0xd3, 0xe0, 0x72, 0x90, 0xbb, 0xe0, 0x95, 0xce, 0xec, 0xc1, 0xb9, 0x58, 0x78, 0xa1, 0x19, 0xa2, 0x1e, - 0xe1, 0xda, 0x78, 0xea, 0x92, 0xc4, 0xa9, 0x6a, 0x49, 0xc2, 0x72, 0xd2, 0xe9, 0x4a, 0x03, 0xf7, 0xea, 0x65, 0x8f, - 0x31, 0x90, 0x26, 0xb3, 0x04, 0xa1, 0x7a, 0x5e, 0x23, 0xbc, 0x46, 0x0a, 0x92, 0x76, 0x1e, 0xf6, 0x37, 0x09, 0x28, - 0x6f, 0xfd, 0x43, 0xbd, 0xa2, 0xc0, 0xf2, 0xa7, 0x82, 0xbc, 0x57, 0xeb, 0x6f, 0x33, 0xea, 0x46, 0x37, 0x09, 0xc3, - 0x6e, 0xfd, 0xc3, 0xc6, 0x2a, 0x35, 0x39, 0x9d, 0xf4, 0x6d, 0xb1, 0x7b, 0x00, 0xf2, 0x72, 0xb7, 0x37, 0xc4, 0x64, - 0x44, 0x10, 0x35, 0x07, 0x2e, 0x42, 0x75, 0xc6, 0xf8, 0x76, 0xa2, 0x1b, 0x35, 0xad, 0x11, 0x62, 0xc9, 0xea, 0x1a, - 0x17, 0x72, 0x57, 0x4c, 0x9c, 0x8c, 0x44, 0xe8, 0x96, 0xe4, 0x5c, 0x7f, 0x80, 0xc3, 0x07, 0x92, 0x29, 0x15, 0xc1, - 0x65, 0x82, 0xa4, 0xfa, 0xbc, 0x89, 0xa0, 0x5b, 0x0d, 0x10, 0x58, 0x02, 0xa9, 0x96, 0xb9, 0x59, 0xdc, 0x32, 0x22, - 0x70, 0x54, 0xcb, 0x57, 0x27, 0x52, 0x38, 0xa3, 0xd9, 0xce, 0x1f, 0x5f, 0xfa, 0xc8, 0xbc, 0x55, 0x85, 0x61, 0x49, - 0x01, 0xe8, 0xca, 0xf8, 0x92, 0x42, 0x90, 0x4a, 0xf9, 0xa2, 0x5b, 0xab, 0x9a, 0xb9, 0x4e, 0x6c, 0xe8, 0xc6, 0x0b, - 0xcc, 0xaf, 0xd5, 0x86, 0x81, 0xcd, 0xdd, 0xae, 0x65, 0xae, 0xd8, 0x20, 0xe7, 0x1d, 0xb5, 0x2d, 0x1f, 0x96, 0xd3, - 0xd1, 0xd5, 0x8c, 0x85, 0x8b, 0xdb, 0xa1, 0x48, 0x7d, 0x60, 0x32, 0xe4, 0x34, 0xba, 0x5f, 0x02, 0x32, 0xff, 0xb4, - 0x34, 0x6a, 0x37, 0x5f, 0x30, 0x7a, 0x0e, 0xbd, 0x8c, 0xe3, 0xd9, 0x45, 0xfe, 0x00, 0xa1, 0xec, 0x0d, 0x4e, 0xa1, - 0xb1, 0x01, 0x9d, 0x8b, 0xf0, 0x99, 0x18, 0x05, 0xd6, 0x91, 0x00, 0xbc, 0x38, 0xb7, 0x71, 0x74, 0x00, 0xa8, 0x35, - 0xaa, 0x80, 0xfb, 0xfd, 0xd1, 0x23, 0x87, 0x28, 0xe2, 0x86, 0xdc, 0x53, 0xd4, 0xa5, 0x3c, 0x9f, 0x48, 0x2b, 0x0b, - 0x1f, 0xa6, 0xc8, 0x2b, 0x7e, 0xa1, 0x17, 0x76, 0x69, 0xe7, 0xa7, 0xa5, 0x9b, 0xf7, 0x4b, 0x4d, 0x3c, 0x95, 0xa3, - 0x9f, 0x53, 0x35, 0x65, 0x50, 0xd2, 0xf5, 0xee, 0x22, 0xa2, 0x03, 0x73, 0x2c, 0x6c, 0xf7, 0x03, 0xa7, 0x9a, 0xb6, - 0xca, 0xe4, 0x6e, 0xe5, 0xa1, 0x02, 0x15, 0x1c, 0xa4, 0xeb, 0x65, 0x7b, 0xef, 0x3f, 0xb1, 0xe1, 0x87, 0x4d, 0xf9, - 0x30, 0xd5, 0x75, 0xda, 0xd3, 0xab, 0xa1, 0x0d, 0x91, 0x83, 0xb4, 0x90, 0xb6, 0xab, 0xc6, 0xbd, 0x35, 0x93, 0xd6, - 0xfe, 0xcd, 0xa6, 0x97, 0xed, 0x14, 0x3b, 0x7f, 0x8c, 0x7a, 0x05, 0x51, 0xe4, 0xfa, 0xbd, 0x74, 0xf5, 0x73, 0xe9, - 0x76, 0x2d, 0x48, 0x3f, 0x50, 0x05, 0xcd, 0x2c, 0xa7, 0xbf, 0x2c, 0xf9, 0xe6, 0x96, 0xd2, 0xc7, 0xf4, 0x87, 0x38, - 0xe7, 0xf8, 0xcc, 0xf0, 0x4c, 0x1d, 0x3d, 0xe8, 0x14, 0x11, 0xcd, 0x38, 0x9b, 0x67, 0xd1, 0x74, 0x16, 0xf0, 0x9a, - 0x54, 0x70, 0x57, 0x3f, 0x1c, 0x3a, 0xd6, 0xb4, 0x8b, 0x90, 0xc5, 0x3e, 0x7e, 0xd8, 0xb5, 0x23, 0xe8, 0x61, 0x14, - 0x14, 0x90, 0xe6, 0x5e, 0x32, 0xca, 0x26, 0x06, 0x7e, 0xeb, 0x25, 0xb0, 0xdd, 0xfb, 0xad, 0x7d, 0x64, 0x77, 0xe2, - 0x95, 0x79, 0x15, 0xf4, 0x8e, 0x44, 0x8d, 0x08, 0x55, 0xdb, 0x0e, 0x71, 0x7d, 0xe5, 0xd8, 0xc4, 0xa6, 0x2c, 0x57, - 0x4c, 0xb8, 0xf8, 0x0d, 0xa0, 0x20, 0x4b, 0x72, 0x08, 0x3a, 0x44, 0x4e, 0x1b, 0xdc, 0x39, 0x3a, 0xd5, 0xa3, 0x16, - 0x7f, 0xe6, 0x0b, 0xf4, 0xb8, 0x26, 0x94, 0x51, 0x40, 0x3b, 0x50, 0xf0, 0x99, 0xec, 0xa0, 0xab, 0x55, 0x76, 0x99, - 0xad, 0xb1, 0x81, 0x08, 0x10, 0x52, 0xd1, 0x9f, 0xa6, 0xa7, 0x05, 0x5d, 0xc2, 0xa5, 0x46, 0x0e, 0xda, 0x97, 0xca, - 0x30, 0x0e, 0x75, 0x74, 0x7d, 0x2a, 0x8f, 0x5f, 0x0d, 0x2c, 0x01, 0xe0, 0xe8, 0x33, 0x08, 0x3b, 0xf8, 0x6c, 0xe7, - 0x8a, 0xc5, 0x65, 0xd0, 0x1d, 0x18, 0xd2, 0xbe, 0xda, 0xb9, 0xea, 0xa7, 0xe8, 0xb7, 0xf6, 0x2e, 0xbe, 0x54, 0xd8, - 0x33, 0x2a, 0xb1, 0x46, 0xe8, 0x10, 0x99, 0x71, 0x8d, 0xbc, 0x7b, 0xcf, 0xbd, 0x1f, 0xdb, 0xe8, 0x15, 0x6c, 0xa1, - 0x4b, 0x48, 0x66, 0x05, 0x2e, 0xfc, 0x47, 0x80, 0x0b, 0x0f, 0x8d, 0x9e, 0x05, 0x56, 0x94, 0x32, 0x03, 0x37, 0x92, - 0xdf, 0xec, 0x1d, 0x2c, 0xb3, 0xf4, 0x96, 0xf0, 0x84, 0xb2, 0x36, 0xca, 0x02, 0x9b, 0x60, 0x9f, 0x1a, 0xa2, 0x3d, - 0x74, 0xfc, 0xa0, 0xfd, 0x09, 0xa7, 0x7f, 0x7f, 0xea, 0x09, 0x1a, 0x0b, 0x3e, 0x46, 0x16, 0xf1, 0x87, 0x69, 0x2f, - 0xdd, 0xed, 0x67, 0x86, 0x46, 0x88, 0x20, 0xde, 0x9a, 0xa5, 0x33, 0x52, 0x49, 0xa5, 0x99, 0x6a, 0xde, 0xef, 0x40, - 0xb0, 0x5b, 0x52, 0x82, 0xdd, 0x08, 0x8b, 0x27, 0xde, 0xb3, 0xf6, 0xe5, 0x05, 0x31, 0x61, 0x31, 0xc5, 0x64, 0xed, - 0x11, 0x40, 0xf1, 0x2e, 0xdc, 0x44, 0x94, 0x74, 0xe5, 0xc7, 0x22, 0x19, 0xc9, 0x9f, 0x49, 0x34, 0x17, 0x49, 0x49, - 0xaf, 0xdd, 0x65, 0x7a, 0xb6, 0x02, 0x55, 0x79, 0xbb, 0xe7, 0x46, 0xed, 0x11, 0x36, 0xbe, 0x1b, 0xd4, 0x81, 0x0f, - 0xc8, 0xf5, 0x2c, 0x71, 0x78, 0xff, 0x12, 0x06, 0x34, 0x14, 0xcb, 0x96, 0x10, 0x17, 0x39, 0xee, 0xf3, 0x95, 0xfa, - 0xc0, 0x38, 0x21, 0x2c, 0xf0, 0xf5, 0x22, 0xd0, 0x9a, 0x83, 0xc4, 0xf7, 0x2b, 0x7e, 0xe1, 0x89, 0x82, 0xfa, 0x78, - 0x71, 0xda, 0x3f, 0xea, 0x4d, 0x5f, 0xd5, 0x4c, 0x93, 0xf3, 0x89, 0x90, 0x50, 0x3e, 0xcf, 0xb3, 0x50, 0x3a, 0x86, - 0x49, 0x8e, 0x4f, 0xfa, 0xe2, 0x92, 0x2e, 0x7c, 0x0c, 0xab, 0xf6, 0x57, 0xa3, 0xb0, 0xea, 0xe2, 0x7d, 0xd2, 0x67, - 0xf4, 0xcb, 0x15, 0x56, 0x8d, 0xf6, 0x0b, 0x17, 0x46, 0x75, 0x28, 0xa9, 0xaf, 0x80, 0x00, 0x06, 0xee, 0x70, 0xc7, - 0xaf, 0x13, 0x35, 0x0d, 0x69, 0xb5, 0x86, 0x20, 0x17, 0xfa, 0x0f, 0x7e, 0x07, 0xbf, 0x6f, 0x39, 0x48, 0x22, 0x07, - 0x1a, 0x3a, 0x94, 0x06, 0x58, 0x69, 0x50, 0x19, 0x54, 0x90, 0xe1, 0xd1, 0xd9, 0x29, 0x72, 0x4b, 0xa2, 0x0a, 0x0c, - 0x35, 0xf5, 0xd4, 0x51, 0x99, 0x00, 0xaf, 0x40, 0xed, 0x07, 0x67, 0x15, 0x21, 0xfa, 0x6b, 0x49, 0x0b, 0xea, 0x14, - 0xe9, 0xf3, 0x4b, 0x0b, 0x40, 0xec, 0x2f, 0x22, 0xdd, 0x69, 0xf8, 0xa4, 0xee, 0x3b, 0x32, 0x00, 0xae, 0x7c, 0x03, - 0x22, 0x20, 0x92, 0xb8, 0xb3, 0x0c, 0x5a, 0xc9, 0x4f, 0xe4, 0x3a, 0x27, 0x51, 0xaa, 0x8b, 0xb2, 0x02, 0x74, 0x6b, - 0x28, 0xe9, 0x2f, 0xda, 0xd1, 0x84, 0xd7, 0xcf, 0x77, 0x38, 0x16, 0xe8, 0x9f, 0x8e, 0xff, 0xb5, 0x40, 0x5a, 0x1a, - 0x02, 0xd7, 0x5b, 0x65, 0x18, 0xd4, 0x77, 0x8a, 0xc0, 0xbc, 0x44, 0xa5, 0x01, 0x25, 0x01, 0xeb, 0x95, 0xfa, 0xfb, - 0x6f, 0x75, 0xf4, 0x15, 0xa8, 0xdd, 0x3a, 0xfa, 0xa9, 0xe7, 0x7b, 0xf8, 0x83, 0xf4, 0x56, 0x3b, 0x40, 0x7f, 0x9c, - 0x67, 0xaa, 0x3f, 0x74, 0x76, 0x3d, 0x62, 0x30, 0x27, 0xe0, 0x82, 0x8c, 0x73, 0x92, 0x1f, 0xc1, 0x56, 0xfc, 0x0f, - 0x8b, 0x54, 0x63, 0xd2, 0xfd, 0xa3, 0x15, 0x78, 0x0d, 0x5d, 0x6a, 0x72, 0x4e, 0xe1, 0x0a, 0xa8, 0x1c, 0xaa, 0xeb, - 0x9c, 0x8a, 0x95, 0x64, 0xe6, 0xbf, 0xac, 0x60, 0xf3, 0xa8, 0x14, 0xa7, 0xcb, 0x0f, 0xaf, 0x5c, 0x62, 0xed, 0xc9, - 0xc5, 0x2f, 0x6e, 0x18, 0x9f, 0x52, 0xef, 0xce, 0xf7, 0xd4, 0x93, 0x0f, 0x3b, 0x26, 0x3f, 0xc0, 0x4f, 0x1f, 0xf6, - 0x9d, 0xe5, 0x94, 0x4f, 0x3f, 0xf9, 0xa5, 0xdf, 0xea, 0xd7, 0x3c, 0xf7, 0x03, 0x77, 0x66, 0x3b, 0xec, 0x1f, 0x09, - 0x6f, 0xa6, 0xcb, 0xbb, 0x86, 0x65, 0xeb, 0x15, 0x93, 0xaf, 0x97, 0x42, 0x9f, 0xfe, 0xe2, 0xfa, 0xa3, 0x07, 0xee, - 0x3d, 0x87, 0x92, 0x66, 0x1c, 0xd5, 0xb9, 0x39, 0x6b, 0xb0, 0xa5, 0x6d, 0x1c, 0x4d, 0x82, 0xad, 0x81, 0x30, 0x19, - 0x1a, 0xa1, 0x89, 0x0a, 0x7a, 0xed, 0x82, 0x52, 0xc1, 0x50, 0x9a, 0xe3, 0xb8, 0x7e, 0x32, 0x09, 0x84, 0xda, 0x22, - 0xa2, 0x6e, 0x4d, 0xab, 0x6c, 0x7c, 0xb0, 0x10, 0x70, 0x06, 0x15, 0xc6, 0x90, 0xdc, 0xeb, 0x0e, 0x04, 0xa6, 0x90, - 0x34, 0xc4, 0xf8, 0x53, 0xf9, 0x38, 0x8a, 0xe2, 0xba, 0x0a, 0x5f, 0x1f, 0xdc, 0x74, 0xe3, 0x94, 0xa3, 0x84, 0x8a, - 0xf2, 0x8e, 0x04, 0x6a, 0x8a, 0x16, 0x6c, 0x29, 0x32, 0x97, 0x23, 0x16, 0xc9, 0x9d, 0xc6, 0xe5, 0x18, 0x42, 0x41, - 0x3a, 0xd0, 0xe9, 0xc4, 0x4a, 0x21, 0xb1, 0x55, 0x21, 0x24, 0x08, 0xcd, 0x6e, 0xcb, 0x6b, 0x15, 0x50, 0x4e, 0xea, - 0xdf, 0xd3, 0x16, 0xf8, 0xba, 0x97, 0xe7, 0xf8, 0xa6, 0x95, 0xce, 0xab, 0xdc, 0xf3, 0xfc, 0xe0, 0xf9, 0xed, 0xf6, - 0x7b, 0x7c, 0x34, 0x63, 0xd5, 0x84, 0x8d, 0x1f, 0xf7, 0x31, 0x21, 0xd4, 0x02, 0x55, 0x04, 0x08, 0xad, 0xb2, 0x06, - 0xd6, 0x75, 0xc8, 0x2c, 0xa1, 0xe1, 0xeb, 0x9f, 0x3a, 0xe4, 0x88, 0x1b, 0x6c, 0xc2, 0x9b, 0xb0, 0xc8, 0xc3, 0x51, - 0x47, 0x7b, 0x03, 0xae, 0xb5, 0x70, 0x40, 0x29, 0x50, 0x67, 0x4b, 0xce, 0x12, 0x41, 0xd4, 0x2d, 0xb3, 0x30, 0x55, - 0xe9, 0x2c, 0xaf, 0x3c, 0x3f, 0x82, 0x5e, 0xb3, 0xbf, 0xd6, 0x49, 0xf0, 0xe4, 0xe9, 0x6c, 0x69, 0x6d, 0x43, 0x81, - 0x9b, 0xd2, 0x2a, 0x9f, 0xac, 0x6d, 0x3c, 0xfa, 0xb1, 0x4f, 0x92, 0x12, 0xba, 0xc4, 0x27, 0x41, 0xea, 0x93, 0xbc, - 0x4b, 0x4b, 0xd7, 0x87, 0x2e, 0xb9, 0x36, 0x54, 0x35, 0x77, 0x23, 0xa6, 0xf2, 0xc3, 0x1b, 0x9a, 0x77, 0xf2, 0x2d, - 0xd2, 0xfd, 0x00, 0xff, 0xfb, 0xb0, 0x33, 0x4e, 0xf9, 0xef, 0x27, 0xff, 0x94, 0x47, 0x76, 0x1d, 0x42, 0xb5, 0x97, - 0x29, 0x78, 0xdf, 0xe6, 0xa3, 0x5f, 0xae, 0xad, 0x46, 0x71, 0x3d, 0xfe, 0xd9, 0xaf, 0x42, 0xf5, 0xf4, 0x17, 0xcb, - 0x8c, 0x4b, 0xdf, 0x4e, 0xd9, 0xcc, 0x2f, 0x8e, 0x39, 0xf3, 0xdc, 0x70, 0xd3, 0x2d, 0xda, 0x90, 0x5e, 0x21, 0xec, - 0xd4, 0xe5, 0x49, 0x17, 0x7d, 0xae, 0x88, 0x7b, 0x71, 0x12, 0x45, 0x0f, 0x51, 0x16, 0x87, 0xd6, 0x94, 0xd3, 0xcc, - 0xec, 0xa3, 0x58, 0x37, 0x1d, 0x29, 0x60, 0x08, 0x17, 0xb0, 0xe0, 0x17, 0x9f, 0x69, 0x3c, 0x63, 0x73, 0xe6, 0xf0, - 0x3f, 0x78, 0x50, 0xb2, 0xcc, 0x19, 0x0f, 0xf2, 0x55, 0x2d, 0x59, 0xbe, 0xe9, 0x60, 0xed, 0xe4, 0x7e, 0x00, 0x7f, - 0x99, 0x59, 0xd3, 0xe1, 0x92, 0x7e, 0x9b, 0xdd, 0xfa, 0x83, 0xd6, 0x52, 0x1e, 0x74, 0x10, 0xb4, 0xd6, 0xa7, 0xfd, - 0x4d, 0x4c, 0xea, 0x03, 0xbe, 0xd5, 0x1c, 0x6c, 0x97, 0xee, 0x9c, 0x47, 0x33, 0x45, 0xfb, 0x95, 0x69, 0x6e, 0xef, - 0xf0, 0x3a, 0x13, 0xad, 0x88, 0xb8, 0x3c, 0x54, 0xf1, 0xd9, 0x0d, 0xe7, 0xc8, 0xcc, 0xee, 0x70, 0x9f, 0x1e, 0x28, - 0x1e, 0x90, 0xcd, 0x15, 0xda, 0x79, 0xf0, 0x10, 0xab, 0xcd, 0x3c, 0xd4, 0x8e, 0xf9, 0xde, 0x74, 0x6e, 0x18, 0xaf, - 0x0c, 0xae, 0x49, 0xa3, 0xe0, 0x7a, 0xbe, 0x35, 0xde, 0x3d, 0x93, 0x3a, 0xea, 0x6c, 0x47, 0x1b, 0xd0, 0x2a, 0xb5, - 0x6b, 0xb2, 0x7a, 0x47, 0xb4, 0x9b, 0xc5, 0xbf, 0x5f, 0x85, 0xeb, 0x7b, 0x07, 0x7b, 0x7e, 0xe3, 0x30, 0x94, 0xa3, - 0x0f, 0xb1, 0xbb, 0xca, 0xff, 0x14, 0x2d, 0xab, 0x6e, 0xad, 0xbb, 0x3a, 0xed, 0xde, 0x49, 0xba, 0xa4, 0xac, 0x8f, - 0x60, 0x30, 0x39, 0x39, 0x77, 0x1d, 0xa5, 0x42, 0x3f, 0x86, 0x9f, 0xa4, 0xbc, 0x3c, 0x5d, 0x1f, 0xd6, 0x79, 0x09, - 0xbd, 0x70, 0xd8, 0x49, 0xeb, 0x1f, 0xbf, 0x5f, 0xe0, 0x13, 0x98, 0x9a, 0x5e, 0x37, 0xa3, 0x61, 0x51, 0x48, 0xda, - 0x1f, 0xc3, 0xce, 0xa5, 0xf1, 0x1b, 0xaa, 0xff, 0xe0, 0xa8, 0x22, 0xb8, 0x3a, 0x2e, 0xb5, 0xa2, 0x8a, 0xef, 0xb3, - 0x4d, 0xdd, 0x62, 0x41, 0xd8, 0xbf, 0x13, 0x39, 0x6a, 0x0c, 0x35, 0x55, 0x5c, 0x5b, 0x54, 0x04, 0x04, 0x89, 0x8b, - 0xfc, 0x5c, 0x3c, 0xac, 0xba, 0x17, 0xbc, 0x29, 0x2a, 0xd0, 0xed, 0x2b, 0x04, 0x55, 0x4e, 0x0a, 0xa6, 0x99, 0xec, - 0x5c, 0x17, 0x7d, 0x5a, 0x7f, 0xda, 0x52, 0xe8, 0x81, 0x70, 0x4c, 0x58, 0x82, 0x85, 0x8a, 0x3b, 0xc8, 0xc1, 0xd3, - 0xe3, 0xf6, 0x82, 0x1f, 0xab, 0x18, 0xed, 0xf8, 0x44, 0x32, 0x07, 0xeb, 0x92, 0x71, 0x03, 0x0f, 0x8e, 0x95, 0x86, - 0xe1, 0x58, 0x01, 0x70, 0x68, 0x76, 0x75, 0x22, 0x7f, 0x68, 0x46, 0xf0, 0x57, 0x24, 0x43, 0xeb, 0x12, 0x35, 0x85, - 0x06, 0xd6, 0x32, 0x7a, 0xae, 0x98, 0x78, 0x31, 0x05, 0x9d, 0x80, 0x20, 0xcb, 0x93, 0x43, 0x7a, 0xb8, 0x8b, 0x64, - 0x51, 0xbd, 0x67, 0x17, 0x8b, 0x48, 0x97, 0x81, 0x06, 0xd3, 0x20, 0xa4, 0xc3, 0x6a, 0xba, 0x6a, 0x6f, 0xee, 0x91, - 0xa5, 0x79, 0x4c, 0x8c, 0x95, 0x86, 0x9e, 0xd5, 0x38, 0xb0, 0xe1, 0x96, 0x09, 0x0b, 0x87, 0xc4, 0xd1, 0xc9, 0x61, - 0x15, 0x91, 0xa0, 0x59, 0xdf, 0x82, 0xac, 0x74, 0x00, 0x1b, 0xf0, 0x30, 0xaf, 0x2e, 0xb1, 0xbb, 0x6d, 0xcd, 0x22, - 0x9e, 0x59, 0x86, 0x61, 0x5d, 0xfc, 0xa7, 0xae, 0x39, 0x61, 0xfb, 0xdf, 0x3c, 0x1e, 0x1e, 0x8b, 0xae, 0x36, 0x16, - 0x4b, 0xb1, 0x07, 0x3d, 0xa2, 0xfb, 0xc3, 0xc7, 0xc3, 0x9b, 0xc0, 0x24, 0x3e, 0xe9, 0x67, 0x16, 0x34, 0x13, 0xdb, - 0xd9, 0xe8, 0x09, 0xfb, 0x68, 0x9b, 0x62, 0x87, 0x54, 0x60, 0x51, 0xd3, 0xd9, 0x09, 0xd5, 0x69, 0x68, 0x24, 0x69, - 0x86, 0x50, 0x58, 0xed, 0x0d, 0x7e, 0x11, 0x62, 0x6f, 0xaf, 0xfb, 0x7b, 0x0e, 0x62, 0x2d, 0x06, 0xa8, 0x41, 0x4d, - 0x8b, 0xc4, 0xee, 0xd2, 0xdd, 0x33, 0x5e, 0x02, 0x55, 0x1d, 0x95, 0x43, 0x0a, 0xb3, 0x5c, 0x8c, 0x68, 0x43, 0x27, - 0x59, 0x62, 0x1d, 0x93, 0xa9, 0x94, 0xb8, 0xfe, 0xbb, 0x04, 0x12, 0x14, 0x1e, 0xd9, 0x91, 0x70, 0xcb, 0x9f, 0x27, - 0xfc, 0xf9, 0x0b, 0xb6, 0x1a, 0x6c, 0xa7, 0x00, 0x5c, 0x3e, 0xfa, 0xfc, 0x0e, 0xe4, 0x2f, 0x54, 0x0c, 0xfc, 0xbc, - 0x70, 0xc2, 0x0b, 0xf0, 0x4f, 0xb0, 0x14, 0x89, 0xe9, 0x5e, 0x4a, 0xf3, 0x14, 0x6b, 0x98, 0x40, 0xaf, 0xcb, 0x7e, - 0xd9, 0x02, 0x87, 0x11, 0xc4, 0xa5, 0xee, 0xdb, 0x05, 0xb4, 0x51, 0x01, 0x28, 0x8b, 0x6a, 0xe0, 0x58, 0xc7, 0xdb, - 0x26, 0x45, 0xdc, 0xf4, 0xab, 0x04, 0x99, 0xd1, 0x2b, 0xb1, 0xb8, 0x0c, 0x5d, 0x5b, 0x39, 0x4e, 0x53, 0xf4, 0x99, - 0x0c, 0x36, 0xcc, 0x3a, 0x15, 0x81, 0x99, 0xf4, 0xf0, 0xa0, 0x6f, 0xd3, 0x9a, 0x6f, 0xd7, 0xf5, 0xf2, 0x6e, 0x93, - 0x5f, 0x77, 0x7c, 0xf9, 0xea, 0xc9, 0x85, 0x94, 0x48, 0x5b, 0xa0, 0x5b, 0xaa, 0xa7, 0xc5, 0xd6, 0xba, 0xd1, 0xf4, - 0xb8, 0xc2, 0xf0, 0x50, 0x19, 0x4d, 0xfd, 0x69, 0x52, 0x98, 0xcd, 0x16, 0xdd, 0xe8, 0x63, 0xff, 0x4a, 0x02, 0x0d, - 0x96, 0x2d, 0xf5, 0xde, 0x9b, 0x05, 0x0b, 0x7a, 0xeb, 0x20, 0x6b, 0xb9, 0xca, 0x91, 0x7b, 0x42, 0x51, 0x5d, 0x20, - 0x28, 0xf2, 0xb0, 0x48, 0x2b, 0xdc, 0x99, 0xbd, 0xcc, 0x06, 0xf4, 0x21, 0xe3, 0x4a, 0xee, 0x9c, 0x03, 0x25, 0xd3, - 0xe6, 0x4d, 0x7a, 0xef, 0x2f, 0x76, 0x7a, 0xec, 0xde, 0x41, 0x86, 0xe5, 0xff, 0x8d, 0xea, 0x6a, 0xbe, 0x25, 0x45, - 0x0a, 0x8f, 0xa2, 0x7d, 0xac, 0x4a, 0xe1, 0x3b, 0xc2, 0x56, 0x0a, 0x54, 0x07, 0xda, 0x57, 0xa4, 0x2e, 0x61, 0x6e, - 0xd6, 0x41, 0x60, 0x65, 0x3a, 0xfc, 0x2b, 0x52, 0x03, 0x7e, 0xb3, 0x05, 0x44, 0x88, 0x9d, 0xec, 0x21, 0x7c, 0x14, - 0x00, 0xc7, 0x15, 0x00, 0xcd, 0x88, 0xdc, 0xe0, 0xe4, 0xe0, 0x21, 0xee, 0x8f, 0x57, 0x77, 0x59, 0x51, 0xe1, 0xbd, - 0x45, 0x58, 0x07, 0xf0, 0xd7, 0x72, 0xb8, 0x9e, 0x97, 0xfe, 0xc2, 0x87, 0xea, 0x09, 0x2a, 0x77, 0xee, 0xeb, 0x82, - 0xa1, 0x3c, 0x95, 0x38, 0x36, 0xd0, 0x55, 0x79, 0x6b, 0xaf, 0xb4, 0x99, 0x04, 0xbb, 0x1b, 0xa1, 0xa9, 0x0e, 0xa3, - 0x21, 0x6e, 0x7e, 0x5b, 0xd9, 0xfa, 0xc3, 0xc5, 0xed, 0x9f, 0xdf, 0x9d, 0x0b, 0x3f, 0xc0, 0x25, 0x06, 0x6c, 0xea, - 0x20, 0xc4, 0x7e, 0xe7, 0xdc, 0x04, 0x42, 0x88, 0x3d, 0x06, 0x93, 0x29, 0x62, 0x26, 0x34, 0x95, 0xa3, 0x10, 0x82, - 0x49, 0xde, 0x52, 0x6d, 0xc8, 0x85, 0x07, 0xd9, 0x21, 0x33, 0x65, 0x6a, 0x13, 0xc2, 0x26, 0xdc, 0xb6, 0x8d, 0x75, - 0x73, 0x65, 0x31, 0x36, 0x77, 0x5b, 0x7d, 0x61, 0x45, 0xe8, 0xed, 0x5d, 0xdf, 0xea, 0xdc, 0xee, 0x9a, 0xfc, 0x08, - 0x3a, 0x64, 0xef, 0x8a, 0x0a, 0x07, 0xbb, 0x93, 0xd3, 0x45, 0xd2, 0x6c, 0x08, 0x24, 0x16, 0x08, 0x81, 0x5f, 0x68, - 0x68, 0x86, 0x8c, 0xf1, 0xc8, 0x2b, 0xdf, 0xb8, 0x2a, 0x3b, 0xf6, 0x12, 0x54, 0xbd, 0x87, 0x98, 0x73, 0x9f, 0x86, - 0x75, 0x1c, 0xc9, 0x61, 0xea, 0x66, 0xe8, 0x87, 0xb0, 0xdd, 0x24, 0x71, 0x99, 0x8e, 0xe4, 0x3e, 0xbb, 0xbf, 0xf4, - 0x7c, 0x37, 0x6a, 0xe1, 0x22, 0xda, 0x14, 0x50, 0x8f, 0x48, 0x76, 0xea, 0xda, 0x8b, 0xf4, 0x63, 0x8e, 0xc4, 0x5d, - 0xd9, 0x5a, 0xd2, 0xfc, 0x28, 0xa0, 0x21, 0x3a, 0xa3, 0xf8, 0xd2, 0xcf, 0x46, 0x7b, 0x9a, 0xff, 0xea, 0x87, 0xab, - 0xb3, 0xff, 0xd1, 0xae, 0x44, 0xa1, 0xe2, 0xc9, 0x31, 0xd0, 0x36, 0x5f, 0x92, 0x72, 0x1d, 0x4b, 0x64, 0x9c, 0xd7, - 0x86, 0x77, 0xcb, 0x06, 0x82, 0x3d, 0xea, 0x1c, 0xd1, 0xfa, 0x05, 0x76, 0x08, 0xdd, 0xd9, 0xd1, 0x40, 0xd7, 0x1e, - 0xfa, 0xe7, 0xfa, 0xdf, 0xfe, 0xe7, 0xd6, 0xae, 0x52, 0x6a, 0xa9, 0x1e, 0x72, 0x47, 0xe5, 0x25, 0x09, 0xd1, 0x01, - 0xa8, 0x48, 0x23, 0x70, 0x5f, 0x6e, 0xad, 0xf9, 0x5d, 0x59, 0x67, 0xfe, 0xa7, 0x05, 0x63, 0x24, 0x72, 0x7a, 0x43, - 0x48, 0xd8, 0x84, 0x24, 0x8e, 0x9d, 0xeb, 0x8c, 0xb3, 0xa4, 0x69, 0x11, 0xba, 0xba, 0x53, 0x8f, 0x04, 0xcb, 0x93, - 0x36, 0xcb, 0xb8, 0x21, 0x5b, 0x6e, 0xbb, 0x49, 0xfa, 0xe8, 0xe7, 0xae, 0xd5, 0x5c, 0x01, 0x41, 0x50, 0xb5, 0x2c, - 0x2f, 0x8d, 0xc8, 0xab, 0x0d, 0xf7, 0x65, 0xf9, 0x6b, 0xf7, 0x53, 0x18, 0x69, 0x51, 0x1b, 0x9c, 0x72, 0xd6, 0xad, - 0x7a, 0x50, 0x2d, 0x45, 0x19, 0x59, 0xf5, 0x21, 0xfa, 0x4f, 0x70, 0x83, 0x97, 0x77, 0x37, 0x47, 0x2f, 0xa6, 0x16, - 0x5e, 0x70, 0x24, 0x67, 0xe2, 0xee, 0xfc, 0x28, 0x4b, 0xec, 0x65, 0xd0, 0x97, 0x88, 0xea, 0x9c, 0x18, 0x6f, 0x8a, - 0x67, 0x06, 0xa2, 0xdb, 0xd4, 0xf7, 0x4d, 0x70, 0x90, 0xf1, 0x0d, 0xb2, 0x3f, 0x27, 0x48, 0x4e, 0x7d, 0xa2, 0xf1, - 0x32, 0x98, 0xb6, 0x23, 0x05, 0xc7, 0xc7, 0x76, 0x0f, 0x38, 0xde, 0xc8, 0xe5, 0x42, 0xf5, 0xad, 0xbb, 0xff, 0xc3, - 0xea, 0x61, 0x76, 0x06, 0xc7, 0x9d, 0x4d, 0xcb, 0x04, 0xaf, 0x58, 0xe2, 0x4f, 0xb5, 0x89, 0xdd, 0x9e, 0x4d, 0xba, - 0xe3, 0x72, 0x7b, 0x38, 0xbb, 0x0b, 0xad, 0x51, 0xee, 0x36, 0x7f, 0x01, 0x48, 0x21, 0xd0, 0x86, 0xfd, 0xa2, 0x70, - 0x10, 0xd4, 0x00, 0x1f, 0x00, 0x23, 0xb4, 0xc4, 0x62, 0x45, 0x9e, 0x68, 0x28, 0xad, 0x72, 0x46, 0x4c, 0x83, 0xe7, - 0x83, 0x77, 0x95, 0xc4, 0xa5, 0xf4, 0x77, 0x61, 0x73, 0x4b, 0x89, 0xcf, 0x9c, 0x7e, 0x7c, 0x9b, 0xea, 0xbb, 0x2e, - 0x39, 0x5b, 0xbe, 0xf7, 0x9c, 0x56, 0x1a, 0x3a, 0xb8, 0x83, 0x8f, 0xd5, 0x16, 0x42, 0x36, 0x6e, 0xa0, 0xdb, 0xec, - 0x0f, 0xb9, 0x67, 0xe7, 0xa9, 0x62, 0x4f, 0xb2, 0x5c, 0x58, 0xac, 0x08, 0x17, 0xae, 0xde, 0x2d, 0x02, 0x58, 0x90, - 0xef, 0x43, 0x1f, 0xcb, 0xac, 0xe4, 0xc7, 0x0f, 0xfc, 0xcf, 0x83, 0x00, 0x8b, 0x92, 0xe5, 0x34, 0xa1, 0xca, 0x9d, - 0x41, 0xcc, 0xb3, 0x9e, 0x91, 0x35, 0x9b, 0x7c, 0xe8, 0x00}; + 0x5b, 0x90, 0x7a, 0x53, 0xc1, 0x6e, 0xc1, 0x56, 0x6f, 0x00, 0x79, 0xaf, 0xf6, 0x6d, 0x2b, 0x05, 0x44, 0x11, 0x6c, + 0x9c, 0x06, 0x03, 0x82, 0x71, 0xa5, 0x64, 0xba, 0x39, 0x78, 0xe4, 0x76, 0x00, 0x6c, 0xbb, 0xaa, 0xb6, 0x41, 0xaa, + 0x9a, 0x70, 0x54, 0x0e, 0x31, 0xb1, 0x27, 0x5a, 0x0c, 0xe6, 0x4f, 0xe4, 0x1a, 0x89, 0x16, 0xe8, 0x24, 0x0c, 0xc4, + 0xa0, 0x60, 0x71, 0x7b, 0x07, 0x92, 0xb2, 0x62, 0xb6, 0x5c, 0x32, 0xac, 0x0d, 0x63, 0xd8, 0x38, 0xf8, 0xf0, 0x15, + 0xdd, 0xce, 0xfe, 0x4e, 0x15, 0x9d, 0xab, 0xfb, 0x0e, 0x21, 0x59, 0x85, 0x78, 0xe1, 0xae, 0xca, 0x1f, 0x7a, 0x37, + 0xc2, 0x07, 0x0d, 0xc2, 0x31, 0x1f, 0x88, 0x73, 0x48, 0x2a, 0x4c, 0xba, 0xd2, 0xbd, 0x41, 0xc1, 0xe2, 0x9d, 0x07, + 0x35, 0xb2, 0xf3, 0xee, 0xab, 0xbf, 0x18, 0xc2, 0xf6, 0xaa, 0xb0, 0x9f, 0xb5, 0xd2, 0xfa, 0x3f, 0xf6, 0x7d, 0x54, + 0x0b, 0xb3, 0xd2, 0xab, 0x5f, 0x04, 0x6e, 0xfc, 0x69, 0xbd, 0x97, 0x2e, 0xb2, 0x64, 0x16, 0xef, 0x3e, 0x91, 0x2b, + 0x71, 0x11, 0xbe, 0xcd, 0xb8, 0x53, 0x58, 0x09, 0xdb, 0x0f, 0x9b, 0x37, 0x7d, 0x0d, 0x07, 0x83, 0x1b, 0x9b, 0xc5, + 0xa1, 0xa2, 0xe7, 0xc8, 0x8e, 0x39, 0x27, 0x54, 0x9d, 0x10, 0x84, 0x65, 0x80, 0xed, 0x72, 0x63, 0x84, 0x60, 0x65, + 0x09, 0x3d, 0x91, 0xd0, 0x17, 0xe9, 0x5b, 0x6f, 0xa9, 0xff, 0x5f, 0xbf, 0x19, 0xbe, 0x8d, 0x2c, 0x45, 0xbe, 0xa4, + 0xee, 0xb2, 0x8e, 0xab, 0xf6, 0x25, 0xb1, 0x13, 0xcf, 0x4b, 0x29, 0x70, 0xf3, 0x70, 0x1a, 0x71, 0xeb, 0x60, 0x02, + 0x80, 0xb6, 0x64, 0x56, 0x7e, 0x96, 0xa9, 0xdf, 0x79, 0x7a, 0x39, 0xd9, 0x2f, 0x99, 0x06, 0xff, 0x44, 0x32, 0x0f, + 0x49, 0x5e, 0x9a, 0x51, 0x37, 0x3b, 0xfb, 0xea, 0x76, 0x1c, 0x8c, 0x90, 0x44, 0x3f, 0x06, 0x17, 0x50, 0x96, 0xaa, + 0xbd, 0x5f, 0x7a, 0xef, 0xaf, 0xf5, 0xfd, 0xd7, 0x2f, 0x5d, 0xbd, 0x98, 0x7a, 0x54, 0x54, 0x66, 0xf6, 0xc2, 0xc0, + 0xdd, 0x76, 0xe7, 0x2e, 0x2b, 0xed, 0xa5, 0x51, 0x22, 0x72, 0x9a, 0x0e, 0x3e, 0x12, 0x5b, 0x1c, 0xc8, 0x2c, 0x36, + 0xad, 0x5e, 0xff, 0xd9, 0xc6, 0xde, 0xf5, 0x2f, 0x57, 0xd3, 0x1a, 0x69, 0xe5, 0x0a, 0xe3, 0xd8, 0x0a, 0x88, 0x38, + 0x12, 0x2b, 0xcb, 0xa4, 0xf8, 0x6a, 0xf6, 0xed, 0x74, 0x85, 0x3d, 0xf9, 0x75, 0x53, 0x96, 0xb5, 0xff, 0x7b, 0xbe, + 0x86, 0x1b, 0x47, 0xce, 0x65, 0xb3, 0x5a, 0xcf, 0xc4, 0x52, 0x94, 0x87, 0x12, 0x77, 0x36, 0x60, 0xdf, 0x57, 0xb5, + 0xaf, 0xdf, 0x23, 0x5f, 0x9e, 0x0f, 0xce, 0x24, 0x3b, 0x36, 0x75, 0x59, 0x4e, 0x87, 0x73, 0xc9, 0x5b, 0x75, 0xaf, + 0xd5, 0xf9, 0xc5, 0xac, 0x8c, 0x54, 0x48, 0x14, 0x20, 0x21, 0xd0, 0x29, 0x79, 0xdf, 0x57, 0x7d, 0xff, 0xeb, 0x5b, + 0x3a, 0x29, 0x0a, 0x95, 0xb2, 0x2b, 0xa8, 0x63, 0xa2, 0xe3, 0x75, 0x6c, 0xdf, 0x39, 0xfc, 0x18, 0x1a, 0xb2, 0x94, + 0xc3, 0x80, 0xbe, 0x24, 0x95, 0x09, 0xf8, 0xff, 0xfa, 0x9a, 0xbd, 0xff, 0xef, 0x9f, 0x2f, 0x89, 0x68, 0x95, 0xd8, + 0xd4, 0x2a, 0x4a, 0xb2, 0xe7, 0x73, 0x48, 0xd2, 0xd3, 0x9b, 0xc7, 0x76, 0x85, 0xc0, 0xba, 0xdc, 0x6e, 0x7a, 0x80, + 0x0e, 0x40, 0x9e, 0xb2, 0xf6, 0x31, 0x97, 0x55, 0xf5, 0x16, 0x15, 0x12, 0xf1, 0xeb, 0xf6, 0xfd, 0x8c, 0xfb, 0x98, + 0x6e, 0x60, 0x06, 0xc3, 0x46, 0x9e, 0x13, 0x8c, 0xeb, 0xf9, 0x69, 0xea, 0xe7, 0xe9, 0x2a, 0x78, 0x61, 0x23, 0x4f, + 0x7e, 0x1c, 0x0f, 0xab, 0x28, 0x12, 0x09, 0xd3, 0xda, 0x39, 0x9d, 0xdb, 0xf5, 0xd3, 0xfa, 0xf6, 0x79, 0x78, 0x48, + 0x3e, 0xa0, 0x56, 0xdf, 0xf0, 0xfb, 0x5f, 0x6f, 0xba, 0xfe, 0xeb, 0xd7, 0xee, 0xe2, 0x89, 0x73, 0xd1, 0x91, 0x52, + 0x09, 0x6f, 0xbd, 0x9a, 0x4b, 0xb3, 0xac, 0xf5, 0xc8, 0x52, 0x38, 0xac, 0x2a, 0xd7, 0x60, 0xac, 0x26, 0xa3, 0x19, + 0x23, 0xbb, 0xd4, 0x9d, 0x41, 0xc1, 0x6a, 0xfb, 0xd4, 0xb7, 0xf7, 0x8b, 0x52, 0x6b, 0xaa, 0x86, 0x85, 0x26, 0x1a, + 0x47, 0xb6, 0x43, 0x90, 0x4d, 0xbc, 0xfd, 0x26, 0x09, 0x1e, 0x02, 0x5a, 0xc2, 0xec, 0xb0, 0x56, 0x0f, 0xbc, 0x2b, + 0x52, 0xd7, 0x76, 0xad, 0x70, 0xf9, 0xa6, 0xfa, 0x5f, 0xbf, 0x91, 0x87, 0x33, 0xa5, 0x7a, 0xd2, 0xed, 0x3b, 0xbe, + 0x94, 0x8b, 0xb9, 0xda, 0x9a, 0x8e, 0x5e, 0x22, 0xe7, 0xf2, 0x64, 0xd0, 0xc5, 0xcd, 0x04, 0x04, 0xf0, 0x76, 0x17, + 0x24, 0x20, 0x8d, 0x0b, 0x14, 0x36, 0x44, 0x82, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, 0x34, 0x55, 0x84, + 0xc8, 0x6e, 0x80, 0x1c, 0x67, 0xd8, 0xb2, 0x7e, 0xdf, 0x59, 0x59, 0x05, 0xaa, 0x01, 0x92, 0x3d, 0xce, 0xac, 0xa4, + 0xb5, 0x16, 0x9b, 0x8a, 0x6b, 0xde, 0x65, 0x7e, 0x17, 0x9d, 0xf1, 0xc3, 0xb0, 0xc2, 0x64, 0x36, 0xd2, 0xd5, 0xb0, + 0x6c, 0x57, 0x96, 0xd3, 0x00, 0x20, 0x78, 0xdf, 0xfb, 0x3f, 0x0a, 0xff, 0xff, 0xc8, 0xe2, 0x44, 0x44, 0x16, 0xa8, + 0xc8, 0xac, 0xe2, 0x9c, 0xac, 0x02, 0x66, 0x54, 0x05, 0x70, 0x46, 0x05, 0xb0, 0x8f, 0x0e, 0xc8, 0xb1, 0x20, 0x68, + 0x34, 0x4d, 0x77, 0x34, 0xec, 0x96, 0xf7, 0x2b, 0x2d, 0x56, 0x1c, 0xca, 0xf5, 0x8c, 0x6c, 0x4b, 0x7e, 0xb7, 0x03, + 0x65, 0xcd, 0x52, 0x5a, 0xe9, 0xe8, 0x7f, 0xd7, 0xd4, 0xb6, 0x1b, 0x3b, 0x02, 0xd5, 0x37, 0x95, 0x0a, 0x21, 0xfb, + 0x7f, 0x52, 0xf8, 0x29, 0x61, 0x52, 0x4c, 0x86, 0xb9, 0x1b, 0xdd, 0x8d, 0xd0, 0xcd, 0x4a, 0x04, 0x25, 0x66, 0x36, + 0x46, 0xe4, 0xa0, 0x24, 0x70, 0xa0, 0xfa, 0x5f, 0x21, 0xd9, 0x6c, 0xda, 0x6e, 0x43, 0xb5, 0x73, 0x33, 0x3b, 0xf2, + 0xf9, 0x15, 0x33, 0x96, 0x10, 0xd3, 0x20, 0x6c, 0xda, 0x73, 0xf4, 0xcd, 0x8f, 0xd6, 0x9e, 0xbe, 0xb3, 0x6a, 0x92, + 0xd4, 0x5d, 0x7e, 0x0b, 0xff, 0x61, 0x80, 0x61, 0xe0, 0xec, 0x5b, 0x16, 0xd3, 0xec, 0x26, 0xfe, 0xba, 0x16, 0x0d, + 0x21, 0x44, 0x08, 0xd4, 0xb6, 0x43, 0xe6, 0xfa, 0xef, 0xbc, 0xb5, 0x3d, 0x71, 0x77, 0x7f, 0x13, 0x42, 0x4a, 0x63, + 0x52, 0x2a, 0x98, 0x71, 0x5f, 0x4c, 0x7d, 0xea, 0xb9, 0x75, 0xdc, 0x34, 0xa9, 0x9b, 0x99, 0xd9, 0xad, 0x45, 0x51, + 0x14, 0xaf, 0x13, 0x04, 0x40, 0xe5, 0x2f, 0x63, 0x62, 0xfd, 0xe8, 0xba, 0xd1, 0xff, 0xad, 0xc8, 0x96, 0x11, 0x86, + 0x08, 0x49, 0xac, 0x6b, 0x25, 0xd8, 0xdc, 0x18, 0x45, 0x9c, 0x5b, 0x1b, 0xc0, 0x8e, 0x8e, 0xd1, 0x6c, 0x41, 0x55, + 0xa0, 0xb1, 0xcd, 0x1d, 0xfc, 0x7c, 0x51, 0x00, 0xa6, 0x91, 0x1e, 0x4a, 0xde, 0x19, 0x9f, 0x10, 0x43, 0x0f, 0x19, + 0x5c, 0x78, 0x74, 0xe4, 0x81, 0x49, 0x75, 0x60, 0x44, 0x7f, 0xe9, 0xe6, 0x96, 0xb0, 0x06, 0x9e, 0x69, 0xb9, 0xe4, + 0x37, 0x82, 0xde, 0xe9, 0x7b, 0x00, 0x62, 0x12, 0x28, 0xd5, 0xed, 0x17, 0x6c, 0x0b, 0x4c, 0x8f, 0x9c, 0xa7, 0xbd, + 0x21, 0x29, 0x78, 0x70, 0xdc, 0xfd, 0xba, 0x0b, 0xa4, 0x5d, 0xca, 0x57, 0xec, 0x92, 0x61, 0xd6, 0xd1, 0x8d, 0xef, + 0xa6, 0xe8, 0x0a, 0xcd, 0x59, 0x0a, 0xea, 0x9c, 0xbb, 0x9e, 0x1b, 0xcb, 0x2f, 0x5a, 0x72, 0xfa, 0xb7, 0xa5, 0x8f, + 0xd9, 0xfb, 0xd2, 0x2f, 0xd4, 0x55, 0xf3, 0x2d, 0x70, 0x12, 0x00, 0xc8, 0xb2, 0x0f, 0x31, 0x2d, 0xc8, 0x92, 0xea, + 0x6b, 0xf9, 0xb9, 0x19, 0x6f, 0x35, 0x0d, 0x26, 0x68, 0x44, 0x36, 0x28, 0x00, 0xd8, 0xbb, 0xef, 0x9e, 0xbd, 0x5b, + 0x59, 0x4a, 0xe9, 0xd3, 0xec, 0x2f, 0xf3, 0xc0, 0x4b, 0xb3, 0x6c, 0x40, 0x8a, 0xb6, 0xa5, 0x1b, 0xf9, 0x50, 0x82, + 0x88, 0x86, 0xcd, 0x05, 0xcf, 0x46, 0x77, 0x6c, 0xe3, 0x51, 0x8b, 0x2f, 0xd6, 0xa8, 0x1c, 0x43, 0x83, 0xf8, 0x7a, + 0xe7, 0xdd, 0x4a, 0x85, 0x96, 0x94, 0xd7, 0xf8, 0x8e, 0xf6, 0x03, 0x26, 0x77, 0x6e, 0xe0, 0x03, 0x8d, 0xeb, 0xcf, + 0xe1, 0xaf, 0xed, 0xb9, 0x1c, 0x9a, 0x44, 0xa6, 0x97, 0xd9, 0x31, 0xce, 0x78, 0x76, 0x3f, 0x22, 0x09, 0x12, 0x8d, + 0xbe, 0xa8, 0x67, 0xfa, 0xf9, 0x5a, 0x73, 0x44, 0x8a, 0x50, 0xdf, 0xdf, 0x63, 0x17, 0xc8, 0x0b, 0xa7, 0x0b, 0xca, + 0xed, 0x7b, 0xdc, 0xff, 0x1c, 0x38, 0xda, 0x47, 0xf7, 0xf8, 0xdd, 0xea, 0x6e, 0x66, 0xdf, 0xbc, 0xc0, 0x63, 0x41, + 0x48, 0x9b, 0x20, 0x61, 0x98, 0xf9, 0xdd, 0x37, 0x11, 0x16, 0xef, 0x7b, 0x0b, 0x62, 0x35, 0xea, 0x4f, 0x7f, 0xfd, + 0xcb, 0x3e, 0xdd, 0xed, 0xf5, 0x88, 0x5f, 0x7f, 0x38, 0x78, 0x7a, 0x6f, 0x98, 0x86, 0xd5, 0x14, 0xda, 0x9e, 0xf5, + 0xcc, 0xf8, 0xb6, 0xad, 0xc2, 0xbe, 0xff, 0xf2, 0xf5, 0xe0, 0xae, 0xe7, 0x30, 0xb4, 0xee, 0x4e, 0x94, 0xc5, 0x23, + 0x86, 0x7f, 0x13, 0x24, 0xfd, 0x33, 0x27, 0xfd, 0xc2, 0xe7, 0x56, 0x80, 0x01, 0xba, 0xa5, 0xe6, 0x43, 0x6b, 0x8c, + 0x17, 0xbe, 0x41, 0x37, 0xc2, 0xc4, 0xfc, 0x0a, 0x4b, 0x29, 0x76, 0xde, 0xbf, 0x18, 0xd3, 0x27, 0xd6, 0x45, 0x4d, + 0x00, 0x44, 0x4a, 0x66, 0x13, 0xc0, 0xa0, 0x44, 0x06, 0x38, 0x1b, 0xc6, 0x75, 0xe9, 0x2e, 0xf4, 0xc8, 0xea, 0x66, + 0xd8, 0xc2, 0xfe, 0xcf, 0x17, 0x38, 0xc0, 0x27, 0xd6, 0x41, 0xc7, 0xcb, 0x4c, 0xc8, 0x1d, 0xb3, 0xe2, 0xff, 0xc7, + 0x4f, 0x6a, 0x72, 0x21, 0x96, 0xc2, 0x66, 0xb6, 0x75, 0x77, 0x8d, 0xdd, 0x48, 0x95, 0x89, 0xad, 0xcc, 0x8a, 0xea, + 0x5b, 0xa8, 0xe4, 0xf7, 0x4e, 0xee, 0x45, 0x95, 0xa2, 0xfa, 0x16, 0xc8, 0x96, 0x67, 0x78, 0xc7, 0xf1, 0xf5, 0x4f, + 0x03, 0xe2, 0xad, 0x94, 0x1c, 0xa5, 0x6a, 0x60, 0xc9, 0x93, 0x43, 0x3f, 0x6d, 0x50, 0x1e, 0x67, 0xa4, 0x0d, 0x38, + 0x72, 0x25, 0x7a, 0x66, 0xd0, 0xc8, 0xbb, 0x4e, 0x1e, 0x8b, 0x2a, 0xff, 0x2e, 0xf1, 0xfb, 0x4a, 0x6a, 0x11, 0x2c, + 0x19, 0xc9, 0x1d, 0x41, 0xcc, 0x16, 0xaa, 0x08, 0xed, 0x28, 0x9c, 0x48, 0x2b, 0x1e, 0xf1, 0x82, 0xf7, 0x7c, 0xbf, + 0x6d, 0x7b, 0x83, 0x84, 0x0b, 0x6f, 0x61, 0xf1, 0x2d, 0x3e, 0xc8, 0xf9, 0xe7, 0x72, 0xb2, 0x96, 0x8a, 0x9e, 0xb2, + 0x79, 0x9a, 0xd8, 0x52, 0xa2, 0x4b, 0x86, 0x40, 0x17, 0x54, 0x47, 0x6e, 0x98, 0x5c, 0x2f, 0x78, 0x7f, 0x83, 0xdb, + 0xe6, 0x17, 0x0b, 0x29, 0x5f, 0xcf, 0xcc, 0x6e, 0xeb, 0x01, 0x50, 0x75, 0xd8, 0x00, 0x3c, 0x65, 0xff, 0xdd, 0xe3, + 0x6e, 0xf2, 0x12, 0x61, 0xe1, 0xb1, 0x5b, 0x22, 0xed, 0xb2, 0x8f, 0x93, 0xa1, 0x57, 0x07, 0xf0, 0xf6, 0x44, 0x05, + 0x10, 0xb9, 0x8a, 0x39, 0x37, 0x9c, 0x88, 0xa4, 0xfe, 0x7d, 0xfa, 0x2d, 0x5d, 0xd8, 0xb0, 0x0d, 0x4d, 0xd0, 0x57, + 0x09, 0xaf, 0xa2, 0xf5, 0x8d, 0x8a, 0x5d, 0x8e, 0x00, 0x64, 0xad, 0x82, 0x99, 0x75, 0xdb, 0x10, 0xab, 0x93, 0x54, + 0x6e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd3, 0x1c, 0xb9, 0xa1, 0xea, 0x18, 0xff, 0xca, 0xd8, 0x9c, 0x4d, 0x34, 0x55, + 0xc3, 0xe2, 0x6f, 0x0d, 0xf2, 0x10, 0x2f, 0xfb, 0x88, 0x06, 0x3d, 0xca, 0xba, 0xe0, 0x1a, 0xb8, 0x0a, 0xf4, 0x92, + 0x1c, 0x3c, 0x73, 0x8d, 0x06, 0xc3, 0x1b, 0x63, 0x07, 0x02, 0x60, 0x93, 0x10, 0xca, 0x02, 0x5b, 0x2b, 0x1d, 0x54, + 0x75, 0xc7, 0xd4, 0xbc, 0xdf, 0xbd, 0x65, 0xa2, 0x4f, 0x45, 0x0b, 0x97, 0xa8, 0xbe, 0x90, 0x58, 0xed, 0xa1, 0xf9, + 0x0f, 0xed, 0xc2, 0x6f, 0x90, 0x20, 0x3c, 0xaf, 0x1d, 0xd0, 0x4f, 0x49, 0x9b, 0x52, 0x85, 0x0a, 0xa3, 0x6c, 0xe3, + 0xca, 0x76, 0x77, 0x45, 0x33, 0x0b, 0xe1, 0x9b, 0x89, 0x66, 0xbd, 0xed, 0xf8, 0xc1, 0x1e, 0x0d, 0x9b, 0x00, 0x5a, + 0x81, 0x05, 0x20, 0xea, 0xcf, 0xd5, 0xb6, 0xfd, 0x2e, 0x6c, 0x06, 0x55, 0x51, 0x92, 0x55, 0xa1, 0x8d, 0xa0, 0x91, + 0x81, 0x41, 0x13, 0x4d, 0xbf, 0xe8, 0x1e, 0xfc, 0xc2, 0x85, 0xb8, 0xa0, 0xb0, 0xa1, 0x74, 0xeb, 0xfa, 0x25, 0x52, + 0x05, 0xa6, 0xb1, 0x72, 0xb9, 0xff, 0x7e, 0x07, 0x1d, 0x7f, 0x5d, 0xec, 0x94, 0x7a, 0xae, 0xaa, 0x09, 0x75, 0x77, + 0x42, 0x13, 0x08, 0x1e, 0x0e, 0xbd, 0x70, 0xfa, 0x47, 0xc2, 0x1d, 0x24, 0xe7, 0xe5, 0xfb, 0xbf, 0x42, 0x0d, 0xfe, + 0x3c, 0xa0, 0x80, 0xf6, 0xaa, 0x7c, 0xde, 0x1d, 0x21, 0x38, 0x51, 0xbf, 0x02, 0x3b, 0xa2, 0xd2, 0x94, 0x1c, 0x51, + 0x58, 0x9c, 0x21, 0xbe, 0x01, 0xba, 0xf9, 0xb6, 0x53, 0xfd, 0xf9, 0xdb, 0x85, 0x13, 0xf1, 0xab, 0x6f, 0x97, 0xec, + 0x6d, 0xa4, 0x44, 0xe0, 0xa1, 0x5a, 0x9f, 0x1b, 0x84, 0x92, 0x0d, 0x96, 0x28, 0x45, 0x5c, 0x26, 0xa2, 0x4a, 0x08, + 0x16, 0x6d, 0x35, 0x6a, 0xe8, 0xd7, 0xeb, 0x2e, 0xb2, 0xae, 0xf1, 0x54, 0x05, 0x5f, 0xa8, 0xdf, 0xf6, 0x0c, 0x9b, + 0x79, 0x4d, 0xe7, 0x62, 0xff, 0x2b, 0x74, 0x4e, 0x2e, 0xb4, 0x76, 0xe9, 0x29, 0x04, 0x10, 0x85, 0x3b, 0xd3, 0x96, + 0x15, 0xc9, 0xd0, 0xae, 0xc0, 0xec, 0x07, 0x06, 0x92, 0x09, 0xf2, 0xc9, 0xfe, 0x4c, 0x0e, 0x21, 0x4d, 0x3c, 0x4e, + 0x46, 0x30, 0xbc, 0xd2, 0x50, 0xfa, 0xe6, 0x62, 0x78, 0xab, 0x5c, 0x9f, 0xc2, 0x2e, 0x88, 0x32, 0x07, 0xbe, 0xed, + 0x72, 0x74, 0x2b, 0x62, 0xf0, 0x8c, 0xc7, 0x8c, 0xb9, 0x77, 0xeb, 0xbd, 0xfb, 0x23, 0x52, 0x1d, 0x0b, 0x41, 0x6a, + 0x18, 0xc8, 0xaf, 0xc5, 0x40, 0x0f, 0xa8, 0x0a, 0x22, 0xf4, 0xd9, 0x58, 0x01, 0x9c, 0xbf, 0x5f, 0x31, 0x46, 0x6e, + 0xa9, 0x9e, 0x4b, 0xab, 0xab, 0x67, 0x15, 0x50, 0xd0, 0x18, 0x1d, 0x4c, 0xdd, 0x1a, 0x84, 0xd3, 0x86, 0xf6, 0xc1, + 0xc3, 0x23, 0xd2, 0x6b, 0x28, 0x62, 0xb1, 0x70, 0x56, 0xb8, 0xd4, 0xea, 0x6a, 0x61, 0x2a, 0x47, 0x7a, 0x24, 0xb9, + 0x72, 0x3b, 0x70, 0xfb, 0xde, 0xb4, 0x06, 0x09, 0x70, 0x8e, 0x18, 0xe2, 0x82, 0x46, 0x78, 0x5c, 0x13, 0x24, 0x48, + 0x48, 0x6f, 0x0c, 0xc8, 0x22, 0xc1, 0x45, 0xa6, 0x24, 0x7a, 0x11, 0x94, 0xda, 0x3d, 0x1d, 0xe9, 0x53, 0x80, 0x8b, + 0x71, 0xb2, 0x5a, 0x80, 0x25, 0x84, 0xf1, 0xba, 0xe6, 0x22, 0xc0, 0x56, 0x06, 0xb8, 0xb1, 0x66, 0x54, 0x70, 0x2e, + 0xec, 0xd0, 0x68, 0xd7, 0xca, 0xcf, 0xef, 0xc7, 0x02, 0x5c, 0x7a, 0xd1, 0x2c, 0x20, 0x10, 0x67, 0x2e, 0xef, 0x03, + 0x08, 0x39, 0x48, 0x5b, 0xa3, 0x37, 0x2d, 0x61, 0xa3, 0x84, 0x7c, 0x5a, 0x74, 0xf9, 0x95, 0x0f, 0x8d, 0x78, 0x58, + 0x2b, 0x6a, 0x2a, 0x41, 0x9f, 0xb1, 0x0d, 0x3e, 0xb8, 0x51, 0x93, 0xae, 0x0f, 0x96, 0x00, 0xa4, 0xc7, 0x32, 0x19, + 0x70, 0x8f, 0xa6, 0x17, 0xbd, 0x06, 0x52, 0xfa, 0xae, 0x1c, 0x39, 0x0e, 0x51, 0x7c, 0xbe, 0x45, 0x31, 0xb8, 0x37, + 0xad, 0xf1, 0x18, 0xc4, 0x07, 0x59, 0x32, 0xbe, 0x59, 0x14, 0x73, 0xac, 0x38, 0x13, 0x21, 0x7f, 0xd9, 0x48, 0x1a, + 0x09, 0x2b, 0x9d, 0xb6, 0x4a, 0x9a, 0x0a, 0x1b, 0x1b, 0xa0, 0x10, 0xa9, 0x87, 0xa0, 0x27, 0xb0, 0xeb, 0x0d, 0x89, + 0x79, 0x38, 0xd2, 0x52, 0xa4, 0x2f, 0x45, 0x5f, 0x73, 0x76, 0xca, 0x80, 0x4d, 0x84, 0x73, 0x73, 0x49, 0xf0, 0xdf, + 0xc4, 0xb6, 0x2e, 0x2e, 0x50, 0x31, 0xa3, 0x95, 0xe0, 0x21, 0x2c, 0x86, 0x97, 0x45, 0x05, 0x22, 0xeb, 0x6d, 0x7a, + 0x99, 0xb4, 0x92, 0x56, 0x79, 0x2c, 0x01, 0xd4, 0x71, 0x4f, 0x56, 0x16, 0x7a, 0x32, 0x1c, 0x61, 0x1f, 0x64, 0x9c, + 0x62, 0x1c, 0xc7, 0x9a, 0xd4, 0x66, 0xe4, 0xba, 0x13, 0x2d, 0x16, 0x32, 0xe3, 0xa1, 0xae, 0xa2, 0x12, 0x12, 0x18, + 0xd5, 0x24, 0x5d, 0x04, 0xde, 0xfa, 0x89, 0xf7, 0x04, 0x90, 0x80, 0xe8, 0x13, 0x3e, 0xf2, 0x93, 0x0c, 0xad, 0x86, + 0x84, 0x62, 0x45, 0xae, 0x21, 0xe7, 0xc5, 0x1b, 0xe5, 0x28, 0x72, 0xa7, 0xd1, 0x89, 0xbf, 0x16, 0xed, 0x9b, 0xc2, + 0xe6, 0x10, 0x84, 0xc3, 0x47, 0x85, 0x5d, 0xe8, 0x49, 0x3b, 0x95, 0x6a, 0x63, 0xa3, 0x9e, 0x87, 0x03, 0xde, 0xda, + 0x94, 0x09, 0x1e, 0xff, 0x5b, 0x43, 0x0d, 0xd1, 0xe6, 0xaf, 0x63, 0x06, 0x6c, 0xb3, 0xcd, 0xf6, 0x74, 0x0b, 0xf8, + 0x93, 0x38, 0xd9, 0x67, 0x50, 0x53, 0x36, 0x0f, 0x16, 0xdb, 0x75, 0x5f, 0x4e, 0x7e, 0x26, 0x53, 0x01, 0xc4, 0x55, + 0x41, 0xd5, 0x63, 0x64, 0x38, 0x20, 0xed, 0xa5, 0xe1, 0x71, 0x31, 0x40, 0x8a, 0x8c, 0xab, 0x92, 0x02, 0x81, 0x66, + 0x33, 0xa2, 0xb8, 0x01, 0xf4, 0xd8, 0x8c, 0xa3, 0xc4, 0x28, 0xb8, 0x41, 0x9e, 0x34, 0xd8, 0x98, 0x03, 0x97, 0x6a, + 0xd1, 0xac, 0xd2, 0xe6, 0x10, 0xd9, 0x03, 0x8b, 0x02, 0xe2, 0xf8, 0xf3, 0x5a, 0x43, 0x82, 0xbc, 0xe1, 0x7c, 0x12, + 0xc2, 0x00, 0xb7, 0x61, 0x04, 0xd9, 0xc3, 0x38, 0x22, 0xa1, 0xb8, 0xa9, 0x23, 0x7d, 0xfd, 0xc8, 0xde, 0x54, 0xde, + 0xef, 0x5a, 0x60, 0x18, 0xc7, 0x83, 0x81, 0xde, 0xbc, 0xd0, 0x92, 0x6e, 0x50, 0x97, 0x10, 0xf3, 0xb3, 0xb3, 0x99, + 0x19, 0x67, 0x6b, 0x8e, 0xe1, 0x61, 0xd8, 0x5c, 0x94, 0xf7, 0xf7, 0x6e, 0x12, 0x20, 0xbf, 0x13, 0x56, 0x7d, 0x72, + 0x12, 0x4f, 0x54, 0xfd, 0x5e, 0xd6, 0x3f, 0x12, 0xaf, 0x7f, 0x18, 0x50, 0xb2, 0xe9, 0xa1, 0x5e, 0xa9, 0x7b, 0x8b, + 0xe5, 0xac, 0xec, 0x9a, 0x82, 0x4a, 0x4b, 0x97, 0x65, 0x8c, 0x03, 0x49, 0xa0, 0x82, 0x7e, 0x29, 0xfb, 0xbc, 0x55, + 0x38, 0x50, 0x41, 0x21, 0x5b, 0x3f, 0x0d, 0xea, 0xe2, 0xf4, 0x2a, 0xc5, 0x2c, 0xc5, 0x18, 0xcf, 0x4e, 0x6d, 0x7d, + 0x1b, 0x90, 0x4e, 0x9d, 0xd2, 0xc0, 0xf3, 0x13, 0xdb, 0xed, 0xf6, 0x89, 0x13, 0x02, 0xb1, 0x52, 0x38, 0x11, 0x9b, + 0x59, 0x6c, 0x7e, 0xd0, 0x88, 0x54, 0x7e, 0x30, 0x0e, 0xc8, 0xca, 0x39, 0x6c, 0x81, 0xec, 0xb9, 0x29, 0x3c, 0x30, + 0xe6, 0x78, 0xdf, 0xf2, 0xd0, 0xad, 0xbf, 0xc3, 0x9f, 0x90, 0x93, 0x19, 0x65, 0xa6, 0xcf, 0xeb, 0xc1, 0x74, 0x57, + 0xdd, 0xb3, 0xc4, 0xe6, 0xcd, 0x75, 0xd2, 0x8b, 0x64, 0xb1, 0x97, 0xa2, 0x49, 0xba, 0x0c, 0x66, 0xed, 0x32, 0x88, + 0x5a, 0x2a, 0x60, 0xda, 0xe9, 0x6d, 0xa6, 0x71, 0x56, 0x40, 0x9f, 0x01, 0x33, 0xbb, 0xbb, 0x04, 0x5c, 0x17, 0x19, + 0x2c, 0xb1, 0x52, 0x88, 0xc2, 0xe3, 0x29, 0xed, 0xde, 0x4f, 0x0c, 0x94, 0x3e, 0x76, 0x81, 0xec, 0xa5, 0xa3, 0x87, + 0xa4, 0x76, 0x84, 0x28, 0xa2, 0x96, 0xfd, 0x21, 0x82, 0x42, 0x8a, 0x33, 0xfc, 0x80, 0xe9, 0xce, 0x47, 0xc8, 0xb8, + 0x00, 0xf9, 0xd9, 0x4c, 0xb4, 0xd5, 0x77, 0x5b, 0xc4, 0xc0, 0xcb, 0x0f, 0x25, 0xee, 0x27, 0xbd, 0x95, 0x6f, 0xc2, + 0xe3, 0x58, 0x71, 0x16, 0xc8, 0x58, 0xa1, 0x30, 0x8c, 0xe6, 0xfc, 0x04, 0x49, 0xd2, 0x7b, 0x38, 0x8f, 0x02, 0xb8, + 0x0c, 0xc1, 0x88, 0x02, 0xb5, 0x8d, 0x60, 0xf6, 0xc2, 0x4c, 0x35, 0xa0, 0xcc, 0x2d, 0x9a, 0x29, 0xc9, 0x5a, 0x3b, + 0x99, 0xe3, 0xcc, 0x73, 0x3f, 0x53, 0x18, 0x00, 0x54, 0x6c, 0xfa, 0xbd, 0x6a, 0xc5, 0xf2, 0x3a, 0x1e, 0x66, 0x6d, + 0xe5, 0x84, 0x98, 0x75, 0xf6, 0xfb, 0x14, 0x4d, 0x52, 0x01, 0xc8, 0x0a, 0xac, 0x4e, 0x8d, 0x49, 0x2a, 0xe7, 0x03, + 0xa3, 0x9b, 0x3a, 0x18, 0x46, 0x2c, 0x43, 0x65, 0x69, 0x1a, 0x06, 0x87, 0x6d, 0xfb, 0x3e, 0xc8, 0xe8, 0xd0, 0xef, + 0x5b, 0xd9, 0x58, 0x0a, 0x81, 0x96, 0x05, 0x5a, 0x3e, 0x0c, 0x68, 0x52, 0x86, 0x2b, 0x45, 0x79, 0x22, 0x47, 0xca, + 0x3d, 0xb2, 0xe4, 0x24, 0xef, 0xfb, 0xa9, 0x69, 0x57, 0x97, 0x0c, 0x88, 0x66, 0x2e, 0x54, 0xc3, 0xd7, 0x2c, 0xf9, + 0x33, 0x4c, 0x98, 0xac, 0xbd, 0x71, 0x98, 0xd7, 0x64, 0x8d, 0x1c, 0x99, 0xaa, 0x0e, 0x18, 0x82, 0x6a, 0x74, 0x39, + 0x36, 0xc6, 0x4f, 0x2c, 0x1a, 0xb5, 0xa1, 0x30, 0xaf, 0x1d, 0x2b, 0x25, 0x67, 0x96, 0x8e, 0x98, 0x77, 0x37, 0x16, + 0x9d, 0xea, 0xa7, 0x07, 0xb2, 0x65, 0xfd, 0x00, 0xdf, 0x59, 0x22, 0xc2, 0x07, 0xcb, 0x1f, 0xce, 0x6f, 0x23, 0xbb, + 0x74, 0x2d, 0x74, 0x4c, 0x6b, 0xeb, 0xf0, 0xa7, 0x66, 0x93, 0x96, 0x2c, 0xf5, 0xdf, 0xcb, 0x00, 0x15, 0xe4, 0x29, + 0xa8, 0x42, 0x75, 0x54, 0x42, 0x94, 0xe1, 0x60, 0x53, 0xad, 0xab, 0xa3, 0xf2, 0xc6, 0xb9, 0xeb, 0x1d, 0xdc, 0xd9, + 0x81, 0x2c, 0xa9, 0x3b, 0xc2, 0x27, 0x17, 0x7d, 0x15, 0x21, 0x45, 0xd8, 0x32, 0x23, 0x77, 0xf6, 0xe5, 0xe9, 0x23, + 0xaf, 0x6f, 0xed, 0x3c, 0x1d, 0x3a, 0x5f, 0x61, 0x90, 0x5d, 0x7b, 0x74, 0x6c, 0x64, 0xcb, 0x8d, 0x68, 0xdb, 0x78, + 0xde, 0x1d, 0xa5, 0xd1, 0x4f, 0x4a, 0x89, 0x57, 0x6e, 0x82, 0xa8, 0xfd, 0xc1, 0x42, 0xf2, 0x19, 0x9e, 0x43, 0xb6, + 0x60, 0xb4, 0x68, 0x4c, 0x6c, 0x3c, 0x07, 0xdc, 0x23, 0x8a, 0xeb, 0x47, 0x8f, 0x05, 0x09, 0x17, 0x9c, 0x01, 0xf6, + 0xd2, 0x9c, 0xdd, 0xb6, 0x06, 0xd8, 0xe5, 0x62, 0xe2, 0x8a, 0x3e, 0x2e, 0xcc, 0xf1, 0xee, 0xfa, 0x85, 0xb2, 0x23, + 0xf1, 0xae, 0xb9, 0x6c, 0x6f, 0x79, 0x2d, 0xa2, 0x34, 0x15, 0x01, 0x4c, 0x13, 0x84, 0x86, 0x32, 0xc7, 0x14, 0xe9, + 0xcd, 0xf4, 0x6a, 0x98, 0x73, 0x27, 0x6b, 0x2e, 0x76, 0x65, 0x50, 0xa8, 0x01, 0x51, 0x19, 0xe2, 0x38, 0x39, 0x4e, + 0x18, 0xd8, 0x6d, 0x02, 0xd0, 0x11, 0xb4, 0x61, 0x48, 0xe8, 0xad, 0x13, 0x40, 0x0b, 0xb1, 0xc8, 0x1f, 0x32, 0x29, + 0x15, 0xa7, 0xbe, 0x97, 0x97, 0x79, 0xf3, 0x82, 0x1b, 0x14, 0x47, 0x08, 0xda, 0x8a, 0xe7, 0xc1, 0x15, 0x43, 0xb7, + 0x47, 0xe1, 0xd0, 0xc6, 0x56, 0xe6, 0x19, 0x7f, 0x96, 0xe8, 0x07, 0xca, 0x6e, 0xec, 0xf5, 0x90, 0x76, 0xaa, 0x39, + 0x28, 0xc7, 0x30, 0xf8, 0x96, 0xe9, 0x51, 0xd2, 0xba, 0x05, 0x2e, 0x86, 0xdf, 0x3c, 0xc4, 0x7b, 0xef, 0xb8, 0x3d, + 0x7d, 0xcc, 0xd3, 0xee, 0xef, 0xc3, 0x67, 0x83, 0xd9, 0x97, 0xf9, 0x80, 0x2e, 0x1e, 0x0e, 0x5c, 0x43, 0x02, 0x33, + 0x12, 0x10, 0xba, 0xd1, 0xf5, 0xd6, 0xbd, 0x43, 0xcd, 0xf3, 0xe0, 0xc4, 0x3d, 0xe5, 0x37, 0x2e, 0x49, 0x17, 0x49, + 0xd7, 0x08, 0x65, 0xef, 0xff, 0x45, 0x0e, 0x4b, 0xcf, 0x23, 0xe3, 0xd1, 0xa6, 0xa6, 0x38, 0x13, 0x9c, 0x5d, 0x0e, + 0xf6, 0x16, 0x24, 0x8c, 0x63, 0xe4, 0x92, 0xc1, 0x38, 0x67, 0x66, 0x4c, 0xc4, 0xd6, 0x1c, 0xa4, 0x8d, 0x0c, 0x79, + 0x9d, 0x22, 0xf7, 0xc5, 0x4e, 0x01, 0xfa, 0x50, 0xc8, 0x69, 0xb7, 0x15, 0xfa, 0x24, 0x60, 0xe0, 0xff, 0x4e, 0x4b, + 0xfb, 0x1e, 0xf9, 0x3e, 0x6d, 0x62, 0x89, 0x14, 0x9b, 0xb1, 0x51, 0xcf, 0xc5, 0xdc, 0x2a, 0x64, 0xc3, 0xfa, 0x45, + 0x84, 0xfa, 0xdd, 0xac, 0x3c, 0x3b, 0xe6, 0x27, 0x12, 0xc0, 0x69, 0xeb, 0x10, 0x6c, 0xe7, 0xf3, 0xad, 0xff, 0x26, + 0xe9, 0xfb, 0xcc, 0xa2, 0x87, 0x73, 0x9d, 0x8c, 0x35, 0x27, 0xb0, 0xa0, 0xd4, 0xdb, 0xb1, 0x73, 0x7d, 0xba, 0xc7, + 0x73, 0xd5, 0x2c, 0xca, 0x20, 0xb9, 0xb6, 0x8b, 0xa4, 0x48, 0x3c, 0xb9, 0x7a, 0xe3, 0x6c, 0xc6, 0xf8, 0x58, 0xfc, + 0xbd, 0x3d, 0x4e, 0xfb, 0x7e, 0xe3, 0x33, 0xda, 0xbb, 0xf4, 0x7f, 0xce, 0xa6, 0xd3, 0xdf, 0x21, 0xe3, 0xb9, 0xae, + 0xd9, 0x52, 0x35, 0x85, 0x54, 0x93, 0x2d, 0x02, 0x50, 0x8d, 0x38, 0xdf, 0x1d, 0x77, 0xfb, 0xef, 0x0a, 0xa2, 0x99, + 0xbf, 0x20, 0xee, 0xbe, 0xd7, 0x52, 0x3d, 0x6d, 0x71, 0x34, 0xe5, 0xac, 0xf7, 0xc8, 0x6e, 0xf6, 0x1e, 0xf0, 0xb6, + 0xb4, 0xfa, 0xa7, 0xfa, 0x4f, 0xf8, 0xdd, 0x62, 0xf3, 0xb7, 0xdd, 0x7c, 0xea, 0xc3, 0xf6, 0xa4, 0xae, 0xb6, 0x78, + 0xb3, 0xd6, 0xdf, 0xec, 0x79, 0xbb, 0xdb, 0x7c, 0xa0, 0xd3, 0xfa, 0x2f, 0xe5, 0x75, 0x35, 0x18, 0x97, 0xea, 0xaf, + 0x40, 0xe2, 0xdf, 0x2a, 0xf4, 0xee, 0x0e, 0x90, 0x2f, 0xd5, 0xec, 0x20, 0xc3, 0xcc, 0xf8, 0x60, 0xbc, 0x0b, 0x5d, + 0x68, 0xeb, 0xf1, 0x6e, 0x14, 0x26, 0x2a, 0xc4, 0xfd, 0xdc, 0x35, 0x33, 0xd5, 0xbb, 0xe4, 0x6a, 0xd2, 0xa5, 0x5f, + 0x1b, 0x14, 0xaf, 0x4d, 0x68, 0xb1, 0x66, 0xc4, 0x36, 0x35, 0xff, 0x05, 0x58, 0xfe, 0xb9, 0xe0, 0x19, 0xc6, 0x4d, + 0xda, 0x8f, 0x6a, 0xbb, 0x52, 0xf9, 0xfe, 0xa7, 0xf1, 0xd7, 0xa6, 0x9e, 0xb2, 0xce, 0x7f, 0xde, 0x7d, 0x5b, 0xfe, + 0x99, 0xcb, 0x8e, 0x4c, 0x55, 0xfd, 0x05, 0xf9, 0xc4, 0xa4, 0x2b, 0xe5, 0x78, 0x3d, 0xcb, 0xfe, 0x5f, 0x84, 0xbb, + 0x7f, 0x3b, 0xff, 0xf2, 0x9f, 0x66, 0xe1, 0x7d, 0x20, 0xcd, 0x4e, 0xc3, 0x17, 0x92, 0xdf, 0xd9, 0xb2, 0x7a, 0x7e, + 0xe7, 0x0b, 0xd4, 0x58, 0x71, 0x8f, 0xac, 0x2f, 0x65, 0x62, 0x55, 0x2e, 0xe0, 0xd6, 0x7f, 0x3b, 0xd5, 0x5f, 0x0f, + 0xe4, 0xf3, 0x9e, 0x92, 0xf9, 0x62, 0xf8, 0xb5, 0x79, 0x73, 0x4f, 0xa7, 0x7a, 0xd7, 0x2f, 0xfc, 0x78, 0x4c, 0x4a, + 0x7f, 0xd5, 0xe3, 0x32, 0xb8, 0xb9, 0x52, 0xff, 0xd5, 0xc2, 0xa7, 0x2b, 0x83, 0xf2, 0xcf, 0xc8, 0xc7, 0xe3, 0xf5, + 0xcd, 0xe2, 0x63, 0xf9, 0x3e, 0x0b, 0x18, 0x27, 0x38, 0xa3, 0xe6, 0x0b, 0xdc, 0x11, 0x54, 0x1f, 0xe2, 0x91, 0xac, + 0x3f, 0x99, 0x55, 0x3c, 0xdc, 0x2b, 0x70, 0xfc, 0x96, 0x57, 0x7e, 0xe6, 0xd2, 0x24, 0x5c, 0x30, 0x4e, 0x7f, 0xc4, + 0xa3, 0xef, 0x3b, 0x18, 0x7d, 0xd0, 0xbb, 0xf1, 0xdd, 0x8c, 0x3a, 0xe2, 0x63, 0xf3, 0xac, 0xab, 0x96, 0xc6, 0x5b, + 0x29, 0x39, 0x61, 0x1b, 0xfd, 0x55, 0xc0, 0x43, 0x0c, 0xda, 0xbe, 0xf7, 0xad, 0xf2, 0x37, 0x7e, 0x17, 0xa6, 0xf7, + 0xd6, 0x8f, 0xbf, 0xbf, 0x12, 0xef, 0xf6, 0xef, 0x0c, 0x13, 0x88, 0xf5, 0xc0, 0xbb, 0xe8, 0xff, 0xa8, 0x86, 0x4f, + 0x48, 0xe6, 0x44, 0x61, 0x4d, 0xdd, 0x2f, 0xd5, 0xf7, 0xe1, 0xe2, 0x41, 0x24, 0x5f, 0x16, 0xef, 0xfb, 0x44, 0x1e, + 0xee, 0xd1, 0xb3, 0xbc, 0x97, 0x46, 0x1c, 0x40, 0x0d, 0x05, 0xc8, 0x82, 0x7c, 0x32, 0x8c, 0xc0, 0xce, 0x73, 0x0a, + 0x3b, 0xa7, 0xaa, 0xcf, 0xee, 0x22, 0xd2, 0xbb, 0xd5, 0xdc, 0x9a, 0x3f, 0x01, 0x4a, 0x61, 0x9b, 0x08, 0xb0, 0xef, + 0xa7, 0x3b, 0x9a, 0xd4, 0x7a, 0x9d, 0x6e, 0xfd, 0xe9, 0xe4, 0x4a, 0x4d, 0xea, 0xb6, 0xba, 0xc8, 0x78, 0xe0, 0x79, + 0x93, 0x13, 0x9e, 0xdd, 0x98, 0xe8, 0x14, 0x63, 0x13, 0x0e, 0xda, 0x99, 0x29, 0xeb, 0xb1, 0x73, 0x1d, 0x12, 0x91, + 0xdd, 0xd0, 0x10, 0x77, 0x99, 0xdb, 0x23, 0xb8, 0x51, 0x11, 0x89, 0x5a, 0x42, 0x7d, 0xf1, 0x7b, 0x26, 0x93, 0x89, + 0x6f, 0xe5, 0x39, 0x1b, 0x7e, 0xe1, 0x7f, 0x56, 0xc9, 0x82, 0x01, 0xc8, 0xc9, 0xd4, 0xc9, 0x23, 0x50, 0xf1, 0x35, + 0x41, 0xb4, 0xf3, 0x59, 0x4e, 0xdc, 0x3b, 0x2c, 0xca, 0x53, 0xcd, 0xcc, 0xf3, 0xbf, 0x6b, 0x60, 0xcd, 0x42, 0x51, + 0xc4, 0x46, 0x34, 0xcb, 0xf6, 0x76, 0x33, 0x8b, 0x7a, 0x1e, 0xbe, 0x02, 0xe1, 0xec, 0x32, 0x00, 0x7d, 0x5b, 0xd5, + 0xb0, 0x96, 0x33, 0xf3, 0x97, 0xde, 0x08, 0x01, 0x6a, 0x1e, 0xf4, 0x30, 0x66, 0xef, 0x4d, 0xc9, 0xfe, 0x51, 0x90, + 0x53, 0x9e, 0x9b, 0x9a, 0xce, 0x19, 0x67, 0xc9, 0x73, 0x38, 0x93, 0x12, 0xd2, 0x4e, 0x7b, 0xa4, 0x22, 0xd2, 0xf0, + 0xda, 0xac, 0x5e, 0x2c, 0x65, 0x7d, 0xb8, 0xe5, 0x85, 0x29, 0x20, 0x0c, 0x48, 0x82, 0xd8, 0x53, 0xf8, 0x39, 0x58, + 0xf4, 0x21, 0x14, 0x45, 0x12, 0xbd, 0x52, 0x38, 0xbd, 0x9d, 0x98, 0xbd, 0x24, 0xa9, 0xd1, 0xe9, 0x11, 0xae, 0xff, + 0xbe, 0xb7, 0x73, 0x8e, 0x9e, 0x49, 0x16, 0xe9, 0xdb, 0xf4, 0x97, 0x51, 0xbb, 0x59, 0xa2, 0xa9, 0xed, 0x0d, 0x00, + 0xce, 0xb1, 0x52, 0xc3, 0xee, 0xfb, 0xa5, 0x91, 0xa2, 0x25, 0xbe, 0xbc, 0x20, 0xa3, 0xa2, 0x4b, 0x5a, 0xea, 0xbb, + 0x38, 0x5d, 0x54, 0x65, 0x1b, 0xfc, 0x3e, 0x39, 0xe0, 0xc5, 0x1b, 0x30, 0x49, 0x5f, 0x91, 0x3e, 0x12, 0x04, 0xa7, + 0xcd, 0xc6, 0x6c, 0x6f, 0xdd, 0x47, 0xf2, 0xd6, 0xc2, 0x7f, 0xd1, 0x5e, 0x58, 0xf5, 0xa2, 0x67, 0x2a, 0x03, 0xdc, + 0x22, 0x5f, 0x96, 0x71, 0x4e, 0x34, 0xad, 0x5a, 0xf0, 0xa2, 0x2b, 0xa8, 0x33, 0xf7, 0x34, 0x6f, 0xed, 0x22, 0xd8, + 0x10, 0xda, 0xe7, 0xc1, 0x2c, 0x59, 0x60, 0x85, 0x20, 0x94, 0xb7, 0x63, 0xeb, 0x19, 0xd7, 0x5f, 0x35, 0xf8, 0x65, + 0xe5, 0x62, 0x29, 0x74, 0x80, 0x61, 0xf2, 0xdb, 0x1a, 0x08, 0x9e, 0xfa, 0x12, 0xca, 0x02, 0xbd, 0x6d, 0xe1, 0xf1, + 0x9a, 0xee, 0xde, 0x9d, 0xe1, 0x84, 0x10, 0xdf, 0x6f, 0xc6, 0x42, 0x79, 0x1e, 0xfd, 0x92, 0xd1, 0x08, 0xcb, 0x1d, + 0x8e, 0x28, 0xa7, 0x47, 0x83, 0x6c, 0x70, 0x7c, 0x67, 0xeb, 0x51, 0x65, 0x59, 0xe6, 0x11, 0x16, 0x9f, 0x92, 0x05, + 0xf6, 0x82, 0xec, 0xe2, 0xfe, 0xd3, 0x75, 0x28, 0x4c, 0xb1, 0x07, 0x6a, 0x72, 0xab, 0xde, 0xa6, 0x5c, 0x3b, 0xfe, + 0x35, 0x5b, 0xe8, 0xc8, 0x6e, 0xf7, 0x90, 0x7e, 0x8b, 0x6b, 0x6b, 0x0c, 0x6d, 0xdf, 0x90, 0x44, 0xe9, 0x34, 0xdd, + 0x3d, 0x03, 0x0a, 0xf4, 0x3f, 0x26, 0x94, 0xfc, 0x85, 0x34, 0xd3, 0xac, 0x4b, 0xb1, 0xab, 0xfd, 0x12, 0xe7, 0x64, + 0xfa, 0xeb, 0x99, 0x87, 0x7a, 0xa9, 0xfe, 0xdf, 0xeb, 0x35, 0x0d, 0x98, 0xe8, 0x8d, 0x69, 0x04, 0x34, 0x90, 0x22, + 0x95, 0x98, 0x6f, 0x2c, 0xa3, 0x06, 0x49, 0x67, 0x99, 0x91, 0x52, 0xae, 0xa3, 0xfb, 0x8d, 0x0a, 0x85, 0x0b, 0xdd, + 0xbd, 0xad, 0xb8, 0x31, 0xa5, 0xb7, 0x45, 0x8f, 0xe2, 0x37, 0xe6, 0xbd, 0x19, 0xc7, 0x71, 0x73, 0x91, 0x21, 0xe1, + 0x02, 0x3d, 0x8b, 0x1e, 0x57, 0xe7, 0x88, 0xd7, 0x44, 0x39, 0x78, 0x04, 0xd1, 0x31, 0xd1, 0x13, 0xe2, 0x66, 0xbc, + 0xf5, 0x16, 0x7c, 0x62, 0x40, 0xbe, 0xe7, 0xcd, 0x12, 0x7c, 0x68, 0x5b, 0xe5, 0x39, 0x06, 0x1d, 0xf0, 0xab, 0xf5, + 0x6c, 0x29, 0x00, 0x0b, 0xb3, 0x29, 0xef, 0x6a, 0x29, 0xd0, 0x85, 0x86, 0xa4, 0xc9, 0xf3, 0x5d, 0x3d, 0x1d, 0xbf, + 0x44, 0xc3, 0x54, 0x24, 0x52, 0xd2, 0x9b, 0xf8, 0x86, 0xf3, 0x78, 0xa0, 0xad, 0x4e, 0x7d, 0x16, 0x7a, 0xb5, 0x55, + 0x9d, 0x9d, 0x77, 0x93, 0xd7, 0x61, 0x41, 0x17, 0x67, 0x1b, 0x50, 0x8e, 0x35, 0x93, 0x6e, 0x4a, 0x56, 0x55, 0x93, + 0xa2, 0x9c, 0x04, 0x86, 0x68, 0x17, 0xe1, 0x0a, 0xca, 0x9f, 0x57, 0x7d, 0x22, 0x95, 0xfa, 0x62, 0x16, 0x7f, 0x7a, + 0xb0, 0x52, 0x15, 0xf1, 0x3f, 0x38, 0xf2, 0x92, 0xed, 0x12, 0x29, 0x96, 0xa5, 0xa2, 0xf7, 0x33, 0x41, 0x5e, 0xfd, + 0xe1, 0x86, 0xe5, 0xba, 0x87, 0xfd, 0x2a, 0xd5, 0x1b, 0xe2, 0x69, 0xac, 0x18, 0x99, 0x5a, 0x5c, 0xf1, 0x96, 0xcb, + 0x53, 0x48, 0x8b, 0xf5, 0x98, 0x97, 0x2e, 0x69, 0xbc, 0x07, 0xde, 0x6e, 0x30, 0x41, 0x3f, 0x49, 0x6e, 0xd7, 0xb1, + 0x38, 0xa8, 0x45, 0x5d, 0xc8, 0xdb, 0x47, 0x63, 0x76, 0xe4, 0x72, 0x03, 0x1f, 0xbf, 0xb8, 0xd3, 0x39, 0x6f, 0xbc, + 0x56, 0xbe, 0xaa, 0x3b, 0xa1, 0xe0, 0xd7, 0x06, 0xa8, 0x26, 0x43, 0x6c, 0x11, 0xa2, 0x05, 0xdf, 0x7c, 0xb4, 0x59, + 0x9e, 0xd0, 0x12, 0x93, 0x66, 0xe5, 0xf2, 0xc5, 0x0b, 0xf3, 0xae, 0xd8, 0x1f, 0x2b, 0xe7, 0x66, 0x2a, 0xe3, 0x2b, + 0x7d, 0xed, 0x2a, 0x72, 0x59, 0x78, 0x8d, 0x42, 0x45, 0x28, 0xaa, 0x48, 0x1b, 0x17, 0xd8, 0xea, 0x66, 0xd8, 0xf2, + 0x99, 0x79, 0xa1, 0x69, 0xda, 0x98, 0x71, 0x52, 0x5c, 0x32, 0xc2, 0x3f, 0xe8, 0x08, 0xf6, 0x45, 0xab, 0x3c, 0xff, + 0xb1, 0x63, 0xb1, 0x70, 0x03, 0xed, 0x38, 0x7a, 0x21, 0x47, 0x25, 0xe9, 0xd1, 0x27, 0x85, 0xb2, 0xca, 0x34, 0xf2, + 0xae, 0xfa, 0xa4, 0xc2, 0x53, 0x74, 0x07, 0x45, 0x8e, 0xc2, 0x96, 0x0c, 0x6b, 0x65, 0x8c, 0xeb, 0x11, 0x7e, 0xd6, + 0xce, 0xde, 0x39, 0xdc, 0xec, 0x41, 0xec, 0xf0, 0x5f, 0x94, 0xe3, 0x73, 0x93, 0x25, 0x1e, 0x46, 0xfa, 0x2a, 0x79, + 0x9b, 0xa7, 0x13, 0x1f, 0xbe, 0xc9, 0x8c, 0xec, 0x96, 0xfa, 0x4f, 0xec, 0xf3, 0x3a, 0x42, 0x44, 0xce, 0xf3, 0x5d, + 0x45, 0x46, 0xa7, 0x70, 0x91, 0xeb, 0x94, 0xd2, 0x47, 0x95, 0x42, 0x02, 0x65, 0x49, 0xe3, 0x96, 0x65, 0xf7, 0x1f, + 0x7f, 0x50, 0xa1, 0xe5, 0x6b, 0x07, 0x66, 0xd2, 0x6d, 0x66, 0x96, 0x48, 0x16, 0x35, 0x46, 0x76, 0xa3, 0xe7, 0x1f, + 0x15, 0x89, 0x04, 0x49, 0x1a, 0x43, 0xa4, 0x73, 0x37, 0xdc, 0xe9, 0xff, 0x0e, 0xf7, 0xec, 0xc6, 0x92, 0xa2, 0x69, + 0x16, 0xca, 0xec, 0x0f, 0xf8, 0xa6, 0xdf, 0x21, 0x87, 0xa6, 0x8a, 0x92, 0x41, 0x0d, 0x6f, 0xe4, 0xdc, 0x86, 0x6e, + 0xcd, 0x83, 0xf5, 0xec, 0x17, 0xd0, 0x67, 0x8c, 0x06, 0x6a, 0xab, 0xd1, 0x4b, 0xd2, 0x37, 0x4a, 0xd4, 0x79, 0x1f, + 0x14, 0x14, 0xd4, 0xdb, 0x40, 0xe7, 0xa6, 0x26, 0x44, 0xbb, 0x5f, 0x04, 0x45, 0x90, 0x85, 0x68, 0xbc, 0xf0, 0xb1, + 0x7c, 0x91, 0xee, 0x49, 0x94, 0x48, 0xa8, 0x76, 0x5c, 0x7c, 0xcf, 0xa5, 0x34, 0x28, 0x78, 0xd4, 0x1a, 0x50, 0xec, + 0xba, 0x40, 0x7d, 0x80, 0x95, 0x55, 0xd6, 0x61, 0xde, 0x0a, 0x52, 0x35, 0x1a, 0x56, 0xdb, 0xcc, 0x2e, 0x4e, 0x9e, + 0x29, 0x32, 0x93, 0x84, 0x3d, 0xeb, 0xef, 0x2a, 0x5e, 0xe6, 0x48, 0x94, 0x95, 0x2d, 0x01, 0xeb, 0x5d, 0xb3, 0xc3, + 0xd1, 0x6c, 0x51, 0x5a, 0xbb, 0x16, 0xf6, 0xaf, 0x6c, 0x54, 0x49, 0x53, 0xaf, 0x63, 0x29, 0x71, 0x0d, 0x1b, 0xb9, + 0x4d, 0x06, 0xe2, 0x63, 0xf9, 0x6d, 0x92, 0x00, 0xe1, 0xbb, 0x78, 0xc4, 0x43, 0x37, 0x59, 0xb1, 0xa9, 0xec, 0x5c, + 0x59, 0xec, 0xf5, 0xe8, 0x05, 0x9c, 0x1e, 0x4d, 0xae, 0x24, 0x47, 0xb7, 0xc5, 0x79, 0x71, 0x57, 0xf1, 0x54, 0xe9, + 0xb2, 0xf8, 0x97, 0xfa, 0x0f, 0x54, 0x6e, 0x0f, 0x2b, 0x84, 0xfd, 0x2d, 0x91, 0xbb, 0x80, 0x94, 0x67, 0x81, 0x10, + 0x6a, 0x89, 0x08, 0x9b, 0x6f, 0x85, 0x28, 0xb0, 0x28, 0xb0, 0x49, 0xf3, 0x38, 0xc7, 0x6a, 0xbd, 0x15, 0x4d, 0x72, + 0x07, 0x92, 0x7b, 0xd8, 0x8d, 0x5b, 0x12, 0xca, 0xbd, 0xf2, 0xd8, 0xe6, 0x2f, 0x51, 0xd0, 0x07, 0x2d, 0x69, 0x5c, + 0x35, 0x02, 0x9c, 0x5e, 0xf2, 0xd5, 0x2b, 0xfd, 0xb6, 0xeb, 0x87, 0x1b, 0xe4, 0x9e, 0x65, 0x22, 0xd2, 0x2e, 0xc4, + 0xc4, 0xa7, 0xbe, 0xea, 0x3a, 0x1b, 0x07, 0xab, 0xb5, 0x8d, 0xf9, 0x78, 0x4a, 0x96, 0xad, 0x67, 0x97, 0x11, 0xbc, + 0xec, 0x38, 0x81, 0xc7, 0x77, 0x44, 0x17, 0x13, 0xd7, 0x48, 0x2a, 0x1a, 0x70, 0xc5, 0xd9, 0x46, 0x53, 0xbc, 0xef, + 0x53, 0xa0, 0xc3, 0xa2, 0xb9, 0x47, 0x65, 0xd0, 0x85, 0x80, 0x8e, 0x77, 0xee, 0x5e, 0x17, 0xc6, 0x6e, 0x9e, 0x28, + 0xad, 0xff, 0xc1, 0xad, 0x26, 0x2a, 0x0d, 0xeb, 0xb0, 0x04, 0x8a, 0x09, 0x39, 0xd1, 0x6e, 0xcc, 0xed, 0xd1, 0x43, + 0xc3, 0x67, 0x75, 0xd1, 0x68, 0x0d, 0xc4, 0x59, 0xe0, 0xf9, 0xdb, 0xb0, 0xb6, 0xb5, 0x11, 0x71, 0xff, 0x6b, 0x32, + 0x8a, 0x5a, 0x6e, 0x45, 0xe5, 0xcf, 0x3a, 0xc2, 0x45, 0x92, 0x81, 0xd9, 0x32, 0xfc, 0x46, 0x84, 0xd5, 0x1f, 0x21, + 0xe6, 0x1e, 0x87, 0x36, 0x21, 0xfd, 0xa5, 0x2d, 0xaf, 0xad, 0x87, 0x41, 0xc8, 0x87, 0x23, 0x9e, 0xa0, 0x88, 0x35, + 0xaa, 0x7b, 0x70, 0x32, 0x6c, 0x9c, 0x03, 0xab, 0xb6, 0x8b, 0x32, 0x0b, 0x67, 0x91, 0x91, 0x62, 0xe6, 0x33, 0xdb, + 0x04, 0x3e, 0x86, 0x0e, 0x3a, 0xa9, 0x3a, 0x75, 0x72, 0x50, 0x0d, 0x02, 0x30, 0x21, 0x0b, 0xed, 0x0b, 0x84, 0xae, + 0x11, 0x2c, 0xcb, 0x4a, 0xa5, 0xd5, 0x7a, 0x00, 0x8b, 0x8f, 0x50, 0xea, 0x17, 0x9f, 0xb8, 0xd5, 0x93, 0xce, 0xc1, + 0x28, 0xe2, 0xd0, 0x93, 0x5e, 0x8a, 0x3e, 0x45, 0x1e, 0x8b, 0x1d, 0x08, 0xb9, 0xb8, 0xf5, 0x4e, 0x36, 0x23, 0x1b, + 0x09, 0x5a, 0x09, 0xee, 0x01, 0x5a, 0xf7, 0xdc, 0x6a, 0x67, 0x3a, 0x21, 0xd0, 0x12, 0x69, 0x8c, 0x90, 0xe8, 0x1e, + 0x62, 0x0e, 0x89, 0x08, 0xf0, 0xa2, 0x60, 0x82, 0x29, 0x85, 0xb2, 0xb3, 0x1e, 0x52, 0xe8, 0xfd, 0x95, 0x65, 0x5c, + 0x4d, 0x64, 0x1e, 0x58, 0x61, 0x20, 0x8c, 0x33, 0x5f, 0x23, 0x0f, 0x09, 0x20, 0x67, 0x68, 0xfb, 0xa3, 0xa6, 0x47, + 0x6b, 0x33, 0x67, 0xda, 0xb8, 0x42, 0x36, 0x3e, 0x07, 0x45, 0xbc, 0x60, 0xc2, 0xf5, 0x59, 0xfd, 0xb8, 0xca, 0x75, + 0xa5, 0xe3, 0xd5, 0x8d, 0x94, 0xfb, 0x2a, 0xfe, 0xec, 0x12, 0x23, 0x59, 0x36, 0xbd, 0x69, 0x2a, 0x3d, 0x9d, 0x5a, + 0x7d, 0x67, 0x35, 0xd0, 0xb3, 0x3d, 0xc0, 0x13, 0x1e, 0x82, 0x4b, 0xcd, 0xc8, 0x2f, 0xb9, 0x04, 0x2d, 0xe0, 0x87, + 0x26, 0xa4, 0x23, 0x15, 0x0c, 0x8b, 0x79, 0x91, 0x96, 0xd3, 0xb2, 0xd8, 0x26, 0x35, 0x65, 0x60, 0x18, 0xc7, 0x64, + 0xa2, 0xc2, 0xa9, 0xfd, 0x03, 0xbf, 0xe7, 0xd9, 0x8c, 0x3c, 0xcd, 0x1a, 0x64, 0xf7, 0x6d, 0x9a, 0xc7, 0x2a, 0x17, + 0xd6, 0xda, 0x0a, 0x10, 0x7e, 0xc7, 0xbb, 0x82, 0xde, 0x48, 0xd1, 0x64, 0x98, 0xc1, 0x68, 0x69, 0xfc, 0xc8, 0xe0, + 0x7f, 0x97, 0x61, 0x55, 0xda, 0xa2, 0x06, 0x6e, 0x5f, 0xc4, 0x52, 0x1f, 0x94, 0x28, 0xd2, 0x56, 0x19, 0x62, 0xcb, + 0x63, 0x15, 0x7e, 0x57, 0x45, 0x47, 0x90, 0x61, 0xbb, 0x7e, 0xe6, 0xa8, 0xcd, 0xb1, 0x1f, 0x0e, 0x59, 0xb1, 0x27, + 0x73, 0x06, 0xc5, 0xc7, 0xfd, 0xc5, 0xa2, 0xab, 0x3a, 0x49, 0xcf, 0x16, 0x81, 0xba, 0x42, 0xc6, 0x53, 0xaf, 0x74, + 0x37, 0x52, 0x58, 0x6a, 0x64, 0x2b, 0xa0, 0x0c, 0x33, 0x54, 0x4b, 0x53, 0x74, 0xfb, 0x3d, 0x2b, 0x84, 0x44, 0x09, + 0x01, 0x46, 0x78, 0xef, 0x85, 0x2e, 0xfa, 0x7f, 0x9a, 0x37, 0xbe, 0x6f, 0x9d, 0x3a, 0x36, 0x0f, 0x47, 0x48, 0x09, + 0x10, 0x32, 0x29, 0xd7, 0xd0, 0x0f, 0x86, 0x82, 0xf1, 0x20, 0x51, 0x30, 0xf8, 0x39, 0xf6, 0x23, 0xe0, 0x66, 0x96, + 0x96, 0x47, 0x7e, 0x11, 0x4d, 0x4c, 0x89, 0xc7, 0x74, 0x46, 0x2a, 0xb7, 0xfb, 0x88, 0xab, 0x47, 0xba, 0x41, 0xf5, + 0x2d, 0x8a, 0x60, 0xf2, 0x2f, 0x35, 0x10, 0xde, 0xbd, 0x8e, 0xb9, 0x74, 0x9b, 0x9a, 0x37, 0x39, 0x00, 0xd3, 0xbd, + 0x2d, 0x51, 0xd7, 0x02, 0xa4, 0xde, 0x34, 0x85, 0x1f, 0xf6, 0x4f, 0x11, 0xb0, 0x38, 0x62, 0xb1, 0x49, 0x9d, 0x9e, + 0x53, 0xed, 0x7d, 0xb1, 0x6c, 0x04, 0xe1, 0xfe, 0x2a, 0xbb, 0xc8, 0x5d, 0x20, 0x90, 0xc9, 0x1a, 0x64, 0x10, 0x8e, + 0x35, 0xc3, 0x7a, 0x47, 0xab, 0xb2, 0xb1, 0x26, 0xad, 0xdd, 0xc7, 0xa5, 0xb4, 0xfb, 0x5a, 0x17, 0x0d, 0xa8, 0x81, + 0x21, 0xbc, 0xd6, 0xa2, 0x6d, 0x25, 0x60, 0x5e, 0xd5, 0xd8, 0x23, 0x98, 0x4b, 0x71, 0x29, 0xae, 0x25, 0x24, 0x1f, + 0x3f, 0x6a, 0x47, 0x8f, 0xd0, 0xd0, 0x64, 0xe3, 0xd3, 0x8d, 0x3c, 0x6d, 0xcf, 0x3f, 0xa8, 0x9d, 0xd8, 0xf7, 0xcb, + 0xe8, 0x40, 0xc8, 0xee, 0xd8, 0xfd, 0xe8, 0x87, 0x6f, 0x06, 0xce, 0x23, 0xda, 0xa9, 0xe1, 0xe1, 0xd0, 0x9b, 0x5c, + 0x2c, 0x99, 0xe6, 0x90, 0x3b, 0xa0, 0x29, 0xe3, 0x63, 0x6b, 0x03, 0x71, 0xad, 0x17, 0x12, 0x36, 0xd3, 0x10, 0x53, + 0xf9, 0x51, 0x63, 0x04, 0xc4, 0x28, 0x36, 0xd8, 0xc0, 0xb4, 0xef, 0x05, 0x6a, 0x36, 0x3f, 0x87, 0x55, 0x4e, 0x6d, + 0x11, 0x33, 0x4b, 0x72, 0x59, 0xa4, 0x05, 0x01, 0x2b, 0x8c, 0x81, 0xb3, 0x50, 0x95, 0x54, 0x2f, 0x4a, 0x24, 0x3d, + 0xc7, 0x11, 0x70, 0x50, 0x2e, 0xed, 0x3f, 0x0f, 0x82, 0x25, 0xa1, 0xf7, 0xb3, 0x30, 0x4b, 0x9b, 0xa5, 0xb4, 0x8c, + 0x2c, 0xa8, 0x84, 0x1a, 0xa9, 0x3e, 0x2f, 0x25, 0x79, 0x9c, 0x14, 0xfc, 0xce, 0xd8, 0x6c, 0x46, 0xf2, 0xe5, 0xe2, + 0xdd, 0xf8, 0x4b, 0xc5, 0xdf, 0x42, 0x32, 0x7d, 0x28, 0x80, 0x05, 0x34, 0x49, 0xaf, 0x31, 0xe8, 0xbe, 0x5e, 0xdc, + 0x96, 0x22, 0xfc, 0x6d, 0x00, 0x5a, 0xa5, 0x79, 0x9d, 0x1d, 0x4f, 0x19, 0xaf, 0x9d, 0xfc, 0x65, 0x9a, 0xa4, 0x29, + 0x18, 0xae, 0x03, 0xf3, 0x0c, 0xdd, 0x94, 0xa0, 0x1f, 0x31, 0x57, 0x5f, 0xaa, 0x97, 0x5c, 0x3c, 0x4d, 0x91, 0xb3, + 0x5b, 0xba, 0xde, 0x73, 0x36, 0x52, 0x81, 0x59, 0xa9, 0x7c, 0xff, 0x95, 0x34, 0x2b, 0xd0, 0xea, 0x13, 0xf7, 0x94, + 0x81, 0xd0, 0xd5, 0xa4, 0x44, 0xba, 0xbb, 0x85, 0x9a, 0x5e, 0x5b, 0x4c, 0x60, 0x2a, 0x55, 0xa8, 0xbd, 0x63, 0xd6, + 0x45, 0xdc, 0xfb, 0x77, 0x74, 0xed, 0x76, 0xe7, 0x56, 0xba, 0x08, 0xd8, 0x63, 0xc2, 0x18, 0x88, 0x1e, 0xc3, 0xa9, + 0x6b, 0xae, 0xb7, 0x95, 0x35, 0xd7, 0x05, 0x7e, 0x96, 0x08, 0xb2, 0x71, 0xe5, 0x0e, 0xac, 0xcc, 0x45, 0x10, 0x30, + 0x7f, 0xdb, 0xf8, 0x85, 0x27, 0x44, 0x26, 0x82, 0xb7, 0xec, 0xf8, 0x18, 0x2f, 0xeb, 0x7d, 0x76, 0xfc, 0x0a, 0xb6, + 0x4e, 0xad, 0x14, 0x36, 0x61, 0x20, 0x95, 0x00, 0xeb, 0xbb, 0xe4, 0xe9, 0x70, 0x61, 0xb6, 0x8a, 0xc2, 0xf5, 0x41, + 0x26, 0xe0, 0xb1, 0xa0, 0x94, 0xd4, 0x25, 0x7c, 0x1f, 0xc7, 0x07, 0x5f, 0x27, 0x0d, 0x58, 0x04, 0x2d, 0x09, 0x38, + 0x5b, 0x8f, 0x34, 0xd8, 0xd4, 0x8b, 0x6a, 0xc7, 0xb7, 0x28, 0x9c, 0xb7, 0x8c, 0xf5, 0x30, 0x08, 0xf7, 0xb8, 0x6d, + 0x5f, 0xe1, 0x00, 0xbf, 0x79, 0x43, 0x3d, 0x3e, 0xf0, 0xe1, 0x35, 0xba, 0x28, 0x3a, 0x54, 0x4d, 0xf1, 0xa7, 0x05, + 0x69, 0x5e, 0x1a, 0xe6, 0x70, 0x6f, 0x25, 0x5d, 0xf0, 0x82, 0xf1, 0x30, 0x22, 0x1a, 0x9b, 0xf4, 0xa0, 0x00, 0x9e, + 0xeb, 0xde, 0xcd, 0xbd, 0x7b, 0x2d, 0x49, 0xb5, 0x88, 0x36, 0x69, 0xe2, 0xbb, 0xb5, 0x66, 0x92, 0x35, 0x20, 0x49, + 0x69, 0xaf, 0xd8, 0x91, 0x50, 0xe2, 0xf5, 0x6f, 0xd2, 0xb3, 0x00, 0xc5, 0x77, 0xb3, 0xeb, 0x31, 0xe8, 0x52, 0xcf, + 0xd2, 0x0b, 0x56, 0x4b, 0xa0, 0x9a, 0xa9, 0x6a, 0xb2, 0xe1, 0x14, 0xd2, 0xd9, 0xd7, 0xc9, 0x2e, 0x3a, 0xa7, 0xa4, + 0x10, 0x4a, 0x19, 0xf5, 0x4c, 0xaa, 0x88, 0xe8, 0x58, 0x06, 0x3f, 0x2b, 0xcc, 0xa5, 0x3b, 0x68, 0x04, 0x16, 0x63, + 0x44, 0x6e, 0xc2, 0x61, 0xdf, 0xb7, 0x29, 0x01, 0xa1, 0x7e, 0xd7, 0x4e, 0x9c, 0xf5, 0x06, 0x07, 0x76, 0xbe, 0xff, + 0x03, 0x5f, 0x2b, 0x9f, 0x80, 0xd0, 0xc3, 0x89, 0x66, 0x49, 0xf1, 0x17, 0x2f, 0x3d, 0xf1, 0x4e, 0xac, 0xa4, 0x6e, + 0x3f, 0xf1, 0x87, 0x7f, 0x91, 0x2a, 0x6a, 0x1c, 0xc4, 0xb9, 0x75, 0x7f, 0x25, 0x0d, 0x8d, 0x1c, 0xad, 0x89, 0x7b, + 0x00, 0xb0, 0xd0, 0x84, 0x8a, 0xb0, 0x9c, 0x91, 0x34, 0xfc, 0x4c, 0xfd, 0xc4, 0x92, 0x27, 0x14, 0x2b, 0x04, 0x48, + 0xe0, 0xfb, 0xf7, 0x12, 0x5c, 0xb9, 0xef, 0x01, 0xfc, 0xc3, 0x62, 0x04, 0x5a, 0xc5, 0x12, 0x0d, 0x75, 0xf3, 0x91, + 0xf5, 0xdd, 0xe1, 0xa2, 0xd5, 0xd9, 0x46, 0x08, 0x2a, 0x74, 0xd7, 0x21, 0x40, 0xd8, 0xa7, 0x11, 0x78, 0xf2, 0xaf, + 0x92, 0xb8, 0xad, 0x64, 0x33, 0x1d, 0x76, 0xd7, 0x79, 0x05, 0xde, 0x3d, 0xe8, 0x17, 0x2b, 0xe3, 0x5d, 0xe5, 0x91, + 0xf5, 0xf1, 0xbf, 0x9f, 0x94, 0x5d, 0x52, 0x1b, 0x64, 0xa5, 0x00, 0xc4, 0x6a, 0xa4, 0xd7, 0x38, 0xd3, 0x54, 0xeb, + 0xd0, 0x5a, 0x93, 0x6d, 0x21, 0x6c, 0x87, 0xb0, 0x82, 0x07, 0xab, 0x19, 0x51, 0x27, 0x34, 0xb6, 0xb8, 0x97, 0x1e, + 0xba, 0xeb, 0xdd, 0x8b, 0xa0, 0xf2, 0x98, 0x1d, 0x32, 0x0f, 0x80, 0xef, 0x71, 0x63, 0x37, 0xc8, 0xac, 0xc0, 0x05, + 0x1c, 0x04, 0x8c, 0x5d, 0xcf, 0x5d, 0x30, 0xe4, 0x7a, 0x16, 0x37, 0x1c, 0xf6, 0x44, 0x03, 0x65, 0xd7, 0x01, 0x4d, + 0xa1, 0x75, 0x52, 0x91, 0xc6, 0xd0, 0x03, 0xbf, 0xaf, 0xc0, 0x3a, 0xeb, 0x51, 0x6c, 0x67, 0xd6, 0xe5, 0xb9, 0x54, + 0x78, 0x5a, 0xbc, 0x5e, 0xdb, 0xf4, 0x31, 0x1d, 0x9a, 0xad, 0x09, 0xdf, 0xeb, 0x2e, 0x60, 0x21, 0xac, 0xd4, 0x25, + 0x49, 0x5e, 0xd6, 0x1f, 0x2f, 0x32, 0x9a, 0x85, 0xc7, 0x5c, 0xda, 0x66, 0xf6, 0xdf, 0xef, 0x5f, 0xa0, 0xb5, 0x42, + 0xe1, 0xd3, 0x51, 0x40, 0x66, 0x25, 0x6d, 0x08, 0xde, 0xea, 0x6f, 0x36, 0xdb, 0x2c, 0xee, 0x5f, 0xdf, 0x55, 0xec, + 0xf5, 0xaf, 0x6f, 0xba, 0x71, 0x93, 0x02, 0xaf, 0x51, 0x50, 0x74, 0x6e, 0xb6, 0x27, 0x38, 0x21, 0xce, 0xad, 0x4a, + 0x58, 0xe7, 0x76, 0xfc, 0xb4, 0xa6, 0x4f, 0xff, 0xe0, 0x1d, 0x77, 0x80, 0x47, 0x2d, 0x4e, 0x96, 0x76, 0x4c, 0x3d, + 0x72, 0x16, 0x75, 0x2f, 0x3d, 0xec, 0x03, 0x9b, 0xc2, 0xe6, 0x96, 0xee, 0x7b, 0xfb, 0xd9, 0x73, 0x69, 0x8e, 0xb7, + 0xfa, 0xab, 0xfc, 0x95, 0xfb, 0xc6, 0x2a, 0x3b, 0x34, 0xac, 0xdd, 0x54, 0x49, 0x31, 0x5b, 0x7a, 0x99, 0xf5, 0x47, + 0xe1, 0x72, 0x9f, 0x3e, 0x17, 0x1a, 0xc5, 0x3d, 0x4e, 0x18, 0xb9, 0x09, 0x21, 0x1f, 0x7e, 0x49, 0x6c, 0x23, 0xf3, + 0x8f, 0x5b, 0x95, 0x31, 0x08, 0x22, 0xcf, 0x8e, 0x5a, 0x2f, 0xcb, 0x9c, 0x53, 0xe2, 0x62, 0x9e, 0x93, 0xe0, 0x17, + 0x34, 0xc2, 0xd1, 0x2a, 0xfb, 0x4b, 0x1d, 0xb6, 0x3b, 0x2c, 0x2b, 0x07, 0x1a, 0x37, 0xfb, 0x04, 0x9c, 0x11, 0x5d, + 0xab, 0xb0, 0xa3, 0xdd, 0xc8, 0xec, 0x62, 0xc3, 0xe1, 0xae, 0xb0, 0x04, 0xfc, 0xfc, 0x05, 0x8c, 0x41, 0xb7, 0x62, + 0xba, 0x52, 0xfb, 0x81, 0x41, 0xaa, 0x6a, 0x0f, 0xa5, 0xb8, 0x87, 0xe6, 0xca, 0xb4, 0x6b, 0xbd, 0xa3, 0x8e, 0x30, + 0xa0, 0x0e, 0xba, 0x0b, 0x1e, 0xb3, 0x02, 0x5c, 0xd7, 0x6d, 0xeb, 0xb8, 0xcb, 0x1a, 0x3b, 0xf1, 0x31, 0x5d, 0xfb, + 0xe7, 0xe0, 0xa8, 0x64, 0x47, 0xb7, 0x15, 0x27, 0xcc, 0xb0, 0xf2, 0xff, 0x14, 0x2e, 0x4f, 0x6f, 0x15, 0x6c, 0x0f, + 0x0d, 0xf5, 0xf9, 0x14, 0x6c, 0x75, 0x03, 0x1b, 0x1c, 0x41, 0x9b, 0x77, 0x72, 0x5d, 0xd2, 0x29, 0x13, 0xb2, 0xa6, + 0xb7, 0xa4, 0x29, 0x13, 0x9c, 0xe4, 0x5c, 0xc1, 0x7c, 0x2e, 0xce, 0x4c, 0x3e, 0x34, 0xa8, 0x15, 0x24, 0x6b, 0xc7, + 0x5e, 0x47, 0x5f, 0x88, 0xec, 0x7a, 0xce, 0xac, 0x75, 0xbf, 0x16, 0x9a, 0xc4, 0x72, 0xa8, 0x03, 0xe7, 0xeb, 0xdc, + 0xfc, 0x09, 0x0c, 0x01, 0x8f, 0xbf, 0xca, 0x18, 0xe7, 0x26, 0xed, 0x39, 0x33, 0xcb, 0x54, 0x2f, 0x15, 0x62, 0xd0, + 0xb7, 0x61, 0x42, 0x15, 0x8d, 0x17, 0xb3, 0xab, 0x54, 0x04, 0x46, 0x3e, 0x2c, 0x28, 0x43, 0x97, 0xe7, 0x1c, 0xe7, + 0x0d, 0xe5, 0x59, 0x64, 0x66, 0x00, 0x6c, 0xb4, 0x5d, 0x46, 0x09, 0xf7, 0x2e, 0xd3, 0x90, 0xd5, 0xa3, 0xb2, 0x79, + 0x8f, 0x3a, 0xbd, 0x68, 0x60, 0x05, 0xae, 0x9c, 0xae, 0x38, 0x9c, 0x14, 0x6a, 0x82, 0xb8, 0xcf, 0xfb, 0x84, 0x58, + 0x36, 0x2e, 0x31, 0x31, 0xcd, 0xb2, 0x2e, 0xef, 0xee, 0x77, 0x11, 0x34, 0x72, 0x42, 0x83, 0x85, 0x77, 0xf8, 0x0b, + 0xd8, 0x1d, 0xaf, 0xac, 0xc9, 0x0d, 0x86, 0xdf, 0x08, 0x24, 0xd3, 0x11, 0x42, 0x19, 0x4b, 0xe0, 0x76, 0xfa, 0xe9, + 0x7e, 0x0b, 0x6e, 0x1d, 0x22, 0x3d, 0x70, 0xb4, 0x10, 0x6c, 0xad, 0xb0, 0x36, 0x95, 0xe3, 0x86, 0x43, 0x71, 0x13, + 0x1a, 0x91, 0x8a, 0x68, 0x75, 0x89, 0x9e, 0xec, 0x0e, 0x41, 0xc4, 0xce, 0x21, 0x4b, 0x10, 0x41, 0x93, 0xa3, 0xfb, + 0x11, 0x5a, 0x96, 0x58, 0x22, 0x0d, 0x89, 0x5c, 0x77, 0x9e, 0xa1, 0x8a, 0x11, 0xd8, 0x76, 0x4a, 0x5d, 0x5b, 0x43, + 0xc1, 0x65, 0x6f, 0xd0, 0x75, 0x33, 0xc1, 0x89, 0x56, 0x42, 0x99, 0xd1, 0x29, 0xb9, 0x8f, 0xe9, 0x53, 0x3f, 0xca, + 0xc9, 0x28, 0x55, 0x37, 0xcc, 0xf5, 0x05, 0x42, 0x11, 0x88, 0x53, 0x97, 0x97, 0x53, 0xb5, 0x25, 0x65, 0xae, 0xb4, + 0x04, 0x73, 0xa4, 0xff, 0xb4, 0x47, 0x0d, 0xd9, 0x7a, 0x37, 0xec, 0xb4, 0xe9, 0x61, 0xd6, 0x42, 0x11, 0x8e, 0xb9, + 0x62, 0xb0, 0xda, 0xed, 0x23, 0x72, 0x6d, 0x83, 0xe9, 0x33, 0xbd, 0x9c, 0x86, 0x74, 0xa7, 0x57, 0x43, 0x33, 0x87, + 0x15, 0x7e, 0x28, 0xca, 0x3d, 0xe6, 0xe3, 0x76, 0x7f, 0x34, 0xf1, 0x59, 0x65, 0xdd, 0x7c, 0xc8, 0x7f, 0x85, 0xf4, + 0x73, 0x59, 0x8a, 0x93, 0xab, 0x1e, 0x78, 0xdb, 0x17, 0x06, 0x42, 0x2a, 0x57, 0x37, 0x9b, 0x5c, 0xc2, 0xb4, 0x13, + 0xb1, 0x4e, 0x64, 0x56, 0xbe, 0x89, 0x6c, 0x36, 0xda, 0x57, 0x7d, 0xaf, 0x5d, 0xbd, 0x29, 0x68, 0x5c, 0xab, 0x5f, + 0x74, 0x4b, 0x67, 0x7f, 0x6f, 0x95, 0x36, 0x74, 0x23, 0x1b, 0xe3, 0x0e, 0x44, 0xdb, 0xa5, 0x15, 0x45, 0x94, 0x5f, + 0x72, 0x72, 0x2f, 0x9d, 0x1f, 0x13, 0x1f, 0x8d, 0xef, 0xd2, 0x3e, 0x87, 0x23, 0x7c, 0x98, 0xfc, 0x0f, 0x27, 0x59, + 0x7f, 0xf7, 0x63, 0xd1, 0x9e, 0xf3, 0xbb, 0xad, 0x3b, 0xd8, 0x72, 0x3b, 0x96, 0x6e, 0xce, 0x65, 0x03, 0x7d, 0x17, + 0xe7, 0xf8, 0x2f, 0xbb, 0x9d, 0x94, 0xf5, 0xc1, 0x32, 0x85, 0x1c, 0x87, 0x09, 0x16, 0xa5, 0x9e, 0x14, 0xfa, 0x90, + 0x37, 0x34, 0xcd, 0x6a, 0x17, 0x93, 0xd7, 0x01, 0x02, 0x3f, 0x16, 0x75, 0xa1, 0x03, 0x99, 0x2a, 0xdd, 0x1a, 0x3f, + 0x1c, 0xd0, 0x47, 0x18, 0x13, 0xaa, 0x89, 0xe4, 0xb7, 0x04, 0x79, 0x17, 0x0a, 0xec, 0x71, 0x13, 0xb0, 0xa6, 0xd1, + 0x41, 0xa6, 0xae, 0x04, 0x49, 0xe4, 0x40, 0x2f, 0x7a, 0x07, 0xa1, 0x9d, 0x73, 0xd1, 0xe8, 0xaf, 0x57, 0xef, 0x9e, + 0x90, 0x9b, 0xad, 0xb2, 0xb3, 0x98, 0xb5, 0x87, 0x81, 0x58, 0xed, 0x4b, 0xdd, 0xf5, 0xba, 0x10, 0x18, 0x36, 0xfe, + 0x9b, 0x8d, 0x39, 0xc0, 0x76, 0x5e, 0x16, 0x7b, 0x57, 0xc0, 0x2f, 0xc1, 0x7f, 0xb5, 0x25, 0x0a, 0x4b, 0x74, 0x66, + 0x46, 0xe9, 0xe0, 0xee, 0x5b, 0xa8, 0x69, 0x08, 0x7a, 0x25, 0x2f, 0x69, 0xc4, 0xad, 0x94, 0xcb, 0x5b, 0x59, 0x63, + 0xf5, 0xd1, 0x30, 0xe5, 0xf1, 0x6b, 0x2d, 0xa0, 0x0b, 0x74, 0x81, 0x18, 0x1a, 0x52, 0x5b, 0xd2, 0x30, 0x05, 0x92, + 0x46, 0x6e, 0x1f, 0xb4, 0xb0, 0xc2, 0x69, 0xda, 0x46, 0x10, 0x27, 0xff, 0x0e, 0xc2, 0x70, 0xce, 0xef, 0xb6, 0x16, + 0x82, 0x1b, 0x88, 0xb4, 0x41, 0x56, 0x4e, 0x85, 0x5d, 0x01, 0xcd, 0xb7, 0x01, 0xa3, 0x15, 0x26, 0x19, 0x32, 0x49, + 0xf7, 0xe3, 0x3f, 0xf2, 0x0e, 0xbf, 0x3a, 0x73, 0x1e, 0x0a, 0x46, 0x0c, 0xb4, 0x43, 0x23, 0x1f, 0x14, 0xdc, 0x4e, + 0x96, 0xbd, 0xa0, 0x2e, 0x89, 0x59, 0xca, 0xe0, 0x14, 0x37, 0x85, 0xbe, 0x7c, 0x1c, 0x0e, 0x2a, 0x78, 0x63, 0x2c, + 0x0e, 0x74, 0x96, 0x82, 0x95, 0x0f, 0x7a, 0x96, 0x4e, 0x04, 0x98, 0x02, 0x9d, 0xc6, 0xd1, 0x6e, 0xc6, 0x5d, 0x29, + 0xdd, 0x0b, 0x50, 0x38, 0x2f, 0xa4, 0xd9, 0x08, 0x0a, 0x60, 0x37, 0x46, 0x4b, 0xf2, 0x8f, 0xbc, 0xc3, 0xf7, 0x33, + 0x71, 0x95, 0x5b, 0xe2, 0xd7, 0xca, 0x47, 0x0c, 0x64, 0x53, 0x7f, 0xb0, 0x7e, 0x4d, 0xcd, 0xd5, 0xee, 0x24, 0x1d, + 0x8e, 0xc3, 0x00, 0x38, 0xe6, 0x28, 0x96, 0x83, 0x58, 0x56, 0x20, 0xc9, 0x39, 0xb1, 0x5c, 0x3f, 0xe6, 0xcf, 0x49, + 0x62, 0x5f, 0xb5, 0x14, 0x57, 0xb8, 0x16, 0x4f, 0x8b, 0xe4, 0xc4, 0x1b, 0xfc, 0x2a, 0xfa, 0xef, 0xf6, 0x52, 0xc6, + 0x30, 0xf7, 0x53, 0x8c, 0x70, 0x43, 0xde, 0x32, 0x9f, 0x26, 0x81, 0x72, 0x56, 0x97, 0x83, 0x32, 0x9f, 0x5d, 0x2c, + 0x59, 0xe7, 0xd9, 0xf8, 0x4e, 0xce, 0x5b, 0xd7, 0xbd, 0xb0, 0x3f, 0x7a, 0x28, 0xdf, 0x1f, 0x2b, 0xff, 0x1e, 0x88, + 0x73, 0x28, 0x86, 0x11, 0x2b, 0x36, 0xea, 0xed, 0x49, 0xbe, 0x96, 0x0d, 0x74, 0xa4, 0x88, 0xf4, 0x95, 0x25, 0x3d, + 0x9f, 0x18, 0xd6, 0x45, 0x34, 0xf7, 0x6f, 0x30, 0x5d, 0x74, 0xf0, 0x0e, 0x13, 0x0c, 0xde, 0x2c, 0x4d, 0x5b, 0xdc, + 0x8f, 0x6d, 0x6a, 0x54, 0x28, 0x9c, 0x19, 0xd4, 0xb6, 0xc6, 0x0b, 0xec, 0x29, 0x5c, 0xfc, 0xc4, 0x39, 0x69, 0x5e, + 0x61, 0xb8, 0xb1, 0xa3, 0x95, 0x68, 0xa4, 0xb5, 0x1c, 0x1d, 0x74, 0xc8, 0xe4, 0xbd, 0x9c, 0x14, 0xb3, 0x48, 0x82, + 0x70, 0x5e, 0x2b, 0x1f, 0x4d, 0xbd, 0xb7, 0xb5, 0x6f, 0x30, 0xee, 0x02, 0x19, 0xb8, 0x4c, 0x16, 0x5a, 0x9a, 0x78, + 0xd9, 0x6d, 0xbe, 0x6d, 0xc3, 0x32, 0xe6, 0x56, 0x94, 0x55, 0x8c, 0x31, 0x89, 0x29, 0xda, 0xc5, 0xb2, 0xf1, 0x08, + 0xa6, 0x2e, 0x91, 0x24, 0x44, 0x96, 0xd1, 0x12, 0x8d, 0x6d, 0x50, 0xfa, 0x22, 0x66, 0x61, 0x30, 0xf2, 0x3f, 0xb3, + 0xf8, 0xcb, 0xb5, 0x7e, 0x2d, 0xcd, 0x14, 0xdd, 0x29, 0xf7, 0x6a, 0x6c, 0xdb, 0xe5, 0xf6, 0x6b, 0x3b, 0x44, 0x79, + 0xfd, 0x0a, 0x9e, 0x02, 0x4d, 0x8a, 0xe0, 0x10, 0x11, 0x68, 0x95, 0xf5, 0x45, 0x2d, 0x6d, 0x4b, 0x47, 0x7e, 0x4a, + 0x36, 0x11, 0xce, 0xf9, 0x21, 0xc4, 0xb3, 0x0a, 0xa2, 0x2e, 0x4b, 0x2f, 0x22, 0x1b, 0xb4, 0xb6, 0x3e, 0xd2, 0xa9, + 0x54, 0xc3, 0x07, 0x86, 0x22, 0xf2, 0x3d, 0xbc, 0x3a, 0x09, 0x5d, 0xda, 0x5a, 0x45, 0x49, 0xbc, 0x44, 0x3a, 0x7e, + 0x22, 0xab, 0x0e, 0x51, 0x24, 0xa8, 0x16, 0x0c, 0x6a, 0x05, 0xb8, 0x1c, 0x54, 0xb5, 0x37, 0x5b, 0x91, 0x08, 0x82, + 0x68, 0xb0, 0x8a, 0x0f, 0xd4, 0xed, 0x28, 0xc8, 0x24, 0xd2, 0x13, 0x63, 0x93, 0xf1, 0xe6, 0x85, 0xe4, 0x5e, 0x91, + 0x46, 0xa0, 0x4f, 0x9c, 0xd4, 0xb3, 0x71, 0x92, 0xf5, 0xfe, 0xa6, 0x8f, 0x1c, 0x1c, 0x37, 0x58, 0x4a, 0x8f, 0x62, + 0x07, 0xc7, 0x7a, 0x4e, 0x64, 0x2b, 0x29, 0xeb, 0x1c, 0x4a, 0x15, 0x6f, 0xc6, 0x28, 0x72, 0x2c, 0x63, 0x32, 0x70, + 0x36, 0x07, 0xd1, 0xb6, 0xa3, 0xf7, 0x94, 0xd8, 0xc8, 0x15, 0xf5, 0x02, 0xa5, 0x4e, 0xfc, 0xef, 0x13, 0xb4, 0xdf, + 0x6e, 0x4f, 0x08, 0xbd, 0x9d, 0x45, 0xb7, 0xf0, 0x45, 0xc7, 0x32, 0x6e, 0x0e, 0xdd, 0x49, 0x88, 0x63, 0x8a, 0x16, + 0x78, 0xc7, 0x0a, 0xc5, 0xb9, 0x68, 0x48, 0xec, 0x72, 0x6c, 0xd4, 0xfc, 0x54, 0x4d, 0x5d, 0xd6, 0x0a, 0xe9, 0x5d, + 0xfe, 0x1b, 0xf3, 0xbb, 0xfc, 0xf9, 0xf1, 0xa9, 0xca, 0xf5, 0x3a, 0x35, 0xc4, 0xe2, 0x0d, 0x2d, 0x13, 0x8d, 0x15, + 0x5e, 0x54, 0xc3, 0x1e, 0x25, 0x5b, 0x8b, 0xf4, 0x62, 0x65, 0xd5, 0x4c, 0xe4, 0x21, 0x09, 0x42, 0xd4, 0xe8, 0x84, + 0xba, 0x5b, 0xb8, 0xd0, 0xf8, 0x1d, 0x46, 0x26, 0x92, 0x01, 0x25, 0xdb, 0xea, 0x96, 0xfa, 0x51, 0x4b, 0x4f, 0x3d, + 0x9f, 0xcc, 0x06, 0x57, 0x4d, 0xa3, 0x71, 0x3a, 0xa6, 0xc6, 0x89, 0xb7, 0x8f, 0x66, 0x7a, 0x8d, 0x06, 0x0b, 0xbc, + 0xb0, 0xbb, 0xfe, 0x0d, 0x74, 0xc4, 0x2d, 0x34, 0x4a, 0x6c, 0x48, 0xd6, 0x18, 0x93, 0x96, 0x30, 0x6d, 0x29, 0xb3, + 0x96, 0x71, 0xd0, 0x06, 0x1c, 0xb6, 0x21, 0x47, 0x6d, 0xc4, 0x71, 0x1b, 0xf3, 0x4b, 0x8b, 0xca, 0xaf, 0x33, 0x7a, + 0x4e, 0x66, 0x0c, 0x9c, 0xce, 0x18, 0xb9, 0xd3, 0x62, 0xe2, 0xee, 0x8c, 0x99, 0x5c, 0xb4, 0xba, 0xa8, 0x8a, 0x6a, + 0x51, 0x95, 0x95, 0xb2, 0x6f, 0x58, 0x92, 0x1b, 0xff, 0xa2, 0x64, 0xd4, 0x87, 0x98, 0x72, 0xd9, 0xea, 0xfe, 0xde, + 0xd3, 0xc9, 0x74, 0xe7, 0x25, 0x4c, 0xbc, 0x89, 0x22, 0x55, 0xe7, 0x96, 0xa9, 0x01, 0xf3, 0xe4, 0x95, 0xf9, 0x0d, + 0x09, 0x0d, 0x2c, 0x29, 0xb6, 0xdb, 0x1f, 0xcf, 0xfe, 0xed, 0x89, 0xaf, 0xaa, 0xee, 0x1b, 0x6f, 0x97, 0x9c, 0x9c, + 0xfb, 0xe0, 0xb9, 0x03, 0x8d, 0xa7, 0xe7, 0x0d, 0x63, 0xf7, 0x7e, 0x65, 0xd1, 0x2d, 0xca, 0x3c, 0x78, 0xd2, 0xf1, + 0x17, 0xe1, 0x5a, 0x32, 0xe9, 0xef, 0xd0, 0x21, 0x59, 0x6a, 0xe4, 0x46, 0xfd, 0xcd, 0x35, 0x68, 0xb4, 0xd3, 0xcc, + 0xd3, 0x8a, 0xb1, 0x7f, 0xa8, 0xd9, 0x90, 0xea, 0xcb, 0xcc, 0x72, 0xbe, 0x1c, 0x2d, 0x2a, 0xe3, 0x9c, 0x56, 0xb8, + 0xb1, 0xe2, 0x98, 0x67, 0xc7, 0x16, 0xf3, 0x49, 0x93, 0x47, 0xd5, 0xf0, 0x98, 0x4b, 0x41, 0x46, 0x62, 0xa1, 0xf7, + 0xfc, 0xd0, 0x1f, 0xb7, 0x26, 0xc3, 0x27, 0x6b, 0xbd, 0xbd, 0x79, 0xf3, 0xe4, 0x8d, 0xa6, 0x09, 0x15, 0xe7, 0x92, + 0xa4, 0x92, 0xce, 0x2d, 0x96, 0x64, 0xde, 0x80, 0x8d, 0x9a, 0x1b, 0xe7, 0x86, 0x42, 0xde, 0x08, 0x8d, 0xdc, 0x4e, + 0x99, 0x84, 0xf4, 0xfe, 0xfa, 0xf7, 0xfa, 0x9b, 0xd5, 0xe3, 0x7c, 0xfa, 0x03, 0xc3, 0x66, 0x02, 0x00, 0x46, 0x4b, + 0xdf, 0xfb, 0xcf, 0xeb, 0x37, 0xd5, 0xd3, 0xca, 0xaf, 0xeb, 0xe7, 0x55, 0xa9, 0x3d, 0x87, 0xd0, 0xc1, 0x1c, 0x5f, + 0xe6, 0x9d, 0x27, 0x1b, 0xb7, 0x2b, 0xb8, 0xdb, 0x0c, 0xdd, 0xb3, 0xd8, 0xc4, 0xc6, 0x64, 0xba, 0xf8, 0xfc, 0xd3, + 0x55, 0x1f, 0x4d, 0x91, 0xda, 0xee, 0xcf, 0xf5, 0x38, 0x1f, 0xf7, 0xf8, 0x3b, 0xf1, 0xcd, 0x8e, 0x38, 0x8b, 0xc2, + 0xa9, 0xfc, 0xe7, 0xa1, 0xf4, 0xb8, 0xfc, 0xc4, 0x45, 0xad, 0xb0, 0x66, 0xf0, 0x2c, 0xbf, 0xf7, 0xb7, 0x11, 0x0f, + 0x3c, 0x35, 0xae, 0xfb, 0xf9, 0x33, 0x96, 0xff, 0x45, 0xc5, 0x2a, 0x0f, 0x8f, 0x6f, 0xf1, 0xdd, 0xac, 0xd6, 0x24, + 0xd2, 0x34, 0x08, 0xc2, 0x8a, 0xfc, 0x50, 0xfd, 0xb0, 0x3c, 0x27, 0x89, 0xae, 0xfd, 0xa7, 0xc7, 0x33, 0x08, 0x1d, + 0x83, 0x78, 0x75, 0x4d, 0x14, 0x0f, 0x3f, 0xa0, 0x7c, 0x3c, 0x04, 0x73, 0x08, 0xf4, 0x5f, 0xdf, 0x8d, 0x09, 0xc7, + 0xce, 0x11, 0x82, 0x08, 0x6b, 0xbd, 0x9f, 0x9f, 0xf9, 0x40, 0x81, 0x0f, 0xa3, 0xff, 0x66, 0x52, 0x4c, 0x01, 0x72, + 0xea, 0x44, 0x4c, 0xff, 0x66, 0xa0, 0x64, 0x05, 0x3a, 0xa8, 0xeb, 0x40, 0xf1, 0xa0, 0x06, 0xdd, 0x4d, 0x8e, 0xe1, + 0x76, 0xce, 0x32, 0x75, 0x76, 0xa9, 0xd3, 0xf3, 0x93, 0x26, 0x64, 0xa7, 0x97, 0x6a, 0x52, 0xc0, 0x65, 0xf9, 0x75, + 0x74, 0xf7, 0x05, 0x64, 0x2c, 0xd0, 0x8d, 0x87, 0xb6, 0x89, 0x6f, 0x0e, 0x72, 0x79, 0xde, 0x98, 0xd7, 0x88, 0x37, + 0xc6, 0x3f, 0x3b, 0x20, 0x1c, 0x72, 0x4f, 0x72, 0xcc, 0x7d, 0xc4, 0x73, 0xe8, 0xfe, 0x94, 0x74, 0x3f, 0x6c, 0xf6, + 0x4e, 0x8b, 0xff, 0xb1, 0xca, 0xd1, 0x85, 0x51, 0xf2, 0xbc, 0xde, 0xe7, 0xa1, 0xb1, 0xb3, 0x32, 0xb5, 0x7a, 0x26, + 0x6d, 0x08, 0x0d, 0x76, 0xfc, 0xbc, 0x39, 0xe5, 0xfe, 0x4c, 0x6c, 0x94, 0x18, 0xcd, 0x40, 0xec, 0x24, 0xd3, 0xa0, + 0x51, 0x44, 0xe0, 0xff, 0x20, 0x06, 0xb5, 0x8b, 0x35, 0x42, 0x21, 0xac, 0xe5, 0x53, 0x68, 0x79, 0x35, 0x8f, 0xde, + 0x48, 0x57, 0xe2, 0xc4, 0x72, 0xa6, 0x39, 0xe6, 0x5c, 0xc5, 0xcf, 0xc9, 0x8e, 0x15, 0xbc, 0xc8, 0xf4, 0x16, 0x8e, + 0xe7, 0x47, 0xcc, 0xf8, 0xdc, 0x43, 0x77, 0x5c, 0x1c, 0x59, 0xb3, 0x80, 0x36, 0xd5, 0x6e, 0x80, 0x6a, 0x90, 0xc0, + 0xb5, 0x08, 0xfd, 0x5e, 0x25, 0x38, 0xd2, 0x9c, 0x97, 0xb5, 0x18, 0xf5, 0x44, 0x1e, 0x39, 0x1b, 0x5c, 0x8c, 0x7a, + 0x52, 0x79, 0x01, 0xc1, 0xa7, 0xa0, 0xdb, 0x06, 0xd5, 0x64, 0xd9, 0xbf, 0x24, 0xcd, 0x61, 0xa0, 0xd7, 0x58, 0x80, + 0x59, 0xf3, 0x8f, 0x52, 0xff, 0xfb, 0x4d, 0xc9, 0xbd, 0x21, 0xfe, 0x03, 0x20, 0xe6, 0xea, 0xa6, 0xcd, 0xb3, 0x51, + 0x95, 0x0b, 0xed, 0x12, 0x4e, 0x2f, 0x55, 0xbc, 0x86, 0x4d, 0x85, 0x72, 0x4a, 0x02, 0x51, 0x27, 0x9c, 0x2d, 0x1d, + 0x21, 0x3c, 0x4f, 0xd6, 0x0e, 0x4d, 0xe8, 0x3d, 0x60, 0xeb, 0x5d, 0x4b, 0xfb, 0x28, 0xe7, 0xf2, 0xec, 0xeb, 0xfc, + 0x64, 0x5f, 0x4e, 0x32, 0x19, 0xff, 0x89, 0x9a, 0xc6, 0x2b, 0xd4, 0x27, 0x15, 0xbd, 0x7e, 0x3e, 0x56, 0x94, 0xa4, + 0xb1, 0x1d, 0xf1, 0xab, 0xad, 0xc0, 0xff, 0x4a, 0x5f, 0x8b, 0x58, 0x75, 0xfa, 0x46, 0x8f, 0xa3, 0x2e, 0xe7, 0xd2, + 0xbf, 0xbc, 0xb1, 0x64, 0x6d, 0x59, 0x02, 0x13, 0xdb, 0x3d, 0xdf, 0x96, 0xc1, 0xac, 0xb5, 0x8a, 0x4d, 0xde, 0x6d, + 0x45, 0xe9, 0x6b, 0x75, 0x6d, 0xd2, 0x6e, 0x3c, 0x80, 0xcb, 0x63, 0xb5, 0x52, 0x33, 0x92, 0x64, 0xa6, 0x77, 0xbe, + 0x7b, 0xce, 0xa5, 0x52, 0xa1, 0xc4, 0x1d, 0x32, 0xbe, 0x3b, 0x30, 0x76, 0x7f, 0xae, 0xa1, 0x1a, 0x9d, 0x1b, 0xe1, + 0x69, 0xe9, 0x10, 0x02, 0x4f, 0x1c, 0xf7, 0xc7, 0xbe, 0x6c, 0x1b, 0x9d, 0xd1, 0xe9, 0x1c, 0xad, 0x8b, 0xc6, 0x3f, + 0xba, 0x55, 0x34, 0x9b, 0xbd, 0xad, 0x2c, 0x36, 0x8f, 0xcd, 0xf2, 0x28, 0x73, 0xf1, 0x3f, 0xf1, 0xa7, 0xe1, 0x54, + 0xe7, 0x40, 0xb6, 0x74, 0x35, 0x65, 0x12, 0xc8, 0x11, 0x5e, 0xcf, 0xf5, 0x0e, 0x48, 0x3e, 0x77, 0x4b, 0xa0, 0x0c, + 0x45, 0x56, 0x33, 0x2a, 0xae, 0x8a, 0x15, 0x99, 0x67, 0xd6, 0x24, 0x78, 0xa1, 0x77, 0xa0, 0x39, 0x8b, 0x35, 0x6b, + 0x24, 0x71, 0xde, 0x43, 0xca, 0x8e, 0x7c, 0xd8, 0xc8, 0x1c, 0xc2, 0xc3, 0x26, 0x7e, 0xd6, 0x63, 0x02, 0x85, 0x13, + 0x03, 0xe8, 0xed, 0x2f, 0xc0, 0xea, 0xcf, 0x14, 0xeb, 0x83, 0xec, 0x74, 0xd6, 0xae, 0xe9, 0x0f, 0x97, 0x79, 0x9f, + 0xd8, 0xd3, 0xf5, 0xdb, 0xb0, 0x76, 0x4c, 0x2d, 0xed, 0x3c, 0xc0, 0xce, 0x6b, 0xf8, 0xae, 0x43, 0xb5, 0xaf, 0x11, + 0xba, 0x1f, 0xb9, 0xc9, 0x63, 0x0a, 0x1d, 0x7b, 0xfc, 0x27, 0xc0, 0x43, 0x0a, 0x5d, 0x05, 0xee, 0x53, 0x58, 0x3f, + 0x0e, 0xc0, 0x5d, 0x0a, 0xd5, 0x13, 0xb8, 0x4d, 0x61, 0x44, 0xfc, 0x5e, 0x79, 0x93, 0x82, 0x7d, 0x14, 0xee, 0xf2, + 0xbe, 0xac, 0xe8, 0xcd, 0xbb, 0x3e, 0xde, 0x3e, 0x2a, 0x57, 0xde, 0xd3, 0xfb, 0x7a, 0xbc, 0x5b, 0xbd, 0x09, 0x4c, + 0x9f, 0xa8, 0xc4, 0x9b, 0x02, 0xcf, 0x9f, 0xb0, 0xe2, 0x5d, 0x1e, 0xaf, 0x9b, 0x77, 0x71, 0xa5, 0x7b, 0x75, 0xff, + 0x3f, 0xb4, 0x35, 0xe6, 0xed, 0x1c, 0xdf, 0x6d, 0x2b, 0xe7, 0x59, 0xde, 0xee, 0x9d, 0xfd, 0xeb, 0x59, 0x3c, 0x80, + 0xd3, 0x14, 0x9a, 0x0a, 0x9c, 0xa4, 0x50, 0x56, 0xe0, 0x38, 0x85, 0x53, 0x6d, 0x9a, 0x16, 0xd8, 0x4d, 0x41, 0x37, + 0xe0, 0x28, 0x85, 0xcd, 0x37, 0xb0, 0x97, 0x42, 0xf1, 0xbc, 0xb5, 0xc0, 0x7e, 0x0a, 0x7a, 0x05, 0x0e, 0x04, 0xf2, + 0x2a, 0xef, 0xf0, 0x9f, 0x8d, 0xe3, 0x37, 0x18, 0x7b, 0xa8, 0xf6, 0x0c, 0x37, 0xfa, 0x1b, 0x18, 0xce, 0x5d, 0x8e, + 0x5d, 0x7d, 0x3a, 0x03, 0x97, 0xcc, 0xbf, 0x85, 0xd6, 0x9b, 0x44, 0xf8, 0x63, 0x40, 0x12, 0xab, 0xd3, 0x7d, 0x05, + 0xbc, 0xda, 0x1f, 0x7a, 0x3e, 0x67, 0x61, 0xee, 0xc2, 0x2b, 0x06, 0xac, 0x62, 0x51, 0x9e, 0xfa, 0xbf, 0x0c, 0x21, + 0xbb, 0x6d, 0x48, 0x32, 0x23, 0xdb, 0x0f, 0x8b, 0x13, 0xa3, 0x3e, 0x29, 0x4d, 0x6c, 0x55, 0x3a, 0x43, 0x45, 0x93, + 0x9b, 0xe0, 0x51, 0x52, 0xaa, 0xc0, 0xdc, 0x45, 0xf7, 0x44, 0xf8, 0x66, 0xbd, 0xc3, 0xf5, 0x53, 0x52, 0x21, 0x4a, + 0x86, 0xf4, 0xeb, 0xbf, 0x9c, 0x4d, 0x4f, 0xa9, 0xf5, 0xe4, 0x45, 0xfc, 0xc9, 0xf7, 0xd5, 0xb5, 0x29, 0x30, 0x79, + 0x66, 0x72, 0x99, 0xa7, 0x6d, 0xf5, 0x1e, 0xdb, 0x21, 0x59, 0xbb, 0x3d, 0x05, 0x2f, 0x89, 0xf5, 0x6f, 0x72, 0xcd, + 0x02, 0x7b, 0x4f, 0x30, 0xa7, 0x61, 0x89, 0x12, 0x25, 0x46, 0x62, 0xbc, 0xea, 0x41, 0x61, 0xcc, 0x70, 0x8d, 0xbf, + 0x4a, 0xed, 0xdf, 0xce, 0xa6, 0x3a, 0x01, 0x0b, 0x39, 0xd7, 0x61, 0x78, 0xe0, 0x24, 0xa4, 0x1c, 0xb2, 0x48, 0x68, + 0xa3, 0x99, 0x4e, 0xaa, 0xa7, 0x5a, 0x3d, 0xd8, 0x8d, 0x96, 0x27, 0xa2, 0x77, 0xed, 0xa8, 0x9c, 0x89, 0xa0, 0xbb, + 0x81, 0xd3, 0x1c, 0xfa, 0x63, 0x5a, 0xf2, 0x32, 0x80, 0x14, 0xbe, 0xf1, 0x76, 0x6a, 0xec, 0x5f, 0xe2, 0x3b, 0xb6, + 0xa2, 0x5c, 0xe1, 0x4f, 0xf0, 0x1b, 0xb6, 0x36, 0x9b, 0xbf, 0x61, 0x75, 0x79, 0xb8, 0x15, 0xb0, 0x02, 0x30, 0x7f, + 0x67, 0xcd, 0xf6, 0xe9, 0x08, 0x27, 0x93, 0xb7, 0x82, 0xb2, 0xd2, 0x80, 0x85, 0xf1, 0x36, 0x01, 0xbf, 0x15, 0x06, + 0x37, 0xdb, 0x9b, 0x33, 0x31, 0x77, 0x22, 0x5a, 0x5c, 0x06, 0x76, 0x0f, 0x6e, 0xd4, 0xc2, 0x4a, 0xdd, 0x1c, 0xf6, + 0xf7, 0xea, 0x06, 0x25, 0x2e, 0x82, 0xb0, 0x55, 0x75, 0x40, 0xd6, 0xb8, 0x8e, 0x22, 0x9f, 0x87, 0x7d, 0xb3, 0xdd, + 0x5b, 0xa9, 0x25, 0x5b, 0xde, 0xeb, 0xb5, 0xea, 0x27, 0x55, 0x4d, 0x9f, 0xce, 0xb1, 0xec, 0x34, 0x66, 0xc9, 0x4f, + 0x5b, 0x7b, 0x78, 0xc5, 0x15, 0x82, 0x68, 0xd5, 0x14, 0x33, 0xf3, 0x41, 0x1d, 0x34, 0x61, 0xae, 0xc2, 0xe3, 0x98, + 0x60, 0x80, 0xd9, 0x79, 0x78, 0x11, 0x42, 0x07, 0xc1, 0x76, 0xce, 0xc1, 0x56, 0xf1, 0xb4, 0x69, 0x2d, 0x0b, 0x68, + 0x1a, 0x8d, 0xfd, 0x28, 0x6b, 0xfc, 0x41, 0x36, 0x6a, 0x9d, 0x5a, 0xda, 0x1e, 0x47, 0x4f, 0x31, 0x7f, 0x1b, 0x50, + 0x11, 0xd0, 0x66, 0x90, 0xb3, 0x41, 0xa3, 0x72, 0xf1, 0xdf, 0x09, 0xa4, 0x33, 0xed, 0xdf, 0x70, 0x36, 0xa6, 0x35, + 0x68, 0xf6, 0x8d, 0xf6, 0x43, 0x4c, 0xdf, 0x17, 0x6c, 0x11, 0xbd, 0xe4, 0xb8, 0xe5, 0x29, 0x1a, 0xb8, 0x4a, 0xa6, + 0x4b, 0x70, 0x84, 0x2e, 0xca, 0xbd, 0xf7, 0x49, 0xf8, 0x93, 0x00, 0xd6, 0x8f, 0x3e, 0xa6, 0x53, 0xb6, 0x0e, 0x0e, + 0x95, 0xb1, 0x47, 0xcd, 0x32, 0x56, 0xf0, 0x4a, 0x7a, 0x23, 0x33, 0x00, 0x02, 0x01, 0xcf, 0x65, 0x87, 0x3f, 0xd5, + 0x07, 0xb9, 0x2a, 0xc0, 0x6a, 0xe9, 0x66, 0x3b, 0x1d, 0x6a, 0xcd, 0x8f, 0x79, 0x5b, 0xda, 0xd1, 0xa3, 0x77, 0xb4, + 0xbd, 0xac, 0xc1, 0x05, 0x39, 0x72, 0x09, 0x3a, 0x4b, 0x65, 0x54, 0xe1, 0x3a, 0x34, 0xe0, 0x7c, 0x29, 0xd4, 0x28, + 0x5a, 0xf4, 0x9b, 0x1b, 0x7d, 0xcb, 0x5e, 0x1e, 0x41, 0x63, 0xce, 0xfb, 0x4d, 0x36, 0x57, 0x2d, 0x10, 0x84, 0x39, + 0xb6, 0xa5, 0xf7, 0x1f, 0x13, 0x9c, 0x6f, 0x5f, 0xb0, 0xdd, 0x72, 0xcb, 0x03, 0xb6, 0xfe, 0x89, 0x47, 0x15, 0x8a, + 0x9d, 0x78, 0x56, 0x56, 0x67, 0x57, 0x6d, 0xad, 0x31, 0xa4, 0xff, 0x6a, 0xbd, 0x6b, 0x6b, 0x5a, 0x7b, 0x07, 0x3c, + 0x08, 0x84, 0x74, 0xb8, 0x1c, 0x48, 0xc4, 0x7a, 0x4b, 0x87, 0x87, 0x12, 0xe1, 0x80, 0xec, 0x01, 0xb3, 0x73, 0x1b, + 0xda, 0xb3, 0x87, 0x07, 0xb8, 0x97, 0x39, 0xd0, 0x80, 0x5c, 0x1e, 0x1e, 0xe5, 0xd9, 0xfd, 0x01, 0x09, 0xf0, 0x16, + 0x0a, 0x58, 0x6a, 0x80, 0x75, 0x47, 0x4c, 0xb8, 0x7c, 0x20, 0xcb, 0xce, 0x8b, 0x40, 0xc7, 0x95, 0xd3, 0xc0, 0x46, + 0x0f, 0x1e, 0x42, 0xf1, 0x64, 0x73, 0xac, 0x71, 0x6e, 0x4d, 0x7a, 0xe1, 0x08, 0xc9, 0x98, 0xb9, 0x47, 0x8c, 0x1c, + 0x52, 0x1f, 0x26, 0xa6, 0x8b, 0x49, 0x7a, 0x5c, 0xb1, 0x2e, 0x86, 0xc0, 0x8e, 0x60, 0xe9, 0x0b, 0xc4, 0xde, 0x64, + 0x2c, 0x61, 0x82, 0x58, 0x47, 0x83, 0x18, 0xc2, 0xc6, 0x1d, 0x96, 0xa6, 0x6e, 0x02, 0x16, 0x81, 0xeb, 0x45, 0x90, + 0x4b, 0x61, 0x8d, 0x67, 0xe1, 0xdd, 0x3b, 0x9f, 0xc6, 0xdb, 0xfd, 0xaf, 0xf8, 0xd0, 0xa8, 0x36, 0x5a, 0x94, 0xbe, + 0xee, 0x00, 0xc6, 0xec, 0x57, 0xe0, 0x33, 0x05, 0x42, 0x9c, 0xfb, 0xfb, 0x57, 0x58, 0xe6, 0xf0, 0xda, 0x06, 0x19, + 0x8c, 0xcc, 0xbe, 0x1c, 0xd8, 0xa4, 0x96, 0x48, 0xe6, 0x2b, 0x86, 0xb7, 0x80, 0x55, 0xe9, 0x4b, 0xa2, 0x36, 0xcc, + 0xdd, 0xf8, 0xae, 0x0e, 0x1a, 0x6d, 0xe5, 0x47, 0x68, 0x1c, 0x4c, 0xde, 0xea, 0xc4, 0x40, 0x86, 0x78, 0x12, 0xab, + 0xbe, 0xb8, 0x68, 0x6b, 0x90, 0x34, 0x3d, 0x06, 0x14, 0x8a, 0x5d, 0xbc, 0xbd, 0x60, 0xbb, 0xa4, 0x06, 0xb0, 0xb1, + 0x31, 0x69, 0x98, 0x1d, 0xb5, 0x26, 0xa6, 0xed, 0x3d, 0x3e, 0x4a, 0x9b, 0x23, 0x77, 0x0f, 0x6b, 0x2a, 0xdb, 0x9d, + 0x27, 0x4a, 0x1c, 0x73, 0x70, 0x86, 0x5f, 0x1f, 0x98, 0x80, 0x7c, 0x3f, 0x3e, 0x11, 0x87, 0x83, 0xaf, 0xc7, 0x09, + 0x94, 0x88, 0x42, 0x2d, 0xc0, 0x03, 0x11, 0x10, 0xc7, 0xee, 0x08, 0x20, 0xeb, 0x7d, 0xbc, 0x94, 0xad, 0x56, 0xbd, + 0x9c, 0x5e, 0x6c, 0x34, 0x01, 0x42, 0x7c, 0xca, 0x21, 0x48, 0xc9, 0xe2, 0xc1, 0x01, 0xc4, 0x0c, 0x54, 0x30, 0x65, + 0x37, 0xbc, 0x51, 0x18, 0x0b, 0x2d, 0x51, 0x9d, 0xc0, 0xc5, 0x11, 0xa8, 0xe9, 0x27, 0x3f, 0x64, 0x03, 0x18, 0x4a, + 0xa9, 0x09, 0x92, 0xae, 0x1c, 0x10, 0xa0, 0x4b, 0x44, 0x42, 0xfc, 0x72, 0x31, 0x40, 0x80, 0x0d, 0xd6, 0x9b, 0xe0, + 0xa6, 0x49, 0x8d, 0xe1, 0x70, 0xff, 0x94, 0x17, 0xad, 0xef, 0x53, 0x20, 0x1b, 0x13, 0x68, 0x5e, 0xfc, 0xe8, 0x48, + 0x2d, 0x74, 0x19, 0x1a, 0x2e, 0x29, 0xd6, 0xb2, 0x1f, 0xa6, 0xc5, 0x96, 0xa9, 0x41, 0x88, 0xa0, 0x1f, 0xfc, 0xfa, + 0x32, 0xa3, 0x91, 0x5c, 0x7c, 0x10, 0x7e, 0x08, 0xee, 0x05, 0x78, 0x1c, 0x19, 0x24, 0x29, 0x05, 0x9c, 0x46, 0x95, + 0x08, 0xf7, 0xb8, 0x0b, 0x39, 0x82, 0xe8, 0xf7, 0xb8, 0x4d, 0x8d, 0x16, 0x45, 0xaa, 0x70, 0xd3, 0xef, 0xdb, 0xdb, + 0x45, 0x7d, 0x0d, 0x0f, 0xf0, 0x23, 0x20, 0xbe, 0x26, 0x6e, 0x8c, 0x57, 0x21, 0x9f, 0x92, 0x01, 0x61, 0x02, 0x6a, + 0x42, 0x19, 0x73, 0x0e, 0x37, 0xe6, 0x8a, 0x2c, 0x14, 0x92, 0x41, 0xc3, 0x6d, 0x5d, 0xc2, 0x98, 0x14, 0xc7, 0x89, + 0x40, 0xfc, 0x9e, 0x12, 0x4b, 0x9e, 0x5a, 0x00, 0xf0, 0xad, 0xa2, 0xb9, 0x75, 0xd0, 0x26, 0x13, 0xc4, 0xc9, 0xbe, + 0xc7, 0xf2, 0xdd, 0x66, 0x7f, 0xc6, 0x5f, 0x48, 0x3a, 0x4e, 0x12, 0xf1, 0xae, 0xa7, 0x29, 0xc2, 0x3e, 0x87, 0xaa, + 0x2e, 0x38, 0x04, 0x58, 0xfc, 0x10, 0x16, 0x0c, 0xb2, 0xc1, 0x51, 0xac, 0x07, 0x82, 0xa0, 0x98, 0x84, 0xb6, 0xb3, + 0x10, 0xb7, 0xc1, 0xea, 0x18, 0x95, 0x35, 0x12, 0x24, 0x93, 0x35, 0x13, 0xa2, 0xa6, 0x7e, 0xa2, 0x37, 0x3c, 0xa9, + 0x1d, 0xcf, 0xdd, 0xc4, 0xf4, 0x1a, 0xf9, 0xb1, 0xba, 0x34, 0xd6, 0xe7, 0xbd, 0x85, 0xe4, 0x63, 0xc0, 0x27, 0x89, + 0x0d, 0xd1, 0xfc, 0xc3, 0xb0, 0x6c, 0x18, 0x27, 0x25, 0x1b, 0x4b, 0x35, 0x3a, 0xeb, 0xcc, 0xe3, 0x3d, 0x3f, 0xbf, + 0x5a, 0x0c, 0x49, 0x89, 0xef, 0xe1, 0x0b, 0x59, 0xdb, 0xd1, 0xfa, 0x53, 0xd6, 0x03, 0xa2, 0x3a, 0x13, 0xe0, 0x3d, + 0x56, 0xb3, 0x09, 0x8d, 0x82, 0x0c, 0xe2, 0x7a, 0x6b, 0xb4, 0xd7, 0x9b, 0x6c, 0xfb, 0x25, 0xb7, 0x47, 0xf5, 0x2b, + 0x88, 0xbc, 0xc2, 0xec, 0x7a, 0x3f, 0x6a, 0x87, 0x00, 0x1e, 0x2f, 0xb8, 0x5b, 0x03, 0xf7, 0x5c, 0xc5, 0x82, 0xe4, + 0xcd, 0x54, 0xe8, 0x9c, 0x73, 0x3f, 0xa4, 0xce, 0xd1, 0xbb, 0x71, 0xe3, 0xff, 0x34, 0x57, 0x96, 0x65, 0x96, 0xc2, + 0x64, 0x0c, 0x09, 0x95, 0x08, 0xcf, 0xdd, 0x16, 0xd6, 0x45, 0x79, 0x28, 0x8d, 0xae, 0x31, 0xa8, 0x47, 0x9d, 0x55, + 0x9a, 0x46, 0xb2, 0xf8, 0x1e, 0xed, 0x68, 0xbd, 0x30, 0x15, 0xa0, 0x59, 0x4a, 0xa9, 0x65, 0xd9, 0x3e, 0x97, 0x4b, + 0xa1, 0xef, 0xb4, 0x15, 0xfe, 0xfc, 0x0c, 0xf7, 0xdc, 0xa4, 0xdb, 0x0d, 0xf6, 0x1b, 0xdb, 0xc1, 0x8d, 0xc1, 0x34, + 0x7f, 0xfd, 0xbc, 0x19, 0x66, 0x83, 0x19, 0xcc, 0xc5, 0xb3, 0xbc, 0xc7, 0xb1, 0x2a, 0x6e, 0x5a, 0x1d, 0xf8, 0x27, + 0x37, 0x29, 0x36, 0x3f, 0x60, 0x86, 0x56, 0x7b, 0x97, 0x2b, 0x12, 0xce, 0xd7, 0xbc, 0x80, 0xbe, 0xc4, 0x2c, 0x26, + 0xcc, 0xe7, 0x7c, 0x1a, 0x10, 0x40, 0x55, 0x91, 0x3f, 0x4a, 0x29, 0x58, 0xd9, 0x12, 0xb9, 0x81, 0x0f, 0x54, 0x7b, + 0x40, 0xed, 0x64, 0xce, 0x57, 0x76, 0x48, 0x5d, 0x85, 0x5d, 0x81, 0x91, 0x9d, 0x93, 0x6b, 0x3b, 0x6e, 0xfb, 0x4f, + 0x97, 0x62, 0xbf, 0x58, 0x76, 0xd2, 0x73, 0xf4, 0x49, 0x2c, 0x9a, 0x85, 0x8e, 0x1e, 0xc9, 0xe9, 0x6b, 0xee, 0xef, + 0x8a, 0x48, 0x9e, 0xbf, 0xc1, 0xe5, 0x67, 0x29, 0x24, 0xf8, 0x47, 0x29, 0x6d, 0xb7, 0x23, 0xe6, 0x13, 0x5e, 0x43, + 0x69, 0xce, 0x42, 0xcb, 0x35, 0xd8, 0x00, 0x48, 0x18, 0x65, 0x34, 0x2a, 0xab, 0x6d, 0xfc, 0x75, 0x42, 0xa3, 0xfc, + 0x4b, 0x89, 0x05, 0x35, 0x98, 0x63, 0x44, 0xc5, 0x6b, 0x22, 0x84, 0xe7, 0xfe, 0x32, 0x17, 0xc7, 0x62, 0xd1, 0xe6, + 0xfe, 0x36, 0x67, 0x0b, 0x46, 0x65, 0xb6, 0x5a, 0x5f, 0x89, 0x1e, 0xda, 0x5d, 0x5d, 0xbc, 0x4c, 0xd7, 0xe6, 0xae, + 0x0f, 0x00, 0xe5, 0xa4, 0x0f, 0x96, 0x2e, 0xbc, 0x5e, 0x9f, 0x21, 0xc3, 0x06, 0xaf, 0x0b, 0xae, 0x22, 0xed, 0x07, + 0x48, 0xcd, 0x72, 0x6e, 0x6b, 0x57, 0x89, 0x9a, 0xec, 0x1b, 0x15, 0xa0, 0xef, 0x65, 0xce, 0x63, 0xa6, 0xd1, 0x47, + 0xad, 0x43, 0x8d, 0x18, 0x24, 0x42, 0xab, 0x88, 0xf8, 0xb3, 0xc9, 0x38, 0x0a, 0x45, 0xbc, 0x31, 0x61, 0xac, 0x50, + 0x20, 0x67, 0xf7, 0xdf, 0x3a, 0xbf, 0xba, 0xb2, 0x9f, 0x4e, 0x9a, 0xb2, 0x2e, 0x77, 0xed, 0x2e, 0xf8, 0xf4, 0xea, + 0x25, 0x26, 0x18, 0x17, 0x9f, 0xea, 0x95, 0xf7, 0x96, 0xbf, 0xea, 0x79, 0x7a, 0x77, 0x1d, 0x36, 0xf7, 0x11, 0xaa, + 0xc2, 0xaa, 0xb8, 0x63, 0xe6, 0x49, 0xd3, 0xfa, 0xcb, 0xf7, 0xa2, 0xf6, 0x8b, 0x1e, 0x1b, 0xe8, 0x65, 0x44, 0x71, + 0x3f, 0xd5, 0x5e, 0x3f, 0x28, 0x24, 0x8e, 0x5f, 0x27, 0x44, 0xc5, 0x55, 0xcb, 0xc2, 0xa7, 0x13, 0xac, 0x22, 0xab, + 0xe9, 0x9c, 0x44, 0x35, 0x10, 0xd9, 0x4c, 0x83, 0x00, 0x49, 0xe5, 0x29, 0xed, 0x21, 0xac, 0xdd, 0xd0, 0x2f, 0xef, + 0xc1, 0x08, 0x85, 0x0b, 0xd2, 0x4f, 0x32, 0xa7, 0xd4, 0xe6, 0x74, 0x46, 0x56, 0xe3, 0x80, 0x80, 0xdf, 0xff, 0xf7, + 0xcd, 0x57, 0xc2, 0xd4, 0x3e, 0x85, 0xf1, 0x59, 0xd1, 0x36, 0x41, 0x94, 0xdf, 0x43, 0x96, 0xb5, 0x17, 0xb9, 0xc8, + 0x2a, 0xd5, 0x65, 0xf2, 0x60, 0xcd, 0x6f, 0x62, 0x6c, 0xcb, 0xc3, 0x8d, 0x35, 0x5a, 0xc8, 0xe9, 0x36, 0x9a, 0x41, + 0xa1, 0x62, 0x4c, 0x7a, 0xf5, 0xe7, 0x15, 0x9b, 0xc7, 0x91, 0xc7, 0xaf, 0xf2, 0x29, 0x90, 0xc0, 0x6d, 0x62, 0x05, + 0x47, 0xcd, 0x4e, 0x45, 0x4d, 0x1f, 0x9e, 0xf3, 0xe5, 0xf1, 0x05, 0x50, 0x6d, 0xa8, 0x71, 0xc6, 0xbc, 0x56, 0x94, + 0x35, 0xa9, 0x23, 0x19, 0xcf, 0xbb, 0x0c, 0xb4, 0x9c, 0xa8, 0xe8, 0xbd, 0x5a, 0x52, 0xf4, 0x29, 0x5b, 0xbb, 0x0c, + 0xdf, 0x9a, 0x4c, 0xc8, 0x04, 0x05, 0x47, 0x20, 0xd2, 0xce, 0xc5, 0x0a, 0xed, 0xbf, 0x79, 0x52, 0xdf, 0x9b, 0xf1, + 0x49, 0x62, 0x44, 0x49, 0xc9, 0x77, 0x1f, 0x35, 0x5a, 0x08, 0xa2, 0xce, 0x86, 0x9b, 0xa4, 0x3f, 0xf3, 0xaa, 0x1c, + 0x13, 0x58, 0xe3, 0x48, 0x0c, 0xae, 0x2a, 0xfa, 0x09, 0x25, 0x5c, 0x21, 0xdd, 0x4e, 0x49, 0xc2, 0xd9, 0x23, 0xb4, + 0xa7, 0x79, 0xf5, 0xfd, 0x54, 0x95, 0x1f, 0x48, 0x04, 0x44, 0xb5, 0x19, 0x3a, 0x31, 0xf7, 0xf4, 0x75, 0xed, 0xd2, + 0x13, 0xfe, 0xfb, 0x52, 0xb9, 0x90, 0x3e, 0x8f, 0x17, 0xf3, 0xff, 0x7c, 0x33, 0xae, 0x23, 0x6d, 0xa3, 0xbe, 0xed, + 0x9a, 0x16, 0xed, 0xc8, 0xb2, 0x3e, 0x45, 0x0a, 0x0a, 0x43, 0x08, 0x25, 0x3f, 0x42, 0x58, 0x89, 0x6e, 0x8a, 0xae, + 0x22, 0x83, 0x35, 0x67, 0xc0, 0x0a, 0xaf, 0xea, 0xc0, 0xad, 0x22, 0x9f, 0xec, 0xbc, 0x62, 0x8b, 0xba, 0x4e, 0xa5, + 0x9b, 0x38, 0xe3, 0x77, 0x62, 0x82, 0x54, 0x6d, 0xdf, 0xf3, 0xc7, 0x3a, 0xa9, 0x39, 0xf9, 0x93, 0x8f, 0xf9, 0xd8, + 0x9d, 0xf4, 0xd7, 0x9d, 0xaf, 0xdb, 0x84, 0xb0, 0xe3, 0xa5, 0x4d, 0x4b, 0xb1, 0xc6, 0xdb, 0x60, 0x28, 0x5f, 0x89, + 0xa2, 0x4d, 0x7c, 0x8c, 0xc2, 0xbf, 0x29, 0xb4, 0x4f, 0x92, 0xb6, 0x59, 0x03, 0x45, 0x17, 0x6b, 0x7e, 0xfc, 0x6b, + 0x42, 0x83, 0x50, 0x0c, 0xd8, 0xd4, 0xf7, 0x32, 0x06, 0xed, 0xd3, 0x16, 0x0d, 0x1f, 0x7b, 0xf1, 0x01, 0x23, 0x4e, + 0x57, 0x3f, 0x06, 0xa8, 0x27, 0x8c, 0x63, 0x37, 0x4d, 0x2e, 0x92, 0x86, 0x51, 0xf1, 0x6a, 0x1c, 0xad, 0xdf, 0xdf, + 0xa7, 0xb1, 0x18, 0xfa, 0x6d, 0x06, 0x1f, 0x73, 0x73, 0x6e, 0xde, 0x1d, 0x93, 0x73, 0x72, 0x5e, 0x9e, 0x01, 0x39, + 0x74, 0x25, 0x78, 0x9c, 0x5c, 0x46, 0x69, 0x03, 0x6d, 0x3f, 0x6b, 0xec, 0x70, 0x28, 0xcb, 0xfb, 0xaa, 0x7a, 0x61, + 0xbf, 0xdb, 0xa4, 0xe0, 0x66, 0xcb, 0x37, 0xc5, 0xcf, 0xf2, 0xdf, 0xc0, 0x94, 0x30, 0x5f, 0x84, 0x24, 0xdf, 0x55, + 0xf9, 0xf5, 0xb1, 0x1f, 0x02, 0x78, 0x65, 0x94, 0x98, 0xb5, 0xab, 0xc2, 0xbc, 0x44, 0x3c, 0xc9, 0x9f, 0x2a, 0x42, + 0x10, 0x9d, 0x38, 0x64, 0xc9, 0xaf, 0x47, 0xc2, 0x66, 0x0c, 0x63, 0x73, 0x73, 0x91, 0x29, 0x7d, 0x4b, 0x93, 0x04, + 0x95, 0xe4, 0xa4, 0x02, 0x46, 0x2a, 0xc3, 0x19, 0xfe, 0x34, 0x97, 0x25, 0x7a, 0x8e, 0xd0, 0x7d, 0x8d, 0x6a, 0xdf, + 0x69, 0xdc, 0x26, 0xd7, 0x6a, 0x6e, 0xdc, 0x66, 0xfb, 0xee, 0xc9, 0x31, 0xf4, 0x38, 0xfb, 0x64, 0x42, 0xad, 0x3a, + 0xe1, 0xdc, 0xcd, 0xc3, 0xcb, 0xb8, 0x27, 0x7d, 0x43, 0x5b, 0x63, 0xe1, 0x6a, 0x0e, 0xf3, 0x23, 0xfd, 0x2e, 0xc6, + 0x90, 0xa7, 0xae, 0xb8, 0xdd, 0xa7, 0x71, 0xb4, 0x5e, 0x71, 0x0b, 0x32, 0x94, 0x5a, 0xf1, 0x01, 0x1b, 0xe5, 0x07, + 0x60, 0x8d, 0x0f, 0x01, 0xf9, 0xf6, 0x05, 0x17, 0xa8, 0x35, 0xcc, 0x2c, 0x2f, 0x3e, 0xbf, 0x98, 0x43, 0x38, 0xb9, + 0xa7, 0x4d, 0x0a, 0xb7, 0xdc, 0xa4, 0xe5, 0x6d, 0xd6, 0x4f, 0xd1, 0xf6, 0x90, 0xcb, 0x9e, 0xae, 0x3f, 0x61, 0x24, + 0x72, 0xe2, 0x84, 0xfb, 0xba, 0xb6, 0x58, 0xdf, 0x0f, 0xa3, 0xe2, 0xb4, 0x91, 0xeb, 0x91, 0x81, 0xab, 0x77, 0xf4, + 0x6e, 0x48, 0x3c, 0x55, 0xf3, 0x6b, 0xc5, 0xaa, 0x6e, 0x82, 0x7f, 0x1e, 0xab, 0x21, 0xed, 0x54, 0x5c, 0xec, 0xaf, + 0xce, 0x4e, 0xb2, 0xfc, 0x53, 0x0b, 0x48, 0x2f, 0x38, 0x76, 0x4d, 0x19, 0x6e, 0x21, 0xce, 0x77, 0x73, 0x3c, 0xbd, + 0xd4, 0xd2, 0x38, 0xa7, 0x88, 0x22, 0xa4, 0xb7, 0x82, 0xbf, 0xc7, 0xf0, 0xf5, 0x8c, 0xee, 0xa0, 0x11, 0x49, 0xce, + 0xbf, 0x3c, 0xa3, 0x59, 0xf9, 0xb5, 0xdd, 0x0a, 0x73, 0x07, 0x49, 0x5b, 0xc9, 0xe1, 0x0c, 0xd6, 0x86, 0x84, 0x0b, + 0xc9, 0x96, 0xa6, 0x4b, 0xaa, 0x3a, 0x60, 0x23, 0x7d, 0xd2, 0x27, 0x67, 0x1b, 0x9e, 0x88, 0x06, 0xc1, 0xf9, 0xf3, + 0x90, 0x0e, 0x96, 0xe3, 0xa5, 0x0d, 0x7d, 0x0a, 0x38, 0x5b, 0x36, 0x3e, 0xe8, 0xd4, 0x9a, 0x74, 0x3e, 0x52, 0x97, + 0x98, 0xe2, 0x27, 0xb6, 0xd2, 0x7d, 0x62, 0xbb, 0xd6, 0xa8, 0x7e, 0x5d, 0xdf, 0x6d, 0xea, 0x14, 0x99, 0x3a, 0x6d, + 0xca, 0x2d, 0xe4, 0xaa, 0xce, 0x77, 0x97, 0x1e, 0x6b, 0x19, 0xe4, 0xea, 0x97, 0x65, 0xbf, 0x49, 0xd0, 0xcd, 0xeb, + 0x7f, 0xca, 0xb5, 0xb3, 0xe5, 0x5a, 0xf9, 0x0c, 0x9a, 0xac, 0xae, 0xb5, 0xe9, 0xe6, 0x06, 0x56, 0x56, 0x48, 0x11, + 0x8a, 0x44, 0x48, 0x5b, 0x2d, 0xcf, 0x63, 0xf9, 0x12, 0x4e, 0xfc, 0xfd, 0x51, 0x30, 0x91, 0xa3, 0xa2, 0xb3, 0x50, + 0x37, 0xdb, 0x20, 0xa3, 0xe7, 0xe9, 0x01, 0xf7, 0x2a, 0xca, 0xd9, 0xc6, 0xed, 0x06, 0x51, 0x32, 0x7b, 0x5e, 0xc8, + 0x02, 0xf5, 0x58, 0xae, 0x5b, 0x61, 0xd3, 0xdd, 0x7c, 0xb6, 0x0b, 0x6a, 0x99, 0x2c, 0x8c, 0x9e, 0xb4, 0xc1, 0x42, + 0x22, 0x96, 0xdc, 0x02, 0x2b, 0xb2, 0x65, 0x90, 0xd5, 0xc5, 0x2b, 0xa0, 0x11, 0x6a, 0x5b, 0xf4, 0xc2, 0xe2, 0x0d, + 0x0a, 0x4c, 0x6e, 0x70, 0x16, 0x9d, 0x56, 0xbc, 0x35, 0x26, 0xfe, 0xd7, 0xee, 0x19, 0x37, 0x7d, 0xb8, 0x25, 0x5d, + 0x44, 0xb9, 0x71, 0x79, 0x5b, 0x53, 0xdf, 0xe6, 0x18, 0xe8, 0x7a, 0xcb, 0xab, 0x6a, 0xe4, 0x12, 0xb0, 0xc7, 0x65, + 0x68, 0x24, 0xdd, 0xfc, 0xbc, 0x06, 0x33, 0xa7, 0x33, 0x27, 0x90, 0xf0, 0xa2, 0x91, 0x51, 0x30, 0xf1, 0xf3, 0x85, + 0x68, 0x47, 0x35, 0x63, 0xa0, 0xc0, 0x07, 0xa4, 0xc1, 0x6d, 0x8e, 0x4b, 0xb3, 0x15, 0x9b, 0x45, 0x68, 0x4d, 0x99, + 0x63, 0xc2, 0xab, 0x6e, 0xc6, 0x51, 0x35, 0x06, 0xbb, 0x78, 0x18, 0x6d, 0xc6, 0x5b, 0xdb, 0x24, 0x01, 0x55, 0xd2, + 0x02, 0x38, 0xfd, 0x7c, 0x25, 0x52, 0xa3, 0xe4, 0x52, 0x40, 0xf0, 0x97, 0x53, 0xa0, 0x2d, 0xb7, 0x86, 0x6e, 0x62, + 0x10, 0x6e, 0x3a, 0x57, 0x70, 0xcb, 0x38, 0xf9, 0xc5, 0x70, 0x5a, 0x55, 0xf1, 0x82, 0x94, 0x89, 0x95, 0x1d, 0xf3, + 0x83, 0xad, 0x79, 0x9b, 0x6d, 0x97, 0xef, 0x03, 0xf9, 0x7d, 0xbf, 0xef, 0x5b, 0x6a, 0x5c, 0x9f, 0xef, 0xf2, 0x82, + 0x1d, 0x37, 0x91, 0xd6, 0x4a, 0x14, 0x59, 0x04, 0x8d, 0x76, 0x39, 0xb9, 0x80, 0xf7, 0xa0, 0xe6, 0xee, 0xce, 0xa8, + 0x8d, 0xac, 0xf0, 0x5e, 0xc1, 0xf6, 0x67, 0x99, 0xaf, 0x10, 0xe8, 0xe0, 0x01, 0x0c, 0xf5, 0x89, 0x22, 0x68, 0x24, + 0x42, 0x02, 0x58, 0x3f, 0x6f, 0x08, 0x30, 0x75, 0x8d, 0x92, 0x4d, 0xf0, 0x96, 0xf6, 0x47, 0x37, 0x1e, 0xb2, 0x74, + 0x19, 0xf1, 0x84, 0x48, 0x51, 0x78, 0x00, 0xed, 0xed, 0x23, 0x84, 0x19, 0xf3, 0x54, 0x8d, 0xf8, 0xf5, 0xd4, 0x9e, + 0x5e, 0x18, 0x67, 0xfb, 0x53, 0xfa, 0xff, 0xb9, 0x48, 0x55, 0x9e, 0x8f, 0xe9, 0xcc, 0x79, 0xfb, 0x43, 0xf1, 0xc1, + 0x93, 0x1b, 0x76, 0x0f, 0xe0, 0xd0, 0xb8, 0x9c, 0xac, 0x51, 0xd1, 0xfa, 0x4b, 0xc7, 0xa1, 0x89, 0xe7, 0xcf, 0xb2, + 0xaa, 0xf8, 0xd1, 0x7f, 0xaa, 0xe6, 0x3a, 0x9d, 0xb9, 0x88, 0xb3, 0x2b, 0xb9, 0x15, 0x94, 0x4e, 0xc0, 0x1f, 0xc6, + 0x6b, 0x8d, 0xb9, 0xc4, 0xbd, 0xe1, 0x66, 0xd7, 0xa3, 0xfa, 0xe3, 0x26, 0x03, 0xe3, 0xfd, 0x5b, 0xc9, 0x06, 0xe4, + 0x79, 0x5a, 0x8c, 0x39, 0x7a, 0xe1, 0x9d, 0x2e, 0x90, 0x81, 0xb0, 0x7b, 0xb6, 0xf1, 0x98, 0x28, 0x34, 0x7a, 0x89, + 0x14, 0x2e, 0xd8, 0x3b, 0xb6, 0x03, 0xb2, 0xdb, 0xcf, 0x77, 0xdb, 0x3a, 0xa0, 0xb4, 0x9b, 0xf0, 0xfa, 0x65, 0xcb, + 0x2a, 0x6f, 0x6e, 0xf9, 0x56, 0x99, 0x54, 0xdc, 0xd7, 0x36, 0xc4, 0x7a, 0xe4, 0x14, 0x3b, 0x80, 0x80, 0xc8, 0x62, + 0x09, 0x8d, 0x3b, 0x37, 0x17, 0x1e, 0x1f, 0x4f, 0x9e, 0x95, 0x8c, 0x3a, 0x57, 0xaf, 0xdf, 0xca, 0xba, 0x8a, 0x29, + 0xdb, 0x4b, 0xcf, 0x09, 0x7d, 0x3b, 0x05, 0xee, 0x89, 0x65, 0x34, 0x80, 0x56, 0x7a, 0xcc, 0x19, 0xb1, 0xc6, 0x89, + 0x47, 0xb4, 0x94, 0xc8, 0x3a, 0x94, 0x6f, 0x37, 0x62, 0x4b, 0x08, 0xd5, 0x2e, 0xb5, 0xd7, 0x8d, 0x06, 0x62, 0xfb, + 0x06, 0x10, 0x06, 0x90, 0xcc, 0x62, 0xcd, 0xf5, 0xa5, 0x90, 0x1e, 0xd7, 0x40, 0xa1, 0x76, 0xdf, 0x9c, 0xed, 0x35, + 0x29, 0x9f, 0x4b, 0x33, 0x07, 0xb4, 0xd4, 0xad, 0xf1, 0x7b, 0x60, 0x59, 0xac, 0xb7, 0x0e, 0xfb, 0x7e, 0x9c, 0x31, + 0xed, 0xc2, 0x68, 0x71, 0x6a, 0x3c, 0x41, 0x3d, 0xa8, 0x6b, 0x14, 0x84, 0x72, 0xb0, 0x95, 0xa4, 0x1d, 0xe0, 0x74, + 0x8a, 0xd9, 0x14, 0x80, 0xdb, 0xed, 0x48, 0x9e, 0x30, 0x49, 0x81, 0xe3, 0xb9, 0x86, 0x78, 0x12, 0x57, 0xf4, 0x97, + 0x40, 0xa1, 0x0a, 0x09, 0xc6, 0x8d, 0xf3, 0x48, 0xa8, 0x7f, 0x3f, 0x20, 0x92, 0xcb, 0x65, 0x92, 0x6c, 0x97, 0x2d, + 0x0d, 0x45, 0xad, 0xc0, 0x0f, 0xe8, 0xdb, 0xb8, 0x3d, 0xa4, 0xef, 0xc2, 0x87, 0xc3, 0xda, 0xda, 0x57, 0x1e, 0x61, + 0x16, 0x8e, 0x3d, 0x81, 0xdd, 0x19, 0x66, 0xc5, 0xfd, 0x9f, 0xcf, 0xf1, 0xeb, 0x0f, 0xef, 0x19, 0xd7, 0x1d, 0xfd, + 0x24, 0xf6, 0x7e, 0xd8, 0xd1, 0x71, 0xb3, 0x49, 0x71, 0x31, 0xb3, 0xdf, 0xb4, 0x91, 0xff, 0x75, 0xf1, 0x6c, 0xe2, + 0x9e, 0xde, 0xf1, 0x3b, 0x3d, 0x13, 0x7b, 0x39, 0x51, 0x55, 0xfe, 0xb8, 0x3f, 0x37, 0xf2, 0xfa, 0xac, 0xbf, 0xea, + 0x73, 0xd6, 0xe3, 0xda, 0xc3, 0x78, 0xfb, 0x8c, 0xeb, 0xa9, 0xe5, 0xf5, 0x61, 0xbf, 0x39, 0x1d, 0xf8, 0x3b, 0x0b, + 0x8a, 0xf7, 0xca, 0x15, 0xd3, 0x0a, 0x6d, 0xfc, 0x80, 0x72, 0x7a, 0xf0, 0x47, 0x6c, 0x88, 0x32, 0xb6, 0xc1, 0xf5, + 0x27, 0xb8, 0xce, 0x5a, 0xe1, 0x6c, 0xe0, 0x42, 0x94, 0x1e, 0xe9, 0xd7, 0x39, 0xbd, 0xd2, 0xf1, 0x30, 0x7e, 0xaa, + 0x6b, 0xe1, 0x58, 0xaa, 0x70, 0x66, 0x27, 0xe5, 0x78, 0xbb, 0x8d, 0xf5, 0x0c, 0xbe, 0x37, 0x0b, 0x4a, 0xaf, 0x32, + 0xd8, 0xc8, 0x15, 0xf3, 0x3e, 0x0e, 0x6a, 0xdb, 0x07, 0x1f, 0x8d, 0xf1, 0x6d, 0x9f, 0x8e, 0x2f, 0xda, 0xa4, 0x58, + 0xd9, 0xe3, 0x19, 0x03, 0x19, 0x1c, 0x7e, 0xc1, 0x88, 0x1d, 0xfa, 0xbf, 0x31, 0x55, 0xe9, 0x45, 0x54, 0x1d, 0x5b, + 0x99, 0x02, 0xd4, 0xc3, 0x36, 0x8e, 0x9f, 0xa8, 0x8d, 0xdd, 0x6a, 0x24, 0xe0, 0xf0, 0xda, 0xfd, 0x7a, 0x55, 0x10, + 0xc6, 0xf9, 0x7d, 0x80, 0xf7, 0x80, 0xca, 0xc2, 0x3e, 0x24, 0xee, 0xd0, 0x3e, 0x26, 0xe2, 0xfe, 0x5f, 0xfa, 0x1a, + 0x12, 0xd6, 0xab, 0xfd, 0x80, 0xaa, 0x86, 0x9f, 0x30, 0xc3, 0x9b, 0x2f, 0x97, 0xe3, 0x42, 0x2e, 0x42, 0x9e, 0xc7, + 0xca, 0xda, 0x59, 0xe7, 0xe6, 0x52, 0x16, 0x01, 0x97, 0x05, 0x58, 0xb1, 0xd5, 0xf7, 0x3f, 0xd6, 0x79, 0x4f, 0x03, + 0x88, 0xaf, 0x4b, 0x21, 0xc5, 0xd2, 0x8c, 0x4b, 0x2a, 0xa3, 0x4d, 0x45, 0xf4, 0x6f, 0x64, 0x48, 0x93, 0x39, 0x96, + 0x33, 0x67, 0xe9, 0x03, 0x09, 0x3e, 0x59, 0x30, 0xb0, 0x78, 0x0e, 0xaa, 0x95, 0xa4, 0x99, 0x10, 0x31, 0x91, 0x44, + 0x03, 0xd4, 0x3c, 0xa9, 0x2a, 0x28, 0x3c, 0xd5, 0x70, 0x6d, 0xf5, 0xc2, 0x29, 0x00, 0x24, 0x07, 0x44, 0x45, 0x2d, + 0x3c, 0xa5, 0xc5, 0x4b, 0x4d, 0xc7, 0x6f, 0xbb, 0xa5, 0x1d, 0x7b, 0x7b, 0x8f, 0xfc, 0x45, 0x4c, 0x4e, 0x44, 0xc5, + 0xd6, 0x26, 0x22, 0x81, 0xb7, 0x00, 0xb2, 0x39, 0x56, 0x8c, 0x03, 0x3a, 0x7e, 0xa3, 0x69, 0xb8, 0x8d, 0x1c, 0x95, + 0xf0, 0x0e, 0x46, 0xda, 0x62, 0x2e, 0x98, 0x6e, 0xa4, 0xd5, 0x10, 0x57, 0xaf, 0xd0, 0xaa, 0xb4, 0xd9, 0xc6, 0xc0, + 0x99, 0x6b, 0x31, 0x8a, 0xd7, 0x51, 0x31, 0x27, 0x64, 0x81, 0xf3, 0x70, 0x6e, 0x86, 0xb3, 0xb1, 0x06, 0xa5, 0x71, + 0xd4, 0x15, 0xa7, 0xf3, 0x6d, 0xb6, 0xee, 0xda, 0x77, 0x32, 0xcf, 0xb3, 0xc8, 0x26, 0xed, 0x66, 0x17, 0xd4, 0x38, + 0x57, 0x8c, 0xf9, 0x88, 0x1d, 0x9f, 0x71, 0xe9, 0xb9, 0x85, 0x61, 0x12, 0x1a, 0x8c, 0x9d, 0xd6, 0x2f, 0xd0, 0xf3, + 0x19, 0xdb, 0x15, 0x2e, 0xa0, 0x3c, 0x31, 0x16, 0xad, 0x20, 0x58, 0xbe, 0xad, 0x7f, 0x29, 0xf2, 0x30, 0x1b, 0x77, + 0x78, 0x60, 0x37, 0x4d, 0x3a, 0xf3, 0x7e, 0x78, 0x1e, 0x57, 0xd7, 0xb1, 0x9b, 0x65, 0x4f, 0x4c, 0x6e, 0x04, 0x54, + 0xac, 0x62, 0x9b, 0x97, 0x15, 0xf7, 0x50, 0x91, 0x4f, 0x5a, 0x28, 0xad, 0x52, 0xaa, 0x5e, 0x69, 0x4f, 0x46, 0x48, + 0x73, 0xb5, 0x9e, 0x81, 0x71, 0x21, 0xf0, 0x3e, 0x49, 0x2f, 0xbb, 0x6b, 0xcb, 0xdb, 0x74, 0x80, 0xb4, 0xf6, 0x36, + 0x7e, 0x79, 0x1d, 0x20, 0xce, 0xd5, 0xec, 0xa9, 0xe8, 0xf1, 0x8b, 0x20, 0x54, 0x9e, 0x4d, 0xd3, 0x0a, 0xea, 0xe2, + 0x8e, 0xae, 0xce, 0x61, 0x0d, 0x76, 0x9f, 0x7f, 0x16, 0xb6, 0x52, 0xf9, 0x7f, 0x7e, 0x93, 0xe8, 0x01, 0x3b, 0xec, + 0x21, 0x4d, 0x47, 0xf5, 0xa5, 0x9a, 0xdc, 0x05, 0x3e, 0x83, 0xd9, 0x8f, 0x1f, 0x74, 0x80, 0x65, 0xde, 0x9f, 0x8f, + 0x02, 0xbd, 0xb6, 0xda, 0x92, 0xf6, 0x64, 0x98, 0x6b, 0x82, 0xc1, 0x7d, 0xaf, 0x3b, 0x66, 0x2f, 0x9b, 0x8c, 0x4d, + 0x2c, 0x12, 0xe0, 0x83, 0xd0, 0x18, 0xc8, 0xfe, 0xc9, 0xfd, 0x9b, 0xa1, 0x2c, 0xcf, 0x7d, 0x38, 0x2b, 0xbc, 0x2e, + 0xdb, 0x67, 0xc2, 0x19, 0x6a, 0x91, 0x45, 0xca, 0x6a, 0x96, 0x5f, 0xda, 0x76, 0x0d, 0xd6, 0x4d, 0x59, 0xce, 0x5e, + 0xff, 0x98, 0xf2, 0x8d, 0x46, 0xa9, 0x4c, 0x86, 0xd5, 0x4e, 0x2a, 0x1d, 0x1e, 0x21, 0x90, 0x7a, 0x31, 0x96, 0x05, + 0xf3, 0x42, 0xf4, 0xf2, 0xf3, 0x91, 0x36, 0xb5, 0x17, 0x20, 0x08, 0xcc, 0xd5, 0x1e, 0x59, 0x2c, 0xf9, 0xba, 0x0d, + 0x80, 0xde, 0xb4, 0xd6, 0x57, 0x90, 0x50, 0xe5, 0xec, 0xb6, 0x60, 0x09, 0x7e, 0x92, 0xd6, 0x88, 0xc3, 0x8e, 0x2e, + 0xd8, 0x71, 0x1b, 0x73, 0x0c, 0xb0, 0x5c, 0xbb, 0xc9, 0x69, 0x38, 0x79, 0xc7, 0xdb, 0x8b, 0xe5, 0x64, 0x09, 0x2f, + 0xdc, 0xb8, 0x3d, 0x4c, 0xc3, 0x35, 0x6c, 0x6c, 0xf9, 0x24, 0x5d, 0x3c, 0xb5, 0xcb, 0xac, 0x49, 0xe8, 0xd3, 0x71, + 0xca, 0x77, 0x49, 0xc1, 0xf3, 0xdc, 0xc9, 0xec, 0xd0, 0xc5, 0xaa, 0x90, 0xcf, 0x5e, 0xdd, 0x0f, 0x2b, 0x0e, 0xab, + 0x07, 0x0f, 0xff, 0x87, 0xec, 0xda, 0x6c, 0x1e, 0x1a, 0x57, 0x6e, 0xb2, 0xec, 0x5c, 0x08, 0x91, 0x8e, 0x07, 0x62, + 0xa4, 0xfc, 0xd5, 0x3f, 0xa3, 0x2b, 0x77, 0x9a, 0xd9, 0xfe, 0xb5, 0x30, 0xc6, 0xc1, 0xdf, 0xd8, 0x56, 0x7b, 0xc8, + 0x1d, 0x54, 0xd7, 0x94, 0x9d, 0xd2, 0x7b, 0x76, 0x6c, 0xa3, 0x4f, 0x46, 0x34, 0xe8, 0x79, 0x7d, 0x33, 0x01, 0x72, + 0xde, 0x5f, 0xb4, 0x2d, 0x3e, 0x62, 0x04, 0xe4, 0x8d, 0x2e, 0x4f, 0xed, 0x3b, 0xc0, 0x70, 0x6d, 0xff, 0xb0, 0x02, + 0xa0, 0x9c, 0xb5, 0xa7, 0xb4, 0xc7, 0xed, 0xc3, 0x78, 0x20, 0x60, 0x61, 0x0d, 0xd6, 0x44, 0x65, 0x5f, 0x22, 0x5b, + 0x52, 0xb7, 0x40, 0x99, 0x0a, 0x0f, 0xb1, 0x63, 0x45, 0x38, 0x9f, 0xf4, 0x00, 0xb3, 0xb0, 0x74, 0xe6, 0x06, 0x1e, + 0x34, 0x83, 0x3a, 0xfe, 0x4e, 0x58, 0xb9, 0xee, 0x29, 0x75, 0x8f, 0x4c, 0x95, 0x31, 0x58, 0xea, 0x28, 0x95, 0x2c, + 0x78, 0x0e, 0xa6, 0x63, 0x09, 0x45, 0x8d, 0x6b, 0x97, 0x64, 0x10, 0x23, 0x5e, 0xbb, 0x80, 0x8e, 0x7e, 0x77, 0x73, + 0x70, 0x02, 0x3b, 0x24, 0xf3, 0x05, 0xc9, 0x6e, 0x1e, 0x21, 0x5b, 0x31, 0x1e, 0x99, 0xee, 0x46, 0x5c, 0xac, 0x58, + 0xb0, 0xc4, 0x12, 0xda, 0xa6, 0xe3, 0xbc, 0xe6, 0x0c, 0x64, 0x90, 0x47, 0x95, 0x8a, 0x52, 0xde, 0x6f, 0xc6, 0xf6, + 0x09, 0x49, 0xc3, 0x58, 0xfd, 0x04, 0xf3, 0x7a, 0xdc, 0x4a, 0x7c, 0x7a, 0x63, 0xa3, 0x67, 0x29, 0xea, 0x54, 0xa8, + 0x2f, 0xac, 0xa3, 0x62, 0x45, 0x24, 0xeb, 0x58, 0x6b, 0x2b, 0x0c, 0x8e, 0x0f, 0x33, 0x56, 0xe2, 0xb9, 0x27, 0xec, + 0x7f, 0x6c, 0xa4, 0xe1, 0xbe, 0x1b, 0x14, 0x72, 0x7d, 0xda, 0xb8, 0xb6, 0x62, 0x3e, 0x64, 0x69, 0x3a, 0x54, 0x9e, + 0x33, 0x5e, 0xdc, 0xc1, 0x83, 0x7c, 0x1f, 0x43, 0x9d, 0x09, 0xb2, 0x05, 0xa4, 0x2d, 0xc1, 0xa4, 0x85, 0xc9, 0xa4, + 0x80, 0xf5, 0x77, 0xa0, 0x36, 0x66, 0xf5, 0xc8, 0x93, 0x49, 0x14, 0xb4, 0xd1, 0x69, 0x5c, 0x56, 0xb3, 0x52, 0xcd, + 0xc8, 0x19, 0x27, 0x4f, 0x9c, 0x71, 0x8a, 0x9a, 0x1f, 0x06, 0x80, 0xf6, 0x7c, 0x18, 0x63, 0x90, 0x47, 0x08, 0x85, + 0xe2, 0xe3, 0x3a, 0x01, 0x69, 0xab, 0xb6, 0x59, 0x87, 0x04, 0x09, 0xfc, 0xa1, 0xd2, 0x34, 0x6a, 0x7b, 0x68, 0x34, + 0x41, 0x70, 0x9d, 0xd1, 0xad, 0x53, 0x3c, 0x60, 0x9a, 0x76, 0x74, 0x7b, 0xb7, 0xbc, 0xce, 0xf1, 0x88, 0xc4, 0x6c, + 0x95, 0xf9, 0xaa, 0x28, 0x91, 0xd8, 0x4c, 0x7b, 0x6c, 0x1c, 0x41, 0x38, 0xdd, 0xae, 0x0d, 0xda, 0x5d, 0xd5, 0x05, + 0x17, 0x68, 0xe2, 0x14, 0x85, 0x40, 0x6e, 0xae, 0x15, 0x3a, 0xa9, 0xc9, 0x51, 0x77, 0x40, 0x73, 0x53, 0x9d, 0x97, + 0x19, 0xb6, 0x7f, 0xc2, 0x9d, 0x4a, 0x2f, 0xc4, 0x22, 0x37, 0xf8, 0xab, 0x8f, 0xdc, 0xae, 0xb6, 0x41, 0x1b, 0xaf, + 0xd6, 0x49, 0x2b, 0xaf, 0xb6, 0xe1, 0x48, 0x56, 0x1a, 0x3a, 0x73, 0x19, 0xc6, 0xe6, 0xda, 0x4b, 0x19, 0x9d, 0xa7, + 0x17, 0x61, 0xdc, 0xa9, 0xcd, 0xf3, 0x11, 0x43, 0xce, 0x6d, 0xca, 0xc7, 0xf4, 0x6c, 0xbc, 0xfe, 0x67, 0xfe, 0xef, + 0xea, 0x84, 0x85, 0x0d, 0x6b, 0xbd, 0x13, 0x49, 0x23, 0x50, 0x49, 0x54, 0x8b, 0xbb, 0x0e, 0xda, 0x7b, 0x89, 0x71, + 0x6a, 0x9f, 0x1b, 0x0d, 0x92, 0xbe, 0x3f, 0x61, 0x24, 0x03, 0x41, 0xac, 0x29, 0x69, 0xf5, 0xfe, 0x75, 0x62, 0x2b, + 0xfa, 0x95, 0x20, 0xf1, 0x1f, 0xdf, 0x75, 0xbd, 0x95, 0x44, 0xa4, 0x41, 0xd3, 0x4e, 0x85, 0xcc, 0x06, 0xf0, 0xab, + 0x4f, 0x1f, 0x4a, 0x34, 0x31, 0x94, 0x9e, 0x5c, 0x21, 0xb0, 0x6b, 0x2f, 0x4e, 0xd7, 0x67, 0xde, 0xf0, 0xa6, 0xe2, + 0x0d, 0xc4, 0xe6, 0xaf, 0xfb, 0xc9, 0x9b, 0x95, 0x5f, 0x03, 0x5e, 0x16, 0xdc, 0xa1, 0xce, 0x6e, 0x54, 0xc2, 0x0f, + 0x1a, 0xce, 0x02, 0xe4, 0x28, 0x3f, 0xe9, 0x5f, 0x83, 0x0f, 0x1f, 0x0d, 0xde, 0xf0, 0xce, 0xa1, 0x7a, 0x53, 0x45, + 0x90, 0xe3, 0x92, 0x9c, 0x56, 0x16, 0x59, 0x1a, 0xae, 0x5b, 0xb0, 0x3a, 0x78, 0x83, 0x99, 0xa6, 0x6f, 0x6f, 0xc9, + 0xe9, 0x06, 0xa4, 0x15, 0xe1, 0x49, 0xec, 0x27, 0xd6, 0x29, 0x6c, 0xe2, 0x8b, 0x38, 0xdf, 0xaa, 0x68, 0x30, 0xde, + 0xde, 0xda, 0x89, 0x89, 0xd4, 0x07, 0xb0, 0x36, 0x2f, 0xde, 0x00, 0x6b, 0xbb, 0xf4, 0xcd, 0xef, 0x97, 0x59, 0xe4, + 0x12, 0x29, 0x73, 0x43, 0x1e, 0xee, 0x6b, 0x33, 0xa2, 0xae, 0x84, 0x42, 0x8e, 0xd0, 0xaa, 0x70, 0x95, 0x18, 0x51, + 0x72, 0x7a, 0xdb, 0xd5, 0xed, 0x24, 0x21, 0x16, 0x0a, 0xf5, 0x75, 0x25, 0x92, 0xd1, 0x4a, 0xc9, 0xf5, 0x3d, 0x72, + 0xa9, 0xaa, 0x3f, 0x82, 0x51, 0xaa, 0x6a, 0x68, 0xc8, 0xb5, 0x09, 0x08, 0xec, 0x6a, 0x2a, 0x2e, 0xe1, 0xc8, 0xb3, + 0xb6, 0x2c, 0xe1, 0xd2, 0x18, 0x94, 0x25, 0x5a, 0x0c, 0x32, 0xb5, 0xc8, 0x3b, 0x2f, 0xe9, 0x9a, 0xc7, 0x02, 0x9b, + 0x38, 0x62, 0xb1, 0x66, 0xfa, 0x31, 0x0f, 0xdb, 0x26, 0x5b, 0x0a, 0xda, 0x03, 0xbe, 0xe7, 0x26, 0x93, 0xf9, 0x4c, + 0xda, 0xeb, 0x9b, 0xf0, 0x92, 0x1b, 0x41, 0xa8, 0xed, 0xd1, 0x14, 0x11, 0x76, 0x7e, 0xe2, 0x0d, 0xce, 0xa0, 0x6a, + 0x9e, 0x89, 0xe5, 0x6a, 0xbd, 0xdd, 0x39, 0x83, 0xf4, 0x4d, 0xf8, 0xdb, 0x03, 0x79, 0xc0, 0x4d, 0xd9, 0x50, 0xe4, + 0xa4, 0x99, 0x27, 0x4e, 0x93, 0x27, 0xaa, 0xd5, 0x8f, 0x67, 0x28, 0xa3, 0x6e, 0x22, 0x62, 0xbd, 0xd9, 0xae, 0x14, + 0x29, 0xee, 0x25, 0xdd, 0xa5, 0x0e, 0xd7, 0x6e, 0x5e, 0x99, 0xd1, 0x8e, 0x42, 0x9f, 0xde, 0xad, 0x60, 0x85, 0x1a, + 0x6f, 0xfc, 0x98, 0x8d, 0x37, 0xe2, 0x82, 0x08, 0xf0, 0x21, 0x46, 0xcb, 0x82, 0x4e, 0x13, 0x2d, 0x66, 0x4f, 0x0f, + 0xca, 0xe7, 0x2e, 0xed, 0xd4, 0x55, 0xcb, 0xf8, 0x7a, 0xf8, 0xa0, 0x0d, 0x39, 0x6b, 0xd5, 0x18, 0xa7, 0xe5, 0x62, + 0x39, 0xbb, 0x3c, 0x42, 0x49, 0x71, 0xb8, 0x96, 0xdd, 0xfc, 0x2f, 0xda, 0xdc, 0xb0, 0xa1, 0xe6, 0x58, 0x38, 0xdd, + 0x69, 0x42, 0x63, 0x64, 0x37, 0x84, 0x83, 0xad, 0xa1, 0x16, 0x54, 0x10, 0xe9, 0x4f, 0xcc, 0xe1, 0xd9, 0xdb, 0x2c, + 0x05, 0x87, 0x8a, 0x11, 0x29, 0x1a, 0xf5, 0xd0, 0x29, 0x97, 0x89, 0x75, 0x8d, 0x5c, 0x4b, 0x8a, 0xf1, 0x27, 0xa3, + 0x9f, 0x48, 0xb3, 0xfc, 0x47, 0xe0, 0xe5, 0xd2, 0xb8, 0x34, 0xf8, 0x8d, 0xbf, 0x8d, 0xa1, 0x87, 0x27, 0x4f, 0x74, + 0x71, 0x61, 0xe3, 0xf0, 0x6f, 0xb8, 0xec, 0x42, 0x31, 0x66, 0x5b, 0x66, 0xbc, 0xb3, 0x5c, 0x9a, 0xbc, 0xa5, 0x0b, + 0x79, 0xca, 0x43, 0xe7, 0x0e, 0x9c, 0x10, 0x6d, 0x2c, 0x3b, 0xa0, 0xbe, 0x02, 0xe3, 0xdc, 0x87, 0xcc, 0xb8, 0xc8, + 0x16, 0x5d, 0xb9, 0xfe, 0x9a, 0x8b, 0x0e, 0x40, 0x2d, 0x12, 0x59, 0x5f, 0xd8, 0xc7, 0x58, 0xbb, 0x78, 0x5d, 0x6b, + 0xcf, 0x87, 0x28, 0xa6, 0x3e, 0xd7, 0x2b, 0x80, 0xa2, 0xc0, 0x68, 0xc3, 0x36, 0x76, 0x28, 0x21, 0x40, 0xba, 0x95, + 0x2d, 0xfa, 0x76, 0x8f, 0x46, 0x69, 0xa5, 0x54, 0x38, 0x67, 0x29, 0x1c, 0x95, 0xda, 0xc1, 0x22, 0x24, 0x16, 0xf1, + 0xa1, 0x74, 0x7e, 0x41, 0x24, 0x64, 0x3c, 0x67, 0x43, 0x54, 0x38, 0x49, 0x95, 0xe2, 0xf9, 0xb1, 0x9e, 0xb9, 0x6e, + 0x13, 0x8d, 0xd9, 0xa0, 0xfe, 0xc5, 0x67, 0xb7, 0xd4, 0xa9, 0x03, 0x88, 0x17, 0xbc, 0x73, 0x12, 0xfc, 0xb2, 0x00, + 0xe1, 0x9f, 0x1a, 0x17, 0xbd, 0xc8, 0xf2, 0x18, 0x8a, 0x94, 0x10, 0xe9, 0x9d, 0xc6, 0x4e, 0x64, 0xe8, 0xf4, 0x44, + 0x64, 0x01, 0xa3, 0x6b, 0x1b, 0xc8, 0x21, 0x1e, 0xfb, 0x31, 0xcb, 0x04, 0x2f, 0x40, 0x61, 0xa3, 0xd8, 0x44, 0x8b, + 0x7a, 0x59, 0xad, 0xa9, 0x59, 0x50, 0x13, 0x57, 0xa0, 0x47, 0xd3, 0x53, 0x5c, 0x07, 0x5e, 0xfb, 0xfa, 0x58, 0xc5, + 0xa2, 0x3d, 0x29, 0xd0, 0x04, 0x2b, 0x1c, 0xd0, 0x15, 0x8e, 0xc7, 0x0f, 0xe8, 0xdc, 0x3e, 0xa6, 0x1a, 0x9a, 0x58, + 0x15, 0xce, 0x6a, 0x8f, 0x39, 0x16, 0xd3, 0xda, 0x54, 0x79, 0xdd, 0x44, 0xa2, 0x41, 0x73, 0x5f, 0xd8, 0xc3, 0x67, + 0x7a, 0xb5, 0xd5, 0x62, 0x1c, 0x45, 0xfd, 0xe7, 0x5d, 0x84, 0x6f, 0xd0, 0xc6, 0xad, 0x16, 0xbe, 0x12, 0x54, 0xe5, + 0x05, 0x3a, 0x22, 0x20, 0x8e, 0xd6, 0x42, 0x64, 0xe6, 0x26, 0x05, 0x05, 0x55, 0x61, 0xbf, 0x67, 0x94, 0x57, 0x5f, + 0x6f, 0xca, 0xde, 0x8e, 0x33, 0xac, 0x37, 0x96, 0x1f, 0x8d, 0x11, 0xeb, 0x26, 0x24, 0x9c, 0x24, 0xbf, 0x83, 0xbf, + 0xa9, 0x19, 0xf4, 0x1f, 0xc0, 0xe9, 0xa3, 0x3e, 0xcc, 0xf8, 0x5d, 0x3d, 0x69, 0x02, 0x5d, 0x99, 0x6b, 0x06, 0xcf, + 0x8b, 0x53, 0x77, 0xa2, 0x90, 0x8d, 0x3d, 0xab, 0x65, 0x89, 0x1f, 0xb3, 0xa4, 0xeb, 0x35, 0xf1, 0xe8, 0x52, 0x66, + 0x50, 0x42, 0x28, 0x0d, 0x8c, 0xdd, 0x86, 0x22, 0xb3, 0xde, 0x03, 0xda, 0x1d, 0xb6, 0x31, 0x03, 0xeb, 0x29, 0x9a, + 0x24, 0x8d, 0xe3, 0x57, 0x9f, 0x7e, 0xa4, 0x36, 0x15, 0x43, 0x1a, 0xb6, 0x03, 0x94, 0x4d, 0x32, 0x14, 0x2b, 0xcc, + 0xfa, 0x6f, 0xd0, 0x7b, 0xbb, 0x6f, 0x87, 0xfd, 0x0a, 0xfe, 0xc8, 0x6f, 0x8f, 0x9a, 0x50, 0x36, 0x87, 0x15, 0x0e, + 0x1b, 0xb4, 0xe6, 0x5b, 0x32, 0x75, 0x50, 0x22, 0x0c, 0xe6, 0x05, 0x2a, 0x53, 0x3e, 0x0c, 0xe7, 0x24, 0x93, 0x90, + 0x19, 0x86, 0xbd, 0x9d, 0x58, 0x83, 0xb6, 0x7d, 0xb7, 0x52, 0x5a, 0xdd, 0xd5, 0xd3, 0x0c, 0x0e, 0x69, 0x96, 0xde, + 0xb6, 0x81, 0x81, 0x0e, 0xd7, 0xae, 0x58, 0xa1, 0x9f, 0x67, 0x13, 0x1a, 0x29, 0xc6, 0x80, 0x51, 0x4d, 0x80, 0xec, + 0x56, 0x71, 0xf3, 0x6c, 0xc3, 0x16, 0x49, 0xc4, 0xb4, 0x3f, 0xbd, 0x3a, 0x93, 0x83, 0x8a, 0xf6, 0x22, 0xfc, 0x96, + 0x85, 0x84, 0x70, 0x07, 0x7e, 0xd2, 0x8f, 0x5b, 0x49, 0xbd, 0x95, 0xd9, 0xe6, 0xd6, 0x1b, 0x6a, 0xe7, 0x96, 0x9a, + 0xb9, 0x93, 0x88, 0xf2, 0x64, 0x90, 0x01, 0x37, 0x60, 0xca, 0x46, 0x3f, 0x3a, 0x96, 0x4d, 0x89, 0x4e, 0x94, 0x07, + 0x8a, 0xcd, 0x5a, 0x06, 0xa1, 0x1b, 0x63, 0xba, 0x70, 0x8d, 0xd4, 0xc6, 0x04, 0xa0, 0x64, 0xc3, 0x6c, 0x31, 0x6d, + 0xfa, 0xdb, 0xe7, 0x22, 0xec, 0x0f, 0xf1, 0x40, 0x94, 0xdd, 0x83, 0xa8, 0x83, 0x8e, 0xe8, 0xbf, 0x2f, 0x60, 0x95, + 0xc1, 0x0b, 0xd6, 0x6f, 0x12, 0x1a, 0x3a, 0xe0, 0x2f, 0x6b, 0x2f, 0xd7, 0x22, 0xe5, 0xbc, 0xd5, 0x9d, 0x73, 0xf5, + 0x12, 0xae, 0xbf, 0xb5, 0x67, 0x4a, 0x88, 0x18, 0x2d, 0x4a, 0x40, 0x05, 0x0d, 0xca, 0x27, 0xb0, 0xba, 0x09, 0x54, + 0xf5, 0x36, 0xa5, 0x66, 0x2e, 0x2e, 0xec, 0xcf, 0xdf, 0x66, 0x83, 0x42, 0xeb, 0xe1, 0x83, 0x8c, 0x94, 0x47, 0x10, + 0x44, 0xaa, 0xc6, 0xc2, 0x37, 0x10, 0xf3, 0xaa, 0xa2, 0x74, 0x2d, 0xbe, 0x0d, 0x84, 0x7b, 0x9f, 0x52, 0xb3, 0xa0, + 0x1f, 0x44, 0x44, 0x17, 0xaa, 0xbd, 0x42, 0x46, 0x85, 0x78, 0x7e, 0x1b, 0x65, 0xc8, 0x92, 0x53, 0x53, 0x04, 0x6a, + 0x06, 0x4e, 0x5b, 0xeb, 0xf2, 0x60, 0xa3, 0xf1, 0x81, 0x79, 0x2a, 0xf8, 0xff, 0x3a, 0x7a, 0x09, 0xdf, 0xdd, 0x37, + 0x01, 0xc2, 0xda, 0x7f, 0x1e, 0xd5, 0x5d, 0xbd, 0x69, 0x2e, 0xc4, 0xec, 0x11, 0x7f, 0x1c, 0x02, 0x4f, 0xa7, 0xb9, + 0x77, 0xb1, 0x2a, 0xc1, 0xc0, 0x8e, 0x45, 0x0e, 0x7f, 0xd4, 0xf5, 0x34, 0x7f, 0xbe, 0xaa, 0x9a, 0xc4, 0xb2, 0x86, + 0x22, 0x7e, 0x8e, 0x67, 0x73, 0xa1, 0x3a, 0x51, 0x9a, 0x4c, 0x60, 0x84, 0x23, 0xad, 0x29, 0x49, 0x1e, 0xc1, 0xba, + 0xac, 0x3d, 0x34, 0x7b, 0xbf, 0xb5, 0x92, 0xe8, 0x19, 0x0f, 0xf9, 0xf9, 0x9b, 0xa1, 0x59, 0x9e, 0x8f, 0x28, 0x4f, + 0xbb, 0x97, 0x03, 0x1a, 0xf5, 0xce, 0x09, 0xab, 0xca, 0x05, 0xb1, 0x34, 0xf6, 0x11, 0x54, 0x73, 0x9e, 0xeb, 0x1a, + 0x0b, 0xc1, 0x55, 0x8f, 0xff, 0x06, 0x8e, 0x1a, 0xb5, 0xa1, 0xd2, 0xb3, 0x51, 0xb4, 0x36, 0xb8, 0x7c, 0x4b, 0x07, + 0x98, 0x02, 0x0a, 0x84, 0x5a, 0xb3, 0x3b, 0xaf, 0xdc, 0xf2, 0xc4, 0x03, 0xa9, 0xf7, 0xcc, 0x37, 0xce, 0xc0, 0x7c, + 0x95, 0xee, 0x5a, 0xe6, 0xb5, 0xdb, 0x54, 0xf1, 0x3d, 0xf4, 0x12, 0x54, 0x51, 0xc0, 0xdf, 0x85, 0x5d, 0x29, 0x89, + 0xac, 0xc3, 0x25, 0x88, 0xcb, 0xbe, 0x9d, 0xa1, 0x80, 0xd1, 0x7b, 0xc5, 0x15, 0xbb, 0xe1, 0x5d, 0xe7, 0x51, 0x99, + 0x43, 0x59, 0x93, 0x0f, 0xf0, 0x85, 0x97, 0xa3, 0xd5, 0xd7, 0xf6, 0x24, 0x19, 0x13, 0xfe, 0x1d, 0x90, 0x8c, 0x09, + 0x33, 0xa2, 0x12, 0xf3, 0x5c, 0x05, 0x1e, 0x98, 0x7f, 0xed, 0x21, 0xb7, 0xac, 0x47, 0xeb, 0xac, 0x03, 0xad, 0xe7, + 0xd4, 0xbb, 0x68, 0xe0, 0xf7, 0xa4, 0xb5, 0x03, 0x01, 0x00, 0xb2, 0x0e, 0x9d, 0x43, 0xcd, 0xad, 0x20, 0x5d, 0x55, + 0xb7, 0x87, 0x65, 0xe6, 0xb2, 0x6b, 0xb2, 0x66, 0x47, 0x8e, 0xf8, 0x25, 0x89, 0x2e, 0x50, 0x63, 0x7b, 0xca, 0x7b, + 0x7c, 0x9f, 0xd8, 0x16, 0xbc, 0x8c, 0xea, 0x0b, 0xe7, 0xa6, 0x09, 0x15, 0xf4, 0x83, 0x49, 0x15, 0xc4, 0x7a, 0x42, + 0x02, 0x66, 0xeb, 0xbe, 0x45, 0xd5, 0x7c, 0xcb, 0x57, 0xf6, 0xca, 0x84, 0x7c, 0xc2, 0xd5, 0xb3, 0xa2, 0x0a, 0x24, + 0xad, 0x2f, 0x06, 0x18, 0x0a, 0xe4, 0x12, 0x84, 0xe0, 0x12, 0x14, 0x1d, 0x8c, 0xf1, 0x04, 0x1c, 0x22, 0xce, 0x4b, + 0x8d, 0x87, 0xc9, 0xfd, 0x37, 0x6e, 0x62, 0x0d, 0x46, 0xc2, 0xe0, 0x8a, 0x0d, 0x80, 0x43, 0x2b, 0xd0, 0xea, 0x57, + 0xfb, 0xec, 0x0b, 0xdf, 0x0f, 0xd4, 0x25, 0xab, 0x09, 0xd9, 0x17, 0x51, 0x43, 0xf7, 0x02, 0x64, 0xf1, 0x2c, 0x8e, + 0x4b, 0xa2, 0x33, 0xbe, 0xf1, 0xd0, 0x43, 0x21, 0x0d, 0x42, 0xfe, 0x27, 0xa3, 0xe0, 0x04, 0xcc, 0x24, 0x2a, 0xda, + 0x12, 0x1e, 0xdd, 0xe8, 0x40, 0x03, 0xbb, 0xb1, 0x6e, 0x6a, 0xe1, 0x4e, 0x4c, 0xa5, 0xd5, 0x0d, 0x63, 0x58, 0x65, + 0x84, 0xa6, 0x91, 0xba, 0xdb, 0x9a, 0xb9, 0xba, 0x58, 0xed, 0x8e, 0x67, 0xdf, 0xff, 0x0d, 0x97, 0x32, 0x5b, 0x94, + 0x10, 0x67, 0x12, 0x63, 0xe2, 0x54, 0x2d, 0xbf, 0x11, 0x71, 0xe7, 0x7e, 0xa7, 0x00, 0x44, 0x9f, 0x71, 0x1a, 0x6d, + 0x36, 0x52, 0xd3, 0x03, 0x76, 0x07, 0x3c, 0x50, 0xfc, 0x21, 0xd8, 0xf8, 0x34, 0x79, 0xc8, 0xd6, 0x4a, 0x26, 0x97, + 0xb6, 0xae, 0x6b, 0x3b, 0xf5, 0x2e, 0x7e, 0xcc, 0xb1, 0xbd, 0xb5, 0x92, 0x3c, 0x15, 0x21, 0xe3, 0xe8, 0x93, 0x8d, + 0x27, 0xd4, 0x39, 0xe4, 0xe7, 0xc0, 0x00, 0xba, 0xf5, 0xba, 0xfe, 0x8f, 0x44, 0x84, 0xa7, 0x23, 0x06, 0x32, 0x4c, + 0x0c, 0x9e, 0x39, 0xc3, 0xa9, 0x57, 0x20, 0x3f, 0x86, 0x61, 0x9a, 0x00, 0x7d, 0x22, 0xc9, 0x15, 0xf8, 0x82, 0x60, + 0xf8, 0x48, 0x2d, 0x1b, 0xe2, 0x7d, 0x15, 0x3e, 0xac, 0xa6, 0x16, 0xc3, 0xa2, 0x07, 0x8b, 0x48, 0xe4, 0x81, 0x1c, + 0x60, 0x7d, 0x60, 0xc9, 0x0a, 0x23, 0x02, 0x1f, 0xb3, 0xbd, 0x71, 0xac, 0x00, 0x8c, 0x76, 0xc8, 0x75, 0xfe, 0xf2, + 0x29, 0xf8, 0x1b, 0x2f, 0x54, 0x8a, 0x7d, 0x43, 0x56, 0xfc, 0x23, 0x23, 0x58, 0x1c, 0x0f, 0xa3, 0x69, 0x74, 0x12, + 0xd0, 0x4c, 0x0e, 0xdd, 0x2a, 0x21, 0x86, 0xd9, 0x77, 0x01, 0xe3, 0xd2, 0x95, 0x93, 0xe4, 0xad, 0xfa, 0xc0, 0x58, + 0x90, 0x6e, 0x13, 0x0d, 0xb2, 0xf0, 0x97, 0x05, 0xad, 0xa4, 0x41, 0x5c, 0x93, 0xf7, 0x6e, 0xa6, 0x50, 0xda, 0x97, + 0xae, 0xc3, 0xd4, 0x5d, 0x49, 0xe0, 0xba, 0x12, 0x23, 0x81, 0x5f, 0x66, 0x0d, 0x8a, 0x7c, 0x8e, 0x98, 0xc7, 0xf1, + 0x0e, 0x80, 0x3b, 0x81, 0xe6, 0xc8, 0x21, 0x3b, 0x4f, 0xc4, 0xee, 0x9e, 0xc0, 0x1f, 0xcb, 0x1f, 0x89, 0xfa, 0xe5, + 0xf1, 0x28, 0x3b, 0xa0, 0x68, 0x7f, 0x93, 0x58, 0xaa, 0x42, 0x09, 0xa0, 0x91, 0x2d, 0x50, 0xe9, 0x0a, 0xe0, 0x32, + 0x70, 0x88, 0x58, 0x3d, 0xb3, 0x1e, 0x01, 0x3d, 0xf6, 0xf0, 0x67, 0xa7, 0xaf, 0x7d, 0x5d, 0x13, 0x56, 0x79, 0xdb, + 0x98, 0xac, 0xb3, 0x05, 0xe7, 0x5c, 0x57, 0x27, 0x69, 0xe6, 0xd5, 0x3d, 0x6d, 0xa8, 0x5f, 0x92, 0xb4, 0x6d, 0x2d, + 0xca, 0xc0, 0xf4, 0x73, 0x92, 0x86, 0x50, 0xe8, 0x8f, 0xe5, 0x99, 0x86, 0x52, 0xf3, 0x42, 0x77, 0x1e, 0xc5, 0xb7, + 0x54, 0x3b, 0xa4, 0x76, 0x5d, 0x9a, 0xf6, 0x11, 0xe1, 0x95, 0x34, 0xf6, 0x4c, 0x06, 0x1f, 0x41, 0x58, 0x1a, 0x8a, + 0x13, 0x73, 0x76, 0x09, 0x00, 0x09, 0x43, 0x0e, 0xee, 0x44, 0xde, 0xa6, 0xd8, 0x13, 0xd0, 0xd2, 0xa6, 0x76, 0xef, + 0xaa, 0xc1, 0x84, 0x2a, 0x51, 0xf2, 0xc0, 0xad, 0x6d, 0xf1, 0x58, 0x28, 0x93, 0xe8, 0x9f, 0x4d, 0x49, 0xa8, 0x24, + 0x7f, 0xea, 0xfc, 0x8f, 0x3f, 0x28, 0x22, 0x9d, 0x00, 0xb7, 0xac, 0x6a, 0xff, 0xdc, 0x89, 0x77, 0x32, 0xc4, 0x21, + 0x23, 0x23, 0xfc, 0x17, 0x95, 0xd1, 0xc7, 0x13, 0xb8, 0x24, 0x7c, 0xa4, 0x3d, 0xc8, 0x55, 0xf7, 0x44, 0x9d, 0x83, + 0x51, 0x1e, 0x6d, 0x60, 0x62, 0x7e, 0x9e, 0x86, 0xb3, 0x6e, 0x32, 0xb0, 0x30, 0xcb, 0x90, 0xcf, 0x8b, 0xed, 0xc1, + 0x01, 0x5f, 0x09, 0xc0, 0x17, 0x1a, 0x26, 0x1f, 0x73, 0x82, 0x6a, 0xc3, 0xc9, 0x94, 0xeb, 0xec, 0x6e, 0x9c, 0x6a, + 0xa9, 0x82, 0x76, 0x60, 0x42, 0x00, 0xf4, 0x5c, 0x70, 0x0b, 0x07, 0xcd, 0xcf, 0x9b, 0x7c, 0xc2, 0xc9, 0xa7, 0x7e, + 0x25, 0x7d, 0xd1, 0x18, 0x6a, 0x7d, 0x9e, 0x11, 0xb4, 0x34, 0x03, 0x6e, 0xe1, 0x72, 0x08, 0x5b, 0x38, 0x86, 0x05, + 0x19, 0x2f, 0x84, 0xf1, 0x02, 0x4a, 0xe0, 0xcb, 0x21, 0xc4, 0x00, 0xb6, 0x3f, 0x52, 0xb2, 0x9c, 0x50, 0xed, 0x59, + 0xd9, 0xa3, 0x00, 0x41, 0x64, 0xf2, 0xeb, 0x97, 0x8f, 0xff, 0x85, 0x22, 0xb0, 0x0a, 0xa8, 0x4d, 0x07, 0x90, 0xad, + 0x45, 0xc4, 0xb5, 0xf2, 0x54, 0x85, 0x79, 0xa5, 0x04, 0x93, 0xde, 0xf5, 0x0f, 0xaf, 0x7b, 0xab, 0xa0, 0x0f, 0x4b, + 0xcd, 0x31, 0x1b, 0x4d, 0x84, 0x4f, 0x19, 0xfd, 0x79, 0x6d, 0x1d, 0x20, 0xb7, 0x61, 0xf5, 0xc6, 0x95, 0x34, 0x0c, + 0x1a, 0xb5, 0x5f, 0xb2, 0x92, 0xd2, 0xea, 0x46, 0xce, 0x33, 0x4c, 0xbd, 0xe5, 0x1f, 0xee, 0x02, 0x3e, 0x06, 0xac, + 0x30, 0x3f, 0xd0, 0x4b, 0xed, 0x85, 0x57, 0x80, 0xdf, 0x18, 0x11, 0xe4, 0xbe, 0x6d, 0x89, 0x82, 0x4c, 0x6d, 0xbd, + 0x36, 0x95, 0x1e, 0xe6, 0x58, 0x4f, 0xbc, 0xcf, 0xc9, 0xbe, 0x78, 0xe7, 0x5e, 0x2b, 0xc1, 0x7c, 0x48, 0xe2, 0xbb, + 0x88, 0x28, 0x3d, 0x58, 0x4c, 0x8d, 0xa9, 0xf9, 0x03, 0xc0, 0x45, 0xe1, 0xe1, 0xd4, 0xfb, 0x37, 0xd9, 0x25, 0xaf, + 0x6d, 0x2f, 0x2f, 0x79, 0x1c, 0xf7, 0x77, 0x37, 0xfd, 0x86, 0x1f, 0x86, 0xaf, 0xd5, 0x8d, 0xa6, 0xc0, 0xf4, 0x2c, + 0x13, 0xc1, 0x35, 0xfc, 0x41, 0x52, 0x6e, 0x1f, 0x90, 0xb5, 0x0d, 0x9b, 0xe7, 0xd4, 0xda, 0x74, 0xed, 0x06, 0xbe, + 0x72, 0x3a, 0xbe, 0x7c, 0xf9, 0xfe, 0x03, 0x85, 0x72, 0x08, 0x3f, 0x1d, 0x13, 0x03, 0xa9, 0x2b, 0x74, 0x70, 0x27, + 0x9e, 0xe9, 0x71, 0x01, 0xfd, 0xe0, 0xd4, 0x06, 0xe4, 0x0f, 0xd7, 0xda, 0x0a, 0xbb, 0x35, 0xe3, 0x25, 0xea, 0x43, + 0x8f, 0xb0, 0xcd, 0xb2, 0xb0, 0xec, 0xb6, 0x6a, 0x00, 0x65, 0xc1, 0xe2, 0x1b, 0x38, 0x4d, 0x4d, 0x49, 0x0e, 0x9f, + 0xb5, 0xb7, 0x8b, 0x56, 0xdf, 0x63, 0x01, 0xee, 0x1f, 0x90, 0x14, 0x54, 0x08, 0xff, 0x5b, 0xb4, 0x7f, 0xd0, 0x14, + 0x88, 0x2f, 0x49, 0xa1, 0x06, 0xc3, 0x47, 0x9e, 0x60, 0xfd, 0x49, 0x11, 0x35, 0x56, 0xf2, 0xdc, 0x7b, 0x08, 0x68, + 0x5c, 0xde, 0x20, 0xf4, 0x1a, 0xbc, 0xaa, 0x1c, 0x1e, 0x94, 0x37, 0x51, 0xce, 0x78, 0x6a, 0xf2, 0xbe, 0x2e, 0x31, + 0xa1, 0xb7, 0xb7, 0x55, 0xaa, 0x78, 0xaa, 0x7a, 0xa4, 0x3c, 0x24, 0x01, 0xd2, 0x45, 0x81, 0x8b, 0x36, 0x1d, 0xe7, + 0x67, 0xc1, 0x9c, 0x15, 0xf8, 0x52, 0x6e, 0x24, 0xca, 0x2f, 0xc6, 0xcc, 0x6c, 0xe4, 0xaf, 0x37, 0x2e, 0x37, 0x5e, + 0xdd, 0xd6, 0x4a, 0x34, 0xd7, 0x92, 0x02, 0x5d, 0xae, 0xa3, 0xbf, 0xba, 0x11, 0x86, 0x72, 0x48, 0xf9, 0x4f, 0x28, + 0x4c, 0x6c, 0x81, 0x14, 0xe4, 0x25, 0x91, 0xff, 0x1e, 0x96, 0xb3, 0x85, 0xaf, 0x62, 0x1f, 0xa0, 0x6c, 0x24, 0xf6, + 0x07, 0x22, 0x45, 0xa6, 0xdd, 0x58, 0xb6, 0xfb, 0xbf, 0x16, 0x6f, 0xfe, 0x55, 0x95, 0x2f, 0xd5, 0xb3, 0x44, 0x14, + 0xea, 0x9c, 0x94, 0xcf, 0x30, 0xda, 0xe2, 0x7f, 0x86, 0x22, 0xad, 0x42, 0x0f, 0x6d, 0x0f, 0x3c, 0x0c, 0xad, 0x49, + 0x60, 0xcb, 0x7b, 0x3a, 0x04, 0x1b, 0x54, 0x9b, 0xd8, 0x72, 0x1a, 0x75, 0x56, 0xb4, 0x2a, 0xf7, 0xd8, 0x73, 0xed, + 0x19, 0xd4, 0xa3, 0x58, 0xe5, 0xa7, 0xe6, 0xd2, 0x80, 0x85, 0x01, 0x7f, 0x03, 0xf1, 0x55, 0xcc, 0xb9, 0xde, 0xad, + 0xe3, 0xb7, 0xcd, 0x4d, 0x58, 0x69, 0xa8, 0x5b, 0x00, 0x19, 0x17, 0x0c, 0x98, 0x3d, 0xf3, 0x04, 0x82, 0x62, 0x50, + 0x06, 0x03, 0x4e, 0xd3, 0xe7, 0x39, 0x67, 0x09, 0xf4, 0x91, 0xbd, 0x82, 0x03, 0x12, 0x42, 0xab, 0x58, 0x33, 0x91, + 0x2f, 0x40, 0x91, 0xae, 0xda, 0xe4, 0xcc, 0xb5, 0xa8, 0xa7, 0x09, 0xad, 0x02, 0x99, 0xc7, 0x0a, 0xa6, 0xcf, 0xbe, + 0x51, 0xc8, 0xa5, 0x30, 0x93, 0x3b, 0x7f, 0x41, 0xf3, 0x38, 0xcc, 0xd0, 0x45, 0x7e, 0x4a, 0x43, 0xb6, 0x73, 0x73, + 0xbf, 0x7d, 0x90, 0xc4, 0x27, 0xea, 0xc4, 0x7c, 0xc2, 0xfc, 0x57, 0x6f, 0xde, 0x75, 0x6f, 0x9a, 0xf3, 0xab, 0x69, + 0xfe, 0x5a, 0x41, 0xb3, 0x3f, 0x2e, 0xae, 0x50, 0xea, 0x8f, 0x58, 0xae, 0x9a, 0x56, 0x3e, 0xb2, 0x5f, 0x8d, 0x93, + 0x11, 0x91, 0xd0, 0x5e, 0x96, 0xd7, 0x31, 0x69, 0xf6, 0x9e, 0x5b, 0xb8, 0x6f, 0xc3, 0x4b, 0xc3, 0x62, 0xb9, 0x94, + 0x29, 0xad, 0x97, 0xc4, 0xfa, 0xc8, 0x05, 0xfe, 0x58, 0x22, 0x53, 0x1b, 0x6f, 0xf2, 0x8e, 0x74, 0x7e, 0x55, 0x77, + 0x79, 0x9c, 0x30, 0x98, 0xb9, 0x1b, 0x0b, 0x83, 0x3e, 0xd8, 0xcd, 0xd7, 0x91, 0xb7, 0x32, 0x04, 0xbd, 0x28, 0xdd, + 0xcd, 0x6e, 0x77, 0x9f, 0xa1, 0x60, 0xa5, 0x64, 0xc8, 0x96, 0x94, 0xf1, 0x47, 0x47, 0x0d, 0xf9, 0x4b, 0xa9, 0xcf, + 0xff, 0x4c, 0x22, 0x6e, 0xec, 0x7e, 0x79, 0xea, 0x44, 0x06, 0x5f, 0x90, 0xbb, 0x63, 0x24, 0xcb, 0xa7, 0x40, 0x21, + 0xec, 0x48, 0xb0, 0xf9, 0x4e, 0xb7, 0x09, 0x0e, 0x89, 0x34, 0x82, 0x86, 0xfa, 0xa8, 0x12, 0x81, 0x0a, 0xf1, 0x39, + 0x7d, 0x49, 0x1d, 0x3d, 0xeb, 0x5f, 0x8e, 0x7d, 0x06, 0x82, 0x56, 0x25, 0x32, 0x2a, 0x9d, 0x5c, 0x26, 0xa7, 0x30, + 0x82, 0x48, 0x50, 0x04, 0xb9, 0x49, 0x43, 0xf8, 0x70, 0x94, 0x5e, 0x3c, 0x29, 0x0d, 0x6b, 0x70, 0x0d, 0x1e, 0x4f, + 0x10, 0x93, 0x8c, 0x71, 0xeb, 0xdd, 0x6e, 0xdc, 0x9f, 0xde, 0x36, 0x60, 0xf5, 0x8f, 0x04, 0x9a, 0x20, 0xdc, 0x97, + 0x5c, 0xa0, 0x27, 0xe0, 0xb8, 0x16, 0x5c, 0xfb, 0x04, 0x86, 0x46, 0x07, 0x6a, 0xe9, 0xc8, 0x9d, 0x22, 0xff, 0x06, + 0x3c, 0xbb, 0x5b, 0x01, 0xe1, 0xda, 0xe5, 0x7d, 0x16, 0xd5, 0x12, 0x81, 0x5a, 0x67, 0x12, 0xcd, 0x6a, 0x11, 0xaa, + 0x6d, 0xbb, 0x01, 0x57, 0xc7, 0x50, 0xec, 0xa1, 0xf1, 0x17, 0xb0, 0xf0, 0x7c, 0xf2, 0xce, 0xc6, 0xc9, 0x78, 0x48, + 0x5f, 0xb5, 0x19, 0x2d, 0x9e, 0x7c, 0x6c, 0x39, 0xa6, 0xd2, 0x41, 0x0a, 0x1e, 0x2d, 0x08, 0xc2, 0x22, 0x7d, 0xe6, + 0x11, 0xb3, 0x1d, 0xe7, 0x7d, 0x00, 0x67, 0x71, 0x81, 0xee, 0x85, 0x11, 0x3c, 0x3c, 0xb6, 0x17, 0x07, 0x16, 0xb4, + 0x9f, 0x6b, 0x9d, 0xad, 0x48, 0x8b, 0x11, 0xee, 0x45, 0xcb, 0x5d, 0xc5, 0xb8, 0x8e, 0x3c, 0xc2, 0x97, 0xc1, 0xfb, + 0xee, 0x20, 0xc9, 0x73, 0x2b, 0x1c, 0x1c, 0x05, 0x3c, 0x90, 0x27, 0x46, 0x32, 0x46, 0x33, 0xf9, 0xf6, 0x67, 0x72, + 0xb7, 0x67, 0xbf, 0x19, 0x6e, 0x76, 0xc1, 0x45, 0x55, 0xa4, 0xcb, 0x6b, 0xbe, 0xee, 0xd6, 0xd1, 0xe5, 0x6b, 0x00, + 0xbe, 0x55, 0xf4, 0xa6, 0x2b, 0xac, 0x66, 0xb2, 0x11, 0x15, 0xce, 0xdf, 0xe5, 0x08, 0xae, 0x3c, 0xb7, 0x07, 0x15, + 0x63, 0xf0, 0x1e, 0x53, 0x9f, 0xd5, 0xda, 0xdb, 0x97, 0xba, 0x4d, 0x3f, 0xed, 0xb7, 0xdd, 0x68, 0x1a, 0xb5, 0xf8, + 0xfd, 0xf8, 0xc2, 0xa2, 0x63, 0x88, 0x74, 0x99, 0xf2, 0x65, 0xfa, 0x9b, 0x53, 0x56, 0x81, 0xb3, 0x50, 0x80, 0x6e, + 0xdd, 0x70, 0x31, 0x96, 0xf2, 0xdd, 0xd8, 0x42, 0xd4, 0xd7, 0x57, 0xa1, 0xb4, 0x27, 0xf6, 0xdc, 0xef, 0x1a, 0x0e, + 0x64, 0xf0, 0x6c, 0xbc, 0x0a, 0x3b, 0xba, 0x0a, 0xcf, 0x24, 0xde, 0xe7, 0xd7, 0xb9, 0xec, 0x3d, 0x53, 0x37, 0xef, + 0x10, 0xf8, 0x5f, 0x33, 0xbc, 0xf2, 0xb7, 0x4a, 0x98, 0xf3, 0x15, 0xff, 0x4a, 0xfc, 0xce, 0xd1, 0x0d, 0x17, 0xd1, + 0x65, 0xeb, 0x84, 0x56, 0xac, 0xf8, 0x75, 0xde, 0x7f, 0xfb, 0xf0, 0x29, 0x7a, 0x30, 0xae, 0x47, 0x86, 0x5f, 0xa5, + 0x3c, 0x87, 0x75, 0x9b, 0x46, 0x65, 0xfe, 0x54, 0xe0, 0xc5, 0x3a, 0x7f, 0x51, 0x30, 0xea, 0x4d, 0xf2, 0x57, 0xcf, + 0xbf, 0x4e, 0x5f, 0x3c, 0x90, 0x5c, 0xf8, 0x8f, 0x79, 0x7b, 0xb4, 0x1d, 0x81, 0x8b, 0xe7, 0x8f, 0x5e, 0x45, 0xe7, + 0xfa, 0xd3, 0xd6, 0x27, 0x31, 0x88, 0x7d, 0xa9, 0x8e, 0x30, 0x37, 0xde, 0xa3, 0x45, 0xd8, 0x67, 0xf4, 0x13, 0x7b, + 0x4a, 0x56, 0xaf, 0x40, 0xe4, 0x09, 0x5a, 0x9d, 0x9d, 0x23, 0x82, 0x3f, 0x44, 0x7f, 0xe4, 0x97, 0xa8, 0xd1, 0xce, + 0xb3, 0x7f, 0xd9, 0xd6, 0xff, 0xff, 0xa7, 0xeb, 0xb9, 0x19, 0x2d, 0x1a, 0xe0, 0xa5, 0xff, 0x0b, 0x44, 0xdb, 0xd9, + 0xde, 0x08, 0x52, 0x03, 0x17, 0x1e, 0xf1, 0xb3, 0x5b, 0xcb, 0xba, 0xfc, 0xf2, 0xb9, 0x9a, 0x2d, 0xa3, 0x09, 0x95, + 0x93, 0x0b, 0x4d, 0x93, 0xa4, 0x86, 0x0c, 0x5e, 0x33, 0x49, 0x7f, 0x4d, 0xcb, 0xc0, 0xbb, 0x2d, 0xa9, 0x45, 0xe6, + 0x24, 0x1f, 0x67, 0x48, 0xc5, 0xe2, 0x59, 0xb7, 0xa9, 0x36, 0x1e, 0x3d, 0x8d, 0xde, 0x0c, 0x08, 0x5f, 0x59, 0x40, + 0xcf, 0xc1, 0x52, 0xd3, 0x95, 0x1b, 0x3b, 0x4b, 0xf7, 0xb6, 0x19, 0x87, 0x22, 0x82, 0xa6, 0x6e, 0x5d, 0x6e, 0x5b, + 0x1f, 0x95, 0x54, 0x72, 0xe6, 0xcd, 0x01, 0x02, 0xbc, 0xf8, 0x7e, 0xbc, 0x2d, 0x7d, 0xde, 0x0f, 0x72, 0x95, 0x46, + 0x18, 0xd6, 0xf1, 0x52, 0x3a, 0x8b, 0x57, 0x9b, 0x55, 0x08, 0xda, 0x05, 0x10, 0x67, 0x2d, 0x74, 0x8d, 0x80, 0xa6, + 0x45, 0xbc, 0xc7, 0x95, 0x20, 0x9b, 0x1a, 0x54, 0xb2, 0x94, 0x86, 0x0f, 0xf4, 0x07, 0x10, 0x83, 0xae, 0xb6, 0x91, + 0x0a, 0x6e, 0x1c, 0xbb, 0x4f, 0x65, 0x20, 0x99, 0xc4, 0xf7, 0xaf, 0xb2, 0x4a, 0x58, 0x1b, 0xc5, 0x78, 0x29, 0xb4, + 0x4f, 0x7e, 0xcd, 0x6d, 0xaa, 0x26, 0x07, 0x3d, 0xfb, 0x8f, 0x7b, 0x81, 0xee, 0x89, 0xa2, 0xed, 0x8c, 0x31, 0x35, + 0xcf, 0xb9, 0x07, 0x66, 0x91, 0x02, 0x8d, 0x21, 0xf4, 0xa0, 0x7f, 0x4f, 0xe8, 0xa1, 0x9e, 0x54, 0x45, 0x79, 0xb1, + 0x62, 0x5c, 0xbe, 0x9a, 0x4e, 0x0b, 0x69, 0x67, 0x1c, 0xbb, 0x0e, 0x77, 0x03, 0xff, 0xbd, 0xfa, 0x57, 0x1f, 0xc6, + 0x67, 0xfb, 0x18, 0xd3, 0x9e, 0xcf, 0x54, 0x4d, 0xfd, 0x38, 0xad, 0xfa, 0x6d, 0x70, 0x56, 0x79, 0x3e, 0xdf, 0x2a, + 0x2d, 0x10, 0x89, 0x44, 0xa1, 0xcc, 0x3c, 0xcf, 0xb7, 0x7d, 0x1a, 0x2d, 0x13, 0xdb, 0xf8, 0xd6, 0x0d, 0x8a, 0x7a, + 0x2f, 0xaf, 0x26, 0x0a, 0x80, 0x6e, 0x2c, 0x29, 0xa4, 0x5b, 0x62, 0x0b, 0x20, 0x9d, 0xcf, 0xb1, 0x27, 0x09, 0xac, + 0xb6, 0x26, 0xf3, 0x00, 0x0a, 0x59, 0xa2, 0x4d, 0x12, 0x23, 0xd2, 0x2f, 0x00, 0xe2, 0x35, 0x42, 0x79, 0x91, 0xfd, + 0x02, 0x69, 0x80, 0x55, 0x11, 0xe5, 0x8d, 0x4a, 0xe4, 0x2c, 0x6f, 0x32, 0x46, 0x19, 0x2c, 0xff, 0x07, 0xfc, 0xca, + 0x7c, 0x89, 0x40, 0x89, 0xc9, 0x6b, 0x87, 0x96, 0xce, 0x22, 0x4f, 0x2b, 0x6c, 0xf7, 0x43, 0x98, 0xcf, 0xd8, 0xf5, + 0xd9, 0x74, 0x33, 0xb3, 0x24, 0xb6, 0xb8, 0x6a, 0x6e, 0x3e, 0x73, 0xb8, 0x6d, 0x0b, 0xc9, 0xb6, 0xd5, 0x03, 0x7b, + 0x92, 0xee, 0xea, 0x87, 0x9b, 0xa7, 0x36, 0xfd, 0x48, 0xe1, 0xbc, 0x9a, 0xc8, 0xbc, 0x1c, 0x3e, 0xf2, 0xba, 0x77, + 0x2d, 0x42, 0x8d, 0x8d, 0x27, 0xe1, 0xa1, 0xe6, 0xbd, 0x6b, 0x13, 0xbe, 0xf2, 0xbf, 0x8a, 0xe3, 0x69, 0x55, 0xd6, + 0xfd, 0x7a, 0x1e, 0x1b, 0x1f, 0x31, 0x3e, 0x6a, 0x6d, 0xca, 0x0c, 0xc8, 0x43, 0xb5, 0xe7, 0xba, 0x93, 0xa7, 0xb4, + 0xdd, 0x8c, 0x99, 0x6e, 0x39, 0x17, 0x8a, 0xcc, 0xcc, 0xf6, 0x28, 0x17, 0x3c, 0xad, 0xf9, 0x7a, 0x0b, 0xe5, 0x2c, + 0x2d, 0xc7, 0x99, 0xda, 0x29, 0x5d, 0xcf, 0xe5, 0xda, 0xa3, 0x9a, 0x40, 0x0e, 0x29, 0x36, 0xea, 0x5d, 0x26, 0x41, + 0x90, 0xf0, 0xb1, 0xb4, 0x74, 0xeb, 0x0c, 0x28, 0x9f, 0x57, 0xb9, 0x2f, 0xd1, 0xd4, 0xaf, 0xae, 0x5d, 0x90, 0x71, + 0xb7, 0x03, 0x91, 0xd8, 0x56, 0x32, 0xcc, 0x8a, 0x48, 0x03, 0x0f, 0x4e, 0x4d, 0x6d, 0xcf, 0xba, 0xec, 0xac, 0xda, + 0x9a, 0x39, 0xa0, 0x03, 0x26, 0x8f, 0x96, 0x61, 0x3e, 0xe6, 0x05, 0x7f, 0xae, 0x39, 0xdb, 0x68, 0xd4, 0x2f, 0x55, + 0xd8, 0xb6, 0x19, 0x16, 0x3d, 0x29, 0xc0, 0x3f, 0x94, 0xc0, 0x9b, 0x0a, 0x32, 0x00, 0x5c, 0xba, 0x36, 0x1c, 0xc1, + 0x65, 0xcb, 0x42, 0x42, 0xb2, 0xad, 0x5e, 0x7b, 0x0b, 0x10, 0x6c, 0xb6, 0xa4, 0x04, 0x0a, 0xc5, 0xcd, 0xa0, 0x79, + 0x8b, 0x6f, 0xb5, 0x47, 0x92, 0x36, 0xbe, 0x98, 0xe1, 0xee, 0x93, 0x20, 0xf0, 0xe6, 0x37, 0x07, 0xb6, 0xe8, 0x87, + 0x31, 0xce, 0x20, 0x0c, 0xcb, 0xba, 0xbf, 0x64, 0x46, 0x3c, 0xf7, 0x51, 0x7a, 0x1b, 0x7f, 0xbb, 0x08, 0xde, 0x44, + 0xf2, 0x6b, 0x0c, 0xd6, 0x68, 0x9c, 0xbc, 0xe0, 0x92, 0xf7, 0x62, 0x13, 0x78, 0xeb, 0xe7, 0x70, 0xc6, 0x34, 0x92, + 0xe7, 0xb1, 0xba, 0xf9, 0xd3, 0xd8, 0xad, 0x47, 0xbe, 0x7f, 0xf9, 0xfd, 0x2e, 0x94, 0xa4, 0x35, 0xf2, 0x20, 0x85, + 0x5c, 0x64, 0x80, 0x3a, 0x05, 0x2f, 0x5b, 0xa2, 0x6e, 0x65, 0x45, 0x9e, 0x1c, 0xf6, 0xf2, 0xfb, 0x1f, 0xcd, 0xed, + 0xf8, 0x72, 0x83, 0xb4, 0x89, 0x06, 0x88, 0xd1, 0xa9, 0x92, 0x2e, 0x11, 0xc7, 0xd7, 0xe1, 0x3f, 0xfe, 0x30, 0x9a, + 0x6f, 0x9c, 0x89, 0x77, 0xdb, 0x68, 0x11, 0xb5, 0x95, 0xe4, 0xf9, 0x71, 0xf8, 0xc8, 0x73, 0x0b, 0x6b, 0xff, 0x33, + 0x6d, 0x34, 0x8d, 0x79, 0xa1, 0x4e, 0x4f, 0x98, 0xf1, 0x77, 0x98, 0xf1, 0xff, 0xa5, 0xc7, 0x7f, 0x5e, 0xfd, 0xff, + 0xf6, 0xfe, 0x4b, 0xd0, 0xd5, 0xf1, 0xf2, 0xfe, 0xaf, 0x59, 0xfe, 0x35, 0x7f, 0x84, 0x75, 0xfc, 0x6e, 0x67, 0xf3, + 0xb5, 0x4a, 0xb3, 0x29, 0x1f, 0xad, 0xed, 0x3c, 0x21, 0x60, 0x34, 0xcf, 0x4a, 0x14, 0xcc, 0x73, 0x5c, 0x9d, 0x9b, + 0x51, 0xfe, 0xd8, 0x11, 0x16, 0x7e, 0x31, 0xbe, 0x8b, 0xce, 0x75, 0x70, 0x2f, 0xe7, 0xdf, 0x48, 0xe1, 0xbe, 0x38, + 0xa6, 0xd8, 0x56, 0xd6, 0x4a, 0xfa, 0x3e, 0x74, 0xec, 0x88, 0xc0, 0xf6, 0x73, 0xff, 0x95, 0x95, 0xb1, 0x27, 0x83, + 0xb7, 0x21, 0x35, 0x6b, 0xc6, 0xe0, 0x0b, 0x6d, 0xa6, 0x95, 0xc3, 0x15, 0xf7, 0x6a, 0x6c, 0x43, 0x1b, 0x94, 0xa6, + 0x1b, 0x80, 0x90, 0x54, 0xd0, 0x20, 0xac, 0xb3, 0xdf, 0xfe, 0x72, 0xd1, 0x7e, 0x84, 0x22, 0x9f, 0xfe, 0x00, 0xac, + 0x57, 0x8e, 0xaa, 0xc0, 0x91, 0x18, 0x64, 0xc6, 0x2e, 0x05, 0xbd, 0xc1, 0x0c, 0x0f, 0xf5, 0xf4, 0xb6, 0x60, 0xcd, + 0x67, 0x09, 0xad, 0xd1, 0xaf, 0xc8, 0x70, 0x7d, 0x89, 0x24, 0x41, 0x88, 0xd3, 0x50, 0xf9, 0x7f, 0xe2, 0x89, 0x48, + 0x9a, 0x4e, 0x13, 0x45, 0xe5, 0x94, 0x55, 0xfd, 0x2a, 0xd1, 0xec, 0x05, 0xcd, 0x99, 0xbd, 0x4c, 0x8a, 0x41, 0x67, + 0x41, 0x50, 0x5c, 0xd1, 0xe3, 0x92, 0xab, 0x72, 0x26, 0xc4, 0x43, 0xec, 0x8f, 0xb1, 0x4c, 0x2c, 0xcc, 0x39, 0x46, + 0x7b, 0xe7, 0x47, 0xc8, 0x4a, 0xb2, 0x16, 0x36, 0x64, 0x0f, 0xba, 0xd3, 0x47, 0x4f, 0xa0, 0x41, 0xd7, 0x7f, 0xbc, + 0x82, 0x20, 0x7c, 0xe0, 0xdd, 0xea, 0x66, 0x54, 0xde, 0x35, 0xa3, 0x75, 0xf0, 0xf1, 0x62, 0xe0, 0xe8, 0x22, 0x10, + 0x1c, 0x4a, 0xec, 0x57, 0x1f, 0x24, 0x95, 0x9f, 0x4c, 0x9b, 0xb0, 0x3e, 0x1c, 0x07, 0xed, 0xb7, 0x90, 0x9c, 0x21, + 0x87, 0x96, 0x4b, 0x47, 0x25, 0x10, 0x27, 0xf9, 0x73, 0x60, 0xd9, 0xb6, 0x57, 0x92, 0xd1, 0xe3, 0x4c, 0xba, 0x65, + 0xf3, 0xd9, 0x23, 0x11, 0x56, 0x12, 0xb1, 0x51, 0xc1, 0x51, 0xae, 0xca, 0xc4, 0xfc, 0xa2, 0x3d, 0x2c, 0x6d, 0xc4, + 0xa1, 0xde, 0x66, 0x36, 0xec, 0x22, 0xd0, 0xdf, 0xca, 0x21, 0x69, 0xc5, 0xab, 0xc0, 0x49, 0x21, 0xdd, 0xf3, 0x84, + 0x85, 0x5b, 0x98, 0xdf, 0x7d, 0xe1, 0x76, 0xd8, 0x77, 0xd1, 0x6f, 0x91, 0xbd, 0xd7, 0x83, 0x6e, 0x04, 0xbb, 0xae, + 0x7a, 0xfd, 0x7d, 0x1d, 0x07, 0xfc, 0xdf, 0x4b, 0x26, 0xa4, 0xc0, 0x22, 0xc8, 0x17, 0xbc, 0x3c, 0x00, 0x03, 0x3f, + 0xb0, 0xef, 0x60, 0x12, 0xb2, 0xff, 0x18, 0x26, 0x08, 0xd9, 0x4e, 0xaa, 0x87, 0x76, 0x2c, 0xb8, 0x32, 0x1d, 0xb6, + 0x98, 0xb7, 0x82, 0x34, 0x48, 0x75, 0xef, 0x58, 0x28, 0x51, 0x22, 0xe3, 0xcc, 0x93, 0x2d, 0x01, 0x68, 0xd5, 0x8a, + 0xf0, 0x32, 0x20, 0xbf, 0x6a, 0x14, 0x14, 0xf4, 0x07, 0x98, 0x4d, 0xc1, 0x27, 0xa0, 0x83, 0x8b, 0x09, 0x13, 0x53, + 0x26, 0x1d, 0xb7, 0xab, 0xa3, 0x01, 0xa2, 0xa1, 0x73, 0x1e, 0x16, 0xb3, 0x7c, 0x9a, 0xea, 0xa5, 0x67, 0xbf, 0x81, + 0x2e, 0xda, 0x6d, 0xb3, 0x4f, 0x67, 0x1b, 0x82, 0x85, 0x0d, 0xa4, 0x59, 0x75, 0x12, 0xe1, 0xf9, 0x43, 0x9f, 0x98, + 0x01, 0x69, 0x8e, 0xb7, 0x4d, 0xc8, 0xca, 0x29, 0x08, 0x99, 0xd6, 0xcb, 0x43, 0xfd, 0xd6, 0x79, 0x2f, 0x90, 0xdf, + 0xce, 0xf8, 0x84, 0x0b, 0x46, 0x6b, 0x85, 0xc7, 0x44, 0xa8, 0x60, 0x84, 0xc4, 0x46, 0x40, 0x02, 0xbc, 0xc1, 0x6c, + 0x80, 0xee, 0x27, 0xa5, 0xba, 0xd3, 0x99, 0x63, 0xdc, 0x10, 0x0e, 0xf6, 0xa9, 0x12, 0xb8, 0xc9, 0xa8, 0xd0, 0x3f, + 0x91, 0xa9, 0x21, 0xd9, 0x6b, 0x50, 0x8c, 0x8f, 0x80, 0x0b, 0x32, 0x0b, 0x4a, 0x75, 0x18, 0x20, 0xf7, 0xb8, 0x1f, + 0x88, 0x0f, 0x7e, 0x88, 0xba, 0x1f, 0x71, 0x47, 0x9e, 0x77, 0xd3, 0x42, 0xd3, 0x1e, 0x71, 0x17, 0x34, 0xd8, 0xe6, + 0xfd, 0xfd, 0x4c, 0xef, 0x4d, 0xe5, 0x68, 0x81, 0xbe, 0x4f, 0x41, 0xa6, 0x52, 0x8f, 0xd7, 0x32, 0x55, 0x7b, 0x58, + 0x41, 0x2a, 0x81, 0xb2, 0x8c, 0xd9, 0x3c, 0xce, 0x56, 0xed, 0xb5, 0xb7, 0x51, 0xc4, 0x2f, 0xd2, 0x68, 0x35, 0x6c, + 0x05, 0x38, 0xdb, 0x3c, 0xd1, 0xb5, 0x9b, 0xec, 0x38, 0x14, 0xd1, 0xd1, 0x13, 0xe6, 0xac, 0x4c, 0x10, 0x9b, 0xd7, + 0x5c, 0xcb, 0xcd, 0x3a, 0x3a, 0x1b, 0xf5, 0x1d, 0x97, 0x3e, 0xc9, 0x4d, 0x49, 0xc1, 0x25, 0x2f, 0xdf, 0x5f, 0x25, + 0xaa, 0xf2, 0xb2, 0xec, 0xfb, 0xb4, 0x3a, 0xf3, 0xcc, 0x98, 0x7d, 0xad, 0x92, 0x97, 0xdf, 0x6a, 0x5a, 0x26, 0xff, + 0x9a, 0x06, 0x5b, 0xc7, 0xbe, 0xad, 0x8a, 0xaa, 0xdf, 0x12, 0x87, 0xcc, 0x5b, 0x29, 0x59, 0x81, 0x13, 0x58, 0x13, + 0x17, 0x99, 0x4f, 0xd1, 0x0b, 0xd3, 0x1d, 0x9c, 0x03, 0x00, 0x65, 0xd0, 0x24, 0xf8, 0xbf, 0xf8, 0x1a, 0x63, 0xcc, + 0x57, 0x8c, 0xc6, 0x1c, 0x37, 0x2c, 0xcf, 0x6f, 0xcd, 0x17, 0x78, 0x0b, 0xc8, 0x42, 0x5b, 0xd8, 0xc1, 0x63, 0x4d, + 0xba, 0x1b, 0xd2, 0x4e, 0x7d, 0xfa, 0xde, 0x77, 0xf8, 0xef, 0x82, 0xc2, 0xa4, 0x52, 0x20, 0xc3, 0xe5, 0xaa, 0x9b, + 0x11, 0x5a, 0xad, 0x9b, 0xff, 0xed, 0xee, 0x66, 0x54, 0x1c, 0x99, 0xf7, 0x20, 0xc3, 0x0d, 0x64, 0xac, 0xc5, 0x30, + 0x6c, 0x9a, 0x49, 0xb6, 0x3c, 0x86, 0xe8, 0xa3, 0xa6, 0xae, 0xf1, 0xba, 0x2b, 0x77, 0x37, 0x87, 0x0e, 0x6d, 0x60, + 0x70, 0xd7, 0xfe, 0x1c, 0x1e, 0x06, 0xf2, 0xa2, 0x28, 0xe2, 0x36, 0x3a, 0x44, 0x84, 0x9b, 0x98, 0xb1, 0x5a, 0xf2, + 0xff, 0x15, 0x33, 0x4d, 0x3e, 0x33, 0x1b, 0x9c, 0xac, 0x9b, 0xba, 0x62, 0x05, 0xfd, 0xb3, 0x51, 0xda, 0xbf, 0xca, + 0x3a, 0x6f, 0x05, 0x7f, 0xb4, 0x4a, 0x8c, 0x7d, 0x26, 0x39, 0xb4, 0xbc, 0xd0, 0xc7, 0x11, 0x2f, 0xfa, 0xf7, 0x01, + 0x09, 0x77, 0xfe, 0xb1, 0x8a, 0xba, 0x3a, 0x79, 0xa9, 0xaf, 0x6f, 0x57, 0xc2, 0x1e, 0x12, 0x3d, 0x23, 0x0a, 0x0d, + 0xd7, 0x5c, 0xe7, 0xe5, 0xd2, 0x07, 0x1b, 0x51, 0x41, 0xe7, 0xcb, 0x24, 0x88, 0xc6, 0x86, 0x4d, 0x35, 0x55, 0x17, + 0x9d, 0x33, 0x89, 0x50, 0x46, 0x3c, 0x36, 0x81, 0x3e, 0x0c, 0x16, 0x4b, 0x8d, 0x55, 0xcb, 0xc7, 0x6f, 0xd5, 0xe8, + 0x4f, 0x72, 0x76, 0x89, 0x46, 0x39, 0x7f, 0xc3, 0xac, 0xcf, 0xfa, 0xf8, 0x90, 0xd1, 0xbd, 0x7f, 0x27, 0xb9, 0xac, + 0xbf, 0xec, 0x2b, 0x4d, 0xb0, 0x39, 0x77, 0xa3, 0x36, 0x8f, 0x5d, 0x38, 0xc6, 0x3e, 0x42, 0x40, 0xd0, 0x37, 0x94, + 0xd3, 0x42, 0x0f, 0x31, 0x1d, 0x2d, 0xf7, 0x20, 0xbf, 0xad, 0x88, 0x92, 0x68, 0xd8, 0x2d, 0x8e, 0x87, 0xf4, 0x66, + 0x5b, 0xdc, 0x65, 0x43, 0x1d, 0x07, 0xdd, 0x4a, 0x58, 0x02, 0x8d, 0x29, 0x0d, 0xdf, 0x43, 0x8f, 0x9d, 0x2d, 0x99, + 0x5e, 0xee, 0x8c, 0x62, 0x4f, 0xf0, 0x73, 0x42, 0x7d, 0x03, 0xee, 0x78, 0xe0, 0x4b, 0x1c, 0x6a, 0x69, 0x76, 0x23, + 0x2f, 0xd4, 0x0a, 0xd5, 0xa9, 0xd5, 0xe0, 0x0b, 0x35, 0x7e, 0x3c, 0x23, 0x09, 0xf6, 0xf4, 0x55, 0x8d, 0x8b, 0x8f, + 0xd7, 0x72, 0xa1, 0x1c, 0x5d, 0x64, 0x0b, 0x34, 0x3b, 0x4f, 0xd3, 0x8e, 0x50, 0x8f, 0x95, 0xd4, 0xd5, 0xa7, 0x13, + 0x40, 0x45, 0x28, 0x6e, 0xe5, 0x50, 0x90, 0x7e, 0x96, 0xb9, 0x7b, 0x9c, 0x63, 0xa1, 0x06, 0xd0, 0x99, 0x96, 0x49, + 0xa7, 0x2e, 0xa4, 0xc5, 0x3f, 0x24, 0x98, 0xd8, 0xfe, 0x81, 0xa2, 0x00, 0x4a, 0x52, 0xe7, 0xd0, 0xc8, 0xef, 0xeb, + 0x4e, 0x63, 0x8c, 0x39, 0x78, 0x06, 0x0e, 0x84, 0xf5, 0x94, 0xbc, 0xf6, 0x0c, 0xda, 0x35, 0x94, 0x34, 0xe8, 0xb6, + 0xed, 0x71, 0x69, 0xdd, 0x6f, 0x87, 0x26, 0x8b, 0x84, 0x16, 0xaa, 0x2b, 0xd4, 0xc6, 0xb2, 0x74, 0xd2, 0x9d, 0x75, + 0x43, 0x8a, 0x4f, 0x14, 0x6e, 0x61, 0x2e, 0x5b, 0x95, 0xaf, 0x9c, 0x1b, 0x2c, 0xe1, 0xd2, 0x28, 0xb1, 0xe4, 0xef, + 0x7b, 0x40, 0x10, 0x85, 0xaa, 0x3c, 0x13, 0x44, 0x48, 0x6a, 0x87, 0x03, 0x26, 0x8a, 0xf9, 0x7c, 0x13, 0x09, 0x1a, + 0x7c, 0xf5, 0xa3, 0x82, 0xa4, 0x50, 0x09, 0x08, 0x80, 0xc1, 0x40, 0x0a, 0x28, 0xbf, 0x78, 0x32, 0xee, 0x16, 0x3a, + 0xe7, 0x44, 0xfc, 0x40, 0x09, 0x32, 0xe4, 0xcf, 0x7f, 0x9a, 0x10, 0x06, 0x6d, 0x00, 0xc9, 0x59, 0x70, 0xc0, 0x0c, + 0x0b, 0xfd, 0x69, 0xa4, 0xab, 0x96, 0xc4, 0x52, 0x8b, 0x3d, 0x8f, 0xdb, 0x90, 0x5e, 0xb0, 0xe2, 0x12, 0x4a, 0xba, + 0x31, 0x7c, 0xec, 0x75, 0x48, 0x79, 0xd9, 0x6b, 0x7c, 0xc0, 0xc4, 0xc2, 0x70, 0x91, 0xab, 0x9c, 0xa6, 0xb0, 0x4d, + 0xc0, 0x63, 0x3e, 0x1c, 0xa4, 0xde, 0x10, 0x3c, 0x64, 0x95, 0x8d, 0x4e, 0x32, 0x03, 0x07, 0x7f, 0x9f, 0x0b, 0x09, + 0x29, 0x8c, 0x63, 0x18, 0xe2, 0x37, 0x89, 0xe5, 0x44, 0x36, 0xf3, 0x36, 0xce, 0xd0, 0xe9, 0x07, 0xec, 0x3a, 0x50, + 0x77, 0x36, 0x95, 0x10, 0xec, 0x25, 0x1d, 0x13, 0x51, 0x4a, 0x75, 0x19, 0x14, 0x9f, 0x11, 0xc5, 0xa5, 0x1f, 0xe1, + 0x4c, 0x87, 0x9f, 0xb8, 0x97, 0x01, 0x91, 0x98, 0x89, 0xc8, 0xd9, 0xe0, 0x48, 0x9e, 0xc9, 0x96, 0xb5, 0x74, 0x51, + 0xd3, 0xfe, 0x47, 0x82, 0xee, 0x88, 0x5c, 0x9c, 0x9f, 0x65, 0xa1, 0xee, 0xb4, 0xb2, 0xce, 0x26, 0x8b, 0xd3, 0x0f, + 0xde, 0x75, 0xb7, 0xaa, 0xa2, 0x84, 0xf7, 0x80, 0x06, 0x99, 0xdc, 0xb9, 0x55, 0xcb, 0xd8, 0xea, 0xf6, 0x9d, 0xab, + 0x83, 0xe6, 0xda, 0x41, 0x45, 0x12, 0xf9, 0xf9, 0x26, 0xcf, 0x12, 0x33, 0x8d, 0x3e, 0x40, 0xc9, 0x5a, 0x72, 0x70, + 0xa9, 0x01, 0x6a, 0x0c, 0xf8, 0x72, 0xcf, 0xa4, 0xf6, 0x51, 0x07, 0xbe, 0x13, 0x13, 0x22, 0x17, 0xb9, 0x57, 0x9a, + 0x46, 0x5e, 0x4e, 0xef, 0x36, 0x2c, 0xf2, 0x23, 0xbf, 0xfa, 0x39, 0xb3, 0x3c, 0xa5, 0x67, 0x95, 0x30, 0x8b, 0x15, + 0x1e, 0xd1, 0xcd, 0x30, 0x8f, 0xe0, 0xa3, 0xae, 0xfa, 0x73, 0x03, 0x68, 0xf5, 0xe0, 0x4d, 0x47, 0xa3, 0x08, 0xe0, + 0xb9, 0xe9, 0x2a, 0x71, 0x39, 0x3f, 0xe1, 0x06, 0x86, 0x3d, 0x4c, 0x30, 0x10, 0x12, 0x65, 0x26, 0x0c, 0x00, 0x76, + 0x0e, 0xf1, 0x5b, 0xcc, 0xef, 0x75, 0xc3, 0xa6, 0x5a, 0xe0, 0x9c, 0x29, 0x0b, 0xb8, 0x5e, 0x46, 0x9a, 0x0b, 0xa8, + 0x0b, 0xb2, 0x9f, 0xb4, 0x11, 0x63, 0xfb, 0x4c, 0x09, 0x27, 0x8c, 0x9b, 0x01, 0x8d, 0x0d, 0x9a, 0x95, 0x4f, 0xcc, + 0x4d, 0x02, 0x9f, 0x2a, 0x11, 0xb9, 0xb4, 0x47, 0x22, 0xf9, 0x0c, 0x25, 0x70, 0x84, 0x5f, 0xa4, 0xff, 0x03, 0x44, + 0x7a, 0x3b, 0x27, 0x68, 0x6f, 0x43, 0xc6, 0xfb, 0x52, 0x4b, 0x9c, 0xb4, 0x8c, 0xed, 0x1e, 0x8a, 0xc3, 0xeb, 0x60, + 0x44, 0xd7, 0x58, 0xae, 0x6b, 0x34, 0x7e, 0x49, 0xa9, 0x2e, 0xb6, 0xfb, 0x44, 0x0a, 0x0c, 0x00, 0xbd, 0x37, 0x82, + 0xc6, 0x5b, 0xff, 0xd7, 0x05, 0x0e, 0xb3, 0xba, 0x24, 0x94, 0xf6, 0x40, 0x7c, 0x93, 0x7f, 0x63, 0x1a, 0x0e, 0x0a, + 0xdc, 0xd4, 0x4a, 0xbc, 0xd7, 0x76, 0x77, 0xe9, 0x50, 0xf0, 0xf3, 0x75, 0x18, 0x32, 0x7f, 0xc1, 0x11, 0x36, 0x90, + 0xd3, 0x76, 0xfa, 0x55, 0x35, 0xd2, 0xce, 0x20, 0xc3, 0x15, 0x79, 0x41, 0x2a, 0x89, 0xfc, 0xa8, 0x27, 0xab, 0x4b, + 0x2c, 0xec, 0x14, 0x07, 0x80, 0xee, 0x38, 0x86, 0x4d, 0x1b, 0x1b, 0xcd, 0x13, 0xcf, 0xc1, 0x99, 0xeb, 0x14, 0x00, + 0x78, 0xdf, 0x89, 0xc1, 0x84, 0x39, 0xe6, 0x28, 0x5b, 0x81, 0x7a, 0x3c, 0xc9, 0x1c, 0x1c, 0xe7, 0xa3, 0xfa, 0xf8, + 0x84, 0x6d, 0x56, 0x5c, 0x5e, 0x00, 0xc4, 0xe1, 0x38, 0x29, 0x0c, 0x86, 0x44, 0xbd, 0x4f, 0x45, 0xd6, 0xd1, 0x74, + 0xd1, 0x3c, 0xb9, 0x69, 0xec, 0xde, 0x07, 0xa7, 0x86, 0x04, 0xa8, 0x0a, 0xa6, 0x61, 0xfd, 0x9f, 0x81, 0xe0, 0x25, + 0x7b, 0x57, 0xa0, 0xd9, 0x86, 0x83, 0x52, 0xf8, 0xc8, 0x21, 0xed, 0x90, 0x14, 0xea, 0x70, 0x2e, 0xa2, 0x79, 0x16, + 0x82, 0xa7, 0x0d, 0x64, 0x44, 0x5e, 0x4c, 0xde, 0x6b, 0x57, 0xb6, 0xeb, 0x72, 0x8f, 0xd2, 0x2d, 0xce, 0x1a, 0xab, + 0xd9, 0xa4, 0x47, 0xf4, 0xa0, 0x49, 0x15, 0x40, 0x36, 0x81, 0x0a, 0xaa, 0x90, 0x06, 0x1b, 0x3f, 0x07, 0x40, 0xbd, + 0xdc, 0xf0, 0xb6, 0xc6, 0xbd, 0x2c, 0x13, 0xba, 0xad, 0xd1, 0x50, 0x93, 0x30, 0xb8, 0x0f, 0x0c, 0x3a, 0x83, 0x38, + 0x51, 0x3b, 0xcf, 0x78, 0xe8, 0x24, 0x73, 0x21, 0xf4, 0xf8, 0x0b, 0xfc, 0x22, 0xf1, 0xc2, 0xaa, 0xcc, 0xad, 0xe0, + 0x59, 0x4a, 0xe9, 0x3d, 0x06, 0x6b, 0xf5, 0x6f, 0xf7, 0xb3, 0xa3, 0xd2, 0x40, 0x03, 0x9e, 0x23, 0xc9, 0xdd, 0xbc, + 0x3d, 0xd3, 0xa3, 0x3b, 0xfe, 0xf2, 0xea, 0x1b, 0x4f, 0x97, 0xd9, 0x68, 0x74, 0x54, 0x94, 0xf8, 0xc8, 0xe9, 0xc1, + 0x76, 0x66, 0x2d, 0x71, 0xfd, 0x06, 0x24, 0x80, 0x5d, 0x6d, 0x3c, 0x6d, 0xc3, 0xcb, 0x3a, 0xed, 0x49, 0x13, 0xe4, + 0xca, 0xfe, 0xa3, 0xb6, 0xa7, 0x8f, 0x78, 0xf4, 0xc4, 0x94, 0x23, 0x4a, 0x46, 0x11, 0xa8, 0x7e, 0xa0, 0x00, 0xf2, + 0x12, 0x9a, 0x92, 0x2e, 0x08, 0x7c, 0x65, 0x50, 0xb4, 0x1c, 0x30, 0x06, 0x28, 0x47, 0x7d, 0xa7, 0x39, 0x7d, 0xd3, + 0xb3, 0x5c, 0x09, 0x78, 0x6f, 0x51, 0x55, 0x9e, 0x5b, 0xd9, 0x86, 0x4b, 0x79, 0xed, 0xe2, 0xd0, 0x1a, 0xeb, 0x69, + 0xb5, 0xb6, 0xeb, 0x54, 0x3a, 0x7c, 0x8a, 0x63, 0xe4, 0xba, 0xc6, 0x33, 0x08, 0x68, 0x1e, 0x68, 0x92, 0x77, 0xda, + 0xae, 0xa3, 0x59, 0x0d, 0x87, 0x11, 0x7d, 0x5e, 0x51, 0xac, 0x82, 0x1b, 0x64, 0xbe, 0x55, 0xda, 0xa7, 0x35, 0x18, + 0xd6, 0x29, 0x29, 0x7d, 0x56, 0xbf, 0xd2, 0x13, 0x3f, 0xe5, 0x4d, 0xdf, 0x37, 0x25, 0xe1, 0xdb, 0xe4, 0x4b, 0xea, + 0xd4, 0xa5, 0xe9, 0x71, 0x7a, 0xe4, 0x50, 0x8e, 0x1d, 0xdc, 0xbd, 0xf2, 0x2b, 0xf4, 0x3a, 0x33, 0x50, 0x3f, 0x73, + 0x73, 0xda, 0x5d, 0x2b, 0x6a, 0xca, 0x92, 0xea, 0xe9, 0xeb, 0x5c, 0xbd, 0x0b, 0x6f, 0x6b, 0x22, 0x12, 0xdc, 0x9f, + 0xf1, 0x58, 0x91, 0xb9, 0x16, 0x46, 0x7e, 0x58, 0x45, 0x0d, 0x76, 0xad, 0xd4, 0x88, 0x3b, 0xb3, 0x84, 0x9e, 0x14, + 0xbb, 0xf9, 0x2a, 0x89, 0x60, 0x54, 0x19, 0x99, 0x3c, 0x9d, 0xe5, 0x84, 0xa0, 0x5f, 0x31, 0x88, 0x97, 0x75, 0x8d, + 0x17, 0xd7, 0x6a, 0xca, 0x3c, 0x75, 0xeb, 0x11, 0xd7, 0x9f, 0x6f, 0x43, 0xed, 0x7b, 0x02, 0xae, 0xb4, 0xa9, 0x63, + 0x1e, 0x8d, 0xe1, 0x4b, 0x46, 0x72, 0x5e, 0xd0, 0xd4, 0x04, 0xec, 0x17, 0x10, 0x41, 0x94, 0x7f, 0x34, 0xdb, 0x93, + 0x9c, 0x92, 0xed, 0x2f, 0x7c, 0x73, 0xdf, 0x2a, 0x3e, 0x68, 0x3d, 0xfd, 0xa3, 0x48, 0xd1, 0xf4, 0x92, 0x50, 0x54, + 0x54, 0x06, 0xcd, 0x5b, 0x4a, 0x7d, 0xce, 0xf3, 0x2f, 0x75, 0xc9, 0x92, 0x51, 0x98, 0x25, 0x99, 0x25, 0x7d, 0x00, + 0x34, 0xf5, 0x35, 0xe4, 0x8c, 0xa2, 0xf1, 0x33, 0x4a, 0xfe, 0x35, 0xfc, 0x38, 0xed, 0xee, 0xd1, 0x77, 0xef, 0x4a, + 0x1b, 0x92, 0x40, 0x95, 0xde, 0xd2, 0x1f, 0xd3, 0x52, 0x5f, 0x14, 0x8d, 0x2b, 0x45, 0x3b, 0xc3, 0xfc, 0xb4, 0x78, + 0xb6, 0xe0, 0x17, 0xcf, 0x16, 0xbc, 0xf6, 0x82, 0xb9, 0x89, 0x75, 0xab, 0x82, 0x97, 0xc7, 0xb8, 0xc6, 0x50, 0x62, + 0xa7, 0x76, 0xfc, 0x47, 0x47, 0x60, 0x4a, 0xff, 0xa9, 0x51, 0x06, 0xfa, 0x53, 0x06, 0x4e, 0x33, 0x37, 0xcc, 0x28, + 0xba, 0xf1, 0xc2, 0x08, 0x33, 0xe7, 0x49, 0x13, 0x7c, 0x4d, 0x63, 0x0d, 0x76, 0xb5, 0x9c, 0x65, 0x08, 0x45, 0x8c, + 0x1f, 0x15, 0xb6, 0xa0, 0xed, 0x4c, 0xf8, 0x09, 0x44, 0x2b, 0x40, 0xef, 0x39, 0x37, 0xc7, 0xd1, 0xce, 0x52, 0xdf, + 0x3a, 0xa7, 0x98, 0x3e, 0x9c, 0x88, 0xec, 0x81, 0xa6, 0xee, 0x39, 0x9d, 0xf8, 0x25, 0x91, 0xb1, 0xa8, 0xdf, 0x9f, + 0x43, 0xdb, 0x22, 0xdd, 0xab, 0x11, 0x38, 0x05, 0x20, 0x6f, 0x48, 0x18, 0xfe, 0x45, 0x43, 0x79, 0x8d, 0x3c, 0x52, + 0xa9, 0x4c, 0x9f, 0x77, 0x5a, 0xd3, 0x89, 0x2c, 0x2d, 0xb4, 0x93, 0x31, 0xb6, 0xac, 0x4a, 0x14, 0x5b, 0x99, 0xf7, + 0x0c, 0x12, 0xc9, 0xe7, 0x2f, 0x32, 0x5a, 0xac, 0xa9, 0x21, 0x40, 0xb3, 0x0a, 0xb5, 0x75, 0xe1, 0xe9, 0x15, 0x2a, + 0x06, 0x86, 0x82, 0xb2, 0xef, 0x87, 0xd8, 0x1a, 0x3e, 0xb0, 0x9f, 0xf5, 0x1e, 0x12, 0xaf, 0xbd, 0xc0, 0x44, 0x10, + 0xae, 0x37, 0x05, 0x71, 0x6b, 0x97, 0x64, 0x04, 0x37, 0x54, 0x2f, 0xd8, 0x98, 0x63, 0x67, 0xa7, 0x70, 0x76, 0xec, + 0xec, 0x24, 0x67, 0x16, 0x5d, 0xc9, 0x4c, 0xbd, 0x22, 0xb1, 0x64, 0x85, 0x1d, 0xbc, 0xfc, 0x3a, 0xaf, 0xe4, 0x10, + 0x0b, 0x40, 0x95, 0x96, 0x5c, 0x95, 0x16, 0xc4, 0xcc, 0x35, 0x90, 0x06, 0x75, 0x20, 0xf0, 0x12, 0xbf, 0x99, 0x7c, + 0x00, 0x8c, 0x1d, 0x9c, 0xa3, 0xa3, 0x72, 0xda, 0x18, 0xf6, 0xbb, 0x2a, 0x13, 0x28, 0xaa, 0xe6, 0x83, 0x29, 0xc9, + 0x1b, 0x3c, 0x33, 0x2d, 0xd9, 0x43, 0x21, 0x7c, 0xc1, 0xbb, 0x33, 0x63, 0x8a, 0xf9, 0xed, 0x1b, 0x15, 0xfd, 0xbc, + 0xa2, 0x51, 0xa8, 0x39, 0x54, 0x5f, 0x68, 0x9e, 0xe8, 0x01, 0x99, 0xa6, 0x38, 0xb9, 0xf8, 0x50, 0x0a, 0xf9, 0xf8, + 0x77, 0xf6, 0x05, 0xf1, 0xf6, 0x76, 0xb1, 0xad, 0xc0, 0x09, 0xab, 0xd8, 0x09, 0x6d, 0xae, 0xf9, 0x67, 0xea, 0x20, + 0x6b, 0x66, 0x35, 0xde, 0x19, 0x9f, 0x5f, 0xd5, 0xd8, 0x24, 0x9d, 0x21, 0xa8, 0xe0, 0x69, 0x67, 0x08, 0xda, 0xf2, + 0x93, 0xa4, 0x80, 0x08, 0x34, 0x0e, 0xd4, 0x65, 0x33, 0x91, 0x03, 0x73, 0x01, 0x95, 0x2c, 0x67, 0xb8, 0xe6, 0xb5, + 0x3f, 0x74, 0x2d, 0x32, 0x4f, 0xa0, 0x45, 0xf3, 0x68, 0xa7, 0xa7, 0xea, 0xc8, 0xd7, 0xde, 0xa5, 0xd6, 0x4d, 0x2d, + 0x96, 0x25, 0x5c, 0xcf, 0xc8, 0x4d, 0xac, 0xcb, 0xdb, 0x00, 0xcd, 0xe4, 0xd3, 0x28, 0xfc, 0x89, 0xa9, 0x29, 0x35, + 0x91, 0x31, 0x64, 0x5b, 0x48, 0x55, 0xdb, 0x28, 0xd1, 0x36, 0xa4, 0xdd, 0xce, 0x4f, 0x5b, 0x48, 0xf1, 0x53, 0x5b, + 0x16, 0xd2, 0xfe, 0xf5, 0x0a, 0x4a, 0x49, 0xf8, 0x20, 0x5c, 0x4c, 0x00, 0x84, 0xfb, 0xd0, 0x29, 0x0b, 0x70, 0xe1, + 0x8e, 0xa3, 0xb0, 0xd7, 0x3b, 0x6b, 0xae, 0xa6, 0xc5, 0xe6, 0x07, 0xdd, 0xe7, 0x61, 0x50, 0x8e, 0xf3, 0x9a, 0x3c, + 0x15, 0xdc, 0xf8, 0x23, 0x0b, 0x85, 0x82, 0xf1, 0x6e, 0x22, 0x66, 0xa5, 0xe8, 0xb5, 0x25, 0xc5, 0xda, 0xa9, 0x80, + 0x1a, 0x84, 0xdd, 0x40, 0x55, 0x33, 0xa6, 0x34, 0x95, 0x96, 0x60, 0xf9, 0xbc, 0xd3, 0xf4, 0x9f, 0xd3, 0xf6, 0x47, + 0x42, 0x48, 0xad, 0x6c, 0x43, 0xe1, 0x01, 0x94, 0xe8, 0xb4, 0xcf, 0xfd, 0x45, 0xf0, 0xea, 0xab, 0x4f, 0xd7, 0xd1, + 0x48, 0x8e, 0x12, 0xb3, 0xa8, 0xbb, 0x76, 0x73, 0x7a, 0xfd, 0x9f, 0x91, 0xbc, 0x14, 0xcd, 0x36, 0x4c, 0x03, 0xc5, + 0xcd, 0x5c, 0xf3, 0x5c, 0xd0, 0x45, 0xce, 0x71, 0x41, 0xc5, 0x0b, 0xc7, 0xb5, 0xac, 0xa9, 0xc6, 0x57, 0xba, 0x8a, + 0x41, 0xa5, 0x8c, 0x87, 0x0d, 0x9e, 0x13, 0x8d, 0x30, 0x5c, 0xaf, 0x1c, 0x36, 0x15, 0x4a, 0x5f, 0x09, 0x1c, 0x36, + 0xb5, 0x11, 0x22, 0x59, 0xc3, 0x51, 0xc3, 0x9d, 0x61, 0x49, 0x2b, 0x7d, 0xe5, 0x36, 0x88, 0x76, 0xeb, 0xd3, 0x1c, + 0x3c, 0x0a, 0x3e, 0xb3, 0xc3, 0x23, 0x3c, 0xa9, 0x49, 0x4e, 0x11, 0x3c, 0xc8, 0x93, 0x87, 0xfa, 0x40, 0x77, 0x7e, + 0x29, 0xd1, 0x5e, 0xc1, 0x22, 0xe3, 0x31, 0xcd, 0xf3, 0x10, 0x3a, 0xa6, 0x5b, 0x09, 0x6d, 0xd7, 0x0b, 0xf6, 0xc2, + 0xb8, 0x7a, 0x48, 0x11, 0x4d, 0x09, 0xf4, 0x3f, 0x8d, 0x31, 0x3b, 0xab, 0x97, 0x0f, 0xef, 0x33, 0x66, 0x60, 0x3b, + 0xae, 0xdd, 0x40, 0x81, 0xec, 0xfb, 0xbf, 0x8e, 0xc2, 0x9b, 0x58, 0xf8, 0x69, 0x9f, 0xd4, 0x6f, 0x9d, 0x75, 0x8e, + 0xfd, 0x0b, 0xbb, 0x4d, 0x96, 0x5e, 0x39, 0x8a, 0x6b, 0x14, 0x60, 0x72, 0x2c, 0x3d, 0xaa, 0xef, 0x45, 0xc1, 0x9e, + 0xf0, 0x40, 0x9c, 0xac, 0x62, 0xff, 0x90, 0x5e, 0x1b, 0x00, 0x4c, 0x61, 0x72, 0x9f, 0x56, 0xf6, 0xab, 0x1f, 0x6e, + 0x6c, 0xb0, 0xe5, 0x4a, 0x85, 0x7d, 0x0d, 0x87, 0xeb, 0x55, 0x42, 0xb0, 0xdb, 0xaa, 0xeb, 0x81, 0x90, 0x9b, 0x8c, + 0x37, 0xc5, 0xe0, 0xad, 0x05, 0x5e, 0xb0, 0x5d, 0xc7, 0xc2, 0x9b, 0xd8, 0x6c, 0x7d, 0xa1, 0xf6, 0x82, 0x8f, 0xf2, + 0xa8, 0x3f, 0xcb, 0x83, 0xfe, 0x3c, 0xd6, 0x01, 0xfc, 0xe1, 0x39, 0x61, 0x95, 0x7f, 0x92, 0x18, 0x1c, 0x61, 0x61, + 0xcd, 0x6c, 0x34, 0x34, 0x17, 0xc6, 0x8d, 0x19, 0x3d, 0xf5, 0xc9, 0xc5, 0xa1, 0xb8, 0xd9, 0x5a, 0x02, 0x97, 0xe8, + 0xd4, 0x2c, 0xfd, 0xf7, 0x06, 0x4f, 0x42, 0xa4, 0xbc, 0x55, 0xfa, 0x03, 0xb4, 0x8b, 0xd5, 0x97, 0xff, 0xd3, 0x4a, + 0x38, 0x60, 0x9c, 0x46, 0xe9, 0x22, 0x7e, 0xbf, 0x82, 0x1b, 0xf9, 0x27, 0x5b, 0x58, 0xbd, 0x13, 0x7f, 0xd4, 0xa6, + 0xf6, 0xf4, 0x69, 0x58, 0xe8, 0x0b, 0x63, 0x94, 0xb0, 0x18, 0xc6, 0x4b, 0x63, 0x77, 0x07, 0x33, 0x36, 0x6c, 0x9f, + 0x6f, 0x24, 0x7c, 0xe8, 0x9f, 0x17, 0x82, 0x3a, 0xce, 0xa9, 0xd9, 0xd2, 0x8a, 0x46, 0xbf, 0x5d, 0xc2, 0xd6, 0x40, + 0x02, 0xcc, 0x33, 0xbf, 0x84, 0xc0, 0xc9, 0x24, 0x6a, 0x12, 0x12, 0x58, 0xed, 0x4c, 0xff, 0x6a, 0x55, 0xf1, 0xfb, + 0x7c, 0xe8, 0x10, 0xde, 0xd6, 0xae, 0xe2, 0xfb, 0x42, 0xb8, 0x99, 0xd4, 0xcd, 0x06, 0xe9, 0xc7, 0xb2, 0x4d, 0x63, + 0xe7, 0x00, 0xbe, 0x52, 0x3d, 0x14, 0x90, 0x13, 0xd4, 0x3b, 0x9d, 0xd7, 0x1d, 0xea, 0x88, 0x83, 0x74, 0x31, 0xdb, + 0xa0, 0xa9, 0x37, 0x2b, 0xdf, 0x76, 0xdc, 0x68, 0x46, 0x43, 0xe3, 0xdc, 0x20, 0x85, 0x83, 0x6f, 0x04, 0xe8, 0x6c, + 0xba, 0xc7, 0x0d, 0xd2, 0x49, 0x33, 0x34, 0xfd, 0xd6, 0x11, 0xa5, 0x9a, 0x84, 0xd9, 0x64, 0x0b, 0x8b, 0xa3, 0xb4, + 0xa3, 0xd6, 0x5d, 0xe1, 0xf6, 0xcd, 0x85, 0x83, 0x96, 0x53, 0xb4, 0x49, 0x24, 0x8a, 0xc4, 0x51, 0xcb, 0x29, 0x7d, + 0x74, 0x8a, 0x62, 0x84, 0x8e, 0xb3, 0x8b, 0xcd, 0xab, 0x98, 0x69, 0xb8, 0x12, 0x15, 0x73, 0x7f, 0x81, 0xef, 0xc6, + 0xba, 0x7b, 0x8a, 0x49, 0xa9, 0x74, 0x49, 0x75, 0x17, 0xb3, 0x05, 0xbe, 0x8e, 0xf9, 0x0b, 0xab, 0x57, 0x17, 0xaf, + 0x17, 0x56, 0x93, 0xe9, 0x16, 0xfc, 0xb4, 0x69, 0xfd, 0x16, 0x92, 0x96, 0x03, 0x42, 0x15, 0xff, 0x4c, 0xa6, 0x78, + 0xd5, 0x58, 0x43, 0x4a, 0x36, 0x47, 0x9a, 0x7e, 0xaf, 0xd0, 0xe4, 0x23, 0x8d, 0xce, 0xd2, 0xd5, 0xa9, 0x58, 0xa5, + 0x9f, 0xaa, 0x14, 0xf1, 0xad, 0xda, 0x84, 0x51, 0x41, 0x2b, 0x73, 0x47, 0x75, 0x6f, 0xdf, 0xae, 0x23, 0x44, 0x9f, + 0x97, 0x84, 0x72, 0xec, 0x72, 0xa9, 0x03, 0x1d, 0x20, 0xbe, 0xed, 0x14, 0x30, 0x2f, 0xc7, 0xa8, 0xdd, 0xbc, 0x1b, + 0x0b, 0x09, 0xf9, 0x87, 0xa4, 0x8e, 0x93, 0xd1, 0xa5, 0xf8, 0xb9, 0xee, 0xf9, 0x59, 0xde, 0x89, 0x60, 0x3e, 0xfa, + 0x36, 0x62, 0x50, 0x96, 0x60, 0xf3, 0x5f, 0xe7, 0x81, 0x02, 0x93, 0x40, 0x93, 0x6b, 0x23, 0x4e, 0x35, 0xa9, 0xfa, + 0x5a, 0x82, 0xc2, 0x34, 0xbd, 0xaa, 0x15, 0xb9, 0xa9, 0x96, 0x11, 0x0b, 0xf6, 0x80, 0x3a, 0x53, 0x74, 0x0b, 0xc0, + 0x22, 0x8c, 0xcf, 0xc4, 0xd9, 0xf2, 0x45, 0xa6, 0xd4, 0x58, 0x0e, 0x15, 0x3b, 0xf6, 0xeb, 0xd9, 0xfd, 0xf5, 0x1f, + 0xcd, 0xdf, 0xfe, 0xfa, 0xda, 0xab, 0x47, 0x59, 0x3a, 0x84, 0xfb, 0x9d, 0x75, 0x0c, 0x83, 0x02, 0x44, 0x65, 0xfb, + 0x6d, 0x89, 0xbf, 0xe6, 0x55, 0x94, 0x74, 0xd6, 0xc6, 0xbd, 0x49, 0xc2, 0xa7, 0x35, 0x23, 0xdf, 0x06, 0x16, 0x7c, + 0x6b, 0x98, 0x5d, 0xea, 0xe0, 0x39, 0xd5, 0xa3, 0x9d, 0x02, 0x8e, 0x83, 0xc1, 0xbf, 0x91, 0xda, 0x26, 0x0c, 0x30, + 0xe4, 0x24, 0x9a, 0x2f, 0x74, 0x65, 0x79, 0x9e, 0xa5, 0x64, 0x47, 0x4c, 0xdf, 0x73, 0xc1, 0x8f, 0xbc, 0x2e, 0xf1, + 0x16, 0x6e, 0x08, 0xb0, 0x09, 0xca, 0x1a, 0x03, 0xc7, 0x29, 0x6e, 0xe4, 0xdb, 0x0a, 0xef, 0x21, 0xb0, 0x33, 0x85, + 0x5b, 0x3c, 0xbf, 0xdb, 0x8b, 0x23, 0x04, 0xa7, 0xe0, 0x93, 0x95, 0xd9, 0xac, 0xe8, 0xa5, 0x7f, 0x99, 0x95, 0xf4, + 0xc8, 0x28, 0x77, 0x9b, 0x3c, 0x6d, 0xd9, 0x9a, 0x02, 0x30, 0x83, 0x67, 0x0c, 0x58, 0x70, 0xa7, 0x98, 0xc6, 0x9f, + 0xde, 0xf7, 0x11, 0x6b, 0x75, 0xcb, 0x97, 0xd3, 0x3a, 0x76, 0xef, 0x53, 0x92, 0x40, 0x8d, 0xb3, 0xeb, 0xc7, 0xcb, + 0xb8, 0x6e, 0xdd, 0x67, 0x56, 0xb7, 0x1e, 0x4b, 0xf1, 0xdf, 0x57, 0xab, 0xf3, 0x25, 0x7a, 0x95, 0xf0, 0x26, 0x15, + 0xf5, 0xa4, 0x92, 0x73, 0x8b, 0xbc, 0xbc, 0x72, 0x2e, 0x06, 0xe4, 0xd9, 0x51, 0xbb, 0x51, 0x85, 0x16, 0x5b, 0x63, + 0xb1, 0x3e, 0xcd, 0x24, 0x43, 0x7d, 0xaf, 0xe1, 0x5e, 0x9f, 0x5e, 0xae, 0xc2, 0xf2, 0x34, 0xaa, 0x5d, 0x5a, 0x5f, + 0x6e, 0x94, 0xe4, 0xba, 0xf8, 0x81, 0xb5, 0xb5, 0xf0, 0xe6, 0x60, 0xa3, 0x65, 0x4c, 0xb4, 0x92, 0xd5, 0xd3, 0x4a, + 0x56, 0x4e, 0x13, 0x97, 0x7b, 0xbd, 0xe8, 0x02, 0x39, 0xfe, 0x60, 0xd0, 0xaa, 0xe5, 0x83, 0xc6, 0xac, 0xb6, 0x0f, + 0x3a, 0xa5, 0x5a, 0x9f, 0x14, 0x16, 0xf1, 0xc8, 0x1a, 0x70, 0xb0, 0xb1, 0x56, 0x4a, 0xa6, 0x95, 0x6d, 0x32, 0xae, + 0xd0, 0x0f, 0xa9, 0x6a, 0xd5, 0xfb, 0x1f, 0xa6, 0xb8, 0xc1, 0xd5, 0xc6, 0x9f, 0x05, 0xb9, 0xfe, 0x53, 0x61, 0x47, + 0x39, 0xe8, 0x28, 0xb4, 0xfe, 0xe6, 0x7f, 0xa8, 0xf9, 0x11, 0xdc, 0x0c, 0xb1, 0x95, 0xd9, 0x5b, 0x10, 0xb5, 0x2b, + 0x09, 0xe4, 0x7b, 0xc0, 0xb5, 0x02, 0xa4, 0x62, 0xaf, 0x57, 0xa2, 0x75, 0x9a, 0x04, 0x63, 0x43, 0x90, 0x39, 0x8b, + 0xd8, 0x05, 0xa9, 0x1d, 0xdd, 0x66, 0x46, 0x75, 0xf3, 0x13, 0xaf, 0xf1, 0xa7, 0x4a, 0xa8, 0xbe, 0x7c, 0xa3, 0xb0, + 0x78, 0xc2, 0x03, 0x6a, 0x9f, 0x82, 0x46, 0x75, 0xad, 0x29, 0xa6, 0xb4, 0x20, 0x32, 0x91, 0x31, 0xf8, 0x20, 0x43, + 0x83, 0xb8, 0x5d, 0xb6, 0x5e, 0x90, 0xee, 0xc9, 0xbb, 0xdd, 0xaf, 0x92, 0x5e, 0xda, 0x27, 0x90, 0xfa, 0x16, 0x4d, + 0x60, 0xb6, 0x52, 0xd0, 0x6e, 0x61, 0xbd, 0xbd, 0x60, 0xee, 0x85, 0xb8, 0x72, 0xe1, 0xc0, 0x9a, 0x30, 0xd6, 0xbb, + 0x9a, 0xe7, 0x86, 0xf5, 0xaf, 0x7f, 0xb6, 0x57, 0x8d, 0x5c, 0x54, 0xa6, 0x75, 0x5e, 0x06, 0xc8, 0x4e, 0x5c, 0xe6, + 0xf6, 0x59, 0xca, 0x7b, 0x16, 0x11, 0x34, 0xe4, 0x99, 0x5b, 0xf1, 0x25, 0x6c, 0xfa, 0x1a, 0x36, 0xdf, 0xb5, 0x4f, + 0x6d, 0xb5, 0x62, 0x92, 0x54, 0xa3, 0x3c, 0x71, 0xdd, 0x05, 0x06, 0xed, 0x0f, 0x2e, 0xcd, 0x4e, 0xe7, 0xee, 0x67, + 0xda, 0x03, 0x8e, 0x59, 0x8b, 0xde, 0x36, 0xe0, 0xc8, 0x87, 0xf4, 0x90, 0xba, 0x3b, 0xb9, 0xcd, 0x2d, 0x80, 0xdb, + 0x42, 0x5f, 0x5a, 0x5a, 0xe6, 0x9b, 0x58, 0x6e, 0xae, 0xce, 0x8b, 0x34, 0xbd, 0x50, 0xd6, 0x6d, 0x2f, 0xc1, 0xd1, + 0x26, 0xcf, 0x65, 0x83, 0x6b, 0x54, 0x0a, 0x97, 0x81, 0xff, 0x17, 0x25, 0x45, 0xbf, 0x16, 0x03, 0xc1, 0xd8, 0x31, + 0xe9, 0x2b, 0xbd, 0x3a, 0xe2, 0x4a, 0x89, 0x0e, 0xfc, 0x11, 0x54, 0x27, 0x7b, 0x03, 0x4d, 0xea, 0xcc, 0xde, 0x25, + 0x25, 0x42, 0xbb, 0xa7, 0x69, 0x73, 0x29, 0xa1, 0xfe, 0x7a, 0xc1, 0x87, 0xb7, 0xfd, 0xe2, 0xf6, 0x6c, 0xef, 0x2b, + 0xf7, 0x9e, 0x77, 0x2b, 0x55, 0xb3, 0x3f, 0xcb, 0x89, 0x3d, 0x3b, 0xf6, 0xd3, 0x34, 0x1f, 0xf4, 0xf4, 0x93, 0xfb, + 0x0f, 0x2f, 0xcc, 0x79, 0xc2, 0x0e, 0xb4, 0x76, 0x7b, 0x5c, 0xf3, 0x55, 0x28, 0x15, 0x9c, 0x08, 0x1b, 0x5f, 0x16, + 0xbd, 0x35, 0xe4, 0x82, 0x93, 0x72, 0x12, 0xc5, 0xd4, 0x5e, 0x34, 0xc7, 0x5b, 0x70, 0x93, 0x9f, 0x76, 0x17, 0x81, + 0x14, 0x5a, 0xe5, 0xb9, 0xfa, 0x5f, 0xec, 0x18, 0x8b, 0x97, 0xb9, 0xeb, 0x30, 0xb7, 0x13, 0xaa, 0x88, 0x3f, 0xb7, + 0x44, 0x93, 0xff, 0x70, 0xfc, 0xaf, 0xa3, 0x3f, 0xb5, 0x24, 0x1f, 0x79, 0x3b, 0xa1, 0xe3, 0x89, 0xab, 0x64, 0xf7, + 0x1a, 0x65, 0x76, 0x16, 0x53, 0x4f, 0x55, 0xe7, 0x33, 0x49, 0x66, 0x5d, 0xe5, 0x13, 0xc2, 0xe1, 0xd1, 0xfc, 0x10, + 0xee, 0x96, 0xc5, 0x9a, 0xac, 0xcc, 0x15, 0x65, 0x57, 0x68, 0x9f, 0x53, 0x0f, 0xc4, 0xd6, 0x64, 0x7e, 0xa0, 0x73, + 0x2f, 0x92, 0x91, 0x49, 0xa5, 0x2c, 0x6b, 0x87, 0x48, 0xc3, 0xcb, 0x5d, 0x9e, 0xf2, 0x3e, 0x3f, 0x54, 0x54, 0xb6, + 0x43, 0xe6, 0xb9, 0xfb, 0x3a, 0x33, 0x40, 0xa3, 0x98, 0xa3, 0x2b, 0xe0, 0x96, 0x80, 0x79, 0x6a, 0x34, 0x7b, 0xd6, + 0x5c, 0x95, 0x4c, 0xda, 0xcb, 0x35, 0xf4, 0xb9, 0x67, 0x9a, 0xc9, 0x36, 0x76, 0x11, 0x32, 0x2d, 0x57, 0x65, 0x6b, + 0xe9, 0x33, 0x5f, 0x73, 0xe7, 0x99, 0x07, 0xfc, 0xf4, 0x55, 0x72, 0x89, 0xfa, 0x7a, 0xda, 0x9a, 0xb4, 0x3c, 0x5b, + 0x50, 0xa8, 0x71, 0x8a, 0xc2, 0x1b, 0x28, 0x26, 0x1a, 0xaa, 0xc2, 0x3c, 0x9e, 0xfc, 0x0c, 0x7b, 0x6a, 0xc9, 0xc1, + 0x74, 0xc6, 0x97, 0x9a, 0xee, 0xa7, 0xe6, 0xac, 0x3e, 0x23, 0x07, 0xad, 0xb1, 0x3a, 0xdb, 0x7e, 0xf1, 0xdc, 0x1f, + 0xbc, 0x3f, 0x0d, 0x90, 0xf8, 0x7a, 0x98, 0x7c, 0x8d, 0xad, 0xd4, 0xe4, 0xcf, 0xd7, 0xdf, 0xd7, 0xab, 0x40, 0xb2, + 0x39, 0xdf, 0xbb, 0xbe, 0x0b, 0x16, 0x4a, 0x7f, 0x18, 0x58, 0x31, 0xbb, 0x31, 0x7a, 0x94, 0x22, 0x44, 0xe1, 0x1e, + 0x4b, 0x11, 0x79, 0xab, 0x87, 0xc1, 0xdf, 0x12, 0x71, 0x32, 0x5c, 0xa2, 0x80, 0xc6, 0xe7, 0xd3, 0x4c, 0x2b, 0xae, + 0x88, 0x22, 0x81, 0xbd, 0x16, 0x35, 0x93, 0x6c, 0x13, 0x8c, 0xa0, 0x45, 0x2d, 0x07, 0x32, 0x9c, 0xc5, 0x82, 0x2f, + 0x18, 0x69, 0xce, 0xed, 0x9a, 0xc5, 0xc4, 0x85, 0x8c, 0xb7, 0x57, 0x11, 0x33, 0xda, 0xad, 0x07, 0x0c, 0xe7, 0x33, + 0x03, 0xcd, 0xc5, 0xb8, 0x22, 0x36, 0x7f, 0x84, 0x23, 0x4a, 0xee, 0xb5, 0x90, 0x7d, 0x3f, 0x23, 0xf5, 0x09, 0x43, + 0xc6, 0x24, 0x63, 0xbb, 0x61, 0xc6, 0xe4, 0x7d, 0x91, 0xa7, 0xab, 0xc1, 0xa2, 0xfb, 0x60, 0xb7, 0x16, 0xae, 0x2d, + 0x20, 0xeb, 0x70, 0x18, 0x7a, 0x5f, 0xde, 0x47, 0x81, 0xd2, 0x6c, 0x5f, 0x5f, 0x3d, 0xc0, 0xfe, 0x6e, 0x45, 0x26, + 0x06, 0x24, 0x69, 0x1b, 0x50, 0x78, 0xdc, 0x52, 0xdf, 0xd6, 0xa8, 0xf5, 0x2c, 0xab, 0xb9, 0x97, 0x25, 0xd5, 0x68, + 0xe3, 0x8b, 0x45, 0x7f, 0x31, 0x25, 0x12, 0xc9, 0x3c, 0x08, 0xd6, 0x48, 0xf8, 0x9b, 0xf7, 0x24, 0x75, 0xc5, 0x79, + 0xea, 0x7d, 0xc2, 0x45, 0x4c, 0xa4, 0x37, 0x50, 0xa4, 0x4c, 0x5b, 0x2f, 0xfe, 0xdd, 0x57, 0xe8, 0xf4, 0xe6, 0x63, + 0x13, 0x2b, 0x17, 0x03, 0x40, 0x98, 0x89, 0x16, 0xf1, 0x38, 0xf4, 0xb4, 0x87, 0x58, 0xa4, 0x27, 0x4b, 0xbd, 0xc4, + 0x65, 0x3a, 0x2e, 0x94, 0x2f, 0x57, 0x0b, 0x41, 0xda, 0x50, 0xa4, 0xbe, 0x0b, 0xf9, 0xc2, 0x07, 0x57, 0x82, 0x55, + 0xf2, 0x0d, 0x93, 0xc9, 0xf9, 0xb3, 0xbc, 0x6f, 0x7e, 0x0b, 0x2c, 0x7e, 0xd7, 0xe0, 0x25, 0xee, 0x7d, 0x1f, 0x7c, + 0x8d, 0x06, 0x5a, 0xfd, 0xcf, 0x56, 0x8c, 0x62, 0x88, 0x65, 0xb5, 0x08, 0x3e, 0xd5, 0x6e, 0x7a, 0x8a, 0x96, 0x7c, + 0xc9, 0x93, 0xbb, 0xf0, 0x92, 0xd4, 0xda, 0xc6, 0x61, 0xd6, 0xde, 0xa3, 0xdc, 0xd0, 0x7b, 0xad, 0x16, 0xa4, 0x43, + 0xcc, 0xae, 0xe0, 0x32, 0xe3, 0x05, 0x26, 0xeb, 0xcf, 0x52, 0x58, 0x2c, 0xf2, 0x8b, 0x2a, 0xd2, 0x9e, 0xb2, 0xcc, + 0x87, 0x6c, 0xa6, 0x75, 0x4d, 0xc9, 0xa2, 0x80, 0x4b, 0x94, 0x95, 0x42, 0x6c, 0xe4, 0xe2, 0xb3, 0x56, 0x80, 0x35, + 0xf0, 0x0a, 0x84, 0x62, 0x92, 0x9a, 0xbc, 0x71, 0xf5, 0xdf, 0x9a, 0xfc, 0xab, 0x3a, 0xe6, 0xdf, 0x54, 0x32, 0xff, + 0xfa, 0x7c, 0x4d, 0x1b, 0x7f, 0x6f, 0xf4, 0x25, 0xf1, 0xad, 0x94, 0x80, 0x12, 0x5b, 0x29, 0xbe, 0x23, 0x70, 0x1a, + 0x5d, 0x19, 0xec, 0xc6, 0x03, 0x0b, 0x2b, 0x21, 0xcf, 0x4d, 0x4e, 0x33, 0xad, 0x47, 0xb6, 0xa8, 0xfe, 0xce, 0x1e, + 0x38, 0x49, 0x7a, 0x2d, 0xfd, 0xbb, 0x19, 0x4f, 0x51, 0x20, 0x59, 0xe4, 0x12, 0x3b, 0x91, 0x87, 0xd8, 0x20, 0x40, + 0x90, 0x8b, 0x1c, 0xd0, 0x61, 0xaa, 0x26, 0x12, 0x91, 0xfa, 0xcf, 0x40, 0x0e, 0x2b, 0x60, 0xc0, 0x21, 0x90, 0x23, + 0x31, 0x30, 0x92, 0xe3, 0x13, 0x11, 0x17, 0x92, 0x77, 0x22, 0x2b, 0x42, 0xac, 0x06, 0x76, 0xbc, 0x41, 0x19, 0x6e, + 0x8b, 0xe4, 0x39, 0x0a, 0x14, 0x65, 0xe5, 0x8c, 0x65, 0xc4, 0xd6, 0xea, 0x59, 0xe7, 0xb4, 0x5e, 0xad, 0xa9, 0x73, + 0xc9, 0xd4, 0x69, 0x76, 0xe9, 0x64, 0xbe, 0x00, 0xf6, 0xb5, 0x28, 0x03, 0x7b, 0xd6, 0x01, 0xec, 0xd4, 0x8a, 0x13, + 0x53, 0x71, 0xd9, 0x73, 0xd6, 0x00, 0xd0, 0xd1, 0xb3, 0x06, 0x31, 0x33, 0xe8, 0x5c, 0xb3, 0x5c, 0x83, 0x04, 0x2e, + 0x5c, 0xa2, 0x5e, 0x1a, 0x4a, 0x5b, 0xcf, 0x2c, 0x0a, 0xbf, 0x45, 0xf9, 0xfc, 0x1c, 0x9a, 0x70, 0x11, 0x25, 0xec, + 0xb2, 0xb8, 0xfc, 0x29, 0x5e, 0xe3, 0xa3, 0x5a, 0xd3, 0xca, 0x4b, 0xbb, 0x35, 0xa6, 0xe7, 0x92, 0x82, 0x2d, 0xba, + 0xaa, 0xcf, 0x7b, 0xba, 0xa4, 0x8b, 0xb8, 0x8f, 0x9e, 0x12, 0x05, 0xca, 0xda, 0x15, 0x07, 0x0c, 0x2d, 0xd9, 0x89, + 0xc6, 0xa6, 0x68, 0xe9, 0xed, 0xdd, 0x76, 0xe9, 0xb6, 0x26, 0x43, 0x8e, 0x03, 0x85, 0x1d, 0x01, 0x51, 0x53, 0xdc, + 0x09, 0x8a, 0xba, 0xf2, 0xe1, 0x06, 0xa7, 0x39, 0x9d, 0x19, 0xbe, 0x15, 0x24, 0x9b, 0x08, 0x7c, 0xce, 0x8f, 0xde, + 0x4b, 0xa9, 0xab, 0xaf, 0x74, 0x3a, 0xf4, 0xb0, 0xd9, 0xc0, 0x41, 0x5e, 0xb0, 0x7d, 0x22, 0x75, 0x5a, 0x11, 0x52, + 0x11, 0x7f, 0x5f, 0xf0, 0x55, 0xba, 0xd7, 0x69, 0x43, 0x99, 0xaf, 0x59, 0xb1, 0x03, 0xd9, 0x88, 0xb5, 0x37, 0x52, + 0xde, 0xf6, 0x98, 0x9a, 0xf6, 0x9f, 0x18, 0xb8, 0x3f, 0xb7, 0xbc, 0x5e, 0x3c, 0x85, 0x29, 0x5e, 0x61, 0xa4, 0x6a, + 0xb1, 0x19, 0x8e, 0x39, 0x37, 0xee, 0xe5, 0x9a, 0x3d, 0xeb, 0xa9, 0x14, 0x50, 0x2c, 0x2b, 0x7c, 0xae, 0xca, 0xec, + 0x4d, 0xbe, 0x84, 0x5e, 0x58, 0xde, 0x7d, 0x9f, 0xf5, 0xf5, 0xaa, 0xf3, 0xad, 0x82, 0x57, 0xf5, 0x3b, 0xed, 0x17, + 0xcb, 0x29, 0x0d, 0xaf, 0x7a, 0x34, 0x71, 0x35, 0x98, 0x9d, 0x47, 0xa7, 0x80, 0x9a, 0x29, 0x00, 0x3e, 0x62, 0x53, + 0xd0, 0x15, 0xca, 0x23, 0x70, 0xde, 0x48, 0x98, 0xbd, 0x11, 0x10, 0xbd, 0x59, 0x33, 0x45, 0xf2, 0x45, 0xfb, 0x13, + 0x9b, 0x2e, 0x2e, 0x51, 0xb6, 0xf2, 0x21, 0xed, 0x0e, 0xf1, 0x42, 0x8e, 0x33, 0x2b, 0xa1, 0x6b, 0xc9, 0x6e, 0x9b, + 0xc9, 0xd6, 0x24, 0x4c, 0x00, 0xb0, 0x22, 0x67, 0x91, 0x2f, 0x5d, 0x9f, 0xd9, 0x86, 0xb2, 0x35, 0xc1, 0x08, 0x43, + 0xc3, 0x27, 0xea, 0xde, 0xf9, 0x53, 0xb3, 0xe2, 0xed, 0xc0, 0x88, 0x49, 0xf1, 0x9c, 0x31, 0xfc, 0x3c, 0xfc, 0xf2, + 0xad, 0x4e, 0x59, 0x63, 0x2f, 0xac, 0xcc, 0x0a, 0x22, 0x1e, 0x30, 0x13, 0x20, 0xf9, 0xdf, 0xe5, 0x32, 0xea, 0x8d, + 0xf2, 0x54, 0x62, 0x72, 0x6f, 0x17, 0x18, 0x2a, 0x40, 0x9c, 0x53, 0x4d, 0xa7, 0x14, 0x6f, 0x56, 0x07, 0x61, 0x76, + 0x3e, 0x28, 0x39, 0x62, 0x83, 0x25, 0x0c, 0xf5, 0x61, 0xd7, 0x62, 0x73, 0x89, 0x6b, 0xd9, 0x51, 0x27, 0xb1, 0x16, + 0xca, 0x14, 0x7f, 0xb8, 0xac, 0x30, 0x22, 0xc4, 0x45, 0x4d, 0x27, 0xe2, 0xa3, 0x29, 0xda, 0xd1, 0x6a, 0x02, 0xee, + 0x7a, 0x3a, 0xe5, 0xe3, 0xba, 0xbe, 0xb8, 0x74, 0x0d, 0x32, 0x71, 0x51, 0x60, 0x29, 0x2f, 0x93, 0x5f, 0x19, 0x3f, + 0x02, 0x5b, 0x78, 0xa0, 0x13, 0x1e, 0x27, 0x59, 0x9d, 0x20, 0xc6, 0x40, 0x34, 0x8b, 0xf0, 0x2a, 0x7a, 0x01, 0x92, + 0x9a, 0xe9, 0x32, 0x38, 0x6d, 0x5b, 0xae, 0x18, 0x49, 0xfb, 0xba, 0x12, 0x5d, 0x4b, 0xbe, 0x54, 0x84, 0x7c, 0xd9, + 0x0e, 0x67, 0x77, 0x1e, 0x9d, 0x6e, 0x67, 0x56, 0xc4, 0x8d, 0x4f, 0x3a, 0x09, 0x2e, 0x83, 0xbe, 0x21, 0xd9, 0xa1, + 0x3c, 0xa0, 0xad, 0x5f, 0xe6, 0x64, 0x4c, 0xbe, 0xe2, 0x6c, 0x43, 0x8a, 0x4a, 0x9e, 0x29, 0xdd, 0xce, 0x47, 0x57, + 0x71, 0xaa, 0x37, 0x58, 0x0f, 0x42, 0xe5, 0x00, 0x43, 0x6a, 0x12, 0x7e, 0xc4, 0xad, 0xdc, 0x58, 0xfb, 0xae, 0x4e, + 0x2a, 0xbc, 0x82, 0x33, 0x1d, 0xca, 0xb6, 0x95, 0xb9, 0xcb, 0x6c, 0x94, 0x64, 0xcb, 0x92, 0xe0, 0xbf, 0x5b, 0x45, + 0xb1, 0xe6, 0xc1, 0x79, 0x18, 0x95, 0xef, 0x8b, 0x5c, 0x3d, 0xac, 0xa7, 0xec, 0xed, 0x24, 0x94, 0xf0, 0x89, 0xa5, + 0xe3, 0xf4, 0xdb, 0x01, 0xe3, 0x94, 0x9d, 0x48, 0x5a, 0x20, 0xa7, 0xff, 0xc2, 0xb7, 0x9d, 0x06, 0x21, 0xc4, 0x3b, + 0x65, 0xbd, 0x5a, 0x00, 0x38, 0x97, 0x32, 0x3e, 0xab, 0xff, 0x02, 0x54, 0xb2, 0xeb, 0x8b, 0x71, 0x3f, 0xe0, 0xd1, + 0xa6, 0x95, 0xdf, 0x8e, 0x24, 0xcc, 0xee, 0xba, 0x7c, 0x03, 0x3d, 0x8e, 0x65, 0x07, 0x2b, 0xec, 0xab, 0x04, 0x79, + 0xe6, 0xb9, 0x48, 0x81, 0x65, 0x13, 0xc5, 0xfc, 0xa6, 0xa1, 0x4f, 0xc0, 0xc1, 0x4c, 0x77, 0x06, 0x8d, 0xd9, 0x55, + 0xad, 0xbe, 0xc6, 0xf1, 0xa2, 0x2c, 0x09, 0x5e, 0xa4, 0x31, 0x0a, 0xab, 0xb9, 0x9c, 0x87, 0xaa, 0x42, 0xe5, 0xcc, + 0x75, 0x33, 0xd6, 0xd5, 0x6d, 0xb6, 0xbb, 0x47, 0x9b, 0x13, 0xa0, 0x4a, 0x6f, 0xcc, 0x58, 0x82, 0x8a, 0xe8, 0xa0, + 0x9f, 0xb1, 0xbb, 0xca, 0xa0, 0xe3, 0x95, 0x35, 0x9f, 0x88, 0x01, 0xb7, 0x36, 0xa3, 0x22, 0x4a, 0x28, 0x1a, 0xeb, + 0xac, 0x42, 0xb5, 0xd7, 0x83, 0x6d, 0xab, 0x36, 0x10, 0x6d, 0x32, 0xa9, 0x40, 0x52, 0x11, 0xfe, 0xa2, 0xfc, 0xda, + 0xd2, 0x5e, 0xcf, 0x74, 0x46, 0x3a, 0xa8, 0x4a, 0x73, 0xce, 0x9c, 0x33, 0x3b, 0x60, 0x31, 0x5e, 0x1f, 0x6f, 0x84, + 0xa7, 0x80, 0x6c, 0x11, 0xde, 0x1c, 0xc0, 0xed, 0x6d, 0x2b, 0x0a, 0x07, 0xbb, 0xe9, 0x21, 0xaf, 0xd2, 0x36, 0x8e, + 0x80, 0x01, 0x79, 0x89, 0x93, 0xb9, 0x05, 0x12, 0x15, 0x06, 0x7e, 0x85, 0x60, 0x83, 0x25, 0x3b, 0x29, 0x2d, 0x2e, + 0x8f, 0xed, 0x62, 0x87, 0x4f, 0xcb, 0x7a, 0xb9, 0xf6, 0x06, 0xfd, 0xb5, 0xc6, 0x39, 0xf8, 0xd8, 0x21, 0x74, 0xf9, + 0xc7, 0x6c, 0x95, 0x26, 0xe9, 0xdf, 0x8a, 0x31, 0x2d, 0x2f, 0x92, 0x9c, 0x66, 0xdc, 0xe9, 0x5b, 0xe3, 0xc2, 0x47, + 0xef, 0xb9, 0x64, 0xf1, 0xbd, 0xdc, 0x1e, 0x89, 0x7e, 0x25, 0x18, 0xfa, 0xcb, 0xfa, 0x7a, 0x32, 0x88, 0xb6, 0x9d, + 0xa6, 0x0b, 0xcd, 0x2b, 0xb8, 0x94, 0xa2, 0xe2, 0x56, 0xc3, 0x0f, 0x05, 0x14, 0x49, 0xf9, 0xa8, 0x7d, 0x2c, 0x91, + 0xb5, 0x58, 0x39, 0x93, 0xed, 0x3f, 0xcb, 0x71, 0x86, 0x21, 0xef, 0xac, 0x55, 0x65, 0x55, 0xf9, 0x44, 0x17, 0xb6, + 0x45, 0xaf, 0xd4, 0x0b, 0xb9, 0xec, 0x18, 0x76, 0xbe, 0xb5, 0x37, 0x40, 0x89, 0xff, 0xe5, 0x96, 0xb7, 0xe1, 0x4c, + 0xb0, 0x0b, 0x59, 0x1d, 0x80, 0x0f, 0x8a, 0x52, 0xb2, 0xcd, 0x0b, 0x81, 0x48, 0xd7, 0x5d, 0x30, 0x8f, 0x3a, 0x62, + 0x51, 0xf0, 0x4b, 0xf7, 0x2a, 0xbc, 0xea, 0x27, 0x67, 0x51, 0x19, 0xa0, 0x59, 0x9e, 0xc7, 0x23, 0xd7, 0xc4, 0xc2, + 0xa2, 0xe4, 0xa5, 0x9a, 0xaf, 0xc6, 0x27, 0x36, 0x85, 0xad, 0x16, 0x14, 0xa7, 0xc9, 0x26, 0xe9, 0xfe, 0x40, 0x61, + 0x14, 0x16, 0xf8, 0x8f, 0x6b, 0x9f, 0x98, 0x67, 0x90, 0x68, 0x2e, 0x00, 0xa5, 0xc4, 0xfb, 0x42, 0xbd, 0x1e, 0x55, + 0x59, 0x72, 0xa0, 0xb0, 0xe3, 0x1b, 0x59, 0xbd, 0xf2, 0x3b, 0x95, 0x1a, 0x15, 0xf4, 0xfa, 0xa7, 0xb2, 0xcb, 0x02, + 0xa0, 0xed, 0xa0, 0x5a, 0x4d, 0x2d, 0xeb, 0x29, 0x17, 0xdd, 0xe1, 0x0e, 0x5e, 0xf9, 0x4e, 0xeb, 0x39, 0x9a, 0x0b, + 0x4b, 0x88, 0xb3, 0xef, 0xb1, 0x2c, 0x59, 0xce, 0x7e, 0xd6, 0xbc, 0xd0, 0x8d, 0x32, 0x7d, 0xb9, 0xd7, 0xf3, 0x99, + 0x2c, 0x5c, 0x95, 0x00, 0x33, 0xf2, 0xea, 0x72, 0x00, 0xe0, 0x13, 0x53, 0xba, 0xc2, 0x68, 0x1d, 0x47, 0x59, 0xe6, + 0x98, 0xc6, 0x3e, 0xf7, 0x90, 0xa6, 0x6f, 0x4e, 0xdc, 0x22, 0x97, 0xda, 0x6b, 0xb3, 0x0a, 0xc7, 0xc9, 0xc4, 0x3a, + 0xbe, 0xc8, 0x74, 0xa6, 0x07, 0x49, 0x97, 0x5e, 0xce, 0x80, 0x4c, 0xad, 0xee, 0xc0, 0x5c, 0x35, 0x09, 0xa0, 0xa7, + 0xef, 0x8a, 0x2c, 0x8f, 0xc9, 0xfe, 0xbc, 0x37, 0xbb, 0xf8, 0x8c, 0x74, 0xa3, 0x53, 0xf4, 0xd9, 0x31, 0x2d, 0xd7, + 0xac, 0x48, 0x00, 0x28, 0x17, 0x84, 0xbd, 0x71, 0x4c, 0x62, 0x0b, 0x5a, 0xb6, 0xeb, 0x05, 0x08, 0x1d, 0x01, 0x48, + 0xee, 0x8b, 0x02, 0xdf, 0xcf, 0xce, 0x35, 0x2f, 0x86, 0x2c, 0x7c, 0x9e, 0xa1, 0x5f, 0x0f, 0xb8, 0x2e, 0x13, 0x82, + 0x89, 0x7c, 0x86, 0x86, 0xbf, 0xca, 0xbc, 0x89, 0xb3, 0x11, 0xd1, 0xb5, 0xbf, 0x4f, 0xe9, 0xe3, 0x0a, 0x8e, 0x1f, + 0x2a, 0xe0, 0xf7, 0x03, 0xb3, 0x37, 0xd4, 0x3f, 0x7a, 0x31, 0xa8, 0x86, 0x47, 0x96, 0x9f, 0x2a, 0x30, 0x9a, 0x39, + 0xf0, 0x00, 0x11, 0x44, 0x92, 0xd9, 0x57, 0x71, 0x5b, 0xda, 0x1d, 0x46, 0x01, 0x01, 0x8c, 0x59, 0x93, 0x5d, 0x08, + 0x13, 0x80, 0x75, 0xee, 0x9b, 0xd1, 0x45, 0x0f, 0x7a, 0x6c, 0xf3, 0x51, 0xb9, 0x16, 0xe5, 0x18, 0x8c, 0x69, 0xcc, + 0x17, 0x36, 0xec, 0x09, 0xb6, 0xd1, 0x08, 0x47, 0xaf, 0x60, 0x08, 0x97, 0x34, 0xee, 0x55, 0x3a, 0x17, 0xbe, 0xf7, + 0x2a, 0xca, 0x82, 0x18, 0xbb, 0x6f, 0xc6, 0xa9, 0x01, 0xb2, 0x64, 0xff, 0xb4, 0x60, 0xc9, 0xa9, 0xb3, 0xaf, 0xe9, + 0xe4, 0xd9, 0xc7, 0xdc, 0xf0, 0x4e, 0x9e, 0x83, 0x43, 0xd3, 0x52, 0x4f, 0xeb, 0xfc, 0x0d, 0x5a, 0x68, 0x05, 0xf3, + 0x82, 0x76, 0x76, 0x06, 0x58, 0x5a, 0xa1, 0xb6, 0xa6, 0xb6, 0xe4, 0x0d, 0xfb, 0xa1, 0x95, 0x95, 0x62, 0x30, 0x0d, + 0x20, 0x89, 0x1d, 0x88, 0x46, 0xa1, 0xfd, 0xd0, 0xf7, 0xb7, 0xb9, 0xef, 0x65, 0x89, 0xdf, 0xba, 0xbe, 0x8e, 0x95, + 0x56, 0x8f, 0x7f, 0x3e, 0x0f, 0x97, 0x24, 0x62, 0xbf, 0x56, 0xc1, 0xca, 0x64, 0x63, 0x05, 0x2e, 0xaa, 0xcf, 0x38, + 0x96, 0x7c, 0x28, 0x38, 0xe5, 0x66, 0x85, 0x94, 0x99, 0xec, 0xf3, 0xb0, 0x80, 0xc6, 0xda, 0x8c, 0x6a, 0x50, 0x2b, + 0xe6, 0x60, 0x4e, 0x8f, 0x0a, 0x84, 0xc7, 0x14, 0x40, 0x95, 0x2f, 0x4e, 0x7d, 0xf9, 0x75, 0xce, 0x91, 0x90, 0x4b, + 0xd3, 0xd4, 0xfd, 0xef, 0x52, 0x91, 0xf3, 0x0e, 0x82, 0x10, 0xc3, 0x23, 0xe8, 0x1b, 0x94, 0x5f, 0xfc, 0x89, 0xbf, + 0xf8, 0xba, 0xf8, 0xb9, 0x60, 0xe6, 0x9b, 0x66, 0x39, 0xb3, 0x78, 0x8b, 0x59, 0x6f, 0x1d, 0xb2, 0x15, 0x61, 0x91, + 0xd2, 0x4c, 0x43, 0xce, 0x04, 0xcd, 0xb3, 0xa0, 0x80, 0xcd, 0x7c, 0xae, 0xf5, 0x26, 0x20, 0x3d, 0x90, 0x04, 0xf7, + 0xaf, 0x12, 0x5d, 0x0e, 0x54, 0x4d, 0x47, 0x51, 0x0a, 0x1e, 0x80, 0x9b, 0x4a, 0xa8, 0x01, 0xea, 0xa4, 0xe1, 0x29, + 0xb4, 0x62, 0x2c, 0xc1, 0xb3, 0x2c, 0x62, 0x9d, 0x06, 0x30, 0x1a, 0x49, 0x3c, 0xac, 0x51, 0xb8, 0x3a, 0xcf, 0x26, + 0x63, 0x56, 0xc7, 0xbc, 0xad, 0x2e, 0xb2, 0x3b, 0xd2, 0x04, 0x9f, 0xb9, 0x4e, 0xc5, 0xde, 0xee, 0x38, 0x60, 0x4a, + 0x4d, 0x03, 0x07, 0x99, 0x4a, 0xf3, 0x40, 0xa1, 0x69, 0x5c, 0x0b, 0x30, 0xd0, 0xc9, 0x59, 0x2d, 0x4a, 0x88, 0xad, + 0xb8, 0x01, 0x10, 0x47, 0x3a, 0xfa, 0x20, 0x85, 0x0d, 0x3f, 0x30, 0x96, 0xfc, 0x11, 0xf0, 0x98, 0x3f, 0x78, 0x08, + 0x08, 0x51, 0xda, 0x08, 0x79, 0x62, 0x0d, 0x5a, 0x59, 0x2c, 0x0c, 0x7e, 0x2b, 0xda, 0xcb, 0x9e, 0xe2, 0xf3, 0x8d, + 0xba, 0x1f, 0x08, 0x51, 0xb7, 0xc1, 0x9a, 0x45, 0x46, 0x73, 0x37, 0xf8, 0xaf, 0xf9, 0x3d, 0x49, 0xa4, 0x50, 0x2c, + 0x15, 0xb9, 0x8f, 0x28, 0x6f, 0x31, 0x6e, 0x21, 0x6f, 0xed, 0xe0, 0xe3, 0x56, 0x18, 0xa8, 0x23, 0xad, 0x16, 0x92, + 0xf2, 0x16, 0x53, 0xcd, 0xb8, 0xa3, 0x60, 0x35, 0x51, 0x6a, 0xf8, 0x1c, 0x49, 0xba, 0x7a, 0x8e, 0xcd, 0x4c, 0xfc, + 0x63, 0x66, 0x9a, 0xa7, 0x26, 0x1f, 0x15, 0x75, 0x93, 0xd9, 0xb8, 0xb1, 0xe0, 0xe8, 0x09, 0xcf, 0x84, 0xbc, 0x4b, + 0x1d, 0xed, 0x54, 0x6f, 0x21, 0xe5, 0x21, 0xc3, 0x14, 0xc4, 0x7a, 0x40, 0xef, 0x68, 0x6a, 0x74, 0xeb, 0x6e, 0x4c, + 0x0f, 0x12, 0x88, 0xd5, 0xa9, 0x1d, 0xa1, 0x2d, 0x6e, 0x0f, 0x31, 0x5c, 0x56, 0x5d, 0x0a, 0x14, 0xa9, 0x55, 0x9e, + 0xf2, 0x59, 0x82, 0x12, 0xb0, 0x49, 0x51, 0x9f, 0x73, 0x1c, 0xd6, 0x45, 0x41, 0xed, 0x33, 0x85, 0x48, 0x16, 0xca, + 0x34, 0x5f, 0x06, 0x5f, 0x44, 0x33, 0x68, 0x00, 0xc9, 0x80, 0xaf, 0xf6, 0x9b, 0x6b, 0xe8, 0x46, 0x20, 0x6f, 0xb3, + 0x26, 0xca, 0xe6, 0xc3, 0x39, 0xc4, 0xb6, 0xb6, 0xf7, 0x1b, 0xb4, 0x9e, 0x85, 0x7a, 0x97, 0xf2, 0xac, 0xb0, 0xad, + 0x5c, 0x05, 0x5a, 0x72, 0x72, 0xb2, 0x91, 0xc7, 0x40, 0x1d, 0x61, 0xdb, 0x63, 0x64, 0x4e, 0xe0, 0x5f, 0x6a, 0xb3, + 0x16, 0x84, 0x67, 0x36, 0xb2, 0xe0, 0x0f, 0x74, 0x31, 0xd8, 0x30, 0xde, 0xc4, 0x3f, 0xa3, 0xec, 0xb9, 0x7b, 0xed, + 0x25, 0xab, 0xa0, 0x1e, 0x8e, 0xda, 0x09, 0x9d, 0xb6, 0xc9, 0xb7, 0x2d, 0x08, 0x84, 0xe4, 0xe3, 0xa5, 0x88, 0xee, + 0x84, 0x59, 0xd2, 0xaa, 0x96, 0xd8, 0xf3, 0xe6, 0xa7, 0xf1, 0x9e, 0xd7, 0xfb, 0x82, 0x85, 0xa8, 0xb9, 0x37, 0x1b, + 0xd6, 0xf5, 0xc6, 0xf2, 0xee, 0xbd, 0x32, 0xb3, 0xe8, 0x6c, 0xcc, 0x65, 0x01, 0x93, 0xea, 0x9e, 0x40, 0x2f, 0x96, + 0x27, 0xfd, 0xb1, 0xcd, 0x54, 0xe3, 0x58, 0x24, 0xf3, 0x28, 0x4e, 0x09, 0x6f, 0x0c, 0x68, 0xf4, 0x6b, 0x8a, 0x24, + 0x91, 0x79, 0x06, 0x8b, 0xcc, 0x58, 0x79, 0x1b, 0x7c, 0x43, 0xcc, 0x4c, 0x44, 0x34, 0xc8, 0x4e, 0x60, 0x8e, 0xc6, + 0x02, 0xe1, 0x0f, 0x71, 0x86, 0x26, 0xbe, 0xa3, 0x9b, 0x97, 0x9c, 0x4c, 0x5d, 0x80, 0x0b, 0x70, 0xbb, 0x7a, 0x06, + 0xfd, 0x70, 0xb3, 0x55, 0x84, 0x94, 0x92, 0x0a, 0x5c, 0x74, 0xac, 0x35, 0xf9, 0x3b, 0xa5, 0x98, 0x68, 0xdd, 0x88, + 0xea, 0x4b, 0x07, 0x60, 0xdf, 0x1d, 0xd4, 0xe7, 0x96, 0x34, 0x56, 0x92, 0xcf, 0x83, 0x2e, 0x35, 0x7d, 0x10, 0x2b, + 0xe4, 0x19, 0x9f, 0x1c, 0x81, 0x70, 0x87, 0xdf, 0x5d, 0xda, 0x4c, 0xd0, 0xdb, 0x44, 0x1b, 0x97, 0x0c, 0xf0, 0x8b, + 0x1c, 0x23, 0xec, 0x62, 0x86, 0x9c, 0xad, 0x19, 0xbf, 0x4c, 0x8e, 0x8c, 0x17, 0x84, 0x3f, 0x15, 0x9e, 0x97, 0x76, + 0xd3, 0x04, 0xc4, 0x3f, 0x10, 0x5d, 0x34, 0x18, 0x9d, 0x04, 0xf3, 0xcc, 0xcb, 0x65, 0x71, 0x51, 0x55, 0xd0, 0x60, + 0x9f, 0xbb, 0x5e, 0xc9, 0x96, 0x6f, 0xcf, 0xff, 0x71, 0x6e, 0x75, 0x53, 0xe2, 0xc8, 0x43, 0x57, 0xe2, 0xaa, 0x97, + 0x7b, 0x7e, 0xd2, 0xbd, 0xd5, 0x4e, 0xb8, 0xdf, 0xc8, 0x55, 0x5f, 0x21, 0x84, 0x7f, 0xf2, 0x07, 0x0d, 0xc1, 0xca, + 0x23, 0x58, 0xb3, 0x94, 0x72, 0xc7, 0xd5, 0x72, 0xdb, 0x0f, 0xf6, 0x3e, 0x60, 0xa5, 0x73, 0x17, 0x16, 0xe3, 0x09, + 0x12, 0x94, 0x17, 0xca, 0xd7, 0x62, 0x8c, 0xb3, 0xdd, 0xac, 0xc6, 0xa1, 0x15, 0xc4, 0x63, 0xcf, 0x72, 0xb8, 0xa8, + 0x43, 0x84, 0x2e, 0x1d, 0x5c, 0x5e, 0xc9, 0xe2, 0x81, 0xa3, 0x4c, 0xd3, 0x18, 0xcf, 0x56, 0x20, 0x39, 0x79, 0xfa, + 0xf0, 0x40, 0x8f, 0x90, 0x80, 0xd1, 0xe7, 0xce, 0x5b, 0x4a, 0x86, 0x6d, 0xd5, 0xb7, 0x09, 0xa0, 0xcd, 0x17, 0x34, + 0x87, 0x68, 0xc5, 0xc8, 0x34, 0x78, 0xed, 0x5d, 0x6c, 0xb5, 0x92, 0x39, 0x09, 0xad, 0x46, 0xac, 0x41, 0x52, 0xbf, + 0xd3, 0xa4, 0x0f, 0xe6, 0x67, 0xb9, 0x85, 0xda, 0xc9, 0x58, 0xed, 0x84, 0x33, 0x3b, 0x9d, 0xf3, 0x2d, 0xfb, 0xf5, + 0x8c, 0xe9, 0x3c, 0x47, 0x36, 0x5f, 0x7a, 0xcd, 0xd7, 0x9f, 0x87, 0xfc, 0xd3, 0x53, 0x79, 0x9b, 0xb0, 0x80, 0xfd, + 0x36, 0x35, 0xa8, 0x27, 0xd6, 0xed, 0x92, 0x6a, 0x29, 0x9a, 0x63, 0x71, 0x44, 0x11, 0xb1, 0x5d, 0xc0, 0x11, 0x7a, + 0x1f, 0xf1, 0x6b, 0x56, 0x67, 0xa2, 0xe4, 0x3c, 0x83, 0x77, 0x0a, 0x63, 0x25, 0x92, 0xbc, 0x22, 0x8d, 0x4c, 0xa4, + 0x75, 0x43, 0xde, 0x26, 0x79, 0xa9, 0xc9, 0xe9, 0xe8, 0x74, 0xec, 0x3d, 0xfe, 0x67, 0x40, 0x25, 0x21, 0x50, 0x81, + 0xd2, 0x3e, 0xdf, 0x1d, 0x31, 0x44, 0x93, 0x29, 0x4a, 0x91, 0xac, 0xa5, 0xe8, 0x2f, 0x31, 0x2b, 0x4d, 0x59, 0xdd, + 0x9d, 0x80, 0xeb, 0x36, 0x4e, 0x12, 0x77, 0x1b, 0x33, 0x99, 0x87, 0x13, 0xd8, 0x9f, 0xcb, 0x75, 0x7e, 0x88, 0xc1, + 0x96, 0x87, 0xa7, 0x25, 0x82, 0x5f, 0x47, 0x15, 0xbc, 0x1e, 0x44, 0x10, 0x1c, 0x67, 0x23, 0x22, 0xf6, 0x9b, 0x21, + 0x7b, 0x27, 0x2f, 0x00, 0x28, 0xce, 0xef, 0xe3, 0xe6, 0x79, 0x9d, 0x9f, 0x00, 0x45, 0x38, 0x2a, 0xfc, 0xb0, 0x33, + 0x82, 0x41, 0x15, 0xde, 0xc9, 0x22, 0x6b, 0xcc, 0x8e, 0x97, 0x2b, 0x9a, 0x73, 0x32, 0xb3, 0x55, 0x4f, 0x48, 0x22, + 0x48, 0x33, 0xcc, 0x7a, 0x10, 0x8c, 0x18, 0xbf, 0xac, 0x27, 0x83, 0xd1, 0x59, 0x92, 0x2c, 0x6c, 0x1a, 0x4e, 0xa4, + 0x6d, 0x84, 0x18, 0xc9, 0x76, 0x29, 0xc5, 0xa4, 0x6b, 0xcf, 0x36, 0x67, 0xcd, 0x17, 0x42, 0x51, 0xc0, 0x6e, 0x29, + 0x81, 0x18, 0xe7, 0x50, 0x42, 0xc3, 0x68, 0xca, 0x9f, 0x8b, 0x13, 0xc4, 0x3a, 0xf2, 0xd2, 0x54, 0x68, 0xb3, 0xc1, + 0x9d, 0x0f, 0x48, 0x11, 0xc6, 0xfd, 0x19, 0x38, 0x66, 0xb2, 0x52, 0x5c, 0x32, 0x87, 0xb7, 0x3b, 0x52, 0xac, 0x63, + 0xf6, 0x82, 0x60, 0xf0, 0x1c, 0x5b, 0x98, 0x58, 0xa4, 0xa2, 0x8f, 0x24, 0x15, 0x5c, 0x96, 0xea, 0xfe, 0x3d, 0x6c, + 0xbb, 0x6d, 0x0a, 0x62, 0x9b, 0x93, 0x30, 0x53, 0x8d, 0xc7, 0xd5, 0xa3, 0x0d, 0xb8, 0xfe, 0x1c, 0xa0, 0x91, 0x26, + 0xab, 0x74, 0x65, 0x7d, 0x73, 0xbf, 0xa9, 0xc7, 0x8a, 0x79, 0x7c, 0xf0, 0x89, 0x80, 0x35, 0xee, 0x80, 0x29, 0x6b, + 0x30, 0x24, 0x1c, 0x8a, 0xb0, 0xd9, 0x01, 0x98, 0x62, 0xfd, 0x28, 0x22, 0x71, 0xef, 0xa2, 0x4d, 0x02, 0x32, 0x2d, + 0xd7, 0x39, 0x37, 0x4b, 0xfd, 0xce, 0x24, 0xfc, 0x24, 0x86, 0x30, 0xc6, 0x21, 0x8e, 0x10, 0x8d, 0x25, 0xea, 0xf5, + 0x6b, 0x3c, 0xf6, 0xd2, 0x92, 0xff, 0xc9, 0xc6, 0xf9, 0x9d, 0x12, 0x9a, 0x63, 0xcb, 0xa6, 0xcd, 0x16, 0x74, 0xfb, + 0x5a, 0xd2, 0x52, 0xec, 0x2a, 0x8a, 0x4f, 0x1e, 0xf9, 0x41, 0x65, 0x78, 0x7f, 0x77, 0x49, 0xac, 0x07, 0xad, 0x24, + 0xb8, 0x35, 0x23, 0xbc, 0xbf, 0x4b, 0x27, 0xfc, 0x70, 0x10, 0xf1, 0x6e, 0x91, 0xd1, 0xb6, 0x98, 0x9a, 0x6d, 0x60, + 0x71, 0xe9, 0x43, 0x05, 0xb0, 0x8b, 0x0c, 0xeb, 0xf4, 0x1a, 0x77, 0xbb, 0xd2, 0xec, 0x1e, 0x21, 0x3c, 0x49, 0x95, + 0x9d, 0x6b, 0xb3, 0x98, 0xcb, 0x02, 0x3a, 0x49, 0xa5, 0x22, 0x9a, 0x49, 0xe3, 0xd0, 0x52, 0xe1, 0xdf, 0x05, 0x49, + 0x6a, 0x63, 0xdc, 0xfd, 0xd9, 0x19, 0x46, 0x54, 0x41, 0x4d, 0x49, 0x49, 0x1d, 0xc6, 0x64, 0xc7, 0x20, 0xfe, 0xb7, + 0xc7, 0x1e, 0x52, 0xaf, 0x59, 0x68, 0x99, 0x51, 0x1e, 0x7f, 0x37, 0x4c, 0x3b, 0x59, 0xe3, 0x91, 0xd7, 0xf5, 0x4e, + 0xd1, 0xd6, 0xb7, 0x70, 0xb6, 0xa1, 0x1b, 0xde, 0x74, 0xf5, 0x0c, 0xe3, 0xf1, 0x15, 0xfc, 0xbc, 0x81, 0x49, 0x4f, + 0xa4, 0x26, 0xee, 0x7c, 0x53, 0x72, 0x62, 0xab, 0x9e, 0x2a, 0xb0, 0x14, 0x4f, 0xc4, 0x6a, 0x57, 0x51, 0x32, 0xb5, + 0x51, 0x83, 0xe1, 0x8c, 0x35, 0xf4, 0xc9, 0xa9, 0xe1, 0x9c, 0x67, 0x80, 0x87, 0x97, 0xae, 0x4f, 0x21, 0x53, 0x3f, + 0x8d, 0x71, 0x29, 0x20, 0x4e, 0xc4, 0xb3, 0x0b, 0x2f, 0x31, 0xbe, 0x71, 0x7d, 0x0a, 0xf6, 0xd6, 0xa4, 0xab, 0x78, + 0x6a, 0x58, 0x85, 0x53, 0x9b, 0xab, 0xe1, 0xd4, 0xd6, 0x59, 0x0f, 0xfb, 0xb7, 0x14, 0xb9, 0x12, 0x50, 0x94, 0x1c, + 0x65, 0x2a, 0xae, 0x5c, 0x1b, 0xc6, 0xed, 0xb5, 0xf3, 0xc7, 0x54, 0x5d, 0x62, 0x28, 0x29, 0x51, 0xda, 0x3c, 0xb1, + 0x2d, 0x30, 0x92, 0x75, 0x13, 0xdc, 0xd2, 0x6b, 0xb9, 0xb4, 0xfb, 0xe2, 0x0e, 0x49, 0xa1, 0x96, 0xb4, 0xf6, 0x3c, + 0x89, 0x3e, 0xd6, 0xdc, 0xd2, 0xc6, 0x43, 0x62, 0xef, 0xf4, 0x58, 0x45, 0xfa, 0xf9, 0x52, 0x1d, 0x6a, 0x77, 0x20, + 0xe0, 0x32, 0x6d, 0x20, 0xbf, 0x6c, 0x0b, 0x44, 0xf6, 0x7c, 0x45, 0xb2, 0xf1, 0x87, 0x0a, 0x38, 0x1d, 0x38, 0xc5, + 0x04, 0x60, 0x65, 0x2a, 0x94, 0x4e, 0x12, 0x58, 0x16, 0x1f, 0xa1, 0x6a, 0x31, 0x37, 0x2d, 0xae, 0x0f, 0x8c, 0x78, + 0x7e, 0x9b, 0x10, 0x0f, 0x00, 0x71, 0x3d, 0x43, 0xd4, 0x15, 0x88, 0xfa, 0xcc, 0x8c, 0x81, 0x84, 0x1e, 0xb2, 0xef, + 0x0f, 0x98, 0xb9, 0x63, 0x3a, 0xf1, 0x52, 0xa5, 0xdc, 0x46, 0xcb, 0xc7, 0x72, 0x58, 0xa5, 0x99, 0x26, 0xc5, 0x35, + 0x09, 0x55, 0xf2, 0x8a, 0x06, 0x56, 0xb9, 0x6c, 0xf7, 0x5f, 0x7d, 0xe0, 0x35, 0x6c, 0x73, 0x3e, 0x5e, 0x3c, 0xc6, + 0xb7, 0x02, 0x45, 0xa3, 0x8a, 0xd9, 0x2a, 0x37, 0x18, 0x13, 0xd3, 0x8b, 0x03, 0xb1, 0xd4, 0xac, 0xe9, 0xce, 0x3c, + 0x87, 0xf6, 0x4d, 0xf1, 0xa0, 0x4c, 0xa5, 0x0a, 0x54, 0x70, 0x8d, 0x30, 0x56, 0x59, 0xb3, 0xa8, 0x4b, 0xc4, 0xfb, + 0xed, 0xd0, 0xbc, 0x94, 0x25, 0xa6, 0x88, 0x1d, 0x54, 0xd4, 0x19, 0x3e, 0xe7, 0xe1, 0xd6, 0xde, 0x7d, 0x76, 0x64, + 0x43, 0xc5, 0xc4, 0x94, 0x84, 0xf4, 0x64, 0x63, 0x4a, 0x92, 0x45, 0xe3, 0x99, 0xba, 0xa9, 0xbe, 0x86, 0xf1, 0x08, + 0x07, 0x6b, 0x3f, 0x66, 0x37, 0x40, 0x15, 0xd2, 0xe6, 0xa6, 0xda, 0xcc, 0xc1, 0x67, 0xb5, 0xe5, 0xdf, 0x96, 0x9e, + 0xde, 0x96, 0x2e, 0x7c, 0xd1, 0x2d, 0xe9, 0xe0, 0xd7, 0xf8, 0xd7, 0xa6, 0x09, 0x3f, 0xdd, 0x0c, 0x90, 0x9e, 0xef, + 0x72, 0x81, 0x28, 0x71, 0xad, 0x19, 0x03, 0xc5, 0x1b, 0xa4, 0x89, 0xa6, 0xc0, 0x1c, 0x8c, 0x76, 0xe0, 0x1f, 0x04, + 0x35, 0xa0, 0x12, 0x7a, 0x73, 0x45, 0x59, 0x5c, 0x7b, 0x9e, 0x0d, 0xfd, 0x18, 0x3a, 0x91, 0xbc, 0xfb, 0xa5, 0xd1, + 0x18, 0x05, 0xed, 0x7e, 0x89, 0x65, 0x02, 0x8e, 0xec, 0xa2, 0x95, 0x05, 0x33, 0x01, 0x6b, 0x81, 0x1d, 0x9a, 0x47, + 0x17, 0x7c, 0xbb, 0x2e, 0x19, 0x30, 0xa4, 0xcc, 0x5a, 0xfb, 0x74, 0xd5, 0xd1, 0xf8, 0x5a, 0x43, 0xb1, 0xd2, 0xb8, + 0x00, 0x86, 0x44, 0x15, 0x75, 0x3c, 0x59, 0x17, 0x1d, 0x30, 0x36, 0x97, 0x7c, 0x33, 0x44, 0x64, 0xce, 0x63, 0x83, + 0x41, 0x4c, 0x58, 0x3b, 0x56, 0x7f, 0xbe, 0xd0, 0x72, 0xa0, 0x69, 0x3e, 0x1f, 0x48, 0x94, 0xb6, 0x73, 0x08, 0x6d, + 0x27, 0x4a, 0xd7, 0x8d, 0x68, 0x0e, 0x84, 0x7b, 0xbf, 0x88, 0xc6, 0x19, 0x36, 0xde, 0xb9, 0x2c, 0xae, 0xaf, 0xba, + 0xba, 0x1f, 0x55, 0x23, 0x1e, 0x06, 0x5c, 0xbb, 0x85, 0x48, 0x9a, 0xf5, 0x77, 0xd4, 0x5b, 0x65, 0x94, 0x3e, 0x1d, + 0xef, 0x96, 0xbc, 0x6c, 0xed, 0x97, 0xfd, 0x9f, 0xcc, 0x3c, 0xe4, 0xf7, 0x85, 0x29, 0x54, 0x1f, 0x0d, 0x3d, 0xa2, + 0x6e, 0x1c, 0xe0, 0x7c, 0x6b, 0x13, 0x32, 0xb4, 0x60, 0x11, 0x19, 0x8f, 0xc0, 0xdc, 0x94, 0xa3, 0xbb, 0xde, 0x57, + 0x6c, 0xf8, 0x66, 0xc9, 0xbe, 0xd0, 0x95, 0x68, 0x5a, 0x47, 0xb8, 0x8b, 0x56, 0x92, 0x38, 0xa3, 0x91, 0x0e, 0x9d, + 0x51, 0xfd, 0x12, 0x3d, 0xef, 0x52, 0x60, 0x6b, 0xb9, 0xda, 0xf9, 0x9d, 0x95, 0x7c, 0x08, 0xa7, 0x63, 0x5c, 0x9b, + 0x0b, 0x48, 0xe3, 0x32, 0x71, 0x72, 0x58, 0x00, 0xcb, 0xde, 0xde, 0x2b, 0xe9, 0x70, 0x40, 0x6a, 0x3c, 0x16, 0xb3, + 0x43, 0x8a, 0x70, 0x03, 0x3a, 0x87, 0x06, 0x4b, 0x54, 0x09, 0xc7, 0x45, 0xec, 0xfa, 0xa6, 0xe2, 0x95, 0xab, 0xa0, + 0x0c, 0xca, 0x84, 0x75, 0x5b, 0xfe, 0x6d, 0xc9, 0xe7, 0xbe, 0x0d, 0x42, 0xce, 0x85, 0x0c, 0xee, 0x55, 0x09, 0x14, + 0x9b, 0x37, 0x82, 0xd8, 0x1a, 0xd3, 0x3d, 0xb0, 0x52, 0x9d, 0xb2, 0x58, 0x4f, 0x6c, 0xb6, 0x05, 0xf5, 0xa4, 0x61, + 0xe6, 0xf6, 0x1c, 0x41, 0x74, 0x07, 0xa1, 0x8f, 0xf7, 0xae, 0x8f, 0x52, 0x5e, 0xf9, 0xe5, 0xf9, 0x3e, 0x64, 0x85, + 0x62, 0x63, 0x0b, 0x3d, 0xa9, 0xf3, 0x70, 0x93, 0x07, 0x2d, 0xa2, 0x48, 0xf5, 0x5a, 0xac, 0x58, 0x01, 0x3b, 0xa2, + 0x0c, 0xff, 0x1e, 0x5c, 0x60, 0x1b, 0x58, 0x87, 0x4b, 0x00, 0x73, 0x37, 0xc6, 0xed, 0xd4, 0x53, 0xe5, 0x27, 0x1a, + 0x3f, 0x23, 0x82, 0x8b, 0x30, 0x45, 0x24, 0xb4, 0x4f, 0x15, 0x5f, 0xd1, 0x81, 0xc7, 0xb2, 0x7c, 0x6a, 0xc6, 0x9b, + 0x7c, 0xa9, 0x58, 0xaf, 0xfc, 0xf2, 0x90, 0xbd, 0xd0, 0xf8, 0x79, 0xd2, 0x12, 0xe2, 0xf2, 0x25, 0x82, 0x55, 0x25, + 0x5f, 0x8d, 0xd0, 0x47, 0xde, 0xc3, 0x97, 0x1b, 0x76, 0xd0, 0xf9, 0x80, 0x4a, 0xa6, 0x71, 0x81, 0x6f, 0x38, 0x2f, + 0xcd, 0xaa, 0x09, 0x33, 0x44, 0xf8, 0xc4, 0x69, 0x03, 0xc7, 0x57, 0xbe, 0x34, 0x74, 0x29, 0x3e, 0x15, 0x00, 0x7b, + 0x92, 0x74, 0x0e, 0x65, 0x32, 0xc7, 0x52, 0x24, 0x0e, 0x26, 0x95, 0xd9, 0x13, 0x48, 0x30, 0x5b, 0xac, 0xd2, 0x55, + 0xe7, 0x56, 0x8c, 0x6b, 0x32, 0x01, 0x30, 0xc6, 0x39, 0xd0, 0x9c, 0x99, 0xad, 0xd8, 0x21, 0x73, 0x62, 0x45, 0x05, + 0xf6, 0x7f, 0x8c, 0xbd, 0xc2, 0xdd, 0x67, 0xa6, 0x1f, 0xb3, 0x31, 0xdf, 0xf4, 0x3a, 0x34, 0x9b, 0xdc, 0x70, 0x79, + 0xb7, 0x5e, 0xcc, 0x89, 0x30, 0x5b, 0x40, 0x79, 0x1a, 0xd9, 0x48, 0x74, 0xd4, 0x40, 0xea, 0x1a, 0x48, 0x76, 0xf6, + 0xcd, 0x65, 0x6f, 0xf5, 0x59, 0x01, 0x31, 0xd1, 0xcd, 0x0c, 0xd4, 0xed, 0x2f, 0xf8, 0xb6, 0x3a, 0x15, 0x4c, 0x10, + 0xc0, 0x63, 0xd7, 0x86, 0x73, 0x21, 0x0b, 0xd5, 0xe9, 0xf6, 0xd3, 0x0e, 0x29, 0xfb, 0x59, 0x67, 0x52, 0xfe, 0x42, + 0x5b, 0x84, 0x11, 0x45, 0xa8, 0xae, 0x43, 0xcc, 0xb6, 0xa5, 0x1f, 0x84, 0x13, 0x70, 0xdc, 0x85, 0xd2, 0xf1, 0x01, + 0x5f, 0x52, 0x81, 0x08, 0xb9, 0x16, 0xe2, 0x6e, 0xd3, 0xd0, 0xb2, 0x82, 0xb7, 0xcd, 0x86, 0xd4, 0x4d, 0x3a, 0x7a, + 0x03, 0xaf, 0xe8, 0x66, 0xdd, 0xcb, 0xf4, 0x00, 0x64, 0x3c, 0x9a, 0x89, 0x81, 0x33, 0x6e, 0xdf, 0xde, 0x76, 0x2e, + 0x4d, 0x98, 0x17, 0x9d, 0x6c, 0x06, 0xaf, 0xe6, 0xc6, 0x9d, 0xb5, 0x0b, 0x67, 0xe3, 0xc3, 0x86, 0x66, 0x9b, 0xc7, + 0x1b, 0x6d, 0x1f, 0x66, 0xd7, 0xb3, 0xae, 0x5e, 0x96, 0x79, 0x99, 0x3e, 0xeb, 0xbb, 0x93, 0x5b, 0x35, 0x7f, 0x86, + 0x68, 0xb0, 0x19, 0xc8, 0x4c, 0x31, 0x49, 0xc2, 0x00, 0x30, 0x5a, 0x70, 0x7b, 0x13, 0xcd, 0xa0, 0x0b, 0x18, 0x28, + 0x4b, 0x93, 0xee, 0xe6, 0x8a, 0xe3, 0x97, 0x79, 0xaf, 0x54, 0xed, 0x85, 0x1b, 0x24, 0x0a, 0x4e, 0x83, 0xfd, 0x27, + 0x7e, 0xf7, 0x1f, 0x45, 0xdc, 0xcc, 0xf0, 0x95, 0x04, 0xa0, 0xb5, 0x60, 0xe1, 0x71, 0x62, 0x8b, 0xcd, 0xb2, 0x06, + 0x92, 0x52, 0x8b, 0xca, 0x7f, 0xd0, 0xf8, 0x51, 0x41, 0x5e, 0x9d, 0x6e, 0x0e, 0x31, 0xe0, 0x18, 0x8d, 0xda, 0x32, + 0xfd, 0xb8, 0x29, 0xc9, 0x70, 0x8a, 0x36, 0xb9, 0x8c, 0x68, 0x3e, 0x21, 0x1b, 0x0e, 0x01, 0x00, 0x4a, 0x95, 0x61, + 0x8d, 0xa4, 0x57, 0x93, 0xc4, 0xad, 0x0c, 0x47, 0x18, 0xa9, 0x02, 0xa3, 0x6f, 0xd6, 0x98, 0x5a, 0x08, 0xb5, 0x38, + 0x12, 0xc6, 0x76, 0x06, 0x29, 0xc7, 0xc0, 0x1c, 0xc4, 0x15, 0xf0, 0xec, 0xe4, 0x93, 0xda, 0x93, 0x96, 0x25, 0x14, + 0xfb, 0x4e, 0xc9, 0xd9, 0x6b, 0x3a, 0x28, 0x60, 0xd4, 0x75, 0xde, 0x86, 0xd3, 0x3c, 0x23, 0x4c, 0xf9, 0xd2, 0x8f, + 0xfe, 0x60, 0xdb, 0x03, 0xcf, 0x10, 0xaa, 0x02, 0xe1, 0xe3, 0x5c, 0x4d, 0x45, 0x54, 0xaa, 0x9c, 0x8b, 0xb4, 0xfd, + 0xf1, 0x88, 0x24, 0xdb, 0xc4, 0x7f, 0x40, 0x2c, 0xa5, 0x40, 0xf1, 0xf7, 0x9d, 0x13, 0x4d, 0x96, 0x98, 0x25, 0xf9, + 0x52, 0x9d, 0x26, 0x79, 0xf3, 0x35, 0x9c, 0x63, 0x35, 0x15, 0xff, 0x19, 0xa2, 0xa0, 0x69, 0x20, 0x84, 0xd6, 0x5b, + 0x9a, 0x6d, 0x40, 0xe9, 0xd6, 0x99, 0x6d, 0xe1, 0x9c, 0x07, 0x3c, 0x03, 0xb8, 0x98, 0x6d, 0xc6, 0x5d, 0x2a, 0x8d, + 0xa8, 0xf5, 0xca, 0x40, 0xba, 0x9d, 0x02, 0x0e, 0x51, 0x5b, 0x1f, 0xcc, 0x0e, 0x45, 0xef, 0x82, 0x17, 0x4c, 0x7e, + 0x06, 0x1f, 0x0a, 0x2a, 0xb5, 0xa0, 0xdb, 0x8b, 0xd9, 0x97, 0xd4, 0xa8, 0xca, 0x4b, 0xb3, 0xa1, 0xb6, 0xce, 0x5f, + 0x6b, 0x31, 0xe5, 0x2e, 0x00, 0x9d, 0xd0, 0x86, 0xad, 0x43, 0x06, 0x9e, 0xac, 0xe9, 0x53, 0x6e, 0x9a, 0x71, 0xc9, + 0xbe, 0x28, 0xc3, 0xdc, 0x8f, 0x88, 0xcd, 0xd8, 0xf7, 0xbe, 0x49, 0xad, 0xf9, 0x39, 0x87, 0xa7, 0xd6, 0xd5, 0x5a, + 0xc1, 0xd8, 0x3a, 0x7d, 0xd9, 0x38, 0x8a, 0x57, 0xf5, 0x4f, 0x80, 0x77, 0xf1, 0x79, 0xcd, 0xc8, 0xf4, 0xb5, 0x38, + 0x34, 0x22, 0x14, 0xb9, 0xde, 0x30, 0x04, 0x66, 0x22, 0x0c, 0xaf, 0xbb, 0x0b, 0xc1, 0xf4, 0xba, 0x52, 0x90, 0xe0, + 0xe0, 0xc6, 0x52, 0xec, 0x37, 0x7a, 0x7e, 0x65, 0xff, 0x50, 0x44, 0x43, 0x33, 0x15, 0xc0, 0x67, 0x33, 0x09, 0xd1, + 0x8f, 0x33, 0xb3, 0xe1, 0xc9, 0x83, 0xed, 0x6d, 0x44, 0x6d, 0x22, 0x81, 0x49, 0xe2, 0x32, 0x24, 0x51, 0xde, 0x25, + 0x5a, 0x90, 0xba, 0x84, 0xeb, 0x4f, 0x23, 0xf3, 0x4d, 0xa9, 0xca, 0x7c, 0x45, 0xe2, 0x5b, 0xd3, 0xb8, 0x7f, 0x08, + 0xa7, 0x79, 0x7d, 0x75, 0xfb, 0xbc, 0x65, 0xdd, 0x97, 0x7b, 0xb0, 0x95, 0x85, 0xff, 0x42, 0xdb, 0x98, 0xba, 0x6a, + 0x9d, 0x2e, 0x27, 0x62, 0xfc, 0x25, 0xea, 0x65, 0xec, 0x60, 0xbc, 0xed, 0x37, 0xb8, 0xd5, 0x08, 0x53, 0x7b, 0xf3, + 0x6b, 0x8e, 0x4c, 0x3d, 0x48, 0xdd, 0x00, 0x0d, 0x2b, 0x76, 0xa9, 0xca, 0x52, 0x5b, 0xfe, 0xd9, 0xad, 0xe7, 0x3b, + 0x19, 0x8e, 0x0e, 0x9f, 0x43, 0x1a, 0xf3, 0x5d, 0x6f, 0xbe, 0x79, 0xcd, 0xa4, 0x67, 0x9d, 0x46, 0x11, 0xdd, 0x8a, + 0x61, 0x3b, 0x46, 0x87, 0x43, 0x52, 0xb8, 0x2b, 0x49, 0x35, 0xc1, 0x3e, 0x51, 0x54, 0x8e, 0x06, 0x42, 0x18, 0x30, + 0xb1, 0x27, 0x61, 0xbb, 0x2f, 0x14, 0x70, 0xda, 0xd0, 0xbd, 0xab, 0x0e, 0x54, 0x42, 0x89, 0x8c, 0xbd, 0xac, 0xc6, + 0x37, 0xa5, 0x8a, 0x7c, 0x88, 0x57, 0xf0, 0xb0, 0xf4, 0x9a, 0x72, 0x97, 0x0c, 0x20, 0xf7, 0xea, 0xf4, 0xe6, 0x9f, + 0xb3, 0x7b, 0xee, 0xb3, 0x90, 0x6f, 0x7c, 0xed, 0xaf, 0x76, 0xdf, 0x5f, 0xe8, 0x60, 0x5e, 0xc1, 0x2a, 0xee, 0x5f, + 0xfe, 0x50, 0x29, 0x0a, 0x35, 0xea, 0x07, 0x79, 0x60, 0x7b, 0xe9, 0x71, 0x53, 0x16, 0xd6, 0x02, 0x13, 0x72, 0xe5, + 0xcd, 0x99, 0x06, 0xc2, 0x38, 0x8e, 0x7f, 0xcd, 0x29, 0xa4, 0x6c, 0xdc, 0x9c, 0x3c, 0xe3, 0xd1, 0x58, 0x11, 0xea, + 0x50, 0x97, 0x9b, 0x79, 0xd7, 0x71, 0x46, 0x8e, 0xbb, 0xa6, 0xe8, 0x8f, 0xe6, 0xe2, 0x5f, 0xcd, 0x3e, 0x43, 0xf8, + 0x15, 0x70, 0x3a, 0xe0, 0x3a, 0x65, 0xc6, 0x2e, 0x18, 0xed, 0x2e, 0x49, 0xc3, 0xc3, 0xc7, 0x76, 0xb0, 0xb5, 0xff, + 0xf1, 0xda, 0x83, 0x8a, 0x08, 0x21, 0x87, 0x9f, 0x1d, 0x3a, 0x39, 0xe8, 0xc3, 0xaa, 0x72, 0x7a, 0xd1, 0x17, 0x2c, + 0x2b, 0xd8, 0x42, 0x0d, 0x30, 0x25, 0xe8, 0x7e, 0x85, 0x96, 0x17, 0xbb, 0xa6, 0x7f, 0x78, 0xe6, 0xf3, 0x2c, 0xf2, + 0xc1, 0x02, 0x7e, 0x77, 0xa8, 0x92, 0x47, 0x6d, 0x2c, 0x5f, 0x68, 0xc9, 0xb7, 0x86, 0x14, 0x18, 0x55, 0x90, 0x36, + 0xc4, 0xc3, 0x51, 0x75, 0x39, 0x17, 0x5c, 0xa0, 0xfa, 0xd1, 0xa3, 0xb8, 0x4c, 0x51, 0x00, 0x58, 0xae, 0xb4, 0x40, + 0x38, 0x1f, 0x20, 0x42, 0xa1, 0x61, 0x35, 0x09, 0x99, 0x7e, 0x9e, 0xed, 0xa6, 0x06, 0xa1, 0xf1, 0xbe, 0xb4, 0xf6, + 0x23, 0xca, 0xc8, 0x9c, 0xa2, 0x29, 0x5d, 0xa5, 0xb6, 0x19, 0xf2, 0xc0, 0xb7, 0xb4, 0x2c, 0x00, 0x46, 0x4b, 0x24, + 0x1f, 0x36, 0x16, 0x91, 0xb5, 0xaf, 0xe7, 0x84, 0xbb, 0xcc, 0x7e, 0xf4, 0x4d, 0xcd, 0x2f, 0xb6, 0x4d, 0x83, 0xf3, + 0x87, 0xc8, 0x75, 0xee, 0x06, 0xc9, 0xc6, 0x26, 0x5e, 0xb9, 0x8d, 0x6f, 0x47, 0xf4, 0x87, 0x76, 0x59, 0x7f, 0xcb, + 0x30, 0x01, 0x75, 0x26, 0x2d, 0xe1, 0x1a, 0x80, 0x72, 0x18, 0xc2, 0xd3, 0x38, 0x14, 0x2f, 0x97, 0x3c, 0x44, 0x13, + 0x8d, 0x04, 0x4a, 0x60, 0x85, 0x37, 0xec, 0xa2, 0xaa, 0x7e, 0x3d, 0xf0, 0xff, 0x1b, 0x68, 0xaa, 0xfa, 0x36, 0xb3, + 0xd4, 0x4d, 0x4b, 0x40, 0xdb, 0x86, 0x04, 0xab, 0xa0, 0xc2, 0x11, 0xb6, 0x96, 0xa4, 0x32, 0x18, 0xb6, 0x9e, 0x7c, + 0xd8, 0x10, 0xb1, 0x99, 0x8c, 0x33, 0xad, 0xdf, 0x0e, 0x33, 0xdb, 0x2f, 0x05, 0xde, 0x10, 0x8b, 0xc6, 0x5c, 0xd4, + 0xb8, 0xf6, 0x34, 0x42, 0x20, 0x13, 0xa4, 0xd1, 0x9d, 0xd1, 0xd6, 0xc5, 0xf8, 0xda, 0xba, 0x24, 0x9f, 0x91, 0x75, + 0x72, 0xba, 0xc3, 0x07, 0x03, 0x21, 0xee, 0xa3, 0x5c, 0x30, 0xa3, 0xd4, 0x56, 0xe2, 0x6a, 0x88, 0x65, 0xd1, 0x4e, + 0x64, 0x11, 0x00, 0x23, 0xc0, 0xfe, 0x60, 0x5e, 0x6b, 0xd2, 0xe4, 0x0d, 0xe1, 0xcb, 0xd5, 0x38, 0x1d, 0x6b, 0xfd, + 0x36, 0x2c, 0x9b, 0x0e, 0x4c, 0xe1, 0x7a, 0x58, 0x9d, 0xc6, 0xb3, 0xf7, 0x6a, 0x8b, 0xd1, 0x9f, 0xf7, 0xe8, 0x05, + 0xbc, 0x41, 0x90, 0xc1, 0xa9, 0x98, 0x6c, 0x69, 0x7c, 0xd8, 0x43, 0xbc, 0x90, 0xea, 0x7c, 0x10, 0xb4, 0x1d, 0xd5, + 0x1e, 0x50, 0xce, 0x5f, 0x0b, 0xd4, 0x7d, 0x24, 0x3c, 0x13, 0x20, 0x23, 0x05, 0xe5, 0x89, 0xd6, 0xa7, 0xe8, 0xa1, + 0x07, 0x3e, 0xe9, 0xea, 0x9a, 0xb5, 0xa0, 0x93, 0x20, 0xd1, 0x10, 0x27, 0x27, 0x31, 0xfa, 0xe6, 0xc5, 0x03, 0x08, + 0xd2, 0x72, 0x4d, 0x86, 0xd2, 0x42, 0x1b, 0xc5, 0x19, 0x9b, 0xc4, 0x14, 0xd6, 0xff, 0xdc, 0x4e, 0x73, 0xa4, 0xe1, + 0xe0, 0x12, 0x25, 0x6f, 0x35, 0x91, 0x42, 0x82, 0x75, 0x52, 0x27, 0xbd, 0x9f, 0xb0, 0x1b, 0xdc, 0xf5, 0x8e, 0x0f, + 0x25, 0x11, 0x82, 0x09, 0xa1, 0x90, 0x9f, 0x96, 0xe1, 0xfc, 0x51, 0xe0, 0x37, 0x35, 0x0a, 0xce, 0x78, 0x5c, 0xc9, + 0x86, 0xa0, 0xd0, 0xef, 0xd9, 0x83, 0x5d, 0x38, 0x41, 0xd8, 0x74, 0xf8, 0xd0, 0x95, 0xb2, 0x0c, 0x82, 0x94, 0xde, + 0xeb, 0xbc, 0x0d, 0x15, 0xc9, 0x04, 0xd4, 0x42, 0xbb, 0x1e, 0x67, 0x15, 0x76, 0x73, 0x84, 0x7e, 0x2b, 0x36, 0xf8, + 0xb2, 0xb3, 0x05, 0x04, 0xd7, 0xd0, 0xc2, 0xe0, 0xa2, 0x42, 0x66, 0xb7, 0x88, 0x9e, 0x60, 0x72, 0x16, 0xb9, 0xc3, + 0x97, 0xb4, 0x50, 0xb9, 0x64, 0x25, 0x3d, 0x97, 0x3e, 0xf8, 0x5d, 0x76, 0xb4, 0x8a, 0x1b, 0x67, 0x6d, 0x94, 0x6a, + 0x74, 0x8b, 0x99, 0xef, 0x1f, 0x31, 0xc7, 0x25, 0xb1, 0x51, 0x0b, 0x2e, 0x19, 0xba, 0x32, 0x65, 0x29, 0x0b, 0x1c, + 0x71, 0x20, 0x82, 0xba, 0xcd, 0x77, 0xc4, 0x2b, 0xaa, 0x3b, 0xd9, 0x6b, 0x83, 0x0d, 0x5a, 0x87, 0xac, 0x95, 0xc2, + 0x9b, 0xb4, 0x42, 0x17, 0xb1, 0x8a, 0x19, 0xb8, 0x1c, 0x6f, 0xbf, 0x34, 0x19, 0xa0, 0x9b, 0x23, 0x71, 0xe7, 0x74, + 0x06, 0x45, 0x66, 0x78, 0xd1, 0xbf, 0x92, 0x56, 0x69, 0x50, 0xd6, 0x5b, 0xc9, 0x61, 0xac, 0xa3, 0xf9, 0x61, 0xb8, + 0xbf, 0x8a, 0x5f, 0xd3, 0x1d, 0xe5, 0xbf, 0x55, 0x7f, 0x39, 0x50, 0x55, 0x5e, 0x68, 0x15, 0x87, 0x6a, 0x1b, 0x27, + 0x21, 0xa1, 0x9f, 0x6c, 0xdf, 0xb7, 0xef, 0xbf, 0x19, 0x71, 0x8d, 0x5b, 0xda, 0x38, 0xdc, 0x6b, 0x71, 0xd0, 0xa2, + 0xbc, 0xff, 0x0f, 0xa5, 0x99, 0x01, 0x6c, 0xd2, 0xa1, 0x19, 0x32, 0x57, 0x1e, 0x7d, 0xa5, 0x5f, 0x8d, 0x19, 0x09, + 0x33, 0x7b, 0xcd, 0x18, 0xe3, 0xb5, 0xef, 0xfe, 0x9e, 0xa2, 0x85, 0x45, 0x93, 0x3c, 0x39, 0x2f, 0x05, 0xe3, 0xaa, + 0x2e, 0x7e, 0x76, 0xc7, 0x93, 0xf0, 0x3f, 0xa8, 0xda, 0xbe, 0x3c, 0x08, 0x31, 0x77, 0x3d, 0x85, 0x68, 0x83, 0x59, + 0xf2, 0x29, 0x6f, 0x7a, 0xba, 0xc6, 0x92, 0xc6, 0x4f, 0x66, 0xe5, 0xba, 0x75, 0xcd, 0x4e, 0x02, 0x60, 0xdc, 0x1f, + 0x9b, 0x3f, 0x2c, 0x2a, 0xf4, 0xed, 0x66, 0x2a, 0x81, 0xaf, 0x0c, 0xb3, 0x79, 0x9f, 0x05, 0xe0, 0x6f, 0x70, 0x96, + 0xd3, 0x72, 0x9e, 0x5a, 0x52, 0x3c, 0xf5, 0x4b, 0x6c, 0xd5, 0xaf, 0x1c, 0xd9, 0x50, 0x1e, 0x7f, 0xdd, 0xb0, 0x12, + 0xa8, 0xb8, 0x1b, 0x98, 0x60, 0xfa, 0xf7, 0xc9, 0xc8, 0x71, 0x14, 0x36, 0xb6, 0x51, 0x40, 0x56, 0x1f, 0x6f, 0x7e, + 0x3f, 0xcb, 0x36, 0xfc, 0xe3, 0x71, 0xb2, 0x6e, 0x20, 0x50, 0x83, 0x45, 0xd6, 0xdd, 0xf5, 0x9e, 0x05, 0x48, 0x65, + 0x77, 0x2b, 0xea, 0x8b, 0xc3, 0xd0, 0x7f, 0xfc, 0xdc, 0x19, 0xd5, 0xbb, 0x70, 0x8e, 0x71, 0x84, 0xd4, 0x2f, 0x61, + 0x7f, 0xff, 0x64, 0xd2, 0x2f, 0xcf, 0x9c, 0xff, 0x24, 0xea, 0x17, 0xa9, 0x7a, 0x43, 0x17, 0x12, 0xc7, 0x3e, 0x6c, + 0x7e, 0x9a, 0x23, 0x0f, 0x76, 0x3e, 0xcf, 0x44, 0x6a, 0xac, 0xc7, 0x52, 0x1d, 0x57, 0xc9, 0xca, 0x0f, 0x3e, 0x5c, + 0x6a, 0x5f, 0x2c, 0x59, 0x5a, 0xed, 0x5e, 0xd1, 0xf7, 0x68, 0x6e, 0xa0, 0xf5, 0xd8, 0x07, 0xef, 0xa6, 0x4f, 0xb5, + 0xfb, 0x18, 0xdd, 0x3d, 0xbd, 0x92, 0x38, 0xdb, 0x2a, 0x4d, 0x6c, 0xe1, 0xb3, 0xa3, 0xd7, 0x89, 0xb4, 0x14, 0x5a, + 0x19, 0x61, 0x7a, 0xca, 0x1e, 0xc1, 0x12, 0x24, 0x4b, 0xab, 0xde, 0xb1, 0x6b, 0x2e, 0xd2, 0x98, 0xfe, 0xf4, 0xc4, + 0x4a, 0x8f, 0x7b, 0xcd, 0x6a, 0x7a, 0x98, 0x5f, 0x19, 0x33, 0xe3, 0x0c, 0x09, 0x9e, 0x42, 0x24, 0xa0, 0xb3, 0x05, + 0xe5, 0x13, 0x4d, 0x66, 0x25, 0xac, 0xbe, 0x3a, 0x53, 0x82, 0x30, 0x2b, 0x1b, 0x77, 0x29, 0x67, 0xda, 0xe8, 0x34, + 0xc7, 0x72, 0x5d, 0x3a, 0x8f, 0xcb, 0xd5, 0x71, 0x50, 0xff, 0xa6, 0x43, 0x18, 0xce, 0x36, 0x9c, 0x1f, 0xa9, 0x9e, + 0x18, 0x25, 0x5f, 0x90, 0x7f, 0x11, 0x2a, 0xd8, 0xa8, 0xbe, 0x79, 0x82, 0x0e, 0x64, 0x52, 0xef, 0x8f, 0xdf, 0xed, + 0x8f, 0xef, 0x61, 0x0c, 0xc3, 0x36, 0x68, 0x2b, 0x28, 0x55, 0x45, 0xb9, 0x14, 0x6d, 0x9c, 0x77, 0x3d, 0x2e, 0xbb, + 0xfc, 0xa6, 0x0f, 0x34, 0xfa, 0xe5, 0x79, 0xe7, 0x5a, 0x5a, 0x7a, 0x44, 0xa6, 0x5e, 0x24, 0x0a, 0x31, 0xd6, 0x52, + 0x78, 0xb3, 0x74, 0xa2, 0xe2, 0x80, 0xe1, 0xae, 0xc9, 0xc8, 0x33, 0x73, 0xc6, 0x6e, 0x25, 0xed, 0x08, 0x16, 0x86, + 0x75, 0xd3, 0xb5, 0x94, 0x64, 0x99, 0xf5, 0xe9, 0x5e, 0x9d, 0x08, 0x2b, 0x38, 0xbc, 0x11, 0xdb, 0x13, 0xd2, 0xfc, + 0x69, 0x22, 0x99, 0x93, 0xd7, 0xfb, 0x12, 0x30, 0x4b, 0x5c, 0x3a, 0x9b, 0x7c, 0x46, 0x9a, 0xe2, 0x5f, 0x07, 0x95, + 0xe9, 0x8b, 0x6f, 0xac, 0x26, 0xd4, 0xbe, 0x4a, 0x56, 0xa9, 0x38, 0xc7, 0x17, 0x14, 0x29, 0xf6, 0x8c, 0xf6, 0x4c, + 0x76, 0xe8, 0x46, 0x63, 0x6f, 0x73, 0x4f, 0x29, 0xa4, 0xcc, 0x62, 0xdf, 0x4b, 0xd0, 0xbf, 0x22, 0xcc, 0x30, 0x09, + 0x4a, 0xf0, 0xf2, 0x3f, 0xe0, 0xc6, 0x1c, 0x38, 0xa2, 0xde, 0x3b, 0x8f, 0x89, 0x45, 0x0b, 0x75, 0xe8, 0x86, 0x0c, + 0xab, 0x74, 0x22, 0x7e, 0xbd, 0x44, 0xd1, 0xb4, 0x0f, 0x6b, 0x84, 0x79, 0xe1, 0x2b, 0xed, 0x6f, 0x13, 0x01, 0x34, + 0x08, 0x4b, 0x43, 0x0c, 0xec, 0xea, 0x26, 0x6d, 0x61, 0xb8, 0xd5, 0x13, 0x68, 0x0a, 0x17, 0xaf, 0xe9, 0x78, 0xfa, + 0x5a, 0xa4, 0x13, 0x4a, 0x7a, 0x94, 0x8b, 0xc9, 0xb1, 0x16, 0xcb, 0x31, 0x7b, 0x2c, 0x7f, 0x27, 0xd7, 0xcb, 0xb3, + 0x08, 0x4d, 0x4f, 0x05, 0x16, 0x39, 0x08, 0x9c, 0x71, 0x69, 0xa5, 0x54, 0xef, 0x30, 0x78, 0x99, 0x99, 0x28, 0xfc, + 0x40, 0x5e, 0x06, 0x0b, 0xa5, 0x93, 0x1f, 0xb4, 0xea, 0xef, 0x3d, 0x45, 0x61, 0xf6, 0xf4, 0x10, 0x45, 0xc7, 0xa8, + 0xb3, 0xbb, 0x8e, 0x41, 0xf5, 0xa7, 0x35, 0xf5, 0x6b, 0xf8, 0x05, 0xa3, 0x0b, 0x24, 0x32, 0x73, 0x0c, 0x24, 0x8f, + 0xc0, 0x1f, 0xef, 0xb0, 0xc9, 0x7d, 0xe6, 0x6c, 0x87, 0xe4, 0xf1, 0xea, 0x6d, 0xc5, 0x01, 0x5d, 0x32, 0x56, 0x4b, + 0x1e, 0xa2, 0xf6, 0xaa, 0x96, 0xf5, 0xa7, 0xe5, 0x98, 0x77, 0x0b, 0xb7, 0xa3, 0xc7, 0x53, 0x1c, 0xb0, 0xbd, 0xdf, + 0x9d, 0x09, 0x8b, 0x43, 0x9c, 0x1f, 0x1b, 0xd5, 0xed, 0x18, 0x5d, 0x96, 0x01, 0x3e, 0xad, 0x0f, 0xb4, 0x41, 0x10, + 0xd7, 0x67, 0x07, 0xaa, 0x3b, 0xf7, 0x15, 0x2f, 0x4c, 0x8f, 0xd7, 0x24, 0x94, 0x96, 0xf2, 0x64, 0x6c, 0xc8, 0x3a, + 0x80, 0xa2, 0x51, 0xcc, 0x51, 0x10, 0xa2, 0x08, 0x10, 0x72, 0x48, 0x49, 0xf2, 0x6a, 0x0f, 0x40, 0x11, 0x6b, 0xa1, + 0x72, 0xd0, 0x1c, 0xf7, 0x7e, 0x10, 0xc4, 0x30, 0x63, 0xfa, 0x0f, 0xf1, 0x43, 0x78, 0xb6, 0xc3, 0x32, 0x96, 0x19, + 0xaf, 0x71, 0x95, 0xae, 0xcf, 0x81, 0x72, 0xe9, 0xe6, 0xad, 0xfa, 0x4d, 0x4f, 0x80, 0x69, 0x7d, 0x16, 0x84, 0x2d, + 0x22, 0x77, 0x09, 0x42, 0x64, 0xd7, 0x05, 0x7a, 0xf5, 0x40, 0xb6, 0x3b, 0xf4, 0x43, 0xaf, 0x20, 0x52, 0xfa, 0x5a, + 0x10, 0x7e, 0x45, 0x7e, 0x10, 0x16, 0x3c, 0xdf, 0x50, 0x94, 0x06, 0x88, 0x9e, 0x42, 0xad, 0x3b, 0x7d, 0xab, 0xe2, + 0x1c, 0x3b, 0xa8, 0xdb, 0xcc, 0xc2, 0xf6, 0xa7, 0x13, 0xf1, 0xb1, 0xac, 0x8b, 0x97, 0x74, 0xe9, 0xae, 0xde, 0xb7, + 0x0c, 0x7b, 0x00, 0xc4, 0x52, 0x85, 0x9d, 0xa1, 0x12, 0x81, 0xaf, 0xf3, 0x82, 0x87, 0x14, 0xbd, 0x4a, 0xb6, 0xf7, + 0xdd, 0xef, 0xbd, 0x42, 0x47, 0x7c, 0xd9, 0x16, 0x7d, 0xc2, 0x57, 0xd5, 0x24, 0x5e, 0x5f, 0xd9, 0x2b, 0xf7, 0xb6, + 0xea, 0xf9, 0xf3, 0x61, 0x14, 0x67, 0xf1, 0x8e, 0xa6, 0x4b, 0x8d, 0xde, 0x27, 0xab, 0xbf, 0x03, 0xb5, 0xa8, 0x7d, + 0x97, 0xe8, 0xf4, 0x72, 0xe4, 0x98, 0xf9, 0xa2, 0xa4, 0x69, 0xdd, 0xe1, 0x34, 0x7f, 0x95, 0x59, 0x8f, 0xaf, 0xf4, + 0x9c, 0x59, 0xcd, 0xf4, 0xc1, 0xcf, 0x54, 0xdb, 0x73, 0x19, 0x00, 0x5b, 0xc7, 0xa7, 0xcf, 0xc7, 0xbd, 0x0d, 0xab, + 0xd5, 0x17, 0xfd, 0x88, 0x75, 0xd1, 0x0d, 0x3d, 0xd7, 0x13, 0x84, 0xf4, 0x9c, 0xee, 0x1d, 0x58, 0xa5, 0x1f, 0x1b, + 0x29, 0xfa, 0x36, 0xc5, 0xbe, 0x67, 0x45, 0x2e, 0x48, 0xc7, 0xae, 0x7a, 0xc3, 0x6d, 0x16, 0xfa, 0x66, 0xda, 0x52, + 0x5f, 0xd4, 0xa8, 0x6d, 0x89, 0xcf, 0x67, 0xa9, 0x64, 0x22, 0xea, 0x17, 0x37, 0x5c, 0x59, 0xdf, 0x79, 0x07, 0xc9, + 0x6a, 0x95, 0xc0, 0x5d, 0x91, 0x5c, 0xe9, 0xd2, 0x7f, 0x1f, 0x46, 0xcf, 0x53, 0x0e, 0xab, 0xa5, 0x9c, 0xa6, 0xa7, + 0xa8, 0xec, 0x8d, 0x9d, 0x94, 0xf9, 0x49, 0xf2, 0xef, 0xfc, 0xf0, 0x64, 0xb1, 0x9b, 0x18, 0xf5, 0xf9, 0x88, 0xd7, + 0xf9, 0xfb, 0x2a, 0x63, 0x14, 0xc4, 0xd0, 0xee, 0xab, 0x9c, 0x26, 0x6d, 0x95, 0xf8, 0xd8, 0x7b, 0x45, 0xb1, 0xc9, + 0xf2, 0xe8, 0xa9, 0xc2, 0x24, 0xf8, 0x69, 0x44, 0xce, 0xfc, 0x5c, 0x4d, 0xc2, 0xc4, 0x78, 0xba, 0xb4, 0xfa, 0x1e, + 0x9e, 0xba, 0x0b, 0x67, 0xbd, 0xc7, 0x08, 0x69, 0x8c, 0xff, 0x39, 0x66, 0x58, 0xe2, 0xd5, 0x99, 0xe5, 0xdb, 0xe0, + 0xc6, 0x74, 0x58, 0x4a, 0x1a, 0xce, 0x71, 0x30, 0xa1, 0x1b, 0x8c, 0x7a, 0xab, 0x04, 0x35, 0x54, 0x84, 0x83, 0x02, + 0x22, 0xfb, 0x88, 0x66, 0x51, 0x56, 0x24, 0x40, 0x91, 0x69, 0xf1, 0xb7, 0x39, 0xb6, 0xc8, 0x0f, 0x2d, 0xf6, 0xcb, + 0xf2, 0xbd, 0xbe, 0x0a, 0xa2, 0xfe, 0x36, 0x01, 0x45, 0xa8, 0x0d, 0x59, 0x9b, 0x80, 0x29, 0x44, 0x31, 0x35, 0xc1, + 0xa7, 0x05, 0x45, 0xa1, 0x32, 0xf1, 0x2a, 0x6c, 0x0d, 0x16, 0x0e, 0xb5, 0xb4, 0xa8, 0x35, 0xe9, 0xbc, 0x05, 0xe4, + 0x68, 0xbf, 0x75, 0xf1, 0x5c, 0x76, 0x6a, 0x3c, 0x4c, 0xaa, 0x3d, 0x24, 0x22, 0xc1, 0x3c, 0xce, 0x46, 0xc0, 0x6e, + 0xf3, 0x29, 0xbe, 0x14, 0xd0, 0x64, 0x49, 0xdd, 0xc5, 0x6f, 0xba, 0xed, 0x04, 0x54, 0x46, 0x2b, 0x0d, 0x05, 0x09, + 0xdf, 0x1d, 0x8d, 0x07, 0xaa, 0x0a, 0xd9, 0x65, 0xbc, 0xc3, 0x25, 0x37, 0x22, 0xcc, 0x52, 0x74, 0x87, 0x5f, 0x92, + 0xfe, 0xdd, 0x51, 0x99, 0x93, 0x9d, 0xd6, 0xb4, 0x77, 0x1b, 0x06, 0x5f, 0xc4, 0xe8, 0xcc, 0x00, 0x47, 0xf6, 0x3a, + 0xc0, 0x06, 0xce, 0x63, 0x84, 0x09, 0x38, 0x5e, 0x54, 0x64, 0xb2, 0xce, 0x2f, 0xd9, 0xbd, 0xb8, 0xca, 0x1c, 0x1c, + 0x08, 0x51, 0x0b, 0x3f, 0xe0, 0x46, 0x0b, 0xc8, 0x70, 0x30, 0x4b, 0xe8, 0xb1, 0x50, 0x3c, 0x37, 0x00, 0xef, 0x95, + 0x36, 0x90, 0x80, 0xdc, 0xec, 0x49, 0x01, 0xc9, 0xfc, 0x85, 0x59, 0x03, 0xc2, 0x87, 0x64, 0x26, 0x73, 0x72, 0x06, + 0xa5, 0xc4, 0x1a, 0x00, 0x45, 0xc8, 0x2c, 0x00, 0x9f, 0x35, 0xef, 0x37, 0x6f, 0x5f, 0x4e, 0x15, 0x3b, 0x1d, 0x80, + 0x7f, 0x50, 0x8a, 0x4c, 0x6e, 0x46, 0x42, 0x19, 0x38, 0xbf, 0x00, 0x93, 0x0d, 0x58, 0xfd, 0x18, 0x86, 0xdf, 0xf5, + 0x0c, 0x23, 0x97, 0xd1, 0xc2, 0xea, 0x42, 0x52, 0x94, 0xee, 0xad, 0x0b, 0x91, 0x2a, 0x65, 0x33, 0x6a, 0x43, 0x86, + 0x2d, 0xf8, 0x3c, 0x55, 0x9f, 0x78, 0xad, 0x4c, 0x8e, 0x9a, 0x85, 0xcd, 0x3a, 0xb1, 0x85, 0x4c, 0x58, 0x9c, 0x26, + 0xe7, 0xe6, 0x2d, 0x4f, 0xb3, 0x88, 0x57, 0x2e, 0x49, 0x93, 0x96, 0x45, 0x85, 0xd8, 0xc6, 0x4c, 0x95, 0x0d, 0x7f, + 0x72, 0x9c, 0xc7, 0xb3, 0x01, 0x23, 0x7f, 0xb6, 0xa0, 0xeb, 0xed, 0x43, 0x2c, 0x12, 0x72, 0x56, 0x5b, 0xf3, 0xcd, + 0x2e, 0xb5, 0xcd, 0xbd, 0xb1, 0x73, 0xfa, 0xd8, 0xfa, 0xcb, 0x47, 0x32, 0x3b, 0x57, 0x54, 0x84, 0xdd, 0x71, 0x90, + 0x74, 0x89, 0xa9, 0x8a, 0x2b, 0xa7, 0x3e, 0x1b, 0x2e, 0x89, 0xf3, 0x1a, 0xdf, 0x5d, 0x82, 0x5d, 0xde, 0xe4, 0xff, + 0x92, 0xe2, 0xf8, 0x02, 0xb8, 0xa2, 0x08, 0x9c, 0x96, 0x5a, 0x28, 0xa2, 0x78, 0xca, 0x99, 0xe5, 0x16, 0x68, 0xd5, + 0x53, 0xb5, 0xb6, 0xd4, 0x5d, 0x31, 0xc2, 0xb3, 0xd8, 0x0a, 0x43, 0x20, 0xd3, 0x59, 0x90, 0xe5, 0x24, 0x36, 0x38, + 0xe8, 0x73, 0x41, 0x90, 0xcc, 0x85, 0x72, 0x37, 0xee, 0xb1, 0x8d, 0x35, 0x1b, 0x8c, 0x76, 0x96, 0x5a, 0x24, 0xe7, + 0x51, 0x91, 0xbd, 0x2f, 0x77, 0x0b, 0xf6, 0x6d, 0x07, 0x14, 0x25, 0x52, 0x59, 0xfa, 0x3a, 0x52, 0xc2, 0x63, 0xde, + 0xda, 0x4c, 0x23, 0x8c, 0x61, 0xc1, 0x8e, 0x36, 0xb6, 0xcd, 0x65, 0x48, 0x2c, 0x6b, 0x1b, 0x46, 0x95, 0xa1, 0xd9, + 0x88, 0x3c, 0x85, 0xf2, 0xa8, 0xbe, 0x09, 0xda, 0x90, 0x4a, 0xf6, 0xf0, 0xae, 0xa1, 0xb0, 0x48, 0xe9, 0x23, 0xd8, + 0xa2, 0xf9, 0x22, 0xd1, 0xed, 0x51, 0x63, 0x43, 0x76, 0xac, 0x92, 0x1c, 0xa6, 0xcb, 0x06, 0xe9, 0xf3, 0x28, 0x50, + 0xea, 0x2a, 0x91, 0x10, 0x14, 0x12, 0xe6, 0xd9, 0x1b, 0x3e, 0x35, 0x2d, 0xf7, 0x08, 0x08, 0x66, 0x9f, 0x57, 0xbd, + 0xa8, 0x1b, 0x21, 0xe2, 0x43, 0x11, 0x39, 0x7e, 0xaf, 0x1c, 0x86, 0xee, 0x6d, 0x2a, 0x86, 0x5b, 0x1b, 0x1f, 0x4f, + 0x92, 0x29, 0xd1, 0xb4, 0x43, 0xa4, 0x0b, 0x24, 0x56, 0x00, 0xb1, 0x2c, 0x9d, 0x4a, 0x50, 0x0a, 0x3d, 0x05, 0x3b, + 0x9e, 0x8f, 0x37, 0xe9, 0xb4, 0xc5, 0x48, 0x73, 0x59, 0x9a, 0xff, 0xe6, 0xc3, 0x30, 0x3d, 0x4d, 0xec, 0xae, 0xfe, + 0xc2, 0xfd, 0xdc, 0x7d, 0xb3, 0x61, 0x88, 0x62, 0x97, 0x6c, 0x10, 0x81, 0xf0, 0x77, 0xd1, 0xb4, 0xb0, 0x60, 0x2a, + 0xb4, 0x1b, 0xc7, 0xc6, 0x2f, 0x93, 0x61, 0xcf, 0x74, 0xba, 0x23, 0x50, 0xfc, 0x1a, 0x42, 0x87, 0x2b, 0xa0, 0x01, + 0x21, 0x50, 0x3f, 0x8b, 0x5c, 0x0b, 0xe3, 0xde, 0xe6, 0x3f, 0xa2, 0x98, 0x83, 0x01, 0x02, 0x39, 0x15, 0xe4, 0x5e, + 0x70, 0x46, 0x12, 0x67, 0x1d, 0x69, 0x59, 0x7f, 0xea, 0xba, 0x4d, 0xe9, 0xc8, 0xde, 0xb7, 0x82, 0x03, 0x45, 0x7b, + 0xb9, 0x95, 0xe9, 0x3f, 0x80, 0xbd, 0xb0, 0x2b, 0xcb, 0x7f, 0x3c, 0x17, 0x4d, 0x15, 0x19, 0xf5, 0xd4, 0x55, 0xf5, + 0x76, 0x64, 0xcc, 0x4c, 0x66, 0xe3, 0x91, 0x5f, 0x06, 0xed, 0xbe, 0x15, 0xc1, 0xc6, 0x2b, 0xd7, 0xf1, 0xf1, 0xc9, + 0xc8, 0x20, 0xb6, 0xab, 0x0b, 0xd5, 0x8c, 0x09, 0x44, 0x1e, 0xa6, 0xd2, 0x6e, 0x6c, 0xf3, 0x3a, 0xfd, 0xe4, 0x6e, + 0xfd, 0xf6, 0x9b, 0x54, 0x71, 0x6e, 0x85, 0x4d, 0x32, 0xdd, 0xc4, 0x0b, 0xf7, 0xdc, 0xef, 0xda, 0x66, 0xf3, 0xb6, + 0xdb, 0xa5, 0x88, 0xae, 0x6d, 0x04, 0x9d, 0x0f, 0xb5, 0xdd, 0x40, 0xe3, 0x67, 0xda, 0xc4, 0xd7, 0xf9, 0x4f, 0x55, + 0x03, 0x1d, 0xff, 0x89, 0x53, 0xb6, 0x45, 0x1c, 0xb5, 0xe5, 0x52, 0x0a, 0xdf, 0xe0, 0x2b, 0x13, 0xbe, 0x02, 0x77, + 0xe5, 0xc4, 0xf0, 0xec, 0x55, 0xe9, 0x6d, 0x67, 0x3f, 0xfa, 0xc9, 0x9a, 0x7a, 0x12, 0x83, 0xd2, 0x57, 0xc1, 0x3e, + 0x40, 0x5f, 0xa8, 0x1a, 0x22, 0x75, 0xf7, 0xee, 0x2b, 0x81, 0x13, 0x15, 0xe2, 0x3f, 0x08, 0x06, 0x46, 0x69, 0x53, + 0xaa, 0x5f, 0x6c, 0x1d, 0x31, 0xdb, 0x51, 0xe5, 0xb4, 0x7a, 0xd6, 0x07, 0x8f, 0x9f, 0x7b, 0xbf, 0xf9, 0x8f, 0xd4, + 0x3a, 0xc0, 0x2a, 0xab, 0xc3, 0x2f, 0xcb, 0x39, 0x6d, 0xbf, 0xd2, 0xcd, 0x85, 0x62, 0x7a, 0xa1, 0xf5, 0x26, 0x6e, + 0xbd, 0xce, 0xe6, 0xc3, 0xb9, 0x56, 0x84, 0x96, 0x97, 0xfa, 0xe2, 0xd3, 0xf3, 0xbf, 0x1d, 0x8d, 0x75, 0xbf, 0xb7, + 0xdd, 0x56, 0xaa, 0xf6, 0x36, 0x12, 0x46, 0xaa, 0xac, 0x77, 0x8c, 0x1d, 0xba, 0xc6, 0x78, 0x34, 0x86, 0x44, 0xb2, + 0x58, 0x9d, 0x02, 0x0e, 0x9d, 0x10, 0xf9, 0x3a, 0x89, 0x3b, 0x75, 0x12, 0xcd, 0x2c, 0x17, 0x41, 0x22, 0x45, 0xfa, + 0x36, 0x20, 0x6a, 0xe1, 0x90, 0x01, 0x0f, 0xe3, 0xd6, 0x64, 0x10, 0xd6, 0x75, 0x2c, 0x13, 0xa1, 0xda, 0xe1, 0xf5, + 0x29, 0xf5, 0x0a, 0x06, 0xd6, 0x14, 0x49, 0x1b, 0x89, 0x68, 0x4b, 0xdd, 0x7f, 0x35, 0xdd, 0x0f, 0xea, 0xcd, 0x8d, + 0xfd, 0x94, 0xb7, 0x51, 0x8b, 0xe6, 0x5e, 0xd4, 0x30, 0xac, 0x46, 0xd6, 0xcc, 0xb0, 0xcd, 0x23, 0xff, 0x23, 0x29, + 0x70, 0xe8, 0x3a, 0x00, 0xd0, 0x7e, 0x80, 0x36, 0x28, 0x86, 0x11, 0x98, 0xfd, 0xb8, 0x68, 0x23, 0xb5, 0x29, 0xbf, + 0x30, 0xab, 0x6e, 0x39, 0xb2, 0x5b, 0x04, 0x61, 0x4d, 0x96, 0x01, 0xe0, 0x2b, 0x1b, 0x6e, 0x03, 0x50, 0x34, 0x82, + 0xb2, 0xa9, 0x17, 0xb8, 0x2d, 0xfe, 0x1d, 0x9a, 0x35, 0x8f, 0x07, 0x45, 0xcf, 0x88, 0x0a, 0x2a, 0xcb, 0x08, 0xcf, + 0xbf, 0xba, 0x50, 0xae, 0xa4, 0xe1, 0x5b, 0x7a, 0x6e, 0x65, 0x6b, 0xce, 0x7b, 0xbb, 0x8a, 0xfe, 0xb9, 0x5d, 0xcf, + 0xaf, 0xd9, 0x06, 0xcb, 0x08, 0x8f, 0xdc, 0x7e, 0xf9, 0x91, 0x6e, 0xc2, 0xb1, 0x8f, 0x22, 0x3b, 0x2c, 0x4c, 0x41, + 0x70, 0xa8, 0x35, 0xda, 0x94, 0xfc, 0x62, 0x0f, 0x28, 0xcc, 0x1e, 0x36, 0x1c, 0x30, 0xd8, 0x54, 0x19, 0x26, 0x91, + 0x3d, 0x05, 0xbf, 0x6c, 0x83, 0x18, 0x4c, 0xa2, 0xa1, 0x24, 0xe0, 0xa6, 0x74, 0xcd, 0x09, 0xd9, 0x99, 0x53, 0xff, + 0x51, 0x23, 0xac, 0xe7, 0x09, 0x43, 0xd4, 0xc3, 0x34, 0xd3, 0xca, 0xaa, 0x59, 0x78, 0x6b, 0x58, 0xea, 0x1a, 0x82, + 0x94, 0xb2, 0x48, 0xe8, 0x7d, 0xeb, 0x04, 0xb5, 0x81, 0x09, 0xd3, 0x3d, 0x2a, 0xe3, 0xf0, 0x71, 0x9d, 0x16, 0x67, + 0xa2, 0x18, 0xad, 0xac, 0xd7, 0x18, 0xcb, 0xdc, 0x78, 0xcd, 0xcb, 0xa2, 0x99, 0x17, 0xbd, 0x3e, 0xd9, 0x90, 0xf0, + 0xfc, 0x39, 0x14, 0x89, 0x62, 0x63, 0x86, 0xda, 0x8d, 0xe7, 0xc4, 0xa7, 0xf9, 0x46, 0x53, 0x24, 0xb6, 0xf4, 0x9a, + 0x61, 0x25, 0xb3, 0x95, 0x30, 0xbd, 0x5a, 0x95, 0x19, 0xe1, 0xba, 0xc3, 0xb1, 0xcf, 0xf4, 0x70, 0x34, 0x05, 0x3f, + 0x02, 0x6c, 0xee, 0x74, 0xe4, 0xc6, 0xc3, 0xff, 0x01, 0xf2, 0xa8, 0xe6, 0xd1, 0x0a, 0xb9, 0x5c, 0x1e, 0x62, 0x13, + 0x0f, 0x35, 0xc7, 0xee, 0xaf, 0x61, 0xfd, 0xe7, 0x2d, 0xba, 0xa2, 0xed, 0x85, 0x56, 0x29, 0x91, 0x83, 0x36, 0xb1, + 0x2e, 0xdb, 0xc3, 0xa0, 0xb5, 0x88, 0x84, 0x13, 0x55, 0x9d, 0xf5, 0xc2, 0x3c, 0xce, 0xa5, 0xff, 0xc7, 0x4f, 0xb5, + 0x15, 0x04, 0x01, 0x61, 0x7e, 0x17, 0xbb, 0x13, 0x48, 0x71, 0x3e, 0x6b, 0xc8, 0x8c, 0x13, 0xfe, 0x95, 0x27, 0x7c, + 0x4f, 0x33, 0xb2, 0x92, 0xf9, 0x97, 0x32, 0x89, 0x4e, 0x71, 0xd5, 0x1c, 0xf1, 0x3a, 0x65, 0x0c, 0xa6, 0xb7, 0x0c, + 0x72, 0x2e, 0xc8, 0x67, 0x68, 0xca, 0xb9, 0x23, 0xeb, 0x4d, 0x81, 0xa7, 0x11, 0x18, 0x43, 0x01, 0xb2, 0x42, 0x57, + 0x99, 0x9d, 0x76, 0x86, 0x31, 0x30, 0xe4, 0x5e, 0x01, 0x1e, 0x5c, 0x09, 0xa0, 0x92, 0x81, 0x5f, 0xc5, 0x9e, 0x95, + 0x98, 0x7f, 0xb9, 0xa8, 0xd0, 0xee, 0x35, 0xc0, 0x5f, 0xa1, 0xe0, 0x12, 0xd5, 0x42, 0x81, 0x13, 0x01, 0x5d, 0x12, + 0x5c, 0xa0, 0x39, 0x89, 0x10, 0x5b, 0x0d, 0x08, 0x6a, 0x1b, 0xb7, 0x5c, 0x1c, 0xf0, 0xce, 0x7b, 0x59, 0xf1, 0xd5, + 0x75, 0x01, 0x1c, 0x0f, 0xf3, 0xfc, 0xdb, 0xca, 0x5c, 0xf6, 0x73, 0x02, 0x11, 0x17, 0x16, 0x66, 0x8e, 0x28, 0xe7, + 0xb4, 0x20, 0xcb, 0x5c, 0x84, 0x32, 0x5e, 0x6b, 0x98, 0xec, 0x84, 0xb3, 0x8c, 0xb4, 0xfb, 0xd0, 0x99, 0x48, 0x5f, + 0xbc, 0xcb, 0x20, 0xec, 0x90, 0xb5, 0x27, 0x52, 0xb9, 0x9d, 0x45, 0x13, 0xd0, 0xe7, 0x5b, 0x5f, 0xbb, 0xbe, 0xa7, + 0x8d, 0x35, 0x98, 0xbc, 0x6b, 0x36, 0x45, 0x0c, 0xa5, 0xf9, 0x62, 0x82, 0x99, 0xa7, 0xfd, 0x31, 0xcf, 0xc1, 0x22, + 0x7d, 0x99, 0xf4, 0xb2, 0x62, 0xa2, 0x3e, 0xb2, 0x83, 0x60, 0x91, 0x24, 0x86, 0xdc, 0x1a, 0x74, 0x14, 0x54, 0xe4, + 0x6d, 0xb4, 0x90, 0x15, 0xcb, 0x9a, 0x83, 0x9d, 0xf7, 0xdf, 0xb9, 0x62, 0x65, 0x62, 0x60, 0xc7, 0x18, 0x63, 0x9e, + 0x3c, 0x5a, 0xe3, 0xad, 0xdd, 0x5b, 0xae, 0xd0, 0x31, 0x69, 0xc0, 0x49, 0x21, 0x32, 0x2e, 0x5d, 0x62, 0xae, 0xad, + 0x99, 0x2d, 0x6b, 0x6a, 0xe1, 0x3f, 0x3d, 0x2b, 0x63, 0x60, 0xcc, 0x13, 0x41, 0x7e, 0x2e, 0xad, 0x76, 0xcc, 0x9b, + 0xb0, 0x57, 0x02, 0x4e, 0x9d, 0xcb, 0x5c, 0x12, 0x01, 0x5e, 0x2a, 0xfd, 0x4f, 0xdf, 0xfd, 0x0a, 0x09, 0x30, 0x28, + 0x1b, 0x7d, 0x91, 0x56, 0x04, 0x8f, 0x56, 0x83, 0x2f, 0x06, 0x96, 0x88, 0x82, 0x0b, 0xa3, 0x05, 0xde, 0x32, 0xfa, + 0xc2, 0x46, 0x1b, 0x5c, 0xa1, 0x19, 0xe9, 0xb8, 0x4c, 0xed, 0xa3, 0x7d, 0x1f, 0xc0, 0xae, 0x80, 0xd9, 0xda, 0x35, + 0x20, 0x88, 0x96, 0xba, 0x30, 0xa8, 0x48, 0xe1, 0x5a, 0xeb, 0x84, 0xf1, 0x3a, 0x71, 0xdb, 0x38, 0xdc, 0x87, 0x00, + 0x8c, 0xc0, 0x5d, 0xd1, 0x03, 0x0b, 0x44, 0xa5, 0x1e, 0x1d, 0x8d, 0x4b, 0x79, 0x51, 0x97, 0x18, 0xc9, 0x74, 0xdd, + 0x0f, 0xdb, 0xdf, 0xbb, 0x87, 0xbd, 0xf8, 0x94, 0xae, 0x07, 0xda, 0x6d, 0xe9, 0xa5, 0xe8, 0xa1, 0x87, 0xd6, 0x3d, + 0x68, 0x5e, 0x81, 0xde, 0xcb, 0x66, 0x93, 0x44, 0xdd, 0x17, 0xf4, 0xb6, 0x61, 0xfb, 0x5f, 0xda, 0xd0, 0xc0, 0x50, + 0xb5, 0x98, 0x89, 0x52, 0x91, 0x05, 0x61, 0x2c, 0xf4, 0xf7, 0x31, 0xdd, 0x2b, 0xb3, 0x23, 0x5f, 0x31, 0x37, 0xe3, + 0x30, 0x0f, 0x1a, 0xbd, 0x4b, 0xd5, 0x1f, 0x8c, 0xb9, 0x33, 0x34, 0x04, 0x3d, 0x28, 0x0f, 0x90, 0x06, 0x89, 0x41, + 0xab, 0x52, 0x28, 0xe0, 0x12, 0x52, 0xc9, 0x7e, 0x77, 0xf4, 0xcb, 0x4d, 0xbb, 0x6a, 0x0c, 0xc1, 0xa7, 0x77, 0x0e, + 0x10, 0x50, 0xb0, 0x8a, 0x83, 0x34, 0x48, 0xde, 0x90, 0xc3, 0x88, 0xe9, 0x3b, 0x0e, 0x70, 0x75, 0xe0, 0x77, 0xa5, + 0xc4, 0x79, 0x46, 0x08, 0x3d, 0xfe, 0x2f, 0x54, 0xbd, 0x6f, 0x2f, 0x85, 0x19, 0x94, 0x0d, 0xcf, 0x6b, 0x6a, 0x7a, + 0x36, 0xb4, 0x85, 0xfd, 0xbf, 0x4b, 0xc5, 0xfc, 0x96, 0x79, 0xa9, 0xc4, 0x96, 0xca, 0x07, 0x8c, 0xc1, 0x0f, 0x7f, + 0x78, 0x53, 0x73, 0xb1, 0xe4, 0x8d, 0x92, 0xca, 0x82, 0xda, 0xb9, 0xb9, 0xce, 0x6c, 0x60, 0x4f, 0x39, 0x29, 0xb6, + 0xa1, 0x9f, 0x86, 0xfb, 0x21, 0xe7, 0x0a, 0xe8, 0x38, 0xd5, 0x18, 0x2e, 0x24, 0xc1, 0xae, 0x83, 0x9d, 0x8c, 0x6a, + 0x73, 0xc3, 0xe0, 0x5a, 0x89, 0xef, 0x80, 0xb7, 0x03, 0x4c, 0x81, 0xef, 0xe7, 0x7b, 0xf9, 0x33, 0x42, 0xec, 0xb1, + 0x4c, 0x24, 0x01, 0x54, 0x62, 0x45, 0x4f, 0x39, 0x94, 0xb7, 0x8a, 0x6f, 0x65, 0x9e, 0x6a, 0xee, 0xcd, 0xd5, 0x65, + 0x06, 0x5a, 0x2c, 0x32, 0x8a, 0x2f, 0xc0, 0x8e, 0xea, 0x59, 0xfc, 0x17, 0xfa, 0x09, 0x8c, 0xe8, 0xc2, 0xc9, 0x4d, + 0x05, 0x8c, 0x6d, 0x23, 0x1d, 0x4e, 0x75, 0x2f, 0x51, 0xc4, 0x65, 0xa3, 0x11, 0x83, 0x37, 0x58, 0xe2, 0x95, 0x56, + 0x69, 0x7b, 0x4c, 0x82, 0x97, 0x8a, 0x09, 0x5b, 0x8c, 0x0a, 0xda, 0x48, 0x5f, 0x8c, 0x34, 0xd7, 0xa8, 0xdf, 0x8f, + 0xd7, 0xf6, 0x4b, 0x2b, 0x74, 0xcf, 0xe6, 0xa3, 0x82, 0xa0, 0xf1, 0x86, 0x00, 0x02, 0xec, 0x5e, 0x82, 0xae, 0xb8, + 0x63, 0xc8, 0x54, 0xc9, 0xe0, 0x3b, 0x85, 0x47, 0xac, 0xfa, 0xd3, 0xcd, 0xcf, 0xe5, 0x96, 0x95, 0x21, 0x65, 0xdb, + 0xdb, 0xdc, 0xbc, 0x1f, 0x61, 0xd3, 0x38, 0xc3, 0x88, 0x19, 0xf5, 0x0c, 0x18, 0xc3, 0x12, 0x00, 0xab, 0xb8, 0xa0, + 0xde, 0x3c, 0x74, 0x99, 0xdd, 0x30, 0xbd, 0x5e, 0xe9, 0x69, 0x1a, 0x44, 0xb0, 0xb7, 0xec, 0x4d, 0x12, 0xb6, 0x2b, + 0x1b, 0x2f, 0xa1, 0x63, 0xde, 0x7a, 0xc8, 0x59, 0x42, 0xdc, 0x10, 0xd6, 0xc2, 0xdd, 0x4b, 0xc4, 0x7d, 0xee, 0x62, + 0x7d, 0x22, 0x12, 0x1e, 0xf5, 0x02, 0xdd, 0xcb, 0x97, 0x15, 0xc8, 0x99, 0x66, 0xe9, 0xfd, 0x2f, 0x58, 0xeb, 0xca, + 0x65, 0x83, 0x66, 0xa0, 0x47, 0x07, 0xc5, 0x44, 0xcb, 0xe0, 0x02, 0x54, 0x14, 0xbb, 0x9a, 0x58, 0xe6, 0xd1, 0x04, + 0x28, 0xa4, 0x2c, 0x29, 0x4d, 0x26, 0x33, 0x56, 0x50, 0x60, 0x1a, 0xec, 0xbc, 0x78, 0xc0, 0xa0, 0x62, 0x93, 0xa9, + 0x4c, 0xac, 0x2c, 0x24, 0x09, 0x0e, 0x66, 0x85, 0xe6, 0x7a, 0x95, 0xdb, 0x41, 0x08, 0x59, 0x1d, 0x60, 0xdf, 0xac, + 0x64, 0x02, 0x6a, 0x1f, 0xe6, 0xb1, 0x63, 0x54, 0x52, 0x40, 0xbf, 0x10, 0x42, 0x6e, 0x77, 0x87, 0x3b, 0x6a, 0x8e, + 0x4e, 0x2f, 0x72, 0x97, 0x0c, 0x29, 0xf2, 0xdd, 0x17, 0x81, 0x63, 0x66, 0xe4, 0x32, 0xab, 0x84, 0xa8, 0x7b, 0x2b, + 0x5a, 0xc6, 0x2f, 0xe8, 0xef, 0x5c, 0xfa, 0x84, 0xd2, 0x82, 0x58, 0x74, 0x38, 0xa8, 0x01, 0xb2, 0xcd, 0x0e, 0x73, + 0x58, 0xda, 0xcd, 0x0b, 0x4b, 0xf0, 0x59, 0xfe, 0x36, 0xf6, 0xec, 0x27, 0x4f, 0xd7, 0xd5, 0x37, 0x5f, 0xc3, 0x28, + 0xe6, 0x5e, 0x6f, 0x34, 0x79, 0xbb, 0xc3, 0x08, 0xe1, 0x44, 0xda, 0xed, 0xf6, 0xd0, 0xc3, 0x15, 0x24, 0x60, 0x83, + 0x83, 0x4b, 0xaf, 0x6e, 0x9f, 0xac, 0x7f, 0xd5, 0x85, 0x39, 0xff, 0x99, 0x06, 0x70, 0x08, 0x19, 0x42, 0xda, 0x04, + 0x41, 0x0f, 0x43, 0x05, 0x6b, 0x2a, 0xb6, 0x32, 0x96, 0x25, 0xfd, 0x80, 0x58, 0xdf, 0xe0, 0xb2, 0x95, 0x65, 0xd4, + 0x42, 0xf0, 0xfc, 0x17, 0x07, 0x08, 0xde, 0x16, 0x9c, 0xfd, 0xd7, 0xc8, 0xc2, 0xf7, 0x8e, 0x0d, 0x52, 0xfa, 0x58, + 0x79, 0x67, 0xb8, 0x6c, 0xaa, 0xd9, 0xc0, 0x8e, 0xac, 0x5c, 0xef, 0xe9, 0x4d, 0x85, 0x32, 0xda, 0x8c, 0x1a, 0xd5, + 0xa6, 0xcc, 0xd2, 0x18, 0xbe, 0x47, 0xb3, 0xa8, 0x4f, 0x52, 0xbd, 0x61, 0x6f, 0xb6, 0x16, 0xb5, 0x83, 0xa9, 0xc6, + 0xf0, 0xde, 0xfe, 0xa9, 0xd9, 0x04, 0x81, 0xd2, 0x09, 0x76, 0xdc, 0x81, 0x8f, 0x94, 0x9e, 0x22, 0xa6, 0x1d, 0x44, + 0xfc, 0xbd, 0x95, 0xec, 0xe8, 0xf7, 0x38, 0x8a, 0x9f, 0x91, 0x31, 0x00, 0x31, 0xba, 0x2d, 0x4c, 0x41, 0xa4, 0x84, + 0xe6, 0x07, 0x2f, 0x14, 0xc4, 0x53, 0xa2, 0x01, 0x50, 0x76, 0x9b, 0xba, 0x02, 0xfb, 0x8c, 0x2f, 0x59, 0x5b, 0xcd, + 0x61, 0x3a, 0xd0, 0xb2, 0x60, 0xbd, 0xcb, 0xe9, 0x39, 0x53, 0x96, 0x5c, 0x6b, 0x37, 0x28, 0xc4, 0xfd, 0x57, 0xcb, + 0xbb, 0x05, 0x96, 0xb3, 0xc7, 0xbf, 0xdf, 0xc8, 0x4f, 0xdc, 0x2a, 0x1b, 0xc2, 0xac, 0x87, 0x4c, 0x91, 0x25, 0x39, + 0x0c, 0x32, 0xad, 0xa5, 0xfb, 0x07, 0x32, 0x68, 0x6e, 0xb7, 0xf5, 0x14, 0xd6, 0xe4, 0xf9, 0xe0, 0xcb, 0x0e, 0x64, + 0x67, 0x0a, 0x61, 0xa0, 0x7f, 0xd9, 0xde, 0x5e, 0x80, 0xce, 0x4d, 0x86, 0xb8, 0xbb, 0xe2, 0x8d, 0x73, 0x51, 0xde, + 0xf8, 0xe5, 0xb6, 0x13, 0x56, 0xd0, 0xb6, 0x88, 0xa6, 0x41, 0xb5, 0xfc, 0x3d, 0xa2, 0xbc, 0xd8, 0xac, 0xb6, 0x7c, + 0x3e, 0x55, 0x46, 0x4f, 0x2f, 0x41, 0x37, 0xe8, 0x07, 0x43, 0xc4, 0xb7, 0x9f, 0xb5, 0xe3, 0x23, 0xd3, 0x96, 0x3f, + 0xb5, 0xed, 0x19, 0x22, 0xfa, 0xd9, 0xee, 0x11, 0xed, 0xd8, 0x03, 0x68, 0x78, 0x58, 0xa9, 0xa1, 0x83, 0xde, 0x43, + 0xc1, 0x3c, 0xc5, 0x5b, 0x90, 0xc3, 0xe6, 0xc1, 0xf2, 0x0e, 0x10, 0xd9, 0x42, 0xb9, 0x64, 0x6f, 0x21, 0xbd, 0xf3, + 0xf6, 0xcc, 0xc9, 0xe0, 0x91, 0x9e, 0x20, 0x9e, 0x22, 0x80, 0x74, 0x0c, 0x26, 0xbb, 0x75, 0xa9, 0xf5, 0x6c, 0xa2, + 0x00, 0x3b, 0xa7, 0x70, 0x1a, 0xf3, 0x5c, 0xd2, 0x08, 0x82, 0x3d, 0x6b, 0x12, 0x69, 0x09, 0x51, 0xe8, 0xa3, 0xb3, + 0x6d, 0xfb, 0x24, 0x2f, 0x23, 0x5f, 0x87, 0xd8, 0xac, 0xd2, 0xdf, 0x58, 0xe5, 0xc4, 0xd5, 0x23, 0x9f, 0xcf, 0x5d, + 0xe8, 0xe7, 0xcc, 0x20, 0x42, 0xbb, 0xb0, 0x92, 0xd1, 0xa8, 0xc8, 0x34, 0x7a, 0x45, 0xb2, 0x97, 0x0a, 0x21, 0x19, + 0x46, 0x37, 0x46, 0xb1, 0x87, 0x23, 0x67, 0x53, 0xc9, 0x12, 0x76, 0x61, 0x89, 0xf3, 0x5f, 0xea, 0x0c, 0xf4, 0x52, + 0x15, 0x4d, 0xe6, 0xa2, 0x9c, 0x6b, 0x87, 0x34, 0x19, 0x00, 0x43, 0x8d, 0xb7, 0x09, 0x9e, 0xf6, 0xa8, 0xc6, 0xab, + 0x56, 0xe4, 0x48, 0xd8, 0x7c, 0x5c, 0xc4, 0x8e, 0xf1, 0x80, 0x3c, 0x62, 0x1c, 0x0f, 0x3e, 0xc7, 0x83, 0x06, 0x48, + 0xfe, 0x44, 0x0a, 0x3e, 0x7a, 0x5e, 0x31, 0x07, 0xb3, 0x0d, 0x6c, 0xcf, 0x44, 0x53, 0x05, 0xb3, 0x93, 0xf5, 0x1e, + 0x50, 0x47, 0xc5, 0x50, 0x38, 0x32, 0xec, 0xc1, 0x70, 0xa6, 0xde, 0xb1, 0xf5, 0x39, 0x3b, 0x68, 0x79, 0x50, 0x25, + 0x19, 0x08, 0x5c, 0x7c, 0x18, 0x71, 0x8d, 0x4f, 0xea, 0x05, 0xd0, 0x1c, 0x79, 0xa5, 0xc5, 0xc7, 0xa3, 0x61, 0xc2, + 0x11, 0x43, 0x46, 0x7f, 0xb4, 0x31, 0xd5, 0x90, 0x6e, 0x97, 0xae, 0x77, 0x13, 0xbe, 0x4a, 0xc9, 0xd2, 0xcd, 0x51, + 0xf6, 0x9a, 0xc6, 0x03, 0xcd, 0x75, 0x33, 0xdb, 0x97, 0x7f, 0xc7, 0x74, 0x8e, 0xcc, 0x45, 0xc2, 0xba, 0x29, 0xb7, + 0xa8, 0xe3, 0x2e, 0x3e, 0x1c, 0x8e, 0x8c, 0x61, 0x7b, 0xf0, 0x44, 0xee, 0x30, 0xc7, 0xb1, 0xbf, 0xb2, 0xe0, 0x46, + 0xe9, 0x25, 0xc7, 0xe2, 0xab, 0xd9, 0x84, 0x2c, 0x66, 0x29, 0x50, 0xb1, 0xea, 0xb7, 0x01, 0xb6, 0xd8, 0x8a, 0x5a, + 0x27, 0x51, 0xef, 0x33, 0x8d, 0x98, 0x5b, 0xb6, 0x3c, 0x22, 0x08, 0xf2, 0x8d, 0xac, 0xa6, 0x79, 0xd4, 0x58, 0x06, + 0xa8, 0x6b, 0x12, 0x8b, 0x5a, 0xee, 0x50, 0x90, 0x59, 0xe8, 0x20, 0xa4, 0xd7, 0x29, 0x8c, 0x47, 0x2e, 0x57, 0xc8, + 0x74, 0xa9, 0xf3, 0x80, 0x17, 0x2b, 0xc7, 0x46, 0xbf, 0xfe, 0x78, 0x20, 0xaf, 0x48, 0xc4, 0x72, 0x82, 0x2f, 0xe1, + 0xd2, 0x98, 0x31, 0x90, 0x4c, 0xb4, 0x4f, 0x45, 0x2b, 0xf6, 0x63, 0x44, 0x5d, 0x48, 0xf4, 0x58, 0x70, 0x44, 0xb2, + 0x23, 0x61, 0x7f, 0x28, 0x8a, 0x21, 0x89, 0xc7, 0x9c, 0x63, 0x1a, 0x78, 0xdf, 0x16, 0xbd, 0xed, 0x70, 0x68, 0x5b, + 0x94, 0xd7, 0x8a, 0x0b, 0x74, 0xca, 0x92, 0x1b, 0xe0, 0x25, 0xaf, 0x7e, 0xc2, 0xee, 0x1a, 0x07, 0xe5, 0xeb, 0xe2, + 0xee, 0xed, 0x26, 0xc1, 0xc0, 0x3b, 0x88, 0xf3, 0x7a, 0x19, 0xc5, 0xf1, 0xbb, 0x5d, 0xf0, 0xea, 0x98, 0xcf, 0x08, + 0x18, 0x3c, 0x42, 0x3a, 0x91, 0xed, 0x35, 0x27, 0x78, 0xf8, 0xa1, 0xd4, 0x1f, 0x0b, 0x28, 0x67, 0x85, 0xbf, 0x51, + 0xa6, 0xb6, 0x8d, 0x2e, 0xa4, 0xe4, 0xe3, 0x52, 0x7a, 0x17, 0x62, 0xc4, 0x80, 0x5c, 0xed, 0xca, 0xf7, 0x62, 0x55, + 0x7a, 0x54, 0x6a, 0xc4, 0x17, 0xf4, 0x8a, 0xa1, 0x35, 0x46, 0xbd, 0xe3, 0x66, 0x9d, 0x08, 0x13, 0x83, 0xaf, 0xa8, + 0x9d, 0xb4, 0xcd, 0x98, 0x08, 0x81, 0x34, 0x59, 0xb4, 0x7e, 0xb2, 0x88, 0xc2, 0x42, 0x28, 0x62, 0xc2, 0x12, 0x2d, + 0x87, 0x04, 0x04, 0x91, 0x21, 0x8d, 0xf0, 0x98, 0xbb, 0x96, 0x03, 0xe3, 0x01, 0x8c, 0xa5, 0xb8, 0xf7, 0x8f, 0xaf, + 0x46, 0x30, 0x05, 0x11, 0x3c, 0xd5, 0x95, 0x17, 0x49, 0x43, 0x63, 0x35, 0xcc, 0x43, 0x73, 0x21, 0x47, 0x19, 0x78, + 0x33, 0x27, 0x58, 0x5c, 0xb5, 0x32, 0xc2, 0x4d, 0x7f, 0xb6, 0xfb, 0x50, 0xcf, 0x9d, 0x83, 0x36, 0x27, 0xcb, 0x59, + 0xb2, 0xd2, 0x1f, 0x6d, 0x4f, 0x10, 0x81, 0xc8, 0x60, 0x06, 0x52, 0x57, 0x04, 0x42, 0x42, 0x1c, 0x45, 0x92, 0x9b, + 0x27, 0x87, 0x08, 0xc4, 0xe7, 0xe5, 0x17, 0xfa, 0x20, 0x03, 0x4a, 0x64, 0xbd, 0xbe, 0x59, 0x01, 0xd3, 0x13, 0x4e, + 0x21, 0xc5, 0x1e, 0xab, 0x82, 0x41, 0x46, 0x24, 0xcc, 0x16, 0x27, 0x0c, 0x99, 0xd7, 0x57, 0xbf, 0x77, 0x38, 0x35, + 0x3c, 0xe8, 0x00, 0x30, 0xaa, 0x1c, 0x41, 0x21, 0x92, 0x3f, 0x29, 0x60, 0x58, 0x21, 0xe1, 0xdd, 0x9b, 0xe4, 0xc2, + 0x89, 0x6c, 0x63, 0x55, 0x79, 0x25, 0xac, 0x7e, 0xa8, 0x81, 0x67, 0x24, 0x04, 0xa6, 0xa8, 0x18, 0xdb, 0xbf, 0xff, + 0x59, 0x55, 0x49, 0x1a, 0x2f, 0x92, 0x94, 0x7e, 0xed, 0x71, 0x5b, 0xa8, 0x85, 0x86, 0x49, 0x9a, 0x1d, 0xea, 0x6d, + 0x67, 0x12, 0x39, 0xe3, 0x10, 0x72, 0x16, 0x62, 0x00, 0x88, 0x97, 0xc1, 0xe0, 0x43, 0xeb, 0x63, 0xda, 0x01, 0xa7, + 0x5f, 0xbb, 0x67, 0x65, 0xf4, 0xa3, 0x35, 0xcf, 0xe8, 0xc2, 0xf9, 0xe9, 0x51, 0xad, 0x26, 0x7e, 0x48, 0xe0, 0xac, + 0x84, 0x5e, 0x8a, 0x59, 0x35, 0x1e, 0x67, 0xae, 0xf8, 0x7a, 0x74, 0x6a, 0xab, 0x40, 0xac, 0x2a, 0x0d, 0x37, 0xc2, + 0x78, 0xf6, 0x40, 0xb2, 0x79, 0x14, 0x7e, 0xa4, 0x92, 0x71, 0xaf, 0x38, 0xc2, 0x0c, 0xd1, 0x06, 0x7a, 0xce, 0x0b, + 0x58, 0xce, 0xca, 0x22, 0x19, 0x79, 0x1d, 0x0a, 0x9a, 0xde, 0x38, 0xe4, 0x21, 0x53, 0x1c, 0x9c, 0xc9, 0x0a, 0x9f, + 0xd3, 0xa3, 0xe6, 0xc6, 0x28, 0xab, 0x60, 0x63, 0x34, 0x9f, 0x96, 0x9e, 0x3c, 0x90, 0x4d, 0x63, 0x9a, 0xd2, 0xa2, + 0xa4, 0x21, 0x71, 0xa9, 0x6a, 0xe6, 0x68, 0x1e, 0x98, 0x43, 0xac, 0x6f, 0x5f, 0x70, 0xf6, 0x88, 0xe7, 0xe3, 0x82, + 0x14, 0xa4, 0xcd, 0xf4, 0xa8, 0xe4, 0xfa, 0xf3, 0x33, 0x20, 0xac, 0xbc, 0x7d, 0xb0, 0xe1, 0xd7, 0x15, 0x12, 0xd9, + 0xde, 0xbc, 0x1c, 0xa0, 0x68, 0xc2, 0xaf, 0x1d, 0x6c, 0xd6, 0x57, 0x96, 0x38, 0xbe, 0x35, 0x5b, 0x15, 0x44, 0x4e, + 0x66, 0x46, 0xbf, 0xee, 0x05, 0xac, 0x15, 0x61, 0xca, 0xd9, 0xd9, 0xe6, 0x1a, 0xa0, 0xa5, 0xe0, 0x38, 0x2a, 0x46, + 0x7c, 0x54, 0xcf, 0x48, 0x65, 0x26, 0xbd, 0xc6, 0x42, 0x97, 0xe1, 0x0b, 0x35, 0xf5, 0x5a, 0xd4, 0x7c, 0xe4, 0x43, + 0x46, 0x84, 0x9d, 0x46, 0xb8, 0xf8, 0xc6, 0xc0, 0x6b, 0x79, 0x1a, 0x9d, 0x07, 0x7a, 0x2f, 0x36, 0x5b, 0x9e, 0xf8, + 0xee, 0xba, 0x4d, 0x8e, 0x8f, 0xb1, 0x35, 0x5b, 0x36, 0x63, 0xf9, 0xe9, 0xf5, 0x27, 0xa3, 0x2a, 0xa1, 0x66, 0xeb, + 0xbe, 0x9f, 0xba, 0x7e, 0x3d, 0x34, 0xcf, 0xf3, 0x36, 0x6d, 0x1b, 0xe7, 0xe6, 0xde, 0x80, 0x6c, 0x2f, 0x0a, 0xe6, + 0xb9, 0xd0, 0x9c, 0x36, 0xb4, 0x3e, 0xbd, 0x84, 0x59, 0x99, 0xd9, 0xd0, 0x76, 0x7d, 0xad, 0x7f, 0xa9, 0x28, 0x8c, + 0xd8, 0xfa, 0x80, 0x13, 0x51, 0x4a, 0x54, 0x5a, 0xe5, 0xe7, 0x4b, 0x6f, 0x45, 0x48, 0x9e, 0xcb, 0x7e, 0x19, 0x4d, + 0xff, 0x09, 0xbd, 0x56, 0x26, 0x42, 0xf1, 0x35, 0x73, 0xee, 0x59, 0x2d, 0xf9, 0xd7, 0x52, 0xb1, 0x74, 0xac, 0x71, + 0xd5, 0x7a, 0x5e, 0xc6, 0x93, 0x6b, 0xb8, 0x3e, 0x4e, 0xd1, 0x7a, 0xc6, 0x48, 0x7f, 0x0e, 0xae, 0x44, 0xa4, 0x16, + 0x97, 0xbe, 0x03, 0x73, 0x25, 0x0a, 0xc9, 0xd5, 0x54, 0x7a, 0xf6, 0x56, 0xf5, 0x38, 0xd1, 0x3c, 0x23, 0x73, 0xef, + 0xca, 0xbe, 0x59, 0x95, 0xd6, 0x5e, 0x93, 0x57, 0x29, 0x1c, 0x9f, 0xe0, 0x3a, 0xb9, 0x77, 0x4f, 0x31, 0x25, 0x88, + 0x10, 0xba, 0x38, 0xed, 0x0b, 0xbf, 0x42, 0x38, 0xe0, 0xf5, 0xd4, 0x69, 0xdd, 0x5e, 0x52, 0x2d, 0x41, 0x9c, 0xab, + 0x3b, 0x9c, 0xb3, 0x5b, 0x73, 0xb6, 0x90, 0x1d, 0x67, 0x59, 0xa1, 0x9e, 0x6e, 0x0e, 0x19, 0x76, 0x28, 0x78, 0x86, + 0x5c, 0xb7, 0x57, 0xd3, 0x67, 0x23, 0x32, 0x71, 0xab, 0xdd, 0xbe, 0x45, 0x72, 0x79, 0x1a, 0x00, 0xc1, 0x18, 0xfe, + 0x79, 0xd1, 0x9e, 0x8c, 0xce, 0x84, 0x05, 0xb3, 0x21, 0x90, 0x06, 0x8c, 0x19, 0x24, 0xc2, 0xe3, 0x3f, 0x91, 0xff, + 0x57, 0x93, 0xdf, 0x78, 0x31, 0xce, 0xa9, 0xe3, 0x37, 0xef, 0x35, 0xa0, 0x24, 0x66, 0xc1, 0x89, 0x0d, 0xaf, 0x82, + 0x6c, 0x99, 0xb6, 0x81, 0x63, 0xb0, 0x4c, 0x7f, 0x0c, 0xca, 0xd8, 0x0b, 0x48, 0x32, 0xf1, 0x8e, 0x84, 0xea, 0x74, + 0xd6, 0x5e, 0x1c, 0x09, 0x5c, 0xce, 0x99, 0xe4, 0xe8, 0x02, 0x1b, 0x33, 0xc1, 0xd3, 0xee, 0x30, 0xd2, 0xcf, 0x50, + 0xbc, 0x96, 0xab, 0xdb, 0xc8, 0x00, 0xa1, 0x04, 0x13, 0xea, 0x13, 0xd2, 0xfe, 0xed, 0xe1, 0x88, 0x81, 0x44, 0x81, + 0x26, 0x0b, 0x76, 0x80, 0x4d, 0xa1, 0xae, 0xdd, 0x3c, 0x96, 0x36, 0xc6, 0x23, 0x69, 0x94, 0x61, 0x71, 0x59, 0x91, + 0xd1, 0x4a, 0x5f, 0x39, 0x9a, 0x2d, 0x1c, 0xfb, 0xce, 0x62, 0xb0, 0xd0, 0x86, 0xab, 0x97, 0x09, 0xba, 0x9f, 0x3a, + 0xf2, 0xca, 0xff, 0x6a, 0xb2, 0xea, 0xd6, 0x67, 0x6f, 0xf2, 0x95, 0x43, 0x46, 0xdc, 0x5e, 0x3d, 0x7f, 0x8c, 0x47, + 0x4f, 0xb5, 0xd2, 0x87, 0x11, 0x67, 0x18, 0x54, 0xb9, 0x2d, 0x08, 0xcf, 0x6a, 0x32, 0x6c, 0x74, 0x14, 0xf4, 0x03, + 0x4d, 0x09, 0x66, 0xec, 0xc7, 0xd4, 0x04, 0x58, 0xf2, 0xa4, 0xb3, 0xb0, 0xf2, 0x7a, 0x76, 0x1d, 0x6f, 0x73, 0x81, + 0xe5, 0x13, 0x8e, 0x3d, 0xd8, 0xc4, 0x0a, 0x9b, 0x0a, 0x9b, 0x24, 0x2e, 0x3c, 0xb1, 0xb2, 0x8c, 0x78, 0xe1, 0x0a, + 0x5b, 0xa7, 0x3c, 0x95, 0xc2, 0x6e, 0xe8, 0xca, 0xaf, 0xf5, 0xca, 0x8b, 0xd1, 0x79, 0x1d, 0xa3, 0x9b, 0xe4, 0x26, + 0x86, 0x60, 0x30, 0xec, 0x46, 0x4e, 0xfa, 0xf6, 0x40, 0xc9, 0xe0, 0x06, 0x0d, 0xca, 0xd7, 0x91, 0xb5, 0x42, 0x3c, + 0xd7, 0x95, 0x0b, 0x67, 0x9e, 0x00, 0x98, 0x2f, 0xaf, 0x17, 0xda, 0x44, 0x07, 0x3b, 0xbe, 0x9f, 0xf7, 0x05, 0x0b, + 0x78, 0xd9, 0x21, 0x96, 0x95, 0x37, 0x3b, 0xfd, 0x05, 0x6e, 0x38, 0x73, 0x6d, 0x9b, 0x51, 0x6d, 0xa1, 0x97, 0xe8, + 0xc8, 0xdc, 0xb3, 0x64, 0xab, 0x89, 0x80, 0xb3, 0x03, 0xc1, 0xa2, 0x24, 0xe6, 0x09, 0x82, 0x25, 0x7e, 0xc2, 0x03, + 0x59, 0xd8, 0x2f, 0xcd, 0xa5, 0xe8, 0x89, 0xf6, 0xfa, 0xa5, 0xf9, 0x9c, 0x5f, 0x84, 0x43, 0x7c, 0xae, 0x28, 0xeb, + 0xa1, 0xce, 0xe3, 0x20, 0x8a, 0xa3, 0x5f, 0x33, 0x95, 0xd0, 0xfe, 0x31, 0x5a, 0x94, 0x34, 0x76, 0x59, 0xb8, 0xd2, + 0xca, 0x9a, 0x70, 0x95, 0x76, 0x93, 0x41, 0x5e, 0x89, 0x67, 0x5e, 0x65, 0x5d, 0xd6, 0x1c, 0xdf, 0x83, 0xba, 0x1d, + 0x39, 0xfb, 0xac, 0xa1, 0x4a, 0x0e, 0xd0, 0xfe, 0xe0, 0xa1, 0xb3, 0x08, 0x6a, 0x08, 0xae, 0x6e, 0x7c, 0x82, 0x38, + 0xe0, 0x32, 0x08, 0xa9, 0x0c, 0xfb, 0x52, 0xc9, 0xbf, 0x91, 0x32, 0x8a, 0xff, 0xab, 0x34, 0xaf, 0x1e, 0x18, 0x84, + 0xaf, 0xbb, 0x9b, 0x5f, 0x01, 0xb2, 0xb5, 0x30, 0x33, 0xb8, 0xc9, 0x6d, 0x13, 0xf7, 0x45, 0x39, 0x68, 0x1b, 0xac, + 0x97, 0x16, 0xa1, 0x0f, 0x1a, 0x8f, 0x34, 0x61, 0xf5, 0x39, 0x5c, 0x0b, 0x02, 0x37, 0x75, 0xfe, 0x78, 0x3c, 0xc9, + 0xd4, 0x14, 0x9a, 0xc6, 0xee, 0x4c, 0x5a, 0x8e, 0x30, 0x90, 0x30, 0x40, 0x36, 0x3e, 0xb0, 0x6d, 0xe9, 0xf6, 0x66, + 0x11, 0x5c, 0xaf, 0x41, 0x50, 0xca, 0x96, 0x45, 0x07, 0x47, 0x63, 0xb6, 0xc1, 0x9c, 0xee, 0x13, 0x8d, 0xc8, 0xae, + 0x60, 0x38, 0x0b, 0x23, 0xd7, 0x5f, 0x9c, 0x35, 0xeb, 0x2e, 0x28, 0x52, 0x3d, 0xf2, 0xa1, 0xd8, 0x46, 0x00, 0x4f, + 0xa8, 0xf4, 0xf1, 0xc0, 0x23, 0x8a, 0x56, 0x87, 0x14, 0x1e, 0x16, 0x85, 0x43, 0xbe, 0xc1, 0x38, 0x1d, 0xa1, 0x3e, + 0x39, 0x82, 0x31, 0x45, 0x7e, 0xf8, 0x8b, 0x85, 0xf1, 0xb5, 0x7c, 0x81, 0x79, 0x5a, 0x69, 0x11, 0x77, 0x3d, 0xe5, + 0xb6, 0xcf, 0xed, 0xe1, 0x13, 0x2f, 0x21, 0x1b, 0xa1, 0xdf, 0x47, 0x7e, 0xd4, 0x6c, 0xfd, 0xe7, 0x01, 0xe6, 0xdb, + 0xc1, 0x1a, 0x4c, 0x38, 0x2a, 0x78, 0xa4, 0x1f, 0x5d, 0x99, 0x76, 0x83, 0x82, 0xf5, 0x21, 0x94, 0x32, 0x3a, 0x71, + 0xd0, 0xed, 0x6a, 0xe6, 0xbf, 0x3c, 0x76, 0x31, 0x02, 0x59, 0x48, 0xe2, 0xe7, 0xa5, 0xec, 0xdb, 0xba, 0x0c, 0x6b, + 0x69, 0xe9, 0xe6, 0x69, 0x22, 0x86, 0xcb, 0x24, 0xa8, 0xbc, 0xea, 0x11, 0x11, 0x23, 0x52, 0x16, 0x4c, 0xbd, 0x8c, + 0xbf, 0xe3, 0x3b, 0x63, 0x17, 0xb5, 0x6e, 0x23, 0xb5, 0x6e, 0xaf, 0x7a, 0xb3, 0xb5, 0xeb, 0xc3, 0x36, 0x0e, 0xf0, + 0xde, 0xd2, 0x4f, 0x50, 0xa0, 0xf1, 0x4a, 0x3b, 0xfa, 0xed, 0x40, 0x4c, 0xf8, 0x87, 0xd8, 0x35, 0x89, 0xee, 0x0b, + 0x86, 0x2b, 0xb5, 0xc9, 0xda, 0x06, 0xc6, 0x08, 0xc5, 0x5a, 0x9e, 0x47, 0x70, 0x9e, 0x8d, 0x1c, 0x15, 0xda, 0x65, + 0x8c, 0xcf, 0xc8, 0x8e, 0xf1, 0x4f, 0xc8, 0xca, 0x16, 0x46, 0x70, 0x4f, 0x72, 0x2a, 0x92, 0xe8, 0xfc, 0x14, 0x05, + 0xf2, 0x46, 0xeb, 0x12, 0x1d, 0x78, 0x7d, 0xd1, 0x2c, 0x1e, 0xfe, 0x1e, 0x2d, 0x29, 0x44, 0x38, 0x78, 0x7c, 0x47, + 0x84, 0x50, 0xab, 0x29, 0x54, 0x47, 0x5b, 0x0c, 0x32, 0x7b, 0x7c, 0x4a, 0x36, 0x5f, 0x64, 0x1b, 0x1c, 0xb1, 0x04, + 0x3f, 0xa9, 0xec, 0xc7, 0x95, 0x4d, 0xfc, 0x48, 0xff, 0x43, 0x69, 0xc9, 0xa9, 0x8e, 0xd7, 0x74, 0x55, 0x43, 0x53, + 0xe8, 0x0a, 0xb5, 0x11, 0x1d, 0x87, 0xfd, 0x2b, 0x94, 0x49, 0x9d, 0x6a, 0xda, 0x20, 0x6a, 0x1d, 0xf4, 0x3d, 0x5a, + 0x70, 0xbf, 0xf2, 0x3a, 0xf2, 0x45, 0x0c, 0x22, 0x27, 0xe8, 0x57, 0x62, 0x73, 0x25, 0x9f, 0xa7, 0xd1, 0x9d, 0xb7, + 0x54, 0xb2, 0xb1, 0x11, 0x2a, 0xca, 0xda, 0xdb, 0xe4, 0x52, 0xca, 0x5b, 0x4f, 0xe8, 0x29, 0xf7, 0xf2, 0xc1, 0x6c, + 0x93, 0xc6, 0x22, 0x22, 0x4e, 0x36, 0x1e, 0xae, 0xe3, 0x0d, 0x79, 0xa1, 0xd8, 0x82, 0x91, 0x0a, 0x5a, 0x83, 0x97, + 0x9d, 0xb3, 0x8c, 0xf2, 0x95, 0x38, 0x5e, 0xe4, 0x6f, 0xbb, 0xd9, 0x20, 0x9e, 0x1f, 0x06, 0xde, 0x47, 0x12, 0xea, + 0xac, 0x40, 0xc2, 0x1c, 0x77, 0x90, 0x05, 0xcb, 0x73, 0x25, 0x8f, 0x40, 0x32, 0x30, 0x52, 0xb4, 0x0d, 0xd3, 0xb9, + 0x14, 0x1f, 0xb4, 0x83, 0x8d, 0xb3, 0x41, 0x10, 0x1c, 0xd8, 0xf9, 0xfd, 0xfc, 0xeb, 0x5b, 0x1a, 0x83, 0xd3, 0xdb, + 0x2d, 0xc3, 0xff, 0x13, 0x5c, 0x9a, 0x45, 0xb4, 0x9c, 0xfe, 0x14, 0x63, 0xbe, 0xfc, 0x3f, 0xb9, 0x5b, 0x68, 0x1d, + 0xb4, 0xf0, 0x81, 0xed, 0x8e, 0x56, 0xdd, 0x46, 0x92, 0xda, 0xda, 0x0d, 0x06, 0x14, 0x66, 0x48, 0x39, 0x29, 0xa3, + 0x7a, 0x87, 0x46, 0x2f, 0x9c, 0x6e, 0x8e, 0x02, 0x30, 0xf7, 0xc1, 0xca, 0x7b, 0xca, 0x93, 0xdd, 0xbd, 0x02, 0x2b, + 0xb1, 0x1e, 0x0d, 0x90, 0xa3, 0xd4, 0xfe, 0x7d, 0xe1, 0xd4, 0xba, 0xa7, 0x25, 0xab, 0x6c, 0x38, 0x7f, 0xd1, 0x55, + 0x82, 0xb0, 0xc1, 0xd5, 0x53, 0xae, 0xcb, 0x2d, 0x7d, 0x5a, 0xa9, 0xca, 0x18, 0x1f, 0x0a, 0x09, 0x60, 0xa7, 0xaa, + 0x64, 0xdd, 0x19, 0xbf, 0x94, 0x62, 0x77, 0xac, 0xd9, 0xc9, 0x5f, 0x6f, 0x80, 0xdf, 0x2b, 0xe6, 0x75, 0x57, 0x8f, + 0xd6, 0x13, 0xd8, 0x93, 0x4b, 0x8f, 0xa1, 0x42, 0x60, 0x87, 0x97, 0x34, 0xd8, 0x7d, 0x90, 0x36, 0x0b, 0x93, 0x03, + 0x87, 0xe8, 0x34, 0x12, 0x3c, 0x57, 0x69, 0x69, 0xe4, 0xc4, 0x5b, 0x79, 0x62, 0xb7, 0x2e, 0x6e, 0xd2, 0x54, 0xc2, + 0x21, 0xa3, 0x90, 0x67, 0xf0, 0x86, 0x73, 0x89, 0xd2, 0xb3, 0xd9, 0xb4, 0xc9, 0x68, 0xc2, 0x79, 0x9a, 0xdf, 0x87, + 0x93, 0x6b, 0xac, 0x3e, 0xea, 0x98, 0xf4, 0x02, 0x38, 0x4b, 0xd1, 0x1a, 0xf1, 0xab, 0x03, 0x03, 0x0d, 0x2e, 0x2f, + 0xec, 0x25, 0x0b, 0xc1, 0x18, 0x6d, 0x63, 0x8f, 0x49, 0x07, 0x0e, 0xa1, 0xbe, 0x4e, 0x19, 0xc2, 0x0c, 0x2b, 0x88, + 0x60, 0x9a, 0xe2, 0xcc, 0xe1, 0x37, 0x70, 0xcf, 0x0a, 0x8c, 0x0a, 0xb9, 0x89, 0x0e, 0x23, 0xe0, 0x0a, 0xb7, 0x03, + 0x44, 0x76, 0xe6, 0x63, 0xc6, 0x6c, 0x9d, 0x71, 0xd8, 0xaf, 0x5c, 0x62, 0xd3, 0x1e, 0xa9, 0xfe, 0x8e, 0xdb, 0x7e, + 0x3b, 0xe1, 0xcf, 0x05, 0x8e, 0x62, 0x03, 0x71, 0x4f, 0xcb, 0x59, 0x4a, 0x2d, 0x1c, 0x1f, 0x47, 0x33, 0x8c, 0x43, + 0xe9, 0x9c, 0x32, 0xc9, 0x36, 0x0a, 0x9b, 0x01, 0xa4, 0xed, 0xe6, 0x90, 0x4c, 0x99, 0xa4, 0xb1, 0x38, 0x11, 0x85, + 0x2c, 0xfc, 0x12, 0xac, 0xcd, 0x2f, 0x36, 0x9f, 0xc0, 0x51, 0x85, 0xb9, 0xba, 0x23, 0xf0, 0x6e, 0xa1, 0xcc, 0x4b, + 0xe9, 0x28, 0xf4, 0x28, 0x4c, 0x9d, 0xb1, 0xd5, 0x0b, 0xeb, 0x94, 0x21, 0x64, 0x23, 0x5b, 0x67, 0x89, 0x16, 0x65, + 0x83, 0x7f, 0x1c, 0xff, 0x6b, 0x90, 0xd8, 0xf6, 0x20, 0xd8, 0xde, 0x32, 0x65, 0xa7, 0xef, 0x2d, 0xbf, 0xfb, 0x44, + 0x4f, 0x74, 0x07, 0x1c, 0x06, 0x5c, 0x75, 0x7a, 0xee, 0xa7, 0x3e, 0xbc, 0xcb, 0x06, 0xff, 0x0d, 0x37, 0x7e, 0x0a, + 0x5f, 0xa5, 0x8f, 0x0a, 0xe7, 0xfa, 0xca, 0x7b, 0x43, 0x1e, 0x6d, 0x53, 0xf3, 0x3b, 0x4f, 0x54, 0xbc, 0x21, 0xdf, + 0x4d, 0xbc, 0x9a, 0x13, 0xef, 0xc9, 0xe7, 0x9c, 0x6f, 0xa7, 0x4e, 0xc0, 0x62, 0xb0, 0x07, 0x3b, 0x64, 0xd7, 0x7b, + 0x6d, 0x54, 0x8c, 0x5f, 0x99, 0xdb, 0xfb, 0x1f, 0x59, 0xef, 0x65, 0x11, 0x0d, 0x74, 0x03, 0x98, 0xc0, 0x69, 0xeb, + 0x10, 0xe5, 0x86, 0x2c, 0xb1, 0xec, 0x50, 0xa5, 0x89, 0x0e, 0x15, 0x21, 0x5d, 0x02, 0xb0, 0x7c, 0xe2, 0xf8, 0xc3, + 0x8a, 0xd3, 0x4a, 0xd2, 0x60, 0x88, 0xb5, 0x98, 0xdd, 0xa6, 0xd3, 0xfa, 0x71, 0xca, 0xe4, 0x5f, 0x01, 0xe3, 0x75, + 0x82, 0xb7, 0x48, 0x7f, 0xbe, 0x7c, 0x67, 0xf9, 0x39, 0xd1, 0x6f, 0xe4, 0x42, 0xff, 0x53, 0xf8, 0xba, 0x90, 0x26, + 0xf5, 0x3a, 0xff, 0x6c, 0xa7, 0xfa, 0x1d, 0x4a, 0x4b, 0x96, 0x83, 0xbc, 0x54, 0xdf, 0xd7, 0x9d, 0xfe, 0x43, 0xf9, + 0xfa, 0xd8, 0xc9, 0x06, 0x82, 0x5b, 0x9e, 0xfd, 0x64, 0x45, 0x44, 0xcf, 0xb6, 0x3f, 0x70, 0x32, 0x93, 0xdc, 0xcd, + 0xf5, 0xc8, 0xea, 0x24, 0xab, 0x82, 0x87, 0xbd, 0x4a, 0xdf, 0x33, 0xd3, 0xc3, 0x3d, 0x37, 0xe5, 0x9f, 0x44, 0x2a, + 0xf0, 0x44, 0x43, 0x63, 0x33, 0x54, 0x23, 0x14, 0x8f, 0xd3, 0x80, 0xcd, 0x9f, 0x34, 0xaf, 0x07, 0x0d, 0x56, 0x2e, + 0x15, 0x28, 0xaa, 0xd6, 0x9e, 0xa0, 0x03, 0x53, 0x50, 0x38, 0xda, 0x12, 0x02, 0x54, 0xb0, 0x2c, 0x6a, 0x48, 0xf4, + 0x23, 0x0d, 0x56, 0xb8, 0xd1, 0xc1, 0xdf, 0x82, 0x15, 0x41, 0x50, 0xb7, 0x36, 0xe6, 0x75, 0x57, 0x63, 0x28, 0x8c, + 0xfa, 0x31, 0x98, 0xa0, 0xfc, 0x0d, 0xd4, 0x4b, 0x5b, 0x0c, 0x57, 0xab, 0x06, 0x7c, 0x50, 0xcd, 0x49, 0xbc, 0x6c, + 0xb6, 0x09, 0x9b, 0xdc, 0x20, 0x65, 0x91, 0xc3, 0x1e, 0xfa, 0x04, 0xd5, 0x51, 0xa4, 0x72, 0x11, 0x17, 0xb3, 0xe6, + 0xc2, 0x6c, 0x4a, 0x76, 0xf3, 0xc0, 0x65, 0x6f, 0xe4, 0x99, 0x44, 0xaf, 0xf6, 0xfe, 0x1b, 0x89, 0xe8, 0x80, 0x25, + 0x40, 0xbc, 0x62, 0x61, 0xca, 0x60, 0x60, 0x08, 0xd1, 0xb6, 0x68, 0x1c, 0x8c, 0x5e, 0xf3, 0xe5, 0x6a, 0x31, 0xdf, + 0xcd, 0x66, 0x24, 0x1b, 0x8d, 0x7e, 0x2d, 0xa0, 0x55, 0x3d, 0x6d, 0xfa, 0x37, 0x2c, 0xee, 0x27, 0xf9, 0xe1, 0x53, + 0xef, 0x3c, 0x8b, 0xe8, 0xa9, 0x07, 0xf8, 0xf2, 0x3c, 0x10, 0xc2, 0xf4, 0xfc, 0x05, 0xf4, 0x40, 0x88, 0xb6, 0x31, + 0x17, 0x96, 0x3c, 0x52, 0xe5, 0x7f, 0x5e, 0x95, 0x4f, 0xb0, 0xa0, 0x0e, 0x4d, 0xc2, 0x44, 0x01, 0xb3, 0x46, 0xce, + 0x62, 0xf3, 0x19, 0xf3, 0xbc, 0x4e, 0xb3, 0x77, 0x9d, 0xc4, 0x0d, 0xcb, 0x73, 0xf9, 0x6b, 0xcc, 0x13, 0xae, 0x1f, + 0xb2, 0x33, 0x2c, 0xea, 0x44, 0xd5, 0x80, 0x5f, 0x96, 0x16, 0x3f, 0x81, 0xd6, 0xa5, 0x81, 0x90, 0x58, 0x79, 0x85, + 0xcd, 0x63, 0xa9, 0xd2, 0x37, 0xe4, 0x35, 0xd2, 0x1d, 0x0e, 0x9e, 0x8f, 0xe1, 0xbe, 0x3b, 0xc0, 0x73, 0x52, 0xfd, + 0xfc, 0x89, 0x78, 0x4c, 0x04, 0x61, 0x1b, 0x84, 0xe8, 0xf6, 0xe5, 0x3a, 0xbd, 0xfd, 0x6d, 0x34, 0xe6, 0x46, 0x69, + 0x25, 0xdc, 0x3a, 0xb9, 0xea, 0xc4, 0x78, 0x79, 0x89, 0x9a, 0x13, 0xb7, 0xd3, 0xce, 0xe3, 0x20, 0x52, 0x5a, 0x8d, + 0x65, 0x1b, 0xe3, 0x34, 0x45, 0xe1, 0x91, 0x47, 0x02, 0x76, 0xe4, 0x25, 0x9c, 0x04, 0x54, 0xff, 0x63, 0x7c, 0xe6, + 0x9d, 0x25, 0xb0, 0x02, 0x89, 0x3f, 0x5f, 0xdc, 0x7a, 0xd4, 0xff, 0x33, 0x68, 0xad, 0x7a, 0x26, 0xbd, 0x33, 0x49, + 0x26, 0x7c, 0x76, 0x37, 0xe0, 0x5d, 0xd7, 0x46, 0x4c, 0x3e, 0x51, 0x31, 0x36, 0x20, 0xb5, 0xdf, 0xc6, 0xbe, 0x36, + 0xa3, 0xf4, 0xe6, 0x23, 0x7a, 0x06, 0xae, 0x7e, 0x44, 0xb8, 0xac, 0xd7, 0xd6, 0x7e, 0x07, 0x02, 0x74, 0x82, 0xe5, + 0x74, 0xe0, 0xb4, 0xcb, 0x17, 0xed, 0x93, 0x30, 0x5a, 0x00, 0xa9, 0xdc, 0x40, 0x66, 0x3c, 0xa2, 0x3a, 0x93, 0x31, + 0x36, 0x49, 0x8f, 0x1e, 0x74, 0xc2, 0xee, 0xdf, 0x01, 0x6b, 0x79, 0xc5, 0xb1, 0x76, 0xee, 0x20, 0x78, 0x92, 0x9c, + 0xbc, 0xaa, 0x67, 0x17, 0x6c, 0x69, 0x19, 0xcb, 0x43, 0x7f, 0x1e, 0x82, 0x98, 0x2e, 0xef, 0x6d, 0x23, 0x28, 0xa1, + 0x72, 0xf5, 0x07, 0x41, 0xa1, 0xcf, 0xfa, 0x17, 0x5b, 0x65, 0x53, 0x9d, 0xc7, 0x3e, 0xec, 0xbd, 0xeb, 0xab, 0xc2, + 0xc9, 0x45, 0xf3, 0x7e, 0x14, 0x87, 0x54, 0x75, 0x54, 0xbe, 0xb5, 0x58, 0xf6, 0xda, 0xec, 0x64, 0xa1, 0x3d, 0xf2, + 0x45, 0xfb, 0xd4, 0x1a, 0xb4, 0xd2, 0xb2, 0x28, 0xa4, 0xcd, 0x5c, 0xf4, 0xce, 0x67, 0xcc, 0x22, 0x8e, 0x88, 0xc0, + 0x72, 0xeb, 0x17, 0xf9, 0x23, 0xb6, 0x74, 0x44, 0x59, 0xf8, 0x46, 0x68, 0xea, 0x98, 0x93, 0x87, 0x13, 0x70, 0x5b, + 0x19, 0xde, 0x66, 0x20, 0x46, 0xb5, 0xc8, 0x21, 0x02, 0xfd, 0x8b, 0x63, 0x89, 0x38, 0x57, 0xbf, 0x50, 0x63, 0xe4, + 0x42, 0x0d, 0x42, 0x88, 0x5e, 0x0b, 0x65, 0xe6, 0xe3, 0xbc, 0x4b, 0xb2, 0x36, 0x66, 0x5f, 0xa1, 0x55, 0x63, 0x66, + 0xb6, 0x7a, 0x38, 0xb0, 0x45, 0xd0, 0xed, 0x25, 0x7e, 0x3b, 0x3b, 0x08, 0xdf, 0x4f, 0x45, 0x2e, 0xae, 0x05, 0x73, + 0xb1, 0x8f, 0x53, 0xe3, 0xd3, 0xfd, 0x87, 0x81, 0x62, 0x04, 0x87, 0xab, 0xf2, 0x8a, 0xd6, 0xb3, 0xe1, 0xfd, 0xc0, + 0xd7, 0xb1, 0x39, 0x26, 0xf3, 0xcc, 0x38, 0x58, 0xb1, 0x76, 0xc1, 0xbb, 0x1a, 0x26, 0xac, 0x22, 0x46, 0xb8, 0x5c, + 0x35, 0xc5, 0xda, 0x7c, 0x06, 0xeb, 0x23, 0x48, 0xe2, 0xca, 0x57, 0xe8, 0x8c, 0x0c, 0x0e, 0x66, 0x35, 0x1a, 0xf4, + 0xf3, 0xbe, 0xb4, 0xee, 0x11, 0x08, 0x73, 0x01, 0xb8, 0x7b, 0x73, 0x41, 0x81, 0x1c, 0x40, 0x76, 0xdf, 0x47, 0x00, + 0x19, 0x09, 0xcc, 0x4c, 0x24, 0x48, 0xd2, 0xaa, 0xb5, 0x8f, 0x79, 0x71, 0x09, 0x89, 0x1e, 0x02, 0x82, 0x59, 0x2b, + 0x77, 0x89, 0xea, 0x95, 0xd8, 0x9c, 0x30, 0x04, 0x5a, 0x7b, 0x56, 0x44, 0x4f, 0xd9, 0xfd, 0xab, 0x23, 0x10, 0xfe, + 0xa9, 0xb0, 0x78, 0xd6, 0x39, 0x53, 0x8c, 0xe7, 0x91, 0x65, 0xb6, 0xe0, 0xdf, 0x16, 0x96, 0x8b, 0xf7, 0x50, 0xcc, + 0xa1, 0x1b, 0x93, 0x39, 0x09, 0xbb, 0xef, 0x71, 0x50, 0x12, 0xa8, 0x7f, 0x14, 0xe6, 0x6e, 0x9c, 0xa3, 0x18, 0x3b, + 0x19, 0xe7, 0x12, 0x6a, 0xc5, 0x52, 0xb3, 0x11, 0x58, 0x73, 0xf2, 0x5c, 0x98, 0x4c, 0x2d, 0xf5, 0x49, 0x85, 0x12, + 0x76, 0x66, 0x4a, 0x52, 0x26, 0xe7, 0x45, 0xc1, 0x51, 0x53, 0x51, 0x99, 0xe2, 0x20, 0x94, 0x9f, 0xce, 0xfa, 0xc5, + 0xee, 0xf9, 0x11, 0xdb, 0xf1, 0x6a, 0x70, 0xdb, 0x90, 0xa9, 0x51, 0x53, 0xe0, 0xcf, 0x8c, 0x87, 0xe9, 0xff, 0xe4, + 0x20, 0x9d, 0x87, 0xf0, 0xce, 0xf4, 0xcb, 0x29, 0xb7, 0x81, 0x18, 0x3f, 0xd0, 0xc2, 0x5b, 0x5a, 0x8d, 0x12, 0xa9, + 0xff, 0x4a, 0xe2, 0x73, 0x74, 0xc2, 0x4a, 0x28, 0x25, 0x89, 0x4b, 0x38, 0xa4, 0xba, 0x63, 0xcc, 0xa8, 0x8c, 0x6e, + 0x41, 0x14, 0x34, 0xae, 0xd3, 0x88, 0x2c, 0xdc, 0x2a, 0x3a, 0xba, 0xf8, 0xc5, 0x9f, 0xd9, 0x87, 0xc1, 0x97, 0xc1, + 0x81, 0x40, 0x8e, 0x06, 0x41, 0xfb, 0xc3, 0x2b, 0x6c, 0x78, 0xd9, 0x79, 0xa1, 0x8e, 0x05, 0xe2, 0x51, 0xa7, 0x5e, + 0x42, 0x26, 0x21, 0xff, 0xd0, 0xa9, 0x12, 0x08, 0xe4, 0xcd, 0x0e, 0xab, 0xdf, 0xa0, 0x9f, 0x77, 0xda, 0x2d, 0x37, + 0x75, 0x13, 0x7a, 0x22, 0x84, 0x00, 0x48, 0x6c, 0x8d, 0x04, 0x91, 0xb7, 0x1a, 0x44, 0x52, 0x1d, 0x76, 0x5f, 0xe9, + 0x85, 0x20, 0xe0, 0x46, 0x6d, 0x34, 0x1a, 0x21, 0xf3, 0x0a, 0xb6, 0xc3, 0x4c, 0xc0, 0x38, 0x97, 0x51, 0xc6, 0x2f, + 0xf0, 0x50, 0x78, 0x25, 0x09, 0xbe, 0xa6, 0x4c, 0x7b, 0x0e, 0xa2, 0x5b, 0x6e, 0x2e, 0x3a, 0x1e, 0xc0, 0x20, 0x7a, + 0x02, 0xe6, 0x4f, 0xe6, 0xbf, 0x65, 0x67, 0xa4, 0x68, 0x20, 0x57, 0x7b, 0x87, 0x4b, 0xc6, 0xfc, 0xa9, 0xe4, 0x49, + 0x75, 0x4b, 0x81, 0x21, 0x72, 0xf1, 0xb2, 0xeb, 0x8f, 0x61, 0xae, 0xa8, 0x1d, 0xe0, 0x7d, 0xa2, 0x61, 0xf5, 0x62, + 0x3d, 0xa9, 0x6f, 0x8d, 0xc4, 0x7f, 0x51, 0x19, 0x1b, 0xe3, 0xa8, 0xf4, 0x42, 0x3c, 0xe9, 0x6e, 0xef, 0xac, 0xde, + 0x45, 0xae, 0xd6, 0xc4, 0x83, 0xc1, 0x5a, 0xb7, 0x42, 0x2b, 0xa7, 0xb6, 0xfc, 0x36, 0x87, 0x4b, 0x5f, 0x99, 0xb8, + 0x35, 0x5d, 0x20, 0x86, 0x82, 0xd2, 0xf1, 0xb8, 0xfc, 0x0c, 0x4f, 0x76, 0xf2, 0xa4, 0x33, 0x66, 0x66, 0x21, 0x3e, + 0xdd, 0xd9, 0x3c, 0xd3, 0x1f, 0x87, 0x2c, 0x21, 0x65, 0xaa, 0x9b, 0x9f, 0xe6, 0x85, 0x2f, 0x66, 0x3e, 0xcf, 0x27, + 0x9c, 0x71, 0x0b, 0x2b, 0xb4, 0x5e, 0x33, 0x7e, 0x4e, 0x18, 0x0e, 0xef, 0x2c, 0x4d, 0x94, 0x25, 0xa3, 0xe1, 0x1f, + 0x3f, 0xdf, 0x2d, 0x6d, 0xbe, 0xf3, 0xd3, 0xf1, 0x76, 0x12, 0x93, 0x02, 0x1b, 0xa5, 0x03, 0xc1, 0xf7, 0x80, 0xb2, + 0x97, 0xef, 0x6c, 0xcc, 0xe4, 0x7e, 0xd0, 0x41, 0x81, 0x61, 0x0b, 0x81, 0x0b, 0xad, 0x3f, 0xe4, 0x3d, 0xd6, 0x3b, + 0x55, 0x9e, 0xed, 0xa7, 0xe9, 0xbe, 0x2a, 0x0a, 0x05, 0x3f, 0xbb, 0xf5, 0xd8, 0x5b, 0x07, 0xcd, 0x91, 0x96, 0x30, + 0x79, 0x26, 0xd5, 0xe4, 0x67, 0x62, 0xaa, 0x08, 0x96, 0xbf, 0xfe, 0x32, 0xb9, 0xc8, 0x5d, 0xaf, 0x71, 0x10, 0xa6, + 0x66, 0xc2, 0xd4, 0xaf, 0x95, 0xb7, 0x23, 0xf5, 0x4f, 0xe9, 0xbb, 0x2b, 0x50, 0x57, 0x64, 0x2d, 0x40, 0xa4, 0x34, + 0x0c, 0xa9, 0x56, 0x87, 0x15, 0xa7, 0x6e, 0x83, 0x95, 0x1d, 0xbe, 0x80, 0x1b, 0x25, 0x67, 0x09, 0x51, 0xd1, 0xa6, + 0x26, 0x03, 0x87, 0x41, 0xa0, 0x30, 0x54, 0x14, 0x87, 0x47, 0x58, 0x7c, 0xd9, 0xe1, 0x45, 0xd3, 0x45, 0xb1, 0xe1, + 0xd5, 0x7e, 0xa2, 0x8c, 0x33, 0xb6, 0x8b, 0x0a, 0x40, 0x2d, 0x22, 0xfc, 0xf8, 0x34, 0xc0, 0xca, 0x9f, 0xf0, 0xb1, + 0x7b, 0x12, 0x96, 0x1e, 0x74, 0x29, 0x6a, 0xd9, 0x52, 0x4a, 0x53, 0x5b, 0xd4, 0x35, 0xce, 0x50, 0x71, 0xec, 0xf0, + 0xc8, 0x7a, 0x84, 0xf1, 0xdc, 0xe9, 0x22, 0xf8, 0x2c, 0x36, 0xc8, 0x23, 0x95, 0x20, 0xca, 0xdd, 0x32, 0x6e, 0x3d, + 0xe8, 0x63, 0x2e, 0x07, 0x61, 0xfb, 0x0c, 0xa5, 0x72, 0x11, 0x2b, 0x09, 0x2e, 0x83, 0xf2, 0x8f, 0x1e, 0xaa, 0x4c, + 0x74, 0xf2, 0x9e, 0x3a, 0xb6, 0x1d, 0x68, 0xac, 0xe9, 0x21, 0x89, 0x36, 0x6e, 0xd5, 0x62, 0x5c, 0x31, 0x75, 0x7a, + 0x6e, 0x89, 0x29, 0x41, 0x7e, 0x73, 0x39, 0xda, 0x9a, 0xba, 0x04, 0x62, 0x49, 0x89, 0xf8, 0x94, 0x4b, 0xfe, 0xae, + 0xeb, 0x24, 0xbe, 0x60, 0x2b, 0xb2, 0x64, 0xdc, 0xaa, 0xdd, 0x46, 0x5a, 0xcf, 0x05, 0x21, 0xf3, 0x2f, 0x35, 0x08, + 0x07, 0x9f, 0x2e, 0x58, 0xae, 0xc5, 0x47, 0xeb, 0xaf, 0x69, 0xd2, 0xa6, 0x07, 0x15, 0xb4, 0xd4, 0x41, 0x25, 0x2f, + 0x6b, 0xe6, 0x11, 0x57, 0xb3, 0x30, 0xbe, 0xa6, 0xdf, 0x5d, 0x72, 0x50, 0xd9, 0x19, 0x04, 0xf1, 0xe9, 0x20, 0xad, + 0x15, 0x79, 0xaa, 0x70, 0xaf, 0xd4, 0x5f, 0x89, 0x53, 0x0d, 0xa4, 0xf3, 0x02, 0x56, 0x08, 0xb9, 0x8e, 0x1f, 0xb8, + 0xda, 0x44, 0x80, 0x65, 0x99, 0xde, 0x6f, 0x2e, 0xa5, 0xd4, 0xf9, 0x01, 0xc0, 0xb3, 0xed, 0xa2, 0x5f, 0xa0, 0x39, + 0x01, 0x8c, 0x28, 0x50, 0x77, 0x21, 0xde, 0xea, 0x86, 0x8c, 0xb1, 0xfd, 0x92, 0xf6, 0xb0, 0x65, 0x3b, 0x06, 0x48, + 0x80, 0x91, 0x65, 0x58, 0xdc, 0x7b, 0x94, 0x8a, 0xd6, 0x74, 0x66, 0x63, 0x54, 0x95, 0xb4, 0x62, 0x7f, 0x79, 0x93, + 0xc8, 0xec, 0xd7, 0x8d, 0x8b, 0xa6, 0xbc, 0xb6, 0x48, 0x25, 0x8a, 0x13, 0x64, 0x65, 0xaa, 0xc8, 0x28, 0x8c, 0xb5, + 0xa3, 0x64, 0x81, 0xc7, 0xc5, 0x9e, 0x30, 0xa6, 0xff, 0x34, 0x15, 0x28, 0xdf, 0xbf, 0x6b, 0x1a, 0xa9, 0x50, 0x21, + 0xec, 0xc9, 0x72, 0x1a, 0x5b, 0xd1, 0xa7, 0xe2, 0x64, 0x4d, 0x22, 0xfd, 0xb7, 0x01, 0x06, 0x53, 0x1b, 0xf0, 0xe4, + 0x06, 0x29, 0x96, 0x10, 0x3e, 0x29, 0xdd, 0x67, 0x4d, 0x74, 0xa3, 0x32, 0xc0, 0x99, 0x1b, 0x37, 0x67, 0x2b, 0x0d, + 0x5c, 0xd9, 0x3a, 0x08, 0x53, 0x61, 0xe1, 0xce, 0xa6, 0x41, 0x8a, 0x4b, 0x8e, 0x94, 0x4c, 0xbf, 0x16, 0xc4, 0x8b, + 0x23, 0xfc, 0x2a, 0x7f, 0x72, 0x8b, 0x4c, 0x57, 0xa8, 0x2a, 0xa5, 0x53, 0xcc, 0x61, 0x7a, 0x98, 0x96, 0x2e, 0xe9, + 0xe5, 0x84, 0x77, 0x9e, 0x1f, 0xce, 0x05, 0x3d, 0x6d, 0xd5, 0x6a, 0xd5, 0x50, 0x18, 0xd0, 0x49, 0x47, 0x80, 0x78, + 0xd4, 0xf4, 0x97, 0xf0, 0xba, 0x92, 0x9b, 0x17, 0x71, 0x4d, 0x81, 0xe3, 0xb4, 0x7d, 0xed, 0xdc, 0x5f, 0x2e, 0xab, + 0x85, 0x1c, 0x24, 0x60, 0x2c, 0xa3, 0x0f, 0x81, 0xdc, 0xe9, 0xe9, 0xb3, 0xd2, 0xb2, 0x46, 0xd6, 0x27, 0x9b, 0x2d, + 0x3e, 0x79, 0x3f, 0x78, 0x81, 0x25, 0xdb, 0xe0, 0xe1, 0xad, 0xbe, 0xa6, 0xed, 0x64, 0x83, 0xb0, 0x16, 0x8d, 0x83, + 0x28, 0x56, 0xa0, 0x1d, 0xd9, 0x8a, 0xac, 0xcb, 0x9c, 0x64, 0x5f, 0x5f, 0xe4, 0x3f, 0xcf, 0x8a, 0x50, 0xa2, 0x05, + 0x8d, 0x9c, 0xc3, 0x1a, 0x2e, 0xe8, 0xa0, 0x34, 0x01, 0x83, 0x32, 0x00, 0x1b, 0x65, 0xec, 0xea, 0x34, 0x14, 0xf0, + 0x31, 0x46, 0x14, 0xca, 0x99, 0xcb, 0xd9, 0x5b, 0x5c, 0x58, 0x8b, 0x53, 0x66, 0x56, 0x9a, 0x7e, 0xa6, 0x85, 0xf9, + 0x7a, 0x23, 0x49, 0x10, 0xd9, 0x5a, 0x4e, 0x57, 0xae, 0x4b, 0xf4, 0xf4, 0x28, 0x28, 0x50, 0x59, 0x49, 0xc9, 0xb9, + 0x7c, 0x5e, 0xa1, 0xb3, 0x92, 0xf2, 0x2b, 0x4b, 0x4c, 0xc0, 0xd8, 0x26, 0x76, 0x8f, 0x9f, 0xcb, 0xca, 0xa7, 0x3c, + 0x66, 0x7c, 0xfa, 0xd3, 0xb6, 0xbe, 0x53, 0x58, 0x40, 0xa0, 0xe6, 0x0f, 0x6b, 0xae, 0xf4, 0xda, 0x8c, 0x81, 0x58, + 0x38, 0x31, 0xc0, 0xe7, 0xf0, 0x51, 0x01, 0xa3, 0xd4, 0x6c, 0x07, 0x13, 0x29, 0xd1, 0x92, 0x90, 0xc8, 0xb4, 0x1d, + 0xb4, 0x3e, 0x8b, 0x41, 0x59, 0x31, 0xc1, 0x35, 0xc5, 0x15, 0x6f, 0x57, 0x3b, 0x6a, 0x68, 0x5d, 0x23, 0x83, 0x78, + 0xa8, 0xa4, 0x3f, 0x3b, 0xde, 0x8f, 0x50, 0x10, 0x67, 0xa5, 0xc2, 0x5b, 0x9c, 0x6d, 0xed, 0xf8, 0x19, 0x05, 0xf7, + 0xc2, 0x5b, 0xb0, 0x31, 0x86, 0xa6, 0x6c, 0xb2, 0x62, 0xff, 0x6c, 0x06, 0xc4, 0x5e, 0xdf, 0x46, 0x86, 0xbb, 0xcd, + 0x8a, 0xc3, 0x07, 0xb3, 0xe5, 0x1f, 0xb1, 0xc7, 0xee, 0x3e, 0x79, 0x51, 0xac, 0x71, 0x6a, 0x0f, 0x6b, 0xc6, 0xb7, + 0xdf, 0x5b, 0x2e, 0x48, 0x8f, 0xe6, 0xda, 0x12, 0xd1, 0x13, 0xd3, 0x13, 0x0c, 0x0b, 0xa4, 0xc8, 0xea, 0x55, 0xca, + 0x54, 0xdb, 0x1b, 0xd6, 0x5e, 0x5a, 0x72, 0x55, 0x68, 0x0f, 0xc5, 0xec, 0xb2, 0x97, 0xe7, 0xb2, 0xe3, 0xeb, 0xe2, + 0xa3, 0x32, 0x6b, 0x8e, 0x95, 0x5f, 0x08, 0x53, 0x61, 0xaf, 0x0a, 0x72, 0x4a, 0x07, 0xeb, 0x08, 0xd5, 0x61, 0x98, + 0x2a, 0x1e, 0x3d, 0xb7, 0x25, 0xa4, 0x06, 0xbc, 0x1f, 0x5e, 0xe4, 0xf9, 0x55, 0xb4, 0xab, 0x00, 0x86, 0x4b, 0x01, + 0x07, 0x8f, 0x26, 0x08, 0x5c, 0x92, 0x10, 0x78, 0x9b, 0x41, 0x1f, 0xae, 0xdf, 0xbc, 0x7d, 0x0d, 0x65, 0x96, 0x33, + 0x6c, 0xa9, 0x38, 0xfb, 0x40, 0x7a, 0xb6, 0x2b, 0x92, 0xfa, 0x9e, 0x9a, 0xad, 0xb8, 0x35, 0xa6, 0x29, 0x12, 0x03, + 0xca, 0xae, 0x5a, 0xd3, 0xbd, 0x52, 0xd7, 0xf4, 0xec, 0x3c, 0x58, 0xd7, 0x12, 0xed, 0x0a, 0xa2, 0x52, 0x7f, 0x40, + 0xa2, 0xaf, 0x14, 0xda, 0x39, 0xb6, 0xae, 0x87, 0x3a, 0xaa, 0xa0, 0x5a, 0xc7, 0x08, 0xa9, 0xb6, 0xa5, 0x54, 0xfd, + 0x52, 0xeb, 0x70, 0xe9, 0x35, 0xc1, 0x70, 0xf4, 0xe0, 0x61, 0xbc, 0x4b, 0xd4, 0xa4, 0xdc, 0x5f, 0xf8, 0x12, 0xd6, + 0xdd, 0xee, 0x35, 0xf6, 0x7f, 0x51, 0xcf, 0xd6, 0x45, 0x37, 0xf1, 0x3e, 0xc8, 0xff, 0x57, 0x0f, 0x18, 0x99, 0x3c, + 0x7c, 0x38, 0xae, 0xb2, 0xde, 0x66, 0x31, 0x35, 0x25, 0x7f, 0x9d, 0x6b, 0xfa, 0x6a, 0xa5, 0x9d, 0x9a, 0xbb, 0x3b, + 0x39, 0xfb, 0x0d, 0x9b, 0x13, 0x87, 0x30, 0x4c, 0x94, 0xc8, 0xdd, 0x95, 0xc9, 0xa6, 0xeb, 0x72, 0xa9, 0xc1, 0x77, + 0x4b, 0x83, 0x90, 0xbc, 0x46, 0xe3, 0x87, 0x30, 0xcb, 0xa5, 0x44, 0x6c, 0x00, 0xcf, 0x9c, 0x99, 0xa8, 0x87, 0x8d, + 0x2d, 0x25, 0x88, 0xb2, 0x2a, 0x16, 0x5f, 0x65, 0x6a, 0xe7, 0xa8, 0x2a, 0x8d, 0xe2, 0xb9, 0x7b, 0xc3, 0x03, 0x86, + 0x64, 0xe2, 0xec, 0x57, 0xd0, 0xbb, 0xd0, 0x40, 0xba, 0x1d, 0xbb, 0x1f, 0xf0, 0x13, 0x29, 0xd1, 0xe7, 0xc1, 0x58, + 0x80, 0xd8, 0x22, 0x99, 0x65, 0x50, 0x28, 0x7e, 0x71, 0x2b, 0x5c, 0x25, 0x6a, 0x33, 0xde, 0xb3, 0x97, 0x2a, 0x6e, + 0x03, 0x33, 0xab, 0x96, 0x8f, 0x4c, 0x85, 0x10, 0x7b, 0xd5, 0x89, 0x7a, 0x96, 0x50, 0x36, 0xa3, 0x1e, 0xfe, 0xbe, + 0xa3, 0x1c, 0x8d, 0x28, 0xed, 0x68, 0x50, 0x8d, 0x85, 0xf7, 0x3b, 0x63, 0x7c, 0x67, 0xb6, 0x3f, 0x46, 0x88, 0x39, + 0xaf, 0x88, 0x83, 0x43, 0x38, 0x61, 0x78, 0xb5, 0xb5, 0x1c, 0x95, 0x21, 0x28, 0xdc, 0xf3, 0x4d, 0xcf, 0xcd, 0x46, + 0x59, 0x88, 0x19, 0x6f, 0xeb, 0xbc, 0x8f, 0x73, 0x19, 0xb9, 0x91, 0x99, 0x69, 0x18, 0x9b, 0x92, 0xe0, 0x1e, 0x70, + 0xa1, 0x24, 0xb0, 0x9c, 0xcb, 0xbf, 0x04, 0xc3, 0x9c, 0xd8, 0xfa, 0x07, 0xb6, 0xce, 0xf4, 0x3e, 0x1a, 0xc8, 0x55, + 0x8b, 0xfc, 0x8f, 0x76, 0xa5, 0xe9, 0x5f, 0x3a, 0x6b, 0x35, 0xcf, 0xd8, 0xc0, 0x0a, 0x1f, 0x50, 0x1d, 0x38, 0x40, + 0xaa, 0x17, 0x25, 0x41, 0xdc, 0x14, 0x5a, 0xf4, 0x32, 0x57, 0x9d, 0x68, 0xb4, 0x57, 0x6c, 0xc5, 0x38, 0xaf, 0xfd, + 0x97, 0xdb, 0x3d, 0x11, 0x73, 0x14, 0xa9, 0xa3, 0x86, 0x64, 0x2b, 0xf6, 0x87, 0xab, 0x4c, 0xe5, 0x9d, 0xe7, 0x2b, + 0x5f, 0xc1, 0x4b, 0xed, 0xef, 0xc8, 0x30, 0x24, 0xea, 0x42, 0xf5, 0xac, 0x80, 0xd7, 0xc7, 0x3f, 0x82, 0x7b, 0xa3, + 0x80, 0x28, 0xf8, 0x59, 0x21, 0xec, 0x9e, 0xcd, 0x6e, 0x3d, 0x1e, 0xfc, 0x3a, 0xae, 0xad, 0x75, 0x83, 0x67, 0x8a, + 0xff, 0xf8, 0x60, 0x15, 0x0e, 0x79, 0xe0, 0x7c, 0xa2, 0x77, 0xf7, 0xf3, 0xcb, 0x2f, 0x35, 0x7a, 0xfe, 0x42, 0xd8, + 0xcb, 0x56, 0x3a, 0x50, 0xd7, 0x28, 0x7e, 0xe2, 0x70, 0xac, 0x14, 0x35, 0xfc, 0x63, 0x9c, 0x38, 0x1f, 0xae, 0x8f, + 0x92, 0x69, 0x01, 0x16, 0x62, 0x1a, 0xba, 0x25, 0x71, 0x5e, 0x14, 0x67, 0xbd, 0xbb, 0x80, 0x9a, 0x4e, 0x7b, 0x80, + 0x52, 0x52, 0xcc, 0x13, 0x29, 0xd1, 0x5d, 0xfc, 0x9e, 0x9b, 0x4e, 0xee, 0xdc, 0xbe, 0x38, 0xac, 0x0f, 0x86, 0x6d, + 0x37, 0x19, 0xe3, 0x4f, 0x55, 0x9e, 0x30, 0xe2, 0x85, 0xb1, 0x2a, 0xe4, 0xf7, 0x08, 0x03, 0xfa, 0x7d, 0x38, 0x51, + 0x11, 0x7d, 0x3f, 0x00, 0xb8, 0xa7, 0x6e, 0x02, 0xaa, 0xf5, 0xf9, 0x4d, 0xef, 0x0a, 0x88, 0x26, 0x78, 0x51, 0xc9, + 0x6b, 0x80, 0x84, 0x5c, 0x5c, 0x9b, 0x72, 0x78, 0x37, 0x54, 0x24, 0xf4, 0xa1, 0x74, 0xce, 0xf4, 0x46, 0x06, 0x88, + 0xca, 0x31, 0x22, 0xbc, 0xe9, 0x4e, 0xf4, 0xa6, 0xbe, 0x87, 0x3f, 0x37, 0x63, 0xcf, 0x05, 0x86, 0x75, 0x6b, 0x7a, + 0xa6, 0x9f, 0x81, 0x6a, 0xc6, 0x9f, 0x7b, 0xd1, 0xd2, 0x53, 0xdb, 0x9a, 0x55, 0x8c, 0xc3, 0x5f, 0xcc, 0x83, 0x91, + 0xac, 0x2f, 0x2e, 0x22, 0xcc, 0x08, 0x6e, 0x56, 0x51, 0x2f, 0x2f, 0x59, 0xc2, 0xec, 0x6c, 0xd5, 0x38, 0xd0, 0x8c, + 0xb6, 0xa5, 0x07, 0xd7, 0xf9, 0x21, 0x96, 0xf1, 0x50, 0x1d, 0x5a, 0x3b, 0x8e, 0x6b, 0x9f, 0x41, 0x71, 0xb5, 0xc4, + 0x3f, 0x97, 0xf3, 0x25, 0xae, 0xf7, 0xcf, 0xfd, 0xb4, 0xd2, 0xdb, 0x54, 0xb3, 0x8f, 0xb9, 0xa5, 0x97, 0x24, 0xa4, + 0xef, 0x76, 0x18, 0xb0, 0x34, 0x19, 0x4c, 0xbe, 0x21, 0x39, 0xb0, 0x41, 0x95, 0x7c, 0x7a, 0xa0, 0xe7, 0x42, 0x07, + 0x2b, 0xa0, 0x1d, 0xf8, 0x0d, 0xcf, 0xeb, 0xb5, 0x10, 0x39, 0xdc, 0x20, 0x99, 0x00, 0x9d, 0x91, 0xc9, 0x85, 0xac, + 0xaa, 0x30, 0x81, 0x68, 0x2e, 0x21, 0x1a, 0xd4, 0x6d, 0x03, 0x67, 0x7c, 0x30, 0x29, 0x61, 0x3a, 0xdd, 0x2d, 0x95, + 0xce, 0x2b, 0x92, 0xa8, 0xeb, 0xfd, 0x30, 0xde, 0x0f, 0xcf, 0x3c, 0xc2, 0xbc, 0xdc, 0xee, 0x75, 0x91, 0xe5, 0xe5, + 0xd4, 0x42, 0xbb, 0x8f, 0xd9, 0xd1, 0x34, 0x5c, 0xea, 0x2e, 0xd8, 0x79, 0x60, 0x52, 0x5d, 0xd8, 0x83, 0x7d, 0x94, + 0x22, 0x4c, 0x73, 0xc9, 0xc8, 0xb2, 0xe8, 0xd2, 0x0c, 0xde, 0xe9, 0x00, 0x4f, 0x4b, 0xc4, 0x93, 0x20, 0xd2, 0xa4, + 0x17, 0x1b, 0x56, 0xd1, 0xe0, 0x6e, 0xd0, 0x9d, 0x19, 0x34, 0x54, 0x2c, 0x96, 0xea, 0xd1, 0x95, 0x72, 0x77, 0x62, + 0x69, 0x56, 0xd4, 0xf3, 0x81, 0x98, 0xec, 0xf9, 0x7a, 0x43, 0xaa, 0x14, 0x13, 0x16, 0xd1, 0xe8, 0xd3, 0x0f, 0x59, + 0xc5, 0x51, 0xc2, 0x62, 0xa5, 0xb8, 0xaa, 0xc8, 0xa9, 0xf1, 0xe6, 0x65, 0x56, 0x22, 0xed, 0xb0, 0x4c, 0x3c, 0x85, + 0x7c, 0x47, 0xd3, 0x4e, 0xcb, 0xac, 0xad, 0x62, 0x31, 0x7b, 0x02, 0x29, 0x11, 0x87, 0x75, 0x86, 0xb7, 0x65, 0x8e, + 0xd3, 0x60, 0x6d, 0xc9, 0xa9, 0x5f, 0xd0, 0x97, 0x30, 0xfb, 0x8c, 0xd5, 0x27, 0xa9, 0xd7, 0x91, 0x04, 0x28, 0xfe, + 0x4d, 0x1f, 0x04, 0x85, 0x5b, 0xfa, 0x7f, 0x7b, 0x6d, 0x38, 0x54, 0x0f, 0x75, 0xcf, 0x10, 0xab, 0x22, 0x15, 0xce, + 0xdd, 0x57, 0xe7, 0x93, 0x42, 0x3a, 0x99, 0x39, 0xe6, 0x91, 0x68, 0x2b, 0x2e, 0x07, 0x37, 0x2a, 0x23, 0x6a, 0x3a, + 0x7d, 0x50, 0x9d, 0xe1, 0xae, 0xde, 0xe7, 0x1a, 0xc2, 0xeb, 0x6a, 0x9f, 0xbb, 0xd3, 0x5b, 0xb1, 0xc5, 0x63, 0xae, + 0x4e, 0xdb, 0x89, 0x4b, 0xbb, 0xd4, 0xe9, 0x87, 0x23, 0xa8, 0xb8, 0x4c, 0xc4, 0x6c, 0x82, 0x0e, 0x2e, 0x8b, 0xa6, + 0x28, 0x75, 0xe9, 0x76, 0x92, 0x6b, 0x70, 0x07, 0x42, 0xaa, 0x72, 0x97, 0x19, 0x6e, 0xba, 0x10, 0x29, 0x3e, 0x93, + 0xae, 0x21, 0x92, 0xa2, 0x34, 0xbd, 0xe0, 0x34, 0x32, 0x72, 0xb7, 0x53, 0x99, 0x49, 0xeb, 0x90, 0x1a, 0xc7, 0x94, + 0x13, 0xf6, 0x32, 0x46, 0x70, 0xd0, 0xaa, 0x2f, 0x4b, 0x55, 0xe8, 0xfa, 0xa6, 0x67, 0xcb, 0x75, 0xfd, 0x87, 0x8f, + 0xc7, 0xcb, 0x51, 0x88, 0x2e, 0x6c, 0xaf, 0x94, 0x8e, 0x2c, 0xbd, 0x97, 0x8c, 0xb8, 0xe0, 0x50, 0xce, 0x5e, 0x0d, + 0x09, 0xb8, 0xa5, 0x57, 0x2c, 0xd2, 0xba, 0x71, 0x2d, 0xcb, 0xb4, 0x7b, 0xe5, 0x94, 0x49, 0x21, 0x56, 0xc6, 0x1a, + 0xc1, 0xfb, 0x69, 0xc4, 0xb0, 0xe9, 0x4d, 0xd8, 0x90, 0x4c, 0xcd, 0x5c, 0x6f, 0x28, 0x73, 0xf9, 0xa9, 0xf1, 0x23, + 0x36, 0x1a, 0x87, 0x60, 0xe8, 0xcc, 0x75, 0x1e, 0x0b, 0xe3, 0x0a, 0x66, 0x54, 0x23, 0xcb, 0x81, 0xb5, 0xd5, 0xda, + 0x0b, 0xb7, 0xa3, 0xde, 0x1c, 0x48, 0x7e, 0xe7, 0x65, 0xa6, 0x1a, 0xe3, 0xa0, 0xc5, 0x66, 0xed, 0x48, 0x23, 0x0a, + 0xbc, 0x78, 0x7a, 0x15, 0x41, 0xd1, 0xef, 0x49, 0x33, 0xc8, 0x41, 0x4b, 0xf5, 0xf5, 0xcf, 0x49, 0x89, 0xed, 0x98, + 0xa6, 0x05, 0x86, 0x59, 0xa5, 0x81, 0xbf, 0x26, 0x95, 0x86, 0x17, 0x36, 0x9f, 0x1f, 0xed, 0x12, 0xb9, 0xdc, 0xf3, + 0xac, 0xe6, 0x00, 0xc3, 0x74, 0xcc, 0x8d, 0x7f, 0x8f, 0xa2, 0x9f, 0x6c, 0x1c, 0x83, 0xd1, 0xd3, 0x2f, 0x4a, 0x3d, + 0x9b, 0x49, 0x7b, 0x5e, 0x53, 0x17, 0x70, 0x3c, 0x19, 0xe9, 0x00, 0x3c, 0x48, 0x27, 0x76, 0x1f, 0xc0, 0x25, 0x63, + 0x2f, 0x41, 0x17, 0xbb, 0xaf, 0x01, 0x48, 0xb6, 0x63, 0x8b, 0xdc, 0x8a, 0x91, 0xaf, 0x92, 0x4a, 0x79, 0x29, 0x7f, + 0x25, 0xb3, 0x11, 0xc0, 0xbe, 0x4a, 0x2f, 0x0f, 0xb8, 0x1b, 0xa5, 0xb7, 0x03, 0x82, 0xdd, 0x02, 0x61, 0xdf, 0x6d, + 0xd5, 0xa8, 0x81, 0xdd, 0x5f, 0x98, 0xb1, 0x69, 0x01, 0x1b, 0x19, 0xfa, 0xc3, 0xad, 0x4f, 0x94, 0x53, 0x10, 0x7e, + 0xff, 0xd2, 0xdc, 0x8d, 0x2b, 0x33, 0x18, 0x25, 0xb6, 0x43, 0x60, 0x3e, 0x53, 0xf9, 0x12, 0xe5, 0x27, 0xe1, 0xe5, + 0x6a, 0xd7, 0x9f, 0x95, 0x73, 0x29, 0xe6, 0xce, 0x35, 0xfc, 0x36, 0x1a, 0x3f, 0x2a, 0xed, 0x3a, 0xcf, 0xa2, 0x4b, + 0xdc, 0xe7, 0xfe, 0x3e, 0x80, 0x23, 0x6f, 0xcc, 0x87, 0x89, 0x7c, 0x27, 0x19, 0x56, 0x68, 0xf3, 0x76, 0x23, 0x3d, + 0xfc, 0xf6, 0x8d, 0xd4, 0x23, 0x7e, 0xac, 0x8a, 0xe0, 0xd7, 0x4d, 0x01, 0x6c, 0x82, 0x53, 0xcf, 0x5f, 0x37, 0xa9, + 0xe3, 0xc7, 0x4b, 0x48, 0xfa, 0x26, 0xcc, 0xdd, 0xbb, 0xd9, 0xe0, 0xe9, 0x10, 0x9e, 0x65, 0x44, 0x07, 0x03, 0x99, + 0x5b, 0x93, 0x1b, 0xf4, 0x5f, 0x30, 0xcd, 0xb7, 0x83, 0xc0, 0x26, 0x9e, 0x25, 0x15, 0x5f, 0x74, 0xf7, 0x36, 0x34, + 0x75, 0x10, 0x15, 0x0d, 0xc4, 0x25, 0x1b, 0xb8, 0xd9, 0x0a, 0xca, 0x73, 0x63, 0xa8, 0xb3, 0xe7, 0x88, 0xdd, 0x56, + 0xda, 0xbd, 0x95, 0x8b, 0x57, 0x94, 0xa8, 0x11, 0x50, 0x21, 0xe8, 0x2e, 0x7f, 0x28, 0xf7, 0x25, 0xdd, 0x59, 0x69, + 0xca, 0x5c, 0x24, 0x98, 0xd7, 0x05, 0x55, 0x3f, 0x80, 0x04, 0xb4, 0x0f, 0x09, 0xa8, 0xd0, 0x7d, 0xf9, 0x35, 0x93, + 0x79, 0xeb, 0x49, 0xac, 0xab, 0xf0, 0xc3, 0x00, 0x0e, 0xff, 0xa5, 0x21, 0x23, 0x21, 0x7b, 0xb9, 0x5f, 0xd7, 0x43, + 0xdd, 0xd2, 0x71, 0x1b, 0xab, 0x79, 0xa0, 0xac, 0x23, 0x1c, 0x27, 0x56, 0xdb, 0xef, 0x06, 0xa4, 0xe5, 0xb8, 0xbf, + 0xaa, 0xe9, 0xd2, 0x6e, 0x5e, 0x87, 0x61, 0x1d, 0xb6, 0x86, 0xe5, 0x17, 0xe6, 0x8a, 0x87, 0xf6, 0x1c, 0xfe, 0xdb, + 0x57, 0xc6, 0x97, 0x34, 0xfb, 0xbf, 0x15, 0x4f, 0x83, 0x44, 0xd3, 0x67, 0x29, 0x92, 0x30, 0x4a, 0xf7, 0x27, 0x12, + 0x25, 0x0d, 0x24, 0x72, 0x70, 0x2f, 0xdf, 0xd2, 0xf8, 0x57, 0xa5, 0x2c, 0x43, 0x87, 0xcb, 0x66, 0x07, 0x32, 0x6f, + 0x9d, 0xbb, 0xbf, 0x1c, 0x7a, 0x0b, 0x54, 0xe9, 0x14, 0x26, 0x2f, 0x3d, 0x5c, 0xb1, 0x65, 0xcf, 0x62, 0xe8, 0xa7, + 0x60, 0x2a, 0x46, 0xb2, 0x19, 0x26, 0xe6, 0x2a, 0x85, 0xc8, 0x2f, 0x8f, 0x3a, 0xb9, 0xbb, 0xe5, 0x6f, 0x6e, 0x7d, + 0xbc, 0x28, 0x79, 0x63, 0x76, 0x66, 0x7b, 0x3e, 0x76, 0xfb, 0x3d, 0x2b, 0x72, 0x27, 0xec, 0x74, 0xf4, 0x0e, 0xb9, + 0xe6, 0x4e, 0x68, 0x2a, 0x60, 0xb9, 0x38, 0x4f, 0xad, 0xd4, 0xc4, 0xa0, 0x44, 0x28, 0x23, 0xf1, 0x0f, 0xd1, 0x36, + 0xec, 0x25, 0x55, 0xf7, 0x1e, 0x84, 0x62, 0xdb, 0x23, 0x11, 0x48, 0xf1, 0x8f, 0x82, 0x52, 0x4a, 0x58, 0x97, 0x46, + 0x99, 0x29, 0x3f, 0xa1, 0xb0, 0x03, 0x07, 0x01, 0x1f, 0x12, 0x68, 0x69, 0x28, 0xeb, 0xbf, 0xdf, 0x30, 0xea, 0xb2, + 0x1f, 0x4b, 0xf2, 0x57, 0x8d, 0xea, 0x5a, 0xa2, 0x7f, 0xbc, 0xcc, 0x4f, 0x69, 0x0a, 0x1e, 0x14, 0x7a, 0x5d, 0x3b, + 0xdd, 0x27, 0x4c, 0x6d, 0x57, 0x2e, 0x12, 0x5f, 0xda, 0x53, 0xfe, 0x08, 0x6a, 0xd3, 0xd4, 0xd8, 0x5c, 0x2f, 0x54, + 0x33, 0xa5, 0x28, 0x2b, 0xbc, 0x6a, 0x2c, 0xb4, 0xe2, 0x90, 0x54, 0x49, 0x9c, 0x33, 0xf7, 0xd8, 0xd5, 0x9b, 0xf0, + 0x82, 0x30, 0x50, 0x60, 0x92, 0x59, 0x6c, 0x44, 0x5f, 0xa1, 0x2f, 0xe9, 0xcb, 0x74, 0xb5, 0x1f, 0x19, 0xf0, 0x06, + 0x87, 0xa3, 0x55, 0x0d, 0xf9, 0x2a, 0x25, 0xaa, 0x44, 0x31, 0x88, 0x52, 0xc7, 0x6f, 0x60, 0x0b, 0xcc, 0xcf, 0x27, + 0x0b, 0xfa, 0xba, 0xac, 0x39, 0x65, 0xbf, 0x59, 0xf3, 0x27, 0x43, 0x7e, 0x3c, 0x6e, 0x91, 0xbb, 0x8e, 0xc8, 0x25, + 0x42, 0xd4, 0x9f, 0xdf, 0x76, 0xad, 0x27, 0x22, 0x9f, 0xd7, 0x66, 0xb1, 0xd8, 0xe5, 0x02, 0xf6, 0x9b, 0xb3, 0x72, + 0xe3, 0xc4, 0xae, 0x3f, 0xf2, 0xc4, 0x33, 0xf9, 0xc4, 0x6d, 0x18, 0x28, 0xef, 0x61, 0xbd, 0xb0, 0x74, 0x4d, 0x02, + 0x50, 0x62, 0xe8, 0xd3, 0xaf, 0x50, 0xad, 0xec, 0x58, 0x6c, 0x2e, 0x79, 0x52, 0x86, 0x40, 0xf1, 0xf5, 0xfd, 0x25, + 0xf9, 0x34, 0x56, 0x20, 0xa5, 0x61, 0x1e, 0x81, 0x45, 0x31, 0x14, 0x35, 0xd4, 0x72, 0xf1, 0x06, 0x6f, 0x60, 0x08, + 0x5f, 0x68, 0x75, 0xb8, 0x6c, 0x37, 0x08, 0x77, 0xc9, 0x8e, 0x95, 0x4e, 0x29, 0x57, 0xe3, 0x00, 0x84, 0x97, 0x3f, + 0x02, 0x50, 0x17, 0x6a, 0x4d, 0xb0, 0xb7, 0x72, 0xb2, 0xdf, 0xdc, 0x11, 0x34, 0xc0, 0x7b, 0xff, 0x2c, 0xfe, 0x74, + 0xfc, 0x41, 0x21, 0x75, 0x27, 0xe5, 0xb5, 0x54, 0xba, 0xd5, 0x7a, 0x4b, 0xba, 0x57, 0xb0, 0xdd, 0x5c, 0xf5, 0x26, + 0xa3, 0x54, 0xeb, 0xfc, 0x3e, 0x19, 0x28, 0x30, 0x53, 0x4d, 0x28, 0x5d, 0x1c, 0x49, 0xed, 0x92, 0x9e, 0x2e, 0x6b, + 0xe8, 0x6f, 0x39, 0xb1, 0x15, 0xec, 0x8f, 0xab, 0x63, 0xc9, 0xb7, 0xf8, 0xfc, 0x2b, 0xc0, 0xde, 0x95, 0x1f, 0xfe, + 0x24, 0xcc, 0xcf, 0x45, 0x97, 0x36, 0xea, 0x91, 0xa3, 0x9e, 0xf7, 0xb7, 0x3c, 0xfa, 0x09, 0xb2, 0x1d, 0x9b, 0x87, + 0xbc, 0xdf, 0xbf, 0xf9, 0xb5, 0x6b, 0xfc, 0xd4, 0x4e, 0x36, 0xa1, 0xd9, 0xb5, 0xf2, 0x5e, 0x7e, 0x0f, 0xfe, 0xe4, + 0x76, 0x8f, 0x4c, 0xaa, 0x61, 0x75, 0x06, 0x7e, 0x18, 0x64, 0x85, 0x5e, 0xfd, 0xb4, 0x67, 0x98, 0x93, 0x7d, 0x88, + 0x1a, 0xdc, 0xe4, 0x86, 0xc6, 0xae, 0x19, 0xd3, 0xb0, 0xad, 0xaf, 0xf1, 0x5c, 0xa3, 0x9c, 0xef, 0x6b, 0xd5, 0x90, + 0xeb, 0xac, 0xa7, 0xd5, 0xf3, 0x8d, 0x09, 0x9c, 0x01, 0x6e, 0x75, 0xc5, 0x2c, 0xa4, 0x20, 0xf9, 0xd6, 0x9e, 0x83, + 0xdb, 0x6a, 0x20, 0xe4, 0x9d, 0x73, 0x9f, 0x48, 0x81, 0x3f, 0xed, 0x7a, 0x27, 0x93, 0x55, 0xbf, 0xf1, 0xad, 0xda, + 0x6d, 0xff, 0xef, 0x46, 0xfc, 0xa3, 0x90, 0x3a, 0x7d, 0xce, 0x9f, 0x42, 0x58, 0x88, 0x6f, 0x74, 0x82, 0x2b, 0xe8, + 0x56, 0x95, 0xc2, 0xbc, 0x97, 0x36, 0xe7, 0xbd, 0x32, 0x07, 0x2d, 0x29, 0xe3, 0x09, 0x5b, 0x5c, 0xd4, 0xdb, 0x6e, + 0x46, 0xe9, 0x16, 0xe6, 0x47, 0x57, 0x2a, 0xb0, 0x20, 0x21, 0x49, 0x53, 0x64, 0xf0, 0x4f, 0x72, 0xe4, 0xb9, 0x0a, + 0x21, 0xdd, 0x68, 0xd2, 0x51, 0x67, 0xb5, 0xb8, 0xa9, 0xe3, 0x93, 0xf8, 0xb4, 0x46, 0xbb, 0xd6, 0x09, 0xff, 0x40, + 0xff, 0x3a, 0xd5, 0x4a, 0xfe, 0xfb, 0x54, 0x37, 0xf2, 0x5f, 0x67, 0x3a, 0x91, 0xff, 0x3e, 0xd3, 0xae, 0x87, 0x57, + 0x8f, 0xac, 0xab, 0x27, 0xd6, 0xd5, 0x33, 0x6b, 0xcc, 0x90, 0x1e, 0x5a, 0xe7, 0x3a, 0xff, 0xec, 0xc4, 0xf9, 0xa4, + 0xb5, 0x64, 0x9f, 0x6f, 0x95, 0xc2, 0x92, 0xf5, 0x6f, 0x27, 0xcd, 0x7c, 0x56, 0x4d, 0xe5, 0xe3, 0x01, 0x2a, 0x4f, + 0x3e, 0x0e, 0xea, 0x5c, 0x45, 0x44, 0x8d, 0x59, 0x51, 0x7b, 0xca, 0xec, 0xee, 0x9d, 0x78, 0x32, 0x7d, 0x88, 0xe8, + 0x6d, 0xe9, 0x66, 0xa8, 0xf4, 0x40, 0x7e, 0x6a, 0xd8, 0xb1, 0x11, 0xf5, 0xa0, 0xf1, 0xd2, 0xdd, 0x23, 0x31, 0xbe, + 0x5f, 0x0a, 0x11, 0x2b, 0xd2, 0x0a, 0x8a, 0x6f, 0x30, 0xf5, 0x50, 0xab, 0x16, 0x7b, 0xee, 0xc7, 0x6c, 0xe9, 0x5e, + 0x52, 0x62, 0x10, 0xc6, 0x76, 0x85, 0xff, 0x2c, 0xc0, 0xaa, 0xf8, 0x99, 0x59, 0x3a, 0x6d, 0xe6, 0x68, 0xe9, 0xf4, + 0x4b, 0xb6, 0x20, 0x5e, 0x86, 0x31, 0xdd, 0x91, 0x64, 0xec, 0x2e, 0x14, 0x5c, 0x41, 0x36, 0x7f, 0x8c, 0x8a, 0x7f, + 0x8a, 0xd5, 0xc3, 0xd3, 0x07, 0x65, 0x18, 0xfc, 0x4f, 0x13, 0xed, 0xa0, 0x1d, 0xa1, 0x8e, 0x71, 0xba, 0x25, 0x15, + 0xee, 0x0b, 0x14, 0xaf, 0xe7, 0xfe, 0x14, 0x55, 0xdf, 0x3a, 0x25, 0x24, 0x2e, 0x67, 0xdb, 0xcf, 0xdd, 0x1c, 0x7a, + 0xb2, 0xcf, 0x8f, 0x29, 0xc8, 0x4d, 0x37, 0xfc, 0x26, 0x58, 0x65, 0xf3, 0xc6, 0x6a, 0x57, 0x4f, 0xe2, 0xf2, 0x97, + 0xff, 0xd3, 0x7e, 0x9e, 0x40, 0xfb, 0xfd, 0x49, 0x3f, 0xf2, 0xd3, 0xe3, 0x18, 0x9d, 0x78, 0x33, 0x47, 0x1f, 0x7e, + 0x2e, 0xca, 0x37, 0xfb, 0x54, 0x3d, 0x4e, 0x76, 0xf3, 0x47, 0xf4, 0x1c, 0xfd, 0xd4, 0x6d, 0x35, 0xfd, 0xc7, 0x09, + 0xb4, 0xcf, 0x9f, 0xf5, 0xe3, 0xb3, 0x3b, 0x68, 0xfa, 0x23, 0xd3, 0xe4, 0x91, 0xcd, 0xf2, 0x95, 0xc5, 0x47, 0x59, + 0xd7, 0x38, 0xdc, 0x4c, 0x73, 0xad, 0x2b, 0x3c, 0xbd, 0xe9, 0x78, 0xa8, 0x8a, 0xc5, 0x31, 0x3e, 0x3d, 0x9e, 0xe0, + 0x43, 0x36, 0xfa, 0xcc, 0xe8, 0x52, 0x44, 0xef, 0xc9, 0x31, 0x44, 0x97, 0xcd, 0xa7, 0xe4, 0x2c, 0x9e, 0x3b, 0x47, + 0x5b, 0xe5, 0x1a, 0x59, 0x18, 0xb5, 0x86, 0xa7, 0xb8, 0x31, 0xfc, 0x9e, 0x53, 0x0e, 0x0c, 0x56, 0x22, 0xb5, 0x87, + 0xa9, 0x62, 0x7a, 0x4b, 0xa2, 0x4f, 0x4a, 0x71, 0xd4, 0x7e, 0x1b, 0x5d, 0x0d, 0x85, 0x27, 0x0f, 0x1c, 0xd5, 0x55, + 0x39, 0x7c, 0xc6, 0x49, 0xef, 0xdc, 0x88, 0xfa, 0xcb, 0xe0, 0x9b, 0x38, 0xd3, 0xa5, 0xeb, 0x4f, 0xd7, 0x91, 0x4f, + 0xba, 0x49, 0x53, 0x56, 0x6f, 0xab, 0xe9, 0x62, 0x8c, 0xce, 0x24, 0xcf, 0x82, 0x94, 0x10, 0x61, 0xac, 0xf0, 0xfc, + 0xf3, 0x69, 0xdb, 0x84, 0x09, 0xdb, 0x24, 0xaf, 0x05, 0x55, 0x44, 0xff, 0xf1, 0x90, 0x3a, 0x1c, 0xc4, 0x86, 0xea, + 0x5d, 0xdf, 0x1e, 0x33, 0xac, 0xcd, 0x8c, 0x78, 0xab, 0xc8, 0x3d, 0x0e, 0x92, 0x59, 0x16, 0x1f, 0x54, 0x9b, 0xe2, + 0xf7, 0xea, 0xc4, 0x38, 0x8d, 0x1a, 0x8f, 0x70, 0x66, 0xa6, 0xcd, 0xd9, 0x8e, 0x17, 0xf5, 0xae, 0xd6, 0x2f, 0x4f, + 0xc7, 0x87, 0xfe, 0xe1, 0x10, 0x2e, 0xe5, 0x61, 0x41, 0x7c, 0x5a, 0x3c, 0x8b, 0x1d, 0x1b, 0x27, 0xe3, 0xf0, 0x3f, + 0xb5, 0x23, 0xe3, 0x4e, 0x51, 0xc2, 0xa9, 0x7e, 0x9a, 0xd2, 0x59, 0xee, 0xa3, 0xe2, 0x1e, 0xb0, 0x1d, 0xce, 0x85, + 0xdb, 0x3d, 0x8f, 0x8c, 0xe8, 0x40, 0x55, 0x5f, 0xbf, 0x83, 0xe6, 0x5f, 0xe3, 0xfa, 0x0e, 0x14, 0xb1, 0xbe, 0xbf, + 0x9c, 0x62, 0x4e, 0x57, 0xe0, 0x98, 0x6f, 0xf9, 0x8e, 0x55, 0x13, 0xcf, 0xea, 0xaf, 0x87, 0xa7, 0x58, 0x85, 0x43, + 0xc1, 0x49, 0xc1, 0x21, 0xb1, 0x69, 0xca, 0x50, 0x38, 0xac, 0x11, 0x7e, 0xf5, 0x69, 0xea, 0x74, 0x71, 0x02, 0xe7, + 0x06, 0xc1, 0x54, 0x0b, 0xda, 0xf3, 0x63, 0x24, 0xde, 0x96, 0xa7, 0x85, 0x22, 0x1b, 0x9c, 0xa3, 0xf2, 0xd7, 0xcc, + 0x62, 0xe7, 0x70, 0x91, 0xff, 0xf3, 0x84, 0x3f, 0x1c, 0x43, 0xd0, 0xc8, 0xb2, 0x63, 0xf1, 0x9b, 0x49, 0x19, 0xde, + 0x3e, 0xe6, 0x5a, 0xb1, 0xa9, 0x27, 0xe3, 0x1f, 0x0e, 0x69, 0x66, 0x1f, 0x3d, 0xa2, 0xac, 0x40, 0xb4, 0xdd, 0xd9, + 0x56, 0x3f, 0x19, 0xa2, 0x96, 0x67, 0xca, 0x93, 0xfd, 0x04, 0xef, 0xd2, 0x0f, 0xf6, 0x83, 0x71, 0x3c, 0x48, 0x42, + 0x43, 0x65, 0xa5, 0x3f, 0x46, 0x85, 0x22, 0x9d, 0xaf, 0xf5, 0xa9, 0x0e, 0x5c, 0x09, 0x05, 0x4c, 0xb9, 0xd6, 0x5c, + 0x33, 0x1c, 0xdb, 0xf2, 0x2c, 0x2f, 0x8c, 0x2d, 0xc0, 0xa7, 0xfc, 0x2a, 0x44, 0x1b, 0x9c, 0x1b, 0x51, 0x16, 0xc8, + 0x44, 0x17, 0x45, 0x5f, 0xb3, 0x38, 0x34, 0xbb, 0x6a, 0x30, 0x4e, 0x43, 0x7f, 0xbd, 0x76, 0x3d, 0xd7, 0x29, 0x65, + 0x2d, 0x72, 0xe7, 0xa6, 0x63, 0x19, 0x36, 0x14, 0x39, 0xe5, 0x66, 0x3e, 0x91, 0x42, 0xdd, 0x40, 0x6f, 0x01, 0xae, + 0x9b, 0xf1, 0xc7, 0x2c, 0x90, 0xc4, 0x6a, 0x00, 0x06, 0x59, 0xfc, 0x8e, 0x00, 0x40, 0x49, 0x5f, 0x94, 0x81, 0x37, + 0x1c, 0x6e, 0x78, 0x5d, 0xd0, 0x5b, 0xed, 0xca, 0xe5, 0x29, 0x16, 0xee, 0xec, 0xf6, 0x3f, 0xaa, 0x27, 0xcf, 0xa1, + 0xb2, 0x23, 0xf3, 0xe9, 0xac, 0xb9, 0x87, 0xb8, 0x95, 0x21, 0xbf, 0x20, 0xe0, 0x02, 0x24, 0x50, 0x3a, 0xc2, 0x39, + 0xe3, 0x92, 0x6b, 0xdc, 0x55, 0xb3, 0x84, 0x12, 0x2c, 0xa1, 0xe3, 0xe7, 0x56, 0xd1, 0x81, 0x7a, 0x57, 0x4f, 0xb7, + 0xee, 0x41, 0x4a, 0xc9, 0xa7, 0x15, 0xeb, 0xc4, 0xf1, 0xfa, 0x35, 0x89, 0xe8, 0xc9, 0x43, 0x79, 0x9a, 0x73, 0x01, + 0xf9, 0x2d, 0x1b, 0x15, 0x33, 0xf3, 0x54, 0x8f, 0xfc, 0xd4, 0x14, 0xeb, 0xf6, 0x70, 0x07, 0xf4, 0xb4, 0x81, 0xf8, + 0x41, 0x71, 0x3f, 0x8b, 0xbc, 0xc6, 0xc3, 0x2c, 0x30, 0x8b, 0x98, 0x5a, 0x8d, 0x34, 0x3b, 0x52, 0x12, 0xd6, 0x42, + 0x26, 0x68, 0xae, 0x33, 0xb2, 0x69, 0xd7, 0x68, 0x17, 0x05, 0x46, 0x34, 0x1d, 0x6c, 0xaf, 0x91, 0x0c, 0xba, 0x8d, + 0xeb, 0x88, 0x10, 0x43, 0x05, 0xe8, 0xe3, 0x20, 0x14, 0xca, 0x3e, 0xa3, 0xf2, 0x22, 0x37, 0xeb, 0xe7, 0x42, 0x30, + 0x5a, 0x98, 0xa1, 0xaa, 0x1c, 0xbb, 0xa6, 0x40, 0xbe, 0x88, 0x8d, 0x20, 0x3b, 0xe5, 0xe3, 0x65, 0x3b, 0x55, 0x3d, + 0xdc, 0x44, 0xd5, 0x3f, 0xb0, 0xde, 0x5e, 0xb4, 0x7d, 0xc0, 0x2f, 0xb5, 0x23, 0xb7, 0x05, 0xae, 0x46, 0xe3, 0x9c, + 0x24, 0x8e, 0xdc, 0x3c, 0xce, 0xf5, 0x83, 0x59, 0x9f, 0xb4, 0xd6, 0x0e, 0xf2, 0x29, 0x02, 0x56, 0x29, 0x75, 0x92, + 0x5e, 0xfb, 0x28, 0xe3, 0xf1, 0x20, 0x21, 0x29, 0x5f, 0x30, 0x3e, 0x9b, 0x7d, 0xe6, 0x45, 0xc9, 0x02, 0xb3, 0x88, + 0x4a, 0xac, 0xc1, 0x74, 0x6c, 0x97, 0xc8, 0x48, 0x77, 0x02, 0xa7, 0x72, 0xac, 0x28, 0xec, 0x6e, 0x57, 0xb3, 0x6f, + 0x26, 0x6f, 0x4d, 0xea, 0x3b, 0xc6, 0x5c, 0xd0, 0x6b, 0xa3, 0xb4, 0x01, 0xb4, 0x07, 0x03, 0x87, 0xd5, 0x85, 0xd9, + 0x69, 0x35, 0xdb, 0xd4, 0x33, 0x62, 0x73, 0xd3, 0xd3, 0xd5, 0x44, 0x3f, 0x43, 0xc0, 0x38, 0x36, 0x8a, 0x7b, 0x6c, + 0x11, 0x6b, 0xe4, 0x35, 0xb5, 0x84, 0xd9, 0xb2, 0x70, 0x2b, 0x46, 0x73, 0x02, 0x63, 0x8c, 0xc9, 0x41, 0x0c, 0x9e, + 0x9b, 0xc3, 0x66, 0x4d, 0x4c, 0xa0, 0x6a, 0x7f, 0x53, 0x46, 0x96, 0xac, 0x62, 0x96, 0x06, 0x32, 0x2c, 0x03, 0x65, + 0xef, 0x85, 0x96, 0x3e, 0xda, 0xb9, 0x10, 0x6a, 0xda, 0xb6, 0xec, 0x36, 0x74, 0x48, 0x81, 0x0f, 0x4c, 0xb7, 0x3b, + 0x07, 0xae, 0xd8, 0xa3, 0xe0, 0x9d, 0xc1, 0xe3, 0x0f, 0xb3, 0x67, 0xc9, 0xef, 0x79, 0xa1, 0xca, 0xf5, 0x89, 0x8e, + 0x76, 0x0b, 0xc8, 0xc4, 0xec, 0xda, 0x96, 0x8f, 0xf6, 0x39, 0x3d, 0x64, 0xb8, 0x82, 0x8c, 0x23, 0x49, 0x11, 0x95, + 0xaf, 0xf4, 0x2a, 0xcb, 0x58, 0xb0, 0xcc, 0x65, 0xcc, 0x92, 0x9a, 0x4c, 0xaa, 0xbd, 0x9b, 0xc1, 0x93, 0xd7, 0x2c, + 0x4c, 0xa6, 0xb0, 0x66, 0x9b, 0x5d, 0x29, 0x47, 0x13, 0x44, 0x26, 0x71, 0x92, 0x64, 0x74, 0x06, 0x1f, 0x04, 0xa2, + 0xe4, 0x44, 0x50, 0xcd, 0xbe, 0x1f, 0xd5, 0x64, 0xad, 0x83, 0x51, 0x49, 0x95, 0xc1, 0xeb, 0x26, 0x45, 0x84, 0x26, + 0x49, 0xbe, 0x76, 0xc4, 0x64, 0x5b, 0xc7, 0xb9, 0x62, 0x95, 0x65, 0x1b, 0x47, 0x16, 0xb9, 0xd2, 0x90, 0x4a, 0x13, + 0xbd, 0xa0, 0x74, 0xe5, 0x5d, 0x28, 0x80, 0x88, 0x43, 0x2b, 0xc8, 0xed, 0xa5, 0x31, 0x13, 0x88, 0xf4, 0xc8, 0xfa, + 0x70, 0x64, 0x2b, 0xe9, 0x62, 0xa3, 0x14, 0x2c, 0x9e, 0x10, 0x16, 0x19, 0x7b, 0xc6, 0xea, 0x6f, 0xbf, 0x6b, 0x8a, + 0xb5, 0xdf, 0x1e, 0xd8, 0x9e, 0xff, 0xdd, 0xfb, 0xfd, 0x48, 0x01, 0x18, 0x71, 0x2f, 0x47, 0x44, 0xfc, 0x56, 0xe7, + 0xb7, 0x88, 0xdf, 0x7c, 0xfe, 0x6d, 0x78, 0x81, 0xae, 0x6b, 0x6c, 0x98, 0x69, 0xe7, 0x56, 0x95, 0x8e, 0xd8, 0x10, + 0x0b, 0xef, 0xf5, 0x29, 0xe9, 0x69, 0x22, 0xc3, 0xfe, 0xd1, 0xcc, 0x0a, 0xd5, 0xf4, 0x29, 0x21, 0xda, 0xc0, 0x64, + 0x84, 0x94, 0xbd, 0x14, 0xcc, 0xba, 0x75, 0xea, 0xe6, 0xb6, 0x18, 0x9f, 0x8f, 0x89, 0x75, 0xcb, 0xbf, 0xd2, 0xc5, + 0xc5, 0x84, 0x61, 0xd0, 0x15, 0x6f, 0xde, 0xb3, 0xe1, 0x50, 0xaa, 0x30, 0x06, 0x9a, 0xc3, 0x59, 0x54, 0x11, 0xa3, + 0x96, 0x71, 0xe7, 0x0e, 0xb8, 0x8e, 0x1e, 0xf0, 0x1b, 0xaa, 0x6a, 0x2c, 0x19, 0x9d, 0xbe, 0xad, 0x63, 0xc8, 0xd7, + 0x91, 0x55, 0x1c, 0xbf, 0xce, 0x53, 0xd0, 0xfb, 0x6e, 0x2a, 0xd7, 0xae, 0x2a, 0x88, 0x7e, 0x96, 0x20, 0xb1, 0x26, + 0x1f, 0x77, 0x6c, 0x95, 0x1b, 0x7f, 0x3e, 0xd5, 0x54, 0xdb, 0x20, 0xb4, 0x2c, 0xc5, 0x82, 0x9d, 0x88, 0x05, 0x2b, + 0xc2, 0xa7, 0x2f, 0x62, 0xd0, 0x38, 0xab, 0x02, 0x67, 0x1f, 0xac, 0x5c, 0xc5, 0x87, 0x2f, 0x01, 0x3a, 0xa9, 0xea, + 0xff, 0x20, 0x71, 0x9d, 0x9d, 0x6e, 0xc9, 0x5f, 0xfb, 0x33, 0x25, 0x82, 0x49, 0x4b, 0x08, 0x81, 0x33, 0xe2, 0xb7, + 0xbe, 0x3c, 0x41, 0x06, 0xb0, 0x66, 0xb4, 0x6b, 0xbf, 0x9c, 0x0c, 0xd3, 0x90, 0x10, 0x35, 0x6b, 0xd8, 0xbb, 0x78, + 0x85, 0x0e, 0x44, 0x62, 0xd0, 0xe4, 0x4d, 0xf0, 0x2b, 0xd5, 0x52, 0xb9, 0xe6, 0x9f, 0x77, 0x73, 0xb9, 0x38, 0xb2, + 0x71, 0x64, 0x65, 0xa1, 0xc0, 0xd7, 0x01, 0xf4, 0x09, 0x9a, 0x13, 0x17, 0xfe, 0x38, 0x4b, 0x5a, 0x64, 0x67, 0xf2, + 0x40, 0xdd, 0x40, 0xc9, 0x62, 0xa5, 0x78, 0x5f, 0x02, 0x1f, 0x94, 0xc1, 0x36, 0x7c, 0x26, 0x71, 0x51, 0x65, 0x4d, + 0xab, 0x7e, 0x8c, 0x5b, 0x88, 0x98, 0x09, 0x65, 0x20, 0x24, 0x39, 0x2b, 0x71, 0x43, 0x65, 0xc5, 0xd1, 0x9d, 0xc5, + 0x02, 0x4c, 0x90, 0xcc, 0x46, 0x04, 0xfe, 0x25, 0x2c, 0x9e, 0x8b, 0x9f, 0xe9, 0xbd, 0x0d, 0x34, 0x31, 0x22, 0x92, + 0x5d, 0xf4, 0x6a, 0x45, 0x0f, 0x76, 0x69, 0x0c, 0x1f, 0x12, 0xc5, 0xb1, 0x7d, 0xde, 0x0f, 0x1a, 0x35, 0x00, 0x0a, + 0x16, 0xdb, 0x92, 0xba, 0x64, 0xde, 0x5e, 0x7b, 0xb9, 0xab, 0xc3, 0xdd, 0x55, 0x08, 0x0a, 0x7c, 0xb6, 0x99, 0x54, + 0x1e, 0x09, 0x64, 0x8d, 0x2d, 0xe6, 0x89, 0xe8, 0x15, 0xd3, 0x95, 0xd1, 0x45, 0x91, 0xad, 0xe3, 0x37, 0x04, 0x8a, + 0x9c, 0x5d, 0x22, 0x31, 0x65, 0x3f, 0x47, 0xb9, 0xe4, 0x42, 0x63, 0x75, 0x24, 0x2f, 0x76, 0x35, 0x88, 0x97, 0xa9, + 0x09, 0x30, 0x05, 0x79, 0x67, 0x46, 0x23, 0x44, 0x54, 0x92, 0x48, 0x11, 0x90, 0x98, 0x4b, 0x3e, 0xc5, 0x43, 0xc8, + 0x4f, 0x15, 0x12, 0x5a, 0x32, 0x94, 0xff, 0xe1, 0x3a, 0xc1, 0xb7, 0x0a, 0x78, 0x91, 0xd4, 0x2f, 0x3c, 0x70, 0x5b, + 0xda, 0xeb, 0x94, 0x0d, 0x12, 0xf0, 0xfd, 0xf4, 0xf0, 0x59, 0x67, 0x0f, 0xe2, 0x27, 0x45, 0x40, 0xf0, 0x41, 0xaf, + 0x6a, 0xb7, 0x4c, 0xa1, 0x92, 0x6a, 0x48, 0xb9, 0x1f, 0x5d, 0x72, 0x3a, 0xe1, 0xf0, 0x02, 0xfe, 0xf1, 0xfd, 0x7c, + 0x03, 0x73, 0xf0, 0x95, 0xae, 0x9a, 0x48, 0xde, 0x0d, 0x83, 0x3d, 0x85, 0xf4, 0x12, 0x0e, 0x6d, 0x5f, 0x23, 0xcc, + 0x76, 0xae, 0xb5, 0xd9, 0xfe, 0xc4, 0x50, 0xa7, 0xd3, 0x8f, 0xdf, 0xc4, 0x46, 0x8d, 0x14, 0xb7, 0x4e, 0xc4, 0x42, + 0x49, 0x3f, 0x7b, 0x72, 0x63, 0x69, 0x3a, 0x56, 0x6f, 0x43, 0xcd, 0xe3, 0x9b, 0x63, 0x3d, 0x79, 0xb3, 0x6c, 0xc9, + 0x07, 0x98, 0x70, 0xcc, 0xb7, 0xa2, 0xe7, 0x59, 0xd9, 0x0b, 0xa6, 0xd6, 0x1f, 0x34, 0x42, 0x62, 0xa8, 0x22, 0xa9, + 0xd7, 0xc0, 0xfb, 0x3a, 0xad, 0x3d, 0xab, 0x67, 0x44, 0xe9, 0xd4, 0x54, 0xac, 0x79, 0xa1, 0x5e, 0x28, 0x53, 0x95, + 0x5a, 0xe6, 0xce, 0x56, 0xd9, 0x53, 0x2c, 0x2f, 0x65, 0x32, 0xc2, 0x7e, 0x02, 0x51, 0x89, 0xef, 0xa1, 0x9e, 0xc4, + 0xba, 0x33, 0xa7, 0x4f, 0xcc, 0xa4, 0x81, 0xf1, 0x11, 0x31, 0x02, 0xab, 0x78, 0x1b, 0x18, 0x26, 0x6a, 0x8d, 0x0b, + 0xdd, 0x91, 0xd1, 0x3a, 0x7c, 0xc3, 0x3d, 0x61, 0x7d, 0x2f, 0xc8, 0x6e, 0xf8, 0xef, 0x99, 0x70, 0xdb, 0xcb, 0x3c, + 0x9a, 0x29, 0xbd, 0x79, 0x7c, 0x1c, 0xd1, 0xf4, 0x96, 0xca, 0x91, 0x2d, 0xe8, 0xae, 0xd7, 0xb0, 0xf1, 0x47, 0x41, + 0xf5, 0x58, 0xba, 0x19, 0x19, 0x31, 0x8e, 0x07, 0x83, 0x24, 0xe8, 0x43, 0xce, 0xaf, 0xa4, 0xe5, 0x79, 0x48, 0x5b, + 0x4c, 0xd8, 0x83, 0xe5, 0x14, 0x99, 0x18, 0x2e, 0xc1, 0xdc, 0xe6, 0x6c, 0xde, 0x7c, 0xe3, 0x8f, 0xc3, 0x9e, 0x4a, + 0x54, 0xc8, 0x83, 0x73, 0xdf, 0xca, 0x38, 0x4d, 0x1a, 0x28, 0x96, 0x31, 0x97, 0xf9, 0x61, 0x53, 0x47, 0xdb, 0xa1, + 0x50, 0x4d, 0xed, 0x9c, 0x7e, 0x9d, 0xec, 0xd3, 0x5e, 0x1d, 0xc9, 0x00, 0x59, 0x03, 0xa1, 0x0a, 0x02, 0x3e, 0xaf, + 0x29, 0x02, 0xc0, 0x72, 0x04, 0x8f, 0xf8, 0x83, 0x30, 0x7e, 0xfa, 0x46, 0xd2, 0x49, 0x58, 0xec, 0x7a, 0x01, 0x47, + 0xaf, 0x03, 0x68, 0xa3, 0x9e, 0xdb, 0x7e, 0x04, 0xa0, 0x5c, 0xac, 0xaf, 0x12, 0x6d, 0x23, 0x75, 0x08, 0xfb, 0xbe, + 0x35, 0xdb, 0xd1, 0x46, 0x9b, 0xe7, 0xd2, 0x68, 0x34, 0xb4, 0x59, 0x1d, 0xe8, 0x1e, 0xa9, 0x00, 0xd0, 0x65, 0x43, + 0xe1, 0xeb, 0xfb, 0x87, 0x28, 0xdd, 0x08, 0x76, 0xc1, 0x19, 0x7c, 0xb9, 0x74, 0xcc, 0xb7, 0x70, 0x34, 0x9f, 0x99, + 0x7a, 0x2b, 0x3f, 0x83, 0xfa, 0xba, 0xdb, 0x05, 0xe0, 0x57, 0x2e, 0x72, 0xc0, 0xf4, 0x3b, 0x9b, 0xe2, 0xa0, 0xb7, + 0x1c, 0xbd, 0xc6, 0xe9, 0xcc, 0x0c, 0x58, 0xc8, 0xb3, 0x6b, 0xe5, 0x43, 0x72, 0x03, 0x59, 0x5c, 0x40, 0x43, 0x76, + 0x0b, 0xb8, 0xf2, 0x4c, 0x97, 0x28, 0x49, 0x13, 0x84, 0x9e, 0xc0, 0x63, 0x35, 0x73, 0xb0, 0xec, 0x7d, 0x39, 0xd1, + 0xf3, 0x5c, 0x3e, 0x05, 0x8d, 0x14, 0xa8, 0x74, 0x5e, 0x52, 0x16, 0x90, 0x73, 0xa8, 0x83, 0x10, 0x33, 0x1d, 0xf4, + 0x92, 0xa9, 0xa6, 0x32, 0x87, 0x46, 0x48, 0x7e, 0x50, 0x90, 0x9c, 0xc0, 0xb9, 0xf9, 0x6a, 0x1d, 0xf5, 0xcb, 0x45, + 0x65, 0xbd, 0xa8, 0xc8, 0x04, 0xb7, 0x12, 0x1f, 0xb2, 0xfa, 0xc6, 0xc8, 0xe8, 0x68, 0x1d, 0x56, 0x9e, 0xc6, 0xf9, + 0x81, 0x07, 0x87, 0xe0, 0xc8, 0x1e, 0x62, 0x01, 0xa0, 0x89, 0xdb, 0x1c, 0xc2, 0x9f, 0xf9, 0xc8, 0x14, 0xb8, 0x35, + 0x0c, 0x09, 0x02, 0x02, 0x3e, 0xb1, 0x04, 0x8e, 0x99, 0x41, 0xc4, 0xb1, 0xd5, 0xe6, 0x0f, 0x98, 0x48, 0xab, 0xbc, + 0x31, 0x62, 0x13, 0x4e, 0x5c, 0xe3, 0x12, 0x29, 0x64, 0x6f, 0x4d, 0x76, 0xc2, 0x22, 0x0b, 0x1b, 0x72, 0xe4, 0x63, + 0xed, 0x65, 0x92, 0xf7, 0x65, 0x16, 0x2d, 0x29, 0x51, 0x77, 0x29, 0x52, 0xbc, 0x6e, 0x1f, 0xa2, 0xd5, 0x5a, 0xb5, + 0xd4, 0x71, 0xe8, 0x2e, 0x58, 0xcf, 0xfb, 0xbf, 0x7e, 0x2b, 0xa5, 0x7e, 0x72, 0x3e, 0x06, 0x55, 0xdc, 0x05, 0x85, + 0x35, 0x47, 0xc2, 0xd6, 0x4d, 0x93, 0x35, 0x79, 0x68, 0xbf, 0xec, 0x85, 0xae, 0xbb, 0x8d, 0xa8, 0x6a, 0x29, 0xf5, + 0x98, 0x17, 0x22, 0x1f, 0x86, 0x3e, 0x56, 0x8c, 0x50, 0x15, 0x1a, 0x5b, 0x3a, 0xe4, 0x71, 0x62, 0xe9, 0xf4, 0x41, + 0xe8, 0x5d, 0x0e, 0xf7, 0x21, 0x96, 0x87, 0x95, 0x24, 0xca, 0x8c, 0xa9, 0x44, 0x34, 0x8e, 0x80, 0xd1, 0xc6, 0xd8, + 0x6d, 0x04, 0x4e, 0x09, 0x36, 0x67, 0xd6, 0xbf, 0x62, 0x3c, 0xf1, 0x35, 0x74, 0x24, 0x19, 0x34, 0xe3, 0x87, 0x98, + 0xcf, 0x78, 0x23, 0x3a, 0x0c, 0x0d, 0x9a, 0xfe, 0x61, 0x9b, 0x8f, 0xbd, 0x96, 0xd0, 0x8f, 0x38, 0x84, 0x73, 0xde, + 0xf9, 0xa1, 0xfd, 0x62, 0x35, 0xe4, 0x6b, 0xd8, 0xbf, 0xf2, 0x94, 0xbf, 0xf2, 0x35, 0xdc, 0x87, 0x3c, 0xe5, 0x43, + 0xbe, 0x86, 0xfc, 0x90, 0x27, 0xc9, 0xe0, 0xf4, 0x7c, 0xa5, 0x3e, 0xf7, 0xd7, 0x42, 0x9d, 0x5c, 0x9e, 0x09, 0xad, + 0xe4, 0xa0, 0x17, 0xdf, 0x25, 0xda, 0x67, 0x02, 0x19, 0x3e, 0x2e, 0xa6, 0x44, 0x88, 0x43, 0x56, 0x96, 0x2e, 0x01, + 0x74, 0x1a, 0xe0, 0xdd, 0xeb, 0xeb, 0xbb, 0xfe, 0x15, 0xb6, 0x48, 0x1a, 0x03, 0xf1, 0xb8, 0x0f, 0xfa, 0xa9, 0x4e, + 0xdd, 0x78, 0x6e, 0x2b, 0x20, 0xe4, 0xca, 0x91, 0x80, 0x93, 0x8c, 0x76, 0x84, 0x10, 0xbd, 0x73, 0xbf, 0x67, 0x66, + 0xe6, 0xdb, 0xf7, 0xd0, 0x6b, 0xe1, 0x30, 0x87, 0x00, 0x39, 0xcb, 0x92, 0xc1, 0x5e, 0xec, 0x5f, 0xaf, 0x3e, 0x46, + 0xfa, 0xd4, 0x0c, 0x50, 0xd1, 0xa0, 0x6a, 0xb2, 0x3f, 0xe6, 0xc8, 0x48, 0x7a, 0xf9, 0x8f, 0x79, 0x97, 0x94, 0xa5, + 0xcb, 0x64, 0x08, 0xdc, 0x13, 0xb4, 0xdc, 0xcf, 0x82, 0x84, 0x4c, 0x33, 0xcb, 0x06, 0x51, 0x5b, 0x4e, 0x33, 0xe6, + 0x91, 0x1e, 0x4b, 0xb5, 0x54, 0x16, 0xee, 0x7c, 0xc7, 0xcf, 0xf8, 0x3f, 0x98, 0x84, 0xe6, 0x57, 0x83, 0xf2, 0x45, + 0xce, 0xac, 0xbb, 0x2b, 0x6c, 0x69, 0x0d, 0xa6, 0x25, 0x92, 0xa5, 0xc5, 0xb9, 0xd5, 0x98, 0x56, 0x90, 0xd6, 0x23, + 0x4f, 0x43, 0x34, 0xba, 0x49, 0x22, 0x36, 0x72, 0x6a, 0x3d, 0xe9, 0xda, 0x52, 0x93, 0xcc, 0x8a, 0xa5, 0x57, 0xb2, + 0xf7, 0xcd, 0x37, 0xd4, 0xa7, 0xe6, 0x72, 0x39, 0xc0, 0x26, 0xd3, 0x4d, 0xb1, 0x35, 0x05, 0xde, 0x25, 0x49, 0x11, + 0x1a, 0x02, 0xe5, 0xa8, 0x6d, 0x26, 0xbb, 0x4b, 0x55, 0x2d, 0xa7, 0x6a, 0x84, 0x48, 0x7d, 0x55, 0x61, 0xa9, 0x8e, + 0xe2, 0xe1, 0xc5, 0xbe, 0x88, 0xdd, 0x07, 0x71, 0x9d, 0xa5, 0x69, 0xb4, 0x59, 0xab, 0xad, 0x85, 0x3c, 0x06, 0x5f, + 0xee, 0x1a, 0x62, 0x00, 0xeb, 0x88, 0x46, 0x67, 0xf1, 0xe5, 0xd9, 0x35, 0x3c, 0x76, 0x68, 0xbf, 0xf6, 0xc1, 0x49, + 0x8b, 0xed, 0xa9, 0x14, 0x6e, 0x7d, 0x46, 0x06, 0x81, 0x44, 0xe2, 0x03, 0x00, 0x06, 0x00, 0x98, 0xea, 0x25, 0x45, + 0x35, 0x32, 0x68, 0x25, 0x0a, 0xf4, 0x48, 0xc1, 0x7d, 0x74, 0x19, 0x5a, 0x0e, 0x0e, 0x7f, 0x44, 0x4a, 0xab, 0x1d, + 0xb2, 0xc4, 0x44, 0xa6, 0x85, 0x92, 0x39, 0x4c, 0x68, 0xa5, 0xc5, 0x18, 0xb4, 0x44, 0xe1, 0x3d, 0x41, 0x3a, 0x6a, + 0x49, 0x80, 0xfa, 0xf2, 0xe8, 0x40, 0xc2, 0xe9, 0xbd, 0x79, 0xbe, 0x36, 0x7e, 0x2d, 0x6f, 0x9b, 0xe5, 0xba, 0x23, + 0x5b, 0xc1, 0x14, 0x92, 0x21, 0xd8, 0xe5, 0x6c, 0x95, 0x33, 0xfa, 0x08, 0x71, 0x12, 0xcb, 0x92, 0xd7, 0x56, 0xb9, + 0x59, 0x8c, 0x3e, 0x74, 0xcd, 0x7d, 0xd1, 0x0f, 0x75, 0xcf, 0x8f, 0x40, 0x70, 0x44, 0xb0, 0x08, 0x9e, 0xe3, 0xb4, + 0x6e, 0xf2, 0x52, 0x52, 0x13, 0xa4, 0x28, 0xf0, 0x21, 0xfd, 0xfc, 0x06, 0x43, 0x05, 0xdb, 0x6c, 0xc3, 0x21, 0x47, + 0x03, 0xcd, 0x77, 0x35, 0xfe, 0x7a, 0x75, 0x02, 0xd6, 0x92, 0xce, 0x53, 0xdb, 0xb6, 0x89, 0x3d, 0xe6, 0x8a, 0xb4, + 0xd3, 0x56, 0x08, 0xf5, 0xb9, 0xf8, 0xec, 0x67, 0xcf, 0x89, 0xaa, 0xfb, 0xf2, 0x43, 0xf0, 0xbd, 0x5d, 0x54, 0xed, + 0xb5, 0x05, 0x94, 0x1f, 0x67, 0x52, 0x6a, 0xb6, 0x0e, 0x8a, 0xd2, 0xe3, 0xd1, 0x88, 0x16, 0xb7, 0xb7, 0x94, 0xbd, + 0x1f, 0x24, 0xc1, 0x4d, 0xa6, 0x56, 0xfe, 0xdb, 0xbb, 0xdb, 0x93, 0x7c, 0x8f, 0x82, 0xcc, 0xbd, 0x16, 0xce, 0x33, + 0x73, 0x09, 0x41, 0x01, 0x22, 0x23, 0x28, 0xb3, 0x31, 0x6f, 0x03, 0xf3, 0x0e, 0xcc, 0x2f, 0xe8, 0x51, 0xa9, 0x38, + 0x90, 0x9c, 0xd5, 0xc5, 0xa8, 0x98, 0x94, 0x03, 0x2f, 0x71, 0xfd, 0x5d, 0x1a, 0x12, 0x10, 0xb8, 0x46, 0x5d, 0x06, + 0x8b, 0xc4, 0x3e, 0x51, 0x7c, 0x04, 0x67, 0xfb, 0xc6, 0x0e, 0x32, 0xbb, 0xe1, 0x7d, 0x5d, 0x5c, 0xc0, 0x1d, 0x84, + 0xcf, 0xd2, 0x53, 0x10, 0xa1, 0xa9, 0xfb, 0xdf, 0xb8, 0xa8, 0x14, 0xbe, 0xd9, 0x20, 0x63, 0xcf, 0x2f, 0xeb, 0x00, + 0xe4, 0xd2, 0x34, 0x0a, 0x83, 0x19, 0x7f, 0x72, 0xa4, 0x5f, 0x85, 0x1e, 0x52, 0x5d, 0x8b, 0xba, 0x4b, 0x72, 0x3f, + 0x74, 0xec, 0x1c, 0x8a, 0x54, 0xb1, 0xad, 0xc3, 0xf9, 0xa2, 0x91, 0xa9, 0x49, 0xff, 0xc2, 0xe3, 0x9d, 0x4d, 0xb7, + 0xdf, 0x60, 0x2e, 0x85, 0x40, 0x36, 0x32, 0xb1, 0xe9, 0xa4, 0x1d, 0x95, 0xea, 0xca, 0x9d, 0x17, 0x15, 0xea, 0xad, + 0x65, 0x2f, 0xe9, 0xe8, 0xc3, 0x8a, 0x5c, 0x4a, 0xd8, 0x12, 0x49, 0x53, 0xb8, 0x54, 0xc6, 0x58, 0x3a, 0x33, 0x77, + 0xe7, 0xbb, 0xb8, 0x92, 0xc6, 0x01, 0x3e, 0x86, 0xa1, 0x6c, 0xc4, 0xdf, 0x0f, 0x90, 0x86, 0x6a, 0x6a, 0xdd, 0x0a, + 0x64, 0x82, 0x65, 0x85, 0x12, 0x3a, 0x54, 0x50, 0x7c, 0xe0, 0xfb, 0xce, 0xe0, 0xc6, 0x49, 0xc9, 0xc6, 0xdf, 0x37, + 0xeb, 0x1e, 0x93, 0x87, 0x33, 0x93, 0xbb, 0x00, 0xaa, 0xd8, 0x6b, 0x05, 0xce, 0x0c, 0xa1, 0x70, 0x72, 0x1c, 0xd7, + 0x32, 0x27, 0xc8, 0x3a, 0x7a, 0xdb, 0x03, 0x6f, 0x91, 0x76, 0xd7, 0x45, 0x9a, 0x52, 0xed, 0x28, 0xd8, 0xc6, 0x09, + 0x38, 0xeb, 0xfb, 0x0f, 0x4a, 0xe3, 0x4a, 0xea, 0xf2, 0x79, 0x5a, 0x64, 0xdb, 0x33, 0xe2, 0x60, 0x57, 0xb5, 0x29, + 0xca, 0xa2, 0x08, 0x23, 0x0c, 0x46, 0x08, 0x5b, 0x96, 0x18, 0xc7, 0x44, 0x6c, 0x12, 0x0a, 0xa3, 0x8f, 0xca, 0x6a, + 0xe5, 0x3a, 0x96, 0x7e, 0xd5, 0x59, 0x21, 0x75, 0x44, 0x7b, 0x1f, 0xbc, 0xc4, 0x24, 0x65, 0x79, 0x4e, 0xb6, 0xf8, + 0xf4, 0x42, 0xad, 0x4f, 0xa9, 0xf6, 0xc0, 0xde, 0xdc, 0x1c, 0x24, 0x4d, 0xbe, 0x27, 0x21, 0x1e, 0x16, 0x9d, 0xd7, + 0x06, 0xe7, 0xe5, 0x69, 0xdc, 0xfd, 0x59, 0x37, 0x2d, 0x5b, 0x17, 0xe2, 0x14, 0x55, 0x47, 0xbd, 0xc9, 0xe9, 0xb5, + 0xcf, 0x3f, 0x11, 0xea, 0x84, 0x41, 0xc3, 0xcc, 0x69, 0x89, 0x89, 0x48, 0xd7, 0x65, 0x1e, 0x98, 0x08, 0xee, 0x3d, + 0x83, 0x61, 0x87, 0xe4, 0x71, 0xb2, 0x30, 0x9d, 0xb0, 0x0b, 0x51, 0xd9, 0x26, 0x67, 0xbe, 0xe7, 0xe6, 0x5f, 0x0f, + 0x64, 0x18, 0xf6, 0x69, 0x41, 0xcb, 0x79, 0xfd, 0xa6, 0x77, 0x7f, 0xb9, 0xe8, 0xa9, 0x3f, 0x06, 0xd7, 0x15, 0x9a, + 0xb0, 0x78, 0x4d, 0x87, 0xfd, 0x2f, 0xa2, 0x9f, 0xb8, 0xcf, 0xf2, 0x9e, 0x46, 0x33, 0x86, 0xc6, 0xac, 0x89, 0xfa, + 0x9d, 0x99, 0x1d, 0x85, 0x20, 0x39, 0xb1, 0x93, 0xb3, 0xfa, 0x11, 0x90, 0x88, 0x31, 0xb5, 0x9b, 0x83, 0x61, 0x76, + 0x8c, 0xb3, 0xb0, 0x68, 0xd1, 0x97, 0x87, 0x9c, 0x56, 0x00, 0x86, 0x97, 0xca, 0x2f, 0xbb, 0x76, 0x68, 0xca, 0xe3, + 0x84, 0x5a, 0x2b, 0xb8, 0x16, 0x32, 0x47, 0x55, 0x6d, 0xa2, 0xb5, 0x14, 0x81, 0x59, 0x1c, 0xeb, 0xf6, 0x53, 0x5d, + 0xff, 0x01, 0x46, 0x5f, 0xf3, 0xb0, 0x3d, 0x7f, 0x92, 0xd8, 0x52, 0xeb, 0x73, 0xbe, 0x25, 0x7a, 0x19, 0x7b, 0xaf, + 0x13, 0xb5, 0x09, 0x96, 0x6c, 0xc9, 0xca, 0x35, 0x45, 0xb8, 0x89, 0xa1, 0xea, 0x1a, 0x42, 0xb9, 0x41, 0xe2, 0x1b, + 0x32, 0x81, 0xd5, 0xf9, 0xa5, 0xce, 0xd2, 0xb3, 0x84, 0x76, 0x79, 0xa0, 0x9d, 0x9d, 0x30, 0xd2, 0x45, 0xe1, 0xff, + 0x4e, 0x26, 0x84, 0xe0, 0xca, 0x86, 0x67, 0x4b, 0xa8, 0x8b, 0xe2, 0xe2, 0xaa, 0x5d, 0x40, 0xf1, 0xeb, 0xf5, 0xbb, + 0xf5, 0xbf, 0xa5, 0xef, 0x70, 0xd9, 0x20, 0xf6, 0xd7, 0x88, 0x7a, 0x9a, 0xcc, 0xb0, 0xda, 0xe8, 0x16, 0xc3, 0xfe, + 0xd1, 0xf4, 0x8d, 0x24, 0x76, 0x0a, 0x17, 0xdf, 0x77, 0x4a, 0x1c, 0xef, 0xa6, 0x29, 0x6b, 0xa2, 0xf1, 0xbf, 0x51, + 0xd3, 0xe0, 0x14, 0xbe, 0xbe, 0xc1, 0xa9, 0xe0, 0x61, 0xd7, 0xd4, 0x50, 0xec, 0xee, 0x17, 0x2b, 0x9a, 0xd6, 0x5a, + 0x57, 0x18, 0xa0, 0x0a, 0x1f, 0x41, 0x4e, 0x45, 0xbe, 0x97, 0xfb, 0x8a, 0x2f, 0xf2, 0x47, 0xdf, 0xbc, 0x74, 0x84, + 0x35, 0x97, 0x42, 0xcd, 0xad, 0x4c, 0xf2, 0xd3, 0xf2, 0x22, 0xe9, 0x96, 0x18, 0x94, 0x73, 0xcb, 0xfc, 0x7a, 0x07, + 0x8a, 0x4a, 0xcc, 0xb6, 0x2b, 0x37, 0x08, 0xd3, 0x3a, 0x17, 0xe1, 0xbd, 0xb6, 0x12, 0x29, 0x6a, 0x8d, 0x59, 0xce, + 0xb4, 0xa4, 0x1e, 0x9b, 0xcf, 0x44, 0x1d, 0xb8, 0x01, 0x31, 0xfa, 0x9e, 0x29, 0x79, 0x0d, 0x08, 0xbb, 0xe7, 0xe1, + 0xfb, 0x64, 0x79, 0x19, 0xe6, 0x5a, 0x59, 0x52, 0x4d, 0xd6, 0x3d, 0x55, 0x48, 0x1a, 0x13, 0x7a, 0x6b, 0x97, 0x79, + 0xb9, 0x55, 0x67, 0x78, 0xb2, 0x4e, 0xef, 0x59, 0xea, 0x07, 0x78, 0x5d, 0x25, 0x0f, 0x15, 0x1e, 0x2c, 0xdc, 0xb8, + 0x00, 0x5a, 0x56, 0xde, 0xea, 0x1c, 0x47, 0xb7, 0x79, 0x4a, 0xd6, 0x66, 0x83, 0xd7, 0x44, 0x2c, 0xa0, 0x64, 0x7b, + 0xb0, 0xdd, 0xc6, 0xca, 0x21, 0x1a, 0x6f, 0x1f, 0x59, 0x48, 0xd1, 0x75, 0x83, 0x36, 0x2f, 0x0f, 0x98, 0xc3, 0x51, + 0x75, 0x75, 0xa3, 0x9c, 0xbd, 0xc4, 0xfc, 0x60, 0xa4, 0x40, 0x41, 0x23, 0x7b, 0xc1, 0xa2, 0x4a, 0xbd, 0x8f, 0xad, + 0x57, 0x7d, 0xbb, 0x16, 0x7e, 0x24, 0x82, 0x91, 0xda, 0x28, 0xe1, 0x79, 0x8a, 0xe4, 0xd9, 0xb1, 0x9b, 0x27, 0x27, + 0x64, 0x64, 0x5e, 0xba, 0x02, 0x92, 0xb0, 0xe0, 0xa1, 0x09, 0xc2, 0xe2, 0x54, 0x32, 0x82, 0x88, 0x7d, 0xce, 0xdc, + 0x40, 0xa8, 0x1a, 0xae, 0x22, 0xc0, 0xcd, 0x93, 0x5e, 0xd2, 0x3c, 0x96, 0xdb, 0x62, 0xcc, 0xea, 0x34, 0x13, 0x6a, + 0x79, 0x26, 0xa2, 0x44, 0x7e, 0x5e, 0x0f, 0xf9, 0x08, 0xe8, 0xd0, 0x6d, 0xc2, 0xb9, 0x58, 0x63, 0x27, 0x56, 0xa9, + 0xb5, 0xa0, 0xf0, 0xdb, 0xb1, 0xc9, 0xda, 0x6f, 0x32, 0xa3, 0x67, 0x30, 0xff, 0x2c, 0x46, 0xb2, 0x9b, 0x3e, 0x8a, + 0xe3, 0x3e, 0x40, 0x01, 0x99, 0x6f, 0xe8, 0x20, 0xf9, 0x6d, 0xa9, 0x1e, 0xd7, 0xbb, 0x51, 0x2e, 0xc4, 0x93, 0x2c, + 0xf2, 0x40, 0xaa, 0x9d, 0xaf, 0x72, 0x5c, 0x7a, 0xe4, 0xd6, 0x0f, 0x54, 0x03, 0x42, 0x20, 0xcb, 0x0d, 0xa4, 0xf0, + 0x06, 0x07, 0xce, 0x9b, 0x38, 0x22, 0xa1, 0xac, 0x67, 0x22, 0x98, 0x2c, 0x4a, 0xf1, 0x5e, 0xfc, 0xe2, 0xd7, 0xee, + 0x2f, 0x16, 0x67, 0x7d, 0xb1, 0x87, 0xcd, 0xf2, 0xc5, 0x7b, 0x0d, 0xc4, 0x56, 0x15, 0x1e, 0x2c, 0x59, 0x4c, 0x0f, + 0x5e, 0xef, 0x11, 0x36, 0xf6, 0x0c, 0xef, 0xc1, 0x27, 0xfd, 0x5a, 0x42, 0xa5, 0xcd, 0xa5, 0xe8, 0x80, 0xfd, 0x30, + 0xdc, 0x64, 0xdf, 0x08, 0x13, 0xd2, 0xc5, 0xfa, 0x44, 0xff, 0x19, 0x24, 0x79, 0xb7, 0xeb, 0xef, 0xeb, 0x45, 0xe4, + 0x06, 0x2b, 0x05, 0xd9, 0xd8, 0x6d, 0x76, 0x90, 0x35, 0x64, 0x25, 0x53, 0x63, 0x82, 0x50, 0x06, 0xe9, 0x0b, 0x51, + 0x97, 0xf7, 0x57, 0x6d, 0x78, 0x98, 0xae, 0xb6, 0x96, 0x15, 0xc5, 0xb7, 0xf2, 0x5f, 0x85, 0xee, 0x78, 0x8e, 0x8e, + 0xa4, 0xbe, 0x73, 0x88, 0x3f, 0x7b, 0x1d, 0x34, 0x11, 0xaa, 0x02, 0xf2, 0xd7, 0xda, 0x0b, 0xe7, 0xd6, 0x53, 0x4e, + 0xee, 0xce, 0xa7, 0x5b, 0xb9, 0x08, 0xe9, 0x07, 0x86, 0x5e, 0xb6, 0xd8, 0xe8, 0xc5, 0x63, 0x3a, 0xd6, 0xa1, 0x25, + 0x12, 0xe3, 0x73, 0x60, 0xa6, 0x4e, 0x5d, 0x63, 0x62, 0x3a, 0xeb, 0x8f, 0x91, 0x15, 0x58, 0x80, 0x31, 0xd6, 0xc2, + 0x4f, 0x57, 0xe1, 0xdb, 0xe9, 0x37, 0x84, 0x20, 0x70, 0x9b, 0x34, 0xf1, 0xd3, 0xd5, 0x53, 0x6c, 0x7e, 0x53, 0x31, + 0x57, 0xc4, 0xb6, 0x1c, 0x68, 0xd1, 0xaa, 0x86, 0x3a, 0xb3, 0x13, 0x14, 0x84, 0x29, 0x12, 0x85, 0x31, 0x57, 0x47, + 0x89, 0x41, 0xd4, 0x72, 0xea, 0x2e, 0x64, 0x9b, 0x0a, 0xb5, 0x25, 0xb9, 0x28, 0x28, 0xe1, 0x88, 0x4d, 0xe2, 0x4c, + 0x35, 0x07, 0xa8, 0x5f, 0xdb, 0xb4, 0x09, 0x67, 0xbd, 0xe0, 0xde, 0xa9, 0xa0, 0x50, 0x53, 0xc3, 0xe0, 0x15, 0x1b, + 0x83, 0x57, 0xe5, 0x0c, 0xed, 0xf0, 0x22, 0xfd, 0xbe, 0xf9, 0x44, 0x5b, 0x4b, 0x73, 0xb3, 0xec, 0xdf, 0xcb, 0xc3, + 0x1f, 0x0d, 0x6f, 0xbf, 0x73, 0x26, 0xc4, 0x45, 0xf3, 0xa1, 0xa7, 0x5e, 0xe2, 0x71, 0x83, 0x62, 0x0f, 0xcd, 0x8c, + 0x19, 0x76, 0x9f, 0x69, 0xe9, 0x30, 0xc6, 0xed, 0xc4, 0x2d, 0xed, 0x41, 0x37, 0x2a, 0x8c, 0x3d, 0x3d, 0xdf, 0x40, + 0xeb, 0xad, 0xf0, 0xb6, 0xb5, 0x3b, 0x6d, 0x7c, 0x3e, 0x1d, 0x03, 0xe8, 0x1b, 0x6d, 0xba, 0x6c, 0x1e, 0xba, 0x4c, + 0xc6, 0x22, 0xd1, 0x76, 0xc8, 0x17, 0xcb, 0xc3, 0xef, 0xbd, 0xad, 0x4d, 0x7b, 0x0b, 0xd7, 0x91, 0x21, 0x83, 0xb4, + 0x54, 0x89, 0x54, 0xd1, 0xa3, 0x0b, 0xe4, 0xd5, 0x4c, 0xb4, 0x72, 0x8d, 0x3a, 0xe3, 0xf5, 0xed, 0x52, 0x65, 0xf9, + 0x63, 0x0b, 0x51, 0xa5, 0x97, 0xff, 0x02, 0x31, 0xcf, 0x0e, 0x93, 0x81, 0xe1, 0x14, 0x42, 0x63, 0xf7, 0x7f, 0x80, + 0xd3, 0x2e, 0x03, 0x6a, 0x42, 0xcd, 0xcb, 0x45, 0x17, 0x49, 0x71, 0xf9, 0xe9, 0x7e, 0x37, 0x04, 0xf1, 0x7c, 0x75, + 0x16, 0x5c, 0x7b, 0x49, 0x92, 0x4a, 0xfc, 0xa5, 0x34, 0x4d, 0x38, 0xc9, 0xb6, 0x22, 0x7e, 0x55, 0x9f, 0x00, 0x48, + 0x21, 0x5e, 0x69, 0x16, 0x69, 0xe2, 0x2d, 0xe9, 0xaa, 0x90, 0x51, 0xf1, 0x21, 0x85, 0x6f, 0x65, 0xb4, 0x3d, 0x9a, + 0x61, 0x74, 0x8d, 0x25, 0x76, 0x10, 0xba, 0x61, 0x9a, 0x30, 0x02, 0x1d, 0xd8, 0xc9, 0x00, 0x89, 0xbc, 0x53, 0x0e, + 0x31, 0x57, 0x4d, 0x4c, 0xc1, 0x0f, 0x49, 0xbd, 0x97, 0x20, 0xb7, 0xa0, 0x79, 0x56, 0xd6, 0x84, 0xd8, 0xe4, 0xc8, + 0xfd, 0x3e, 0x39, 0xe0, 0x7a, 0x61, 0x73, 0xb0, 0x51, 0xe9, 0x38, 0xb9, 0xcf, 0xf0, 0x6f, 0x3b, 0x49, 0x01, 0xb5, + 0x5b, 0xc5, 0x5c, 0x8e, 0xd3, 0x5c, 0xd0, 0x62, 0xfa, 0x6f, 0x06, 0x92, 0x83, 0xfe, 0x91, 0xa0, 0x81, 0xa5, 0xc3, + 0x4f, 0x74, 0x6b, 0xf0, 0x2f, 0x6c, 0x35, 0xcd, 0x4a, 0x64, 0xb5, 0xa7, 0x58, 0x7b, 0xe6, 0x65, 0xf2, 0xed, 0xa4, + 0xfe, 0x35, 0xaf, 0x49, 0xac, 0x7e, 0xe2, 0xa6, 0x16, 0x8f, 0x5c, 0x9f, 0x72, 0x70, 0x7a, 0xaa, 0xc7, 0x5e, 0xd8, + 0x75, 0x9a, 0x95, 0x0c, 0x51, 0x9c, 0x4b, 0xb6, 0xeb, 0xe2, 0x6f, 0x2f, 0x12, 0x41, 0x79, 0x9b, 0x80, 0x11, 0x12, + 0x10, 0xb9, 0x60, 0xf6, 0x34, 0x64, 0x72, 0xd4, 0x57, 0x9b, 0x87, 0xc3, 0x0a, 0x81, 0xe6, 0xa1, 0x70, 0x3f, 0xcc, + 0x54, 0xca, 0x2e, 0x0e, 0x01, 0x55, 0xba, 0x7f, 0x8d, 0x69, 0x35, 0xff, 0x9b, 0x24, 0xf1, 0x27, 0xab, 0x3f, 0x6c, + 0x55, 0x0d, 0xd1, 0x10, 0x17, 0x46, 0x29, 0x1a, 0x4f, 0x19, 0x0b, 0x3d, 0xa3, 0x67, 0x4e, 0x22, 0x4b, 0x41, 0xff, + 0xec, 0x3c, 0x9c, 0xd7, 0xfa, 0xb4, 0x45, 0x35, 0x70, 0x94, 0x44, 0xb1, 0x65, 0x06, 0x46, 0xbc, 0x00, 0x24, 0x66, + 0x7a, 0x90, 0x15, 0x2d, 0xf8, 0xda, 0x76, 0x65, 0xc5, 0x9c, 0x65, 0x60, 0xf5, 0x43, 0xd4, 0x1f, 0x6e, 0xda, 0x1b, + 0x7a, 0x4b, 0x2b, 0xe3, 0x2d, 0x3d, 0xde, 0xd3, 0x66, 0xd6, 0x2f, 0x6d, 0xa0, 0xe9, 0x52, 0x95, 0x3c, 0x7d, 0x7f, + 0xdf, 0xf7, 0xc5, 0xfd, 0x79, 0x3f, 0x15, 0x57, 0x6c, 0xef, 0xe7, 0x81, 0x4a, 0x4e, 0xfc, 0x73, 0xd4, 0xaf, 0x27, + 0x33, 0xaa, 0x09, 0xd7, 0x6d, 0xdd, 0xb7, 0xc2, 0x23, 0x5f, 0x4f, 0x2c, 0x1c, 0x49, 0x5d, 0xa1, 0xe4, 0x3d, 0x69, + 0xd9, 0xa0, 0x7b, 0x8a, 0x20, 0xdf, 0x57, 0x40, 0x29, 0x05, 0x34, 0x1f, 0x5c, 0x22, 0x44, 0x69, 0x6a, 0x5d, 0xba, + 0xf1, 0x86, 0xca, 0xcd, 0x07, 0x66, 0x39, 0x1b, 0x82, 0x8f, 0x13, 0xf0, 0x8b, 0x79, 0x50, 0x3f, 0xae, 0xc2, 0x34, + 0x33, 0x54, 0xf6, 0x80, 0x6c, 0x82, 0x92, 0x13, 0xa9, 0x47, 0x5f, 0xd4, 0x91, 0x40, 0xa3, 0xa8, 0x57, 0x9e, 0x75, + 0xbf, 0xd0, 0x45, 0xae, 0x34, 0xff, 0xbf, 0x84, 0x92, 0x0d, 0xf5, 0xe7, 0xe3, 0x4b, 0x69, 0xb0, 0x40, 0xdf, 0x2f, + 0xfc, 0xf6, 0xf2, 0xa2, 0xd1, 0xe3, 0xd2, 0x77, 0x37, 0x64, 0xb9, 0xc1, 0x71, 0x6f, 0x9e, 0xcd, 0x4b, 0x29, 0x05, + 0xe1, 0xb9, 0xe9, 0xaf, 0xcc, 0xd6, 0x89, 0x82, 0xb0, 0xd9, 0x5c, 0x70, 0x10, 0xa0, 0x6a, 0xd9, 0x03, 0x4c, 0xb5, + 0x42, 0x76, 0xea, 0x18, 0x84, 0xf2, 0xdb, 0xc4, 0x7b, 0xf9, 0x7e, 0x7e, 0xbd, 0xe3, 0x91, 0xb9, 0x72, 0xc8, 0x13, + 0x55, 0x76, 0x51, 0x74, 0xb7, 0x08, 0x8f, 0x05, 0xc2, 0x9b, 0x3f, 0x4c, 0x63, 0xbe, 0xae, 0x7b, 0x0a, 0x80, 0x19, + 0x00, 0x9f, 0x10, 0x22, 0x28, 0xd8, 0xcc, 0x74, 0x73, 0x3f, 0xdc, 0xab, 0xa4, 0x6a, 0x78, 0x0a, 0x6c, 0x22, 0x28, + 0xb8, 0xce, 0xd4, 0x63, 0x71, 0x06, 0x9b, 0x7e, 0x44, 0x84, 0x50, 0x9a, 0xe5, 0xb8, 0x19, 0x37, 0xc0, 0x3c, 0x17, + 0x6d, 0xcc, 0xf0, 0x34, 0xd6, 0x84, 0x78, 0x9f, 0xd8, 0x64, 0x4a, 0xc7, 0x05, 0xf9, 0xb2, 0x8b, 0x57, 0xee, 0xfc, + 0x18, 0x65, 0xee, 0x89, 0xc1, 0xb7, 0xc8, 0x1d, 0x73, 0x3f, 0xe2, 0x13, 0x56, 0xd9, 0xb4, 0xbe, 0x04, 0x36, 0x6e, + 0x69, 0x5d, 0x98, 0x68, 0xfe, 0x5b, 0x68, 0x49, 0xe4, 0x0b, 0x76, 0x6d, 0x33, 0x1e, 0xa1, 0xbe, 0xf2, 0xc9, 0xe0, + 0x81, 0x37, 0xff, 0xda, 0xa3, 0xfb, 0x8b, 0x09, 0x84, 0x62, 0x78, 0x2f, 0xdb, 0xc9, 0x5a, 0xde, 0xcb, 0x52, 0x81, + 0xeb, 0x55, 0xbc, 0x26, 0x8f, 0xe9, 0x38, 0x8c, 0xc4, 0xe8, 0x68, 0x50, 0x00, 0xf7, 0x4d, 0xd1, 0xdb, 0x88, 0x71, + 0xa2, 0xa0, 0x0a, 0x55, 0xce, 0xf4, 0x32, 0x8e, 0xb2, 0xbc, 0x4a, 0x1a, 0xfc, 0x6d, 0x3f, 0x6f, 0x52, 0x04, 0x04, + 0x1f, 0xe8, 0x80, 0x9b, 0xfd, 0xd9, 0x98, 0xd3, 0x9a, 0xb6, 0xa4, 0x62, 0x8d, 0x07, 0x44, 0x8e, 0xe8, 0xff, 0x38, + 0x64, 0xb9, 0x66, 0xe8, 0x3e, 0x1a, 0x74, 0x43, 0xc8, 0x1b, 0x11, 0x19, 0x19, 0x0c, 0x90, 0xcd, 0x57, 0x9b, 0xb9, + 0x86, 0x81, 0x30, 0x09, 0xeb, 0x16, 0x0f, 0xfd, 0x12, 0x70, 0x94, 0x8f, 0xb9, 0xdb, 0xbe, 0x60, 0x98, 0xc8, 0x2b, + 0xca, 0x2f, 0x29, 0x38, 0x17, 0x9a, 0x99, 0xb7, 0x1c, 0x80, 0x39, 0xcd, 0x14, 0x14, 0xa6, 0x38, 0x18, 0x95, 0x6d, + 0xad, 0x1f, 0xd2, 0xbc, 0x16, 0xa8, 0x52, 0x30, 0x5c, 0x91, 0xb9, 0xa8, 0x92, 0xbb, 0x9a, 0x77, 0x13, 0x11, 0xa1, + 0xe3, 0xd8, 0x31, 0x67, 0x58, 0x67, 0x0a, 0x32, 0x32, 0x4d, 0x91, 0x6f, 0x1f, 0x21, 0x09, 0x97, 0x88, 0x5a, 0x44, + 0xf7, 0xcb, 0xb9, 0x36, 0xbb, 0x35, 0xa6, 0xa9, 0xae, 0x1d, 0xd2, 0x84, 0x4d, 0x0c, 0x6a, 0xfa, 0x12, 0xc5, 0x87, + 0xd2, 0xf8, 0xed, 0x4e, 0xfb, 0x18, 0x46, 0xb2, 0xb1, 0xf4, 0xdc, 0x38, 0x5c, 0x8d, 0x23, 0xea, 0x58, 0x3d, 0x95, + 0xa2, 0xc6, 0x56, 0x65, 0x0a, 0x6d, 0x91, 0x45, 0x08, 0x80, 0xf3, 0x95, 0xb9, 0x9a, 0xdf, 0x0a, 0x1f, 0x34, 0x67, + 0x9a, 0x55, 0x2a, 0x15, 0x9f, 0x68, 0xd1, 0x54, 0x46, 0x62, 0x71, 0x9b, 0xcb, 0x7d, 0x62, 0xfc, 0xae, 0x95, 0x1b, + 0xc0, 0x6f, 0xd1, 0x2d, 0x77, 0xd5, 0x0c, 0xdc, 0x64, 0x6f, 0xf4, 0x9c, 0x55, 0x06, 0x72, 0x17, 0x32, 0x6f, 0xd0, + 0x70, 0x2d, 0xd9, 0x6e, 0xcd, 0xfb, 0xba, 0x2c, 0xf4, 0x65, 0xec, 0xf2, 0xdb, 0x5c, 0x83, 0x56, 0x7f, 0x1a, 0x76, + 0x57, 0x1a, 0x8e, 0xac, 0x04, 0x3d, 0x0d, 0xe6, 0x80, 0x94, 0xd7, 0xba, 0x7f, 0xbb, 0xaa, 0x00, 0xf8, 0x9b, 0xe9, + 0x22, 0xd1, 0x7c, 0x09, 0xdf, 0x40, 0x63, 0xa0, 0x74, 0x1e, 0xd8, 0xca, 0xd7, 0xb3, 0x76, 0x18, 0xf4, 0xbe, 0x9a, + 0x49, 0x0b, 0xaf, 0xcb, 0x9b, 0x10, 0xf6, 0x0a, 0x97, 0x24, 0xd6, 0x78, 0x58, 0xcd, 0x60, 0x61, 0x1e, 0xee, 0xb0, + 0x52, 0x9b, 0xca, 0x9f, 0x10, 0xd5, 0x25, 0xda, 0xf3, 0xba, 0x8b, 0x25, 0x36, 0x2e, 0xec, 0xfb, 0x25, 0xb9, 0xa0, + 0x3a, 0x50, 0xf4, 0x41, 0x32, 0x31, 0xc7, 0x96, 0x1d, 0x08, 0x5e, 0x1e, 0x56, 0x62, 0x40, 0xc1, 0xbe, 0xe5, 0xa8, + 0x4f, 0x54, 0x1c, 0x40, 0x52, 0x8a, 0x91, 0xf4, 0x8a, 0x57, 0xc4, 0xde, 0xb4, 0x0a, 0x28, 0xfb, 0xdd, 0xba, 0xef, + 0xd9, 0x2a, 0x7f, 0x32, 0xd7, 0xfa, 0xa4, 0xdf, 0x23, 0xe9, 0xbd, 0xa2, 0x7e, 0x1c, 0x80, 0x33, 0xdb, 0xac, 0x7d, + 0x02, 0x67, 0x1e, 0x4b, 0xf7, 0xda, 0x70, 0xd1, 0xee, 0xab, 0x02, 0x98, 0x10, 0x4c, 0x87, 0xaa, 0x35, 0xe3, 0x73, + 0xf9, 0xc4, 0x96, 0xed, 0x9e, 0xf4, 0x9d, 0x14, 0x43, 0x6c, 0x90, 0x31, 0x3c, 0x4b, 0xe4, 0x9c, 0x9a, 0xc7, 0xd3, + 0xa7, 0xa7, 0x7a, 0x26, 0xa5, 0xe7, 0xd9, 0x47, 0x47, 0x1c, 0x28, 0x51, 0x23, 0x4b, 0x86, 0xb6, 0x6f, 0xf5, 0xd1, + 0x0b, 0x5e, 0x0b, 0x80, 0x14, 0x4b, 0x20, 0x4d, 0x33, 0x2a, 0xce, 0xf1, 0xc9, 0x07, 0x09, 0x92, 0xc1, 0x5d, 0x49, + 0xe8, 0x93, 0x16, 0x6a, 0x0d, 0x7e, 0x20, 0x2f, 0xca, 0x8d, 0x03, 0x40, 0xed, 0x1e, 0x32, 0x45, 0xb1, 0x9c, 0x37, + 0xb2, 0x13, 0xee, 0x21, 0x1a, 0x87, 0x7a, 0x54, 0x9a, 0xa7, 0x9c, 0x5e, 0x40, 0xb4, 0x5c, 0xe6, 0xc9, 0x8c, 0x3d, + 0x7b, 0xbe, 0x41, 0xc3, 0x29, 0xb4, 0xf1, 0x25, 0x4e, 0x5b, 0xa7, 0xfe, 0x54, 0x43, 0x71, 0x79, 0x36, 0x5f, 0x26, + 0xea, 0x88, 0x3d, 0xa2, 0x0b, 0xcd, 0xe8, 0x82, 0xde, 0x98, 0xcb, 0x9d, 0xfb, 0x59, 0x01, 0x02, 0x1d, 0x95, 0x17, + 0x43, 0x27, 0x31, 0xc6, 0xab, 0xf4, 0x84, 0x3b, 0x5e, 0x28, 0xa5, 0xfa, 0x00, 0x3e, 0x7f, 0x08, 0xc2, 0x5f, 0x89, + 0xf7, 0x8e, 0x5a, 0x7d, 0xe3, 0x16, 0x27, 0x26, 0x3c, 0x28, 0xc0, 0x4c, 0x87, 0x48, 0x8d, 0x24, 0x74, 0x04, 0xda, + 0x47, 0x81, 0x90, 0xac, 0xa4, 0x5b, 0x53, 0x5e, 0x87, 0x75, 0xea, 0x30, 0x07, 0x3f, 0x2e, 0x18, 0xaf, 0xe5, 0x4d, + 0x37, 0xa2, 0xb7, 0xbe, 0x6e, 0x05, 0xd9, 0x79, 0xdc, 0x83, 0xc8, 0xf8, 0x62, 0x67, 0x8c, 0x29, 0xda, 0x29, 0xa6, + 0x25, 0x15, 0xb3, 0x8f, 0x14, 0xa1, 0xbf, 0x5c, 0x17, 0x67, 0xb6, 0xa6, 0x84, 0xda, 0xc1, 0x04, 0x09, 0xa1, 0xa7, + 0x0a, 0x25, 0x58, 0xb2, 0xfa, 0xe0, 0x25, 0x2e, 0xd2, 0xc1, 0xb6, 0x2a, 0x82, 0x27, 0xf5, 0x7c, 0xf8, 0x6b, 0x47, + 0x84, 0x70, 0x9a, 0xa5, 0x48, 0x88, 0xc5, 0xf6, 0xb1, 0x9a, 0x48, 0x2a, 0x18, 0xd3, 0x3c, 0xe5, 0x03, 0xf6, 0xa0, + 0xf6, 0xe1, 0x26, 0xf5, 0x55, 0xdc, 0x8f, 0xae, 0x97, 0xf8, 0x73, 0x5d, 0x38, 0x0f, 0x86, 0x1a, 0x6f, 0xa9, 0x9c, + 0xb9, 0x1e, 0x35, 0x41, 0x63, 0xe0, 0xd2, 0xa8, 0x3f, 0x43, 0xea, 0xa0, 0xca, 0xc2, 0x78, 0x16, 0xbf, 0x04, 0x71, + 0x6e, 0x8d, 0x29, 0xf7, 0x67, 0x48, 0xe2, 0x71, 0x6f, 0xd4, 0x9f, 0x3d, 0xba, 0xcb, 0x74, 0x85, 0x00, 0xbb, 0x56, + 0xcb, 0x76, 0xd5, 0x5e, 0x42, 0x2e, 0x76, 0xe2, 0x76, 0xa6, 0x55, 0x49, 0xc0, 0x68, 0x4e, 0x53, 0xfd, 0x3d, 0x3e, + 0x0d, 0xf1, 0x2b, 0xd8, 0x70, 0x9f, 0x12, 0x54, 0x4b, 0x32, 0x9f, 0xbe, 0x44, 0x39, 0x7d, 0xa8, 0xb5, 0x6b, 0x83, + 0xc8, 0xa5, 0xeb, 0x08, 0x4f, 0x96, 0x0b, 0x39, 0x3b, 0x4e, 0xe8, 0xde, 0xfc, 0x05, 0x71, 0xa6, 0xa8, 0x45, 0x4d, + 0x81, 0x64, 0xa3, 0xc5, 0x77, 0x3a, 0xb7, 0xd0, 0x72, 0xb9, 0x1c, 0x85, 0x67, 0xdd, 0xfb, 0xb4, 0x5f, 0x91, 0x74, + 0xb5, 0x5e, 0x1b, 0xdd, 0x46, 0x77, 0x2d, 0x55, 0x64, 0x41, 0x1d, 0x1f, 0x29, 0xe3, 0xe5, 0xd0, 0x4a, 0x71, 0xf3, + 0xaa, 0x2c, 0x98, 0xe7, 0x94, 0x7a, 0x75, 0xd9, 0xf7, 0xe7, 0xb7, 0x3e, 0x41, 0x98, 0xb0, 0x47, 0xb5, 0x82, 0x5e, + 0x61, 0xbb, 0x95, 0xb7, 0x15, 0xac, 0x36, 0x69, 0x91, 0xb2, 0x33, 0xa0, 0x2d, 0x8e, 0x4f, 0x31, 0xed, 0x14, 0x05, + 0x8f, 0x3a, 0x6d, 0x74, 0x55, 0x08, 0x13, 0x9e, 0x54, 0xfc, 0xb7, 0x03, 0x33, 0x71, 0x84, 0x73, 0x43, 0x6e, 0x6f, + 0x2b, 0xb9, 0x3e, 0x1e, 0x8c, 0x9e, 0x4e, 0x84, 0x84, 0x06, 0x6d, 0x0c, 0x5e, 0xe5, 0xe0, 0xaf, 0xbf, 0x0b, 0xb1, + 0xc2, 0x87, 0x04, 0x2e, 0x87, 0x6e, 0x94, 0xeb, 0x81, 0x71, 0xcd, 0x17, 0xe8, 0x84, 0x5c, 0x3c, 0x70, 0x90, 0xd9, + 0x91, 0x4f, 0xc8, 0xc8, 0x6f, 0xcc, 0x20, 0x70, 0x4e, 0x4e, 0x56, 0x8c, 0x22, 0x84, 0x0e, 0x76, 0x1e, 0x05, 0x3a, + 0x86, 0x24, 0xe1, 0x57, 0xc7, 0x89, 0xa4, 0xb5, 0xce, 0x7b, 0x5a, 0x7f, 0x78, 0x51, 0x40, 0xf2, 0x0e, 0x62, 0xea, + 0xbe, 0x26, 0x61, 0xf2, 0x1a, 0x13, 0xb7, 0x15, 0xa3, 0xff, 0xcc, 0x4d, 0x60, 0xb6, 0xca, 0xc0, 0x06, 0x2b, 0x73, + 0x3c, 0x9d, 0x89, 0xc2, 0xb3, 0x54, 0x81, 0x79, 0x76, 0xe4, 0xac, 0x94, 0x28, 0x10, 0x28, 0x4a, 0x2d, 0x6d, 0x56, + 0xeb, 0x70, 0x45, 0x39, 0x76, 0x9f, 0x65, 0x0b, 0x95, 0x80, 0x54, 0x47, 0x93, 0x69, 0x6d, 0xf0, 0x81, 0xbb, 0xb3, + 0x5b, 0xc9, 0x28, 0x58, 0x2e, 0xfc, 0x5b, 0xa1, 0x77, 0xa8, 0xa6, 0x22, 0xa6, 0x48, 0xeb, 0xd6, 0x2a, 0x25, 0x45, + 0xd2, 0x00, 0xad, 0xb3, 0x2c, 0x28, 0x82, 0x90, 0x1e, 0xf1, 0x55, 0xb3, 0x80, 0x07, 0xb3, 0xda, 0x22, 0x9b, 0x15, + 0xdc, 0x13, 0xc1, 0xd9, 0x9a, 0x42, 0x89, 0x59, 0xcb, 0x6c, 0xdf, 0x9e, 0x6e, 0xd2, 0xd6, 0x6d, 0x45, 0xcb, 0xa0, + 0x09, 0x7d, 0x4a, 0xd3, 0xe4, 0xdf, 0xb5, 0xd9, 0xc2, 0xe1, 0x03, 0x63, 0x0e, 0x2f, 0x5d, 0x33, 0x0f, 0x00, 0x95, + 0x5a, 0xf4, 0xeb, 0x44, 0x9f, 0x7e, 0xa5, 0x91, 0x1b, 0x52, 0x80, 0x1e, 0x94, 0x82, 0x6c, 0xe4, 0x6b, 0xea, 0xc0, + 0x9d, 0x12, 0x6d, 0x02, 0xcb, 0xad, 0x88, 0x65, 0xc1, 0xea, 0xae, 0xf8, 0xfb, 0x0b, 0xd0, 0xa0, 0x2f, 0x6f, 0x18, + 0xd0, 0x4f, 0xd4, 0xde, 0x1f, 0xea, 0x50, 0x29, 0xc9, 0xed, 0xe9, 0xd2, 0xed, 0x88, 0x02, 0x6a, 0xad, 0x5e, 0x15, + 0x15, 0x9c, 0x67, 0xca, 0x00, 0xd2, 0x0e, 0x69, 0xb0, 0x61, 0x30, 0xea, 0x23, 0xf0, 0xc1, 0x7a, 0x1d, 0xc7, 0x6d, + 0x7b, 0x29, 0xba, 0x97, 0xb3, 0x3b, 0x36, 0x6a, 0x90, 0x09, 0x56, 0x4e, 0x8c, 0x61, 0x74, 0x9f, 0x77, 0xbd, 0xa7, + 0x8e, 0x89, 0x97, 0x4d, 0xaa, 0xa7, 0x98, 0x00, 0x2c, 0x98, 0x29, 0xd8, 0xa6, 0x92, 0x5a, 0x99, 0x10, 0xb4, 0x2d, + 0xe7, 0xca, 0x9a, 0x33, 0x45, 0x39, 0x7b, 0x73, 0xc8, 0xcb, 0x73, 0x73, 0x69, 0x1d, 0x45, 0x14, 0x35, 0x42, 0xda, + 0x2e, 0x8a, 0x97, 0x62, 0xc5, 0xc5, 0x47, 0x02, 0xf7, 0x46, 0xa8, 0x4c, 0x39, 0xee, 0xb8, 0x2a, 0x53, 0xfa, 0xe0, + 0x16, 0xbf, 0x67, 0x4c, 0x22, 0x9e, 0xc0, 0xe4, 0x33, 0x66, 0xc1, 0xf9, 0x42, 0x3f, 0xe2, 0x5d, 0x22, 0xbf, 0xf0, + 0xba, 0x68, 0x2b, 0xfb, 0x4c, 0x8b, 0xa0, 0xd5, 0x7b, 0x38, 0xdd, 0x9a, 0xac, 0xb9, 0x3a, 0x23, 0x47, 0x80, 0xef, + 0x58, 0xb2, 0x47, 0x32, 0x76, 0xe0, 0xb3, 0x58, 0xf4, 0xe0, 0x18, 0x12, 0x9e, 0x31, 0x82, 0xdb, 0x63, 0x9e, 0xcd, + 0xb8, 0x1c, 0x9f, 0xb5, 0x2e, 0x9e, 0xf3, 0xda, 0xeb, 0x5a, 0x91, 0x9e, 0x92, 0xd9, 0x3c, 0xe2, 0x4d, 0x43, 0xd2, + 0x79, 0xff, 0xb9, 0x47, 0x38, 0xe7, 0x1a, 0x58, 0xc5, 0x9d, 0x70, 0x5d, 0xaa, 0xd0, 0xe7, 0xe7, 0x7b, 0xe8, 0xb3, + 0x51, 0xd2, 0x5d, 0x5c, 0xa7, 0x3c, 0x9a, 0x7e, 0xb6, 0x24, 0x1e, 0xf6, 0x38, 0x1e, 0x5f, 0xd2, 0xdf, 0xd6, 0x36, + 0x40, 0xd9, 0x6a, 0x1b, 0x23, 0xd4, 0xa6, 0x39, 0x05, 0x7e, 0xbf, 0xcf, 0x71, 0x74, 0x34, 0x9e, 0xda, 0x35, 0xf0, + 0xe9, 0x7d, 0x01, 0xba, 0xaa, 0xb4, 0x7a, 0xe7, 0xe9, 0x1d, 0x2e, 0xcc, 0x06, 0xb9, 0xd7, 0x88, 0x2c, 0x83, 0xb9, + 0x5c, 0x70, 0xb2, 0xab, 0x7e, 0x48, 0xa5, 0xb4, 0x9f, 0xf9, 0xef, 0x07, 0x5d, 0x4e, 0xf7, 0xc9, 0x61, 0x1b, 0xc8, + 0x95, 0x38, 0x33, 0x2a, 0xac, 0xbe, 0x69, 0x69, 0x49, 0x3f, 0xe3, 0x32, 0x0c, 0x04, 0x44, 0xf9, 0xbf, 0x78, 0x38, + 0x48, 0xc8, 0x5b, 0x27, 0x24, 0x45, 0xd5, 0x9a, 0xd5, 0x24, 0x2f, 0xf6, 0x23, 0xa4, 0xe0, 0x50, 0x24, 0x4b, 0x5f, + 0xb4, 0x3f, 0x97, 0x88, 0x42, 0x06, 0x81, 0x51, 0x06, 0x49, 0x10, 0xad, 0xa3, 0x5b, 0x3d, 0xed, 0x24, 0xbd, 0x3c, + 0x40, 0x5f, 0xe9, 0xf9, 0xfb, 0x11, 0x0e, 0x41, 0x59, 0x73, 0xfd, 0xdc, 0x8a, 0x6c, 0xe7, 0xcf, 0x5d, 0x55, 0x58, + 0x07, 0x44, 0x2c, 0x66, 0x39, 0x5a, 0xcc, 0x8b, 0xa2, 0x64, 0xef, 0xba, 0x03, 0xf8, 0x15, 0xde, 0x99, 0x73, 0x55, + 0x5c, 0xc8, 0x31, 0x7d, 0x25, 0xae, 0xe8, 0x1c, 0x1e, 0xd1, 0x4a, 0xda, 0x96, 0xc8, 0xfe, 0x72, 0x68, 0x97, 0x9c, + 0x50, 0xa1, 0x15, 0x6e, 0x69, 0x36, 0xa7, 0xe7, 0x00, 0xc2, 0x8a, 0x2f, 0x08, 0xa5, 0xdc, 0xf3, 0x4a, 0xa7, 0x0e, + 0x86, 0xce, 0xdc, 0xa4, 0x08, 0x7d, 0x37, 0x66, 0x4e, 0x25, 0xf9, 0xd1, 0x8f, 0xed, 0xa2, 0x0a, 0xfb, 0x9f, 0xc3, + 0x95, 0x12, 0xc9, 0x7d, 0xef, 0x56, 0xb7, 0x24, 0xda, 0xf4, 0xb2, 0x22, 0x99, 0x63, 0x1d, 0xed, 0x73, 0x5a, 0x16, + 0xef, 0xae, 0x04, 0x23, 0x98, 0x3d, 0x30, 0x23, 0x9c, 0x8b, 0x41, 0x31, 0x6e, 0x99, 0x0a, 0x0b, 0xe6, 0x21, 0x72, + 0xbb, 0xeb, 0xa2, 0xca, 0x9d, 0x4c, 0x6e, 0xce, 0xf3, 0xf0, 0xb2, 0xb0, 0x62, 0xa1, 0x14, 0xbb, 0x38, 0xb7, 0x7e, + 0xe3, 0xde, 0xb7, 0xd4, 0x85, 0x25, 0xff, 0x1a, 0x4f, 0x23, 0x3c, 0x3d, 0xc2, 0xa8, 0xfc, 0x00, 0xbb, 0xb1, 0x13, + 0x7d, 0x25, 0x06, 0xe8, 0xf1, 0x9e, 0x1c, 0xbf, 0x5c, 0xde, 0x8b, 0x8e, 0x33, 0x9c, 0x30, 0xd2, 0xb8, 0xcd, 0x17, + 0xc4, 0xe9, 0x30, 0x37, 0x69, 0xc6, 0x8a, 0x7a, 0x24, 0x82, 0xf1, 0xd2, 0xfa, 0xb7, 0x2d, 0x4f, 0xf3, 0xf7, 0xf9, + 0x33, 0xc9, 0x17, 0xd3, 0x15, 0xf0, 0xf5, 0xe0, 0xcf, 0xd3, 0xfe, 0x40, 0x22, 0x10, 0x3d, 0x84, 0x23, 0x3d, 0xa6, + 0x65, 0x69, 0xf7, 0xec, 0xd8, 0x22, 0xf4, 0xfa, 0xb3, 0x44, 0x50, 0xea, 0x85, 0x52, 0xea, 0x0d, 0xca, 0x38, 0x25, + 0x81, 0x4d, 0x97, 0x42, 0x88, 0xf2, 0xfd, 0xdf, 0x38, 0x79, 0x8a, 0xf0, 0xb3, 0xe6, 0x94, 0xf6, 0x2a, 0x6a, 0x0a, + 0xea, 0x8c, 0x02, 0x60, 0x25, 0xee, 0xe3, 0x01, 0xb4, 0x6c, 0xa8, 0x0b, 0xae, 0x30, 0xa8, 0x5a, 0x95, 0x93, 0x40, + 0x9d, 0x6c, 0x14, 0x11, 0xb9, 0x29, 0xbe, 0x8b, 0x88, 0xc8, 0x1a, 0x06, 0xe5, 0x1c, 0x6c, 0x99, 0xce, 0x25, 0xc3, + 0xee, 0x36, 0xb5, 0xbc, 0xf0, 0x5e, 0x4d, 0x7a, 0xcc, 0xca, 0x76, 0xb8, 0x8f, 0x1c, 0x1d, 0x67, 0xb7, 0x7c, 0x91, + 0x38, 0x4c, 0xe2, 0x5a, 0xbd, 0xb7, 0x87, 0xac, 0xdd, 0x21, 0xe9, 0xaf, 0x05, 0x37, 0xdd, 0x21, 0xb3, 0x50, 0xda, + 0xbe, 0x3e, 0xfb, 0xa9, 0xba, 0xc3, 0xc0, 0x1b, 0x00, 0x4f, 0x31, 0xee, 0xfe, 0x6a, 0x6e, 0x43, 0xf5, 0xf8, 0x67, + 0x0f, 0x5d, 0x91, 0x48, 0x0b, 0xcc, 0x62, 0x0f, 0x87, 0x75, 0xd9, 0x4a, 0xdd, 0xb5, 0x71, 0x6e, 0x03, 0xe2, 0x8c, + 0x94, 0x90, 0x54, 0x0e, 0xd9, 0x28, 0x59, 0x1e, 0x51, 0x06, 0x6b, 0xbd, 0xbd, 0x74, 0x17, 0x73, 0x0f, 0xc3, 0x05, + 0x80, 0x92, 0x80, 0x65, 0x7b, 0xac, 0xb5, 0xfb, 0x00, 0x30, 0x42, 0xab, 0xc6, 0xcc, 0xe8, 0x55, 0xdc, 0x2a, 0xeb, + 0xc5, 0x8a, 0xcc, 0xa8, 0x1f, 0x6a, 0x22, 0x77, 0x07, 0x52, 0xd1, 0x56, 0xa8, 0x2c, 0xbf, 0x94, 0x4a, 0x4f, 0xab, + 0x02, 0xad, 0xd4, 0xd5, 0x8a, 0x0e, 0xba, 0x91, 0x92, 0xa2, 0x44, 0xdb, 0xb9, 0x00, 0xb9, 0xf2, 0x66, 0x18, 0x78, + 0x13, 0xd8, 0x2a, 0x32, 0x22, 0x81, 0x6b, 0xe1, 0xa9, 0x88, 0x24, 0x2f, 0xea, 0xae, 0x55, 0x35, 0x29, 0x8d, 0xb3, + 0x06, 0x9e, 0x6e, 0x29, 0xf2, 0x0b, 0x8d, 0x30, 0x2d, 0xf5, 0x41, 0x06, 0x89, 0xb4, 0x48, 0xe4, 0x7c, 0x5e, 0xbb, + 0x1f, 0xa2, 0x8e, 0x53, 0x74, 0x3c, 0x24, 0xdb, 0x6e, 0xbb, 0x14, 0x25, 0x87, 0x89, 0xee, 0x24, 0x16, 0xd3, 0x11, + 0x03, 0x95, 0xb2, 0x21, 0xc7, 0xd2, 0x6b, 0xd7, 0x8a, 0x13, 0xb8, 0xf8, 0x0f, 0xf9, 0xd8, 0xe6, 0xd9, 0x86, 0x61, + 0x0b, 0x2d, 0xcb, 0x11, 0xfd, 0xe5, 0xa5, 0x84, 0x0e, 0xd2, 0x12, 0x3d, 0xe4, 0x07, 0xc5, 0xb2, 0xab, 0x90, 0x35, + 0xe8, 0xa0, 0x71, 0xee, 0x4c, 0x66, 0x0b, 0x89, 0x94, 0x69, 0x52, 0x6b, 0x5a, 0x6c, 0x42, 0xc4, 0x33, 0x3f, 0x58, + 0x15, 0xa2, 0x46, 0x3c, 0xc8, 0x54, 0x58, 0x0a, 0xce, 0x16, 0x41, 0xe2, 0x4b, 0x9c, 0x1d, 0xce, 0x8b, 0xdd, 0x60, + 0x91, 0x45, 0xef, 0x30, 0xea, 0xcb, 0x61, 0x5f, 0xb7, 0x22, 0x36, 0xbd, 0x35, 0x2e, 0x3c, 0xaf, 0x99, 0xb5, 0x6a, + 0x47, 0x8c, 0x39, 0x43, 0x18, 0x29, 0x04, 0xf9, 0xe8, 0xd3, 0x11, 0xce, 0x8a, 0x53, 0x81, 0x0d, 0x1b, 0xd7, 0xb1, + 0xc3, 0xd9, 0x87, 0xba, 0x8b, 0xa0, 0xe1, 0xb9, 0x3a, 0x22, 0x48, 0xcc, 0x78, 0x83, 0x51, 0x2b, 0x34, 0xdf, 0xe8, + 0x3a, 0x6f, 0xcd, 0x74, 0xf3, 0x8d, 0xa4, 0x47, 0x69, 0xe1, 0x91, 0xdf, 0x62, 0x52, 0x71, 0xe6, 0xd6, 0x7e, 0x90, + 0x25, 0xd6, 0xfd, 0x0f, 0x41, 0xfc, 0x8a, 0x80, 0xea, 0x24, 0x21, 0x20, 0x40, 0x43, 0xeb, 0x7a, 0xa1, 0xd9, 0x56, + 0x58, 0x09, 0x0a, 0xcf, 0x55, 0xf0, 0x5f, 0x92, 0xa2, 0x61, 0xd2, 0x84, 0x26, 0x1e, 0x95, 0xfb, 0xb1, 0x83, 0x05, + 0xe2, 0x2c, 0x20, 0x8a, 0xc1, 0x49, 0x50, 0x09, 0x09, 0xb7, 0x54, 0x42, 0x7b, 0xa1, 0x15, 0x13, 0x2c, 0x80, 0x69, + 0x4f, 0x5c, 0x4a, 0x81, 0x62, 0xda, 0x8a, 0xa3, 0x39, 0x56, 0x43, 0x80, 0x61, 0x90, 0x51, 0x7f, 0x04, 0x5d, 0xac, + 0x61, 0x9a, 0x8c, 0xf7, 0xbb, 0x78, 0xe1, 0xe9, 0xe6, 0x74, 0x85, 0x52, 0x16, 0xf9, 0x2c, 0xc0, 0x09, 0xcd, 0xf8, + 0xa4, 0x00, 0xf5, 0x45, 0xbd, 0xb4, 0xf1, 0xdc, 0x3a, 0x9e, 0x83, 0x27, 0xe7, 0x8d, 0xe0, 0x6d, 0x1c, 0x54, 0xee, + 0x60, 0x0f, 0x60, 0x91, 0xd7, 0x5c, 0x33, 0x92, 0xcc, 0x18, 0x1e, 0x0d, 0xf3, 0x8c, 0xb9, 0x53, 0x42, 0xdb, 0x33, + 0xb9, 0x09, 0x5c, 0x9b, 0x06, 0xab, 0x86, 0xa5, 0x1f, 0xaf, 0xae, 0xd7, 0x5c, 0x1f, 0x40, 0xee, 0xdb, 0x96, 0x12, + 0x76, 0x37, 0x22, 0x8d, 0x31, 0x60, 0x9b, 0x50, 0xbd, 0x3f, 0x21, 0x9b, 0xa6, 0x5a, 0xd6, 0xc1, 0x61, 0xce, 0x2f, + 0x12, 0x54, 0xee, 0x41, 0xdb, 0x54, 0x16, 0xa1, 0xd7, 0x3c, 0xee, 0x89, 0x3e, 0x4f, 0xb8, 0x21, 0x58, 0x83, 0xd4, + 0x89, 0x8b, 0xab, 0xf2, 0x24, 0x41, 0x37, 0x5a, 0x6a, 0x2b, 0x96, 0x07, 0x03, 0x2e, 0xca, 0xb1, 0x1b, 0x92, 0x52, + 0xc1, 0x51, 0x92, 0xf4, 0x34, 0x96, 0x6a, 0x97, 0xdb, 0x6f, 0x33, 0x2e, 0xf5, 0x8e, 0x12, 0x9a, 0xd0, 0x69, 0x21, + 0x23, 0x0d, 0x84, 0x02, 0xb5, 0xb9, 0xbf, 0x4c, 0xdf, 0x8c, 0x3e, 0xc3, 0xb0, 0x91, 0x8b, 0xe1, 0x01, 0x94, 0xb3, + 0xda, 0x71, 0x38, 0xc7, 0xc3, 0xb2, 0x90, 0x5e, 0x30, 0x99, 0x21, 0xb2, 0x44, 0x2e, 0x7f, 0xd4, 0xa4, 0xe4, 0x02, + 0x1d, 0x4b, 0x6b, 0x1e, 0xd0, 0xae, 0x4e, 0x70, 0xa0, 0x3b, 0x7c, 0xd5, 0xc9, 0x57, 0x75, 0x14, 0xc9, 0x1c, 0x43, + 0xe7, 0xc0, 0xe2, 0x54, 0xcb, 0xb3, 0x91, 0x9d, 0xee, 0x0e, 0x70, 0x5e, 0x4a, 0xb7, 0x0b, 0x70, 0xd7, 0xfe, 0xc5, + 0x89, 0x8b, 0xe7, 0xb6, 0xd5, 0x60, 0x8b, 0xce, 0x74, 0x08, 0xe7, 0xcf, 0xd4, 0xcd, 0x09, 0x6f, 0xa1, 0xcb, 0xa9, + 0xfd, 0xb9, 0xe0, 0xfa, 0xe3, 0x15, 0xdd, 0x6e, 0xeb, 0x82, 0xc3, 0x72, 0x94, 0xb3, 0x2e, 0x89, 0x54, 0xb2, 0xd2, + 0x1b, 0x7d, 0x3e, 0x90, 0xa7, 0x0d, 0xb6, 0x5f, 0x28, 0x98, 0x39, 0x75, 0x50, 0xac, 0x62, 0x92, 0xd9, 0xe1, 0xc1, + 0xe4, 0xbb, 0xb2, 0x58, 0x32, 0x56, 0x27, 0xb3, 0xdc, 0x81, 0x71, 0x4b, 0x6b, 0xef, 0x57, 0x76, 0x29, 0xe3, 0xcb, + 0x88, 0x72, 0x2b, 0xaf, 0x8d, 0x83, 0x4c, 0xdb, 0x25, 0xb2, 0xdc, 0xd6, 0xb7, 0xcb, 0x34, 0x7b, 0x48, 0xd2, 0xed, + 0x04, 0xc9, 0x77, 0x06, 0x9f, 0x18, 0x52, 0xa2, 0x17, 0x52, 0xeb, 0xf1, 0xb5, 0x77, 0x95, 0x38, 0x45, 0xbc, 0x2a, + 0x06, 0x61, 0x65, 0x7d, 0x8e, 0x2d, 0x69, 0x16, 0xa8, 0x63, 0x15, 0x49, 0xdc, 0x2a, 0x24, 0x7e, 0x69, 0xf5, 0x17, + 0xb6, 0xdc, 0xa8, 0xfc, 0x14, 0x89, 0x77, 0x88, 0xfe, 0x72, 0x5c, 0xa2, 0x7b, 0xad, 0x0a, 0x44, 0x19, 0xe6, 0xa9, + 0x9c, 0xb1, 0x60, 0xe9, 0xe6, 0x89, 0x2c, 0x9a, 0x3d, 0x5f, 0x6e, 0xa0, 0x49, 0x94, 0x88, 0xcd, 0x85, 0x5e, 0xe6, + 0xce, 0x19, 0xe8, 0xe8, 0x24, 0xac, 0x53, 0xab, 0xc9, 0xc4, 0x1e, 0x83, 0xb3, 0x97, 0xac, 0xe8, 0x09, 0xae, 0x7b, + 0xce, 0x3b, 0xfb, 0xaf, 0xb9, 0x70, 0x3a, 0x34, 0xfb, 0xe9, 0xfc, 0x98, 0x61, 0x96, 0x8e, 0x14, 0xb8, 0x25, 0x76, + 0xab, 0x3b, 0x11, 0x65, 0x4c, 0xfb, 0xc4, 0x58, 0x5d, 0xdf, 0x76, 0x8a, 0x8e, 0xc9, 0xbf, 0x99, 0xa7, 0xe1, 0xdc, + 0x39, 0x51, 0x62, 0x37, 0x39, 0x61, 0xb7, 0xd6, 0xdd, 0xf3, 0xe0, 0x67, 0x84, 0x18, 0xa5, 0x14, 0x6c, 0x82, 0x7a, + 0xab, 0xaa, 0x02, 0xe6, 0x69, 0x58, 0x34, 0x63, 0x4f, 0x14, 0x91, 0x5d, 0x7f, 0x27, 0x66, 0x8e, 0x29, 0x8b, 0x2e, + 0x59, 0x93, 0xc1, 0x54, 0x4d, 0xa9, 0x3b, 0x92, 0x1a, 0xb9, 0x83, 0x84, 0xec, 0x6f, 0x8d, 0x14, 0x81, 0x7a, 0xa3, + 0x71, 0x71, 0x6f, 0x0d, 0x8c, 0x69, 0xa0, 0xd9, 0xd6, 0x2c, 0x1d, 0xa8, 0x03, 0x37, 0xda, 0xd6, 0x85, 0x4a, 0xd5, + 0x76, 0xe1, 0xeb, 0x57, 0xfb, 0xbc, 0xcf, 0xac, 0x05, 0x6d, 0x18, 0xfa, 0x19, 0xd8, 0x26, 0xc5, 0xfd, 0x17, 0x22, + 0x4d, 0x15, 0xa5, 0xd8, 0x77, 0x20, 0x9b, 0x75, 0x6f, 0xad, 0x82, 0x90, 0x93, 0xaa, 0xf4, 0x7d, 0x9a, 0xf5, 0xa4, + 0xd3, 0x95, 0x65, 0x65, 0xb6, 0x8d, 0xdf, 0xee, 0x86, 0xed, 0x83, 0x85, 0xcd, 0x2b, 0x95, 0x4e, 0xa4, 0x83, 0x08, + 0x0c, 0x83, 0xe7, 0xd0, 0x97, 0x7e, 0xa0, 0xf2, 0x7b, 0xa0, 0xfa, 0xac, 0x8c, 0x1d, 0xae, 0xbd, 0xd0, 0x78, 0x01, + 0x5d, 0x90, 0x70, 0x3f, 0x4d, 0x2a, 0xa7, 0x61, 0x52, 0x83, 0x8e, 0xb6, 0xba, 0x4e, 0x2c, 0x0f, 0x44, 0x80, 0x7f, + 0x28, 0x50, 0x8d, 0x99, 0x01, 0x76, 0x3d, 0x09, 0x6c, 0xab, 0x59, 0xd6, 0x43, 0x2f, 0x38, 0x9c, 0xae, 0xa0, 0xbb, + 0x97, 0x5f, 0x31, 0x0e, 0x72, 0x87, 0x5d, 0x29, 0xb0, 0x3e, 0x39, 0x72, 0x2c, 0x50, 0x3b, 0x47, 0x0d, 0x0c, 0xbb, + 0x45, 0x6d, 0xb8, 0xef, 0x53, 0x6a, 0x76, 0x43, 0xb8, 0x1b, 0x1c, 0xb8, 0xa5, 0x62, 0xdb, 0xf2, 0xa8, 0xd2, 0xfc, + 0x65, 0x3b, 0x50, 0x46, 0xeb, 0x8d, 0x51, 0xef, 0xed, 0xee, 0x43, 0x49, 0x4a, 0xdb, 0xcf, 0x97, 0xf9, 0x24, 0xd9, + 0x7b, 0x65, 0x96, 0xba, 0x7a, 0x3f, 0x35, 0xb9, 0x5d, 0xad, 0xa9, 0xd2, 0x99, 0x0a, 0x0e, 0x85, 0x72, 0x9e, 0x5d, + 0xb9, 0x93, 0x12, 0x2b, 0x6c, 0xee, 0xa5, 0x1b, 0x41, 0x7a, 0xec, 0x24, 0x53, 0x62, 0x42, 0x48, 0x9d, 0xfd, 0x76, + 0x67, 0xee, 0x0f, 0x57, 0xdf, 0x92, 0xa2, 0xbe, 0xe3, 0xa6, 0xe5, 0x78, 0xe9, 0xb7, 0xcb, 0x8d, 0x32, 0x98, 0x46, + 0xd1, 0x60, 0x69, 0x19, 0x1c, 0x74, 0xd7, 0x32, 0xc0, 0xb9, 0x4b, 0xfc, 0x5d, 0x3f, 0xae, 0x68, 0xda, 0x00, 0x5d, + 0x16, 0xfb, 0x84, 0x72, 0x49, 0x1c, 0x94, 0xf0, 0x48, 0xd3, 0x26, 0x4d, 0x88, 0x14, 0x39, 0xd8, 0xb6, 0x90, 0x81, + 0x21, 0x59, 0x88, 0x62, 0x50, 0xf9, 0x55, 0xae, 0x4e, 0x78, 0x9d, 0xcf, 0x16, 0xbc, 0x84, 0x28, 0x5c, 0x95, 0x71, + 0x75, 0xa3, 0x66, 0x31, 0xaf, 0x0e, 0x3b, 0xa9, 0xa6, 0x0d, 0x0d, 0x63, 0xd4, 0x11, 0xb9, 0xdb, 0xf8, 0xe0, 0x9d, + 0x2d, 0xd4, 0x0c, 0x16, 0xdf, 0xa9, 0x09, 0xf8, 0x6b, 0x7d, 0xf1, 0x16, 0x42, 0x0e, 0x71, 0x9e, 0x56, 0x68, 0x78, + 0xa1, 0xac, 0xd1, 0xb8, 0x17, 0xb2, 0x1a, 0xfb, 0xb9, 0xcb, 0x20, 0x6d, 0x38, 0x19, 0x94, 0x8e, 0xc3, 0xa5, 0x7c, + 0x97, 0xd4, 0x2d, 0xbd, 0x41, 0x89, 0xb8, 0x0e, 0x60, 0x27, 0x6a, 0xa9, 0x74, 0x51, 0x49, 0xeb, 0xa7, 0x86, 0xf2, + 0x64, 0xd8, 0x4b, 0xe7, 0x64, 0x60, 0xcc, 0xe8, 0x3c, 0xd4, 0x8c, 0x41, 0xb4, 0x86, 0x65, 0xd8, 0xa0, 0x7d, 0xac, + 0x5e, 0x20, 0xfb, 0x44, 0xd3, 0xaa, 0x33, 0x74, 0xd8, 0xc9, 0x84, 0x5f, 0xaa, 0x53, 0x31, 0x65, 0xfe, 0x95, 0x99, + 0xb6, 0xcd, 0xfb, 0x6e, 0x34, 0x94, 0x37, 0x97, 0x7e, 0xcc, 0xf9, 0x15, 0x97, 0x02, 0x97, 0x0b, 0x68, 0x0d, 0xf7, + 0x90, 0x7f, 0xc3, 0xbc, 0xec, 0xd7, 0x76, 0x60, 0x02, 0x11, 0xa7, 0x1a, 0x8d, 0x73, 0x4a, 0x8e, 0xa6, 0x3a, 0xe7, + 0x7d, 0x13, 0xce, 0x28, 0x95, 0x06, 0x64, 0xd4, 0xb2, 0x48, 0x26, 0xc1, 0x4c, 0x07, 0xcd, 0x0b, 0x67, 0x1b, 0xed, + 0xa4, 0xd1, 0xc1, 0xeb, 0x4d, 0xdc, 0x75, 0x41, 0x93, 0x5e, 0x11, 0x3f, 0x76, 0xd4, 0x56, 0x8c, 0x53, 0x17, 0x2e, + 0x02, 0xcf, 0xe4, 0x2c, 0x8b, 0x43, 0x99, 0xf4, 0x7a, 0x45, 0xd5, 0xb2, 0xa4, 0xb3, 0x54, 0x0f, 0xe8, 0x12, 0xd4, + 0xe3, 0xd3, 0xa2, 0xbc, 0x62, 0x35, 0x98, 0xef, 0x40, 0xd9, 0x6b, 0x97, 0xd0, 0xf3, 0x7d, 0xa1, 0x0e, 0x32, 0x1a, + 0xbb, 0xf3, 0xf9, 0x92, 0x1a, 0x93, 0x03, 0xe7, 0x4d, 0xf3, 0x0a, 0x67, 0xd7, 0x5b, 0x52, 0x0b, 0xa1, 0x4f, 0xda, + 0xa0, 0x67, 0x89, 0x84, 0xbf, 0x83, 0x3a, 0x9c, 0xdd, 0x20, 0xa9, 0x33, 0x6c, 0xca, 0xe9, 0xa7, 0xa0, 0x35, 0xe1, + 0x62, 0x23, 0x0b, 0xdb, 0x87, 0x1e, 0x54, 0x9b, 0x47, 0x76, 0x71, 0xb8, 0xa3, 0x98, 0x36, 0x83, 0xb0, 0x96, 0xe0, + 0xa1, 0x34, 0xf4, 0x16, 0x9b, 0xfe, 0x7c, 0x23, 0xc3, 0xe5, 0x26, 0xc9, 0xc2, 0x95, 0xe9, 0xd1, 0x10, 0x60, 0xd7, + 0xee, 0xf7, 0xb6, 0x3a, 0x05, 0x7f, 0x09, 0x0f, 0x46, 0x31, 0x7d, 0x3e, 0x7b, 0x65, 0x80, 0xfd, 0x44, 0x4f, 0xa7, + 0xfb, 0xa6, 0x50, 0x3a, 0x87, 0x5c, 0x62, 0x5d, 0x18, 0x63, 0x8c, 0xa3, 0x7a, 0xb7, 0xa3, 0x8c, 0xbd, 0xe4, 0xd8, + 0x01, 0x0f, 0x85, 0x0f, 0x77, 0x94, 0xf2, 0xaa, 0x1d, 0x6b, 0x37, 0xb9, 0xe6, 0x1b, 0xf9, 0x88, 0x1c, 0xbd, 0xa4, + 0x18, 0xa4, 0x65, 0x23, 0xa0, 0x19, 0x83, 0x97, 0x48, 0x0b, 0xd2, 0x36, 0xf4, 0xb3, 0xcc, 0x75, 0x42, 0xa1, 0x05, + 0x9c, 0x9e, 0x31, 0xa8, 0x28, 0x2c, 0x3a, 0xaa, 0xa4, 0xfd, 0x87, 0x03, 0x42, 0x06, 0xa3, 0xd5, 0xda, 0x6c, 0xcb, + 0xf6, 0xa6, 0xc9, 0x1f, 0x6c, 0x3f, 0xd1, 0x9b, 0xe9, 0x43, 0x7e, 0x7a, 0x1c, 0x03, 0x5f, 0x35, 0xb7, 0x6b, 0x3c, + 0xaf, 0xf7, 0x5e, 0x55, 0x93, 0x6f, 0xfd, 0x55, 0x8e, 0x8f, 0xa1, 0x86, 0x64, 0xe9, 0x44, 0xe9, 0xf2, 0xb0, 0xf7, + 0xb3, 0x3e, 0xb1, 0x4f, 0x16, 0x26, 0xd3, 0x3b, 0x93, 0xd8, 0x8c, 0xd7, 0x9d, 0x6f, 0x30, 0xae, 0x8c, 0x78, 0x65, + 0xfd, 0x56, 0x9f, 0xc9, 0xc1, 0xf6, 0x12, 0x30, 0x52, 0xaf, 0x2c, 0x05, 0x0e, 0x0a, 0x3a, 0x71, 0x08, 0x1e, 0x22, + 0xcf, 0x71, 0xe6, 0x86, 0x2f, 0x6a, 0x5d, 0x93, 0x88, 0xc8, 0x97, 0xf5, 0x2c, 0x4f, 0x21, 0x73, 0x24, 0x6c, 0xb9, + 0x9e, 0x3e, 0x06, 0x4e, 0x95, 0xb6, 0xec, 0x2f, 0x9b, 0xad, 0xe6, 0xfa, 0x10, 0xfc, 0x23, 0xd2, 0x5d, 0xfc, 0x1a, + 0xc7, 0x23, 0x8d, 0x64, 0x21, 0x55, 0xb5, 0x90, 0x5b, 0x16, 0x0d, 0x16, 0x32, 0x8c, 0x2f, 0x2b, 0x53, 0xd9, 0x8b, + 0x3b, 0x50, 0x22, 0x5f, 0xdf, 0xc2, 0x19, 0x0e, 0x87, 0xd0, 0xf9, 0xeb, 0x9b, 0x2a, 0x43, 0x56, 0x3f, 0xef, 0xd9, + 0x88, 0x63, 0xac, 0x8f, 0xad, 0xb7, 0x37, 0xbd, 0x5b, 0x81, 0xc8, 0x19, 0x27, 0xdb, 0xa7, 0x5f, 0x71, 0xbf, 0x56, + 0xf8, 0x7a, 0xd8, 0x54, 0xf8, 0xf5, 0xd6, 0xc5, 0x81, 0xac, 0x20, 0xe3, 0x09, 0x0b, 0x46, 0x20, 0xc5, 0x63, 0x83, + 0x0e, 0x1a, 0xa7, 0x0c, 0xa8, 0x37, 0xb0, 0xaf, 0x9b, 0x3a, 0xf2, 0xf5, 0x65, 0xf6, 0xb7, 0xe9, 0xb2, 0x1f, 0x40, + 0x96, 0x7d, 0xfe, 0x01, 0x1b, 0xb6, 0xa5, 0xbb, 0x01, 0xb3, 0x37, 0x90, 0x19, 0x99, 0xf6, 0x4b, 0xa4, 0x8f, 0x30, + 0x68, 0x9b, 0xcb, 0x00, 0xae, 0x4d, 0xfa, 0xf3, 0xf9, 0x18, 0x42, 0x0c, 0x21, 0x2c, 0xe3, 0x9d, 0x1b, 0xef, 0x46, + 0xfa, 0xa6, 0xd1, 0x2d, 0x52, 0xfc, 0x17, 0xf1, 0x2c, 0x0b, 0x38, 0x0f, 0x91, 0x3a, 0xc1, 0x55, 0xbd, 0x6c, 0x4f, + 0x90, 0x2a, 0xd7, 0xe2, 0xf5, 0xe1, 0x1b, 0x89, 0xc5, 0x9e, 0x88, 0x8f, 0x39, 0xd4, 0x39, 0x64, 0x3a, 0x89, 0x66, + 0xe9, 0x2b, 0x75, 0x40, 0x28, 0x27, 0x60, 0x7e, 0x96, 0x58, 0xeb, 0x94, 0x1c, 0xc2, 0xdb, 0x37, 0xff, 0x26, 0xca, + 0x3d, 0x78, 0x2c, 0x29, 0x86, 0x29, 0x5a, 0x88, 0x31, 0x8e, 0x8b, 0xa7, 0x75, 0x9d, 0x90, 0x11, 0xeb, 0xcf, 0xcf, + 0x56, 0x99, 0xad, 0x81, 0x1a, 0x49, 0x43, 0xe1, 0x90, 0x1b, 0x1d, 0x33, 0x0b, 0x93, 0x0b, 0xe3, 0x6c, 0xdd, 0x16, + 0xef, 0x24, 0xf2, 0xa8, 0x7c, 0x33, 0x0e, 0x8f, 0xd4, 0xe3, 0x90, 0x8d, 0xb4, 0xca, 0x92, 0x4e, 0xb8, 0x13, 0x0c, + 0x87, 0xc9, 0xa2, 0x8c, 0xcd, 0x2c, 0xa4, 0x10, 0xad, 0xe4, 0x04, 0x20, 0x7b, 0x38, 0x41, 0x2d, 0x04, 0x66, 0x95, + 0x61, 0x65, 0x28, 0x0c, 0x88, 0x38, 0x08, 0x77, 0x9f, 0xfc, 0xb1, 0xc0, 0xfe, 0x56, 0x1e, 0x43, 0xf2, 0xe1, 0x97, + 0x38, 0x42, 0x0f, 0xc6, 0xb5, 0x50, 0x06, 0x13, 0x21, 0x7a, 0xcb, 0x18, 0xce, 0x53, 0x9d, 0x78, 0x8b, 0xde, 0x3a, + 0xd1, 0x0d, 0x24, 0x04, 0x71, 0xb3, 0x96, 0xf3, 0x0d, 0xac, 0x28, 0x0b, 0x1c, 0x34, 0x61, 0x9d, 0x15, 0x5b, 0xb1, + 0x4d, 0xc1, 0x43, 0x94, 0xe4, 0x00, 0xf8, 0x32, 0x40, 0xae, 0x4e, 0xb2, 0x2b, 0x25, 0xb0, 0x0e, 0xe1, 0xa4, 0x60, + 0xa6, 0x31, 0xb2, 0xe6, 0xd5, 0xa6, 0xf6, 0x61, 0x56, 0x8d, 0x6f, 0x00, 0xa6, 0xbe, 0x72, 0x4e, 0xd8, 0x66, 0x97, + 0x8e, 0x6a, 0xb1, 0x2d, 0x16, 0xfd, 0x8f, 0x7b, 0x51, 0x03, 0x5e, 0xbd, 0x1e, 0x67, 0xff, 0x0b, 0x46, 0xe7, 0x0e, + 0x88, 0x7e, 0x75, 0xef, 0xb0, 0xcd, 0x01, 0x9b, 0x64, 0x55, 0xdb, 0x48, 0x9c, 0x0e, 0x78, 0x4e, 0xaa, 0x75, 0x92, + 0x46, 0x41, 0xf5, 0xc4, 0xa6, 0x7b, 0x1d, 0x59, 0x71, 0xd6, 0x44, 0x01, 0x5b, 0xc5, 0x1a, 0xe1, 0x82, 0xf1, 0xe5, + 0x42, 0xdc, 0x6c, 0xbb, 0x00, 0x86, 0x30, 0xd6, 0xac, 0xb8, 0xc6, 0x07, 0xbf, 0x3d, 0x05, 0xd4, 0x13, 0x96, 0x78, + 0x08, 0xfb, 0x1a, 0x84, 0x93, 0xf9, 0xf0, 0xb3, 0x59, 0xdf, 0x7c, 0x83, 0xaa, 0xcb, 0x10, 0xf3, 0xfc, 0x24, 0xa7, + 0xc7, 0xdf, 0x2e, 0x3f, 0x74, 0x3a, 0x4b, 0x3f, 0xe3, 0x3a, 0x4b, 0x84, 0x79, 0xf7, 0xd3, 0x1f, 0x4d, 0x6b, 0x03, + 0x6f, 0xd1, 0x55, 0x73, 0x51, 0x33, 0xce, 0x9d, 0x3d, 0x27, 0x9b, 0x08, 0x7b, 0x4a, 0x80, 0x4a, 0x35, 0x57, 0xf5, + 0x9b, 0x22, 0xf5, 0x31, 0xb6, 0xa9, 0xe2, 0xe3, 0x09, 0xd0, 0x52, 0xbe, 0xb9, 0xa3, 0x0b, 0x26, 0x41, 0xd6, 0xfd, + 0x7c, 0xcb, 0xa8, 0xd0, 0xc0, 0xb0, 0x1f, 0x13, 0xc2, 0x79, 0xfa, 0x89, 0x80, 0x91, 0xb4, 0x93, 0x4d, 0xfa, 0x20, + 0xe9, 0xb1, 0x89, 0x22, 0xe7, 0x4c, 0xc3, 0xf8, 0x8c, 0x13, 0x68, 0x0c, 0x58, 0x5a, 0x16, 0x1d, 0xca, 0x4a, 0xdb, + 0xc4, 0x9f, 0xc8, 0x77, 0x63, 0x13, 0x5b, 0x0d, 0x41, 0x1a, 0x4c, 0x80, 0x36, 0xc3, 0xe9, 0x0c, 0x74, 0x41, 0x17, + 0xbd, 0xb9, 0x79, 0x6f, 0xb9, 0xf9, 0x30, 0x32, 0x0f, 0x5d, 0xfe, 0x9c, 0xd8, 0x8a, 0xb7, 0x26, 0x75, 0x4e, 0xd5, + 0xb5, 0x2e, 0xe9, 0x4c, 0x7f, 0xc2, 0xb6, 0x12, 0x4b, 0x88, 0xbc, 0xa3, 0xfd, 0x21, 0x3c, 0x84, 0xb4, 0x45, 0xc9, + 0x89, 0xed, 0x9f, 0x14, 0x2b, 0x39, 0x9e, 0x6c, 0x2c, 0xfb, 0x69, 0x53, 0xfb, 0x5b, 0xa4, 0x83, 0xdd, 0x57, 0xea, + 0x87, 0x55, 0x5c, 0x12, 0x35, 0x5c, 0x8b, 0x2e, 0x28, 0xfd, 0x0b, 0xd3, 0x49, 0x62, 0xd5, 0xe5, 0x18, 0xf7, 0x2c, + 0x99, 0x63, 0x7d, 0x0c, 0x0a, 0x4f, 0x57, 0x91, 0x4c, 0xe8, 0xbc, 0x86, 0xba, 0x34, 0xbd, 0xeb, 0xea, 0x14, 0xe1, + 0x0d, 0x65, 0xce, 0x5b, 0x6d, 0x89, 0xda, 0xe9, 0x7d, 0xcd, 0xff, 0x6e, 0x50, 0x64, 0x93, 0x91, 0x9c, 0x07, 0xce, + 0x60, 0x2d, 0xc9, 0xe0, 0x51, 0x89, 0x28, 0x2a, 0x1f, 0x62, 0xf3, 0x45, 0xae, 0xa0, 0x97, 0xa7, 0x88, 0x8a, 0xbb, + 0x65, 0xb1, 0xf3, 0x31, 0x7f, 0x50, 0x5b, 0xa2, 0x0e, 0x4b, 0x2a, 0x4a, 0x60, 0x65, 0xdd, 0x4f, 0x23, 0x2e, 0xf5, + 0x9f, 0xe2, 0xf6, 0xfb, 0x95, 0xc7, 0x70, 0x45, 0xde, 0xdb, 0x14, 0x5d, 0xd1, 0x0e, 0x8e, 0xba, 0x61, 0xd9, 0x2d, + 0x7f, 0x48, 0x03, 0x92, 0x3d, 0xb7, 0x7a, 0x78, 0x08, 0x9f, 0x27, 0xff, 0xb0, 0xac, 0xfd, 0x65, 0x55, 0x49, 0x0f, + 0xa5, 0x91, 0x42, 0x1f, 0xa9, 0xe6, 0xc7, 0x15, 0xdd, 0xde, 0x4f, 0xad, 0x5b, 0xaf, 0x1f, 0x60, 0xf6, 0x51, 0x86, + 0xc8, 0xda, 0x2c, 0x5b, 0xf5, 0x01, 0x2a, 0x18, 0x5a, 0xf1, 0x19, 0xf4, 0x44, 0xd3, 0xa4, 0x5e, 0x79, 0x33, 0x3a, + 0x33, 0x73, 0x90, 0x71, 0x68, 0xb9, 0xfc, 0xf1, 0x1b, 0x11, 0x13, 0x93, 0xaa, 0xa5, 0xb6, 0x28, 0xc3, 0xf5, 0x82, + 0x93, 0x28, 0x11, 0x4f, 0x30, 0xa7, 0xdf, 0xa5, 0xf4, 0x82, 0x39, 0x14, 0xac, 0x70, 0x8e, 0x3e, 0x9f, 0x95, 0x72, + 0x29, 0x09, 0xf9, 0xb6, 0x84, 0x6c, 0xa1, 0x21, 0x94, 0x52, 0x6e, 0x39, 0x1a, 0x97, 0x73, 0x38, 0x65, 0x6c, 0xf6, + 0x14, 0x26, 0x3e, 0x15, 0xaf, 0x62, 0xde, 0xe8, 0xf5, 0x35, 0x62, 0x91, 0x72, 0xd9, 0x05, 0x09, 0x0b, 0x67, 0x24, + 0x97, 0x18, 0xd9, 0x04, 0x2b, 0x9c, 0x5b, 0xa8, 0x06, 0xb3, 0xae, 0x0d, 0x94, 0xaa, 0x6f, 0x40, 0x8f, 0x86, 0x7c, + 0xd5, 0xd4, 0xb9, 0xea, 0x7f, 0x3a, 0xa1, 0x11, 0x2f, 0x0b, 0xdf, 0x71, 0x1f, 0x4a, 0x4f, 0xaf, 0x90, 0x11, 0xd7, + 0x6d, 0x27, 0x1d, 0x68, 0xc6, 0xc8, 0x48, 0x98, 0xa3, 0x45, 0x9d, 0x8b, 0x06, 0xda, 0x28, 0xc4, 0x95, 0x04, 0x2d, + 0xa4, 0x11, 0x92, 0x54, 0xec, 0x5c, 0x06, 0x4e, 0x1a, 0x48, 0x4f, 0x12, 0x14, 0x32, 0xe4, 0x61, 0xee, 0x7f, 0x25, + 0x65, 0xd1, 0xd4, 0xc2, 0x25, 0xe6, 0xb7, 0xf2, 0xfd, 0xa9, 0x2d, 0x5a, 0xb5, 0x0e, 0x14, 0x90, 0xca, 0x23, 0xd6, + 0x2c, 0x9b, 0x71, 0xaf, 0x38, 0x2a, 0xc7, 0xa3, 0xd2, 0xd6, 0x94, 0x9a, 0xae, 0x68, 0x1e, 0x34, 0xa5, 0x87, 0xe9, + 0x94, 0xd8, 0x1a, 0xcb, 0xab, 0x53, 0x4b, 0xa5, 0xfa, 0xf7, 0x99, 0xa5, 0xba, 0x38, 0x6a, 0xf9, 0x26, 0xb0, 0xd8, + 0x9d, 0x83, 0x09, 0x0d, 0xf7, 0x99, 0xcd, 0xa7, 0x30, 0x2c, 0xa7, 0xcc, 0xb2, 0xec, 0xc1, 0xd2, 0x66, 0x42, 0xd0, + 0xe6, 0x3b, 0x8c, 0x13, 0xf2, 0x8c, 0x18, 0x50, 0x48, 0xa9, 0x91, 0xaf, 0xcd, 0x06, 0x31, 0xf8, 0x89, 0xdb, 0x9f, + 0xe8, 0x22, 0x41, 0xc1, 0x11, 0x3d, 0x1f, 0x1c, 0x72, 0x3c, 0x7e, 0x90, 0xa9, 0x19, 0x46, 0xb0, 0x14, 0x2f, 0x67, + 0xd6, 0xd3, 0x12, 0x10, 0x10, 0x4d, 0xf2, 0x5e, 0xbd, 0x11, 0x81, 0x9a, 0x59, 0x09, 0x51, 0x07, 0x27, 0x0c, 0xbf, + 0x08, 0x31, 0xe0, 0x8c, 0x02, 0x10, 0x8e, 0x39, 0x3d, 0x20, 0x87, 0xaf, 0x73, 0x96, 0x7e, 0x4b, 0x4b, 0xe5, 0xa8, + 0xed, 0x45, 0x61, 0x9a, 0x3e, 0x8e, 0x05, 0x0e, 0x95, 0x04, 0xd5, 0x4b, 0x61, 0xb4, 0xd8, 0xf0, 0x7b, 0xe1, 0xea, + 0xd0, 0x27, 0x6f, 0xee, 0xc3, 0x6b, 0xce, 0x3a, 0x7c, 0x4c, 0xc2, 0x8e, 0x49, 0xc1, 0x85, 0x9d, 0xba, 0x6c, 0xe4, + 0x40, 0x00, 0x60, 0x6f, 0xeb, 0xcf, 0x13, 0xde, 0x66, 0xcb, 0x58, 0xd0, 0xf1, 0xf6, 0x0d, 0x3e, 0x1c, 0x02, 0x3f, + 0xea, 0xed, 0x68, 0x99, 0xa4, 0x7b, 0xd2, 0x90, 0xba, 0x97, 0x35, 0x6c, 0xc1, 0xe4, 0x9c, 0x5f, 0xa0, 0xa3, 0xb7, + 0x99, 0xa3, 0xe4, 0xbe, 0xe8, 0xeb, 0x01, 0x21, 0x8d, 0x07, 0x65, 0x70, 0x84, 0x35, 0x9e, 0x31, 0x23, 0x6f, 0xf5, + 0xcd, 0x76, 0xce, 0x5a, 0x60, 0x2b, 0xb4, 0xb6, 0xda, 0x20, 0x66, 0xa1, 0xfa, 0xb7, 0x37, 0x95, 0x00, 0x46, 0xd0, + 0xb0, 0xcf, 0x4b, 0xfa, 0x46, 0xd5, 0xa9, 0x7f, 0x9f, 0x7b, 0x73, 0x51, 0x64, 0x98, 0x93, 0x28, 0xc6, 0x57, 0xcc, + 0x29, 0xfa, 0x45, 0x29, 0x52, 0x03, 0xb7, 0x79, 0x99, 0x95, 0x58, 0x73, 0x46, 0x3d, 0xc2, 0x73, 0x4a, 0x32, 0x07, + 0x6c, 0xc5, 0xbf, 0x8d, 0x76, 0x2a, 0x94, 0x7c, 0x54, 0xff, 0x15, 0x7f, 0x90, 0xa0, 0x80, 0x91, 0xe1, 0x4e, 0x07, + 0x61, 0xd5, 0xb2, 0xee, 0x74, 0xdb, 0x83, 0x8f, 0x2b, 0xa2, 0xa5, 0xb3, 0xd5, 0x95, 0xd7, 0x63, 0xe7, 0x6f, 0x8f, + 0xbf, 0xfd, 0x67, 0x63, 0x11, 0x33, 0x8e, 0x37, 0xe0, 0xa7, 0x88, 0xdb, 0x50, 0x0a, 0x1a, 0xe1, 0xcb, 0xf0, 0x71, + 0x64, 0x98, 0x7f, 0x93, 0x79, 0x37, 0xed, 0xf5, 0x7d, 0xb1, 0xe7, 0xe9, 0x2c, 0xa8, 0xd6, 0xc6, 0x49, 0xce, 0x4a, + 0x5c, 0xae, 0xe4, 0xc8, 0x87, 0xaf, 0xc4, 0xad, 0xe3, 0x7b, 0xab, 0x12, 0xce, 0xf5, 0xf8, 0x46, 0x8e, 0x95, 0x61, + 0x50, 0xba, 0x45, 0xe7, 0x40, 0x2c, 0xc3, 0xd7, 0x12, 0x09, 0xd9, 0xe9, 0x07, 0x84, 0x61, 0xf4, 0x8b, 0x9f, 0x1f, + 0x4d, 0x98, 0x59, 0xed, 0x1f, 0x39, 0x18, 0x8e, 0x5d, 0x4c, 0x23, 0x30, 0x42, 0x2c, 0xa1, 0x90, 0xd2, 0x41, 0x1f, + 0xc1, 0x95, 0x54, 0xd9, 0x07, 0xdc, 0xce, 0x7c, 0x42, 0x65, 0x7f, 0x64, 0x67, 0x7d, 0xef, 0x44, 0x7c, 0x52, 0xb3, + 0xfb, 0xbd, 0x56, 0x55, 0x7b, 0x77, 0xbd, 0x16, 0x59, 0x62, 0x07, 0x4b, 0x60, 0x87, 0xc5, 0x8c, 0xc5, 0x96, 0x18, + 0x2e, 0x68, 0xcf, 0xea, 0x78, 0x0f, 0x4c, 0xc6, 0xf0, 0x63, 0x15, 0xb3, 0x4c, 0x0e, 0xd2, 0x6d, 0x95, 0xe9, 0xd9, + 0x1e, 0x95, 0x9b, 0x3f, 0x54, 0x96, 0xec, 0xe1, 0xff, 0x33, 0x3f, 0xce, 0x60, 0x8e, 0xe2, 0xeb, 0x45, 0x96, 0xe4, + 0x86, 0x7a, 0xcd, 0x7e, 0xfc, 0xab, 0xb1, 0xed, 0x31, 0x24, 0x82, 0xcd, 0xdd, 0x6a, 0x6b, 0x3f, 0x03, 0x14, 0xa7, + 0xac, 0x02, 0x29, 0x4a, 0xa6, 0x63, 0x8e, 0x6c, 0xd0, 0xa1, 0x38, 0x18, 0x04, 0x8f, 0xbb, 0x4f, 0xad, 0x5a, 0xe0, + 0xe9, 0x0a, 0x57, 0x20, 0x63, 0x37, 0x96, 0xb5, 0xd5, 0xcf, 0xda, 0x78, 0x3f, 0xa2, 0x27, 0x21, 0xb0, 0x64, 0xbd, + 0x0f, 0xf0, 0x51, 0xb0, 0x97, 0x0d, 0x00, 0xca, 0x5b, 0xbe, 0xb6, 0x6f, 0x9f, 0x9f, 0x53, 0xa7, 0xb9, 0x6c, 0x3f, + 0xb1, 0x77, 0xe2, 0x33, 0x67, 0xae, 0xaa, 0xb3, 0xdc, 0xd2, 0x7d, 0x0c, 0x81, 0x20, 0x46, 0xc3, 0x03, 0x42, 0x06, + 0x8c, 0x9e, 0xe2, 0x1d, 0x67, 0xc6, 0x3f, 0x9b, 0x27, 0x35, 0x4e, 0xf6, 0x1f, 0xde, 0x58, 0x78, 0x2d, 0x2d, 0x81, + 0xde, 0x45, 0xf8, 0xdf, 0xde, 0x95, 0x67, 0x1d, 0x13, 0x4d, 0x50, 0x75, 0x70, 0xb5, 0x53, 0x5f, 0xf5, 0x26, 0x37, + 0x6f, 0x15, 0x63, 0xcf, 0xfb, 0xd8, 0x16, 0x3e, 0x12, 0x0a, 0x4d, 0xe1, 0xa3, 0x2d, 0x9b, 0xaf, 0xca, 0x75, 0xe8, + 0x07, 0xb3, 0x6c, 0x74, 0x49, 0xd6, 0x10, 0x4e, 0xef, 0x13, 0x59, 0x6c, 0x3b, 0x99, 0x4d, 0xc4, 0xf5, 0x47, 0xc0, + 0x00, 0x1e, 0xeb, 0xa2, 0xf6, 0x54, 0xdd, 0x96, 0x7a, 0xd4, 0xa5, 0x9e, 0xfb, 0x9d, 0xe6, 0xed, 0xb9, 0xb8, 0xd9, + 0xa6, 0xf7, 0x05, 0x9f, 0x5a, 0x8b, 0x8e, 0x20, 0xdf, 0xd2, 0x8d, 0x72, 0x01, 0x80, 0x0c, 0xf0, 0xc2, 0xb8, 0x89, + 0x2e, 0xab, 0xfd, 0xb1, 0xf7, 0xa3, 0x35, 0xb6, 0xc7, 0x66, 0x53, 0x6e, 0x64, 0x87, 0xd9, 0xc5, 0x81, 0xb2, 0xe3, + 0xd8, 0xf8, 0x0e, 0x7b, 0x8d, 0x87, 0x17, 0x6a, 0x46, 0x0a, 0x6b, 0x89, 0xde, 0x9b, 0x3a, 0xa9, 0x67, 0x9f, 0x1b, + 0x9c, 0x15, 0xee, 0x8b, 0xb9, 0x14, 0xde, 0x27, 0x8e, 0x5a, 0x1d, 0x00, 0x98, 0x6e, 0x60, 0x82, 0x23, 0x3a, 0xfd, + 0x58, 0x12, 0xfc, 0x77, 0x1d, 0x74, 0x2b, 0x4e, 0xe0, 0xb6, 0x14, 0x77, 0xa3, 0x96, 0xcb, 0xf7, 0xb3, 0x83, 0x90, + 0x52, 0x5c, 0x75, 0x76, 0x20, 0xf2, 0x3a, 0x50, 0x11, 0x72, 0x0a, 0x09, 0x01, 0x87, 0x4b, 0xd9, 0xa5, 0x60, 0x92, + 0x04, 0xf4, 0x53, 0xe1, 0xbe, 0x50, 0xf6, 0x92, 0xdb, 0x8d, 0xda, 0xf2, 0x47, 0x32, 0x04, 0x54, 0xcd, 0xc5, 0xb4, + 0xb6, 0x45, 0x70, 0x3c, 0x75, 0xc4, 0x7c, 0x7a, 0xac, 0xbf, 0x39, 0x90, 0xf4, 0x34, 0xf0, 0xc8, 0xc0, 0xe2, 0x6d, + 0x89, 0xd1, 0xd5, 0x8e, 0x37, 0xac, 0xec, 0x1d, 0x17, 0x5b, 0xcc, 0x41, 0x3d, 0xb1, 0xc2, 0x80, 0xf7, 0x31, 0x32, + 0x35, 0xe9, 0xc1, 0x55, 0xec, 0x54, 0x58, 0x0e, 0xcb, 0xc9, 0x02, 0xc4, 0x51, 0xea, 0x97, 0x2f, 0x73, 0xde, 0xe8, + 0x6b, 0xd6, 0x12, 0xca, 0xb0, 0x94, 0x63, 0x75, 0xb9, 0x4c, 0x1e, 0x36, 0x86, 0xac, 0x38, 0x9f, 0xb6, 0x9d, 0xa5, + 0xa2, 0x09, 0x2b, 0x88, 0x76, 0x5c, 0x23, 0x84, 0x64, 0xbf, 0x90, 0x4e, 0xd6, 0xec, 0xf0, 0x0b, 0x96, 0xd5, 0x92, + 0xd2, 0xb9, 0x25, 0xd9, 0x93, 0x19, 0xf0, 0x73, 0x04, 0x19, 0x49, 0x4a, 0x4c, 0xec, 0xa4, 0x0b, 0xc1, 0x63, 0x0d, + 0xc3, 0xd3, 0xa2, 0xac, 0x97, 0xc9, 0xa2, 0xd5, 0x8d, 0x4e, 0x3d, 0x29, 0x1e, 0x18, 0x74, 0x90, 0x58, 0x52, 0x73, + 0x88, 0xc8, 0x3f, 0x99, 0xa8, 0x0b, 0x41, 0x84, 0x64, 0xd3, 0x91, 0x4c, 0x25, 0x25, 0xeb, 0x45, 0x88, 0x23, 0x1f, + 0x90, 0x2b, 0x79, 0x44, 0x96, 0xe4, 0xd5, 0x77, 0x90, 0xc9, 0x3b, 0xd1, 0x4a, 0x8a, 0xed, 0x6c, 0x08, 0x71, 0xcf, + 0xdc, 0x64, 0x0c, 0x41, 0x26, 0x3c, 0x4f, 0xc9, 0xd8, 0x1a, 0x19, 0xe9, 0x13, 0xf2, 0xe4, 0xc0, 0x42, 0xa9, 0xbd, + 0x4a, 0x0a, 0x2c, 0x4b, 0x90, 0x85, 0x76, 0xf2, 0xa7, 0x2c, 0xa9, 0xe5, 0x91, 0x03, 0xdb, 0xa7, 0xf5, 0x84, 0x82, + 0x4c, 0x11, 0x21, 0xc7, 0x3e, 0x37, 0x02, 0x18, 0xe5, 0x61, 0x05, 0x4a, 0xe7, 0x39, 0xe1, 0x45, 0x9e, 0x23, 0x4a, + 0xe4, 0xc5, 0xc0, 0x1a, 0x55, 0xbc, 0xab, 0x91, 0xfa, 0x2b, 0x08, 0xb9, 0x50, 0xe0, 0xe1, 0x5e, 0x74, 0x7a, 0x9e, + 0xdf, 0x14, 0xeb, 0x2f, 0x18, 0x6f, 0xca, 0xea, 0xa2, 0x95, 0x1b, 0x46, 0x8a, 0x66, 0xc4, 0xf9, 0x99, 0xbb, 0x78, + 0x82, 0x4f, 0x95, 0x8c, 0xa8, 0x1c, 0xc5, 0x8c, 0x0b, 0xdf, 0x87, 0xc9, 0xbf, 0x8b, 0x6e, 0x41, 0xd1, 0x7d, 0xdb, + 0xac, 0x8d, 0x44, 0x43, 0x5c, 0x95, 0x93, 0xcf, 0x7b, 0xa4, 0xa6, 0xc1, 0x50, 0x71, 0x8b, 0xe7, 0x99, 0x51, 0xef, + 0x21, 0x3e, 0x33, 0x0a, 0x6a, 0x93, 0x84, 0x2b, 0x39, 0xc1, 0xc6, 0x84, 0x97, 0x7c, 0xa9, 0x16, 0x19, 0xc5, 0xec, + 0xbe, 0x52, 0xf9, 0xe5, 0x42, 0xd1, 0x3c, 0x4d, 0x50, 0x50, 0x4a, 0x4b, 0xd5, 0x88, 0xbe, 0x1a, 0x78, 0x88, 0x9c, + 0x6e, 0x74, 0x7e, 0x1b, 0xb9, 0x70, 0x08, 0x64, 0x8b, 0x57, 0x5e, 0xf8, 0x4c, 0xc3, 0x52, 0xed, 0xd0, 0x3e, 0x83, + 0x25, 0x4e, 0x95, 0xd1, 0x11, 0xfe, 0x67, 0x22, 0x58, 0xb4, 0xb9, 0x11, 0x78, 0x4b, 0x59, 0x49, 0x1d, 0xa7, 0x7e, + 0x83, 0xf2, 0x9e, 0x8e, 0xf2, 0x5a, 0xf9, 0xca, 0x24, 0x99, 0x31, 0x57, 0xa3, 0x31, 0x28, 0xc8, 0xc7, 0x8b, 0xf9, + 0x26, 0x00, 0x93, 0xe8, 0x76, 0x62, 0x33, 0x68, 0x87, 0xc8, 0xaa, 0x3c, 0x14, 0x77, 0x9a, 0xaf, 0xa7, 0xf3, 0x46, + 0x9e, 0x43, 0xb8, 0x85, 0xda, 0x44, 0xa3, 0x6e, 0xa2, 0xab, 0x26, 0xa0, 0x4c, 0xf2, 0x73, 0xd8, 0x01, 0x5e, 0xca, + 0x9c, 0x00, 0xac, 0x47, 0x6a, 0x4c, 0x70, 0x3b, 0x10, 0x7f, 0xa9, 0x75, 0xf5, 0x9c, 0x72, 0xba, 0xad, 0x9a, 0x55, + 0x0b, 0x14, 0x7b, 0x00, 0x2a, 0xcf, 0x9f, 0xdf, 0x9e, 0x7a, 0x1b, 0xc1, 0x56, 0xec, 0x60, 0x54, 0x32, 0xe7, 0x2a, + 0xcb, 0x06, 0xa5, 0x76, 0xcb, 0xb9, 0x69, 0x20, 0xbe, 0x7b, 0x50, 0x5d, 0xbd, 0xe0, 0x8f, 0x3b, 0x6b, 0xe3, 0x1d, + 0x07, 0xa8, 0x3d, 0xf2, 0x93, 0x17, 0x9a, 0xf4, 0x01, 0xc1, 0x1b, 0x4e, 0xd7, 0x09, 0xab, 0x09, 0x63, 0x24, 0x62, + 0x86, 0x02, 0x32, 0xa5, 0xfe, 0xb9, 0x0b, 0x34, 0xe7, 0x5f, 0xbc, 0xef, 0x40, 0xc1, 0xa1, 0x68, 0xe0, 0x3a, 0xaf, + 0x1e, 0x5e, 0xfa, 0x94, 0x1d, 0xc5, 0x18, 0xf7, 0x2d, 0xd7, 0x5b, 0xac, 0xb9, 0xd6, 0x8a, 0xf3, 0xbb, 0x74, 0x3f, + 0xb4, 0x9b, 0xe2, 0xf9, 0x06, 0xdd, 0x27, 0xb7, 0x8f, 0x73, 0xe0, 0x4f, 0x54, 0xc9, 0xa4, 0x58, 0x57, 0x38, 0xf2, + 0xa8, 0x02, 0x4d, 0xbd, 0xb7, 0x6d, 0xe3, 0x0d, 0xc6, 0x1b, 0x10, 0xfd, 0x3d, 0xa8, 0xe2, 0xa6, 0x33, 0xdc, 0xb7, + 0xba, 0xe5, 0xa4, 0x09, 0x14, 0x5a, 0x45, 0x10, 0x57, 0x5c, 0xe0, 0xe7, 0xbd, 0x00, 0x39, 0xc0, 0x1e, 0x20, 0x0d, + 0xf0, 0x68, 0x45, 0x0f, 0x21, 0x63, 0x4c, 0x6c, 0x4b, 0x2d, 0x39, 0x8b, 0x1d, 0x7b, 0x38, 0x69, 0xf2, 0x26, 0x59, + 0x1b, 0xb7, 0xf4, 0xb0, 0x10, 0x6d, 0x7d, 0xc5, 0xb3, 0x7e, 0x13, 0x72, 0x12, 0x20, 0x56, 0x5b, 0x7c, 0x4a, 0xa6, + 0x1c, 0xb7, 0xfb, 0x2b, 0x89, 0x1f, 0x7d, 0x9c, 0xd8, 0x71, 0x08, 0xa4, 0xf6, 0xa9, 0x29, 0x5c, 0x6f, 0x77, 0xd1, + 0x77, 0xaf, 0x1f, 0x7f, 0x4b, 0x57, 0xd1, 0xf5, 0xa7, 0x69, 0x77, 0xdd, 0xe9, 0xed, 0x7b, 0x2d, 0xc9, 0xb2, 0xcc, + 0x7a, 0xd7, 0x9f, 0x26, 0x77, 0x8c, 0x1b, 0xaf, 0x28, 0x07, 0x1a, 0x58, 0xef, 0xdf, 0xa0, 0xb4, 0x3b, 0xb4, 0xd0, + 0x37, 0xab, 0x0f, 0xa3, 0x02, 0x9b, 0xaa, 0xc1, 0x66, 0x87, 0x93, 0x9c, 0xcc, 0x89, 0x62, 0xe8, 0x0f, 0xa2, 0x13, + 0xb0, 0x0e, 0x5f, 0xb2, 0xa5, 0xf9, 0x03, 0x1c, 0xe0, 0xfa, 0xc2, 0x07, 0x4c, 0x68, 0xa2, 0xcd, 0x06, 0x5b, 0xeb, + 0x7f, 0xf7, 0xa9, 0x77, 0x8e, 0xd1, 0x8f, 0x6b, 0xfb, 0xcd, 0x3f, 0x1d, 0x6f, 0x71, 0x8e, 0x77, 0x45, 0xd2, 0x0e, + 0xe4, 0xc8, 0x19, 0x92, 0xdc, 0xee, 0xe2, 0xb0, 0x9f, 0xd9, 0xe5, 0x69, 0xee, 0xbe, 0xfb, 0xa9, 0x98, 0x60, 0x72, + 0x27, 0x67, 0xa9, 0x02, 0xf1, 0xef, 0x06, 0x01, 0x70, 0xb7, 0xec, 0xd7, 0x51, 0xd3, 0xd6, 0x4b, 0xee, 0x3c, 0xab, + 0x5a, 0x8d, 0xf5, 0x76, 0xeb, 0x00, 0xff, 0x5d, 0xf8, 0x00, 0x69, 0xac, 0xe7, 0xbe, 0xc7, 0xba, 0x66, 0x64, 0x0d, + 0x82, 0xdd, 0xe6, 0x61, 0x54, 0x95, 0x70, 0x88, 0x41, 0x3c, 0x91, 0x07, 0x7f, 0x01, 0xa2, 0xdf, 0xed, 0xcd, 0xfe, + 0xd3, 0xe1, 0x00, 0xe8, 0xe0, 0x8f, 0x37, 0x59, 0x73, 0x88, 0x3d, 0x81, 0x75, 0x07, 0x8c, 0x73, 0xa3, 0x49, 0x74, + 0x02, 0x5c, 0xf2, 0xae, 0x3c, 0x59, 0x74, 0xf9, 0xdc, 0xc7, 0x40, 0xe8, 0x7a, 0x8f, 0x84, 0x25, 0xd0, 0x58, 0x60, + 0x0d, 0x6c, 0xfc, 0xa0, 0x58, 0xfe, 0xb5, 0xb7, 0x54, 0x3d, 0x5d, 0xb7, 0x86, 0x79, 0xad, 0xe3, 0xf2, 0x8d, 0x38, + 0xda, 0x29, 0xc4, 0xb3, 0x5e, 0xca, 0x6b, 0xa2, 0x37, 0x0d, 0x7e, 0x6e, 0x1a, 0x7b, 0xa0, 0xe0, 0x23, 0xbe, 0xb8, + 0x30, 0x6f, 0x58, 0xef, 0xf6, 0xb3, 0x03, 0x98, 0x35, 0xe2, 0x30, 0x60, 0xa7, 0x05, 0xbf, 0xe9, 0x61, 0x3c, 0x27, + 0x66, 0x2b, 0x28, 0x08, 0x31, 0x57, 0x4f, 0x5e, 0x73, 0xcd, 0x6b, 0xb3, 0x22, 0x6b, 0x89, 0xcf, 0xb8, 0x76, 0x01, + 0xa0, 0x25, 0x1a, 0x65, 0xee, 0x5b, 0x90, 0x3a, 0xe5, 0xf5, 0xb2, 0x9c, 0x09, 0x8e, 0x05, 0xad, 0x9d, 0x80, 0xa7, + 0xc3, 0xb9, 0x98, 0x37, 0x29, 0x1c, 0x7d, 0xc5, 0xa2, 0xdb, 0x57, 0x21, 0x95, 0x58, 0x28, 0x0b, 0x1f, 0x3e, 0x8b, + 0x29, 0xd9, 0xec, 0x0d, 0x10, 0x58, 0x0c, 0xde, 0x77, 0x41, 0x7b, 0xdd, 0x30, 0x64, 0xe9, 0xe0, 0x60, 0x25, 0xee, + 0xf2, 0x6e, 0x44, 0x94, 0x3f, 0x7e, 0xfc, 0xcf, 0x4a, 0x76, 0x23, 0x97, 0x61, 0x78, 0x91, 0xd8, 0x3d, 0xcb, 0x36, + 0xdf, 0xa6, 0x31, 0x6a, 0xc8, 0x69, 0xf9, 0x87, 0x3a, 0x6e, 0x69, 0x46, 0x8a, 0x33, 0x1f, 0x40, 0xbe, 0x2d, 0xbb, + 0x08, 0x01, 0x06, 0xf3, 0x96, 0x44, 0x6c, 0xd3, 0xaf, 0x47, 0x88, 0x35, 0xfb, 0x7c, 0x03, 0xc9, 0x9d, 0xd6, 0x14, + 0xda, 0x12, 0x45, 0xce, 0x05, 0x15, 0x5d, 0x32, 0xce, 0xd7, 0x15, 0x36, 0xba, 0xc7, 0x31, 0x52, 0x29, 0x63, 0xdc, + 0xe4, 0x89, 0xa6, 0xfc, 0xc6, 0x42, 0x35, 0xf8, 0xcb, 0xec, 0x89, 0xb1, 0x3c, 0x1f, 0x0f, 0x89, 0x3e, 0x12, 0xfe, + 0x3a, 0x4e, 0xcc, 0xa0, 0xee, 0xee, 0xaf, 0x74, 0x09, 0xb3, 0x65, 0xea, 0xb5, 0xc1, 0x48, 0x54, 0x6e, 0x64, 0xef, + 0x2f, 0xe2, 0x10, 0x2b, 0xf3, 0x9c, 0x2f, 0x08, 0x0f, 0xbc, 0xd7, 0x28, 0x5e, 0x90, 0x3a, 0xff, 0x91, 0xcc, 0xf1, + 0x50, 0xa2, 0xe0, 0x35, 0xcc, 0x73, 0xef, 0x1d, 0x21, 0x40, 0xdb, 0x56, 0xc0, 0xc9, 0x3c, 0x49, 0x0e, 0xed, 0x2f, + 0x01, 0x75, 0xa5, 0x1b, 0xe4, 0x41, 0xb8, 0xd8, 0x5a, 0x93, 0x10, 0xdf, 0xff, 0xc4, 0xad, 0x44, 0x42, 0x74, 0x36, + 0xec, 0x68, 0x0a, 0x80, 0x3d, 0xe4, 0x0c, 0x26, 0xac, 0x69, 0x7f, 0x3a, 0x4e, 0x98, 0x55, 0x39, 0xeb, 0x5d, 0xa8, + 0xaa, 0x58, 0x39, 0x55, 0x03, 0x25, 0x01, 0x8d, 0x66, 0xda, 0x46, 0x8e, 0x44, 0x43, 0x94, 0x17, 0x0d, 0x70, 0x74, + 0x60, 0xdb, 0x04, 0x99, 0xd4, 0xe1, 0xdb, 0x0c, 0x8a, 0x24, 0xb0, 0xff, 0x6b, 0x28, 0x84, 0xe2, 0xb6, 0xec, 0x17, + 0xb1, 0xf0, 0xda, 0x34, 0xd8, 0xd7, 0x4e, 0xf6, 0x9c, 0x73, 0x8e, 0x76, 0x41, 0x34, 0x93, 0xb0, 0x7d, 0xbc, 0x88, + 0xf9, 0xa8, 0x61, 0x9a, 0xab, 0x3c, 0x55, 0x63, 0xbf, 0x09, 0x5d, 0x76, 0x07, 0xbd, 0x26, 0x47, 0x69, 0xc9, 0xa8, + 0xfd, 0x08, 0x6c, 0xd8, 0xc1, 0xf8, 0x2b, 0x5a, 0x17, 0x39, 0x3d, 0xad, 0x36, 0xfa, 0x66, 0x11, 0x09, 0xa0, 0x09, + 0xc1, 0xea, 0xd3, 0x04, 0xde, 0xc3, 0x25, 0x7a, 0x79, 0xcf, 0xd8, 0x06, 0x52, 0x79, 0x6f, 0x82, 0xa3, 0x31, 0x50, + 0x9f, 0xe4, 0x1c, 0x68, 0x11, 0x53, 0x2d, 0x66, 0x77, 0xa9, 0x45, 0x0a, 0x77, 0xa9, 0xeb, 0xb0, 0x02, 0x6a, 0x71, + 0xfc, 0x33, 0x02, 0xf7, 0x0c, 0x82, 0x31, 0x90, 0x68, 0x56, 0x33, 0x41, 0x72, 0xfb, 0xfe, 0x80, 0x11, 0x58, 0x49, + 0xcf, 0xda, 0x53, 0xf3, 0x52, 0x24, 0xe4, 0x23, 0x98, 0x86, 0xdf, 0x33, 0x83, 0x14, 0x92, 0xbe, 0xb0, 0x0d, 0x90, + 0x24, 0x00, 0x5d, 0x56, 0x82, 0xc6, 0x99, 0x09, 0x4e, 0xe4, 0x62, 0x4d, 0xc7, 0x3d, 0x37, 0x76, 0x2c, 0x64, 0xeb, + 0xe9, 0x62, 0xa6, 0x17, 0x98, 0x25, 0xf9, 0x0b, 0x7f, 0x23, 0x33, 0x8e, 0x9a, 0xff, 0x75, 0x0d, 0xf1, 0xf0, 0xcb, + 0x24, 0x4e, 0x99, 0xf2, 0x8e, 0xb4, 0x38, 0x2e, 0x67, 0x31, 0x35, 0x88, 0xdf, 0x0b, 0x94, 0x13, 0xb8, 0x78, 0x23, + 0x52, 0x1f, 0x83, 0xdb, 0x75, 0x34, 0x00, 0xa0, 0x34, 0xd6, 0x67, 0xde, 0xbf, 0x94, 0xc7, 0x78, 0x3b, 0x36, 0xcf, + 0x0c, 0x89, 0x08, 0x2a, 0x2d, 0xee, 0xe0, 0x9a, 0x76, 0x1d, 0xfc, 0x8b, 0x72, 0x9a, 0x2b, 0x77, 0x5e, 0x50, 0xce, + 0x7c, 0x8f, 0x94, 0x20, 0xb3, 0x97, 0xed, 0x5e, 0xb6, 0x02, 0x1d, 0x84, 0xd6, 0x16, 0x56, 0x1e, 0xd3, 0x16, 0x7f, + 0x3e, 0x8d, 0xd5, 0x26, 0xf0, 0x9b, 0x21, 0x55, 0x5d, 0x3d, 0x37, 0x68, 0xd4, 0x3f, 0x22, 0x8b, 0xde, 0x26, 0x84, + 0xdd, 0x1a, 0x9f, 0xcf, 0x0a, 0x40, 0x0b, 0xc4, 0x5e, 0xfd, 0x6f, 0x09, 0x16, 0xfa, 0x1a, 0x3f, 0x8f, 0x75, 0x75, + 0x71, 0xf9, 0x24, 0x19, 0x59, 0xf1, 0x43, 0x2f, 0x93, 0x6a, 0x59, 0x58, 0x2a, 0xa6, 0x01, 0xc8, 0x86, 0xdf, 0xef, + 0xaa, 0x67, 0xd9, 0x4f, 0xa7, 0x36, 0x5f, 0xf4, 0x74, 0x15, 0x3f, 0x07, 0x19, 0x96, 0x3c, 0x65, 0xf0, 0xdf, 0xe2, + 0xd6, 0xe0, 0x14, 0xfd, 0xdb, 0xe0, 0x87, 0x89, 0xed, 0xb3, 0x12, 0x24, 0x54, 0x84, 0xe7, 0x36, 0xea, 0xbb, 0x04, + 0xa4, 0x88, 0xee, 0x50, 0xe6, 0x55, 0x8d, 0x1d, 0x25, 0x1b, 0x6a, 0xfb, 0x19, 0x12, 0x6a, 0xe2, 0xa8, 0x86, 0x5f, + 0xdc, 0x38, 0xfc, 0x42, 0xc8, 0x21, 0xce, 0xd1, 0x93, 0x43, 0xc7, 0x26, 0xf3, 0x9b, 0xe1, 0xb2, 0x79, 0x1c, 0x2e, + 0xb7, 0xb0, 0xef, 0x23, 0x93, 0x9e, 0x2b, 0x1a, 0xcf, 0xf1, 0xec, 0xd1, 0xa2, 0x58, 0xce, 0xea, 0xde, 0x4a, 0x20, + 0x46, 0x36, 0x51, 0x5f, 0xcb, 0x0b, 0x5e, 0x9e, 0xcd, 0xac, 0x7e, 0x49, 0xe2, 0xdd, 0xd1, 0x5f, 0xdf, 0x0e, 0xd7, + 0x81, 0x1f, 0x69, 0xb8, 0x61, 0x5b, 0xc6, 0x93, 0x2d, 0xcc, 0x0e, 0x23, 0xd7, 0xc5, 0xea, 0x32, 0xcb, 0x90, 0xb7, + 0x50, 0xfc, 0xec, 0x0f, 0xa3, 0x5c, 0x32, 0x35, 0x06, 0x3f, 0xba, 0xdc, 0x8f, 0x69, 0x38, 0x95, 0x18, 0xa2, 0x95, + 0x9c, 0x74, 0x8f, 0xb5, 0x1d, 0x2b, 0x20, 0xcb, 0xde, 0x3f, 0x1a, 0x9d, 0xbb, 0x98, 0x97, 0x12, 0x75, 0x1c, 0x34, + 0xcf, 0x53, 0x1e, 0x94, 0xdb, 0x85, 0xb6, 0xd9, 0x3b, 0xe2, 0xd3, 0xd6, 0xc6, 0x05, 0xd0, 0x6e, 0x0d, 0x5d, 0x68, + 0x5d, 0xb0, 0x80, 0x84, 0xbe, 0x4b, 0xed, 0x16, 0x58, 0x49, 0xd6, 0x32, 0x86, 0x2e, 0x39, 0xbb, 0x4e, 0x5c, 0x43, + 0x95, 0xc3, 0x86, 0x4b, 0x96, 0x93, 0x2c, 0x11, 0x93, 0xed, 0xff, 0xcb, 0x1b, 0x94, 0x30, 0xd2, 0xcb, 0x12, 0x3a, + 0xde, 0x14, 0xbe, 0xb0, 0xc8, 0x02, 0x1e, 0xb7, 0xc8, 0xe8, 0x79, 0xf9, 0x90, 0x44, 0xc1, 0xa1, 0xb8, 0xe0, 0x7e, + 0xf8, 0xf2, 0x5d, 0x1d, 0xf7, 0xd6, 0xec, 0x63, 0xca, 0x91, 0xbf, 0xaa, 0x0a, 0x44, 0x5b, 0x97, 0x45, 0x4c, 0xfe, + 0x4f, 0x24, 0x67, 0x45, 0xd6, 0xa2, 0xa3, 0x03, 0x68, 0x6e, 0xe7, 0x4c, 0xb6, 0x84, 0xa5, 0x90, 0xcc, 0x43, 0x97, + 0x66, 0x0e, 0x16, 0x80, 0xae, 0x68, 0x81, 0x5d, 0x3c, 0x66, 0xcc, 0xbd, 0xcb, 0x92, 0xd3, 0xda, 0x65, 0x1e, 0x2d, + 0xa0, 0xb9, 0x70, 0x4b, 0xa2, 0x09, 0x44, 0x37, 0x52, 0x82, 0x35, 0xb6, 0x9d, 0xdb, 0x73, 0xff, 0x3e, 0x8e, 0xa8, + 0x2f, 0x0f, 0x38, 0x27, 0xc4, 0xe1, 0xdb, 0x51, 0x6e, 0x9a, 0x7e, 0xe0, 0x65, 0xab, 0x33, 0x07, 0x13, 0x17, 0xf3, + 0xeb, 0x01, 0x3c, 0x49, 0xbb, 0xce, 0xa6, 0xe8, 0xf6, 0x69, 0xed, 0xf1, 0x97, 0x84, 0x2e, 0x29, 0x96, 0x35, 0x64, + 0x32, 0x7d, 0x24, 0x61, 0xce, 0xf7, 0x3a, 0xef, 0xc3, 0x40, 0x73, 0x13, 0x70, 0x37, 0x29, 0x14, 0xbd, 0xb9, 0xcf, + 0x27, 0x1c, 0x07, 0x64, 0xb5, 0x37, 0x8a, 0xe9, 0xd1, 0x03, 0xdd, 0xe4, 0x02, 0x87, 0xe7, 0x23, 0x08, 0x91, 0x30, + 0x2b, 0xb8, 0xd5, 0xb5, 0xea, 0x1a, 0xe8, 0xa7, 0xf0, 0x63, 0x9d, 0x09, 0x0c, 0x4b, 0xf6, 0x72, 0x74, 0xae, 0xcb, + 0x50, 0x72, 0x47, 0x5c, 0xe6, 0x50, 0xf0, 0xee, 0x29, 0xf2, 0xe4, 0xfc, 0xf1, 0xdf, 0x33, 0x01, 0x43, 0xcd, 0x22, + 0x27, 0x7f, 0xcf, 0xb4, 0xf3, 0x53, 0xc0, 0x89, 0xa9, 0x30, 0xb5, 0xd8, 0xaa, 0xbc, 0x01, 0x9a, 0x53, 0x12, 0x14, + 0x1c, 0x56, 0xd1, 0xf9, 0x1d, 0x85, 0xc5, 0x25, 0xfe, 0xb0, 0x90, 0x19, 0x34, 0xb2, 0xe9, 0x75, 0x50, 0xa9, 0x74, + 0xfb, 0x04, 0xb1, 0x87, 0xaa, 0x7d, 0x6f, 0xcf, 0xd6, 0x84, 0x99, 0x1d, 0x8a, 0x02, 0xea, 0x46, 0xf1, 0xa6, 0x1f, + 0x5a, 0x6f, 0x81, 0x97, 0x05, 0xb0, 0x92, 0x4c, 0x3f, 0x1b, 0x20, 0x25, 0xe1, 0xc7, 0xca, 0x19, 0xdc, 0x70, 0x58, + 0xb9, 0x80, 0x5b, 0xbe, 0x5c, 0x3e, 0x20, 0xbb, 0xa6, 0x3b, 0x22, 0x02, 0x5d, 0x3f, 0x59, 0xb2, 0x6b, 0xc5, 0x94, + 0xc1, 0xe8, 0x46, 0x71, 0x17, 0xfa, 0x34, 0xca, 0x2e, 0x57, 0x56, 0xa0, 0xc6, 0x58, 0x9f, 0xa2, 0x26, 0xbf, 0x1f, + 0x2f, 0x9b, 0xca, 0xf5, 0x0f, 0x2e, 0x27, 0x72, 0x92, 0x8c, 0x32, 0x74, 0x67, 0xd2, 0xe7, 0x6c, 0x8e, 0x9a, 0x05, + 0xfc, 0x9f, 0x56, 0xab, 0x9e, 0x7b, 0xb8, 0x7d, 0x98, 0xf4, 0x42, 0x04, 0x03, 0xbd, 0xc2, 0xb2, 0xe9, 0x76, 0x23, + 0xdb, 0x56, 0xf8, 0xb6, 0x48, 0x81, 0xf8, 0x04, 0x68, 0x7e, 0x8d, 0x44, 0x80, 0x33, 0xf3, 0xcb, 0xbe, 0x04, 0x50, + 0x63, 0xe5, 0xe2, 0xf8, 0x83, 0x0a, 0x82, 0xe7, 0xb3, 0x9e, 0x7b, 0x01, 0x8b, 0x0b, 0x84, 0xcc, 0xbd, 0x27, 0x0a, + 0x6c, 0x6b, 0xe2, 0x4c, 0xfc, 0x66, 0x90, 0xeb, 0xf8, 0x6b, 0x35, 0xbd, 0xb5, 0x61, 0xa1, 0xb3, 0x92, 0xc2, 0xf2, + 0xa0, 0x47, 0xbb, 0x87, 0x88, 0x91, 0xae, 0xcf, 0x37, 0xe9, 0x37, 0x44, 0x23, 0xfa, 0x2d, 0x2a, 0x9e, 0x7e, 0x30, + 0x20, 0x90, 0x2c, 0x0b, 0xb7, 0xb7, 0xe9, 0x51, 0x51, 0x10, 0xd4, 0x7b, 0x18, 0xfc, 0x57, 0x23, 0xea, 0x4d, 0x1f, + 0x42, 0x80, 0xbf, 0x6a, 0x83, 0x7e, 0xea, 0x9f, 0x2c, 0x72, 0xd7, 0x0c, 0xd8, 0xb5, 0x87, 0xb0, 0xec, 0x0c, 0x1f, + 0x98, 0x41, 0x93, 0x62, 0xb2, 0x87, 0x70, 0x69, 0x4e, 0x13, 0x30, 0xa8, 0x77, 0x13, 0xcb, 0x9f, 0xb8, 0xa7, 0x9c, + 0x88, 0x3e, 0xe4, 0x77, 0x53, 0x8a, 0x00, 0xa7, 0xf9, 0xd2, 0x1c, 0xc1, 0x15, 0x81, 0x53, 0x5c, 0x60, 0xb6, 0x30, + 0x7f, 0xf2, 0xf5, 0x4d, 0x29, 0x60, 0x84, 0xcf, 0x17, 0x28, 0x03, 0x72, 0x46, 0x64, 0xe6, 0x90, 0xd1, 0xac, 0xea, + 0x08, 0xa1, 0x03, 0x72, 0x50, 0xa8, 0xdf, 0x8b, 0x59, 0x30, 0x62, 0xd8, 0x2f, 0x75, 0x22, 0xc9, 0x87, 0xc0, 0x88, + 0xd8, 0x42, 0xf3, 0xd6, 0xe4, 0x0e, 0x12, 0x44, 0x0f, 0x72, 0xa6, 0x51, 0x41, 0x79, 0x57, 0xc9, 0xcb, 0x29, 0x52, + 0x13, 0x0f, 0x7b, 0x13, 0x94, 0x53, 0x2d, 0x6f, 0x56, 0xd0, 0x7b, 0x70, 0xca, 0xe7, 0xfd, 0x93, 0xbc, 0x33, 0x60, + 0x81, 0x38, 0xaa, 0xec, 0x38, 0xb1, 0x5a, 0xe5, 0x6a, 0x1b, 0x47, 0x4e, 0x55, 0xc1, 0x95, 0x68, 0xa5, 0xbd, 0x9b, + 0xe7, 0x3f, 0x95, 0x17, 0x9b, 0x22, 0x6b, 0x62, 0xf2, 0x83, 0xe0, 0xc2, 0x23, 0xaf, 0xe0, 0xa3, 0x51, 0x87, 0xc3, + 0xaf, 0x95, 0x16, 0x82, 0x58, 0x20, 0x0c, 0x97, 0x6f, 0x7b, 0x85, 0xfd, 0x0a, 0x57, 0xe4, 0xb8, 0x84, 0xd6, 0x85, + 0xae, 0x1e, 0x7f, 0x49, 0x16, 0x13, 0xe4, 0xc8, 0x9c, 0xfd, 0xca, 0x8d, 0x18, 0xc1, 0x2c, 0x78, 0x49, 0x8f, 0x76, + 0x3c, 0xa6, 0x15, 0x41, 0x82, 0x10, 0x8a, 0xcc, 0xf3, 0x63, 0xe8, 0x26, 0xb1, 0x99, 0x50, 0xa4, 0x4d, 0x16, 0x83, + 0x06, 0x9c, 0x71, 0xb5, 0x21, 0x8a, 0x35, 0xc7, 0xa7, 0x7c, 0xdf, 0x43, 0x5c, 0x44, 0xde, 0xf5, 0xe8, 0x66, 0x38, + 0x80, 0x36, 0xdc, 0xac, 0x54, 0xf4, 0xa7, 0x88, 0x74, 0xf5, 0xd7, 0xca, 0xfb, 0xd0, 0x77, 0x88, 0x93, 0x79, 0x5c, + 0x2d, 0xbf, 0x82, 0x43, 0xa9, 0xe4, 0x13, 0xb8, 0xc2, 0x4f, 0x71, 0x08, 0x0b, 0x51, 0x91, 0x5e, 0x59, 0x88, 0x50, + 0xde, 0x0a, 0xf2, 0x56, 0x91, 0x4f, 0x4a, 0x1f, 0x34, 0xb1, 0x7d, 0xcb, 0x6e, 0xb6, 0xaf, 0x4a, 0xb8, 0x7d, 0x9f, + 0x9e, 0x8c, 0x05, 0xe7, 0x80, 0x46, 0x8f, 0x61, 0xd1, 0x64, 0xd0, 0x62, 0xac, 0xd2, 0xc0, 0x5d, 0x91, 0xc5, 0xa7, + 0xfe, 0xc0, 0x92, 0xf4, 0xc5, 0x67, 0x1a, 0x68, 0x1e, 0xa9, 0xff, 0x26, 0x14, 0xc6, 0xb1, 0xfc, 0xa3, 0x2f, 0x9f, + 0x89, 0x44, 0xd5, 0xd5, 0x1d, 0xc5, 0x1a, 0xc5, 0x3c, 0x1b, 0x98, 0x75, 0xba, 0xa3, 0x81, 0x55, 0x47, 0xf1, 0x4a, + 0xcd, 0x6d, 0x4c, 0x39, 0x14, 0x50, 0x57, 0xbd, 0xdd, 0x40, 0x54, 0xfa, 0x6a, 0x35, 0x5f, 0x11, 0x4e, 0x0b, 0x67, + 0x64, 0x12, 0xe7, 0xd6, 0xa8, 0x42, 0x1b, 0x9c, 0x59, 0xbd, 0xa7, 0xfd, 0x7a, 0xa5, 0x3a, 0xd6, 0xfa, 0x3b, 0xec, + 0x17, 0x37, 0x0e, 0xc8, 0xcf, 0x0f, 0x04, 0xce, 0x30, 0x80, 0x62, 0x0b, 0x8c, 0x43, 0xa1, 0x9c, 0x4d, 0x1c, 0x79, + 0x79, 0x89, 0x72, 0x82, 0xe2, 0x4e, 0x9f, 0x06, 0x07, 0x25, 0x70, 0x82, 0x95, 0x86, 0x8c, 0x85, 0xb0, 0x1c, 0x68, + 0xb9, 0x0b, 0xc5, 0x5d, 0x59, 0xa2, 0xad, 0x25, 0x36, 0x9d, 0x5b, 0x3c, 0x35, 0x50, 0x67, 0xba, 0x05, 0x81, 0x55, + 0x94, 0x88, 0xad, 0x55, 0xe4, 0xd2, 0x6f, 0x7d, 0x69, 0x30, 0x8c, 0xa3, 0x7b, 0x5f, 0xeb, 0x69, 0x37, 0x95, 0x38, + 0xf6, 0xe0, 0x2d, 0xf3, 0xfc, 0x9c, 0xe8, 0xc5, 0x54, 0x23, 0x3b, 0x13, 0x6f, 0x11, 0x0b, 0x46, 0x83, 0x92, 0xb6, + 0xad, 0x5a, 0xda, 0xc2, 0xd6, 0x01, 0xf4, 0x6f, 0x41, 0x1d, 0xff, 0x6f, 0xb8, 0x41, 0xd9, 0x41, 0xe8, 0x14, 0xaa, + 0xd5, 0xfa, 0x3c, 0xcb, 0xc6, 0xc6, 0x7a, 0xc7, 0x1c, 0x09, 0x44, 0x04, 0x2f, 0x61, 0x94, 0xc2, 0xcc, 0x1c, 0x2f, + 0xb1, 0xa5, 0x4a, 0x6d, 0xa7, 0x63, 0xf3, 0xe1, 0x6c, 0xac, 0x3a, 0x90, 0x43, 0x4d, 0x74, 0xde, 0xb4, 0x11, 0x0d, + 0x55, 0x4a, 0x94, 0x17, 0xc9, 0xac, 0x46, 0x5a, 0xf3, 0xe1, 0x25, 0xb0, 0x45, 0xc4, 0xec, 0xc0, 0xa6, 0x20, 0x06, + 0x2b, 0x66, 0xc8, 0xa9, 0x1a, 0x27, 0xbd, 0x45, 0x2f, 0x97, 0x59, 0x63, 0xeb, 0xd1, 0xa6, 0xe3, 0x98, 0x9f, 0x6e, + 0x3d, 0x16, 0x0f, 0x84, 0xb7, 0xe7, 0x7f, 0x2a, 0x94, 0xb2, 0x1f, 0xc7, 0xce, 0xda, 0xef, 0xcd, 0x71, 0x21, 0x16, + 0xcd, 0xf3, 0x83, 0xc8, 0x0d, 0xbf, 0x54, 0x08, 0x5f, 0x04, 0xc0, 0x8b, 0x6d, 0xf0, 0xaa, 0x21, 0xa8, 0x7d, 0x7f, + 0x45, 0x41, 0x8e, 0x3b, 0xf5, 0xde, 0x83, 0xd0, 0xb2, 0x2e, 0xf6, 0xf2, 0x8c, 0xd5, 0x25, 0x1d, 0x5a, 0x63, 0x88, + 0x44, 0x4f, 0x44, 0xb1, 0xf6, 0x1f, 0x37, 0xaf, 0xb2, 0xa0, 0x3e, 0x12, 0x2e, 0x71, 0xd1, 0x43, 0xf1, 0xf1, 0x57, + 0x49, 0x33, 0x37, 0x6d, 0x54, 0xa6, 0x67, 0xae, 0x9c, 0xfc, 0x0b, 0x1c, 0x5b, 0x56, 0x57, 0x28, 0x0f, 0xd7, 0x0d, + 0x4c, 0xf8, 0x7b, 0x73, 0xe3, 0xd7, 0xb8, 0xb2, 0xc6, 0xa5, 0x8b, 0xf1, 0x4e, 0xe9, 0x62, 0xc5, 0xdb, 0xc6, 0x15, + 0x4b, 0x45, 0xc6, 0x1c, 0x34, 0xb5, 0xfa, 0x67, 0x06, 0xb9, 0xfd, 0x59, 0x98, 0xfe, 0x2d, 0x85, 0x0e, 0x12, 0x0f, + 0xb3, 0xbb, 0x10, 0x1f, 0xaf, 0x0b, 0xb9, 0x9a, 0xe0, 0x92, 0x84, 0xa4, 0x24, 0x3f, 0x86, 0x6d, 0xdf, 0x71, 0xf2, + 0x9c, 0x29, 0x1c, 0x8d, 0xb8, 0x5d, 0x26, 0xf9, 0x95, 0xf0, 0x3f, 0x95, 0x8d, 0xeb, 0x4e, 0x9b, 0x35, 0x07, 0x0a, + 0xf0, 0x79, 0x97, 0x85, 0x09, 0xd1, 0xd1, 0xda, 0x46, 0xed, 0x45, 0xb8, 0xf1, 0x2b, 0x45, 0x82, 0xfe, 0x25, 0xa3, + 0x50, 0xd8, 0xbc, 0x47, 0x2e, 0xb0, 0x4d, 0xc1, 0xd3, 0x6f, 0xc1, 0xb5, 0x4a, 0x19, 0x30, 0xf1, 0x2b, 0xd8, 0x26, + 0x9f, 0x98, 0xb9, 0x9b, 0xf4, 0x82, 0xa8, 0x2f, 0xab, 0x68, 0x82, 0xeb, 0xca, 0x85, 0xd5, 0x95, 0xf1, 0x3d, 0x75, + 0x7d, 0x04, 0xb9, 0x78, 0x7c, 0x9a, 0xe7, 0x77, 0xa9, 0x69, 0x03, 0xf6, 0x5e, 0x8c, 0x63, 0xfc, 0x75, 0xc5, 0x3c, + 0xb3, 0x7a, 0x52, 0x55, 0xa6, 0x80, 0xf7, 0xf4, 0xe3, 0x2b, 0xee, 0xf1, 0x9b, 0x87, 0x6d, 0xb0, 0xf4, 0x3f, 0xfa, + 0x99, 0x27, 0xa0, 0x2c, 0xd1, 0x8e, 0x2b, 0x8d, 0xdd, 0x32, 0xc6, 0x96, 0x0a, 0xc2, 0x05, 0x2c, 0x48, 0x45, 0x8d, + 0x5d, 0x1e, 0x6a, 0xd9, 0x7c, 0xdb, 0x1c, 0x9a, 0x90, 0x66, 0xfd, 0x71, 0xd6, 0x73, 0x33, 0x30, 0xaa, 0x68, 0xc3, + 0x03, 0x66, 0x85, 0x36, 0x24, 0xe0, 0x60, 0xa1, 0xc1, 0xa4, 0x08, 0x02, 0xe9, 0x6e, 0xd0, 0xe3, 0x82, 0x3e, 0x51, + 0x08, 0x6c, 0xbc, 0x8b, 0x16, 0x24, 0xd0, 0xfe, 0x9f, 0x02, 0x7d, 0x12, 0x1b, 0xfa, 0x7b, 0xcc, 0xc6, 0xb1, 0xe1, + 0x58, 0xca, 0xe8, 0xde, 0x23, 0x95, 0xc0, 0x49, 0xea, 0x1e, 0xe9, 0xfc, 0x54, 0x1e, 0xa9, 0xed, 0xdc, 0x92, 0xbf, + 0x44, 0x3f, 0x8e, 0xc6, 0xd8, 0xf9, 0xed, 0xe7, 0xa8, 0x26, 0xa6, 0xf3, 0x16, 0xb6, 0xb8, 0xf6, 0xc8, 0x32, 0x3f, + 0xab, 0x33, 0xd0, 0x81, 0x84, 0x93, 0x58, 0x29, 0xbb, 0x54, 0x2e, 0xf9, 0x7f, 0xc8, 0xd3, 0x26, 0x97, 0xd6, 0x08, + 0xe2, 0x4b, 0x56, 0x7d, 0x47, 0x10, 0x19, 0x53, 0xcd, 0xaa, 0x8a, 0xde, 0x23, 0x29, 0x62, 0xa5, 0xda, 0x55, 0x8d, + 0xd7, 0x6c, 0x33, 0x3b, 0x1b, 0x9d, 0x7b, 0xa1, 0x7e, 0x2f, 0x2c, 0x45, 0x57, 0xb4, 0xdf, 0xc5, 0x36, 0x52, 0x65, + 0x13, 0x11, 0x66, 0x70, 0x87, 0xa3, 0x11, 0x62, 0x4b, 0xa9, 0xa4, 0xcf, 0x76, 0x41, 0xba, 0xe7, 0x65, 0xaa, 0x26, + 0x5c, 0x8e, 0x84, 0x45, 0x6c, 0xa9, 0x8d, 0x57, 0xb2, 0xd3, 0x83, 0x27, 0xb7, 0xb8, 0x1d, 0xcb, 0xdd, 0x80, 0xe0, + 0x34, 0x64, 0xe9, 0x89, 0x63, 0x65, 0x22, 0xdd, 0xc9, 0xae, 0x73, 0x4d, 0x91, 0x62, 0xf7, 0x99, 0x74, 0xfb, 0xa1, + 0x94, 0x7e, 0xaa, 0x34, 0xe6, 0xc0, 0x35, 0x8e, 0xc0, 0x45, 0xc3, 0x88, 0x3e, 0x5e, 0x93, 0xf9, 0xd4, 0x07, 0xe9, + 0x49, 0x2d, 0x00, 0xc7, 0x41, 0xe9, 0x2c, 0x71, 0xb9, 0xc4, 0x0e, 0xfc, 0x24, 0xec, 0xac, 0x7a, 0x76, 0x1e, 0x0b, + 0xf9, 0x4c, 0xb5, 0xd9, 0x3a, 0x48, 0xe4, 0x9b, 0x9a, 0x87, 0x62, 0xd5, 0x0e, 0x0b, 0x0f, 0x7c, 0xbc, 0xc3, 0xe7, + 0xc7, 0xbb, 0xab, 0x6c, 0xc5, 0xcb, 0xc6, 0x39, 0x0d, 0x16, 0x97, 0x38, 0xd1, 0xf2, 0xcb, 0x65, 0x65, 0x83, 0x85, + 0x27, 0xf1, 0xe8, 0x7f, 0x53, 0x65, 0xfc, 0x4a, 0x86, 0x62, 0x39, 0x68, 0xbd, 0x2a, 0xab, 0xa4, 0xb8, 0x75, 0x7b, + 0x64, 0x91, 0x44, 0xf4, 0x30, 0x29, 0x97, 0x3a, 0xad, 0x6a, 0xa5, 0xc3, 0xdf, 0x4f, 0xe8, 0x8e, 0xb2, 0x0a, 0x00, + 0x53, 0x09, 0xfd, 0x83, 0x15, 0xdf, 0x65, 0xd4, 0xe8, 0xb0, 0x17, 0x2c, 0x96, 0x7d, 0x8e, 0xe2, 0x5f, 0xdb, 0xf3, + 0x30, 0x2c, 0x4b, 0xd2, 0x5d, 0xbd, 0x85, 0xd8, 0x0b, 0xfe, 0xf0, 0xc0, 0x69, 0x14, 0xa9, 0xc5, 0x8b, 0xab, 0xd0, + 0x24, 0xde, 0x21, 0x1d, 0x3f, 0x6d, 0x2d, 0xff, 0x26, 0xac, 0x24, 0xf6, 0x79, 0x5c, 0xcd, 0xb5, 0x6a, 0xd7, 0x52, + 0xb4, 0x38, 0x94, 0xd6, 0x48, 0x2f, 0x43, 0x7d, 0x0d, 0xf1, 0x26, 0xb7, 0xb6, 0xc4, 0x23, 0xee, 0x5e, 0x4a, 0xcf, + 0xb8, 0x68, 0x17, 0x72, 0xbe, 0xdf, 0x4a, 0x4a, 0x28, 0xee, 0xe4, 0xb1, 0x51, 0x3c, 0xb1, 0x9f, 0x5d, 0x92, 0x7c, + 0x20, 0x48, 0x71, 0xb1, 0xd2, 0xe9, 0x77, 0xce, 0x0e, 0xcf, 0x4a, 0x1d, 0x96, 0x68, 0x75, 0x6a, 0x3b, 0xb0, 0x12, + 0xef, 0xd9, 0xd7, 0x78, 0x13, 0xab, 0x04, 0xf4, 0xce, 0x85, 0x46, 0x5c, 0xba, 0x19, 0x11, 0xba, 0x48, 0xa7, 0x09, + 0x84, 0xbf, 0xdc, 0xfa, 0x25, 0xf1, 0xec, 0x7e, 0x2e, 0x07, 0x12, 0x35, 0xd4, 0x81, 0x43, 0x28, 0x2c, 0x5f, 0x44, + 0x33, 0x63, 0x2a, 0xd1, 0x1b, 0xb6, 0xab, 0x59, 0xea, 0x0e, 0x5f, 0x98, 0x4d, 0x4f, 0x7e, 0x95, 0xa3, 0x0d, 0x71, + 0x78, 0x26, 0xec, 0x8f, 0xdd, 0xe3, 0xff, 0x4a, 0x93, 0xe5, 0x45, 0xd3, 0xd1, 0x11, 0xc8, 0x16, 0x2d, 0x6b, 0x7c, + 0x63, 0x73, 0x0d, 0x5a, 0xc1, 0xce, 0xbc, 0x12, 0x28, 0x19, 0xda, 0xd2, 0x1d, 0x7d, 0x4f, 0x5e, 0x93, 0x00, 0xc6, + 0x32, 0xb5, 0x6e, 0x67, 0xbb, 0xf2, 0x2c, 0x18, 0x45, 0xb9, 0xe5, 0xc0, 0x1a, 0xb8, 0x6e, 0x0c, 0x8d, 0x9d, 0x31, + 0xba, 0xe6, 0xff, 0xac, 0x14, 0xd3, 0x15, 0x73, 0x90, 0x04, 0x5b, 0x5e, 0x1e, 0x06, 0xa9, 0xd9, 0xa7, 0x96, 0xae, + 0x33, 0xb5, 0x44, 0x50, 0x98, 0x15, 0x4f, 0x4d, 0x1a, 0xfa, 0x05, 0xec, 0xdf, 0xde, 0x98, 0x0e, 0x82, 0x7c, 0x2b, + 0x99, 0xc6, 0x68, 0x50, 0x39, 0x2f, 0xd4, 0x43, 0x6f, 0xbe, 0x70, 0x20, 0xbb, 0x5d, 0x59, 0x64, 0x54, 0x3b, 0xd4, + 0x0b, 0xb3, 0xe9, 0x9d, 0x81, 0x19, 0x89, 0x08, 0xb0, 0x11, 0x1f, 0xf5, 0x57, 0x84, 0x62, 0x89, 0x89, 0xb4, 0xf2, + 0x46, 0x9f, 0xdf, 0xe7, 0xc2, 0x42, 0xe7, 0x09, 0x36, 0xbd, 0x59, 0x34, 0xa3, 0x91, 0x00, 0x23, 0xe8, 0x8b, 0x9c, + 0xe5, 0x9c, 0xd5, 0x20, 0xb4, 0x3a, 0xa5, 0xe1, 0x16, 0x9c, 0x1e, 0x77, 0xad, 0x09, 0x94, 0xdb, 0x5f, 0x3a, 0x7b, + 0xab, 0xd7, 0xc2, 0xf6, 0xd6, 0x23, 0xd5, 0x8b, 0x3a, 0x1f, 0x7f, 0x70, 0x65, 0xe6, 0xf2, 0xef, 0x6d, 0x66, 0x22, + 0xa9, 0xfc, 0xf9, 0x0a, 0x89, 0xa0, 0xf2, 0xf0, 0x56, 0x1b, 0xc1, 0x85, 0xec, 0xe8, 0x19, 0xb3, 0x75, 0xd2, 0x0a, + 0xb6, 0x7f, 0x53, 0xfc, 0x40, 0x64, 0xf8, 0x17, 0x33, 0x70, 0xc4, 0x59, 0xc8, 0xb2, 0xa3, 0x40, 0x2b, 0xca, 0x03, + 0x35, 0x4e, 0xbc, 0x98, 0x8f, 0xe5, 0xba, 0x7c, 0x7b, 0x73, 0xa2, 0x82, 0xac, 0xb1, 0x08, 0x1e, 0xd6, 0xcb, 0x37, + 0x29, 0x93, 0x65, 0xc7, 0xa7, 0x37, 0x3d, 0x6e, 0xcf, 0x8d, 0x08, 0x48, 0x8b, 0x67, 0xc8, 0xe7, 0x4a, 0x24, 0x66, + 0x37, 0x1a, 0x2f, 0x39, 0x62, 0x31, 0x96, 0x12, 0x51, 0x2a, 0x74, 0x5c, 0x0b, 0x87, 0x28, 0xc4, 0x2a, 0x8c, 0x24, + 0xa8, 0xfc, 0x72, 0x61, 0x69, 0x16, 0x61, 0x62, 0x1f, 0x8b, 0x2b, 0x39, 0x4c, 0xb1, 0x87, 0x36, 0xd3, 0x7e, 0x52, + 0xd7, 0xf8, 0x8f, 0x51, 0xd7, 0xd7, 0x13, 0xea, 0x15, 0x43, 0x7b, 0x0d, 0xa5, 0xa9, 0x4e, 0x26, 0x56, 0x2c, 0x78, + 0xa4, 0x46, 0xe3, 0x3e, 0x34, 0x02, 0x84, 0xe2, 0xf6, 0x71, 0xd0, 0xb1, 0xad, 0x58, 0x62, 0xc4, 0x69, 0x51, 0x32, + 0xb3, 0xb4, 0xe9, 0xd8, 0xad, 0xa4, 0x43, 0x5a, 0x5e, 0xea, 0xf0, 0xfc, 0xc6, 0xbe, 0xee, 0x0a, 0x23, 0x8d, 0x79, + 0x37, 0x70, 0xbb, 0xdc, 0x74, 0x45, 0x45, 0xd1, 0x66, 0x64, 0x43, 0x5d, 0x0f, 0x88, 0x42, 0x88, 0x0d, 0x73, 0x6b, + 0x28, 0x4e, 0x46, 0x3b, 0xda, 0x61, 0x81, 0x79, 0x6c, 0x60, 0x1c, 0x83, 0x59, 0x47, 0xb5, 0xb1, 0x13, 0x59, 0xd6, + 0xbf, 0xe7, 0xb5, 0x8d, 0xf8, 0x7c, 0xb9, 0x26, 0x40, 0x40, 0xe3, 0x41, 0x2f, 0x7b, 0x45, 0xe4, 0xa0, 0x97, 0x21, + 0x97, 0xd8, 0x38, 0x21, 0x43, 0x63, 0xe3, 0xfb, 0x83, 0xd9, 0x93, 0x99, 0xe3, 0xe7, 0x33, 0x83, 0xb1, 0x8f, 0xd5, + 0xfc, 0xc8, 0x82, 0x43, 0x99, 0x34, 0x5d, 0x3f, 0x72, 0x44, 0xef, 0x99, 0x56, 0xdc, 0x77, 0x38, 0x58, 0x26, 0x65, + 0x96, 0x4c, 0xba, 0x19, 0x40, 0x65, 0xb0, 0x92, 0x77, 0x3b, 0x3f, 0x5c, 0x69, 0x88, 0x7e, 0x68, 0x2e, 0x16, 0x53, + 0xd9, 0x0e, 0xce, 0x53, 0x43, 0xa4, 0x2c, 0x0d, 0x6f, 0x8e, 0x06, 0x21, 0xc4, 0xf5, 0x69, 0xbe, 0xfe, 0x75, 0x54, + 0x3b, 0x9b, 0x4d, 0x4d, 0x91, 0x34, 0x15, 0x4c, 0xcf, 0x58, 0x29, 0x0d, 0x8e, 0x41, 0x80, 0x01, 0x27, 0x0b, 0x39, + 0x6f, 0x7b, 0xe4, 0xfc, 0xd3, 0x20, 0xd6, 0x03, 0x5a, 0xeb, 0x5e, 0x64, 0x44, 0x62, 0x1f, 0xda, 0x8a, 0x4b, 0x54, + 0x9d, 0xca, 0x06, 0xa0, 0xa2, 0xfe, 0xda, 0xeb, 0xd1, 0x0a, 0xfe, 0x9e, 0x83, 0xae, 0x7a, 0x8d, 0x2f, 0xda, 0x7b, + 0xa2, 0xdf, 0x34, 0xf5, 0x7f, 0xa2, 0x0c, 0xc2, 0xf6, 0x32, 0xa1, 0x03, 0x6f, 0x20, 0x0b, 0x08, 0xf8, 0x9d, 0x1e, + 0xf4, 0x05, 0xe0, 0x91, 0x18, 0x72, 0x40, 0x8e, 0x9f, 0x5b, 0x03, 0x35, 0xae, 0xf6, 0x3a, 0xf7, 0xfd, 0x37, 0x1f, + 0x1c, 0xe9, 0x83, 0x6b, 0x1c, 0xba, 0xc7, 0x27, 0x12, 0x59, 0xc8, 0x8e, 0xb3, 0x74, 0x78, 0x21, 0xa7, 0xdb, 0xfa, + 0xa8, 0xa4, 0xdb, 0xf1, 0x44, 0xe1, 0x1f, 0x5a, 0x90, 0xbc, 0xcd, 0xe3, 0xd9, 0x81, 0xa6, 0xfa, 0x76, 0x26, 0x35, + 0x62, 0xd3, 0xdd, 0x4e, 0xa9, 0x4f, 0xb2, 0x12, 0x8e, 0x85, 0xc1, 0x36, 0x06, 0xe3, 0x2a, 0xb7, 0x73, 0x2b, 0xb7, + 0x39, 0xac, 0x35, 0x7d, 0xf1, 0xed, 0x6e, 0x6f, 0x5a, 0xe8, 0xfd, 0x4b, 0xfb, 0x9c, 0x8e, 0xa1, 0x99, 0x3b, 0x0c, + 0x08, 0x0a, 0x5f, 0x28, 0x4e, 0x2f, 0xd3, 0xd7, 0xb7, 0xc3, 0xf8, 0x18, 0xda, 0xf9, 0xaa, 0xd8, 0x09, 0x32, 0x8f, + 0xca, 0x45, 0x6a, 0xf3, 0x99, 0x71, 0x59, 0x4d, 0x6e, 0x8b, 0xf3, 0xdb, 0x53, 0x32, 0xef, 0xf9, 0x15, 0x34, 0xa8, + 0xc7, 0xfe, 0xa3, 0x86, 0xbf, 0x3c, 0xad, 0x61, 0x5d, 0x29, 0xca, 0x80, 0xdd, 0xd6, 0x35, 0x20, 0x9b, 0x9c, 0xf3, + 0xe0, 0xb8, 0x56, 0x38, 0xf0, 0x6a, 0x17, 0x9d, 0x43, 0x5c, 0x56, 0xc6, 0xf5, 0xa6, 0x4f, 0xbb, 0xdc, 0xcf, 0xb8, + 0x53, 0xd8, 0x75, 0x70, 0x12, 0xb1, 0x81, 0x07, 0x15, 0x7d, 0x40, 0x77, 0xd2, 0x87, 0x7a, 0xd8, 0xab, 0x06, 0x42, + 0x08, 0x8c, 0x6f, 0xbe, 0x50, 0xe6, 0xcf, 0xd2, 0xea, 0xbb, 0xac, 0x55, 0x31, 0x96, 0x64, 0x0d, 0x9c, 0x9d, 0xde, + 0x1f, 0x71, 0x18, 0x62, 0xc7, 0x9b, 0x04, 0xc4, 0x59, 0xe6, 0x46, 0xcc, 0x49, 0x10, 0x7d, 0xc8, 0x3a, 0xea, 0xe9, + 0x47, 0xf3, 0x1f, 0x10, 0x01, 0x02, 0x16, 0x1c, 0x27, 0x02, 0x61, 0xc8, 0x7c, 0x85, 0xf0, 0x9d, 0xbe, 0xfd, 0xf0, + 0x0b, 0xa6, 0xb6, 0x6f, 0x74, 0xd7, 0xc8, 0xff, 0x6b, 0x38, 0xe4, 0xf6, 0x57, 0x9e, 0x2e, 0x0f, 0xf9, 0x93, 0xcb, + 0x3e, 0x7f, 0xbb, 0x77, 0xd3, 0xe4, 0xee, 0xe4, 0xe6, 0x63, 0x05, 0xd4, 0xfa, 0x7c, 0x95, 0x1e, 0xa1, 0x62, 0x44, + 0x19, 0x73, 0xa7, 0x87, 0x31, 0x6d, 0x96, 0x9d, 0x0d, 0x2e, 0x11, 0xfb, 0x35, 0x2e, 0x4f, 0xbd, 0x86, 0x09, 0x6c, + 0x57, 0xe1, 0x5a, 0x3a, 0x97, 0x49, 0xd6, 0x3c, 0x53, 0xe6, 0xa8, 0x60, 0x2c, 0x6c, 0x4c, 0x00, 0x6f, 0x60, 0xa7, + 0xcb, 0x77, 0xfa, 0xd6, 0x8b, 0xbe, 0x94, 0x07, 0x09, 0x6a, 0x1e, 0x70, 0x11, 0xe8, 0xea, 0x99, 0x6d, 0xb1, 0xf1, + 0xfb, 0x39, 0xd1, 0xd1, 0x04, 0x92, 0xfa, 0xe3, 0x31, 0x6a, 0xaf, 0x72, 0x57, 0xda, 0x2a, 0xaa, 0x85, 0x9e, 0xed, + 0x89, 0xd0, 0xa7, 0x4c, 0x26, 0x03, 0x76, 0x01, 0x5f, 0xf5, 0x92, 0xbe, 0xb4, 0x35, 0xe4, 0x53, 0xe5, 0x29, 0x17, + 0x2c, 0x1c, 0x4f, 0x70, 0x9c, 0xf6, 0xa8, 0x3e, 0x10, 0x4c, 0xe2, 0x2a, 0x58, 0xc3, 0xbe, 0x64, 0x55, 0xe9, 0x45, + 0x73, 0x32, 0x0c, 0x2e, 0xa7, 0xc9, 0xfa, 0x37, 0xb6, 0xc5, 0xd2, 0xf7, 0x24, 0xd0, 0x6e, 0xd1, 0xc8, 0x66, 0x8c, + 0x85, 0x0c, 0x65, 0x3a, 0x68, 0x03, 0x09, 0x40, 0x67, 0x4d, 0x67, 0xc5, 0xa7, 0xa9, 0xa5, 0x70, 0x6e, 0x92, 0x18, + 0x0b, 0x97, 0xe6, 0x48, 0x36, 0x53, 0x30, 0xe1, 0x75, 0x4b, 0x7b, 0x9e, 0x4d, 0x32, 0xef, 0xcb, 0x24, 0xa6, 0x7c, + 0x2f, 0x70, 0xef, 0x20, 0x9c, 0x48, 0xe8, 0x55, 0xc8, 0x52, 0x28, 0xb5, 0x04, 0xdb, 0x98, 0xb9, 0xf0, 0x37, 0x00, + 0xa2, 0x7c, 0x1a, 0x63, 0x03, 0xf6, 0xaf, 0xd1, 0x10, 0x3a, 0xb1, 0xfd, 0xc1, 0x5a, 0x49, 0x61, 0x06, 0xaa, 0x2c, + 0x94, 0xd8, 0x9c, 0x25, 0x7b, 0x71, 0xf8, 0x06, 0x17, 0x3a, 0x77, 0x4a, 0x61, 0x9f, 0xd3, 0x39, 0xc1, 0x54, 0x55, + 0xce, 0x1b, 0x72, 0x13, 0xe2, 0xf9, 0x46, 0x92, 0x46, 0xcb, 0x21, 0x76, 0x11, 0x73, 0xbd, 0xf8, 0xed, 0xdf, 0x47, + 0xb8, 0xd9, 0x94, 0x16, 0x9b, 0xd9, 0xce, 0x08, 0xcf, 0x3b, 0x38, 0x3a, 0x23, 0x8f, 0x5d, 0x8f, 0x2c, 0x0d, 0xfe, + 0xf1, 0x4d, 0x6e, 0x97, 0xeb, 0x9d, 0x13, 0x40, 0x3d, 0xf9, 0xef, 0x45, 0xed, 0x6a, 0x72, 0x1a, 0x89, 0xa1, 0xb1, + 0x91, 0x91, 0x05, 0x00, 0x12, 0x18, 0x6b, 0x3a, 0x36, 0xb3, 0x29, 0xda, 0x76, 0x82, 0x68, 0xf6, 0xf3, 0x47, 0x5c, + 0xbf, 0x37, 0x1b, 0xbe, 0xc0, 0x7d, 0xdc, 0xb1, 0x51, 0x5c, 0x3e, 0xb0, 0x89, 0x1c, 0xfa, 0xad, 0x16, 0x33, 0xfa, + 0x46, 0x26, 0xdc, 0x88, 0xf5, 0x39, 0xb4, 0xdb, 0xa0, 0xc2, 0x01, 0x90, 0xf9, 0x93, 0x7c, 0x3c, 0xff, 0x57, 0xaa, + 0xb9, 0x13, 0xc6, 0xac, 0xb1, 0x72, 0x69, 0x4c, 0xe2, 0xe4, 0xd0, 0x5e, 0x70, 0xd4, 0x9c, 0xd0, 0x3e, 0xac, 0x08, + 0x7a, 0x8c, 0xb6, 0x31, 0x99, 0x81, 0xd0, 0x90, 0x62, 0x05, 0x63, 0xb0, 0x1f, 0x56, 0x9f, 0x5d, 0x77, 0xbf, 0x40, + 0x8a, 0x7b, 0xe3, 0x3a, 0x33, 0x9e, 0x9b, 0x4c, 0x66, 0x3a, 0x8f, 0x2d, 0x78, 0x4b, 0x5c, 0x34, 0xad, 0x56, 0x3e, + 0x6b, 0x77, 0x4c, 0xdb, 0xbe, 0x63, 0xba, 0x8a, 0x5f, 0xc7, 0x87, 0x64, 0xb6, 0x37, 0xe7, 0x10, 0x40, 0x8b, 0xfa, + 0xec, 0x13, 0xfc, 0xe4, 0xa2, 0xd3, 0xd4, 0x9b, 0x6d, 0x68, 0x68, 0xbb, 0x5c, 0x9f, 0x1f, 0xb4, 0x3a, 0x41, 0xc7, + 0x90, 0xb3, 0x66, 0x50, 0xf4, 0x3e, 0xb1, 0xf3, 0x12, 0x9f, 0x58, 0xa7, 0x82, 0x71, 0xd2, 0x80, 0x7e, 0x9c, 0x93, + 0x97, 0xbb, 0xdc, 0x3c, 0x06, 0xf2, 0x53, 0x8a, 0x23, 0x74, 0xc3, 0xe8, 0x61, 0x4d, 0xf4, 0xbd, 0x47, 0x8f, 0x2d, + 0x5b, 0xb3, 0x0d, 0x40, 0x63, 0x72, 0x85, 0x2b, 0x4b, 0xb2, 0x4d, 0xf8, 0x98, 0x1e, 0x5c, 0xa3, 0x05, 0x4d, 0x9f, + 0x7d, 0xf6, 0x37, 0x17, 0xd0, 0xd9, 0x63, 0x02, 0xb5, 0xc4, 0xb3, 0x74, 0x50, 0x2f, 0x14, 0xca, 0x73, 0x04, 0x46, + 0x5e, 0x62, 0x9e, 0x55, 0xd3, 0xa1, 0xa6, 0x75, 0x8f, 0x4e, 0x4f, 0x5d, 0x6a, 0x2d, 0xbb, 0x98, 0xb1, 0x40, 0x34, + 0x47, 0x2b, 0xb3, 0xaf, 0x04, 0xfd, 0x50, 0x83, 0x8d, 0x99, 0x05, 0xf0, 0x8a, 0x5c, 0x6f, 0xa4, 0xa6, 0x27, 0xf1, + 0x1e, 0xe1, 0x8a, 0x40, 0xb8, 0x23, 0x8a, 0x94, 0xf1, 0x14, 0x88, 0xa3, 0x75, 0xbc, 0x9e, 0x4e, 0xec, 0x38, 0x78, + 0x52, 0x90, 0x17, 0x7e, 0x6b, 0x46, 0x02, 0x9e, 0xfd, 0x11, 0x48, 0xca, 0x5e, 0x07, 0x21, 0xba, 0xca, 0x12, 0xdb, + 0x5b, 0x35, 0x16, 0x77, 0x1f, 0x36, 0x2d, 0x32, 0x77, 0xc5, 0x90, 0x9d, 0x85, 0x73, 0x45, 0xeb, 0x62, 0xd9, 0x76, + 0x4f, 0xe4, 0xee, 0x6c, 0xc5, 0x41, 0x62, 0xe1, 0x7a, 0xe7, 0x13, 0x32, 0xe5, 0xc3, 0x98, 0xd2, 0xf5, 0xda, 0xa8, + 0x55, 0xbb, 0xcc, 0x91, 0x17, 0x29, 0xe2, 0xed, 0x5a, 0x48, 0x11, 0x8b, 0x53, 0x11, 0xad, 0x09, 0x5f, 0x1d, 0x24, + 0x0d, 0x6a, 0x7d, 0xbf, 0xee, 0x6c, 0xf6, 0x83, 0x3c, 0xb7, 0x4e, 0x25, 0xe5, 0xe1, 0xf0, 0xd7, 0xe6, 0xdb, 0x11, + 0xf7, 0xa2, 0x41, 0xf1, 0xa5, 0xea, 0x2a, 0x12, 0xcd, 0xed, 0x95, 0xea, 0x4c, 0x17, 0xc5, 0xef, 0x53, 0x76, 0xca, + 0x61, 0x8a, 0xf1, 0xd9, 0x74, 0xda, 0xdd, 0x27, 0x0f, 0x42, 0xc7, 0xee, 0xba, 0xdc, 0x99, 0xf9, 0x7a, 0xc7, 0xde, + 0x9c, 0x70, 0xfa, 0x9f, 0xca, 0x8a, 0xb3, 0x11, 0xd1, 0xff, 0xfa, 0x37, 0x2f, 0xc0, 0xb7, 0x4e, 0xbb, 0x2e, 0x9d, + 0x1a, 0x48, 0xa1, 0x85, 0x35, 0x6d, 0xec, 0x5f, 0xfc, 0x44, 0x0a, 0x01, 0xa1, 0x77, 0x9e, 0x57, 0x57, 0x48, 0x60, + 0x9b, 0xda, 0xc5, 0xd4, 0xed, 0xbe, 0xd6, 0x4b, 0x4c, 0xca, 0x12, 0xd7, 0x75, 0xf8, 0x85, 0xa5, 0x9f, 0x84, 0x69, + 0xc8, 0xbd, 0xd3, 0xa6, 0xd1, 0x86, 0x18, 0x41, 0x39, 0xbb, 0x17, 0x4b, 0x4d, 0x08, 0x5d, 0xdc, 0x51, 0x16, 0x60, + 0xd7, 0x3f, 0x9e, 0xa2, 0xc9, 0x95, 0x08, 0xf5, 0xc7, 0x78, 0x13, 0xb6, 0x5c, 0xdd, 0x29, 0x4d, 0x61, 0x3b, 0x4c, + 0xd9, 0x67, 0x08, 0xf4, 0x1a, 0x31, 0xf8, 0x7c, 0x7b, 0x0b, 0x07, 0x7b, 0x23, 0x34, 0x91, 0x49, 0xb7, 0x10, 0xb3, + 0xa3, 0xf1, 0xdb, 0x9f, 0xa9, 0xc6, 0xfc, 0xdc, 0xb7, 0x58, 0xee, 0x90, 0x9e, 0x00, 0x47, 0x3a, 0xe0, 0xf1, 0x3c, + 0x1d, 0x29, 0xbe, 0x0d, 0xfa, 0xb5, 0x49, 0xfe, 0xd7, 0xb8, 0xe1, 0x1b, 0x4d, 0x37, 0x84, 0xa7, 0xab, 0xc2, 0x0e, + 0x7d, 0xce, 0x60, 0x2e, 0xa9, 0x4b, 0xfa, 0xf0, 0x4f, 0x27, 0x9d, 0x71, 0x7d, 0x53, 0x44, 0x06, 0x03, 0x97, 0x05, + 0x93, 0xb3, 0xeb, 0x0e, 0xf3, 0xd2, 0xf7, 0x04, 0x32, 0x30, 0x78, 0x18, 0x47, 0x48, 0x22, 0x93, 0x81, 0xbd, 0xc1, + 0x84, 0xbe, 0xba, 0x94, 0x70, 0xc6, 0x6b, 0x4a, 0xd3, 0xa1, 0xea, 0xb8, 0xd9, 0xf4, 0x42, 0x81, 0x71, 0x04, 0xa1, + 0xc4, 0x33, 0x60, 0x15, 0xa8, 0x48, 0xcf, 0x99, 0xe5, 0x9c, 0xf2, 0x5b, 0xe7, 0xb0, 0x75, 0x9d, 0xd5, 0xa8, 0x3e, + 0x3f, 0x97, 0x85, 0x00, 0x91, 0xe6, 0xda, 0x99, 0xb4, 0x94, 0x7a, 0xfa, 0xe1, 0x91, 0x94, 0xc3, 0xff, 0x20, 0x89, + 0x57, 0x79, 0x3e, 0xfe, 0xf5, 0xe3, 0x44, 0x55, 0x3d, 0xf8, 0x76, 0xd1, 0x07, 0xba, 0x6f, 0x5e, 0x8f, 0x6a, 0xe5, + 0xf9, 0x8a, 0xfd, 0xe2, 0x22, 0xe3, 0xc2, 0xfc, 0x13, 0x83, 0x30, 0x06, 0x3a, 0xb3, 0xe0, 0x2b, 0x62, 0xc5, 0xaf, + 0xf9, 0xec, 0xb4, 0x07, 0x6a, 0x8e, 0xe4, 0x4c, 0xa6, 0x28, 0xab, 0x75, 0xeb, 0xdd, 0x4e, 0x0d, 0x88, 0x48, 0x47, + 0x6f, 0xc6, 0xe9, 0x06, 0x2e, 0x70, 0x5a, 0x75, 0x86, 0xfa, 0x59, 0xb0, 0x22, 0xb9, 0xfd, 0x0d, 0x59, 0xbc, 0xeb, + 0xbe, 0xdf, 0x51, 0xb9, 0x72, 0x12, 0x87, 0x26, 0xd6, 0x7e, 0xda, 0x29, 0x80, 0x99, 0xba, 0xb3, 0x4d, 0xd1, 0x73, + 0x1d, 0x1d, 0x1c, 0x53, 0x06, 0x0e, 0xa7, 0x9e, 0x1f, 0x24, 0x34, 0x7c, 0x15, 0xbe, 0xe8, 0xa3, 0x6e, 0xf7, 0x47, + 0x0c, 0xa4, 0x20, 0x23, 0xb9, 0xb3, 0x27, 0x96, 0x57, 0x21, 0x6f, 0xa2, 0xc6, 0x71, 0x31, 0xa3, 0x42, 0x28, 0xfb, + 0xd7, 0xf2, 0x72, 0x3f, 0x0c, 0xc9, 0x5d, 0x93, 0x12, 0x6f, 0x76, 0xae, 0x91, 0x72, 0x96, 0x60, 0x6e, 0x47, 0x2c, + 0x47, 0x33, 0xa8, 0xd7, 0x7d, 0x7a, 0xd7, 0xe1, 0x33, 0x34, 0x45, 0x8f, 0x1b, 0x74, 0xa1, 0xd0, 0xa8, 0x5b, 0x5b, + 0xa3, 0x6d, 0x1a, 0xa5, 0x89, 0xc8, 0xa9, 0x22, 0xa4, 0x0f, 0xf3, 0xcd, 0xe4, 0x9b, 0x1d, 0x90, 0x32, 0x06, 0x0f, + 0xd0, 0xa4, 0x7a, 0x05, 0x10, 0x69, 0xbe, 0x7c, 0xaa, 0xa4, 0xdb, 0xcf, 0x5e, 0x24, 0xfd, 0x04, 0x34, 0x4e, 0x34, + 0xe9, 0x1a, 0x3f, 0xa1, 0x4c, 0x6b, 0x8a, 0xa3, 0x09, 0x49, 0x34, 0x5a, 0x26, 0xcf, 0x86, 0xda, 0x91, 0xd7, 0x82, + 0x95, 0xa1, 0x27, 0x0d, 0x16, 0x81, 0xe0, 0x00, 0x89, 0x24, 0x5c, 0x53, 0x92, 0x61, 0x8c, 0x0b, 0x84, 0xd1, 0xbf, + 0xb0, 0x25, 0x1d, 0x62, 0xed, 0x66, 0xc1, 0x84, 0x8c, 0xee, 0xcf, 0xf8, 0x25, 0x0c, 0x0d, 0xab, 0x66, 0x18, 0x4f, + 0xd2, 0x71, 0xaa, 0x35, 0x46, 0x51, 0x5a, 0x9c, 0x05, 0x93, 0x5a, 0xc8, 0xa1, 0xc6, 0x00, 0xdb, 0x8d, 0xe3, 0x69, + 0x4d, 0xd9, 0x32, 0x62, 0x26, 0xdd, 0xdb, 0xda, 0x51, 0xa7, 0xb9, 0xa5, 0x9f, 0x7b, 0x21, 0xb3, 0x0d, 0x39, 0xe6, + 0xbc, 0xa5, 0x5f, 0x36, 0xd1, 0x87, 0x16, 0xeb, 0x66, 0x1c, 0x08, 0x33, 0xfc, 0xb9, 0xe5, 0x90, 0x78, 0x54, 0x30, + 0xa8, 0xf2, 0xa4, 0x46, 0x2b, 0xd2, 0xf6, 0xbe, 0xaf, 0x8e, 0xe6, 0xb6, 0xa9, 0x48, 0x1a, 0x82, 0xdc, 0x08, 0x4d, + 0x04, 0x8e, 0x5d, 0xe9, 0x1f, 0x67, 0x75, 0xff, 0xdd, 0x43, 0x1f, 0x49, 0x83, 0xf0, 0xe5, 0x9a, 0xe9, 0x20, 0x14, + 0x30, 0x57, 0xad, 0xdb, 0xd4, 0x67, 0x71, 0x35, 0xa2, 0xbf, 0x22, 0x64, 0xcc, 0x38, 0x56, 0xfd, 0x98, 0x66, 0xe4, + 0x77, 0xfa, 0x1a, 0x39, 0x26, 0xef, 0xc7, 0xcc, 0x6a, 0x55, 0xf2, 0xe1, 0xa9, 0x3b, 0x5d, 0xc9, 0x68, 0x46, 0xca, + 0xb3, 0xba, 0xc3, 0xd2, 0x56, 0x88, 0x39, 0x8b, 0xf7, 0xe4, 0x7a, 0x36, 0x5d, 0x65, 0x2b, 0xf1, 0x43, 0x7a, 0x70, + 0xaf, 0x8f, 0x99, 0xa4, 0xc3, 0x0f, 0x59, 0x7e, 0xdd, 0x9d, 0x00, 0x21, 0x4f, 0x4f, 0xc0, 0xac, 0x6e, 0x5d, 0xd9, + 0x69, 0xad, 0xb8, 0xef, 0x24, 0xdb, 0x36, 0x5c, 0xbf, 0xe6, 0x8f, 0x79, 0xf0, 0x70, 0xef, 0xcb, 0x36, 0x17, 0x4f, + 0xc3, 0xc7, 0xc9, 0x52, 0x0b, 0x21, 0xf1, 0x55, 0x97, 0x42, 0x15, 0xa3, 0xe0, 0x0d, 0xe3, 0x41, 0x5c, 0xc8, 0x1f, + 0xe7, 0xb4, 0x35, 0x2d, 0x3b, 0xb5, 0x92, 0x78, 0xac, 0xab, 0x30, 0x2d, 0xf9, 0x75, 0x51, 0xcd, 0x79, 0x66, 0xe2, + 0x55, 0xa7, 0x9e, 0xa1, 0x39, 0x8d, 0xc9, 0xf5, 0xf0, 0x9e, 0x97, 0x68, 0x64, 0xd9, 0xf0, 0x6e, 0xc2, 0x5b, 0xb1, + 0x57, 0x9e, 0xa1, 0xdc, 0x1d, 0x29, 0x35, 0x84, 0x02, 0x62, 0x04, 0x1a, 0x57, 0xe7, 0x2e, 0xad, 0xa4, 0xb3, 0xe4, + 0x51, 0x63, 0xe0, 0x8b, 0x39, 0x8f, 0x5b, 0x63, 0xa1, 0x1c, 0x6b, 0x0e, 0x61, 0x46, 0xaa, 0x70, 0x32, 0xd5, 0x0d, + 0xe0, 0xce, 0x34, 0x43, 0x88, 0x26, 0x4a, 0xcd, 0x29, 0xee, 0xe2, 0x6b, 0x34, 0x99, 0x6c, 0xe8, 0x18, 0xf4, 0x2c, + 0xaf, 0xc8, 0x34, 0x1e, 0x07, 0xd0, 0x7d, 0xe0, 0xeb, 0x06, 0x89, 0x05, 0xdb, 0xb2, 0x4e, 0xf8, 0x2a, 0x70, 0xe2, + 0x28, 0xab, 0x12, 0x53, 0xc3, 0xb3, 0xa1, 0xdb, 0x1f, 0xe8, 0x88, 0xb5, 0xa2, 0xa6, 0xbb, 0x23, 0x26, 0x28, 0xf8, + 0xee, 0xfb, 0x2f, 0x78, 0x77, 0x64, 0xe2, 0x38, 0x83, 0x38, 0xae, 0x5d, 0x78, 0x9b, 0x74, 0x04, 0x4d, 0x30, 0x56, + 0x96, 0x63, 0x9e, 0x72, 0x49, 0xa1, 0xf6, 0xfc, 0x97, 0x86, 0x23, 0x54, 0xc9, 0x35, 0x44, 0x6f, 0x19, 0xba, 0x43, + 0xb0, 0x6b, 0x1f, 0xa2, 0x53, 0x11, 0x1f, 0x78, 0x7f, 0x81, 0x48, 0x98, 0x4b, 0xa1, 0xcc, 0xb2, 0x5e, 0xed, 0xb1, + 0x80, 0x3a, 0xef, 0x29, 0xc7, 0x46, 0x01, 0x2b, 0x4b, 0xaf, 0x58, 0xab, 0x4e, 0xd9, 0xe1, 0xd7, 0x3a, 0x12, 0x62, + 0x63, 0xae, 0x1b, 0x1a, 0x3f, 0x91, 0xae, 0x02, 0x89, 0xcd, 0x7b, 0xb5, 0x9c, 0x8d, 0xa2, 0x50, 0x1f, 0xbe, 0xe4, + 0x93, 0xb6, 0x52, 0x3f, 0x41, 0x82, 0x3f, 0xe1, 0x90, 0x88, 0xf9, 0x94, 0x1f, 0x24, 0x56, 0x75, 0xb9, 0xa9, 0x59, + 0x66, 0xdb, 0x21, 0xf9, 0x97, 0x5f, 0x88, 0x3f, 0x7b, 0x8f, 0x25, 0x78, 0xac, 0x30, 0x43, 0xc2, 0x18, 0xa3, 0xd4, + 0x4b, 0xfe, 0x68, 0x81, 0x8f, 0xe7, 0x6e, 0x7e, 0xf5, 0xdb, 0x59, 0x3b, 0xfc, 0x82, 0x81, 0x42, 0x8c, 0xfa, 0x42, + 0x4b, 0x0a, 0xf6, 0xee, 0x64, 0x71, 0xbb, 0x20, 0x27, 0xa1, 0x48, 0x45, 0x89, 0x12, 0xc6, 0x90, 0xb6, 0x01, 0xd0, + 0x4d, 0x80, 0x4a, 0x94, 0x6a, 0x1a, 0xd1, 0x23, 0xf8, 0x01, 0x9f, 0x6d, 0xde, 0x1e, 0x64, 0x1d, 0x4c, 0xa4, 0x36, + 0x2e, 0x63, 0x03, 0x98, 0xe2, 0xb9, 0xb5, 0xc3, 0xfb, 0x65, 0x04, 0xad, 0x75, 0xac, 0xd4, 0x10, 0xea, 0x22, 0xe7, + 0x7e, 0xf0, 0x19, 0x75, 0x37, 0xd9, 0x39, 0xcc, 0xd3, 0x0c, 0x0c, 0xe4, 0x78, 0x40, 0xb3, 0x6d, 0x4c, 0x96, 0x28, + 0x66, 0xd9, 0x0c, 0xbf, 0x54, 0x2f, 0x6f, 0xb4, 0xa5, 0x20, 0x69, 0xad, 0xce, 0x9e, 0x29, 0x86, 0x09, 0x1b, 0x58, + 0x60, 0x3e, 0x40, 0xd8, 0xc2, 0x12, 0xb6, 0x8e, 0x3d, 0x87, 0xfe, 0x68, 0x6c, 0xce, 0x71, 0x76, 0xb2, 0xe9, 0x5c, + 0xcb, 0xc6, 0x93, 0x1f, 0x15, 0xe7, 0x3c, 0x4d, 0xca, 0x41, 0x25, 0x54, 0x5b, 0xb1, 0x40, 0x87, 0xe8, 0x56, 0x1f, + 0x2a, 0x9d, 0x33, 0xf7, 0x9c, 0x90, 0x88, 0xa7, 0x73, 0xcc, 0xb5, 0xc7, 0xfb, 0x15, 0x25, 0x10, 0x2a, 0xbc, 0x75, + 0xf1, 0x31, 0x3b, 0x40, 0x56, 0x1e, 0x0a, 0x4f, 0xb6, 0x9c, 0x96, 0x48, 0x09, 0x4e, 0xbf, 0x79, 0x9d, 0x3c, 0x15, + 0x18, 0x19, 0x8a, 0x35, 0x26, 0xd5, 0x90, 0x78, 0x83, 0x11, 0x7a, 0x71, 0x11, 0xc9, 0x15, 0x98, 0x3b, 0x97, 0x66, + 0xea, 0x7a, 0x21, 0x67, 0x2c, 0xcf, 0x3d, 0xd8, 0xe3, 0xa5, 0xa7, 0x96, 0x5d, 0x78, 0xec, 0x5e, 0x32, 0xc7, 0xeb, + 0xf3, 0x90, 0x66, 0xb0, 0x3b, 0x85, 0xb5, 0x7a, 0xac, 0x8a, 0x82, 0x01, 0x58, 0x57, 0xc8, 0xca, 0xce, 0x34, 0x29, + 0x07, 0xca, 0x4f, 0x50, 0xdb, 0x41, 0xfd, 0x1b, 0x23, 0x11, 0x8c, 0xdf, 0x6d, 0xdd, 0xd7, 0x6e, 0xc9, 0x84, 0x99, + 0x8f, 0x02, 0x1b, 0xa2, 0xc7, 0x14, 0x66, 0x6c, 0x98, 0x2a, 0x63, 0xdc, 0x79, 0x0f, 0x83, 0xae, 0x2e, 0xdb, 0x4c, + 0xe5, 0x68, 0x7c, 0xb1, 0x8c, 0xab, 0x61, 0xa6, 0xef, 0xde, 0x03, 0x66, 0xbc, 0xda, 0xf3, 0x28, 0xe2, 0xd8, 0x49, + 0xcc, 0xa9, 0x9e, 0x51, 0xed, 0x6b, 0x2f, 0xdb, 0x74, 0x87, 0x98, 0xf0, 0xee, 0x0e, 0xde, 0x3b, 0x86, 0x99, 0x4c, + 0xe8, 0xe4, 0x40, 0x66, 0x42, 0xca, 0x1e, 0xa0, 0x89, 0x0c, 0x1d, 0x1e, 0x37, 0xe6, 0xa2, 0x3c, 0x4b, 0x32, 0x0b, + 0x0b, 0x17, 0xf6, 0x4d, 0xfa, 0x6f, 0xb8, 0x98, 0xfb, 0x22, 0xd0, 0xe6, 0x30, 0x5d, 0x37, 0xd9, 0xbc, 0x67, 0x15, + 0x9b, 0x2c, 0x1d, 0xb2, 0xd6, 0xa8, 0x12, 0xfd, 0x22, 0x31, 0x29, 0x3b, 0x84, 0x1e, 0x86, 0x6e, 0x10, 0xc5, 0x82, + 0xc5, 0xbe, 0xd1, 0x45, 0x3b, 0xc0, 0x47, 0x27, 0xe1, 0xb1, 0xf8, 0x9e, 0xee, 0x5c, 0x69, 0xce, 0xb7, 0xbb, 0x93, + 0xdf, 0xa8, 0x68, 0xd4, 0x34, 0x12, 0x1b, 0x95, 0xf8, 0x58, 0xec, 0xe5, 0xa6, 0xd2, 0x76, 0xf9, 0xd8, 0xd3, 0x5f, + 0xcc, 0xc8, 0x28, 0x1d, 0xcc, 0x99, 0x0e, 0x1e, 0xc2, 0xab, 0x79, 0x25, 0x8a, 0x7b, 0xae, 0x94, 0x70, 0x82, 0x9a, + 0x0b, 0x4e, 0x1d, 0x54, 0x29, 0x3c, 0x41, 0xa0, 0xd0, 0xfa, 0xc7, 0x75, 0xfd, 0x00, 0x48, 0xdb, 0xb3, 0x63, 0x30, + 0xf7, 0x55, 0x2f, 0x51, 0xa6, 0xee, 0x99, 0xd4, 0x0a, 0x68, 0x63, 0xab, 0xb8, 0x07, 0x12, 0xf4, 0x2d, 0x87, 0x94, + 0x90, 0x95, 0x79, 0x50, 0xd8, 0x2c, 0xa7, 0x27, 0xc9, 0x54, 0xe9, 0xcc, 0x5a, 0x51, 0x2e, 0xee, 0x89, 0x0a, 0xe1, + 0xd6, 0xfa, 0xfb, 0x80, 0x10, 0xa3, 0x94, 0xc1, 0x68, 0x62, 0xe2, 0x32, 0x42, 0x06, 0x8c, 0x0b, 0xc9, 0xb0, 0x82, + 0x48, 0x61, 0x97, 0x33, 0x8c, 0xc7, 0x74, 0x79, 0xd6, 0x9e, 0x9d, 0x87, 0xed, 0x7b, 0x6e, 0xc8, 0x1d, 0x82, 0xce, + 0xc6, 0x89, 0x4d, 0xe3, 0xe7, 0x67, 0xe2, 0x7d, 0x04, 0x37, 0x2a, 0x87, 0x35, 0x1a, 0x38, 0x35, 0xe6, 0x39, 0x8b, + 0xaf, 0xe2, 0x63, 0xbc, 0xad, 0x67, 0x4b, 0xae, 0x74, 0xec, 0x98, 0x3b, 0xf2, 0x63, 0x77, 0xa5, 0xb4, 0x29, 0x48, + 0xa2, 0x9e, 0xf6, 0xb4, 0x31, 0xe8, 0x76, 0xc8, 0xcd, 0x97, 0x0b, 0x0b, 0x7d, 0x83, 0xae, 0x8f, 0xf6, 0x01, 0xf7, + 0xe9, 0x20, 0xa2, 0x6a, 0xf1, 0x5d, 0x8b, 0x2f, 0x52, 0x10, 0x68, 0x89, 0x7d, 0x40, 0xde, 0xbb, 0x13, 0xe7, 0xbe, + 0x8b, 0x81, 0x1b, 0xfa, 0x07, 0x60, 0x21, 0xdd, 0x8a, 0xfb, 0xc9, 0xdb, 0x48, 0xd2, 0x0a, 0x80, 0x55, 0x9b, 0xc6, + 0x81, 0x23, 0x61, 0xfa, 0x02, 0x4b, 0xf6, 0x45, 0xce, 0x25, 0x9f, 0x14, 0x8a, 0xee, 0xf0, 0xb7, 0xf0, 0xe2, 0xf9, + 0x09, 0xe7, 0x64, 0xdd, 0xd2, 0xf1, 0x5d, 0xb5, 0x29, 0x91, 0x6a, 0xa9, 0x18, 0x24, 0x30, 0x23, 0x14, 0x39, 0x0f, + 0xd2, 0xb7, 0x17, 0xd9, 0x23, 0xfe, 0x01, 0xef, 0xf1, 0x0c, 0xdc, 0x74, 0x10, 0x26, 0xb3, 0xd9, 0x23, 0x1a, 0xaf, + 0x6f, 0x55, 0x27, 0xec, 0x02, 0x95, 0xc2, 0x68, 0x98, 0xc4, 0xf9, 0x4c, 0x95, 0x64, 0x38, 0xbe, 0xa9, 0x12, 0x52, + 0x38, 0xf1, 0x09, 0x88, 0xdb, 0x98, 0xdc, 0x8b, 0xb9, 0x12, 0xd5, 0xe9, 0xb6, 0x63, 0x68, 0xad, 0xfe, 0xfb, 0xf7, + 0x37, 0xe1, 0x7f, 0x90, 0x6c, 0xfa, 0x1b, 0x5f, 0x65, 0xe7, 0x9d, 0x13, 0xc1, 0xec, 0x21, 0x09, 0xdf, 0x38, 0xb3, + 0xac, 0x47, 0xbc, 0x26, 0x56, 0x48, 0xf7, 0xd4, 0xc9, 0xc2, 0x6e, 0x18, 0x72, 0xd5, 0x14, 0x9b, 0x4f, 0xbb, 0x54, + 0x80, 0x3e, 0xf6, 0x92, 0xad, 0x9a, 0x50, 0x4e, 0x00, 0x4a, 0x65, 0x3c, 0xb3, 0x52, 0x47, 0x83, 0x9a, 0x8d, 0xf2, + 0x32, 0x72, 0x46, 0x1f, 0x0b, 0xdd, 0x56, 0xb3, 0x20, 0x4b, 0x56, 0xe9, 0xa6, 0x86, 0x3a, 0x6b, 0xd6, 0xee, 0xcd, + 0xe7, 0xff, 0x6e, 0x3d, 0x2b, 0x13, 0x44, 0xf5, 0x46, 0x8d, 0xfe, 0xac, 0x97, 0x70, 0x45, 0x1c, 0xc7, 0xeb, 0x1d, + 0x9f, 0xd5, 0x7f, 0xb7, 0xf8, 0x47, 0xab, 0x5a, 0xf7, 0x12, 0x08, 0xcd, 0xcb, 0x5a, 0x00, 0xb3, 0x8a, 0x21, 0xbd, + 0x9e, 0x75, 0xe2, 0xc8, 0x86, 0x00, 0x7c, 0xf8, 0x13, 0xb7, 0x6b, 0xf7, 0x7e, 0x67, 0xa2, 0x6d, 0x7b, 0xe2, 0x8c, + 0x55, 0x05, 0x94, 0x27, 0xba, 0x79, 0x4c, 0x34, 0x63, 0x55, 0x77, 0x85, 0x69, 0xf6, 0x7f, 0x52, 0x4e, 0xfa, 0xcb, + 0x92, 0xb9, 0x9a, 0x11, 0x00, 0xe2, 0x34, 0x8f, 0x89, 0xaa, 0x77, 0x33, 0xed, 0xbd, 0xab, 0xe7, 0xf4, 0xda, 0xa2, + 0xb5, 0xcf, 0x64, 0x2b, 0x35, 0x8c, 0x41, 0xd7, 0x3c, 0x51, 0x7d, 0x53, 0x72, 0x19, 0x69, 0x15, 0x6d, 0xcc, 0x1b, + 0x7f, 0x6a, 0x4d, 0xae, 0xde, 0xa5, 0xae, 0x30, 0x42, 0x64, 0xd6, 0xdf, 0x19, 0xc9, 0x97, 0x37, 0x7f, 0x38, 0xb1, + 0x17, 0xcb, 0x24, 0x2c, 0x6f, 0xd4, 0x8a, 0xb0, 0x31, 0x56, 0x81, 0x85, 0x7c, 0xf9, 0x16, 0xcd, 0x34, 0x85, 0xa5, + 0x4d, 0x24, 0x67, 0x94, 0xfe, 0x28, 0x2e, 0xeb, 0x54, 0xed, 0x5d, 0x88, 0x95, 0xbd, 0x16, 0xda, 0x4f, 0x7f, 0x95, + 0xd4, 0x63, 0xd9, 0x59, 0x04, 0x9d, 0x0c, 0xa0, 0xa1, 0x5a, 0xb5, 0xe7, 0x88, 0x5d, 0x70, 0xc6, 0x66, 0xf1, 0xd2, + 0x19, 0xe6, 0x9d, 0x61, 0x10, 0x82, 0xd3, 0x24, 0xc7, 0x82, 0x9b, 0x8c, 0x73, 0x00, 0x6d, 0x55, 0xa3, 0x9e, 0xab, + 0x14, 0x4f, 0x9f, 0xf7, 0x42, 0x59, 0xf8, 0x39, 0xa0, 0xba, 0x73, 0x47, 0x12, 0x6e, 0xe1, 0xe8, 0xf8, 0x89, 0xab, + 0xe2, 0xb2, 0x86, 0xee, 0x51, 0xcc, 0x9c, 0xb7, 0xcf, 0x84, 0x2b, 0xb6, 0xe1, 0xb4, 0x12, 0xcc, 0x09, 0x00, 0xd6, + 0x4d, 0xb0, 0x6e, 0xbe, 0x81, 0xaa, 0x2e, 0x9d, 0x4b, 0x46, 0x72, 0x7d, 0x80, 0x0b, 0xe1, 0x65, 0xbe, 0xf1, 0x1e, + 0x38, 0x09, 0x2a, 0x2d, 0x78, 0x30, 0x7b, 0x0c, 0xe6, 0xd5, 0x34, 0xf8, 0x43, 0x70, 0x67, 0xa6, 0x8e, 0x50, 0x1c, + 0x79, 0x4e, 0xad, 0x97, 0xee, 0xa5, 0x1d, 0x1f, 0xac, 0x54, 0x4f, 0x9c, 0x43, 0x19, 0xd7, 0x39, 0xd8, 0x3e, 0xea, + 0xbd, 0xd0, 0x7e, 0xc1, 0xac, 0x0f, 0xbc, 0xa6, 0x09, 0x8f, 0x03, 0xaf, 0x73, 0x45, 0xb5, 0x33, 0x5a, 0xe9, 0xb5, + 0x42, 0x8c, 0x70, 0xe8, 0x14, 0xf3, 0xe7, 0x37, 0x31, 0xca, 0xa0, 0xb7, 0x28, 0xb9, 0x57, 0xb5, 0xc4, 0x69, 0xf7, + 0xbb, 0x21, 0xe9, 0xdf, 0x55, 0x40, 0xfd, 0x9f, 0x19, 0x0f, 0x77, 0xbf, 0xba, 0x97, 0xb3, 0x17, 0xd1, 0xe6, 0xcd, + 0xb8, 0xba, 0x98, 0xd1, 0x2e, 0x40, 0x69, 0x60, 0xf1, 0xad, 0x9b, 0xfd, 0x98, 0xc7, 0x59, 0x8d, 0x31, 0x86, 0x26, + 0xa1, 0xb1, 0x89, 0x60, 0x63, 0xbc, 0x49, 0x6c, 0x05, 0x2f, 0x45, 0x10, 0x8b, 0xc9, 0xe4, 0x47, 0x1d, 0x06, 0xd7, + 0x8c, 0x3c, 0xfd, 0x86, 0x14, 0xe7, 0xa2, 0x68, 0xa5, 0xc7, 0x93, 0x1f, 0xc5, 0x96, 0x84, 0x7b, 0xb5, 0xdf, 0x2c, + 0x49, 0xb9, 0xe7, 0x25, 0xa5, 0xc5, 0xba, 0x60, 0x2b, 0xd9, 0x5a, 0x6b, 0xea, 0x9f, 0xda, 0x35, 0x51, 0xd1, 0x78, + 0x1a, 0xde, 0xa8, 0x7e, 0x90, 0x5f, 0x67, 0x37, 0x36, 0x0b, 0xb9, 0x56, 0x38, 0x68, 0xfa, 0x91, 0x5e, 0x74, 0xdd, + 0x86, 0x36, 0xee, 0xf4, 0x44, 0xeb, 0x18, 0x22, 0xde, 0xc1, 0x25, 0x5e, 0x30, 0x2f, 0x47, 0xb9, 0x5d, 0xc4, 0x5c, + 0x65, 0x4e, 0xec, 0xae, 0x25, 0xf3, 0xcc, 0xa2, 0xb2, 0x3c, 0xe9, 0x34, 0x79, 0x41, 0x02, 0x49, 0x7b, 0x0e, 0x0e, + 0xc0, 0xdf, 0xd2, 0x35, 0x6f, 0x76, 0xa0, 0x6b, 0xb9, 0xe9, 0xd5, 0x21, 0xde, 0xb5, 0x1f, 0x1e, 0xc9, 0xb4, 0x8d, + 0x80, 0xc6, 0x37, 0x34, 0x0e, 0x80, 0x4c, 0x57, 0x34, 0x6d, 0x6c, 0x1c, 0x04, 0x98, 0x50, 0x91, 0xbd, 0x4b, 0x04, + 0x9c, 0x0a, 0xde, 0x07, 0x32, 0x56, 0x64, 0xd2, 0xae, 0xfd, 0xb3, 0x41, 0x26, 0x21, 0x2d, 0x64, 0xa3, 0x3e, 0x6d, + 0x6a, 0x6f, 0x26, 0xff, 0x76, 0x2b, 0x77, 0x49, 0xc5, 0xd6, 0x92, 0x9d, 0x6d, 0x41, 0x4e, 0x0b, 0x49, 0x3e, 0x56, + 0x01, 0xe1, 0x58, 0xb3, 0xd8, 0xc8, 0x0f, 0x05, 0x4f, 0x80, 0x62, 0x28, 0x5a, 0x42, 0x33, 0x76, 0xb3, 0x3d, 0xd8, + 0x5e, 0x47, 0x0f, 0x89, 0x7b, 0x40, 0xca, 0x39, 0x32, 0x17, 0x79, 0x4c, 0x77, 0xef, 0x6c, 0x5b, 0x8f, 0xad, 0x6b, + 0xf1, 0x59, 0x1d, 0x6c, 0x6e, 0xbd, 0xa2, 0xca, 0xff, 0x3f, 0x74, 0x35, 0x7f, 0x1e, 0x07, 0x70, 0xf0, 0xee, 0x83, + 0x4e, 0x21, 0xb5, 0xa1, 0x56, 0x6f, 0xb7, 0x35, 0x51, 0x88, 0x26, 0x7a, 0xfe, 0x58, 0xb1, 0x4a, 0x2f, 0x31, 0xca, + 0xc2, 0x97, 0x54, 0xe2, 0x74, 0xbb, 0xfc, 0xa9, 0x4b, 0x86, 0xb3, 0xab, 0x64, 0xfd, 0xd9, 0x30, 0x8f, 0x7e, 0x13, + 0x43, 0x5c, 0xe5, 0xc5, 0x6d, 0x04, 0x43, 0x28, 0xf4, 0xd8, 0xf9, 0x07, 0x74, 0x52, 0xd6, 0x7c, 0x22, 0x81, 0x62, + 0x79, 0xaa, 0x0c, 0x0d, 0x28, 0xd2, 0xdb, 0x0c, 0x51, 0x4d, 0x14, 0xa3, 0x9d, 0xb5, 0x42, 0x90, 0x46, 0x37, 0xfa, + 0x2f, 0x03, 0x9b, 0x34, 0xcb, 0xea, 0x73, 0xe2, 0x04, 0xd9, 0xbe, 0x3b, 0xe9, 0x33, 0x96, 0x0b, 0xbe, 0x1e, 0xc7, + 0x65, 0x23, 0x78, 0x1b, 0x8a, 0xd0, 0x39, 0x66, 0x50, 0x9b, 0x3a, 0xaf, 0xda, 0x19, 0x42, 0x39, 0x8e, 0x03, 0xb9, + 0xa6, 0xa5, 0xdd, 0x01, 0x5a, 0xc4, 0x73, 0x9e, 0x4e, 0xf0, 0x98, 0xa4, 0xf9, 0x3e, 0x07, 0x79, 0x37, 0x09, 0x82, + 0x26, 0xfa, 0xba, 0x83, 0x0b, 0xf2, 0x58, 0xd1, 0xb5, 0x83, 0xd9, 0x1b, 0xeb, 0xef, 0xea, 0xb0, 0x88, 0xe7, 0x18, + 0x42, 0xc6, 0x0d, 0x29, 0x72, 0xc5, 0xdd, 0xac, 0x54, 0x99, 0xc2, 0xcb, 0x85, 0x1f, 0x98, 0x07, 0xb6, 0xad, 0x3a, + 0xa2, 0x66, 0x27, 0x71, 0x95, 0x1a, 0xed, 0xe9, 0xf7, 0x69, 0x9b, 0x58, 0xa3, 0xe3, 0x33, 0xe3, 0xd7, 0xe8, 0xa3, + 0xf6, 0xe2, 0xb1, 0x06, 0xe6, 0x22, 0x8b, 0x12, 0xf6, 0x25, 0xc8, 0x39, 0x52, 0x4c, 0x7d, 0xef, 0x26, 0x96, 0xfe, + 0x0c, 0x6c, 0xd0, 0x5e, 0xd3, 0x4a, 0xaa, 0x0f, 0xdc, 0xa0, 0xdf, 0x1e, 0x0d, 0x1a, 0xf4, 0x12, 0xcf, 0x30, 0x77, + 0x09, 0x1e, 0xdf, 0xcc, 0x29, 0x51, 0xbf, 0x03, 0xf2, 0x72, 0xac, 0xc1, 0x16, 0x0b, 0xc2, 0x02, 0xc2, 0x88, 0xda, + 0xaf, 0xf7, 0x5f, 0x6a, 0xde, 0xe5, 0xeb, 0x39, 0x42, 0xac, 0x60, 0x3f, 0xa2, 0x9c, 0x8c, 0x77, 0x2a, 0x9a, 0x99, + 0x7b, 0x66, 0xde, 0xdf, 0xf3, 0x74, 0x4f, 0x37, 0x37, 0xf3, 0x4a, 0xeb, 0xb3, 0xee, 0xa9, 0x3e, 0x55, 0x91, 0x26, + 0x66, 0xf5, 0x65, 0x87, 0xf2, 0xc1, 0x3c, 0xb8, 0x73, 0x95, 0xed, 0xdc, 0x01, 0x1d, 0x74, 0xd6, 0x1d, 0xfc, 0x30, + 0xf7, 0x8a, 0x0f, 0x4d, 0x81, 0xd3, 0xff, 0x97, 0x80, 0x87, 0x06, 0x43, 0xd1, 0x92, 0x66, 0x8a, 0x79, 0x0d, 0x36, + 0x2f, 0xb4, 0x58, 0x89, 0x8d, 0xfb, 0x3d, 0x8d, 0xc7, 0x36, 0x9f, 0x2b, 0x94, 0x3d, 0xfc, 0x67, 0x0f, 0x05, 0x94, + 0xc5, 0x51, 0xcc, 0xce, 0x66, 0xa1, 0xa2, 0xd8, 0x25, 0xc0, 0x14, 0xc1, 0x77, 0x97, 0x2c, 0x36, 0x73, 0x42, 0x9b, + 0xaf, 0x60, 0xad, 0xe9, 0xd3, 0xc4, 0x74, 0xbe, 0x0a, 0x41, 0x05, 0xb3, 0x58, 0x33, 0xbc, 0x24, 0xe9, 0xa1, 0x23, + 0x35, 0xed, 0x63, 0x46, 0x3d, 0x35, 0x94, 0xd1, 0xd6, 0xfd, 0xad, 0xa7, 0x14, 0x1e, 0x49, 0x93, 0x0b, 0x5d, 0x93, + 0x50, 0x00, 0xff, 0x4f, 0xb5, 0x91, 0x4a, 0x93, 0x89, 0xb0, 0x59, 0x55, 0x64, 0xcb, 0xe9, 0xc8, 0x3f, 0xfe, 0xaa, + 0xd6, 0xc5, 0x90, 0xf8, 0xe1, 0x44, 0xdd, 0x93, 0x98, 0x83, 0x1c, 0xb4, 0x38, 0x85, 0x19, 0x68, 0x8d, 0x6c, 0x9b, + 0xa3, 0x9a, 0x25, 0x79, 0x79, 0x27, 0x81, 0xa7, 0x87, 0x26, 0xfa, 0xd5, 0x57, 0x69, 0xdb, 0xac, 0x3d, 0xef, 0x82, + 0x74, 0x00, 0xe1, 0xe0, 0x98, 0x19, 0x2f, 0x36, 0x7a, 0x7b, 0x09, 0xbe, 0xdf, 0x47, 0xb5, 0xb3, 0x0b, 0x94, 0x09, + 0xb5, 0x6f, 0x74, 0xe8, 0xf5, 0x6d, 0xae, 0x39, 0x61, 0x37, 0xa6, 0x32, 0xff, 0x28, 0x34, 0x4f, 0x67, 0xa5, 0xc7, + 0xc7, 0xdf, 0xa9, 0x9d, 0xe8, 0x18, 0x45, 0x4b, 0x82, 0xc4, 0xde, 0x82, 0x6a, 0xb4, 0xac, 0x35, 0xdb, 0x58, 0xf8, + 0x4c, 0x86, 0x05, 0xc6, 0x04, 0xdf, 0x26, 0xf3, 0xfe, 0x86, 0x48, 0x08, 0xf3, 0x85, 0x50, 0x1c, 0x4c, 0xdd, 0x69, + 0xbc, 0xd2, 0x5c, 0x2a, 0x5b, 0xd3, 0x25, 0xfe, 0xc1, 0xcc, 0x82, 0x42, 0xe6, 0x13, 0x05, 0xbf, 0xcc, 0xe1, 0xb8, + 0x6b, 0x84, 0xad, 0x67, 0x50, 0xf0, 0x81, 0x39, 0x0c, 0x10, 0x29, 0x8c, 0x6e, 0xeb, 0x29, 0x1e, 0x20, 0xb3, 0x2e, + 0x43, 0x9a, 0x61, 0xbf, 0x09, 0x18, 0x81, 0x57, 0x94, 0x37, 0x2b, 0xa0, 0xbc, 0x91, 0xe6, 0x6d, 0x57, 0x1e, 0x01, + 0xca, 0x5d, 0x48, 0x3a, 0x28, 0xa1, 0x17, 0x53, 0xfb, 0xa0, 0xb2, 0x7a, 0x82, 0x56, 0x31, 0x93, 0x1b, 0xac, 0xe6, + 0x46, 0x90, 0x49, 0x42, 0x1c, 0x9f, 0xd3, 0x80, 0xe1, 0x4e, 0xc2, 0x0b, 0xc4, 0x1c, 0x46, 0x04, 0xe9, 0xe4, 0x76, + 0xde, 0x2a, 0x53, 0x74, 0xe5, 0x42, 0xda, 0x22, 0x59, 0xe6, 0xa3, 0x06, 0xf2, 0x59, 0x82, 0x05, 0xf0, 0x0f, 0x0c, + 0x8a, 0x3d, 0x12, 0x36, 0x73, 0x2c, 0xb9, 0x86, 0x41, 0xa4, 0xf4, 0xf4, 0x56, 0x99, 0xa2, 0x0e, 0x57, 0x54, 0x42, + 0xc8, 0x0c, 0x98, 0xe0, 0x4b, 0x38, 0xbe, 0xd5, 0xa0, 0xc1, 0xd0, 0x9d, 0x82, 0xda, 0x67, 0xc0, 0x49, 0x53, 0x6a, + 0x96, 0xc4, 0x9e, 0x52, 0xf8, 0xd3, 0x8c, 0x45, 0xd8, 0x34, 0x0f, 0x94, 0xef, 0x9a, 0xa9, 0x62, 0xc1, 0x1b, 0xf9, + 0x13, 0xf8, 0x0e, 0x93, 0xae, 0x28, 0x81, 0xef, 0xe3, 0x61, 0xbc, 0xc3, 0x28, 0xc4, 0x3f, 0x66, 0xba, 0x0d, 0x09, + 0xcb, 0x62, 0x86, 0x00, 0xa4, 0xdf, 0xb8, 0x2b, 0x3e, 0x2c, 0xcf, 0x9a, 0x49, 0xe2, 0xd6, 0xef, 0xf7, 0xff, 0x69, + 0x20, 0xb3, 0x0f, 0x3d, 0x91, 0xcd, 0xe6, 0x30, 0x06, 0x14, 0x9d, 0x4c, 0xd8, 0xa3, 0x71, 0xe2, 0x41, 0x01, 0xd7, + 0xa3, 0x73, 0x5d, 0x49, 0x6d, 0x3d, 0xc4, 0x7b, 0x10, 0x26, 0xac, 0xac, 0x1a, 0xc5, 0xb3, 0xbf, 0x6f, 0xba, 0xe9, + 0xd4, 0x71, 0xa0, 0x80, 0xd9, 0x5f, 0x77, 0xaa, 0x43, 0x77, 0x77, 0x83, 0xc4, 0xb5, 0x44, 0xdb, 0x70, 0xc4, 0xfb, + 0xa1, 0x01, 0x4c, 0xd9, 0xc9, 0x79, 0x71, 0x1e, 0xa6, 0x97, 0xbf, 0x1c, 0x3a, 0x2a, 0x39, 0xeb, 0x12, 0x91, 0x49, + 0xb6, 0x92, 0x6c, 0xc6, 0x5e, 0xcc, 0xad, 0x8c, 0xfe, 0x84, 0x27, 0xe8, 0xac, 0xf3, 0x30, 0x0a, 0x0a, 0x15, 0xe1, + 0x2d, 0x80, 0xc2, 0x59, 0xb6, 0xe9, 0x74, 0xf0, 0x5a, 0xc4, 0x34, 0x08, 0xd7, 0x75, 0x07, 0x54, 0xfa, 0x96, 0x92, + 0x21, 0x33, 0x05, 0x70, 0x11, 0xc5, 0x58, 0x8c, 0x04, 0xa5, 0x8c, 0x23, 0x0e, 0x95, 0xf5, 0xed, 0xe6, 0x48, 0x61, + 0x10, 0x7d, 0xb4, 0x43, 0xd7, 0xa1, 0x45, 0xd1, 0x7f, 0x8b, 0x45, 0xc8, 0xf7, 0x14, 0xa7, 0x84, 0x9b, 0x34, 0x35, + 0xf9, 0xa1, 0x0f, 0x2f, 0x60, 0x71, 0x06, 0x46, 0x77, 0x67, 0xb7, 0x3c, 0x8a, 0xbb, 0x1b, 0xfa, 0x18, 0x7e, 0xd1, + 0xcf, 0x32, 0x3b, 0xa7, 0xa6, 0xf0, 0x55, 0xec, 0xe2, 0x7b, 0x22, 0x90, 0x63, 0xce, 0x36, 0xcc, 0xf3, 0x0f, 0xb6, + 0xaf, 0x05, 0x89, 0xd5, 0xad, 0xc0, 0x29, 0x05, 0xdb, 0x7a, 0xa5, 0x01, 0x9d, 0x5d, 0x89, 0xf0, 0xfe, 0x8d, 0xef, + 0x81, 0x16, 0x51, 0x49, 0x76, 0x8a, 0x47, 0x4e, 0x7f, 0x0b, 0xe2, 0xcc, 0x81, 0x9c, 0xa2, 0x7a, 0x32, 0x82, 0x5e, + 0x40, 0x5b, 0x3e, 0x8f, 0x2e, 0x39, 0x19, 0xd6, 0x45, 0xf9, 0x44, 0x7b, 0x8e, 0xc9, 0xce, 0xa2, 0x14, 0x86, 0xa4, + 0xf4, 0x3d, 0xcc, 0x06, 0x07, 0x20, 0x3b, 0xaa, 0x7e, 0x58, 0x24, 0x61, 0xf3, 0xce, 0x24, 0x33, 0x17, 0x21, 0x39, + 0xa7, 0xf5, 0xca, 0xbd, 0x88, 0xcc, 0x5c, 0x3b, 0x8a, 0xb2, 0x8e, 0xab, 0x49, 0xd2, 0xcd, 0x66, 0x96, 0x3a, 0xa5, + 0x1a, 0x63, 0x24, 0x21, 0xa3, 0x13, 0xaf, 0x7a, 0x91, 0x94, 0x41, 0xd6, 0x44, 0xc5, 0xb2, 0xa6, 0x21, 0x59, 0x04, + 0xf4, 0x21, 0xf6, 0xba, 0xa8, 0x5c, 0xd4, 0xae, 0xa2, 0x55, 0xa9, 0xb2, 0x73, 0x50, 0xcf, 0x73, 0x13, 0xf4, 0x40, + 0xca, 0x26, 0xbb, 0xdf, 0x6e, 0x45, 0x97, 0x90, 0x43, 0x67, 0x38, 0xad, 0x66, 0x20, 0x8c, 0x97, 0xb1, 0xd6, 0xb1, + 0x2f, 0x50, 0xd4, 0xc0, 0xb5, 0xd3, 0xa0, 0xcb, 0xdb, 0xad, 0xd1, 0xc5, 0xe4, 0x51, 0x60, 0x4a, 0x56, 0xe5, 0xd2, + 0x54, 0xe1, 0x6c, 0x9e, 0x5f, 0xf6, 0x77, 0xc6, 0xb7, 0x5d, 0x3a, 0x0e, 0x54, 0x30, 0xc3, 0xbb, 0x60, 0x0f, 0x13, + 0xaf, 0x71, 0x82, 0x9c, 0x98, 0x3a, 0xf6, 0x11, 0x21, 0xd1, 0x56, 0xff, 0x7a, 0xad, 0x99, 0xf9, 0x63, 0x3f, 0xa6, + 0xdc, 0x3d, 0xd0, 0xcb, 0x91, 0xdd, 0x6c, 0xe1, 0xa5, 0x7c, 0x58, 0x42, 0x7c, 0xe1, 0x6c, 0x2e, 0xdd, 0x66, 0xe8, + 0xd2, 0xe7, 0x2f, 0x87, 0x31, 0x15, 0x5b, 0x22, 0x39, 0x1c, 0x88, 0xcd, 0xed, 0x3a, 0x27, 0x49, 0x14, 0xf0, 0x3e, + 0xcf, 0x11, 0x01, 0xcf, 0x5c, 0xf6, 0x9c, 0x49, 0x94, 0x16, 0xe9, 0x68, 0xa4, 0x4f, 0xc7, 0xa0, 0xe2, 0x53, 0xa1, + 0x84, 0xc1, 0x7d, 0x66, 0x13, 0x83, 0xfc, 0xf9, 0xb1, 0x48, 0xb7, 0xa9, 0x31, 0x6c, 0xf8, 0x0a, 0x6e, 0x15, 0x54, + 0x7e, 0xff, 0x13, 0x8d, 0xbb, 0xe6, 0x87, 0xd5, 0xd1, 0x7b, 0xfc, 0x5c, 0x41, 0x1b, 0x3c, 0xba, 0x3a, 0x0f, 0xdb, + 0x78, 0x07, 0x80, 0xe6, 0xdc, 0x16, 0x4c, 0x11, 0x6c, 0xbc, 0x75, 0x89, 0x5f, 0x86, 0xa4, 0xd6, 0xf8, 0x84, 0x40, + 0x7d, 0x36, 0xcc, 0xc3, 0xe4, 0x7d, 0xf2, 0x23, 0x1c, 0x99, 0x67, 0xa7, 0x04, 0xbc, 0x51, 0x76, 0xe5, 0x91, 0x7e, + 0x94, 0xa7, 0xbb, 0x2f, 0xbe, 0x9f, 0x5b, 0x58, 0x7f, 0x80, 0xe3, 0xf8, 0x45, 0xfd, 0xfd, 0xf0, 0x90, 0xed, 0x0f, + 0x5b, 0xff, 0xfd, 0x89, 0x92, 0xdf, 0x2a, 0x0d, 0xde, 0xfc, 0xf1, 0x42, 0x08, 0x4e, 0x0d, 0x6a, 0x98, 0xc5, 0xc8, + 0x70, 0xe9, 0x17, 0x51, 0x8a, 0x49, 0xd6, 0x18, 0xad, 0xa4, 0xa5, 0x85, 0xf7, 0x4a, 0x9b, 0xb3, 0x2b, 0xb7, 0x57, + 0x05, 0x71, 0x67, 0x69, 0xea, 0x83, 0x02, 0x93, 0x51, 0x45, 0xe0, 0x48, 0xa1, 0x6a, 0x2d, 0x61, 0x91, 0xfa, 0x8d, + 0x80, 0xae, 0xd5, 0x6b, 0x65, 0x60, 0x9c, 0xaf, 0x77, 0xb6, 0xc9, 0x3c, 0x23, 0x5b, 0xd0, 0x3c, 0xf2, 0xd2, 0x9a, + 0xb7, 0x22, 0xaa, 0xaa, 0xd6, 0x1d, 0xb6, 0x7a, 0x11, 0x23, 0xd6, 0xdd, 0x3c, 0x05, 0xc6, 0x3b, 0xc2, 0x03, 0xdc, + 0xdc, 0x30, 0x0a, 0xed, 0x56, 0x4f, 0xca, 0xd3, 0xec, 0xdd, 0x21, 0xdd, 0x68, 0x32, 0x85, 0xc6, 0x82, 0x2d, 0x5d, + 0x45, 0x87, 0xc4, 0x31, 0xe5, 0x90, 0x90, 0x33, 0xb4, 0x6f, 0xb0, 0x64, 0xd3, 0xa9, 0xda, 0x0c, 0xd7, 0x68, 0xc7, + 0x13, 0x0d, 0x31, 0x1d, 0x74, 0x45, 0x3a, 0x44, 0x0f, 0xc0, 0x14, 0x33, 0x9e, 0x26, 0x1d, 0x2d, 0xec, 0xae, 0xd5, + 0x88, 0x33, 0x4a, 0x07, 0xa3, 0x81, 0x51, 0xa2, 0xab, 0xe8, 0xf5, 0x0d, 0x42, 0xe7, 0x44, 0x76, 0x7b, 0xca, 0x5b, + 0xa5, 0x86, 0xf5, 0x99, 0xa1, 0x75, 0xa9, 0x12, 0x61, 0xa5, 0x38, 0xb1, 0xec, 0xae, 0x4c, 0xfb, 0x4a, 0x8b, 0xab, + 0xdc, 0xd0, 0xb6, 0x01, 0x50, 0x3d, 0x2d, 0xf1, 0x7a, 0xf2, 0x9a, 0xaf, 0xf6, 0xf4, 0xa4, 0x4d, 0x9f, 0x5b, 0x50, + 0xd3, 0x2e, 0x05, 0xe6, 0xf5, 0x6e, 0xa3, 0xee, 0x2b, 0xd3, 0xf0, 0xae, 0x2a, 0x26, 0x89, 0xbf, 0xb4, 0x0f, 0x71, + 0xa5, 0x43, 0xd2, 0xb0, 0x17, 0x5d, 0xc1, 0x6a, 0x71, 0x09, 0x9b, 0xf2, 0x04, 0x04, 0x46, 0x4b, 0x5a, 0x52, 0x70, + 0x83, 0xaa, 0xa2, 0xaf, 0x84, 0x57, 0xcf, 0xa7, 0xd3, 0x14, 0xac, 0xfb, 0xcd, 0xc4, 0x26, 0x8b, 0x3e, 0xcf, 0x5d, + 0x59, 0x73, 0xde, 0x1b, 0x1e, 0x55, 0x1d, 0xdb, 0x9c, 0x02, 0x74, 0xb7, 0xd3, 0x16, 0xda, 0xe2, 0x47, 0xb6, 0xc9, + 0x34, 0x6a, 0xad, 0x15, 0x95, 0xfc, 0xcc, 0x3b, 0xae, 0xfc, 0x2b, 0x65, 0xab, 0x02, 0xd5, 0x26, 0x24, 0x26, 0xe6, + 0xa3, 0x15, 0x88, 0x1d, 0x74, 0x3e, 0xe6, 0x2f, 0x74, 0x95, 0x2c, 0xce, 0x78, 0x6e, 0x72, 0x64, 0x52, 0x63, 0x78, + 0x68, 0x42, 0xd1, 0xf6, 0x71, 0xb0, 0xe9, 0x60, 0xed, 0x2f, 0xe9, 0xd4, 0xbc, 0x26, 0x0a, 0xfe, 0x9c, 0x08, 0x3b, + 0x41, 0xe3, 0xcb, 0x98, 0xe8, 0xd2, 0xe6, 0xa7, 0xfc, 0xad, 0xdb, 0x07, 0xd9, 0x7a, 0x05, 0xab, 0xf5, 0xd0, 0xea, + 0xf6, 0xec, 0x22, 0x3c, 0x37, 0x44, 0x59, 0x9f, 0x72, 0x8d, 0x79, 0xbd, 0x8a, 0x0d, 0x24, 0x8f, 0xc8, 0x41, 0x85, + 0x57, 0x4e, 0x3f, 0x06, 0x05, 0xe0, 0xe7, 0x4d, 0x76, 0x84, 0x5f, 0xb5, 0x30, 0x0f, 0xfb, 0x04, 0x56, 0x8e, 0x07, + 0x8f, 0x6e, 0x3a, 0x73, 0x5e, 0x43, 0x58, 0x20, 0x7f, 0x39, 0x4f, 0xc6, 0x23, 0xc6, 0xb2, 0x43, 0xea, 0x8a, 0xb4, + 0x27, 0x00, 0x90, 0x52, 0x34, 0x1c, 0x44, 0xc5, 0xc6, 0xc9, 0x0f, 0x94, 0xa6, 0x05, 0x44, 0x81, 0x3a, 0x9d, 0x71, + 0x0c, 0xd4, 0x0d, 0xda, 0xb1, 0x6d, 0x66, 0x4b, 0x8d, 0xc5, 0x6b, 0xb4, 0x9f, 0x9a, 0xf4, 0x2c, 0xba, 0x04, 0x6f, + 0xd1, 0x22, 0xc6, 0x2f, 0xc6, 0xb4, 0x66, 0x8b, 0x1b, 0xfd, 0xc4, 0x4e, 0xc0, 0x8d, 0xd1, 0x6d, 0x9c, 0xdd, 0xb2, + 0xb3, 0x44, 0xa5, 0x37, 0xdf, 0x40, 0xf0, 0xae, 0xb7, 0x5b, 0xbb, 0xb1, 0xd2, 0xfe, 0x33, 0x05, 0xe3, 0x2a, 0x99, + 0x1b, 0x88, 0x20, 0x55, 0x8f, 0x96, 0xfc, 0x59, 0x20, 0xb1, 0xf5, 0x5c, 0xda, 0x5a, 0x00, 0x83, 0xef, 0xf6, 0xe1, + 0x35, 0xd3, 0xb3, 0x96, 0xc3, 0x6a, 0xf0, 0xbd, 0x6f, 0xdf, 0x8c, 0xd6, 0xc7, 0x74, 0xb7, 0xbd, 0xdb, 0xc7, 0x0e, + 0x7d, 0x52, 0x4a, 0x89, 0x1b, 0x00, 0xce, 0x7d, 0xbe, 0x83, 0x49, 0xb6, 0xd9, 0x6b, 0x96, 0x0a, 0x9e, 0xab, 0xdd, + 0x9e, 0x30, 0x40, 0xdc, 0xcf, 0xb9, 0xde, 0x48, 0x18, 0xc1, 0x31, 0xe7, 0x75, 0xf3, 0x92, 0x64, 0xcc, 0x20, 0x8d, + 0x8d, 0xa1, 0x83, 0xba, 0xb6, 0x15, 0xb0, 0x20, 0xca, 0x89, 0x0b, 0x3e, 0x2d, 0x86, 0x0d, 0x22, 0x95, 0x19, 0x4d, + 0x44, 0x41, 0x35, 0x44, 0xf7, 0x72, 0xf0, 0xda, 0x81, 0x8e, 0x13, 0x07, 0x03, 0xe6, 0x5f, 0x7d, 0x02, 0xdb, 0xc7, + 0x0e, 0xb7, 0x07, 0x85, 0x38, 0xf6, 0x82, 0xa4, 0x22, 0x9d, 0xb6, 0x2e, 0x99, 0xeb, 0xe0, 0xad, 0xab, 0x96, 0x66, + 0x6f, 0xaa, 0x0f, 0xd4, 0xd7, 0xd0, 0xe3, 0x78, 0xea, 0xe7, 0x83, 0xb9, 0x03, 0xab, 0xa2, 0x2e, 0xca, 0x04, 0xc0, + 0x75, 0x6d, 0x28, 0x6d, 0x6b, 0x20, 0x60, 0x33, 0x79, 0x5a, 0x49, 0xe6, 0x0a, 0x2f, 0xe7, 0x66, 0xf3, 0x33, 0x9f, + 0x23, 0xf4, 0x9a, 0xf7, 0xab, 0xb7, 0xaa, 0xf6, 0x79, 0x69, 0x1e, 0x9e, 0xaa, 0x42, 0x05, 0xaa, 0x59, 0x67, 0xec, + 0x79, 0x06, 0x1b, 0x24, 0xc8, 0xd6, 0xb8, 0xed, 0xe3, 0xe1, 0x6f, 0x26, 0x16, 0xd3, 0x85, 0x6d, 0xe8, 0x25, 0x26, + 0x6f, 0xbf, 0xcb, 0x6c, 0x01, 0xa4, 0x48, 0x49, 0x7d, 0xc6, 0x97, 0x8c, 0x68, 0x52, 0xaf, 0x97, 0x5a, 0xd5, 0xf8, + 0x48, 0xab, 0x56, 0xfb, 0x07, 0x86, 0xac, 0x9f, 0x7f, 0xf4, 0x4f, 0xc6, 0x6e, 0x2f, 0xfe, 0x7d, 0xf3, 0xe4, 0xb5, + 0xdb, 0xc7, 0xd6, 0x62, 0xeb, 0x3f, 0x76, 0x26, 0xea, 0x86, 0x9e, 0xe7, 0xb5, 0x7f, 0xb7, 0x0a, 0x34, 0x78, 0x4f, + 0x85, 0x2f, 0x0c, 0x83, 0x3b, 0xf9, 0x66, 0x80, 0x17, 0x90, 0xad, 0xcc, 0xa2, 0xad, 0x83, 0x6b, 0x5c, 0xe3, 0xff, + 0xb8, 0x42, 0x8c, 0xe9, 0xa5, 0xda, 0x78, 0x80, 0xfe, 0xbc, 0xa3, 0xe5, 0xa6, 0xc1, 0xb7, 0x1d, 0x36, 0x65, 0x9e, + 0x89, 0x0b, 0xeb, 0x87, 0x75, 0x4a, 0x9a, 0x6b, 0x8e, 0xd7, 0x4d, 0xe7, 0xdd, 0x25, 0x8f, 0xa6, 0x30, 0xe0, 0x32, + 0x97, 0xa1, 0xdb, 0x5c, 0x38, 0x74, 0xbe, 0x89, 0xad, 0x9f, 0x54, 0xa2, 0xd2, 0x54, 0x02, 0x55, 0xfd, 0xda, 0x52, + 0x45, 0x19, 0xea, 0xd8, 0xfa, 0xb7, 0x0d, 0x2f, 0x56, 0xe5, 0xde, 0xc4, 0x03, 0xcc, 0xc8, 0x56, 0x20, 0x86, 0x0b, + 0x7e, 0x86, 0xa9, 0x35, 0xae, 0x1c, 0x68, 0xcc, 0x0e, 0xff, 0x8b, 0x48, 0x2a, 0x41, 0x40, 0x5b, 0x38, 0xd8, 0xc7, + 0xcc, 0xb8, 0x27, 0x3a, 0xa6, 0x0e, 0x3a, 0xb3, 0x93, 0x0f, 0x4e, 0x71, 0xf0, 0x5d, 0xbb, 0xdb, 0xa1, 0xdb, 0x0c, + 0xdb, 0x3b, 0x45, 0x4f, 0x9d, 0x14, 0x5b, 0x49, 0xe1, 0xae, 0xae, 0xa8, 0x1d, 0xe9, 0x74, 0xbe, 0x76, 0x57, 0x08, + 0x6a, 0x76, 0x05, 0xd1, 0x34, 0xbe, 0x36, 0x9e, 0x68, 0x72, 0xf0, 0x17, 0xfe, 0x25, 0x24, 0xf0, 0x65, 0x6f, 0x62, + 0x90, 0xbe, 0xce, 0xd0, 0x5d, 0xba, 0x8a, 0xee, 0x42, 0xba, 0xaa, 0x1f, 0x61, 0x15, 0xb3, 0x1f, 0xc1, 0x7d, 0xa2, + 0xf7, 0xe2, 0xcd, 0x86, 0xa1, 0xb1, 0xc2, 0x64, 0x68, 0x73, 0x1b, 0x32, 0xcc, 0xf9, 0x6d, 0x48, 0xd1, 0xc6, 0xa6, + 0x1b, 0x90, 0x57, 0xe4, 0x64, 0x76, 0x4d, 0x94, 0x4d, 0x97, 0x2e, 0x22, 0x38, 0x08, 0xf7, 0xa1, 0x9a, 0xd0, 0x9e, + 0x3d, 0x09, 0x3e, 0xcd, 0xca, 0x34, 0x61, 0xa9, 0xe6, 0x72, 0x5c, 0x20, 0x33, 0xd9, 0xc4, 0x00, 0xe6, 0xc3, 0xd8, + 0xe5, 0xb3, 0xc7, 0x1d, 0xd8, 0x7b, 0xb1, 0xe3, 0xa1, 0xdb, 0x1e, 0x94, 0xed, 0xa3, 0x83, 0xd5, 0xe7, 0xf3, 0xfe, + 0x2a, 0xb3, 0xdd, 0xeb, 0xbd, 0x74, 0x1b, 0x66, 0xe9, 0x31, 0xcf, 0x66, 0x8b, 0xa5, 0x9e, 0xdf, 0x20, 0xaf, 0x66, + 0xa7, 0x4a, 0x71, 0x29, 0x9e, 0x00, 0xf0, 0xbb, 0xac, 0xe1, 0x07, 0x92, 0x16, 0xcf, 0xea, 0xf4, 0xfc, 0x48, 0x9b, + 0xb6, 0x92, 0xc5, 0x10, 0x10, 0x9d, 0xca, 0x29, 0xea, 0xc6, 0xd6, 0x66, 0x50, 0xa4, 0xd3, 0xee, 0xcc, 0x66, 0x48, + 0xe1, 0x59, 0xf9, 0xcf, 0x66, 0xce, 0x3e, 0x74, 0xd2, 0xa0, 0xdc, 0x1e, 0x1c, 0xdc, 0x2a, 0x95, 0x49, 0x47, 0xa2, + 0xf0, 0x52, 0x51, 0x20, 0x44, 0x10, 0xe7, 0x41, 0xaf, 0xbc, 0xa4, 0x35, 0xa2, 0x62, 0x4d, 0x88, 0x1f, 0xb5, 0x06, + 0xd7, 0xe0, 0xd6, 0xfe, 0xf6, 0x3c, 0xc0, 0x0d, 0x1c, 0x72, 0x94, 0xf7, 0x29, 0xcf, 0x9b, 0xdc, 0xb1, 0xa2, 0xfb, + 0x89, 0xc1, 0x5c, 0x03, 0x03, 0x2a, 0x29, 0xdf, 0x2b, 0x6e, 0xc6, 0x98, 0x3f, 0xfd, 0x7e, 0x15, 0xc2, 0x4a, 0x7d, + 0xb1, 0xca, 0x61, 0x07, 0xe4, 0xdb, 0xaf, 0x20, 0x68, 0x51, 0x36, 0x51, 0xf8, 0x9a, 0xaf, 0xf0, 0xec, 0xd6, 0x66, + 0xa9, 0xff, 0xc7, 0x3d, 0x49, 0xcd, 0x5c, 0xfc, 0xbb, 0x4b, 0x47, 0x8d, 0x6f, 0x36, 0x7e, 0xa5, 0x5b, 0x99, 0xd5, + 0x48, 0x51, 0xd6, 0xae, 0xc9, 0x46, 0xf3, 0x33, 0x30, 0x4e, 0xd0, 0x8b, 0xaf, 0xd8, 0x81, 0x9f, 0x77, 0x49, 0xaa, + 0xd2, 0xad, 0xa5, 0x9f, 0xfb, 0x2b, 0xc9, 0x78, 0xca, 0xe8, 0x57, 0x19, 0x6e, 0x14, 0x34, 0x27, 0x5f, 0xfa, 0x3f, + 0x0c, 0xe0, 0x1d, 0x28, 0xc3, 0xd9, 0x0a, 0x7f, 0xad, 0xe3, 0x2e, 0x7e, 0xdd, 0x85, 0x9b, 0xf9, 0xb2, 0x11, 0x06, + 0xda, 0x43, 0x20, 0xa7, 0xea, 0xf7, 0x39, 0x9e, 0xb8, 0x0c, 0xd3, 0x99, 0x26, 0xbc, 0x8a, 0x82, 0xe5, 0xce, 0x7b, + 0xed, 0x9b, 0x34, 0x1b, 0x8f, 0x17, 0x24, 0x16, 0x27, 0x78, 0x45, 0xd8, 0xea, 0x42, 0xc9, 0xb7, 0xb9, 0x85, 0xa6, + 0xc0, 0x2b, 0xdd, 0xec, 0x41, 0xda, 0x2f, 0x93, 0x9d, 0x25, 0xab, 0x9e, 0x33, 0x84, 0x11, 0x1b, 0x7b, 0x74, 0x95, + 0x26, 0xf5, 0x59, 0x69, 0x8d, 0x36, 0x34, 0x63, 0x4d, 0xa7, 0xe6, 0x72, 0x40, 0xaa, 0x55, 0xb5, 0xc2, 0x59, 0x57, + 0xb9, 0xc0, 0x36, 0x73, 0x4a, 0xd1, 0x67, 0x07, 0x05, 0x9e, 0x25, 0xac, 0xeb, 0x1c, 0xb8, 0x86, 0x12, 0x0d, 0xce, + 0x6b, 0x76, 0xdb, 0x80, 0xac, 0x44, 0x7e, 0x61, 0x40, 0x09, 0x1b, 0x8f, 0x7f, 0xb1, 0x43, 0xf1, 0xed, 0xd9, 0x6a, + 0x19, 0xc1, 0xc8, 0x8a, 0x49, 0xfd, 0x9d, 0x23, 0xb1, 0x3f, 0x3f, 0xa3, 0xb4, 0xb7, 0x5c, 0x4c, 0xa8, 0x5b, 0x36, + 0xab, 0xd8, 0x6f, 0xa5, 0x84, 0xa3, 0x69, 0xaa, 0x96, 0x78, 0x7a, 0x1f, 0x29, 0xab, 0xd6, 0x5b, 0xc0, 0x06, 0x2d, + 0xaa, 0x36, 0x22, 0x5e, 0x30, 0x21, 0x7e, 0xff, 0xc1, 0x46, 0x80, 0x47, 0xa4, 0x64, 0xb2, 0xe5, 0x38, 0xab, 0x14, + 0xc3, 0xf9, 0xe6, 0x63, 0xb3, 0x5d, 0x4f, 0x58, 0xe4, 0x23, 0x8c, 0x58, 0xb7, 0x54, 0xc1, 0xba, 0x1f, 0xf6, 0x24, + 0xf5, 0xe8, 0x39, 0x3a, 0xc2, 0x61, 0x54, 0x41, 0x2b, 0x7a, 0x73, 0xf6, 0x0a, 0x49, 0x53, 0xc8, 0x44, 0x90, 0x7c, + 0x18, 0x97, 0x62, 0xc8, 0xad, 0x7d, 0x23, 0x4f, 0x95, 0xef, 0x1b, 0x30, 0x54, 0xde, 0xb7, 0x84, 0x26, 0xc8, 0x9a, + 0x9f, 0xa2, 0xa2, 0xe7, 0xce, 0x6e, 0x45, 0xb0, 0x5a, 0x74, 0x72, 0x52, 0x95, 0x69, 0x7e, 0x02, 0xa1, 0x65, 0x2e, + 0xc8, 0x66, 0xbf, 0xae, 0x86, 0xfc, 0xe8, 0xe4, 0xbc, 0x8d, 0x19, 0x67, 0x33, 0x64, 0x1b, 0x2b, 0xce, 0x94, 0xd3, + 0xe2, 0x5b, 0x73, 0xb7, 0x87, 0xbc, 0xec, 0xae, 0x03, 0x05, 0x0f, 0x87, 0x12, 0x9a, 0xf1, 0xe7, 0xea, 0x9f, 0x27, + 0x41, 0x55, 0xe5, 0x84, 0x36, 0xfe, 0x59, 0x7c, 0xc6, 0xe7, 0x6a, 0xc1, 0x97, 0x70, 0xd8, 0x31, 0x00, 0x54, 0x02, + 0xeb, 0x62, 0xa8, 0xfd, 0x54, 0x80, 0xdd, 0xef, 0x0d, 0x69, 0x7c, 0xef, 0x9c, 0xa4, 0x59, 0xd8, 0xc7, 0xae, 0xbd, + 0x69, 0x72, 0x90, 0xa3, 0xed, 0x5a, 0x85, 0x37, 0xea, 0xab, 0x3e, 0xd6, 0x33, 0xcb, 0xf0, 0x03, 0x08, 0x2d, 0xcd, + 0x25, 0x90, 0x63, 0x18, 0x83, 0x7e, 0xf1, 0xe6, 0x7f, 0xfd, 0x02, 0x5c, 0x40, 0xb0, 0x45, 0xc1, 0xf3, 0x6d, 0xaf, + 0x7c, 0xc2, 0xb4, 0x94, 0x4a, 0x21, 0x38, 0x67, 0xfd, 0x47, 0xb0, 0x21, 0x2e, 0xed, 0x4e, 0x6d, 0x32, 0x61, 0x38, + 0x25, 0x15, 0xd1, 0x06, 0x8d, 0xd9, 0xce, 0x73, 0x4e, 0xf3, 0x60, 0xf3, 0xcf, 0x82, 0x8b, 0x92, 0xef, 0x9b, 0x99, + 0x9e, 0x3d, 0x50, 0x75, 0xe6, 0xda, 0x6a, 0x7a, 0x82, 0x1e, 0xa4, 0xce, 0x5f, 0x8b, 0x65, 0xac, 0xee, 0x77, 0x4b, + 0x4a, 0x22, 0x1b, 0x13, 0x0a, 0x36, 0xb4, 0xa1, 0xbb, 0x26, 0x88, 0x39, 0x8d, 0x6b, 0xbb, 0x15, 0xfd, 0xde, 0x89, + 0x66, 0x20, 0xdd, 0x28, 0x87, 0x65, 0x98, 0x32, 0x84, 0xe4, 0x96, 0xf1, 0x1d, 0x59, 0x97, 0x5d, 0xd9, 0x58, 0x84, + 0xb2, 0x7f, 0xb7, 0xe5, 0x70, 0x4a, 0xa1, 0x6a, 0xd4, 0x17, 0x60, 0x48, 0x89, 0x69, 0x9b, 0x2c, 0x8b, 0xb8, 0xb3, + 0x05, 0x05, 0xcd, 0x94, 0x8d, 0x9d, 0xda, 0x75, 0x84, 0x21, 0x73, 0xf8, 0x35, 0xb2, 0x27, 0x1d, 0x99, 0xa7, 0xc8, + 0x65, 0x93, 0x9e, 0xf5, 0xfa, 0x73, 0x07, 0x28, 0x6c, 0x5f, 0xe0, 0x94, 0x3c, 0xcf, 0x69, 0xaa, 0xa1, 0x96, 0x1b, + 0xd2, 0x45, 0x51, 0x25, 0x38, 0x3a, 0x27, 0x78, 0x81, 0x23, 0x84, 0xca, 0x96, 0x92, 0xa0, 0x1e, 0x0f, 0xa1, 0x4a, + 0x24, 0x47, 0xc7, 0x09, 0xcc, 0x75, 0xbc, 0x9a, 0x6b, 0xfc, 0x37, 0x24, 0x8f, 0x36, 0x7e, 0x80, 0xb8, 0x96, 0xd9, + 0xc8, 0xc7, 0x43, 0x6a, 0x98, 0xc2, 0x58, 0x1f, 0x29, 0xf8, 0x6a, 0x1a, 0xc2, 0xa2, 0xc9, 0x40, 0x1a, 0x18, 0x9c, + 0x02, 0xff, 0x2d, 0x5c, 0x33, 0x56, 0x5e, 0xb9, 0x0e, 0x15, 0xab, 0xb4, 0x6b, 0xfa, 0x55, 0xff, 0xcc, 0xd8, 0x8b, + 0xa8, 0x6f, 0x77, 0x18, 0x7b, 0x96, 0x6a, 0x05, 0x3f, 0xcf, 0xb5, 0x61, 0x7c, 0x37, 0x74, 0x9a, 0x74, 0x9e, 0x53, + 0x5f, 0x39, 0x70, 0x51, 0x6c, 0xa2, 0x68, 0x33, 0x7a, 0x4d, 0x9d, 0x9a, 0x25, 0x9c, 0xea, 0xb8, 0x49, 0xb2, 0x2e, + 0x31, 0x8e, 0xa4, 0x17, 0xfb, 0xfa, 0x46, 0x63, 0xaa, 0x68, 0x25, 0xbe, 0x53, 0x51, 0xae, 0x80, 0xb3, 0x10, 0x84, + 0x56, 0xec, 0x89, 0x57, 0xcb, 0xca, 0x4a, 0x7c, 0xa4, 0x05, 0xf3, 0x46, 0x54, 0x20, 0xc8, 0x13, 0xd2, 0x3a, 0x71, + 0x27, 0x46, 0x66, 0x15, 0x72, 0xb7, 0x21, 0xc9, 0x08, 0x11, 0x5d, 0xb0, 0x97, 0xd0, 0xdb, 0xa5, 0xab, 0xb3, 0xa7, + 0x00, 0x2f, 0x10, 0x23, 0xfa, 0x07, 0xd3, 0xc2, 0x72, 0xd4, 0x4e, 0x94, 0xe8, 0x4e, 0xf6, 0x6f, 0x36, 0xff, 0x7e, + 0xac, 0x4a, 0x50, 0xa8, 0xbd, 0x0e, 0x01, 0xb3, 0x16, 0x93, 0x9e, 0xa4, 0x6d, 0x93, 0x02, 0x28, 0x96, 0xa0, 0x0d, + 0x7e, 0x5d, 0x0d, 0xa4, 0xbb, 0xf6, 0xde, 0x97, 0x46, 0x4c, 0xb8, 0x7c, 0x96, 0x92, 0x57, 0x19, 0xd5, 0x32, 0x7b, + 0xde, 0xb5, 0x17, 0x94, 0x96, 0xc0, 0xd5, 0x2f, 0x31, 0xa7, 0x3f, 0xef, 0x60, 0x46, 0x26, 0xc4, 0xb4, 0x67, 0xcc, + 0xcb, 0x66, 0x3d, 0xa6, 0xbe, 0xad, 0x63, 0xb1, 0xb5, 0x59, 0x3b, 0x7c, 0xf0, 0xc7, 0xd1, 0x9d, 0xa2, 0x35, 0xee, + 0x9f, 0xcb, 0x7f, 0xdb, 0x70, 0xdf, 0x7a, 0x67, 0xab, 0xd0, 0x5c, 0x5d, 0x27, 0xdb, 0xe8, 0xbe, 0x57, 0x3b, 0xc7, + 0x8a, 0x58, 0x7c, 0x1b, 0x63, 0xd7, 0x1d, 0xa0, 0xe3, 0xbb, 0x46, 0x81, 0xfb, 0x13, 0xd8, 0xe5, 0xf3, 0xe3, 0xf3, + 0x6a, 0x41, 0x8c, 0x23, 0xd9, 0x7a, 0x36, 0xf3, 0x0f, 0x97, 0x44, 0x77, 0xb7, 0xf4, 0x1e, 0x45, 0x20, 0xfa, 0x3e, + 0xa9, 0x97, 0x75, 0x26, 0xe3, 0x0b, 0xf2, 0xc8, 0xea, 0x15, 0xf8, 0xcd, 0x74, 0xd7, 0x1e, 0xdb, 0x89, 0x33, 0xc7, + 0xe6, 0x97, 0xcf, 0xf0, 0x48, 0x90, 0xe1, 0x9c, 0x21, 0xc6, 0x29, 0xea, 0xf8, 0x51, 0x2f, 0xe6, 0x4c, 0x3e, 0x92, + 0x02, 0xbe, 0xde, 0x74, 0x4e, 0x71, 0xa8, 0xa6, 0x30, 0x17, 0x1a, 0x4d, 0x3a, 0xb1, 0x8f, 0x14, 0x00, 0xda, 0x9e, + 0x98, 0x12, 0x33, 0x71, 0x39, 0xbd, 0x01, 0x75, 0xbd, 0x07, 0x29, 0x95, 0xf3, 0x17, 0x31, 0x99, 0x71, 0xea, 0x39, + 0x98, 0x55, 0x7d, 0x51, 0xcc, 0x3f, 0xc1, 0xcc, 0xd4, 0xa8, 0x4d, 0x01, 0x4f, 0x8b, 0x19, 0x35, 0x3d, 0xb6, 0xdf, + 0x08, 0x49, 0xda, 0x6b, 0x96, 0x70, 0xb1, 0x33, 0x3e, 0x77, 0x50, 0x0a, 0xff, 0x56, 0x01, 0x3c, 0xa3, 0xd5, 0x67, + 0x55, 0xf2, 0x1c, 0x50, 0x16, 0xc3, 0xf6, 0xa5, 0x17, 0x7b, 0x1a, 0x5f, 0x05, 0xd7, 0x9f, 0x15, 0xc4, 0x56, 0xfc, + 0xfb, 0x97, 0x9b, 0xbe, 0xae, 0xf6, 0x16, 0xa2, 0x4f, 0x9d, 0x85, 0x27, 0x27, 0xbc, 0xde, 0x09, 0xe2, 0x74, 0x83, + 0xfd, 0x29, 0x6b, 0x89, 0xc1, 0xc9, 0x82, 0x7f, 0x6c, 0x45, 0x11, 0xaa, 0x8e, 0xfa, 0x98, 0xc5, 0x9d, 0x84, 0x2c, + 0x2b, 0x18, 0x86, 0x91, 0x41, 0xa6, 0x03, 0xfc, 0xd9, 0x97, 0xea, 0x8b, 0x8b, 0x68, 0xe0, 0xa5, 0x35, 0xfb, 0x9d, + 0x4f, 0xe1, 0x58, 0xd1, 0x85, 0x4f, 0xe1, 0xa7, 0x77, 0xa1, 0x02, 0x6c, 0x7d, 0x2d, 0x93, 0x33, 0x49, 0xf4, 0x65, + 0xd8, 0x57, 0x0c, 0x97, 0x34, 0x25, 0x8f, 0xbb, 0xa8, 0x92, 0xf3, 0xbf, 0xca, 0x75, 0x3f, 0xa3, 0x2f, 0xa9, 0xc6, + 0x3a, 0x0a, 0x46, 0xdd, 0xd5, 0x36, 0xa5, 0x77, 0x9c, 0x29, 0x29, 0xca, 0xd5, 0x0b, 0x4d, 0xfb, 0xfa, 0x93, 0xab, + 0xaf, 0xf4, 0x55, 0xd2, 0x4e, 0x35, 0x7a, 0xc2, 0x4b, 0x75, 0xd3, 0x81, 0x7f, 0xcb, 0xc9, 0xbd, 0x78, 0x2b, 0x35, + 0xb2, 0x37, 0xfd, 0x0f, 0xb6, 0x5d, 0x93, 0x73, 0x25, 0x4e, 0xb9, 0x60, 0x07, 0xe5, 0xd0, 0xe5, 0x38, 0x9e, 0xc4, + 0xb6, 0x55, 0x34, 0x8a, 0x2d, 0xe5, 0x96, 0x05, 0xce, 0x8d, 0x79, 0x22, 0x13, 0x24, 0x6a, 0x19, 0xae, 0x19, 0x5e, + 0x53, 0x80, 0x70, 0xba, 0x94, 0xe0, 0x66, 0xc0, 0x74, 0xea, 0x76, 0x4c, 0xe4, 0x74, 0xec, 0x35, 0x7e, 0x68, 0x84, + 0x10, 0x95, 0x72, 0xbe, 0x4d, 0x19, 0x51, 0xf5, 0x59, 0x76, 0x57, 0xf2, 0x56, 0x29, 0xd1, 0xb6, 0xea, 0x98, 0x8b, + 0x72, 0x60, 0xd1, 0x0b, 0x06, 0xad, 0x9c, 0x39, 0x89, 0xf5, 0xe9, 0x39, 0x69, 0xe3, 0x7f, 0xd9, 0x89, 0x1d, 0xe6, + 0xc8, 0xfb, 0x28, 0x75, 0x67, 0x0c, 0xe2, 0x9b, 0x3a, 0x49, 0x82, 0xbe, 0xb8, 0xea, 0x06, 0x4e, 0x59, 0x9c, 0x9a, + 0x5a, 0x5d, 0x03, 0xb0, 0x45, 0x0b, 0xad, 0x3e, 0x50, 0xf5, 0x40, 0xec, 0x57, 0xb5, 0xc1, 0x5f, 0x2b, 0x5e, 0xa6, + 0xf3, 0xb4, 0x0f, 0x15, 0x6b, 0xa4, 0x03, 0x43, 0x0e, 0xee, 0x4c, 0xb0, 0x06, 0xa1, 0x40, 0xc9, 0xe2, 0x5c, 0xc9, + 0x23, 0x8c, 0x8d, 0xe3, 0x88, 0xb5, 0x04, 0xc5, 0x94, 0xb7, 0x7d, 0x60, 0x07, 0x17, 0x88, 0x6e, 0xc4, 0x85, 0x65, + 0x1b, 0x51, 0xb4, 0x20, 0x29, 0x4a, 0x8e, 0x15, 0xea, 0x05, 0xdf, 0x08, 0xb1, 0x18, 0xc0, 0x5c, 0xd2, 0x37, 0x8b, + 0x89, 0x82, 0x0a, 0xc6, 0xe1, 0x0d, 0xfe, 0x6d, 0xe2, 0x12, 0xa1, 0x2f, 0xc4, 0x6b, 0xe3, 0x5b, 0x32, 0x5f, 0x60, + 0x4f, 0xa7, 0x20, 0xeb, 0x25, 0xbe, 0xdd, 0x7c, 0xf6, 0x1b, 0x56, 0xbf, 0x81, 0xb9, 0x9a, 0x5f, 0x26, 0xce, 0x59, + 0x4d, 0x79, 0xe7, 0xba, 0x3d, 0xcb, 0x02, 0xcd, 0xd9, 0xf8, 0xde, 0xa1, 0x6a, 0x82, 0x66, 0x7c, 0x41, 0xd3, 0x9b, + 0x8b, 0xb1, 0x2e, 0xd0, 0xdf, 0x5b, 0xcd, 0x2d, 0x30, 0x89, 0x0b, 0xd6, 0x53, 0xde, 0xe7, 0xf7, 0xa6, 0x4d, 0x03, + 0xeb, 0xc5, 0x9c, 0x03, 0x34, 0x2f, 0xc3, 0xa7, 0xd3, 0x4a, 0x7b, 0x46, 0x93, 0x82, 0x3f, 0xdc, 0xe0, 0xd0, 0x32, + 0xed, 0xd7, 0xcf, 0x5e, 0xf4, 0xba, 0xe1, 0x5f, 0x2e, 0x03, 0x38, 0xea, 0x5f, 0x46, 0x42, 0xc7, 0xde, 0x19, 0xe7, + 0x56, 0x41, 0x1c, 0x8d, 0xb1, 0x21, 0xf4, 0x3f, 0x12, 0xe7, 0x33, 0x32, 0x78, 0x06, 0x76, 0x41, 0x05, 0x42, 0x92, + 0x7e, 0xb1, 0xa2, 0x39, 0x2c, 0x6f, 0x31, 0x6d, 0xd4, 0x72, 0xc1, 0xb4, 0x65, 0xb8, 0xc5, 0xcb, 0x56, 0x1b, 0x8b, + 0xea, 0xcb, 0xe7, 0xc2, 0x60, 0x12, 0x56, 0x91, 0xfb, 0x3f, 0xce, 0x00, 0xd4, 0x4f, 0x20, 0x79, 0x0c, 0x5b, 0xdf, + 0x2e, 0xfa, 0xd5, 0xb2, 0x40, 0xaf, 0xcc, 0x93, 0x0d, 0x5a, 0xe3, 0x32, 0x46, 0xd4, 0x85, 0xe9, 0x75, 0x6d, 0xae, + 0xa1, 0x7b, 0x63, 0x7d, 0x1a, 0x09, 0x7d, 0x07, 0x0b, 0xf1, 0xed, 0xc7, 0xb4, 0xd1, 0x71, 0x07, 0x71, 0x53, 0xd8, + 0x6f, 0x55, 0x9b, 0xc8, 0x59, 0xeb, 0xb9, 0x89, 0x82, 0xe2, 0x1a, 0x51, 0x7d, 0x93, 0x73, 0x87, 0x8f, 0x6e, 0xa2, + 0xa3, 0xf2, 0x1a, 0xef, 0x2d, 0xd5, 0xd4, 0xd7, 0x00, 0x2d, 0xd4, 0x1d, 0x6a, 0xa0, 0xe7, 0xc5, 0xab, 0x22, 0x02, + 0x9e, 0xa9, 0x73, 0xfc, 0x25, 0x2a, 0x78, 0x04, 0x1f, 0xcd, 0xab, 0x52, 0xaa, 0xda, 0x37, 0x21, 0xab, 0x83, 0x5c, + 0x93, 0x07, 0x7e, 0x48, 0x75, 0x1d, 0xde, 0x46, 0x01, 0x1a, 0x3c, 0xa2, 0x1a, 0x3c, 0xb2, 0xfe, 0xbc, 0x38, 0x4f, + 0x31, 0x7e, 0x3a, 0x05, 0x4b, 0x37, 0x02, 0x4b, 0x1b, 0xfb, 0xf2, 0xe2, 0xb0, 0xb9, 0x64, 0x55, 0x00, 0x92, 0x19, + 0xf5, 0x52, 0x2c, 0x7e, 0x26, 0x15, 0x9e, 0x37, 0xaa, 0xac, 0x6e, 0xb3, 0xa3, 0x8f, 0x74, 0x6e, 0x2b, 0x13, 0x10, + 0x0a, 0xfd, 0xfe, 0x91, 0x09, 0x95, 0x78, 0x55, 0x68, 0x04, 0x01, 0x7a, 0xab, 0xc1, 0x79, 0x35, 0xca, 0x7e, 0xfe, + 0x75, 0xeb, 0x3e, 0x2d, 0x5e, 0xa2, 0x61, 0x2f, 0xdd, 0xa8, 0xb1, 0xa0, 0x93, 0x60, 0x30, 0x25, 0x8c, 0x82, 0xdc, + 0x82, 0x76, 0xa4, 0x77, 0x12, 0xbd, 0x19, 0xa8, 0x4f, 0x0b, 0xaa, 0xfe, 0xdf, 0xee, 0xa7, 0x54, 0xf4, 0x13, 0x81, + 0x16, 0xf2, 0x64, 0xeb, 0x01, 0x5f, 0x1b, 0xbe, 0xc5, 0xf9, 0xab, 0x46, 0xba, 0x90, 0x5c, 0x52, 0x10, 0x1b, 0x99, + 0xb2, 0x19, 0x69, 0x90, 0x56, 0x3c, 0x73, 0x4d, 0xea, 0x42, 0x4a, 0xbb, 0x69, 0xf0, 0xb3, 0x95, 0xd7, 0x20, 0xd5, + 0xe4, 0xd1, 0x15, 0x6b, 0x2f, 0x6e, 0x5c, 0xc6, 0x1b, 0x67, 0xd7, 0x47, 0xb4, 0x2a, 0xb4, 0x2c, 0x54, 0x2b, 0xd2, + 0xa5, 0xd4, 0x77, 0x66, 0x79, 0x89, 0x00, 0xf6, 0x88, 0xbd, 0x0b, 0x17, 0xed, 0x9b, 0x65, 0x16, 0x39, 0xb0, 0xcd, + 0x3d, 0x0b, 0xdb, 0x5e, 0x1f, 0x12, 0xf9, 0x52, 0xfc, 0xcc, 0x8c, 0xea, 0x62, 0xd5, 0x34, 0x9f, 0x1d, 0x0c, 0x12, + 0xad, 0x36, 0x11, 0x67, 0xe2, 0xa4, 0x47, 0x20, 0x0a, 0x53, 0xa2, 0x9f, 0x45, 0xb1, 0x8c, 0x20, 0xfb, 0x47, 0xf6, + 0x86, 0x23, 0xdd, 0x84, 0x15, 0x87, 0xef, 0x01, 0xfb, 0x37, 0xfb, 0x6f, 0x1b, 0x46, 0x30, 0xad, 0xe0, 0xbc, 0x10, + 0x2c, 0x42, 0xe3, 0x2d, 0x86, 0x46, 0xb8, 0x9f, 0x04, 0x24, 0xde, 0x48, 0x71, 0x82, 0xfa, 0xdc, 0x8e, 0xaf, 0x5e, + 0x1d, 0xd2, 0x23, 0xcc, 0x50, 0x78, 0x36, 0xe5, 0x94, 0x67, 0xb0, 0x8f, 0xe7, 0xa2, 0xfb, 0x97, 0xea, 0x10, 0x1b, + 0x05, 0x47, 0xca, 0x52, 0xab, 0x42, 0xd6, 0x71, 0xdd, 0xbf, 0x5b, 0x1d, 0x73, 0x36, 0x36, 0x7d, 0xe5, 0x25, 0x0d, + 0x5a, 0x69, 0x48, 0xf4, 0x80, 0x1d, 0xe3, 0xd9, 0x86, 0x24, 0x3b, 0x56, 0x9a, 0x84, 0x18, 0xcd, 0x24, 0xd6, 0xc1, + 0xb4, 0x7f, 0xf4, 0xca, 0xb3, 0x56, 0xec, 0xba, 0xe6, 0x74, 0x6d, 0x06, 0xa9, 0xd0, 0x36, 0x22, 0xac, 0x26, 0xa6, + 0xbb, 0x88, 0x76, 0xfa, 0x33, 0x55, 0xbf, 0x1e, 0x29, 0xd3, 0xd8, 0x4f, 0x50, 0x28, 0x4f, 0xf0, 0x66, 0xbb, 0x2b, + 0x27, 0x77, 0x09, 0x00, 0x4d, 0xff, 0x72, 0xdd, 0x85, 0x73, 0xa6, 0x8a, 0x56, 0x3d, 0xf0, 0x69, 0xd2, 0x35, 0x2f, + 0xe1, 0x50, 0xcd, 0x68, 0x04, 0xe0, 0x3c, 0x09, 0xa1, 0xcb, 0xd9, 0x9e, 0x6b, 0x08, 0x9a, 0xd6, 0xf3, 0xb4, 0xce, + 0x9e, 0x11, 0x3d, 0xff, 0xa9, 0xcf, 0x7c, 0x21, 0x5d, 0x51, 0x14, 0xb5, 0x29, 0x6b, 0x8a, 0xa1, 0xa1, 0x8d, 0x33, + 0xb9, 0xe1, 0xb4, 0x8b, 0x16, 0x21, 0x9d, 0xd9, 0x4b, 0x7d, 0x8a, 0x75, 0xa5, 0xdb, 0xce, 0x06, 0x16, 0x96, 0x06, + 0x26, 0x50, 0x72, 0x54, 0x69, 0x71, 0x9d, 0x59, 0xbe, 0x54, 0x5b, 0xb7, 0x74, 0x9e, 0xcb, 0x17, 0x79, 0x1a, 0xc6, + 0xe7, 0x5f, 0x01, 0x77, 0x72, 0xe4, 0x02, 0xcb, 0xbc, 0xa2, 0x5a, 0x42, 0xfa, 0x94, 0x5f, 0xc3, 0x68, 0xe1, 0xb1, + 0xf1, 0xc0, 0xb4, 0xba, 0x7f, 0xb0, 0x54, 0x95, 0xf3, 0x82, 0xa9, 0x31, 0x8f, 0x49, 0x93, 0x02, 0x37, 0xb9, 0x0d, + 0xea, 0x4a, 0x0c, 0xb0, 0x4d, 0x91, 0x7f, 0xf2, 0xa3, 0x20, 0x43, 0x3c, 0x90, 0xd1, 0xa8, 0x06, 0xea, 0x34, 0x73, + 0xbc, 0xb3, 0x4b, 0x5d, 0xac, 0xda, 0xde, 0x82, 0x62, 0x78, 0x5b, 0xea, 0x82, 0xe1, 0x99, 0xe2, 0xa9, 0x84, 0x37, + 0xe5, 0x0a, 0xf6, 0xaf, 0x12, 0xa1, 0xa1, 0x72, 0xa1, 0xf6, 0xc3, 0x31, 0x6c, 0xb5, 0x0b, 0x81, 0xd2, 0x6f, 0x1a, + 0x1a, 0x85, 0x86, 0xac, 0x57, 0xcd, 0xab, 0xba, 0xb7, 0x79, 0xab, 0x36, 0x84, 0xa1, 0x29, 0xd2, 0xb9, 0x60, 0xdb, + 0xc5, 0x1e, 0xee, 0xff, 0x14, 0x43, 0x11, 0x52, 0x2b, 0xe7, 0xe2, 0x43, 0x3e, 0xee, 0x20, 0x60, 0x7e, 0x52, 0x0f, + 0xfe, 0xfa, 0xa3, 0x30, 0xe4, 0x7f, 0x56, 0x7a, 0xa0, 0xe2, 0x87, 0xfd, 0x22, 0xfc, 0x2a, 0xf3, 0xb7, 0x86, 0x94, + 0x93, 0x77, 0x7d, 0xdb, 0x05, 0x00, 0x2d, 0x5f, 0xc8, 0x81, 0xbc, 0xeb, 0xcc, 0x8d, 0x91, 0xb5, 0x6d, 0x32, 0xaf, + 0xd6, 0xf1, 0x2b, 0x81, 0x82, 0xd8, 0xf8, 0x2d, 0x94, 0xfd, 0xd9, 0x90, 0x1b, 0xfe, 0xc3, 0xc1, 0xdc, 0x52, 0x42, + 0x57, 0x59, 0x93, 0x53, 0xca, 0x0e, 0x19, 0x01, 0xd2, 0x08, 0x1c, 0x47, 0x3e, 0x33, 0xa0, 0xbf, 0x8d, 0x2b, 0xfa, + 0xe9, 0x15, 0xb7, 0xa1, 0x58, 0x4d, 0x4f, 0x75, 0x8d, 0x90, 0x87, 0xe9, 0x42, 0x76, 0x33, 0xa1, 0x89, 0x58, 0x38, + 0x2e, 0x47, 0x02, 0xd9, 0x9b, 0xc8, 0x74, 0x02, 0x2d, 0xd8, 0x9a, 0xe5, 0xd6, 0x48, 0xae, 0x6a, 0x2b, 0xa7, 0xcb, + 0xfa, 0xe4, 0x48, 0xea, 0x55, 0x81, 0x1b, 0x79, 0xeb, 0x7c, 0x51, 0x67, 0x47, 0x45, 0xa5, 0x67, 0xc8, 0xdb, 0xdc, + 0xc2, 0x89, 0xe5, 0x93, 0xe2, 0x37, 0x9c, 0xe4, 0xee, 0xd5, 0x7a, 0xa0, 0x48, 0xc2, 0x54, 0x28, 0xb3, 0x17, 0x39, + 0xdb, 0x6e, 0xf4, 0xe0, 0xbd, 0xa5, 0xa0, 0x57, 0x90, 0x0d, 0xb6, 0xdc, 0x5d, 0xdd, 0x29, 0xbd, 0xc0, 0xb3, 0x12, + 0x4e, 0x9b, 0x71, 0xed, 0x85, 0x46, 0x66, 0x49, 0x96, 0x90, 0xf6, 0xbf, 0xba, 0xc7, 0x90, 0x58, 0x5e, 0x6e, 0xc4, + 0xbe, 0xf9, 0xba, 0x0b, 0x43, 0xc9, 0x42, 0x87, 0x0f, 0xec, 0xc1, 0x7b, 0x4c, 0xc5, 0x9b, 0xae, 0x06, 0x3c, 0xf4, + 0x20, 0xa1, 0x94, 0xef, 0xa2, 0xd4, 0xc7, 0xdf, 0x30, 0x7d, 0x7d, 0xef, 0x56, 0x6c, 0xf6, 0x80, 0x17, 0x81, 0x81, + 0xd1, 0xb3, 0x6d, 0xd2, 0xe3, 0x53, 0xd7, 0x11, 0xaa, 0x06, 0x5c, 0xcd, 0xbf, 0xee, 0xa4, 0x37, 0xbb, 0x7d, 0x1a, + 0xf7, 0x76, 0x3f, 0xc4, 0xef, 0x65, 0x63, 0x2a, 0x0f, 0xf5, 0x44, 0xb1, 0xae, 0xcf, 0x5b, 0x62, 0x44, 0x11, 0x27, + 0x1e, 0xd6, 0x7d, 0x6e, 0x54, 0x67, 0x1d, 0x49, 0xf7, 0x6e, 0xc0, 0x8e, 0x92, 0x36, 0x9d, 0x7d, 0xda, 0xe9, 0xb2, + 0x7c, 0x4d, 0x6b, 0x0f, 0x5f, 0x1f, 0x78, 0xe9, 0x36, 0xbf, 0xee, 0x14, 0xb5, 0x31, 0xdb, 0xa2, 0xc9, 0xba, 0xbe, + 0xe3, 0xe2, 0x45, 0xf3, 0xe2, 0x47, 0xcd, 0x6d, 0x55, 0x1d, 0x99, 0x16, 0xb3, 0x7c, 0x9e, 0x0f, 0x90, 0xfc, 0x3e, + 0x3d, 0x05, 0x27, 0x4f, 0xf1, 0xdb, 0xee, 0x1b, 0xde, 0x82, 0x8f, 0xee, 0x5e, 0x8d, 0x4b, 0x59, 0xef, 0x3f, 0xf3, + 0x5b, 0x5e, 0x62, 0xfd, 0xa2, 0x6a, 0xdb, 0xab, 0x41, 0x51, 0xda, 0xd4, 0xfb, 0x2d, 0xff, 0xbc, 0x33, 0x43, 0x46, + 0xfe, 0x99, 0xda, 0xd9, 0x64, 0x2c, 0x01, 0xf4, 0x5f, 0x95, 0xaa, 0x9d, 0x59, 0xe0, 0x8d, 0x67, 0x30, 0x11, 0x0f, + 0x04, 0xaa, 0x5f, 0x50, 0xc8, 0x4c, 0xf1, 0x9d, 0xc6, 0x80, 0xf7, 0x78, 0x74, 0x2a, 0x3c, 0x5e, 0xf6, 0x7e, 0x15, + 0xe3, 0xe0, 0x19, 0x46, 0xec, 0xf6, 0x3f, 0x0e, 0xa2, 0x40, 0x2a, 0x1c, 0x0c, 0xd2, 0x15, 0xce, 0x74, 0xfc, 0xc9, + 0xc0, 0xfe, 0x25, 0xfd, 0x53, 0x75, 0x86, 0xf1, 0x31, 0xbe, 0x72, 0x63, 0xd4, 0x12, 0x5f, 0xa2, 0x7d, 0x9b, 0x2c, + 0xc2, 0xda, 0xf3, 0x64, 0xaf, 0xee, 0xf2, 0x6a, 0x83, 0x88, 0xea, 0xc9, 0x64, 0x79, 0xdc, 0xac, 0x22, 0x4c, 0x00, + 0x45, 0xaa, 0x97, 0x07, 0x2e, 0x43, 0x7e, 0x9f, 0x3f, 0x3f, 0x21, 0xce, 0x2d, 0x9e, 0x11, 0x3f, 0x98, 0x4f, 0x4e, + 0xf8, 0xa8, 0x7b, 0x6d, 0xfd, 0x6d, 0x22, 0x80, 0x2e, 0x99, 0xda, 0x36, 0x39, 0x60, 0x38, 0x70, 0x90, 0xf4, 0xee, + 0xf0, 0xe6, 0x5f, 0x0d, 0x41, 0x28, 0x5f, 0xad, 0x60, 0x69, 0xf5, 0x27, 0x88, 0xd9, 0xd2, 0x98, 0x84, 0x9c, 0x40, + 0x10, 0xae, 0x8d, 0x8f, 0x1d, 0x64, 0x1e, 0xd8, 0x54, 0x0b, 0x2c, 0x2d, 0x39, 0x05, 0xa2, 0x36, 0xee, 0x55, 0xcd, + 0xbd, 0x48, 0x73, 0x32, 0xca, 0xd4, 0xe6, 0x19, 0xab, 0xd6, 0x52, 0x4d, 0x06, 0xfe, 0xc3, 0xbc, 0xc6, 0xfe, 0xac, + 0x70, 0x41, 0x5f, 0xba, 0x79, 0x72, 0xf0, 0xb0, 0x48, 0x30, 0x07, 0x1f, 0x05, 0x30, 0x94, 0x11, 0xfc, 0xa7, 0x96, + 0x5b, 0x39, 0x8f, 0x81, 0x77, 0x28, 0xa9, 0x6a, 0xb1, 0xfb, 0xd2, 0x68, 0x06, 0xce, 0xca, 0xe8, 0x07, 0xf2, 0xbd, + 0xe4, 0x16, 0xf6, 0xf1, 0x23, 0x5f, 0xd0, 0x76, 0x94, 0x33, 0x55, 0x24, 0x54, 0x8d, 0xf7, 0xb6, 0x7f, 0xcb, 0x8a, + 0xfe, 0x95, 0xf7, 0x97, 0x72, 0xc6, 0xab, 0x02, 0x9f, 0x78, 0xc6, 0xa7, 0xf9, 0x72, 0x5a, 0x3c, 0x2a, 0xae, 0x58, + 0x48, 0xb2, 0xa8, 0xf2, 0xd0, 0xeb, 0x3f, 0x89, 0x15, 0x0a, 0x5e, 0xd1, 0xd9, 0x0a, 0x60, 0x8b, 0x18, 0x1d, 0x54, + 0x2a, 0xab, 0x7d, 0x95, 0x47, 0xc6, 0xbc, 0x79, 0xe7, 0x47, 0x61, 0x80, 0x5c, 0xb6, 0xa1, 0xaa, 0x7b, 0x2a, 0xfa, + 0x1a, 0x52, 0x61, 0xd9, 0x8a, 0x4d, 0xef, 0x19, 0x9e, 0x3a, 0x98, 0x7c, 0x4f, 0x2c, 0x77, 0x1f, 0x50, 0x1c, 0xc6, + 0x9a, 0x53, 0xaa, 0x2a, 0x33, 0x3e, 0x8f, 0x9c, 0x7e, 0x3e, 0x85, 0x67, 0xf4, 0x58, 0x64, 0xab, 0xbf, 0xe6, 0xc3, + 0x5a, 0xd8, 0xc2, 0xb7, 0x85, 0x50, 0x83, 0x5e, 0xe8, 0x05, 0xd7, 0xeb, 0x4b, 0x38, 0x88, 0x99, 0x11, 0x37, 0xef, + 0x6b, 0x93, 0x08, 0x64, 0xfd, 0x6c, 0xc4, 0x35, 0xd9, 0xfa, 0xc2, 0xc2, 0x7e, 0x8b, 0xf0, 0x8d, 0x84, 0xe8, 0x4f, + 0xe4, 0x31, 0xeb, 0x07, 0xc9, 0x74, 0xdd, 0x4e, 0x4e, 0xd5, 0x3f, 0x14, 0xf0, 0x6a, 0xc4, 0xfd, 0x15, 0x10, 0x3e, + 0x1f, 0xcb, 0xf5, 0x38, 0x13, 0x04, 0x05, 0x8f, 0xb5, 0x0a, 0x42, 0x79, 0x1b, 0xb5, 0x25, 0xb4, 0xde, 0x2a, 0x08, + 0x60, 0x33, 0xd6, 0xb1, 0x8b, 0x9f, 0x8e, 0xa5, 0x3f, 0x97, 0xfb, 0x3b, 0xa7, 0xf4, 0xc0, 0x8d, 0x0b, 0x0f, 0xf0, + 0x85, 0xef, 0x11, 0xbb, 0xd0, 0x88, 0x67, 0x0d, 0x62, 0x3f, 0x8e, 0xb7, 0x9a, 0xde, 0xd6, 0xa9, 0x76, 0xd8, 0x5c, + 0xa1, 0x54, 0x57, 0xde, 0x4b, 0x78, 0x1b, 0xe6, 0x3c, 0x4f, 0x22, 0xcf, 0x8f, 0x62, 0x1e, 0x38, 0xae, 0x94, 0xc4, + 0x99, 0x94, 0x86, 0xe0, 0xc7, 0x51, 0x27, 0x58, 0xf9, 0x31, 0x33, 0xf6, 0x59, 0x58, 0xdf, 0xf7, 0x0c, 0x3b, 0xf6, + 0x27, 0x5e, 0x07, 0x47, 0x27, 0x2c, 0xa7, 0xe6, 0x66, 0x07, 0xc6, 0x4f, 0x81, 0x2a, 0x4f, 0x08, 0xc2, 0xd6, 0xac, + 0xdc, 0x9b, 0xdc, 0xbe, 0xee, 0x12, 0xa2, 0xd9, 0x10, 0x55, 0x8f, 0x5d, 0xe0, 0xea, 0x65, 0x49, 0xa5, 0x2a, 0xd5, + 0x53, 0x85, 0x0a, 0x43, 0x6b, 0xb5, 0x2d, 0x66, 0x9c, 0xde, 0xbb, 0x11, 0x5c, 0xb8, 0x34, 0xd2, 0x0c, 0x2f, 0x04, + 0x16, 0x58, 0x3b, 0x3d, 0x55, 0xca, 0x68, 0xa5, 0x50, 0x17, 0xf5, 0x79, 0x5c, 0xbf, 0x86, 0x2e, 0x7b, 0xe1, 0x4d, + 0x65, 0x6d, 0x53, 0x34, 0x2c, 0xd8, 0x86, 0x89, 0xae, 0xd3, 0x95, 0xba, 0x9c, 0x7d, 0xf4, 0x57, 0xf5, 0x8c, 0xe6, + 0x58, 0x75, 0xec, 0x49, 0x08, 0xb5, 0x50, 0x83, 0x42, 0xa4, 0xd7, 0xdb, 0x01, 0x88, 0xdc, 0x13, 0xd2, 0xe0, 0x1c, + 0x0b, 0x36, 0x92, 0xed, 0x5c, 0xc1, 0xa6, 0xcd, 0x01, 0x71, 0xe2, 0xe7, 0x7e, 0x10, 0x07, 0x3e, 0x69, 0x43, 0x9a, + 0xf3, 0xb8, 0xfd, 0xd2, 0xdd, 0x1e, 0x58, 0xc9, 0x53, 0x56, 0x28, 0x32, 0x66, 0xbb, 0xab, 0x42, 0x4c, 0x7e, 0x4e, + 0xa6, 0x1e, 0x7c, 0x37, 0x60, 0xfd, 0xab, 0xe1, 0xcc, 0x09, 0xaf, 0x4b, 0x91, 0x45, 0x11, 0x64, 0xff, 0x3a, 0x8e, + 0x1c, 0x01, 0xec, 0x17, 0x5c, 0xa7, 0x58, 0xf7, 0x2d, 0xd5, 0x7c, 0x69, 0xa5, 0xc4, 0xcb, 0xfb, 0xa9, 0xc4, 0x8e, + 0x45, 0xc1, 0x07, 0x01, 0x69, 0xb0, 0xe2, 0xe3, 0x38, 0x06, 0x34, 0x95, 0x0d, 0xb8, 0xee, 0x61, 0x86, 0x15, 0xa5, + 0xdb, 0x3d, 0xbe, 0x8f, 0x4f, 0x71, 0x42, 0xc0, 0x1f, 0x9d, 0x39, 0x58, 0xa4, 0x15, 0x6c, 0xe9, 0x71, 0x78, 0x71, + 0xb0, 0xea, 0x69, 0x9b, 0xa4, 0xb8, 0xe6, 0xc7, 0x6f, 0x8e, 0xd5, 0x5c, 0xb6, 0x34, 0x6b, 0xbd, 0x74, 0xf7, 0xc7, + 0x8b, 0x03, 0x6a, 0x2b, 0x6c, 0x64, 0x81, 0xa8, 0x06, 0x15, 0xb4, 0x0e, 0xb2, 0xaf, 0xd3, 0x4e, 0xa9, 0x81, 0x66, + 0xb4, 0x98, 0xca, 0x3e, 0xa9, 0xe7, 0x93, 0xb1, 0xb5, 0x68, 0x3c, 0xad, 0xc3, 0x26, 0xec, 0x98, 0x9c, 0xa7, 0x60, + 0x64, 0x92, 0xe2, 0xb9, 0x9c, 0xe1, 0x33, 0x0a, 0x20, 0x8a, 0xba, 0x2a, 0x01, 0x5a, 0x5d, 0x28, 0xf6, 0xda, 0x98, + 0x29, 0x01, 0x52, 0xe1, 0xcf, 0x2b, 0xad, 0xcb, 0x08, 0xc5, 0x91, 0xd7, 0x36, 0xaf, 0x34, 0x5f, 0x27, 0xb4, 0x0e, + 0x71, 0xec, 0xf5, 0x64, 0xbd, 0xad, 0x60, 0x0a, 0x50, 0x43, 0x86, 0xae, 0xa9, 0x03, 0xbe, 0xfb, 0xdd, 0x0c, 0x80, + 0x3f, 0x88, 0x3c, 0xb2, 0x4e, 0x34, 0x1b, 0x1e, 0x92, 0x47, 0xc0, 0xd9, 0x43, 0xe5, 0x2a, 0xae, 0xac, 0xec, 0x62, + 0xdd, 0x16, 0xb8, 0x57, 0xb2, 0xf1, 0x65, 0x13, 0xe4, 0x94, 0x3d, 0x67, 0xa9, 0x65, 0x43, 0xc4, 0x81, 0x4a, 0x52, + 0x9b, 0x6c, 0xb0, 0x94, 0x66, 0xf3, 0x2d, 0x2a, 0xcd, 0xf5, 0xd6, 0xf9, 0xc7, 0x80, 0x34, 0x9a, 0xab, 0xd2, 0xdc, + 0x01, 0x0a, 0x00, 0x93, 0x76, 0xf1, 0x4c, 0x93, 0x23, 0x0a, 0x51, 0x58, 0xc0, 0xa0, 0x82, 0xab, 0xb1, 0x77, 0xd4, + 0xec, 0xcc, 0x0e, 0x80, 0x1d, 0x77, 0x75, 0x2b, 0x76, 0xa9, 0x60, 0xbc, 0x89, 0x81, 0xea, 0x57, 0xe3, 0x40, 0xd1, + 0xa6, 0xa3, 0xcb, 0xa2, 0xe8, 0x42, 0x32, 0x57, 0x97, 0x2a, 0x4f, 0xf0, 0x10, 0x95, 0x29, 0x36, 0x6a, 0x22, 0x1c, + 0x40, 0xae, 0x57, 0xbe, 0x6e, 0x7c, 0xad, 0xe3, 0xeb, 0x41, 0x10, 0x70, 0x3f, 0x91, 0x34, 0x92, 0x80, 0x8d, 0xbc, + 0xc2, 0x3e, 0xae, 0x40, 0x5f, 0x7c, 0x6a, 0x2b, 0x72, 0x72, 0xa9, 0xd7, 0x92, 0xc9, 0x92, 0xd5, 0x6c, 0x7f, 0x93, + 0x13, 0x84, 0x3e, 0x25, 0x29, 0x85, 0x9c, 0x4e, 0x77, 0x50, 0x75, 0xc8, 0xe3, 0x75, 0x2c, 0x60, 0x92, 0x8d, 0x5e, + 0xba, 0xad, 0x2d, 0xac, 0xb9, 0x10, 0xde, 0x28, 0x1b, 0x61, 0x4e, 0xac, 0x2b, 0x52, 0xf3, 0x0b, 0x34, 0x5e, 0xbc, + 0xf1, 0x57, 0x2c, 0xb4, 0x7e, 0xe0, 0x2b, 0xd5, 0x89, 0x65, 0xb1, 0x9b, 0x39, 0x19, 0x2a, 0x25, 0x8b, 0xdb, 0xad, + 0x75, 0x08, 0x91, 0xa7, 0x49, 0x9b, 0x81, 0x5c, 0x02, 0x16, 0xc1, 0x13, 0x44, 0x58, 0x74, 0x18, 0x0a, 0x9b, 0xe6, + 0x3a, 0x7e, 0x1e, 0x3e, 0x9a, 0x10, 0x4b, 0xed, 0x8a, 0xa5, 0x25, 0x11, 0x7e, 0xf8, 0xcd, 0x36, 0x56, 0x89, 0xba, + 0xb5, 0x30, 0x49, 0x58, 0x9a, 0xde, 0xfb, 0x45, 0xdd, 0xa5, 0xaf, 0x80, 0x74, 0x58, 0x86, 0xad, 0x88, 0xdd, 0x8b, + 0xd1, 0xdd, 0xb8, 0x04, 0x48, 0x38, 0x92, 0x4e, 0x0a, 0xcd, 0x4b, 0x4a, 0xca, 0xcf, 0x5c, 0xdd, 0xa8, 0xd2, 0x0c, + 0xa2, 0x94, 0xf3, 0x3a, 0x51, 0x68, 0xb9, 0x27, 0x36, 0x09, 0x11, 0x19, 0x3e, 0x2f, 0x12, 0xe4, 0xad, 0xd6, 0x6f, + 0x7b, 0xe8, 0x20, 0xc0, 0x86, 0x4e, 0x01, 0x7a, 0x8c, 0x92, 0x61, 0x10, 0x98, 0x0d, 0x85, 0x3d, 0x1b, 0x54, 0x94, + 0x20, 0xb4, 0x2d, 0x98, 0x13, 0xa1, 0xcb, 0x37, 0x99, 0x66, 0x98, 0xfc, 0x3c, 0xed, 0xf2, 0xf1, 0xdd, 0x19, 0x2e, + 0x8f, 0x95, 0x77, 0x36, 0x9a, 0xf7, 0x80, 0xf4, 0x9c, 0xb4, 0xe9, 0xa1, 0x34, 0x51, 0x7a, 0x0f, 0x51, 0x4f, 0x0e, + 0xaf, 0x09, 0x56, 0xa1, 0x25, 0x4c, 0x8d, 0xe9, 0x56, 0xbb, 0xfb, 0x42, 0xa2, 0x77, 0x6d, 0xae, 0x10, 0xa5, 0xb5, + 0x1b, 0x6a, 0xb5, 0x87, 0xe6, 0x99, 0xa4, 0x79, 0xda, 0x95, 0xfa, 0x8e, 0x6b, 0x0a, 0x70, 0xda, 0x66, 0x7d, 0x4e, + 0xa0, 0x35, 0x00, 0x2d, 0x48, 0x0d, 0x12, 0x23, 0xe8, 0x89, 0x31, 0x4f, 0xc5, 0xde, 0x38, 0x5f, 0x53, 0x64, 0x15, + 0x13, 0x9a, 0x04, 0xbc, 0xed, 0xbd, 0x84, 0x70, 0x06, 0x81, 0x90, 0x48, 0xc7, 0xa3, 0x14, 0xab, 0xee, 0x17, 0xef, + 0x24, 0xc2, 0x96, 0x13, 0x35, 0x8c, 0x10, 0xce, 0x41, 0x83, 0x58, 0x80, 0x0a, 0x53, 0x1a, 0x06, 0x87, 0x01, 0x6b, + 0x06, 0x19, 0xd0, 0x79, 0x2b, 0xa5, 0x48, 0xb8, 0x20, 0x87, 0x44, 0xd1, 0x77, 0x25, 0xc4, 0x21, 0x2b, 0x72, 0x69, + 0xa0, 0xda, 0x3b, 0x18, 0x8d, 0x37, 0xe3, 0xb4, 0x94, 0x2e, 0x71, 0x46, 0x7d, 0x8c, 0x62, 0xa6, 0x80, 0x73, 0xfb, + 0x11, 0x73, 0xdd, 0x8d, 0xc8, 0xc5, 0xd0, 0xc7, 0x75, 0x5b, 0x69, 0x89, 0xeb, 0xe1, 0x9c, 0x22, 0x41, 0x15, 0x8d, + 0x0a, 0x6e, 0x1b, 0x85, 0xc8, 0x4e, 0x5d, 0x30, 0xaa, 0x42, 0x88, 0xc4, 0x10, 0xd5, 0x56, 0x85, 0xc5, 0x15, 0xb7, + 0x98, 0x24, 0xcc, 0x38, 0x8b, 0x88, 0x16, 0xf0, 0x3c, 0xdb, 0xff, 0x29, 0x8a, 0xde, 0x3c, 0xf2, 0x05, 0x55, 0xa0, + 0xff, 0xf6, 0x04, 0x63, 0xfc, 0xf8, 0xd6, 0x0f, 0x1f, 0xf7, 0x14, 0x4f, 0x3f, 0xef, 0xa9, 0x5f, 0x7f, 0xe2, 0xe3, + 0x48, 0x9e, 0xf1, 0x8b, 0xfd, 0x5b, 0x0c, 0x96, 0x19, 0x30, 0x65, 0x05, 0xcb, 0xfe, 0x6e, 0x65, 0x7a, 0xe7, 0x84, + 0x9c, 0xb6, 0xe1, 0x62, 0xcb, 0x78, 0x6c, 0x75, 0xb2, 0x06, 0x2a, 0xb2, 0x38, 0x56, 0xb0, 0x32, 0xcb, 0xd7, 0x3c, + 0xd7, 0x67, 0x97, 0xde, 0x9e, 0xb8, 0x23, 0x51, 0x25, 0x77, 0x1e, 0x80, 0x93, 0x92, 0xf5, 0xa3, 0x6f, 0x23, 0xff, + 0x11, 0xd5, 0x6e, 0x3b, 0x28, 0x11, 0x4a, 0x2c, 0xc9, 0x7e, 0x55, 0x5a, 0xd3, 0xaf, 0xb7, 0x98, 0xb3, 0xa6, 0x96, + 0x1b, 0x86, 0x87, 0x51, 0xfe, 0x48, 0xbe, 0xdc, 0xb1, 0x3e, 0x34, 0x8d, 0xe7, 0xe4, 0x69, 0xe8, 0xa5, 0x8b, 0x88, + 0x55, 0x58, 0xd0, 0xff, 0xab, 0xa7, 0xff, 0xbf, 0x18, 0x24, 0xd2, 0xe1, 0xb7, 0x41, 0x8f, 0x37, 0x0c, 0x10, 0x93, + 0x73, 0xbe, 0xd1, 0xc7, 0x3b, 0xf1, 0xaf, 0x3c, 0xcc, 0x9f, 0xb3, 0xfd, 0xdd, 0xe0, 0xef, 0xeb, 0xb2, 0xef, 0xfa, + 0xb5, 0x69, 0x0b, 0x69, 0x37, 0x48, 0xe3, 0x95, 0x1a, 0x13, 0x34, 0xab, 0xc6, 0x91, 0xd1, 0x54, 0x8f, 0x47, 0x55, + 0x88, 0xac, 0x29, 0xc7, 0x4e, 0x7f, 0x08, 0x3a, 0x28, 0x78, 0x1c, 0x0d, 0x95, 0xe5, 0x99, 0x34, 0x47, 0xb5, 0x0d, + 0x4c, 0xf6, 0x66, 0xd4, 0x56, 0x2c, 0x16, 0xd6, 0xd6, 0x6c, 0xe2, 0xd9, 0xa3, 0xf1, 0xae, 0x56, 0xc6, 0xc6, 0x03, + 0xa9, 0x27, 0x17, 0xa7, 0x19, 0x91, 0x58, 0x8c, 0x91, 0x6d, 0xb9, 0xa9, 0x2f, 0x7b, 0xe5, 0x2d, 0xfa, 0xf3, 0x8a, + 0x3f, 0x9a, 0x9b, 0xba, 0x88, 0x51, 0xaf, 0x07, 0xdd, 0x1f, 0x9e, 0x2b, 0x71, 0x71, 0x58, 0xec, 0x7c, 0x8d, 0x0f, + 0x87, 0x1d, 0xbf, 0xda, 0x9c, 0x63, 0xea, 0x25, 0xc1, 0x86, 0x7e, 0x1a, 0x1c, 0xcd, 0xfd, 0xa3, 0xc1, 0x15, 0x03, + 0x7a, 0x20, 0x95, 0x9b, 0x22, 0xcd, 0x08, 0x30, 0x51, 0x3c, 0xd6, 0x5c, 0xaf, 0x73, 0x0f, 0xf1, 0xd5, 0xb6, 0x40, + 0x62, 0xc4, 0xe9, 0xf4, 0x62, 0x48, 0x24, 0x98, 0x98, 0x9e, 0xd2, 0x5e, 0x5c, 0x3e, 0x19, 0xde, 0x22, 0x3a, 0x1b, + 0xd7, 0xde, 0xde, 0xf9, 0xcc, 0x77, 0x89, 0x6b, 0x7c, 0x61, 0xb9, 0xcc, 0x2e, 0x30, 0x8d, 0x78, 0x0d, 0x54, 0x88, + 0x71, 0x60, 0x28, 0x7e, 0x82, 0xfe, 0x72, 0x21, 0x02, 0xb5, 0xcc, 0x68, 0x97, 0xb6, 0x37, 0x69, 0xec, 0xd8, 0x79, + 0x2e, 0x77, 0x09, 0x94, 0x38, 0x2e, 0x52, 0x6b, 0xbe, 0x73, 0x3f, 0x38, 0xd6, 0x85, 0xe1, 0xbe, 0x6e, 0xa3, 0xe4, + 0xdb, 0xca, 0xa9, 0x6e, 0x79, 0x14, 0xee, 0x88, 0xe1, 0x68, 0x6c, 0x53, 0xfa, 0x99, 0x2d, 0x72, 0xa3, 0x7c, 0xd2, + 0x0b, 0x51, 0xfe, 0x04, 0xd8, 0x9a, 0xe1, 0x2e, 0x58, 0xaf, 0xcf, 0x01, 0xa2, 0xae, 0xae, 0xd6, 0xf6, 0x7c, 0x31, + 0xfa, 0x5d, 0xe1, 0xde, 0xf2, 0x20, 0xc1, 0x98, 0xb6, 0x39, 0x9e, 0xc8, 0xbe, 0x72, 0x5a, 0x09, 0x5d, 0xe7, 0xe0, + 0x34, 0x71, 0x7f, 0x3c, 0x87, 0x9e, 0xab, 0x91, 0xbc, 0x4b, 0x09, 0x97, 0x29, 0x53, 0x92, 0x31, 0xbd, 0xbb, 0x3a, + 0xc0, 0x76, 0xe8, 0xa0, 0x48, 0xb3, 0x0e, 0xc2, 0x20, 0xe1, 0xa9, 0x0d, 0x3e, 0xdd, 0x33, 0x06, 0x1f, 0x3f, 0x53, + 0xce, 0x2b, 0x5a, 0x55, 0x09, 0x9f, 0x57, 0x1f, 0xf2, 0xfb, 0xef, 0x50, 0x41, 0xd6, 0x37, 0x6b, 0x64, 0xc3, 0xae, + 0x2c, 0x0f, 0x10, 0xe7, 0x51, 0x84, 0xfd, 0x80, 0xce, 0x7e, 0xcc, 0xc2, 0xa6, 0x7d, 0x18, 0x3f, 0xf9, 0xa6, 0xe9, + 0x7a, 0xde, 0x99, 0xd6, 0x9c, 0x1f, 0x7c, 0xd8, 0x2b, 0xe1, 0x40, 0xb7, 0xb3, 0xf4, 0xbf, 0x88, 0x18, 0x20, 0x18, + 0x6c, 0xfe, 0xbe, 0x9c, 0x0f, 0xcf, 0x1e, 0xf2, 0x73, 0x44, 0xe4, 0x0e, 0x37, 0xb1, 0x77, 0xfc, 0x2e, 0xaf, 0x2a, + 0xc3, 0x06, 0xf2, 0x8a, 0x73, 0x19, 0xe1, 0xf2, 0xd6, 0xba, 0x6b, 0xc5, 0xb6, 0x24, 0x0b, 0xae, 0x25, 0x40, 0x61, + 0x64, 0x72, 0xc8, 0xed, 0xf2, 0x3f, 0x2b, 0xb6, 0x20, 0x21, 0xaa, 0x9d, 0xd4, 0x5d, 0xbd, 0x77, 0xae, 0x36, 0x55, + 0x1e, 0xfb, 0x87, 0x8f, 0x72, 0xe6, 0x0c, 0xa3, 0x0a, 0x77, 0x6c, 0xb3, 0x87, 0x2a, 0xa3, 0x36, 0x19, 0x13, 0x87, + 0x2a, 0xed, 0xac, 0xef, 0xa9, 0x58, 0x7a, 0x8c, 0x58, 0x62, 0x20, 0x23, 0x33, 0x1b, 0x92, 0xf6, 0xde, 0xec, 0x17, + 0x5e, 0x2f, 0xae, 0xb8, 0x4c, 0x08, 0x20, 0x6b, 0x63, 0xa0, 0xab, 0xad, 0x34, 0xec, 0xed, 0xf6, 0x7e, 0xfa, 0x28, + 0xbb, 0x3e, 0xe8, 0x1f, 0xe6, 0x0f, 0x5c, 0xaa, 0x35, 0x2b, 0xa7, 0xd6, 0xb2, 0xed, 0x15, 0xed, 0xd0, 0xeb, 0x2d, + 0xb3, 0xe9, 0x12, 0xd6, 0x23, 0xc9, 0xa2, 0xa5, 0x3c, 0xae, 0xaa, 0x4e, 0xd5, 0xb0, 0xdb, 0x34, 0x75, 0x9f, 0x39, + 0xbe, 0x43, 0x0a, 0x65, 0x59, 0x99, 0xd2, 0x27, 0xcf, 0x9c, 0x78, 0xaa, 0x28, 0x83, 0x39, 0x13, 0xdc, 0x96, 0x93, + 0x11, 0xa9, 0x88, 0xd7, 0x18, 0xcd, 0x0f, 0x01, 0xab, 0xb8, 0xae, 0x9f, 0x78, 0x14, 0x97, 0x0e, 0xae, 0xb3, 0xa1, + 0x6e, 0x3e, 0x5f, 0x13, 0x92, 0x96, 0x89, 0xf3, 0x69, 0xc0, 0xd7, 0x40, 0xd7, 0x47, 0x91, 0x02, 0xc0, 0x71, 0x26, + 0x93, 0xca, 0x7e, 0xd4, 0x91, 0xf3, 0x7e, 0xd3, 0x7c, 0xb5, 0x3e, 0xbb, 0xc8, 0xd7, 0xad, 0xf1, 0xab, 0xe1, 0x34, + 0x8f, 0x9e, 0x96, 0x9e, 0xf6, 0xf5, 0x79, 0xa6, 0x12, 0xc5, 0xfe, 0xca, 0x99, 0xbd, 0x51, 0xde, 0x15, 0xab, 0xec, + 0x2e, 0x7a, 0x78, 0xd7, 0xcf, 0x09, 0x70, 0xf8, 0x6e, 0x57, 0x20, 0xf2, 0xc3, 0xb2, 0x79, 0x8a, 0xcb, 0xa9, 0xb1, + 0x53, 0x94, 0x82, 0x19, 0x8d, 0xad, 0x88, 0x67, 0x6a, 0x26, 0xb0, 0x5e, 0xed, 0xe5, 0x61, 0x5a, 0x36, 0xa4, 0x19, + 0x7f, 0x58, 0x8b, 0xd1, 0x0e, 0x93, 0x07, 0x59, 0x06, 0xb3, 0xc8, 0xfa, 0xd0, 0x1c, 0x9d, 0xba, 0x62, 0xd2, 0xf6, + 0xd4, 0x29, 0x0b, 0xb7, 0x0f, 0xd6, 0xd8, 0x25, 0xe5, 0x50, 0x95, 0xe7, 0xef, 0xd7, 0x78, 0xe5, 0xb9, 0x48, 0xc6, + 0x3b, 0x70, 0xde, 0xb2, 0xdf, 0xc6, 0x09, 0x62, 0xdc, 0xd8, 0x6a, 0x7c, 0x16, 0x1b, 0x77, 0x82, 0x96, 0x09, 0xe4, + 0xec, 0xc1, 0x02, 0x9c, 0x86, 0x37, 0x45, 0xa6, 0xb5, 0xfc, 0x6c, 0x08, 0x78, 0x6f, 0xe8, 0x77, 0x75, 0x0b, 0x00, + 0x8b, 0xc8, 0x7b, 0xbd, 0x52, 0x9c, 0x2e, 0x8d, 0xc3, 0xc7, 0xdd, 0x95, 0xe2, 0x51, 0xda, 0x4d, 0x74, 0x77, 0xca, + 0x33, 0x48, 0x41, 0xbc, 0x7c, 0xa5, 0x5a, 0x8c, 0xaa, 0x97, 0xc8, 0x09, 0x04, 0x2c, 0x52, 0x8a, 0xff, 0xac, 0x7b, + 0x02, 0x2b, 0xd5, 0x77, 0xfc, 0xaa, 0x7a, 0x41, 0xac, 0x01, 0xbb, 0x6d, 0xb9, 0x85, 0x9e, 0x2a, 0x81, 0x7c, 0x00, + 0x99, 0x0b, 0xc0, 0xc0, 0xfd, 0xbb, 0x6e, 0xc2, 0xf5, 0x9f, 0x47, 0x99, 0x6f, 0x75, 0x5b, 0xae, 0xcf, 0xe6, 0xd1, + 0xd9, 0x8c, 0x9d, 0x90, 0x2f, 0x27, 0x7d, 0x09, 0x8a, 0xc9, 0xa6, 0x80, 0xfa, 0x21, 0xb3, 0x0f, 0xdb, 0xae, 0x72, + 0x46, 0x40, 0xb5, 0x7d, 0xae, 0x20, 0x61, 0xa0, 0xe5, 0x9e, 0xac, 0xcd, 0x47, 0xbe, 0xd2, 0xe6, 0xed, 0xfc, 0xfc, + 0xef, 0xbc, 0xe5, 0xa1, 0x83, 0xba, 0xff, 0x8a, 0xc5, 0x55, 0xfe, 0x4e, 0x46, 0x91, 0xed, 0xc3, 0x76, 0xf3, 0x6e, + 0x24, 0xc4, 0x05, 0xa7, 0xfc, 0x07, 0x9f, 0xbf, 0x94, 0x2e, 0xbc, 0xde, 0xc5, 0xa0, 0xf4, 0x11, 0x6a, 0xdc, 0x98, + 0xdb, 0x22, 0x91, 0xeb, 0x4a, 0x20, 0xf2, 0xd8, 0xc1, 0xa8, 0xe7, 0xb5, 0x4b, 0x6e, 0x00, 0xa3, 0x6e, 0xc7, 0xc3, + 0x03, 0x6d, 0x4a, 0x7f, 0x32, 0xe1, 0x46, 0x0b, 0x55, 0xc4, 0x1d, 0xa3, 0xe6, 0x03, 0x45, 0xe2, 0x15, 0x06, 0x08, + 0xd0, 0xad, 0xcf, 0xa3, 0xe8, 0x6d, 0x9a, 0xf7, 0x43, 0xb1, 0x9d, 0xa6, 0x2c, 0x50, 0xc0, 0x78, 0x32, 0x47, 0xb4, + 0xec, 0x89, 0x7d, 0xba, 0x3b, 0x1d, 0x56, 0x46, 0x6f, 0x71, 0x6d, 0xea, 0x72, 0xaf, 0xaf, 0xda, 0xce, 0xd6, 0x09, + 0xf7, 0x34, 0x6c, 0xe3, 0x0a, 0x12, 0x36, 0x72, 0x2a, 0x7a, 0xae, 0xe8, 0x6b, 0x3a, 0x2b, 0xe1, 0x1a, 0xf3, 0x2d, + 0x02, 0x60, 0x4d, 0x06, 0xf9, 0x4b, 0x31, 0x3d, 0x43, 0x45, 0xde, 0xb3, 0x39, 0x7b, 0x27, 0xd3, 0x29, 0x7b, 0x6b, + 0x48, 0x29, 0x17, 0x98, 0xcf, 0x1e, 0x10, 0xa6, 0x79, 0xe8, 0x6d, 0x24, 0xc9, 0xcc, 0xd3, 0x96, 0xbc, 0xa9, 0xee, + 0x69, 0x22, 0x78, 0x50, 0xca, 0xb3, 0xde, 0x4f, 0xde, 0x0d, 0xeb, 0x82, 0xf1, 0xbc, 0x23, 0x1c, 0x28, 0x3e, 0x97, + 0xbd, 0x09, 0xee, 0x3e, 0xcf, 0x7f, 0x34, 0x27, 0xdb, 0x5a, 0x1b, 0xe4, 0xe6, 0x27, 0x59, 0xbf, 0x90, 0xf3, 0x89, + 0x27, 0xbd, 0xfa, 0xf8, 0x93, 0x7e, 0x91, 0x08, 0x65, 0xd7, 0xa9, 0x09, 0xf6, 0x88, 0x3f, 0x4f, 0x30, 0x80, 0xcd, + 0x62, 0xb2, 0xa4, 0x1a, 0x2d, 0xab, 0x28, 0x6f, 0xe9, 0xb4, 0x99, 0xe2, 0x97, 0xda, 0xd3, 0x69, 0xac, 0xf0, 0x56, + 0x0b, 0xcf, 0xd8, 0x6e, 0xc1, 0xda, 0x66, 0xda, 0x92, 0x25, 0xa7, 0x74, 0xed, 0x83, 0x1d, 0x7f, 0x58, 0x03, 0xa8, + 0x22, 0xca, 0x95, 0xf4, 0xb2, 0x12, 0x7f, 0xe0, 0xb3, 0x5d, 0x84, 0x57, 0x03, 0xaf, 0xaa, 0x99, 0xa7, 0x5a, 0x3d, + 0xb0, 0xdd, 0xf4, 0x69, 0x6f, 0x25, 0x3b, 0xde, 0x51, 0x9c, 0xf0, 0x2a, 0xa1, 0xe3, 0x5c, 0xb6, 0xd0, 0xf5, 0xd3, + 0x5d, 0x58, 0xd8, 0xf7, 0x5f, 0xa0, 0x47, 0x0e, 0x26, 0x6e, 0xe7, 0x67, 0xf6, 0x0a, 0x5a, 0x07, 0x8a, 0x6c, 0x0f, + 0xaf, 0x3b, 0x2b, 0x2c, 0xc2, 0x08, 0x29, 0xff, 0xa5, 0xe1, 0x2d, 0xda, 0xbd, 0x2a, 0x2d, 0xc1, 0xf8, 0xec, 0x5d, + 0xd5, 0xd8, 0xb6, 0x03, 0x65, 0x3a, 0x5b, 0x47, 0xca, 0x05, 0xed, 0x80, 0x91, 0x82, 0xd3, 0x9d, 0x55, 0xdf, 0xff, + 0x3a, 0x99, 0x6a, 0x75, 0x8f, 0xed, 0x70, 0x26, 0xba, 0x53, 0x8c, 0x03, 0x68, 0x09, 0x85, 0xac, 0xad, 0x4e, 0xfd, + 0x7b, 0x9f, 0xad, 0xd7, 0xbc, 0x63, 0x5a, 0xac, 0x34, 0x2f, 0x78, 0x42, 0x6b, 0x1b, 0x9e, 0xb4, 0x18, 0xf7, 0x56, + 0x29, 0x27, 0x42, 0x82, 0x86, 0x6e, 0x39, 0x1f, 0xe4, 0x15, 0x1e, 0xd4, 0x40, 0x25, 0xb8, 0x36, 0x0e, 0xa1, 0x0e, + 0xad, 0x2d, 0xeb, 0xdd, 0x95, 0x18, 0xb7, 0xc0, 0xb5, 0xec, 0xc6, 0xd9, 0x1d, 0xce, 0xad, 0xc3, 0x46, 0xab, 0x91, + 0xdd, 0xe8, 0x0f, 0x43, 0x0f, 0x22, 0x85, 0x9b, 0x1d, 0x4d, 0xb7, 0x1d, 0x46, 0x7b, 0x0e, 0x9d, 0x17, 0x6d, 0x8c, + 0x89, 0x30, 0x33, 0x69, 0x33, 0xdf, 0xc5, 0xe5, 0x4c, 0x1b, 0x96, 0xf2, 0x01, 0x5a, 0x03, 0x08, 0x88, 0xb2, 0x50, + 0xd1, 0x2e, 0x72, 0x9a, 0xed, 0x42, 0x6d, 0xb8, 0xa1, 0x44, 0x2c, 0x82, 0x40, 0xde, 0x40, 0xc8, 0x9f, 0x6a, 0x17, + 0x7e, 0x4d, 0xb0, 0x51, 0x30, 0x83, 0x39, 0xd1, 0x50, 0x63, 0x42, 0x90, 0x3e, 0xb5, 0x52, 0x96, 0x3e, 0xe4, 0x8c, + 0x84, 0xd0, 0x82, 0x1a, 0x55, 0xcb, 0x23, 0x72, 0x9b, 0x6e, 0xe6, 0xf0, 0xb9, 0xa8, 0x38, 0x2a, 0xbd, 0x74, 0x9b, + 0x79, 0x06, 0x1f, 0x75, 0x18, 0x7b, 0x2e, 0xc0, 0x38, 0xd8, 0x39, 0x09, 0xe0, 0x2f, 0xe2, 0x7f, 0x0d, 0xc0, 0x13, + 0x2c, 0x2a, 0xd3, 0x5a, 0x57, 0x6f, 0x60, 0xca, 0x29, 0x8a, 0xd9, 0xf2, 0x14, 0xbd, 0x89, 0xbd, 0xd6, 0xbe, 0x0c, + 0xa4, 0xc4, 0x47, 0x16, 0x3a, 0x7a, 0xeb, 0xc9, 0x4e, 0xcf, 0x40, 0x64, 0xfc, 0x6a, 0xec, 0xfd, 0x71, 0x73, 0xb5, + 0x1b, 0x86, 0xf8, 0x16, 0x05, 0xec, 0xcc, 0x7b, 0xe7, 0xf8, 0xe4, 0xb3, 0x38, 0x4c, 0xe8, 0xcd, 0x41, 0x68, 0x5c, + 0xcf, 0x42, 0xc9, 0xf8, 0xc8, 0xcb, 0x85, 0xfb, 0xb2, 0x0d, 0xb6, 0x33, 0x3e, 0xf9, 0xf4, 0xd0, 0x07, 0x82, 0x87, + 0x4c, 0x49, 0x50, 0x73, 0xa0, 0xbb, 0x36, 0x8d, 0x80, 0xa5, 0x37, 0x79, 0xa1, 0x99, 0xd7, 0xc1, 0xb2, 0x67, 0x28, + 0x40, 0x08, 0x70, 0x20, 0x47, 0xa0, 0x68, 0x7a, 0x37, 0x1a, 0x70, 0x11, 0x7c, 0x58, 0xe4, 0x1c, 0xfe, 0x37, 0x0d, + 0xf7, 0x5d, 0xee, 0xf9, 0xeb, 0x5c, 0x0c, 0x3e, 0xb5, 0x43, 0xdf, 0xb7, 0x03, 0xe1, 0xca, 0xef, 0x78, 0x11, 0x7c, + 0x72, 0x89, 0x90, 0xae, 0x0d, 0x5e, 0x63, 0xe2, 0xdd, 0x8d, 0x90, 0xfb, 0x50, 0x78, 0xb9, 0xc4, 0x03, 0xe6, 0xda, + 0xf4, 0xc6, 0x9c, 0xf9, 0xad, 0xe8, 0x4d, 0x33, 0x47, 0x07, 0xa3, 0x23, 0xbb, 0x1f, 0x61, 0x6d, 0xe7, 0x5f, 0xfa, + 0x57, 0x60, 0x8d, 0xee, 0x67, 0x91, 0x7c, 0x3a, 0xde, 0x56, 0x00, 0x4b, 0x83, 0x0f, 0x64, 0x38, 0xaf, 0x63, 0x0c, + 0x6b, 0xe8, 0x3e, 0xea, 0x7e, 0x25, 0xc0, 0x86, 0x30, 0x0e, 0x95, 0x81, 0xa9, 0x37, 0x30, 0x45, 0xee, 0xff, 0xb3, + 0x8a, 0xfa, 0xb8, 0x61, 0x62, 0x2e, 0x87, 0x34, 0x00, 0x12, 0x0a, 0x7e, 0xee, 0x1e, 0x13, 0xad, 0xd8, 0x43, 0x46, + 0x6b, 0x94, 0x89, 0x47, 0xb2, 0xc9, 0xaf, 0x7a, 0x77, 0xa4, 0xac, 0x0f, 0x7c, 0x2f, 0x9b, 0xbc, 0x4f, 0x98, 0x7b, + 0xce, 0xdf, 0x69, 0x03, 0xa8, 0x5c, 0x8a, 0xb3, 0x8a, 0x7a, 0x09, 0x58, 0x13, 0x39, 0x7e, 0x5a, 0x98, 0x0c, 0x37, + 0x6a, 0x7e, 0x93, 0x45, 0xe0, 0x1e, 0x90, 0xa6, 0xd0, 0x2c, 0x28, 0x57, 0xc8, 0x22, 0xf9, 0x90, 0x9c, 0x3e, 0x20, + 0xd6, 0x85, 0xbc, 0x0d, 0xb5, 0xc5, 0x32, 0x12, 0x93, 0x7b, 0x89, 0x89, 0x57, 0xde, 0x32, 0xb6, 0xc4, 0x58, 0xb4, + 0xa6, 0xec, 0x52, 0x88, 0xbc, 0x51, 0x65, 0xd8, 0xd4, 0x65, 0x06, 0x13, 0xa5, 0x75, 0x3f, 0x3c, 0xc6, 0x51, 0x95, + 0x9e, 0x49, 0x8f, 0x80, 0xad, 0x70, 0xb6, 0x98, 0xd4, 0x55, 0x90, 0xc0, 0xf9, 0x40, 0x78, 0x28, 0x1f, 0x88, 0x15, + 0xaa, 0xb8, 0xf8, 0x13, 0x0e, 0x27, 0xd0, 0x2d, 0xc9, 0x2d, 0xab, 0x8e, 0xeb, 0x78, 0x9f, 0x43, 0x8e, 0x22, 0x51, + 0x02, 0x6d, 0xf0, 0x3b, 0x15, 0xd2, 0x43, 0x06, 0x0b, 0x50, 0x0e, 0x03, 0x3a, 0x3c, 0x18, 0x25, 0xa6, 0xe0, 0xf0, + 0xf0, 0x20, 0x12, 0x79, 0x59, 0xc8, 0x9f, 0x0e, 0xce, 0x3a, 0x54, 0x7d, 0x65, 0xf0, 0xdf, 0xc1, 0xb5, 0x45, 0x28, + 0x4e, 0x4c, 0xac, 0x63, 0x14, 0x1c, 0xdc, 0xba, 0x4d, 0x65, 0xc3, 0x9f, 0x7a, 0x7f, 0xad, 0xf0, 0x68, 0xe9, 0xc1, + 0xea, 0xbc, 0xad, 0x02, 0x9e, 0x0d, 0x4a, 0x8f, 0x35, 0x4f, 0xac, 0x7d, 0xc5, 0xc9, 0x81, 0x04, 0xa6, 0x49, 0x6f, + 0x6b, 0xcb, 0xf8, 0x05, 0xf1, 0xcb, 0x3d, 0x0b, 0x2f, 0xfc, 0x76, 0xd4, 0x12, 0x8b, 0xf5, 0xa9, 0x14, 0x7b, 0x2d, + 0x0d, 0x37, 0xd2, 0x06, 0x59, 0xbf, 0xd3, 0x3a, 0xcf, 0x8d, 0x45, 0x7a, 0x63, 0xff, 0x48, 0xc4, 0xdb, 0x19, 0xea, + 0x53, 0x28, 0xb1, 0x9e, 0x41, 0xf4, 0x6a, 0x48, 0x7d, 0xd1, 0x1a, 0x91, 0xa2, 0x70, 0xd9, 0xea, 0xf2, 0x22, 0x66, + 0x60, 0x8c, 0x68, 0xf5, 0x8a, 0x2d, 0x25, 0x86, 0xf7, 0x42, 0xa4, 0x56, 0xe9, 0xa9, 0xee, 0x8a, 0x62, 0xd3, 0x25, + 0x65, 0xd3, 0x46, 0x68, 0x2b, 0x0a, 0xec, 0x20, 0x94, 0xa2, 0x40, 0x2b, 0xe3, 0xb0, 0x87, 0x7a, 0x8b, 0xcc, 0x68, + 0xa3, 0x14, 0x36, 0xf3, 0x34, 0x02, 0xb8, 0xb9, 0x55, 0x13, 0x69, 0x17, 0x25, 0xce, 0x65, 0xb4, 0x4c, 0xb2, 0xde, + 0xb2, 0x52, 0xb8, 0x2f, 0x64, 0x38, 0x31, 0x3a, 0x36, 0xc0, 0x97, 0xc7, 0xff, 0xef, 0x0f, 0x60, 0xcd, 0xd2, 0x61, + 0x48, 0x5e, 0x43, 0x75, 0x84, 0xd0, 0x8c, 0x3d, 0xea, 0x72, 0x80, 0x22, 0x75, 0x6d, 0xa9, 0x65, 0x6e, 0x47, 0x39, + 0xc6, 0x85, 0x2b, 0xcf, 0xdb, 0xc5, 0x82, 0x0e, 0x0b, 0x23, 0x3e, 0xcc, 0x37, 0x18, 0x4b, 0xae, 0x14, 0xdd, 0x32, + 0x19, 0x81, 0x49, 0x75, 0xc5, 0x0b, 0xe7, 0x0b, 0x5e, 0xc9, 0xf4, 0x07, 0xf9, 0x48, 0x4e, 0xa5, 0x31, 0x1b, 0xab, + 0x0d, 0xa1, 0x26, 0x82, 0x36, 0x4f, 0x4b, 0xa4, 0xdb, 0x2e, 0x4d, 0x2c, 0x50, 0x18, 0x96, 0x46, 0xe8, 0xaa, 0x49, + 0x58, 0xf3, 0xb3, 0xab, 0x05, 0x89, 0x87, 0x49, 0x57, 0xcd, 0x55, 0x70, 0x6e, 0xed, 0xb1, 0xd3, 0x47, 0x7a, 0x2c, + 0x82, 0x56, 0xb3, 0x0b, 0xa5, 0x35, 0x68, 0xcd, 0x2d, 0xb3, 0x36, 0x6c, 0xc0, 0x2b, 0xe7, 0x32, 0xc5, 0x19, 0x35, + 0xbc, 0xb1, 0x31, 0x84, 0xc9, 0x4f, 0xc5, 0x79, 0xf2, 0x7f, 0x66, 0x0b, 0x97, 0xa6, 0x6e, 0xdd, 0x14, 0x57, 0x1c, + 0x48, 0x31, 0x1f, 0xc4, 0xc3, 0x79, 0x11, 0xc9, 0x9b, 0xeb, 0x5e, 0x46, 0x9c, 0x0e, 0xf4, 0x82, 0xac, 0x62, 0x87, + 0xbe, 0x93, 0x1f, 0xf5, 0xa8, 0xc4, 0x19, 0x8c, 0x65, 0x03, 0xb1, 0x04, 0x82, 0xf8, 0xae, 0x7d, 0x88, 0xe4, 0xc6, + 0xa5, 0x5a, 0x97, 0x07, 0xb2, 0xe5, 0x45, 0x90, 0x78, 0xe7, 0xee, 0x5e, 0x33, 0xc6, 0x4b, 0x7c, 0x42, 0x3e, 0x5e, + 0x10, 0xbc, 0x72, 0x0b, 0xe4, 0x0e, 0xd7, 0xc1, 0x03, 0xf1, 0x51, 0x82, 0x17, 0x23, 0x89, 0x7b, 0xa9, 0x43, 0x85, + 0xa0, 0x45, 0x4f, 0x30, 0x22, 0x91, 0x7c, 0xb5, 0xb6, 0x2e, 0x88, 0x02, 0x4d, 0xb0, 0x5e, 0x3c, 0x8a, 0x9a, 0x56, + 0x9f, 0xa0, 0xcc, 0x08, 0xb9, 0x63, 0xab, 0x83, 0x1e, 0xdf, 0xe7, 0xa1, 0x60, 0xf6, 0xae, 0x49, 0x84, 0xfb, 0x5d, + 0x56, 0xb7, 0x3b, 0x20, 0x19, 0xfe, 0xa4, 0x55, 0xf7, 0x72, 0x0a, 0x69, 0x48, 0x43, 0x59, 0x7c, 0xf0, 0x56, 0x09, + 0x4e, 0x1e, 0xb2, 0xac, 0x4f, 0x8b, 0x31, 0x23, 0x25, 0x05, 0x25, 0x86, 0xe5, 0x52, 0x49, 0xd9, 0xe1, 0x10, 0x5b, + 0x62, 0x2f, 0xba, 0x3e, 0xfc, 0xbe, 0xa5, 0x0f, 0x00, 0x0f, 0xe5, 0x66, 0xfa, 0xda, 0x42, 0x54, 0xc0, 0xd0, 0xcc, + 0x7e, 0xca, 0xa7, 0xf5, 0xec, 0x7f, 0x3f, 0x60, 0x1f, 0x33, 0xf6, 0x9b, 0xc7, 0x38, 0xe0, 0xa7, 0x3c, 0xb4, 0x7c, + 0x8d, 0x8a, 0xee, 0x71, 0x5a, 0xcd, 0x7d, 0x69, 0x86, 0x18, 0x38, 0x09, 0x1e, 0xee, 0x72, 0x48, 0x83, 0xfc, 0xb3, + 0x35, 0x24, 0x9b, 0x60, 0x69, 0x2c, 0xb0, 0x42, 0xd6, 0x7c, 0xba, 0x0b, 0x2e, 0xb6, 0x92, 0x82, 0x27, 0x35, 0xb0, + 0xca, 0xf5, 0x26, 0xe6, 0xdc, 0xa4, 0x66, 0x77, 0x04, 0x12, 0xc8, 0x26, 0xb3, 0xbd, 0xa4, 0xe4, 0xaf, 0x89, 0x29, + 0xe9, 0xf7, 0x8d, 0x84, 0x08, 0x80, 0x95, 0x3e, 0x21, 0xba, 0xe0, 0xab, 0x58, 0x93, 0x4c, 0x3a, 0x96, 0x1a, 0xd5, + 0x56, 0x0a, 0xe8, 0x7a, 0xe1, 0x9f, 0xbd, 0xb9, 0x19, 0xcd, 0xa6, 0xe4, 0x4e, 0xe5, 0x0d, 0xf9, 0x14, 0xfc, 0xb5, + 0x19, 0x6d, 0xad, 0x86, 0x89, 0xa1, 0x8f, 0x01, 0xb4, 0xf7, 0x07, 0x78, 0xe1, 0xd1, 0x0a, 0x4b, 0x0a, 0x74, 0x8a, + 0x85, 0xce, 0x4b, 0x98, 0x7b, 0x58, 0x70, 0x54, 0xf2, 0xdd, 0x3b, 0xcc, 0xe3, 0xfa, 0xd6, 0x11, 0x24, 0x65, 0x3b, + 0xd3, 0xe9, 0x52, 0x2b, 0x12, 0xd0, 0xeb, 0x8c, 0x55, 0x22, 0xae, 0x49, 0x4e, 0x6e, 0xf8, 0xca, 0xc8, 0x68, 0x11, + 0x63, 0x1c, 0x53, 0x41, 0x1f, 0x2f, 0xbd, 0xcd, 0x0b, 0xc3, 0xbb, 0x3d, 0xa6, 0x95, 0x1e, 0x39, 0xc0, 0x55, 0xc2, + 0x4c, 0x19, 0xb4, 0x89, 0x78, 0xdc, 0x0f, 0x10, 0x05, 0x62, 0xa1, 0xd3, 0xc8, 0x51, 0x6a, 0xec, 0xfe, 0x88, 0xbd, + 0x80, 0x32, 0xaf, 0x99, 0x41, 0xd1, 0xf0, 0x5b, 0xfd, 0x95, 0xff, 0x8f, 0x1f, 0x67, 0x5e, 0xed, 0x47, 0x6f, 0x52, + 0x56, 0x9a, 0x03, 0xd5, 0xc8, 0x01, 0x77, 0x8f, 0xdb, 0x3b, 0xd7, 0x10, 0x61, 0x78, 0x2e, 0xab, 0xf1, 0x4e, 0x0f, + 0xed, 0xf6, 0x39, 0xfc, 0x9c, 0xdd, 0xae, 0xf9, 0xdd, 0xef, 0xfe, 0x44, 0x1e, 0x74, 0x0d, 0x17, 0x11, 0x1d, 0x30, + 0x5e, 0x5e, 0x6d, 0xd0, 0x9c, 0x67, 0xf9, 0x01, 0xec, 0x3d, 0xbe, 0x35, 0x52, 0x7d, 0xaa, 0x78, 0x85, 0x08, 0xc8, + 0x5b, 0xa5, 0xba, 0x4a, 0xc4, 0xbe, 0xc0, 0x66, 0x91, 0x01, 0x7d, 0xd6, 0xa1, 0x6b, 0xb5, 0x53, 0xc4, 0xcb, 0xcb, + 0x39, 0xe1, 0x87, 0x9b, 0x4e, 0x40, 0x93, 0xdc, 0x79, 0xcb, 0x3b, 0x5b, 0xe2, 0xac, 0xa7, 0x8c, 0x76, 0x9d, 0x5c, + 0x35, 0x0a, 0x48, 0x3b, 0x26, 0x22, 0xd3, 0xd6, 0xdc, 0x76, 0xed, 0xf8, 0x4a, 0xa1, 0xdf, 0xe1, 0xd5, 0xe5, 0x86, + 0x47, 0x43, 0x39, 0xa9, 0x36, 0xc9, 0xab, 0x2d, 0x9b, 0xc9, 0x49, 0x3f, 0xda, 0xda, 0x43, 0xf0, 0xd1, 0x0d, 0x1f, + 0x67, 0xca, 0x7e, 0xa7, 0x61, 0x9f, 0x67, 0xad, 0xfd, 0x55, 0xc2, 0x70, 0x2f, 0x9f, 0xa4, 0x09, 0xda, 0x38, 0xa7, + 0x54, 0x62, 0x0e, 0x78, 0x89, 0xde, 0xf2, 0x20, 0x6c, 0xa6, 0x29, 0xd5, 0xab, 0xca, 0xe5, 0x66, 0x4a, 0xe4, 0x9c, + 0xe8, 0xb1, 0xdb, 0x2c, 0x6e, 0x8a, 0x6b, 0xb0, 0x33, 0x03, 0x26, 0xa1, 0xb5, 0xef, 0xb6, 0x23, 0x3b, 0x38, 0xb7, + 0xfd, 0x61, 0xfc, 0x17, 0x98, 0x27, 0xf2, 0x7c, 0x8e, 0x15, 0x1b, 0xaf, 0xe7, 0xef, 0xfe, 0x1e, 0x03, 0xf6, 0xf9, + 0x98, 0x0d, 0x79, 0xe9, 0xed, 0xc7, 0xd1, 0x3c, 0xee, 0xc7, 0xc3, 0xc0, 0x37, 0x0c, 0x65, 0x38, 0xe0, 0xd1, 0x32, + 0xdd, 0xe9, 0x30, 0xb5, 0x19, 0xd9, 0x13, 0xea, 0xee, 0x9c, 0xb9, 0xe1, 0xe3, 0x4f, 0x22, 0x6c, 0x86, 0xb3, 0x75, + 0x19, 0x24, 0xfa, 0x0a, 0x01, 0xc5, 0x38, 0x8d, 0x18, 0xd7, 0x3b, 0x9f, 0x36, 0xa1, 0xb6, 0x95, 0xa4, 0x67, 0xb7, + 0x40, 0x4d, 0x80, 0xaa, 0x94, 0x2f, 0xd7, 0x45, 0x34, 0x34, 0xf3, 0x24, 0x94, 0x5e, 0xee, 0xe9, 0x73, 0xb4, 0x63, + 0x03, 0x7b, 0x39, 0xa7, 0xa1, 0x94, 0xf4, 0xb2, 0xab, 0x06, 0x37, 0xb0, 0x95, 0xa8, 0xf1, 0x22, 0xe2, 0xdd, 0x66, + 0x0f, 0x25, 0x03, 0xcb, 0x53, 0x12, 0x73, 0xc0, 0xb4, 0x9b, 0x14, 0x55, 0xf6, 0x0c, 0xab, 0x21, 0x98, 0xc7, 0xdd, + 0x7e, 0x66, 0x87, 0xd7, 0x52, 0x54, 0xcd, 0x2d, 0xb6, 0x00, 0x6b, 0x8b, 0x14, 0xe2, 0x70, 0x44, 0x49, 0xd3, 0x11, + 0xe9, 0xc8, 0xf8, 0x93, 0xa6, 0x44, 0x02, 0x10, 0x1d, 0xfe, 0x33, 0xcd, 0xf4, 0x50, 0xf4, 0xdf, 0x8b, 0x57, 0x6b, + 0x73, 0xaf, 0x5d, 0x30, 0x72, 0x9a, 0x7f, 0x38, 0x1d, 0x6f, 0xfa, 0xb9, 0xb5, 0x8f, 0x33, 0xd7, 0xab, 0x5b, 0x1b, + 0x73, 0xbd, 0xb0, 0xe7, 0xfe, 0x49, 0x24, 0xcf, 0x0a, 0x94, 0x6f, 0x47, 0x60, 0x54, 0x41, 0xb8, 0x97, 0x01, 0x76, + 0xbf, 0x17, 0xae, 0xff, 0x5f, 0xe5, 0x9d, 0x1f, 0xe4, 0xf7, 0xff, 0xb6, 0x86, 0xff, 0xcb, 0x6e, 0xba, 0xda, 0x60, + 0xff, 0x5b, 0x03, 0x94, 0xdf, 0x66, 0xa9, 0x1d, 0x48, 0xff, 0xd6, 0x09, 0xe1, 0x22, 0x4e, 0x27, 0x77, 0x02, 0x2b, + 0x3d, 0x4d, 0xce, 0xc1, 0xc0, 0x03, 0xfb, 0xff, 0x59, 0x0e, 0x40, 0x2f, 0xe0, 0x8b, 0x27, 0xd9, 0xb6, 0x9f, 0xe1, + 0x05, 0xb8, 0x53, 0xa2, 0x8c, 0x70, 0xc8, 0xeb, 0xca, 0xaf, 0xf8, 0xfa, 0x39, 0x24, 0x78, 0x75, 0x0a, 0xe6, 0xa7, + 0x93, 0x50, 0x59, 0x9e, 0x20, 0xee, 0xbb, 0x78, 0xb2, 0xd5, 0xa5, 0x84, 0x0f, 0x54, 0xeb, 0x43, 0x97, 0xe2, 0x23, + 0x7e, 0x47, 0xdd, 0x48, 0xe2, 0x27, 0xda, 0x3f, 0x6a, 0xf3, 0x91, 0xa7, 0x76, 0x41, 0xbc, 0x37, 0xb9, 0xf5, 0x17, + 0x11, 0xce, 0x3d, 0x21, 0xa9, 0x35, 0x09, 0x55, 0xe7, 0x24, 0x71, 0xc4, 0xd9, 0x1d, 0xda, 0x6a, 0x98, 0x93, 0xf0, + 0x9f, 0xaa, 0x2f, 0xb5, 0x4e, 0xae, 0x03, 0x11, 0x4d, 0xef, 0xb1, 0xd3, 0x65, 0x10, 0xa0, 0x06, 0xeb, 0xb3, 0xbc, + 0xa5, 0xdf, 0xf9, 0x1c, 0x9f, 0xaf, 0x26, 0xba, 0xb3, 0xa1, 0x7b, 0x34, 0xf2, 0x65, 0xfc, 0xf6, 0x21, 0x24, 0xd5, + 0xa4, 0x86, 0x1c, 0x4c, 0x24, 0x3a, 0xe7, 0xeb, 0xf4, 0x8b, 0xa8, 0xee, 0x5b, 0x0b, 0x8e, 0xb5, 0x39, 0xeb, 0x20, + 0x63, 0x98, 0x31, 0x18, 0x56, 0xd0, 0x00, 0x16, 0x63, 0x1c, 0x32, 0xef, 0xe8, 0x6e, 0x3f, 0x5a, 0xdb, 0xff, 0xfb, + 0x3c, 0x33, 0x20, 0xed, 0xf9, 0xc0, 0x5b, 0xd5, 0x47, 0xe1, 0x90, 0xb6, 0xef, 0xe9, 0xc1, 0xbe, 0x45, 0xa4, 0x17, + 0x31, 0xfd, 0x1a, 0xde, 0x9a, 0xc7, 0xcf, 0x47, 0x45, 0x69, 0x51, 0x47, 0x65, 0xf1, 0xc2, 0x1d, 0x1a, 0xf7, 0xd7, + 0xf0, 0xd9, 0x98, 0x77, 0x67, 0x83, 0x00, 0x32, 0x26, 0x5a, 0xc7, 0x6b, 0xb1, 0xff, 0xc5, 0x73, 0x3a, 0x0f, 0xe6, + 0xdb, 0x83, 0x63, 0x15, 0xb1, 0xf9, 0xd8, 0x4a, 0x2d, 0xd1, 0x37, 0x59, 0x9c, 0x6d, 0x21, 0x74, 0x65, 0x3b, 0x78, + 0xf6, 0xa4, 0x26, 0xaa, 0xce, 0x4e, 0xc8, 0x7b, 0x6a, 0xf3, 0xa2, 0xcb, 0x36, 0x7b, 0xb0, 0x49, 0x1b, 0x43, 0xe3, + 0x29, 0x75, 0x95, 0x6d, 0x5b, 0x19, 0x5f, 0x9b, 0xee, 0xeb, 0xef, 0x5f, 0x62, 0x69, 0xed, 0x04, 0x1d, 0x0a, 0x67, + 0x33, 0x62, 0xa6, 0xe0, 0x07, 0x14, 0x48, 0xb8, 0x61, 0x28, 0x89, 0x37, 0xc1, 0xaf, 0xa3, 0x36, 0x99, 0x12, 0x4c, + 0xc3, 0x68, 0xf6, 0xfd, 0x6b, 0x0f, 0x37, 0x3b, 0x7a, 0x11, 0x50, 0xe7, 0x8f, 0xac, 0xdb, 0x70, 0x32, 0x24, 0x84, + 0x8b, 0xbb, 0x75, 0x72, 0x0b, 0x3a, 0x26, 0xf2, 0x88, 0x23, 0x69, 0xc9, 0xdd, 0x79, 0xff, 0x88, 0x65, 0x3f, 0x5b, + 0xff, 0x89, 0x77, 0xb5, 0xa9, 0xec, 0x85, 0x92, 0x4d, 0xed, 0x67, 0xe8, 0x58, 0x94, 0x00, 0x4a, 0xa8, 0xbc, 0xb3, + 0x36, 0x67, 0x8f, 0xc6, 0xaa, 0xca, 0xe8, 0xb7, 0xbc, 0xae, 0x66, 0xc5, 0x82, 0xc7, 0xdd, 0xe2, 0x38, 0x8e, 0x8f, + 0xd5, 0x43, 0xdb, 0xfb, 0x15, 0x32, 0x95, 0xef, 0xf0, 0xb9, 0x7a, 0x23, 0x9f, 0x36, 0x16, 0xc9, 0xab, 0x87, 0x87, + 0x2c, 0xe4, 0xf3, 0xba, 0x39, 0x3a, 0xd1, 0xe4, 0x72, 0x8c, 0x4a, 0x16, 0x6b, 0xf9, 0x10, 0x69, 0x3b, 0x8b, 0x9d, + 0x44, 0x2f, 0xa5, 0x55, 0x67, 0x2c, 0x2c, 0x05, 0xdc, 0x97, 0x51, 0xb9, 0x42, 0x5d, 0x4d, 0x4a, 0x1d, 0x06, 0x72, + 0x1d, 0xa8, 0x0a, 0x36, 0xb4, 0x78, 0x64, 0x66, 0x05, 0xbf, 0xf0, 0xe9, 0x11, 0x11, 0x0c, 0x6c, 0x7b, 0x81, 0x8f, + 0xa7, 0xa9, 0xc5, 0xdc, 0xe0, 0x0b, 0x55, 0xc6, 0x3b, 0x5f, 0xf2, 0x39, 0x3a, 0x6b, 0x54, 0x48, 0x16, 0x43, 0x8e, + 0x46, 0x71, 0x8b, 0x56, 0xd2, 0xfe, 0x4b, 0xf2, 0x3e, 0x73, 0x4a, 0x89, 0x96, 0x5a, 0x82, 0x02, 0xd2, 0x34, 0x4d, + 0x77, 0x4d, 0xe9, 0x7b, 0xf1, 0x68, 0x9e, 0xd6, 0x68, 0x9b, 0xdb, 0x59, 0x0a, 0x09, 0xa2, 0x9b, 0xa2, 0x13, 0x8d, + 0xf4, 0x62, 0x00, 0x52, 0xae, 0x1f, 0x7a, 0x23, 0x64, 0xef, 0x74, 0xa6, 0x96, 0xf0, 0xe0, 0x94, 0x03, 0x61, 0xe5, + 0x9d, 0x35, 0x76, 0x9a, 0x46, 0xd7, 0x4a, 0xf6, 0x8e, 0xdf, 0xca, 0xe9, 0xa6, 0x39, 0x88, 0xaf, 0xa1, 0x7d, 0xed, + 0x55, 0x0a, 0x6c, 0x71, 0xad, 0xb6, 0x36, 0x17, 0xca, 0xba, 0xf4, 0x41, 0x8e, 0xdc, 0x2c, 0x30, 0x36, 0xe9, 0xad, + 0x73, 0xd9, 0xbb, 0x2e, 0x4a, 0x65, 0x0b, 0xbf, 0x56, 0xa5, 0x3d, 0xc1, 0x8a, 0x81, 0xe0, 0x38, 0x7e, 0x55, 0x10, + 0xcb, 0x6a, 0x54, 0xdb, 0xf1, 0x12, 0x2f, 0x0e, 0x8c, 0x55, 0xa8, 0xe7, 0xe8, 0x9d, 0x77, 0x84, 0x1a, 0xac, 0x27, + 0xa9, 0x50, 0xb2, 0xc9, 0x2c, 0x50, 0xac, 0xe2, 0x2e, 0x07, 0xf6, 0x4b, 0x50, 0x06, 0xe0, 0x7f, 0x32, 0x55, 0x76, + 0x7f, 0xaa, 0x39, 0x39, 0xb7, 0x4c, 0xed, 0x97, 0x92, 0x5c, 0xf3, 0xf3, 0xcc, 0xfa, 0x69, 0x30, 0xca, 0x68, 0x06, + 0x98, 0x97, 0xea, 0x5a, 0x76, 0x9e, 0xce, 0x14, 0xd7, 0xe0, 0x0f, 0x26, 0x49, 0x4f, 0xfb, 0xcf, 0x43, 0x0e, 0x7d, + 0x76, 0xea, 0xf9, 0xbd, 0x43, 0xce, 0x54, 0x7e, 0xfb, 0x69, 0x1e, 0x3c, 0xfd, 0xe3, 0x13, 0xfe, 0xfa, 0xf1, 0x5f, + 0xfa, 0x14, 0x9d, 0xe0, 0xcf, 0xd9, 0x4b, 0xe8, 0xa3, 0xda, 0x25, 0xdc, 0x8f, 0x56, 0xed, 0x01, 0x1a, 0x7d, 0x76, + 0xc1, 0x92, 0x57, 0x17, 0x8c, 0x03, 0x4a, 0xb5, 0x66, 0x2c, 0xb7, 0xfa, 0x9e, 0xb8, 0x7e, 0xb2, 0xd9, 0x2b, 0x5d, + 0x1a, 0xb8, 0x35, 0xb6, 0x9f, 0x97, 0x55, 0x0b, 0xd7, 0xbd, 0x32, 0xc9, 0xeb, 0xf7, 0x67, 0xd8, 0x13, 0xff, 0x3b, + 0x04, 0xc8, 0x0f, 0x08, 0x3c, 0x5a, 0x8d, 0x4b, 0x5f, 0xaa, 0x61, 0xa9, 0xaa, 0xe6, 0xa5, 0xa2, 0x5a, 0x96, 0x16, + 0xd5, 0xed, 0xe1, 0xe7, 0x27, 0x7e, 0xcf, 0x63, 0x5d, 0x98, 0x77, 0x25, 0xc8, 0xd9, 0xa6, 0x97, 0xa1, 0x92, 0x1b, + 0xee, 0x0a, 0x76, 0x2b, 0x85, 0x1f, 0xed, 0xe2, 0xd3, 0xbb, 0x1b, 0xf0, 0x56, 0x09, 0x7a, 0x35, 0xd3, 0x1c, 0x4f, + 0xd0, 0x2d, 0x26, 0x11, 0x20, 0x66, 0xa5, 0xa3, 0xbd, 0x0f, 0x1d, 0x0a, 0xca, 0x83, 0xec, 0x5a, 0x73, 0x8b, 0xfb, + 0x09, 0x26, 0xd4, 0xdf, 0x30, 0x01, 0x25, 0x63, 0x41, 0x54, 0x23, 0xa1, 0x46, 0x13, 0xde, 0x8a, 0x44, 0x00, 0xc4, + 0xfb, 0xa5, 0x4e, 0x72, 0x2f, 0x97, 0xa9, 0x50, 0x9d, 0x7b, 0x0b, 0x20, 0xf5, 0x54, 0x53, 0x5a, 0xea, 0x8b, 0x1a, + 0x06, 0xa9, 0xb8, 0xa6, 0x8c, 0x54, 0x09, 0x57, 0x7d, 0xc0, 0xfa, 0x86, 0xc5, 0xbc, 0xa2, 0x97, 0xac, 0x0d, 0x97, + 0xff, 0xd3, 0xfc, 0xe5, 0x98, 0x2d, 0xe4, 0x65, 0x27, 0x64, 0x8e, 0x65, 0x59, 0x8f, 0xac, 0x52, 0x8d, 0x97, 0xd6, + 0xe7, 0xb1, 0x97, 0xbf, 0xac, 0x05, 0xa2, 0x10, 0xd1, 0xe7, 0x75, 0x8c, 0xaa, 0x5c, 0x85, 0xbd, 0x0a, 0x64, 0x19, + 0x42, 0x6e, 0xd2, 0x50, 0x5a, 0x6f, 0x11, 0x8b, 0x16, 0x4b, 0x3c, 0x7d, 0x3f, 0xc8, 0xad, 0x19, 0x04, 0x6f, 0x03, + 0x88, 0x03, 0xba, 0xad, 0x4b, 0x2e, 0xf8, 0xff, 0xa8, 0x7f, 0x7a, 0x79, 0xf6, 0x3f, 0xa5, 0xba, 0x32, 0x22, 0xcf, + 0xd0, 0x77, 0x9a, 0x3c, 0x01, 0x0a, 0x62, 0xb0, 0x43, 0x34, 0x90, 0xf7, 0x53, 0xdf, 0xa1, 0x47, 0x20, 0x3c, 0x0e, + 0x05, 0x67, 0x30, 0x34, 0x55, 0x78, 0xa3, 0x41, 0x66, 0x3c, 0x1c, 0x3a, 0x11, 0x32, 0x34, 0x51, 0xe7, 0x74, 0x28, + 0x4b, 0x75, 0x25, 0xb3, 0xe6, 0x5f, 0x57, 0x31, 0x06, 0xfb, 0xf1, 0x72, 0xe5, 0xcb, 0x07, 0xed, 0x7e, 0xcf, 0xfe, + 0x64, 0x2e, 0x4c, 0xd1, 0x3b, 0xa9, 0x5b, 0x63, 0xd6, 0x1c, 0xf1, 0xc0, 0xb0, 0x3c, 0x8c, 0x1e, 0xf5, 0x84, 0xd8, + 0x6c, 0x87, 0x1e, 0x37, 0xed, 0x9b, 0x2c, 0xc3, 0x3c, 0xdc, 0x1f, 0x14, 0x76, 0x3f, 0x66, 0xde, 0xe5, 0xae, 0xc7, + 0x05, 0xbb, 0x3d, 0x1c, 0xd4, 0xaf, 0x41, 0xc1, 0x7f, 0xe4, 0x1d, 0x6b, 0x7b, 0x8c, 0xad, 0x47, 0x5e, 0x78, 0x9b, + 0x32, 0x5d, 0xd1, 0xca, 0x11, 0x0b, 0x27, 0x26, 0xd4, 0x18, 0x24, 0x31, 0x5c, 0xe5, 0x99, 0x7b, 0x0f, 0x41, 0x9c, + 0x71, 0x4e, 0x44, 0x7e, 0x22, 0x5b, 0x64, 0x7c, 0x5e, 0x7a, 0x6d, 0xb6, 0x6b, 0x42, 0x39, 0x46, 0xa8, 0x1c, 0x08, + 0xde, 0x05, 0x95, 0x43, 0xfb, 0xf1, 0xea, 0xa3, 0xcc, 0x16, 0xf5, 0x4f, 0xaf, 0x0c, 0xab, 0xe2, 0x2b, 0x7d, 0xdc, + 0xaa, 0x7f, 0x76, 0x74, 0x00, 0xaa, 0x7f, 0x40, 0xfa, 0x3d, 0xa5, 0xbc, 0x2e, 0x24, 0x1f, 0x99, 0x44, 0x73, 0xb3, + 0xa5, 0xc5, 0xba, 0x0b, 0x4b, 0x6d, 0x25, 0x8b, 0x43, 0x9d, 0xb7, 0x86, 0xd7, 0xb5, 0x6f, 0x4d, 0x8f, 0x0e, 0xf5, + 0x8b, 0xd4, 0xd6, 0xe7, 0xbf, 0xc3, 0x7d, 0xfd, 0x86, 0x51, 0xad, 0xb6, 0xc6, 0xa5, 0x27, 0xe9, 0xd3, 0x62, 0x51, + 0xd1, 0xd0, 0xc5, 0x3e, 0xfd, 0x2e, 0x1a, 0x1a, 0xe8, 0xd8, 0xb3, 0xb6, 0x5e, 0x69, 0x9c, 0xee, 0x0b, 0x74, 0xd0, + 0x69, 0x39, 0x42, 0xd2, 0xbd, 0x61, 0x60, 0x10, 0xa0, 0x98, 0xc1, 0x26, 0xc4, 0x74, 0xcb, 0xcf, 0x4e, 0xa3, 0x99, + 0xbb, 0x13, 0x6e, 0x7f, 0xb1, 0x3e, 0x01, 0xd5, 0x2f, 0xf3, 0x77, 0xaa, 0x68, 0x3e, 0xe2, 0x8f, 0x78, 0xd0, 0x86, + 0x44, 0xbe, 0x0e, 0x89, 0xf5, 0xb4, 0x31, 0x96, 0x6e, 0x88, 0xd8, 0xae, 0xab, 0x27, 0x0f, 0x2b, 0xaf, 0x6d, 0x34, + 0x75, 0xf9, 0x95, 0x6d, 0x5b, 0xfa, 0xbc, 0xf2, 0x80, 0x81, 0xe3, 0xae, 0x87, 0x0e, 0x7c, 0x25, 0xc9, 0xd8, 0x82, + 0xf7, 0x4a, 0xe2, 0x7f, 0x89, 0xfd, 0x3b, 0x39, 0x62, 0x9b, 0x1a, 0xa8, 0x59, 0xea, 0xee, 0x04, 0x9b, 0x35, 0xb5, + 0x90, 0x34, 0x47, 0x8f, 0x69, 0xf5, 0xd3, 0xf2, 0x98, 0xef, 0x76, 0x1e, 0x5b, 0x3f, 0xfb, 0x28, 0x0b, 0x2a, 0x4c, + 0xcf, 0xd8, 0x21, 0x70, 0xc6, 0xb0, 0xa8, 0x8c, 0x45, 0x99, 0xdc, 0xdb, 0x94, 0x13, 0x69, 0xb2, 0x7c, 0x1f, 0x7e, + 0xe7, 0x82, 0x0a, 0xe8, 0x35, 0x3e, 0x8f, 0xee, 0x50, 0x7e, 0x5c, 0xf6, 0x06, 0x3c, 0x3d, 0x48, 0x99, 0xea, 0x0e, + 0x3a, 0xa5, 0xe9, 0xd3, 0xbc, 0xfe, 0xb8, 0x1f, 0xfd, 0x84, 0xeb, 0x1f, 0xff, 0x93, 0x4c, 0x8f, 0x5f, 0x43, 0x32, + 0x4c, 0x82, 0xd3, 0x14, 0x76, 0xb5, 0xf2, 0xff, 0xdd, 0x32, 0xf5, 0x4a, 0x5c, 0x0c, 0x6f, 0xea, 0xf8, 0x01, 0x51, + 0x34, 0xeb, 0x23, 0xcb, 0x98, 0x4f, 0xdb, 0xf2, 0xc3, 0xb6, 0x54, 0x87, 0xb8, 0xc8, 0x9d, 0xcb, 0x92, 0xd8, 0x35, + 0x28, 0xd3, 0x1a, 0x29, 0xed, 0x33, 0xe6, 0xb0, 0x37, 0x93, 0x76, 0x2f, 0x2d, 0x6d, 0x29, 0xa4, 0xe0, 0x68, 0x8a, + 0x33, 0x1a, 0xc0, 0x7d, 0xac, 0x49, 0xdf, 0xda, 0x35, 0x7a, 0x3e, 0x1e, 0xcb, 0x4a, 0xae, 0x24, 0x9d, 0xcb, 0x52, + 0x0e, 0x1f, 0x71, 0x2b, 0xf7, 0x11, 0x23, 0x20, 0xe6, 0xc5, 0xaa, 0xd2, 0x02, 0x33, 0x44, 0x0d, 0x2e, 0x95, 0x8e, + 0xb1, 0x54, 0x06, 0x13, 0xb5, 0xbe, 0xbc, 0xa0, 0x5d, 0xbe, 0x81, 0x03, 0xa9, 0x3b, 0xef, 0x61, 0x75, 0x62, 0xa9, + 0xd0, 0xe5, 0xd0, 0xde, 0x96, 0xf4, 0xc4, 0xe5, 0x7c, 0x24, 0x90, 0xc6, 0x02, 0x54, 0x78, 0x6c, 0x5f, 0xe2, 0xcf, + 0x22, 0xf2, 0x47, 0x61, 0xf3, 0x22, 0xce, 0x06, 0x9a, 0x82, 0x56, 0x50, 0x8d, 0x69, 0xf4, 0x5f, 0x56, 0x09, 0x41, + 0x4a, 0xc1, 0x56, 0xd4, 0x1c, 0xf0, 0x0c, 0xd9, 0x38, 0x89, 0x44, 0x60, 0x87, 0xe9, 0xe0, 0x42, 0xdb, 0x2f, 0x64, + 0x89, 0xd6, 0x4f, 0x23, 0x63, 0x0f, 0x49, 0x78, 0xf8, 0x72, 0x99, 0xe8, 0x95, 0x38, 0x13, 0x6f, 0xe9, 0x5b, 0x0b, + 0xfe, 0x79, 0x5d, 0x0b, 0xf6, 0xd9, 0x20, 0x7b, 0x89, 0x8f, 0x3c, 0x0c, 0xf1, 0x74, 0x85, 0xdb, 0xee, 0x41, 0xe5, + 0x5e, 0x12, 0x0f, 0x6b, 0x7b, 0x7b, 0x70, 0xbe, 0xb3, 0xf6, 0xb4, 0x56, 0xad, 0x0f, 0x94, 0x6b, 0x4c, 0xfb, 0xe1, + 0xf5, 0x97, 0xf7, 0xad, 0x29, 0x95, 0x7e, 0x14, 0xba, 0x99, 0x84, 0xb1, 0xf2, 0x6c, 0xef, 0x4c, 0xf6, 0x61, 0x48, + 0x4f, 0xf5, 0x80, 0xd3, 0x8e, 0x12, 0xb7, 0x64, 0x35, 0x1e, 0x65, 0x6f, 0x12, 0xf4, 0xa9, 0xac, 0x68, 0x20, 0xa2, + 0x9a, 0x7f, 0x3f, 0x19, 0x0b, 0xcc, 0x0c, 0xc4, 0xe0, 0xe3, 0xb9, 0x6d, 0xc9, 0x2c, 0xe0, 0x7e, 0xcc, 0xdf, 0x36, + 0xd1, 0xa4, 0x1d, 0x3b, 0x08, 0x87, 0x51, 0x30, 0xef, 0xd5, 0x5b, 0xc2, 0xfd, 0x50, 0xca, 0xcf, 0xc0, 0xcf, 0x8e, + 0x81, 0x13, 0x9c, 0x15, 0xf1, 0x32, 0xb4, 0xdf, 0x10, 0xce, 0xc8, 0x44, 0xf0, 0xa3, 0xe2, 0xee, 0x00, 0xdb, 0x4d, + 0x73, 0xb8, 0xc7, 0x3f, 0x3d, 0x1b, 0x70, 0x27, 0x29, 0x7d, 0xc9, 0x24, 0x07, 0xef, 0x56, 0x19, 0x92, 0x2d, 0x15, + 0x39, 0xd9, 0xc4, 0x72, 0xda, 0x53, 0x8e, 0x70, 0x7b, 0xa7, 0x4b, 0xbf, 0xa7, 0x3c, 0x3a, 0xef, 0xc5, 0xa5, 0xde, + 0x43, 0x3c, 0x7a, 0xea, 0x6d, 0x83, 0xb6, 0xcd, 0xd2, 0xd2, 0x9c, 0x94, 0x2e, 0x75, 0xa6, 0x6b, 0x97, 0x89, 0xd1, + 0x95, 0x2f, 0x9a, 0x77, 0xc8, 0x15, 0x86, 0x28, 0x3d, 0x75, 0x60, 0xb3, 0xda, 0xa7, 0x44, 0x89, 0xd4, 0x61, 0x95, + 0x48, 0x7a, 0x14, 0x29, 0xc4, 0x27, 0x67, 0x89, 0xa0, 0xf7, 0x69, 0x6c, 0x01, 0xa5, 0x65, 0x35, 0x79, 0x14, 0xbd, + 0x62, 0xde, 0x8b, 0xdb, 0xd8, 0x29, 0x34, 0x8b, 0x4d, 0x36, 0x9b, 0xc9, 0xde, 0x4b, 0xff, 0xf5, 0xdf, 0xb9, 0xae, + 0xa0, 0xdf, 0x8f, 0xe9, 0x12, 0xff, 0x7a, 0x0d, 0xf0, 0x5e, 0x8d, 0x82, 0xe8, 0x61, 0x8a, 0xba, 0x2b, 0xe6, 0x80, + 0x2e, 0x84, 0xf0, 0x55, 0xa4, 0xab, 0x1a, 0x79, 0xba, 0x54, 0xfc, 0x49, 0xb2, 0xdb, 0x08, 0x9b, 0x3a, 0x6d, 0x4b, + 0x06, 0x68, 0x5f, 0x81, 0xeb, 0x24, 0xeb, 0x35, 0x8a, 0xc8, 0x1d, 0x14, 0xfd, 0x27, 0x7f, 0xd6, 0xc4, 0xcf, 0x16, + 0xf1, 0x63, 0x98, 0xf2, 0xb1, 0x4f, 0x32, 0xc6, 0x20, 0xe6, 0x14, 0x72, 0x13, 0x88, 0x77, 0x63, 0xc2, 0x96, 0x3c, + 0x83, 0x46, 0xbf, 0x37, 0x4d, 0x29, 0x55, 0x59, 0x2f, 0xab, 0xb6, 0x64, 0xd7, 0x8e, 0x5b, 0x7b, 0x16, 0xd3, 0xfc, + 0x18, 0x58, 0x8d, 0xdf, 0x8b, 0x14, 0xaf, 0x1c, 0x15, 0x76, 0xb7, 0xb8, 0x2a, 0x8e, 0x21, 0x78, 0xfd, 0xf8, 0xf3, + 0x20, 0x70, 0x22, 0x3b, 0xdd, 0x5b, 0x02, 0xe5, 0xbb, 0x6b, 0xe3, 0xf4, 0x37, 0xf9, 0xea, 0xf7, 0x7d, 0x74, 0x8f, + 0xfa, 0x33, 0xa6, 0xce, 0x5e, 0x25, 0x9c, 0x6e, 0x11, 0xfd, 0xcf, 0xa1, 0x2d, 0x2f, 0xb7, 0xe6, 0x8e, 0xaa, 0x70, + 0x9f, 0x18, 0xdf, 0x7b, 0x52, 0x26, 0xa3, 0x3d, 0xf8, 0xdb, 0x9d, 0x7a, 0xfe, 0xc7, 0x84, 0x23, 0x08, 0x6f, 0xba, + 0xf1, 0x41, 0xbf, 0xa7, 0x74, 0xfc, 0x34, 0x2f, 0x9f, 0xfe, 0xe1, 0x09, 0x97, 0x3f, 0xfe, 0x27, 0x39, 0xf6, 0x8e, + 0xb9, 0x34, 0xef, 0x80, 0xdd, 0x7d, 0x16, 0xf1, 0x74, 0xf2, 0x5a, 0x2e, 0x91, 0x3f, 0x55, 0x3d, 0x5e, 0x09, 0x2f, + 0x0f, 0x76, 0x02, 0x16, 0x68, 0x11, 0x79, 0xcf, 0xe6, 0x25, 0x68, 0xc1, 0x90, 0x1d, 0xc5, 0xd1, 0xc4, 0x9b, 0x01, + 0xa6, 0x42, 0x6a, 0x35, 0x88, 0x0e, 0xcc, 0x77, 0xdf, 0xc9, 0x7c, 0x20, 0xcc, 0x1a, 0x26, 0x54, 0x71, 0x27, 0xde, + 0xa5, 0x1e, 0x49, 0x4a, 0x75, 0x55, 0xef, 0x45, 0xa2, 0xcc, 0x7e, 0x40, 0x7a, 0xcc, 0x02, 0x63, 0x26, 0x42, 0x03, + 0xf0, 0x0c, 0x01, 0x91, 0xc3, 0x48, 0x4e, 0x92, 0xbe, 0xd5, 0x81, 0x11, 0xef, 0x38, 0x4d, 0x95, 0xaf, 0x04, 0x90, + 0x9f, 0x65, 0xe5, 0xf1, 0xdd, 0x5d, 0x9a, 0xd9, 0x70, 0x47, 0xe7, 0x5b, 0xef, 0x82, 0x6f, 0x68, 0xd2, 0x55, 0xb9, + 0xa7, 0x02, 0xc2, 0xc6, 0xd5, 0x25, 0x64, 0xc4, 0x39, 0xe4, 0x50, 0xa6, 0x60, 0x07, 0x52, 0x89, 0x75, 0xe8, 0xc9, + 0xc0, 0x1f, 0xbd, 0x2e, 0x01, 0x11, 0x4b, 0x29, 0x79, 0x92, 0xb3, 0xdd, 0x18, 0x8e, 0x4d, 0xe4, 0xe2, 0x3d, 0xa9, + 0x7b, 0x6f, 0x70, 0xbc, 0x86, 0x2a, 0x89, 0x54, 0x6b, 0x21, 0xad, 0x4a, 0xba, 0xef, 0x6c, 0x0f, 0x37, 0x9c, 0xfc, + 0x63, 0x6d, 0xe4, 0x8f, 0x4c, 0xee, 0xf1, 0x9e, 0x31, 0x69, 0x1e, 0x70, 0x96, 0xcd, 0xa2, 0x00, 0x46, 0x99, 0x6a, + 0x97, 0x9c, 0x75, 0x94, 0x4b, 0x2d, 0x4a, 0x5a, 0x06, 0xbe, 0x42, 0x91, 0xe4, 0xe6, 0x37, 0x7a, 0xbd, 0xe9, 0x7b, + 0x34, 0x97, 0x10, 0xe8, 0x95, 0x7e, 0xce, 0xd7, 0x7b, 0xba, 0x7a, 0xdf, 0x55, 0xb6, 0xb3, 0x0b, 0x56, 0x69, 0xac, + 0xf7, 0x86, 0x5b, 0x01, 0xc8, 0x02, 0xb1, 0xce, 0x0d, 0xcb, 0xed, 0xbe, 0x47, 0xd4, 0xeb, 0x33, 0x9f, 0xd8, 0x13, + 0x19, 0x51, 0xba, 0x45, 0x24, 0xba, 0x20, 0xe2, 0xff, 0x3f, 0xf7, 0x69, 0x2c, 0x26, 0xb7, 0xad, 0x91, 0x2a, 0xbf, + 0x6e, 0x9d, 0xe5, 0xc5, 0xfe, 0x2d, 0xd7, 0x15, 0x82, 0x62, 0x64, 0x06, 0x32, 0x45, 0xd3, 0x34, 0xbb, 0x0f, 0x93, + 0x19, 0x5b, 0x22, 0x34, 0xa2, 0x4c, 0x4a, 0xcb, 0x35, 0xd2, 0x42, 0x42, 0x2b, 0x07, 0x90, 0x61, 0x52, 0xda, 0x85, + 0x16, 0xd7, 0x3a, 0x24, 0x83, 0xe7, 0xb3, 0x49, 0x8f, 0xa7, 0x84, 0x24, 0x70, 0x73, 0xad, 0x22, 0xc2, 0x1c, 0xd5, + 0x16, 0x84, 0xf0, 0x63, 0x7f, 0x01, 0x3a, 0x61, 0x52, 0x03, 0xdf, 0x68, 0xf1, 0x2e, 0x08, 0x02, 0xb4, 0x78, 0x42, + 0x72, 0x0c, 0x0e, 0x40, 0x6a, 0xc9, 0x4a, 0x7f, 0x90, 0xa4, 0xeb, 0xb0, 0x3f, 0x1f, 0x33, 0x6e, 0xce, 0xa7, 0x9d, + 0xe9, 0xc9, 0x04, 0xe8, 0xd5, 0x07, 0x0e, 0xc3, 0x76, 0xc7, 0xc0, 0xf0, 0x28, 0xe8, 0xd3, 0x44, 0xf7, 0x7b, 0xb8, + 0xe9, 0xb2, 0xdd, 0x97, 0x43, 0x4c, 0x04, 0x8b, 0x99, 0xec, 0x66, 0x1c, 0xe1, 0xec, 0x86, 0x8d, 0xf6, 0x48, 0xb5, + 0xc6, 0x7e, 0x1f, 0x94, 0x2a, 0x36, 0x34, 0xdd, 0x49, 0xcf, 0x2c, 0xc3, 0xec, 0x16, 0x9a, 0xac, 0x2a, 0x03, 0x4e, + 0xa2, 0x02, 0x9c, 0x48, 0x61, 0xdb, 0xe8, 0xd8, 0xf0, 0xa6, 0x28, 0x81, 0xe6, 0xa1, 0x25, 0x46, 0x9f, 0x02, 0xef, + 0x52, 0x52, 0xf1, 0x8b, 0xd5, 0x98, 0x4a, 0xb2, 0xa1, 0x49, 0x8a, 0xcc, 0x72, 0x7c, 0xba, 0x8b, 0xdc, 0xb0, 0x3c, + 0x61, 0x3a, 0xb5, 0x66, 0x59, 0x91, 0x49, 0xd1, 0xfd, 0x7f, 0xf5, 0xe4, 0x90, 0x90, 0x56, 0xd5, 0xdc, 0x4d, 0x95, + 0x72, 0xf8, 0x8c, 0x5b, 0xc9, 0x04, 0xae, 0x89, 0x2f, 0xf4, 0x6c, 0x67, 0xdf, 0x80, 0xee, 0x94, 0x1a, 0x14, 0x77, + 0x21, 0x07, 0x85, 0x19, 0x35, 0xd8, 0xfb, 0x0b, 0xa2, 0xc7, 0xa3, 0xe4, 0xa6, 0xf1, 0x77, 0x0e, 0x57, 0xa8, 0x7a, + 0x23, 0xe9, 0xb4, 0x7f, 0xe0, 0x22, 0x70, 0x54, 0xa7, 0xc6, 0x98, 0x77, 0x37, 0x5a, 0xb7, 0x17, 0x55, 0xdc, 0x21, + 0x03, 0xec, 0x6b, 0x79, 0xd7, 0x02, 0x6b, 0xaf, 0x78, 0xd3, 0x48, 0x6e, 0x91, 0x8f, 0xff, 0xda, 0x67, 0xb7, 0xc5, + 0x2d, 0x5a, 0x64, 0x6a, 0xbb, 0x3c, 0x58, 0xf4, 0x65, 0x1b, 0x36, 0xa3, 0xd3, 0xb3, 0xbf, 0xb9, 0x90, 0xcd, 0x67, + 0x06, 0xb5, 0xc3, 0x4f, 0x1f, 0x4f, 0x5d, 0x1c, 0x38, 0x45, 0x2c, 0xf1, 0x10, 0x4e, 0xda, 0x56, 0xab, 0xcb, 0x14, + 0xbd, 0xec, 0xbe, 0x05, 0x92, 0x60, 0x16, 0xe7, 0x53, 0x0f, 0x5f, 0x88, 0x57, 0x28, 0x38, 0x6c, 0x1f, 0xf6, 0x57, + 0x71, 0x24, 0x6f, 0xfd, 0x53, 0xbd, 0x71, 0xd0, 0xf2, 0xab, 0x9c, 0xbb, 0x97, 0xeb, 0x77, 0x5d, 0x9b, 0xf2, 0x2a, + 0xee, 0xd7, 0xad, 0x7f, 0xda, 0x10, 0xa5, 0x62, 0x4f, 0x26, 0x3d, 0x9f, 0x9b, 0xe5, 0xc7, 0xef, 0x57, 0x26, 0x94, + 0x2f, 0x46, 0x18, 0x50, 0xab, 0x1f, 0xc2, 0x4c, 0x47, 0x8a, 0x6f, 0x92, 0x9a, 0xb2, 0x06, 0xad, 0x50, 0x4c, 0x59, + 0x6d, 0xe2, 0x7c, 0xe8, 0xa0, 0xd9, 0x48, 0x87, 0xc3, 0x6e, 0x49, 0xac, 0xf5, 0xd3, 0x54, 0x4f, 0x23, 0x70, 0x08, + 0x82, 0xf3, 0x83, 0x4a, 0x2d, 0x39, 0xc6, 0x73, 0x6e, 0xd5, 0x33, 0x64, 0x31, 0xa2, 0xca, 0x64, 0xcc, 0xe4, 0xe6, + 0x0d, 0x15, 0x46, 0x95, 0x79, 0xe8, 0x00, 0x0a, 0x47, 0x32, 0xdb, 0x71, 0xe3, 0x8b, 0xc7, 0x4c, 0x53, 0xd5, 0x0b, + 0x22, 0xbe, 0x7f, 0x5d, 0xe7, 0x8e, 0x84, 0x0e, 0xa4, 0xee, 0x1d, 0x91, 0xa9, 0x55, 0x9b, 0x8c, 0x0e, 0x68, 0xe8, + 0x3a, 0x8a, 0xcc, 0x8f, 0x55, 0x55, 0x91, 0x4d, 0xd5, 0xae, 0x4c, 0x46, 0x91, 0x43, 0xac, 0x3b, 0x4a, 0x59, 0x4e, + 0x96, 0xb5, 0xd1, 0xb5, 0x89, 0xc8, 0x6a, 0xb7, 0x25, 0x91, 0x6a, 0x3f, 0x48, 0x83, 0xd3, 0xd0, 0x7b, 0x0a, 0xb0, + 0xf9, 0xd4, 0x92, 0xa4, 0x5d, 0x4b, 0xd1, 0xf0, 0xb1, 0xf3, 0xd2, 0x5d, 0x77, 0x17, 0x96, 0x23, 0x84, 0x71, 0x4a, + 0x70, 0x0a, 0x2a, 0x2d, 0xe8, 0x18, 0x84, 0x37, 0x62, 0xba, 0x68, 0xf7, 0x00, 0xe0, 0xd9, 0xb9, 0xcc, 0x5e, 0x01, + 0x40, 0xca, 0xac, 0x02, 0x4d, 0xf3, 0xc7, 0x8d, 0x38, 0x94, 0x39, 0xd9, 0x91, 0x6a, 0x8a, 0x98, 0x14, 0xdf, 0x13, + 0x0d, 0x75, 0x82, 0xec, 0xc7, 0x94, 0x46, 0xfc, 0x41, 0x1e, 0x6c, 0xcb, 0xce, 0xb9, 0xdd, 0x98, 0x22, 0xc7, 0xc4, + 0x93, 0xa1, 0x15, 0xb9, 0x41, 0x3c, 0xe9, 0x7b, 0x7c, 0xad, 0xba, 0x70, 0xe5, 0xc1, 0xec, 0xf2, 0xe2, 0xfd, 0x31, + 0xff, 0x77, 0x1b, 0x85, 0xda, 0xe4, 0x61, 0xc5, 0x9f, 0x02, 0xb2, 0x3b, 0xa4, 0xcb, 0x63, 0x73, 0x89, 0x7f, 0xe5, + 0xc2, 0x0f, 0x9b, 0xd0, 0x61, 0x17, 0xd3, 0x69, 0x46, 0x2f, 0x83, 0x14, 0x84, 0x3d, 0x0b, 0x9f, 0x96, 0x4c, 0xe3, + 0x26, 0xc9, 0x24, 0xad, 0x7f, 0xb7, 0x29, 0xad, 0x69, 0xa4, 0xc6, 0x51, 0x77, 0x83, 0xf2, 0x84, 0x9f, 0xdf, 0x45, + 0xcd, 0x8f, 0xbd, 0xdb, 0xa6, 0x20, 0x9a, 0x60, 0x15, 0x86, 0x88, 0x72, 0xfa, 0xcd, 0x12, 0x67, 0x6e, 0x09, 0x7b, + 0x48, 0x79, 0xb5, 0x8d, 0x35, 0x3e, 0xdd, 0xbc, 0x54, 0x5b, 0x1f, 0x74, 0x4f, 0x55, 0xf5, 0x37, 0xdb, 0x86, 0xa2, + 0xd1, 0x29, 0xe1, 0x15, 0x45, 0x23, 0x3b, 0xf5, 0xc3, 0x21, 0x5b, 0x8d, 0xa2, 0x10, 0x59, 0xcc, 0xe2, 0x87, 0x5d, + 0x2a, 0x02, 0x1a, 0x86, 0xd9, 0xfc, 0xd3, 0xec, 0x4a, 0x46, 0x9e, 0x44, 0xb3, 0x6f, 0x3d, 0x63, 0xdb, 0xae, 0xdf, + 0xda, 0x67, 0x76, 0xeb, 0x3d, 0x66, 0x6b, 0x67, 0x77, 0x28, 0xa4, 0x83, 0x18, 0xf7, 0x6b, 0xd7, 0x16, 0x73, 0xf5, + 0x34, 0x64, 0x95, 0x8f, 0x2b, 0x46, 0x38, 0xfc, 0x1a, 0xe8, 0xe2, 0x33, 0x66, 0x41, 0x68, 0xd7, 0x38, 0x6d, 0x1f, + 0x0e, 0xd0, 0x9a, 0x1e, 0xcc, 0xf4, 0x4c, 0x0f, 0xd0, 0x6e, 0x4e, 0x10, 0xa0, 0x81, 0x12, 0x4f, 0xf0, 0xbf, 0x92, + 0x38, 0x57, 0xd9, 0xed, 0xfc, 0x5a, 0x23, 0x2b, 0xae, 0x3f, 0xa4, 0x82, 0x3e, 0x8d, 0x36, 0x13, 0x3a, 0x77, 0x4b, + 0xc5, 0x3b, 0x50, 0x5c, 0x2b, 0xc3, 0xee, 0x26, 0xa0, 0xcd, 0x53, 0xf1, 0xfb, 0xaa, 0xff, 0x28, 0xa0, 0x86, 0x1e, + 0x9b, 0xa3, 0xc4, 0x3d, 0xdb, 0xaa, 0x62, 0x56, 0x19, 0xb4, 0x03, 0x06, 0x83, 0xbf, 0xb6, 0x9a, 0xd6, 0xc8, 0xe6, + 0xe9, 0xef, 0x22, 0x7a, 0x4d, 0xdd, 0x19, 0xb9, 0x5f, 0xc1, 0x75, 0x1f, 0x59, 0xab, 0x86, 0x4e, 0xda, 0x73, 0xa7, + 0x61, 0x1b, 0x79, 0x82, 0x09, 0x74, 0x50, 0xb1, 0xa9, 0xc1, 0x05, 0xfb, 0x48, 0xd1, 0xb2, 0x56, 0x83, 0x66, 0x51, + 0x27, 0x72, 0x97, 0x81, 0x0a, 0xf1, 0x6d, 0x52, 0x06, 0xcb, 0x32, 0xb4, 0x8a, 0x38, 0x1e, 0x65, 0x36, 0xb8, 0x02, + 0x53, 0xe0, 0xad, 0x34, 0x94, 0xcd, 0x9e, 0xe0, 0x89, 0xd2, 0x12, 0x4e, 0x7e, 0x78, 0xe2, 0x35, 0x6a, 0x09, 0x3e, + 0x87, 0xa6, 0xfd, 0x07, 0x69, 0x69, 0xe6, 0xfa, 0x93, 0x23, 0x3d, 0x78, 0x0e, 0x6f, 0xcd, 0x04, 0xbe, 0x4b, 0x3c, + 0x1d, 0xb9, 0xf6, 0xfc, 0x43, 0xe2, 0x81, 0x5d, 0x61, 0x22, 0x24, 0x21, 0x2c, 0x5c, 0x7b, 0xa7, 0xad, 0xc5, 0xff, + 0x70, 0x06, 0x8c, 0x11, 0x23, 0x6c, 0x07, 0x05, 0x4e, 0x1f, 0xb6, 0x51, 0x84, 0x30, 0x5f, 0x7e, 0xcd, 0x8e, 0x91, + 0xdc, 0x54, 0x5e, 0x5c, 0xc4, 0x18, 0xc1, 0x56, 0xce, 0x4a, 0xfc, 0x80, 0x88, 0x4c, 0xe6, 0x05, 0xc3, 0x36, 0xfc, + 0x1e, 0xdf, 0xf5, 0xdd, 0xc4, 0xf7, 0x80, 0xf5, 0x8c, 0x0f, 0xd5, 0x73, 0xdf, 0xcf, 0x91, 0x44, 0xeb, 0x69, 0xfb, + 0x83, 0x20, 0x58, 0x6c, 0xba, 0xb5, 0x33, 0xb5, 0x86, 0xfe, 0x41, 0x98, 0xe0, 0xf6, 0xbc, 0xa9, 0x28, 0x56, 0xe2, + 0xf2, 0xfa, 0x82, 0x37, 0x3c, 0x1e, 0x60, 0x9f, 0xde, 0x59, 0xbb, 0x7b, 0x73, 0x97, 0xde, 0x8d, 0x3b, 0xf1, 0xa4, + 0x7f, 0x47, 0x3d, 0xe4, 0x6b, 0x9e, 0x31, 0xa3, 0x5d, 0x95, 0x65, 0xbf, 0xa4, 0xdf, 0x39, 0xa7, 0x33, 0x1d, 0xc1, + 0x44, 0xfa, 0x1b, 0xf8, 0xfa, 0x58, 0x6c, 0x7f, 0x21, 0x39, 0x46, 0xd3, 0x05, 0x66, 0x8d, 0xd4, 0x0b, 0x0b, 0x6d, + 0xda, 0x17, 0xdd, 0x2d, 0x40, 0xc5, 0x02, 0x55, 0x78, 0xe0, 0xed, 0xc8, 0x1f, 0x71, 0xbb, 0xd2, 0x8b, 0x81, 0x65, + 0xf6, 0x8f, 0x9c, 0xfd, 0xc9, 0xeb, 0x50, 0x89, 0xbe, 0x88, 0xd6, 0x27, 0x94, 0xa9, 0xb0, 0x4b, 0x44, 0x39, 0x72, + 0x23, 0x8e, 0x3e, 0x1d, 0x3d, 0x89, 0x80, 0x0d, 0x52, 0x37, 0x22, 0xac, 0xb8, 0x27, 0x9f, 0x45, 0x69, 0x40, 0x2f, + 0x80, 0xd4, 0x0f, 0x67, 0x1c, 0xea, 0xfa, 0x37, 0x61, 0x26, 0x5a, 0x1c, 0xc6, 0x73, 0x5f, 0x66, 0x55, 0x68, 0xdd, + 0xf3, 0x28, 0x3e, 0x49, 0xe4, 0x7b, 0xf7, 0xd8, 0xe2, 0x48, 0x70, 0xe6, 0x9b, 0xa0, 0x17, 0xf2, 0xa4, 0xbf, 0x65, + 0x41, 0x74, 0xe7, 0x17, 0x52, 0xab, 0x12, 0xb9, 0xb9, 0xc0, 0xb1, 0x60, 0x99, 0x43, 0x0e, 0x7f, 0xd6, 0x9e, 0xa5, + 0xf5, 0x3b, 0x18, 0xd5, 0x30, 0x8f, 0xff, 0x5c, 0x7c, 0xca, 0x42, 0x91, 0xa9, 0x17, 0x8f, 0x3f, 0x45, 0x69, 0x10, + 0xdd, 0x9e, 0x44, 0x28, 0xb6, 0x91, 0xba, 0x44, 0x90, 0x28, 0x1c, 0x67, 0x6a, 0xdf, 0xdf, 0xe5, 0xd9, 0x70, 0x17, + 0xcd, 0x3f, 0x0d, 0xa0, 0x27, 0xbf, 0x4a, 0xeb, 0xef, 0x17, 0x7f, 0x4a, 0x8a, 0xe0, 0xf6, 0xac, 0x9f, 0xce, 0xfc, + 0xd8, 0x59, 0xe9, 0x62, 0x10, 0x3d, 0x82, 0xd5, 0xb8, 0xa2, 0x4a, 0x7e, 0x06, 0x3f, 0xb1, 0xfd, 0x61, 0xe1, 0x66, + 0xc4, 0xbf, 0x8f, 0x4f, 0xee, 0xe2, 0x7c, 0x3a, 0x57, 0x58, 0x75, 0x38, 0x03, 0xa2, 0x86, 0xd1, 0xa5, 0xea, 0x62, + 0xc7, 0x91, 0xf9, 0x97, 0x05, 0x6b, 0x3c, 0x8b, 0x04, 0xa6, 0xf3, 0x0f, 0x2f, 0x3f, 0x62, 0xe4, 0xc9, 0x62, 0xb2, + 0xbf, 0xf8, 0x42, 0x9d, 0x38, 0xb8, 0xa7, 0xdd, 0xd6, 0xaf, 0x44, 0xc9, 0xa7, 0xf9, 0xe3, 0xe3, 0xfe, 0xba, 0x9f, + 0xf0, 0xe3, 0xc7, 0xbf, 0xf4, 0x57, 0xd9, 0x9a, 0x67, 0xdf, 0x85, 0x33, 0xca, 0x61, 0xb7, 0x17, 0x31, 0x3b, 0xd9, + 0xbf, 0xd7, 0x1f, 0x5f, 0x63, 0x4f, 0xee, 0xef, 0x19, 0x3e, 0xfd, 0xf6, 0xf2, 0xfe, 0x5d, 0x78, 0xb7, 0x90, 0xcb, + 0x8c, 0xbd, 0x39, 0x37, 0xd7, 0xa5, 0xac, 0xa5, 0xd9, 0x7a, 0x91, 0x80, 0x24, 0x88, 0x89, 0x0d, 0x2a, 0xf0, 0x44, + 0x12, 0x2d, 0xcb, 0x20, 0x47, 0x30, 0xe4, 0xe4, 0x38, 0xec, 0xce, 0x79, 0xc6, 0x82, 0x54, 0x19, 0x51, 0x5e, 0xa2, + 0x38, 0xdb, 0x7a, 0xcc, 0x00, 0x9c, 0x81, 0xf7, 0x11, 0xc8, 0xef, 0x6a, 0x10, 0x07, 0x4d, 0x06, 0x69, 0xf0, 0xed, + 0xa7, 0xae, 0x77, 0x64, 0xc3, 0x75, 0x65, 0xbc, 0xde, 0xbb, 0x97, 0x89, 0x93, 0x7d, 0x09, 0x66, 0xe3, 0x1d, 0x4a, + 0x99, 0x29, 0xc2, 0xdb, 0xcc, 0x33, 0xe7, 0x21, 0x16, 0x8e, 0x47, 0x92, 0x39, 0x88, 0x3f, 0x2d, 0x5d, 0xc1, 0xe9, + 0x38, 0xc9, 0x21, 0x3e, 0x55, 0xc1, 0x17, 0x0c, 0xbd, 0xce, 0xe6, 0xd3, 0xca, 0x9c, 0x9c, 0xac, 0xda, 0x70, 0x05, + 0xbe, 0xbd, 0xf5, 0x39, 0xbe, 0x6a, 0x61, 0xf3, 0x03, 0xbf, 0x73, 0xe1, 0xc1, 0xf6, 0xf1, 0xf5, 0x6b, 0xbf, 0x68, + 0xc6, 0x62, 0x09, 0x6b, 0xff, 0x58, 0xfa, 0x82, 0x50, 0x78, 0x2a, 0x04, 0x10, 0xfa, 0x82, 0x1a, 0x58, 0xce, 0x21, + 0x33, 0x67, 0x86, 0x9e, 0xbf, 0x66, 0x89, 0x23, 0x5a, 0xb0, 0xf1, 0x6b, 0xc3, 0xc2, 0x02, 0x4b, 0xed, 0xe5, 0x0d, + 0x58, 0x89, 0x85, 0x3d, 0xc6, 0x99, 0xe9, 0x6c, 0x8e, 0x99, 0x13, 0xf0, 0xb6, 0x65, 0x66, 0xa2, 0x0a, 0x9c, 0xe5, + 0x07, 0x5a, 0x9f, 0xa0, 0x5a, 0xc9, 0xbf, 0xba, 0x30, 0xae, 0x68, 0x83, 0xb3, 0xb9, 0xb4, 0x35, 0x04, 0xae, 0x4a, + 0x9a, 0x7c, 0x4c, 0xd6, 0x71, 0x27, 0x07, 0x3f, 0x4b, 0x03, 0x3e, 0x6b, 0x7c, 0x16, 0xe2, 0xb2, 0x24, 0xef, 0xd1, + 0x9c, 0xf5, 0xa1, 0x73, 0xad, 0x0d, 0x16, 0x6e, 0xec, 0x87, 0x29, 0xf8, 0xf0, 0x9a, 0x6c, 0xb7, 0xb5, 0x0f, 0x70, + 0x9f, 0xe6, 0xcd, 0xc7, 0x1d, 0xf4, 0x84, 0x9b, 0x1f, 0xff, 0x13, 0xf6, 0xed, 0xf2, 0x83, 0x2a, 0x85, 0x29, 0xf8, + 0xb8, 0xec, 0x8b, 0x22, 0xb2, 0xfd, 0x1e, 0xfa, 0x1e, 0xf8, 0x71, 0xd0, 0x70, 0xa1, 0x5f, 0xba, 0xcb, 0x18, 0x8d, + 0xe7, 0x4e, 0xb0, 0xda, 0x43, 0xe3, 0xba, 0x1e, 0x8c, 0xaa, 0x6c, 0x83, 0x61, 0x8d, 0x90, 0xa0, 0xcb, 0x63, 0x2b, + 0xfb, 0x2c, 0xc8, 0x06, 0x63, 0x25, 0x7b, 0x40, 0x09, 0x7b, 0xd0, 0x96, 0xd3, 0x00, 0x2c, 0x24, 0x1f, 0x37, 0xed, + 0x10, 0x68, 0xc8, 0x6a, 0x30, 0xdc, 0xe7, 0xaf, 0x89, 0xae, 0x2c, 0xad, 0x03, 0xfd, 0x07, 0xf7, 0x3d, 0x9a, 0x29, + 0xe2, 0xbe, 0x3c, 0xab, 0x29, 0xcb, 0x9d, 0xf6, 0xc9, 0x52, 0x1e, 0x7b, 0x18, 0x9e, 0x67, 0x0a, 0x39, 0x9d, 0xd3, + 0xaf, 0xb3, 0x35, 0x0e, 0xd2, 0x4a, 0x79, 0xd2, 0xbe, 0x4e, 0x5b, 0x5f, 0xf6, 0x9d, 0x88, 0xd5, 0x09, 0xee, 0x6a, + 0xa8, 0xd5, 0x4b, 0xaf, 0x0d, 0x86, 0xd3, 0x41, 0xfb, 0x0d, 0xe8, 0x6e, 0x69, 0x7d, 0x3b, 0xa9, 0x96, 0x48, 0x9c, + 0x1e, 0xe2, 0x76, 0x30, 0x9b, 0xa1, 0xb0, 0xb3, 0xad, 0xae, 0x2e, 0x09, 0x1c, 0xa0, 0xa9, 0x15, 0xf8, 0x70, 0xb7, + 0x88, 0xd5, 0x54, 0x1e, 0xe2, 0x63, 0x20, 0x77, 0x08, 0x38, 0x2f, 0xab, 0x90, 0xf3, 0x91, 0x61, 0x2d, 0xd6, 0x34, + 0xc3, 0x01, 0x53, 0x52, 0x07, 0x35, 0xdc, 0x28, 0x6b, 0xac, 0x8a, 0x96, 0x29, 0xb6, 0x3a, 0xfc, 0xba, 0xfd, 0xf3, + 0x35, 0x42, 0x90, 0xf5, 0x9b, 0x1f, 0x0b, 0xa2, 0x93, 0x41, 0x76, 0x8f, 0x38, 0x3e, 0x47, 0xc7, 0x5e, 0xae, 0xd6, + 0x5d, 0x94, 0x76, 0x27, 0x9b, 0xa9, 0xf2, 0xf9, 0x08, 0xf4, 0x92, 0x63, 0x70, 0xd8, 0x0e, 0x92, 0xe1, 0xc7, 0xd0, + 0x91, 0x50, 0x97, 0x97, 0xd4, 0x9a, 0x75, 0xf8, 0x61, 0xcf, 0xab, 0x5e, 0xce, 0x62, 0x37, 0x3d, 0x03, 0x8c, 0x53, + 0x6e, 0x7a, 0x7b, 0xac, 0x06, 0x00, 0x5b, 0x28, 0xbe, 0x86, 0x7d, 0x48, 0xc0, 0x3b, 0x14, 0xfd, 0xc1, 0xce, 0xc3, + 0x70, 0x51, 0x5c, 0xaa, 0x2c, 0x1d, 0x3f, 0x4e, 0xa3, 0x3a, 0x40, 0xf0, 0xf7, 0x78, 0xc2, 0xca, 0xd2, 0x42, 0x0d, + 0xee, 0x5c, 0x9a, 0xb8, 0x50, 0x04, 0xe2, 0x10, 0xfb, 0x59, 0xab, 0xea, 0xfe, 0x7d, 0xed, 0x8a, 0x00, 0xd4, 0xbe, + 0xa4, 0x83, 0x7b, 0x61, 0x87, 0xf9, 0x01, 0x6b, 0x5d, 0x23, 0x7c, 0x5e, 0xab, 0x29, 0x33, 0x3c, 0x10, 0x7c, 0x09, + 0xcf, 0xd5, 0x41, 0x59, 0x1d, 0xe4, 0x18, 0x29, 0x20, 0x59, 0x41, 0x74, 0x49, 0x90, 0x12, 0x3d, 0x11, 0x9b, 0xd1, + 0x3a, 0x32, 0x15, 0xd8, 0xb8, 0xb1, 0xc0, 0x30, 0xec, 0x12, 0x08, 0xf6, 0xc0, 0xb2, 0xe6, 0xe4, 0x95, 0xfe, 0xc0, + 0x6f, 0x11, 0x35, 0xac, 0x43, 0x94, 0x10, 0x6a, 0x56, 0x53, 0x11, 0x08, 0xaf, 0x8a, 0x98, 0x27, 0x93, 0xc9, 0x09, + 0xf0, 0xae, 0x3d, 0x51, 0xf4, 0x74, 0x67, 0xc7, 0xa2, 0x32, 0xcf, 0x2e, 0x52, 0xe1, 0x2a, 0x03, 0xaa, 0xc5, 0x81, + 0x2b, 0x87, 0x45, 0x74, 0x55, 0x4a, 0xee, 0x81, 0xcd, 0x7c, 0x03, 0xe7, 0x3a, 0x0d, 0xda, 0xca, 0xb1, 0x43, 0xc3, + 0x15, 0x5e, 0x14, 0x14, 0x0e, 0x94, 0xb2, 0x3b, 0x45, 0x98, 0xe6, 0xd6, 0x53, 0x91, 0x05, 0x0e, 0x60, 0x01, 0xf7, + 0xe6, 0xee, 0x22, 0x03, 0xb6, 0x8f, 0x86, 0x70, 0x6a, 0x01, 0x7a, 0x6f, 0xf3, 0x9f, 0xba, 0xcc, 0x69, 0xf3, 0x5f, + 0xbe, 0xa1, 0x6e, 0xad, 0x99, 0x4c, 0x8b, 0x5e, 0x86, 0xe4, 0x9b, 0xde, 0xaa, 0xbf, 0x7b, 0x31, 0x83, 0xc1, 0x7b, + 0x92, 0xcb, 0xac, 0x4f, 0x02, 0x4e, 0xbd, 0x0d, 0x1f, 0xa8, 0x8f, 0xb6, 0xa1, 0x75, 0x08, 0x01, 0x16, 0x87, 0x30, + 0x76, 0x82, 0x3d, 0xfc, 0x8c, 0x98, 0x4b, 0x11, 0xc6, 0x6b, 0xec, 0x05, 0x5f, 0xba, 0xd6, 0x9b, 0x9b, 0x62, 0xcf, + 0xce, 0xab, 0x45, 0x08, 0xa5, 0xa7, 0x69, 0x12, 0x9f, 0x5d, 0xba, 0x5d, 0xc6, 0x73, 0xd0, 0x44, 0x46, 0xa1, 0x10, + 0x91, 0x3c, 0x17, 0x34, 0x2d, 0xb4, 0xbd, 0x03, 0xea, 0x18, 0x44, 0xa5, 0x80, 0xf5, 0xf0, 0xa0, 0xd0, 0xe2, 0xeb, + 0xa7, 0xd9, 0x33, 0xd4, 0x9f, 0xd8, 0x39, 0xe1, 0x5f, 0x1d, 0xf8, 0x29, 0x11, 0xfb, 0x2d, 0x5a, 0xe0, 0xdc, 0xfc, + 0x6a, 0x28, 0xc0, 0xfe, 0x88, 0x09, 0x7f, 0x85, 0x01, 0x8c, 0x8c, 0xe0, 0xff, 0xf2, 0x4b, 0x56, 0x54, 0x30, 0xcc, + 0x4b, 0xe1, 0x9d, 0xe2, 0x23, 0x14, 0xd0, 0xf3, 0x92, 0x26, 0x5b, 0xc0, 0x79, 0x4b, 0x4d, 0xd7, 0x05, 0x90, 0x31, + 0x06, 0x20, 0x10, 0x57, 0x9f, 0x30, 0xef, 0x56, 0xa3, 0x64, 0x6f, 0xd3, 0x6f, 0x06, 0x68, 0xc6, 0xcd, 0x88, 0xd9, + 0x64, 0x68, 0xc1, 0xd2, 0x71, 0x34, 0xc2, 0x4f, 0xa3, 0x58, 0xff, 0xfa, 0x54, 0x09, 0xa8, 0xa4, 0x7b, 0x01, 0x7f, + 0x9b, 0x96, 0x78, 0x4b, 0xe3, 0xfc, 0x5e, 0xe3, 0x5b, 0xb7, 0x6f, 0xfd, 0xf2, 0xf1, 0xc3, 0xd5, 0x42, 0x58, 0xad, + 0x4f, 0x3e, 0xa5, 0xad, 0x73, 0x83, 0xe8, 0x51, 0xa8, 0x71, 0x28, 0x84, 0x46, 0xf2, 0x38, 0xc9, 0xc8, 0x66, 0xb3, + 0xac, 0x77, 0x21, 0xff, 0xd8, 0xd5, 0x7b, 0xc9, 0x95, 0x0d, 0xf2, 0xee, 0x2e, 0x30, 0x3b, 0xbb, 0xb5, 0x25, 0x6b, + 0x9e, 0xca, 0xa1, 0x1b, 0x3c, 0x53, 0x2d, 0x1d, 0x29, 0x2c, 0xf0, 0x48, 0xcb, 0xd8, 0x99, 0x3d, 0xbf, 0x06, 0x34, + 0x15, 0xe7, 0x0a, 0xea, 0x9c, 0x05, 0xa5, 0x41, 0xc1, 0x9f, 0xf4, 0x46, 0xde, 0xec, 0xb0, 0xd8, 0xbd, 0x83, 0xac, + 0x8e, 0xff, 0x37, 0xd2, 0xa8, 0xee, 0x12, 0x1a, 0x85, 0x67, 0xd1, 0x5b, 0xab, 0x0a, 0xdd, 0x3b, 0xdc, 0x55, 0x72, + 0x50, 0xfb, 0xda, 0xa6, 0x18, 0xad, 0x61, 0xae, 0xd6, 0xbe, 0xde, 0x65, 0xda, 0xcb, 0x3b, 0xe2, 0x1f, 0x7e, 0xb2, + 0x39, 0x42, 0x08, 0x99, 0xec, 0x9e, 0xfa, 0x14, 0x00, 0xbe, 0x15, 0x00, 0xc4, 0x08, 0xbf, 0x60, 0xdd, 0xe0, 0x29, + 0x76, 0x8f, 0x67, 0xb7, 0xa5, 0x16, 0xee, 0x23, 0xc4, 0x58, 0x3b, 0xee, 0xd7, 0x12, 0x1e, 0x09, 0xfc, 0xb6, 0x75, + 0xea, 0x71, 0xa8, 0x77, 0xf6, 0xd3, 0x4e, 0x22, 0x3e, 0xc6, 0x46, 0x5a, 0x0f, 0xe7, 0xd8, 0x92, 0xdf, 0x50, 0x3b, + 0x71, 0x72, 0xd7, 0xd2, 0x59, 0xf4, 0x0b, 0x01, 0xfc, 0xe5, 0xb7, 0x95, 0x35, 0x3f, 0x5c, 0xd8, 0xfe, 0x4b, 0xff, + 0x65, 0x61, 0xff, 0x39, 0xb7, 0x80, 0x8d, 0x04, 0x8c, 0x58, 0xdf, 0x8c, 0x1b, 0x0f, 0x18, 0xb1, 0x63, 0x00, 0xa4, + 0x83, 0x18, 0x01, 0x4d, 0x79, 0x28, 0x04, 0x2f, 0xa2, 0x37, 0x8a, 0xce, 0xcd, 0x98, 0x06, 0xb2, 0xf2, 0x9a, 0x4c, + 0xf5, 0x41, 0xd8, 0xf8, 0x59, 0xb7, 0xb6, 0x70, 0x93, 0x0f, 0x63, 0xbd, 0xb4, 0xe6, 0xcc, 0x02, 0xd0, 0xa7, 0xb8, + 0xbf, 0x55, 0xa9, 0xcd, 0x35, 0xf6, 0xe6, 0xb4, 0x93, 0x1f, 0x7e, 0x0e, 0x7b, 0xbb, 0xe3, 0xcf, 0x85, 0xb9, 0x74, + 0xf4, 0xf9, 0xe5, 0xcc, 0x98, 0x5a, 0xd7, 0xda, 0xfd, 0xd1, 0xc2, 0x03, 0x6f, 0x50, 0xd9, 0x28, 0xdb, 0xe7, 0x12, + 0xa4, 0x8d, 0x84, 0x71, 0x27, 0x4e, 0x83, 0xad, 0x7c, 0x23, 0x59, 0x4a, 0xdd, 0xda, 0xcc, 0x00, 0xb6, 0x9b, 0xe0, + 0x2d, 0xa3, 0x8b, 0xde, 0x17, 0x96, 0xe9, 0xe9, 0x2e, 0xae, 0xdd, 0x22, 0xda, 0xa1, 0x5c, 0xb3, 0x88, 0x67, 0x6a, + 0xc1, 0x93, 0xe4, 0x62, 0x0e, 0xb8, 0x81, 0x32, 0xb1, 0xa4, 0x7d, 0x9d, 0x39, 0x43, 0x64, 0x45, 0x7e, 0xa5, 0x9f, + 0x1a, 0x7f, 0xbf, 0x8d, 0xbf, 0x9a, 0xdb, 0x6c, 0xd7, 0xaf, 0xeb, 0x94, 0x28, 0xd4, 0xb4, 0xd8, 0xf7, 0xd9, 0xa2, + 0x27, 0x8c, 0xed, 0x63, 0x4e, 0x8c, 0xd5, 0x5a, 0xf3, 0xee, 0x7b, 0x3d, 0x75, 0x9e, 0x6a, 0x1f, 0x51, 0xf3, 0x05, + 0xf6, 0xfb, 0xa0, 0xbd, 0xeb, 0xf5, 0x67, 0xf1, 0xa1, 0x6f, 0x2f, 0xbe, 0x7c, 0x5c, 0xaa, 0x4f, 0x4c, 0xcd, 0xd1, + 0x43, 0x76, 0xa8, 0x3c, 0xc1, 0x14, 0x3e, 0x50, 0x26, 0xa2, 0x02, 0xde, 0xbb, 0xcd, 0xfb, 0xec, 0x45, 0xd7, 0x92, + 0xff, 0xa8, 0x41, 0x0b, 0x09, 0x6b, 0xee, 0x50, 0x15, 0xac, 0x3b, 0xe2, 0xbf, 0xce, 0x79, 0xad, 0x2c, 0x6b, 0x2b, + 0x42, 0xcb, 0x87, 0x1d, 0xbe, 0xf3, 0x54, 0xeb, 0x63, 0xdc, 0x62, 0x27, 0xb9, 0xdd, 0xf2, 0x4c, 0x14, 0xb7, 0xa0, + 0xea, 0x72, 0x04, 0x82, 0xb4, 0x01, 0x19, 0x69, 0x2b, 0x46, 0x2d, 0xdc, 0x27, 0xed, 0xd7, 0xf6, 0xbb, 0x10, 0x4b, + 0x4f, 0x6b, 0x9a, 0xb2, 0xd2, 0x4d, 0xec, 0x45, 0x4a, 0x11, 0x42, 0x66, 0x7d, 0xf0, 0xfa, 0x93, 0x9a, 0x61, 0x73, + 0x77, 0xb7, 0x3a, 0x23, 0x3a, 0x16, 0xae, 0x51, 0x22, 0x2b, 0xe2, 0x6e, 0xe3, 0x30, 0x8b, 0xcf, 0xa5, 0x7f, 0x96, + 0xe7, 0x60, 0xce, 0x09, 0xed, 0xa6, 0x78, 0xa1, 0x19, 0xba, 0xe9, 0x1c, 0x3f, 0x30, 0x0c, 0x24, 0xbd, 0x40, 0xfe, + 0x3a, 0x95, 0xe3, 0x94, 0x23, 0x6a, 0x2d, 0x2b, 0xd1, 0xb6, 0xa0, 0x60, 0xf1, 0xd8, 0xdc, 0x01, 0xbe, 0x1b, 0x7e, + 0x5c, 0x60, 0xbe, 0x79, 0xf7, 0x19, 0xa2, 0x87, 0xf2, 0x40, 0xcd, 0x3b, 0xab, 0x95, 0x09, 0xde, 0x90, 0xc6, 0x9f, + 0x4a, 0x12, 0xbb, 0x37, 0x34, 0x69, 0x75, 0xd3, 0xbd, 0xb1, 0xd9, 0x2d, 0x65, 0x0e, 0xf3, 0xb0, 0xe9, 0x8a, 0x62, + 0x14, 0xf0, 0xac, 0x7b, 0x3b, 0x94, 0x95, 0x02, 0x16, 0xe0, 0x04, 0xea, 0x83, 0x5a, 0x58, 0x2c, 0x8f, 0x13, 0xf5, + 0x98, 0x59, 0x0e, 0x7c, 0x6d, 0xf0, 0xb2, 0x8f, 0xce, 0x12, 0xb0, 0x94, 0x6a, 0x21, 0x6d, 0x2a, 0x29, 0x7e, 0x99, + 0x93, 0xd3, 0xdb, 0x54, 0x13, 0xb5, 0xc9, 0xed, 0x7e, 0xdf, 0x71, 0x06, 0xad, 0xe4, 0xe0, 0x0e, 0x8e, 0xbd, 0x1e, + 0x84, 0x6c, 0x54, 0x40, 0xa6, 0xd9, 0x9f, 0xf2, 0xc8, 0x4e, 0x4b, 0xf9, 0x9c, 0xd4, 0xb4, 0x29, 0x02, 0xd6, 0x6c, + 0xbc, 0x9b, 0x36, 0x92, 0x62, 0xed, 0x0c, 0x47, 0x3c, 0x37, 0x8d, 0x8b, 0xef, 0xf3, 0x1f, 0x7b, 0xca, 0x16, 0xc2, + 0xea, 0x69, 0x7c, 0xd4, 0x3b, 0xbd, 0x32, 0xad, 0x1a, 0x2a, 0x73, 0x36, 0x96, 0xf0, 0x01}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From bb67b1ca1e2b36ba8919c1f2d6be1b37991f8ad3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:16:15 -1000 Subject: [PATCH 0298/2030] Bump actions/checkout from 6.0.1 to 6.0.2 (#13452) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto-label-pr.yml | 2 +- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-clang-tidy-hash.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .../workflows/ci-memory-impact-comment.yml | 2 +- .github/workflows/ci.yml | 30 +++++++++---------- .github/workflows/codeql.yml | 2 +- .github/workflows/release.yml | 8 ++--- .github/workflows/sync-device-classes.yml | 4 +-- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/.github/workflows/auto-label-pr.yml b/.github/workflows/auto-label-pr.yml index 8e96297cc0..d32d8e01c2 100644 --- a/.github/workflows/auto-label-pr.yml +++ b/.github/workflows/auto-label-pr.yml @@ -22,7 +22,7 @@ jobs: if: github.event.action != 'labeled' || github.event.sender.type != 'Bot' steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Generate a token id: generate-token diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 4c4bbf9981..20385b2461 100644 --- a/.github/workflows/ci-api-proto.yml +++ b/.github/workflows/ci-api-proto.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 with: diff --git a/.github/workflows/ci-clang-tidy-hash.yml b/.github/workflows/ci-clang-tidy-hash.yml index 94068c19d6..db311ed3e5 100644 --- a/.github/workflows/ci-clang-tidy-hash.yml +++ b/.github/workflows/ci-clang-tidy-hash.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 84d79cda17..52e2f1599a 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -43,7 +43,7 @@ jobs: - "docker" # - "lint" steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 with: diff --git a/.github/workflows/ci-memory-impact-comment.yml b/.github/workflows/ci-memory-impact-comment.yml index 7e81e1184d..fbcf5ea584 100644 --- a/.github/workflows/ci-memory-impact-comment.yml +++ b/.github/workflows/ci-memory-impact-comment.yml @@ -49,7 +49,7 @@ jobs: - name: Check out code from base repository if: steps.pr.outputs.skip != 'true' - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Always check out from the base repository (esphome/esphome), never from forks # Use the PR's target branch to ensure we run trusted code from the main repo diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81d3c826d7..a42ab0e422 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: cache-key: ${{ steps.cache-key.outputs.key }} steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Generate cache-key id: cache-key run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT @@ -70,7 +70,7 @@ jobs: if: needs.determine-jobs.outputs.python-linters == 'true' steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -91,7 +91,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -132,7 +132,7 @@ jobs: - common steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python id: restore-python uses: ./.github/actions/restore-python @@ -183,7 +183,7 @@ jobs: component-test-batches: ${{ steps.determine.outputs.component-test-batches }} steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Fetch enough history to find the merge base fetch-depth: 2 @@ -237,7 +237,7 @@ jobs: if: needs.determine-jobs.outputs.integration-tests == 'true' steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.13 id: python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 @@ -273,7 +273,7 @@ jobs: if: github.event_name == 'pull_request' && (needs.determine-jobs.outputs.cpp-unit-tests-run-all == 'true' || needs.determine-jobs.outputs.cpp-unit-tests-components != '[]') steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python @@ -321,7 +321,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Need history for HEAD~1 to work for checking changed files fetch-depth: 2 @@ -400,7 +400,7 @@ jobs: GH_TOKEN: ${{ github.token }} steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Need history for HEAD~1 to work for checking changed files fetch-depth: 2 @@ -489,7 +489,7 @@ jobs: steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: # Need history for HEAD~1 to work for checking changed files fetch-depth: 2 @@ -577,7 +577,7 @@ jobs: version: 1.0 - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -662,7 +662,7 @@ jobs: if: github.event_name == 'pull_request' && !startsWith(github.base_ref, 'beta') && !startsWith(github.base_ref, 'release') steps: - name: Check out code from GitHub - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -688,7 +688,7 @@ jobs: skip: ${{ steps.check-script.outputs.skip }} steps: - name: Check out target branch - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.base_ref }} @@ -840,7 +840,7 @@ jobs: flash_usage: ${{ steps.extract.outputs.flash_usage }} steps: - name: Check out PR branch - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: @@ -908,7 +908,7 @@ jobs: GH_TOKEN: ${{ github.token }} steps: - name: Check out code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Restore Python uses: ./.github/actions/restore-python with: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 399fb13aa5..f043cc5ca6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -54,7 +54,7 @@ jobs: # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b41b118504..b6e26a35af 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: branch_build: ${{ steps.tag.outputs.branch_build }} deploy_env: ${{ steps.tag.outputs.deploy_env }} steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get tag id: tag # yamllint disable rule:line-length @@ -60,7 +60,7 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 with: @@ -92,7 +92,7 @@ jobs: os: "ubuntu-24.04-arm" steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 with: @@ -168,7 +168,7 @@ jobs: - ghcr - dockerhub steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download digests uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 97fbf7aa9e..175ef88eb8 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -13,10 +13,10 @@ jobs: if: github.repository == 'esphome/esphome' steps: - name: Checkout - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Checkout Home Assistant - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: home-assistant/core path: lib/home-assistant From 04e102f344891af153894206832fca042e631df7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:16:27 -1000 Subject: [PATCH 0299/2030] Bump actions/setup-python from 6.1.0 to 6.2.0 (#13454) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci-clang-tidy-hash.yml | 2 +- .github/workflows/ci-docker.yml | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- .github/workflows/sync-device-classes.yml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 20385b2461..0328611f5c 100644 --- a/.github/workflows/ci-api-proto.yml +++ b/.github/workflows/ci-api-proto.yml @@ -23,7 +23,7 @@ jobs: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.11" diff --git a/.github/workflows/ci-clang-tidy-hash.yml b/.github/workflows/ci-clang-tidy-hash.yml index db311ed3e5..5054a62207 100644 --- a/.github/workflows/ci-clang-tidy-hash.yml +++ b/.github/workflows/ci-clang-tidy-hash.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.11" diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index 52e2f1599a..a83bcae0b0 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -45,7 +45,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.11" - name: Set up Docker Buildx diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a42ab0e422..f521b07bae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: run: echo key="${{ hashFiles('requirements.txt', 'requirements_test.txt', '.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT - name: Set up Python ${{ env.DEFAULT_PYTHON }} id: python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment @@ -240,7 +240,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python 3.13 id: python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" - name: Restore Python virtual environment diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6e26a35af..5cd8db6181 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,7 +62,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.x" - name: Build @@ -94,7 +94,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.11" diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index 175ef88eb8..b0d966555b 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -22,7 +22,7 @@ jobs: path: lib/home-assistant - name: Setup Python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: 3.13 From 6008abae625ebe3c57093be8a7985b49fec0fce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:16:40 -1000 Subject: [PATCH 0300/2030] Bump actions/setup-python from 6.1.0 to 6.2.0 in /.github/actions/restore-python (#13453) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/restore-python/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index 370c8bcc46..e178610a97 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -17,7 +17,7 @@ runs: steps: - name: Set up Python ${{ inputs.python-version }} id: python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment From 110c173eac6c4f2d3b84c901cfe94bce2c441025 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:16:53 -1000 Subject: [PATCH 0301/2030] Update wheel requirement from <0.46,>=0.43 to >=0.43,<0.47 (#13451) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 47dd4b7473..3ce2e6ebec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools==80.10.1", "wheel>=0.43,<0.46"] +requires = ["setuptools==80.10.1", "wheel>=0.43,<0.47"] build-backend = "setuptools.build_meta" [project] From 98a926f37f233247401e9cc00b35a27ca79753c3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:22:33 -0500 Subject: [PATCH 0302/2030] [heatpumpir] Fix ambiguous millis() call with HeatpumpIR library (#13458) Co-authored-by: Claude Opus 4.5 --- esphome/components/heatpumpir/heatpumpir.cpp | 35 +++++++++++++++++-- .../heatpumpir/ir_sender_esphome.cpp | 32 ----------------- .../components/heatpumpir/ir_sender_esphome.h | 25 ------------- 3 files changed, 33 insertions(+), 59 deletions(-) delete mode 100644 esphome/components/heatpumpir/ir_sender_esphome.cpp delete mode 100644 esphome/components/heatpumpir/ir_sender_esphome.h diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 1f1362f8d8..6b73a24dc4 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -3,13 +3,44 @@ #if defined(USE_ARDUINO) || defined(USE_ESP32) #include -#include "ir_sender_esphome.h" -#include "HeatpumpIRFactory.h" +#include +#include +#include "esphome/components/remote_base/remote_base.h" #include "esphome/core/log.h" namespace esphome { namespace heatpumpir { +// IRSenderESPHome - bridge between ESPHome's remote_transmitter and HeatpumpIR library +// Defined here (not in a header) to isolate HeatpumpIR's headers from the rest of ESPHome, +// as they define conflicting symbols like millis() in the global namespace. +class IRSenderESPHome : public IRSender { + public: + IRSenderESPHome(remote_base::RemoteTransmitterBase *transmitter) : IRSender(0), transmit_(transmitter->transmit()) {} + + void setFrequency(int frequency) override { // NOLINT(readability-identifier-naming) + auto *data = this->transmit_.get_data(); + data->set_carrier_frequency(1000 * frequency); + } + + void space(int space_length) override { + if (space_length) { + auto *data = this->transmit_.get_data(); + data->space(space_length); + } else { + this->transmit_.perform(); + } + } + + void mark(int mark_length) override { + auto *data = this->transmit_.get_data(); + data->mark(mark_length); + } + + protected: + remote_base::RemoteTransmitterBase::TransmitCall transmit_; +}; + static const char *const TAG = "heatpumpir.climate"; const std::map> PROTOCOL_CONSTRUCTOR_MAP = { diff --git a/esphome/components/heatpumpir/ir_sender_esphome.cpp b/esphome/components/heatpumpir/ir_sender_esphome.cpp deleted file mode 100644 index f010c72dac..0000000000 --- a/esphome/components/heatpumpir/ir_sender_esphome.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "ir_sender_esphome.h" - -#if defined(USE_ARDUINO) || defined(USE_ESP32) - -namespace esphome { -namespace heatpumpir { - -void IRSenderESPHome::setFrequency(int frequency) { // NOLINT(readability-identifier-naming) - auto *data = transmit_.get_data(); - data->set_carrier_frequency(1000 * frequency); -} - -// Send an IR 'mark' symbol, i.e. transmitter ON -void IRSenderESPHome::mark(int mark_length) { - auto *data = transmit_.get_data(); - data->mark(mark_length); -} - -// Send an IR 'space' symbol, i.e. transmitter OFF -void IRSenderESPHome::space(int space_length) { - if (space_length) { - auto *data = transmit_.get_data(); - data->space(space_length); - } else { - transmit_.perform(); - } -} - -} // namespace heatpumpir -} // namespace esphome - -#endif diff --git a/esphome/components/heatpumpir/ir_sender_esphome.h b/esphome/components/heatpumpir/ir_sender_esphome.h deleted file mode 100644 index c4209145ba..0000000000 --- a/esphome/components/heatpumpir/ir_sender_esphome.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#if defined(USE_ARDUINO) || defined(USE_ESP32) - -#include "esphome/components/remote_base/remote_base.h" -#include // arduino-heatpump library - -namespace esphome { -namespace heatpumpir { - -class IRSenderESPHome : public IRSender { - public: - IRSenderESPHome(remote_base::RemoteTransmitterBase *transmitter) : IRSender(0), transmit_(transmitter->transmit()){}; - void setFrequency(int frequency) override; // NOLINT(readability-identifier-naming) - void space(int space_length) override; - void mark(int mark_length) override; - - protected: - remote_base::RemoteTransmitterBase::TransmitCall transmit_; -}; - -} // namespace heatpumpir -} // namespace esphome - -#endif From effbcece49a469e08154441cf271c24c847d577e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 11:27:04 -1000 Subject: [PATCH 0303/2030] [time] Always call time sync callbacks even when time unchanged (#13456) --- esphome/components/time/real_time_clock.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index f217d14c55..f53a0a7cf7 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -40,6 +40,9 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { // Unsigned subtraction handles wraparound correctly, then cast to signed int32_t diff = static_cast(epoch - static_cast(current_time)); if (diff >= -1 && diff <= 1) { + // Time is already synchronized, but still call callbacks so components + // waiting for time sync (e.g., uptime timestamp sensor) can initialize + this->time_sync_callback_.call(); return; } } From 6725e6c01e0618fa79075f7ea1666b28a6d6c252 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 20 Jan 2026 17:49:40 -1000 Subject: [PATCH 0304/2030] [wifi] Process scan results one at a time to avoid heap allocation (#13400) --- .../wifi/wifi_component_esp_idf.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 848ec3e11c..99474ac2f8 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -827,16 +827,17 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } uint16_t number = it.number; - auto records = std::make_unique(number); - err = esp_wifi_scan_get_ap_records(&number, records.get()); - if (err != ESP_OK) { - ESP_LOGW(TAG, "esp_wifi_scan_get_ap_records failed: %s", esp_err_to_name(err)); - return; - } - scan_result_.init(number); - for (int i = 0; i < number; i++) { - auto &record = records[i]; + + // Process one record at a time to avoid large buffer allocation + wifi_ap_record_t record; + for (uint16_t i = 0; i < number; i++) { + err = esp_wifi_scan_get_ap_record(&record); + if (err != ESP_OK) { + ESP_LOGW(TAG, "esp_wifi_scan_get_ap_record failed: %s", esp_err_to_name(err)); + esp_wifi_clear_ap_list(); // Free remaining records not yet retrieved + break; + } bssid_t bssid; std::copy(record.bssid, record.bssid + 6, bssid.begin()); std::string ssid(reinterpret_cast(record.ssid)); From 9261b9ecaabd6c671720cadc626c3285b9871cb4 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:32:55 -0500 Subject: [PATCH 0305/2030] =?UTF-8?q?[lvgl]=20Validate=20LVGL=20dropdown?= =?UTF-8?q?=20symbols=20require=20Unicode=20codepoint=20=E2=89=A5=200x100?= =?UTF-8?q?=20(#13394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/lvgl/widgets/dropdown.py | 33 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/esphome/components/lvgl/widgets/dropdown.py b/esphome/components/lvgl/widgets/dropdown.py index 9ff183f3dd..ca89bb625b 100644 --- a/esphome/components/lvgl/widgets/dropdown.py +++ b/esphome/components/lvgl/widgets/dropdown.py @@ -1,3 +1,4 @@ +from esphome import codegen as cg import esphome.config_validation as cv from esphome.const import CONF_OPTIONS @@ -24,6 +25,34 @@ from .label import CONF_LABEL CONF_DROPDOWN = "dropdown" CONF_DROPDOWN_LIST = "dropdown_list" +# Example valid dropdown symbol (left arrow) for error messages +EXAMPLE_DROPDOWN_SYMBOL = "\U00002190" # ← + + +def dropdown_symbol_validator(value): + """ + Validate that the dropdown symbol is a single Unicode character + with a codepoint of 0x100 (256) or greater. + This is required because LVGL uses codepoints below 0x100 for internal symbols. + """ + value = cv.string(value) + # len(value) counts Unicode code points, not grapheme clusters or bytes + if len(value) != 1: + raise cv.Invalid( + f"Dropdown symbol must be a single character, got '{value}' with length {len(value)}" + ) + codepoint = ord(value) + if codepoint < 0x100: + # Format the example symbol as a Unicode escape for the error message + example_escape = f"\\U{ord(EXAMPLE_DROPDOWN_SYMBOL):08X}" + raise cv.Invalid( + f"Dropdown symbol must have a Unicode codepoint of 0x100 (256) or greater. " + f"'{value}' has codepoint {codepoint} (0x{codepoint:X}). " + f"Use a character like '{example_escape}' ({EXAMPLE_DROPDOWN_SYMBOL}) or other Unicode symbols with codepoint >= 0x100." + ) + return value + + lv_dropdown_t = LvSelect("LvDropdownType", parents=(LvCompound,)) lv_dropdown_list_t = LvType("lv_dropdown_list_t") @@ -33,7 +62,7 @@ dropdown_list_spec = WidgetType( DROPDOWN_BASE_SCHEMA = cv.Schema( { - cv.Optional(CONF_SYMBOL): lv_text, + cv.Optional(CONF_SYMBOL): dropdown_symbol_validator, cv.Exclusive(CONF_SELECTED_INDEX, CONF_SELECTED_TEXT): lv_int, cv.Exclusive(CONF_SELECTED_TEXT, CONF_SELECTED_TEXT): lv_text, cv.Optional(CONF_DROPDOWN_LIST): part_schema(dropdown_list_spec.parts), @@ -70,7 +99,7 @@ class DropdownType(WidgetType): if options := config.get(CONF_OPTIONS): lv_add(w.var.set_options(options)) if symbol := config.get(CONF_SYMBOL): - lv.dropdown_set_symbol(w.var.obj, await lv_text.process(symbol)) + lv.dropdown_set_symbol(w.var.obj, cg.safe_exp(symbol)) if (selected := config.get(CONF_SELECTED_INDEX)) is not None: value = await lv_int.process(selected) lv_add(w.var.set_selected_index(value, literal("LV_ANIM_OFF"))) From 65bcfee0356a38d659f807fde4fd46cf203186af Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:18:37 -0500 Subject: [PATCH 0306/2030] [http_request] Fix verify_ssl: false not working on ESP32 (#13422) Co-authored-by: Claude Opus 4.5 --- esphome/components/http_request/__init__.py | 1 + esphome/components/http_request/http_request_idf.cpp | 2 +- esphome/components/http_request/http_request_idf.h | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index b133aa69b2..9f74fb1023 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -157,6 +157,7 @@ async def to_code(config): if CORE.is_esp32: cg.add(var.set_buffer_size_rx(config[CONF_BUFFER_SIZE_RX])) cg.add(var.set_buffer_size_tx(config[CONF_BUFFER_SIZE_TX])) + cg.add(var.set_verify_ssl(config[CONF_VERIFY_SSL])) if config.get(CONF_VERIFY_SSL): esp32.add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 1de947ba5b..eedd321d80 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -89,7 +89,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c config.max_redirection_count = this->redirect_limit_; config.auth_type = HTTP_AUTH_TYPE_BASIC; #if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE - if (secure) { + if (secure && this->verify_ssl_) { config.crt_bundle_attach = esp_crt_bundle_attach; } #endif diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 4dc4736423..0fae67f5bc 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -34,6 +34,7 @@ class HttpRequestIDF : public HttpRequestComponent { void set_buffer_size_rx(uint16_t buffer_size_rx) { this->buffer_size_rx_ = buffer_size_rx; } void set_buffer_size_tx(uint16_t buffer_size_tx) { this->buffer_size_tx_ = buffer_size_tx; } + void set_verify_ssl(bool verify_ssl) { this->verify_ssl_ = verify_ssl; } protected: std::shared_ptr perform(const std::string &url, const std::string &method, const std::string &body, @@ -42,6 +43,7 @@ class HttpRequestIDF : public HttpRequestComponent { // if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE uint16_t buffer_size_rx_{}; uint16_t buffer_size_tx_{}; + bool verify_ssl_{true}; /// @brief Monitors the http client events to gather response headers static esp_err_t http_event_handler(esp_http_client_event_t *evt); From b06cce9eeba73489f8824e78f206b56351ee2fba Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:17:11 -0500 Subject: [PATCH 0307/2030] [esp32] Add warning for experimental 400MHz on ESP32-P4 (#13433) Co-authored-by: Claude Opus 4.5 --- esphome/components/esp32/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 45fe8d1c26..7fb708dea4 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -180,6 +180,12 @@ def set_core_data(config): path=[CONF_CPU_FREQUENCY], ) + if variant == VARIANT_ESP32P4 and cpu_frequency == "400MHZ": + _LOGGER.warning( + "400MHz on ESP32-P4 is experimental and may not boot. " + "Consider using 360MHz instead. See https://github.com/esphome/esphome/issues/13425" + ) + CORE.data[KEY_ESP32] = {} CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP32 conf = config[CONF_FRAMEWORK] From 5433c0f7074cd164492b3a7b972561d0ce38e427 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 14:03:49 -1000 Subject: [PATCH 0308/2030] [wifi] Fix bk72xx manual_ip preventing API connection (#13426) --- esphome/components/wifi/wifi_component_libretiny.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 162ed4e835..cc9f4ec193 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -460,13 +460,15 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); } #endif - // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) + // For static IP configurations, GOT_IP event may not fire, so set connected state here +#ifdef USE_WIFI_MANUAL_IP if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_state = LTWiFiSTAState::CONNECTED; +#ifdef USE_WIFI_IP_STATE_LISTENERS for (auto *listener : this->ip_state_listeners_) { listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); } +#endif } #endif break; From f01bd68a4b916322bfa417efa77fdcec258da1ec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 14:04:07 -1000 Subject: [PATCH 0309/2030] [spi] Fix display init failure by marking displays as write-only for half-duplex mode (#13431) --- esphome/components/epaper_spi/display.py | 2 +- esphome/components/ili9xxx/display.py | 2 +- esphome/components/max7219/display.py | 2 +- esphome/components/max7219digit/display.py | 2 +- esphome/components/mipi_rgb/display.py | 2 +- esphome/components/mipi_spi/display.py | 4 +--- esphome/components/pcd8544/display.py | 2 +- esphome/components/qspi_dbi/display.py | 2 +- esphome/components/spi/__init__.py | 7 ++++++- esphome/components/spi/spi_esp_idf.cpp | 5 ++++- esphome/components/ssd1306_spi/display.py | 2 +- esphome/components/ssd1322_spi/display.py | 2 +- esphome/components/ssd1325_spi/display.py | 2 +- esphome/components/ssd1327_spi/display.py | 2 +- esphome/components/ssd1331_spi/display.py | 2 +- esphome/components/ssd1351_spi/display.py | 2 +- esphome/components/st7567_spi/display.py | 2 +- esphome/components/st7701s/display.py | 2 +- esphome/components/st7735/display.py | 2 +- esphome/components/st7789v/display.py | 2 +- esphome/components/st7920/display.py | 2 +- esphome/components/waveshare_epaper/display.py | 2 +- 22 files changed, 30 insertions(+), 24 deletions(-) diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index a77e291237..8cc7b2663c 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -190,7 +190,7 @@ async def to_code(config): # Rotation is handled by setting the transform display_config = {k: v for k, v in config.items() if k != CONF_ROTATION} await display.register_display(var, display_config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 9588bccd55..bfb2300f4f 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -223,7 +223,7 @@ async def to_code(config): var = cg.Pvariable(config[CONF_ID], rhs) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) if init_sequences := config.get(CONF_INIT_SEQUENCE): diff --git a/esphome/components/max7219/display.py b/esphome/components/max7219/display.py index c9d10f3c45..a434125148 100644 --- a/esphome/components/max7219/display.py +++ b/esphome/components/max7219/display.py @@ -29,7 +29,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index fef121ff10..e6d53efc5d 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -86,7 +86,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) diff --git a/esphome/components/mipi_rgb/display.py b/esphome/components/mipi_rgb/display.py index 96e167b2e6..084fe6de14 100644 --- a/esphome/components/mipi_rgb/display.py +++ b/esphome/components/mipi_rgb/display.py @@ -260,7 +260,7 @@ async def to_code(config): cg.add(var.set_enable_pins(enable)) if CONF_SPI_ID in config: - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) sequence, madctl = model.get_sequence(config) cg.add(var.set_init_sequence(sequence)) cg.add(var.set_madctl(madctl)) diff --git a/esphome/components/mipi_spi/display.py b/esphome/components/mipi_spi/display.py index 69bf133c68..8dccfa3a92 100644 --- a/esphome/components/mipi_spi/display.py +++ b/esphome/components/mipi_spi/display.py @@ -443,6 +443,4 @@ async def to_code(config): ) cg.add(var.set_writer(lambda_)) await display.register_display(var, config) - await spi.register_spi_device(var, config) - # Displays are write-only, set the SPI device to write-only as well - cg.add(var.set_write_only(True)) + await spi.register_spi_device(var, config, write_only=True) diff --git a/esphome/components/pcd8544/display.py b/esphome/components/pcd8544/display.py index 2c24b133da..9d993c2105 100644 --- a/esphome/components/pcd8544/display.py +++ b/esphome/components/pcd8544/display.py @@ -44,7 +44,7 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/qspi_dbi/display.py b/esphome/components/qspi_dbi/display.py index e4440c9b81..48d1f6d12e 100644 --- a/esphome/components/qspi_dbi/display.py +++ b/esphome/components/qspi_dbi/display.py @@ -161,7 +161,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) chip = DriverChip.chips[config[CONF_MODEL]] if chip.initsequence: diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index e890567abf..931882be8d 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -39,6 +39,7 @@ from esphome.const import ( ) from esphome.core import CORE, CoroPriority, coroutine_with_priority import esphome.final_validate as fv +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core", "@clydebarrow"] spi_ns = cg.esphome_ns.namespace("spi") @@ -448,9 +449,13 @@ def spi_device_schema( ) -async def register_spi_device(var, config): +async def register_spi_device( + var: cg.Pvariable, config: ConfigType, write_only: bool = False +) -> None: parent = await cg.get_variable(config[CONF_SPI_ID]) cg.add(var.set_spi_parent(parent)) + if write_only: + cg.add(var.set_write_only(True)) if cs_pin := config.get(CONF_CS_PIN): pin = await cg.gpio_pin_expression(cs_pin) cg.add(var.set_cs_pin(pin)) diff --git a/esphome/components/spi/spi_esp_idf.cpp b/esphome/components/spi/spi_esp_idf.cpp index a1837fa58d..107b6a3f1a 100644 --- a/esphome/components/spi/spi_esp_idf.cpp +++ b/esphome/components/spi/spi_esp_idf.cpp @@ -195,8 +195,11 @@ class SPIDelegateHw : public SPIDelegate { config.post_cb = nullptr; if (this->bit_order_ == BIT_ORDER_LSB_FIRST) config.flags |= SPI_DEVICE_BIT_LSBFIRST; - if (this->write_only_) + if (this->write_only_) { config.flags |= SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY; + ESP_LOGD(TAG, "SPI device with CS pin %d using half-duplex mode (write-only)", + Utility::get_pin_no(this->cs_pin_)); + } esp_err_t const err = spi_bus_add_device(this->channel_, &config, &this->handle_); if (err != ESP_OK) { ESP_LOGE(TAG, "Add device failed - err %X", err); diff --git a/esphome/components/ssd1306_spi/display.py b/esphome/components/ssd1306_spi/display.py index 4af41073d4..26953b4f39 100644 --- a/esphome/components/ssd1306_spi/display.py +++ b/esphome/components/ssd1306_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1306_base.setup_ssd1306(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1322_spi/display.py b/esphome/components/ssd1322_spi/display.py index 849e71abee..3d01caf874 100644 --- a/esphome/components/ssd1322_spi/display.py +++ b/esphome/components/ssd1322_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1322_base.setup_ssd1322(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1325_spi/display.py b/esphome/components/ssd1325_spi/display.py index e18db33c68..dbb9a14ac2 100644 --- a/esphome/components/ssd1325_spi/display.py +++ b/esphome/components/ssd1325_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1325_base.setup_ssd1325(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1327_spi/display.py b/esphome/components/ssd1327_spi/display.py index b622c098ec..f052764a91 100644 --- a/esphome/components/ssd1327_spi/display.py +++ b/esphome/components/ssd1327_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1327_base.setup_ssd1327(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1331_spi/display.py b/esphome/components/ssd1331_spi/display.py index 50895b3175..c16780302f 100644 --- a/esphome/components/ssd1331_spi/display.py +++ b/esphome/components/ssd1331_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1331_base.setup_ssd1331(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/ssd1351_spi/display.py b/esphome/components/ssd1351_spi/display.py index bd7033c3d4..2a6e984029 100644 --- a/esphome/components/ssd1351_spi/display.py +++ b/esphome/components/ssd1351_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await ssd1351_base.setup_ssd1351(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7567_spi/display.py b/esphome/components/st7567_spi/display.py index 305aa35024..02cd2c105c 100644 --- a/esphome/components/st7567_spi/display.py +++ b/esphome/components/st7567_spi/display.py @@ -32,7 +32,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await st7567_base.setup_st7567(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index 3078158d25..a8b12dfa28 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -173,7 +173,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) sequence = [] for seq in config[CONF_INIT_SEQUENCE]: diff --git a/esphome/components/st7735/display.py b/esphome/components/st7735/display.py index 2761214315..9dc69f27ff 100644 --- a/esphome/components/st7735/display.py +++ b/esphome/components/st7735/display.py @@ -99,7 +99,7 @@ async def to_code(config): config[CONF_INVERT_COLORS], ) await setup_st7735(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index 8259eacf2d..c9f4199616 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -177,7 +177,7 @@ FINAL_VALIDATE_SCHEMA = spi.final_validate_device_schema( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) cg.add(var.set_model_str(config[CONF_MODEL])) diff --git a/esphome/components/st7920/display.py b/esphome/components/st7920/display.py index de7b2247dd..ef33fac6c6 100644 --- a/esphome/components/st7920/display.py +++ b/esphome/components/st7920/display.py @@ -28,7 +28,7 @@ CONFIG_SCHEMA = ( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) if CONF_LAMBDA in config: lambda_ = await cg.process_lambda( diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index cea0b2be5e..5db7a1fc3d 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -239,7 +239,7 @@ async def to_code(config): raise NotImplementedError() await display.register_display(var, config) - await spi.register_spi_device(var, config) + await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) cg.add(var.set_dc_pin(dc)) From 811ac813204794a08b24af2611a581537824eff8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Jan 2026 19:48:32 -1000 Subject: [PATCH 0310/2030] [http_request] Fix OTA failures on ESP8266/Arduino by making read semantics consistent (#13435) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../update/esp32_hosted_update.cpp | 49 ++++-- .../components/http_request/http_request.h | 151 +++++++++++++++++- .../http_request/http_request_arduino.cpp | 29 +++- .../http_request/http_request_idf.cpp | 43 ++++- .../http_request/ota/ota_http_request.cpp | 62 +++---- .../update/http_request_update.cpp | 31 ++-- 6 files changed, 296 insertions(+), 69 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index d69a438578..0e0778dd23 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -11,6 +11,7 @@ #include #ifdef USE_ESP32_HOSTED_HTTP_UPDATE +#include "esphome/components/http_request/http_request.h" #include "esphome/components/json/json_util.h" #include "esphome/components/network/util.h" #endif @@ -181,15 +182,23 @@ bool Esp32HostedUpdate::fetch_manifest_() { } // Read manifest JSON into string (manifest is small, ~1KB max) + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly std::string json_str; json_str.reserve(container->content_length); uint8_t buf[256]; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->http_request_parent_->get_timeout(); while (container->get_bytes_read() < container->content_length) { - int read = container->read(buf, sizeof(buf)); - if (read > 0) { - json_str.append(reinterpret_cast(buf), read); - } + int read_or_error = container->read(buf, sizeof(buf)); + App.feed_wdt(); yield(); + auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == http_request::HttpReadLoopResult::RETRY) + continue; + if (result != http_request::HttpReadLoopResult::DATA) + break; // ERROR or TIMEOUT + json_str.append(reinterpret_cast(buf), read_or_error); } container->end(); @@ -294,32 +303,38 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { } // Stream firmware to coprocessor while computing SHA256 + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly sha256::SHA256 hasher; hasher.init(); uint8_t buffer[CHUNK_SIZE]; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->http_request_parent_->get_timeout(); while (container->get_bytes_read() < total_size) { - int read = container->read(buffer, sizeof(buffer)); + int read_or_error = container->read(buffer, sizeof(buffer)); // Feed watchdog and give other tasks a chance to run App.feed_wdt(); yield(); - // Exit loop if no data available (stream closed or end of data) - if (read <= 0) { - if (read < 0) { - ESP_LOGE(TAG, "Stream closed with error"); - esp_hosted_slave_ota_end(); // NOLINT - container->end(); - this->status_set_error(LOG_STR("Download failed")); - return false; + auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == http_request::HttpReadLoopResult::RETRY) + continue; + if (result != http_request::HttpReadLoopResult::DATA) { + if (result == http_request::HttpReadLoopResult::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading firmware data"); + } else { + ESP_LOGE(TAG, "Error reading firmware data: %d", read_or_error); } - // read == 0: no more data available, exit loop - break; + esp_hosted_slave_ota_end(); // NOLINT + container->end(); + this->status_set_error(LOG_STR("Download failed")); + return false; } - hasher.add(buffer, read); - err = esp_hosted_slave_ota_write(buffer, read); // NOLINT + hasher.add(buffer, read_or_error); + err = esp_hosted_slave_ota_write(buffer, read_or_error); // NOLINT if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err)); esp_hosted_slave_ota_end(); // NOLINT diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index a8c2cdfc63..fb39ca504c 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -79,6 +79,81 @@ inline bool is_redirect(int const status) { */ inline bool is_success(int const status) { return status >= HTTP_STATUS_OK && status < HTTP_STATUS_MULTIPLE_CHOICES; } +/* + * HTTP Container Read Semantics + * ============================= + * + * IMPORTANT: These semantics differ from standard BSD sockets! + * + * BSD socket read() returns: + * > 0: bytes read + * == 0: connection closed (EOF) + * < 0: error (check errno) + * + * HttpContainer::read() returns: + * > 0: bytes read successfully + * == 0: no data available yet OR all content read + * (caller should check bytes_read vs content_length) + * < 0: error or connection closed (caller should EXIT) + * HTTP_ERROR_CONNECTION_CLOSED (-1) = connection closed prematurely + * other negative values = platform-specific errors + * + * Platform behaviors: + * - ESP-IDF: blocking reads, 0 only returned when all content read + * - Arduino: non-blocking, 0 means "no data yet" or "all content read" + * + * Use the helper functions below instead of checking return values directly: + * - http_read_loop_result(): for manual loops with per-chunk processing + * - http_read_fully(): for simple "read N bytes into buffer" operations + */ + +/// Error code returned by HttpContainer::read() when connection closed prematurely +/// NOTE: Unlike BSD sockets where 0 means EOF, here 0 means "no data yet, retry" +static constexpr int HTTP_ERROR_CONNECTION_CLOSED = -1; + +/// Status of a read operation +enum class HttpReadStatus : uint8_t { + OK, ///< Read completed successfully + ERROR, ///< Read error occurred + TIMEOUT, ///< Timeout waiting for data +}; + +/// Result of an HTTP read operation +struct HttpReadResult { + HttpReadStatus status; ///< Status of the read operation + int error_code; ///< Error code from read() on failure, 0 on success +}; + +/// Result of processing a non-blocking read with timeout (for manual loops) +enum class HttpReadLoopResult : uint8_t { + DATA, ///< Data was read, process it + RETRY, ///< No data yet, already delayed, caller should continue loop + ERROR, ///< Read error, caller should exit loop + TIMEOUT, ///< Timeout waiting for data, caller should exit loop +}; + +/// Process a read result with timeout tracking and delay handling +/// @param bytes_read_or_error Return value from read() - positive for bytes read, negative for error +/// @param last_data_time Time of last successful read, updated when data received +/// @param timeout_ms Maximum time to wait for data +/// @return DATA if data received, RETRY if should continue loop, ERROR/TIMEOUT if should exit +inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, + uint32_t timeout_ms) { + if (bytes_read_or_error > 0) { + last_data_time = millis(); + return HttpReadLoopResult::DATA; + } + if (bytes_read_or_error < 0) { + return HttpReadLoopResult::ERROR; + } + // bytes_read_or_error == 0: no data available yet + if (millis() - last_data_time >= timeout_ms) { + return HttpReadLoopResult::TIMEOUT; + } + delay(1); // Small delay to prevent tight spinning + return HttpReadLoopResult::RETRY; +} + class HttpRequestComponent; class HttpContainer : public Parented { @@ -88,6 +163,33 @@ class HttpContainer : public Parented { int status_code; uint32_t duration_ms; + /** + * @brief Read data from the HTTP response body. + * + * WARNING: These semantics differ from BSD sockets! + * BSD sockets: 0 = EOF (connection closed) + * This method: 0 = no data yet OR all content read, negative = error/closed + * + * @param buf Buffer to read data into + * @param max_len Maximum number of bytes to read + * @return + * - > 0: Number of bytes read successfully + * - 0: No data available yet OR all content read + * (check get_bytes_read() >= content_length to distinguish) + * - HTTP_ERROR_CONNECTION_CLOSED (-1): Connection closed prematurely + * - < -1: Other error (platform-specific error code) + * + * Platform notes: + * - ESP-IDF: blocking read, 0 only when all content read + * - Arduino: non-blocking, 0 can mean "no data yet" or "all content read" + * + * Use get_bytes_read() and content_length to track progress. + * When get_bytes_read() >= content_length, all data has been received. + * + * IMPORTANT: Do not use raw return values directly. Use these helpers: + * - http_read_loop_result(): for loops with per-chunk processing + * - http_read_fully(): for simple "read N bytes" operations + */ virtual int read(uint8_t *buf, size_t max_len) = 0; virtual void end() = 0; @@ -110,6 +212,38 @@ class HttpContainer : public Parented { std::map> response_headers_{}; }; +/// Read data from HTTP container into buffer with timeout handling +/// Handles feed_wdt, yield, and timeout checking internally +/// @param container The HTTP container to read from +/// @param buffer Buffer to read into +/// @param total_size Total bytes to read +/// @param chunk_size Maximum bytes per read call +/// @param timeout_ms Read timeout in milliseconds +/// @return HttpReadResult with status and error_code on failure +inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, size_t total_size, size_t chunk_size, + uint32_t timeout_ms) { + size_t read_index = 0; + uint32_t last_data_time = millis(); + + while (read_index < total_size) { + int read_bytes_or_error = container->read(buffer + read_index, std::min(chunk_size, total_size - read_index)); + + App.feed_wdt(); + yield(); + + auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result == HttpReadLoopResult::ERROR) + return {HttpReadStatus::ERROR, read_bytes_or_error}; + if (result == HttpReadLoopResult::TIMEOUT) + return {HttpReadStatus::TIMEOUT, 0}; + + read_index += read_bytes_or_error; + } + return {HttpReadStatus::OK, 0}; +} + class HttpRequestResponseTrigger : public Trigger, std::string &> { public: void process(const std::shared_ptr &container, std::string &response_body) { @@ -124,6 +258,7 @@ class HttpRequestComponent : public Component { void set_useragent(const char *useragent) { this->useragent_ = useragent; } void set_timeout(uint32_t timeout) { this->timeout_ = timeout; } + uint32_t get_timeout() const { return this->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; } @@ -249,15 +384,21 @@ template class HttpRequestSendAction : public Action { RAMAllocator allocator; uint8_t *buf = allocator.allocate(max_length); if (buf != nullptr) { + // NOTE: HttpContainer::read() has non-BSD socket semantics - see top of this file + // Use http_read_loop_result() helper instead of checking return values directly size_t read_index = 0; + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->parent_->get_timeout(); while (container->get_bytes_read() < max_length) { - int read = container->read(buf + read_index, std::min(max_length - read_index, 512)); - if (read <= 0) { - break; - } + int read_or_error = container->read(buf + read_index, std::min(max_length - read_index, 512)); App.feed_wdt(); yield(); - read_index += read; + auto result = http_read_loop_result(read_or_error, last_data_time, read_timeout); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result != HttpReadLoopResult::DATA) + break; // ERROR or TIMEOUT + read_index += read_or_error; } response_body.reserve(read_index); response_body.assign((char *) buf, read_index); diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index a653942b18..8ec4d2bc4b 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -139,6 +139,23 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur return container; } +// Arduino HTTP read implementation +// +// WARNING: Return values differ from BSD sockets! See http_request.h for full documentation. +// +// Arduino's WiFiClient is inherently non-blocking - available() returns 0 when +// no data is ready. We use connected() to distinguish "no data yet" from +// "connection closed". +// +// WiFiClient behavior: +// available() > 0: data ready to read +// available() == 0 && connected(): no data yet, still connected +// available() == 0 && !connected(): connection closed +// +// We normalize to HttpContainer::read() contract (NOT BSD socket semantics!): +// > 0: bytes read +// 0: no data yet, retry <-- NOTE: 0 means retry, NOT EOF! +// < 0: error/connection closed <-- connection closed returns -1, not 0 int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); @@ -146,7 +163,7 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { WiFiClient *stream_ptr = this->client_.getStreamPtr(); if (stream_ptr == nullptr) { ESP_LOGE(TAG, "Stream pointer vanished!"); - return -1; + return HTTP_ERROR_CONNECTION_CLOSED; } int available_data = stream_ptr->available(); @@ -154,7 +171,15 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { if (bufsize == 0) { this->duration_ms += (millis() - start); - return 0; + // Check if we've read all expected content + if (this->bytes_read_ >= this->content_length) { + return 0; // All content read successfully + } + // No data available - check if connection is still open + if (!stream_ptr->connected()) { + return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed prematurely + } + return 0; // No data yet, caller should retry } App.feed_wdt(); diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index eedd321d80..b6fb7f7ea9 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -209,26 +209,57 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c return container; } +// ESP-IDF HTTP read implementation (blocking mode) +// +// WARNING: Return values differ from BSD sockets! See http_request.h for full documentation. +// +// esp_http_client_read() in blocking mode returns: +// > 0: bytes read +// 0: connection closed (end of stream) +// < 0: error +// +// We normalize to HttpContainer::read() contract: +// > 0: bytes read +// 0: no data yet / all content read (caller should check bytes_read vs content_length) +// < 0: error/connection closed int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); - this->feed_wdt(); - int read_len = esp_http_client_read(this->client_, (char *) buf, max_len); - this->feed_wdt(); - if (read_len > 0) { - this->bytes_read_ += read_len; + // Check if we've already read all expected content + if (this->bytes_read_ >= this->content_length) { + return 0; // All content read successfully } + + this->feed_wdt(); + int read_len_or_error = esp_http_client_read(this->client_, (char *) buf, max_len); + this->feed_wdt(); + this->duration_ms += (millis() - start); - return read_len; + if (read_len_or_error > 0) { + this->bytes_read_ += read_len_or_error; + return read_len_or_error; + } + + // Connection closed by server before all content received + if (read_len_or_error == 0) { + return HTTP_ERROR_CONNECTION_CLOSED; + } + + // Negative value - error, return the actual error code for debugging + return read_len_or_error; } void HttpContainerIDF::end() { + if (this->client_ == nullptr) { + return; // Already cleaned up + } watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); esp_http_client_close(this->client_); esp_http_client_cleanup(this->client_); + this->client_ = nullptr; } void HttpContainerIDF::feed_wdt() { diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 2a7db9137f..6c77e75d8c 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -115,39 +115,47 @@ uint8_t OtaHttpRequestComponent::do_ota_() { return error_code; } + // NOTE: HttpContainer::read() has non-BSD socket semantics - see http_request.h + // Use http_read_loop_result() helper instead of checking return values directly + uint32_t last_data_time = millis(); + const uint32_t read_timeout = this->parent_->get_timeout(); + while (container->get_bytes_read() < container->content_length) { - // read a maximum of chunk_size bytes into buf. (real read size returned) - 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); + // read a maximum of chunk_size bytes into buf. (real read size returned, or negative error code) + int bufsize_or_error = container->read(buf, OtaHttpRequestComponent::HTTP_RECV_BUFFER); + ESP_LOGVV(TAG, "bytes_read_ = %u, body_length_ = %u, bufsize_or_error = %i", container->get_bytes_read(), + container->content_length, bufsize_or_error); // feed watchdog and give other tasks a chance to run App.feed_wdt(); yield(); - // Exit loop if no data available (stream closed or end of data) - if (bufsize <= 0) { - if (bufsize < 0) { - ESP_LOGE(TAG, "Stream closed with error"); - this->cleanup_(std::move(backend), container); - return OTA_CONNECTION_ERROR; + auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout); + if (result == HttpReadLoopResult::RETRY) + continue; + if (result != HttpReadLoopResult::DATA) { + if (result == HttpReadLoopResult::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading data"); + } else { + ESP_LOGE(TAG, "Error reading data: %d", bufsize_or_error); } - // bufsize == 0: no more data available, exit loop - break; + this->cleanup_(std::move(backend), container); + return OTA_CONNECTION_ERROR; } - if (bufsize <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { + // At this point bufsize_or_error > 0, so it's a valid size + if (bufsize_or_error <= OtaHttpRequestComponent::HTTP_RECV_BUFFER) { // add read bytes to MD5 - md5_receive.add(buf, bufsize); + md5_receive.add(buf, bufsize_or_error); // write bytes to OTA backend this->update_started_ = true; - error_code = backend->write(buf, bufsize); + error_code = backend->write(buf, bufsize_or_error); 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, - container->get_bytes_read() - bufsize, container->content_length); + container->get_bytes_read() - bufsize_or_error, container->content_length); this->cleanup_(std::move(backend), container); return error_code; } @@ -244,19 +252,19 @@ bool OtaHttpRequestComponent::http_get_md5_() { } this->md5_expected_.resize(MD5_SIZE); - int read_len = 0; - while (container->get_bytes_read() < MD5_SIZE) { - read_len = container->read((uint8_t *) this->md5_expected_.data(), MD5_SIZE); - if (read_len <= 0) { - break; - } - App.feed_wdt(); - yield(); - } + auto result = http_read_fully(container.get(), (uint8_t *) this->md5_expected_.data(), MD5_SIZE, MD5_SIZE, + this->parent_->get_timeout()); container->end(); - ESP_LOGV(TAG, "Read len: %u, MD5 expected: %u", read_len, MD5_SIZE); - return read_len == MD5_SIZE; + if (result.status != HttpReadStatus::OK) { + if (result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading MD5"); + } else { + ESP_LOGE(TAG, "Error reading MD5: %d", result.error_code); + } + return false; + } + return true; } bool OtaHttpRequestComponent::validate_url_(const std::string &url) { diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 82b391e01f..c63e55d159 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -11,7 +11,12 @@ namespace http_request { // The update function runs in a task only on ESP32s. #ifdef USE_ESP32 -#define UPDATE_RETURN vTaskDelete(nullptr) // Delete the current update task +// vTaskDelete doesn't return, but clang-tidy doesn't know that +#define UPDATE_RETURN \ + do { \ + vTaskDelete(nullptr); \ + __builtin_unreachable(); \ + } while (0) #else #define UPDATE_RETURN return #endif @@ -70,19 +75,21 @@ void HttpRequestUpdate::update_task(void *params) { UPDATE_RETURN; } - size_t read_index = 0; - while (container->get_bytes_read() < container->content_length) { - int read_bytes = container->read(data + read_index, MAX_READ_SIZE); - - yield(); - - if (read_bytes <= 0) { - // Network error or connection closed - break to avoid infinite loop - break; + auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, + this_update->request_parent_->get_timeout()); + if (read_result.status != HttpReadStatus::OK) { + if (read_result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading manifest"); + } else { + ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); } - - read_index += read_bytes; + // Defer to main loop to avoid race condition on component_state_ read-modify-write + this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to read manifest")); }); + allocator.deallocate(data, container->content_length); + container->end(); + UPDATE_RETURN; } + size_t read_index = container->get_bytes_read(); bool valid = false; { // Ensures the response string falls out of scope and deallocates before the task ends From 3c3d5c2fca3c3a75a61a8e10ed9701409b28898b Mon Sep 17 00:00:00 2001 From: Rene Guca <45061891+rguca@users.noreply.github.com> Date: Thu, 22 Jan 2026 13:54:10 +0100 Subject: [PATCH 0311/2030] [dht] Increase delay for DHT22 and RHT03 (#13446) --- esphome/components/dht/dht.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 6cb204c8de..276ea24717 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -89,10 +89,8 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r delayMicroseconds(500); } else if (this->model_ == DHT_MODEL_DHT22_TYPE2) { delayMicroseconds(2000); - } else if (this->model_ == DHT_MODEL_AM2120 || this->model_ == DHT_MODEL_AM2302) { - delayMicroseconds(1000); } else { - delayMicroseconds(800); + delayMicroseconds(1000); } #ifdef USE_ESP32 From 95eebcd74fc50d033fc2d71e5329dcdc4ba8e024 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 08:09:14 -1000 Subject: [PATCH 0312/2030] [api] Limit Nagle batching for log messages to reduce LWIP buffer pressure (#13439) --- esphome/components/api/api_connection.cpp | 19 +------ esphome/components/api/api_frame_helper.h | 67 +++++++++++++++-------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 25512de4c7..b6398c0309 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1844,23 +1844,8 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { return false; } - // Toggle Nagle's algorithm based on message type to prevent log messages from - // filling the TCP send buffer and crowding out important state updates. - // - // This honors the `no_delay` proto option - SubscribeLogsResponse is the only - // message with `option (no_delay) = false;` in api.proto, indicating it should - // allow Nagle coalescing. This option existed since 2019 but was never implemented. - // - // - Log messages: Enable Nagle (NODELAY=false) so small log packets coalesce - // into fewer, larger packets. They flush naturally via TCP delayed ACK timer - // (~200ms), buffer filling, or when a state update triggers a flush. - // - // - All other messages (state updates, responses): Disable Nagle (NODELAY=true) - // for immediate delivery. These are time-sensitive and should not be delayed. - // - // This must be done proactively BEFORE the buffer fills up - checking buffer - // state here would be too late since we'd already be in a degraded state. - this->helper_->set_nodelay(!is_log_message); + // Set TCP_NODELAY based on message type - see set_nodelay_for_message() for details + this->helper_->set_nodelay_for_message(is_log_message); APIError err = this->helper_->write_protobuf_packet(message_type, buffer); if (err == APIError::WOULD_BLOCK) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 27ec1ff915..f311e34fd7 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -120,26 +120,39 @@ class APIFrameHelper { } return APIError::OK; } - /// Toggle TCP_NODELAY socket option to control Nagle's algorithm. - /// - /// This is used to allow log messages to coalesce (Nagle enabled) while keeping - /// state updates low-latency (NODELAY enabled). Without this, many small log - /// packets fill the TCP send buffer, crowding out important state updates. - /// - /// State is tracked to minimize setsockopt() overhead - on lwip_raw (ESP8266/RP2040) - /// this is just a boolean assignment; on other platforms it's a lightweight syscall. - /// - /// @param enable true to enable NODELAY (disable Nagle), false to enable Nagle - /// @return true if successful or already in desired state - bool set_nodelay(bool enable) { - if (this->nodelay_enabled_ == enable) - return true; - int val = enable ? 1 : 0; - int err = this->socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int)); - if (err == 0) { - this->nodelay_enabled_ = enable; + // Manage TCP_NODELAY (Nagle's algorithm) based on message type. + // + // For non-log messages (sensor data, state updates): Always disable Nagle + // (NODELAY on) for immediate delivery - these are time-sensitive. + // + // For log messages: Use Nagle to coalesce multiple small log packets into + // fewer larger packets, reducing WiFi overhead. However, we limit batching + // to 3 messages to avoid excessive LWIP buffer pressure on memory-constrained + // devices like ESP8266. LWIP's TCP_OVERSIZE option coalesces the data into + // shared pbufs, but holding data too long waiting for Nagle's timer causes + // buffer exhaustion and dropped messages. + // + // Flow: Log 1 (Nagle on) -> Log 2 (Nagle on) -> Log 3 (NODELAY, flush all) + // + void set_nodelay_for_message(bool is_log_message) { + if (!is_log_message) { + if (this->nodelay_state_ != NODELAY_ON) { + this->set_nodelay_raw_(true); + this->nodelay_state_ = NODELAY_ON; + } + return; + } + + // Log messages 1-3: state transitions -1 -> 1 -> 2 -> -1 (flush on 3rd) + if (this->nodelay_state_ == NODELAY_ON) { + this->set_nodelay_raw_(false); + this->nodelay_state_ = 1; + } else if (this->nodelay_state_ >= LOG_NAGLE_COUNT) { + this->set_nodelay_raw_(true); + this->nodelay_state_ = NODELAY_ON; + } else { + this->nodelay_state_++; } - return err == 0; } virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0; // Write multiple protobuf messages in a single operation @@ -229,10 +242,18 @@ class APIFrameHelper { uint8_t tx_buf_head_{0}; uint8_t tx_buf_tail_{0}; uint8_t tx_buf_count_{0}; - // Tracks TCP_NODELAY state to minimize setsockopt() calls. Initialized to true - // since init_common_() enables NODELAY. Used by set_nodelay() to allow log - // messages to coalesce while keeping state updates low-latency. - bool nodelay_enabled_{true}; + // Nagle batching state for log messages. NODELAY_ON (-1) means NODELAY is enabled + // (immediate send). Values 1-2 count log messages in the current Nagle batch. + // After LOG_NAGLE_COUNT logs, we switch to NODELAY to flush and reset. + static constexpr int8_t NODELAY_ON = -1; + static constexpr int8_t LOG_NAGLE_COUNT = 2; + int8_t nodelay_state_{NODELAY_ON}; + + // Internal helper to set TCP_NODELAY socket option + void set_nodelay_raw_(bool enable) { + int val = enable ? 1 : 0; + this->socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int)); + } // Common initialization for both plaintext and noise protocols APIError init_common_(); From 95b23702e46783784102b16409271d461473aafb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 10:42:14 -1000 Subject: [PATCH 0313/2030] [wifi] Fix stale error_from_callback_ causing immediate connection failures (#13450) --- esphome/components/wifi/wifi_component.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index ff6284c073..52d9b2b442 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -565,6 +565,11 @@ void WiFiComponent::start() { void WiFiComponent::restart_adapter() { ESP_LOGW(TAG, "Restarting adapter"); this->wifi_mode_(false, {}); + // Clear error flag here because restart_adapter() enters COOLDOWN state, + // and check_connecting_finished() is called after cooldown without going + // through start_connecting() first. Without this clear, stale errors would + // trigger spurious "failed (callback)" logs. The canonical clear location + // is in start_connecting(); this is the only exception to that pattern. this->error_from_callback_ = false; } @@ -618,8 +623,6 @@ void WiFiComponent::loop() { if (!this->is_connected()) { ESP_LOGW(TAG, "Connection lost; reconnecting"); this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; - // Clear error flag before reconnecting so first attempt is not seen as immediate failure - this->error_from_callback_ = false; this->retry_connect(); } else { this->status_clear_warning(); @@ -963,6 +966,12 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { ESP_LOGV(TAG, " Hidden: %s", YESNO(ap.get_hidden())); #endif + // Clear any stale error from previous connection attempt. + // This is the canonical location for clearing the flag since all connection + // attempts go through start_connecting(). The only other clear is in + // restart_adapter() which enters COOLDOWN without calling start_connecting(). + this->error_from_callback_ = false; + if (!this->wifi_sta_connect_(ap)) { ESP_LOGE(TAG, "wifi_sta_connect_ failed"); // Enter cooldown to allow WiFi hardware to stabilize @@ -1068,7 +1077,6 @@ void WiFiComponent::enable() { return; ESP_LOGD(TAG, "Enabling"); - this->error_from_callback_ = false; this->state_ = WIFI_COMPONENT_STATE_OFF; this->start(); } @@ -1329,11 +1337,6 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { // Reset to initial phase on successful connection (don't log transition, just reset state) this->retry_phase_ = WiFiRetryPhase::INITIAL_CONNECT; this->num_retried_ = 0; - // Ensure next connection attempt does not inherit error state - // so when WiFi disconnects later we start fresh and don't see - // the first connection as a failure. - this->error_from_callback_ = false; - if (this->has_ap()) { #ifdef USE_CAPTIVE_PORTAL if (this->is_captive_portal_active_()) { @@ -1844,8 +1847,6 @@ void WiFiComponent::retry_connect() { this->advance_to_next_target_or_increment_retry_(); } - this->error_from_callback_ = false; - yield(); // Check if we have a valid target before building params // After exhausting all networks in a phase, selected_sta_index_ may be -1 @@ -2171,7 +2172,6 @@ void WiFiComponent::process_roaming_scan_() { this->roaming_state_ = RoamingState::CONNECTING; // Connect directly - wifi_sta_connect_ handles disconnect internally - this->error_from_callback_ = false; this->start_connecting(roam_params); } From 85181779d18c3cc304a6c927f0e45ab0927ec354 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:07:41 -0500 Subject: [PATCH 0314/2030] [fingerprint_grow] Use buffer-based dump_summary to fix deprecation warnings (#13447) Co-authored-by: Claude Opus 4.5 --- .../fingerprint_grow/fingerprint_grow.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index eb7ede8fe9..da4535fc82 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -1,4 +1,5 @@ #include "fingerprint_grow.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" #include @@ -532,14 +533,21 @@ void FingerprintGrowComponent::sensor_sleep_() { } void FingerprintGrowComponent::dump_config() { + char sensing_pin_buf[GPIO_SUMMARY_MAX_LEN]; + char power_pin_buf[GPIO_SUMMARY_MAX_LEN]; + if (this->has_sensing_pin_) { + this->sensing_pin_->dump_summary(sensing_pin_buf, sizeof(sensing_pin_buf)); + } + if (this->has_power_pin_) { + this->sensor_power_pin_->dump_summary(power_pin_buf, sizeof(power_pin_buf)); + } ESP_LOGCONFIG(TAG, "GROW_FINGERPRINT_READER:\n" " System Identifier Code: 0x%.4X\n" " Touch Sensing Pin: %s\n" " Sensor Power Pin: %s", - this->system_identifier_code_, - this->has_sensing_pin_ ? this->sensing_pin_->dump_summary().c_str() : "None", - this->has_power_pin_ ? this->sensor_power_pin_->dump_summary().c_str() : "None"); + this->system_identifier_code_, this->has_sensing_pin_ ? sensing_pin_buf : "None", + this->has_power_pin_ ? power_pin_buf : "None"); if (this->idle_period_to_sleep_ms_ < UINT32_MAX) { ESP_LOGCONFIG(TAG, " Idle Period to Sleep: %" PRIu32 " ms", this->idle_period_to_sleep_ms_); } else { From fb984cd052aeba9b9f6e497bd124cfe0b445ec7c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:10:55 -0500 Subject: [PATCH 0315/2030] [aqi] Remove unit_of_measurement to fix Home Assistant warning (#13448) Co-authored-by: Claude Opus 4.5 --- esphome/components/aqi/sensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/aqi/sensor.py b/esphome/components/aqi/sensor.py index 0b5ee8d75a..5842aea88c 100644 --- a/esphome/components/aqi/sensor.py +++ b/esphome/components/aqi/sensor.py @@ -13,14 +13,11 @@ from . import AQI_CALCULATION_TYPE, CONF_CALCULATION_TYPE, aqi_ns CODEOWNERS = ["@jasstrong"] DEPENDENCIES = ["sensor"] -UNIT_INDEX = "index" - AQISensor = aqi_ns.class_("AQISensor", sensor.Sensor, cg.Component) CONFIG_SCHEMA = ( sensor.sensor_schema( AQISensor, - unit_of_measurement=UNIT_INDEX, accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, From ec791063b383fbe068e4c9c6a418905016abc9ba Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 11:27:04 -1000 Subject: [PATCH 0316/2030] [time] Always call time sync callbacks even when time unchanged (#13456) --- esphome/components/time/real_time_clock.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index f217d14c55..f53a0a7cf7 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -40,6 +40,9 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { // Unsigned subtraction handles wraparound correctly, then cast to signed int32_t diff = static_cast(epoch - static_cast(current_time)); if (diff >= -1 && diff <= 1) { + // Time is already synchronized, but still call callbacks so components + // waiting for time sync (e.g., uptime timestamp sensor) can initialize + this->time_sync_callback_.call(); return; } } From f938de16afd22ce458b56eb8cf7e942c285d7aaf Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 22 Jan 2026 16:30:52 -0500 Subject: [PATCH 0317/2030] Bump version to 2026.1.1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 70eeefb85e..20582c14a6 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.0 +PROJECT_NUMBER = 2026.1.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 951414f006..0c6a46e233 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.0" +__version__ = "2026.1.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 3dbebb728d2ee05e06b858276361286b39e9a550 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 23 Jan 2026 09:34:29 +1100 Subject: [PATCH 0318/2030] [sensor] Clamp filter handles non-finite values better (#13457) --- esphome/components/sensor/filter.cpp | 22 +++++++++------------- tests/components/template/common-base.yaml | 1 + 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 3adf28748d..375505a557 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -445,22 +445,18 @@ optional CalibratePolynomialFilter::new_value(float value) { ClampFilter::ClampFilter(float min, float max, bool ignore_out_of_range) : min_(min), max_(max), ignore_out_of_range_(ignore_out_of_range) {} optional ClampFilter::new_value(float value) { - if (std::isfinite(value)) { - if (std::isfinite(this->min_) && value < this->min_) { - if (this->ignore_out_of_range_) { - return {}; - } else { - return this->min_; - } + if (std::isfinite(this->min_) && !(value >= this->min_)) { + if (this->ignore_out_of_range_) { + return {}; } + return this->min_; + } - if (std::isfinite(this->max_) && value > this->max_) { - if (this->ignore_out_of_range_) { - return {}; - } else { - return this->max_; - } + if (std::isfinite(this->max_) && !(value <= this->max_)) { + if (this->ignore_out_of_range_) { + return {}; } + return this->max_; } return value; } diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index afc3fd9819..9dc65fbab8 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -117,6 +117,7 @@ sensor: - 10.0 -> 12.1 - 13.0 -> 14.0 - clamp: + # Infinity and NaN will be clamped (NaN -> min_value, +Infinity -> max_value, -Infinity -> min_value) max_value: 10.0 min_value: -10.0 - debounce: 0.1s From 71cda050738461b4413b552396dbf535d5c24dc6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:42:28 -1000 Subject: [PATCH 0319/2030] [st7701s] Fix dump_summary deprecation warning (#13462) --- esphome/components/st7701s/st7701s.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 6314c99fb0..221fe39b9d 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -1,5 +1,6 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "st7701s.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" namespace esphome { @@ -183,8 +184,11 @@ void ST7701S::dump_config() { LOG_PIN(" DE Pin: ", this->de_pin_); LOG_PIN(" Reset Pin: ", this->reset_pin_); size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); - for (size_t i = 0; i != data_pin_count; i++) - ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, (this->data_pins_[i])->dump_summary().c_str()); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + for (size_t i = 0; i != data_pin_count; i++) { + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary); + } ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); } From e8972c65c8a654092068aca12922efc7ced80c4c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:53:15 -1000 Subject: [PATCH 0320/2030] [mipi_rgb] Fix dump_summary deprecation warning (#13463) --- esphome/components/mipi_rgb/mipi_rgb.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index ef96da8a1c..d0e716bd24 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -1,9 +1,11 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "mipi_rgb.h" +#include "esphome/core/gpio.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/hal.h" #include "esp_lcd_panel_rgb.h" +#include namespace esphome { namespace mipi_rgb { @@ -343,19 +345,27 @@ int MipiRgb::get_height() { } } -static std::string get_pin_name(GPIOPin *pin) { +static const char *get_pin_name(GPIOPin *pin, std::span buffer) { if (pin == nullptr) return "None"; - return pin->dump_summary(); + pin->dump_summary(buffer.data(), buffer.size()); + return buffer.data(); } void MipiRgb::dump_pins_(uint8_t start, uint8_t end, const char *name, uint8_t offset) { + char pin_summary[GPIO_SUMMARY_MAX_LEN]; for (uint8_t i = start; i != end; i++) { - ESP_LOGCONFIG(TAG, " %s pin %d: %s", name, offset++, this->data_pins_[i]->dump_summary().c_str()); + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " %s pin %d: %s", name, offset++, pin_summary); } } void MipiRgb::dump_config() { + char reset_buf[GPIO_SUMMARY_MAX_LEN]; + char de_buf[GPIO_SUMMARY_MAX_LEN]; + char pclk_buf[GPIO_SUMMARY_MAX_LEN]; + char hsync_buf[GPIO_SUMMARY_MAX_LEN]; + char vsync_buf[GPIO_SUMMARY_MAX_LEN]; ESP_LOGCONFIG(TAG, "MIPI_RGB LCD" "\n Model: %s" @@ -379,9 +389,9 @@ void MipiRgb::dump_config() { this->model_, this->width_, this->height_, this->rotation_, YESNO(this->pclk_inverted_), this->hsync_pulse_width_, this->hsync_back_porch_, this->hsync_front_porch_, this->vsync_pulse_width_, this->vsync_back_porch_, this->vsync_front_porch_, YESNO(this->invert_colors_), - (unsigned) (this->pclk_frequency_ / 1000000), get_pin_name(this->reset_pin_).c_str(), - get_pin_name(this->de_pin_).c_str(), get_pin_name(this->pclk_pin_).c_str(), - get_pin_name(this->hsync_pin_).c_str(), get_pin_name(this->vsync_pin_).c_str()); + (unsigned) (this->pclk_frequency_ / 1000000), get_pin_name(this->reset_pin_, reset_buf), + get_pin_name(this->de_pin_, de_buf), get_pin_name(this->pclk_pin_, pclk_buf), + get_pin_name(this->hsync_pin_, hsync_buf), get_pin_name(this->vsync_pin_, vsync_buf)); this->dump_pins_(8, 13, "Blue", 0); this->dump_pins_(13, 16, "Green", 0); From 3184717607ce32c4ac79ca9fefd33d1f00f8d8d8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:53:38 -1000 Subject: [PATCH 0321/2030] [rpi_dpi_rgb] Fix dump_summary deprecation warning (#13461) --- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index a81bb17dfc..363f4b63b8 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -1,5 +1,6 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "rpi_dpi_rgb.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" namespace esphome { @@ -134,8 +135,11 @@ void RpiDpiRgb::dump_config() { LOG_PIN(" Enable Pin: ", this->enable_pin_); LOG_PIN(" Reset Pin: ", this->reset_pin_); size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); - for (size_t i = 0; i != data_pin_count; i++) - ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, (this->data_pins_[i])->dump_summary().c_str()); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + for (size_t i = 0; i != data_pin_count; i++) { + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary); + } } void RpiDpiRgb::reset_display_() const { From 5779e3e6e466438677f3102ca777ae8ab02aba25 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:54:01 -1000 Subject: [PATCH 0322/2030] [atm90e32] Fix dump_summary deprecation warning and remove stored cs_summary_ (#13465) --- esphome/components/atm90e32/atm90e32.cpp | 56 ++++++++++++++++-------- esphome/components/atm90e32/atm90e32.h | 4 +- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/esphome/components/atm90e32/atm90e32.cpp b/esphome/components/atm90e32/atm90e32.cpp index f4c199cb98..412964d0f8 100644 --- a/esphome/components/atm90e32/atm90e32.cpp +++ b/esphome/components/atm90e32/atm90e32.cpp @@ -108,10 +108,14 @@ void ATM90E32Component::update() { #endif } +void ATM90E32Component::get_cs_summary_(std::span buffer) { + this->cs_->dump_summary(buffer.data(), buffer.size()); +} + void ATM90E32Component::setup() { this->spi_setup(); - this->cs_summary_ = this->cs_->dump_summary(); - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); uint16_t mmode0 = 0x87; // 3P4W 50Hz uint16_t high_thresh = 0; @@ -159,13 +163,13 @@ void ATM90E32Component::setup() { if (this->enable_offset_calibration_) { // Initialize flash storage for offset calibrations uint32_t o_hash = fnv1_hash("_offset_calibration_"); - o_hash = fnv1_hash_extend(o_hash, this->cs_summary_); + o_hash = fnv1_hash_extend(o_hash, cs); this->offset_pref_ = global_preferences->make_preference(o_hash, true); this->restore_offset_calibrations_(); // Initialize flash storage for power offset calibrations uint32_t po_hash = fnv1_hash("_power_offset_calibration_"); - po_hash = fnv1_hash_extend(po_hash, this->cs_summary_); + po_hash = fnv1_hash_extend(po_hash, cs); this->power_offset_pref_ = global_preferences->make_preference(po_hash, true); this->restore_power_offset_calibrations_(); } else { @@ -186,7 +190,7 @@ void ATM90E32Component::setup() { if (this->enable_gain_calibration_) { // Initialize flash storage for gain calibration uint32_t g_hash = fnv1_hash("_gain_calibration_"); - g_hash = fnv1_hash_extend(g_hash, this->cs_summary_); + g_hash = fnv1_hash_extend(g_hash, cs); this->gain_calibration_pref_ = global_preferences->make_preference(g_hash, true); this->restore_gain_calibrations_(); @@ -217,7 +221,8 @@ void ATM90E32Component::setup() { } void ATM90E32Component::log_calibration_status_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); bool offset_mismatch = false; bool power_mismatch = false; @@ -568,7 +573,8 @@ float ATM90E32Component::get_chip_temperature_() { } void ATM90E32Component::run_gain_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->enable_gain_calibration_) { ESP_LOGW(TAG, "[CALIBRATION][%s] Gain calibration is disabled! Enable it first with enable_gain_calibration: true", cs); @@ -668,7 +674,8 @@ void ATM90E32Component::run_gain_calibrations() { } void ATM90E32Component::save_gain_calibration_to_memory_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); bool success = this->gain_calibration_pref_.save(&this->gain_phase_); global_preferences->sync(); if (success) { @@ -681,7 +688,8 @@ void ATM90E32Component::save_gain_calibration_to_memory_() { } void ATM90E32Component::save_offset_calibration_to_memory_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); bool success = this->offset_pref_.save(&this->offset_phase_); global_preferences->sync(); if (success) { @@ -697,7 +705,8 @@ void ATM90E32Component::save_offset_calibration_to_memory_() { } void ATM90E32Component::save_power_offset_calibration_to_memory_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); bool success = this->power_offset_pref_.save(&this->power_offset_phase_); global_preferences->sync(); if (success) { @@ -713,7 +722,8 @@ void ATM90E32Component::save_power_offset_calibration_to_memory_() { } void ATM90E32Component::run_offset_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->enable_offset_calibration_) { ESP_LOGW(TAG, "[CALIBRATION][%s] Offset calibration is disabled! Enable it first with enable_offset_calibration: true", @@ -743,7 +753,8 @@ void ATM90E32Component::run_offset_calibrations() { } void ATM90E32Component::run_power_offset_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->enable_offset_calibration_) { ESP_LOGW( TAG, @@ -816,7 +827,8 @@ void ATM90E32Component::write_power_offsets_to_registers_(uint8_t phase, int16_t } void ATM90E32Component::restore_gain_calibrations_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); for (uint8_t i = 0; i < 3; ++i) { this->config_gain_phase_[i].voltage_gain = this->phase_[i].voltage_gain_; this->config_gain_phase_[i].current_gain = this->phase_[i].ct_gain_; @@ -870,7 +882,8 @@ void ATM90E32Component::restore_gain_calibrations_() { } void ATM90E32Component::restore_offset_calibrations_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); for (uint8_t i = 0; i < 3; ++i) this->config_offset_phase_[i] = this->offset_phase_[i]; @@ -912,7 +925,8 @@ void ATM90E32Component::restore_offset_calibrations_() { } void ATM90E32Component::restore_power_offset_calibrations_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); for (uint8_t i = 0; i < 3; ++i) this->config_power_offset_phase_[i] = this->power_offset_phase_[i]; @@ -954,7 +968,8 @@ void ATM90E32Component::restore_power_offset_calibrations_() { } void ATM90E32Component::clear_gain_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->using_saved_calibrations_) { ESP_LOGI(TAG, "[CALIBRATION][%s] No stored gain calibrations to clear. Current values:", cs); ESP_LOGI(TAG, "[CALIBRATION][%s] ----------------------------------------------------------", cs); @@ -1003,7 +1018,8 @@ void ATM90E32Component::clear_gain_calibrations() { } void ATM90E32Component::clear_offset_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->restored_offset_calibration_) { ESP_LOGI(TAG, "[CALIBRATION][%s] No stored offset calibrations to clear. Current values:", cs); ESP_LOGI(TAG, "[CALIBRATION][%s] --------------------------------------------------------------", cs); @@ -1045,7 +1061,8 @@ void ATM90E32Component::clear_offset_calibrations() { } void ATM90E32Component::clear_power_offset_calibrations() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); if (!this->restored_power_offset_calibration_) { ESP_LOGI(TAG, "[CALIBRATION][%s] No stored power offsets to clear. Current values:", cs); ESP_LOGI(TAG, "[CALIBRATION][%s] ---------------------------------------------------------------------", cs); @@ -1120,7 +1137,8 @@ int16_t ATM90E32Component::calibrate_power_offset(uint8_t phase, bool reactive) } bool ATM90E32Component::verify_gain_writes_() { - const char *cs = this->cs_summary_.c_str(); + char cs[GPIO_SUMMARY_MAX_LEN]; + this->get_cs_summary_(cs); bool success = true; for (uint8_t phase = 0; phase < 3; phase++) { uint16_t read_voltage = this->read16_(voltage_gain_registers[phase]); diff --git a/esphome/components/atm90e32/atm90e32.h b/esphome/components/atm90e32/atm90e32.h index 938ce512ce..2524616470 100644 --- a/esphome/components/atm90e32/atm90e32.h +++ b/esphome/components/atm90e32/atm90e32.h @@ -1,11 +1,13 @@ #pragma once +#include #include #include "atm90e32_reg.h" #include "esphome/components/sensor/sensor.h" #include "esphome/components/spi/spi.h" #include "esphome/core/application.h" #include "esphome/core/component.h" +#include "esphome/core/gpio.h" #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" @@ -182,6 +184,7 @@ class ATM90E32Component : public PollingComponent, bool verify_gain_writes_(); bool validate_spi_read_(uint16_t expected, const char *context = nullptr); void log_calibration_status_(); + void get_cs_summary_(std::span buffer); struct ATM90E32Phase { uint16_t voltage_gain_{0}; @@ -247,7 +250,6 @@ class ATM90E32Component : public PollingComponent, ESPPreferenceObject offset_pref_; ESPPreferenceObject power_offset_pref_; ESPPreferenceObject gain_calibration_pref_; - std::string cs_summary_; sensor::Sensor *freq_sensor_{nullptr}; #ifdef USE_TEXT_SENSOR From cfb61bc50a82c97bca295e14db9d971f2d8a5dc9 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 22 Jan 2026 20:35:37 -0600 Subject: [PATCH 0323/2030] [ir_rf_proxy] Remove unnecessary headers, add tests (#13464) --- esphome/components/ir_rf_proxy/ir_rf_proxy.h | 2 - tests/components/ir_rf_proxy/common-rx.yaml | 18 +++++++++ tests/components/ir_rf_proxy/common-tx.yaml | 19 +++++++++ tests/components/ir_rf_proxy/common.yaml | 39 +------------------ .../ir_rf_proxy/test-rx.esp32-idf.yaml | 7 ++++ .../ir_rf_proxy/test-rx.esp8266-ard.yaml | 7 ++++ .../ir_rf_proxy/test-rx.rp2040-ard.yaml | 7 ++++ .../ir_rf_proxy/test-tx.esp32-idf.yaml | 7 ++++ .../ir_rf_proxy/test-tx.esp8266-ard.yaml | 7 ++++ .../ir_rf_proxy/test-tx.rp2040-ard.yaml | 7 ++++ .../ir_rf_proxy/test.bk72xx-ard.yaml | 8 ++++ .../ir_rf_proxy/test.esp32-idf.yaml | 5 ++- .../ir_rf_proxy/test.esp8266-ard.yaml | 5 ++- .../ir_rf_proxy/test.rp2040-ard.yaml | 5 ++- 14 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 tests/components/ir_rf_proxy/common-rx.yaml create mode 100644 tests/components/ir_rf_proxy/common-tx.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test.bk72xx-ard.yaml diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.h b/esphome/components/ir_rf_proxy/ir_rf_proxy.h index d7c8919def..f067a6e17a 100644 --- a/esphome/components/ir_rf_proxy/ir_rf_proxy.h +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.h @@ -5,8 +5,6 @@ // Once the API is considered stable, this warning will be removed. #include "esphome/components/infrared/infrared.h" -#include "esphome/components/remote_transmitter/remote_transmitter.h" -#include "esphome/components/remote_receiver/remote_receiver.h" namespace esphome::ir_rf_proxy { diff --git a/tests/components/ir_rf_proxy/common-rx.yaml b/tests/components/ir_rf_proxy/common-rx.yaml new file mode 100644 index 0000000000..0f758f832d --- /dev/null +++ b/tests/components/ir_rf_proxy/common-rx.yaml @@ -0,0 +1,18 @@ +remote_receiver: + id: ir_receiver + pin: ${rx_pin} + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared receiver + - platform: ir_rf_proxy + id: ir_rx + name: "IR Receiver" + remote_receiver_id: ir_receiver + + # RF 900MHz receiver + - platform: ir_rf_proxy + id: rf_900_rx + name: "RF 900 Receiver" + frequency: 900 MHz + remote_receiver_id: ir_receiver diff --git a/tests/components/ir_rf_proxy/common-tx.yaml b/tests/components/ir_rf_proxy/common-tx.yaml new file mode 100644 index 0000000000..4af9e2635e --- /dev/null +++ b/tests/components/ir_rf_proxy/common-tx.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + id: ir_transmitter + pin: ${tx_pin} + carrier_duty_percent: 50% + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared transmitter + - platform: ir_rf_proxy + id: ir_tx + name: "IR Transmitter" + remote_transmitter_id: ir_transmitter + + # RF 433MHz transmitter + - platform: ir_rf_proxy + id: rf_433_tx + name: "RF 433 Transmitter" + frequency: 433 MHz + remote_transmitter_id: ir_transmitter diff --git a/tests/components/ir_rf_proxy/common.yaml b/tests/components/ir_rf_proxy/common.yaml index cd2b10d31b..53a0cd379a 100644 --- a/tests/components/ir_rf_proxy/common.yaml +++ b/tests/components/ir_rf_proxy/common.yaml @@ -1,42 +1,7 @@ +network: + wifi: ssid: MySSID password: password1 api: - -remote_transmitter: - id: ir_transmitter - pin: ${tx_pin} - carrier_duty_percent: 50% - -remote_receiver: - id: ir_receiver - pin: ${rx_pin} - -# Test various hardware types with transmitter/receiver using infrared platform -infrared: - # Infrared transmitter - - platform: ir_rf_proxy - id: ir_tx - name: "IR Transmitter" - remote_transmitter_id: ir_transmitter - - # Infrared receiver - - platform: ir_rf_proxy - id: ir_rx - name: "IR Receiver" - remote_receiver_id: ir_receiver - - # RF 433MHz transmitter - - platform: ir_rf_proxy - id: rf_433_tx - name: "RF 433 Transmitter" - frequency: 433 MHz - remote_transmitter_id: ir_transmitter - - # RF 900MHz receiver - - platform: ir_rf_proxy - id: rf_900_rx - name: "RF 900 Receiver" - frequency: 900 MHz - remote_receiver_id: ir_receiver diff --git a/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml b/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml b/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml b/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..a0e145f476 --- /dev/null +++ b/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml @@ -0,0 +1,8 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.esp32-idf.yaml b/tests/components/ir_rf_proxy/test.esp32-idf.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.esp32-idf.yaml +++ b/tests/components/ir_rf_proxy/test.esp32-idf.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.esp8266-ard.yaml +++ b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.rp2040-ard.yaml +++ b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml From 0cdcacc7fca01ea12ef5de23662cfbbd5a009ac4 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 24 Jan 2026 09:02:27 +1100 Subject: [PATCH 0324/2030] [mipi_rgb] Add software reset command to st7701s init sequence (#13470) --- esphome/components/mipi_rgb/models/st7701s.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/mipi_rgb/models/st7701s.py b/esphome/components/mipi_rgb/models/st7701s.py index 3c66380d04..990a1ca4f3 100644 --- a/esphome/components/mipi_rgb/models/st7701s.py +++ b/esphome/components/mipi_rgb/models/st7701s.py @@ -55,6 +55,7 @@ st7701s = ST7701S( pclk_frequency="16MHz", pclk_inverted=True, initsequence=( + (0x01,), # Software Reset (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10), # Page 0 (0xC0, 0x3B, 0x00), (0xC1, 0x0D, 0x02), (0xC2, 0x31, 0x05), (0xB0, 0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,), From 5c67e04fef9708cb4f2783c29daccaa087388efe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 23 Jan 2026 12:37:06 -1000 Subject: [PATCH 0325/2030] [slow_pwm] Fix dump_summary deprecation warning (#13460) --- esphome/components/slow_pwm/slow_pwm_output.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/slow_pwm/slow_pwm_output.cpp b/esphome/components/slow_pwm/slow_pwm_output.cpp index 48ded94b3a..033729c407 100644 --- a/esphome/components/slow_pwm/slow_pwm_output.cpp +++ b/esphome/components/slow_pwm/slow_pwm_output.cpp @@ -1,6 +1,7 @@ #include "slow_pwm_output.h" -#include "esphome/core/log.h" #include "esphome/core/application.h" +#include "esphome/core/gpio.h" +#include "esphome/core/log.h" namespace esphome { namespace slow_pwm { @@ -20,7 +21,9 @@ void SlowPWMOutput::set_output_state_(bool new_state) { } if (new_state != current_state_) { if (this->pin_) { - ESP_LOGV(TAG, "Switching output pin %s to %s", this->pin_->dump_summary().c_str(), ONOFF(new_state)); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + this->pin_->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGV(TAG, "Switching output pin %s to %s", pin_summary, ONOFF(new_state)); } else { ESP_LOGV(TAG, "Switching to %s", ONOFF(new_state)); } From 5f2203b915b82f04b6aa86d95fedef2766bdb919 Mon Sep 17 00:00:00 2001 From: Big Mike Date: Fri, 23 Jan 2026 17:03:23 -0600 Subject: [PATCH 0326/2030] [sen5x] Fix store baseline functionality (#13469) --- esphome/components/sen5x/sen5x.cpp | 94 +++++++++++++----------------- esphome/components/sen5x/sen5x.h | 15 ++--- esphome/components/sen5x/sensor.py | 1 + 3 files changed, 45 insertions(+), 65 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index d5c9dfa3ae..09d93a2b2f 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -124,8 +124,8 @@ void SEN5XComponent::setup() { sen5x_type = SEN55; } } - ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); } + ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); if (this->humidity_sensor_ && sen5x_type == SEN50) { ESP_LOGE(TAG, "Relative humidity requires a SEN54 or SEN55"); this->humidity_sensor_ = nullptr; // mark as not used @@ -159,28 +159,14 @@ void SEN5XComponent::setup() { // This ensures the baseline storage is cleared after OTA // Serial numbers are unique to each sensor, so multiple sensors can be used without conflict uint32_t hash = fnv1a_hash_extend(App.get_config_version_hash(), combined_serial); - this->pref_ = global_preferences->make_preference(hash, true); - - if (this->pref_.load(&this->voc_baselines_storage_)) { - ESP_LOGI(TAG, "Loaded VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - } - - // Initialize storage timestamp - this->seconds_since_last_store_ = 0; - - if (this->voc_baselines_storage_.state0 > 0 && this->voc_baselines_storage_.state1 > 0) { - ESP_LOGI(TAG, "Setting VOC baseline from save state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - uint16_t states[4]; - - states[0] = this->voc_baselines_storage_.state0 >> 16; - states[1] = this->voc_baselines_storage_.state0 & 0xFFFF; - states[2] = this->voc_baselines_storage_.state1 >> 16; - states[3] = this->voc_baselines_storage_.state1 & 0xFFFF; - - if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, states, 4)) { - ESP_LOGE(TAG, "Failed to set VOC baseline from saved state"); + this->pref_ = global_preferences->make_preference(hash, true); + this->voc_baseline_time_ = App.get_loop_component_start_time(); + if (this->pref_.load(&this->voc_baseline_state_)) { + if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, this->voc_baseline_state_, 4)) { + ESP_LOGE(TAG, "VOC Baseline State write to sensor failed"); + } else { + ESP_LOGV(TAG, "VOC Baseline State loaded"); + delay(20); } } } @@ -288,6 +274,14 @@ void SEN5XComponent::dump_config() { ESP_LOGCONFIG(TAG, " RH/T acceleration mode: %s", LOG_STR_ARG(rht_accel_mode_to_string(this->acceleration_mode_.value()))); } + if (this->voc_sensor_) { + char hex_buf[5 * 4]; + format_hex_pretty_to(hex_buf, this->voc_baseline_state_, 4, 0); + ESP_LOGCONFIG(TAG, + " Store Baseline: %s\n" + " State: %s\n", + TRUEFALSE(this->store_baseline_), hex_buf); + } LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "PM 1.0", this->pm_1_0_sensor_); LOG_SENSOR(" ", "PM 2.5", this->pm_2_5_sensor_); @@ -304,36 +298,6 @@ void SEN5XComponent::update() { return; } - // Store baselines after defined interval or if the difference between current and stored baseline becomes too - // much - if (this->store_baseline_ && this->seconds_since_last_store_ > SHORTEST_BASELINE_STORE_INTERVAL) { - if (this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE)) { - // run it a bit later to avoid adding a delay here - this->set_timeout(550, [this]() { - uint16_t states[4]; - if (this->read_data(states, 4)) { - uint32_t state0 = states[0] << 16 | states[1]; - uint32_t state1 = states[2] << 16 | states[3]; - if ((uint32_t) std::abs(static_cast(this->voc_baselines_storage_.state0 - state0)) > - MAXIMUM_STORAGE_DIFF || - (uint32_t) std::abs(static_cast(this->voc_baselines_storage_.state1 - state1)) > - MAXIMUM_STORAGE_DIFF) { - this->seconds_since_last_store_ = 0; - this->voc_baselines_storage_.state0 = state0; - this->voc_baselines_storage_.state1 = state1; - - if (this->pref_.save(&this->voc_baselines_storage_)) { - ESP_LOGI(TAG, "Stored VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - } else { - ESP_LOGW(TAG, "Could not store VOC baselines"); - } - } - } - }); - } - } - if (!this->write_command(SEN5X_CMD_READ_MEASUREMENT)) { this->status_set_warning(); ESP_LOGD(TAG, "Write error: read measurement (%d)", this->last_error_); @@ -402,7 +366,29 @@ void SEN5XComponent::update() { if (this->nox_sensor_ != nullptr) { this->nox_sensor_->publish_state(nox); } - this->status_clear_warning(); + + if (!this->voc_sensor_ || !this->store_baseline_ || + (App.get_loop_component_start_time() - this->voc_baseline_time_) < SHORTEST_BASELINE_STORE_INTERVAL) { + this->status_clear_warning(); + } else { + this->voc_baseline_time_ = App.get_loop_component_start_time(); + if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE)) { + this->status_set_warning(); + ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); + } else { + this->set_timeout(20, [this]() { + if (!this->read_data(this->voc_baseline_state_, 4)) { + this->status_set_warning(); + ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); + } else { + if (this->pref_.save(&this->voc_baseline_state_)) { + ESP_LOGD(TAG, "VOC Baseline State saved"); + } + this->status_clear_warning(); + } + }); + } + } }); } diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index 9e5b6bf231..aaa672dbc4 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -24,11 +24,6 @@ enum RhtAccelerationMode : uint16_t { HIGH_ACCELERATION = 2, }; -struct Sen5xBaselines { - int32_t state0; - int32_t state1; -} PACKED; // NOLINT - struct GasTuning { uint16_t index_offset; uint16_t learning_time_offset_hours; @@ -44,11 +39,9 @@ struct TemperatureCompensation { uint16_t time_constant; }; -// Shortest time interval of 3H for storing baseline values. +// Shortest time interval of 2H (in milliseconds) for storing baseline values. // Prevents wear of the flash because of too many write operations -static const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 10800; -// Store anyway if the baseline difference exceeds the max storage diff value -static const uint32_t MAXIMUM_STORAGE_DIFF = 50; +static const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 2 * 60 * 60 * 1000; class SEN5XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { public: @@ -107,7 +100,8 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri bool write_tuning_parameters_(uint16_t i2c_command, const GasTuning &tuning); bool write_temperature_compensation_(const TemperatureCompensation &compensation); - uint32_t seconds_since_last_store_; + uint16_t voc_baseline_state_[4]{0}; + uint32_t voc_baseline_time_; uint16_t firmware_version_; ERRORCODE error_code_; uint8_t serial_number_[4]; @@ -132,7 +126,6 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri optional temperature_compensation_; ESPPreferenceObject pref_; std::string product_name_; - Sen5xBaselines voc_baselines_storage_; }; } // namespace sen5x diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 9c3114b9e2..538a2f5239 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -210,6 +210,7 @@ SENSOR_MAP = { SETTING_MAP = { CONF_AUTO_CLEANING_INTERVAL: "set_auto_cleaning_interval", CONF_ACCELERATION_MODE: "set_acceleration_mode", + CONF_STORE_BASELINE: "set_store_baseline", } From 069db2e12827b14e7eb88958104f715a85e77d1d Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 24 Jan 2026 11:44:34 +1100 Subject: [PATCH 0327/2030] [lvgl] Fix setting empty text (#13494) --- esphome/components/lvgl/widgets/label.py | 2 +- tests/components/lvgl/lvgl-package.yaml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/lvgl/widgets/label.py b/esphome/components/lvgl/widgets/label.py index 3a3a997737..8afd8d610f 100644 --- a/esphome/components/lvgl/widgets/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -32,7 +32,7 @@ class LabelType(WidgetType): async def to_code(self, w: Widget, config): """For a text object, create and set text""" - if value := config.get(CONF_TEXT): + if (value := config.get(CONF_TEXT)) is not None: await w.set_property(CONF_TEXT, await lv_text.process(value)) await w.set_property(CONF_LONG_MODE, config) await w.set_property(CONF_RECOLOR, config) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 65d629bcdf..3635fc710f 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -197,6 +197,9 @@ lvgl: - lvgl.label.update: id: msgbox_label text: Unloaded + - lvgl.label.update: + id: msgbox_label + text: "" # Empty text on_all_events: logger.log: format: "Event %s" From faea546a0e7b416bf8d9b23252e6f1d32c11ee86 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 23 Jan 2026 18:53:20 -0600 Subject: [PATCH 0328/2030] [light] Fix cwww state restore (#13493) --- esphome/components/light/light_call.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 234d641f0d..6d42dd1513 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -391,7 +391,10 @@ void LightCall::transform_parameters_() { min_mireds > 0.0f && max_mireds > 0.0f) { ESP_LOGD(TAG, "'%s': setting cold/warm white channels using white/color temperature values", this->parent_->get_name().c_str()); - if (this->has_color_temperature()) { + // Only compute cold_white/warm_white from color_temperature if they're not already explicitly set. + // This is important for state restoration, where both color_temperature and cold_white/warm_white + // are restored from flash - we want to preserve the saved cold_white/warm_white values. + if (this->has_color_temperature() && !this->has_cold_white() && !this->has_warm_white()) { const float color_temp = clamp(this->color_temperature_, min_mireds, max_mireds); const float range = max_mireds - min_mireds; const float ww_fraction = (color_temp - min_mireds) / range; From 9fddd0659ed2e6083e24630b7b6228542a19b855 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Fri, 23 Jan 2026 20:28:14 -0500 Subject: [PATCH 0329/2030] [bmp581] Split into `bmp581_base` and `bmp581_i2c` (#12485) Co-authored-by: Keith Burzinski --- CODEOWNERS | 3 +- esphome/components/bmp581/sensor.py | 165 +----------------- esphome/components/bmp581_base/__init__.py | 157 +++++++++++++++++ .../bmp581_base.cpp} | 35 ++-- .../bmp581.h => bmp581_base/bmp581_base.h} | 14 +- esphome/components/bmp581_i2c/__init__.py | 0 esphome/components/bmp581_i2c/bmp581_i2c.cpp | 12 ++ esphome/components/bmp581_i2c/bmp581_i2c.h | 24 +++ esphome/components/bmp581_i2c/sensor.py | 23 +++ .../{bmp581 => bmp581_i2c}/common.yaml | 2 +- .../test.esp32-idf.yaml | 0 .../test.esp8266-ard.yaml | 0 .../test.rp2040-ard.yaml | 0 13 files changed, 246 insertions(+), 189 deletions(-) create mode 100644 esphome/components/bmp581_base/__init__.py rename esphome/components/{bmp581/bmp581.cpp => bmp581_base/bmp581_base.cpp} (95%) rename esphome/components/{bmp581/bmp581.h => bmp581_base/bmp581_base.h} (95%) create mode 100644 esphome/components/bmp581_i2c/__init__.py create mode 100644 esphome/components/bmp581_i2c/bmp581_i2c.cpp create mode 100644 esphome/components/bmp581_i2c/bmp581_i2c.h create mode 100644 esphome/components/bmp581_i2c/sensor.py rename tests/components/{bmp581 => bmp581_i2c}/common.yaml (86%) rename tests/components/{bmp581 => bmp581_i2c}/test.esp32-idf.yaml (100%) rename tests/components/{bmp581 => bmp581_i2c}/test.esp8266-ard.yaml (100%) rename tests/components/{bmp581 => bmp581_i2c}/test.rp2040-ard.yaml (100%) diff --git a/CODEOWNERS b/CODEOWNERS index 8a37aeb29f..8537d451db 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -88,7 +88,8 @@ esphome/components/bmp3xx/* @latonita esphome/components/bmp3xx_base/* @latonita @martgras esphome/components/bmp3xx_i2c/* @latonita esphome/components/bmp3xx_spi/* @latonita -esphome/components/bmp581/* @kahrendt +esphome/components/bmp581_base/* @danielkent-net @kahrendt +esphome/components/bmp581_i2c/* @danielkent-net @kahrendt esphome/components/bp1658cj/* @Cossid esphome/components/bp5758d/* @Cossid esphome/components/bthome_mithermometer/* @nagyrobi diff --git a/esphome/components/bmp581/sensor.py b/esphome/components/bmp581/sensor.py index e2790f83b9..0dd06bfd36 100644 --- a/esphome/components/bmp581/sensor.py +++ b/esphome/components/bmp581/sensor.py @@ -1,164 +1,5 @@ -import math - -import esphome.codegen as cg -from esphome.components import i2c, sensor import esphome.config_validation as cv -from esphome.const import ( - CONF_ID, - CONF_IIR_FILTER, - CONF_OVERSAMPLING, - CONF_PRESSURE, - CONF_TEMPERATURE, - DEVICE_CLASS_ATMOSPHERIC_PRESSURE, - DEVICE_CLASS_TEMPERATURE, - STATE_CLASS_MEASUREMENT, - UNIT_CELSIUS, - UNIT_PASCAL, + +CONFIG_SCHEMA = cv.invalid( + "The bmp581 sensor component has been renamed to bmp581_i2c." ) - -CODEOWNERS = ["@kahrendt"] -DEPENDENCIES = ["i2c"] - -bmp581_ns = cg.esphome_ns.namespace("bmp581") - -Oversampling = bmp581_ns.enum("Oversampling") -OVERSAMPLING_OPTIONS = { - "NONE": Oversampling.OVERSAMPLING_NONE, - "2X": Oversampling.OVERSAMPLING_X2, - "4X": Oversampling.OVERSAMPLING_X4, - "8X": Oversampling.OVERSAMPLING_X8, - "16X": Oversampling.OVERSAMPLING_X16, - "32X": Oversampling.OVERSAMPLING_X32, - "64X": Oversampling.OVERSAMPLING_X64, - "128X": Oversampling.OVERSAMPLING_X128, -} - -IIRFilter = bmp581_ns.enum("IIRFilter") -IIR_FILTER_OPTIONS = { - "OFF": IIRFilter.IIR_FILTER_OFF, - "2X": IIRFilter.IIR_FILTER_2, - "4X": IIRFilter.IIR_FILTER_4, - "8X": IIRFilter.IIR_FILTER_8, - "16X": IIRFilter.IIR_FILTER_16, - "32X": IIRFilter.IIR_FILTER_32, - "64X": IIRFilter.IIR_FILTER_64, - "128X": IIRFilter.IIR_FILTER_128, -} - -BMP581Component = bmp581_ns.class_( - "BMP581Component", cg.PollingComponent, i2c.I2CDevice -) - - -def compute_measurement_conversion_time(config): - # - adds up sensor conversion time based on temperature and pressure oversampling rates given in datasheet - # - returns a rounded up time in ms - - # Page 12 of datasheet - PRESSURE_OVERSAMPLING_CONVERSION_TIMES = { - "NONE": 1.0, - "2X": 1.7, - "4X": 2.9, - "8X": 5.4, - "16X": 10.4, - "32X": 20.4, - "64X": 40.4, - "128X": 80.4, - } - - # Page 12 of datasheet - TEMPERATURE_OVERSAMPLING_CONVERSION_TIMES = { - "NONE": 1.0, - "2X": 1.1, - "4X": 1.5, - "8X": 2.1, - "16X": 3.3, - "32X": 5.8, - "64X": 10.8, - "128X": 20.8, - } - - pressure_conversion_time = ( - 0.0 # No conversion time necessary without a pressure sensor - ) - if pressure_config := config.get(CONF_PRESSURE): - pressure_conversion_time = PRESSURE_OVERSAMPLING_CONVERSION_TIMES[ - pressure_config.get(CONF_OVERSAMPLING) - ] - - temperature_conversion_time = ( - 1.0 # BMP581 always samples the temperature even if only reading pressure - ) - if temperature_config := config.get(CONF_TEMPERATURE): - temperature_conversion_time = TEMPERATURE_OVERSAMPLING_CONVERSION_TIMES[ - temperature_config.get(CONF_OVERSAMPLING) - ] - - # Datasheet indicates a 5% possible error in each conversion time listed - return math.ceil(1.05 * (pressure_conversion_time + temperature_conversion_time)) - - -CONFIG_SCHEMA = ( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(BMP581Component), - cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( - unit_of_measurement=UNIT_CELSIUS, - accuracy_decimals=1, - device_class=DEVICE_CLASS_TEMPERATURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.Optional(CONF_OVERSAMPLING, default="NONE"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( - IIR_FILTER_OPTIONS, upper=True - ), - } - ), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema( - unit_of_measurement=UNIT_PASCAL, - accuracy_decimals=0, - device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE, - state_class=STATE_CLASS_MEASUREMENT, - ).extend( - { - cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( - OVERSAMPLING_OPTIONS, upper=True - ), - cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( - IIR_FILTER_OPTIONS, upper=True - ), - } - ), - } - ) - .extend(cv.polling_component_schema("60s")) - .extend(i2c.i2c_device_schema(0x46)) -) - - -async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - await i2c.register_i2c_device(var, config) - if temperature_config := config.get(CONF_TEMPERATURE): - sens = await sensor.new_sensor(temperature_config) - cg.add(var.set_temperature_sensor(sens)) - cg.add( - var.set_temperature_oversampling_config( - temperature_config[CONF_OVERSAMPLING] - ) - ) - cg.add( - var.set_temperature_iir_filter_config(temperature_config[CONF_IIR_FILTER]) - ) - - if pressure_config := config.get(CONF_PRESSURE): - sens = await sensor.new_sensor(pressure_config) - cg.add(var.set_pressure_sensor(sens)) - cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING])) - cg.add(var.set_pressure_iir_filter_config(pressure_config[CONF_IIR_FILTER])) - - cg.add(var.set_conversion_time(compute_measurement_conversion_time(config))) diff --git a/esphome/components/bmp581_base/__init__.py b/esphome/components/bmp581_base/__init__.py new file mode 100644 index 0000000000..6a7cf45089 --- /dev/null +++ b/esphome/components/bmp581_base/__init__.py @@ -0,0 +1,157 @@ +import math + +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_IIR_FILTER, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PASCAL, +) + +CODEOWNERS = ["@kahrendt", "@danielkent-net"] + +bmp581_ns = cg.esphome_ns.namespace("bmp581_base") + +Oversampling = bmp581_ns.enum("Oversampling") +OVERSAMPLING_OPTIONS = { + "NONE": Oversampling.OVERSAMPLING_NONE, + "2X": Oversampling.OVERSAMPLING_X2, + "4X": Oversampling.OVERSAMPLING_X4, + "8X": Oversampling.OVERSAMPLING_X8, + "16X": Oversampling.OVERSAMPLING_X16, + "32X": Oversampling.OVERSAMPLING_X32, + "64X": Oversampling.OVERSAMPLING_X64, + "128X": Oversampling.OVERSAMPLING_X128, +} + +IIRFilter = bmp581_ns.enum("IIRFilter") +IIR_FILTER_OPTIONS = { + "OFF": IIRFilter.IIR_FILTER_OFF, + "2X": IIRFilter.IIR_FILTER_2, + "4X": IIRFilter.IIR_FILTER_4, + "8X": IIRFilter.IIR_FILTER_8, + "16X": IIRFilter.IIR_FILTER_16, + "32X": IIRFilter.IIR_FILTER_32, + "64X": IIRFilter.IIR_FILTER_64, + "128X": IIRFilter.IIR_FILTER_128, +} + +BMP581Component = bmp581_ns.class_("BMP581Component", cg.PollingComponent) + + +def compute_measurement_conversion_time(config): + # - adds up sensor conversion time based on temperature and pressure oversampling rates given in datasheet + # - returns a rounded up time in ms + + # Page 12 of datasheet + PRESSURE_OVERSAMPLING_CONVERSION_TIMES = { + "NONE": 1.0, + "2X": 1.7, + "4X": 2.9, + "8X": 5.4, + "16X": 10.4, + "32X": 20.4, + "64X": 40.4, + "128X": 80.4, + } + + # Page 12 of datasheet + TEMPERATURE_OVERSAMPLING_CONVERSION_TIMES = { + "NONE": 1.0, + "2X": 1.1, + "4X": 1.5, + "8X": 2.1, + "16X": 3.3, + "32X": 5.8, + "64X": 10.8, + "128X": 20.8, + } + + pressure_conversion_time = ( + 0.0 # No conversion time necessary without a pressure sensor + ) + if pressure_config := config.get(CONF_PRESSURE): + pressure_conversion_time = PRESSURE_OVERSAMPLING_CONVERSION_TIMES[ + pressure_config.get(CONF_OVERSAMPLING) + ] + + temperature_conversion_time = ( + 1.0 # BMP581 always samples the temperature even if only reading pressure + ) + if temperature_config := config.get(CONF_TEMPERATURE): + temperature_conversion_time = TEMPERATURE_OVERSAMPLING_CONVERSION_TIMES[ + temperature_config.get(CONF_OVERSAMPLING) + ] + + # Datasheet indicates a 5% possible error in each conversion time listed + return math.ceil(1.05 * (pressure_conversion_time + temperature_conversion_time)) + + +CONFIG_SCHEMA_BASE = cv.Schema( + { + cv.GenerateID(): cv.declare_id(BMP581Component), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="NONE"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( + IIR_FILTER_OPTIONS, upper=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_PASCAL, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( + IIR_FILTER_OPTIONS, upper=True + ), + } + ), + } +).extend(cv.polling_component_schema("60s")) + + +async def to_code_base(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature_sensor(sens)) + cg.add( + var.set_temperature_oversampling_config( + temperature_config[CONF_OVERSAMPLING] + ) + ) + cg.add( + var.set_temperature_iir_filter_config(temperature_config[CONF_IIR_FILTER]) + ) + + if pressure_config := config.get(CONF_PRESSURE): + sens = await sensor.new_sensor(pressure_config) + cg.add(var.set_pressure_sensor(sens)) + cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING])) + cg.add(var.set_pressure_iir_filter_config(pressure_config[CONF_IIR_FILTER])) + + cg.add(var.set_conversion_time(compute_measurement_conversion_time(config))) + return var diff --git a/esphome/components/bmp581/bmp581.cpp b/esphome/components/bmp581_base/bmp581_base.cpp similarity index 95% rename from esphome/components/bmp581/bmp581.cpp rename to esphome/components/bmp581_base/bmp581_base.cpp index 301fc31df0..67c6771862 100644 --- a/esphome/components/bmp581/bmp581.cpp +++ b/esphome/components/bmp581_base/bmp581_base.cpp @@ -10,12 +10,11 @@ * - All datasheet page references refer to Bosch Document Number BST-BMP581-DS004-04 (revision number 1.4) */ -#include "bmp581.h" +#include "bmp581_base.h" #include "esphome/core/log.h" #include "esphome/core/hal.h" -namespace esphome { -namespace bmp581 { +namespace esphome::bmp581_base { static const char *const TAG = "bmp581"; @@ -91,7 +90,6 @@ void BMP581Component::dump_config() { break; } - LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); ESP_LOGCONFIG(TAG, " Measurement conversion time: %ums", this->conversion_time_); @@ -149,7 +147,7 @@ void BMP581Component::setup() { uint8_t chip_id; // read chip id from sensor - if (!this->read_byte(BMP581_CHIP_ID, &chip_id)) { + if (!this->bmp_read_byte(BMP581_CHIP_ID, &chip_id)) { ESP_LOGE(TAG, "Read chip ID failed"); this->error_code_ = ERROR_COMMUNICATION_FAILED; @@ -172,7 +170,7 @@ void BMP581Component::setup() { // 3) Verify sensor status (check if NVM is okay) // //////////////////////////////////////////////////// - if (!this->read_byte(BMP581_STATUS, &this->status_.reg)) { + if (!this->bmp_read_byte(BMP581_STATUS, &this->status_.reg)) { ESP_LOGE(TAG, "Failed to read status register"); this->error_code_ = ERROR_COMMUNICATION_FAILED; @@ -359,7 +357,7 @@ bool BMP581Component::check_data_readiness_() { uint8_t status; - if (!this->read_byte(BMP581_INT_STATUS, &status)) { + if (!this->bmp_read_byte(BMP581_INT_STATUS, &status)) { ESP_LOGE(TAG, "Failed to read interrupt status register"); return false; } @@ -400,7 +398,7 @@ bool BMP581Component::prime_iir_filter_() { // flush the IIR filter with forced measurements (we will only flush once) this->dsp_config_.bit.iir_flush_forced_en = true; - if (!this->write_byte(BMP581_DSP, this->dsp_config_.reg)) { + if (!this->bmp_write_byte(BMP581_DSP, this->dsp_config_.reg)) { ESP_LOGE(TAG, "Failed to write IIR source register"); return false; @@ -430,7 +428,7 @@ bool BMP581Component::prime_iir_filter_() { // disable IIR filter flushings on future forced measurements this->dsp_config_.bit.iir_flush_forced_en = false; - if (!this->write_byte(BMP581_DSP, this->dsp_config_.reg)) { + if (!this->bmp_write_byte(BMP581_DSP, this->dsp_config_.reg)) { ESP_LOGE(TAG, "Failed to write IIR source register"); return false; @@ -454,7 +452,7 @@ bool BMP581Component::read_temperature_(float &temperature) { } uint8_t data[3]; - if (!this->read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 3)) { + if (!this->bmp_read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 3)) { ESP_LOGW(TAG, "Failed to read measurement"); this->status_set_warning(); @@ -483,7 +481,7 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float & } uint8_t data[6]; - if (!this->read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 6)) { + if (!this->bmp_read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 6)) { ESP_LOGW(TAG, "Failed to read measurement"); this->status_set_warning(); @@ -507,7 +505,7 @@ bool BMP581Component::reset_() { // - returns the Power-On-Reboot interrupt status, which is asserted if successful // writes reset command to BMP's command register - if (!this->write_byte(BMP581_COMMAND, RESET_COMMAND)) { + if (!this->bmp_write_byte(BMP581_COMMAND, RESET_COMMAND)) { ESP_LOGE(TAG, "Failed to write reset command"); return false; @@ -518,7 +516,7 @@ bool BMP581Component::reset_() { delay(3); // read interrupt status register - if (!this->read_byte(BMP581_INT_STATUS, &this->int_status_.reg)) { + if (!this->bmp_read_byte(BMP581_INT_STATUS, &this->int_status_.reg)) { ESP_LOGE(TAG, "Failed to read interrupt status register"); return false; @@ -562,7 +560,7 @@ bool BMP581Component::write_iir_settings_(IIRFilter temperature_iir, IIRFilter p // BMP581_DSP register and BMP581_DSP_IIR registers are successive // - allows us to write the IIR configuration with one command to both registers uint8_t register_data[2] = {this->dsp_config_.reg, this->iir_config_.reg}; - return this->write_bytes(BMP581_DSP, register_data, sizeof(register_data)); + return this->bmp_write_bytes(BMP581_DSP, register_data, sizeof(register_data)); } bool BMP581Component::write_interrupt_source_settings_(bool data_ready_enable) { @@ -572,7 +570,7 @@ bool BMP581Component::write_interrupt_source_settings_(bool data_ready_enable) { this->int_source_.bit.drdy_data_reg_en = data_ready_enable; // write interrupt source register - return this->write_byte(BMP581_INT_SOURCE, this->int_source_.reg); + return this->bmp_write_byte(BMP581_INT_SOURCE, this->int_source_.reg); } bool BMP581Component::write_oversampling_settings_(Oversampling temperature_oversampling, @@ -583,7 +581,7 @@ bool BMP581Component::write_oversampling_settings_(Oversampling temperature_over this->osr_config_.bit.osr_t = temperature_oversampling; this->osr_config_.bit.osr_p = pressure_oversampling; - return this->write_byte(BMP581_OSR, this->osr_config_.reg); + return this->bmp_write_byte(BMP581_OSR, this->osr_config_.reg); } bool BMP581Component::write_power_mode_(OperationMode mode) { @@ -593,8 +591,7 @@ bool BMP581Component::write_power_mode_(OperationMode mode) { this->odr_config_.bit.pwr_mode = mode; // write odr register - return this->write_byte(BMP581_ODR, this->odr_config_.reg); + return this->bmp_write_byte(BMP581_ODR, this->odr_config_.reg); } -} // namespace bmp581 -} // namespace esphome +} // namespace esphome::bmp581_base diff --git a/esphome/components/bmp581/bmp581.h b/esphome/components/bmp581_base/bmp581_base.h similarity index 95% rename from esphome/components/bmp581/bmp581.h rename to esphome/components/bmp581_base/bmp581_base.h index 1d7e932fa1..d99c420272 100644 --- a/esphome/components/bmp581/bmp581.h +++ b/esphome/components/bmp581_base/bmp581_base.h @@ -3,11 +3,9 @@ #pragma once #include "esphome/core/component.h" -#include "esphome/components/i2c/i2c.h" #include "esphome/components/sensor/sensor.h" -namespace esphome { -namespace bmp581 { +namespace esphome::bmp581_base { static const uint8_t BMP581_ASIC_ID = 0x50; // BMP581's ASIC chip ID (page 51 of datasheet) static const uint8_t RESET_COMMAND = 0xB6; // Soft reset command @@ -59,7 +57,7 @@ enum IIRFilter { IIR_FILTER_128 = 0x7 }; -class BMP581Component : public PollingComponent, public i2c::I2CDevice { +class BMP581Component : public PollingComponent { public: void dump_config() override; @@ -84,6 +82,11 @@ class BMP581Component : public PollingComponent, public i2c::I2CDevice { void set_conversion_time(uint8_t conversion_time) { this->conversion_time_ = conversion_time; } protected: + virtual bool bmp_read_byte(uint8_t a_register, uint8_t *data) = 0; + virtual bool bmp_write_byte(uint8_t a_register, uint8_t data) = 0; + virtual bool bmp_read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + virtual bool bmp_write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *pressure_sensor_{nullptr}; @@ -216,5 +219,4 @@ class BMP581Component : public PollingComponent, public i2c::I2CDevice { } odr_config_ = {.reg = 0}; }; -} // namespace bmp581 -} // namespace esphome +} // namespace esphome::bmp581_base diff --git a/esphome/components/bmp581_i2c/__init__.py b/esphome/components/bmp581_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp581_i2c/bmp581_i2c.cpp b/esphome/components/bmp581_i2c/bmp581_i2c.cpp new file mode 100644 index 0000000000..8df4610e0b --- /dev/null +++ b/esphome/components/bmp581_i2c/bmp581_i2c.cpp @@ -0,0 +1,12 @@ +#include "bmp581_i2c.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome::bmp581_i2c { + +void BMP581I2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + BMP581Component::dump_config(); +} + +} // namespace esphome::bmp581_i2c diff --git a/esphome/components/bmp581_i2c/bmp581_i2c.h b/esphome/components/bmp581_i2c/bmp581_i2c.h new file mode 100644 index 0000000000..a4e43daf64 --- /dev/null +++ b/esphome/components/bmp581_i2c/bmp581_i2c.h @@ -0,0 +1,24 @@ +#pragma once + +#include "esphome/components/bmp581_base/bmp581_base.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome::bmp581_i2c { + +static const char *const TAG = "bmp581_i2c.sensor"; + +/// This class implements support for the BMP581 Temperature+Pressure i2c sensor. +class BMP581I2CComponent : public esphome::bmp581_base::BMP581Component, public i2c::I2CDevice { + public: + bool bmp_read_byte(uint8_t a_register, uint8_t *data) override { return read_byte(a_register, data); } + bool bmp_write_byte(uint8_t a_register, uint8_t data) override { return write_byte(a_register, data); } + bool bmp_read_bytes(uint8_t a_register, uint8_t *data, size_t len) override { + return read_bytes(a_register, data, len); + } + bool bmp_write_bytes(uint8_t a_register, uint8_t *data, size_t len) override { + return write_bytes(a_register, data, len); + } + void dump_config() override; +}; + +} // namespace esphome::bmp581_i2c diff --git a/esphome/components/bmp581_i2c/sensor.py b/esphome/components/bmp581_i2c/sensor.py new file mode 100644 index 0000000000..42645022a6 --- /dev/null +++ b/esphome/components/bmp581_i2c/sensor.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +from esphome.components import i2c +import esphome.config_validation as cv + +from ..bmp581_base import CONFIG_SCHEMA_BASE, to_code_base + +AUTO_LOAD = ["bmp581_base"] +CODEOWNERS = ["@kahrendt", "@danielkent-net"] +DEPENDENCIES = ["i2c"] + +bmp581_ns = cg.esphome_ns.namespace("bmp581_i2c") +BMP581I2CComponent = bmp581_ns.class_( + "BMP581I2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x46) +).extend({cv.GenerateID(): cv.declare_id(BMP581I2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/tests/components/bmp581/common.yaml b/tests/components/bmp581_i2c/common.yaml similarity index 86% rename from tests/components/bmp581/common.yaml rename to tests/components/bmp581_i2c/common.yaml index 250b1f5857..258d8a5020 100644 --- a/tests/components/bmp581/common.yaml +++ b/tests/components/bmp581_i2c/common.yaml @@ -1,5 +1,5 @@ sensor: - - platform: bmp581 + - platform: bmp581_i2c i2c_id: i2c_bus temperature: name: BMP581 Temperature diff --git a/tests/components/bmp581/test.esp32-idf.yaml b/tests/components/bmp581_i2c/test.esp32-idf.yaml similarity index 100% rename from tests/components/bmp581/test.esp32-idf.yaml rename to tests/components/bmp581_i2c/test.esp32-idf.yaml diff --git a/tests/components/bmp581/test.esp8266-ard.yaml b/tests/components/bmp581_i2c/test.esp8266-ard.yaml similarity index 100% rename from tests/components/bmp581/test.esp8266-ard.yaml rename to tests/components/bmp581_i2c/test.esp8266-ard.yaml diff --git a/tests/components/bmp581/test.rp2040-ard.yaml b/tests/components/bmp581_i2c/test.rp2040-ard.yaml similarity index 100% rename from tests/components/bmp581/test.rp2040-ard.yaml rename to tests/components/bmp581_i2c/test.rp2040-ard.yaml From e4763f8e7192d691df17249d8cd4293e19ba1609 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:12:17 -1000 Subject: [PATCH 0330/2030] Bump ruff from 0.14.13 to 0.14.14 (#13487) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06f9bf2a5b..b068673ecf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.14.13 + rev: v0.14.14 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index d93a5d108f..5d90764021 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.13 # also change in .pre-commit-config.yaml when updating +ruff==0.14.14 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From 165e362a1bd8db14f23bd24cb1eba97192edcb82 Mon Sep 17 00:00:00 2001 From: Big Mike Date: Fri, 23 Jan 2026 20:19:41 -0600 Subject: [PATCH 0331/2030] [sensirion_common] Fix incorrect Big Endian conversion (#13492) --- esphome/components/sensirion_common/i2c_sensirion.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/esphome/components/sensirion_common/i2c_sensirion.cpp b/esphome/components/sensirion_common/i2c_sensirion.cpp index 9eac6b4525..e39a3ce0a0 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.cpp +++ b/esphome/components/sensirion_common/i2c_sensirion.cpp @@ -57,24 +57,14 @@ bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len temp[raw_idx++] = command & 0xFF; } else { // command is 2 bytes -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ temp[raw_idx++] = command >> 8; temp[raw_idx++] = command & 0xFF; -#else - temp[raw_idx++] = command & 0xFF; - temp[raw_idx++] = command >> 8; -#endif } // add parameters followed by crc // skipped if len == 0 for (size_t i = 0; i < data_len; i++) { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ temp[raw_idx++] = data[i] >> 8; temp[raw_idx++] = data[i] & 0xFF; -#else - temp[raw_idx++] = data[i] & 0xFF; - temp[raw_idx++] = data[i] >> 8; -#endif // Use MSB first since Sensirion devices use CRC-8 with MSB first uint8_t crc = crc8(&temp[raw_idx - 2], 2, 0xFF, CRC_POLYNOMIAL, true); temp[raw_idx++] = crc; From 42e50ca1789956668e3daf1038d7d942f0f77fd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 16:26:11 -1000 Subject: [PATCH 0332/2030] Bump github/codeql-action from 4.31.10 to 4.31.11 (#13488) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f043cc5ca6..15edd8421a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 + uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 with: category: "/language:${{matrix.language}}" From bba00a3906c150b1062a0b2c2ab650949d9cdef0 Mon Sep 17 00:00:00 2001 From: Jas Strong Date: Fri, 23 Jan 2026 19:01:19 -0800 Subject: [PATCH 0333/2030] [rd03d] Fix speed and resolution field order (#13495) Co-authored-by: jas --- esphome/components/rd03d/rd03d.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index d9b0b59fe9..ba05abe8e0 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -133,14 +133,17 @@ void RD03DComponent::process_frame_() { uint8_t offset = FRAME_HEADER_SIZE + (i * TARGET_DATA_SIZE); // Extract raw bytes for this target + // Note: Despite datasheet Table 5-2 showing order as X, Y, Speed, Resolution, + // actual radar output has Resolution before Speed (verified empirically - + // stationary targets were showing non-zero speed with original field order) uint8_t x_low = this->buffer_[offset + 0]; uint8_t x_high = this->buffer_[offset + 1]; uint8_t y_low = this->buffer_[offset + 2]; uint8_t y_high = this->buffer_[offset + 3]; - uint8_t speed_low = this->buffer_[offset + 4]; - uint8_t speed_high = this->buffer_[offset + 5]; - uint8_t res_low = this->buffer_[offset + 6]; - uint8_t res_high = this->buffer_[offset + 7]; + uint8_t res_low = this->buffer_[offset + 4]; + uint8_t res_high = this->buffer_[offset + 5]; + uint8_t speed_low = this->buffer_[offset + 6]; + uint8_t speed_high = this->buffer_[offset + 7]; // Decode values per RD-03D format int16_t x = decode_value(x_low, x_high); From cdda3fb7cc38aca7284ede6cdd0d8899e5cfdd42 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 23 Jan 2026 22:01:40 -0500 Subject: [PATCH 0334/2030] [modbus_controller] Fix YAML serialization error with custom_command (#13482) Co-authored-by: Claude Opus 4.5 --- esphome/components/modbus_controller/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 1c23783ce3..c45c338bb3 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -279,7 +279,7 @@ def modbus_calc_properties(config): if isinstance(value, str): value = value.encode() config[CONF_ADDRESS] = binascii.crc_hqx(value, 0) - config[CONF_REGISTER_TYPE] = ModbusRegisterType.CUSTOM + config[CONF_REGISTER_TYPE] = cv.enum(MODBUS_REGISTER_TYPE)("custom") config[CONF_FORCE_NEW_RANGE] = True return byte_offset, reg_count From beb9c8d32890436adb414537508e411d6b35def0 Mon Sep 17 00:00:00 2001 From: Big Mike Date: Fri, 23 Jan 2026 21:04:09 -0600 Subject: [PATCH 0335/2030] [sen5x] Fix missing this-> on class members and member functions (#13497) --- esphome/components/sen5x/sen5x.cpp | 4 ++-- esphome/components/sen5x/sen5x.h | 30 ++++++++++++++++-------------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index 09d93a2b2f..ea08a5ee77 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -173,9 +173,9 @@ void SEN5XComponent::setup() { bool result; if (this->auto_cleaning_interval_.has_value()) { // override default value - result = write_command(SEN5X_CMD_AUTO_CLEANING_INTERVAL, this->auto_cleaning_interval_.value()); + result = this->write_command(SEN5X_CMD_AUTO_CLEANING_INTERVAL, this->auto_cleaning_interval_.value()); } else { - result = write_command(SEN5X_CMD_AUTO_CLEANING_INTERVAL); + result = this->write_command(SEN5X_CMD_AUTO_CLEANING_INTERVAL); } if (result) { delay(20); diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index aaa672dbc4..aacdfa5717 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -51,18 +51,20 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri enum Sen5xType { SEN50, SEN54, SEN55, UNKNOWN }; - void set_pm_1_0_sensor(sensor::Sensor *pm_1_0) { pm_1_0_sensor_ = pm_1_0; } - void set_pm_2_5_sensor(sensor::Sensor *pm_2_5) { pm_2_5_sensor_ = pm_2_5; } - void set_pm_4_0_sensor(sensor::Sensor *pm_4_0) { pm_4_0_sensor_ = pm_4_0; } - void set_pm_10_0_sensor(sensor::Sensor *pm_10_0) { pm_10_0_sensor_ = pm_10_0; } + void set_pm_1_0_sensor(sensor::Sensor *pm_1_0) { this->pm_1_0_sensor_ = pm_1_0; } + void set_pm_2_5_sensor(sensor::Sensor *pm_2_5) { this->pm_2_5_sensor_ = pm_2_5; } + void set_pm_4_0_sensor(sensor::Sensor *pm_4_0) { this->pm_4_0_sensor_ = pm_4_0; } + void set_pm_10_0_sensor(sensor::Sensor *pm_10_0) { this->pm_10_0_sensor_ = pm_10_0; } - void set_voc_sensor(sensor::Sensor *voc_sensor) { voc_sensor_ = voc_sensor; } - void set_nox_sensor(sensor::Sensor *nox_sensor) { nox_sensor_ = nox_sensor; } - void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } - void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } - void set_store_baseline(bool store_baseline) { store_baseline_ = store_baseline; } - void set_acceleration_mode(RhtAccelerationMode mode) { acceleration_mode_ = mode; } - void set_auto_cleaning_interval(uint32_t auto_cleaning_interval) { auto_cleaning_interval_ = auto_cleaning_interval; } + void set_voc_sensor(sensor::Sensor *voc_sensor) { this->voc_sensor_ = voc_sensor; } + void set_nox_sensor(sensor::Sensor *nox_sensor) { this->nox_sensor_ = nox_sensor; } + void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } + void set_store_baseline(bool store_baseline) { this->store_baseline_ = store_baseline; } + void set_acceleration_mode(RhtAccelerationMode mode) { this->acceleration_mode_ = mode; } + void set_auto_cleaning_interval(uint32_t auto_cleaning_interval) { + this->auto_cleaning_interval_ = auto_cleaning_interval; + } void set_voc_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours, uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes, uint16_t std_initial, uint16_t gain_factor) { @@ -73,7 +75,7 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri tuning_params.gating_max_duration_minutes = gating_max_duration_minutes; tuning_params.std_initial = std_initial; tuning_params.gain_factor = gain_factor; - voc_tuning_params_ = tuning_params; + this->voc_tuning_params_ = tuning_params; } void set_nox_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours, uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes, @@ -85,14 +87,14 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri tuning_params.gating_max_duration_minutes = gating_max_duration_minutes; tuning_params.std_initial = 50; tuning_params.gain_factor = gain_factor; - nox_tuning_params_ = tuning_params; + this->nox_tuning_params_ = tuning_params; } void set_temperature_compensation(float offset, float normalized_offset_slope, uint16_t time_constant) { TemperatureCompensation temp_comp; temp_comp.offset = offset * 200; temp_comp.normalized_offset_slope = normalized_offset_slope * 10000; temp_comp.time_constant = time_constant; - temperature_compensation_ = temp_comp; + this->temperature_compensation_ = temp_comp; } bool start_fan_cleaning(); From 468ae39a9ec3eebb9ce80dc06c985af2f9f9db96 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 23 Jan 2026 23:13:03 -0500 Subject: [PATCH 0336/2030] [i2c] Increase ESP-IDF I2C transaction timeout from 20ms to 100ms (#13483) Co-authored-by: Claude Opus 4.5 --- esphome/components/i2c/i2c_bus_esp_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index 191c849aa3..7a965ce5ad 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -185,7 +185,7 @@ ErrorCode IDFI2CBus::write_readv(uint8_t address, const uint8_t *write_buffer, s } jobs[num_jobs++].command = I2C_MASTER_CMD_STOP; ESP_LOGV(TAG, "Sending %zu jobs", num_jobs); - esp_err_t err = i2c_master_execute_defined_operations(this->dev_, jobs, num_jobs, 20); + esp_err_t err = i2c_master_execute_defined_operations(this->dev_, jobs, num_jobs, 100); if (err == ESP_ERR_INVALID_STATE) { ESP_LOGV(TAG, "TX to %02X failed: not acked", address); return ERROR_NOT_ACKNOWLEDGED; From 30584e2e96f9dea57b8c61a3c6960402a35c84eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 23 Jan 2026 18:53:44 -1000 Subject: [PATCH 0337/2030] [sensirion_common] Use SmallBufferWithHeapFallback helper (#13496) --- .../components/sensirion_common/i2c_sensirion.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/esphome/components/sensirion_common/i2c_sensirion.cpp b/esphome/components/sensirion_common/i2c_sensirion.cpp index e39a3ce0a0..26702c148c 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.cpp +++ b/esphome/components/sensirion_common/i2c_sensirion.cpp @@ -39,18 +39,9 @@ bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) { */ bool SensirionI2CDevice::write_command_(uint16_t command, CommandLen command_len, const uint16_t *data, const uint8_t data_len) { - uint8_t temp_stack[BUFFER_STACK_SIZE]; - std::unique_ptr temp_heap; - uint8_t *temp; size_t required_buffer_len = data_len * 3 + 2; - - // Is a dynamic allocation required ? - if (required_buffer_len >= BUFFER_STACK_SIZE) { - temp_heap = std::unique_ptr(new uint8_t[required_buffer_len]); - temp = temp_heap.get(); - } else { - temp = temp_stack; - } + SmallBufferWithHeapFallback buffer(required_buffer_len); + uint8_t *temp = buffer.get(); // First byte or word is the command uint8_t raw_idx = 0; if (command_len == 1) { From 60968d311bbaee2aa16a5417f8dbb0c73fb21930 Mon Sep 17 00:00:00 2001 From: Peter Meiser Date: Sat, 24 Jan 2026 07:20:18 +0100 Subject: [PATCH 0338/2030] [thermostat] make comparisons consistent with documentation (#13499) --- .../thermostat/thermostat_climate.cpp | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 0416438dcd..44087969b5 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -1060,11 +1060,11 @@ bool ThermostatClimate::cooling_required_() { auto temperature = this->supports_two_points_ ? this->target_temperature_high : this->target_temperature; if (this->supports_cool_) { - if (this->current_temperature > temperature + this->cooling_deadband_) { - // if the current temperature exceeds the target + deadband, cooling is required + if (this->current_temperature >= temperature + this->cooling_deadband_) { + // if the current temperature reaches or exceeds the target + deadband, cooling is required return true; - } else if (this->current_temperature < temperature - this->cooling_overrun_) { - // if the current temperature is less than the target - overrun, cooling should stop + } else if (this->current_temperature <= temperature - this->cooling_overrun_) { + // if the current temperature is less than or equal to the target - overrun, cooling should stop return false; } else { // if we get here, the current temperature is between target + deadband and target - overrun, @@ -1081,11 +1081,11 @@ bool ThermostatClimate::fanning_required_() { if (this->supports_fan_only_) { if (this->supports_fan_only_cooling_) { - if (this->current_temperature > temperature + this->cooling_deadband_) { - // if the current temperature exceeds the target + deadband, fanning is required + if (this->current_temperature >= temperature + this->cooling_deadband_) { + // if the current temperature reaches or exceeds the target + deadband, fanning is required return true; - } else if (this->current_temperature < temperature - this->cooling_overrun_) { - // if the current temperature is less than the target - overrun, fanning should stop + } else if (this->current_temperature <= temperature - this->cooling_overrun_) { + // if the current temperature is less than or equal to the target - overrun, fanning should stop return false; } else { // if we get here, the current temperature is between target + deadband and target - overrun, @@ -1103,11 +1103,12 @@ bool ThermostatClimate::heating_required_() { auto temperature = this->supports_two_points_ ? this->target_temperature_low : this->target_temperature; if (this->supports_heat_) { - if (this->current_temperature < temperature - this->heating_deadband_) { - // if the current temperature is below the target - deadband, heating is required + if (this->current_temperature <= temperature - this->heating_deadband_) { + // if the current temperature is below or equal to the target - deadband, heating is required return true; - } else if (this->current_temperature > temperature + this->heating_overrun_) { - // if the current temperature is above the target + overrun, heating should stop + } else if (this->current_temperature >= temperature + this->heating_overrun_) { + // if the current temperature is above or equal to the target + overrun, heating should stop + return false; } else { // if we get here, the current temperature is between target - deadband and target + overrun, From f93e84397272b811825ed55420022f74222250cc Mon Sep 17 00:00:00 2001 From: Big Mike Date: Sat, 24 Jan 2026 13:55:51 -0600 Subject: [PATCH 0339/2030] [sen5x] Fix mangled serial number (#13491) --- esphome/components/sen5x/sen5x.cpp | 36 +++++++++++++++++------------- esphome/components/sen5x/sen5x.h | 2 +- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index ea08a5ee77..b23837f2b1 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -43,6 +43,15 @@ static const LogString *rht_accel_mode_to_string(RhtAccelerationMode mode) { } } +// This function performs an in-place conversion of the provided buffer +// from uint16_t values to big endianness +static inline const char *sensirion_convert_to_string_in_place(uint16_t *array, size_t length) { + for (size_t i = 0; i < length; i++) { + array[i] = convert_big_endian(array[i]); + } + return reinterpret_cast(array); +} + void SEN5XComponent::setup() { // the sensor needs 1000 ms to enter the idle state this->set_timeout(1000, [this]() { @@ -75,18 +84,18 @@ void SEN5XComponent::setup() { stop_measurement_delay = 200; } this->set_timeout(stop_measurement_delay, [this]() { - uint16_t raw_serial_number[3]; - if (!this->get_register(SEN5X_CMD_GET_SERIAL_NUMBER, raw_serial_number, 3, 20)) { + // note: serial number register is actually 32-bytes long but we grab only the first 16-bytes, + // this appears to be all that Sensirion uses for serial numbers, this could change + uint16_t raw_serial_number[8]; + if (!this->get_register(SEN5X_CMD_GET_SERIAL_NUMBER, raw_serial_number, 8, 20)) { ESP_LOGE(TAG, "Failed to read serial number"); this->error_code_ = SERIAL_NUMBER_IDENTIFICATION_FAILED; this->mark_failed(); return; } - this->serial_number_[0] = static_cast(uint16_t(raw_serial_number[0]) & 0xFF); - this->serial_number_[1] = static_cast(raw_serial_number[0] & 0xFF); - this->serial_number_[2] = static_cast(raw_serial_number[1] >> 8); - ESP_LOGV(TAG, "Serial number %02d.%02d.%02d", this->serial_number_[0], this->serial_number_[1], - this->serial_number_[2]); + const char *serial_number = sensirion_convert_to_string_in_place(raw_serial_number, 8); + snprintf(this->serial_number_, sizeof(this->serial_number_), "%s", serial_number); + ESP_LOGV(TAG, "Serial number %s", this->serial_number_); uint16_t raw_product_name[16]; if (!this->get_register(SEN5X_CMD_GET_PRODUCT_NAME, raw_product_name, 16, 20)) { @@ -153,12 +162,8 @@ void SEN5XComponent::setup() { ESP_LOGV(TAG, "Firmware version %d", this->firmware_version_); if (this->voc_sensor_ && this->store_baseline_) { - uint32_t combined_serial = - encode_uint24(this->serial_number_[0], this->serial_number_[1], this->serial_number_[2]); - // Hash with config hash, version, and serial number - // This ensures the baseline storage is cleared after OTA - // Serial numbers are unique to each sensor, so multiple sensors can be used without conflict - uint32_t hash = fnv1a_hash_extend(App.get_config_version_hash(), combined_serial); + // Hash with serial number, serial numbers are unique, so multiple sensors can be used without conflict + uint32_t hash = fnv1a_hash(this->serial_number_); this->pref_ = global_preferences->make_preference(hash, true); this->voc_baseline_time_ = App.get_loop_component_start_time(); if (this->pref_.load(&this->voc_baseline_state_)) { @@ -264,9 +269,8 @@ void SEN5XComponent::dump_config() { ESP_LOGCONFIG(TAG, " Product name: %s\n" " Firmware version: %d\n" - " Serial number %02d.%02d.%02d", - this->product_name_.c_str(), this->firmware_version_, this->serial_number_[0], this->serial_number_[1], - this->serial_number_[2]); + " Serial number: %s", + this->product_name_.c_str(), this->firmware_version_, this->serial_number_); if (this->auto_cleaning_interval_.has_value()) { ESP_LOGCONFIG(TAG, " Auto cleaning interval: %" PRId32 "s", this->auto_cleaning_interval_.value()); } diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index aacdfa5717..822160833e 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -102,11 +102,11 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri bool write_tuning_parameters_(uint16_t i2c_command, const GasTuning &tuning); bool write_temperature_compensation_(const TemperatureCompensation &compensation); + char serial_number_[17] = "UNKNOWN"; uint16_t voc_baseline_state_[4]{0}; uint32_t voc_baseline_time_; uint16_t firmware_version_; ERRORCODE error_code_; - uint8_t serial_number_[4]; bool initialized_{false}; bool store_baseline_; From 58746b737fb58c81df860360e469629452ef1e28 Mon Sep 17 00:00:00 2001 From: Big Mike Date: Sat, 24 Jan 2026 15:07:12 -0600 Subject: [PATCH 0340/2030] [sen5x] Eliminate product name string (#13489) --- esphome/components/sen5x/sen5x.cpp | 68 +++++++++++++++--------------- esphome/components/sen5x/sen5x.h | 6 +-- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index b23837f2b1..fc4932d867 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -30,6 +30,19 @@ static const int8_t SEN5X_INDEX_SCALE_FACTOR = 10; // static const int8_t SEN5X_MIN_INDEX_VALUE = 1 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor static const int16_t SEN5X_MAX_INDEX_VALUE = 500 * SEN5X_INDEX_SCALE_FACTOR; // must be adjusted by the scale factor +static const LogString *type_to_string(Sen5xType type) { + switch (type) { + case Sen5xType::SEN50: + return LOG_STR("SEN50"); + case Sen5xType::SEN54: + return LOG_STR("SEN54"); + case Sen5xType::SEN55: + return LOG_STR("SEN55"); + default: + return LOG_STR("UNKNOWN"); + } +} + static const LogString *rht_accel_mode_to_string(RhtAccelerationMode mode) { switch (mode) { case LOW_ACCELERATION: @@ -104,50 +117,35 @@ void SEN5XComponent::setup() { this->mark_failed(); return; } - // 2 ASCII bytes are encoded in an int - const uint16_t *current_int = raw_product_name; - char current_char; - uint8_t max = 16; - do { - // first char - current_char = *current_int >> 8; - if (current_char) { - this->product_name_.push_back(current_char); - // second char - current_char = *current_int & 0xFF; - if (current_char) { - this->product_name_.push_back(current_char); - } - } - current_int++; - } while (current_char && --max); - - Sen5xType sen5x_type = UNKNOWN; - if (this->product_name_ == "SEN50") { - sen5x_type = SEN50; + const char *product_name = sensirion_convert_to_string_in_place(raw_product_name, 16); + if (strncmp(product_name, "SEN50", 5) == 0) { + this->type_ = Sen5xType::SEN50; + } else if (strncmp(product_name, "SEN54", 5) == 0) { + this->type_ = Sen5xType::SEN54; + } else if (strncmp(product_name, "SEN55", 5) == 0) { + this->type_ = Sen5xType::SEN55; } else { - if (this->product_name_ == "SEN54") { - sen5x_type = SEN54; - } else { - if (this->product_name_ == "SEN55") { - sen5x_type = SEN55; - } - } + this->type_ = Sen5xType::UNKNOWN; + ESP_LOGE(TAG, "Unknown product name: %.32s", product_name); + this->error_code_ = PRODUCT_NAME_FAILED; + this->mark_failed(); + return; } - ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); - if (this->humidity_sensor_ && sen5x_type == SEN50) { + + ESP_LOGD(TAG, "Type: %s", LOG_STR_ARG(type_to_string(this->type_))); + if (this->humidity_sensor_ && this->type_ == Sen5xType::SEN50) { ESP_LOGE(TAG, "Relative humidity requires a SEN54 or SEN55"); this->humidity_sensor_ = nullptr; // mark as not used } - if (this->temperature_sensor_ && sen5x_type == SEN50) { + if (this->temperature_sensor_ && this->type_ == Sen5xType::SEN50) { ESP_LOGE(TAG, "Temperature requires a SEN54 or SEN55"); this->temperature_sensor_ = nullptr; // mark as not used } - if (this->voc_sensor_ && sen5x_type == SEN50) { + if (this->voc_sensor_ && this->type_ == Sen5xType::SEN50) { ESP_LOGE(TAG, "VOC requires a SEN54 or SEN55"); this->voc_sensor_ = nullptr; // mark as not used } - if (this->nox_sensor_ && sen5x_type != SEN55) { + if (this->nox_sensor_ && this->type_ != Sen5xType::SEN55) { ESP_LOGE(TAG, "NOx requires a SEN55"); this->nox_sensor_ = nullptr; // mark as not used } @@ -267,10 +265,10 @@ void SEN5XComponent::dump_config() { } } ESP_LOGCONFIG(TAG, - " Product name: %s\n" + " Type: %s\n" " Firmware version: %d\n" " Serial number: %s", - this->product_name_.c_str(), this->firmware_version_, this->serial_number_); + LOG_STR_ARG(type_to_string(this->type_)), this->firmware_version_, this->serial_number_); if (this->auto_cleaning_interval_.has_value()) { ESP_LOGCONFIG(TAG, " Auto cleaning interval: %" PRId32 "s", this->auto_cleaning_interval_.value()); } diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index 822160833e..e3bf931b41 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -24,6 +24,8 @@ enum RhtAccelerationMode : uint16_t { HIGH_ACCELERATION = 2, }; +enum class Sen5xType : uint8_t { SEN50, SEN54, SEN55, UNKNOWN }; + struct GasTuning { uint16_t index_offset; uint16_t learning_time_offset_hours; @@ -49,8 +51,6 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri void dump_config() override; void update() override; - enum Sen5xType { SEN50, SEN54, SEN55, UNKNOWN }; - void set_pm_1_0_sensor(sensor::Sensor *pm_1_0) { this->pm_1_0_sensor_ = pm_1_0; } void set_pm_2_5_sensor(sensor::Sensor *pm_2_5) { this->pm_2_5_sensor_ = pm_2_5; } void set_pm_4_0_sensor(sensor::Sensor *pm_4_0) { this->pm_4_0_sensor_ = pm_4_0; } @@ -106,6 +106,7 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri uint16_t voc_baseline_state_[4]{0}; uint32_t voc_baseline_time_; uint16_t firmware_version_; + Sen5xType type_{Sen5xType::UNKNOWN}; ERRORCODE error_code_; bool initialized_{false}; bool store_baseline_; @@ -127,7 +128,6 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri optional nox_tuning_params_; optional temperature_compensation_; ESPPreferenceObject pref_; - std::string product_name_; }; } // namespace sen5x From 8d84fe0113587c9a2f4e0b37e263092881917af6 Mon Sep 17 00:00:00 2001 From: Stephen Cox <69124219+linkedupbits@users.noreply.github.com> Date: Sun, 25 Jan 2026 10:31:26 +1300 Subject: [PATCH 0341/2030] [sy6970] Support for the sy6970 BMS chip (#13311) --- CODEOWNERS | 1 + esphome/components/sy6970/__init__.py | 63 ++++++ .../sy6970/binary_sensor/__init__.py | 56 +++++ .../binary_sensor/sy6970_binary_sensor.h | 43 ++++ esphome/components/sy6970/sensor/__init__.py | 95 +++++++++ .../components/sy6970/sensor/sy6970_sensor.h | 46 ++++ esphome/components/sy6970/sy6970.cpp | 201 ++++++++++++++++++ esphome/components/sy6970/sy6970.h | 122 +++++++++++ .../components/sy6970/text_sensor/__init__.py | 52 +++++ .../sy6970/text_sensor/sy6970_text_sensor.h | 96 +++++++++ tests/components/sy6970/common.yaml | 57 +++++ tests/components/sy6970/test.esp32-idf.yaml | 4 + 12 files changed, 836 insertions(+) create mode 100644 esphome/components/sy6970/__init__.py create mode 100644 esphome/components/sy6970/binary_sensor/__init__.py create mode 100644 esphome/components/sy6970/binary_sensor/sy6970_binary_sensor.h create mode 100644 esphome/components/sy6970/sensor/__init__.py create mode 100644 esphome/components/sy6970/sensor/sy6970_sensor.h create mode 100644 esphome/components/sy6970/sy6970.cpp create mode 100644 esphome/components/sy6970/sy6970.h create mode 100644 esphome/components/sy6970/text_sensor/__init__.py create mode 100644 esphome/components/sy6970/text_sensor/sy6970_text_sensor.h create mode 100644 tests/components/sy6970/common.yaml create mode 100644 tests/components/sy6970/test.esp32-idf.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8537d451db..00a22fed7c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -482,6 +482,7 @@ esphome/components/switch/* @esphome/core esphome/components/switch/binary_sensor/* @ssieb esphome/components/sx126x/* @swoboda1337 esphome/components/sx127x/* @swoboda1337 +esphome/components/sy6970/* @linkedupbits esphome/components/syslog/* @clydebarrow esphome/components/t6615/* @tylermenezes esphome/components/tc74/* @sethgirvan diff --git a/esphome/components/sy6970/__init__.py b/esphome/components/sy6970/__init__.py new file mode 100644 index 0000000000..2390d046e4 --- /dev/null +++ b/esphome/components/sy6970/__init__.py @@ -0,0 +1,63 @@ +import esphome.codegen as cg +from esphome.components import i2c +import esphome.config_validation as cv +from esphome.const import CONF_ID + +CODEOWNERS = ["@linkedupbits"] +DEPENDENCIES = ["i2c"] +MULTI_CONF = True + +CONF_SY6970_ID = "sy6970_id" +CONF_ENABLE_STATUS_LED = "enable_status_led" +CONF_INPUT_CURRENT_LIMIT = "input_current_limit" +CONF_CHARGE_VOLTAGE = "charge_voltage" +CONF_CHARGE_CURRENT = "charge_current" +CONF_PRECHARGE_CURRENT = "precharge_current" +CONF_CHARGE_ENABLED = "charge_enabled" +CONF_ENABLE_ADC = "enable_adc" + +sy6970_ns = cg.esphome_ns.namespace("sy6970") +SY6970Component = sy6970_ns.class_( + "SY6970Component", cg.PollingComponent, i2c.I2CDevice +) +SY6970Listener = sy6970_ns.class_("SY6970Listener") + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SY6970Component), + cv.Optional(CONF_ENABLE_STATUS_LED, default=True): cv.boolean, + cv.Optional(CONF_INPUT_CURRENT_LIMIT, default=500): cv.int_range( + min=100, max=3200 + ), + cv.Optional(CONF_CHARGE_VOLTAGE, default=4208): cv.int_range( + min=3840, max=4608 + ), + cv.Optional(CONF_CHARGE_CURRENT, default=2048): cv.int_range( + min=0, max=5056 + ), + cv.Optional(CONF_PRECHARGE_CURRENT, default=128): cv.int_range( + min=64, max=1024 + ), + cv.Optional(CONF_CHARGE_ENABLED, default=True): cv.boolean, + cv.Optional(CONF_ENABLE_ADC, default=True): cv.boolean, + } + ) + .extend(cv.polling_component_schema("5s")) + .extend(i2c.i2c_device_schema(0x6A)) +) + + +async def to_code(config): + var = cg.new_Pvariable( + config[CONF_ID], + config[CONF_ENABLE_STATUS_LED], + config[CONF_INPUT_CURRENT_LIMIT], + config[CONF_CHARGE_VOLTAGE], + config[CONF_CHARGE_CURRENT], + config[CONF_PRECHARGE_CURRENT], + config[CONF_CHARGE_ENABLED], + config[CONF_ENABLE_ADC], + ) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/sy6970/binary_sensor/__init__.py b/esphome/components/sy6970/binary_sensor/__init__.py new file mode 100644 index 0000000000..132b282051 --- /dev/null +++ b/esphome/components/sy6970/binary_sensor/__init__.py @@ -0,0 +1,56 @@ +import esphome.codegen as cg +from esphome.components import binary_sensor +import esphome.config_validation as cv +from esphome.const import DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_POWER + +from .. import CONF_SY6970_ID, SY6970Component, sy6970_ns + +DEPENDENCIES = ["sy6970"] + +CONF_VBUS_CONNECTED = "vbus_connected" +CONF_CHARGING = "charging" +CONF_CHARGE_DONE = "charge_done" + +SY6970VbusConnectedBinarySensor = sy6970_ns.class_( + "SY6970VbusConnectedBinarySensor", binary_sensor.BinarySensor +) +SY6970ChargingBinarySensor = sy6970_ns.class_( + "SY6970ChargingBinarySensor", binary_sensor.BinarySensor +) +SY6970ChargeDoneBinarySensor = sy6970_ns.class_( + "SY6970ChargeDoneBinarySensor", binary_sensor.BinarySensor +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_SY6970_ID): cv.use_id(SY6970Component), + cv.Optional(CONF_VBUS_CONNECTED): binary_sensor.binary_sensor_schema( + SY6970VbusConnectedBinarySensor, + device_class=DEVICE_CLASS_CONNECTIVITY, + ), + cv.Optional(CONF_CHARGING): binary_sensor.binary_sensor_schema( + SY6970ChargingBinarySensor, + device_class=DEVICE_CLASS_POWER, + ), + cv.Optional(CONF_CHARGE_DONE): binary_sensor.binary_sensor_schema( + SY6970ChargeDoneBinarySensor, + device_class=DEVICE_CLASS_POWER, + ), + } +) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_SY6970_ID]) + + if vbus_connected_config := config.get(CONF_VBUS_CONNECTED): + sens = await binary_sensor.new_binary_sensor(vbus_connected_config) + cg.add(parent.add_listener(sens)) + + if charging_config := config.get(CONF_CHARGING): + sens = await binary_sensor.new_binary_sensor(charging_config) + cg.add(parent.add_listener(sens)) + + if charge_done_config := config.get(CONF_CHARGE_DONE): + sens = await binary_sensor.new_binary_sensor(charge_done_config) + cg.add(parent.add_listener(sens)) diff --git a/esphome/components/sy6970/binary_sensor/sy6970_binary_sensor.h b/esphome/components/sy6970/binary_sensor/sy6970_binary_sensor.h new file mode 100644 index 0000000000..4a374d7e3d --- /dev/null +++ b/esphome/components/sy6970/binary_sensor/sy6970_binary_sensor.h @@ -0,0 +1,43 @@ +#pragma once + +#include "../sy6970.h" +#include "esphome/components/binary_sensor/binary_sensor.h" + +namespace esphome::sy6970 { + +template +class StatusBinarySensor : public SY6970Listener, public binary_sensor::BinarySensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t value = (data.registers[REG] >> SHIFT) & MASK; + this->publish_state(value == TRUE_VALUE); + } +}; + +template +class InverseStatusBinarySensor : public SY6970Listener, public binary_sensor::BinarySensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t value = (data.registers[REG] >> SHIFT) & MASK; + this->publish_state(value != FALSE_VALUE); + } +}; + +// Custom binary sensor for charging (true when pre-charge or fast charge) +class SY6970ChargingBinarySensor : public SY6970Listener, public binary_sensor::BinarySensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t chrg_stat = (data.registers[SY6970_REG_STATUS] >> 3) & 0x03; + bool charging = chrg_stat != CHARGE_STATUS_NOT_CHARGING && chrg_stat != CHARGE_STATUS_CHARGE_DONE; + this->publish_state(charging); + } +}; + +// Specialized sensor types using templates +// VBUS connected: BUS_STATUS != NO_INPUT +using SY6970VbusConnectedBinarySensor = InverseStatusBinarySensor; + +// Charge done: CHARGE_STATUS == CHARGE_DONE +using SY6970ChargeDoneBinarySensor = StatusBinarySensor; + +} // namespace esphome::sy6970 diff --git a/esphome/components/sy6970/sensor/__init__.py b/esphome/components/sy6970/sensor/__init__.py new file mode 100644 index 0000000000..e6ee9d1337 --- /dev/null +++ b/esphome/components/sy6970/sensor/__init__.py @@ -0,0 +1,95 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_BATTERY_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + UNIT_MILLIAMP, + UNIT_VOLT, +) + +from .. import CONF_SY6970_ID, SY6970Component, sy6970_ns + +DEPENDENCIES = ["sy6970"] + +CONF_VBUS_VOLTAGE = "vbus_voltage" +CONF_SYSTEM_VOLTAGE = "system_voltage" +CONF_CHARGE_CURRENT = "charge_current" +CONF_PRECHARGE_CURRENT = "precharge_current" + +SY6970VbusVoltageSensor = sy6970_ns.class_("SY6970VbusVoltageSensor", sensor.Sensor) +SY6970BatteryVoltageSensor = sy6970_ns.class_( + "SY6970BatteryVoltageSensor", sensor.Sensor +) +SY6970SystemVoltageSensor = sy6970_ns.class_("SY6970SystemVoltageSensor", sensor.Sensor) +SY6970ChargeCurrentSensor = sy6970_ns.class_("SY6970ChargeCurrentSensor", sensor.Sensor) +SY6970PrechargeCurrentSensor = sy6970_ns.class_( + "SY6970PrechargeCurrentSensor", sensor.Sensor +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_SY6970_ID): cv.use_id(SY6970Component), + cv.Optional(CONF_VBUS_VOLTAGE): sensor.sensor_schema( + SY6970VbusVoltageSensor, + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema( + SY6970BatteryVoltageSensor, + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_SYSTEM_VOLTAGE): sensor.sensor_schema( + SY6970SystemVoltageSensor, + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CHARGE_CURRENT): sensor.sensor_schema( + SY6970ChargeCurrentSensor, + unit_of_measurement=UNIT_MILLIAMP, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PRECHARGE_CURRENT): sensor.sensor_schema( + SY6970PrechargeCurrentSensor, + unit_of_measurement=UNIT_MILLIAMP, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + } +) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_SY6970_ID]) + + if vbus_voltage_config := config.get(CONF_VBUS_VOLTAGE): + sens = await sensor.new_sensor(vbus_voltage_config) + cg.add(parent.add_listener(sens)) + + if battery_voltage_config := config.get(CONF_BATTERY_VOLTAGE): + sens = await sensor.new_sensor(battery_voltage_config) + cg.add(parent.add_listener(sens)) + + if system_voltage_config := config.get(CONF_SYSTEM_VOLTAGE): + sens = await sensor.new_sensor(system_voltage_config) + cg.add(parent.add_listener(sens)) + + if charge_current_config := config.get(CONF_CHARGE_CURRENT): + sens = await sensor.new_sensor(charge_current_config) + cg.add(parent.add_listener(sens)) + + if precharge_current_config := config.get(CONF_PRECHARGE_CURRENT): + sens = await sensor.new_sensor(precharge_current_config) + cg.add(parent.add_listener(sens)) diff --git a/esphome/components/sy6970/sensor/sy6970_sensor.h b/esphome/components/sy6970/sensor/sy6970_sensor.h new file mode 100644 index 0000000000..f912d726b2 --- /dev/null +++ b/esphome/components/sy6970/sensor/sy6970_sensor.h @@ -0,0 +1,46 @@ +#pragma once + +#include "../sy6970.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome::sy6970 { + +// Template for voltage sensors (converts mV to V) +template +class VoltageSensor : public SY6970Listener, public sensor::Sensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t val = data.registers[REG] & MASK; + uint16_t voltage_mv = BASE + (val * STEP); + this->publish_state(voltage_mv * 0.001f); // Convert mV to V + } +}; + +// Template for current sensors (returns mA) +template +class CurrentSensor : public SY6970Listener, public sensor::Sensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t val = data.registers[REG] & MASK; + uint16_t current_ma = BASE + (val * STEP); + this->publish_state(current_ma); + } +}; + +// Specialized sensor types using templates +using SY6970VbusVoltageSensor = VoltageSensor; +using SY6970BatteryVoltageSensor = VoltageSensor; +using SY6970SystemVoltageSensor = VoltageSensor; +using SY6970ChargeCurrentSensor = CurrentSensor; + +// Precharge current sensor needs special handling (bit shift) +class SY6970PrechargeCurrentSensor : public SY6970Listener, public sensor::Sensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t iprechg = (data.registers[SY6970_REG_PRECHARGE_CURRENT] >> 4) & 0x0F; + uint16_t iprechg_ma = PRE_CHG_BASE_MA + (iprechg * PRE_CHG_STEP_MA); + this->publish_state(iprechg_ma); + } +}; + +} // namespace esphome::sy6970 diff --git a/esphome/components/sy6970/sy6970.cpp b/esphome/components/sy6970/sy6970.cpp new file mode 100644 index 0000000000..1f1648cfa7 --- /dev/null +++ b/esphome/components/sy6970/sy6970.cpp @@ -0,0 +1,201 @@ +#include "sy6970.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome::sy6970 { + +static const char *const TAG = "sy6970"; + +bool SY6970Component::read_all_registers_() { + // Read all registers from 0x00 to 0x14 in one transaction (21 bytes) + // This includes unused registers 0x0F, 0x10 for performance + if (!this->read_bytes(SY6970_REG_INPUT_CURRENT_LIMIT, this->data_.registers, 21)) { + ESP_LOGW(TAG, "Failed to read registers 0x00-0x14"); + return false; + } + + return true; +} + +bool SY6970Component::write_register_(uint8_t reg, uint8_t value) { + if (!this->write_byte(reg, value)) { + ESP_LOGW(TAG, "Failed to write register 0x%02X", reg); + return false; + } + return true; +} + +bool SY6970Component::update_register_(uint8_t reg, uint8_t mask, uint8_t value) { + uint8_t reg_value; + if (!this->read_byte(reg, ®_value)) { + ESP_LOGW(TAG, "Failed to read register 0x%02X for update", reg); + return false; + } + reg_value = (reg_value & ~mask) | (value & mask); + return this->write_register_(reg, reg_value); +} + +void SY6970Component::setup() { + ESP_LOGV(TAG, "Setting up SY6970..."); + + // Try to read chip ID + uint8_t reg_value; + if (!this->read_byte(SY6970_REG_DEVICE_ID, ®_value)) { + ESP_LOGE(TAG, "Failed to communicate with SY6970"); + this->mark_failed(); + return; + } + + uint8_t chip_id = reg_value & 0x03; + if (chip_id != 0x00) { + ESP_LOGW(TAG, "Unexpected chip ID: 0x%02X (expected 0x00)", chip_id); + } + + // Apply configuration options (all have defaults now) + ESP_LOGV(TAG, "Setting LED enabled to %s", ONOFF(this->led_enabled_)); + this->set_led_enabled(this->led_enabled_); + + ESP_LOGV(TAG, "Setting input current limit to %u mA", this->input_current_limit_); + this->set_input_current_limit(this->input_current_limit_); + + ESP_LOGV(TAG, "Setting charge voltage to %u mV", this->charge_voltage_); + this->set_charge_target_voltage(this->charge_voltage_); + + ESP_LOGV(TAG, "Setting charge current to %u mA", this->charge_current_); + this->set_charge_current(this->charge_current_); + + ESP_LOGV(TAG, "Setting precharge current to %u mA", this->precharge_current_); + this->set_precharge_current(this->precharge_current_); + + ESP_LOGV(TAG, "Setting charge enabled to %s", ONOFF(this->charge_enabled_)); + this->set_charge_enabled(this->charge_enabled_); + + ESP_LOGV(TAG, "Setting ADC measurements to %s", ONOFF(this->enable_adc_)); + this->set_enable_adc_measure(this->enable_adc_); + + ESP_LOGV(TAG, "SY6970 initialized successfully"); +} + +void SY6970Component::dump_config() { + ESP_LOGCONFIG(TAG, + "SY6970:\n" + " LED Enabled: %s\n" + " Input Current Limit: %u mA\n" + " Charge Voltage: %u mV\n" + " Charge Current: %u mA\n" + " Precharge Current: %u mA\n" + " Charge Enabled: %s\n" + " ADC Enabled: %s", + ONOFF(this->led_enabled_), this->input_current_limit_, this->charge_voltage_, this->charge_current_, + this->precharge_current_, ONOFF(this->charge_enabled_), ONOFF(this->enable_adc_)); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); + if (this->is_failed()) { + ESP_LOGE(TAG, "Communication with SY6970 failed!"); + } +} + +void SY6970Component::update() { + if (this->is_failed()) { + return; + } + + // Read all registers in one transaction + if (!this->read_all_registers_()) { + ESP_LOGW(TAG, "Failed to read registers during update"); + this->status_set_warning(); + return; + } + + this->status_clear_warning(); + + // Notify all listeners with the new data + for (auto *listener : this->listeners_) { + listener->on_data(this->data_); + } +} + +void SY6970Component::set_input_current_limit(uint16_t milliamps) { + if (this->is_failed()) + return; + + if (milliamps < INPUT_CURRENT_MIN) { + milliamps = INPUT_CURRENT_MIN; + } + + uint8_t val = (milliamps - INPUT_CURRENT_MIN) / INPUT_CURRENT_STEP; + if (val > 0x3F) { + val = 0x3F; + } + + this->update_register_(SY6970_REG_INPUT_CURRENT_LIMIT, 0x3F, val); +} + +void SY6970Component::set_charge_target_voltage(uint16_t millivolts) { + if (this->is_failed()) + return; + + if (millivolts < CHG_VOLTAGE_BASE) { + millivolts = CHG_VOLTAGE_BASE; + } + + uint8_t val = (millivolts - CHG_VOLTAGE_BASE) / CHG_VOLTAGE_STEP; + if (val > 0x3F) { + val = 0x3F; + } + + this->update_register_(SY6970_REG_CHARGE_VOLTAGE, 0xFC, val << 2); +} + +void SY6970Component::set_precharge_current(uint16_t milliamps) { + if (this->is_failed()) + return; + + if (milliamps < PRE_CHG_BASE_MA) { + milliamps = PRE_CHG_BASE_MA; + } + + uint8_t val = (milliamps - PRE_CHG_BASE_MA) / PRE_CHG_STEP_MA; + if (val > 0x0F) { + val = 0x0F; + } + + this->update_register_(SY6970_REG_PRECHARGE_CURRENT, 0xF0, val << 4); +} + +void SY6970Component::set_charge_current(uint16_t milliamps) { + if (this->is_failed()) + return; + + uint8_t val = milliamps / 64; + if (val > 0x7F) { + val = 0x7F; + } + + this->update_register_(SY6970_REG_CHARGE_CURRENT, 0x7F, val); +} + +void SY6970Component::set_charge_enabled(bool enabled) { + if (this->is_failed()) + return; + + this->update_register_(SY6970_REG_SYS_CONTROL, 0x10, enabled ? 0x10 : 0x00); +} + +void SY6970Component::set_led_enabled(bool enabled) { + if (this->is_failed()) + return; + + // Bit 6: 0 = LED enabled, 1 = LED disabled + this->update_register_(SY6970_REG_TIMER_CONTROL, 0x40, enabled ? 0x00 : 0x40); +} + +void SY6970Component::set_enable_adc_measure(bool enabled) { + if (this->is_failed()) + return; + + // Set bits to enable ADC conversion + this->update_register_(SY6970_REG_ADC_CONTROL, 0xC0, enabled ? 0xC0 : 0x00); +} + +} // namespace esphome::sy6970 diff --git a/esphome/components/sy6970/sy6970.h b/esphome/components/sy6970/sy6970.h new file mode 100644 index 0000000000..bacc072f9b --- /dev/null +++ b/esphome/components/sy6970/sy6970.h @@ -0,0 +1,122 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/core/component.h" +#include + +namespace esphome::sy6970 { + +// SY6970 Register addresses with descriptive names +static const uint8_t SY6970_REG_INPUT_CURRENT_LIMIT = 0x00; // Input current limit control +static const uint8_t SY6970_REG_VINDPM = 0x01; // Input voltage limit +static const uint8_t SY6970_REG_ADC_CONTROL = 0x02; // ADC control and function disable +static const uint8_t SY6970_REG_SYS_CONTROL = 0x03; // Charge enable and system config +static const uint8_t SY6970_REG_CHARGE_CURRENT = 0x04; // Fast charge current limit +static const uint8_t SY6970_REG_PRECHARGE_CURRENT = 0x05; // Pre-charge/termination current +static const uint8_t SY6970_REG_CHARGE_VOLTAGE = 0x06; // Charge voltage limit +static const uint8_t SY6970_REG_TIMER_CONTROL = 0x07; // Charge timer and status LED control +static const uint8_t SY6970_REG_IR_COMP = 0x08; // IR compensation +static const uint8_t SY6970_REG_FORCE_DPDM = 0x09; // Force DPDM detection +static const uint8_t SY6970_REG_BOOST_CONTROL = 0x0A; // Boost mode voltage/current +static const uint8_t SY6970_REG_STATUS = 0x0B; // System status (bus, charge status) +static const uint8_t SY6970_REG_FAULT = 0x0C; // Fault status (NTC) +static const uint8_t SY6970_REG_VINDPM_STATUS = 0x0D; // Input voltage limit status (also sys voltage) +static const uint8_t SY6970_REG_BATV = 0x0E; // Battery voltage +static const uint8_t SY6970_REG_VBUS_VOLTAGE = 0x11; // VBUS voltage +static const uint8_t SY6970_REG_CHARGE_CURRENT_MONITOR = 0x12; // Charge current +static const uint8_t SY6970_REG_INPUT_VOLTAGE_LIMIT = 0x13; // Input voltage limit +static const uint8_t SY6970_REG_DEVICE_ID = 0x14; // Part information + +// Constants for voltage and current calculations +static const uint16_t VBUS_BASE_MV = 2600; // mV +static const uint16_t VBUS_STEP_MV = 100; // mV +static const uint16_t VBAT_BASE_MV = 2304; // mV +static const uint16_t VBAT_STEP_MV = 20; // mV +static const uint16_t VSYS_BASE_MV = 2304; // mV +static const uint16_t VSYS_STEP_MV = 20; // mV +static const uint16_t CHG_CURRENT_STEP_MA = 50; // mA +static const uint16_t PRE_CHG_BASE_MA = 64; // mA +static const uint16_t PRE_CHG_STEP_MA = 64; // mA +static const uint16_t CHG_VOLTAGE_BASE = 3840; // mV +static const uint16_t CHG_VOLTAGE_STEP = 16; // mV +static const uint16_t INPUT_CURRENT_MIN = 100; // mA +static const uint16_t INPUT_CURRENT_STEP = 50; // mA + +// Bus Status values (REG_0B[7:5]) +enum BusStatus { + BUS_STATUS_NO_INPUT = 0, + BUS_STATUS_USB_SDP = 1, + BUS_STATUS_USB_CDP = 2, + BUS_STATUS_USB_DCP = 3, + BUS_STATUS_HVDCP = 4, + BUS_STATUS_ADAPTER = 5, + BUS_STATUS_NO_STD_ADAPTER = 6, + BUS_STATUS_OTG = 7, +}; + +// Charge Status values (REG_0B[4:3]) +enum ChargeStatus { + CHARGE_STATUS_NOT_CHARGING = 0, + CHARGE_STATUS_PRE_CHARGE = 1, + CHARGE_STATUS_FAST_CHARGE = 2, + CHARGE_STATUS_CHARGE_DONE = 3, +}; + +// Structure to hold all register data read in one transaction +struct SY6970Data { + uint8_t registers[21]; // Registers 0x00-0x14 (includes unused 0x0F, 0x10) +}; + +// Listener interface for components that want to receive SY6970 data updates +class SY6970Listener { + public: + virtual void on_data(const SY6970Data &data) = 0; +}; + +class SY6970Component : public PollingComponent, public i2c::I2CDevice { + public: + SY6970Component(bool led_enabled, uint16_t input_current_limit, uint16_t charge_voltage, uint16_t charge_current, + uint16_t precharge_current, bool charge_enabled, bool enable_adc) + : led_enabled_(led_enabled), + input_current_limit_(input_current_limit), + charge_voltage_(charge_voltage), + charge_current_(charge_current), + precharge_current_(precharge_current), + charge_enabled_(charge_enabled), + enable_adc_(enable_adc) {} + void setup() override; + void dump_config() override; + void update() override; + float get_setup_priority() const override { return setup_priority::DATA; } + + // Listener registration + void add_listener(SY6970Listener *listener) { this->listeners_.push_back(listener); } + + // Configuration methods to be called from lambdas + void set_input_current_limit(uint16_t milliamps); + void set_charge_target_voltage(uint16_t millivolts); + void set_precharge_current(uint16_t milliamps); + void set_charge_current(uint16_t milliamps); + void set_charge_enabled(bool enabled); + void set_led_enabled(bool enabled); + void set_enable_adc_measure(bool enabled = true); + + protected: + bool read_all_registers_(); + bool write_register_(uint8_t reg, uint8_t value); + bool update_register_(uint8_t reg, uint8_t mask, uint8_t value); + + SY6970Data data_{}; + std::vector listeners_; + + // Configuration values to set during setup() + bool led_enabled_; + uint16_t input_current_limit_; + uint16_t charge_voltage_; + uint16_t charge_current_; + uint16_t precharge_current_; + bool charge_enabled_; + bool enable_adc_; +}; + +} // namespace esphome::sy6970 diff --git a/esphome/components/sy6970/text_sensor/__init__.py b/esphome/components/sy6970/text_sensor/__init__.py new file mode 100644 index 0000000000..2a4eb90811 --- /dev/null +++ b/esphome/components/sy6970/text_sensor/__init__.py @@ -0,0 +1,52 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv + +from .. import CONF_SY6970_ID, SY6970Component, sy6970_ns + +DEPENDENCIES = ["sy6970"] + +CONF_BUS_STATUS = "bus_status" +CONF_CHARGE_STATUS = "charge_status" +CONF_NTC_STATUS = "ntc_status" + +SY6970BusStatusTextSensor = sy6970_ns.class_( + "SY6970BusStatusTextSensor", text_sensor.TextSensor +) +SY6970ChargeStatusTextSensor = sy6970_ns.class_( + "SY6970ChargeStatusTextSensor", text_sensor.TextSensor +) +SY6970NtcStatusTextSensor = sy6970_ns.class_( + "SY6970NtcStatusTextSensor", text_sensor.TextSensor +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_SY6970_ID): cv.use_id(SY6970Component), + cv.Optional(CONF_BUS_STATUS): text_sensor.text_sensor_schema( + SY6970BusStatusTextSensor + ), + cv.Optional(CONF_CHARGE_STATUS): text_sensor.text_sensor_schema( + SY6970ChargeStatusTextSensor + ), + cv.Optional(CONF_NTC_STATUS): text_sensor.text_sensor_schema( + SY6970NtcStatusTextSensor + ), + } +) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_SY6970_ID]) + + if bus_status_config := config.get(CONF_BUS_STATUS): + sens = await text_sensor.new_text_sensor(bus_status_config) + cg.add(parent.add_listener(sens)) + + if charge_status_config := config.get(CONF_CHARGE_STATUS): + sens = await text_sensor.new_text_sensor(charge_status_config) + cg.add(parent.add_listener(sens)) + + if ntc_status_config := config.get(CONF_NTC_STATUS): + sens = await text_sensor.new_text_sensor(ntc_status_config) + cg.add(parent.add_listener(sens)) diff --git a/esphome/components/sy6970/text_sensor/sy6970_text_sensor.h b/esphome/components/sy6970/text_sensor/sy6970_text_sensor.h new file mode 100644 index 0000000000..665c5eca64 --- /dev/null +++ b/esphome/components/sy6970/text_sensor/sy6970_text_sensor.h @@ -0,0 +1,96 @@ +#pragma once + +#include "../sy6970.h" +#include "esphome/components/text_sensor/text_sensor.h" + +namespace esphome::sy6970 { + +// Bus status text sensor +class SY6970BusStatusTextSensor : public SY6970Listener, public text_sensor::TextSensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t status = (data.registers[SY6970_REG_STATUS] >> 5) & 0x07; + const char *status_str = this->get_bus_status_string_(status); + this->publish_state(status_str); + } + + protected: + const char *get_bus_status_string_(uint8_t status) { + switch (status) { + case BUS_STATUS_NO_INPUT: + return "No Input"; + case BUS_STATUS_USB_SDP: + return "USB SDP"; + case BUS_STATUS_USB_CDP: + return "USB CDP"; + case BUS_STATUS_USB_DCP: + return "USB DCP"; + case BUS_STATUS_HVDCP: + return "HVDCP"; + case BUS_STATUS_ADAPTER: + return "Adapter"; + case BUS_STATUS_NO_STD_ADAPTER: + return "Non-Standard Adapter"; + case BUS_STATUS_OTG: + return "OTG"; + default: + return "Unknown"; + } + } +}; + +// Charge status text sensor +class SY6970ChargeStatusTextSensor : public SY6970Listener, public text_sensor::TextSensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t status = (data.registers[SY6970_REG_STATUS] >> 3) & 0x03; + const char *status_str = this->get_charge_status_string_(status); + this->publish_state(status_str); + } + + protected: + const char *get_charge_status_string_(uint8_t status) { + switch (status) { + case CHARGE_STATUS_NOT_CHARGING: + return "Not Charging"; + case CHARGE_STATUS_PRE_CHARGE: + return "Pre-charge"; + case CHARGE_STATUS_FAST_CHARGE: + return "Fast Charge"; + case CHARGE_STATUS_CHARGE_DONE: + return "Charge Done"; + default: + return "Unknown"; + } + } +}; + +// NTC status text sensor +class SY6970NtcStatusTextSensor : public SY6970Listener, public text_sensor::TextSensor { + public: + void on_data(const SY6970Data &data) override { + uint8_t status = data.registers[SY6970_REG_FAULT] & 0x07; + const char *status_str = this->get_ntc_status_string_(status); + this->publish_state(status_str); + } + + protected: + const char *get_ntc_status_string_(uint8_t status) { + switch (status) { + case 0: + return "Normal"; + case 2: + return "Warm"; + case 3: + return "Cool"; + case 5: + return "Cold"; + case 6: + return "Hot"; + default: + return "Unknown"; + } + } +}; + +} // namespace esphome::sy6970 diff --git a/tests/components/sy6970/common.yaml b/tests/components/sy6970/common.yaml new file mode 100644 index 0000000000..53699fe6fb --- /dev/null +++ b/tests/components/sy6970/common.yaml @@ -0,0 +1,57 @@ +sy6970: + id: sy6970_component + i2c_id: i2c_bus + address: 0x6A + enable_status_led: true + input_current_limit: 1000 + charge_voltage: 4200 + charge_current: 500 + precharge_current: 128 + charge_enabled: true + enable_adc: true + update_interval: 5s + +sensor: + - platform: sy6970 + sy6970_id: sy6970_component + vbus_voltage: + name: "VBUS Voltage" + id: vbus_voltage_sensor + battery_voltage: + name: "Battery Voltage" + id: battery_voltage_sensor + system_voltage: + name: "System Voltage" + id: system_voltage_sensor + charge_current: + name: "Charge Current" + id: charge_current_sensor + precharge_current: + name: "Precharge Current" + id: precharge_current_sensor + +binary_sensor: + - platform: sy6970 + sy6970_id: sy6970_component + vbus_connected: + name: "VBUS Connected" + id: vbus_connected_binary + charging: + name: "Charging" + id: charging_binary + charge_done: + name: "Charge Done" + id: charge_done_binary + +text_sensor: + - platform: sy6970 + sy6970_id: sy6970_component + bus_status: + name: "Bus Status" + id: bus_status_text + charge_status: + name: "Charge Status" + id: charge_status_text + ntc_status: + name: "NTC Status" + id: ntc_status_text diff --git a/tests/components/sy6970/test.esp32-idf.yaml b/tests/components/sy6970/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/sy6970/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml From 993765d732e0c67dec192bb73577ea30aad2cb29 Mon Sep 17 00:00:00 2001 From: Douwe <61123717+dhoeben@users.noreply.github.com> Date: Sun, 25 Jan 2026 02:18:13 +0100 Subject: [PATCH 0342/2030] [water_heater] Remove Component inheritance from base class (#13510) Co-authored-by: J. Nick Koston Co-authored-by: Claude Opus 4.5 --- .../template/water_heater/__init__.py | 33 +++++++++++-------- .../water_heater/template_water_heater.cpp | 2 +- .../water_heater/template_water_heater.h | 2 +- esphome/components/water_heater/__init__.py | 6 ++-- .../components/water_heater/water_heater.cpp | 7 ++-- .../components/water_heater/water_heater.h | 9 +++-- 6 files changed, 29 insertions(+), 30 deletions(-) diff --git a/esphome/components/template/water_heater/__init__.py b/esphome/components/template/water_heater/__init__.py index 716289035a..bddd378b23 100644 --- a/esphome/components/template/water_heater/__init__.py +++ b/esphome/components/template/water_heater/__init__.py @@ -20,7 +20,7 @@ from .. import template_ns CONF_CURRENT_TEMPERATURE = "current_temperature" TemplateWaterHeater = template_ns.class_( - "TemplateWaterHeater", water_heater.WaterHeater + "TemplateWaterHeater", cg.Component, water_heater.WaterHeater ) TemplateWaterHeaterPublishAction = template_ns.class_( @@ -36,24 +36,29 @@ RESTORE_MODES = { "RESTORE_AND_CALL": TemplateWaterHeaterRestoreMode.WATER_HEATER_RESTORE_AND_CALL, } -CONFIG_SCHEMA = water_heater.water_heater_schema(TemplateWaterHeater).extend( - { - cv.Optional(CONF_OPTIMISTIC, default=True): cv.boolean, - cv.Optional(CONF_SET_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_RESTORE_MODE, default="NO_RESTORE"): cv.enum( - RESTORE_MODES, upper=True - ), - cv.Optional(CONF_CURRENT_TEMPERATURE): cv.returning_lambda, - cv.Optional(CONF_MODE): cv.returning_lambda, - cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list( - water_heater.validate_water_heater_mode - ), - } +CONFIG_SCHEMA = ( + water_heater.water_heater_schema(TemplateWaterHeater) + .extend( + { + cv.Optional(CONF_OPTIMISTIC, default=True): cv.boolean, + cv.Optional(CONF_SET_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_RESTORE_MODE, default="NO_RESTORE"): cv.enum( + RESTORE_MODES, upper=True + ), + cv.Optional(CONF_CURRENT_TEMPERATURE): cv.returning_lambda, + cv.Optional(CONF_MODE): cv.returning_lambda, + cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list( + water_heater.validate_water_heater_mode + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) ) async def to_code(config: ConfigType) -> None: var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) await water_heater.register_water_heater(var, config) cg.add(var.set_optimistic(config[CONF_OPTIMISTIC])) diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index 5ae5c30f36..e89c96ca48 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -10,7 +10,7 @@ TemplateWaterHeater::TemplateWaterHeater() : set_trigger_(new Trigger<>()) {} void TemplateWaterHeater::setup() { if (this->restore_mode_ == TemplateWaterHeaterRestoreMode::WATER_HEATER_RESTORE || this->restore_mode_ == TemplateWaterHeaterRestoreMode::WATER_HEATER_RESTORE_AND_CALL) { - auto restore = this->restore_state(); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->perform(); diff --git a/esphome/components/template/water_heater/template_water_heater.h b/esphome/components/template/water_heater/template_water_heater.h index e5f51b72dc..c2a2dcbb23 100644 --- a/esphome/components/template/water_heater/template_water_heater.h +++ b/esphome/components/template/water_heater/template_water_heater.h @@ -13,7 +13,7 @@ enum TemplateWaterHeaterRestoreMode { WATER_HEATER_RESTORE_AND_CALL, }; -class TemplateWaterHeater : public water_heater::WaterHeater { +class TemplateWaterHeater : public Component, public water_heater::WaterHeater { public: TemplateWaterHeater(); diff --git a/esphome/components/water_heater/__init__.py b/esphome/components/water_heater/__init__.py index 5420e7c435..db32c2d919 100644 --- a/esphome/components/water_heater/__init__.py +++ b/esphome/components/water_heater/__init__.py @@ -18,7 +18,7 @@ CODEOWNERS = ["@dhoeben"] IS_PLATFORM_COMPONENT = True water_heater_ns = cg.esphome_ns.namespace("water_heater") -WaterHeater = water_heater_ns.class_("WaterHeater", cg.EntityBase, cg.Component) +WaterHeater = water_heater_ns.class_("WaterHeater", cg.EntityBase) WaterHeaterCall = water_heater_ns.class_("WaterHeaterCall") WaterHeaterTraits = water_heater_ns.class_("WaterHeaterTraits") @@ -46,7 +46,7 @@ _WATER_HEATER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( } ), } -).extend(cv.COMPONENT_SCHEMA) +) _WATER_HEATER_SCHEMA.add_extra(entity_duplicate_validator("water_heater")) @@ -91,8 +91,6 @@ async def register_water_heater(var: cg.Pvariable, config: ConfigType) -> cg.Pva cg.add_define("USE_WATER_HEATER") - await cg.register_component(var, config) - cg.add(cg.App.register_water_heater(var)) CORE.register_platform_component("water_heater", var) diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 7b947057e1..fbb4181209 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -146,10 +146,6 @@ void WaterHeaterCall::validate_() { } } -void WaterHeater::setup() { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); -} - void WaterHeater::publish_state() { auto traits = this->get_traits(); ESP_LOGD(TAG, @@ -188,7 +184,8 @@ void WaterHeater::publish_state() { this->pref_.save(&saved); } -optional WaterHeater::restore_state() { +optional WaterHeater::restore_state_() { + this->pref_ = global_preferences->make_preference(this->get_preference_hash()); SavedWaterHeaterState recovered{}; if (!this->pref_.load(&recovered)) return {}; diff --git a/esphome/components/water_heater/water_heater.h b/esphome/components/water_heater/water_heater.h index e223dd59b2..84fc46d208 100644 --- a/esphome/components/water_heater/water_heater.h +++ b/esphome/components/water_heater/water_heater.h @@ -177,7 +177,7 @@ class WaterHeaterTraits { WaterHeaterModeMask supported_modes_; }; -class WaterHeater : public EntityBase, public Component { +class WaterHeater : public EntityBase { public: WaterHeaterMode get_mode() const { return this->mode_; } float get_current_temperature() const { return this->current_temperature_; } @@ -204,16 +204,15 @@ class WaterHeater : public EntityBase, public Component { #endif virtual void control(const WaterHeaterCall &call) = 0; - void setup() override; - - optional restore_state(); - protected: virtual WaterHeaterTraits traits() = 0; /// Log the traits of this water heater for dump_config(). void dump_traits_(const char *tag); + /// Restore the state of the water heater, call this from your setup() method. + optional restore_state_(); + /// Set the mode of the water heater. Should only be called from control(). void set_mode_(WaterHeaterMode mode) { this->mode_ = mode; } /// Set the target temperature of the water heater. Should only be called from control(). From c32e4bc65b76eadc2f62761caa7a113166f752b7 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 26 Jan 2026 03:52:23 +1100 Subject: [PATCH 0343/2030] [wifi] Fix watchdog timeout on P4 WiFi scan (#13520) --- esphome/components/esp32_hosted/__init__.py | 2 ++ .../wifi/wifi_component_esp_idf.cpp | 20 ++++++++++++++++--- esphome/core/defines.h | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index e40431c851..170f436f02 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -12,6 +12,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, ) from esphome.core import CORE +from esphome.cpp_generator import add_define CODEOWNERS = ["@swoboda1337"] @@ -42,6 +43,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): + add_define("USE_ESP32_HOSTED") if config[CONF_ACTIVE_HIGH]: esp32.add_idf_sdkconfig_option( "CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH", diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 99474ac2f8..15fd407e3c 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #ifdef USE_WIFI_WPA2_EAP #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) @@ -828,16 +829,29 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { uint16_t number = it.number; scan_result_.init(number); - - // Process one record at a time to avoid large buffer allocation - wifi_ap_record_t record; +#ifdef USE_ESP32_HOSTED + // getting records one at a time fails on P4 with hosted esp32 WiFi coprocessor + // Presumably an upstream bug, work-around by getting all records at once + auto records = std::make_unique(number); + err = esp_wifi_scan_get_ap_records(&number, records.get()); + if (err != ESP_OK) { + esp_wifi_clear_ap_list(); + ESP_LOGW(TAG, "esp_wifi_scan_get_ap_records failed: %s", esp_err_to_name(err)); + return; + } for (uint16_t i = 0; i < number; i++) { + wifi_ap_record_t &record = records[i]; +#else + // Process one record at a time to avoid large buffer allocation + for (uint16_t i = 0; i < number; i++) { + wifi_ap_record_t record; err = esp_wifi_scan_get_ap_record(&record); if (err != ESP_OK) { ESP_LOGW(TAG, "esp_wifi_scan_get_ap_record failed: %s", esp_err_to_name(err)); esp_wifi_clear_ap_list(); // Free remaining records not yet retrieved break; } +#endif // USE_ESP32_HOSTED bssid_t bssid; std::copy(record.bssid, record.bssid + 6, bssid.begin()); std::string ssid(reinterpret_cast(record.ssid)); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 7c13823fba..e98cdd0ba0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -42,6 +42,7 @@ #define USE_DEVICES #define USE_DISPLAY #define USE_ENTITY_ICON +#define USE_ESP32_HOSTED #define USE_ESP32_IMPROV_STATE_CALLBACK #define USE_EVENT #define USE_FAN From bac96086be2a3702c5f01afa317670d6ebb2d27a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 25 Jan 2026 07:16:07 -1000 Subject: [PATCH 0344/2030] [wifi] Fix scan flag race condition causing reconnect failure on ESP8266/LibreTiny (#13514) --- esphome/components/wifi/wifi_component_esp8266.cpp | 4 ++++ esphome/components/wifi/wifi_component_libretiny.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index de0600cf5b..91db7ae0eb 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -698,6 +698,10 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { if (!this->wifi_mode_(true, {})) return false; + // Reset scan_done_ before starting new scan to prevent stale flag from previous scan + // (e.g., roaming scan completed just before unexpected disconnect) + this->scan_done_ = false; + struct scan_config config {}; memset(&config, 0, sizeof(config)); config.ssid = nullptr; diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index cc9f4ec193..20cd32fa8f 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -649,6 +649,10 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { if (!this->wifi_mode_(true, {})) return false; + // Reset scan_done_ before starting new scan to prevent stale flag from previous scan + // (e.g., roaming scan completed just before unexpected disconnect) + this->scan_done_ = false; + // need to use WiFi because of WiFiScanClass allocations :( int16_t err = WiFi.scanNetworks(true, true, passive, 200); if (err != WIFI_SCAN_RUNNING) { From ccbf17d5ab9074f78387c54eef3fecd424ce6c34 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:42:28 -1000 Subject: [PATCH 0345/2030] [st7701s] Fix dump_summary deprecation warning (#13462) --- esphome/components/st7701s/st7701s.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 6314c99fb0..221fe39b9d 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -1,5 +1,6 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "st7701s.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" namespace esphome { @@ -183,8 +184,11 @@ void ST7701S::dump_config() { LOG_PIN(" DE Pin: ", this->de_pin_); LOG_PIN(" Reset Pin: ", this->reset_pin_); size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); - for (size_t i = 0; i != data_pin_count; i++) - ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, (this->data_pins_[i])->dump_summary().c_str()); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + for (size_t i = 0; i != data_pin_count; i++) { + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary); + } ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000)); } From ab1661ef22760685f9f79bd8137f1d3b727614c9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:53:15 -1000 Subject: [PATCH 0346/2030] [mipi_rgb] Fix dump_summary deprecation warning (#13463) --- esphome/components/mipi_rgb/mipi_rgb.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index ef96da8a1c..d0e716bd24 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -1,9 +1,11 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "mipi_rgb.h" +#include "esphome/core/gpio.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/hal.h" #include "esp_lcd_panel_rgb.h" +#include namespace esphome { namespace mipi_rgb { @@ -343,19 +345,27 @@ int MipiRgb::get_height() { } } -static std::string get_pin_name(GPIOPin *pin) { +static const char *get_pin_name(GPIOPin *pin, std::span buffer) { if (pin == nullptr) return "None"; - return pin->dump_summary(); + pin->dump_summary(buffer.data(), buffer.size()); + return buffer.data(); } void MipiRgb::dump_pins_(uint8_t start, uint8_t end, const char *name, uint8_t offset) { + char pin_summary[GPIO_SUMMARY_MAX_LEN]; for (uint8_t i = start; i != end; i++) { - ESP_LOGCONFIG(TAG, " %s pin %d: %s", name, offset++, this->data_pins_[i]->dump_summary().c_str()); + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " %s pin %d: %s", name, offset++, pin_summary); } } void MipiRgb::dump_config() { + char reset_buf[GPIO_SUMMARY_MAX_LEN]; + char de_buf[GPIO_SUMMARY_MAX_LEN]; + char pclk_buf[GPIO_SUMMARY_MAX_LEN]; + char hsync_buf[GPIO_SUMMARY_MAX_LEN]; + char vsync_buf[GPIO_SUMMARY_MAX_LEN]; ESP_LOGCONFIG(TAG, "MIPI_RGB LCD" "\n Model: %s" @@ -379,9 +389,9 @@ void MipiRgb::dump_config() { this->model_, this->width_, this->height_, this->rotation_, YESNO(this->pclk_inverted_), this->hsync_pulse_width_, this->hsync_back_porch_, this->hsync_front_porch_, this->vsync_pulse_width_, this->vsync_back_porch_, this->vsync_front_porch_, YESNO(this->invert_colors_), - (unsigned) (this->pclk_frequency_ / 1000000), get_pin_name(this->reset_pin_).c_str(), - get_pin_name(this->de_pin_).c_str(), get_pin_name(this->pclk_pin_).c_str(), - get_pin_name(this->hsync_pin_).c_str(), get_pin_name(this->vsync_pin_).c_str()); + (unsigned) (this->pclk_frequency_ / 1000000), get_pin_name(this->reset_pin_, reset_buf), + get_pin_name(this->de_pin_, de_buf), get_pin_name(this->pclk_pin_, pclk_buf), + get_pin_name(this->hsync_pin_, hsync_buf), get_pin_name(this->vsync_pin_, vsync_buf)); this->dump_pins_(8, 13, "Blue", 0); this->dump_pins_(13, 16, "Green", 0); From c4f7d09553b2c634c4d007f201470307a0068d38 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 22 Jan 2026 12:53:38 -1000 Subject: [PATCH 0347/2030] [rpi_dpi_rgb] Fix dump_summary deprecation warning (#13461) --- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index a81bb17dfc..363f4b63b8 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -1,5 +1,6 @@ #ifdef USE_ESP32_VARIANT_ESP32S3 #include "rpi_dpi_rgb.h" +#include "esphome/core/gpio.h" #include "esphome/core/log.h" namespace esphome { @@ -134,8 +135,11 @@ void RpiDpiRgb::dump_config() { LOG_PIN(" Enable Pin: ", this->enable_pin_); LOG_PIN(" Reset Pin: ", this->reset_pin_); size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); - for (size_t i = 0; i != data_pin_count; i++) - ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, (this->data_pins_[i])->dump_summary().c_str()); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + for (size_t i = 0; i != data_pin_count; i++) { + this->data_pins_[i]->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGCONFIG(TAG, " Data pin %d: %s", i, pin_summary); + } } void RpiDpiRgb::reset_display_() const { From 9cc39621a6bdfe505fb668b502ecaac1431dc457 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Thu, 22 Jan 2026 20:35:37 -0600 Subject: [PATCH 0348/2030] [ir_rf_proxy] Remove unnecessary headers, add tests (#13464) --- esphome/components/ir_rf_proxy/ir_rf_proxy.h | 2 - tests/components/ir_rf_proxy/common-rx.yaml | 18 +++++++++ tests/components/ir_rf_proxy/common-tx.yaml | 19 +++++++++ tests/components/ir_rf_proxy/common.yaml | 39 +------------------ .../ir_rf_proxy/test-rx.esp32-idf.yaml | 7 ++++ .../ir_rf_proxy/test-rx.esp8266-ard.yaml | 7 ++++ .../ir_rf_proxy/test-rx.rp2040-ard.yaml | 7 ++++ .../ir_rf_proxy/test-tx.esp32-idf.yaml | 7 ++++ .../ir_rf_proxy/test-tx.esp8266-ard.yaml | 7 ++++ .../ir_rf_proxy/test-tx.rp2040-ard.yaml | 7 ++++ .../ir_rf_proxy/test.bk72xx-ard.yaml | 8 ++++ .../ir_rf_proxy/test.esp32-idf.yaml | 5 ++- .../ir_rf_proxy/test.esp8266-ard.yaml | 5 ++- .../ir_rf_proxy/test.rp2040-ard.yaml | 5 ++- 14 files changed, 101 insertions(+), 42 deletions(-) create mode 100644 tests/components/ir_rf_proxy/common-rx.yaml create mode 100644 tests/components/ir_rf_proxy/common-tx.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml create mode 100644 tests/components/ir_rf_proxy/test.bk72xx-ard.yaml diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.h b/esphome/components/ir_rf_proxy/ir_rf_proxy.h index d7c8919def..f067a6e17a 100644 --- a/esphome/components/ir_rf_proxy/ir_rf_proxy.h +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.h @@ -5,8 +5,6 @@ // Once the API is considered stable, this warning will be removed. #include "esphome/components/infrared/infrared.h" -#include "esphome/components/remote_transmitter/remote_transmitter.h" -#include "esphome/components/remote_receiver/remote_receiver.h" namespace esphome::ir_rf_proxy { diff --git a/tests/components/ir_rf_proxy/common-rx.yaml b/tests/components/ir_rf_proxy/common-rx.yaml new file mode 100644 index 0000000000..0f758f832d --- /dev/null +++ b/tests/components/ir_rf_proxy/common-rx.yaml @@ -0,0 +1,18 @@ +remote_receiver: + id: ir_receiver + pin: ${rx_pin} + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared receiver + - platform: ir_rf_proxy + id: ir_rx + name: "IR Receiver" + remote_receiver_id: ir_receiver + + # RF 900MHz receiver + - platform: ir_rf_proxy + id: rf_900_rx + name: "RF 900 Receiver" + frequency: 900 MHz + remote_receiver_id: ir_receiver diff --git a/tests/components/ir_rf_proxy/common-tx.yaml b/tests/components/ir_rf_proxy/common-tx.yaml new file mode 100644 index 0000000000..4af9e2635e --- /dev/null +++ b/tests/components/ir_rf_proxy/common-tx.yaml @@ -0,0 +1,19 @@ +remote_transmitter: + id: ir_transmitter + pin: ${tx_pin} + carrier_duty_percent: 50% + +# Test various hardware types with transmitter/receiver using infrared platform +infrared: + # Infrared transmitter + - platform: ir_rf_proxy + id: ir_tx + name: "IR Transmitter" + remote_transmitter_id: ir_transmitter + + # RF 433MHz transmitter + - platform: ir_rf_proxy + id: rf_433_tx + name: "RF 433 Transmitter" + frequency: 433 MHz + remote_transmitter_id: ir_transmitter diff --git a/tests/components/ir_rf_proxy/common.yaml b/tests/components/ir_rf_proxy/common.yaml index cd2b10d31b..53a0cd379a 100644 --- a/tests/components/ir_rf_proxy/common.yaml +++ b/tests/components/ir_rf_proxy/common.yaml @@ -1,42 +1,7 @@ +network: + wifi: ssid: MySSID password: password1 api: - -remote_transmitter: - id: ir_transmitter - pin: ${tx_pin} - carrier_duty_percent: 50% - -remote_receiver: - id: ir_receiver - pin: ${rx_pin} - -# Test various hardware types with transmitter/receiver using infrared platform -infrared: - # Infrared transmitter - - platform: ir_rf_proxy - id: ir_tx - name: "IR Transmitter" - remote_transmitter_id: ir_transmitter - - # Infrared receiver - - platform: ir_rf_proxy - id: ir_rx - name: "IR Receiver" - remote_receiver_id: ir_receiver - - # RF 433MHz transmitter - - platform: ir_rf_proxy - id: rf_433_tx - name: "RF 433 Transmitter" - frequency: 433 MHz - remote_transmitter_id: ir_transmitter - - # RF 900MHz receiver - - platform: ir_rf_proxy - id: rf_900_rx - name: "RF 900 Receiver" - frequency: 900 MHz - remote_receiver_id: ir_receiver diff --git a/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml b/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml new file mode 100644 index 0000000000..8172885b31 --- /dev/null +++ b/tests/components/ir_rf_proxy/test-rx.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml b/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml new file mode 100644 index 0000000000..7162f15b2d --- /dev/null +++ b/tests/components/ir_rf_proxy/test-tx.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml b/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..a0e145f476 --- /dev/null +++ b/tests/components/ir_rf_proxy/test.bk72xx-ard.yaml @@ -0,0 +1,8 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.esp32-idf.yaml b/tests/components/ir_rf_proxy/test.esp32-idf.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.esp32-idf.yaml +++ b/tests/components/ir_rf_proxy/test.esp32-idf.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.esp8266-ard.yaml b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.esp8266-ard.yaml +++ b/tests/components/ir_rf_proxy/test.esp8266-ard.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml diff --git a/tests/components/ir_rf_proxy/test.rp2040-ard.yaml b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml index b516342f3b..a0e145f476 100644 --- a/tests/components/ir_rf_proxy/test.rp2040-ard.yaml +++ b/tests/components/ir_rf_proxy/test.rp2040-ard.yaml @@ -2,4 +2,7 @@ substitutions: tx_pin: GPIO4 rx_pin: GPIO5 -<<: !include common.yaml +packages: + common: !include common.yaml + rx: !include common-rx.yaml + tx: !include common-tx.yaml From 6870d3dc5086dd8b80a86a7e0131f5843273182b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 24 Jan 2026 09:02:27 +1100 Subject: [PATCH 0349/2030] [mipi_rgb] Add software reset command to st7701s init sequence (#13470) --- esphome/components/mipi_rgb/models/st7701s.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/mipi_rgb/models/st7701s.py b/esphome/components/mipi_rgb/models/st7701s.py index 3c66380d04..990a1ca4f3 100644 --- a/esphome/components/mipi_rgb/models/st7701s.py +++ b/esphome/components/mipi_rgb/models/st7701s.py @@ -55,6 +55,7 @@ st7701s = ST7701S( pclk_frequency="16MHz", pclk_inverted=True, initsequence=( + (0x01,), # Software Reset (0xFF, 0x77, 0x01, 0x00, 0x00, 0x10), # Page 0 (0xC0, 0x3B, 0x00), (0xC1, 0x0D, 0x02), (0xC2, 0x31, 0x05), (0xB0, 0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,), From ef469c20dfffd31cfb6a144fbacb4dd2c75b76fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 23 Jan 2026 12:37:06 -1000 Subject: [PATCH 0350/2030] [slow_pwm] Fix dump_summary deprecation warning (#13460) --- esphome/components/slow_pwm/slow_pwm_output.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/slow_pwm/slow_pwm_output.cpp b/esphome/components/slow_pwm/slow_pwm_output.cpp index 48ded94b3a..033729c407 100644 --- a/esphome/components/slow_pwm/slow_pwm_output.cpp +++ b/esphome/components/slow_pwm/slow_pwm_output.cpp @@ -1,6 +1,7 @@ #include "slow_pwm_output.h" -#include "esphome/core/log.h" #include "esphome/core/application.h" +#include "esphome/core/gpio.h" +#include "esphome/core/log.h" namespace esphome { namespace slow_pwm { @@ -20,7 +21,9 @@ void SlowPWMOutput::set_output_state_(bool new_state) { } if (new_state != current_state_) { if (this->pin_) { - ESP_LOGV(TAG, "Switching output pin %s to %s", this->pin_->dump_summary().c_str(), ONOFF(new_state)); + char pin_summary[GPIO_SUMMARY_MAX_LEN]; + this->pin_->dump_summary(pin_summary, sizeof(pin_summary)); + ESP_LOGV(TAG, "Switching output pin %s to %s", pin_summary, ONOFF(new_state)); } else { ESP_LOGV(TAG, "Switching to %s", ONOFF(new_state)); } From d285706b41d30be068cbf87782f76810cb36a20b Mon Sep 17 00:00:00 2001 From: Big Mike Date: Fri, 23 Jan 2026 17:03:23 -0600 Subject: [PATCH 0351/2030] [sen5x] Fix store baseline functionality (#13469) --- esphome/components/sen5x/sen5x.cpp | 94 +++++++++++++----------------- esphome/components/sen5x/sen5x.h | 15 ++--- esphome/components/sen5x/sensor.py | 1 + 3 files changed, 45 insertions(+), 65 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index d5c9dfa3ae..09d93a2b2f 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -124,8 +124,8 @@ void SEN5XComponent::setup() { sen5x_type = SEN55; } } - ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); } + ESP_LOGD(TAG, "Product name: %s", this->product_name_.c_str()); if (this->humidity_sensor_ && sen5x_type == SEN50) { ESP_LOGE(TAG, "Relative humidity requires a SEN54 or SEN55"); this->humidity_sensor_ = nullptr; // mark as not used @@ -159,28 +159,14 @@ void SEN5XComponent::setup() { // This ensures the baseline storage is cleared after OTA // Serial numbers are unique to each sensor, so multiple sensors can be used without conflict uint32_t hash = fnv1a_hash_extend(App.get_config_version_hash(), combined_serial); - this->pref_ = global_preferences->make_preference(hash, true); - - if (this->pref_.load(&this->voc_baselines_storage_)) { - ESP_LOGI(TAG, "Loaded VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - } - - // Initialize storage timestamp - this->seconds_since_last_store_ = 0; - - if (this->voc_baselines_storage_.state0 > 0 && this->voc_baselines_storage_.state1 > 0) { - ESP_LOGI(TAG, "Setting VOC baseline from save state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - uint16_t states[4]; - - states[0] = this->voc_baselines_storage_.state0 >> 16; - states[1] = this->voc_baselines_storage_.state0 & 0xFFFF; - states[2] = this->voc_baselines_storage_.state1 >> 16; - states[3] = this->voc_baselines_storage_.state1 & 0xFFFF; - - if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, states, 4)) { - ESP_LOGE(TAG, "Failed to set VOC baseline from saved state"); + this->pref_ = global_preferences->make_preference(hash, true); + this->voc_baseline_time_ = App.get_loop_component_start_time(); + if (this->pref_.load(&this->voc_baseline_state_)) { + if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE, this->voc_baseline_state_, 4)) { + ESP_LOGE(TAG, "VOC Baseline State write to sensor failed"); + } else { + ESP_LOGV(TAG, "VOC Baseline State loaded"); + delay(20); } } } @@ -288,6 +274,14 @@ void SEN5XComponent::dump_config() { ESP_LOGCONFIG(TAG, " RH/T acceleration mode: %s", LOG_STR_ARG(rht_accel_mode_to_string(this->acceleration_mode_.value()))); } + if (this->voc_sensor_) { + char hex_buf[5 * 4]; + format_hex_pretty_to(hex_buf, this->voc_baseline_state_, 4, 0); + ESP_LOGCONFIG(TAG, + " Store Baseline: %s\n" + " State: %s\n", + TRUEFALSE(this->store_baseline_), hex_buf); + } LOG_UPDATE_INTERVAL(this); LOG_SENSOR(" ", "PM 1.0", this->pm_1_0_sensor_); LOG_SENSOR(" ", "PM 2.5", this->pm_2_5_sensor_); @@ -304,36 +298,6 @@ void SEN5XComponent::update() { return; } - // Store baselines after defined interval or if the difference between current and stored baseline becomes too - // much - if (this->store_baseline_ && this->seconds_since_last_store_ > SHORTEST_BASELINE_STORE_INTERVAL) { - if (this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE)) { - // run it a bit later to avoid adding a delay here - this->set_timeout(550, [this]() { - uint16_t states[4]; - if (this->read_data(states, 4)) { - uint32_t state0 = states[0] << 16 | states[1]; - uint32_t state1 = states[2] << 16 | states[3]; - if ((uint32_t) std::abs(static_cast(this->voc_baselines_storage_.state0 - state0)) > - MAXIMUM_STORAGE_DIFF || - (uint32_t) std::abs(static_cast(this->voc_baselines_storage_.state1 - state1)) > - MAXIMUM_STORAGE_DIFF) { - this->seconds_since_last_store_ = 0; - this->voc_baselines_storage_.state0 = state0; - this->voc_baselines_storage_.state1 = state1; - - if (this->pref_.save(&this->voc_baselines_storage_)) { - ESP_LOGI(TAG, "Stored VOC baseline state0: 0x%04" PRIX32 ", state1: 0x%04" PRIX32, - this->voc_baselines_storage_.state0, this->voc_baselines_storage_.state1); - } else { - ESP_LOGW(TAG, "Could not store VOC baselines"); - } - } - } - }); - } - } - if (!this->write_command(SEN5X_CMD_READ_MEASUREMENT)) { this->status_set_warning(); ESP_LOGD(TAG, "Write error: read measurement (%d)", this->last_error_); @@ -402,7 +366,29 @@ void SEN5XComponent::update() { if (this->nox_sensor_ != nullptr) { this->nox_sensor_->publish_state(nox); } - this->status_clear_warning(); + + if (!this->voc_sensor_ || !this->store_baseline_ || + (App.get_loop_component_start_time() - this->voc_baseline_time_) < SHORTEST_BASELINE_STORE_INTERVAL) { + this->status_clear_warning(); + } else { + this->voc_baseline_time_ = App.get_loop_component_start_time(); + if (!this->write_command(SEN5X_CMD_VOC_ALGORITHM_STATE)) { + this->status_set_warning(); + ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); + } else { + this->set_timeout(20, [this]() { + if (!this->read_data(this->voc_baseline_state_, 4)) { + this->status_set_warning(); + ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); + } else { + if (this->pref_.save(&this->voc_baseline_state_)) { + ESP_LOGD(TAG, "VOC Baseline State saved"); + } + this->status_clear_warning(); + } + }); + } + } }); } diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index 9e5b6bf231..aaa672dbc4 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -24,11 +24,6 @@ enum RhtAccelerationMode : uint16_t { HIGH_ACCELERATION = 2, }; -struct Sen5xBaselines { - int32_t state0; - int32_t state1; -} PACKED; // NOLINT - struct GasTuning { uint16_t index_offset; uint16_t learning_time_offset_hours; @@ -44,11 +39,9 @@ struct TemperatureCompensation { uint16_t time_constant; }; -// Shortest time interval of 3H for storing baseline values. +// Shortest time interval of 2H (in milliseconds) for storing baseline values. // Prevents wear of the flash because of too many write operations -static const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 10800; -// Store anyway if the baseline difference exceeds the max storage diff value -static const uint32_t MAXIMUM_STORAGE_DIFF = 50; +static const uint32_t SHORTEST_BASELINE_STORE_INTERVAL = 2 * 60 * 60 * 1000; class SEN5XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { public: @@ -107,7 +100,8 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri bool write_tuning_parameters_(uint16_t i2c_command, const GasTuning &tuning); bool write_temperature_compensation_(const TemperatureCompensation &compensation); - uint32_t seconds_since_last_store_; + uint16_t voc_baseline_state_[4]{0}; + uint32_t voc_baseline_time_; uint16_t firmware_version_; ERRORCODE error_code_; uint8_t serial_number_[4]; @@ -132,7 +126,6 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri optional temperature_compensation_; ESPPreferenceObject pref_; std::string product_name_; - Sen5xBaselines voc_baselines_storage_; }; } // namespace sen5x diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 9c3114b9e2..538a2f5239 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -210,6 +210,7 @@ SENSOR_MAP = { SETTING_MAP = { CONF_AUTO_CLEANING_INTERVAL: "set_auto_cleaning_interval", CONF_ACCELERATION_MODE: "set_acceleration_mode", + CONF_STORE_BASELINE: "set_store_baseline", } From 10cbd0164ad36dfb44d622e39140194151f612ae Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 24 Jan 2026 11:44:34 +1100 Subject: [PATCH 0352/2030] [lvgl] Fix setting empty text (#13494) --- esphome/components/lvgl/widgets/label.py | 2 +- tests/components/lvgl/lvgl-package.yaml | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/lvgl/widgets/label.py b/esphome/components/lvgl/widgets/label.py index 3a3a997737..8afd8d610f 100644 --- a/esphome/components/lvgl/widgets/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -32,7 +32,7 @@ class LabelType(WidgetType): async def to_code(self, w: Widget, config): """For a text object, create and set text""" - if value := config.get(CONF_TEXT): + if (value := config.get(CONF_TEXT)) is not None: await w.set_property(CONF_TEXT, await lv_text.process(value)) await w.set_property(CONF_LONG_MODE, config) await w.set_property(CONF_RECOLOR, config) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 65d629bcdf..3635fc710f 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -197,6 +197,9 @@ lvgl: - lvgl.label.update: id: msgbox_label text: Unloaded + - lvgl.label.update: + id: msgbox_label + text: "" # Empty text on_all_events: logger.log: format: "Event %s" From d6841ba33a754f2cb9be6dd08deb15ac6f813839 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Fri, 23 Jan 2026 18:53:20 -0600 Subject: [PATCH 0353/2030] [light] Fix cwww state restore (#13493) --- esphome/components/light/light_call.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 234d641f0d..6d42dd1513 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -391,7 +391,10 @@ void LightCall::transform_parameters_() { min_mireds > 0.0f && max_mireds > 0.0f) { ESP_LOGD(TAG, "'%s': setting cold/warm white channels using white/color temperature values", this->parent_->get_name().c_str()); - if (this->has_color_temperature()) { + // Only compute cold_white/warm_white from color_temperature if they're not already explicitly set. + // This is important for state restoration, where both color_temperature and cold_white/warm_white + // are restored from flash - we want to preserve the saved cold_white/warm_white values. + if (this->has_color_temperature() && !this->has_cold_white() && !this->has_warm_white()) { const float color_temp = clamp(this->color_temperature_, min_mireds, max_mireds); const float range = max_mireds - min_mireds; const float ww_fraction = (color_temp - min_mireds) / range; From 56a2a2269fff7e716c19a79725b11bd4b2b7c761 Mon Sep 17 00:00:00 2001 From: Jas Strong Date: Fri, 23 Jan 2026 19:01:19 -0800 Subject: [PATCH 0354/2030] [rd03d] Fix speed and resolution field order (#13495) Co-authored-by: jas --- esphome/components/rd03d/rd03d.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index d9b0b59fe9..ba05abe8e0 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -133,14 +133,17 @@ void RD03DComponent::process_frame_() { uint8_t offset = FRAME_HEADER_SIZE + (i * TARGET_DATA_SIZE); // Extract raw bytes for this target + // Note: Despite datasheet Table 5-2 showing order as X, Y, Speed, Resolution, + // actual radar output has Resolution before Speed (verified empirically - + // stationary targets were showing non-zero speed with original field order) uint8_t x_low = this->buffer_[offset + 0]; uint8_t x_high = this->buffer_[offset + 1]; uint8_t y_low = this->buffer_[offset + 2]; uint8_t y_high = this->buffer_[offset + 3]; - uint8_t speed_low = this->buffer_[offset + 4]; - uint8_t speed_high = this->buffer_[offset + 5]; - uint8_t res_low = this->buffer_[offset + 6]; - uint8_t res_high = this->buffer_[offset + 7]; + uint8_t res_low = this->buffer_[offset + 4]; + uint8_t res_high = this->buffer_[offset + 5]; + uint8_t speed_low = this->buffer_[offset + 6]; + uint8_t speed_high = this->buffer_[offset + 7]; // Decode values per RD-03D format int16_t x = decode_value(x_low, x_high); From 70e45706d96eeebc6e577d03323c70f75d79a10e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 23 Jan 2026 22:01:40 -0500 Subject: [PATCH 0355/2030] [modbus_controller] Fix YAML serialization error with custom_command (#13482) Co-authored-by: Claude Opus 4.5 --- esphome/components/modbus_controller/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 1c23783ce3..c45c338bb3 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -279,7 +279,7 @@ def modbus_calc_properties(config): if isinstance(value, str): value = value.encode() config[CONF_ADDRESS] = binascii.crc_hqx(value, 0) - config[CONF_REGISTER_TYPE] = ModbusRegisterType.CUSTOM + config[CONF_REGISTER_TYPE] = cv.enum(MODBUS_REGISTER_TYPE)("custom") config[CONF_FORCE_NEW_RANGE] = True return byte_offset, reg_count From 723f67d5e21ad3f52cd6faee6ff1fb0eb6ba1b5f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 23 Jan 2026 23:13:03 -0500 Subject: [PATCH 0356/2030] [i2c] Increase ESP-IDF I2C transaction timeout from 20ms to 100ms (#13483) Co-authored-by: Claude Opus 4.5 --- esphome/components/i2c/i2c_bus_esp_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index 191c849aa3..7a965ce5ad 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -185,7 +185,7 @@ ErrorCode IDFI2CBus::write_readv(uint8_t address, const uint8_t *write_buffer, s } jobs[num_jobs++].command = I2C_MASTER_CMD_STOP; ESP_LOGV(TAG, "Sending %zu jobs", num_jobs); - esp_err_t err = i2c_master_execute_defined_operations(this->dev_, jobs, num_jobs, 20); + esp_err_t err = i2c_master_execute_defined_operations(this->dev_, jobs, num_jobs, 100); if (err == ESP_ERR_INVALID_STATE) { ESP_LOGV(TAG, "TX to %02X failed: not acked", address); return ERROR_NOT_ACKNOWLEDGED; From cc2f3d85dc4f0394fec3985d0b2f2769a2d1ea67 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 26 Jan 2026 03:52:23 +1100 Subject: [PATCH 0357/2030] [wifi] Fix watchdog timeout on P4 WiFi scan (#13520) --- esphome/components/esp32_hosted/__init__.py | 2 ++ .../wifi/wifi_component_esp_idf.cpp | 20 ++++++++++++++++--- esphome/core/defines.h | 1 + 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index e40431c851..170f436f02 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -12,6 +12,7 @@ from esphome.const import ( KEY_FRAMEWORK_VERSION, ) from esphome.core import CORE +from esphome.cpp_generator import add_define CODEOWNERS = ["@swoboda1337"] @@ -42,6 +43,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): + add_define("USE_ESP32_HOSTED") if config[CONF_ACTIVE_HIGH]: esp32.add_idf_sdkconfig_option( "CONFIG_ESP_HOSTED_SDIO_RESET_ACTIVE_HIGH", diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 99474ac2f8..15fd407e3c 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #ifdef USE_WIFI_WPA2_EAP #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) @@ -828,16 +829,29 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { uint16_t number = it.number; scan_result_.init(number); - - // Process one record at a time to avoid large buffer allocation - wifi_ap_record_t record; +#ifdef USE_ESP32_HOSTED + // getting records one at a time fails on P4 with hosted esp32 WiFi coprocessor + // Presumably an upstream bug, work-around by getting all records at once + auto records = std::make_unique(number); + err = esp_wifi_scan_get_ap_records(&number, records.get()); + if (err != ESP_OK) { + esp_wifi_clear_ap_list(); + ESP_LOGW(TAG, "esp_wifi_scan_get_ap_records failed: %s", esp_err_to_name(err)); + return; + } for (uint16_t i = 0; i < number; i++) { + wifi_ap_record_t &record = records[i]; +#else + // Process one record at a time to avoid large buffer allocation + for (uint16_t i = 0; i < number; i++) { + wifi_ap_record_t record; err = esp_wifi_scan_get_ap_record(&record); if (err != ESP_OK) { ESP_LOGW(TAG, "esp_wifi_scan_get_ap_record failed: %s", esp_err_to_name(err)); esp_wifi_clear_ap_list(); // Free remaining records not yet retrieved break; } +#endif // USE_ESP32_HOSTED bssid_t bssid; std::copy(record.bssid, record.bssid + 6, bssid.begin()); std::string ssid(reinterpret_cast(record.ssid)); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c229d1df7d..3723d96c79 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -42,6 +42,7 @@ #define USE_DEVICES #define USE_DISPLAY #define USE_ENTITY_ICON +#define USE_ESP32_HOSTED #define USE_ESP32_IMPROV_STATE_CALLBACK #define USE_EVENT #define USE_FAN From 3a7b83ba934f4dc2bf1c2df9495ba048af75fd08 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 25 Jan 2026 07:16:07 -1000 Subject: [PATCH 0358/2030] [wifi] Fix scan flag race condition causing reconnect failure on ESP8266/LibreTiny (#13514) --- esphome/components/wifi/wifi_component_esp8266.cpp | 4 ++++ esphome/components/wifi/wifi_component_libretiny.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 6fb5dd5769..4c204f7cf3 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -698,6 +698,10 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { if (!this->wifi_mode_(true, {})) return false; + // Reset scan_done_ before starting new scan to prevent stale flag from previous scan + // (e.g., roaming scan completed just before unexpected disconnect) + this->scan_done_ = false; + struct scan_config config {}; memset(&config, 0, sizeof(config)); config.ssid = nullptr; diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index cc9f4ec193..20cd32fa8f 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -649,6 +649,10 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { if (!this->wifi_mode_(true, {})) return false; + // Reset scan_done_ before starting new scan to prevent stale flag from previous scan + // (e.g., roaming scan completed just before unexpected disconnect) + this->scan_done_ = false; + // need to use WiFi because of WiFiScanClass allocations :( int16_t err = WiFi.scanNetworks(true, true, passive, 200); if (err != WIFI_SCAN_RUNNING) { From 214ce95cf3d05a19413d715566b5dce5165863f4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 25 Jan 2026 12:22:18 -0500 Subject: [PATCH 0359/2030] Bump version to 2026.1.2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 20582c14a6..7fcf0f92f1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.1 +PROJECT_NUMBER = 2026.1.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 0c6a46e233..36adcbf500 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.1" +__version__ = "2026.1.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 1c9a9c75369c4b2772b3c0e08604fec9875b3e0c Mon Sep 17 00:00:00 2001 From: sebcaps Date: Mon, 26 Jan 2026 07:07:29 +0100 Subject: [PATCH 0360/2030] [mhz19] Fix Uninitialized var warning message (#13526) --- esphome/components/mhz19/mhz19.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 00e6e14d85..259d597b44 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -155,6 +155,9 @@ void MHZ19Component::dump_config() { case MHZ19_DETECTION_RANGE_0_10000PPM: range_str = "0 to 10000ppm"; break; + default: + range_str = "default"; + break; } ESP_LOGCONFIG(TAG, " Detection range: %s", range_str); } From dd91039ff1e6bae2070c671fe20c7f454f8dbce1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 15:43:16 -1000 Subject: [PATCH 0361/2030] Bump github/codeql-action from 4.31.11 to 4.32.0 (#13559) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 15edd8421a..be761cee3d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@19b2f06db2b6f5108140aeb04014ef02b648f789 # v4.31.11 + uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 with: category: "/language:${{matrix.language}}" From 65dc1825267ca18be7eb92a778ec9803a61ecc1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 15:43:27 -1000 Subject: [PATCH 0362/2030] Bump setuptools from 80.10.1 to 80.10.2 (#13558) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 3ce2e6ebec..1bd43ea2f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools==80.10.1", "wheel>=0.43,<0.47"] +requires = ["setuptools==80.10.2", "wheel>=0.43,<0.47"] build-backend = "setuptools.build_meta" [project] From 27a212c14da264f53070aadea3d0ce8e97aa0aaf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jan 2026 15:43:40 -1000 Subject: [PATCH 0363/2030] Bump aioesphomeapi from 43.13.0 to 43.14.0 (#13557) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a707fda059..821324262b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 -aioesphomeapi==43.13.0 +aioesphomeapi==43.14.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 0cc80557578538c7be12a915f753dd4f67a17b5d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 26 Jan 2026 22:07:27 -0500 Subject: [PATCH 0364/2030] [http_request] Add custom CA certificate support for ESP32 (#13552) Co-authored-by: Claude Opus 4.5 --- esphome/components/http_request/__init__.py | 11 +++++++++-- .../components/http_request/http_request_idf.cpp | 15 ++++++++++----- .../components/http_request/http_request_idf.h | 2 ++ .../http_request/test-custom-ca.esp32-idf.yaml | 7 +++++++ tests/components/http_request/test_ca.pem | 10 ++++++++++ 5 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 tests/components/http_request/test-custom-ca.esp32-idf.yaml create mode 100644 tests/components/http_request/test_ca.pem diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 9f74fb1023..7347b8ebf7 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -126,7 +126,7 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_CA_CERTIFICATE_PATH): cv.All( cv.file_, - cv.only_on(PLATFORM_HOST), + cv.Any(cv.only_on(PLATFORM_HOST), cv.only_on_esp32), ), } ).extend(cv.COMPONENT_SCHEMA), @@ -160,7 +160,14 @@ async def to_code(config): cg.add(var.set_verify_ssl(config[CONF_VERIFY_SSL])) if config.get(CONF_VERIFY_SSL): - esp32.add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True) + if ca_cert_path := config.get(CONF_CA_CERTIFICATE_PATH): + with open(ca_cert_path, encoding="utf-8") as f: + ca_cert_content = f.read() + cg.add(var.set_ca_certificate(ca_cert_content)) + else: + esp32.add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True + ) esp32.add_idf_sdkconfig_option( "CONFIG_ESP_TLS_INSECURE", diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index b6fb7f7ea9..680ae6c801 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -27,8 +27,9 @@ void HttpRequestIDF::dump_config() { HttpRequestComponent::dump_config(); ESP_LOGCONFIG(TAG, " Buffer Size RX: %u\n" - " Buffer Size TX: %u", - this->buffer_size_rx_, this->buffer_size_tx_); + " Buffer Size TX: %u\n" + " Custom CA Certificate: %s", + this->buffer_size_rx_, this->buffer_size_tx_, YESNO(this->ca_certificate_ != nullptr)); } esp_err_t HttpRequestIDF::http_event_handler(esp_http_client_event_t *evt) { @@ -88,11 +89,15 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c config.disable_auto_redirect = !this->follow_redirects_; config.max_redirection_count = this->redirect_limit_; config.auth_type = HTTP_AUTH_TYPE_BASIC; -#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE if (secure && this->verify_ssl_) { - config.crt_bundle_attach = esp_crt_bundle_attach; - } + if (this->ca_certificate_ != nullptr) { + config.cert_pem = this->ca_certificate_; +#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE + } else { + config.crt_bundle_attach = esp_crt_bundle_attach; #endif + } + } if (this->useragent_ != nullptr) { config.user_agent = this->useragent_; diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 0fae67f5bc..ad11811a8f 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -35,6 +35,7 @@ class HttpRequestIDF : public HttpRequestComponent { void set_buffer_size_rx(uint16_t buffer_size_rx) { this->buffer_size_rx_ = buffer_size_rx; } void set_buffer_size_tx(uint16_t buffer_size_tx) { this->buffer_size_tx_ = buffer_size_tx; } void set_verify_ssl(bool verify_ssl) { this->verify_ssl_ = verify_ssl; } + void set_ca_certificate(const char *ca_certificate) { this->ca_certificate_ = ca_certificate; } protected: std::shared_ptr perform(const std::string &url, const std::string &method, const std::string &body, @@ -44,6 +45,7 @@ class HttpRequestIDF : public HttpRequestComponent { uint16_t buffer_size_rx_{}; uint16_t buffer_size_tx_{}; bool verify_ssl_{true}; + const char *ca_certificate_{nullptr}; /// @brief Monitors the http client events to gather response headers static esp_err_t http_event_handler(esp_http_client_event_t *evt); diff --git a/tests/components/http_request/test-custom-ca.esp32-idf.yaml b/tests/components/http_request/test-custom-ca.esp32-idf.yaml new file mode 100644 index 0000000000..0b1b2f8829 --- /dev/null +++ b/tests/components/http_request/test-custom-ca.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + verify_ssl: "true" + +http_request: + ca_certificate_path: $component_dir/test_ca.pem + +<<: !include common.yaml diff --git a/tests/components/http_request/test_ca.pem b/tests/components/http_request/test_ca.pem new file mode 100644 index 0000000000..30cbc1a3c4 --- /dev/null +++ b/tests/components/http_request/test_ca.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBkTCB+wIJAKHBfpegPjMCMA0GCSqGSIb3DQEBCwUAMBExDzANBgNVBAMMBnVu +dXNlZDAeFw0yNDAxMDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMBExDzANBgNVBAMM +BnVudXNlZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQC5mMUB1hOgLmlnXtsvcGMP +XkhAqZaR0dDPW5OS8VEopWLJCX9Y0cvNCqiDI8cnP8pP8XJGU1hGLvA5PJzWnWZz +AgMBAAGjUzBRMB0GA1UdDgQWBBR5oQ9KqFeZOdBuAJrXxEP0dqzPtTAfBgNVHSME +GDAWgBR5oQ9KqFeZOdBuAJrXxEP0dqzPtTAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBCwUAA0EAKqZFf6+f8FPDbKyPCpssquojgn7fEXqr/I/yz0R5CowGdMms +H3WH3aKP4lLSHdPTBtfIoJi3gEIZjFxp3S1TWw== +-----END CERTIFICATE----- From 123ee02d390e9ea68f0ec62adacb00e662820b39 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:13:18 -1000 Subject: [PATCH 0365/2030] [ota] Improve error message when device closes connection without responding (#13562) --- esphome/espota2.py | 6 ++++++ tests/unit_tests/test_espota2.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/esphome/espota2.py b/esphome/espota2.py index 95dd602ad2..2d90251b38 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -154,6 +154,12 @@ def check_error(data: list[int] | bytes, expect: int | list[int] | None) -> None """ if not expect: return + if not data: + raise OTAError( + "Error: Device closed connection without responding. " + "This may indicate the device ran out of memory, " + "a network issue, or the connection was interrupted." + ) dat = data[0] if dat == RESPONSE_ERROR_MAGIC: raise OTAError("Error: Invalid magic byte") diff --git a/tests/unit_tests/test_espota2.py b/tests/unit_tests/test_espota2.py index 02f965782b..1885b769f1 100644 --- a/tests/unit_tests/test_espota2.py +++ b/tests/unit_tests/test_espota2.py @@ -192,6 +192,20 @@ def test_check_error_unexpected_response() -> None: espota2.check_error([0x7F], [espota2.RESPONSE_OK, espota2.RESPONSE_AUTH_OK]) +def test_check_error_empty_data() -> None: + """Test check_error raises error when device closes connection without responding.""" + with pytest.raises( + espota2.OTAError, match="Device closed connection without responding" + ): + espota2.check_error([], [espota2.RESPONSE_OK]) + + # Also test with empty bytes + with pytest.raises( + espota2.OTAError, match="Device closed connection without responding" + ): + espota2.check_error(b"", [espota2.RESPONSE_OK]) + + def test_send_check_with_various_data_types(mock_socket: Mock) -> None: """Test send_check handles different data types.""" From bc491749205a2942880d409ab5bbae78943d77dc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:18:36 -1000 Subject: [PATCH 0366/2030] Add additional text_sensor filter tests (#13479) --- tests/components/text_sensor/common.yaml | 13 ++ .../fixtures/text_sensor_raw_state.yaml | 100 +++++++++++++ .../integration/test_text_sensor_raw_state.py | 141 ++++++++++++++++++ 3 files changed, 254 insertions(+) diff --git a/tests/components/text_sensor/common.yaml b/tests/components/text_sensor/common.yaml index 4459c0fa44..97b0b8ad94 100644 --- a/tests/components/text_sensor/common.yaml +++ b/tests/components/text_sensor/common.yaml @@ -64,3 +64,16 @@ text_sensor: - suffix -> SUFFIX - map: - PREFIX text SUFFIX -> mapped + + - platform: template + name: "Test Lambda Filter" + id: test_lambda_filter + filters: + - lambda: |- + return {"[" + x + "]"}; + - to_upper + - lambda: |- + if (x.length() > 10) { + return {x.substr(0, 10) + "..."}; + } + return {x}; diff --git a/tests/integration/fixtures/text_sensor_raw_state.yaml b/tests/integration/fixtures/text_sensor_raw_state.yaml index 54ab2e8dcc..a4b735e889 100644 --- a/tests/integration/fixtures/text_sensor_raw_state.yaml +++ b/tests/integration/fixtures/text_sensor_raw_state.yaml @@ -56,6 +56,36 @@ text_sensor: - prepend: "[" - append: "]" + - platform: template + name: "To Lower Sensor" + id: to_lower_sensor + filters: + - to_lower + + - platform: template + name: "Lambda Sensor" + id: lambda_sensor + filters: + - lambda: |- + return {"[" + x + "]"}; + + - platform: template + name: "Lambda Raw State Sensor" + id: lambda_raw_state_sensor + filters: + - lambda: |- + return {x + " MODIFIED"}; + + - platform: template + name: "Lambda Skip Sensor" + id: lambda_skip_sensor + filters: + - lambda: |- + if (x == "skip") { + return {}; + } + return {x + " passed"}; + # Button to publish values and log raw_state vs state button: - platform: template @@ -179,3 +209,73 @@ button: format: "CHAINED: state='%s'" args: - id(chained_sensor).state.c_str() + + - platform: template + name: "Test To Lower Button" + id: test_to_lower_button + on_press: + - text_sensor.template.publish: + id: to_lower_sensor + state: "HELLO WORLD" + - delay: 50ms + - logger.log: + format: "TO_LOWER: state='%s'" + args: + - id(to_lower_sensor).state.c_str() + + - platform: template + name: "Test Lambda Button" + id: test_lambda_button + on_press: + - text_sensor.template.publish: + id: lambda_sensor + state: "test" + - delay: 50ms + - logger.log: + format: "LAMBDA: state='%s'" + args: + - id(lambda_sensor).state.c_str() + + - platform: template + name: "Test Lambda Pass Button" + id: test_lambda_pass_button + on_press: + - text_sensor.template.publish: + id: lambda_skip_sensor + state: "value" + - delay: 50ms + - logger.log: + format: "LAMBDA_PASS: state='%s'" + args: + - id(lambda_skip_sensor).state.c_str() + + - platform: template + name: "Test Lambda Skip Button" + id: test_lambda_skip_button + on_press: + - text_sensor.template.publish: + id: lambda_skip_sensor + state: "skip" + - delay: 50ms + # When lambda returns {}, the value should NOT be published + # so state should remain from previous publish (or empty if first) + - logger.log: + format: "LAMBDA_SKIP: state='%s'" + args: + - id(lambda_skip_sensor).state.c_str() + + - platform: template + name: "Test Lambda Raw State Button" + id: test_lambda_raw_state_button + on_press: + - text_sensor.template.publish: + id: lambda_raw_state_sensor + state: "original" + - delay: 50ms + # Verify raw_state is preserved (not mutated) after lambda filter + # state should be "original MODIFIED", raw_state should be "original" + - logger.log: + format: "LAMBDA_RAW_STATE: state='%s' raw_state='%s'" + args: + - id(lambda_raw_state_sensor).state.c_str() + - id(lambda_raw_state_sensor).get_raw_state().c_str() diff --git a/tests/integration/test_text_sensor_raw_state.py b/tests/integration/test_text_sensor_raw_state.py index 482ebbe9c2..476dd2713e 100644 --- a/tests/integration/test_text_sensor_raw_state.py +++ b/tests/integration/test_text_sensor_raw_state.py @@ -42,6 +42,11 @@ async def test_text_sensor_raw_state( map_off_future: asyncio.Future[str] = loop.create_future() map_unknown_future: asyncio.Future[str] = loop.create_future() chained_future: asyncio.Future[str] = loop.create_future() + to_lower_future: asyncio.Future[str] = loop.create_future() + lambda_future: asyncio.Future[str] = loop.create_future() + lambda_pass_future: asyncio.Future[str] = loop.create_future() + lambda_skip_future: asyncio.Future[str] = loop.create_future() + lambda_raw_state_future: asyncio.Future[tuple[str, str]] = loop.create_future() # Patterns to match log output # NO_FILTER: state='hello world' raw_state='hello world' @@ -58,6 +63,13 @@ async def test_text_sensor_raw_state( map_off_pattern = re.compile(r"MAP_OFF: state='([^']*)'") map_unknown_pattern = re.compile(r"MAP_UNKNOWN: state='([^']*)'") chained_pattern = re.compile(r"CHAINED: state='([^']*)'") + to_lower_pattern = re.compile(r"TO_LOWER: state='([^']*)'") + lambda_pattern = re.compile(r"LAMBDA: state='([^']*)'") + lambda_pass_pattern = re.compile(r"LAMBDA_PASS: state='([^']*)'") + lambda_skip_pattern = re.compile(r"LAMBDA_SKIP: state='([^']*)'") + lambda_raw_state_pattern = re.compile( + r"LAMBDA_RAW_STATE: state='([^']*)' raw_state='([^']*)'" + ) def check_output(line: str) -> None: """Check log output for expected messages.""" @@ -92,6 +104,27 @@ async def test_text_sensor_raw_state( if not chained_future.done() and (match := chained_pattern.search(line)): chained_future.set_result(match.group(1)) + if not to_lower_future.done() and (match := to_lower_pattern.search(line)): + to_lower_future.set_result(match.group(1)) + + if not lambda_future.done() and (match := lambda_pattern.search(line)): + lambda_future.set_result(match.group(1)) + + if not lambda_pass_future.done() and ( + match := lambda_pass_pattern.search(line) + ): + lambda_pass_future.set_result(match.group(1)) + + if not lambda_skip_future.done() and ( + match := lambda_skip_pattern.search(line) + ): + lambda_skip_future.set_result(match.group(1)) + + if not lambda_raw_state_future.done() and ( + match := lambda_raw_state_pattern.search(line) + ): + lambda_raw_state_future.set_result((match.group(1), match.group(2))) + async with ( run_compiled(yaml_config, line_callback=check_output), api_client_connected() as client, @@ -272,3 +305,111 @@ async def test_text_sensor_raw_state( pytest.fail("Timeout waiting for CHAINED log message") assert state == "[value]", f"Chained failed: expected '[value]', got '{state}'" + + # Test 10: to_lower filter + # "HELLO WORLD" -> "hello world" + to_lower_button = next( + (e for e in entities if "test_to_lower_button" in e.object_id.lower()), + None, + ) + assert to_lower_button is not None, "Test To Lower Button not found" + client.button_command(to_lower_button.key) + + try: + state = await asyncio.wait_for(to_lower_future, timeout=5.0) + except TimeoutError: + pytest.fail("Timeout waiting for TO_LOWER log message") + + assert state == "hello world", ( + f"to_lower failed: expected 'hello world', got '{state}'" + ) + + # Test 11: Lambda filter + # "test" -> "[test]" + lambda_button = next( + (e for e in entities if "test_lambda_button" in e.object_id.lower()), + None, + ) + assert lambda_button is not None, "Test Lambda Button not found" + client.button_command(lambda_button.key) + + try: + state = await asyncio.wait_for(lambda_future, timeout=5.0) + except TimeoutError: + pytest.fail("Timeout waiting for LAMBDA log message") + + assert state == "[test]", f"Lambda failed: expected '[test]', got '{state}'" + + # Test 12: Lambda filter - value passes through + # "value" -> "value passed" + lambda_pass_button = next( + (e for e in entities if "test_lambda_pass_button" in e.object_id.lower()), + None, + ) + assert lambda_pass_button is not None, "Test Lambda Pass Button not found" + client.button_command(lambda_pass_button.key) + + try: + state = await asyncio.wait_for(lambda_pass_future, timeout=5.0) + except TimeoutError: + pytest.fail("Timeout waiting for LAMBDA_PASS log message") + + assert state == "value passed", ( + f"Lambda pass failed: expected 'value passed', got '{state}'" + ) + + # Test 13: Lambda filter - skip publishing (return {}) + # "skip" -> no publish, state remains "value passed" from previous test + lambda_skip_button = next( + (e for e in entities if "test_lambda_skip_button" in e.object_id.lower()), + None, + ) + assert lambda_skip_button is not None, "Test Lambda Skip Button not found" + client.button_command(lambda_skip_button.key) + + try: + state = await asyncio.wait_for(lambda_skip_future, timeout=5.0) + except TimeoutError: + pytest.fail("Timeout waiting for LAMBDA_SKIP log message") + + # When lambda returns {}, value should NOT be published + # State remains from previous successful publish ("value passed") + assert state == "value passed", ( + f"Lambda skip failed: expected 'value passed' (unchanged), got '{state}'" + ) + + # Test 14: Lambda filter - verify raw_state is preserved (not mutated) + # This is critical to verify the in-place mutation optimization is safe + # "original" -> state="original MODIFIED", raw_state="original" + lambda_raw_state_button = next( + ( + e + for e in entities + if "test_lambda_raw_state_button" in e.object_id.lower() + ), + None, + ) + assert lambda_raw_state_button is not None, ( + "Test Lambda Raw State Button not found" + ) + client.button_command(lambda_raw_state_button.key) + + try: + state, raw_state = await asyncio.wait_for( + lambda_raw_state_future, timeout=5.0 + ) + except TimeoutError: + pytest.fail("Timeout waiting for LAMBDA_RAW_STATE log message") + + assert state == "original MODIFIED", ( + f"Lambda raw_state test failed: expected state='original MODIFIED', " + f"got '{state}'" + ) + assert raw_state == "original", ( + f"Lambda raw_state test failed: raw_state was mutated! " + f"Expected 'original', got '{raw_state}'" + ) + assert state != raw_state, ( + f"Lambda filter should modify state but preserve raw_state. " + f"state='{state}', raw_state='{raw_state}'" + ) From 8ae901b3f1ef47ef5bb18ec3ab19c204fb1bc07c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:19:30 -1000 Subject: [PATCH 0367/2030] [http_request] Use stack allocation for MD5 buffer in OTA (#13550) --- esphome/components/http_request/ota/ota_http_request.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 6c77e75d8c..8a4b3684cf 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -82,7 +82,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { uint32_t last_progress = 0; uint32_t update_start_time = millis(); md5::MD5Digest md5_receive; - std::unique_ptr md5_receive_str(new char[33]); + char md5_receive_str[33]; if (this->md5_expected_.empty() && !this->http_get_md5_()) { return OTA_MD5_INVALID; @@ -176,14 +176,14 @@ uint8_t OtaHttpRequestComponent::do_ota_() { // 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(); + md5_receive.get_hex(md5_receive_str); + this->md5_computed_ = md5_receive_str; 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), container); return ota::OTA_RESPONSE_ERROR_MD5_MISMATCH; } else { - backend->set_update_md5(md5_receive_str.get()); + backend->set_update_md5(md5_receive_str); } container->end(); From 4ddd40bcfb976b0e0c94addc9a6526d143f3e264 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:19:50 -1000 Subject: [PATCH 0368/2030] [core] Add PROGMEM string comparison helpers and use in cover/valve/helpers (#13545) --- esphome/components/cover/cover.cpp | 12 ++++++------ esphome/components/valve/valve.cpp | 10 ++++++---- esphome/core/helpers.cpp | 7 ++++--- esphome/core/progmem.h | 8 ++++++++ 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index 97b8c2213e..68688794d7 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -1,11 +1,11 @@ #include "cover.h" #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" +#include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include -#include "esphome/core/log.h" - namespace esphome::cover { static const char *const TAG = "cover"; @@ -39,13 +39,13 @@ Cover::Cover() : position{COVER_OPEN} {} CoverCall::CoverCall(Cover *parent) : parent_(parent) {} CoverCall &CoverCall::set_command(const char *command) { - if (strcasecmp(command, "OPEN") == 0) { + if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("OPEN")) == 0) { this->set_command_open(); - } else if (strcasecmp(command, "CLOSE") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("CLOSE")) == 0) { this->set_command_close(); - } else if (strcasecmp(command, "STOP") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("STOP")) == 0) { this->set_command_stop(); - } else if (strcasecmp(command, "TOGGLE") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) { this->set_command_toggle(); } else { ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index a9086747ce..3a7c3cbf88 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -2,6 +2,8 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" + #include namespace esphome { @@ -38,13 +40,13 @@ Valve::Valve() : position{VALVE_OPEN} {} ValveCall::ValveCall(Valve *parent) : parent_(parent) {} ValveCall &ValveCall::set_command(const char *command) { - if (strcasecmp(command, "OPEN") == 0) { + if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("OPEN")) == 0) { this->set_command_open(); - } else if (strcasecmp(command, "CLOSE") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("CLOSE")) == 0) { this->set_command_close(); - } else if (strcasecmp(command, "STOP") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("STOP")) == 0) { this->set_command_stop(); - } else if (strcasecmp(command, "TOGGLE") == 0) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) { this->set_command_toggle(); } else { ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command); diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index e7b901d71f..1a5d22f8d8 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -3,6 +3,7 @@ #include "esphome/core/defines.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "esphome/core/string_ref.h" #include @@ -451,15 +452,15 @@ std::string format_bin(const uint8_t *data, size_t length) { } ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) { - if (on == nullptr && strcasecmp(str, "on") == 0) + if (on == nullptr && ESPHOME_strcasecmp_P(str, ESPHOME_PSTR("on")) == 0) return PARSE_ON; if (on != nullptr && strcasecmp(str, on) == 0) return PARSE_ON; - if (off == nullptr && strcasecmp(str, "off") == 0) + if (off == nullptr && ESPHOME_strcasecmp_P(str, ESPHOME_PSTR("off")) == 0) return PARSE_OFF; if (off != nullptr && strcasecmp(str, off) == 0) return PARSE_OFF; - if (strcasecmp(str, "toggle") == 0) + if (ESPHOME_strcasecmp_P(str, ESPHOME_PSTR("toggle")) == 0) return PARSE_TOGGLE; return PARSE_NONE; diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index 6c3e4cec96..4b897fb2de 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -12,6 +12,10 @@ #define ESPHOME_strncpy_P strncpy_P #define ESPHOME_strncat_P strncat_P #define ESPHOME_snprintf_P snprintf_P +#define ESPHOME_strcmp_P strcmp_P +#define ESPHOME_strcasecmp_P strcasecmp_P +#define ESPHOME_strncmp_P strncmp_P +#define ESPHOME_strncasecmp_P strncasecmp_P // Type for pointers to PROGMEM strings (for use with ESPHOME_F return values) using ProgmemStr = const __FlashStringHelper *; #else @@ -21,6 +25,10 @@ using ProgmemStr = const __FlashStringHelper *; #define ESPHOME_strncpy_P strncpy #define ESPHOME_strncat_P strncat #define ESPHOME_snprintf_P snprintf +#define ESPHOME_strcmp_P strcmp +#define ESPHOME_strcasecmp_P strcasecmp +#define ESPHOME_strncmp_P strncmp +#define ESPHOME_strncasecmp_P strncasecmp // Type for pointers to strings (no PROGMEM on non-ESP8266 platforms) using ProgmemStr = const char *; #endif From 7ef933abec861c4e9b02f3a65ae6b5568d5f79c7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:20:08 -1000 Subject: [PATCH 0369/2030] [libretiny] Bump to 1.11.0 (#13512) --- .clang-tidy.hash | 2 +- esphome/components/libretiny/__init__.py | 13 ++++++++++--- platformio.ini | 2 +- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 0a272d21ba..009f9db388 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -15dc295268b2dcf75942f42759b3ddec64eba89f75525698eb39c95a7f4b14ce +d565b0589e35e692b5f2fc0c14723a99595b4828a3a3ef96c442e86a23176c00 diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 503ec7e167..553179beec 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -191,10 +191,17 @@ def _notify_old_style(config): # The dev and latest branches will be at *least* this version, which is what matters. +# Use GitHub releases directly to avoid PlatformIO moderation delays. ARDUINO_VERSIONS = { - "dev": (cv.Version(1, 9, 2), "https://github.com/libretiny-eu/libretiny.git"), - "latest": (cv.Version(1, 9, 2), "libretiny"), - "recommended": (cv.Version(1, 9, 2), None), + "dev": (cv.Version(1, 11, 0), "https://github.com/libretiny-eu/libretiny.git"), + "latest": ( + cv.Version(1, 11, 0), + "https://github.com/libretiny-eu/libretiny.git#v1.11.0", + ), + "recommended": ( + cv.Version(1, 11, 0), + "https://github.com/libretiny-eu/libretiny.git#v1.11.0", + ), } diff --git a/platformio.ini b/platformio.ini index e9a588e4fd..9de72cd622 100644 --- a/platformio.ini +++ b/platformio.ini @@ -212,7 +212,7 @@ build_unflags = ; This are common settings for the LibreTiny (all variants) using Arduino. [common:libretiny-arduino] extends = common:arduino -platform = libretiny@1.9.2 +platform = https://github.com/libretiny-eu/libretiny.git#v1.11.0 framework = arduino lib_compat_mode = soft lib_deps = From 2f1a345905064015e7e0376665a980c1d0b7f1b0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:20:21 -1000 Subject: [PATCH 0370/2030] [mhz19] Refactor detection range logging to use LogString (#13541) --- esphome/components/mhz19/mhz19.cpp | 62 +++++++++++++----------------- esphome/components/mhz19/mhz19.h | 8 ++-- 2 files changed, 30 insertions(+), 40 deletions(-) diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 259d597b44..b6b4031e16 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -3,8 +3,7 @@ #include -namespace esphome { -namespace mhz19 { +namespace esphome::mhz19 { static const char *const TAG = "mhz19"; static const uint8_t MHZ19_REQUEST_LENGTH = 8; @@ -17,6 +16,19 @@ static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM[] = {0xFF, 0x01, 0x static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88}; static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x27, 0x10}; +static const LogString *detection_range_to_log_string(MHZ19DetectionRange range) { + switch (range) { + case MHZ19_DETECTION_RANGE_0_2000PPM: + return LOG_STR("0-2000 ppm"); + case MHZ19_DETECTION_RANGE_0_5000PPM: + return LOG_STR("0-5000 ppm"); + case MHZ19_DETECTION_RANGE_0_10000PPM: + return LOG_STR("0-10000 ppm"); + default: + return LOG_STR("default"); + } +} + uint8_t mhz19_checksum(const uint8_t *command) { uint8_t sum = 0; for (uint8_t i = 1; i < MHZ19_REQUEST_LENGTH; i++) { @@ -91,24 +103,24 @@ void MHZ19Component::abc_disable() { this->mhz19_write_command_(MHZ19_COMMAND_ABC_DISABLE, nullptr); } -void MHZ19Component::range_set(MHZ19DetectionRange detection_ppm) { - switch (detection_ppm) { - case MHZ19_DETECTION_RANGE_DEFAULT: - ESP_LOGV(TAG, "Using previously set detection range (no change)"); - break; +void MHZ19Component::range_set(MHZ19DetectionRange detection_range) { + const uint8_t *command; + switch (detection_range) { case MHZ19_DETECTION_RANGE_0_2000PPM: - ESP_LOGD(TAG, "Setting detection range to 0 to 2000ppm"); - this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM, nullptr); + command = MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM; break; case MHZ19_DETECTION_RANGE_0_5000PPM: - ESP_LOGD(TAG, "Setting detection range to 0 to 5000ppm"); - this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM, nullptr); + command = MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM; break; case MHZ19_DETECTION_RANGE_0_10000PPM: - ESP_LOGD(TAG, "Setting detection range to 0 to 10000ppm"); - this->mhz19_write_command_(MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM, nullptr); + command = MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM; break; + default: + ESP_LOGV(TAG, "Using previously set detection range (no change)"); + return; } + ESP_LOGD(TAG, "Setting detection range to %s", LOG_STR_ARG(detection_range_to_log_string(detection_range))); + this->mhz19_write_command_(command, nullptr); } bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *response) { @@ -140,27 +152,7 @@ void MHZ19Component::dump_config() { } ESP_LOGCONFIG(TAG, " Warmup time: %" PRIu32 " s", this->warmup_seconds_); - - const char *range_str; - switch (this->detection_range_) { - case MHZ19_DETECTION_RANGE_DEFAULT: - range_str = "default"; - break; - case MHZ19_DETECTION_RANGE_0_2000PPM: - range_str = "0 to 2000ppm"; - break; - case MHZ19_DETECTION_RANGE_0_5000PPM: - range_str = "0 to 5000ppm"; - break; - case MHZ19_DETECTION_RANGE_0_10000PPM: - range_str = "0 to 10000ppm"; - break; - default: - range_str = "default"; - break; - } - ESP_LOGCONFIG(TAG, " Detection range: %s", range_str); + ESP_LOGCONFIG(TAG, " Detection range: %s", LOG_STR_ARG(detection_range_to_log_string(this->detection_range_))); } -} // namespace mhz19 -} // namespace esphome +} // namespace esphome::mhz19 diff --git a/esphome/components/mhz19/mhz19.h b/esphome/components/mhz19/mhz19.h index 5898bab649..a27f1c31eb 100644 --- a/esphome/components/mhz19/mhz19.h +++ b/esphome/components/mhz19/mhz19.h @@ -5,8 +5,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/uart/uart.h" -namespace esphome { -namespace mhz19 { +namespace esphome::mhz19 { enum MHZ19ABCLogic { MHZ19_ABC_NONE = 0, @@ -32,7 +31,7 @@ class MHZ19Component : public PollingComponent, public uart::UARTDevice { void calibrate_zero(); void abc_enable(); void abc_disable(); - void range_set(MHZ19DetectionRange detection_ppm); + void range_set(MHZ19DetectionRange detection_range); void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_co2_sensor(sensor::Sensor *co2_sensor) { co2_sensor_ = co2_sensor; } @@ -74,5 +73,4 @@ template class MHZ19DetectionRangeSetAction : public Actionparent_->range_set(this->detection_range_.value(x...)); } }; -} // namespace mhz19 -} // namespace esphome +} // namespace esphome::mhz19 From 003b9c6c3fd56e9c95ce86a4c1af218ff58e0805 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:20:33 -1000 Subject: [PATCH 0371/2030] [uln2003] Refactor step mode logging to use LogString (#13543) --- esphome/components/uln2003/uln2003.cpp | 36 ++++++++++++-------------- esphome/components/uln2003/uln2003.h | 6 ++--- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/esphome/components/uln2003/uln2003.cpp b/esphome/components/uln2003/uln2003.cpp index 11e1c3d4c0..a2244eadaa 100644 --- a/esphome/components/uln2003/uln2003.cpp +++ b/esphome/components/uln2003/uln2003.cpp @@ -1,11 +1,23 @@ #include "uln2003.h" #include "esphome/core/log.h" -namespace esphome { -namespace uln2003 { +namespace esphome::uln2003 { static const char *const TAG = "uln2003.stepper"; +static const LogString *step_mode_to_log_string(ULN2003StepMode mode) { + switch (mode) { + case ULN2003_STEP_MODE_FULL_STEP: + return LOG_STR("FULL STEP"); + case ULN2003_STEP_MODE_HALF_STEP: + return LOG_STR("HALF STEP"); + case ULN2003_STEP_MODE_WAVE_DRIVE: + return LOG_STR("WAVE DRIVE"); + default: + return LOG_STR("UNKNOWN"); + } +} + void ULN2003::setup() { this->pin_a_->setup(); this->pin_b_->setup(); @@ -42,22 +54,7 @@ void ULN2003::dump_config() { LOG_PIN(" Pin B: ", this->pin_b_); LOG_PIN(" Pin C: ", this->pin_c_); LOG_PIN(" Pin D: ", this->pin_d_); - const char *step_mode_s; - switch (this->step_mode_) { - case ULN2003_STEP_MODE_FULL_STEP: - step_mode_s = "FULL STEP"; - break; - case ULN2003_STEP_MODE_HALF_STEP: - step_mode_s = "HALF STEP"; - break; - case ULN2003_STEP_MODE_WAVE_DRIVE: - step_mode_s = "WAVE DRIVE"; - break; - default: - step_mode_s = "UNKNOWN"; - break; - } - ESP_LOGCONFIG(TAG, " Step Mode: %s", step_mode_s); + ESP_LOGCONFIG(TAG, " Step Mode: %s", LOG_STR_ARG(step_mode_to_log_string(this->step_mode_))); } void ULN2003::write_step_(int32_t step) { int32_t n = this->step_mode_ == ULN2003_STEP_MODE_HALF_STEP ? 8 : 4; @@ -90,5 +87,4 @@ void ULN2003::write_step_(int32_t step) { this->pin_d_->digital_write((res >> 3) & 1); } -} // namespace uln2003 -} // namespace esphome +} // namespace esphome::uln2003 diff --git a/esphome/components/uln2003/uln2003.h b/esphome/components/uln2003/uln2003.h index 4f559ed9a0..70f55f72bf 100644 --- a/esphome/components/uln2003/uln2003.h +++ b/esphome/components/uln2003/uln2003.h @@ -4,8 +4,7 @@ #include "esphome/core/hal.h" #include "esphome/components/stepper/stepper.h" -namespace esphome { -namespace uln2003 { +namespace esphome::uln2003 { enum ULN2003StepMode { ULN2003_STEP_MODE_FULL_STEP, @@ -40,5 +39,4 @@ class ULN2003 : public stepper::Stepper, public Component { int32_t current_uln_pos_{0}; }; -} // namespace uln2003 -} // namespace esphome +} // namespace esphome::uln2003 From 67dea1e5389785f62b3f67ceb812af954217b283 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:20:49 -1000 Subject: [PATCH 0372/2030] [light] Use member array instead of heap allocation in AddressableLightWrapper (#13503) --- esphome/components/light/addressable_light_wrapper.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/light/addressable_light_wrapper.h b/esphome/components/light/addressable_light_wrapper.h index 8665e62a79..cd83482248 100644 --- a/esphome/components/light/addressable_light_wrapper.h +++ b/esphome/components/light/addressable_light_wrapper.h @@ -7,9 +7,7 @@ namespace esphome::light { class AddressableLightWrapper : public light::AddressableLight { public: - explicit AddressableLightWrapper(light::LightState *light_state) : light_state_(light_state) { - this->wrapper_state_ = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory) - } + explicit AddressableLightWrapper(light::LightState *light_state) : light_state_(light_state) {} int32_t size() const override { return 1; } @@ -118,7 +116,7 @@ class AddressableLightWrapper : public light::AddressableLight { } light::LightState *light_state_; - uint8_t *wrapper_state_; + mutable uint8_t wrapper_state_[5]{}; ColorMode color_mode_{ColorMode::UNKNOWN}; }; From ee9e3315b6f73ddd06ea326577fbe68b99e14e9f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:21:05 -1000 Subject: [PATCH 0373/2030] [tm1638] Use member array instead of heap allocation for display buffer (#13504) --- esphome/components/tm1638/tm1638.cpp | 3 --- esphome/components/tm1638/tm1638.h | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/esphome/components/tm1638/tm1638.cpp b/esphome/components/tm1638/tm1638.cpp index 7ba63fe218..8ef546ff32 100644 --- a/esphome/components/tm1638/tm1638.cpp +++ b/esphome/components/tm1638/tm1638.cpp @@ -35,9 +35,6 @@ void TM1638Component::setup() { this->set_intensity(intensity_); this->reset_(); // all LEDs off - - for (uint8_t i = 0; i < 8; i++) // zero fill print buffer - this->buffer_[i] = 0; } void TM1638Component::dump_config() { diff --git a/esphome/components/tm1638/tm1638.h b/esphome/components/tm1638/tm1638.h index f6b2922ecf..27898aa3dc 100644 --- a/esphome/components/tm1638/tm1638.h +++ b/esphome/components/tm1638/tm1638.h @@ -70,7 +70,7 @@ class TM1638Component : public PollingComponent { GPIOPin *clk_pin_; GPIOPin *stb_pin_; GPIOPin *dio_pin_; - uint8_t *buffer_ = new uint8_t[8]; + uint8_t buffer_[8]{}; tm1638_writer_t writer_{}; std::vector listeners_{}; }; From 9c3817f544e7818038d81d1cc65afc7b79fcc700 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:21:17 -1000 Subject: [PATCH 0374/2030] [sml] Use constexpr std::array for START_SEQ constant (#13506) --- esphome/components/sml/constants.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/sml/constants.h b/esphome/components/sml/constants.h index d6761d4bb7..0142fe98f7 100644 --- a/esphome/components/sml/constants.h +++ b/esphome/components/sml/constants.h @@ -1,5 +1,6 @@ #pragma once +#include #include namespace esphome { @@ -21,7 +22,7 @@ enum SmlMessageType : uint16_t { SML_PUBLIC_OPEN_RES = 0x0101, SML_GET_LIST_RES const uint16_t START_MASK = 0x55aa; // 0x1b 1b 1b 1b 01 01 01 01 const uint16_t END_MASK = 0x0157; // 0x1b 1b 1b 1b 1a -const std::vector START_SEQ = {0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01}; +constexpr std::array START_SEQ = {0x1b, 0x1b, 0x1b, 0x1b, 0x01, 0x01, 0x01, 0x01}; } // namespace sml } // namespace esphome From bf92d948636a8655c934a11a0f616343e7ccd714 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:25:02 -1000 Subject: [PATCH 0375/2030] [mqtt] Use stack buffers for publish_state() topic building (#13434) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../mqtt/mqtt_alarm_control_panel.cpp | 3 +- .../components/mqtt/mqtt_binary_sensor.cpp | 3 +- esphome/components/mqtt/mqtt_component.cpp | 18 ++++++-- esphome/components/mqtt/mqtt_component.h | 46 +++++++++++++++++++ esphome/components/mqtt/mqtt_cover.cpp | 3 +- esphome/components/mqtt/mqtt_date.cpp | 3 +- esphome/components/mqtt/mqtt_datetime.cpp | 20 ++++---- esphome/components/mqtt/mqtt_event.cpp | 3 +- esphome/components/mqtt/mqtt_fan.cpp | 3 +- esphome/components/mqtt/mqtt_light.cpp | 3 +- esphome/components/mqtt/mqtt_lock.cpp | 5 +- esphome/components/mqtt/mqtt_number.cpp | 5 +- esphome/components/mqtt/mqtt_select.cpp | 3 +- esphome/components/mqtt/mqtt_sensor.cpp | 5 +- esphome/components/mqtt/mqtt_switch.cpp | 3 +- esphome/components/mqtt/mqtt_text.cpp | 3 +- esphome/components/mqtt/mqtt_text_sensor.cpp | 5 +- esphome/components/mqtt/mqtt_time.cpp | 3 +- esphome/components/mqtt/mqtt_update.cpp | 3 +- esphome/components/mqtt/mqtt_valve.cpp | 3 +- 20 files changed, 111 insertions(+), 32 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index 715e6feed8..fbdc6dce23 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -119,7 +119,8 @@ bool MQTTAlarmControlPanelComponent::publish_state() { default: state_s = "unknown"; } - return this->publish(this->get_state_topic_(), state_s); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish(this->get_state_topic_to_(topic_buf), state_s); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_binary_sensor.cpp b/esphome/components/mqtt/mqtt_binary_sensor.cpp index 7cbb5dcc0e..75995f61e0 100644 --- a/esphome/components/mqtt/mqtt_binary_sensor.cpp +++ b/esphome/components/mqtt/mqtt_binary_sensor.cpp @@ -52,8 +52,9 @@ bool MQTTBinarySensorComponent::publish_state(bool state) { if (this->binary_sensor_->is_status_binary_sensor()) return true; + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; const char *state_s = state ? "ON" : "OFF"; - return this->publish(this->get_state_topic_(), state_s); + return this->publish(this->get_state_topic_to_(topic_buf), state_s); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 7607a4e817..aec6140e3f 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -132,17 +132,29 @@ std::string MQTTComponent::get_command_topic_() const { } bool MQTTComponent::publish(const std::string &topic, const std::string &payload) { - return this->publish(topic, payload.data(), payload.size()); + return this->publish(topic.c_str(), payload.data(), payload.size()); } bool MQTTComponent::publish(const std::string &topic, const char *payload, size_t payload_length) { - if (topic.empty()) + return this->publish(topic.c_str(), payload, payload_length); +} + +bool MQTTComponent::publish(const char *topic, const char *payload, size_t payload_length) { + if (topic[0] == '\0') return false; return global_mqtt_client->publish(topic, payload, payload_length, this->qos_, this->retain_); } +bool MQTTComponent::publish(const char *topic, const char *payload) { + return this->publish(topic, payload, strlen(payload)); +} + bool MQTTComponent::publish_json(const std::string &topic, const json::json_build_t &f) { - if (topic.empty()) + return this->publish_json(topic.c_str(), f); +} + +bool MQTTComponent::publish_json(const char *topic, const json::json_build_t &f) { + if (topic[0] == '\0') return false; return global_mqtt_client->publish_json(topic, f, this->qos_, this->retain_); } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 1a5e6db3af..304a2c0d0e 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -157,6 +157,38 @@ class MQTTComponent : public Component { */ bool publish(const std::string &topic, const char *payload, size_t payload_length); + /** Send a MQTT message (no heap allocation for topic). + * + * @param topic The topic as C string. + * @param payload The payload buffer. + * @param payload_length The length of the payload. + */ + bool publish(const char *topic, const char *payload, size_t payload_length); + + /** Send a MQTT message (no heap allocation for topic). + * + * @param topic The topic as StringRef (for use with get_state_topic_to_()). + * @param payload The payload buffer. + * @param payload_length The length of the payload. + */ + bool publish(StringRef topic, const char *payload, size_t payload_length) { + return this->publish(topic.c_str(), payload, payload_length); + } + + /** Send a MQTT message (no heap allocation for topic). + * + * @param topic The topic as C string. + * @param payload The null-terminated payload. + */ + bool publish(const char *topic, const char *payload); + + /** Send a MQTT message (no heap allocation for topic). + * + * @param topic The topic as StringRef (for use with get_state_topic_to_()). + * @param payload The null-terminated payload. + */ + bool publish(StringRef topic, const char *payload) { return this->publish(topic.c_str(), payload); } + /** Construct and send a JSON MQTT message. * * @param topic The topic. @@ -164,6 +196,20 @@ class MQTTComponent : public Component { */ bool publish_json(const std::string &topic, const json::json_build_t &f); + /** Construct and send a JSON MQTT message (no heap allocation for topic). + * + * @param topic The topic as C string. + * @param f The Json Message builder. + */ + bool publish_json(const char *topic, const json::json_build_t &f); + + /** Construct and send a JSON MQTT message (no heap allocation for topic). + * + * @param topic The topic as StringRef (for use with get_state_topic_to_()). + * @param f The Json Message builder. + */ + bool publish_json(StringRef topic, const json::json_build_t &f) { return this->publish_json(topic.c_str(), f); } + /** Subscribe to a MQTT topic. * * @param topic The topic. Wildcards are currently not supported. diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index 493514c8fb..d5bd13869a 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -115,7 +115,8 @@ bool MQTTCoverComponent::publish_state() { : this->cover_->position == COVER_OPEN ? "open" : traits.get_supports_position() ? "open" : "unknown"; - if (!this->publish(this->get_state_topic_(), state_s)) + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + if (!this->publish(this->get_state_topic_to_(topic_buf), state_s)) success = false; return success; } diff --git a/esphome/components/mqtt/mqtt_date.cpp b/esphome/components/mqtt/mqtt_date.cpp index cbe4045486..c422bb3058 100644 --- a/esphome/components/mqtt/mqtt_date.cpp +++ b/esphome/components/mqtt/mqtt_date.cpp @@ -53,7 +53,8 @@ bool MQTTDateComponent::send_initial_state() { } } bool MQTTDateComponent::publish_state(uint16_t year, uint8_t month, uint8_t day) { - return this->publish_json(this->get_state_topic_(), [year, month, day](JsonObject root) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), [year, month, day](JsonObject root) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson root[ESPHOME_F("year")] = year; root[ESPHOME_F("month")] = month; diff --git a/esphome/components/mqtt/mqtt_datetime.cpp b/esphome/components/mqtt/mqtt_datetime.cpp index f7b4ef0685..1492abd011 100644 --- a/esphome/components/mqtt/mqtt_datetime.cpp +++ b/esphome/components/mqtt/mqtt_datetime.cpp @@ -66,15 +66,17 @@ bool MQTTDateTimeComponent::send_initial_state() { } bool MQTTDateTimeComponent::publish_state(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { - return this->publish_json(this->get_state_topic_(), [year, month, day, hour, minute, second](JsonObject root) { - // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - root[ESPHOME_F("year")] = year; - root[ESPHOME_F("month")] = month; - root[ESPHOME_F("day")] = day; - root[ESPHOME_F("hour")] = hour; - root[ESPHOME_F("minute")] = minute; - root[ESPHOME_F("second")] = second; - }); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), + [year, month, day, hour, minute, second](JsonObject root) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + root[ESPHOME_F("year")] = year; + root[ESPHOME_F("month")] = month; + root[ESPHOME_F("day")] = day; + root[ESPHOME_F("hour")] = hour; + root[ESPHOME_F("minute")] = minute; + root[ESPHOME_F("second")] = second; + }); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_event.cpp b/esphome/components/mqtt/mqtt_event.cpp index 42fbc1eabd..37d5c2551a 100644 --- a/esphome/components/mqtt/mqtt_event.cpp +++ b/esphome/components/mqtt/mqtt_event.cpp @@ -44,7 +44,8 @@ void MQTTEventComponent::dump_config() { } bool MQTTEventComponent::publish_event_(const std::string &event_type) { - return this->publish_json(this->get_state_topic_(), [event_type](JsonObject root) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), [event_type](JsonObject root) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson root[MQTT_EVENT_TYPE] = event_type; }); diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index 0909090023..c9791fb0f1 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -158,9 +158,10 @@ void MQTTFanComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig } } bool MQTTFanComponent::publish_state() { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; const char *state_s = this->state_->state ? "ON" : "OFF"; ESP_LOGD(TAG, "'%s' Sending state %s.", this->state_->get_name().c_str(), state_s); - this->publish(this->get_state_topic_(), state_s); + this->publish(this->get_state_topic_to_(topic_buf), state_s); bool failed = false; if (this->state_->get_traits().supports_direction()) { bool success = this->publish(this->get_direction_state_topic(), diff --git a/esphome/components/mqtt/mqtt_light.cpp b/esphome/components/mqtt/mqtt_light.cpp index e43cb63f4f..3e3537fa5c 100644 --- a/esphome/components/mqtt/mqtt_light.cpp +++ b/esphome/components/mqtt/mqtt_light.cpp @@ -34,7 +34,8 @@ void MQTTJSONLightComponent::on_light_remote_values_update() { MQTTJSONLightComponent::MQTTJSONLightComponent(LightState *state) : state_(state) {} bool MQTTJSONLightComponent::publish_state_() { - return this->publish_json(this->get_state_topic_(), [this](JsonObject root) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), [this](JsonObject root) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson LightJSONSchema::dump_json(*this->state_, root); }); diff --git a/esphome/components/mqtt/mqtt_lock.cpp b/esphome/components/mqtt/mqtt_lock.cpp index 43ef60bdf4..96c9397da8 100644 --- a/esphome/components/mqtt/mqtt_lock.cpp +++ b/esphome/components/mqtt/mqtt_lock.cpp @@ -47,13 +47,14 @@ void MQTTLockComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfi bool MQTTLockComponent::send_initial_state() { return this->publish_state(); } bool MQTTLockComponent::publish_state() { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; #ifdef USE_STORE_LOG_STR_IN_FLASH char buf[LOCK_STATE_STR_SIZE]; strncpy_P(buf, (PGM_P) lock_state_to_string(this->lock_->state), sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; - return this->publish(this->get_state_topic_(), buf); + return this->publish(this->get_state_topic_to_(topic_buf), buf); #else - return this->publish(this->get_state_topic_(), LOG_STR_ARG(lock_state_to_string(this->lock_->state))); + return this->publish(this->get_state_topic_to_(topic_buf), LOG_STR_ARG(lock_state_to_string(this->lock_->state))); #endif } diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index a014096c5f..7dc93eee0c 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -74,9 +74,10 @@ bool MQTTNumberComponent::send_initial_state() { } } bool MQTTNumberComponent::publish_state(float value) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; char buffer[64]; - buf_append_printf(buffer, sizeof(buffer), 0, "%f", value); - return this->publish(this->get_state_topic_(), buffer); + size_t len = buf_append_printf(buffer, sizeof(buffer), 0, "%f", value); + return this->publish(this->get_state_topic_to_(topic_buf), buffer, len); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_select.cpp b/esphome/components/mqtt/mqtt_select.cpp index 2d830998ec..25fd813496 100644 --- a/esphome/components/mqtt/mqtt_select.cpp +++ b/esphome/components/mqtt/mqtt_select.cpp @@ -50,7 +50,8 @@ bool MQTTSelectComponent::send_initial_state() { } } bool MQTTSelectComponent::publish_state(const std::string &value) { - return this->publish(this->get_state_topic_(), value); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish(this->get_state_topic_to_(topic_buf), value.data(), value.size()); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index f136b82355..e83eab6732 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -79,12 +79,13 @@ bool MQTTSensorComponent::send_initial_state() { } } bool MQTTSensorComponent::publish_state(float value) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; if (mqtt::global_mqtt_client->is_publish_nan_as_none() && std::isnan(value)) - return this->publish(this->get_state_topic_(), "None", 4); + return this->publish(this->get_state_topic_to_(topic_buf), "None", 4); int8_t accuracy = this->sensor_->get_accuracy_decimals(); char buf[VALUE_ACCURACY_MAX_LEN]; size_t len = value_accuracy_to_buf(buf, value, accuracy); - return this->publish(this->get_state_topic_(), buf, len); + return this->publish(this->get_state_topic_to_(topic_buf), buf, len); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_switch.cpp b/esphome/components/mqtt/mqtt_switch.cpp index a985ec66be..70cd03a4eb 100644 --- a/esphome/components/mqtt/mqtt_switch.cpp +++ b/esphome/components/mqtt/mqtt_switch.cpp @@ -52,8 +52,9 @@ void MQTTSwitchComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon bool MQTTSwitchComponent::send_initial_state() { return this->publish_state(this->switch_->state); } bool MQTTSwitchComponent::publish_state(bool state) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; const char *state_s = state ? "ON" : "OFF"; - return this->publish(this->get_state_topic_(), state_s); + return this->publish(this->get_state_topic_to_(topic_buf), state_s); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_text.cpp b/esphome/components/mqtt/mqtt_text.cpp index fed9224b42..16293c0603 100644 --- a/esphome/components/mqtt/mqtt_text.cpp +++ b/esphome/components/mqtt/mqtt_text.cpp @@ -53,7 +53,8 @@ bool MQTTTextComponent::send_initial_state() { } } bool MQTTTextComponent::publish_state(const std::string &value) { - return this->publish(this->get_state_topic_(), value); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish(this->get_state_topic_to_(topic_buf), value.data(), value.size()); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_text_sensor.cpp b/esphome/components/mqtt/mqtt_text_sensor.cpp index 5346923b41..a6b9f90b68 100644 --- a/esphome/components/mqtt/mqtt_text_sensor.cpp +++ b/esphome/components/mqtt/mqtt_text_sensor.cpp @@ -31,7 +31,10 @@ void MQTTTextSensor::dump_config() { LOG_MQTT_COMPONENT(true, false); } -bool MQTTTextSensor::publish_state(const std::string &value) { return this->publish(this->get_state_topic_(), value); } +bool MQTTTextSensor::publish_state(const std::string &value) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish(this->get_state_topic_to_(topic_buf), value.data(), value.size()); +} bool MQTTTextSensor::send_initial_state() { if (this->sensor_->has_state()) { return this->publish_state(this->sensor_->state); diff --git a/esphome/components/mqtt/mqtt_time.cpp b/esphome/components/mqtt/mqtt_time.cpp index 8749c3b59e..be391ce88c 100644 --- a/esphome/components/mqtt/mqtt_time.cpp +++ b/esphome/components/mqtt/mqtt_time.cpp @@ -53,7 +53,8 @@ bool MQTTTimeComponent::send_initial_state() { } } bool MQTTTimeComponent::publish_state(uint8_t hour, uint8_t minute, uint8_t second) { - return this->publish_json(this->get_state_topic_(), [hour, minute, second](JsonObject root) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), [hour, minute, second](JsonObject root) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson root[ESPHOME_F("hour")] = hour; root[ESPHOME_F("minute")] = minute; diff --git a/esphome/components/mqtt/mqtt_update.cpp b/esphome/components/mqtt/mqtt_update.cpp index 99e0c85509..c01fb9e52e 100644 --- a/esphome/components/mqtt/mqtt_update.cpp +++ b/esphome/components/mqtt/mqtt_update.cpp @@ -28,7 +28,8 @@ void MQTTUpdateComponent::setup() { } bool MQTTUpdateComponent::publish_state() { - return this->publish_json(this->get_state_topic_(), [this](JsonObject root) { + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + return this->publish_json(this->get_state_topic_to_(topic_buf), [this](JsonObject root) { root[ESPHOME_F("installed_version")] = this->update_->update_info.current_version; root[ESPHOME_F("latest_version")] = this->update_->update_info.latest_version; root[ESPHOME_F("title")] = this->update_->update_info.title; diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 8e66a69c6f..2e100823bf 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -84,7 +84,8 @@ bool MQTTValveComponent::publish_state() { : this->valve_->position == VALVE_OPEN ? "open" : traits.get_supports_position() ? "open" : "unknown"; - if (!this->publish(this->get_state_topic_(), state_s)) + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; + if (!this->publish(this->get_state_topic_to_(topic_buf), state_s)) success = false; return success; } From a7fbecb25c03c2584acfd85d56504db253106681 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:28:07 -1000 Subject: [PATCH 0376/2030] [ci] Soft-deprecate str_sprintf/str_snprintf to prevent hidden heap allocations (#13227) --- esphome/core/helpers.h | 2 ++ script/ci-custom.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 1aa29fa3f7..81397668e8 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -655,9 +655,11 @@ inline uint32_t fnv1_hash_object_id(const char *str, size_t len) { } /// snprintf-like function returning std::string of maximum length \p len (excluding null terminator). +/// @warning Allocates heap memory. Use snprintf() with a stack buffer instead. std::string __attribute__((format(printf, 1, 3))) str_snprintf(const char *fmt, size_t len, ...); /// sprintf-like function returning std::string. +/// @warning Allocates heap memory. Use snprintf() with a stack buffer instead. std::string __attribute__((format(printf, 1, 2))) str_sprintf(const char *fmt, ...); #ifdef USE_ESP8266 diff --git a/script/ci-custom.py b/script/ci-custom.py index 01e197057a..b146c9867e 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -692,6 +692,8 @@ HEAP_ALLOCATING_HELPERS = { "str_truncate": "removal (function is unused)", "str_upper_case": "removal (function is unused)", "str_snake_case": "removal (function is unused)", + "str_sprintf": "snprintf() with a stack buffer", + "str_snprintf": "snprintf() with a stack buffer", } @@ -710,7 +712,9 @@ HEAP_ALLOCATING_HELPERS = { r"str_sanitize(?!_)|" r"str_truncate|" r"str_upper_case|" - r"str_snake_case" + r"str_snake_case|" + r"str_sprintf|" + r"str_snprintf" r")\s*\(" + CPP_RE_EOL, include=cpp_include, exclude=[ From 5cbe9af48504f7bc84772eb5c1a32d2310c63dde Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:32:03 -1000 Subject: [PATCH 0377/2030] [rp2040] Use SmallBufferWithHeapFallback for preferences (#13501) --- esphome/components/rp2040/preferences.cpp | 29 +++++++++++++---------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/esphome/components/rp2040/preferences.cpp b/esphome/components/rp2040/preferences.cpp index cbf2b00641..e84033bc52 100644 --- a/esphome/components/rp2040/preferences.cpp +++ b/esphome/components/rp2040/preferences.cpp @@ -8,7 +8,6 @@ #include "preferences.h" #include -#include #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -25,6 +24,9 @@ static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-no static const uint32_t RP2040_FLASH_STORAGE_SIZE = 512; +// Stack buffer size for preferences - covers virtually all real-world preferences without heap allocation +static constexpr size_t PREF_BUFFER_SIZE = 64; + extern "C" uint8_t _EEPROM_start; template uint8_t calculate_crc(It first, It last, uint32_t type) { @@ -42,12 +44,14 @@ class RP2040PreferenceBackend : public ESPPreferenceBackend { uint32_t type = 0; bool save(const uint8_t *data, size_t len) override { - std::vector buffer; - buffer.resize(len + 1); - memcpy(buffer.data(), data, len); - buffer[buffer.size() - 1] = calculate_crc(buffer.begin(), buffer.end() - 1, type); + const size_t buffer_size = len + 1; + SmallBufferWithHeapFallback buffer_alloc(buffer_size); + uint8_t *buffer = buffer_alloc.get(); - for (uint32_t i = 0; i < len + 1; i++) { + memcpy(buffer, data, len); + buffer[len] = calculate_crc(buffer, buffer + len, type); + + for (size_t i = 0; i < buffer_size; i++) { uint32_t j = offset + i; if (j >= RP2040_FLASH_STORAGE_SIZE) return false; @@ -60,22 +64,23 @@ class RP2040PreferenceBackend : public ESPPreferenceBackend { return true; } bool load(uint8_t *data, size_t len) override { - std::vector buffer; - buffer.resize(len + 1); + const size_t buffer_size = len + 1; + SmallBufferWithHeapFallback buffer_alloc(buffer_size); + uint8_t *buffer = buffer_alloc.get(); - for (size_t i = 0; i < len + 1; i++) { + for (size_t i = 0; i < buffer_size; i++) { uint32_t j = offset + i; if (j >= RP2040_FLASH_STORAGE_SIZE) return false; buffer[i] = s_flash_storage[j]; } - uint8_t crc = calculate_crc(buffer.begin(), buffer.end() - 1, type); - if (buffer[buffer.size() - 1] != crc) { + uint8_t crc = calculate_crc(buffer, buffer + len, type); + if (buffer[len] != crc) { return false; } - memcpy(data, buffer.data(), len); + memcpy(data, buffer, len); return true; } }; From f91bffff9aa50f7ad6e8a56ce02fcefc7687c07b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:32:58 -1000 Subject: [PATCH 0378/2030] [wifi] Avoid heap allocation when building AP SSID (#13474) --- esphome/components/wifi/wifi_component.cpp | 26 +++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 52d9b2b442..ec9978da79 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -746,16 +746,32 @@ void WiFiComponent::setup_ap_config_() { return; if (this->ap_.get_ssid().empty()) { - std::string name = App.get_name(); - if (name.length() > 32) { + // Build AP SSID from app name without heap allocation + // WiFi SSID max is 32 bytes, with MAC suffix we keep first 25 + last 7 + static constexpr size_t AP_SSID_MAX_LEN = 32; + static constexpr size_t AP_SSID_PREFIX_LEN = 25; + static constexpr size_t AP_SSID_SUFFIX_LEN = 7; + + const std::string &app_name = App.get_name(); + const char *name_ptr = app_name.c_str(); + size_t name_len = app_name.length(); + + if (name_len <= AP_SSID_MAX_LEN) { + // Name fits, use directly + this->ap_.set_ssid(name_ptr); + } else { + // Name too long, need to truncate into stack buffer + char ssid_buf[AP_SSID_MAX_LEN + 1]; if (App.is_name_add_mac_suffix_enabled()) { // Keep first 25 chars and last 7 chars (MAC suffix), remove middle - name.erase(25, name.length() - 32); + memcpy(ssid_buf, name_ptr, AP_SSID_PREFIX_LEN); + memcpy(ssid_buf + AP_SSID_PREFIX_LEN, name_ptr + name_len - AP_SSID_SUFFIX_LEN, AP_SSID_SUFFIX_LEN); } else { - name.resize(32); + memcpy(ssid_buf, name_ptr, AP_SSID_MAX_LEN); } + ssid_buf[AP_SSID_MAX_LEN] = '\0'; + this->ap_.set_ssid(ssid_buf); } - this->ap_.set_ssid(name); } this->ap_setup_ = this->wifi_start_ap_(this->ap_); From cd6314dc96d9d13c66ac7935144c9cf089badf1d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:34:55 -1000 Subject: [PATCH 0379/2030] [socket] ESP8266: call delay(0) instead of esp_delay(0, cb) for zero timeout (#13530) --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 429f59ceca..a9c2eda4e8 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -29,6 +29,14 @@ void socket_delay(uint32_t ms) { // Use esp_delay with a callback that checks if socket data arrived. // This allows the delay to exit early when socket_wake() is called by // lwip recv_fn/accept_fn callbacks, reducing socket latency. + // + // When ms is 0, we must use delay(0) because esp_delay(0, callback) + // exits immediately without yielding, which can cause watchdog timeouts + // when the main loop runs in high-frequency mode (e.g., during light effects). + if (ms == 0) { + delay(0); + return; + } s_socket_woke = false; esp_delay(ms, []() { return !s_socket_woke; }); } From 75a78b2bf3eaa4c8790194beab88b75b59d543e4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:35:45 -1000 Subject: [PATCH 0380/2030] [core] Encapsulate entity preference creation to prepare for hash migration (#13505) --- .../bl0940/number/calibration_number.cpp | 2 +- esphome/components/climate/climate.cpp | 3 +- esphome/components/cover/cover.cpp | 2 +- .../components/duty_time/duty_time_sensor.cpp | 2 +- esphome/components/fan/fan.cpp | 3 +- esphome/components/haier/haier_base.cpp | 3 +- esphome/components/haier/hon_climate.cpp | 3 +- .../integration/integration_sensor.cpp | 2 +- esphome/components/ld2450/ld2450.cpp | 2 +- esphome/components/light/light_state.cpp | 4 +- esphome/components/lvgl/number/lvgl_number.h | 2 +- esphome/components/lvgl/select/lvgl_select.h | 2 +- esphome/components/number/automation.cpp | 3 +- .../opentherm/number/opentherm_number.cpp | 2 +- .../rotary_encoder/rotary_encoder.cpp | 2 +- esphome/components/sensor/automation.h | 2 +- .../media_player/speaker_media_player.cpp | 2 +- esphome/components/sprinkler/sprinkler.cpp | 2 +- esphome/components/switch/switch.cpp | 2 +- .../template_alarm_control_panel.cpp | 2 +- .../template/datetime/template_date.cpp | 3 +- .../template/datetime/template_datetime.cpp | 3 +- .../template/datetime/template_time.cpp | 3 +- .../template/number/template_number.cpp | 2 +- .../template/select/template_select.cpp | 2 +- .../template/text/template_text.cpp | 7 ++++ .../total_daily_energy/total_daily_energy.cpp | 2 +- .../components/tuya/number/tuya_number.cpp | 2 +- esphome/components/valve/valve.cpp | 2 +- .../components/water_heater/water_heater.cpp | 2 +- esphome/core/entity_base.cpp | 42 +++++++++++++++++++ esphome/core/entity_base.h | 18 ++++++++ 32 files changed, 97 insertions(+), 38 deletions(-) diff --git a/esphome/components/bl0940/number/calibration_number.cpp b/esphome/components/bl0940/number/calibration_number.cpp index e83c3add1f..5e775004bd 100644 --- a/esphome/components/bl0940/number/calibration_number.cpp +++ b/esphome/components/bl0940/number/calibration_number.cpp @@ -9,7 +9,7 @@ static const char *const TAG = "bl0940.number"; void CalibrationNumber::setup() { float value = 0.0f; if (this->restore_value_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (!this->pref_.load(&value)) { value = 0.0f; } diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 816bd5dfcb..ba6de4ff61 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -360,8 +360,7 @@ void Climate::add_on_control_callback(std::function &&callb static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL; optional Climate::restore_state_() { - this->rtc_ = global_preferences->make_preference(this->get_preference_hash() ^ - RESTORE_STATE_VERSION); + this->rtc_ = this->make_entity_preference(RESTORE_STATE_VERSION); ClimateDeviceRestoreState recovered{}; if (!this->rtc_.load(&recovered)) return {}; diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index 68688794d7..0d9e7e8ffb 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -187,7 +187,7 @@ void Cover::publish_state(bool save) { } } optional Cover::restore_state_() { - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); CoverRestoreState recovered{}; if (!this->rtc_.load(&recovered)) return {}; diff --git a/esphome/components/duty_time/duty_time_sensor.cpp b/esphome/components/duty_time/duty_time_sensor.cpp index f77f1fcf53..561040623d 100644 --- a/esphome/components/duty_time/duty_time_sensor.cpp +++ b/esphome/components/duty_time/duty_time_sensor.cpp @@ -41,7 +41,7 @@ void DutyTimeSensor::setup() { uint32_t seconds = 0; if (this->restore_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); this->pref_.load(&seconds); } diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 02fde730eb..a983babe1c 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -227,8 +227,7 @@ void Fan::publish_state() { constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABA; optional Fan::restore_state_() { FanRestoreState recovered{}; - this->rtc_ = - global_preferences->make_preference(this->get_preference_hash() ^ RESTORE_STATE_VERSION); + this->rtc_ = this->make_entity_preference(RESTORE_STATE_VERSION); bool restored = this->rtc_.load(&recovered); switch (this->restore_mode_) { diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index cd2673a272..1882aa439e 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -350,8 +350,7 @@ ClimateTraits HaierClimateBase::traits() { return traits_; } void HaierClimateBase::initialization() { constexpr uint32_t restore_settings_version = 0xA77D21EF; - this->base_rtc_ = - global_preferences->make_preference(this->get_preference_hash() ^ restore_settings_version); + this->base_rtc_ = this->make_entity_preference(restore_settings_version); HaierBaseSettings recovered; if (!this->base_rtc_.load(&recovered)) { recovered = {false, true}; diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 23d28bfd47..d98d273957 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -515,8 +515,7 @@ haier_protocol::HaierMessage HonClimate::get_power_message(bool state) { void HonClimate::initialization() { HaierClimateBase::initialization(); constexpr uint32_t restore_settings_version = 0x57EB59DDUL; - this->hon_rtc_ = - global_preferences->make_preference(this->get_preference_hash() ^ restore_settings_version); + this->hon_rtc_ = this->make_entity_preference(restore_settings_version); HonSettings recovered; if (this->hon_rtc_.load(&recovered)) { this->settings_ = recovered; diff --git a/esphome/components/integration/integration_sensor.cpp b/esphome/components/integration/integration_sensor.cpp index 80c718dc8d..b084801d3b 100644 --- a/esphome/components/integration/integration_sensor.cpp +++ b/esphome/components/integration/integration_sensor.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "integration"; void IntegrationSensor::setup() { if (this->restore_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); float preference_value = 0; this->pref_.load(&preference_value); this->result_ = preference_value; diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 58d469b2a7..07809023cd 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -184,7 +184,7 @@ static inline bool validate_header_footer(const uint8_t *header_footer, const ui void LD2450Component::setup() { #ifdef USE_NUMBER if (this->presence_timeout_number_ != nullptr) { - this->pref_ = global_preferences->make_preference(this->presence_timeout_number_->get_preference_hash()); + this->pref_ = this->presence_timeout_number_->make_entity_preference(); this->set_presence_timeout(); } #endif diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index 91bb2e2f1f..ed86bf58da 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -44,7 +44,7 @@ void LightState::setup() { case LIGHT_RESTORE_DEFAULT_ON: case LIGHT_RESTORE_INVERTED_DEFAULT_OFF: case LIGHT_RESTORE_INVERTED_DEFAULT_ON: - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); // Attempt to load from preferences, else fall back to default values if (!this->rtc_.load(&recovered)) { recovered.state = (this->restore_mode_ == LIGHT_RESTORE_DEFAULT_ON || @@ -57,7 +57,7 @@ void LightState::setup() { break; case LIGHT_RESTORE_AND_OFF: case LIGHT_RESTORE_AND_ON: - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); this->rtc_.load(&recovered); recovered.state = (this->restore_mode_ == LIGHT_RESTORE_AND_ON); break; diff --git a/esphome/components/lvgl/number/lvgl_number.h b/esphome/components/lvgl/number/lvgl_number.h index d9885bc7fb..44409a0ad5 100644 --- a/esphome/components/lvgl/number/lvgl_number.h +++ b/esphome/components/lvgl/number/lvgl_number.h @@ -21,7 +21,7 @@ class LVGLNumber : public number::Number, public Component { void setup() override { float value = this->value_lambda_(); if (this->restore_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (this->pref_.load(&value)) { this->control_lambda_(value); } diff --git a/esphome/components/lvgl/select/lvgl_select.h b/esphome/components/lvgl/select/lvgl_select.h index 70bb3e7bcb..ba03920a88 100644 --- a/esphome/components/lvgl/select/lvgl_select.h +++ b/esphome/components/lvgl/select/lvgl_select.h @@ -20,7 +20,7 @@ class LVGLSelect : public select::Select, public Component { this->set_options_(); if (this->restore_) { size_t index; - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (this->pref_.load(&index)) this->widget_->set_selected_index(index, LV_ANIM_OFF); } diff --git a/esphome/components/number/automation.cpp b/esphome/components/number/automation.cpp index 78ffc255fe..a3d49a6ff6 100644 --- a/esphome/components/number/automation.cpp +++ b/esphome/components/number/automation.cpp @@ -14,8 +14,7 @@ void ValueRangeTrigger::setup() { float local_min = this->min_.value(0.0); float local_max = this->max_.value(0.0); convert hash = {.from = (local_max - local_min)}; - uint32_t myhash = hash.to ^ this->parent_->get_preference_hash(); - this->rtc_ = global_preferences->make_preference(myhash); + this->rtc_ = this->parent_->make_entity_preference(hash.to); bool initial_state; if (this->rtc_.load(&initial_state)) { this->previous_in_range_ = initial_state; diff --git a/esphome/components/opentherm/number/opentherm_number.cpp b/esphome/components/opentherm/number/opentherm_number.cpp index f0c69144c8..bdb02a605c 100644 --- a/esphome/components/opentherm/number/opentherm_number.cpp +++ b/esphome/components/opentherm/number/opentherm_number.cpp @@ -17,7 +17,7 @@ void OpenthermNumber::setup() { if (!this->restore_value_) { value = this->initial_value_; } else { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (!this->pref_.load(&value)) { if (!std::isnan(this->initial_value_)) { value = this->initial_value_; diff --git a/esphome/components/rotary_encoder/rotary_encoder.cpp b/esphome/components/rotary_encoder/rotary_encoder.cpp index 26e20664f2..c652944120 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.cpp +++ b/esphome/components/rotary_encoder/rotary_encoder.cpp @@ -132,7 +132,7 @@ void RotaryEncoderSensor::setup() { int32_t initial_value = 0; switch (this->restore_mode_) { case ROTARY_ENCODER_RESTORE_DEFAULT_ZERO: - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); if (!this->rtc_.load(&initial_value)) { initial_value = 0; } diff --git a/esphome/components/sensor/automation.h b/esphome/components/sensor/automation.h index 996c7fc9b5..b4de712727 100644 --- a/esphome/components/sensor/automation.h +++ b/esphome/components/sensor/automation.h @@ -39,7 +39,7 @@ class ValueRangeTrigger : public Trigger, public Component { template void set_max(V max) { this->max_ = max; } void setup() override { - this->rtc_ = global_preferences->make_preference(this->parent_->get_preference_hash()); + this->rtc_ = this->parent_->make_entity_preference(); bool initial_state; if (this->rtc_.load(&initial_state)) { this->previous_in_range_ = initial_state; diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 9a3a47bac8..172bc980a8 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -55,7 +55,7 @@ void SpeakerMediaPlayer::setup() { this->media_control_command_queue_ = xQueueCreate(MEDIA_CONTROLS_QUEUE_LENGTH, sizeof(MediaCallCommand)); - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); VolumeRestoreState volume_restore_state; if (this->pref_.load(&volume_restore_state)) { diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 369ee5e6ff..2a60eb042b 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -16,7 +16,7 @@ void SprinklerControllerNumber::setup() { if (!this->restore_value_) { value = this->initial_value_; } else { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (!this->pref_.load(&value)) { if (!std::isnan(this->initial_value_)) { value = this->initial_value_; diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 069533fa78..d880139c5f 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -34,7 +34,7 @@ optional Switch::get_initial_state() { if (!(restore_mode & RESTORE_MODE_PERSISTENT_MASK)) return {}; - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); bool initial_state; if (!this->rtc_.load(&initial_state)) return {}; diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp index 028d6f0879..1a5aef6b8d 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp @@ -82,7 +82,7 @@ void TemplateAlarmControlPanel::setup() { this->current_state_ = ACP_STATE_DISARMED; if (this->restore_mode_ == ALARM_CONTROL_PANEL_RESTORE_DEFAULT_DISARMED) { uint8_t value; - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (this->pref_.load(&value)) { this->current_state_ = static_cast(value); } diff --git a/esphome/components/template/datetime/template_date.cpp b/esphome/components/template/datetime/template_date.cpp index 303d5ae2b0..be1d875a7e 100644 --- a/esphome/components/template/datetime/template_date.cpp +++ b/esphome/components/template/datetime/template_date.cpp @@ -18,8 +18,7 @@ void TemplateDate::setup() { state = this->initial_value_; } else { datetime::DateEntityRestoreState temp; - this->pref_ = - global_preferences->make_preference(194434030U ^ this->get_preference_hash()); + this->pref_ = this->make_entity_preference(194434030U); if (this->pref_.load(&temp)) { temp.apply(this); return; diff --git a/esphome/components/template/datetime/template_datetime.cpp b/esphome/components/template/datetime/template_datetime.cpp index 81a823f53e..e134f2b654 100644 --- a/esphome/components/template/datetime/template_datetime.cpp +++ b/esphome/components/template/datetime/template_datetime.cpp @@ -18,8 +18,7 @@ void TemplateDateTime::setup() { state = this->initial_value_; } else { datetime::DateTimeEntityRestoreState temp; - this->pref_ = global_preferences->make_preference( - 194434090U ^ this->get_preference_hash()); + this->pref_ = this->make_entity_preference(194434090U); if (this->pref_.load(&temp)) { temp.apply(this); return; diff --git a/esphome/components/template/datetime/template_time.cpp b/esphome/components/template/datetime/template_time.cpp index 21f843dcc7..586e126e3b 100644 --- a/esphome/components/template/datetime/template_time.cpp +++ b/esphome/components/template/datetime/template_time.cpp @@ -18,8 +18,7 @@ void TemplateTime::setup() { state = this->initial_value_; } else { datetime::TimeEntityRestoreState temp; - this->pref_ = - global_preferences->make_preference(194434060U ^ this->get_preference_hash()); + this->pref_ = this->make_entity_preference(194434060U); if (this->pref_.load(&temp)) { temp.apply(this); return; diff --git a/esphome/components/template/number/template_number.cpp b/esphome/components/template/number/template_number.cpp index 76fef82225..885265cf5d 100644 --- a/esphome/components/template/number/template_number.cpp +++ b/esphome/components/template/number/template_number.cpp @@ -13,7 +13,7 @@ void TemplateNumber::setup() { if (!this->restore_value_) { value = this->initial_value_; } else { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); if (!this->pref_.load(&value)) { if (!std::isnan(this->initial_value_)) { value = this->initial_value_; diff --git a/esphome/components/template/select/template_select.cpp b/esphome/components/template/select/template_select.cpp index 818abfc1d7..fa34aa9fa7 100644 --- a/esphome/components/template/select/template_select.cpp +++ b/esphome/components/template/select/template_select.cpp @@ -11,7 +11,7 @@ void TemplateSelect::setup() { size_t index = this->initial_option_index_; if (this->restore_value_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); size_t restored_index; if (this->pref_.load(&restored_index) && this->has_index(restored_index)) { index = restored_index; diff --git a/esphome/components/template/text/template_text.cpp b/esphome/components/template/text/template_text.cpp index 5acbb6e15a..70b8dce312 100644 --- a/esphome/components/template/text/template_text.cpp +++ b/esphome/components/template/text/template_text.cpp @@ -20,7 +20,14 @@ void TemplateText::setup() { // Need std::string for pref_->setup() to fill from flash std::string value{this->initial_value_ != nullptr ? this->initial_value_ : ""}; + // For future hash migration: use migrate_entity_preference_() with: + // old_key = get_preference_hash() + extra + // new_key = get_preference_hash_v2() + extra + // See: https://github.com/esphome/backlog/issues/85 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" uint32_t key = this->get_preference_hash(); +#pragma GCC diagnostic pop key += this->traits.get_min_length() << 2; key += this->traits.get_max_length() << 4; key += fnv1_hash(this->traits.get_pattern_c_str()) << 6; diff --git a/esphome/components/total_daily_energy/total_daily_energy.cpp b/esphome/components/total_daily_energy/total_daily_energy.cpp index 818696f99b..e7a45a5edf 100644 --- a/esphome/components/total_daily_energy/total_daily_energy.cpp +++ b/esphome/components/total_daily_energy/total_daily_energy.cpp @@ -10,7 +10,7 @@ void TotalDailyEnergy::setup() { float initial_value = 0; if (this->restore_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); this->pref_.load(&initial_value); } this->publish_state_and_save(initial_value); diff --git a/esphome/components/tuya/number/tuya_number.cpp b/esphome/components/tuya/number/tuya_number.cpp index 44b22167de..fd22e642c6 100644 --- a/esphome/components/tuya/number/tuya_number.cpp +++ b/esphome/components/tuya/number/tuya_number.cpp @@ -8,7 +8,7 @@ static const char *const TAG = "tuya.number"; void TuyaNumber::setup() { if (this->restore_value_) { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); } this->parent_->register_listener(this->number_id_, [this](const TuyaDatapoint &datapoint) { diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index 3a7c3cbf88..607f614ef7 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -163,7 +163,7 @@ void Valve::publish_state(bool save) { } } optional Valve::restore_state_() { - this->rtc_ = global_preferences->make_preference(this->get_preference_hash()); + this->rtc_ = this->make_entity_preference(); ValveRestoreState recovered{}; if (!this->rtc_.load(&recovered)) return {}; diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index fbb4181209..7266294d84 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -185,7 +185,7 @@ void WaterHeater::publish_state() { } optional WaterHeater::restore_state_() { - this->pref_ = global_preferences->make_preference(this->get_preference_hash()); + this->pref_ = this->make_entity_preference(); SavedWaterHeaterState recovered{}; if (!this->pref_.load(&recovered)) return {}; diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 8508b93411..7d7878f53a 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -92,6 +92,48 @@ StringRef EntityBase::get_object_id_to(std::span buf) c uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; } +// Migrate preference data from old_key to new_key if they differ. +// This helper is exposed so callers with custom key computation (like TextPrefs) +// can use it for manual migration. See: https://github.com/esphome/backlog/issues/85 +// +// FUTURE IMPLEMENTATION: +// This will require raw load/save methods on ESPPreferenceObject that take uint8_t* and size. +// void EntityBase::migrate_entity_preference_(size_t size, uint32_t old_key, uint32_t new_key) { +// if (old_key == new_key) +// return; +// auto old_pref = global_preferences->make_preference(size, old_key); +// auto new_pref = global_preferences->make_preference(size, new_key); +// SmallBufferWithHeapFallback<64> buffer(size); +// if (old_pref.load(buffer.data(), size)) { +// new_pref.save(buffer.data(), size); +// } +// } + +ESPPreferenceObject EntityBase::make_entity_preference_(size_t size, uint32_t version) { + // This helper centralizes preference creation to enable fixing hash collisions. + // See: https://github.com/esphome/backlog/issues/85 + // + // COLLISION PROBLEM: get_preference_hash() uses fnv1_hash on sanitized object_id. + // Multiple entity names can sanitize to the same object_id: + // - "Living Room" and "living_room" both become "living_room" + // - UTF-8 names like "温度" and "湿度" both become "__" (underscores) + // This causes entities to overwrite each other's stored preferences. + // + // FUTURE MIGRATION: When implementing get_preference_hash_v2() that hashes + // the original entity name (not sanitized object_id): + // + // uint32_t old_key = this->get_preference_hash() ^ version; + // uint32_t new_key = this->get_preference_hash_v2() ^ version; + // this->migrate_entity_preference_(size, old_key, new_key); + // return global_preferences->make_preference(size, new_key); + // +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + uint32_t key = this->get_preference_hash() ^ version; +#pragma GCC diagnostic pop + return global_preferences->make_preference(size, key); +} + std::string EntityBase_DeviceClass::get_device_class() { if (this->device_class_ == nullptr) { return ""; diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index f91bd9b20c..0b75b25817 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -6,6 +6,7 @@ #include "string_ref.h" #include "helpers.h" #include "log.h" +#include "preferences.h" #ifdef USE_DEVICES #include "device.h" @@ -138,7 +139,12 @@ class EntityBase { * from previous versions, so existing single-device configurations will continue to work. * * @return uint32_t The unique hash for preferences, including device_id if available. + * @deprecated Use make_entity_preference() instead, or preferences won't be migrated. + * See https://github.com/esphome/backlog/issues/85 */ + ESPDEPRECATED("Use make_entity_preference() instead, or preferences won't be migrated. " + "See https://github.com/esphome/backlog/issues/85. Will be removed in 2027.1.0.", + "2026.7.0") uint32_t get_preference_hash() { #ifdef USE_DEVICES // Combine object_id_hash with device_id to ensure uniqueness across devices @@ -151,7 +157,19 @@ class EntityBase { #endif } + /// Create a preference object for storing this entity's state/settings. + /// @tparam T The type of data to store (must be trivially copyable) + /// @param version Optional version hash XORed with preference key (change when struct layout changes) + template ESPPreferenceObject make_entity_preference(uint32_t version = 0) { + static_assert(std::is_trivially_copyable::value, "T must be trivially copyable"); + return this->make_entity_preference_(sizeof(T), version); + } + protected: + /// Non-template helper for make_entity_preference() to avoid code bloat. + /// When preference hash algorithm changes, migration logic goes here. + ESPPreferenceObject make_entity_preference_(size_t size, uint32_t version); + void calc_object_id_(); StringRef name_; From d056e1040b4469ca9a1296a97ff554711b072412 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:48:06 -1000 Subject: [PATCH 0381/2030] [mqtt] Store command comparison strings in flash on ESP8266 (#13546) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../mqtt/mqtt_alarm_control_panel.cpp | 17 +++++++++-------- esphome/components/mqtt/mqtt_lock.cpp | 7 ++++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index fbdc6dce23..263e554778 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -1,5 +1,6 @@ #include "mqtt_alarm_control_panel.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -18,21 +19,21 @@ void MQTTAlarmControlPanelComponent::setup() { this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); }); this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) { auto call = this->alarm_control_panel_->make_call(); - if (strcasecmp(payload.c_str(), "ARM_AWAY") == 0) { + if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_AWAY")) == 0) { call.arm_away(); - } else if (strcasecmp(payload.c_str(), "ARM_HOME") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_HOME")) == 0) { call.arm_home(); - } else if (strcasecmp(payload.c_str(), "ARM_NIGHT") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_NIGHT")) == 0) { call.arm_night(); - } else if (strcasecmp(payload.c_str(), "ARM_VACATION") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_VACATION")) == 0) { call.arm_vacation(); - } else if (strcasecmp(payload.c_str(), "ARM_CUSTOM_BYPASS") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_CUSTOM_BYPASS")) == 0) { call.arm_custom_bypass(); - } else if (strcasecmp(payload.c_str(), "DISARM") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("DISARM")) == 0) { call.disarm(); - } else if (strcasecmp(payload.c_str(), "PENDING") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("PENDING")) == 0) { call.pending(); - } else if (strcasecmp(payload.c_str(), "TRIGGERED") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("TRIGGERED")) == 0) { call.triggered(); } else { ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name_().c_str(), payload.c_str()); diff --git a/esphome/components/mqtt/mqtt_lock.cpp b/esphome/components/mqtt/mqtt_lock.cpp index 96c9397da8..45d8e4698f 100644 --- a/esphome/components/mqtt/mqtt_lock.cpp +++ b/esphome/components/mqtt/mqtt_lock.cpp @@ -1,5 +1,6 @@ #include "mqtt_lock.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -16,11 +17,11 @@ MQTTLockComponent::MQTTLockComponent(lock::Lock *a_lock) : lock_(a_lock) {} void MQTTLockComponent::setup() { this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) { - if (strcasecmp(payload.c_str(), "LOCK") == 0) { + if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("LOCK")) == 0) { this->lock_->lock(); - } else if (strcasecmp(payload.c_str(), "UNLOCK") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("UNLOCK")) == 0) { this->lock_->unlock(); - } else if (strcasecmp(payload.c_str(), "OPEN") == 0) { + } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("OPEN")) == 0) { this->lock_->open(); } else { ESP_LOGW(TAG, "'%s': Received unknown status payload: %s", this->friendly_name_().c_str(), payload.c_str()); From 33f545a8e36762c417e2bf26bc4b62b1f58529a6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:50:49 -1000 Subject: [PATCH 0382/2030] [factory_reset] Store reset reason comparison strings in flash on ESP8266 (#13547) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/factory_reset/factory_reset.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/factory_reset/factory_reset.cpp b/esphome/components/factory_reset/factory_reset.cpp index 2e3f802343..cd4134e9ae 100644 --- a/esphome/components/factory_reset/factory_reset.cpp +++ b/esphome/components/factory_reset/factory_reset.cpp @@ -3,6 +3,7 @@ #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include @@ -19,7 +20,8 @@ static bool was_power_cycled() { #endif #ifdef USE_ESP8266 auto reset_reason = EspClass::getResetReason(); - return strcasecmp(reset_reason.c_str(), "power On") == 0 || strcasecmp(reset_reason.c_str(), "external system") == 0; + return ESPHOME_strcasecmp_P(reset_reason.c_str(), ESPHOME_PSTR("power On")) == 0 || + ESPHOME_strcasecmp_P(reset_reason.c_str(), ESPHOME_PSTR("external system")) == 0; #endif #ifdef USE_LIBRETINY auto reason = lt_get_reboot_reason(); From 3aaf10b6a88bdf30b2615b94a7474ed891c451ed Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 18:18:57 -1000 Subject: [PATCH 0383/2030] [web_server_base] Update ESPAsyncWebServer to 3.9.5 (#13467) --- .clang-tidy.hash | 2 +- esphome/components/web_server_base/__init__.py | 2 +- platformio.ini | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 009f9db388..55239f961c 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -d565b0589e35e692b5f2fc0c14723a99595b4828a3a3ef96c442e86a23176c00 +a172e2f65981e98354cc6b5ecf69bdb055dd13602226042ab2c7acd037a2bf41 diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index d5d75b395d..e0eec7dedb 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -48,4 +48,4 @@ async def to_code(config): if CORE.is_libretiny: CORE.add_platformio_option("lib_ignore", ["ESPAsyncTCP", "RPAsyncTCP"]) # https://github.com/ESP32Async/ESPAsyncWebServer/blob/main/library.json - cg.add_library("ESP32Async/ESPAsyncWebServer", "3.7.10") + cg.add_library("ESP32Async/ESPAsyncWebServer", "3.9.5") diff --git a/platformio.ini b/platformio.ini index 9de72cd622..accc40ecf2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -114,7 +114,7 @@ lib_deps = ESP8266WiFi ; wifi (Arduino built-in) Update ; ota (Arduino built-in) ESP32Async/ESPAsyncTCP@2.0.0 ; async_tcp - ESP32Async/ESPAsyncWebServer@3.7.8 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base makuna/NeoPixelBus@2.7.3 ; neopixelbus ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) @@ -201,7 +201,7 @@ framework = arduino lib_deps = ${common:arduino.lib_deps} bblanchon/ArduinoJson@7.4.2 ; json - ESP32Async/ESPAsyncWebServer@3.7.8 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base build_flags = ${common:arduino.build_flags} -DUSE_RP2040 @@ -217,7 +217,7 @@ framework = arduino lib_compat_mode = soft lib_deps = bblanchon/ArduinoJson@7.4.2 ; json - ESP32Async/ESPAsyncWebServer@3.7.8 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:arduino.build_flags} From b2474c6de9099ea8f36e84192d3fbfe49c32a7c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 19:43:52 -1000 Subject: [PATCH 0384/2030] [nfc] Use StaticVector for NFC UID storage to eliminate heap allocation (#13507) --- .../nfc/binary_sensor/nfc_binary_sensor.cpp | 4 +-- .../nfc/binary_sensor/nfc_binary_sensor.h | 6 ++-- esphome/components/nfc/nfc.cpp | 12 ++++--- esphome/components/nfc/nfc.h | 9 ++--- esphome/components/nfc/nfc_tag.h | 21 ++++++------ esphome/components/pn532/pn532.cpp | 14 ++++---- esphome/components/pn532/pn532.h | 30 ++++++++-------- .../components/pn532/pn532_mifare_classic.cpp | 11 +++--- .../pn532/pn532_mifare_ultralight.cpp | 4 +-- esphome/components/pn7150/pn7150.cpp | 10 +++--- esphome/components/pn7150/pn7150.h | 10 +++--- .../pn7150/pn7150_mifare_ultralight.cpp | 3 +- esphome/components/pn7160/pn7160.cpp | 10 +++--- esphome/components/pn7160/pn7160.h | 10 +++--- .../pn7160/pn7160_mifare_ultralight.cpp | 3 +- esphome/core/helpers.h | 34 +++++++++++++++++++ 16 files changed, 114 insertions(+), 77 deletions(-) diff --git a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp index b62b243cc6..524ad5a413 100644 --- a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp +++ b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.cpp @@ -40,7 +40,7 @@ void NfcTagBinarySensor::set_tag_name(const std::string &str) { this->match_tag_name_ = true; } -void NfcTagBinarySensor::set_uid(const std::vector &uid) { this->uid_ = uid; } +void NfcTagBinarySensor::set_uid(const NfcTagUid &uid) { this->uid_ = uid; } bool NfcTagBinarySensor::tag_match_ndef_string(const std::shared_ptr &msg) { for (const auto &record : msg->get_records()) { @@ -63,7 +63,7 @@ bool NfcTagBinarySensor::tag_match_tag_name(const std::shared_ptr & return false; } -bool NfcTagBinarySensor::tag_match_uid(const std::vector &data) { +bool NfcTagBinarySensor::tag_match_uid(const NfcTagUid &data) { if (data.size() != this->uid_.size()) { return false; } diff --git a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h index cc313c2f2b..0a7ca0ca76 100644 --- a/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h +++ b/esphome/components/nfc/binary_sensor/nfc_binary_sensor.h @@ -19,11 +19,11 @@ class NfcTagBinarySensor : public binary_sensor::BinarySensor, void set_ndef_match_string(const std::string &str); void set_tag_name(const std::string &str); - void set_uid(const std::vector &uid); + void set_uid(const NfcTagUid &uid); bool tag_match_ndef_string(const std::shared_ptr &msg); bool tag_match_tag_name(const std::shared_ptr &msg); - bool tag_match_uid(const std::vector &data); + bool tag_match_uid(const NfcTagUid &data); void tag_off(NfcTag &tag) override; void tag_on(NfcTag &tag) override; @@ -31,7 +31,7 @@ class NfcTagBinarySensor : public binary_sensor::BinarySensor, protected: bool match_tag_name_{false}; std::string match_string_; - std::vector uid_; + NfcTagUid uid_; }; } // namespace nfc diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index f60d2671cd..8567b0969a 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -8,19 +8,23 @@ namespace nfc { static const char *const TAG = "nfc"; -char *format_uid_to(char *buffer, const std::vector &uid) { +char *format_uid_to(char *buffer, std::span uid) { return format_hex_pretty_to(buffer, FORMAT_UID_BUFFER_SIZE, uid.data(), uid.size(), '-'); } -char *format_bytes_to(char *buffer, const std::vector &bytes) { +char *format_bytes_to(char *buffer, std::span bytes) { return format_hex_pretty_to(buffer, FORMAT_BYTES_BUFFER_SIZE, bytes.data(), bytes.size(), ' '); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" // Deprecated wrappers intentionally use heap-allocating version for backward compatibility -std::string format_uid(const std::vector &uid) { return format_hex_pretty(uid, '-', false); } // NOLINT -std::string format_bytes(const std::vector &bytes) { return format_hex_pretty(bytes, ' ', false); } // NOLINT +std::string format_uid(std::span uid) { + return format_hex_pretty(uid.data(), uid.size(), '-', false); // NOLINT +} +std::string format_bytes(std::span bytes) { + return format_hex_pretty(bytes.data(), bytes.size(), ' ', false); // NOLINT +} #pragma GCC diagnostic pop uint8_t guess_tag_type(uint8_t uid_length) { diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index 6568c60a85..5191904833 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -6,6 +6,7 @@ #include "ndef_record.h" #include "nfc_tag.h" +#include #include namespace esphome { @@ -56,19 +57,19 @@ static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; /// Max UID size is 10 bytes, formatted as "XX-XX-XX-XX-XX-XX-XX-XX-XX-XX\0" = 30 chars static constexpr size_t FORMAT_UID_BUFFER_SIZE = 30; /// Format UID to buffer with '-' separator (e.g., "04-11-22-33"). Returns buffer for inline use. -char *format_uid_to(char *buffer, const std::vector &uid); +char *format_uid_to(char *buffer, std::span uid); /// Buffer size for format_bytes_to (64 bytes max = 192 chars with space separator) static constexpr size_t FORMAT_BYTES_BUFFER_SIZE = 192; /// Format bytes to buffer with ' ' separator (e.g., "04 11 22 33"). Returns buffer for inline use. -char *format_bytes_to(char *buffer, const std::vector &bytes); +char *format_bytes_to(char *buffer, std::span bytes); // Remove before 2026.6.0 ESPDEPRECATED("Use format_uid_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") -std::string format_uid(const std::vector &uid); +std::string format_uid(std::span uid); // Remove before 2026.6.0 ESPDEPRECATED("Use format_bytes_to() with stack buffer instead. Removed in 2026.6.0", "2025.12.0") -std::string format_bytes(const std::vector &bytes); +std::string format_bytes(std::span bytes); uint8_t guess_tag_type(uint8_t uid_length); uint8_t get_mifare_classic_ndef_start_index(std::vector &data); diff --git a/esphome/components/nfc/nfc_tag.h b/esphome/components/nfc/nfc_tag.h index 55600c3bd9..0ded4cd6ee 100644 --- a/esphome/components/nfc/nfc_tag.h +++ b/esphome/components/nfc/nfc_tag.h @@ -10,26 +10,27 @@ namespace esphome { namespace nfc { +// NFC UIDs are 4, 7, or 10 bytes depending on tag type +static constexpr size_t NFC_UID_MAX_LENGTH = 10; +using NfcTagUid = StaticVector; + class NfcTag { public: - NfcTag() { - this->uid_ = {}; - this->tag_type_ = "Unknown"; - }; - NfcTag(std::vector &uid) { + NfcTag() { this->tag_type_ = "Unknown"; }; + NfcTag(const NfcTagUid &uid) { this->uid_ = uid; this->tag_type_ = "Unknown"; }; - NfcTag(std::vector &uid, const std::string &tag_type) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type) { this->uid_ = uid; this->tag_type_ = tag_type; }; - NfcTag(std::vector &uid, const std::string &tag_type, std::unique_ptr ndef_message) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type, std::unique_ptr ndef_message) { this->uid_ = uid; this->tag_type_ = tag_type; this->ndef_message_ = std::move(ndef_message); }; - NfcTag(std::vector &uid, const std::string &tag_type, std::vector &ndef_data) { + NfcTag(const NfcTagUid &uid, const std::string &tag_type, std::vector &ndef_data) { this->uid_ = uid; this->tag_type_ = tag_type; this->ndef_message_ = make_unique(ndef_data); @@ -41,14 +42,14 @@ class NfcTag { ndef_message_ = make_unique(*rhs.ndef_message_); } - std::vector &get_uid() { return this->uid_; }; + NfcTagUid &get_uid() { return this->uid_; }; const std::string &get_tag_type() { return this->tag_type_; }; bool has_ndef_message() { return this->ndef_message_ != nullptr; }; const std::shared_ptr &get_ndef_message() { return this->ndef_message_; }; void set_ndef_message(std::unique_ptr ndef_message) { this->ndef_message_ = std::move(ndef_message); }; protected: - std::vector uid_; + NfcTagUid uid_; std::string tag_type_; std::shared_ptr ndef_message_; }; diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index 8f0c5581d4..733810c242 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -168,11 +168,11 @@ void PN532::loop() { } uint8_t nfcid_length = read[5]; - std::vector nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length); - if (read.size() < 6U + nfcid_length) { + if (nfcid_length > nfc::NFC_UID_MAX_LENGTH || read.size() < 6U + nfcid_length) { // oops, pn532 returned invalid data return; } + nfc::NfcTagUid nfcid(read.begin() + 6, read.begin() + 6 + nfcid_length); bool report = true; for (auto *bin_sens : this->binary_sensors_) { @@ -358,7 +358,7 @@ void PN532::turn_off_rf_() { }); } -std::unique_ptr PN532::read_tag_(std::vector &uid) { +std::unique_ptr PN532::read_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { @@ -393,7 +393,7 @@ void PN532::write_mode(nfc::NdefMessage *message) { ESP_LOGD(TAG, "Waiting to write next tag"); } -bool PN532::clean_tag_(std::vector &uid) { +bool PN532::clean_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->format_mifare_classic_mifare_(uid); @@ -404,7 +404,7 @@ bool PN532::clean_tag_(std::vector &uid) { return false; } -bool PN532::format_tag_(std::vector &uid) { +bool PN532::format_tag_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->format_mifare_classic_ndef_(uid); @@ -415,7 +415,7 @@ bool PN532::format_tag_(std::vector &uid) { return false; } -bool PN532::write_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { uint8_t type = nfc::guess_tag_type(uid.size()); if (type == nfc::TAG_TYPE_MIFARE_CLASSIC) { return this->write_mifare_classic_tag_(uid, message); @@ -448,7 +448,7 @@ void PN532::dump_config() { } } -bool PN532BinarySensor::process(std::vector &data) { +bool PN532BinarySensor::process(const nfc::NfcTagUid &data) { if (data.size() != this->uid_.size()) return false; diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index eeb15648fb..488ec4af3b 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -69,28 +69,28 @@ class PN532 : public PollingComponent { virtual bool read_data(std::vector &data, uint8_t len) = 0; virtual bool read_response(uint8_t command, std::vector &data) = 0; - std::unique_ptr read_tag_(std::vector &uid); + std::unique_ptr read_tag_(nfc::NfcTagUid &uid); - bool format_tag_(std::vector &uid); - bool clean_tag_(std::vector &uid); - bool write_tag_(std::vector &uid, nfc::NdefMessage *message); + bool format_tag_(nfc::NfcTagUid &uid); + bool clean_tag_(nfc::NfcTagUid &uid); + bool write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); - std::unique_ptr read_mifare_classic_tag_(std::vector &uid); + std::unique_ptr read_mifare_classic_tag_(nfc::NfcTagUid &uid); bool read_mifare_classic_block_(uint8_t block_num, std::vector &data); bool write_mifare_classic_block_(uint8_t block_num, std::vector &data); - bool auth_mifare_classic_block_(std::vector &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key); - bool format_mifare_classic_mifare_(std::vector &uid); - bool format_mifare_classic_ndef_(std::vector &uid); - bool write_mifare_classic_tag_(std::vector &uid, nfc::NdefMessage *message); + bool auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key); + bool format_mifare_classic_mifare_(nfc::NfcTagUid &uid); + bool format_mifare_classic_ndef_(nfc::NfcTagUid &uid); + bool write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); - std::unique_ptr read_mifare_ultralight_tag_(std::vector &uid); + std::unique_ptr read_mifare_ultralight_tag_(nfc::NfcTagUid &uid); bool read_mifare_ultralight_bytes_(uint8_t start_page, uint16_t num_bytes, std::vector &data); bool is_mifare_ultralight_formatted_(const std::vector &page_3_to_6); uint16_t read_mifare_ultralight_capacity_(); bool find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); bool write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - bool write_mifare_ultralight_tag_(std::vector &uid, nfc::NdefMessage *message); + bool write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); bool clean_mifare_ultralight_(); bool updates_enabled_{true}; @@ -98,7 +98,7 @@ class PN532 : public PollingComponent { std::vector binary_sensors_; std::vector triggers_ontag_; std::vector triggers_ontagremoved_; - std::vector current_uid_; + nfc::NfcTagUid current_uid_; nfc::NdefMessage *next_task_message_to_write_; uint32_t rd_start_time_{0}; enum PN532ReadReady rd_ready_ { WOULDBLOCK }; @@ -118,9 +118,9 @@ class PN532 : public PollingComponent { class PN532BinarySensor : public binary_sensor::BinarySensor { public: - void set_uid(const std::vector &uid) { uid_ = uid; } + void set_uid(const nfc::NfcTagUid &uid) { uid_ = uid; } - bool process(std::vector &data); + bool process(const nfc::NfcTagUid &data); void on_scan_end() { if (!this->found_) { @@ -130,7 +130,7 @@ class PN532BinarySensor : public binary_sensor::BinarySensor { } protected: - std::vector uid_; + nfc::NfcTagUid uid_; bool found_{false}; }; diff --git a/esphome/components/pn532/pn532_mifare_classic.cpp b/esphome/components/pn532/pn532_mifare_classic.cpp index 28ab22e160..b762d5d936 100644 --- a/esphome/components/pn532/pn532_mifare_classic.cpp +++ b/esphome/components/pn532/pn532_mifare_classic.cpp @@ -8,7 +8,7 @@ namespace pn532 { static const char *const TAG = "pn532.mifare_classic"; -std::unique_ptr PN532::read_mifare_classic_tag_(std::vector &uid) { +std::unique_ptr PN532::read_mifare_classic_tag_(nfc::NfcTagUid &uid) { uint8_t current_block = 4; uint8_t message_start_index = 0; uint32_t message_length = 0; @@ -82,8 +82,7 @@ bool PN532::read_mifare_classic_block_(uint8_t block_num, std::vector & return true; } -bool PN532::auth_mifare_classic_block_(std::vector &uid, uint8_t block_num, uint8_t key_num, - const uint8_t *key) { +bool PN532::auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key) { std::vector data({ PN532_COMMAND_INDATAEXCHANGE, 0x01, // One card @@ -106,7 +105,7 @@ bool PN532::auth_mifare_classic_block_(std::vector &uid, uint8_t block_ return true; } -bool PN532::format_mifare_classic_mifare_(std::vector &uid) { +bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) { std::vector blank_buffer( {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); std::vector trailer_buffer( @@ -141,7 +140,7 @@ bool PN532::format_mifare_classic_mifare_(std::vector &uid) { return !error; } -bool PN532::format_mifare_classic_ndef_(std::vector &uid) { +bool PN532::format_mifare_classic_ndef_(nfc::NfcTagUid &uid) { std::vector empty_ndef_message( {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); std::vector blank_block( @@ -216,7 +215,7 @@ bool PN532::write_mifare_classic_block_(uint8_t block_num, std::vector return true; } -bool PN532::write_mifare_classic_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { auto encoded = message->encode(); uint32_t message_length = encoded.size(); diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index 0221ba31c5..01e41df5c0 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -8,7 +8,7 @@ namespace pn532 { static const char *const TAG = "pn532.mifare_ultralight"; -std::unique_ptr PN532::read_mifare_ultralight_tag_(std::vector &uid) { +std::unique_ptr PN532::read_mifare_ultralight_tag_(nfc::NfcTagUid &uid) { std::vector data; // pages 3 to 6 contain various info we are interested in -- do one read to grab it all if (!this->read_mifare_ultralight_bytes_(3, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE * nfc::MIFARE_ULTRALIGHT_READ_SIZE, @@ -114,7 +114,7 @@ bool PN532::find_mifare_ultralight_ndef_(const std::vector &page_3_to_6 return false; } -bool PN532::write_mifare_ultralight_tag_(std::vector &uid, nfc::NdefMessage *message) { +bool PN532::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/components/pn7150/pn7150.cpp b/esphome/components/pn7150/pn7150.cpp index e1ba3761d4..7bec1e08a9 100644 --- a/esphome/components/pn7150/pn7150.cpp +++ b/esphome/components/pn7150/pn7150.cpp @@ -478,7 +478,7 @@ uint8_t PN7150::read_endpoint_data_(nfc::NfcTag &tag) { return nfc::STATUS_FAILED; } -uint8_t PN7150::clean_endpoint_(std::vector &uid) { +uint8_t PN7150::clean_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -494,7 +494,7 @@ uint8_t PN7150::clean_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7150::format_endpoint_(std::vector &uid) { +uint8_t PN7150::format_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -510,7 +510,7 @@ uint8_t PN7150::format_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7150::write_endpoint_(std::vector &uid, std::shared_ptr &message) { +uint8_t PN7150::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -534,7 +534,7 @@ std::unique_ptr PN7150::build_tag_(const uint8_t mode_tech, const s ESP_LOGE(TAG, "UID length cannot be zero"); return nullptr; } - std::vector uid(data.begin() + 3, data.begin() + 3 + uid_length); + nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length); const auto *tag_type_str = nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2; return make_unique(uid, tag_type_str); @@ -543,7 +543,7 @@ std::unique_ptr PN7150::build_tag_(const uint8_t mode_tech, const s return nullptr; } -optional PN7150::find_tag_uid_(const std::vector &uid) { +optional PN7150::find_tag_uid_(const nfc::NfcTagUid &uid) { if (!this->discovered_endpoint_.empty()) { for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid(); diff --git a/esphome/components/pn7150/pn7150.h b/esphome/components/pn7150/pn7150.h index 42cd7a6ef7..a5dcef9f99 100644 --- a/esphome/components/pn7150/pn7150.h +++ b/esphome/components/pn7150/pn7150.h @@ -203,12 +203,12 @@ class PN7150 : public nfc::Nfcc, public Component { void select_endpoint_(); uint8_t read_endpoint_data_(nfc::NfcTag &tag); - uint8_t clean_endpoint_(std::vector &uid); - uint8_t format_endpoint_(std::vector &uid); - uint8_t write_endpoint_(std::vector &uid, std::shared_ptr &message); + uint8_t clean_endpoint_(nfc::NfcTagUid &uid); + uint8_t format_endpoint_(nfc::NfcTagUid &uid); + uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message); std::unique_ptr build_tag_(uint8_t mode_tech, const std::vector &data); - optional find_tag_uid_(const std::vector &uid); + optional find_tag_uid_(const nfc::NfcTagUid &uid); void purge_old_tags_(); void erase_tag_(uint8_t tag_index); @@ -251,7 +251,7 @@ class PN7150 : public nfc::Nfcc, public Component { uint8_t find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - uint8_t write_mifare_ultralight_tag_(std::vector &uid, const std::shared_ptr &message); + uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message); uint8_t clean_mifare_ultralight_(); enum NfcTask : uint8_t { diff --git a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp index ac15475bad..166065f6c1 100644 --- a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp +++ b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp @@ -115,8 +115,7 @@ uint8_t PN7150::find_mifare_ultralight_ndef_(const std::vector &page_3_ return nfc::STATUS_FAILED; } -uint8_t PN7150::write_mifare_ultralight_tag_(std::vector &uid, - const std::shared_ptr &message) { +uint8_t PN7150::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/components/pn7160/pn7160.cpp b/esphome/components/pn7160/pn7160.cpp index 1a38dce5fd..28907b8e30 100644 --- a/esphome/components/pn7160/pn7160.cpp +++ b/esphome/components/pn7160/pn7160.cpp @@ -506,7 +506,7 @@ uint8_t PN7160::read_endpoint_data_(nfc::NfcTag &tag) { return nfc::STATUS_FAILED; } -uint8_t PN7160::clean_endpoint_(std::vector &uid) { +uint8_t PN7160::clean_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -522,7 +522,7 @@ uint8_t PN7160::clean_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7160::format_endpoint_(std::vector &uid) { +uint8_t PN7160::format_endpoint_(nfc::NfcTagUid &uid) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -538,7 +538,7 @@ uint8_t PN7160::format_endpoint_(std::vector &uid) { return nfc::STATUS_FAILED; } -uint8_t PN7160::write_endpoint_(std::vector &uid, std::shared_ptr &message) { +uint8_t PN7160::write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message) { uint8_t type = nfc::guess_tag_type(uid.size()); switch (type) { case nfc::TAG_TYPE_MIFARE_CLASSIC: @@ -562,7 +562,7 @@ std::unique_ptr PN7160::build_tag_(const uint8_t mode_tech, const s ESP_LOGE(TAG, "UID length cannot be zero"); return nullptr; } - std::vector uid(data.begin() + 3, data.begin() + 3 + uid_length); + nfc::NfcTagUid uid(data.begin() + 3, data.begin() + 3 + uid_length); const auto *tag_type_str = nfc::guess_tag_type(uid_length) == nfc::TAG_TYPE_MIFARE_CLASSIC ? nfc::MIFARE_CLASSIC : nfc::NFC_FORUM_TYPE_2; return make_unique(uid, tag_type_str); @@ -571,7 +571,7 @@ std::unique_ptr PN7160::build_tag_(const uint8_t mode_tech, const s return nullptr; } -optional PN7160::find_tag_uid_(const std::vector &uid) { +optional PN7160::find_tag_uid_(const nfc::NfcTagUid &uid) { if (!this->discovered_endpoint_.empty()) { for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { auto existing_tag_uid = this->discovered_endpoint_[i].tag->get_uid(); diff --git a/esphome/components/pn7160/pn7160.h b/esphome/components/pn7160/pn7160.h index fc00296a71..572fab3351 100644 --- a/esphome/components/pn7160/pn7160.h +++ b/esphome/components/pn7160/pn7160.h @@ -220,12 +220,12 @@ class PN7160 : public nfc::Nfcc, public Component { void select_endpoint_(); uint8_t read_endpoint_data_(nfc::NfcTag &tag); - uint8_t clean_endpoint_(std::vector &uid); - uint8_t format_endpoint_(std::vector &uid); - uint8_t write_endpoint_(std::vector &uid, std::shared_ptr &message); + uint8_t clean_endpoint_(nfc::NfcTagUid &uid); + uint8_t format_endpoint_(nfc::NfcTagUid &uid); + uint8_t write_endpoint_(nfc::NfcTagUid &uid, std::shared_ptr &message); std::unique_ptr build_tag_(uint8_t mode_tech, const std::vector &data); - optional find_tag_uid_(const std::vector &uid); + optional find_tag_uid_(const nfc::NfcTagUid &uid); void purge_old_tags_(); void erase_tag_(uint8_t tag_index); @@ -268,7 +268,7 @@ class PN7160 : public nfc::Nfcc, public Component { uint8_t find_mifare_ultralight_ndef_(const std::vector &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector &write_data); - uint8_t write_mifare_ultralight_tag_(std::vector &uid, const std::shared_ptr &message); + uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message); uint8_t clean_mifare_ultralight_(); enum NfcTask : uint8_t { diff --git a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp index 584385f113..c473ff48d9 100644 --- a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp +++ b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp @@ -115,8 +115,7 @@ uint8_t PN7160::find_mifare_ultralight_ndef_(const std::vector &page_3_ return nfc::STATUS_FAILED; } -uint8_t PN7160::write_mifare_ultralight_tag_(std::vector &uid, - const std::shared_ptr &message) { +uint8_t PN7160::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr &message) { uint32_t capacity = this->read_mifare_ultralight_capacity_(); auto encoded = message->encode(); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 81397668e8..6c5904ef25 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -148,6 +148,25 @@ template class StaticVector { size_t count_{0}; public: + // Default constructor + StaticVector() = default; + + // Iterator range constructor + template StaticVector(InputIt first, InputIt last) { + while (first != last && count_ < N) { + data_[count_++] = *first++; + } + } + + // Initializer list constructor + StaticVector(std::initializer_list init) { + for (const auto &val : init) { + if (count_ >= N) + break; + data_[count_++] = val; + } + } + // Minimal vector-compatible interface - only what we actually use void push_back(const T &value) { if (count_ < N) { @@ -155,6 +174,17 @@ template class StaticVector { } } + // Clear all elements + void clear() { count_ = 0; } + + // Assign from iterator range + template void assign(InputIt first, InputIt last) { + count_ = 0; + while (first != last && count_ < N) { + data_[count_++] = *first++; + } + } + // Return reference to next element and increment count (with bounds checking) T &emplace_next() { if (count_ >= N) { @@ -186,6 +216,10 @@ template class StaticVector { reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + // Conversion to std::span for compatibility with span-based APIs + operator std::span() { return std::span(data_.data(), count_); } + operator std::span() const { return std::span(data_.data(), count_); } }; /// Fixed-capacity vector - allocates once at runtime, never reallocates From ca59ab8f370157af31b5c44a9aaef16eb3ec139c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 07:47:34 -1000 Subject: [PATCH 0385/2030] [esp32] Eliminate dead exception class code via linker wraps (#13564) --- esphome/components/esp32/__init__.py | 13 ++++++ esphome/components/esp32/throw_stubs.cpp | 57 ++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 esphome/components/esp32/throw_stubs.cpp diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index da49fdc070..b7faccaed6 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1048,6 +1048,19 @@ async def to_code(config): cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF") if use_platformio: cg.add_platformio_option("framework", "espidf") + + # Wrap std::__throw_* functions to abort immediately, eliminating ~3KB of + # exception class overhead. See throw_stubs.cpp for implementation. + # ESP-IDF already compiles with -fno-exceptions, so this code was dead anyway. + for mangled in [ + "_ZSt20__throw_length_errorPKc", + "_ZSt19__throw_logic_errorPKc", + "_ZSt20__throw_out_of_rangePKc", + "_ZSt24__throw_out_of_range_fmtPKcz", + "_ZSt17__throw_bad_allocv", + "_ZSt25__throw_bad_function_callv", + ]: + cg.add_build_flag(f"-Wl,--wrap={mangled}") else: cg.add_build_flag("-DUSE_ARDUINO") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO") diff --git a/esphome/components/esp32/throw_stubs.cpp b/esphome/components/esp32/throw_stubs.cpp new file mode 100644 index 0000000000..e82e5645de --- /dev/null +++ b/esphome/components/esp32/throw_stubs.cpp @@ -0,0 +1,57 @@ +/* + * Linker wrap stubs for std::__throw_* functions. + * + * ESP-IDF compiles with -fno-exceptions, so C++ exceptions always abort. + * However, ESP-IDF only wraps low-level functions (__cxa_throw, etc.), + * not the std::__throw_* functions that construct exception objects first. + * This pulls in ~3KB of dead exception class code that can never run. + * + * ESP8266 Arduino already solved this: their toolchain rebuilds libstdc++ + * with throw functions that just call abort(). We achieve the same result + * using linker --wrap without requiring toolchain changes. + * + * These stubs abort immediately with a descriptive message, allowing + * the linker to dead-code eliminate the exception class infrastructure. + * + * Wrapped functions and their callers: + * - std::__throw_length_error: std::string::reserve, std::vector::reserve + * - std::__throw_logic_error: std::promise, std::packaged_task + * - std::__throw_out_of_range: std::string::at, std::vector::at + * - std::__throw_out_of_range_fmt: std::bitset::to_ulong + * - std::__throw_bad_alloc: operator new + * - std::__throw_bad_function_call: std::function::operator() + */ + +#ifdef USE_ESP_IDF +#include "esp_system.h" + +namespace esphome::esp32 {} + +// Linker wraps for std::__throw_* - must be extern "C" at global scope. +// Names must be __wrap_ + mangled name for the linker's --wrap option. + +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +extern "C" { + +// std::__throw_length_error(char const*) - called when container size exceeds max_size() +void __wrap__ZSt20__throw_length_errorPKc(const char *) { esp_system_abort("std::length_error"); } + +// std::__throw_logic_error(char const*) - called for logic errors (e.g., promise already satisfied) +void __wrap__ZSt19__throw_logic_errorPKc(const char *) { esp_system_abort("std::logic_error"); } + +// std::__throw_out_of_range(char const*) - called by at() when index is out of bounds +void __wrap__ZSt20__throw_out_of_rangePKc(const char *) { esp_system_abort("std::out_of_range"); } + +// std::__throw_out_of_range_fmt(char const*, ...) - called by bitset::to_ulong when value doesn't fit +void __wrap__ZSt24__throw_out_of_range_fmtPKcz(const char *, ...) { esp_system_abort("std::out_of_range"); } + +// std::__throw_bad_alloc() - called when operator new fails +void __wrap__ZSt17__throw_bad_allocv() { esp_system_abort("std::bad_alloc"); } + +// std::__throw_bad_function_call() - called when invoking empty std::function +void __wrap__ZSt25__throw_bad_function_callv() { esp_system_abort("std::bad_function_call"); } + +} // extern "C" +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) + +#endif // USE_ESP_IDF From a0790f926ea1d3412124f66a55899d0eebe712ca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 08:59:01 -1000 Subject: [PATCH 0386/2030] [libretiny] Regenerate boards for v1.11.0 (#13539) --- esphome/components/rtl87xx/boards.py | 171 +++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/esphome/components/rtl87xx/boards.py b/esphome/components/rtl87xx/boards.py index 5a3228fb1d..45ef02b7e7 100644 --- a/esphome/components/rtl87xx/boards.py +++ b/esphome/components/rtl87xx/boards.py @@ -23,6 +23,10 @@ RTL87XX_BOARDS = { "name": "WR2 Wi-Fi Module", "family": FAMILY_RTL8710B, }, + "wbr3": { + "name": "WBR3 Wi-Fi Module", + "family": FAMILY_RTL8720C, + }, "generic-rtl8710bn-2mb-468k": { "name": "Generic - RTL8710BN (2M/468k)", "family": FAMILY_RTL8710B, @@ -79,6 +83,10 @@ RTL87XX_BOARDS = { "name": "T103_V1.0", "family": FAMILY_RTL8710B, }, + "generic-rtl8720cf-2mb-896k": { + "name": "Generic - RTL8720CF (2M/896k)", + "family": FAMILY_RTL8720C, + }, "generic-rtl8720cf-2mb-992k": { "name": "Generic - RTL8720CF (2M/992k)", "family": FAMILY_RTL8720C, @@ -221,6 +229,71 @@ RTL87XX_BOARD_PINS = { "D9": 29, "A1": 41, }, + "wbr3": { + "WIRE0_SCL_0": 11, + "WIRE0_SCL_1": 2, + "WIRE0_SCL_2": 19, + "WIRE0_SCL_3": 15, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 12, + "WIRE0_SDA_2": 16, + "SERIAL0_RX_0": 12, + "SERIAL0_RX_1": 13, + "SERIAL0_TX_0": 11, + "SERIAL0_TX_1": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX_0": 2, + "SERIAL1_RX_1": 0, + "SERIAL1_TX_0": 3, + "SERIAL1_TX_1": 1, + "SERIAL2_CTS": 19, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CS0": 15, + "CTS1": 4, + "CTS2": 19, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA07": 7, + "PA7": 7, + "PA11": 11, + "PA12": 12, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PA19": 19, + "PWM5": 17, + "PWM6": 18, + "RX2": 15, + "SDA0": 16, + "TX2": 16, + "D0": 7, + "D1": 11, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 12, + "D6": 16, + "D7": 17, + "D8": 18, + "D9": 19, + "D10": 13, + "D11": 14, + "D12": 15, + "D13": 0, + "D14": 1, + }, "generic-rtl8710bn-2mb-468k": { "SPI0_CS": 19, "SPI0_MISO": 22, @@ -1178,6 +1251,104 @@ RTL87XX_BOARD_PINS = { "A0": 19, "A1": 41, }, + "generic-rtl8720cf-2mb-896k": { + "SPI0_CS_0": 2, + "SPI0_CS_1": 7, + "SPI0_CS_2": 15, + "SPI0_MISO_0": 10, + "SPI0_MISO_1": 20, + "SPI0_MOSI_0": 4, + "SPI0_MOSI_1": 9, + "SPI0_MOSI_2": 19, + "SPI0_SCK_0": 3, + "SPI0_SCK_1": 8, + "SPI0_SCK_2": 16, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 11, + "WIRE0_SCL_2": 15, + "WIRE0_SCL_3": 19, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 12, + "WIRE0_SDA_2": 16, + "WIRE0_SDA_3": 20, + "SERIAL0_CTS": 10, + "SERIAL0_RTS": 9, + "SERIAL0_RX_0": 12, + "SERIAL0_RX_1": 13, + "SERIAL0_TX_0": 11, + "SERIAL0_TX_1": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX_0": 1, + "SERIAL1_TX_1": 3, + "SERIAL2_CTS": 19, + "SERIAL2_RTS": 20, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CS0": 15, + "CTS0": 10, + "CTS1": 4, + "CTS2": 19, + "MOSI0": 19, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PA19": 19, + "PA20": 20, + "PA23": 23, + "PWM0": 20, + "PWM5": 17, + "PWM6": 18, + "PWM7": 23, + "RTS0": 9, + "RTS2": 20, + "RX2": 15, + "SCK0": 16, + "TX2": 16, + "D0": 0, + "D1": 1, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 7, + "D6": 8, + "D7": 9, + "D8": 10, + "D9": 11, + "D10": 12, + "D11": 13, + "D12": 14, + "D13": 15, + "D14": 16, + "D15": 17, + "D16": 18, + "D17": 19, + "D18": 20, + "D19": 23, + }, "generic-rtl8720cf-2mb-992k": { "SPI0_CS_0": 2, "SPI0_CS_1": 7, From 463363a08d88aeeefcb43ca44895cc294a40a93d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 09:08:46 -1000 Subject: [PATCH 0387/2030] [web_server] Add name_id to SSE for entity ID format migration (#13535) --- esphome/components/web_server/web_server.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e538a35e8c..a19c1c9b17 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -531,7 +531,19 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J memcpy(p, name.c_str(), name_len); p[name_len] = '\0'; - root[ESPHOME_F("id")] = id_buf; + // name_id: new format {prefix}/{device?}/{name} - frontend should prefer this + // Remove in 2026.8.0 when id switches to new format permanently + root[ESPHOME_F("name_id")] = id_buf; + + // id: old format {prefix}-{object_id} for backward compatibility + // Will switch to new format in 2026.8.0 + char legacy_buf[ESPHOME_DOMAIN_MAX_LEN + 1 + OBJECT_ID_MAX_LEN]; + char *lp = legacy_buf; + memcpy(lp, prefix, prefix_len); + lp += prefix_len; + *lp++ = '-'; + obj->write_object_id_to(lp, sizeof(legacy_buf) - (lp - legacy_buf)); + root[ESPHOME_F("id")] = legacy_buf; if (start_config == DETAIL_ALL) { root[ESPHOME_F("domain")] = prefix; From f93382445e8816f0c90c6a13545c87e85effcd29 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 28 Jan 2026 08:21:26 +1300 Subject: [PATCH 0388/2030] Update webserver local assets to 20260127-190637 (#13573) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/web_server/server_index_v2.h | 2595 ++- .../components/web_server/server_index_v3.h | 14600 ++++++++-------- 2 files changed, 8598 insertions(+), 8597 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 7c24ae28c6..cc37db6a6b 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,1307 +10,1306 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdc, 0x48, 0xb6, 0xd8, 0xb3, - 0xe7, 0x2b, 0x40, 0x34, 0x2f, 0x85, 0x1c, 0x66, 0xa1, 0x16, 0x92, 0x12, 0x85, 0x62, 0x56, 0x0d, 0x45, 0xa9, 0x47, - 0x3d, 0xad, 0x6d, 0x44, 0xa9, 0x7b, 0xa6, 0xd9, 0x1c, 0x12, 0x04, 0xb2, 0x0a, 0xd9, 0x42, 0x01, 0xd5, 0x89, 0x2c, - 0x2e, 0x5d, 0x85, 0x1b, 0xfe, 0x00, 0x47, 0x38, 0xc2, 0x4f, 0x7e, 0x71, 0xf8, 0x3e, 0xf8, 0x23, 0xfc, 0x7c, 0x3f, - 0xc5, 0x3f, 0x60, 0x7f, 0x82, 0xe3, 0xe4, 0x02, 0x24, 0x6a, 0xa1, 0xa8, 0x9e, 0x9e, 0xeb, 0xfb, 0xe0, 0xe8, 0x68, - 0xaa, 0x90, 0xc8, 0xe5, 0xe4, 0xc9, 0x93, 0x67, 0xcf, 0xc4, 0xd1, 0x56, 0x9c, 0x47, 0xe2, 0x6e, 0x4a, 0x9d, 0x44, - 0x4c, 0xd2, 0xc1, 0x91, 0xfe, 0x4b, 0xc3, 0x78, 0x70, 0x94, 0xb2, 0xec, 0x93, 0xc3, 0x69, 0x4a, 0x58, 0x94, 0x67, - 0x4e, 0xc2, 0xe9, 0x88, 0xc4, 0xa1, 0x08, 0x03, 0x36, 0x09, 0xc7, 0xd4, 0x69, 0x0f, 0x8e, 0x26, 0x54, 0x84, 0x4e, - 0x94, 0x84, 0xbc, 0xa0, 0x82, 0x7c, 0xfc, 0xf0, 0x75, 0xeb, 0x70, 0x70, 0x54, 0x44, 0x9c, 0x4d, 0x85, 0x03, 0x5d, - 0x92, 0x49, 0x1e, 0xcf, 0x52, 0x3a, 0x68, 0xb7, 0x6f, 0x6e, 0x6e, 0xfc, 0x9f, 0x8a, 0xdf, 0x45, 0x79, 0x56, 0x08, - 0xe7, 0x39, 0xb9, 0x61, 0x59, 0x9c, 0xdf, 0x60, 0x2e, 0xc8, 0x73, 0xff, 0x34, 0x09, 0xe3, 0xfc, 0xe6, 0x7d, 0x9e, - 0x8b, 0x9d, 0x1d, 0x4f, 0x3d, 0xde, 0x9d, 0x9c, 0x9e, 0x12, 0x42, 0xae, 0x73, 0x16, 0x3b, 0x9d, 0xc5, 0xa2, 0x2e, - 0xf4, 0xb3, 0x50, 0xb0, 0x6b, 0xaa, 0x9a, 0xa0, 0x9d, 0x1d, 0x37, 0x8c, 0xf3, 0xa9, 0xa0, 0xf1, 0xa9, 0xb8, 0x4b, - 0xe9, 0x69, 0x42, 0xa9, 0x28, 0x5c, 0x96, 0x39, 0xcf, 0xf3, 0x68, 0x36, 0xa1, 0x99, 0xf0, 0xa7, 0x3c, 0x17, 0x39, - 0x40, 0xb2, 0xb3, 0xe3, 0x72, 0x3a, 0x4d, 0xc3, 0x88, 0xc2, 0xfb, 0x93, 0xd3, 0xd3, 0xba, 0x45, 0x5d, 0x09, 0x67, - 0x82, 0x9c, 0xde, 0x4d, 0xae, 0xf2, 0xd4, 0x43, 0x38, 0x11, 0x24, 0xa3, 0x37, 0xce, 0xf7, 0x34, 0xfc, 0xf4, 0x3a, - 0x9c, 0xf6, 0xa3, 0x34, 0x2c, 0x0a, 0xe7, 0x58, 0xcc, 0xe5, 0x14, 0xf8, 0x2c, 0x12, 0x39, 0xf7, 0x04, 0xa6, 0x98, - 0xa1, 0x39, 0x1b, 0x79, 0x22, 0x61, 0x85, 0x7f, 0xb1, 0x1d, 0x15, 0xc5, 0x7b, 0x5a, 0xcc, 0x52, 0xb1, 0x4d, 0xb6, - 0x3a, 0x98, 0x6d, 0x11, 0x92, 0x09, 0x24, 0x12, 0x9e, 0xdf, 0x38, 0x2f, 0x38, 0xcf, 0xb9, 0xe7, 0x9e, 0x9c, 0x9e, - 0xaa, 0x1a, 0x0e, 0x2b, 0x9c, 0x2c, 0x17, 0x4e, 0xd5, 0x5f, 0x78, 0x95, 0x52, 0xdf, 0xf9, 0x58, 0x50, 0xe7, 0x72, - 0x96, 0x15, 0xe1, 0x88, 0x9e, 0x9c, 0x9e, 0x5e, 0x3a, 0x39, 0x77, 0x2e, 0xa3, 0xa2, 0xb8, 0x74, 0x58, 0x56, 0x08, - 0x1a, 0xc6, 0xbe, 0x8b, 0xfa, 0x72, 0xb0, 0xa8, 0x28, 0x3e, 0xd0, 0x5b, 0x41, 0x04, 0x96, 0x8f, 0x82, 0xd0, 0x72, - 0x4c, 0x85, 0x53, 0x54, 0xf3, 0xf2, 0xd0, 0x3c, 0xa5, 0xc2, 0x11, 0x44, 0xbe, 0xcf, 0xfb, 0x0a, 0xf7, 0x54, 0x3d, - 0x8a, 0x3e, 0x1b, 0x79, 0x5c, 0xec, 0xec, 0x88, 0x0a, 0xcf, 0x48, 0x4d, 0xcd, 0x61, 0x84, 0x6e, 0x99, 0xb2, 0x9d, - 0x1d, 0xea, 0xa7, 0x34, 0x1b, 0x8b, 0x84, 0x10, 0xd2, 0xed, 0xb3, 0x9d, 0x1d, 0x4f, 0x90, 0x44, 0xf8, 0x63, 0x2a, - 0x3c, 0x8a, 0x10, 0xae, 0x5b, 0xef, 0xec, 0x78, 0x0a, 0x09, 0x39, 0x51, 0x88, 0x6b, 0xe0, 0x18, 0xf9, 0x1a, 0xfb, - 0xa7, 0x77, 0x59, 0xe4, 0xd9, 0xf0, 0x23, 0xcc, 0x76, 0x76, 0x12, 0xe1, 0x17, 0xd0, 0x23, 0x16, 0x08, 0x95, 0x9c, - 0x8a, 0x19, 0xcf, 0x1c, 0x51, 0x8a, 0xfc, 0x54, 0x70, 0x96, 0x8d, 0x3d, 0x34, 0x37, 0x65, 0x56, 0xc3, 0xb2, 0x54, - 0xe0, 0xbe, 0x17, 0x24, 0x23, 0x03, 0x18, 0xf1, 0x58, 0x78, 0xb0, 0x8a, 0xf9, 0xc8, 0xc9, 0x08, 0x71, 0x0b, 0xd9, - 0xd6, 0x1d, 0x66, 0x41, 0xb6, 0xeb, 0xba, 0x58, 0x41, 0x89, 0x33, 0x81, 0xf0, 0x27, 0xe2, 0x65, 0xd8, 0xf7, 0x7d, - 0x81, 0xc8, 0x60, 0x6e, 0xb0, 0x92, 0x59, 0xf3, 0x1c, 0x66, 0x67, 0x9d, 0xf3, 0x40, 0xf8, 0x9c, 0xc6, 0xb3, 0x88, - 0x7a, 0x1e, 0xc3, 0x1c, 0xe7, 0x88, 0x0c, 0xd8, 0xae, 0x57, 0x90, 0x01, 0x2c, 0xf7, 0xd2, 0x5a, 0x13, 0xb2, 0xd5, - 0x41, 0x1a, 0xc6, 0x0a, 0x40, 0xc0, 0xb0, 0x86, 0xa7, 0x20, 0xc4, 0xcd, 0x66, 0x93, 0x2b, 0xca, 0xdd, 0xaa, 0x5a, - 0xbf, 0x41, 0x16, 0xb3, 0x82, 0x3a, 0x51, 0x51, 0x38, 0xa3, 0x59, 0x16, 0x09, 0x96, 0x67, 0x8e, 0xbb, 0x5b, 0xec, - 0xba, 0x8a, 0x1c, 0x2a, 0x6a, 0x70, 0x51, 0x89, 0x3c, 0x8e, 0x76, 0xb3, 0xb3, 0x7c, 0xb7, 0x7b, 0x8e, 0x01, 0x4a, - 0xd4, 0xd7, 0xfd, 0x69, 0x04, 0x50, 0x9c, 0xc1, 0x1c, 0x4b, 0xfc, 0x4c, 0xc0, 0x2c, 0xe5, 0x14, 0xb9, 0x18, 0x66, - 0xfe, 0xea, 0x46, 0x21, 0xc2, 0x9f, 0x84, 0x53, 0x8f, 0x92, 0x01, 0x95, 0xc4, 0x15, 0x66, 0x11, 0xc0, 0xda, 0x58, - 0xb7, 0x21, 0x0d, 0xa8, 0x5f, 0x93, 0x14, 0x0a, 0x84, 0x3f, 0xca, 0xf9, 0x8b, 0x30, 0x4a, 0xa0, 0x5d, 0x45, 0x30, - 0xb1, 0xd9, 0x6f, 0x11, 0xa7, 0xa1, 0xa0, 0x2f, 0x52, 0x0a, 0x4f, 0x9e, 0x2b, 0x5b, 0xba, 0x08, 0x73, 0xf2, 0xdc, - 0x4f, 0x99, 0x78, 0x93, 0x67, 0x11, 0xed, 0x73, 0x8b, 0xba, 0x18, 0xac, 0xfb, 0xb1, 0x10, 0x9c, 0x5d, 0xcd, 0x04, - 0xf5, 0xdc, 0x0c, 0x6a, 0xb8, 0x98, 0x23, 0xcc, 0x7c, 0x41, 0x6f, 0xc5, 0x49, 0x9e, 0x09, 0x9a, 0x09, 0x42, 0x0d, - 0x52, 0x71, 0xe6, 0x87, 0xd3, 0x29, 0xcd, 0xe2, 0x93, 0x84, 0xa5, 0xb1, 0xc7, 0x50, 0x89, 0x4a, 0x1c, 0x09, 0x02, - 0x73, 0x24, 0x83, 0x2c, 0x80, 0x3f, 0x9b, 0x67, 0xe3, 0x09, 0x32, 0x90, 0x9b, 0x82, 0x12, 0xd7, 0xed, 0x8f, 0x72, - 0xee, 0xe9, 0x19, 0x38, 0xf9, 0xc8, 0x11, 0x30, 0xc6, 0xfb, 0x59, 0x4a, 0x0b, 0x44, 0x77, 0x09, 0xab, 0x96, 0x51, - 0x23, 0xf8, 0x3d, 0x50, 0x7c, 0x89, 0xbc, 0x0c, 0x05, 0x59, 0xff, 0x3a, 0xe4, 0xce, 0x0f, 0x7a, 0x47, 0xfd, 0x64, - 0xb8, 0x59, 0x2c, 0xc8, 0x4f, 0xbe, 0xe0, 0xb3, 0x42, 0xd0, 0xf8, 0xc3, 0xdd, 0x94, 0x16, 0xf8, 0xa5, 0x20, 0xb1, - 0x18, 0xc6, 0xc2, 0xa7, 0x93, 0xa9, 0xb8, 0x3b, 0x95, 0x8c, 0x31, 0x70, 0x5d, 0x3c, 0x83, 0x9a, 0x9c, 0x86, 0x11, - 0x30, 0x33, 0x8d, 0xad, 0x77, 0x79, 0x7a, 0x37, 0x62, 0x69, 0x7a, 0x3a, 0x9b, 0x4e, 0x73, 0x2e, 0xb0, 0x10, 0x64, - 0x2e, 0xf2, 0x1a, 0x37, 0xb0, 0x98, 0xf3, 0xe2, 0x86, 0x89, 0x28, 0xf1, 0x04, 0x9a, 0x47, 0x61, 0x41, 0x9d, 0x67, - 0x79, 0x9e, 0xd2, 0x10, 0x66, 0x9d, 0x0d, 0x5f, 0x8a, 0x20, 0x9b, 0xa5, 0x69, 0xff, 0x8a, 0xd3, 0xf0, 0x53, 0x5f, - 0xbe, 0x7e, 0x7b, 0xf5, 0x13, 0x8d, 0x44, 0x20, 0x7f, 0x1f, 0x73, 0x1e, 0xde, 0x41, 0x45, 0x42, 0xa0, 0xda, 0x30, - 0x0b, 0xfe, 0x74, 0xfa, 0xf6, 0x8d, 0xaf, 0x76, 0x09, 0x1b, 0xdd, 0x79, 0x59, 0xb5, 0xf3, 0xb2, 0x12, 0x8f, 0x78, - 0x3e, 0x59, 0x1a, 0x5a, 0xa1, 0x2d, 0xeb, 0x6f, 0x00, 0x81, 0x92, 0x6c, 0x4b, 0x75, 0x6d, 0x43, 0xf0, 0x46, 0x12, - 0x3d, 0xbc, 0x24, 0x66, 0xdc, 0x59, 0x9a, 0x06, 0xaa, 0xd8, 0xcb, 0xd0, 0xfd, 0xd0, 0x0a, 0x7e, 0x37, 0xa7, 0x44, - 0xc2, 0x39, 0x05, 0x11, 0x03, 0x30, 0x46, 0xa1, 0x88, 0x92, 0x39, 0x95, 0x9d, 0x95, 0x06, 0x62, 0x5a, 0x96, 0xf8, - 0x45, 0x45, 0xf0, 0x02, 0x00, 0x91, 0x9c, 0x8a, 0x88, 0xc5, 0x02, 0x26, 0x8c, 0xf0, 0x9f, 0xc8, 0x3c, 0x34, 0xf3, - 0x09, 0xb6, 0x3a, 0x18, 0x36, 0x66, 0xa0, 0xd8, 0x0b, 0x8e, 0xf2, 0xec, 0x9a, 0x72, 0x41, 0x79, 0x20, 0x04, 0xe6, - 0x74, 0x94, 0x02, 0x18, 0x5b, 0x5d, 0x9c, 0x84, 0xc5, 0x49, 0x12, 0x66, 0x63, 0x1a, 0x07, 0x2f, 0x44, 0x89, 0xa9, - 0x20, 0xee, 0x88, 0x65, 0x61, 0xca, 0x7e, 0xa1, 0xb1, 0xab, 0x05, 0xc2, 0x0b, 0x87, 0xde, 0x0a, 0x9a, 0xc5, 0x85, - 0xf3, 0xf2, 0xc3, 0xeb, 0x57, 0x7a, 0x29, 0x1b, 0x32, 0x02, 0xcd, 0x8b, 0xd9, 0x94, 0x72, 0x0f, 0x61, 0x2d, 0x23, - 0x5e, 0x30, 0xc9, 0x1f, 0x5f, 0x87, 0x53, 0x55, 0xc2, 0x8a, 0x8f, 0xd3, 0x38, 0x14, 0xf4, 0x1d, 0xcd, 0x62, 0x96, - 0x8d, 0xc9, 0x56, 0x57, 0x95, 0x27, 0xa1, 0x7e, 0x11, 0x57, 0x45, 0x17, 0xdb, 0x2f, 0x52, 0x39, 0xf3, 0xea, 0x71, - 0xe6, 0xa1, 0xb2, 0x10, 0xa1, 0x60, 0x91, 0x13, 0xc6, 0xf1, 0x37, 0x19, 0x13, 0x4c, 0x02, 0xc8, 0x61, 0x81, 0x80, - 0x4a, 0xa9, 0x92, 0x16, 0x06, 0x70, 0x0f, 0x61, 0xcf, 0xd3, 0x32, 0x20, 0x41, 0x7a, 0xc5, 0x76, 0x76, 0x6a, 0x8e, - 0x3f, 0xa4, 0x81, 0x7a, 0x49, 0xce, 0xce, 0x91, 0x3f, 0x9d, 0x15, 0xb0, 0xd4, 0x66, 0x08, 0x10, 0x30, 0xf9, 0x55, - 0x41, 0xf9, 0x35, 0x8d, 0x2b, 0xf2, 0x28, 0x3c, 0x34, 0x5f, 0x1a, 0x43, 0xef, 0x0c, 0x41, 0xce, 0xce, 0xfb, 0x36, - 0xeb, 0xa6, 0x9a, 0xd4, 0x79, 0x3e, 0xa5, 0x5c, 0x30, 0x5a, 0x54, 0xdc, 0xc4, 0x03, 0x41, 0x5a, 0x71, 0x14, 0x4e, - 0xcc, 0xfc, 0xa6, 0x1e, 0xc3, 0x14, 0x35, 0x78, 0x86, 0x91, 0xb5, 0x2f, 0xae, 0xa5, 0xd0, 0xe0, 0x98, 0x21, 0x2c, - 0x14, 0xa4, 0x1c, 0xa1, 0x12, 0x61, 0x61, 0xc0, 0x55, 0xdc, 0x48, 0x8f, 0x76, 0x07, 0xd2, 0x9a, 0xfc, 0x49, 0x4a, - 0x6b, 0xe0, 0x69, 0xa1, 0xa0, 0x3b, 0x3b, 0x1e, 0xf5, 0x2b, 0xb2, 0x20, 0x5b, 0x5d, 0xbd, 0x46, 0x16, 0xb2, 0x36, - 0x80, 0x0d, 0x03, 0x0b, 0x4c, 0x11, 0xde, 0xa2, 0x7e, 0x96, 0x1f, 0x47, 0x11, 0x2d, 0x8a, 0x9c, 0xef, 0xec, 0x6c, - 0xc9, 0xfa, 0x95, 0x42, 0x01, 0x6b, 0xf8, 0xf6, 0x26, 0xab, 0x21, 0x40, 0xb5, 0x90, 0xd5, 0xa2, 0x41, 0x80, 0xa8, - 0x92, 0x3a, 0x87, 0x3b, 0x34, 0xba, 0x47, 0xe0, 0x5e, 0x5c, 0xb8, 0xbb, 0x02, 0x6b, 0x34, 0x8c, 0xa9, 0x19, 0xfa, - 0xee, 0x39, 0x55, 0xda, 0x95, 0xd4, 0x3d, 0x56, 0x30, 0xa3, 0x76, 0x90, 0x1f, 0xd3, 0x11, 0xcb, 0xac, 0x69, 0x37, - 0x40, 0xc2, 0x02, 0x73, 0x54, 0x5a, 0x0b, 0xba, 0xb6, 0x6b, 0xa9, 0xd6, 0xa8, 0x95, 0x9b, 0x8f, 0xa5, 0x2a, 0x61, - 0x2d, 0xe3, 0x19, 0x3d, 0x2f, 0xb1, 0x44, 0xbd, 0x99, 0x4d, 0x2e, 0x01, 0x3d, 0x13, 0xe7, 0x7d, 0xfd, 0x9e, 0x70, - 0x85, 0x39, 0x4e, 0x7f, 0x9e, 0xd1, 0x42, 0x28, 0x3a, 0xf6, 0x04, 0xce, 0x31, 0x03, 0x7e, 0x9d, 0x67, 0x23, 0x36, - 0x9e, 0x71, 0xd0, 0x78, 0x60, 0x33, 0xd2, 0x6c, 0x36, 0xa1, 0xe6, 0x69, 0x1d, 0x6c, 0x6f, 0xa7, 0x20, 0x13, 0x0b, - 0xa0, 0xe9, 0xfb, 0xc9, 0x09, 0x60, 0x15, 0x68, 0xb1, 0xf8, 0x93, 0xe9, 0xa4, 0x5e, 0xca, 0x4a, 0x4b, 0x5b, 0x5a, - 0x13, 0x2a, 0x90, 0x96, 0xc9, 0x5b, 0x5d, 0x0d, 0xbe, 0x38, 0x27, 0x5b, 0x9d, 0x8a, 0x86, 0x35, 0x56, 0x15, 0x38, - 0x0a, 0x89, 0x6f, 0x55, 0x57, 0x48, 0x8a, 0xf8, 0x06, 0xb9, 0xf8, 0xc9, 0x0a, 0xa5, 0x26, 0xe4, 0x0c, 0x94, 0x0d, - 0x3f, 0x39, 0xdf, 0x44, 0x4e, 0x86, 0x1f, 0x78, 0x62, 0xf5, 0x5d, 0xcd, 0x36, 0xae, 0x9b, 0x6c, 0x63, 0x69, 0x1a, - 0xee, 0xb4, 0x6a, 0xe2, 0x56, 0x54, 0xa6, 0x37, 0x7a, 0xfd, 0x0a, 0x33, 0x09, 0x4c, 0x3d, 0x25, 0xab, 0x8b, 0x37, - 0xe1, 0x84, 0x16, 0x1e, 0x45, 0x78, 0x53, 0x05, 0x45, 0x9e, 0x50, 0xe5, 0xdc, 0x92, 0x9d, 0x1c, 0x64, 0x27, 0x43, - 0x4a, 0x35, 0x6b, 0x6e, 0x38, 0x8e, 0xe9, 0x19, 0x3f, 0xaf, 0x35, 0x3a, 0x6b, 0xf2, 0x52, 0x28, 0x17, 0xa4, 0xb1, - 0xdd, 0x54, 0x99, 0x42, 0x9a, 0xd4, 0x1c, 0x0a, 0x84, 0xb7, 0x3a, 0xcb, 0x2b, 0x69, 0x6a, 0xd5, 0x73, 0x3c, 0x3b, - 0x87, 0x75, 0x90, 0x22, 0xc3, 0x67, 0x85, 0xfc, 0xb7, 0xb1, 0xd3, 0x00, 0x6d, 0xa7, 0x40, 0x18, 0xfe, 0x28, 0x0d, - 0x85, 0xd7, 0x6d, 0x77, 0x40, 0x1d, 0xbd, 0xa6, 0x20, 0x51, 0x10, 0x5a, 0x9d, 0x0a, 0xf5, 0x67, 0x59, 0x91, 0xb0, - 0x91, 0xf0, 0x22, 0x21, 0x59, 0x0a, 0x4d, 0x0b, 0xea, 0x88, 0x86, 0x52, 0x2c, 0xd9, 0x4d, 0x04, 0xc4, 0x56, 0x69, - 0x60, 0xd4, 0x40, 0x2a, 0xd9, 0x16, 0x70, 0x87, 0x5a, 0xa1, 0xae, 0xb9, 0x8c, 0xa9, 0xcd, 0x40, 0x69, 0xec, 0x0e, - 0x55, 0x8f, 0x81, 0x66, 0x06, 0xcc, 0xd2, 0x5b, 0x59, 0x60, 0x73, 0x08, 0x5d, 0x28, 0x7c, 0x91, 0xbf, 0xca, 0x6f, - 0x28, 0x3f, 0x09, 0x01, 0xf8, 0x40, 0x35, 0x2f, 0x95, 0x20, 0x90, 0xfc, 0x5e, 0xf4, 0x0d, 0xbd, 0x5c, 0xc8, 0x89, - 0xbf, 0xe3, 0xf9, 0x84, 0x15, 0x14, 0xd4, 0x35, 0x85, 0xff, 0x0c, 0xf6, 0x99, 0xdc, 0x90, 0x20, 0x6c, 0x68, 0x45, - 0x5f, 0xc7, 0xaf, 0x9a, 0xf4, 0x75, 0xb1, 0xfd, 0x62, 0x6c, 0x18, 0x60, 0x73, 0x1b, 0x23, 0xec, 0x69, 0xa3, 0xc2, - 0x92, 0x73, 0x7e, 0x82, 0xb4, 0x88, 0x5f, 0x2c, 0x84, 0x65, 0xbb, 0x35, 0x14, 0x46, 0xaa, 0xb6, 0x0d, 0x2a, 0xc3, - 0x38, 0x06, 0xd5, 0x8e, 0xe7, 0x69, 0x6a, 0x89, 0x2a, 0xcc, 0xfa, 0x95, 0x70, 0xba, 0xd8, 0x7e, 0x71, 0x7a, 0x9f, - 0x7c, 0x82, 0xf7, 0xb6, 0x88, 0x32, 0x80, 0x66, 0x31, 0xe5, 0x60, 0x4b, 0x5a, 0xab, 0xa5, 0xa5, 0xec, 0x49, 0x9e, - 0x65, 0x34, 0x12, 0x34, 0x06, 0x53, 0x85, 0x11, 0xe1, 0x27, 0x79, 0x21, 0xaa, 0xc2, 0x1a, 0x7a, 0x66, 0x41, 0xcf, - 0xfc, 0x28, 0x4c, 0x53, 0x4f, 0x99, 0x25, 0x93, 0xfc, 0x9a, 0xae, 0x81, 0xba, 0xdf, 0x00, 0xb9, 0xea, 0x86, 0x5a, - 0xdd, 0x50, 0xbf, 0x98, 0xa6, 0x2c, 0xa2, 0x95, 0xe8, 0x3a, 0xf5, 0x59, 0x16, 0xd3, 0x5b, 0xe0, 0x23, 0x68, 0x30, - 0x18, 0x74, 0x70, 0x17, 0x95, 0x0a, 0xe1, 0xf3, 0x15, 0xc4, 0xde, 0x23, 0x34, 0x81, 0xc8, 0xc8, 0x60, 0xbe, 0x96, - 0xad, 0x21, 0x4b, 0x52, 0x32, 0x63, 0x5e, 0x29, 0xee, 0x8c, 0x70, 0x4c, 0x53, 0x2a, 0xa8, 0xe1, 0xe6, 0xa0, 0x44, - 0xab, 0xad, 0xfb, 0xbe, 0xc2, 0x5f, 0x45, 0x4e, 0x66, 0x97, 0x99, 0x35, 0x2f, 0x2a, 0x73, 0xbd, 0x5e, 0x9e, 0x1a, - 0xdb, 0x43, 0xa1, 0x96, 0x27, 0x14, 0x22, 0x8c, 0x12, 0x65, 0xa7, 0x7b, 0x2b, 0x53, 0xaa, 0xfb, 0xd0, 0x9c, 0xbd, - 0xda, 0x44, 0xcf, 0x0c, 0x98, 0xeb, 0x50, 0x70, 0xaa, 0x99, 0x02, 0x05, 0xd3, 0x4f, 0x2d, 0xdb, 0x49, 0x98, 0xa6, - 0x57, 0x61, 0xf4, 0xa9, 0x49, 0xfd, 0x35, 0x19, 0x90, 0x65, 0x6e, 0x6c, 0xbd, 0xb2, 0x58, 0x96, 0x3d, 0x6f, 0xc3, - 0xa5, 0x1b, 0x1b, 0xc5, 0xdb, 0xea, 0xd4, 0x64, 0xdf, 0x5c, 0xe8, 0x8d, 0xd4, 0x2e, 0x21, 0x62, 0x7a, 0x66, 0x1e, - 0x70, 0x81, 0xcf, 0x52, 0x9c, 0xe1, 0x07, 0x9a, 0xee, 0xc0, 0xe0, 0x28, 0x97, 0x00, 0x11, 0x68, 0x5e, 0xc6, 0xac, - 0xd8, 0x8c, 0x81, 0xdf, 0x04, 0xca, 0xe7, 0xd6, 0x08, 0x0f, 0x05, 0xb4, 0xe2, 0x71, 0x5a, 0x6b, 0xae, 0x20, 0xd3, - 0xfa, 0x84, 0x61, 0x34, 0xdf, 0x82, 0xee, 0x22, 0xe9, 0xfd, 0xad, 0x7a, 0x05, 0x5a, 0x19, 0x40, 0xc1, 0xfb, 0xb6, - 0x3a, 0xd1, 0xa0, 0x00, 0xcd, 0x53, 0x99, 0x14, 0xb9, 0x79, 0xc3, 0x82, 0xd4, 0x1a, 0xbb, 0x32, 0xc2, 0x35, 0xcb, - 0x2d, 0x88, 0xe7, 0x79, 0x1c, 0x8c, 0x38, 0xa3, 0xdb, 0xd7, 0x93, 0xe0, 0x2b, 0x93, 0xe0, 0xbe, 0x65, 0x68, 0xa1, - 0x9a, 0x96, 0xad, 0xe6, 0x81, 0x10, 0xc8, 0xae, 0x05, 0xfa, 0xaa, 0x0f, 0x0c, 0x1a, 0x55, 0xfc, 0x36, 0x25, 0x02, - 0x17, 0xda, 0xca, 0xd1, 0xa4, 0x06, 0x1c, 0xa3, 0x6e, 0x92, 0x23, 0xb5, 0x37, 0x1a, 0x26, 0x6f, 0x8e, 0x2d, 0x11, - 0x9f, 0x6a, 0xb3, 0x46, 0x23, 0x89, 0x22, 0xbd, 0x38, 0x0d, 0xad, 0xd8, 0x42, 0x0b, 0xce, 0x09, 0x57, 0x9a, 0xb0, - 0x52, 0x7c, 0x96, 0x91, 0x53, 0xf5, 0xbb, 0x45, 0x48, 0x5e, 0xe3, 0x86, 0xfb, 0x6b, 0x74, 0xab, 0x1c, 0xe1, 0xc8, - 0x28, 0xa5, 0x45, 0x3d, 0x71, 0x42, 0x5c, 0xe3, 0x93, 0x70, 0x87, 0xf3, 0x86, 0x5d, 0x18, 0x58, 0xd5, 0xca, 0x00, - 0x78, 0x6a, 0xb1, 0x0e, 0xdf, 0xeb, 0x88, 0xa6, 0xd1, 0x8f, 0x85, 0xf1, 0xa2, 0x81, 0x71, 0x0b, 0xb5, 0xb9, 0xe2, - 0x5d, 0xf9, 0x39, 0x89, 0x9a, 0x8d, 0x3d, 0x8a, 0x0b, 0xb5, 0x10, 0x2b, 0x58, 0x5c, 0x56, 0x3e, 0x25, 0x11, 0x82, - 0x19, 0xcb, 0x41, 0xbd, 0xb3, 0x25, 0x84, 0x07, 0xc0, 0xb3, 0xc5, 0x62, 0x85, 0xec, 0xd6, 0xea, 0xa0, 0xc8, 0xaf, - 0x2d, 0xc3, 0xc5, 0xe2, 0x85, 0x40, 0x9e, 0xd6, 0x7e, 0x31, 0x45, 0x43, 0xc3, 0x73, 0x8f, 0x5f, 0x41, 0x2d, 0xa9, - 0x8c, 0xd6, 0x25, 0x95, 0xd9, 0xd0, 0xa4, 0xda, 0xe6, 0x42, 0x09, 0x8b, 0x71, 0x9f, 0xac, 0xf0, 0x2f, 0x59, 0xa8, - 0x05, 0x75, 0x3d, 0xe5, 0x13, 0xdd, 0x35, 0x43, 0x08, 0x05, 0x5c, 0x5a, 0x32, 0x5b, 0xeb, 0x8c, 0xcb, 0x9d, 0x1d, - 0x6e, 0x75, 0x74, 0x51, 0x31, 0x8a, 0x9f, 0x3c, 0x10, 0xca, 0xc5, 0x5d, 0x26, 0xb5, 0x97, 0x9f, 0x8c, 0x18, 0x5a, - 0x31, 0x4d, 0x3b, 0x7d, 0xb0, 0xc9, 0xc3, 0x9b, 0x90, 0x09, 0xa7, 0xea, 0x45, 0xd9, 0xe4, 0x1e, 0x45, 0x73, 0xad, - 0x6c, 0xf8, 0x9c, 0x82, 0xfa, 0x08, 0x5c, 0xc1, 0x28, 0xd1, 0x8a, 0xf0, 0xa3, 0x84, 0x82, 0x3f, 0xd8, 0xe8, 0x11, - 0x95, 0x6d, 0xb8, 0xa5, 0xe5, 0x88, 0xee, 0x78, 0x3d, 0xec, 0xe5, 0x72, 0xf3, 0x86, 0x2d, 0x30, 0xa5, 0x7c, 0x94, - 0xf3, 0x89, 0x79, 0x57, 0x2e, 0x3d, 0x6b, 0xde, 0xc8, 0x46, 0xde, 0xda, 0xbe, 0xb5, 0x05, 0xd0, 0x5f, 0x32, 0xbc, - 0x6b, 0x93, 0xbd, 0x21, 0x4c, 0x2b, 0xf9, 0xab, 0xdc, 0x82, 0x86, 0x32, 0xb9, 0x6d, 0xe2, 0x6b, 0x9f, 0x6a, 0x5f, - 0xb9, 0x4d, 0xb6, 0xba, 0xfd, 0xca, 0xee, 0x33, 0xd4, 0xd0, 0x57, 0xee, 0x0d, 0x2d, 0x54, 0xf3, 0x59, 0x1a, 0x6b, - 0x60, 0x19, 0xc2, 0x54, 0xd3, 0xd1, 0x0d, 0x4b, 0xd3, 0xba, 0xf4, 0x4b, 0x38, 0x3b, 0xd7, 0x9c, 0x3d, 0x37, 0x9c, - 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd5, 0x5d, 0xdd, 0x3c, 0x5f, 0xd9, 0x9e, 0xb9, 0xe2, 0xe9, 0x5c, 0xda, 0xd2, 0x30, - 0xde, 0xcc, 0x40, 0x80, 0x2a, 0xdd, 0xeb, 0x93, 0xa7, 0x5d, 0x31, 0x60, 0x04, 0x2a, 0x4f, 0x26, 0xb5, 0xdd, 0x14, - 0x9f, 0x3c, 0x84, 0x79, 0x49, 0x2b, 0xca, 0x3e, 0x7e, 0x01, 0xbe, 0x3a, 0x6b, 0x3a, 0x20, 0xc6, 0x64, 0xf1, 0x17, - 0xa9, 0x51, 0x66, 0x76, 0x4c, 0xcf, 0x8e, 0x9b, 0xd9, 0x01, 0xaf, 0xaf, 0x67, 0x17, 0xdf, 0xcf, 0xed, 0xe5, 0xf4, - 0x58, 0x35, 0xbd, 0x7a, 0xbd, 0x17, 0x0b, 0x6f, 0xa9, 0x04, 0xdc, 0xf8, 0xda, 0x48, 0xe1, 0x55, 0xef, 0xc0, 0x03, - 0x6c, 0xcc, 0x40, 0x41, 0xa9, 0x26, 0x5d, 0x09, 0xb9, 0x57, 0x9f, 0x73, 0xf2, 0x48, 0x6f, 0xbd, 0x6a, 0x7f, 0x92, - 0x4f, 0xa6, 0xa0, 0x8f, 0x2d, 0x91, 0xf4, 0x98, 0xea, 0x01, 0xeb, 0xf7, 0xe5, 0x9a, 0xb2, 0x46, 0x1b, 0xb9, 0x1f, - 0x1b, 0xd4, 0x54, 0xd9, 0xcc, 0x5b, 0x9d, 0x72, 0x56, 0x15, 0x55, 0x8c, 0x63, 0x9d, 0x63, 0xe5, 0x64, 0xd9, 0x2d, - 0x63, 0x5e, 0xbc, 0xf5, 0x98, 0xe2, 0xc3, 0x0c, 0x78, 0x9d, 0xc5, 0x7e, 0x0c, 0xb9, 0xdb, 0xeb, 0x5f, 0xd6, 0xc8, - 0x99, 0x97, 0x4b, 0xe8, 0x9b, 0x97, 0xe5, 0x0b, 0x6d, 0x67, 0xe3, 0x17, 0x9b, 0x0d, 0xe2, 0xfa, 0x9d, 0xb6, 0x17, - 0xcf, 0xce, 0xf1, 0x8b, 0x55, 0xed, 0x91, 0xcc, 0x27, 0x79, 0x4c, 0x03, 0x37, 0x9f, 0xd2, 0xcc, 0x2d, 0xc1, 0xbb, - 0xaa, 0x17, 0x7f, 0x26, 0xbc, 0xf9, 0xfb, 0xa6, 0x9b, 0x35, 0x78, 0x51, 0x82, 0x0b, 0xec, 0x87, 0x55, 0x07, 0xec, - 0x77, 0x94, 0x17, 0x52, 0x17, 0xad, 0xd4, 0xda, 0x1f, 0x6a, 0xc1, 0xf4, 0x43, 0xb0, 0xb1, 0x7e, 0x6d, 0x85, 0xb8, - 0x5d, 0xff, 0xb1, 0xbf, 0xe7, 0x22, 0xe9, 0x1e, 0xfe, 0x56, 0xef, 0xf8, 0x9f, 0x8d, 0x7b, 0xf8, 0x94, 0xfc, 0xdc, - 0xf4, 0x0e, 0x4f, 0x05, 0x39, 0x1d, 0x9e, 0x1a, 0xa3, 0x39, 0x4f, 0x59, 0x74, 0xe7, 0xb9, 0x29, 0x13, 0x2d, 0x08, - 0xc1, 0xb9, 0x78, 0xae, 0x5e, 0x80, 0x5f, 0x51, 0xba, 0xb5, 0x4b, 0x63, 0xee, 0x61, 0x26, 0x88, 0xbb, 0x9d, 0x32, - 0xb1, 0xed, 0xe2, 0x3b, 0x72, 0x09, 0x3f, 0xb6, 0xe7, 0xde, 0xeb, 0x50, 0x24, 0x3e, 0x0f, 0xb3, 0x38, 0x9f, 0x78, - 0x68, 0xd7, 0x75, 0x91, 0x5f, 0x48, 0x93, 0xe3, 0x29, 0x2a, 0xb7, 0x2f, 0xf1, 0xa9, 0x20, 0xee, 0xd0, 0xdd, 0xbd, - 0xc3, 0xaf, 0x05, 0xb9, 0x3c, 0xda, 0x9e, 0x9f, 0x8a, 0x72, 0x70, 0x89, 0x8f, 0x2b, 0xcf, 0x3d, 0x7e, 0x43, 0x3c, - 0x44, 0x06, 0xc7, 0x1a, 0x9a, 0x93, 0x7c, 0xa2, 0x3c, 0xf8, 0x2e, 0xc2, 0xef, 0x65, 0x7c, 0xa5, 0x66, 0x37, 0x3a, - 0xc4, 0xb2, 0x45, 0xdc, 0x5c, 0x7a, 0x09, 0xdc, 0x9d, 0x1d, 0xab, 0xac, 0x52, 0x16, 0xf0, 0x89, 0x20, 0x0d, 0x9b, - 0x1c, 0xbf, 0x92, 0x91, 0x9a, 0x13, 0xe1, 0x65, 0xc8, 0x74, 0xe3, 0x19, 0x77, 0xb4, 0xde, 0x9b, 0xd9, 0x99, 0x72, - 0x32, 0xf8, 0x4c, 0x50, 0x1e, 0x8a, 0x9c, 0x9f, 0x23, 0x5b, 0x01, 0xc1, 0x7f, 0x26, 0x97, 0x67, 0xce, 0x7f, 0xf8, - 0xdd, 0x8f, 0xa3, 0x1f, 0xf9, 0xf9, 0x25, 0xfe, 0x48, 0xda, 0x47, 0xde, 0x30, 0xf0, 0xb6, 0x5a, 0xad, 0xc5, 0x8f, - 0xed, 0xb3, 0xbf, 0x85, 0xad, 0x5f, 0x8e, 0x5b, 0x3f, 0x9c, 0xa3, 0x85, 0xf7, 0x63, 0x7b, 0x78, 0xa6, 0x9f, 0xce, - 0xfe, 0x36, 0xf8, 0xb1, 0x38, 0xff, 0xbd, 0x2a, 0xdc, 0x46, 0xa8, 0x3d, 0xc6, 0x63, 0x41, 0xda, 0xad, 0xd6, 0xa0, - 0x3d, 0xc6, 0x13, 0x41, 0xda, 0xf0, 0xef, 0x0d, 0x79, 0x4f, 0xc7, 0x2f, 0x6e, 0xa7, 0xde, 0xe5, 0x60, 0xb1, 0x3d, - 0xff, 0x73, 0x09, 0xbd, 0x9e, 0xfd, 0xed, 0xc7, 0x1f, 0x0b, 0xf7, 0xd1, 0x80, 0xb4, 0xcf, 0x77, 0x91, 0x07, 0xa5, - 0xbf, 0x27, 0xf2, 0xaf, 0x37, 0x0c, 0xce, 0xfe, 0xa6, 0xa1, 0x70, 0x1f, 0xfd, 0x78, 0x79, 0x34, 0x20, 0xe7, 0x0b, - 0xcf, 0x5d, 0x3c, 0x42, 0x0b, 0x84, 0x16, 0xdb, 0xe8, 0x12, 0xbb, 0x63, 0x17, 0xe1, 0x91, 0x20, 0xed, 0x47, 0xed, - 0x31, 0xbe, 0x10, 0xa4, 0xed, 0xb6, 0xc7, 0xf8, 0xad, 0x20, 0xed, 0xbf, 0x79, 0xc3, 0x40, 0xb9, 0xd9, 0x16, 0xd2, - 0xc3, 0xb1, 0x80, 0x20, 0x47, 0xc8, 0x69, 0xb8, 0x10, 0x4c, 0xa4, 0x14, 0x6d, 0xb7, 0x19, 0xfe, 0x24, 0xd1, 0xe4, - 0x09, 0xf0, 0xc3, 0x80, 0x79, 0xe7, 0xcd, 0x2f, 0x60, 0xb1, 0x81, 0x66, 0xb6, 0x83, 0x0c, 0x2b, 0x57, 0x40, 0x11, - 0x08, 0x7c, 0x1d, 0xa6, 0x33, 0x5a, 0x04, 0xb4, 0x44, 0x38, 0x25, 0x9f, 0x84, 0xd7, 0x45, 0xf8, 0x1b, 0x01, 0x3f, - 0x7a, 0x08, 0x9f, 0xe8, 0x40, 0x26, 0xec, 0x64, 0x45, 0x54, 0x59, 0xae, 0x54, 0x16, 0x17, 0xe1, 0xf1, 0x9a, 0x97, - 0x22, 0x01, 0x07, 0x03, 0xc2, 0xd7, 0x8d, 0xb0, 0x27, 0xbe, 0x25, 0x86, 0x24, 0x3e, 0x70, 0x4a, 0xbf, 0x0f, 0xd3, - 0x4f, 0x94, 0x7b, 0xc7, 0xb8, 0xdb, 0x7b, 0x8a, 0xa5, 0x1f, 0x7a, 0xab, 0x8b, 0xfa, 0x55, 0xcc, 0xea, 0x9d, 0x50, - 0xa1, 0x02, 0x90, 0xb2, 0x4d, 0x77, 0x0c, 0xac, 0xf8, 0x56, 0xb6, 0xe2, 0xb3, 0xe2, 0xe1, 0x8d, 0x8b, 0x9a, 0xf1, - 0x51, 0x96, 0x5d, 0x87, 0x29, 0x8b, 0x1d, 0x41, 0x27, 0xd3, 0x34, 0x14, 0xd4, 0xd1, 0xf3, 0x75, 0x42, 0xe8, 0xc8, - 0xad, 0x74, 0x86, 0xa9, 0x65, 0x73, 0x4e, 0x4d, 0xe0, 0x09, 0xf6, 0x8a, 0x07, 0x51, 0x2a, 0xad, 0x77, 0x3c, 0xaf, - 0x83, 0x60, 0xcb, 0x71, 0xbe, 0x56, 0x17, 0x7c, 0x61, 0xe7, 0x52, 0x3e, 0x83, 0x1e, 0x0d, 0x52, 0xb4, 0x37, 0x74, - 0x8f, 0x8a, 0xeb, 0xf1, 0xc0, 0x85, 0x18, 0x4d, 0x41, 0x3e, 0x4a, 0xd7, 0x10, 0x54, 0x88, 0x48, 0xa7, 0x1f, 0x1d, - 0xd1, 0x7e, 0xb4, 0xbb, 0x6b, 0xb4, 0xe8, 0x90, 0x64, 0x67, 0x91, 0x6a, 0x9e, 0xe0, 0x18, 0xcf, 0x48, 0xab, 0x8b, - 0xa7, 0xa4, 0x23, 0x9b, 0xf4, 0xa7, 0x47, 0xa1, 0x1e, 0x66, 0x67, 0xc7, 0x2b, 0xfc, 0x34, 0x2c, 0xc4, 0x37, 0x60, - 0xef, 0x93, 0x29, 0x8e, 0x49, 0xe1, 0xd3, 0x5b, 0x1a, 0x79, 0x21, 0xc2, 0xb1, 0xe6, 0x34, 0xa8, 0x8f, 0xa6, 0xc4, - 0xaa, 0x06, 0x66, 0x04, 0xf9, 0x38, 0x8c, 0xcf, 0xba, 0xe7, 0x84, 0x10, 0x77, 0xab, 0xd5, 0x72, 0x87, 0x05, 0x19, - 0x8b, 0x00, 0x4a, 0x2c, 0x65, 0x99, 0x4c, 0xa0, 0xa8, 0x67, 0x15, 0x79, 0x6f, 0x85, 0x2f, 0x68, 0x21, 0x3c, 0x28, - 0x06, 0x0f, 0x00, 0x37, 0x84, 0xed, 0x1e, 0xb5, 0xdd, 0x5d, 0x28, 0x95, 0xc4, 0x89, 0x70, 0x41, 0x6e, 0x50, 0x10, - 0x9f, 0xed, 0x9d, 0xdb, 0x02, 0x40, 0x16, 0xc2, 0xe0, 0x37, 0xc3, 0xf8, 0xac, 0x23, 0x07, 0x1f, 0xb8, 0x43, 0xaf, - 0x20, 0x5c, 0x69, 0x68, 0x43, 0x1e, 0x7c, 0x94, 0x53, 0x45, 0x81, 0x06, 0x4e, 0x8f, 0x3b, 0x23, 0xad, 0x5e, 0xe0, - 0xcd, 0xec, 0x49, 0xb4, 0x60, 0x30, 0x8d, 0x05, 0x9c, 0x10, 0xa8, 0x8f, 0x0b, 0x02, 0x23, 0xd6, 0xcd, 0x6e, 0x02, - 0xfd, 0xfc, 0xc8, 0x7d, 0x34, 0xbc, 0x10, 0xc1, 0x48, 0xa8, 0xe1, 0x2f, 0xc4, 0x62, 0x01, 0xff, 0x8e, 0xc4, 0xb0, - 0x20, 0x37, 0xb2, 0x68, 0xac, 0x8b, 0x26, 0x50, 0xf4, 0x31, 0x00, 0x50, 0x31, 0xaf, 0xb4, 0x2c, 0xb5, 0x26, 0x13, - 0x22, 0x61, 0xdf, 0xd9, 0xc9, 0xce, 0xa2, 0xdd, 0xee, 0x39, 0x38, 0xf9, 0xb9, 0x28, 0xbe, 0x67, 0x22, 0xf1, 0xdc, - 0xf6, 0xc0, 0x45, 0x43, 0xd7, 0x81, 0xa5, 0xed, 0xe7, 0xbb, 0x44, 0x61, 0x38, 0xdc, 0x7d, 0x2d, 0x82, 0xd9, 0x80, - 0x74, 0x86, 0x1e, 0x53, 0x2c, 0x3c, 0x41, 0x38, 0xd4, 0x8c, 0xb3, 0x83, 0x67, 0x68, 0x97, 0x89, 0x5d, 0xf3, 0x3c, - 0x43, 0xbb, 0x77, 0xbb, 0x13, 0x14, 0x84, 0xbb, 0x77, 0xbb, 0xde, 0x8c, 0x10, 0xd2, 0xea, 0x55, 0xcd, 0x8c, 0xf8, - 0x8b, 0x50, 0x30, 0x31, 0xfe, 0xce, 0x33, 0xb9, 0x1d, 0xf2, 0x5d, 0x2f, 0x3b, 0xa3, 0xe7, 0x8b, 0x85, 0x7b, 0x34, - 0x1c, 0xb8, 0x68, 0xd7, 0x33, 0x84, 0xd6, 0x36, 0x94, 0x86, 0x10, 0x66, 0xe7, 0xa5, 0x8e, 0x27, 0x3d, 0x6b, 0xc4, - 0x8e, 0xe6, 0xf5, 0x66, 0xb7, 0x78, 0x00, 0x2d, 0x2b, 0x43, 0x46, 0x29, 0xac, 0x53, 0x98, 0xa6, 0x21, 0xe6, 0x9c, - 0x74, 0x70, 0x41, 0x8c, 0xfb, 0x3a, 0x22, 0xa2, 0x26, 0xf8, 0x90, 0xd4, 0xd5, 0xf1, 0x59, 0x82, 0xe3, 0x73, 0xf2, - 0x5c, 0x19, 0x24, 0x7d, 0xe3, 0x1c, 0xa7, 0x29, 0x79, 0xb6, 0x14, 0xc5, 0x4d, 0x20, 0xc0, 0x72, 0xeb, 0x47, 0x33, - 0xce, 0x69, 0x26, 0xde, 0xe4, 0xb1, 0xd6, 0xd3, 0x68, 0x0a, 0xa6, 0x12, 0x84, 0x67, 0x31, 0x28, 0x69, 0x3d, 0xb3, - 0x33, 0x66, 0x2b, 0xaf, 0xa7, 0x64, 0xa6, 0xf4, 0x27, 0x19, 0xb4, 0xed, 0x4f, 0xb5, 0x65, 0xec, 0x21, 0x3c, 0xd3, - 0xd1, 0x5c, 0xcf, 0xf7, 0xfd, 0xa9, 0x1f, 0xc1, 0x6b, 0x18, 0xa0, 0x40, 0xa5, 0xdc, 0x47, 0x1e, 0x27, 0xb7, 0x7e, - 0x46, 0x6f, 0xe5, 0xa8, 0x1e, 0xaa, 0x25, 0xb3, 0xd9, 0x5e, 0x47, 0x51, 0x5f, 0xb2, 0x1b, 0xee, 0x67, 0x79, 0x4c, - 0x01, 0x3d, 0x10, 0xbf, 0xd7, 0x45, 0x49, 0x58, 0xd8, 0x41, 0xaa, 0x1a, 0xbe, 0x33, 0xdb, 0x7f, 0x3d, 0x05, 0xa7, - 0xaf, 0xb4, 0xf4, 0xaa, 0xca, 0xca, 0x13, 0x8e, 0x10, 0x1b, 0x79, 0x53, 0x1f, 0x82, 0x7b, 0x92, 0x84, 0x18, 0xd8, - 0x72, 0x53, 0x9b, 0xa8, 0xee, 0xaa, 0x3e, 0x27, 0x24, 0x3e, 0x2b, 0x76, 0x77, 0xa5, 0x23, 0x7a, 0xa6, 0x48, 0x62, - 0x8a, 0xf0, 0xa4, 0xda, 0x5b, 0xa6, 0xde, 0x3b, 0xd2, 0x1c, 0xc9, 0x9b, 0x34, 0x1d, 0xba, 0xbb, 0x4c, 0x20, 0xe9, - 0x2b, 0x14, 0xde, 0x1d, 0xc2, 0x23, 0xd2, 0xf6, 0xce, 0xfc, 0xe1, 0x1f, 0xce, 0xd1, 0xd0, 0xf3, 0x7f, 0x8f, 0xda, - 0x8a, 0x71, 0x4c, 0x50, 0x3f, 0x54, 0x43, 0xcc, 0x65, 0x14, 0xb3, 0x8b, 0xa5, 0x2f, 0x31, 0xc8, 0x71, 0x16, 0x4e, - 0x68, 0x30, 0x82, 0x3d, 0x6e, 0xe8, 0xe6, 0x1d, 0x06, 0x3a, 0x0a, 0x46, 0x9a, 0x93, 0xf8, 0xee, 0xf0, 0x67, 0x51, - 0x3d, 0x0d, 0xdd, 0xe1, 0xd7, 0xf5, 0xd3, 0x1f, 0xdc, 0xe1, 0x77, 0x22, 0xf8, 0xae, 0xd4, 0xee, 0xee, 0xc6, 0x10, - 0x8f, 0xcd, 0x10, 0xa5, 0x5a, 0x18, 0x0b, 0x73, 0x33, 0xc4, 0x57, 0x1c, 0x1d, 0x53, 0x54, 0xb2, 0x51, 0xc5, 0x8a, - 0xb8, 0x2f, 0xc2, 0x31, 0xa0, 0xd4, 0x5a, 0x01, 0x6e, 0x47, 0xf7, 0xeb, 0x09, 0x03, 0xa1, 0x18, 0x6a, 0x05, 0x54, - 0x4e, 0x07, 0x1d, 0x34, 0x6f, 0xd4, 0x95, 0x1a, 0x53, 0x33, 0x9a, 0x5e, 0x71, 0xe9, 0x09, 0xe9, 0xf4, 0x27, 0x47, - 0xd3, 0xfe, 0x64, 0x77, 0x17, 0x71, 0x43, 0x58, 0xb3, 0xb3, 0xc9, 0x39, 0x7e, 0x03, 0x5e, 0x3d, 0x9b, 0x92, 0x70, - 0x63, 0x7a, 0x3d, 0x3d, 0xbd, 0xdd, 0xdd, 0xbc, 0x44, 0x7d, 0xab, 0xe9, 0x54, 0x35, 0x2d, 0x4b, 0x85, 0x93, 0x65, - 0x42, 0x3b, 0x44, 0xb2, 0x04, 0x52, 0xa2, 0x08, 0x21, 0xa7, 0x02, 0xad, 0xed, 0x15, 0xfa, 0x84, 0xe6, 0x72, 0xc7, - 0x02, 0xf3, 0x54, 0x32, 0xc2, 0x03, 0x2c, 0x40, 0xd3, 0xca, 0x15, 0x7c, 0x87, 0x67, 0xbb, 0x5d, 0x49, 0xe4, 0xad, - 0x6e, 0xbf, 0xd9, 0xd7, 0x93, 0xba, 0x2f, 0x3c, 0xdb, 0x25, 0x77, 0x15, 0x96, 0xca, 0x7c, 0x77, 0xb7, 0x6c, 0xc6, - 0x3b, 0xcd, 0xbe, 0x6d, 0x44, 0x20, 0x8e, 0x97, 0x53, 0x33, 0x8c, 0x7c, 0xad, 0x25, 0x2a, 0xf3, 0x59, 0x96, 0x51, - 0x0e, 0x32, 0x94, 0x08, 0xcc, 0xca, 0xb2, 0x92, 0xeb, 0x6f, 0x41, 0x88, 0x62, 0x4a, 0x32, 0xe0, 0x3b, 0xd2, 0xec, - 0xc2, 0x39, 0x2e, 0x70, 0x24, 0xb9, 0x06, 0x21, 0xe4, 0xc4, 0x24, 0xb5, 0x08, 0xc9, 0x81, 0x42, 0xc2, 0x2c, 0x89, - 0xc4, 0x09, 0xf5, 0x2f, 0xb6, 0x4f, 0xf2, 0x7b, 0x4d, 0xb2, 0x33, 0x76, 0x1e, 0xc8, 0x6a, 0xa9, 0xe6, 0x5b, 0x09, - 0x79, 0xef, 0x09, 0x54, 0x85, 0x47, 0x7c, 0xc9, 0xfe, 0x9e, 0x33, 0x4e, 0xa5, 0x06, 0xbe, 0x6d, 0xcc, 0xbe, 0xb0, - 0xa9, 0x3e, 0x86, 0xb6, 0xf3, 0x06, 0x10, 0x09, 0xf2, 0xd7, 0xcb, 0xc9, 0x4a, 0xb5, 0x8b, 0xed, 0xe3, 0xb7, 0xeb, - 0x4c, 0xe0, 0xc5, 0x42, 0x1b, 0xbf, 0x21, 0x68, 0x36, 0x38, 0xa9, 0x21, 0x0d, 0xf5, 0x8f, 0xc0, 0x0b, 0xa5, 0x82, - 0x94, 0x78, 0x19, 0x50, 0xd1, 0xc5, 0xf6, 0xf1, 0x07, 0x2f, 0x93, 0xae, 0x25, 0x84, 0xed, 0x69, 0x7b, 0x05, 0xf1, - 0x22, 0x42, 0x91, 0x9a, 0x7b, 0xc5, 0xb8, 0x0a, 0x4b, 0x7c, 0x07, 0x91, 0x7c, 0x09, 0xf6, 0xc3, 0x19, 0x3b, 0x27, - 0xa1, 0xc6, 0x00, 0x09, 0x11, 0x0e, 0x1b, 0x66, 0x19, 0x81, 0x05, 0x90, 0x63, 0x9d, 0xc2, 0x4a, 0xf8, 0x4a, 0xf1, - 0x43, 0x38, 0x94, 0xa3, 0x8a, 0x52, 0x89, 0x8e, 0x9f, 0x56, 0x72, 0xd3, 0x6a, 0x6b, 0xf4, 0x3b, 0xb0, 0x9c, 0xcc, - 0xc3, 0x1b, 0xdd, 0x75, 0x55, 0xf0, 0xdc, 0x24, 0x91, 0x5d, 0x6c, 0x1f, 0xbf, 0xd6, 0x79, 0x64, 0xd3, 0xd0, 0x70, - 0xfb, 0x15, 0x0b, 0xf3, 0xf8, 0xb5, 0x5f, 0xbf, 0x95, 0x95, 0x2f, 0xb6, 0x8f, 0x3f, 0xae, 0xab, 0x06, 0xe5, 0xe5, - 0xac, 0x36, 0xf1, 0x25, 0x7c, 0x73, 0x9a, 0x06, 0x73, 0x2d, 0x1a, 0x02, 0x56, 0x62, 0x29, 0x8e, 0x02, 0x5e, 0x56, - 0x9e, 0x91, 0xe7, 0x38, 0x27, 0x32, 0x0e, 0xd4, 0x5c, 0x35, 0xad, 0xe4, 0xb1, 0x3c, 0x3b, 0x8d, 0xf2, 0x29, 0xdd, - 0x10, 0x1c, 0x3a, 0x46, 0x3e, 0x9b, 0x40, 0x02, 0x8d, 0x04, 0x9d, 0xe1, 0xad, 0x0e, 0xea, 0x37, 0x85, 0x57, 0x2e, - 0x89, 0xb4, 0x68, 0x48, 0x16, 0x1c, 0x91, 0x0e, 0x0e, 0x49, 0x07, 0x27, 0x84, 0x9f, 0x75, 0x94, 0x78, 0xe8, 0xd7, - 0xa1, 0x5c, 0x25, 0x64, 0x22, 0x42, 0x48, 0xa2, 0x76, 0xab, 0x12, 0xbf, 0x71, 0x3f, 0x91, 0xae, 0x47, 0x29, 0xd1, - 0x63, 0x65, 0xb4, 0x7a, 0x05, 0x2e, 0x64, 0xc7, 0xa7, 0xec, 0x2a, 0x85, 0xec, 0x12, 0x98, 0x15, 0x16, 0x28, 0xa8, - 0xaa, 0x76, 0x75, 0xd5, 0xc4, 0x97, 0xeb, 0x54, 0xe0, 0xc4, 0x07, 0xc6, 0x8d, 0x13, 0x9d, 0x8c, 0x53, 0xac, 0x36, - 0x79, 0xbc, 0xb3, 0xe3, 0xa9, 0x46, 0xdf, 0x0b, 0xaf, 0x7a, 0x5f, 0x87, 0xee, 0xbe, 0x53, 0xbc, 0x22, 0x46, 0x12, - 0xfe, 0xdd, 0xdd, 0xf0, 0xbc, 0x8c, 0xb6, 0x08, 0xf1, 0x92, 0x26, 0x06, 0x0d, 0xf0, 0x52, 0xd3, 0x6b, 0x4e, 0x7f, - 0x77, 0xb7, 0x0a, 0xd3, 0x36, 0xb1, 0x75, 0x8c, 0xf3, 0xf2, 0xda, 0xab, 0xf2, 0x7f, 0x3a, 0x2b, 0x59, 0x53, 0x06, - 0x04, 0xc4, 0x6c, 0x9a, 0x65, 0x66, 0x32, 0xd6, 0x96, 0x60, 0x50, 0xef, 0x1b, 0x9d, 0xb8, 0x80, 0x65, 0x8e, 0x95, - 0xae, 0x64, 0xd8, 0x59, 0x0f, 0x05, 0xa6, 0x12, 0x84, 0xa5, 0xa0, 0xd2, 0x6e, 0xa9, 0xc9, 0xfb, 0xf5, 0x6a, 0xe6, - 0x25, 0xe6, 0x48, 0xfb, 0xb8, 0x24, 0x14, 0x12, 0x59, 0xbd, 0x0a, 0x29, 0x2f, 0xc9, 0x78, 0x33, 0xc9, 0x1f, 0x5b, - 0x24, 0xff, 0x8c, 0x50, 0x8b, 0xfc, 0x95, 0x87, 0xc3, 0xcf, 0xb5, 0x6b, 0x81, 0x9b, 0x57, 0x27, 0x53, 0x02, 0x3e, - 0xb4, 0x26, 0x46, 0xb9, 0x1d, 0x57, 0xdc, 0xc0, 0x50, 0xec, 0x1d, 0x22, 0xbd, 0x90, 0xd8, 0x04, 0x81, 0xbd, 0x3a, - 0xaa, 0x06, 0x43, 0xaf, 0x73, 0xe9, 0xd9, 0x1c, 0xf0, 0xf8, 0xe3, 0xfd, 0x01, 0xd1, 0x93, 0xe9, 0xea, 0xce, 0xb5, - 0x32, 0x40, 0x61, 0xd6, 0xd6, 0xc6, 0x6d, 0xe6, 0x83, 0xc2, 0xf8, 0x55, 0x20, 0xbb, 0xc9, 0x7c, 0x96, 0x36, 0xa1, - 0x91, 0x7f, 0x00, 0x6d, 0xb7, 0x2b, 0x6b, 0x50, 0xab, 0x5b, 0xe0, 0x47, 0x2a, 0x0f, 0x35, 0xe4, 0x1b, 0xd8, 0xc7, - 0xb1, 0xac, 0x40, 0xb3, 0x78, 0xfd, 0xeb, 0x67, 0xa5, 0x26, 0x13, 0x05, 0x1a, 0x9a, 0x03, 0xff, 0x53, 0x24, 0x0f, - 0x74, 0x23, 0xe5, 0x02, 0x20, 0x68, 0x2c, 0xf1, 0x54, 0x23, 0xcc, 0x75, 0x6b, 0xe7, 0xfb, 0xcb, 0x2d, 0x42, 0xc6, - 0xb5, 0xf3, 0xf1, 0x7d, 0x9d, 0x7d, 0x05, 0x64, 0x81, 0x02, 0x30, 0x1e, 0xab, 0x02, 0x15, 0xbf, 0x3c, 0x31, 0xd5, - 0xa5, 0x01, 0xe9, 0xd7, 0xfa, 0xb6, 0x15, 0xdb, 0x94, 0x5e, 0x39, 0xf5, 0xde, 0xa0, 0x61, 0xe9, 0xed, 0x36, 0xbc, - 0x7d, 0x25, 0x24, 0x8c, 0xf0, 0xfc, 0x41, 0xd6, 0x36, 0xfd, 0x96, 0x9f, 0x96, 0x53, 0x58, 0x96, 0x16, 0xc5, 0x67, - 0x59, 0x41, 0xb9, 0x78, 0x46, 0x47, 0x39, 0x87, 0x90, 0x45, 0x85, 0x13, 0x54, 0x6e, 0x5b, 0x6e, 0x3b, 0x39, 0x3f, - 0x2b, 0x4e, 0xb0, 0x34, 0x41, 0xf9, 0xeb, 0x93, 0x8c, 0x5a, 0x5f, 0x2c, 0xb7, 0x1a, 0xef, 0xec, 0xbc, 0xaf, 0xd1, - 0xa4, 0xa1, 0x94, 0x50, 0x58, 0x4c, 0x4b, 0xa9, 0x34, 0x3a, 0x94, 0xbb, 0xed, 0x55, 0x2e, 0x00, 0xc3, 0x30, 0x6c, - 0xde, 0xf3, 0x92, 0x88, 0x72, 0xbc, 0xcc, 0xe2, 0xb5, 0x6b, 0x82, 0xd9, 0x66, 0x0b, 0x70, 0x78, 0x30, 0xb4, 0x95, - 0xaf, 0x88, 0xd7, 0x29, 0xb1, 0x15, 0x0c, 0x27, 0x80, 0x2c, 0x0f, 0xc2, 0xbd, 0x76, 0xd8, 0x83, 0xaf, 0x33, 0x4a, - 0xde, 0x81, 0x5e, 0x99, 0x60, 0xee, 0x27, 0x90, 0x04, 0xdb, 0xd8, 0xb2, 0x08, 0x61, 0x2e, 0x0d, 0x1a, 0x2b, 0x97, - 0xe0, 0xf8, 0xe5, 0x3a, 0x8f, 0xb2, 0x21, 0x6a, 0x2a, 0xa5, 0x0e, 0xd4, 0xc8, 0x51, 0xd5, 0xc0, 0xbf, 0xf6, 0x98, - 0x56, 0xdc, 0x4c, 0xdc, 0x0c, 0x18, 0xf0, 0x4f, 0xc2, 0x53, 0xb1, 0x28, 0x90, 0x19, 0x85, 0x3f, 0xf3, 0x1a, 0x43, - 0xf7, 0x0b, 0xd9, 0x0c, 0x6b, 0xc4, 0x45, 0x36, 0x9a, 0x0a, 0x19, 0xd7, 0x3b, 0xa9, 0x79, 0xe9, 0xb5, 0xca, 0xa3, - 0x16, 0x86, 0x0b, 0xd6, 0x99, 0x24, 0xd6, 0xf4, 0xaf, 0x55, 0x6a, 0x74, 0x55, 0x09, 0xd4, 0x30, 0x7a, 0xe3, 0x3c, - 0x93, 0x6b, 0x40, 0x4b, 0xa0, 0xaf, 0xf9, 0x89, 0xb0, 0x56, 0xd4, 0xf8, 0xb0, 0xe5, 0x98, 0x96, 0xd4, 0x7f, 0x0f, - 0xb9, 0x2e, 0xcb, 0x7b, 0xfe, 0xa5, 0x94, 0x85, 0x0c, 0xf3, 0x06, 0x63, 0xcf, 0x25, 0x63, 0x47, 0xa0, 0xa7, 0x99, - 0xf4, 0xef, 0xa1, 0x4e, 0x79, 0xd1, 0xb9, 0x8b, 0x9e, 0x26, 0xb1, 0x37, 0x55, 0xb8, 0xdc, 0xfa, 0xbd, 0xb4, 0x1a, - 0x01, 0x23, 0x90, 0x06, 0x84, 0x35, 0x67, 0xcf, 0x11, 0xe6, 0xbb, 0xbb, 0x7d, 0x7e, 0x44, 0x6b, 0x17, 0x49, 0x0d, - 0x23, 0x83, 0x88, 0x2e, 0x10, 0x7c, 0x43, 0x86, 0x72, 0x84, 0xab, 0x3c, 0x74, 0x0e, 0xae, 0xf6, 0xe3, 0xf7, 0x9e, - 0xcd, 0xd5, 0xec, 0xba, 0x55, 0xd0, 0x14, 0xe6, 0xe3, 0xd5, 0xf1, 0x96, 0x77, 0xf7, 0x67, 0x78, 0x00, 0xdc, 0x5b, - 0x5d, 0x0c, 0xd9, 0x68, 0xa8, 0x2f, 0x14, 0x4b, 0xa8, 0x76, 0x5f, 0x1f, 0xd5, 0x89, 0x89, 0xf6, 0x60, 0x7d, 0x51, - 0x9b, 0xb2, 0x82, 0xf0, 0xb2, 0x2c, 0x68, 0x1d, 0xdf, 0x5f, 0xca, 0xc0, 0x94, 0xc2, 0x65, 0xd5, 0xd9, 0x7e, 0x32, - 0x25, 0x02, 0x5b, 0x84, 0xfa, 0x6e, 0x53, 0xe8, 0xa3, 0x06, 0x13, 0xf6, 0xb5, 0x16, 0x8a, 0xdf, 0xad, 0x13, 0x8a, - 0x38, 0xd7, 0x5b, 0x5e, 0x0a, 0xc4, 0xee, 0x03, 0x04, 0xa2, 0x76, 0xb2, 0x1b, 0x99, 0x08, 0xea, 0x48, 0x43, 0x26, - 0xf2, 0xa6, 0x4c, 0xcc, 0x31, 0xd3, 0xab, 0x31, 0xe8, 0x2d, 0x16, 0xec, 0xac, 0x03, 0x4e, 0x24, 0xd7, 0x85, 0x9f, - 0x5d, 0xf5, 0xd3, 0xe2, 0xc4, 0xca, 0x09, 0xec, 0xb1, 0xca, 0x64, 0x41, 0x3e, 0xa4, 0x39, 0x7b, 0x32, 0x2b, 0x4b, - 0xd2, 0xb4, 0xa6, 0x20, 0x4d, 0xe0, 0x84, 0x55, 0x51, 0x26, 0x80, 0x58, 0xca, 0x0a, 0x6d, 0x40, 0x7a, 0x6b, 0xd3, - 0xff, 0x8c, 0x79, 0xf9, 0x79, 0x4d, 0xb4, 0x21, 0x57, 0x94, 0xfa, 0xd0, 0x48, 0x38, 0xd0, 0x10, 0x68, 0xfd, 0x70, - 0x4b, 0x9a, 0xa0, 0xb5, 0x28, 0x47, 0xb6, 0x1c, 0xc2, 0x1d, 0x70, 0xa1, 0x6d, 0xbd, 0x57, 0x01, 0xde, 0x35, 0xd2, - 0x04, 0x17, 0x16, 0x5d, 0xbf, 0x24, 0xa2, 0xc1, 0x4a, 0x22, 0xa2, 0x2d, 0x25, 0x9c, 0x48, 0x32, 0x15, 0x24, 0x3f, - 0xeb, 0x9c, 0x83, 0x02, 0xda, 0x0f, 0x8f, 0xf2, 0xda, 0x04, 0x0e, 0x77, 0x77, 0x51, 0x62, 0x46, 0x8d, 0xce, 0xd8, - 0x6e, 0x78, 0x8e, 0x29, 0x0e, 0x95, 0x61, 0x72, 0xb2, 0xb3, 0xe3, 0x25, 0xf5, 0xb8, 0x67, 0xe1, 0x39, 0xc2, 0xc5, - 0x62, 0xe1, 0x49, 0xb0, 0x12, 0xb4, 0x58, 0x24, 0x36, 0x58, 0xf2, 0x35, 0x34, 0x1b, 0x0f, 0x05, 0x19, 0x4b, 0x01, - 0x38, 0x06, 0x08, 0x77, 0x89, 0x97, 0x68, 0xe7, 0x5e, 0x02, 0xce, 0xa8, 0xdd, 0xfc, 0x2c, 0xdc, 0xed, 0x9e, 0x5b, - 0x8c, 0xeb, 0x2c, 0x3c, 0x27, 0x49, 0x59, 0xec, 0xec, 0x6c, 0x71, 0x2d, 0x22, 0x7f, 0x02, 0x51, 0xf6, 0x93, 0x94, - 0x2c, 0xaa, 0x43, 0x7b, 0x35, 0x96, 0x9d, 0x01, 0x15, 0x45, 0xe9, 0x65, 0x35, 0xf5, 0x1a, 0x59, 0x10, 0x55, 0x25, - 0xac, 0x63, 0xc1, 0x43, 0xb0, 0xec, 0x2b, 0x32, 0xff, 0x59, 0x54, 0x69, 0xd6, 0xdf, 0xad, 0x4d, 0xae, 0xf6, 0x7d, - 0x3f, 0xe4, 0x63, 0x19, 0xc9, 0x30, 0xe9, 0x14, 0x92, 0xf8, 0xf7, 0x34, 0x98, 0xd6, 0xc0, 0x67, 0xd5, 0x58, 0xe7, - 0x44, 0x81, 0x6f, 0x54, 0x1b, 0x73, 0xa2, 0xe4, 0x97, 0xb5, 0x5e, 0x06, 0x05, 0xc9, 0xd7, 0xbf, 0x16, 0x92, 0x7d, - 0x0d, 0x89, 0x22, 0x8f, 0x25, 0x9c, 0x6d, 0xc0, 0xc5, 0x2f, 0x62, 0x09, 0x67, 0x9b, 0x71, 0x5b, 0x31, 0x84, 0x4d, - 0xf0, 0x59, 0xbc, 0x41, 0x01, 0x5a, 0x17, 0x58, 0x50, 0x1e, 0x2c, 0xeb, 0x5e, 0x8a, 0x95, 0x82, 0x30, 0x15, 0xc4, - 0x63, 0xcd, 0x0d, 0x50, 0x6b, 0xa3, 0x96, 0xe1, 0xcb, 0x82, 0x31, 0xb2, 0x5c, 0x02, 0xcd, 0xd4, 0x15, 0x20, 0x27, - 0xed, 0x6b, 0x87, 0x54, 0x84, 0x2d, 0xa5, 0xc4, 0xf9, 0x51, 0x38, 0x15, 0x33, 0x0e, 0xaa, 0x14, 0x37, 0xbf, 0xa1, - 0x18, 0xce, 0x82, 0xc8, 0x32, 0xf8, 0x01, 0x05, 0xd3, 0xb0, 0x28, 0xd8, 0xb5, 0x2a, 0xd3, 0xbf, 0x71, 0x41, 0x0c, - 0x29, 0x73, 0xa5, 0x13, 0xe6, 0xa8, 0x9f, 0x6b, 0x3a, 0x6d, 0xa2, 0xed, 0xc5, 0x35, 0xcd, 0xc4, 0x2b, 0x56, 0x08, - 0x9a, 0xc1, 0xf4, 0x6b, 0x8a, 0x83, 0x19, 0x71, 0x04, 0x1b, 0xb6, 0xd1, 0x2a, 0x8c, 0xe3, 0x7b, 0x9b, 0x88, 0xa6, - 0x0e, 0x94, 0x84, 0x59, 0x9c, 0xaa, 0x41, 0xec, 0x84, 0x46, 0x93, 0xc4, 0x59, 0xd5, 0xb4, 0xf3, 0x69, 0x6a, 0x65, - 0x43, 0x72, 0x77, 0x8f, 0x11, 0x23, 0x09, 0x8c, 0xf4, 0xbc, 0x57, 0x6b, 0x81, 0x80, 0xf7, 0x86, 0x45, 0xb0, 0x67, - 0x82, 0x85, 0xc5, 0x51, 0xfd, 0x26, 0x9c, 0x86, 0x6e, 0xbe, 0x5f, 0x7b, 0xb0, 0x6d, 0x9d, 0x70, 0x90, 0x74, 0xf2, - 0x78, 0xb3, 0x65, 0xf5, 0xda, 0x48, 0x0e, 0x23, 0x2d, 0xd8, 0x43, 0x19, 0x33, 0x9a, 0x1b, 0xf2, 0x42, 0x66, 0x2b, - 0x6e, 0x0b, 0xf2, 0x33, 0x9c, 0x1c, 0x7a, 0x29, 0x26, 0xe9, 0xd2, 0x01, 0x99, 0xfe, 0x76, 0xa5, 0xfd, 0x6f, 0x0b, - 0xef, 0x19, 0x7e, 0x0d, 0x61, 0xdd, 0x6f, 0xeb, 0xea, 0xab, 0xe1, 0xdc, 0x6f, 0x6b, 0x04, 0x7d, 0x1b, 0xac, 0xd4, - 0xb3, 0xc2, 0xb8, 0x3d, 0xff, 0xd0, 0xef, 0xb8, 0x46, 0x5b, 0xfa, 0x41, 0x05, 0x91, 0x54, 0xaa, 0xa5, 0xdc, 0x0f, - 0xb8, 0x4e, 0x54, 0x83, 0x84, 0xb9, 0xa6, 0x85, 0x44, 0x75, 0x8a, 0xa1, 0xd2, 0xe1, 0x37, 0x2d, 0x8f, 0x96, 0x31, - 0xb9, 0xb2, 0x33, 0xde, 0x85, 0x5c, 0x6c, 0xc3, 0x2e, 0x2b, 0x56, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0x0f, 0x1b, - 0xa2, 0x3e, 0x0b, 0x30, 0xe4, 0xea, 0x30, 0x90, 0xdd, 0x3f, 0x29, 0x8c, 0xee, 0xd6, 0xb4, 0x32, 0xde, 0x80, 0xfd, - 0x8f, 0x70, 0x64, 0x8e, 0xc8, 0x51, 0xcd, 0x81, 0x69, 0x30, 0x2f, 0x2b, 0xa7, 0x40, 0xa1, 0x94, 0xb7, 0x0c, 0xe1, - 0xa2, 0x94, 0xe1, 0xed, 0xbf, 0xe0, 0xbf, 0x6a, 0x96, 0x78, 0x51, 0x71, 0x9c, 0x17, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, - 0x2a, 0x7a, 0x0f, 0x74, 0x2c, 0x29, 0xb4, 0x34, 0x54, 0xf4, 0x3c, 0xd7, 0x13, 0xd9, 0x98, 0x97, 0x8a, 0x69, 0x95, - 0x51, 0x23, 0x87, 0x59, 0x93, 0xc8, 0x69, 0xac, 0x6c, 0x51, 0xed, 0xaa, 0xc6, 0xb8, 0x68, 0x03, 0x16, 0xeb, 0xc0, - 0xe2, 0x62, 0xe1, 0x35, 0x51, 0x4d, 0x98, 0x15, 0xc7, 0x40, 0x98, 0x59, 0x09, 0x15, 0x0d, 0xcd, 0x5a, 0xb5, 0xf1, - 0xd0, 0x72, 0x3e, 0x91, 0xd1, 0xcd, 0x1b, 0x70, 0xd8, 0x2e, 0x04, 0xd5, 0xdc, 0xf6, 0x29, 0x60, 0x35, 0xbb, 0x6a, - 0x20, 0x0b, 0x43, 0x3f, 0x54, 0xb9, 0xb2, 0x75, 0x52, 0xeb, 0x1a, 0xfc, 0xa2, 0x7b, 0xb2, 0x65, 0x35, 0xea, 0x56, - 0xdf, 0x5b, 0xb9, 0x46, 0xcf, 0xf3, 0x4d, 0xb9, 0x46, 0x0d, 0x6d, 0x77, 0xab, 0x83, 0xee, 0xcf, 0x4b, 0x55, 0x63, - 0xad, 0xaf, 0xf2, 0x2b, 0x86, 0xeb, 0x02, 0x6d, 0x2a, 0x34, 0x1b, 0xae, 0x72, 0x52, 0x96, 0x17, 0xd5, 0x69, 0x02, - 0x99, 0xba, 0x73, 0xa1, 0xe8, 0x5f, 0x5b, 0x8d, 0xf2, 0x50, 0xae, 0xf7, 0x17, 0x32, 0x4e, 0xf3, 0xab, 0x30, 0xfd, - 0x00, 0xe3, 0xd5, 0x2f, 0x5f, 0xde, 0xc5, 0x3c, 0x14, 0x54, 0x73, 0x97, 0x1a, 0x86, 0xbf, 0x58, 0x30, 0xfc, 0x45, - 0xf1, 0xe9, 0xba, 0x3d, 0x9e, 0xbf, 0xaa, 0x3a, 0x08, 0x2e, 0x4a, 0xc3, 0x32, 0xee, 0xc4, 0xfa, 0x31, 0x96, 0x59, - 0xd8, 0x5d, 0xc5, 0xc2, 0xee, 0x84, 0xb7, 0xdc, 0x95, 0xe7, 0xfd, 0x75, 0x7d, 0x2f, 0xab, 0x9c, 0xed, 0xaf, 0xf5, - 0xc6, 0xff, 0x6b, 0x70, 0x6f, 0x1b, 0x8b, 0xcb, 0xed, 0xf9, 0x7b, 0x32, 0x59, 0x45, 0x81, 0xfc, 0x0a, 0x92, 0x0e, - 0x04, 0x19, 0x58, 0x87, 0x0e, 0x6a, 0x39, 0x65, 0xf2, 0x80, 0xbc, 0x68, 0x56, 0x88, 0x7c, 0xa2, 0xfb, 0x2c, 0xf4, - 0x49, 0x23, 0xf9, 0x12, 0x5c, 0xd1, 0x32, 0xd6, 0x1e, 0x34, 0xcf, 0x72, 0xcd, 0x3f, 0xb1, 0x2c, 0x0e, 0x38, 0xd6, - 0x52, 0xa4, 0x08, 0xf2, 0x92, 0x98, 0x6c, 0xe3, 0xd5, 0x77, 0x78, 0xc4, 0x32, 0x56, 0x24, 0x94, 0x7b, 0x05, 0x9a, - 0x6f, 0x1a, 0xac, 0x80, 0x80, 0x8c, 0x1a, 0x0c, 0xff, 0xa9, 0x3e, 0xf5, 0xe7, 0x43, 0x6f, 0xe0, 0x07, 0x9a, 0x50, - 0x91, 0xe4, 0x31, 0xa4, 0xa5, 0xf8, 0x71, 0x75, 0xa8, 0x69, 0x67, 0x67, 0xcb, 0x73, 0xa5, 0x5b, 0x02, 0x0e, 0x80, - 0xdb, 0x6f, 0xd0, 0x70, 0x0e, 0xe7, 0x73, 0xea, 0xa1, 0x29, 0x9a, 0xd3, 0xe5, 0xa3, 0x2c, 0xc2, 0xff, 0x44, 0xef, - 0x70, 0x86, 0xca, 0x32, 0x50, 0x50, 0xbb, 0x23, 0x46, 0xd3, 0xd8, 0xc5, 0x9f, 0xe8, 0x5d, 0x50, 0x9d, 0x19, 0x97, - 0x47, 0x9c, 0xe5, 0x02, 0xba, 0xf9, 0x4d, 0xe6, 0xe2, 0x7a, 0x90, 0x60, 0x5e, 0xe2, 0x9c, 0xb3, 0x31, 0x10, 0xe7, - 0xb7, 0xf4, 0x2e, 0x50, 0xfd, 0x31, 0xeb, 0xbc, 0x1e, 0x9a, 0x1b, 0xd4, 0xfb, 0x56, 0xb1, 0xbd, 0x0c, 0xda, 0xa0, - 0x38, 0x93, 0x6d, 0xcf, 0x49, 0xa3, 0x5e, 0x6d, 0x1e, 0x22, 0x54, 0x3e, 0x74, 0x2a, 0xf8, 0x5b, 0x5b, 0xb4, 0x89, - 0x46, 0xe6, 0xeb, 0x52, 0x23, 0x0a, 0x0d, 0xea, 0x4c, 0x8f, 0x6d, 0x2f, 0x33, 0xbb, 0x4e, 0x1f, 0x42, 0xb0, 0x1c, - 0x61, 0xdf, 0x0a, 0xdd, 0x69, 0xf0, 0x27, 0x95, 0x10, 0x52, 0x47, 0x92, 0xbe, 0xa9, 0xdb, 0x39, 0xdb, 0x1e, 0xe0, - 0x1d, 0x12, 0x5a, 0x42, 0x79, 0x26, 0xb3, 0x34, 0xd9, 0xa2, 0x7f, 0x16, 0xc4, 0x9b, 0x9b, 0x29, 0x04, 0x99, 0x8d, - 0x45, 0x51, 0x02, 0x15, 0x6a, 0xfa, 0x52, 0x09, 0x80, 0x6c, 0xe4, 0xb1, 0x15, 0xa9, 0x99, 0x4b, 0xa9, 0xe9, 0x5b, - 0x18, 0xdf, 0x20, 0x25, 0xa9, 0x44, 0x86, 0x54, 0x22, 0xa5, 0xd0, 0xd3, 0x8b, 0xab, 0x49, 0xc8, 0x5e, 0xd0, 0xea, - 0x04, 0x9d, 0x5a, 0xf3, 0xbc, 0x01, 0x96, 0x27, 0xfb, 0x41, 0x65, 0x00, 0x53, 0xa2, 0xaa, 0x42, 0x59, 0x1d, 0xcd, - 0x36, 0xe9, 0xad, 0x9e, 0x3c, 0xeb, 0x24, 0xa7, 0x45, 0x0c, 0x4a, 0xbc, 0x08, 0xcd, 0x33, 0x2f, 0xc2, 0x39, 0xa4, - 0x23, 0x16, 0x65, 0x05, 0x3f, 0xb5, 0x57, 0xa3, 0x91, 0xac, 0xbc, 0xfe, 0x94, 0x1f, 0x28, 0xf3, 0x02, 0x52, 0x34, - 0x71, 0x66, 0x78, 0x4a, 0xe6, 0xc9, 0xe3, 0x76, 0xd6, 0xb2, 0xfd, 0x45, 0x27, 0xe8, 0x68, 0xc0, 0xfe, 0x2c, 0xbc, - 0xb9, 0x35, 0x0b, 0xfb, 0x44, 0xb7, 0x3e, 0xf5, 0xa7, 0x83, 0x7d, 0x75, 0x0e, 0xa9, 0xc7, 0xc9, 0x92, 0xc4, 0xb9, - 0x3f, 0xd5, 0xf2, 0xe7, 0x19, 0xe5, 0x77, 0xa7, 0x14, 0x52, 0x9d, 0x73, 0x38, 0xf0, 0x5b, 0x2f, 0x43, 0x9d, 0xa7, - 0x3e, 0xcc, 0xa5, 0xb2, 0x52, 0x36, 0xcf, 0x01, 0x2e, 0x9f, 0x12, 0x2c, 0x65, 0xb4, 0xd1, 0x72, 0xc4, 0xa8, 0xdd, - 0x42, 0x37, 0x9e, 0x9f, 0xa4, 0x7d, 0x06, 0xfe, 0xb5, 0x1a, 0xd3, 0x3a, 0x58, 0x80, 0x0b, 0xfb, 0x4c, 0xea, 0x19, - 0x3f, 0x5f, 0xf6, 0xca, 0x40, 0x11, 0x84, 0xef, 0xf2, 0xcd, 0x53, 0x5d, 0x97, 0x34, 0xbb, 0x79, 0xaa, 0x8d, 0xa0, - 0x9f, 0x4c, 0xf8, 0xc1, 0x7a, 0x9c, 0xea, 0x04, 0x33, 0x2b, 0x4b, 0x54, 0x02, 0x78, 0x7f, 0xec, 0x7b, 0xde, 0x1f, - 0x75, 0xca, 0xa0, 0x0f, 0xb1, 0xd8, 0xd3, 0x34, 0x37, 0x4c, 0xbc, 0x1e, 0xff, 0x8f, 0x2b, 0xe3, 0xff, 0xd1, 0x3a, - 0x75, 0x0a, 0xa6, 0xd1, 0x38, 0xa3, 0xb1, 0x61, 0x9d, 0x48, 0x11, 0xa0, 0xd4, 0xdb, 0x0a, 0x41, 0x3e, 0x5d, 0x06, - 0xa0, 0x71, 0xcd, 0x47, 0x79, 0x26, 0x5a, 0xa3, 0x70, 0xc2, 0xd2, 0xbb, 0x60, 0xc6, 0x5a, 0x93, 0x3c, 0xcb, 0x8b, - 0x69, 0x18, 0x51, 0x5c, 0xdc, 0x15, 0x82, 0x4e, 0x5a, 0x33, 0x86, 0x5f, 0xd2, 0xf4, 0x9a, 0x0a, 0x16, 0x85, 0xd8, - 0x3d, 0xe6, 0x2c, 0x4c, 0x9d, 0x37, 0x21, 0xe7, 0xf9, 0x8d, 0x8b, 0xdf, 0xe7, 0x57, 0xb9, 0xc8, 0xf1, 0xdb, 0xdb, - 0xbb, 0x31, 0xcd, 0xf0, 0xc7, 0xab, 0x59, 0x26, 0x66, 0xb8, 0x08, 0xb3, 0xa2, 0x55, 0x50, 0xce, 0x46, 0xfd, 0x28, - 0x4f, 0x73, 0xde, 0x82, 0x8c, 0xed, 0x09, 0x0d, 0x52, 0x36, 0x4e, 0x84, 0x13, 0x87, 0xfc, 0x53, 0xbf, 0xd5, 0x9a, - 0x72, 0x36, 0x09, 0xf9, 0x5d, 0x4b, 0xd6, 0x08, 0xbe, 0xea, 0xec, 0x85, 0x4f, 0x47, 0xfb, 0x7d, 0xc1, 0xc3, 0xac, - 0x60, 0xb0, 0x4c, 0x41, 0x98, 0xa6, 0xce, 0xde, 0x41, 0x67, 0x52, 0x6c, 0xa9, 0x40, 0x5e, 0x98, 0x89, 0xf2, 0x12, - 0x7f, 0x00, 0xb8, 0xfd, 0x2b, 0x91, 0xe1, 0xab, 0x99, 0x10, 0x79, 0x36, 0x8f, 0x66, 0xbc, 0xc8, 0x79, 0x30, 0xcd, - 0x59, 0x26, 0x28, 0xef, 0x5f, 0xe5, 0x3c, 0xa6, 0xbc, 0xc5, 0xc3, 0x98, 0xcd, 0x8a, 0x60, 0x7f, 0x7a, 0xdb, 0x07, - 0xcd, 0x62, 0xcc, 0xf3, 0x59, 0x16, 0xeb, 0xb1, 0x58, 0x96, 0x50, 0xce, 0x84, 0xfd, 0x42, 0x5e, 0x64, 0x12, 0xa4, - 0x2c, 0xa3, 0x21, 0x6f, 0x8d, 0xa1, 0x31, 0x98, 0x45, 0x9d, 0x98, 0x8e, 0x31, 0x1f, 0x5f, 0x85, 0x5e, 0xb7, 0xf7, - 0x04, 0x9b, 0xff, 0xfd, 0x03, 0xe4, 0x74, 0xd6, 0x17, 0x77, 0x3b, 0x9d, 0x7f, 0x42, 0xfd, 0xa5, 0x51, 0x24, 0x40, - 0x41, 0x77, 0x7a, 0xeb, 0x14, 0x39, 0x64, 0xb4, 0xad, 0x6b, 0xd9, 0x9f, 0x86, 0x31, 0xe4, 0x03, 0x07, 0xbd, 0xe9, - 0x6d, 0x09, 0xb3, 0x0b, 0x54, 0x8a, 0xa9, 0x9e, 0xa4, 0x7e, 0x9a, 0xff, 0x5a, 0x88, 0x0f, 0xd7, 0x43, 0xdc, 0x33, - 0x10, 0xd7, 0x58, 0x6f, 0xc5, 0x33, 0x2e, 0x63, 0xab, 0x41, 0xb7, 0x50, 0x80, 0x24, 0xf9, 0x35, 0xe5, 0x06, 0x0e, - 0xf9, 0xf0, 0xab, 0xc1, 0xe8, 0xad, 0x07, 0xe3, 0xf0, 0x73, 0x60, 0xf0, 0x2c, 0x9e, 0x37, 0xd7, 0xb5, 0xcb, 0xe9, - 0xa4, 0x9f, 0x50, 0xa0, 0xa7, 0xa0, 0x07, 0xbf, 0x6f, 0x58, 0x2c, 0x12, 0xf5, 0x53, 0x92, 0xf3, 0x8d, 0x7a, 0x77, - 0xd0, 0xe9, 0xa8, 0xe7, 0x82, 0xfd, 0x42, 0x83, 0xae, 0x0f, 0x15, 0xca, 0x4b, 0xfc, 0xd7, 0xea, 0x34, 0x6f, 0x93, - 0x7b, 0xe2, 0x3f, 0xda, 0xc7, 0x7c, 0xad, 0x14, 0xc5, 0xfa, 0x50, 0x34, 0xce, 0x8d, 0xac, 0x54, 0xc2, 0x07, 0xdc, - 0x76, 0x92, 0x3b, 0x12, 0x36, 0xa8, 0x8e, 0x71, 0xb2, 0xe1, 0x1f, 0x55, 0xde, 0x45, 0x00, 0x91, 0x0e, 0x2b, 0xd5, - 0xb0, 0xe8, 0xe7, 0x03, 0xd2, 0xe9, 0xe7, 0xad, 0x16, 0xf2, 0x0a, 0x92, 0x9d, 0xe5, 0x3a, 0x39, 0xcf, 0x63, 0xc3, - 0x42, 0x1a, 0xdb, 0x1c, 0x05, 0x05, 0x9c, 0x35, 0x5d, 0x2c, 0x78, 0x9d, 0x90, 0x21, 0x4f, 0x6b, 0xfc, 0x55, 0xe8, - 0x0a, 0x98, 0x5b, 0x9c, 0x3c, 0x34, 0xd7, 0xbb, 0x64, 0x86, 0x57, 0xa4, 0x79, 0x24, 0x31, 0xe7, 0x4f, 0x43, 0x91, - 0x80, 0x97, 0xa2, 0x12, 0x3f, 0x75, 0x0a, 0x93, 0xdb, 0x76, 0xd1, 0x30, 0xab, 0xf2, 0xdb, 0x20, 0x8f, 0x2f, 0x2b, - 0xa1, 0x97, 0x2b, 0x41, 0xa0, 0xc7, 0xba, 0xff, 0x8f, 0xc2, 0x92, 0xd4, 0x99, 0xcf, 0xb2, 0x28, 0x9d, 0xc5, 0xb4, - 0x90, 0x3d, 0xd4, 0xe2, 0x1c, 0xee, 0x86, 0xa8, 0x6a, 0xc9, 0x26, 0xd0, 0xbb, 0xcc, 0xe6, 0x81, 0x8a, 0x70, 0x8b, - 0x4a, 0xf5, 0xdc, 0x92, 0xcf, 0x75, 0xdb, 0x37, 0x75, 0xb2, 0x28, 0xb4, 0xf4, 0x67, 0x19, 0xfb, 0x79, 0x46, 0x2f, - 0x58, 0x6c, 0x9d, 0xdc, 0xa5, 0x59, 0x94, 0xc7, 0xf4, 0xe3, 0xfb, 0x6f, 0x20, 0xdb, 0x3d, 0xcf, 0x80, 0xc4, 0x32, - 0xe5, 0xef, 0xc2, 0x9c, 0x64, 0x7e, 0x4c, 0xaf, 0x59, 0x44, 0x87, 0x97, 0xdb, 0xf3, 0xb5, 0x15, 0xd5, 0x6b, 0x54, - 0xb6, 0x2f, 0xc1, 0x7f, 0xa7, 0xa0, 0xbc, 0xdc, 0x9e, 0x5f, 0x89, 0xb2, 0xbd, 0x3d, 0xcf, 0xfc, 0x38, 0x9f, 0x84, - 0x2c, 0x83, 0xdf, 0xbc, 0xdc, 0x9e, 0x33, 0xf8, 0x21, 0xca, 0xcb, 0xb2, 0x4e, 0x14, 0xad, 0x20, 0xb2, 0xa6, 0xa0, - 0x71, 0xd7, 0x45, 0xfe, 0x4f, 0x39, 0xcb, 0x64, 0xd1, 0x7d, 0x3d, 0x53, 0xd3, 0x2b, 0x20, 0xf9, 0x17, 0xa2, 0x0c, - 0x66, 0x63, 0x2e, 0x5f, 0x3c, 0xd4, 0x5c, 0xa6, 0x99, 0x60, 0x32, 0x2d, 0xde, 0x84, 0x73, 0x92, 0xb0, 0xb8, 0x88, - 0xd4, 0x49, 0xd4, 0xa2, 0x3e, 0x75, 0x11, 0x4a, 0xc4, 0x2a, 0x0b, 0x98, 0x72, 0x69, 0xec, 0xd3, 0xcd, 0x47, 0x25, - 0xb3, 0xfb, 0x8c, 0xbf, 0x8a, 0xaa, 0x8a, 0x7c, 0xc6, 0x23, 0x88, 0xf5, 0x6a, 0x95, 0x62, 0xd5, 0x2b, 0xe6, 0x4a, - 0xfd, 0xcd, 0xc5, 0xc2, 0x4a, 0xb2, 0x15, 0x70, 0xa6, 0xaf, 0xbe, 0xb6, 0x83, 0xca, 0x78, 0xa2, 0x3a, 0x0b, 0xa3, - 0xf5, 0x07, 0x33, 0x25, 0x50, 0x88, 0x62, 0x99, 0x2f, 0xea, 0xe5, 0x64, 0x90, 0xd7, 0x38, 0x27, 0x84, 0x30, 0x9f, - 0xc5, 0x32, 0x90, 0x07, 0x8a, 0x45, 0xab, 0x0b, 0x91, 0x21, 0x16, 0xd7, 0x1a, 0x1e, 0xd3, 0x78, 0x5e, 0x2c, 0xe0, - 0x6c, 0x8a, 0xac, 0xab, 0x9c, 0x2a, 0xa0, 0x83, 0x31, 0xac, 0x5e, 0x06, 0x39, 0xae, 0xba, 0x0c, 0xa0, 0x52, 0xd9, - 0x57, 0xe8, 0x53, 0xc8, 0x22, 0x06, 0x9d, 0xc7, 0x4a, 0x45, 0x28, 0x10, 0xb6, 0x5f, 0x57, 0x47, 0xf8, 0x1b, 0xf8, - 0xee, 0x2c, 0x2d, 0x8b, 0xb2, 0xa7, 0x96, 0x17, 0xcb, 0x2f, 0x72, 0x2e, 0x3c, 0x2f, 0xc2, 0x21, 0x22, 0x83, 0x48, - 0x52, 0xed, 0x51, 0x28, 0xff, 0x19, 0xb6, 0xba, 0x41, 0xb7, 0xf2, 0x84, 0x34, 0x4e, 0x56, 0xab, 0x3c, 0x33, 0x7d, - 0x3a, 0x17, 0xc0, 0xc5, 0xd5, 0x6f, 0x35, 0x9f, 0xfa, 0xb9, 0x9a, 0x16, 0xd6, 0x9c, 0x4b, 0x49, 0x7d, 0xaf, 0x01, - 0x84, 0x8c, 0xbb, 0x6d, 0x18, 0x0a, 0x95, 0xf5, 0xbc, 0xab, 0x5d, 0x7c, 0xa9, 0xb4, 0x9d, 0x0b, 0x8b, 0x8c, 0x2f, - 0x99, 0xf1, 0xd7, 0x35, 0x09, 0xac, 0xd4, 0x18, 0xb1, 0x58, 0xc0, 0xba, 0x6a, 0x0a, 0x96, 0x3b, 0x92, 0xad, 0xa5, - 0x52, 0x5f, 0x3d, 0x52, 0x45, 0x16, 0xeb, 0xab, 0xc8, 0xac, 0xc7, 0x75, 0x80, 0x81, 0x07, 0xa0, 0x10, 0x66, 0x0a, - 0xc0, 0x4c, 0x46, 0x14, 0x8e, 0x24, 0x69, 0xd6, 0x82, 0xe7, 0x4a, 0x8d, 0x0f, 0xdc, 0x77, 0x6f, 0x4f, 0x3f, 0xb8, - 0x18, 0xee, 0x34, 0xa3, 0xbc, 0x08, 0xe6, 0xae, 0x4e, 0x26, 0x6c, 0x41, 0x60, 0xda, 0x0d, 0xdc, 0x70, 0x0a, 0xa7, - 0xb3, 0x25, 0xf7, 0x6c, 0xdf, 0xb6, 0x6e, 0x6e, 0x6e, 0x5a, 0x70, 0x74, 0xac, 0x35, 0xe3, 0xa9, 0xe2, 0x2b, 0xb1, - 0x5b, 0x96, 0xc8, 0x17, 0x09, 0xcd, 0xaa, 0x5b, 0x8f, 0xf2, 0x94, 0xfa, 0x69, 0x3e, 0x56, 0x07, 0x5f, 0x97, 0xfd, - 0x10, 0xe9, 0xe5, 0x91, 0xbc, 0xcd, 0x6b, 0x70, 0x24, 0xd4, 0x3d, 0x6a, 0x82, 0xc3, 0xcf, 0x01, 0x44, 0xa9, 0x8e, - 0xda, 0x22, 0x91, 0x0f, 0xa7, 0xb0, 0x6d, 0xe4, 0xd3, 0xf6, 0x7c, 0x85, 0xc8, 0x86, 0xd0, 0x45, 0x32, 0x50, 0x53, - 0x2b, 0x64, 0xad, 0xcb, 0x20, 0xbd, 0xbc, 0x2c, 0x8f, 0xda, 0xd0, 0x57, 0xdb, 0xf4, 0x7b, 0x95, 0xc7, 0x77, 0xa6, - 0x7d, 0x45, 0x78, 0x70, 0xab, 0x53, 0x46, 0x06, 0xd0, 0x05, 0x8c, 0x1b, 0x0f, 0x24, 0xce, 0x34, 0xaf, 0x3c, 0xab, - 0x1f, 0xca, 0x73, 0x07, 0x38, 0x63, 0x09, 0x25, 0x40, 0x97, 0xd0, 0x79, 0x5c, 0x35, 0x90, 0xdb, 0x5a, 0x15, 0x6d, - 0x02, 0x50, 0x55, 0xac, 0xb7, 0x8b, 0xf2, 0x67, 0xd7, 0x64, 0x61, 0x20, 0x8e, 0x6d, 0xe0, 0x2f, 0x11, 0xfc, 0x2b, - 0x01, 0x3f, 0x6a, 0x2b, 0x34, 0x5d, 0xda, 0xf7, 0xcb, 0xa8, 0x9b, 0x1f, 0x2a, 0x64, 0x9e, 0x15, 0x02, 0x7f, 0x10, - 0xf8, 0xd3, 0xa5, 0xac, 0x6a, 0xd4, 0x01, 0xd0, 0x53, 0x41, 0x6d, 0xea, 0x18, 0xbd, 0x2f, 0xca, 0xd3, 0x34, 0x9c, - 0x16, 0x34, 0x30, 0x3f, 0xb4, 0x66, 0x00, 0x0a, 0xc6, 0xaa, 0x2a, 0xa6, 0x13, 0x9c, 0x4e, 0x40, 0x61, 0x5b, 0xd5, - 0x13, 0xaf, 0x43, 0xee, 0xb5, 0x5a, 0x51, 0xeb, 0x6a, 0x8c, 0x4a, 0x91, 0xcc, 0x6d, 0xbd, 0xe2, 0x71, 0xa7, 0xd3, - 0x87, 0x6c, 0xd4, 0x56, 0x98, 0xb2, 0x71, 0x16, 0xa4, 0x74, 0x24, 0x4a, 0x01, 0xc7, 0x04, 0xe7, 0x46, 0x91, 0xf3, - 0x7b, 0x07, 0x9c, 0x4e, 0x1c, 0x1f, 0xfe, 0xde, 0x3f, 0x70, 0x29, 0xe2, 0x20, 0x13, 0x49, 0x4b, 0x66, 0x3d, 0xc3, - 0x99, 0x0d, 0x91, 0x34, 0x9e, 0xe7, 0xd6, 0x40, 0x11, 0x05, 0x25, 0xb7, 0x14, 0xdc, 0x11, 0x09, 0x16, 0xdc, 0xae, - 0x97, 0xa1, 0xf9, 0xca, 0x0c, 0x56, 0x75, 0xad, 0x3d, 0x54, 0x16, 0xd2, 0x34, 0x59, 0xad, 0x6c, 0x14, 0xd6, 0xe6, - 0xd3, 0x0a, 0xfa, 0x2c, 0xd5, 0xba, 0x54, 0xae, 0xfd, 0xb9, 0x6a, 0xf1, 0x10, 0x64, 0x36, 0x94, 0x7e, 0x6c, 0xb7, - 0x40, 0x25, 0xcb, 0xa6, 0x33, 0x71, 0x26, 0xc3, 0x0a, 0x1c, 0x0e, 0xa8, 0x9c, 0x63, 0xab, 0x04, 0x70, 0x70, 0x3e, - 0x57, 0xc0, 0x44, 0x61, 0x1a, 0x79, 0x00, 0x91, 0xd3, 0x72, 0x0e, 0x39, 0x9d, 0xa0, 0xfe, 0x84, 0x65, 0x2d, 0xf5, - 0xee, 0xc0, 0x52, 0x0c, 0xfd, 0x27, 0xf0, 0x54, 0xfa, 0xb2, 0x37, 0x2c, 0xb3, 0x87, 0xd7, 0xe0, 0xf2, 0xf2, 0xbc, - 0x2c, 0xfb, 0xb9, 0xf0, 0xce, 0xbe, 0xf1, 0xd0, 0x39, 0xfe, 0xc5, 0xba, 0x21, 0xc7, 0x35, 0x3b, 0xc9, 0xc5, 0x3d, - 0xb4, 0xa1, 0x8a, 0xbd, 0x17, 0x64, 0xb5, 0x5f, 0x08, 0x54, 0x7c, 0xe5, 0xb9, 0xb4, 0x98, 0xb6, 0x14, 0xcb, 0x6b, - 0x49, 0x92, 0x75, 0xa1, 0x29, 0xd2, 0xbe, 0x72, 0x4a, 0xe7, 0x92, 0x9b, 0xe9, 0x43, 0x32, 0xca, 0x9d, 0x73, 0x5e, - 0x1d, 0xaa, 0xd2, 0xcf, 0xf6, 0x31, 0x2a, 0xd4, 0x60, 0x37, 0x97, 0xc7, 0x4d, 0xd6, 0x08, 0xca, 0x45, 0x75, 0x91, - 0x60, 0x98, 0xa6, 0x30, 0xe0, 0xa5, 0xd1, 0x48, 0xec, 0x7b, 0x57, 0xce, 0xc4, 0xb9, 0x87, 0x4a, 0xbd, 0x4f, 0x9f, - 0x49, 0xa5, 0xde, 0xba, 0xbd, 0x70, 0x4b, 0x98, 0x70, 0x9d, 0x12, 0xd1, 0x0c, 0x12, 0x0e, 0x1a, 0x89, 0xe9, 0xfd, - 0x9a, 0xb5, 0x29, 0x93, 0xc0, 0x91, 0x13, 0x22, 0x2e, 0xcf, 0x62, 0xd7, 0xf9, 0x43, 0x94, 0xb2, 0xe8, 0x13, 0x71, - 0xb7, 0xe7, 0x1e, 0x5a, 0x3d, 0x77, 0x2a, 0xb9, 0x82, 0xe1, 0xf3, 0xa8, 0x19, 0xca, 0xc8, 0x7d, 0x8b, 0x85, 0xab, - 0xab, 0x89, 0xdc, 0x01, 0xe8, 0x4d, 0x47, 0x6d, 0x35, 0xce, 0xe0, 0xb2, 0xbc, 0xa8, 0xaf, 0x1c, 0xab, 0xa1, 0x00, - 0x34, 0xab, 0x72, 0x47, 0x12, 0x15, 0x71, 0x3f, 0x4b, 0x69, 0xae, 0xa3, 0x98, 0x1a, 0xc0, 0x29, 0x34, 0x7f, 0x73, - 0x9d, 0x3f, 0x54, 0x65, 0xb4, 0xf2, 0x29, 0xc9, 0xa4, 0x18, 0xe2, 0xc2, 0x58, 0xe0, 0x48, 0xf0, 0x63, 0x2a, 0x42, - 0x96, 0xaa, 0x26, 0x7d, 0xe3, 0x02, 0x59, 0x9a, 0xd1, 0x62, 0xc1, 0x9b, 0x73, 0x61, 0x4d, 0x0c, 0xca, 0x99, 0x1d, - 0xb5, 0x6b, 0xb8, 0xe5, 0xcc, 0xe4, 0x9e, 0xb4, 0x83, 0xb3, 0xf5, 0x0c, 0xd5, 0x3b, 0xe7, 0x0f, 0x91, 0x3c, 0xb6, - 0x05, 0x00, 0x16, 0x1a, 0x40, 0x48, 0x1b, 0x50, 0xc7, 0x92, 0xbc, 0x90, 0x14, 0xbe, 0x08, 0xf9, 0x98, 0x8a, 0x25, - 0xc4, 0x86, 0x2a, 0x4b, 0xb8, 0x6f, 0x52, 0x04, 0x56, 0xa0, 0x4d, 0x9a, 0xd0, 0x82, 0x12, 0x5d, 0x0e, 0x41, 0x0f, - 0x26, 0x6b, 0xd5, 0xe9, 0x08, 0x81, 0xbc, 0x95, 0x8b, 0xc3, 0xa5, 0x84, 0x29, 0xa4, 0x84, 0x51, 0x9c, 0xc0, 0x91, - 0x63, 0x49, 0x10, 0x4b, 0xd7, 0x19, 0x2a, 0xc8, 0x69, 0xac, 0x60, 0x26, 0xb9, 0x6c, 0x55, 0x94, 0x47, 0x6d, 0x55, - 0x5b, 0x89, 0x00, 0x55, 0x09, 0x90, 0x20, 0xf7, 0x69, 0x8d, 0x03, 0xc8, 0x2c, 0xb7, 0xf1, 0x10, 0xb3, 0xeb, 0x8a, - 0xd8, 0xe4, 0x01, 0xb6, 0xc1, 0x51, 0x1a, 0x5e, 0xd1, 0x74, 0xb0, 0x3d, 0xcf, 0x17, 0x8b, 0x4e, 0x79, 0xd4, 0x56, - 0x8f, 0xce, 0x91, 0xe4, 0x1b, 0xea, 0xe2, 0x51, 0xb9, 0xc4, 0x70, 0x2a, 0x14, 0xf2, 0x6d, 0x4d, 0xa2, 0x59, 0xa0, - 0x3b, 0x28, 0x5d, 0x47, 0xa6, 0xb8, 0xc8, 0x4a, 0x95, 0x1e, 0x55, 0xba, 0x0e, 0x8b, 0x57, 0xcb, 0x0a, 0x41, 0xa7, - 0x50, 0x1a, 0x2d, 0x16, 0xdd, 0xd2, 0x75, 0x26, 0x2c, 0x83, 0xa7, 0x7c, 0xb1, 0x90, 0x07, 0x2e, 0x27, 0x2c, 0xf3, - 0x3a, 0x40, 0xb6, 0xae, 0x33, 0x09, 0x6f, 0xe5, 0x84, 0xcd, 0x9b, 0xf0, 0xd6, 0xeb, 0xea, 0x57, 0x7e, 0x85, 0x1f, - 0x0e, 0x14, 0x57, 0xaf, 0x68, 0xa8, 0x57, 0x34, 0xc6, 0x33, 0x75, 0x94, 0x8c, 0x78, 0x31, 0x09, 0xd7, 0xaf, 0x68, - 0x6c, 0x56, 0x74, 0xb6, 0x61, 0x45, 0x67, 0xf7, 0xac, 0x68, 0xa2, 0x57, 0xcf, 0xa9, 0x70, 0x57, 0x2c, 0x16, 0xdd, - 0x4e, 0x8d, 0xbd, 0xa3, 0x76, 0xcc, 0xae, 0x61, 0x35, 0x40, 0x3b, 0x14, 0x6c, 0x42, 0xd7, 0x13, 0x65, 0x13, 0xc5, - 0xf4, 0x8b, 0x30, 0x59, 0x63, 0x21, 0x6f, 0x62, 0xc1, 0xa6, 0xeb, 0x2a, 0xea, 0xf9, 0x5b, 0x52, 0x36, 0x03, 0x3c, - 0x70, 0xc0, 0x43, 0x64, 0x2e, 0x22, 0xf5, 0xdc, 0x0f, 0x2e, 0x76, 0x1d, 0xd7, 0x90, 0xf5, 0x65, 0x79, 0x01, 0x32, - 0x42, 0xce, 0xef, 0x41, 0xb4, 0x08, 0xb5, 0xdd, 0xc1, 0x66, 0x9a, 0x83, 0x04, 0x85, 0x9b, 0x9c, 0xc7, 0x6e, 0xa0, - 0xaa, 0x7e, 0x11, 0xaa, 0x26, 0x2c, 0xd3, 0xe9, 0x6e, 0x1b, 0x69, 0xad, 0x7e, 0x6f, 0x53, 0x5c, 0xef, 0xe0, 0x40, - 0xd5, 0x98, 0x86, 0x42, 0x50, 0x9e, 0x69, 0xca, 0x75, 0xdd, 0x7f, 0x17, 0x54, 0xb8, 0x86, 0xaf, 0x24, 0x66, 0x01, - 0x0c, 0x01, 0x6a, 0x3d, 0x5f, 0xf3, 0x7c, 0x25, 0x9e, 0xb6, 0x6a, 0x05, 0xf7, 0x0e, 0xd9, 0xb6, 0x86, 0x2a, 0x02, - 0xd3, 0x67, 0x36, 0xa1, 0xf1, 0x85, 0x64, 0xd0, 0xc3, 0xf4, 0x52, 0x2b, 0xac, 0x4b, 0xe2, 0xae, 0x6e, 0x80, 0xdd, - 0x1f, 0x67, 0xbd, 0x27, 0xfb, 0x27, 0x2e, 0x56, 0x3c, 0x3e, 0x1f, 0x8d, 0x5c, 0x54, 0x3a, 0x0f, 0x6b, 0xd6, 0xdd, - 0xff, 0x71, 0xf6, 0xf5, 0x8b, 0xce, 0xd7, 0x55, 0xe3, 0x0c, 0x88, 0x48, 0x67, 0x58, 0x18, 0x51, 0x65, 0xc1, 0x6b, - 0x66, 0x34, 0x0a, 0xb3, 0xcd, 0xd3, 0x39, 0xb3, 0xa7, 0x53, 0x4c, 0x29, 0x8d, 0x81, 0x38, 0xf1, 0x4a, 0xe9, 0x45, - 0x4a, 0xaf, 0xa9, 0xb9, 0xfe, 0x71, 0xcd, 0x60, 0x6b, 0x5a, 0x44, 0xf9, 0x2c, 0x13, 0x3a, 0xd5, 0x44, 0xb3, 0x5a, - 0x6b, 0x4a, 0x97, 0x72, 0x0e, 0xb6, 0x09, 0x71, 0xa7, 0xe4, 0x5c, 0x53, 0x7a, 0x95, 0x97, 0xd8, 0xb5, 0x00, 0xd8, - 0x08, 0xd9, 0x70, 0x43, 0x79, 0xd0, 0xc1, 0x9d, 0x4d, 0xb0, 0xe1, 0x2e, 0x0a, 0x5c, 0xf7, 0xdc, 0xe0, 0x49, 0x7a, - 0x8b, 0x1b, 0x37, 0x76, 0x6c, 0xc4, 0xd7, 0x67, 0x31, 0x70, 0xc5, 0xa1, 0xb3, 0x8c, 0x16, 0xc5, 0x46, 0x04, 0x54, - 0x8b, 0x88, 0xdd, 0xba, 0xb6, 0xbb, 0xa1, 0x17, 0xdc, 0xc1, 0xb0, 0xc3, 0x24, 0xc0, 0x55, 0xcc, 0x5a, 0xd7, 0xa2, - 0xa3, 0x11, 0x8d, 0x2a, 0x67, 0x3b, 0x44, 0x1f, 0x47, 0x2c, 0x15, 0x10, 0x84, 0x93, 0xd1, 0x31, 0xf7, 0x4d, 0x9e, - 0x51, 0x17, 0x99, 0x7c, 0x5a, 0x0d, 0xbf, 0x96, 0xff, 0xeb, 0xe1, 0x51, 0x3d, 0x36, 0x61, 0xd1, 0xa3, 0x2c, 0x16, - 0xc6, 0x17, 0xd4, 0x28, 0x6f, 0x22, 0x32, 0x97, 0xce, 0x9e, 0x4d, 0x1b, 0xe8, 0x61, 0xdb, 0x64, 0xde, 0xfd, 0xfa, - 0xa0, 0xdb, 0x29, 0x5d, 0xec, 0x42, 0x77, 0x0f, 0xdd, 0x25, 0xb2, 0xd5, 0x1e, 0xb4, 0x9a, 0x65, 0x5f, 0xd2, 0xae, - 0xd7, 0x7d, 0xda, 0x75, 0xb1, 0xba, 0xc8, 0x01, 0x95, 0x15, 0x33, 0x88, 0xc0, 0xfd, 0xfc, 0x77, 0x4f, 0xa5, 0xd9, - 0xf9, 0xc3, 0xe0, 0x79, 0xdc, 0xed, 0xb8, 0xd8, 0x2d, 0x44, 0x3e, 0xfd, 0x82, 0x29, 0xec, 0xb9, 0xd8, 0x8d, 0xd2, - 0xbc, 0xa0, 0xf6, 0x1c, 0x94, 0x3a, 0xfb, 0xf7, 0x4f, 0x42, 0x41, 0x34, 0xe5, 0xb4, 0x28, 0x1c, 0xbb, 0x7f, 0x4d, - 0x4a, 0x9f, 0x61, 0x98, 0x6b, 0x29, 0xae, 0xa0, 0x42, 0xe2, 0x45, 0xdd, 0xb1, 0x60, 0x53, 0x95, 0x2a, 0x5b, 0x21, - 0x36, 0x29, 0x02, 0x2a, 0xc6, 0xa6, 0xb4, 0xab, 0xcf, 0x8e, 0xbc, 0x66, 0xeb, 0xa9, 0x81, 0x55, 0x54, 0x7e, 0x75, - 0x80, 0x46, 0xc9, 0x84, 0x65, 0x17, 0x6b, 0x4a, 0xc3, 0xdb, 0x35, 0xa5, 0xa0, 0xb2, 0x55, 0xd0, 0xe9, 0xfb, 0x7f, - 0x3e, 0x8f, 0xf5, 0x5a, 0xf1, 0xb1, 0x41, 0x8c, 0xa5, 0x73, 0xf3, 0x33, 0x90, 0x5a, 0xcb, 0x20, 0x7b, 0xf8, 0xf5, - 0xc3, 0x41, 0xc9, 0x97, 0x0c, 0x57, 0xf5, 0xf2, 0xf7, 0xcd, 0x10, 0x4a, 0x5b, 0x10, 0x41, 0x48, 0xbf, 0x68, 0xae, - 0xf4, 0xf6, 0xf3, 0x04, 0x67, 0x69, 0x55, 0x7f, 0xc7, 0xd2, 0xeb, 0x7b, 0x04, 0x96, 0xd7, 0x7e, 0x4d, 0xb1, 0x56, - 0x7c, 0xaa, 0xf5, 0x8f, 0x52, 0x36, 0xa9, 0x49, 0x60, 0x15, 0x4c, 0xa9, 0xf1, 0x40, 0x3a, 0x99, 0xdd, 0x89, 0x52, - 0x7d, 0x2e, 0xe0, 0x90, 0x2c, 0xdc, 0x43, 0x32, 0xe3, 0xf4, 0x22, 0xcd, 0x6f, 0x96, 0x6f, 0x56, 0xdb, 0x5c, 0x39, - 0x61, 0xe3, 0xc4, 0x3a, 0xf9, 0x46, 0x49, 0xb5, 0x08, 0xf7, 0x0e, 0x50, 0xfe, 0xeb, 0xbf, 0xf8, 0xfe, 0xbf, 0xfe, - 0xcb, 0x67, 0xab, 0x42, 0xf7, 0xe5, 0x25, 0x16, 0x75, 0xb7, 0x9b, 0x77, 0xd7, 0xfa, 0x91, 0x9a, 0x38, 0x5f, 0x5f, - 0x67, 0x65, 0x11, 0xe0, 0xfd, 0xca, 0x12, 0xac, 0x14, 0xaa, 0xdd, 0xe7, 0xfc, 0x1a, 0xc0, 0x60, 0x5e, 0x9f, 0x85, - 0x0c, 0x2a, 0xfd, 0x5d, 0xa0, 0x5d, 0xa2, 0xe0, 0x41, 0x2b, 0xf2, 0xeb, 0x31, 0xfc, 0xb9, 0x39, 0xfc, 0x9d, 0xe0, - 0x6b, 0xff, 0x44, 0x7a, 0x79, 0x59, 0xa5, 0x38, 0xda, 0x4d, 0xe1, 0x02, 0x85, 0xe1, 0x4a, 0x89, 0x56, 0x3c, 0x82, - 0x0e, 0x1a, 0xc8, 0x03, 0x9a, 0x24, 0xbd, 0x7c, 0x0d, 0xb7, 0x26, 0x1d, 0x5d, 0x71, 0xe3, 0xe0, 0xbd, 0x47, 0x38, - 0x40, 0x17, 0xcd, 0x59, 0xc9, 0x4e, 0x57, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0xe2, 0xf4, 0x52, 0x5b, 0x9b, - 0x27, 0xca, 0x0d, 0x13, 0x2c, 0x93, 0xb6, 0x76, 0xcf, 0x34, 0x90, 0x8e, 0x9d, 0x0f, 0x12, 0x5f, 0xb2, 0x32, 0xad, - 0xad, 0x7b, 0xe9, 0xea, 0x02, 0x3b, 0xa2, 0x62, 0x3f, 0xd7, 0x61, 0x7a, 0xfd, 0x30, 0xc6, 0xb7, 0x59, 0xa0, 0x2e, - 0x9c, 0xc5, 0x3f, 0x5a, 0x25, 0x58, 0xb4, 0x16, 0xeb, 0xf4, 0x81, 0x9b, 0x50, 0x50, 0x7e, 0x91, 0x40, 0x96, 0x15, - 0xff, 0x0c, 0x73, 0x82, 0x95, 0xc6, 0x54, 0xfe, 0x65, 0x44, 0xdf, 0x52, 0xfd, 0x0f, 0xe2, 0x54, 0x0c, 0x52, 0x24, - 0x61, 0x28, 0x6b, 0x11, 0xfe, 0x3f, 0xdf, 0xfa, 0x77, 0xc3, 0xb7, 0xee, 0x1f, 0xa2, 0x71, 0x00, 0xfb, 0x8b, 0x17, - 0xf2, 0xdf, 0x37, 0xbb, 0xe3, 0x92, 0xdd, 0xfd, 0x0a, 0x46, 0xc7, 0xff, 0x31, 0x8c, 0x4e, 0xda, 0xc8, 0x86, 0xd3, - 0xe9, 0x8b, 0x77, 0xec, 0xf7, 0xe1, 0x4d, 0x78, 0x57, 0xef, 0xab, 0xf4, 0xf2, 0xf8, 0x26, 0xbc, 0xab, 0x17, 0x61, - 0x33, 0xbb, 0x58, 0xee, 0x63, 0xe8, 0xbe, 0x7d, 0xe3, 0x06, 0xee, 0xdb, 0xaf, 0xbf, 0x76, 0xf1, 0x65, 0x41, 0xc5, - 0x10, 0x0a, 0xc9, 0xf6, 0x7c, 0x6b, 0xb9, 0x22, 0xb8, 0x51, 0x60, 0x8a, 0x32, 0xd4, 0x86, 0x8b, 0x06, 0x30, 0xac, - 0xb8, 0xc8, 0x33, 0x1b, 0x9a, 0x77, 0x60, 0xd9, 0x7f, 0x29, 0x38, 0xb2, 0x97, 0x15, 0x78, 0x64, 0xe9, 0x32, 0x40, - 0xb2, 0xb0, 0x01, 0x51, 0x7d, 0x1f, 0xd1, 0xfd, 0xfc, 0xbf, 0xbe, 0x73, 0x41, 0x5d, 0x25, 0x12, 0x0d, 0xd3, 0xcb, - 0x2f, 0x11, 0x1f, 0x6a, 0xb0, 0xda, 0x63, 0x67, 0xdc, 0x9d, 0x61, 0xb9, 0x3d, 0x8f, 0x76, 0x76, 0xd8, 0xd0, 0xc5, - 0xf2, 0x12, 0xa8, 0x72, 0x9d, 0x70, 0xe1, 0xf0, 0x27, 0x87, 0x3f, 0x45, 0xcd, 0xa8, 0x59, 0x36, 0xe2, 0x21, 0xa7, - 0xf1, 0x66, 0x26, 0x5d, 0x5d, 0x9e, 0xa4, 0x49, 0x43, 0x65, 0x77, 0x17, 0x17, 0x32, 0xaf, 0x69, 0xc2, 0x40, 0x1f, - 0xdd, 0xb2, 0x3f, 0x11, 0xa4, 0x6f, 0x5b, 0xab, 0xbe, 0x30, 0x60, 0x23, 0x9c, 0x12, 0x5e, 0x25, 0x52, 0xc0, 0x95, - 0x9d, 0x3a, 0xf5, 0x04, 0xbb, 0x48, 0x7a, 0xdd, 0x63, 0x32, 0x90, 0x39, 0x15, 0xdf, 0x64, 0xc2, 0x8b, 0x7d, 0xc1, - 0xd9, 0xc4, 0x43, 0xb8, 0xdb, 0x41, 0xc8, 0x38, 0x1b, 0x62, 0x32, 0xd8, 0x62, 0xc5, 0x9b, 0xf0, 0x8d, 0x17, 0xcb, - 0x5b, 0xbe, 0xe4, 0x77, 0x81, 0xe0, 0x04, 0xe6, 0xb3, 0xd9, 0x68, 0x44, 0xb9, 0x67, 0x4e, 0x17, 0xfe, 0x7e, 0x1f, - 0x0e, 0x30, 0xc3, 0xdb, 0xe7, 0xa1, 0x08, 0xbf, 0x63, 0xf4, 0xc6, 0x2b, 0x50, 0x3f, 0xaf, 0x6f, 0x7e, 0x8c, 0xf1, - 0x4c, 0x26, 0x2e, 0x14, 0x54, 0x7c, 0x93, 0x89, 0xbd, 0x9e, 0x37, 0xfb, 0xfd, 0x3e, 0x8e, 0xe1, 0x3e, 0x0d, 0x93, - 0x32, 0xae, 0x2e, 0x42, 0xf9, 0xc8, 0x32, 0x71, 0xa8, 0xce, 0x78, 0x16, 0x48, 0xbb, 0x0f, 0xab, 0x74, 0x1b, 0x27, - 0xac, 0x3a, 0x8c, 0xc9, 0x20, 0xd9, 0x25, 0xea, 0xc4, 0xa7, 0xbc, 0xc2, 0xf7, 0x24, 0x09, 0xf9, 0x09, 0x9c, 0x26, - 0x07, 0x40, 0xaf, 0x44, 0x1e, 0x7a, 0x49, 0xf5, 0x99, 0x28, 0xaf, 0xfd, 0xe3, 0x6e, 0x7b, 0x8c, 0x65, 0xc6, 0x4d, - 0x5d, 0xd4, 0x86, 0xa2, 0x0b, 0xbb, 0x88, 0xec, 0x6e, 0xb7, 0x31, 0xec, 0xc1, 0xfe, 0x5a, 0x1f, 0xad, 0x59, 0xba, - 0xd6, 0x0d, 0x0f, 0xa7, 0x55, 0xdc, 0xe0, 0x24, 0xe4, 0x9c, 0x51, 0xee, 0x78, 0x2f, 0x7f, 0x41, 0xc1, 0xbf, 0xfe, - 0xcb, 0xfa, 0xf8, 0x81, 0x0e, 0x19, 0x38, 0x90, 0xb9, 0xd2, 0x92, 0xb9, 0xde, 0xc4, 0x8d, 0x54, 0x43, 0xd7, 0x84, - 0x3b, 0xf6, 0x0e, 0x3b, 0x9d, 0x8e, 0x0e, 0x09, 0x74, 0xd5, 0x4f, 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x90, 0x91, 0x6c, - 0xe2, 0xaa, 0x00, 0xe5, 0x61, 0x67, 0x7a, 0xeb, 0x0e, 0x60, 0x3b, 0x68, 0x28, 0xde, 0xd3, 0x29, 0x0d, 0xc5, 0x17, - 0x8d, 0xcf, 0x65, 0x93, 0x6a, 0xf8, 0xae, 0x19, 0xba, 0x1e, 0x77, 0x69, 0xd0, 0x83, 0xe5, 0x41, 0x3f, 0xb0, 0x89, - 0xbc, 0x17, 0x6a, 0xd3, 0xa8, 0xd2, 0x53, 0xdd, 0x18, 0x53, 0xa8, 0x16, 0xae, 0x23, 0x31, 0x9e, 0xe4, 0x69, 0x4c, - 0x39, 0x71, 0xa9, 0x3f, 0xf6, 0x9d, 0xa7, 0x9d, 0x4e, 0x07, 0xb7, 0xf6, 0x0f, 0x3a, 0x1d, 0x7c, 0xf0, 0xb8, 0x83, - 0x5b, 0xf0, 0xc7, 0xf7, 0xfd, 0x25, 0x18, 0xee, 0x8b, 0xda, 0x76, 0x3b, 0x9c, 0x4e, 0x34, 0x80, 0xf7, 0x86, 0x15, - 0xeb, 0x3d, 0x01, 0xb7, 0x57, 0xeb, 0x7d, 0xaf, 0x24, 0x9b, 0xbe, 0x3d, 0x41, 0xe7, 0xba, 0x4a, 0x7f, 0x61, 0x51, - 0x07, 0x4d, 0xa9, 0xba, 0x55, 0xf0, 0x1b, 0x4d, 0x08, 0x81, 0x73, 0x02, 0x57, 0xa3, 0xca, 0x78, 0x29, 0x64, 0x1e, - 0xc1, 0xd7, 0xd7, 0x44, 0xc8, 0x32, 0xf8, 0x30, 0x97, 0x89, 0x9a, 0x1a, 0x46, 0x55, 0x2c, 0x65, 0xf4, 0x3e, 0x52, - 0x61, 0xe9, 0x75, 0x04, 0x71, 0xfe, 0x08, 0xe1, 0xf0, 0x21, 0x0d, 0xf4, 0x0a, 0x42, 0xfd, 0xe4, 0x21, 0xf5, 0x0d, - 0xf6, 0xcf, 0x1f, 0xc9, 0x44, 0xa8, 0xad, 0x68, 0xb1, 0xd8, 0x0a, 0x17, 0x8b, 0xad, 0xe4, 0xe1, 0x33, 0x54, 0xcb, - 0x6b, 0x8e, 0x58, 0xc0, 0xb5, 0xa2, 0x0a, 0xe8, 0x6f, 0xa0, 0x3c, 0x88, 0xb0, 0x02, 0x49, 0x3d, 0x85, 0x58, 0x0f, - 0xa8, 0x1e, 0x93, 0x72, 0x09, 0x29, 0x31, 0x89, 0x94, 0x7d, 0xbe, 0x58, 0x68, 0xe2, 0xc7, 0x33, 0x12, 0x56, 0x45, - 0x5d, 0x17, 0x4f, 0x49, 0x52, 0x3d, 0xba, 0x12, 0xe4, 0xa9, 0xe6, 0x52, 0x35, 0xc4, 0x37, 0x21, 0xcf, 0x6c, 0x80, - 0xdf, 0xe4, 0x8e, 0x1e, 0xd6, 0x99, 0xf2, 0xfc, 0x9a, 0x41, 0xc2, 0xcd, 0xd2, 0xc0, 0x13, 0x02, 0xb7, 0x8a, 0xf5, - 0xed, 0x50, 0xb8, 0xd5, 0xc1, 0x07, 0xc3, 0x67, 0xe1, 0x0a, 0xcb, 0x6a, 0x82, 0x41, 0xac, 0xe7, 0x16, 0xcc, 0xcc, - 0xb4, 0xde, 0x87, 0x37, 0xc1, 0xd4, 0x3c, 0xbc, 0x50, 0xb9, 0x3d, 0xc1, 0xa4, 0x3a, 0xb6, 0xf3, 0x8e, 0xbc, 0x81, - 0xd8, 0x8f, 0x6b, 0xf8, 0x36, 0x5c, 0xe2, 0xa9, 0x78, 0xdc, 0xfb, 0x57, 0xa7, 0x34, 0xe4, 0x51, 0xf2, 0x2e, 0xe4, - 0xe1, 0xa4, 0xe8, 0x8f, 0xcc, 0x15, 0x61, 0x86, 0x02, 0x2e, 0x46, 0x32, 0xbb, 0x2a, 0x8b, 0xee, 0x5c, 0x1c, 0x23, - 0x5c, 0xbf, 0x57, 0x10, 0x28, 0x3f, 0xb7, 0x8b, 0x67, 0xf6, 0x2b, 0x58, 0x67, 0x17, 0x4f, 0x10, 0x56, 0x49, 0x4b, - 0xef, 0x7e, 0xcb, 0x74, 0x25, 0x0c, 0xf9, 0x35, 0xc1, 0xc8, 0xaf, 0x3f, 0xa1, 0x67, 0x12, 0x98, 0x3e, 0x2c, 0x25, - 0x30, 0xad, 0x41, 0xa3, 0xc3, 0x69, 0x31, 0xcd, 0xb3, 0x82, 0xba, 0xf8, 0x03, 0xb4, 0x53, 0xf7, 0x3c, 0xdb, 0x0d, - 0x57, 0x68, 0xae, 0x6a, 0x2a, 0xdf, 0xa8, 0x76, 0x10, 0xd4, 0xf9, 0xf0, 0x97, 0x2a, 0x8e, 0x6f, 0xe2, 0x3b, 0x32, - 0xcb, 0x9d, 0xd1, 0x0d, 0x89, 0xb8, 0x9c, 0x7e, 0x36, 0x11, 0x37, 0x7d, 0x50, 0x22, 0xae, 0xbc, 0x3e, 0xe5, 0x37, - 0x4d, 0xc4, 0x65, 0xd4, 0x4a, 0xc4, 0x05, 0x39, 0xf7, 0xf5, 0x83, 0xf2, 0x39, 0x4d, 0xf6, 0x5d, 0x7e, 0x53, 0x90, - 0xae, 0x8e, 0x81, 0xa4, 0xf9, 0x18, 0x92, 0x39, 0xff, 0xf1, 0xb9, 0x99, 0x69, 0x3e, 0xb6, 0x33, 0x33, 0xe1, 0xab, - 0x27, 0x40, 0x76, 0x38, 0x27, 0x73, 0xf7, 0xc7, 0xdb, 0xee, 0xb3, 0xb3, 0x6e, 0x7f, 0xaf, 0x3b, 0x71, 0x03, 0x17, - 0x9c, 0x8e, 0xb2, 0xa0, 0xd3, 0xdf, 0xdb, 0x83, 0x82, 0x1b, 0xab, 0xa0, 0x07, 0x05, 0xcc, 0x2a, 0x38, 0x80, 0x82, - 0xc8, 0x2a, 0x78, 0x0c, 0x05, 0xb1, 0x55, 0xf0, 0x04, 0x0a, 0xae, 0xdd, 0xf2, 0x8c, 0x55, 0xd9, 0xc6, 0x4f, 0x90, - 0xbc, 0x1e, 0x71, 0x2b, 0x6f, 0x1e, 0x0d, 0x8f, 0x88, 0xa9, 0xf2, 0xa4, 0xba, 0x56, 0xa2, 0xb5, 0x6f, 0x6e, 0x41, - 0xbc, 0xfc, 0xdd, 0x25, 0xb0, 0xd6, 0x08, 0xae, 0x47, 0x80, 0x98, 0xa4, 0xaa, 0xb9, 0x67, 0x5e, 0xbb, 0x41, 0x95, - 0x92, 0xdb, 0xc1, 0x3d, 0x93, 0x94, 0x1b, 0xb8, 0x48, 0xf2, 0x25, 0xf5, 0xe2, 0x60, 0x37, 0xd6, 0xdd, 0xc2, 0x05, - 0x83, 0xf5, 0xed, 0x9e, 0x7b, 0x08, 0x4f, 0x8c, 0x02, 0x44, 0x3d, 0xf8, 0xba, 0xc3, 0x07, 0x36, 0xa1, 0x66, 0xbf, - 0x98, 0x01, 0x1c, 0x99, 0xb6, 0xdc, 0x8f, 0x6a, 0xc5, 0xe8, 0x1d, 0x1e, 0xd5, 0x17, 0xca, 0x7e, 0x20, 0xea, 0x82, - 0xbe, 0x1c, 0xab, 0x30, 0xd7, 0x14, 0x8b, 0x70, 0x1c, 0x40, 0xda, 0x26, 0x64, 0x8c, 0x04, 0x23, 0x42, 0x48, 0x67, - 0x38, 0x0b, 0xde, 0xe1, 0x9b, 0x84, 0x66, 0xc1, 0xa4, 0xec, 0x57, 0xeb, 0xaf, 0xb2, 0x46, 0x3f, 0x54, 0xb7, 0x90, - 0x4b, 0x9a, 0xa8, 0xdf, 0x2a, 0x28, 0x5b, 0x15, 0xed, 0x6c, 0xc8, 0x33, 0xb4, 0x94, 0x9d, 0x51, 0x9a, 0xdf, 0xb4, - 0x40, 0xdc, 0xaf, 0xcd, 0x3d, 0x84, 0xb9, 0x55, 0xb9, 0x87, 0xaf, 0x00, 0xd6, 0xea, 0xe9, 0x43, 0x38, 0xae, 0x7e, - 0xbf, 0xa6, 0x45, 0x11, 0x8e, 0x75, 0xcd, 0xcd, 0xb9, 0x86, 0x12, 0x44, 0x3b, 0xcf, 0xd0, 0x00, 0x01, 0x09, 0x81, - 0x80, 0x10, 0x08, 0xe8, 0xea, 0xfc, 0x40, 0x98, 0x79, 0x33, 0xb5, 0x50, 0xa2, 0xaa, 0x59, 0x24, 0xc2, 0x71, 0x5d, - 0x70, 0x34, 0xe5, 0x54, 0x27, 0x2d, 0x02, 0x16, 0xcb, 0xa3, 0x36, 0x14, 0xa8, 0xd7, 0x1b, 0x52, 0x08, 0x0d, 0x77, - 0xd9, 0x9c, 0x48, 0xe8, 0x98, 0x14, 0x42, 0xfb, 0xd8, 0x4b, 0x75, 0xe6, 0x65, 0x35, 0x71, 0xed, 0xab, 0x6e, 0x04, - 0xff, 0xe9, 0xb4, 0xb8, 0xaf, 0x46, 0xa3, 0xd1, 0xbd, 0x29, 0x85, 0x5f, 0xc5, 0x23, 0xda, 0xa3, 0x07, 0x7d, 0x38, - 0x12, 0xd1, 0xd2, 0x89, 0x68, 0xdd, 0x52, 0xe2, 0x6e, 0xfe, 0xb0, 0xca, 0x90, 0xb3, 0x26, 0x92, 0xf9, 0xc3, 0xd3, - 0x0b, 0xcb, 0x29, 0xa7, 0xf3, 0x49, 0xc8, 0xc7, 0x2c, 0x0b, 0x3a, 0xa5, 0x7f, 0xad, 0xf3, 0xf1, 0xbe, 0x3a, 0x3c, - 0x3c, 0x2c, 0xfd, 0xd8, 0x3c, 0x75, 0xe2, 0xb8, 0xf4, 0xa3, 0x79, 0x35, 0x8d, 0x4e, 0x67, 0x34, 0x2a, 0x7d, 0x66, - 0x0a, 0xf6, 0x7a, 0x51, 0xbc, 0xd7, 0x2b, 0xfd, 0x1b, 0xab, 0x46, 0xe9, 0x53, 0xfd, 0xc4, 0x69, 0xdc, 0x38, 0x57, - 0xf1, 0xa4, 0xd3, 0x29, 0x7d, 0x45, 0x68, 0x73, 0x88, 0xc9, 0xa9, 0x9f, 0x41, 0x38, 0x13, 0x79, 0x79, 0x59, 0x96, - 0xfd, 0x54, 0x78, 0x67, 0xdb, 0xfa, 0xce, 0x4a, 0xf5, 0x91, 0xc7, 0x12, 0x9d, 0xe3, 0xaf, 0xed, 0xcc, 0x39, 0x20, - 0x66, 0x99, 0x31, 0x97, 0x9a, 0xc4, 0xba, 0xc6, 0x6b, 0xa0, 0x2c, 0xf9, 0xfa, 0x6b, 0x92, 0xd6, 0x09, 0x75, 0xc0, - 0xc7, 0xa0, 0xa6, 0xba, 0x5a, 0x3d, 0xdb, 0x24, 0x3d, 0x8a, 0xcf, 0x4b, 0x8f, 0xab, 0x87, 0x08, 0x8f, 0xe2, 0x37, - 0x17, 0x1e, 0x99, 0x2d, 0x3c, 0x14, 0xeb, 0xb8, 0x11, 0xc4, 0x8d, 0x12, 0x1a, 0x7d, 0xba, 0xca, 0x6f, 0x5b, 0xb0, - 0x25, 0xb8, 0x2b, 0xc5, 0xca, 0xf5, 0xaf, 0x3d, 0x26, 0x60, 0x3a, 0xb3, 0xbe, 0x10, 0x29, 0x75, 0xfc, 0xb7, 0x19, - 0x71, 0xdf, 0x9a, 0xc0, 0x9e, 0x2a, 0x19, 0x8d, 0x88, 0xfb, 0x76, 0x34, 0x72, 0xcd, 0xcd, 0x3b, 0xa1, 0xa0, 0xb2, - 0xd6, 0x9b, 0x46, 0x89, 0xac, 0x05, 0x86, 0x7e, 0x5d, 0x66, 0x17, 0xe8, 0xbc, 0x3b, 0x3b, 0xc7, 0x4e, 0xbf, 0x89, - 0x59, 0x01, 0x5b, 0x0d, 0x3e, 0x5c, 0xd9, 0xbc, 0xf9, 0x3f, 0x6b, 0x7c, 0xa6, 0xa9, 0x02, 0x78, 0xcd, 0xb7, 0xa5, - 0x96, 0xaf, 0x9d, 0x1b, 0x53, 0xa3, 0xe2, 0x3f, 0xbb, 0xfb, 0x26, 0xf6, 0x6e, 0x04, 0x2a, 0x59, 0xf1, 0x36, 0x5b, - 0xba, 0x52, 0x42, 0xc1, 0x48, 0x88, 0x3d, 0xad, 0x52, 0xe4, 0xe3, 0x71, 0x2a, 0x4f, 0xaa, 0x34, 0x0c, 0x6e, 0xd5, - 0x7c, 0xd8, 0x98, 0x6f, 0x60, 0x37, 0xd4, 0xdf, 0xee, 0x90, 0x1f, 0x33, 0x56, 0x47, 0x91, 0xaf, 0xf5, 0x57, 0x6d, - 0x65, 0x4c, 0x70, 0xae, 0x79, 0xfc, 0x5c, 0x1d, 0x60, 0x15, 0x98, 0xc5, 0xaa, 0x39, 0x8b, 0xcb, 0x52, 0x1f, 0xfd, - 0x8f, 0x59, 0x31, 0x05, 0xed, 0x49, 0xb5, 0xa4, 0x9f, 0x63, 0xe1, 0xc5, 0x8d, 0x95, 0xdc, 0xd6, 0x58, 0xae, 0xd2, - 0xd8, 0x69, 0x2a, 0x5b, 0xe8, 0x46, 0x94, 0xae, 0x36, 0xd9, 0x0c, 0x12, 0x5d, 0x47, 0xe1, 0x53, 0xa5, 0xdd, 0x59, - 0x33, 0x84, 0xcc, 0x9f, 0x6a, 0x41, 0xcc, 0x2b, 0x53, 0x50, 0xda, 0x56, 0x96, 0x7c, 0xa3, 0xb0, 0x25, 0x53, 0xc5, - 0x8a, 0x69, 0x98, 0x19, 0x63, 0x4e, 0xf1, 0x83, 0xed, 0x79, 0xbd, 0xf2, 0xa5, 0x6b, 0xc0, 0x56, 0xc4, 0x3b, 0x38, - 0x6a, 0x43, 0x83, 0x81, 0xd3, 0x00, 0x3d, 0x5b, 0xc9, 0x30, 0xbb, 0x3f, 0xd7, 0xfb, 0xd3, 0xa5, 0x5f, 0xdc, 0x60, - 0xbf, 0xb8, 0x71, 0x7e, 0x3f, 0x6f, 0xdd, 0xd0, 0xab, 0x4f, 0x4c, 0xb4, 0x44, 0x38, 0x6d, 0x81, 0xf7, 0x54, 0x66, - 0x86, 0x68, 0xf6, 0x2c, 0x75, 0x74, 0x65, 0xfa, 0xf5, 0x67, 0x05, 0xa4, 0x84, 0x4b, 0x33, 0x2a, 0xc8, 0xf2, 0x8c, - 0xf6, 0x9b, 0x67, 0x03, 0xed, 0x0c, 0x63, 0x83, 0xad, 0xf3, 0x79, 0x0e, 0x29, 0xe4, 0xe2, 0x2e, 0xe8, 0x68, 0xb6, - 0xde, 0x31, 0xe9, 0xc3, 0x9d, 0xb5, 0xf5, 0x03, 0x8d, 0xdc, 0x5d, 0x29, 0xbd, 0xf8, 0x6a, 0x1a, 0xf5, 0xa6, 0x34, - 0xe8, 0xcf, 0x9d, 0x94, 0x83, 0x7c, 0x12, 0xf3, 0xbf, 0x75, 0xc4, 0x70, 0xb9, 0x58, 0x9e, 0x94, 0x7b, 0x08, 0x64, - 0x41, 0x38, 0x12, 0x94, 0xe3, 0x87, 0xd4, 0xbc, 0x92, 0x97, 0x5a, 0xcc, 0x41, 0xcc, 0x04, 0xdd, 0xc3, 0xe9, 0xed, - 0xc3, 0xbb, 0xbf, 0x7f, 0xfa, 0xa5, 0xc6, 0x91, 0xb9, 0xe4, 0xd5, 0x75, 0xfb, 0xb0, 0x11, 0xd2, 0xf0, 0x2e, 0x60, - 0x99, 0x94, 0x79, 0x57, 0x90, 0x14, 0xd2, 0x9f, 0xe6, 0xfa, 0xc8, 0x27, 0xa7, 0xa9, 0xfc, 0xae, 0xbb, 0x5e, 0x8a, - 0xbd, 0xc7, 0xd3, 0x5b, 0xb3, 0x1a, 0xdd, 0xa5, 0xa3, 0x9c, 0xbf, 0xe9, 0x89, 0xcd, 0xcd, 0x47, 0x44, 0x9b, 0xa7, - 0x0e, 0x0f, 0xa6, 0xb7, 0x7d, 0x25, 0x68, 0x5b, 0x5c, 0x41, 0xd5, 0x99, 0xde, 0xda, 0x67, 0x56, 0xeb, 0x8e, 0x1c, - 0x7f, 0xaf, 0x70, 0x68, 0x58, 0xd0, 0x3e, 0x7c, 0xc6, 0x8a, 0x45, 0x61, 0xaa, 0x85, 0xf9, 0x84, 0xc5, 0x71, 0x4a, - 0xfb, 0x46, 0x5e, 0x3b, 0xdd, 0xc7, 0x70, 0xe4, 0xd3, 0x5e, 0xb2, 0xe6, 0xaa, 0x58, 0xc8, 0xab, 0xf0, 0x14, 0x5e, - 0x15, 0x79, 0x0a, 0x1f, 0x91, 0x5c, 0x8b, 0x4e, 0x7d, 0x16, 0xb2, 0x53, 0x23, 0x4f, 0xfe, 0x6e, 0xce, 0xe5, 0xa0, - 0xf3, 0x4f, 0x7d, 0xb9, 0xe0, 0x9d, 0xbe, 0xc8, 0xa7, 0x41, 0x6b, 0xaf, 0x39, 0x11, 0x78, 0x55, 0x4d, 0x01, 0xaf, - 0x99, 0x16, 0x06, 0x69, 0xa5, 0xf8, 0xb4, 0xe3, 0x77, 0x75, 0x99, 0xec, 0x00, 0x8c, 0xd0, 0xaa, 0xa8, 0x6c, 0x4e, - 0xe6, 0x1f, 0xb3, 0x5b, 0x9e, 0xae, 0xdf, 0x2d, 0x4f, 0xcd, 0x6e, 0xb9, 0x9f, 0x62, 0xbf, 0x1a, 0x75, 0xe1, 0xbf, - 0x7e, 0x3d, 0xa1, 0xa0, 0xe3, 0xec, 0x4d, 0x6f, 0x1d, 0xd0, 0xd3, 0x5a, 0xbd, 0xe9, 0xad, 0x3a, 0xb1, 0x0b, 0x89, - 0x6b, 0x1d, 0x38, 0xc3, 0x8a, 0x3b, 0x0e, 0x14, 0xc2, 0xff, 0x9d, 0xc6, 0xab, 0xee, 0x3e, 0xbc, 0x83, 0x56, 0x07, - 0xab, 0xef, 0x7a, 0xf7, 0x6f, 0xda, 0x20, 0xcb, 0x85, 0x17, 0x18, 0x6e, 0x8c, 0x7c, 0x11, 0x5e, 0x5d, 0xd1, 0x38, - 0x18, 0xe5, 0xd1, 0xac, 0xf8, 0x67, 0x0d, 0xbf, 0x46, 0xe2, 0xbd, 0x5b, 0x7a, 0xa9, 0x1f, 0xd3, 0x54, 0x9d, 0x1f, - 0x36, 0x3d, 0xcc, 0xab, 0x75, 0x0a, 0x8a, 0x28, 0x4c, 0xa9, 0xd7, 0xf3, 0xf7, 0xd7, 0x6c, 0x82, 0x7f, 0x93, 0xb5, - 0x59, 0x3b, 0x99, 0xbf, 0x17, 0x19, 0xf7, 0x22, 0xe1, 0x8b, 0x70, 0x60, 0xaf, 0x61, 0xe7, 0x70, 0x3d, 0xb8, 0x67, - 0x66, 0xa4, 0x73, 0x23, 0x14, 0xb4, 0xdc, 0x89, 0xe9, 0x28, 0x9c, 0xa5, 0xe2, 0xfe, 0x5e, 0x37, 0x51, 0xc6, 0x4a, - 0xaf, 0xf7, 0x30, 0xf4, 0xba, 0xee, 0x03, 0xb9, 0xf4, 0x57, 0x4f, 0xf7, 0xe1, 0x3f, 0x75, 0xf8, 0xe5, 0xaa, 0xd6, - 0xd5, 0x95, 0xd5, 0x0b, 0xba, 0xfa, 0x75, 0x43, 0x19, 0x57, 0x22, 0x5c, 0xea, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, - 0x83, 0xaa, 0x6b, 0x2d, 0xeb, 0x8b, 0x6a, 0x7f, 0x59, 0xe7, 0x0f, 0xac, 0x1b, 0x29, 0xcd, 0xb5, 0x59, 0x57, 0x7f, - 0xd7, 0x7e, 0xa5, 0xb2, 0xc1, 0xb8, 0xac, 0x7f, 0x4d, 0xae, 0x2a, 0x13, 0x45, 0xa5, 0xa2, 0x82, 0x95, 0x72, 0xad, - 0xac, 0x94, 0x9c, 0x92, 0xcb, 0xa3, 0xe1, 0xed, 0x24, 0x75, 0xae, 0xd5, 0xe5, 0x3b, 0xc4, 0xed, 0xfa, 0x1d, 0xd7, - 0x91, 0x4e, 0x3a, 0xf8, 0x06, 0x98, 0xfb, 0xf1, 0xc3, 0xd7, 0xad, 0x43, 0x77, 0x08, 0x9a, 0xd6, 0xf5, 0x58, 0x6a, - 0x76, 0xaf, 0xc2, 0x3b, 0xca, 0x2f, 0x7a, 0xda, 0x05, 0xaf, 0xf2, 0xc5, 0x65, 0x99, 0xd3, 0x73, 0x9d, 0xdb, 0x49, - 0x9a, 0x15, 0xc4, 0x4d, 0x84, 0x98, 0x06, 0xed, 0xf6, 0xcd, 0xcd, 0x8d, 0x7f, 0xb3, 0xe7, 0xe7, 0x7c, 0xdc, 0xee, - 0x75, 0x3a, 0x1d, 0xf8, 0x9c, 0x88, 0xeb, 0x5c, 0x33, 0x7a, 0xf3, 0x2c, 0xbf, 0x25, 0x6e, 0xc7, 0xe9, 0x38, 0xdd, - 0xde, 0xa1, 0xd3, 0xed, 0xed, 0xfb, 0x8f, 0x0f, 0xdd, 0xc1, 0xef, 0x1c, 0xe7, 0x28, 0xa6, 0xa3, 0x02, 0x7e, 0x38, - 0xce, 0x91, 0x54, 0xbc, 0xd4, 0x6f, 0xc7, 0xf1, 0xa3, 0xb4, 0x68, 0x75, 0x9d, 0xb9, 0x7e, 0x74, 0x1c, 0xb8, 0xa2, - 0x28, 0x70, 0xbe, 0x1a, 0xf5, 0x46, 0xfb, 0xa3, 0xa7, 0x7d, 0x5d, 0x5c, 0xfe, 0xae, 0x51, 0x1d, 0xab, 0x7f, 0x7b, - 0x56, 0xb3, 0x42, 0xf0, 0xfc, 0x13, 0xd5, 0xae, 0x7d, 0x07, 0x44, 0xcf, 0xda, 0xa6, 0xbd, 0xd5, 0x91, 0xba, 0x87, - 0x57, 0xd1, 0xa8, 0x57, 0x57, 0x97, 0x30, 0xb6, 0x2b, 0x20, 0x8f, 0xda, 0x06, 0xf4, 0x23, 0x1b, 0x4d, 0xdd, 0xd6, - 0x3a, 0x44, 0x75, 0x5d, 0x3d, 0xc7, 0xb1, 0x99, 0xdf, 0x11, 0x9c, 0x88, 0x37, 0xba, 0xaa, 0x84, 0xc0, 0x75, 0x62, - 0xe2, 0xbe, 0xee, 0xf6, 0x0e, 0x71, 0xb7, 0xfb, 0xd8, 0x7f, 0x7c, 0x18, 0x75, 0xf0, 0xbe, 0xbf, 0xdf, 0xda, 0xf3, - 0x1f, 0xe3, 0xc3, 0xd6, 0x21, 0x3e, 0x7c, 0x79, 0x18, 0xb5, 0xf6, 0xfd, 0x7d, 0xdc, 0x69, 0x1d, 0x42, 0x61, 0xeb, - 0xb0, 0x75, 0x78, 0xdd, 0xda, 0x3f, 0x8c, 0x3a, 0xb2, 0xb4, 0xe7, 0x1f, 0x1c, 0xb4, 0xba, 0x1d, 0xff, 0xe0, 0x00, - 0x1f, 0xf8, 0x8f, 0x1f, 0xb7, 0xba, 0x7b, 0xfe, 0xe3, 0xc7, 0xaf, 0x0e, 0x0e, 0xfd, 0x3d, 0x78, 0xb7, 0xb7, 0x17, - 0xed, 0xf9, 0xdd, 0x6e, 0x0b, 0xfe, 0xe0, 0x43, 0xbf, 0xa7, 0x7e, 0x74, 0xbb, 0xfe, 0x5e, 0x17, 0x77, 0xd2, 0x83, - 0x9e, 0xff, 0xf8, 0x29, 0x96, 0x7f, 0x65, 0x35, 0x2c, 0xff, 0x40, 0x37, 0xf8, 0xa9, 0xdf, 0x7b, 0xac, 0x7e, 0xc9, - 0x0e, 0xaf, 0xf7, 0x0f, 0x7f, 0x70, 0xdb, 0x1b, 0xe7, 0xd0, 0x55, 0x73, 0x38, 0x3c, 0xf0, 0xf7, 0xf6, 0xf0, 0x7e, - 0xd7, 0x3f, 0xdc, 0x4b, 0x5a, 0xfb, 0x3d, 0xff, 0xf1, 0x93, 0xa8, 0xd5, 0xf5, 0x9f, 0x3c, 0xc1, 0x9d, 0xd6, 0x9e, - 0xdf, 0xc3, 0x5d, 0x7f, 0x7f, 0x4f, 0xfe, 0xd8, 0xf3, 0x7b, 0xd7, 0x4f, 0x9e, 0xfa, 0x8f, 0x0f, 0x92, 0xc7, 0xfe, - 0xfe, 0x77, 0xfb, 0x87, 0x7e, 0x6f, 0x2f, 0xd9, 0x7b, 0xec, 0xf7, 0x9e, 0x5c, 0x3f, 0xf6, 0xf7, 0x93, 0x56, 0xef, - 0xf1, 0xbd, 0x2d, 0xbb, 0x3d, 0x1f, 0x70, 0x24, 0x5f, 0xc3, 0x0b, 0xac, 0x5f, 0xc0, 0xff, 0x89, 0x6c, 0xfb, 0x6f, - 0xd8, 0x4d, 0xb1, 0xda, 0xf4, 0xa9, 0x7f, 0xf8, 0x24, 0x52, 0xd5, 0xa1, 0xa0, 0x65, 0x6a, 0x40, 0x93, 0xeb, 0x96, - 0x1a, 0x56, 0x76, 0xd7, 0x32, 0x1d, 0x99, 0xff, 0xf5, 0x60, 0xd7, 0x2d, 0x18, 0x58, 0x8d, 0xfb, 0xff, 0xb4, 0x9f, - 0x6a, 0xc9, 0x8f, 0xda, 0x63, 0x45, 0xfa, 0xe3, 0xc1, 0xef, 0xd4, 0xb7, 0x82, 0x7e, 0x77, 0x89, 0xc3, 0x4d, 0x8e, - 0x8f, 0xf4, 0xf3, 0x8e, 0x8f, 0x84, 0x3e, 0xc4, 0xf3, 0x91, 0xfe, 0xe6, 0x9e, 0x8f, 0x70, 0xd9, 0x6d, 0x7e, 0x2b, - 0x56, 0x1c, 0x1c, 0xcb, 0x56, 0xf1, 0x37, 0xc2, 0x3b, 0xcb, 0xe1, 0xbb, 0xd4, 0x65, 0xff, 0x56, 0x90, 0x84, 0xda, - 0x7e, 0xa0, 0x1c, 0x58, 0xec, 0xad, 0x50, 0x3c, 0x36, 0xda, 0x84, 0x90, 0xf8, 0xf3, 0x08, 0xf9, 0xfe, 0x21, 0xf8, - 0x88, 0x7f, 0x73, 0x7c, 0x44, 0x36, 0x3e, 0x1a, 0x9e, 0x7c, 0xe9, 0x69, 0x90, 0x9e, 0x82, 0x53, 0xf9, 0xec, 0xc1, - 0x95, 0x1c, 0xbb, 0x6e, 0x9b, 0x5e, 0xcb, 0xc8, 0x9d, 0x0a, 0xae, 0xbf, 0xfc, 0x92, 0xa0, 0x83, 0xba, 0x7f, 0x87, - 0xb8, 0xda, 0x2d, 0x33, 0x95, 0x52, 0x47, 0x3f, 0x54, 0x42, 0xa9, 0xe7, 0x77, 0xfc, 0x4e, 0xe5, 0xd2, 0x81, 0x3b, - 0x97, 0xc8, 0x3c, 0x17, 0x61, 0xb0, 0xd5, 0xc5, 0x69, 0x3e, 0x86, 0x9b, 0x98, 0xe4, 0xb7, 0xe9, 0xe0, 0xc4, 0x43, - 0xa4, 0x3e, 0x0b, 0x08, 0xe9, 0x13, 0xda, 0xd1, 0x13, 0xf2, 0x4f, 0x7f, 0x86, 0x20, 0xa6, 0x89, 0x49, 0x4c, 0xc0, - 0xdb, 0xf1, 0x9a, 0xc6, 0x2c, 0xf4, 0x5c, 0x6f, 0xca, 0xe9, 0x88, 0xf2, 0xa2, 0xd5, 0xb8, 0x0c, 0x48, 0xde, 0x03, - 0x84, 0x5c, 0x0d, 0xe1, 0x88, 0xc3, 0xb7, 0x96, 0xc8, 0x99, 0xf6, 0x37, 0xba, 0xda, 0x00, 0x73, 0x4b, 0x6c, 0x4a, - 0x38, 0xc8, 0xda, 0x5a, 0x69, 0x73, 0x95, 0xd6, 0xd6, 0xf5, 0x7b, 0x07, 0xc8, 0x91, 0xc5, 0xf0, 0x15, 0x9b, 0xbf, - 0x7a, 0xad, 0xbd, 0xce, 0x3f, 0x21, 0xab, 0x59, 0xd5, 0xd1, 0xb9, 0x76, 0xb7, 0x65, 0xd5, 0xb7, 0x0e, 0x97, 0xc2, - 0xae, 0xae, 0xa2, 0x88, 0xaf, 0xd4, 0xdc, 0x5d, 0xd4, 0xcf, 0x74, 0xd2, 0x9c, 0xba, 0x6f, 0x70, 0xc4, 0xc6, 0x9e, - 0x75, 0x97, 0x45, 0xa6, 0xbe, 0x92, 0x03, 0x57, 0xe1, 0x23, 0x54, 0xd6, 0x55, 0x32, 0x34, 0x97, 0xd1, 0x16, 0x96, - 0x39, 0xd9, 0x62, 0xe1, 0x65, 0xe0, 0x22, 0x27, 0x16, 0x4e, 0xe1, 0x19, 0x35, 0x90, 0x9c, 0xe1, 0x0a, 0x20, 0x89, - 0x60, 0x92, 0xa9, 0x7f, 0xeb, 0x62, 0xf3, 0x43, 0x3b, 0xbe, 0xfc, 0x34, 0xcc, 0xc6, 0x40, 0x85, 0x61, 0x36, 0x5e, - 0x71, 0xab, 0xa9, 0x80, 0xd1, 0x52, 0x69, 0xdd, 0x55, 0xed, 0x3e, 0x2b, 0x9e, 0xdd, 0x7d, 0xd0, 0xd7, 0x69, 0xbb, - 0xe0, 0x9d, 0x96, 0xf1, 0x8d, 0xfa, 0xd3, 0x3f, 0xbb, 0xe4, 0xd1, 0xd1, 0x84, 0x8a, 0x50, 0x1d, 0x56, 0x03, 0x7d, - 0x02, 0x72, 0x59, 0x1c, 0x6d, 0x8d, 0xea, 0xa0, 0x3e, 0x51, 0x17, 0x08, 0x28, 0x51, 0x8f, 0x1d, 0x7d, 0x0f, 0x5d, - 0x4b, 0x2e, 0x0d, 0xe9, 0x62, 0xe5, 0x8f, 0x89, 0x42, 0x79, 0x1c, 0x99, 0x64, 0xb9, 0x3b, 0x78, 0x54, 0xe5, 0xba, - 0x6c, 0x5a, 0x84, 0x94, 0x65, 0x9f, 0xce, 0x38, 0x4d, 0xff, 0x99, 0x3c, 0x62, 0x51, 0x9e, 0x3d, 0x3a, 0x77, 0x51, - 0x5f, 0xf8, 0x09, 0xa7, 0x23, 0xf2, 0x08, 0x64, 0x7c, 0x20, 0xad, 0x0f, 0x60, 0x84, 0xbb, 0xb7, 0x93, 0x14, 0x4b, - 0x8d, 0xe9, 0x01, 0x0a, 0x91, 0x02, 0xd7, 0xed, 0x1d, 0xb8, 0x8e, 0xb2, 0x89, 0xe5, 0xef, 0x81, 0x12, 0xa7, 0x52, - 0x09, 0x70, 0xba, 0x3d, 0xff, 0x20, 0xe9, 0xf9, 0x4f, 0xaf, 0x9f, 0xf8, 0x87, 0x49, 0xf7, 0xc9, 0x75, 0x0b, 0xfe, - 0xed, 0xf9, 0x4f, 0xd3, 0x56, 0xcf, 0x7f, 0x0a, 0xff, 0x7f, 0xb7, 0xef, 0x1f, 0x24, 0xad, 0xae, 0x7f, 0x78, 0xbd, - 0xe7, 0xef, 0xbd, 0xea, 0xf6, 0xfc, 0x3d, 0xa7, 0xeb, 0xa8, 0x76, 0xc0, 0xae, 0x15, 0x77, 0x7e, 0xb4, 0xb4, 0x21, - 0xd6, 0x04, 0xe3, 0xd4, 0x81, 0x3b, 0x17, 0xcb, 0x33, 0xd2, 0xf6, 0xfe, 0xd4, 0xce, 0xba, 0xe7, 0x21, 0x87, 0xcf, - 0xa6, 0x36, 0xf7, 0x6e, 0xe3, 0x1d, 0x6e, 0xf0, 0x8b, 0x35, 0x43, 0x4c, 0x65, 0x04, 0xdc, 0xbe, 0xc8, 0x0d, 0x6e, - 0x41, 0x93, 0x5f, 0x99, 0x32, 0x97, 0xed, 0x6f, 0x26, 0x6d, 0x55, 0xd1, 0x5c, 0xe8, 0x2f, 0x99, 0x05, 0x93, 0xdf, - 0xf3, 0x93, 0x83, 0x7c, 0x13, 0x97, 0xcb, 0xe3, 0xc3, 0xb9, 0x3f, 0x9e, 0x5b, 0x77, 0xd9, 0xd1, 0x3a, 0xc8, 0x1f, - 0x33, 0xb8, 0x7d, 0xb0, 0x2c, 0x0d, 0xe8, 0x0d, 0x37, 0x6d, 0x8d, 0x25, 0xc9, 0x2f, 0x68, 0x31, 0x74, 0xa1, 0xc8, - 0x0d, 0x5c, 0xe9, 0xe2, 0x73, 0xab, 0x4f, 0xc7, 0x56, 0x84, 0x5d, 0x17, 0x60, 0x79, 0xe3, 0x04, 0xec, 0x5a, 0xc0, - 0x8f, 0x8b, 0x76, 0x76, 0x36, 0xee, 0x17, 0xa9, 0x40, 0xc2, 0x5c, 0xeb, 0x2f, 0x4e, 0xda, 0xac, 0xc8, 0xb5, 0x11, - 0x5d, 0xf5, 0x2b, 0x51, 0x88, 0x34, 0x9e, 0xae, 0x68, 0x28, 0xfc, 0x30, 0x53, 0x27, 0x08, 0x2c, 0x86, 0x85, 0xbb, - 0x74, 0x0f, 0x95, 0xb9, 0x08, 0x55, 0x52, 0x98, 0xbd, 0xcf, 0x73, 0x11, 0x9a, 0x9b, 0x99, 0x42, 0xd1, 0x38, 0x38, - 0x9f, 0xf4, 0x06, 0x6f, 0x3f, 0x1c, 0x3b, 0x6a, 0x7b, 0x1e, 0xb5, 0x93, 0xde, 0xe0, 0x48, 0xfa, 0x4c, 0x54, 0xd8, - 0x9f, 0xa8, 0xb0, 0xbf, 0xa3, 0x2f, 0xa6, 0x81, 0x48, 0x5a, 0xd9, 0x56, 0xd3, 0x96, 0x36, 0x83, 0xf2, 0xf6, 0x4e, - 0x66, 0xa9, 0x60, 0xf0, 0xc5, 0xa4, 0xb6, 0x8c, 0xf9, 0xcb, 0x1c, 0x02, 0x73, 0x08, 0x55, 0x6b, 0x87, 0x57, 0x22, - 0x33, 0xbe, 0xe1, 0x11, 0x4b, 0xa9, 0x39, 0x76, 0xaa, 0xbb, 0xaa, 0x12, 0x7e, 0x56, 0x6b, 0x17, 0xb3, 0x2b, 0x48, - 0x7a, 0x30, 0xe9, 0x45, 0x1f, 0x75, 0x83, 0x23, 0x39, 0x14, 0x44, 0xee, 0x95, 0x98, 0x36, 0xdf, 0x86, 0x6d, 0x2e, - 0xa9, 0x9e, 0xbd, 0x96, 0x10, 0x70, 0x3d, 0x48, 0xb2, 0x37, 0xa8, 0xdc, 0xc5, 0xf6, 0xbb, 0xf2, 0xa8, 0x9d, 0xec, - 0x0d, 0x2e, 0x83, 0xb1, 0xee, 0xef, 0x55, 0x3e, 0x5e, 0xdf, 0x57, 0x9a, 0x8f, 0x87, 0xf2, 0x1c, 0xbc, 0xba, 0x30, - 0xca, 0x28, 0xbf, 0x79, 0xea, 0x0e, 0x8e, 0xb4, 0x32, 0xe0, 0xc8, 0xb0, 0xba, 0x7b, 0xd0, 0x31, 0x47, 0xeb, 0xd3, - 0x7c, 0x0c, 0x1b, 0x52, 0x35, 0xb1, 0x06, 0x69, 0x78, 0xdc, 0x93, 0xee, 0xe0, 0x28, 0x74, 0x24, 0x6f, 0x91, 0xcc, - 0xa3, 0x08, 0xda, 0xd0, 0x38, 0xc9, 0x27, 0xd4, 0x67, 0x79, 0xfb, 0x86, 0x5e, 0xb5, 0xc2, 0x29, 0xab, 0xdd, 0xdb, - 0xa0, 0x74, 0x54, 0x43, 0xe6, 0x4b, 0x29, 0x56, 0xbd, 0xda, 0xdd, 0xb6, 0x0f, 0x36, 0x8f, 0x71, 0xcd, 0x49, 0x9f, - 0x9c, 0x05, 0x56, 0x3e, 0x38, 0x6a, 0x87, 0x4b, 0x18, 0x91, 0xfc, 0xbe, 0xd4, 0x8e, 0x76, 0x30, 0x6c, 0xae, 0x64, - 0x7e, 0x97, 0x12, 0x07, 0xc6, 0x21, 0xaf, 0x05, 0x75, 0xe9, 0x0e, 0xfe, 0xd7, 0x7f, 0xfb, 0x1f, 0xda, 0xc7, 0x7e, - 0xd4, 0x4e, 0xba, 0xa6, 0xaf, 0xa5, 0x55, 0x29, 0x8f, 0xe0, 0x72, 0x9c, 0x3a, 0x28, 0x4c, 0x6f, 0x5b, 0x63, 0xce, - 0xe2, 0x56, 0x12, 0xa6, 0x23, 0x77, 0xb0, 0x19, 0x9b, 0x2a, 0xff, 0xb0, 0x65, 0xc2, 0xa9, 0xab, 0x45, 0x40, 0xaf, - 0xbf, 0xea, 0xd6, 0x05, 0x93, 0xd2, 0x25, 0xb7, 0xb6, 0x7d, 0x07, 0x43, 0xbd, 0xfb, 0x1a, 0xf7, 0x30, 0x64, 0xfa, - 0x83, 0xd3, 0x9a, 0x03, 0x66, 0x8d, 0xeb, 0x17, 0x4a, 0xd7, 0xa9, 0x82, 0x5a, 0xff, 0xe7, 0xbf, 0xff, 0xa7, 0xff, - 0x62, 0x1e, 0x21, 0x56, 0xf5, 0xbf, 0xfe, 0xeb, 0x7f, 0xfc, 0xdf, 0xff, 0xf3, 0x3f, 0x43, 0xfe, 0x99, 0x8e, 0x67, - 0x49, 0xa6, 0xe2, 0xd4, 0xc1, 0x2c, 0xc5, 0x5d, 0x1c, 0x38, 0xd5, 0x36, 0x61, 0x85, 0x60, 0x51, 0xf3, 0x42, 0x86, - 0x53, 0x39, 0xa0, 0xdc, 0x99, 0x1a, 0x3a, 0xb9, 0xc3, 0xcb, 0x9a, 0xa0, 0x1a, 0x28, 0x97, 0x84, 0x5b, 0x1e, 0xb5, - 0x01, 0xdf, 0x0f, 0xbb, 0xc3, 0xc6, 0xaf, 0x96, 0x63, 0x6e, 0xc8, 0x04, 0x4a, 0xca, 0xba, 0xdc, 0x81, 0xd8, 0xca, - 0x1c, 0x1e, 0x83, 0x9e, 0x55, 0x2c, 0x57, 0xaf, 0xd1, 0xa6, 0xff, 0xd3, 0xac, 0x10, 0x6c, 0x04, 0x28, 0x57, 0x7e, - 0x62, 0x19, 0xc6, 0x6e, 0x81, 0xae, 0x98, 0xde, 0x95, 0xb2, 0x17, 0x45, 0xa0, 0xfb, 0x87, 0xff, 0x54, 0xfe, 0x61, - 0x02, 0x1a, 0x99, 0xe3, 0x4d, 0xc2, 0x5b, 0x6d, 0x9e, 0x3f, 0xee, 0x74, 0xa6, 0xb7, 0x68, 0x5e, 0x8f, 0x80, 0x37, - 0x0d, 0x26, 0xe9, 0xd8, 0xee, 0x50, 0xc6, 0xbf, 0x2b, 0x37, 0x76, 0xc7, 0x01, 0x5f, 0xb8, 0xd3, 0x29, 0xcb, 0xdf, - 0xcf, 0xa5, 0x27, 0x95, 0xfd, 0x02, 0x71, 0x6a, 0xed, 0x74, 0xbe, 0xca, 0xed, 0xc9, 0xcd, 0xad, 0x56, 0x3d, 0xd5, - 0x2a, 0xe9, 0xae, 0x5e, 0xcd, 0x62, 0xc7, 0xd9, 0xed, 0x08, 0xf9, 0x3e, 0xc4, 0xbc, 0x93, 0x2e, 0x4e, 0x7a, 0xf3, - 0xaa, 0x7b, 0x21, 0xf2, 0x89, 0x1d, 0x58, 0xa7, 0x21, 0x8d, 0xe8, 0xc8, 0x38, 0xeb, 0xf5, 0x7b, 0x15, 0x34, 0x2f, - 0x93, 0xbd, 0x35, 0x63, 0x69, 0x90, 0x64, 0x40, 0xdd, 0xe9, 0x94, 0x5f, 0xc1, 0x0e, 0x9c, 0x8f, 0xd2, 0x3c, 0x14, - 0x81, 0x24, 0xd8, 0xbe, 0x1d, 0x9e, 0x0f, 0x81, 0x27, 0xe5, 0x73, 0x0b, 0x9e, 0xbe, 0xaa, 0x0a, 0x6e, 0xf3, 0xe6, - 0x05, 0x3a, 0xa5, 0x2f, 0x9b, 0xdb, 0x5d, 0x29, 0xaf, 0xdb, 0xf7, 0x3a, 0xea, 0xfd, 0xb2, 0xe1, 0xae, 0xd2, 0x02, - 0xa9, 0x87, 0xd6, 0xbf, 0x57, 0x72, 0x5d, 0xbd, 0xfd, 0x8b, 0xf0, 0x5c, 0x09, 0xa6, 0xbb, 0x5c, 0x4b, 0x16, 0x42, - 0xad, 0x97, 0xe4, 0xfb, 0xca, 0x64, 0x0a, 0xa7, 0x53, 0x59, 0x11, 0xf5, 0x8f, 0xda, 0x4a, 0xd3, 0x05, 0xee, 0x21, - 0x53, 0x3a, 0x54, 0x06, 0x85, 0xae, 0xa4, 0xb7, 0x82, 0xfa, 0xa5, 0x73, 0x2b, 0xe0, 0x43, 0xe4, 0x83, 0xff, 0x0b, - 0x64, 0xce, 0x91, 0xa6, 0x21, 0x98, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdb, 0x48, 0xb6, 0xe0, 0xf3, + 0xd4, 0x57, 0x40, 0x28, 0xb5, 0x8c, 0x2c, 0x26, 0xc1, 0x45, 0x92, 0x2d, 0x83, 0x4a, 0xb2, 0x65, 0xd9, 0xd5, 0x76, + 0x97, 0xb7, 0xb6, 0xec, 0xda, 0x58, 0x6c, 0x09, 0x02, 0x92, 0x44, 0x96, 0x41, 0x80, 0x05, 0x24, 0xb5, 0x14, 0x89, + 0x1b, 0xf3, 0x01, 0x13, 0x31, 0x11, 0xf3, 0x34, 0x2f, 0x13, 0x73, 0x1f, 0xe6, 0x23, 0xe6, 0xf9, 0x7e, 0xca, 0xfd, + 0x81, 0x99, 0x4f, 0x98, 0x38, 0xb9, 0x00, 0x09, 0x2e, 0xb2, 0x5c, 0x55, 0x7d, 0xef, 0x7d, 0x98, 0xa8, 0x28, 0x99, + 0x48, 0xe4, 0x72, 0xf2, 0xe4, 0xc9, 0xb3, 0x67, 0xe2, 0x78, 0x27, 0x4c, 0x03, 0x7e, 0x3b, 0xa3, 0x56, 0xc4, 0xa7, + 0x71, 0xff, 0x58, 0xfd, 0xa5, 0x7e, 0xd8, 0x3f, 0x8e, 0x59, 0xf2, 0xd1, 0xca, 0x68, 0x4c, 0x58, 0x90, 0x26, 0x56, + 0x94, 0xd1, 0x31, 0x09, 0x7d, 0xee, 0x7b, 0x6c, 0xea, 0x4f, 0xa8, 0xd5, 0xea, 0x1f, 0x4f, 0x29, 0xf7, 0xad, 0x20, + 0xf2, 0xb3, 0x9c, 0x72, 0xf2, 0xe1, 0xfd, 0xd7, 0xcd, 0xa3, 0xfe, 0x71, 0x1e, 0x64, 0x6c, 0xc6, 0x2d, 0xe8, 0x92, + 0x4c, 0xd3, 0x70, 0x1e, 0xd3, 0x7e, 0xab, 0x75, 0x7d, 0x7d, 0xed, 0xfe, 0x9c, 0x7f, 0x11, 0xa4, 0x49, 0xce, 0xad, + 0xa7, 0xe4, 0x9a, 0x25, 0x61, 0x7a, 0x8d, 0x73, 0x4e, 0x9e, 0xba, 0x67, 0x91, 0x1f, 0xa6, 0xd7, 0xef, 0xd2, 0x94, + 0xef, 0xed, 0x39, 0xf2, 0xf1, 0xf6, 0xf4, 0xec, 0x8c, 0x10, 0x72, 0x95, 0xb2, 0xd0, 0x6a, 0x2f, 0x97, 0x55, 0xa1, + 0x9b, 0xf8, 0x9c, 0x5d, 0x51, 0xd9, 0x04, 0xed, 0xed, 0xd9, 0x7e, 0x98, 0xce, 0x38, 0x0d, 0xcf, 0xf8, 0x6d, 0x4c, + 0xcf, 0x22, 0x4a, 0x79, 0x6e, 0xb3, 0xc4, 0x7a, 0x9a, 0x06, 0xf3, 0x29, 0x4d, 0xb8, 0x3b, 0xcb, 0x52, 0x9e, 0x02, + 0x24, 0x7b, 0x7b, 0x76, 0x46, 0x67, 0xb1, 0x1f, 0x50, 0x78, 0x7f, 0x7a, 0x76, 0x56, 0xb5, 0xa8, 0x2a, 0xe1, 0x84, + 0x93, 0xb3, 0xdb, 0xe9, 0x65, 0x1a, 0x3b, 0x08, 0x47, 0x9c, 0x24, 0xf4, 0xda, 0xfa, 0x8e, 0xfa, 0x1f, 0x5f, 0xf9, + 0xb3, 0x5e, 0x10, 0xfb, 0x79, 0x6e, 0x9d, 0xf0, 0x85, 0x98, 0x42, 0x36, 0x0f, 0x78, 0x9a, 0x39, 0x1c, 0x53, 0xcc, + 0xd0, 0x82, 0x8d, 0x1d, 0x1e, 0xb1, 0xdc, 0x3d, 0xdf, 0x0d, 0xf2, 0xfc, 0x1d, 0xcd, 0xe7, 0x31, 0xdf, 0x25, 0x3b, + 0x6d, 0xcc, 0x76, 0x08, 0x49, 0x38, 0xe2, 0x51, 0x96, 0x5e, 0x5b, 0xcf, 0xb2, 0x2c, 0xcd, 0x1c, 0xfb, 0xf4, 0xec, + 0x4c, 0xd6, 0xb0, 0x58, 0x6e, 0x25, 0x29, 0xb7, 0xca, 0xfe, 0xfc, 0xcb, 0x98, 0xba, 0xd6, 0x87, 0x9c, 0x5a, 0x17, + 0xf3, 0x24, 0xf7, 0xc7, 0xf4, 0xf4, 0xec, 0xec, 0xc2, 0x4a, 0x33, 0xeb, 0x22, 0xc8, 0xf3, 0x0b, 0x8b, 0x25, 0x39, + 0xa7, 0x7e, 0xe8, 0xda, 0xa8, 0x27, 0x06, 0x0b, 0xf2, 0xfc, 0x3d, 0xbd, 0xe1, 0x84, 0x63, 0xf1, 0xc8, 0x09, 0x2d, + 0x26, 0x94, 0x5b, 0x79, 0x39, 0x2f, 0x07, 0x2d, 0x62, 0xca, 0x2d, 0x4e, 0xc4, 0xfb, 0xb4, 0x27, 0x71, 0x4f, 0xe5, + 0x23, 0xef, 0xb1, 0xb1, 0x93, 0xf3, 0xbd, 0x3d, 0x5e, 0xe2, 0x19, 0xc9, 0xa9, 0x59, 0x8c, 0xd0, 0x1d, 0x5d, 0xb6, + 0xb7, 0x47, 0xdd, 0x98, 0x26, 0x13, 0x1e, 0x11, 0x42, 0x3a, 0x3d, 0xb6, 0xb7, 0xe7, 0x70, 0x12, 0x71, 0x77, 0x42, + 0xb9, 0x43, 0x11, 0xc2, 0x55, 0xeb, 0xbd, 0x3d, 0x47, 0x22, 0x21, 0x25, 0x12, 0x71, 0x35, 0x1c, 0x23, 0x57, 0x61, + 0xff, 0xec, 0x36, 0x09, 0x1c, 0x13, 0x7e, 0x84, 0xd9, 0xde, 0x5e, 0xc4, 0xdd, 0x1c, 0x7a, 0xc4, 0x1c, 0xa1, 0x22, + 0xa3, 0x7c, 0x9e, 0x25, 0x16, 0x2f, 0x78, 0x7a, 0xc6, 0x33, 0x96, 0x4c, 0x1c, 0xb4, 0xd0, 0x65, 0x46, 0xc3, 0xa2, + 0x90, 0xe0, 0xbe, 0xe3, 0x24, 0x21, 0x7d, 0x18, 0xf1, 0x84, 0x3b, 0xb0, 0x8a, 0xe9, 0xd8, 0x4a, 0x08, 0xb1, 0x73, + 0xd1, 0xd6, 0x1e, 0x24, 0x5e, 0xd2, 0xb0, 0x6d, 0x2c, 0xa1, 0xc4, 0x09, 0x47, 0xf8, 0x23, 0x71, 0x12, 0xec, 0xba, + 0x2e, 0x47, 0xa4, 0xbf, 0xd0, 0x58, 0x49, 0x8c, 0x79, 0x0e, 0x92, 0x61, 0x7b, 0xe4, 0x71, 0x37, 0xa3, 0xe1, 0x3c, + 0xa0, 0x8e, 0xc3, 0x70, 0x8e, 0x53, 0x44, 0xfa, 0xac, 0xe1, 0x64, 0xa4, 0x0f, 0xcb, 0x9d, 0xd5, 0xd7, 0x9a, 0x90, + 0x9d, 0x36, 0x52, 0x30, 0x66, 0x1a, 0x40, 0xc0, 0xb0, 0x82, 0x27, 0x23, 0xc4, 0x4e, 0xe6, 0xd3, 0x4b, 0x9a, 0xd9, + 0x65, 0xb5, 0x5e, 0x8d, 0x2c, 0xe6, 0x39, 0xb5, 0x82, 0x3c, 0xb7, 0xc6, 0xf3, 0x24, 0xe0, 0x2c, 0x4d, 0x2c, 0xbb, + 0x91, 0x35, 0x6c, 0x49, 0x0e, 0x25, 0x35, 0xd8, 0xa8, 0x40, 0x4e, 0x8e, 0x1a, 0xc9, 0x30, 0x6d, 0x74, 0x46, 0x18, + 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0x4f, 0x38, 0xcc, 0x52, 0x4c, 0x31, 0xe7, + 0x83, 0xc4, 0x5d, 0xdf, 0x28, 0x84, 0xbb, 0x53, 0x7f, 0xe6, 0x50, 0xd2, 0xa7, 0x82, 0xb8, 0xfc, 0x24, 0x00, 0x58, + 0x6b, 0xeb, 0x36, 0xa0, 0x1e, 0x75, 0x2b, 0x92, 0x42, 0x1e, 0x77, 0xc7, 0x69, 0xf6, 0xcc, 0x0f, 0x22, 0x68, 0x57, + 0x12, 0x4c, 0xa8, 0xf7, 0x5b, 0x90, 0x51, 0x9f, 0xd3, 0x67, 0x31, 0x85, 0x27, 0xc7, 0x16, 0x2d, 0x6d, 0x84, 0x73, + 0xf2, 0xd4, 0x8d, 0x19, 0x7f, 0x9d, 0x26, 0x01, 0xed, 0xe5, 0x06, 0x75, 0x31, 0x58, 0xf7, 0x13, 0xce, 0x33, 0x76, + 0x39, 0xe7, 0xd4, 0xb1, 0x13, 0xa8, 0x61, 0xe3, 0x1c, 0x61, 0xe6, 0x72, 0x7a, 0xc3, 0x4f, 0xd3, 0x84, 0xd3, 0x84, + 0x13, 0xaa, 0x91, 0x8a, 0x13, 0xd7, 0x9f, 0xcd, 0x68, 0x12, 0x9e, 0x46, 0x2c, 0x0e, 0x1d, 0x86, 0x0a, 0x54, 0xe0, + 0x80, 0x13, 0x98, 0x23, 0xe9, 0x27, 0x1e, 0xfc, 0xd9, 0x3e, 0x1b, 0x87, 0x93, 0xbe, 0xd8, 0x14, 0x94, 0xd8, 0x76, + 0x6f, 0x9c, 0x66, 0x8e, 0x9a, 0x81, 0x95, 0x8e, 0x2d, 0x0e, 0x63, 0xbc, 0x9b, 0xc7, 0x34, 0x47, 0xb4, 0x41, 0x58, + 0xb9, 0x8c, 0x0a, 0xc1, 0xef, 0x80, 0xe2, 0x0b, 0xe4, 0x24, 0xc8, 0x4b, 0x7a, 0x57, 0x7e, 0x66, 0xfd, 0xa8, 0x76, + 0xd4, 0xcf, 0x9a, 0x9b, 0x85, 0x9c, 0xfc, 0xec, 0xf2, 0x6c, 0x9e, 0x73, 0x1a, 0xbe, 0xbf, 0x9d, 0xd1, 0x1c, 0x3f, + 0xe7, 0x24, 0xe4, 0x83, 0x90, 0xbb, 0x74, 0x3a, 0xe3, 0xb7, 0x67, 0x82, 0x31, 0x7a, 0xb6, 0x8d, 0xe7, 0x50, 0x33, + 0xa3, 0x7e, 0x00, 0xcc, 0x4c, 0x61, 0xeb, 0x6d, 0x1a, 0xdf, 0x8e, 0x59, 0x1c, 0x9f, 0xcd, 0x67, 0xb3, 0x34, 0xe3, + 0x98, 0x73, 0xb2, 0xe0, 0x69, 0x85, 0x1b, 0x58, 0xcc, 0x45, 0x7e, 0xcd, 0x78, 0x10, 0x39, 0x1c, 0x2d, 0x02, 0x3f, + 0xa7, 0xd6, 0x93, 0x34, 0x8d, 0xa9, 0x0f, 0xb3, 0x4e, 0x06, 0xcf, 0xb9, 0x97, 0xcc, 0xe3, 0xb8, 0x77, 0x99, 0x51, + 0xff, 0x63, 0x4f, 0xbc, 0x7e, 0x73, 0xf9, 0x33, 0x0d, 0xb8, 0x27, 0x7e, 0x9f, 0x64, 0x99, 0x7f, 0x0b, 0x15, 0x09, + 0x81, 0x6a, 0x83, 0xc4, 0xfb, 0xeb, 0xd9, 0x9b, 0xd7, 0xae, 0xdc, 0x25, 0x6c, 0x7c, 0xeb, 0x24, 0xe5, 0xce, 0x4b, + 0x0a, 0x3c, 0xce, 0xd2, 0xe9, 0xca, 0xd0, 0x12, 0x6d, 0x49, 0x6f, 0x0b, 0x08, 0x94, 0x24, 0x3b, 0xb2, 0x6b, 0x13, + 0x82, 0xd7, 0x82, 0xe8, 0xe1, 0x25, 0xd1, 0xe3, 0xce, 0xe3, 0xd8, 0x93, 0xc5, 0x4e, 0x82, 0xee, 0x86, 0x96, 0x67, + 0xb7, 0x0b, 0x4a, 0x04, 0x9c, 0x33, 0x10, 0x31, 0x00, 0x63, 0xe0, 0xf3, 0x20, 0x5a, 0x50, 0xd1, 0x59, 0xa1, 0x21, + 0xa6, 0x45, 0x81, 0x9f, 0x95, 0x04, 0xcf, 0x01, 0x10, 0xc1, 0xa9, 0x08, 0x5f, 0x2e, 0x61, 0xc2, 0x08, 0xff, 0x95, + 0x2c, 0x7c, 0x3d, 0x1f, 0x6f, 0xa7, 0x8d, 0x61, 0x63, 0x7a, 0x92, 0xbd, 0xe0, 0x20, 0x4d, 0xae, 0x68, 0xc6, 0x69, + 0xe6, 0x71, 0x8e, 0x33, 0x3a, 0x8e, 0x01, 0x8c, 0x9d, 0x0e, 0x8e, 0xfc, 0xfc, 0x34, 0xf2, 0x93, 0x09, 0x0d, 0xbd, + 0x67, 0xbc, 0xc0, 0x94, 0x13, 0x7b, 0xcc, 0x12, 0x3f, 0x66, 0xbf, 0xd2, 0xd0, 0x56, 0x02, 0xe1, 0x99, 0x45, 0x6f, + 0x38, 0x4d, 0xc2, 0xdc, 0x7a, 0xfe, 0xfe, 0xd5, 0x4b, 0xb5, 0x94, 0x35, 0x19, 0x81, 0x16, 0xf9, 0x7c, 0x46, 0x33, + 0x07, 0x61, 0x25, 0x23, 0x9e, 0x31, 0xc1, 0x1f, 0x5f, 0xf9, 0x33, 0x59, 0xc2, 0xf2, 0x0f, 0xb3, 0xd0, 0xe7, 0xf4, + 0x2d, 0x4d, 0x42, 0x96, 0x4c, 0xc8, 0x4e, 0x47, 0x96, 0x47, 0xbe, 0x7a, 0x11, 0x96, 0x45, 0xe7, 0xbb, 0xcf, 0x62, + 0x31, 0xf3, 0xf2, 0x71, 0xee, 0xa0, 0x22, 0xe7, 0x3e, 0x67, 0x81, 0xe5, 0x87, 0xe1, 0x8b, 0x84, 0x71, 0x26, 0x00, + 0xcc, 0x60, 0x81, 0x80, 0x4a, 0xa9, 0x94, 0x16, 0x1a, 0x70, 0x07, 0x61, 0xc7, 0x51, 0x32, 0x20, 0x42, 0x6a, 0xc5, + 0xf6, 0xf6, 0x2a, 0x8e, 0x3f, 0xa0, 0x9e, 0x7c, 0x49, 0x86, 0x23, 0xe4, 0xce, 0xe6, 0x39, 0x2c, 0xb5, 0x1e, 0x02, + 0x04, 0x4c, 0x7a, 0x99, 0xd3, 0xec, 0x8a, 0x86, 0x25, 0x79, 0xe4, 0x0e, 0x5a, 0xac, 0x8c, 0xa1, 0x76, 0x06, 0x27, + 0xc3, 0x51, 0xcf, 0x64, 0xdd, 0x54, 0x91, 0x7a, 0x96, 0xce, 0x68, 0xc6, 0x19, 0xcd, 0x4b, 0x6e, 0xe2, 0x80, 0x20, + 0x2d, 0x39, 0x4a, 0x4e, 0xf4, 0xfc, 0x66, 0x0e, 0xc3, 0x14, 0xd5, 0x78, 0x86, 0x96, 0xb5, 0xcf, 0xae, 0x84, 0xd0, + 0xc8, 0x31, 0x43, 0x98, 0x4b, 0x48, 0x73, 0x84, 0x0a, 0x84, 0xb9, 0x06, 0x57, 0x72, 0x23, 0x35, 0xda, 0x2d, 0x48, + 0x6b, 0xf2, 0x57, 0x21, 0xad, 0x81, 0xa7, 0xf9, 0x9c, 0xee, 0xed, 0x39, 0xd4, 0x2d, 0xc9, 0x82, 0xec, 0x74, 0xd4, + 0x1a, 0x19, 0xc8, 0xda, 0x02, 0x36, 0x0c, 0xcc, 0x31, 0x45, 0x78, 0x87, 0xba, 0x49, 0x7a, 0x12, 0x04, 0x34, 0xcf, + 0xd3, 0x6c, 0x6f, 0x6f, 0x47, 0xd4, 0x2f, 0x15, 0x0a, 0x58, 0xc3, 0x37, 0xd7, 0x49, 0x05, 0x01, 0xaa, 0x84, 0xac, + 0x12, 0x0d, 0x1c, 0x44, 0x95, 0xd0, 0x39, 0xec, 0x81, 0xd6, 0x3d, 0x3c, 0xfb, 0xfc, 0xdc, 0x6e, 0x70, 0xac, 0xd0, + 0x30, 0xa1, 0x7a, 0xe8, 0xdb, 0xa7, 0x54, 0x6a, 0x57, 0x42, 0xf7, 0x58, 0xc3, 0x8c, 0xdc, 0x41, 0x6e, 0x48, 0xc7, + 0x2c, 0x31, 0xa6, 0x5d, 0x03, 0x09, 0x73, 0x9c, 0xa3, 0xc2, 0x58, 0xd0, 0x8d, 0x5d, 0x0b, 0xb5, 0x46, 0xae, 0xdc, + 0x62, 0x22, 0x54, 0x09, 0x63, 0x19, 0x87, 0x74, 0x54, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x54, 0x00, 0x3a, 0xe4, 0xa3, + 0x9e, 0x7a, 0x4f, 0x72, 0x89, 0xb9, 0x8c, 0xfe, 0x32, 0xa7, 0x39, 0x97, 0x74, 0xec, 0x70, 0x9c, 0x62, 0x06, 0xfc, + 0x3a, 0x4d, 0xc6, 0x6c, 0x32, 0xcf, 0x40, 0xe3, 0x81, 0xcd, 0x48, 0x93, 0xf9, 0x94, 0xea, 0xa7, 0x4d, 0xb0, 0xbd, + 0x99, 0x81, 0x4c, 0xcc, 0x81, 0xa6, 0xef, 0x26, 0x27, 0x80, 0x95, 0xa3, 0xe5, 0xf2, 0xaf, 0xba, 0x93, 0x6a, 0x29, + 0x4b, 0x2d, 0x6d, 0x65, 0x4d, 0x28, 0x47, 0x4a, 0x26, 0xef, 0x74, 0x14, 0xf8, 0x7c, 0x44, 0x76, 0xda, 0x25, 0x0d, + 0x2b, 0xac, 0x4a, 0x70, 0x24, 0x12, 0xdf, 0xc8, 0xae, 0x90, 0x10, 0xf1, 0x35, 0x72, 0x71, 0xa3, 0x35, 0x4a, 0x8d, + 0xc8, 0x10, 0x94, 0x0d, 0x37, 0x1a, 0x6d, 0x23, 0x27, 0xcd, 0x0f, 0x1c, 0xbe, 0xfe, 0xae, 0x62, 0x1b, 0x57, 0x75, + 0xb6, 0xb1, 0x32, 0x0d, 0x7b, 0x56, 0x36, 0xb1, 0x4b, 0x2a, 0x53, 0x1b, 0xbd, 0x7a, 0x85, 0x99, 0x00, 0xa6, 0x9a, + 0x92, 0xd1, 0xc5, 0x6b, 0x7f, 0x4a, 0x73, 0x87, 0x22, 0xbc, 0xad, 0x82, 0x24, 0x4f, 0xa8, 0x32, 0x32, 0x64, 0x67, + 0x0e, 0xb2, 0x93, 0x21, 0xa9, 0x9a, 0xd5, 0x37, 0x5c, 0x8e, 0xe9, 0x30, 0x1f, 0x55, 0x1a, 0x9d, 0x31, 0x79, 0x21, + 0x94, 0x15, 0x7d, 0x6b, 0xfc, 0xc9, 0x32, 0x89, 0x34, 0xa1, 0x39, 0xe4, 0x08, 0xef, 0xb4, 0x57, 0x57, 0x52, 0xd7, + 0xaa, 0xe6, 0x38, 0x1c, 0xc1, 0x3a, 0x08, 0x91, 0xe1, 0xb2, 0x5c, 0xfc, 0x5b, 0xdb, 0x69, 0x80, 0xb6, 0x33, 0x20, + 0x0c, 0x77, 0x1c, 0xfb, 0xdc, 0xe9, 0xb4, 0xda, 0xa0, 0x8e, 0x5e, 0x51, 0x90, 0x28, 0x08, 0xad, 0x4f, 0x85, 0xba, + 0xf3, 0x24, 0x8f, 0xd8, 0x98, 0x3b, 0x01, 0x17, 0x2c, 0x85, 0xc6, 0x39, 0xb5, 0x78, 0x4d, 0x29, 0x16, 0xec, 0x26, + 0x00, 0x62, 0x2b, 0x35, 0x30, 0xaa, 0x21, 0x15, 0x6c, 0x0b, 0xb8, 0x43, 0xa5, 0x50, 0x57, 0x5c, 0x46, 0xd7, 0x66, + 0xa0, 0x34, 0x76, 0x06, 0xb2, 0x47, 0x4f, 0x31, 0x03, 0x66, 0xe8, 0xad, 0xcc, 0x33, 0x39, 0x84, 0x2a, 0xe4, 0x2e, + 0x4f, 0x5f, 0xa6, 0xd7, 0x34, 0x3b, 0xf5, 0x01, 0x78, 0x4f, 0x36, 0x2f, 0xa4, 0x20, 0x10, 0xfc, 0x9e, 0xf7, 0x34, + 0xbd, 0x9c, 0x8b, 0x89, 0xbf, 0xcd, 0xd2, 0x29, 0xcb, 0x29, 0xa8, 0x6b, 0x12, 0xff, 0x09, 0xec, 0x33, 0xb1, 0x21, + 0x41, 0xd8, 0xd0, 0x92, 0xbe, 0x4e, 0x5e, 0xd6, 0xe9, 0xeb, 0x7c, 0xf7, 0xd9, 0x44, 0x33, 0xc0, 0xfa, 0x36, 0x46, + 0xd8, 0x51, 0x46, 0x85, 0x21, 0xe7, 0xdc, 0x08, 0x29, 0x11, 0xbf, 0x5c, 0x72, 0xc3, 0x76, 0xab, 0x29, 0x8c, 0x54, + 0x6e, 0x1b, 0x54, 0xf8, 0x61, 0x08, 0xaa, 0x5d, 0x96, 0xc6, 0xb1, 0x21, 0xaa, 0x30, 0xeb, 0x95, 0xc2, 0xe9, 0x7c, + 0xf7, 0xd9, 0xd9, 0x5d, 0xf2, 0x09, 0xde, 0x9b, 0x22, 0x4a, 0x03, 0x9a, 0x84, 0x34, 0x03, 0x5b, 0xd2, 0x58, 0x2d, + 0x25, 0x65, 0x4f, 0xd3, 0x24, 0xa1, 0x01, 0xa7, 0x21, 0x98, 0x2a, 0x8c, 0x70, 0x37, 0x4a, 0x73, 0x5e, 0x16, 0x56, + 0xd0, 0x33, 0x03, 0x7a, 0xe6, 0x06, 0x7e, 0x1c, 0x3b, 0xd2, 0x2c, 0x99, 0xa6, 0x57, 0x74, 0x03, 0xd4, 0xbd, 0x1a, + 0xc8, 0x65, 0x37, 0xd4, 0xe8, 0x86, 0xba, 0xf9, 0x2c, 0x66, 0x01, 0x2d, 0x45, 0xd7, 0x99, 0xcb, 0x92, 0x90, 0xde, + 0x00, 0x1f, 0x41, 0xfd, 0x7e, 0xbf, 0x8d, 0x3b, 0xa8, 0x90, 0x08, 0x5f, 0xac, 0x21, 0xf6, 0x0e, 0xa1, 0x09, 0x44, + 0x46, 0xfa, 0x8b, 0x8d, 0x6c, 0x0d, 0x19, 0x92, 0x92, 0x69, 0xf3, 0x4a, 0x72, 0x67, 0x84, 0x43, 0x1a, 0x53, 0x4e, + 0x35, 0x37, 0x07, 0x25, 0x5a, 0x6e, 0xdd, 0x77, 0x25, 0xfe, 0x4a, 0x72, 0xd2, 0xbb, 0x4c, 0xaf, 0x79, 0x5e, 0x9a, + 0xeb, 0xd5, 0xf2, 0x54, 0xd8, 0x1e, 0x70, 0xb9, 0x3c, 0x3e, 0xe7, 0x7e, 0x10, 0x49, 0x3b, 0xdd, 0x59, 0x9b, 0x52, + 0xd5, 0x87, 0xe2, 0xec, 0xe5, 0x26, 0x7a, 0xa2, 0xc1, 0xdc, 0x84, 0x82, 0x33, 0xc5, 0x14, 0x28, 0x98, 0x7e, 0x72, + 0xd9, 0x4e, 0xfd, 0x38, 0xbe, 0xf4, 0x83, 0x8f, 0x75, 0xea, 0xaf, 0xc8, 0x80, 0xac, 0x72, 0x63, 0xe3, 0x95, 0xc1, + 0xb2, 0xcc, 0x79, 0x6b, 0x2e, 0x5d, 0xdb, 0x28, 0xce, 0x4e, 0xbb, 0x22, 0xfb, 0xfa, 0x42, 0x6f, 0xa5, 0x76, 0x01, + 0x11, 0x53, 0x33, 0x73, 0x80, 0x0b, 0x7c, 0x92, 0xe2, 0x34, 0x3f, 0x50, 0x74, 0x07, 0x06, 0x47, 0xb1, 0x02, 0x08, + 0x47, 0x8b, 0x22, 0x64, 0xf9, 0x76, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x35, 0x46, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x53, + 0x5a, 0x73, 0x09, 0x99, 0xd2, 0x27, 0x34, 0xa3, 0xf9, 0x06, 0x74, 0x17, 0x41, 0xef, 0x6f, 0xe4, 0x2b, 0xd0, 0xca, + 0x00, 0x8a, 0xbc, 0x67, 0xaa, 0x13, 0x35, 0x0a, 0x50, 0x3c, 0x95, 0x09, 0x91, 0x9b, 0xd6, 0x2c, 0x48, 0xa5, 0xb1, + 0x4b, 0x23, 0x5c, 0xb1, 0xdc, 0x8c, 0x38, 0x8e, 0x93, 0x83, 0x11, 0xa7, 0x75, 0xfb, 0x6a, 0x12, 0xf9, 0xda, 0x24, + 0x72, 0xd7, 0x30, 0xb4, 0x50, 0x45, 0xcb, 0x46, 0x73, 0x8f, 0x73, 0x64, 0xd6, 0x02, 0x7d, 0xd5, 0x05, 0x06, 0x8d, + 0x4a, 0x7e, 0x1b, 0x13, 0x8e, 0x33, 0x65, 0xe5, 0x28, 0x52, 0x03, 0x8e, 0x51, 0x35, 0x49, 0x91, 0xdc, 0x1b, 0x35, + 0x93, 0x37, 0xc5, 0x19, 0x5a, 0x51, 0xee, 0x8b, 0x42, 0x21, 0x89, 0x22, 0xb5, 0x38, 0x35, 0xad, 0xd8, 0x40, 0x0b, + 0x4e, 0x89, 0xd2, 0x84, 0xa5, 0xe2, 0xb3, 0x8a, 0x9c, 0xb2, 0xdf, 0x1d, 0x42, 0xd2, 0x0a, 0x37, 0x35, 0x95, 0x52, + 0xeb, 0x56, 0x29, 0xc2, 0x91, 0x56, 0x4a, 0xb3, 0x6a, 0xe2, 0x84, 0xd8, 0xda, 0x27, 0x61, 0x0f, 0x16, 0x35, 0xbb, + 0xd0, 0x33, 0xaa, 0x15, 0x1e, 0xf0, 0xd4, 0x6c, 0x13, 0xbe, 0x37, 0x11, 0x4d, 0xad, 0x1f, 0x03, 0xe3, 0x59, 0x0d, + 0xe3, 0x06, 0x6a, 0x53, 0xc9, 0xbb, 0xd2, 0x11, 0x89, 0xea, 0x8d, 0x1d, 0x8a, 0x33, 0xb9, 0x10, 0x6b, 0x58, 0x5c, + 0x55, 0x3e, 0x05, 0x11, 0x82, 0x19, 0x9b, 0x83, 0x7a, 0x67, 0x4a, 0x08, 0x07, 0x80, 0x67, 0xcb, 0xe5, 0x1a, 0xd9, + 0x6d, 0xd4, 0x41, 0x91, 0x5b, 0x59, 0x86, 0xcb, 0xe5, 0x33, 0x8e, 0x1c, 0xa5, 0xfd, 0x62, 0x8a, 0x06, 0x9a, 0xe7, + 0x9e, 0xbc, 0x84, 0x5a, 0x42, 0x19, 0xad, 0x4a, 0x4a, 0xb3, 0xa1, 0x4e, 0xb5, 0xf5, 0x85, 0xe2, 0x06, 0xe3, 0x3e, + 0x5d, 0xe3, 0x5f, 0xa2, 0x50, 0x09, 0xea, 0x6a, 0xca, 0xa7, 0xaa, 0x6b, 0x86, 0x10, 0xf2, 0x72, 0x61, 0xc9, 0xec, + 0x6c, 0x32, 0x2e, 0xf7, 0xf6, 0x72, 0xa3, 0xa3, 0xf3, 0x92, 0x51, 0xfc, 0xec, 0x80, 0x50, 0xce, 0x6f, 0x13, 0xa1, + 0xbd, 0xfc, 0xac, 0xc5, 0xd0, 0x9a, 0x69, 0xda, 0xee, 0x81, 0x4d, 0xee, 0x5f, 0xfb, 0x8c, 0x5b, 0x65, 0x2f, 0xd2, + 0x26, 0x77, 0x28, 0x5a, 0x28, 0x65, 0xc3, 0xcd, 0x28, 0xa8, 0x8f, 0xc0, 0x15, 0xb4, 0x12, 0x2d, 0x09, 0x3f, 0x88, + 0x28, 0xf8, 0x83, 0xb5, 0x1e, 0x51, 0xda, 0x86, 0x3b, 0x4a, 0x8e, 0xa8, 0x8e, 0x37, 0xc3, 0x5e, 0xac, 0x36, 0xaf, + 0xd9, 0x02, 0x33, 0x9a, 0x8d, 0xd3, 0x6c, 0xaa, 0xdf, 0x15, 0x2b, 0xcf, 0x8a, 0x37, 0xb2, 0xb1, 0xb3, 0xb1, 0x6f, + 0x65, 0x01, 0xf4, 0x56, 0x0c, 0xef, 0xca, 0x64, 0xaf, 0x09, 0xd3, 0x52, 0xfe, 0x4a, 0xb7, 0xa0, 0xa6, 0xcc, 0xdc, + 0x34, 0xf1, 0x95, 0x4f, 0xb5, 0x27, 0xdd, 0x26, 0x3b, 0x9d, 0x5e, 0x69, 0xf7, 0x69, 0x6a, 0xe8, 0x49, 0xf7, 0x86, + 0x12, 0xaa, 0xe9, 0x3c, 0x0e, 0x15, 0xb0, 0x0c, 0x61, 0xaa, 0xe8, 0xe8, 0x9a, 0xc5, 0x71, 0x55, 0xfa, 0x39, 0x9c, + 0x3d, 0x57, 0x9c, 0x3d, 0xd5, 0x9c, 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd9, 0x5d, 0xd5, 0x3c, 0x5d, 0xdb, 0x9e, 0xa9, + 0xe4, 0xe9, 0xb9, 0xb0, 0xa5, 0x61, 0xbc, 0xb9, 0x86, 0x00, 0x95, 0xba, 0xd7, 0x47, 0x47, 0xb9, 0x62, 0xc0, 0x08, + 0x94, 0x9e, 0x4c, 0x6a, 0xba, 0x29, 0x3e, 0x3a, 0x08, 0xe7, 0x05, 0x2d, 0x29, 0xfb, 0xe4, 0x19, 0xf8, 0xea, 0x8c, + 0xe9, 0x80, 0x18, 0x13, 0xc5, 0x9f, 0xa5, 0x46, 0xe9, 0xd9, 0x31, 0x35, 0xbb, 0x5c, 0xcf, 0x0e, 0x78, 0x7d, 0x35, + 0xbb, 0xf0, 0x6e, 0x6e, 0x2f, 0xa6, 0xc7, 0xca, 0xe9, 0x55, 0xeb, 0xbd, 0x5c, 0x3a, 0x2b, 0x25, 0xe0, 0xc6, 0x57, + 0x46, 0x4a, 0x56, 0xf6, 0x0e, 0x3c, 0xc0, 0xc4, 0x0c, 0x14, 0x14, 0x72, 0xd2, 0xa5, 0x90, 0x7b, 0xf9, 0x29, 0x27, + 0x8f, 0xf0, 0xd6, 0xcb, 0xf6, 0xa7, 0xe9, 0x74, 0x06, 0xfa, 0xd8, 0x0a, 0x49, 0x4f, 0xa8, 0x1a, 0xb0, 0x7a, 0x5f, + 0x6c, 0x28, 0xab, 0xb5, 0x11, 0xfb, 0xb1, 0x46, 0x4d, 0xa5, 0xcd, 0xbc, 0xd3, 0x2e, 0xe6, 0x65, 0x51, 0xc9, 0x38, + 0x36, 0x39, 0x56, 0x4e, 0x57, 0xdd, 0x32, 0xfa, 0xc5, 0x1b, 0x87, 0x49, 0x3e, 0xcc, 0x80, 0xd7, 0x19, 0xec, 0x47, + 0x93, 0xbb, 0xb9, 0xfe, 0x45, 0x85, 0x9c, 0x45, 0xb1, 0x82, 0xbe, 0x45, 0x51, 0x3c, 0x53, 0x76, 0x36, 0x7e, 0xb6, + 0xdd, 0x20, 0xae, 0xde, 0x29, 0x7b, 0x71, 0x38, 0xc2, 0xcf, 0xd6, 0xb5, 0x47, 0xb2, 0x98, 0xa6, 0x21, 0xf5, 0xec, + 0x74, 0x46, 0x13, 0xbb, 0x00, 0xef, 0xaa, 0x5a, 0xfc, 0x39, 0x77, 0x16, 0xef, 0xea, 0x6e, 0x56, 0xef, 0x59, 0x01, + 0x2e, 0xb0, 0x1f, 0xd7, 0x1d, 0xb0, 0xdf, 0xd2, 0x2c, 0x17, 0xba, 0x68, 0xa9, 0xd6, 0xfe, 0x58, 0x09, 0xa6, 0x1f, + 0xbd, 0xad, 0xf5, 0x2b, 0x2b, 0xc4, 0xee, 0xb8, 0x0f, 0xdd, 0x7d, 0x1b, 0x09, 0xf7, 0xf0, 0x37, 0x6a, 0xc7, 0xff, + 0xa2, 0xdd, 0xc3, 0x67, 0xe4, 0x97, 0xba, 0x77, 0x78, 0xc6, 0xc9, 0xd9, 0xe0, 0x4c, 0x1b, 0xcd, 0x69, 0xcc, 0x82, + 0x5b, 0xc7, 0x8e, 0x19, 0x6f, 0x42, 0x08, 0xce, 0xc6, 0x0b, 0xf9, 0x02, 0xfc, 0x8a, 0xc2, 0xad, 0x5d, 0x68, 0x73, + 0x0f, 0x33, 0x4e, 0xec, 0xdd, 0x98, 0xf1, 0x5d, 0x1b, 0xdf, 0x92, 0x0b, 0xf8, 0xb1, 0xbb, 0x70, 0x5e, 0xf9, 0x3c, + 0x72, 0x33, 0x3f, 0x09, 0xd3, 0xa9, 0x83, 0x1a, 0xb6, 0x8d, 0xdc, 0x5c, 0x98, 0x1c, 0x8f, 0x51, 0xb1, 0x7b, 0x81, + 0xcf, 0x38, 0xb1, 0x07, 0x76, 0xe3, 0x16, 0xbf, 0xe2, 0xe4, 0xe2, 0x78, 0x77, 0x71, 0xc6, 0x8b, 0xfe, 0x05, 0x3e, + 0x29, 0x3d, 0xf7, 0xf8, 0x35, 0x71, 0x10, 0xe9, 0x9f, 0x28, 0x68, 0x4e, 0xd3, 0xa9, 0xf4, 0xe0, 0xdb, 0x08, 0xbf, + 0x13, 0xf1, 0x95, 0x8a, 0xdd, 0xa8, 0x10, 0xcb, 0x0e, 0xb1, 0x53, 0xe1, 0x25, 0xb0, 0xf7, 0xf6, 0x8c, 0xb2, 0x52, + 0x59, 0xc0, 0xa7, 0x9c, 0xd4, 0x6c, 0x72, 0xfc, 0x52, 0x44, 0x6a, 0x4e, 0xb9, 0x93, 0x20, 0xdd, 0x8d, 0xa3, 0xdd, + 0xd1, 0x6a, 0x6f, 0x26, 0x43, 0xe9, 0x64, 0x70, 0x19, 0xa7, 0x99, 0xcf, 0xd3, 0x6c, 0x84, 0x4c, 0x05, 0x04, 0xff, + 0x8d, 0x5c, 0x0c, 0xad, 0xff, 0xf4, 0xc5, 0x4f, 0xe3, 0x9f, 0xb2, 0xd1, 0x05, 0xfe, 0x40, 0x5a, 0xc7, 0xce, 0xc0, + 0x73, 0x76, 0x9a, 0xcd, 0xe5, 0x4f, 0xad, 0xe1, 0xdf, 0xfd, 0xe6, 0xaf, 0x27, 0xcd, 0x1f, 0x47, 0x68, 0xe9, 0xfc, + 0xd4, 0x1a, 0x0c, 0xd5, 0xd3, 0xf0, 0xef, 0xfd, 0x9f, 0xf2, 0xd1, 0x57, 0xb2, 0x70, 0x17, 0xa1, 0xd6, 0x04, 0x4f, + 0x38, 0x69, 0x35, 0x9b, 0xfd, 0xd6, 0x04, 0x4f, 0x39, 0x69, 0xc1, 0xbf, 0xd7, 0xe4, 0x1d, 0x9d, 0x3c, 0xbb, 0x99, + 0x39, 0x17, 0xfd, 0xe5, 0xee, 0xe2, 0x6f, 0x05, 0xf4, 0x3a, 0xfc, 0xfb, 0x4f, 0x3f, 0xe5, 0xf6, 0x83, 0x3e, 0x69, + 0x8d, 0x1a, 0xc8, 0x81, 0xd2, 0xaf, 0x88, 0xf8, 0xeb, 0x0c, 0xbc, 0xe1, 0xdf, 0x15, 0x14, 0xf6, 0x83, 0x9f, 0x2e, + 0x8e, 0xfb, 0x64, 0xb4, 0x74, 0xec, 0xe5, 0x03, 0xb4, 0x44, 0x68, 0xb9, 0x8b, 0x2e, 0xb0, 0x3d, 0xb1, 0x11, 0x1e, + 0x73, 0xd2, 0x7a, 0xd0, 0x9a, 0xe0, 0x73, 0x4e, 0x5a, 0x76, 0x6b, 0x82, 0xdf, 0x70, 0xd2, 0xfa, 0xbb, 0x33, 0xf0, + 0xa4, 0x9b, 0x6d, 0x29, 0x3c, 0x1c, 0x4b, 0x08, 0x72, 0xf8, 0x19, 0xf5, 0x97, 0x9c, 0xf1, 0x98, 0xa2, 0xdd, 0x16, + 0xc3, 0x1f, 0x05, 0x9a, 0x1c, 0x0e, 0x7e, 0x18, 0x30, 0xef, 0x9c, 0xc5, 0x39, 0x2c, 0x36, 0xd0, 0xcc, 0xae, 0x97, + 0x60, 0xe9, 0x0a, 0xc8, 0x3d, 0x8e, 0xaf, 0xfc, 0x78, 0x4e, 0x73, 0x8f, 0x16, 0x08, 0xc7, 0xe4, 0x23, 0x77, 0x3a, + 0x08, 0xbf, 0xe0, 0xf0, 0xa3, 0x8b, 0xf0, 0xa9, 0x0a, 0x64, 0xc2, 0x4e, 0x96, 0x44, 0x95, 0xa4, 0x52, 0x65, 0xb1, + 0x11, 0x9e, 0x6c, 0x78, 0xc9, 0x23, 0x70, 0x30, 0x20, 0x7c, 0x55, 0x0b, 0x7b, 0xe2, 0x1b, 0xa2, 0x49, 0xe2, 0x7d, + 0x46, 0xe9, 0x77, 0x7e, 0xfc, 0x91, 0x66, 0xce, 0x09, 0xee, 0x74, 0x1f, 0x63, 0xe1, 0x87, 0xde, 0xe9, 0xa0, 0x5e, + 0x19, 0xb3, 0x7a, 0xcb, 0x65, 0xa8, 0x00, 0xa4, 0x6c, 0xdd, 0x1d, 0x03, 0x2b, 0xbe, 0x93, 0xac, 0xf9, 0xac, 0x32, + 0xff, 0xda, 0x46, 0xf5, 0xf8, 0x28, 0x4b, 0xae, 0xfc, 0x98, 0x85, 0x16, 0xa7, 0xd3, 0x59, 0xec, 0x73, 0x6a, 0xa9, + 0xf9, 0x5a, 0x3e, 0x74, 0x64, 0x97, 0x3a, 0xc3, 0xcc, 0xb0, 0x39, 0x67, 0x3a, 0xf0, 0x04, 0x7b, 0xc5, 0x81, 0x28, + 0x95, 0xd2, 0x3b, 0x9e, 0x56, 0x41, 0xb0, 0xd5, 0x38, 0x5f, 0xb3, 0x03, 0xbe, 0xb0, 0x91, 0x90, 0xcf, 0x39, 0x86, + 0xa0, 0x25, 0x21, 0xdd, 0x81, 0x7d, 0x9c, 0x5f, 0x4d, 0xfa, 0x36, 0xc4, 0x68, 0x32, 0xf2, 0x41, 0xb8, 0x86, 0xa0, + 0x42, 0x44, 0xda, 0xbd, 0xe8, 0x98, 0xf6, 0xa2, 0x46, 0x43, 0x6b, 0xd1, 0x3e, 0x49, 0x86, 0x91, 0x6c, 0x1e, 0xe0, + 0x10, 0xcf, 0x49, 0xb3, 0x83, 0x67, 0xa4, 0x2d, 0x9a, 0xf4, 0x66, 0xc7, 0xbe, 0x1a, 0x66, 0x6f, 0xcf, 0xc9, 0xdc, + 0xd8, 0xcf, 0xf9, 0x0b, 0xb0, 0xf7, 0xc9, 0x0c, 0x87, 0x24, 0x73, 0xe9, 0x0d, 0x0d, 0x1c, 0x1f, 0xe1, 0x50, 0x71, + 0x1a, 0xd4, 0x43, 0x33, 0x62, 0x54, 0x03, 0x33, 0x82, 0x7c, 0x18, 0x84, 0xc3, 0xce, 0x88, 0x10, 0x62, 0xef, 0x34, + 0x9b, 0xf6, 0x20, 0x23, 0x13, 0xee, 0x41, 0x89, 0xa1, 0x2c, 0x93, 0x29, 0x14, 0x75, 0x8d, 0x22, 0xe7, 0x0d, 0x77, + 0x39, 0xcd, 0xb9, 0x03, 0xc5, 0xe0, 0x01, 0xc8, 0x35, 0x61, 0xdb, 0xc7, 0x2d, 0xbb, 0x01, 0xa5, 0x82, 0x38, 0x11, + 0xce, 0xc8, 0x35, 0xf2, 0xc2, 0xe1, 0xfe, 0xc8, 0x14, 0x00, 0xa2, 0x10, 0x06, 0xbf, 0x1e, 0x84, 0xc3, 0xb6, 0x18, + 0xbc, 0x6f, 0x0f, 0x9c, 0x8c, 0xe4, 0x52, 0x43, 0x1b, 0xe4, 0xde, 0x07, 0x31, 0x55, 0xe4, 0x29, 0xe0, 0xd4, 0xb8, + 0x73, 0xd2, 0xec, 0x7a, 0xce, 0xdc, 0x9c, 0x44, 0x13, 0x06, 0x53, 0x58, 0xc0, 0x01, 0x81, 0xfa, 0x38, 0x23, 0x30, + 0x62, 0xd5, 0xec, 0xda, 0x53, 0xcf, 0x0f, 0xec, 0x07, 0x83, 0x73, 0xee, 0x8d, 0xb9, 0x1c, 0xfe, 0x9c, 0x2f, 0x97, + 0xf0, 0xef, 0x98, 0x0f, 0x32, 0x72, 0x2d, 0x8a, 0x26, 0xaa, 0x68, 0x0a, 0x45, 0x1f, 0x3c, 0x00, 0x15, 0xe7, 0xa5, + 0x96, 0x25, 0xd7, 0x64, 0x4a, 0x04, 0xec, 0x7b, 0x7b, 0xc9, 0x30, 0x6a, 0x74, 0x46, 0xe0, 0xe4, 0xcf, 0x78, 0xfe, + 0x1d, 0xe3, 0x91, 0x63, 0xb7, 0xfa, 0x36, 0x1a, 0xd8, 0x16, 0x2c, 0x6d, 0x2f, 0x6d, 0x10, 0x89, 0x61, 0xbf, 0xf1, + 0x8a, 0x7b, 0xf3, 0x3e, 0x69, 0x0f, 0x1c, 0xa6, 0x5c, 0x7a, 0x08, 0xfb, 0x8a, 0x71, 0xb6, 0xf1, 0x1c, 0x35, 0x18, + 0x6f, 0xe8, 0xe7, 0x39, 0x6a, 0xdc, 0x36, 0xa6, 0xc8, 0xf3, 0x1b, 0xb7, 0x0d, 0x67, 0x4e, 0x08, 0x69, 0x76, 0xcb, + 0x66, 0x5a, 0xfc, 0x45, 0xc8, 0x9b, 0x6a, 0x7f, 0xe7, 0x50, 0x6c, 0x87, 0xb4, 0xe1, 0x24, 0x43, 0x3a, 0x5a, 0x2e, + 0xed, 0xe3, 0x41, 0xdf, 0x46, 0x0d, 0x47, 0x13, 0x5a, 0x4b, 0x53, 0x1a, 0x42, 0x98, 0x8d, 0x0a, 0x15, 0x4f, 0x7a, + 0x52, 0x8b, 0x1d, 0x2d, 0xaa, 0xcd, 0x6e, 0xf0, 0x00, 0x5a, 0x94, 0x86, 0x8c, 0x54, 0x58, 0x67, 0x30, 0x4d, 0x4d, + 0xcc, 0x29, 0x69, 0xe3, 0x8c, 0x68, 0xf7, 0x75, 0x44, 0x78, 0x45, 0xf0, 0x3e, 0xa9, 0xaa, 0xe3, 0x61, 0x80, 0xc3, + 0x11, 0x79, 0x2a, 0x0d, 0x92, 0x9e, 0x76, 0x8e, 0xd3, 0x98, 0x3c, 0x59, 0x89, 0xe2, 0x06, 0x10, 0x60, 0xb9, 0x71, + 0x83, 0x79, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcf, 0x62, 0x50, 0xd2, + 0xba, 0x7a, 0x67, 0xcc, 0xd7, 0x5e, 0xcf, 0xc8, 0x5c, 0xea, 0x4f, 0x22, 0x68, 0xdb, 0x9b, 0x29, 0xcb, 0xd8, 0x41, + 0x78, 0xae, 0xa2, 0xb9, 0x8e, 0xeb, 0xba, 0x33, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, 0x8f, 0x9c, 0x9c, + 0xdc, 0xb8, 0x09, 0xbd, 0x11, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0x1d, 0x47, 0x3d, 0xc1, 0x6e, 0x72, 0x37, + 0x49, 0x43, 0x0a, 0xe8, 0x81, 0xf8, 0xbd, 0x2a, 0x8a, 0xfc, 0xdc, 0x0c, 0x52, 0x55, 0xf0, 0x0d, 0x4d, 0xff, 0xf5, + 0x0c, 0x9c, 0xbe, 0x42, 0xd9, 0x2a, 0x2b, 0x4b, 0x4f, 0x38, 0x42, 0x6c, 0xec, 0xcc, 0x5c, 0x08, 0xee, 0x09, 0x12, + 0x62, 0x60, 0xcb, 0xcd, 0x4c, 0xa2, 0xba, 0x2d, 0xfb, 0x9c, 0x92, 0x70, 0x98, 0x35, 0x1a, 0xc2, 0x11, 0x3d, 0x97, + 0x24, 0x31, 0x43, 0x78, 0x5a, 0xee, 0x2d, 0x5d, 0xef, 0x2d, 0xa9, 0x8f, 0xe4, 0x4c, 0xeb, 0x0e, 0xdd, 0x06, 0xe3, + 0x48, 0xf8, 0x0a, 0xb9, 0x73, 0x8b, 0xf0, 0x98, 0xb4, 0x9c, 0xa1, 0x3b, 0xf8, 0xf3, 0x08, 0x0d, 0x1c, 0xf7, 0x2b, + 0xd4, 0x92, 0x8c, 0x63, 0x8a, 0x7a, 0xbe, 0x1c, 0x62, 0x21, 0xa2, 0x98, 0x1d, 0x2c, 0x7c, 0x89, 0x5e, 0x8a, 0x13, + 0x7f, 0x4a, 0xbd, 0x31, 0xec, 0x71, 0x4d, 0x37, 0x6f, 0x31, 0xd0, 0x91, 0x37, 0x56, 0x9c, 0xc4, 0xb5, 0x07, 0xbf, + 0xf0, 0xf2, 0x69, 0x60, 0x0f, 0xbe, 0xae, 0x9e, 0xfe, 0x6c, 0x0f, 0xbe, 0xe5, 0xde, 0xb7, 0x85, 0x72, 0x77, 0xd7, + 0x86, 0x78, 0xa8, 0x87, 0x28, 0xe4, 0xc2, 0x18, 0x98, 0x9b, 0xa3, 0x75, 0x47, 0xc7, 0x0c, 0x15, 0x6c, 0x5c, 0xb2, + 0xa2, 0xdc, 0xe5, 0xfe, 0x04, 0x50, 0x6a, 0xac, 0x40, 0x6e, 0x46, 0xf7, 0xab, 0x09, 0x03, 0xa1, 0x68, 0x6a, 0x05, + 0x54, 0xce, 0xfa, 0x6d, 0xb4, 0xa8, 0xd5, 0x15, 0x1a, 0x53, 0x3d, 0x9a, 0x5e, 0x72, 0xe9, 0x29, 0x69, 0xf7, 0xa6, + 0xc7, 0xb3, 0xde, 0xb4, 0xd1, 0x40, 0xb9, 0x26, 0xac, 0xf9, 0x70, 0x3a, 0xc2, 0xaf, 0xc1, 0xab, 0x67, 0x52, 0x12, + 0xae, 0x4d, 0xaf, 0xab, 0xa6, 0xd7, 0x68, 0xa4, 0x05, 0xea, 0x19, 0x4d, 0x67, 0xb2, 0x69, 0x51, 0x48, 0x9c, 0xac, + 0x12, 0xda, 0x11, 0x12, 0x25, 0x90, 0x12, 0x45, 0x08, 0x39, 0xe3, 0x68, 0x63, 0xaf, 0xd0, 0x27, 0x34, 0x17, 0x3b, + 0x16, 0x98, 0xa7, 0x94, 0x11, 0x0e, 0x60, 0x01, 0x9a, 0x96, 0xae, 0xe0, 0x5b, 0x3c, 0x6f, 0x74, 0x04, 0x91, 0x37, + 0x3b, 0xbd, 0x7a, 0x5f, 0x8f, 0xaa, 0xbe, 0xf0, 0xbc, 0x41, 0x6e, 0x4b, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0xe3, + 0x9d, 0x7a, 0xdf, 0xd6, 0x22, 0x10, 0x27, 0xab, 0xa9, 0x19, 0x5a, 0xbe, 0x56, 0x12, 0x95, 0xb9, 0x2c, 0x49, 0x68, + 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, 0x12, 0xe0, 0x3b, 0xc2, 0xec, + 0xc2, 0x29, 0xce, 0x70, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x54, 0x27, 0xb5, 0x70, 0xc1, 0x81, 0x7c, 0xc2, 0x0c, 0x89, + 0x94, 0x13, 0xea, 0x9e, 0xef, 0x9e, 0xa6, 0x77, 0x9a, 0x64, 0x43, 0x36, 0xf2, 0x44, 0xb5, 0x58, 0xf1, 0xad, 0x80, + 0xbc, 0x73, 0x38, 0x2a, 0xc3, 0x23, 0xae, 0x60, 0x7f, 0x4f, 0x59, 0x46, 0x85, 0x06, 0xbe, 0xab, 0xcd, 0x3e, 0xbf, + 0xae, 0x3e, 0xfa, 0xa6, 0xf3, 0x06, 0x10, 0x19, 0x80, 0x6f, 0x27, 0x25, 0x6b, 0xd5, 0xce, 0x77, 0x4f, 0xde, 0x6c, + 0x32, 0x81, 0x97, 0x4b, 0x65, 0xfc, 0xfa, 0xa0, 0xd9, 0xe0, 0xa0, 0x82, 0xd4, 0x57, 0x3f, 0x3c, 0xc7, 0x17, 0x0a, + 0x52, 0xe0, 0x24, 0x40, 0x45, 0xe7, 0xbb, 0x27, 0xef, 0x9d, 0x44, 0xb8, 0x96, 0x10, 0x36, 0xa7, 0xed, 0x64, 0xc4, + 0x89, 0x08, 0x45, 0x72, 0xee, 0x25, 0xe3, 0xca, 0x0c, 0xf1, 0xed, 0x45, 0xe2, 0x25, 0xd8, 0x0f, 0x43, 0x36, 0x22, + 0xbe, 0xc2, 0x00, 0xf1, 0x11, 0xf6, 0x6b, 0x66, 0x19, 0x81, 0x05, 0x10, 0x63, 0x9d, 0xc1, 0x4a, 0xb8, 0x52, 0xf1, + 0x43, 0xd8, 0x17, 0xa3, 0xf2, 0x42, 0x8a, 0x8e, 0x9f, 0xd7, 0x72, 0xd3, 0x2a, 0x6b, 0xf4, 0x5b, 0xb0, 0x9c, 0xf4, + 0xc3, 0x6b, 0xd5, 0x75, 0x59, 0xf0, 0x54, 0x27, 0x91, 0x9d, 0xef, 0x9e, 0xbc, 0x52, 0x79, 0x64, 0x33, 0x5f, 0x73, + 0xfb, 0x35, 0x0b, 0xf3, 0xe4, 0x95, 0x5b, 0xbd, 0x15, 0x95, 0xcf, 0x77, 0x4f, 0x3e, 0x6c, 0xaa, 0x06, 0xe5, 0xc5, + 0xbc, 0x32, 0xf1, 0x05, 0x7c, 0x0b, 0x1a, 0x7b, 0x0b, 0x25, 0x1a, 0x3c, 0x56, 0x60, 0x21, 0x8e, 0xbc, 0xbc, 0x28, + 0x3d, 0x23, 0x4f, 0x71, 0x4a, 0x44, 0x1c, 0xa8, 0xbe, 0x6a, 0x4a, 0xc9, 0x63, 0x69, 0x72, 0x16, 0xa4, 0x33, 0xba, + 0x25, 0x38, 0x74, 0x82, 0x5c, 0x36, 0x85, 0x04, 0x1a, 0x01, 0x3a, 0xc3, 0x3b, 0x6d, 0xd4, 0xab, 0x0b, 0xaf, 0x54, + 0x10, 0x69, 0x56, 0x93, 0x2c, 0x38, 0x22, 0x6d, 0xec, 0x93, 0x36, 0x0e, 0x48, 0x3e, 0x6c, 0x4b, 0xf1, 0xd0, 0x0b, + 0xca, 0x7e, 0xa5, 0x90, 0x81, 0xdc, 0xb0, 0x40, 0xee, 0x56, 0x29, 0x7e, 0xc3, 0x5e, 0x20, 0x5c, 0x8f, 0x42, 0xa2, + 0x87, 0xd2, 0x68, 0x75, 0x32, 0x9c, 0x89, 0x8e, 0xcf, 0xd8, 0x65, 0x0c, 0xd9, 0x25, 0x30, 0x2b, 0xcc, 0x91, 0x57, + 0x56, 0xed, 0xa8, 0xaa, 0x81, 0x2b, 0xd6, 0x29, 0xc3, 0x81, 0x0b, 0x8c, 0x1b, 0x07, 0x2a, 0x19, 0x27, 0x5f, 0x6f, + 0xf2, 0x70, 0x6f, 0xcf, 0x91, 0x8d, 0xbe, 0xe3, 0x4e, 0xa6, 0xdf, 0x57, 0xa1, 0xbb, 0x6f, 0x25, 0xaf, 0x08, 0x91, + 0x80, 0xbf, 0xd1, 0xf0, 0x47, 0x05, 0xc4, 0xa1, 0x9d, 0xa0, 0x8e, 0x41, 0x0d, 0xbc, 0xd0, 0xf4, 0xea, 0xd3, 0x6f, + 0x34, 0xca, 0x30, 0x6d, 0x1d, 0x5b, 0x27, 0x38, 0x2d, 0xae, 0x9c, 0x32, 0xff, 0xa7, 0xbd, 0x96, 0x35, 0xa5, 0x41, + 0x40, 0xcc, 0xa4, 0x59, 0xa6, 0x27, 0x63, 0x6c, 0x09, 0x06, 0xf5, 0x5e, 0xa8, 0xc4, 0x05, 0x2c, 0x72, 0xac, 0x54, + 0x25, 0xcd, 0xce, 0xba, 0xc8, 0xd3, 0x95, 0x20, 0x2c, 0x05, 0x95, 0x1a, 0x85, 0x22, 0xef, 0x57, 0xeb, 0x99, 0x97, + 0x38, 0x47, 0xca, 0xc7, 0x25, 0xa0, 0x10, 0xc8, 0xea, 0x96, 0x48, 0x79, 0x4e, 0x26, 0xdb, 0x49, 0xfe, 0xc4, 0x20, + 0xf9, 0x27, 0x84, 0x1a, 0xe4, 0x2f, 0x3d, 0x1c, 0x6e, 0xaa, 0x5c, 0x0b, 0xb9, 0x7e, 0x75, 0x3a, 0x23, 0xe0, 0x43, + 0xab, 0x63, 0xb4, 0x16, 0x57, 0xdc, 0xc2, 0x50, 0xcc, 0x1d, 0x22, 0xbc, 0x90, 0x58, 0x07, 0x81, 0x9d, 0x2a, 0xaa, + 0x06, 0x43, 0x6f, 0x72, 0xe9, 0x99, 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0x01, 0xd1, 0xd3, 0xd9, 0xfa, 0xce, 0x35, 0x32, + 0x40, 0x61, 0xd6, 0xc6, 0xc6, 0xad, 0xe7, 0x83, 0xc2, 0xf8, 0x65, 0x20, 0xbb, 0xce, 0x7c, 0x56, 0x36, 0xa1, 0x96, + 0x7f, 0x00, 0x6d, 0xa7, 0x23, 0x6a, 0x50, 0xa3, 0x5b, 0xe0, 0x47, 0x32, 0x0f, 0xd5, 0xcf, 0xb6, 0xb0, 0x8f, 0x13, + 0x51, 0x81, 0x26, 0xe1, 0xe6, 0xd7, 0x4f, 0x0a, 0x45, 0x26, 0x12, 0x34, 0xb4, 0x00, 0xfe, 0x27, 0x49, 0x1e, 0xe8, + 0x46, 0xc8, 0x05, 0x40, 0xd0, 0x44, 0xe0, 0xa9, 0x42, 0x98, 0x6d, 0x57, 0xce, 0xf7, 0xe7, 0x3b, 0x84, 0x4c, 0x2a, + 0xe7, 0xe3, 0xbb, 0x2a, 0xfb, 0x0a, 0xc8, 0x02, 0x79, 0x60, 0x3c, 0x96, 0x05, 0x32, 0x7e, 0x79, 0xaa, 0xab, 0x0b, + 0x03, 0xd2, 0xad, 0xf4, 0x6d, 0x23, 0xb6, 0x29, 0xbc, 0x72, 0xf2, 0xbd, 0x46, 0xc3, 0xca, 0xdb, 0x5d, 0x78, 0xfb, + 0x92, 0x0b, 0x18, 0xe1, 0xf9, 0xbd, 0xa8, 0xad, 0xfb, 0x2d, 0x3e, 0xae, 0xa6, 0xb0, 0xac, 0x2c, 0x8a, 0xcb, 0x92, + 0x9c, 0x66, 0xfc, 0x09, 0x1d, 0xa7, 0x19, 0x84, 0x2c, 0x4a, 0x9c, 0xa0, 0x62, 0xd7, 0x70, 0xdb, 0x89, 0xf9, 0x19, + 0x71, 0x82, 0x95, 0x09, 0x8a, 0x5f, 0x1f, 0x45, 0xd4, 0xfa, 0x7c, 0xb5, 0xd5, 0x64, 0x6f, 0xef, 0x5d, 0x85, 0x26, + 0x05, 0xa5, 0x80, 0xc2, 0x60, 0x5a, 0x52, 0xa5, 0x51, 0xa1, 0xdc, 0x5d, 0xa7, 0x74, 0x01, 0x68, 0x86, 0x61, 0xf2, + 0x9e, 0xe7, 0x84, 0x17, 0x93, 0x55, 0x16, 0xaf, 0x5c, 0x13, 0xcc, 0x34, 0x5b, 0x80, 0xc3, 0x83, 0xa1, 0x2d, 0x7d, + 0x45, 0x79, 0x95, 0x12, 0x5b, 0xc2, 0x70, 0x0a, 0xc8, 0x72, 0x84, 0x11, 0x62, 0x50, 0xe0, 0x46, 0xa3, 0xe4, 0x2d, + 0xe8, 0x95, 0x11, 0xce, 0xdd, 0x08, 0x92, 0x60, 0x6b, 0x5b, 0x16, 0x21, 0x2c, 0x33, 0x73, 0x8c, 0x5c, 0x82, 0x93, + 0xe7, 0x9b, 0x3c, 0xca, 0x9a, 0xa8, 0xa9, 0x90, 0x3a, 0x50, 0x23, 0x45, 0x65, 0x03, 0xf7, 0xca, 0x61, 0x4a, 0x71, + 0xd3, 0x71, 0x33, 0x60, 0xc0, 0x3f, 0x73, 0x47, 0xc6, 0xa2, 0x40, 0x66, 0x64, 0xee, 0xdc, 0xa9, 0x0d, 0xdd, 0xcb, + 0x44, 0x33, 0xac, 0x10, 0x17, 0x99, 0x68, 0xca, 0x44, 0x5c, 0xef, 0xb4, 0xe2, 0xa5, 0x57, 0x32, 0x8f, 0x9a, 0x6b, + 0x2e, 0x58, 0x65, 0x92, 0x18, 0xd3, 0xbf, 0x92, 0xa9, 0xd1, 0x65, 0x25, 0x50, 0xc3, 0xe8, 0xb5, 0xf5, 0x44, 0xac, + 0x01, 0x2d, 0x80, 0xbe, 0x16, 0xa7, 0xdc, 0x58, 0x51, 0xed, 0xc3, 0x16, 0x63, 0x1a, 0x52, 0xff, 0x1d, 0xe4, 0xba, + 0xac, 0xee, 0xf9, 0xe7, 0x42, 0x16, 0x32, 0x9c, 0xd7, 0x18, 0x7b, 0x2a, 0x18, 0x3b, 0x02, 0x3d, 0x4d, 0xa7, 0x7f, + 0x0f, 0x54, 0xca, 0x8b, 0xca, 0x5d, 0x74, 0x14, 0x89, 0xbd, 0x2e, 0xc3, 0xe5, 0xc6, 0xef, 0x95, 0xd5, 0xf0, 0x18, + 0x81, 0x34, 0x20, 0xac, 0x38, 0x7b, 0x8a, 0x70, 0xde, 0x68, 0xf4, 0xf2, 0x63, 0x5a, 0xb9, 0x48, 0x2a, 0x18, 0x19, + 0x44, 0x74, 0x81, 0xe0, 0x6b, 0x32, 0x14, 0x62, 0xfe, 0x3a, 0x3f, 0x3b, 0x07, 0x57, 0xfb, 0xc9, 0x3b, 0xc7, 0xe4, + 0x6a, 0x66, 0xdd, 0x32, 0x68, 0x0a, 0xf3, 0x71, 0xaa, 0x78, 0xcb, 0xdb, 0xbb, 0x33, 0x3c, 0x00, 0xee, 0x9d, 0x0e, + 0x86, 0x6c, 0x34, 0xd4, 0xe3, 0x92, 0x25, 0x94, 0xbb, 0xaf, 0x87, 0xaa, 0xc4, 0x44, 0x73, 0xb0, 0x1e, 0xaf, 0x4c, + 0x59, 0x4e, 0xf2, 0xa2, 0xc8, 0x69, 0x15, 0xdf, 0x5f, 0xc9, 0xc0, 0x14, 0xc2, 0x65, 0xdd, 0xd9, 0x7e, 0x3a, 0x23, + 0x1c, 0x1b, 0x84, 0xfa, 0x76, 0x5b, 0xe8, 0xa3, 0x02, 0x13, 0xf6, 0xb5, 0x12, 0x8a, 0xdf, 0x6e, 0x12, 0x8a, 0x38, + 0x55, 0x5b, 0x5e, 0x08, 0xc4, 0xce, 0x3d, 0x04, 0xa2, 0x72, 0xb2, 0x6b, 0x99, 0x08, 0xea, 0x48, 0x4d, 0x26, 0xd6, + 0x97, 0x94, 0xa4, 0x98, 0xa9, 0xd5, 0xe8, 0x77, 0x97, 0x4b, 0x36, 0x6c, 0x83, 0x13, 0xc9, 0xb6, 0xe1, 0x67, 0x47, + 0xfe, 0x34, 0x38, 0xb1, 0x74, 0x02, 0x3b, 0xac, 0x34, 0x59, 0x90, 0x0b, 0x69, 0xce, 0x8e, 0xc8, 0xca, 0x12, 0x34, + 0xad, 0x28, 0x48, 0x11, 0x38, 0x61, 0x65, 0x94, 0x09, 0x20, 0x16, 0xb2, 0x42, 0x19, 0x90, 0xce, 0xc6, 0xf4, 0x3f, + 0x6d, 0x5e, 0x7e, 0x5a, 0x13, 0xad, 0xc9, 0x15, 0xa9, 0x3e, 0xd4, 0x12, 0x0e, 0x14, 0x04, 0x4a, 0x3f, 0xdc, 0x11, + 0x26, 0x68, 0x25, 0xca, 0x91, 0x29, 0x87, 0x70, 0x1b, 0x5c, 0x68, 0x3b, 0xef, 0x64, 0x80, 0x77, 0x83, 0x34, 0xc1, + 0x99, 0x41, 0xd7, 0xcf, 0x09, 0xaf, 0xb1, 0x92, 0x88, 0x28, 0x4b, 0x09, 0x07, 0x82, 0x4c, 0x39, 0x49, 0x87, 0xed, + 0x11, 0x28, 0xa0, 0x3d, 0xff, 0x38, 0xad, 0x4c, 0x60, 0xbf, 0xd1, 0x40, 0x81, 0x1e, 0x35, 0x1a, 0xb2, 0x86, 0x3f, + 0xc2, 0x14, 0xfb, 0xd2, 0x30, 0x39, 0xdd, 0xdb, 0x73, 0x82, 0x6a, 0xdc, 0xa1, 0x3f, 0x42, 0x38, 0x5b, 0x2e, 0x1d, + 0x01, 0x56, 0x80, 0x96, 0xcb, 0xc0, 0x04, 0x4b, 0xbc, 0x86, 0x66, 0x93, 0x01, 0x27, 0x13, 0x21, 0x00, 0x27, 0x00, + 0x61, 0x83, 0x38, 0x81, 0x72, 0xee, 0x05, 0xe0, 0x8c, 0x6a, 0xa4, 0x43, 0xbf, 0xd1, 0x19, 0x19, 0x8c, 0x6b, 0xe8, + 0x8f, 0x48, 0x50, 0x40, 0x72, 0x6b, 0xae, 0x44, 0xe4, 0xcf, 0x20, 0xca, 0x7e, 0x16, 0x92, 0x45, 0x76, 0x68, 0xae, + 0xc6, 0xaa, 0x33, 0xa0, 0xa4, 0x28, 0xb5, 0xac, 0xba, 0x5e, 0x2d, 0x0b, 0xa2, 0xac, 0x84, 0x55, 0x2c, 0x78, 0x00, + 0x96, 0x7d, 0x49, 0xe6, 0xbf, 0xf0, 0x32, 0xcd, 0xfa, 0xdb, 0x8d, 0xc9, 0xd5, 0xae, 0xeb, 0xfa, 0xd9, 0x44, 0x44, + 0x32, 0x74, 0x14, 0x56, 0x10, 0xff, 0xbe, 0x02, 0xd3, 0x18, 0x78, 0x58, 0x8e, 0x35, 0x22, 0x12, 0x7c, 0xad, 0xda, + 0xe8, 0x13, 0x25, 0xbf, 0x6e, 0xf4, 0x32, 0x48, 0x48, 0xbe, 0xfe, 0xad, 0x90, 0x1c, 0x28, 0x48, 0x24, 0x79, 0xac, + 0xe0, 0x6c, 0x0b, 0x2e, 0x7e, 0xe5, 0x2b, 0x38, 0xdb, 0x8e, 0xdb, 0x92, 0x21, 0x6c, 0x83, 0xcf, 0xe0, 0x0d, 0x12, + 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x70, 0x55, 0xf7, 0x92, 0xac, 0x14, 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, + 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0x4d, 0x90, 0xe1, 0x12, 0xa8, 0xa7, 0xae, 0x00, 0x39, 0x29, 0x5f, 0x3b, 0xa4, 0x22, + 0xec, 0x48, 0x25, 0xce, 0x0d, 0xfc, 0x19, 0x9f, 0x67, 0xa0, 0x4a, 0xe5, 0xfa, 0x37, 0x14, 0xc3, 0x59, 0x10, 0x51, + 0x06, 0x3f, 0xa0, 0x60, 0xe6, 0xe7, 0x39, 0xbb, 0x92, 0x65, 0xea, 0x37, 0xce, 0x88, 0x26, 0xe5, 0x5c, 0xea, 0x84, + 0x29, 0xea, 0xa5, 0x8a, 0x4e, 0xeb, 0x68, 0x7b, 0x76, 0x45, 0x13, 0xfe, 0x92, 0xe5, 0x9c, 0x26, 0x30, 0xfd, 0x8a, + 0xe2, 0x60, 0x46, 0x39, 0x82, 0x0d, 0x5b, 0x6b, 0xe5, 0x87, 0xe1, 0x9d, 0x4d, 0x78, 0x5d, 0x07, 0x8a, 0xfc, 0x24, + 0x8c, 0xe5, 0x20, 0x66, 0x42, 0xa3, 0x4e, 0xe2, 0x2c, 0x6b, 0x9a, 0xf9, 0x34, 0x95, 0xb2, 0x21, 0xb8, 0xbb, 0xc3, + 0x88, 0x96, 0x04, 0x5a, 0x7a, 0xde, 0xa9, 0xb5, 0x40, 0xc0, 0x7b, 0xcb, 0x22, 0x98, 0x33, 0xc1, 0xdc, 0xe0, 0xa8, + 0x6e, 0x1d, 0x4e, 0x4d, 0x37, 0xdf, 0x6d, 0x3c, 0xd8, 0xb6, 0x49, 0x38, 0x08, 0x3a, 0x79, 0xb8, 0xdd, 0xb2, 0x7a, + 0xa5, 0x25, 0x87, 0x96, 0x16, 0xec, 0xbe, 0x8c, 0x19, 0x2d, 0x34, 0x79, 0x21, 0xbd, 0x15, 0x77, 0x39, 0xf9, 0x05, + 0x4e, 0x0e, 0x3d, 0xe7, 0xd3, 0x78, 0xe5, 0x80, 0x4c, 0x6f, 0xb7, 0xd4, 0xfe, 0x77, 0xb9, 0xf3, 0x04, 0xbf, 0x82, + 0xb0, 0xee, 0x37, 0x55, 0xf5, 0xf5, 0x70, 0xee, 0x37, 0x15, 0x82, 0xbe, 0xf1, 0xd6, 0xea, 0x19, 0x61, 0xdc, 0xae, + 0x7b, 0xe4, 0xb6, 0x6d, 0xad, 0x2d, 0xfd, 0x28, 0x83, 0x48, 0x32, 0xd5, 0x52, 0xec, 0x07, 0x5c, 0x25, 0xaa, 0x41, + 0xc2, 0x5c, 0xdd, 0x42, 0xa2, 0x2a, 0xc5, 0x50, 0xea, 0xf0, 0xdb, 0x96, 0x47, 0xc9, 0x98, 0x54, 0xda, 0x19, 0x6f, + 0xfd, 0x8c, 0xef, 0xc2, 0x2e, 0xcb, 0xd6, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0xf7, 0x1b, 0xc2, 0x30, 0xb6, 0x73, + 0x79, 0x18, 0xc8, 0xec, 0x9f, 0x64, 0x5a, 0x77, 0xab, 0x5b, 0x19, 0xaf, 0xc1, 0xfe, 0x47, 0x38, 0xd2, 0x47, 0xe4, + 0xa8, 0xe2, 0xc0, 0xd4, 0x5b, 0x14, 0xa5, 0x53, 0x20, 0x93, 0xca, 0x5b, 0x82, 0x70, 0x56, 0x88, 0xf0, 0xf6, 0xf7, + 0xf8, 0x07, 0xc5, 0x12, 0xcf, 0x4b, 0x8e, 0xf3, 0xec, 0xbe, 0x1c, 0x51, 0x82, 0x5f, 0x46, 0xef, 0x81, 0x8e, 0x05, + 0x85, 0x16, 0x9a, 0x8a, 0x9e, 0xa6, 0x6a, 0x22, 0x5b, 0xf3, 0x52, 0x31, 0x2d, 0x33, 0x6a, 0xc4, 0x30, 0x1b, 0x12, + 0x39, 0xb5, 0x95, 0xcd, 0xcb, 0x5d, 0x55, 0x1b, 0x17, 0x6d, 0xc1, 0x62, 0x15, 0x58, 0x5c, 0x2e, 0x9d, 0x3a, 0xaa, + 0x09, 0x33, 0xe2, 0x18, 0x08, 0x33, 0x23, 0xa1, 0xa2, 0xa6, 0x59, 0xcb, 0x36, 0x0e, 0x5a, 0xcd, 0x27, 0xd2, 0xba, + 0x79, 0x0d, 0x0e, 0xd3, 0x85, 0x20, 0x9b, 0x9b, 0x3e, 0x05, 0x2c, 0x67, 0x57, 0x0e, 0x64, 0x60, 0xe8, 0xc7, 0x32, + 0x57, 0xb6, 0x4a, 0x6a, 0xdd, 0x80, 0x5f, 0x74, 0x47, 0xb6, 0xac, 0x42, 0xdd, 0xfa, 0x7b, 0x23, 0xd7, 0xe8, 0x69, + 0xba, 0x2d, 0xd7, 0xa8, 0xa6, 0xed, 0xee, 0xb4, 0xd1, 0xdd, 0x79, 0xa9, 0x72, 0xac, 0xcd, 0x55, 0x7e, 0xc3, 0x70, + 0x1d, 0xa0, 0x4d, 0x89, 0x66, 0xcd, 0x55, 0x4e, 0x8b, 0xe2, 0xbc, 0x3c, 0x4d, 0x20, 0x52, 0x77, 0xce, 0x25, 0xfd, + 0x2b, 0xab, 0x51, 0x1c, 0xca, 0x75, 0xbe, 0x27, 0x93, 0x38, 0xbd, 0xf4, 0xe3, 0xf7, 0x30, 0x5e, 0xf5, 0xf2, 0xf9, + 0x6d, 0x98, 0xf9, 0x9c, 0x2a, 0xee, 0x52, 0xc1, 0xf0, 0xbd, 0x01, 0xc3, 0xf7, 0x92, 0x4f, 0x57, 0xed, 0xf1, 0xe2, + 0x65, 0xd9, 0x81, 0x77, 0x5e, 0x68, 0x96, 0x71, 0xcb, 0x37, 0x8f, 0xb1, 0xca, 0xc2, 0x6e, 0x4b, 0x16, 0x76, 0xcb, + 0x9d, 0xd5, 0xae, 0x1c, 0xe7, 0x87, 0xcd, 0xbd, 0xac, 0x73, 0xb6, 0x1f, 0xaa, 0x8d, 0xff, 0x83, 0x77, 0x67, 0x1b, + 0x83, 0xcb, 0xed, 0xbb, 0xfb, 0x22, 0x59, 0x45, 0x82, 0xfc, 0x12, 0x92, 0x0e, 0x38, 0xe9, 0x1b, 0x87, 0x0e, 0x2a, + 0x39, 0xa5, 0xf3, 0x80, 0x9c, 0x60, 0x9e, 0xf3, 0x74, 0xaa, 0xfa, 0xcc, 0xd5, 0x49, 0x23, 0xf1, 0x12, 0x5c, 0xd1, + 0x22, 0xd6, 0xee, 0xd5, 0xcf, 0x72, 0x2d, 0x3e, 0xb2, 0x24, 0xf4, 0x72, 0xac, 0xa4, 0x48, 0xee, 0xa5, 0x05, 0xd1, + 0xd9, 0xc6, 0xeb, 0xef, 0xf0, 0x98, 0x25, 0x2c, 0x8f, 0x68, 0xe6, 0x64, 0x68, 0xb1, 0x6d, 0xb0, 0x0c, 0x02, 0x32, + 0x72, 0x30, 0xfc, 0xd7, 0xea, 0xd4, 0x9f, 0x0b, 0xbd, 0x81, 0x1f, 0x68, 0x4a, 0x79, 0x94, 0x86, 0x90, 0x96, 0xe2, + 0x86, 0xe5, 0xa1, 0xa6, 0xbd, 0xbd, 0x1d, 0xc7, 0x16, 0x6e, 0x09, 0x38, 0x00, 0x6e, 0xbe, 0x41, 0x83, 0x05, 0x9c, + 0xcf, 0xa9, 0x86, 0xa6, 0x68, 0x41, 0x57, 0x8f, 0xb2, 0x70, 0xf7, 0x23, 0xbd, 0xc5, 0x09, 0x2a, 0x0a, 0x4f, 0x42, + 0x6d, 0x8f, 0x19, 0x8d, 0x43, 0x1b, 0x7f, 0xa4, 0xb7, 0x5e, 0x79, 0x66, 0x5c, 0x1c, 0x71, 0x16, 0x0b, 0x68, 0xa7, + 0xd7, 0x89, 0x8d, 0xab, 0x41, 0xbc, 0x45, 0x81, 0xd3, 0x8c, 0x4d, 0x80, 0x38, 0xbf, 0xa1, 0xb7, 0x9e, 0xec, 0x8f, + 0x19, 0xe7, 0xf5, 0xd0, 0x42, 0xa3, 0xde, 0x35, 0x8a, 0xcd, 0x65, 0x50, 0x06, 0xc5, 0x50, 0xb4, 0x1d, 0x91, 0x5a, + 0xbd, 0xca, 0x3c, 0x44, 0xa8, 0xb8, 0xef, 0x54, 0xf0, 0x37, 0xa6, 0x68, 0xe3, 0xb5, 0xcc, 0xd7, 0x95, 0x46, 0x14, + 0x1a, 0x54, 0x99, 0x1e, 0xbb, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, 0x84, 0x60, 0x38, 0xc2, 0xbe, 0xe1, 0xaa, 0x53, 0xef, + 0xaf, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xa8, 0xda, 0x59, 0xbb, 0x0e, 0xe0, 0x1d, 0x12, 0x5a, 0x7c, 0x71, 0x26, + 0xb3, 0xd0, 0xd9, 0xa2, 0x7f, 0xe3, 0xc4, 0x59, 0xe8, 0x29, 0x78, 0x89, 0x89, 0x45, 0x5e, 0x00, 0x15, 0x2a, 0xfa, + 0x92, 0x09, 0x80, 0x6c, 0xec, 0xb0, 0x35, 0xa9, 0x99, 0x0a, 0xa9, 0xe9, 0x1a, 0x18, 0xdf, 0x22, 0x25, 0xa9, 0x40, + 0x86, 0x50, 0x22, 0x85, 0xd0, 0x53, 0x8b, 0xab, 0x48, 0xc8, 0x5c, 0xd0, 0xf2, 0x04, 0x9d, 0x5c, 0xf3, 0xb4, 0x06, + 0x96, 0x23, 0xfa, 0x41, 0x85, 0x07, 0x53, 0xa2, 0xb2, 0x42, 0x51, 0x1e, 0xcd, 0xd6, 0xe9, 0xad, 0x4e, 0xe6, 0xea, + 0x69, 0x11, 0x8d, 0x12, 0x27, 0x42, 0x8b, 0xc4, 0x89, 0x70, 0x0a, 0xe9, 0x88, 0x59, 0x51, 0xc2, 0x4f, 0xcd, 0xd5, + 0xa8, 0x25, 0x2b, 0x6f, 0x3e, 0xe5, 0x07, 0xca, 0x3c, 0x87, 0x14, 0x4d, 0x9c, 0x68, 0x9e, 0x92, 0x38, 0xe2, 0xb8, + 0x9d, 0xb1, 0x6c, 0xdf, 0xab, 0x04, 0x1d, 0x05, 0xd8, 0xdf, 0xb8, 0xb3, 0x30, 0x66, 0x61, 0x9e, 0xe8, 0x56, 0xa7, + 0xfe, 0x54, 0xb0, 0xaf, 0xca, 0x21, 0x75, 0x72, 0xb2, 0x22, 0x71, 0xee, 0x4e, 0xb5, 0xfc, 0x65, 0x4e, 0xb3, 0xdb, + 0x33, 0x0a, 0xa9, 0xce, 0x29, 0x1c, 0xf8, 0xad, 0x96, 0xa1, 0xca, 0x53, 0x1f, 0xa4, 0x42, 0x59, 0x29, 0xea, 0xe7, + 0x00, 0x57, 0x4f, 0x09, 0x16, 0x22, 0xda, 0x68, 0x38, 0x62, 0xe4, 0x6e, 0xa1, 0x5b, 0xcf, 0x4f, 0xd2, 0x1e, 0x03, + 0xff, 0x5a, 0x85, 0x69, 0x15, 0x2c, 0xc0, 0x99, 0x79, 0x26, 0x75, 0x98, 0x8f, 0x56, 0xbd, 0x32, 0x50, 0x04, 0xe1, + 0xbb, 0x74, 0xfb, 0x54, 0x37, 0x25, 0xcd, 0x6e, 0x9f, 0x6a, 0x2d, 0xe8, 0x27, 0x12, 0x7e, 0xb0, 0x1a, 0xa7, 0x3c, + 0xc1, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0x5f, 0x7a, 0x8e, 0xf3, 0x17, 0x95, 0x32, 0xe8, 0x42, 0x2c, 0xf6, 0x2c, + 0x4e, 0x35, 0x13, 0xaf, 0xc6, 0xff, 0xcb, 0xda, 0xf8, 0x7f, 0x31, 0x4e, 0x9d, 0x82, 0x69, 0x34, 0x49, 0x68, 0xa8, + 0x59, 0x27, 0x92, 0x04, 0x28, 0xf4, 0xb6, 0x8c, 0x93, 0x8f, 0x17, 0x1e, 0x68, 0x5c, 0x8b, 0x71, 0x9a, 0xf0, 0xe6, + 0xd8, 0x9f, 0xb2, 0xf8, 0xd6, 0x9b, 0xb3, 0xe6, 0x34, 0x4d, 0xd2, 0x7c, 0xe6, 0x07, 0x14, 0xe7, 0xb7, 0x39, 0xa7, + 0xd3, 0xe6, 0x9c, 0xe1, 0xe7, 0x34, 0xbe, 0xa2, 0x9c, 0x05, 0x3e, 0xb6, 0x4f, 0x32, 0xe6, 0xc7, 0xd6, 0x6b, 0x3f, + 0xcb, 0xd2, 0x6b, 0x1b, 0xbf, 0x4b, 0x2f, 0x53, 0x9e, 0xe2, 0x37, 0x37, 0xb7, 0x13, 0x9a, 0xe0, 0x0f, 0x97, 0xf3, + 0x84, 0xcf, 0x71, 0xee, 0x27, 0x79, 0x33, 0xa7, 0x19, 0x1b, 0xf7, 0x82, 0x34, 0x4e, 0xb3, 0x26, 0x64, 0x6c, 0x4f, + 0xa9, 0x17, 0xb3, 0x49, 0xc4, 0xad, 0xd0, 0xcf, 0x3e, 0xf6, 0x9a, 0xcd, 0x59, 0xc6, 0xa6, 0x7e, 0x76, 0xdb, 0x14, + 0x35, 0xbc, 0x2f, 0xdb, 0xfb, 0xfe, 0xe3, 0xf1, 0x41, 0x8f, 0x67, 0x7e, 0x92, 0x33, 0x58, 0x26, 0xcf, 0x8f, 0x63, + 0x6b, 0xff, 0xb0, 0x3d, 0xcd, 0x77, 0x64, 0x20, 0xcf, 0x4f, 0x78, 0x71, 0x81, 0xdf, 0x03, 0xdc, 0xee, 0x25, 0x4f, + 0xf0, 0xe5, 0x9c, 0xf3, 0x34, 0x59, 0x04, 0xf3, 0x2c, 0x4f, 0x33, 0x6f, 0x96, 0xb2, 0x84, 0xd3, 0xac, 0x77, 0x99, + 0x66, 0x21, 0xcd, 0x9a, 0x99, 0x1f, 0xb2, 0x79, 0xee, 0x1d, 0xcc, 0x6e, 0x7a, 0xa0, 0x59, 0x4c, 0xb2, 0x74, 0x9e, + 0x84, 0x6a, 0x2c, 0x96, 0x44, 0x34, 0x63, 0xdc, 0x7c, 0x21, 0x2e, 0x32, 0xf1, 0x62, 0x96, 0x50, 0x3f, 0x6b, 0x4e, + 0xa0, 0x31, 0x98, 0x45, 0xed, 0x90, 0x4e, 0x70, 0x36, 0xb9, 0xf4, 0x9d, 0x4e, 0xf7, 0x11, 0xd6, 0xff, 0xbb, 0x87, + 0xc8, 0x6a, 0x6f, 0x2e, 0xee, 0xb4, 0xdb, 0x7f, 0x42, 0xbd, 0x95, 0x51, 0x04, 0x40, 0x5e, 0x67, 0x76, 0x63, 0xe5, + 0x29, 0x64, 0xb4, 0x6d, 0x6a, 0xd9, 0x9b, 0xf9, 0x21, 0xe4, 0x03, 0x7b, 0xdd, 0xd9, 0x4d, 0x01, 0xb3, 0xf3, 0x64, + 0x8a, 0xa9, 0x9a, 0xa4, 0x7a, 0x5a, 0xfc, 0x56, 0x88, 0x8f, 0x36, 0x43, 0xdc, 0xd5, 0x10, 0x57, 0x58, 0x6f, 0x86, + 0xf3, 0x4c, 0xc4, 0x56, 0xbd, 0x4e, 0x2e, 0x01, 0x89, 0xd2, 0x2b, 0x9a, 0x69, 0x38, 0xc4, 0xc3, 0x6f, 0x06, 0xa3, + 0xbb, 0x19, 0x8c, 0xa3, 0x4f, 0x81, 0x91, 0x25, 0xe1, 0xa2, 0xbe, 0xae, 0x9d, 0x8c, 0x4e, 0x7b, 0x11, 0x05, 0x7a, + 0xf2, 0xba, 0xf0, 0xfb, 0x9a, 0x85, 0x3c, 0x92, 0x3f, 0x05, 0x39, 0x5f, 0xcb, 0x77, 0x87, 0xed, 0xb6, 0x7c, 0xce, + 0xd9, 0xaf, 0xd4, 0xeb, 0xb8, 0x50, 0xa1, 0xb8, 0xc0, 0x3f, 0x94, 0xa7, 0x79, 0xeb, 0xdc, 0x13, 0xff, 0xc5, 0x3c, + 0xe6, 0x6b, 0xa4, 0x28, 0x56, 0x87, 0xa2, 0x71, 0xaa, 0x65, 0xa5, 0x14, 0x3e, 0xe0, 0xb6, 0x13, 0xdc, 0x91, 0xb0, + 0x7e, 0x79, 0x8c, 0x93, 0x0d, 0xfe, 0x22, 0xf3, 0x2e, 0x3c, 0x88, 0x74, 0x18, 0xa9, 0x86, 0x59, 0x2f, 0xed, 0x93, + 0x76, 0x2f, 0x6d, 0x36, 0x91, 0x93, 0x91, 0x64, 0x98, 0xaa, 0xe4, 0x3c, 0x87, 0x0d, 0xa4, 0xb1, 0x9d, 0x23, 0x2f, + 0x83, 0xb3, 0xa6, 0xcb, 0x65, 0x15, 0x06, 0x60, 0xe2, 0xb4, 0xc6, 0x0f, 0x5c, 0x55, 0xc0, 0xb9, 0xc1, 0xc9, 0x7d, + 0x7d, 0xbd, 0x4b, 0xa2, 0x79, 0x45, 0x9c, 0x06, 0x02, 0x73, 0xee, 0xcc, 0xe7, 0x11, 0x78, 0x29, 0x4a, 0xf1, 0x53, + 0xa5, 0x30, 0xd9, 0x2d, 0x1b, 0x0d, 0x92, 0x32, 0xbf, 0x0d, 0xf2, 0xf8, 0x92, 0x02, 0x7a, 0xb9, 0xe4, 0x04, 0x7a, + 0xac, 0xfa, 0xff, 0xc0, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, 0x09, 0xe2, 0x79, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xe1, + 0x6e, 0x88, 0xb2, 0x96, 0x68, 0x02, 0xbd, 0x8b, 0x6c, 0x1e, 0xa8, 0x08, 0xb7, 0xa8, 0x94, 0xcf, 0x4d, 0xf1, 0x5c, + 0xb5, 0x7d, 0x5d, 0x25, 0x8b, 0x42, 0x4b, 0x77, 0x9e, 0xb0, 0x5f, 0xe6, 0xf4, 0x9c, 0x85, 0xc6, 0xc9, 0x5d, 0x9a, + 0x04, 0x69, 0x48, 0x3f, 0xbc, 0x7b, 0x01, 0xd9, 0xee, 0x69, 0x02, 0x24, 0x96, 0x48, 0x7f, 0x17, 0xce, 0x49, 0xe2, + 0x86, 0xf4, 0x8a, 0x05, 0x74, 0x70, 0xb1, 0xbb, 0xd8, 0x58, 0x51, 0xbe, 0x46, 0x45, 0xeb, 0x02, 0xfc, 0x77, 0x12, + 0xca, 0x8b, 0xdd, 0xc5, 0x25, 0x2f, 0x5a, 0xbb, 0x8b, 0xc4, 0x0d, 0xd3, 0xa9, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xbb, + 0x0b, 0x06, 0x3f, 0x78, 0x71, 0x51, 0x54, 0x89, 0xa2, 0x25, 0x44, 0xc6, 0x14, 0x14, 0xee, 0x3a, 0xc8, 0xfd, 0x39, + 0x65, 0x89, 0x28, 0xba, 0xab, 0x67, 0xaa, 0x7b, 0x05, 0x24, 0xff, 0x4a, 0xa4, 0xc1, 0xac, 0xcd, 0xe5, 0xf3, 0xfb, + 0x9a, 0xcb, 0x34, 0xe1, 0x4c, 0xa4, 0xc5, 0xeb, 0x70, 0x4e, 0xe4, 0xe7, 0xe7, 0x81, 0x3c, 0x89, 0x9a, 0x57, 0xa7, + 0x2e, 0x7c, 0x81, 0x58, 0x69, 0x01, 0x53, 0x69, 0xec, 0xd3, 0xed, 0x47, 0x25, 0x93, 0xbb, 0x8c, 0xbf, 0x92, 0xaa, + 0xf2, 0x74, 0x9e, 0x05, 0x10, 0xeb, 0x55, 0x2a, 0xc5, 0xba, 0x57, 0xcc, 0x16, 0xfa, 0x9b, 0x8d, 0xb9, 0x91, 0x64, + 0xcb, 0xe1, 0x4c, 0x5f, 0x75, 0x6d, 0x07, 0x15, 0xf1, 0x44, 0x58, 0x33, 0x26, 0x56, 0xef, 0x9c, 0x85, 0x10, 0x78, + 0x61, 0xa1, 0x4a, 0x58, 0xac, 0x4d, 0x12, 0x54, 0xa4, 0x50, 0x64, 0x90, 0xc2, 0x65, 0x3b, 0x59, 0xb5, 0x0a, 0x84, + 0x10, 0x19, 0xd7, 0x03, 0xe1, 0xdb, 0xec, 0xec, 0xed, 0xe5, 0xd5, 0x89, 0x36, 0xa6, 0x70, 0xbe, 0x5c, 0x72, 0xea, + 0xe4, 0xf2, 0xd4, 0x4d, 0x44, 0x40, 0x19, 0x63, 0x58, 0xbe, 0xf1, 0x32, 0x5c, 0xf6, 0xe4, 0xe5, 0x45, 0x2f, 0x12, + 0x48, 0x94, 0x28, 0x23, 0x1a, 0xa9, 0x27, 0x5a, 0x25, 0xc3, 0xe6, 0xeb, 0xf2, 0x20, 0x7f, 0x0d, 0xeb, 0xed, 0x95, + 0xc5, 0x91, 0x56, 0x55, 0xb4, 0x5a, 0x9a, 0xa7, 0x19, 0x77, 0x1c, 0x1f, 0x07, 0x88, 0xf4, 0x7d, 0x31, 0xfb, 0x63, + 0x99, 0xef, 0x31, 0x68, 0x76, 0xbc, 0x4e, 0xe9, 0x0f, 0xa9, 0x9d, 0xaf, 0x96, 0xd9, 0x66, 0xea, 0x8c, 0x2e, 0xe0, + 0x09, 0x97, 0xbf, 0x15, 0xfa, 0xaa, 0x02, 0x39, 0xbb, 0xea, 0xb9, 0x9c, 0x24, 0x56, 0x0c, 0x4d, 0x2a, 0x03, 0x4e, + 0x0d, 0xaa, 0x61, 0x3a, 0xc2, 0x6c, 0xcb, 0xd8, 0xa8, 0xa8, 0x10, 0x51, 0x6e, 0xee, 0x0b, 0xa9, 0x04, 0x9d, 0x1b, + 0xd4, 0x7d, 0xc1, 0xb4, 0x1b, 0xaf, 0x4e, 0x77, 0x85, 0x42, 0x91, 0xc1, 0x19, 0x36, 0x55, 0x93, 0xb0, 0xdc, 0x92, + 0x64, 0x23, 0xf1, 0xba, 0xf2, 0x91, 0x66, 0xa4, 0x0a, 0x28, 0xae, 0x75, 0x00, 0xc9, 0x90, 0x9b, 0x00, 0x03, 0xc7, + 0x40, 0xce, 0xf5, 0x14, 0x80, 0xc7, 0x8c, 0x29, 0x9c, 0x54, 0x52, 0x1c, 0x07, 0x2f, 0xa4, 0x76, 0xef, 0xd9, 0x6f, + 0xdf, 0x9c, 0xbd, 0xb7, 0x31, 0x5c, 0x75, 0x46, 0xb3, 0xdc, 0x5b, 0xd8, 0x2a, 0xc7, 0xb0, 0x09, 0xf1, 0x6a, 0xdb, + 0xb3, 0xfd, 0x19, 0x1c, 0xda, 0x16, 0x4c, 0xb5, 0x75, 0xd3, 0xbc, 0xbe, 0xbe, 0x6e, 0xc2, 0x89, 0xb2, 0xe6, 0x3c, + 0x8b, 0x25, 0xbb, 0x09, 0xed, 0xa2, 0x40, 0x2e, 0x8f, 0x68, 0x52, 0x5e, 0x86, 0x94, 0xc6, 0xd4, 0x8d, 0xd3, 0x89, + 0x3c, 0x0f, 0xbb, 0xea, 0x9e, 0x88, 0x2f, 0x8e, 0xc5, 0x25, 0x5f, 0xfd, 0x63, 0x2e, 0xaf, 0x57, 0xe3, 0x19, 0xfc, + 0xec, 0x43, 0xf0, 0xea, 0xb8, 0xc5, 0x23, 0xf1, 0x70, 0x06, 0xbb, 0x49, 0x3c, 0xed, 0x2e, 0xd6, 0xa8, 0x6e, 0x00, + 0x5d, 0x44, 0x7d, 0x39, 0xb5, 0x5c, 0xd4, 0xba, 0xf0, 0xe2, 0x8b, 0x8b, 0xe2, 0xb8, 0x05, 0x7d, 0xb5, 0x74, 0xbf, + 0x97, 0x69, 0x78, 0xab, 0xdb, 0x97, 0x94, 0x08, 0x97, 0x3d, 0x25, 0xa4, 0x0f, 0x5d, 0xc0, 0xb8, 0x61, 0x5f, 0xe0, + 0x4c, 0xb1, 0xd0, 0x61, 0xf5, 0x50, 0x8c, 0x2c, 0x60, 0x98, 0x05, 0x94, 0x00, 0xb9, 0x41, 0xe7, 0x61, 0xd9, 0x40, + 0xec, 0x76, 0x59, 0xb4, 0x0d, 0x40, 0x59, 0xb1, 0xda, 0x3f, 0xd2, 0xcd, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, + 0xbf, 0x40, 0xf0, 0xaf, 0x00, 0xfc, 0xb8, 0x25, 0xd1, 0x74, 0x61, 0x5e, 0x3b, 0x23, 0x2f, 0x84, 0x28, 0x91, 0x39, + 0xcc, 0x38, 0x7e, 0xcf, 0xf1, 0xc7, 0x0b, 0x51, 0x55, 0x6b, 0x09, 0xa0, 0xbe, 0x82, 0x36, 0xd5, 0xd6, 0xea, 0x60, + 0x90, 0xc6, 0xb1, 0x3f, 0xcb, 0xa9, 0xa7, 0x7f, 0x28, 0x85, 0x01, 0xf4, 0x8e, 0x75, 0x0d, 0x4d, 0xe5, 0x3d, 0x9d, + 0x82, 0x1e, 0xb7, 0xae, 0x3e, 0x5e, 0xf9, 0x99, 0xd3, 0x6c, 0x06, 0xcd, 0xcb, 0x09, 0x2a, 0x78, 0xb4, 0x30, 0xd5, + 0x8d, 0x87, 0xed, 0x76, 0x0f, 0x92, 0x54, 0x9b, 0x7e, 0xcc, 0x26, 0x89, 0x17, 0xd3, 0x31, 0x2f, 0x38, 0x9c, 0x1e, + 0x5c, 0x68, 0xfd, 0xce, 0xed, 0x1e, 0x66, 0x74, 0x6a, 0xb9, 0xf0, 0xf7, 0xee, 0x81, 0x0b, 0x1e, 0x7a, 0x09, 0x8f, + 0x9a, 0x22, 0x19, 0x1a, 0x8e, 0x72, 0xf0, 0xa8, 0xf6, 0xbc, 0x30, 0x06, 0x0a, 0x28, 0xe8, 0xbe, 0x05, 0xcf, 0x2c, + 0x1e, 0x61, 0x9e, 0x99, 0xf5, 0x12, 0xb4, 0x58, 0x9b, 0xc1, 0xba, 0x0a, 0xb6, 0x8f, 0x8a, 0x5c, 0x58, 0x2c, 0x8b, + 0x35, 0xbc, 0x18, 0xaa, 0x74, 0xc1, 0x92, 0xd9, 0x9c, 0x0f, 0x85, 0xe7, 0x3f, 0x83, 0x33, 0x24, 0x23, 0x6c, 0x94, + 0x00, 0x3c, 0x23, 0xd5, 0x3e, 0xf0, 0xe3, 0xc0, 0x81, 0x4e, 0xac, 0xa6, 0x75, 0x94, 0xd1, 0x29, 0xea, 0x4d, 0x59, + 0xd2, 0x94, 0xef, 0x0e, 0x0d, 0xdd, 0xcd, 0x7d, 0x04, 0x4f, 0x85, 0x2b, 0x7a, 0xc3, 0x22, 0xc1, 0x77, 0xc3, 0xbc, + 0x2e, 0x46, 0x45, 0xd1, 0x4b, 0xb9, 0x33, 0x7c, 0xe1, 0xa0, 0x11, 0xfe, 0xd5, 0xb8, 0xc4, 0xc6, 0xd6, 0x54, 0x6d, + 0xe3, 0x2e, 0xda, 0x52, 0xc5, 0xa4, 0x4b, 0x51, 0xed, 0x57, 0x02, 0x15, 0x5f, 0x3a, 0x36, 0xcd, 0x67, 0x4d, 0xc9, + 0x7e, 0x9a, 0x82, 0x7c, 0x6c, 0x68, 0x8a, 0x94, 0x3b, 0x9b, 0xd2, 0x85, 0xe0, 0x2c, 0xea, 0x1c, 0x8b, 0xf4, 0xb8, + 0x8c, 0xca, 0x73, 0x4f, 0xea, 0xd9, 0x3c, 0xe9, 0x84, 0x6a, 0x5b, 0xff, 0xe2, 0xa4, 0xce, 0xa6, 0x40, 0xfe, 0x97, + 0x77, 0xfd, 0xf9, 0x71, 0x0c, 0x03, 0x5e, 0x68, 0xa5, 0xc1, 0xbc, 0x1a, 0x65, 0xc8, 0x47, 0x0e, 0x2a, 0xd4, 0x9e, + 0x79, 0x22, 0xf4, 0x6e, 0xe3, 0x82, 0xc1, 0x1d, 0xae, 0x23, 0x6a, 0xf2, 0x04, 0x33, 0x83, 0x9c, 0x80, 0x5a, 0xee, + 0x78, 0xaf, 0x62, 0x33, 0x52, 0x6b, 0xb7, 0xc4, 0x84, 0x88, 0x9d, 0x25, 0xa1, 0x6d, 0xfd, 0x39, 0x88, 0x59, 0xf0, + 0x91, 0xd8, 0xbb, 0x0b, 0x07, 0xad, 0x1f, 0x0d, 0x15, 0x3b, 0x54, 0xf3, 0x5c, 0x54, 0x8f, 0x36, 0xa4, 0xae, 0xc1, + 0x4e, 0xe5, 0xed, 0x41, 0x76, 0x1f, 0x54, 0x9b, 0xe3, 0x96, 0x1c, 0xa7, 0x7f, 0x51, 0x9c, 0x57, 0xb7, 0x82, 0x55, + 0x50, 0x00, 0x9a, 0x65, 0xb9, 0x25, 0xe8, 0x8f, 0xd8, 0x72, 0x0b, 0xd5, 0x2c, 0x40, 0x6c, 0xd2, 0x3e, 0xb2, 0x2d, + 0xc9, 0x60, 0x00, 0x4e, 0xae, 0x78, 0x8d, 0x6d, 0xfd, 0xb9, 0x2c, 0xa3, 0xa5, 0xdb, 0x47, 0xe4, 0xad, 0x10, 0x1b, + 0xc6, 0x02, 0x5b, 0xdf, 0x0d, 0x29, 0xf7, 0x59, 0x2c, 0x9b, 0xf4, 0xb4, 0x97, 0x62, 0x65, 0x46, 0xcb, 0x65, 0x5e, + 0x9f, 0x0b, 0xab, 0x63, 0x50, 0xcc, 0xec, 0xb8, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0x87, 0x19, 0x3f, 0xad, 0x66, + 0x28, 0xdf, 0x59, 0x7f, 0x0e, 0xc4, 0xc9, 0x2a, 0x00, 0x30, 0x53, 0x00, 0x42, 0x64, 0x5f, 0x2a, 0x21, 0x8e, 0x4f, + 0x32, 0x97, 0xfb, 0xd9, 0x84, 0xf2, 0x15, 0xc4, 0xfa, 0x32, 0x91, 0xb7, 0xa7, 0xa3, 0xf8, 0x6b, 0xd0, 0x06, 0x75, + 0x68, 0x41, 0xcf, 0x2d, 0x06, 0xa0, 0xaa, 0x92, 0x8d, 0x1a, 0x6f, 0x84, 0x40, 0xf6, 0x89, 0xc5, 0x91, 0xdc, 0x3e, + 0x13, 0xdc, 0x5e, 0xc6, 0xe1, 0x2c, 0x31, 0x96, 0x00, 0xb1, 0xb0, 0xad, 0x81, 0x84, 0x9c, 0x86, 0x12, 0x66, 0x92, + 0x8a, 0x56, 0x59, 0x71, 0xdc, 0x92, 0xb5, 0x25, 0x3b, 0x96, 0x95, 0x00, 0x09, 0x62, 0x9f, 0x56, 0x38, 0x80, 0xe4, + 0x6f, 0x13, 0x0f, 0x21, 0xbb, 0x2a, 0x89, 0x4d, 0x9c, 0x31, 0xeb, 0x1f, 0xc7, 0xfe, 0x25, 0x8d, 0xfb, 0xbb, 0x8b, + 0x74, 0xb9, 0x6c, 0x17, 0xc7, 0x2d, 0xf9, 0x68, 0x1d, 0x0b, 0xbe, 0x21, 0xef, 0x06, 0x15, 0x4b, 0x0c, 0x07, 0x37, + 0x21, 0x25, 0x56, 0xe7, 0x82, 0x79, 0xaa, 0x83, 0xc2, 0xb6, 0x44, 0x16, 0x8a, 0xa8, 0x54, 0xea, 0x34, 0x85, 0x6d, + 0xb1, 0x70, 0xbd, 0x2c, 0xe7, 0x74, 0x06, 0xa5, 0xd1, 0x72, 0xd9, 0x29, 0x6c, 0x6b, 0xca, 0x12, 0x78, 0x4a, 0x97, + 0x4b, 0x71, 0x26, 0x72, 0xca, 0x12, 0xa7, 0x0d, 0x64, 0x6b, 0x5b, 0x53, 0xff, 0x46, 0x4c, 0x58, 0xbf, 0xf1, 0x6f, + 0x9c, 0x8e, 0x7a, 0xe5, 0x96, 0xf8, 0xc9, 0x81, 0xe2, 0xaa, 0x15, 0xf5, 0xd5, 0x8a, 0x86, 0x78, 0x2e, 0x4f, 0x7b, + 0x11, 0x27, 0x24, 0xfe, 0xe6, 0x15, 0x0d, 0xf5, 0x8a, 0xce, 0xb7, 0xac, 0xe8, 0xfc, 0x8e, 0x15, 0x0d, 0xd4, 0xea, + 0x59, 0x25, 0xee, 0xb2, 0xe5, 0xb2, 0xd3, 0xae, 0xb0, 0x77, 0xdc, 0x0a, 0xd9, 0x15, 0xac, 0x06, 0x68, 0x6a, 0x9c, + 0x4d, 0xe9, 0x66, 0xa2, 0xac, 0xa3, 0x98, 0x7e, 0x16, 0x26, 0x2b, 0x2c, 0xa4, 0x75, 0x2c, 0x98, 0x74, 0x5d, 0x06, + 0x26, 0xff, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x10, 0xe9, 0xbb, 0x42, 0x1d, 0xfb, 0xbd, 0x8d, 0x6d, 0xcb, + 0xd6, 0x64, 0x7d, 0x51, 0x9c, 0x83, 0x8c, 0x10, 0xf3, 0xbb, 0x17, 0x2d, 0x42, 0x6d, 0xbb, 0xbf, 0x9d, 0xe6, 0x20, + 0x87, 0xe0, 0x3a, 0xcd, 0x42, 0xdb, 0x93, 0x55, 0x3f, 0x0b, 0x55, 0x53, 0x96, 0xa8, 0x8c, 0xb4, 0xad, 0xb4, 0x56, + 0xbd, 0x37, 0x29, 0xae, 0x7b, 0x78, 0x28, 0x6b, 0xcc, 0x7c, 0xce, 0x69, 0x96, 0x28, 0xca, 0xb5, 0xed, 0xff, 0x10, + 0x54, 0xb8, 0x81, 0xaf, 0x04, 0x7a, 0x01, 0x34, 0x01, 0x2a, 0x9d, 0x5b, 0xf1, 0x7c, 0x29, 0x9e, 0x76, 0x2a, 0x65, + 0xf3, 0x16, 0x99, 0x7a, 0xbf, 0x2c, 0x02, 0x33, 0x64, 0x3e, 0xa5, 0xe1, 0xb9, 0x60, 0xd0, 0x83, 0xf8, 0x42, 0x29, + 0x8f, 0x2b, 0xe2, 0xae, 0x6a, 0x80, 0xed, 0x9f, 0xe6, 0xdd, 0x47, 0x07, 0xa7, 0x36, 0x96, 0x3c, 0x3e, 0x1d, 0x8f, + 0x6d, 0x54, 0x58, 0xf7, 0x6b, 0xd6, 0x39, 0xf8, 0x69, 0xfe, 0xf5, 0xb3, 0xf6, 0xd7, 0x65, 0xe3, 0x04, 0x88, 0x48, + 0x25, 0x41, 0x68, 0x51, 0x65, 0xc0, 0xab, 0x67, 0x34, 0xf6, 0x93, 0xed, 0xd3, 0x19, 0x9a, 0xd3, 0xc9, 0x67, 0x94, + 0x86, 0x40, 0x9c, 0x78, 0xad, 0xf4, 0x3c, 0xa6, 0x57, 0x54, 0xdf, 0xd0, 0xb8, 0x61, 0xb0, 0x0d, 0x2d, 0x82, 0x74, + 0x9e, 0x70, 0x95, 0x0d, 0xa2, 0x58, 0xad, 0x31, 0xa5, 0x0b, 0x31, 0x07, 0x53, 0x9d, 0xbf, 0x95, 0x72, 0xae, 0x2e, + 0xbd, 0x8a, 0x0b, 0x6c, 0x1b, 0x00, 0x6c, 0x85, 0x6c, 0xb0, 0xa5, 0xdc, 0x6b, 0xe3, 0xf6, 0x36, 0xd8, 0x70, 0x07, + 0x79, 0xb6, 0x3d, 0xd2, 0x78, 0x12, 0x0e, 0xdd, 0xda, 0xa5, 0x1a, 0x5b, 0xf1, 0xf5, 0x49, 0x0c, 0x5c, 0x66, 0xd0, + 0x59, 0x42, 0xf3, 0x7c, 0x2b, 0x02, 0xca, 0x45, 0xc4, 0x76, 0x55, 0xdb, 0xde, 0xd2, 0x0b, 0x6e, 0x63, 0xd8, 0x61, + 0x02, 0xe0, 0x32, 0xac, 0xac, 0x6a, 0xd1, 0xf1, 0x98, 0x06, 0xa5, 0x3f, 0x1c, 0x02, 0x84, 0x63, 0x16, 0x73, 0x88, + 0x93, 0x89, 0x00, 0x96, 0xfd, 0x3a, 0x4d, 0xa8, 0x8d, 0x74, 0xca, 0xab, 0x82, 0x5f, 0xc9, 0xff, 0xcd, 0xf0, 0xc8, + 0x1e, 0xeb, 0xb0, 0xa8, 0x51, 0x96, 0x4b, 0xed, 0xae, 0xa9, 0x95, 0xd7, 0x11, 0x99, 0x0a, 0x7f, 0xcc, 0xb6, 0x0d, + 0x74, 0xbf, 0x6d, 0xb2, 0xe8, 0x7c, 0x7d, 0xd8, 0x69, 0x17, 0x36, 0xb6, 0xa1, 0xbb, 0xfb, 0xee, 0x12, 0xd1, 0x6a, + 0x1f, 0x5a, 0xcd, 0x93, 0xcf, 0x69, 0xd7, 0xed, 0x3c, 0xee, 0xd8, 0x58, 0xde, 0xb5, 0x80, 0x8a, 0x92, 0x19, 0x04, + 0xe0, 0x21, 0xfe, 0xdd, 0x53, 0xa9, 0x77, 0x7e, 0x3f, 0x78, 0x1e, 0x76, 0xda, 0x36, 0xb6, 0x73, 0x9e, 0xce, 0x3e, + 0x63, 0x0a, 0xfb, 0x36, 0xb6, 0x83, 0x38, 0xcd, 0xa9, 0x39, 0x07, 0xa9, 0xce, 0xfe, 0xfe, 0x49, 0x48, 0x88, 0x66, + 0x19, 0xcd, 0x73, 0xcb, 0xec, 0x5f, 0x91, 0xd2, 0x27, 0x18, 0xe6, 0x46, 0x8a, 0xcb, 0x29, 0x17, 0x78, 0x91, 0xd7, + 0x20, 0x98, 0x54, 0x25, 0xcb, 0xd6, 0x88, 0x4d, 0x88, 0x80, 0x92, 0xb1, 0x49, 0xed, 0xea, 0x93, 0x23, 0x6f, 0xd8, + 0x7a, 0x72, 0x60, 0x19, 0x38, 0x5f, 0x1f, 0xa0, 0x56, 0x32, 0x65, 0xc9, 0xf9, 0x86, 0x52, 0xff, 0x66, 0x43, 0x29, + 0xa8, 0x6c, 0x25, 0x74, 0xea, 0x8a, 0x9e, 0x4f, 0x63, 0xbd, 0x52, 0x7c, 0x4c, 0x10, 0x43, 0xe1, 0x7f, 0xfc, 0x04, + 0xa4, 0xc6, 0x32, 0x88, 0x1e, 0x7e, 0xfb, 0x70, 0x50, 0xf2, 0x39, 0xc3, 0x95, 0xbd, 0xfc, 0xbe, 0x19, 0x42, 0x69, + 0x13, 0x9c, 0xfc, 0xf1, 0x67, 0xcd, 0x95, 0xde, 0x7c, 0x9a, 0xe0, 0x0c, 0xad, 0xea, 0x77, 0x2c, 0xbd, 0x3a, 0xea, + 0xbf, 0xba, 0xf6, 0x1b, 0x8a, 0x95, 0xe2, 0x53, 0xae, 0x7f, 0x10, 0xb3, 0x69, 0x45, 0x02, 0xeb, 0x60, 0x0a, 0x8d, + 0x07, 0x32, 0xbe, 0xcc, 0x4e, 0xa4, 0xea, 0x73, 0x0e, 0xe7, 0x58, 0xe1, 0xaa, 0x90, 0x79, 0x46, 0xcf, 0xe3, 0xf4, + 0x7a, 0xf5, 0xf2, 0xb3, 0xed, 0x95, 0x23, 0x36, 0x89, 0x8c, 0xc3, 0x69, 0x94, 0x94, 0x8b, 0x70, 0xe7, 0x00, 0xc5, + 0xbf, 0xfc, 0xb3, 0xeb, 0xfe, 0xcb, 0x3f, 0x7f, 0xb2, 0x2a, 0x74, 0x5f, 0x5c, 0x60, 0x5e, 0x75, 0xbb, 0x7d, 0x77, + 0x6d, 0x1e, 0xa9, 0x8e, 0xf3, 0xcd, 0x75, 0xd6, 0x16, 0x01, 0xde, 0xaf, 0x2d, 0xc1, 0x5a, 0xa1, 0xdc, 0x7d, 0xd6, + 0x6f, 0x01, 0x0c, 0xe6, 0xf5, 0x49, 0xc8, 0xa0, 0xd2, 0xef, 0x02, 0xed, 0x02, 0x79, 0xf7, 0x5a, 0x91, 0xdf, 0x8e, + 0xe1, 0x4f, 0xcd, 0xe1, 0x77, 0x82, 0xaf, 0xfc, 0x13, 0xf1, 0xc5, 0x45, 0x99, 0x85, 0x68, 0x36, 0x85, 0x3b, 0x0e, + 0x06, 0x6b, 0x25, 0x4a, 0xf1, 0xf0, 0xda, 0xa8, 0x2f, 0xce, 0x50, 0x92, 0xf8, 0xe2, 0x15, 0x5c, 0x6c, 0x74, 0x7c, + 0x99, 0x69, 0x67, 0xeb, 0x1d, 0xc2, 0x01, 0xba, 0xa8, 0xcf, 0x4a, 0x74, 0xba, 0x26, 0x19, 0xa0, 0x14, 0xcc, 0x0d, + 0x00, 0x13, 0xc7, 0x17, 0xca, 0xda, 0x3c, 0x95, 0x6e, 0x18, 0x6f, 0x95, 0xb4, 0x95, 0x7b, 0xa6, 0x86, 0x74, 0x6c, + 0xbd, 0x17, 0xf8, 0x12, 0x95, 0x69, 0x65, 0xdd, 0x0b, 0x57, 0x17, 0xd8, 0x11, 0x25, 0xfb, 0xb9, 0xf2, 0xe3, 0xab, + 0xfb, 0x31, 0xbe, 0xed, 0x02, 0x75, 0x69, 0x2d, 0xff, 0xd1, 0x2a, 0xc1, 0xb2, 0xb9, 0xdc, 0xa4, 0x0f, 0x5c, 0xfb, + 0x9c, 0x66, 0xe7, 0x11, 0x24, 0x42, 0x65, 0x9f, 0x60, 0x4e, 0xb0, 0xd2, 0x98, 0x8a, 0xbf, 0x8c, 0xa8, 0x8b, 0xa4, + 0xff, 0x41, 0x9c, 0x8a, 0x41, 0x16, 0x23, 0x0c, 0x65, 0x2c, 0xc2, 0xff, 0xe7, 0x5b, 0xff, 0x61, 0xf8, 0xd6, 0xdd, + 0x43, 0xd4, 0xce, 0x48, 0x7f, 0xf6, 0x42, 0xfe, 0xc7, 0x66, 0x77, 0xb9, 0x60, 0x77, 0xbf, 0x81, 0xd1, 0xe5, 0xff, + 0x18, 0x46, 0x27, 0x6c, 0x64, 0xcd, 0xe9, 0xd6, 0x42, 0xcd, 0xb7, 0xae, 0x7f, 0xed, 0xdf, 0x56, 0xfb, 0x2a, 0xbe, + 0x38, 0xb9, 0xf6, 0x6f, 0xab, 0x45, 0xd8, 0xce, 0x2e, 0x56, 0xfb, 0x18, 0xd8, 0x6f, 0x5e, 0xdb, 0x9e, 0xfd, 0xe6, + 0xeb, 0xaf, 0x6d, 0x7c, 0x91, 0x53, 0x3e, 0x80, 0x42, 0xb2, 0xbb, 0xd8, 0x59, 0xad, 0x08, 0x6e, 0x14, 0x98, 0xa2, + 0x08, 0x7b, 0xe1, 0xac, 0x06, 0x0c, 0xcb, 0xcf, 0xd3, 0xc4, 0x84, 0xe6, 0x2d, 0x58, 0xf6, 0x9f, 0x0b, 0x8e, 0xe8, + 0x65, 0x0d, 0x1e, 0x51, 0xba, 0x0a, 0x90, 0x28, 0xac, 0x41, 0x54, 0x5d, 0x19, 0x74, 0x37, 0xff, 0xaf, 0xae, 0x45, + 0x90, 0xb7, 0x7d, 0x44, 0x83, 0xf8, 0xe2, 0x73, 0xc4, 0x87, 0x1c, 0xac, 0xf2, 0xd8, 0x69, 0x77, 0xa7, 0x5f, 0xec, + 0x2e, 0xa2, 0xbd, 0x3d, 0x36, 0xb0, 0xb1, 0xb8, 0xa7, 0xa9, 0xd8, 0x24, 0x5c, 0x72, 0xf8, 0x93, 0xc2, 0x9f, 0xac, + 0x62, 0xd4, 0x2c, 0x19, 0x67, 0x7e, 0x46, 0xc3, 0xed, 0x4c, 0xba, 0xbc, 0xdf, 0x48, 0x91, 0x86, 0x4c, 0xc0, 0xce, + 0xcf, 0x45, 0xea, 0xd1, 0x94, 0x81, 0x3e, 0xba, 0x63, 0x7e, 0xc5, 0x47, 0x5d, 0x88, 0x56, 0x7e, 0x04, 0xc0, 0x44, + 0x38, 0x25, 0x79, 0x99, 0xeb, 0x00, 0xb7, 0x6a, 0xaa, 0xec, 0x10, 0x6c, 0x23, 0xe1, 0x75, 0x0f, 0x49, 0x5f, 0xa4, + 0x3d, 0xbc, 0x48, 0xb8, 0x13, 0xba, 0x3c, 0x63, 0x53, 0x07, 0xe1, 0x4e, 0x1b, 0x21, 0xed, 0x6c, 0x08, 0x49, 0x7f, + 0x87, 0xe5, 0xaf, 0xfd, 0xd7, 0x4e, 0x28, 0x2e, 0xe2, 0x12, 0x9f, 0xee, 0x81, 0x43, 0x92, 0x4f, 0xe6, 0xe3, 0x31, + 0xcd, 0x1c, 0x7d, 0x00, 0xf0, 0xab, 0x03, 0x38, 0x63, 0x0c, 0x6f, 0x9f, 0xfa, 0xdc, 0xff, 0x96, 0xd1, 0x6b, 0x27, + 0x43, 0xbd, 0xb4, 0xba, 0x9c, 0x31, 0xc4, 0x73, 0x44, 0xfa, 0x11, 0x24, 0xc6, 0xbf, 0x48, 0xf8, 0x7e, 0xd7, 0x99, + 0x7f, 0x75, 0x80, 0x43, 0xb8, 0xf2, 0x42, 0x67, 0x75, 0xcb, 0xbb, 0x4a, 0x3e, 0xb0, 0x84, 0x1f, 0xc9, 0x63, 0x98, + 0x19, 0x52, 0xee, 0xc3, 0x32, 0x23, 0xc6, 0xf2, 0xcb, 0x0e, 0x43, 0xd2, 0x0f, 0x1a, 0x44, 0x1e, 0xca, 0x14, 0xb7, + 0xec, 0x9e, 0x46, 0x7e, 0x76, 0x0a, 0x07, 0xbe, 0x01, 0xd0, 0x4b, 0x9e, 0xfa, 0x4e, 0x50, 0x7e, 0xc9, 0xc9, 0x69, + 0xfd, 0xd4, 0x68, 0x4d, 0xb0, 0x48, 0x8a, 0xa9, 0x8a, 0x5a, 0x50, 0x74, 0x6e, 0x16, 0x91, 0xc6, 0x6e, 0x0b, 0xc3, + 0x1e, 0xec, 0x6d, 0xf4, 0xd1, 0xea, 0xa5, 0x6b, 0x5e, 0x67, 0xfe, 0xac, 0x8c, 0x1b, 0x9c, 0xfa, 0x59, 0xc6, 0x68, + 0x66, 0x39, 0xcf, 0x7f, 0x45, 0xde, 0xbf, 0xfc, 0xf3, 0xe6, 0xf8, 0x81, 0x0a, 0x19, 0x58, 0x90, 0x5c, 0xd2, 0x14, + 0xe9, 0xd8, 0xc4, 0x0e, 0x64, 0x43, 0x5b, 0x87, 0x3b, 0xf6, 0x8f, 0xda, 0xed, 0xb6, 0x0a, 0x09, 0x74, 0xe4, 0x4f, + 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x10, 0x51, 0x65, 0x62, 0xcb, 0x00, 0xe5, 0x51, 0x7b, 0x76, 0x63, 0xf7, 0x61, 0x3b, + 0x28, 0x28, 0xde, 0xd1, 0x19, 0xf5, 0xf9, 0x67, 0x8d, 0x9f, 0x89, 0x26, 0xe5, 0xf0, 0x1d, 0x3d, 0x74, 0x35, 0xee, + 0xca, 0xa0, 0x87, 0xab, 0x83, 0xbe, 0x67, 0x53, 0x71, 0x75, 0xd3, 0xb6, 0x51, 0x85, 0xa7, 0xba, 0x36, 0x26, 0x97, + 0x2d, 0x6c, 0x4b, 0x60, 0x3c, 0x4a, 0xe3, 0x90, 0x66, 0xc4, 0xa6, 0xee, 0xc4, 0xb5, 0x1e, 0xb7, 0xdb, 0x6d, 0xdc, + 0x3c, 0x38, 0x6c, 0xb7, 0xf1, 0xe1, 0xc3, 0x36, 0x6e, 0xc2, 0x1f, 0xd7, 0x75, 0x57, 0x60, 0xb8, 0x2b, 0x6a, 0xdb, + 0x69, 0x67, 0x74, 0xaa, 0x00, 0xbc, 0x33, 0xac, 0x58, 0xed, 0x09, 0xb8, 0x60, 0x5a, 0xed, 0x7b, 0x29, 0xd9, 0xd4, + 0x05, 0x07, 0x2a, 0x1d, 0x55, 0xf8, 0x0b, 0xb3, 0x2a, 0x68, 0x4a, 0xe5, 0xc5, 0x7f, 0x2f, 0x14, 0x21, 0x78, 0xd6, + 0x29, 0xdc, 0x5e, 0x2a, 0xe2, 0xa5, 0x90, 0x0a, 0x04, 0x1f, 0x48, 0xe3, 0x3e, 0x4b, 0xe0, 0xdb, 0x59, 0x3a, 0x6a, + 0xaa, 0x19, 0x55, 0xb6, 0x92, 0x74, 0xfb, 0x40, 0x86, 0xa5, 0x37, 0x11, 0xc4, 0xe8, 0x01, 0xc2, 0xfe, 0x7d, 0x1a, + 0xa8, 0x15, 0x84, 0xfa, 0xc1, 0x7d, 0xea, 0x6b, 0xec, 0x8f, 0x1e, 0x88, 0xe4, 0xa4, 0x9d, 0x68, 0xb9, 0xdc, 0xf1, + 0x97, 0xcb, 0x9d, 0xe0, 0xfe, 0x33, 0x94, 0xcb, 0xab, 0x4f, 0x41, 0xc0, 0xcd, 0x9f, 0x12, 0xe8, 0x17, 0x50, 0xee, + 0x45, 0x58, 0x82, 0x24, 0x9f, 0x7c, 0xac, 0x06, 0x94, 0x8f, 0x41, 0xb1, 0x82, 0x94, 0x90, 0x44, 0xd2, 0x3e, 0x5f, + 0x2e, 0x15, 0xf1, 0xe3, 0x39, 0xf1, 0xcb, 0xa2, 0x8e, 0x8d, 0x67, 0x24, 0x28, 0x1f, 0x6d, 0x01, 0xf2, 0x4c, 0x71, + 0xa9, 0x0a, 0xe2, 0x6b, 0x3f, 0x4b, 0x4c, 0x80, 0x5f, 0xa7, 0x96, 0x1a, 0xd6, 0x9a, 0x65, 0xe9, 0x15, 0x83, 0xe4, + 0x97, 0x95, 0x81, 0xa7, 0x04, 0x2e, 0xfe, 0xea, 0x99, 0xa1, 0x70, 0xa3, 0x83, 0xf7, 0x9a, 0xcf, 0xc2, 0x2d, 0x93, + 0xe5, 0x04, 0xbd, 0x50, 0xcd, 0xcd, 0x9b, 0xeb, 0x69, 0xbd, 0xf3, 0xaf, 0xbd, 0x99, 0x7e, 0x78, 0x26, 0xf3, 0x6c, + 0xbc, 0x69, 0x79, 0xb2, 0xe6, 0x2d, 0x79, 0x0d, 0xb1, 0x1f, 0x5b, 0xf3, 0x6d, 0xb8, 0x67, 0x53, 0xf2, 0xb8, 0x77, + 0x2f, 0xcf, 0xa8, 0x9f, 0x05, 0xd1, 0x5b, 0x3f, 0xf3, 0xa7, 0x79, 0x6f, 0xac, 0x6f, 0xf1, 0xd2, 0x14, 0x70, 0x3e, + 0x16, 0x99, 0x4e, 0x49, 0x70, 0x6b, 0xe3, 0x10, 0xe1, 0xea, 0xbd, 0x84, 0x40, 0xfa, 0xb9, 0x6d, 0x3c, 0x37, 0x5f, + 0xc1, 0x3a, 0xdb, 0x78, 0x8a, 0xb0, 0x4c, 0x20, 0x7a, 0xfb, 0x47, 0xa6, 0x0e, 0x61, 0xc8, 0x75, 0xf1, 0xc6, 0x6e, + 0xf5, 0x95, 0x3b, 0x9d, 0x4c, 0xf4, 0x7e, 0x25, 0x99, 0x68, 0x03, 0x1a, 0xad, 0x8c, 0xe6, 0xb3, 0x34, 0xc9, 0xa9, + 0x8d, 0xdf, 0x43, 0x3b, 0x79, 0x15, 0xb3, 0xd9, 0x70, 0x8d, 0xe6, 0xca, 0xa6, 0xe2, 0x8d, 0x6c, 0x07, 0x41, 0x9d, + 0xf7, 0xdf, 0x97, 0x71, 0x7c, 0x1d, 0xdf, 0x11, 0x89, 0xe8, 0x8c, 0x6e, 0xc9, 0x95, 0xcd, 0xe9, 0x27, 0x73, 0x65, + 0xe3, 0x7b, 0xe5, 0xca, 0xe6, 0xf4, 0x8f, 0xce, 0x95, 0x65, 0xd4, 0xc8, 0x95, 0x05, 0x39, 0xf7, 0xf5, 0xbd, 0x52, + 0x2e, 0x75, 0x26, 0x5c, 0x7a, 0x9d, 0x93, 0x8e, 0x8a, 0x81, 0xc4, 0xe9, 0x04, 0xf2, 0x2d, 0xff, 0xf1, 0xe9, 0x93, + 0x71, 0x3a, 0x31, 0x93, 0x27, 0xe1, 0xc3, 0x24, 0x40, 0x76, 0x38, 0x25, 0x0b, 0xfb, 0xa7, 0x9b, 0xce, 0x93, 0x61, + 0xa7, 0xb7, 0xdf, 0x99, 0xda, 0x9e, 0x0d, 0x4e, 0x47, 0x51, 0xd0, 0xee, 0xed, 0xef, 0x43, 0xc1, 0xb5, 0x51, 0xd0, + 0x85, 0x02, 0x66, 0x14, 0x1c, 0x42, 0x41, 0x60, 0x14, 0x3c, 0x84, 0x82, 0xd0, 0x28, 0x78, 0x04, 0x05, 0x57, 0x76, + 0x31, 0x64, 0x65, 0x42, 0xf0, 0x23, 0x24, 0x6e, 0x30, 0xdc, 0x49, 0xeb, 0xa7, 0xb7, 0x23, 0xa2, 0xab, 0x3c, 0x2a, + 0x6f, 0x7e, 0x68, 0x1e, 0xe8, 0x8b, 0x0a, 0x2f, 0xbe, 0xb8, 0x00, 0xd6, 0x0a, 0x17, 0xb1, 0x60, 0x88, 0x49, 0xca, + 0x9a, 0xfb, 0xfa, 0xb5, 0xed, 0x95, 0x59, 0xb3, 0x6d, 0xdc, 0xd5, 0x79, 0xb3, 0x9e, 0x8d, 0x04, 0x5f, 0x92, 0x2f, + 0x0e, 0x1b, 0xa1, 0xea, 0x16, 0xee, 0x00, 0xac, 0x2e, 0xe0, 0xdc, 0x47, 0x78, 0xaa, 0x15, 0x20, 0xea, 0xc0, 0x07, + 0x18, 0xde, 0xb3, 0x29, 0xd5, 0xfb, 0x45, 0x0f, 0x60, 0x89, 0xcc, 0xe2, 0x5e, 0x54, 0x29, 0x46, 0x6f, 0xf1, 0xb8, + 0xba, 0xf3, 0xf5, 0x3d, 0x91, 0x77, 0xe8, 0xa5, 0x58, 0x86, 0xb9, 0x66, 0x98, 0xfb, 0x13, 0x0f, 0x52, 0x28, 0x21, + 0x63, 0xc4, 0x1b, 0x13, 0x42, 0xda, 0x83, 0xb9, 0xf7, 0x16, 0x5f, 0x47, 0x34, 0xf1, 0xa6, 0x45, 0xaf, 0x5c, 0x7f, + 0x99, 0xd2, 0xf9, 0xbe, 0xbc, 0x28, 0x5c, 0xd0, 0x44, 0xf5, 0x56, 0x42, 0xd9, 0x2c, 0x69, 0x67, 0x4b, 0xce, 0x9f, + 0xa1, 0xec, 0x8c, 0xe3, 0xf4, 0xba, 0x09, 0xe2, 0x7e, 0x63, 0x1e, 0x20, 0xcc, 0xad, 0xcc, 0x03, 0x7c, 0x09, 0xb0, + 0x96, 0x4f, 0xef, 0xfd, 0x49, 0xf9, 0xfb, 0x15, 0xcd, 0x73, 0x7f, 0xa2, 0x6a, 0x6e, 0xcf, 0xfb, 0x13, 0x20, 0x9a, + 0x39, 0x7f, 0x1a, 0x08, 0x48, 0xce, 0x03, 0x84, 0x40, 0x40, 0x57, 0xe5, 0xea, 0xc1, 0xcc, 0xeb, 0x69, 0x7e, 0x02, + 0x55, 0xf5, 0x22, 0xee, 0x4f, 0xaa, 0x82, 0xe3, 0x59, 0x46, 0x55, 0x02, 0x21, 0x60, 0xb1, 0x38, 0x6e, 0x41, 0x81, + 0x7c, 0xbd, 0x25, 0x9d, 0x4f, 0x73, 0x97, 0xed, 0x49, 0x7d, 0x96, 0x4e, 0xe7, 0x33, 0x4f, 0xa6, 0x94, 0xc7, 0x52, + 0xd6, 0x33, 0xf2, 0xbe, 0xec, 0x04, 0xf0, 0x9f, 0x3a, 0x78, 0xf1, 0xe5, 0x78, 0x3c, 0xbe, 0x33, 0xbd, 0xef, 0xcb, + 0x70, 0x4c, 0xbb, 0xf4, 0xb0, 0x07, 0xa7, 0x16, 0x9a, 0x2a, 0x11, 0xad, 0x53, 0x08, 0xdc, 0x2d, 0xee, 0x57, 0x19, + 0x72, 0xd6, 0x78, 0xb4, 0xb8, 0x7f, 0xaa, 0x5f, 0x31, 0xcb, 0xe8, 0x62, 0xea, 0x67, 0x13, 0x96, 0x78, 0xed, 0xc2, + 0xbd, 0x5a, 0x28, 0x50, 0x8f, 0x8e, 0x8e, 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x51, 0x4e, 0xa3, + 0xdd, 0x1e, 0x8f, 0x0b, 0x97, 0xe9, 0x82, 0xfd, 0x6e, 0x10, 0xee, 0x77, 0x0b, 0xf7, 0xda, 0xa8, 0x51, 0xb8, 0x54, + 0x3d, 0x65, 0x34, 0xac, 0x1d, 0x7d, 0x78, 0xd4, 0x6e, 0x17, 0xae, 0x24, 0xb4, 0x05, 0xc4, 0xe4, 0xe4, 0x4f, 0xcf, + 0x9f, 0xf3, 0xb4, 0xb8, 0x28, 0x8a, 0x5e, 0xcc, 0x9d, 0xe1, 0xae, 0xba, 0x56, 0x52, 0x7e, 0x87, 0xb1, 0x40, 0x23, + 0xfc, 0xb5, 0x99, 0x39, 0x07, 0xc4, 0x2c, 0x32, 0xe6, 0x62, 0x9d, 0x58, 0x57, 0x7b, 0x0d, 0x94, 0x25, 0x5e, 0x7f, + 0x4d, 0xe2, 0x2a, 0xa1, 0x0e, 0xf8, 0x18, 0xd4, 0x94, 0xb7, 0x9f, 0x27, 0xdb, 0xa4, 0x47, 0xf6, 0x69, 0xe9, 0x71, + 0x79, 0x1f, 0xe1, 0x91, 0xfd, 0xe1, 0xc2, 0x23, 0x31, 0x85, 0x87, 0x64, 0x1d, 0xd7, 0x9c, 0xd8, 0x41, 0x44, 0x83, + 0x8f, 0x97, 0xe9, 0x4d, 0x13, 0xb6, 0x44, 0x66, 0x0b, 0xb1, 0x72, 0xf5, 0x5b, 0x33, 0xf9, 0x75, 0x67, 0xc6, 0x47, + 0x1c, 0x85, 0x8e, 0xff, 0x26, 0x21, 0xf6, 0x1b, 0x1d, 0xd8, 0x93, 0x25, 0xe3, 0x31, 0xb1, 0xdf, 0x8c, 0xc7, 0xb6, + 0xbe, 0x1c, 0xc7, 0xe7, 0x54, 0xd4, 0x7a, 0x5d, 0x2b, 0x11, 0xb5, 0xc0, 0xd0, 0xaf, 0xca, 0xcc, 0x02, 0x95, 0x77, + 0x67, 0xe6, 0xd8, 0xa9, 0x37, 0x21, 0xcb, 0x61, 0xab, 0xc1, 0xb7, 0x25, 0xeb, 0x97, 0xf3, 0x27, 0xb5, 0x2f, 0x29, + 0x95, 0x00, 0x6f, 0xf8, 0xfc, 0xd3, 0xea, 0xcd, 0x70, 0x13, 0xaa, 0x55, 0xfc, 0x27, 0xb7, 0x2f, 0x42, 0xe7, 0x9a, + 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0x95, 0x5b, 0x1f, 0x24, 0x8c, 0x84, 0x98, 0xd3, 0x2a, 0x78, 0x3a, 0x99, 0xc4, 0xe2, + 0x30, 0x49, 0xcd, 0xe0, 0x96, 0xcd, 0x07, 0xb5, 0xf9, 0x7a, 0x66, 0x43, 0xf5, 0x79, 0x0d, 0xf1, 0xbd, 0x61, 0x79, + 0x5a, 0xf8, 0x4a, 0x7d, 0x78, 0x56, 0xc4, 0x04, 0x17, 0x8a, 0xc7, 0x2f, 0xe4, 0x19, 0x53, 0x8e, 0x59, 0x28, 0x9b, + 0xb3, 0xb0, 0x28, 0xd4, 0xe9, 0xfc, 0x90, 0xe5, 0x33, 0xd0, 0x9e, 0x64, 0x4b, 0xfa, 0x29, 0x16, 0x9e, 0x5f, 0x1b, + 0xc9, 0x6d, 0xb5, 0xe5, 0x2a, 0xb4, 0x9d, 0x26, 0xb3, 0x85, 0xae, 0x79, 0x61, 0x2b, 0x93, 0x4d, 0x23, 0xd1, 0xb6, + 0x24, 0x3e, 0x65, 0xda, 0x9d, 0x31, 0x43, 0xc8, 0xfc, 0x29, 0x17, 0x44, 0xbf, 0xd2, 0x05, 0x85, 0x69, 0x65, 0x89, + 0x37, 0x12, 0x5b, 0x22, 0x55, 0x2c, 0x9f, 0xf9, 0x89, 0x36, 0xe6, 0x24, 0x3f, 0xd8, 0x5d, 0x54, 0x2b, 0x5f, 0xd8, + 0x1a, 0x6c, 0x49, 0xbc, 0xfd, 0xe3, 0x16, 0x34, 0xe8, 0x5b, 0x35, 0xd0, 0x93, 0xb5, 0x0c, 0xb3, 0xbb, 0xf3, 0xae, + 0x3f, 0x5e, 0xb8, 0xf9, 0x35, 0x76, 0xf3, 0x6b, 0xeb, 0xab, 0x45, 0xf3, 0x9a, 0x5e, 0x7e, 0x64, 0xbc, 0xc9, 0xfd, + 0x59, 0x13, 0xbc, 0xa7, 0x22, 0x33, 0x44, 0xb1, 0x67, 0xa1, 0xa3, 0x4b, 0xd3, 0xaf, 0x37, 0xcf, 0x21, 0x3d, 0x5b, + 0x98, 0x51, 0x5e, 0x92, 0x26, 0xb4, 0x57, 0x3f, 0xbe, 0x67, 0x66, 0x18, 0x6b, 0x6c, 0x8d, 0x16, 0x29, 0xa4, 0x73, + 0xf3, 0x5b, 0xaf, 0xad, 0xd8, 0x7a, 0x5b, 0xa7, 0x0f, 0xb7, 0x37, 0xd6, 0xf7, 0x14, 0x72, 0x1b, 0x42, 0x7a, 0x65, + 0xeb, 0xf9, 0xcf, 0xdb, 0xf2, 0xbb, 0x3f, 0x75, 0x98, 0x0d, 0xf2, 0x49, 0xf4, 0xff, 0xc6, 0x29, 0xc0, 0xd5, 0x62, + 0x71, 0x98, 0xed, 0x3e, 0x90, 0x79, 0xfe, 0x98, 0xd3, 0x0c, 0xdf, 0xa7, 0xe6, 0xa5, 0xb8, 0x77, 0x62, 0x01, 0x62, + 0xc6, 0xeb, 0x1c, 0xd5, 0x53, 0xb1, 0xef, 0xee, 0xfe, 0xee, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x1e, 0x56, 0xdb, 0xee, + 0xc1, 0x46, 0x88, 0xfd, 0x5b, 0x8f, 0x25, 0x42, 0xe6, 0x5d, 0x42, 0x52, 0x48, 0x6f, 0x96, 0xaa, 0x53, 0x99, 0x19, + 0x8d, 0xc5, 0xa7, 0xd7, 0xd5, 0x52, 0xec, 0x3f, 0x9c, 0xdd, 0xe8, 0xd5, 0xe8, 0xac, 0x9c, 0xb6, 0xfc, 0x43, 0x0f, + 0x55, 0x6e, 0x3f, 0xc5, 0x59, 0x3f, 0x18, 0x78, 0x38, 0xbb, 0xe9, 0x49, 0x41, 0xdb, 0xcc, 0x24, 0x54, 0xed, 0xd9, + 0x8d, 0x79, 0xac, 0xb4, 0xea, 0xc8, 0x72, 0xf7, 0x73, 0x8b, 0xfa, 0x39, 0xed, 0xc1, 0x97, 0xa6, 0x58, 0xe0, 0xc7, + 0x4a, 0x98, 0x4f, 0x59, 0x18, 0xc6, 0xb4, 0xa7, 0xe5, 0xb5, 0xd5, 0x79, 0x08, 0xa7, 0x32, 0xcd, 0x25, 0xab, 0xaf, + 0x8a, 0x81, 0xbc, 0x12, 0x4f, 0xfe, 0x65, 0x9e, 0xc6, 0xf0, 0x9d, 0xc7, 0x8d, 0xe8, 0x54, 0xc7, 0x15, 0xdb, 0x15, + 0xf2, 0xc4, 0xef, 0xfa, 0x5c, 0x0e, 0xdb, 0x7f, 0xea, 0x89, 0x05, 0x6f, 0xf7, 0x78, 0x3a, 0xf3, 0x9a, 0xfb, 0xf5, + 0x89, 0xc0, 0xab, 0x72, 0x0a, 0x78, 0xc3, 0xb4, 0x30, 0x48, 0x2b, 0xc9, 0xa7, 0x2d, 0xb7, 0xa3, 0xca, 0x44, 0x07, + 0x60, 0x84, 0x96, 0x45, 0x45, 0x7d, 0x32, 0xff, 0x98, 0xdd, 0xf2, 0x78, 0xf3, 0x6e, 0x79, 0xac, 0x77, 0xcb, 0xdd, + 0x14, 0xfb, 0xe5, 0xb8, 0x03, 0xff, 0xf5, 0xaa, 0x09, 0x79, 0x6d, 0x6b, 0x7f, 0x76, 0x63, 0x81, 0x9e, 0xd6, 0xec, + 0xce, 0x6e, 0xe4, 0xa1, 0x5a, 0x48, 0x5c, 0x6b, 0xc3, 0x31, 0x53, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, + 0x75, 0x0e, 0xe0, 0x1d, 0xb4, 0x3a, 0x5c, 0x7f, 0xd7, 0xbd, 0x7b, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, + 0xe4, 0x72, 0xff, 0xf2, 0x92, 0x86, 0xde, 0x38, 0x0d, 0xe6, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdc, 0xd2, + 0x2b, 0xfd, 0xe8, 0xa6, 0xf2, 0x88, 0xaf, 0xee, 0x61, 0x51, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, + 0xb0, 0x61, 0x13, 0xfc, 0x9b, 0xac, 0xcd, 0xc6, 0xc9, 0xfc, 0x5e, 0x64, 0xdc, 0x89, 0x84, 0xcf, 0xc2, 0x81, 0xb9, + 0x86, 0xed, 0xa3, 0xcd, 0xe0, 0x0e, 0xf5, 0x48, 0x23, 0x2d, 0x14, 0x94, 0xdc, 0x09, 0xe9, 0xd8, 0x9f, 0xc7, 0xfc, + 0xee, 0x5e, 0xb7, 0x51, 0xc6, 0x5a, 0xaf, 0x77, 0x30, 0xf4, 0xaa, 0xee, 0x3d, 0xb9, 0xf4, 0x97, 0x8f, 0x0f, 0xe0, + 0x3f, 0x79, 0xf8, 0xe5, 0xb2, 0xd2, 0xd5, 0xa5, 0xd5, 0x0b, 0xba, 0xfa, 0x55, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, + 0xe3, 0xf7, 0xad, 0x0d, 0x5a, 0xe5, 0xbd, 0xaa, 0x2b, 0x2d, 0xeb, 0xb3, 0x6a, 0x7f, 0x5e, 0xe7, 0xf7, 0xac, 0x1b, + 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x7a, 0x7e, 0xad, 0xb2, 0xc6, 0xb8, 0xa8, 0x7f, 0x45, 0x2e, 0x4b, 0x13, 0x45, + 0xa6, 0xa2, 0x82, 0x95, 0x72, 0x25, 0xad, 0x94, 0x94, 0x92, 0x8b, 0xe3, 0xc1, 0xcd, 0x34, 0xb6, 0xae, 0xe4, 0xfd, + 0x38, 0xc4, 0xee, 0xb8, 0x6d, 0xdb, 0x12, 0x4e, 0x3a, 0xf8, 0x4c, 0x97, 0xfd, 0xe1, 0xfd, 0xd7, 0xcd, 0x23, 0x7b, + 0x00, 0x9a, 0xd6, 0xd5, 0x44, 0x68, 0x76, 0x2f, 0xfd, 0x5b, 0x9a, 0x9d, 0x77, 0x95, 0x0b, 0x5e, 0xe6, 0x8b, 0x8b, + 0x32, 0xab, 0x6b, 0x5b, 0x37, 0xd3, 0x38, 0xc9, 0x89, 0x1d, 0x71, 0x3e, 0xf3, 0x5a, 0xad, 0xeb, 0xeb, 0x6b, 0xf7, + 0x7a, 0xdf, 0x4d, 0xb3, 0x49, 0xab, 0xdb, 0x6e, 0xb7, 0xe1, 0x8b, 0x1f, 0xb6, 0x75, 0xc5, 0xe8, 0xf5, 0x93, 0xf4, + 0x86, 0xd8, 0x6d, 0xab, 0x6d, 0x75, 0xba, 0x47, 0x56, 0xa7, 0x7b, 0xe0, 0x3e, 0x3c, 0xb2, 0xfb, 0x5f, 0x58, 0xd6, + 0x71, 0x48, 0xc7, 0x39, 0xfc, 0xb0, 0xac, 0x63, 0xa1, 0x78, 0xc9, 0xdf, 0x96, 0xe5, 0x06, 0x71, 0xde, 0xec, 0x58, + 0x0b, 0xf5, 0x68, 0x59, 0x70, 0x8b, 0x90, 0x67, 0x7d, 0x39, 0xee, 0x8e, 0x0f, 0xc6, 0x8f, 0x7b, 0xaa, 0xb8, 0xf8, + 0xa2, 0x56, 0x1d, 0xcb, 0x7f, 0xbb, 0x46, 0xb3, 0x9c, 0x67, 0xe9, 0x47, 0xaa, 0x5c, 0xfb, 0x16, 0x88, 0x9e, 0x8d, + 0x4d, 0xbb, 0xeb, 0x23, 0x75, 0x8e, 0x2e, 0x83, 0x71, 0xb7, 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0x1e, 0xb7, 0x34, + 0xe8, 0xc7, 0x26, 0x9a, 0x3a, 0xcd, 0x4d, 0x88, 0xea, 0xd8, 0x6a, 0x8e, 0x13, 0x3d, 0xbf, 0x63, 0x38, 0xb4, 0xae, + 0x75, 0x55, 0x01, 0x81, 0x6d, 0x85, 0xc4, 0x7e, 0xd5, 0xe9, 0x1e, 0xe1, 0x4e, 0xe7, 0xa1, 0xfb, 0xf0, 0x28, 0x68, + 0xe3, 0x03, 0xf7, 0xa0, 0xb9, 0xef, 0x3e, 0xc4, 0x47, 0xcd, 0x23, 0x7c, 0xf4, 0xfc, 0x28, 0x68, 0x1e, 0xb8, 0x07, + 0xb8, 0xdd, 0x3c, 0x82, 0xc2, 0xe6, 0x51, 0xf3, 0xe8, 0xaa, 0x79, 0x70, 0x14, 0xb4, 0x45, 0x69, 0xd7, 0x3d, 0x3c, + 0x6c, 0x76, 0xda, 0xee, 0xe1, 0x21, 0x3e, 0x74, 0x1f, 0x3e, 0x6c, 0x76, 0xf6, 0xdd, 0x87, 0x0f, 0x5f, 0x1e, 0x1e, + 0xb9, 0xfb, 0xf0, 0x6e, 0x7f, 0x3f, 0xd8, 0x77, 0x3b, 0x9d, 0x26, 0xfc, 0xc1, 0x47, 0x6e, 0x57, 0xfe, 0xe8, 0x74, + 0xdc, 0xfd, 0x0e, 0x6e, 0xc7, 0x87, 0x5d, 0xf7, 0xe1, 0x63, 0x2c, 0xfe, 0x8a, 0x6a, 0x58, 0xfc, 0x81, 0x6e, 0xf0, + 0x63, 0xb7, 0xfb, 0x50, 0xfe, 0x12, 0x1d, 0x5e, 0x1d, 0x1c, 0xfd, 0x68, 0xb7, 0xb6, 0xce, 0xa1, 0x23, 0xe7, 0x70, + 0x74, 0xe8, 0xee, 0xef, 0xe3, 0x83, 0x8e, 0x7b, 0xb4, 0x1f, 0x35, 0x0f, 0xba, 0xee, 0xc3, 0x47, 0x41, 0xb3, 0xe3, + 0x3e, 0x7a, 0x84, 0xdb, 0xcd, 0x7d, 0xb7, 0x8b, 0x3b, 0xee, 0xc1, 0xbe, 0xf8, 0xb1, 0xef, 0x76, 0xaf, 0x1e, 0x3d, + 0x76, 0x1f, 0x1e, 0x46, 0x0f, 0xdd, 0x83, 0x6f, 0x0f, 0x8e, 0xdc, 0xee, 0x7e, 0xb4, 0xff, 0xd0, 0xed, 0x3e, 0xba, + 0x7a, 0xe8, 0x1e, 0x44, 0xcd, 0xee, 0xc3, 0x3b, 0x5b, 0x76, 0xba, 0x2e, 0xe0, 0x48, 0xbc, 0x86, 0x17, 0x58, 0xbd, + 0x80, 0xff, 0x23, 0xd1, 0xf6, 0xdf, 0xb0, 0x9b, 0x7c, 0xbd, 0xe9, 0x63, 0xf7, 0xe8, 0x51, 0x20, 0xab, 0x43, 0x41, + 0x53, 0xd7, 0x80, 0x26, 0x57, 0x4d, 0x39, 0xac, 0xe8, 0xae, 0xa9, 0x3b, 0xd2, 0xff, 0xab, 0xc1, 0xae, 0x9a, 0x30, + 0xb0, 0x1c, 0xf7, 0xdf, 0xb5, 0x9f, 0x72, 0xc9, 0x8f, 0x5b, 0x13, 0x49, 0xfa, 0x93, 0xfe, 0x17, 0xf2, 0x73, 0x3e, + 0x5f, 0x5c, 0x60, 0x7f, 0x9b, 0xe3, 0x23, 0xfe, 0xb4, 0xe3, 0x23, 0xa2, 0xf7, 0xf1, 0x7c, 0xc4, 0x7f, 0xb8, 0xe7, + 0xc3, 0x5f, 0x75, 0x9b, 0xdf, 0xf0, 0x35, 0x07, 0xc7, 0xaa, 0x55, 0xfc, 0x82, 0x3b, 0xc3, 0x14, 0x3e, 0x1d, 0x5d, + 0xf4, 0x6e, 0x38, 0x89, 0xa8, 0xe9, 0x07, 0x4a, 0x81, 0xc5, 0xde, 0x70, 0xc9, 0x63, 0x83, 0x6d, 0x08, 0x09, 0x3f, + 0x8d, 0x90, 0xef, 0xee, 0x83, 0x8f, 0xf0, 0x0f, 0xc7, 0x47, 0x60, 0xe2, 0xa3, 0xe6, 0xc9, 0x17, 0x9e, 0x06, 0xe1, + 0x29, 0x38, 0x13, 0xcf, 0x0e, 0xdc, 0x9a, 0xd1, 0xb0, 0x5b, 0xf4, 0x4a, 0x44, 0xee, 0x64, 0x70, 0xfd, 0xf9, 0xe7, + 0x04, 0x1d, 0xe4, 0x15, 0x39, 0xc4, 0x56, 0x6e, 0x99, 0x99, 0x90, 0x3a, 0xea, 0xa1, 0x14, 0x4a, 0x5d, 0xb7, 0xed, + 0xb6, 0x4b, 0x97, 0x0e, 0x5c, 0x8b, 0x44, 0x16, 0x29, 0xf7, 0xbd, 0x9d, 0x0e, 0x8e, 0xd3, 0x09, 0x5c, 0x96, 0x24, + 0x3e, 0x1f, 0x07, 0x27, 0x1e, 0x02, 0xf9, 0xe5, 0x3e, 0x48, 0x9f, 0x50, 0x8e, 0x1e, 0x3f, 0xfb, 0xf8, 0x37, 0x08, + 0x62, 0xea, 0x98, 0xc4, 0x14, 0xbc, 0x1d, 0xaf, 0x68, 0xc8, 0x7c, 0xc7, 0x76, 0x66, 0x19, 0x1d, 0xd3, 0x2c, 0x6f, + 0xd6, 0xee, 0xeb, 0x11, 0x57, 0xf5, 0x20, 0x5b, 0x41, 0x38, 0xce, 0xe0, 0x73, 0x48, 0x64, 0xa8, 0xfc, 0x8d, 0xb6, + 0x32, 0xc0, 0xec, 0x02, 0xeb, 0x92, 0x0c, 0x64, 0x6d, 0xa5, 0xb4, 0xd9, 0x52, 0x6b, 0xeb, 0xb8, 0xdd, 0x43, 0x64, + 0x89, 0x62, 0xf8, 0xd0, 0xcc, 0x0f, 0x4e, 0x73, 0xbf, 0xfd, 0x27, 0x64, 0x34, 0x2b, 0x3b, 0x1a, 0x29, 0x77, 0x5b, + 0x52, 0x7e, 0x8e, 0x70, 0x25, 0xec, 0x6a, 0x4b, 0x8a, 0xf8, 0x52, 0xce, 0xdd, 0x46, 0xbd, 0x44, 0x25, 0xcd, 0xc9, + 0x2b, 0x01, 0xc7, 0x6c, 0xe2, 0x18, 0xd7, 0x4d, 0x24, 0xf2, 0x43, 0x36, 0x70, 0x5b, 0x3d, 0x42, 0x45, 0x55, 0x25, + 0x41, 0x0b, 0x11, 0x6d, 0x61, 0x89, 0x95, 0x2c, 0x97, 0x4e, 0x02, 0x2e, 0x72, 0x62, 0xe0, 0x14, 0x9e, 0x51, 0x0d, + 0xc9, 0x09, 0x2e, 0x01, 0x12, 0x08, 0x26, 0x89, 0xfc, 0xb7, 0x2a, 0xd6, 0x3f, 0x94, 0xe3, 0xcb, 0x8d, 0xfd, 0x64, + 0x02, 0x54, 0xe8, 0x27, 0x93, 0x35, 0xb7, 0x9a, 0x0c, 0x18, 0xad, 0x94, 0x56, 0x5d, 0x55, 0xee, 0xb3, 0xfc, 0xc9, + 0xed, 0x7b, 0x75, 0xe3, 0xb5, 0x0d, 0xde, 0x69, 0x11, 0xdf, 0xa8, 0xbe, 0xce, 0xd3, 0x20, 0x0f, 0x8e, 0xa7, 0x94, + 0xfb, 0xf2, 0xb0, 0x1a, 0xe8, 0x13, 0x90, 0xcb, 0x62, 0x29, 0x6b, 0x54, 0x05, 0xf5, 0x89, 0x3c, 0xcc, 0x2f, 0x45, + 0x3d, 0xb6, 0xd4, 0x55, 0x71, 0x4d, 0xb1, 0x34, 0xa4, 0x83, 0xa5, 0x3f, 0x26, 0xf0, 0xc5, 0x71, 0x64, 0x92, 0xa4, + 0x76, 0xff, 0x41, 0x99, 0xeb, 0xb2, 0x6d, 0x11, 0x62, 0x96, 0x7c, 0x1c, 0x66, 0x34, 0xfe, 0x27, 0xf2, 0x80, 0x05, + 0x69, 0xf2, 0x60, 0x64, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, 0x8e, 0xc9, 0x03, 0x90, 0xf1, 0x9e, 0xb0, 0x3e, 0x80, 0x11, + 0x36, 0x6e, 0xa6, 0x31, 0x16, 0x1a, 0xd3, 0x3d, 0x14, 0x22, 0x09, 0xae, 0xdd, 0x3d, 0xb4, 0x2d, 0x69, 0x13, 0x8b, + 0xdf, 0x7d, 0x29, 0x4e, 0x85, 0x12, 0x60, 0x75, 0xba, 0xee, 0x61, 0xd4, 0x75, 0x1f, 0x5f, 0x3d, 0x72, 0x8f, 0xa2, + 0xce, 0xa3, 0xab, 0x26, 0xfc, 0xdb, 0x75, 0x1f, 0xc7, 0xcd, 0xae, 0xfb, 0x18, 0xfe, 0xff, 0xf6, 0xc0, 0x3d, 0x8c, + 0x9a, 0x1d, 0xf7, 0xe8, 0x6a, 0xdf, 0xdd, 0x7f, 0xd9, 0xe9, 0xba, 0xfb, 0x56, 0xc7, 0x92, 0xed, 0x80, 0x5d, 0x4b, + 0xee, 0xfc, 0x60, 0x65, 0x43, 0x6c, 0x08, 0xc6, 0xc9, 0x03, 0x77, 0x36, 0x16, 0x67, 0xa4, 0xcd, 0xfd, 0xa9, 0x9c, + 0x75, 0x4f, 0xfd, 0x0c, 0xbe, 0x6c, 0x5a, 0xdf, 0xbb, 0xb5, 0x77, 0xb8, 0xc6, 0x2f, 0x36, 0x0c, 0x31, 0x13, 0x11, + 0x70, 0xf3, 0xae, 0x35, 0xb8, 0xa8, 0x4c, 0x7c, 0x08, 0x4a, 0xdf, 0x87, 0xbf, 0x9d, 0xb4, 0x65, 0x45, 0x7d, 0xe7, + 0xbe, 0x60, 0x16, 0x4c, 0x7c, 0x72, 0x4f, 0x0c, 0xf2, 0x22, 0x2c, 0x56, 0xc7, 0x87, 0x73, 0x7f, 0x59, 0x6a, 0x5c, + 0x37, 0x47, 0xab, 0x20, 0x7f, 0xc8, 0xe0, 0x82, 0xc0, 0xa2, 0xd0, 0xa0, 0xd7, 0xdc, 0xb4, 0x15, 0x96, 0x04, 0xbf, + 0xa0, 0xf9, 0xc0, 0x86, 0x22, 0xdb, 0xb3, 0x85, 0x8b, 0xcf, 0x2e, 0xbf, 0xee, 0x5a, 0x12, 0x76, 0x55, 0x80, 0xc5, + 0xed, 0x0f, 0xb0, 0x6b, 0x01, 0x3f, 0x36, 0xda, 0xdb, 0xdb, 0xba, 0x5f, 0x84, 0x02, 0x09, 0x73, 0xad, 0x3e, 0x0a, + 0x69, 0xb2, 0x22, 0xdb, 0x44, 0x74, 0xd9, 0xaf, 0x40, 0x21, 0x52, 0x78, 0xba, 0xa4, 0x3e, 0x77, 0xfd, 0x44, 0x9e, + 0x20, 0x30, 0x18, 0x16, 0xee, 0xd0, 0x7d, 0x54, 0xa4, 0xdc, 0x97, 0x49, 0x61, 0xe6, 0x3e, 0x4f, 0xb9, 0xaf, 0x2f, + 0x4f, 0xf2, 0x79, 0xed, 0xe0, 0x7c, 0xd4, 0xed, 0xbf, 0x79, 0x7f, 0x62, 0xc9, 0xed, 0x79, 0xdc, 0x8a, 0xba, 0xfd, + 0x63, 0xe1, 0x33, 0x91, 0x61, 0x7f, 0x22, 0xc3, 0xfe, 0x96, 0xba, 0x35, 0x06, 0x22, 0x69, 0x45, 0x4b, 0x4e, 0x5b, + 0xd8, 0x0c, 0xd2, 0xdb, 0x3b, 0x9d, 0xc7, 0x9c, 0xc1, 0x47, 0x8d, 0x5a, 0x22, 0xe6, 0x2f, 0x72, 0x08, 0xf4, 0x21, + 0x54, 0xa5, 0x1d, 0x5e, 0xf2, 0x44, 0xfb, 0x86, 0xc7, 0x2c, 0xa6, 0xfa, 0xd8, 0xa9, 0xea, 0xaa, 0x4c, 0xf8, 0x59, + 0xaf, 0x9d, 0xcf, 0x2f, 0x21, 0xe9, 0x41, 0xa7, 0x17, 0x7d, 0x50, 0x0d, 0x8e, 0xc5, 0x50, 0x10, 0xb9, 0x97, 0x62, + 0x5a, 0x7f, 0xbe, 0xb5, 0xbe, 0xa4, 0x6a, 0xf6, 0x4a, 0x42, 0xc0, 0x55, 0x1d, 0xd1, 0x7e, 0xbf, 0x74, 0x17, 0x9b, + 0xef, 0x8a, 0xe3, 0x56, 0xb4, 0xdf, 0xbf, 0xf0, 0x26, 0xaa, 0xbf, 0x97, 0xe9, 0x64, 0x73, 0x5f, 0x71, 0x3a, 0x19, + 0x88, 0x73, 0xf0, 0xf2, 0x4e, 0x27, 0xad, 0xfc, 0xa6, 0xb1, 0xdd, 0x3f, 0x56, 0xca, 0x80, 0x25, 0xc2, 0xea, 0xf6, + 0x61, 0x5b, 0x1f, 0xad, 0x8f, 0xd3, 0x09, 0x6c, 0x48, 0xd9, 0xc4, 0x18, 0xa4, 0xe6, 0x71, 0x8f, 0x3a, 0xfd, 0x63, + 0xdf, 0x12, 0xbc, 0x45, 0x30, 0x8f, 0xdc, 0x6b, 0x41, 0xe3, 0x28, 0x9d, 0x52, 0x97, 0xa5, 0xad, 0x6b, 0x7a, 0xd9, + 0xf4, 0x67, 0xac, 0x72, 0x6f, 0x83, 0xd2, 0x51, 0x0e, 0x99, 0xae, 0xa4, 0x58, 0x75, 0x2b, 0x77, 0xdb, 0x01, 0xd8, + 0x3c, 0xda, 0x35, 0x27, 0x7c, 0x72, 0x06, 0x58, 0x69, 0xff, 0xb8, 0xe5, 0xaf, 0x60, 0x44, 0xf0, 0xfb, 0x42, 0x39, + 0xda, 0xc1, 0xb0, 0xb9, 0x14, 0xf9, 0x5d, 0x52, 0x1c, 0x68, 0x87, 0xbc, 0x12, 0xd4, 0x85, 0xdd, 0xff, 0xd7, 0xff, + 0xf1, 0xbf, 0x94, 0x8f, 0xfd, 0xb8, 0x15, 0x75, 0x74, 0x5f, 0x2b, 0xab, 0x52, 0x1c, 0xc3, 0x45, 0x35, 0x55, 0x50, + 0x98, 0xde, 0x34, 0x27, 0x19, 0x0b, 0x9b, 0x91, 0x1f, 0x8f, 0xed, 0xfe, 0x76, 0x6c, 0xca, 0xfc, 0xc3, 0xa6, 0x0e, + 0xa7, 0xae, 0x17, 0x01, 0xbd, 0xfe, 0xa6, 0x5b, 0x17, 0x74, 0x4a, 0x97, 0xd8, 0xda, 0xe6, 0x1d, 0x0c, 0xd5, 0xee, + 0xab, 0xdd, 0xc3, 0x90, 0xa8, 0x6f, 0x42, 0x2b, 0x0e, 0x98, 0xd4, 0xae, 0x5f, 0x28, 0x6c, 0xab, 0x0c, 0x6a, 0xfd, + 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x7e, 0x84, 0x58, 0xd5, 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, + 0x85, 0xfc, 0x33, 0x15, 0xcf, 0x12, 0x4c, 0xc5, 0xaa, 0x82, 0x59, 0x92, 0xbb, 0x58, 0x70, 0xaa, 0x6d, 0xca, 0x72, + 0xce, 0x82, 0xfa, 0x85, 0x0c, 0x67, 0x62, 0x40, 0xb1, 0x33, 0x15, 0x74, 0x62, 0x87, 0x17, 0x15, 0x41, 0xd5, 0x50, + 0x2e, 0x08, 0xb7, 0x38, 0x6e, 0x01, 0xbe, 0xef, 0x77, 0x9f, 0x8c, 0x5b, 0x2e, 0xc7, 0x42, 0x93, 0x09, 0x94, 0x14, + 0x55, 0xb9, 0x05, 0xb1, 0x95, 0x05, 0x3c, 0x7a, 0x5d, 0xa3, 0x58, 0xac, 0x5e, 0xad, 0x4d, 0xef, 0xe7, 0x79, 0xce, + 0xd9, 0x18, 0x50, 0x2e, 0xfd, 0xc4, 0x22, 0x8c, 0xdd, 0x04, 0x5d, 0x31, 0xbe, 0x2d, 0x44, 0x2f, 0x92, 0x40, 0x0f, + 0x8e, 0xfe, 0x54, 0xfc, 0x79, 0x0a, 0x1a, 0x99, 0xe5, 0x4c, 0xfd, 0x1b, 0x65, 0x9e, 0x3f, 0x6c, 0xb7, 0x67, 0x37, + 0x68, 0x51, 0x8d, 0x80, 0xb7, 0x0d, 0x26, 0xe8, 0xd8, 0xec, 0x50, 0xc4, 0xbf, 0x4b, 0x37, 0x76, 0xdb, 0x02, 0x5f, + 0xb8, 0xd5, 0x2e, 0x8a, 0xaf, 0x16, 0xc2, 0x93, 0xca, 0x7e, 0x85, 0x38, 0xb5, 0x72, 0x3a, 0x5f, 0xa6, 0xe6, 0xe4, + 0x16, 0x46, 0xab, 0xae, 0x6c, 0x15, 0x75, 0xd6, 0xaf, 0x66, 0x31, 0xe3, 0xec, 0x66, 0x84, 0xfc, 0x00, 0x62, 0xde, + 0x51, 0x07, 0x47, 0xdd, 0x45, 0xd9, 0x3d, 0xe7, 0xe9, 0xd4, 0x0c, 0xac, 0x53, 0x9f, 0x06, 0x74, 0xac, 0x9d, 0xf5, + 0xea, 0xbd, 0x0c, 0x9a, 0x17, 0xd1, 0xfe, 0x86, 0xb1, 0x14, 0x48, 0x22, 0xa0, 0x6e, 0xb5, 0x8b, 0x2f, 0x61, 0x07, + 0x2e, 0xc6, 0x71, 0xea, 0x73, 0x4f, 0x10, 0x6c, 0xcf, 0x0c, 0xcf, 0xfb, 0xc0, 0x93, 0xd2, 0x85, 0x01, 0x4f, 0x4f, + 0x56, 0x05, 0xb7, 0x79, 0xfd, 0x8a, 0xc6, 0xc2, 0x15, 0xcd, 0xcd, 0xae, 0xa4, 0xd7, 0xed, 0x3b, 0x15, 0xf5, 0x7e, + 0x5e, 0x73, 0x57, 0x29, 0x81, 0xd4, 0x45, 0x9b, 0xdf, 0x4b, 0xb9, 0x2e, 0xdf, 0x7e, 0xcf, 0x1d, 0x5b, 0x80, 0x69, + 0xaf, 0xd6, 0x12, 0x85, 0x50, 0xeb, 0x39, 0xf9, 0xae, 0x34, 0x99, 0xfc, 0xd9, 0x4c, 0x54, 0x44, 0xbd, 0xe3, 0x96, + 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, + 0x56, 0x78, 0xff, 0xff, 0x01, 0xa2, 0x89, 0x8c, 0x0d, 0xc4, 0x97, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0x20, 0x98, 0x51, 0xd4, 0x8d, 0x56, 0x4b, 0xe5, 0xa2, 0xa8, 0x56, 0xa5, 0x80, 0x56, 0x05, 0xd9, 0x90, 0x89, - 0x0d, 0xfb, 0x77, 0x53, 0xb6, 0xa6, 0x94, 0xb5, 0x35, 0x4d, 0x09, 0x86, 0xa5, 0xbd, 0xe9, 0xf6, 0x5f, 0xc7, 0xd8, - 0xa5, 0xc5, 0x13, 0x67, 0x4e, 0x5c, 0xc8, 0x0a, 0xc3, 0x73, 0x8e, 0xd0, 0xd8, 0x27, 0xb9, 0xf7, 0xbe, 0x4d, 0xff, - 0xbf, 0x7e, 0x63, 0x35, 0x27, 0x95, 0x6f, 0x03, 0x48, 0x26, 0x74, 0x17, 0xcd, 0xb2, 0x2d, 0xa7, 0x0f, 0x84, 0x3d, - 0xe0, 0x49, 0x6c, 0xc9, 0x1d, 0x8d, 0x59, 0x62, 0xf2, 0xff, 0xf3, 0xfc, 0xac, 0xa5, 0xdf, 0x7d, 0x2e, 0x27, 0x83, - 0xa2, 0x56, 0xbd, 0xe9, 0x4a, 0xfd, 0xe5, 0xd8, 0xf8, 0x85, 0x59, 0x77, 0xcf, 0x9c, 0x10, 0x52, 0x98, 0xd0, 0xb6, - 0xf3, 0x17, 0x88, 0xa0, 0xb2, 0xd3, 0xfe, 0xbf, 0xda, 0xfa, 0x8a, 0xbb, 0x92, 0xc8, 0xa5, 0xcf, 0x29, 0xfc, 0x3e, - 0x57, 0x36, 0x86, 0x9e, 0x5e, 0x9e, 0x90, 0xd5, 0xfb, 0x32, 0x3b, 0x78, 0xb0, 0x3f, 0xa8, 0xc0, 0xa7, 0x29, 0x9b, - 0x63, 0xab, 0x96, 0x3f, 0xf2, 0xeb, 0x24, 0x98, 0x30, 0x9c, 0x28, 0xec, 0x20, 0x99, 0x71, 0xca, 0x01, 0x6b, 0xf3, - 0xb6, 0x34, 0x69, 0x05, 0x17, 0xb8, 0x27, 0x2e, 0xd6, 0xc1, 0xcc, 0x73, 0xbe, 0x59, 0xba, 0xac, 0x5a, 0xff, 0x07, - 0x35, 0x91, 0x76, 0x74, 0xc7, 0x0e, 0x72, 0x8d, 0x9d, 0x71, 0xfc, 0x41, 0xf6, 0xdf, 0x9b, 0x6a, 0x95, 0x36, 0x40, - 0xb3, 0xbb, 0xe7, 0x7c, 0x6a, 0x5c, 0x6a, 0x9c, 0x32, 0x88, 0x2b, 0x9d, 0xf3, 0x49, 0x70, 0x41, 0xc8, 0x7e, 0xef, - 0xfd, 0xff, 0x86, 0xed, 0x30, 0x44, 0x77, 0x13, 0x3b, 0x70, 0x94, 0x08, 0x92, 0x58, 0xfa, 0x12, 0xad, 0xe4, 0xff, - 0xff, 0x0d, 0x80, 0xdd, 0x00, 0xa5, 0x05, 0x29, 0x69, 0x8b, 0xe2, 0x70, 0xab, 0x68, 0xd6, 0x19, 0xce, 0xac, 0x3d, - 0xe3, 0x75, 0x53, 0x75, 0xd6, 0x45, 0x36, 0x4a, 0x8c, 0xcf, 0xae, 0x72, 0x1b, 0x85, 0xc6, 0xa6, 0x97, 0x5d, 0x78, - 0xe9, 0x39, 0x15, 0x55, 0xca, 0xed, 0x59, 0x9b, 0x06, 0x63, 0xd8, 0x32, 0x74, 0xf8, 0xac, 0x3a, 0xeb, 0xd9, 0x94, - 0x1b, 0xc2, 0x2d, 0x27, 0xc4, 0xba, 0x6d, 0xa4, 0xda, 0xe1, 0x38, 0xe9, 0x72, 0xee, 0x62, 0xa6, 0x10, 0x42, 0x03, - 0xc1, 0xfb, 0xe3, 0xc6, 0xf4, 0xc2, 0xdd, 0x9c, 0x44, 0x30, 0x31, 0xb6, 0x38, 0x40, 0x3a, 0x05, 0x7e, 0xe8, 0x50, - 0xa7, 0x9b, 0x52, 0x9c, 0x27, 0xe8, 0xf4, 0x37, 0x82, 0x69, 0xb6, 0x87, 0xa0, 0x1c, 0xc3, 0x81, 0x0d, 0x68, 0x64, - 0x79, 0xe6, 0xea, 0xdd, 0x07, 0x36, 0x5e, 0xd7, 0x2f, 0xc8, 0xa0, 0xc7, 0xbb, 0xdd, 0x1c, 0x70, 0x93, 0x92, 0x73, - 0xd7, 0x28, 0x1b, 0x41, 0xd7, 0xac, 0x5a, 0x08, 0xf2, 0x77, 0xfd, 0xf3, 0xb7, 0x37, 0x07, 0x1a, 0x93, 0xe8, 0x1f, - 0x52, 0xd3, 0x52, 0xc2, 0xb3, 0xa0, 0x4b, 0xda, 0x5e, 0xc0, 0xe1, 0x8b, 0x90, 0x87, 0x9e, 0x87, 0x5d, 0xf0, 0x5a, - 0x6b, 0xdd, 0x4e, 0x73, 0x3c, 0x33, 0x66, 0x6c, 0xb9, 0x48, 0xf5, 0x40, 0xcd, 0xf4, 0xce, 0xe1, 0xa0, 0x4b, 0x55, - 0x38, 0xab, 0xce, 0x49, 0xb4, 0xe9, 0x76, 0x89, 0x91, 0x3b, 0x5d, 0x7e, 0x9c, 0x52, 0xba, 0xf9, 0xbb, 0xad, 0x9a, - 0x84, 0x7b, 0x7a, 0x8b, 0x5f, 0xe3, 0xe1, 0x4f, 0x3b, 0x2f, 0xc2, 0x0a, 0x8a, 0x88, 0x78, 0xa4, 0x48, 0xb9, 0x3c, - 0x58, 0x4d, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0xc1, 0x48, 0x01, 0x2b, 0x1a, 0xe7, 0x08, 0xe7, 0x65, 0x7e, 0x9c, - 0x8c, 0x79, 0x59, 0xc4, 0xa7, 0x87, 0xc3, 0x79, 0xe7, 0x0e, 0xd7, 0x9d, 0x9b, 0xbd, 0x59, 0x0f, 0xa6, 0x6e, 0x5f, - 0x7f, 0x17, 0xf2, 0x6e, 0x58, 0x4f, 0xc1, 0xd6, 0x96, 0x5f, 0xbb, 0x5e, 0xf1, 0x0b, 0x35, 0x97, 0xae, 0xeb, 0xf5, - 0x80, 0x9b, 0xa6, 0x09, 0x32, 0x16, 0xda, 0x03, 0xfa, 0x73, 0x55, 0xc9, 0xfa, 0xf3, 0x20, 0x13, 0xca, 0x29, 0xfb, - 0x2e, 0xb8, 0xed, 0xba, 0xc4, 0xb1, 0x78, 0x42, 0xa6, 0x9a, 0xc8, 0x37, 0xf8, 0x8f, 0x80, 0x5a, 0x1e, 0x6c, 0xf0, - 0x28, 0xe4, 0x21, 0x30, 0xae, 0x23, 0x8a, 0xaa, 0xe6, 0x91, 0x50, 0xfd, 0xd6, 0xef, 0xd6, 0x20, 0x83, 0xfc, 0x5b, - 0xa3, 0x31, 0xda, 0x60, 0x08, 0x92, 0x99, 0xbb, 0x4d, 0xb2, 0x0b, 0x80, 0xc0, 0x54, 0x1d, 0x49, 0x69, 0x99, 0x47, - 0xe4, 0xe9, 0x78, 0x8e, 0x91, 0xf9, 0xc0, 0x7b, 0x1c, 0x16, 0xd3, 0x8d, 0xb8, 0xe1, 0x76, 0x00, 0x43, 0xc8, 0xdd, - 0x82, 0xa9, 0x6b, 0xca, 0x20, 0x19, 0xec, 0x14, 0x94, 0x34, 0x29, 0x90, 0x9c, 0x5d, 0xd3, 0x1c, 0x15, 0x01, 0x79, - 0xdd, 0xb5, 0xd3, 0xb1, 0x6f, 0x6b, 0xbc, 0xc5, 0x9b, 0xbf, 0xb3, 0x8e, 0x46, 0xc4, 0xf8, 0xbb, 0x6b, 0xe7, 0x92, - 0x8b, 0xb5, 0x02, 0xa4, 0x93, 0x70, 0xd7, 0x6b, 0xbf, 0x51, 0x3a, 0x6d, 0x9b, 0x39, 0x6c, 0x3f, 0x62, 0x26, 0xed, - 0xdc, 0x7a, 0x8f, 0x73, 0x9d, 0xaa, 0x98, 0x6d, 0x0e, 0x8f, 0x9f, 0x53, 0x24, 0x2a, 0xa9, 0x87, 0xed, 0xb7, 0x51, - 0x02, 0xfb, 0x5e, 0x6e, 0x3a, 0x4f, 0x98, 0xe9, 0x13, 0x9c, 0xf2, 0x8c, 0x58, 0x16, 0x30, 0xe5, 0x02, 0xf1, 0xde, - 0xc6, 0x4a, 0xb3, 0x4d, 0xd0, 0x10, 0xcc, 0xe4, 0x4f, 0xa5, 0x6b, 0x1b, 0xff, 0xb2, 0x88, 0x21, 0xd6, 0x41, 0x82, - 0x0f, 0x3f, 0x57, 0x0d, 0xa1, 0x94, 0xb0, 0x70, 0x9d, 0x8f, 0xef, 0x2a, 0x40, 0xca, 0x29, 0x90, 0x40, 0x42, 0x05, - 0xd4, 0xb9, 0x73, 0x46, 0xb0, 0xed, 0x27, 0x3c, 0xbf, 0x0f, 0xf2, 0x76, 0xb2, 0xc8, 0xf2, 0x5a, 0x64, 0x2b, 0x87, - 0x3b, 0x01, 0xf6, 0x7d, 0x9b, 0xea, 0x01, 0xf3, 0xd1, 0xef, 0x76, 0xb4, 0x39, 0x81, 0x85, 0xdb, 0x7a, 0x30, 0xdb, - 0x78, 0x5e, 0xfa, 0x17, 0x82, 0x5e, 0xf9, 0x1e, 0x44, 0xd3, 0x96, 0xa8, 0xc2, 0x7f, 0x7f, 0xfd, 0x9a, 0x40, 0xdc, - 0xb5, 0xe2, 0xd6, 0xff, 0xf0, 0xee, 0x26, 0x37, 0x44, 0x61, 0x3d, 0x70, 0x5d, 0xaa, 0xd3, 0xa5, 0x5a, 0x5f, 0x83, - 0x00, 0x34, 0x6e, 0x25, 0xd8, 0xdf, 0x14, 0x01, 0xb1, 0xfb, 0xd5, 0xf1, 0xaf, 0xdb, 0x11, 0x42, 0x82, 0xd4, 0xd9, - 0xce, 0x19, 0xf6, 0xbb, 0xf4, 0x41, 0x9b, 0x2d, 0x6a, 0x0a, 0xb3, 0x3f, 0x30, 0xbe, 0x26, 0x50, 0x28, 0x33, 0x9e, - 0x17, 0x99, 0xc4, 0x9d, 0xdc, 0xe1, 0x7a, 0x70, 0x5d, 0xe5, 0x2a, 0x7c, 0x24, 0xd6, 0x2a, 0x91, 0x3c, 0x73, 0xed, - 0x02, 0x7d, 0xb0, 0xe8, 0xc0, 0xae, 0x91, 0x11, 0xfe, 0xf3, 0xa8, 0x0a, 0x5e, 0x39, 0x9a, 0x95, 0x35, 0x5f, 0x8d, - 0x17, 0xbd, 0x05, 0x57, 0x7c, 0xde, 0xa9, 0x87, 0xce, 0xcc, 0xdb, 0xd1, 0xcf, 0x25, 0x83, 0xe4, 0xca, 0x62, 0x12, - 0x0a, 0x75, 0xea, 0x88, 0x32, 0x8b, 0x16, 0x18, 0x9b, 0xf9, 0xcb, 0x17, 0xcf, 0x82, 0x4e, 0x88, 0xb4, 0x9d, 0xca, - 0xce, 0x86, 0x67, 0xfc, 0x60, 0x87, 0x7a, 0x91, 0x9d, 0x4f, 0x48, 0x04, 0x0a, 0xdf, 0xba, 0xed, 0xd9, 0x7f, 0xca, - 0x43, 0xcb, 0x17, 0x5d, 0xfb, 0x93, 0x27, 0xd9, 0xed, 0x36, 0x12, 0xc5, 0x6d, 0x92, 0x90, 0xd8, 0x70, 0xd3, 0x7d, - 0x5c, 0xd6, 0x0a, 0x89, 0x4b, 0x34, 0xd7, 0x4a, 0x3b, 0xa5, 0x63, 0xec, 0xd2, 0x48, 0x59, 0xbb, 0x3d, 0x3e, 0x8b, - 0x1b, 0x7d, 0x15, 0x57, 0x20, 0x43, 0x4c, 0xd5, 0x13, 0xea, 0x9e, 0xc4, 0x35, 0x60, 0x58, 0x70, 0x64, 0x45, 0x73, - 0x21, 0x51, 0x09, 0x09, 0x86, 0xe9, 0xb4, 0x1f, 0x78, 0x29, 0xea, 0x6d, 0x10, 0x07, 0x88, 0x37, 0xf0, 0xf2, 0xfc, - 0x0a, 0x84, 0x15, 0xb5, 0x15, 0x80, 0x13, 0x55, 0x90, 0xf0, 0x15, 0x0a, 0x0c, 0x0a, 0xd4, 0x6b, 0x50, 0x04, 0x7b, - 0x44, 0xef, 0x04, 0x60, 0x90, 0x5b, 0xcd, 0x18, 0xde, 0xb6, 0x46, 0x6f, 0x03, 0x8e, 0xd9, 0xd8, 0x36, 0xcd, 0xa4, - 0x48, 0x61, 0x70, 0x7a, 0x89, 0xc5, 0x14, 0x75, 0xa3, 0xe6, 0xca, 0x92, 0xd8, 0x55, 0xdd, 0xdd, 0x9a, 0x22, 0x8d, - 0x7c, 0x58, 0x0f, 0xd1, 0x77, 0x67, 0xda, 0xe3, 0x02, 0x70, 0x0a, 0xb5, 0x61, 0xe5, 0xf6, 0x25, 0x8f, 0xb5, 0x50, - 0xf0, 0xf7, 0xbc, 0x6e, 0x20, 0xee, 0x45, 0x77, 0xea, 0x72, 0x22, 0x8c, 0xe3, 0x27, 0x03, 0xfb, 0xa9, 0x31, 0xc2, - 0x3d, 0xe4, 0x91, 0xb5, 0xb3, 0xa1, 0x0a, 0x8d, 0x70, 0x3d, 0x24, 0x9f, 0xf7, 0x97, 0xb4, 0xaf, 0x31, 0xd2, 0x71, - 0x71, 0x3e, 0xbc, 0x78, 0x63, 0x30, 0x15, 0xe0, 0x16, 0xad, 0xe7, 0xa0, 0xd9, 0x5a, 0xc6, 0x32, 0x7b, 0x70, 0xc8, - 0x8e, 0xe3, 0xda, 0xe9, 0xda, 0x22, 0xac, 0xda, 0x78, 0x20, 0x31, 0x24, 0xf0, 0x9b, 0x25, 0x86, 0x94, 0xc0, 0x4a, - 0x7c, 0xf4, 0xda, 0x40, 0x08, 0x5c, 0xbf, 0xe6, 0x20, 0x25, 0x98, 0xe5, 0xcb, 0x5f, 0xd2, 0x90, 0x8a, 0x5c, 0x0d, - 0x08, 0x19, 0xa9, 0xcf, 0x28, 0xcf, 0xac, 0xe0, 0x41, 0x71, 0xfc, 0x23, 0x46, 0x87, 0xcf, 0x9f, 0xed, 0x87, 0xc6, - 0xbe, 0x85, 0xf2, 0xa2, 0xac, 0x54, 0x66, 0x8e, 0x72, 0x42, 0x82, 0x22, 0x4b, 0x9e, 0x22, 0xb6, 0xf1, 0x15, 0x2b, - 0x41, 0x05, 0xf0, 0x8d, 0x40, 0xc6, 0xbb, 0x53, 0xc1, 0xb1, 0x89, 0x14, 0x01, 0x86, 0x76, 0x3b, 0x81, 0x84, 0xc0, - 0x20, 0x13, 0x47, 0x92, 0xab, 0xa3, 0x41, 0x62, 0x7f, 0x32, 0x8f, 0x5d, 0x38, 0x23, 0x92, 0xb5, 0x10, 0x24, 0x18, - 0x69, 0xbc, 0x57, 0x46, 0x9a, 0x80, 0xb0, 0x36, 0x40, 0xc7, 0xca, 0x3f, 0x83, 0x15, 0x96, 0x23, 0x30, 0x37, 0x2b, - 0xb8, 0x4b, 0xf3, 0x12, 0x42, 0xf4, 0x87, 0x95, 0x0a, 0xe8, 0xc7, 0x43, 0x7f, 0xce, 0x26, 0x28, 0x52, 0x10, 0xb4, - 0x42, 0x3c, 0xe4, 0x98, 0x4e, 0x14, 0x31, 0x70, 0xfa, 0xc7, 0x3d, 0x2c, 0xf6, 0x03, 0xb1, 0x60, 0x45, 0x45, 0x63, - 0x92, 0xbd, 0x14, 0xf5, 0x31, 0x62, 0xf0, 0x87, 0x19, 0x3b, 0x74, 0x9a, 0xa8, 0xa4, 0x97, 0x2a, 0x15, 0xeb, 0x60, - 0x5d, 0xa8, 0xac, 0x04, 0xe9, 0xd4, 0xe4, 0xe2, 0x1b, 0xa0, 0x28, 0x78, 0x27, 0x5e, 0x75, 0x06, 0x29, 0xbc, 0xd4, - 0x41, 0x2f, 0x40, 0xbf, 0x6c, 0x51, 0xe8, 0x19, 0x57, 0xe7, 0xde, 0xa4, 0x89, 0x2c, 0x61, 0x4f, 0xe8, 0xa0, 0x44, - 0xcb, 0x3f, 0xb8, 0xb0, 0x7a, 0x45, 0x08, 0x8e, 0x3d, 0x1f, 0xfe, 0xff, 0x69, 0x40, 0xfa, 0xf0, 0xa8, 0x87, 0x14, - 0x92, 0x08, 0x9f, 0xb0, 0xe5, 0x80, 0xae, 0x3b, 0x20, 0x29, 0x80, 0x77, 0x95, 0x31, 0x2d, 0x8f, 0x0b, 0xe2, 0xee, - 0x64, 0x4d, 0xcd, 0xd8, 0x2f, 0x13, 0xd0, 0xa9, 0xe0, 0xb8, 0x7a, 0xd7, 0x84, 0x35, 0xef, 0x6d, 0xa4, 0xe8, 0x58, - 0x60, 0x96, 0x40, 0x22, 0x44, 0x7a, 0x7f, 0x16, 0xe7, 0x42, 0xcc, 0xeb, 0x24, 0xb3, 0xdf, 0x72, 0x6a, 0x15, 0xa3, - 0x09, 0x14, 0x8e, 0x63, 0x59, 0xde, 0x93, 0x94, 0xe4, 0x09, 0x8f, 0x11, 0x8e, 0x57, 0x58, 0x47, 0xc1, 0x34, 0xa9, - 0x29, 0x29, 0x71, 0xf8, 0x5f, 0xa6, 0x34, 0x31, 0xd8, 0x95, 0xe8, 0x50, 0x11, 0x20, 0xa5, 0x59, 0x6a, 0x31, 0xf8, - 0x3c, 0x22, 0x1e, 0x0b, 0x80, 0x44, 0x44, 0xa2, 0xf0, 0x2f, 0x5d, 0xc9, 0xcf, 0x3c, 0x85, 0x88, 0xca, 0x4c, 0x83, - 0xce, 0xa2, 0xf7, 0xd5, 0x51, 0x4f, 0xd2, 0x6f, 0x74, 0x18, 0xd5, 0x2c, 0xff, 0x52, 0xf8, 0x90, 0xb8, 0xe1, 0xfe, - 0x59, 0x40, 0xa4, 0x7a, 0x93, 0x53, 0x2a, 0xed, 0x2c, 0xbd, 0xfc, 0xed, 0x0b, 0x14, 0x1b, 0x15, 0xc3, 0xf5, 0x63, - 0x7d, 0xb4, 0x21, 0xea, 0x9c, 0x1b, 0xe2, 0x80, 0x27, 0xac, 0x66, 0x4e, 0xe7, 0x8a, 0xbe, 0xb8, 0x4c, 0x1e, 0x13, - 0x53, 0x73, 0x9a, 0xde, 0xea, 0xe9, 0xb3, 0x48, 0x0e, 0x53, 0x67, 0x2b, 0x30, 0x05, 0x94, 0x61, 0xc5, 0x18, 0x59, - 0x0e, 0x24, 0xb1, 0x58, 0x72, 0xb9, 0x00, 0xa0, 0x45, 0xd6, 0x95, 0x63, 0x86, 0x42, 0xe5, 0x34, 0x32, 0x87, 0x83, - 0x8a, 0x63, 0xa4, 0x5d, 0xa9, 0x3e, 0x33, 0x84, 0x34, 0xea, 0xae, 0x01, 0x46, 0x14, 0x72, 0x96, 0xed, 0xbb, 0x28, - 0xe6, 0x22, 0x3c, 0x11, 0x06, 0xc8, 0xf3, 0x87, 0xd9, 0x66, 0xdd, 0x41, 0xe3, 0xc5, 0xc1, 0x78, 0x41, 0x65, 0xc3, - 0x48, 0xb2, 0x2c, 0x71, 0x50, 0x82, 0xc0, 0x29, 0x02, 0x8d, 0x7d, 0xfa, 0xd6, 0xa9, 0xfc, 0xfd, 0x32, 0x13, 0x89, - 0x87, 0x32, 0x8a, 0x11, 0x8f, 0x2f, 0xaa, 0xac, 0xab, 0x5b, 0x0e, 0x31, 0x7f, 0x78, 0xdb, 0xd8, 0x7e, 0xd3, 0x95, - 0x46, 0xcf, 0x0f, 0x9d, 0x15, 0x92, 0x66, 0x1c, 0xcd, 0xe9, 0xf4, 0x27, 0x71, 0x55, 0x53, 0x6c, 0x04, 0x14, 0x81, - 0xb0, 0xc7, 0x9b, 0x77, 0x4a, 0xa3, 0xbd, 0x13, 0xb0, 0x64, 0x1d, 0x83, 0x3d, 0xa9, 0xf6, 0x98, 0x90, 0xb4, 0xbc, - 0xff, 0x08, 0xcc, 0x95, 0x0a, 0x92, 0x4f, 0xc1, 0x87, 0x23, 0x94, 0x16, 0x14, 0xa2, 0x83, 0x4f, 0xba, 0x0d, 0x99, - 0x26, 0x60, 0xa2, 0x27, 0x41, 0x9e, 0x6d, 0xde, 0xb8, 0xa8, 0x42, 0x08, 0xe0, 0x81, 0xc9, 0xa6, 0x6f, 0xb2, 0xa4, - 0x55, 0xf6, 0xec, 0x3f, 0x87, 0x51, 0x96, 0xe5, 0x12, 0x9a, 0x04, 0xe9, 0x3d, 0x23, 0x72, 0xdb, 0x16, 0x9c, 0x9f, - 0xc5, 0x0a, 0xc9, 0xac, 0x2d, 0x0d, 0x69, 0x39, 0x84, 0x31, 0x28, 0x87, 0x8e, 0x08, 0xbe, 0x0c, 0x19, 0x56, 0x13, - 0x92, 0xe1, 0x5b, 0xfc, 0x07, 0x87, 0x4c, 0x52, 0x72, 0xa4, 0xc9, 0x7e, 0x2f, 0x06, 0x93, 0x5d, 0xe9, 0xa2, 0x02, - 0x1e, 0x66, 0xd3, 0x41, 0x0c, 0xc9, 0x56, 0xef, 0x29, 0xcd, 0x52, 0xcb, 0x11, 0xdc, 0x9d, 0x07, 0x52, 0xb0, 0x0d, - 0xaa, 0x9e, 0x47, 0x67, 0x1c, 0x2d, 0x00, 0xca, 0x5c, 0x92, 0xdc, 0x27, 0xc5, 0x20, 0x9b, 0x48, 0xa1, 0x80, 0x3d, - 0x65, 0x34, 0x86, 0x25, 0xb4, 0xfd, 0x71, 0x84, 0xc1, 0xd2, 0x90, 0x48, 0x91, 0x3e, 0x75, 0x62, 0xa7, 0x14, 0x8f, - 0x50, 0xf9, 0xd8, 0xba, 0x77, 0x50, 0x90, 0x40, 0x75, 0x92, 0x27, 0x08, 0xda, 0x73, 0xa0, 0x77, 0x4c, 0xc0, 0x7c, - 0x24, 0x19, 0xf1, 0xe3, 0x78, 0xbb, 0x62, 0x61, 0xf7, 0x21, 0xc5, 0x9d, 0x99, 0xdd, 0xfc, 0xc5, 0x7c, 0x8e, 0x34, - 0x67, 0x86, 0x4e, 0xea, 0x14, 0x92, 0xd9, 0x38, 0x27, 0xfa, 0x0b, 0xd2, 0xbc, 0x77, 0x11, 0x1d, 0xf1, 0x18, 0x7e, - 0x9f, 0x08, 0xae, 0x8f, 0xe7, 0x30, 0x82, 0xaf, 0xba, 0x28, 0x76, 0xb3, 0xde, 0x8a, 0x14, 0x5a, 0x3b, 0x19, 0xe2, - 0x82, 0xed, 0x3e, 0x18, 0x28, 0xa5, 0x24, 0xa2, 0xe9, 0xf7, 0x4a, 0x43, 0xc6, 0xa6, 0x41, 0x32, 0x63, 0x2b, 0x05, - 0x7a, 0x56, 0x8b, 0x38, 0x95, 0xd8, 0x91, 0x12, 0x74, 0x56, 0x38, 0x67, 0xa8, 0x01, 0x18, 0xed, 0xbc, 0xce, 0x1a, - 0x2c, 0x1d, 0x0c, 0x27, 0xae, 0xa1, 0x64, 0x8b, 0x3c, 0xc6, 0x87, 0x6e, 0xf6, 0x9e, 0xe5, 0x35, 0x40, 0xc1, 0x8f, - 0x8b, 0x20, 0xca, 0x03, 0xd4, 0x8c, 0xe0, 0xd8, 0x34, 0xab, 0x9e, 0xa4, 0x0d, 0xe7, 0x26, 0xbd, 0x19, 0x41, 0x5c, - 0xf6, 0x89, 0x8a, 0xc6, 0xff, 0x7e, 0x1c, 0x99, 0x7e, 0xb5, 0xea, 0x81, 0x94, 0x73, 0x16, 0x4a, 0xe3, 0x1b, 0x34, - 0xe2, 0x91, 0x07, 0xf6, 0xbb, 0xc6, 0x36, 0x4c, 0xa7, 0xa4, 0xa5, 0xc2, 0x7c, 0x55, 0x0d, 0xec, 0x80, 0x70, 0xd4, - 0xb2, 0x74, 0xac, 0x5f, 0x1e, 0x54, 0xf4, 0x7a, 0x9e, 0x7f, 0xb5, 0x7c, 0x6f, 0xd3, 0x02, 0x64, 0x67, 0x0c, 0x07, - 0x33, 0x26, 0x8d, 0x0a, 0xa8, 0x05, 0x64, 0xca, 0x3a, 0xa4, 0xe2, 0x69, 0x52, 0xc2, 0x91, 0x0d, 0x38, 0x1a, 0xb7, - 0x8d, 0xf4, 0x92, 0xf5, 0xd0, 0x01, 0xca, 0xac, 0xc3, 0x17, 0xb7, 0xad, 0xc7, 0x48, 0x35, 0xe0, 0x35, 0x00, 0x9c, - 0x14, 0xa9, 0x90, 0x12, 0x15, 0x52, 0x0e, 0x55, 0x4c, 0x07, 0x9d, 0x72, 0x4d, 0x9d, 0x95, 0x66, 0xe6, 0x5d, 0xdc, - 0xc1, 0x9f, 0x1e, 0x21, 0x84, 0x75, 0x19, 0x08, 0x16, 0xc5, 0x6f, 0x40, 0x10, 0x31, 0x59, 0x33, 0x7d, 0x23, 0x03, - 0x73, 0xbc, 0xa4, 0xe9, 0x57, 0x71, 0xc0, 0x2c, 0x96, 0x5e, 0x25, 0x26, 0xf1, 0x91, 0x51, 0x48, 0xdf, 0x58, 0x02, - 0xa2, 0x6e, 0x66, 0x79, 0x7e, 0xb5, 0xde, 0x33, 0x2e, 0x29, 0xf8, 0x98, 0x6f, 0xf7, 0xa3, 0xc2, 0xe1, 0xdb, 0x23, - 0x87, 0x03, 0x67, 0x90, 0x8a, 0x34, 0x66, 0x90, 0x53, 0xf0, 0xa2, 0x57, 0x98, 0xf1, 0xc7, 0x5c, 0xc9, 0x12, 0x51, - 0x78, 0x1b, 0xf0, 0xf7, 0x2c, 0x45, 0xe8, 0xf6, 0x80, 0xf0, 0x5d, 0xc8, 0xf8, 0xac, 0x84, 0x49, 0xfe, 0x08, 0x63, - 0x24, 0xb9, 0x7c, 0x1f, 0x6e, 0x2a, 0x93, 0xf1, 0xcd, 0x6f, 0x59, 0x14, 0xa8, 0x2c, 0x83, 0x69, 0x6a, 0x50, 0x52, - 0xe7, 0x00, 0x21, 0x8f, 0x9c, 0x57, 0xf5, 0xcc, 0xd4, 0x49, 0x23, 0xd2, 0x46, 0x1f, 0x64, 0x8a, 0x40, 0x74, 0x7a, - 0x10, 0x46, 0x1e, 0x08, 0x01, 0xf0, 0x1c, 0x02, 0x40, 0x4b, 0xe0, 0x0c, 0xe0, 0x98, 0xee, 0xc9, 0xa0, 0x11, 0x1a, - 0xf5, 0x9f, 0xed, 0x49, 0x54, 0xa4, 0x72, 0x1b, 0xdb, 0x0f, 0x7b, 0x8b, 0x44, 0xa3, 0x82, 0x1a, 0x8a, 0x29, 0xe2, - 0x6b, 0xfd, 0x4d, 0xe2, 0xae, 0xf7, 0xc9, 0x33, 0x8c, 0x2d, 0x4d, 0x23, 0x4d, 0x0b, 0x54, 0x3c, 0x75, 0x5f, 0xb0, - 0xb5, 0x27, 0x08, 0x69, 0x12, 0x8a, 0x32, 0x8c, 0xea, 0x9a, 0x2a, 0xc5, 0x2d, 0x1c, 0xc1, 0x51, 0xfa, 0xee, 0x44, - 0xdc, 0xfb, 0xc8, 0xf1, 0xe9, 0xcf, 0x08, 0x6a, 0x7d, 0x7e, 0xf4, 0xb6, 0xc9, 0xe9, 0x97, 0x61, 0x85, 0xbe, 0x12, - 0x11, 0xd1, 0x10, 0x06, 0x76, 0x38, 0xd0, 0x93, 0x86, 0x17, 0x63, 0x17, 0x77, 0x34, 0xd1, 0x83, 0x33, 0xf6, 0x54, - 0x86, 0xf4, 0xed, 0x99, 0xc8, 0xda, 0x16, 0xf5, 0xfa, 0xef, 0xe2, 0x4b, 0x78, 0x72, 0x3e, 0x1e, 0x93, 0x3a, 0x45, - 0x05, 0x9c, 0xa8, 0x55, 0xbd, 0x95, 0xc7, 0x60, 0x66, 0x1e, 0x7d, 0x2b, 0x26, 0x63, 0x9c, 0x9a, 0x91, 0x91, 0xb5, - 0x0b, 0x41, 0x5e, 0xec, 0x20, 0xbf, 0x53, 0x48, 0x7e, 0x74, 0x27, 0x03, 0x1a, 0x51, 0x10, 0x54, 0x8e, 0x1f, 0x28, - 0x94, 0x81, 0xb1, 0x7c, 0x6e, 0x6b, 0x3f, 0x21, 0xf6, 0x8c, 0x62, 0x19, 0xcf, 0x36, 0xe3, 0x39, 0x2f, 0x7f, 0xb1, - 0xa7, 0x41, 0x96, 0xd8, 0x7c, 0x26, 0x9e, 0x8e, 0x78, 0x68, 0x9b, 0x79, 0x41, 0xed, 0x04, 0xf0, 0x5e, 0x6a, 0x97, - 0xe6, 0x7a, 0xaa, 0xf5, 0x87, 0x91, 0xf6, 0x3e, 0x08, 0x52, 0x3e, 0x4f, 0xc2, 0xca, 0x43, 0x14, 0x28, 0xaa, 0x6d, - 0xc1, 0xf3, 0x93, 0x3d, 0xa7, 0x3c, 0x8a, 0x25, 0xb2, 0x59, 0x14, 0xd9, 0xd7, 0xac, 0xab, 0x3c, 0xa5, 0xfe, 0xc9, - 0xa8, 0x0f, 0xfe, 0x4d, 0x11, 0x1f, 0x71, 0xc3, 0x7f, 0x17, 0xab, 0xaa, 0xdf, 0xb4, 0x37, 0x5a, 0x28, 0x7d, 0x01, - 0x2f, 0x2e, 0x8a, 0xcb, 0xad, 0x5f, 0x3e, 0xf6, 0x52, 0x84, 0x26, 0x12, 0xe6, 0x16, 0x71, 0x6a, 0x3b, 0x28, 0x26, - 0xdf, 0xcf, 0x05, 0x74, 0x8a, 0x59, 0x71, 0xeb, 0x17, 0x35, 0x16, 0x1c, 0xde, 0x39, 0xe0, 0xa2, 0xf1, 0x64, 0x36, - 0x17, 0x42, 0xd1, 0x73, 0x50, 0xf5, 0x7b, 0xfb, 0x41, 0x32, 0x1b, 0xae, 0xdf, 0x38, 0x85, 0x13, 0x8b, 0x85, 0x9e, - 0x39, 0x87, 0xbf, 0x57, 0x9b, 0x1b, 0x2f, 0x65, 0xbd, 0xbe, 0x35, 0x7b, 0x7f, 0x8f, 0x9e, 0x53, 0xc6, 0xb6, 0xff, - 0x31, 0x44, 0xc2, 0x13, 0xbf, 0x5e, 0x84, 0x22, 0x5c, 0x13, 0x02, 0x1e, 0x54, 0xd2, 0xcd, 0x62, 0x55, 0x74, 0x9e, - 0xd3, 0x83, 0x77, 0x6b, 0xe1, 0xac, 0x30, 0x9c, 0xc6, 0x8e, 0xd3, 0x2e, 0xaf, 0xe8, 0xa9, 0x97, 0xb6, 0xfa, 0xa9, - 0x8b, 0xc3, 0x5b, 0x24, 0xae, 0x68, 0x39, 0x3e, 0x23, 0xd7, 0x7d, 0xd1, 0x54, 0xfe, 0x49, 0xd0, 0xf3, 0x32, 0xf8, - 0xbc, 0xc4, 0x55, 0x64, 0x6f, 0xbf, 0x6f, 0x57, 0x66, 0xb8, 0x5d, 0x79, 0xe7, 0x66, 0x77, 0xbf, 0xa3, 0xaa, 0xc6, - 0x9d, 0xe9, 0x6c, 0xe4, 0x1f, 0x96, 0x91, 0xd6, 0xd3, 0x2e, 0xdf, 0xfe, 0xaf, 0xd1, 0xef, 0x1f, 0xb7, 0x9e, 0xff, - 0xd2, 0x94, 0x32, 0x9f, 0xea, 0xb6, 0xe3, 0xa9, 0xe5, 0x72, 0x37, 0x56, 0xaf, 0xaf, 0x3f, 0xf9, 0x8c, 0x28, 0x3f, - 0x61, 0x12, 0x6c, 0x47, 0xeb, 0x32, 0xca, 0x95, 0x70, 0x8d, 0x66, 0xf6, 0xab, 0xed, 0x71, 0xfd, 0xb0, 0x9c, 0x66, - 0xf1, 0xea, 0xa3, 0xe4, 0x71, 0xb3, 0xb5, 0xbb, 0x5d, 0xcd, 0x4b, 0x9b, 0x57, 0x0b, 0x4a, 0x63, 0xc2, 0xd7, 0xf6, - 0x23, 0x5b, 0x30, 0xde, 0x04, 0x24, 0x7f, 0x20, 0x6a, 0xbe, 0xab, 0x37, 0x7d, 0x5b, 0x4d, 0xa9, 0x98, 0xe6, 0x34, - 0x11, 0x4d, 0x33, 0xaa, 0x21, 0x4e, 0x8a, 0x30, 0x0e, 0xb6, 0x33, 0xcf, 0x4f, 0x18, 0xe0, 0x9c, 0xca, 0x5d, 0x4c, - 0xfc, 0xcb, 0x4f, 0x53, 0x6d, 0xee, 0x34, 0xcb, 0x11, 0x4c, 0x8e, 0x62, 0x77, 0x72, 0xd8, 0x6e, 0xa0, 0x59, 0xde, - 0xe2, 0x0d, 0x55, 0xa5, 0x94, 0xe7, 0x62, 0x26, 0x81, 0xa2, 0x52, 0x33, 0xe8, 0x70, 0xa0, 0x9b, 0xb9, 0xd9, 0x4f, - 0x87, 0xff, 0x1e, 0xbb, 0x88, 0xe1, 0x14, 0xfe, 0xb9, 0x18, 0x84, 0x50, 0xd8, 0xb7, 0x90, 0x6a, 0xc2, 0x91, 0xb2, - 0xe1, 0x3b, 0x56, 0xe2, 0xef, 0x38, 0x33, 0x61, 0x34, 0x13, 0x61, 0x45, 0xd3, 0x7c, 0x06, 0xdc, 0xe3, 0x82, 0xb1, - 0x27, 0xc2, 0x6f, 0x6d, 0xb7, 0xec, 0xd4, 0xf5, 0xd9, 0xd0, 0x39, 0xc9, 0x02, 0x8e, 0x1b, 0x02, 0x07, 0xd0, 0xb8, - 0x33, 0x2f, 0xb2, 0xb5, 0xae, 0x57, 0x1f, 0x62, 0x2e, 0xba, 0x15, 0x69, 0x32, 0x7e, 0xab, 0xe8, 0xd2, 0xdd, 0x05, - 0x20, 0x69, 0xf5, 0xee, 0xc7, 0x5e, 0x3f, 0x38, 0x72, 0xf3, 0x56, 0xef, 0x65, 0x18, 0x1e, 0x6b, 0xf2, 0x91, 0x86, - 0xed, 0xe4, 0x86, 0x97, 0x2b, 0xd5, 0x44, 0x9b, 0x71, 0x5b, 0x5e, 0xb1, 0xd6, 0x1b, 0xd2, 0x95, 0xdd, 0x79, 0xa8, - 0x72, 0x1b, 0x2f, 0x5b, 0x84, 0xc1, 0x5c, 0x9c, 0xcd, 0xe4, 0x17, 0x48, 0xf4, 0xf5, 0xcd, 0x5c, 0xbe, 0x03, 0xce, - 0x1e, 0xa1, 0x4e, 0xf8, 0xeb, 0x55, 0x4f, 0xa6, 0x31, 0x89, 0x13, 0x9b, 0xf0, 0x70, 0xba, 0x52, 0x2c, 0x14, 0x02, - 0xef, 0xa6, 0x87, 0x20, 0xd1, 0xcf, 0x98, 0x52, 0x99, 0x74, 0x0f, 0x4d, 0x1a, 0x63, 0x5c, 0x9a, 0x65, 0xa3, 0x2e, - 0x2d, 0xe2, 0xa7, 0xcd, 0x35, 0xd3, 0x9a, 0x2d, 0x8d, 0x8a, 0x2a, 0xdb, 0xdc, 0xaf, 0x6a, 0x6f, 0xab, 0x7a, 0xf7, - 0x10, 0x64, 0xb0, 0x73, 0xe5, 0xf9, 0x45, 0x59, 0x69, 0xc6, 0x60, 0xf0, 0x94, 0x6f, 0xc4, 0x02, 0x19, 0xb7, 0x79, - 0x77, 0x98, 0xf8, 0xca, 0xa4, 0xbf, 0x76, 0x0d, 0x34, 0xe6, 0xee, 0x4f, 0xd6, 0xe9, 0xca, 0x1a, 0x23, 0x6e, 0x5b, - 0x2d, 0xe1, 0x02, 0x27, 0x9e, 0x42, 0xb9, 0xe9, 0xf6, 0x9d, 0x2f, 0x0b, 0x93, 0x9a, 0xbc, 0xe0, 0xf5, 0x1b, 0x10, - 0x05, 0xb3, 0x00, 0x01, 0x11, 0xf7, 0xa2, 0xd8, 0x74, 0xc4, 0x22, 0x06, 0x09, 0xf4, 0x06, 0x42, 0xe0, 0x0c, 0x7f, - 0x50, 0xd0, 0xb5, 0x1d, 0x18, 0x01, 0x00, 0xe4, 0x66, 0x43, 0xea, 0xa5, 0x52, 0xb9, 0x27, 0xa2, 0x6a, 0xa8, 0x56, - 0x97, 0x74, 0xd7, 0x5c, 0x97, 0xc0, 0x79, 0x9d, 0xb5, 0xf9, 0x53, 0x09, 0xcb, 0xba, 0x21, 0xce, 0x65, 0x85, 0x02, - 0x13, 0x15, 0xcd, 0x99, 0xa7, 0x82, 0xc0, 0x5a, 0x95, 0xac, 0xf1, 0x2c, 0x85, 0xdd, 0xfd, 0x59, 0xcd, 0xdd, 0x80, - 0xd3, 0xd8, 0x41, 0x98, 0x19, 0xf0, 0xb6, 0x7d, 0xbc, 0x61, 0xec, 0xed, 0xca, 0x59, 0xf0, 0xc8, 0x24, 0x5f, 0x96, - 0xee, 0x7e, 0x82, 0x1b, 0x2b, 0xfd, 0x94, 0x3e, 0x87, 0xb0, 0x24, 0xfc, 0x77, 0x85, 0xe0, 0xba, 0x34, 0xbe, 0xab, - 0x9e, 0x0b, 0x22, 0x78, 0xba, 0x64, 0x6f, 0x13, 0x79, 0x5f, 0x91, 0x13, 0x49, 0xf7, 0xce, 0x1a, 0x1f, 0x89, 0xe5, - 0xe7, 0xda, 0xf8, 0xbb, 0xa7, 0xfa, 0xca, 0x2a, 0x27, 0x91, 0x8d, 0xcf, 0xe5, 0x80, 0x65, 0x9e, 0xf7, 0x29, 0xd4, - 0x58, 0xa0, 0xc7, 0x30, 0x7b, 0xdc, 0xb0, 0x88, 0x9f, 0xc1, 0x16, 0xee, 0x94, 0x9a, 0xc6, 0xb4, 0x92, 0xac, 0x52, - 0x04, 0xce, 0xa7, 0xe0, 0x72, 0xce, 0xd3, 0xed, 0x86, 0xc4, 0x2f, 0xed, 0xa3, 0xb8, 0x0e, 0xfa, 0x69, 0x29, 0x36, - 0x7f, 0xfa, 0x8a, 0x16, 0x92, 0xd8, 0x82, 0xce, 0xcb, 0x16, 0x22, 0x60, 0x2f, 0x3e, 0xa5, 0xec, 0xb6, 0xff, 0x28, - 0xd5, 0x0c, 0x78, 0x95, 0x0f, 0x94, 0xa1, 0x18, 0x33, 0xa4, 0xb4, 0xe2, 0xaa, 0x13, 0x49, 0xd0, 0xdb, 0x3c, 0x15, - 0x02, 0xa7, 0xb0, 0x0f, 0xa5, 0x64, 0xa2, 0x1f, 0xb0, 0xcc, 0x72, 0x97, 0xbe, 0xe4, 0x9a, 0xf5, 0x76, 0xd7, 0x28, - 0x09, 0xcc, 0x04, 0xf9, 0x59, 0xf0, 0x89, 0xdb, 0x9e, 0xdc, 0x2d, 0xb9, 0x22, 0x30, 0x7f, 0x92, 0x89, 0xe0, 0xd8, - 0x40, 0x3e, 0x93, 0x8b, 0x27, 0x91, 0xa8, 0xa4, 0xd0, 0x2e, 0x39, 0x3a, 0x7a, 0xd7, 0x49, 0x6a, 0x15, 0x6b, 0x1d, - 0x0a, 0x1d, 0xb7, 0x71, 0x53, 0x59, 0xc7, 0x73, 0x12, 0xa3, 0xf6, 0xe8, 0x2e, 0x49, 0xdb, 0xec, 0xee, 0x54, 0x1a, - 0xa1, 0x92, 0xea, 0x0a, 0x19, 0x4b, 0x33, 0x92, 0x38, 0x3f, 0xb1, 0x45, 0x88, 0x18, 0x90, 0x58, 0x3a, 0xcb, 0x21, - 0x56, 0xdd, 0xa7, 0x0d, 0xcb, 0x71, 0xe8, 0x94, 0x25, 0x01, 0x45, 0xb3, 0x34, 0x46, 0x07, 0x03, 0xc7, 0xd1, 0x1c, - 0x55, 0x0a, 0x8c, 0x99, 0x97, 0x39, 0xec, 0x7c, 0x95, 0xa1, 0x73, 0x69, 0xa4, 0xd9, 0xf0, 0x75, 0x31, 0xb5, 0x47, - 0xa9, 0xce, 0xb5, 0x11, 0xc9, 0xc8, 0x41, 0x7b, 0x2e, 0x53, 0x11, 0x56, 0x71, 0x51, 0xee, 0xc6, 0x92, 0x59, 0x17, - 0x62, 0x9c, 0x8c, 0xf6, 0x6a, 0xb2, 0x68, 0x55, 0x40, 0x39, 0xbe, 0x64, 0xda, 0x03, 0x2e, 0x59, 0xdb, 0x7e, 0x29, - 0x27, 0x75, 0x81, 0xe6, 0x7c, 0xac, 0x2b, 0xfc, 0x8d, 0x2c, 0x80, 0x31, 0x3b, 0xf2, 0xa5, 0xdd, 0x6e, 0xfe, 0x25, - 0x27, 0xdb, 0x5f, 0xc6, 0x39, 0xf3, 0x98, 0x2b, 0x61, 0xec, 0x5a, 0x4d, 0xf4, 0x64, 0x86, 0x1a, 0x9f, 0x13, 0x70, - 0xc9, 0xeb, 0x27, 0x03, 0xec, 0x8c, 0xc7, 0xb9, 0xa4, 0x9d, 0xd2, 0xa5, 0xd2, 0x52, 0x9c, 0xc6, 0xdc, 0x64, 0x2d, - 0xab, 0xdd, 0x3f, 0x0f, 0xb1, 0x5c, 0xc1, 0xbe, 0xf5, 0x91, 0x75, 0x1f, 0xdf, 0x97, 0x29, 0x6f, 0xbd, 0x9a, 0xd1, - 0xaf, 0xb6, 0xc2, 0x84, 0xbd, 0xa3, 0x6b, 0x0c, 0x93, 0x1d, 0x6b, 0x15, 0xa4, 0x3d, 0xb2, 0xa3, 0x45, 0x32, 0x1e, - 0x4e, 0x68, 0x55, 0x7b, 0x21, 0x43, 0x1e, 0x7e, 0x6e, 0x34, 0x12, 0x8b, 0xa4, 0x58, 0x40, 0xe7, 0x7b, 0x54, 0x57, - 0x4b, 0x8a, 0xe9, 0x49, 0x6b, 0x32, 0x78, 0xd4, 0x99, 0x53, 0xe7, 0xca, 0x2f, 0x2c, 0xf7, 0x55, 0x53, 0x06, 0x03, - 0x71, 0xfd, 0x09, 0xea, 0xae, 0xec, 0x71, 0x2e, 0x31, 0x81, 0x9a, 0xb2, 0x68, 0xe2, 0x48, 0x32, 0xf9, 0xe5, 0xcb, - 0x4c, 0x9b, 0xec, 0xc3, 0x55, 0x24, 0x82, 0x17, 0x23, 0xb1, 0x85, 0xdf, 0xe9, 0x02, 0xcb, 0xa2, 0x3e, 0x6c, 0x1a, - 0x73, 0xe3, 0x28, 0x19, 0xae, 0x50, 0x04, 0x8e, 0x5a, 0x60, 0xa0, 0x24, 0x27, 0x6a, 0xb2, 0x66, 0x76, 0x9e, 0x0e, - 0x5e, 0x5c, 0x68, 0x1d, 0xdf, 0x11, 0x3a, 0xa4, 0x33, 0x94, 0x57, 0xf0, 0xcd, 0xbe, 0xcb, 0x5c, 0x60, 0xaa, 0x25, - 0x7d, 0x8c, 0x5e, 0x33, 0x7d, 0xec, 0x1a, 0xbc, 0x10, 0x3d, 0xb7, 0x96, 0x67, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, - 0x1e, 0x87, 0x77, 0x07, 0x59, 0xb1, 0x88, 0x6c, 0x77, 0x2e, 0x2e, 0x5b, 0x14, 0xe8, 0x14, 0x27, 0xeb, 0x36, 0xa8, - 0xd7, 0xa0, 0x29, 0xe7, 0x58, 0xa5, 0x31, 0x3b, 0x30, 0x43, 0x90, 0x0b, 0x1d, 0xb6, 0x44, 0xa9, 0xf4, 0x23, 0x4e, - 0x04, 0x1b, 0xac, 0xee, 0xcc, 0x66, 0x59, 0xb3, 0xc3, 0x9e, 0x93, 0xfa, 0x9f, 0x78, 0xd7, 0xb6, 0x9c, 0xd7, 0xc2, - 0x48, 0x13, 0xb2, 0xb1, 0x40, 0x7a, 0x94, 0xbf, 0xf9, 0xdb, 0x87, 0x7c, 0x61, 0xfa, 0xf5, 0xb0, 0x2a, 0x64, 0xc6, - 0x4e, 0xe0, 0x00, 0x32, 0x41, 0x06, 0x1f, 0x29, 0x3d, 0x93, 0x82, 0x91, 0xd6, 0xf7, 0xc2, 0x0c, 0xb6, 0x63, 0xb2, - 0x10, 0x1d, 0xab, 0xdd, 0x0c, 0x20, 0x87, 0x36, 0xb6, 0x7c, 0x0d, 0xa5, 0x55, 0x92, 0x96, 0x72, 0x71, 0x40, 0x61, - 0xd5, 0x5b, 0x71, 0xd3, 0x4b, 0xfb, 0x08, 0x4d, 0xbf, 0x4b, 0x06, 0xca, 0x94, 0x80, 0xf6, 0x33, 0xf3, 0x4a, 0x07, - 0x11, 0x1e, 0xa6, 0x34, 0x01, 0xd8, 0x10, 0x2b, 0x5b, 0xec, 0xad, 0xc5, 0xc2, 0x7b, 0xd2, 0x02, 0xd6, 0x34, 0x73, - 0xd8, 0x09, 0x58, 0x5f, 0xee, 0x26, 0x62, 0x53, 0xfe, 0x6c, 0x25, 0xd6, 0x1c, 0x71, 0x11, 0x1f, 0xbd, 0x5f, 0xd7, - 0xa7, 0x29, 0x16, 0xa9, 0x73, 0x6f, 0x3d, 0xc9, 0x00, 0xff, 0xbc, 0x78, 0x0e, 0x9c, 0xde, 0x25, 0xdf, 0xf7, 0xcf, - 0xd6, 0x92, 0xc5, 0xd5, 0xc0, 0xf1, 0x55, 0x2b, 0x93, 0xd3, 0x15, 0x2d, 0x05, 0x65, 0xb0, 0xf9, 0xbe, 0x77, 0x49, - 0x21, 0x6e, 0xa0, 0x3c, 0x9a, 0xf9, 0x08, 0xe3, 0xca, 0x2b, 0x7c, 0x4a, 0x8d, 0x78, 0x68, 0x26, 0x2c, 0x10, 0x49, - 0xad, 0x44, 0xc5, 0x82, 0x54, 0x55, 0x4f, 0x5f, 0x90, 0xa1, 0xe7, 0x02, 0x3e, 0xeb, 0x53, 0x3c, 0x38, 0x5b, 0x3b, - 0x0e, 0xa2, 0x68, 0x2b, 0x7e, 0x56, 0xa8, 0x10, 0xfc, 0x57, 0x81, 0x1a, 0x29, 0x32, 0x02, 0xcc, 0xf5, 0x84, 0xba, - 0x3f, 0x90, 0x27, 0x3c, 0x3f, 0xa5, 0x82, 0xa5, 0x42, 0x4e, 0xea, 0x94, 0x88, 0x28, 0xff, 0xca, 0xcb, 0x26, 0x41, - 0xb3, 0x9c, 0xd2, 0x98, 0x7c, 0xc4, 0x92, 0x08, 0xae, 0x66, 0x4d, 0x3e, 0xfd, 0x88, 0x52, 0xdd, 0xcb, 0x0c, 0xd7, - 0xa6, 0x04, 0x0d, 0x85, 0x6f, 0x3c, 0xe0, 0xe8, 0xd3, 0xed, 0x74, 0x42, 0x6e, 0x4b, 0x19, 0x9c, 0x7c, 0x44, 0x87, - 0xb9, 0xf5, 0xd5, 0x4c, 0xd0, 0xdc, 0x98, 0xb7, 0x0d, 0xc5, 0x2d, 0x21, 0xdb, 0xec, 0xd7, 0xbb, 0x35, 0xf9, 0x3a, - 0xfd, 0xe0, 0x92, 0xa6, 0x4c, 0xe8, 0x62, 0xe2, 0x17, 0x61, 0x86, 0x36, 0xdc, 0xf0, 0xe5, 0x8b, 0xed, 0xe5, 0x70, - 0x1c, 0x20, 0x73, 0x2c, 0xca, 0xef, 0xa8, 0xed, 0x19, 0x50, 0x50, 0x8e, 0xd1, 0x55, 0x6b, 0xc0, 0xd8, 0x8e, 0xad, - 0x75, 0x5f, 0x9e, 0x64, 0x0d, 0x50, 0x4f, 0xb5, 0x72, 0x8a, 0xc1, 0xd8, 0x87, 0x96, 0x6e, 0x03, 0x6c, 0x90, 0x3a, - 0x2c, 0x1c, 0x4c, 0xeb, 0x1f, 0x2d, 0x5e, 0x68, 0x01, 0x22, 0x6f, 0x92, 0xa5, 0x35, 0xde, 0x13, 0x7f, 0x07, 0xd7, - 0x14, 0x7c, 0x8f, 0xe3, 0x07, 0x89, 0xf7, 0x3c, 0xbb, 0xac, 0x28, 0x2a, 0x61, 0x9e, 0x0b, 0x6f, 0x88, 0xb0, 0x62, - 0x82, 0x98, 0x63, 0x1e, 0x72, 0x42, 0xf6, 0x85, 0x5b, 0xd6, 0xb6, 0x3a, 0x04, 0x3c, 0xbc, 0xef, 0xfb, 0xe9, 0x85, - 0x80, 0xa2, 0x2b, 0x3b, 0x77, 0x9c, 0x47, 0x33, 0x60, 0x35, 0x43, 0xbe, 0xc5, 0x76, 0x98, 0x8a, 0x32, 0x4a, 0x08, - 0xe2, 0x06, 0x2b, 0xb0, 0x30, 0xf4, 0xac, 0x71, 0xf5, 0x89, 0xd3, 0x7a, 0xca, 0x00, 0x80, 0x52, 0xda, 0xa1, 0x7b, - 0x86, 0x32, 0x61, 0xf4, 0xd2, 0x2a, 0x50, 0x6e, 0xb9, 0x3a, 0x78, 0xd9, 0xb9, 0xc7, 0x30, 0xb0, 0x33, 0x5b, 0xeb, - 0x4c, 0xe3, 0x40, 0x64, 0x19, 0x08, 0x10, 0x87, 0xba, 0x48, 0x95, 0x86, 0xa2, 0xeb, 0x00, 0xaf, 0x45, 0x7d, 0x92, - 0x61, 0x61, 0x21, 0xee, 0x56, 0xa2, 0x63, 0xc0, 0x34, 0x5e, 0xe3, 0xed, 0x42, 0x2a, 0x04, 0x5e, 0x09, 0x91, 0x07, - 0x12, 0xd9, 0x03, 0xed, 0xa0, 0x6c, 0x00, 0x24, 0xb9, 0x13, 0x5c, 0x29, 0x48, 0x6b, 0x09, 0xe5, 0x64, 0xff, 0x4f, - 0x54, 0x1a, 0x65, 0x02, 0xf2, 0x99, 0x6b, 0x89, 0x49, 0xe3, 0x25, 0x30, 0x17, 0x0e, 0x24, 0x1f, 0x66, 0xb0, 0x93, - 0x05, 0x8d, 0xc8, 0x94, 0xe9, 0xdc, 0x0a, 0xb6, 0xf1, 0xea, 0x4d, 0xd2, 0x48, 0x54, 0x98, 0xfe, 0xe6, 0x57, 0x97, - 0x4f, 0x5d, 0x18, 0x61, 0xf9, 0x5b, 0x2e, 0xfb, 0x1c, 0xf9, 0x4d, 0x18, 0x25, 0xed, 0x6c, 0xf8, 0x52, 0xc9, 0x74, - 0xdc, 0x9e, 0x9f, 0x69, 0x6d, 0xb4, 0x78, 0x0f, 0xf2, 0x05, 0xef, 0x41, 0x75, 0x47, 0x92, 0xec, 0x73, 0x5a, 0x93, - 0xd4, 0x35, 0xaa, 0xca, 0x70, 0x90, 0x68, 0x8c, 0x8b, 0xd4, 0x9a, 0x98, 0x53, 0xb3, 0x78, 0x1a, 0x40, 0x32, 0x8d, - 0xfd, 0x8c, 0x2a, 0x0f, 0x2c, 0x27, 0x36, 0x2f, 0xa6, 0x27, 0xd2, 0x68, 0xba, 0x20, 0x97, 0x9f, 0x52, 0xef, 0x66, - 0x4a, 0xd1, 0xb2, 0x58, 0x86, 0xc3, 0xd9, 0x41, 0x98, 0x23, 0x5d, 0xbe, 0x9a, 0xeb, 0xa3, 0x2f, 0x19, 0x26, 0xa5, - 0x4b, 0x57, 0xf2, 0x67, 0x94, 0x2c, 0x5f, 0x08, 0xab, 0x0f, 0xdb, 0x26, 0x08, 0x64, 0xd4, 0xa0, 0x1c, 0xe1, 0xd6, - 0xf2, 0x00, 0x1b, 0x1b, 0xf2, 0xe0, 0xec, 0xa6, 0x2a, 0x7b, 0x64, 0x9a, 0xb3, 0xa9, 0xa0, 0xf2, 0x46, 0xa3, 0x85, - 0x66, 0x26, 0x9b, 0xaf, 0x2e, 0xbe, 0x4a, 0x90, 0x1b, 0xa7, 0x83, 0xd5, 0x52, 0x7d, 0x68, 0x42, 0x56, 0x1f, 0xc8, - 0xcb, 0xa4, 0xa8, 0xaa, 0x85, 0x22, 0xed, 0x94, 0xfc, 0x34, 0x9a, 0xba, 0xeb, 0x4e, 0x72, 0x42, 0x65, 0x35, 0x89, - 0x8a, 0x02, 0x5b, 0x78, 0x59, 0x08, 0x15, 0x40, 0x71, 0xb7, 0xfb, 0xa1, 0x02, 0xe5, 0xcf, 0x45, 0x0e, 0xee, 0x78, - 0xaf, 0x0e, 0x4c, 0xcb, 0x00, 0x92, 0xfc, 0x4c, 0x26, 0xbd, 0x69, 0xdc, 0xbb, 0x87, 0xf2, 0xf0, 0x59, 0x54, 0x62, - 0xee, 0x43, 0x7e, 0x15, 0x03, 0x8d, 0x59, 0x02, 0xee, 0xb7, 0xcb, 0x5e, 0x7c, 0x94, 0x74, 0x82, 0xcc, 0x50, 0xb9, - 0x36, 0xde, 0x37, 0xf5, 0x48, 0x85, 0x91, 0x4b, 0x81, 0x7c, 0x70, 0xf7, 0xfb, 0x3d, 0x40, 0x31, 0xfe, 0xa2, 0x7d, - 0xf1, 0x3a, 0x29, 0x37, 0x31, 0x04, 0x24, 0x7a, 0x5d, 0x8e, 0x36, 0x08, 0xc8, 0xd1, 0x24, 0x41, 0x7e, 0x3c, 0x9e, - 0x49, 0xbe, 0xec, 0x38, 0xc5, 0x36, 0x95, 0x25, 0xa6, 0xdc, 0xfb, 0xe5, 0x2a, 0x0f, 0x84, 0xfd, 0x39, 0x91, 0x46, - 0xa4, 0x00, 0x30, 0xcc, 0x16, 0x78, 0x04, 0x0e, 0x34, 0xf1, 0xe2, 0x44, 0xad, 0xc2, 0x81, 0x86, 0xcd, 0xd9, 0x8b, - 0x98, 0x54, 0x64, 0xcc, 0x3e, 0x7e, 0x65, 0x5c, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xe7, 0xb2, 0x4a, 0x00, - 0xb5, 0x10, 0x0a, 0xa1, 0xc1, 0x20, 0xc1, 0xf8, 0x46, 0xef, 0x4f, 0xa8, 0x47, 0x14, 0x8a, 0x57, 0xab, 0xc5, 0x44, - 0xbb, 0x7c, 0xc7, 0x2d, 0x4c, 0x97, 0x8c, 0x41, 0x75, 0xaf, 0xd8, 0x23, 0x2f, 0x5e, 0xad, 0xca, 0xed, 0xd8, 0xa9, - 0xea, 0xd6, 0x18, 0xa1, 0xee, 0xe6, 0xb5, 0xce, 0x8d, 0x69, 0x22, 0xb8, 0x2c, 0x68, 0xb6, 0x38, 0xf4, 0x74, 0xfe, - 0xe1, 0xca, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0x27, 0x89, 0x60, 0xa8, 0x51, 0x5e, 0x08, 0x23, 0x52, 0xff, - 0xce, 0x90, 0x7b, 0x96, 0xa2, 0x53, 0x6d, 0x54, 0x97, 0x2d, 0x80, 0x2d, 0x7d, 0x0d, 0x23, 0x43, 0x21, 0x74, 0xc4, - 0x30, 0xd2, 0x2e, 0xf5, 0x51, 0x66, 0x48, 0x16, 0x5d, 0x57, 0x45, 0x90, 0x79, 0xd7, 0x4e, 0xde, 0x24, 0x89, 0x12, - 0x6a, 0xe8, 0x67, 0xe6, 0x93, 0x3a, 0x3b, 0x89, 0x53, 0x5a, 0x4b, 0xa1, 0xe6, 0xa4, 0xba, 0x8e, 0xe9, 0x3b, 0x55, - 0x29, 0xa1, 0x27, 0x8c, 0xdd, 0x7b, 0x33, 0x78, 0xd5, 0xc6, 0x18, 0x9f, 0x6b, 0xfe, 0x79, 0xd2, 0x0e, 0xe3, 0xd0, - 0x03, 0xd4, 0x02, 0x39, 0x85, 0xd6, 0x80, 0xcc, 0xff, 0xdd, 0xd9, 0xd9, 0x9e, 0x10, 0xb6, 0x4d, 0x82, 0x96, 0xcb, - 0xad, 0x5c, 0x4f, 0x42, 0x59, 0x37, 0x4f, 0x5a, 0xe7, 0x24, 0xb1, 0x38, 0xd8, 0x22, 0x39, 0x52, 0xe6, 0x13, 0x7c, - 0xce, 0x79, 0x42, 0xea, 0x07, 0x5b, 0xf8, 0xce, 0xc6, 0x77, 0x15, 0x21, 0xf7, 0x3d, 0x36, 0x2f, 0x63, 0x08, 0x11, - 0x89, 0xc9, 0xdc, 0xab, 0x23, 0x1f, 0x44, 0x91, 0x0b, 0x55, 0x7b, 0xc4, 0x3c, 0x21, 0xc0, 0x54, 0xb5, 0x1f, 0x9c, - 0xf6, 0xe5, 0x42, 0xf6, 0xb7, 0x58, 0x19, 0xa0, 0x9c, 0x33, 0xa9, 0x97, 0xff, 0xf9, 0x52, 0xeb, 0xfe, 0xf7, 0x0b, - 0xac, 0xcb, 0x6d, 0x3b, 0xdf, 0xe9, 0x01, 0x60, 0x00, 0x78, 0x5d, 0x50, 0xb5, 0xca, 0x8b, 0x5d, 0x7d, 0x51, 0x6f, - 0x9b, 0x20, 0x24, 0x01, 0xef, 0x2a, 0xe9, 0xff, 0x3e, 0xd3, 0x40, 0xd0, 0x7c, 0x93, 0xec, 0x8f, 0x6c, 0x10, 0x89, - 0x3c, 0xf5, 0xa4, 0xc5, 0xc7, 0x3b, 0xe1, 0xdd, 0xc1, 0xf8, 0x65, 0x6c, 0x5d, 0xd1, 0x3d, 0xf3, 0x07, 0x09, 0x2c, - 0x07, 0x6a, 0xb7, 0x1e, 0xbd, 0x71, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x33, 0x98, 0x12, 0x07, 0x81, 0xa2, 0x91, 0x16, - 0xe0, 0x49, 0x4c, 0x13, 0x4c, 0x0b, 0x08, 0xa9, 0x53, 0x40, 0x62, 0xbe, 0x1d, 0x96, 0x23, 0x78, 0x95, 0x22, 0x27, - 0x9e, 0x38, 0x37, 0xab, 0x0a, 0xe8, 0x3e, 0x44, 0xd5, 0xfc, 0x74, 0xf3, 0x06, 0x77, 0xe0, 0x26, 0xf6, 0x8d, 0xe3, - 0x0f, 0x71, 0xbf, 0xa1, 0x81, 0xe4, 0x1c, 0x12, 0x8b, 0xbc, 0xe6, 0x61, 0x3c, 0x93, 0x84, 0x3a, 0xdc, 0x42, 0x48, - 0xe7, 0x17, 0x30, 0x98, 0x17, 0x4c, 0x63, 0xab, 0xce, 0x22, 0x20, 0xe4, 0x3c, 0xbe, 0x1d, 0xc7, 0xb7, 0x1e, 0xac, - 0x07, 0xd1, 0x5e, 0x44, 0xfc, 0xad, 0x2d, 0x6a, 0x14, 0x2a, 0x0f, 0xa7, 0xd6, 0xd7, 0xd4, 0x70, 0x0c, 0x71, 0xf8, - 0x57, 0x90, 0x48, 0x09, 0x64, 0xb7, 0xed, 0x6b, 0x2e, 0xe8, 0xf4, 0x6e, 0xa7, 0x23, 0xb4, 0xd6, 0x0c, 0x2a, 0x73, - 0xd5, 0xac, 0xc1, 0xca, 0xb4, 0xd3, 0xff, 0x61, 0x73, 0x5b, 0x92, 0x80, 0x20, 0x5a, 0xe9, 0xf7, 0x55, 0x98, 0xb0, - 0xc4, 0x18, 0x03, 0x1e, 0x09, 0x32, 0xe7, 0x29, 0x44, 0x12, 0x0b, 0x30, 0x1c, 0xad, 0xd5, 0xc5, 0x7f, 0x56, 0xdc, - 0xfa, 0xd1, 0xe8, 0x4d, 0x9b, 0x64, 0xca, 0xcd, 0xaa, 0x05, 0xf0, 0xc7, 0x59, 0x65, 0xd9, 0xd6, 0x33, 0x40, 0xca, - 0x93, 0x2c, 0x09, 0x2e, 0xdd, 0x82, 0x93, 0xf2, 0x49, 0x4a, 0x9b, 0xe4, 0xca, 0xfd, 0xc2, 0x55, 0xf6, 0x3d, 0x53, - 0x04, 0x87, 0xf5, 0x4c, 0x73, 0x60, 0x01, 0x16, 0xcc, 0xa5, 0x74, 0xb1, 0xda, 0x19, 0x12, 0x09, 0x56, 0x92, 0x0f, - 0xcb, 0x0c, 0x49, 0x8f, 0x6f, 0xab, 0x8b, 0x84, 0x9c, 0xf1, 0xbc, 0xad, 0x01, 0x07, 0x78, 0x77, 0x2e, 0x46, 0x5a, - 0xef, 0xb0, 0x23, 0xef, 0x9d, 0x92, 0x52, 0x52, 0x35, 0x05, 0xe4, 0xd1, 0x86, 0x20, 0xed, 0x36, 0xc5, 0xa0, 0xbf, - 0x19, 0x2c, 0x8d, 0x7b, 0xcf, 0x25, 0x46, 0x0a, 0xa4, 0xda, 0x99, 0x3e, 0x70, 0xe1, 0x2f, 0xc8, 0xa9, 0xf9, 0xe0, - 0x9d, 0x6d, 0xd8, 0x4f, 0x4b, 0x0e, 0x08, 0xc5, 0xc5, 0x5d, 0x7f, 0xd4, 0x27, 0xb6, 0x58, 0x1c, 0x5c, 0xbe, 0x51, - 0xf6, 0xa8, 0x09, 0xec, 0xc1, 0x07, 0x5a, 0x46, 0x2a, 0x0d, 0x0a, 0x25, 0xc5, 0xbb, 0x73, 0x63, 0xda, 0x5b, 0x9b, - 0x5a, 0x56, 0x58, 0x55, 0x83, 0x55, 0xf5, 0xb1, 0xc4, 0xd2, 0xd2, 0xb6, 0xd8, 0x02, 0x73, 0xdd, 0x7b, 0x01, 0x26, - 0x5f, 0xc7, 0x47, 0x4c, 0x4b, 0x89, 0xee, 0x41, 0xa2, 0x2f, 0xe3, 0x30, 0x80, 0x8b, 0x2a, 0x08, 0x20, 0xbd, 0xae, - 0xe3, 0x48, 0x6c, 0xd6, 0x98, 0xe8, 0xb0, 0x68, 0xd3, 0x08, 0x54, 0x84, 0x1a, 0x18, 0x01, 0x2d, 0xe4, 0xca, 0x54, - 0x2c, 0x9d, 0xf9, 0xec, 0x02, 0x4b, 0x9f, 0xfb, 0x69, 0x5b, 0xdb, 0x5d, 0x31, 0x4b, 0x15, 0x24, 0xa5, 0x51, 0xd7, - 0x1b, 0x7d, 0xbb, 0x76, 0x67, 0x5d, 0xe3, 0x3d, 0x6e, 0xa4, 0x68, 0x6d, 0x2a, 0xd7, 0x47, 0xc9, 0x76, 0xfb, 0xdd, - 0xd2, 0x02, 0xd5, 0xcc, 0x59, 0x5a, 0x3b, 0x45, 0xf6, 0x3b, 0x0a, 0x70, 0xf9, 0x8e, 0x37, 0x18, 0x03, 0x64, 0x39, - 0xd2, 0xc6, 0xdc, 0x9a, 0x7c, 0xe4, 0x1e, 0x68, 0xe7, 0xdf, 0xbf, 0x4a, 0x82, 0xad, 0x3f, 0x2d, 0xc6, 0x65, 0xf0, - 0xcc, 0x61, 0x14, 0x38, 0x0a, 0x1f, 0xbd, 0x47, 0x5e, 0xad, 0x94, 0x31, 0xad, 0xcd, 0xe9, 0x4b, 0x23, 0x0d, 0x3e, - 0xd8, 0x86, 0xb5, 0x48, 0xae, 0xc7, 0xc8, 0xc6, 0x5e, 0xb7, 0xb0, 0x16, 0xc6, 0xe2, 0x8e, 0x21, 0xe5, 0x53, 0x49, - 0x09, 0xdc, 0xad, 0xe0, 0xe9, 0xc9, 0x9f, 0x52, 0x3e, 0x95, 0xd3, 0x4d, 0xae, 0xb3, 0x2f, 0x7f, 0x77, 0x4e, 0x17, - 0x1e, 0x34, 0x02, 0xfb, 0x32, 0x4b, 0x97, 0x55, 0x72, 0x2d, 0x90, 0x97, 0x6e, 0x3c, 0x17, 0xe5, 0xfa, 0xeb, 0x6e, - 0x23, 0x4c, 0x60, 0x9f, 0x2e, 0xf9, 0xdb, 0x7b, 0xf0, 0x7e, 0x2e, 0xe7, 0xf5, 0xb9, 0xb7, 0xa8, 0x93, 0x42, 0xbe, - 0xf9, 0xe4, 0x8b, 0x5d, 0x71, 0x9c, 0x10, 0x1f, 0xe8, 0x43, 0xe3, 0xbd, 0x5f, 0x8b, 0x04, 0xc4, 0x0a, 0xbf, 0x24, - 0x40, 0x44, 0x06, 0x70, 0xbc, 0xf3, 0xcf, 0xb1, 0xdb, 0x2c, 0x8d, 0x11, 0xdb, 0xe4, 0x61, 0x69, 0x4a, 0xda, 0xce, - 0x83, 0x0d, 0xf7, 0x67, 0x85, 0x52, 0x9c, 0x00, 0xcb, 0x33, 0xed, 0xb4, 0x8b, 0xbd, 0x08, 0xae, 0x69, 0x9b, 0x79, - 0xf5, 0x16, 0xf4, 0x84, 0xed, 0x2c, 0xcf, 0x63, 0x7b, 0xcb, 0xcf, 0xea, 0x20, 0xc2, 0x90, 0xbb, 0xe2, 0x4c, 0x5a, - 0x26, 0x90, 0x2a, 0xa6, 0x7d, 0xe3, 0xb8, 0xcd, 0x19, 0x3b, 0xf1, 0x02, 0xd1, 0x3f, 0x4e, 0x35, 0x2a, 0x9a, 0x4f, - 0xcd, 0x07, 0x8e, 0x34, 0x30, 0xf1, 0xab, 0x8d, 0xca, 0x54, 0x8e, 0x75, 0x00, 0x94, 0x2c, 0xd1, 0x9f, 0xb6, 0x28, - 0xad, 0x2b, 0x84, 0x51, 0xe1, 0x76, 0xf9, 0xf7, 0xf7, 0x36, 0xad, 0x62, 0x22, 0xda, 0xa3, 0x2b, 0xcd, 0xd9, 0x87, - 0x13, 0xf1, 0x96, 0x61, 0x07, 0x8a, 0x31, 0xa3, 0x03, 0x99, 0x94, 0xd5, 0x1e, 0x8d, 0x55, 0xe9, 0x46, 0x9e, 0x27, - 0x45, 0xa4, 0xbd, 0x80, 0xf5, 0xbd, 0xe0, 0x90, 0x8f, 0xef, 0x95, 0x21, 0x79, 0x5f, 0x77, 0x04, 0xe5, 0x00, 0xee, - 0x37, 0x4c, 0x1a, 0x7c, 0xf0, 0xcd, 0x5f, 0x72, 0xc5, 0xe8, 0xea, 0x95, 0x53, 0x36, 0xcd, 0xd8, 0x97, 0x1c, 0x26, - 0x57, 0xb8, 0x90, 0xed, 0xd3, 0x18, 0x79, 0xa3, 0x40, 0x72, 0x8e, 0x8d, 0x43, 0x3e, 0x6d, 0x58, 0x6f, 0x47, 0x52, - 0xba, 0x80, 0x90, 0xa9, 0x40, 0xd3, 0x83, 0x3a, 0x58, 0x92, 0x91, 0xd6, 0xa9, 0xbc, 0x8b, 0x8e, 0xfa, 0x3d, 0xeb, - 0x41, 0x73, 0xa5, 0xac, 0x0a, 0x84, 0x9b, 0xe5, 0xe5, 0x44, 0xc5, 0xb2, 0x3d, 0x9b, 0xca, 0xc7, 0xe5, 0x20, 0xb2, - 0x69, 0xda, 0xf9, 0xdb, 0xbe, 0x94, 0x22, 0x82, 0x07, 0xd4, 0x43, 0x08, 0xa1, 0xb4, 0x21, 0x03, 0x3d, 0xf2, 0x74, - 0x0d, 0xef, 0xf4, 0x03, 0x85, 0x7e, 0x3b, 0x0b, 0x82, 0xe0, 0xf8, 0x4a, 0xe8, 0x64, 0xcb, 0x9d, 0xda, 0x75, 0xde, - 0x63, 0x9f, 0xc8, 0x5e, 0x38, 0x79, 0xe5, 0xd2, 0xb4, 0x44, 0xdb, 0xd5, 0x8d, 0x3b, 0xff, 0xd8, 0xe1, 0x27, 0xa5, - 0x29, 0xa2, 0xd6, 0x24, 0x75, 0x3a, 0x58, 0x6e, 0x89, 0xa2, 0x45, 0x83, 0x83, 0x08, 0x74, 0x9c, 0x9c, 0x17, 0x71, - 0xdb, 0x0d, 0x05, 0xbe, 0xe4, 0x93, 0x70, 0x8f, 0x32, 0x16, 0xd0, 0x38, 0x52, 0xd0, 0x95, 0x16, 0x47, 0xb5, 0x32, - 0x86, 0x62, 0xcc, 0xde, 0x60, 0x0c, 0x65, 0x05, 0x1a, 0xac, 0x63, 0xeb, 0x45, 0xba, 0x1b, 0xa7, 0xbc, 0x86, 0x66, - 0x40, 0xe3, 0x7e, 0xea, 0x6b, 0x66, 0x84, 0x30, 0x34, 0xe1, 0xed, 0xd1, 0x3b, 0x77, 0x6c, 0x7f, 0xa5, 0xbe, 0x20, - 0x0c, 0x85, 0x18, 0xb0, 0x8b, 0x47, 0x31, 0x5b, 0x58, 0x22, 0x01, 0x71, 0xe5, 0x3e, 0x38, 0x30, 0xcb, 0xf2, 0xe0, - 0x1d, 0xa2, 0x42, 0x7b, 0x6c, 0xe3, 0xa6, 0x78, 0x4a, 0xc8, 0x15, 0x18, 0xc6, 0xfe, 0x32, 0x7d, 0x34, 0xf2, 0x54, - 0xd2, 0x7f, 0x11, 0x5a, 0x3f, 0x7b, 0xa4, 0x5b, 0x2c, 0xbb, 0xad, 0x0b, 0x6e, 0xdf, 0xea, 0x9f, 0xa5, 0xae, 0x4c, - 0xa4, 0xff, 0xb1, 0xb1, 0x6e, 0x75, 0xd9, 0x77, 0xfd, 0xfe, 0x43, 0x27, 0xea, 0x20, 0xff, 0xf4, 0x75, 0xdd, 0xe2, - 0x10, 0x8a, 0x27, 0x1f, 0xda, 0x43, 0x03, 0xf1, 0x31, 0xcd, 0x9a, 0x4b, 0x72, 0xde, 0xd0, 0xd0, 0x3f, 0x2b, 0x5c, - 0xfb, 0x51, 0x1f, 0x7a, 0x5c, 0xcc, 0x7f, 0x4e, 0xbe, 0xc3, 0xdd, 0xe8, 0xa3, 0x0b, 0x8f, 0xe4, 0x5c, 0x24, 0x8f, - 0xc9, 0x9e, 0xfe, 0xd8, 0x76, 0x91, 0xd2, 0x08, 0x50, 0x47, 0xaf, 0x9b, 0x96, 0xa6, 0x6b, 0x92, 0xd2, 0x3c, 0x28, - 0x5f, 0xe0, 0xaa, 0x1f, 0xbd, 0x5f, 0xdb, 0x43, 0x21, 0x9f, 0xd8, 0x5e, 0x2e, 0x49, 0xb7, 0xa7, 0x0f, 0x6f, 0x33, - 0xad, 0xce, 0x48, 0x8d, 0x5b, 0xd8, 0x97, 0xdb, 0xa3, 0xd0, 0x81, 0x32, 0x4a, 0xaf, 0x48, 0xbc, 0xc4, 0x38, 0xb9, - 0xc9, 0x0f, 0x4a, 0xcd, 0xb1, 0x7d, 0x1c, 0x79, 0x83, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0xde, 0x83, 0xa1, 0x72, - 0x2a, 0x58, 0x31, 0x2d, 0xe9, 0x89, 0x01, 0xb0, 0x69, 0xf4, 0x4b, 0xa8, 0xb6, 0x3b, 0x81, 0x4e, 0x6f, 0x9a, 0x54, - 0xdb, 0xc4, 0xff, 0xbe, 0x6f, 0xf4, 0x28, 0x59, 0x4a, 0x01, 0x59, 0xf7, 0xfd, 0x64, 0x6c, 0x12, 0x40, 0xa5, 0x79, - 0x96, 0xd5, 0x44, 0xdd, 0x81, 0xa1, 0x57, 0x33, 0x93, 0x3c, 0x7f, 0x8b, 0x0b, 0x3d, 0xee, 0x66, 0x4a, 0x0e, 0x95, - 0x22, 0x6f, 0x91, 0x08, 0xf5, 0x15, 0x7c, 0x1f, 0x49, 0x54, 0xcc, 0x2f, 0xe9, 0xec, 0x71, 0x68, 0xbc, 0x20, 0xd4, - 0x6f, 0xc0, 0x10, 0xf9, 0x21, 0x3a, 0x08, 0x81, 0xdd, 0xb9, 0x5c, 0x41, 0x72, 0x55, 0xdf, 0xcf, 0xa0, 0xee, 0x18, - 0xfd, 0x76, 0x55, 0xbf, 0x76, 0x0f, 0x86, 0x8c, 0x12, 0xbc, 0x46, 0xba, 0x39, 0x74, 0xd0, 0xa8, 0x1d, 0x3d, 0xd3, - 0x53, 0xe5, 0xa3, 0x0b, 0x14, 0x7d, 0xd8, 0x52, 0xe3, 0x89, 0x37, 0x52, 0xd0, 0x73, 0x71, 0xc0, 0x1b, 0xc3, 0x5e, - 0xd5, 0x81, 0xd1, 0x31, 0x7c, 0x7e, 0x29, 0x32, 0x20, 0x49, 0xaa, 0xa7, 0x45, 0xc4, 0x72, 0x28, 0x67, 0x6d, 0xe6, - 0x0e, 0xfa, 0x5e, 0x9c, 0x62, 0x86, 0xef, 0x6e, 0xf8, 0x8b, 0xbf, 0x19, 0x5f, 0xda, 0xe5, 0xda, 0x93, 0x6e, 0x51, - 0x1a, 0xac, 0xdb, 0xfa, 0x0e, 0x7a, 0x33, 0x12, 0x5d, 0xd0, 0xf4, 0xc7, 0x02, 0x11, 0x87, 0x94, 0x88, 0xa6, 0x69, - 0xe8, 0x94, 0x81, 0x23, 0x36, 0xe2, 0x7f, 0xb0, 0xa2, 0x41, 0x50, 0x6a, 0x1e, 0x58, 0x12, 0x2f, 0x07, 0x39, 0x92, - 0xf2, 0x06, 0x42, 0x41, 0x50, 0x53, 0xc1, 0x59, 0x90, 0xd2, 0x8d, 0x69, 0x87, 0xc8, 0x15, 0xb9, 0xae, 0x8f, 0x1b, - 0xf4, 0xe5, 0x2b, 0x39, 0x31, 0xa9, 0x32, 0x72, 0x6b, 0xaa, 0x62, 0xc7, 0xe0, 0x1d, 0xe7, 0xd6, 0x81, 0x7b, 0x83, - 0x22, 0x68, 0x8a, 0x92, 0xa5, 0x97, 0x39, 0x2f, 0x42, 0x5b, 0xe4, 0xba, 0x1e, 0x3d, 0xa8, 0x18, 0x28, 0xa9, 0xb0, - 0xd8, 0x90, 0x56, 0xf4, 0xa7, 0xce, 0x3b, 0x8c, 0xc2, 0x95, 0x76, 0x65, 0xe4, 0xe1, 0x3d, 0x1e, 0x47, 0xef, 0x26, - 0x51, 0x2c, 0xf2, 0x5c, 0x9d, 0xd7, 0x2c, 0xc8, 0xba, 0x9d, 0x26, 0x79, 0xbe, 0x1b, 0xce, 0xa2, 0x62, 0x52, 0xb2, - 0x95, 0x24, 0xaf, 0x59, 0x28, 0x8c, 0xd8, 0xfa, 0xcd, 0xa3, 0x20, 0xf9, 0x2c, 0xba, 0xbd, 0x1f, 0x09, 0xaf, 0x17, - 0x49, 0x66, 0x11, 0xcf, 0xf3, 0x2c, 0xb5, 0x6c, 0xcc, 0xa9, 0x50, 0xa9, 0xce, 0x10, 0xf8, 0x2b, 0x69, 0x7a, 0x53, - 0x26, 0x28, 0xdc, 0xb6, 0xe9, 0x3e, 0x98, 0x8c, 0x88, 0x0e, 0xdf, 0xb9, 0xd1, 0xcc, 0xc7, 0x6f, 0x94, 0x81, 0x1d, - 0xd6, 0xda, 0xd0, 0x76, 0x81, 0x97, 0x5b, 0x95, 0xc1, 0x9e, 0x46, 0x95, 0x32, 0xf2, 0x82, 0xa8, 0x3a, 0xd1, 0x56, - 0x70, 0xe8, 0x87, 0x0d, 0xfe, 0x3d, 0xc2, 0x70, 0xc9, 0x3d, 0xbb, 0x0d, 0x40, 0x0e, 0x59, 0x44, 0x3a, 0x2a, 0xa0, - 0x47, 0x9f, 0xae, 0x66, 0xcc, 0x15, 0xdc, 0x65, 0x0d, 0x82, 0x3b, 0xda, 0x3e, 0xc3, 0x40, 0xd2, 0x1d, 0x2e, 0xb4, - 0x29, 0x7a, 0xd4, 0xdf, 0x36, 0x4b, 0x67, 0xc1, 0x9b, 0x54, 0xc1, 0xcf, 0xb4, 0xe0, 0x84, 0xb7, 0xfd, 0x1e, 0xef, - 0x1b, 0xad, 0xb1, 0x6d, 0x86, 0xc7, 0xc6, 0xbc, 0x3b, 0xc8, 0x1a, 0xab, 0x8b, 0xc5, 0x35, 0x41, 0x2e, 0x25, 0xf9, - 0x88, 0xeb, 0xe5, 0x69, 0x19, 0x7c, 0xaa, 0x9e, 0x2a, 0x56, 0xa0, 0x1c, 0x16, 0x21, 0x14, 0x4c, 0xb3, 0x87, 0xb1, - 0x0e, 0x1f, 0x23, 0x31, 0x28, 0x24, 0x84, 0x05, 0x16, 0xa5, 0xee, 0xc7, 0x42, 0xa7, 0xd2, 0x40, 0x50, 0x42, 0x85, - 0x02, 0x23, 0xce, 0x7b, 0x2d, 0xbd, 0x86, 0xb6, 0xa9, 0x8c, 0x1e, 0x06, 0xbb, 0x58, 0xf6, 0x0e, 0x99, 0xc2, 0x92, - 0x2d, 0x0f, 0x21, 0x37, 0xdc, 0xd8, 0xa7, 0xef, 0xdb, 0xb5, 0x8a, 0x55, 0x33, 0xba, 0x9a, 0xfa, 0xdf, 0x11, 0xa1, - 0x71, 0x00, 0xd9, 0xc7, 0x6b, 0xe9, 0x60, 0x45, 0x8c, 0x9d, 0xe6, 0x23, 0xf5, 0xa2, 0x9c, 0x3f, 0x9b, 0x02, 0x82, - 0x6d, 0x6f, 0xed, 0x58, 0x37, 0x40, 0xe2, 0x76, 0x8e, 0xc9, 0x5e, 0x5d, 0xe2, 0x49, 0xef, 0x83, 0xf2, 0xb9, 0x75, - 0xdb, 0x25, 0x81, 0xcc, 0x17, 0xac, 0x28, 0x06, 0x24, 0x2b, 0x25, 0x78, 0xce, 0x7f, 0x6b, 0x1d, 0x54, 0x90, 0x90, - 0xe7, 0x83, 0x46, 0xb2, 0x32, 0xea, 0xf9, 0x98, 0x08, 0x1c, 0xd4, 0x02, 0x44, 0x63, 0x70, 0x06, 0x25, 0x28, 0x5b, - 0xc6, 0x3e, 0x1c, 0xce, 0x69, 0xf2, 0x12, 0xa1, 0x29, 0xca, 0x87, 0x2c, 0xf6, 0x57, 0x3f, 0x51, 0xa8, 0x9b, 0x1b, - 0xb9, 0x11, 0x1d, 0x0a, 0x5d, 0xbd, 0x6b, 0x6f, 0x32, 0x82, 0x34, 0xda, 0xba, 0xb9, 0x9e, 0x3d, 0x3f, 0xeb, 0xe1, - 0x63, 0x73, 0xba, 0x1e, 0x2e, 0x6f, 0x4a, 0xb5, 0x22, 0x42, 0xfb, 0x7f, 0x56, 0x96, 0x93, 0xff, 0x2c, 0xfa, 0x8b, - 0xcf, 0x8a, 0xfe, 0x94, 0x02, 0x49, 0x5d, 0x44, 0x5c, 0x5c, 0xb3, 0xd1, 0x5c, 0x29, 0x37, 0x6c, 0xaf, 0x9c, 0x27, - 0xbe, 0x72, 0x2e, 0x7f, 0x08, 0x07, 0xd5, 0x4e, 0x38, 0x0b, 0xe0, 0xa4, 0x8c, 0xb8, 0x1c, 0x3c, 0x8b, 0x01, 0xad, - 0xe2, 0x8a, 0x5a, 0x1d, 0x39, 0xcf, 0x1d, 0x6f, 0x1b, 0x6a, 0x2e, 0xea, 0xa1, 0x10, 0xe7, 0x03, 0x31, 0x32, 0x1b, - 0x88, 0xba, 0x09, 0x33, 0xd8, 0xdf, 0x91, 0xb2, 0x93, 0xe5, 0xa2, 0x4b, 0x6d, 0xf7, 0xc4, 0x51, 0xa4, 0xa4, 0x97, - 0xa9, 0xad, 0x40, 0x45, 0xaa, 0x24, 0x75, 0x74, 0x44, 0x14, 0xc2, 0x26, 0x58, 0x50, 0x3c, 0x6a, 0xc2, 0xa8, 0x4d, - 0xc2, 0xed, 0x00, 0x49, 0x8a, 0xd5, 0x28, 0xe3, 0xba, 0xa3, 0x12, 0x34, 0x24, 0xd4, 0x99, 0xa3, 0x03, 0x1a, 0x35, - 0x09, 0x25, 0x43, 0x49, 0xf3, 0x2f, 0x53, 0xd3, 0x98, 0x21, 0xea, 0x0f, 0x8c, 0xd0, 0x3b, 0xb7, 0x21, 0xe0, 0x96, - 0xf9, 0xad, 0x56, 0x2e, 0x8b, 0x04, 0xe2, 0x53, 0xc6, 0x3e, 0x50, 0xad, 0x11, 0xb5, 0x93, 0x2f, 0x54, 0x3a, 0x7c, - 0x09, 0xc5, 0x31, 0xd1, 0xc9, 0x09, 0x67, 0xcf, 0x4c, 0x28, 0x2b, 0xfe, 0x4d, 0xa6, 0xcd, 0x90, 0xb6, 0xf4, 0x41, - 0x8f, 0x4e, 0x24, 0xe1, 0x1c, 0xcb, 0x16, 0xb9, 0xaf, 0x46, 0xba, 0xaa, 0x25, 0x09, 0x43, 0x05, 0x99, 0xcb, 0xc2, - 0xf5, 0x49, 0x78, 0xed, 0x1e, 0x92, 0xf6, 0xb3, 0x0e, 0x2c, 0xb7, 0xcd, 0x4b, 0xec, 0xc2, 0x59, 0xef, 0x41, 0xb4, - 0xf7, 0x4c, 0x08, 0x7c, 0x16, 0xeb, 0x13, 0x29, 0x74, 0xff, 0x60, 0x12, 0x86, 0x84, 0xcf, 0xe0, 0xe1, 0x72, 0xf4, - 0x23, 0x45, 0x57, 0x24, 0x94, 0xb7, 0x6a, 0x5d, 0x12, 0x12, 0x85, 0x7b, 0x8b, 0x45, 0x63, 0x5d, 0x44, 0x43, 0xa1, - 0xb9, 0x78, 0xed, 0x49, 0xf5, 0xbe, 0x17, 0x75, 0x75, 0x8c, 0x50, 0xbd, 0xe0, 0x9f, 0xc1, 0x4f, 0x48, 0x42, 0xa7, - 0xd0, 0xdd, 0x36, 0x2d, 0x20, 0xb3, 0xc3, 0x69, 0x88, 0x02, 0x1e, 0xa2, 0x2a, 0x02, 0xb4, 0x98, 0x36, 0x97, 0x43, - 0x0a, 0xd5, 0xf3, 0x13, 0x9d, 0x7c, 0x40, 0xdd, 0x03, 0x99, 0xb2, 0xed, 0xb4, 0x7c, 0xba, 0x57, 0x38, 0x2c, 0xb5, - 0xbf, 0x89, 0x84, 0x92, 0x99, 0x58, 0x42, 0xdb, 0x98, 0x24, 0x7c, 0xfe, 0x75, 0xeb, 0x4a, 0xc4, 0xf8, 0x90, 0xbe, - 0x1c, 0xc9, 0xb8, 0xc2, 0x3b, 0x95, 0x9c, 0x40, 0xc4, 0xa6, 0xb7, 0x47, 0x21, 0x21, 0x65, 0x6a, 0x7c, 0x20, 0xa5, - 0xa5, 0x77, 0x7b, 0xda, 0x7c, 0x2a, 0x85, 0x1f, 0xaf, 0x3a, 0xd9, 0x73, 0x75, 0xb0, 0x75, 0x94, 0xf6, 0x98, 0x4c, - 0xf6, 0x1f, 0xfa, 0x98, 0xa2, 0x89, 0x81, 0x32, 0x62, 0xec, 0x30, 0x0f, 0xac, 0x12, 0x62, 0xda, 0x50, 0xaa, 0x2c, - 0x25, 0x39, 0x07, 0x0c, 0x3f, 0x4e, 0x1e, 0xa1, 0x80, 0xc1, 0xc4, 0x04, 0x2b, 0xc3, 0xe5, 0x62, 0x69, 0x50, 0x97, - 0x4a, 0x3c, 0x79, 0x2a, 0x4d, 0xae, 0xa7, 0xb1, 0xc4, 0x55, 0x22, 0x81, 0x49, 0x0d, 0x3d, 0x02, 0x18, 0x8f, 0xd4, - 0x8b, 0x6c, 0xfa, 0x0c, 0x9c, 0x96, 0xbe, 0x73, 0x7a, 0xca, 0x24, 0x6f, 0xb4, 0x59, 0x20, 0x98, 0xf0, 0xd8, 0x30, - 0x74, 0x47, 0x95, 0x7c, 0xb4, 0x4f, 0xac, 0xcf, 0x99, 0x45, 0x19, 0x8f, 0x3d, 0x05, 0x18, 0x38, 0xad, 0xf7, 0xe8, - 0x47, 0xd9, 0x74, 0x56, 0x93, 0x71, 0x22, 0x4f, 0x54, 0x52, 0x65, 0xd9, 0x89, 0x49, 0x8d, 0x1e, 0xaa, 0x65, 0x4f, - 0x76, 0x4c, 0x81, 0x04, 0x50, 0x4d, 0x72, 0xf8, 0x19, 0xb8, 0x74, 0x16, 0xda, 0x22, 0x95, 0x24, 0x6c, 0x00, 0xab, - 0xcf, 0x69, 0xdc, 0x38, 0xff, 0xba, 0x8f, 0x02, 0xa8, 0x57, 0x42, 0x4c, 0x54, 0xd0, 0x0a, 0xfb, 0xa0, 0x32, 0x81, - 0x76, 0xcb, 0x29, 0x69, 0x3b, 0xca, 0x48, 0x72, 0x15, 0xd7, 0x81, 0x18, 0xdc, 0xd3, 0x03, 0xb1, 0x88, 0xae, 0x1b, - 0xd8, 0x74, 0x60, 0xc7, 0x6f, 0x8c, 0x97, 0x6a, 0x7b, 0xac, 0xea, 0x4a, 0x92, 0x8f, 0x92, 0x4d, 0xaa, 0x9d, 0x00, - 0xe4, 0x48, 0xa8, 0x5a, 0xe4, 0xa7, 0x4d, 0x29, 0xa5, 0xb5, 0x61, 0xf7, 0x9e, 0x9a, 0x90, 0xeb, 0x55, 0x3d, 0x85, - 0x8f, 0x63, 0x64, 0x0e, 0xf1, 0x18, 0x67, 0x67, 0x88, 0x78, 0xc7, 0x95, 0x85, 0xfb, 0xdb, 0x22, 0xf5, 0x5c, 0x4a, - 0x52, 0x7b, 0x90, 0x4b, 0xb9, 0x4c, 0x3e, 0x98, 0xe6, 0xd2, 0x22, 0x30, 0xe7, 0x45, 0x25, 0x8e, 0x2e, 0x29, 0xc1, - 0x1d, 0x9a, 0x5e, 0x67, 0x39, 0x08, 0x2d, 0x53, 0xcc, 0x06, 0x48, 0x21, 0x20, 0x02, 0xe3, 0x2a, 0x5f, 0xb0, 0x77, - 0xb9, 0x8a, 0x0b, 0x8d, 0x60, 0x29, 0x32, 0x43, 0xaa, 0xed, 0xc4, 0xb4, 0xfb, 0xca, 0x59, 0xf4, 0xd3, 0x72, 0x39, - 0xd2, 0x71, 0x4d, 0x9c, 0x97, 0x92, 0xbc, 0x19, 0x46, 0x86, 0xce, 0x5b, 0x53, 0x6c, 0x75, 0x36, 0xf3, 0xd9, 0x90, - 0x40, 0x48, 0xc0, 0x82, 0x42, 0x2e, 0x4b, 0xd9, 0x99, 0xc7, 0xb4, 0xc7, 0xe3, 0xcc, 0xe8, 0xfe, 0xfa, 0x7d, 0x3d, - 0x9d, 0x96, 0x05, 0x55, 0x79, 0xb8, 0xed, 0x0e, 0x96, 0xc7, 0x41, 0x97, 0x76, 0x59, 0x4c, 0x15, 0xbf, 0x92, 0xec, - 0x27, 0x0d, 0x2f, 0xa3, 0x61, 0xae, 0x79, 0x49, 0xf5, 0x52, 0xcc, 0x70, 0x64, 0x91, 0xe6, 0xab, 0x23, 0xf6, 0xb3, - 0x33, 0xad, 0xad, 0xfc, 0xfb, 0x91, 0x59, 0x3b, 0xda, 0x5e, 0x49, 0x7d, 0xa5, 0x8f, 0x7e, 0xee, 0x83, 0xc5, 0x04, - 0x7f, 0x56, 0x28, 0x17, 0x7a, 0x52, 0x58, 0xa1, 0xfe, 0xb3, 0xae, 0x65, 0x7f, 0x6c, 0x82, 0x0f, 0xed, 0x83, 0x0f, - 0x98, 0x26, 0x34, 0x3f, 0x32, 0xc0, 0xa6, 0x8a, 0x09, 0xcb, 0xb7, 0x15, 0xb6, 0x21, 0xc5, 0xfb, 0xe7, 0x75, 0xcb, - 0x63, 0x9e, 0x8a, 0x29, 0x2f, 0x90, 0x5b, 0xfe, 0x2c, 0x20, 0x12, 0x75, 0x06, 0xd7, 0x43, 0x3e, 0x81, 0x6e, 0xec, - 0x3c, 0x3c, 0x12, 0xb9, 0xe2, 0x36, 0xc3, 0x9d, 0xc2, 0xb7, 0x87, 0xc7, 0xca, 0xbb, 0xb4, 0x52, 0x48, 0xa3, 0xfa, - 0x83, 0x36, 0xc3, 0x1b, 0xab, 0xd1, 0x43, 0x5d, 0x2d, 0x09, 0x61, 0x11, 0x84, 0x87, 0x45, 0xe8, 0xfd, 0x9f, 0xae, - 0x54, 0x48, 0x4c, 0x4e, 0x5b, 0x46, 0x72, 0x0e, 0x84, 0x54, 0xa0, 0x96, 0xe9, 0x3e, 0x65, 0x51, 0xa9, 0xdb, 0x42, - 0x6e, 0xfc, 0x96, 0x7c, 0x44, 0x15, 0x16, 0x3b, 0xbf, 0xd6, 0xdd, 0x27, 0xd2, 0x75, 0x57, 0xd4, 0x85, 0x56, 0x53, - 0x96, 0xa7, 0x68, 0x7a, 0x0e, 0xc4, 0xee, 0x71, 0x95, 0xfc, 0x9e, 0x40, 0x3a, 0xff, 0xb1, 0xe0, 0xef, 0xef, 0x15, - 0x49, 0xa2, 0xf5, 0x45, 0xe3, 0x51, 0xeb, 0x8b, 0x3d, 0x75, 0x68, 0x80, 0xd3, 0x05, 0x24, 0x8f, 0xaf, 0x02, 0x74, - 0x0d, 0x66, 0xe9, 0xaa, 0x63, 0x8e, 0x9b, 0xee, 0x7c, 0xd9, 0x16, 0x69, 0x3d, 0x43, 0x00, 0xed, 0x0d, 0x19, 0x77, - 0xff, 0x21, 0x4e, 0xb4, 0x67, 0x61, 0x82, 0x2e, 0x22, 0xe9, 0x3d, 0xec, 0x28, 0xb9, 0xd5, 0x9c, 0xe5, 0x0e, 0xdd, - 0x81, 0xae, 0x67, 0xbd, 0x88, 0x4a, 0x43, 0x0e, 0x76, 0x52, 0x6a, 0x08, 0x20, 0xda, 0x83, 0x6e, 0x2f, 0x4e, 0xee, - 0xed, 0x62, 0xc5, 0x7a, 0xdb, 0x0e, 0x4d, 0x2c, 0x54, 0x85, 0x2b, 0xac, 0x31, 0xe6, 0x96, 0xe3, 0xf6, 0x70, 0xd6, - 0x39, 0x16, 0x4a, 0xa3, 0xc1, 0xc0, 0xb7, 0xaf, 0xf3, 0xe3, 0x78, 0x61, 0x8f, 0x1c, 0x80, 0xd0, 0xb1, 0x17, 0x65, - 0x52, 0x05, 0x8a, 0x63, 0x19, 0x02, 0x2d, 0xda, 0xad, 0x59, 0xa5, 0x20, 0x17, 0x1e, 0x50, 0x8b, 0x8f, 0x17, 0xfe, - 0xb3, 0xcd, 0xb9, 0xd0, 0x42, 0xe6, 0xa8, 0x9d, 0x96, 0xec, 0x53, 0xbd, 0xa0, 0x00, 0x89, 0x32, 0xc2, 0xb6, 0x56, - 0x32, 0xf5, 0x71, 0x0a, 0x36, 0x21, 0xfb, 0x35, 0x49, 0x72, 0x3a, 0x32, 0x81, 0xd6, 0x79, 0xbb, 0x91, 0xa8, 0x0b, - 0x51, 0xe5, 0xc6, 0xa8, 0x0f, 0x7b, 0x46, 0xc7, 0x13, 0x8c, 0xe4, 0x98, 0xd2, 0xb1, 0xce, 0xbc, 0x7b, 0xab, 0x3d, - 0x76, 0xa7, 0x4d, 0x2b, 0x53, 0x9a, 0x29, 0x88, 0x39, 0x94, 0x49, 0x12, 0x04, 0x24, 0xb6, 0xbe, 0xbb, 0xce, 0x51, - 0x2d, 0xe8, 0x0e, 0x4c, 0x9f, 0x19, 0x8d, 0x02, 0x09, 0xf8, 0x6e, 0x39, 0x23, 0xe7, 0x90, 0xc2, 0xba, 0xb6, 0x50, - 0x91, 0x76, 0x97, 0x57, 0x82, 0x0a, 0xe7, 0x82, 0xd0, 0xec, 0xa0, 0xe0, 0xd4, 0xee, 0x77, 0x9b, 0xa1, 0xae, 0x3a, - 0xfa, 0x80, 0x1b, 0xb0, 0xd9, 0x10, 0xe2, 0x48, 0xdc, 0x78, 0xa1, 0x6c, 0x80, 0x13, 0x37, 0x2a, 0x61, 0x75, 0x62, - 0x7b, 0x72, 0xf4, 0xa3, 0x0b, 0xb5, 0xcc, 0x27, 0x58, 0xa2, 0x8b, 0x9e, 0x57, 0xb6, 0xdd, 0x5e, 0xe6, 0xdb, 0x6a, - 0x5e, 0xa0, 0xd8, 0x26, 0x21, 0xc4, 0x32, 0x4d, 0xe7, 0x98, 0xe7, 0xc2, 0x8f, 0x0e, 0x26, 0xc8, 0x3c, 0x94, 0x82, - 0x56, 0xf5, 0x0a, 0x34, 0x65, 0x97, 0xac, 0x84, 0x7b, 0xb7, 0xbe, 0xc9, 0xa4, 0x5d, 0xb4, 0x56, 0xde, 0x5d, 0x3d, - 0x6d, 0x40, 0xf7, 0xdc, 0xfb, 0x94, 0xfe, 0x25, 0xd0, 0x71, 0xc9, 0x6a, 0xf7, 0xbc, 0x9f, 0x52, 0x4e, 0xe3, 0x9a, - 0x28, 0x25, 0x0a, 0x3f, 0x1c, 0x06, 0xc4, 0xcc, 0x10, 0xe2, 0x8f, 0x7e, 0xe0, 0xcd, 0x5e, 0xec, 0x52, 0xa6, 0x4a, - 0x8b, 0xe2, 0x4f, 0x7a, 0x3f, 0x65, 0xc2, 0xc9, 0x7d, 0xd1, 0x3f, 0x37, 0xc4, 0x77, 0xa2, 0x01, 0x26, 0x62, 0x50, - 0x47, 0xbf, 0x45, 0x60, 0x3d, 0xa2, 0x23, 0x4b, 0xde, 0x2c, 0xff, 0x5d, 0xd6, 0xde, 0x9f, 0x76, 0x16, 0xaf, 0x2d, - 0xa9, 0xc1, 0x46, 0xb7, 0x1b, 0xc3, 0xda, 0xb0, 0xed, 0x29, 0x15, 0x20, 0x32, 0x7a, 0x04, 0xaa, 0x31, 0x5f, 0xcd, - 0x12, 0x14, 0x03, 0x1f, 0x71, 0x02, 0x1c, 0xb9, 0xad, 0x93, 0x95, 0x14, 0xee, 0xde, 0xfa, 0xb6, 0xd7, 0xc4, 0xbe, - 0xb2, 0x4b, 0x58, 0xee, 0xc8, 0x1d, 0xbb, 0xe9, 0x04, 0xaa, 0xa3, 0xb0, 0x57, 0x30, 0xac, 0x68, 0xd1, 0xb5, 0x03, - 0x11, 0x85, 0xde, 0x4e, 0x54, 0x14, 0x3e, 0x66, 0x58, 0x51, 0xd9, 0xd9, 0x01, 0x8c, 0x00, 0xfe, 0x45, 0x1c, 0x9e, - 0xd8, 0xe5, 0xa9, 0x66, 0x31, 0x83, 0x00, 0x63, 0xf8, 0xca, 0x06, 0x67, 0xc6, 0x0b, 0xcb, 0xc0, 0x26, 0x07, 0x80, - 0x5a, 0x47, 0x51, 0x6f, 0x71, 0x8a, 0x0f, 0x53, 0xdf, 0x18, 0xbc, 0xbd, 0x54, 0x4e, 0x47, 0xbc, 0x87, 0xdd, 0x95, - 0x8a, 0x1a, 0x52, 0xb0, 0x85, 0x6f, 0xbb, 0x21, 0x60, 0xa5, 0x30, 0x09, 0xfa, 0x50, 0x4e, 0x9b, 0xcb, 0x93, 0xcf, - 0x54, 0xff, 0x57, 0x4f, 0xc9, 0x54, 0x2c, 0x78, 0xd9, 0x49, 0x4f, 0x67, 0x9c, 0x96, 0xa5, 0xb2, 0xcf, 0xfd, 0xd3, - 0x4e, 0x12, 0x28, 0xf0, 0xed, 0x10, 0xf0, 0xec, 0xff, 0x2c, 0xda, 0xa8, 0x48, 0xad, 0x9a, 0x68, 0xa3, 0xa5, 0x75, - 0xec, 0x11, 0xff, 0x7e, 0x94, 0x76, 0x75, 0xe0, 0xa1, 0xaa, 0xcf, 0x27, 0x79, 0xe6, 0xbf, 0xe2, 0x49, 0xde, 0x10, - 0x75, 0x3b, 0xb1, 0xfb, 0x26, 0xa7, 0x4b, 0x79, 0x3b, 0x99, 0x57, 0x41, 0x7c, 0x47, 0x53, 0x03, 0xb3, 0x39, 0x29, - 0x71, 0xeb, 0xa5, 0xa2, 0xde, 0xe2, 0xc8, 0x23, 0x3a, 0x48, 0x32, 0x8c, 0xe6, 0xfc, 0xdc, 0x4e, 0xfc, 0x78, 0x2e, - 0x58, 0xfc, 0xb8, 0xbf, 0x2f, 0x30, 0x1c, 0x7d, 0x70, 0x12, 0x67, 0xda, 0xd5, 0x18, 0x29, 0x86, 0xaa, 0x14, 0x70, - 0x26, 0x36, 0xb7, 0xed, 0x47, 0x00, 0xe8, 0x3d, 0x70, 0xdc, 0xfb, 0x6e, 0xc1, 0xd9, 0xb3, 0xba, 0xb9, 0x90, 0x49, - 0xe6, 0x15, 0x65, 0x8c, 0x2b, 0x5e, 0xf4, 0x95, 0x2b, 0xf7, 0x3a, 0xc9, 0x03, 0x18, 0x52, 0x41, 0x4e, 0xe4, 0x9d, - 0x96, 0xba, 0xa2, 0xce, 0x42, 0xc8, 0x42, 0xce, 0x05, 0xb8, 0xca, 0xf3, 0xa7, 0xb3, 0x32, 0x8b, 0xe9, 0xdd, 0x5a, - 0xeb, 0x04, 0x08, 0x41, 0xf5, 0x95, 0x0c, 0xc6, 0xa1, 0x27, 0x79, 0x9f, 0x0a, 0x89, 0xb5, 0xe1, 0x1d, 0xb3, 0x1e, - 0x73, 0xf0, 0xc7, 0x84, 0xda, 0x4e, 0xa9, 0x07, 0xf9, 0x46, 0x6a, 0xd3, 0x7b, 0xc6, 0xe3, 0xf6, 0x0d, 0xb7, 0xd3, - 0x04, 0x09, 0x8a, 0x6b, 0x02, 0x2d, 0x97, 0x71, 0x0b, 0x60, 0xa9, 0x33, 0x45, 0xc3, 0x5b, 0xea, 0x7e, 0x62, 0x01, - 0x6b, 0xde, 0xad, 0x8c, 0x27, 0x0e, 0x73, 0xb2, 0x3d, 0x58, 0xbf, 0x2d, 0x86, 0x56, 0xa2, 0x0a, 0x07, 0x2b, 0x7b, - 0xde, 0x6d, 0x3b, 0xfe, 0x60, 0xcf, 0x65, 0x46, 0x84, 0x61, 0x1f, 0x38, 0x0a, 0x53, 0xec, 0xf2, 0x2a, 0x5b, 0x23, - 0x47, 0x18, 0x4e, 0xbe, 0xde, 0xa8, 0x81, 0xe5, 0xc4, 0xce, 0x69, 0xf6, 0x6f, 0xe8, 0x89, 0x40, 0xc6, 0x53, 0x7f, - 0xfc, 0xcc, 0x0c, 0xf5, 0xe0, 0x21, 0xdb, 0xed, 0xd2, 0xd7, 0xd6, 0x76, 0xb9, 0xb6, 0xad, 0x71, 0x8b, 0x68, 0x39, - 0x94, 0xd8, 0xb5, 0x46, 0x2c, 0xdd, 0xa1, 0x0b, 0x1f, 0xd8, 0x02, 0x37, 0xaa, 0x42, 0xe4, 0x2e, 0x37, 0x53, 0x89, - 0x35, 0x14, 0x80, 0xab, 0x9d, 0x17, 0x66, 0xd4, 0x27, 0x92, 0xf1, 0x15, 0x7b, 0x64, 0xa9, 0xf9, 0xa9, 0xcf, 0x3c, - 0xb0, 0x17, 0x8d, 0x42, 0xdf, 0xa4, 0x39, 0xcd, 0x8b, 0xf6, 0x83, 0xec, 0x16, 0xf9, 0x09, 0x42, 0x2b, 0xe1, 0x7c, - 0x7e, 0xd9, 0x7e, 0xd1, 0x2e, 0x66, 0x39, 0xe2, 0x61, 0x7f, 0x53, 0x4f, 0x2b, 0xbd, 0x8f, 0x77, 0x04, 0x0b, 0xb7, - 0x1d, 0x08, 0x26, 0x92, 0x3e, 0x12, 0xf2, 0xf0, 0x9d, 0xf8, 0xff, 0x6b, 0x43, 0xa0, 0x0d, 0x5b, 0x31, 0x5b, 0x1c, - 0x7e, 0x6a, 0x0a, 0xde, 0x41, 0x33, 0x4f, 0xa3, 0xb6, 0xb2, 0xce, 0xaa, 0xda, 0x2c, 0xe0, 0x15, 0x2f, 0x3f, 0x65, - 0x78, 0x81, 0x93, 0x71, 0x8e, 0x64, 0x78, 0x3f, 0x0f, 0x10, 0x25, 0x04, 0x24, 0xc4, 0xe9, 0x75, 0xf7, 0x60, 0x70, - 0x07, 0x6d, 0x7c, 0x09, 0x0a, 0xeb, 0xf9, 0x6c, 0x3c, 0x8f, 0xd9, 0x9b, 0xfc, 0x33, 0xba, 0x9e, 0xe8, 0x34, 0xae, - 0x54, 0x5b, 0xad, 0x5f, 0xbd, 0xf0, 0xdb, 0x43, 0xcd, 0x37, 0xf7, 0x93, 0xfb, 0x6c, 0x92, 0xad, 0x7c, 0xa8, 0x54, - 0x59, 0xde, 0x0d, 0x68, 0x31, 0x44, 0x65, 0x39, 0x4c, 0xa3, 0xdd, 0x86, 0xa3, 0xc3, 0x96, 0xdb, 0x49, 0xad, 0x9d, - 0x80, 0xec, 0xa0, 0x69, 0x51, 0x89, 0x17, 0x56, 0x90, 0x71, 0x9f, 0x72, 0x37, 0xa2, 0xa0, 0x20, 0xba, 0xc9, 0x52, - 0x9d, 0x61, 0x6a, 0x6c, 0x38, 0xf5, 0x80, 0xb2, 0xa0, 0xff, 0x75, 0x60, 0x28, 0x32, 0xa3, 0xb6, 0x30, 0x3f, 0xa6, - 0xca, 0xc9, 0x1f, 0xb7, 0x9c, 0xca, 0xc4, 0xaa, 0x57, 0xe8, 0xd5, 0xeb, 0x7d, 0x6e, 0x9a, 0x4e, 0x0c, 0x14, 0x1f, - 0x70, 0x35, 0x27, 0x58, 0x4d, 0xe4, 0x8b, 0x78, 0xb9, 0xca, 0x9c, 0x7d, 0x00, 0x7e, 0xd1, 0x75, 0x0b, 0x87, 0x69, - 0x79, 0xdb, 0xec, 0x8f, 0xe8, 0xec, 0x4a, 0xf2, 0x62, 0xc9, 0x16, 0x7c, 0x8c, 0x06, 0x70, 0x64, 0x0f, 0xaa, 0xc6, - 0x29, 0xc0, 0x22, 0x91, 0xd8, 0xc2, 0x52, 0x5a, 0x0f, 0xca, 0x05, 0x31, 0xb5, 0x8c, 0xe9, 0x36, 0x7a, 0x3c, 0x2d, - 0x23, 0x40, 0x0b, 0xb5, 0xb5, 0xc2, 0x3b, 0x8a, 0x29, 0x2a, 0x9b, 0x0b, 0xb9, 0x0a, 0x6c, 0xff, 0x9a, 0x52, 0x29, - 0x17, 0xb1, 0xdb, 0xa4, 0xb4, 0x43, 0xfd, 0x87, 0x7e, 0xc5, 0x6a, 0xc9, 0x09, 0x89, 0xd1, 0x47, 0x2e, 0x2e, 0x09, - 0x69, 0x45, 0xa6, 0x39, 0x5c, 0x33, 0x24, 0xf8, 0x73, 0x5a, 0x6b, 0x2f, 0xc5, 0x91, 0x31, 0x67, 0xee, 0x9b, 0xe2, - 0xda, 0x69, 0xab, 0xbf, 0xd8, 0x19, 0x57, 0x02, 0x82, 0xe1, 0xfc, 0x32, 0x97, 0x43, 0x77, 0xee, 0xbd, 0xb4, 0xe7, - 0xbc, 0xcc, 0x10, 0xc1, 0x4c, 0x20, 0xe4, 0x49, 0xe9, 0x5c, 0x74, 0x7d, 0x3a, 0x75, 0x24, 0xb1, 0xb6, 0x3e, 0x65, - 0xc6, 0x64, 0xc2, 0x64, 0x28, 0x28, 0xee, 0x19, 0xbf, 0x3f, 0x81, 0x8c, 0xa0, 0x86, 0xa0, 0xa0, 0xba, 0xee, 0xf1, - 0xf4, 0x65, 0x35, 0xf8, 0xf5, 0xb2, 0x42, 0x49, 0xe8, 0xb8, 0xf4, 0xdf, 0xe6, 0xb2, 0xcb, 0x92, 0x83, 0xbd, 0xbd, - 0x37, 0x30, 0xce, 0xa6, 0xd1, 0x93, 0x9d, 0x98, 0x72, 0xb7, 0x9d, 0xa0, 0x52, 0xf2, 0x9a, 0x52, 0x51, 0xb8, 0xd5, - 0x4b, 0xb4, 0x9e, 0x79, 0xe5, 0x70, 0x97, 0x78, 0x43, 0x59, 0xbc, 0x63, 0xc3, 0x4e, 0xf9, 0xcf, 0x8f, 0x6d, 0xf9, - 0xb2, 0x8d, 0x07, 0x7b, 0xba, 0x3f, 0x09, 0xfa, 0xce, 0xb8, 0xdf, 0x31, 0xf2, 0x57, 0x5f, 0x7c, 0x57, 0x93, 0xbf, - 0xf4, 0x9b, 0xb5, 0x1e, 0xf3, 0xba, 0x87, 0xdf, 0xef, 0xd3, 0x29, 0x7b, 0xe0, 0x6d, 0xe8, 0x9f, 0x47, 0xab, 0x75, - 0x05, 0xe4, 0x43, 0x87, 0xce, 0x7f, 0xe6, 0xfd, 0x33, 0x9f, 0xb9, 0xf4, 0xa7, 0xa3, 0x85, 0xd8, 0x1d, 0xf3, 0x37, - 0x06, 0x6f, 0x1b, 0xb1, 0x7b, 0x29, 0x76, 0x5f, 0xf4, 0x9a, 0x33, 0x0f, 0x53, 0x16, 0x5e, 0x41, 0xd0, 0x52, 0x79, - 0x57, 0xf8, 0x9c, 0xb7, 0x85, 0x6d, 0x3e, 0x14, 0x1e, 0xf2, 0xb1, 0xf0, 0x98, 0x4f, 0x6b, 0x4f, 0x4a, 0xb6, 0xd8, - 0xe3, 0xb8, 0x9a, 0xa8, 0x4a, 0x14, 0x7a, 0xf4, 0xc3, 0xc3, 0xa7, 0x52, 0x2a, 0x6b, 0x7c, 0xe3, 0x99, 0x67, 0x05, - 0x1b, 0x94, 0x10, 0x2b, 0xc3, 0x9b, 0x3a, 0x79, 0x75, 0x52, 0x12, 0x09, 0xf5, 0xcc, 0x5a, 0xd5, 0x41, 0x57, 0x49, - 0x59, 0x70, 0xb7, 0xdc, 0x86, 0x62, 0x7b, 0xb2, 0xb8, 0x8c, 0x5a, 0x43, 0xbd, 0xb7, 0x92, 0x19, 0xbd, 0x46, 0xa8, - 0xac, 0xbd, 0xbd, 0x4f, 0x47, 0x28, 0x2d, 0x27, 0x54, 0x25, 0xee, 0x67, 0x68, 0x15, 0x71, 0x86, 0x2d, 0x41, 0xde, - 0x7f, 0x06, 0x4c, 0x5a, 0x38, 0x6a, 0x5d, 0xae, 0xf7, 0x84, 0xd5, 0xe8, 0xd6, 0x12, 0xe9, 0x8b, 0x3c, 0x9a, 0xba, - 0xee, 0xaa, 0xc0, 0xcd, 0x89, 0x33, 0xf4, 0x1a, 0xf9, 0xed, 0xf0, 0xd8, 0x1a, 0xbb, 0xdc, 0xaa, 0xf9, 0x72, 0xfd, - 0xeb, 0xec, 0x3b, 0x2e, 0xc5, 0x84, 0x01, 0xea, 0x39, 0x0a, 0x91, 0x45, 0x0d, 0x17, 0xfc, 0x4a, 0x40, 0x5a, 0x6c, - 0x85, 0x1f, 0xbd, 0xaf, 0x61, 0x72, 0x81, 0x07, 0xa6, 0xbb, 0x75, 0x74, 0x96, 0x9f, 0xdc, 0xff, 0xf0, 0x9b, 0xff, - 0x19, 0x91, 0x13, 0x34, 0x16, 0x99, 0xfe, 0xb3, 0x9d, 0x1c, 0xc5, 0xa4, 0xb9, 0x74, 0x4b, 0xee, 0x6f, 0xc8, 0x60, - 0xea, 0x7d, 0x0d, 0x25, 0x20, 0xf0, 0x00, 0xa4, 0x94, 0x45, 0x75, 0x26, 0x04, 0xd7, 0xe3, 0x85, 0x45, 0x11, 0x5d, - 0x86, 0xf5, 0x10, 0x37, 0xa7, 0x63, 0x73, 0x53, 0x0d, 0xfe, 0x81, 0x98, 0x04, 0xd5, 0xf0, 0x4b, 0x4a, 0xda, 0xe8, - 0x46, 0x48, 0x29, 0x4c, 0xfb, 0x9d, 0x09, 0xfd, 0xe4, 0x47, 0x1f, 0xfa, 0xc2, 0xe7, 0x3e, 0x66, 0x42, 0xdc, 0x52, - 0xd1, 0xfc, 0x6d, 0xe0, 0x35, 0xb3, 0xfd, 0x6e, 0x85, 0x3f, 0xc8, 0xa7, 0xe3, 0xbd, 0x5f, 0x75, 0xbd, 0xb5, 0x39, - 0x75, 0x43, 0x3d, 0xe2, 0xef, 0x11, 0x44, 0x0d, 0x1f, 0x4b, 0xaf, 0xdd, 0x83, 0x84, 0x73, 0xec, 0x62, 0xb8, 0x2a, - 0xd7, 0xc1, 0xc7, 0x79, 0x99, 0xe7, 0xc6, 0x6c, 0x1a, 0xc1, 0x7d, 0xe1, 0x83, 0xcf, 0x38, 0x33, 0x9a, 0x7d, 0xc6, - 0xb2, 0x6d, 0xad, 0x54, 0x3a, 0xe5, 0xda, 0x52, 0xfb, 0x7e, 0x8d, 0xe2, 0x57, 0x58, 0xdb, 0xa6, 0x5d, 0xdb, 0xf4, - 0x4c, 0xd5, 0x78, 0x1d, 0x81, 0x67, 0xc9, 0x1f, 0xc7, 0x56, 0x58, 0xdf, 0xa2, 0x31, 0x0b, 0x6c, 0x4e, 0x6c, 0x97, - 0xa3, 0x97, 0xbf, 0x18, 0xdb, 0xc7, 0xd0, 0x4b, 0x2d, 0x62, 0x8a, 0x90, 0xbe, 0xac, 0xd2, 0xad, 0xa4, 0x89, 0x1e, - 0xdf, 0x43, 0xa8, 0xc2, 0x7e, 0xef, 0x39, 0x08, 0xd0, 0xd8, 0x6b, 0x2e, 0x28, 0x3a, 0xd7, 0xe9, 0x4a, 0x20, 0x74, - 0xe1, 0xf7, 0xa1, 0x7d, 0x53, 0x74, 0xaa, 0x83, 0xb4, 0x0c, 0x54, 0x13, 0x79, 0xf5, 0x3d, 0xb9, 0x1c, 0xe4, 0x2a, - 0xc3, 0x43, 0x8f, 0x0e, 0xdf, 0xe4, 0xe1, 0xd2, 0xc2, 0x4e, 0x24, 0x7e, 0xf3, 0x33, 0xb7, 0x62, 0xde, 0x6f, 0x47, - 0x47, 0x8b, 0x70, 0x50, 0x59, 0xcb, 0x5b, 0x64, 0x3a, 0x54, 0x40, 0x1a, 0xa8, 0xce, 0x12, 0x89, 0xe5, 0xfc, 0x57, - 0xfa, 0xd1, 0x6d, 0x88, 0x1f, 0xdd, 0x54, 0xf4, 0xfa, 0xb8, 0xb7, 0x02, 0xd0, 0x8d, 0xea, 0x33, 0x50, 0x65, 0xe6, - 0x5c, 0x94, 0xbe, 0xbf, 0xc5, 0xfe, 0xbe, 0x76, 0x11, 0x7d, 0xef, 0xb4, 0x7e, 0x76, 0x42, 0x56, 0xce, 0x3f, 0x7d, - 0x84, 0x8d, 0x0a, 0xea, 0xff, 0x81, 0x6b, 0xda, 0xd7, 0x81, 0x4e, 0x9c, 0x5f, 0xca, 0x44, 0x7a, 0x2e, 0x89, 0xcb, - 0x8c, 0x4f, 0x30, 0x0b, 0x24, 0xed, 0xf8, 0xa3, 0x8b, 0xe2, 0x2a, 0x9c, 0xfb, 0x8c, 0x75, 0x9a, 0x37, 0x4e, 0xad, - 0x0d, 0xf6, 0xeb, 0x1b, 0xdd, 0x64, 0x44, 0xd6, 0xb9, 0x39, 0xc3, 0x9a, 0xd1, 0x47, 0x88, 0xe4, 0x16, 0x4d, 0xa8, - 0x8e, 0x19, 0x2c, 0x0f, 0x7a, 0xf0, 0x9b, 0x74, 0xde, 0x6d, 0xc4, 0x96, 0x99, 0x81, 0x47, 0x23, 0xb6, 0xe1, 0x51, - 0x84, 0x0c, 0x32, 0x70, 0xce, 0x77, 0xd2, 0xfd, 0x50, 0x90, 0x8c, 0x0f, 0x8e, 0xcf, 0x1d, 0xdc, 0x74, 0x2f, 0x0b, - 0x64, 0xa5, 0x1e, 0x43, 0x73, 0xb3, 0x20, 0x6a, 0xb3, 0x4d, 0x79, 0x83, 0x2f, 0xf8, 0xd2, 0xf5, 0x8a, 0x54, 0x57, - 0xda, 0x6a, 0xe9, 0x29, 0x2c, 0xcd, 0x82, 0x81, 0x6c, 0x69, 0xb1, 0x2c, 0x62, 0x0c, 0xd2, 0x70, 0x9d, 0x4d, 0x11, - 0x4a, 0x13, 0x84, 0x3a, 0x14, 0x98, 0x12, 0x05, 0x3a, 0x05, 0xe0, 0xa0, 0x9c, 0xd0, 0x5e, 0x07, 0xbf, 0xa7, 0xeb, - 0x65, 0xd6, 0x7e, 0x7f, 0x6f, 0x38, 0x5f, 0x6f, 0x87, 0x67, 0xec, 0xf5, 0xe4, 0xbf, 0x38, 0x83, 0xfc, 0x9a, 0xe6, - 0xe6, 0xaa, 0x67, 0x2c, 0x17, 0x49, 0xb4, 0x3a, 0x7f, 0xf9, 0x26, 0x53, 0x8f, 0x7e, 0xd0, 0xd5, 0x7a, 0xea, 0x6e, - 0xb2, 0x37, 0x8c, 0x0f, 0xd4, 0x7a, 0x19, 0x4b, 0x8c, 0xd5, 0xaa, 0xe8, 0xff, 0xeb, 0x5a, 0xf8, 0x2a, 0x69, 0x0f, - 0x54, 0x17, 0xe2, 0xfe, 0x4a, 0x8f, 0xcf, 0x08, 0x0e, 0x17, 0x6d, 0x17, 0x27, 0x74, 0xa5, 0xd6, 0xa2, 0x42, 0xb7, - 0x86, 0x19, 0x62, 0xaf, 0x2d, 0xf1, 0x2f, 0xfd, 0x24, 0x4b, 0xd1, 0x77, 0xc7, 0xd0, 0xb9, 0xfc, 0xe1, 0x70, 0x75, - 0xac, 0x9a, 0xe6, 0xa7, 0x77, 0xe3, 0xec, 0xf7, 0x30, 0xb7, 0x7e, 0x57, 0xac, 0xe8, 0x08, 0x05, 0x9e, 0xac, 0x4c, - 0xe8, 0xf5, 0xe5, 0x85, 0x32, 0x93, 0xcd, 0x27, 0xcc, 0x40, 0x4f, 0xde, 0x31, 0xd0, 0x8d, 0x53, 0xed, 0x23, 0x67, - 0xc5, 0xff, 0x2c, 0x47, 0x6d, 0xb6, 0x3b, 0x4c, 0x54, 0xef, 0xf6, 0x8e, 0xdc, 0x07, 0xe8, 0x33, 0xe8, 0x23, 0x53, - 0x01, 0xea, 0xb8, 0x55, 0xc5, 0xb0, 0x99, 0xa4, 0xdd, 0x7d, 0x63, 0x7d, 0xac, 0x97, 0x99, 0x63, 0x9f, 0xd8, 0x02, - 0x10, 0xc7, 0x1f, 0x94, 0x55, 0x81, 0xaf, 0xcf, 0xdf, 0xe2, 0x6d, 0xba, 0xcf, 0x68, 0x08, 0x4c, 0x98, 0xa7, 0x3f, - 0x19, 0xa5, 0xf4, 0xfd, 0xe9, 0x89, 0xd2, 0x6b, 0x83, 0x7b, 0x9a, 0x3d, 0x5d, 0x30, 0x9e, 0xfe, 0x43, 0x50, 0x6b, - 0xef, 0xfd, 0x95, 0x5b, 0xeb, 0x3b, 0x48, 0xb3, 0x33, 0xfa, 0xc1, 0x69, 0x0e, 0x72, 0x2c, 0x4a, 0xab, 0xc7, 0xf9, - 0x11, 0xcd, 0x5c, 0x08, 0xf0, 0x21, 0x2b, 0x0e, 0xfa, 0xe7, 0x18, 0x63, 0xae, 0xe0, 0xc7, 0xe8, 0x8f, 0x0e, 0x42, - 0x6d, 0xe5, 0xd3, 0x7d, 0xf1, 0x77, 0x6a, 0xcd, 0x51, 0xeb, 0x59, 0x15, 0xaa, 0xbe, 0x93, 0xb2, 0xda, 0x64, 0x6b, - 0x05, 0xd0, 0xf8, 0x92, 0xe2, 0xfb, 0x3a, 0x24, 0x04, 0x55, 0x48, 0xc0, 0x2d, 0xab, 0xa4, 0x4b, 0xda, 0x2f, 0x39, - 0xbc, 0x91, 0xde, 0x43, 0xd8, 0x88, 0xbb, 0x8d, 0x5d, 0x1f, 0xd2, 0x9f, 0x29, 0xf2, 0x9b, 0x28, 0x63, 0x6c, 0xbd, - 0x71, 0x99, 0x91, 0x03, 0xff, 0x77, 0x37, 0x08, 0x44, 0x3e, 0x2a, 0x98, 0x25, 0xb5, 0xd3, 0x18, 0x62, 0x69, 0x4a, - 0x31, 0xfa, 0x95, 0xcb, 0xfb, 0xb3, 0xf9, 0xff, 0x61, 0x02, 0x93, 0xf1, 0x9f, 0x44, 0x07, 0xed, 0x2a, 0x42, 0xda, - 0x47, 0x44, 0x17, 0x0f, 0x9a, 0x3f, 0x7e, 0x3b, 0x54, 0x0e, 0xb6, 0xb6, 0x05, 0x55, 0xc6, 0x20, 0xf2, 0x1e, 0xc1, - 0x59, 0x43, 0x07, 0x26, 0x7f, 0xc7, 0xb5, 0xe5, 0x14, 0xa2, 0x7d, 0xf5, 0x5d, 0x49, 0xa9, 0x2b, 0x9f, 0x3e, 0xf4, - 0x7f, 0xd3, 0x00, 0x98, 0xd4, 0xa8, 0xbc, 0x4e, 0x5b, 0xbe, 0xf0, 0x7d, 0xd9, 0x54, 0x64, 0xe3, 0xf8, 0xe8, 0x8a, - 0x8e, 0xb7, 0xc6, 0xb8, 0x5f, 0x44, 0x49, 0xab, 0x6b, 0x3f, 0xdd, 0xb4, 0xa0, 0x1b, 0x47, 0x44, 0x8f, 0xf1, 0x2e, - 0xe6, 0xb6, 0x37, 0xaf, 0x12, 0xeb, 0xf8, 0xa8, 0x4d, 0xed, 0x68, 0x33, 0x85, 0x07, 0x76, 0xc0, 0x63, 0x78, 0x6a, - 0xf9, 0x78, 0xb8, 0xe1, 0x10, 0x44, 0xb0, 0x41, 0x02, 0x8c, 0xa4, 0x24, 0x31, 0x65, 0x49, 0xec, 0x71, 0x38, 0xae, - 0xb4, 0x15, 0x3e, 0x9d, 0x4a, 0x77, 0xc8, 0x1f, 0x6a, 0xbc, 0x4f, 0xaa, 0xe1, 0xb1, 0xcf, 0x38, 0x89, 0x5b, 0x89, - 0xfa, 0x51, 0x1e, 0xc4, 0x56, 0xb0, 0xcf, 0x02, 0x5c, 0x55, 0x84, 0xb3, 0x35, 0x0f, 0x1c, 0xc0, 0x06, 0x09, 0x4c, - 0x29, 0xe2, 0x28, 0x8e, 0xef, 0x7e, 0xd2, 0x4f, 0xfc, 0xdc, 0x8a, 0x65, 0x31, 0x2b, 0x48, 0xf2, 0xfe, 0x73, 0x78, - 0x24, 0x4f, 0xcb, 0x9b, 0x24, 0xd9, 0x64, 0xfe, 0x7e, 0x7c, 0x61, 0x4f, 0x2c, 0x7c, 0xc1, 0x0a, 0xa7, 0x3b, 0xb2, - 0xf4, 0x32, 0x6a, 0x5d, 0xfc, 0x05, 0x4e, 0xb0, 0xbf, 0x4d, 0xef, 0x5d, 0x79, 0x75, 0xbf, 0xea, 0x7d, 0x5f, 0xae, - 0x49, 0xed, 0x97, 0x1b, 0x2d, 0x1e, 0x3f, 0x4f, 0x27, 0x5a, 0xb7, 0x8c, 0x3e, 0xf4, 0xbf, 0x79, 0x76, 0x87, 0x20, - 0xfb, 0x49, 0xd6, 0xde, 0x27, 0xb1, 0xed, 0x07, 0x28, 0x72, 0xdd, 0xdc, 0xaf, 0x10, 0x4e, 0xbf, 0xb3, 0xc0, 0x4b, - 0x09, 0x7e, 0x66, 0x83, 0xaa, 0xc7, 0x6a, 0x39, 0xb9, 0xda, 0xc1, 0xa0, 0x1c, 0x2e, 0x78, 0x02, 0xd6, 0x59, 0xcc, - 0x0c, 0x4a, 0xba, 0xa3, 0xd6, 0xdf, 0x3d, 0xc5, 0xf7, 0xda, 0x66, 0x36, 0x26, 0x22, 0xb9, 0x51, 0xf6, 0xb0, 0x74, - 0x11, 0xce, 0xf2, 0x9d, 0xf3, 0xf1, 0xf7, 0x46, 0xc8, 0x19, 0x56, 0xf9, 0x2e, 0x91, 0x93, 0xcf, 0xf8, 0x94, 0x0d, - 0x57, 0x97, 0x1b, 0x2d, 0x36, 0x88, 0x56, 0xf4, 0x95, 0x38, 0x20, 0x51, 0xb4, 0x5b, 0x3c, 0xef, 0x65, 0x48, 0xfe, - 0x36, 0xb9, 0xc6, 0x01, 0x46, 0x2e, 0xb3, 0x9c, 0xc1, 0x17, 0xd7, 0x8c, 0x81, 0xea, 0x57, 0xd3, 0xfb, 0x60, 0x91, - 0x92, 0x51, 0x69, 0x9e, 0xd1, 0xa8, 0x65, 0x2e, 0xc1, 0xf8, 0x0a, 0x0d, 0xfd, 0x88, 0x7d, 0xfa, 0x7c, 0x23, 0x72, - 0x77, 0x0c, 0xeb, 0x3f, 0x8a, 0xef, 0x01, 0x72, 0xec, 0x0d, 0xea, 0x06, 0xd9, 0xb0, 0x48, 0x6a, 0x44, 0xe3, 0x12, - 0xab, 0x74, 0x41, 0x36, 0xb0, 0x7b, 0x61, 0xef, 0x7f, 0xc7, 0x7f, 0xa6, 0x12, 0x09, 0x43, 0x84, 0x2f, 0x36, 0x32, - 0xe8, 0x06, 0x17, 0xc1, 0xf4, 0x19, 0xe1, 0x41, 0x92, 0xa8, 0xbb, 0x62, 0x2c, 0xf0, 0x04, 0x4a, 0x50, 0x32, 0xcf, - 0xe2, 0xea, 0x0e, 0xfa, 0xff, 0xa5, 0x18, 0xd5, 0xe7, 0xed, 0xf2, 0xa6, 0x12, 0xf5, 0xd0, 0x21, 0xc7, 0x79, 0xc1, - 0x17, 0x60, 0xb3, 0x27, 0x4b, 0x5e, 0x02, 0x31, 0x4c, 0xfe, 0x2b, 0x2c, 0x2c, 0x7d, 0x8a, 0xe5, 0x74, 0xf8, 0x97, - 0x6b, 0x16, 0x7b, 0x7b, 0xb8, 0xe9, 0x84, 0x61, 0x7c, 0x4a, 0xf3, 0x05, 0xbd, 0x5d, 0x37, 0x35, 0x6c, 0xe5, 0xc7, - 0x55, 0x16, 0x4f, 0x9d, 0xfb, 0xe5, 0x9b, 0xbc, 0xb8, 0xb4, 0x67, 0x53, 0x75, 0x7e, 0xf0, 0xdc, 0x17, 0xe3, 0x96, - 0xf1, 0xdf, 0xe8, 0x88, 0x97, 0x5f, 0xbc, 0xaf, 0x48, 0xc4, 0xcc, 0x83, 0xcd, 0x7d, 0x5d, 0x90, 0xd3, 0x2f, 0xd1, - 0x3c, 0x2c, 0x57, 0x94, 0x5e, 0x65, 0x76, 0xd5, 0x0f, 0xdf, 0xe4, 0xd9, 0xa5, 0x97, 0x1d, 0xb4, 0xda, 0x7c, 0xaa, - 0x6d, 0xc0, 0xda, 0x02, 0xfa, 0x2f, 0x4b, 0xb5, 0xd9, 0x86, 0x34, 0x5e, 0xa8, 0x7c, 0x57, 0x1d, 0x51, 0x03, 0xfb, - 0x23, 0x3b, 0x6c, 0x78, 0xa0, 0xff, 0x36, 0xbd, 0x9e, 0x3a, 0xb5, 0xaa, 0xb6, 0x3b, 0x09, 0x70, 0xc6, 0x64, 0xad, - 0x62, 0x8c, 0x04, 0xd1, 0x5d, 0x7a, 0xb3, 0x6d, 0x7c, 0x68, 0xda, 0x52, 0xc1, 0xf7, 0xfd, 0x89, 0x61, 0x8a, 0x7b, - 0xda, 0x70, 0xf1, 0x2c, 0x14, 0xf8, 0x9d, 0xb1, 0x43, 0x4f, 0xf4, 0x00, 0x5d, 0x1f, 0x64, 0xb3, 0x58, 0xb6, 0x4b, - 0x20, 0xcf, 0x33, 0xf8, 0xd9, 0x22, 0x96, 0x45, 0xfa, 0x66, 0x46, 0xf7, 0x8f, 0x9a, 0x20, 0x90, 0xb3, 0xa2, 0x2f, - 0x26, 0x05, 0x25, 0x72, 0x54, 0x53, 0x1f, 0xed, 0x4b, 0x9d, 0xa3, 0x2f, 0x36, 0xc2, 0x1a, 0x4a, 0x20, 0xea, 0x0c, - 0xf9, 0xad, 0x52, 0x70, 0xf3, 0xc4, 0x72, 0x81, 0x06, 0x03, 0x25, 0x5c, 0xce, 0x5f, 0xfc, 0x0f, 0xd9, 0x5a, 0xeb, - 0x02, 0x69, 0x65, 0xc3, 0xfc, 0xaa, 0xca, 0xad, 0xe8, 0xe6, 0x3b, 0x34, 0x35, 0xbd, 0x7a, 0x22, 0x54, 0x78, 0xaf, - 0xdc, 0x3f, 0xab, 0xc8, 0xb8, 0x8e, 0x73, 0x48, 0x73, 0x10, 0xc5, 0x33, 0x29, 0x1b, 0x1a, 0x34, 0x53, 0x0e, 0xb2, - 0xaf, 0x32, 0x40, 0xa2, 0xac, 0xea, 0x28, 0xb6, 0xb8, 0xdc, 0xd0, 0x76, 0x89, 0xdb, 0x96, 0x52, 0x9b, 0x48, 0x5b, - 0xbc, 0xc2, 0x23, 0x4b, 0x88, 0x2e, 0x3b, 0x00, 0x85, 0x48, 0x8e, 0xac, 0x7b, 0xae, 0x48, 0xd1, 0xca, 0xed, 0xdb, - 0xb0, 0xe3, 0x3a, 0x42, 0xeb, 0xae, 0xe6, 0xaa, 0x35, 0x6a, 0x34, 0x32, 0xc9, 0xb0, 0x71, 0x6d, 0xf0, 0xaa, 0x04, - 0x35, 0xd4, 0xd8, 0xc6, 0xa1, 0x4c, 0xff, 0xf3, 0xcc, 0x17, 0x33, 0x67, 0x5a, 0x5f, 0xf2, 0xfd, 0x24, 0xb6, 0x48, - 0x45, 0xc3, 0x7e, 0xc6, 0xbe, 0x89, 0x0c, 0x41, 0x8b, 0x8e, 0x58, 0xf5, 0xa9, 0x58, 0xcd, 0x75, 0x32, 0x28, 0x50, - 0x6a, 0xde, 0x38, 0x6d, 0xae, 0x57, 0xe5, 0xdc, 0x23, 0xae, 0x8c, 0x81, 0xdd, 0x9c, 0xdc, 0xb6, 0xf2, 0xbb, 0x99, - 0x9f, 0x36, 0xce, 0x2b, 0x45, 0x86, 0x33, 0xb6, 0x73, 0x52, 0x9f, 0x17, 0x48, 0x0c, 0x97, 0x16, 0xf3, 0x87, 0x0b, - 0x4a, 0x4d, 0x1d, 0x16, 0x8a, 0x24, 0xa7, 0xa5, 0xa9, 0xc0, 0x6f, 0x3f, 0xbc, 0xf6, 0xca, 0x2c, 0x15, 0x0b, 0x02, - 0x2f, 0x14, 0xf3, 0xe7, 0xc2, 0x0e, 0x16, 0xef, 0x33, 0xa1, 0x83, 0x49, 0x9f, 0xf2, 0xdc, 0xe6, 0x26, 0xef, 0xe5, - 0x85, 0xc3, 0xe4, 0xc5, 0x86, 0xe8, 0x67, 0x11, 0x8d, 0x7e, 0x3a, 0xe8, 0x5c, 0x5b, 0xa8, 0x70, 0xe2, 0x09, 0x92, - 0x6c, 0x4a, 0xa1, 0x7b, 0xcd, 0x23, 0x45, 0x52, 0x83, 0x1c, 0xed, 0x7e, 0x27, 0x17, 0xe3, 0xa4, 0xd5, 0x38, 0x2a, - 0xab, 0x24, 0xe1, 0xf3, 0x83, 0xe4, 0x36, 0xa1, 0x44, 0xf9, 0x2c, 0xd2, 0x8c, 0x24, 0x6b, 0xdc, 0x6b, 0x2b, 0xb8, - 0x46, 0xcc, 0xad, 0x0a, 0x06, 0x9b, 0xfd, 0x44, 0xfa, 0xd5, 0x76, 0xf0, 0x26, 0xc5, 0x83, 0x44, 0x09, 0x86, 0x8b, - 0x73, 0xfa, 0xa1, 0x45, 0x47, 0x7e, 0x9d, 0x8d, 0x30, 0x08, 0x0e, 0xa1, 0x14, 0x2a, 0x6b, 0x29, 0x68, 0xe8, 0xbf, - 0x27, 0x6b, 0x87, 0x14, 0x48, 0x04, 0x7c, 0x4e, 0xde, 0x4d, 0x98, 0x12, 0x9c, 0x3c, 0x95, 0x9c, 0x10, 0xae, 0x2a, - 0x16, 0x6f, 0x4a, 0xee, 0x40, 0x79, 0x0c, 0xdc, 0x8a, 0xa0, 0x0b, 0xaa, 0x13, 0x51, 0x2a, 0x70, 0xf4, 0xf6, 0x29, - 0xba, 0xbb, 0x8b, 0x33, 0x58, 0x88, 0x04, 0xf7, 0x2a, 0xb3, 0x4e, 0x6a, 0xc9, 0x51, 0x46, 0x21, 0x9b, 0xcd, 0x46, - 0x34, 0xfa, 0x84, 0x2b, 0x60, 0xe2, 0x49, 0xfc, 0x1f, 0x51, 0x55, 0x13, 0xad, 0xbb, 0xa1, 0xbb, 0x2e, 0x49, 0x1f, - 0x9a, 0x8e, 0x61, 0x5a, 0x5c, 0xb7, 0x13, 0x92, 0x3a, 0xd3, 0x7e, 0x1b, 0x06, 0xcf, 0x6f, 0xce, 0x57, 0x9b, 0x3f, - 0xde, 0x6e, 0xad, 0x44, 0x51, 0xe4, 0x82, 0xc9, 0xc0, 0x91, 0x11, 0x72, 0xd5, 0x45, 0xdd, 0xf1, 0xb0, 0x35, 0x2d, - 0x92, 0xdc, 0xe9, 0xb8, 0xdd, 0x40, 0x35, 0xbe, 0xfc, 0xc6, 0x75, 0x9b, 0xcd, 0x10, 0xf2, 0x76, 0x7f, 0xf0, 0x34, - 0x39, 0x10, 0x55, 0xe5, 0x5f, 0x4a, 0xd6, 0x0f, 0x03, 0x4f, 0x4a, 0x72, 0xe8, 0xa9, 0x30, 0xee, 0xc9, 0xca, 0x44, - 0x87, 0x89, 0x45, 0x24, 0xff, 0x2f, 0x7f, 0x04, 0x4b, 0x4c, 0x71, 0x2d, 0x15, 0xd8, 0x62, 0x7e, 0x58, 0xdd, 0x5b, - 0x19, 0x03, 0x22, 0x97, 0x00, 0x12, 0x21, 0x6f, 0xc8, 0xd7, 0x49, 0xf2, 0xae, 0x70, 0xed, 0x54, 0xaf, 0x79, 0x62, - 0xe6, 0x91, 0xdf, 0xf9, 0x89, 0x79, 0x9c, 0x6a, 0x82, 0x59, 0x82, 0x2b, 0x26, 0x2e, 0x00, 0xaf, 0xf4, 0x17, 0x55, - 0x6e, 0x0a, 0x04, 0x82, 0xb3, 0xaf, 0xd2, 0x9f, 0x14, 0x54, 0x21, 0x6e, 0x47, 0x42, 0x9b, 0x6a, 0x11, 0x9e, 0xd9, - 0x33, 0x0e, 0x2e, 0x36, 0x39, 0x22, 0x03, 0x03, 0x90, 0xe5, 0xa9, 0xd7, 0xc2, 0x3e, 0x9f, 0xf9, 0x37, 0xda, 0x5e, - 0x5b, 0x65, 0x2b, 0x16, 0x3c, 0x78, 0xed, 0xd5, 0x77, 0xb3, 0x4a, 0xd9, 0x2a, 0xb7, 0xfc, 0x86, 0xce, 0xf0, 0x3e, - 0x83, 0x36, 0xd1, 0xf7, 0x1e, 0x0d, 0x56, 0x28, 0xcd, 0x4f, 0x09, 0x93, 0xb0, 0x10, 0xe6, 0x98, 0x6d, 0x27, 0x54, - 0xcf, 0x99, 0xf5, 0xab, 0x14, 0x55, 0xfe, 0x91, 0x63, 0xdc, 0x75, 0xea, 0x5c, 0x98, 0x67, 0xf2, 0x99, 0x92, 0x6c, - 0x58, 0x03, 0xe3, 0x86, 0xe1, 0xdb, 0xfc, 0x8b, 0x9e, 0x0c, 0xed, 0x51, 0xbf, 0xef, 0xd0, 0xf6, 0x30, 0xaa, 0xd3, - 0xad, 0x10, 0x17, 0x5d, 0x18, 0x82, 0x70, 0xf7, 0x29, 0x2f, 0x48, 0xeb, 0xb0, 0xf6, 0x54, 0xa3, 0xc3, 0xa0, 0xc6, - 0x40, 0x9d, 0x16, 0x83, 0xe5, 0xb4, 0x54, 0x50, 0x36, 0x05, 0x33, 0xd5, 0x06, 0x6e, 0xd8, 0x9a, 0xfb, 0x7f, 0xf9, - 0x1f, 0x21, 0xbc, 0x3f, 0xf0, 0x87, 0xf1, 0xbf, 0x97, 0x48, 0x8e, 0x98, 0xb0, 0xa4, 0x92, 0xbb, 0x77, 0x01, 0xe3, - 0x4f, 0xa1, 0xbf, 0x86, 0xf6, 0xa1, 0x1d, 0x43, 0x7b, 0x20, 0xca, 0xe0, 0xfe, 0x6a, 0x29, 0xc6, 0x4e, 0x01, 0x21, - 0xc6, 0xf2, 0xa2, 0x04, 0x2a, 0x29, 0xc5, 0x81, 0x17, 0x15, 0x00, 0xce, 0xbb, 0x40, 0xc7, 0xa6, 0xd8, 0xf6, 0x92, - 0x20, 0x06, 0x15, 0x10, 0x4d, 0x89, 0x9c, 0x93, 0xb4, 0xaf, 0x38, 0xf1, 0x1e, 0x73, 0x72, 0x62, 0x1f, 0xd4, 0xf5, - 0xf9, 0x86, 0xcb, 0xb1, 0x40, 0xd7, 0x15, 0x63, 0x53, 0xb6, 0xa3, 0xcb, 0x8b, 0xd5, 0xcb, 0x5b, 0x31, 0x89, 0x02, - 0xe9, 0xd2, 0x46, 0x5e, 0x90, 0x8f, 0xb8, 0x3d, 0x5b, 0x96, 0x65, 0xf3, 0xa2, 0x65, 0x9c, 0xaf, 0x0c, 0x90, 0x0d, - 0x50, 0xb4, 0xa5, 0x2f, 0x2c, 0xe4, 0xb0, 0x2c, 0x0d, 0xe5, 0x36, 0x70, 0xae, 0xca, 0xf6, 0xe6, 0x4d, 0x82, 0x34, - 0x3f, 0xe4, 0x75, 0xac, 0x4d, 0x2d, 0xb5, 0xff, 0x6e, 0xab, 0x36, 0xec, 0x68, 0x14, 0xcd, 0x81, 0xe9, 0xa8, 0x73, - 0x98, 0x8f, 0x39, 0x17, 0xe4, 0x59, 0xd4, 0xb6, 0x76, 0xbd, 0x95, 0x3c, 0xbf, 0xf1, 0x2a, 0xce, 0x05, 0x0f, 0xab, - 0x3f, 0x3e, 0xb6, 0xd4, 0xc6, 0xf5, 0x2d, 0xbe, 0xf1, 0x07, 0x7f, 0x0f, 0xa2, 0x54, 0x43, 0x0d, 0xe7, 0x2f, 0x27, - 0xe7, 0xb5, 0x7d, 0x02, 0x2c, 0xa7, 0xad, 0xca, 0x7e, 0x9d, 0x57, 0xb1, 0x30, 0x13, 0x99, 0xef, 0xd2, 0x9a, 0xe8, - 0x4b, 0x4d, 0x16, 0x99, 0xd3, 0xf1, 0x37, 0x6d, 0xf8, 0xed, 0xd2, 0x9b, 0x11, 0x42, 0xc9, 0x8c, 0xd0, 0x8c, 0xa3, - 0x9a, 0x37, 0xff, 0xa1, 0xe5, 0xfb, 0xb2, 0x43, 0x0a, 0xee, 0x78, 0x4b, 0x56, 0x43, 0x79, 0x3b, 0x5d, 0x9b, 0x8f, - 0xbc, 0x2c, 0x40, 0xed, 0xa9, 0x54, 0x82, 0x04, 0x7e, 0x4f, 0x1f, 0x9a, 0x87, 0xcd, 0xa6, 0xaa, 0xbd, 0x5e, 0x1f, - 0x1a, 0x13, 0x61, 0x2a, 0x8f, 0x60, 0x71, 0xb9, 0x51, 0x68, 0x67, 0xf8, 0x95, 0xce, 0xb9, 0x19}; + 0x1b, 0xc3, 0x97, 0x11, 0x55, 0xb5, 0x65, 0x2c, 0x8a, 0x8a, 0x55, 0x0b, 0xd0, 0xba, 0x80, 0x1b, 0x32, 0xb0, 0x81, + 0x4f, 0x27, 0x63, 0xf1, 0x7e, 0x88, 0xe3, 0xd8, 0x52, 0x84, 0x55, 0xe8, 0x35, 0x5b, 0x2b, 0x82, 0xe1, 0xed, 0x1f, + 0xfd, 0xde, 0x63, 0x38, 0x3a, 0x71, 0x78, 0xb0, 0x42, 0x17, 0x15, 0x54, 0x23, 0xe1, 0xaa, 0x28, 0x11, 0x94, 0x23, + 0xb4, 0xf4, 0x91, 0x3c, 0xfc, 0xff, 0xab, 0x5a, 0x56, 0x2d, 0x07, 0xcb, 0x09, 0x6f, 0x79, 0x15, 0x1c, 0xd2, 0x87, + 0x40, 0x38, 0x97, 0xce, 0x9d, 0x87, 0x67, 0xe0, 0xa0, 0x4d, 0x49, 0x1a, 0x27, 0xf0, 0xf5, 0x8d, 0x9d, 0x72, 0x02, + 0x12, 0x45, 0x49, 0x2b, 0x48, 0xe0, 0x6a, 0xff, 0x5f, 0x6d, 0x55, 0xf1, 0x54, 0x12, 0xc1, 0x2f, 0x1e, 0xc8, 0x83, + 0x0c, 0x92, 0x0d, 0x75, 0xd8, 0xf5, 0xdd, 0xc7, 0x75, 0x50, 0x6c, 0xa1, 0xb2, 0x85, 0xad, 0x6d, 0x63, 0xd1, 0x96, + 0x38, 0xaa, 0x65, 0x4d, 0x1e, 0x6c, 0x14, 0x4e, 0x10, 0xed, 0xbe, 0xaf, 0xf3, 0xff, 0xeb, 0xf7, 0xc6, 0x6f, 0xd9, + 0x77, 0x24, 0x81, 0xbb, 0x26, 0xd0, 0x31, 0x81, 0xae, 0x49, 0x8d, 0x23, 0xb0, 0x5a, 0x62, 0xe5, 0x49, 0x4a, 0x17, + 0xa7, 0x66, 0xda, 0xb2, 0x6a, 0x9d, 0xf0, 0x4d, 0xa4, 0x1d, 0x59, 0xe6, 0x00, 0x55, 0x58, 0x63, 0xf9, 0x0c, 0xfe, + 0xa0, 0xbd, 0xa5, 0xfa, 0x75, 0x9f, 0xcb, 0x49, 0x22, 0x0c, 0xe1, 0xd5, 0xb0, 0xd8, 0x13, 0x72, 0xd3, 0x25, 0x4e, + 0x48, 0x1b, 0xa2, 0x76, 0x4f, 0x5c, 0x42, 0xe2, 0x98, 0x6d, 0x9b, 0x80, 0x3e, 0x69, 0x90, 0xcf, 0x69, 0xa5, 0x2e, + 0xc0, 0x47, 0x4f, 0x5c, 0xac, 0x83, 0x99, 0xe7, 0xfc, 0xff, 0xdf, 0x96, 0x7e, 0xa5, 0xd5, 0x2d, 0x98, 0x45, 0x4a, + 0x81, 0x52, 0x20, 0x67, 0x6d, 0x8d, 0xbd, 0xc4, 0x49, 0xb0, 0x41, 0xa8, 0xba, 0xf7, 0xbe, 0x77, 0x47, 0x45, 0x3d, + 0xea, 0xaa, 0x52, 0xcf, 0x6f, 0xb2, 0x2d, 0xea, 0x11, 0x1f, 0x0b, 0x6d, 0x7e, 0xef, 0x55, 0x75, 0xab, 0xaa, 0x5b, + 0xf6, 0x74, 0x4b, 0xf6, 0x18, 0xe7, 0x1c, 0x59, 0xf6, 0xfe, 0x01, 0xd2, 0xff, 0x8b, 0xe4, 0xf9, 0xe7, 0x2c, 0x52, + 0x84, 0x51, 0x02, 0x9c, 0xed, 0xc9, 0x31, 0x0a, 0x01, 0xd3, 0xcd, 0x36, 0xdc, 0x74, 0x55, 0x87, 0x2a, 0x51, 0x4e, + 0xcf, 0x28, 0xc5, 0x71, 0xec, 0x2d, 0x23, 0x97, 0xcb, 0x55, 0x7d, 0xfd, 0xd6, 0x83, 0x1d, 0xc6, 0x0a, 0x21, 0x9e, + 0x5d, 0x46, 0xd3, 0xfc, 0xcd, 0xca, 0x21, 0x21, 0x24, 0xce, 0x75, 0x5d, 0x7f, 0xa6, 0x0d, 0xf7, 0x70, 0x16, 0xd1, + 0xc4, 0x38, 0xe2, 0x00, 0xf9, 0x14, 0x84, 0xa1, 0x23, 0x9d, 0x6e, 0xcc, 0x71, 0xee, 0xa1, 0xc8, 0x1a, 0xc1, 0xb4, + 0xda, 0x43, 0x30, 0xcf, 0xe1, 0xc0, 0x01, 0x34, 0xb2, 0x3c, 0xb7, 0x7f, 0xf5, 0x81, 0xad, 0xdb, 0xf5, 0x23, 0x32, + 0xe8, 0xf1, 0x66, 0xa5, 0x04, 0xdc, 0x46, 0x71, 0x3d, 0x0e, 0x94, 0x8d, 0x00, 0x35, 0xab, 0xb1, 0x1b, 0x92, 0xef, + 0xcd, 0xef, 0x3f, 0x1d, 0x1c, 0x84, 0x98, 0xe9, 0x3f, 0x54, 0xae, 0x9d, 0x84, 0x17, 0xa2, 0x2e, 0x69, 0x5b, 0xc0, + 0xd5, 0x10, 0x62, 0x1e, 0x06, 0x1e, 0xa2, 0xe0, 0xb5, 0xd7, 0xe2, 0xe9, 0xb4, 0xc6, 0x33, 0x43, 0xc6, 0x96, 0x8b, + 0x5c, 0x0f, 0xd4, 0x5c, 0x18, 0x1c, 0x0e, 0xba, 0x54, 0x85, 0xf3, 0x4c, 0x2e, 0xa2, 0x4d, 0xd7, 0x9a, 0x23, 0xba, + 0x9a, 0xf4, 0xba, 0xa4, 0xf4, 0xdc, 0xdf, 0x7c, 0x53, 0x67, 0xdc, 0x17, 0x7a, 0x7e, 0x49, 0x87, 0x3f, 0xe3, 0xbc, + 0x98, 0x12, 0x88, 0xe8, 0x78, 0x4f, 0x91, 0x72, 0x75, 0x32, 0xc8, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0x83, 0x7d, + 0x06, 0x6e, 0x11, 0x1b, 0xc7, 0xf9, 0x71, 0x99, 0x5f, 0x17, 0x63, 0x5e, 0x35, 0xf3, 0xd5, 0xe1, 0x70, 0xd9, 0xbb, + 0xc1, 0x75, 0x93, 0x66, 0x1f, 0xd6, 0x83, 0xa5, 0xdb, 0x37, 0x7f, 0x59, 0xd3, 0xe6, 0x66, 0x37, 0x45, 0x5b, 0x5b, + 0x7e, 0xf1, 0xd4, 0xd3, 0x0b, 0xb5, 0x90, 0xaf, 0xeb, 0x69, 0xc2, 0xcd, 0x5c, 0x30, 0xca, 0x16, 0xda, 0x1d, 0xf0, + 0xb9, 0xea, 0xb2, 0xfc, 0xba, 0x5d, 0x25, 0xf3, 0xe3, 0xe4, 0x1b, 0xf1, 0xdb, 0x25, 0x73, 0x7d, 0x31, 0x43, 0x95, + 0x9a, 0x88, 0x6a, 0xf8, 0x47, 0x20, 0x2d, 0xb7, 0xd7, 0x78, 0x6f, 0xe2, 0xbb, 0xa1, 0x85, 0x75, 0xa4, 0xae, 0x6a, + 0x11, 0x25, 0xb7, 0xdf, 0xcd, 0xab, 0xa1, 0x2c, 0x20, 0xff, 0xd6, 0x84, 0xc8, 0x33, 0xee, 0x86, 0x44, 0x55, 0x79, + 0x98, 0x27, 0x37, 0x80, 0x50, 0xa9, 0x8e, 0x88, 0xb5, 0xcc, 0x13, 0xf0, 0x74, 0x38, 0xc7, 0xd8, 0x86, 0xc0, 0x7b, + 0x1d, 0x9e, 0xa6, 0x3b, 0xf3, 0xc3, 0xb5, 0x00, 0x77, 0xc3, 0xca, 0x83, 0x98, 0xba, 0x41, 0x85, 0x3c, 0xd9, 0x29, + 0xc8, 0x79, 0x52, 0x60, 0x25, 0xbb, 0xa6, 0x39, 0xca, 0x76, 0xf2, 0xa6, 0x7d, 0x57, 0xa3, 0xcc, 0xd6, 0xb8, 0xe7, + 0xcd, 0xdf, 0xf9, 0x24, 0x84, 0x14, 0x7f, 0x63, 0x51, 0x9b, 0x98, 0x4a, 0x48, 0xb8, 0x74, 0x9a, 0x74, 0xbf, 0xf1, + 0x9d, 0x48, 0x62, 0x9e, 0xe7, 0x8a, 0x92, 0x75, 0xc8, 0x64, 0x1b, 0xbf, 0xde, 0x54, 0x9b, 0xb6, 0x5c, 0x42, 0xc3, + 0x1a, 0x1e, 0x3f, 0xa7, 0x59, 0xa4, 0x90, 0x50, 0xb2, 0xa7, 0x25, 0x61, 0x65, 0x41, 0xde, 0x83, 0x2f, 0x53, 0x38, + 0x7c, 0xb9, 0xd3, 0xe7, 0x0b, 0x42, 0x59, 0xb8, 0xa9, 0xc0, 0xc4, 0x7b, 0x1b, 0x2b, 0xcd, 0xd7, 0x51, 0x43, 0x30, + 0x93, 0x3f, 0x13, 0xd6, 0x31, 0xfe, 0x55, 0x33, 0xb5, 0x25, 0x44, 0x09, 0x3e, 0xfc, 0x5c, 0x85, 0xac, 0x1b, 0xc1, + 0xd4, 0xb4, 0x54, 0xf2, 0x05, 0x97, 0x72, 0x0e, 0x24, 0x80, 0x50, 0x03, 0x26, 0x7f, 0xce, 0x9a, 0xbe, 0x9f, 0xf1, + 0xf2, 0x7e, 0xc4, 0x9b, 0x26, 0x24, 0x96, 0x37, 0x92, 0x0d, 0x75, 0xff, 0x64, 0xa0, 0xec, 0x38, 0xa6, 0x7a, 0xc8, + 0x7c, 0x1f, 0x76, 0x7b, 0x1a, 0x19, 0x21, 0xc8, 0x7d, 0x33, 0x42, 0xc3, 0x6c, 0x5e, 0xf0, 0x0b, 0x41, 0xaf, 0x8c, + 0x34, 0xa9, 0x8a, 0x2a, 0xbc, 0xff, 0xf5, 0x0b, 0x21, 0x7a, 0x1c, 0xea, 0xd1, 0xff, 0x4e, 0xe9, 0x2e, 0xd5, 0x12, + 0xc3, 0x7a, 0x28, 0xbc, 0x54, 0xe7, 0x95, 0xaa, 0xcd, 0x05, 0x02, 0x30, 0xe4, 0x56, 0x22, 0xfb, 0x9b, 0x91, 0x04, + 0xec, 0x30, 0x53, 0xfe, 0x75, 0x2d, 0xc2, 0x32, 0xc1, 0xe5, 0xcf, 0x59, 0x65, 0xaf, 0xe2, 0x93, 0x94, 0x3e, 0x9a, + 0x23, 0xaa, 0x2c, 0x61, 0x7c, 0x59, 0x10, 0xa4, 0x3c, 0x9b, 0x17, 0x9b, 0xc6, 0x8d, 0xdc, 0x51, 0x7b, 0x10, 0xaf, + 0x72, 0x1d, 0xc7, 0x12, 0x95, 0xad, 0x72, 0x02, 0x90, 0x3c, 0xbb, 0xef, 0x06, 0x61, 0xb0, 0x9c, 0x10, 0xa9, 0x2e, + 0x23, 0xfc, 0x73, 0xae, 0x0a, 0x6e, 0x25, 0x9a, 0x55, 0xcd, 0xfd, 0x37, 0xe8, 0x62, 0xb7, 0xe0, 0x8e, 0xcf, 0xeb, + 0xb9, 0xe1, 0x2a, 0xbc, 0x29, 0xfc, 0xb6, 0x64, 0x90, 0x5e, 0x59, 0x8e, 0x26, 0xd1, 0xaa, 0x8e, 0x38, 0x89, 0x68, + 0x81, 0xb1, 0xd9, 0x7f, 0xd2, 0xe2, 0xbd, 0xa0, 0x13, 0x2a, 0x6d, 0x2f, 0xd5, 0xe5, 0x74, 0xc6, 0x0f, 0x2e, 0xa8, + 0xd7, 0xc5, 0xf9, 0x94, 0x45, 0x50, 0xe1, 0xdb, 0xd4, 0x9f, 0xe9, 0x9c, 0x7a, 0x9f, 0x2f, 0x37, 0xcd, 0x73, 0x8f, + 0x65, 0xb7, 0x5b, 0x6b, 0x14, 0xb7, 0xae, 0x42, 0x6a, 0xc3, 0x8d, 0x97, 0x71, 0x5b, 0x2b, 0x28, 0xae, 0x08, 0x4f, + 0xb5, 0xa6, 0x89, 0x34, 0x76, 0x89, 0x53, 0x36, 0xc6, 0xfb, 0x77, 0x4b, 0xdc, 0x57, 0x4b, 0x99, 0x32, 0xc4, 0x34, + 0x3c, 0xa1, 0xee, 0x5e, 0x9a, 0x1a, 0x0c, 0x0b, 0x1e, 0xbb, 0x45, 0x7c, 0x21, 0x55, 0x09, 0x0a, 0x46, 0xe5, 0x34, + 0x4f, 0xbc, 0x78, 0xe8, 0x5d, 0xb0, 0x04, 0x88, 0xb7, 0xe8, 0xf2, 0x7e, 0x01, 0xc1, 0x8a, 0xd6, 0x0a, 0xb8, 0x13, + 0x4d, 0x90, 0xf0, 0x02, 0x1d, 0x06, 0x19, 0xea, 0x0d, 0xc8, 0x66, 0x95, 0xe8, 0x9d, 0xb3, 0x63, 0x50, 0x5a, 0xcd, + 0xa2, 0xbd, 0x76, 0x9e, 0xde, 0x05, 0xb6, 0xe4, 0xfc, 0x9c, 0x66, 0x63, 0xc6, 0x48, 0x9c, 0x5e, 0x14, 0x31, 0x65, + 0x9e, 0xa8, 0xb9, 0xb6, 0x44, 0x75, 0x9a, 0xbb, 0x3b, 0x63, 0xc6, 0x89, 0xfd, 0x7a, 0x15, 0x7d, 0xd7, 0xc7, 0x55, + 0xcd, 0x80, 0x0b, 0xcc, 0x86, 0xb5, 0xf1, 0xff, 0x69, 0x28, 0x94, 0x82, 0xbf, 0x9a, 0x75, 0x83, 0xe2, 0x5e, 0x2c, + 0xa7, 0xae, 0x27, 0x42, 0xd7, 0xdf, 0x19, 0xd8, 0x8f, 0x77, 0x84, 0x4f, 0x50, 0x46, 0x36, 0x76, 0xfb, 0xa6, 0x34, + 0xc2, 0xf5, 0x2a, 0xf9, 0xbc, 0x7f, 0x6a, 0xfb, 0x86, 0xfa, 0xfc, 0x58, 0x1c, 0xfb, 0x57, 0x6f, 0x28, 0xa6, 0x0e, + 0xdc, 0xc5, 0xec, 0xb9, 0x68, 0xbe, 0xb5, 0xce, 0xd1, 0x83, 0x87, 0xfc, 0x30, 0xec, 0x9d, 0x6e, 0x2c, 0xa6, 0xa6, + 0x8d, 0x07, 0x1a, 0x43, 0x02, 0xbf, 0x66, 0x0e, 0x6b, 0xf5, 0x40, 0x1c, 0xb1, 0x6a, 0x93, 0x53, 0x91, 0xfa, 0x8d, + 0x2a, 0x63, 0x85, 0x79, 0x2d, 0xae, 0x64, 0x21, 0x95, 0x75, 0x18, 0x28, 0x64, 0xa4, 0x3d, 0xa3, 0xdc, 0xb3, 0x82, + 0x87, 0xb9, 0xfe, 0x5d, 0x70, 0x87, 0xaf, 0xef, 0xed, 0x87, 0x26, 0xbe, 0x85, 0xf1, 0xa2, 0xec, 0x54, 0x66, 0x89, + 0x72, 0xcc, 0x02, 0x51, 0x24, 0xcf, 0x88, 0xe6, 0xf8, 0x9a, 0x8d, 0x21, 0x01, 0x72, 0x23, 0x20, 0xc7, 0xdd, 0x7b, + 0xc5, 0xb1, 0x4d, 0x88, 0x40, 0xa1, 0xdd, 0x2d, 0x90, 0x85, 0x82, 0x4c, 0x12, 0x49, 0xee, 0x8e, 0x86, 0x12, 0xfb, + 0x63, 0xf5, 0xd2, 0x85, 0x5b, 0x44, 0xb2, 0xb1, 0x1b, 0x12, 0x08, 0xa4, 0xf1, 0x3e, 0xd5, 0xe7, 0x02, 0x61, 0x29, + 0x40, 0xc7, 0xc1, 0x3f, 0x49, 0x09, 0xab, 0x99, 0x0c, 0x69, 0x36, 0x70, 0x57, 0xe6, 0x65, 0x37, 0xec, 0x7f, 0x67, + 0xa3, 0x02, 0xc2, 0xf1, 0xa1, 0x7f, 0xec, 0x26, 0x28, 0x32, 0x50, 0xb4, 0x42, 0x3d, 0x14, 0x94, 0x6e, 0x28, 0x62, + 0x50, 0xed, 0x8f, 0x9b, 0xc2, 0xdc, 0xdd, 0xc0, 0x64, 0x89, 0x8a, 0xd6, 0x3c, 0x79, 0x2f, 0xea, 0xdb, 0x88, 0xc1, + 0x27, 0x33, 0x76, 0xe8, 0x66, 0xa2, 0x92, 0x5d, 0xaa, 0x0c, 0xac, 0x83, 0x75, 0x2a, 0x95, 0x02, 0x2f, 0x6a, 0x72, + 0xf7, 0x2d, 0x20, 0x2a, 0xde, 0xa9, 0x8b, 0xce, 0xa0, 0x85, 0x57, 0x5a, 0xe8, 0x0c, 0xfa, 0xe5, 0x8c, 0x42, 0xd2, + 0xb1, 0xa6, 0x76, 0xb9, 0x4e, 0x54, 0x0c, 0xf6, 0x84, 0x0d, 0x4a, 0xb4, 0xfc, 0x43, 0x9b, 0x92, 0x88, 0x30, 0xd7, + 0x3d, 0x1f, 0xfe, 0x71, 0x66, 0x48, 0x1f, 0xde, 0xea, 0x21, 0x95, 0x24, 0xc2, 0x27, 0x7c, 0x39, 0x88, 0xd7, 0x1d, + 0x90, 0x14, 0xb8, 0x77, 0x5d, 0xb1, 0x76, 0x2f, 0x3b, 0xe2, 0xe5, 0x64, 0x4b, 0xcd, 0xb8, 0x2e, 0x53, 0xd0, 0xa8, + 0xe3, 0x78, 0xcb, 0xa7, 0xb0, 0xe1, 0x5d, 0xe9, 0x33, 0x3a, 0x16, 0x98, 0x25, 0x90, 0x08, 0x91, 0xde, 0x3f, 0xba, + 0x73, 0xa1, 0xe6, 0x75, 0x92, 0x19, 0x0a, 0x91, 0x5a, 0x25, 0x37, 0x41, 0x85, 0xe3, 0xa9, 0x42, 0xec, 0x48, 0x4a, + 0xca, 0x84, 0x23, 0x4c, 0x8f, 0x2b, 0xa2, 0xa3, 0xe4, 0x3e, 0x69, 0x2a, 0x19, 0x73, 0xf5, 0xbf, 0x4c, 0x69, 0x82, + 0xd9, 0x95, 0xc3, 0x21, 0x11, 0x20, 0x65, 0x5a, 0x6a, 0x37, 0x78, 0x3f, 0x22, 0x3e, 0x15, 0x80, 0x4a, 0x44, 0xa2, + 0x70, 0xcf, 0x2e, 0xfa, 0xb3, 0x28, 0x21, 0x62, 0x30, 0x13, 0xd3, 0x59, 0xf2, 0xfe, 0x5a, 0xe9, 0xe4, 0x75, 0xa3, + 0xab, 0x51, 0xcd, 0xeb, 0x07, 0x95, 0x8f, 0x98, 0x2b, 0x97, 0x4f, 0x02, 0x19, 0x5b, 0x4d, 0xae, 0xa9, 0xcc, 0xb3, + 0xb2, 0xb8, 0x0a, 0x0b, 0x54, 0x1b, 0xb5, 0x80, 0xeb, 0x73, 0x9d, 0xdb, 0x10, 0x75, 0xce, 0x41, 0xe4, 0x80, 0x1d, + 0x56, 0xb3, 0xd0, 0xd9, 0x31, 0x7d, 0x70, 0x99, 0x1c, 0xe1, 0x34, 0x9d, 0xb9, 0x63, 0x68, 0xa7, 0xf7, 0x22, 0x39, + 0x0c, 0x2e, 0x56, 0xa0, 0x0b, 0x28, 0xa7, 0x86, 0x31, 0x8a, 0x1c, 0x50, 0x62, 0xa9, 0x94, 0x72, 0x01, 0x40, 0x8b, + 0xa2, 0xab, 0xa0, 0x0c, 0x85, 0x2a, 0x69, 0x64, 0x0b, 0x07, 0x2b, 0x8e, 0x11, 0xaf, 0xbd, 0xfa, 0x21, 0x10, 0xb2, + 0x68, 0xbb, 0x06, 0xea, 0x40, 0xa9, 0xe6, 0xad, 0x7f, 0x17, 0xb9, 0xe8, 0xc2, 0xb3, 0x32, 0x40, 0x99, 0x3f, 0xaa, + 0x36, 0xeb, 0x4e, 0x26, 0x2f, 0xae, 0x8c, 0x17, 0xaa, 0x6c, 0x78, 0x90, 0x3c, 0x4b, 0x64, 0x4a, 0x28, 0x70, 0xca, + 0x92, 0xc6, 0x3e, 0xf1, 0xc1, 0x8e, 0xfc, 0xf6, 0x84, 0xb9, 0x39, 0x56, 0x46, 0x35, 0xe2, 0xe9, 0x8b, 0xaa, 0xeb, + 0x9a, 0x21, 0x42, 0xcd, 0x3f, 0x7c, 0xed, 0xac, 0xff, 0xa6, 0x1b, 0x8d, 0xde, 0x91, 0x75, 0xd6, 0xe4, 0xdf, 0x86, + 0xc1, 0x9d, 0xce, 0x9e, 0xd5, 0x55, 0x83, 0x58, 0x2b, 0x28, 0x02, 0xe1, 0x80, 0x07, 0xbf, 0xa9, 0x8e, 0xf6, 0x9b, + 0x80, 0x25, 0xef, 0x18, 0xda, 0x93, 0xea, 0x8a, 0x09, 0x4d, 0xcb, 0xe7, 0x1f, 0x41, 0x73, 0xa5, 0x86, 0xb2, 0x2c, + 0xf8, 0xf0, 0x01, 0x65, 0x06, 0xa5, 0xca, 0x51, 0x3b, 0xdd, 0x86, 0x5c, 0x13, 0x68, 0xa2, 0x27, 0x41, 0x9e, 0xaf, + 0xbf, 0x70, 0x57, 0xa5, 0x32, 0x90, 0x6f, 0x98, 0xec, 0xc2, 0x5d, 0xb2, 0xba, 0xca, 0x39, 0xfb, 0x2f, 0x51, 0xcc, + 0xf3, 0xbc, 0xa7, 0x23, 0x23, 0xbd, 0x67, 0x47, 0x6e, 0x6a, 0xc5, 0xf9, 0x29, 0x4a, 0x48, 0x16, 0x6d, 0x59, 0x68, + 0xcb, 0x11, 0x8c, 0x81, 0x12, 0x3a, 0x12, 0xb9, 0x0c, 0x59, 0xd6, 0xb0, 0xcc, 0xbe, 0xe5, 0x7f, 0xe3, 0x90, 0x49, + 0x4a, 0x72, 0x9a, 0x5c, 0xf7, 0xb2, 0xb8, 0xec, 0xca, 0x12, 0x95, 0xd8, 0x51, 0x6b, 0xba, 0x12, 0x43, 0xf2, 0xd5, + 0x7b, 0xda, 0xb4, 0xd4, 0x7e, 0x84, 0x74, 0x67, 0x46, 0x0a, 0xfa, 0xa0, 0xea, 0x6d, 0x74, 0xc1, 0xd1, 0x06, 0x90, + 0x63, 0x49, 0xf2, 0x3c, 0x29, 0x06, 0xd9, 0x44, 0x0a, 0x25, 0xea, 0x49, 0x0e, 0x63, 0x59, 0xc2, 0xdc, 0x8f, 0x12, + 0xcc, 0xd2, 0xb2, 0x8c, 0x91, 0x3e, 0x2d, 0x62, 0xa7, 0x14, 0x8f, 0x50, 0xf9, 0x38, 0xbb, 0xef, 0xa6, 0xa1, 0x24, + 0xd5, 0x49, 0x99, 0x20, 0x68, 0xcf, 0x81, 0xd0, 0x31, 0x01, 0xf3, 0xbd, 0xa9, 0xe8, 0x2f, 0x7f, 0x8e, 0x2b, 0x16, + 0xf6, 0x1f, 0x52, 0x3c, 0x33, 0xb3, 0x9b, 0x5f, 0x59, 0xce, 0x91, 0xe5, 0xcc, 0xd0, 0x49, 0x9b, 0x42, 0x0a, 0x1b, + 0x67, 0xbb, 0xfe, 0x82, 0x34, 0xef, 0x8d, 0x0e, 0x47, 0x7a, 0x09, 0xbf, 0x2f, 0x04, 0xd7, 0x87, 0x24, 0x8c, 0x90, + 0xab, 0x2e, 0xaa, 0xdd, 0x3c, 0x79, 0x91, 0xc2, 0x6a, 0x47, 0x47, 0x5c, 0x8a, 0xdd, 0xdb, 0x59, 0xc4, 0x5a, 0x91, + 0x0a, 0xf6, 0xbd, 0x32, 0x91, 0x89, 0xcd, 0xa0, 0x04, 0x67, 0x2b, 0x03, 0x7a, 0x56, 0xbb, 0x78, 0x26, 0xaa, 0xa3, + 0x26, 0xd4, 0x59, 0x81, 0x67, 0xa8, 0x01, 0x64, 0xeb, 0xbc, 0x69, 0xc9, 0x9e, 0x0e, 0x96, 0x93, 0xd4, 0x50, 0x9a, + 0x45, 0x04, 0xfe, 0xd0, 0xdd, 0xde, 0x93, 0x88, 0x0c, 0x03, 0x3f, 0xce, 0x46, 0x94, 0x07, 0xa8, 0x19, 0xc3, 0x89, + 0xa5, 0x49, 0x92, 0x35, 0x5c, 0x98, 0xf7, 0x56, 0x04, 0x71, 0xdf, 0xc7, 0xb6, 0x88, 0xfa, 0xdb, 0x51, 0x26, 0xd8, + 0x57, 0xeb, 0x04, 0xa2, 0x62, 0x16, 0xca, 0xe4, 0x5b, 0x42, 0x78, 0xcb, 0x03, 0xc3, 0xd5, 0xf9, 0x86, 0xd9, 0x58, + 0xb5, 0x92, 0x23, 0x5f, 0x55, 0x0b, 0x3b, 0x20, 0x1c, 0xb5, 0x2f, 0x1d, 0xeb, 0x67, 0xb7, 0x2a, 0x7a, 0x3d, 0x2d, + 0xbf, 0xda, 0xd4, 0x95, 0xaa, 0x03, 0xb9, 0x18, 0xa3, 0x6c, 0xc6, 0xa4, 0xd1, 0x00, 0xb5, 0x80, 0x5c, 0x59, 0x47, + 0xaa, 0x78, 0x9a, 0x96, 0x70, 0x88, 0x07, 0x1e, 0xaf, 0xae, 0x1d, 0xe9, 0x25, 0xdb, 0xa1, 0x03, 0xda, 0x7a, 0x87, + 0x6f, 0xbd, 0x76, 0x2d, 0xc6, 0x8d, 0x05, 0xbc, 0x01, 0xa0, 0x12, 0x95, 0x0a, 0x2a, 0xd1, 0x20, 0xe5, 0x52, 0xc5, + 0x75, 0xd0, 0x29, 0xd7, 0xb4, 0x58, 0x59, 0x2b, 0xbc, 0xcb, 0x03, 0xfc, 0x69, 0x07, 0xa4, 0xb2, 0xae, 0x82, 0x62, + 0xd1, 0xfd, 0x16, 0x84, 0x14, 0xe2, 0xcd, 0xf4, 0xcd, 0x1c, 0xcc, 0xc9, 0x92, 0x35, 0x5f, 0xcb, 0x13, 0x61, 0xb1, + 0x72, 0x6b, 0x4e, 0xce, 0x91, 0x51, 0x49, 0xdf, 0xde, 0x03, 0xa2, 0x6e, 0x76, 0x79, 0xbf, 0xf8, 0xd1, 0x33, 0xee, + 0x29, 0xf0, 0xf1, 0x76, 0xbf, 0x1b, 0x1c, 0x7e, 0x78, 0xcb, 0xe1, 0x90, 0x33, 0x48, 0x43, 0x1a, 0x1b, 0xc8, 0x10, + 0xbc, 0x58, 0x15, 0x16, 0xfc, 0xb1, 0x6e, 0x75, 0x89, 0xe8, 0x3c, 0x05, 0xfc, 0x3d, 0x73, 0x17, 0xba, 0x3f, 0x20, + 0x72, 0x17, 0xf2, 0x78, 0xde, 0x65, 0x52, 0x3e, 0x42, 0x1a, 0x49, 0xee, 0xdf, 0x47, 0x9a, 0xca, 0xe4, 0x7c, 0xf3, + 0x97, 0x3c, 0x2a, 0x54, 0xd6, 0xc1, 0x14, 0x1a, 0x94, 0xd4, 0x39, 0x60, 0xd0, 0x46, 0xc6, 0x55, 0xbd, 0x1c, 0x3a, + 0x69, 0xf5, 0x79, 0xb6, 0x07, 0x99, 0x22, 0x10, 0x9d, 0x1e, 0x94, 0x51, 0x06, 0x42, 0x00, 0xbc, 0x80, 0x00, 0x68, + 0x09, 0x06, 0x03, 0xf8, 0x48, 0xf7, 0x74, 0xd0, 0x98, 0x8c, 0xd3, 0xa7, 0x92, 0x0c, 0x75, 0xa9, 0xfc, 0x9a, 0x58, + 0x8f, 0x92, 0x25, 0x62, 0x52, 0x41, 0x0b, 0xc5, 0x8c, 0xe2, 0x53, 0xf3, 0xce, 0xdc, 0xd2, 0xfb, 0x92, 0x19, 0xc6, + 0x99, 0x66, 0xa9, 0xd3, 0x46, 0xf2, 0x91, 0xba, 0x4f, 0x79, 0xb0, 0x4a, 0x10, 0x9e, 0x12, 0xaa, 0x32, 0x3c, 0xd4, + 0x35, 0x53, 0x8a, 0x67, 0x38, 0x86, 0xe3, 0xf2, 0xad, 0x45, 0xea, 0xe0, 0x83, 0xc4, 0xa7, 0xef, 0x63, 0xa8, 0xad, + 0xf9, 0xe3, 0xaf, 0x1d, 0x09, 0xbf, 0x8c, 0x32, 0xcc, 0x95, 0x88, 0x03, 0x2d, 0x53, 0x60, 0x87, 0x0b, 0x3d, 0x4f, + 0xbc, 0xdc, 0x97, 0xb8, 0xa3, 0x40, 0x0f, 0x46, 0xec, 0xa9, 0x0f, 0x99, 0xdb, 0x33, 0x91, 0xb5, 0x2d, 0xea, 0xf5, + 0xdf, 0x17, 0xdf, 0xe5, 0xc9, 0xed, 0x98, 0x27, 0x75, 0x8a, 0x0a, 0xb4, 0x52, 0x7b, 0xcb, 0x7c, 0x5f, 0xcc, 0xc2, + 0xa3, 0xef, 0x56, 0xc8, 0x18, 0x43, 0x33, 0xf2, 0x60, 0x63, 0x44, 0x50, 0x16, 0x3b, 0x98, 0xdf, 0x29, 0x24, 0x3f, + 0x3e, 0xc8, 0x41, 0x23, 0x0a, 0x82, 0xaa, 0xfd, 0x05, 0x85, 0xb2, 0x30, 0xf6, 0x37, 0xbe, 0xf6, 0x3d, 0xb2, 0xea, + 0x14, 0xcb, 0xe3, 0xec, 0x33, 0x3e, 0x67, 0x71, 0xc5, 0xaa, 0x05, 0x59, 0x91, 0x7b, 0x25, 0x9e, 0x8e, 0x59, 0xda, + 0x66, 0xd1, 0xb4, 0x4e, 0x00, 0xef, 0x63, 0xe7, 0xb6, 0xdc, 0x0f, 0xb5, 0xfe, 0x08, 0xe2, 0xea, 0x8b, 0xb0, 0xf6, + 0x3c, 0x08, 0x2b, 0xaf, 0xa2, 0x40, 0x31, 0x6d, 0x4b, 0x7e, 0xde, 0xdb, 0xcf, 0xd8, 0x46, 0xf1, 0x44, 0xb6, 0x9b, + 0xf7, 0xb6, 0x67, 0xdb, 0x38, 0x65, 0x4a, 0xfd, 0x6d, 0xae, 0x0f, 0xfe, 0x0f, 0x11, 0x3f, 0xe6, 0x40, 0xbf, 0x5f, + 0xac, 0xa6, 0xf9, 0xa9, 0xf9, 0x64, 0x85, 0xd2, 0x07, 0xf0, 0xe2, 0xb2, 0x79, 0x31, 0x7a, 0xb5, 0xf6, 0x52, 0xc4, + 0xf2, 0x20, 0xf4, 0x2d, 0x62, 0x68, 0x3b, 0xc8, 0x2e, 0xdf, 0xcf, 0x05, 0xba, 0x60, 0xac, 0x47, 0xbf, 0x01, 0x9e, + 0xb4, 0xda, 0x38, 0x64, 0xe0, 0x32, 0x99, 0x73, 0x13, 0x24, 0xdd, 0x07, 0x55, 0xbf, 0xb7, 0xaf, 0xf2, 0xb8, 0xa2, + 0x07, 0x2e, 0xa8, 0x30, 0xdd, 0x71, 0xd7, 0xb5, 0xba, 0xfa, 0xdb, 0x1d, 0x78, 0x9e, 0x1b, 0xed, 0x45, 0xef, 0x6f, + 0xe2, 0x50, 0xc4, 0x95, 0xec, 0x0b, 0x88, 0x44, 0x26, 0x7e, 0xb3, 0x99, 0x24, 0xf6, 0xe5, 0x02, 0x66, 0x2a, 0x99, + 0x66, 0xb1, 0xb6, 0x74, 0x3b, 0xa7, 0x07, 0xaf, 0x86, 0xe5, 0x6c, 0x30, 0x3c, 0xcb, 0xc0, 0xe5, 0x97, 0xd7, 0xb8, + 0xe3, 0xa6, 0xad, 0x7f, 0xe5, 0x96, 0xf0, 0x25, 0xb2, 0xd4, 0xb5, 0xe4, 0xcf, 0x28, 0xb5, 0x1f, 0x34, 0x95, 0x7f, + 0x12, 0xf4, 0xb4, 0xf4, 0x3e, 0x2f, 0x9d, 0xca, 0xaf, 0xdf, 0xb7, 0x3d, 0xad, 0x16, 0xaf, 0xfe, 0x3a, 0xb9, 0x5e, + 0xff, 0xaf, 0xed, 0x1a, 0x3d, 0xfa, 0x39, 0xbd, 0xb2, 0xbf, 0x13, 0x9b, 0x85, 0x61, 0x77, 0x3d, 0x5d, 0x5c, 0x8b, + 0xea, 0xcf, 0x0f, 0xfc, 0xb3, 0xd3, 0x4a, 0x98, 0x8f, 0xbf, 0xb7, 0x98, 0x4c, 0xad, 0x66, 0xb7, 0xa6, 0x7b, 0xf8, + 0xe9, 0xa7, 0x1e, 0x04, 0xda, 0x95, 0x9c, 0xbb, 0xa6, 0x61, 0x98, 0x45, 0x85, 0x1a, 0x4e, 0xd1, 0x83, 0x3e, 0xda, + 0x1e, 0x37, 0xdf, 0x64, 0xeb, 0xc0, 0xed, 0x65, 0x93, 0x27, 0xcd, 0xd6, 0xf5, 0xb5, 0xc5, 0xf5, 0x5c, 0xa6, 0xcb, + 0x29, 0xb8, 0x91, 0x09, 0x1f, 0xe2, 0xbf, 0x6c, 0xc1, 0x64, 0x15, 0x90, 0xfc, 0x81, 0x14, 0xd7, 0xb7, 0xab, 0xab, + 0x5f, 0x65, 0xb9, 0x12, 0xb3, 0x8e, 0xb4, 0x06, 0x5a, 0x07, 0x41, 0xa3, 0xe6, 0x71, 0x21, 0x66, 0xae, 0xe9, 0x68, + 0x57, 0x72, 0x82, 0x0b, 0x50, 0x18, 0x4d, 0xfd, 0xc7, 0x4f, 0xa1, 0x36, 0xf7, 0x1a, 0xe5, 0x08, 0xae, 0x89, 0x62, + 0xf7, 0x9a, 0xb0, 0xdd, 0x82, 0x71, 0xaa, 0x78, 0x87, 0xaa, 0xca, 0x8d, 0xf6, 0xc5, 0x4c, 0x03, 0xa2, 0xca, 0x72, + 0x12, 0xe0, 0x10, 0x6f, 0x16, 0x6e, 0x92, 0xc4, 0xff, 0x1e, 0xbb, 0x48, 0x99, 0x14, 0xfe, 0xb9, 0x22, 0x64, 0xb1, + 0xd0, 0x2f, 0xb7, 0x8e, 0xd8, 0xd4, 0x0d, 0xab, 0xeb, 0x0f, 0x92, 0x99, 0x90, 0x9a, 0x89, 0xb0, 0xa2, 0x66, 0xbe, + 0x05, 0xdc, 0x93, 0x82, 0x89, 0xe7, 0x22, 0x6f, 0x6d, 0xd7, 0xfc, 0x7d, 0xea, 0xb3, 0xc5, 0x47, 0x91, 0x05, 0xd0, + 0x0d, 0x01, 0x02, 0x1a, 0xd7, 0xa7, 0xc5, 0x7a, 0x6f, 0x3b, 0xef, 0x5f, 0xd2, 0x58, 0x74, 0x3b, 0xe3, 0xca, 0x79, + 0xab, 0x68, 0xec, 0xe9, 0x02, 0x28, 0x69, 0xf5, 0xe5, 0xc7, 0x55, 0x3f, 0xbc, 0xdf, 0xc4, 0xad, 0xde, 0xc7, 0xbb, + 0xfe, 0xb5, 0x50, 0x8e, 0x34, 0x7c, 0x3a, 0xa5, 0xe1, 0xe5, 0x4e, 0x35, 0x31, 0x67, 0x3c, 0x2d, 0xaf, 0x5c, 0xd8, + 0x0d, 0xd9, 0xc6, 0xef, 0x7c, 0x68, 0xeb, 0x81, 0x5f, 0x76, 0x98, 0x22, 0x34, 0x27, 0x9b, 0x29, 0x2f, 0x90, 0x98, + 0xeb, 0x9b, 0xad, 0x38, 0xd8, 0x7b, 0x84, 0x36, 0xe1, 0xaf, 0x97, 0x24, 0x2b, 0xc4, 0xa8, 0xc2, 0x41, 0x5e, 0x1e, + 0xf6, 0x29, 0x4c, 0x82, 0xf5, 0x25, 0x3c, 0x04, 0x8a, 0x3e, 0x62, 0x14, 0xcb, 0xf1, 0x16, 0xea, 0x58, 0x8e, 0x83, + 0xde, 0x2c, 0x1f, 0xb5, 0xb1, 0x8b, 0x9f, 0x31, 0xb0, 0x62, 0xab, 0x90, 0xd3, 0x88, 0x35, 0x5b, 0xf8, 0xde, 0xdc, + 0xfa, 0xa1, 0xde, 0x73, 0x37, 0x24, 0x1c, 0x6e, 0x2b, 0xcf, 0x2f, 0xaa, 0x2d, 0x2b, 0xb5, 0x01, 0xde, 0xd2, 0x9d, + 0x79, 0x50, 0x49, 0x9b, 0xf7, 0x44, 0x76, 0x6f, 0x54, 0xf5, 0xd7, 0x4e, 0x16, 0xe2, 0x97, 0xdf, 0x45, 0xdb, 0x59, + 0x0a, 0x22, 0x5c, 0x84, 0x21, 0xd4, 0x56, 0xa5, 0x47, 0x51, 0x9e, 0xba, 0xfd, 0x14, 0x37, 0xa5, 0xdd, 0x06, 0x19, + 0xe9, 0xfe, 0x0d, 0x90, 0x82, 0x5e, 0x80, 0x40, 0x88, 0x7b, 0xd9, 0x1c, 0x0a, 0x98, 0x64, 0x90, 0x40, 0x2f, 0x13, + 0xac, 0x03, 0xfe, 0xa0, 0xe4, 0xbd, 0xed, 0xc0, 0x03, 0xe0, 0x80, 0xc2, 0x61, 0xa4, 0x7c, 0x65, 0x4e, 0x75, 0x46, + 0x66, 0xcb, 0xaa, 0x75, 0x13, 0x8f, 0xa6, 0xeb, 0x0a, 0x9c, 0x37, 0x15, 0x9b, 0x7f, 0x26, 0x0a, 0xdb, 0x4e, 0xc4, + 0xa9, 0x2c, 0x14, 0x98, 0xa8, 0x31, 0x48, 0x4f, 0x0d, 0x96, 0xad, 0x4a, 0xd3, 0xf8, 0x10, 0xcb, 0x6e, 0x1c, 0xa5, + 0xeb, 0x7a, 0x63, 0xe3, 0xcc, 0x41, 0x98, 0xbd, 0xb1, 0xd7, 0xee, 0xf9, 0x96, 0xb5, 0x37, 0xad, 0x0e, 0xc5, 0x63, + 0x65, 0x71, 0x53, 0xf9, 0xf2, 0xcd, 0xb9, 0x31, 0xe5, 0x59, 0xe6, 0x1c, 0xc2, 0x5a, 0xf0, 0xdf, 0xb0, 0x1b, 0x36, + 0x6d, 0x2c, 0xf9, 0x72, 0x5f, 0x10, 0xc1, 0xee, 0x92, 0xbd, 0xc6, 0xec, 0xb2, 0xa4, 0x0a, 0x43, 0xf0, 0xce, 0x67, + 0x2a, 0x11, 0xcb, 0x1f, 0x51, 0x94, 0x6f, 0x3c, 0xb6, 0xfb, 0xc2, 0x2a, 0xc1, 0xb0, 0x5e, 0x13, 0x78, 0xe1, 0x79, + 0x4b, 0x49, 0x8b, 0x49, 0x79, 0x59, 0x66, 0xf7, 0xcb, 0xee, 0xca, 0x0d, 0xc2, 0xc3, 0xbd, 0xa4, 0x15, 0x62, 0x18, + 0x35, 0x95, 0x2a, 0x70, 0x31, 0x22, 0xea, 0x98, 0xa7, 0xdb, 0xb2, 0xc4, 0x2f, 0x4d, 0x25, 0x49, 0x2d, 0x74, 0x6b, + 0x07, 0x87, 0xdf, 0x59, 0xd2, 0x44, 0x88, 0x2d, 0x28, 0x5e, 0x77, 0x48, 0x60, 0xe7, 0x9c, 0x52, 0xbe, 0x9f, 0x3f, + 0xca, 0x2c, 0x19, 0x5e, 0x95, 0x03, 0x55, 0xc8, 0xce, 0x0c, 0x19, 0xad, 0xb8, 0xeb, 0x44, 0x12, 0xf4, 0x2e, 0x12, + 0x83, 0x15, 0xc2, 0x7e, 0x28, 0xca, 0x12, 0xfd, 0x80, 0x57, 0x93, 0x1b, 0x78, 0x11, 0x58, 0x75, 0xe5, 0xb1, 0x53, + 0x12, 0xe4, 0x00, 0xf9, 0x49, 0x70, 0xd6, 0xc3, 0x4c, 0xee, 0x8e, 0x40, 0x04, 0x8f, 0x77, 0x32, 0x11, 0xd0, 0x06, + 0xf2, 0x55, 0x5d, 0xdc, 0x89, 0x44, 0x15, 0x82, 0xbf, 0x24, 0x77, 0xf4, 0x6e, 0xab, 0x34, 0x1a, 0xed, 0x6c, 0x28, + 0x4c, 0xdc, 0xc6, 0x75, 0xe3, 0x1d, 0x2f, 0x98, 0xa3, 0xcd, 0xe8, 0xae, 0x58, 0x9e, 0xe7, 0xcd, 0x4d, 0x69, 0x04, + 0x4b, 0xea, 0x2b, 0xcc, 0x4b, 0xb3, 0x56, 0x74, 0x64, 0x6c, 0x11, 0x24, 0x06, 0xcc, 0x69, 0x67, 0xc9, 0x62, 0xf5, + 0xdb, 0x58, 0x8b, 0x1c, 0x47, 0x58, 0x96, 0x04, 0x10, 0xcd, 0x0b, 0x91, 0x17, 0x43, 0x8e, 0xa3, 0x25, 0xaa, 0x14, + 0x18, 0x73, 0x8b, 0x18, 0x76, 0xb1, 0xc9, 0xc9, 0x6d, 0x69, 0xa4, 0x68, 0xf8, 0x26, 0xa7, 0xa7, 0xf7, 0xd6, 0xf0, + 0xda, 0x88, 0x64, 0xe4, 0x60, 0x7b, 0x2e, 0xb7, 0x25, 0xac, 0xf2, 0x53, 0xbf, 0x5b, 0x6b, 0x15, 0x2d, 0x97, 0xe3, + 0x60, 0xb4, 0xd7, 0x92, 0x45, 0xbb, 0x01, 0x35, 0x7f, 0xc9, 0xba, 0x87, 0x8c, 0x35, 0xda, 0xb0, 0xd5, 0x41, 0x5d, + 0x88, 0x73, 0x3e, 0xf6, 0x15, 0xfe, 0x46, 0x9e, 0xc0, 0x4c, 0x53, 0x72, 0x91, 0xff, 0xbe, 0xbf, 0x54, 0x25, 0xf9, + 0xeb, 0x60, 0x27, 0x3c, 0x16, 0x6a, 0x64, 0xbf, 0x57, 0x13, 0x33, 0x99, 0x61, 0x87, 0xf7, 0x09, 0xb8, 0x42, 0x7c, + 0x31, 0xc0, 0xce, 0x2c, 0x9d, 0x4b, 0xda, 0xa9, 0x8c, 0x19, 0x97, 0xe2, 0x38, 0x93, 0x26, 0x1b, 0x5b, 0x53, 0x7f, + 0x7b, 0x89, 0x55, 0x4b, 0x9e, 0x5a, 0x9f, 0x5b, 0x5f, 0xe3, 0xe3, 0x1c, 0xf2, 0xd6, 0x87, 0x19, 0xff, 0x64, 0x2b, + 0x4c, 0xd8, 0x3b, 0xa2, 0x45, 0xb0, 0x63, 0xa3, 0x81, 0x9f, 0xde, 0x8b, 0xa3, 0x65, 0x09, 0xda, 0x3f, 0x80, 0x55, + 0x5d, 0x85, 0x9c, 0xc9, 0xf0, 0xf3, 0xa4, 0x91, 0x58, 0x24, 0xc5, 0x02, 0x38, 0xdf, 0xab, 0xd9, 0xef, 0xd5, 0xeb, + 0x93, 0xd5, 0x64, 0xc8, 0xa8, 0xb3, 0xa4, 0x2e, 0xd4, 0x9f, 0x5d, 0xdf, 0x36, 0x75, 0x1d, 0x9c, 0x88, 0xeb, 0x4f, + 0xd0, 0xb6, 0x75, 0xc7, 0xd0, 0x9c, 0xa0, 0xa6, 0x3c, 0x53, 0x1c, 0xeb, 0x4e, 0xbf, 0x19, 0x8f, 0x6c, 0x6e, 0x3e, + 0xda, 0x44, 0x36, 0x5e, 0x8c, 0xc4, 0x16, 0x5e, 0xe8, 0x05, 0xd0, 0xa2, 0xbe, 0xc7, 0x42, 0xfc, 0xe4, 0xe8, 0x19, + 0x4e, 0x60, 0x04, 0x72, 0x2d, 0x64, 0xa0, 0xa4, 0x27, 0x1a, 0xb6, 0x55, 0x73, 0x0e, 0x07, 0x2f, 0x3f, 0xb1, 0x2d, + 0x79, 0x44, 0x07, 0x75, 0x86, 0xfe, 0x4a, 0x3e, 0xdb, 0x4f, 0x15, 0xef, 0x30, 0xd5, 0xf6, 0xeb, 0x72, 0x9c, 0x35, + 0xd3, 0x79, 0xd7, 0x90, 0x85, 0xe8, 0xf9, 0x60, 0x7b, 0x86, 0xd4, 0xb1, 0x8a, 0x56, 0xcd, 0xe2, 0xf5, 0xf0, 0xee, + 0x91, 0x25, 0x66, 0xeb, 0x76, 0x67, 0x74, 0xd8, 0x41, 0x50, 0x43, 0x0c, 0xd6, 0x6d, 0x21, 0x91, 0x19, 0x25, 0xc7, + 0xba, 0x10, 0x1f, 0xc1, 0x0d, 0x41, 0x29, 0xf4, 0xb0, 0x97, 0xd2, 0x4a, 0x3f, 0xea, 0x22, 0x19, 0x26, 0x83, 0x47, + 0xb3, 0x5b, 0x36, 0xd7, 0x62, 0x17, 0x55, 0xfd, 0xb3, 0xec, 0xda, 0x15, 0xf4, 0xd1, 0x14, 0x75, 0x42, 0x0d, 0x22, + 0x90, 0xde, 0xca, 0xdf, 0xe2, 0xf8, 0x92, 0x6e, 0x5c, 0xbf, 0x1e, 0xde, 0x84, 0xcc, 0xf9, 0x00, 0x0e, 0x00, 0xd3, + 0xc9, 0xfb, 0x77, 0x0e, 0x25, 0x55, 0x85, 0x46, 0x5a, 0xdf, 0x91, 0x1b, 0x6c, 0xc7, 0xe4, 0x21, 0x3a, 0xbe, 0x76, + 0x33, 0x40, 0x80, 0x36, 0x16, 0xfa, 0x1c, 0x5a, 0x6f, 0x24, 0xad, 0x04, 0x4b, 0xa0, 0xb3, 0xfa, 0xa1, 0xa5, 0xf0, + 0xd2, 0x90, 0x98, 0xfa, 0x0d, 0x96, 0x45, 0xa2, 0x24, 0xe6, 0xcf, 0xc2, 0x2b, 0xdb, 0xaa, 0xf0, 0x30, 0xc6, 0x0a, + 0xd0, 0x86, 0x58, 0xfb, 0x15, 0xbb, 0x22, 0xb0, 0xf0, 0xde, 0x12, 0xc0, 0xbb, 0x66, 0x8e, 0x02, 0x01, 0xc7, 0x2b, + 0x1c, 0x44, 0x1a, 0x8c, 0x3f, 0x5b, 0x89, 0x23, 0x47, 0x9a, 0xd5, 0x47, 0xef, 0xdb, 0xfd, 0x69, 0x8a, 0x47, 0xea, + 0x1c, 0xb7, 0x9e, 0x64, 0x81, 0x3f, 0xec, 0x9e, 0x0b, 0x2f, 0xac, 0xc8, 0x5e, 0xf6, 0x77, 0xf7, 0x92, 0xc5, 0x4d, + 0x2f, 0xf1, 0x55, 0x2f, 0x93, 0xeb, 0x95, 0x43, 0x0d, 0x6a, 0x60, 0xf3, 0x7d, 0x8f, 0xaa, 0x82, 0xdc, 0x80, 0xbf, + 0x77, 0xf3, 0x11, 0xc6, 0xb5, 0x0b, 0x9c, 0xe3, 0x52, 0x3d, 0xcc, 0x45, 0xcc, 0xa8, 0xa4, 0x76, 0x94, 0x5c, 0x40, + 0xaa, 0x93, 0x94, 0x0b, 0x32, 0xac, 0x5c, 0xa0, 0xb7, 0xfa, 0x14, 0xaf, 0x9c, 0x2d, 0x4d, 0x82, 0x28, 0xea, 0xb9, + 0x7b, 0x85, 0x0a, 0xc1, 0x7f, 0x1d, 0xc8, 0x8c, 0x29, 0x2b, 0x30, 0x57, 0x13, 0xea, 0x30, 0x4b, 0x26, 0xbc, 0x3c, + 0x8a, 0xe1, 0xc5, 0x08, 0x32, 0x6d, 0xa9, 0x22, 0xaa, 0xdf, 0x43, 0xdf, 0xa4, 0x68, 0x56, 0xa3, 0x10, 0x73, 0x8e, + 0x25, 0x15, 0x5c, 0xaf, 0xea, 0x10, 0x7e, 0x44, 0xad, 0xee, 0x15, 0x8e, 0xeb, 0x9c, 0x31, 0xb9, 0xf3, 0xad, 0x07, + 0x9c, 0x9e, 0xc7, 0xe9, 0x01, 0xb9, 0x6d, 0x2a, 0xa2, 0xfa, 0x18, 0x0f, 0x43, 0x58, 0xab, 0x59, 0x66, 0x08, 0x99, + 0xb7, 0x0d, 0xc5, 0xaf, 0x84, 0x66, 0xf3, 0x67, 0x57, 0x43, 0xf2, 0x79, 0xf1, 0xc4, 0x8d, 0xeb, 0x54, 0xc5, 0x12, + 0x93, 0xbc, 0x08, 0x2b, 0xcc, 0xe1, 0xb2, 0x37, 0x63, 0xd1, 0xf9, 0xc9, 0x79, 0x08, 0x09, 0x58, 0x94, 0x8f, 0x68, + 0xed, 0x19, 0x50, 0x50, 0x2d, 0xc7, 0xa9, 0x5a, 0x03, 0xc6, 0xf6, 0x3c, 0x78, 0x4b, 0xf9, 0x2f, 0xdb, 0x03, 0xd4, + 0x93, 0xed, 0x9c, 0x62, 0x30, 0x86, 0xf0, 0x94, 0x6e, 0x03, 0x9c, 0x90, 0xca, 0x16, 0x0e, 0xaa, 0xf5, 0x37, 0x37, + 0x2f, 0xb4, 0x81, 0x12, 0x7f, 0x49, 0x91, 0xd6, 0x8a, 0x14, 0x8f, 0x30, 0x34, 0x05, 0x9f, 0xf1, 0xd8, 0x93, 0x78, + 0xcf, 0xdd, 0x97, 0x35, 0x22, 0x05, 0x71, 0x2e, 0xfc, 0x85, 0x08, 0x2b, 0x47, 0x88, 0x79, 0xca, 0x0d, 0x95, 0x64, + 0x5f, 0xda, 0xb3, 0xfa, 0x2a, 0x0b, 0x78, 0xea, 0xb2, 0x4f, 0xe1, 0x85, 0xc0, 0x1c, 0xae, 0x3d, 0x7a, 0x52, 0x3f, + 0x9a, 0x01, 0xab, 0x7a, 0x6e, 0x31, 0x8d, 0x50, 0x51, 0xb8, 0x84, 0x20, 0x6e, 0x29, 0x41, 0x84, 0x61, 0x66, 0x8d, + 0x87, 0x4f, 0x0c, 0xeb, 0x29, 0x0c, 0x00, 0xa6, 0xa4, 0xa1, 0x7b, 0x86, 0x32, 0x81, 0x7b, 0x69, 0x17, 0x28, 0xcf, + 0x5c, 0x65, 0x5e, 0x4e, 0xee, 0x31, 0x0c, 0x9c, 0xcc, 0xd6, 0x16, 0xd3, 0xc8, 0x88, 0xac, 0x03, 0x2d, 0xd4, 0x91, + 0xbf, 0x57, 0x2b, 0x2b, 0xbb, 0x6e, 0x02, 0xdd, 0x8b, 0x7a, 0x2f, 0xfd, 0x22, 0x42, 0xdc, 0x5e, 0xa5, 0xa7, 0x80, + 0x69, 0xf8, 0x14, 0xf7, 0x33, 0xa9, 0x10, 0x78, 0x15, 0xf4, 0x3c, 0x90, 0xc8, 0x1e, 0xe2, 0x0e, 0xea, 0x06, 0x00, + 0x92, 0x5b, 0xe2, 0x4a, 0x41, 0x5a, 0x1b, 0x52, 0x25, 0xeb, 0x3f, 0xb5, 0xd5, 0x28, 0x01, 0xc8, 0x47, 0xf6, 0xcd, + 0x91, 0xc6, 0x2b, 0x08, 0x2d, 0x5c, 0x48, 0x39, 0xcc, 0xe0, 0x51, 0x13, 0x74, 0x22, 0x33, 0xc1, 0xe6, 0x56, 0xb0, + 0x8d, 0x9f, 0xbc, 0x79, 0x1d, 0x89, 0x0a, 0xd3, 0x8f, 0xe2, 0xdf, 0xab, 0x3b, 0x6e, 0x8a, 0xb2, 0xe2, 0x21, 0xf7, + 0xfd, 0x1c, 0x3f, 0x37, 0x45, 0x49, 0x9a, 0x13, 0xbe, 0x54, 0x32, 0x9d, 0xb4, 0x17, 0x47, 0x6d, 0x8e, 0x96, 0x3d, + 0x00, 0x79, 0xc5, 0x4b, 0x60, 0xdd, 0x63, 0xe5, 0xbb, 0x96, 0x56, 0x99, 0xf9, 0x88, 0xaa, 0x2a, 0x2a, 0x24, 0x9a, + 0xe0, 0x22, 0xb3, 0x26, 0xb6, 0x71, 0x5a, 0x1c, 0x06, 0x90, 0x42, 0x63, 0x58, 0x31, 0xe4, 0xa1, 0xf9, 0xb1, 0x98, + 0x17, 0xe1, 0x89, 0x2c, 0xba, 0x2e, 0x28, 0xe5, 0x67, 0x48, 0x69, 0xa6, 0x8c, 0x6c, 0x8b, 0x65, 0x38, 0x9c, 0x01, + 0xc0, 0x5c, 0xeb, 0x88, 0xa8, 0x54, 0x98, 0xec, 0x98, 0x54, 0xc6, 0x5e, 0xc9, 0x9f, 0xa5, 0x84, 0x88, 0x08, 0xab, + 0xb3, 0x6d, 0x03, 0x62, 0x77, 0x0e, 0xea, 0x11, 0x9e, 0x2d, 0x33, 0xd8, 0xc4, 0xb2, 0x08, 0xce, 0x8a, 0xaa, 0xaa, + 0x46, 0xa3, 0xf9, 0xb0, 0x37, 0x34, 0xde, 0x64, 0xee, 0x0c, 0x85, 0xb0, 0x75, 0x3b, 0x42, 0x50, 0x6e, 0x3c, 0xdb, + 0x86, 0xd6, 0x86, 0x0f, 0x33, 0x37, 0xf5, 0x41, 0x5e, 0x2e, 0xa2, 0xaa, 0xd1, 0x66, 0xcf, 0x53, 0xca, 0xd3, 0x68, + 0xef, 0xa9, 0x3b, 0x29, 0x09, 0x95, 0xdd, 0x24, 0x2a, 0x0a, 0x6c, 0xe1, 0x59, 0x12, 0x12, 0x40, 0x71, 0xfb, 0xeb, + 0x50, 0x83, 0xfc, 0x8b, 0x91, 0x83, 0x03, 0x5f, 0xd5, 0x81, 0xb5, 0x2b, 0x20, 0xcd, 0xcf, 0x64, 0xd2, 0x5b, 0x7c, + 0xef, 0x6e, 0xe8, 0xc3, 0x47, 0x91, 0x22, 0xdc, 0x47, 0x68, 0x1d, 0x27, 0x21, 0x6e, 0x01, 0xf7, 0x9b, 0x6d, 0x2f, + 0x3e, 0x6a, 0x3a, 0x41, 0x66, 0x68, 0x5c, 0x1b, 0x2f, 0x9b, 0x56, 0xa4, 0x16, 0x28, 0x54, 0x20, 0x1f, 0xe9, 0x7e, + 0x2b, 0x01, 0x29, 0xc7, 0xa9, 0xdc, 0x76, 0xaf, 0x93, 0xf2, 0x1c, 0xee, 0x86, 0x8a, 0xe8, 0x75, 0x3d, 0xda, 0x12, + 0xd0, 0x62, 0x4e, 0x06, 0x7e, 0x3a, 0x5a, 0x45, 0xbe, 0x9c, 0x38, 0xc5, 0x39, 0x55, 0x2d, 0xd6, 0x3c, 0xf8, 0x78, + 0x97, 0x07, 0xc2, 0xfe, 0x92, 0x8c, 0x93, 0x31, 0x00, 0x59, 0xc5, 0x02, 0x73, 0xe0, 0x40, 0xed, 0x36, 0x27, 0x6a, + 0x03, 0x0e, 0xd4, 0xea, 0xce, 0x9e, 0xa6, 0x32, 0xd9, 0xa7, 0x94, 0xe3, 0x57, 0xf8, 0x82, 0xa5, 0xac, 0x46, 0xda, + 0x8a, 0x6a, 0x79, 0xae, 0xa5, 0x05, 0x50, 0x4b, 0x65, 0xa9, 0x6c, 0x29, 0xa4, 0x18, 0xdf, 0xec, 0xf1, 0x31, 0x12, + 0xba, 0x52, 0x3c, 0x4f, 0x2e, 0x03, 0xed, 0xf2, 0x37, 0x9e, 0xc2, 0x74, 0xc6, 0x04, 0xa6, 0xa9, 0x89, 0x2b, 0xb2, + 0x79, 0xff, 0xfe, 0xda, 0xa9, 0xb6, 0xec, 0x48, 0xaa, 0x40, 0xda, 0x2c, 0x76, 0x74, 0x69, 0x4c, 0x81, 0xe0, 0xaa, + 0xa1, 0xdb, 0xe2, 0x68, 0x77, 0xfe, 0xe1, 0xce, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0xc7, 0xa5, 0x10, 0x50, + 0xa3, 0xbe, 0x10, 0x4e, 0xa4, 0xfe, 0xc8, 0x90, 0x4b, 0x17, 0xb3, 0x43, 0x6b, 0x54, 0xd7, 0x2d, 0x00, 0x2d, 0x7d, + 0x0f, 0x23, 0x43, 0x21, 0x6c, 0xc4, 0xb0, 0xcf, 0x53, 0xea, 0xe3, 0xca, 0x49, 0x17, 0x5d, 0x62, 0x29, 0x64, 0xde, + 0xc7, 0x24, 0x6f, 0x92, 0x46, 0x89, 0xc8, 0xeb, 0x2c, 0xe5, 0xa4, 0x2e, 0x4e, 0xe2, 0x28, 0x6f, 0x29, 0x64, 0x20, + 0xd5, 0x4d, 0x2a, 0xdd, 0x96, 0x4b, 0x25, 0xf4, 0x58, 0xf6, 0xb7, 0xe4, 0x06, 0xaf, 0xfb, 0x72, 0x1c, 0xfc, 0x31, + 0xf2, 0xcf, 0x13, 0x5b, 0x2c, 0x45, 0x07, 0xd0, 0x83, 0x20, 0xa5, 0x35, 0x40, 0xc2, 0xcf, 0xeb, 0x5b, 0xdf, 0x09, + 0xbe, 0x76, 0x04, 0xb4, 0x42, 0xb0, 0x72, 0xbd, 0x0a, 0x35, 0xdd, 0x5e, 0x36, 0x56, 0x65, 0x54, 0x75, 0xb0, 0x83, + 0x68, 0x89, 0x24, 0x04, 0xf8, 0x9c, 0xbc, 0x43, 0xea, 0x87, 0x9a, 0x74, 0xeb, 0x4b, 0xbe, 0x88, 0xd6, 0xb5, 0x92, + 0x67, 0x04, 0x57, 0xdf, 0xa8, 0xc9, 0xc2, 0xad, 0xe3, 0x27, 0x51, 0xd7, 0x4e, 0xd5, 0x15, 0x31, 0x07, 0x04, 0x98, + 0xaa, 0x86, 0x11, 0x75, 0x9f, 0x24, 0xc9, 0xbf, 0xc4, 0x54, 0x80, 0x0a, 0x96, 0x49, 0xbd, 0xfa, 0xbf, 0x6f, 0xb5, + 0xee, 0x7f, 0xbc, 0xc1, 0xba, 0x9a, 0xe7, 0xb7, 0x77, 0x7a, 0x00, 0x30, 0x80, 0x1f, 0x83, 0xaa, 0x0e, 0x5e, 0x6e, + 0xc7, 0x0b, 0xbb, 0x32, 0x05, 0xa9, 0x09, 0xf8, 0xac, 0x92, 0xfe, 0xcf, 0x91, 0x06, 0x82, 0xe6, 0x6b, 0x64, 0x6d, + 0x6c, 0x46, 0x24, 0x72, 0xdf, 0x65, 0x83, 0x8f, 0x57, 0xe1, 0xd9, 0x11, 0xf8, 0x65, 0x6c, 0x9d, 0xd3, 0x31, 0xcb, + 0x07, 0x09, 0x2c, 0x17, 0x6a, 0xbf, 0x7a, 0xcc, 0xf9, 0x44, 0x88, 0x53, 0x54, 0xa8, 0x27, 0xa8, 0x08, 0x32, 0x81, + 0x62, 0x91, 0x96, 0xa8, 0xe3, 0x2a, 0xce, 0x11, 0x16, 0x10, 0x5a, 0xa7, 0x44, 0x44, 0xbc, 0x1d, 0xd0, 0x11, 0xbc, + 0xad, 0x21, 0x27, 0xee, 0x38, 0x37, 0x6b, 0x1b, 0x98, 0xcb, 0x20, 0xd5, 0xa0, 0xe9, 0xee, 0x0b, 0x6c, 0xc0, 0x43, + 0x9c, 0x37, 0x8e, 0x4f, 0xe2, 0x72, 0x8b, 0x2c, 0x72, 0x0e, 0x45, 0x5d, 0x5e, 0xd4, 0xc8, 0xc4, 0x24, 0xa1, 0x0e, + 0x4f, 0x21, 0xa4, 0xdb, 0x17, 0x30, 0x98, 0x16, 0x4c, 0xe3, 0xac, 0x4e, 0x12, 0xc0, 0x2d, 0x9f, 0xde, 0x0f, 0xc3, + 0x97, 0x1e, 0x6a, 0x07, 0xd1, 0xb9, 0x88, 0xf8, 0x4d, 0xdb, 0xd4, 0x28, 0x4c, 0x1e, 0xae, 0xad, 0xef, 0xa9, 0xe1, + 0x23, 0x24, 0xe1, 0x5f, 0xc3, 0xa2, 0x08, 0x48, 0xdc, 0xa6, 0xb7, 0x5c, 0x30, 0xe9, 0x9d, 0x66, 0x21, 0xb4, 0xd9, + 0x0c, 0x52, 0xa5, 0x6a, 0x3e, 0xc0, 0xca, 0xb4, 0xd3, 0xff, 0xe4, 0xe4, 0xb6, 0x24, 0x05, 0x41, 0xb4, 0xd2, 0xef, + 0x4c, 0x99, 0xb0, 0xc6, 0x98, 0x40, 0xde, 0x15, 0x25, 0x9c, 0x67, 0xd0, 0x49, 0x2c, 0x00, 0x3b, 0x5a, 0x7f, 0x2f, + 0xff, 0x0e, 0x8b, 0xd1, 0xa9, 0xd1, 0x9b, 0x4e, 0x92, 0xa9, 0xd6, 0x7f, 0x7b, 0x00, 0x7f, 0x9c, 0x81, 0xb5, 0x3e, + 0x77, 0x81, 0xb5, 0xdb, 0x4d, 0x12, 0x52, 0xba, 0x25, 0xaf, 0xaa, 0xaf, 0x62, 0xdd, 0xa4, 0x54, 0xee, 0x67, 0xbf, + 0xbf, 0xbd, 0xd8, 0x32, 0x82, 0xc3, 0x3a, 0xa7, 0x18, 0x58, 0x80, 0x0d, 0x73, 0x19, 0x6e, 0x56, 0x3b, 0x81, 0xa0, + 0xa4, 0x97, 0xe4, 0xc3, 0x36, 0x43, 0xb2, 0xe3, 0x53, 0x2d, 0x91, 0xd0, 0x33, 0x9e, 0xf6, 0x35, 0x80, 0xc0, 0xbb, + 0x73, 0x93, 0xd2, 0x7a, 0xf3, 0x19, 0x79, 0xaf, 0x4a, 0x14, 0x91, 0x61, 0x4a, 0x8c, 0x67, 0x4e, 0x08, 0xd2, 0x7e, + 0xcd, 0x60, 0x6b, 0xbf, 0x19, 0x3c, 0x8d, 0x9b, 0x87, 0xe6, 0x88, 0x20, 0x72, 0x31, 0x7d, 0x90, 0xc2, 0x9f, 0x25, + 0xe3, 0xf2, 0x85, 0xcf, 0x6c, 0xc3, 0x75, 0x5a, 0x49, 0x80, 0x73, 0x8a, 0xbb, 0x79, 0xca, 0x33, 0xb1, 0x58, 0x9e, + 0xbc, 0x7c, 0xb5, 0xac, 0xd2, 0x14, 0x38, 0x83, 0x0f, 0x71, 0x19, 0xa9, 0x34, 0xc8, 0x94, 0x14, 0x3f, 0x9e, 0x27, + 0x93, 0x6e, 0x6f, 0x6a, 0x95, 0xb0, 0xab, 0x06, 0x87, 0xea, 0x13, 0x2a, 0x4b, 0x4f, 0xdb, 0x52, 0x0b, 0xcc, 0x63, + 0x1f, 0x04, 0x98, 0x7c, 0x93, 0x7d, 0xcc, 0xda, 0x11, 0x74, 0x0f, 0x4a, 0xe5, 0x32, 0x1e, 0x06, 0xb8, 0xa9, 0x82, + 0x00, 0xd2, 0xc7, 0x7a, 0x0a, 0x73, 0x79, 0x8f, 0x89, 0x0e, 0x8b, 0x1e, 0x46, 0xa0, 0x2e, 0xd4, 0xc2, 0x08, 0xcc, + 0x90, 0x07, 0x53, 0xb1, 0x74, 0xe2, 0x4f, 0x37, 0xd8, 0xfa, 0xdc, 0x8f, 0x73, 0x4d, 0xbb, 0x63, 0x96, 0x06, 0x48, + 0xaa, 0xa3, 0xee, 0x37, 0xfa, 0x46, 0x3d, 0x9e, 0x75, 0x8b, 0xf7, 0x69, 0x33, 0xa6, 0xbd, 0xa9, 0x3c, 0x1e, 0x55, + 0xdb, 0xef, 0xdf, 0x16, 0x97, 0xa8, 0x96, 0x92, 0xa5, 0x3d, 0xc8, 0xbe, 0x3b, 0xa3, 0x00, 0xb7, 0xef, 0x78, 0x13, + 0x1e, 0x20, 0xcf, 0x91, 0x4e, 0xcc, 0x6d, 0xd8, 0x53, 0x9d, 0x03, 0xed, 0xfc, 0xe7, 0x47, 0xa9, 0xb0, 0xf3, 0xf7, + 0xa7, 0x61, 0xe9, 0x3d, 0x49, 0x18, 0x05, 0x8e, 0xd2, 0xef, 0xde, 0x77, 0x59, 0xad, 0xf4, 0x71, 0x81, 0xcb, 0x9d, + 0xd7, 0x56, 0x9c, 0x78, 0xb1, 0x61, 0x3d, 0x25, 0x8f, 0x63, 0x14, 0x63, 0x6f, 0x7a, 0xb2, 0xee, 0x8c, 0xdd, 0x3d, + 0x85, 0xb5, 0x67, 0x3d, 0x25, 0x48, 0xb7, 0x92, 0x1f, 0xf7, 0xfe, 0x23, 0xb6, 0x53, 0x25, 0xdd, 0xf4, 0x07, 0xdb, + 0x2f, 0x3f, 0x3a, 0x3b, 0x88, 0x07, 0xad, 0xb3, 0x32, 0x9d, 0xa5, 0xeb, 0x2a, 0xe9, 0x72, 0xb8, 0x40, 0xde, 0xcd, + 0xc4, 0x73, 0x61, 0xae, 0xbf, 0xce, 0x36, 0x42, 0x05, 0xf6, 0xe5, 0x6a, 0xbc, 0xbd, 0x47, 0xcc, 0xe7, 0x72, 0x2e, + 0xfb, 0xde, 0xa2, 0x29, 0x04, 0x7d, 0x8b, 0x91, 0x72, 0xc1, 0x38, 0x4e, 0x90, 0x0f, 0xb8, 0x34, 0xde, 0x07, 0xb4, + 0x18, 0xa3, 0x5b, 0xf8, 0x79, 0x0c, 0xdb, 0x03, 0x6c, 0xcd, 0xfc, 0x73, 0xc2, 0x63, 0x5e, 0x88, 0x30, 0x4d, 0x1e, + 0x50, 0x53, 0xb2, 0x81, 0x0f, 0x36, 0x9c, 0x9f, 0x15, 0x12, 0xc3, 0x00, 0xcb, 0x23, 0x4f, 0xa7, 0x8d, 0xec, 0x69, + 0xa8, 0x2e, 0xcf, 0x73, 0xb5, 0xde, 0x82, 0x9e, 0x30, 0x9d, 0xe5, 0x65, 0x1a, 0xee, 0xd2, 0x3b, 0x13, 0xec, 0x70, + 0xb9, 0x6b, 0x38, 0x69, 0x99, 0x22, 0x55, 0x8e, 0xf3, 0xc6, 0x71, 0x9a, 0x33, 0x06, 0xe2, 0x29, 0xe6, 0xf5, 0xeb, + 0x54, 0x60, 0xd1, 0x62, 0x5c, 0xbe, 0x40, 0x69, 0x60, 0xea, 0x2f, 0x36, 0x32, 0x53, 0xa1, 0x75, 0x00, 0x31, 0x59, + 0x82, 0x3f, 0x1b, 0xa4, 0xb4, 0xa0, 0x10, 0x8d, 0x0a, 0xb7, 0xd5, 0x3f, 0xdc, 0x15, 0xb5, 0x4a, 0x13, 0xd1, 0xee, + 0x5d, 0xf1, 0xce, 0x10, 0xdb, 0xc5, 0x5b, 0x4e, 0x07, 0x50, 0x8c, 0x1a, 0x1d, 0xd0, 0xa4, 0x60, 0x7b, 0xb4, 0xfe, + 0x26, 0x29, 0xe5, 0x79, 0x66, 0x44, 0xf6, 0x58, 0xc0, 0xfa, 0x6e, 0x70, 0x18, 0x5b, 0x5b, 0x55, 0x58, 0xef, 0x9b, + 0x36, 0xc1, 0x1c, 0x80, 0xfd, 0x96, 0x44, 0xf1, 0xde, 0x27, 0x7f, 0x49, 0x8c, 0xd1, 0xf5, 0x3d, 0x17, 0x59, 0x7a, + 0x63, 0x28, 0x26, 0x48, 0xae, 0x69, 0x56, 0xc9, 0xe2, 0x18, 0x8d, 0x46, 0x41, 0xc9, 0x39, 0x31, 0x8e, 0x50, 0x36, + 0x40, 0x3d, 0x4d, 0x49, 0xe9, 0x02, 0x40, 0x66, 0x58, 0x4d, 0x0f, 0x0a, 0x60, 0x19, 0x8d, 0xb4, 0x40, 0xe5, 0x59, + 0x74, 0x14, 0xee, 0x79, 0x72, 0x9a, 0x6b, 0x66, 0xd5, 0xe0, 0xf0, 0x96, 0x07, 0x8a, 0xca, 0x79, 0x7a, 0x36, 0x99, + 0x8f, 0xe8, 0x20, 0xd2, 0x6b, 0x1a, 0xff, 0xb6, 0xaf, 0x44, 0x74, 0x70, 0x1b, 0x09, 0x16, 0x9c, 0xfd, 0x90, 0x93, + 0x21, 0x72, 0x7f, 0xb5, 0xce, 0xf4, 0x83, 0x0a, 0xfd, 0x6e, 0x35, 0x84, 0x48, 0xf9, 0x4a, 0xd8, 0xd8, 0x94, 0x3b, + 0x35, 0xe8, 0xbc, 0xd3, 0x30, 0x91, 0xa1, 0x70, 0x7c, 0xcf, 0x6d, 0xe9, 0x13, 0x6d, 0x56, 0x37, 0xce, 0xfc, 0xe3, + 0x01, 0x3f, 0x59, 0x9a, 0x22, 0x68, 0x4d, 0xa5, 0x4e, 0x07, 0xe8, 0x96, 0x48, 0x83, 0xa3, 0x7c, 0x60, 0x5e, 0x78, + 0xd0, 0x52, 0xbb, 0xa1, 0x44, 0x57, 0x74, 0x14, 0xee, 0x91, 0xe7, 0x02, 0x1a, 0x67, 0x0a, 0xba, 0x1e, 0x71, 0x54, + 0x3b, 0x63, 0x28, 0xc5, 0x1c, 0x0c, 0xe6, 0x50, 0xd6, 0x64, 0x8d, 0x7d, 0x6c, 0xbd, 0x44, 0x77, 0xe3, 0x19, 0x22, + 0xd7, 0x13, 0x1a, 0x87, 0xa4, 0xeb, 0x99, 0x91, 0xc2, 0x30, 0x84, 0x77, 0x40, 0xf2, 0xee, 0xc4, 0xfa, 0x5c, 0xa9, + 0xa4, 0x1d, 0x69, 0x63, 0x60, 0x17, 0xcf, 0x62, 0xb6, 0xb0, 0x22, 0x3b, 0x71, 0x6d, 0xbd, 0xb6, 0x76, 0xfd, 0x15, + 0xa2, 0xc2, 0x78, 0x6c, 0xeb, 0x70, 0x9e, 0x33, 0x72, 0xc5, 0x0d, 0x13, 0x3f, 0xcb, 0xae, 0xcf, 0x3c, 0x95, 0xf4, + 0x5f, 0x84, 0xd6, 0x4f, 0x5d, 0x71, 0x81, 0x75, 0xb7, 0x4d, 0xec, 0xfa, 0x75, 0x4a, 0x6a, 0x5d, 0xb9, 0x0b, 0xfd, + 0x8f, 0xad, 0xed, 0x58, 0x6d, 0xe6, 0x69, 0xde, 0x7f, 0xe8, 0x44, 0x1d, 0xe4, 0x9f, 0x7e, 0xb5, 0x1b, 0xb9, 0x91, + 0x16, 0x2f, 0xc9, 0xc7, 0xbb, 0x9e, 0xe6, 0x0b, 0x1e, 0xfb, 0xf3, 0x66, 0xd8, 0xf3, 0x32, 0xbf, 0x16, 0xec, 0xcf, + 0xd3, 0xd9, 0x67, 0x8e, 0x1e, 0xdf, 0x1f, 0xd2, 0xc4, 0xa3, 0xe9, 0xf3, 0xe4, 0xcf, 0xe4, 0x5c, 0x24, 0x8f, 0xc9, + 0x5e, 0xf5, 0xb6, 0xed, 0x22, 0xa5, 0x11, 0xa0, 0x8e, 0xde, 0xac, 0xdf, 0x85, 0x74, 0x4d, 0x32, 0x15, 0x0f, 0xca, + 0xa7, 0x7c, 0x20, 0xbe, 0xae, 0xbf, 0x4c, 0xf7, 0x50, 0x88, 0x78, 0x11, 0xf8, 0xef, 0xf9, 0xfe, 0x23, 0xb6, 0x59, + 0x57, 0x5a, 0x9d, 0xcd, 0x8d, 0x1e, 0xba, 0x7d, 0x75, 0x32, 0xf5, 0x89, 0x94, 0x51, 0x7a, 0x5d, 0x88, 0x97, 0x18, + 0x17, 0x37, 0xf9, 0x21, 0xdb, 0x7e, 0x18, 0x9f, 0xd7, 0xf8, 0x81, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0x3e, 0x40, + 0x4d, 0xe5, 0x54, 0xb0, 0x62, 0x5a, 0xa9, 0x4a, 0x03, 0xa0, 0x69, 0xf4, 0x4b, 0x94, 0x7f, 0xa6, 0x07, 0xf2, 0xc3, + 0x1f, 0xbd, 0x75, 0xde, 0x3f, 0xa7, 0xff, 0xbe, 0xff, 0xfc, 0xa3, 0x06, 0x26, 0x05, 0x64, 0xdd, 0x87, 0x95, 0x6d, + 0x12, 0x8e, 0xca, 0xc6, 0x55, 0x56, 0x13, 0x75, 0x07, 0x99, 0x5e, 0xcd, 0x6c, 0xf7, 0xcd, 0x5b, 0xf6, 0xa1, 0x17, + 0xd1, 0x4c, 0xc9, 0xa3, 0x52, 0xe4, 0x1d, 0x72, 0x71, 0xf5, 0x39, 0x7c, 0x19, 0xeb, 0xaa, 0x90, 0x5f, 0xa9, 0x8a, + 0xe7, 0xa5, 0x0f, 0x82, 0xa8, 0x73, 0x72, 0x0c, 0x12, 0xc7, 0x91, 0x07, 0x14, 0xd8, 0x9f, 0xeb, 0x39, 0x74, 0xcf, + 0xeb, 0xcb, 0x09, 0x3c, 0x0d, 0x97, 0xb0, 0x5d, 0xef, 0xbc, 0x4b, 0x1f, 0x6a, 0x32, 0x4a, 0xb0, 0x8d, 0x74, 0x73, + 0xe8, 0xa0, 0x51, 0x3b, 0x7a, 0xe4, 0xe3, 0x9e, 0xf1, 0xd1, 0x05, 0x8a, 0xbe, 0xc7, 0xb9, 0xd1, 0x33, 0x57, 0x0e, + 0xfa, 0x5c, 0xae, 0xbb, 0xa6, 0xbd, 0xaa, 0x13, 0xa3, 0x63, 0x52, 0x79, 0x29, 0x0a, 0x20, 0x49, 0xaa, 0xa7, 0x2d, + 0x52, 0xfb, 0xa9, 0x9c, 0x0d, 0x6c, 0x9e, 0xe1, 0x5e, 0x3c, 0x13, 0x4a, 0x42, 0x37, 0xfc, 0xc5, 0xb9, 0xa6, 0x7d, + 0x61, 0x99, 0xaa, 0x30, 0xb8, 0x61, 0x35, 0x2d, 0x21, 0xe8, 0x35, 0x08, 0x36, 0x0d, 0xee, 0x3f, 0x8e, 0x20, 0xd8, + 0x04, 0x5a, 0x3b, 0x83, 0x94, 0x81, 0x33, 0x36, 0xe2, 0x1f, 0xae, 0x68, 0x10, 0xc9, 0xcd, 0x03, 0x4f, 0xe2, 0xe5, + 0xb0, 0x24, 0x52, 0xde, 0x40, 0x28, 0x08, 0x7a, 0x2a, 0xb8, 0x08, 0x52, 0xd0, 0x98, 0xf6, 0x98, 0x1d, 0xa8, 0x36, + 0x38, 0x6e, 0x80, 0xcb, 0x57, 0x49, 0xd9, 0xa4, 0xda, 0xd4, 0x65, 0xaa, 0x62, 0xc7, 0xe0, 0x91, 0x97, 0xd6, 0x41, + 0x7a, 0x81, 0x22, 0x68, 0x8a, 0x52, 0xa4, 0x57, 0x35, 0x1d, 0x85, 0xb6, 0xa8, 0x36, 0x18, 0x3d, 0xa8, 0x18, 0x28, + 0xa9, 0xb0, 0xd8, 0xc8, 0x46, 0xd1, 0x9f, 0x19, 0x22, 0x8c, 0xc2, 0x0f, 0xed, 0xca, 0xc8, 0x87, 0x8f, 0x6a, 0x98, + 0xbd, 0x9b, 0x44, 0xb1, 0xc8, 0x4b, 0x7d, 0x5e, 0xf3, 0x88, 0x9a, 0x9d, 0x26, 0xf9, 0xfc, 0x66, 0x35, 0x70, 0x8a, + 0x49, 0xc9, 0x4e, 0x78, 0xb7, 0x4a, 0x4c, 0x82, 0x88, 0xad, 0xdf, 0x3e, 0xf5, 0xbc, 0x1b, 0xb8, 0xb4, 0xf7, 0x23, + 0x61, 0x7b, 0x59, 0xf2, 0xe8, 0xf0, 0xb2, 0xa8, 0xb9, 0xf9, 0xc6, 0x9c, 0xea, 0x2a, 0xd5, 0x1b, 0x02, 0x7e, 0x95, + 0x8e, 0x5e, 0x94, 0x09, 0x0a, 0xa7, 0x36, 0xdd, 0x07, 0x93, 0x11, 0xd0, 0xd1, 0xb3, 0x1a, 0xcd, 0xf2, 0xf4, 0xd5, + 0x32, 0xb1, 0xc3, 0xc6, 0xe8, 0x23, 0x0a, 0xbc, 0x6c, 0x55, 0x06, 0x47, 0x1a, 0x55, 0xca, 0xcc, 0x0b, 0xa2, 0xea, + 0x44, 0xad, 0x60, 0x2f, 0x35, 0xf8, 0x0f, 0x08, 0xd3, 0x25, 0x0f, 0x9c, 0x1a, 0x80, 0x1c, 0xb3, 0x88, 0x74, 0x54, + 0x80, 0xdf, 0x3e, 0x4d, 0xcf, 0x98, 0x6b, 0xb8, 0xcb, 0x1a, 0x44, 0x11, 0x6d, 0x1f, 0xb1, 0x44, 0xd2, 0x1d, 0x2e, + 0x8c, 0x29, 0x42, 0xb8, 0x39, 0x2a, 0x04, 0x01, 0xac, 0x30, 0xf8, 0x12, 0xe3, 0x80, 0xb4, 0xa8, 0x7b, 0x14, 0x5e, + 0xb6, 0x0a, 0xbe, 0xcb, 0x05, 0xc7, 0x58, 0xd9, 0xbb, 0x90, 0x58, 0x17, 0xa2, 0x41, 0xb7, 0xfc, 0x7b, 0x84, 0xfc, + 0x6a, 0x68, 0x66, 0xb5, 0xf9, 0x0a, 0xee, 0x5b, 0xaf, 0x9d, 0x4d, 0x26, 0x30, 0xbb, 0x12, 0x55, 0x21, 0x8b, 0x90, + 0xb2, 0x17, 0x22, 0xd3, 0xb4, 0x95, 0x28, 0x39, 0x47, 0x40, 0x12, 0xd8, 0x02, 0x01, 0x36, 0xf8, 0xa1, 0x5a, 0x96, + 0x43, 0x09, 0x55, 0x0d, 0x8c, 0x90, 0xef, 0xc5, 0x02, 0x88, 0x5a, 0x56, 0xbd, 0xa2, 0x0c, 0xec, 0x68, 0xd9, 0xeb, + 0xac, 0x67, 0x40, 0xc9, 0x7e, 0x83, 0x40, 0x78, 0x1b, 0x9e, 0xbe, 0xff, 0x26, 0xe4, 0xd1, 0x99, 0x63, 0x4d, 0x58, + 0x78, 0x44, 0x6e, 0x1c, 0x60, 0xe5, 0x73, 0x5b, 0x82, 0x90, 0x05, 0xa5, 0xdf, 0x95, 0x2b, 0x7b, 0xd4, 0x67, 0xa6, + 0x46, 0x15, 0x82, 0xbc, 0xb9, 0xec, 0x03, 0x69, 0xa9, 0x03, 0xed, 0x1f, 0x90, 0x81, 0xc1, 0x09, 0xdc, 0x3b, 0x55, + 0x84, 0xb2, 0xc7, 0x18, 0xfe, 0xdc, 0xa6, 0xa6, 0x4d, 0xdc, 0xf3, 0x33, 0x98, 0x14, 0x03, 0x92, 0x95, 0x92, 0x7b, + 0x9e, 0xff, 0xae, 0x86, 0x2a, 0x48, 0x28, 0x4c, 0x4b, 0xf0, 0x24, 0x2b, 0x23, 0x84, 0xc8, 0x44, 0xc7, 0x41, 0xe7, + 0x40, 0xbc, 0xba, 0x37, 0x30, 0x9f, 0xd9, 0x31, 0x4b, 0x7e, 0xf7, 0x68, 0xb9, 0x4e, 0xc4, 0xb2, 0x86, 0x1f, 0x46, + 0xb3, 0x1b, 0xfb, 0x89, 0x70, 0xdd, 0xc2, 0x1a, 0x97, 0x06, 0xcf, 0xd0, 0xad, 0xf6, 0xf8, 0x4d, 0xce, 0x50, 0x4c, + 0xdb, 0x74, 0xac, 0x0e, 0xaf, 0xaf, 0xd5, 0xac, 0xb2, 0x85, 0x6a, 0xb7, 0x9c, 0x5f, 0xab, 0x6a, 0xcd, 0xd6, 0x6e, + 0xa1, 0x95, 0xd5, 0xe7, 0x3f, 0x8b, 0xf9, 0x9c, 0xc2, 0x62, 0x7e, 0x30, 0x80, 0xbb, 0x28, 0xe2, 0xc5, 0x89, 0xbb, + 0xe6, 0xda, 0xfe, 0xa0, 0xf6, 0xca, 0xe5, 0xe3, 0x6b, 0x8f, 0xfb, 0xef, 0x22, 0x46, 0xbd, 0xb0, 0x8f, 0x02, 0xb8, + 0x56, 0x23, 0x1e, 0x0f, 0x1f, 0x5d, 0xcc, 0xab, 0x35, 0xf5, 0x49, 0x1d, 0x79, 0xcf, 0x5d, 0xef, 0x5b, 0x5a, 0xb2, + 0x38, 0xad, 0x3c, 0xcd, 0x3e, 0x10, 0x23, 0xb3, 0x81, 0xd6, 0x9b, 0x34, 0x43, 0x86, 0x3b, 0x12, 0x7c, 0xb2, 0x52, + 0xf4, 0xe2, 0x64, 0xf7, 0xd4, 0x20, 0x52, 0xb2, 0xd1, 0xcc, 0x42, 0xa0, 0x96, 0x97, 0x21, 0xd3, 0x74, 0x2c, 0x0a, + 0x51, 0x0e, 0x2c, 0x28, 0x0f, 0x9a, 0x30, 0xc5, 0x93, 0x70, 0x1a, 0x47, 0x92, 0x62, 0x35, 0x0d, 0xb9, 0xcd, 0x49, + 0x89, 0x1a, 0xd2, 0xd5, 0xb9, 0xc1, 0x03, 0xad, 0x16, 0x98, 0xc0, 0xa1, 0x24, 0x05, 0x98, 0x6b, 0xa4, 0x67, 0x88, + 0x28, 0x04, 0x03, 0xf4, 0xfa, 0x96, 0x9d, 0x87, 0xce, 0xbb, 0x93, 0x72, 0x59, 0x53, 0x10, 0x6f, 0x3e, 0xf6, 0xa1, + 0x65, 0xa6, 0x75, 0x27, 0x37, 0x54, 0xf2, 0x7c, 0x09, 0xb5, 0x34, 0x81, 0xfb, 0x84, 0x8b, 0x6a, 0x26, 0x54, 0x21, + 0xff, 0x26, 0xf7, 0xfd, 0x62, 0xef, 0xc2, 0xbc, 0xba, 0x7d, 0x80, 0xcf, 0x8f, 0x97, 0x2a, 0x47, 0xe1, 0x93, 0x91, + 0xdc, 0x6a, 0x25, 0x9f, 0x67, 0x10, 0x32, 0xf3, 0x85, 0x9b, 0xbb, 0x1f, 0xb5, 0xe9, 0xc3, 0x26, 0x7f, 0xd6, 0x81, + 0xe5, 0xb6, 0x79, 0x25, 0x26, 0x7f, 0xac, 0x76, 0x2c, 0xda, 0x7b, 0x77, 0x85, 0x3e, 0x8a, 0xf5, 0xe9, 0x84, 0xbb, + 0x7f, 0xa8, 0x7c, 0x5e, 0x36, 0xfa, 0x48, 0x5d, 0xae, 0x8f, 0x7f, 0x85, 0xee, 0x8b, 0x84, 0x6a, 0x58, 0xe3, 0xbd, + 0x4c, 0xb9, 0x30, 0x7b, 0x81, 0x8d, 0xb9, 0x3a, 0xed, 0x66, 0x52, 0x82, 0x6e, 0xdb, 0xfb, 0x8f, 0xfc, 0x08, 0x67, + 0x11, 0x05, 0x37, 0xf9, 0x9d, 0x19, 0xcb, 0xa1, 0x3f, 0xdf, 0x99, 0x41, 0x2f, 0x1f, 0xc2, 0xde, 0xc5, 0xbb, 0xf4, + 0x01, 0xb9, 0x1e, 0xa7, 0x4a, 0x3e, 0xfb, 0xb1, 0xfe, 0x56, 0xc9, 0x3f, 0x8b, 0x84, 0x79, 0x6b, 0x62, 0x85, 0xb9, + 0x31, 0x49, 0x7e, 0xfb, 0xeb, 0xb6, 0xa5, 0x9d, 0xc9, 0xed, 0x62, 0xd3, 0xba, 0x85, 0x67, 0x42, 0x36, 0x81, 0x89, + 0xd9, 0x2f, 0x52, 0xd0, 0x95, 0x32, 0x35, 0x6e, 0x92, 0xd2, 0xca, 0xb3, 0xce, 0xdb, 0x77, 0xcc, 0x1c, 0xd7, 0xa7, + 0x2a, 0x0b, 0x72, 0xab, 0x28, 0xe4, 0x14, 0xda, 0x63, 0xe4, 0x12, 0x3a, 0x4c, 0x97, 0xdc, 0x45, 0xcc, 0x65, 0x11, + 0xd3, 0x7b, 0x79, 0xee, 0x93, 0x10, 0xd3, 0x66, 0x3b, 0xe5, 0x95, 0xfc, 0x0f, 0xb9, 0x79, 0x90, 0x55, 0x41, 0x1d, + 0x80, 0xe9, 0xfd, 0xd5, 0xfa, 0xf3, 0xd9, 0xd2, 0xe0, 0x54, 0x71, 0xf0, 0xf2, 0x53, 0x69, 0x72, 0xf3, 0xc6, 0x39, + 0xdd, 0x10, 0x95, 0x4a, 0x39, 0x16, 0x83, 0x8e, 0x91, 0xa3, 0x6a, 0x34, 0x8b, 0xf9, 0x04, 0x75, 0xed, 0x24, 0xfe, + 0x78, 0x26, 0x67, 0x35, 0x54, 0x73, 0x17, 0x7c, 0x72, 0x6c, 0x79, 0x37, 0x0d, 0xc5, 0x70, 0x7f, 0xb7, 0x55, 0x3f, + 0x67, 0x74, 0xd6, 0x4d, 0x0f, 0x05, 0x37, 0x70, 0xbe, 0xeb, 0xe1, 0x4b, 0x69, 0xdd, 0xaa, 0x59, 0x2a, 0x51, 0x10, + 0xaa, 0xa4, 0xb9, 0x7a, 0xc3, 0xd4, 0x40, 0x1f, 0x6a, 0xfe, 0x8e, 0x32, 0x98, 0xe2, 0x12, 0x00, 0x35, 0xc9, 0xe1, + 0xdb, 0xd4, 0x42, 0xc9, 0x48, 0x6f, 0x05, 0xe6, 0x18, 0xff, 0x1b, 0x48, 0x43, 0x26, 0x03, 0x6e, 0xf5, 0x35, 0xbf, + 0x99, 0xe4, 0xdf, 0x74, 0xdf, 0x07, 0xe7, 0xd3, 0x38, 0x7d, 0x0d, 0x05, 0xf6, 0x41, 0x7b, 0x9f, 0xf6, 0x9c, 0x29, + 0x69, 0x7b, 0x5c, 0x6d, 0xc5, 0x57, 0xdc, 0x4d, 0x61, 0xf0, 0x4f, 0x0f, 0x84, 0x22, 0xfa, 0x6e, 0xe0, 0x50, 0xb8, + 0x1d, 0x3f, 0x31, 0x8d, 0xa8, 0x43, 0xa6, 0xaa, 0x2f, 0x49, 0x3e, 0xda, 0xfc, 0x21, 0xac, 0x09, 0x8e, 0x1c, 0xe3, + 0xa6, 0x67, 0xa8, 0x88, 0xcc, 0x13, 0xaf, 0x76, 0x0f, 0x9c, 0x9a, 0x80, 0xeb, 0x79, 0x64, 0xde, 0xa7, 0xa9, 0x6d, + 0x70, 0xf1, 0x04, 0xb9, 0x73, 0x03, 0x78, 0xa7, 0x56, 0x57, 0xfb, 0x97, 0x5a, 0xef, 0x42, 0x84, 0x5b, 0x00, 0x51, + 0x8e, 0x5f, 0x64, 0x13, 0xb9, 0x7f, 0x70, 0xe6, 0x62, 0x4e, 0xc3, 0x3d, 0xd2, 0xa1, 0xe4, 0xee, 0x10, 0xb5, 0xce, + 0x2a, 0x67, 0x72, 0xa3, 0x98, 0x25, 0x93, 0x42, 0x00, 0x04, 0xa6, 0x55, 0xbe, 0x22, 0x02, 0xb8, 0x0a, 0x0b, 0x8d, + 0xa6, 0x28, 0xf2, 0x2b, 0xaa, 0xed, 0x67, 0xb4, 0x5b, 0xf6, 0xa3, 0xa3, 0x6b, 0xc7, 0x4c, 0x6a, 0x35, 0x71, 0xe9, + 0x48, 0x0a, 0x66, 0x98, 0xbc, 0xb9, 0x28, 0xe4, 0x15, 0x1f, 0xcc, 0x0f, 0x43, 0x02, 0x53, 0x69, 0x05, 0x85, 0x5c, + 0xaf, 0xb1, 0x33, 0x47, 0xa8, 0xe1, 0x34, 0x6b, 0x3c, 0x3d, 0x7d, 0x5e, 0x8a, 0xd7, 0x8e, 0x53, 0xb5, 0xcd, 0x38, + 0x1d, 0x2c, 0xc2, 0x79, 0x91, 0x76, 0x59, 0xb6, 0x12, 0x81, 0xec, 0xc7, 0xf4, 0x6f, 0xe3, 0xbc, 0xd0, 0xbf, 0x59, + 0xe7, 0x58, 0x9e, 0xc0, 0xc8, 0x12, 0x2d, 0x54, 0xc7, 0xfc, 0xa7, 0x56, 0x6c, 0xad, 0xf0, 0x9d, 0xa8, 0x24, 0xc6, + 0xab, 0x73, 0x69, 0xcf, 0x75, 0xe7, 0x87, 0x10, 0x2c, 0x0f, 0xf0, 0xb3, 0xb8, 0xca, 0xf7, 0x67, 0x85, 0x5b, 0xe9, + 0x3f, 0xeb, 0xe6, 0xef, 0x8a, 0xde, 0x93, 0x8f, 0x1f, 0x52, 0xc4, 0x34, 0x81, 0xf9, 0xae, 0x01, 0x34, 0x55, 0x48, + 0x58, 0x94, 0x2a, 0x6e, 0x43, 0x8e, 0xf7, 0xcf, 0xeb, 0x5e, 0xc4, 0xa2, 0x94, 0x23, 0xbb, 0x8e, 0x3b, 0x7e, 0x29, + 0x30, 0x03, 0x5c, 0xc0, 0xf7, 0x50, 0x4e, 0xa0, 0x1f, 0x3b, 0x8f, 0x8f, 0x44, 0x51, 0x38, 0x65, 0xbc, 0x53, 0x58, + 0xeb, 0xf0, 0x42, 0x79, 0x97, 0x6e, 0x14, 0xd3, 0xa8, 0x89, 0x9f, 0x32, 0xbe, 0xb1, 0x1a, 0x3d, 0xd6, 0x35, 0xba, + 0x1f, 0xcd, 0x8f, 0x82, 0x36, 0xb0, 0x88, 0xbd, 0xff, 0xd3, 0x21, 0xc5, 0xc4, 0xe4, 0xbc, 0x65, 0x2c, 0x70, 0x24, + 0xa4, 0xca, 0xad, 0xcc, 0xf7, 0xa9, 0x88, 0xca, 0xf4, 0x2b, 0x9c, 0xf1, 0x3b, 0x42, 0x44, 0x15, 0x16, 0xfb, 0xa7, + 0xd6, 0x3d, 0x66, 0xd2, 0xcd, 0xa6, 0x3e, 0x55, 0x20, 0x0d, 0x45, 0x9e, 0xaa, 0xe9, 0x25, 0x34, 0xb7, 0xbb, 0xcf, + 0xcf, 0x67, 0x8f, 0x0a, 0xf2, 0xf9, 0xef, 0x0f, 0xfa, 0xfe, 0xbe, 0x90, 0x07, 0xad, 0x6f, 0xe5, 0x33, 0xd4, 0xfe, + 0x75, 0x95, 0x3d, 0x35, 0xc0, 0x99, 0x22, 0x92, 0x97, 0xfc, 0x08, 0xa7, 0x6b, 0x6e, 0x96, 0xbe, 0x7a, 0xca, 0x75, + 0x3f, 0x5d, 0xce, 0x6a, 0x91, 0x1c, 0x33, 0x44, 0xd0, 0xde, 0xc8, 0xb8, 0xc7, 0xf7, 0x59, 0x22, 0x9d, 0x85, 0x09, + 0xba, 0x88, 0xea, 0xf6, 0x68, 0x43, 0xd9, 0xad, 0xe6, 0x2d, 0xf7, 0xc6, 0x1f, 0xe8, 0x7b, 0xd6, 0x8b, 0xa0, 0x34, + 0x94, 0x60, 0xc7, 0xdd, 0xa8, 0x71, 0x44, 0x3a, 0xd7, 0x1d, 0xa4, 0x91, 0x7b, 0xa1, 0x58, 0x52, 0xde, 0x77, 0xb3, + 0xa3, 0x30, 0x69, 0x81, 0x15, 0x76, 0xea, 0xf2, 0xe0, 0x6e, 0x5a, 0x98, 0x75, 0x0a, 0x85, 0xca, 0x74, 0x31, 0xf0, + 0xc5, 0xa6, 0xb4, 0xae, 0x57, 0x0e, 0xc8, 0x01, 0x8c, 0x8e, 0x83, 0x14, 0x26, 0xd5, 0x58, 0x92, 0xca, 0xd0, 0xd1, + 0x72, 0x68, 0x59, 0xaa, 0x14, 0x14, 0xbd, 0x03, 0x0c, 0xca, 0x78, 0xf6, 0xff, 0xc3, 0x9c, 0x0b, 0x83, 0x58, 0x0e, + 0xec, 0x57, 0x64, 0x5f, 0x5d, 0x77, 0xc2, 0x49, 0x54, 0x10, 0xa6, 0xba, 0x91, 0xa9, 0x47, 0x15, 0xd8, 0x84, 0x1c, + 0xd2, 0x24, 0xc9, 0xe9, 0xc0, 0x04, 0x72, 0xe4, 0x69, 0x13, 0x51, 0x17, 0x92, 0xca, 0xe5, 0x97, 0xce, 0xb7, 0x5f, + 0x71, 0xe6, 0x2f, 0x30, 0x92, 0x53, 0x4a, 0xc7, 0x3a, 0x8b, 0xf1, 0x3b, 0xed, 0x7e, 0x3a, 0x6f, 0xfb, 0x9c, 0x5f, + 0x72, 0x80, 0xde, 0x42, 0x55, 0xce, 0x10, 0x90, 0x1e, 0xfa, 0xfe, 0x7a, 0x47, 0xb5, 0xa0, 0x3b, 0x6e, 0xfa, 0xe4, + 0x33, 0xce, 0x5e, 0xad, 0x93, 0xcf, 0x4f, 0xde, 0x28, 0xc4, 0x48, 0x04, 0x5d, 0x3b, 0x52, 0x95, 0x76, 0x9f, 0x6f, + 0xe4, 0x2a, 0x5c, 0xae, 0x41, 0xb3, 0x83, 0xa2, 0x53, 0xda, 0xcf, 0x94, 0xb1, 0xae, 0x7e, 0x4a, 0x0e, 0x1b, 0xb0, + 0xd9, 0x10, 0xe3, 0x48, 0xdc, 0x78, 0xa5, 0x62, 0x80, 0x33, 0x37, 0xaa, 0x61, 0xa5, 0xb7, 0x9d, 0x93, 0x5f, 0xe2, + 0x95, 0x06, 0xcf, 0x13, 0x2c, 0xd1, 0x45, 0x9f, 0x57, 0x8f, 0xd3, 0x51, 0xe6, 0x1b, 0xea, 0xdf, 0xa0, 0xda, 0x26, + 0x5d, 0x88, 0x75, 0x9a, 0xce, 0x21, 0xcf, 0x95, 0x1f, 0xdd, 0x99, 0x20, 0x73, 0x47, 0x85, 0x6b, 0xd5, 0xa0, 0x40, + 0x53, 0xf6, 0xc9, 0x4a, 0x78, 0x74, 0xeb, 0x93, 0x4c, 0xda, 0x47, 0x6b, 0xe5, 0xc3, 0xad, 0x28, 0xfb, 0x77, 0xcf, + 0xbf, 0xf7, 0x99, 0xde, 0x22, 0x1d, 0xd7, 0xac, 0xf6, 0x2f, 0xf8, 0x29, 0xe7, 0x34, 0xde, 0x12, 0xa5, 0x44, 0xe5, + 0x87, 0xe3, 0x80, 0x58, 0xbc, 0x41, 0xfc, 0xd1, 0x0f, 0xdc, 0xec, 0x45, 0xac, 0x2f, 0x55, 0x5a, 0x54, 0x7f, 0xb2, + 0xc7, 0x55, 0x0d, 0x8e, 0x1f, 0xeb, 0xf9, 0x75, 0xac, 0xbc, 0x13, 0x0d, 0xb0, 0x56, 0x02, 0x1f, 0xdb, 0x95, 0x80, + 0x02, 0x22, 0xbd, 0x25, 0x6f, 0xcf, 0xff, 0x77, 0x8b, 0xfd, 0x7e, 0x47, 0xf7, 0xd3, 0xce, 0x8d, 0xaa, 0xd1, 0x69, + 0x53, 0x58, 0x0a, 0xdb, 0xee, 0xb3, 0xc0, 0x45, 0xc6, 0x80, 0x40, 0x35, 0xe6, 0x1f, 0x92, 0x30, 0xa7, 0xc0, 0xbb, + 0x3c, 0x38, 0x8e, 0xfc, 0x96, 0xfa, 0xc6, 0x0a, 0xf7, 0xef, 0xf6, 0xae, 0xb7, 0x20, 0x42, 0x65, 0x9f, 0xa0, 0xdc, + 0x91, 0x3f, 0xf6, 0xd3, 0x0b, 0xd4, 0x47, 0x61, 0xaf, 0x60, 0xd5, 0xd1, 0xa2, 0x6b, 0x07, 0x3a, 0x07, 0xbd, 0x1b, + 0x51, 0x51, 0xf9, 0x98, 0x8d, 0xa5, 0x66, 0x7c, 0x04, 0x30, 0x02, 0x58, 0x0c, 0x71, 0xe2, 0xda, 0x2b, 0xf7, 0x35, + 0xba, 0x02, 0x02, 0x8c, 0xe1, 0x1f, 0x36, 0x38, 0xb7, 0x5e, 0x59, 0x06, 0x9a, 0x1c, 0xe0, 0xd4, 0x26, 0x8b, 0x53, + 0x8b, 0x53, 0xbc, 0xdf, 0xf9, 0xc6, 0xe8, 0xed, 0x05, 0x39, 0x1d, 0xf0, 0x1e, 0x7b, 0x14, 0x15, 0x35, 0x64, 0xa0, + 0x85, 0x6f, 0xbb, 0x21, 0x62, 0x65, 0x30, 0x0b, 0xfa, 0x70, 0xee, 0xfb, 0xf3, 0x4b, 0x2a, 0x54, 0xff, 0x57, 0xaf, + 0xbd, 0xae, 0x5a, 0xf0, 0xc4, 0x35, 0xec, 0x2e, 0xb8, 0x72, 0x4a, 0xed, 0x58, 0xa5, 0xa7, 0x9d, 0x64, 0x50, 0x10, + 0xda, 0x21, 0x85, 0x67, 0xff, 0x67, 0x51, 0x7d, 0x9e, 0x5b, 0xcd, 0xa1, 0xfa, 0xcc, 0x3a, 0x0e, 0x88, 0x7f, 0x3f, + 0xca, 0xbb, 0x3a, 0x08, 0x50, 0x35, 0xe4, 0x93, 0x02, 0xf3, 0x5f, 0xf1, 0x2c, 0x6f, 0x44, 0xba, 0x9d, 0xd9, 0x7d, + 0x8d, 0xcb, 0x99, 0xdc, 0x4e, 0xe6, 0x9b, 0x79, 0xb8, 0xd9, 0x79, 0x7f, 0xbd, 0xa5, 0x4a, 0xda, 0x7a, 0xa5, 0x3e, + 0x3d, 0xe0, 0x38, 0x20, 0xd2, 0x66, 0x19, 0x46, 0x73, 0x7e, 0xee, 0x06, 0xbe, 0x1f, 0x16, 0x61, 0xbe, 0x5f, 0xfb, + 0xb5, 0xe0, 0xc6, 0x24, 0x6f, 0x24, 0x4e, 0xd4, 0xc0, 0x65, 0x8a, 0xa1, 0x2b, 0x05, 0xbc, 0x89, 0x43, 0x5f, 0xc3, + 0x94, 0x1d, 0xf4, 0x5e, 0xb8, 0x1e, 0xf5, 0x74, 0xc4, 0x05, 0xae, 0xba, 0x79, 0x24, 0x93, 0xcc, 0x37, 0x94, 0x31, + 0xde, 0xf0, 0xaa, 0xdf, 0xb8, 0x73, 0xaf, 0x93, 0x32, 0x80, 0x5d, 0x2a, 0x28, 0x7e, 0xbc, 0x6a, 0x55, 0x53, 0x9f, + 0x8a, 0x10, 0xb2, 0x90, 0x4b, 0x01, 0xee, 0xf2, 0xfc, 0x99, 0x7c, 0x1e, 0x5d, 0xdc, 0x0d, 0x55, 0x03, 0xd0, 0x6a, + 0xea, 0xeb, 0x02, 0xc6, 0x91, 0x27, 0x45, 0xca, 0x70, 0x66, 0x6d, 0x78, 0x51, 0xab, 0x4f, 0xb9, 0xa4, 0x21, 0xa3, + 0xb6, 0x53, 0xea, 0x41, 0xbe, 0xd6, 0xd9, 0xec, 0x91, 0x37, 0xb8, 0xa1, 0x65, 0xbb, 0x92, 0x8f, 0x20, 0x8a, 0x26, + 0xc0, 0x72, 0x96, 0xb6, 0x09, 0x32, 0xf8, 0x0e, 0x2d, 0x92, 0xc1, 0x10, 0xb1, 0xc0, 0x9e, 0x77, 0xab, 0xe2, 0xb5, + 0xbd, 0x9c, 0x6a, 0x27, 0xd3, 0xef, 0x72, 0x74, 0xf6, 0x81, 0x3a, 0x1c, 0xac, 0xea, 0x65, 0x17, 0x6a, 0xfd, 0xbb, + 0x1f, 0xda, 0x0a, 0x02, 0x59, 0x03, 0x27, 0x4a, 0x8a, 0xbd, 0x52, 0x65, 0x6b, 0xe4, 0x24, 0xc0, 0x5d, 0x1f, 0xcf, + 0x44, 0x14, 0xb3, 0x74, 0x4e, 0xbf, 0x0b, 0x42, 0x8f, 0x31, 0xac, 0x90, 0x6a, 0x02, 0x8d, 0x9f, 0x5c, 0xd1, 0xdd, + 0x60, 0x35, 0xd9, 0x33, 0xd2, 0x17, 0x63, 0x3d, 0xdd, 0xd9, 0x36, 0xa8, 0x43, 0xfb, 0x6c, 0xb6, 0xaf, 0x2b, 0x8c, + 0x58, 0xf9, 0xa2, 0x1a, 0x7b, 0x61, 0x0b, 0xdc, 0xa9, 0x0b, 0x91, 0xb1, 0x62, 0x66, 0x7a, 0xc2, 0x50, 0x70, 0x5c, + 0x23, 0x1f, 0xe3, 0xc4, 0x4c, 0xa4, 0xb4, 0x2b, 0x76, 0x9a, 0x12, 0x70, 0x0a, 0x84, 0x8e, 0x3d, 0xed, 0xd6, 0x6a, + 0x41, 0xf2, 0x60, 0xe9, 0xb2, 0x1f, 0xe2, 0x7a, 0x3c, 0x2d, 0x29, 0x84, 0x20, 0x5c, 0x9c, 0x9e, 0x75, 0xb3, 0x8c, + 0xe3, 0xc1, 0x94, 0xa6, 0xc3, 0xfe, 0x69, 0x3f, 0xad, 0x0c, 0x3e, 0xde, 0x57, 0x2b, 0x3c, 0x76, 0x20, 0xf8, 0x3c, + 0xfa, 0xde, 0x20, 0xcf, 0xff, 0x34, 0xc9, 0xff, 0x3a, 0x86, 0x40, 0x0d, 0x5b, 0xb1, 0xa0, 0x1b, 0xbe, 0xb1, 0x09, + 0x5e, 0xae, 0x99, 0x57, 0x3a, 0x5b, 0x8b, 0xb3, 0x88, 0x0c, 0x0b, 0x78, 0x7c, 0xf3, 0xe3, 0xfa, 0x23, 0x9c, 0x8d, + 0xcb, 0x18, 0xc3, 0x4b, 0x6e, 0x80, 0x24, 0x21, 0x5c, 0x42, 0xcc, 0x58, 0x77, 0xcf, 0x0d, 0x6e, 0xab, 0x8d, 0xaf, + 0x01, 0xb7, 0x9e, 0x2f, 0xc6, 0xcb, 0x84, 0xf3, 0xe9, 0xcf, 0xca, 0x75, 0x4f, 0xa5, 0xb9, 0x51, 0x6f, 0xb5, 0xfe, + 0xe3, 0xd9, 0xef, 0x1e, 0xb0, 0x24, 0xdc, 0x4f, 0x2d, 0xc3, 0x7c, 0xf2, 0xea, 0x92, 0x89, 0x10, 0xcf, 0x02, 0x5a, + 0x0e, 0x51, 0x88, 0x0f, 0x17, 0x90, 0xe7, 0xee, 0xe8, 0x70, 0xe4, 0x76, 0x9a, 0x4b, 0x23, 0x47, 0x76, 0x30, 0xb4, + 0xa8, 0xa4, 0x0b, 0xab, 0x95, 0x69, 0x9f, 0x4a, 0x37, 0x22, 0x72, 0x20, 0x31, 0x59, 0xb1, 0xcf, 0x30, 0xd3, 0x0e, + 0x9c, 0x7a, 0x40, 0xfc, 0xcf, 0x7f, 0x11, 0x19, 0xca, 0x09, 0x2f, 0xb5, 0xb0, 0x84, 0xa5, 0xca, 0x6c, 0x1f, 0x8f, + 0x9c, 0xca, 0xcc, 0xaa, 0x57, 0x8b, 0x78, 0xeb, 0x8d, 0x86, 0xa6, 0x13, 0x23, 0xc5, 0x07, 0xbe, 0x8c, 0x02, 0x2a, + 0x34, 0xe9, 0xa1, 0x88, 0xd7, 0xf3, 0xcc, 0x39, 0x04, 0xe0, 0x1b, 0x7d, 0xb7, 0x54, 0x75, 0x5d, 0x5f, 0xec, 0x77, + 0x29, 0xf7, 0x25, 0x05, 0xb1, 0xe4, 0xdc, 0x3d, 0xc6, 0x39, 0x1c, 0x39, 0x78, 0x6a, 0x24, 0x15, 0x75, 0x16, 0x89, + 0xc4, 0x82, 0x96, 0xd2, 0xed, 0xb0, 0xdc, 0x03, 0xa6, 0x51, 0xa8, 0x6a, 0xa3, 0xc7, 0x5d, 0x97, 0x00, 0xda, 0xec, + 0x24, 0x84, 0xf7, 0xf0, 0x7d, 0xb6, 0x98, 0x0b, 0xb9, 0xe0, 0x6c, 0x7f, 0x9b, 0x53, 0x29, 0x57, 0xb1, 0x67, 0xa3, + 0xb4, 0x43, 0xf3, 0xed, 0xdc, 0xb3, 0x5a, 0x32, 0x2b, 0x62, 0x0c, 0x91, 0xd3, 0x37, 0x92, 0xb6, 0x0d, 0xd2, 0xe1, + 0x70, 0xcd, 0x90, 0xe0, 0x73, 0x5e, 0x6b, 0x2f, 0xc5, 0x93, 0x71, 0x52, 0xf8, 0x6f, 0x26, 0xd9, 0x79, 0x6d, 0xfd, + 0xa3, 0x3f, 0x24, 0x5b, 0x01, 0xc1, 0x13, 0x7e, 0x35, 0xd9, 0xcc, 0xae, 0xb9, 0xf9, 0xbd, 0x86, 0xf6, 0xd4, 0x52, + 0xb0, 0x66, 0x02, 0xad, 0x4d, 0xca, 0xe7, 0xa2, 0x8f, 0xaf, 0x57, 0x77, 0x24, 0xee, 0xd3, 0x67, 0xd2, 0x35, 0x25, + 0x2f, 0x19, 0x0b, 0xca, 0x37, 0xbc, 0xd9, 0x1f, 0xa3, 0x08, 0xa8, 0x1a, 0x72, 0x05, 0xf5, 0x75, 0x4f, 0xa6, 0xcf, + 0xda, 0x41, 0x58, 0xaf, 0x02, 0x9b, 0x80, 0x22, 0x11, 0xfd, 0xb7, 0x79, 0x8f, 0x3e, 0xe4, 0xd0, 0x1d, 0xb2, 0x37, + 0xb0, 0x9e, 0xac, 0x74, 0x27, 0x11, 0x8a, 0x0a, 0x9f, 0x3b, 0x01, 0xa5, 0x64, 0x07, 0xa5, 0x06, 0x7c, 0xd6, 0x4b, + 0xe4, 0x98, 0xf9, 0xc6, 0xf1, 0x2e, 0xf1, 0x8e, 0xb2, 0xf8, 0xc0, 0x81, 0x9d, 0xea, 0xe7, 0xef, 0x63, 0xf9, 0x72, + 0x8c, 0x07, 0x91, 0xd1, 0xef, 0x45, 0x01, 0xbe, 0xec, 0x37, 0xcd, 0xc8, 0xf3, 0xaf, 0xbf, 0xa5, 0x8d, 0x3c, 0xf3, + 0x6b, 0xa9, 0x84, 0x65, 0xdd, 0x9d, 0x3f, 0x45, 0xbb, 0x94, 0xd8, 0x70, 0x5b, 0xf4, 0xc1, 0x20, 0x97, 0x1b, 0x00, + 0x1f, 0x70, 0x2e, 0xff, 0x99, 0xa3, 0x50, 0x3e, 0x52, 0xeb, 0xf2, 0x64, 0x29, 0xc4, 0x98, 0xfc, 0x8d, 0x51, 0x2d, + 0x67, 0xae, 0x8f, 0xfc, 0x7e, 0xc1, 0x2f, 0x9c, 0x9d, 0xee, 0x07, 0xc8, 0x02, 0x41, 0x8b, 0x15, 0x5d, 0xe9, 0xa1, + 0xa8, 0xa5, 0xaa, 0x18, 0x4a, 0xf3, 0x62, 0x2c, 0x2d, 0x8a, 0x69, 0x63, 0x0f, 0x5e, 0x20, 0x52, 0x70, 0x3d, 0x35, + 0x4b, 0xa6, 0xd0, 0x43, 0xcf, 0xe0, 0x9e, 0xa9, 0xa4, 0xac, 0x75, 0x4e, 0xc3, 0xc0, 0x0a, 0x66, 0xc4, 0x0a, 0x6b, + 0xab, 0x93, 0x96, 0xbd, 0x02, 0x31, 0x96, 0x05, 0x0a, 0x14, 0xaa, 0x83, 0x58, 0x49, 0x15, 0x12, 0xcc, 0xd9, 0x16, + 0x23, 0x3d, 0x5b, 0x49, 0x95, 0xee, 0x34, 0x34, 0xe7, 0x67, 0x85, 0xd1, 0x1b, 0x01, 0xdd, 0xa2, 0xb8, 0xbf, 0x5f, + 0xd7, 0xb0, 0x41, 0x66, 0xa5, 0x2a, 0xaa, 0x17, 0x51, 0x95, 0x69, 0x46, 0x5a, 0x82, 0xec, 0xf9, 0x0c, 0xe4, 0xaa, + 0x72, 0xd4, 0x1e, 0xd3, 0x5e, 0x00, 0xd5, 0xe8, 0xb3, 0xe8, 0xe8, 0x45, 0x9a, 0x43, 0x5d, 0x37, 0x6c, 0xa9, 0x15, + 0x65, 0x52, 0x50, 0xac, 0x91, 0xdf, 0x4e, 0xb2, 0x46, 0x44, 0x76, 0xb3, 0x8b, 0xef, 0xe9, 0xae, 0x92, 0x4d, 0xb2, + 0xf1, 0x69, 0x1c, 0x20, 0xb4, 0x4e, 0x48, 0x2c, 0x6a, 0xbc, 0xe0, 0x2d, 0xe1, 0xd2, 0x72, 0x18, 0x7f, 0x74, 0xbc, + 0xbf, 0xe4, 0x0a, 0x0f, 0xac, 0x48, 0xeb, 0x84, 0x45, 0x7e, 0x32, 0x2e, 0xe0, 0xd7, 0xfe, 0xac, 0x90, 0x59, 0x33, + 0x16, 0xb9, 0xf0, 0x59, 0x94, 0x27, 0xb1, 0xae, 0x2d, 0xdd, 0x93, 0x71, 0xff, 0xd8, 0x99, 0x3a, 0xde, 0x9f, 0x74, + 0x08, 0xfc, 0x02, 0x50, 0xaa, 0x1e, 0x10, 0xfb, 0xc0, 0xf7, 0x78, 0x65, 0x51, 0x04, 0x97, 0xe1, 0xf6, 0x90, 0x8a, + 0xf2, 0x34, 0x77, 0xd5, 0xb4, 0xf2, 0x17, 0x21, 0x09, 0xaa, 0xe1, 0x9b, 0x94, 0xa4, 0x40, 0xe9, 0xa3, 0x1c, 0x26, + 0x3d, 0x62, 0x9f, 0xdf, 0xfb, 0xd2, 0x67, 0xa7, 0xf0, 0xa5, 0x4f, 0xba, 0x66, 0x6d, 0x85, 0xb7, 0xff, 0x36, 0xb0, + 0x83, 0x99, 0x1e, 0xc5, 0xef, 0x87, 0x38, 0x2d, 0xd6, 0x32, 0xea, 0xce, 0x2f, 0x96, 0xbd, 0x0d, 0xf9, 0x3f, 0xfc, + 0xee, 0x82, 0xd3, 0xf0, 0xfd, 0x69, 0xd5, 0xdd, 0x78, 0x5b, 0x39, 0x74, 0xbf, 0x75, 0xbf, 0x6d, 0xa5, 0x5b, 0x3a, + 0x79, 0xe1, 0x7f, 0x7b, 0xef, 0x9c, 0xfb, 0x96, 0x8b, 0xcf, 0x24, 0x33, 0x5e, 0x7d, 0x12, 0xeb, 0x74, 0xac, 0x20, + 0xbd, 0x72, 0x91, 0x49, 0xaf, 0xb7, 0xc6, 0xf1, 0x8b, 0xc4, 0xda, 0xee, 0xc4, 0x9a, 0x7d, 0x50, 0x35, 0x79, 0x8c, + 0xc1, 0xa3, 0xad, 0x2c, 0xa6, 0x3f, 0x58, 0xe7, 0xd1, 0xff, 0x36, 0xb2, 0x39, 0x6e, 0x5c, 0x8e, 0x36, 0x7f, 0xb1, + 0x44, 0x3c, 0x5b, 0xed, 0x57, 0xde, 0xa7, 0xb5, 0x25, 0x8b, 0xbf, 0x49, 0x4b, 0xd2, 0x5a, 0x8c, 0xef, 0xe5, 0x83, + 0x25, 0x7d, 0x8a, 0x3d, 0x07, 0x11, 0x1a, 0xb1, 0xe6, 0x82, 0x1a, 0xb9, 0x4e, 0x57, 0x02, 0xb1, 0x0b, 0x3f, 0x1f, + 0x7a, 0x8a, 0x0b, 0xa4, 0x3a, 0xc8, 0xcb, 0x40, 0x35, 0x51, 0x40, 0x3f, 0x50, 0x53, 0x82, 0x9c, 0x67, 0x7b, 0xc7, + 0xb7, 0x87, 0xaf, 0xf1, 0xf6, 0xcc, 0xd2, 0x46, 0x64, 0x7e, 0x8b, 0x07, 0x47, 0x58, 0x9a, 0xdb, 0x09, 0x93, 0x45, + 0xd8, 0x42, 0xd1, 0xf2, 0x0e, 0xd9, 0x63, 0xf3, 0x4b, 0x03, 0xd5, 0x85, 0x1c, 0xb1, 0x9e, 0xff, 0x5a, 0xef, 0xd2, + 0x15, 0xbc, 0x4b, 0xfb, 0xa2, 0x97, 0x66, 0x3d, 0x04, 0x40, 0x77, 0xea, 0xcf, 0x40, 0x95, 0xb9, 0xa1, 0x28, 0x7d, + 0x7e, 0x9d, 0xb5, 0xa7, 0xda, 0x55, 0xe0, 0xde, 0x69, 0x78, 0x76, 0x42, 0x56, 0x2e, 0x11, 0xfd, 0x18, 0xec, 0x73, + 0x02, 0xfd, 0x41, 0x33, 0xb4, 0xaf, 0x3b, 0x3a, 0x71, 0x09, 0x28, 0x13, 0x75, 0xb8, 0x24, 0x46, 0x30, 0x7e, 0x90, + 0x83, 0x0d, 0xbc, 0x5a, 0xdf, 0xa5, 0x24, 0xae, 0xba, 0x73, 0x08, 0xd1, 0x6b, 0xde, 0xff, 0xea, 0xd7, 0x60, 0xbf, + 0xde, 0xe8, 0x26, 0x23, 0xf2, 0xf7, 0xfc, 0x9c, 0x4b, 0x34, 0x63, 0x88, 0x10, 0x55, 0x2c, 0x5a, 0xf3, 0x1c, 0x0b, + 0x58, 0x9e, 0x97, 0xe0, 0xbb, 0x7c, 0xde, 0x75, 0x62, 0xab, 0x89, 0xa5, 0x6a, 0x30, 0x62, 0x17, 0x0e, 0xde, 0x07, + 0x29, 0x30, 0x70, 0x59, 0x76, 0xd2, 0x7d, 0x47, 0x32, 0x1b, 0x1f, 0x34, 0x07, 0x04, 0x37, 0x3d, 0xc8, 0x02, 0x7f, + 0x23, 0x8c, 0xa1, 0x85, 0x07, 0xeb, 0xa1, 0xd9, 0xa6, 0xbc, 0x06, 0x17, 0xdc, 0x74, 0xa5, 0x22, 0xd5, 0x97, 0xb6, + 0x5a, 0x06, 0x0a, 0x4b, 0xb3, 0x60, 0xe0, 0x5b, 0x5a, 0x2c, 0x8b, 0x10, 0x83, 0x3c, 0x5c, 0xe7, 0x24, 0x84, 0xf2, + 0x04, 0xa1, 0x0e, 0x05, 0x66, 0x3c, 0x38, 0x9d, 0x22, 0x70, 0x30, 0xaf, 0x39, 0xaf, 0x3b, 0xbf, 0x67, 0xc2, 0x32, + 0x4b, 0x8f, 0x7b, 0x0d, 0x97, 0x4b, 0x13, 0x39, 0xd0, 0xbd, 0xd9, 0xfb, 0xdb, 0x2d, 0xf2, 0xbe, 0x11, 0x5a, 0xb1, + 0x0d, 0x17, 0x15, 0x17, 0x59, 0xb4, 0xba, 0xc4, 0xb8, 0x93, 0xae, 0x57, 0xee, 0x85, 0xdd, 0x7a, 0xea, 0x9e, 0xac, + 0x37, 0x4c, 0xe1, 0xd3, 0xb0, 0x8c, 0x25, 0xc4, 0x1a, 0x4b, 0x47, 0xff, 0xbb, 0x2c, 0x7c, 0x96, 0xb5, 0x07, 0x0c, + 0x85, 0xb8, 0x3f, 0xd3, 0xe3, 0x27, 0x00, 0x0e, 0xc7, 0x13, 0x1f, 0x27, 0xe0, 0x40, 0x6b, 0x49, 0xa1, 0x5b, 0x33, + 0x01, 0x11, 0x6b, 0x4b, 0xfe, 0x4b, 0x5f, 0x89, 0x52, 0xf4, 0xd9, 0xb1, 0xeb, 0xdc, 0xe4, 0xfd, 0xdb, 0xea, 0x58, + 0x35, 0x2d, 0x21, 0xef, 0xba, 0x05, 0xea, 0x61, 0xf9, 0xfb, 0xae, 0x58, 0xd1, 0x11, 0x08, 0x3c, 0x7f, 0x63, 0x5a, + 0xac, 0x4f, 0x06, 0x48, 0xd7, 0x83, 0x4f, 0x58, 0x24, 0x9e, 0x82, 0x63, 0x20, 0x8e, 0xab, 0xe1, 0x23, 0xf3, 0xc3, + 0xff, 0x2c, 0x27, 0x56, 0xa6, 0x9d, 0xc9, 0xa9, 0x63, 0xaa, 0x23, 0x83, 0x00, 0xfa, 0x22, 0xf7, 0xb8, 0xee, 0xbf, + 0x3a, 0xb5, 0x54, 0x31, 0x6c, 0xb6, 0x37, 0x71, 0x6b, 0xee, 0xc4, 0x7a, 0xa5, 0xcb, 0xe0, 0xd3, 0xca, 0xfd, 0xe2, + 0xf4, 0x43, 0x26, 0xcc, 0xe0, 0x6c, 0xf1, 0xe5, 0x83, 0x4d, 0x0f, 0x19, 0x0d, 0x80, 0x09, 0x4b, 0xe9, 0x27, 0x83, + 0x94, 0x3e, 0x3f, 0x31, 0x12, 0xda, 0x36, 0xf8, 0x67, 0x6e, 0x2e, 0x47, 0x39, 0xd0, 0x7f, 0x18, 0xec, 0x62, 0xa3, + 0xb7, 0x49, 0x18, 0x3f, 0x40, 0x9a, 0xbd, 0xd1, 0x8f, 0x7a, 0xcd, 0xa1, 0x25, 0x16, 0xe5, 0xd5, 0x93, 0xfc, 0x98, + 0x65, 0x46, 0x01, 0xf8, 0x90, 0xf7, 0x1e, 0xfa, 0xe7, 0x98, 0x62, 0xce, 0xe1, 0xeb, 0xf8, 0xd7, 0x0e, 0x62, 0x6d, + 0xed, 0x74, 0xcd, 0xff, 0xce, 0x5c, 0x78, 0x6a, 0x73, 0xc2, 0x8c, 0xb6, 0x5f, 0xbd, 0xba, 0xda, 0x74, 0x18, 0x01, + 0x34, 0xbe, 0xc2, 0xe8, 0xb1, 0x09, 0xdd, 0x06, 0x66, 0x24, 0xe0, 0x9e, 0x67, 0xd2, 0x95, 0x8e, 0x3f, 0x16, 0xf0, + 0x66, 0xe6, 0x77, 0xa0, 0x09, 0x77, 0x57, 0xd2, 0x68, 0x4b, 0x92, 0x1c, 0xf9, 0x6d, 0xc1, 0x44, 0xb1, 0x75, 0xeb, + 0x26, 0xbc, 0x16, 0xf8, 0xff, 0xf8, 0x41, 0x00, 0xf2, 0x6e, 0x51, 0xb3, 0xa4, 0x76, 0x9a, 0xe6, 0x2b, 0x4d, 0x29, + 0xbb, 0xb0, 0x72, 0x93, 0x5d, 0xce, 0xfc, 0xff, 0x30, 0x82, 0x9b, 0x1c, 0x3e, 0x89, 0x1e, 0xda, 0x57, 0x80, 0xa4, + 0x07, 0x44, 0x17, 0x0f, 0x5a, 0x38, 0x7e, 0x23, 0xca, 0x1c, 0x2c, 0x6c, 0x0b, 0x96, 0x05, 0x83, 0x28, 0x7b, 0x04, + 0xf3, 0x0b, 0x1d, 0x98, 0xfc, 0x4d, 0xef, 0x28, 0xe7, 0x10, 0xe9, 0xd5, 0x77, 0x25, 0xa7, 0xae, 0x9d, 0x5e, 0xfa, + 0xbf, 0x69, 0x02, 0x4c, 0xe6, 0xb6, 0xbe, 0x4e, 0x2d, 0x5f, 0xf8, 0x3c, 0x6b, 0x2f, 0x8a, 0x71, 0xfc, 0xed, 0x8a, + 0x8e, 0x77, 0xc6, 0xac, 0x77, 0x14, 0x35, 0xad, 0xae, 0x7d, 0x75, 0xd3, 0x82, 0x6e, 0x9c, 0x10, 0x3c, 0xc6, 0x87, + 0x58, 0x7e, 0xde, 0x7c, 0x93, 0x50, 0xc7, 0xdf, 0xc6, 0x1e, 0x6f, 0x9b, 0x29, 0x3c, 0xb1, 0x03, 0x7e, 0x47, 0xf7, + 0x96, 0x8e, 0x57, 0x57, 0x4c, 0x7c, 0x08, 0x4e, 0x45, 0x80, 0xd7, 0x93, 0x24, 0xbe, 0x29, 0x89, 0x83, 0x0d, 0xa7, + 0xd6, 0xb6, 0xc2, 0x7d, 0x59, 0xbb, 0x43, 0x16, 0x4e, 0xe3, 0x9b, 0xa8, 0x1b, 0x1e, 0x71, 0xc6, 0x49, 0xdc, 0xea, + 0xa9, 0xef, 0xb6, 0x41, 0x8c, 0xc0, 0xe1, 0x0a, 0x30, 0x3e, 0x11, 0x3e, 0xc4, 0x6c, 0x6a, 0x00, 0xa7, 0x22, 0xb0, + 0xea, 0x87, 0x03, 0x4c, 0xd9, 0xfd, 0x94, 0x0f, 0xe9, 0x88, 0xc0, 0xcc, 0xf4, 0x10, 0xe5, 0xfd, 0xe7, 0xf0, 0x48, + 0xde, 0x9f, 0x4f, 0x86, 0xe1, 0x50, 0xc8, 0xb5, 0xd9, 0xb0, 0x07, 0x56, 0xbe, 0xe0, 0x06, 0xe7, 0x6b, 0xb6, 0xed, + 0xda, 0x84, 0xdc, 0xfc, 0x23, 0x9e, 0x61, 0x97, 0x98, 0xde, 0xdc, 0x3b, 0x5d, 0x47, 0x3d, 0xdf, 0x2b, 0x17, 0x52, + 0xc3, 0x3e, 0xd1, 0xe2, 0xd1, 0xf3, 0x6c, 0xa4, 0x75, 0xc7, 0xc9, 0x5b, 0xfd, 0x4b, 0x72, 0x24, 0x04, 0xc5, 0x4f, + 0xb2, 0xf6, 0x3e, 0x91, 0x6d, 0xdf, 0x05, 0xcf, 0xad, 0xf6, 0x3a, 0x42, 0x77, 0xfa, 0xd3, 0x23, 0x6c, 0x4a, 0xe7, + 0xe7, 0x0e, 0xa0, 0x3a, 0x92, 0xf3, 0xd9, 0xe5, 0x1e, 0x06, 0xe5, 0x70, 0xc5, 0x33, 0x70, 0xb7, 0x62, 0xe6, 0x21, + 0xd2, 0x35, 0x5a, 0x7f, 0xf7, 0x82, 0x37, 0x5c, 0x33, 0x59, 0x1b, 0x91, 0xdc, 0x16, 0xf2, 0x30, 0xc7, 0x08, 0x65, + 0xbe, 0xa0, 0xfc, 0x70, 0xd1, 0x66, 0x72, 0x96, 0x84, 0x2f, 0x24, 0x0a, 0xfc, 0x49, 0x95, 0x67, 0xae, 0x1c, 0x2f, + 0x57, 0x6c, 0x60, 0x2e, 0xe8, 0x8b, 0x51, 0x40, 0x22, 0x73, 0xb7, 0xfc, 0x32, 0xcf, 0x90, 0xfc, 0x35, 0x72, 0x6d, + 0x07, 0x58, 0xbe, 0xce, 0x53, 0x06, 0x37, 0x2e, 0x5a, 0x0b, 0x1d, 0x5f, 0x4a, 0x26, 0x41, 0x91, 0x42, 0xa8, 0xb4, + 0x48, 0x68, 0xd4, 0x2a, 0x15, 0x30, 0x6e, 0xa1, 0xa1, 0xdf, 0x6b, 0xd5, 0xe7, 0x4f, 0xd8, 0xf9, 0x63, 0x94, 0xff, + 0x51, 0x5c, 0x04, 0xc8, 0x91, 0xb7, 0xa8, 0x1b, 0xf0, 0x4c, 0x91, 0xd4, 0x66, 0x8e, 0x4b, 0x24, 0x1c, 0x83, 0x64, + 0x61, 0xb7, 0x61, 0xef, 0x7f, 0xc7, 0xd7, 0x54, 0x90, 0x30, 0x88, 0xf0, 0xeb, 0x2c, 0x83, 0x6e, 0xe0, 0x22, 0x98, + 0x6a, 0x84, 0x07, 0x1c, 0x45, 0xdd, 0x35, 0xab, 0x80, 0x13, 0x28, 0x41, 0xc9, 0x22, 0x89, 0x1f, 0x77, 0xa0, 0xff, + 0x5f, 0x8a, 0x51, 0x7d, 0xd6, 0xd7, 0xb7, 0x15, 0xd4, 0x43, 0x87, 0x02, 0x15, 0x19, 0x37, 0xc0, 0x66, 0x8f, 0x8f, + 0x45, 0x0e, 0xd8, 0x30, 0xf9, 0xaf, 0xb0, 0xb0, 0x52, 0xd9, 0x72, 0x3a, 0xfc, 0xcb, 0x35, 0x8b, 0x83, 0x3d, 0x3c, + 0x4c, 0xe3, 0x30, 0x3e, 0xa5, 0x25, 0x7d, 0x5e, 0xe8, 0xa4, 0x51, 0xd1, 0xf9, 0x71, 0x9e, 0xf5, 0x7d, 0x57, 0xf2, + 0xf8, 0x35, 0x5e, 0x9f, 0xd9, 0x53, 0x74, 0x9d, 0x1f, 0x7e, 0xf4, 0xa3, 0xb1, 0x65, 0xfc, 0x37, 0x7a, 0x61, 0x4f, + 0x17, 0x94, 0x96, 0x81, 0xf7, 0xe9, 0xd1, 0x62, 0x25, 0xfb, 0x82, 0x1c, 0x7d, 0x8c, 0x8e, 0xf6, 0x78, 0x4e, 0xf9, + 0x79, 0x16, 0xe7, 0xfd, 0xed, 0x6b, 0xbc, 0x38, 0xf3, 0xac, 0x5c, 0xeb, 0xcd, 0xa7, 0xde, 0x06, 0xec, 0x2d, 0x70, + 0x3f, 0x89, 0xdd, 0x40, 0x84, 0x93, 0x60, 0x0c, 0xd3, 0xbd, 0x69, 0x44, 0x03, 0xec, 0x77, 0xed, 0xf9, 0xc0, 0x03, + 0xfd, 0xcf, 0xe6, 0xf5, 0xe0, 0xdc, 0x6e, 0x54, 0x53, 0x0a, 0x70, 0xc1, 0x64, 0x45, 0x31, 0x46, 0x82, 0x48, 0x23, + 0xbd, 0x1d, 0x1d, 0xb9, 0xa8, 0x2b, 0x9c, 0x26, 0xba, 0xe4, 0x69, 0xe2, 0x26, 0x65, 0x6b, 0x99, 0x00, 0x50, 0x96, + 0x64, 0xec, 0xd0, 0xf3, 0x7a, 0x80, 0xf4, 0x0e, 0x72, 0x42, 0x2c, 0xc7, 0x25, 0x90, 0x2d, 0x19, 0x7c, 0xfb, 0x0f, + 0xab, 0x40, 0x5e, 0x6f, 0xe8, 0xb0, 0x09, 0x69, 0xf6, 0x38, 0x3d, 0x7d, 0x71, 0x00, 0xae, 0x44, 0xa6, 0x67, 0x9a, + 0x06, 0x17, 0x7d, 0x8e, 0x3e, 0x34, 0xc2, 0x5a, 0x60, 0x2a, 0xea, 0xb4, 0xe5, 0xad, 0x52, 0x71, 0xf3, 0xe0, 0x78, + 0x0a, 0x07, 0x43, 0x33, 0x30, 0x22, 0x7f, 0xfa, 0x0f, 0x1b, 0xc6, 0x72, 0x24, 0xad, 0x6c, 0x98, 0xbf, 0xec, 0x72, + 0x2b, 0x37, 0x4b, 0x12, 0x9a, 0x86, 0x5e, 0x3d, 0x88, 0x15, 0xde, 0xa9, 0xff, 0xe7, 0x41, 0x69, 0x83, 0x38, 0x87, + 0x64, 0x01, 0x51, 0x3c, 0x47, 0x38, 0xc5, 0xa0, 0xc5, 0x6c, 0x90, 0xc3, 0x94, 0x81, 0xc0, 0x2b, 0xab, 0x37, 0x81, + 0x1b, 0x71, 0xb9, 0xec, 0xe9, 0xd4, 0x6b, 0xae, 0x9d, 0xd4, 0x26, 0xb2, 0x08, 0x57, 0xf8, 0xcd, 0x07, 0x80, 0xae, + 0x36, 0xd4, 0x51, 0x08, 0xe4, 0x08, 0x9b, 0xe7, 0x8a, 0x14, 0xdd, 0x78, 0x7c, 0x1b, 0xf6, 0x2d, 0x47, 0x88, 0xcd, + 0x8f, 0xb9, 0x6b, 0x8d, 0x06, 0x8d, 0x4c, 0x32, 0x6c, 0x5c, 0x0a, 0x76, 0x92, 0xa0, 0x87, 0x1a, 0xc7, 0x38, 0x94, + 0x15, 0x7a, 0x1e, 0x19, 0xe3, 0x88, 0xaf, 0x7c, 0xc9, 0x9a, 0x93, 0x68, 0x91, 0x8a, 0x81, 0xfd, 0x1c, 0xbe, 0xce, + 0x0b, 0x41, 0x2e, 0x8e, 0xb8, 0xe9, 0xa9, 0x21, 0xa7, 0x3e, 0x19, 0x14, 0xa8, 0x88, 0x5b, 0xaf, 0x2d, 0x68, 0x98, + 0x47, 0x01, 0x71, 0x6e, 0x16, 0x38, 0xc2, 0x29, 0x2c, 0x6a, 0xff, 0xe0, 0xe8, 0xbc, 0x75, 0xb4, 0x40, 0x90, 0xda, + 0x09, 0x67, 0x38, 0x99, 0xd1, 0x11, 0x32, 0xc3, 0xe5, 0xf1, 0x71, 0x53, 0xd3, 0x5a, 0x53, 0xa7, 0x95, 0x22, 0xc9, + 0x0c, 0x69, 0x26, 0xb0, 0xc4, 0x0f, 0xdb, 0xde, 0x5c, 0xa4, 0x62, 0x45, 0xe0, 0x2d, 0x66, 0xfc, 0x5c, 0xd8, 0x81, + 0xe2, 0xd5, 0x84, 0x0e, 0x6c, 0xaa, 0xfc, 0xdc, 0xe6, 0xa6, 0x27, 0xfc, 0xc2, 0x61, 0xfa, 0x75, 0x26, 0xfa, 0x59, + 0x98, 0xa3, 0xd5, 0x41, 0x2f, 0x5c, 0x21, 0xe3, 0xc4, 0x33, 0x64, 0xd9, 0x94, 0x43, 0xf7, 0x1a, 0x25, 0x8a, 0xa4, + 0x01, 0x39, 0xda, 0x43, 0x4e, 0x2e, 0xf3, 0xa4, 0xd5, 0x34, 0x2a, 0xbb, 0x24, 0xe1, 0x2d, 0x7e, 0xe4, 0x31, 0xa1, + 0x44, 0xf9, 0x3c, 0xcd, 0x33, 0x92, 0xac, 0x71, 0xb7, 0xa3, 0xe0, 0x1a, 0xbd, 0xb5, 0xba, 0xac, 0xd5, 0xb0, 0x9f, + 0xc8, 0xbf, 0x52, 0x47, 0x6f, 0x52, 0x3c, 0x18, 0x04, 0x19, 0x86, 0xab, 0x96, 0xdd, 0x43, 0x8b, 0x1e, 0xfb, 0xa2, + 0xfa, 0x77, 0x83, 0x60, 0xe2, 0x49, 0x21, 0x84, 0x96, 0x91, 0x03, 0xfd, 0x37, 0x55, 0xaa, 0x25, 0x12, 0xde, 0x3b, + 0x9f, 0xb3, 0x77, 0x13, 0xa4, 0x04, 0xb3, 0x4d, 0x95, 0x7b, 0x20, 0x5c, 0x87, 0x80, 0xd7, 0x0d, 0x77, 0xa8, 0x77, + 0x91, 0x5b, 0x11, 0x74, 0x29, 0x05, 0x88, 0x88, 0x00, 0x8c, 0x5e, 0x0c, 0x34, 0x1c, 0xa6, 0x19, 0xac, 0x44, 0x82, + 0x7f, 0x95, 0x85, 0x21, 0xb5, 0xec, 0x28, 0x07, 0xc0, 0x66, 0xb3, 0x11, 0x8c, 0xbe, 0x60, 0x05, 0x7c, 0x36, 0x89, + 0xff, 0xc6, 0xa9, 0x6a, 0xa6, 0x75, 0x23, 0xe5, 0xdd, 0xb8, 0xb1, 0x76, 0x81, 0x18, 0xa6, 0xa5, 0x75, 0x3b, 0x21, + 0x09, 0x28, 0x0d, 0x0b, 0x9f, 0x3c, 0xbf, 0x3d, 0x46, 0xd7, 0xdf, 0x1f, 0x3e, 0x30, 0x49, 0x14, 0x19, 0x55, 0x32, + 0x30, 0x4d, 0x84, 0x8c, 0x6f, 0x11, 0x3a, 0x1e, 0x8e, 0xa6, 0x45, 0x7e, 0xea, 0x75, 0x6c, 0x37, 0x50, 0x8f, 0x2f, + 0xbf, 0xb6, 0xdc, 0x39, 0xd1, 0xda, 0xe9, 0xb8, 0x3f, 0x04, 0x9a, 0x9c, 0x88, 0xaa, 0xb2, 0x18, 0x25, 0xfb, 0x87, + 0x81, 0x6d, 0x24, 0x39, 0xf5, 0x54, 0x18, 0x77, 0x6f, 0x73, 0x4f, 0x87, 0x89, 0x8b, 0x23, 0xff, 0xcb, 0x1f, 0xc1, + 0xb5, 0x52, 0xbc, 0xf2, 0x1d, 0xd8, 0x72, 0x09, 0x57, 0x0e, 0x56, 0x0d, 0x02, 0xa2, 0x94, 0x00, 0x72, 0x1d, 0x1f, + 0x1d, 0xe3, 0x24, 0x79, 0xd7, 0x33, 0xd6, 0xd4, 0x6c, 0x49, 0x69, 0xe6, 0x63, 0x5f, 0x53, 0x69, 0x1e, 0xe7, 0x9a, + 0x60, 0x96, 0x64, 0xd9, 0x49, 0x56, 0x80, 0xd7, 0x74, 0x0d, 0xf3, 0x55, 0x85, 0x40, 0x30, 0xdf, 0x55, 0x99, 0x8b, + 0x53, 0x85, 0xb8, 0x1d, 0x09, 0x6d, 0xaa, 0x45, 0x78, 0xe1, 0xc0, 0x38, 0x9c, 0x5f, 0x33, 0x2d, 0x06, 0x06, 0x20, + 0x57, 0x52, 0x6f, 0x84, 0xf3, 0xf4, 0x20, 0x6f, 0x43, 0xf1, 0xa4, 0xc0, 0x56, 0xac, 0x78, 0xf0, 0xad, 0x97, 0x46, + 0xb3, 0xca, 0x68, 0x97, 0x5b, 0x71, 0xa6, 0xf3, 0xa4, 0xcf, 0x4e, 0x9b, 0xd2, 0xad, 0x87, 0x80, 0x0a, 0xe5, 0xf9, + 0x19, 0xcf, 0xc7, 0x2b, 0xc4, 0x39, 0xe6, 0xac, 0x09, 0xd5, 0x73, 0x61, 0xfd, 0x3a, 0x3d, 0x64, 0xff, 0x7a, 0xbc, + 0xb5, 0xce, 0x54, 0xdc, 0x3c, 0x53, 0xc8, 0x54, 0xfc, 0x15, 0xf7, 0x5e, 0x3c, 0x30, 0x5c, 0x93, 0xc7, 0x90, 0x67, + 0x2a, 0x27, 0x7c, 0x69, 0xa0, 0xe9, 0x20, 0xaa, 0xd3, 0xad, 0x10, 0x57, 0x5d, 0x18, 0xa2, 0x70, 0xf7, 0x29, 0x2f, + 0x48, 0xeb, 0xb0, 0xf7, 0x54, 0xa3, 0xc3, 0xa0, 0xa6, 0x40, 0x9d, 0x16, 0x83, 0x95, 0xb4, 0x5c, 0x50, 0x0e, 0x05, + 0x33, 0xd5, 0x06, 0x1e, 0xd8, 0x9a, 0xff, 0x7f, 0x40, 0x21, 0x7a, 0xdc, 0xf6, 0xaf, 0xfc, 0x05, 0x73, 0xc2, 0x8c, + 0x25, 0x33, 0x3c, 0xbc, 0xda, 0x19, 0x7f, 0x0a, 0xba, 0xb1, 0x6a, 0xa3, 0x8c, 0x55, 0x39, 0x51, 0x06, 0xf7, 0x93, + 0xa5, 0x98, 0x3a, 0x85, 0x0b, 0x31, 0x95, 0x97, 0x7d, 0xa4, 0x92, 0x52, 0x1c, 0x79, 0x51, 0x01, 0xc0, 0xbc, 0x0b, + 0x34, 0x65, 0xca, 0x93, 0x20, 0x09, 0x5c, 0x54, 0x01, 0xd1, 0x8c, 0x97, 0x73, 0x7a, 0xe3, 0x2b, 0x8e, 0x7b, 0xc4, + 0x49, 0x74, 0xe6, 0x10, 0xd4, 0xf5, 0xf9, 0x29, 0x23, 0x62, 0x41, 0xd8, 0x57, 0x8c, 0x43, 0xd9, 0x4e, 0x58, 0x5f, + 0xac, 0xd7, 0x77, 0xde, 0x24, 0x8a, 0xa4, 0x2b, 0xb3, 0x7c, 0xe4, 0xfb, 0x0c, 0x99, 0xad, 0x92, 0x8d, 0x38, 0x86, + 0x32, 0xce, 0x19, 0x8f, 0x62, 0x03, 0x81, 0xb3, 0xa5, 0x2f, 0xb5, 0x90, 0xe3, 0xb2, 0x34, 0x94, 0xc7, 0xc0, 0xb9, + 0x2b, 0xdb, 0x9b, 0xd7, 0xf1, 0x31, 0xe7, 0xfd, 0xb7, 0xeb, 0x4d, 0xad, 0xa8, 0x3f, 0x63, 0xd5, 0x86, 0x7d, 0x81, + 0xa2, 0x79, 0x30, 0xeb, 0x74, 0x8e, 0xf2, 0x88, 0x27, 0x9c, 0x3c, 0x8b, 0x3a, 0xd6, 0xae, 0x8f, 0x92, 0x17, 0x67, + 0xaf, 0xa3, 0xe2, 0x34, 0x88, 0x7e, 0x59, 0xcd, 0x52, 0x07, 0xd7, 0x77, 0xc8, 0x5e, 0xe6, 0x72, 0xed, 0x44, 0xa9, + 0x86, 0x06, 0xce, 0x9f, 0xe4, 0xab, 0xd8, 0x3e, 0xe1, 0x2c, 0x67, 0xa2, 0xca, 0x7e, 0x9d, 0x07, 0xa9, 0x30, 0xe7, + 0xf8, 0xe3, 0xd2, 0x86, 0xe8, 0x2b, 0x22, 0x24, 0xe6, 0xac, 0xfb, 0xce, 0xa6, 0x2c, 0x71, 0xe9, 0xc3, 0x08, 0xa1, + 0x9f, 0x18, 0xa1, 0x19, 0x47, 0x3d, 0x6f, 0xfe, 0xb7, 0x91, 0xef, 0xb3, 0x9e, 0x53, 0x74, 0xc7, 0x7b, 0xb2, 0x1a, + 0x2a, 0xdb, 0xe9, 0x67, 0xee, 0xd4, 0x9e, 0x82, 0x53, 0x7b, 0x82, 0x4a, 0x90, 0xc0, 0xcf, 0x0b, 0xcf, 0xf1, 0xa4, + 0xd9, 0x54, 0x17, 0x4f, 0xdb, 0x5f, 0x8d, 0xcf, 0x2f, 0x95, 0x8d, 0xaf, 0x38, 0xbb, 0x52, 0x68, 0x67, 0x78, 0x4b, + 0x67, 0xae, 0x0c}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index b230f2a906..bd47071dce 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -379,7308 +379,7310 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xd0, 0x69, 0x79, 0x18, 0x5b, 0x98, 0x9e, 0x2f, 0x6e, 0xf7, 0xac, 0x60, 0x80, 0x15, 0xdb, 0xbd, 0x1d, 0x24, 0xa7, 0xea, 0x80, 0x51, 0xc5, 0x36, 0x7f, 0xe1, 0x11, 0x05, 0xdc, 0x30, 0x48, 0x3b, 0x30, 0x72, 0x2a, 0xac, 0xc0, 0x70, 0x75, 0xc3, 0xc7, 0x7a, 0x96, 0xb6, 0x5b, 0xad, 0xef, 0x2a, 0x4c, 0xea, 0xcd, 0xec, 0x92, 0xb6, 0x0b, 0x36, 0xaf, - 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0x76, - 0xa6, 0xcc, 0xc5, 0x8c, 0x15, 0x5c, 0xf7, 0xea, 0x5f, 0x55, 0xc7, 0xbb, 0x73, 0xda, 0x58, 0xf9, 0x78, 0x65, 0x6b, - 0xb8, 0xcb, 0xd8, 0xc7, 0xf0, 0xb1, 0x8b, 0x95, 0x5f, 0x68, 0x11, 0x6f, 0x6d, 0x18, 0x1c, 0xd6, 0x40, 0x9b, 0x60, - 0xce, 0x05, 0x98, 0x8a, 0x0e, 0xf1, 0x57, 0xa0, 0x90, 0xd1, 0x3c, 0x8b, 0x61, 0x44, 0x07, 0xcd, 0x83, 0xd3, 0x82, - 0xcd, 0x91, 0x07, 0x44, 0x72, 0xbf, 0x5b, 0xb0, 0xf9, 0x26, 0x31, 0xd5, 0x57, 0x06, 0x75, 0x69, 0xce, 0xa7, 0x22, - 0xcd, 0x18, 0x6c, 0xab, 0x4d, 0xc2, 0x84, 0xe6, 0xfa, 0xae, 0x59, 0xc8, 0x9b, 0xd5, 0x98, 0xab, 0x45, 0x4e, 0xef, - 0xd2, 0x49, 0xce, 0x6e, 0x7b, 0xa6, 0x54, 0x93, 0x6b, 0x36, 0x57, 0xae, 0x6c, 0x0f, 0xd2, 0x9b, 0x63, 0x6b, 0xce, - 0x01, 0xd0, 0x93, 0x37, 0xdb, 0xfb, 0xda, 0x2f, 0x5a, 0x53, 0x2e, 0xf5, 0x41, 0x4b, 0xf5, 0xe6, 0x5c, 0x34, 0xdd, - 0x40, 0xce, 0x00, 0x23, 0x76, 0x21, 0x1f, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, 0x36, 0x5e, 0x05, 0xd5, 0x3a, - 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x1b, 0xb4, 0xb8, 0x23, 0xd0, 0x57, 0x50, 0xfe, 0x41, 0x0b, 0xdb, - 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xae, 0x09, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, - 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, 0x2b, 0x98, 0x7f, 0xda, 0x3a, - 0x68, 0x1d, 0x98, 0xb9, 0xb8, 0x6d, 0x70, 0x76, 0x76, 0xff, 0xf4, 0x01, 0xeb, 0xe5, 0x5c, 0xb0, 0xda, 0x54, 0xbf, - 0x09, 0xea, 0xb0, 0xe1, 0x8e, 0x6b, 0xb8, 0x7d, 0xd0, 0x3e, 0x38, 0x6b, 0x7d, 0xe7, 0xa9, 0x48, 0xce, 0x26, 0xda, - 0xee, 0x9b, 0x1a, 0x59, 0xb9, 0xf0, 0x4d, 0xdf, 0x14, 0x74, 0x91, 0x0a, 0x09, 0x7f, 0x7a, 0xb0, 0xf9, 0x27, 0xb9, - 0xbc, 0x49, 0x67, 0x7c, 0x3c, 0x06, 0x17, 0x2e, 0x28, 0x50, 0x26, 0xb2, 0x3c, 0xe7, 0x0b, 0xc5, 0xed, 0x6a, 0x38, - 0xdc, 0xed, 0x6e, 0x41, 0x35, 0x1c, 0xd0, 0x69, 0x30, 0xa0, 0x6e, 0x35, 0xa0, 0xaa, 0xff, 0x70, 0x84, 0x9d, 0xad, - 0xb9, 0x9a, 0x52, 0xbd, 0x1a, 0x26, 0x7d, 0x5a, 0x2a, 0x0d, 0x30, 0xf7, 0xc6, 0x23, 0xe6, 0x74, 0x69, 0x8e, 0x98, - 0xbe, 0x61, 0x4c, 0x7c, 0x7d, 0x10, 0x57, 0xa9, 0x14, 0xf9, 0x9d, 0xfd, 0x5c, 0x85, 0x5d, 0xd2, 0xa5, 0x96, 0x9b, - 0x64, 0xc4, 0x05, 0x2d, 0xee, 0x3e, 0x2a, 0x26, 0x94, 0x2c, 0x3e, 0xca, 0xc9, 0x64, 0xf5, 0x35, 0x92, 0x77, 0x1f, - 0x6d, 0x12, 0xc5, 0xc5, 0x34, 0x67, 0x96, 0xc0, 0x19, 0x44, 0x70, 0x87, 0x8c, 0x6d, 0xd7, 0x34, 0x59, 0x1b, 0xf4, - 0x26, 0xc9, 0x72, 0x3e, 0xa7, 0x9a, 0x19, 0x38, 0x07, 0xa4, 0xc6, 0x4d, 0xde, 0x52, 0xb9, 0xd6, 0x81, 0xfd, 0x53, - 0x95, 0x86, 0x6d, 0x14, 0x14, 0xf6, 0x4d, 0x72, 0x61, 0xf0, 0xc3, 0x80, 0xc3, 0xec, 0x22, 0xb3, 0x7a, 0x66, 0xed, - 0x02, 0xd8, 0xc1, 0xec, 0x6a, 0x4d, 0x5d, 0x39, 0xba, 0x64, 0x5b, 0xec, 0xb6, 0xbe, 0xab, 0xe7, 0xe6, 0x74, 0xc4, - 0xf2, 0x95, 0xdd, 0xa8, 0x1e, 0xb8, 0x6e, 0xab, 0x86, 0xcb, 0x1c, 0x90, 0x0c, 0x03, 0xa2, 0x61, 0x9a, 0x36, 0x6f, - 0xd8, 0xe8, 0x33, 0xd7, 0x76, 0xcb, 0x34, 0xd5, 0x0d, 0x38, 0x15, 0x99, 0x31, 0x2d, 0x58, 0xb1, 0xf2, 0x84, 0xbc, - 0x55, 0x23, 0xa0, 0xbf, 0x08, 0x73, 0x40, 0x6b, 0x3a, 0x6a, 0x42, 0x88, 0x35, 0x56, 0xac, 0xf6, 0x4d, 0x6e, 0x4e, - 0x6f, 0x1d, 0x8a, 0x3d, 0x68, 0x7d, 0x57, 0x3b, 0x64, 0xcf, 0x5a, 0x2d, 0x7f, 0x44, 0x34, 0x6d, 0x8d, 0xb4, 0x9d, - 0x74, 0xd9, 0xbc, 0x4c, 0xd4, 0x72, 0x91, 0xd6, 0x12, 0x46, 0x52, 0x6b, 0x39, 0xb7, 0x69, 0x7b, 0xa8, 0x51, 0x9d, - 0xf4, 0xb6, 0x3b, 0x8b, 0xdb, 0x03, 0xf3, 0x4f, 0xeb, 0xa0, 0xb5, 0x4b, 0x6a, 0x77, 0xb1, 0xe2, 0x14, 0x79, 0x3c, - 0x86, 0x8e, 0xdb, 0x6c, 0xde, 0x5b, 0x2a, 0x38, 0xee, 0x0d, 0xc4, 0xcd, 0x89, 0xb6, 0x31, 0x93, 0x05, 0xc0, 0x52, - 0x2e, 0xe0, 0x74, 0xb5, 0x87, 0x1d, 0xf4, 0xa1, 0x24, 0x98, 0xc3, 0xef, 0x6d, 0xb4, 0x3e, 0xac, 0xd6, 0x41, 0x35, - 0x30, 0xf8, 0x67, 0xf3, 0x57, 0xc5, 0x9f, 0x3f, 0x61, 0x81, 0x7c, 0xc4, 0x1b, 0x49, 0x77, 0xdd, 0x72, 0x32, 0xd1, - 0x58, 0x57, 0xa2, 0x9a, 0xf1, 0x28, 0x99, 0xd3, 0x5b, 0xeb, 0x5a, 0x32, 0xe7, 0x02, 0x0c, 0xd7, 0x10, 0xd6, 0x81, - 0x89, 0xff, 0x2c, 0x6c, 0x68, 0xac, 0x63, 0x68, 0xf8, 0xb8, 0x93, 0x74, 0xbb, 0x08, 0xb7, 0x70, 0xa7, 0xdb, 0x0d, - 0x64, 0xb2, 0x89, 0xde, 0x57, 0x74, 0x5f, 0x49, 0xb9, 0xa7, 0xe4, 0x89, 0x69, 0xf4, 0xa4, 0xdd, 0x6a, 0x61, 0xe3, - 0x3e, 0x5f, 0x16, 0x16, 0x6a, 0x4f, 0xb3, 0xed, 0x56, 0x0b, 0x9a, 0x85, 0x3f, 0x6e, 0x5e, 0x3f, 0x91, 0x55, 0x2b, - 0x6d, 0xe1, 0x76, 0xda, 0xc6, 0x9d, 0xb4, 0x83, 0x4f, 0xd3, 0x53, 0x7c, 0x96, 0x9e, 0xe1, 0x6e, 0xda, 0xc5, 0xe7, - 0xe9, 0x39, 0xbe, 0x9f, 0xde, 0xc7, 0x17, 0xe9, 0x05, 0x7e, 0x90, 0x3e, 0xc0, 0x0f, 0xd3, 0x76, 0x0b, 0x3f, 0x4a, - 0xdb, 0x6d, 0xfc, 0x38, 0x6d, 0x77, 0xf0, 0x93, 0xb4, 0x7d, 0x8a, 0x9f, 0xa6, 0xed, 0x33, 0xfc, 0x2c, 0x6d, 0x77, - 0x31, 0x85, 0xdc, 0x11, 0xe4, 0x66, 0x90, 0x3b, 0x86, 0x5c, 0x06, 0xb9, 0x93, 0xb4, 0xdd, 0xdd, 0x60, 0x69, 0x43, - 0x6e, 0x44, 0xad, 0x76, 0xe7, 0xf4, 0xac, 0x7b, 0x7e, 0xff, 0xe2, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x7d, 0x16, - 0x0d, 0xf1, 0x9d, 0xf1, 0x7c, 0x91, 0x62, 0xc0, 0x8f, 0xda, 0xdd, 0x21, 0xbe, 0xf5, 0x9f, 0x31, 0x3f, 0xea, 0x9c, - 0xb5, 0xd0, 0xd5, 0xd5, 0xd9, 0xb0, 0x51, 0xe6, 0x3e, 0x32, 0x0e, 0x37, 0x55, 0x16, 0x21, 0x24, 0x86, 0x1c, 0x84, - 0xbf, 0x58, 0x07, 0x1a, 0x16, 0xf3, 0xa4, 0x40, 0x47, 0x47, 0xe6, 0xc7, 0xd4, 0xff, 0x18, 0xf9, 0x1f, 0x34, 0x58, - 0xa4, 0x1b, 0x1a, 0x3b, 0x8f, 0x6b, 0x5d, 0xfa, 0x3b, 0x94, 0xa6, 0x44, 0x07, 0xdc, 0x19, 0xf5, 0xff, 0x57, 0x64, - 0x8d, 0x76, 0xc8, 0x99, 0x55, 0x8c, 0x75, 0xfb, 0x8c, 0xac, 0x8a, 0xb4, 0xd3, 0xed, 0x1e, 0xfd, 0x34, 0xe0, 0x83, - 0xf6, 0x70, 0x78, 0xdc, 0xbe, 0x8f, 0xa7, 0x65, 0x42, 0xc7, 0x26, 0x8c, 0xca, 0x84, 0x53, 0x9b, 0x40, 0x53, 0x5b, - 0x1b, 0x92, 0xce, 0x4c, 0x12, 0x94, 0xd8, 0xa4, 0xa6, 0xed, 0xfb, 0xb6, 0xed, 0x07, 0x60, 0x4d, 0x66, 0x9a, 0x77, - 0x4d, 0x5f, 0x5e, 0x9e, 0xad, 0x5d, 0xa3, 0x78, 0x9a, 0xba, 0xd6, 0x7c, 0xe2, 0xd9, 0x70, 0x88, 0x47, 0x26, 0xb1, - 0x5b, 0x25, 0x9e, 0x0f, 0x87, 0xae, 0xab, 0x07, 0xa6, 0xab, 0xfb, 0x55, 0xd6, 0xc5, 0x70, 0x68, 0xba, 0x44, 0x2e, - 0x76, 0x80, 0xd2, 0x07, 0x9f, 0x4b, 0xfd, 0x0d, 0xbf, 0xec, 0x74, 0xbb, 0x7d, 0xc0, 0x30, 0x63, 0x13, 0xec, 0x61, - 0x74, 0x1d, 0xc0, 0xe8, 0x0b, 0xfc, 0xee, 0xdf, 0xd1, 0xf4, 0x96, 0x96, 0x40, 0xea, 0x47, 0xff, 0x15, 0x35, 0xb4, - 0x81, 0xb9, 0xf9, 0x33, 0xb5, 0x7f, 0x46, 0xa8, 0xf1, 0x99, 0x02, 0xb8, 0x41, 0x23, 0xe5, 0x55, 0xca, 0xa6, 0xc7, - 0x5f, 0x28, 0xb8, 0xf8, 0xcc, 0x54, 0x4e, 0xfb, 0xeb, 0xd9, 0xcd, 0x68, 0x3d, 0x53, 0x5f, 0xd0, 0x9f, 0xf1, 0x9f, - 0xea, 0x38, 0x1e, 0x34, 0x1b, 0x09, 0xfb, 0x73, 0x0c, 0xbe, 0x44, 0xfd, 0x74, 0xcc, 0xa6, 0xa8, 0x3f, 0xf8, 0x53, - 0xe1, 0x61, 0x23, 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0x50, 0x1f, 0xf5, 0xff, 0x54, - 0xc7, 0x7f, 0xa2, 0x7b, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x85, 0x1f, 0x3a, 0x2e, 0xb7, 0x30, 0xc3, 0xed, - 0x26, 0x83, 0x60, 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe0, 0x27, 0xa7, 0x2d, 0xf4, 0x5d, 0xbb, 0x03, 0xca, 0x95, - 0xa6, 0x38, 0xde, 0xdd, 0xf4, 0x45, 0xf3, 0x14, 0x3f, 0x68, 0x16, 0xb8, 0x8d, 0x70, 0xb3, 0xed, 0xb5, 0xde, 0x03, - 0x15, 0xb7, 0x10, 0x56, 0xf1, 0x05, 0xfc, 0x73, 0x86, 0x86, 0xd5, 0x86, 0x7c, 0x4c, 0xb7, 0x7b, 0x07, 0xbf, 0x59, - 0x12, 0xab, 0x06, 0x3f, 0x39, 0x6f, 0xa1, 0xef, 0xce, 0x4d, 0x47, 0xec, 0x58, 0xef, 0xe9, 0x4a, 0xe2, 0xb3, 0xa6, - 0x84, 0x8e, 0x5a, 0x65, 0x3f, 0x22, 0xee, 0x22, 0x2c, 0xe2, 0x53, 0xf8, 0xa7, 0x1d, 0xf6, 0x73, 0x6f, 0xa7, 0x1f, - 0x33, 0xef, 0x36, 0x4e, 0xba, 0xd6, 0x0d, 0x57, 0xd9, 0x3b, 0xf1, 0x06, 0xbb, 0x6a, 0x9b, 0xcb, 0xbc, 0xf6, 0x09, - 0x7c, 0x20, 0xac, 0x8f, 0x89, 0xc2, 0xec, 0x18, 0xfc, 0x77, 0xc1, 0x6c, 0x45, 0x5d, 0x9e, 0xf6, 0x54, 0xa3, 0x81, - 0xc4, 0x40, 0x0d, 0x8f, 0x49, 0xbb, 0xa9, 0x9b, 0x0c, 0xc3, 0xef, 0x06, 0x29, 0x83, 0xc2, 0x89, 0xaa, 0xd7, 0x57, - 0xae, 0x57, 0x7b, 0xf3, 0xef, 0xb1, 0x83, 0x10, 0xa2, 0xfa, 0xb1, 0x6e, 0x32, 0x74, 0x22, 0x1a, 0xb1, 0xbe, 0x64, - 0xfd, 0xf3, 0xb4, 0x85, 0x0c, 0x76, 0xaa, 0x7e, 0xcc, 0x9a, 0x1c, 0xd2, 0x3b, 0x69, 0xcc, 0x9b, 0x1a, 0x7e, 0x9d, - 0x05, 0xd0, 0x12, 0x80, 0x77, 0x95, 0x37, 0x52, 0x71, 0xd2, 0xe9, 0x76, 0xb1, 0x20, 0x3c, 0x99, 0x9a, 0x5f, 0x8a, - 0xf0, 0x64, 0x64, 0x7e, 0x49, 0x52, 0xc2, 0xcb, 0xf6, 0x8e, 0x0b, 0x12, 0xac, 0xaa, 0x49, 0xa1, 0xb0, 0xa0, 0x05, - 0x3a, 0xe9, 0x78, 0xb3, 0x00, 0x3c, 0xf3, 0x73, 0x00, 0x35, 0x48, 0x61, 0x2c, 0x42, 0x65, 0xb3, 0xc0, 0x39, 0xa1, - 0x57, 0x49, 0xb7, 0x3f, 0x3b, 0x89, 0x3b, 0x4d, 0xd9, 0x2c, 0x50, 0x3a, 0x3b, 0x31, 0x35, 0x71, 0x46, 0x5e, 0x51, - 0xdb, 0x1a, 0x9e, 0xc1, 0x5d, 0x6e, 0x46, 0xb2, 0xe3, 0xf3, 0x56, 0x23, 0xe9, 0x22, 0x3c, 0xc8, 0xd6, 0x2d, 0x9c, - 0xaf, 0xd7, 0x2d, 0x4c, 0xc3, 0x65, 0x10, 0x1e, 0x20, 0xa5, 0xa6, 0x6e, 0x3b, 0x36, 0x4f, 0x9f, 0xc7, 0x1a, 0xec, - 0x12, 0x34, 0x78, 0xfb, 0x68, 0xf0, 0x43, 0x4a, 0xb9, 0xbb, 0x10, 0x44, 0x26, 0x3a, 0xe1, 0x24, 0xd4, 0xdd, 0xbd, - 0x12, 0x7e, 0x5d, 0xdd, 0xc8, 0xef, 0x89, 0xf8, 0x83, 0xc4, 0x36, 0xad, 0x2a, 0xf6, 0x9a, 0xee, 0x16, 0xbb, 0x47, - 0x77, 0x8a, 0x3d, 0xdc, 0x53, 0xec, 0xf1, 0x6e, 0xb1, 0xbf, 0x65, 0xa0, 0x69, 0xe4, 0xdf, 0x9d, 0x9e, 0xb7, 0x1a, - 0xa7, 0x80, 0xac, 0xa7, 0xe7, 0xad, 0xaa, 0xd0, 0x53, 0x5a, 0xad, 0x95, 0x26, 0xbf, 0x50, 0xeb, 0x6b, 0xc1, 0xbd, - 0xd3, 0xb7, 0x59, 0x38, 0xeb, 0x72, 0x5e, 0xfa, 0x97, 0x0f, 0xba, 0x60, 0xcb, 0x22, 0x0c, 0xb5, 0xd3, 0x83, 0xf3, - 0x61, 0x7f, 0xc6, 0xe2, 0x06, 0xa4, 0xa2, 0x74, 0xa2, 0xdd, 0x2f, 0x54, 0x5e, 0x69, 0xff, 0x2d, 0x21, 0xa9, 0x33, - 0x44, 0x58, 0x92, 0x86, 0x1e, 0x9c, 0x0e, 0xcd, 0x79, 0x57, 0xc0, 0xef, 0x33, 0xf3, 0xbb, 0x54, 0x28, 0x39, 0x87, - 0x8c, 0xd9, 0xcd, 0x28, 0xea, 0x0b, 0xf2, 0x9a, 0xc6, 0xc6, 0xc6, 0x1e, 0xa5, 0x65, 0x86, 0xfa, 0x02, 0x19, 0x0f, - 0xcb, 0x0c, 0x41, 0x5e, 0x09, 0xf7, 0x1b, 0xaf, 0x8a, 0x14, 0xec, 0x6d, 0xf0, 0x34, 0x05, 0x5b, 0x1b, 0x3c, 0x4a, - 0x05, 0xf8, 0x83, 0xd0, 0x94, 0x05, 0x56, 0xfc, 0x2f, 0x9c, 0x06, 0xcf, 0xdc, 0x3a, 0x13, 0x83, 0xa5, 0x3d, 0x06, - 0x27, 0xc5, 0xdf, 0x32, 0x86, 0xbf, 0x0d, 0x8d, 0x30, 0x83, 0x36, 0x19, 0xc2, 0x3c, 0x29, 0x08, 0xa4, 0x61, 0x9e, - 0x4c, 0x09, 0x83, 0x26, 0x79, 0x32, 0x22, 0x6c, 0xd0, 0x09, 0xd0, 0xe4, 0x89, 0x81, 0x1d, 0x00, 0x87, 0xd7, 0x2f, - 0xf2, 0xb5, 0x6d, 0x1c, 0x2c, 0x04, 0xa0, 0x09, 0x41, 0x20, 0xe6, 0xc2, 0x00, 0xcc, 0x46, 0x94, 0xfd, 0xd9, 0xa9, - 0xc2, 0x5f, 0xf2, 0x84, 0x1a, 0xea, 0xfd, 0x17, 0x90, 0xd5, 0xf8, 0xde, 0x8a, 0x6d, 0xf0, 0xc1, 0xbd, 0x95, 0xd8, - 0x7c, 0x07, 0x7f, 0x94, 0xfd, 0x03, 0xcc, 0x43, 0x42, 0xd1, 0x06, 0xfd, 0x95, 0x42, 0xb1, 0x3d, 0xa5, 0xd0, 0x5f, - 0x8e, 0x44, 0x2b, 0x45, 0x56, 0xb7, 0x69, 0x34, 0xa6, 0xc5, 0xe7, 0x08, 0xff, 0x91, 0x46, 0x39, 0x70, 0x8b, 0x11, - 0xfe, 0x90, 0x46, 0x05, 0x8b, 0xf0, 0xef, 0x69, 0x34, 0xca, 0x97, 0x11, 0xfe, 0x2d, 0x8d, 0xa6, 0x45, 0x84, 0xdf, - 0x83, 0xb2, 0x76, 0xcc, 0x97, 0xf3, 0x08, 0xbf, 0x4b, 0x23, 0x65, 0xbc, 0x21, 0xf0, 0xc3, 0x34, 0x62, 0x2c, 0xc2, - 0x6f, 0xd3, 0x48, 0xe6, 0x11, 0xbe, 0x4e, 0x23, 0x59, 0x44, 0xf8, 0x51, 0x1a, 0x15, 0x34, 0xc2, 0x8f, 0xd3, 0x08, - 0x0a, 0x4d, 0x23, 0xfc, 0x24, 0x8d, 0xa0, 0x65, 0x15, 0xe1, 0x37, 0x69, 0xc4, 0x45, 0x84, 0x7f, 0x4d, 0x23, 0xbd, - 0x2c, 0xfe, 0x5e, 0x4a, 0xae, 0x22, 0xfc, 0x34, 0x8d, 0x66, 0x3c, 0xc2, 0xaf, 0xd3, 0xa8, 0x90, 0x11, 0x7e, 0x95, - 0x46, 0x34, 0x8f, 0xf0, 0xcb, 0x34, 0xca, 0x59, 0x84, 0x7f, 0x49, 0xa3, 0x31, 0x8b, 0xf0, 0xcf, 0x69, 0x74, 0xc7, - 0xf2, 0x5c, 0x46, 0xf8, 0x59, 0x1a, 0x31, 0x11, 0xe1, 0x9f, 0xd2, 0x28, 0x9b, 0x45, 0xf8, 0x87, 0x34, 0xa2, 0xc5, - 0x67, 0x15, 0xe1, 0xe7, 0x69, 0xc4, 0x68, 0x84, 0x5f, 0xd8, 0x8e, 0xa6, 0x11, 0xfe, 0x31, 0x8d, 0x6e, 0x66, 0xd1, - 0x06, 0x4b, 0x45, 0x56, 0xaf, 0x78, 0xc6, 0x7e, 0x67, 0x69, 0x34, 0x69, 0x4d, 0x2e, 0x26, 0x93, 0x08, 0x53, 0xa1, - 0xf9, 0xdf, 0x4b, 0x76, 0xf3, 0x54, 0x43, 0x22, 0x65, 0xa3, 0xf1, 0xfd, 0x08, 0xd3, 0xbf, 0x97, 0x34, 0x8d, 0x26, - 0x13, 0x53, 0xe0, 0xef, 0x25, 0x9d, 0xd3, 0xe2, 0x0d, 0x4b, 0xa3, 0xfb, 0x93, 0xc9, 0x64, 0x7c, 0x16, 0x61, 0xfa, - 0xcf, 0xf2, 0x83, 0x69, 0xc1, 0x14, 0x18, 0x31, 0x3e, 0x85, 0xba, 0xdd, 0x49, 0x77, 0x9c, 0x45, 0x78, 0xc4, 0xd5, - 0xdf, 0x4b, 0xf8, 0x9e, 0xb0, 0xb3, 0xec, 0x2c, 0xc2, 0xa3, 0x9c, 0x66, 0x9f, 0xd3, 0xa8, 0x65, 0x7e, 0x89, 0x9f, - 0xd8, 0xf8, 0xd5, 0x5c, 0x9a, 0xab, 0x8c, 0x09, 0x1b, 0x65, 0xe3, 0x08, 0x9b, 0xc1, 0x4c, 0xe0, 0xef, 0x17, 0xfe, - 0x96, 0xe9, 0x34, 0xba, 0xa0, 0x9d, 0x11, 0xeb, 0x44, 0x78, 0xf4, 0xfa, 0x46, 0xa4, 0x11, 0xed, 0x76, 0x68, 0x87, - 0x46, 0x78, 0xb4, 0x2c, 0xf2, 0xbb, 0x1b, 0x29, 0xc7, 0x00, 0x84, 0xd1, 0xc5, 0xc5, 0xfd, 0x08, 0x67, 0xf4, 0x17, - 0x0d, 0xb5, 0xbb, 0x93, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x13, 0x2d, 0xf4, 0x87, 0xa5, 0x72, 0x03, 0x6d, 0x41, 0x8a, - 0xcc, 0xde, 0x82, 0x9a, 0x3f, 0x1a, 0x77, 0xce, 0x1f, 0xb4, 0x59, 0x84, 0xb3, 0xeb, 0x57, 0xd0, 0xdb, 0xfd, 0x49, - 0xb7, 0x05, 0x1f, 0x02, 0xe4, 0x52, 0x56, 0x40, 0x23, 0xe7, 0x67, 0x0f, 0xba, 0x6c, 0x6c, 0x12, 0x15, 0xcf, 0x3f, - 0x9b, 0xd9, 0x5f, 0xc0, 0x7c, 0xb2, 0x82, 0xcf, 0x95, 0x14, 0x69, 0x34, 0xce, 0xda, 0x67, 0xa7, 0x90, 0x70, 0x47, - 0x85, 0x07, 0xce, 0x2d, 0x54, 0xbd, 0x18, 0x45, 0xf8, 0xd6, 0xa6, 0x5e, 0x8c, 0xcc, 0xc7, 0xf4, 0xed, 0x2f, 0xe2, - 0xf5, 0x38, 0x8d, 0x46, 0x17, 0x17, 0xe7, 0x2d, 0x48, 0xf8, 0x8d, 0xde, 0xa5, 0x11, 0x7d, 0x00, 0xff, 0x41, 0xf6, - 0x87, 0x67, 0xd0, 0x21, 0x8c, 0xf0, 0x76, 0xfa, 0x21, 0xcc, 0xf9, 0x3c, 0xa3, 0x9f, 0x79, 0x1a, 0x8d, 0xc6, 0xa3, - 0xfb, 0xe7, 0x50, 0x6f, 0x4e, 0xa7, 0xcf, 0x34, 0x85, 0x76, 0x5b, 0x2d, 0xd3, 0xf2, 0x5b, 0xfe, 0x85, 0x99, 0xea, - 0xdd, 0xee, 0xf9, 0xa8, 0x03, 0x23, 0xb8, 0x06, 0x85, 0x0a, 0x8c, 0xe7, 0x22, 0x33, 0x0d, 0x5e, 0x67, 0x4f, 0xc7, - 0x69, 0xf4, 0xe0, 0xc1, 0x69, 0x27, 0xcb, 0x22, 0x7c, 0xfb, 0x61, 0x6c, 0x6b, 0x9b, 0x3c, 0x05, 0xb0, 0x4f, 0x23, - 0xf6, 0xe0, 0xc1, 0xf9, 0x7d, 0x0a, 0xdf, 0xcf, 0x4d, 0x5b, 0x17, 0x93, 0x51, 0x76, 0x01, 0x6d, 0xbd, 0x83, 0xe9, - 0x9c, 0x5d, 0x9c, 0x8e, 0x4d, 0x5f, 0xef, 0xcc, 0xa8, 0x3b, 0x93, 0xb3, 0xc9, 0x99, 0xc9, 0x34, 0x43, 0x2d, 0x3f, - 0x7f, 0x65, 0x69, 0x94, 0xb1, 0x71, 0x3b, 0xc2, 0xb7, 0x6e, 0xe1, 0x1e, 0x9c, 0xb5, 0x5a, 0xe3, 0xd3, 0x08, 0x8f, - 0x1f, 0x2e, 0x16, 0x6f, 0x0c, 0x04, 0xdb, 0x67, 0x0f, 0xec, 0xb7, 0xfa, 0x7c, 0x07, 0x4d, 0x8f, 0x0c, 0xd0, 0xc6, - 0x7c, 0x6e, 0x5a, 0x3e, 0x7f, 0x00, 0xff, 0x99, 0x6f, 0xd3, 0x74, 0xf9, 0x2d, 0xc7, 0x53, 0xbb, 0x28, 0x6d, 0xf6, - 0xa0, 0x05, 0x35, 0x26, 0xfc, 0xc3, 0xa8, 0xe0, 0x80, 0x46, 0xa3, 0x0e, 0xfc, 0x5f, 0x84, 0x27, 0xf9, 0xf5, 0x2b, - 0x87, 0xb3, 0x93, 0x09, 0x9d, 0xb4, 0x22, 0x3c, 0x91, 0x1f, 0x94, 0xfe, 0xed, 0xa1, 0x48, 0xa3, 0x4e, 0xe7, 0x62, - 0x64, 0xca, 0x2c, 0x7f, 0x52, 0xdc, 0xe0, 0x71, 0xcb, 0xb4, 0x32, 0xa5, 0x6f, 0xd4, 0xe8, 0x5a, 0xc2, 0x4a, 0xc2, - 0x7f, 0x11, 0x9e, 0x82, 0x16, 0xce, 0xb5, 0x72, 0x61, 0xb7, 0xc3, 0xf4, 0xad, 0x41, 0xcd, 0xf1, 0x7d, 0x80, 0x97, - 0x5f, 0xc6, 0x31, 0xa5, 0xdd, 0x4e, 0x2b, 0xc2, 0x66, 0xd4, 0x17, 0x2d, 0xf8, 0x2f, 0xc2, 0x16, 0x72, 0x06, 0xae, - 0xd3, 0x0f, 0xcf, 0x7e, 0xbe, 0x49, 0x23, 0x3a, 0x9e, 0x4c, 0x60, 0x49, 0xcc, 0x64, 0x7c, 0xb1, 0x99, 0x14, 0xec, - 0xee, 0x97, 0x1b, 0xb7, 0x5d, 0x4c, 0x82, 0x76, 0xd0, 0x39, 0x7f, 0x30, 0x3a, 0x8b, 0xf0, 0x9b, 0x31, 0xa7, 0x02, - 0x56, 0x29, 0x1b, 0x77, 0xb3, 0x6e, 0x66, 0x12, 0xa6, 0x32, 0x8d, 0xce, 0x60, 0xc9, 0x3b, 0x11, 0xe6, 0x5f, 0xae, - 0xef, 0x2c, 0xba, 0x41, 0x6d, 0x87, 0x20, 0x93, 0x16, 0x3b, 0xbf, 0xc8, 0x22, 0x9c, 0xd3, 0x2f, 0xcf, 0x7e, 0x29, - 0xd2, 0x88, 0x9d, 0xb3, 0xf3, 0x09, 0xf5, 0xdf, 0xbf, 0xab, 0x99, 0xa9, 0xd1, 0x9a, 0x74, 0x21, 0xe9, 0x46, 0x98, - 0xb1, 0xde, 0xcf, 0x26, 0x06, 0x43, 0x5e, 0xce, 0xa5, 0xc8, 0x9e, 0x4e, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, - 0x07, 0x40, 0x9b, 0x8e, 0xc7, 0x17, 0xec, 0x3c, 0xc2, 0x7f, 0xd8, 0x5d, 0xe2, 0x26, 0xf0, 0x87, 0xc5, 0x6c, 0xe6, - 0x76, 0xfb, 0x1f, 0x16, 0x28, 0x30, 0xdf, 0x09, 0x9d, 0xd0, 0x71, 0x27, 0xc2, 0x7f, 0x18, 0xb8, 0x8c, 0x4f, 0xe1, - 0x3f, 0x28, 0x00, 0x9d, 0x3d, 0x68, 0x31, 0xf6, 0xa0, 0x65, 0xbe, 0xc2, 0x3c, 0x37, 0xf3, 0xd1, 0x79, 0xd6, 0x8e, - 0xf0, 0x1f, 0x0e, 0x1d, 0x27, 0x13, 0xda, 0x02, 0x74, 0xfc, 0xc3, 0xa1, 0x63, 0xa7, 0x35, 0xea, 0x50, 0xf3, 0x6d, - 0xb1, 0xe6, 0xe2, 0x7e, 0xc6, 0x60, 0x72, 0x7f, 0x58, 0x84, 0xbc, 0x7f, 0xff, 0xe2, 0xe2, 0xc1, 0x03, 0xf8, 0x34, - 0x6d, 0x97, 0x9f, 0x4a, 0x3f, 0xcc, 0x0d, 0x92, 0xb5, 0xb2, 0x33, 0xa0, 0x93, 0x7f, 0x98, 0x31, 0x4e, 0x26, 0x13, - 0xd6, 0x8a, 0x70, 0xce, 0xe7, 0xcc, 0x62, 0x82, 0xfd, 0x6d, 0x3a, 0x3a, 0xed, 0x64, 0xe3, 0xd3, 0x4e, 0x84, 0xf3, - 0x37, 0xcf, 0xcc, 0x6c, 0x5a, 0x30, 0x7b, 0xbf, 0xe5, 0x3c, 0xd6, 0xcc, 0xe9, 0x6b, 0x18, 0x24, 0xac, 0x34, 0x54, - 0x7e, 0x1f, 0xd0, 0xc3, 0xf3, 0xf3, 0x6c, 0x0c, 0x03, 0x7d, 0x0f, 0xdd, 0x02, 0x18, 0xdf, 0xdb, 0xcd, 0x37, 0xa2, - 0xdd, 0x2e, 0x4c, 0xf7, 0xfd, 0x62, 0x59, 0x2c, 0x5e, 0xa6, 0xd1, 0x83, 0xd3, 0xfb, 0xad, 0xf1, 0x28, 0xc2, 0xef, - 0xdd, 0x04, 0x4f, 0xb3, 0xd1, 0xe9, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, 0x7f, 0x74, 0x7e, 0x01, 0xe7, 0xc6, - 0x7b, 0xb5, 0x28, 0xde, 0x4c, 0x4d, 0x81, 0x09, 0x7d, 0x00, 0xcd, 0xfe, 0x6a, 0x76, 0xe3, 0xb8, 0x0d, 0x1b, 0xf9, - 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0xbb, 0x17, 0xdd, 0x08, 0xcf, 0xf9, 0x58, 0x00, 0x81, 0x37, 0x1b, 0xe5, - 0x41, 0xfb, 0xc1, 0xfd, 0x56, 0x84, 0xe7, 0x6f, 0x74, 0xf6, 0x81, 0xce, 0x0d, 0x35, 0x9e, 0x00, 0xcc, 0xe6, 0x5c, - 0xe9, 0xbb, 0xd7, 0xca, 0xd1, 0x63, 0xd6, 0x8e, 0xf0, 0x5c, 0x66, 0x19, 0x55, 0x6f, 0x6c, 0xc2, 0xa8, 0x1b, 0x61, - 0x41, 0xbf, 0xd0, 0x4f, 0xd2, 0x6f, 0xa6, 0x31, 0xa3, 0x63, 0x93, 0x66, 0x70, 0x38, 0xc2, 0x6f, 0xc7, 0x70, 0x19, - 0x99, 0x46, 0x93, 0xf1, 0xa4, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb1, 0x1b, 0xa0, 0x01, 0x5f, 0xe3, 0x47, 0xa3, 0x34, - 0x3a, 0x1f, 0x5d, 0xb0, 0xce, 0x69, 0x84, 0x4b, 0x6a, 0x44, 0xbb, 0x90, 0x6f, 0x3e, 0x3f, 0x98, 0x2d, 0x75, 0x66, - 0x13, 0x0c, 0x80, 0xc6, 0xf4, 0x7e, 0x6b, 0x7c, 0x1e, 0xe1, 0xc5, 0x2b, 0xe6, 0xf7, 0x18, 0x63, 0xec, 0x02, 0x60, - 0x09, 0x49, 0x06, 0x81, 0x2e, 0x26, 0xa3, 0x07, 0x17, 0xe6, 0x1b, 0xc0, 0x40, 0x27, 0x8c, 0x01, 0x90, 0x16, 0xaf, - 0x58, 0x09, 0x88, 0xf1, 0xe8, 0x7e, 0x0b, 0xe8, 0xcb, 0x82, 0x2e, 0xe8, 0x1d, 0xbd, 0x79, 0xba, 0x30, 0x73, 0x9a, - 0x8c, 0xbb, 0x11, 0x5e, 0x3c, 0xff, 0x69, 0xb1, 0x9c, 0x4c, 0xcc, 0x84, 0xe8, 0xe8, 0x41, 0x84, 0x17, 0xac, 0x58, - 0xc2, 0x1a, 0x5d, 0x74, 0x4f, 0x27, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, 0x11, 0xdc, 0xb6, 0x2e, 0xe7, 0x69, 0x34, - 0x1e, 0xd3, 0xd6, 0x18, 0xee, 0x5e, 0xe5, 0xcd, 0x2f, 0x85, 0x45, 0x23, 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, - 0xe0, 0xf1, 0x61, 0xc4, 0xb2, 0x8c, 0xba, 0xc4, 0xf3, 0xf3, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0xaf, - 0xd5, 0xdd, 0xa8, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xfa, 0xee, 0x95, 0xa1, 0xab, 0xed, 0xf3, 0x07, - 0xb0, 0x00, 0x8a, 0x8e, 0xc7, 0x2f, 0xed, 0xe1, 0x76, 0x31, 0x3a, 0xeb, 0xb6, 0x4f, 0x23, 0xec, 0x37, 0x02, 0xbd, - 0x68, 0xdd, 0xef, 0x40, 0x09, 0x31, 0xbe, 0xb3, 0x25, 0x26, 0x67, 0xf4, 0xec, 0xbc, 0x15, 0x61, 0xbf, 0x35, 0xd8, - 0xc5, 0xa8, 0x7b, 0x1f, 0x3e, 0xd5, 0x8c, 0xe5, 0xb9, 0xc1, 0xef, 0x2e, 0xc0, 0x45, 0xf1, 0x67, 0x82, 0xa6, 0x11, - 0x6d, 0x75, 0x3b, 0x9d, 0x31, 0x7c, 0xe6, 0x5f, 0x58, 0x91, 0x46, 0x59, 0x0b, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, - 0x28, 0xc2, 0x06, 0xef, 0xce, 0x69, 0xd7, 0xec, 0x7d, 0xb7, 0xab, 0x5a, 0x17, 0x2d, 0xd8, 0xb0, 0x6e, 0x53, 0xb9, - 0x2f, 0x25, 0xe4, 0x8d, 0x23, 0xb1, 0x34, 0xc2, 0x01, 0x82, 0x4e, 0xee, 0x4f, 0x22, 0xec, 0x77, 0xdc, 0xd9, 0xf9, - 0x45, 0x07, 0x48, 0x99, 0x06, 0x42, 0x31, 0xee, 0x8c, 0xce, 0x80, 0x34, 0x69, 0xf6, 0xca, 0xe2, 0x49, 0x84, 0xf5, - 0x53, 0xa5, 0x5f, 0xa6, 0xd1, 0xf8, 0x62, 0x34, 0x19, 0x5f, 0x44, 0x58, 0xcb, 0x39, 0xd5, 0xd2, 0x50, 0xc0, 0xd3, - 0xb3, 0xfb, 0x11, 0x36, 0x68, 0xde, 0x62, 0xad, 0x71, 0x2b, 0xc2, 0xee, 0x28, 0x61, 0xec, 0xa2, 0x03, 0xd3, 0xfa, - 0xf1, 0xb9, 0x06, 0x5c, 0x1e, 0xb3, 0xd1, 0x69, 0x84, 0x4b, 0x7a, 0x6f, 0x08, 0x11, 0x7c, 0xa9, 0xb9, 0xfc, 0xec, - 0x58, 0x0f, 0x20, 0x75, 0x7e, 0xc3, 0xc3, 0x32, 0xfc, 0x7c, 0x63, 0xd1, 0x88, 0x9a, 0x2d, 0x1e, 0xdc, 0x46, 0xbf, - 0xa5, 0xb1, 0x67, 0xdb, 0x39, 0x59, 0x6d, 0x70, 0x19, 0xe4, 0xf5, 0x33, 0xbb, 0x53, 0xb1, 0x54, 0x86, 0x93, 0x0d, - 0x52, 0x94, 0x42, 0xde, 0xad, 0xc1, 0x79, 0xae, 0x82, 0x20, 0x29, 0x48, 0xab, 0x27, 0x2e, 0xbd, 0x37, 0x6d, 0x4f, - 0x40, 0xe8, 0x07, 0x48, 0x2f, 0x08, 0x25, 0x1a, 0x22, 0xe4, 0x58, 0x61, 0xd2, 0x3b, 0x19, 0x18, 0x99, 0x52, 0x5a, - 0xb7, 0x05, 0x4a, 0xa8, 0x8f, 0x8d, 0x1f, 0x4b, 0xac, 0x20, 0x7a, 0x14, 0xea, 0x49, 0x62, 0x22, 0x5d, 0xbf, 0x10, - 0x3a, 0x96, 0x6a, 0x50, 0x0c, 0x71, 0xfb, 0x1c, 0x61, 0x88, 0x21, 0x41, 0x06, 0xf2, 0xea, 0xaa, 0x7d, 0x7e, 0x64, - 0x84, 0xbe, 0xab, 0xab, 0x0b, 0xfb, 0x03, 0xfe, 0x1d, 0x56, 0x71, 0xbb, 0x61, 0x7c, 0xef, 0x59, 0x35, 0xc7, 0x9f, - 0x0d, 0x7f, 0xfd, 0x9e, 0xad, 0xd7, 0xf1, 0x7b, 0x46, 0x60, 0xc6, 0xf8, 0x3d, 0x4b, 0xcc, 0x1d, 0x89, 0xf5, 0x10, - 0x22, 0x03, 0xd0, 0x9c, 0xb5, 0x30, 0x44, 0x93, 0xf7, 0x9c, 0xf7, 0x7b, 0x36, 0xe0, 0x75, 0xef, 0xf2, 0x2a, 0x84, - 0xf3, 0xd1, 0xd1, 0xaa, 0x48, 0xb5, 0x15, 0x13, 0xb4, 0x15, 0x13, 0xb4, 0x15, 0x13, 0x74, 0x15, 0x44, 0xff, 0xac, - 0x0f, 0x52, 0x8a, 0x51, 0xb6, 0x38, 0x9e, 0xfa, 0x0d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, - 0x62, 0xaf, 0x02, 0x63, 0x6f, 0xa2, 0xd3, 0x76, 0x9c, 0xfc, 0x3b, 0xea, 0x8e, 0x67, 0x35, 0xb1, 0xec, 0xcd, 0x5e, - 0xb1, 0x0c, 0x56, 0xd2, 0x88, 0x66, 0x87, 0x36, 0x1e, 0x89, 0x1e, 0xdc, 0x37, 0x82, 0x59, 0x15, 0x24, 0xaf, 0x01, - 0x49, 0x3d, 0x90, 0x42, 0x2e, 0x8c, 0x94, 0x56, 0xa0, 0x74, 0xac, 0xe3, 0x02, 0x34, 0x94, 0x5e, 0x41, 0x59, 0xc6, - 0x72, 0x6d, 0x18, 0x80, 0x28, 0x2b, 0xa3, 0x59, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0x8c, 0xc4, 0x02, 0x0d, - 0x08, 0xd3, 0x80, 0x70, 0x95, 0x41, 0x9c, 0x71, 0xd9, 0x67, 0x26, 0x5b, 0x99, 0x6c, 0x55, 0x66, 0x4b, 0x9f, 0x6d, - 0x85, 0x44, 0x69, 0xb2, 0x65, 0x99, 0x0d, 0x32, 0x1b, 0x9e, 0xa6, 0x0a, 0x8f, 0x52, 0x69, 0x45, 0xb5, 0x4a, 0xb6, - 0x7a, 0x49, 0x43, 0x6d, 0xee, 0xd1, 0x51, 0x5c, 0xca, 0x49, 0x46, 0x4d, 0x7c, 0x6f, 0xc5, 0x93, 0xc2, 0xc8, 0x40, - 0x3c, 0x99, 0xba, 0xbf, 0xa3, 0xcd, 0xb6, 0xac, 0x54, 0x4c, 0x47, 0x5f, 0x29, 0x89, 0xfe, 0xf2, 0x4a, 0xd4, 0xe7, - 0xdc, 0x44, 0x01, 0xba, 0x24, 0x49, 0xab, 0x75, 0xda, 0x3e, 0x6d, 0x5d, 0xf4, 0xf9, 0x71, 0xbb, 0x93, 0x3c, 0xe8, - 0xa4, 0x46, 0x11, 0xb1, 0x90, 0x37, 0xa0, 0x80, 0x39, 0xe9, 0x24, 0x67, 0xe8, 0xb8, 0x9d, 0xb4, 0xba, 0xdd, 0x26, - 0xfc, 0x83, 0x1f, 0xe9, 0xb2, 0xda, 0x59, 0xeb, 0xac, 0xdb, 0xe7, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x80, 0x82, 0xe8, - 0xc4, 0x54, 0xc2, 0x50, 0xbf, 0x5a, 0xde, 0x7f, 0x76, 0xf4, 0x3c, 0x8f, 0x74, 0x2c, 0xad, 0x2a, 0x0e, 0xa0, 0xea, - 0xbf, 0xa6, 0x06, 0x88, 0xfe, 0x6b, 0x54, 0x46, 0xea, 0x5d, 0x15, 0x20, 0x6a, 0x3f, 0xe7, 0xb1, 0x68, 0xb0, 0xe3, - 0xd8, 0xe6, 0x6b, 0xa8, 0xdb, 0x84, 0xe8, 0x79, 0x78, 0xea, 0x72, 0x55, 0x98, 0x3b, 0x45, 0xa8, 0xa9, 0x20, 0x77, - 0xe4, 0x72, 0x65, 0x98, 0x3b, 0x42, 0xa8, 0x29, 0x21, 0x97, 0xa6, 0x3c, 0xa1, 0x90, 0xa3, 0x13, 0xda, 0x34, 0x90, - 0xac, 0x16, 0xe5, 0x39, 0xf3, 0xc3, 0xe6, 0x13, 0x58, 0x1e, 0x43, 0x50, 0x9c, 0x20, 0x2d, 0xe0, 0x85, 0x95, 0x52, - 0x9b, 0xd3, 0xc2, 0xa5, 0x1a, 0x07, 0x32, 0x1a, 0xf0, 0xcf, 0x31, 0x33, 0xcf, 0x6e, 0xb4, 0xfa, 0xa7, 0xe7, 0xad, - 0xb4, 0x0d, 0xae, 0xe2, 0x20, 0x6b, 0x0b, 0x2b, 0x6b, 0x0b, 0x2f, 0x6b, 0x0b, 0x2f, 0x6b, 0x83, 0x00, 0x1f, 0xf4, - 0xfd, 0xbb, 0xac, 0x99, 0xdf, 0xf0, 0xd2, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, - 0xac, 0x51, 0xa8, 0x4a, 0xfd, 0xb9, 0x2a, 0xd2, 0x16, 0x9e, 0xa6, 0xa0, 0xe5, 0x6e, 0x61, 0x6a, 0x36, 0xb7, 0xa7, - 0x0a, 0xdb, 0x51, 0x7c, 0xfa, 0x5e, 0x9d, 0x7c, 0x45, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa4, 0xdc, 0xd2, 0x0c, 0x6e, - 0x69, 0x06, 0xb7, 0x34, 0x03, 0x1a, 0xc1, 0x65, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x06, 0xa7, 0x43, 0x08, - 0x62, 0x18, 0x6b, 0x62, 0x46, 0xbd, 0xd5, 0x79, 0x1b, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1c, - 0xf3, 0xa7, 0x1a, 0xda, 0x27, 0xf0, 0xa2, 0xce, 0x43, 0x1d, 0xb7, 0xc0, 0x74, 0x25, 0x2a, 0xa2, 0xbe, 0x21, 0x0b, - 0xa9, 0xd1, 0xd9, 0x38, 0x93, 0xf4, 0xcf, 0x5b, 0x9e, 0xc0, 0x96, 0x12, 0x84, 0xef, 0x48, 0x7c, 0x66, 0x55, 0x68, - 0x82, 0xd2, 0xe2, 0xd6, 0x99, 0xcb, 0xd9, 0x23, 0xa1, 0x07, 0x66, 0xf3, 0x3e, 0xe6, 0x55, 0x5f, 0x90, 0x02, 0x62, - 0x3e, 0xa6, 0x26, 0xd1, 0x45, 0x6d, 0x06, 0x27, 0x66, 0x72, 0x43, 0x8d, 0x4b, 0xcf, 0xcf, 0xf6, 0xcf, 0x27, 0x1a, - 0xf8, 0x3c, 0x16, 0xd3, 0x91, 0x77, 0x15, 0xfe, 0x68, 0x62, 0x1b, 0x91, 0xc3, 0x43, 0x6b, 0xd1, 0x6e, 0xbe, 0xb6, - 0x4d, 0xda, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x77, 0xef, 0xb1, 0x57, 0x4c, 0x47, 0x28, 0xa0, 0xd9, - 0x06, 0xac, 0xb2, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x47, 0x4e, 0xe8, 0xdd, 0x8c, 0x79, 0x53, 0x4c, 0x47, 0x7b, 0x9f, - 0x5e, 0xb1, 0x3d, 0xf6, 0x5f, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb1, 0xdb, 0x6f, 0xd5, 0xb9, 0xde, 0x5b, 0x47, - 0xe5, 0xdf, 0xaa, 0xf3, 0x64, 0x5f, 0x9d, 0x39, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, 0x81, 0x1a, 0xdb, 0x98, 0x49, 0x4d, - 0x47, 0x10, 0x2b, 0x1f, 0xfe, 0xda, 0x88, 0x36, 0x3d, 0x4f, 0xc2, 0x61, 0x15, 0x64, 0x3f, 0xe9, 0xa6, 0x0c, 0x53, - 0xd2, 0x39, 0x2e, 0x4c, 0x4c, 0x1b, 0x91, 0xd0, 0xa6, 0x4a, 0x28, 0xce, 0x49, 0x1c, 0xd3, 0xe3, 0x0c, 0x22, 0xf3, - 0xb4, 0xfb, 0x34, 0x8d, 0x69, 0x23, 0x43, 0x27, 0x71, 0xbb, 0x41, 0x8f, 0x33, 0x84, 0x1a, 0x6d, 0xd0, 0x99, 0x4a, - 0xd2, 0x6e, 0xe6, 0x10, 0xab, 0xd3, 0x90, 0xe2, 0xfc, 0x58, 0x24, 0x45, 0x43, 0x1e, 0xab, 0xa4, 0x68, 0x24, 0x5d, - 0x2c, 0x92, 0x69, 0x99, 0x3c, 0x35, 0xc9, 0x53, 0x9b, 0x3c, 0x2a, 0x93, 0x47, 0x26, 0x79, 0x64, 0x93, 0x29, 0x29, - 0x8e, 0x45, 0x42, 0x1b, 0x71, 0xbb, 0x59, 0xa0, 0x63, 0x18, 0x81, 0x1f, 0x3d, 0x11, 0x61, 0x88, 0xf4, 0x8d, 0xb1, - 0x31, 0x5a, 0xc8, 0xdc, 0x05, 0x2d, 0xad, 0x80, 0x54, 0x3a, 0x7e, 0x41, 0x9d, 0x7f, 0x02, 0x30, 0x61, 0x6d, 0xff, - 0xf8, 0x90, 0x7c, 0x9b, 0x2c, 0x97, 0x22, 0x70, 0x6c, 0x03, 0x5b, 0xfc, 0xcf, 0xce, 0x9d, 0x07, 0xa0, 0xba, 0xa1, - 0xf9, 0x62, 0x46, 0x77, 0xbc, 0x87, 0x8b, 0xe9, 0xc8, 0xed, 0xac, 0xb2, 0x19, 0x46, 0x0b, 0x1b, 0xea, 0xba, 0xee, - 0xe7, 0x09, 0xa0, 0xf6, 0xbe, 0xa5, 0x09, 0x35, 0x4a, 0x72, 0x5b, 0x63, 0x5a, 0xb0, 0x3b, 0x95, 0xd1, 0x9c, 0xc5, - 0xd5, 0x01, 0x5c, 0x0d, 0x93, 0x91, 0x27, 0xe0, 0x11, 0x50, 0x1c, 0x27, 0xa7, 0x0d, 0x9d, 0x4c, 0x8f, 0x93, 0xee, - 0x83, 0x86, 0x4e, 0x46, 0xc7, 0x49, 0xbb, 0x5d, 0xe1, 0x6c, 0x52, 0x10, 0x9d, 0x4c, 0x89, 0x06, 0x8d, 0xa1, 0x6d, - 0x54, 0x2e, 0x28, 0x98, 0xb8, 0xfd, 0x1b, 0xc3, 0x68, 0xb8, 0x61, 0x08, 0x36, 0xb5, 0x51, 0x3f, 0x77, 0xc6, 0x10, - 0x76, 0xd3, 0xe9, 0x76, 0x9b, 0x3a, 0x29, 0xb0, 0xb6, 0x2b, 0xd9, 0xd4, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x4d, 0x9d, - 0x8c, 0x6c, 0x53, 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0xe7, 0x2c, 0x80, 0x7c, 0xc7, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, - 0xf8, 0xad, 0x72, 0x4d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xdb, 0x55, 0x93, 0xec, 0x5f, 0x97, - 0x2d, 0x9b, 0x2d, 0xa4, 0xae, 0x17, 0x7c, 0x51, 0xc3, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x8f, 0x28, 0x89, 0x21, 0xb6, - 0x9f, 0x39, 0x85, 0x38, 0xf1, 0x7a, 0x64, 0x48, 0xe2, 0x8d, 0xc6, 0x06, 0xc5, 0xc1, 0x79, 0xfb, 0x22, 0xa4, 0xaa, - 0x3b, 0x01, 0xff, 0x08, 0x89, 0x96, 0xc2, 0x9a, 0x84, 0x8e, 0xa3, 0x8a, 0x16, 0xbf, 0x71, 0xda, 0xdd, 0xda, 0x01, - 0x71, 0x74, 0xb4, 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xec, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, - 0x98, 0x07, 0x88, 0xe2, 0x43, 0x6f, 0xdd, 0x37, 0x14, 0x7e, 0x50, 0xc5, 0x1d, 0x74, 0x39, 0xcd, 0x73, 0x93, 0x61, - 0xfa, 0x1a, 0x06, 0x63, 0x7b, 0x15, 0x4e, 0xa8, 0xb4, 0x95, 0xfc, 0x97, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, - 0x46, 0x3f, 0x85, 0x96, 0xc9, 0x15, 0x6c, 0x9c, 0x4f, 0xfa, 0x7a, 0x5d, 0x7b, 0x9e, 0xc8, 0x3e, 0x82, 0x83, 0x8e, - 0x8e, 0xb8, 0x7a, 0x06, 0xc6, 0xd4, 0x2c, 0x6e, 0x84, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x93, 0x39, 0x57, 0xd3, - 0xe0, 0xa0, 0x7b, 0x58, 0xcb, 0xdf, 0xbb, 0x12, 0x7d, 0x9d, 0x72, 0xb7, 0xd6, 0xef, 0x2b, 0x53, 0xf5, 0x9d, 0x87, - 0xb2, 0x8e, 0x8e, 0x78, 0x15, 0xae, 0x2a, 0xfa, 0x2e, 0x42, 0x7d, 0x23, 0x83, 0x3c, 0xcb, 0x25, 0x85, 0x1b, 0x51, - 0xb8, 0x62, 0x48, 0x1b, 0xfc, 0x44, 0xe3, 0x9f, 0xe4, 0xff, 0xa7, 0x46, 0x8e, 0x75, 0xda, 0xe0, 0x81, 0xb9, 0x41, - 0xc8, 0x0a, 0x55, 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1e, 0xe6, 0x74, 0xb1, 0xc8, 0xef, 0xcc, 0x5b, - 0x61, 0x01, 0x47, 0x55, 0x5d, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x00, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xf2, - 0x72, 0x5b, 0x20, 0x90, 0xcc, 0x14, 0x91, 0xcd, 0x76, 0x4f, 0x5d, 0x81, 0x5c, 0xd6, 0x6c, 0x22, 0xed, 0x82, 0x97, - 0x63, 0x0e, 0x32, 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, - 0x0c, 0x68, 0x84, 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xc2, 0x77, 0xfc, 0x95, 0x96, 0x8a, 0x81, 0x1a, - 0x0e, 0x71, 0x61, 0x9e, 0xc7, 0x28, 0xe7, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, - 0x33, 0x72, 0x6d, 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbd, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x65, 0x2e, 0x0a, 0x9d, 0xbc, - 0xc9, 0x2e, 0x45, 0xaf, 0xd1, 0x60, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, - 0xc5, 0x6c, 0x04, 0x3e, 0x08, 0x0d, 0x5e, 0x4b, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xb2, - 0x9f, 0x32, 0x94, 0x6c, 0x65, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x53, 0xed, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, - 0x9b, 0x60, 0x00, 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8c, 0x13, - 0x60, 0x6f, 0x6e, 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x80, 0x1c, 0x3d, 0x24, 0xd0, 0xb9, 0xfd, 0x59, - 0xd1, 0x85, 0x4a, 0x26, 0x2e, 0xc7, 0xf8, 0x43, 0x70, 0x9b, 0x37, 0x88, 0x3e, 0x7e, 0x34, 0x9b, 0xfc, 0xe3, 0xc7, - 0x08, 0x87, 0xc6, 0xf5, 0x51, 0xc0, 0x0b, 0x46, 0xc3, 0x32, 0xb4, 0x96, 0xd9, 0xf8, 0xcd, 0x76, 0x80, 0x76, 0xb4, - 0xc2, 0x3b, 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x80, 0x03, 0xbc, 0xd9, 0x80, 0x0f, 0x7b, 0xaf, 0x62, 0x85, - 0x8e, 0x8e, 0x5e, 0xc5, 0x12, 0xf5, 0xaf, 0x99, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x01, 0x37, 0xc3, 0x97, 0x01, 0x02, - 0x5c, 0xb3, 0x6d, 0xc9, 0xe6, 0x8d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0xbe, - 0x0a, 0xa1, 0xdd, 0x63, 0x84, 0x01, 0x0b, 0x5f, 0xfa, 0x0a, 0xb2, 0x64, 0xce, 0x8a, 0x29, 0x2b, 0xd6, 0xeb, 0xe7, - 0xd4, 0xfa, 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xbd, 0x46, 0x83, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x87, 0xf8, 0xf0, 0x55, - 0x5c, 0x20, 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0x56, 0x5b, 0x97, 0x02, 0x95, 0x8d, 0xe4, 0xa4, 0x85, - 0x67, 0x24, 0x2b, 0xd7, 0xe8, 0x72, 0xd6, 0x6b, 0x34, 0x72, 0x24, 0xe3, 0x6c, 0x90, 0x0f, 0x31, 0xc7, 0x05, 0x5c, - 0xa6, 0xee, 0xae, 0xc3, 0x82, 0xd5, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x47, 0x37, 0x01, 0x30, 0xde, - 0xd1, 0x80, 0x48, 0xec, 0x03, 0xb2, 0xb0, 0x40, 0x56, 0x1e, 0xc8, 0xc2, 0x00, 0x59, 0xa1, 0xfe, 0x02, 0x82, 0x36, - 0x29, 0x94, 0xee, 0x50, 0xf4, 0x7a, 0x78, 0x51, 0xe7, 0xba, 0x82, 0xb9, 0x89, 0x70, 0xe1, 0x96, 0x03, 0xdc, 0x58, - 0xdc, 0xdc, 0x15, 0x59, 0x45, 0x91, 0x89, 0xb4, 0x8b, 0x6f, 0xcd, 0x9f, 0xe4, 0x16, 0xdf, 0xd9, 0x1f, 0x77, 0x81, - 0x32, 0xe9, 0xb7, 0x9a, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xfe, 0xee, - 0x9c, 0xb2, 0xe1, 0x30, 0x44, 0x83, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xe7, 0x9f, 0x11, 0xea, 0x0b, 0x88, 0x66, 0xe4, - 0x4e, 0xb6, 0x66, 0x1b, 0x35, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0x54, - 0x36, 0x1e, 0xb5, 0x61, 0x98, 0x41, 0x55, 0xe1, 0x3f, 0xae, 0x56, 0xdb, 0xc1, 0x96, 0x0c, 0x54, 0x85, 0x89, 0x74, - 0x83, 0xec, 0x43, 0x6c, 0x8c, 0xb0, 0xa3, 0x23, 0x36, 0x10, 0xc3, 0xe0, 0x65, 0xb5, 0xaa, 0x75, 0x1d, 0x2e, 0x5c, - 0x9c, 0x41, 0xb4, 0xfb, 0xf5, 0xda, 0xfe, 0x25, 0x1f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0xb7, 0xf1, 0x62, 0xbf, - 0x2c, 0x96, 0x68, 0xf9, 0x0e, 0x2c, 0xfb, 0x5c, 0xec, 0x42, 0xee, 0xa6, 0xda, 0xf6, 0x50, 0x5f, 0x18, 0x8d, 0x42, - 0x10, 0x39, 0xb8, 0x3a, 0xd2, 0xf0, 0x42, 0x87, 0x79, 0xb5, 0x08, 0xc0, 0xb9, 0x2a, 0x03, 0xb9, 0xc2, 0x91, 0x92, - 0x80, 0xa5, 0xb7, 0xa1, 0x93, 0xf0, 0xa3, 0x4e, 0x25, 0x1d, 0x0b, 0x09, 0x50, 0xe0, 0xc8, 0x5c, 0xce, 0x9b, 0x40, - 0xfd, 0x0c, 0xed, 0x21, 0x72, 0xd5, 0x2a, 0xff, 0x5d, 0x97, 0x2d, 0x5d, 0x44, 0xad, 0x68, 0x2e, 0x97, 0x8a, 0x2d, - 0x17, 0x70, 0xbe, 0x97, 0x69, 0x59, 0xce, 0xb3, 0xcf, 0xf5, 0x14, 0x30, 0x88, 0xbc, 0xd5, 0x73, 0x26, 0x96, 0x91, - 0x9b, 0xe7, 0x4b, 0x2b, 0xee, 0xbf, 0x7e, 0x81, 0xdf, 0x93, 0xce, 0xf1, 0x4b, 0xfc, 0x3b, 0x25, 0xef, 0x1b, 0x2f, - 0xf1, 0x94, 0x13, 0xcb, 0x1b, 0x24, 0xaf, 0x5f, 0x5d, 0xbf, 0x78, 0xfb, 0xe2, 0xfd, 0xd3, 0x8f, 0x2f, 0x5e, 0x3e, - 0x7b, 0xf1, 0xf2, 0xc5, 0xdb, 0x0f, 0xf8, 0x27, 0x4a, 0x5e, 0x9e, 0xb4, 0x2f, 0x5a, 0xf8, 0x1d, 0x79, 0x79, 0xd2, - 0xc1, 0xb7, 0x9a, 0xbc, 0x3c, 0x39, 0xc3, 0x33, 0x45, 0x5e, 0x1e, 0x77, 0x4e, 0x4e, 0xf1, 0x52, 0xdb, 0x26, 0x73, - 0x39, 0x6d, 0xb7, 0xf0, 0xdf, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x53, 0xb6, 0x65, 0xfc, 0x60, 0xca, 0xd0, 0x91, - 0x32, 0x86, 0x28, 0x97, 0x01, 0x3a, 0x8d, 0x55, 0xdd, 0xb4, 0x01, 0x42, 0x49, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, - 0xae, 0x1d, 0x7e, 0xd2, 0x66, 0xa7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd3, 0x62, 0x4c, 0x72, - 0x29, 0x8b, 0x78, 0x09, 0x8c, 0x80, 0xd1, 0x5a, 0xf0, 0x93, 0x32, 0x66, 0x95, 0xb8, 0x24, 0xed, 0x7e, 0x3b, 0x15, - 0x97, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x9b, 0xb6, 0x5b, 0xe8, 0x38, 0x18, 0xc7, 0x0f, 0x35, 0xb4, 0x1e, - 0x0c, 0xb1, 0xeb, 0x42, 0xfd, 0x5d, 0x68, 0xaf, 0xd2, 0x13, 0x4e, 0x1d, 0xdb, 0xee, 0x89, 0x4b, 0x66, 0xf4, 0xb0, - 0xfc, 0x3b, 0x40, 0x6d, 0xe3, 0x56, 0x53, 0x6e, 0x1c, 0xf7, 0x8b, 0x9f, 0x08, 0x54, 0x0b, 0x8c, 0x13, 0xb3, 0x75, - 0x0b, 0x01, 0xd3, 0x68, 0xb2, 0xc1, 0x1c, 0x28, 0x51, 0xb2, 0xd0, 0x3e, 0xb8, 0xbf, 0x6a, 0x4a, 0x94, 0x2c, 0xe4, - 0x22, 0xae, 0xa9, 0x1a, 0x7e, 0x09, 0xcc, 0x1c, 0x0f, 0xb9, 0x7a, 0x49, 0x5f, 0xc6, 0x35, 0x9e, 0x27, 0x64, 0xed, - 0xc2, 0x6d, 0xf1, 0xab, 0xb3, 0xa2, 0xa8, 0x81, 0xab, 0x04, 0xac, 0x1f, 0x55, 0x53, 0x5f, 0xc2, 0x2b, 0x86, 0xac, - 0xa1, 0xaf, 0x48, 0x40, 0x3d, 0x7f, 0x2d, 0xcd, 0xb8, 0x4a, 0x65, 0xb4, 0x57, 0x44, 0x1b, 0xb3, 0x20, 0xaf, 0x88, - 0xbe, 0x54, 0x06, 0x08, 0x92, 0xf0, 0x81, 0x18, 0xc2, 0x81, 0x6f, 0x07, 0x28, 0x0d, 0x9d, 0x03, 0xb5, 0x52, 0x65, - 0x26, 0x64, 0x3e, 0x4d, 0x88, 0x06, 0xd0, 0x3c, 0x55, 0x2a, 0x28, 0xf3, 0x89, 0x25, 0x0a, 0x86, 0xfe, 0x47, 0xb8, - 0x01, 0x8e, 0x63, 0x83, 0x8a, 0xa1, 0x5d, 0x8d, 0xa8, 0xe7, 0xb7, 0x2f, 0x5a, 0x27, 0x2f, 0x83, 0xfc, 0xa5, 0xf2, - 0xf6, 0x1e, 0x9f, 0x02, 0x4a, 0x6e, 0x83, 0x8a, 0xb5, 0xb1, 0x8f, 0x07, 0xd7, 0x0b, 0x01, 0x72, 0xac, 0xd1, 0x89, - 0x79, 0xd0, 0xb1, 0x87, 0xf4, 0x31, 0x69, 0xb7, 0x20, 0x88, 0xdb, 0x1e, 0xca, 0xf7, 0xc7, 0x16, 0x4c, 0x75, 0x72, - 0xdb, 0x04, 0x5a, 0x0d, 0x6f, 0x3c, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, 0x33, 0xec, 0x98, 0x35, 0xc4, 0xb1, - 0x40, 0x2e, 0xf8, 0xad, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0x6b, 0xd0, 0x1b, 0x47, 0x5d, 0x36, 0x93, 0xee, 0xf1, - 0xcb, 0xa3, 0xa3, 0x58, 0x36, 0xc8, 0x7b, 0x84, 0x57, 0x14, 0x6c, 0xb6, 0xc1, 0xf7, 0x8e, 0x5b, 0x26, 0x3e, 0x55, - 0x01, 0x75, 0x9c, 0xa8, 0xda, 0xb1, 0x56, 0x75, 0x56, 0xee, 0x06, 0x3f, 0xa6, 0x0e, 0x6a, 0x04, 0x69, 0x76, 0x74, - 0x9d, 0x10, 0xca, 0x3f, 0xd6, 0x1c, 0xe5, 0x60, 0x5b, 0x36, 0x7e, 0xa7, 0xe8, 0xbb, 0xf7, 0xcd, 0x97, 0x01, 0x1e, - 0xd4, 0x4c, 0x93, 0xde, 0x37, 0xde, 0xa3, 0xef, 0xde, 0x07, 0xae, 0x8e, 0xbc, 0x62, 0x4f, 0x3c, 0x37, 0xf2, 0xab, - 0xe5, 0x4a, 0x7f, 0x05, 0xc9, 0xbe, 0x20, 0xbf, 0x02, 0x96, 0x53, 0xf2, 0x6b, 0x2c, 0x9b, 0x10, 0x02, 0x92, 0xfc, - 0x1a, 0x17, 0xf0, 0x23, 0x27, 0xbf, 0xc6, 0x80, 0xed, 0x78, 0x66, 0x7e, 0x14, 0x25, 0x30, 0xc0, 0xbd, 0x4e, 0x5a, - 0x2f, 0xbb, 0x62, 0xbd, 0x16, 0x47, 0x47, 0xd2, 0xfe, 0xa2, 0x57, 0xd9, 0xd1, 0x51, 0x7e, 0x39, 0xab, 0xfa, 0xe6, - 0x7a, 0x1f, 0x7d, 0x31, 0x08, 0x85, 0x03, 0xd3, 0x34, 0x1e, 0xce, 0x58, 0x67, 0x21, 0xe2, 0x40, 0x03, 0xcd, 0xd3, - 0xce, 0xfd, 0xf3, 0x0b, 0x0c, 0xff, 0xde, 0x0f, 0x0a, 0x82, 0x0e, 0xdf, 0x4e, 0x8c, 0xb4, 0x59, 0xf3, 0xbc, 0xaa, - 0x73, 0x15, 0xe0, 0x33, 0x66, 0xa8, 0x29, 0x8e, 0x8e, 0xf8, 0x65, 0x80, 0xcb, 0x98, 0xa1, 0x46, 0x60, 0xb1, 0xf7, - 0xb4, 0xb4, 0x27, 0x33, 0x5c, 0x13, 0x3c, 0xee, 0xcb, 0x07, 0xc5, 0xf0, 0x52, 0x3b, 0x6a, 0x12, 0x86, 0x00, 0x57, - 0xa4, 0xe5, 0x36, 0x59, 0x4f, 0x34, 0xd5, 0x55, 0xbb, 0x87, 0x24, 0x51, 0x0d, 0x71, 0x75, 0xd5, 0xc6, 0xa0, 0x92, - 0xef, 0x2b, 0x22, 0x53, 0x41, 0xbc, 0x9b, 0xe2, 0x2a, 0x97, 0xa9, 0xc2, 0x33, 0x9e, 0x0a, 0x2f, 0x67, 0xdf, 0xf3, - 0xd6, 0xd3, 0xc6, 0x71, 0xd4, 0xf4, 0xcc, 0xb0, 0xe8, 0xab, 0xd2, 0xe1, 0x11, 0x36, 0xa9, 0x1a, 0xc2, 0xdb, 0x89, - 0x25, 0xe6, 0x31, 0xeb, 0xe5, 0xc7, 0x20, 0x36, 0xb5, 0x6a, 0xb4, 0x21, 0x13, 0x3e, 0x37, 0xa9, 0x82, 0x81, 0x9a, - 0xc2, 0x97, 0x60, 0x64, 0x95, 0x55, 0x86, 0xd9, 0xbe, 0x61, 0x28, 0x20, 0xa0, 0xc0, 0x15, 0x61, 0x81, 0x04, 0x2f, - 0xb2, 0x1a, 0xe1, 0xa8, 0x93, 0x0b, 0x3b, 0xb9, 0x4b, 0x05, 0xdd, 0x89, 0xe1, 0xa5, 0xee, 0x21, 0xd1, 0x68, 0x38, - 0x6e, 0xfb, 0x4a, 0x98, 0x41, 0x34, 0xdb, 0xc3, 0x2b, 0xd6, 0x43, 0xaa, 0xd9, 0x2c, 0x0d, 0x20, 0xaf, 0x5a, 0xeb, - 0xb5, 0xba, 0xf4, 0x8d, 0xf4, 0xfd, 0x39, 0x6e, 0xf8, 0x2e, 0x2f, 0x78, 0xfe, 0x21, 0xc9, 0x20, 0x02, 0xaa, 0x0a, - 0x7c, 0xb6, 0x5c, 0x44, 0x38, 0x32, 0xcf, 0xea, 0xc1, 0x5f, 0xf3, 0x1c, 0x5a, 0x84, 0x23, 0xf7, 0xd2, 0x5e, 0x34, - 0xac, 0x06, 0xab, 0xb2, 0x32, 0x48, 0x3c, 0x4f, 0x3e, 0x02, 0xe3, 0xa0, 0x3f, 0x29, 0xb4, 0xaa, 0x7e, 0x27, 0xb9, - 0x0b, 0x97, 0xa2, 0xfc, 0xe3, 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, - 0x8d, 0xd7, 0x27, 0xdb, 0xee, 0xd1, 0xf3, 0x55, 0xd9, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0x7f, 0xc8, 0xbd, 0x2f, - 0x20, 0x47, 0x1f, 0xa5, 0x78, 0x42, 0x35, 0x8d, 0x1a, 0xaf, 0x8d, 0xe1, 0x9b, 0x95, 0xb3, 0x7a, 0x5f, 0x1b, 0x07, - 0xfb, 0xb7, 0xba, 0x87, 0x00, 0x16, 0xb5, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, - 0x3c, 0xfc, 0x18, 0x29, 0xb8, 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x9a, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, - 0xe3, 0xef, 0x06, 0x85, 0x5c, 0xf7, 0x42, 0xd5, 0x89, 0x69, 0xd5, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xaa, - 0xde, 0x8d, 0x84, 0x52, 0xbd, 0x6b, 0x67, 0xde, 0x26, 0x6d, 0xb6, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, - 0xbc, 0x87, 0x65, 0xd0, 0xae, 0x2b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xad, 0xdc, 0xcb, 0x74, 0x7c, 0x20, - 0x87, 0x9b, 0xf2, 0x9d, 0xba, 0x00, 0x0f, 0x02, 0xa7, 0x80, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x35, 0xfd, 0x10, - 0xff, 0x07, 0x0e, 0xf8, 0x0a, 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0xfe, 0x28, 0x43, - 0x47, 0xdd, 0xba, 0x4e, 0xc5, 0xfa, 0xc2, 0xd6, 0x15, 0x2b, 0x65, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, - 0x59, 0xf7, 0xe8, 0xd4, 0x43, 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x67, 0x05, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x08, - 0x5f, 0x55, 0x1e, 0xc0, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, - 0x3a, 0x16, 0x26, 0xb6, 0x84, 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, - 0xb0, 0xa2, 0xf0, 0xd2, 0xa9, 0xc8, 0x82, 0xbe, 0xf6, 0xf5, 0x21, 0xaa, 0x29, 0xf7, 0x63, 0xa3, 0xef, 0x7d, 0xcb, - 0xe7, 0x4c, 0x2e, 0xe1, 0xf1, 0x26, 0xcc, 0x88, 0x62, 0xda, 0x7f, 0x03, 0x05, 0x81, 0x17, 0x80, 0x78, 0x88, 0x8f, - 0xc0, 0x57, 0x79, 0x5a, 0x47, 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0xfd, 0x08, 0xbc, 0x88, 0x40, 0x84, - 0x22, 0x24, 0x62, 0x62, 0x1c, 0xf5, 0x23, 0xe3, 0x92, 0x15, 0x81, 0xd5, 0x18, 0x28, 0xb9, 0x23, 0x3c, 0x55, 0x15, - 0x11, 0x0b, 0x6b, 0xea, 0xa0, 0x12, 0x4b, 0x8d, 0x99, 0xf6, 0x49, 0xa7, 0x02, 0x61, 0x96, 0x6d, 0x0b, 0xca, 0x7a, - 0x4b, 0x5d, 0x80, 0x25, 0x31, 0xa6, 0xb7, 0x3c, 0xf9, 0x08, 0xdc, 0x1c, 0x1b, 0xbb, 0xa2, 0x2b, 0x7e, 0x0d, 0xea, - 0xe9, 0xb4, 0xc0, 0x1f, 0x0d, 0xc3, 0x36, 0x4e, 0xe9, 0x86, 0x70, 0x9c, 0x91, 0x22, 0xa1, 0xb7, 0x10, 0x5b, 0x63, - 0xce, 0x45, 0x9a, 0xe3, 0x39, 0xbd, 0x4d, 0x67, 0x78, 0xce, 0xc5, 0x13, 0xbb, 0xec, 0xe9, 0x18, 0x92, 0xfc, 0xc7, - 0x72, 0x43, 0xcc, 0xd3, 0x60, 0xef, 0x14, 0x2b, 0x1e, 0x01, 0xaf, 0xa2, 0x62, 0xd4, 0x1b, 0x1b, 0x9b, 0x72, 0xae, - 0x2b, 0xe3, 0xf5, 0x7b, 0x3a, 0xa6, 0x38, 0xc3, 0x39, 0x4a, 0x72, 0x89, 0x59, 0x5f, 0xa4, 0xf7, 0x20, 0xae, 0x76, - 0x86, 0xed, 0xb3, 0x62, 0xfc, 0x96, 0xe5, 0xcf, 0x64, 0xf1, 0xde, 0x6c, 0xf9, 0x1c, 0x41, 0x21, 0x70, 0x51, 0x11, - 0x4d, 0xb8, 0xdd, 0x5b, 0xf6, 0x65, 0xd5, 0x14, 0xbd, 0xb5, 0x4d, 0xb9, 0x21, 0xce, 0x20, 0x20, 0x71, 0x32, 0xe3, - 0x8d, 0x36, 0x66, 0xfd, 0xd6, 0x37, 0x1a, 0x9d, 0xa1, 0xb2, 0x24, 0xc2, 0xb0, 0x56, 0x4d, 0x95, 0x4a, 0x22, 0x9a, - 0xca, 0x49, 0x78, 0x2b, 0x03, 0xec, 0x54, 0xe1, 0x4c, 0x2e, 0x85, 0x4e, 0x65, 0x80, 0x37, 0x79, 0xb5, 0xb9, 0x56, - 0xb7, 0x16, 0x62, 0x1a, 0xdf, 0xd9, 0x1f, 0x0c, 0x7f, 0x34, 0x2a, 0xfe, 0x37, 0x60, 0xd8, 0xa3, 0x52, 0x01, 0xf0, - 0x03, 0xc3, 0x59, 0x80, 0x9c, 0xe5, 0x27, 0x6f, 0x01, 0x7c, 0x96, 0x85, 0xbc, 0x83, 0x54, 0x66, 0x52, 0xef, 0x20, - 0x95, 0x41, 0xaa, 0xf1, 0xa8, 0x3f, 0x14, 0x95, 0xb2, 0x28, 0x6c, 0x90, 0x28, 0x5c, 0xaa, 0x83, 0x25, 0x11, 0x09, - 0xb4, 0x6b, 0x44, 0xb9, 0x39, 0x17, 0x10, 0x5a, 0x11, 0x1a, 0xb7, 0xdf, 0xf4, 0x16, 0xbe, 0xef, 0x6c, 0x3e, 0xf3, - 0xf9, 0x77, 0x36, 0xdf, 0x74, 0xe4, 0x31, 0xbe, 0x7e, 0xdb, 0x69, 0x2c, 0xe3, 0xa5, 0xc3, 0xda, 0x77, 0xe5, 0x43, - 0x36, 0x2d, 0xf3, 0x60, 0x38, 0x69, 0xe3, 0x79, 0x80, 0x94, 0xcd, 0x8a, 0x87, 0xeb, 0xe0, 0x76, 0xeb, 0x38, 0xe6, - 0x4d, 0xd2, 0x46, 0xe8, 0xd8, 0x09, 0x57, 0x22, 0x36, 0x92, 0xd3, 0xf1, 0xfb, 0x13, 0xb8, 0x7b, 0x19, 0xa9, 0x2d, - 0x5f, 0x29, 0x5b, 0xad, 0xd9, 0x6e, 0x1d, 0xf3, 0xbd, 0x55, 0x1a, 0x6d, 0x3c, 0x67, 0x64, 0x05, 0x1e, 0x68, 0xb4, - 0xb0, 0xaa, 0x06, 0x70, 0x59, 0x7d, 0x21, 0x7e, 0x5d, 0xd2, 0xb1, 0xf9, 0x3e, 0xb6, 0x29, 0xaf, 0x96, 0xda, 0x27, - 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x5c, 0xc9, 0x20, 0x27, 0xe6, 0x27, 0x24, 0xe9, 0xa2, 0xcb, 0x76, 0x3f, 0xe9, 0x1e, - 0xf3, 0x63, 0x9e, 0x02, 0x0f, 0x1b, 0x37, 0x7d, 0x85, 0x66, 0xdb, 0xd7, 0x79, 0xbc, 0x1c, 0xf1, 0xcc, 0x35, 0x5f, - 0x75, 0x50, 0xa6, 0xda, 0x39, 0x42, 0x16, 0xa0, 0x98, 0xef, 0x25, 0xc8, 0xae, 0x77, 0x73, 0xcc, 0x53, 0xe8, 0x07, - 0x6a, 0x75, 0x6c, 0xad, 0x72, 0x70, 0xbf, 0x2e, 0x01, 0xc1, 0x7c, 0x47, 0xb5, 0xb9, 0xd8, 0xf4, 0x66, 0x5c, 0x75, - 0x76, 0xcc, 0xab, 0x11, 0x86, 0x65, 0x76, 0xfb, 0xf3, 0x53, 0xab, 0xba, 0x3c, 0x0e, 0x20, 0xf2, 0xeb, 0x92, 0x8b, - 0xb0, 0xd3, 0xb0, 0x5b, 0x97, 0x13, 0x76, 0x5a, 0x9f, 0x65, 0x50, 0x64, 0xb7, 0xd7, 0x9d, 0x99, 0xd6, 0x67, 0x7b, - 0x0d, 0x8e, 0x84, 0x30, 0x29, 0xb3, 0xd2, 0x99, 0x54, 0x31, 0x3f, 0x7e, 0x87, 0x5c, 0xeb, 0xaf, 0x96, 0xda, 0xe7, - 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xe5, 0x31, 0x0f, 0x56, 0xee, 0xe9, 0xed, - 0x42, 0xa6, 0x1e, 0x5f, 0xfb, 0xad, 0x74, 0x07, 0x39, 0x81, 0x78, 0xb8, 0xee, 0xc2, 0xb2, 0x20, 0x67, 0x37, 0x77, - 0x50, 0x32, 0x9c, 0xb8, 0x2f, 0xfd, 0x8e, 0xd9, 0xeb, 0x06, 0x7e, 0x99, 0x74, 0x61, 0xea, 0xdb, 0x3d, 0x1c, 0x77, - 0xa0, 0x0f, 0x03, 0x87, 0xed, 0x06, 0x7d, 0x66, 0x05, 0x91, 0xc7, 0xbc, 0xb0, 0x78, 0x76, 0x45, 0xda, 0x7d, 0x9e, - 0xba, 0xcd, 0x64, 0x44, 0xa3, 0x76, 0x93, 0x07, 0x33, 0x03, 0xfc, 0x72, 0x65, 0xc3, 0x22, 0x7e, 0x9d, 0x02, 0x28, - 0xf9, 0x62, 0xd5, 0xfa, 0x54, 0xf0, 0xaa, 0x37, 0x9c, 0x6e, 0xa7, 0xfb, 0x75, 0x83, 0xdb, 0x5d, 0x0f, 0x4f, 0x78, - 0x88, 0xc6, 0xa2, 0xb5, 0x9f, 0xf8, 0x1c, 0x38, 0xa0, 0xa4, 0x75, 0xbf, 0x0b, 0x2e, 0x94, 0x25, 0x2c, 0x77, 0xcb, - 0x8d, 0x76, 0xca, 0x59, 0x38, 0xda, 0x92, 0x01, 0x77, 0xb0, 0x0d, 0x51, 0xe8, 0xe0, 0xb8, 0x83, 0x93, 0x76, 0xbb, - 0xd3, 0xc5, 0xc9, 0x59, 0x17, 0x06, 0xda, 0x48, 0xba, 0xc7, 0x23, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x8f, - 0x20, 0x68, 0x55, 0x28, 0x5e, 0xf3, 0xe3, 0x38, 0x6e, 0x27, 0xf7, 0x5b, 0xed, 0xee, 0x45, 0x03, 0x00, 0xd4, 0x74, - 0x1f, 0xae, 0xc6, 0xab, 0xa5, 0xae, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xab, 0x35, 0xda, 0x9b, 0x6a, 0x0a, - 0xbe, 0xaa, 0x13, 0xce, 0x6d, 0x11, 0xaf, 0xb4, 0x09, 0xb7, 0x45, 0x6c, 0x07, 0x12, 0x83, 0x74, 0x9e, 0x74, 0x3b, - 0x5d, 0x64, 0xc7, 0xa2, 0x1d, 0x7e, 0x94, 0xfb, 0x64, 0xa7, 0x48, 0x43, 0x03, 0x92, 0x94, 0xb3, 0x93, 0x4b, 0x90, - 0xa8, 0x39, 0xb9, 0x6a, 0x37, 0xe7, 0x2c, 0xf1, 0x13, 0x30, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xb8, 0xa4, 0x00, 0x10, - 0x97, 0x60, 0x5c, 0x74, 0xbf, 0xdb, 0xbf, 0x9f, 0x74, 0xcf, 0x3b, 0x96, 0xe8, 0xf1, 0xcb, 0x4e, 0x2d, 0xcd, 0x4c, - 0x3d, 0xe9, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0xdf, 0x85, 0x32, 0x2e, 0x25, 0x2c, 0x05, 0xc1, 0x36, 0xaa, 0x62, 0x10, - 0x61, 0x23, 0xad, 0xe5, 0x9e, 0xd7, 0xb2, 0x2f, 0xce, 0x4e, 0xef, 0x77, 0x43, 0xa8, 0x95, 0xb3, 0x30, 0x0b, 0xed, - 0x26, 0xe2, 0x67, 0x07, 0x4b, 0x8b, 0x8e, 0x93, 0x6e, 0xba, 0x33, 0x41, 0xbb, 0x69, 0x8e, 0x0d, 0x0e, 0x04, 0x0a, - 0xc7, 0x17, 0xc2, 0xe9, 0x4b, 0x82, 0xfb, 0xb1, 0xca, 0xd0, 0x24, 0x54, 0x38, 0xfb, 0x7b, 0xca, 0xe0, 0x3d, 0xcd, - 0xf0, 0xaa, 0xf2, 0x31, 0x15, 0x5f, 0xa8, 0x7a, 0x4d, 0x21, 0x82, 0x88, 0x18, 0x46, 0x2e, 0xbe, 0x79, 0x3d, 0xf7, - 0x07, 0x70, 0x11, 0x66, 0x02, 0x2e, 0x34, 0xbd, 0x12, 0xb4, 0xe2, 0x05, 0x3e, 0x86, 0x0e, 0xb5, 0x66, 0x58, 0x7d, - 0x9e, 0x3a, 0x93, 0x82, 0x50, 0xb7, 0xf5, 0x8e, 0x7f, 0xab, 0x5c, 0x52, 0x5e, 0x65, 0x27, 0x5d, 0x94, 0xb8, 0xcb, - 0xf2, 0xa4, 0x8d, 0x92, 0xc0, 0x84, 0xc4, 0x1d, 0xc9, 0xb3, 0x8c, 0x0c, 0xa2, 0xdb, 0x08, 0x47, 0x77, 0x11, 0x8e, - 0xac, 0x0f, 0xf3, 0x6f, 0xe0, 0xc7, 0x1d, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, 0xd2, 0x4c, 0x40, 0x60, 0xb1, 0x68, - 0x88, 0xc7, 0x50, 0xda, 0x78, 0x56, 0x97, 0xa5, 0x1f, 0xfb, 0xaf, 0xd2, 0xf5, 0xda, 0xa6, 0x04, 0x52, 0xe6, 0xd2, - 0xec, 0x50, 0xfb, 0x30, 0x76, 0x44, 0x3d, 0xb3, 0x1e, 0x61, 0x10, 0x40, 0xe8, 0x9d, 0x7f, 0x58, 0xaf, 0x8a, 0x49, - 0xc2, 0x4e, 0x61, 0xa5, 0xc1, 0x15, 0x3d, 0x0a, 0xcf, 0xb0, 0x08, 0x4f, 0x84, 0x2f, 0x0c, 0x62, 0x85, 0xff, 0x9d, - 0x4b, 0xb9, 0xf0, 0xbf, 0xb5, 0x2c, 0x7f, 0xc1, 0x73, 0x2c, 0xce, 0xa2, 0x05, 0x2c, 0xb7, 0x6c, 0x08, 0xa4, 0x11, - 0xab, 0x8f, 0xe0, 0xe3, 0xc4, 0x85, 0xa9, 0x03, 0x89, 0xf0, 0xa3, 0x11, 0xa8, 0xbc, 0x7c, 0xf8, 0xd1, 0x86, 0x4c, - 0x32, 0x9f, 0x10, 0x33, 0x0d, 0xc2, 0x22, 0x4b, 0xb8, 0xd0, 0x98, 0x16, 0x4c, 0xa9, 0xc8, 0xc6, 0x12, 0x8c, 0xa4, - 0xf0, 0x8f, 0x43, 0xfa, 0x94, 0x89, 0x88, 0x4c, 0x87, 0xf5, 0xd9, 0x5a, 0x71, 0x38, 0x97, 0x85, 0x4a, 0xed, 0x4b, - 0x31, 0x1e, 0x8c, 0x8b, 0xf2, 0x19, 0xc6, 0x74, 0x9c, 0x6d, 0xb0, 0xbd, 0xc3, 0x2e, 0x0b, 0xb9, 0x2b, 0xed, 0xb0, - 0xd4, 0x2c, 0xdb, 0x7c, 0x6d, 0x42, 0xaa, 0x36, 0xa3, 0x60, 0xa2, 0xd5, 0x80, 0xaa, 0xc0, 0x1d, 0x50, 0xd8, 0x06, - 0xa5, 0x49, 0x57, 0x65, 0xc9, 0x74, 0x55, 0x2e, 0xc3, 0x59, 0xab, 0xb5, 0xd9, 0xe0, 0x82, 0x99, 0x40, 0x2e, 0x7b, - 0x4b, 0x40, 0xbe, 0x9a, 0xc9, 0x9b, 0x20, 0x57, 0xa5, 0xe5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, - 0x5f, 0xb8, 0xe2, 0x00, 0x4f, 0x37, 0xbb, 0x91, 0x94, 0x39, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x7c, - 0xcc, 0xf6, 0xb7, 0x09, 0x66, 0xcc, 0xff, 0x5e, 0x8b, 0x1e, 0x81, 0x2c, 0xbb, 0x67, 0x50, 0x07, 0x16, 0x71, 0x0d, - 0x1d, 0x84, 0x32, 0xf8, 0x24, 0xc4, 0xcd, 0x9c, 0xde, 0xc9, 0xa5, 0x06, 0xb8, 0x2c, 0xb5, 0x7c, 0xed, 0xc2, 0x21, - 0x1c, 0xb6, 0xb0, 0x8f, 0x8c, 0xb0, 0x82, 0x90, 0x01, 0x2d, 0x6c, 0x23, 0x62, 0xb4, 0xb0, 0x0b, 0x54, 0xd0, 0xc2, - 0x26, 0x3c, 0x45, 0x6b, 0x53, 0xc6, 0x36, 0xbb, 0x2b, 0x9f, 0xd4, 0xac, 0x36, 0xc1, 0xc2, 0x49, 0x87, 0x9a, 0xe8, - 0xe0, 0xf6, 0x90, 0x11, 0xde, 0xf8, 0xf1, 0xfa, 0xd5, 0x4b, 0x17, 0xb9, 0x9a, 0x4f, 0xc0, 0x65, 0xd3, 0xa9, 0xc6, - 0xee, 0x6c, 0x88, 0xf9, 0x4a, 0x51, 0x6a, 0x85, 0x53, 0x13, 0xec, 0x53, 0xe8, 0x3c, 0xb1, 0x97, 0x17, 0xcf, 0x64, - 0x31, 0xa7, 0xf6, 0xc6, 0x08, 0xdf, 0x29, 0xf7, 0xf8, 0xbc, 0x79, 0xdf, 0xa6, 0x9a, 0xe4, 0xdb, 0xed, 0xab, 0x88, - 0x45, 0x66, 0xe4, 0x57, 0xd0, 0x06, 0x98, 0xca, 0x7e, 0xe0, 0xac, 0x20, 0x2e, 0xfe, 0x7f, 0x40, 0x5e, 0xde, 0x58, - 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, - 0xd5, 0xdf, 0xde, 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0xc9, 0x25, 0x88, 0x1e, 0xe5, 0x33, 0x7f, 0x1c, 0x44, 0x13, - 0x7f, 0xf7, 0x7c, 0xd5, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, - 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x17, 0xe7, 0x97, 0x6d, 0xd6, 0x3c, 0x5b, 0xaf, 0xf3, 0xab, 0x36, - 0x6b, 0x77, 0xed, 0xb3, 0x7b, 0x91, 0xca, 0x80, 0xe6, 0xf2, 0x09, 0xcf, 0x22, 0xd0, 0xce, 0x4e, 0x33, 0x13, 0x4e, - 0x61, 0xe3, 0x15, 0x3f, 0x4b, 0x5d, 0xf5, 0x25, 0xc1, 0xb8, 0x94, 0x58, 0x3d, 0x7e, 0x81, 0xfa, 0xed, 0x74, 0xd7, - 0x55, 0xba, 0xd9, 0x3e, 0x0e, 0x2e, 0x5c, 0x0a, 0x84, 0x3b, 0x10, 0xf2, 0x00, 0xf4, 0xbb, 0x2b, 0x01, 0xa6, 0x41, - 0x80, 0xca, 0x0a, 0x44, 0x5a, 0x3e, 0x5f, 0xce, 0x9f, 0x15, 0xd4, 0x2c, 0xc3, 0x13, 0x3e, 0xe5, 0x5a, 0xa5, 0x14, - 0xa4, 0xdb, 0x7d, 0xe9, 0x9b, 0xfd, 0x12, 0x54, 0x56, 0x8b, 0xbf, 0x9b, 0x68, 0x9e, 0x7d, 0x56, 0x6e, 0xe1, 0x10, - 0x36, 0x2b, 0x2b, 0x70, 0x86, 0x36, 0x38, 0x97, 0x53, 0x5a, 0x70, 0x3d, 0x9b, 0xff, 0x5b, 0xab, 0xc3, 0x06, 0x7a, - 0x68, 0x2e, 0xac, 0x00, 0x24, 0x54, 0x8c, 0xd7, 0x6b, 0x7e, 0xf2, 0xed, 0xfb, 0x24, 0xef, 0x13, 0xde, 0xc6, 0x1d, - 0x7c, 0x8a, 0xbb, 0xb8, 0xdd, 0xc2, 0xed, 0x2e, 0x5c, 0xdd, 0x67, 0xf9, 0x72, 0xcc, 0x54, 0x0c, 0xef, 0xaf, 0xe9, - 0xab, 0xe4, 0xe2, 0xb8, 0x7a, 0x75, 0xa0, 0x48, 0x1c, 0xba, 0x04, 0xc1, 0xef, 0x5d, 0xd4, 0xc0, 0x28, 0x0a, 0x43, - 0xd6, 0x4d, 0x43, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x3a, 0xed, 0x83, 0x3d, 0xb7, 0x5d, 0xd9, 0x26, 0x98, 0x7d, 0xdb, - 0x9f, 0x69, 0xf5, 0xb3, 0xa9, 0x4b, 0xc4, 0xf0, 0xd0, 0xab, 0xd0, 0x03, 0x5d, 0x91, 0xf6, 0xd1, 0x11, 0x58, 0x1d, - 0x05, 0xb3, 0xe1, 0x36, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, 0x18, 0x77, 0xbe, 0xe2, 0x64, 0x65, 0x61, - 0xab, 0x81, 0x0a, 0xb3, 0x22, 0x8c, 0xab, 0x17, 0x92, 0x0a, 0x23, 0x44, 0xc3, 0x11, 0xe6, 0x82, 0xa1, 0x1c, 0xb6, - 0xb0, 0x9c, 0x4c, 0x14, 0xd3, 0x70, 0x74, 0x14, 0xec, 0x0b, 0x2b, 0x94, 0x39, 0x45, 0x46, 0x6c, 0xca, 0xc5, 0x43, - 0xfd, 0x07, 0x2b, 0xa4, 0xf9, 0x34, 0x1a, 0x8c, 0x34, 0x32, 0xab, 0x18, 0xe1, 0x2c, 0xe7, 0x0b, 0xa8, 0x3a, 0x2d, - 0xc0, 0xe9, 0x07, 0xfe, 0xf2, 0x71, 0x1a, 0xb6, 0x09, 0xe4, 0xeb, 0x37, 0x1b, 0xd3, 0x05, 0x8f, 0x0b, 0x7a, 0xf3, - 0x4a, 0x3c, 0x86, 0x1d, 0xf5, 0xb0, 0x60, 0x14, 0xb2, 0x21, 0xe9, 0x2d, 0x34, 0x05, 0x1f, 0xd0, 0xe6, 0xcf, 0x06, - 0x70, 0xe9, 0x85, 0xf9, 0xb0, 0x15, 0x7d, 0xec, 0xc6, 0xa4, 0x6c, 0xcb, 0x64, 0x9a, 0x53, 0xba, 0xca, 0xb4, 0x51, - 0xa8, 0xca, 0x29, 0x6c, 0xb0, 0x8b, 0x7a, 0x12, 0x0e, 0x66, 0x4c, 0xd5, 0x2c, 0x1d, 0x0c, 0xcd, 0xdf, 0x57, 0xb6, - 0x64, 0x0b, 0xbb, 0x88, 0x33, 0x1b, 0x6c, 0x1e, 0x4e, 0x0d, 0xca, 0xb7, 0x31, 0xdc, 0xc3, 0xc2, 0xeb, 0x9d, 0x35, - 0xf2, 0x79, 0xe6, 0xc9, 0xe6, 0xd9, 0x66, 0x63, 0x06, 0xa2, 0x52, 0xd0, 0x03, 0xbd, 0xf1, 0xdb, 0xa6, 0x05, 0xdb, - 0xa3, 0xfc, 0xea, 0xb6, 0xf0, 0x9c, 0xc3, 0x63, 0xa4, 0xbe, 0xbd, 0x6b, 0x5d, 0xc8, 0xcf, 0x0e, 0x24, 0xad, 0x20, - 0xc5, 0x4e, 0x27, 0xe8, 0xec, 0x14, 0x07, 0x23, 0x07, 0x7a, 0x7e, 0xfd, 0xd9, 0xc2, 0xda, 0xff, 0x7e, 0x5d, 0x16, - 0x34, 0xf1, 0x74, 0xca, 0x09, 0x65, 0xfe, 0xfc, 0x7c, 0xc5, 0x93, 0x0a, 0x15, 0xdc, 0x2b, 0x5e, 0xb0, 0xa7, 0x6d, - 0xa0, 0xcf, 0x39, 0xfd, 0x64, 0x7f, 0xd8, 0x18, 0x3e, 0xa5, 0x96, 0x2d, 0x2b, 0xa4, 0x52, 0x0f, 0x6d, 0x9a, 0x3d, - 0x7a, 0xe0, 0x88, 0xfc, 0x19, 0xba, 0x00, 0x5e, 0x7f, 0x5c, 0xc8, 0x85, 0x41, 0x04, 0xf7, 0xdb, 0x8d, 0xdb, 0xf8, - 0x0a, 0x80, 0xb7, 0xc3, 0x41, 0xf5, 0x4f, 0x0b, 0xd8, 0xdf, 0xa8, 0x2c, 0xe9, 0xc7, 0xdb, 0xb1, 0xc7, 0x7f, 0x21, - 0x21, 0x6a, 0xbc, 0xc5, 0xc3, 0xc4, 0xa1, 0x53, 0xc9, 0x9a, 0x95, 0x3f, 0x77, 0x4a, 0x02, 0x86, 0xd5, 0x0b, 0x86, - 0x6c, 0xdc, 0x4e, 0x71, 0x9b, 0xf9, 0x1f, 0x54, 0x30, 0x58, 0xf0, 0xb5, 0x91, 0x54, 0x2c, 0x8b, 0xdf, 0x3e, 0x75, - 0xfe, 0xab, 0xce, 0x71, 0x1d, 0xea, 0xda, 0x4b, 0xa1, 0x23, 0x13, 0xa5, 0x39, 0x42, 0x47, 0x47, 0x5b, 0x19, 0x74, - 0x02, 0x80, 0x47, 0x8e, 0xfd, 0xf2, 0xcb, 0xe7, 0xd9, 0x31, 0xa3, 0x79, 0x2c, 0xa2, 0x90, 0xb9, 0xf3, 0xdc, 0x9c, - 0x9d, 0xc8, 0x13, 0xaa, 0x66, 0xbe, 0x30, 0xc0, 0xf1, 0xd1, 0x4e, 0x2a, 0xe0, 0x7b, 0xb4, 0xd9, 0x33, 0x81, 0x2d, - 0x7e, 0xcb, 0x4e, 0x6a, 0x5f, 0x41, 0xbf, 0x40, 0xab, 0x7d, 0x4c, 0xe5, 0xd6, 0x02, 0x47, 0xdb, 0x13, 0xd9, 0x3b, - 0xf4, 0xad, 0x3a, 0x25, 0xeb, 0xf1, 0x62, 0xbf, 0xd1, 0x57, 0x21, 0xf6, 0x25, 0x57, 0xb4, 0x6d, 0xc4, 0xaa, 0xd7, - 0x82, 0x75, 0x65, 0xea, 0x54, 0x5d, 0xf3, 0x56, 0x96, 0x36, 0xa5, 0x5d, 0x92, 0xbd, 0xdb, 0x62, 0xe1, 0x55, 0x78, - 0xa3, 0x51, 0x5e, 0x84, 0x82, 0x3d, 0x96, 0x18, 0xf6, 0x38, 0x81, 0xeb, 0x85, 0xf5, 0x3a, 0x86, 0x3f, 0xfb, 0xc6, - 0xb0, 0xcf, 0x74, 0xe9, 0x37, 0xbe, 0xc5, 0xaf, 0x04, 0x01, 0x8b, 0x9d, 0x1d, 0x24, 0x58, 0x77, 0xb9, 0x41, 0xc3, - 0x71, 0xe2, 0xbf, 0xe0, 0xb9, 0x6c, 0xed, 0x5d, 0x0e, 0x46, 0xd9, 0x57, 0x9e, 0xd8, 0x2b, 0x59, 0xcb, 0x5a, 0xb4, - 0xfb, 0x2d, 0x09, 0x86, 0xd8, 0x4d, 0xe9, 0x1c, 0xb7, 0x92, 0x36, 0x8a, 0x5c, 0xb1, 0x0a, 0xfd, 0xbf, 0x56, 0x24, - 0xb3, 0x99, 0xff, 0x75, 0x7e, 0x7e, 0xee, 0x52, 0x9c, 0xcd, 0x9f, 0x32, 0x1e, 0x70, 0x26, 0x81, 0x7d, 0xe1, 0x19, - 0x33, 0x3a, 0xe4, 0x37, 0x30, 0x14, 0x22, 0xc8, 0x95, 0x70, 0xec, 0x12, 0xbc, 0xf6, 0x08, 0x94, 0x07, 0xd8, 0xbf, - 0x27, 0x5b, 0xe5, 0xfc, 0x73, 0x51, 0x3e, 0x9c, 0x72, 0xd9, 0x20, 0xfb, 0x62, 0x3e, 0x07, 0xd6, 0x4c, 0x06, 0x5e, - 0x48, 0x88, 0xb0, 0xfd, 0x6d, 0x58, 0x5a, 0x67, 0x29, 0x83, 0x23, 0x2d, 0x97, 0xd9, 0xcc, 0x6a, 0xfe, 0xdd, 0x87, - 0x29, 0xeb, 0x9e, 0x1a, 0x82, 0xc8, 0x5d, 0x64, 0xe5, 0xa2, 0x82, 0x46, 0xdf, 0x97, 0x01, 0x40, 0x0f, 0x5e, 0xb2, - 0x25, 0xfb, 0x1e, 0x1f, 0x54, 0x29, 0xf0, 0xf1, 0xb0, 0xe0, 0x34, 0xff, 0x1e, 0x1f, 0x54, 0x81, 0x40, 0xc1, 0x15, - 0xd2, 0xc4, 0xd2, 0xc4, 0xe6, 0x59, 0xed, 0x34, 0x12, 0x40, 0x41, 0xf3, 0xc8, 0x1c, 0x64, 0xcf, 0x5d, 0x8c, 0xc6, - 0xa4, 0x83, 0x5d, 0x70, 0x30, 0x1b, 0x11, 0xd6, 0x06, 0x52, 0x87, 0xb8, 0x75, 0xe5, 0x6c, 0xcc, 0xd7, 0xa3, 0xad, - 0x05, 0x31, 0xca, 0x64, 0x72, 0xf5, 0x8e, 0xc7, 0x3b, 0x8b, 0x85, 0xc2, 0x6a, 0xc1, 0x02, 0xd5, 0xaa, 0x54, 0xe9, - 0x61, 0xf1, 0xdd, 0x82, 0x59, 0x50, 0xc4, 0x6c, 0xbd, 0x87, 0xb7, 0x5c, 0x11, 0x90, 0x92, 0x5d, 0x12, 0xbc, 0x8c, - 0x6e, 0x30, 0x95, 0xac, 0xe6, 0x72, 0xcc, 0x2c, 0xa1, 0x67, 0x4a, 0x47, 0xd8, 0xe4, 0x29, 0x88, 0x24, 0x76, 0xd8, - 0xc2, 0x8e, 0x35, 0x7a, 0x21, 0xbc, 0x90, 0x02, 0xe7, 0xaa, 0x69, 0x62, 0x4e, 0xb9, 0x89, 0x2e, 0xf6, 0x50, 0x2d, - 0x58, 0xa6, 0x2d, 0x02, 0x1c, 0x3a, 0x34, 0x94, 0xe2, 0xb9, 0x01, 0x85, 0x79, 0xd2, 0xdb, 0xa5, 0x3c, 0x86, 0xc5, - 0x0b, 0x52, 0x80, 0xa8, 0x71, 0x31, 0x2d, 0xeb, 0x2c, 0xf2, 0xe5, 0x94, 0x8b, 0x0a, 0x19, 0x0a, 0xa6, 0x16, 0x52, - 0xc0, 0x8b, 0x1a, 0x65, 0x11, 0x43, 0x87, 0x6a, 0xf8, 0x6e, 0x49, 0x58, 0x59, 0xc7, 0x1c, 0x53, 0x5c, 0x54, 0x35, - 0x80, 0xb9, 0x78, 0x68, 0x04, 0x44, 0x1f, 0x5e, 0xf6, 0x95, 0x78, 0x2b, 0x17, 0x55, 0xbe, 0xa7, 0x71, 0x3e, 0x70, - 0xbd, 0xb3, 0x1b, 0x46, 0x1b, 0xf3, 0xe8, 0x55, 0xb0, 0x7d, 0x7f, 0xe3, 0xd5, 0x43, 0x70, 0x1b, 0xf3, 0x6c, 0x56, - 0x99, 0x35, 0x62, 0xe5, 0x1b, 0x11, 0x55, 0x7b, 0xf5, 0xaa, 0x85, 0xb0, 0x15, 0x01, 0x2a, 0x05, 0x1f, 0xef, 0xe4, - 0xbf, 0xd0, 0x36, 0xdf, 0x9e, 0x43, 0x65, 0x78, 0x20, 0x4f, 0x86, 0xaa, 0x1e, 0x70, 0x51, 0x7e, 0x08, 0x60, 0xf1, - 0x23, 0x13, 0x3f, 0x78, 0xdf, 0x05, 0x32, 0x67, 0x2a, 0x96, 0x78, 0x35, 0xa0, 0xc3, 0xd4, 0xca, 0x43, 0xa9, 0x04, - 0xdb, 0x9e, 0x9b, 0x82, 0x6b, 0x1f, 0xa8, 0x18, 0x0f, 0xd8, 0x30, 0x5d, 0xd5, 0x83, 0x19, 0xdb, 0x70, 0xca, 0xde, - 0x9c, 0xd3, 0x44, 0xff, 0xa5, 0x43, 0x9c, 0x13, 0xb0, 0x3d, 0x2e, 0x99, 0xfb, 0x38, 0x43, 0xfd, 0x3a, 0x87, 0xbf, - 0xda, 0xe0, 0x1c, 0x67, 0x28, 0x7d, 0x18, 0xc3, 0x05, 0xd6, 0x06, 0x03, 0xf8, 0x32, 0x4b, 0xaa, 0xc0, 0x23, 0x35, - 0x33, 0x12, 0xab, 0xbb, 0x08, 0x44, 0x2b, 0x1d, 0xde, 0x8e, 0x33, 0x1f, 0x0e, 0xdc, 0x70, 0xaf, 0xcf, 0x8c, 0x70, - 0x38, 0xca, 0xe2, 0xda, 0x39, 0xc3, 0xc9, 0xd5, 0x21, 0xaf, 0x9d, 0x98, 0x60, 0xed, 0x1d, 0x9e, 0x2a, 0xa0, 0x47, - 0x83, 0x53, 0xc5, 0xd2, 0x10, 0x88, 0x99, 0x00, 0xde, 0xcc, 0xe1, 0xd1, 0x16, 0xe0, 0x7c, 0xb4, 0xc1, 0xc1, 0x57, - 0x5a, 0xeb, 0x6a, 0x5b, 0x89, 0xb2, 0xd9, 0xe0, 0xc1, 0x32, 0xc3, 0x93, 0x0c, 0xcf, 0xb3, 0x61, 0x70, 0xdc, 0x7c, - 0xcc, 0x42, 0x93, 0xae, 0xf5, 0xfa, 0x85, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0xa8, 0x0f, 0x08, 0x9f, 0x42, - 0x16, 0xd0, 0x92, 0xbe, 0xfb, 0xdb, 0xb0, 0xaf, 0x85, 0xa3, 0x46, 0xcc, 0x13, 0x4b, 0x46, 0xfa, 0xfe, 0x47, 0x99, - 0x65, 0x5b, 0x6b, 0x44, 0x8b, 0xdb, 0x83, 0xa8, 0xe1, 0xdb, 0xab, 0xce, 0x97, 0x51, 0x69, 0xb6, 0x03, 0x88, 0x62, - 0x8d, 0x93, 0x74, 0xb0, 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcc, 0x03, 0x7a, - 0xb1, 0x42, 0x89, 0xe1, 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x9a, 0xc8, - 0x7d, 0x97, 0x55, 0x96, 0x41, 0x82, 0x08, 0x23, 0xf2, 0xdb, 0xeb, 0x52, 0x61, 0x9f, 0xe8, 0xb3, 0x7f, 0x8c, 0x2f, - 0x20, 0xdc, 0xbc, 0x4d, 0x69, 0x31, 0xa2, 0x53, 0x60, 0x63, 0x21, 0x0e, 0xe1, 0x4e, 0xc2, 0x7a, 0x3d, 0x18, 0xf6, - 0x84, 0x21, 0xcf, 0xee, 0x01, 0xc1, 0xb2, 0xa1, 0xfd, 0x0d, 0xc0, 0x55, 0xb7, 0xa5, 0xe6, 0xda, 0xe8, 0x7e, 0xa8, - 0x79, 0xe3, 0x8c, 0xbb, 0x24, 0xf7, 0x4c, 0x49, 0xf5, 0x12, 0x79, 0xcd, 0x02, 0xdc, 0x84, 0xae, 0xc2, 0x63, 0xbc, - 0xb4, 0x36, 0x9c, 0xe6, 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x64, 0x43, 0x3c, 0xf6, 0xe1, - 0xce, 0x0f, 0xdf, 0xc4, 0x63, 0x84, 0x0a, 0x62, 0x60, 0x6a, 0x5d, 0xb6, 0xc7, 0x95, 0xdd, 0xbe, 0xc9, 0x34, 0x0c, - 0x83, 0x31, 0x62, 0x1e, 0x87, 0x46, 0xcc, 0x79, 0xa3, 0x81, 0x96, 0x64, 0x0c, 0x46, 0xcc, 0xcb, 0xa0, 0xb5, 0xa5, - 0x7d, 0xec, 0x34, 0x68, 0x6f, 0x89, 0x50, 0x8f, 0x03, 0x4d, 0xd3, 0xf0, 0xac, 0x49, 0xf5, 0xac, 0xbc, 0x7f, 0x64, - 0xeb, 0xa4, 0x03, 0x8a, 0x84, 0xc9, 0x95, 0x9f, 0x84, 0x75, 0x0d, 0xb7, 0xe3, 0x9e, 0x98, 0x71, 0x3b, 0xdb, 0x06, - 0x35, 0x90, 0x83, 0x6c, 0x38, 0xec, 0x49, 0x6f, 0x25, 0xd1, 0xc2, 0x93, 0xea, 0x21, 0x94, 0x6a, 0xf1, 0xbe, 0xe8, - 0xed, 0x2b, 0x6f, 0xee, 0xdf, 0x57, 0xdd, 0x3e, 0x8f, 0x81, 0x03, 0x3a, 0x84, 0xfb, 0xa1, 0x2a, 0x3e, 0xd8, 0x49, - 0x07, 0xa2, 0xa0, 0xa5, 0xad, 0x9a, 0x40, 0x6a, 0xcd, 0xec, 0x62, 0xdd, 0x54, 0xe8, 0x58, 0x40, 0x18, 0x32, 0x55, - 0x75, 0x77, 0xab, 0x02, 0xd5, 0x10, 0x87, 0x53, 0xff, 0xb1, 0x35, 0x62, 0x8d, 0xa3, 0xce, 0x38, 0x32, 0x46, 0x92, - 0x76, 0xf9, 0xe0, 0xed, 0x23, 0xb0, 0x12, 0xf0, 0x31, 0xa8, 0x4d, 0x92, 0x31, 0x24, 0x78, 0xc3, 0x32, 0x6d, 0xf8, - 0x10, 0xee, 0x10, 0x94, 0x27, 0x36, 0x28, 0xad, 0xab, 0x64, 0x21, 0x17, 0x74, 0x19, 0xa0, 0xe7, 0x97, 0xf2, 0x37, - 0x36, 0x1c, 0x59, 0x00, 0x87, 0x6c, 0x67, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2f, 0x85, 0x4e, 0x4c, 0xbc, - 0xee, 0x6b, 0xd8, 0xa0, 0x78, 0x01, 0x0e, 0x82, 0x4e, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x35, 0xc9, 0x06, 0xb7, 0xe6, - 0x24, 0x5e, 0xac, 0xd7, 0x2d, 0x74, 0xfc, 0x93, 0x79, 0x92, 0x7a, 0x52, 0x2a, 0xdc, 0x27, 0x95, 0xc2, 0x1d, 0x2c, - 0x01, 0xc9, 0x24, 0xd0, 0xb5, 0x63, 0x19, 0xaa, 0xd1, 0x21, 0x5a, 0xfa, 0x0b, 0x88, 0x9d, 0xed, 0x8e, 0x25, 0xd0, - 0xb3, 0xef, 0x14, 0xb0, 0xba, 0xf6, 0xb2, 0x04, 0x32, 0x82, 0xbb, 0xdf, 0x04, 0x46, 0x85, 0x68, 0x7c, 0xfe, 0xcc, - 0xab, 0x16, 0x3c, 0x71, 0xfe, 0x5c, 0x73, 0xc3, 0xba, 0x17, 0xf4, 0xc6, 0x34, 0x1f, 0x4f, 0x70, 0x73, 0x62, 0xc1, - 0x79, 0xd2, 0x81, 0x9f, 0x16, 0xa2, 0x27, 0x1d, 0xec, 0x52, 0xf1, 0xa4, 0x04, 0x72, 0x88, 0x9e, 0xce, 0x40, 0x0a, - 0x58, 0xe9, 0xd8, 0x6a, 0x91, 0xa6, 0x68, 0xbd, 0x9e, 0x5e, 0x92, 0x16, 0x42, 0x2b, 0x75, 0xc3, 0x75, 0x36, 0x03, - 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa6, 0x7a, 0x16, 0x23, 0x3c, 0x41, 0xab, 0x31, 0x9b, 0xd0, 0x65, 0xae, 0x53, 0xd5, - 0xe7, 0x89, 0x0d, 0xdc, 0xcb, 0x6c, 0x24, 0xb8, 0x93, 0x0e, 0x9e, 0x1a, 0xfe, 0xf2, 0xbd, 0x31, 0x07, 0x29, 0x32, - 0x93, 0x3c, 0x35, 0x09, 0x98, 0x27, 0x59, 0x2e, 0x15, 0xb3, 0xcd, 0xf4, 0xac, 0x6d, 0x39, 0x84, 0x24, 0x8f, 0x74, - 0xc1, 0x8d, 0x15, 0x65, 0x94, 0xce, 0x88, 0xea, 0xab, 0x93, 0x4e, 0x3a, 0xc5, 0x3c, 0x01, 0x4e, 0xef, 0xad, 0x8c, - 0x59, 0xa3, 0xbc, 0x15, 0x9d, 0xa3, 0xe3, 0x19, 0x16, 0xd5, 0x25, 0xea, 0x1c, 0x1d, 0x4f, 0x11, 0x9e, 0x37, 0xc8, - 0x4c, 0x81, 0xc7, 0x30, 0x17, 0xff, 0x47, 0xca, 0x7f, 0x75, 0xd8, 0x10, 0x62, 0xfa, 0x0d, 0xec, 0x14, 0x36, 0x8e, - 0xd2, 0x9c, 0x80, 0xd7, 0x62, 0xfb, 0x1c, 0x67, 0x64, 0xda, 0xcc, 0x7d, 0xc0, 0x3d, 0xd3, 0x4a, 0xe3, 0x56, 0xa3, - 0xe3, 0x0c, 0x8f, 0xb7, 0x93, 0x62, 0x33, 0xd7, 0x66, 0x9e, 0x66, 0x70, 0xbe, 0x57, 0xa3, 0x70, 0xe5, 0x97, 0xdb, - 0x49, 0x61, 0x79, 0x07, 0xdc, 0xe6, 0x18, 0x8b, 0x26, 0xc5, 0x39, 0x9e, 0x37, 0x5f, 0xe2, 0x79, 0xf3, 0x5d, 0x99, - 0xd1, 0x58, 0x62, 0x01, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xab, 0xe4, 0x31, 0x16, 0x0d, 0x53, 0x1e, 0xcf, 0x1b, 0x55, - 0xe9, 0xe6, 0x12, 0x8b, 0x86, 0x29, 0xdd, 0x78, 0x87, 0xe7, 0x8d, 0x97, 0xff, 0x62, 0xd2, 0x51, 0x0a, 0xe8, 0xb2, - 0x40, 0xab, 0xcc, 0x0e, 0xf1, 0xfa, 0xd7, 0x37, 0x6f, 0xdb, 0x1f, 0x3b, 0xc7, 0x53, 0xec, 0xd7, 0x2f, 0x33, 0x38, - 0x96, 0xe9, 0x98, 0x35, 0x01, 0xa2, 0x19, 0xee, 0x1c, 0xcf, 0x70, 0xe7, 0x38, 0x73, 0x4d, 0x6d, 0xe6, 0x0d, 0x72, - 0xab, 0x43, 0x28, 0xea, 0x28, 0x0d, 0xe1, 0xe3, 0x27, 0x9b, 0x4e, 0x51, 0x0d, 0x94, 0xe8, 0x78, 0x5a, 0x03, 0x15, - 0x7c, 0x2f, 0x6b, 0xdf, 0x55, 0xbd, 0x0a, 0x83, 0x2c, 0x94, 0x50, 0xb8, 0xe6, 0x06, 0x3c, 0xb5, 0x14, 0x03, 0x99, - 0x30, 0xc5, 0x02, 0xe5, 0x1b, 0xa0, 0x30, 0xca, 0x13, 0x33, 0xf4, 0x60, 0x3a, 0x26, 0xf1, 0xff, 0xe7, 0xc9, 0x94, - 0x43, 0x2f, 0xb7, 0xcc, 0xce, 0xf4, 0xdc, 0x64, 0xc2, 0xe1, 0x03, 0x8f, 0xf5, 0x7f, 0xed, 0x40, 0xb1, 0x01, 0x29, - 0xfe, 0xbf, 0x74, 0x74, 0x21, 0x18, 0x21, 0x2b, 0x4a, 0x0b, 0x87, 0xf8, 0xdf, 0x1e, 0x56, 0xd0, 0x7d, 0xb1, 0xd3, - 0x7d, 0x61, 0xba, 0x0f, 0x9b, 0x36, 0xaa, 0x9c, 0xb4, 0xaa, 0x64, 0xc9, 0x7f, 0x9d, 0x6e, 0xed, 0x80, 0x46, 0xd4, - 0xe8, 0xd9, 0x34, 0x6c, 0xf0, 0xb0, 0x9d, 0xee, 0x41, 0xe6, 0x0d, 0xb7, 0x2f, 0xa4, 0xc2, 0xe1, 0x1b, 0xdc, 0xa9, - 0x5e, 0xb5, 0xc0, 0x7b, 0x53, 0x19, 0x7d, 0x65, 0x1c, 0x5a, 0x0e, 0xd2, 0x6d, 0x53, 0x6e, 0x63, 0x2c, 0x9d, 0x74, - 0xb1, 0x71, 0x45, 0x84, 0x4a, 0xb7, 0x57, 0xa0, 0x14, 0x9f, 0xe8, 0x26, 0x33, 0x5f, 0x97, 0x3a, 0x31, 0x97, 0x50, - 0x0d, 0xf3, 0x79, 0x77, 0xa5, 0x13, 0x2d, 0x17, 0x36, 0xef, 0xee, 0x12, 0xfa, 0x04, 0x0d, 0x6b, 0x23, 0xb0, 0xdb, - 0xe7, 0xce, 0x0e, 0x32, 0x38, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, - 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x11, 0xf2, 0x14, 0xa2, 0xb0, 0xfa, 0xf1, 0x3d, 0xec, 0xc6, - 0x4d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, - 0x13, 0x97, 0x3f, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, - 0x2e, 0x58, 0x44, 0x69, 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0xa1, 0x5f, 0x96, - 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9a, 0xc6, 0xe7, 0x80, 0x6b, 0xfa, 0x57, 0x93, - 0x48, 0x46, 0xec, 0x1f, 0xce, 0x8a, 0xc7, 0xcb, 0xc2, 0x60, 0x9a, 0xe8, 0xeb, 0x24, 0x5b, 0xb4, 0xc1, 0x54, 0x2f, - 0x5b, 0x74, 0x6e, 0xb1, 0xfb, 0xbe, 0xb3, 0xdf, 0x77, 0x58, 0xf4, 0x99, 0xc9, 0x48, 0x99, 0x29, 0xe6, 0xbf, 0xef, - 0xec, 0xf7, 0x1d, 0xde, 0x1d, 0xcc, 0xb5, 0xbf, 0x50, 0x2c, 0xd9, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x6a, - 0x59, 0x26, 0x08, 0x6c, 0x2d, 0x01, 0xe2, 0x7c, 0xbe, 0x88, 0x2b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xab, - 0x54, 0xe0, 0x31, 0x41, 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd4, 0x93, 0x24, 0xc0, - 0xab, 0x1a, 0x95, 0xb7, 0x29, 0x52, 0x7e, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x44, 0x15, 0x03, 0x58, 0x95, 0x25, 0x7d, - 0x02, 0xa9, 0xe7, 0x07, 0x13, 0xfd, 0x65, 0x1b, 0x79, 0xec, 0x3b, 0xbf, 0x9f, 0x99, 0x9e, 0x15, 0x72, 0x39, 0x9d, - 0x81, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, - 0x33, 0xbd, 0xa4, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xfa, 0x48, 0xde, 0xfe, 0x0c, 0xd8, 0x4d, 0x89, 0x6e, 0xec, 0xc9, - 0x7b, 0x03, 0x3b, 0x00, 0x67, 0x84, 0xed, 0xab, 0xf8, 0x50, 0x81, 0xce, 0x1f, 0xe7, 0x84, 0xed, 0xab, 0xfa, 0x84, - 0xd9, 0xec, 0x19, 0xd9, 0x1a, 0x6e, 0x3f, 0xce, 0x1a, 0x39, 0x3a, 0xe9, 0xa4, 0x79, 0xcf, 0x13, 0x03, 0x0b, 0xd0, - 0x00, 0xb8, 0x3b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0xa0, 0x77, 0xc9, 0xa4, 0xbd, 0x2e, 0x37, 0x29, 0xeb, 0x75, 0xa7, - 0xa2, 0x82, 0x05, 0x9e, 0x05, 0x7b, 0x81, 0xda, 0xaf, 0x3d, 0x14, 0xe7, 0x71, 0xb6, 0x6d, 0x7a, 0x5e, 0xf6, 0xdd, - 0xdb, 0xb3, 0xc8, 0xd8, 0xa6, 0xbd, 0xd9, 0x43, 0x24, 0x2c, 0x27, 0xac, 0x03, 0x4e, 0xb8, 0xaa, 0x1d, 0x10, 0xa0, - 0x8f, 0x81, 0xc8, 0x8d, 0x25, 0x59, 0x6d, 0x2a, 0xa3, 0xfb, 0xc0, 0xef, 0x96, 0x12, 0xe9, 0x46, 0x5b, 0x12, 0x4c, - 0x9f, 0x60, 0xd4, 0x74, 0xe6, 0x69, 0xea, 0xda, 0xab, 0xcb, 0xdb, 0xa2, 0xad, 0x7f, 0x03, 0x1a, 0x9b, 0xed, 0x61, - 0x62, 0x28, 0x83, 0x18, 0xe8, 0x7d, 0xc4, 0x7b, 0x8d, 0x46, 0x86, 0x40, 0x21, 0x93, 0x0d, 0xb1, 0x4c, 0xbc, 0x16, - 0xfd, 0xe8, 0xc8, 0xc0, 0xa3, 0x4a, 0x40, 0x98, 0x82, 0x10, 0x12, 0x76, 0x6d, 0x10, 0x36, 0x5c, 0xae, 0x5a, 0x2e, - 0x6c, 0xa4, 0xda, 0xd0, 0xc1, 0xff, 0x2b, 0x5c, 0xb6, 0x7a, 0x66, 0xb9, 0x28, 0x06, 0x37, 0x73, 0x03, 0x16, 0x09, - 0xd2, 0xa3, 0xcd, 0xf6, 0x50, 0xdc, 0x9f, 0x8b, 0xcd, 0x86, 0x80, 0xc4, 0x1c, 0x26, 0x28, 0x1a, 0xce, 0x8d, 0x31, - 0x56, 0x49, 0xa5, 0x65, 0xad, 0x49, 0xcc, 0x41, 0xc0, 0xe8, 0x70, 0xdd, 0x57, 0xb7, 0x29, 0xc3, 0x77, 0xa9, 0xc0, - 0x37, 0xe0, 0x49, 0x93, 0x4a, 0xec, 0x1e, 0x2f, 0x28, 0x36, 0x44, 0xf7, 0x3c, 0x7b, 0x5b, 0xc0, 0x3a, 0x9b, 0x3d, - 0x22, 0x82, 0xdf, 0xd5, 0xaf, 0x36, 0xf8, 0x6e, 0xe1, 0x97, 0x60, 0xfd, 0x1c, 0x9c, 0xa4, 0x58, 0x34, 0x64, 0xb3, - 0x70, 0x47, 0x06, 0x94, 0xab, 0xf8, 0xe5, 0x30, 0x75, 0xa7, 0x18, 0xae, 0x7d, 0xbc, 0xc4, 0xef, 0xb6, 0xda, 0x6d, - 0xa8, 0xb2, 0xb8, 0xdd, 0x9b, 0xa2, 0x21, 0xab, 0xa6, 0xf7, 0x64, 0x6e, 0xa5, 0xd4, 0xbf, 0xde, 0xe1, 0xd6, 0x4e, - 0xfb, 0x7e, 0x9a, 0x6f, 0x3c, 0x3a, 0x57, 0x4d, 0xfb, 0xd4, 0x5a, 0x11, 0x1c, 0xfc, 0x6c, 0xe1, 0xe6, 0xce, 0x80, - 0x03, 0xf8, 0xf9, 0x3b, 0x9a, 0x57, 0x19, 0x44, 0xa7, 0xb7, 0x9a, 0xf1, 0x75, 0xfc, 0xe7, 0xb8, 0x11, 0xf7, 0xd3, - 0x3f, 0x93, 0x3f, 0xc7, 0x0d, 0xd4, 0x47, 0xf1, 0xe2, 0x76, 0xcd, 0xe6, 0x6b, 0x08, 0xb6, 0x76, 0xef, 0x04, 0xbf, - 0x0e, 0x4b, 0x72, 0x4d, 0x73, 0x9e, 0xad, 0xdd, 0x83, 0x80, 0x6b, 0xf7, 0x2a, 0xd1, 0xda, 0xbc, 0x71, 0xb5, 0x8e, - 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, 0x3d, 0xaa, - 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, 0xf5, 0x3d, - 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, 0x96, 0x34, - 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, 0xf2, 0x5d, - 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, 0x06, 0x5f, - 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, 0x87, 0xae, - 0xf2, 0xf0, 0x1e, 0x32, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, 0x61, 0x3e, - 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, 0x64, 0x85, - 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, 0x0c, 0xcb, - 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, 0xba, 0x8d, - 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, 0xf5, 0xd8, - 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, 0x64, 0x62, - 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, 0xee, 0xdc, - 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, 0x2d, 0x76, - 0xae, 0xde, 0xbd, 0xf0, 0x75, 0xbe, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, 0xce, 0xf4, - 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xec, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, 0x0c, 0x94, - 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, 0x20, 0x07, - 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, 0xdf, 0x83, - 0xbb, 0xb3, 0x7b, 0x1d, 0xb2, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, 0x39, 0xbc, - 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, 0x5a, 0xcc, - 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, 0x4b, 0xe9, - 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, - 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, 0xa5, 0xe6, - 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, - 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, 0xb0, 0xea, - 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0x81, 0xd1, - 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, 0x71, 0xac, - 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, 0x36, 0x32, - 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, 0xdb, 0x3c, - 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, 0x92, 0x41, - 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, 0x8b, 0x9a, - 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, 0x06, 0xf6, - 0xe9, 0xca, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, 0x2a, 0xe9, - 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, 0x08, 0xfc, - 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, 0x1e, 0x50, - 0x0c, 0xef, 0xae, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, 0x8b, 0x0b, - 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, 0xbf, 0x93, - 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, 0xa2, 0x30, - 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x5a, 0x3b, 0x65, 0x3a, 0x88, 0x0a, 0xf2, - 0xa4, 0x7c, 0x96, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, 0xc8, 0x34, - 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, 0x10, 0x8a, - 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, 0xeb, 0x85, - 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, 0xea, 0x83, - 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, 0x7f, 0xd2, - 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, 0xa9, 0xc6, - 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, 0x81, 0x55, - 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, 0x84, 0x72, - 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, 0xd8, 0xc2, - 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, 0x6f, 0x32, - 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x3c, 0xb0, 0xea, 0x7b, 0x84, 0x98, - 0x99, 0xf8, 0x4f, 0xf0, 0x2c, 0xf4, 0xb7, 0x9f, 0xa3, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, 0xec, 0x3f, - 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0xd6, 0xa1, - 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x94, - 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, - 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, 0x61, 0xdb, - 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0x28, - 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, 0x70, 0x19, - 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, 0x00, 0x05, - 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0x4f, 0xf2, 0xd6, 0x5e, 0xd0, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, 0xdb, 0x45, - 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, 0x95, 0x9b, - 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, 0x35, 0x90, - 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, 0x10, 0xf2, - 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, 0xc1, 0xe4, - 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, 0x6c, 0x2a, - 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, 0x4a, 0x55, - 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, 0xb2, 0xe5, - 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0x2c, 0x6c, 0xc2, 0xed, 0x30, 0xcd, 0x32, 0x6d, - 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, 0xdf, 0x06, - 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, 0x62, 0x37, - 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, - 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, - 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, 0x03, 0x6a, - 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, 0x2f, 0x43, - 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, 0x33, 0xd4, - 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, - 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, 0xd5, 0x9e, - 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xab, 0x8d, - 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, 0xc8, 0xc1, - 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, - 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, - 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, 0xd8, 0xe5, - 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, 0xc8, 0x81, - 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xeb, - 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, - 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, - 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, 0x6a, 0x8b, - 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, - 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0xaa, - 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, 0x70, 0x23, - 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, 0xfc, 0x4e, - 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, 0x7a, 0x5f, - 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, 0x03, 0x44, - 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, 0xc8, 0x6e, - 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, 0x4c, 0xd9, - 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, 0x2e, 0x40, - 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, 0xb8, 0x30, - 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, 0x5e, 0x66, - 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, 0xad, 0xcd, - 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, 0x47, 0xf7, - 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, 0x1e, 0x6c, - 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, 0x45, 0x19, - 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, - 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, - 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0xe5, 0xce, - 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, 0x9c, 0xe3, - 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, 0xe4, 0xb6, - 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, 0xa6, 0x82, - 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, 0xef, 0x3d, - 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, 0x5a, 0xbd, - 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, 0x75, 0x0e, - 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, 0x84, 0x56, - 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, 0xce, 0x86, - 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, 0x8b, 0x5e, - 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, 0xcd, 0xb8, - 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, 0x29, 0x84, - 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, 0x24, 0xf3, - 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, 0xc2, 0x18, - 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, 0x02, 0xff, - 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x06, - 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, 0xf0, 0x93, - 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, - 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, - 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, 0xc0, 0x3b, - 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, 0xae, 0x9f, - 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, - 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, - 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, 0x87, 0x80, - 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, 0x3a, 0x3a, - 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, 0x93, 0x0f, - 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, 0x5a, 0x05, - 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, 0xcd, 0x84, - 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, 0xed, 0xbd, - 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, 0x1f, 0x1f, - 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, 0xf6, 0xca, - 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, 0x67, 0xe4, - 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, 0x9c, 0x7c, - 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, 0x76, 0x17, - 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, 0xbb, 0x81, - 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, 0x25, 0xcb, - 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, 0xf8, 0xcf, - 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, 0x86, 0xa6, - 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, 0x1a, 0x43, - 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, 0x77, 0x21, - 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, 0xd8, 0xfb, - 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, 0x82, 0xc4, - 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, 0x7c, 0x75, - 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, 0xac, 0xaa, - 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, 0xe5, 0xe1, - 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, 0x11, 0xc6, - 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, 0xdd, 0x75, - 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, 0x35, 0x97, - 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, 0xa0, 0x51, - 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, 0xb1, 0x7c, - 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, 0x72, 0xbc, - 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, 0x5d, 0x52, - 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0xff, 0xb2, 0xf7, 0xae, 0xcb, 0x6d, - 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, 0xa8, 0x32, - 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, 0xe0, 0x06, - 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, 0xfd, 0x3a, - 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0x2f, 0xe2, 0x05, 0xad, 0x77, 0x15, 0x0a, 0x8f, - 0xaa, 0x28, 0xe5, 0x56, 0x72, 0x9d, 0x41, 0x10, 0x3b, 0x7a, 0x61, 0xf8, 0x13, 0x08, 0x21, 0x88, 0x30, 0xe1, 0xb7, - 0x61, 0x46, 0xdb, 0x59, 0xa4, 0x93, 0x7e, 0x1f, 0x66, 0xb8, 0x81, 0x95, 0xfc, 0x5c, 0xf5, 0xd9, 0x7e, 0x1b, 0x84, - 0x6c, 0x17, 0x44, 0xec, 0xa6, 0xd8, 0x06, 0xa5, 0x75, 0x24, 0x7e, 0x54, 0x86, 0xbf, 0xa5, 0xd7, 0xcb, 0x43, 0x88, - 0xf7, 0xe9, 0xa5, 0xf9, 0x59, 0xda, 0x8a, 0x02, 0xdc, 0x47, 0xe8, 0x51, 0x1d, 0x08, 0x76, 0xc2, 0x13, 0x1e, 0xc0, - 0xc9, 0x6a, 0x56, 0xf1, 0xf7, 0x29, 0x88, 0x13, 0x05, 0x87, 0x80, 0xab, 0xed, 0xc7, 0xf4, 0x2b, 0x18, 0xbe, 0x74, - 0xb0, 0xe5, 0xf0, 0xa6, 0xd8, 0xf6, 0x58, 0xc9, 0xdf, 0x01, 0xfb, 0x56, 0x4f, 0xc6, 0xea, 0xf6, 0xc0, 0x59, 0x97, - 0x52, 0x74, 0xbc, 0x29, 0x0e, 0x6f, 0xcf, 0x67, 0xfb, 0x6d, 0x10, 0xb1, 0x5d, 0x90, 0x61, 0xad, 0x93, 0x86, 0xe3, - 0x60, 0x08, 0x9f, 0xc5, 0x08, 0xfb, 0xbf, 0xac, 0x07, 0x5e, 0x42, 0x6a, 0x28, 0x70, 0x31, 0xd8, 0x70, 0xb4, 0xb6, - 0xcb, 0x34, 0x70, 0x53, 0x83, 0x5e, 0xdf, 0x53, 0x88, 0xf2, 0x92, 0xd1, 0xdc, 0x08, 0xd6, 0x8d, 0x21, 0x17, 0x87, - 0xe3, 0x66, 0x39, 0xe4, 0x25, 0x4d, 0xa7, 0x41, 0x28, 0xdd, 0x59, 0xd6, 0x90, 0x44, 0xd9, 0x07, 0xa1, 0x76, 0x6d, - 0xd9, 0x6f, 0x03, 0xdb, 0x97, 0x3f, 0x1a, 0xc6, 0xfe, 0xc5, 0xf2, 0xb1, 0x90, 0x2e, 0xe2, 0x39, 0x08, 0xa2, 0xf6, - 0xf3, 0x6c, 0xb8, 0xf1, 0x2f, 0xd6, 0x8f, 0x85, 0xf2, 0x1b, 0xcf, 0x6d, 0x39, 0x24, 0xcd, 0x5a, 0xf8, 0xc2, 0x38, - 0x25, 0xb8, 0x32, 0xb4, 0x1d, 0x0e, 0x42, 0xff, 0x6d, 0xd6, 0x08, 0x6e, 0x6c, 0x68, 0x9f, 0x2f, 0x7c, 0xd8, 0xda, - 0x68, 0xac, 0x29, 0xa6, 0x5b, 0xe8, 0xdf, 0x64, 0xb6, 0xb4, 0xa7, 0x51, 0xc9, 0x8b, 0x53, 0xd3, 0x88, 0x85, 0x30, - 0x60, 0xe8, 0x27, 0xf3, 0x0e, 0x54, 0x73, 0xc7, 0x23, 0x90, 0xc9, 0x07, 0x7a, 0xb0, 0x26, 0xb5, 0xea, 0xaf, 0x61, - 0x26, 0xff, 0x8f, 0x54, 0x58, 0x8c, 0xee, 0xb6, 0x61, 0xa6, 0xfe, 0x88, 0xe4, 0x1f, 0x2c, 0xe7, 0xbb, 0xd4, 0x0b, - 0xb5, 0x1f, 0x0b, 0x2b, 0x30, 0x28, 0x51, 0x35, 0xa0, 0x07, 0x22, 0xa8, 0xca, 0x20, 0xcd, 0xb0, 0x3a, 0x07, 0xfd, - 0xee, 0x69, 0xd5, 0x91, 0x1c, 0xd2, 0x5a, 0x0d, 0xa9, 0x60, 0xaa, 0xd4, 0x20, 0x3f, 0x1c, 0x6e, 0x53, 0xa6, 0xcb, - 0x80, 0x4b, 0xfa, 0x6d, 0xaa, 0x94, 0xc2, 0x5f, 0x10, 0x80, 0xce, 0xc1, 0x3d, 0xbe, 0x1c, 0x03, 0x69, 0x86, 0x85, - 0xdf, 0x9a, 0x1d, 0x5f, 0x93, 0x70, 0x9b, 0x04, 0x17, 0x03, 0x9c, 0xa3, 0xab, 0xb0, 0xbc, 0x4d, 0x21, 0x82, 0xaa, - 0x84, 0xfa, 0x56, 0xa6, 0x41, 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, - 0x11, 0xd7, 0x33, 0xc2, 0x9a, 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, - 0x8d, 0xab, 0x4a, 0x55, 0x77, 0x73, 0x6a, 0x29, 0x2d, 0xdb, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, - 0xe4, 0x08, 0x26, 0x90, 0x24, 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, - 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0x7f, 0x11, 0x46, - 0x9a, 0xcc, 0x58, 0xc9, 0x22, 0xdb, 0xd5, 0x29, 0x71, 0x1e, 0x27, 0xb0, 0x3d, 0x9a, 0xde, 0xf2, 0x7d, 0x06, 0x51, - 0x41, 0xa0, 0x60, 0xc6, 0x7c, 0xd9, 0xc5, 0x13, 0xdf, 0x67, 0x96, 0xa9, 0xfb, 0x70, 0x30, 0x66, 0x6c, 0xbf, 0xdf, - 0xcf, 0xfb, 0x7d, 0x35, 0xdf, 0xfa, 0xfd, 0xe4, 0xa9, 0xf9, 0xdb, 0x03, 0x06, 0x05, 0x39, 0x11, 0x4d, 0x85, 0x08, - 0xfe, 0x21, 0x79, 0x8c, 0x64, 0x74, 0xc7, 0x7d, 0x6e, 0x79, 0x7e, 0x56, 0x47, 0x20, 0x98, 0x87, 0xc3, 0xa5, 0x02, - 0xbb, 0x96, 0x28, 0x12, 0xb2, 0xfc, 0xc7, 0x60, 0x3c, 0x73, 0x1f, 0x60, 0xc9, 0x00, 0x84, 0xad, 0xf2, 0x74, 0xbd, - 0xe7, 0xab, 0xe0, 0x9d, 0x8e, 0x77, 0x8d, 0x15, 0x19, 0x88, 0x5b, 0x60, 0x23, 0xd6, 0xda, 0x03, 0x72, 0xa6, 0x00, - 0xc7, 0x8b, 0xc3, 0xe1, 0x5c, 0xfe, 0xd2, 0xcd, 0xd6, 0x09, 0x54, 0x0a, 0xdc, 0x1e, 0x9d, 0x1c, 0xfc, 0x0f, 0xa0, - 0x19, 0x94, 0xc3, 0xbc, 0xde, 0xfe, 0xc1, 0x9c, 0xfc, 0xf4, 0x14, 0xff, 0x84, 0x87, 0xe8, 0xf4, 0xdb, 0xbd, 0xf9, - 0x83, 0xa2, 0xf2, 0x70, 0x50, 0x8b, 0xff, 0x9c, 0xf3, 0x0a, 0x7e, 0xe1, 0x9b, 0xc0, 0x6c, 0x32, 0xf5, 0x4e, 0xbe, - 0xc9, 0x73, 0xa6, 0x5e, 0xe3, 0x15, 0x93, 0xef, 0x70, 0x38, 0x17, 0xa3, 0x7a, 0x3b, 0x72, 0xa2, 0x9d, 0x72, 0x8c, - 0x83, 0xc1, 0x7f, 0x11, 0x6d, 0x13, 0x02, 0x0c, 0xe5, 0x12, 0xcd, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, - 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, - 0x88, 0x53, 0x9c, 0x80, 0x08, 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x04, 0xc1, 0x90, 0xaf, 0x25, 0xe0, - 0xae, 0xd7, 0xab, 0x31, 0xbe, 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, - 0x81, 0x67, 0xcb, 0xde, 0x44, 0xb9, 0xdb, 0xf0, 0xb4, 0x1f, 0x5b, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, - 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, - 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0x67, 0xd6, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0xc7, 0x0a, 0x1f, - 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x22, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, - 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, - 0xd3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0x0b, 0x3b, 0xb7, 0x63, 0xd7, 0xc5, 0x0f, 0xe2, 0x6d, 0x6d, 0x47, 0x7f, - 0xec, 0x20, 0xd2, 0x71, 0x4f, 0x2e, 0xd4, 0x97, 0x90, 0x4a, 0x2e, 0xd4, 0x0d, 0xc4, 0x2e, 0xd4, 0x78, 0xc7, 0x45, - 0xac, 0xf5, 0x37, 0x35, 0x0a, 0x56, 0x02, 0xce, 0xb4, 0x37, 0x60, 0xb0, 0x81, 0x75, 0xcb, 0x32, 0xf8, 0x1b, 0xae, - 0x69, 0x02, 0x37, 0x2c, 0xb2, 0xde, 0x1b, 0x6c, 0xa5, 0x37, 0xe0, 0x68, 0x99, 0x38, 0x97, 0x92, 0xa4, 0x6c, 0x91, - 0x71, 0xf5, 0x28, 0xa4, 0x6a, 0xba, 0xbf, 0x11, 0xf5, 0xbd, 0x10, 0x79, 0xb0, 0x4a, 0x59, 0x54, 0xac, 0x40, 0x66, - 0x0f, 0xfe, 0x1e, 0x32, 0x72, 0x94, 0x03, 0x47, 0xa1, 0x7f, 0x36, 0x81, 0xce, 0x23, 0x22, 0x9d, 0x47, 0x82, 0xad, - 0xd4, 0x43, 0x61, 0xe5, 0x05, 0x44, 0x07, 0xab, 0x23, 0xde, 0x54, 0x9e, 0x84, 0x8a, 0x4d, 0x99, 0xc8, 0xe3, 0xa0, - 0x96, 0x80, 0xb1, 0x82, 0x60, 0xce, 0x72, 0xe9, 0x82, 0x54, 0x35, 0x7a, 0x58, 0x64, 0xee, 0x1f, 0x04, 0xe5, 0xff, - 0x41, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x7f, 0x00, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x8c, 0x2e, 0x99, 0xb3, - 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, 0xc1, 0x74, 0x7b, 0x4a, 0xab, - 0xee, 0x61, 0xc3, 0x93, 0xd2, 0x43, 0xa5, 0xbe, 0x8d, 0x09, 0x2c, 0xab, 0x94, 0xe1, 0xdb, 0x09, 0x55, 0x27, 0x06, - 0x15, 0xeb, 0x86, 0x2d, 0xe1, 0x10, 0x8b, 0x49, 0x63, 0x9d, 0x0d, 0x78, 0xc4, 0x12, 0xf8, 0x67, 0xc3, 0xc7, 0x6c, - 0xc9, 0xa3, 0xc9, 0xe6, 0x6a, 0xd9, 0xef, 0x97, 0x5e, 0xe8, 0xd5, 0xb3, 0xec, 0x87, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, - 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x07, 0x78, 0xed, 0x07, 0x1e, - 0xa9, 0x25, 0x95, 0x5c, 0x65, 0xb0, 0xbf, 0x0f, 0x78, 0xe4, 0xb3, 0xce, 0x4f, 0xcb, 0xa6, 0x4b, 0xf7, 0x33, 0xab, - 0x03, 0x22, 0xdd, 0x01, 0x36, 0xde, 0x36, 0xe8, 0xc8, 0xbf, 0xdd, 0x21, 0xa5, 0x6e, 0x32, 0x00, 0xbb, 0xd1, 0x00, - 0x87, 0x4c, 0xf5, 0x52, 0x64, 0xf5, 0x52, 0xa6, 0x7a, 0x49, 0x56, 0x2e, 0xc1, 0x42, 0x62, 0xaa, 0xdc, 0x46, 0x56, - 0x6e, 0xd9, 0x70, 0x3d, 0x1c, 0x6c, 0xad, 0xb8, 0x6c, 0x6e, 0xe1, 0xbe, 0xb0, 0xa2, 0xc0, 0xff, 0x1b, 0xb6, 0x60, - 0x77, 0xf2, 0x18, 0xb8, 0x46, 0xc7, 0xa4, 0xc8, 0xab, 0xd8, 0x1d, 0xbb, 0x01, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, - 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, 0x8d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x6e, - 0x0f, 0x87, 0x6b, 0xcf, 0x67, 0xf7, 0xf8, 0xe3, 0xfc, 0xf6, 0x70, 0xd8, 0x79, 0x46, 0xbd, 0xf7, 0x86, 0x27, 0xec, - 0x11, 0x4f, 0x26, 0x6f, 0xae, 0x78, 0x3c, 0x19, 0x0c, 0xde, 0xf8, 0x0b, 0x5e, 0xcf, 0xde, 0x80, 0x76, 0xe0, 0x7c, - 0x21, 0x75, 0xcd, 0xde, 0x0d, 0xcf, 0xbc, 0x05, 0x8e, 0xcd, 0x0d, 0x1c, 0xbd, 0xfd, 0xbe, 0x77, 0xcb, 0x23, 0xef, - 0x86, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0x37, 0xc1, - 0x23, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x1b, 0xd5, - 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x88, 0xbf, 0x61, 0x77, 0xdc, 0xb0, 0xcd, - 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x50, 0xea, 0xda, 0x82, 0x64, 0x6e, 0x5d, 0xf9, 0x10, 0x38, 0x1c, 0x90, - 0x9f, 0x6e, 0x11, 0x07, 0xa1, 0x75, 0x93, 0xd5, 0x5c, 0x51, 0xce, 0x85, 0x36, 0xca, 0xbc, 0x1c, 0x58, 0xcc, 0x52, - 0x0a, 0x8d, 0x05, 0x00, 0x82, 0x49, 0xa1, 0xb5, 0xf7, 0x32, 0x80, 0x9c, 0xa0, 0xe1, 0x8f, 0xcd, 0x55, 0x49, 0xd6, - 0xb2, 0x25, 0x21, 0xca, 0x76, 0x3d, 0xbc, 0x44, 0xc8, 0xb4, 0x7e, 0xff, 0x9c, 0x48, 0xd6, 0x26, 0xd5, 0x55, 0x8d, - 0x96, 0x80, 0x8a, 0x2c, 0x01, 0x13, 0xbf, 0xd2, 0x7c, 0x02, 0xf0, 0xa4, 0xe3, 0x41, 0xf5, 0x03, 0xaf, 0x99, 0x20, - 0xb2, 0x8d, 0xca, 0x9f, 0x14, 0x4f, 0x91, 0x8c, 0xa0, 0xf8, 0xa1, 0x56, 0x19, 0x0b, 0xc3, 0x3c, 0x50, 0x40, 0xde, - 0xbd, 0x3b, 0xf5, 0x2d, 0xda, 0x9a, 0x8e, 0x3d, 0x5b, 0xab, 0x50, 0x0b, 0x35, 0x85, 0x4b, 0x0e, 0xd1, 0x15, 0x68, - 0xa0, 0x88, 0x64, 0x3c, 0x79, 0x3d, 0xb8, 0x9c, 0x44, 0x57, 0x5c, 0xa0, 0x33, 0xbe, 0xbe, 0xe9, 0xa6, 0xb3, 0xe8, - 0x87, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, 0xf0, 0xf5, - 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0xfe, 0x81, 0x2a, 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x87, 0x4a, 0xee, 0x7b, 0x40, 0x5a, - 0xcb, 0x4b, 0x2e, 0xdf, 0x8f, 0x10, 0x63, 0xc4, 0x0f, 0xbc, 0x92, 0x47, 0x2c, 0x54, 0x53, 0xb8, 0xe6, 0x11, 0x82, - 0xbc, 0x65, 0x3a, 0xf8, 0x5b, 0x4f, 0x9c, 0xee, 0x4f, 0x94, 0x76, 0xf1, 0x85, 0xc5, 0xb4, 0x72, 0xa4, 0x1b, 0x90, - 0x83, 0x0d, 0xd3, 0x45, 0x41, 0xb6, 0x29, 0x8d, 0xa0, 0x8d, 0x96, 0x03, 0x1b, 0x4e, 0xa5, 0x36, 0x9c, 0xb9, 0x86, - 0xe0, 0x3e, 0x3f, 0x4f, 0x47, 0x0b, 0xf8, 0x90, 0xea, 0xf6, 0x12, 0x3f, 0x0f, 0x1b, 0x2d, 0x90, 0xd9, 0x11, 0x9f, - 0xd9, 0x44, 0xd2, 0x49, 0x9d, 0x2b, 0x60, 0xb7, 0xb3, 0x6b, 0x90, 0x23, 0x66, 0xee, 0x2b, 0x54, 0xdf, 0xa2, 0x01, - 0x57, 0xc6, 0xda, 0xd7, 0x24, 0x63, 0xe1, 0x55, 0x39, 0x0d, 0x07, 0x00, 0x43, 0x97, 0xd1, 0xd7, 0x96, 0x9b, 0x2c, - 0x7b, 0x5d, 0x40, 0x10, 0x44, 0x49, 0x3c, 0x3e, 0xe0, 0x7d, 0x59, 0x0d, 0x35, 0x4a, 0x3e, 0x96, 0x1d, 0xc3, 0xd7, - 0x4b, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, 0x1f, 0x19, 0xcf, - 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x60, 0x69, 0xe6, 0x8b, 0x85, 0xbf, 0xd8, 0x39, 0x89, 0x88, 0x82, 0xc0, 0x8e, 0x84, - 0x07, 0x91, 0xfa, 0x51, 0xe5, 0xe9, 0x4e, 0xf5, 0xd9, 0x7e, 0x61, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, - 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, - 0x9d, 0xc6, 0x36, 0x3c, 0x36, 0x62, 0xd9, 0xd2, 0x5b, 0xb3, 0x5b, 0xb6, 0x62, 0x37, 0xaa, 0x4e, 0x0b, 0x1e, 0x4e, - 0x87, 0x97, 0x01, 0xae, 0xbe, 0xf5, 0x39, 0xe7, 0xb7, 0x74, 0x82, 0xad, 0x07, 0x3c, 0x9a, 0x88, 0xd9, 0xfa, 0x87, - 0x48, 0x2d, 0x9e, 0xf5, 0x90, 0x2f, 0x68, 0xfd, 0x89, 0xd9, 0xad, 0x49, 0xbe, 0x1d, 0xf0, 0xc5, 0x64, 0xfd, 0x43, - 0x04, 0xaf, 0xfe, 0x00, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0x1f, 0x22, 0x1c, 0xb3, 0xdb, 0x1f, 0x22, 0x1a, 0xb5, - 0x95, 0xdc, 0x97, 0x6e, 0x1a, 0x10, 0x56, 0x6e, 0x58, 0x0c, 0xaf, 0x81, 0x78, 0xa6, 0x8d, 0xa4, 0x6b, 0x69, 0xe8, - 0x8d, 0x79, 0x38, 0x8d, 0x83, 0x35, 0xb5, 0x42, 0x9e, 0x19, 0x62, 0x16, 0xff, 0x10, 0xcd, 0xd9, 0x0a, 0x2b, 0xb2, - 0xe1, 0xf1, 0xe0, 0x72, 0xb2, 0xb9, 0xe2, 0x6b, 0x20, 0x3f, 0x9b, 0x6c, 0xcc, 0x16, 0x75, 0xc3, 0xc5, 0x6c, 0xf3, - 0x43, 0x34, 0x9f, 0xac, 0xa0, 0x67, 0xed, 0x01, 0xf3, 0x5e, 0x82, 0x08, 0x25, 0x21, 0x35, 0xe5, 0xa6, 0xd7, 0x63, - 0xeb, 0x71, 0x70, 0xcb, 0xd6, 0x97, 0xc1, 0x0d, 0x5b, 0x8f, 0x81, 0x88, 0x83, 0xfa, 0xdd, 0xdb, 0xc0, 0xe2, 0x8b, - 0xd8, 0xfa, 0xd2, 0xa4, 0x6d, 0x7e, 0x88, 0x98, 0x3b, 0x38, 0x0d, 0x5c, 0xb0, 0xd6, 0x99, 0xb7, 0x62, 0x70, 0x09, - 0x59, 0x7a, 0x31, 0xdb, 0x0c, 0x2f, 0xd9, 0x7a, 0x84, 0x53, 0x3d, 0xf1, 0xd9, 0x2d, 0xbf, 0x61, 0x09, 0x5f, 0x35, - 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, 0x0a, 0x65, 0xb1, 0x30, 0x2a, 0xf7, 0x2d, 0x38, 0xa0, - 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0xeb, 0x70, 0xfd, 0x51, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, 0x60, 0xfa, - 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0xbf, 0x17, 0x69, 0xee, 0x16, 0xae, 0x53, - 0x98, 0x15, 0x05, 0xaa, 0x9f, 0x92, 0xd2, 0xc0, 0x42, 0x25, 0x32, 0x95, 0x82, 0x5f, 0xd6, 0x4e, 0xbb, 0xce, 0x8e, - 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, - 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, - 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xdd, 0x66, 0x0e, 0xd2, - 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0xb6, 0x86, 0x47, 0x55, 0xac, 0xdc, 0x9b, 0x3c, 0x47, - 0x38, 0xa3, 0x4b, 0x99, 0x00, 0xb8, 0xde, 0x2f, 0xc2, 0x5a, 0xe1, 0x15, 0x35, 0x8b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, - 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, - 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, 0x0b, 0x40, 0x4d, 0x3f, 0xd6, 0x62, 0x5d, 0x05, 0xa5, - 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, 0x26, 0x4a, 0xe4, 0xfc, 0x58, 0x94, 0x62, 0x59, 0x8a, - 0x2a, 0x69, 0x37, 0x14, 0x3c, 0x22, 0xdc, 0x06, 0x8d, 0x99, 0xdb, 0x13, 0x5d, 0xb4, 0x22, 0x94, 0x63, 0xb3, 0x8e, - 0x91, 0x46, 0x99, 0x9d, 0xec, 0x3a, 0x59, 0x68, 0xbf, 0xaf, 0x72, 0xc8, 0x3a, 0x60, 0x8d, 0xe4, 0xeb, 0x35, 0x87, - 0x6e, 0x1b, 0xe5, 0xc5, 0xbd, 0xe7, 0x2b, 0x38, 0xcd, 0xf1, 0xc4, 0xee, 0x7a, 0xdd, 0x29, 0x12, 0xf1, 0x0a, 0x27, - 0x55, 0x3e, 0x92, 0x85, 0xe3, 0xce, 0x9d, 0xd6, 0x62, 0x55, 0xb9, 0xac, 0xa7, 0x16, 0x47, 0x04, 0x3e, 0x95, 0x47, - 0x7b, 0xa1, 0x6d, 0x51, 0x2c, 0x84, 0xd1, 0xa3, 0x13, 0x7e, 0x52, 0x02, 0xeb, 0xeb, 0x70, 0x58, 0xfa, 0x11, 0x47, - 0xbf, 0xd3, 0x68, 0xb4, 0x20, 0xa4, 0xe1, 0xa9, 0x17, 0x8d, 0x16, 0x75, 0x51, 0x87, 0xd9, 0xd3, 0x5c, 0x0f, 0x14, - 0x86, 0x11, 0xa8, 0x1f, 0x5c, 0x65, 0xf0, 0x59, 0x84, 0xa8, 0x79, 0x60, 0x9a, 0x0d, 0xe1, 0xa8, 0x0b, 0x3c, 0xb4, - 0x82, 0x16, 0x33, 0xf3, 0x51, 0x88, 0xe1, 0x43, 0xba, 0x38, 0x7f, 0x42, 0x56, 0x3e, 0xc0, 0xee, 0xd0, 0x5d, 0x28, - 0xe7, 0x4c, 0xc5, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, 0x8c, 0x8e, - 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x96, 0xab, 0x09, 0x43, 0xe1, 0x13, 0x03, 0xdd, 0xfc, 0xc6, 0x6f, - 0xcf, 0x5b, 0x30, 0xb2, 0x4b, 0x52, 0xbc, 0xd6, 0x0c, 0xf7, 0x1b, 0x70, 0x3b, 0x02, 0xca, 0x9a, 0xea, 0x98, 0x64, - 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x7b, 0x59, 0x14, 0x38, 0x80, 0xab, 0x99, - 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0xf6, 0xaa, 0xea, 0x90, 0xac, 0x9a, 0x1f, 0xcc, 0xe6, - 0x4d, 0xc3, 0xc4, 0x88, 0x20, 0xba, 0x08, 0x27, 0x98, 0x5e, 0x91, 0xbe, 0x56, 0x72, 0x3a, 0x5a, 0x75, 0xb4, 0x96, - 0x98, 0x98, 0x2b, 0x8a, 0xbf, 0x06, 0x3c, 0x6e, 0xf0, 0xea, 0x24, 0x4d, 0x27, 0xaa, 0x47, 0x8f, 0x5f, 0xa7, 0xe9, - 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7e, 0x41, 0x11, 0x17, 0x35, 0xb8, 0xf2, 0x4e, - 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, 0x0e, 0x5c, - 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x44, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xcc, 0x59, 0x35, 0x5a, 0xa8, 0xcc, 0x08, 0xed, - 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xe3, 0x3d, 0xba, 0xab, 0xce, 0x32, 0x93, - 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xad, 0x0e, 0x90, 0x51, 0x7b, 0xed, 0x77, 0x9d, - 0xe5, 0xab, 0x9b, 0xad, 0xa1, 0xa8, 0xd4, 0x4a, 0x52, 0x1c, 0x64, 0xb8, 0x6e, 0x2b, 0x1f, 0x2e, 0x2e, 0xa0, 0x67, - 0x8c, 0x44, 0xe6, 0xf9, 0x13, 0xf9, 0x12, 0x9c, 0x33, 0xce, 0x0a, 0x81, 0x09, 0x63, 0xf5, 0xae, 0xb5, 0x54, 0x1a, - 0x52, 0x8c, 0x1d, 0x8d, 0xb2, 0xac, 0xb2, 0x74, 0x99, 0xad, 0x25, 0x6c, 0x59, 0x45, 0x6e, 0x61, 0xb7, 0x99, 0xac, - 0xe6, 0xbb, 0x8a, 0x3b, 0x28, 0xdf, 0x6c, 0x95, 0xf1, 0xbd, 0x44, 0xf6, 0x6e, 0x03, 0x25, 0x3c, 0x1d, 0xfd, 0x05, - 0xe9, 0xb7, 0x19, 0xc6, 0x29, 0xb7, 0x95, 0xb4, 0x00, 0xa7, 0x7f, 0x38, 0xbc, 0xab, 0x30, 0x68, 0x70, 0x84, 0x71, - 0x64, 0xfd, 0xfe, 0xa2, 0xf2, 0x6a, 0x4c, 0xd4, 0xf1, 0x59, 0xfd, 0x7e, 0x45, 0x0f, 0xa7, 0xd5, 0x68, 0x95, 0x6e, - 0x91, 0x9d, 0xd0, 0xc6, 0xca, 0x0f, 0x6a, 0x05, 0xcc, 0xde, 0xfa, 0x7c, 0x3a, 0x00, 0x1d, 0x0b, 0x90, 0x68, 0x36, - 0x13, 0x89, 0x39, 0xe9, 0x9e, 0x84, 0xc7, 0x07, 0x16, 0x38, 0xc0, 0x54, 0xfc, 0x5f, 0xc2, 0x9b, 0x81, 0x0d, 0x1a, - 0x25, 0xfa, 0x1a, 0x5d, 0xd5, 0xe6, 0x46, 0xc7, 0x4b, 0x4f, 0x21, 0x91, 0x15, 0xac, 0x9a, 0xfb, 0x72, 0x03, 0xa7, - 0x3d, 0xd4, 0x1c, 0x2a, 0x4b, 0xf0, 0xb7, 0x5f, 0xe6, 0x87, 0xc3, 0x2a, 0x83, 0xc2, 0x76, 0x6b, 0xa1, 0xbd, 0x31, - 0x4b, 0x35, 0x54, 0x84, 0x83, 0xce, 0x57, 0x62, 0x56, 0x8f, 0xe8, 0xef, 0xf9, 0xe1, 0xb0, 0x22, 0x30, 0xe0, 0xb0, - 0x94, 0x99, 0x68, 0xa1, 0x58, 0x5a, 0x67, 0x33, 0xaa, 0x03, 0x0f, 0x4c, 0xcc, 0x59, 0xb8, 0x03, 0xd0, 0x26, 0xb5, - 0x0a, 0xf4, 0x2a, 0xa2, 0x9f, 0xb8, 0x5f, 0xdb, 0xaf, 0xd7, 0x23, 0xb3, 0x74, 0xe4, 0xc6, 0x58, 0x00, 0x70, 0xe0, - 0x79, 0x4d, 0xf2, 0x9c, 0x7c, 0x0d, 0xed, 0x9e, 0x5c, 0xc8, 0x9f, 0xa0, 0x6c, 0xe1, 0xb9, 0x6a, 0x5a, 0x59, 0xac, - 0xb8, 0xaa, 0x5e, 0x5d, 0xf0, 0xca, 0x64, 0x5a, 0xa5, 0x95, 0xa8, 0x94, 0x60, 0x40, 0x5d, 0xe2, 0xb5, 0xa6, 0x19, - 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x7e, 0x69, 0x1c, 0x3e, 0xed, - 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0x2b, 0x1f, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, 0xc5, 0xc4, 0xee, - 0xd0, 0xbc, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, 0x01, 0x2f, 0x1e, - 0xea, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x2a, 0x26, 0xc0, 0x0f, 0x4a, - 0xad, 0xe9, 0xbd, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, 0xe7, 0xe3, 0xf9, - 0xa5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x79, 0xab, 0x7f, 0x98, 0xea, 0x5b, 0xe8, 0x4e, 0xd0, - 0x67, 0xe8, 0xaa, 0xea, 0xae, 0xc4, 0x16, 0x86, 0x7a, 0x62, 0x91, 0x17, 0xf2, 0xa4, 0x35, 0x76, 0x1c, 0xec, 0x0d, - 0x70, 0xe2, 0x97, 0x87, 0x83, 0xb8, 0xca, 0x7d, 0x76, 0xde, 0x35, 0xb2, 0x72, 0x00, 0x2b, 0x88, 0x82, 0x71, 0x6b, - 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xd5, 0xf8, 0xf8, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0xe4, 0x3f, 0x3c, 0x01, - 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7a, 0x39, 0x7d, 0x32, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, 0x31, 0x5f, 0x5d, - 0x32, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, 0xe6, 0x3e, 0x4c, - 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, 0x5d, 0x41, 0xba, - 0xe7, 0x11, 0xe9, 0xe5, 0x5e, 0x3a, 0xdd, 0xef, 0x4b, 0x01, 0x96, 0xfa, 0x52, 0x7c, 0x06, 0x85, 0x45, 0xe3, 0x1b, - 0x01, 0xda, 0x1a, 0xaa, 0x69, 0xaf, 0x14, 0x55, 0x2f, 0xe8, 0x95, 0xe2, 0x73, 0x4f, 0x0f, 0x95, 0xf9, 0xb2, 0x74, - 0xf4, 0x3f, 0xa1, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xe2, 0x68, 0xe3, 0x53, 0xbd, - 0x8a, 0x9b, 0x3e, 0xaf, 0xad, 0x65, 0x4e, 0x08, 0x9b, 0xee, 0x25, 0x40, 0x45, 0x5e, 0x09, 0x8f, 0x60, 0xf9, 0xe5, - 0x0f, 0x79, 0xba, 0x42, 0xb4, 0x8e, 0x7b, 0x96, 0xb9, 0x34, 0xf6, 0x2f, 0x0d, 0xa6, 0xaf, 0x6f, 0xb7, 0x45, 0x7e, - 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0xb7, 0xe1, 0x4a, 0xa0, 0xc0, 0xa1, 0x44, 0x62, 0x9b, 0x2a, 0x14, 0xf1, - 0x20, 0xe9, 0xd3, 0x45, 0xeb, 0xd3, 0x00, 0x53, 0x6b, 0x39, 0x30, 0x87, 0x70, 0x15, 0x17, 0x3e, 0x7a, 0xfa, 0x16, - 0xb3, 0x70, 0x3e, 0xf1, 0x3e, 0x78, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x38, 0xcc, 0xaa, 0xb9, - 0xef, 0xd0, 0x47, 0x7a, 0xa8, 0x72, 0x41, 0xd9, 0x1b, 0x63, 0x12, 0x81, 0xd2, 0x18, 0xef, 0xe3, 0xe0, 0x38, 0xef, - 0xd3, 0x00, 0x52, 0xfb, 0xc4, 0x3b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0x55, 0x7c, 0x9b, 0xa1, - 0x5c, 0x77, 0x4a, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x99, 0x57, 0xa3, 0x47, - 0x55, 0x12, 0x96, 0x22, 0xee, 0xf7, 0x77, 0x99, 0x67, 0xd8, 0x1b, 0x1e, 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, - 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, - 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, 0xfd, 0x06, 0xc7, 0x7c, 0x70, 0x1f, 0x71, - 0xbc, 0xc3, 0x59, 0x68, 0x09, 0x79, 0x72, 0xc7, 0x20, 0x4d, 0x63, 0x69, 0x04, 0x9c, 0x88, 0x64, 0x1b, 0x4b, 0xe1, - 0x08, 0x20, 0x20, 0xd0, 0x4d, 0x99, 0x61, 0x4c, 0x07, 0x23, 0xcf, 0xa3, 0x9e, 0xf1, 0x5e, 0x85, 0xa7, 0x90, 0x26, - 0xdb, 0xd7, 0xf3, 0xf7, 0x46, 0x90, 0x95, 0x5b, 0xce, 0xf1, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, 0x79, 0x8a, 0x59, - 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0xe7, 0x28, 0xbd, 0x65, 0x3e, 0x59, 0x45, 0xd2, 0xa5, 0xb7, - 0xe9, 0xf7, 0xe3, 0x91, 0x3a, 0xd4, 0xfc, 0x7d, 0x3c, 0x92, 0x67, 0xd8, 0x86, 0x25, 0x2c, 0xb4, 0x0a, 0xc6, 0x00, - 0x92, 0xd8, 0x88, 0x68, 0x30, 0xda, 0x9b, 0xc3, 0xe1, 0x7c, 0x63, 0xce, 0x92, 0x3d, 0xb8, 0xbe, 0xf2, 0xc4, 0xbc, - 0x03, 0x5f, 0xe6, 0x31, 0x41, 0xc4, 0x66, 0xde, 0x86, 0xd5, 0xe0, 0xc1, 0x0e, 0xae, 0x8f, 0xd8, 0xa2, 0x58, 0xeb, - 0x58, 0x2a, 0xeb, 0xe0, 0xb4, 0x8e, 0x4d, 0x33, 0x52, 0x8a, 0xec, 0x73, 0xec, 0xef, 0xdd, 0xe0, 0xea, 0xda, 0x18, - 0xd4, 0x1a, 0x77, 0x98, 0x3b, 0xa7, 0x02, 0xea, 0x31, 0x5d, 0x41, 0xf5, 0xac, 0x22, 0x5f, 0x7e, 0x6b, 0xe7, 0x80, - 0xa0, 0x11, 0x08, 0x5c, 0x34, 0xfe, 0x77, 0x5d, 0xca, 0x79, 0x17, 0x10, 0xe2, 0xbb, 0x14, 0xf4, 0xe9, 0x0c, 0x36, - 0xb1, 0xf9, 0x04, 0x62, 0xd1, 0x74, 0x9f, 0x6b, 0xcd, 0x7c, 0x31, 0xa2, 0x9d, 0x59, 0x77, 0x8b, 0xdc, 0x6a, 0x21, - 0x92, 0xd1, 0xb3, 0xcd, 0x84, 0xdb, 0x0e, 0xe5, 0x8c, 0x04, 0x4c, 0xd0, 0xda, 0x4a, 0xc9, 0xe7, 0xba, 0xd7, 0x09, - 0xda, 0x03, 0x49, 0xeb, 0xfe, 0xcd, 0xa2, 0x33, 0x4a, 0x4e, 0xae, 0x37, 0x39, 0x83, 0x14, 0x2c, 0xd8, 0x5e, 0xe6, - 0x84, 0x1b, 0xe0, 0x23, 0x9b, 0x25, 0xa7, 0x69, 0x90, 0xc7, 0x42, 0xd7, 0xec, 0x7d, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, - 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, - 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, - 0x98, 0x07, 0xee, 0x6c, 0xe3, 0x9a, 0xc0, 0x40, 0xa7, 0xf6, 0xb5, 0x28, 0xe7, 0x58, 0x45, 0xf4, 0x3e, 0x7f, 0x5f, - 0xd9, 0xd3, 0x07, 0x11, 0x36, 0x2a, 0xd0, 0x58, 0x4a, 0x8c, 0x8d, 0x1c, 0xff, 0x96, 0x28, 0x1b, 0x32, 0x04, 0x84, - 0x90, 0x36, 0x72, 0xfa, 0x61, 0x07, 0xad, 0x64, 0xda, 0xff, 0x93, 0xc4, 0x6f, 0x83, 0xbd, 0x9c, 0xfa, 0x53, 0x8f, - 0x78, 0xbc, 0xd6, 0xe8, 0x31, 0x25, 0xdd, 0x06, 0x79, 0xaa, 0x3c, 0x05, 0xc9, 0x84, 0xb1, 0x84, 0x60, 0x51, 0x2e, - 0x78, 0xce, 0x2b, 0x2e, 0xe1, 0x3e, 0x6a, 0x59, 0x11, 0xa1, 0x2a, 0x91, 0xd3, 0xe7, 0x2b, 0xe0, 0x99, 0x80, 0x40, - 0xc7, 0x18, 0x69, 0x54, 0xc1, 0x97, 0xc0, 0x58, 0x48, 0xca, 0x4e, 0x33, 0x12, 0x5c, 0x76, 0x3f, 0x22, 0x51, 0xea, - 0x0b, 0x52, 0x92, 0xbe, 0x11, 0x35, 0x5e, 0x89, 0x55, 0x44, 0x02, 0x19, 0x6a, 0x88, 0x58, 0x55, 0x4f, 0xdd, 0xab, - 0x62, 0x32, 0x18, 0x54, 0xbe, 0x9c, 0x9e, 0x78, 0x43, 0x43, 0xe5, 0x5d, 0x57, 0xb4, 0xd3, 0x33, 0xad, 0x94, 0xb7, - 0x90, 0x96, 0xa0, 0x69, 0x18, 0x69, 0x0e, 0xa5, 0xae, 0xa4, 0xbb, 0x31, 0x88, 0x2f, 0x99, 0xe8, 0xd9, 0x4e, 0xed, - 0x28, 0x6d, 0x49, 0x7b, 0x08, 0xe9, 0xb9, 0x4b, 0x3e, 0x66, 0x21, 0x57, 0x77, 0xca, 0x49, 0x79, 0x15, 0xa2, 0x93, - 0xfb, 0x1e, 0x43, 0x22, 0xd0, 0xe7, 0x1c, 0xc3, 0xba, 0x68, 0xa8, 0x73, 0x58, 0x21, 0x66, 0x0b, 0x25, 0xcc, 0x97, - 0x8c, 0xa7, 0x92, 0x41, 0x03, 0x20, 0x03, 0x3e, 0x7b, 0x19, 0x58, 0xfe, 0x0a, 0xe2, 0x47, 0x1b, 0x1f, 0x0e, 0x5f, - 0x6a, 0x0a, 0xb1, 0xfd, 0x02, 0x9b, 0x21, 0x3c, 0xaa, 0x07, 0x3c, 0xf3, 0x4d, 0x9c, 0xa0, 0xe5, 0x88, 0x93, 0xd9, - 0xd1, 0x44, 0xf6, 0xaa, 0x87, 0x70, 0x2a, 0x2b, 0x50, 0x47, 0x59, 0x67, 0x25, 0xfc, 0x08, 0x53, 0xdd, 0x4a, 0xac, - 0x05, 0xda, 0x5c, 0xad, 0x58, 0x0b, 0xe0, 0xc0, 0xcf, 0x21, 0x78, 0x22, 0x9f, 0x83, 0x8b, 0x41, 0x01, 0x3e, 0x07, - 0xc0, 0x8b, 0xdc, 0xd1, 0xb9, 0x3f, 0x3d, 0xb0, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, - 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x4e, 0x98, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x8f, - 0xf6, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0x87, 0xe5, 0x35, 0x60, 0x7a, 0x05, 0x91, - 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x6e, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x11, 0xa9, 0xae, 0x85, 0xb4, - 0x91, 0x4f, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfd, 0xe9, 0x6f, 0xcf, 0x3e, 0xbd, 0xfa, 0xf5, 0xa7, 0xc5, 0xab, 0xb7, - 0x2f, 0x5f, 0xbd, 0x7d, 0xf5, 0xe9, 0x77, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xfd, 0xbb, 0x8f, 0xaf, 0x9c, 0x0c, - 0x36, 0xcc, 0x58, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0x92, 0x39, 0x66, 0x62, 0x8e, - 0xb1, 0x77, 0x02, 0x93, 0x2d, 0xf0, 0x1d, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x37, 0xe0, - 0x22, 0x93, 0xe6, 0xb7, 0xbf, 0x12, 0xc4, 0x3e, 0xad, 0xa4, 0xdc, 0x57, 0xdb, 0x9a, 0xe7, 0xdb, 0xfb, 0xbd, 0x84, - 0xf3, 0x9f, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0xe7, 0xf0, 0xc7, 0x95, 0xb6, 0xa4, 0xc9, 0x2c, 0xda, 0xcf, 0x18, - 0x82, 0x2e, 0x0d, 0x3e, 0x88, 0x3d, 0xf2, 0x52, 0x9f, 0x2c, 0x24, 0x70, 0x47, 0x0c, 0x9f, 0x56, 0x04, 0xbd, 0x62, - 0x44, 0x71, 0xc9, 0x15, 0x2a, 0xa5, 0xe4, 0xdf, 0x28, 0xbb, 0xa8, 0x90, 0xb3, 0x82, 0xdd, 0x29, 0x72, 0x64, 0xfc, - 0x20, 0x98, 0xf8, 0x72, 0x70, 0xff, 0x25, 0xde, 0xe1, 0x4c, 0x71, 0x24, 0x27, 0xfc, 0x63, 0x86, 0x81, 0xfd, 0x39, - 0xf8, 0xbc, 0x3a, 0xcc, 0xcb, 0x1b, 0x7d, 0xca, 0x2d, 0xf9, 0x78, 0xb2, 0xbc, 0x02, 0x83, 0xfd, 0x52, 0x35, 0x77, - 0xcd, 0xeb, 0xd9, 0x72, 0xce, 0xf6, 0xb3, 0x68, 0x1e, 0xdc, 0xb2, 0x59, 0x36, 0x0f, 0x56, 0x0d, 0x5f, 0xb3, 0x1b, - 0xbe, 0xb6, 0xaa, 0xb6, 0xb6, 0xab, 0x36, 0xd9, 0xf0, 0x1b, 0x90, 0x10, 0xae, 0xc1, 0x2f, 0x39, 0x61, 0xb7, 0x3e, - 0xdb, 0x80, 0x44, 0xbb, 0x62, 0x1b, 0xb8, 0x88, 0xad, 0xf9, 0xab, 0xca, 0xdb, 0xb0, 0x92, 0x9d, 0x8f, 0x59, 0x8e, - 0xf3, 0xcf, 0x87, 0x07, 0xb4, 0x17, 0xea, 0x67, 0x97, 0xea, 0xd9, 0x44, 0xd9, 0xcd, 0x36, 0xa3, 0xc5, 0x5d, 0x5a, - 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x4d, 0x9c, 0xdf, 0xd3, 0xb6, - 0x5d, 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x9c, 0x3f, 0x85, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, - 0xfd, 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xfc, 0x52, 0x59, - 0xad, 0x34, 0x27, 0xa1, 0x6d, 0xc4, 0xaa, 0xe5, 0x48, 0xd5, 0x8c, 0x48, 0x1f, 0xa4, 0xe7, 0x7d, 0x8f, 0xa8, 0x06, - 0x7b, 0x32, 0xaf, 0x03, 0xfb, 0xf4, 0xae, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, - 0x78, 0xaf, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xa1, 0x0a, 0x38, 0x5f, 0xaf, 0x44, 0xbb, 0x13, 0x61, 0x57, - 0x2e, 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, - 0xce, 0x73, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xa5, 0x26, 0x13, 0x39, 0x28, 0x1f, - 0x0e, 0x05, 0xec, 0xa5, 0xc6, 0x4f, 0x13, 0x7e, 0xc2, 0xf2, 0xd6, 0xde, 0x9a, 0x52, 0x54, 0xd2, 0x00, 0x15, 0xf8, - 0x98, 0xc1, 0xff, 0xee, 0x0c, 0xb1, 0x60, 0x8a, 0x8e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x94, 0xad, - 0xd1, 0x4e, 0xc0, 0xa9, 0x8e, 0x93, 0x44, 0x38, 0xf5, 0x1e, 0x71, 0x51, 0xf7, 0x72, 0x88, 0xba, 0x61, 0x9f, 0x2a, - 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, 0x7b, 0x2b, 0x88, 0x20, 0x45, 0x36, 0xa2, 0x24, 0x8d, - 0x63, 0x91, 0xc3, 0xf6, 0xbe, 0x90, 0xfb, 0x7f, 0xbf, 0x0f, 0xe1, 0xa4, 0x55, 0x10, 0x97, 0x9e, 0x40, 0x44, 0x38, - 0x3a, 0xfc, 0x88, 0xf0, 0x44, 0xaa, 0x0a, 0xdf, 0xd7, 0x27, 0x6e, 0xcc, 0xee, 0x85, 0x39, 0xaa, 0xb7, 0x00, 0xc3, - 0x58, 0x6f, 0x2d, 0x42, 0x12, 0xad, 0x34, 0xa3, 0xad, 0x07, 0xc4, 0x88, 0x77, 0x6b, 0x8b, 0x0c, 0xc6, 0xda, 0x92, - 0x48, 0x00, 0xbf, 0x25, 0x21, 0x43, 0xdb, 0x46, 0x60, 0xc6, 0xf0, 0x76, 0x56, 0x5c, 0xba, 0x0e, 0xdb, 0x9c, 0xc3, - 0x17, 0xb2, 0xd0, 0xac, 0x23, 0x4a, 0x13, 0x84, 0xfc, 0x03, 0x4e, 0x16, 0x0a, 0xa3, 0x79, 0x71, 0x94, 0x4e, 0x12, - 0xeb, 0xbb, 0xae, 0x52, 0xc1, 0x66, 0xf3, 0x11, 0xf5, 0x65, 0x47, 0xc9, 0xd7, 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, - 0x44, 0x2d, 0x2a, 0xe7, 0x63, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xcd, 0x7a, 0x5d, 0x94, 0x75, 0xf5, 0x42, 0x44, 0x8a, - 0xde, 0x47, 0x3d, 0x7a, 0x24, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe5, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, - 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0xee, 0x65, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x03, 0xaf, 0x1c, 0xe5, - 0x97, 0x56, 0x9b, 0xf4, 0x2b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, - 0x62, 0x96, 0xe6, 0x7f, 0xe2, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x53, 0xe5, 0xd5, 0x72, 0x2d, 0x33, - 0xcd, 0xcd, 0x12, 0xc7, 0x8a, 0xc5, 0x45, 0xbd, 0xae, 0x44, 0x16, 0x08, 0x71, 0x84, 0x69, 0xac, 0xa7, 0xde, 0x28, - 0xad, 0xde, 0x23, 0xa1, 0xcc, 0x4f, 0xd8, 0xdb, 0xb1, 0xd7, 0x83, 0x2c, 0xc4, 0xb1, 0xe5, 0x60, 0xb3, 0xf5, 0x3e, - 0x95, 0xa9, 0x88, 0xcf, 0xea, 0xe2, 0x6c, 0x53, 0x89, 0xb3, 0x3a, 0x11, 0x67, 0x3f, 0x42, 0xce, 0x1f, 0xcf, 0xa8, - 0xe8, 0xb3, 0xfb, 0xb4, 0x4e, 0x8a, 0x4d, 0x4d, 0x4f, 0x5e, 0x62, 0x19, 0x3f, 0x9e, 0x11, 0x57, 0xcd, 0x19, 0x8d, - 0x64, 0x3c, 0x3a, 0x7b, 0x9f, 0x01, 0xc9, 0xeb, 0x59, 0xba, 0x82, 0xc1, 0x3b, 0x0b, 0xf3, 0xf8, 0xac, 0x14, 0xb7, - 0x60, 0x71, 0x2a, 0x3b, 0xdf, 0x83, 0x0c, 0xab, 0xf0, 0x4f, 0x71, 0x06, 0xd0, 0xae, 0x67, 0x69, 0x7d, 0x96, 0x56, - 0x67, 0x79, 0x51, 0x9f, 0x29, 0x29, 0x1c, 0xc2, 0xf8, 0xe1, 0x3d, 0x7d, 0x65, 0x97, 0xb7, 0x59, 0xdc, 0x65, 0x91, - 0x3f, 0x45, 0xaf, 0x22, 0x62, 0xd2, 0xa8, 0x84, 0xd7, 0xee, 0x6f, 0x9b, 0xfb, 0x87, 0xd7, 0x8d, 0xdd, 0xcf, 0xee, - 0x18, 0xd1, 0x05, 0xf5, 0x78, 0x25, 0x29, 0x15, 0x14, 0x10, 0x38, 0xd1, 0xac, 0xf1, 0xe0, 0x8e, 0x03, 0x5e, 0x0d, - 0x6c, 0xc9, 0xd6, 0x3e, 0x7f, 0x1a, 0xcb, 0x30, 0xed, 0x4d, 0x80, 0x7f, 0x95, 0xbd, 0xe9, 0x3a, 0x58, 0xe2, 0x7d, - 0x0b, 0xd9, 0x86, 0x5e, 0xbd, 0xe0, 0xcf, 0xbc, 0x5c, 0xfd, 0xcd, 0x7e, 0x07, 0x20, 0x0c, 0x88, 0x59, 0xf5, 0xd1, - 0xc4, 0xbd, 0xb3, 0xb2, 0xec, 0x9c, 0x2c, 0xbb, 0x1e, 0xfa, 0x35, 0x89, 0x51, 0x69, 0x65, 0x29, 0x9d, 0x2c, 0x25, - 0x64, 0x01, 0x9f, 0x18, 0x4d, 0x6d, 0x04, 0x10, 0xb6, 0xa3, 0x54, 0xbe, 0x50, 0x79, 0x11, 0x85, 0x73, 0x82, 0xe7, - 0x89, 0x18, 0xdd, 0x59, 0xc9, 0x80, 0xe1, 0x10, 0x82, 0x39, 0x68, 0x8b, 0xbd, 0xa1, 0x9b, 0x88, 0xbf, 0x5e, 0x16, - 0xe5, 0xab, 0x98, 0x7c, 0x0a, 0x76, 0x27, 0x1f, 0x97, 0xf0, 0xb8, 0x3c, 0xf9, 0x38, 0x44, 0x8f, 0x84, 0x93, 0x8f, - 0xc1, 0xf7, 0x48, 0xce, 0xeb, 0xae, 0xc7, 0x09, 0x72, 0x0b, 0xe9, 0xfe, 0x76, 0x4c, 0x02, 0x34, 0xaf, 0x61, 0x39, - 0x6a, 0x2a, 0xae, 0x99, 0x19, 0xe3, 0x79, 0xa3, 0xf7, 0xc7, 0x8e, 0xb7, 0x4c, 0xa1, 0x98, 0xc5, 0xbc, 0x86, 0xdf, - 0xb3, 0x2a, 0x50, 0x77, 0xbd, 0x4d, 0x72, 0xcb, 0xac, 0x9e, 0xa3, 0xdd, 0xf7, 0x5d, 0x9d, 0x08, 0x6a, 0x7f, 0x87, - 0x3d, 0xcf, 0xac, 0x77, 0x55, 0x0c, 0x5c, 0xaa, 0x64, 0x87, 0x4c, 0x55, 0xd3, 0x03, 0x95, 0xd2, 0xe0, 0xe9, 0xa5, - 0x75, 0xf9, 0x52, 0x69, 0x23, 0xcf, 0x34, 0xbf, 0x01, 0xbc, 0x98, 0xba, 0x2c, 0x76, 0xdf, 0xdc, 0x57, 0x70, 0x1b, - 0xef, 0xf7, 0xd7, 0x95, 0x67, 0x7e, 0xe2, 0x02, 0xb0, 0x37, 0x15, 0x5a, 0x27, 0x50, 0x6a, 0x58, 0x87, 0xd7, 0x89, - 0x88, 0xfe, 0x6c, 0x97, 0xeb, 0xcc, 0x75, 0xc0, 0x88, 0x22, 0x7e, 0x1b, 0x8f, 0xfe, 0x00, 0xc5, 0xb5, 0xb1, 0x07, - 0x84, 0x75, 0x48, 0xe8, 0x33, 0x02, 0x90, 0x7a, 0xf4, 0x51, 0xf2, 0x27, 0x68, 0x56, 0x34, 0x77, 0x4c, 0x7e, 0xae, - 0xaf, 0x94, 0xfe, 0x7e, 0x5d, 0x79, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0x54, 0x02, 0xe1, 0x15, 0x95, 0xac, - 0xc2, 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x9f, 0xb6, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0xc2, 0xef, - 0xf7, 0x2b, 0x80, 0x79, 0x91, 0xcd, 0xec, 0x3e, 0x0e, 0xa8, 0x52, 0xa2, 0x69, 0x9c, 0xcd, 0xf3, 0x7b, 0x7a, 0x53, - 0x76, 0xd0, 0xa9, 0x53, 0x05, 0x2e, 0xb8, 0x2a, 0x19, 0xaf, 0xac, 0x27, 0xf2, 0xf9, 0xcd, 0xcd, 0x26, 0xcd, 0xe2, - 0x77, 0xe5, 0x2f, 0x38, 0xb6, 0xba, 0x0e, 0x0f, 0x4c, 0x9d, 0xae, 0x9d, 0x47, 0x5a, 0x7b, 0x21, 0x20, 0xa2, 0x5d, - 0x43, 0xad, 0x17, 0x16, 0x7a, 0xa4, 0x27, 0xc2, 0x39, 0x49, 0xd4, 0xb4, 0x03, 0x2d, 0x8d, 0xd0, 0xd7, 0xd7, 0x9c, - 0xfe, 0xc2, 0x60, 0xed, 0xf3, 0x31, 0x03, 0xb2, 0x12, 0xfd, 0x58, 0x3d, 0x34, 0x36, 0x73, 0xe8, 0x59, 0xab, 0xf2, - 0xcc, 0xab, 0x0e, 0x07, 0xc4, 0x87, 0xd1, 0x5f, 0xf2, 0xfb, 0xfd, 0x17, 0x34, 0xff, 0x98, 0x50, 0xe3, 0x67, 0x9b, - 0x01, 0xba, 0xf6, 0x5d, 0x79, 0x20, 0xea, 0xb9, 0x56, 0x09, 0x42, 0xbc, 0x41, 0x4c, 0x34, 0x23, 0xe6, 0xe0, 0xb4, - 0x43, 0xcd, 0x3f, 0x49, 0x0d, 0x08, 0x51, 0xe2, 0x75, 0x4c, 0x59, 0x90, 0xd3, 0x26, 0x8e, 0xf4, 0xa3, 0x70, 0x22, - 0x3f, 0x88, 0xaa, 0xc8, 0xee, 0xe0, 0x82, 0xc1, 0xd4, 0x7b, 0xda, 0x2f, 0xd1, 0x6f, 0x09, 0x47, 0xce, 0xd1, 0xaa, - 0x10, 0x44, 0x4e, 0x08, 0x6b, 0x0d, 0x61, 0x82, 0xd8, 0x20, 0x5e, 0xf6, 0x5d, 0x92, 0xe1, 0x48, 0xc1, 0x65, 0x1d, - 0x3b, 0xc6, 0x5c, 0x1d, 0x55, 0xaf, 0x01, 0x8c, 0x57, 0x8e, 0xa0, 0xd9, 0x28, 0xb2, 0x4b, 0x88, 0x2a, 0x72, 0x3c, - 0x01, 0xb5, 0x83, 0xd2, 0xd8, 0x4c, 0xcf, 0xc7, 0x41, 0x3e, 0x5a, 0x54, 0xa8, 0x73, 0x62, 0x19, 0xaf, 0x01, 0x58, - 0x3b, 0x57, 0xfd, 0x3c, 0xab, 0xc1, 0x93, 0x86, 0xf8, 0x7c, 0x8c, 0xb6, 0x57, 0x36, 0x07, 0xd5, 0x76, 0x3a, 0x2b, - 0xaf, 0x98, 0x2e, 0x07, 0xc6, 0x7d, 0xc3, 0x2b, 0x8a, 0x33, 0xfc, 0xe0, 0xc1, 0x16, 0xe7, 0x4f, 0x37, 0xd4, 0x7e, - 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0xbb, 0x8e, 0x6c, 0xef, 0xb4, 0xc8, 0x68, 0xf2, - 0xd9, 0xcf, 0xdf, 0x97, 0xe9, 0x2a, 0x85, 0xfb, 0x92, 0x93, 0x45, 0x33, 0x0f, 0x81, 0xbd, 0x21, 0x86, 0xeb, 0xa3, - 0xc2, 0x23, 0xca, 0xfa, 0x7d, 0xf8, 0x7d, 0x95, 0x81, 0x29, 0x06, 0xae, 0x2b, 0x04, 0xe3, 0x21, 0x10, 0xc4, 0xc3, - 0x34, 0x3a, 0x19, 0xd4, 0xa0, 0x0d, 0xdf, 0x00, 0x64, 0x06, 0x78, 0x64, 0x2e, 0x3d, 0x02, 0xee, 0x02, 0xd7, 0x9e, - 0x8c, 0xc7, 0xfe, 0xc4, 0x34, 0x34, 0x6a, 0x4a, 0x33, 0x3d, 0x37, 0x7e, 0xd3, 0x51, 0x2d, 0xd7, 0xce, 0x7f, 0x7c, - 0xc9, 0x6f, 0xd0, 0x0b, 0x5a, 0x5e, 0xee, 0x23, 0x75, 0xb9, 0xcf, 0x28, 0x2e, 0x13, 0xc9, 0x61, 0x41, 0x2c, 0x4b, - 0x38, 0xf0, 0x18, 0x95, 0x2c, 0xb6, 0xf4, 0x58, 0x15, 0x2d, 0x5f, 0x94, 0x1b, 0xa4, 0x43, 0x27, 0x04, 0x4b, 0x54, - 0x10, 0x2c, 0x81, 0x71, 0x11, 0x6b, 0xbe, 0x19, 0xe4, 0x2c, 0x9e, 0x6d, 0xe6, 0x1c, 0x09, 0xeb, 0x92, 0xc3, 0xa1, - 0x90, 0x60, 0x33, 0xd9, 0x6c, 0x3d, 0x67, 0x6b, 0x9f, 0x81, 0x12, 0xa0, 0x94, 0x69, 0x82, 0xd2, 0xb4, 0x62, 0x2b, - 0x6e, 0x5a, 0x83, 0xd5, 0x6a, 0xca, 0x56, 0x35, 0x65, 0xe7, 0x34, 0xe5, 0xa8, 0x82, 0x92, 0x13, 0x4a, 0x51, 0x86, - 0x01, 0x8c, 0xd8, 0x24, 0xba, 0xca, 0xd0, 0xc7, 0x3b, 0xe1, 0x11, 0x54, 0x11, 0x91, 0x4f, 0x18, 0x42, 0x60, 0x22, - 0x8a, 0x0b, 0x55, 0x28, 0x06, 0xc8, 0x88, 0x04, 0x82, 0x89, 0x4a, 0x9d, 0x02, 0xf3, 0xd1, 0x54, 0x31, 0x6c, 0xda, - 0x13, 0xe5, 0x7b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0x1f, 0x62, 0x17, 0x84, 0xc8, 0xdd, 0xb8, 0x53, 0x3f, 0x23, 0xde, - 0xdb, 0x1d, 0x61, 0xfc, 0x64, 0xc7, 0x2d, 0xc2, 0x15, 0xc1, 0x96, 0x6a, 0x0e, 0xb1, 0x98, 0x57, 0x93, 0x04, 0xb5, - 0x2c, 0x89, 0xbf, 0xe1, 0xc9, 0x20, 0x67, 0x4b, 0xf0, 0xa0, 0x9d, 0xb3, 0x0c, 0xf0, 0x57, 0xac, 0x16, 0xfd, 0x5e, - 0x7b, 0x4b, 0x90, 0x9f, 0x36, 0x76, 0xa3, 0x30, 0x31, 0x82, 0x44, 0xdd, 0xae, 0x0c, 0xe4, 0x87, 0xf7, 0x38, 0x1d, - 0x8f, 0x3d, 0x65, 0xcc, 0xad, 0x4c, 0x2f, 0xd3, 0xb9, 0x92, 0x6f, 0xe4, 0x5e, 0xfa, 0xd0, 0x4b, 0xb0, 0x73, 0xc0, - 0x1b, 0x48, 0x1b, 0xf8, 0x11, 0xb6, 0x0b, 0xaf, 0x0d, 0x12, 0x66, 0x04, 0xd8, 0xe2, 0xf8, 0x18, 0x29, 0x81, 0x21, - 0x1c, 0x67, 0x29, 0x00, 0xd3, 0xe8, 0xcb, 0x6c, 0x65, 0x5f, 0x66, 0xb5, 0x66, 0x4b, 0xe5, 0x74, 0xef, 0xdc, 0xba, - 0x9d, 0xcf, 0x24, 0x00, 0x98, 0xd4, 0x39, 0x10, 0x67, 0x26, 0xd8, 0xa5, 0x49, 0x64, 0xf9, 0x10, 0xe6, 0xb7, 0xe2, - 0x65, 0x59, 0xac, 0x54, 0x57, 0xb4, 0x7d, 0x66, 0xf2, 0x19, 0xe9, 0x24, 0x54, 0x40, 0x41, 0x21, 0xd7, 0xfa, 0xf4, - 0x6d, 0xf8, 0x36, 0x28, 0x34, 0x30, 0x5b, 0x85, 0x7b, 0x9a, 0xac, 0x91, 0x7a, 0xa3, 0xea, 0xf7, 0xc9, 0x35, 0x90, - 0xea, 0xcc, 0xa1, 0x65, 0xcf, 0x2a, 0x0c, 0x10, 0x3b, 0xea, 0x33, 0x12, 0xea, 0x40, 0xea, 0x01, 0x43, 0x88, 0xb6, - 0xe9, 0xe3, 0x4f, 0x86, 0x44, 0x17, 0x60, 0x0b, 0xd1, 0x06, 0x7e, 0xfc, 0x09, 0xf6, 0x59, 0x10, 0x1e, 0xd3, 0xfc, - 0x0d, 0x24, 0x1d, 0x1b, 0x38, 0xad, 0x3e, 0x05, 0x1f, 0x24, 0x39, 0x98, 0xa8, 0x83, 0x97, 0xfb, 0x4b, 0xbf, 0x0f, - 0x5b, 0x76, 0x2e, 0xa5, 0x3a, 0x56, 0xea, 0x6d, 0x5b, 0xfb, 0x41, 0xb4, 0x05, 0x47, 0x16, 0xf1, 0xf7, 0x19, 0x22, - 0x82, 0x99, 0x41, 0x84, 0x5d, 0x0b, 0x75, 0xb7, 0xa7, 0xd4, 0xb2, 0xa8, 0xb7, 0x3d, 0xa5, 0xd4, 0x6d, 0x18, 0xbe, - 0x9b, 0x60, 0xa6, 0xb8, 0xe1, 0x6f, 0x32, 0x2f, 0xd4, 0x1b, 0x8f, 0x71, 0x8c, 0x5f, 0x7b, 0xfe, 0x7e, 0xc9, 0xab, - 0xd9, 0x46, 0x99, 0x30, 0x6f, 0xf9, 0x72, 0x16, 0xca, 0xae, 0x96, 0xc6, 0x9d, 0xcf, 0xde, 0x52, 0xcd, 0x07, 0xff, - 0x70, 0x48, 0x20, 0xde, 0x28, 0xbe, 0xba, 0x6d, 0xe4, 0xd6, 0x35, 0xd9, 0x5c, 0x95, 0x80, 0xfa, 0x7d, 0xbe, 0xc6, - 0xfd, 0x16, 0xeb, 0xdf, 0x3d, 0x0d, 0x32, 0x56, 0x33, 0x5c, 0x31, 0x85, 0x4f, 0x01, 0x60, 0x70, 0x38, 0x15, 0xa4, - 0x05, 0xde, 0xf0, 0x72, 0x78, 0x39, 0xd9, 0x90, 0x49, 0x77, 0xe3, 0x23, 0x77, 0x16, 0xa8, 0x7a, 0xbf, 0xa3, 0x38, - 0x69, 0x90, 0x68, 0xec, 0x35, 0xf8, 0x2c, 0xcb, 0x28, 0x17, 0x4d, 0xdc, 0x87, 0xe4, 0x2b, 0x3d, 0x80, 0xb9, 0x0a, - 0x25, 0x40, 0xf4, 0x1b, 0xcb, 0x62, 0x23, 0xda, 0x16, 0x1b, 0x58, 0x4a, 0xd5, 0x5c, 0xaf, 0xa6, 0xcf, 0x5e, 0x89, - 0xe6, 0x7d, 0x34, 0xe3, 0x94, 0x46, 0x03, 0x8e, 0xd3, 0x28, 0xdc, 0xbe, 0xbb, 0x13, 0xe5, 0x32, 0x03, 0x4b, 0xb6, - 0x0a, 0xa7, 0xb8, 0x6c, 0xd4, 0x19, 0xf1, 0x2c, 0x8f, 0x15, 0x40, 0xc7, 0x43, 0x02, 0xa0, 0xba, 0x20, 0xa0, 0x22, - 0x5a, 0x4a, 0x6f, 0x85, 0x16, 0x0b, 0xf5, 0x86, 0xa3, 0x14, 0xfe, 0x48, 0x7f, 0x1e, 0xe4, 0x53, 0x00, 0x62, 0xd7, - 0xc7, 0xd1, 0xcb, 0xa2, 0xa4, 0x4f, 0x15, 0xb3, 0x5c, 0x0e, 0x26, 0xb0, 0xab, 0x13, 0x19, 0x6a, 0x05, 0x79, 0xab, - 0xae, 0xbc, 0x95, 0xc9, 0xdb, 0x18, 0xa7, 0xe4, 0x07, 0x6e, 0x3a, 0xd6, 0x88, 0x81, 0x57, 0x9e, 0xd6, 0x69, 0x82, - 0x34, 0xb9, 0x00, 0x86, 0x21, 0x7e, 0x9f, 0x79, 0xcf, 0x3c, 0x47, 0xaa, 0x82, 0x64, 0x76, 0x97, 0x79, 0xea, 0x22, - 0xaa, 0xaf, 0x9c, 0x5a, 0x3a, 0x73, 0xfa, 0x11, 0xc0, 0x7b, 0x4c, 0x4d, 0x1a, 0xf2, 0x11, 0x6e, 0x4b, 0xf1, 0xf5, - 0x56, 0x5d, 0xe3, 0xa5, 0xd1, 0xb9, 0x7b, 0xf9, 0xd2, 0x9d, 0x06, 0xfd, 0x14, 0x04, 0xe5, 0x7c, 0x56, 0x0a, 0xd8, - 0x53, 0x66, 0x73, 0xbd, 0x5a, 0xb5, 0x42, 0xeb, 0x70, 0x18, 0x6b, 0x47, 0x21, 0xad, 0xce, 0x02, 0xb6, 0x1a, 0xe9, - 0x94, 0x00, 0x21, 0x38, 0x4e, 0xc3, 0x4e, 0x30, 0xee, 0xd2, 0x69, 0x44, 0xd6, 0x2b, 0x25, 0xe9, 0xc2, 0x0c, 0x92, - 0x7f, 0x92, 0xd7, 0x33, 0xa0, 0x25, 0x80, 0x43, 0x11, 0x4b, 0x78, 0x38, 0x49, 0xae, 0x00, 0x3a, 0x1d, 0x0e, 0x2a, - 0x0d, 0xcd, 0x59, 0xcd, 0x92, 0xf9, 0x24, 0x96, 0xaa, 0xca, 0xc3, 0xc1, 0x53, 0x6e, 0x06, 0xfd, 0x7e, 0x36, 0x2d, - 0x95, 0x0b, 0x40, 0x10, 0xeb, 0xc2, 0x00, 0xf1, 0x48, 0x0b, 0x4f, 0x16, 0x7d, 0x4a, 0xe2, 0x97, 0xb3, 0x64, 0x6e, - 0xb2, 0xe1, 0x1d, 0x18, 0xc1, 0x66, 0x5c, 0x97, 0x94, 0x69, 0x8f, 0xca, 0xef, 0x19, 0x3d, 0xb5, 0x7d, 0xad, 0xd5, - 0x16, 0xb1, 0xae, 0x83, 0xab, 0x12, 0xf5, 0x14, 0x1f, 0x94, 0x24, 0x78, 0xbf, 0x70, 0x6e, 0x46, 0xca, 0xd7, 0x22, - 0xf7, 0x83, 0x76, 0xa6, 0x56, 0x0e, 0x1c, 0x81, 0x1c, 0xab, 0xa8, 0xe4, 0xf5, 0xae, 0x43, 0xf0, 0xe8, 0xae, 0x54, - 0xa0, 0x1c, 0xfc, 0x14, 0xc4, 0xe8, 0xfa, 0xaa, 0xb3, 0x86, 0x9a, 0x69, 0x54, 0x79, 0x04, 0x9d, 0x3a, 0x80, 0x27, - 0x05, 0x2f, 0xb5, 0xfa, 0xf1, 0x70, 0xf0, 0xcc, 0x0f, 0xfe, 0x2e, 0xd3, 0xb7, 0x10, 0x13, 0xe5, 0x54, 0x23, 0x24, - 0xae, 0x94, 0x24, 0xe2, 0xe3, 0x45, 0xcb, 0x8a, 0x51, 0x19, 0xde, 0xf3, 0x4a, 0x95, 0xaf, 0x4e, 0x55, 0x5e, 0x8c, - 0xb4, 0x2d, 0x81, 0xd7, 0xe4, 0x1f, 0x22, 0xd7, 0xbc, 0xf5, 0x75, 0x57, 0x19, 0xfa, 0x48, 0x56, 0xa0, 0x23, 0xd8, - 0xca, 0x52, 0x72, 0xc0, 0x27, 0xd5, 0x5d, 0xb5, 0x6a, 0x7d, 0x4e, 0xd9, 0x46, 0xb8, 0xc9, 0xaf, 0x63, 0x07, 0x47, - 0xca, 0x6f, 0xf0, 0x5c, 0x00, 0x7b, 0x0d, 0xd8, 0x9b, 0x73, 0x56, 0x34, 0x0f, 0x0e, 0x69, 0x5b, 0xa0, 0x91, 0x99, - 0xdb, 0xb9, 0xba, 0x6f, 0xcb, 0xa3, 0x34, 0x86, 0xc8, 0xb4, 0x07, 0xa6, 0x83, 0xcd, 0x28, 0xff, 0x3d, 0xe5, 0xb7, - 0x0a, 0xc7, 0xc0, 0xb7, 0x53, 0xef, 0x00, 0xaa, 0x9e, 0x36, 0xc8, 0x58, 0x33, 0x0c, 0xad, 0xec, 0x72, 0x29, 0xb4, - 0x04, 0x2d, 0x75, 0x13, 0x04, 0xe7, 0x47, 0x44, 0x39, 0x02, 0xd0, 0x45, 0x0a, 0x98, 0xe0, 0xa7, 0xb4, 0xdd, 0xfd, - 0xfe, 0x3a, 0xf5, 0xc8, 0xbd, 0x2b, 0xd4, 0x28, 0xa1, 0x04, 0x63, 0x3f, 0xd1, 0x98, 0x41, 0x47, 0x57, 0xe4, 0x84, - 0x67, 0xad, 0x0e, 0xeb, 0xba, 0x29, 0x83, 0xb2, 0x38, 0xe6, 0xd5, 0x74, 0xf6, 0xc7, 0xa3, 0x7d, 0xdd, 0x20, 0x0b, - 0xf9, 0x1f, 0xac, 0x87, 0x64, 0xd0, 0x3d, 0x08, 0x85, 0xe8, 0xcd, 0x83, 0x19, 0xfe, 0xc7, 0x36, 0x3c, 0xfb, 0x8e, - 0x1b, 0x75, 0x82, 0x98, 0x23, 0x8e, 0x97, 0x9e, 0xa2, 0xad, 0x87, 0x5b, 0x20, 0x5b, 0xe3, 0xe5, 0xad, 0xbd, 0x06, - 0x72, 0x8a, 0xe3, 0xbf, 0xe5, 0x99, 0x5a, 0xd9, 0xe0, 0xa7, 0xa7, 0x6c, 0x07, 0x1e, 0x5e, 0x84, 0x80, 0x62, 0x58, - 0x36, 0xfe, 0xd6, 0x72, 0x9c, 0xd1, 0x7f, 0xf3, 0x88, 0x61, 0xb0, 0x88, 0xfc, 0xf8, 0xb2, 0x14, 0xe2, 0xab, 0xf0, - 0x3e, 0x55, 0xde, 0x2d, 0x39, 0x65, 0xde, 0xea, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x4b, 0x3e, 0xb6, 0x86, 0xed, 0x0f, - 0xed, 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0xd5, 0xec, 0xf4, 0xfa, 0xbd, 0x73, - 0xbc, 0x60, 0x6b, 0x34, 0xc0, 0xe3, 0xa1, 0x8b, 0x79, 0xa2, 0x86, 0x4e, 0xd7, 0xb5, 0x73, 0xf0, 0xc0, 0x20, 0xcb, - 0x93, 0xef, 0x18, 0x96, 0xd8, 0x9f, 0x44, 0x3c, 0x69, 0xab, 0x36, 0x36, 0x47, 0xaa, 0x8d, 0x9a, 0x81, 0x1f, 0xbc, - 0x82, 0x02, 0xa3, 0x0b, 0xd2, 0x02, 0x8c, 0xc3, 0x11, 0x80, 0xac, 0x18, 0xc7, 0x23, 0x83, 0x09, 0x0c, 0xe9, 0x86, - 0xa2, 0x00, 0x3c, 0x3c, 0x8e, 0x07, 0x21, 0x03, 0x48, 0x17, 0x3c, 0x34, 0x6c, 0x93, 0x90, 0xf2, 0xf3, 0x3c, 0xaf, - 0xd5, 0x10, 0xfa, 0xce, 0x42, 0x75, 0xec, 0x47, 0xda, 0x2b, 0xd6, 0xb5, 0x2a, 0x1d, 0xd9, 0xea, 0x00, 0x7d, 0x43, - 0x06, 0xbe, 0x75, 0x6c, 0x01, 0x10, 0x2d, 0xf1, 0x25, 0xf5, 0x6a, 0x5f, 0xc6, 0xac, 0x50, 0xaf, 0x2f, 0x4c, 0xbb, - 0x5e, 0x48, 0x8b, 0x02, 0x2a, 0x6e, 0x5b, 0xb5, 0x3d, 0x92, 0xf3, 0x1f, 0xde, 0x75, 0xb4, 0xe3, 0xb3, 0x53, 0x63, - 0x4b, 0x28, 0x73, 0x8b, 0x27, 0xb2, 0x3a, 0xda, 0x52, 0x9d, 0xea, 0x03, 0x2e, 0x35, 0xa9, 0xce, 0x0c, 0x0c, 0xaf, - 0x11, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xde, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xd8, 0xda, - 0x45, 0x73, 0xfd, 0xfa, 0x92, 0x7a, 0x55, 0x9b, 0xaa, 0x1e, 0xbc, 0xf1, 0x02, 0x67, 0xef, 0xb4, 0x16, 0x10, 0x40, - 0x61, 0x6b, 0x59, 0x0e, 0xce, 0xdd, 0xae, 0x6a, 0xa9, 0x28, 0xa3, 0x7e, 0xff, 0xfc, 0x4b, 0x8a, 0x8a, 0xd8, 0x53, - 0xc5, 0x29, 0xeb, 0xb7, 0x5b, 0xe6, 0xa2, 0xb2, 0xe4, 0x0d, 0xaa, 0x68, 0xad, 0x8e, 0x9a, 0xca, 0x75, 0x73, 0xd5, - 0x92, 0x09, 0x62, 0x74, 0x9f, 0xae, 0x75, 0xee, 0xd4, 0x7b, 0xaf, 0xe2, 0x88, 0x81, 0xe0, 0xa6, 0x7b, 0x7c, 0x70, - 0x10, 0x1a, 0x15, 0xe5, 0x82, 0x1b, 0xa5, 0x55, 0x25, 0xa5, 0x90, 0xb7, 0x2a, 0x9a, 0x33, 0x7d, 0x04, 0x40, 0x04, - 0x58, 0x25, 0xea, 0xff, 0xf0, 0xa5, 0x31, 0x1e, 0x3c, 0xf0, 0x35, 0xb9, 0x8e, 0xad, 0xf7, 0x4f, 0x6b, 0xa4, 0xd5, - 0xc6, 0x31, 0xa9, 0x55, 0x2f, 0x5b, 0xc5, 0xcb, 0xee, 0x75, 0x2a, 0x06, 0xcf, 0xff, 0xe7, 0x3e, 0x40, 0x8d, 0x68, - 0x29, 0x83, 0x5b, 0x57, 0x03, 0x34, 0x3e, 0x1c, 0x0b, 0xdf, 0xf8, 0x21, 0xe3, 0x7c, 0x30, 0x43, 0x47, 0xb5, 0x39, - 0x38, 0x20, 0x38, 0xaa, 0x7b, 0x34, 0x26, 0xcc, 0xc2, 0xb9, 0x07, 0x81, 0xea, 0x13, 0xf7, 0x19, 0xd7, 0x5e, 0xd0, - 0x26, 0xf0, 0xc9, 0xba, 0xae, 0x29, 0x02, 0x5c, 0xc4, 0xc6, 0x44, 0x0c, 0x71, 0xd9, 0x24, 0x52, 0xdf, 0x8c, 0x41, - 0x01, 0x50, 0x3c, 0xad, 0x48, 0x2e, 0x5d, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, - 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, - 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, - 0x19, 0x7f, 0x4a, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, 0x9e, 0xc3, 0xa7, 0xbc, 0x9c, 0x84, - 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, - 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, - 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, - 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, - 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, - 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, - 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, - 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0x7c, 0xbf, 0xc1, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0xf2, - 0x16, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, - 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, - 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x24, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, - 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, 0x99, 0xe4, 0xed, 0x12, 0x8e, 0xba, - 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, - 0xf7, 0xbe, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, - 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, - 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, - 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0xa7, - 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, 0xf3, 0x9a, 0x5d, 0x3f, 0x16, 0x6c, - 0xc7, 0x76, 0x8f, 0x11, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, 0x2f, 0xdc, 0xf2, 0x25, 0x80, 0x07, - 0xb2, 0x18, 0x50, 0x7c, 0x96, 0xde, 0x2f, 0x2c, 0x01, 0x35, 0xf9, 0x0d, 0x5f, 0x7b, 0x6f, 0x29, 0x75, 0x01, 0x7f, - 0x0e, 0x28, 0x7d, 0x92, 0x73, 0xef, 0x76, 0x78, 0xe3, 0x5f, 0x3c, 0x01, 0xe7, 0x89, 0xd5, 0x70, 0x01, 0x7f, 0x15, - 0x7c, 0xe8, 0xdd, 0x0e, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x35, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x05, - 0x39, 0xc3, 0x3f, 0x7e, 0xd7, 0x18, 0xac, 0xbf, 0x05, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0xce, 0x04, - 0xd8, 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xb3, 0x16, 0xf4, 0xe7, 0x03, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, - 0xf9, 0x01, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x53, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x57, 0xae, 0xc1, - 0x8e, 0xd7, 0xc9, 0x91, 0xa5, 0xf0, 0xac, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, - 0xe5, 0xb9, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0e, 0x72, 0x19, 0x1a, 0xf3, 0x0e, 0xd9, 0x30, 0x94, 0x0f, 0x2d, - 0x32, 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xbd, 0xf6, 0x72, 0xe0, - 0x3d, 0x88, 0xfc, 0x46, 0xba, 0x94, 0x4b, 0x6c, 0x74, 0xe2, 0x58, 0x16, 0xda, 0x79, 0x5c, 0x7f, 0x1d, 0x83, 0xfa, - 0xbd, 0xd2, 0x6f, 0x50, 0xce, 0xfe, 0x20, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xbf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, - 0xfe, 0x3f, 0x63, 0x0a, 0xa5, 0xbf, 0x4e, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, - 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x57, 0x26, 0xf8, 0xf0, 0x57, 0xed, 0x5c, - 0x9b, 0xf3, 0xf1, 0x24, 0xbf, 0xb2, 0xf6, 0x6e, 0xc7, 0x8b, 0xc4, 0x28, 0xc6, 0x72, 0x5f, 0x75, 0xb3, 0x72, 0xa2, - 0x92, 0x03, 0x23, 0x5d, 0x93, 0xbd, 0x5c, 0xc9, 0xba, 0x9d, 0x6e, 0x25, 0x10, 0x51, 0x05, 0xde, 0x63, 0x5c, 0xc5, - 0x3e, 0x82, 0xe9, 0xba, 0xe3, 0x32, 0xda, 0xf1, 0x9e, 0xf1, 0xea, 0x44, 0x59, 0xc1, 0xed, 0x46, 0xb4, 0x27, 0x74, - 0xf4, 0xd3, 0xa4, 0xb6, 0x2c, 0x1c, 0x80, 0xdc, 0x25, 0x8c, 0x65, 0x43, 0xb0, 0x62, 0x50, 0xfa, 0x7a, 0x4d, 0xc9, - 0xb2, 0x00, 0x8b, 0xce, 0x2e, 0x23, 0x10, 0xc3, 0xba, 0x69, 0x4e, 0xe8, 0x78, 0xe9, 0xe2, 0xbc, 0xd7, 0x2a, 0x52, - 0xf0, 0x8c, 0x16, 0x1d, 0x73, 0xd3, 0x91, 0x6e, 0x8c, 0xf6, 0xf6, 0xb9, 0x41, 0x48, 0xf1, 0xfc, 0x81, 0xad, 0xd6, - 0xc5, 0x45, 0xe2, 0x15, 0x32, 0xd1, 0x82, 0x58, 0x8a, 0xc0, 0x8c, 0x17, 0x9a, 0x46, 0x98, 0xa0, 0x4c, 0x09, 0x16, - 0xad, 0xd1, 0xa1, 0xfd, 0x61, 0x09, 0xbb, 0xc7, 0x18, 0x01, 0x02, 0x55, 0xa6, 0x5f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, - 0xc5, 0x06, 0x68, 0xab, 0x18, 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x43, 0x9a, 0xdf, 0xfe, 0x0b, 0x8b, 0xb1, 0x3d, 0x81, - 0xd8, 0xde, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xa8, 0x1d, - 0x6b, 0xa9, 0x77, 0xac, 0xb5, 0xde, 0xb1, 0x6e, 0x1b, 0xfe, 0x2c, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, - 0x83, 0xa0, 0x19, 0x1b, 0x76, 0x03, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, - 0x60, 0x19, 0x51, 0x93, 0xef, 0x90, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0x77, - 0x8f, 0x23, 0xc8, 0xbd, 0xe3, 0xde, 0xdd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, - 0x4f, 0x10, 0xad, 0xec, 0x29, 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x1f, 0xdf, 0xb9, 0xdb, 0xda, 0xed, 0xe3, 0x3b, 0x56, - 0x8d, 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xe3, - 0x8e, 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0x8f, 0x33, 0x8d, - 0xe7, 0x70, 0x24, 0x9f, 0x8e, 0x35, 0x36, 0x08, 0xea, 0xfa, 0x9c, 0x41, 0xed, 0xd8, 0x7d, 0x4d, 0xd8, 0x65, 0xc7, - 0xbc, 0xd6, 0x35, 0x6f, 0xaf, 0x3c, 0x15, 0x1b, 0x02, 0x3a, 0x7c, 0xad, 0x6e, 0x90, 0x7f, 0x09, 0x9c, 0x22, 0x00, - 0xe4, 0x70, 0xbc, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0x77, 0xa8, 0xb5, 0xa8, 0x2c, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, - 0x8a, 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2e, 0x2e, 0x7e, 0x3d, 0x2d, - 0x94, 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x8e, - 0x94, 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf1, 0x84, 0xc5, 0x90, 0x08, 0xb0, 0xdd, - 0xa1, 0x62, 0x5b, 0xb8, 0x78, 0xc2, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, - 0x8e, 0x35, 0xd4, 0x6c, 0x6d, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x6e, 0xdb, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, - 0xeb, 0x3d, 0xaa, 0x0b, 0x60, 0xeb, 0xbf, 0x39, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, - 0x7a, 0x95, 0x2c, 0xfc, 0x9b, 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, - 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, - 0x97, 0x15, 0xdb, 0x05, 0xb1, 0x9d, 0xf0, 0x3b, 0x01, 0x53, 0x3e, 0x83, 0x20, 0xae, 0xe0, 0x06, 0xe2, 0xf0, 0xe4, - 0x9f, 0x83, 0xbb, 0xd6, 0x66, 0x7d, 0xc7, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, - 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, 0xb7, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, - 0x40, 0xfc, 0x74, 0x33, 0xe0, 0x77, 0x1d, 0x6b, 0xcb, 0xbb, 0x66, 0x0b, 0xb6, 0x83, 0x4b, 0x50, 0xd3, 0x5e, 0xf6, - 0x27, 0x95, 0x0b, 0xda, 0xb1, 0x4b, 0xe2, 0xe1, 0x8c, 0x59, 0xa5, 0xcc, 0xac, 0x93, 0xea, 0x4a, 0x74, 0xc6, 0x74, - 0xd6, 0x7a, 0x3e, 0x57, 0xf3, 0x49, 0xa1, 0x41, 0xfd, 0xce, 0x89, 0x8f, 0xa8, 0xe8, 0x3c, 0x81, 0xad, 0x65, 0x05, - 0xb1, 0xda, 0xe7, 0x60, 0xad, 0xd5, 0x2e, 0xfd, 0x5e, 0x3e, 0xe0, 0x36, 0xe5, 0xb0, 0x0e, 0x0c, 0x6a, 0x4e, 0xac, - 0xa8, 0x87, 0x6c, 0xc7, 0xb8, 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xf5, 0xb1, 0xa7, - 0xbf, 0x53, 0xfb, 0x17, 0xc2, 0x0f, 0xc6, 0xff, 0xa9, 0xdd, 0xd7, 0x5a, 0x8c, 0xca, 0x56, 0x39, 0x42, 0xe3, 0x6e, - 0x25, 0x4d, 0x96, 0x9f, 0x84, 0x27, 0xac, 0x05, 0xcf, 0x72, 0xbd, 0x44, 0xb3, 0x02, 0x56, 0x58, 0xcb, 0x24, 0x5c, - 0x61, 0xac, 0x96, 0xb6, 0xfa, 0x16, 0x4d, 0x73, 0x7c, 0x38, 0xd7, 0x06, 0x65, 0xca, 0xd9, 0x19, 0xb1, 0x1a, 0x2e, - 0xc3, 0xd2, 0x84, 0x22, 0x64, 0xf7, 0x76, 0x70, 0x63, 0xa7, 0x2c, 0xa5, 0x0c, 0xe7, 0x18, 0x4c, 0x78, 0x24, 0x46, - 0x55, 0xbe, 0xbf, 0x2f, 0x29, 0x72, 0xda, 0x96, 0x83, 0x2a, 0x84, 0x7d, 0x24, 0x51, 0x02, 0xb7, 0x22, 0x2d, 0x14, - 0x29, 0x8b, 0xbf, 0x1d, 0xa0, 0x0b, 0xbc, 0x80, 0xba, 0x1a, 0x75, 0xfb, 0xc3, 0x11, 0x0f, 0x1f, 0x98, 0xfa, 0xc0, - 0x88, 0x25, 0x81, 0xda, 0x9e, 0x65, 0xe9, 0x2d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, - 0x1b, 0xe9, 0x0d, 0xad, 0xc1, 0x23, 0xb4, 0xa6, 0x3c, 0x77, 0x52, 0x6d, 0xd2, 0x79, 0x47, 0xc8, 0xb1, 0xfa, 0xd6, - 0x12, 0x46, 0xbb, 0xa2, 0x17, 0xf7, 0x8e, 0xde, 0xf3, 0x74, 0xd5, 0x73, 0x7f, 0xe2, 0x8a, 0x79, 0x72, 0x1b, 0x81, - 0xba, 0x15, 0x54, 0xb7, 0x77, 0x2a, 0xc1, 0x82, 0x25, 0xed, 0x3e, 0x7e, 0x3b, 0x6b, 0x07, 0xa2, 0x32, 0x56, 0xe9, - 0x5b, 0x92, 0xb0, 0x27, 0x06, 0x9d, 0x42, 0x55, 0x6e, 0x77, 0x47, 0x5b, 0xe0, 0x3a, 0x66, 0x29, 0x7a, 0x66, 0x8b, - 0xdc, 0x2d, 0xff, 0xee, 0xb9, 0x22, 0x67, 0xbf, 0x04, 0x04, 0xa7, 0xe6, 0x1b, 0xe2, 0xcb, 0x11, 0x1e, 0x55, 0xb7, - 0xc0, 0x71, 0xfa, 0x0e, 0xe0, 0x1f, 0x0e, 0x97, 0xa0, 0x09, 0x88, 0x05, 0xeb, 0xa5, 0x71, 0x8f, 0xf5, 0xe2, 0x62, - 0x73, 0x9b, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, - 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, - 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, - 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, - 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, - 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0x7f, 0x19, 0xff, 0xd0, 0x33, 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, - 0xaf, 0xbf, 0x42, 0x00, 0x1c, 0x9e, 0x4d, 0xbd, 0xcb, 0x31, 0x64, 0x95, 0x65, 0x04, 0x92, 0x9f, 0x18, 0x7c, 0xf9, - 0x02, 0xa0, 0xea, 0x33, 0x5d, 0xab, 0xc9, 0x51, 0x7b, 0xcc, 0xa1, 0x2b, 0x06, 0x80, 0x6d, 0x58, 0xa2, 0xaa, 0x16, - 0x36, 0x61, 0x71, 0xfb, 0x19, 0x46, 0x73, 0xd9, 0xf4, 0x82, 0x06, 0xea, 0x11, 0x82, 0x5f, 0x5a, 0x0f, 0xad, 0xb5, - 0x4c, 0x39, 0x74, 0x6d, 0x14, 0x55, 0x36, 0xd4, 0x25, 0xac, 0xd6, 0x22, 0xaa, 0x89, 0x22, 0xe5, 0x92, 0x51, 0x14, - 0x4b, 0x15, 0xec, 0x33, 0x71, 0x0b, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x16, 0x10, 0xd6, 0xc2, 0x5a, 0x48, - 0x67, 0x50, 0x7b, 0xa7, 0x1f, 0x29, 0x7f, 0x79, 0x21, 0xb7, 0x73, 0x0b, 0x45, 0xb8, 0x3d, 0x07, 0xe5, 0x4d, 0x5d, - 0x95, 0x8a, 0x68, 0xb4, 0x04, 0x4a, 0x99, 0x13, 0x44, 0x16, 0x20, 0x80, 0xe3, 0x06, 0x02, 0x9f, 0xd7, 0xf8, 0x04, - 0x1a, 0x85, 0x40, 0x7e, 0x60, 0x15, 0xae, 0x3d, 0xa4, 0xa5, 0xd6, 0x88, 0x28, 0x11, 0x3f, 0xba, 0x7a, 0x8e, 0xed, - 0xab, 0xa7, 0xb1, 0xb6, 0x94, 0x26, 0x88, 0x9f, 0x58, 0x6c, 0x21, 0x26, 0x88, 0xea, 0x10, 0x1d, 0xc1, 0x72, 0x42, - 0x88, 0xc2, 0x9f, 0x42, 0x3f, 0x35, 0xf0, 0x97, 0x6c, 0x59, 0xe4, 0x35, 0xc1, 0x62, 0x56, 0x0c, 0xd0, 0xaa, 0x08, - 0x3c, 0xd3, 0xd9, 0x52, 0x99, 0xd3, 0x3c, 0x3a, 0xb2, 0x83, 0xf3, 0xae, 0x83, 0xbd, 0xf4, 0x65, 0xec, 0x64, 0xd9, - 0x34, 0x6a, 0x63, 0x43, 0x24, 0xbc, 0x22, 0xbf, 0xce, 0x52, 0xe3, 0x1c, 0x99, 0xcb, 0xf5, 0x5d, 0x17, 0xb7, 0xb7, - 0xb4, 0x4d, 0x58, 0x85, 0x08, 0x75, 0xdb, 0x50, 0xb9, 0x14, 0x66, 0x63, 0xd3, 0x34, 0xc0, 0x17, 0x8a, 0x4a, 0xa5, - 0x2a, 0xb5, 0x95, 0x4a, 0x4e, 0x78, 0xd7, 0x37, 0xb5, 0x48, 0x5d, 0x11, 0x6c, 0x63, 0x86, 0x7a, 0x28, 0x37, 0x6a, - 0xec, 0xdb, 0x8e, 0x55, 0x7a, 0x87, 0x09, 0x72, 0x46, 0x5e, 0xe4, 0xe0, 0xa2, 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, - 0x83, 0x86, 0x4f, 0x0b, 0xcb, 0x3d, 0x94, 0x80, 0xd9, 0x51, 0xc3, 0xa3, 0x08, 0x81, 0x88, 0x4b, 0x65, 0x5f, 0x31, - 0xf1, 0x7b, 0x0a, 0x66, 0xc9, 0x84, 0xee, 0x45, 0x2c, 0x8b, 0xd0, 0xc6, 0x27, 0x49, 0x32, 0xf5, 0x34, 0x05, 0x37, - 0x72, 0x19, 0xe6, 0x68, 0x84, 0x96, 0x7c, 0xe4, 0x40, 0xfa, 0x5a, 0x4e, 0x25, 0xf8, 0x88, 0x3a, 0x05, 0x1c, 0xcf, - 0xcf, 0x0b, 0xeb, 0x27, 0xcb, 0x25, 0xe6, 0xb2, 0x36, 0xff, 0x65, 0x47, 0xc7, 0x60, 0x97, 0xa7, 0x89, 0xe3, 0xea, - 0x3f, 0xaa, 0x92, 0xe2, 0xfe, 0x75, 0x9a, 0x03, 0x8a, 0x60, 0x66, 0x4f, 0x31, 0x3e, 0xf6, 0x59, 0xa6, 0x80, 0xbf, - 0x5d, 0x6f, 0x2d, 0x99, 0xd8, 0x25, 0xed, 0xe6, 0xca, 0xf8, 0xa5, 0x36, 0xec, 0x38, 0x38, 0x37, 0x00, 0xc5, 0x59, - 0xa3, 0xc3, 0xf2, 0x5a, 0xb7, 0xad, 0x0a, 0x15, 0xa8, 0xf5, 0x7f, 0x76, 0x0b, 0x53, 0xde, 0xe6, 0xa5, 0xf2, 0x36, - 0x0f, 0x4d, 0x80, 0x40, 0x64, 0x86, 0x3c, 0x6b, 0x3a, 0x26, 0x89, 0x7b, 0x47, 0x4a, 0xda, 0x77, 0xa4, 0xf8, 0xc1, - 0x3b, 0x12, 0xf2, 0x2d, 0xa1, 0x23, 0xfb, 0x92, 0x93, 0x13, 0x28, 0x33, 0xd8, 0xcb, 0x6b, 0x26, 0xfb, 0x07, 0xb4, - 0x17, 0xce, 0x65, 0x79, 0xc5, 0xdf, 0x08, 0x6f, 0xed, 0x4f, 0xd7, 0xa7, 0x5d, 0x55, 0x6f, 0xbe, 0x31, 0x33, 0x0f, - 0x87, 0xe2, 0x70, 0xa8, 0x4c, 0xd0, 0xee, 0x82, 0x8b, 0x41, 0xce, 0xee, 0xdc, 0xf8, 0xf8, 0x6b, 0x8e, 0x22, 0xb6, - 0x52, 0x1e, 0x49, 0x17, 0x2a, 0x31, 0xbc, 0x34, 0xf0, 0x30, 0x3b, 0x3e, 0x9e, 0xec, 0xae, 0xee, 0x26, 0x83, 0xc1, - 0x4e, 0xf5, 0xed, 0x96, 0xd7, 0xb3, 0xdd, 0x9c, 0xdd, 0xf3, 0x9b, 0xe9, 0x36, 0xd8, 0x37, 0xb0, 0xed, 0xee, 0xae, - 0xc4, 0xe1, 0xb0, 0x7b, 0xca, 0x17, 0xfe, 0xfe, 0x1e, 0x01, 0x9d, 0xf9, 0xf9, 0xb8, 0x8d, 0xf1, 0xf3, 0xa6, 0xed, - 0xaa, 0xb5, 0x03, 0x78, 0xfa, 0x57, 0xde, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0xf7, 0xfc, 0x1e, 0xfc, 0xf3, 0x71, 0x93, - 0x44, 0xea, 0x13, 0xed, 0x32, 0xf9, 0x06, 0x1c, 0xc8, 0x77, 0x3e, 0xfb, 0xc4, 0xef, 0x67, 0xcb, 0x39, 0x2f, 0x0e, - 0x87, 0x47, 0xd3, 0x10, 0xc9, 0x9a, 0xc2, 0x8a, 0x58, 0x52, 0x3c, 0x3f, 0x08, 0x8f, 0xdf, 0x8b, 0xc8, 0x10, 0x69, - 0xb9, 0x77, 0x87, 0xec, 0x0d, 0x8b, 0xfc, 0x00, 0x3e, 0xc8, 0x76, 0xfe, 0x44, 0xd6, 0x94, 0xee, 0x17, 0xef, 0xfd, - 0xc3, 0x81, 0xfe, 0xfa, 0xe4, 0x1f, 0x0e, 0x8f, 0xd8, 0x3d, 0x82, 0xa3, 0xf3, 0x1d, 0xf4, 0x8f, 0xbe, 0x75, 0x40, - 0x55, 0x86, 0xd7, 0xb3, 0xcd, 0xdc, 0x7f, 0xba, 0x62, 0xb7, 0xc0, 0x85, 0xa2, 0xbc, 0xd0, 0xde, 0xb0, 0x7b, 0xf4, - 0x3a, 0x23, 0x27, 0xa2, 0xd9, 0x6e, 0xee, 0xb3, 0x18, 0x9f, 0xab, 0xfb, 0x62, 0xf2, 0xcd, 0xfb, 0xe2, 0x8e, 0x6d, - 0xbb, 0xef, 0x8b, 0xf2, 0x4d, 0x77, 0xfd, 0x6c, 0xd9, 0x8e, 0xdd, 0xc3, 0x0c, 0xbb, 0xe6, 0x6f, 0x9a, 0x63, 0xc7, - 0xd8, 0x6f, 0xde, 0x18, 0x01, 0x94, 0xd9, 0x82, 0xc5, 0x82, 0x83, 0x52, 0xad, 0xda, 0x96, 0x44, 0x5e, 0xe9, 0x40, - 0xb5, 0x19, 0xc1, 0x7d, 0xb5, 0x90, 0x33, 0xcf, 0x0c, 0xf4, 0x6d, 0x85, 0x68, 0xe1, 0xb0, 0x01, 0x7f, 0xa3, 0xad, - 0x63, 0x0c, 0xd3, 0xac, 0x66, 0xda, 0x16, 0x75, 0xf9, 0x7d, 0xef, 0x99, 0xfc, 0x46, 0x06, 0xb6, 0x10, 0x49, 0xe1, - 0x38, 0xbe, 0x78, 0x72, 0xc2, 0x7f, 0xd5, 0xf2, 0xa8, 0xd5, 0x7e, 0xa1, 0xd4, 0xa7, 0xd7, 0x74, 0x44, 0x13, 0xf7, - 0xa2, 0x2d, 0xc3, 0x1a, 0x65, 0x4d, 0x2d, 0x1d, 0x86, 0x71, 0x0d, 0xfb, 0xf2, 0xc0, 0xa1, 0xef, 0x80, 0x40, 0x5b, - 0xa5, 0x52, 0xa0, 0x85, 0x63, 0x18, 0x85, 0x59, 0x48, 0x79, 0x58, 0x98, 0xa5, 0xbc, 0xc7, 0x02, 0x2d, 0x6e, 0xd5, - 0x3d, 0xa6, 0xb6, 0x5b, 0x10, 0x61, 0xf5, 0x96, 0x71, 0x7e, 0xd9, 0xa8, 0xc2, 0x6d, 0x01, 0x8a, 0x22, 0x28, 0x83, - 0x3d, 0xc9, 0x6d, 0x0b, 0x25, 0xcd, 0x46, 0x61, 0x2d, 0x6e, 0x8b, 0x72, 0xd7, 0x6b, 0xd8, 0x02, 0x2f, 0xa8, 0xfa, - 0x09, 0x61, 0x5b, 0xf6, 0xac, 0x43, 0xb9, 0x48, 0xff, 0x23, 0x4b, 0xcf, 0xf7, 0x5b, 0x73, 0xfe, 0xa7, 0xaf, 0xe8, - 0xa3, 0xf2, 0x3f, 0xbf, 0xa4, 0x9f, 0x0c, 0x96, 0x91, 0x53, 0xea, 0x97, 0x68, 0x74, 0x93, 0xe6, 0x84, 0xb1, 0xe5, - 0xeb, 0xa7, 0xdf, 0x21, 0x53, 0x90, 0x1c, 0x4a, 0xa9, 0xca, 0xc9, 0x1e, 0xfa, 0xc2, 0xeb, 0x3e, 0xcc, 0x04, 0x03, - 0x10, 0x5e, 0xa3, 0x4d, 0x35, 0x61, 0x12, 0x0f, 0xae, 0xe0, 0xff, 0x46, 0x10, 0x83, 0xf6, 0x89, 0xa2, 0x8e, 0x6d, - 0x23, 0x5d, 0xb7, 0x9d, 0x83, 0xe4, 0x4e, 0x5d, 0xf9, 0xa3, 0x72, 0xf2, 0x9f, 0x68, 0x88, 0xbc, 0xe2, 0x0a, 0xb1, - 0xb2, 0xe0, 0x12, 0x8b, 0xa1, 0x22, 0x05, 0xb8, 0x86, 0x20, 0x52, 0x16, 0x25, 0x85, 0x5b, 0x0e, 0xaa, 0x22, 0x00, - 0xe3, 0x6a, 0x75, 0xd4, 0x89, 0xf0, 0x71, 0x6b, 0x2d, 0x42, 0xb0, 0xa2, 0x51, 0x2b, 0x6b, 0x05, 0xbe, 0x20, 0x7d, - 0xe9, 0x50, 0x10, 0xd3, 0xa3, 0x90, 0xaa, 0xd2, 0xa1, 0x40, 0x9a, 0x43, 0xc5, 0x37, 0x06, 0x1b, 0x45, 0x45, 0x7a, - 0xfe, 0xd2, 0xa4, 0xe4, 0xd2, 0x98, 0xf1, 0x5e, 0x94, 0x91, 0xc8, 0xeb, 0xf0, 0x56, 0x4c, 0x0b, 0xe4, 0x1b, 0x3d, - 0x7e, 0x10, 0x5c, 0xc2, 0xbb, 0x21, 0xf7, 0x0a, 0xb0, 0x25, 0x60, 0x07, 0xb8, 0x57, 0x66, 0x94, 0xeb, 0xb4, 0xae, - 0xdf, 0x5a, 0x0f, 0xc5, 0x30, 0x7c, 0x6c, 0x09, 0x6c, 0x47, 0xeb, 0xe8, 0x48, 0x0f, 0x1f, 0xfe, 0xd7, 0x55, 0xcd, - 0x51, 0xa7, 0x72, 0x39, 0x3b, 0x9e, 0xb0, 0x14, 0x31, 0x83, 0xee, 0xaf, 0xdb, 0x6b, 0x01, 0x74, 0xbb, 0x2c, 0xe6, - 0xd9, 0x68, 0x27, 0xff, 0x96, 0x6e, 0xac, 0x28, 0x6d, 0xe2, 0x5d, 0xd6, 0x1b, 0xfb, 0xc3, 0xd1, 0x5f, 0x1e, 0xbf, - 0x9d, 0x10, 0xaa, 0xce, 0x86, 0xad, 0x75, 0x9c, 0xcb, 0xff, 0xfa, 0xeb, 0x98, 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, - 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, 0x5f, 0x6a, 0x9d, 0x30, 0x31, 0xb2, - 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0x5b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x3e, 0x59, 0x1b, 0x0d, 0xe6, 0x8a, 0xd7, 0xb3, - 0xf5, 0x5c, 0x2a, 0x9f, 0xc1, 0x94, 0xb3, 0x1c, 0x9c, 0x2c, 0x85, 0xdd, 0x91, 0x40, 0xd1, 0x9a, 0xa1, 0x6b, 0x7f, - 0x8a, 0xad, 0x7a, 0x91, 0x56, 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf6, - 0x47, 0xa5, 0x1f, 0x8c, 0x27, 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, - 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x05, 0xdf, 0xf8, 0xca, 0x07, 0xe3, 0x1a, 0xb5, 0xd5, 0xa0, 0xa0, 0x76, 0x74, - 0xcb, 0x63, 0x47, 0xef, 0x7c, 0x77, 0x42, 0x5f, 0xbd, 0xd0, 0xc2, 0xf1, 0x37, 0xce, 0xc8, 0x35, 0x5b, 0x75, 0xc8, - 0x11, 0xcd, 0xa4, 0x43, 0x88, 0x58, 0xb1, 0x35, 0xbb, 0x26, 0x95, 0x73, 0xe7, 0x90, 0x9d, 0x3e, 0x42, 0x95, 0x5e, - 0xeb, 0xe1, 0xed, 0x44, 0xe9, 0x6e, 0x8f, 0x77, 0x93, 0xef, 0xd9, 0x44, 0xc4, 0x60, 0x40, 0x1b, 0x84, 0x33, 0xb2, - 0x0e, 0x91, 0x4a, 0x07, 0x08, 0x81, 0x63, 0x02, 0x9a, 0xfe, 0xfb, 0x5b, 0x12, 0x05, 0x1c, 0x69, 0x23, 0x64, 0x2d, - 0x3b, 0x1c, 0x72, 0xd0, 0x28, 0x37, 0x7f, 0x7a, 0x85, 0x3a, 0xcd, 0x81, 0x79, 0xba, 0x84, 0x3d, 0x07, 0x8f, 0xf4, - 0xe2, 0xf8, 0x48, 0xff, 0xef, 0x68, 0xa2, 0xc6, 0xff, 0xb9, 0x26, 0x4a, 0x69, 0x91, 0x1c, 0xd5, 0xd2, 0x77, 0xa9, - 0xa3, 0xe0, 0x22, 0xef, 0xa8, 0x85, 0xec, 0x59, 0x36, 0x6e, 0x54, 0xf3, 0xfe, 0x7f, 0xad, 0xcc, 0xff, 0xd7, 0xb4, - 0x32, 0x4c, 0xc9, 0x8e, 0xa5, 0x9a, 0x79, 0xa0, 0x55, 0x0c, 0xb3, 0xd7, 0x24, 0x21, 0x32, 0x5c, 0x1a, 0xf0, 0xa3, - 0x0a, 0xf6, 0x71, 0x5a, 0xad, 0xb3, 0x70, 0x87, 0x4a, 0xd4, 0x1b, 0x71, 0x9b, 0xe6, 0xcf, 0xea, 0x7f, 0x8b, 0xb2, - 0x80, 0xa9, 0x7d, 0x5b, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, 0x63, 0x1b, 0x5f, 0xcb, 0xf1, 0xb4, - 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0x96, 0x92, 0x9c, 0xcb, 0xca, 0xe2, 0x1e, 0xa1, 0x9b, 0x7f, 0x2a, 0xcb, - 0xa2, 0xf4, 0x7a, 0x9f, 0x92, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, - 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, - 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, - 0x36, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, - 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xdb, 0x1c, 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, - 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, - 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x5c, 0xb6, 0x92, 0xb0, 0x6f, 0xdf, 0xb5, 0x53, 0x45, - 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0x4f, 0x19, 0x47, 0x92, 0x28, 0x11, 0xbc, 0xcd, 0x1b, 0x33, 0x0e, 0xaf, 0xda, - 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, - 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, - 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x0b, 0x89, 0x4b, 0x88, 0x97, 0xf9, 0x6a, 0x9a, 0x46, - 0xc1, 0xa3, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, - 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, - 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, - 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, - 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0xd7, 0x42, 0x75, 0xb0, 0x2d, 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, - 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, - 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, - 0xf8, 0xab, 0xcc, 0xc3, 0xb4, 0x9a, 0x95, 0x60, 0xce, 0x37, 0x50, 0x89, 0xf1, 0x64, 0x79, 0xc5, 0x37, 0x2e, 0x56, - 0x62, 0x32, 0x5b, 0xce, 0x27, 0x6b, 0x49, 0x35, 0x97, 0x7b, 0x6b, 0x96, 0xb1, 0x25, 0xec, 0x1f, 0x06, 0xf9, 0xd1, - 0x81, 0x1d, 0x4d, 0x35, 0x6d, 0x12, 0x60, 0x32, 0x9d, 0x73, 0x3e, 0xbc, 0x44, 0x34, 0x59, 0x9d, 0xba, 0x93, 0xa9, - 0x6a, 0x07, 0xd7, 0xe4, 0x4c, 0x4e, 0x8f, 0xd4, 0x53, 0xad, 0x7b, 0xc9, 0x47, 0xdb, 0x61, 0x35, 0xda, 0xfa, 0x01, - 0xb8, 0x75, 0x0a, 0x3b, 0x7d, 0x37, 0xac, 0x46, 0x3b, 0x5f, 0xc3, 0xee, 0x92, 0x42, 0xa0, 0xfa, 0x52, 0xd6, 0x64, - 0x2e, 0x5e, 0x17, 0xf7, 0x5e, 0xc1, 0x9e, 0xf8, 0x03, 0xfd, 0xab, 0x64, 0x4f, 0x7c, 0x9b, 0xc9, 0xf5, 0xb7, 0xb4, - 0x6b, 0x34, 0x66, 0x3a, 0x5e, 0xbb, 0x02, 0x2b, 0x34, 0x40, 0x7e, 0xc1, 0x8e, 0xf6, 0x2a, 0x07, 0x81, 0x00, 0xdd, - 0x4b, 0x70, 0x14, 0x05, 0x44, 0x4d, 0xab, 0xca, 0xa3, 0xd3, 0xbd, 0xbf, 0xc7, 0x37, 0x42, 0xc0, 0x26, 0x4f, 0xad, - 0x7b, 0xcb, 0xd8, 0x3f, 0x1c, 0x20, 0x84, 0x5e, 0x4e, 0xbf, 0xd1, 0x96, 0xd5, 0xa3, 0x1d, 0xcb, 0x7d, 0xc3, 0xa8, - 0xa7, 0x60, 0x0c, 0x43, 0x17, 0x56, 0x31, 0x92, 0x67, 0x40, 0xd6, 0xf8, 0x0d, 0xa2, 0x0b, 0x58, 0xf4, 0x7a, 0x9f, - 0x8e, 0x68, 0x10, 0x01, 0x95, 0x5e, 0x73, 0xd4, 0x22, 0x9f, 0xab, 0x42, 0xf4, 0xde, 0x5b, 0x3b, 0x6f, 0x66, 0x24, - 0xcb, 0xa4, 0x91, 0x6a, 0xb7, 0xb2, 0x58, 0x57, 0xde, 0xec, 0x84, 0x74, 0x31, 0xc7, 0x50, 0x19, 0x3c, 0x0e, 0x40, - 0xe9, 0xf9, 0xef, 0xd0, 0x2b, 0x19, 0x32, 0xcd, 0x12, 0xcd, 0xec, 0xae, 0xf1, 0x27, 0xab, 0xd4, 0x8b, 0x11, 0x31, - 0x1b, 0xd8, 0x42, 0xdc, 0x16, 0x95, 0x6e, 0x8b, 0x42, 0xd9, 0xa2, 0x48, 0x1f, 0x6a, 0x67, 0xba, 0x33, 0x0b, 0x9f, - 0x55, 0xd6, 0x4a, 0xc9, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, 0x40, 0x85, 0x90, 0xbf, 0x40, 0x44, 0x24, - 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, 0x46, 0x79, 0xc9, 0x93, 0xa3, 0x01, 0xa9, - 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xba, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, - 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, - 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, - 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, - 0xe9, 0xd9, 0x7f, 0xa4, 0x6e, 0xcf, 0xca, 0xc9, 0x5e, 0x74, 0x4e, 0xf6, 0xe9, 0x6c, 0x1e, 0x08, 0x2e, 0x77, 0xee, - 0xf3, 0x7c, 0xaa, 0xa7, 0x5d, 0xe5, 0x07, 0xad, 0x21, 0xb2, 0xc6, 0xae, 0xea, 0x5e, 0x57, 0xb0, 0x80, 0x25, 0xb8, - 0x5b, 0x2f, 0xcd, 0x7f, 0xc3, 0xee, 0xef, 0x05, 0xbd, 0x34, 0xff, 0x9d, 0xfe, 0xa4, 0x00, 0x0e, 0x40, 0x63, 0x6a, - 0xb7, 0xc0, 0x43, 0x0c, 0x15, 0x14, 0xee, 0x66, 0xe5, 0xdc, 0xab, 0x01, 0x0e, 0x93, 0xf4, 0x0d, 0xad, 0x5e, 0x69, - 0xb1, 0xeb, 0x65, 0xb2, 0x57, 0x80, 0x87, 0x2a, 0xe4, 0xe1, 0xe1, 0x10, 0x75, 0x0c, 0x3b, 0xa8, 0x23, 0x60, 0xd8, - 0x43, 0x68, 0x6c, 0x81, 0xe7, 0xe3, 0x87, 0x8c, 0xef, 0x05, 0xa8, 0x8d, 0x10, 0x1e, 0xaf, 0x16, 0x65, 0x88, 0x2d, - 0x7b, 0x85, 0x54, 0x52, 0xaf, 0x05, 0xa2, 0x8c, 0x56, 0x01, 0x6d, 0xb5, 0xc7, 0x2c, 0x8d, 0x1f, 0x21, 0x54, 0x2c, - 0xf5, 0x31, 0x84, 0x06, 0x0e, 0xbf, 0xc3, 0x01, 0x24, 0xf8, 0x92, 0x6b, 0xb2, 0xb9, 0x57, 0xf9, 0x1d, 0xed, 0xf3, - 0x87, 0xc3, 0xf9, 0x25, 0x82, 0xd2, 0xa5, 0xf0, 0x91, 0x4a, 0x44, 0xf5, 0x14, 0x37, 0x25, 0x64, 0xb3, 0x64, 0xa5, - 0x1f, 0xfc, 0x43, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, - 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, - 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, - 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, - 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, - 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, - 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, - 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, - 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, - 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, - 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, 0xe0, 0x4f, 0xc5, 0x68, 0x5d, 0x10, 0x20, - 0xb2, 0xd9, 0xbe, 0x3e, 0x54, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, - 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0xbd, 0xbd, 0xfd, 0x69, 0x90, 0x9d, 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, - 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, - 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0x4b, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, - 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, - 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, - 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, - 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, - 0x46, 0x69, 0xf5, 0xb3, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, - 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xeb, 0x34, 0xd8, 0x61, 0xa2, 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, - 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, - 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, - 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, - 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x6b, 0x8b, 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0xcf, - 0x8b, 0xed, 0x9b, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x67, 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, - 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, - 0x1c, 0xc7, 0x1f, 0xa1, 0x82, 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, - 0x59, 0xbf, 0x2f, 0x7f, 0x51, 0x17, 0x5d, 0x64, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, - 0xcf, 0x93, 0x69, 0xf2, 0x38, 0x0f, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc2, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, - 0xe9, 0x8b, 0xcf, 0x2b, 0x3f, 0xd0, 0xd9, 0x73, 0x93, 0x0c, 0x6f, 0x56, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, - 0x9f, 0x9d, 0xc1, 0xc6, 0xb9, 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x34, 0xc3, 0x75, 0xa9, 0xda, - 0xe8, 0xa3, 0x10, 0x9d, 0x43, 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x65, 0x52, 0x69, 0x23, 0x01, 0x74, - 0x0f, 0x93, 0x06, 0x5b, 0x0c, 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0x43, 0x25, 0x71, 0x68, 0x59, - 0x24, 0xff, 0xde, 0xf5, 0xf4, 0x15, 0x52, 0x77, 0xb2, 0x40, 0x66, 0x8c, 0x67, 0x79, 0xfc, 0x09, 0x08, 0xb3, 0x41, - 0x1b, 0x15, 0x85, 0x10, 0xb2, 0x41, 0x0c, 0x1a, 0xcf, 0xf2, 0xf8, 0xb9, 0xa2, 0xf1, 0x90, 0x8f, 0x22, 0x5f, 0xfd, - 0x55, 0xea, 0xbf, 0x42, 0x9f, 0x99, 0xe0, 0x11, 0xaa, 0x89, 0xfe, 0xdd, 0xf3, 0xd9, 0x1d, 0xa8, 0x0d, 0xa3, 0x30, - 0x33, 0xe5, 0x57, 0xbe, 0x29, 0xce, 0x5e, 0x7f, 0x45, 0x57, 0xd9, 0xd6, 0xfd, 0xe8, 0xe5, 0x11, 0x81, 0xb5, 0x31, - 0xba, 0xe2, 0xc6, 0x00, 0x72, 0x98, 0xbc, 0x5f, 0x51, 0x5a, 0x0e, 0x69, 0x10, 0x3a, 0x68, 0x08, 0xa3, 0x25, 0xd1, - 0x07, 0x12, 0x8b, 0x18, 0xc3, 0x0b, 0xf1, 0x8c, 0xd4, 0x64, 0xa2, 0x21, 0x5e, 0x11, 0xfb, 0x21, 0x5a, 0x72, 0x6a, - 0xa2, 0x1b, 0x61, 0x8a, 0x81, 0xc4, 0xce, 0x20, 0x39, 0x49, 0x6a, 0xe5, 0x17, 0xcf, 0x24, 0x61, 0x89, 0x9d, 0x87, - 0x18, 0x4c, 0x6a, 0xe9, 0x4e, 0x6f, 0xaa, 0xf4, 0xfc, 0x48, 0xcb, 0x41, 0xfb, 0x00, 0xec, 0x52, 0xd2, 0xfb, 0x27, - 0x85, 0x22, 0xde, 0x87, 0x71, 0x0c, 0xe1, 0x5b, 0x44, 0x75, 0x05, 0xce, 0xb5, 0x02, 0x8d, 0xd5, 0xc0, 0x43, 0x33, - 0xab, 0xe6, 0x43, 0x4e, 0x3f, 0x95, 0x96, 0x3f, 0x46, 0x34, 0x36, 0x5a, 0x37, 0x87, 0xc3, 0x9e, 0x56, 0xbd, 0x74, - 0x0e, 0xba, 0x6c, 0x26, 0x31, 0x71, 0x03, 0xe9, 0xfa, 0xd1, 0x6f, 0x26, 0xec, 0x45, 0x54, 0xc8, 0xa5, 0x10, 0x14, - 0xb4, 0x3a, 0x10, 0x38, 0x14, 0xde, 0xa2, 0xcc, 0x17, 0x31, 0x6d, 0x20, 0x0c, 0x3e, 0x3f, 0x90, 0x9f, 0x6f, 0x0a, - 0x52, 0xb1, 0x63, 0x5d, 0xfb, 0xfd, 0x65, 0xe9, 0x01, 0x9e, 0x9c, 0x49, 0xf2, 0xb4, 0x19, 0xc2, 0x8a, 0x00, 0x1a, - 0xb3, 0x9a, 0x2c, 0x4e, 0xb8, 0x32, 0x87, 0x2f, 0x2b, 0xaf, 0x64, 0x29, 0x53, 0xe7, 0xa9, 0x5e, 0x00, 0x51, 0xc7, - 0x1b, 0xb4, 0x22, 0xf5, 0x2b, 0x74, 0xf6, 0x9a, 0x95, 0x90, 0xf1, 0xf0, 0x9c, 0xf3, 0x74, 0x74, 0xcf, 0x12, 0x1e, - 0xe1, 0x5f, 0xc9, 0x44, 0x1f, 0x7e, 0xf7, 0x1c, 0x6e, 0xc6, 0x09, 0x8f, 0xdc, 0x66, 0xef, 0xab, 0x70, 0x05, 0x37, - 0xd3, 0x02, 0x90, 0xdc, 0x82, 0xa4, 0x09, 0x28, 0x21, 0x91, 0x09, 0x99, 0x35, 0x25, 0x7f, 0x6d, 0x69, 0x1b, 0xac, - 0x61, 0xd2, 0x79, 0xc0, 0x8b, 0x56, 0x1f, 0xad, 0x26, 0xda, 0x65, 0x96, 0xcf, 0x87, 0x38, 0x43, 0x35, 0xc7, 0xdd, - 0x19, 0xfc, 0x1c, 0xf0, 0x8a, 0x55, 0x4d, 0x3a, 0xda, 0x0d, 0xb8, 0xf0, 0xe4, 0x3a, 0x4f, 0x47, 0x5b, 0xfc, 0x25, - 0xf7, 0x07, 0x80, 0x0e, 0xa6, 0x2e, 0x81, 0x3f, 0x55, 0x5b, 0x4d, 0xa5, 0x7e, 0x6e, 0xed, 0xd7, 0x75, 0x67, 0xb5, - 0x72, 0xcf, 0xba, 0x0c, 0xed, 0x91, 0x21, 0x67, 0xcc, 0x80, 0x3f, 0x67, 0x2c, 0xf9, 0x73, 0xc6, 0x8a, 0x3f, 0x67, - 0xdc, 0x18, 0x19, 0x40, 0x09, 0xee, 0x25, 0x7f, 0xba, 0x47, 0xcc, 0x10, 0xab, 0x41, 0x25, 0xb0, 0xb2, 0x94, 0x73, - 0x1f, 0x39, 0xc5, 0x94, 0x53, 0x86, 0x97, 0x4e, 0x67, 0xee, 0x40, 0xce, 0x83, 0x99, 0x3b, 0x4c, 0xf6, 0xfa, 0xdc, - 0x88, 0x63, 0x69, 0x4c, 0x8a, 0x0a, 0xd2, 0x39, 0x1d, 0x6e, 0x5e, 0x1d, 0xe7, 0x09, 0xcb, 0xf8, 0xb8, 0x7d, 0xa6, - 0x40, 0x88, 0x2d, 0x9e, 0x21, 0x91, 0x52, 0x35, 0xcb, 0x6d, 0xfe, 0x70, 0xa8, 0x47, 0xf7, 0x7a, 0xa7, 0x87, 0x5f, - 0x09, 0xfb, 0x39, 0xf3, 0xec, 0x13, 0x04, 0x30, 0x49, 0xe4, 0x99, 0x84, 0xa3, 0x1f, 0xcb, 0xd1, 0xdf, 0x34, 0xfc, - 0x79, 0x86, 0xea, 0xee, 0x10, 0x98, 0xd8, 0xb2, 0x03, 0x87, 0xe0, 0x74, 0x55, 0x89, 0x04, 0x1c, 0x6c, 0x36, 0x2c, - 0xd2, 0x7b, 0x3c, 0xc4, 0xf9, 0xa0, 0xf0, 0x11, 0x1a, 0x66, 0xf4, 0x7e, 0x7f, 0x23, 0xbc, 0x4a, 0xb6, 0xf2, 0x70, - 0x48, 0x2c, 0x0d, 0x90, 0xa3, 0x8f, 0xa3, 0x3d, 0x4a, 0xa8, 0xfd, 0xa8, 0xd6, 0x9b, 0x4a, 0x3d, 0xc8, 0xcd, 0x2e, - 0x24, 0x06, 0x15, 0x4b, 0xf5, 0xe9, 0x95, 0xea, 0x43, 0xcd, 0x92, 0x43, 0xaa, 0xe3, 0x3e, 0x15, 0xa3, 0xb5, 0x9c, - 0x10, 0xe0, 0x3a, 0x48, 0x34, 0x3a, 0x00, 0xc6, 0xd9, 0x66, 0xcb, 0x4b, 0x6d, 0x9d, 0x28, 0x1d, 0xc7, 0xb9, 0x3e, - 0x8e, 0x0f, 0x07, 0x29, 0x66, 0x5c, 0x1e, 0x89, 0x19, 0x97, 0x0d, 0xc0, 0x9b, 0x75, 0x1e, 0xd4, 0x87, 0xc3, 0x25, - 0x5d, 0x8a, 0x4c, 0x67, 0x1b, 0xe5, 0x67, 0x3d, 0xba, 0x7f, 0x9c, 0xa0, 0xb9, 0xb7, 0xc2, 0xde, 0x8b, 0x64, 0x7b, - 0x26, 0xeb, 0xd4, 0xcb, 0xc8, 0xa7, 0x17, 0xee, 0xd9, 0x25, 0x57, 0x3f, 0xac, 0xbe, 0x9e, 0xfe, 0x26, 0xbc, 0x88, - 0x55, 0xb4, 0x5b, 0x97, 0x4c, 0xd8, 0x5b, 0x4a, 0x25, 0xad, 0xf2, 0xf2, 0xe9, 0xc6, 0x0f, 0x30, 0x33, 0xed, 0xe9, - 0x83, 0x6c, 0x44, 0xf5, 0x67, 0x25, 0x6a, 0x65, 0x98, 0x2c, 0x9c, 0x97, 0x4c, 0x3d, 0x19, 0xf0, 0x98, 0x95, 0x3c, - 0x92, 0x9d, 0xde, 0x18, 0x04, 0x01, 0xac, 0x73, 0xd2, 0xaa, 0x33, 0x8e, 0x46, 0xab, 0xca, 0xc5, 0xe9, 0x2a, 0x17, - 0x18, 0x6e, 0xb7, 0x66, 0x1b, 0x55, 0x67, 0xb9, 0xa9, 0x55, 0xca, 0x77, 0x00, 0x1f, 0xcb, 0x2a, 0x17, 0x74, 0x4c, - 0x99, 0x3a, 0x6f, 0x20, 0x18, 0x5b, 0xd5, 0xb8, 0x70, 0x6a, 0x5c, 0xf0, 0x88, 0xda, 0xdd, 0x34, 0xf5, 0x68, 0x0b, - 0x2c, 0xa5, 0xa3, 0x1d, 0x2f, 0x51, 0xa5, 0xf0, 0x0f, 0xc1, 0xf7, 0x61, 0x1c, 0x3f, 0x2f, 0xb6, 0xea, 0x40, 0xbc, - 0x29, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, - 0x92, 0xc2, 0xb9, 0xf9, 0xf3, 0x70, 0xa0, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, - 0xee, 0x44, 0x09, 0x8e, 0x5c, 0xf2, 0xaf, 0xc3, 0x41, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0xdb, 0x7f, 0x0d, 0xc6, 0x0c, - 0x5d, 0x9a, 0x80, 0x65, 0x63, 0x24, 0xff, 0x6a, 0x9a, 0x79, 0xc3, 0x64, 0xcd, 0x14, 0x8e, 0x43, 0xc3, 0x08, 0x69, - 0x40, 0xb7, 0x41, 0x6d, 0x78, 0x32, 0xdf, 0x54, 0xe5, 0x57, 0x77, 0xa4, 0xda, 0x0f, 0x86, 0x97, 0x13, 0x71, 0x4e, - 0x97, 0x24, 0xf5, 0x54, 0x42, 0x49, 0x08, 0x76, 0xe9, 0x03, 0x39, 0xb1, 0x02, 0xb2, 0x96, 0xb1, 0xfc, 0x56, 0x0f, - 0x08, 0xfd, 0xa7, 0xdd, 0x7a, 0xa1, 0xff, 0x34, 0xcd, 0x16, 0xea, 0xfa, 0xc3, 0xe4, 0xbe, 0xa3, 0xd7, 0x1f, 0x1c, - 0xde, 0xa9, 0xab, 0x8a, 0xab, 0x78, 0x54, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8a, 0x4d, 0xad, 0x96, 0xa7, 0xe3, - 0x30, 0x02, 0x33, 0x82, 0x02, 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xac, 0xe4, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, - 0x71, 0x3e, 0x6e, 0x81, 0x4a, 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0x9f, 0x55, 0x36, 0x76, 0x0b, 0xe4, 0x90, - 0x64, 0xb2, 0xb8, 0x1d, 0xdd, 0x88, 0x65, 0x51, 0x8a, 0xd7, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, - 0x89, 0xd2, 0xde, 0x44, 0x9a, 0xa0, 0xfb, 0x96, 0xad, 0x00, 0x64, 0x00, 0x45, 0x5d, 0xed, 0xd6, 0xe7, 0xfc, 0x1c, - 0x49, 0x33, 0x1c, 0x46, 0xb7, 0x4f, 0x6f, 0x83, 0xdb, 0xc1, 0x25, 0x6a, 0xa5, 0x2f, 0x59, 0xdc, 0xc2, 0xa0, 0xda, - 0x9b, 0x25, 0x1c, 0xd4, 0xcc, 0x5a, 0x1b, 0x81, 0x60, 0xb2, 0x87, 0x82, 0x8a, 0xb9, 0x82, 0x7d, 0x50, 0xb0, 0x96, - 0xbc, 0x0e, 0x0e, 0xb7, 0xf6, 0x65, 0xa5, 0xb8, 0x78, 0x72, 0x91, 0xb4, 0x2e, 0x2c, 0xe5, 0xc5, 0x93, 0x06, 0x0c, - 0x2e, 0x47, 0xd8, 0x54, 0x60, 0x92, 0x00, 0xd0, 0xad, 0x88, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, - 0xc1, 0x86, 0xdd, 0xc3, 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, - 0xe6, 0x5f, 0x33, 0x2f, 0x52, 0x02, 0x6e, 0x86, 0x28, 0x5f, 0x1b, 0x38, 0x99, 0xf4, 0xe4, 0x5a, 0xb2, 0x18, 0xb0, - 0xa0, 0xc1, 0x77, 0xd4, 0xfa, 0x3b, 0x93, 0x7f, 0xe3, 0xe9, 0xa1, 0x1f, 0xfc, 0x9a, 0x79, 0x4b, 0x9f, 0xbd, 0xad, - 0x64, 0xb4, 0x26, 0x89, 0xf2, 0xea, 0xe1, 0x12, 0xe4, 0x86, 0xe5, 0xe8, 0x9e, 0x2d, 0x41, 0x9c, 0x58, 0x8e, 0x12, - 0xca, 0xe8, 0x0a, 0xf7, 0x2a, 0xb3, 0x65, 0x22, 0x90, 0xe2, 0xc0, 0x52, 0xca, 0xbd, 0xc5, 0x3a, 0x58, 0xe2, 0xfe, - 0x44, 0x72, 0x01, 0x25, 0x0f, 0xa0, 0x5c, 0x29, 0x20, 0xe0, 0xd3, 0x01, 0x94, 0x2f, 0xe5, 0x45, 0xf8, 0x13, 0x27, - 0x6a, 0xb0, 0x1c, 0xdd, 0x37, 0xec, 0x67, 0x2f, 0xb4, 0xec, 0x0f, 0xb7, 0x5a, 0xd3, 0xb0, 0xe2, 0xb7, 0x30, 0x2d, - 0x26, 0x6e, 0x5f, 0xae, 0xec, 0xaa, 0xf8, 0x6c, 0xa5, 0xce, 0x6e, 0x6a, 0x48, 0xc2, 0xbe, 0x21, 0xab, 0x00, 0x07, - 0xab, 0x22, 0xee, 0x59, 0x97, 0xfb, 0x30, 0xfa, 0xb2, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, - 0x65, 0xa2, 0x13, 0x2d, 0x04, 0x57, 0x60, 0x10, 0xb8, 0x13, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, - 0x12, 0x42, 0xaa, 0xfb, 0x19, 0xa8, 0xed, 0xc4, 0x5d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, - 0xba, 0xc5, 0xa6, 0xab, 0xcd, 0xea, 0x23, 0x3a, 0x97, 0xb6, 0xdc, 0xfc, 0x84, 0x2d, 0xd6, 0x0a, 0x94, 0x4d, 0x48, - 0xda, 0xce, 0x79, 0x8e, 0xb2, 0x09, 0x2d, 0xed, 0x3d, 0xf5, 0xa8, 0x50, 0x9d, 0x6c, 0xbd, 0x54, 0x4d, 0x2d, 0xc2, - 0x6a, 0x71, 0x51, 0xf9, 0x01, 0xe8, 0xa6, 0xd2, 0xea, 0x59, 0x5d, 0xa3, 0x29, 0xd4, 0x6a, 0xe1, 0xb8, 0xd1, 0xce, - 0xa6, 0xcb, 0xf4, 0x16, 0x71, 0x56, 0xa5, 0x1d, 0xfa, 0x97, 0x4c, 0xbb, 0x5e, 0x76, 0xf4, 0x9b, 0x71, 0x75, 0x81, - 0x0b, 0xb1, 0x01, 0x9f, 0x73, 0x7f, 0x79, 0xbd, 0x27, 0x71, 0xcf, 0x3f, 0x1c, 0x90, 0x3d, 0xa9, 0xfd, 0xa1, 0xfa, - 0xd8, 0x15, 0x0c, 0x59, 0x18, 0xa5, 0xfe, 0x22, 0xe5, 0xbd, 0x47, 0x38, 0xee, 0x9f, 0xab, 0x1e, 0xfb, 0x57, 0xc6, - 0xf7, 0x75, 0xb1, 0x89, 0x12, 0x8a, 0x6a, 0xe8, 0xad, 0x8a, 0x4d, 0x25, 0xe2, 0xe2, 0x3e, 0xef, 0x31, 0x4c, 0x86, - 0xb1, 0x90, 0xa9, 0xf0, 0xa7, 0x4c, 0x05, 0x8f, 0x10, 0x4a, 0xdc, 0xac, 0x7b, 0xa4, 0xdd, 0x84, 0x38, 0xa5, 0x5a, - 0x94, 0x32, 0x19, 0xff, 0xd6, 0x4f, 0xa0, 0x3c, 0xa7, 0x68, 0x99, 0x7e, 0x54, 0xb8, 0x4c, 0xdf, 0xac, 0x8f, 0x4b, - 0xcf, 0x44, 0xa8, 0x33, 0x17, 0x9b, 0x5a, 0xa7, 0x63, 0xec, 0x94, 0x4e, 0x6d, 0xd8, 0xd7, 0x4a, 0x71, 0x59, 0x51, - 0xf8, 0x37, 0x12, 0x59, 0xf5, 0x8c, 0x38, 0xfe, 0x7b, 0xd6, 0x3e, 0xc3, 0x2a, 0xf0, 0xcb, 0x40, 0xde, 0x2f, 0x00, - 0x3e, 0xae, 0xeb, 0x32, 0xbd, 0xd9, 0x00, 0x6d, 0x08, 0x0d, 0x7f, 0xcf, 0x47, 0x06, 0x4c, 0xf7, 0x11, 0xce, 0x90, - 0x1e, 0xea, 0x9c, 0xd3, 0x59, 0x99, 0xce, 0xb9, 0x0a, 0x6b, 0x09, 0xf6, 0x72, 0xd2, 0xe4, 0x72, 0x5d, 0x82, 0x9a, - 0x09, 0xdc, 0x3e, 0xb4, 0x47, 0x84, 0x50, 0x9b, 0xb2, 0x9a, 0x5e, 0x42, 0xcd, 0x3b, 0x39, 0xed, 0x68, 0x52, 0x82, - 0xab, 0x86, 0xce, 0xca, 0xf5, 0x5f, 0x87, 0x43, 0xef, 0x26, 0x2b, 0xa2, 0x3f, 0x7b, 0xe8, 0xef, 0xb8, 0xfd, 0x98, - 0x7e, 0x85, 0x68, 0x19, 0xeb, 0x6f, 0xc8, 0x80, 0x8e, 0x27, 0xc3, 0x9b, 0x62, 0xdb, 0x63, 0x5f, 0x51, 0x83, 0xa5, - 0xaf, 0x1f, 0x1f, 0x41, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0x5f, - 0x21, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, 0xd7, 0xb2, 0xaf, 0x7c, 0xe7, 0x02, 0x60, - 0x65, 0x9f, 0xd8, 0x70, 0x4f, 0xfa, 0x53, 0xaa, 0x0f, 0xdb, 0xdf, 0x92, 0x05, 0x14, 0x5a, 0x58, 0x4f, 0xe5, 0xec, - 0xbc, 0x2d, 0x79, 0x95, 0x4d, 0xf7, 0x6b, 0xd8, 0xa3, 0xee, 0xd0, 0x6b, 0x2a, 0x38, 0xbf, 0x34, 0xa3, 0xf7, 0xc5, - 0x50, 0xa8, 0x8e, 0x3a, 0x77, 0x90, 0xdb, 0xd2, 0xba, 0xe4, 0xfc, 0x66, 0xe5, 0x8e, 0xc2, 0xfc, 0x2e, 0x04, 0xcf, - 0xb0, 0xee, 0xdd, 0xc5, 0x79, 0xef, 0x1f, 0xad, 0x39, 0xf2, 0xaf, 0x6c, 0x96, 0x22, 0x16, 0xc9, 0x1c, 0xac, 0x7e, - 0xe8, 0xe7, 0xb1, 0xdf, 0x06, 0x39, 0x1c, 0x37, 0x0d, 0xe8, 0xb0, 0x21, 0xb3, 0xf6, 0x25, 0x02, 0xa7, 0x1a, 0x41, - 0x9a, 0x9a, 0xa0, 0x66, 0x79, 0x88, 0xc4, 0x76, 0x29, 0xdb, 0x06, 0xb9, 0xee, 0x82, 0x69, 0x8e, 0xb4, 0x67, 0xf0, - 0xbe, 0x49, 0x93, 0x54, 0x68, 0x16, 0x8d, 0xae, 0x64, 0xfc, 0x3b, 0xd2, 0x66, 0x4a, 0xf6, 0xd8, 0x1a, 0x78, 0x2f, - 0x41, 0x39, 0x19, 0xa6, 0x18, 0xbe, 0xe3, 0xeb, 0x9d, 0x47, 0x17, 0xf1, 0xb7, 0x63, 0xb6, 0x49, 0xd9, 0x11, 0x4c, - 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xdd, 0x4d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, 0x53, 0x69, 0x73, 0x85, 0x6e, - 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, 0xe2, 0xb7, 0x60, 0x0e, 0x63, - 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, 0x02, 0x8c, 0xbe, 0xda, 0x16, - 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, 0xd0, 0xf9, 0x7d, 0x73, 0x53, - 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xf3, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, 0xad, 0x71, 0x9a, 0xf9, 0xdf, - 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x9f, 0x21, 0x7a, 0x5f, 0xb7, 0x72, 0x55, 0x6a, 0x37, - 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, 0x39, 0xff, 0x5c, 0xf5, 0xfb, - 0xde, 0x67, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, 0x6d, 0x4a, 0xd8, 0x90, 0xdb, - 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x6f, 0x39, 0xdf, 0xaf, 0x85, 0xbc, 0x59, 0xc9, - 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, - 0xfe, 0x8e, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, 0x5a, 0x82, 0x76, 0xc1, 0xa6, - 0xb0, 0x3a, 0x79, 0x68, 0xc8, 0xfb, 0xfd, 0x97, 0xb9, 0xd7, 0xe2, 0x75, 0x37, 0x70, 0x97, 0xa5, 0x87, 0x10, 0xc0, - 0x5a, 0x06, 0xca, 0x38, 0xc2, 0xa4, 0x8b, 0xbc, 0x46, 0xd9, 0x74, 0x22, 0xf0, 0x31, 0xcb, 0xae, 0x9c, 0x64, 0x1a, - 0x60, 0x46, 0x35, 0x85, 0x99, 0x00, 0x23, 0xf5, 0x01, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, - 0x65, 0x1c, 0xc5, 0x4c, 0x00, 0xb0, 0xf9, 0x00, 0xf2, 0x15, 0x5d, 0x1d, 0x92, 0x56, 0xaa, 0xbc, 0x5f, 0x67, 0x44, - 0x46, 0x93, 0x10, 0xcd, 0x6f, 0xe1, 0x81, 0x7d, 0xdb, 0xcc, 0xa8, 0x52, 0xcf, 0xa8, 0xca, 0x67, 0x38, 0x2c, 0x85, - 0x63, 0xc4, 0xff, 0x5b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, - 0x73, 0x38, 0xf4, 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0x14, 0x0f, 0x75, 0x65, 0x4d, 0x6b, 0x25, 0x05, 0x4e, 0x45, - 0x8d, 0x10, 0x21, 0xbc, 0x7f, 0x00, 0xcf, 0x6a, 0xea, 0xfb, 0x8d, 0x65, 0xa2, 0xfb, 0x92, 0x01, 0xe5, 0x0f, 0xc8, - 0xd7, 0x95, 0x14, 0x67, 0xd2, 0xe4, 0x21, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xb6, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, - 0x86, 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x3d, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xc7, 0x92, 0xa5, 0xd1, 0xc2, - 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x31, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, 0xea, - 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x0e, 0xd6, 0x93, 0x57, 0x5e, 0xe9, 0x4f, 0x85, 0x9c, 0xc3, - 0x46, 0x22, 0x28, 0xfc, 0x00, 0x57, 0x83, 0x95, 0x02, 0x06, 0x53, 0xdf, 0xc2, 0xd7, 0xc4, 0x73, 0x14, 0x3c, 0x0a, - 0xbb, 0x18, 0x5b, 0x2b, 0xdf, 0xf9, 0xa4, 0xa0, 0xdc, 0xb3, 0x62, 0xce, 0x2b, 0xe0, 0x5c, 0x06, 0x85, 0x30, 0x1d, - 0xcf, 0xf2, 0x7f, 0x26, 0x79, 0x3d, 0xb1, 0x21, 0x40, 0x06, 0x7f, 0x4a, 0x9c, 0x96, 0xee, 0xd0, 0x9d, 0x87, 0x9e, - 0x45, 0x1c, 0x36, 0x7a, 0xb4, 0x2e, 0x8b, 0x6d, 0x8a, 0x7a, 0x09, 0xf3, 0x03, 0xf9, 0x79, 0x4b, 0xbe, 0x0f, 0x51, - 0xbc, 0x0d, 0xfe, 0x96, 0xb1, 0x58, 0xe0, 0x5f, 0xff, 0xcc, 0x18, 0x4d, 0xb4, 0xa0, 0x4e, 0x1a, 0x24, 0x2a, 0x16, - 0xc9, 0x04, 0x60, 0x1d, 0xb9, 0xfa, 0xf0, 0x29, 0x31, 0xde, 0x9a, 0x0d, 0x0f, 0x7c, 0xb3, 0x02, 0x9d, 0xfa, 0xdc, - 0x5d, 0xd9, 0x9e, 0xae, 0x46, 0xaa, 0xaa, 0xf1, 0xb7, 0x54, 0x55, 0xe3, 0x6f, 0x29, 0x55, 0xe3, 0xb7, 0x8c, 0xe2, - 0x77, 0x2a, 0x9f, 0x21, 0x73, 0xb2, 0x89, 0x49, 0x3a, 0x7d, 0x6f, 0x38, 0xb1, 0xcb, 0x7e, 0xeb, 0x36, 0x91, 0x67, - 0x26, 0x52, 0xc8, 0xbd, 0x01, 0xa8, 0x99, 0xf8, 0x32, 0x37, 0x9c, 0x12, 0xe7, 0xe7, 0x1e, 0xae, 0xd8, 0xb4, 0xba, - 0xa6, 0x05, 0x0b, 0x6c, 0x5e, 0x66, 0x79, 0xe6, 0x09, 0x6c, 0x9b, 0x32, 0xeb, 0x87, 0xdc, 0x03, 0x08, 0x66, 0x52, - 0x13, 0x00, 0xd2, 0x42, 0x54, 0x0a, 0x91, 0x5f, 0xe3, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, - 0xdf, 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0x7f, 0xc9, 0x82, 0x34, 0x91, 0xab, 0xf4, 0x9f, 0x6e, - 0x90, 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, - 0x55, 0xca, 0x23, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0xbf, 0x97, 0x7a, 0x1a, 0xdd, 0x17, - 0x7b, 0x30, 0x06, 0xef, 0x00, 0xf0, 0x4c, 0x87, 0x06, 0x48, 0xdf, 0x33, 0xf2, 0x70, 0x9f, 0x5b, 0xf2, 0x93, 0xca, - 0xda, 0x24, 0x61, 0x45, 0xb1, 0x19, 0xc6, 0x08, 0x25, 0xe3, 0x34, 0xb6, 0x7e, 0xbf, 0xaf, 0xfe, 0xde, 0x61, 0x14, - 0x15, 0x15, 0x77, 0x8c, 0x46, 0x65, 0x55, 0x8f, 0xb6, 0x83, 0xc3, 0xe1, 0x3c, 0xb7, 0x71, 0xb4, 0xf5, 0x0a, 0xd8, - 0x5b, 0xa1, 0x52, 0xf6, 0x4a, 0x84, 0xe5, 0x87, 0x2b, 0xbf, 0xdf, 0x87, 0x7f, 0x65, 0xa4, 0x85, 0xe7, 0x4f, 0xf1, - 0xd7, 0xa2, 0x2e, 0x30, 0x3c, 0x83, 0xd6, 0x68, 0x05, 0xc1, 0x04, 0xff, 0xec, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x80, - 0x6e, 0x05, 0x7a, 0xd0, 0x70, 0x12, 0x27, 0xed, 0x0b, 0x89, 0xba, 0xbd, 0xd5, 0x69, 0xf4, 0x67, 0xc5, 0x72, 0x5e, - 0xc0, 0xe4, 0x70, 0x43, 0x9f, 0x56, 0xe1, 0xf6, 0x13, 0x3c, 0x7d, 0x0d, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, - 0xb8, 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x08, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, - 0x57, 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xaa, 0x56, 0xda, 0x59, - 0x94, 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x65, 0x82, 0x3e, 0xaf, 0xe4, 0x04, - 0x57, 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0xd3, 0x4b, 0xba, 0x21, 0xa3, 0xe7, 0xbc, - 0xe7, 0x45, 0xc3, 0xd0, 0xbf, 0xf0, 0x4a, 0x08, 0xdf, 0xc4, 0x6d, 0x1b, 0xa5, 0xb0, 0xbf, 0x09, 0x2c, 0x3e, 0x61, - 0xaf, 0xbc, 0xa5, 0x3f, 0x1d, 0x07, 0xe1, 0x10, 0xb9, 0xa1, 0x62, 0x0e, 0xec, 0x69, 0xc0, 0x62, 0x13, 0x5f, 0x6d, - 0x26, 0xf1, 0x60, 0xe0, 0xeb, 0x8c, 0xc5, 0x2c, 0x06, 0x1a, 0xe4, 0x78, 0x70, 0x39, 0xd7, 0x27, 0x84, 0x7e, 0x18, - 0x51, 0x39, 0x2a, 0xd0, 0x39, 0x88, 0x06, 0x4b, 0xc0, 0x53, 0x6f, 0x65, 0x83, 0x24, 0xe3, 0x18, 0x92, 0xb8, 0xd6, - 0x24, 0xd5, 0xe1, 0x84, 0xd6, 0x81, 0x8e, 0xab, 0x0b, 0xe8, 0x7c, 0x5c, 0xf7, 0x3e, 0x5e, 0x0d, 0x17, 0x54, 0xfa, - 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0x70, 0xb1, 0x0a, 0xb7, 0xaf, 0xe5, 0x03, 0xc7, 0x1d, 0x95, - 0x34, 0x04, 0x06, 0x6f, 0x0f, 0xdd, 0xcd, 0x8c, 0x77, 0xc8, 0xd1, 0x61, 0x9c, 0xc9, 0x21, 0x56, 0xad, 0xb8, 0x90, - 0xde, 0x08, 0xbe, 0x5d, 0x28, 0xc6, 0xb2, 0xb1, 0x4b, 0x43, 0x51, 0xf8, 0x37, 0x00, 0x3b, 0xd4, 0xfe, 0x4a, 0x25, - 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, 0x89, 0x3f, 0xb2, 0xc6, 0xba, - 0xe9, 0xfa, 0x82, 0xa9, 0x6a, 0x98, 0x74, 0x3b, 0x93, 0x58, 0x4e, 0x24, 0xa9, 0xed, 0x3e, 0x22, 0x06, 0x03, 0x1f, - 0x6c, 0xc4, 0x34, 0x13, 0xe1, 0x88, 0x47, 0x25, 0xb2, 0xe8, 0xf2, 0xdb, 0x88, 0x92, 0xb6, 0x2f, 0x2b, 0xb2, 0x05, - 0xc1, 0xf4, 0x24, 0xfa, 0x20, 0x49, 0x39, 0x15, 0x89, 0x34, 0x23, 0x04, 0xf8, 0xf1, 0xa4, 0xbc, 0xd2, 0x9f, 0x83, - 0xa6, 0x95, 0xe0, 0x25, 0x83, 0xe4, 0x91, 0xf8, 0x99, 0x14, 0xcc, 0x62, 0xac, 0x1a, 0x0c, 0xb0, 0x9c, 0xea, 0xb1, - 0x63, 0x92, 0xfe, 0x5b, 0xa7, 0x13, 0xf6, 0x33, 0x2f, 0xb7, 0xb5, 0xbc, 0x69, 0xee, 0x3d, 0xf3, 0x2a, 0x96, 0x6a, - 0x58, 0x06, 0xfd, 0xd7, 0x44, 0xbb, 0x60, 0x6b, 0xcb, 0x98, 0xb0, 0xea, 0x07, 0x90, 0xf6, 0x48, 0x97, 0x57, 0x0d, - 0x73, 0x26, 0x78, 0x74, 0x61, 0xcd, 0x83, 0xe8, 0x42, 0xf8, 0xc8, 0x65, 0x37, 0x49, 0xae, 0xc6, 0x13, 0x3f, 0x1c, - 0x0c, 0x14, 0x00, 0x2d, 0xad, 0x93, 0x62, 0x10, 0x3e, 0x16, 0x72, 0x20, 0x8d, 0x8e, 0xaa, 0x00, 0x8b, 0x65, 0x76, - 0x55, 0x4e, 0xb2, 0xc1, 0xc0, 0x07, 0xb1, 0x31, 0xb1, 0x1b, 0x9a, 0xcd, 0x7d, 0x76, 0xa2, 0x20, 0xab, 0xcd, 0x59, - 0x6b, 0xa6, 0x5b, 0x60, 0x00, 0x30, 0x88, 0x08, 0x96, 0xfb, 0xc4, 0xc8, 0x47, 0xd4, 0xe9, 0x29, 0x8c, 0x80, 0xe0, - 0x97, 0x13, 0x81, 0xc8, 0x45, 0x02, 0xf5, 0x00, 0x33, 0x01, 0x66, 0x54, 0x31, 0xbc, 0x04, 0x76, 0xf1, 0xdc, 0xbc, - 0x62, 0xd0, 0xbf, 0x68, 0x97, 0x48, 0x34, 0x95, 0x38, 0x1a, 0x23, 0xa7, 0xd2, 0x18, 0x19, 0x10, 0xbb, 0x38, 0xfe, - 0x3d, 0xa5, 0x47, 0x41, 0xca, 0x9e, 0x57, 0x86, 0x38, 0x1c, 0xc5, 0x57, 0xb0, 0x6a, 0x1c, 0x0e, 0xb5, 0x79, 0x3d, - 0x9d, 0xd5, 0xf3, 0x81, 0x08, 0xe0, 0xbf, 0xa1, 0x60, 0xbf, 0x6a, 0x2a, 0x72, 0x83, 0xd4, 0x79, 0x38, 0xa4, 0x20, - 0x9f, 0x1a, 0xab, 0x6c, 0xe5, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0x2f, 0x6a, 0x5c, 0xb7, 0x56, 0x37, 0x14, 0x12, - 0xad, 0x69, 0x52, 0x5c, 0x55, 0x93, 0x62, 0xc0, 0x73, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, 0xe7, 0x16, 0x08, - 0x93, 0xfe, 0x56, 0xdc, 0x21, 0x55, 0xe3, 0xae, 0xad, 0x76, 0xdb, 0xca, 0x86, 0x14, 0xcd, 0x87, 0x97, 0xb0, 0x4b, - 0xa7, 0x88, 0xb6, 0x5d, 0x12, 0x7c, 0x01, 0x5a, 0x56, 0x17, 0x22, 0x8f, 0xe9, 0x57, 0xc8, 0x2f, 0xc5, 0xf0, 0xaf, - 0xd2, 0xbd, 0x39, 0xb5, 0x41, 0x0e, 0x60, 0xbb, 0xf7, 0x70, 0x3b, 0x46, 0x0f, 0x64, 0xf0, 0x46, 0xc8, 0x39, 0xe7, - 0x97, 0x53, 0x6b, 0xc6, 0x44, 0xc3, 0x82, 0x95, 0xc3, 0xc8, 0x0f, 0x90, 0xf1, 0x72, 0x0a, 0xac, 0xec, 0x47, 0x45, - 0x5c, 0xfa, 0xc3, 0xc8, 0xbf, 0x78, 0x12, 0x64, 0xdc, 0x8b, 0x86, 0x1d, 0x5f, 0x80, 0xbd, 0xfa, 0xe2, 0x09, 0x8b, - 0x06, 0xbc, 0xba, 0xaa, 0xa7, 0x59, 0x30, 0xcc, 0x58, 0x74, 0x55, 0x0c, 0xc1, 0x87, 0xf6, 0x69, 0x39, 0x08, 0x7d, - 0xdf, 0xec, 0x1c, 0xc6, 0x98, 0x2c, 0x8f, 0xb0, 0x9f, 0xc1, 0x6d, 0x57, 0x4b, 0xcc, 0x60, 0xb2, 0xb9, 0x8d, 0x98, - 0xc1, 0x96, 0xbf, 0x78, 0x62, 0xb8, 0x84, 0xaa, 0xa7, 0x52, 0xb3, 0x51, 0xa0, 0x39, 0xb9, 0x42, 0x73, 0xb2, 0x12, - 0x6a, 0xc9, 0x27, 0x15, 0x4e, 0xd8, 0xf9, 0x24, 0x57, 0x76, 0xa3, 0x31, 0x06, 0x2e, 0xda, 0x5b, 0x93, 0x30, 0x32, - 0xd3, 0x59, 0x8a, 0x06, 0x2c, 0x3c, 0x13, 0xa7, 0x34, 0x06, 0xb4, 0x2f, 0x07, 0x96, 0x36, 0xe4, 0x17, 0x39, 0x33, - 0xd0, 0x36, 0xa4, 0x34, 0x6a, 0x06, 0xfe, 0x4c, 0x4d, 0x98, 0xdf, 0xc0, 0x4a, 0x04, 0x51, 0x5d, 0x80, 0x49, 0x92, - 0x93, 0xd1, 0x48, 0x59, 0x89, 0xe4, 0x1c, 0xf0, 0x3e, 0x80, 0x27, 0x8b, 0xd8, 0xd6, 0xfe, 0x94, 0xfe, 0x57, 0x87, - 0xcf, 0xa5, 0xff, 0x58, 0x00, 0x0b, 0xb9, 0x34, 0x88, 0x0c, 0x14, 0x0e, 0xa9, 0xe5, 0x18, 0x93, 0x38, 0x9e, 0x81, - 0x2f, 0xe1, 0x02, 0x4d, 0x01, 0xfd, 0x41, 0xcd, 0x28, 0x22, 0x0b, 0x7f, 0xf5, 0xec, 0xa6, 0xae, 0xf5, 0x3c, 0x73, - 0x5e, 0x83, 0x66, 0x06, 0x42, 0x7a, 0x9c, 0xaa, 0xb7, 0x21, 0xd1, 0x79, 0xf9, 0x56, 0xbf, 0x4c, 0x88, 0x64, 0x61, - 0xe4, 0xe9, 0xfb, 0x1c, 0xcc, 0x23, 0x8a, 0xd0, 0xc1, 0x95, 0x79, 0x38, 0x9c, 0x0b, 0x0a, 0xdf, 0x51, 0x9e, 0x0f, - 0x38, 0xcd, 0x92, 0x04, 0xb4, 0x81, 0x2c, 0x37, 0x65, 0xae, 0x92, 0x96, 0xa9, 0x7b, 0x0f, 0x56, 0x82, 0x0a, 0xdd, - 0x9c, 0x82, 0x42, 0x19, 0x09, 0x4a, 0x69, 0x35, 0x08, 0xa5, 0x3a, 0x2c, 0x82, 0xc8, 0x21, 0x0b, 0x01, 0x37, 0x53, - 0xd1, 0x68, 0x49, 0xc3, 0x23, 0x9c, 0x1b, 0x28, 0x04, 0x20, 0xb1, 0xa7, 0x8a, 0x32, 0x2e, 0x87, 0x80, 0x8f, 0x12, - 0x0e, 0x71, 0xd6, 0xa4, 0x2d, 0xcf, 0x41, 0x1c, 0xcb, 0x25, 0xbf, 0xad, 0x10, 0x0c, 0x22, 0xf4, 0x19, 0xf2, 0x27, - 0xcb, 0xf9, 0x77, 0xe3, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0x9b, 0xf9, 0x04, 0xe2, 0x5b, 0x6e, - 0xe6, 0xc7, 0x18, 0x22, 0x0b, 0x7f, 0x70, 0x3b, 0x94, 0x5c, 0x51, 0xe8, 0xb2, 0x1e, 0x91, 0x22, 0x7b, 0xba, 0xe6, - 0x08, 0x82, 0x03, 0xad, 0x1a, 0x64, 0x68, 0x24, 0xbe, 0x78, 0x02, 0x59, 0x83, 0x35, 0x7f, 0x5e, 0x91, 0xb3, 0xba, - 0x3f, 0xd9, 0x40, 0x35, 0xc9, 0x64, 0xad, 0xa8, 0x9c, 0xbf, 0x5d, 0x95, 0xe5, 0xc9, 0xaa, 0x0c, 0x57, 0x83, 0xae, - 0xaa, 0x2c, 0x39, 0x52, 0x1b, 0xa0, 0x35, 0x5d, 0x21, 0x86, 0x42, 0xd6, 0x60, 0x69, 0x55, 0x65, 0x4d, 0x7d, 0x02, - 0x81, 0x3e, 0xc0, 0x32, 0x6a, 0xf6, 0xd3, 0xe1, 0x2f, 0xc1, 0x2f, 0x2a, 0x64, 0xa9, 0x4e, 0xeb, 0x4c, 0xfc, 0x16, - 0x2c, 0x19, 0xfe, 0xf1, 0x7b, 0xb0, 0x06, 0x2c, 0x01, 0xb2, 0xdc, 0x6d, 0x6c, 0xb4, 0x5e, 0x15, 0x3f, 0x57, 0xeb, - 0x8b, 0x7e, 0xeb, 0x36, 0x51, 0x2b, 0xc0, 0x08, 0x85, 0x16, 0x01, 0xb6, 0x7a, 0xe0, 0x9e, 0x82, 0x1f, 0x88, 0xe1, - 0x5c, 0x93, 0xd6, 0xd4, 0x09, 0xaf, 0xb3, 0x71, 0x24, 0xa2, 0x7a, 0x0b, 0x17, 0xf7, 0x7a, 0x6b, 0xf1, 0x37, 0x2a, - 0x10, 0x00, 0x59, 0x4c, 0xb1, 0x76, 0xde, 0x90, 0x5e, 0x19, 0x76, 0x12, 0x7a, 0x6f, 0xd8, 0x09, 0xe4, 0xc5, 0x61, - 0xa7, 0xd0, 0x25, 0xda, 0x4e, 0x91, 0x9a, 0x68, 0x3b, 0x69, 0xb1, 0x0a, 0x4b, 0x08, 0x7e, 0xd5, 0xde, 0x3a, 0xca, - 0xf6, 0x45, 0x96, 0x30, 0x6d, 0x01, 0xa3, 0xdc, 0xaa, 0xcf, 0x9c, 0x22, 0x56, 0xca, 0xde, 0xe9, 0xa4, 0xca, 0x5d, - 0xe4, 0x53, 0xab, 0x29, 0x32, 0xf9, 0xf9, 0x71, 0x8b, 0xe4, 0x93, 0xd7, 0xed, 0x86, 0xc9, 0xf4, 0x0f, 0x47, 0x5f, - 0x40, 0x57, 0x64, 0xa7, 0x4f, 0x20, 0x20, 0x53, 0x41, 0xb5, 0xba, 0x55, 0x4c, 0xf3, 0x76, 0x95, 0xdd, 0x5e, 0x28, - 0x31, 0x9c, 0xce, 0x4e, 0xc2, 0xa3, 0xcd, 0x90, 0x81, 0x43, 0x10, 0x28, 0x84, 0x8a, 0x62, 0x78, 0x04, 0x6a, 0x8d, - 0xe4, 0x03, 0xfc, 0x68, 0x77, 0x2a, 0x88, 0xd4, 0x6e, 0x2a, 0x6e, 0x9c, 0xdc, 0x74, 0xbd, 0x14, 0xa8, 0x75, 0x4a, - 0x56, 0x00, 0x25, 0x44, 0xfd, 0x49, 0x6c, 0xeb, 0x6b, 0xb8, 0x62, 0xf3, 0x7d, 0xa3, 0xe8, 0xc9, 0xf5, 0x29, 0xea, - 0x56, 0x5c, 0x9d, 0xa6, 0xad, 0xe6, 0xd8, 0x71, 0x86, 0x1c, 0x3c, 0x2b, 0x08, 0xb6, 0xa3, 0x12, 0xe5, 0x9b, 0x76, - 0xd3, 0x31, 0xb1, 0xd5, 0x3f, 0x8b, 0x6a, 0x73, 0x0b, 0x15, 0x11, 0xf1, 0x51, 0x76, 0xf3, 0xa4, 0xfd, 0x0e, 0xf6, - 0x58, 0xab, 0x41, 0x64, 0x9f, 0xc1, 0x55, 0xae, 0xd3, 0x22, 0xb7, 0x65, 0x70, 0xfe, 0xe1, 0xd5, 0xae, 0xc2, 0x26, - 0xc7, 0xba, 0xba, 0x9a, 0xa9, 0x4e, 0x2a, 0x36, 0x30, 0xd6, 0xb4, 0x96, 0x6a, 0x1e, 0x43, 0xd2, 0x5d, 0x59, 0x9c, - 0x55, 0x49, 0x37, 0x3d, 0x37, 0xce, 0x14, 0x62, 0xe0, 0x6c, 0x35, 0x5a, 0xce, 0x30, 0x44, 0xd7, 0x87, 0x59, 0xe2, - 0xb7, 0x7a, 0xca, 0x7d, 0x1e, 0x6e, 0xfd, 0xae, 0x5e, 0x70, 0x32, 0xd9, 0x4f, 0x8e, 0x73, 0xb7, 0x8b, 0xb4, 0x9f, - 0xf8, 0x36, 0xcc, 0xbf, 0xbe, 0x41, 0xdc, 0x8a, 0xfa, 0x97, 0x0a, 0x80, 0x06, 0x37, 0x79, 0x2c, 0x51, 0xea, 0xf7, - 0xaa, 0xfa, 0x41, 0xcd, 0x54, 0x4d, 0x03, 0xc1, 0x9c, 0x4a, 0x01, 0x7f, 0xb8, 0x5d, 0xb8, 0xe2, 0x11, 0x37, 0x2c, - 0x8c, 0x5f, 0xbc, 0x9a, 0x9d, 0x0a, 0x2a, 0x03, 0x37, 0xe3, 0x2f, 0x9e, 0x60, 0xa7, 0xb0, 0x56, 0x40, 0x56, 0xf8, - 0xe2, 0xe5, 0x0f, 0xbc, 0x5f, 0xf1, 0x2f, 0x5e, 0xf5, 0xc0, 0xfb, 0x88, 0xf3, 0xf2, 0x05, 0x49, 0x9d, 0x10, 0xd5, - 0xe5, 0x0b, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x05, 0x29, 0x7c, 0x82, 0xcf, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, - 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, - 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, - 0x37, 0x61, 0x1d, 0x25, 0x69, 0x7e, 0x2b, 0xa3, 0x8f, 0x64, 0xd8, 0x91, 0xbe, 0x92, 0x12, 0xed, 0xb5, 0x0a, 0xcb, - 0xd1, 0xec, 0xd7, 0x25, 0x07, 0xca, 0xeb, 0x56, 0x50, 0xbe, 0x6a, 0x02, 0xe8, 0x95, 0x6a, 0x9f, 0x81, 0x56, 0x50, - 0x58, 0x2a, 0x0f, 0x56, 0xe2, 0x5c, 0xf4, 0x59, 0x71, 0x38, 0xa8, 0x8b, 0x21, 0xa1, 0x40, 0x95, 0x38, 0x09, 0x8d, - 0x78, 0x0e, 0x17, 0x42, 0xf1, 0x34, 0xc7, 0xd8, 0x8a, 0x1c, 0x38, 0x90, 0xe1, 0x07, 0x04, 0xde, 0xcb, 0xfe, 0x15, - 0x0c, 0x86, 0x09, 0x6e, 0x64, 0xd4, 0xc9, 0x39, 0xfb, 0x82, 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, - 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, 0x9d, 0xf4, 0x4f, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, - 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, - 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, - 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, - 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, - 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, - 0x28, 0x07, 0xfb, 0x17, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, - 0x71, 0x50, 0xb1, 0xdb, 0x32, 0x8c, 0x80, 0x41, 0x1d, 0xfb, 0x1f, 0x7d, 0x36, 0x6d, 0xc8, 0x3e, 0x00, 0x54, 0xae, - 0x42, 0xc0, 0x1e, 0x80, 0x13, 0x8d, 0x70, 0x03, 0xdc, 0x6a, 0xb4, 0xa4, 0x83, 0xba, 0x2d, 0x18, 0x88, 0x96, 0xb0, - 0x91, 0xb7, 0x5d, 0x9d, 0xbe, 0x21, 0x7c, 0xa8, 0x9d, 0x94, 0x0e, 0xe5, 0x6f, 0x9e, 0xb3, 0xff, 0xd9, 0x61, 0x4d, - 0x4d, 0xf9, 0x08, 0x98, 0x39, 0x2b, 0x91, 0x57, 0x08, 0x9d, 0x22, 0xbf, 0x57, 0x75, 0x25, 0x86, 0xcb, 0x5a, 0x94, - 0x9d, 0xd9, 0xad, 0x13, 0xbd, 0x73, 0x0a, 0x6a, 0xa9, 0x6c, 0x90, 0x93, 0x54, 0x9b, 0x8f, 0xac, 0x15, 0x94, 0xa8, - 0x6b, 0x14, 0x38, 0x3e, 0xe5, 0xda, 0xfd, 0xbf, 0x73, 0x26, 0xa8, 0xd9, 0x46, 0x75, 0x7f, 0xa1, 0x9f, 0xaa, 0x9a, - 0xc4, 0x02, 0x5c, 0x4e, 0xd2, 0xbc, 0xe3, 0x11, 0x56, 0xff, 0x38, 0x59, 0x8a, 0x40, 0x9f, 0x22, 0xda, 0x95, 0x80, - 0x04, 0xed, 0xe4, 0x2c, 0x54, 0x04, 0x0a, 0xf4, 0xf5, 0xe7, 0x9b, 0x34, 0x8b, 0xe5, 0x6a, 0xb6, 0x87, 0x89, 0xb2, - 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x57, 0xa6, 0x04, 0x97, 0xe2, 0x2a, 0x2a, - 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0x4b, 0x54, 0x3b, 0x52, 0x20, 0x87, 0x92, - 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0xd7, 0x0a, 0xc1, 0xfd, 0xb5, 0x2d, 0x36, 0xaa, 0x3c, - 0xd1, 0x83, 0x4f, 0xb1, 0xfe, 0x27, 0x0b, 0x28, 0xd5, 0x7d, 0x1b, 0x9c, 0x8a, 0x47, 0xe1, 0xa6, 0x2e, 0x3e, 0x22, - 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, 0x9d, 0x3a, 0x0c, 0x1c, - 0x50, 0x13, 0x25, 0xa2, 0xd8, 0x2d, 0xe8, 0x9e, 0xe6, 0x58, 0x89, 0x67, 0xb2, 0x74, 0x90, 0x75, 0x22, 0x4d, 0xa8, - 0xdc, 0xd5, 0x55, 0x47, 0xa5, 0x52, 0x37, 0xbc, 0x4c, 0x35, 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x6c, 0xfd, - 0x56, 0xab, 0xbd, 0xb1, 0x7a, 0x54, 0xb2, 0xe6, 0x38, 0x9b, 0x90, 0x94, 0x3e, 0x61, 0xbb, 0x99, 0x74, 0xad, 0x03, - 0x4f, 0x82, 0xcb, 0xa1, 0x27, 0xa0, 0x62, 0xd0, 0xc4, 0xdb, 0x5d, 0xa0, 0x1e, 0x81, 0x67, 0xa0, 0x7c, 0xa2, 0xd6, - 0x01, 0x3f, 0xaf, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x38, 0xef, 0x14, 0x81, 0x6b, 0x57, 0x02, - 0xcf, 0x87, 0xea, 0xbd, 0x10, 0x30, 0xdc, 0x3f, 0x15, 0x2a, 0x9b, 0xdd, 0x0c, 0xe7, 0x51, 0xe3, 0xf4, 0x40, 0x7b, - 0xdb, 0xb5, 0x1e, 0xea, 0x5d, 0xb7, 0x73, 0x5b, 0xe9, 0xde, 0xaf, 0x9d, 0x4c, 0xba, 0x80, 0xd6, 0xe6, 0xb3, 0xef, - 0xec, 0x4a, 0xeb, 0xa6, 0xe7, 0xec, 0xc1, 0xd6, 0x2d, 0xd1, 0xb9, 0x20, 0x9a, 0xfc, 0x7e, 0xe0, 0x59, 0xdb, 0x8e, - 0x7e, 0x9b, 0x76, 0x6c, 0x73, 0x0f, 0x75, 0xaf, 0xa0, 0xd6, 0x1b, 0x9a, 0xf7, 0xcf, 0x5c, 0xdb, 0x8e, 0xaf, 0x7e, - 0x5d, 0x77, 0xb8, 0xce, 0x9b, 0xe0, 0xb8, 0xe9, 0xda, 0x56, 0x3b, 0xfb, 0xb9, 0xbb, 0xb7, 0x16, 0x51, 0x98, 0x65, - 0x3f, 0x17, 0xc5, 0x9f, 0x95, 0xbe, 0x23, 0xd0, 0xd1, 0x9d, 0x17, 0x75, 0xba, 0xdc, 0xbd, 0x27, 0x8c, 0x27, 0xaf, - 0x3e, 0x22, 0xba, 0xf5, 0x7d, 0xe6, 0x7e, 0x05, 0xb8, 0x11, 0xdc, 0x41, 0xb4, 0x77, 0x4b, 0x7d, 0x52, 0xab, 0xaf, - 0xf5, 0xda, 0x79, 0x7a, 0x7e, 0xd3, 0xb9, 0xfd, 0xee, 0x9b, 0xa3, 0xad, 0xf7, 0xb8, 0xb0, 0x56, 0x96, 0x9e, 0xaa, - 0x82, 0xbd, 0x59, 0x9e, 0xaa, 0x82, 0xc9, 0x03, 0xaf, 0xd9, 0x2f, 0x68, 0x70, 0xa5, 0xa3, 0x8d, 0xf7, 0x44, 0x0d, - 0xdc, 0xa2, 0xb0, 0x74, 0xf8, 0x25, 0x37, 0x93, 0x6b, 0xdc, 0x5f, 0x2a, 0x72, 0xb1, 0xef, 0x9c, 0xd1, 0x9d, 0x99, - 0x75, 0xaf, 0x2a, 0x5c, 0x2d, 0xc8, 0xd5, 0x81, 0xad, 0x65, 0x17, 0x87, 0x1b, 0x16, 0x51, 0x80, 0x40, 0x4c, 0xaf, - 0xd4, 0xda, 0x1f, 0xd1, 0x20, 0xe4, 0x83, 0x81, 0x5f, 0x60, 0xb0, 0x2a, 0x50, 0xf8, 0x40, 0x91, 0xfc, 0x85, 0x27, - 0x60, 0x17, 0xcf, 0x00, 0xdd, 0x8a, 0xcd, 0x8a, 0x11, 0x22, 0x64, 0xb2, 0x9c, 0xd5, 0x74, 0x06, 0xf9, 0xd4, 0x17, - 0xdf, 0xd9, 0xaa, 0xd3, 0x79, 0x5b, 0x53, 0xe5, 0xd4, 0xa1, 0xd0, 0xdd, 0x4d, 0xdd, 0xb9, 0x75, 0x91, 0xa7, 0x0e, - 0x21, 0x57, 0x2a, 0x56, 0x62, 0x1a, 0x6a, 0x9e, 0xa4, 0x19, 0xf5, 0x57, 0x7b, 0xbf, 0xd7, 0x28, 0x9c, 0xf2, 0xa7, - 0x63, 0x50, 0x85, 0xab, 0x1a, 0xe2, 0x58, 0xaa, 0xe2, 0x91, 0x0d, 0x02, 0xcd, 0xab, 0x5b, 0x95, 0x34, 0x21, 0x93, - 0x1b, 0xe1, 0x53, 0x93, 0x52, 0x9e, 0xa6, 0x4d, 0x5a, 0x29, 0x52, 0x07, 0x1f, 0xd4, 0xa9, 0xc6, 0x73, 0xb3, 0x7a, - 0x0a, 0x60, 0xc6, 0xf9, 0x15, 0xbf, 0x54, 0x5c, 0x46, 0x6d, 0x65, 0x26, 0xed, 0x4f, 0x8e, 0xc6, 0x46, 0x5d, 0x4e, - 0x95, 0x79, 0xc5, 0xa0, 0x4f, 0xbf, 0xd6, 0xe7, 0x1f, 0x30, 0x58, 0xf3, 0x04, 0x76, 0x30, 0x51, 0x29, 0xef, 0x23, - 0x20, 0xbe, 0x4e, 0xd2, 0xdb, 0x04, 0x52, 0xa4, 0x7f, 0xe9, 0x92, 0xa7, 0x0e, 0x63, 0x03, 0x31, 0x66, 0xc5, 0xcc, - 0xe8, 0x7f, 0x70, 0x97, 0xf4, 0x27, 0x21, 0x00, 0x6e, 0xa2, 0x29, 0x74, 0xea, 0x3c, 0xb9, 0xc8, 0x83, 0xe5, 0x85, - 0x87, 0x56, 0x8c, 0x78, 0xf0, 0xd7, 0xa7, 0x21, 0x82, 0x98, 0x63, 0x8a, 0xa7, 0x5f, 0x18, 0xfd, 0x25, 0xb8, 0xc4, - 0x08, 0x42, 0x77, 0xef, 0x1c, 0x86, 0x70, 0xb3, 0x07, 0x19, 0xd4, 0x1f, 0xea, 0x90, 0xa8, 0xe1, 0x2f, 0x95, 0x07, - 0xfd, 0x5f, 0x67, 0xc2, 0x52, 0xfb, 0xe9, 0xe9, 0x00, 0x2a, 0x78, 0x5f, 0xf1, 0x36, 0x22, 0xbe, 0x4f, 0xfc, 0x38, - 0x1e, 0x6c, 0x1e, 0x6f, 0xc0, 0x5a, 0xf7, 0x2c, 0x37, 0xd6, 0x55, 0xc2, 0x06, 0x02, 0xbe, 0xc6, 0xb4, 0xf6, 0xbc, - 0x76, 0xbb, 0x07, 0x7f, 0xf5, 0x2f, 0x42, 0x06, 0x4c, 0x9c, 0xbe, 0xcf, 0x9c, 0xac, 0xd1, 0x45, 0x26, 0xd3, 0x87, - 0x4e, 0xfa, 0x46, 0xa7, 0xfb, 0x4e, 0xf8, 0x47, 0xc5, 0x2c, 0x3e, 0xdc, 0xd2, 0x57, 0x9a, 0x14, 0x77, 0xc0, 0xca, - 0xe6, 0x41, 0x41, 0xa8, 0x73, 0x11, 0x7d, 0x63, 0xca, 0xb7, 0x84, 0x9a, 0x7d, 0x63, 0x49, 0x29, 0xdd, 0x6b, 0xe8, - 0x65, 0x5a, 0xeb, 0xb7, 0x51, 0x82, 0x31, 0xd1, 0xf1, 0xe4, 0x65, 0x3c, 0x56, 0xde, 0xc7, 0xe3, 0x46, 0x2a, 0xe4, - 0x01, 0x88, 0x40, 0xc5, 0xf8, 0xd3, 0x95, 0x27, 0x27, 0xbd, 0x30, 0x5e, 0x85, 0x52, 0x50, 0x18, 0xd0, 0x15, 0x48, - 0x01, 0x8f, 0xda, 0x13, 0x9d, 0x85, 0x5d, 0xc2, 0x3d, 0xba, 0x09, 0x18, 0xeb, 0xf3, 0x2f, 0x80, 0xe6, 0x2e, 0xdc, - 0xe1, 0xc5, 0x00, 0xb5, 0xa9, 0x57, 0x77, 0x1f, 0xd7, 0xea, 0x1c, 0x0e, 0xc1, 0xc1, 0x6a, 0x10, 0xc1, 0xe9, 0x7c, - 0xea, 0x68, 0x96, 0x05, 0xa8, 0x9c, 0x2c, 0x37, 0xf2, 0xe6, 0xd1, 0xa2, 0x57, 0xf7, 0xbd, 0x65, 0x5a, 0x56, 0x75, - 0x90, 0xb1, 0x2c, 0xac, 0x00, 0x57, 0x87, 0xd6, 0x0f, 0xc2, 0x65, 0xe1, 0xfc, 0x81, 0x10, 0xc4, 0xee, 0xd5, 0xb6, - 0xe4, 0xb9, 0x9a, 0xc3, 0x8f, 0x9f, 0xb0, 0x35, 0x97, 0xa8, 0x93, 0xce, 0x44, 0x00, 0x62, 0x4f, 0xcd, 0x2a, 0xba, - 0x06, 0x92, 0x3a, 0xcd, 0x2a, 0xba, 0xa6, 0x66, 0x1b, 0xe3, 0x40, 0x3e, 0x5a, 0xa5, 0x80, 0x7d, 0x37, 0x1d, 0x07, - 0xab, 0xc7, 0xb1, 0xbc, 0x0e, 0xdd, 0x3e, 0xde, 0x28, 0x9f, 0x41, 0xdd, 0x6a, 0x63, 0x4c, 0x6c, 0x37, 0x5f, 0xce, - 0xf5, 0x9b, 0xc1, 0xd2, 0xb7, 0x83, 0xe6, 0x9c, 0xb2, 0x6f, 0x75, 0xd9, 0x2b, 0xbb, 0x6c, 0xea, 0xb9, 0xa3, 0xa2, - 0xd5, 0x18, 0xd0, 0x1b, 0x58, 0xb0, 0x3e, 0x17, 0x69, 0xb6, 0x2a, 0x55, 0x09, 0x78, 0x61, 0xac, 0xd8, 0xad, 0xdf, - 0xc8, 0x0c, 0x49, 0x98, 0xc7, 0x99, 0x78, 0x43, 0xf7, 0x5a, 0x98, 0x1c, 0xc7, 0x22, 0x99, 0x12, 0x3a, 0xa5, 0x3b, - 0xdb, 0xd0, 0xb9, 0x0a, 0xa3, 0x88, 0xd6, 0x4a, 0x2a, 0x8d, 0x04, 0xa6, 0x66, 0x80, 0x92, 0xb9, 0x02, 0xa7, 0x74, - 0xb9, 0xff, 0x1d, 0x89, 0x71, 0xe6, 0x8b, 0x92, 0x19, 0xd0, 0x2d, 0xbf, 0x2e, 0xd6, 0xad, 0x14, 0x19, 0x61, 0xde, - 0x1c, 0xb7, 0xd7, 0xf5, 0x21, 0x90, 0xab, 0x65, 0x8f, 0xa2, 0x71, 0x50, 0xe8, 0x70, 0xa9, 0x12, 0x60, 0x5f, 0x24, - 0x7e, 0x46, 0xd8, 0xd2, 0x1e, 0xc8, 0xed, 0xd1, 0x99, 0x30, 0xe7, 0x9c, 0x94, 0x65, 0xe7, 0xd2, 0x0c, 0x2e, 0x27, - 0xae, 0x04, 0x17, 0xe9, 0x6d, 0x7b, 0x9a, 0xb4, 0xb4, 0x7d, 0x6c, 0x38, 0x47, 0x43, 0xdb, 0xa0, 0x3b, 0xf6, 0x87, - 0xe6, 0x62, 0x11, 0x5b, 0x17, 0x8b, 0x61, 0x67, 0xf6, 0xa3, 0xc5, 0x02, 0xe4, 0x00, 0x70, 0xd4, 0x6d, 0xf8, 0x98, - 0x2d, 0x81, 0xd3, 0x6a, 0x9a, 0x4d, 0xbd, 0x0d, 0xaf, 0x1e, 0xab, 0x9e, 0x5e, 0xf2, 0xfc, 0xb1, 0x30, 0x63, 0xb1, - 0xe1, 0xf9, 0x63, 0xeb, 0xc8, 0xa9, 0x1e, 0x0b, 0x25, 0x5a, 0x17, 0xd0, 0x0c, 0xbc, 0xa6, 0x80, 0x11, 0x4b, 0x26, - 0x53, 0xaa, 0xc8, 0xe3, 0xde, 0x74, 0xa3, 0x06, 0x2f, 0x28, 0x1c, 0x02, 0x29, 0x9d, 0x7e, 0xf1, 0x84, 0xe9, 0xf7, - 0x2e, 0x9e, 0x74, 0xc8, 0xda, 0x86, 0xe9, 0x72, 0x33, 0x4c, 0x06, 0xa5, 0xff, 0xd8, 0x4c, 0x8c, 0x0b, 0x6b, 0x92, - 0x00, 0xe2, 0xdf, 0xd8, 0xef, 0x90, 0xc2, 0xcd, 0xfb, 0xcb, 0x61, 0xfc, 0xc0, 0xfb, 0x31, 0xb2, 0x27, 0x69, 0x86, - 0x58, 0x33, 0xa9, 0x90, 0xbb, 0xaf, 0xd6, 0x3f, 0x26, 0x76, 0x93, 0x3d, 0xb0, 0x00, 0xc4, 0xd6, 0xb4, 0xd5, 0x2d, - 0xef, 0xf7, 0x3d, 0x53, 0x04, 0xf8, 0x41, 0xf9, 0x47, 0x77, 0x86, 0x64, 0x50, 0x76, 0xdd, 0x10, 0xe2, 0x41, 0xd9, - 0x34, 0xed, 0xf5, 0xb6, 0x77, 0xe6, 0xb1, 0xba, 0x4e, 0x3b, 0x8b, 0xab, 0x45, 0x06, 0x69, 0xf5, 0x21, 0x3b, 0xce, - 0xec, 0xb3, 0xa3, 0xa5, 0xd2, 0xfd, 0x3e, 0x44, 0xc4, 0x1d, 0x65, 0x6d, 0xbf, 0xdd, 0x82, 0x6b, 0x38, 0x1a, 0x84, - 0xae, 0xec, 0xed, 0x32, 0xda, 0xb8, 0x10, 0xc7, 0x3d, 0xd3, 0xf9, 0x82, 0x2f, 0x8f, 0xd2, 0xce, 0x83, 0x53, 0x3d, - 0xd1, 0xe7, 0xa6, 0xbb, 0xca, 0xe4, 0x5a, 0x87, 0xd5, 0x18, 0xd4, 0x66, 0x61, 0x0b, 0x77, 0x61, 0x1b, 0x1d, 0xb4, - 0xf6, 0x65, 0xc1, 0x3f, 0x65, 0x00, 0xbe, 0xf4, 0x6c, 0xd9, 0xf6, 0x9a, 0xb4, 0x7a, 0x29, 0xa3, 0x10, 0x5b, 0xda, - 0x5e, 0x7d, 0x3a, 0xca, 0xc7, 0xcd, 0x09, 0xc5, 0x85, 0x1c, 0xe5, 0x07, 0xaf, 0x21, 0xea, 0x5a, 0xd7, 0x71, 0xb1, - 0xe8, 0x70, 0xe3, 0xaa, 0xdb, 0x6e, 0x5c, 0xaf, 0x10, 0x6f, 0x8d, 0x36, 0x29, 0xd4, 0xca, 0xd8, 0x11, 0xbc, 0x2c, - 0x1f, 0x0e, 0x99, 0x18, 0x0e, 0x25, 0x64, 0xea, 0x43, 0xf7, 0x86, 0xa6, 0x7d, 0x7e, 0xda, 0xfa, 0x11, 0x4b, 0x8d, - 0xa3, 0xd8, 0xf0, 0x4e, 0xdf, 0x79, 0x6c, 0x8d, 0x2b, 0xf9, 0x32, 0x98, 0xed, 0x0a, 0xaa, 0xad, 0xf1, 0x86, 0xbd, - 0x9c, 0xff, 0x5c, 0x49, 0x25, 0x7f, 0xfb, 0x33, 0x5c, 0xc3, 0x5b, 0x5b, 0x3a, 0x68, 0xaa, 0x59, 0xce, 0x72, 0x7d, - 0x2f, 0x38, 0xfe, 0xb8, 0x7b, 0x45, 0x30, 0xf8, 0x3d, 0x1d, 0x05, 0xb9, 0x58, 0xaa, 0x35, 0xa0, 0x20, 0x1d, 0xd9, - 0x31, 0x95, 0x05, 0x86, 0x01, 0xbc, 0x21, 0x03, 0xe4, 0x31, 0x85, 0xbb, 0xa1, 0xc2, 0x0b, 0x7f, 0xad, 0xc8, 0x2e, - 0x81, 0x6d, 0xcd, 0xf8, 0x98, 0xe1, 0x0e, 0x42, 0xfe, 0x11, 0xec, 0x96, 0xad, 0xd8, 0x0d, 0x5b, 0x30, 0x24, 0x1b, - 0xc7, 0x61, 0x8c, 0xf9, 0x78, 0x12, 0x5f, 0x89, 0x49, 0x3c, 0xe0, 0x11, 0x3a, 0x46, 0xac, 0x79, 0x3d, 0x8b, 0xe5, - 0x00, 0xb2, 0x5b, 0xae, 0x74, 0x40, 0x08, 0x8d, 0x0d, 0x2d, 0x79, 0x59, 0x18, 0x5c, 0xec, 0xd8, 0x67, 0x24, 0x92, - 0x71, 0x08, 0x16, 0xad, 0x6a, 0x60, 0x61, 0x62, 0x37, 0xbc, 0x98, 0xad, 0xe6, 0xf8, 0xcf, 0xe1, 0x80, 0x00, 0xd8, - 0xc1, 0xbe, 0x61, 0xb7, 0x11, 0x22, 0xbd, 0x2d, 0xf8, 0xad, 0xe5, 0xe9, 0xc2, 0xee, 0xf8, 0x35, 0x1f, 0xb3, 0xf3, - 0x57, 0x1e, 0x44, 0xce, 0x9e, 0x7f, 0x00, 0x34, 0xc4, 0x3b, 0x7e, 0x93, 0x7a, 0x15, 0xbb, 0x21, 0x0a, 0xc2, 0x1b, - 0x70, 0x06, 0xba, 0x83, 0x08, 0xd8, 0x6b, 0xbe, 0xc0, 0x58, 0xb1, 0xb3, 0x74, 0xe9, 0x61, 0x46, 0xa8, 0x3d, 0x9d, - 0x2f, 0x6b, 0x35, 0x09, 0x37, 0x57, 0xcb, 0xc9, 0x60, 0xb0, 0xf1, 0x77, 0x7c, 0x0d, 0x7c, 0x30, 0xe7, 0xaf, 0xbc, - 0x1d, 0x95, 0x0b, 0xff, 0x79, 0x9d, 0x25, 0xef, 0x7c, 0x76, 0x3d, 0xe0, 0x0b, 0xc0, 0x5b, 0x42, 0x07, 0xae, 0x3b, - 0x9f, 0x49, 0xbc, 0xb6, 0x6b, 0x7d, 0x8d, 0x40, 0x22, 0x5f, 0x00, 0x46, 0x4c, 0xcc, 0xef, 0x6b, 0x88, 0xc0, 0xd8, - 0x80, 0x6f, 0xab, 0xf6, 0x88, 0xdf, 0x72, 0x03, 0xf8, 0x95, 0xf9, 0xec, 0x9e, 0x87, 0xfa, 0x67, 0xe2, 0xb3, 0x37, - 0xfc, 0x11, 0x7f, 0xea, 0x49, 0x49, 0xba, 0x9c, 0x3d, 0x9a, 0xc3, 0xf5, 0x50, 0xca, 0xd3, 0x21, 0xfd, 0x6c, 0x0c, - 0x06, 0x10, 0x0a, 0x99, 0x6f, 0x3c, 0x60, 0x4d, 0x0a, 0xf1, 0x2f, 0xe0, 0xdb, 0x51, 0xc2, 0xe6, 0x1b, 0x6f, 0xeb, - 0x6b, 0x79, 0xf3, 0x8d, 0x77, 0xef, 0x53, 0x14, 0x60, 0x15, 0x94, 0xb2, 0xc0, 0x2a, 0x08, 0x1b, 0x6d, 0x84, 0x31, - 0x70, 0xf5, 0xae, 0x31, 0xd4, 0xf5, 0x1c, 0xb1, 0x6d, 0xa5, 0x6f, 0xc3, 0xb7, 0x90, 0x01, 0x1f, 0xbc, 0x2c, 0x4a, - 0xa2, 0xcf, 0xa9, 0x29, 0x92, 0xd6, 0x3d, 0xf7, 0x5b, 0xeb, 0x8e, 0xd6, 0x94, 0xfa, 0xc8, 0xd5, 0xf8, 0x70, 0xa8, - 0x9f, 0x0a, 0x2d, 0x12, 0x4c, 0x41, 0xe3, 0x1a, 0xb4, 0x05, 0x08, 0xfa, 0x3c, 0x40, 0xd6, 0x92, 0x62, 0xc1, 0xb7, - 0xbf, 0x42, 0x0c, 0x5e, 0x99, 0xde, 0xb9, 0x5c, 0x65, 0x24, 0x6c, 0x2f, 0xfc, 0x72, 0x58, 0xfb, 0x13, 0xa7, 0x16, - 0x96, 0x56, 0x73, 0x50, 0x3f, 0xb6, 0xe5, 0x38, 0x5d, 0xb5, 0xc8, 0xeb, 0x50, 0x5a, 0x4e, 0xef, 0xec, 0x9b, 0x2e, - 0x13, 0x6c, 0xec, 0x07, 0x54, 0x1d, 0x59, 0x0d, 0xbb, 0x2f, 0xd4, 0x17, 0x3d, 0x25, 0x13, 0x9a, 0x8f, 0x2a, 0x9a, - 0xe7, 0xd6, 0x37, 0x8f, 0xeb, 0x3f, 0xbd, 0x1c, 0x8a, 0x00, 0xc9, 0x2a, 0x2d, 0x96, 0x22, 0x67, 0x63, 0x3f, 0x1e, - 0x26, 0x99, 0x0a, 0x2f, 0x48, 0x47, 0x77, 0xbf, 0x71, 0x7f, 0xcb, 0x0d, 0x64, 0x85, 0x56, 0x6d, 0x30, 0x56, 0x8a, - 0x96, 0xc1, 0xfa, 0x6a, 0xdc, 0xef, 0x8b, 0xab, 0xf1, 0x54, 0x04, 0x35, 0x10, 0x17, 0x89, 0xa7, 0xe3, 0x69, 0x4d, - 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x14, 0x42, 0x91, 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, - 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, 0x75, 0x72, 0xec, 0x5c, 0xc0, - 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x65, 0x62, 0x6b, 0x23, 0xdc, 0x52, 0x40, 0x19, 0xe5, - 0x37, 0x96, 0x13, 0x76, 0xa7, 0x7a, 0x47, 0xaa, 0x76, 0xc4, 0x89, 0x0b, 0x58, 0x6e, 0x78, 0x6a, 0xf5, 0x4d, 0x0c, - 0x4e, 0x84, 0xaa, 0x95, 0x0e, 0x77, 0x32, 0x81, 0xb8, 0x5f, 0xdd, 0xd7, 0xbd, 0x12, 0xfc, 0x24, 0xe4, 0xf5, 0x5b, - 0xde, 0x01, 0x60, 0xc5, 0x87, 0xbc, 0x98, 0x16, 0x8e, 0xd6, 0x65, 0x50, 0x06, 0x88, 0xd0, 0x0c, 0x80, 0x4e, 0xae, - 0x0e, 0xa2, 0x34, 0x70, 0xc5, 0x1d, 0x22, 0xfc, 0x34, 0x7a, 0x9c, 0x3f, 0x0d, 0x1f, 0x57, 0xd3, 0xf0, 0x22, 0x0f, - 0xa2, 0x8b, 0x2a, 0x88, 0x1e, 0x57, 0x57, 0xe1, 0xe3, 0x7c, 0x1a, 0x5d, 0xe4, 0x41, 0x78, 0x51, 0x35, 0xf6, 0x5d, - 0xbb, 0xbb, 0x27, 0xe4, 0x6d, 0x57, 0x7f, 0xe4, 0x5c, 0xd9, 0x53, 0xa6, 0xe7, 0xe7, 0xb5, 0x5e, 0xa9, 0xdd, 0xe6, - 0x7a, 0x8d, 0x9a, 0xa9, 0x8f, 0xb2, 0xbf, 0xd9, 0xc6, 0xc2, 0xa3, 0x39, 0x84, 0x3e, 0x23, 0x2d, 0xe6, 0x1e, 0xe7, - 0x7a, 0xb3, 0x27, 0x85, 0x81, 0x11, 0x93, 0x4a, 0x46, 0x4e, 0x2f, 0x70, 0x11, 0xaa, 0x10, 0xc3, 0x5a, 0xba, 0xda, - 0x67, 0x5d, 0x7a, 0x03, 0x75, 0x4d, 0xb1, 0xaf, 0x21, 0x03, 0x2f, 0x9a, 0x5e, 0x06, 0x63, 0x40, 0x8e, 0xc0, 0x3b, - 0x3e, 0x5b, 0xc2, 0x81, 0xb9, 0x06, 0xe8, 0x9b, 0x07, 0x7d, 0x5d, 0x6e, 0xf9, 0x5a, 0xf5, 0xcd, 0x74, 0x3d, 0x52, - 0xca, 0x8f, 0x15, 0xbf, 0xbd, 0x78, 0xc2, 0x6e, 0xb8, 0x46, 0x45, 0x79, 0xae, 0x17, 0xeb, 0x1d, 0x70, 0xd5, 0x3d, - 0x87, 0xdb, 0x2c, 0x1e, 0xbb, 0xf2, 0x80, 0x65, 0x5b, 0x76, 0xcf, 0xde, 0xb0, 0x47, 0xec, 0x3d, 0xfb, 0xc4, 0xbe, - 0xb2, 0x1a, 0x21, 0xca, 0x4b, 0x25, 0xe5, 0xf9, 0x0b, 0x7e, 0x23, 0x6d, 0x8f, 0x12, 0x96, 0xec, 0xde, 0xb6, 0xd3, - 0x0c, 0x37, 0xec, 0x11, 0x5f, 0x0c, 0x57, 0xec, 0x13, 0x64, 0x43, 0xa1, 0x78, 0xb0, 0x62, 0x35, 0x5c, 0x61, 0x29, - 0x83, 0x3e, 0x0d, 0x4b, 0x4b, 0x58, 0x34, 0x85, 0xa2, 0x14, 0xfd, 0x89, 0xd7, 0x84, 0x9d, 0x56, 0x63, 0x21, 0xf2, - 0x43, 0xc3, 0x15, 0xbb, 0xe7, 0x8b, 0xc1, 0x8a, 0x3d, 0xd2, 0x36, 0xa2, 0xc1, 0xc6, 0x2d, 0x8e, 0xc0, 0xac, 0x74, - 0x61, 0x52, 0xa0, 0xde, 0xda, 0x37, 0xc1, 0x0d, 0x7b, 0x83, 0xf5, 0x7b, 0x8f, 0x45, 0xa3, 0xcc, 0x3f, 0x58, 0xb1, - 0xaf, 0x5c, 0x62, 0xa8, 0xb9, 0xe5, 0x49, 0xc7, 0x50, 0x5d, 0x20, 0x5d, 0x11, 0xde, 0x73, 0x7a, 0x91, 0x7d, 0xc5, - 0x32, 0xe8, 0x2b, 0xc3, 0x15, 0xdb, 0x62, 0xed, 0xde, 0x18, 0xe3, 0x96, 0x55, 0x3d, 0x09, 0x0a, 0x8c, 0xb2, 0x4a, - 0x69, 0xb9, 0x38, 0x62, 0xd9, 0xd4, 0x51, 0x83, 0xda, 0x30, 0xa0, 0x0f, 0x46, 0x7f, 0xf1, 0xf5, 0xbb, 0xef, 0xbc, - 0x52, 0xdf, 0x7c, 0x9f, 0x3b, 0xde, 0x95, 0x25, 0x7a, 0x57, 0xfe, 0xc6, 0xcb, 0xd9, 0xf3, 0xf9, 0x44, 0xd7, 0x92, - 0x36, 0x19, 0x72, 0x37, 0x9d, 0x3d, 0xef, 0xf0, 0xb7, 0xfc, 0xcd, 0xf7, 0x1b, 0xab, 0x8f, 0xd5, 0x77, 0x75, 0xf7, - 0xde, 0x0f, 0x36, 0x8d, 0x53, 0xf1, 0xdd, 0xe9, 0x8a, 0x63, 0x3b, 0x6b, 0xed, 0x9d, 0xf9, 0x3f, 0x5c, 0xeb, 0x2d, - 0x8e, 0xdd, 0x1b, 0xbe, 0x1d, 0x6e, 0xec, 0x61, 0x90, 0xdf, 0x97, 0x8a, 0xe3, 0xac, 0xe6, 0xcf, 0xbc, 0x4e, 0x49, - 0x16, 0x50, 0x8d, 0x5e, 0x1b, 0x69, 0xe8, 0x92, 0x99, 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, - 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, 0xb5, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, - 0xd8, 0x4b, 0xf2, 0xb9, 0xcf, 0xde, 0x0a, 0x77, 0x95, 0x3e, 0xf7, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, - 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, 0x16, 0xfc, 0x2d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0x3f, - 0xd7, 0xea, 0xe7, 0x3b, 0x19, 0x9b, 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0x9b, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, - 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0xd7, 0x3c, 0x96, 0x16, 0xe6, 0x3b, 0x08, - 0x07, 0xbe, 0xb6, 0x61, 0x0a, 0x76, 0x1c, 0x37, 0x83, 0x6b, 0x06, 0x10, 0x92, 0xd9, 0x74, 0xcb, 0xdf, 0xf0, 0xf7, - 0xfc, 0x2b, 0xdf, 0x05, 0xf7, 0xfc, 0x11, 0xff, 0xc4, 0xeb, 0x9a, 0xef, 0xd8, 0x52, 0x42, 0x9e, 0xd6, 0xdb, 0xcb, - 0x60, 0xcb, 0xea, 0xdd, 0x65, 0x70, 0xcf, 0xea, 0xed, 0x93, 0xe0, 0x0d, 0xab, 0x77, 0x4f, 0x82, 0x47, 0x6c, 0x7b, - 0x19, 0xbc, 0x67, 0xbb, 0xcb, 0xe0, 0x13, 0xdb, 0x3e, 0x09, 0xbe, 0xb2, 0xdd, 0x93, 0xa0, 0x56, 0x48, 0x0f, 0x5f, - 0x85, 0x64, 0x3a, 0xf9, 0x5a, 0x33, 0xc3, 0xaa, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, 0x65, 0xf0, 0xb9, 0x66, 0xba, - 0xcd, 0x81, 0x10, 0x4c, 0xb7, 0x38, 0xb8, 0xa1, 0x27, 0xa6, 0x5d, 0x41, 0x2a, 0x58, 0x57, 0x4b, 0x83, 0x45, 0xdd, - 0xb4, 0x4e, 0x66, 0xc7, 0x3b, 0x31, 0xee, 0xf0, 0x4e, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, 0xaa, 0x73, 0xfa, 0x3c, 0xd0, - 0x47, 0x80, 0xde, 0xfb, 0x2b, 0xe9, 0x41, 0x53, 0x34, 0x3c, 0x57, 0xba, 0xe3, 0xd6, 0x7e, 0x1f, 0x5a, 0xfb, 0x3d, - 0x93, 0x8a, 0xb4, 0x88, 0x45, 0x65, 0x51, 0x55, 0xc8, 0x27, 0x1e, 0x64, 0x5a, 0xab, 0x96, 0x30, 0x52, 0x67, 0x02, - 0x26, 0x7d, 0x41, 0x87, 0x41, 0x4e, 0x76, 0x05, 0xb6, 0xe4, 0x9b, 0x41, 0xc2, 0xd6, 0x3c, 0x9e, 0x0e, 0x93, 0x60, - 0xc9, 0x6e, 0xf9, 0xb0, 0x5b, 0x2c, 0x58, 0xa9, 0x30, 0x26, 0x7d, 0x7d, 0x3a, 0xda, 0xdd, 0x79, 0x6f, 0x95, 0xc6, - 0x71, 0x26, 0x50, 0xe7, 0x56, 0xe9, 0x6d, 0x7e, 0xeb, 0xec, 0xea, 0x6b, 0xb5, 0xcb, 0x83, 0xc0, 0xf0, 0x1b, 0x10, - 0xed, 0x10, 0xef, 0x1d, 0xd4, 0x18, 0xe9, 0x96, 0xcc, 0xba, 0xaf, 0xec, 0x7d, 0x7d, 0x6b, 0xb6, 0xea, 0xff, 0xb4, - 0x08, 0xda, 0xcb, 0x65, 0xef, 0xbf, 0x36, 0xaf, 0xfe, 0xde, 0xf1, 0xea, 0xc6, 0x9f, 0xdc, 0xf3, 0xd7, 0x18, 0x9d, - 0x80, 0x89, 0x6c, 0xc7, 0x5f, 0x8f, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xcb, 0xff, 0xaf, 0x14, 0x68, 0xef, 0xe6, 0x95, - 0xbd, 0x29, 0x6e, 0x79, 0xc7, 0x5e, 0xbe, 0xb4, 0xf6, 0x44, 0x83, 0x50, 0xf2, 0x9a, 0xbb, 0x41, 0xd1, 0xb0, 0x27, - 0x3e, 0xe7, 0xd5, 0xec, 0xf5, 0x7c, 0xb2, 0xe5, 0xc7, 0x3b, 0xe2, 0xeb, 0x8e, 0x1d, 0xf1, 0xb9, 0x3f, 0x58, 0x36, - 0xdf, 0xea, 0xd5, 0xce, 0x9d, 0xdc, 0xa9, 0xf4, 0x8e, 0x1f, 0xef, 0xe3, 0xc3, 0xff, 0xb8, 0xd2, 0xbb, 0xef, 0xae, - 0xb4, 0x5d, 0xe5, 0xee, 0xce, 0x37, 0x1d, 0xdf, 0xc8, 0x5a, 0x63, 0xb8, 0x99, 0x51, 0x30, 0xc2, 0xb4, 0x85, 0x69, - 0x1a, 0x44, 0x96, 0x62, 0x11, 0x12, 0x35, 0x4a, 0xe7, 0x44, 0x9f, 0x05, 0x9d, 0x82, 0x2e, 0x6e, 0xf4, 0x37, 0x7c, - 0xcc, 0x16, 0xc6, 0x65, 0xf3, 0xe6, 0x6a, 0x31, 0x19, 0x0c, 0x6e, 0xfc, 0xfd, 0x1d, 0x0f, 0x67, 0x37, 0x73, 0x76, - 0xcd, 0xef, 0x68, 0x3d, 0x4d, 0x54, 0xe3, 0x8b, 0x87, 0x24, 0xb0, 0x1b, 0xdf, 0x9f, 0x58, 0x44, 0xb0, 0xf6, 0x8d, - 0xf3, 0xc6, 0x1f, 0x48, 0xb3, 0xb4, 0xdc, 0xda, 0x1f, 0x3d, 0xac, 0xa1, 0xb8, 0x01, 0x21, 0xe3, 0x91, 0xad, 0x72, - 0xf8, 0xc4, 0x3f, 0x78, 0xd7, 0xfe, 0xf4, 0x5a, 0x07, 0xdf, 0x4c, 0xd4, 0xb9, 0xf4, 0xe9, 0xe2, 0x09, 0xfb, 0x8d, - 0xbf, 0x96, 0x67, 0xca, 0x5b, 0x21, 0xa7, 0xed, 0x47, 0x24, 0x71, 0xa2, 0xa3, 0xe2, 0xab, 0x9b, 0x48, 0xa0, 0x10, - 0xb0, 0x2b, 0x7c, 0xad, 0xf9, 0xfd, 0xa4, 0x9c, 0x7a, 0x3b, 0x20, 0x79, 0xe5, 0xb6, 0x22, 0xfa, 0x86, 0x73, 0xbe, - 0x18, 0x5e, 0x4e, 0xbf, 0x76, 0xfb, 0xf6, 0xa8, 0xb0, 0x36, 0x15, 0xf1, 0x76, 0x83, 0x41, 0x58, 0x27, 0x33, 0xcb, - 0x5c, 0xf2, 0xa5, 0xaf, 0xb5, 0x99, 0x7b, 0x4c, 0xef, 0x38, 0xd3, 0x0c, 0x19, 0x7d, 0x81, 0x99, 0xe9, 0x70, 0xb8, - 0x3d, 0xc7, 0xf2, 0xf8, 0xf0, 0xd3, 0xe3, 0xf7, 0x83, 0xf7, 0x18, 0xc2, 0x65, 0x85, 0x85, 0x7c, 0xe5, 0xc3, 0xac, - 0x6e, 0x5d, 0x3b, 0x2e, 0x9e, 0x0c, 0x9f, 0x43, 0xde, 0xa0, 0xeb, 0xa1, 0x29, 0xa2, 0x55, 0x7e, 0x47, 0xd1, 0x27, - 0x4a, 0x0e, 0x3a, 0x9e, 0x40, 0xed, 0x90, 0x0b, 0xf7, 0xeb, 0x63, 0x0e, 0x8a, 0x0e, 0x2c, 0xb5, 0xdf, 0x3f, 0x7f, - 0x4d, 0x84, 0xd2, 0x30, 0xde, 0xcf, 0xc3, 0xe8, 0xcf, 0xb8, 0x2c, 0xd6, 0x70, 0xc4, 0x0e, 0xe0, 0x73, 0x8f, 0xf5, - 0x35, 0xec, 0xd6, 0xf7, 0xfd, 0xc0, 0xdb, 0xf2, 0x37, 0xec, 0x2b, 0xf7, 0x2e, 0x87, 0x9f, 0xfc, 0xc7, 0xef, 0x41, - 0x7e, 0x42, 0x9c, 0x14, 0x0c, 0x89, 0xed, 0x28, 0x46, 0xad, 0xc3, 0xcf, 0x35, 0xc4, 0x6a, 0xbd, 0x46, 0xea, 0x2e, - 0x48, 0x7f, 0xaf, 0x90, 0xfd, 0x84, 0xc0, 0x6a, 0x92, 0x3e, 0x05, 0x26, 0xf1, 0x4d, 0x0d, 0x09, 0xa4, 0x69, 0x81, - 0x18, 0x1c, 0x28, 0x3e, 0x15, 0xfc, 0xeb, 0xf0, 0x33, 0xc9, 0x7f, 0x8b, 0x9a, 0x8f, 0xe1, 0x6f, 0x18, 0x9a, 0x49, - 0x75, 0x9f, 0xd6, 0x10, 0x11, 0x0d, 0xa7, 0x5e, 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, - 0x4c, 0x6e, 0x4a, 0x11, 0xfe, 0x39, 0xc1, 0x67, 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, - 0x65, 0xaf, 0x06, 0x8b, 0x7a, 0xc8, 0x6f, 0x6a, 0xf7, 0x7d, 0x39, 0x27, 0xe8, 0x91, 0xfd, 0x80, 0xe6, 0x60, 0xa0, - 0x66, 0x20, 0x65, 0x08, 0x6e, 0xe0, 0xd2, 0xef, 0xa9, 0x82, 0x7c, 0xf9, 0xbd, 0xcf, 0x42, 0x06, 0xae, 0x2c, 0x08, - 0x53, 0x2e, 0x15, 0x52, 0xe0, 0xb8, 0xa9, 0x07, 0x9f, 0x35, 0x3a, 0x89, 0x04, 0x9f, 0x12, 0x90, 0x24, 0x2d, 0x0f, - 0x24, 0x8d, 0x98, 0x0e, 0xc4, 0x85, 0xd2, 0x34, 0x2b, 0x29, 0xe2, 0x10, 0xbb, 0xea, 0x35, 0x12, 0x9e, 0x05, 0x8f, - 0x18, 0xac, 0x1d, 0x29, 0x5a, 0x7c, 0x35, 0xa6, 0x63, 0x1d, 0x36, 0x74, 0x2b, 0x8b, 0xfb, 0x4d, 0x52, 0xa7, 0x91, - 0xb8, 0xf2, 0x56, 0xc8, 0x9f, 0xff, 0x52, 0x22, 0x90, 0xde, 0xd5, 0x40, 0x0c, 0x82, 0x1f, 0xa0, 0xff, 0x80, 0x45, - 0x0e, 0x82, 0x52, 0x5d, 0x86, 0x79, 0x95, 0x51, 0x81, 0xb3, 0x1d, 0xdb, 0xce, 0x99, 0xaa, 0x5b, 0xf0, 0x59, 0x18, - 0x86, 0xb4, 0xb3, 0x55, 0x73, 0x72, 0xab, 0x37, 0x50, 0xcf, 0x24, 0x8e, 0xd4, 0x52, 0x1c, 0x69, 0x6b, 0xee, 0xd3, - 0xa5, 0xd7, 0x2d, 0x2f, 0x68, 0xb8, 0x00, 0xbd, 0x28, 0xdd, 0x75, 0x3e, 0xa1, 0xd0, 0x65, 0x35, 0xae, 0x86, 0xa2, - 0x0e, 0xe5, 0x18, 0x6b, 0x7f, 0xae, 0xe4, 0xf9, 0x1d, 0x58, 0x8f, 0xd0, 0xf0, 0x55, 0xa9, 0x83, 0xd8, 0x7e, 0xa2, - 0x77, 0x9d, 0x4a, 0xfd, 0x0d, 0x00, 0x03, 0xa7, 0x8e, 0x87, 0xfa, 0xa8, 0x9d, 0x42, 0xb6, 0x73, 0x6f, 0x89, 0x51, - 0xb9, 0x12, 0x9e, 0x2a, 0x2d, 0x4f, 0x29, 0xab, 0xbe, 0x16, 0xdc, 0xca, 0xee, 0xb3, 0x01, 0x64, 0xb4, 0x41, 0x81, - 0x3c, 0xa3, 0xb6, 0xc6, 0x83, 0x54, 0xd3, 0x2c, 0x71, 0x0c, 0x1f, 0x14, 0x69, 0x56, 0x81, 0xc5, 0xcb, 0x5c, 0x32, - 0x07, 0x05, 0xcb, 0xf5, 0x66, 0x33, 0xcd, 0x54, 0x5f, 0xe4, 0xf6, 0x46, 0xe3, 0x65, 0xfa, 0x6f, 0x96, 0x0c, 0x78, - 0x74, 0xf1, 0xc4, 0x0f, 0x20, 0x4d, 0x52, 0x3c, 0x40, 0x12, 0x6c, 0x0f, 0x76, 0xb1, 0xc3, 0xb0, 0x55, 0xac, 0xec, - 0xc9, 0xd3, 0xe5, 0x0e, 0x4d, 0xb9, 0x04, 0x97, 0x9c, 0x98, 0xcb, 0xa9, 0xef, 0x4b, 0xd6, 0x1b, 0x8a, 0x53, 0x36, - 0x4d, 0x40, 0x49, 0xa0, 0xdd, 0x82, 0xff, 0xc2, 0xa7, 0x86, 0x4e, 0x0b, 0xb0, 0xd4, 0x76, 0x03, 0xfe, 0x0b, 0xfd, - 0x62, 0xbb, 0x8b, 0xfa, 0x81, 0x79, 0xb0, 0x37, 0x8b, 0x2b, 0x63, 0xc0, 0x49, 0xe2, 0x4a, 0xf3, 0xc8, 0xf5, 0x83, - 0xa2, 0x4f, 0x97, 0xb5, 0x03, 0x67, 0x8a, 0x0b, 0xab, 0xd4, 0x26, 0xe9, 0xb5, 0xdf, 0x52, 0x13, 0x6f, 0xa2, 0xa4, - 0x2a, 0x6c, 0x87, 0xb4, 0x7f, 0x49, 0x39, 0x53, 0xc5, 0x1d, 0xa2, 0x27, 0xbb, 0x89, 0xab, 0xc0, 0x0b, 0xab, 0x8a, - 0x8d, 0x50, 0x9b, 0x91, 0xe5, 0x04, 0x4e, 0xf7, 0x58, 0x5d, 0xf0, 0xb1, 0x5d, 0xcd, 0x2e, 0x58, 0xc9, 0xd6, 0x4c, - 0xba, 0xcf, 0xdb, 0x31, 0x17, 0xf2, 0x4a, 0x2f, 0x8b, 0x56, 0x40, 0x7b, 0x10, 0x38, 0xfc, 0x5c, 0xd3, 0x3d, 0x7a, - 0xb6, 0xd9, 0xa6, 0x36, 0x1b, 0x5b, 0x8b, 0x10, 0x32, 0x10, 0x0d, 0x7d, 0x21, 0x67, 0x14, 0xf9, 0x2a, 0x2d, 0xd7, - 0x6a, 0x63, 0x95, 0xf1, 0x02, 0x13, 0x41, 0x86, 0xb3, 0xf0, 0x0e, 0x3d, 0xad, 0x47, 0x9a, 0x62, 0x12, 0x9c, 0x74, - 0xf1, 0x17, 0x60, 0x43, 0x79, 0x92, 0x9b, 0x03, 0x72, 0x00, 0x95, 0x4b, 0x51, 0x2a, 0x65, 0xf0, 0x6b, 0x75, 0x47, - 0xb6, 0x55, 0xff, 0x9d, 0x06, 0x32, 0xb8, 0x03, 0x7d, 0xdb, 0x0b, 0xad, 0x1d, 0xed, 0x5c, 0xd9, 0x9a, 0xb6, 0x65, - 0x9a, 0xc7, 0xc8, 0x62, 0x03, 0xc8, 0x27, 0xd2, 0x39, 0x10, 0x79, 0x4d, 0x34, 0xde, 0xd9, 0x53, 0x3e, 0x9e, 0x8a, - 0x87, 0xe4, 0xbd, 0xca, 0xf7, 0xcd, 0xbd, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x32, 0xf1, 0xc1, 0x6a, 0x6b, 0x5d, 0x62, - 0xbd, 0x55, 0x9a, 0x44, 0x37, 0x5c, 0x41, 0xc7, 0x91, 0xb8, 0x41, 0x0c, 0x8e, 0x19, 0xaf, 0xad, 0xb2, 0xf4, 0x15, - 0x96, 0xb9, 0x8e, 0x59, 0x32, 0x64, 0x52, 0xe7, 0x89, 0x82, 0x27, 0x3f, 0x4f, 0x48, 0x46, 0x44, 0xcd, 0xb6, 0x1c, - 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0xe0, 0x9b, 0x34, 0x01, 0x28, 0x97, 0x2f, 0x41, 0x2a, 0x0d, 0x11, 0x5c, - 0xb3, 0xbd, 0x64, 0x74, 0xe3, 0x68, 0x1d, 0x54, 0x49, 0xe6, 0x0e, 0xce, 0xed, 0x2c, 0x52, 0xea, 0xcd, 0x47, 0x18, - 0x76, 0xf2, 0x3e, 0xac, 0x13, 0xfc, 0x36, 0xa0, 0x26, 0x7d, 0x2a, 0xbc, 0x68, 0x04, 0x68, 0xea, 0x3b, 0x55, 0xc6, - 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, 0x98, 0x57, 0xd5, 0x40, 0x1b, - 0xe4, 0x76, 0x1d, 0x33, 0xa0, 0x51, 0xdb, 0x95, 0x47, 0x16, 0xe0, 0xd6, 0x4c, 0x04, 0x46, 0xce, 0xbf, 0xcb, 0xaf, - 0x55, 0x38, 0x4f, 0xbf, 0x1f, 0x7a, 0xfb, 0x6d, 0x10, 0x8d, 0xb6, 0x97, 0x6c, 0x17, 0x44, 0xa3, 0xdd, 0x65, 0xc3, - 0xe8, 0xf7, 0x13, 0xfa, 0xfd, 0xa4, 0x01, 0x55, 0x89, 0x30, 0x11, 0xf7, 0xfa, 0x8d, 0x5a, 0xbe, 0x52, 0xeb, 0x77, - 0x6a, 0xf9, 0x52, 0x0d, 0x6f, 0xed, 0x49, 0x24, 0x88, 0x2c, 0x8d, 0xcd, 0xbd, 0x64, 0x4b, 0xb5, 0x54, 0x3a, 0x46, - 0x95, 0x11, 0xb5, 0x74, 0x36, 0xc7, 0x8a, 0x91, 0x76, 0x0e, 0x4a, 0x06, 0x64, 0x5a, 0x5c, 0xd5, 0x98, 0x6e, 0x56, - 0xb4, 0xc4, 0x64, 0x84, 0x95, 0x6d, 0x79, 0xbb, 0x49, 0xd5, 0x74, 0x4e, 0x6e, 0x6e, 0x95, 0x72, 0x73, 0x2b, 0x78, - 0xfe, 0x0d, 0xdd, 0x72, 0xc9, 0xb5, 0x97, 0xd9, 0xb4, 0x50, 0xba, 0x65, 0x5c, 0x83, 0xad, 0x7d, 0x13, 0xc8, 0x32, - 0x1f, 0x28, 0x6a, 0x6c, 0x2f, 0x1a, 0xe5, 0x1b, 0x64, 0x2b, 0x62, 0xd4, 0x29, 0x0b, 0xc6, 0xdf, 0xee, 0xe8, 0x81, - 0x0c, 0x54, 0x55, 0xb5, 0x71, 0x70, 0x67, 0xa5, 0x3f, 0x2c, 0x2f, 0x9e, 0xb0, 0xc4, 0x4a, 0x27, 0x17, 0xaa, 0xd0, - 0x1f, 0x84, 0xe8, 0xa6, 0xb2, 0xe1, 0xe0, 0x50, 0x17, 0x5b, 0x19, 0x10, 0x7a, 0x98, 0xde, 0xdb, 0x58, 0xc9, 0x72, - 0xd7, 0x94, 0x2f, 0x66, 0x3c, 0xe1, 0x38, 0xfa, 0x72, 0xb5, 0x08, 0x6b, 0xb5, 0xc8, 0x4e, 0x80, 0x87, 0xd6, 0x6a, - 0x29, 0xe4, 0x6a, 0x11, 0xce, 0x4c, 0x17, 0x6a, 0xa6, 0x67, 0xa0, 0x80, 0x14, 0x6a, 0x96, 0x27, 0x00, 0x0b, 0x2f, - 0xcc, 0x0c, 0x17, 0x66, 0x86, 0xe3, 0x90, 0x1a, 0xff, 0x07, 0xbd, 0xd7, 0xb9, 0xe7, 0x96, 0xbb, 0xd1, 0x69, 0xc4, - 0xb7, 0xa3, 0x0d, 0xe6, 0xf8, 0x20, 0x9c, 0x54, 0xfd, 0x7e, 0x5a, 0x22, 0x56, 0x8f, 0x81, 0x11, 0x94, 0x43, 0xe5, - 0x68, 0xbf, 0x2c, 0x2c, 0xc9, 0x92, 0xb0, 0x24, 0xf7, 0x6a, 0x9c, 0x4b, 0xcb, 0xc5, 0xab, 0x24, 0x10, 0x89, 0x8c, - 0x97, 0xd2, 0x04, 0x9f, 0xf0, 0x72, 0x64, 0xa4, 0xe6, 0xc9, 0x22, 0xf5, 0x72, 0x96, 0xb1, 0x31, 0x62, 0x18, 0x85, - 0x7e, 0x53, 0xf5, 0xfb, 0x79, 0xe9, 0xe5, 0xd4, 0xce, 0x4f, 0xe0, 0x7a, 0x79, 0xea, 0x2c, 0x72, 0x84, 0xbc, 0x1a, - 0x49, 0x85, 0xe5, 0xb5, 0x52, 0x4f, 0x5f, 0x82, 0x0f, 0xea, 0xee, 0x8d, 0x02, 0x20, 0x2e, 0x72, 0xe9, 0x5f, 0x5b, - 0xc2, 0xa5, 0x29, 0x37, 0x30, 0xe8, 0x21, 0xcf, 0x49, 0x08, 0x95, 0x20, 0x24, 0x85, 0x75, 0xe3, 0xbe, 0x78, 0x32, - 0x71, 0xdd, 0x59, 0x6c, 0x60, 0x82, 0xc3, 0x01, 0x10, 0x0f, 0xa6, 0x5e, 0x34, 0xe0, 0xa5, 0x9a, 0x33, 0x1f, 0xbc, - 0x9c, 0x60, 0x32, 0x40, 0x55, 0x31, 0x70, 0xca, 0x7a, 0x2c, 0x1f, 0x19, 0x37, 0x33, 0xdf, 0x0f, 0xf0, 0xdd, 0xba, - 0x90, 0xe8, 0x0f, 0x0a, 0xa0, 0x20, 0x53, 0x00, 0x05, 0x89, 0x01, 0x28, 0x88, 0x0d, 0x40, 0xc1, 0xa6, 0xe1, 0x2b, - 0xa9, 0xc3, 0x8d, 0x80, 0x2e, 0xc2, 0x87, 0x9e, 0x85, 0x8d, 0x15, 0x8a, 0x67, 0x63, 0x36, 0x66, 0x85, 0xda, 0x79, - 0x72, 0x39, 0x15, 0x3b, 0x8b, 0xb1, 0xae, 0x22, 0xb7, 0x89, 0x17, 0x12, 0x8a, 0x9c, 0x73, 0x23, 0x51, 0x77, 0x3f, - 0xf7, 0x5e, 0x92, 0xb1, 0x64, 0xde, 0xd0, 0xa8, 0xc1, 0xbc, 0xec, 0x3a, 0x80, 0x69, 0xc9, 0xb7, 0x05, 0x0d, 0xa6, - 0x53, 0xe5, 0x11, 0x69, 0x12, 0xd4, 0xce, 0x65, 0x52, 0xe4, 0x84, 0x30, 0x09, 0x7a, 0x25, 0xf8, 0x8d, 0x44, 0xf9, - 0xff, 0xa6, 0x13, 0x3c, 0xc0, 0x31, 0xd1, 0x2a, 0xf9, 0x0a, 0x06, 0xcc, 0x9c, 0x3f, 0x93, 0x4e, 0xd9, 0x08, 0xc5, - 0x58, 0xa6, 0xf1, 0xe8, 0x2b, 0x1b, 0x22, 0xb4, 0xd5, 0x33, 0x34, 0x31, 0x41, 0x1d, 0xe0, 0x11, 0xfd, 0x35, 0xfa, - 0x6a, 0x28, 0x54, 0xba, 0x1a, 0xa9, 0x6b, 0x76, 0xce, 0xf9, 0xdb, 0xda, 0x70, 0x22, 0x63, 0xda, 0x14, 0xf8, 0x06, - 0x04, 0xf2, 0x0d, 0x04, 0x80, 0xab, 0xa6, 0x33, 0x7b, 0x05, 0x70, 0x0e, 0x04, 0xf0, 0x38, 0xef, 0x78, 0xfc, 0x40, - 0x7f, 0x15, 0xc7, 0xbd, 0xd3, 0x34, 0x6c, 0xff, 0x15, 0x18, 0x8b, 0xa1, 0x1c, 0xcf, 0x77, 0x0a, 0x92, 0x3d, 0x4a, - 0x59, 0xba, 0x6a, 0x22, 0x3b, 0x14, 0xeb, 0xd3, 0x9c, 0x32, 0x96, 0xb6, 0xe5, 0x18, 0x6d, 0xbc, 0x7e, 0x88, 0xc7, - 0x37, 0x37, 0x7a, 0xf2, 0x41, 0x0f, 0x6e, 0x6f, 0xaf, 0x5e, 0xf4, 0x98, 0xcd, 0xb7, 0x62, 0xf1, 0xac, 0x88, 0x13, - 0xa7, 0x75, 0xc8, 0x01, 0x0e, 0x72, 0x12, 0x02, 0xe9, 0x18, 0x97, 0x5a, 0x74, 0x50, 0xb3, 0x9c, 0xd7, 0xc0, 0x32, - 0x8b, 0x20, 0x1b, 0x20, 0xaa, 0x69, 0x2a, 0x56, 0xc3, 0x83, 0x52, 0x35, 0xa7, 0x54, 0x6a, 0xdf, 0x70, 0xb6, 0x3a, - 0x7d, 0x62, 0xd5, 0x26, 0xdc, 0xfa, 0xb7, 0xda, 0x13, 0xb4, 0x95, 0x34, 0x10, 0xea, 0xf9, 0x22, 0xbd, 0xa5, 0x28, - 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, - 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, 0xc9, 0x3f, 0x85, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, - 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, - 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, - 0x9a, 0xa7, 0xd5, 0x7b, 0xf5, 0xf7, 0xbb, 0x25, 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, - 0xe8, 0x16, 0xc0, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x04, 0x6b, 0xa8, 0xca, 0x53, 0x3e, 0x7b, 0xf9, 0x64, 0x07, - 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, - 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, - 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, - 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, 0x76, 0x03, 0x88, 0x81, 0xa5, 0x0e, 0x49, 0x56, 0x1d, 0xdb, 0xef, - 0xbf, 0x1c, 0x19, 0xde, 0x74, 0x44, 0x84, 0xd1, 0xbf, 0x2b, 0x10, 0xa0, 0x60, 0x99, 0xd9, 0xce, 0x4c, 0xba, 0xda, - 0xb3, 0x7a, 0xde, 0x6c, 0xf2, 0xae, 0xde, 0xb1, 0x9a, 0x96, 0x53, 0xd3, 0x2a, 0xab, 0x69, 0x93, 0x1c, 0x6a, 0x26, - 0xfa, 0x7d, 0x8d, 0x8f, 0x9a, 0xcf, 0x01, 0x97, 0x0d, 0x93, 0x5f, 0xce, 0xaa, 0x79, 0xbf, 0xef, 0xc9, 0x47, 0xf0, - 0x0b, 0x89, 0xcb, 0xdc, 0x1a, 0xcb, 0xa7, 0xaf, 0x88, 0xcf, 0xcc, 0x20, 0x1e, 0xdd, 0x1c, 0x41, 0x7d, 0x7d, 0x14, - 0x5e, 0xc7, 0x5c, 0x61, 0x33, 0x31, 0x7d, 0x09, 0x83, 0xe7, 0x09, 0x1f, 0xbc, 0xe5, 0xe8, 0x6f, 0xa4, 0x33, 0x53, - 0xb0, 0x90, 0x73, 0x7f, 0xf2, 0x12, 0xa1, 0x93, 0x11, 0xe9, 0x41, 0xa7, 0x13, 0x34, 0x64, 0xbf, 0xbf, 0x80, 0xce, - 0x6c, 0xa5, 0x52, 0xb6, 0x2a, 0x2a, 0xd3, 0x75, 0x5d, 0x94, 0x15, 0x74, 0x2c, 0xfd, 0xbc, 0x11, 0x32, 0xb3, 0x7e, - 0x66, 0x21, 0x3f, 0x2d, 0x24, 0xd6, 0x94, 0x6d, 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, - 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, - 0xf4, 0xb9, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, - 0x39, 0x79, 0x09, 0xe0, 0x74, 0x88, 0x88, 0x5b, 0x91, 0xa0, 0x63, 0xd5, 0x70, 0x67, 0xe1, 0x9e, 0xf6, 0xd2, 0xb8, - 0x97, 0xe6, 0x67, 0x69, 0xbf, 0x6f, 0x00, 0x34, 0x53, 0x44, 0x86, 0xc7, 0x19, 0xb9, 0x4d, 0x5a, 0x08, 0xa6, 0xb4, - 0xff, 0x6a, 0x0c, 0x09, 0x02, 0x01, 0xff, 0xa7, 0xf0, 0xde, 0x03, 0xda, 0x26, 0x6d, 0xc0, 0x55, 0x8f, 0xe9, 0xc0, - 0x6c, 0xc9, 0xd9, 0xaa, 0xb3, 0x01, 0x28, 0xa7, 0x4a, 0xeb, 0x29, 0x8f, 0x6b, 0x8a, 0x88, 0x54, 0x59, 0xa8, 0xdf, - 0x58, 0x4f, 0x26, 0xab, 0x5c, 0x64, 0xc8, 0x51, 0x99, 0xde, 0xd6, 0x8c, 0x10, 0xbb, 0xf4, 0xf3, 0x05, 0x2c, 0xd9, - 0xf8, 0x03, 0x4e, 0xde, 0x12, 0x20, 0x6d, 0x67, 0xed, 0xaa, 0xda, 0xe5, 0xb8, 0xb5, 0x9b, 0x03, 0x92, 0xaf, 0x37, - 0x1a, 0x8d, 0xb4, 0x9f, 0x9c, 0x80, 0xa1, 0xea, 0xa9, 0xa5, 0xd0, 0x63, 0xb5, 0xc2, 0xd6, 0xed, 0xc8, 0x65, 0x96, - 0x0c, 0xe6, 0x0b, 0xe3, 0xf8, 0xda, 0x7c, 0xf4, 0xe1, 0x52, 0x59, 0xbb, 0x8e, 0xf8, 0xfa, 0x4f, 0xb2, 0x5a, 0xdf, - 0xf3, 0xae, 0x6a, 0x02, 0xbe, 0xa8, 0x62, 0x4b, 0xbf, 0xe3, 0x3d, 0xd9, 0xbb, 0xf8, 0xda, 0x47, 0xec, 0x92, 0xef, - 0x79, 0x8b, 0x3a, 0xcf, 0x57, 0xbe, 0x6e, 0x54, 0xe9, 0xf6, 0x5e, 0xb2, 0xc0, 0xb5, 0x77, 0xd4, 0x34, 0xd6, 0x33, - 0x3f, 0x7a, 0x58, 0x84, 0x6c, 0xe7, 0x43, 0xef, 0xab, 0xe6, 0xe9, 0x59, 0x43, 0x6f, 0x52, 0x43, 0x1f, 0x7a, 0x51, - 0xb6, 0x4f, 0x4d, 0x23, 0x7a, 0x0d, 0x1b, 0xfa, 0xd0, 0x5b, 0x72, 0x72, 0x48, 0x30, 0x38, 0x35, 0xe6, 0x0f, 0x0f, - 0xa7, 0x33, 0xfc, 0x1d, 0x03, 0x2a, 0x31, 0x99, 0x4f, 0x8f, 0x69, 0x47, 0x01, 0x66, 0x54, 0xe9, 0xed, 0xd3, 0x03, - 0xdb, 0xf1, 0xb2, 0x1e, 0x5a, 0x7a, 0xf7, 0xe4, 0xe8, 0x76, 0xbc, 0xaa, 0xc6, 0x97, 0x72, 0xc8, 0xf3, 0x7c, 0x36, - 0x1a, 0x8d, 0x84, 0x41, 0xe7, 0xae, 0xf4, 0x06, 0x56, 0x20, 0x83, 0x8b, 0xea, 0x43, 0xb9, 0xf4, 0x76, 0xea, 0xd0, - 0xae, 0xfc, 0x49, 0x7e, 0x38, 0x14, 0x23, 0x73, 0x8c, 0x03, 0xce, 0x49, 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, - 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x15, 0x91, 0x57, 0x23, 0xe4, 0x43, 0xf0, 0xb3, 0x07, 0x6a, 0xf1, 0xa7, 0x5a, 0x10, - 0x7b, 0xe8, 0x53, 0xa5, 0x74, 0x88, 0x57, 0x05, 0x84, 0x08, 0x03, 0xde, 0x40, 0x3b, 0x28, 0xc1, 0x61, 0x87, 0x7b, - 0x8f, 0x08, 0xd1, 0x2f, 0xbc, 0x7c, 0x26, 0xc3, 0x95, 0x7b, 0x83, 0x6a, 0xce, 0x00, 0xb1, 0xd2, 0x67, 0xe0, 0x82, - 0x09, 0xa8, 0xa7, 0xf8, 0x14, 0xfd, 0xeb, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, 0x50, 0x11, 0x3d, 0xfb, 0xf9, 0x18, - 0xc0, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xe5, 0x6f, 0x80, 0x61, 0xa5, 0x24, 0xd1, 0xce, 0x29, 0x11, 0xb8, 0xf3, 0x91, - 0x2d, 0xfd, 0x28, 0x05, 0x62, 0xee, 0x78, 0x92, 0xc8, 0x1e, 0x6c, 0xe4, 0x04, 0x6e, 0x31, 0xe0, 0xd1, 0x01, 0xa8, - 0x5c, 0x29, 0xc8, 0xbd, 0xe6, 0x48, 0xee, 0xf8, 0xb1, 0xf7, 0xe3, 0xa0, 0x1e, 0xfc, 0xd8, 0x3b, 0x4b, 0x49, 0xee, - 0x08, 0xcf, 0xd4, 0x94, 0x10, 0xf1, 0xd9, 0x8f, 0x83, 0x7c, 0x80, 0x67, 0x89, 0x16, 0x69, 0x91, 0x5b, 0x4d, 0xd4, - 0xb8, 0x09, 0x6f, 0x13, 0x49, 0x43, 0x74, 0xd7, 0x79, 0x44, 0x2c, 0x00, 0x24, 0x8b, 0xcf, 0xe6, 0x0d, 0x45, 0xbd, - 0x9b, 0xf0, 0x2d, 0xba, 0xcb, 0x62, 0xbf, 0xbf, 0xca, 0xd3, 0xba, 0xa7, 0x43, 0x65, 0xf0, 0x05, 0xa9, 0x26, 0xc0, - 0xa3, 0xfd, 0x85, 0x39, 0x5e, 0xbd, 0xda, 0x1c, 0x29, 0x0b, 0x55, 0xa2, 0x7e, 0x8b, 0xd5, 0xac, 0x87, 0x88, 0xdc, - 0x59, 0x66, 0xec, 0xed, 0x05, 0xaf, 0xe4, 0xac, 0x8a, 0xed, 0x72, 0x7c, 0x45, 0x58, 0x5b, 0x49, 0x80, 0x8e, 0xd6, - 0x63, 0x6d, 0x8a, 0x91, 0x5f, 0x29, 0x24, 0xe0, 0xa2, 0x63, 0x6b, 0xa1, 0xd8, 0x78, 0x01, 0xfa, 0x92, 0x9d, 0x69, - 0x80, 0xf5, 0x46, 0xaf, 0x22, 0x6e, 0xcb, 0x07, 0x2a, 0xbc, 0xc9, 0x4d, 0x95, 0x59, 0xd9, 0x2c, 0xda, 0xfd, 0x54, - 0xf1, 0x0a, 0x71, 0xeb, 0x8d, 0xda, 0xa3, 0x00, 0xb5, 0x87, 0x16, 0xca, 0x00, 0x5d, 0x9a, 0x66, 0x00, 0xc8, 0x00, - 0x20, 0x53, 0x45, 0x7c, 0x26, 0x40, 0xa5, 0xad, 0x6e, 0x14, 0x38, 0x91, 0x5e, 0x00, 0xe3, 0x02, 0x2b, 0x7d, 0x64, - 0x23, 0x83, 0xc5, 0x16, 0x01, 0x6e, 0x39, 0xd2, 0x87, 0x69, 0x38, 0xd9, 0x46, 0x73, 0x98, 0xa4, 0xf9, 0x5d, 0x98, - 0xa5, 0x12, 0x5a, 0xe2, 0x95, 0xac, 0x31, 0x62, 0x01, 0xe9, 0xfb, 0xf4, 0xa2, 0xc8, 0x62, 0x82, 0x84, 0xb3, 0x9e, - 0x3a, 0x80, 0x6a, 0x72, 0xae, 0x35, 0xad, 0x9e, 0xd5, 0x26, 0x0f, 0x59, 0xa0, 0xb3, 0x07, 0x63, 0x52, 0xcb, 0x0d, - 0x3d, 0xb2, 0xbf, 0x72, 0x3c, 0x23, 0x7c, 0xd7, 0x33, 0x9c, 0xfa, 0xef, 0x63, 0x0d, 0xa4, 0x4c, 0x09, 0x20, 0xc8, - 0xe0, 0x68, 0x42, 0x28, 0x4f, 0xc7, 0x64, 0x6a, 0xf3, 0x23, 0x10, 0x8e, 0x08, 0x5e, 0xc1, 0x73, 0x43, 0xeb, 0x96, - 0x1b, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x59, 0xbc, 0xe0, 0xf7, 0x80, 0xcc, 0xa9, 0x57, 0x85, 0xec, 0xd9, 0x73, 0x31, - 0x9d, 0xcd, 0x83, 0x8f, 0x09, 0xed, 0x5f, 0x4c, 0xf8, 0x4d, 0x77, 0x95, 0x5c, 0x99, 0x5a, 0xf7, 0x26, 0x7a, 0xcc, - 0xe5, 0x4e, 0x9f, 0x56, 0x1c, 0x23, 0x9e, 0xc1, 0x2a, 0x20, 0xe7, 0x6c, 0xc8, 0x9f, 0x9e, 0x03, 0x76, 0xcb, 0x4a, - 0x78, 0x11, 0x7f, 0x1a, 0xca, 0x6a, 0x01, 0xf2, 0x23, 0xe7, 0x91, 0xf9, 0xe5, 0xab, 0xed, 0x50, 0xce, 0x29, 0x8a, - 0x68, 0x39, 0x35, 0x2d, 0x29, 0x64, 0x87, 0x9e, 0x82, 0xc9, 0xd4, 0x96, 0xbf, 0xef, 0x13, 0x97, 0xe4, 0x9b, 0x49, - 0x64, 0x5f, 0x07, 0x58, 0xb3, 0x56, 0xdd, 0x43, 0x37, 0x04, 0x03, 0x44, 0x46, 0x28, 0xb3, 0xb9, 0xbe, 0x5b, 0x0f, - 0x06, 0x0a, 0xe6, 0x57, 0xd0, 0x4d, 0x8b, 0x4e, 0x71, 0x80, 0x9c, 0xb5, 0xae, 0x51, 0xa9, 0x2a, 0x0e, 0x1d, 0xe6, - 0xdd, 0xb2, 0x2a, 0xbb, 0x2c, 0xbd, 0x10, 0xa4, 0x46, 0x5d, 0x05, 0x8b, 0x94, 0x8a, 0x28, 0xde, 0x93, 0x5f, 0x03, - 0x13, 0xcf, 0xac, 0x1c, 0xa5, 0xf1, 0x1c, 0x10, 0x83, 0x14, 0x10, 0xa7, 0xfc, 0x0a, 0xd0, 0x44, 0x17, 0x51, 0x98, - 0xbd, 0x8a, 0xab, 0xa0, 0xb6, 0x9a, 0xfe, 0xa7, 0x03, 0x19, 0x7b, 0x5e, 0xf7, 0xfb, 0x29, 0x31, 0xfa, 0x61, 0x14, - 0x06, 0xfe, 0x3d, 0x9e, 0xee, 0x9b, 0x20, 0x35, 0xaf, 0x7c, 0x84, 0x57, 0x74, 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, - 0xfc, 0x35, 0x82, 0xc3, 0xa7, 0x8e, 0x62, 0xbb, 0x4d, 0x95, 0x53, 0x1b, 0x83, 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xff, - 0x99, 0x78, 0xf9, 0x2c, 0x9a, 0x83, 0xa2, 0x34, 0xd3, 0x7c, 0x21, 0x85, 0x74, 0x13, 0xa0, 0x8f, 0x06, 0xa1, 0x56, - 0x57, 0xbe, 0x49, 0xbc, 0x54, 0x4d, 0x6b, 0xf3, 0x14, 0x6b, 0x14, 0x88, 0x59, 0x34, 0x6f, 0x58, 0x46, 0x87, 0xa4, - 0xba, 0x5c, 0x9a, 0x66, 0xbc, 0xb1, 0x9a, 0xa1, 0x5a, 0x71, 0xd4, 0x04, 0x35, 0x4a, 0x1f, 0xe1, 0x02, 0xf8, 0x0f, - 0xba, 0xe3, 0xa8, 0x46, 0x91, 0xa2, 0x01, 0x9f, 0x20, 0x46, 0xac, 0xd9, 0x3c, 0x61, 0xad, 0xa9, 0x6b, 0x46, 0xbf, - 0x2f, 0x43, 0x86, 0x4c, 0x12, 0xf2, 0xf4, 0xe1, 0x72, 0xfd, 0x40, 0xaa, 0x0b, 0xe0, 0x57, 0xae, 0xd8, 0xac, 0xd7, - 0x9b, 0x03, 0x5c, 0x2f, 0xac, 0x5f, 0xd8, 0xb8, 0x82, 0xf3, 0x4b, 0x82, 0xdf, 0x55, 0x3f, 0xc2, 0x2c, 0x83, 0x2a, - 0x20, 0xe3, 0x8f, 0x05, 0x55, 0x9c, 0xbb, 0x98, 0xd4, 0x2f, 0x47, 0xea, 0x82, 0x32, 0x4b, 0xe7, 0x16, 0x27, 0x08, - 0x38, 0x0f, 0xab, 0x27, 0x90, 0xec, 0xcb, 0xc7, 0x3e, 0xcd, 0x28, 0x50, 0x1d, 0x01, 0x3e, 0x9b, 0xf5, 0x43, 0xd8, - 0x3f, 0x20, 0xb2, 0x50, 0x7f, 0xf3, 0x5a, 0xce, 0x1a, 0x92, 0x07, 0x52, 0xcd, 0x7d, 0x0c, 0xa7, 0xc6, 0x02, 0x5f, - 0x5a, 0xf4, 0xa6, 0x82, 0xd7, 0x84, 0xcc, 0xbd, 0x40, 0x6b, 0xdf, 0x02, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, - 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, 0x3f, 0x72, 0xf1, 0x8b, 0x53, 0xa4, 0x67, 0xd1, 0x05, 0x06, 0xba, - 0x20, 0xf3, 0xc6, 0xbf, 0x2a, 0x58, 0xb9, 0x80, 0xde, 0x4b, 0xc5, 0x4a, 0x4e, 0xb6, 0x9d, 0xfa, 0xa3, 0x54, 0xf6, - 0xdb, 0x33, 0x6b, 0x02, 0xbf, 0x4b, 0xec, 0x97, 0xc8, 0xe4, 0x9b, 0x1e, 0x9b, 0x7c, 0x65, 0x58, 0x74, 0x6a, 0x19, - 0x9c, 0xd3, 0x23, 0x83, 0x73, 0x6f, 0x67, 0xd5, 0x26, 0x82, 0xa1, 0x20, 0x09, 0x34, 0x5d, 0x7a, 0x58, 0x37, 0xfd, - 0xf9, 0x49, 0x8b, 0x6a, 0xab, 0xf6, 0xad, 0xfb, 0x71, 0x88, 0x5d, 0xfc, 0x2e, 0xf1, 0x0c, 0x11, 0xa9, 0x0f, 0x74, - 0x60, 0x32, 0x78, 0xe2, 0xb2, 0xdf, 0x87, 0xc2, 0x66, 0xe3, 0xf9, 0xa8, 0x2e, 0x5e, 0x17, 0xf7, 0x80, 0xea, 0x50, - 0x81, 0x5d, 0x0e, 0x65, 0x28, 0x23, 0x36, 0xb5, 0xe5, 0x9e, 0x3f, 0xae, 0xc3, 0x1c, 0xe4, 0x1d, 0x0d, 0x8f, 0x73, - 0x06, 0x62, 0x18, 0x7c, 0xfd, 0xc7, 0x47, 0xfb, 0xb4, 0xf9, 0xf1, 0x0c, 0xbe, 0x3b, 0x3a, 0x7b, 0x8f, 0x74, 0x37, - 0x67, 0xeb, 0xb2, 0xb8, 0x4b, 0x63, 0x71, 0xf6, 0x23, 0xa4, 0xfe, 0x78, 0x56, 0x94, 0x67, 0x3f, 0xaa, 0xca, 0xfc, - 0x78, 0x46, 0x0b, 0x6e, 0xf4, 0x87, 0x35, 0xf1, 0x7e, 0xaf, 0x34, 0x03, 0xda, 0x12, 0x22, 0xb3, 0xb4, 0xfa, 0x11, - 0x94, 0x88, 0x8a, 0x1f, 0x55, 0x46, 0xb5, 0x5a, 0x3b, 0xce, 0xfb, 0x44, 0x23, 0x65, 0xd3, 0x84, 0xc4, 0xd5, 0x12, - 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xdf, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x39, 0x7f, 0x9a, 0x8f, 0xb6, 0xf4, 0x35, 0xf8, - 0xd6, 0xe1, 0x90, 0x8f, 0x76, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x77, 0x24, 0x7b, 0x07, 0x6b, 0x0b, 0x9c, 0x20, - 0xc0, 0x01, 0xe0, 0x1f, 0x0e, 0xf4, 0x7b, 0x27, 0x7f, 0xab, 0xdd, 0xd2, 0xaa, 0xe7, 0xb3, 0x16, 0x77, 0xc6, 0xab, - 0xda, 0x10, 0xb5, 0xed, 0x25, 0xb6, 0xf4, 0xbe, 0x69, 0x50, 0x53, 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x8a, 0xc3, 0x82, - 0x94, 0x90, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0x58, 0x7a, 0x72, 0xdf, 0xe1, 0xe5, 0xd6, 0xf7, 0x01, 0x49, - 0xab, 0x70, 0xfe, 0xce, 0x0b, 0x0d, 0x3c, 0x7a, 0x91, 0x57, 0x45, 0x26, 0x46, 0x82, 0x46, 0xf9, 0x15, 0x89, 0x33, - 0x67, 0x58, 0x8b, 0x33, 0x05, 0x16, 0x16, 0x12, 0x24, 0x78, 0x51, 0x52, 0x7a, 0x70, 0xf6, 0x68, 0x5f, 0x36, 0x7f, - 0x10, 0x3c, 0xc4, 0x68, 0x01, 0x8c, 0x38, 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0xba, 0xcd, 0x0b, - 0x08, 0xd1, 0x3c, 0x93, 0x8a, 0xd5, 0xf2, 0x0c, 0x18, 0xf3, 0x44, 0x7c, 0x16, 0x56, 0x72, 0x1a, 0x54, 0x1d, 0xc5, - 0xaa, 0x6d, 0x3c, 0xca, 0x3d, 0xa0, 0xf8, 0x7e, 0x9f, 0x00, 0x97, 0xbb, 0xcf, 0x5e, 0x2a, 0xd7, 0x54, 0xd2, 0x23, - 0xcf, 0x21, 0x5a, 0xf2, 0x51, 0x02, 0x14, 0xcf, 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, - 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, - 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0x2d, 0xcc, 0xbd, 0x10, 0x86, 0x2a, - 0xe1, 0xde, 0xab, 0x7a, 0x16, 0xca, 0x4d, 0xd1, 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, - 0xaf, 0x13, 0x2f, 0x06, 0xc3, 0xf5, 0x92, 0x97, 0xb3, 0x8d, 0x59, 0x08, 0x87, 0xc3, 0x66, 0x52, 0xcc, 0x96, 0x10, - 0xe6, 0xba, 0x9c, 0x1f, 0x0e, 0x5d, 0x2d, 0x5b, 0x0b, 0x0f, 0x1e, 0xaa, 0x16, 0x6e, 0x1a, 0x96, 0xc3, 0xcf, 0x64, - 0x16, 0x63, 0xfb, 0x1a, 0x9f, 0xd9, 0x9f, 0x2f, 0xba, 0x67, 0x09, 0x92, 0x6f, 0xac, 0x81, 0x76, 0x6c, 0xd6, 0xee, - 0x70, 0x35, 0x02, 0x92, 0xd2, 0xdd, 0xe8, 0x1c, 0xcb, 0x4e, 0x9e, 0x12, 0xe4, 0x8e, 0x56, 0x60, 0xbf, 0xfb, 0xc6, - 0x9f, 0x68, 0xb1, 0x07, 0xed, 0x36, 0xb6, 0x84, 0xa8, 0xa6, 0x3d, 0x97, 0x2b, 0xc5, 0xd2, 0x0d, 0x96, 0x36, 0x7a, - 0x3e, 0xac, 0xcf, 0x7d, 0x23, 0x07, 0x0a, 0xc6, 0x88, 0xa7, 0xd6, 0x41, 0x34, 0x9b, 0x03, 0x0d, 0x06, 0x9a, 0x47, - 0x78, 0x6a, 0xa1, 0x83, 0x32, 0x6b, 0xc3, 0xfe, 0x29, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, - 0x31, 0xc5, 0xf6, 0xf8, 0xa5, 0x52, 0x54, 0x78, 0x6c, 0x47, 0x5c, 0x6b, 0x1f, 0x45, 0x6d, 0xa8, 0x1c, 0xfe, 0x2d, - 0xec, 0x23, 0xec, 0x0b, 0x9a, 0x20, 0x0c, 0x76, 0xfd, 0x99, 0x40, 0x88, 0x58, 0x88, 0x17, 0xfc, 0x52, 0x49, 0x2a, - 0x3a, 0xe1, 0xb3, 0x5d, 0x09, 0xbc, 0x75, 0x18, 0xd0, 0x27, 0xe4, 0x67, 0x22, 0x61, 0x68, 0x26, 0xf4, 0x8e, 0xfe, - 0x3b, 0xb1, 0x93, 0x4d, 0x72, 0x2b, 0xe4, 0x03, 0x49, 0x25, 0xc1, 0x04, 0x2b, 0x2f, 0x94, 0xaf, 0xdc, 0x0b, 0xa5, - 0xd6, 0x5a, 0xd0, 0xfa, 0xe5, 0x3f, 0x25, 0x9e, 0xc1, 0xdf, 0x03, 0x19, 0x83, 0x6e, 0x23, 0xaa, 0x49, 0x8e, 0xe9, - 0xa3, 0x74, 0x9e, 0x81, 0x0a, 0xe8, 0x6c, 0x9d, 0x85, 0xf5, 0xb2, 0x28, 0x57, 0xad, 0x48, 0x51, 0x59, 0xfa, 0x48, - 0x3d, 0xc6, 0xbc, 0x30, 0x4f, 0x4e, 0xe4, 0x83, 0x47, 0x00, 0x8c, 0x47, 0x79, 0x5a, 0x75, 0x94, 0xd6, 0x0f, 0x2c, - 0x03, 0x46, 0xe0, 0x44, 0x19, 0xf0, 0x08, 0xcb, 0xc0, 0x3c, 0xed, 0x32, 0xd4, 0x20, 0xd6, 0xa8, 0xba, 0x52, 0x1b, - 0xcc, 0x89, 0xa2, 0xe4, 0x53, 0x2c, 0xad, 0x30, 0x86, 0xa6, 0xae, 0x3c, 0xb2, 0x5e, 0x72, 0xc2, 0x9e, 0xec, 0x06, - 0xd2, 0x2d, 0x6c, 0x14, 0xce, 0xa0, 0x6b, 0x59, 0xa2, 0x5c, 0x74, 0xcb, 0x88, 0x32, 0x11, 0x52, 0x3f, 0x7b, 0x38, - 0xd3, 0x6a, 0xbf, 0xb1, 0x93, 0xf6, 0xed, 0x91, 0xa2, 0x17, 0x0c, 0xda, 0xa7, 0x3d, 0x52, 0xea, 0x59, 0x23, 0x97, - 0x81, 0x2d, 0x5d, 0xaa, 0x7a, 0xfe, 0x1b, 0x94, 0xef, 0x60, 0x66, 0x9c, 0xcd, 0xfe, 0xd0, 0x9b, 0xdb, 0xa3, 0x7d, - 0xdd, 0xfc, 0xc1, 0x7a, 0x3d, 0xd8, 0x1a, 0x64, 0xe2, 0x33, 0xc5, 0x42, 0x65, 0x15, 0x62, 0x05, 0x69, 0xff, 0x5b, - 0x78, 0x7f, 0xc0, 0x5b, 0x23, 0x34, 0x2b, 0xe3, 0x61, 0x3e, 0x7a, 0xb4, 0x17, 0xcd, 0x1f, 0x9d, 0x65, 0x5b, 0xb9, - 0x2a, 0x99, 0xed, 0x8f, 0xa3, 0xa4, 0x39, 0x7b, 0xb8, 0x46, 0x52, 0x07, 0xf8, 0x70, 0x7d, 0x86, 0x0f, 0x54, 0x42, - 0xa9, 0x05, 0x55, 0x0d, 0x5a, 0x1f, 0xfb, 0xa3, 0xf5, 0x9c, 0x3e, 0x7e, 0x2c, 0xa7, 0x5b, 0x52, 0x84, 0xf1, 0x03, - 0x83, 0x29, 0x3b, 0x71, 0xea, 0x92, 0x37, 0x43, 0x7a, 0xd7, 0xad, 0x92, 0xba, 0xec, 0x51, 0x22, 0x08, 0x75, 0xb0, - 0x7e, 0xb1, 0x1f, 0xc2, 0xcc, 0x16, 0xfd, 0x61, 0xb3, 0x9a, 0x13, 0x20, 0x22, 0xa0, 0xb5, 0xca, 0xfb, 0xc0, 0x31, - 0x5f, 0x98, 0x35, 0x37, 0xa4, 0x5b, 0x6f, 0xae, 0xb4, 0x57, 0x52, 0x40, 0x3f, 0x07, 0x99, 0xdb, 0x47, 0xb7, 0x5c, - 0xb5, 0xcc, 0x73, 0x69, 0xcb, 0x01, 0x8b, 0x16, 0x02, 0x35, 0x3b, 0x97, 0x0e, 0x07, 0x0a, 0x42, 0x5d, 0x89, 0x2a, - 0xe2, 0xea, 0x28, 0x5a, 0x88, 0x5a, 0xad, 0xda, 0xe5, 0x64, 0x53, 0x21, 0x5b, 0x12, 0x41, 0x46, 0xc9, 0x5e, 0x09, - 0xf5, 0x51, 0xae, 0xf6, 0x4c, 0xc3, 0x01, 0x9a, 0x80, 0x4d, 0x1b, 0xfc, 0x2d, 0x70, 0x2f, 0x83, 0x33, 0xd3, 0x3e, - 0x0d, 0x23, 0xe0, 0x34, 0x87, 0x98, 0x3f, 0xbf, 0xeb, 0x41, 0x05, 0x0f, 0x3a, 0xd2, 0x5f, 0xd5, 0xb3, 0x02, 0xcf, - 0xdc, 0x13, 0xcf, 0x5f, 0x9e, 0x48, 0x2f, 0x73, 0x78, 0xa0, 0x69, 0x10, 0x33, 0xfe, 0xac, 0x2c, 0xc3, 0xdd, 0x68, - 0x59, 0x16, 0x2b, 0x2f, 0xd2, 0xfb, 0x78, 0x26, 0xc5, 0x40, 0x62, 0xc6, 0xcc, 0xe8, 0x2a, 0xd6, 0x71, 0x0e, 0xe3, - 0xde, 0x9e, 0x84, 0x15, 0xda, 0x3f, 0x4b, 0xec, 0x75, 0x01, 0x58, 0x0e, 0x59, 0x83, 0x56, 0x78, 0xa7, 0xdb, 0xdb, - 0x3d, 0x2e, 0xd9, 0x51, 0xdc, 0x00, 0xfa, 0x59, 0x0d, 0x2d, 0x13, 0xd4, 0x32, 0xeb, 0x4e, 0x26, 0x53, 0x24, 0x97, - 0x6f, 0xc3, 0x5e, 0xb2, 0x32, 0x9f, 0x37, 0x72, 0x7b, 0x78, 0x1b, 0xae, 0x44, 0xac, 0x2d, 0xe8, 0xa4, 0x23, 0xe3, - 0x70, 0x2f, 0x34, 0x37, 0xd2, 0xfd, 0xa3, 0x2a, 0x09, 0x4b, 0x11, 0xc3, 0x2d, 0x90, 0xed, 0xd5, 0xb6, 0x12, 0x94, - 0xc0, 0x07, 0xfb, 0xbe, 0x14, 0xcb, 0x74, 0x2b, 0x00, 0xd7, 0x81, 0xff, 0x26, 0x11, 0x09, 0xdd, 0x9d, 0x87, 0x28, - 0xd6, 0xc8, 0xfb, 0x06, 0xd1, 0xd8, 0x3f, 0x81, 0x9c, 0x06, 0x64, 0x22, 0xc5, 0x48, 0x16, 0x0c, 0x7c, 0x00, 0x39, - 0x5f, 0x83, 0x49, 0x6e, 0x9a, 0x7b, 0x7e, 0x90, 0xeb, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, 0xb8, 0xd6, 0x2c, 0x07, 0xaf, - 0x98, 0x88, 0xff, 0xa3, 0xf6, 0x4a, 0x96, 0xb3, 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, - 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, - 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, 0x41, 0xe8, 0x1f, 0x35, 0x20, 0x6d, 0x30, 0x49, 0x93, 0x50, 0xf9, - 0xe0, 0x82, 0x6e, 0x18, 0x9b, 0x2b, 0x97, 0xab, 0x26, 0x55, 0xcb, 0x2f, 0x47, 0xd4, 0x77, 0xb5, 0xe4, 0x52, 0x6d, - 0x3e, 0x35, 0xca, 0x1a, 0x41, 0x26, 0x47, 0xe9, 0xf7, 0x29, 0x17, 0x6e, 0x65, 0x4c, 0xd6, 0x87, 0x83, 0x57, 0x70, - 0x53, 0xe3, 0x17, 0x39, 0x11, 0x8a, 0xda, 0x43, 0x22, 0x6c, 0xed, 0x56, 0xe8, 0xde, 0xe3, 0x46, 0x69, 0x1e, 0x65, - 0x9b, 0x58, 0x54, 0x5e, 0x2f, 0x01, 0x6b, 0x71, 0x0f, 0x78, 0x51, 0x69, 0xe9, 0x57, 0xac, 0x00, 0xf4, 0x00, 0x29, - 0x6c, 0xbc, 0x40, 0x06, 0xac, 0x77, 0x5e, 0xea, 0xf7, 0xfb, 0xc6, 0x94, 0xff, 0xee, 0x3e, 0x07, 0x92, 0x42, 0x51, - 0xd6, 0x3b, 0x98, 0x40, 0x70, 0xed, 0x24, 0xed, 0x59, 0xcd, 0x9f, 0xae, 0x6b, 0x0f, 0xf8, 0xad, 0x7c, 0x8b, 0xc4, - 0xea, 0x93, 0x7d, 0xb1, 0xd9, 0xa7, 0xd5, 0x47, 0xa3, 0x71, 0x10, 0x2c, 0xad, 0x5e, 0x69, 0x95, 0x43, 0xde, 0xf0, - 0x02, 0x44, 0x2a, 0xeb, 0xea, 0x5a, 0x39, 0x57, 0xd7, 0x82, 0x23, 0x97, 0x6c, 0xc9, 0x73, 0xf8, 0x2f, 0xe4, 0x5e, - 0x79, 0x38, 0x14, 0x7e, 0xbf, 0x9f, 0xce, 0x48, 0x2b, 0x0b, 0xec, 0x69, 0xeb, 0xda, 0x0b, 0xfd, 0xc3, 0xe1, 0x05, - 0x78, 0x8d, 0xf8, 0x87, 0x43, 0xd9, 0xef, 0x7f, 0x30, 0x37, 0x99, 0xf3, 0xb1, 0x52, 0xca, 0x5e, 0xa2, 0xd2, 0xfd, - 0x75, 0xc2, 0x7b, 0xff, 0x7b, 0xf4, 0xbf, 0x47, 0x97, 0x3d, 0xd9, 0xf5, 0x1f, 0x12, 0x3e, 0xc3, 0x1b, 0x3a, 0x53, - 0x97, 0x73, 0x26, 0xdd, 0xdd, 0x95, 0x1f, 0x7a, 0x4f, 0x43, 0xc5, 0xf7, 0xe6, 0xa6, 0x8d, 0xff, 0xa8, 0x8e, 0x34, - 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x43, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0x1c, 0x25, 0x43, 0xee, 0xe6, - 0x16, 0xa6, 0x03, 0xfb, 0x71, 0xf3, 0x55, 0xf2, 0xe2, 0x2c, 0x85, 0x6b, 0x6f, 0x3e, 0x4b, 0xe7, 0x53, 0xb0, 0xae, - 0x0c, 0xf3, 0x59, 0x3d, 0x0f, 0x20, 0x75, 0x08, 0x69, 0xd6, 0x34, 0xfc, 0x67, 0xe5, 0x0a, 0xde, 0xda, 0xe3, 0xdd, - 0xc0, 0x45, 0xa9, 0x23, 0x7d, 0xd2, 0x46, 0xd3, 0x25, 0x95, 0xfc, 0x07, 0x91, 0xc7, 0x18, 0xb3, 0xf1, 0x82, 0x78, - 0x3f, 0x8b, 0xfc, 0xba, 0x00, 0xec, 0x22, 0x00, 0x43, 0x4e, 0xe7, 0x8e, 0x24, 0xfe, 0x32, 0xf9, 0xfe, 0x8f, 0xe9, - 0xd2, 0xde, 0x97, 0xc5, 0x6d, 0x29, 0xaa, 0xea, 0xa8, 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, - 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0xe7, 0xbb, 0x57, - 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, - 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, 0xef, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, - 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, 0xfe, 0x54, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, - 0xb2, 0xbc, 0x3d, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x53, - 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, 0x9b, 0x79, 0xe2, 0x29, 0xd0, 0x31, 0x3f, 0x45, 0x57, 0xc5, - 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, 0xf1, 0xd5, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, - 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, - 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xb3, 0xb3, 0x07, - 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, - 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, - 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, - 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, - 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xc1, 0xb6, - 0xff, 0x2a, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, 0x37, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, - 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, - 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xab, 0x17, 0x67, 0x3f, 0xf6, 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xcf, 0x56, - 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, - 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, - 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, - 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x79, 0x02, 0xa1, 0x16, 0xcc, 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, - 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, - 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, 0xfd, 0x48, 0x05, 0xe5, 0xfc, 0x1f, 0xde, 0xde, 0x85, - 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, - 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, - 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, - 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0xec, 0xa5, 0x7a, 0x52, 0xae, 0x5f, 0x16, 0x8e, 0x32, - 0x65, 0x3f, 0xc4, 0x36, 0x46, 0x40, 0x75, 0xcb, 0x62, 0x13, 0x2e, 0x00, 0xb7, 0x73, 0x42, 0x9d, 0xf1, 0x1e, 0x6b, - 0x02, 0x73, 0x9a, 0x10, 0x14, 0xe6, 0x3a, 0x58, 0x18, 0x00, 0x7a, 0xd7, 0x1e, 0x6d, 0x39, 0xe9, 0x12, 0x2c, 0x9e, - 0x1b, 0x58, 0xbc, 0xba, 0x58, 0x54, 0x57, 0x5c, 0xcb, 0x2d, 0x6c, 0x4a, 0x59, 0xc5, 0x10, 0x40, 0xa0, 0x19, 0x33, - 0xec, 0x96, 0xbb, 0x1c, 0xc9, 0xba, 0x28, 0xb8, 0xd8, 0x0b, 0x0c, 0xdd, 0x8c, 0x4b, 0x66, 0x0e, 0xae, 0x66, 0x58, - 0x27, 0x15, 0x05, 0xd8, 0xd5, 0x05, 0xc8, 0x5e, 0x18, 0xea, 0xba, 0x99, 0x2d, 0xd7, 0x81, 0xaf, 0x4b, 0x17, 0xbe, - 0xa4, 0xe0, 0xe5, 0x4a, 0x8a, 0x32, 0xbb, 0xe6, 0x3f, 0xd9, 0x97, 0xcd, 0x58, 0x52, 0x68, 0x47, 0xfa, 0xba, 0xdd, - 0x1d, 0x2d, 0xc6, 0xb1, 0xe5, 0xf8, 0x96, 0x4a, 0xd7, 0x7a, 0x54, 0xbd, 0x10, 0xda, 0x3a, 0xd7, 0x32, 0x4b, 0x53, - 0x2e, 0x5e, 0x89, 0x34, 0x4b, 0xbc, 0xe4, 0x58, 0xc7, 0xaa, 0x76, 0x41, 0xb0, 0x5c, 0x98, 0xe4, 0x67, 0x59, 0x89, - 0xb1, 0x83, 0x1b, 0x8d, 0x6a, 0x45, 0x9d, 0x32, 0x31, 0x30, 0xe4, 0x7b, 0x0c, 0xbe, 0xcd, 0x8a, 0x04, 0x18, 0x7e, - 0x4c, 0xd4, 0x97, 0xf4, 0x14, 0x02, 0x3e, 0xa8, 0xd0, 0xdc, 0xcf, 0x38, 0x82, 0x5f, 0x5b, 0x95, 0x39, 0x30, 0xd9, - 0x5a, 0x05, 0x89, 0xb8, 0x77, 0xd9, 0x5c, 0x2f, 0xa2, 0x85, 0xba, 0x0b, 0xf5, 0xe2, 0xdd, 0xae, 0x97, 0x28, 0x3a, - 0xe0, 0xe4, 0xa7, 0xc1, 0x8b, 0x38, 0xcb, 0x79, 0x7a, 0x50, 0xc9, 0x03, 0xb5, 0xa1, 0x0e, 0x94, 0x33, 0x07, 0xec, - 0xbc, 0x6f, 0xab, 0x03, 0xbd, 0xa6, 0x0f, 0x74, 0x3b, 0x0f, 0xe0, 0x82, 0x81, 0x3b, 0xf7, 0x32, 0xbb, 0xe6, 0xe2, - 0x00, 0x94, 0x81, 0xd6, 0x78, 0xa0, 0x2e, 0xab, 0x91, 0x9a, 0x18, 0x1d, 0xc3, 0x3a, 0xd1, 0x07, 0x73, 0x40, 0x7f, - 0x86, 0xb0, 0xf6, 0xad, 0xb7, 0x2b, 0x7d, 0xd0, 0x06, 0xf4, 0xc5, 0xd2, 0xf4, 0x41, 0x07, 0x8e, 0x57, 0xd1, 0x81, - 0x1b, 0x43, 0xaa, 0x41, 0x5b, 0x8d, 0xac, 0x02, 0xc5, 0x1b, 0xde, 0xe2, 0xdd, 0xbb, 0x96, 0x6c, 0xbd, 0x97, 0x88, - 0xf1, 0x95, 0x89, 0x2a, 0xce, 0xc4, 0xa9, 0x97, 0xca, 0x6b, 0xed, 0x24, 0x23, 0x8c, 0x6f, 0x59, 0x49, 0xfd, 0x1d, - 0x62, 0x6e, 0x91, 0xe6, 0x30, 0x78, 0x15, 0x56, 0x64, 0xc6, 0xfb, 0x7d, 0x39, 0x93, 0x51, 0x39, 0x13, 0x87, 0x65, - 0xa4, 0xc0, 0xda, 0xee, 0x12, 0x01, 0xdd, 0x2b, 0x01, 0xf2, 0x05, 0x40, 0xd5, 0x7d, 0xc2, 0x9f, 0xfb, 0xa4, 0x3e, - 0x9d, 0x42, 0x9f, 0x42, 0x5b, 0xaf, 0xb8, 0x82, 0x78, 0x55, 0x37, 0x46, 0xb6, 0x51, 0x41, 0x8b, 0xc7, 0xf2, 0xac, - 0x36, 0x8c, 0xcd, 0xa9, 0xf5, 0xaf, 0x37, 0x1b, 0x4c, 0xd9, 0x5c, 0xa8, 0x55, 0x18, 0x92, 0xe8, 0x53, 0xe9, 0x45, - 0x12, 0xb1, 0xb0, 0x59, 0xad, 0xcd, 0x6f, 0xc2, 0x80, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, - 0x55, 0x5f, 0x6b, 0x69, 0x91, 0x69, 0xf3, 0xad, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, - 0x97, 0xb7, 0xac, 0x46, 0x98, 0x00, 0xaf, 0x74, 0x06, 0xdd, 0x68, 0x3c, 0x10, 0xcb, 0x6a, 0x54, 0xac, 0x85, 0x40, - 0xe0, 0x61, 0xc8, 0x31, 0xb3, 0x84, 0x24, 0xfb, 0xcc, 0x7f, 0x50, 0x71, 0x16, 0x8a, 0xf8, 0xc6, 0x20, 0x7b, 0x57, - 0xd6, 0xb5, 0xbb, 0x8e, 0xfc, 0x9c, 0x58, 0x58, 0xed, 0x3f, 0x34, 0x8f, 0x5a, 0xe3, 0x2c, 0xa0, 0xad, 0x69, 0x75, - 0xc3, 0xe1, 0x1e, 0xd5, 0xb1, 0x28, 0x0d, 0x36, 0xb1, 0x47, 0x96, 0x8b, 0xd6, 0x31, 0x83, 0x06, 0xf4, 0xb7, 0xd9, - 0xd5, 0xfa, 0x0a, 0x01, 0xdc, 0x4a, 0x64, 0x9d, 0xa4, 0xf2, 0x2f, 0x69, 0x8f, 0xba, 0xb6, 0xa7, 0xf2, 0xbf, 0x6d, - 0x53, 0xe5, 0xd0, 0x62, 0xca, 0x63, 0x37, 0x67, 0x81, 0xea, 0x48, 0x10, 0x05, 0x6a, 0xeb, 0x05, 0x53, 0xef, 0x94, - 0x29, 0x3a, 0x40, 0xa0, 0x0b, 0x73, 0x86, 0x7d, 0xc5, 0x11, 0x63, 0x96, 0x4a, 0x0c, 0xa6, 0x3e, 0xc6, 0xa8, 0xa6, - 0xb5, 0x02, 0x74, 0xfd, 0x74, 0x0b, 0x7f, 0xa2, 0xa2, 0x46, 0x43, 0xad, 0x91, 0x14, 0x8a, 0x26, 0x2a, 0x14, 0x59, - 0x5a, 0xe8, 0xb8, 0x0a, 0x9d, 0x44, 0xc2, 0x12, 0xd0, 0x30, 0x21, 0x3a, 0xa9, 0xc0, 0x5b, 0x03, 0x38, 0xf3, 0x71, - 0x51, 0xae, 0x0b, 0x6d, 0x30, 0xf7, 0x32, 0xbe, 0xe6, 0xaf, 0x9e, 0x39, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa7, 0x05, - 0x79, 0x19, 0x72, 0x8a, 0x0e, 0x4c, 0xec, 0x64, 0x8b, 0xc6, 0x18, 0x65, 0xad, 0xa3, 0x5e, 0xbc, 0xd5, 0xa1, 0x58, - 0xb4, 0x09, 0xde, 0x3d, 0x9e, 0x22, 0xda, 0xf0, 0x50, 0x18, 0xab, 0x6a, 0x7c, 0x2a, 0x59, 0x4b, 0x0f, 0x56, 0xf0, - 0x74, 0x9d, 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xc5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, - 0x2b, 0xf8, 0x7c, 0x81, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, 0xb8, 0x19, 0x05, 0x75, 0x74, 0x15, 0xaf, 0x1a, - 0x2a, 0x12, 0x3e, 0x2f, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, 0x95, 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0x03, - 0x5b, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, 0x99, 0x77, 0xcf, 0x8c, 0x96, 0x33, 0x8b, 0xc6, - 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x59, 0x50, 0xc4, 0x69, 0x16, 0xe7, 0xe0, 0xb7, 0x19, 0x17, 0x98, 0x31, - 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0xd0, 0x76, 0xe7, 0x2a, 0xb5, 0xae, 0x41, 0x40, 0xf6, 0x12, 0xac, 0x5e, 0x1a, 0x3a, - 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x12, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, - 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x6e, 0xf7, 0xcf, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, - 0x31, 0xf6, 0xcf, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, - 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, - 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, - 0x58, 0x87, 0xdb, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, - 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, - 0x14, 0xb6, 0xc5, 0x6e, 0xa7, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, 0x51, 0xfc, 0x27, 0xf7, 0xc2, 0x4e, - 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x4f, 0x0e, 0x17, 0x89, 0x1f, 0xa4, 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, - 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x9e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, - 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, - 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, - 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, - 0x71, 0xac, 0x89, 0x6a, 0xc1, 0x8f, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, - 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, - 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, - 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, - 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, - 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0x77, 0x0f, 0x09, 0x55, 0x71, 0x6f, 0x78, 0x3b, 0xee, 0x8d, 0x13, 0x7e, 0xcd, - 0xc5, 0x42, 0x87, 0x6a, 0x31, 0x97, 0x2c, 0xbf, 0xb5, 0xde, 0x2d, 0x49, 0x6a, 0x05, 0xb4, 0xcf, 0xb2, 0xa0, 0x26, - 0x02, 0x40, 0xfe, 0xf0, 0x17, 0x08, 0x9d, 0xe1, 0x6f, 0x8f, 0xc1, 0x15, 0x29, 0xbc, 0x73, 0x08, 0x84, 0x35, 0xdd, - 0xdc, 0xab, 0x0d, 0xf8, 0x62, 0xdc, 0x9f, 0x31, 0xf5, 0xf4, 0xdb, 0x4c, 0xee, 0xeb, 0xba, 0x3d, 0xb2, 0x0c, 0x1f, - 0xe1, 0x4a, 0x01, 0xdc, 0x4c, 0xf8, 0x8b, 0x61, 0x26, 0xd5, 0x27, 0x80, 0xa9, 0xa6, 0x83, 0xfb, 0x04, 0x81, 0x01, - 0x54, 0xa2, 0xc5, 0xe8, 0x5a, 0x39, 0xa2, 0x19, 0xb8, 0x35, 0xdd, 0x0a, 0xe3, 0xad, 0x07, 0x2d, 0xf4, 0x4c, 0xc3, - 0x89, 0xff, 0xa0, 0x99, 0x57, 0x05, 0x04, 0xd0, 0xca, 0x08, 0xde, 0x5a, 0x9f, 0xcc, 0x11, 0xe2, 0x13, 0x96, 0x44, - 0x13, 0x16, 0xcf, 0x14, 0x3f, 0x26, 0x74, 0xdb, 0xd4, 0x36, 0x7d, 0x44, 0xfa, 0x8b, 0x6b, 0xd6, 0x4f, 0x59, 0xd6, - 0xbe, 0x3d, 0x54, 0xbc, 0x98, 0x36, 0xe3, 0x20, 0x26, 0xaa, 0x18, 0xff, 0x0b, 0xee, 0x4b, 0xad, 0x00, 0x91, 0xb9, - 0xab, 0x9e, 0x7e, 0xbf, 0x99, 0x2d, 0x07, 0x42, 0xe5, 0x77, 0x06, 0x49, 0x9f, 0x0e, 0xed, 0x07, 0x36, 0x89, 0xda, - 0x42, 0xcf, 0x1f, 0x97, 0xba, 0x89, 0x97, 0xd7, 0xa6, 0x46, 0xb4, 0x42, 0x86, 0xca, 0xd6, 0x01, 0xeb, 0xfb, 0x65, - 0xb8, 0xbf, 0xa8, 0x69, 0xa8, 0x75, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x7f, 0x80, 0xb1, 0xb8, 0x90, 0xd4, 0x3a, 0x1e, - 0x93, 0x7e, 0xb4, 0x90, 0xc9, 0x8d, 0xba, 0x3a, 0x39, 0x53, 0xcc, 0x13, 0xb8, 0x00, 0x97, 0x6d, 0x7f, 0x45, 0xa5, - 0x2e, 0xe5, 0xf6, 0x8a, 0xd2, 0xf4, 0x90, 0xb6, 0x57, 0x71, 0xde, 0x16, 0x5c, 0xf0, 0xaf, 0x14, 0x5c, 0x58, 0x07, - 0xeb, 0x8e, 0x3b, 0x65, 0x4f, 0x78, 0xa2, 0x4c, 0x6b, 0x83, 0xbb, 0x6e, 0x30, 0x26, 0xc6, 0x7e, 0x77, 0xc9, 0x93, - 0x4f, 0xc8, 0x82, 0xff, 0x90, 0x09, 0xf0, 0x4c, 0x76, 0xaf, 0x54, 0xfe, 0x97, 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, - 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xbd, 0x92, 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, - 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0x3b, 0x09, 0xdc, 0xf4, 0xee, 0xda, 0xcc, 0xcc, - 0xe9, 0x5a, 0x89, 0xa6, 0x4b, 0x63, 0x6b, 0x59, 0xaa, 0x30, 0xde, 0xef, 0x3c, 0xc9, 0xa6, 0xf9, 0xf1, 0x72, 0x9a, - 0x5b, 0xea, 0xb6, 0x75, 0xcb, 0x06, 0xd0, 0x10, 0xbb, 0xd6, 0x56, 0x0e, 0x78, 0xb9, 0x3d, 0x88, 0xe6, 0x6b, 0x45, - 0xe8, 0xa9, 0x12, 0xa1, 0x4f, 0xd3, 0x66, 0x1f, 0xec, 0xaa, 0x5a, 0x37, 0x42, 0x1e, 0x0d, 0x52, 0xcd, 0xc8, 0xbf, - 0xbd, 0xe6, 0xc5, 0x45, 0x2e, 0x6f, 0x00, 0x0e, 0x99, 0xd4, 0x46, 0x61, 0x79, 0x05, 0xee, 0xfc, 0xe8, 0x38, 0xce, - 0xc4, 0x28, 0xc7, 0xb8, 0xad, 0x88, 0x94, 0xac, 0x13, 0x67, 0x80, 0x87, 0xec, 0x4f, 0x9a, 0x0e, 0xed, 0x5a, 0x60, - 0x78, 0x5f, 0xe0, 0xae, 0x72, 0x76, 0xb2, 0xcd, 0xed, 0xa2, 0x6f, 0xce, 0xb0, 0xee, 0x48, 0x69, 0x6d, 0x2c, 0xba, - 0xee, 0x60, 0xad, 0x19, 0xb4, 0x45, 0x28, 0xf9, 0x90, 0x3b, 0x69, 0x3f, 0x07, 0x34, 0x38, 0xcb, 0xd2, 0x5b, 0x6b, - 0x95, 0xbf, 0xd5, 0x42, 0x9c, 0x28, 0xa6, 0x4e, 0x7c, 0x13, 0x25, 0xfa, 0xfc, 0x4c, 0x8c, 0x1b, 0x08, 0xa4, 0xbe, - 0xc4, 0xf8, 0x1a, 0x45, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xed, 0x89, 0xda, 0x58, 0x8e, 0xa0, 0x13, 0x42, 0xbc, 0x83, - 0x32, 0x8c, 0xd5, 0xc5, 0x81, 0x36, 0x58, 0xfa, 0xba, 0xb5, 0xce, 0x0d, 0xa1, 0x30, 0x4e, 0x60, 0x8a, 0x41, 0x52, - 0x67, 0x9d, 0x65, 0x82, 0x2a, 0x3b, 0x26, 0x9d, 0xf7, 0x01, 0xba, 0xbf, 0x16, 0x4d, 0xf1, 0x75, 0xe7, 0x0e, 0xba, - 0x8b, 0xeb, 0xd7, 0x5a, 0xe4, 0x06, 0x7f, 0xde, 0x12, 0x61, 0x11, 0x38, 0x6b, 0x4d, 0xbe, 0x6a, 0x84, 0x03, 0x53, - 0x92, 0x69, 0xd8, 0xcb, 0x95, 0x4d, 0xf7, 0x6e, 0xd7, 0xeb, 0xdd, 0x29, 0xe2, 0xea, 0x31, 0x56, 0x79, 0x37, 0x73, - 0x7b, 0xa7, 0x5a, 0x8b, 0xfd, 0x9b, 0xb6, 0x9f, 0x62, 0x47, 0xad, 0xb5, 0xdb, 0x0d, 0x27, 0xd4, 0x90, 0x6f, 0x45, - 0x95, 0x56, 0xa7, 0x1b, 0x83, 0x76, 0x08, 0x6d, 0x2d, 0x32, 0xb8, 0x51, 0x3e, 0x73, 0x42, 0x27, 0x15, 0x72, 0xd5, - 0xa9, 0x0b, 0xb6, 0x57, 0xbc, 0x5a, 0xca, 0x34, 0x12, 0x14, 0x6d, 0xce, 0xa3, 0x92, 0x26, 0x72, 0x2d, 0xaa, 0x48, - 0xd6, 0xa8, 0x17, 0xb5, 0x1a, 0x03, 0x04, 0x64, 0x3a, 0x6b, 0x7a, 0x50, 0x05, 0xb3, 0xa1, 0x8c, 0xe4, 0xf4, 0x0d, - 0x58, 0xda, 0x23, 0xc7, 0x5a, 0xdf, 0x55, 0x67, 0x8b, 0x6f, 0xf5, 0x84, 0x60, 0x0a, 0xb3, 0x07, 0x22, 0xc2, 0x35, - 0x8d, 0x21, 0xa7, 0x5d, 0xe2, 0xb2, 0xa6, 0x5b, 0xc2, 0x1d, 0xdc, 0xae, 0x64, 0x27, 0x6e, 0x9e, 0x34, 0x37, 0x57, - 0xb0, 0x93, 0x62, 0x3e, 0x06, 0xed, 0x97, 0x54, 0xd7, 0x2e, 0xcd, 0xad, 0xc7, 0x83, 0x80, 0x06, 0x83, 0xc2, 0xf0, - 0xaf, 0x13, 0xe3, 0xe1, 0x49, 0x03, 0x82, 0xa4, 0x5c, 0x84, 0x63, 0xdf, 0x88, 0x7e, 0x32, 0x95, 0xc7, 0x1c, 0x2d, - 0xde, 0xa1, 0xd5, 0x39, 0x04, 0xf4, 0x12, 0xa1, 0x24, 0x46, 0x55, 0x68, 0x44, 0x50, 0x9e, 0x96, 0xbf, 0x54, 0xd5, - 0x21, 0xa0, 0x90, 0xf6, 0x15, 0x85, 0xb2, 0x4d, 0x62, 0x68, 0x86, 0x5f, 0xce, 0x27, 0x0b, 0x3d, 0x03, 0x03, 0x39, - 0x3f, 0x5a, 0xe8, 0x59, 0x18, 0xc8, 0xf9, 0xa3, 0x45, 0xed, 0xd6, 0x81, 0x26, 0x20, 0x9e, 0x0b, 0x47, 0x27, 0xa5, - 0x55, 0xd9, 0x02, 0xba, 0xbd, 0x8f, 0xa0, 0xff, 0xd3, 0x1e, 0x82, 0x4e, 0x2e, 0xb4, 0x27, 0x37, 0xa0, 0xed, 0x90, - 0x04, 0xf6, 0x8a, 0x49, 0x85, 0x89, 0x45, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0xad, 0x3e, 0x38, 0x66, 0xe3, 0xa9, 0x4f, - 0x82, 0x80, 0xd1, 0x7d, 0x69, 0xc0, 0xc1, 0x6f, 0xf1, 0x2a, 0x7d, 0xb2, 0x15, 0xe8, 0xa6, 0xef, 0xee, 0x86, 0xde, - 0xc5, 0x15, 0x9c, 0xaa, 0xdd, 0x3d, 0x09, 0xdd, 0x64, 0xda, 0xb1, 0x7a, 0x0d, 0x71, 0x43, 0x7e, 0x65, 0x34, 0x1a, - 0xd9, 0x94, 0x90, 0x10, 0xc3, 0x39, 0x34, 0x73, 0x5a, 0x2e, 0x5f, 0xdd, 0x7a, 0xb6, 0x20, 0xc3, 0x4c, 0x6f, 0x99, - 0xac, 0xef, 0xa1, 0xac, 0x7a, 0x0c, 0xed, 0xd0, 0x7b, 0xe4, 0xf8, 0xfe, 0xc1, 0x37, 0x19, 0xbf, 0x70, 0xb8, 0xf6, - 0x70, 0x2e, 0x7c, 0x97, 0x35, 0x23, 0x73, 0xe8, 0x3c, 0xfb, 0x38, 0xde, 0xc3, 0x38, 0xf9, 0x32, 0x0b, 0xe5, 0x8d, - 0xd7, 0xf4, 0xbf, 0x55, 0x7a, 0xb3, 0xc3, 0x21, 0xa7, 0x2b, 0x58, 0x71, 0xb3, 0x2a, 0x34, 0xfc, 0x2c, 0xf2, 0xc6, - 0x11, 0xaf, 0x49, 0x54, 0x75, 0x9f, 0xf7, 0x36, 0x62, 0x69, 0xc7, 0x38, 0x00, 0x38, 0x51, 0xab, 0x86, 0x7d, 0x69, - 0x5c, 0xab, 0x83, 0x18, 0x91, 0x12, 0xb6, 0x4a, 0x1c, 0x09, 0xe5, 0x6f, 0x00, 0xc2, 0x62, 0x28, 0x8e, 0xb7, 0x86, - 0xf5, 0x1e, 0xf6, 0x43, 0x17, 0x68, 0x9a, 0x53, 0xaa, 0x19, 0x00, 0x24, 0x01, 0x7f, 0xf4, 0x74, 0xd3, 0x50, 0xd9, - 0xe6, 0x79, 0x68, 0x59, 0x5d, 0xc1, 0x3d, 0x3d, 0x75, 0x25, 0x03, 0xe3, 0xaa, 0x8e, 0xbd, 0xed, 0xdd, 0xed, 0xd1, - 0x2a, 0xf2, 0xbd, 0x4d, 0x6a, 0x9a, 0x05, 0x90, 0xa2, 0x71, 0xe9, 0x0b, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, - 0xf6, 0xfb, 0x28, 0x46, 0x8d, 0x0b, 0x05, 0x56, 0x61, 0x82, 0xc2, 0x21, 0xc2, 0x08, 0xa1, 0x3f, 0x97, 0xe1, 0xd6, - 0x17, 0x64, 0x10, 0x0d, 0xd7, 0xa2, 0x43, 0x11, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, - 0x22, 0x03, 0xb6, 0xf3, 0x4f, 0x1b, 0x22, 0x57, 0xe1, 0x02, 0x86, 0xef, 0x89, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, - 0x1b, 0x76, 0x88, 0x8e, 0xa6, 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x81, 0xdc, 0x35, 0x9d, - 0xbd, 0x14, 0x61, 0x50, 0xb7, 0x6c, 0xa0, 0x58, 0xc7, 0x4e, 0x50, 0x80, 0x01, 0x5c, 0x3e, 0x03, 0x1d, 0x1b, 0x0c, - 0x2a, 0x82, 0x4f, 0x0a, 0xdb, 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0x2f, - 0x94, 0x70, 0xf7, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf3, 0x5c, 0x6b, 0x4a, - 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, 0x51, 0xe5, 0xb1, 0x44, 0x91, - 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, 0xb4, 0xcb, 0x96, 0xb9, 0x04, - 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x3d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x47, 0x4d, - 0xbf, 0x7a, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x9f, 0xb0, 0xf1, 0x74, - 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x0a, 0x5a, 0x67, 0x26, 0xae, 0xf1, 0x69, 0xfb, 0x0a, 0x5a, - 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, 0xa9, 0x64, 0x7f, 0x2e, 0xad, - 0xc3, 0xbe, 0x5d, 0x28, 0xb4, 0xd0, 0xc4, 0xaf, 0x32, 0xc4, 0x4f, 0x5d, 0x67, 0xfe, 0x63, 0xda, 0xa7, 0x06, 0xb1, - 0x70, 0x24, 0x06, 0x11, 0xbf, 0x38, 0x55, 0xb6, 0x13, 0x42, 0xc5, 0xc6, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0x18, - 0x4a, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, 0x0b, 0x1d, 0xbe, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, - 0x9c, 0x4a, 0xb9, 0x8a, 0x04, 0x06, 0xca, 0xb3, 0x85, 0x41, 0x80, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0x84, 0xb1, - 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, - 0x71, 0x94, 0x6a, 0xfc, 0x47, 0x84, 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x09, 0x84, 0x40, - 0x73, 0xf6, 0x53, 0x71, 0xb5, 0x37, 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xaa, 0x2e, 0x50, - 0x2f, 0x64, 0xf1, 0x5a, 0xa6, 0xbc, 0x15, 0x22, 0xf3, 0x40, 0xb2, 0xf7, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, - 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x88, 0x33, 0xb6, - 0x77, 0x12, 0x6e, 0xef, 0xe6, 0x81, 0x21, 0x4a, 0xb9, 0x68, 0x89, 0x86, 0xad, 0x1d, 0xaf, 0x27, 0xd7, 0x84, 0xfb, - 0xb0, 0x11, 0x6b, 0x32, 0xc6, 0xb8, 0x36, 0x37, 0xb2, 0x7e, 0xb4, 0xc0, 0x83, 0x31, 0x65, 0xfd, 0x09, 0x64, 0x5a, - 0x49, 0x59, 0xe7, 0x0b, 0x23, 0x66, 0x52, 0x89, 0xde, 0xed, 0x1b, 0x9f, 0xd5, 0x5d, 0x44, 0xfd, 0xd6, 0x7e, 0x4f, - 0xea, 0x61, 0xe3, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, 0x37, 0x4d, 0x8a, 0x38, 0x3d, - 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, 0x24, 0x49, 0xd6, 0xd2, 0xd8, - 0x8a, 0x5d, 0x1a, 0xa4, 0xe7, 0xce, 0x88, 0x4b, 0x2f, 0x2a, 0x34, 0xa4, 0xa5, 0xde, 0x59, 0xa8, 0x64, 0xfe, 0x8a, - 0xff, 0x0c, 0x6a, 0x05, 0x3a, 0xda, 0xa4, 0x18, 0x4f, 0x81, 0x11, 0xdf, 0x0f, 0x66, 0x75, 0x0f, 0x71, 0xd1, 0x04, - 0xa5, 0xde, 0x13, 0x3b, 0x7e, 0x69, 0xf2, 0xf0, 0x2e, 0xe4, 0x9c, 0xc1, 0xa7, 0xf7, 0xb3, 0x44, 0xad, 0x75, 0x24, - 0x46, 0x6a, 0x06, 0xd0, 0x74, 0x50, 0xe6, 0x3c, 0x16, 0xc1, 0xac, 0x67, 0x12, 0xa3, 0x1e, 0xd7, 0xbf, 0x40, 0x43, - 0xed, 0x37, 0x2b, 0xcb, 0xb3, 0x6a, 0xf3, 0x35, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, 0x75, 0x25, 0x2f, 0x2f, 0x55, - 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, 0x37, 0x8b, 0xbb, 0x59, 0x46, - 0x03, 0x61, 0x6d, 0xef, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, 0x00, 0x10, 0xe9, 0x41, 0x14, - 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xde, 0xc5, 0x51, 0x16, 0x4a, 0x2f, 0x67, 0x19, 0x3f, 0x6d, 0x1a, 0x6b, 0x9d, 0x15, - 0xca, 0xd0, 0xda, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, 0x49, 0x9c, 0x2d, 0xc0, 0xfd, 0x31, 0x43, 0xa1, 0xa1, 0xb3, - 0x8c, 0x34, 0xd1, 0xf0, 0x5d, 0x77, 0x0c, 0x32, 0x8a, 0x93, 0x75, 0x5e, 0x49, 0xb7, 0xfa, 0xac, 0x8d, 0x84, 0xb9, - 0x87, 0xe8, 0x57, 0x31, 0x78, 0x94, 0xfb, 0xbc, 0x36, 0x3a, 0x99, 0x96, 0x91, 0x76, 0xe7, 0x27, 0xf5, 0x32, 0x4b, - 0xb5, 0x0e, 0xdb, 0x67, 0xd8, 0x5b, 0x63, 0xd2, 0x9b, 0x90, 0x1a, 0x46, 0xe2, 0xcb, 0x19, 0x35, 0x42, 0x40, 0x5b, - 0x8e, 0xbf, 0xc7, 0x67, 0x18, 0x9a, 0x02, 0x4b, 0x15, 0xb7, 0xb0, 0x1b, 0xbe, 0xe6, 0x93, 0x55, 0x0b, 0x40, 0x30, - 0x2b, 0x5f, 0xef, 0xe2, 0x95, 0x50, 0x9f, 0x69, 0x33, 0x00, 0x64, 0x41, 0x29, 0x77, 0xfc, 0x94, 0x4a, 0x07, 0x4b, - 0x14, 0x6d, 0x2f, 0xa7, 0x6f, 0x74, 0x6c, 0x7c, 0x9f, 0x9e, 0x0b, 0xd8, 0x2e, 0xe4, 0xb7, 0xee, 0xd4, 0x4b, 0x54, - 0xa4, 0xb6, 0xcd, 0xba, 0x87, 0x2f, 0x37, 0x68, 0x12, 0x46, 0x50, 0xa6, 0x4c, 0x01, 0x0c, 0x6e, 0xaa, 0x51, 0x30, - 0x69, 0x35, 0x12, 0xb6, 0xd4, 0x93, 0x2c, 0x37, 0x7d, 0x70, 0xaa, 0x3b, 0x04, 0x3d, 0xb7, 0xca, 0xf9, 0xa2, 0x65, - 0xbf, 0x56, 0x70, 0x74, 0x72, 0x35, 0x44, 0xcd, 0xbc, 0xd7, 0x76, 0x64, 0x48, 0xb9, 0x0c, 0x03, 0xc1, 0x94, 0x63, - 0x9e, 0x1e, 0x5b, 0xcf, 0x88, 0xe8, 0x9e, 0xb3, 0xcf, 0x74, 0xab, 0xae, 0x24, 0x20, 0x3a, 0x7e, 0xf7, 0xf8, 0xd5, - 0x55, 0x7c, 0x69, 0x50, 0x94, 0x1a, 0x16, 0x31, 0xca, 0xb4, 0xaf, 0x92, 0x30, 0x78, 0xbf, 0xbc, 0xff, 0x49, 0x65, - 0xa9, 0xfd, 0x1e, 0x6c, 0xad, 0xa8, 0xea, 0x97, 0x92, 0x17, 0x4d, 0x01, 0xd6, 0x5d, 0x96, 0x28, 0x90, 0xfb, 0xbd, - 0x4d, 0x33, 0xdf, 0x44, 0x8d, 0x9b, 0x0d, 0xeb, 0x8d, 0xeb, 0x76, 0xa9, 0x2d, 0xd9, 0x91, 0x95, 0xc8, 0x99, 0xc5, - 0x60, 0xc6, 0x8f, 0x0a, 0x83, 0xd2, 0xb0, 0x45, 0x55, 0x2a, 0x7e, 0x6f, 0x44, 0x70, 0xea, 0x58, 0x55, 0x18, 0xd3, - 0x80, 0xd9, 0x56, 0xd4, 0x1a, 0xd4, 0x41, 0x29, 0x6d, 0x4d, 0x40, 0xb6, 0x7f, 0xb1, 0x82, 0x9a, 0xdf, 0xff, 0x36, - 0x86, 0x7c, 0x4d, 0x29, 0xa8, 0x24, 0x60, 0x67, 0xd0, 0xe8, 0xa9, 0x12, 0x06, 0x52, 0x10, 0x3c, 0x01, 0xca, 0x17, - 0x51, 0x63, 0xb5, 0xdf, 0x57, 0xa7, 0xc6, 0x68, 0x0b, 0x08, 0x2d, 0xa4, 0x47, 0x97, 0x7d, 0xdc, 0xd6, 0x3a, 0x90, - 0x78, 0x70, 0x82, 0xed, 0x5c, 0x5d, 0xa3, 0x91, 0xd0, 0xfc, 0xbe, 0xd1, 0x80, 0xd7, 0xb4, 0x02, 0x85, 0x7a, 0x8e, - 0xa3, 0xa1, 0xb3, 0x43, 0x0a, 0x22, 0x36, 0x68, 0x61, 0xdf, 0x1d, 0x1f, 0x9a, 0x7d, 0x3d, 0x4f, 0x16, 0xa4, 0xa6, - 0xd2, 0x7d, 0xee, 0x96, 0x90, 0xb5, 0xea, 0x50, 0x56, 0x1e, 0xe0, 0x78, 0xa1, 0x64, 0xfe, 0x0e, 0x93, 0x1a, 0xa5, - 0x31, 0xa1, 0x31, 0x62, 0x01, 0x4b, 0x82, 0xf6, 0x7a, 0xa0, 0x7e, 0x19, 0x84, 0x0a, 0x67, 0x7a, 0x22, 0xf1, 0x29, - 0xe5, 0xea, 0xd3, 0x82, 0xd4, 0xd3, 0x82, 0x39, 0xd0, 0x4b, 0xdf, 0xca, 0xaf, 0x6c, 0x7c, 0xb4, 0xbf, 0x77, 0xcd, - 0x85, 0x75, 0x0c, 0x71, 0xb1, 0x85, 0xdf, 0x9c, 0x9a, 0x02, 0xb0, 0xe1, 0xa9, 0x2e, 0xcb, 0x37, 0x6a, 0x22, 0xb3, - 0x38, 0x24, 0x11, 0x48, 0xb6, 0x9b, 0x9b, 0xdb, 0x08, 0xb6, 0xbd, 0x85, 0xda, 0x50, 0x7f, 0x79, 0xdb, 0xfd, 0x8e, - 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xf2, 0xee, 0x55, 0xf2, 0x7f, 0x55, 0xc9, 0xdd, 0x56, 0x99, 0x75, - 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, 0x35, 0x05, 0x06, 0xd2, 0x93, 0xc6, 0x34, 0xd1, 0xd1, 0x95, - 0x19, 0x33, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, 0xc7, 0x00, 0x1c, 0xe0, 0x1f, 0x79, 0x84, 0xfa, 0xa7, 0xf3, - 0x3c, 0x38, 0x0b, 0x06, 0xe5, 0x20, 0xd0, 0x9f, 0xb8, 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0xe2, 0x4e, 0x5a, - 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, 0x02, 0x48, 0x5f, 0xbc, 0xb0, 0xce, 0x41, 0x85, 0x5e, 0x90, - 0xad, 0xba, 0x8b, 0x66, 0xc5, 0x5e, 0xb5, 0xd3, 0xbc, 0xdf, 0xcf, 0xe7, 0xe5, 0x20, 0x68, 0x54, 0x58, 0x18, 0xef, - 0x3f, 0xda, 0xfc, 0xd2, 0xe8, 0xa4, 0x09, 0x46, 0xac, 0x3d, 0x45, 0xf5, 0x8a, 0xa7, 0x19, 0x6d, 0xdc, 0x8e, 0x95, - 0xf2, 0x05, 0x44, 0xf1, 0xc0, 0x90, 0xb5, 0xf2, 0xee, 0x1d, 0xbc, 0x2e, 0x37, 0xde, 0x1c, 0x51, 0x80, 0xdd, 0x14, - 0xc6, 0x49, 0xcd, 0x45, 0x17, 0x35, 0xf1, 0x0c, 0x76, 0xba, 0x7a, 0x2b, 0xd1, 0x6a, 0xbc, 0x17, 0xef, 0x9b, 0x8d, - 0xbf, 0x91, 0x07, 0xba, 0xcc, 0x83, 0x0b, 0x40, 0x9c, 0x3d, 0x88, 0xab, 0x03, 0x2c, 0xf5, 0x20, 0x18, 0x58, 0xe4, - 0x90, 0x76, 0xb5, 0x7a, 0x28, 0x22, 0x75, 0x1e, 0x83, 0x01, 0x93, 0x69, 0x48, 0x4d, 0xa6, 0xbd, 0x58, 0x41, 0xda, - 0x58, 0x6b, 0x01, 0x6d, 0x38, 0x2c, 0xf6, 0xec, 0x86, 0xdd, 0xe9, 0xd6, 0xa1, 0x50, 0xc2, 0x40, 0xd6, 0x75, 0xf3, - 0x50, 0x6b, 0x78, 0x22, 0xe8, 0x41, 0x35, 0xda, 0x4f, 0x0f, 0xe5, 0x49, 0x7b, 0x2c, 0xc0, 0x45, 0x0f, 0x5f, 0x3e, - 0x17, 0x78, 0xd1, 0xde, 0x43, 0x9e, 0x33, 0x9f, 0x2a, 0x1f, 0xc4, 0x86, 0x5b, 0x86, 0x0f, 0xed, 0xe3, 0x5b, 0x81, - 0x4c, 0xea, 0x8e, 0xa6, 0xb6, 0x76, 0x47, 0xe3, 0x98, 0x40, 0xbf, 0x29, 0x47, 0x29, 0x13, 0x53, 0xcb, 0x92, 0x9d, - 0xf4, 0x72, 0xe5, 0x0d, 0x95, 0xb2, 0x93, 0x65, 0x9b, 0xf3, 0x4b, 0x1b, 0x09, 0xfd, 0xbe, 0x76, 0x07, 0xc2, 0x37, - 0x6a, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, 0xf1, 0x42, 0x2a, 0xd7, 0xee, 0xa2, 0xa9, 0xaa, 0xdb, - 0xdb, 0xca, 0x05, 0x2d, 0xf1, 0x56, 0x0a, 0xac, 0x22, 0x75, 0x7a, 0x3d, 0x95, 0x78, 0xd7, 0x47, 0xb1, 0xfd, 0x08, - 0xd8, 0xc6, 0xc6, 0xd1, 0xd8, 0xb8, 0x45, 0x6c, 0xf1, 0x55, 0x54, 0xd1, 0x82, 0x03, 0x04, 0x77, 0x5b, 0x52, 0x4b, - 0x33, 0x87, 0xb8, 0xaf, 0x78, 0x80, 0xf6, 0x5d, 0x1c, 0xce, 0xa4, 0x02, 0x6c, 0xeb, 0x5a, 0xe7, 0xac, 0x96, 0x03, - 0x36, 0x13, 0x3d, 0xff, 0xb4, 0x6a, 0x24, 0x62, 0x58, 0x65, 0x23, 0x65, 0x85, 0x76, 0xaf, 0x74, 0x09, 0x17, 0x5f, - 0x80, 0x97, 0xed, 0xbb, 0x95, 0xdd, 0x67, 0x4b, 0xec, 0x1f, 0xe6, 0x55, 0x13, 0x3c, 0xf2, 0x1a, 0x6f, 0xef, 0x61, - 0xe2, 0x6b, 0xa5, 0x10, 0x5e, 0xa5, 0x34, 0x94, 0x00, 0x0c, 0x92, 0xa0, 0x86, 0x2b, 0x6d, 0x9b, 0x41, 0x2a, 0x63, - 0xd8, 0xfd, 0xea, 0xad, 0xfe, 0x4f, 0xab, 0x70, 0x51, 0xc9, 0x62, 0x4c, 0x02, 0x9d, 0x53, 0x2d, 0x37, 0x81, 0x05, - 0xcf, 0xf6, 0xc9, 0x11, 0x28, 0xec, 0x04, 0x70, 0x43, 0x09, 0xfb, 0x0b, 0x6f, 0x43, 0x39, 0xfb, 0x6c, 0x25, 0x4f, - 0x6e, 0x5f, 0x52, 0x41, 0x13, 0x32, 0x15, 0x76, 0xff, 0xb6, 0x36, 0xec, 0xb3, 0x50, 0x8e, 0xa4, 0xc0, 0xc5, 0x41, - 0xe7, 0x00, 0xf6, 0x07, 0xb9, 0x8c, 0xcd, 0x67, 0xd2, 0xef, 0xab, 0xf7, 0x4f, 0xf3, 0x2c, 0xf9, 0xb4, 0xf7, 0xde, - 0xf0, 0x34, 0x4b, 0x06, 0x54, 0x22, 0xa6, 0xd6, 0x55, 0x31, 0x5c, 0x6a, 0x17, 0xe3, 0x06, 0xc9, 0x88, 0xef, 0xa4, - 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x3d, 0x92, 0x92, 0xd3, 0x65, 0xdd, 0xd9, 0x73, 0x2d, 0x9a, 0x41, 0x63, 0xb8, 0x3d, - 0xef, 0x25, 0xbd, 0x02, 0x54, 0x80, 0xe8, 0x9e, 0x05, 0xae, 0xe1, 0xcd, 0x25, 0xd1, 0xd8, 0xd2, 0xd3, 0x96, 0x68, - 0xe0, 0x4e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x14, 0x16, 0x00, 0xd4, 0x6a, 0x90, 0x5e, 0xe9, - 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, 0x03, 0xfa, 0xaa, - 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x4f, 0x4b, 0x93, 0x04, 0x82, - 0x12, 0x94, 0x6f, 0xd0, 0xdf, 0x4b, 0xcf, 0xc7, 0xf2, 0x1f, 0xde, 0xa1, 0xf4, 0x32, 0x2c, 0x40, 0xa6, 0xa8, 0x2b, - 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, 0x59, 0x86, 0x38, - 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, 0x4a, 0x20, 0xca, - 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, 0xa4, 0x99, 0x5d, - 0x87, 0x11, 0xa9, 0xf6, 0x92, 0xcc, 0x97, 0xff, 0x90, 0x99, 0xf0, 0xbe, 0x81, 0xc7, 0x66, 0xb3, 0x6c, 0x8a, 0xf9, - 0x42, 0x05, 0x73, 0x70, 0x9f, 0xa8, 0xb8, 0x14, 0x95, 0xff, 0x84, 0x5d, 0xf0, 0x62, 0x3c, 0x78, 0xbd, 0x46, 0x80, - 0xfd, 0xca, 0x7f, 0xf2, 0xc6, 0xec, 0x07, 0xeb, 0xc6, 0x97, 0x99, 0x88, 0x0f, 0x7c, 0x74, 0x4b, 0xf9, 0x68, 0xe3, - 0x65, 0xfa, 0xb5, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x93, 0x44, 0xd9, 0xa8, 0xe2, 0x02, - 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x82, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, 0x61, 0x99, 0xa9, - 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x9f, 0x92, 0xe8, 0x87, 0xa5, 0x07, 0x22, 0x67, 0xa6, 0x6c, 0x5b, 0x3b, - 0x42, 0x6d, 0x7c, 0x1d, 0xe9, 0x56, 0x5b, 0x00, 0xc0, 0x3d, 0x5b, 0xa4, 0x91, 0x64, 0x62, 0x38, 0xa9, 0x19, 0x37, - 0xe9, 0x05, 0xa6, 0xc6, 0x35, 0xab, 0x68, 0xe2, 0x2c, 0x64, 0x40, 0xef, 0x4f, 0x73, 0xfd, 0x9c, 0xc1, 0xfd, 0x07, - 0xad, 0x81, 0xcb, 0xe3, 0xa2, 0xdf, 0x97, 0xc7, 0xc5, 0x6e, 0x57, 0x9e, 0xc4, 0xfd, 0xbe, 0x3c, 0x89, 0x0d, 0xff, - 0xa0, 0x14, 0xdb, 0xc6, 0xdc, 0x20, 0xa1, 0xb9, 0x84, 0xa8, 0x45, 0x23, 0xf8, 0x43, 0xb3, 0x9c, 0x8b, 0x28, 0x3f, - 0x4e, 0xfa, 0xfd, 0xde, 0x72, 0x26, 0x06, 0xf9, 0x30, 0x89, 0xf2, 0x61, 0xe2, 0x39, 0x21, 0xbe, 0xf4, 0x9c, 0x10, - 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, 0xab, 0x5a, 0x12, - 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0xfd, 0xba, 0x04, 0x9e, 0x28, 0xe7, 0xd5, 0x16, 0x18, - 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x6d, 0x4d, 0x2f, 0xe8, 0x8a, 0x5e, 0x22, 0x3f, - 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, 0xc2, 0xf5, 0x2c, - 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x53, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x65, 0x10, 0xde, 0x2f, 0x9d, 0x85, - 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, 0x97, 0x74, 0x45, - 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, 0x55, 0xe1, 0x5d, - 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x69, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, 0x66, 0x64, 0x24, - 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, 0xdc, 0xfd, 0x92, - 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, 0x38, 0xb0, 0x07, - 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x23, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, 0xc4, 0x2b, 0x70, - 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, 0x2b, 0x95, 0x7e, - 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, 0x17, 0xa3, 0x0d, - 0x01, 0x0b, 0xaf, 0xf1, 0x74, 0x7d, 0xcc, 0xe2, 0xe9, 0x60, 0xb0, 0x46, 0xaa, 0xae, 0x72, 0xaf, 0xc9, 0x82, 0x5e, - 0xe0, 0x44, 0x10, 0x60, 0xe8, 0x33, 0xb1, 0x36, 0x34, 0xfc, 0x29, 0x83, 0x8f, 0x37, 0xec, 0x62, 0xb4, 0xa1, 0xb7, - 0xec, 0xe9, 0x6e, 0x3c, 0x05, 0x66, 0x6a, 0x35, 0x0b, 0x37, 0xc7, 0x97, 0xb3, 0x4b, 0xb6, 0x89, 0x36, 0x27, 0xd0, - 0xd0, 0x2b, 0xb6, 0x41, 0xc0, 0xa5, 0xf4, 0xe1, 0x72, 0xf0, 0x94, 0x1c, 0x0e, 0x06, 0x29, 0x89, 0xc2, 0xeb, 0xd0, - 0x6b, 0xe5, 0x53, 0xba, 0x21, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, 0x36, 0xf5, 0x75, 0xe8, - 0xed, 0xe6, 0x5c, 0x74, 0x82, 0x18, 0xa1, 0xaf, 0x81, 0xa3, 0x59, 0x2e, 0xcc, 0x04, 0x3c, 0x99, 0x8b, 0x8c, 0x16, - 0x85, 0x66, 0x20, 0xce, 0x4a, 0x40, 0x2c, 0x89, 0xba, 0xdf, 0x6c, 0x74, 0x06, 0xcb, 0xb9, 0xdf, 0xef, 0x55, 0x86, - 0x1e, 0x20, 0x72, 0x66, 0x27, 0x3d, 0xe8, 0xf9, 0xf4, 0x00, 0x3f, 0xd1, 0xab, 0x06, 0x71, 0x32, 0x7f, 0x59, 0x46, - 0x2f, 0x3d, 0xfa, 0xf0, 0x5b, 0x37, 0xe5, 0x91, 0xf9, 0x7f, 0x4e, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x79, 0x40, 0x6c, - 0xde, 0x9a, 0x54, 0x1a, 0x89, 0x6a, 0x74, 0xb6, 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xfd, 0x84, 0x16, 0x56, 0x10, - 0x21, 0xe7, 0xe8, 0x19, 0x18, 0xa4, 0x42, 0xa8, 0x1c, 0xb5, 0x28, 0xd1, 0x10, 0x24, 0x97, 0x25, 0x57, 0xe1, 0x73, - 0x08, 0x55, 0xa7, 0x8f, 0x33, 0x11, 0x36, 0xf4, 0x38, 0xf4, 0x01, 0xe0, 0xff, 0xda, 0x23, 0x17, 0x25, 0xbf, 0xc4, - 0xb3, 0xb9, 0x4d, 0x30, 0x0a, 0x96, 0x8b, 0x66, 0x68, 0x1b, 0xc4, 0x7e, 0x2c, 0x09, 0xd6, 0x23, 0x69, 0x3c, 0x2a, - 0xcd, 0x11, 0xe1, 0x47, 0xf1, 0x51, 0xf4, 0x34, 0x36, 0x24, 0x92, 0x23, 0x89, 0xe4, 0x03, 0x20, 0x9c, 0x04, 0xfd, - 0xc5, 0x5d, 0x93, 0x5d, 0x0b, 0xb5, 0xd7, 0xef, 0xc1, 0xbf, 0x96, 0x4c, 0xcb, 0xee, 0x55, 0x8f, 0x7d, 0x45, 0x90, - 0x07, 0x13, 0xe0, 0xf5, 0xe1, 0x5f, 0x4b, 0x9c, 0x41, 0xeb, 0xf9, 0xa2, 0x3a, 0x33, 0xf3, 0x06, 0x37, 0xf2, 0xba, - 0xac, 0x5d, 0x97, 0x2f, 0xf8, 0x01, 0xbf, 0xad, 0xb8, 0x48, 0xcb, 0x83, 0x9f, 0xab, 0x36, 0x9e, 0x53, 0xb9, 0x5e, - 0xb9, 0x38, 0x2b, 0xca, 0x38, 0xd5, 0x93, 0xba, 0x18, 0x6b, 0xd8, 0x86, 0xdf, 0x23, 0xea, 0x4a, 0x5a, 0x8e, 0x9e, - 0x52, 0xae, 0x9a, 0x29, 0x17, 0xeb, 0x3c, 0xff, 0x69, 0x2f, 0x15, 0xa7, 0xb8, 0x99, 0x82, 0x54, 0xa9, 0xe5, 0x02, - 0xaa, 0xe7, 0xa8, 0xe5, 0x6e, 0x69, 0x76, 0x80, 0x73, 0xdb, 0x54, 0x1f, 0x2b, 0xb3, 0x0b, 0x2f, 0xb9, 0x71, 0x7f, - 0x32, 0x65, 0x58, 0x30, 0x0a, 0x6d, 0x56, 0x5d, 0x69, 0xfb, 0x42, 0xeb, 0x34, 0x0c, 0x57, 0x7e, 0xbc, 0x80, 0x74, - 0x01, 0xe3, 0x78, 0x51, 0x32, 0x31, 0x6e, 0x8f, 0xde, 0x0a, 0xe2, 0x6b, 0xb6, 0x02, 0xe9, 0xf7, 0x7b, 0xc2, 0xdb, - 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, 0x72, 0x15, 0x8b, 0x1f, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, - 0x4c, 0xa7, 0x3f, 0x27, 0xa1, 0x5f, 0x08, 0x05, 0x9f, 0xf5, 0xd2, 0xca, 0x93, 0xdb, 0xc3, 0x32, 0xae, 0xd1, 0x2b, - 0x71, 0xa5, 0xfb, 0x66, 0xa4, 0x90, 0x7a, 0xe4, 0xab, 0xa6, 0x80, 0xde, 0x8c, 0x7d, 0x33, 0x15, 0xe6, 0xed, 0x8e, - 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, - 0xa7, 0x9d, 0xfb, 0x75, 0xde, 0xe1, 0xae, 0xa8, 0xdf, 0x02, 0x17, 0x9a, 0x15, 0x65, 0xd5, 0x96, 0x0d, 0xdb, 0xc6, - 0x1b, 0x59, 0x28, 0x36, 0xc0, 0xb2, 0xe7, 0xbe, 0x85, 0x07, 0x88, 0x9b, 0x70, 0xcf, 0x2e, 0x6a, 0xb8, 0x31, 0x7c, - 0x5d, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, - 0x85, 0x2f, 0x78, 0x19, 0xce, 0xf9, 0xc2, 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0xd3, 0x21, 0x53, 0xe8, 0x76, 0xa5, 0xb1, - 0x52, 0x22, 0x6e, 0xcd, 0x32, 0x81, 0xb2, 0x94, 0xb5, 0x12, 0xde, 0x14, 0x2d, 0x5b, 0x49, 0x23, 0xef, 0x99, 0x83, - 0xfb, 0xd8, 0x6f, 0x88, 0x89, 0x6c, 0x02, 0x93, 0xa2, 0xa1, 0x03, 0xda, 0x55, 0x17, 0xbe, 0x19, 0xf5, 0x60, 0x90, - 0x5b, 0x92, 0x88, 0x15, 0xa4, 0x58, 0xc1, 0xba, 0x66, 0xc5, 0x3c, 0x5f, 0xd0, 0x0b, 0x26, 0xe7, 0xe9, 0x82, 0xae, - 0x98, 0x9c, 0xaf, 0xf1, 0x26, 0x74, 0x01, 0x27, 0x24, 0xd9, 0xc6, 0x4a, 0x01, 0x7b, 0x81, 0x97, 0x37, 0x3c, 0x53, - 0x35, 0x2d, 0xbb, 0x54, 0x1c, 0x60, 0x7c, 0x5e, 0x86, 0x61, 0x39, 0xbc, 0x00, 0x6b, 0x89, 0xc3, 0x70, 0x35, 0xe7, - 0x0b, 0xf5, 0x1b, 0xa2, 0xce, 0x27, 0xa1, 0x62, 0x17, 0xec, 0x5e, 0x20, 0xd3, 0xab, 0x39, 0x5f, 0xa8, 0x91, 0xd0, - 0x05, 0x5f, 0x59, 0x63, 0x93, 0xd8, 0x13, 0xb4, 0xcc, 0xe2, 0xf9, 0x78, 0x11, 0xc5, 0x35, 0x2c, 0xc3, 0x0f, 0x6a, - 0x66, 0x5a, 0xf2, 0x9f, 0x5c, 0x6d, 0x68, 0xa2, 0x6f, 0xb0, 0x8a, 0xfc, 0xe1, 0xf1, 0xd1, 0x25, 0x90, 0xb1, 0xb3, - 0x2b, 0x99, 0xf9, 0xd0, 0xf7, 0x91, 0xc1, 0x3d, 0x37, 0xe5, 0x8c, 0xab, 0x20, 0x51, 0x06, 0xee, 0x5e, 0xcd, 0x92, - 0xb1, 0x16, 0xe1, 0xfb, 0x47, 0x45, 0xd1, 0x67, 0xd2, 0x34, 0xa0, 0xfb, 0x48, 0x30, 0x07, 0x7a, 0xaf, 0xd0, 0xe1, - 0xb2, 0xda, 0x66, 0x02, 0xfe, 0x22, 0x41, 0x7e, 0x2b, 0xf4, 0xaa, 0xc6, 0xa0, 0x8a, 0x76, 0x11, 0x4b, 0xff, 0x3e, - 0xe2, 0x47, 0xd9, 0xfc, 0xa7, 0xb9, 0xc7, 0x2b, 0x09, 0x83, 0x1f, 0x52, 0xb3, 0x49, 0xe6, 0xed, 0x15, 0xfb, 0x0e, - 0x3a, 0xea, 0x51, 0x6b, 0xbc, 0xaf, 0x5e, 0x70, 0x0a, 0x31, 0x4a, 0x28, 0x3a, 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, - 0x77, 0x83, 0xdd, 0x36, 0xaf, 0x79, 0x51, 0x70, 0xbe, 0xae, 0xaa, 0xc0, 0x0f, 0x68, 0x38, 0x5f, 0xec, 0x87, 0x30, - 0x1c, 0xd3, 0xd6, 0x35, 0x0c, 0xc2, 0x8c, 0x61, 0x24, 0x04, 0xaf, 0x7f, 0xd1, 0x23, 0x9a, 0xc4, 0xab, 0x1f, 0xf8, - 0xe7, 0x8c, 0x17, 0x8a, 0x48, 0x83, 0x08, 0xa9, 0x9b, 0xf8, 0x46, 0xa6, 0x49, 0x01, 0x85, 0x00, 0xa3, 0x80, 0x4a, - 0x6c, 0x68, 0x2a, 0xfe, 0x56, 0x8b, 0x0f, 0x7e, 0x6a, 0x3a, 0x1e, 0x8d, 0xeb, 0x56, 0x67, 0x54, 0xd0, 0x19, 0xe8, - 0x51, 0x2b, 0xea, 0x69, 0xd0, 0x4a, 0x30, 0x8d, 0x34, 0x6f, 0xdd, 0x43, 0xe0, 0x95, 0x69, 0xf1, 0xce, 0x03, 0xba, - 0x3d, 0xf3, 0xc1, 0x93, 0xc7, 0xf4, 0xcc, 0xa1, 0x27, 0x57, 0xec, 0xa4, 0xea, 0xa1, 0xf6, 0xde, 0x8c, 0x50, 0xd0, - 0xef, 0x63, 0x0a, 0x74, 0x23, 0xa8, 0xbd, 0xab, 0x7b, 0x25, 0xf7, 0x39, 0x7c, 0xc7, 0x59, 0x6e, 0x01, 0x4b, 0x45, - 0xd6, 0x0a, 0x3c, 0x0a, 0x50, 0x97, 0xca, 0x10, 0xb6, 0x98, 0xc3, 0xa1, 0xb2, 0x5b, 0xb5, 0x1a, 0x4a, 0x72, 0x5c, - 0x8e, 0xc0, 0x21, 0x74, 0x5d, 0x0e, 0xca, 0xd1, 0x32, 0xab, 0xde, 0xe3, 0x6f, 0xcd, 0x3a, 0x24, 0xd9, 0x5d, 0xac, - 0x03, 0xb7, 0xac, 0xc3, 0xf4, 0x93, 0x41, 0x0a, 0x40, 0x93, 0x8d, 0xc0, 0x25, 0x00, 0xef, 0xed, 0x3f, 0x22, 0xd4, - 0xca, 0xf4, 0x4e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, 0x91, 0xce, - 0x49, 0x9d, 0x89, 0xf7, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x1b, 0xbc, 0xcd, 0x6a, 0xa9, - 0x8d, 0x1e, 0x28, 0x80, 0xdf, 0x0d, 0x36, 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x47, - 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x47, 0xe4, 0xd8, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x41, - 0x83, 0xfe, 0x65, 0x5b, 0xe4, 0x0e, 0x40, 0x69, 0x14, 0x31, 0x50, 0x25, 0x88, 0xa8, 0xc5, 0xbf, 0xef, 0xcd, 0xb5, - 0xc1, 0x5c, 0x20, 0xcc, 0xc1, 0x80, 0x83, 0xb8, 0x0d, 0x42, 0x73, 0xc0, 0x6c, 0x6f, 0x23, 0x41, 0x37, 0xd6, 0x30, - 0xb3, 0xa3, 0x3f, 0xdc, 0x4a, 0xf0, 0x4d, 0xd6, 0x1a, 0x75, 0x5e, 0x1c, 0x02, 0x41, 0xf0, 0xa6, 0x50, 0xd5, 0x5e, - 0xf5, 0xc0, 0xc6, 0x5b, 0xf5, 0x63, 0xb7, 0x1b, 0x4f, 0x85, 0xbb, 0xf6, 0x0b, 0x0a, 0x27, 0x9f, 0x92, 0x7f, 0xbd, - 0x37, 0x19, 0x1c, 0x18, 0x19, 0xbe, 0xf4, 0xf6, 0x2f, 0x7c, 0xad, 0xa5, 0x7b, 0x62, 0x50, 0x92, 0x87, 0x47, 0x8a, - 0xfe, 0xdd, 0x29, 0x2b, 0x9f, 0xda, 0xe9, 0xdf, 0xed, 0xcc, 0xfa, 0x3c, 0x1e, 0x4d, 0x76, 0xbb, 0x5e, 0x5c, 0x69, - 0x8f, 0x35, 0xbd, 0x20, 0xd0, 0xb9, 0x9e, 0x1c, 0x1e, 0x41, 0x54, 0x84, 0x66, 0xdc, 0xcd, 0xb2, 0x21, 0x91, 0xf1, - 0xe3, 0x74, 0x96, 0x0d, 0xc1, 0x0e, 0xf7, 0xa2, 0x12, 0x97, 0xa3, 0xd6, 0x06, 0xa7, 0xb7, 0x49, 0x08, 0xa1, 0x1c, - 0xb0, 0xb2, 0x5b, 0xf5, 0x67, 0xa3, 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x07, 0x66, 0x04, - 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xa7, 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0xf6, 0xe8, 0xa9, - 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, 0xdf, 0x30, 0xee, 0x3f, 0x34, 0x5f, 0xbb, 0xa9, 0x88, 0x1e, 0x53, 0x2c, 0x53, - 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x72, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, - 0x9f, 0x21, 0x7c, 0x46, 0xb2, 0x0b, 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xe4, 0x31, 0x3d, 0x98, 0x7c, 0x77, 0x44, - 0x0f, 0x8e, 0x1e, 0x3d, 0x21, 0x00, 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3d, 0x79, 0x42, 0x0f, 0xbe, 0xff, 0x9e, 0x1e, - 0x4c, 0x1e, 0x1d, 0x35, 0xd2, 0x26, 0x4f, 0xbe, 0xa7, 0x07, 0xdf, 0x3d, 0x6e, 0xa4, 0x1d, 0x8d, 0x9f, 0xd0, 0x83, - 0xbf, 0x7f, 0x67, 0xd2, 0xfe, 0x06, 0xd9, 0xbe, 0x3f, 0xc2, 0xff, 0x4c, 0xda, 0xe4, 0xc9, 0x23, 0x7a, 0x30, 0x19, - 0x43, 0x25, 0x4f, 0x5c, 0x25, 0xe3, 0x09, 0x7c, 0xfc, 0x08, 0xfe, 0xfb, 0x1b, 0x81, 0x4d, 0x20, 0xd9, 0x52, 0xa0, - 0xfe, 0x0c, 0x45, 0x9c, 0xa8, 0x9a, 0x48, 0x78, 0x88, 0x99, 0xd5, 0x37, 0x71, 0x18, 0x10, 0x97, 0x0e, 0x05, 0xd1, - 0x83, 0xf1, 0xe8, 0x09, 0x09, 0x7c, 0x78, 0xba, 0x4f, 0x3e, 0xc8, 0xd8, 0x52, 0xcc, 0xb3, 0x6f, 0x96, 0x26, 0xb6, - 0x82, 0x07, 0x60, 0xf5, 0xc1, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x86, 0xcb, 0xfd, 0x5c, 0x3f, 0xb6, 0x00, 0xe5, 0xfd, - 0x55, 0xcb, 0x3e, 0x15, 0x2a, 0x74, 0x5a, 0x6b, 0xf4, 0xd9, 0x07, 0x4c, 0x1f, 0x0c, 0xbc, 0x1b, 0xf6, 0xcf, 0x7b, - 0xe5, 0xb4, 0xbe, 0xd1, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x65, 0xfc, - 0xfe, 0x1f, 0x96, 0xf1, 0xa1, 0xa3, 0x8c, 0x7f, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, - 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x07, 0x46, 0x14, 0x2d, 0x2f, 0x0e, 0x52, 0x3e, - 0xab, 0xd8, 0xcf, 0x4b, 0x54, 0x6f, 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x77, 0xf3, 0x06, 0xb8, 0x19, 0xf6, - 0xa3, 0x7a, 0xf2, 0x03, 0x67, 0x64, 0xd2, 0xb6, 0x47, 0x99, 0x18, 0x01, 0x56, 0x40, 0x06, 0x0e, 0x3c, 0x00, 0x3a, - 0xe8, 0x8f, 0xf6, 0x6e, 0xa7, 0x52, 0x9a, 0x7d, 0xb6, 0x30, 0x80, 0x86, 0x79, 0x9b, 0xb8, 0xb2, 0xab, 0xd4, 0x97, - 0x97, 0xa0, 0x70, 0xab, 0x59, 0xde, 0x5e, 0x61, 0x2a, 0x6e, 0x4f, 0xca, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, - 0x40, 0xcd, 0x96, 0x8f, 0xb6, 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0xdf, 0x6a, 0xb1, 0x3f, 0x5a, - 0x3f, 0xfa, 0xbe, 0x3d, 0x1e, 0xac, 0x7d, 0x8f, 0x8f, 0xf4, 0x67, 0x8d, 0xeb, 0xc0, 0xb6, 0xe5, 0x1b, 0x2f, 0x6a, - 0x2b, 0xf1, 0x28, 0x81, 0x37, 0x30, 0x11, 0x29, 0x0c, 0x52, 0x2d, 0x70, 0x0c, 0xca, 0x1b, 0x0b, 0xb1, 0x54, 0x5d, - 0xdd, 0xd0, 0x2d, 0x19, 0x82, 0x87, 0x5b, 0x95, 0xaa, 0xc0, 0x51, 0xfd, 0x7e, 0x26, 0x7d, 0xb7, 0x27, 0x63, 0x47, - 0x8e, 0x53, 0x3f, 0x15, 0x0e, 0xfe, 0x9b, 0xd4, 0xb5, 0x7e, 0x99, 0xa5, 0xcc, 0xb2, 0x2c, 0xec, 0x24, 0xd4, 0x72, - 0x8f, 0xca, 0x83, 0xe4, 0x0b, 0x39, 0x44, 0xb2, 0xc0, 0x28, 0x14, 0x64, 0x38, 0xa1, 0x62, 0xb4, 0x16, 0xe5, 0x32, - 0xbb, 0xa8, 0xc2, 0xad, 0x52, 0x28, 0x73, 0x8a, 0xbe, 0xdd, 0xe0, 0x40, 0x42, 0xa2, 0xac, 0x7c, 0x13, 0xbf, 0x09, - 0x11, 0xac, 0x8e, 0x6b, 0x5b, 0x28, 0xee, 0xed, 0x4f, 0x91, 0x76, 0xf1, 0x47, 0xc6, 0x05, 0xd4, 0xc5, 0x62, 0x1a, - 0x4e, 0x6c, 0xec, 0x03, 0xf7, 0x85, 0xd5, 0xf4, 0x00, 0xd4, 0x77, 0xa9, 0xc4, 0x08, 0xea, 0x2b, 0x63, 0x1f, 0xdb, - 0x63, 0x4c, 0xce, 0x20, 0xd6, 0xb0, 0x2e, 0x5b, 0xf5, 0x8d, 0xb0, 0x13, 0x00, 0x6e, 0x84, 0xd6, 0xe8, 0xc8, 0x24, - 0x55, 0x88, 0xe7, 0xa5, 0x0a, 0xdf, 0x9a, 0x11, 0x3a, 0x06, 0x6f, 0x2a, 0xd7, 0x48, 0xe9, 0x0b, 0x06, 0xcd, 0xb1, - 0xad, 0xa3, 0xb0, 0xda, 0xca, 0xb2, 0x13, 0x80, 0x1b, 0xc8, 0x8e, 0xcd, 0xc5, 0x73, 0x56, 0xcd, 0xb3, 0x45, 0x64, - 0x82, 0x02, 0xa6, 0xc2, 0x32, 0x68, 0x6f, 0xee, 0x90, 0xed, 0x38, 0x84, 0x6e, 0xb8, 0x8f, 0x60, 0x3c, 0xed, 0xa6, - 0x60, 0x05, 0xd1, 0x08, 0xf1, 0x30, 0x63, 0x16, 0xdf, 0x2b, 0x4d, 0x79, 0xaa, 0x5a, 0x02, 0x81, 0xa3, 0x10, 0xea, - 0x62, 0xdf, 0x28, 0xc1, 0x65, 0x6a, 0x04, 0x33, 0xd8, 0xb3, 0x23, 0xb5, 0x5d, 0x72, 0x4e, 0x87, 0x6a, 0x4a, 0x4b, - 0x3d, 0xa5, 0xda, 0xd7, 0x50, 0xcc, 0x4b, 0xf4, 0xd0, 0x03, 0xd7, 0x03, 0xed, 0x90, 0x57, 0xd2, 0x89, 0x89, 0xa0, - 0xd3, 0x6a, 0x13, 0x76, 0x6e, 0xa4, 0x5b, 0x56, 0x23, 0xef, 0x18, 0x9a, 0x1d, 0xf1, 0xca, 0x0f, 0xd4, 0x05, 0x10, - 0x21, 0x77, 0xb6, 0xc8, 0x10, 0x67, 0x96, 0x95, 0x2f, 0xa0, 0x2c, 0x8e, 0xd8, 0xba, 0x02, 0xae, 0xa5, 0x60, 0x72, - 0xc9, 0x23, 0x91, 0x22, 0x22, 0xe0, 0xa9, 0xd2, 0xae, 0xef, 0xb5, 0x84, 0xd0, 0x32, 0x05, 0xe2, 0xe6, 0xa2, 0x38, - 0xd7, 0x36, 0x90, 0x05, 0xd0, 0xb7, 0x9f, 0xb2, 0x2b, 0x2f, 0x1c, 0xec, 0xf6, 0x2a, 0x13, 0xcf, 0xf8, 0x45, 0x26, - 0x78, 0x8a, 0x60, 0x57, 0xb7, 0xe6, 0x81, 0x3b, 0xb6, 0x0d, 0x2c, 0xdf, 0x7e, 0x80, 0x05, 0x53, 0x86, 0x5a, 0x29, - 0x91, 0x89, 0x48, 0x40, 0x66, 0x9f, 0xb9, 0x7b, 0x9d, 0x89, 0xd7, 0xf1, 0x2d, 0x78, 0x53, 0x34, 0xf8, 0xe9, 0xd1, - 0x39, 0x7e, 0x89, 0x48, 0xa2, 0x10, 0xc3, 0x16, 0x23, 0x62, 0x21, 0x72, 0xec, 0x98, 0x50, 0xae, 0x04, 0xad, 0xad, - 0x21, 0xf0, 0xe2, 0x4f, 0xab, 0xee, 0x5d, 0x65, 0xc2, 0xd8, 0x67, 0x5c, 0xc5, 0xb7, 0xac, 0x54, 0x60, 0x16, 0x18, - 0xe7, 0xbe, 0x2d, 0x25, 0xb9, 0xca, 0x84, 0x11, 0x90, 0x5c, 0xc5, 0xb7, 0xb4, 0x29, 0xe3, 0xd0, 0x56, 0x74, 0x5e, - 0x9c, 0xdf, 0xfd, 0xe1, 0x97, 0x18, 0x6a, 0x65, 0xdc, 0xef, 0x83, 0xc4, 0x4c, 0xda, 0xa6, 0xcc, 0x64, 0x24, 0x35, - 0x5a, 0x48, 0x45, 0xf9, 0x60, 0x42, 0xf6, 0x57, 0xaa, 0x65, 0x44, 0xed, 0x57, 0xa1, 0x98, 0x8d, 0xa3, 0x09, 0xa1, - 0x93, 0x8e, 0xf5, 0x6e, 0x5a, 0x0b, 0x99, 0x46, 0x4f, 0x22, 0xcf, 0xa7, 0xb3, 0x60, 0xd5, 0xb4, 0x38, 0x66, 0x7c, - 0x5a, 0x0c, 0x06, 0x44, 0xbb, 0x14, 0x6e, 0xb1, 0x1e, 0x30, 0xa5, 0x71, 0xf1, 0xd6, 0x4c, 0xab, 0x5f, 0x48, 0x15, - 0x92, 0xde, 0x33, 0x20, 0x11, 0xd2, 0x05, 0xbb, 0x05, 0x89, 0xa2, 0xe7, 0x7f, 0xa7, 0xb6, 0xe0, 0xbe, 0x07, 0x63, - 0x33, 0xba, 0xaf, 0x67, 0xfc, 0x87, 0xda, 0x16, 0x44, 0x7d, 0x2a, 0x59, 0xaf, 0x23, 0x51, 0x85, 0x5c, 0x84, 0x9f, - 0x1d, 0x0d, 0x31, 0x44, 0xb5, 0xc7, 0x02, 0xb1, 0xbe, 0x3a, 0xe7, 0x05, 0x4e, 0x3f, 0x73, 0x97, 0x2b, 0xd8, 0x16, - 0xb4, 0x32, 0x34, 0xea, 0x4d, 0xfc, 0x26, 0xb2, 0x97, 0x05, 0x5d, 0xe4, 0x33, 0x14, 0xb2, 0xe6, 0x61, 0x58, 0x0d, - 0xdb, 0x83, 0x48, 0x0e, 0xdb, 0x93, 0xd0, 0x68, 0x0c, 0x2c, 0x90, 0x3d, 0x1a, 0x81, 0x8b, 0xd0, 0xca, 0xdf, 0x8e, - 0xc1, 0x85, 0xcb, 0x22, 0xb2, 0x0c, 0x75, 0xfc, 0xa6, 0x76, 0x13, 0x54, 0xaf, 0xd0, 0x69, 0x0a, 0xab, 0x52, 0x26, - 0xf9, 0xf0, 0xeb, 0x85, 0x2c, 0x30, 0x93, 0xd7, 0x65, 0x8f, 0xbe, 0xb6, 0xdb, 0x3b, 0x30, 0x05, 0xeb, 0x3e, 0x79, - 0x5f, 0x3f, 0xec, 0xec, 0x09, 0x18, 0xc5, 0xaa, 0x1c, 0x4d, 0x21, 0xa5, 0xf6, 0x41, 0xa9, 0x3f, 0x85, 0xa9, 0xd0, - 0x1c, 0xbb, 0x05, 0x4c, 0x02, 0xf6, 0x19, 0x52, 0x3d, 0xa6, 0x1d, 0xfb, 0x1c, 0x6d, 0x61, 0x49, 0xc0, 0xe1, 0x1f, - 0x09, 0x59, 0xfb, 0x57, 0x77, 0x99, 0x36, 0x43, 0xb6, 0xcc, 0x17, 0xc0, 0xe7, 0xc3, 0xae, 0x8d, 0x4a, 0x94, 0x4d, - 0x44, 0x92, 0xc2, 0x96, 0xc7, 0x20, 0xed, 0x51, 0x4c, 0x57, 0x05, 0x4f, 0x32, 0x94, 0x52, 0x24, 0xda, 0x27, 0x38, - 0x87, 0x37, 0xb8, 0x1f, 0x55, 0x40, 0x78, 0x15, 0x72, 0x3a, 0x4a, 0xa9, 0xb6, 0x80, 0x51, 0xd4, 0x03, 0x44, 0x79, - 0x19, 0xc8, 0xf1, 0x76, 0xbb, 0x09, 0x5d, 0xb1, 0xe5, 0x70, 0x42, 0x91, 0x94, 0x5c, 0x62, 0xb9, 0x57, 0xa0, 0xf3, - 0x38, 0x67, 0xbd, 0x57, 0x80, 0x45, 0x70, 0x06, 0x7f, 0x63, 0x42, 0xaf, 0xe1, 0x6f, 0x4e, 0xe8, 0x53, 0x16, 0x5e, - 0x0d, 0x2f, 0xc9, 0x61, 0x98, 0x0e, 0x26, 0x4a, 0x30, 0xb6, 0x61, 0x69, 0x19, 0xaa, 0xc4, 0xd5, 0xe1, 0x05, 0x79, - 0x78, 0x41, 0x6f, 0xe9, 0x0d, 0x7d, 0x4d, 0x1f, 0x00, 0xe1, 0xdf, 0x1c, 0x4f, 0xf8, 0x70, 0xf2, 0xb8, 0xdf, 0xef, - 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, 0x7a, 0x31, 0x7d, 0xa0, - 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xdc, 0x90, 0x21, 0x3e, 0x5e, 0xe4, 0x52, 0x16, 0xe1, 0xe5, 0xe1, 0x86, - 0xd0, 0x07, 0x27, 0xa0, 0x37, 0xc5, 0xfa, 0x1e, 0x3c, 0xdc, 0xe8, 0xda, 0x08, 0x7d, 0x15, 0x26, 0xb0, 0x4d, 0x6e, - 0x99, 0xbd, 0x6b, 0x4f, 0xc6, 0x10, 0xcb, 0x64, 0xe3, 0x95, 0xb7, 0x79, 0x78, 0x4b, 0x0e, 0x6f, 0xc1, 0x53, 0xd4, - 0x92, 0xbf, 0x59, 0x78, 0xc3, 0x5a, 0x35, 0x3c, 0xdc, 0xd0, 0xd7, 0xad, 0x46, 0x3c, 0xdc, 0x90, 0x28, 0xbc, 0x61, - 0x97, 0xf4, 0x35, 0xbb, 0x22, 0xf4, 0xbc, 0xdf, 0x3f, 0xeb, 0xf7, 0x65, 0xbf, 0xff, 0x73, 0x1c, 0x86, 0xf1, 0xb0, - 0x20, 0x87, 0x92, 0x6e, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, 0x59, 0x95, 0xb7, 0xca, 0xb5, - 0xa1, 0x60, 0xad, 0xb0, 0x61, 0xea, 0xe9, 0x01, 0xbd, 0x61, 0x05, 0x7d, 0xcd, 0x62, 0x12, 0x5d, 0x43, 0x2b, 0xce, - 0x67, 0x45, 0x74, 0x43, 0x5f, 0xb3, 0xb3, 0x59, 0x1c, 0xbd, 0xa6, 0x0f, 0x58, 0x3e, 0x9c, 0x40, 0xde, 0xd7, 0xc3, - 0x1b, 0x72, 0xf8, 0x80, 0x44, 0xe1, 0x03, 0xfd, 0x7b, 0x43, 0x2f, 0x79, 0xf8, 0x80, 0x7a, 0xd5, 0x3c, 0x20, 0xa6, - 0xfa, 0x46, 0xed, 0x0f, 0x48, 0xe4, 0x0f, 0xe6, 0x03, 0x6b, 0x4f, 0xf3, 0xce, 0xd1, 0xc6, 0x75, 0x19, 0x6e, 0x08, - 0x5d, 0x97, 0xe1, 0x0d, 0x21, 0xd3, 0xe6, 0xd8, 0xc1, 0x80, 0xce, 0xde, 0x45, 0x09, 0xa1, 0x37, 0x7e, 0xa9, 0x37, - 0x38, 0x86, 0x66, 0x84, 0x74, 0x3f, 0x31, 0x0d, 0xd7, 0xc1, 0x47, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, - 0x1f, 0x22, 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0x8f, 0x83, 0x01, 0x74, 0xc6, - 0x2b, 0x29, 0xbc, 0x19, 0x7c, 0x7c, 0xb8, 0x21, 0xaa, 0x8e, 0x82, 0x96, 0x32, 0x2c, 0xe8, 0x53, 0x9a, 0x01, 0xe0, - 0xd7, 0xc7, 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0xfd, 0x78, 0xfc, 0x60, 0x3a, 0x18, 0x7c, 0x34, 0xdb, 0xe4, 0x33, - 0xbb, 0xa3, 0x14, 0x58, 0x7f, 0x67, 0xfd, 0xfe, 0xe7, 0x93, 0x98, 0x9c, 0x17, 0x3c, 0xfe, 0x34, 0x6d, 0xb6, 0xe5, - 0xb3, 0x8b, 0xaa, 0x76, 0xd6, 0xef, 0xaf, 0xfb, 0xfd, 0xd7, 0x80, 0x5d, 0x34, 0x73, 0xbe, 0x9e, 0x20, 0x6d, 0x99, - 0x3b, 0x8a, 0xa4, 0x49, 0x0e, 0x8d, 0xa1, 0x6d, 0xb1, 0x6a, 0xdb, 0xac, 0x23, 0x03, 0x8b, 0xa3, 0x66, 0x45, 0x71, - 0x4d, 0xa2, 0xb0, 0x77, 0xb6, 0xdb, 0xbd, 0x66, 0x8c, 0xc5, 0x04, 0xa4, 0x1f, 0xfe, 0xeb, 0xd7, 0x75, 0x23, 0x86, - 0x58, 0xa9, 0xc4, 0x77, 0xdb, 0xa5, 0x3d, 0x04, 0x22, 0x0e, 0x9b, 0xfe, 0xbd, 0xb9, 0x97, 0x8b, 0xda, 0xf1, 0xad, - 0xbf, 0x03, 0x08, 0x91, 0x64, 0x21, 0x9f, 0xe1, 0x18, 0x94, 0x19, 0x00, 0x99, 0x47, 0x6a, 0xe6, 0x25, 0x80, 0x00, - 0x93, 0xdd, 0x6e, 0x34, 0x1e, 0x4f, 0x68, 0xc1, 0x46, 0x7f, 0x7b, 0xf2, 0xb0, 0x7a, 0x18, 0x06, 0xc1, 0x20, 0x23, - 0x2d, 0x3d, 0x85, 0x5d, 0xac, 0xd5, 0x21, 0x18, 0xc1, 0x6b, 0xf6, 0xf1, 0x3a, 0xfb, 0x6a, 0xf6, 0x11, 0x09, 0x6b, - 0x83, 0x71, 0xe4, 0x22, 0x6d, 0xe9, 0xed, 0xee, 0x60, 0x30, 0xb9, 0x48, 0xbf, 0xc0, 0x76, 0xfa, 0xfc, 0x9b, 0x07, - 0xe3, 0x09, 0x07, 0xa3, 0xbb, 0x28, 0xe8, 0x33, 0x6d, 0xb7, 0xab, 0xfc, 0x4b, 0xe0, 0x1b, 0x4c, 0x05, 0x1d, 0x9b, - 0x65, 0xe1, 0x06, 0x15, 0x51, 0x47, 0xcb, 0xa0, 0xaa, 0x95, 0xed, 0x1c, 0x50, 0x4b, 0xac, 0xca, 0xc4, 0x2d, 0x30, - 0x0c, 0x19, 0xea, 0x72, 0x4f, 0xab, 0xdf, 0x79, 0x21, 0x0d, 0x7c, 0x86, 0x13, 0x11, 0x7a, 0xdc, 0x1a, 0xf7, 0xb9, - 0x35, 0xf1, 0x05, 0x6e, 0xad, 0x44, 0x12, 0x6b, 0x60, 0x49, 0xcd, 0xe5, 0x28, 0x61, 0x27, 0x25, 0xe3, 0xb3, 0x32, - 0x4a, 0x68, 0x0c, 0x0f, 0x92, 0x89, 0x99, 0x8c, 0x12, 0xb4, 0x4f, 0x74, 0x11, 0x06, 0xff, 0x02, 0xcc, 0x7e, 0x9a, - 0xc3, 0x5f, 0x49, 0xa6, 0xc9, 0x31, 0x04, 0x84, 0x38, 0x1e, 0xcf, 0xe2, 0x70, 0x4c, 0xa2, 0xe4, 0x04, 0x9e, 0xe0, - 0xbf, 0x22, 0x1c, 0x93, 0x5a, 0xdf, 0x61, 0xa4, 0xba, 0xdc, 0x26, 0x0c, 0xe0, 0xca, 0xc6, 0xb3, 0x49, 0x64, 0xa5, - 0xbb, 0xf2, 0xe1, 0x68, 0xfc, 0x84, 0x4c, 0xe3, 0x50, 0x0e, 0x12, 0x42, 0xc1, 0xbb, 0x37, 0x2c, 0x87, 0x89, 0x86, - 0x67, 0x03, 0x36, 0xaf, 0x74, 0x6c, 0x9e, 0x84, 0x13, 0x10, 0x86, 0x09, 0x39, 0xd6, 0x3b, 0x90, 0x52, 0xf4, 0x79, - 0x8e, 0xfd, 0xd4, 0x47, 0x10, 0x66, 0x47, 0x2d, 0x15, 0x5f, 0x01, 0xd0, 0x25, 0x0e, 0x0e, 0xb5, 0x67, 0xbe, 0x98, - 0x85, 0xa5, 0x47, 0xa5, 0x4c, 0x75, 0x87, 0xa2, 0x41, 0xf9, 0x4d, 0x83, 0x0e, 0x05, 0x19, 0x4c, 0x68, 0x79, 0x32, - 0xe1, 0x8f, 0x20, 0x80, 0x47, 0x23, 0xe2, 0x97, 0xc2, 0x89, 0x81, 0xf0, 0x2a, 0xc8, 0x40, 0xa5, 0xb5, 0x6a, 0xcc, - 0xc8, 0x56, 0x7c, 0x00, 0x61, 0x52, 0x0e, 0x6e, 0xe4, 0x3a, 0x4f, 0x21, 0x2a, 0xd8, 0x3a, 0xaf, 0x0e, 0x2e, 0xc1, - 0x92, 0x3d, 0xae, 0x20, 0x4e, 0xd8, 0x7a, 0x05, 0xd8, 0xb9, 0x0f, 0xb6, 0x65, 0x7d, 0xa0, 0xbe, 0x3b, 0xc0, 0x96, - 0xc3, 0xab, 0x4a, 0x1e, 0x4c, 0xc6, 0xe3, 0xf1, 0xe8, 0x0f, 0x38, 0x3a, 0x80, 0xd0, 0x92, 0xc8, 0xf0, 0xc9, 0x00, - 0x8d, 0xbb, 0xae, 0xb8, 0x37, 0x2e, 0x14, 0x65, 0xa5, 0x93, 0x09, 0x01, 0xf1, 0xb3, 0xe9, 0x1b, 0xec, 0x2b, 0xae, - 0xe3, 0x9f, 0xec, 0x7f, 0x62, 0x56, 0xb4, 0x5a, 0xa9, 0xa3, 0x77, 0x6f, 0x3f, 0xbc, 0xfa, 0xf8, 0xea, 0xd7, 0xe7, - 0x67, 0xaf, 0xde, 0xbc, 0x78, 0xf5, 0xe6, 0xd5, 0xc7, 0x7f, 0xdf, 0xc3, 0x60, 0xfb, 0xb6, 0x22, 0x76, 0xec, 0xbd, - 0x7b, 0x8c, 0x57, 0x8b, 0x2f, 0x9c, 0x3d, 0x72, 0xb7, 0x58, 0x80, 0x4d, 0x30, 0xdc, 0x82, 0xa0, 0x9a, 0xd1, 0xa8, - 0xf4, 0x3d, 0x01, 0x19, 0x8d, 0x0a, 0xd9, 0x78, 0x58, 0xb1, 0x15, 0x72, 0xf1, 0x8e, 0xe1, 0xe0, 0x23, 0xfb, 0x5b, - 0x71, 0x26, 0xdc, 0x8e, 0xb6, 0x66, 0x45, 0xc0, 0xe7, 0x6b, 0x2d, 0x2a, 0x8f, 0x0b, 0x51, 0x7b, 0xdb, 0x3e, 0x87, - 0x84, 0x7a, 0x44, 0xae, 0x83, 0xf7, 0x6d, 0x90, 0x3d, 0x3e, 0xf2, 0x9e, 0x94, 0x67, 0xa8, 0xcf, 0xd1, 0xf0, 0x51, - 0xe3, 0x19, 0x9d, 0x98, 0x6b, 0xa3, 0x43, 0x3d, 0x2b, 0x60, 0x7f, 0x2b, 0x31, 0x36, 0x98, 0x43, 0xa7, 0x88, 0xf5, - 0xe1, 0x74, 0xbf, 0xfb, 0x37, 0xa3, 0x9f, 0xe1, 0xf8, 0x51, 0xaa, 0x09, 0xa4, 0x45, 0x81, 0xd2, 0x95, 0x21, 0xb7, - 0x3d, 0x0b, 0x0b, 0xf3, 0x33, 0x6c, 0x10, 0x40, 0x7b, 0xd9, 0xb1, 0x24, 0xd0, 0x2c, 0x5e, 0xeb, 0xfa, 0xe7, 0xe5, - 0xcb, 0x44, 0x3b, 0x5f, 0x7c, 0x0b, 0x21, 0x86, 0xfd, 0x2b, 0x42, 0x63, 0xc2, 0xdd, 0x24, 0xbb, 0x4b, 0x8b, 0xb9, - 0x57, 0x5d, 0xc5, 0x78, 0xdc, 0xdd, 0x71, 0xa5, 0x68, 0xde, 0xba, 0xc0, 0x1e, 0xa8, 0x79, 0x1d, 0x2f, 0x59, 0x08, - 0xd8, 0x8c, 0x87, 0x76, 0x91, 0x38, 0xbf, 0x77, 0x3a, 0x21, 0x87, 0x47, 0x53, 0x3e, 0x64, 0x25, 0x15, 0x03, 0x56, - 0xd6, 0x7b, 0xd4, 0x9c, 0xb7, 0x09, 0xb9, 0xd8, 0xa7, 0xe1, 0x62, 0xc8, 0xef, 0xbb, 0x24, 0x7d, 0xe4, 0x0d, 0x87, - 0x6a, 0xdb, 0x5c, 0x0c, 0x69, 0xca, 0xe9, 0x3e, 0x95, 0x01, 0x21, 0xd2, 0x55, 0x5c, 0x91, 0x5a, 0x1f, 0x55, 0x6b, - 0x27, 0xe9, 0xb8, 0xce, 0xb6, 0x5f, 0xb8, 0x64, 0xab, 0xdb, 0xb5, 0x7f, 0xad, 0x6e, 0x5f, 0x98, 0x81, 0xfc, 0xfd, - 0x89, 0xa8, 0x26, 0x06, 0xa2, 0x0b, 0xa8, 0xe0, 0x9f, 0xe0, 0xe5, 0xc9, 0x23, 0xad, 0x00, 0xbd, 0xeb, 0xec, 0xe8, - 0xda, 0xe3, 0x8d, 0x59, 0x6c, 0x2d, 0x71, 0xce, 0x2a, 0xdf, 0x59, 0x5e, 0x95, 0xad, 0xd0, 0x75, 0x04, 0xfb, 0x3d, - 0xec, 0xe8, 0xbb, 0xb7, 0x0d, 0x80, 0x28, 0x85, 0x95, 0x3b, 0xfb, 0x85, 0x77, 0xf6, 0x0b, 0x7b, 0xf6, 0xdb, 0x4d, - 0xa0, 0x7c, 0x58, 0xa1, 0x65, 0x2f, 0xa4, 0xa8, 0x4c, 0x93, 0xc7, 0x4d, 0x5d, 0x16, 0xd2, 0x62, 0x7e, 0x68, 0x69, - 0xd7, 0xe3, 0x31, 0x95, 0xa8, 0x1e, 0x79, 0x89, 0xad, 0x3a, 0x2c, 0xc9, 0xfd, 0xf7, 0xcc, 0xff, 0xd9, 0x1b, 0xe4, - 0x5d, 0x77, 0xbb, 0xff, 0x9b, 0x0b, 0x1d, 0xdc, 0xd6, 0xd6, 0xc2, 0x53, 0x57, 0xc7, 0x05, 0xde, 0xd5, 0xd6, 0xf7, - 0xdf, 0xd5, 0xde, 0x66, 0x7a, 0xd9, 0x55, 0x80, 0x1a, 0x24, 0xd6, 0x57, 0xbc, 0xc8, 0x92, 0xda, 0x2a, 0x34, 0x1e, - 0x70, 0x08, 0xed, 0xe1, 0x1d, 0x5c, 0x20, 0x87, 0x25, 0x84, 0x7e, 0xaa, 0x8c, 0x00, 0xd0, 0x67, 0xb1, 0x1f, 0xf0, - 0x30, 0x23, 0x03, 0x5f, 0xe2, 0x27, 0xa5, 0x2f, 0x2e, 0x3e, 0xdc, 0xcb, 0x4c, 0xd0, 0xab, 0xc4, 0x66, 0x2f, 0x64, - 0x3b, 0xe6, 0x87, 0xff, 0x05, 0x46, 0x83, 0xf0, 0xda, 0x92, 0x1d, 0x8a, 0x8e, 0x59, 0xae, 0xe0, 0xa8, 0x2d, 0xbd, - 0x32, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x01, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, - 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0xf7, 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0x45, - 0xfe, 0x85, 0xfa, 0x1a, 0x5b, 0x92, 0x6c, 0x2b, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, - 0x2d, 0xa1, 0x0d, 0x95, 0x41, 0x4f, 0x2e, 0x52, 0xe5, 0x23, 0x5b, 0x30, 0x79, 0x3c, 0x9e, 0xf9, 0x3d, 0x77, 0x0c, - 0x0e, 0x21, 0xd1, 0xc4, 0x1a, 0xbf, 0xf8, 0x59, 0x30, 0x8e, 0x43, 0x79, 0x22, 0x1b, 0xdf, 0x95, 0x24, 0x1a, 0x1b, - 0x53, 0x65, 0x7d, 0x95, 0xa8, 0x86, 0x09, 0x79, 0x58, 0x90, 0xc3, 0x82, 0x2e, 0xfd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, - 0x70, 0x32, 0x26, 0x0f, 0xe3, 0x87, 0x13, 0x03, 0x37, 0xec, 0xe7, 0xc8, 0x87, 0x4b, 0x72, 0xd8, 0xac, 0x12, 0x4c, - 0x51, 0x4d, 0xcf, 0xfc, 0x4a, 0x92, 0xc1, 0x72, 0x90, 0x3e, 0x6c, 0xe5, 0xc5, 0x5a, 0xf5, 0x78, 0xaf, 0x8f, 0xf9, - 0x94, 0x88, 0xc6, 0x8d, 0x61, 0x4d, 0xaf, 0xe2, 0x3f, 0x65, 0x11, 0x49, 0x09, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, - 0xb2, 0x24, 0x16, 0x69, 0x94, 0xd6, 0x84, 0xa6, 0x27, 0x6c, 0x32, 0x9e, 0xa5, 0x2c, 0x3d, 0x9e, 0x3c, 0x99, 0x4d, - 0x9e, 0x44, 0x47, 0xe3, 0x28, 0x1d, 0x0c, 0x20, 0xf9, 0x68, 0x0c, 0x2e, 0x76, 0xf0, 0x9b, 0x1d, 0xc1, 0xd0, 0x9d, - 0x20, 0x4b, 0x58, 0x40, 0xd3, 0xbe, 0xae, 0x49, 0x7a, 0x38, 0x2f, 0x54, 0x4f, 0xe2, 0x5b, 0xba, 0xf6, 0x1c, 0x5c, - 0xfc, 0x16, 0x5e, 0xb8, 0x16, 0x5e, 0xec, 0xb7, 0x50, 0x68, 0xb2, 0x1d, 0xcb, 0xff, 0x3f, 0x6e, 0x18, 0x77, 0xdd, - 0x25, 0xcc, 0xe2, 0xba, 0xce, 0x46, 0xab, 0x42, 0x56, 0x12, 0x6e, 0x13, 0x4a, 0x14, 0x36, 0x8a, 0x57, 0xab, 0x5c, - 0xbb, 0x88, 0xcd, 0x2b, 0x0a, 0xe0, 0x2e, 0x10, 0xa7, 0x18, 0x58, 0x68, 0x63, 0x20, 0xf7, 0x99, 0x17, 0x92, 0x59, - 0xb5, 0x8f, 0xb9, 0x47, 0xfe, 0x19, 0x82, 0x31, 0xaa, 0x38, 0x19, 0xcf, 0x14, 0xd6, 0xc5, 0x97, 0xe4, 0xbd, 0xff, - 0xc1, 0x51, 0x64, 0x8f, 0x66, 0xd0, 0x13, 0x44, 0xce, 0x23, 0xce, 0x9e, 0x4c, 0x5e, 0x06, 0xee, 0x67, 0xb0, 0xd2, - 0x5f, 0x77, 0x9b, 0xb1, 0xb6, 0x3d, 0xba, 0x17, 0x46, 0x28, 0xfa, 0x19, 0xdf, 0x99, 0x7a, 0x01, 0x97, 0x50, 0x0d, - 0xec, 0xfa, 0xf2, 0x92, 0x97, 0x00, 0x22, 0x94, 0x89, 0x7e, 0xbf, 0xf7, 0xa7, 0x81, 0x26, 0x2d, 0x79, 0xf1, 0x3a, - 0x13, 0xd6, 0x19, 0x07, 0x9a, 0x0a, 0xd4, 0xff, 0x53, 0x65, 0x9f, 0xe9, 0x98, 0xcc, 0xfc, 0xc7, 0xe1, 0x84, 0x44, - 0xcd, 0xd7, 0xe4, 0x0b, 0xa7, 0xe9, 0x17, 0xae, 0x68, 0xff, 0x0d, 0x99, 0xb9, 0xe1, 0x90, 0xa1, 0xfe, 0xd2, 0x31, - 0x4f, 0x46, 0xaf, 0x13, 0xb3, 0x13, 0xc1, 0xaa, 0x19, 0x44, 0x61, 0x2f, 0xe0, 0x41, 0x5d, 0xcb, 0xe2, 0x29, 0xcc, - 0x3e, 0xa8, 0x11, 0xc5, 0x31, 0x1b, 0xcf, 0x42, 0x19, 0x4e, 0xc0, 0xbe, 0x77, 0x32, 0x86, 0xfb, 0x80, 0x0c, 0x3f, - 0x55, 0x21, 0x76, 0x0e, 0xd2, 0x3e, 0x55, 0xa8, 0x98, 0x00, 0x88, 0x40, 0xc8, 0xdb, 0xef, 0x4b, 0x95, 0x84, 0xaf, - 0x4b, 0x4c, 0x29, 0xd4, 0x07, 0xff, 0x1d, 0xa9, 0xba, 0x63, 0xfa, 0xd5, 0xfa, 0xf1, 0x67, 0x42, 0xf1, 0xe9, 0x2e, - 0x25, 0xbe, 0x85, 0xe0, 0xce, 0x31, 0xe8, 0x20, 0x2a, 0x34, 0x63, 0xbb, 0x9f, 0xdf, 0x15, 0x77, 0xf3, 0xbb, 0xe2, - 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, 0xf4, 0xdf, 0xe7, 0x13, 0xef, - 0xe4, 0xa9, 0xaf, 0x32, 0x31, 0xbd, 0x83, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd3, 0x93, 0x75, 0x65, 0x6f, - 0xad, 0x64, 0x88, 0x79, 0xee, 0x61, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, - 0x2b, 0x7d, 0xdf, 0xed, 0x8c, 0x0a, 0xf3, 0x5e, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, - 0xb7, 0x19, 0xab, 0x86, 0x6c, 0xbe, 0x93, 0x91, 0xda, 0x33, 0x79, 0x9a, 0xec, 0x93, 0xde, 0x01, 0xef, 0x90, 0x9f, - 0xd7, 0x9f, 0xc2, 0x58, 0x1a, 0x7e, 0x4b, 0x5e, 0xc6, 0x45, 0x56, 0x2d, 0xaf, 0xb2, 0x04, 0x99, 0x2e, 0x78, 0xf1, - 0xd5, 0x4c, 0x97, 0xf7, 0xb1, 0x3e, 0x60, 0x3c, 0xa5, 0x78, 0xdd, 0x10, 0xa5, 0x5f, 0xb4, 0x3c, 0x2b, 0xd4, 0xe5, - 0x49, 0xc5, 0x6c, 0xcf, 0x4a, 0x70, 0x3a, 0x05, 0x13, 0x7c, 0xfd, 0xd3, 0xf5, 0x3e, 0x01, 0x5c, 0x50, 0xa8, 0x39, - 0x2d, 0xe4, 0xca, 0x60, 0x39, 0x59, 0xe8, 0x4e, 0xc0, 0x0c, 0x95, 0x02, 0x2f, 0x50, 0xf0, 0x17, 0x0d, 0x8c, 0xe8, - 0x0b, 0xf7, 0x9b, 0x0c, 0x0c, 0xd2, 0xa5, 0x39, 0x11, 0xc6, 0x8e, 0xdb, 0x49, 0xd2, 0x56, 0x94, 0x33, 0xce, 0xde, - 0xab, 0x2b, 0x05, 0x18, 0xe0, 0x6d, 0x6f, 0xa2, 0x4d, 0x82, 0x5e, 0x0b, 0x4a, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0x32, - 0xc2, 0xc5, 0x87, 0x95, 0xc7, 0x82, 0x7b, 0xf6, 0x0b, 0x89, 0xb5, 0xf5, 0x03, 0x63, 0x36, 0x2f, 0x58, 0xa0, 0x50, - 0x81, 0x02, 0xcb, 0x99, 0xb6, 0x34, 0xad, 0x86, 0xfc, 0xf0, 0x08, 0xad, 0x4d, 0xab, 0x01, 0x3f, 0x3c, 0xaa, 0xa3, - 0xec, 0x18, 0xb2, 0x9c, 0xf8, 0x19, 0xd4, 0xeb, 0x3a, 0x32, 0x29, 0x26, 0xbb, 0x57, 0x5f, 0x9e, 0xfa, 0xa3, 0xba, - 0x05, 0xd7, 0x0f, 0x40, 0x00, 0x1b, 0x80, 0x43, 0xa0, 0x1a, 0x2c, 0x8d, 0x08, 0x16, 0x65, 0x0a, 0xed, 0x6b, 0xe8, - 0xbd, 0xd1, 0xf0, 0x5f, 0xe0, 0x2e, 0x22, 0x57, 0xfe, 0x27, 0x08, 0xfc, 0x15, 0x65, 0x5a, 0x99, 0xe2, 0x7f, 0xa2, - 0xd5, 0x2b, 0x94, 0xb3, 0xa6, 0x35, 0x1f, 0x44, 0x6b, 0x22, 0x54, 0x33, 0x86, 0xe0, 0xdf, 0xca, 0x32, 0x6d, 0xa9, - 0xaa, 0xd4, 0x87, 0xc6, 0x6b, 0xad, 0x70, 0x96, 0x8f, 0x23, 0xef, 0x35, 0x86, 0x8e, 0x4d, 0x9c, 0xa5, 0x9c, 0x4a, - 0x9d, 0xbd, 0x39, 0x94, 0x91, 0x03, 0x9c, 0x4e, 0xd8, 0x78, 0x9a, 0x1c, 0xcb, 0x69, 0xe2, 0x20, 0xf3, 0x73, 0x86, - 0x91, 0x55, 0x0d, 0x08, 0x8b, 0xb2, 0xa1, 0xb4, 0x05, 0x98, 0xe4, 0x84, 0x90, 0x29, 0x86, 0xa2, 0xc8, 0x47, 0xba, - 0x1f, 0xd6, 0x9b, 0xd5, 0x7d, 0xf1, 0x4e, 0x03, 0x9c, 0x86, 0x09, 0x04, 0x02, 0x2f, 0xe2, 0x9b, 0x4c, 0x5c, 0x82, - 0xc7, 0xf0, 0x00, 0xbe, 0x04, 0x37, 0xb9, 0x94, 0xfd, 0xab, 0x0a, 0x73, 0x5c, 0x5b, 0xc0, 0xa0, 0xc1, 0xea, 0x41, - 0x74, 0xb8, 0x94, 0x36, 0xbb, 0x0a, 0x10, 0x1b, 0x53, 0x88, 0x65, 0xc1, 0xd6, 0x96, 0x3d, 0xfb, 0x59, 0x35, 0x0d, - 0xad, 0x13, 0x4e, 0xc5, 0x65, 0x0e, 0x51, 0x54, 0x06, 0x31, 0xb8, 0x23, 0x79, 0x7c, 0xde, 0xa9, 0x08, 0x2f, 0x08, - 0xb8, 0x95, 0x25, 0x32, 0x5c, 0xd1, 0xe5, 0xe8, 0x96, 0xae, 0x47, 0x37, 0x74, 0x4c, 0x27, 0x7f, 0x1f, 0xa3, 0x45, - 0xb6, 0x4a, 0xdd, 0xd0, 0xf5, 0x68, 0x49, 0xbf, 0x1f, 0xd3, 0xa3, 0xbf, 0x8d, 0xc9, 0x74, 0x89, 0x87, 0x09, 0xbd, - 0x00, 0xc7, 0x2e, 0x52, 0xa3, 0xa7, 0xa6, 0x6f, 0x70, 0x58, 0x8d, 0xf2, 0x21, 0x1f, 0xe5, 0x94, 0x8f, 0x8a, 0x61, - 0x35, 0x02, 0x4f, 0xc7, 0x6a, 0xc8, 0x47, 0x15, 0xe5, 0xa3, 0xf3, 0x61, 0x35, 0x3a, 0x27, 0xcd, 0xa6, 0xbf, 0xaa, - 0xf8, 0x55, 0xc9, 0x2e, 0x60, 0x5b, 0xc0, 0xf2, 0x75, 0xab, 0x6c, 0x99, 0xfa, 0xab, 0xda, 0x9c, 0xcc, 0x96, 0xb3, - 0xb7, 0xd7, 0x5d, 0x4e, 0x2c, 0x1e, 0xb7, 0x4d, 0x87, 0xab, 0x2f, 0x27, 0xea, 0xa4, 0x57, 0xc8, 0x0f, 0xe3, 0xa9, - 0x50, 0xe7, 0x10, 0x98, 0x49, 0xcc, 0xc2, 0x98, 0x61, 0x33, 0x75, 0x1a, 0x28, 0x70, 0xb2, 0x91, 0xe7, 0xa2, 0x98, - 0x8d, 0x72, 0x0a, 0xef, 0x63, 0x42, 0x22, 0x01, 0x67, 0xd5, 0x49, 0x35, 0x2a, 0x20, 0xe6, 0x08, 0x0b, 0xf1, 0x11, - 0xfa, 0xa5, 0x3e, 0xf2, 0x90, 0xc0, 0x33, 0xec, 0x6b, 0x31, 0x88, 0xe1, 0x88, 0xb7, 0x95, 0x55, 0xb3, 0x30, 0x81, - 0xca, 0xaa, 0x61, 0x69, 0x2a, 0x2b, 0x68, 0x36, 0xaa, 0xfc, 0xca, 0x2a, 0x1c, 0xa3, 0x84, 0x90, 0xa8, 0xd4, 0x95, - 0x81, 0xfa, 0x24, 0x61, 0x61, 0xa9, 0x2b, 0x3b, 0x57, 0x1f, 0x9d, 0xfb, 0x95, 0x9d, 0x83, 0x0b, 0xe9, 0x20, 0xf1, - 0xaf, 0x52, 0x69, 0xda, 0xbe, 0x0e, 0x36, 0x56, 0x15, 0xdd, 0xf2, 0xdb, 0xaa, 0x88, 0xa3, 0x92, 0xba, 0x18, 0xd0, - 0xb8, 0x30, 0x22, 0x49, 0xf5, 0x1a, 0x05, 0x7f, 0x48, 0x10, 0x95, 0xc6, 0xe0, 0xd5, 0x99, 0x74, 0xad, 0xd4, 0x8a, - 0x8a, 0x41, 0x39, 0x28, 0xe0, 0xfe, 0x94, 0xb7, 0x16, 0xd2, 0xcf, 0x10, 0x51, 0x19, 0xca, 0x1b, 0xfc, 0x82, 0xc1, - 0x93, 0xd9, 0x55, 0x1a, 0x26, 0xa3, 0x0d, 0x8d, 0x47, 0x4b, 0x84, 0x83, 0x61, 0xab, 0x54, 0xe1, 0xad, 0x5f, 0x42, - 0xfa, 0x2d, 0x8d, 0x47, 0x37, 0x34, 0xb5, 0x36, 0xa7, 0x06, 0xea, 0xaa, 0x37, 0xa6, 0xb7, 0x11, 0xbc, 0xde, 0x44, - 0x4b, 0x0a, 0x5b, 0xe9, 0x34, 0xcf, 0x2e, 0x45, 0x94, 0x52, 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa3, 0x0d, - 0xae, 0x07, 0x50, 0x86, 0x86, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, 0xd2, 0x23, 0x53, 0x6b, 0x7d, 0x91, 0x45, 0xf8, 0x68, - 0x67, 0xa3, 0xa5, 0x78, 0x46, 0x2c, 0x8c, 0x2b, 0x18, 0x42, 0x5d, 0x58, 0x69, 0x0a, 0x92, 0x2e, 0x70, 0x64, 0x2f, - 0x8c, 0xab, 0x70, 0x0b, 0xa6, 0x45, 0x1b, 0x30, 0x8f, 0x02, 0x85, 0x83, 0x4b, 0x90, 0x7e, 0x42, 0xd9, 0xce, 0x51, - 0x9a, 0x1c, 0xde, 0x04, 0x5d, 0xec, 0x4d, 0x10, 0xd2, 0xae, 0x6e, 0xb2, 0x25, 0x7d, 0x83, 0xed, 0x3d, 0x3a, 0x15, - 0x15, 0x54, 0x9f, 0x5b, 0x30, 0x59, 0xb2, 0x41, 0xd8, 0x12, 0xa6, 0x67, 0xfa, 0x02, 0xb0, 0xa7, 0x0f, 0x8f, 0xf6, - 0xe6, 0xbb, 0x98, 0xbd, 0x39, 0x2c, 0xa3, 0xb1, 0xb2, 0xe0, 0xcd, 0x2d, 0xb1, 0x5b, 0xb2, 0xf1, 0x74, 0x79, 0x5c, - 0x4e, 0x97, 0x48, 0xec, 0x0c, 0xdd, 0x62, 0x7c, 0xbe, 0x5c, 0xd0, 0x04, 0xcf, 0x36, 0x56, 0xcd, 0x97, 0x06, 0x2d, - 0x25, 0x65, 0xb8, 0xde, 0x96, 0xe8, 0xff, 0xaf, 0x2e, 0x7e, 0x29, 0xc0, 0x4b, 0x30, 0x16, 0x00, 0xc2, 0x3d, 0x98, - 0x16, 0xa4, 0x36, 0xca, 0xc6, 0x3a, 0x0d, 0x53, 0x5c, 0x04, 0x26, 0xa5, 0xdf, 0x0f, 0x73, 0x96, 0x12, 0x0f, 0x3a, - 0xd4, 0x8e, 0xd2, 0xaa, 0x61, 0x33, 0x07, 0x3c, 0x92, 0x3a, 0xc7, 0x26, 0x7f, 0x1f, 0xcf, 0x02, 0x35, 0x10, 0x41, - 0x94, 0x1d, 0xe3, 0x23, 0x06, 0x2e, 0x8a, 0x74, 0xdc, 0x4e, 0x57, 0xc4, 0xe5, 0xfe, 0x31, 0x0b, 0x71, 0x92, 0x30, - 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, 0x04, 0x91, 0x5a, 0x6d, - 0x19, 0x57, 0x5d, 0x65, 0x7c, 0x0f, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, 0x9b, 0x28, 0xe4, 0x27, - 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0xef, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0xe7, 0xcd, 0x59, 0xd7, 0x50, 0x9a, 0xb8, - 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, 0x82, 0x09, 0x3a, 0x9a, - 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x9e, 0x25, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, 0x0f, 0xaa, 0x93, 0x75, - 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xcd, - 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, - 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, 0x01, 0x70, 0x32, 0xdb, - 0xdb, 0x68, 0x49, 0x37, 0x51, 0x4a, 0x6f, 0xa2, 0x35, 0x5d, 0x46, 0x17, 0xc6, 0xc4, 0x38, 0xa9, 0xe1, 0x1c, 0x80, - 0x56, 0x01, 0x24, 0x9e, 0xfa, 0xf5, 0x9e, 0x27, 0x55, 0xb8, 0xa4, 0x29, 0xb8, 0x0d, 0xfb, 0xf6, 0x99, 0x67, 0xbe, - 0x44, 0x6a, 0x8b, 0x18, 0x6b, 0xd6, 0x50, 0x71, 0xeb, 0xad, 0xfb, 0x48, 0xd4, 0xb0, 0x73, 0x5d, 0x6c, 0xa2, 0x6a, - 0x38, 0x99, 0x96, 0x80, 0xd8, 0x5a, 0x0e, 0x87, 0xee, 0x08, 0xd9, 0x3f, 0x7e, 0x74, 0xa0, 0xe7, 0x9e, 0xb4, 0xd8, - 0xb6, 0x2d, 0x7f, 0x60, 0x08, 0x53, 0xfa, 0xe5, 0x23, 0x1f, 0x10, 0x2b, 0xce, 0xe1, 0x6c, 0x04, 0xea, 0x68, 0x85, - 0x4e, 0xff, 0xaa, 0xc2, 0x42, 0x1f, 0xe0, 0xdb, 0xdb, 0x28, 0xa1, 0x9b, 0x28, 0xf7, 0xc8, 0xda, 0xb2, 0x66, 0x72, - 0x7a, 0x96, 0x85, 0xbc, 0x7d, 0xa0, 0x97, 0x0b, 0x00, 0xd1, 0x1a, 0xc4, 0xbe, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, - 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xb8, 0x92, 0xf0, 0x37, 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, - 0x39, 0x0f, 0x6a, 0x7f, 0x24, 0x5f, 0x17, 0x6d, 0x6f, 0x57, 0x18, 0x4d, 0x30, 0xf6, 0x44, 0xfb, 0x3c, 0x52, 0x8e, - 0xe2, 0x22, 0x09, 0xb3, 0xd1, 0xad, 0x3a, 0xcf, 0x69, 0x36, 0xda, 0xe8, 0x5f, 0x15, 0x1d, 0xd3, 0x5f, 0x75, 0x40, - 0x1b, 0x25, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0x34, 0xfe, 0xd7, 0x72, 0x74, 0x4b, 0xe5, 0x68, 0xe3, 0x5b, - 0x52, 0x4d, 0xa6, 0xc5, 0xb1, 0x40, 0x43, 0xaa, 0xce, 0xef, 0x0b, 0xe0, 0xe7, 0x4a, 0xe3, 0x3b, 0x6d, 0xbe, 0xf7, - 0xda, 0xbf, 0xe9, 0xe4, 0x09, 0x14, 0x4b, 0x54, 0xb0, 0x6a, 0x04, 0x76, 0xec, 0xeb, 0x3c, 0x2e, 0xcc, 0x28, 0xc5, - 0xd4, 0x9a, 0xf4, 0x63, 0xe0, 0x8a, 0x69, 0xaf, 0x00, 0x57, 0x4b, 0x70, 0x12, 0x80, 0x18, 0x9a, 0xb0, 0x67, 0xc7, - 0x10, 0xf5, 0xdc, 0x38, 0x46, 0xc9, 0x86, 0x7b, 0x40, 0xac, 0x65, 0xde, 0xca, 0x25, 0x20, 0x81, 0xb7, 0x1e, 0x26, - 0x05, 0x60, 0x0c, 0x96, 0x4b, 0xa2, 0xf3, 0x78, 0xe8, 0x13, 0xea, 0x85, 0x46, 0x9d, 0x90, 0x8d, 0x2d, 0x81, 0xe3, - 0x0f, 0xeb, 0x43, 0x20, 0x78, 0x95, 0xe7, 0xfa, 0x2b, 0xad, 0xeb, 0x2f, 0x95, 0x9e, 0x3b, 0x96, 0x17, 0xb5, 0xba, - 0x4d, 0x8d, 0x5e, 0x80, 0x85, 0xef, 0x56, 0x99, 0x47, 0x72, 0x8b, 0x90, 0xaa, 0xc0, 0x4a, 0xdd, 0x42, 0x82, 0xf9, - 0x57, 0x72, 0xb6, 0x2a, 0xf3, 0xd5, 0x23, 0xf7, 0xca, 0xd9, 0xf4, 0xf4, 0x37, 0x24, 0x68, 0x9b, 0x8e, 0x34, 0x8f, - 0xb7, 0xe8, 0xf0, 0xd9, 0xb5, 0x96, 0x98, 0x7b, 0x89, 0x8a, 0xe7, 0x53, 0xc0, 0x56, 0xcf, 0xb2, 0x2b, 0xe5, 0x63, - 0xb5, 0x8f, 0xe3, 0x67, 0xce, 0x9f, 0xa4, 0x0a, 0x2f, 0x44, 0x43, 0x09, 0x02, 0xde, 0x1c, 0xc6, 0xae, 0x50, 0x05, - 0x34, 0x34, 0x37, 0x70, 0x9c, 0xab, 0x61, 0xa5, 0x09, 0x98, 0x96, 0xf2, 0xe8, 0x00, 0x87, 0x26, 0x8f, 0xda, 0x4d, - 0xc3, 0xca, 0xd0, 0xb5, 0x46, 0x9f, 0xdb, 0x4a, 0x67, 0xbc, 0xd9, 0xf0, 0xc3, 0xa3, 0x41, 0x85, 0x3f, 0x49, 0x73, - 0x34, 0xda, 0xb9, 0xe1, 0x4e, 0x23, 0x30, 0x73, 0x25, 0x57, 0x64, 0x7f, 0x94, 0xbc, 0xfc, 0x9e, 0x5e, 0x58, 0x40, - 0x7f, 0xfe, 0xfb, 0x62, 0xc2, 0x49, 0x4b, 0x4c, 0x88, 0x96, 0x0e, 0x5a, 0x74, 0xb0, 0xa7, 0xbc, 0xb2, 0x2f, 0xf1, - 0xd2, 0x39, 0xfe, 0xcf, 0xf5, 0x58, 0xfb, 0x0a, 0x84, 0x56, 0x27, 0x0f, 0xdb, 0x93, 0x05, 0xa2, 0x06, 0x54, 0xb3, - 0xab, 0x72, 0x94, 0x69, 0x67, 0x45, 0xb6, 0x0d, 0x99, 0xeb, 0x7e, 0x96, 0x86, 0xcd, 0x64, 0xc7, 0xc2, 0x32, 0xc3, - 0x60, 0xed, 0x54, 0xd1, 0xe7, 0xa0, 0xe5, 0x47, 0xf0, 0xac, 0xa9, 0x3c, 0xf3, 0xd9, 0x2c, 0x23, 0x5e, 0xa0, 0x73, - 0x4e, 0xc5, 0xa2, 0x29, 0x1d, 0x2b, 0x77, 0xbb, 0x12, 0x8d, 0x25, 0xca, 0x28, 0x08, 0x6a, 0x1b, 0x84, 0x5d, 0x97, - 0xee, 0x49, 0x9f, 0xf6, 0xf1, 0x69, 0x05, 0xfa, 0x1e, 0xdf, 0x65, 0x20, 0x31, 0xf5, 0x24, 0x0f, 0x55, 0xa3, 0x39, - 0x3a, 0x79, 0x96, 0xa7, 0x1a, 0x9f, 0x5f, 0xc9, 0xce, 0x9a, 0x77, 0xab, 0x31, 0xc5, 0x7f, 0xa4, 0x6e, 0xdf, 0xb9, - 0x0c, 0x4d, 0xf4, 0xd7, 0xf2, 0xa0, 0xa5, 0xb0, 0xe0, 0xb8, 0x6d, 0xfc, 0xf5, 0xdb, 0xcc, 0x21, 0x86, 0xa5, 0xcb, - 0xe1, 0x4d, 0xe8, 0xd0, 0xdd, 0x55, 0xf6, 0xe6, 0xfa, 0x88, 0x3a, 0x75, 0xb1, 0x6e, 0x03, 0x4a, 0x96, 0xbc, 0x5b, - 0xa7, 0x27, 0x56, 0xfa, 0xf5, 0x30, 0xdc, 0x9b, 0x47, 0xcd, 0xee, 0xee, 0x76, 0x13, 0xd2, 0xb6, 0x0f, 0xc6, 0xfb, - 0x12, 0x16, 0xe2, 0xbc, 0xc3, 0x0e, 0x7e, 0x0e, 0xab, 0x87, 0x7c, 0xf0, 0x3b, 0x8e, 0x33, 0x8c, 0x7e, 0xa6, 0x0c, - 0x7d, 0x5e, 0x14, 0xf2, 0x4a, 0x75, 0xca, 0x17, 0xba, 0xb5, 0x4c, 0xbd, 0xdf, 0xc4, 0x6f, 0x5a, 0x01, 0x62, 0xbc, - 0xae, 0x58, 0x29, 0xde, 0xd0, 0x0a, 0xe3, 0x1a, 0xb8, 0x4d, 0x0e, 0xb5, 0x54, 0x0b, 0x44, 0x5d, 0x7e, 0xf2, 0x90, - 0x47, 0x46, 0x9d, 0x09, 0xdf, 0x3d, 0xe4, 0xbe, 0x74, 0x6d, 0xbf, 0x89, 0x5f, 0x6a, 0xda, 0xe1, 0xfe, 0x40, 0x77, - 0xb4, 0xee, 0xfe, 0xe6, 0xd9, 0xfc, 0x3c, 0x32, 0x5f, 0x0c, 0xb0, 0x59, 0xfb, 0x8c, 0xcb, 0x9e, 0xe1, 0xbe, 0x37, - 0x3d, 0x18, 0x0b, 0x08, 0x24, 0x66, 0xe8, 0x65, 0xe0, 0x02, 0x17, 0xb8, 0x2b, 0x0c, 0x18, 0xe2, 0x9a, 0x96, 0xdc, - 0x6a, 0x2b, 0x5b, 0x1f, 0x79, 0x1b, 0x15, 0x82, 0x75, 0xdd, 0x71, 0x93, 0xe4, 0x10, 0x9c, 0xb0, 0xe5, 0xde, 0xd7, - 0x5e, 0x3b, 0xc3, 0x5f, 0x06, 0xc2, 0xb9, 0x25, 0x7a, 0x46, 0x6d, 0x0f, 0xb5, 0xba, 0xd7, 0xf0, 0x2a, 0x9b, 0xc8, - 0xb3, 0x7e, 0x33, 0x2f, 0x0d, 0xfb, 0x82, 0xd7, 0x52, 0x70, 0x68, 0x6c, 0xb7, 0xc2, 0x2d, 0x16, 0xef, 0x68, 0xb5, - 0xb2, 0xd6, 0x56, 0x7b, 0xad, 0x54, 0xf4, 0xee, 0x35, 0xc7, 0x89, 0xb3, 0x14, 0xb6, 0x1f, 0xde, 0x5f, 0xb0, 0x6b, - 0x02, 0x18, 0xb4, 0x98, 0x2c, 0x50, 0x82, 0x4a, 0xd6, 0xaa, 0x76, 0x3b, 0x25, 0x7e, 0xb9, 0x5f, 0x75, 0x99, 0xed, - 0x3c, 0x7e, 0xdd, 0xa4, 0x7d, 0xe1, 0x73, 0xf4, 0xc3, 0xfc, 0xc1, 0x3a, 0x29, 0x39, 0xc3, 0xb8, 0x96, 0xff, 0x5f, - 0x45, 0x2f, 0x8b, 0x2c, 0x8d, 0xb6, 0x86, 0x07, 0xb3, 0xa1, 0x36, 0x7d, 0x68, 0x8c, 0xca, 0x2d, 0x1b, 0x45, 0x44, - 0xab, 0x5b, 0x10, 0xcc, 0x28, 0xee, 0x4b, 0xb4, 0x79, 0xa5, 0xca, 0xc2, 0x3b, 0x7c, 0x61, 0xa3, 0x37, 0x6c, 0x4f, - 0x08, 0xe5, 0xfb, 0xa7, 0x85, 0x59, 0xb5, 0x54, 0x34, 0xd8, 0x2e, 0xe1, 0x5d, 0x8c, 0x2a, 0xfd, 0x84, 0xc9, 0x96, - 0x05, 0x53, 0xfd, 0xff, 0xb1, 0xc8, 0xd2, 0x36, 0x45, 0x07, 0xa6, 0xb3, 0xe9, 0xd3, 0x49, 0xb7, 0xb8, 0xce, 0x80, - 0x45, 0x04, 0x5b, 0x2a, 0x1c, 0x8f, 0x52, 0xbb, 0x41, 0xc2, 0x44, 0x70, 0x13, 0xf5, 0xb2, 0xa3, 0x65, 0x4a, 0x56, - 0x05, 0x3c, 0xbf, 0x72, 0x95, 0xe9, 0x38, 0x1a, 0xfa, 0xfd, 0xb3, 0xd4, 0x84, 0x7e, 0xa5, 0x5e, 0xaa, 0xe2, 0x3c, - 0x8c, 0xaa, 0x43, 0x85, 0x31, 0x5a, 0xd2, 0x14, 0x8e, 0xc1, 0xec, 0x22, 0x4c, 0xf1, 0x72, 0xb6, 0x4d, 0xd8, 0x57, - 0x0c, 0xe4, 0x52, 0x1b, 0xd4, 0x6b, 0x4a, 0xb4, 0x66, 0xed, 0xcd, 0x9c, 0x12, 0x7a, 0xc1, 0x4a, 0xff, 0x2e, 0xb4, - 0x06, 0x81, 0xa2, 0x6c, 0xa6, 0x4c, 0x37, 0xba, 0x9d, 0x17, 0x34, 0xa1, 0x05, 0x5d, 0x91, 0x1a, 0xf4, 0xbd, 0x4e, - 0xce, 0x8e, 0x4e, 0x76, 0x66, 0xd6, 0x63, 0x56, 0x0c, 0x27, 0xd3, 0x18, 0xae, 0x69, 0xb1, 0xbb, 0xa6, 0x2d, 0x9b, - 0x37, 0xae, 0xc6, 0xc6, 0x69, 0xd0, 0x2e, 0x90, 0xb6, 0x69, 0x6e, 0x3f, 0xf5, 0xb8, 0xfd, 0x75, 0xcd, 0x96, 0xd3, - 0xde, 0x7a, 0xb7, 0xeb, 0xa5, 0x60, 0x23, 0xea, 0xf1, 0xf1, 0x6b, 0x25, 0x5d, 0xb7, 0x5c, 0x7e, 0x0a, 0xcf, 0x1e, - 0x5f, 0xbf, 0xf4, 0xc1, 0xe5, 0x68, 0xd5, 0xe6, 0xee, 0x97, 0xfb, 0xc8, 0x72, 0x5f, 0x35, 0xb4, 0x5c, 0xcf, 0x50, - 0x93, 0x3c, 0x1b, 0xed, 0x1d, 0x6a, 0xc1, 0x72, 0xd6, 0x4d, 0x78, 0x62, 0xb0, 0x63, 0xaf, 0x1a, 0x9b, 0xa3, 0x32, - 0x97, 0xac, 0x06, 0x09, 0xf4, 0x49, 0x9e, 0x69, 0xfa, 0x47, 0x19, 0xe6, 0xa3, 0x5b, 0x9a, 0x03, 0xae, 0x58, 0x65, - 0x2f, 0x19, 0xa4, 0xae, 0xda, 0x4b, 0x5c, 0xf9, 0x0a, 0x87, 0x64, 0x8b, 0x4f, 0x86, 0xa9, 0xfa, 0xe2, 0x92, 0x07, - 0xff, 0x6f, 0xab, 0x56, 0xe9, 0xb9, 0x49, 0x6e, 0x38, 0xfe, 0x75, 0xd2, 0xf6, 0x31, 0x31, 0x48, 0xc0, 0x53, 0xbb, - 0x18, 0xaa, 0x51, 0x55, 0xc4, 0xa2, 0xcc, 0x4d, 0xcc, 0xb1, 0x3b, 0xbb, 0x86, 0x0e, 0xca, 0xe0, 0xd7, 0x0d, 0x9f, - 0x98, 0x3b, 0xb0, 0x15, 0xe8, 0xe8, 0x44, 0x73, 0x19, 0x66, 0xe6, 0x32, 0x4c, 0xbb, 0xb6, 0x0a, 0x0c, 0xaf, 0xda, - 0x2a, 0x89, 0x72, 0x35, 0xea, 0x71, 0x33, 0x4b, 0xcd, 0x5e, 0xe4, 0xdd, 0x6b, 0xd2, 0x93, 0xf8, 0xd3, 0xa5, 0x27, - 0xaf, 0x87, 0x01, 0x91, 0x5f, 0xb3, 0x34, 0x5c, 0xa3, 0x20, 0x38, 0xb5, 0xda, 0x81, 0x34, 0x1f, 0x01, 0x32, 0x3f, - 0x4e, 0xc3, 0x0f, 0x5a, 0x9c, 0x43, 0xb6, 0x4a, 0xe3, 0xc4, 0x96, 0x46, 0x3d, 0x04, 0x77, 0xde, 0x2b, 0x1e, 0x43, - 0xe0, 0xc3, 0x8f, 0xb8, 0x19, 0x54, 0x74, 0x5b, 0x62, 0xa2, 0xb4, 0x79, 0xd4, 0x2d, 0x1f, 0x35, 0x84, 0x4a, 0x56, - 0x86, 0x97, 0x40, 0x7b, 0xf7, 0x04, 0x46, 0x95, 0x13, 0xc8, 0x0c, 0x8b, 0xc3, 0xa3, 0x61, 0xaa, 0x04, 0x45, 0x43, - 0x39, 0x5c, 0xa2, 0x1c, 0x10, 0x93, 0x40, 0x60, 0x54, 0x0c, 0x52, 0x5d, 0x99, 0x7a, 0x31, 0x48, 0xf5, 0xad, 0x8a, - 0xd4, 0x67, 0x59, 0x58, 0x51, 0xdd, 0x22, 0x3a, 0xa6, 0x43, 0x49, 0x97, 0x66, 0xa7, 0xe6, 0x5a, 0x7a, 0xa1, 0x96, - 0xe3, 0x53, 0x9d, 0x06, 0xa3, 0xf8, 0xc1, 0xa5, 0xe8, 0xb7, 0x6a, 0x3f, 0xfb, 0x6f, 0x31, 0xa5, 0x46, 0x6c, 0x6a, - 0x6f, 0x11, 0xc3, 0xaa, 0xfd, 0x98, 0x55, 0x39, 0x68, 0x77, 0x41, 0xd9, 0x58, 0x19, 0xe7, 0xf9, 0x46, 0x30, 0x73, - 0xd0, 0x36, 0x56, 0x4d, 0x1f, 0x7a, 0x23, 0x46, 0xed, 0x8d, 0xa9, 0xc6, 0x3d, 0x81, 0x9f, 0x36, 0x68, 0xba, 0x17, - 0x79, 0x8e, 0x7a, 0xe4, 0xdd, 0xff, 0xcc, 0x91, 0x9d, 0xc9, 0x17, 0xb1, 0x4c, 0xea, 0xf6, 0x31, 0x09, 0x16, 0xaa, - 0x8e, 0xd1, 0x85, 0x1b, 0x99, 0xd2, 0x7e, 0xee, 0x4d, 0x3f, 0xe2, 0x99, 0xdc, 0x6f, 0x87, 0x46, 0x7d, 0x69, 0x58, - 0x4b, 0x8a, 0xa8, 0x2f, 0xe8, 0xad, 0xa9, 0x8e, 0x8e, 0xa8, 0xd7, 0x11, 0x58, 0x5d, 0xd1, 0x16, 0x35, 0x00, 0x93, - 0x71, 0x6d, 0x6b, 0xf3, 0x39, 0x98, 0xda, 0xaa, 0x0a, 0x9e, 0xd0, 0x7d, 0xa1, 0x74, 0x6f, 0x52, 0xd7, 0xad, 0x21, - 0xb6, 0x80, 0x01, 0x81, 0x1b, 0x3d, 0x35, 0xfd, 0x41, 0x13, 0x15, 0x80, 0x06, 0x8d, 0xdb, 0x99, 0xce, 0x91, 0xe8, - 0x77, 0x6a, 0xd3, 0x36, 0x53, 0xbd, 0xaa, 0x7c, 0x00, 0x15, 0x7f, 0x96, 0xce, 0x2e, 0xcc, 0x88, 0x05, 0x30, 0xee, - 0x81, 0x33, 0xd5, 0x3b, 0xcd, 0xc0, 0x7a, 0x22, 0xcf, 0xb3, 0x92, 0x27, 0x52, 0xc0, 0x8c, 0xc8, 0xab, 0x2b, 0x29, - 0x60, 0x18, 0xd4, 0x00, 0xa0, 0x45, 0x73, 0x19, 0x4d, 0xf8, 0xa3, 0x9a, 0xde, 0x95, 0x87, 0x3f, 0xd2, 0xb9, 0xbe, - 0x1b, 0xd7, 0x60, 0xa8, 0xbc, 0xae, 0xf8, 0x5e, 0xa6, 0xef, 0xf8, 0x63, 0x2f, 0xd3, 0x52, 0xae, 0x8b, 0xbd, 0x2c, - 0x8f, 0xbe, 0xe3, 0x4f, 0x74, 0x9e, 0xa3, 0xc7, 0x35, 0x4d, 0xe3, 0xcd, 0x5e, 0x96, 0xbf, 0x7f, 0xf7, 0xd8, 0xe6, - 0x79, 0x34, 0xae, 0xe9, 0x0d, 0xe7, 0x9f, 0x5c, 0xa6, 0x89, 0xae, 0x6a, 0xfc, 0xf8, 0xef, 0x36, 0xd7, 0xe3, 0x9a, - 0x5e, 0x49, 0x51, 0x2d, 0xf7, 0x8a, 0x3a, 0xfa, 0xee, 0xe8, 0xef, 0xfc, 0x3b, 0xd3, 0xbd, 0xa3, 0x9a, 0xfe, 0xb5, - 0x8e, 0x8b, 0x8a, 0x17, 0x7b, 0xc5, 0xfd, 0xed, 0xef, 0x7f, 0x7f, 0x6c, 0x33, 0x3e, 0xae, 0xe9, 0x86, 0xc7, 0x1d, - 0x6d, 0x9f, 0x3c, 0x79, 0xcc, 0xff, 0x56, 0xd7, 0xf4, 0x37, 0xe6, 0x07, 0x47, 0x3d, 0xcd, 0x3c, 0x3d, 0x7c, 0x2e, - 0x9b, 0xa8, 0x01, 0x43, 0x0f, 0x0d, 0x60, 0x29, 0xad, 0x9a, 0xe6, 0x0e, 0xaf, 0x5c, 0x70, 0xfb, 0x3e, 0x8b, 0xd3, - 0x78, 0x05, 0x07, 0xc1, 0x16, 0x8d, 0xb3, 0x0a, 0xe0, 0x54, 0x81, 0xf7, 0x8c, 0x4a, 0x9a, 0x95, 0xf2, 0x37, 0xce, - 0x3f, 0xc1, 0xa0, 0x21, 0xa4, 0x8d, 0x8a, 0x0c, 0xf4, 0x76, 0xa5, 0x23, 0x1b, 0xa1, 0xff, 0x66, 0x33, 0x0e, 0x8e, - 0x0f, 0xa3, 0xd7, 0xef, 0x87, 0x05, 0x13, 0x61, 0x41, 0x08, 0xfd, 0x33, 0x2c, 0xc0, 0xa1, 0xa4, 0x60, 0x5e, 0x3e, - 0xe3, 0x7b, 0xae, 0x8d, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xf6, 0x01, 0x55, 0x8f, 0xbe, 0x43, 0x37, 0xc4, 0xcb, 0x0a, - 0x0b, 0x86, 0x56, 0x35, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x4a, 0xf0, 0x89, 0x07, 0xf8, 0xe8, 0x31, 0x99, 0x71, - 0x75, 0xad, 0x7d, 0x7b, 0x11, 0x16, 0x34, 0xd0, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xff, 0x02, 0x3c, 0x05, 0x06, 0x3e, - 0x2c, 0xec, 0xba, 0x03, 0xcf, 0xe7, 0x37, 0xc3, 0x3a, 0xba, 0xf0, 0xa3, 0xbf, 0x59, 0x17, 0xf6, 0x8c, 0x4c, 0xe5, - 0x71, 0x39, 0x9c, 0x4c, 0x07, 0x03, 0xe9, 0xe2, 0xb8, 0x9d, 0x66, 0xf3, 0xdf, 0xe6, 0x72, 0xb1, 0x40, 0xdd, 0x37, - 0xce, 0xeb, 0x4c, 0xff, 0x8d, 0xb4, 0xf3, 0xc1, 0xeb, 0xd3, 0x7f, 0x9d, 0x7d, 0x38, 0x7d, 0x01, 0xce, 0x07, 0x1f, - 0x9f, 0xff, 0xf8, 0xfc, 0xbd, 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0x72, 0x18, - 0xc6, 0x0f, 0x0b, 0x65, 0xf4, 0x40, 0x8e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, - 0x8b, 0xeb, 0x86, 0x08, 0xd7, 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x4f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, - 0x18, 0x94, 0x0d, 0x6d, 0x3a, 0xcd, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, - 0xba, 0xfa, 0x04, 0x34, 0x00, 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0x37, 0xa8, - 0x7b, 0x32, 0xcd, 0xaa, 0x1a, 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x6d, 0x5e, - 0x2d, 0x4c, 0x73, 0xdc, 0x30, 0x54, 0x5e, 0xc9, 0x17, 0xb2, 0x81, 0xc8, 0x40, 0x32, 0x0c, 0x7b, 0x34, 0x46, 0x91, - 0xfa, 0xc1, 0xbe, 0x77, 0xfc, 0x36, 0x97, 0x10, 0x4d, 0x31, 0x03, 0xe9, 0xfc, 0x73, 0xa1, 0x9c, 0xcb, 0x25, 0xe3, - 0x73, 0xb1, 0x38, 0x01, 0xb7, 0xf3, 0xb9, 0x58, 0x44, 0x18, 0x94, 0x2f, 0x83, 0x58, 0x25, 0x60, 0xf7, 0xe2, 0xa0, - 0x47, 0x3a, 0xa1, 0x0d, 0xec, 0x06, 0x92, 0x6c, 0x50, 0xda, 0x95, 0x86, 0x28, 0x77, 0xca, 0xa3, 0x0d, 0x22, 0x0f, - 0xb1, 0x6a, 0x5e, 0xb5, 0x3d, 0xd9, 0xcc, 0xc5, 0x04, 0x57, 0x59, 0xcc, 0xe4, 0x34, 0x3e, 0x66, 0xc5, 0x34, 0x86, - 0x52, 0xe2, 0x34, 0x0d, 0x63, 0x3a, 0xa1, 0x82, 0x90, 0x84, 0xf1, 0x79, 0xbc, 0xa0, 0x09, 0x4a, 0x09, 0x42, 0x08, - 0xf9, 0x31, 0x42, 0xdb, 0x1c, 0x58, 0xf2, 0x76, 0xfb, 0x79, 0x2a, 0xbe, 0x3d, 0xc3, 0x65, 0x54, 0x84, 0x6e, 0xd1, - 0x59, 0xc3, 0xbf, 0x11, 0x15, 0x34, 0xc6, 0x8a, 0x21, 0x08, 0x78, 0x81, 0x51, 0x09, 0x0b, 0x12, 0xb3, 0x0a, 0xa2, - 0x08, 0x94, 0xf3, 0x78, 0xc1, 0x0a, 0xda, 0xb4, 0x39, 0x8d, 0xb5, 0x49, 0x50, 0xcf, 0x61, 0xa9, 0x1d, 0x48, 0xa5, - 0x42, 0xec, 0xf1, 0x99, 0x88, 0x3e, 0x69, 0x43, 0x03, 0x40, 0x81, 0x52, 0x72, 0xf1, 0x9b, 0xaf, 0xf7, 0x70, 0x53, - 0xd0, 0xff, 0x6c, 0x6b, 0xa2, 0x9d, 0xe5, 0xea, 0xd0, 0x9b, 0x2f, 0x68, 0x9c, 0xe7, 0x10, 0x8a, 0xcd, 0x20, 0x90, - 0x8b, 0xac, 0x82, 0x88, 0x16, 0x9b, 0xc0, 0x84, 0x84, 0x83, 0x36, 0xfd, 0x02, 0xa9, 0x0d, 0x31, 0xb9, 0xf2, 0xc4, - 0xc0, 0x6e, 0xab, 0x04, 0x01, 0x47, 0x7a, 0x9e, 0x7d, 0x6e, 0x62, 0xac, 0x69, 0x6a, 0x66, 0xe2, 0x6d, 0x28, 0x44, - 0x83, 0x16, 0x44, 0x33, 0x78, 0xff, 0x5c, 0x71, 0xbc, 0xea, 0xc0, 0x0f, 0x78, 0xe7, 0xe2, 0xcc, 0xab, 0x99, 0x47, - 0xe4, 0xd4, 0xe7, 0x39, 0xa2, 0x5f, 0xf2, 0xb0, 0x1a, 0xe9, 0x64, 0x8c, 0x95, 0xc4, 0x41, 0x6f, 0x83, 0x05, 0x73, - 0x42, 0x57, 0x3c, 0xb4, 0x7c, 0xfc, 0x0b, 0x64, 0x32, 0x4a, 0x6a, 0xac, 0xe8, 0x4a, 0x8b, 0x11, 0xe7, 0x35, 0xcc, - 0xd2, 0x64, 0x45, 0x17, 0x0b, 0x4d, 0x9a, 0x85, 0x32, 0x0d, 0xf0, 0x09, 0xb4, 0x18, 0xb9, 0x87, 0x9a, 0x36, 0x10, - 0x1a, 0xf6, 0x87, 0x80, 0x8f, 0xdc, 0x43, 0x87, 0xff, 0x9f, 0x67, 0x17, 0x88, 0xb4, 0x77, 0x69, 0x22, 0xe3, 0x91, - 0xba, 0x81, 0x83, 0x62, 0x7c, 0xec, 0x9b, 0x89, 0x5f, 0x39, 0xa3, 0xf7, 0x49, 0xe5, 0x3b, 0x7c, 0xb0, 0xfc, 0xf1, - 0xa6, 0x66, 0x56, 0x46, 0xb0, 0x1e, 0x76, 0x3b, 0x5c, 0x10, 0x6d, 0x17, 0x40, 0xea, 0x19, 0xaf, 0x16, 0xbe, 0xf1, - 0x6a, 0x7c, 0x87, 0xf1, 0xaa, 0xb3, 0xfa, 0x0a, 0x73, 0xb2, 0x45, 0x7d, 0x96, 0x92, 0xe7, 0xe7, 0x28, 0x13, 0x6c, - 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, 0x0e, 0x23, 0x81, 0xaa, - 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, 0x03, 0xa1, 0xa1, 0xb1, - 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xdd, 0xae, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, 0xac, 0x46, 0x13, 0xe0, - 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, 0x49, 0x66, 0x65, 0x34, - 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, 0xba, 0xcc, 0x92, 0xcc, - 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, 0x90, 0x1f, 0x40, 0x19, - 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, 0x66, 0x57, 0xbc, 0xac, - 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0xec, 0x2e, 0xb7, 0x3d, 0x2a, 0xcc, 0xab, 0x37, 0xcf, 0x7f, 0x3c, 0x6d, 0xbc, - 0xda, 0x47, 0x1c, 0x0d, 0xc1, 0xb6, 0x62, 0x8c, 0xd1, 0x5b, 0x7c, 0x1a, 0x4c, 0x94, 0x6b, 0x04, 0x7a, 0x97, 0x82, - 0x7e, 0xfb, 0x6b, 0x3d, 0x01, 0xaf, 0xb8, 0x5e, 0x7e, 0xc9, 0x27, 0xc0, 0x12, 0x15, 0x7a, 0x56, 0x98, 0x9b, 0x95, - 0xd9, 0x9d, 0xdd, 0x8a, 0xcc, 0xb4, 0x2b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, 0x16, 0x2e, 0x5d, 0xd3, 0xed, 0x60, - 0x57, 0x4b, 0xcf, 0x12, 0x79, 0xb7, 0x2b, 0xa1, 0x43, 0x76, 0xc0, 0xbd, 0x97, 0xf1, 0x2d, 0xbc, 0x2c, 0xbd, 0x6e, - 0x36, 0x83, 0x27, 0x80, 0x99, 0x70, 0xe1, 0x2c, 0x8b, 0x63, 0x26, 0x92, 0x50, 0xc5, 0xe6, 0x6a, 0x88, 0xbc, 0x15, - 0xa1, 0x35, 0xfb, 0x2b, 0x14, 0x23, 0xb0, 0x3b, 0xf9, 0xf0, 0x29, 0x5b, 0xcd, 0xd6, 0x80, 0x9a, 0x7f, 0x95, 0x09, - 0xa0, 0xb9, 0x76, 0x2d, 0xd8, 0xa6, 0xd0, 0xe6, 0xba, 0x7e, 0x1a, 0xaf, 0xe2, 0x04, 0x54, 0x37, 0xe0, 0x2d, 0x72, - 0xad, 0x45, 0x57, 0x06, 0x5d, 0x94, 0xde, 0x53, 0x8e, 0x25, 0x85, 0x8e, 0xbe, 0xf7, 0x84, 0x3a, 0xf7, 0x0c, 0xe0, - 0x92, 0x46, 0xcd, 0x53, 0x2d, 0x65, 0x2c, 0x00, 0x16, 0x3a, 0x98, 0x29, 0xb2, 0x15, 0xdd, 0x18, 0x4c, 0x0a, 0x78, - 0x6b, 0x80, 0x3f, 0x44, 0x56, 0xa9, 0xbb, 0x62, 0x19, 0x96, 0x9e, 0xfd, 0x75, 0xbf, 0x1f, 0x7b, 0xf6, 0xd7, 0x2b, - 0x4d, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x8d, 0x01, 0x44, 0x4e, 0xf5, 0x40, 0x98, 0x88, 0x62, 0x4d, 0xdf, 0xbf, 0x53, - 0x93, 0x45, 0x81, 0xd0, 0xef, 0xd5, 0xeb, 0x49, 0x49, 0x40, 0xa7, 0x56, 0xb1, 0x93, 0x81, 0x36, 0xfb, 0x80, 0x80, - 0xa8, 0x7e, 0x46, 0x36, 0x5f, 0x28, 0xe7, 0x62, 0x15, 0x3e, 0x7c, 0x4c, 0x21, 0xa0, 0x70, 0x47, 0x8d, 0xce, 0xdb, - 0x10, 0x09, 0x94, 0x15, 0x8a, 0x58, 0xf3, 0x62, 0x2d, 0x09, 0x99, 0x8f, 0x17, 0x28, 0xb8, 0x72, 0xc0, 0xae, 0x9c, - 0x4d, 0x86, 0x65, 0xc4, 0x59, 0x78, 0xf7, 0x37, 0x93, 0x05, 0x41, 0xcd, 0x95, 0x1f, 0xc8, 0x71, 0x2f, 0x53, 0x63, - 0x4f, 0x35, 0x6a, 0x10, 0x4c, 0x46, 0x10, 0x18, 0x6e, 0xf8, 0x15, 0x1f, 0x1f, 0x2d, 0x08, 0xa8, 0xc8, 0xac, 0x59, - 0x88, 0x79, 0x71, 0xfc, 0x08, 0x50, 0x63, 0x46, 0x47, 0x4f, 0xa6, 0x9c, 0xc1, 0x21, 0x4a, 0xc7, 0x20, 0xa3, 0x15, - 0xf0, 0x5b, 0xa8, 0xdf, 0xad, 0x13, 0xdf, 0x87, 0x7e, 0x15, 0xf4, 0x22, 0x06, 0x86, 0x23, 0x9a, 0x1c, 0x86, 0x7c, - 0x30, 0x19, 0x80, 0xb6, 0xc4, 0xdb, 0x7d, 0x2d, 0xad, 0xb8, 0x39, 0x5d, 0x3a, 0xdd, 0x3f, 0x69, 0x13, 0x24, 0x91, - 0x4a, 0x56, 0x2a, 0x62, 0x00, 0xa1, 0x2c, 0xd5, 0x36, 0x59, 0x83, 0x65, 0x85, 0x59, 0xd2, 0xdc, 0xa0, 0x24, 0xee, - 0x6f, 0x06, 0x8e, 0x51, 0xb3, 0x4e, 0xc3, 0xb2, 0xe5, 0x46, 0x0d, 0xf0, 0x39, 0x09, 0x2b, 0xec, 0x0d, 0x67, 0x26, - 0xbd, 0x33, 0x1d, 0xae, 0x8e, 0x39, 0x7b, 0xcd, 0x11, 0x8c, 0x23, 0xc1, 0x1b, 0x0f, 0x5d, 0x32, 0x0d, 0x15, 0x99, - 0x32, 0x0e, 0xa6, 0x3d, 0xc0, 0xbd, 0xe7, 0x60, 0x1c, 0xc6, 0x06, 0x95, 0x25, 0xf5, 0xa9, 0x77, 0x17, 0x02, 0x41, - 0x5a, 0xeb, 0x65, 0x3e, 0xc3, 0xd3, 0x33, 0x42, 0xd9, 0x1f, 0x72, 0xf8, 0x02, 0xec, 0x28, 0xc8, 0xc9, 0x84, 0x3f, - 0x79, 0xb8, 0x1f, 0xa8, 0x8a, 0x0f, 0x82, 0x83, 0x58, 0xa4, 0x07, 0xc1, 0x40, 0xc0, 0xaf, 0x82, 0x1f, 0x54, 0x52, - 0x1e, 0x5c, 0xc4, 0xc5, 0x41, 0xbc, 0x8a, 0x8b, 0xea, 0xe0, 0x26, 0xab, 0x96, 0x07, 0xa6, 0x43, 0x00, 0xcd, 0x1b, - 0x0c, 0xe2, 0x41, 0x70, 0x10, 0x0c, 0x0a, 0x33, 0xb5, 0x2b, 0x56, 0x36, 0x8e, 0x33, 0x13, 0xa2, 0x2c, 0x68, 0x06, - 0x08, 0x6b, 0x9c, 0x06, 0xc0, 0xa7, 0xae, 0x59, 0x4a, 0x2f, 0x30, 0xdc, 0x80, 0x98, 0xae, 0xa1, 0x0f, 0xc0, 0x23, - 0xaf, 0x69, 0x0c, 0x4b, 0xe0, 0x62, 0x30, 0x20, 0x17, 0x10, 0xb9, 0x60, 0x4d, 0x6d, 0x10, 0x87, 0x70, 0xad, 0xec, - 0xb4, 0xf7, 0x81, 0x99, 0x76, 0x3b, 0x40, 0x54, 0x9e, 0x90, 0x7e, 0xdf, 0x7e, 0x43, 0xfd, 0x0b, 0xf6, 0x12, 0xec, - 0xaf, 0x8a, 0x2a, 0xcc, 0xa5, 0xd2, 0x7c, 0x5f, 0xb2, 0x93, 0x81, 0x8a, 0x38, 0xbc, 0xe7, 0x48, 0xd1, 0x46, 0xe5, - 0xb2, 0xec, 0xc9, 0xb2, 0xe1, 0x2b, 0x71, 0xc5, 0x9d, 0x1f, 0x57, 0x25, 0x65, 0x5e, 0x65, 0x2b, 0xc5, 0xfe, 0xcd, - 0xb8, 0xe6, 0xfe, 0xc0, 0xfa, 0xb3, 0xf9, 0x0a, 0xae, 0xad, 0xde, 0xbb, 0x26, 0xd7, 0x88, 0x9c, 0x25, 0x94, 0x4b, - 0x6a, 0x9b, 0x87, 0xb7, 0xf4, 0x7d, 0x7e, 0xf5, 0x6d, 0xa6, 0xd3, 0xf8, 0xac, 0xc2, 0xc2, 0x85, 0x68, 0x45, 0x70, - 0x68, 0xc8, 0x45, 0xf3, 0x08, 0x30, 0xd7, 0x3e, 0x5b, 0x41, 0x41, 0xea, 0xb3, 0x0a, 0xbd, 0x5b, 0x21, 0xe1, 0x85, - 0x66, 0x97, 0xee, 0x07, 0x52, 0xc6, 0xed, 0xa1, 0x25, 0x4c, 0x5a, 0x5e, 0x84, 0xf7, 0x5e, 0x73, 0x93, 0x7b, 0x16, - 0x62, 0xf4, 0x22, 0xcf, 0x4e, 0xc0, 0x58, 0x77, 0xc9, 0xce, 0x86, 0x27, 0x7e, 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, - 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x01, - 0x09, 0x29, 0x22, 0x91, 0xac, 0xd5, 0x49, 0xf2, 0x85, 0xee, 0x02, 0x30, 0xfa, 0xc5, 0x2c, 0x8d, 0x96, 0x77, 0x9a, - 0x59, 0x20, 0x79, 0x86, 0xbe, 0xeb, 0x60, 0x7b, 0x63, 0x1f, 0xa4, 0x9c, 0x1f, 0x8b, 0xe9, 0x60, 0xc0, 0x89, 0x86, - 0x1b, 0x2f, 0x95, 0xb8, 0x56, 0xb7, 0xb8, 0x63, 0x18, 0x4b, 0x7d, 0x5b, 0xc4, 0xe0, 0x80, 0x5d, 0xb4, 0xb2, 0xdb, - 0x07, 0xd8, 0x57, 0x8e, 0x77, 0xa9, 0xb2, 0x3b, 0x3d, 0x66, 0x9a, 0xcb, 0x56, 0x93, 0x4e, 0x2a, 0xee, 0x26, 0xf2, - 0x4d, 0xee, 0xa0, 0xcb, 0xe5, 0x58, 0xf3, 0x96, 0x03, 0x50, 0xd1, 0x8f, 0x14, 0xd5, 0xfd, 0x0a, 0x47, 0x98, 0x7b, - 0xeb, 0x36, 0x9f, 0x1c, 0x9a, 0x02, 0x87, 0xc8, 0x93, 0x36, 0x9a, 0x02, 0xba, 0x77, 0xf1, 0xb0, 0xab, 0xdf, 0x96, - 0xee, 0x02, 0x25, 0xda, 0xab, 0xb8, 0xe1, 0xc7, 0x44, 0x9d, 0xce, 0xb4, 0x21, 0xf4, 0xaf, 0x8c, 0xb8, 0xbf, 0x34, - 0xae, 0xe2, 0x4d, 0xef, 0xf2, 0x19, 0x87, 0x3a, 0xbb, 0x21, 0x14, 0x80, 0xab, 0xf6, 0x74, 0xea, 0xc6, 0x90, 0x5e, - 0x29, 0xd1, 0x6d, 0x70, 0xb0, 0x3b, 0x7d, 0xc6, 0x51, 0xf4, 0x63, 0xd4, 0xc8, 0x37, 0x91, 0x78, 0x28, 0x07, 0xf1, - 0xc3, 0x82, 0x2e, 0x23, 0xf1, 0xb0, 0x18, 0xc4, 0x0f, 0x65, 0x5d, 0xef, 0x9f, 0x2b, 0x77, 0xf7, 0x11, 0x79, 0xd6, - 0xbd, 0xbd, 0x54, 0xc2, 0xc6, 0xc0, 0xb3, 0x6b, 0x01, 0xe1, 0x14, 0x3c, 0x91, 0xad, 0xa5, 0x0f, 0x9d, 0xdb, 0x7d, - 0x6c, 0x99, 0x24, 0x08, 0x7a, 0xde, 0x66, 0x93, 0x28, 0x76, 0xb6, 0x79, 0xf4, 0xe1, 0x14, 0x48, 0xe8, 0x76, 0xdb, - 0xac, 0xab, 0x35, 0xa0, 0x98, 0x86, 0x63, 0x7e, 0x58, 0x8c, 0x6e, 0x7c, 0x77, 0xfd, 0xc3, 0x62, 0xb4, 0x24, 0xc3, - 0x89, 0x99, 0xfc, 0xf8, 0x64, 0x3c, 0x8b, 0xa3, 0x49, 0xdd, 0x71, 0x5a, 0x68, 0xfc, 0x53, 0xef, 0x16, 0x8a, 0xc0, - 0xa9, 0x18, 0xc1, 0x91, 0x53, 0xa1, 0x9c, 0x94, 0x1a, 0x18, 0xfe, 0x07, 0xd5, 0x9e, 0x36, 0xed, 0x75, 0x5c, 0x25, - 0xcb, 0x4c, 0x5c, 0xea, 0xf0, 0xe1, 0x3a, 0xba, 0xb8, 0x0d, 0x68, 0xe7, 0x5d, 0xa6, 0x1d, 0xbf, 0x4e, 0x1a, 0xf4, - 0xc4, 0xd5, 0xcc, 0x80, 0x5b, 0xf7, 0x23, 0x34, 0x43, 0x60, 0xb4, 0x3c, 0x7f, 0x87, 0x98, 0xdb, 0xbf, 0x2a, 0x9b, - 0x5f, 0x45, 0xfb, 0x1c, 0x19, 0x29, 0xdb, 0x64, 0xa4, 0x02, 0x23, 0x4c, 0x29, 0x92, 0xb8, 0x0a, 0x21, 0x90, 0xfd, - 0xd7, 0x14, 0xd7, 0x62, 0xe9, 0xbd, 0x06, 0x61, 0x82, 0xed, 0x82, 0xf6, 0xab, 0xdb, 0xbb, 0xad, 0xb4, 0xd8, 0x23, - 0xf5, 0x7d, 0xee, 0x6c, 0x57, 0x34, 0xf9, 0xfb, 0xba, 0x01, 0x6d, 0x00, 0x51, 0xde, 0xd5, 0x47, 0x25, 0x70, 0x32, - 0xe2, 0x86, 0x12, 0xa3, 0x17, 0x74, 0x75, 0x22, 0xf7, 0xec, 0xd4, 0xbc, 0xa9, 0x98, 0xa9, 0xb8, 0xf2, 0xcd, 0x9e, - 0xf9, 0x0f, 0x86, 0x82, 0x4a, 0x30, 0xf0, 0x36, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, 0x18, 0x9d, 0x16, 0x6c, 0x16, 0xd4, - 0x65, 0xdd, 0xb4, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb1, 0x2a, 0xd4, 0x48, 0x78, 0x22, 0x10, 0x30, 0x65, 0x57, 0x3c, - 0x32, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x4a, 0x54, 0xd3, 0x9b, 0xd0, 0x26, 0x13, 0xa7, 0x19, 0x44, - 0x30, 0x23, 0xb6, 0xfb, 0x2d, 0xa0, 0xcd, 0xad, 0x19, 0x6d, 0xeb, 0xda, 0x6a, 0xab, 0x90, 0x4b, 0x8a, 0x94, 0xe5, - 0xbf, 0x53, 0x53, 0x41, 0x49, 0x2d, 0x17, 0xbd, 0x49, 0xd3, 0x45, 0x8f, 0x67, 0x46, 0x12, 0xa8, 0xdc, 0x72, 0xc7, - 0xe8, 0x0f, 0x61, 0x81, 0x47, 0x4c, 0x9c, 0x58, 0x30, 0xb7, 0x3a, 0x61, 0xd9, 0x5c, 0x2c, 0x46, 0x2b, 0x09, 0x61, - 0x83, 0x8f, 0x59, 0x36, 0x2f, 0xf5, 0x43, 0xe8, 0x0b, 0x4b, 0x1f, 0x80, 0x5d, 0x6c, 0xb0, 0x92, 0x65, 0x00, 0xbe, - 0x17, 0x74, 0xbb, 0x92, 0x65, 0x24, 0x55, 0xf7, 0xe3, 0x1a, 0x4b, 0x50, 0x69, 0x85, 0x4a, 0x4b, 0x6a, 0x2c, 0x08, - 0x7c, 0x55, 0x75, 0xf9, 0x90, 0xec, 0x2a, 0x50, 0x4f, 0x1d, 0x35, 0xe0, 0x14, 0xa8, 0x2a, 0xb0, 0x20, 0x09, 0x2a, - 0x43, 0x57, 0x05, 0xa6, 0x15, 0x98, 0x66, 0xaa, 0x70, 0x51, 0x66, 0x87, 0xd2, 0xac, 0x97, 0x7c, 0x16, 0x0f, 0xc2, - 0x64, 0x18, 0x93, 0x87, 0x08, 0xb5, 0x7f, 0x98, 0x47, 0xb1, 0x96, 0x4b, 0x5e, 0x3a, 0xbf, 0xf8, 0x9b, 0x2f, 0xd8, - 0xeb, 0x9e, 0x61, 0xb0, 0x00, 0x67, 0x69, 0x7b, 0x95, 0x89, 0x77, 0xb2, 0x15, 0x1c, 0x07, 0xb3, 0x28, 0x87, 0x55, - 0x4f, 0x8e, 0x68, 0x2e, 0x72, 0xed, 0x5d, 0x84, 0xc8, 0x41, 0x66, 0x8f, 0x01, 0x76, 0x23, 0x7c, 0x1d, 0x5a, 0x9b, - 0x5b, 0x5d, 0x21, 0xfe, 0x46, 0x89, 0xc4, 0x4f, 0x52, 0x7e, 0x5a, 0xaf, 0x54, 0xae, 0xca, 0xe0, 0xb1, 0xea, 0x66, - 0xf0, 0x4c, 0xfb, 0x1e, 0x6b, 0xff, 0xd6, 0x76, 0x73, 0xbc, 0xf7, 0xe0, 0x41, 0xeb, 0x7f, 0xeb, 0x49, 0x08, 0xed, - 0x95, 0x93, 0xd4, 0x1d, 0x35, 0x7a, 0x66, 0xb2, 0x46, 0x54, 0xc2, 0xd4, 0xee, 0x54, 0x8e, 0x81, 0x9a, 0x0e, 0xe0, - 0x5a, 0xa2, 0x26, 0xe8, 0x49, 0xc1, 0xc6, 0x70, 0xc4, 0x59, 0x1c, 0xb4, 0xe3, 0x18, 0xc5, 0xcb, 0xb9, 0x12, 0x2f, - 0xe7, 0x27, 0x8c, 0x03, 0xb4, 0x16, 0x20, 0xd5, 0x6b, 0xd8, 0xcf, 0x5c, 0xc1, 0x02, 0x9b, 0x3b, 0xdf, 0x91, 0x05, - 0x32, 0xc4, 0xc9, 0xe6, 0x38, 0xd9, 0xe3, 0x5a, 0xcf, 0xbd, 0xc0, 0xc7, 0x49, 0xbd, 0xf0, 0xea, 0x2a, 0xdb, 0x75, - 0x2d, 0x59, 0x39, 0x2f, 0x06, 0x13, 0x08, 0xca, 0x52, 0xce, 0x8b, 0xe1, 0x64, 0x41, 0x73, 0xf8, 0xb1, 0x68, 0xa0, - 0x43, 0x2c, 0x07, 0x09, 0x5c, 0x3a, 0x7b, 0x0c, 0x78, 0x43, 0xa9, 0xc5, 0xdd, 0x58, 0x47, 0x8e, 0x75, 0x14, 0x87, - 0x61, 0x0c, 0xb8, 0xb2, 0x4e, 0xe0, 0x7d, 0xf7, 0xf5, 0xb1, 0x09, 0xc8, 0xaa, 0x5d, 0xe1, 0xd5, 0x28, 0x77, 0x5d, - 0x69, 0xf4, 0x25, 0xa5, 0x27, 0xbc, 0xe0, 0xa9, 0x64, 0xb7, 0xeb, 0x19, 0x38, 0x5b, 0xe2, 0x21, 0xf1, 0x8e, 0x11, - 0xbd, 0x98, 0x36, 0x32, 0x73, 0x02, 0x67, 0xb6, 0xbb, 0x6c, 0x63, 0x7e, 0xec, 0x00, 0x07, 0x8b, 0x20, 0x24, 0x6e, - 0x08, 0xc3, 0xc4, 0x4e, 0xca, 0xa1, 0x16, 0xc2, 0x75, 0x2d, 0xbc, 0x8e, 0xd3, 0x32, 0x06, 0x17, 0x69, 0x6d, 0x9b, - 0x78, 0x07, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, 0x0c, 0x40, 0xd3, - 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, 0xfe, 0xbd, 0xe6, - 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, 0x13, 0xb7, 0xdb, - 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, 0x18, 0x30, 0x97, - 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, 0xcc, 0x03, 0x99, - 0x02, 0xe2, 0xf9, 0x87, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd3, 0xf1, 0x8d, 0xe8, 0x6b, 0xfb, 0xe2, 0x92, - 0x57, 0x6f, 0x6f, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, 0x1d, 0x14, 0x59, - 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xad, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, 0x09, 0x53, 0x80, - 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, 0x31, 0x80, 0xc2, - 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa4, 0x3a, 0x03, 0x2d, 0xeb, 0x69, 0x01, 0xa2, - 0x3a, 0x88, 0xb6, 0x0a, 0x51, 0xa1, 0x53, 0x5a, 0x66, 0x34, 0x15, 0x74, 0x2d, 0x68, 0x92, 0xd1, 0x0b, 0xae, 0x44, - 0xc5, 0x2b, 0xc1, 0x14, 0x6d, 0x37, 0x84, 0xfd, 0x1f, 0x0d, 0xba, 0xde, 0x8a, 0xb5, 0x86, 0x76, 0x27, 0xc8, 0x08, - 0xcd, 0x17, 0x3a, 0x08, 0x19, 0x2a, 0x27, 0xa1, 0x6b, 0x95, 0xc6, 0x2b, 0x70, 0xc9, 0x34, 0x1b, 0x2d, 0xe3, 0x32, - 0x0c, 0xec, 0x57, 0x81, 0xc5, 0xe4, 0xc0, 0xa4, 0x0f, 0xeb, 0xf3, 0xa7, 0xf2, 0x6a, 0x25, 0x05, 0x17, 0x95, 0x82, - 0xe8, 0x37, 0xb8, 0xef, 0x26, 0xae, 0x3a, 0x6b, 0xd6, 0x4a, 0xef, 0xfb, 0xd6, 0x67, 0x6d, 0xdc, 0x17, 0x06, 0xc7, - 0x60, 0xef, 0x23, 0x62, 0x20, 0x0d, 0x2a, 0xdd, 0xe2, 0xd0, 0x04, 0xe8, 0xd2, 0x21, 0x85, 0x2c, 0x99, 0xca, 0x54, - 0x09, 0x2a, 0xbe, 0xf1, 0x7b, 0x29, 0xab, 0xd1, 0x5f, 0x6b, 0x5e, 0x6c, 0x3e, 0xf0, 0x9c, 0xe3, 0x18, 0x05, 0x49, - 0x2c, 0xae, 0xe3, 0x32, 0x20, 0xbe, 0xe5, 0x55, 0x70, 0x94, 0x9a, 0xb0, 0x31, 0x7b, 0x55, 0xa3, 0xd6, 0xab, 0x40, - 0x5f, 0x19, 0xe5, 0x1b, 0x83, 0xa1, 0x89, 0xa8, 0x82, 0xbe, 0xd7, 0xea, 0x9e, 0x56, 0x37, 0x2c, 0x20, 0xfe, 0x5c, - 0xe9, 0x85, 0x5a, 0xaf, 0x9b, 0x31, 0x37, 0x4c, 0x84, 0xa0, 0xd1, 0xa3, 0x7a, 0xe1, 0xf0, 0xf3, 0xb7, 0xca, 0x92, - 0x08, 0x5e, 0x6c, 0xd3, 0x75, 0x61, 0x62, 0x69, 0x50, 0x1d, 0x30, 0x37, 0xda, 0xe6, 0xfc, 0x12, 0x44, 0x7f, 0xce, - 0x8a, 0x68, 0x52, 0xd7, 0x54, 0x21, 0x18, 0x46, 0xdb, 0xdb, 0x46, 0x3a, 0xdd, 0x80, 0x97, 0x9b, 0xb1, 0x46, 0xd2, - 0x9e, 0x8e, 0x35, 0x2d, 0x78, 0xb9, 0x92, 0xa2, 0x84, 0xe8, 0xce, 0xbd, 0x31, 0xbd, 0x8a, 0x33, 0x51, 0xc5, 0x99, - 0x38, 0x2d, 0x57, 0x3c, 0xa9, 0xde, 0x43, 0x85, 0xda, 0x18, 0x07, 0x5b, 0xaf, 0x46, 0x5d, 0x85, 0x43, 0x7e, 0x75, - 0xf1, 0xfc, 0x76, 0x15, 0x8b, 0x14, 0x46, 0xbd, 0xbe, 0xeb, 0x45, 0x73, 0x3a, 0x56, 0x71, 0xc1, 0x85, 0x89, 0x5a, - 0x4c, 0x2b, 0x16, 0x70, 0x9d, 0x31, 0xa0, 0x5c, 0xc5, 0xee, 0xcc, 0x54, 0x2c, 0xc3, 0xb8, 0x2c, 0x7f, 0xca, 0x4a, - 0xbc, 0x03, 0x40, 0x6b, 0xe0, 0xb4, 0x98, 0x19, 0x10, 0x90, 0x4d, 0x6e, 0x70, 0x11, 0x58, 0x70, 0xf4, 0x78, 0xbc, - 0xba, 0x0d, 0xa8, 0xf7, 0x46, 0xaa, 0xeb, 0x21, 0x0b, 0xc6, 0xa3, 0x27, 0x81, 0x43, 0x0e, 0xf1, 0x3f, 0x7a, 0x7c, - 0x74, 0xf7, 0x37, 0x93, 0x80, 0xd4, 0x53, 0x50, 0x55, 0x18, 0x85, 0x28, 0x4c, 0xfb, 0xeb, 0xb5, 0xba, 0xe5, 0xbe, - 0x3d, 0x2f, 0x79, 0x71, 0x0d, 0xfb, 0x92, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, 0xab, 0xaa, 0xc8, - 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, 0x58, 0xd4, 0xa4, - 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, 0x4a, 0x8c, 0x35, - 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, 0xb7, 0x53, 0xd5, - 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xe6, 0x60, 0x78, 0x00, 0xc9, - 0x64, 0xfa, 0x79, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, 0x3d, 0x1f, 0xfe, - 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, 0xef, 0x50, 0xad, - 0xef, 0xd3, 0xa2, 0x88, 0x37, 0x35, 0x59, 0xd0, 0x95, 0x70, 0xde, 0x35, 0xd4, 0x23, 0x0b, 0xf4, 0x88, 0x4c, 0x57, - 0x82, 0xc1, 0x37, 0xef, 0xab, 0x30, 0xe0, 0xe5, 0x6a, 0xc8, 0x45, 0x95, 0x55, 0x9b, 0x21, 0xe6, 0x09, 0xf0, 0x53, - 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x99, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, 0xe2, 0x63, 0xaa, - 0xba, 0x31, 0xf9, 0x8e, 0xea, 0xbe, 0x4d, 0xbe, 0x03, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, 0x8c, 0xc6, 0xf4, - 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf3, 0x76, 0xf6, 0xd1, 0x68, 0xf4, 0xa0, - 0xa0, 0xa3, 0xd1, 0xe8, 0x53, 0x56, 0x13, 0x7a, 0x29, 0x3a, 0xde, 0xbf, 0xe7, 0xf4, 0x5c, 0xa6, 0x9b, 0x28, 0x08, - 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0x4f, 0xd3, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, 0x6d, 0x44, 0x48, - 0x26, 0x42, 0xdf, 0xee, 0xf5, 0x6c, 0x34, 0x1a, 0x3d, 0x4d, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x00, 0xcd, 0x29, 0x9c, - 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x35, 0x9c, 0xcd, 0xc7, 0xc3, 0xef, 0x47, 0x8b, 0x87, 0x87, - 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, 0xb1, 0xf5, 0x2d, - 0xfa, 0xe6, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x12, 0x80, 0x17, 0x67, 0x23, - 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, 0xc7, 0xd3, 0xf2, - 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x13, 0x44, 0x25, 0x3b, 0x7a, 0x32, 0x55, 0x70, 0xc7, - 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x7e, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, 0x72, 0x19, 0x83, - 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, 0x4c, 0x1e, 0x96, - 0x54, 0x7e, 0x33, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0xaa, 0x57, 0x6f, 0x53, 0x76, - 0x38, 0xff, 0x3f, 0x25, 0x5d, 0x0c, 0x0e, 0xdd, 0xd0, 0xbc, 0xd3, 0xee, 0xbc, 0x15, 0x32, 0x8e, 0x55, 0xf8, 0x36, - 0x25, 0xd6, 0x18, 0x97, 0xb3, 0x93, 0xad, 0xe9, 0xce, 0xa8, 0x2a, 0xb2, 0xab, 0x90, 0xe8, 0x5e, 0x39, 0x90, 0xd0, - 0x20, 0xca, 0x46, 0xb8, 0x7e, 0xc0, 0x7a, 0xc6, 0xeb, 0xe4, 0x35, 0x2f, 0xaa, 0x2c, 0x51, 0xef, 0xaf, 0x1b, 0xef, - 0xeb, 0xda, 0x04, 0x54, 0x7d, 0x57, 0x30, 0x98, 0xe7, 0xb7, 0x05, 0x80, 0x98, 0x22, 0x0d, 0xf0, 0x09, 0x66, 0x10, - 0xd4, 0xae, 0x99, 0x57, 0x8d, 0xe0, 0x1b, 0xf0, 0xd5, 0xbb, 0x02, 0x30, 0x48, 0x42, 0x90, 0x22, 0x43, 0x68, 0x20, - 0x10, 0x68, 0x18, 0x72, 0x81, 0xc1, 0x4f, 0xbc, 0x38, 0x92, 0xca, 0x29, 0x91, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0a, - 0x40, 0x62, 0x3c, 0x0e, 0xe1, 0x85, 0xfa, 0xe5, 0xde, 0xa8, 0x3d, 0xc2, 0x1e, 0xa4, 0x21, 0x04, 0x1b, 0xc2, 0x87, - 0x00, 0x96, 0x14, 0xa1, 0xef, 0x90, 0xcb, 0x08, 0x83, 0x8b, 0x3c, 0x5b, 0xe9, 0xa4, 0x6a, 0xd4, 0xd1, 0x7c, 0x28, - 0xb5, 0x23, 0x39, 0xa0, 0x5e, 0x7a, 0x8c, 0xe9, 0x85, 0x4a, 0x57, 0x45, 0x39, 0xa3, 0x9c, 0x53, 0x3d, 0x31, 0x2e, - 0x6c, 0x21, 0x87, 0x48, 0x38, 0xef, 0x0a, 0x15, 0x0a, 0x87, 0x2f, 0x00, 0x0c, 0x0c, 0xa4, 0x1d, 0xfb, 0xf1, 0x6e, - 0x54, 0xf6, 0x33, 0xce, 0x0e, 0xff, 0x6b, 0x1e, 0x0f, 0x3f, 0x8f, 0x87, 0xdf, 0x2f, 0x06, 0xe1, 0xd0, 0xfe, 0x24, - 0x0f, 0x1f, 0x1c, 0xd2, 0x17, 0xdc, 0x72, 0x69, 0xb0, 0xf0, 0x1b, 0xc1, 0x7e, 0xd4, 0x4a, 0x08, 0xa2, 0x00, 0x6f, - 0x58, 0x6e, 0x35, 0x4e, 0x00, 0xf0, 0x30, 0xf8, 0xdf, 0x01, 0x1a, 0x4d, 0xb9, 0x8b, 0x17, 0xe8, 0x4b, 0xd4, 0xef, - 0x93, 0x47, 0x0d, 0x83, 0x41, 0x10, 0xd7, 0xa8, 0x98, 0x30, 0x44, 0x97, 0x31, 0x51, 0x30, 0xc8, 0x36, 0xfb, 0x6e, - 0xd7, 0x6b, 0x4b, 0xc2, 0xf0, 0x4b, 0x3f, 0xd3, 0xc4, 0xcc, 0x3b, 0xdc, 0xd8, 0x56, 0x72, 0x15, 0x22, 0x56, 0xa0, - 0xfe, 0x95, 0x33, 0x88, 0xbd, 0x79, 0x9d, 0x81, 0x4f, 0x87, 0xfd, 0x62, 0x3c, 0x03, 0x36, 0x0a, 0xee, 0x7c, 0x05, - 0xbf, 0xc8, 0xc0, 0xcd, 0x5b, 0xc4, 0x28, 0x70, 0xb0, 0x4b, 0xa2, 0xdf, 0xef, 0xe5, 0x59, 0x98, 0x6b, 0xdc, 0xe9, - 0xbc, 0x36, 0x6a, 0x08, 0xd4, 0x91, 0x83, 0xfa, 0x41, 0x0f, 0xc1, 0x50, 0x0d, 0x41, 0xd1, 0xd1, 0x16, 0x57, 0xaf, - 0xad, 0xa7, 0x30, 0xbd, 0x55, 0xf5, 0x15, 0xa3, 0x3f, 0x65, 0x26, 0xb0, 0x90, 0x76, 0xcd, 0xb1, 0xae, 0x39, 0x46, - 0xda, 0xd3, 0xef, 0x8b, 0x06, 0xf9, 0xe9, 0x2c, 0x3c, 0x08, 0x54, 0xa9, 0x72, 0xaf, 0x2c, 0xca, 0x6d, 0x69, 0xde, - 0x18, 0xd6, 0x34, 0xcf, 0x6c, 0x9c, 0x9b, 0x59, 0xaf, 0x17, 0x86, 0xe8, 0xe0, 0x89, 0xa5, 0x62, 0x6d, 0x10, 0xee, - 0xc8, 0x24, 0x8c, 0xae, 0x40, 0x76, 0x19, 0x9e, 0x71, 0x82, 0x7c, 0x2a, 0xb0, 0x0f, 0xaa, 0x5a, 0x2f, 0x27, 0x3c, - 0x36, 0xf2, 0x65, 0x23, 0x68, 0x90, 0x97, 0x14, 0xf5, 0x26, 0x6e, 0xc7, 0x3e, 0x6f, 0x21, 0x57, 0x6e, 0xeb, 0x69, - 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, 0xcc, 0x70, - 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, 0x13, 0xf9, - 0xe6, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, 0xf5, 0xa2, - 0x84, 0x0a, 0xd8, 0x6e, 0x97, 0x82, 0xe0, 0xdf, 0x4f, 0xd9, 0x0c, 0xff, 0x66, 0xfd, 0x7e, 0x2f, 0xc4, 0x5f, 0x1c, - 0x83, 0x19, 0xcd, 0xc5, 0x82, 0x7d, 0x02, 0x19, 0x13, 0x89, 0x30, 0x55, 0x19, 0x03, 0xb2, 0x0a, 0x2c, 0x02, 0xcd, - 0x07, 0x2a, 0x17, 0x66, 0xb2, 0x97, 0x39, 0xd7, 0x90, 0x57, 0xad, 0x71, 0xca, 0x46, 0x59, 0xa2, 0x5c, 0x39, 0xb2, - 0x51, 0x9c, 0x67, 0x71, 0xc9, 0xcb, 0xdd, 0x4e, 0x1f, 0x8e, 0x49, 0xc1, 0x81, 0x5d, 0x57, 0x54, 0xaa, 0x64, 0x1d, - 0xa9, 0x1e, 0x78, 0x69, 0x58, 0xe0, 0x3e, 0xe5, 0xf3, 0xc2, 0xd0, 0x88, 0x03, 0x10, 0x66, 0x30, 0x75, 0x4b, 0xef, - 0x85, 0x05, 0x34, 0xaf, 0x24, 0x64, 0x8b, 0xa9, 0x9e, 0x85, 0x6f, 0xcc, 0xc4, 0xbc, 0x58, 0x40, 0x58, 0x9d, 0x62, - 0xa1, 0x99, 0x4d, 0x9a, 0xb0, 0x18, 0x60, 0xf3, 0x62, 0x32, 0x85, 0xf8, 0xee, 0xaa, 0x9c, 0x78, 0x61, 0xee, 0xdb, - 0x89, 0x43, 0x0e, 0x81, 0x57, 0xb5, 0x41, 0x57, 0xb3, 0x0d, 0x47, 0x1d, 0x29, 0x27, 0x26, 0xbf, 0x9f, 0x2a, 0x08, - 0x71, 0x27, 0x8e, 0x84, 0xcb, 0x9b, 0xed, 0xc2, 0xb3, 0x0e, 0x04, 0x1d, 0x35, 0x38, 0xe5, 0x17, 0x06, 0x47, 0x63, - 0x92, 0x6e, 0xbd, 0x13, 0xa4, 0x08, 0x63, 0xb2, 0x95, 0xec, 0x5c, 0x86, 0x62, 0x1e, 0x2f, 0x40, 0x79, 0x19, 0x2f, - 0xc0, 0xd2, 0xc8, 0x18, 0xa4, 0x82, 0xfc, 0x8e, 0x7b, 0xa1, 0xb0, 0x28, 0xae, 0x10, 0xe9, 0x59, 0xfd, 0x9e, 0x16, - 0xed, 0x50, 0x20, 0x28, 0xee, 0x50, 0xe6, 0xc9, 0x59, 0x8f, 0x05, 0x12, 0x1b, 0x02, 0xc6, 0x57, 0x3a, 0x4d, 0xb5, - 0xd6, 0xbd, 0x31, 0xf3, 0xc0, 0xa7, 0xd9, 0x48, 0xc8, 0xea, 0xec, 0x02, 0x44, 0x4a, 0x3e, 0x3a, 0x3e, 0xf2, 0x8b, - 0xb8, 0xb3, 0xcc, 0x5b, 0xdb, 0xa2, 0x92, 0x9d, 0x6c, 0x01, 0xb4, 0x50, 0x47, 0xcf, 0x52, 0x72, 0x9b, 0x92, 0xd4, - 0x6e, 0x53, 0xc0, 0x4a, 0xf2, 0x17, 0x30, 0x04, 0x5f, 0x3b, 0x10, 0x4e, 0xc7, 0x0a, 0xf1, 0x9a, 0xa6, 0x88, 0x34, - 0x19, 0x96, 0x14, 0xc7, 0xb6, 0x44, 0x14, 0x54, 0x5b, 0x96, 0x1d, 0x0c, 0x13, 0x25, 0xf8, 0x63, 0xea, 0x51, 0xa2, - 0x20, 0xa0, 0x7a, 0xc8, 0x41, 0x82, 0x6d, 0x1b, 0x08, 0x0f, 0xc8, 0x23, 0x7a, 0x63, 0xfd, 0x73, 0xd6, 0x79, 0x76, - 0xa1, 0x79, 0x2e, 0xd7, 0xbb, 0xc2, 0x8c, 0x11, 0x9e, 0x64, 0x26, 0x6c, 0x80, 0x77, 0x9e, 0x19, 0xb5, 0x4d, 0xcf, - 0xc3, 0x6b, 0x7b, 0x8e, 0x11, 0xfa, 0xee, 0x18, 0x74, 0x13, 0xcc, 0xab, 0xc3, 0x66, 0xbd, 0x52, 0x90, 0x1a, 0xa6, - 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0xa0, 0x7c, 0xb7, 0xeb, 0xe9, 0xb9, 0xba, 0x7b, 0xee, 0x76, 0xbb, 0x1e, 0x76, 0xeb, - 0x63, 0xda, 0x6d, 0x15, 0x5f, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, 0x6c, 0x52, 0x3a, 0x9a, 0x69, - 0xeb, 0x83, 0xf0, 0xc0, 0xe9, 0xa6, 0xd1, 0xa4, 0x9f, 0xb3, 0x50, 0xd2, 0x4b, 0xd1, 0xa8, 0xae, 0x76, 0x26, 0xa6, - 0xf7, 0xae, 0xff, 0xfb, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xd9, 0xa0, 0xa2, 0xd1, 0x16, 0x8e, 0x14, 0xa1, - 0x07, 0x24, 0xe1, 0xae, 0x96, 0xb5, 0xb8, 0xcd, 0x0f, 0xd9, 0xfd, 0xf4, 0xe9, 0xa7, 0xd4, 0xf7, 0x42, 0x70, 0xcb, - 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, 0xbd, 0xf2, - 0x03, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0xfd, 0x90, 0xcd, 0xb3, 0xc5, 0x6e, 0x17, 0xe2, 0xdf, 0xae, 0x16, - 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0xff, 0x2c, 0x1a, 0x4e, 0x13, 0xcf, - 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, 0xc0, 0x15, - 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x7b, 0x4b, 0xdb, 0xaa, 0x62, 0xe3, 0x2d, - 0x69, 0x8e, 0xeb, 0xc0, 0xf9, 0x3a, 0xd8, 0x80, 0x77, 0xba, 0xec, 0x6a, 0x81, 0xdc, 0x2f, 0xaf, 0x69, 0x6f, 0x5c, - 0x27, 0x30, 0x6b, 0xdb, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x17, 0x7a, 0x70, 0x95, 0x31, 0xd8, 0xdc, 0x58, 0x69, 0xd8, - 0x7d, 0xe3, 0xf9, 0x52, 0x40, 0x78, 0x3a, 0x9f, 0x1e, 0x7f, 0xc8, 0x3c, 0x7a, 0x0c, 0x44, 0xc7, 0x7c, 0x54, 0xba, - 0x8f, 0xec, 0xee, 0xf5, 0x03, 0x02, 0xce, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x55, 0xbd, 0xf2, 0x0a, 0xcb, - 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0x20, 0x70, 0x77, 0xd7, 0xb9, 0x10, 0xab, 0x0e, 0x2b, 0x73, 0x9a, 0x84, - 0x9d, 0x84, 0x68, 0xde, 0x1a, 0xcc, 0x82, 0xff, 0x1d, 0x0c, 0xca, 0x41, 0x10, 0x05, 0x51, 0x10, 0x90, 0x41, 0x01, - 0xbf, 0x10, 0x77, 0x8d, 0x60, 0xcc, 0x16, 0xe8, 0xf0, 0x5b, 0xce, 0x7c, 0x46, 0xe4, 0x95, 0x1f, 0xd6, 0xd3, 0x1b, - 0x80, 0x73, 0x29, 0x73, 0x1e, 0xa3, 0xcf, 0xc9, 0x5b, 0xce, 0x32, 0x42, 0xdf, 0x7a, 0xa7, 0xf2, 0x3b, 0xde, 0x08, - 0xf6, 0xb7, 0x3f, 0x6c, 0x2f, 0x40, 0x5e, 0xd1, 0x1b, 0xd3, 0xb7, 0x9c, 0x44, 0x59, 0xc3, 0x99, 0x9a, 0x43, 0xcf, - 0x2a, 0xcb, 0x5a, 0x51, 0x43, 0x6e, 0x50, 0xcc, 0x8d, 0x2c, 0x93, 0x93, 0x69, 0xab, 0x39, 0x15, 0xb8, 0xee, 0xec, - 0x7a, 0x01, 0xc9, 0xa1, 0xd0, 0x2c, 0x9d, 0x0d, 0xe7, 0xed, 0x0e, 0xc5, 0xd6, 0x29, 0xe4, 0x35, 0x44, 0x45, 0x83, - 0x74, 0x04, 0xd4, 0xd0, 0x8a, 0xcb, 0x0a, 0x5c, 0x98, 0x4d, 0x7b, 0xb8, 0x69, 0x8f, 0x69, 0xc6, 0x7b, 0x88, 0x99, - 0xc7, 0xb1, 0x65, 0x60, 0x47, 0xe2, 0x90, 0x9e, 0x9c, 0x2f, 0xd0, 0x3e, 0xbd, 0x75, 0xb5, 0x78, 0x84, 0xb5, 0xe7, - 0xad, 0x90, 0x10, 0x20, 0x3e, 0x4d, 0xa5, 0xbb, 0x5d, 0x10, 0xc0, 0x00, 0xf7, 0xfb, 0x3d, 0xe0, 0x5a, 0x0d, 0x3b, - 0x69, 0x6e, 0xcd, 0x96, 0xd8, 0x2b, 0x0a, 0x8f, 0x81, 0x39, 0x35, 0xff, 0x19, 0x04, 0x14, 0xcf, 0xdd, 0x10, 0xec, - 0x4d, 0xd9, 0xc9, 0xb6, 0xe8, 0xf7, 0x9f, 0x15, 0xf8, 0x80, 0x72, 0x61, 0x10, 0x73, 0xeb, 0x38, 0x1e, 0x86, 0x7d, - 0x52, 0x1f, 0xe2, 0x58, 0xe4, 0x59, 0xe8, 0x08, 0x4b, 0x65, 0x08, 0x0b, 0x57, 0x8c, 0x74, 0x10, 0x07, 0x35, 0xe9, - 0x1c, 0xac, 0xca, 0x05, 0x5f, 0xee, 0xf5, 0x3e, 0x03, 0x4c, 0x7a, 0xe6, 0x0d, 0xcb, 0x1b, 0x0f, 0x10, 0xad, 0xd7, - 0xc3, 0x85, 0xe2, 0x91, 0x89, 0x06, 0x1a, 0x27, 0xbe, 0xb4, 0xec, 0xfa, 0x4c, 0xcb, 0x4a, 0x46, 0xa3, 0x51, 0x55, - 0x2b, 0xc9, 0x87, 0xfd, 0xee, 0xcf, 0x16, 0x8a, 0xa7, 0x8c, 0x53, 0x9e, 0x82, 0xe5, 0xbb, 0xa1, 0x74, 0xf3, 0x05, - 0x5d, 0x71, 0x91, 0xaa, 0x9f, 0x1e, 0xfa, 0x66, 0x83, 0xb8, 0x66, 0x4d, 0x1d, 0x8e, 0x1d, 0x7e, 0x08, 0x80, 0x69, - 0x1f, 0x66, 0x2e, 0x5d, 0xc3, 0xf4, 0x82, 0x78, 0x36, 0x2e, 0x78, 0xe8, 0xf2, 0x00, 0xf6, 0xa1, 0x39, 0x24, 0xf1, - 0x53, 0xf8, 0x39, 0x33, 0x69, 0x1d, 0x9f, 0xe1, 0x6c, 0x46, 0xa5, 0xba, 0x11, 0xb4, 0x5f, 0x43, 0x22, 0x31, 0x48, - 0xcf, 0x0d, 0x86, 0xa2, 0x75, 0xb7, 0x81, 0x2b, 0xbf, 0xa5, 0x77, 0x3e, 0x0d, 0x02, 0xac, 0x6f, 0x2c, 0x06, 0x00, - 0x54, 0xf1, 0x07, 0xaa, 0xae, 0xcc, 0x15, 0xc5, 0x34, 0x4c, 0x25, 0xda, 0x3b, 0x8e, 0xeb, 0xa8, 0x71, 0x1d, 0x16, - 0xac, 0xb4, 0xb6, 0xcd, 0xee, 0x2d, 0x2d, 0x6c, 0x09, 0xa8, 0x16, 0xc4, 0x9d, 0x00, 0x3e, 0x34, 0x52, 0x1d, 0x08, - 0xb2, 0xfb, 0xe0, 0x00, 0x80, 0x37, 0x3c, 0x0f, 0x43, 0xf8, 0x03, 0x0b, 0x07, 0x96, 0xa5, 0xea, 0xe7, 0x72, 0x1a, - 0xc3, 0xb9, 0x9b, 0xab, 0x1d, 0x3e, 0x5b, 0x82, 0x62, 0x53, 0xcd, 0xa9, 0xb9, 0x7c, 0xe5, 0x8d, 0xfd, 0x1e, 0x13, - 0xcc, 0x63, 0x66, 0x1b, 0x7e, 0xeb, 0xe9, 0xb6, 0xbe, 0xc1, 0x6e, 0xe0, 0xa4, 0xbd, 0x70, 0xda, 0x8b, 0xed, 0xd2, - 0x40, 0xfe, 0xd5, 0x0d, 0x21, 0xc2, 0x47, 0x4d, 0x2c, 0xb2, 0x86, 0x4c, 0xc7, 0x62, 0x85, 0xa8, 0x36, 0x15, 0x4f, - 0xb5, 0x81, 0x40, 0x39, 0x55, 0x17, 0xa6, 0x56, 0x2a, 0x13, 0x06, 0x71, 0xa7, 0x84, 0x45, 0x95, 0x01, 0x86, 0x41, - 0x85, 0x14, 0xd7, 0xd6, 0xf3, 0x03, 0x2e, 0xdf, 0xcc, 0xb4, 0xd9, 0x7e, 0xfa, 0x22, 0x8f, 0x2f, 0x77, 0xbb, 0xb0, - 0xfb, 0x05, 0x98, 0xa3, 0x96, 0x4a, 0xc3, 0x08, 0x4e, 0x20, 0x4a, 0x72, 0x7d, 0x47, 0xce, 0x89, 0xe3, 0xe4, 0xda, - 0xcd, 0x9b, 0xed, 0xa5, 0x18, 0x81, 0x05, 0x9c, 0xb8, 0x48, 0x07, 0x5a, 0x2a, 0x49, 0xed, 0x29, 0xe0, 0x6d, 0x7a, - 0x47, 0xa9, 0xf0, 0x6a, 0xa1, 0x49, 0x48, 0xe5, 0xee, 0x25, 0x76, 0xd4, 0x80, 0x73, 0x52, 0x77, 0x10, 0x70, 0xda, - 0xd3, 0x8d, 0xb5, 0x8a, 0x64, 0x93, 0xe0, 0xbd, 0xd2, 0x43, 0x97, 0x68, 0xa7, 0x76, 0xb7, 0xad, 0xca, 0x16, 0x0a, - 0xe6, 0x41, 0xce, 0x12, 0x75, 0x3c, 0xa0, 0xd0, 0x45, 0x1d, 0x0d, 0xf9, 0x82, 0x14, 0x7a, 0xe5, 0x68, 0x55, 0xf3, - 0xbe, 0x64, 0xa0, 0x54, 0xab, 0x20, 0xaf, 0x89, 0x75, 0x5f, 0xcb, 0x1a, 0x8b, 0x2b, 0x27, 0xa4, 0xb0, 0x09, 0x5f, - 0x5b, 0x8a, 0x85, 0x59, 0xec, 0x8d, 0xa9, 0x2f, 0x5c, 0x22, 0xb4, 0xdd, 0x6d, 0x88, 0xd1, 0x06, 0xeb, 0x66, 0xb7, - 0xfb, 0x58, 0x84, 0xf3, 0x6c, 0x41, 0xe5, 0x28, 0x4b, 0x11, 0x52, 0xcd, 0x78, 0x2c, 0xdb, 0x2e, 0x98, 0x89, 0xa1, - 0xae, 0x3d, 0x5e, 0x92, 0x29, 0xd6, 0x26, 0xc9, 0x51, 0x7c, 0x2e, 0x0b, 0xb5, 0xd6, 0x08, 0xc1, 0xc3, 0xfd, 0xd7, - 0x14, 0x62, 0xda, 0x99, 0x75, 0xf7, 0x72, 0xef, 0x86, 0xf8, 0x2b, 0x04, 0x56, 0x28, 0xd9, 0xc7, 0x62, 0x74, 0x9e, - 0x41, 0x30, 0x58, 0x90, 0x35, 0x63, 0x94, 0x60, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, 0x4b, 0x14, 0x20, 0xce, - 0xb3, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x67, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x4a, 0xbc, 0xcf, 0xd3, 0x98, 0x1e, - 0xba, 0x35, 0x08, 0xae, 0xab, 0x7b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, 0x6a, 0x4e, 0xad, 0x2b, - 0x71, 0x3f, 0xab, 0xbc, 0xd1, 0x07, 0xf1, 0x95, 0x00, 0x1e, 0xd6, 0xdb, 0xde, 0xe7, 0xc2, 0x63, 0x6d, 0xf0, 0xed, - 0x6e, 0x77, 0x25, 0xe6, 0x41, 0xe0, 0x31, 0x9a, 0xbf, 0x28, 0x89, 0x79, 0x6f, 0x4c, 0x61, 0xc5, 0xfb, 0x2e, 0x7e, - 0xdd, 0xa4, 0xd6, 0x5a, 0xe4, 0xee, 0x71, 0x7d, 0xc0, 0xf3, 0x94, 0x38, 0xda, 0x51, 0x39, 0x95, 0xd6, 0x76, 0x00, - 0xbb, 0x22, 0x30, 0x50, 0xf6, 0x6f, 0x29, 0xdb, 0x82, 0x79, 0x22, 0x58, 0x1f, 0xa1, 0xdf, 0x96, 0xd2, 0x9f, 0x8c, - 0xd1, 0xb8, 0x47, 0xae, 0xab, 0xe8, 0x88, 0xeb, 0x68, 0xf6, 0x3c, 0xfa, 0xdb, 0x93, 0x31, 0x2d, 0x62, 0x91, 0xca, - 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x1d, 0x21, 0x34, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, 0x7f, 0x77, 0x3a, 0x51, - 0xda, 0x9a, 0x7c, 0x8c, 0x56, 0x55, 0xe4, 0xac, 0x0d, 0xed, 0xa6, 0x92, 0x43, 0xf2, 0xb0, 0x04, 0x7c, 0x4b, 0x6c, - 0x96, 0xb2, 0x41, 0x51, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, 0xb5, 0xdd, 0xc8, 0x7c, - 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x1e, 0x94, 0x9c, 0xad, 0xcf, 0xe4, 0x26, 0x40, 0x1c, 0x60, - 0xb8, 0x6e, 0xe7, 0x37, 0x0b, 0x42, 0x6f, 0xd9, 0xad, 0x15, 0xab, 0xde, 0x58, 0xb9, 0x88, 0x49, 0xbb, 0x19, 0x4c, - 0xe0, 0x32, 0xce, 0x0a, 0xfb, 0x42, 0xab, 0x1b, 0x8a, 0x8e, 0xb6, 0x49, 0xfb, 0x79, 0x47, 0xbb, 0xe1, 0x82, 0x6f, - 0xc5, 0x3a, 0xce, 0x2d, 0x6b, 0xaa, 0xd0, 0xb4, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, 0x5d, 0xd2, 0x14, 0x2f, - 0xd0, 0x74, 0x0d, 0x66, 0x3a, 0x17, 0xd0, 0xd7, 0x6e, 0x1f, 0xed, 0x0b, 0xd5, 0x13, 0xe1, 0x2d, 0x51, 0xf0, 0x6d, - 0x49, 0xc1, 0x4b, 0x2d, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0xa7, 0x51, 0x25, 0x7a, 0x27, 0xc5, 0x25, 0x68, 0x33, 0xe1, - 0x08, 0x34, 0x55, 0x23, 0xb6, 0x72, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, 0xdb, 0x15, 0x79, 0xcb, - 0x4e, 0xb6, 0xb7, 0x60, 0x26, 0x5c, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, 0x6c, 0xbb, 0x87, 0x1a, - 0x1b, 0xde, 0xd2, 0x1b, 0xb2, 0xbd, 0xe9, 0xf7, 0x43, 0xe8, 0x0f, 0xa1, 0xba, 0x43, 0xb7, 0x9d, 0x1d, 0xba, 0xf5, - 0xda, 0x79, 0x6e, 0xf5, 0x7c, 0xca, 0x3b, 0xe4, 0x23, 0x9a, 0xac, 0xd1, 0x55, 0xbc, 0x81, 0x4d, 0x1d, 0x55, 0x54, - 0x55, 0x1e, 0x25, 0x14, 0x54, 0xe2, 0x19, 0x2f, 0x3f, 0x70, 0x8c, 0xf5, 0xaa, 0x9f, 0xde, 0x69, 0x5e, 0x6d, 0x6d, - 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x0b, 0x89, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x83, 0xaa, 0xe2, 0xa8, 0x04, - 0x17, 0x71, 0x96, 0x83, 0x1a, 0xf7, 0xa2, 0xd9, 0xff, 0x50, 0xdb, 0x8e, 0x2d, 0x1b, 0x67, 0xee, 0x75, 0x48, 0xb6, - 0xff, 0x63, 0x03, 0xf5, 0x34, 0xc4, 0x08, 0xb1, 0x66, 0x41, 0x3f, 0x60, 0x10, 0x2b, 0x34, 0x28, 0xd7, 0x49, 0xc2, - 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x1d, 0x3b, 0x79, 0xd7, 0x63, 0xec, 0x96, 0xd0, 0x44, - 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x01, 0x0a, 0x59, 0xda, 0xfb, 0xdc, - 0x9c, 0xc8, 0xea, 0x1b, 0x6d, 0x84, 0x12, 0xa9, 0x44, 0x90, 0x8d, 0xdf, 0x20, 0x80, 0x31, 0x34, 0x3b, 0x20, 0xdb, - 0x25, 0x7b, 0x4d, 0xcf, 0xac, 0x49, 0x10, 0xbc, 0x7e, 0xa0, 0x12, 0xcd, 0x28, 0x2b, 0xa2, 0xab, 0x8c, 0x7e, 0x36, - 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, 0x6a, 0x6c, - 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, 0xbc, 0xa5, - 0xe0, 0x2f, 0xf6, 0x8e, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb1, 0x93, 0xed, 0xbb, - 0xf0, 0x75, 0x63, 0xe6, 0x36, 0x21, 0x5e, 0xaa, 0x92, 0x9e, 0x37, 0x4f, 0x66, 0x20, 0x56, 0x56, 0x6b, 0x7e, 0xcb, - 0xac, 0x3e, 0x01, 0x88, 0xd4, 0xad, 0x75, 0xb0, 0xc5, 0x8f, 0x4d, 0x97, 0xc9, 0x36, 0x65, 0x6d, 0x26, 0x4a, 0xa9, - 0x48, 0x9a, 0x8b, 0x00, 0xfa, 0x0d, 0xc3, 0x51, 0x03, 0xdc, 0xb9, 0x1e, 0x7b, 0x33, 0x34, 0xde, 0x98, 0x1a, 0x7a, - 0xb6, 0xd5, 0xcb, 0xdb, 0x51, 0x08, 0x33, 0x16, 0xd1, 0xad, 0x3b, 0x16, 0xc3, 0xd7, 0xf4, 0x01, 0x54, 0xf8, 0x34, - 0xc4, 0xe8, 0xc2, 0xa4, 0xae, 0xa7, 0x6b, 0xb5, 0x95, 0x6e, 0x08, 0xcd, 0x31, 0xaa, 0x91, 0xd7, 0xb6, 0x0d, 0x35, - 0x42, 0x7b, 0x42, 0x79, 0x78, 0x4b, 0x2b, 0x7a, 0x63, 0x59, 0x04, 0x27, 0x3f, 0xf6, 0xf2, 0x13, 0x7a, 0xee, 0x06, - 0xed, 0xa7, 0xa2, 0xad, 0x01, 0xfc, 0x0d, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, 0xe1, 0x4b, 0xb6, 0x20, - 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0xf6, 0x76, 0x87, 0x37, 0x29, 0x65, 0x88, 0xd6, 0x88, 0x0e, - 0xf2, 0xea, 0xdf, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, 0xdf, 0xcf, 0xf1, 0xb9, - 0xf6, 0x2c, 0xd3, 0x94, 0x05, 0x32, 0xa1, 0x4b, 0x57, 0x1a, 0x88, 0xca, 0xb7, 0x8e, 0x55, 0x00, 0x56, 0x24, 0x81, - 0x46, 0x24, 0x60, 0xb9, 0xe4, 0x89, 0xcb, 0xb6, 0x68, 0x50, 0x13, 0x95, 0x14, 0xb2, 0x44, 0x12, 0xf8, 0x61, 0x04, - 0x65, 0x8a, 0x62, 0x10, 0xf7, 0xea, 0xe5, 0x15, 0xd7, 0xd4, 0x80, 0x35, 0x45, 0x30, 0xc1, 0x3a, 0x9d, 0x02, 0xb1, - 0x15, 0xeb, 0x15, 0x78, 0xa2, 0xba, 0x8b, 0x24, 0xb2, 0x04, 0x68, 0xa0, 0xe7, 0x4b, 0xa7, 0xdd, 0xf2, 0xf6, 0x44, - 0x4b, 0x15, 0x9b, 0x7b, 0x2f, 0x16, 0x96, 0x7b, 0xac, 0xfc, 0xed, 0x40, 0x7b, 0x61, 0xb5, 0x27, 0xa2, 0x06, 0xab, - 0xc3, 0xb6, 0x9d, 0x1f, 0x4a, 0x43, 0x75, 0xaf, 0x1c, 0x13, 0x50, 0xd1, 0x55, 0x5c, 0x2d, 0xa3, 0x6c, 0x04, 0x7f, - 0x76, 0xbb, 0xe0, 0x30, 0x00, 0x8b, 0xd0, 0x5f, 0xde, 0xff, 0x14, 0x61, 0xb8, 0xaa, 0x5f, 0xde, 0xff, 0xb4, 0xdb, - 0x3d, 0x19, 0x8f, 0x0d, 0x57, 0xe0, 0xd4, 0x3a, 0xc0, 0x1f, 0x18, 0xb6, 0xc1, 0x2e, 0xd9, 0xdd, 0xee, 0x09, 0x70, - 0x10, 0x8a, 0x6d, 0x30, 0xbb, 0x58, 0x39, 0xb6, 0x29, 0x56, 0x43, 0xef, 0x48, 0xc0, 0xee, 0xdb, 0x63, 0x29, 0xf6, - 0xa9, 0x8f, 0x0a, 0x49, 0xa9, 0x17, 0xfd, 0xf3, 0x4e, 0x81, 0x25, 0x05, 0x53, 0xde, 0x60, 0x59, 0x55, 0xab, 0x32, - 0x3a, 0x3c, 0x8c, 0x57, 0xd9, 0xa8, 0xcc, 0x60, 0x9b, 0x97, 0xd7, 0x97, 0x00, 0x30, 0x11, 0xd0, 0xc6, 0xbb, 0xb5, - 0xc8, 0xcc, 0x8b, 0x05, 0x5d, 0x66, 0xb8, 0x26, 0xc1, 0xec, 0x20, 0xe7, 0x56, 0x37, 0x39, 0x25, 0xf6, 0x01, 0x6c, - 0x30, 0x77, 0xbb, 0x06, 0xbf, 0x70, 0x32, 0x7a, 0x32, 0x5b, 0x66, 0xda, 0xc0, 0x95, 0x9b, 0xfd, 0x4f, 0x22, 0x2f, - 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x3c, 0x03, 0x3e, 0x8f, 0xfd, 0x29, 0x42, 0x9f, 0xe5, 0x6a, 0xb4, 0x06, 0xd8, 0xd8, - 0xec, 0x62, 0x33, 0x4a, 0x39, 0x44, 0xe8, 0x08, 0xac, 0xba, 0x66, 0x99, 0x11, 0xdf, 0xa6, 0xe2, 0xb6, 0xa5, 0x0a, - 0xfb, 0x53, 0x78, 0xce, 0x3b, 0xdc, 0x38, 0x0e, 0xf5, 0x26, 0x51, 0xf8, 0x1c, 0x85, 0xa8, 0x1c, 0x8d, 0x0b, 0x9d, - 0x7c, 0x2d, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x95, 0x3a, 0x73, 0x19, 0x5f, 0xb8, 0xf7, 0xdc, 0x97, 0x99, - 0x5c, 0x4b, 0x00, 0x89, 0x52, 0xb5, 0xff, 0xfe, 0x05, 0xa9, 0xf1, 0xbf, 0x52, 0xad, 0x01, 0xe8, 0xfd, 0x0e, 0x35, - 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0xd1, 0x05, 0xac, 0x64, 0xfe, 0x27, 0xd4, 0xed, 0x08, 0xb6, 0x55, 0xf1, 0x84, - 0xa2, 0x8a, 0x16, 0x3c, 0x5d, 0x8b, 0x34, 0x16, 0xc9, 0x26, 0xe2, 0xf5, 0x14, 0x4b, 0x62, 0x36, 0x62, 0xd8, 0xef, - 0xcd, 0x2e, 0xbc, 0x2f, 0x1a, 0x26, 0xf1, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, 0x8c, 0x4c, 0xb9, 0x42, - 0x30, 0xb7, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3e, 0x7a, 0x4c, 0xe8, 0xb5, 0x9c, 0x96, 0x08, 0xd2, 0x27, 0x52, 0xeb, - 0xba, 0x8a, 0xfd, 0x9a, 0x42, 0x54, 0x0b, 0xc1, 0x20, 0x94, 0xa9, 0x69, 0x9f, 0xe2, 0xfb, 0x6c, 0xd9, 0x7f, 0x9a, - 0xb2, 0x25, 0xd9, 0x0a, 0xe8, 0x98, 0x74, 0xde, 0xaf, 0xde, 0x9e, 0x9d, 0x79, 0xbf, 0x41, 0x13, 0x0e, 0xaa, 0x1b, - 0x68, 0x57, 0x41, 0xa6, 0x31, 0x8a, 0xcd, 0x62, 0xac, 0xdd, 0x9a, 0x88, 0x20, 0x08, 0x77, 0x39, 0x0b, 0xdb, 0xed, - 0x84, 0x78, 0x1b, 0x48, 0xa0, 0xc0, 0xb5, 0x8d, 0x72, 0x12, 0x12, 0x75, 0x21, 0x33, 0xc7, 0x84, 0x64, 0x81, 0x5e, - 0x63, 0x47, 0x01, 0x3d, 0xe5, 0xf6, 0x29, 0xa0, 0x2f, 0x0a, 0x76, 0xca, 0x07, 0xc1, 0x10, 0xe3, 0xcd, 0x06, 0xf4, - 0x93, 0x54, 0x8f, 0xe0, 0x31, 0x0d, 0x2c, 0x17, 0x7d, 0x53, 0x30, 0x84, 0x59, 0xfa, 0x67, 0xca, 0x26, 0xdf, 0xfd, - 0xdd, 0xcd, 0xef, 0x99, 0x16, 0xb3, 0x83, 0x50, 0xdc, 0x5e, 0x4f, 0x80, 0xf8, 0x55, 0xfc, 0x0a, 0xac, 0xcd, 0xb5, - 0xc4, 0xdb, 0x93, 0x3c, 0x08, 0x5f, 0x8e, 0x6e, 0x3f, 0x29, 0xcd, 0x27, 0x10, 0xb4, 0xc7, 0x49, 0xca, 0xdd, 0x77, - 0x1f, 0xa4, 0xab, 0x08, 0x46, 0x0b, 0x10, 0xfc, 0xee, 0xac, 0x64, 0xd3, 0x14, 0xfe, 0x63, 0x9d, 0x2f, 0x30, 0x96, - 0x8a, 0xfc, 0x80, 0xd3, 0xdf, 0x04, 0x07, 0xf7, 0x6f, 0x65, 0xd6, 0x90, 0xe8, 0x4c, 0x7d, 0x04, 0xf4, 0x7f, 0xac, - 0xc7, 0xef, 0x14, 0x25, 0x7d, 0x49, 0x9c, 0x23, 0x7c, 0x13, 0x2f, 0xd1, 0x74, 0xb1, 0x37, 0xae, 0xe9, 0xe7, 0xc2, - 0xbc, 0xd0, 0x0a, 0x0e, 0xfb, 0xd6, 0x28, 0x3c, 0xf0, 0xcc, 0xfb, 0x55, 0x34, 0x04, 0xdd, 0x3f, 0xe2, 0xde, 0xf8, - 0x55, 0xb0, 0x0c, 0x6f, 0xca, 0x59, 0x66, 0xee, 0x70, 0x37, 0x99, 0x48, 0xe5, 0x0d, 0x63, 0xc1, 0x5a, 0x28, 0x73, - 0xde, 0x34, 0x98, 0x6d, 0xeb, 0x48, 0x25, 0xbb, 0xef, 0xff, 0x6c, 0x9c, 0xb0, 0xd9, 0x20, 0xf8, 0x50, 0xc9, 0x22, - 0xbe, 0xe4, 0xc1, 0x54, 0xab, 0x28, 0x32, 0xb0, 0x2b, 0x04, 0xa4, 0x1c, 0xa7, 0xbd, 0x83, 0x27, 0x4b, 0xcd, 0x4c, - 0xc8, 0x6f, 0xab, 0xb3, 0x80, 0xb7, 0x66, 0x34, 0x4f, 0x2b, 0xd8, 0x65, 0xbe, 0x92, 0xe2, 0x87, 0x96, 0x24, 0x1b, - 0xeb, 0x6f, 0xc8, 0xb0, 0xad, 0x7c, 0xe6, 0x0c, 0x30, 0x77, 0x3e, 0x49, 0x15, 0xf4, 0xaf, 0xc7, 0xd8, 0x8d, 0x44, - 0x22, 0x20, 0x9c, 0xc5, 0xc4, 0xad, 0x30, 0xe1, 0x30, 0x5d, 0xa0, 0xa0, 0x18, 0x03, 0x05, 0x7d, 0x90, 0x21, 0xa7, - 0xa7, 0x7c, 0x90, 0x34, 0x66, 0xeb, 0x07, 0x55, 0x22, 0xbd, 0x91, 0x84, 0x6e, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, - 0x82, 0x75, 0xba, 0x9b, 0xd3, 0xe1, 0x9b, 0x82, 0x0c, 0xff, 0x09, 0xde, 0x6e, 0xb1, 0xbd, 0x2c, 0x27, 0xb0, 0xb8, - 0x63, 0xaf, 0x78, 0x9a, 0xab, 0x16, 0x27, 0xc4, 0x23, 0x16, 0xb9, 0x4f, 0x2c, 0x60, 0x44, 0x0d, 0xa3, 0xf1, 0x8f, - 0x0f, 0x6f, 0xdf, 0x68, 0x0c, 0xab, 0xdc, 0xff, 0x00, 0x46, 0x54, 0x4b, 0xdb, 0xed, 0x80, 0x2f, 0x47, 0x68, 0xc0, - 0x9e, 0xba, 0xc1, 0xee, 0xf7, 0x4d, 0xda, 0x49, 0xe9, 0x65, 0x73, 0x62, 0xd0, 0x3d, 0xa5, 0xcd, 0x52, 0x19, 0x18, - 0x77, 0x15, 0x8e, 0xe6, 0xc4, 0x46, 0xac, 0xea, 0x7d, 0x18, 0x2e, 0x69, 0x6c, 0x65, 0xe5, 0x76, 0x37, 0xe1, 0xc8, - 0x26, 0xc0, 0xf5, 0x29, 0x68, 0xaf, 0xe6, 0x1c, 0xb4, 0xa0, 0x44, 0x81, 0x23, 0xda, 0xed, 0x42, 0x88, 0x48, 0x52, - 0x0c, 0x27, 0xb3, 0xb0, 0x18, 0x0e, 0xd5, 0xc0, 0x17, 0x84, 0x44, 0x9f, 0x8b, 0x79, 0xb6, 0x50, 0x08, 0x46, 0xfe, - 0x4e, 0xfa, 0xb5, 0x50, 0x9c, 0x72, 0xef, 0x57, 0x41, 0xb6, 0x3f, 0xa6, 0x18, 0x83, 0xd1, 0x69, 0x36, 0x33, 0x90, - 0xb0, 0x9e, 0x56, 0x44, 0xad, 0x23, 0x3b, 0x1b, 0xa0, 0x8a, 0x45, 0xd3, 0x60, 0x50, 0xb7, 0x78, 0x62, 0x3d, 0xa3, - 0xf7, 0xa0, 0x12, 0x44, 0xb5, 0x60, 0x37, 0x86, 0x6b, 0xed, 0xb3, 0x08, 0x25, 0xe5, 0xa4, 0xc9, 0xcc, 0x58, 0xd1, - 0x60, 0x01, 0x42, 0xd2, 0xb8, 0xac, 0x5e, 0xcb, 0x34, 0xbb, 0xc8, 0x00, 0x41, 0xc2, 0xf9, 0x13, 0xca, 0xc6, 0x9b, - 0xa7, 0x6a, 0x5e, 0xba, 0x12, 0x67, 0x16, 0xf6, 0xa4, 0xeb, 0x2d, 0x2d, 0x48, 0x54, 0x00, 0x8d, 0xf2, 0xb5, 0x3c, - 0x3f, 0xef, 0x59, 0x85, 0xec, 0x7f, 0x38, 0x55, 0xb6, 0x43, 0xfc, 0x84, 0x55, 0xc4, 0x3b, 0xad, 0x2b, 0x25, 0xd2, - 0xe8, 0x68, 0x1b, 0x10, 0xc3, 0x96, 0x7d, 0x8b, 0x1a, 0x3e, 0x08, 0xbb, 0xe8, 0x24, 0x3f, 0xe8, 0x29, 0x1e, 0x5b, - 0x03, 0x49, 0x5f, 0x8b, 0xe0, 0x6b, 0x74, 0xa4, 0x13, 0x65, 0x1a, 0x89, 0x29, 0x24, 0xfa, 0xf5, 0x42, 0x6b, 0x2c, - 0xa3, 0xec, 0x2b, 0xf2, 0x7f, 0xd7, 0xdd, 0xfb, 0x55, 0xec, 0x76, 0x30, 0xc9, 0x9e, 0x07, 0x1a, 0x6c, 0x6a, 0xd4, - 0x0a, 0xe1, 0xec, 0x9c, 0x56, 0xa8, 0x1d, 0xeb, 0x85, 0x25, 0x90, 0x07, 0xb0, 0x15, 0x69, 0x50, 0x06, 0xc9, 0x3e, - 0x17, 0x73, 0xb1, 0x70, 0xa2, 0x1c, 0xa9, 0xf0, 0xcf, 0xe4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x0b, 0x86, 0xfc, 0xea, - 0xe8, 0xa2, 0x90, 0x57, 0x20, 0x29, 0x31, 0x0c, 0x95, 0xe5, 0x75, 0x71, 0xd5, 0x96, 0x84, 0xf6, 0x36, 0x00, 0x4a, - 0x53, 0x80, 0xe0, 0xa5, 0x51, 0x43, 0xcc, 0xb6, 0x6a, 0x77, 0x45, 0x77, 0x92, 0x03, 0xea, 0x74, 0xd7, 0x6e, 0xbd, - 0x29, 0x5b, 0x75, 0x2b, 0x2e, 0xfc, 0x01, 0x4a, 0x3f, 0xe5, 0x83, 0xc2, 0xa7, 0x12, 0xb8, 0xf1, 0xd5, 0x26, 0xcb, - 0x2e, 0x36, 0xb8, 0xf4, 0xab, 0xc6, 0xf8, 0xf5, 0xfb, 0x3d, 0xb5, 0x10, 0x1a, 0xa9, 0xc0, 0x7c, 0xfb, 0xcc, 0x54, - 0x65, 0x34, 0xa5, 0xf6, 0x12, 0x5c, 0x39, 0xfb, 0x11, 0x54, 0xc4, 0x75, 0x45, 0x6a, 0x53, 0x03, 0x74, 0xe0, 0x65, - 0x85, 0x5b, 0x59, 0x80, 0xc7, 0x4e, 0x40, 0x76, 0x3b, 0x1e, 0x06, 0xfa, 0xd0, 0x09, 0xfc, 0x2d, 0xf9, 0x1a, 0x99, - 0x35, 0xfb, 0xf8, 0x0f, 0x2d, 0xf8, 0xc7, 0x16, 0xfc, 0x84, 0xe2, 0x4e, 0x2b, 0xf3, 0x6f, 0xa5, 0x75, 0x8b, 0xfb, - 0xf7, 0x32, 0x4d, 0x28, 0x2a, 0x13, 0x6a, 0xbf, 0xd2, 0x6a, 0x6d, 0xd4, 0x18, 0x98, 0xfd, 0xa3, 0x84, 0x0f, 0x66, - 0x8d, 0x27, 0xd6, 0x78, 0x32, 0x9c, 0x6e, 0xa5, 0x61, 0x19, 0x50, 0xe8, 0xe7, 0x65, 0xae, 0xa8, 0x7e, 0xfe, 0x79, - 0xcd, 0xd7, 0xbc, 0xd9, 0x62, 0x9b, 0x74, 0x4f, 0x83, 0xbd, 0x3c, 0x9a, 0x52, 0x38, 0x89, 0x3a, 0x37, 0x12, 0x75, - 0x51, 0xb3, 0x0c, 0xd5, 0x09, 0x5e, 0xcd, 0x53, 0x3d, 0xec, 0xcd, 0x44, 0xb4, 0x56, 0x52, 0x96, 0x18, 0xb0, 0xd6, - 0x91, 0x87, 0xe4, 0x6e, 0xad, 0xe3, 0x4e, 0x43, 0x5d, 0x9a, 0x42, 0x4d, 0xb0, 0xc2, 0x05, 0x38, 0x82, 0xde, 0x17, - 0x21, 0x87, 0x6b, 0xaa, 0xd2, 0x2f, 0x68, 0x4a, 0x9e, 0x78, 0x8a, 0x5a, 0xad, 0x48, 0xb7, 0x1f, 0xe5, 0xd8, 0x0d, - 0xdf, 0x38, 0x21, 0x27, 0x46, 0xe8, 0xef, 0x8e, 0xa5, 0x9c, 0xa1, 0xc5, 0x83, 0x3a, 0xc1, 0x7a, 0x79, 0x4b, 0x81, - 0x62, 0x8e, 0x2e, 0xab, 0xae, 0x79, 0x85, 0xb6, 0x2f, 0xcb, 0x7e, 0x3f, 0xb7, 0xf5, 0xa4, 0xec, 0x64, 0xbb, 0x34, - 0xfb, 0x10, 0x15, 0x53, 0xb8, 0xeb, 0x13, 0xcd, 0x5f, 0x85, 0xfa, 0xaa, 0x2d, 0x73, 0x3e, 0xe2, 0x88, 0x13, 0x92, - 0x93, 0xfa, 0x1f, 0x6a, 0xea, 0x95, 0xb8, 0x5f, 0x55, 0xf2, 0x52, 0x18, 0x2b, 0x46, 0x4b, 0x0c, 0x51, 0xa4, 0xdd, - 0x1b, 0xd3, 0x57, 0x05, 0xc0, 0x5f, 0x09, 0xf6, 0x67, 0x1a, 0x6a, 0xe5, 0xb7, 0x68, 0x0b, 0xf8, 0xb7, 0x8a, 0x1b, - 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, 0x2a, 0xcc, 0xd0, 0x50, 0x5b, - 0x18, 0x7d, 0x8d, 0x32, 0x6e, 0x95, 0xd9, 0xbb, 0x31, 0x76, 0x5a, 0xe0, 0x35, 0xfc, 0x1b, 0xbd, 0x50, 0xcc, 0x46, - 0x1d, 0xa4, 0x47, 0x27, 0x31, 0xfd, 0x71, 0x0b, 0x27, 0x37, 0x0b, 0x67, 0x59, 0xb3, 0x04, 0xba, 0x03, 0x17, 0xc4, - 0xb8, 0xdf, 0xcf, 0xe1, 0xc8, 0x34, 0x23, 0x5f, 0xb0, 0x9c, 0xc6, 0x6c, 0x49, 0xb5, 0xe7, 0xe1, 0x65, 0x15, 0xe6, - 0x74, 0x69, 0x65, 0xbc, 0x29, 0x03, 0x95, 0xd1, 0x6e, 0x17, 0xc2, 0x9f, 0x6e, 0x6b, 0x97, 0x74, 0xbe, 0x84, 0x0c, - 0xf0, 0x07, 0x24, 0xa2, 0x88, 0x05, 0xfe, 0x1f, 0x35, 0x4e, 0xe9, 0x89, 0xd2, 0x9a, 0x25, 0x10, 0x3c, 0x4e, 0xd5, - 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0x76, 0xbb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, 0x02, - 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0xaf, 0x1f, - 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xac, 0xd6, 0x61, 0x62, 0x8a, 0x44, 0x85, 0xe8, 0xec, 0x25, 0xc8, 0x72, 0x04, 0xe0, - 0x7a, 0xbe, 0x96, 0x35, 0xe5, 0x6b, 0x88, 0x0b, 0x0f, 0x0d, 0x7a, 0x57, 0xc8, 0xab, 0xac, 0xe4, 0x21, 0xde, 0x13, - 0x3c, 0xcd, 0xe8, 0xdd, 0x06, 0x1f, 0xda, 0xda, 0xa3, 0x27, 0xc8, 0xd6, 0x53, 0xee, 0xd7, 0x2f, 0x45, 0x38, 0x87, - 0xe8, 0x9d, 0x0b, 0xaa, 0xd5, 0xd5, 0x0e, 0x90, 0xcb, 0xb3, 0xbd, 0x7a, 0x07, 0xa7, 0x9b, 0xbe, 0xbe, 0x55, 0xa1, - 0x33, 0x07, 0x90, 0xf6, 0x90, 0xac, 0x6b, 0xae, 0x77, 0x80, 0x3b, 0x12, 0xb3, 0x35, 0xd0, 0x58, 0xb7, 0x35, 0x3b, - 0xed, 0x51, 0x3c, 0x26, 0x32, 0x33, 0x16, 0x29, 0xc6, 0xdc, 0xad, 0xd3, 0xa2, 0x68, 0x8b, 0x66, 0x08, 0xfb, 0x77, - 0x1d, 0xb1, 0x6e, 0x45, 0x9c, 0xbf, 0xdb, 0xf6, 0x05, 0x46, 0xc3, 0x98, 0x6b, 0xf7, 0x3c, 0x43, 0x37, 0x6c, 0xb0, - 0x8d, 0x24, 0x88, 0x48, 0x90, 0x99, 0x3a, 0x10, 0x65, 0x6d, 0x0d, 0xd8, 0xde, 0x71, 0xbd, 0x69, 0x81, 0x9f, 0x37, - 0x31, 0x78, 0x7b, 0xd6, 0x38, 0xa5, 0xf5, 0x35, 0xae, 0x39, 0xae, 0x0a, 0x11, 0xb5, 0x45, 0x0a, 0x80, 0x61, 0xe7, - 0x0b, 0xdc, 0x99, 0x15, 0x06, 0x73, 0xc2, 0x52, 0xc9, 0x5e, 0xe5, 0xfa, 0x73, 0xd8, 0xe2, 0x20, 0x95, 0x2f, 0xbd, - 0xfe, 0xfe, 0xc3, 0x17, 0x5f, 0xa0, 0xdb, 0x9e, 0xf3, 0x23, 0x08, 0x32, 0x81, 0x0e, 0x6a, 0x4a, 0xf5, 0xf8, 0xb2, - 0x00, 0x6a, 0x0f, 0xf3, 0xf0, 0xb2, 0x60, 0x22, 0xbe, 0xce, 0x2e, 0xe3, 0x4a, 0x16, 0xa3, 0x6b, 0x2e, 0x52, 0x59, - 0x58, 0xa9, 0x71, 0x70, 0xba, 0x5a, 0xe5, 0x3c, 0x00, 0x53, 0x79, 0xcb, 0x28, 0x3b, 0x21, 0xa3, 0x1e, 0x5c, 0x2d, - 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, 0x5c, 0xc5, 0xe5, 0xa7, 0x20, 0xb2, - 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0xdf, 0x09, 0x64, 0xba, 0x2f, 0x0b, 0xb0, 0xcc, 0xb6, 0x15, 0x1f, 0xc7, - 0x58, 0xeb, 0x70, 0x42, 0x66, 0xaa, 0x44, 0xef, 0x5d, 0xb2, 0x2e, 0xc0, 0xda, 0x4f, 0x61, 0x3b, 0xab, 0x5c, 0x33, - 0xac, 0x4c, 0x55, 0x64, 0x0c, 0xe0, 0xd7, 0xec, 0x30, 0xb4, 0x4e, 0x34, 0x73, 0xf4, 0x16, 0xd0, 0x0f, 0xe4, 0xf0, - 0x92, 0x16, 0x6b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0x38, 0xbc, 0x74, 0x0b, 0xf6, 0xda, 0xde, 0xc9, 0x51, 0x98, - 0x08, 0x9e, 0xc6, 0x66, 0x7c, 0x91, 0x67, 0x05, 0xec, 0xa0, 0xc9, 0x78, 0x4c, 0xbd, 0xa5, 0xd5, 0xba, 0x39, 0x3a, - 0x64, 0xdb, 0xec, 0x61, 0xf5, 0x90, 0x93, 0x43, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, 0xba, - 0x2f, 0xd7, 0x36, 0x42, 0xbc, 0x72, 0x76, 0x74, 0x5e, 0xd2, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xf3, 0x69, - 0x03, 0xfe, 0x82, 0x15, 0xeb, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, 0xe3, - 0xf4, 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x95, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, 0xb1, - 0xee, 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x9b, 0xde, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, 0x20, - 0x20, 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0x62, 0x24, 0x64, 0x60, 0xf8, 0x1a, 0xac, 0x45, 0xc9, 0x8d, 0x15, 0xac, - 0x77, 0xcf, 0xd7, 0x09, 0x42, 0x0a, 0x1e, 0xb8, 0x09, 0xfa, 0xa5, 0x75, 0xf3, 0x76, 0x94, 0x28, 0x83, 0xf8, 0xe4, - 0xda, 0x29, 0x07, 0x09, 0x04, 0xe0, 0xc0, 0xaa, 0x90, 0x24, 0x0a, 0x74, 0x1e, 0x5c, 0xcd, 0x38, 0x82, 0xcd, 0x2b, - 0x67, 0x2e, 0x6e, 0x00, 0xe7, 0x95, 0x3f, 0x97, 0x0d, 0xb6, 0xac, 0x47, 0x54, 0x99, 0x33, 0x4e, 0x31, 0xa8, 0x93, - 0x25, 0xe8, 0x2b, 0x4b, 0x69, 0x2f, 0x41, 0xd3, 0x78, 0xc5, 0x56, 0xca, 0x07, 0x80, 0x9e, 0xb3, 0x95, 0x32, 0xf6, - 0xc7, 0xaf, 0xcf, 0xd8, 0x4a, 0x4b, 0x83, 0xa7, 0x57, 0xb3, 0xf3, 0xd9, 0xd9, 0x80, 0x1d, 0x45, 0xa1, 0x36, 0x60, - 0x08, 0x5c, 0x64, 0x82, 0x60, 0x10, 0x6a, 0xfc, 0x97, 0x81, 0x0a, 0x10, 0x46, 0x3c, 0x1e, 0x1b, 0x71, 0xc4, 0xc2, - 0xf1, 0x10, 0x83, 0x81, 0x35, 0x5f, 0x90, 0x80, 0x50, 0x53, 0x1a, 0xfa, 0x7a, 0x86, 0xc3, 0xc9, 0xc1, 0x04, 0x52, - 0x31, 0x33, 0x53, 0x85, 0xb1, 0x31, 0x89, 0x20, 0xfe, 0x6b, 0x67, 0xbd, 0x50, 0x6e, 0x77, 0x8d, 0x06, 0x82, 0x66, - 0xf0, 0x55, 0x15, 0x4f, 0x0e, 0x86, 0x5d, 0x15, 0xe3, 0x28, 0x5c, 0x1b, 0xe5, 0xdb, 0xd9, 0x31, 0x80, 0xf9, 0x9e, - 0x0d, 0x7d, 0xb9, 0xc4, 0xd9, 0xe1, 0x63, 0xf2, 0xf0, 0x31, 0xa1, 0x67, 0xec, 0xec, 0x9b, 0xc7, 0xf4, 0x4c, 0x91, - 0x93, 0x83, 0x49, 0x74, 0xcd, 0x2c, 0x06, 0xce, 0x91, 0x6a, 0x02, 0xbd, 0x1c, 0xad, 0x85, 0x5a, 0x60, 0xda, 0xa1, - 0x29, 0xfc, 0x7e, 0x7c, 0x10, 0x0c, 0xae, 0xdb, 0x4d, 0xbf, 0x6e, 0xb7, 0xd5, 0xf3, 0xea, 0x3a, 0x38, 0x8a, 0xf6, - 0x8b, 0x99, 0xfc, 0x7d, 0x7c, 0xe0, 0xe6, 0x00, 0xeb, 0xbb, 0x7f, 0x4c, 0x4c, 0x93, 0xf6, 0x46, 0xc5, 0xaf, 0xe9, - 0x11, 0xf6, 0xa1, 0x59, 0x64, 0x47, 0x1f, 0x86, 0xff, 0x51, 0x27, 0xea, 0xb3, 0x6f, 0x8e, 0x80, 0x1c, 0x81, 0x0c, - 0x14, 0x4b, 0x04, 0x33, 0x1c, 0x68, 0x0a, 0x28, 0xc8, 0xf4, 0xb8, 0x53, 0x3d, 0xfc, 0x6a, 0xd4, 0xd4, 0x8c, 0x5c, - 0xc3, 0xd4, 0x60, 0x5b, 0xf0, 0x03, 0xd5, 0x0d, 0xfd, 0x8d, 0x46, 0x7b, 0xd2, 0x4e, 0x66, 0xe6, 0x25, 0xb5, 0x71, - 0xee, 0xae, 0x21, 0xa0, 0xb3, 0x83, 0x5b, 0x94, 0xec, 0xdb, 0xe3, 0xcb, 0x03, 0x5c, 0x45, 0x80, 0x1a, 0xc6, 0x82, - 0x6f, 0x07, 0x97, 0x7a, 0x73, 0x1f, 0x04, 0x64, 0xf0, 0x6d, 0x70, 0xf2, 0xed, 0x40, 0x0e, 0x82, 0xe3, 0xc3, 0xcb, - 0x93, 0xc0, 0x19, 0xf7, 0x43, 0xc8, 0x4b, 0x55, 0x51, 0xcc, 0x84, 0xa9, 0x22, 0xb1, 0xb5, 0xe7, 0xb6, 0x5e, 0x65, - 0x7c, 0x46, 0xd3, 0xa9, 0x45, 0x42, 0x0f, 0x53, 0x16, 0x9b, 0xdf, 0xc1, 0x84, 0x5f, 0x05, 0x91, 0x0b, 0x0a, 0x3b, - 0xcb, 0xa3, 0x98, 0x2e, 0xd9, 0xb5, 0x08, 0x53, 0x9a, 0x1c, 0xe6, 0x84, 0x44, 0xe1, 0x52, 0x81, 0x09, 0xaa, 0xd7, - 0x09, 0xc4, 0xb5, 0x75, 0x9f, 0x5f, 0x8b, 0x70, 0x49, 0xf3, 0xc3, 0x84, 0xb4, 0x8a, 0x70, 0x11, 0x6a, 0xb6, 0x35, - 0xbd, 0x60, 0xe1, 0x8a, 0x5e, 0x02, 0x33, 0x15, 0xaf, 0xc3, 0x4b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, 0x36, - 0xa4, 0x6f, 0x86, 0x2f, 0xbe, 0xb0, 0x3e, 0x79, 0xc0, 0x43, 0x3a, 0x3f, 0xbc, 0x14, 0x6c, 0x00, 0xae, 0x33, 0x7e, - 0xf3, 0x83, 0xbc, 0xd5, 0xf3, 0xd2, 0x9e, 0x62, 0x9c, 0x99, 0x76, 0x62, 0xd2, 0x4e, 0xc8, 0xfd, 0xfb, 0xb6, 0xef, - 0x5e, 0xbc, 0x56, 0x2e, 0xab, 0x96, 0x21, 0x49, 0xd6, 0xca, 0x75, 0x1a, 0x25, 0xa7, 0x56, 0xe0, 0xc9, 0x2e, 0x78, - 0x95, 0x2c, 0xfd, 0x83, 0xca, 0x5a, 0x0d, 0xd8, 0x63, 0xc4, 0xb2, 0x50, 0x38, 0xf6, 0xaf, 0x33, 0x96, 0xac, 0x7d, - 0x81, 0x46, 0x8e, 0xdc, 0xdb, 0xeb, 0x8c, 0x79, 0x31, 0x68, 0x97, 0x6b, 0x2f, 0x74, 0x9f, 0x97, 0x9e, 0xb6, 0x78, - 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0x83, 0xb1, 0x32, 0xa3, 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0x60, - 0xa0, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, 0x7a, 0x40, 0xbb, 0xd4, 0xa8, 0xca, 0xdd, 0x32, 0x93, - 0xac, 0x1a, 0x04, 0xa3, 0x3f, 0x4b, 0x29, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, 0x55, 0x2d, 0xc3, 0x72, - 0xc8, 0x51, 0x8b, 0x67, 0x7c, 0x52, 0xa5, 0xfe, 0xd1, 0x11, 0x34, 0x78, 0xbd, 0x6e, 0x05, 0x0d, 0x7e, 0x3c, 0x7e, - 0xac, 0x07, 0xfa, 0x62, 0xad, 0x1d, 0x0f, 0x7d, 0x7e, 0x1b, 0xf1, 0xc6, 0x75, 0xef, 0xa9, 0xd6, 0x2a, 0x94, 0x81, - 0x16, 0x2b, 0x2a, 0x57, 0x6a, 0x49, 0xef, 0x76, 0x11, 0x00, 0x8b, 0xd8, 0x98, 0x8d, 0xf7, 0x6d, 0xb3, 0x42, 0xd0, - 0xe8, 0xc2, 0x52, 0x1c, 0xb0, 0x44, 0xb7, 0x76, 0x30, 0xa1, 0xf1, 0x09, 0x2b, 0xfb, 0xfd, 0xfc, 0x04, 0xe8, 0xa9, - 0x36, 0x62, 0x2a, 0xe0, 0xc8, 0xff, 0xda, 0x8a, 0x4c, 0x51, 0x60, 0xb3, 0xa6, 0xee, 0xd6, 0x58, 0x46, 0xa2, 0x2f, - 0x53, 0xba, 0x3c, 0xe1, 0x19, 0x30, 0xad, 0xd6, 0x2d, 0xc7, 0x95, 0x7d, 0xc5, 0x91, 0xa7, 0xc2, 0xb2, 0xe2, 0xbc, - 0x0a, 0xc7, 0x5b, 0x8f, 0x6f, 0x70, 0x68, 0xd8, 0xb4, 0x4b, 0x7f, 0x08, 0x61, 0x21, 0xbc, 0xce, 0xe0, 0x36, 0xa2, - 0xed, 0x24, 0x50, 0x79, 0x63, 0xae, 0x13, 0xca, 0xe6, 0x76, 0xb5, 0xf6, 0x0c, 0xd2, 0x89, 0x39, 0x50, 0xaa, 0x11, - 0xb4, 0x46, 0xb3, 0xa0, 0x6a, 0xc4, 0x23, 0x67, 0xfe, 0xe5, 0x0c, 0x62, 0xb5, 0x7c, 0x49, 0x53, 0x29, 0x1a, 0x80, - 0x71, 0x01, 0x5c, 0x9e, 0x7e, 0x79, 0xff, 0xd3, 0x07, 0x1e, 0x17, 0xc9, 0xf2, 0x5d, 0x5c, 0xc4, 0x57, 0x65, 0xb8, - 0x55, 0x63, 0x14, 0xd7, 0x64, 0x2a, 0x06, 0x4c, 0x9a, 0x95, 0xd4, 0xdc, 0x95, 0x9a, 0x10, 0x63, 0x9d, 0xc9, 0xba, - 0xac, 0xe4, 0x55, 0xa3, 0xd2, 0x75, 0x91, 0xe1, 0xc7, 0x2d, 0x9f, 0xd3, 0x43, 0x00, 0x36, 0x35, 0x2e, 0xa4, 0x91, - 0xd4, 0x85, 0x18, 0x73, 0x11, 0xaf, 0xeb, 0xe3, 0x71, 0xa3, 0xeb, 0x25, 0x7b, 0x32, 0x7e, 0x34, 0x7d, 0x9d, 0x85, - 0xd9, 0x40, 0x90, 0x51, 0xb5, 0xe4, 0xa2, 0x65, 0xca, 0xa9, 0x4c, 0x02, 0xd0, 0xc7, 0xb3, 0xc7, 0xd8, 0xd1, 0x78, - 0x4c, 0xb6, 0x6d, 0xf1, 0x00, 0x0f, 0xd7, 0xeb, 0xb0, 0x20, 0x33, 0x5d, 0x47, 0x14, 0x08, 0x7e, 0x5b, 0x05, 0x80, - 0x6c, 0x69, 0xab, 0x32, 0x5c, 0x1a, 0x7b, 0x32, 0x9e, 0x50, 0x89, 0xdd, 0x0e, 0x49, 0xed, 0x55, 0xe8, 0x66, 0x5e, - 0xfa, 0x1e, 0x45, 0xd2, 0xb8, 0x2c, 0xed, 0x55, 0x2a, 0xd5, 0x9e, 0x99, 0xb9, 0xae, 0x41, 0x4c, 0x8a, 0x50, 0xd7, - 0x5d, 0x7a, 0x75, 0xef, 0x37, 0xd7, 0x9a, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xc9, 0x5b, 0xcc, 0x5b, 0x57, 0x44, - 0x4d, 0xaf, 0xd6, 0x60, 0x56, 0x8c, 0xb2, 0xa5, 0xe8, 0x62, 0x4d, 0x41, 0x29, 0x18, 0x5d, 0xae, 0xbd, 0x85, 0xfb, - 0x54, 0x36, 0x2e, 0x2c, 0x99, 0x5e, 0x2d, 0x4a, 0x4a, 0xa8, 0x6e, 0x2a, 0x46, 0x4a, 0x18, 0x29, 0x0d, 0x4f, 0xe5, - 0x7b, 0x81, 0xc7, 0x79, 0x1e, 0x44, 0x2d, 0x2f, 0xb0, 0xd3, 0x8a, 0x9c, 0x82, 0xa3, 0x97, 0xc9, 0x69, 0x28, 0x70, - 0x25, 0x14, 0xa8, 0xeb, 0x50, 0xdd, 0x6f, 0x70, 0xf3, 0xff, 0x56, 0xb0, 0xc0, 0xe3, 0x5b, 0xcf, 0x71, 0x1b, 0xfd, - 0x56, 0xf8, 0xb4, 0xf4, 0x81, 0xf4, 0x5d, 0x5d, 0x3c, 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x91, 0x29, - 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x13, 0xd1, 0xb8, 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0x57, 0x41, 0x20, 0x47, - 0x40, 0xee, 0xe7, 0x2c, 0x95, 0xc9, 0x1a, 0x10, 0x36, 0xb4, 0xfc, 0x44, 0xe3, 0x6d, 0x84, 0xfa, 0xfa, 0x05, 0x6e, - 0x73, 0xa5, 0xef, 0x73, 0x5e, 0x09, 0x5a, 0x09, 0x00, 0x7e, 0x89, 0x57, 0x20, 0xf7, 0x78, 0x0a, 0x75, 0x23, 0x6c, - 0x2f, 0xc7, 0x60, 0x49, 0x88, 0x8e, 0x22, 0x2a, 0x16, 0x28, 0x68, 0x0a, 0x83, 0x28, 0xa2, 0x2e, 0x98, 0xc3, 0xf3, - 0x5c, 0x26, 0x9f, 0xa6, 0xc6, 0x67, 0x7e, 0x18, 0x63, 0x0c, 0xe9, 0x60, 0x10, 0x56, 0xb3, 0x60, 0x38, 0x1e, 0x4d, - 0x8e, 0x9e, 0xc0, 0xb9, 0x1d, 0x8c, 0x03, 0x32, 0x08, 0xea, 0x72, 0x15, 0x0b, 0x5a, 0x5e, 0x5f, 0xda, 0x32, 0xf0, - 0xe3, 0x3a, 0x18, 0xfc, 0x56, 0xb8, 0x51, 0xf9, 0x37, 0x68, 0x4e, 0x36, 0x32, 0x0c, 0x02, 0x7a, 0xb5, 0x26, 0x20, - 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, - 0xd3, 0x6c, 0xf4, 0x4a, 0x29, 0x72, 0xdf, 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, - 0xe0, 0x46, 0xfe, 0x4a, 0x5c, 0xc7, 0x79, 0x96, 0x1e, 0x34, 0xdf, 0x1c, 0x94, 0x1b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, - 0x58, 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xcf, 0xcc, 0x64, 0xc6, 0x23, 0xf0, - 0x08, 0x6c, 0xfa, 0x40, 0x16, 0x1b, 0xe7, 0x92, 0xe4, 0x6f, 0xa6, 0xd2, 0x5e, 0xf5, 0xca, 0xbd, 0x82, 0xac, 0x57, - 0x5b, 0xb9, 0xef, 0xd6, 0x67, 0xdf, 0x74, 0x78, 0x05, 0x9e, 0x49, 0x70, 0x8b, 0xec, 0xf7, 0x9b, 0x82, 0x4a, 0x61, - 0x54, 0xc4, 0x7b, 0xc9, 0x35, 0xfa, 0xb7, 0x7b, 0x63, 0xa3, 0x48, 0x6e, 0x79, 0xff, 0x00, 0xea, 0x4c, 0xde, 0x15, - 0xb7, 0x73, 0x88, 0xda, 0xba, 0x1b, 0x0f, 0xbc, 0x37, 0x68, 0x97, 0x35, 0x47, 0xb0, 0xe5, 0xc5, 0x41, 0x06, 0x63, - 0x81, 0xb3, 0x32, 0x52, 0x6a, 0x5c, 0x43, 0x6a, 0xc1, 0x27, 0x79, 0x7a, 0x07, 0x59, 0xea, 0x49, 0x50, 0xe4, 0x78, - 0x16, 0x43, 0xa6, 0xf1, 0x36, 0x10, 0xfb, 0xad, 0x0c, 0x41, 0x9a, 0xb6, 0xdb, 0x35, 0x47, 0xa0, 0xec, 0x1e, 0x98, - 0x92, 0xd4, 0xb5, 0x31, 0x35, 0xd0, 0xd0, 0x83, 0xa8, 0x91, 0x8a, 0x38, 0x3b, 0x79, 0x0a, 0x3a, 0x44, 0xf0, 0xfd, - 0x4e, 0xb3, 0xb2, 0xe3, 0xc5, 0x84, 0xe0, 0xc9, 0xfb, 0xfc, 0x36, 0x2b, 0xab, 0x32, 0x7a, 0x93, 0xa2, 0x21, 0x54, - 0x22, 0x45, 0xf4, 0x19, 0xe2, 0x0b, 0x96, 0xf8, 0xbb, 0x8c, 0x5e, 0xa4, 0x34, 0x4e, 0x53, 0x4c, 0x7f, 0x56, 0xc0, - 0xcf, 0xa7, 0x80, 0x72, 0x89, 0x3b, 0x21, 0x3a, 0x93, 0x60, 0xaf, 0x06, 0xd1, 0xbd, 0x2a, 0x0e, 0x98, 0xa2, 0xd1, - 0xb5, 0xa0, 0x88, 0x59, 0x87, 0xd9, 0x7f, 0x29, 0x50, 0x28, 0xa4, 0x8a, 0x79, 0x29, 0xec, 0x43, 0xc4, 0xd7, 0x50, - 0xce, 0xe9, 0xbb, 0x57, 0x66, 0x48, 0xa3, 0x5b, 0x49, 0xf5, 0xd6, 0xc6, 0x63, 0x0b, 0x51, 0x7a, 0xa2, 0xf3, 0x35, - 0x3d, 0x8b, 0x57, 0x59, 0xb4, 0x05, 0xfc, 0x89, 0x77, 0xaf, 0x9e, 0x2a, 0x0b, 0x93, 0x57, 0x19, 0x28, 0x0e, 0x4e, - 0xdf, 0xbd, 0x7a, 0x2d, 0xd3, 0x75, 0xce, 0xa3, 0x8d, 0x44, 0xd2, 0x7a, 0xfa, 0xee, 0xd5, 0xcf, 0x68, 0xee, 0xf5, - 0xbe, 0x80, 0xf7, 0x2f, 0x80, 0xb7, 0x8c, 0xf2, 0x35, 0xf4, 0x49, 0xfd, 0x5e, 0xae, 0xb1, 0x53, 0x5e, 0xad, 0x65, - 0xf4, 0x57, 0x5a, 0x7b, 0xd2, 0xaa, 0xbf, 0x0a, 0x9f, 0xda, 0x79, 0x02, 0x9e, 0xdb, 0x3c, 0x13, 0x9f, 0x22, 0x2b, - 0xda, 0x09, 0xa2, 0x6f, 0x0f, 0x6e, 0xaf, 0x72, 0x51, 0x46, 0xf8, 0x82, 0xa1, 0x5d, 0x50, 0x74, 0x78, 0x78, 0x73, - 0x73, 0x33, 0xba, 0x79, 0x34, 0x92, 0xc5, 0xe5, 0xe1, 0xe4, 0xfb, 0xef, 0xbf, 0x3f, 0xc4, 0xb7, 0xc1, 0xb7, 0x6d, - 0xb7, 0xf7, 0x8a, 0xf0, 0x01, 0x0b, 0x10, 0xb1, 0xfb, 0x5b, 0xb8, 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x6d, 0xf0, 0xad, - 0x3e, 0x74, 0xbe, 0x3d, 0x2e, 0xaf, 0x2f, 0x55, 0xf9, 0x5d, 0x25, 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, - 0x3b, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0x29, 0xaf, 0x2f, 0x4f, 0x02, 0xcf, 0xe4, 0xb5, 0xc1, 0x22, - 0x3a, 0x10, 0x97, 0xe0, 0xf0, 0x92, 0x06, 0xdf, 0x06, 0xc4, 0xa5, 0x7c, 0x03, 0x29, 0xdf, 0x1c, 0x3d, 0xf1, 0xd3, - 0xfe, 0x97, 0x4a, 0x7b, 0xe4, 0xa7, 0x1d, 0x63, 0xda, 0xa3, 0xa7, 0x7e, 0xda, 0x89, 0x4a, 0x7b, 0xee, 0xa7, 0xfd, - 0x9f, 0x72, 0x00, 0xa9, 0x07, 0xbe, 0xf5, 0xdf, 0xc6, 0x6b, 0x0d, 0x9e, 0x42, 0x51, 0x76, 0x15, 0x5f, 0x72, 0x68, - 0xf4, 0xe0, 0xf6, 0x2a, 0xa7, 0xc1, 0x00, 0xdb, 0xeb, 0x19, 0x79, 0x78, 0x1f, 0x7c, 0xbb, 0x2e, 0xf2, 0x30, 0xf8, - 0x76, 0x80, 0x85, 0x0c, 0xbe, 0x0d, 0xc8, 0xb7, 0xc6, 0x40, 0x46, 0xb0, 0x6d, 0xe0, 0x42, 0xb3, 0x0e, 0x6d, 0xc0, - 0x34, 0x5f, 0x1a, 0x57, 0xd3, 0x7f, 0x15, 0xdd, 0xd9, 0xf0, 0x96, 0xa8, 0xdc, 0x74, 0x83, 0x9a, 0xbe, 0x05, 0xef, - 0x04, 0x68, 0x54, 0x14, 0x5c, 0xc7, 0x45, 0x38, 0x1c, 0x96, 0xd7, 0x97, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa2, - 0x40, 0xc8, 0xa1, 0xfa, 0x19, 0xa8, 0x48, 0x60, 0x01, 0x42, 0x19, 0xc1, 0x7f, 0x41, 0x4d, 0xdf, 0x49, 0xb6, 0x0d, - 0x86, 0x37, 0xfc, 0xfc, 0x53, 0x56, 0x0d, 0x95, 0x68, 0xf1, 0x46, 0x50, 0xf8, 0x01, 0x7f, 0x5d, 0xd5, 0xd1, 0xbf, - 0xc0, 0x8d, 0xbb, 0xa9, 0x61, 0x7f, 0x27, 0x3d, 0x87, 0x36, 0x39, 0xcf, 0x16, 0xd3, 0xd6, 0x81, 0xfe, 0x56, 0x92, - 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, 0xe0, 0x0b, 0xf6, 0x56, 0xce, 0xb9, 0x67, 0x3e, 0x75, 0x2a, 0xfd, 0x69, 0x9e, - 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, 0xe4, 0xf0, 0xbf, 0xe6, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0x1c, 0x92, 0x59, 0xb0, - 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xeb, 0x75, 0xdb, 0xcb, 0xe3, 0xce, - 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, - 0x1c, 0xb0, 0xe0, 0xb8, 0x37, 0x1c, 0x1e, 0x04, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x07, 0xc3, 0xe1, 0x49, 0xe0, 0xee, - 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, 0xc1, 0xfe, 0x2a, 0xc2, 0x92, 0x82, 0x78, 0x4c, 0x6a, 0xf1, 0x97, 0x06, 0x97, - 0x19, 0x00, 0xf4, 0x91, 0x92, 0x80, 0x19, 0x58, 0x99, 0x01, 0x84, 0x2a, 0xa7, 0x31, 0xbb, 0x05, 0xe6, 0x11, 0x38, - 0x66, 0x05, 0x93, 0x05, 0x88, 0x25, 0x01, 0xce, 0x5d, 0x10, 0xc5, 0xba, 0x90, 0x53, 0x08, 0x02, 0x80, 0x3f, 0x89, - 0x29, 0x05, 0x93, 0x74, 0xec, 0x46, 0x10, 0xc4, 0xf1, 0xd9, 0x8d, 0x68, 0x4d, 0xce, 0x12, 0x1d, 0xcc, 0x48, 0x02, - 0x6c, 0x88, 0x81, 0xe1, 0x83, 0xfb, 0x39, 0x28, 0x3d, 0xac, 0xde, 0x09, 0xb9, 0xe0, 0x0d, 0x77, 0x2c, 0xd4, 0x0d, - 0x5c, 0x3d, 0xe1, 0x20, 0xd8, 0x70, 0xcd, 0x02, 0x8c, 0xaa, 0x62, 0x5d, 0x56, 0x3c, 0xfd, 0xb8, 0x59, 0x41, 0x2c, - 0x40, 0x1c, 0xd0, 0x77, 0x32, 0xcf, 0x92, 0x4d, 0xe8, 0xec, 0xb9, 0xb6, 0x2a, 0xfd, 0xe5, 0xc7, 0xd7, 0x3f, 0x45, - 0x20, 0x72, 0xac, 0x0d, 0xa5, 0xdf, 0x70, 0x3c, 0x9b, 0xfc, 0x88, 0x57, 0xfe, 0xc6, 0xde, 0x70, 0x7b, 0x7a, 0xf4, - 0xfb, 0x50, 0x37, 0xdd, 0xf0, 0xd9, 0x86, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0xf0, 0xec, 0xb2, 0xd6, 0xbe, 0x11, 0xd2, - 0xfd, 0xf3, 0x4c, 0x79, 0x63, 0x7e, 0xb4, 0x83, 0x61, 0x10, 0x4c, 0xb5, 0x50, 0x12, 0xa2, 0x90, 0x30, 0x25, 0x60, - 0x88, 0x0e, 0xf4, 0xb2, 0x9a, 0x22, 0xe7, 0xa6, 0x46, 0x16, 0xde, 0x0f, 0x98, 0x16, 0x3a, 0x34, 0x72, 0x28, 0x3f, - 0x38, 0x9c, 0x30, 0x66, 0xe1, 0xb7, 0x4a, 0x98, 0x7e, 0xb5, 0xa8, 0x9c, 0x83, 0xe8, 0x01, 0x18, 0xe3, 0x0a, 0x5e, - 0x40, 0x57, 0xd8, 0xa7, 0xb5, 0x8a, 0x12, 0x82, 0x60, 0x7a, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, - 0xab, 0x72, 0x96, 0x2a, 0xea, 0x32, 0x94, 0x95, 0xb1, 0xc2, 0xc0, 0x2f, 0xd9, 0x2f, 0x05, 0x7a, 0x96, 0x4f, 0x45, - 0x17, 0xbc, 0x10, 0x4a, 0xb0, 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xd7, 0x8f, 0xa7, - 0xaf, 0x65, 0xca, 0xb5, 0x09, 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x07, 0xe8, 0x57, 0xdb, 0x46, 0x9f, - 0x5d, 0xaf, 0xf5, 0x66, 0x50, 0xa2, 0x63, 0x5e, 0xa3, 0xe0, 0x5a, 0x29, 0x14, 0x8c, 0xf6, 0x36, 0xfe, 0x02, 0x47, - 0x6e, 0x75, 0x7b, 0xe8, 0xfd, 0x56, 0xc5, 0x97, 0x6f, 0xd0, 0xb7, 0xd3, 0xfe, 0x1c, 0x55, 0xf2, 0x97, 0xd5, 0x0a, - 0x7c, 0xa8, 0x20, 0xd2, 0x8a, 0xc5, 0xe9, 0x85, 0x7a, 0x3e, 0xbc, 0x3b, 0x7d, 0x03, 0x7e, 0x94, 0xf8, 0xfb, 0xd7, - 0x1f, 0x83, 0x9a, 0x4c, 0xe3, 0x59, 0x61, 0x3e, 0xb4, 0x39, 0x20, 0x54, 0x8b, 0x4b, 0xb3, 0xef, 0x67, 0x71, 0x93, - 0x7d, 0xd7, 0x6c, 0x3d, 0x2d, 0x9a, 0x48, 0x52, 0x86, 0xdb, 0x07, 0x03, 0x02, 0x7d, 0x80, 0x28, 0xce, 0xbe, 0xa0, - 0x31, 0xa4, 0xf9, 0xcc, 0xbe, 0x1f, 0x21, 0xf0, 0xd5, 0x5e, 0x48, 0x35, 0xae, 0xb0, 0x68, 0xf4, 0x90, 0xcf, 0x78, - 0xa4, 0x0c, 0x8b, 0xde, 0x63, 0x02, 0x71, 0x86, 0xd3, 0xea, 0x3d, 0x62, 0x40, 0xe3, 0xdd, 0x40, 0xcb, 0x1e, 0xa2, - 0x8c, 0xba, 0xec, 0x0d, 0x8b, 0xef, 0xd7, 0xeb, 0x30, 0xb3, 0x96, 0x97, 0x43, 0xf8, 0x1b, 0x68, 0x03, 0x70, 0xca, - 0x91, 0xe5, 0xab, 0xcc, 0x46, 0x57, 0x4b, 0x4c, 0x6f, 0x22, 0x88, 0x4d, 0xa4, 0xd3, 0x61, 0xed, 0xea, 0x54, 0xbd, - 0xab, 0x9d, 0xcf, 0x44, 0xaf, 0x02, 0xad, 0x5c, 0xdb, 0x1e, 0x0f, 0xe1, 0x3f, 0xb5, 0xb4, 0xc2, 0x46, 0xd8, 0x73, - 0xf1, 0x85, 0xe7, 0xd8, 0x9c, 0x80, 0x06, 0x57, 0x32, 0x05, 0xe0, 0x2c, 0xad, 0x46, 0xa3, 0x46, 0xd8, 0x67, 0xe5, - 0x7c, 0x0e, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x1c, 0xb8, 0x89, 0xc9, 0xc9, 0xbb, 0x31, 0x39, 0xa7, 0x9f, 0x14, 0xdc, - 0x77, 0x70, 0x56, 0x2e, 0xe3, 0x54, 0xde, 0x00, 0x36, 0x65, 0xe0, 0xa7, 0x62, 0xa9, 0x5e, 0x42, 0xb2, 0xe4, 0xc9, - 0x27, 0xb4, 0xda, 0x48, 0x03, 0xe0, 0x2a, 0xa7, 0xc6, 0x72, 0x4f, 0x81, 0xa6, 0xba, 0x52, 0x54, 0x42, 0x5c, 0x55, - 0x71, 0xb2, 0xfc, 0x80, 0xa9, 0xe1, 0x16, 0x7a, 0x11, 0x05, 0x72, 0xc5, 0x05, 0x90, 0xf4, 0x9c, 0xfd, 0x23, 0xd3, - 0xd8, 0xeb, 0x0f, 0x24, 0x0a, 0x98, 0x34, 0x8a, 0x32, 0x56, 0xca, 0x5e, 0x49, 0x13, 0xfd, 0x2e, 0x08, 0x6a, 0xf7, - 0xf2, 0x2f, 0xa8, 0xfb, 0x29, 0xb4, 0x22, 0x6c, 0x80, 0x17, 0x6a, 0xf0, 0xc3, 0xd4, 0x2e, 0x39, 0x0f, 0xc8, 0xd0, - 0x79, 0x9f, 0xd5, 0x76, 0xab, 0x3f, 0x5d, 0x02, 0xd6, 0x6b, 0x6a, 0x7c, 0x0a, 0xc3, 0x84, 0x98, 0x58, 0xc9, 0x56, - 0x59, 0x69, 0x37, 0x94, 0x69, 0x27, 0x5d, 0x32, 0xaf, 0x85, 0xd3, 0xbc, 0xc7, 0xd8, 0x72, 0xa4, 0x72, 0xf7, 0xfb, - 0xa1, 0xf9, 0xc9, 0x72, 0xfa, 0x40, 0x87, 0xb0, 0xf6, 0xc6, 0x83, 0xe6, 0x44, 0xab, 0xab, 0x3a, 0xfa, 0x01, 0x1d, - 0x80, 0x99, 0xb6, 0x08, 0x95, 0x2e, 0xf8, 0xb6, 0xaf, 0x44, 0xc5, 0x25, 0x09, 0x4b, 0x25, 0x81, 0x9d, 0xdd, 0x94, - 0xec, 0x6c, 0x03, 0xe2, 0x19, 0xee, 0x7a, 0x5a, 0xec, 0x84, 0x34, 0xe1, 0x2d, 0x0e, 0x12, 0x10, 0x75, 0xa8, 0xea, - 0x12, 0xb2, 0x35, 0x86, 0x2e, 0xfe, 0x45, 0x29, 0x4c, 0x58, 0xcb, 0xa4, 0x2a, 0x31, 0x41, 0xa1, 0xca, 0xfd, 0x16, - 0x81, 0x25, 0x0a, 0x76, 0x00, 0x7b, 0xef, 0x46, 0xdd, 0x8c, 0x9a, 0xaa, 0x4e, 0xbd, 0x04, 0x1f, 0xa7, 0x59, 0x57, - 0x41, 0x66, 0x61, 0x57, 0xc5, 0x9a, 0x07, 0x3a, 0x56, 0x97, 0x32, 0x26, 0xee, 0xd2, 0x22, 0x43, 0x7c, 0x64, 0x8c, - 0x2d, 0xac, 0xe1, 0x48, 0xdb, 0xe3, 0xa6, 0x27, 0x08, 0xfd, 0x84, 0x0d, 0x25, 0x70, 0xd3, 0xd9, 0x9e, 0x9a, 0x66, - 0x3e, 0x20, 0xe2, 0x30, 0xa0, 0x40, 0xb2, 0x71, 0x48, 0x73, 0xa4, 0x2f, 0x48, 0x9a, 0x30, 0x50, 0xb6, 0xe2, 0x39, - 0x41, 0x56, 0x14, 0x7a, 0xb6, 0xae, 0x6a, 0x88, 0x9f, 0xcb, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xa7, 0x09, 0x32, 0xb1, - 0x3b, 0xda, 0x66, 0x26, 0xc3, 0x51, 0xb2, 0xc0, 0xfc, 0x0a, 0xa2, 0xc4, 0x9d, 0x69, 0x56, 0xe5, 0x60, 0x5c, 0xc0, - 0x02, 0xad, 0x7c, 0x0f, 0xea, 0xc6, 0x1a, 0xda, 0x6a, 0x58, 0x66, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, - 0x8a, 0xe5, 0x65, 0x0a, 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x5e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, - 0x53, 0x03, 0xe8, 0xa9, 0x17, 0x00, 0xbe, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xb8, 0x74, 0x83, 0x20, - 0x45, 0x6f, 0x52, 0x30, 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, - 0xe4, 0x95, 0xd4, 0xc4, 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdb, 0x9d, 0xa6, 0x61, 0xd2, 0x66, - 0x1b, 0x52, 0x90, 0x56, 0x98, 0x38, 0x21, 0x50, 0xd9, 0x2b, 0xdc, 0x2f, 0xd8, 0x4e, 0x9a, 0x82, 0x07, 0x61, 0xa3, - 0x81, 0x89, 0x5b, 0x5d, 0x02, 0x8c, 0x66, 0xc2, 0x25, 0xd5, 0xce, 0x4e, 0x5a, 0x58, 0xdf, 0x5e, 0x97, 0x17, 0xb6, - 0x0f, 0x3a, 0x96, 0x5a, 0xd7, 0xf0, 0x40, 0xf3, 0x9a, 0x5d, 0x5c, 0x31, 0x4d, 0x13, 0x8d, 0xf5, 0x90, 0xb2, 0xe4, - 0x58, 0xd7, 0xd3, 0x15, 0xae, 0x96, 0x99, 0x06, 0xba, 0x97, 0x78, 0xa1, 0x07, 0x7c, 0xf0, 0x70, 0x45, 0xa2, 0x0b, - 0x6c, 0x36, 0x5b, 0xd5, 0x64, 0x9a, 0xdf, 0x95, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, 0x69, - 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, 0xe8, - 0x9d, 0xf3, 0x45, 0xea, 0xe6, 0x17, 0x60, 0x1b, 0xb5, 0xb5, 0xa6, 0x59, 0xeb, 0x30, 0x51, 0x16, 0xd6, 0xc8, 0x42, - 0x2e, 0xc1, 0x07, 0x73, 0xbf, 0xa9, 0xd3, 0xe7, 0x1d, 0x44, 0xd8, 0xef, 0xa2, 0xc7, 0x23, 0x8c, 0x15, 0x6b, 0x90, - 0x18, 0x56, 0x61, 0x4d, 0x9b, 0xcb, 0x21, 0xca, 0xa9, 0x59, 0x32, 0xd1, 0x92, 0xfa, 0x94, 0x22, 0x4a, 0xc1, 0xdc, - 0x78, 0x5a, 0x36, 0x4c, 0x09, 0x11, 0xb2, 0x42, 0x3a, 0xa0, 0x5a, 0x0b, 0x2d, 0xd5, 0x04, 0x01, 0x0f, 0xbd, 0x2c, - 0x34, 0xa6, 0x20, 0xfa, 0x88, 0x0c, 0x37, 0xe2, 0xc8, 0xe8, 0xfe, 0x18, 0xc5, 0x04, 0x42, 0x77, 0x7b, 0x79, 0x61, - 0xf5, 0x69, 0xd9, 0x56, 0x07, 0x71, 0x8d, 0x69, 0x72, 0x07, 0x41, 0x8d, 0x51, 0xd0, 0xe6, 0x74, 0xa3, 0xff, 0x2e, - 0x42, 0xdf, 0x2e, 0x1c, 0xbb, 0x51, 0x10, 0x09, 0x11, 0x69, 0xbd, 0xa6, 0x62, 0x80, 0xda, 0x79, 0xec, 0x22, 0x56, - 0xe9, 0x6e, 0x21, 0xca, 0x1b, 0x95, 0xf5, 0xeb, 0x75, 0x48, 0x76, 0x3b, 0x2c, 0x0b, 0x7c, 0xd9, 0x9f, 0xae, 0xef, - 0x80, 0x40, 0x7f, 0xb0, 0xfe, 0x22, 0x04, 0xfa, 0xb3, 0xec, 0x6b, 0x20, 0xd0, 0x1f, 0xac, 0xff, 0xa7, 0x21, 0xd0, - 0x9f, 0xae, 0x3d, 0x08, 0x74, 0x35, 0x18, 0xff, 0x2c, 0x58, 0xf0, 0xf6, 0x4d, 0x40, 0x9f, 0x49, 0x16, 0xbc, 0x7d, - 0xf1, 0xc2, 0x13, 0xa6, 0x7f, 0xcc, 0x34, 0x92, 0xbf, 0x91, 0x05, 0x23, 0x6e, 0x0b, 0xbc, 0x42, 0xad, 0x93, 0x0f, - 0x54, 0x94, 0x01, 0x10, 0x7d, 0xf9, 0x5b, 0x56, 0x2d, 0xc3, 0xe0, 0x30, 0x20, 0x33, 0x07, 0x09, 0x3a, 0x9c, 0x34, - 0x6e, 0x6f, 0xbf, 0x88, 0x86, 0x50, 0xc7, 0x46, 0x1e, 0x80, 0xaf, 0x5c, 0xae, 0xb7, 0xfe, 0x0d, 0x11, 0x3f, 0x99, - 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x3f, 0x16, 0x9e, 0x6d, - 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, 0xe5, - 0xbf, 0xbc, 0x7f, 0x65, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, 0xfe, - 0x78, 0xb0, 0xed, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x9b, 0xd5, - 0x87, 0x0f, 0xb6, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x5b, 0xc2, 0x0f, 0x5e, 0xff, 0xe1, - 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, 0xa8, - 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, 0x9d, - 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, 0x2e, - 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xfb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, 0x79, - 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0xfc, 0xf8, 0x55, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, 0x2e, - 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, 0x95, - 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0x49, 0x87, 0x5d, - 0x3e, 0x5d, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc5, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, - 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x09, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x45, 0x9d, 0x95, - 0xe0, 0x49, 0xe5, 0x71, 0xe2, 0x2a, 0x16, 0x40, 0x46, 0x4d, 0x34, 0x80, 0x8e, 0x1c, 0x34, 0xb4, 0x7b, 0x4d, 0x3b, - 0x96, 0x1b, 0x95, 0x45, 0x06, 0x96, 0xb0, 0xcf, 0xa1, 0x74, 0x40, 0x6c, 0x87, 0x70, 0x21, 0x70, 0xf5, 0xc4, 0xab, - 0x51, 0x03, 0xb1, 0x87, 0x96, 0xbe, 0xbb, 0x90, 0x62, 0xb5, 0x0c, 0xda, 0x65, 0x63, 0x98, 0xf0, 0x7a, 0x8d, 0x2e, - 0xc3, 0xa0, 0xf8, 0x2f, 0xdc, 0xa2, 0x44, 0x5c, 0xa4, 0x2c, 0x55, 0x46, 0x67, 0x3d, 0x94, 0x85, 0xe1, 0xb3, 0xa7, - 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0xad, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, - 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0x66, 0x61, 0xe0, 0x2e, 0x74, 0x59, - 0xad, 0x49, 0xbc, 0xf3, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, - 0x6a, 0x7f, 0xab, 0x7d, 0xe2, 0x9e, 0x6d, 0xd7, 0x68, 0xd3, 0xcf, 0xa1, 0x5d, 0x23, 0x35, 0x4b, 0xa9, 0xe0, 0x7f, - 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0x34, 0x86, 0x2e, 0x8a, 0x44, 0x2b, 0x24, 0x28, 0x45, 0x7d, - 0x5b, 0x2f, 0x54, 0x1b, 0x08, 0x51, 0xb7, 0xc5, 0x34, 0x7d, 0x8e, 0xa0, 0xed, 0x20, 0x25, 0xc1, 0xbd, 0x65, 0x63, - 0x7e, 0x75, 0x2d, 0x9f, 0x39, 0x74, 0x67, 0x31, 0xfb, 0x52, 0x86, 0xc1, 0x20, 0xfa, 0x52, 0x16, 0x36, 0xb9, 0x67, - 0x95, 0xaa, 0x2c, 0xc7, 0xc6, 0xf6, 0x72, 0x8a, 0xa6, 0x2c, 0xe1, 0xbb, 0x75, 0xd8, 0x5c, 0xfb, 0x14, 0x67, 0x9f, - 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x54, 0xd7, 0x85, 0x06, 0x2d, 0xd2, 0xda, - 0x9c, 0x5c, 0x5e, 0x82, 0x2c, 0xb3, 0x57, 0x8c, 0xe4, 0xa7, 0xbd, 0x28, 0x9f, 0x7f, 0xbc, 0xfc, 0xf8, 0xf1, 0xdd, - 0x01, 0x2a, 0x7c, 0x7a, 0x07, 0x1f, 0x14, 0x7a, 0xc0, 0xc1, 0x83, 0x6d, 0xa1, 0x55, 0xec, 0xf5, 0x1f, 0xf6, 0xac, - 0x2a, 0x5a, 0x0a, 0x72, 0x03, 0x0a, 0xe8, 0x55, 0xd1, 0x1a, 0xd6, 0xc2, 0x69, 0xb1, 0xfd, 0xcc, 0x4a, 0xbb, 0x14, - 0xa0, 0xee, 0x44, 0xd5, 0x1c, 0x29, 0xbd, 0x3c, 0x44, 0x5a, 0x08, 0xab, 0x3b, 0xb6, 0x5a, 0xd5, 0xb5, 0xd5, 0x64, - 0x51, 0x65, 0xe2, 0xf2, 0x0c, 0x77, 0xff, 0x57, 0x6d, 0x39, 0x33, 0xc3, 0x8a, 0x5e, 0xb4, 0x77, 0x5b, 0x03, 0xaa, - 0x4c, 0x1b, 0xe5, 0xea, 0x3d, 0x04, 0x02, 0xb3, 0xb2, 0x9e, 0xfa, 0x1f, 0x1b, 0x8b, 0x11, 0x3f, 0x4d, 0x01, 0xb9, - 0x01, 0x0f, 0xc4, 0x4e, 0xe2, 0x91, 0x69, 0xdf, 0x0d, 0xca, 0x4d, 0x8e, 0x93, 0x56, 0xc2, 0x6c, 0x38, 0x89, 0x26, - 0xc4, 0xc6, 0x97, 0xd0, 0x34, 0xec, 0xc7, 0xd1, 0xf3, 0x37, 0x1f, 0x5f, 0x7d, 0xfc, 0xf7, 0xd9, 0xd3, 0xd3, 0x8f, - 0xcf, 0x7f, 0x7c, 0xfb, 0xfe, 0xd5, 0xf3, 0x0f, 0x78, 0x42, 0x68, 0xc0, 0xca, 0x70, 0xab, 0xad, 0xa2, 0x9b, 0x65, - 0x45, 0xa2, 0x26, 0xcd, 0xa6, 0x28, 0xc4, 0x28, 0xcc, 0x6c, 0x8b, 0xfc, 0xe5, 0xcd, 0xb3, 0xe7, 0x2f, 0x5e, 0xbd, - 0x79, 0xfe, 0xac, 0xfd, 0xf5, 0x70, 0x52, 0x93, 0xda, 0xcd, 0x9c, 0x8e, 0x90, 0xc2, 0xed, 0x78, 0x75, 0xd0, 0x27, - 0xd4, 0xca, 0xfb, 0xf4, 0x29, 0x83, 0x15, 0xc9, 0x94, 0x9c, 0x1e, 0x7f, 0x7b, 0xf8, 0xbf, 0x6a, 0xe3, 0xed, 0x76, - 0xc0, 0x43, 0x20, 0x19, 0x53, 0xb2, 0x7e, 0x18, 0xd5, 0x8c, 0xaa, 0x97, 0x11, 0x44, 0x7a, 0xd1, 0xa5, 0x81, 0x0d, - 0x74, 0x4a, 0x55, 0x48, 0x85, 0xb3, 0x24, 0xae, 0xf8, 0xa5, 0x2c, 0x36, 0x51, 0x36, 0x6a, 0xa5, 0xd0, 0xc6, 0x02, - 0x88, 0x42, 0x10, 0x2c, 0x37, 0x92, 0x48, 0x4f, 0x11, 0x00, 0x6f, 0x08, 0xdc, 0xa8, 0xce, 0x5d, 0xb4, 0x80, 0x76, - 0xc1, 0x64, 0xb1, 0xdb, 0x75, 0x0c, 0x5a, 0x27, 0xed, 0x8b, 0xe6, 0x99, 0x22, 0x8a, 0x0b, 0x60, 0xcc, 0xe1, 0x78, - 0x53, 0x67, 0x17, 0x33, 0xc7, 0xdd, 0xa9, 0x8e, 0xfa, 0x09, 0xd6, 0x88, 0xee, 0xb5, 0x09, 0x2c, 0xd3, 0x3c, 0x0f, - 0xff, 0xbf, 0xf6, 0x9e, 0x36, 0xb9, 0x6d, 0x23, 0xd9, 0xff, 0x39, 0x05, 0x04, 0x7b, 0x6d, 0xc0, 0x06, 0x20, 0x80, - 0x14, 0x25, 0x9a, 0x14, 0xa8, 0xc4, 0xb6, 0x9c, 0x64, 0x57, 0x89, 0x53, 0xb6, 0xe2, 0xfd, 0xd0, 0xaa, 0x44, 0x90, - 0x1c, 0x92, 0x58, 0x83, 0x00, 0x0b, 0x00, 0x45, 0x2a, 0x34, 0xf6, 0x2c, 0x7b, 0x84, 0x77, 0x86, 0x3d, 0xd9, 0xab, - 0xee, 0x9e, 0x01, 0x06, 0x20, 0x48, 0x51, 0xb1, 0x93, 0xdd, 0x57, 0xf5, 0x2a, 0xb1, 0x4d, 0x0c, 0x66, 0x06, 0x3d, - 0x5f, 0xdd, 0x3d, 0xfd, 0x69, 0x57, 0x30, 0xae, 0x88, 0xf1, 0x5b, 0x29, 0xa5, 0x6d, 0xc6, 0x63, 0x2b, 0xc2, 0x4a, - 0x41, 0x3a, 0x2e, 0x21, 0xba, 0xd5, 0x02, 0xb0, 0x90, 0x29, 0xad, 0xaf, 0x98, 0x87, 0xa0, 0x13, 0x89, 0x30, 0x79, - 0x60, 0x32, 0xb8, 0xa5, 0xd6, 0xb4, 0x13, 0x97, 0x02, 0x5e, 0x46, 0xe5, 0x49, 0x3d, 0x8d, 0xcb, 0xcf, 0xb0, 0x8d, - 0x2b, 0x55, 0x50, 0x64, 0x5b, 0xae, 0x04, 0xa2, 0x85, 0xe1, 0x19, 0x7d, 0xde, 0x4a, 0xa3, 0x8b, 0x68, 0x29, 0xc4, - 0xc3, 0xa7, 0x71, 0x4d, 0x21, 0x9e, 0x8d, 0x8e, 0x77, 0x3a, 0xa4, 0x1f, 0x4e, 0xb6, 0x85, 0x08, 0x64, 0xc5, 0x04, - 0xe7, 0xcc, 0x69, 0x9f, 0xae, 0x4c, 0x37, 0x8f, 0xd7, 0x62, 0xe3, 0x65, 0x7d, 0x3f, 0x4f, 0xfe, 0x5a, 0x62, 0x2c, - 0x32, 0x3e, 0xf5, 0x72, 0xac, 0xd1, 0x9a, 0x6a, 0x7c, 0x7f, 0xb8, 0x7e, 0x2d, 0x77, 0x62, 0xd1, 0x23, 0xa3, 0x5c, - 0x98, 0xf5, 0x55, 0xd8, 0x8a, 0x0d, 0xb5, 0x3a, 0xc0, 0x48, 0xbc, 0x24, 0x86, 0x80, 0xe1, 0x97, 0x11, 0xe3, 0x7f, - 0x1b, 0x57, 0x31, 0x3e, 0x5a, 0xd9, 0xe5, 0x08, 0xff, 0xa7, 0xb7, 0xef, 0x2f, 0x41, 0x7b, 0xe5, 0xa1, 0xba, 0x79, - 0xad, 0x72, 0x4b, 0x15, 0x13, 0xf4, 0x41, 0x6a, 0x47, 0xf5, 0xe6, 0x40, 0x8f, 0xf1, 0x5e, 0x70, 0xb8, 0x32, 0x97, - 0xcb, 0xa5, 0x09, 0x76, 0xab, 0xe6, 0x22, 0x0e, 0x88, 0x07, 0x1c, 0xa9, 0x99, 0x40, 0xe4, 0xac, 0x82, 0xc8, 0x21, - 0xe8, 0x2d, 0xcf, 0x9a, 0xf2, 0x7e, 0x1a, 0x2d, 0xbf, 0x09, 0x02, 0x59, 0x38, 0x23, 0x58, 0x35, 0x2e, 0xaf, 0x28, - 0x21, 0x06, 0x0d, 0x74, 0x4c, 0x96, 0x9f, 0xdc, 0x70, 0xab, 0x80, 0xd1, 0xcd, 0xe0, 0xee, 0x86, 0x6b, 0x1e, 0xf2, - 0xa8, 0xc3, 0xef, 0xfb, 0xa7, 0x23, 0xff, 0x56, 0x41, 0x7e, 0xd2, 0x55, 0xc1, 0x65, 0x2b, 0x60, 0x83, 0x45, 0x9a, - 0x46, 0xa1, 0x19, 0x47, 0x4b, 0xb5, 0x77, 0x4a, 0x0f, 0xa2, 0x82, 0x47, 0x8f, 0xaa, 0xf2, 0xf5, 0x30, 0xf0, 0x87, - 0x1f, 0x5d, 0xf5, 0xf1, 0xda, 0x77, 0x7b, 0x15, 0xae, 0xd1, 0xce, 0xd4, 0x1e, 0xc0, 0xaa, 0x7c, 0x13, 0x04, 0xa7, - 0x87, 0xd4, 0xa2, 0x77, 0x7a, 0x38, 0xf2, 0x6f, 0x7b, 0x52, 0x02, 0x18, 0xae, 0x1d, 0x75, 0x79, 0xa0, 0xcd, 0xdc, - 0x9e, 0x2c, 0xc1, 0xc8, 0x0d, 0x43, 0xa6, 0x15, 0x57, 0x5c, 0x88, 0x28, 0x43, 0xf0, 0x6a, 0x43, 0x14, 0x9a, 0x07, - 0x70, 0xa1, 0xfb, 0xf4, 0x49, 0xcb, 0xad, 0x4d, 0xa7, 0x52, 0x28, 0x36, 0x54, 0xe6, 0x61, 0x15, 0x03, 0xe3, 0xc9, - 0xe8, 0x9a, 0x08, 0x18, 0x17, 0xe8, 0xc6, 0x30, 0x33, 0x30, 0x8f, 0x8e, 0x37, 0x07, 0xbd, 0x22, 0xff, 0x29, 0xdd, - 0x7b, 0x87, 0x90, 0x3b, 0x5b, 0x42, 0xdc, 0xba, 0xa4, 0x59, 0xa1, 0x53, 0xc8, 0xa3, 0x01, 0x82, 0x4a, 0x04, 0xbf, - 0x43, 0xda, 0x0e, 0x2d, 0xd0, 0x21, 0x77, 0x5b, 0x1e, 0x82, 0xc7, 0xcb, 0x44, 0xb6, 0x34, 0x31, 0x2f, 0x67, 0xa5, - 0x15, 0xea, 0x54, 0xd7, 0x4b, 0xc4, 0x86, 0x3c, 0x48, 0xb6, 0x2d, 0x19, 0x68, 0xea, 0xb4, 0xd4, 0xa8, 0xd0, 0x59, - 0xf0, 0xdd, 0x93, 0xd4, 0x43, 0xcc, 0xd0, 0xae, 0x12, 0x23, 0xba, 0x2e, 0x68, 0x53, 0x42, 0x88, 0xb2, 0x13, 0x65, - 0x45, 0x98, 0x66, 0x5a, 0xf5, 0xde, 0xe3, 0x75, 0x88, 0xc4, 0x2c, 0x71, 0x7b, 0xe5, 0x7d, 0x90, 0x7a, 0x03, 0x93, - 0x36, 0xb3, 0xaa, 0x7c, 0x3d, 0x1a, 0x04, 0xf9, 0x62, 0xd3, 0x21, 0x98, 0x7a, 0xe1, 0x28, 0x60, 0x97, 0xde, 0xe0, - 0x3b, 0xac, 0xf3, 0x7a, 0x10, 0xbc, 0x82, 0x0a, 0x99, 0xda, 0x7b, 0xbc, 0x26, 0x72, 0x5d, 0x87, 0xb0, 0x33, 0xda, - 0x02, 0xd5, 0xef, 0xf0, 0xc4, 0x4a, 0x2c, 0xa6, 0xd6, 0x08, 0x2c, 0x91, 0x58, 0xc2, 0xa8, 0x65, 0xc8, 0x78, 0x62, - 0x1f, 0xd8, 0x9b, 0x0a, 0x3f, 0xb5, 0x00, 0x57, 0x24, 0x4e, 0xb0, 0xbc, 0x33, 0x65, 0x60, 0x89, 0x94, 0xbe, 0x8b, - 0x96, 0x02, 0x52, 0x3e, 0x01, 0x14, 0x88, 0xf2, 0xec, 0x7d, 0xff, 0x54, 0x56, 0xfe, 0xa0, 0x84, 0x9c, 0xfa, 0x85, - 0x5f, 0x99, 0xaa, 0x14, 0x69, 0x9e, 0xe6, 0x2b, 0xb5, 0x77, 0x7a, 0x28, 0xd7, 0xee, 0xf5, 0x3b, 0xe7, 0xd2, 0xe0, - 0xb0, 0x57, 0x71, 0x3b, 0xbe, 0x2a, 0x1e, 0xb2, 0x6b, 0x05, 0xee, 0xc2, 0x19, 0x94, 0xc0, 0x1c, 0x95, 0x9b, 0x6c, - 0x90, 0x1f, 0x48, 0x8c, 0x58, 0x10, 0x28, 0xda, 0x3d, 0x02, 0x3f, 0x46, 0x7a, 0x27, 0x5f, 0x42, 0xb2, 0xbf, 0x14, - 0xbd, 0xf5, 0xf9, 0xbf, 0xc5, 0x94, 0xa0, 0x3c, 0x9b, 0x85, 0x49, 0x14, 0xab, 0x30, 0xcc, 0x6a, 0x76, 0x24, 0x45, - 0xca, 0xca, 0x86, 0x03, 0xae, 0x25, 0xab, 0x30, 0x61, 0x87, 0xd5, 0xa6, 0xd2, 0xb8, 0xfb, 0x7a, 0xf1, 0x43, 0xe1, - 0x83, 0xa9, 0x20, 0xad, 0x1c, 0xc0, 0xed, 0x59, 0xa7, 0xae, 0x1e, 0xfb, 0xc6, 0x9f, 0x23, 0x63, 0xe0, 0x19, 0x37, - 0x9e, 0xf1, 0x43, 0x78, 0x9d, 0xd5, 0x2e, 0x5e, 0x9e, 0x31, 0xce, 0x60, 0x5d, 0x0d, 0xe2, 0x2c, 0x95, 0xef, 0x15, - 0xbe, 0xc5, 0x2d, 0x43, 0x2e, 0xbd, 0x78, 0xc2, 0x44, 0xa2, 0x36, 0xf1, 0x56, 0x48, 0x08, 0x74, 0x69, 0x5a, 0x20, - 0x08, 0xd9, 0x01, 0x37, 0xa0, 0xf3, 0xad, 0x61, 0x1a, 0x07, 0x7f, 0x62, 0x77, 0x70, 0x9d, 0x4c, 0xd2, 0x68, 0x0e, - 0x92, 0x29, 0x6f, 0xc2, 0x35, 0x0d, 0x06, 0x30, 0x35, 0xfb, 0x7c, 0xee, 0xd3, 0x27, 0x26, 0xe5, 0x0e, 0x4b, 0xa3, - 0xc9, 0x24, 0x60, 0x9a, 0x94, 0x63, 0x2c, 0xff, 0xcc, 0xd9, 0x81, 0x2d, 0xe2, 0x53, 0xeb, 0xd9, 0xb6, 0x83, 0x55, - 0x70, 0x80, 0x42, 0xa7, 0x0f, 0x88, 0x8b, 0x4c, 0xa8, 0x90, 0x09, 0xd7, 0xc4, 0xb9, 0x28, 0x0e, 0xae, 0x39, 0x8a, - 0x16, 0x83, 0x80, 0x99, 0x78, 0x1a, 0xe0, 0x93, 0xeb, 0xc1, 0x62, 0x30, 0x08, 0x28, 0x29, 0x18, 0x44, 0x59, 0x8b, - 0x12, 0x94, 0x7e, 0x66, 0x7a, 0x17, 0x39, 0xb5, 0xb4, 0x0a, 0x3e, 0x58, 0x46, 0xc2, 0x6d, 0x81, 0x3e, 0x90, 0x82, - 0xa4, 0x73, 0xf3, 0x4c, 0xbb, 0x2a, 0xdc, 0x52, 0x58, 0xa2, 0x76, 0x6b, 0x58, 0x3a, 0xf7, 0x4a, 0x7d, 0x8f, 0x33, - 0xac, 0x78, 0xe1, 0x48, 0x79, 0x45, 0x7b, 0x57, 0x35, 0x54, 0x32, 0xf0, 0xe2, 0x39, 0xe4, 0x54, 0x43, 0x7d, 0xed, - 0x7b, 0x93, 0x30, 0x4a, 0x52, 0x7f, 0xa8, 0x5e, 0x77, 0x5f, 0xfb, 0xda, 0xd5, 0x2c, 0xd5, 0xf4, 0x6b, 0xe3, 0x5b, - 0x39, 0xdb, 0x97, 0xc0, 0x94, 0x98, 0xec, 0x6b, 0x4b, 0x1d, 0xf9, 0xf4, 0xec, 0xaa, 0x27, 0x30, 0x32, 0xd6, 0xf9, - 0xd6, 0x85, 0x5a, 0x95, 0xbc, 0x61, 0x98, 0x10, 0x12, 0xf2, 0x86, 0x7d, 0xab, 0x77, 0x49, 0xd4, 0xf2, 0xcd, 0x62, - 0x8d, 0x4c, 0x43, 0x5a, 0x10, 0x5f, 0x0c, 0x75, 0x2f, 0xfc, 0x43, 0xe9, 0xf9, 0x40, 0xf6, 0x6d, 0x28, 0x91, 0xf1, - 0xfe, 0x37, 0x65, 0x0e, 0xe4, 0xf1, 0x3a, 0xcd, 0xc0, 0xb0, 0x30, 0x8c, 0x52, 0x05, 0xe2, 0xb7, 0xc1, 0x07, 0xfb, - 0x55, 0x5b, 0x68, 0xde, 0xab, 0xa6, 0x67, 0x1c, 0x0b, 0xbc, 0x44, 0x5a, 0x8a, 0xf2, 0x49, 0x08, 0x37, 0x01, 0xa1, - 0x48, 0x4b, 0xd1, 0x9a, 0xb8, 0x07, 0x1e, 0x2c, 0x5f, 0x89, 0x7f, 0x93, 0xf0, 0x7e, 0x99, 0x9e, 0x3f, 0x5e, 0x27, - 0x67, 0x82, 0xa8, 0x7f, 0x9f, 0xe0, 0x5a, 0x02, 0xbb, 0xc2, 0xa9, 0x7c, 0xa6, 0x2a, 0x67, 0x82, 0x12, 0x61, 0xdd, - 0x12, 0x7a, 0xd5, 0x04, 0xbb, 0x1b, 0x8b, 0xc8, 0xf8, 0x3c, 0xfd, 0xb8, 0x60, 0xc0, 0x2a, 0x47, 0x0f, 0x42, 0x32, - 0xe5, 0xbc, 0x55, 0x0a, 0x76, 0xd5, 0x48, 0x30, 0x00, 0x73, 0x71, 0x1e, 0xa1, 0x9f, 0xdd, 0x00, 0x23, 0x09, 0x71, - 0xca, 0xc4, 0x18, 0x8d, 0x48, 0x4e, 0x15, 0xe7, 0x87, 0xf3, 0x45, 0x8a, 0xf1, 0xe7, 0x01, 0x00, 0x96, 0xa9, 0x0a, - 0x5e, 0x12, 0x01, 0xd7, 0x17, 0x97, 0x9f, 0x4c, 0x55, 0xfc, 0xd1, 0x66, 0x19, 0x97, 0xc7, 0x00, 0x8e, 0xc3, 0x61, - 0xa0, 0xf6, 0x06, 0x1e, 0x63, 0x3e, 0x8c, 0xa1, 0x51, 0x24, 0x6f, 0xd1, 0x86, 0x68, 0xe5, 0x50, 0x83, 0x40, 0x86, - 0xd4, 0x4f, 0x57, 0x0b, 0x6a, 0x07, 0x0b, 0x31, 0xa9, 0x4b, 0xc3, 0xec, 0x83, 0x24, 0xf2, 0x0c, 0xe6, 0xce, 0x7d, - 0xbc, 0xf6, 0x72, 0x03, 0x3a, 0xf5, 0x52, 0x25, 0xeb, 0xb9, 0x3e, 0x4e, 0x43, 0x3f, 0xbb, 0x29, 0xdc, 0x59, 0x8b, - 0xf1, 0xc2, 0x96, 0xa4, 0x72, 0x05, 0xed, 0xd9, 0x5c, 0x6e, 0xb5, 0x36, 0x8f, 0xfd, 0x99, 0x17, 0xdf, 0x91, 0x91, - 0x9b, 0x21, 0x5b, 0xc2, 0xe9, 0xaa, 0x42, 0xf4, 0x80, 0x26, 0x80, 0x48, 0x83, 0xaa, 0x7c, 0x9d, 0x97, 0x31, 0x3e, - 0xda, 0xdc, 0xd2, 0x07, 0xbe, 0x75, 0xa3, 0x3e, 0x67, 0x16, 0x49, 0x19, 0xa9, 0x49, 0x57, 0x4b, 0xb6, 0x0c, 0x2f, - 0x29, 0x0f, 0x2f, 0x2c, 0x6f, 0x34, 0x1c, 0x0c, 0x51, 0x0a, 0x82, 0x1b, 0x47, 0x86, 0xa9, 0x2e, 0xeb, 0x57, 0x94, - 0xde, 0xfd, 0xae, 0xcb, 0xc1, 0x60, 0x39, 0x42, 0x58, 0x8e, 0x1a, 0x01, 0xac, 0x27, 0x56, 0x04, 0x78, 0x11, 0xe0, - 0x42, 0x62, 0xe4, 0x40, 0x28, 0x0b, 0xa6, 0x92, 0x6f, 0xa1, 0x18, 0x8e, 0x06, 0xc1, 0x4e, 0x47, 0x23, 0x76, 0xdd, - 0x08, 0x5b, 0xc5, 0xd9, 0xe9, 0x21, 0xd5, 0x26, 0xa2, 0x48, 0x95, 0x60, 0x1a, 0x62, 0x18, 0x61, 0x31, 0x0b, 0x90, - 0x06, 0xdc, 0x75, 0x8a, 0x8b, 0x8e, 0x35, 0x43, 0xe5, 0xb3, 0x73, 0x56, 0x66, 0x78, 0xb0, 0x95, 0xda, 0x3b, 0xc5, - 0xc4, 0x9e, 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xe9, 0x21, 0x3d, 0x2a, 0x95, 0x13, 0x51, 0x74, 0x22, 0xa4, 0x8e, 0x1d, - 0xde, 0xc1, 0x83, 0x8e, 0x4a, 0x92, 0xb2, 0x39, 0x94, 0x7a, 0x99, 0xaa, 0xcc, 0x38, 0x83, 0xc5, 0x63, 0xec, 0x41, - 0x00, 0x1e, 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xe6, 0xad, 0x70, 0xe4, 0xe2, 0x8d, 0xb7, 0xd2, 0x1c, 0xfe, 0xaa, 0x38, - 0x6b, 0x49, 0xf9, 0xac, 0x0d, 0xf9, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x29, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, - 0x54, 0x2c, 0xee, 0x68, 0xcb, 0xe2, 0x8e, 0x76, 0x2c, 0x6e, 0xc0, 0x17, 0x52, 0xc9, 0xa7, 0x2e, 0x46, 0x8f, 0xe9, - 0x7c, 0xf2, 0x38, 0x3f, 0xd2, 0xe1, 0xe7, 0x0c, 0xe7, 0xc9, 0x4c, 0x02, 0xb0, 0x18, 0xde, 0x32, 0x57, 0x75, 0xf3, - 0x22, 0x4d, 0xc4, 0xe6, 0xc0, 0xf3, 0x53, 0x37, 0x94, 0x24, 0x03, 0x5a, 0x50, 0x1d, 0x2f, 0xec, 0x52, 0x6c, 0x68, - 0x68, 0xd3, 0x2d, 0x23, 0x9d, 0xee, 0x18, 0xe9, 0xb0, 0x74, 0x74, 0xf9, 0xb0, 0xe9, 0x10, 0xca, 0x83, 0x82, 0x3d, - 0x08, 0x5e, 0x14, 0xb8, 0x65, 0xca, 0xfb, 0x70, 0x3b, 0x8e, 0x95, 0x76, 0xd4, 0xdc, 0x4b, 0x92, 0x65, 0x14, 0x83, - 0x19, 0x02, 0x74, 0xf3, 0xb0, 0x2d, 0x35, 0xf3, 0x43, 0x1e, 0xe1, 0x6c, 0xeb, 0x66, 0x2a, 0xde, 0xcb, 0x5b, 0xaa, - 0xd1, 0x6a, 0x51, 0x8d, 0xb9, 0x97, 0xa6, 0x2c, 0xc6, 0x49, 0xf7, 0x20, 0x15, 0xc6, 0x7f, 0xc9, 0x36, 0xab, 0xc1, - 0x21, 0x81, 0x84, 0xd5, 0x11, 0x43, 0xcf, 0x81, 0x05, 0x23, 0xbd, 0x63, 0xa8, 0xaf, 0xa5, 0x68, 0xa9, 0x71, 0x3e, - 0xf1, 0x3f, 0xe2, 0x71, 0xd5, 0x62, 0xc9, 0x9f, 0xd7, 0x39, 0xd6, 0xad, 0xb9, 0x37, 0x7a, 0x0f, 0xd6, 0x2e, 0x5a, - 0xc3, 0x00, 0xcf, 0x15, 0x39, 0x36, 0x6a, 0x4c, 0x3c, 0xe1, 0xb0, 0x40, 0x92, 0x88, 0x25, 0xb9, 0x5d, 0x30, 0x84, - 0x14, 0xf0, 0xcc, 0xf1, 0xf5, 0xba, 0x91, 0x1d, 0x4e, 0x7c, 0x7d, 0x03, 0x6b, 0x02, 0x6a, 0x0b, 0xdc, 0x5e, 0x2e, - 0x74, 0x0b, 0x0c, 0xe7, 0x58, 0x07, 0x75, 0xe8, 0x15, 0x24, 0x3d, 0xb7, 0xc5, 0x65, 0xba, 0x1f, 0x03, 0xd5, 0x02, - 0xe5, 0xe1, 0x93, 0x09, 0xfe, 0x72, 0xae, 0xb3, 0x27, 0x03, 0xfc, 0xd5, 0xb8, 0xce, 0x55, 0x55, 0x15, 0x29, 0x82, - 0x34, 0x66, 0xb5, 0x57, 0xda, 0x4f, 0x64, 0x94, 0xfd, 0x80, 0x6d, 0xc3, 0x17, 0xf8, 0xd1, 0xe3, 0x75, 0x02, 0x61, - 0x08, 0xe4, 0x31, 0x84, 0x56, 0xac, 0x67, 0xb5, 0xe5, 0x93, 0x2d, 0xe5, 0x03, 0xfd, 0x77, 0x26, 0xfc, 0xb8, 0x4b, - 0xa2, 0x82, 0xa6, 0x94, 0x65, 0x20, 0x37, 0x03, 0x3f, 0xf4, 0xe2, 0xbb, 0x1b, 0xba, 0x85, 0x68, 0x92, 0x90, 0xf7, - 0xa0, 0x10, 0x0e, 0xdc, 0x95, 0x6d, 0x40, 0x52, 0x49, 0x41, 0x75, 0xc7, 0x09, 0xbd, 0xfb, 0xa7, 0x58, 0xe2, 0xef, - 0x4a, 0xd7, 0x58, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3c, 0x5e, 0x6b, 0x6c, 0xb3, 0x9b, 0xca, 0x68, 0x2b, 0x0c, 0x24, - 0x2c, 0x0f, 0x5e, 0x89, 0x67, 0x23, 0xbf, 0x83, 0x46, 0x1e, 0x83, 0x68, 0x65, 0x3e, 0x5e, 0xa7, 0x67, 0xea, 0xcc, - 0x8b, 0x3f, 0xb2, 0x91, 0x39, 0xf4, 0xe3, 0x61, 0x00, 0xcc, 0xe3, 0x20, 0xf0, 0xc2, 0x8f, 0xfc, 0xd1, 0x8c, 0x16, - 0x29, 0x9a, 0x6d, 0xdd, 0x7b, 0x83, 0x16, 0x73, 0x42, 0x82, 0x44, 0xe4, 0x6a, 0x6b, 0x66, 0x41, 0x79, 0xdf, 0x17, - 0xd7, 0xfa, 0x82, 0x51, 0x2c, 0x6a, 0x19, 0xe0, 0x75, 0x00, 0x96, 0x64, 0x10, 0xc6, 0xc1, 0x50, 0x71, 0xbd, 0x54, - 0x43, 0x1e, 0x2a, 0xe9, 0xd1, 0xf2, 0x3c, 0xc4, 0x37, 0xd8, 0xc3, 0xaf, 0xff, 0x1c, 0x94, 0x3c, 0xe4, 0x73, 0x79, - 0x2f, 0x9f, 0x37, 0x42, 0x28, 0x35, 0xc9, 0x7d, 0xf0, 0x01, 0x1f, 0xe7, 0x0c, 0xe6, 0xf6, 0x4f, 0xcb, 0x8d, 0xbd, - 0x24, 0x59, 0xcc, 0xd8, 0x88, 0x94, 0x61, 0x67, 0x05, 0x50, 0xe5, 0x7b, 0x88, 0x0c, 0xd8, 0xdf, 0x17, 0x8d, 0x93, - 0xa3, 0x57, 0x60, 0xc6, 0x07, 0x0c, 0x65, 0x34, 0x1e, 0xab, 0x85, 0x28, 0xe0, 0x9e, 0x66, 0xce, 0xd1, 0xdf, 0x17, - 0x6f, 0xce, 0xed, 0x37, 0x79, 0xe3, 0x10, 0x18, 0x63, 0x61, 0x93, 0xc4, 0xf9, 0x62, 0x09, 0x5e, 0x31, 0xa2, 0xb1, - 0x17, 0x6e, 0x1f, 0xce, 0x55, 0x69, 0x8b, 0xcf, 0x19, 0x1b, 0x01, 0xc3, 0x6d, 0x6c, 0x94, 0xde, 0x04, 0xec, 0x96, - 0xe5, 0xf6, 0x4e, 0x9b, 0x1f, 0xab, 0x69, 0x81, 0x01, 0x59, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0xfa, 0x38, - 0x06, 0x3e, 0x72, 0xf9, 0x88, 0x55, 0x8e, 0x54, 0xdf, 0x50, 0x25, 0x00, 0xb6, 0x42, 0x76, 0xb6, 0xa5, 0xbc, 0x03, - 0x88, 0x7a, 0x0b, 0x6c, 0x86, 0xa3, 0x77, 0x20, 0x81, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0xb6, - 0xcd, 0x58, 0x9d, 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x01, 0x40, 0x5f, 0x18, 0x21, 0xae, 0xaa, 0x5d, 0x1b, 0xa5, - 0x3c, 0xf2, 0x01, 0xa6, 0x77, 0x0f, 0x59, 0x92, 0x6c, 0x9d, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, - 0xa2, 0xdc, 0xb0, 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x99, 0x71, 0x23, 0xce, 0x78, 0x32, - 0x50, 0xb9, 0x81, 0xdd, 0xb6, 0xf7, 0x4b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0xb5, 0xa0, 0x69, 0x25, 0xd4, 0xbb, 0x21, - 0x55, 0xc2, 0x0e, 0x04, 0x4c, 0x15, 0xfc, 0xca, 0xc6, 0x63, 0x36, 0x4c, 0x13, 0x5d, 0xc8, 0x98, 0xf2, 0x90, 0xea, - 0xa0, 0xb4, 0x3b, 0x70, 0xd5, 0x1f, 0x21, 0xb0, 0x8c, 0x88, 0x3c, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xfa, 0x69, 0xa2, - 0x1e, 0xcb, 0x53, 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x9a, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0xa9, - 0xe7, 0x6e, 0x54, 0xb4, 0xeb, 0xf8, 0xae, 0x9d, 0x37, 0x2d, 0xc7, 0xce, 0x54, 0x03, 0x1c, 0x9a, 0x3f, 0x56, 0xb6, - 0x31, 0x11, 0x28, 0x57, 0xbd, 0x78, 0xfb, 0xea, 0x4f, 0xe7, 0xaf, 0xf7, 0xc5, 0x08, 0xd8, 0x65, 0x13, 0xba, 0x5c, - 0x84, 0x3b, 0x3a, 0xfd, 0xf9, 0xc7, 0x87, 0x75, 0xdb, 0x70, 0x5e, 0x38, 0xaa, 0x41, 0x36, 0xe8, 0x12, 0x5e, 0x1c, - 0x46, 0xb7, 0x2c, 0xfe, 0xec, 0x69, 0x90, 0x3b, 0xaf, 0x07, 0xf7, 0xed, 0x4f, 0xe7, 0x3f, 0xee, 0x0d, 0xea, 0xb1, - 0x63, 0x03, 0x6e, 0x4f, 0xa3, 0xf9, 0x03, 0x46, 0xd7, 0x54, 0x0d, 0x75, 0x18, 0x44, 0x09, 0xdb, 0x02, 0xc1, 0xab, - 0x8b, 0xb7, 0xef, 0x71, 0xba, 0x0a, 0x16, 0x84, 0xba, 0xfa, 0xbc, 0xc1, 0xff, 0xf4, 0xee, 0xfc, 0xfd, 0x7b, 0xd5, - 0xc0, 0x94, 0xdc, 0x89, 0xdc, 0x3b, 0xdf, 0xc4, 0xf7, 0x50, 0x9c, 0xda, 0xbd, 0x4e, 0x54, 0x8d, 0x2e, 0xd2, 0xe5, - 0xd1, 0x50, 0xd9, 0xc6, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x7b, 0x8d, 0xab, 0x06, 0x1f, 0xed, 0x26, - 0xa9, 0xa5, 0x92, 0x99, 0x1f, 0xde, 0xd4, 0x94, 0x7a, 0xab, 0x9a, 0x52, 0xb8, 0x3e, 0x6e, 0xe0, 0xc7, 0x45, 0x34, - 0x93, 0xd8, 0x11, 0xb6, 0xba, 0x7f, 0xba, 0xa4, 0x3b, 0xdc, 0x67, 0x00, 0xcd, 0x53, 0xaa, 0x54, 0xa1, 0xae, 0x29, - 0xe6, 0x17, 0xaf, 0x7c, 0x6e, 0x87, 0x01, 0x58, 0xde, 0x33, 0x59, 0x0d, 0x59, 0x66, 0x55, 0xb9, 0xdf, 0x8c, 0x5b, - 0xb9, 0x15, 0x50, 0x33, 0x52, 0xdd, 0x70, 0x9a, 0x32, 0xf7, 0x46, 0x60, 0xce, 0x6e, 0x0e, 0xa2, 0x34, 0x8d, 0x66, - 0x1d, 0xc7, 0x9e, 0xaf, 0x54, 0xa5, 0x2b, 0x84, 0x1d, 0xdc, 0xda, 0xbe, 0xf3, 0xef, 0x7f, 0x55, 0xd0, 0x3c, 0x95, - 0xdf, 0xa4, 0x6c, 0x36, 0x67, 0xb1, 0x97, 0x2e, 0x62, 0x96, 0x29, 0xff, 0xfe, 0x9f, 0x57, 0x95, 0x8b, 0x7d, 0x57, - 0x6e, 0x43, 0x2c, 0xbd, 0xdc, 0xe4, 0x26, 0x88, 0x96, 0x07, 0x85, 0x5f, 0xdd, 0x3d, 0x95, 0xa7, 0xfe, 0x64, 0x9a, - 0xd7, 0x3e, 0x4b, 0x77, 0x8c, 0x4d, 0x40, 0x4f, 0xfa, 0x00, 0xe5, 0x22, 0x5a, 0x76, 0xfe, 0xfd, 0xaf, 0x5c, 0x60, - 0x73, 0xef, 0xae, 0xab, 0x07, 0xb4, 0xbc, 0xa2, 0xf5, 0x75, 0x36, 0x96, 0x18, 0xde, 0x6f, 0x2c, 0xf0, 0x46, 0x21, - 0xed, 0xca, 0x4d, 0xdd, 0xdc, 0x8e, 0x31, 0x7d, 0xe7, 0x4f, 0xa6, 0x9f, 0x3b, 0x28, 0x98, 0xd0, 0x7b, 0x47, 0x05, - 0x95, 0xbe, 0xc0, 0xb0, 0xfa, 0x9d, 0xfd, 0x17, 0xec, 0x33, 0xc7, 0x75, 0xdf, 0x90, 0xbe, 0xc4, 0x68, 0xb8, 0xe4, - 0xf6, 0x7d, 0xbf, 0x9f, 0xa7, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0xd9, 0x46, 0x09, 0x67, 0x2f, 0x3a, 0xb6, 0x4e, - 0x21, 0x7b, 0xf6, 0x98, 0x10, 0xb4, 0x71, 0xaf, 0x99, 0x8e, 0xed, 0xf8, 0x9a, 0x5c, 0xd5, 0x36, 0xbe, 0xbd, 0x81, - 0xac, 0xa1, 0x14, 0xd3, 0x99, 0xe6, 0x5a, 0x43, 0xa3, 0x1e, 0x9c, 0x65, 0xec, 0xcd, 0x49, 0x49, 0xa0, 0xa0, 0xc6, - 0x04, 0x84, 0x2e, 0x95, 0x5b, 0xf4, 0xad, 0x17, 0xdc, 0xee, 0x77, 0xa1, 0xda, 0x4e, 0xc1, 0x90, 0x34, 0xff, 0xe7, - 0x88, 0x37, 0xd2, 0xe5, 0x07, 0xd3, 0xee, 0xa5, 0x97, 0xb2, 0xf8, 0x66, 0x0a, 0x3e, 0xbd, 0x42, 0x7a, 0x00, 0xd1, - 0x72, 0x77, 0x21, 0xe5, 0x12, 0x5b, 0x5a, 0x83, 0x46, 0x0b, 0x0c, 0xf7, 0xeb, 0x70, 0xf7, 0x17, 0xc2, 0xdc, 0x9d, - 0x73, 0xf0, 0xba, 0xfc, 0xcd, 0xb0, 0xf7, 0x2e, 0xca, 0xf4, 0xff, 0xd8, 0xfb, 0xbf, 0x11, 0x7b, 0xef, 0xfc, 0xce, - 0xaf, 0x59, 0xd8, 0xff, 0x03, 0x58, 0xbe, 0xc3, 0xdc, 0x73, 0x8e, 0xe9, 0x35, 0xcd, 0x73, 0x85, 0x72, 0x55, 0xc6, - 0xab, 0x1b, 0x0a, 0x56, 0x1e, 0x52, 0x8d, 0x5b, 0x0e, 0x7a, 0x88, 0xec, 0x77, 0x1c, 0xe5, 0xdf, 0x1e, 0xd1, 0x27, - 0x94, 0x87, 0x4a, 0xc2, 0xf4, 0x9d, 0x73, 0x23, 0x29, 0x8d, 0xc4, 0x5b, 0x7a, 0x77, 0xfb, 0xe0, 0x1d, 0x01, 0xec, - 0x37, 0x4b, 0xef, 0xae, 0x0e, 0xd8, 0xad, 0xe8, 0xb5, 0xfa, 0xb1, 0x33, 0xf0, 0xe5, 0xe9, 0xa0, 0x23, 0x8f, 0xd1, - 0x4f, 0x58, 0x7a, 0x06, 0x85, 0xee, 0xe3, 0xf5, 0x41, 0xb5, 0x62, 0xd6, 0x07, 0x2f, 0x67, 0x09, 0xf0, 0xa8, 0x04, - 0xb8, 0x9f, 0xdc, 0x44, 0xe1, 0x43, 0x20, 0xff, 0x09, 0x84, 0x3f, 0xbf, 0x1a, 0x74, 0xfc, 0xdc, 0x06, 0xec, 0x58, - 0x5a, 0x05, 0x1e, 0x0b, 0xab, 0xd0, 0x77, 0xeb, 0x65, 0xf5, 0x15, 0x42, 0x8b, 0x34, 0x96, 0x11, 0xa1, 0x55, 0x40, - 0xaf, 0xa2, 0x80, 0x8e, 0xab, 0x42, 0x72, 0xfd, 0x70, 0x1c, 0x7b, 0x31, 0x1b, 0x6d, 0xbf, 0x02, 0x94, 0x2c, 0x95, - 0xef, 0xac, 0x64, 0x31, 0x9f, 0x47, 0x71, 0x9a, 0xdc, 0x60, 0x34, 0x96, 0x99, 0x0f, 0x17, 0x0a, 0xc8, 0x1b, 0x96, - 0xc7, 0xe6, 0x3d, 0xaf, 0x93, 0x6f, 0x1b, 0xcc, 0x2d, 0xa7, 0xd4, 0xe0, 0x3e, 0x36, 0x06, 0xf7, 0xd2, 0x99, 0x4a, - 0xfa, 0x8b, 0xa9, 0x95, 0xc6, 0xfe, 0x4c, 0xd3, 0x0d, 0xc7, 0xd6, 0x75, 0x21, 0x5f, 0x99, 0xba, 0xbd, 0x03, 0x8a, - 0x29, 0x3c, 0xd5, 0x21, 0x36, 0x21, 0xfa, 0xad, 0x80, 0xad, 0xdc, 0xcb, 0xc5, 0x78, 0xcc, 0x62, 0x4d, 0x04, 0x5f, - 0x84, 0xe8, 0xaf, 0x64, 0x0c, 0x08, 0xde, 0x8c, 0x1f, 0x7c, 0xb6, 0x84, 0x2c, 0x4f, 0x45, 0xf0, 0x74, 0xf0, 0xe8, - 0x24, 0x13, 0x72, 0xc8, 0x20, 0x97, 0x36, 0x1b, 0xda, 0xe8, 0xd9, 0x91, 0x31, 0x85, 0x90, 0x4b, 0x85, 0x13, 0x3c, - 0x46, 0xf3, 0xf3, 0xc3, 0xb4, 0x8d, 0x5f, 0x80, 0x0e, 0xe0, 0xf0, 0x06, 0x6e, 0xee, 0xfd, 0xa4, 0x0c, 0xf3, 0x0e, - 0xa7, 0x6e, 0x2f, 0x78, 0xee, 0x92, 0x9e, 0x07, 0xed, 0xf6, 0x5e, 0x4d, 0xbd, 0xf8, 0x55, 0x34, 0x62, 0x08, 0xe8, - 0x20, 0x8d, 0xc0, 0x27, 0x53, 0x0a, 0xb6, 0x83, 0xb1, 0x76, 0xcc, 0x52, 0xfc, 0x9d, 0x43, 0x28, 0xba, 0x91, 0x8b, - 0xdc, 0xe7, 0x8f, 0x0f, 0x0d, 0x38, 0x69, 0xf5, 0x2b, 0x2d, 0x16, 0x8d, 0x2f, 0x75, 0xed, 0x2b, 0x79, 0xb7, 0xbe, - 0xf2, 0xe2, 0xd8, 0x67, 0xb1, 0xa2, 0x7d, 0xf7, 0x8b, 0x2e, 0x6f, 0xda, 0x92, 0x42, 0x87, 0x6b, 0x99, 0x15, 0x8c, - 0x39, 0x37, 0xf6, 0x59, 0x30, 0x72, 0xd5, 0x21, 0x35, 0xcc, 0x95, 0x37, 0xcd, 0xb6, 0x6d, 0xdb, 0x5c, 0x61, 0xea, - 0xd0, 0x4f, 0x50, 0x98, 0xc2, 0x4f, 0x78, 0x28, 0x89, 0x17, 0xdb, 0xc4, 0x45, 0x6c, 0x90, 0xb3, 0x5a, 0x08, 0xdf, - 0x51, 0xd4, 0x9e, 0x87, 0xc0, 0xc6, 0xa3, 0xfb, 0x08, 0xd0, 0x1c, 0x01, 0x56, 0x01, 0x53, 0x05, 0xa0, 0xd6, 0x43, - 0x00, 0xba, 0xf4, 0x67, 0x7e, 0x38, 0x49, 0xb6, 0x42, 0x84, 0x6a, 0xd3, 0x12, 0x3c, 0x29, 0xb5, 0x50, 0x15, 0x5c, - 0xc3, 0x69, 0x14, 0x40, 0xb6, 0x21, 0x95, 0x59, 0x13, 0x4b, 0x79, 0x61, 0xdb, 0xb6, 0x61, 0x1e, 0x41, 0x5e, 0xbf, - 0xd6, 0xb1, 0x6d, 0x98, 0xf0, 0x97, 0x65, 0x59, 0x35, 0xf2, 0xd8, 0xee, 0xcc, 0x0f, 0x4d, 0x7a, 0x6c, 0xd8, 0xfb, - 0xc1, 0x7b, 0xaf, 0x55, 0x6f, 0xc2, 0x75, 0x63, 0x83, 0xdc, 0x41, 0x54, 0x1b, 0xb8, 0x49, 0xd9, 0xd6, 0xcd, 0xa2, - 0xb0, 0x4a, 0x3c, 0xea, 0x45, 0x85, 0x18, 0x0d, 0xca, 0x6f, 0x91, 0x2d, 0x8d, 0xab, 0xd9, 0x2a, 0xd4, 0xef, 0x39, - 0x58, 0x1d, 0xe5, 0x55, 0xb4, 0x08, 0x46, 0x68, 0x0e, 0x05, 0xb6, 0xcb, 0x4a, 0x61, 0x15, 0x5a, 0x49, 0x29, 0x05, - 0x19, 0xc3, 0x31, 0x9d, 0xda, 0x7b, 0x24, 0x4e, 0x51, 0xac, 0x3d, 0xc5, 0x29, 0xbe, 0xaa, 0xdb, 0x82, 0xd7, 0x4f, - 0x21, 0x6a, 0xd0, 0x1e, 0x0d, 0xf8, 0xbe, 0x80, 0xfa, 0xc1, 0x3e, 0xf5, 0xc5, 0xba, 0x5d, 0x3f, 0xa5, 0xd0, 0xb2, - 0xde, 0xa7, 0x4f, 0x07, 0xc3, 0x4f, 0x9f, 0x0e, 0x36, 0xf2, 0x71, 0x6c, 0x1f, 0x21, 0x6d, 0x0c, 0xc6, 0x03, 0x89, - 0x40, 0x74, 0x20, 0x02, 0xfa, 0x7b, 0x28, 0xef, 0x78, 0x3c, 0x26, 0x15, 0x3d, 0x0d, 0x0d, 0xfe, 0x41, 0x7a, 0x0c, - 0xb2, 0xca, 0xa4, 0x4c, 0x5d, 0x8f, 0xc4, 0x3c, 0x9f, 0x3e, 0xf1, 0xe3, 0x66, 0x8c, 0xdc, 0x61, 0x5e, 0xe4, 0xa8, - 0xc6, 0xc2, 0x0d, 0xf2, 0x47, 0x15, 0x41, 0x5e, 0x70, 0x8c, 0x59, 0x40, 0xbc, 0xf4, 0xe2, 0x50, 0x06, 0xf8, 0xc7, - 0x48, 0xe1, 0x9f, 0x55, 0x78, 0xdc, 0xd3, 0x51, 0x75, 0x35, 0xc6, 0x2e, 0xd3, 0x16, 0x84, 0x03, 0x85, 0xa5, 0x9b, - 0xd4, 0xc1, 0xa5, 0xc0, 0xf6, 0x98, 0xfc, 0x54, 0x0c, 0x10, 0xbd, 0xa8, 0xf1, 0xe4, 0x8e, 0xc4, 0xb0, 0xde, 0x79, - 0xcb, 0xce, 0x42, 0x3c, 0x9c, 0x93, 0x49, 0x7c, 0x67, 0x9c, 0x7b, 0x27, 0xcf, 0xc9, 0xb7, 0x70, 0xe2, 0x7e, 0x1b, - 0x6b, 0x73, 0x23, 0x35, 0x54, 0x41, 0x46, 0x54, 0xdd, 0x98, 0xd5, 0x85, 0x51, 0xed, 0xce, 0x78, 0x50, 0x19, 0x4d, - 0x6c, 0x85, 0x9b, 0x31, 0xfa, 0x2a, 0x84, 0xc3, 0x3b, 0x0c, 0x93, 0x5c, 0xbc, 0x27, 0x50, 0x6e, 0x78, 0x8e, 0xbd, - 0x91, 0xfc, 0x0a, 0x16, 0x5c, 0x35, 0xc6, 0xba, 0x41, 0x3e, 0x00, 0x93, 0x2f, 0x69, 0xee, 0x4f, 0x91, 0x93, 0x67, - 0x52, 0x50, 0x57, 0xe1, 0x00, 0x70, 0x53, 0x71, 0x00, 0xa8, 0x99, 0x4f, 0x25, 0x66, 0xc9, 0x3c, 0x0a, 0xe1, 0xae, - 0x78, 0x53, 0x78, 0x75, 0xdd, 0x6c, 0x7a, 0x75, 0xd5, 0x34, 0xc5, 0x37, 0xd4, 0x0e, 0x54, 0xd2, 0x97, 0x7f, 0xa9, - 0x58, 0xe8, 0x0b, 0x52, 0x8f, 0xb9, 0xc8, 0xcf, 0xb7, 0xf9, 0x6f, 0x7f, 0x7f, 0xbf, 0xff, 0xf6, 0xc5, 0x5e, 0xfe, - 0xdb, 0xdf, 0x7f, 0x71, 0xff, 0xed, 0x73, 0xd9, 0x7f, 0x1b, 0x48, 0xf0, 0x39, 0xdb, 0xcb, 0x5d, 0x56, 0xb8, 0xb4, - 0x44, 0xcb, 0xc4, 0x75, 0xb8, 0x66, 0x2d, 0x19, 0x4e, 0x19, 0x98, 0x2a, 0x70, 0x56, 0x37, 0x88, 0x26, 0xe0, 0xd5, - 0xba, 0xdd, 0x6f, 0xf5, 0x4b, 0x79, 0xad, 0x06, 0xd1, 0x44, 0x95, 0xb2, 0xb1, 0x85, 0x22, 0x1b, 0x1b, 0x44, 0xa0, - 0xfb, 0xfb, 0xca, 0x79, 0x79, 0xe5, 0x74, 0x9b, 0x0e, 0x44, 0x33, 0x05, 0xed, 0x33, 0x16, 0xd8, 0xdd, 0x66, 0x13, - 0x0a, 0x96, 0x52, 0x41, 0x03, 0x0a, 0x7c, 0xa9, 0xa0, 0x05, 0x05, 0x43, 0xa9, 0xe0, 0x18, 0x0a, 0x46, 0x52, 0xc1, - 0x09, 0x14, 0xdc, 0xaa, 0xd9, 0x55, 0x98, 0x7b, 0xa7, 0x9f, 0xe8, 0xd7, 0xa5, 0x44, 0x9c, 0xb9, 0xa9, 0x84, 0xa8, - 0x72, 0x62, 0x88, 0xac, 0x10, 0xe6, 0x91, 0xce, 0x79, 0xb4, 0xfe, 0x57, 0x7d, 0xc0, 0xbc, 0x60, 0x39, 0x62, 0x80, - 0xdd, 0x0d, 0xd5, 0x6c, 0x8a, 0xd7, 0x6a, 0x27, 0xf7, 0xe6, 0xb6, 0x8d, 0x86, 0xf0, 0x8e, 0xee, 0x60, 0xac, 0x0e, - 0x51, 0xb9, 0xf5, 0x7c, 0x9a, 0x87, 0x88, 0x5e, 0xb8, 0x45, 0xc8, 0x9b, 0x26, 0x24, 0xca, 0xe1, 0xbc, 0x1a, 0xd3, - 0xc0, 0x5e, 0x06, 0x22, 0x9a, 0x88, 0x53, 0x24, 0x3e, 0xa0, 0xa0, 0xcb, 0x7b, 0xd7, 0x2b, 0x78, 0x38, 0x1e, 0x50, - 0x9d, 0xa0, 0x9f, 0xe5, 0x71, 0xaa, 0x49, 0x97, 0xba, 0x30, 0x52, 0x6f, 0xd2, 0x99, 0x1a, 0x64, 0x48, 0xd5, 0x99, - 0x40, 0xe2, 0x91, 0xb3, 0x51, 0x67, 0x6e, 0x2c, 0xa7, 0x2c, 0xec, 0x8c, 0xb9, 0xab, 0x21, 0xac, 0x3f, 0x79, 0x92, - 0xcc, 0x74, 0xe1, 0x02, 0x85, 0x7b, 0xa2, 0x78, 0x4b, 0x50, 0x9a, 0xf9, 0x56, 0x2a, 0xbc, 0x77, 0x34, 0xd9, 0xc8, - 0xea, 0x4b, 0xf8, 0x5a, 0xbc, 0x66, 0x83, 0xc5, 0x44, 0xb9, 0x88, 0x26, 0xf7, 0xfa, 0x55, 0xc8, 0xaf, 0x00, 0x4a, - 0x95, 0xac, 0x49, 0x4d, 0xb1, 0xbd, 0xf9, 0xb7, 0xe8, 0x31, 0x2b, 0xd7, 0x4f, 0x01, 0x36, 0x25, 0x25, 0xb6, 0x01, - 0xbe, 0x03, 0xb3, 0x2d, 0x79, 0x2e, 0x5c, 0xc0, 0xfc, 0x49, 0xcf, 0x97, 0x9e, 0x04, 0x4f, 0xef, 0x07, 0x96, 0x24, - 0xde, 0x84, 0xc9, 0xa8, 0xa5, 0xd4, 0x39, 0x60, 0xc1, 0x5c, 0x9d, 0x8c, 0x13, 0x08, 0x8c, 0xbd, 0xbf, 0xe1, 0x8f, - 0x02, 0x6e, 0xb2, 0xe0, 0xa7, 0x05, 0x8b, 0x56, 0x38, 0x6f, 0xf8, 0x16, 0x2c, 0x4f, 0xd9, 0x8f, 0x02, 0x90, 0xc8, - 0x2d, 0x0b, 0xaa, 0x85, 0xa9, 0x37, 0xa9, 0x16, 0xd1, 0x5a, 0x67, 0x25, 0xb4, 0xa7, 0x97, 0x1e, 0x05, 0x2e, 0xfc, - 0x0c, 0xbb, 0xfc, 0x20, 0x9a, 0xfc, 0xa6, 0x46, 0xf9, 0x3b, 0x9c, 0x29, 0x7e, 0x08, 0x8d, 0x30, 0xed, 0x5b, 0x38, - 0xc7, 0x8a, 0x05, 0x53, 0xd8, 0x09, 0xd3, 0xa9, 0x89, 0xe1, 0xe3, 0xb4, 0x46, 0xa8, 0x1b, 0x16, 0xae, 0xed, 0xba, - 0x1a, 0x34, 0xb3, 0x13, 0x4f, 0x06, 0x9e, 0xe6, 0x34, 0x4e, 0x0c, 0xf1, 0xc7, 0xb2, 0x5b, 0x7a, 0x86, 0x3d, 0x28, - 0x23, 0xff, 0x76, 0x3d, 0x8e, 0xc2, 0xd4, 0x1c, 0x7b, 0x33, 0x3f, 0xb8, 0xeb, 0xcc, 0xa2, 0x30, 0x4a, 0xe6, 0xde, - 0x90, 0x75, 0x25, 0x7e, 0x14, 0xc3, 0x31, 0xf3, 0x88, 0x80, 0x8e, 0xd5, 0x88, 0xd9, 0x8c, 0x5a, 0xe7, 0xd1, 0x96, - 0xc7, 0x01, 0x5b, 0x65, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, 0x96, 0x99, 0x87, 0x72, 0x86, - 0x04, 0x06, 0x5d, 0x2e, 0x75, 0xec, 0x58, 0x8d, 0x56, 0xcc, 0x66, 0x8a, 0xd5, 0xda, 0xda, 0x79, 0x1c, 0x2d, 0x7b, - 0x00, 0x2d, 0x36, 0x36, 0x13, 0x16, 0x8c, 0xf1, 0x8d, 0x89, 0xd1, 0xa3, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, - 0x6c, 0xd6, 0x85, 0xd7, 0x9d, 0x86, 0x62, 0x4b, 0xfc, 0xf4, 0x89, 0x3d, 0x97, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, - 0x75, 0x47, 0xb1, 0xbb, 0xa0, 0x3f, 0x1e, 0x07, 0xd1, 0xb2, 0x33, 0xf5, 0x47, 0x23, 0x16, 0x76, 0x11, 0xe6, 0xbc, - 0x90, 0x05, 0x81, 0x3f, 0x4f, 0xfc, 0xa4, 0x3b, 0xf3, 0x56, 0xbc, 0xd7, 0xa3, 0x6d, 0xbd, 0x36, 0x79, 0xaf, 0xcd, - 0xbd, 0x7b, 0x95, 0xba, 0x81, 0x48, 0x55, 0xd4, 0x0f, 0x07, 0xad, 0xa5, 0xd8, 0x95, 0x71, 0xee, 0xdd, 0xeb, 0x3c, - 0x66, 0xeb, 0x99, 0x17, 0x4f, 0xfc, 0xb0, 0x63, 0x67, 0xd6, 0xed, 0x9a, 0x36, 0xc6, 0xa3, 0x76, 0xbb, 0x9d, 0x59, - 0x23, 0xf1, 0x64, 0x8f, 0x46, 0x99, 0x35, 0x14, 0x4f, 0xe3, 0xb1, 0x6d, 0x8f, 0xc7, 0x99, 0xe5, 0x8b, 0x82, 0x66, - 0x63, 0x38, 0x6a, 0x36, 0x32, 0x6b, 0x29, 0xd5, 0xc8, 0x2c, 0xc6, 0x9f, 0x62, 0x36, 0xea, 0xe2, 0x46, 0xe2, 0x3e, - 0xcf, 0x27, 0xb6, 0x9d, 0x21, 0x06, 0xb8, 0x2a, 0xe1, 0x26, 0x34, 0x5d, 0xb9, 0x5e, 0xef, 0x5d, 0x53, 0x29, 0x3e, - 0x37, 0x1c, 0xd6, 0xd6, 0x1b, 0x79, 0xf1, 0xc7, 0x6b, 0x45, 0x1a, 0x85, 0xe7, 0x51, 0xb5, 0xb5, 0x98, 0x06, 0x73, - 0xd5, 0x81, 0xb4, 0x1c, 0xdd, 0x41, 0x14, 0xc3, 0x99, 0x8d, 0xbd, 0x91, 0xbf, 0x48, 0x3a, 0x4e, 0x63, 0xbe, 0x12, - 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0x3a, 0x49, 0x14, 0xf8, 0x23, 0x51, 0xb4, 0xed, 0x2c, 0x39, 0x0d, 0xbd, - 0x8b, 0xfc, 0xab, 0x8f, 0xa1, 0x95, 0xbd, 0x20, 0x50, 0xac, 0x66, 0xa2, 0x30, 0x2f, 0x41, 0x73, 0x39, 0xc5, 0x4e, - 0x68, 0x5e, 0x30, 0x00, 0xad, 0x73, 0x34, 0x5f, 0xe5, 0x7b, 0xde, 0x39, 0x9e, 0xaf, 0xb2, 0xaf, 0x67, 0x6c, 0xe4, - 0x7b, 0x8a, 0x56, 0xec, 0x26, 0xc7, 0x06, 0x93, 0x3a, 0x7d, 0xbd, 0x65, 0x9b, 0x8a, 0x63, 0x01, 0xe9, 0x8b, 0x0e, - 0xfc, 0x19, 0xc8, 0x61, 0xbc, 0x30, 0xcd, 0xb2, 0xfe, 0x75, 0x96, 0x75, 0x2f, 0x7c, 0xed, 0xea, 0xaf, 0x1a, 0xd1, - 0x42, 0x32, 0x41, 0xcd, 0xf4, 0x6b, 0xe3, 0x9c, 0xc9, 0xee, 0x32, 0x40, 0xc6, 0xd0, 0x55, 0x46, 0xae, 0x4c, 0xf4, - 0x76, 0xb3, 0x32, 0x4d, 0x72, 0x5e, 0x9d, 0xbc, 0x6f, 0xca, 0x55, 0x90, 0x02, 0x41, 0x85, 0x73, 0xe6, 0x5e, 0x48, - 0xbe, 0x37, 0xc0, 0xf4, 0x60, 0x65, 0x8a, 0x1d, 0xf4, 0x7a, 0x1b, 0xef, 0x79, 0x79, 0x3f, 0xef, 0xf9, 0xb7, 0x74, - 0x1f, 0xde, 0xf3, 0xf2, 0x8b, 0xf3, 0x9e, 0xaf, 0x37, 0x63, 0x07, 0x5d, 0x46, 0xae, 0x9a, 0x1b, 0x4c, 0x02, 0x69, - 0x8a, 0x29, 0x2a, 0xff, 0xeb, 0xf4, 0xd7, 0x06, 0x71, 0x11, 0xbd, 0x21, 0x51, 0xe0, 0x7c, 0x2a, 0x88, 0x59, 0xdf, - 0x86, 0xee, 0x9f, 0x62, 0xf9, 0x79, 0x3c, 0x76, 0x5f, 0x47, 0x52, 0x41, 0xfe, 0xc4, 0x7d, 0x49, 0x4a, 0x11, 0x94, - 0xe9, 0x4d, 0xee, 0xed, 0x03, 0x39, 0xa6, 0x21, 0x00, 0x2b, 0xb9, 0x76, 0x8f, 0x72, 0x9f, 0xbb, 0x6e, 0x19, 0x04, - 0x2d, 0x77, 0x72, 0x15, 0x61, 0xb6, 0x36, 0x2c, 0xa3, 0x26, 0x4c, 0xc8, 0x00, 0x5e, 0xde, 0x7d, 0x3f, 0xd2, 0x2e, - 0x23, 0x3d, 0xf3, 0x93, 0xb7, 0xd5, 0x20, 0x57, 0x42, 0xcf, 0x25, 0x0f, 0x27, 0xe3, 0x7e, 0x73, 0x52, 0x2c, 0x5b, - 0x7c, 0x4d, 0xcd, 0xcf, 0x4a, 0x23, 0xed, 0xc8, 0x0d, 0xbb, 0x14, 0xd9, 0x7b, 0x83, 0x18, 0xf3, 0x60, 0x30, 0x6b, - 0xce, 0xe5, 0xad, 0xf1, 0x19, 0x62, 0x83, 0x8e, 0xa8, 0xb9, 0x3f, 0xca, 0x32, 0xbd, 0x2b, 0x26, 0x42, 0x22, 0xb4, - 0xec, 0x3e, 0x26, 0x2e, 0x29, 0x84, 0x40, 0x5c, 0xe2, 0x43, 0xd6, 0xcc, 0x97, 0xe0, 0x1f, 0xc0, 0x6d, 0x9f, 0xf9, - 0x9c, 0xa9, 0x0a, 0x4d, 0x1f, 0xf9, 0x8d, 0x48, 0x03, 0x02, 0x83, 0x76, 0xd9, 0xdb, 0xaa, 0xb4, 0x20, 0x9b, 0x8e, - 0xad, 0x34, 0x39, 0xe8, 0xe0, 0x00, 0x91, 0x7c, 0x85, 0x58, 0x88, 0xd0, 0x0e, 0xaf, 0x83, 0x0f, 0x99, 0x9a, 0xf3, - 0x7e, 0xb8, 0xfd, 0x7a, 0xa7, 0x87, 0xd0, 0xa0, 0x57, 0x51, 0xba, 0xdd, 0xe3, 0x97, 0x09, 0xac, 0x44, 0xb2, 0x34, - 0xac, 0x64, 0xa9, 0x3c, 0x5b, 0x8b, 0x28, 0xd8, 0xa9, 0x37, 0x37, 0x41, 0xcb, 0x83, 0xb8, 0x97, 0x63, 0x3c, 0x29, - 0xe0, 0x76, 0x77, 0x91, 0x00, 0x6e, 0x44, 0x39, 0x0a, 0xe2, 0x9f, 0xee, 0x70, 0x11, 0x27, 0x51, 0xdc, 0x99, 0x47, - 0x7e, 0x98, 0xb2, 0x38, 0x23, 0xc1, 0x0a, 0xce, 0x8f, 0x98, 0x9e, 0xeb, 0x75, 0x34, 0xf7, 0x86, 0x7e, 0x7a, 0xd7, - 0xb1, 0x39, 0x4b, 0x61, 0x77, 0x39, 0x77, 0x60, 0xd7, 0xd6, 0xef, 0xf0, 0xd9, 0x7c, 0x8e, 0x8c, 0x5f, 0xbc, 0xc9, - 0xce, 0xc8, 0xdb, 0xbc, 0x2b, 0xbd, 0xa5, 0x38, 0xe0, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x01, 0x2c, 0x0f, 0x4b, 0x6d, - 0x8f, 0xd8, 0xc4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0xd5, 0xd2, 0x15, 0xbb, 0xbe, 0x18, 0x38, 0x1e, 0x7d, - 0x1f, 0xc8, 0x3a, 0xde, 0x38, 0x65, 0xb1, 0xb1, 0x4f, 0xcd, 0x01, 0x1b, 0x47, 0x31, 0xa3, 0x9c, 0x71, 0x4e, 0x7b, - 0xbe, 0xda, 0xbf, 0xfb, 0xdd, 0xc3, 0xaf, 0xef, 0x27, 0x8c, 0x52, 0x4d, 0x74, 0xa6, 0xdf, 0xd3, 0xdb, 0x26, 0x3d, - 0x03, 0xd6, 0x90, 0x66, 0x7e, 0x48, 0x52, 0x10, 0x88, 0xf7, 0x55, 0x9b, 0x9a, 0x63, 0x1e, 0x71, 0x9a, 0x17, 0xb3, - 0xc0, 0x4b, 0xfd, 0x5b, 0xc1, 0x33, 0x36, 0x8f, 0xe7, 0x2b, 0xb1, 0xc6, 0x48, 0xf0, 0x1e, 0xb0, 0x48, 0x15, 0x50, - 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xba, 0x1b, 0xa3, 0x11, 0xd1, 0xaa, 0x2b, 0x94, 0xbe, 0x35, 0x5f, 0xc9, 0x24, - 0xba, 0x68, 0x96, 0x53, 0xea, 0x6a, 0x9a, 0x91, 0x99, 0x3f, 0x1a, 0x05, 0x2c, 0x2b, 0x2d, 0x74, 0x79, 0x2d, 0xa5, - 0xc9, 0xc9, 0xe7, 0xc1, 0x1b, 0x24, 0x51, 0xb0, 0x48, 0x59, 0xfd, 0x74, 0x09, 0x89, 0x6e, 0x31, 0x39, 0xf8, 0xbb, - 0x0c, 0x6b, 0x0b, 0xd8, 0x6d, 0xd8, 0x26, 0x76, 0x17, 0xb2, 0x0a, 0x9a, 0xcd, 0x32, 0xe8, 0xf0, 0x2a, 0x07, 0xda, - 0xa8, 0x19, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0xcf, 0xac, 0x96, 0x17, 0x65, 0xe5, 0xc1, - 0xfc, 0x36, 0x67, 0xec, 0x45, 0xfd, 0x19, 0x7b, 0x21, 0xce, 0xd8, 0xee, 0x9d, 0xf9, 0x68, 0xec, 0xc0, 0x7f, 0xdd, - 0x62, 0x40, 0x1d, 0x5b, 0x69, 0xce, 0x57, 0x8a, 0x33, 0x5f, 0x29, 0x66, 0x63, 0xbe, 0x52, 0xb0, 0x6b, 0x74, 0x6f, - 0x31, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf4, 0xca, 0x39, 0x82, 0x77, 0xd0, 0xaa, 0xb5, 0xf9, - 0xae, 0xb1, 0xfb, 0xa8, 0xd3, 0x59, 0x12, 0x48, 0x5b, 0xb7, 0x52, 0x6f, 0x30, 0x00, 0x51, 0x66, 0x34, 0x5c, 0x24, - 0xff, 0xe4, 0xf0, 0xf3, 0x49, 0xdc, 0x89, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0x28, 0xbc, 0x65, 0xa2, 0x87, 0x75, - 0xbe, 0x4e, 0x1d, 0x4a, 0x81, 0xd8, 0xb0, 0x8e, 0x6a, 0x36, 0x79, 0xfd, 0x44, 0xff, 0x66, 0xab, 0xb4, 0x1d, 0xc5, - 0x7c, 0xc6, 0xb4, 0xec, 0x9c, 0x8e, 0x87, 0xcf, 0x06, 0x5f, 0x4d, 0xbb, 0x5d, 0x0f, 0xee, 0x95, 0xf8, 0xd2, 0xb5, - 0x20, 0x2a, 0x9c, 0x6e, 0xf1, 0x50, 0x1c, 0xbb, 0x7b, 0xdd, 0xb6, 0x47, 0x36, 0x7a, 0xdd, 0x41, 0x10, 0x8a, 0xba, - 0x7b, 0x62, 0xf9, 0x47, 0x2f, 0x8e, 0xe0, 0x3f, 0xe2, 0xea, 0xff, 0x96, 0xd6, 0x31, 0xea, 0xaf, 0xd3, 0x12, 0xa3, - 0x4e, 0xac, 0x12, 0x32, 0xe2, 0xfb, 0xd7, 0x1f, 0x8f, 0x1f, 0xd6, 0x60, 0xef, 0xda, 0xe4, 0x19, 0x56, 0xad, 0xfd, - 0x32, 0x8a, 0x02, 0xe6, 0x85, 0x9b, 0xd5, 0xc5, 0xf4, 0x90, 0x9b, 0x7f, 0xea, 0x42, 0x23, 0x71, 0x8f, 0x20, 0xa7, - 0x04, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x62, 0xdb, 0x55, 0xe2, 0xdd, 0xfd, 0x57, 0x89, 0x3f, 0xee, 0x75, 0x95, 0x78, - 0xf7, 0xc5, 0xaf, 0x12, 0x17, 0x9b, 0x57, 0x89, 0x8b, 0x48, 0xb8, 0x03, 0x1b, 0x6f, 0x16, 0xfc, 0xe7, 0x07, 0xb2, - 0xf7, 0x7d, 0x17, 0xb9, 0x2d, 0x9b, 0xd2, 0x1a, 0x5e, 0xfe, 0xea, 0x8b, 0x05, 0x6e, 0xc4, 0x77, 0xe8, 0x1d, 0x57, - 0x5c, 0x2d, 0x38, 0x66, 0xc7, 0xef, 0x48, 0xc5, 0x41, 0x14, 0x4e, 0x7e, 0x02, 0x7b, 0x6f, 0x10, 0x07, 0xc6, 0xd2, - 0x0b, 0x3f, 0xf9, 0x29, 0x9a, 0x2f, 0xe6, 0xa8, 0xa8, 0xfa, 0xe0, 0x27, 0xfe, 0x20, 0x60, 0x79, 0x1c, 0x49, 0xd2, - 0xba, 0x72, 0xd9, 0x3a, 0x28, 0x5e, 0xc5, 0x4f, 0x6f, 0x25, 0x7e, 0xa2, 0x8b, 0x2d, 0xff, 0x4d, 0x6e, 0x82, 0x6a, - 0xfd, 0x45, 0x44, 0x58, 0x88, 0x49, 0x40, 0x3f, 0xfc, 0x32, 0x72, 0x11, 0xe9, 0x35, 0xa3, 0x14, 0xee, 0x1b, 0x5b, - 0xfb, 0x61, 0xd5, 0x7e, 0xde, 0x2c, 0x74, 0x23, 0x4f, 0xb3, 0xb1, 0x29, 0xce, 0x9f, 0x45, 0x8b, 0x84, 0x8d, 0xa2, - 0x65, 0xa8, 0x1a, 0x21, 0xd7, 0xab, 0x46, 0x28, 0x53, 0xcf, 0xdb, 0x94, 0x15, 0x8e, 0xaa, 0x35, 0x87, 0x39, 0x34, - 0x49, 0x83, 0x6d, 0xe2, 0x10, 0x55, 0x11, 0xb2, 0xa9, 0x7b, 0xa0, 0x69, 0x91, 0xfb, 0xb0, 0x96, 0xc2, 0xf3, 0x24, - 0xb2, 0xb8, 0x54, 0x38, 0xd1, 0x42, 0x21, 0x5c, 0x14, 0xb1, 0xae, 0x6b, 0x16, 0x8e, 0xbf, 0xa1, 0x20, 0x91, 0xc5, - 0x5b, 0xd0, 0x55, 0x65, 0x0b, 0xbe, 0x1e, 0x3c, 0xf2, 0x33, 0x3d, 0xbe, 0x92, 0xa6, 0xf1, 0xed, 0x2d, 0x8b, 0x03, - 0xef, 0x4e, 0xd3, 0xb3, 0x28, 0xfc, 0x01, 0x26, 0xe0, 0x75, 0xb4, 0x0c, 0xe5, 0x0a, 0x98, 0x90, 0xbd, 0x66, 0x2f, - 0xd5, 0xc6, 0x28, 0x87, 0x98, 0x1d, 0x12, 0x04, 0xbe, 0x35, 0xf7, 0x26, 0xec, 0x2f, 0x06, 0xfd, 0xfb, 0x57, 0x3d, - 0x33, 0xde, 0x45, 0xf9, 0x87, 0x7e, 0x9e, 0xef, 0xf1, 0x99, 0x27, 0x4f, 0x0e, 0xb6, 0x0f, 0x5b, 0x1b, 0x06, 0xcc, - 0x8b, 0x05, 0x14, 0x35, 0xad, 0xf5, 0xad, 0xa7, 0x00, 0xa0, 0xb8, 0x8c, 0x16, 0xc3, 0x29, 0xfa, 0xed, 0x7e, 0xb9, - 0xf1, 0xa6, 0xd0, 0x27, 0x4b, 0xae, 0xec, 0xeb, 0x7c, 0xe8, 0x95, 0xa2, 0x62, 0x16, 0xf0, 0xfb, 0xe7, 0x90, 0x64, - 0xeb, 0x3f, 0x38, 0x0d, 0x9b, 0xbb, 0x26, 0x0f, 0xf9, 0xf5, 0xa0, 0xcd, 0xdb, 0xf5, 0x21, 0x2a, 0x0f, 0x85, 0xaf, - 0x16, 0x4a, 0xba, 0x7a, 0x24, 0x93, 0x55, 0x27, 0x4d, 0x4e, 0x15, 0xb3, 0x2d, 0x0b, 0x8e, 0xf8, 0x0a, 0xb3, 0x4a, - 0x56, 0x23, 0x06, 0xe3, 0xd8, 0xaa, 0x82, 0x64, 0xb8, 0x37, 0x05, 0x43, 0xf4, 0x55, 0x7d, 0x37, 0xf3, 0x43, 0x03, - 0x33, 0xbd, 0x6e, 0xbe, 0xf1, 0x56, 0x90, 0xeb, 0x10, 0x90, 0x5b, 0xf5, 0x15, 0x14, 0x1a, 0x72, 0xb4, 0x20, 0x6f, - 0x34, 0xd2, 0xd4, 0xda, 0x99, 0x10, 0xda, 0xc0, 0xfe, 0x57, 0x8a, 0xa2, 0x28, 0xf9, 0x35, 0x42, 0xc9, 0xef, 0x11, - 0x58, 0x8e, 0xd7, 0x01, 0xd0, 0x96, 0x64, 0xf3, 0x15, 0x95, 0xc0, 0xcd, 0x00, 0xed, 0xa7, 0x45, 0x01, 0x4f, 0xe7, - 0x03, 0xc6, 0x2d, 0x54, 0x20, 0x2e, 0xf4, 0xa0, 0xfa, 0xf6, 0x62, 0xc8, 0xfa, 0xd7, 0x51, 0xf0, 0xc2, 0x8e, 0x6f, - 0xb9, 0x24, 0x58, 0xb1, 0xe9, 0xb1, 0xdf, 0x65, 0xf5, 0x79, 0x5f, 0x42, 0x09, 0x0b, 0x82, 0xd6, 0xa1, 0x92, 0xc6, - 0xd1, 0x60, 0x35, 0xb8, 0x11, 0xef, 0x45, 0xab, 0x74, 0xc6, 0xc2, 0x85, 0x6a, 0x80, 0xd5, 0x09, 0xe6, 0xe1, 0x81, - 0x3a, 0xaf, 0x89, 0xd9, 0x02, 0x6c, 0x53, 0xdf, 0x72, 0x4a, 0xb4, 0x50, 0x98, 0xaa, 0x78, 0xc6, 0x90, 0x07, 0xc0, - 0x49, 0x38, 0x6e, 0xab, 0x52, 0x08, 0xbe, 0xa4, 0x51, 0x19, 0x9b, 0xf3, 0x90, 0x57, 0xc8, 0x29, 0x90, 0x8d, 0x18, - 0x17, 0x17, 0x89, 0x69, 0xd7, 0xbc, 0xea, 0xa2, 0xe5, 0x1a, 0x19, 0xaf, 0x22, 0x28, 0x8a, 0xf5, 0xcd, 0x6e, 0x38, - 0x9c, 0x90, 0x7c, 0x60, 0x6b, 0x3f, 0xc3, 0x8d, 0x7e, 0xb6, 0x0c, 0xfa, 0x23, 0xbb, 0x23, 0x42, 0x42, 0x53, 0xf5, - 0x91, 0xdd, 0x81, 0x71, 0xf8, 0x39, 0x48, 0x53, 0xd4, 0x1d, 0xe8, 0xda, 0x80, 0x74, 0xbe, 0x43, 0x48, 0x48, 0xb1, - 0xe3, 0x00, 0xd9, 0xd9, 0x0e, 0x2c, 0x8e, 0x53, 0x1c, 0x1a, 0x49, 0x57, 0x1c, 0x62, 0x1e, 0xb1, 0x40, 0xab, 0x9d, - 0x63, 0xb3, 0xe6, 0x68, 0xe8, 0xcf, 0x1c, 0xdb, 0x3e, 0xdc, 0xa8, 0x0f, 0x82, 0xec, 0xba, 0xda, 0xba, 0x91, 0xba, - 0x8e, 0x6d, 0xfa, 0xcf, 0xac, 0x46, 0x77, 0x83, 0x46, 0x4b, 0xf9, 0xa2, 0xfa, 0x28, 0xfe, 0xea, 0x3d, 0x5e, 0x6b, - 0x1b, 0x07, 0x52, 0xaf, 0x46, 0x00, 0x40, 0xd8, 0x32, 0x2e, 0xff, 0xea, 0x6f, 0x92, 0x7e, 0xca, 0x56, 0x45, 0xb9, - 0xcb, 0xfb, 0x90, 0xf1, 0x50, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x7e, 0x57, 0x60, - 0x14, 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0x6e, 0x35, 0x56, 0x68, 0xf4, 0x76, 0x72, - 0x0b, 0xd8, 0xff, 0x16, 0xf2, 0x69, 0x0d, 0x20, 0xc6, 0x23, 0xd4, 0x80, 0xfc, 0xa8, 0xf7, 0x76, 0x08, 0x21, 0x79, - 0xe5, 0xee, 0xca, 0x44, 0x72, 0xff, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x9e, 0xdc, 0x3d, 0xb0, 0x4b, - 0x16, 0x8e, 0xca, 0x1d, 0x56, 0xe8, 0xd7, 0xfe, 0xdd, 0x95, 0x30, 0x0a, 0x24, 0x0e, 0x8e, 0x6a, 0x30, 0x4a, 0x16, - 0x85, 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x7b, 0x71, 0x31, 0xd8, 0x80, 0xb2, 0x7e, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0x64, - 0xa7, 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0xb7, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x6f, 0x6a, - 0x5f, 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, - 0x98, 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x6a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, - 0xb7, 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x51, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, - 0xbf, 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, - 0x24, 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, - 0x6f, 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, - 0xe7, 0x36, 0x10, 0x08, 0x64, 0x4d, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x13, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, - 0x49, 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x25, 0x09, 0x42, 0xc7, 0x56, 0xec, 0x6e, 0x0d, 0x03, 0x80, 0xf4, - 0xbf, 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xdd, - 0xfc, 0x26, 0xc9, 0x7b, 0xd6, 0x3c, 0x26, 0x48, 0x59, 0x9c, 0xcf, 0x6b, 0x74, 0x04, 0x1c, 0x7c, 0x97, 0xc5, 0x8b, - 0x10, 0x53, 0xdd, 0x9a, 0x69, 0xec, 0x0d, 0x3f, 0xae, 0xa5, 0xef, 0x71, 0x91, 0x28, 0x88, 0x8b, 0xcb, 0x4a, 0x85, - 0xae, 0x87, 0x99, 0xa1, 0x58, 0xc7, 0x6a, 0x24, 0x92, 0xa0, 0xa6, 0xf3, 0xc8, 0x6e, 0x7a, 0x2f, 0xc6, 0x47, 0x15, - 0xf9, 0x69, 0xa3, 0x55, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa2, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, - 0x66, 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x8d, 0x92, 0x6d, 0x60, 0x8d, 0xfd, - 0x20, 0x30, 0x03, 0x70, 0x63, 0x58, 0x7f, 0xd6, 0xf0, 0xb0, 0x9f, 0x05, 0xe4, 0x24, 0xfc, 0x8c, 0x7e, 0xca, 0x3b, - 0x25, 0x9d, 0x2e, 0x66, 0x83, 0xb5, 0x2c, 0x28, 0x97, 0xe4, 0xe7, 0x9b, 0x32, 0x73, 0xf9, 0xb3, 0xe3, 0xf1, 0xb8, - 0x2c, 0x35, 0xb6, 0x95, 0x23, 0x94, 0xfc, 0x3e, 0xb2, 0x6d, 0xbb, 0x3a, 0xbf, 0xdb, 0x0e, 0x0a, 0x1d, 0x0c, 0x13, - 0x85, 0xf0, 0xed, 0xfb, 0xf7, 0xd4, 0xef, 0x04, 0x2d, 0x75, 0xb5, 0xed, 0x3c, 0xd2, 0x56, 0xfb, 0xaf, 0x00, 0x05, - 0x51, 0xc3, 0x7d, 0xc7, 0x7f, 0x73, 0xaf, 0xec, 0xe8, 0xa9, 0x7a, 0x80, 0x1f, 0xd6, 0xf8, 0x9e, 0xbd, 0xbe, 0x47, - 0xd3, 0x6d, 0xdb, 0x3b, 0xb3, 0x0a, 0xb2, 0x5b, 0xb2, 0x59, 0xea, 0x92, 0xa5, 0x92, 0x9f, 0xb2, 0x59, 0xd2, 0x19, - 0x32, 0x54, 0x90, 0x5a, 0x12, 0xb5, 0x45, 0xab, 0x1e, 0x73, 0x02, 0x76, 0x5c, 0x8e, 0xc0, 0xc3, 0xb6, 0x82, 0xca, - 0xaa, 0x0d, 0xcd, 0x9a, 0xf8, 0x08, 0x52, 0xb1, 0xf5, 0xa6, 0xc2, 0x09, 0xb7, 0x69, 0xcb, 0xfe, 0x43, 0xa9, 0x9e, - 0x02, 0xdc, 0xe9, 0x5a, 0x58, 0x9b, 0x90, 0xf2, 0x04, 0xff, 0xce, 0x95, 0x73, 0x2f, 0xe6, 0xab, 0xb2, 0x71, 0x57, - 0x1b, 0xd4, 0x4d, 0x05, 0x29, 0x23, 0xa8, 0xeb, 0x50, 0x5f, 0x6e, 0x02, 0x34, 0x96, 0xad, 0x5b, 0xc0, 0x82, 0x46, - 0x4c, 0x41, 0x45, 0x47, 0x98, 0x83, 0x8a, 0xd7, 0x59, 0xd8, 0x79, 0x85, 0x7c, 0x1f, 0x7f, 0x41, 0x2e, 0x72, 0x48, - 0x70, 0xf2, 0x07, 0xe3, 0x79, 0x1b, 0x95, 0x7b, 0xa5, 0xad, 0x8a, 0xa6, 0x32, 0xb8, 0x07, 0xc4, 0x8d, 0x54, 0x59, - 0xc4, 0x81, 0x49, 0xe9, 0xe9, 0x35, 0x7d, 0xbd, 0x39, 0xee, 0xed, 0xdd, 0x3b, 0x2d, 0xd0, 0x6b, 0x6c, 0x4e, 0xd5, - 0x5e, 0xaa, 0xbd, 0xaa, 0x0e, 0x5b, 0xc0, 0x09, 0x2b, 0x00, 0x3e, 0xb3, 0x0a, 0x1a, 0x0d, 0x29, 0x15, 0xdc, 0x47, - 0x83, 0xce, 0xdf, 0xca, 0xc8, 0x5a, 0x8c, 0x13, 0xbb, 0xab, 0xaf, 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xcc, 0x1d, 0xc7, - 0x4e, 0xf8, 0x6c, 0xc2, 0x8e, 0x91, 0xd1, 0x95, 0x83, 0x3b, 0x08, 0x4f, 0xa9, 0x49, 0x69, 0x4f, 0xe8, 0x94, 0xa2, - 0x2e, 0xe1, 0x8f, 0xb5, 0xc2, 0xfb, 0xcb, 0x92, 0x34, 0x9e, 0x07, 0x9d, 0x68, 0xe8, 0x7b, 0xd5, 0x9e, 0xf9, 0xe1, - 0xfe, 0x75, 0xbd, 0xd5, 0xde, 0x75, 0x81, 0x39, 0xdc, 0xbb, 0x32, 0x70, 0x97, 0x58, 0xf9, 0x32, 0x75, 0xff, 0x28, - 0x29, 0x0f, 0xe4, 0x80, 0x89, 0x2a, 0xb6, 0xa2, 0x1b, 0xfd, 0x8f, 0x0b, 0xb7, 0x7f, 0x7a, 0xb6, 0x9a, 0x05, 0xca, - 0x2d, 0x8b, 0x13, 0x48, 0x28, 0xa1, 0x3a, 0x96, 0xad, 0x2a, 0x68, 0xd0, 0xef, 0x87, 0x13, 0x57, 0xfd, 0xf9, 0xf2, - 0x8d, 0xd9, 0x56, 0xcf, 0xc0, 0x1c, 0xe3, 0x76, 0x82, 0x2c, 0xee, 0x85, 0x77, 0xc7, 0xe2, 0x9b, 0x06, 0xf7, 0xf8, - 0x21, 0xe6, 0x16, 0xcb, 0x94, 0x86, 0xba, 0x47, 0xe2, 0x77, 0xe5, 0xd6, 0x67, 0xcb, 0x97, 0xd1, 0xca, 0x55, 0x01, - 0xb1, 0x3a, 0x8d, 0xb6, 0xe2, 0x34, 0x8e, 0xac, 0xe3, 0xb6, 0xda, 0xfb, 0x4a, 0x51, 0x4e, 0x47, 0x6c, 0x9c, 0xf4, - 0x50, 0x1c, 0x73, 0x8a, 0xfc, 0x20, 0xfd, 0x56, 0x14, 0x6b, 0x18, 0x24, 0xa6, 0xa3, 0xac, 0xf9, 0xa3, 0xa2, 0x00, - 0x32, 0xea, 0x28, 0x8f, 0xc6, 0x8d, 0xf1, 0xd1, 0xf8, 0x45, 0x97, 0x17, 0x67, 0x5f, 0x95, 0xaa, 0x1b, 0xf4, 0x6f, - 0x43, 0x6a, 0x96, 0xa4, 0x71, 0xf4, 0x91, 0x71, 0x5e, 0x52, 0xc9, 0x05, 0x45, 0xd5, 0xa6, 0x8d, 0xcd, 0x2f, 0x39, - 0xed, 0xc1, 0x70, 0xdc, 0x28, 0xaa, 0x23, 0x8c, 0x87, 0x39, 0x90, 0xa7, 0x87, 0x02, 0xf4, 0x53, 0x79, 0x9a, 0x1c, - 0xb3, 0x6e, 0xa2, 0x1c, 0x95, 0x8f, 0x71, 0x22, 0xc6, 0x77, 0x0a, 0x79, 0xd5, 0x0a, 0xef, 0xc5, 0x04, 0x9b, 0xb9, - 0xea, 0x0f, 0x4e, 0xa3, 0x6d, 0x38, 0xce, 0xb1, 0x75, 0xdc, 0x1e, 0xda, 0xc6, 0x91, 0x75, 0x64, 0x36, 0xad, 0x63, - 0xa3, 0x6d, 0xb6, 0x8d, 0xf6, 0x77, 0xed, 0xa1, 0x79, 0x64, 0x1d, 0x19, 0xb6, 0xd9, 0x86, 0x42, 0xb3, 0x6d, 0xb6, - 0x6f, 0xcd, 0xa3, 0xf6, 0xd0, 0xc6, 0xd2, 0x86, 0xd5, 0x6a, 0x99, 0x8e, 0x6d, 0xb5, 0x5a, 0x46, 0xcb, 0x3a, 0x3e, - 0x36, 0x9d, 0xa6, 0x75, 0x7c, 0x7c, 0xd1, 0x6a, 0x5b, 0x4d, 0x78, 0xd7, 0x6c, 0x0e, 0x9b, 0x96, 0xe3, 0x98, 0xf0, - 0x97, 0xd1, 0xb6, 0x1a, 0xf4, 0xc3, 0x71, 0xac, 0xa6, 0x63, 0xd8, 0x41, 0xab, 0x61, 0x1d, 0xbf, 0x30, 0xf0, 0x6f, - 0xac, 0x66, 0xe0, 0x5f, 0xd0, 0x8d, 0xf1, 0xc2, 0x6a, 0x1c, 0xd3, 0x2f, 0xec, 0xf0, 0xf6, 0xa8, 0xfd, 0x37, 0xf5, - 0x70, 0xeb, 0x18, 0x1c, 0x1a, 0x43, 0xbb, 0x65, 0x35, 0x9b, 0xc6, 0x91, 0x63, 0xb5, 0x9b, 0x53, 0xf3, 0xa8, 0x61, - 0x1d, 0x9f, 0x0c, 0x4d, 0xc7, 0x3a, 0x39, 0x31, 0x6c, 0xb3, 0x69, 0x35, 0x0c, 0xc7, 0x3a, 0x6a, 0xe2, 0x8f, 0xa6, - 0xd5, 0xb8, 0x3d, 0x79, 0x61, 0x1d, 0xb7, 0xa6, 0xc7, 0xd6, 0xd1, 0x87, 0xa3, 0xb6, 0xd5, 0x68, 0x4e, 0x9b, 0xc7, - 0x56, 0xe3, 0xe4, 0xf6, 0xd8, 0x3a, 0x9a, 0x9a, 0x8d, 0xe3, 0x9d, 0x2d, 0x9d, 0x86, 0x05, 0x73, 0x84, 0xaf, 0xe1, - 0x85, 0xc1, 0x5f, 0xc0, 0x9f, 0x29, 0xb6, 0xfd, 0x1d, 0xbb, 0x49, 0x36, 0x9b, 0xbe, 0xb0, 0xda, 0x27, 0x43, 0xaa, - 0x0e, 0x05, 0xa6, 0xa8, 0x01, 0x4d, 0x6e, 0x4d, 0xfa, 0x2c, 0x76, 0x67, 0x8a, 0x8e, 0xc4, 0x1f, 0xfe, 0xb1, 0x5b, - 0x13, 0x3e, 0x4c, 0xdf, 0xfd, 0x8f, 0xf6, 0x93, 0x2f, 0xf9, 0xe9, 0xe1, 0x84, 0xb6, 0xfe, 0xa4, 0xf7, 0xd5, 0x29, - 0x1c, 0xee, 0x5e, 0xdf, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x1f, 0xf7, 0x2b, 0x25, 0x5f, 0x2e, 0xf6, 0x51, 0x4a, 0xfe, - 0xe3, 0x8b, 0x2b, 0x25, 0x7f, 0xa9, 0xfa, 0xd6, 0xbc, 0xa9, 0xe6, 0x9a, 0xfe, 0xe3, 0xba, 0x2a, 0x72, 0x48, 0x3c, - 0xed, 0xea, 0xc7, 0xc5, 0x35, 0xc4, 0x8f, 0x7f, 0x13, 0xb9, 0x2f, 0x17, 0x25, 0x83, 0xcf, 0x08, 0x70, 0xec, 0x9b, - 0x88, 0x70, 0xec, 0x87, 0x85, 0x0b, 0x56, 0x66, 0x9c, 0xcd, 0xf1, 0x47, 0xe6, 0xd4, 0x0b, 0xc6, 0x39, 0x8b, 0x04, - 0x25, 0x5d, 0x2c, 0x06, 0xbf, 0x79, 0x20, 0xcf, 0x70, 0x93, 0x59, 0xcc, 0xc2, 0x04, 0x2c, 0x82, 0xc1, 0x92, 0x63, - 0x1c, 0x67, 0x95, 0xc6, 0x96, 0x88, 0xb8, 0x7f, 0xc3, 0x3d, 0x8a, 0xb7, 0xbe, 0x47, 0x03, 0xe0, 0xfa, 0xde, 0x9d, - 0xcd, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, 0xbd, 0x2f, 0x9b, 0xe1, 0x56, 0x0c, 0xaf, 0xb7, - 0x43, 0x0a, 0x90, 0x54, 0xdb, 0x3b, 0x65, 0x33, 0xde, 0xfb, 0x86, 0x59, 0xf3, 0xf9, 0x52, 0xf3, 0x1d, 0x36, 0xc4, - 0x79, 0xc7, 0xd5, 0xa9, 0x5a, 0x97, 0xf8, 0xb4, 0xfa, 0x09, 0x29, 0x2e, 0xa8, 0x85, 0xa1, 0x71, 0xc1, 0xa9, 0xda, - 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd4, 0xa7, 0x6c, 0x9c, 0xfc, 0x6c, 0x8d, 0xf7, 0x0a, 0xff, 0x17, 0xe0, 0x44, - 0x39, 0xc7, 0x33, 0x88, 0xe4, 0x79, 0x5e, 0x4b, 0xfd, 0x92, 0x34, 0x22, 0x9b, 0x3a, 0xeb, 0x4d, 0x5e, 0x74, 0xab, - 0x5b, 0x82, 0xc3, 0x66, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x13, 0x40, 0x46, 0x8e, 0x1a, 0xe8, 0xe7, 0xb0, 0xab, 0x33, - 0x51, 0xef, 0x11, 0x6c, 0x62, 0xee, 0x09, 0xa8, 0xc8, 0x21, 0x4d, 0xd7, 0xe3, 0x20, 0xf2, 0xd2, 0x0e, 0xb2, 0x69, - 0x12, 0xcb, 0xdb, 0x40, 0x8f, 0x85, 0xee, 0x0e, 0x63, 0x3a, 0xb9, 0x63, 0xde, 0x09, 0x7a, 0x3e, 0xec, 0xb2, 0xbf, - 0xcb, 0x1d, 0xce, 0xd6, 0x25, 0x73, 0x14, 0xa7, 0x75, 0x62, 0x38, 0xc7, 0x86, 0x75, 0xd2, 0xd2, 0x33, 0x71, 0xe0, - 0xe4, 0x2e, 0x4b, 0x13, 0x02, 0x0e, 0x10, 0x39, 0x98, 0x7e, 0xe8, 0xa7, 0xbe, 0x17, 0x64, 0xc0, 0x0f, 0x97, 0x2f, - 0x29, 0xff, 0x58, 0x24, 0x29, 0x8c, 0x51, 0x30, 0xbd, 0xe8, 0xfc, 0x61, 0x0e, 0x58, 0xba, 0x64, 0x2c, 0xdc, 0x62, - 0x18, 0x53, 0xf5, 0x25, 0xf9, 0xed, 0x2c, 0xeb, 0x33, 0xb2, 0x5a, 0x1b, 0xa4, 0x21, 0xdf, 0x1f, 0xc2, 0xf1, 0x21, - 0xeb, 0x1b, 0xdf, 0x6d, 0x43, 0xb8, 0x3f, 0xdf, 0x8f, 0x70, 0x53, 0xb6, 0x0f, 0xc2, 0xfd, 0xf9, 0x8b, 0x23, 0xdc, - 0xef, 0x64, 0x84, 0x5b, 0xf2, 0x1f, 0x2c, 0x34, 0x4c, 0xef, 0xf1, 0x59, 0x03, 0x17, 0xd9, 0xe7, 0xea, 0x21, 0x31, - 0xf0, 0xaa, 0x5e, 0xe4, 0xa8, 0xfd, 0xf3, 0x42, 0xb6, 0xa0, 0x46, 0x01, 0x28, 0xa6, 0x76, 0xf4, 0xd1, 0x75, 0xd9, - 0x07, 0x57, 0x37, 0x11, 0x86, 0x01, 0xfa, 0xfc, 0x3e, 0x4c, 0x03, 0xeb, 0x1d, 0xbf, 0x47, 0x82, 0x42, 0xf7, 0x4d, - 0x14, 0xcf, 0x3c, 0x4c, 0x31, 0xa2, 0xea, 0xe0, 0x4e, 0x07, 0x0f, 0x36, 0x04, 0x02, 0x19, 0x46, 0xe1, 0x28, 0xd7, - 0x4a, 0x32, 0xf7, 0x8a, 0x38, 0x6e, 0xf5, 0x8e, 0x79, 0xb1, 0x6a, 0xd0, 0x6b, 0x58, 0xdc, 0x67, 0x4d, 0xfb, 0x59, - 0xe3, 0xe8, 0xd9, 0xb1, 0x0d, 0xff, 0x3b, 0xac, 0x99, 0x19, 0xbc, 0xe2, 0x2c, 0x0a, 0xd3, 0x69, 0x51, 0x73, 0x5b, - 0xb5, 0x25, 0x63, 0x1f, 0x8b, 0x5a, 0x27, 0xf5, 0x95, 0x46, 0xde, 0x5d, 0x51, 0xa7, 0xb6, 0xc6, 0x34, 0x5a, 0x48, - 0x60, 0xd5, 0x40, 0xe3, 0x87, 0x0b, 0x90, 0xb3, 0x4b, 0x35, 0xe4, 0xd7, 0x7c, 0xb8, 0xc5, 0xb8, 0x58, 0x33, 0xbb, - 0x16, 0x39, 0x14, 0xd4, 0xae, 0x48, 0x9a, 0x7b, 0xef, 0x0c, 0x72, 0x15, 0xa5, 0x8d, 0x39, 0xa7, 0x30, 0x9b, 0x21, - 0x64, 0x9c, 0x62, 0x62, 0x81, 0x3c, 0x5a, 0xa0, 0x34, 0x5e, 0x84, 0x43, 0x0d, 0x7f, 0x7a, 0x83, 0x44, 0xf3, 0x0f, - 0x63, 0x8b, 0x7f, 0x58, 0xc7, 0x55, 0xf3, 0x7a, 0x76, 0x91, 0x5a, 0x3e, 0x11, 0xab, 0xe2, 0x3d, 0x4b, 0x8d, 0x18, - 0xf5, 0xd8, 0xb4, 0xb4, 0xa6, 0xeb, 0x3d, 0xcb, 0x1b, 0x3e, 0x4b, 0x8d, 0xf0, 0x39, 0xe8, 0x3e, 0x5d, 0xfb, 0xc9, - 0x13, 0xaa, 0x75, 0xe0, 0x8a, 0x61, 0x9d, 0x0d, 0x8b, 0xcc, 0x14, 0x8a, 0x37, 0x89, 0x28, 0x39, 0x45, 0x67, 0x68, - 0x44, 0xcf, 0x9f, 0xf7, 0x5c, 0x47, 0x1f, 0xc4, 0xcc, 0xfb, 0x98, 0x89, 0x70, 0xdf, 0x21, 0x66, 0xa1, 0xbd, 0xd8, - 0xcf, 0xd0, 0x48, 0xaf, 0x75, 0xa5, 0x9d, 0xc3, 0x9d, 0xc9, 0x16, 0xee, 0x08, 0x1c, 0x7b, 0x41, 0x86, 0x7a, 0x32, - 0x28, 0xf0, 0x84, 0xc1, 0x8f, 0xa8, 0x93, 0xdf, 0xba, 0x9a, 0x96, 0x6d, 0xd9, 0x6a, 0xde, 0x70, 0xec, 0x4f, 0xdc, - 0x75, 0x94, 0x7a, 0x9d, 0x03, 0xc7, 0x08, 0xa2, 0x09, 0xf8, 0xd1, 0xa5, 0x7e, 0x1a, 0xb0, 0x8e, 0xaa, 0x82, 0x43, - 0xdd, 0x8c, 0xee, 0xe5, 0x19, 0xf7, 0x6e, 0xf0, 0x62, 0x48, 0x4e, 0x1e, 0xdf, 0x09, 0x57, 0x5c, 0x0c, 0x96, 0xfe, - 0x03, 0x10, 0x43, 0x4d, 0xd5, 0x40, 0x36, 0xc0, 0xe2, 0xc4, 0x94, 0xbd, 0x85, 0x3a, 0x0a, 0xb4, 0xd1, 0x55, 0x3e, - 0x88, 0x71, 0xec, 0xcd, 0x20, 0x7b, 0xee, 0x3a, 0x33, 0x38, 0xa6, 0x55, 0x39, 0xaa, 0x55, 0x9c, 0x17, 0xc7, 0x86, - 0xd2, 0x70, 0x0c, 0xc5, 0x06, 0x74, 0xab, 0x66, 0xc6, 0x3a, 0xbb, 0xee, 0xde, 0x67, 0xf0, 0x40, 0xf8, 0xe5, 0x11, - 0x8d, 0x83, 0x4c, 0x1d, 0xb8, 0x2a, 0x29, 0xa5, 0x24, 0x39, 0x9a, 0x94, 0x35, 0xd3, 0x27, 0xa5, 0xe7, 0x25, 0x5b, - 0xa5, 0x3a, 0x68, 0x8e, 0x44, 0x15, 0x5f, 0x5f, 0xa3, 0xc3, 0xb0, 0x1f, 0x2a, 0xfe, 0xa7, 0x4f, 0x9a, 0x0f, 0xce, - 0x4c, 0xae, 0x34, 0x3f, 0xf0, 0xac, 0x97, 0x26, 0xcc, 0x2f, 0xd4, 0xf4, 0x38, 0x59, 0xe0, 0x69, 0x08, 0xff, 0x16, - 0xc5, 0xe2, 0x07, 0x37, 0x93, 0xb0, 0x02, 0x2f, 0x9c, 0x00, 0x4a, 0xf3, 0xc2, 0xc9, 0x86, 0x39, 0x16, 0xf9, 0x3c, - 0x57, 0x4a, 0x8b, 0xae, 0x0a, 0x53, 0xa9, 0xe4, 0xe5, 0xdd, 0xa5, 0x37, 0xf9, 0xd1, 0x9b, 0x31, 0x4d, 0x05, 0x2a, - 0x87, 0x2e, 0xba, 0x85, 0x26, 0xf7, 0xb9, 0xfb, 0xf4, 0x74, 0xc6, 0x52, 0x8f, 0xd4, 0x40, 0x70, 0xf9, 0x05, 0x76, - 0x40, 0xe1, 0x84, 0x86, 0x07, 0xbc, 0x70, 0x29, 0x97, 0x16, 0xd1, 0x09, 0x43, 0xe1, 0x74, 0xca, 0x44, 0x8b, 0x4f, - 0xd7, 0x31, 0xc8, 0xe1, 0x60, 0xe8, 0x61, 0x3e, 0x1d, 0x37, 0x8c, 0xd4, 0xde, 0xd3, 0xdc, 0x37, 0x73, 0xdb, 0x22, - 0x04, 0x7e, 0xf8, 0xf1, 0x2a, 0x66, 0xc1, 0x3f, 0xdd, 0xa7, 0x40, 0xb8, 0x9f, 0x5e, 0xab, 0x7a, 0x37, 0xb5, 0xa6, - 0x31, 0x1b, 0xbb, 0x4f, 0xe1, 0x42, 0xda, 0x41, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xaf, 0x66, 0x81, 0x81, 0xd7, 0x7b, - 0x82, 0x45, 0x6d, 0x36, 0x8a, 0xb8, 0xe6, 0xcd, 0xbd, 0x2e, 0xf5, 0x3d, 0x7e, 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, - 0xc7, 0x76, 0xba, 0x78, 0x7f, 0x1e, 0x04, 0xde, 0xf0, 0x63, 0x97, 0xde, 0x94, 0x1e, 0x4c, 0xa0, 0xd6, 0x43, 0x6f, - 0xde, 0x41, 0xf2, 0x2a, 0x17, 0x82, 0xf7, 0x34, 0x95, 0xe6, 0x9c, 0x5d, 0xed, 0x5e, 0xc6, 0xad, 0xbc, 0xc6, 0x2f, - 0xe3, 0xa7, 0x96, 0x53, 0x3f, 0x65, 0xe2, 0x53, 0xf8, 0x90, 0x65, 0xe2, 0xa2, 0x4e, 0x57, 0x54, 0xbc, 0x58, 0x5b, - 0x4d, 0xc5, 0x69, 0x7f, 0xd7, 0xba, 0x75, 0xec, 0x69, 0xc3, 0xb1, 0xda, 0x1f, 0x9c, 0xf6, 0xb4, 0x69, 0x9d, 0x04, - 0x66, 0xd3, 0x3a, 0x81, 0x3f, 0x1f, 0x4e, 0xac, 0xf6, 0xd4, 0x6c, 0x58, 0x47, 0x1f, 0x9c, 0x46, 0x60, 0xb6, 0xad, - 0x13, 0xf8, 0x73, 0x41, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, - 0x89, 0xbc, 0xd5, 0xe8, 0x75, 0xe7, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0xbb, 0x5a, 0xe8, 0x32, 0x4a, 0x24, 0x2b, - 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0x59, 0x7b, 0x8c, 0x78, 0x9b, 0xfa, 0x0c, 0x96, 0xba, 0xc8, 0x05, 0x8c, - 0xcf, 0x3f, 0xcf, 0x31, 0xfe, 0xba, 0x48, 0xbc, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x89, 0xb6, 0x15, - 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xfc, 0xd6, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, - 0x21, 0x67, 0x9f, 0x1c, 0xf9, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xfa, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, - 0x7c, 0xeb, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x20, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, - 0x9d, 0x16, 0x90, 0xdd, 0x16, 0x6b, 0xee, 0xb4, 0xa9, 0xa4, 0x9b, 0xce, 0x2e, 0xdf, 0xea, 0x22, 0xd3, 0x91, 0xb0, - 0x9b, 0x12, 0x16, 0x1b, 0x5b, 0x0d, 0x3b, 0x37, 0xec, 0x35, 0x20, 0x55, 0x5c, 0xe5, 0xaa, 0xa3, 0xea, 0xdd, 0x50, - 0x98, 0x1f, 0x84, 0x3b, 0x92, 0xbc, 0xf1, 0xbb, 0x98, 0x0a, 0x53, 0xb3, 0x63, 0x1c, 0xf7, 0x38, 0x88, 0xff, 0xa7, - 0x07, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x39, 0xad, 0x25, 0xe7, 0xbd, 0x9c, 0xae, 0x12, 0x41, 0x65, 0xc9, 0x99, - 0x0a, 0x45, 0x6a, 0x47, 0x45, 0xc7, 0x30, 0x35, 0x37, 0x16, 0xcd, 0xa9, 0x45, 0x51, 0x60, 0xf8, 0x98, 0x50, 0x53, - 0x38, 0x8e, 0xea, 0x4f, 0x9e, 0x6c, 0x25, 0x42, 0x64, 0x9c, 0x93, 0xb0, 0x54, 0x30, 0xe8, 0x9a, 0x2a, 0xe3, 0x37, - 0x55, 0x46, 0x31, 0x79, 0xbf, 0x88, 0x35, 0x84, 0x8d, 0x2b, 0xed, 0x3d, 0xfc, 0x39, 0x60, 0x5e, 0x6a, 0x71, 0x65, - 0xa9, 0x26, 0x11, 0x77, 0xc3, 0x61, 0x4d, 0xb0, 0x6e, 0xe5, 0x69, 0x1a, 0x78, 0x1a, 0x94, 0xc7, 0xeb, 0x3f, 0x2f, - 0x78, 0x54, 0x07, 0xe8, 0xe3, 0x93, 0x5d, 0xc4, 0xe1, 0x7c, 0x9b, 0x7a, 0x14, 0x07, 0x4d, 0x26, 0xb9, 0x51, 0xea, - 0x91, 0x3d, 0x87, 0x8f, 0xa1, 0x6b, 0xea, 0x23, 0x72, 0x49, 0x91, 0x1f, 0x7a, 0x6f, 0x2f, 0xbf, 0x51, 0xf8, 0xfe, - 0x27, 0x6b, 0x01, 0xbc, 0xc8, 0x50, 0xbc, 0x19, 0x97, 0xe2, 0xcd, 0x28, 0x3c, 0x93, 0x31, 0xe4, 0x5c, 0xcd, 0x0e, - 0x69, 0x06, 0x51, 0x00, 0x4d, 0x36, 0x14, 0xb3, 0x45, 0x90, 0xfa, 0x73, 0x2f, 0x4e, 0x0f, 0x31, 0xd8, 0x0c, 0x06, - 0xaf, 0xd9, 0x16, 0x0f, 0x82, 0xcc, 0x30, 0x44, 0x76, 0x90, 0x34, 0x14, 0x76, 0x18, 0x63, 0x3f, 0xc8, 0xcd, 0x30, - 0xc4, 0x07, 0xbc, 0xe1, 0x90, 0xcd, 0x53, 0xb7, 0x14, 0xd4, 0x26, 0x1a, 0xa6, 0x2c, 0x35, 0x93, 0x34, 0x66, 0xde, - 0x4c, 0xcd, 0x83, 0x5c, 0x6d, 0xf6, 0x97, 0x2c, 0x06, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, - 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0x2f, 0xa2, 0x49, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x19, 0x26, 0x09, 0xa3, 0x9b, - 0x0c, 0x48, 0x8b, 0x87, 0x51, 0x70, 0xc3, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xde, 0x29, 0xbf, 0xde, 0x2a, 0x18, - 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x06, 0x6d, 0x5b, 0x74, 0x8b, 0x43, 0x5e, 0x19, 0x48, 0x13, 0xf5, 0x8c, 0x99, 0x2c, - 0x09, 0x96, 0x4b, 0x60, 0x84, 0x4a, 0x06, 0x33, 0x53, 0xa7, 0x97, 0xbb, 0x53, 0x22, 0x54, 0xc8, 0x2b, 0x7d, 0xfa, - 0xf4, 0xbe, 0xff, 0xef, 0x7f, 0x41, 0xba, 0xcd, 0xa9, 0x23, 0x62, 0x4a, 0x5c, 0xc9, 0xb5, 0x38, 0xf7, 0x69, 0xf4, - 0xd1, 0x58, 0x8a, 0x8d, 0x44, 0xb4, 0x3f, 0xb1, 0xb5, 0xb2, 0xfe, 0xb5, 0x88, 0x53, 0x07, 0x89, 0x7a, 0x75, 0x11, - 0xf9, 0xa2, 0x0f, 0xcb, 0xdb, 0x17, 0x31, 0x51, 0x94, 0xbf, 0xaf, 0x5e, 0x9e, 0x28, 0x45, 0xf8, 0xc4, 0x3a, 0x8b, - 0x1e, 0xda, 0x43, 0xbd, 0x53, 0x4f, 0x41, 0xa6, 0x05, 0xd9, 0x8f, 0xa4, 0x73, 0x08, 0xc3, 0x9c, 0x46, 0x33, 0x66, - 0xf9, 0xd1, 0xe1, 0x92, 0x0d, 0x4c, 0x6f, 0xee, 0x93, 0x5d, 0x0e, 0xca, 0xdd, 0x14, 0xe2, 0xfc, 0x72, 0x73, 0x17, - 0xe2, 0xaf, 0xb3, 0x62, 0x2a, 0xa3, 0x4a, 0x20, 0xb4, 0x46, 0xa1, 0x07, 0x3c, 0xe2, 0x41, 0xc6, 0x44, 0xcd, 0xde, - 0xe9, 0xa1, 0xd7, 0x2b, 0x67, 0x9e, 0xb1, 0x44, 0x06, 0xd5, 0x32, 0x11, 0x38, 0xa3, 0x04, 0x32, 0x22, 0x57, 0x4c, - 0xf1, 0x60, 0x46, 0xe3, 0xb1, 0x9c, 0x2d, 0xc6, 0x2a, 0x83, 0x97, 0x4f, 0x5a, 0xb1, 0xa5, 0xa3, 0x39, 0x7d, 0x69, - 0xf3, 0x13, 0xf9, 0x4f, 0xb5, 0x83, 0x69, 0xa2, 0x60, 0xcc, 0x70, 0xdc, 0x37, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, - 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x85, 0x73, 0x39, 0x70, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0x58, - 0x93, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x9b, 0x30, 0x1e, 0x7a, 0x62, - 0xfb, 0x95, 0x36, 0x28, 0x6c, 0x3c, 0xbe, 0xee, 0x80, 0xdf, 0x45, 0x3f, 0x15, 0x34, 0xaf, 0x7c, 0x4d, 0x18, 0xdd, - 0x0c, 0xbc, 0xbb, 0x48, 0x32, 0x63, 0xe2, 0x11, 0x4d, 0x2e, 0xb0, 0xf4, 0x52, 0x78, 0x12, 0x6f, 0x1c, 0x34, 0x24, - 0x61, 0x90, 0x75, 0x73, 0xf3, 0xb0, 0x15, 0xf4, 0x37, 0x60, 0xf7, 0x9d, 0x35, 0xb9, 0x6e, 0x79, 0x30, 0x88, 0x3c, - 0xb3, 0xe2, 0x1c, 0x96, 0x5e, 0x22, 0x5a, 0xc8, 0x4e, 0x0f, 0x61, 0x7c, 0x10, 0x85, 0xa5, 0xc4, 0x38, 0xf9, 0x3a, - 0x84, 0x7a, 0xf1, 0x12, 0x32, 0xc5, 0xfa, 0x7e, 0x24, 0x78, 0x3e, 0xbc, 0x58, 0x4a, 0xb9, 0xe4, 0xa5, 0x2a, 0x9b, - 0xbc, 0x8c, 0x5d, 0xcf, 0x04, 0xde, 0x9f, 0xa2, 0xf6, 0xc3, 0x02, 0xf3, 0xd3, 0x66, 0xdd, 0x94, 0x89, 0x20, 0x07, - 0x17, 0xe9, 0x96, 0x38, 0x08, 0xdb, 0xaa, 0x10, 0x3f, 0xbb, 0xa3, 0x42, 0xb1, 0x8f, 0x77, 0xd5, 0x2a, 0x38, 0xa7, - 0xa2, 0x9a, 0xa7, 0xa9, 0x8f, 0x70, 0xc7, 0x6f, 0xd4, 0xc6, 0x52, 0x8c, 0xce, 0x90, 0xba, 0x50, 0x55, 0xc8, 0xe2, - 0xbd, 0xf9, 0x9c, 0x2a, 0xeb, 0xdd, 0xd3, 0x43, 0xba, 0x96, 0xf6, 0x68, 0x87, 0xf5, 0x4e, 0xc1, 0x94, 0x9b, 0x16, - 0xdd, 0x9b, 0xcf, 0xf9, 0x92, 0xd2, 0x2f, 0x7a, 0x73, 0x38, 0x4d, 0x67, 0x41, 0xef, 0x7f, 0x01, 0xb9, 0x4b, 0x40, - 0x75, 0x91, 0x7a, 0x03, 0x00}; + 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0xaa, + 0x16, 0x77, 0x07, 0xbb, 0x09, 0xfa, 0x2f, 0xc0, 0x6c, 0x73, 0x88, 0xbf, 0x32, 0xa2, 0x8c, 0xe6, 0x59, 0x0c, 0x8d, + 0x1c, 0x34, 0x0f, 0x4e, 0x0b, 0x36, 0x47, 0x7e, 0x50, 0xc9, 0xfd, 0x6e, 0xc1, 0xe6, 0x9b, 0xc4, 0x54, 0x5f, 0x19, + 0x34, 0xa2, 0x39, 0x9f, 0x8a, 0x34, 0x63, 0x80, 0xe2, 0x9b, 0x84, 0x09, 0xcd, 0xf5, 0x5d, 0xb3, 0x90, 0x37, 0xab, + 0x31, 0x57, 0x8b, 0x9c, 0xde, 0xa5, 0x93, 0x9c, 0xdd, 0xf6, 0x4c, 0xa9, 0x26, 0xd7, 0x6c, 0xae, 0x5c, 0xd9, 0x1e, + 0xa4, 0x37, 0xc7, 0xd6, 0xb4, 0x02, 0x66, 0x22, 0x6f, 0xb6, 0xf7, 0x98, 0x07, 0x60, 0x53, 0x2e, 0xf5, 0x41, 0x4b, + 0xf5, 0xe6, 0x5c, 0x34, 0xdd, 0x40, 0xce, 0x60, 0x75, 0x76, 0xa1, 0x10, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, + 0x36, 0x5e, 0x05, 0xd5, 0x3a, 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x7b, 0xb0, 0xb8, 0x23, 0xd0, 0x57, + 0xd0, 0xef, 0x41, 0x0b, 0xdb, 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xa1, 0x99, 0xf8, 0xe4, 0xae, 0x09, 0x7f, + 0x57, 0xe0, 0x7f, 0xc4, 0x33, 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, + 0x2b, 0x98, 0x7f, 0xda, 0x3a, 0x68, 0x1d, 0x98, 0xb9, 0x38, 0x94, 0x3c, 0x3b, 0xbb, 0x7f, 0xfa, 0x80, 0xf5, 0x72, + 0x2e, 0x58, 0x6d, 0xaa, 0xdf, 0x04, 0x75, 0xd8, 0x70, 0xc7, 0x35, 0xdc, 0x3e, 0x68, 0x1f, 0x9c, 0xb5, 0xbe, 0xf3, + 0x3b, 0x3a, 0x67, 0x13, 0x6d, 0x71, 0xb8, 0xb6, 0xc5, 0x2f, 0x7c, 0xd3, 0x37, 0x05, 0x5d, 0xa4, 0x42, 0xc2, 0x9f, + 0x1e, 0x6c, 0xc4, 0x49, 0x2e, 0x6f, 0xd2, 0x19, 0x1f, 0x8f, 0xc1, 0x9d, 0x0a, 0x0a, 0x94, 0x89, 0x2c, 0xcf, 0xf9, + 0x42, 0x71, 0xbb, 0x1a, 0x0e, 0xdd, 0xba, 0x5b, 0x50, 0x0d, 0x07, 0x74, 0x1a, 0x0c, 0xa8, 0x5b, 0x0d, 0xa8, 0xea, + 0x3f, 0x1c, 0x61, 0x67, 0x6b, 0xae, 0xa6, 0x54, 0xaf, 0x86, 0x49, 0x9f, 0x96, 0x4a, 0x03, 0xcc, 0xbd, 0x21, 0x87, + 0xa1, 0xf4, 0xcd, 0x11, 0xd3, 0x37, 0x8c, 0x89, 0xaf, 0x0f, 0xe2, 0x2a, 0x95, 0x22, 0xbf, 0xb3, 0x9f, 0xab, 0xb0, + 0x4b, 0xba, 0xd4, 0x72, 0x93, 0x8c, 0xb8, 0xa0, 0xc5, 0xdd, 0x47, 0xc5, 0x84, 0x92, 0xc5, 0x47, 0x39, 0x99, 0xac, + 0xbe, 0x46, 0x7e, 0xee, 0xa3, 0x4d, 0xa2, 0xb8, 0x98, 0xe6, 0xcc, 0x12, 0x1b, 0x83, 0x08, 0x8e, 0xe0, 0xdb, 0x76, + 0x4d, 0x93, 0xb5, 0x41, 0x6f, 0x92, 0x2c, 0xe7, 0x73, 0xaa, 0x99, 0x81, 0x73, 0xb8, 0x49, 0x5d, 0x0d, 0x43, 0x71, + 0x5a, 0x07, 0xf6, 0x4f, 0x55, 0x1a, 0xb6, 0x51, 0x50, 0xd8, 0x37, 0xc9, 0x85, 0xc1, 0x0f, 0x03, 0x0e, 0xb3, 0x8b, + 0xcc, 0xea, 0x99, 0xb5, 0x0b, 0x60, 0x07, 0xb3, 0xab, 0x35, 0x75, 0x55, 0xa3, 0x11, 0xdd, 0xd6, 0x77, 0xf5, 0xdc, + 0x9c, 0x8e, 0x58, 0xbe, 0xb2, 0x1b, 0xd5, 0x03, 0xd7, 0x6d, 0xd5, 0x70, 0x99, 0x03, 0x92, 0x61, 0x40, 0x34, 0x4c, + 0xd3, 0xe6, 0x0d, 0x1b, 0x7d, 0xe6, 0xda, 0x6e, 0x99, 0xa6, 0xba, 0x01, 0x07, 0x1f, 0x33, 0xa6, 0x05, 0x2b, 0x56, + 0x9e, 0xa8, 0xb6, 0x6a, 0xc4, 0xec, 0x17, 0x61, 0x0e, 0x4b, 0x4d, 0x47, 0x4d, 0x08, 0x77, 0xc6, 0x8a, 0xd5, 0xbe, + 0xc9, 0xcd, 0xe9, 0xad, 0x43, 0xb1, 0x07, 0xad, 0xef, 0x6a, 0x07, 0xde, 0x59, 0xab, 0xe5, 0xc9, 0x75, 0xd3, 0xd6, + 0x48, 0xdb, 0x49, 0x97, 0xcd, 0xcb, 0x44, 0x2d, 0x17, 0x69, 0x2d, 0x61, 0x24, 0xb5, 0x96, 0x73, 0x9b, 0xb6, 0x87, + 0x1a, 0xd5, 0xa9, 0x65, 0xbb, 0xb3, 0xb8, 0x3d, 0x30, 0xff, 0xb4, 0x0e, 0x5a, 0xbb, 0x87, 0xf1, 0x2e, 0x56, 0x9c, + 0x22, 0x8f, 0xc7, 0xd0, 0x71, 0x9b, 0xcd, 0x7b, 0x4b, 0x05, 0x47, 0xaf, 0x81, 0xb8, 0x39, 0x5d, 0x36, 0x66, 0xb2, + 0x00, 0x58, 0xca, 0x05, 0x9c, 0x74, 0xf6, 0xe0, 0x81, 0x3e, 0x94, 0x04, 0xd3, 0xf4, 0xbd, 0x8d, 0xd6, 0x87, 0xd5, + 0x3a, 0xa8, 0x06, 0x06, 0xff, 0x6c, 0xfe, 0xaa, 0x78, 0xe5, 0x27, 0x2c, 0x90, 0x55, 0x78, 0x23, 0xe9, 0xae, 0x5b, + 0x4e, 0x3e, 0x19, 0xeb, 0x4a, 0x6c, 0x32, 0xde, 0x1d, 0x73, 0x7a, 0x6b, 0xdd, 0x3c, 0xe6, 0x5c, 0x80, 0x11, 0x19, + 0xc2, 0x3a, 0x30, 0xb7, 0x9f, 0x85, 0x0d, 0x8d, 0x75, 0x0c, 0x0d, 0x1f, 0x77, 0x92, 0x6e, 0x17, 0xe1, 0x16, 0xee, + 0x74, 0xbb, 0x81, 0x7c, 0x34, 0xd1, 0xfb, 0x8a, 0xee, 0x2b, 0x29, 0xf7, 0x94, 0x3c, 0x31, 0x8d, 0x9e, 0xb4, 0x5b, + 0x2d, 0x6c, 0x5c, 0xd9, 0xcb, 0xc2, 0x42, 0xed, 0x69, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, 0xc7, 0xcd, 0xeb, 0x27, + 0xb2, 0x6a, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x69, 0x7a, 0x8a, 0xcf, 0xd2, 0x33, 0xdc, 0x4d, + 0xbb, 0xf8, 0x3c, 0x3d, 0xc7, 0xf7, 0xd3, 0xfb, 0xf8, 0x22, 0xbd, 0xc0, 0x0f, 0xd2, 0x07, 0xf8, 0x61, 0xda, 0x6e, + 0xe1, 0x47, 0x69, 0xbb, 0x8d, 0x1f, 0xa7, 0xed, 0x0e, 0x7e, 0x92, 0xb6, 0x4f, 0xf1, 0xd3, 0xb4, 0x7d, 0x86, 0x9f, + 0xa5, 0xed, 0x2e, 0xa6, 0x90, 0x3b, 0x82, 0xdc, 0x0c, 0x72, 0xc7, 0x90, 0xcb, 0x20, 0x77, 0x92, 0xb6, 0xbb, 0x1b, + 0x2c, 0x6d, 0xf8, 0x8b, 0xa8, 0xd5, 0xee, 0x9c, 0x9e, 0x75, 0xcf, 0xef, 0x5f, 0x3c, 0x78, 0xf8, 0xe8, 0xf1, 0x93, + 0xa7, 0xcf, 0xa2, 0x21, 0xbe, 0x33, 0x5e, 0x28, 0x52, 0x0c, 0xf8, 0x51, 0xbb, 0x3b, 0xc4, 0xb7, 0xfe, 0x33, 0xe6, + 0x47, 0x9d, 0xb3, 0x16, 0xba, 0xba, 0x3a, 0x1b, 0x36, 0xca, 0xdc, 0x47, 0xc6, 0xf9, 0xa5, 0xca, 0x22, 0x84, 0xc4, + 0x90, 0x83, 0xf0, 0x17, 0xeb, 0xcc, 0xc2, 0x62, 0x9e, 0x14, 0xe8, 0xe8, 0xc8, 0xfc, 0x98, 0xfa, 0x1f, 0x23, 0xff, + 0x83, 0x06, 0x8b, 0x74, 0x43, 0x63, 0xe7, 0xfd, 0xac, 0x4b, 0xdf, 0x83, 0xd2, 0xac, 0xe7, 0x80, 0x3b, 0x03, 0xfb, + 0xff, 0x8a, 0xac, 0x01, 0x0d, 0x39, 0xb3, 0x4a, 0xaa, 0x6e, 0x9f, 0x91, 0x55, 0x91, 0x76, 0xba, 0xdd, 0xa3, 0x9f, + 0x06, 0x7c, 0xd0, 0x1e, 0x0e, 0x8f, 0xdb, 0xf7, 0xf1, 0xb4, 0x4c, 0xe8, 0xd8, 0x84, 0x51, 0x99, 0x70, 0x6a, 0x13, + 0x68, 0x6a, 0x6b, 0x43, 0xd2, 0x99, 0x49, 0x82, 0x12, 0x9b, 0xd4, 0xb4, 0x7d, 0xdf, 0xb6, 0xfd, 0x00, 0x2c, 0xbb, + 0x4c, 0xf3, 0xae, 0xe9, 0xcb, 0xcb, 0xb3, 0xb5, 0x6b, 0x14, 0x4f, 0x53, 0xd7, 0x9a, 0x4f, 0x3c, 0x1b, 0x0e, 0xf1, + 0xc8, 0x24, 0x76, 0xab, 0xc4, 0xf3, 0xe1, 0xd0, 0x75, 0xf5, 0xc0, 0x74, 0x75, 0xbf, 0xca, 0xba, 0x18, 0x0e, 0x4d, + 0x97, 0xc8, 0xf9, 0xf1, 0x2b, 0x7d, 0xf0, 0xb9, 0xd4, 0xa5, 0xf0, 0xcb, 0x4e, 0xb7, 0xdb, 0x07, 0x0c, 0x33, 0xf6, + 0xb9, 0x1e, 0x46, 0xd7, 0x01, 0x8c, 0xbe, 0xc0, 0xef, 0xfe, 0x1d, 0x4d, 0x6f, 0x69, 0x09, 0xa4, 0x7e, 0xf4, 0x5f, + 0x51, 0x43, 0x1b, 0x98, 0x9b, 0x3f, 0x53, 0xfb, 0x67, 0x84, 0x1a, 0x9f, 0x29, 0x80, 0x1b, 0xb4, 0x43, 0x5e, 0xbd, + 0x6b, 0x7a, 0xfc, 0x85, 0x82, 0xbb, 0xcd, 0x4c, 0xe5, 0xb4, 0xbf, 0x9e, 0xdd, 0x8c, 0xd6, 0x33, 0xf5, 0x05, 0xfd, + 0x19, 0xff, 0xa9, 0x8e, 0xe3, 0x41, 0xb3, 0x91, 0xb0, 0x3f, 0xc7, 0xe0, 0xd7, 0xd3, 0x4f, 0xc7, 0x6c, 0x8a, 0xfa, + 0x83, 0x3f, 0x15, 0x1e, 0x36, 0x82, 0x8c, 0xef, 0x76, 0x53, 0xc0, 0xeb, 0x67, 0x3b, 0x31, 0xfe, 0x0e, 0xf5, 0x51, + 0xff, 0x4f, 0x75, 0xfc, 0x27, 0xba, 0x77, 0x12, 0x68, 0x30, 0xa4, 0xdb, 0xc2, 0x55, 0x28, 0xa0, 0xe3, 0x72, 0x0b, + 0x33, 0xdc, 0x6e, 0x32, 0x08, 0x9c, 0x06, 0x6e, 0xe1, 0x24, 0x96, 0x0d, 0x7e, 0x72, 0xda, 0x42, 0xdf, 0xb5, 0x3b, + 0xa0, 0xe8, 0x68, 0x8a, 0xe3, 0xdd, 0x4d, 0x5f, 0x34, 0x4f, 0xf1, 0x83, 0x66, 0x81, 0xdb, 0x08, 0x37, 0xdb, 0x5e, + 0x03, 0x3d, 0x50, 0x71, 0x0b, 0x61, 0x15, 0x5f, 0xc0, 0x3f, 0x67, 0x68, 0x58, 0x6d, 0xc8, 0xc7, 0x74, 0xbb, 0x77, + 0xf0, 0x61, 0x25, 0xb1, 0x6a, 0xf0, 0x93, 0xf3, 0x16, 0xfa, 0xee, 0xdc, 0x74, 0xc4, 0x8e, 0xf5, 0x9e, 0xae, 0x24, + 0x3e, 0x6b, 0x4a, 0xe8, 0xa8, 0x55, 0xf6, 0x23, 0xe2, 0x2e, 0xc2, 0x22, 0x3e, 0x85, 0x7f, 0xda, 0x61, 0x3f, 0xf7, + 0x76, 0xfa, 0x31, 0xf3, 0x6e, 0xe3, 0xa4, 0x6b, 0x5d, 0x62, 0x95, 0xbd, 0x9f, 0x6e, 0xb0, 0xab, 0xb6, 0xb9, 0x58, + 0x6b, 0x9f, 0xc0, 0x07, 0xc2, 0xfa, 0x98, 0x28, 0xcc, 0x8e, 0xc1, 0x97, 0x16, 0x4c, 0x48, 0xd4, 0xe5, 0x69, 0x4f, + 0x35, 0x1a, 0x48, 0x0c, 0xd4, 0xf0, 0x98, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, 0x6e, 0x90, 0x32, 0x40, 0x9b, 0xa8, + 0x7a, 0x7d, 0xe5, 0x7a, 0xb5, 0xb7, 0xf0, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x1f, 0xeb, 0x26, 0x43, 0x27, 0xa2, 0x11, + 0xeb, 0x4b, 0xd6, 0x3f, 0x4f, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc7, 0xac, 0xc9, 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, + 0xe1, 0xd7, 0x59, 0x00, 0x2d, 0x01, 0x78, 0x57, 0x79, 0x06, 0x15, 0x27, 0x9d, 0x6e, 0x17, 0x0b, 0xc2, 0x93, 0xa9, + 0xf9, 0xa5, 0x08, 0x4f, 0x46, 0xe6, 0x97, 0x24, 0x25, 0xbc, 0x6c, 0xef, 0xb8, 0x20, 0xc1, 0xaa, 0x9a, 0x14, 0x0a, + 0x0b, 0x5a, 0xa0, 0x93, 0x8e, 0xbf, 0xa2, 0xc7, 0x33, 0x3f, 0x07, 0x50, 0x49, 0x14, 0xc6, 0x3a, 0x53, 0x36, 0x0b, + 0x9c, 0x13, 0x7a, 0x95, 0x74, 0xfb, 0xb3, 0x93, 0xb8, 0xd3, 0x94, 0xcd, 0x02, 0xa5, 0xb3, 0x13, 0x53, 0x13, 0x67, + 0xe4, 0x15, 0xb5, 0xad, 0xe1, 0x19, 0xdc, 0xab, 0x66, 0x24, 0x3b, 0x3e, 0x6f, 0x35, 0x92, 0x2e, 0xc2, 0x83, 0x6c, + 0xdd, 0xc2, 0xf9, 0x7a, 0xdd, 0xc2, 0x34, 0x5c, 0x06, 0xe1, 0x01, 0x52, 0x6a, 0xcd, 0xb6, 0xe3, 0xe4, 0xf4, 0x79, + 0xac, 0xc1, 0x46, 0x40, 0x83, 0xe7, 0x8d, 0x06, 0x9f, 0xa0, 0x94, 0xbb, 0xcb, 0x39, 0x64, 0x22, 0x05, 0x4e, 0x42, + 0x3d, 0xda, 0x2b, 0xe1, 0xd7, 0xd5, 0x8d, 0xfc, 0x9e, 0x88, 0x3f, 0x48, 0x6c, 0xd3, 0xaa, 0x62, 0xaf, 0xe9, 0x6e, + 0xb1, 0x7b, 0x74, 0xa7, 0xd8, 0xc3, 0x3d, 0xc5, 0x1e, 0xef, 0x16, 0xfb, 0x5b, 0x06, 0x5a, 0x3f, 0xfe, 0xdd, 0xe9, + 0x79, 0xab, 0x71, 0x0a, 0xc8, 0x7a, 0x7a, 0xde, 0xaa, 0x0a, 0x3d, 0xa5, 0xd5, 0x5a, 0x69, 0xf2, 0x0b, 0xb5, 0x7e, + 0x0f, 0xdc, 0x3b, 0x60, 0x9b, 0x85, 0xb3, 0xee, 0xdf, 0xa5, 0xaf, 0xf7, 0xa0, 0x0b, 0x76, 0x25, 0xc2, 0x50, 0x3b, + 0x3d, 0x38, 0x1f, 0xf6, 0x67, 0x2c, 0x6e, 0x40, 0x2a, 0x4a, 0x27, 0xda, 0xfd, 0x42, 0xe5, 0xf5, 0xf2, 0xdf, 0x12, + 0x92, 0x3a, 0x43, 0x84, 0x25, 0x69, 0xe8, 0xc1, 0xe9, 0xd0, 0x9c, 0x77, 0x05, 0xfc, 0x3e, 0x33, 0xbf, 0x4b, 0xe5, + 0x8e, 0x73, 0x8e, 0x98, 0xdd, 0x8c, 0xa2, 0xbe, 0x20, 0xaf, 0x69, 0x6c, 0xec, 0xdd, 0x51, 0x5a, 0x66, 0xa8, 0x2f, + 0x90, 0xf1, 0xb0, 0xcc, 0x10, 0xe4, 0x95, 0x70, 0xbf, 0xf1, 0xaa, 0x48, 0xc1, 0xf6, 0x05, 0x4f, 0x53, 0xb0, 0x7b, + 0xc1, 0xa3, 0x54, 0x80, 0x6f, 0x06, 0x4d, 0x59, 0x60, 0x51, 0xff, 0xc2, 0x69, 0xd3, 0xcc, 0x0d, 0x30, 0x31, 0x58, + 0xda, 0x63, 0x70, 0x52, 0xfc, 0x2d, 0x63, 0xf8, 0xdb, 0xd0, 0x08, 0x33, 0x68, 0x93, 0x21, 0xcc, 0x93, 0x82, 0x40, + 0x1a, 0xe6, 0xc9, 0x94, 0x30, 0x68, 0x92, 0x27, 0x23, 0xc2, 0x06, 0x9d, 0x00, 0x4d, 0x9e, 0x18, 0xd8, 0x01, 0x70, + 0x78, 0xfd, 0x52, 0x5d, 0xdb, 0xc6, 0xe1, 0xb6, 0x1e, 0x9a, 0x10, 0x04, 0xe2, 0x1f, 0x0c, 0xc0, 0x84, 0x43, 0xd9, + 0x9f, 0x9d, 0x2a, 0x14, 0x25, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, 0xad, 0xd8, 0x06, 0x1f, 0xdc, + 0x5b, 0x89, 0xcd, 0x77, 0xf0, 0x47, 0xd9, 0x3f, 0xc0, 0x3c, 0x24, 0x14, 0x6d, 0xd0, 0x5f, 0x29, 0x14, 0xdb, 0x53, + 0x0a, 0xfd, 0xe5, 0x48, 0xb4, 0x52, 0x64, 0x75, 0x9b, 0x46, 0x63, 0x5a, 0x7c, 0x8e, 0xf0, 0x1f, 0x69, 0x94, 0x03, + 0xb7, 0x18, 0xe1, 0x0f, 0x69, 0x54, 0xb0, 0x08, 0xff, 0x9e, 0x46, 0xa3, 0x7c, 0x19, 0xe1, 0xdf, 0xd2, 0x68, 0x5a, + 0x44, 0xf8, 0x3d, 0x28, 0x4e, 0xc7, 0x7c, 0x39, 0x8f, 0xf0, 0xbb, 0x34, 0x52, 0xc6, 0x33, 0x01, 0x3f, 0x4c, 0x23, + 0xc6, 0x22, 0xfc, 0x36, 0x8d, 0x64, 0x1e, 0xe1, 0xeb, 0x34, 0x92, 0x45, 0x84, 0x1f, 0xa5, 0x51, 0x41, 0x23, 0xfc, + 0x38, 0x8d, 0xa0, 0xd0, 0x34, 0xc2, 0x4f, 0xd2, 0x08, 0x5a, 0x56, 0x11, 0x7e, 0x93, 0x46, 0x5c, 0x44, 0xf8, 0xd7, + 0x34, 0xd2, 0xcb, 0xe2, 0xef, 0xa5, 0xe4, 0x2a, 0xc2, 0x4f, 0xd3, 0x68, 0xc6, 0x23, 0xfc, 0x3a, 0x8d, 0x0a, 0x19, + 0xe1, 0x57, 0x69, 0x44, 0xf3, 0x08, 0xbf, 0x4c, 0xa3, 0x9c, 0x45, 0xf8, 0x97, 0x34, 0x1a, 0xb3, 0x08, 0xff, 0x9c, + 0x46, 0x77, 0x2c, 0xcf, 0x65, 0x84, 0x9f, 0xa5, 0x11, 0x13, 0x11, 0xfe, 0x29, 0x8d, 0xb2, 0x59, 0x84, 0x7f, 0x48, + 0x23, 0x5a, 0x7c, 0x56, 0x11, 0x7e, 0x9e, 0x46, 0x8c, 0x46, 0xf8, 0x85, 0xed, 0x68, 0x1a, 0xe1, 0x1f, 0xd3, 0xe8, + 0x66, 0x16, 0x6d, 0xb0, 0x54, 0x64, 0xf5, 0x8a, 0x67, 0xec, 0x77, 0x96, 0x46, 0x93, 0xd6, 0xe4, 0x62, 0x32, 0x89, + 0x30, 0x15, 0x9a, 0xff, 0xbd, 0x64, 0x37, 0x4f, 0x35, 0x24, 0x52, 0x36, 0x1a, 0xdf, 0x8f, 0x30, 0xfd, 0x7b, 0x49, + 0xd3, 0x68, 0x32, 0x31, 0x05, 0xfe, 0x5e, 0xd2, 0x39, 0x2d, 0xde, 0xb0, 0x34, 0xba, 0x3f, 0x99, 0x4c, 0xc6, 0x67, + 0x11, 0xa6, 0xff, 0x2c, 0x3f, 0x98, 0x16, 0x4c, 0x81, 0x11, 0xe3, 0x53, 0xa8, 0xdb, 0x9d, 0x74, 0xc7, 0x59, 0x84, + 0x47, 0x5c, 0xfd, 0xbd, 0x84, 0xef, 0x09, 0x3b, 0xcb, 0xce, 0x22, 0x3c, 0xca, 0x69, 0xf6, 0x39, 0x8d, 0x5a, 0xe6, + 0x97, 0xf8, 0x89, 0x8d, 0x5f, 0xcd, 0xa5, 0xb9, 0x56, 0x98, 0xb0, 0x51, 0x36, 0x8e, 0xb0, 0x19, 0xcc, 0x04, 0xfe, + 0x7e, 0xe1, 0x6f, 0x99, 0x4e, 0xa3, 0x0b, 0xda, 0x19, 0xb1, 0x4e, 0x84, 0x47, 0xaf, 0x6f, 0x44, 0x1a, 0xd1, 0x6e, + 0x87, 0x76, 0x68, 0x84, 0x47, 0xcb, 0x22, 0xbf, 0xbb, 0x91, 0x72, 0x0c, 0x40, 0x18, 0x5d, 0x5c, 0xdc, 0x8f, 0x70, + 0x46, 0x7f, 0xd1, 0x50, 0xbb, 0x3b, 0x79, 0xc0, 0x68, 0x2b, 0xc2, 0x3f, 0xd1, 0x42, 0x7f, 0x58, 0x2a, 0x37, 0xd0, + 0x16, 0xa4, 0xc8, 0xec, 0x2d, 0xa8, 0xdc, 0xa3, 0x71, 0xe7, 0xfc, 0x41, 0x9b, 0x45, 0x38, 0xbb, 0x7e, 0x05, 0xbd, + 0xdd, 0x9f, 0x74, 0x5b, 0xf0, 0x21, 0x40, 0x2e, 0x65, 0x05, 0x34, 0x72, 0x7e, 0xf6, 0xa0, 0xcb, 0xc6, 0x26, 0x51, + 0xf1, 0xfc, 0xb3, 0x99, 0xfd, 0x05, 0xcc, 0x27, 0x2b, 0xf8, 0x5c, 0x49, 0x91, 0x46, 0xe3, 0xac, 0x7d, 0x76, 0x0a, + 0x09, 0x77, 0x54, 0x78, 0xe0, 0xdc, 0x42, 0xd5, 0x8b, 0x51, 0x84, 0x6f, 0x6d, 0xea, 0xc5, 0xc8, 0x7c, 0x4c, 0xdf, + 0xfe, 0x22, 0x5e, 0x8f, 0xd3, 0x68, 0x74, 0x71, 0x71, 0xde, 0x82, 0x84, 0xdf, 0xe8, 0x5d, 0x1a, 0xd1, 0x07, 0xf0, + 0x1f, 0x64, 0x7f, 0x78, 0x06, 0x1d, 0xc2, 0x08, 0x6f, 0xa7, 0x1f, 0xc2, 0x9c, 0xcf, 0x33, 0xfa, 0x99, 0xa7, 0xd1, + 0x68, 0x3c, 0xba, 0x7f, 0x0e, 0xf5, 0xe6, 0x74, 0xfa, 0x4c, 0x53, 0x68, 0xb7, 0xd5, 0x32, 0x2d, 0xbf, 0xe5, 0x5f, + 0x98, 0xa9, 0xde, 0xed, 0x9e, 0x8f, 0x3a, 0x30, 0x82, 0x6b, 0x50, 0xa8, 0xc0, 0x78, 0x2e, 0x32, 0xd3, 0xe0, 0x75, + 0xf6, 0x74, 0x9c, 0x46, 0x0f, 0x1e, 0x9c, 0x76, 0xb2, 0x2c, 0xc2, 0xb7, 0x1f, 0xc6, 0xb6, 0xb6, 0xc9, 0x53, 0x00, + 0xfb, 0x34, 0x62, 0x0f, 0x1e, 0x9c, 0xdf, 0xa7, 0xf0, 0xfd, 0xdc, 0xb4, 0x75, 0x31, 0x19, 0x65, 0x17, 0xd0, 0xd6, + 0x3b, 0x98, 0xce, 0xd9, 0xc5, 0xe9, 0xd8, 0xf4, 0xf5, 0xce, 0x8c, 0xba, 0x33, 0x39, 0x9b, 0x9c, 0x99, 0x4c, 0x33, + 0xd4, 0xf2, 0xf3, 0x57, 0x96, 0x46, 0x19, 0x1b, 0xb7, 0x23, 0x7c, 0xeb, 0x16, 0xee, 0xc1, 0x59, 0xab, 0x35, 0x3e, + 0x8d, 0xf0, 0xf8, 0xe1, 0x62, 0xf1, 0xc6, 0x40, 0xb0, 0x7d, 0xf6, 0xc0, 0x7e, 0xab, 0xcf, 0x77, 0xd0, 0xf4, 0xc8, + 0x00, 0x6d, 0xcc, 0xe7, 0xa6, 0xe5, 0xf3, 0x07, 0xf0, 0x9f, 0xf9, 0x36, 0x4d, 0x97, 0xdf, 0x72, 0x3c, 0xb5, 0x8b, + 0xd2, 0x66, 0x0f, 0x5a, 0x50, 0x63, 0xc2, 0x3f, 0x8c, 0x0a, 0x0e, 0x68, 0x34, 0xea, 0xc0, 0xff, 0x45, 0x78, 0x92, + 0x5f, 0xbf, 0x72, 0x38, 0x3b, 0x99, 0xd0, 0x49, 0x2b, 0xc2, 0x13, 0xf9, 0x41, 0xe9, 0xdf, 0x1e, 0x8a, 0x34, 0xea, + 0x74, 0x2e, 0x46, 0xa6, 0xcc, 0xf2, 0x27, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x53, 0xfa, 0x46, 0x8d, 0xae, 0x25, + 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x29, 0x68, 0xc4, 0x5c, 0x2b, 0x17, 0x76, 0x3b, 0x4c, 0xdf, 0x1a, 0xd4, 0x1c, 0xdf, + 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x53, 0xda, 0xed, 0xb4, 0x22, 0x6c, 0x46, 0x7d, 0xd1, 0x82, 0xff, 0x22, 0x6c, 0x21, + 0x67, 0xe0, 0x3a, 0xfd, 0xf0, 0xec, 0xe7, 0x9b, 0x34, 0xa2, 0xe3, 0xc9, 0x04, 0x96, 0xc4, 0x4c, 0xc6, 0x17, 0x9b, + 0x49, 0xc1, 0xee, 0x7e, 0xb9, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xf3, 0x07, 0xa3, 0xb3, 0x08, 0xbf, 0x19, + 0x73, 0x2a, 0x60, 0x95, 0xb2, 0x71, 0x37, 0xeb, 0x66, 0x26, 0x61, 0x2a, 0xd3, 0xe8, 0x0c, 0x96, 0xbc, 0x13, 0x61, + 0xfe, 0xe5, 0xfa, 0xce, 0xa2, 0x1b, 0xd4, 0x76, 0x08, 0x32, 0x69, 0xb1, 0xf3, 0x8b, 0x2c, 0xc2, 0x39, 0xfd, 0xf2, + 0xec, 0x97, 0x22, 0x8d, 0xd8, 0x39, 0x3b, 0x9f, 0x50, 0xff, 0xfd, 0xbb, 0x9a, 0x99, 0x1a, 0xad, 0x49, 0x17, 0x92, + 0x6e, 0x84, 0x19, 0xeb, 0xfd, 0x6c, 0x62, 0x30, 0xe4, 0xe5, 0x5c, 0x8a, 0xec, 0xe9, 0x64, 0x22, 0x2d, 0x16, 0x53, + 0xd8, 0x84, 0x7f, 0x00, 0xb4, 0xe9, 0x78, 0x7c, 0xc1, 0xce, 0x23, 0xfc, 0x87, 0xdd, 0x25, 0x6e, 0x02, 0x7f, 0x58, + 0xcc, 0x66, 0x6e, 0xb7, 0xff, 0x61, 0x81, 0x02, 0xf3, 0x9d, 0xd0, 0x09, 0x1d, 0x77, 0x22, 0xfc, 0x87, 0x81, 0xcb, + 0xf8, 0x14, 0xfe, 0x83, 0x02, 0xd0, 0xd9, 0x83, 0x16, 0x63, 0x0f, 0x5a, 0xe6, 0x2b, 0xcc, 0x73, 0x33, 0x1f, 0x9d, + 0x67, 0xed, 0x08, 0xff, 0xe1, 0xd0, 0x71, 0x32, 0xa1, 0x2d, 0x40, 0xc7, 0x3f, 0x1c, 0x3a, 0x76, 0x5a, 0xa3, 0x0e, + 0x35, 0xdf, 0x16, 0x6b, 0x2e, 0xee, 0x67, 0x0c, 0x26, 0xf7, 0x87, 0x45, 0xc8, 0xfb, 0xf7, 0x2f, 0x2e, 0x1e, 0x3c, + 0x80, 0x4f, 0xd3, 0x76, 0xf9, 0xa9, 0xf4, 0xc3, 0xdc, 0x20, 0x59, 0x2b, 0x3b, 0x03, 0x3a, 0xf9, 0x87, 0x19, 0xe3, + 0x64, 0x32, 0x61, 0xad, 0x08, 0xe7, 0x7c, 0xce, 0x2c, 0x26, 0xd8, 0xdf, 0xa6, 0xa3, 0xd3, 0x4e, 0x36, 0x3e, 0xed, + 0x44, 0x38, 0x7f, 0xf3, 0xcc, 0xcc, 0xa6, 0x05, 0xb3, 0xf7, 0x5b, 0xce, 0x63, 0xcd, 0x9c, 0xbe, 0x86, 0x41, 0xc2, + 0x4a, 0x43, 0xe5, 0xf7, 0x01, 0x3d, 0x3c, 0x3f, 0xcf, 0xc6, 0x30, 0xd0, 0xf7, 0xd0, 0x2d, 0x80, 0xf1, 0xbd, 0xdd, + 0x7c, 0x23, 0xda, 0xed, 0xc2, 0x74, 0xdf, 0x2f, 0x96, 0xc5, 0xe2, 0x65, 0x1a, 0x3d, 0x38, 0xbd, 0xdf, 0x1a, 0x8f, + 0x22, 0xfc, 0xde, 0x4d, 0xf0, 0x34, 0x1b, 0x9d, 0xde, 0x6f, 0x47, 0xf8, 0xbd, 0xd9, 0x6f, 0xf7, 0x47, 0xe7, 0x17, + 0x70, 0x6e, 0xbc, 0x57, 0x8b, 0xe2, 0xcd, 0xd4, 0x14, 0x98, 0xd0, 0x07, 0xd0, 0xec, 0xaf, 0x66, 0x37, 0x8e, 0xdb, + 0xb0, 0x91, 0xdf, 0x9b, 0x4d, 0x66, 0xf0, 0xe4, 0x7e, 0xbb, 0x7b, 0xd1, 0x8d, 0xf0, 0x9c, 0x8f, 0x05, 0x10, 0x78, + 0xb3, 0x51, 0x1e, 0xb4, 0x1f, 0xdc, 0x6f, 0x45, 0x78, 0xfe, 0x46, 0x67, 0x1f, 0xe8, 0xdc, 0x50, 0xe3, 0x09, 0xc0, + 0x6c, 0xce, 0x95, 0xbe, 0x7b, 0xad, 0x1c, 0x3d, 0x66, 0xed, 0x08, 0xcf, 0x65, 0x96, 0x51, 0xf5, 0xc6, 0x26, 0x8c, + 0xba, 0x11, 0x16, 0xf4, 0x0b, 0xfd, 0x24, 0xfd, 0x66, 0x1a, 0x33, 0x3a, 0x36, 0x69, 0x06, 0x87, 0x23, 0xfc, 0x76, + 0x0c, 0x17, 0x83, 0x69, 0x34, 0x19, 0x4f, 0xba, 0x00, 0x1e, 0x20, 0x40, 0x16, 0xbb, 0x01, 0x1a, 0xf0, 0x35, 0x7e, + 0x34, 0x4a, 0xa3, 0xf3, 0xd1, 0x05, 0xeb, 0x9c, 0x46, 0xb8, 0xa4, 0x46, 0xb4, 0x0b, 0xf9, 0xe6, 0xf3, 0x83, 0xd9, + 0x52, 0x67, 0x36, 0xc1, 0x00, 0x68, 0x4c, 0xef, 0xb7, 0xc6, 0xe7, 0x11, 0x5e, 0xbc, 0x62, 0x7e, 0x8f, 0x31, 0xc6, + 0x2e, 0x00, 0x96, 0x90, 0x64, 0x10, 0xe8, 0x62, 0x32, 0x7a, 0x70, 0x61, 0xbe, 0x01, 0x0c, 0x74, 0xc2, 0x18, 0x00, + 0x69, 0xf1, 0x8a, 0x95, 0x80, 0x18, 0x8f, 0xee, 0xb7, 0x80, 0xbe, 0x2c, 0xe8, 0x82, 0xde, 0xd1, 0x9b, 0xa7, 0x0b, + 0x33, 0xa7, 0xc9, 0xb8, 0x1b, 0xe1, 0xc5, 0xf3, 0x9f, 0x16, 0xcb, 0xc9, 0xc4, 0x4c, 0x88, 0x8e, 0x1e, 0x44, 0x78, + 0xc1, 0x8a, 0x25, 0xac, 0xd1, 0x45, 0xf7, 0x74, 0x12, 0x61, 0x87, 0x86, 0x59, 0x2b, 0x1b, 0xc1, 0xcd, 0xe7, 0x72, + 0x9e, 0x46, 0xe3, 0x31, 0x6d, 0x8d, 0xe1, 0x1e, 0x54, 0xde, 0xfc, 0x52, 0x58, 0x34, 0x62, 0x06, 0x1f, 0xdc, 0x1a, + 0xc2, 0x7c, 0x01, 0x1e, 0x1f, 0x46, 0x2c, 0xcb, 0xa8, 0x4b, 0x3c, 0x3f, 0x3f, 0x3d, 0x05, 0xdc, 0xb3, 0x33, 0xb4, + 0x08, 0xf2, 0x5a, 0xdd, 0x8d, 0x0a, 0x09, 0x47, 0x17, 0x10, 0x55, 0x20, 0xab, 0xaf, 0xef, 0x5e, 0x19, 0xba, 0xda, + 0x3e, 0x7f, 0x00, 0x0b, 0xa0, 0xe8, 0x78, 0xfc, 0xd2, 0x1e, 0x6e, 0x17, 0xa3, 0xb3, 0x6e, 0xfb, 0x34, 0xc2, 0x7e, + 0x23, 0xd0, 0x8b, 0xd6, 0xfd, 0x0e, 0x94, 0x10, 0xe3, 0x3b, 0x5b, 0x62, 0x72, 0x46, 0xcf, 0xce, 0x5b, 0x11, 0xf6, + 0x5b, 0x83, 0x5d, 0x8c, 0xba, 0xf7, 0xe1, 0x53, 0xcd, 0x58, 0x9e, 0x1b, 0xfc, 0xee, 0x02, 0x5c, 0x14, 0x7f, 0x26, + 0x68, 0x1a, 0xd1, 0x56, 0xb7, 0xd3, 0x19, 0xc3, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, 0xb5, 0xe0, 0xbf, 0x08, 0x07, + 0x3b, 0x89, 0x8d, 0x22, 0x6c, 0xf0, 0xee, 0x9c, 0x76, 0xcd, 0xde, 0x77, 0xbb, 0xaa, 0x75, 0xd1, 0x82, 0x0d, 0xeb, + 0x36, 0x95, 0xfb, 0x52, 0x42, 0xde, 0x38, 0x12, 0x4b, 0x23, 0x1c, 0x20, 0xe8, 0xe4, 0xfe, 0x24, 0xc2, 0x7e, 0xc7, + 0x9d, 0x9d, 0x5f, 0x74, 0x80, 0x94, 0x69, 0x20, 0x14, 0xe3, 0xce, 0xe8, 0x0c, 0x48, 0x93, 0x66, 0xaf, 0x2c, 0x9e, + 0x44, 0x58, 0x3f, 0x55, 0xfa, 0x65, 0x1a, 0x8d, 0x2f, 0x46, 0x93, 0xf1, 0x45, 0x84, 0xb5, 0x9c, 0x53, 0x2d, 0x0d, + 0x05, 0x3c, 0x3d, 0xbb, 0x1f, 0x61, 0x83, 0xe6, 0x2d, 0xd6, 0x1a, 0xb7, 0x22, 0xec, 0x8e, 0x12, 0xc6, 0x2e, 0x3a, + 0x30, 0xad, 0x1f, 0x9f, 0x6b, 0xc0, 0xe5, 0x31, 0x1b, 0x9d, 0x46, 0xb8, 0xa4, 0xf7, 0x86, 0x10, 0xc1, 0x97, 0x9a, + 0xcb, 0xcf, 0x8e, 0xf5, 0x00, 0x52, 0xe7, 0x37, 0x3c, 0x2c, 0xc3, 0xcf, 0x37, 0x16, 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, + 0xcd, 0xf0, 0x5b, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xd5, 0x06, 0x97, 0x01, 0x57, 0x3f, 0xb3, 0x3b, 0x15, 0x4b, 0x65, + 0x38, 0xd9, 0x20, 0x45, 0x29, 0xe4, 0x5d, 0x0c, 0x9c, 0x17, 0x29, 0x08, 0x92, 0x82, 0xb4, 0x7a, 0xe2, 0xd2, 0x7b, + 0xb6, 0xf6, 0x04, 0x84, 0x61, 0x80, 0xf4, 0x82, 0x50, 0xa2, 0x21, 0x5a, 0x8d, 0x15, 0x26, 0xbd, 0xc1, 0xbf, 0x91, + 0x29, 0xa5, 0x75, 0x21, 0xa0, 0x84, 0xfa, 0x38, 0xf5, 0xb1, 0xc4, 0x0a, 0x22, 0x39, 0xa1, 0x9e, 0x24, 0x26, 0xea, + 0xf4, 0x0b, 0xa1, 0x63, 0xa9, 0x06, 0xc5, 0x10, 0xb7, 0xcf, 0x11, 0x86, 0x78, 0x0e, 0x64, 0x20, 0xaf, 0xae, 0xda, + 0xe7, 0x47, 0x46, 0xe8, 0xbb, 0xba, 0xba, 0xb0, 0x3f, 0xe0, 0xdf, 0x61, 0x15, 0x43, 0x1b, 0xc6, 0xf7, 0x9e, 0x55, + 0x73, 0xfc, 0xd9, 0xf0, 0xd7, 0xef, 0xd9, 0x7a, 0x1d, 0xbf, 0x67, 0x04, 0x66, 0x8c, 0xdf, 0xb3, 0xc4, 0xdc, 0x91, + 0x58, 0x6f, 0x1d, 0x32, 0x00, 0xcd, 0x59, 0x0b, 0x43, 0x64, 0x77, 0xcf, 0x79, 0xbf, 0x67, 0x03, 0x5e, 0xf7, 0xf4, + 0xae, 0xc2, 0x29, 0x1f, 0x1d, 0xad, 0x8a, 0x54, 0x5b, 0x31, 0x41, 0x5b, 0x31, 0x41, 0x5b, 0x31, 0x41, 0x57, 0x01, + 0xed, 0xcf, 0xfa, 0x20, 0xa5, 0x18, 0x65, 0x8b, 0xe3, 0xa9, 0xdf, 0x80, 0xda, 0x03, 0xb4, 0x93, 0xfd, 0x4a, 0xd9, + 0x51, 0xea, 0x2a, 0xf6, 0x2a, 0x30, 0xf6, 0x26, 0x3a, 0x6d, 0xc7, 0xc9, 0xbf, 0xa3, 0xee, 0x78, 0x56, 0x13, 0xcb, + 0xde, 0xec, 0x15, 0xcb, 0x60, 0x25, 0x8d, 0x68, 0x76, 0x68, 0x63, 0x83, 0xe8, 0xc1, 0x7d, 0x23, 0x98, 0x55, 0x01, + 0xeb, 0x1a, 0x90, 0xd4, 0x03, 0x29, 0xe4, 0xc2, 0x48, 0x69, 0x05, 0x4a, 0xc7, 0x3a, 0x2e, 0x40, 0x43, 0xe9, 0x15, + 0x94, 0x65, 0x5c, 0xd5, 0x86, 0x01, 0x88, 0xb2, 0x32, 0x9a, 0x95, 0xd5, 0xba, 0x20, 0xba, 0x80, 0x26, 0xcc, 0x48, + 0x2c, 0xd0, 0x80, 0x30, 0x0d, 0x08, 0x57, 0x19, 0xc4, 0x19, 0x97, 0x7d, 0x66, 0xb2, 0x95, 0xc9, 0x56, 0x65, 0xb6, + 0xf4, 0xd9, 0x56, 0x48, 0x94, 0x26, 0x5b, 0x96, 0xd9, 0x20, 0xb3, 0xe1, 0x69, 0xaa, 0xf0, 0x28, 0x95, 0x56, 0x54, + 0xab, 0x64, 0xab, 0x97, 0x34, 0xd4, 0xe6, 0x1e, 0x1d, 0xc5, 0xa5, 0x9c, 0x64, 0xd4, 0xc4, 0xf7, 0x56, 0x3c, 0x29, + 0x8c, 0x0c, 0xc4, 0x93, 0xa9, 0xfb, 0x3b, 0xda, 0x6c, 0xcb, 0x4a, 0xc5, 0x74, 0xf4, 0x95, 0x92, 0xe8, 0x2f, 0xaf, + 0x44, 0x7d, 0xce, 0x4d, 0x44, 0x9e, 0x4b, 0x92, 0xb4, 0x5a, 0xa7, 0xed, 0xd3, 0xd6, 0x45, 0x9f, 0x1f, 0xb7, 0x3b, + 0xc9, 0x83, 0x4e, 0x6a, 0x14, 0x11, 0x0b, 0x79, 0x03, 0x0a, 0x98, 0x93, 0x4e, 0x72, 0x86, 0x8e, 0xdb, 0x49, 0xab, + 0xdb, 0x6d, 0xc2, 0x3f, 0xf8, 0x91, 0x2e, 0xab, 0x9d, 0xb5, 0xce, 0xba, 0x7d, 0x7e, 0xb2, 0x55, 0x29, 0xe6, 0x0d, + 0x28, 0x88, 0x4e, 0x4c, 0x25, 0x0c, 0xf5, 0xab, 0xe5, 0xfd, 0x67, 0x47, 0xcf, 0xf3, 0x48, 0xc7, 0xd2, 0xaa, 0xe2, + 0x00, 0xaa, 0xfe, 0x6b, 0x6a, 0x80, 0xe8, 0xbf, 0x46, 0x65, 0xd4, 0xdc, 0x55, 0x01, 0xa2, 0xf6, 0x73, 0x1e, 0x8b, + 0x06, 0x3b, 0x8e, 0x6d, 0xbe, 0x86, 0xba, 0x4d, 0x88, 0x64, 0x87, 0xa7, 0x2e, 0x57, 0x85, 0xb9, 0x53, 0x84, 0x9a, + 0x0a, 0x72, 0x47, 0x2e, 0x57, 0x86, 0xb9, 0x23, 0x84, 0x9a, 0x12, 0x72, 0x69, 0xca, 0x13, 0x0a, 0x39, 0x3a, 0xa1, + 0x4d, 0x03, 0xc9, 0x6a, 0x51, 0x9e, 0x33, 0x3f, 0x6c, 0x3e, 0x81, 0xe5, 0x31, 0x04, 0xc5, 0x09, 0xd2, 0x02, 0x5e, + 0x3b, 0x29, 0xb5, 0x39, 0x2d, 0x5c, 0xaa, 0x71, 0x20, 0xa3, 0x01, 0xff, 0x1c, 0x33, 0xf3, 0x04, 0x46, 0xab, 0x7f, + 0x7a, 0xde, 0x4a, 0xdb, 0xe0, 0xb6, 0x0d, 0xb2, 0xb6, 0xb0, 0xb2, 0xb6, 0xf0, 0xb2, 0xb6, 0xf0, 0xb2, 0x36, 0x08, + 0xf0, 0x41, 0xdf, 0xbf, 0xcb, 0x9a, 0x29, 0x0c, 0x2f, 0xed, 0x6a, 0xac, 0xe1, 0x44, 0xac, 0xd7, 0xeb, 0xd5, 0x06, + 0xac, 0x9e, 0xca, 0x1a, 0x85, 0xaa, 0xd4, 0x9f, 0xab, 0x22, 0x6d, 0xe1, 0x69, 0x0a, 0x5a, 0xee, 0x16, 0xa6, 0x66, + 0x73, 0x7b, 0xaa, 0xb0, 0x1d, 0x51, 0xa7, 0xef, 0xd5, 0xc9, 0x57, 0xe4, 0xd4, 0x68, 0x8f, 0x57, 0x45, 0xca, 0x2d, + 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, 0x4a, 0xe0, 0x4a, 0x60, 0x70, + 0x3a, 0x84, 0x80, 0x82, 0xb1, 0x26, 0x66, 0xd4, 0x5b, 0x9d, 0xb7, 0x21, 0x80, 0x9a, 0x2d, 0xa9, 0x13, 0x6a, 0xfc, + 0xc8, 0xcb, 0x31, 0x7f, 0xaa, 0xa1, 0x7d, 0x02, 0xaf, 0xdb, 0x3c, 0xd4, 0x71, 0x0b, 0xcc, 0x48, 0xa2, 0x22, 0xea, + 0x1b, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x0f, 0xff, 0xbc, 0xe5, 0x95, 0x6b, 0x29, 0x41, 0xf8, 0xa6, 0xc3, 0x67, + 0x56, 0x85, 0x09, 0x28, 0xad, 0x5f, 0x9d, 0xe9, 0x9a, 0x3d, 0x12, 0x7a, 0x60, 0xc2, 0xee, 0xe3, 0x4f, 0xf5, 0x05, + 0x29, 0x20, 0xfe, 0x62, 0x6a, 0x12, 0x5d, 0x04, 0x65, 0x70, 0x28, 0x26, 0x37, 0xd4, 0xb8, 0xd7, 0xfc, 0x6c, 0xff, + 0x7c, 0xa2, 0x81, 0xff, 0x61, 0x31, 0x1d, 0x79, 0xb7, 0xdd, 0x8f, 0x26, 0xce, 0x10, 0x39, 0x3c, 0xb4, 0xd6, 0xe5, + 0xe6, 0x6b, 0xdb, 0xbc, 0xdc, 0x24, 0x9a, 0x6c, 0xd8, 0xa1, 0x7e, 0x8d, 0x7e, 0xf7, 0xde, 0x73, 0xc5, 0x74, 0x84, + 0x02, 0x9a, 0x6d, 0xc0, 0x2a, 0x2b, 0x60, 0x29, 0x57, 0xaf, 0x74, 0xaa, 0x84, 0xde, 0xcd, 0x98, 0x37, 0xc5, 0x74, + 0xb4, 0xf7, 0x19, 0x14, 0xdb, 0x63, 0xff, 0x25, 0x0d, 0x7a, 0xf0, 0xaa, 0xed, 0x19, 0xbb, 0xfd, 0x56, 0x9d, 0xeb, + 0xbd, 0x75, 0x54, 0xfe, 0xad, 0x3a, 0x4f, 0xf6, 0xd5, 0x99, 0xf3, 0xdb, 0xd8, 0xef, 0x1d, 0x1d, 0xa8, 0xb1, 0x8d, + 0xc9, 0xd2, 0x74, 0x04, 0x71, 0xeb, 0xe1, 0xaf, 0x8d, 0x2e, 0xd3, 0xf3, 0x24, 0x1c, 0x56, 0x41, 0xf6, 0x93, 0x6e, + 0xca, 0x30, 0x25, 0x9d, 0xe3, 0xc2, 0xc4, 0x97, 0x11, 0x09, 0x6d, 0xaa, 0x84, 0xe2, 0x9c, 0xc4, 0x31, 0x3d, 0xce, + 0x20, 0x4a, 0x4e, 0xbb, 0x4f, 0xd3, 0x98, 0x36, 0x32, 0x74, 0x12, 0xb7, 0x1b, 0xf4, 0x38, 0x43, 0xa8, 0xd1, 0x06, + 0x9d, 0xa9, 0x24, 0xed, 0x66, 0x0e, 0x71, 0x33, 0x0d, 0x29, 0xce, 0x8f, 0x45, 0x52, 0x34, 0xe4, 0xb1, 0x4a, 0x8a, + 0x46, 0xd2, 0xc5, 0x22, 0x99, 0x96, 0xc9, 0x53, 0x93, 0x3c, 0xb5, 0xc9, 0xa3, 0x32, 0x79, 0x64, 0x92, 0x47, 0x36, + 0x99, 0x92, 0xe2, 0x58, 0x24, 0xb4, 0x11, 0xb7, 0x9b, 0x05, 0x3a, 0x86, 0x11, 0xf8, 0xd1, 0x13, 0x11, 0x86, 0x2b, + 0xdf, 0x18, 0x7b, 0x9f, 0x85, 0xcc, 0x5d, 0x00, 0xd1, 0x0a, 0x48, 0xa5, 0x13, 0x16, 0xd4, 0xf9, 0x27, 0x00, 0x13, + 0xd6, 0xf6, 0x8f, 0x0f, 0x8f, 0xb7, 0xc9, 0x72, 0x29, 0x02, 0x27, 0x33, 0xb0, 0x8b, 0xff, 0xec, 0x5c, 0x6b, 0x00, + 0xaa, 0x1b, 0x9a, 0x2f, 0x66, 0x74, 0xc7, 0x93, 0xb7, 0x98, 0x8e, 0xdc, 0xce, 0x2a, 0x9b, 0x61, 0xb4, 0xb0, 0x61, + 0xa7, 0xeb, 0x3e, 0x97, 0x00, 0x6a, 0xef, 0xe7, 0x99, 0x50, 0xa3, 0x24, 0xb7, 0x35, 0xa6, 0x05, 0xbb, 0x53, 0x19, + 0xcd, 0x59, 0x5c, 0x1d, 0xc0, 0xd5, 0x30, 0x19, 0x79, 0x02, 0xd6, 0xf9, 0xc5, 0x71, 0x72, 0xda, 0xd0, 0xc9, 0xf4, + 0x38, 0xe9, 0x3e, 0x68, 0xe8, 0x64, 0x74, 0x9c, 0xb4, 0xdb, 0x15, 0xce, 0x26, 0x05, 0xd1, 0xc9, 0x94, 0x68, 0xd0, + 0x18, 0xda, 0x46, 0xe5, 0x82, 0x82, 0xb9, 0xd9, 0xbf, 0x31, 0x8c, 0x86, 0x1b, 0x86, 0x60, 0x53, 0x1b, 0x81, 0x73, + 0x67, 0x0c, 0x61, 0x37, 0x9d, 0x6e, 0xb7, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, 0x4c, 0xb1, 0xb6, 0xcb, + 0xd7, 0xd4, 0xc9, 0xc8, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, 0x77, 0xbc, 0xc3, 0xcc, + 0x06, 0xb4, 0x86, 0xdf, 0x2a, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x76, 0xc4, 0xbe, 0x56, 0xb4, 0x5d, 0x35, 0xc9, + 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x17, 0x35, 0x0c, 0x71, 0xa5, 0xdc, 0xc1, 0xfd, 0x88, 0x92, + 0x18, 0xe2, 0xec, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0x6c, 0x50, 0x1c, 0x9c, 0xb7, 0x2f, + 0x42, 0xaa, 0xba, 0x13, 0x7c, 0x8f, 0x90, 0x68, 0x29, 0xac, 0x79, 0xe6, 0x38, 0xaa, 0x68, 0xf1, 0x1b, 0xa7, 0xdd, + 0xad, 0x1d, 0x10, 0x47, 0x47, 0xdb, 0xe7, 0x85, 0x7f, 0x06, 0x61, 0xe7, 0xe9, 0x83, 0xca, 0xb6, 0xcf, 0x3f, 0xce, + 0x64, 0xad, 0x7e, 0x79, 0x80, 0x28, 0x3e, 0x0c, 0xd6, 0x7d, 0x43, 0xe1, 0x07, 0x55, 0x0c, 0x40, 0x97, 0xd3, 0x3c, + 0x37, 0x19, 0xa6, 0xaf, 0x61, 0x30, 0xb6, 0x57, 0xe1, 0x84, 0x4a, 0xbb, 0xc5, 0x7f, 0xd9, 0x71, 0xd0, 0x89, 0x7b, + 0x3c, 0x26, 0x6c, 0xf4, 0x53, 0x68, 0x25, 0x5c, 0xc1, 0xc6, 0xf9, 0x87, 0xaf, 0xd7, 0xb5, 0xa7, 0x82, 0xec, 0x83, + 0x34, 0xe8, 0xe8, 0x88, 0xab, 0x67, 0x60, 0xd8, 0xcc, 0xe2, 0x46, 0x78, 0xf8, 0xfe, 0x5d, 0x3b, 0xad, 0x3f, 0x99, + 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0xbd, 0x2b, 0xd1, 0xd7, 0x29, 0x77, 0x6b, 0xfd, 0xbe, 0x32, 0x1b, + 0xdf, 0x79, 0xb4, 0xea, 0xe8, 0x88, 0x57, 0xa1, 0xa3, 0xa2, 0xef, 0x22, 0xd4, 0x37, 0x32, 0xc8, 0xb3, 0x5c, 0x52, + 0xb8, 0x11, 0x85, 0x2b, 0x86, 0xb4, 0xc1, 0x4f, 0x34, 0xfe, 0x49, 0xfe, 0x7f, 0x6a, 0xe4, 0x58, 0xa7, 0x0d, 0x1e, + 0x98, 0x1b, 0x84, 0xac, 0x50, 0x15, 0xb4, 0xd1, 0x40, 0x3a, 0xb4, 0x02, 0x47, 0xe5, 0x61, 0x4e, 0x17, 0x8b, 0xfc, + 0xce, 0xbc, 0xdb, 0x15, 0x70, 0x54, 0xd5, 0x45, 0x93, 0x8b, 0x98, 0x87, 0x0b, 0xe0, 0xe9, 0x01, 0xf7, 0x90, 0xf1, + 0x78, 0x2d, 0x2f, 0xb7, 0x05, 0x02, 0xc9, 0x4c, 0x11, 0xd9, 0x6c, 0xf7, 0xd4, 0x15, 0xc8, 0x65, 0xcd, 0x26, 0xd2, + 0x2e, 0x90, 0x38, 0xe6, 0x20, 0x93, 0x29, 0xeb, 0xd5, 0x7a, 0x60, 0x0b, 0x82, 0xe4, 0x26, 0x8d, 0xc8, 0xb6, 0xbf, + 0x14, 0x9f, 0xc4, 0x80, 0x46, 0xc8, 0x0a, 0x7c, 0xa1, 0xb0, 0xc8, 0x81, 0xeb, 0x2c, 0x7c, 0xc7, 0x5f, 0x69, 0xa9, + 0x18, 0xa8, 0xe1, 0x10, 0x17, 0xe6, 0xa9, 0x8a, 0x72, 0x3e, 0x54, 0x05, 0x4f, 0x1f, 0x05, 0x22, 0x0a, 0x5f, 0xaf, + 0x0f, 0xe1, 0x65, 0x21, 0xd7, 0x26, 0xb8, 0xc1, 0xba, 0x9f, 0xd5, 0x2b, 0x22, 0x30, 0x0e, 0x46, 0x5a, 0xe6, 0xa2, + 0xd0, 0xc9, 0x9b, 0xec, 0x52, 0xf4, 0x1a, 0x0d, 0x66, 0x82, 0x3e, 0x11, 0x88, 0xf0, 0x06, 0x3e, 0x8a, 0xf0, 0xc7, + 0xc6, 0x71, 0x52, 0xcc, 0x46, 0xc3, 0x83, 0x30, 0xdd, 0xb5, 0x84, 0xf5, 0x5a, 0xd9, 0x68, 0x2b, 0x26, 0xc7, 0xc6, + 0x5d, 0x29, 0xfb, 0x29, 0xc3, 0xba, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0x37, 0xd5, 0x7e, 0x3e, 0xe0, 0xf6, 0x1a, + 0x8f, 0x9b, 0x18, 0x06, 0x06, 0x50, 0xab, 0xad, 0x0d, 0x6e, 0x6d, 0xee, 0x63, 0x6b, 0x20, 0xcc, 0xb6, 0x21, 0x28, + 0x4a, 0x9f, 0x7d, 0x7b, 0x73, 0xeb, 0x63, 0x18, 0x2a, 0x33, 0x27, 0x85, 0xf4, 0x00, 0xe4, 0xe8, 0x21, 0x81, 0xce, + 0xed, 0xcf, 0x8a, 0x2e, 0x54, 0x32, 0x71, 0x39, 0xc6, 0x1f, 0x82, 0xdb, 0xbc, 0x41, 0xf4, 0xf1, 0xa3, 0xd9, 0xe4, + 0x1f, 0x3f, 0x46, 0x38, 0x34, 0x74, 0x8f, 0x02, 0x5e, 0x30, 0x1a, 0x96, 0x61, 0xae, 0xcc, 0xc6, 0x6f, 0xb6, 0x03, + 0xb4, 0xa3, 0x15, 0xde, 0xc1, 0xf2, 0x98, 0xc6, 0x77, 0x1c, 0x43, 0x07, 0x1c, 0xe0, 0xcd, 0x06, 0x7c, 0xd8, 0x7b, + 0x15, 0x2b, 0x74, 0x74, 0xf4, 0x2a, 0x96, 0xa8, 0x7f, 0xcd, 0xcc, 0x9d, 0x1b, 0x78, 0x86, 0x0f, 0xb8, 0x19, 0xbe, + 0x0c, 0x10, 0xe0, 0x9a, 0x6d, 0x4b, 0x36, 0x6f, 0x4c, 0x1c, 0x8e, 0x14, 0xe2, 0x7c, 0x43, 0xb4, 0x61, 0x07, 0x12, + 0xe8, 0xf5, 0x55, 0x08, 0xed, 0x1e, 0x23, 0x0c, 0x58, 0xf8, 0xd2, 0x6f, 0x8f, 0x25, 0x73, 0x56, 0x4c, 0x59, 0xb1, + 0x5e, 0x3f, 0xa7, 0xd6, 0x17, 0x6f, 0x2b, 0x6c, 0xa4, 0xea, 0x35, 0x1a, 0xd4, 0x8c, 0x1f, 0xc4, 0x07, 0x3a, 0xc4, + 0x87, 0xaf, 0xe2, 0x02, 0x21, 0xb0, 0x30, 0xe2, 0x62, 0xe9, 0xfd, 0xce, 0xb2, 0xda, 0xba, 0x14, 0xa8, 0x6c, 0x24, + 0x27, 0x2d, 0x3c, 0x23, 0x59, 0xb9, 0x46, 0x97, 0xb3, 0x5e, 0xa3, 0x91, 0x23, 0x19, 0x67, 0x83, 0x7c, 0x88, 0x39, + 0x2e, 0xe0, 0x32, 0x75, 0x77, 0x1d, 0x16, 0xac, 0x46, 0xb9, 0xdc, 0x7c, 0x57, 0x76, 0xac, 0xe9, 0x3b, 0xba, 0x09, + 0x80, 0xf1, 0x8e, 0x06, 0x44, 0x62, 0x1f, 0x90, 0x85, 0x05, 0xb2, 0xf2, 0x40, 0x16, 0x06, 0xc8, 0x0a, 0xf5, 0x17, + 0x10, 0x40, 0x49, 0xa1, 0x74, 0x87, 0xa2, 0xd7, 0x43, 0x7d, 0x3a, 0x37, 0x12, 0xcc, 0x4d, 0xb4, 0x09, 0xb7, 0x1c, + 0xe0, 0x52, 0xe2, 0xe6, 0xae, 0xc8, 0x2a, 0x8a, 0x4c, 0xd4, 0x5b, 0x7c, 0x6b, 0xfe, 0x24, 0xb7, 0xf8, 0xce, 0xfe, + 0xb8, 0x0b, 0x94, 0x49, 0xbf, 0xd5, 0xb4, 0x0d, 0xdc, 0xc5, 0x88, 0x8b, 0x92, 0x08, 0xd0, 0xda, 0x05, 0x3c, 0x14, + 0xf5, 0x37, 0xe0, 0x94, 0x0d, 0x4d, 0x21, 0x1a, 0x44, 0x61, 0x11, 0x90, 0xce, 0x3f, 0xff, 0x8c, 0x50, 0x5f, 0x40, + 0x64, 0x21, 0x77, 0xb2, 0x35, 0xdb, 0xa8, 0x11, 0x25, 0x51, 0x1a, 0xfb, 0xc0, 0x15, 0xb0, 0x33, 0xa2, 0x28, 0x78, + 0xff, 0xa5, 0xb2, 0xf1, 0xa8, 0x0d, 0xc3, 0x0c, 0xaa, 0x0a, 0xc5, 0x71, 0xb5, 0xda, 0x0e, 0x7c, 0x64, 0xa0, 0x2a, + 0x4c, 0xd4, 0x19, 0x64, 0x1f, 0x45, 0x63, 0x84, 0x1d, 0x1d, 0xb1, 0x81, 0x18, 0x06, 0xaf, 0x9c, 0x55, 0xad, 0xeb, + 0x70, 0xe1, 0xe2, 0x0c, 0x22, 0xcf, 0xaf, 0xd7, 0xf6, 0x2f, 0xf9, 0x60, 0xa4, 0x19, 0x78, 0xae, 0x2e, 0xb8, 0x8d, + 0x17, 0xfb, 0x65, 0xb1, 0x44, 0xcb, 0x77, 0x60, 0xd9, 0xe7, 0xe2, 0x08, 0x72, 0x37, 0xd5, 0xb6, 0x87, 0xfa, 0xc2, + 0x68, 0x14, 0x82, 0x28, 0xbe, 0xd5, 0x91, 0x86, 0x17, 0x3a, 0xcc, 0xab, 0x45, 0xe3, 0xcd, 0x55, 0x19, 0x54, 0x15, + 0x8e, 0x94, 0x04, 0xac, 0xae, 0x0d, 0x9d, 0x84, 0x1f, 0x75, 0x2a, 0xe9, 0x58, 0x48, 0x80, 0x02, 0x47, 0xe6, 0x72, + 0xde, 0x04, 0xcd, 0x67, 0x68, 0x0f, 0x91, 0xab, 0x56, 0xf9, 0xef, 0xba, 0x6c, 0xe9, 0xa2, 0x5b, 0x45, 0x73, 0xb9, + 0x54, 0x6c, 0xb9, 0x80, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0x41, 0xe4, 0xad, 0x9e, 0x33, + 0xb1, 0x8c, 0xdc, 0x3c, 0x5f, 0x5a, 0x71, 0xff, 0xf5, 0x0b, 0xfc, 0x9e, 0x74, 0x8e, 0x5f, 0xe2, 0xdf, 0x29, 0x79, + 0xdf, 0x78, 0x89, 0xa7, 0x9c, 0x58, 0xde, 0x20, 0x79, 0xfd, 0xea, 0xfa, 0xc5, 0xdb, 0x17, 0xef, 0x9f, 0x7e, 0x7c, + 0xf1, 0xf2, 0xd9, 0x8b, 0x97, 0x2f, 0xde, 0x7e, 0xc0, 0x3f, 0x51, 0xf2, 0xf2, 0xa4, 0x7d, 0xd1, 0xc2, 0xef, 0xc8, + 0xcb, 0x93, 0x0e, 0xbe, 0xd5, 0xe4, 0xe5, 0xc9, 0x19, 0x9e, 0x29, 0xf2, 0xf2, 0xb8, 0x73, 0x72, 0x8a, 0x97, 0xda, + 0x36, 0x99, 0xcb, 0x69, 0xbb, 0x85, 0xff, 0x76, 0x5f, 0x20, 0xde, 0x57, 0xb3, 0x98, 0xb2, 0x2d, 0xe3, 0x07, 0x53, + 0x86, 0x8e, 0x94, 0x31, 0x44, 0xb9, 0x0c, 0xd0, 0x69, 0xac, 0xea, 0xa6, 0x0d, 0x10, 0xd6, 0x19, 0x6c, 0x18, 0x01, + 0xad, 0x38, 0x71, 0xed, 0xf0, 0x93, 0x36, 0x3b, 0x05, 0xfa, 0xc4, 0x4b, 0xe1, 0xb8, 0x54, 0xe1, 0xb4, 0x9d, 0x16, + 0x63, 0x92, 0x4b, 0x59, 0xc4, 0x4b, 0x60, 0x04, 0x8c, 0xd6, 0x82, 0x9f, 0x94, 0xf1, 0xa3, 0xc4, 0x25, 0x69, 0xf7, + 0xdb, 0xa9, 0xb8, 0x24, 0x9d, 0x7e, 0x07, 0xfe, 0x74, 0xfb, 0xdd, 0xb4, 0xdd, 0x42, 0xc7, 0xc1, 0x38, 0x7e, 0xa8, + 0xa1, 0xf5, 0x60, 0x88, 0x5d, 0x17, 0xea, 0xef, 0x42, 0x7b, 0x95, 0x9e, 0x70, 0xea, 0xd8, 0x76, 0x4f, 0x5c, 0x32, + 0xa3, 0x87, 0xe5, 0xdf, 0x01, 0x6a, 0x1b, 0x17, 0x97, 0x72, 0xe3, 0xb8, 0x5f, 0xfc, 0x44, 0xa0, 0x5a, 0x90, 0x9a, + 0x98, 0xad, 0x5b, 0x08, 0x98, 0x46, 0x93, 0x0d, 0xe6, 0x40, 0x89, 0x92, 0x85, 0xf6, 0x81, 0xf6, 0x55, 0x53, 0xa2, + 0x64, 0x21, 0x17, 0x71, 0x4d, 0xd5, 0xf0, 0x4b, 0x60, 0xe6, 0x78, 0xc8, 0xd5, 0x4b, 0xfa, 0x32, 0xae, 0xf1, 0x3c, + 0x21, 0x6b, 0x17, 0x6e, 0x8b, 0x5f, 0x9d, 0x15, 0x45, 0x0d, 0x5c, 0x25, 0x60, 0xfd, 0xa8, 0x9a, 0xfa, 0x12, 0x5e, + 0x14, 0x64, 0x0d, 0x7d, 0x45, 0x02, 0xea, 0xf9, 0x6b, 0x69, 0xc6, 0x55, 0x2a, 0xa3, 0xbd, 0x22, 0xda, 0x98, 0x05, + 0x79, 0x45, 0xf4, 0xa5, 0x32, 0x40, 0x90, 0x84, 0x0f, 0xc4, 0x10, 0x0e, 0x7c, 0x3b, 0x40, 0x69, 0xe8, 0x1c, 0xa8, + 0x95, 0x2a, 0x33, 0x21, 0xf3, 0x69, 0xc2, 0x25, 0x80, 0xe6, 0xa9, 0x52, 0x41, 0x99, 0x4f, 0x2c, 0x51, 0x30, 0xf4, + 0x3f, 0xc2, 0x0d, 0x70, 0x1c, 0x1b, 0x54, 0x0c, 0xed, 0x6a, 0x44, 0x3d, 0xbf, 0x7d, 0xd1, 0x3a, 0x79, 0x19, 0xe4, + 0x2f, 0x95, 0xb7, 0xf7, 0xf8, 0x14, 0x50, 0x72, 0x1b, 0xe0, 0xab, 0x8d, 0x7d, 0x6c, 0xb6, 0x5e, 0x08, 0x90, 0x63, + 0x8d, 0x4e, 0xcc, 0xe3, 0x8a, 0x3d, 0xa4, 0x8f, 0x49, 0xbb, 0x05, 0x01, 0xd5, 0xf6, 0x50, 0xbe, 0x3f, 0xb6, 0x60, + 0xaa, 0x93, 0xdb, 0x26, 0xd0, 0x6a, 0x78, 0x6f, 0xe9, 0xae, 0xc9, 0x93, 0x3b, 0xac, 0x02, 0x9c, 0x61, 0xc7, 0xac, + 0x21, 0x8e, 0x05, 0x72, 0x81, 0x68, 0xed, 0x06, 0xd0, 0x54, 0x74, 0xec, 0xbb, 0x7f, 0xde, 0x38, 0xea, 0xb2, 0x99, + 0x74, 0x8f, 0x5f, 0x1e, 0x1d, 0xc5, 0xb2, 0x41, 0xde, 0x23, 0xbc, 0xa2, 0x60, 0xb3, 0x0d, 0x7e, 0x70, 0xdc, 0x32, + 0xf1, 0xa9, 0x0a, 0xa8, 0xe3, 0x44, 0xd5, 0x8e, 0xb5, 0xaa, 0xb3, 0x72, 0x37, 0xf8, 0x31, 0x75, 0x50, 0x23, 0x48, + 0xb3, 0xa3, 0xeb, 0x84, 0x50, 0xfe, 0xb1, 0xe6, 0xb4, 0x06, 0xdb, 0xb2, 0xf1, 0x3b, 0x45, 0xdf, 0xbd, 0x6f, 0xbe, + 0x0c, 0xf0, 0xa0, 0x66, 0x9a, 0xf4, 0xbe, 0xf1, 0x1e, 0x7d, 0xf7, 0x3e, 0x70, 0x3b, 0xe4, 0x15, 0x7b, 0xe2, 0xb9, + 0x91, 0x5f, 0x2d, 0x57, 0xfa, 0x2b, 0x48, 0xf6, 0x05, 0xf9, 0x15, 0xb0, 0x9c, 0x92, 0x5f, 0x63, 0xd9, 0x84, 0x70, + 0x8c, 0xe4, 0xd7, 0xb8, 0x80, 0x1f, 0x39, 0xf9, 0x35, 0x06, 0x6c, 0xc7, 0x33, 0xf3, 0xa3, 0x28, 0x81, 0x01, 0xae, + 0x6e, 0xd2, 0x7a, 0xbc, 0x15, 0xeb, 0xb5, 0x38, 0x3a, 0x92, 0xf6, 0x17, 0xbd, 0xca, 0x8e, 0x8e, 0xf2, 0xcb, 0x59, + 0xd5, 0x37, 0xd7, 0xfb, 0xe8, 0x8b, 0x41, 0x28, 0x1c, 0x98, 0xa6, 0xf1, 0x70, 0xc6, 0x3a, 0x0b, 0x11, 0x07, 0x1a, + 0x68, 0x9e, 0x76, 0xee, 0x9f, 0x5f, 0x60, 0xf8, 0xf7, 0x7e, 0x50, 0x10, 0x74, 0xf8, 0x76, 0x62, 0xa4, 0xcd, 0x9a, + 0xe7, 0x55, 0x9d, 0xab, 0x00, 0x9f, 0x31, 0x43, 0x4d, 0x71, 0x74, 0xc4, 0x2f, 0x03, 0x5c, 0xc6, 0x0c, 0x35, 0x02, + 0x8b, 0xbd, 0xa7, 0xa5, 0x3d, 0x99, 0xe1, 0x9a, 0xe0, 0xa1, 0x5d, 0x3e, 0x28, 0x86, 0x97, 0xda, 0x51, 0x93, 0x30, + 0x1c, 0xb7, 0x22, 0x2d, 0xb7, 0xc9, 0x7a, 0xa2, 0xa9, 0xae, 0xda, 0x3d, 0x24, 0x89, 0x6a, 0x88, 0xab, 0xab, 0x36, + 0x06, 0x95, 0x7c, 0x5f, 0x11, 0x99, 0x0a, 0xe2, 0x5d, 0x06, 0x57, 0xb9, 0x4c, 0x15, 0x9e, 0xf1, 0x54, 0x78, 0x39, + 0xfb, 0x9e, 0xb7, 0x9e, 0x36, 0x4e, 0x9c, 0xa6, 0x67, 0x86, 0x45, 0x5f, 0x95, 0xce, 0x87, 0xb0, 0x49, 0xd5, 0x10, + 0xde, 0x31, 0x2c, 0x31, 0x8f, 0x59, 0x8f, 0x3b, 0x06, 0x71, 0xa2, 0x55, 0xa3, 0x0d, 0x99, 0xf0, 0xb9, 0x49, 0x15, + 0x0c, 0xd4, 0x14, 0xbe, 0x04, 0x23, 0xab, 0xac, 0x32, 0xcc, 0xf6, 0x0d, 0x43, 0x01, 0x01, 0x05, 0xae, 0x08, 0x0b, + 0x24, 0x78, 0x91, 0xd5, 0x08, 0x47, 0x9d, 0x5c, 0xd8, 0xc9, 0x5d, 0x2a, 0xe8, 0x4e, 0x0c, 0x2f, 0x75, 0x0f, 0x89, + 0x46, 0xc3, 0x71, 0xdb, 0x57, 0xc2, 0x0c, 0xa2, 0xd9, 0x1e, 0x5e, 0xb1, 0x1e, 0x52, 0xcd, 0x66, 0x69, 0x00, 0x79, + 0xd5, 0x5a, 0xaf, 0xd5, 0xa5, 0x6f, 0xa4, 0xef, 0xcf, 0x71, 0xc3, 0x77, 0x79, 0xc1, 0xf3, 0x0f, 0x49, 0x06, 0x11, + 0x50, 0x55, 0xe0, 0xb3, 0xe5, 0x22, 0xc2, 0x91, 0x79, 0xe2, 0x0e, 0xfe, 0x9a, 0xa7, 0xc9, 0x22, 0x1c, 0xb9, 0x57, + 0xef, 0xa2, 0x61, 0x35, 0x58, 0x95, 0x95, 0x01, 0xdb, 0x79, 0xf2, 0x11, 0x18, 0x07, 0xfd, 0x49, 0xa1, 0x55, 0xf5, + 0x3b, 0xc9, 0x5d, 0xe8, 0x12, 0xe5, 0x1f, 0x62, 0x73, 0xa3, 0xda, 0xec, 0x77, 0x16, 0xe5, 0x38, 0xf2, 0x55, 0xe1, + 0x41, 0x83, 0x6f, 0xbc, 0x04, 0xd9, 0x76, 0x0f, 0x90, 0xaf, 0xca, 0x1e, 0x80, 0xf3, 0xde, 0x6c, 0x10, 0xfe, 0x43, + 0xee, 0x7d, 0x8d, 0x38, 0xfa, 0x28, 0xc5, 0x13, 0xaa, 0x69, 0xd4, 0x78, 0x6d, 0x0c, 0xdf, 0xac, 0x9c, 0xd5, 0xfb, + 0xda, 0x38, 0xd8, 0xbf, 0xd5, 0x3d, 0x04, 0x93, 0xa8, 0x3d, 0x9c, 0x64, 0x65, 0x5f, 0x13, 0x42, 0x44, 0x06, 0xa6, + 0x6f, 0x7b, 0xe0, 0xe1, 0xc7, 0x48, 0xc1, 0xc5, 0xd9, 0xf2, 0x49, 0x14, 0xa2, 0xb4, 0xd6, 0x1c, 0xab, 0x21, 0xc5, + 0xf6, 0x61, 0x9c, 0x70, 0x37, 0x28, 0xe4, 0xba, 0x17, 0xaa, 0x4e, 0x4c, 0xab, 0x6e, 0x8c, 0xd4, 0xc1, 0xb6, 0x59, + 0x70, 0x56, 0xf5, 0x6e, 0x24, 0x94, 0xea, 0x8d, 0x39, 0xf3, 0x4e, 0x68, 0xb3, 0x6d, 0x1e, 0x5e, 0xb6, 0x2f, 0xd1, + 0x29, 0x30, 0xe4, 0x3d, 0x2c, 0x03, 0x68, 0x5d, 0xc1, 0xb1, 0x1b, 0x07, 0x90, 0x95, 0xe4, 0x6a, 0xe5, 0x5e, 0x89, + 0xe3, 0x03, 0x39, 0xdc, 0x94, 0x6f, 0xc6, 0x05, 0x78, 0x10, 0x38, 0x05, 0x64, 0x21, 0x67, 0xe0, 0x1f, 0x5c, 0xac, + 0xe9, 0x87, 0xf8, 0x3f, 0x70, 0xc0, 0x57, 0x48, 0x9a, 0x5a, 0xf5, 0x13, 0xbc, 0xe5, 0x04, 0x0a, 0x6f, 0x5b, 0xf7, + 0x47, 0x19, 0x3a, 0xcd, 0xd6, 0x75, 0x2a, 0xd6, 0x2f, 0xb5, 0xae, 0x58, 0x29, 0x0b, 0x07, 0x54, 0x2b, 0x46, 0x9b, + 0xd4, 0xf9, 0xb0, 0xba, 0x07, 0xa0, 0x1e, 0x0a, 0xf0, 0x8d, 0xe1, 0x52, 0x3c, 0x2b, 0x20, 0xa2, 0x57, 0xa8, 0x4f, + 0xd3, 0x45, 0xf8, 0xc2, 0xf1, 0x00, 0xee, 0x09, 0x4b, 0x9e, 0xb3, 0x7c, 0x95, 0x1b, 0x16, 0x48, 0x01, 0x85, 0x52, + 0x58, 0xac, 0xd7, 0xb1, 0x30, 0x71, 0x1e, 0x5c, 0x98, 0x5f, 0xf7, 0x9e, 0x87, 0xd1, 0xdf, 0x41, 0x5d, 0xec, 0xd5, + 0x23, 0xc6, 0x84, 0x15, 0x85, 0x97, 0x4e, 0x45, 0x16, 0xf4, 0xb5, 0xaf, 0x0f, 0x51, 0x4d, 0xb9, 0x1f, 0x1b, 0x7d, + 0xef, 0x5b, 0x3e, 0x67, 0x72, 0x09, 0x0f, 0x29, 0x61, 0x46, 0x14, 0xd3, 0xfe, 0x1b, 0x28, 0x08, 0xbc, 0xc6, 0xc3, + 0x43, 0x7c, 0x04, 0xbe, 0xca, 0xd3, 0x3a, 0x9a, 0xf9, 0xe7, 0x39, 0x22, 0x13, 0x3e, 0x33, 0xea, 0x47, 0xe0, 0x45, + 0x04, 0x22, 0x14, 0x21, 0x11, 0x13, 0xe3, 0xa8, 0x1f, 0x19, 0x97, 0xac, 0x08, 0xac, 0xc6, 0x40, 0xc9, 0x1d, 0xe1, + 0xa9, 0xaa, 0x88, 0x58, 0x58, 0x53, 0x07, 0x95, 0x58, 0x6a, 0xcc, 0xb4, 0x4f, 0x3a, 0x15, 0x08, 0xb3, 0x6c, 0x5b, + 0x50, 0xd6, 0x5b, 0xea, 0x02, 0x2c, 0x89, 0x31, 0xbd, 0xe5, 0xc9, 0x47, 0xe0, 0xe6, 0xd8, 0xd8, 0x15, 0x5d, 0xf1, + 0x6b, 0x50, 0x4f, 0xa7, 0x05, 0xfe, 0x68, 0x18, 0xb6, 0x71, 0x4a, 0x37, 0x84, 0xe3, 0x8c, 0x14, 0x09, 0xbd, 0x85, + 0x38, 0x17, 0x73, 0x2e, 0xd2, 0x1c, 0xcf, 0xe9, 0x6d, 0x3a, 0xc3, 0x73, 0x2e, 0x9e, 0xd8, 0x65, 0x4f, 0xc7, 0x90, + 0xe4, 0x3f, 0x96, 0x1b, 0x62, 0x9e, 0xe9, 0x7a, 0xa7, 0x58, 0xf1, 0x08, 0x78, 0x15, 0x15, 0xa3, 0xde, 0xd8, 0xd8, + 0x94, 0x73, 0x5d, 0x19, 0xaf, 0xdf, 0xd3, 0x31, 0xc5, 0x19, 0xce, 0x51, 0x92, 0x4b, 0xcc, 0xfa, 0x22, 0xbd, 0x07, + 0x31, 0xae, 0x33, 0x6c, 0x9f, 0xf8, 0xe2, 0xb7, 0x2c, 0x7f, 0x26, 0x8b, 0xf7, 0x66, 0xcb, 0xe7, 0x08, 0x0a, 0x81, + 0x8b, 0x8a, 0x68, 0xc2, 0xed, 0xde, 0xb2, 0x2f, 0xab, 0xa6, 0xe8, 0xad, 0x6d, 0xca, 0x0d, 0x71, 0x06, 0xc1, 0x81, + 0x93, 0x19, 0x6f, 0xb4, 0x31, 0xeb, 0xb7, 0xbe, 0xd1, 0xe8, 0x0c, 0x95, 0x25, 0x11, 0x86, 0xb5, 0x6a, 0xaa, 0x54, + 0x12, 0xd1, 0x54, 0x4e, 0xc2, 0x5b, 0x19, 0x60, 0xa7, 0x0a, 0x67, 0x72, 0x29, 0x74, 0x2a, 0x03, 0xbc, 0xc9, 0xab, + 0xcd, 0xb5, 0xba, 0xb5, 0x10, 0xd3, 0xf8, 0xce, 0xfe, 0x60, 0xf8, 0xa3, 0x51, 0xf1, 0xbf, 0x01, 0xc3, 0x1e, 0x95, + 0x0a, 0x80, 0x1f, 0x18, 0xce, 0x02, 0xe4, 0x2c, 0x3f, 0x79, 0x0b, 0xe0, 0xb3, 0x2c, 0xe4, 0x1d, 0xa4, 0x32, 0x93, + 0x7a, 0x07, 0xa9, 0x0c, 0x52, 0x8d, 0x77, 0xfb, 0xa1, 0xa8, 0x94, 0x45, 0x61, 0x83, 0x44, 0xe1, 0x52, 0x1d, 0x2c, + 0x89, 0x48, 0xa0, 0x5d, 0x23, 0xca, 0xcd, 0xb9, 0x80, 0x30, 0x87, 0xd0, 0xb8, 0xfd, 0xa6, 0xb7, 0xf0, 0x7d, 0x67, + 0xf3, 0x99, 0xcf, 0xbf, 0xb3, 0xf9, 0xa6, 0x23, 0x8f, 0xf1, 0xf5, 0xdb, 0x4e, 0x63, 0x19, 0x2f, 0x1d, 0xd6, 0xbe, + 0x2b, 0x1f, 0x95, 0x69, 0x99, 0xc7, 0xbb, 0x49, 0x1b, 0xcf, 0x03, 0xa4, 0x6c, 0x56, 0x3c, 0x5c, 0x07, 0xb7, 0x5b, + 0xc7, 0x31, 0x6f, 0x92, 0x36, 0x42, 0xc7, 0x4e, 0xb8, 0x12, 0xb1, 0x91, 0x9c, 0x8e, 0xdf, 0x9f, 0xc0, 0xdd, 0xcb, + 0x48, 0x6d, 0xf9, 0x4a, 0xd9, 0x6a, 0xcd, 0x76, 0xeb, 0x98, 0xef, 0xad, 0xd2, 0x68, 0xe3, 0x39, 0x23, 0x2b, 0xf0, + 0x40, 0xa3, 0x85, 0x55, 0x35, 0x80, 0xcb, 0xea, 0x0b, 0xf1, 0xeb, 0x92, 0x8e, 0xcd, 0xf7, 0xb1, 0x4d, 0x79, 0xb5, + 0xd4, 0x3e, 0xa9, 0xc9, 0x61, 0x10, 0x1d, 0xe4, 0x4a, 0x06, 0x39, 0x31, 0x3f, 0x21, 0x49, 0x17, 0x5d, 0xb6, 0xfb, + 0x49, 0xf7, 0x98, 0x1f, 0xf3, 0x14, 0x78, 0xd8, 0xb8, 0xe9, 0x2b, 0x34, 0xdb, 0xbe, 0xce, 0xe3, 0xe5, 0x88, 0x67, + 0xae, 0xf9, 0xaa, 0x83, 0x32, 0xd5, 0xce, 0x11, 0xb2, 0x00, 0xc5, 0x7c, 0x2f, 0x41, 0x76, 0xbd, 0x9b, 0x63, 0x9e, + 0x42, 0x3f, 0x50, 0xab, 0x63, 0x6b, 0x95, 0x83, 0xfb, 0x75, 0x09, 0x08, 0xe6, 0x3b, 0xaa, 0xcd, 0xc5, 0xa6, 0x37, + 0xe3, 0xaa, 0xb3, 0x63, 0x5e, 0x8d, 0x30, 0x2c, 0xb3, 0xdb, 0x9f, 0x9f, 0x5a, 0xd5, 0xe5, 0x71, 0x00, 0x91, 0x5f, + 0x97, 0x5c, 0x84, 0x9d, 0x86, 0xdd, 0xba, 0x9c, 0xb0, 0xd3, 0xfa, 0x2c, 0x83, 0x22, 0xbb, 0xbd, 0xee, 0xcc, 0xb4, + 0x3e, 0xdb, 0x6b, 0x70, 0x24, 0x84, 0x49, 0x99, 0x95, 0xce, 0xa4, 0x8a, 0xf9, 0xf1, 0x3b, 0xe4, 0x5a, 0x7f, 0xb5, + 0xd4, 0x3e, 0xbf, 0x44, 0x04, 0xc8, 0xae, 0xba, 0x2e, 0xab, 0x43, 0x1f, 0x65, 0x13, 0x2f, 0x8f, 0x79, 0xb0, 0x72, + 0x4f, 0x6f, 0x17, 0x32, 0xf5, 0xf8, 0xda, 0x6f, 0xa5, 0x3b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, + 0xbb, 0xb9, 0x83, 0x92, 0xe1, 0xc4, 0x7d, 0xe9, 0x77, 0xcc, 0x5e, 0x37, 0xf0, 0xcb, 0xa4, 0x0b, 0x53, 0xdf, 0xee, + 0xe1, 0xb8, 0x03, 0x7d, 0x18, 0x38, 0x6c, 0x37, 0xe8, 0x33, 0x2b, 0x88, 0x3c, 0xe6, 0x85, 0xc5, 0xb3, 0x2b, 0xd2, + 0xee, 0xf3, 0xd4, 0x6d, 0x26, 0x23, 0x1a, 0xb5, 0x9b, 0x3c, 0x98, 0x19, 0xe0, 0x97, 0x2b, 0x1b, 0x16, 0xf1, 0xeb, + 0x14, 0x40, 0xc9, 0x17, 0xab, 0xd6, 0xa7, 0x82, 0x57, 0xbd, 0xe1, 0x74, 0x3b, 0xdd, 0xaf, 0x1b, 0xdc, 0xee, 0x7a, + 0x78, 0xc2, 0xa3, 0x30, 0x16, 0xad, 0xfd, 0xc4, 0xe7, 0xc0, 0x01, 0x25, 0xad, 0xfb, 0x5d, 0x70, 0xa1, 0x2c, 0x61, + 0xb9, 0x5b, 0x6e, 0xb4, 0x53, 0xce, 0xc2, 0xd1, 0x96, 0x0c, 0xb8, 0x83, 0x6d, 0x88, 0x42, 0x07, 0xc7, 0x1d, 0x9c, + 0xb4, 0xdb, 0x9d, 0x2e, 0x4e, 0xce, 0xba, 0x30, 0xd0, 0x46, 0xd2, 0x3d, 0x1e, 0x29, 0x0b, 0xc0, 0x20, 0x67, 0xe3, + 0xda, 0x7d, 0x04, 0x01, 0xa4, 0x42, 0xf1, 0x9a, 0x1f, 0xc7, 0x71, 0x3b, 0xb9, 0xdf, 0x6a, 0x77, 0x2f, 0x1a, 0x00, + 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2d, 0x75, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, 0xad, 0xd1, 0xde, + 0x54, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, 0x18, 0xa4, 0xf3, + 0xa4, 0xdb, 0xe9, 0x22, 0x3b, 0x16, 0xed, 0xf0, 0xa3, 0xdc, 0x27, 0x3b, 0x45, 0x1a, 0x1a, 0x90, 0xa4, 0x9c, 0x9d, + 0x5c, 0x82, 0x44, 0xcd, 0xc9, 0x55, 0xbb, 0x39, 0x67, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0x2c, 0x57, 0xc1, 0x25, + 0x05, 0x80, 0xb8, 0x04, 0xe3, 0xa2, 0xfb, 0xdd, 0xfe, 0xfd, 0xa4, 0x7b, 0xde, 0xb1, 0x44, 0x8f, 0x5f, 0x76, 0x6a, + 0x69, 0x66, 0xea, 0x49, 0xd7, 0xa4, 0x41, 0xd7, 0xc9, 0xfd, 0x2e, 0x94, 0x71, 0x29, 0x61, 0x29, 0x08, 0x7c, 0x51, + 0x15, 0x83, 0x68, 0x17, 0x69, 0x2d, 0xf7, 0xbc, 0x96, 0x7d, 0x71, 0x76, 0x7a, 0xbf, 0x1b, 0x42, 0xad, 0x9c, 0x85, + 0x59, 0x68, 0x37, 0x11, 0x3f, 0x3b, 0x58, 0x5a, 0x74, 0x9c, 0x74, 0xd3, 0x9d, 0x09, 0xda, 0x4d, 0x73, 0x6c, 0x70, + 0x20, 0x50, 0x38, 0xbe, 0x10, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, 0xd9, 0xdf, 0x53, 0x06, + 0x6f, 0x5b, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x6b, 0x0a, 0xd1, 0x3c, 0xc4, 0x30, 0x72, 0xb1, 0xc6, + 0xeb, 0xb9, 0x3f, 0x80, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0xf0, 0x31, 0x74, 0xa8, 0x35, + 0xc3, 0xea, 0xf3, 0xd4, 0x99, 0x14, 0x84, 0xba, 0xad, 0x77, 0xfc, 0x5b, 0xe5, 0x92, 0xf2, 0x2a, 0x3b, 0xe9, 0xa2, + 0xc4, 0x5d, 0x96, 0x27, 0x6d, 0x94, 0x04, 0x26, 0x24, 0xee, 0x48, 0x9e, 0x65, 0x64, 0x10, 0xdd, 0x46, 0x38, 0xba, + 0x8b, 0x70, 0x64, 0x7d, 0x98, 0x7f, 0x03, 0x3f, 0xee, 0x08, 0x47, 0xd6, 0x95, 0x39, 0xc2, 0x91, 0x66, 0x02, 0x82, + 0x7c, 0x45, 0x43, 0x3c, 0x86, 0xd2, 0xc6, 0xb3, 0xba, 0x2c, 0xfd, 0xd8, 0x7f, 0x95, 0xae, 0xd7, 0x36, 0x25, 0x90, + 0x32, 0x97, 0x66, 0x87, 0xda, 0x47, 0xaa, 0x23, 0xea, 0x99, 0xf5, 0x08, 0x83, 0x00, 0x42, 0xef, 0xfc, 0x23, 0x77, + 0x55, 0x7c, 0x10, 0x76, 0x0a, 0x2b, 0x0d, 0xae, 0xe8, 0x51, 0x78, 0x86, 0x45, 0x78, 0x22, 0x7c, 0x61, 0x10, 0x2b, + 0xfc, 0xef, 0x5c, 0xca, 0x85, 0xff, 0xad, 0x65, 0xf9, 0x0b, 0x9e, 0x46, 0x71, 0x16, 0x2d, 0x60, 0xb9, 0x65, 0xc3, + 0x11, 0x8d, 0x58, 0x7d, 0x04, 0x1f, 0x27, 0x2e, 0x64, 0x1c, 0x48, 0x84, 0x1f, 0x8d, 0x40, 0xe5, 0xe5, 0xc3, 0x8f, + 0x36, 0x7c, 0x91, 0xf9, 0x84, 0xf8, 0x65, 0x10, 0xa2, 0x58, 0xc2, 0x85, 0xc6, 0xb4, 0x60, 0x4a, 0x45, 0x36, 0xae, + 0x5f, 0x24, 0x85, 0x7f, 0xa8, 0xd1, 0xa7, 0x4c, 0x44, 0x64, 0x3a, 0xac, 0xcf, 0xd6, 0x8a, 0xc3, 0xb9, 0x2c, 0x54, + 0x6a, 0x5f, 0x6d, 0xf1, 0x60, 0x5c, 0x94, 0x4f, 0x22, 0xa6, 0xe3, 0x6c, 0x83, 0xed, 0x1d, 0x76, 0x59, 0xc8, 0x5d, + 0x69, 0x87, 0xa5, 0x66, 0xd9, 0xe6, 0x6b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x05, 0xee, 0x80, + 0xc2, 0x36, 0x40, 0x4c, 0xba, 0x2a, 0x4b, 0xa6, 0xab, 0x72, 0x19, 0xce, 0x5a, 0xad, 0xcd, 0x06, 0x17, 0xcc, 0x04, + 0x55, 0xd9, 0x5b, 0x02, 0xf2, 0xd5, 0x4c, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, 0x8c, 0x60, + 0xa3, 0x0d, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x8d, 0xa4, 0xcc, 0x19, 0x85, 0x78, 0x66, 0x41, 0x93, 0x1b, + 0x3c, 0xe3, 0x63, 0xb6, 0xbf, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, 0x3a, 0xb0, + 0x88, 0x6b, 0xe8, 0x20, 0x94, 0xc1, 0x27, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x35, 0xc0, 0x65, 0xa9, 0xe5, 0x6b, + 0x17, 0x0e, 0xe1, 0xb0, 0x85, 0x7d, 0x64, 0x84, 0x15, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x11, 0xa3, 0x85, 0x5d, 0xa0, + 0x82, 0x16, 0x36, 0xe1, 0x29, 0x5a, 0x9b, 0x32, 0xce, 0xd8, 0x5d, 0xf9, 0xbc, 0x65, 0xb5, 0x09, 0x16, 0x4e, 0x3a, + 0xd4, 0x44, 0x07, 0xb7, 0x87, 0x8c, 0xf0, 0xc6, 0x8f, 0xd7, 0xaf, 0x5e, 0xba, 0x28, 0xd2, 0x7c, 0x02, 0x2e, 0x9b, + 0x4e, 0x35, 0x76, 0x67, 0xc3, 0xbd, 0x57, 0x8a, 0x52, 0x2b, 0x9c, 0x9a, 0xc0, 0x9b, 0x42, 0xe7, 0x89, 0xbd, 0xbc, + 0x78, 0x26, 0x8b, 0x39, 0xb5, 0x37, 0x46, 0xf8, 0x4e, 0xb9, 0x87, 0xe0, 0xcd, 0x5b, 0x33, 0xd5, 0x24, 0xdf, 0x6e, + 0x5f, 0x45, 0x2c, 0x32, 0x23, 0xbf, 0x82, 0x36, 0xc0, 0x54, 0xf6, 0x03, 0x67, 0x05, 0x71, 0xb1, 0xf8, 0x03, 0xf2, + 0xf2, 0xc6, 0x52, 0x97, 0x28, 0x6a, 0x70, 0x83, 0x9f, 0xac, 0xe0, 0x59, 0x70, 0x5d, 0x68, 0xd8, 0x23, 0x27, 0x5e, + 0x44, 0xad, 0xa8, 0xfe, 0x0e, 0xae, 0x51, 0x25, 0xf8, 0x38, 0xae, 0x49, 0x2e, 0x41, 0xf4, 0x28, 0x9f, 0xdc, 0xe3, + 0x20, 0x9a, 0xf8, 0xbb, 0xe7, 0xab, 0xb6, 0xa7, 0xb3, 0x79, 0xa5, 0x4e, 0x2c, 0xaf, 0x4c, 0xc0, 0xc3, 0xd1, 0x3e, + 0x6a, 0x83, 0x70, 0x90, 0xc8, 0x4a, 0xed, 0xa1, 0xcf, 0x45, 0xbd, 0x38, 0xbf, 0x6c, 0xb3, 0xe6, 0xd9, 0x7a, 0x9d, + 0x5f, 0xb5, 0x59, 0xbb, 0x6b, 0x9f, 0xc0, 0x8b, 0x54, 0x06, 0x34, 0x97, 0x4f, 0x78, 0x16, 0x81, 0x76, 0x76, 0x9a, + 0x99, 0x70, 0x0a, 0x1b, 0xaf, 0xf8, 0x59, 0xea, 0xaa, 0x2f, 0x09, 0xc6, 0xa5, 0xc4, 0xea, 0xf1, 0x0b, 0xd4, 0x6f, + 0xa7, 0xbb, 0xae, 0xd2, 0xcd, 0xf6, 0x71, 0x70, 0xe1, 0x52, 0x20, 0xdc, 0x81, 0x90, 0x07, 0xa0, 0xdf, 0x5d, 0x09, + 0x30, 0x0d, 0x02, 0x54, 0x56, 0x20, 0xd2, 0xf2, 0xf9, 0x72, 0xfe, 0xac, 0xa0, 0x66, 0x19, 0x9e, 0xf0, 0x29, 0xd7, + 0x2a, 0xa5, 0x20, 0xdd, 0xee, 0x4b, 0xdf, 0xec, 0x97, 0xa0, 0xb2, 0x5a, 0x2c, 0xdc, 0x44, 0xf3, 0xec, 0xb3, 0x72, + 0x0b, 0x87, 0xb0, 0x59, 0x59, 0x81, 0x33, 0xb4, 0xc1, 0xb9, 0x9c, 0xd2, 0x82, 0xeb, 0xd9, 0xfc, 0xdf, 0x5a, 0x1d, + 0x36, 0xd0, 0x43, 0x73, 0x61, 0x05, 0x20, 0xa1, 0x62, 0xbc, 0x5e, 0xf3, 0x93, 0x6f, 0xdf, 0x27, 0x79, 0x9f, 0xf0, + 0x36, 0xee, 0xe0, 0x53, 0xdc, 0xc5, 0xed, 0x16, 0x6e, 0x77, 0xe1, 0xea, 0x3e, 0xcb, 0x97, 0x63, 0xa6, 0x62, 0x78, + 0x0b, 0x4d, 0x5f, 0x25, 0x17, 0xc7, 0xd5, 0x0b, 0x00, 0x45, 0xe2, 0xd0, 0x25, 0x08, 0x44, 0xef, 0x22, 0xf8, 0x45, + 0x51, 0x18, 0x3e, 0x6e, 0x1a, 0xaa, 0x4e, 0x4a, 0xfd, 0xc2, 0xd5, 0x69, 0x1f, 0xec, 0xb9, 0xed, 0xca, 0x36, 0xc1, + 0xec, 0xdb, 0xfe, 0x4c, 0xab, 0x9f, 0x4d, 0x5d, 0x22, 0x86, 0x87, 0x5e, 0x85, 0x1e, 0xe8, 0x8a, 0xb4, 0x8f, 0x8e, + 0xc0, 0xea, 0x28, 0x98, 0x0d, 0xb7, 0xd1, 0x0f, 0x78, 0xb3, 0x96, 0x06, 0xc1, 0x0a, 0xc0, 0xb8, 0xf3, 0x15, 0x27, + 0x2b, 0x0b, 0x5b, 0x0d, 0x54, 0x98, 0x15, 0x61, 0x8c, 0xbb, 0x90, 0x54, 0x18, 0x21, 0x1a, 0x8e, 0x30, 0x17, 0x0c, + 0xe5, 0xb0, 0x85, 0xe5, 0x64, 0xa2, 0x98, 0x86, 0xa3, 0xa3, 0x60, 0x5f, 0x58, 0xa1, 0xcc, 0x29, 0x32, 0x62, 0x53, + 0x2e, 0x1e, 0xea, 0x3f, 0x58, 0x21, 0xcd, 0xa7, 0xd1, 0x60, 0xa4, 0x91, 0x59, 0xc5, 0x08, 0x67, 0x39, 0x5f, 0x40, + 0xd5, 0x69, 0x01, 0x4e, 0x3f, 0xf0, 0x97, 0x8f, 0xd3, 0xb0, 0x4d, 0x20, 0x5f, 0xbf, 0xd9, 0x98, 0x2e, 0x78, 0x5c, + 0xd0, 0x9b, 0x57, 0xe2, 0x31, 0xec, 0xa8, 0x87, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0x6f, 0xa1, 0x29, 0xf8, 0x80, 0x36, + 0x7f, 0x36, 0x80, 0x4b, 0x2f, 0xcc, 0x87, 0xad, 0xe8, 0xe3, 0x28, 0x26, 0x65, 0x5b, 0x26, 0xd3, 0x9c, 0xd2, 0x55, + 0xa6, 0xa1, 0xb0, 0xd5, 0x14, 0x36, 0xd8, 0x45, 0x3d, 0x09, 0x07, 0x33, 0xa6, 0x6a, 0x96, 0x0e, 0x86, 0xe6, 0xef, + 0x2b, 0x5b, 0xb2, 0x85, 0x5d, 0xc4, 0x99, 0x0d, 0x36, 0x8f, 0x98, 0x06, 0xe5, 0xdb, 0x18, 0xee, 0x61, 0xe1, 0x25, + 0xcd, 0x1a, 0xf9, 0x3c, 0xf3, 0x64, 0xf3, 0x6c, 0xb3, 0x31, 0x03, 0x51, 0x29, 0xe8, 0x81, 0xde, 0xf8, 0x6d, 0xd3, + 0x82, 0xed, 0x51, 0x7e, 0x75, 0x5b, 0x78, 0xce, 0xe1, 0x61, 0x50, 0xdf, 0xde, 0xb5, 0x2e, 0xe4, 0x67, 0x07, 0x92, + 0x56, 0x90, 0x62, 0xa7, 0x13, 0x74, 0x76, 0x8a, 0x83, 0x91, 0x03, 0x3d, 0xbf, 0xfe, 0x6c, 0x61, 0xed, 0x7f, 0xbf, + 0x2e, 0x0b, 0x9a, 0x78, 0x3a, 0xe5, 0x84, 0x32, 0x7f, 0x7e, 0xbe, 0xe2, 0x49, 0x85, 0x0a, 0xee, 0x45, 0x2d, 0xd8, + 0xd3, 0x36, 0xe8, 0xe6, 0x9c, 0x7e, 0xb2, 0x3f, 0x6c, 0x0c, 0x9f, 0x52, 0xcb, 0x96, 0x15, 0x52, 0xa9, 0x87, 0x36, + 0xcd, 0x1e, 0x3d, 0x70, 0x44, 0xfe, 0x0c, 0x5d, 0x00, 0xaf, 0x3f, 0x2e, 0xe4, 0xc2, 0x20, 0x82, 0xfb, 0xed, 0xc6, + 0x6d, 0x7c, 0x05, 0xc0, 0xdb, 0xe1, 0xa0, 0xfa, 0xa7, 0x05, 0xec, 0x6f, 0x54, 0x96, 0xf4, 0xe3, 0xed, 0xd8, 0xe3, + 0xbf, 0x90, 0x10, 0xc1, 0xdd, 0xe2, 0x61, 0xe2, 0xd0, 0xa9, 0x64, 0xcd, 0xca, 0x9f, 0x3b, 0x25, 0x01, 0xc3, 0xea, + 0x05, 0x43, 0x36, 0x6e, 0xa7, 0xb8, 0xcd, 0xfc, 0x0f, 0x2a, 0x18, 0x2c, 0xf8, 0xda, 0x48, 0x2a, 0x96, 0xc5, 0x6f, + 0x9f, 0x3a, 0xff, 0x55, 0xe7, 0xb8, 0x0e, 0x75, 0xed, 0xd5, 0xce, 0x91, 0x89, 0x98, 0x1c, 0xa1, 0xa3, 0xa3, 0xad, + 0x0c, 0x3a, 0x01, 0xc0, 0x23, 0xc7, 0x7e, 0xf9, 0xe5, 0xf3, 0xec, 0x98, 0xd1, 0x3c, 0x16, 0x51, 0xc8, 0xdc, 0x79, + 0x6e, 0xce, 0x4e, 0xe4, 0x09, 0x55, 0x33, 0x5f, 0x18, 0xe0, 0xf8, 0x68, 0x27, 0x15, 0xf0, 0x3d, 0xda, 0xec, 0x99, + 0xc0, 0x16, 0xbf, 0x65, 0x27, 0xb5, 0xaf, 0xa0, 0x5f, 0xa0, 0xd5, 0x3e, 0xa6, 0x72, 0x6b, 0x81, 0xa3, 0xed, 0x89, + 0xec, 0x1d, 0xfa, 0x56, 0x9d, 0x92, 0xf5, 0x78, 0xb1, 0xdf, 0xe8, 0xab, 0x10, 0xfb, 0x92, 0x2b, 0xda, 0x36, 0x62, + 0xd5, 0xcb, 0xbd, 0xba, 0x32, 0x75, 0xaa, 0xae, 0x79, 0x2b, 0x4b, 0x9b, 0xd2, 0x2e, 0xc9, 0xde, 0x6d, 0xb1, 0xf0, + 0x2a, 0xbc, 0xd1, 0x28, 0x2f, 0x42, 0xc1, 0x1e, 0x4b, 0x0c, 0x7b, 0x9c, 0xc0, 0xf5, 0xc2, 0x7a, 0x1d, 0xc3, 0x9f, + 0x7d, 0x63, 0xd8, 0x67, 0xba, 0xf4, 0x1b, 0xdf, 0xe2, 0x57, 0x82, 0xe0, 0xc1, 0xce, 0x0e, 0x12, 0xac, 0xbb, 0xdc, + 0xa0, 0xe1, 0x38, 0xf1, 0x5f, 0xf0, 0x74, 0xb5, 0xf6, 0x2e, 0x07, 0xa3, 0xec, 0x2b, 0xcf, 0xdd, 0x95, 0xac, 0x65, + 0x2d, 0xf2, 0xfc, 0x96, 0x04, 0x43, 0xec, 0xa6, 0x74, 0x8e, 0x5b, 0x49, 0x1b, 0x45, 0xae, 0x58, 0x85, 0xfe, 0x5f, + 0x2b, 0x92, 0xd9, 0xcc, 0xff, 0x3a, 0x3f, 0x3f, 0x77, 0x29, 0xce, 0xe6, 0x4f, 0x19, 0x0f, 0x38, 0x93, 0xc0, 0xbe, + 0xf0, 0x8c, 0x19, 0x1d, 0xf2, 0x1b, 0x18, 0x0a, 0x11, 0xe4, 0x4a, 0x38, 0x76, 0x09, 0x5e, 0x5e, 0x04, 0xca, 0x03, + 0xec, 0xdf, 0x93, 0xad, 0x72, 0xfe, 0xe9, 0x26, 0x1f, 0xda, 0xb8, 0x6c, 0x90, 0x7d, 0x31, 0x9f, 0x03, 0x6b, 0x26, + 0x03, 0xaf, 0x15, 0x44, 0xd8, 0xfe, 0x36, 0x2c, 0xad, 0xb3, 0x94, 0xc1, 0x91, 0x96, 0xcb, 0x6c, 0x66, 0x35, 0xff, + 0xee, 0xc3, 0x94, 0x75, 0xcf, 0xfe, 0x40, 0xe4, 0x2e, 0xb2, 0x72, 0x11, 0x3a, 0xa3, 0xef, 0xcb, 0x60, 0x9c, 0x07, + 0x2f, 0xd9, 0x92, 0x7d, 0x8f, 0x0f, 0xaa, 0x14, 0xf8, 0x78, 0x58, 0x70, 0x9a, 0x7f, 0x8f, 0x0f, 0xaa, 0xa0, 0x9c, + 0xe0, 0x0a, 0x69, 0xe2, 0x5a, 0x62, 0xf3, 0xc4, 0x75, 0x1a, 0x09, 0xa0, 0xa0, 0x79, 0x64, 0x0e, 0xb2, 0xe7, 0x2e, + 0x5e, 0x62, 0xd2, 0xc1, 0x2e, 0x38, 0x98, 0x8d, 0xce, 0x6a, 0x83, 0x9a, 0x43, 0xdc, 0xba, 0x72, 0x36, 0xe6, 0xeb, + 0xd1, 0xd6, 0x82, 0x18, 0x65, 0x32, 0xb9, 0x7a, 0xc7, 0xe3, 0x9d, 0xc5, 0x42, 0x61, 0xb5, 0x60, 0x81, 0x6a, 0x55, + 0xaa, 0xf4, 0xb0, 0xf8, 0x6e, 0xc1, 0x2c, 0x28, 0x62, 0xb6, 0xde, 0xc3, 0x5b, 0xae, 0x08, 0x48, 0xc9, 0x2e, 0x09, + 0x5e, 0x29, 0x37, 0x98, 0xea, 0x1f, 0xa5, 0x07, 0x42, 0xcf, 0x94, 0x8e, 0xb0, 0xc9, 0x53, 0x10, 0x49, 0xec, 0xb0, + 0x85, 0x1d, 0x6b, 0xf4, 0x42, 0x78, 0x21, 0x05, 0xce, 0x55, 0xd3, 0xc4, 0x9c, 0x72, 0x13, 0x5d, 0xec, 0xa1, 0x5a, + 0xb0, 0x4c, 0x5b, 0x04, 0x38, 0x74, 0x68, 0x28, 0xc5, 0x73, 0x03, 0x0a, 0xf3, 0xbc, 0xb6, 0x4b, 0x79, 0x0c, 0x8b, + 0x17, 0xa4, 0x00, 0x51, 0xe3, 0x62, 0x5a, 0xd6, 0x59, 0xe4, 0xcb, 0x29, 0x17, 0x15, 0x32, 0x14, 0x4c, 0x2d, 0xa4, + 0x80, 0xd7, 0x2d, 0xca, 0x22, 0x86, 0x0e, 0xd5, 0xf0, 0xdd, 0x92, 0xb0, 0xb2, 0x8e, 0x39, 0xa6, 0xb8, 0xa8, 0x6a, + 0x00, 0x73, 0xf1, 0xd0, 0x08, 0x88, 0x3e, 0xd4, 0xeb, 0x2b, 0xf1, 0x56, 0x2e, 0xaa, 0x7c, 0x4f, 0xe3, 0x7c, 0x10, + 0x79, 0x67, 0x37, 0x8c, 0x36, 0xe6, 0x01, 0xaa, 0x60, 0xfb, 0xfe, 0xc6, 0xab, 0x47, 0xd9, 0x36, 0xe6, 0x09, 0xab, + 0x32, 0x6b, 0xc4, 0xca, 0xf7, 0x1a, 0xaa, 0xf6, 0xea, 0x55, 0x0b, 0x61, 0x2b, 0x02, 0x54, 0x0a, 0x3e, 0xde, 0xc9, + 0x7f, 0xa1, 0x6d, 0xbe, 0x3d, 0x87, 0xca, 0xf0, 0x40, 0x9e, 0x0c, 0x55, 0x3d, 0xe0, 0xa2, 0xfc, 0x10, 0xc0, 0xe2, + 0x47, 0x26, 0x96, 0xef, 0xbe, 0x0b, 0x64, 0xce, 0x54, 0x2c, 0xf1, 0x6a, 0x40, 0x87, 0xa9, 0x95, 0x87, 0x52, 0x09, + 0xb6, 0x3d, 0x37, 0x05, 0xd7, 0x3e, 0x68, 0x30, 0x1e, 0xb0, 0x61, 0xba, 0xaa, 0x07, 0x16, 0xb6, 0xa1, 0x8d, 0xbd, + 0x39, 0xa7, 0x89, 0xc4, 0x4b, 0x87, 0x38, 0x27, 0x60, 0x7b, 0x5c, 0x32, 0xf7, 0x71, 0x86, 0xfa, 0x75, 0x0e, 0x7f, + 0xb5, 0xc1, 0x39, 0xce, 0x50, 0xfa, 0x30, 0x86, 0x0b, 0xac, 0x0d, 0x06, 0xf0, 0x65, 0x96, 0x54, 0x81, 0x47, 0x6a, + 0x66, 0x24, 0x56, 0x77, 0x11, 0x88, 0x56, 0x3a, 0xbc, 0x1d, 0x67, 0x3e, 0x34, 0xb7, 0xe1, 0x5e, 0x9f, 0x19, 0xe1, + 0x70, 0x94, 0xc5, 0xb5, 0x73, 0x86, 0x93, 0xab, 0x43, 0x5e, 0x3b, 0x31, 0xc1, 0xda, 0x3b, 0x3c, 0x55, 0x40, 0x8f, + 0x06, 0xa7, 0x8a, 0xa5, 0x21, 0x10, 0x33, 0x01, 0xbc, 0x99, 0xc3, 0xa3, 0x2d, 0xc0, 0xf9, 0x68, 0x83, 0x83, 0xaf, + 0xb4, 0xd6, 0xd5, 0xb6, 0x12, 0x65, 0xb3, 0xc1, 0x83, 0x65, 0x86, 0x27, 0x19, 0x9e, 0x67, 0xc3, 0xe0, 0xb8, 0xf9, + 0x98, 0x85, 0x26, 0x5d, 0xeb, 0xf5, 0x0b, 0x67, 0x46, 0x88, 0xec, 0x4f, 0x4b, 0x7f, 0x50, 0x1f, 0x10, 0x3e, 0x85, + 0x2c, 0xa0, 0x25, 0x7d, 0xf7, 0xb7, 0x61, 0x5f, 0xee, 0x46, 0x8d, 0x98, 0x27, 0x96, 0x8c, 0xf4, 0xfd, 0x8f, 0x32, + 0xcb, 0xb6, 0xd6, 0x88, 0x16, 0xb7, 0x07, 0x51, 0xc3, 0xb7, 0x57, 0x9d, 0x2f, 0xa3, 0xd2, 0x6c, 0x07, 0x10, 0xc5, + 0x1a, 0x27, 0xe9, 0x60, 0x8d, 0xe4, 0x7a, 0x1d, 0xdb, 0x14, 0xc2, 0x93, 0x39, 0xa3, 0x6a, 0x59, 0x98, 0xc7, 0xec, + 0x62, 0x85, 0x12, 0xc3, 0xef, 0x62, 0x67, 0x23, 0x0a, 0x6f, 0xc7, 0x49, 0x30, 0xdc, 0x88, 0x05, 0x91, 0x35, 0x91, + 0xfb, 0x2e, 0xab, 0x2c, 0x83, 0x04, 0x11, 0x46, 0xe4, 0xb7, 0xd7, 0xa5, 0xc2, 0x3e, 0x97, 0x67, 0xff, 0x18, 0x5f, + 0x40, 0xb8, 0x79, 0x9b, 0xd2, 0x62, 0x44, 0xa7, 0xc0, 0xc6, 0x42, 0x1c, 0xc2, 0x9d, 0x84, 0xf5, 0x7a, 0x30, 0xec, + 0x09, 0x43, 0x9e, 0xdd, 0x63, 0x7e, 0x65, 0x43, 0xfb, 0x1b, 0x80, 0xab, 0x6e, 0x4b, 0xcd, 0xb5, 0xd1, 0xfd, 0x50, + 0xf3, 0xde, 0x18, 0x77, 0x49, 0xee, 0xc9, 0x90, 0xea, 0x55, 0xf0, 0x9a, 0x05, 0xb8, 0x09, 0x5d, 0x85, 0xc7, 0x78, + 0x69, 0x6d, 0x38, 0xcd, 0xe3, 0x52, 0xd4, 0xbc, 0x29, 0x05, 0x4f, 0x59, 0x13, 0x36, 0xc8, 0x86, 0x78, 0xec, 0x43, + 0x8f, 0x1f, 0xbe, 0x89, 0xc7, 0x08, 0x15, 0xc4, 0xc0, 0xd4, 0xba, 0x6c, 0x8f, 0x2b, 0xbb, 0x7d, 0x93, 0x69, 0x18, + 0x06, 0x63, 0xc4, 0x3c, 0x0e, 0x8d, 0x98, 0xf3, 0x46, 0x03, 0x2d, 0xc9, 0x18, 0x8c, 0x98, 0x97, 0x41, 0x6b, 0x4b, + 0xfb, 0xf0, 0x68, 0xd0, 0xde, 0x12, 0xa1, 0x1e, 0x07, 0x9a, 0xa6, 0xe1, 0x89, 0x91, 0xea, 0x89, 0x77, 0xff, 0xe0, + 0xd5, 0x49, 0x07, 0x14, 0x09, 0x93, 0x2b, 0x3f, 0x09, 0xeb, 0x1a, 0x6e, 0xc7, 0x3d, 0x31, 0xe3, 0x76, 0xb6, 0x0d, + 0x6a, 0x20, 0x07, 0xd9, 0x70, 0xd8, 0x93, 0xde, 0x4a, 0xa2, 0x85, 0x27, 0xd5, 0xa3, 0x24, 0xd5, 0xe2, 0x7d, 0xd1, + 0xdb, 0x57, 0xde, 0xdc, 0xbf, 0x75, 0xba, 0x7d, 0x1e, 0x03, 0x07, 0x74, 0x08, 0xf7, 0x43, 0x55, 0x7c, 0xb0, 0x93, + 0x0e, 0x44, 0x41, 0x4b, 0x5b, 0x35, 0x81, 0xd4, 0x9a, 0xd9, 0xc5, 0xba, 0xa9, 0xd0, 0xb1, 0x80, 0x30, 0x64, 0xaa, + 0xea, 0xee, 0x56, 0x05, 0xaa, 0x21, 0x0e, 0xa7, 0xfe, 0x63, 0x6b, 0xc4, 0x1a, 0x47, 0x9d, 0x71, 0x64, 0x8c, 0x24, + 0xed, 0xf2, 0xc1, 0x3b, 0x44, 0x60, 0x25, 0xe0, 0xe3, 0x41, 0x9b, 0x24, 0x63, 0x48, 0xf0, 0x86, 0x65, 0xda, 0xf0, + 0x21, 0xdc, 0x21, 0x28, 0x4f, 0x6c, 0x50, 0x5a, 0x57, 0xc9, 0x42, 0x2e, 0xe8, 0x32, 0x40, 0xcf, 0x2f, 0xe5, 0x6f, + 0x6c, 0x38, 0xb2, 0x00, 0x0e, 0xd9, 0xce, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x21, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0xd8, + 0xd9, 0xd7, 0xb0, 0x41, 0xf1, 0x02, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, + 0x49, 0xbc, 0x58, 0xaf, 0x5b, 0xe8, 0xf8, 0x27, 0xf3, 0x3c, 0xf4, 0xa4, 0x54, 0xb8, 0x4f, 0x2a, 0x85, 0x3b, 0x58, + 0x02, 0x92, 0x49, 0xa0, 0x6b, 0xc7, 0x32, 0x54, 0xa3, 0x43, 0xe4, 0xf2, 0x17, 0x10, 0xc7, 0xda, 0x1d, 0x4b, 0xa0, + 0x67, 0xdf, 0x29, 0x60, 0x75, 0xed, 0x65, 0x09, 0x64, 0x04, 0x77, 0xbf, 0x09, 0x8c, 0x0a, 0xd1, 0xf8, 0xfc, 0x99, + 0x17, 0x26, 0x78, 0xe2, 0xfc, 0xb9, 0xe6, 0x86, 0x75, 0x2f, 0xe8, 0x8d, 0x69, 0x3e, 0x9e, 0xe0, 0xe6, 0xc4, 0x82, + 0xf3, 0xa4, 0x03, 0x3f, 0x2d, 0x44, 0x4f, 0x3a, 0xd8, 0xa5, 0xe2, 0x49, 0x09, 0xe4, 0x10, 0x3d, 0x9d, 0x81, 0x14, + 0xb0, 0xd2, 0xb1, 0xd5, 0x22, 0x4d, 0xd1, 0x7a, 0x3d, 0xbd, 0x24, 0x2d, 0x84, 0x56, 0xea, 0x86, 0xeb, 0x6c, 0x06, + 0x3e, 0xd2, 0xa0, 0x18, 0x78, 0x4d, 0xf5, 0x2c, 0x46, 0x78, 0x82, 0x56, 0x63, 0x36, 0xa1, 0xcb, 0x5c, 0xa7, 0xaa, + 0xcf, 0x13, 0x1b, 0xb8, 0x97, 0xd9, 0x48, 0x70, 0x27, 0x1d, 0x3c, 0x35, 0xfc, 0xe5, 0x7b, 0x63, 0x0e, 0x52, 0x64, + 0x26, 0x79, 0x6a, 0x12, 0x30, 0x4f, 0xb2, 0x5c, 0x2a, 0x66, 0x9b, 0xe9, 0x59, 0xdb, 0x72, 0x08, 0x0f, 0x1e, 0xe9, + 0x82, 0x1b, 0x2b, 0xca, 0x28, 0x9d, 0x11, 0xd5, 0x57, 0x27, 0x9d, 0x74, 0x8a, 0x79, 0x02, 0x9c, 0xde, 0x5b, 0x19, + 0xb3, 0x46, 0x79, 0x2b, 0x3a, 0x47, 0xc7, 0x33, 0x2c, 0xaa, 0x4b, 0xd4, 0x39, 0x3a, 0x9e, 0x22, 0x3c, 0x6f, 0x90, + 0x99, 0x02, 0x8f, 0x61, 0x2e, 0xfe, 0x8f, 0x94, 0xff, 0xea, 0xb0, 0x21, 0xc4, 0xf4, 0x1b, 0xd8, 0x29, 0x6c, 0x1c, + 0xa5, 0x39, 0x01, 0xaf, 0xc5, 0xf6, 0x39, 0xce, 0xc8, 0xb4, 0x99, 0xfb, 0x80, 0x7b, 0xa6, 0x95, 0xc6, 0xad, 0x46, + 0xc7, 0x19, 0x1e, 0x6f, 0x27, 0xc5, 0x66, 0xae, 0xcd, 0x3c, 0xcd, 0xe0, 0x7c, 0xaf, 0x46, 0xe1, 0xca, 0x2f, 0xb7, + 0x93, 0xc2, 0xf2, 0x0e, 0xb8, 0xcd, 0x31, 0x16, 0x4d, 0x8a, 0x73, 0x3c, 0x6f, 0xbe, 0xc4, 0xf3, 0xe6, 0xbb, 0x32, + 0xa3, 0xb1, 0xc4, 0x02, 0x82, 0xf7, 0x41, 0x22, 0x9e, 0x57, 0xc9, 0x63, 0x2c, 0x1a, 0xa6, 0x3c, 0x9e, 0x37, 0xaa, + 0xd2, 0xcd, 0x25, 0x16, 0x0d, 0x53, 0xba, 0xf1, 0x0e, 0xcf, 0x1b, 0x2f, 0xff, 0xc5, 0xa4, 0xa3, 0x14, 0xd0, 0x65, + 0x81, 0x56, 0x99, 0x1d, 0xe2, 0xf5, 0xaf, 0x6f, 0xde, 0xb6, 0x3f, 0x76, 0x8e, 0xa7, 0xd8, 0xaf, 0x5f, 0x66, 0x70, + 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9e, 0xe1, 0xce, 0x71, 0xe6, 0x9a, 0xda, 0xcc, 0x1b, 0xe4, + 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa2, 0x1a, 0x28, 0xd1, 0xf1, 0xb4, 0x06, 0x2a, + 0xf8, 0x5e, 0xd6, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, + 0x61, 0x8a, 0x05, 0xca, 0x37, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, + 0x87, 0x5e, 0x6e, 0x99, 0x9d, 0xe9, 0xb9, 0xc9, 0x84, 0xc3, 0x07, 0x1e, 0xeb, 0xff, 0xda, 0x81, 0x62, 0x03, 0x52, + 0xfc, 0x7f, 0xe9, 0xe8, 0x42, 0x30, 0x42, 0x56, 0x94, 0x16, 0x0e, 0xf1, 0xbf, 0x3d, 0xac, 0xa0, 0xfb, 0x62, 0xa7, + 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, 0x3a, 0xdd, 0xda, 0x01, 0x8d, 0xa8, + 0xd1, 0xb3, 0x69, 0xd8, 0xe0, 0x61, 0x3b, 0xdd, 0x83, 0xcc, 0x1b, 0x6e, 0x5f, 0x2b, 0x85, 0xc3, 0x37, 0xb8, 0x53, + 0xbd, 0x6a, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0xa4, 0xdb, 0xa6, 0xdc, 0xc6, 0x58, 0x3a, 0xe9, + 0x62, 0xe3, 0x8a, 0x08, 0x95, 0x6e, 0xaf, 0x40, 0x29, 0x3e, 0xd1, 0x4d, 0x66, 0xbe, 0x2e, 0x75, 0x62, 0x2e, 0xa1, + 0x1a, 0xe6, 0xf3, 0xee, 0x4a, 0x27, 0x5a, 0x2e, 0x6c, 0xde, 0xdd, 0x25, 0xf4, 0x09, 0x1a, 0xd6, 0x46, 0x60, 0xb7, + 0xcf, 0x9d, 0x1d, 0x64, 0x70, 0x08, 0x86, 0x07, 0x90, 0x23, 0x2d, 0xb6, 0x0f, 0x6c, 0x5a, 0xc3, 0xae, 0x8b, 0x66, + 0x99, 0x68, 0x5b, 0x6d, 0x9a, 0x5c, 0xbb, 0x87, 0xf9, 0x22, 0xe4, 0x29, 0x44, 0x61, 0xf5, 0xe3, 0x7b, 0xd8, 0x8d, + 0x9b, 0x1a, 0x23, 0x51, 0x57, 0x32, 0x95, 0xd0, 0x4f, 0x6e, 0x31, 0x4b, 0xee, 0x8c, 0x17, 0xa3, 0x32, 0xfe, 0x3e, + 0x26, 0x2e, 0x7f, 0x54, 0x49, 0x72, 0x60, 0xd9, 0xdf, 0x60, 0xc9, 0x2d, 0x98, 0x27, 0x96, 0xd5, 0x24, 0xd6, 0xc9, + 0x5d, 0xb0, 0x88, 0xd2, 0x34, 0xb2, 0x31, 0x0c, 0xa8, 0x69, 0xc6, 0xaa, 0x07, 0x0f, 0x21, 0xd0, 0x43, 0xbf, 0x2c, + 0xa5, 0x5d, 0x67, 0x69, 0xad, 0x7b, 0x6d, 0xba, 0xdf, 0x1e, 0x50, 0x35, 0x8d, 0xcf, 0x01, 0xd7, 0xf4, 0xaf, 0x26, + 0x91, 0x8c, 0xd8, 0x3f, 0x9c, 0x15, 0x8f, 0x97, 0x85, 0xc1, 0x34, 0xd1, 0xd7, 0x49, 0xb6, 0x68, 0x83, 0xa9, 0x5e, + 0xb6, 0xe8, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x33, 0x93, 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, + 0xd9, 0xef, 0x3b, 0xbc, 0x3b, 0x98, 0x6b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, + 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x11, 0x57, 0xbc, 0x1a, 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, + 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0x2f, 0x8d, 0x01, 0x97, 0x47, 0x74, 0xa9, 0x27, 0x49, 0x80, + 0x57, 0x35, 0x2a, 0x6f, 0x53, 0xa4, 0xfc, 0x22, 0x41, 0x8e, 0x2f, 0xf6, 0x88, 0x2a, 0x06, 0xb0, 0x2a, 0x4b, 0xfa, + 0x04, 0x52, 0xcf, 0x0f, 0x26, 0xfa, 0xcb, 0x36, 0xf2, 0xd8, 0x37, 0x77, 0x3f, 0x33, 0x3d, 0x2b, 0xe4, 0x72, 0x3a, + 0x03, 0x1f, 0x5a, 0x60, 0x19, 0x0a, 0x53, 0xaf, 0xb2, 0xf5, 0xaf, 0x49, 0x6e, 0x02, 0x28, 0x9c, 0x6e, 0xca, 0x84, + 0x66, 0x7a, 0x49, 0x73, 0x63, 0x49, 0xca, 0xc5, 0xf4, 0x91, 0xbc, 0xfd, 0x19, 0xb0, 0x9b, 0x12, 0xdd, 0xd8, 0x93, + 0xf7, 0x06, 0x76, 0x00, 0xce, 0x08, 0xdb, 0x57, 0xf1, 0xa1, 0x02, 0x9d, 0x3f, 0xce, 0x09, 0xdb, 0x57, 0xf5, 0x09, + 0xb3, 0xd9, 0x33, 0xb2, 0x35, 0xdc, 0x7e, 0x9c, 0x35, 0x72, 0x74, 0xd2, 0x49, 0xf3, 0x9e, 0x27, 0x06, 0x16, 0xa0, + 0x01, 0x70, 0x77, 0xb6, 0x67, 0x79, 0x77, 0x43, 0x40, 0xef, 0x92, 0x49, 0x7b, 0x5d, 0x6e, 0x52, 0xd6, 0xeb, 0x4e, + 0x45, 0x05, 0x0b, 0x3c, 0x0b, 0xf6, 0x02, 0xb5, 0x5f, 0x7b, 0x28, 0xce, 0xe3, 0x6c, 0xdb, 0xf4, 0xbc, 0xec, 0xbb, + 0xb7, 0x67, 0x91, 0xb1, 0x4d, 0x7b, 0xb3, 0x87, 0x48, 0x58, 0x4e, 0x58, 0x07, 0x9c, 0x70, 0x55, 0x3b, 0x20, 0x40, + 0x1f, 0x03, 0x91, 0x1b, 0x4b, 0xb2, 0xda, 0x54, 0x46, 0xf7, 0x81, 0xdf, 0x2d, 0x25, 0xd2, 0x8d, 0xb6, 0x24, 0x98, + 0x3e, 0xc1, 0xa8, 0xe9, 0xcc, 0x33, 0xd1, 0xb5, 0x17, 0x90, 0xb7, 0x45, 0x5b, 0xff, 0x1e, 0x33, 0x36, 0xdb, 0xc3, + 0xc4, 0x50, 0x06, 0x31, 0xd0, 0xfb, 0x88, 0xf7, 0x1a, 0x8d, 0x0c, 0x81, 0x42, 0x26, 0x1b, 0x62, 0x99, 0x78, 0x2d, + 0xfa, 0xd1, 0x91, 0x81, 0x47, 0x95, 0x80, 0x30, 0x05, 0x21, 0x24, 0xec, 0xda, 0x20, 0x6c, 0xb8, 0x5c, 0xb5, 0x5c, + 0xd8, 0x48, 0xb5, 0xa1, 0x83, 0xff, 0x57, 0xb8, 0x6c, 0xf5, 0xcc, 0x72, 0x51, 0x0c, 0x6e, 0xe6, 0x06, 0x2c, 0x12, + 0xa4, 0x47, 0x9b, 0xed, 0xa1, 0xb8, 0x3f, 0x17, 0x9b, 0x0d, 0x01, 0x89, 0x39, 0x4c, 0x50, 0x34, 0x9c, 0x1b, 0x63, + 0xac, 0x92, 0x4a, 0xcb, 0x5a, 0x93, 0x98, 0x83, 0x80, 0xd1, 0xe1, 0xba, 0xaf, 0x6e, 0x53, 0x86, 0xef, 0x52, 0x81, + 0x6f, 0xc0, 0x93, 0x26, 0x95, 0xd8, 0x3d, 0x5e, 0x50, 0x6c, 0x88, 0xee, 0x79, 0xf6, 0xb6, 0x80, 0x75, 0x36, 0x7b, + 0x44, 0x04, 0xbf, 0xab, 0x5f, 0x6d, 0xf0, 0xdd, 0xc2, 0x2f, 0xc1, 0xfa, 0x39, 0x38, 0x49, 0xb1, 0x68, 0xc8, 0x66, + 0xe1, 0x8e, 0x0c, 0x28, 0x57, 0xf1, 0xcb, 0x61, 0xea, 0x4e, 0x31, 0x5c, 0xfb, 0x78, 0x89, 0xdf, 0x6d, 0xb5, 0xdb, + 0x50, 0x65, 0x71, 0xbb, 0x37, 0x45, 0x43, 0x56, 0x4d, 0xef, 0xc9, 0xdc, 0x4a, 0xa9, 0x7f, 0xbd, 0xc3, 0xad, 0x9d, + 0xf6, 0xfd, 0x34, 0xdf, 0x78, 0x74, 0xae, 0x9a, 0xf6, 0xa9, 0xb5, 0x22, 0x38, 0xf8, 0xd9, 0xc2, 0xcd, 0x9d, 0x01, + 0x07, 0xf0, 0xf3, 0x77, 0x34, 0xaf, 0x32, 0x88, 0x4e, 0x6f, 0x35, 0xe3, 0xeb, 0xf8, 0xcf, 0x71, 0x23, 0xee, 0xa7, + 0x7f, 0x26, 0x7f, 0x8e, 0x1b, 0xa8, 0x8f, 0xe2, 0xc5, 0xed, 0x9a, 0xcd, 0xd7, 0x10, 0x6c, 0xed, 0xde, 0x09, 0x7e, + 0x1d, 0x96, 0xe4, 0x9a, 0xe6, 0x3c, 0x5b, 0xbb, 0xc7, 0xf9, 0xd6, 0x5c, 0xcc, 0x58, 0xc1, 0xf5, 0xda, 0xbc, 0x37, + 0xb5, 0x8e, 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, + 0x3d, 0xaa, 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, + 0xf5, 0x3d, 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, + 0x96, 0x34, 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, + 0xf2, 0x5d, 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, + 0x06, 0x5f, 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, + 0x87, 0xae, 0xf2, 0xf0, 0x36, 0x31, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, + 0x61, 0x3e, 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, + 0x64, 0x85, 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, + 0x0c, 0xcb, 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, + 0xba, 0x8d, 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, + 0xf5, 0xd8, 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, + 0x64, 0x62, 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, + 0xee, 0xdc, 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, + 0x2d, 0x76, 0xae, 0xde, 0xbd, 0xf0, 0xa5, 0xbc, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, + 0xce, 0xf4, 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xcf, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, + 0x0c, 0x94, 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, + 0x20, 0x07, 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, + 0xdf, 0x83, 0xbb, 0xb3, 0x7b, 0xa9, 0xb1, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, + 0x39, 0xbc, 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, + 0x5a, 0xcc, 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, + 0x4b, 0xe9, 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, + 0xcb, 0x95, 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, + 0xa5, 0xe6, 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x85, 0xc1, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0xf3, 0x49, 0x09, 0xb5, + 0x3b, 0xe8, 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, + 0xb0, 0xea, 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, + 0x81, 0xd1, 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, + 0x71, 0xac, 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, + 0x36, 0x32, 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, + 0xdb, 0x3c, 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, + 0x92, 0x41, 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, + 0x8b, 0x9a, 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, + 0x06, 0xf6, 0x19, 0xc9, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, + 0x2a, 0xe9, 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, + 0x08, 0xfc, 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, + 0x1e, 0x50, 0x0c, 0x6f, 0xa0, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, + 0x8b, 0x0b, 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, + 0xbf, 0x93, 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, + 0xa2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x20, 0x3b, 0x65, 0x3a, 0x88, + 0x0a, 0xf2, 0xa4, 0x7c, 0x22, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, + 0xc8, 0x34, 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, + 0x10, 0x8a, 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, + 0xeb, 0x85, 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, + 0xea, 0x83, 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, + 0x7f, 0xd2, 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, + 0xa9, 0xc6, 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, + 0x64, 0x55, 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, + 0x84, 0x72, 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, + 0xd8, 0xc2, 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, + 0x6f, 0x32, 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x54, 0xaf, 0xea, 0x7b, + 0x84, 0x98, 0x99, 0xf8, 0x4f, 0xf0, 0x44, 0xf3, 0xb7, 0x9f, 0x86, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, + 0xec, 0x3f, 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, + 0xd6, 0xa1, 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, + 0x2d, 0x94, 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, + 0x76, 0xb4, 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, + 0x61, 0xdb, 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, + 0xbd, 0x28, 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, + 0x70, 0x19, 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, + 0x00, 0x05, 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0xcf, 0xe3, 0xd6, 0x5e, 0xb3, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, + 0xdb, 0x45, 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, + 0x95, 0x9b, 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, + 0x35, 0x90, 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, + 0x10, 0xf2, 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, + 0xc1, 0xe4, 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, + 0x6c, 0x2a, 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, + 0x4a, 0x55, 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, + 0xb2, 0xe5, 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0xf2, 0x6b, 0xc2, 0xed, 0x30, 0xcd, + 0x32, 0x6d, 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, + 0xdf, 0x06, 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, + 0x62, 0x37, 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, + 0x9e, 0x33, 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, + 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, + 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, + 0x2f, 0x43, 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, + 0x33, 0xd4, 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, + 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, + 0xd5, 0x9e, 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, + 0xab, 0x8d, 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, + 0xc8, 0xc1, 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, + 0xc2, 0x14, 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, + 0x80, 0x80, 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, + 0xd8, 0xe5, 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, + 0xc8, 0x81, 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, + 0x96, 0xeb, 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, + 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, + 0xac, 0x3e, 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, + 0x6a, 0x8b, 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, + 0x1e, 0x36, 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, + 0xe4, 0xaa, 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, + 0x70, 0x23, 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, + 0xfc, 0x4e, 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, + 0x7a, 0x5f, 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, + 0x03, 0x44, 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, + 0xc8, 0x6e, 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, + 0x4c, 0xd9, 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, + 0x2e, 0x40, 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, + 0xb8, 0x30, 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, + 0x5e, 0x66, 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, + 0xad, 0xcd, 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, + 0x47, 0xf7, 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, + 0x1e, 0x6c, 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, + 0x45, 0x19, 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, + 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, + 0x6a, 0xd5, 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, + 0xe5, 0xce, 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, + 0x9c, 0xe3, 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, + 0xe4, 0xb6, 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, + 0xa6, 0x82, 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, + 0xef, 0x3d, 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, + 0x5a, 0xbd, 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, + 0x75, 0x0e, 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, + 0x84, 0x56, 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, + 0xce, 0x86, 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, + 0x8b, 0x5e, 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, + 0xcd, 0xb8, 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, + 0x29, 0x84, 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, + 0x24, 0xf3, 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, + 0xc2, 0x18, 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, + 0x02, 0xff, 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, + 0xcc, 0x06, 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, + 0xf0, 0x93, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, + 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, + 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, + 0xc0, 0x3b, 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, + 0xae, 0x9f, 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, + 0x6a, 0xc3, 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, + 0x9a, 0xca, 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, + 0x87, 0x80, 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, + 0x3a, 0x3a, 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, + 0x93, 0x0f, 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, + 0x5a, 0x05, 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, + 0xcd, 0x84, 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, + 0xed, 0xbd, 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, + 0x1f, 0x1f, 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, + 0xf6, 0xca, 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, + 0x67, 0xe4, 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, + 0x9c, 0x7c, 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, + 0x76, 0x17, 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, + 0xbb, 0x81, 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, + 0x25, 0xcb, 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, + 0xf8, 0xcf, 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, + 0x86, 0xa6, 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, + 0x1a, 0x43, 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, + 0x77, 0x21, 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, + 0xd8, 0xfb, 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, + 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, + 0x7c, 0x75, 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, + 0xac, 0xaa, 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, + 0xe5, 0xe1, 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, + 0x11, 0xc6, 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, + 0xdd, 0x75, 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, + 0x35, 0x97, 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, + 0xa0, 0x51, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, + 0xb1, 0x7c, 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, + 0x72, 0xbc, 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, + 0x5d, 0x52, 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0x9c, 0x11, 0x69, 0xf7, 0xbb, + 0x77, 0x85, 0x37, 0xaa, 0x28, 0x6f, 0x56, 0xf2, 0x38, 0x07, 0x27, 0x76, 0x63, 0x85, 0x81, 0x7a, 0xe0, 0x42, 0x90, + 0x99, 0x84, 0xdf, 0x9b, 0xb9, 0x25, 0x67, 0x59, 0x99, 0xf4, 0xa1, 0x99, 0x1b, 0x02, 0xf6, 0xff, 0xb2, 0xf7, 0xae, + 0xcb, 0x6d, 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, + 0xa8, 0x32, 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, + 0xe0, 0x06, 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, + 0xfd, 0x3a, 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0xaf, 0xe4, 0xe7, 0xaa, 0xcf, 0xf6, + 0xdb, 0x20, 0x64, 0xbb, 0x20, 0x62, 0x37, 0xc5, 0x36, 0x28, 0xad, 0x23, 0xf1, 0xa3, 0x32, 0xfc, 0x2d, 0xbd, 0x5e, + 0x1e, 0x42, 0xbc, 0x4f, 0x2f, 0xcd, 0xcf, 0xd2, 0x56, 0x14, 0xe0, 0x3e, 0x42, 0x8f, 0xea, 0x40, 0xb0, 0x13, 0x9e, + 0xf0, 0x00, 0x4e, 0x56, 0xb3, 0x8a, 0xbf, 0x4f, 0x41, 0x9c, 0x28, 0x38, 0x04, 0x5c, 0x6d, 0x3f, 0xa6, 0x5f, 0xc1, + 0xf0, 0xa5, 0x83, 0x2d, 0x87, 0x37, 0xc5, 0xb6, 0xc7, 0x4a, 0xfe, 0x0e, 0xd8, 0xb7, 0x7a, 0x32, 0x56, 0xb7, 0x07, + 0xce, 0xba, 0x94, 0xa2, 0xe3, 0x4d, 0x71, 0x78, 0x7b, 0x3e, 0xdb, 0x6f, 0x83, 0x88, 0xed, 0x82, 0x0c, 0x6b, 0x9d, + 0x34, 0x1c, 0x07, 0x43, 0xf8, 0x2c, 0x46, 0xd8, 0xff, 0x65, 0x3d, 0xf0, 0x12, 0x52, 0x43, 0x81, 0x8b, 0xc1, 0x86, + 0xa3, 0xb5, 0x5d, 0xa6, 0x81, 0x9b, 0x1a, 0xf4, 0xfa, 0x9e, 0x42, 0x94, 0x97, 0x8c, 0xe6, 0x46, 0xb0, 0x6e, 0x0c, + 0xb9, 0x38, 0x1c, 0x37, 0xcb, 0x21, 0x2f, 0x69, 0x3a, 0x0d, 0x42, 0xe9, 0xce, 0xb2, 0x86, 0x24, 0xca, 0x3e, 0x08, + 0xb5, 0x6b, 0xcb, 0x7e, 0x1b, 0xd8, 0xbe, 0xfc, 0xd1, 0x30, 0xf6, 0x2f, 0x96, 0x8f, 0x85, 0x74, 0x11, 0xcf, 0x41, + 0x10, 0xb5, 0x9f, 0x67, 0xc3, 0x8d, 0x7f, 0xb1, 0x7e, 0x2c, 0x94, 0xdf, 0x78, 0x6e, 0xcb, 0x21, 0x69, 0xd6, 0xc2, + 0x17, 0xc6, 0x29, 0xc1, 0x95, 0xa1, 0xed, 0x70, 0x10, 0xfa, 0x6f, 0xb3, 0x46, 0x70, 0x63, 0x43, 0xfb, 0x7c, 0xe1, + 0xc3, 0xd6, 0x46, 0x63, 0x4d, 0x31, 0xdd, 0x42, 0xff, 0x26, 0xb3, 0xa5, 0x3d, 0x8d, 0x4a, 0x5e, 0x9c, 0x9a, 0x46, + 0x2c, 0x84, 0x01, 0x43, 0x3f, 0x99, 0x77, 0xa0, 0x9a, 0x3b, 0x1e, 0x81, 0x4c, 0x3e, 0xd0, 0x83, 0x35, 0xa9, 0x55, + 0x7f, 0x0d, 0x33, 0xf9, 0x7f, 0xa4, 0xc2, 0x62, 0x74, 0xb7, 0x0d, 0x33, 0xf5, 0x47, 0x24, 0xff, 0x60, 0x39, 0xdf, + 0xa5, 0x5e, 0xa8, 0xfd, 0x58, 0x58, 0x81, 0x41, 0x89, 0xaa, 0x01, 0x3d, 0x10, 0x41, 0x55, 0x06, 0x69, 0x86, 0xd5, + 0x39, 0xe8, 0x77, 0x4f, 0xab, 0x8e, 0xe4, 0x90, 0xd6, 0x6a, 0x48, 0x05, 0x53, 0xa5, 0x06, 0xf9, 0xe1, 0x70, 0x9b, + 0x32, 0x5d, 0x06, 0x5c, 0xd2, 0x6f, 0x53, 0xa5, 0x14, 0xfe, 0x82, 0x00, 0x74, 0x0e, 0xee, 0xf1, 0xe5, 0x18, 0x48, + 0x33, 0x2c, 0xfc, 0xd6, 0xec, 0xf8, 0x9a, 0x84, 0xdb, 0x24, 0xb8, 0x18, 0xe0, 0x1c, 0x5d, 0x85, 0xe5, 0x6d, 0x0a, + 0x11, 0x54, 0x25, 0xd4, 0xb7, 0x32, 0x0d, 0x4a, 0x5b, 0x0d, 0xc2, 0x9a, 0x84, 0x3a, 0x93, 0x6c, 0x54, 0xda, 0x6e, + 0x14, 0x66, 0x8b, 0xb8, 0x9e, 0x11, 0xd6, 0x9c, 0xcd, 0x54, 0x03, 0x93, 0x86, 0xe3, 0xa6, 0xd1, 0x5a, 0x54, 0xa8, + 0x29, 0xcc, 0x6b, 0x5c, 0x55, 0xaa, 0xba, 0x9b, 0x53, 0x4b, 0x69, 0xd9, 0x5e, 0x75, 0x93, 0x6c, 0xc8, 0x65, 0x28, + 0xc3, 0x60, 0x23, 0x47, 0x30, 0x81, 0x24, 0x39, 0xf3, 0x37, 0xf2, 0x0f, 0xb5, 0xe9, 0x5a, 0xc0, 0x1c, 0x63, 0x96, + 0x0d, 0x0b, 0x7a, 0x05, 0xee, 0x81, 0x56, 0x7a, 0x3e, 0xcd, 0x2e, 0xf2, 0x20, 0x19, 0x16, 0x7a, 0xd9, 0x64, 0xfc, + 0x8b, 0x30, 0xd2, 0x64, 0xc6, 0x4a, 0x16, 0xd9, 0xae, 0x4e, 0x89, 0xf3, 0x38, 0x81, 0xed, 0xd1, 0xf4, 0x96, 0xef, + 0x33, 0x88, 0x0a, 0x02, 0x05, 0x33, 0xe6, 0xcb, 0x2e, 0x9e, 0xf8, 0x3e, 0xb3, 0x4c, 0xdd, 0x87, 0x83, 0x31, 0x63, + 0xfb, 0xfd, 0x7e, 0xde, 0xef, 0xab, 0xf9, 0xd6, 0xef, 0x27, 0x4f, 0xcd, 0xdf, 0x1e, 0x30, 0x28, 0xc8, 0x89, 0x68, + 0x2a, 0x44, 0xf0, 0x0f, 0xc9, 0x63, 0x24, 0xa3, 0x3b, 0xee, 0x73, 0xcb, 0xf3, 0xb3, 0x3a, 0x02, 0xc1, 0x3c, 0x1c, + 0x2e, 0x15, 0xd8, 0xb5, 0x44, 0x91, 0x90, 0xe5, 0x3f, 0x06, 0xe3, 0x99, 0xfb, 0x00, 0x4b, 0x06, 0x20, 0x6c, 0x95, + 0xa7, 0xeb, 0x3d, 0x5f, 0x05, 0xef, 0x74, 0xbc, 0x6b, 0xac, 0xc8, 0x40, 0xdc, 0x02, 0x1b, 0xb1, 0xd6, 0x1e, 0x90, + 0x33, 0x05, 0x38, 0x5e, 0x1c, 0x0e, 0xe7, 0xf2, 0x97, 0x6e, 0xb6, 0x4e, 0xa0, 0x52, 0xe0, 0xf6, 0xe8, 0xe4, 0xe0, + 0x7f, 0x00, 0xcd, 0xa0, 0x1c, 0xe6, 0xf5, 0xf6, 0x0f, 0xe6, 0xe4, 0xa7, 0xa7, 0xf8, 0x27, 0x3c, 0x44, 0xa7, 0xdf, + 0xee, 0xcd, 0x1f, 0x14, 0x95, 0x87, 0x83, 0x5a, 0xfc, 0xe7, 0x9c, 0x57, 0xf0, 0x0b, 0xdf, 0x04, 0x66, 0x93, 0xa9, + 0x77, 0xf2, 0x4d, 0x9e, 0x33, 0xf5, 0x1a, 0xaf, 0x98, 0x7c, 0x87, 0xc3, 0xb9, 0x18, 0xd5, 0xdb, 0x91, 0x13, 0xed, + 0x94, 0x63, 0x1c, 0x0c, 0xfe, 0x8b, 0x68, 0x9b, 0x10, 0x60, 0x28, 0x97, 0x68, 0x66, 0xe3, 0xca, 0x12, 0xcf, 0xd2, + 0xf9, 0xe5, 0xa4, 0x2e, 0x77, 0x5a, 0xf1, 0xb4, 0x07, 0x16, 0xb7, 0x35, 0x78, 0x01, 0xdc, 0x59, 0x6c, 0x5d, 0x29, + 0x38, 0x5c, 0x40, 0x9c, 0xe2, 0x04, 0x44, 0xd0, 0x7e, 0x5f, 0xe2, 0xbd, 0x82, 0x3e, 0xe9, 0x27, 0x08, 0x86, 0x7c, + 0x2d, 0x01, 0x77, 0xbd, 0x5e, 0x8d, 0xf1, 0xbd, 0x14, 0x82, 0xeb, 0x33, 0x0d, 0x40, 0x0b, 0x7e, 0x97, 0x0f, 0xe5, + 0xf4, 0x9b, 0x08, 0x3c, 0x5b, 0xf6, 0x26, 0xca, 0xdd, 0x86, 0xa7, 0xfd, 0xd8, 0x42, 0x00, 0x96, 0xe2, 0x99, 0x12, + 0x2c, 0xc8, 0x29, 0xe6, 0xe2, 0xff, 0x05, 0x1f, 0x31, 0xdf, 0x93, 0x2e, 0x62, 0xeb, 0xed, 0xa3, 0x0b, 0x03, 0x09, + 0x34, 0x1d, 0x80, 0x1f, 0xaf, 0x02, 0xba, 0x32, 0x3e, 0xb3, 0x96, 0xf5, 0x58, 0x1f, 0xff, 0x29, 0xb8, 0x4f, 0x3f, + 0x56, 0xf8, 0xe8, 0x70, 0x5c, 0xa5, 0xa3, 0x1d, 0xa5, 0x20, 0x3a, 0xba, 0x7d, 0x3e, 0x15, 0xd9, 0x77, 0x15, 0x90, + 0x5b, 0x8e, 0xda, 0x53, 0x01, 0x58, 0x6c, 0xe9, 0x08, 0x7c, 0x9a, 0xe5, 0x13, 0xf2, 0xbd, 0x9e, 0x8a, 0xab, 0x4b, + 0x9d, 0x2e, 0x9e, 0x8e, 0xa7, 0xf0, 0x3f, 0x10, 0x7b, 0x58, 0xd8, 0xb9, 0x1d, 0xbb, 0x2e, 0x7e, 0x10, 0x6f, 0x6b, + 0x3b, 0xfa, 0x63, 0x07, 0x91, 0x8e, 0x7b, 0x72, 0xa1, 0xbe, 0x84, 0x54, 0x72, 0xa1, 0x6e, 0x20, 0x76, 0xa1, 0xc6, + 0x3b, 0x2e, 0x62, 0xad, 0xbf, 0xa9, 0x51, 0xb0, 0x12, 0x70, 0xa6, 0xbd, 0x01, 0x83, 0x0d, 0xac, 0x5b, 0x96, 0xc1, + 0xdf, 0x70, 0x4d, 0x13, 0xb8, 0x61, 0x91, 0xf5, 0xde, 0x60, 0x2b, 0xbd, 0x01, 0x47, 0xcb, 0xc4, 0xb9, 0x94, 0x24, + 0x65, 0x8b, 0x8c, 0xab, 0x47, 0x21, 0x55, 0xd3, 0xfd, 0x8d, 0xa8, 0xef, 0x85, 0xc8, 0x83, 0x55, 0xca, 0xa2, 0x62, + 0x05, 0x32, 0x7b, 0xf0, 0xf7, 0x90, 0x91, 0xa3, 0x1c, 0x38, 0x0a, 0xfd, 0xb3, 0x09, 0x74, 0x1e, 0x11, 0xe9, 0x3c, + 0x12, 0x6c, 0xa5, 0x1e, 0x0a, 0x2b, 0x2f, 0x20, 0x3a, 0x58, 0x1d, 0xf1, 0xa6, 0xf2, 0x24, 0x54, 0x6c, 0xca, 0x44, + 0x1e, 0x07, 0xb5, 0x04, 0x8c, 0x15, 0x04, 0x73, 0x96, 0x4b, 0x17, 0xa4, 0xaa, 0xd1, 0xc3, 0x22, 0x73, 0xff, 0x20, + 0x28, 0xff, 0x0f, 0x2a, 0x27, 0x5c, 0x5f, 0x86, 0x00, 0x47, 0xfb, 0x03, 0x88, 0x12, 0x63, 0xfd, 0xa2, 0x65, 0x74, + 0xc9, 0x9c, 0x4d, 0x6d, 0x2f, 0x41, 0xc6, 0x76, 0xf8, 0x15, 0x42, 0xab, 0x85, 0x22, 0x8b, 0x86, 0x0b, 0xa6, 0xdb, + 0x53, 0x5a, 0x75, 0x0f, 0x1b, 0x9e, 0x94, 0x1e, 0x2a, 0xf5, 0x6d, 0x4c, 0x60, 0x59, 0xa5, 0x0c, 0xdf, 0x4e, 0xa8, + 0x3a, 0x31, 0xa8, 0x58, 0x37, 0x6c, 0x09, 0x87, 0x58, 0x4c, 0x1a, 0xeb, 0x6c, 0xc0, 0x23, 0x96, 0xc0, 0x3f, 0x1b, + 0x3e, 0x66, 0x4b, 0x1e, 0x4d, 0x36, 0x57, 0xcb, 0x7e, 0xbf, 0xf4, 0x42, 0xaf, 0x9e, 0x65, 0x3f, 0x44, 0xf3, 0x59, + 0x3e, 0xf7, 0x51, 0x71, 0x31, 0x19, 0x0c, 0x36, 0x7e, 0x36, 0x1c, 0xb2, 0x64, 0x38, 0x9c, 0x64, 0x3f, 0xc0, 0x6b, + 0x3f, 0xf0, 0x48, 0x2d, 0xa9, 0xe4, 0x2a, 0x83, 0xfd, 0x7d, 0xc0, 0x23, 0x9f, 0x75, 0x7e, 0x5a, 0x36, 0x5d, 0xba, + 0x9f, 0x59, 0x1d, 0x10, 0xe9, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xed, 0x0e, 0x29, 0x75, 0x93, 0x01, 0xd8, + 0x8d, 0x06, 0x38, 0x64, 0xaa, 0x97, 0x22, 0xab, 0x97, 0x32, 0xd5, 0x4b, 0xb2, 0x72, 0x09, 0x16, 0x12, 0x53, 0xe5, + 0x36, 0xb2, 0x72, 0xcb, 0x86, 0xeb, 0xe1, 0x60, 0x6b, 0xc5, 0x65, 0x73, 0x0b, 0xf7, 0x85, 0x15, 0x05, 0xfe, 0xdf, + 0xb0, 0x05, 0xbb, 0x93, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0x45, 0x5e, 0xc5, 0xee, 0xd8, 0x0d, 0xd8, 0x61, 0xe1, 0x2f, + 0xb8, 0x4e, 0x8e, 0xd9, 0x0e, 0x1f, 0x85, 0x5e, 0xc1, 0x6e, 0x7c, 0x02, 0xda, 0x05, 0x5b, 0x03, 0x64, 0x63, 0x5b, + 0x7c, 0x74, 0x7b, 0x38, 0x5c, 0x7b, 0x3e, 0xbb, 0xc7, 0x1f, 0xe7, 0xb7, 0x87, 0xc3, 0xce, 0x33, 0xea, 0xbd, 0x37, + 0x3c, 0x61, 0x8f, 0x78, 0x32, 0x79, 0x73, 0xc5, 0xe3, 0xc9, 0x60, 0xf0, 0xc6, 0x5f, 0xf0, 0x7a, 0xf6, 0x06, 0xb4, + 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x78, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe0, 0xe8, 0xed, 0xf7, 0xbd, 0x5b, + 0x1e, 0x79, 0x37, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, 0x99, + 0xbe, 0x09, 0x1e, 0xf9, 0x6c, 0xa5, 0x59, 0xe0, 0xee, 0x31, 0xc7, 0x9a, 0xec, 0x84, 0x66, 0xe2, 0xaf, 0xb0, 0x7f, + 0xde, 0xa8, 0xfe, 0xa1, 0xf9, 0x5f, 0xea, 0x7e, 0x02, 0xb7, 0x2f, 0xb2, 0x20, 0xb1, 0x47, 0xfc, 0x0d, 0xbb, 0xe3, + 0x86, 0x6d, 0xf6, 0xcc, 0x94, 0x7d, 0xa2, 0xd4, 0xf8, 0x81, 0x52, 0xd7, 0x16, 0x24, 0x73, 0xeb, 0xca, 0x87, 0xc0, + 0xe1, 0x80, 0xfc, 0x74, 0x8b, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x51, 0xe6, 0xe5, 0xc0, + 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, 0xae, + 0x4a, 0xb2, 0x96, 0x2d, 0x09, 0x51, 0xb6, 0xeb, 0xe1, 0x25, 0x42, 0xa6, 0xf5, 0xfb, 0xe7, 0x44, 0xb2, 0x36, 0xa9, + 0xae, 0x6a, 0xb4, 0x04, 0x54, 0x64, 0x09, 0x98, 0xf8, 0x95, 0xe6, 0x13, 0x80, 0x27, 0x1d, 0x0f, 0xaa, 0x1f, 0x78, + 0xcd, 0x04, 0x91, 0x6d, 0x54, 0xfe, 0xa4, 0x78, 0x8a, 0x64, 0x04, 0xc5, 0x0f, 0xb5, 0xca, 0x58, 0x18, 0xe6, 0x81, + 0x02, 0xf2, 0xee, 0xdd, 0xa9, 0x6f, 0xd1, 0xd6, 0x74, 0xec, 0xd9, 0x5a, 0x85, 0x5a, 0xa8, 0x29, 0x5c, 0x72, 0x88, + 0xae, 0x40, 0x03, 0x45, 0x24, 0xe3, 0xc9, 0xeb, 0xc1, 0xe5, 0x24, 0xba, 0xe2, 0x02, 0x9d, 0xf1, 0xf5, 0x4d, 0x37, + 0x9d, 0x45, 0x3f, 0x54, 0xf3, 0x09, 0x29, 0xc9, 0x0e, 0x87, 0x6c, 0x54, 0xd5, 0xc5, 0x7a, 0x1a, 0xca, 0x9f, 0x1e, + 0x82, 0xaf, 0x17, 0xd4, 0x6b, 0xb2, 0x4a, 0xf5, 0x0f, 0x54, 0x29, 0x2f, 0x1a, 0x5e, 0xfa, 0x3f, 0x54, 0x72, 0xdf, + 0x03, 0xd2, 0x5a, 0x5e, 0x72, 0xf9, 0x7e, 0x84, 0x18, 0x23, 0x7e, 0xe0, 0x95, 0x3c, 0x62, 0xa1, 0x9a, 0xc2, 0x35, + 0x8f, 0x10, 0xe4, 0x2d, 0xd3, 0xc1, 0xdf, 0x7a, 0xe2, 0x74, 0x7f, 0xa2, 0xb4, 0x8b, 0x2f, 0x2c, 0xa6, 0x95, 0x23, + 0xdd, 0x80, 0x1c, 0x6c, 0x98, 0x2e, 0x0a, 0xb2, 0x4d, 0x69, 0x04, 0x6d, 0xb4, 0x1c, 0xd8, 0x70, 0x2a, 0xb5, 0xe1, + 0xcc, 0x35, 0x04, 0xf7, 0xf9, 0x79, 0x3a, 0x5a, 0xc0, 0x87, 0x54, 0xb7, 0x97, 0xf8, 0x79, 0xd8, 0x68, 0x81, 0xcc, + 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x5c, 0x01, 0xbb, 0x9d, 0x5d, 0x83, 0x1c, 0x31, 0x73, 0x5f, 0xa1, 0xfa, + 0x16, 0x0d, 0xb8, 0x32, 0xd6, 0xbe, 0x26, 0x19, 0x0b, 0xaf, 0xca, 0x69, 0x38, 0x00, 0x18, 0xba, 0x8c, 0xbe, 0xb6, + 0xdc, 0x64, 0xd9, 0xeb, 0x02, 0x82, 0x20, 0x4a, 0xe2, 0xf1, 0x01, 0xef, 0xcb, 0x6a, 0xa8, 0x51, 0xf2, 0xb1, 0xec, + 0x18, 0xbe, 0x5e, 0xa2, 0xbf, 0x1b, 0x73, 0x89, 0x01, 0xaf, 0xab, 0xb6, 0xa0, 0x70, 0x9e, 0x1f, 0x0e, 0xe7, 0xf9, + 0xc8, 0x78, 0x96, 0x81, 0x6a, 0x65, 0x5a, 0x07, 0x4b, 0x33, 0x5f, 0x2c, 0xfc, 0xc5, 0xce, 0x49, 0x44, 0x14, 0x04, + 0x76, 0x24, 0x3c, 0x88, 0xd4, 0x8f, 0x2a, 0x4f, 0x77, 0xaa, 0xcf, 0xf6, 0x0b, 0x9b, 0x48, 0x2f, 0x28, 0x99, 0x7c, + 0x12, 0xec, 0x55, 0x7f, 0x07, 0x61, 0x43, 0x78, 0xf3, 0xaa, 0xd7, 0x59, 0xa6, 0x66, 0x25, 0x48, 0x98, 0x31, 0x47, + 0xf0, 0x38, 0xec, 0x34, 0xb6, 0xe1, 0xb1, 0x11, 0xcb, 0x96, 0xde, 0x9a, 0xdd, 0xb2, 0x15, 0xbb, 0x51, 0x75, 0x5a, + 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa5, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, + 0xd6, 0x3f, 0x44, 0x6a, 0xf1, 0xac, 0x87, 0x7c, 0x41, 0xeb, 0x4f, 0xcc, 0x6e, 0x4d, 0xf2, 0xed, 0x80, 0x2f, 0x26, + 0xeb, 0x1f, 0x22, 0x78, 0xf5, 0x07, 0xb0, 0x62, 0x64, 0xce, 0x2c, 0x5b, 0xff, 0x10, 0xe1, 0x98, 0xdd, 0xfe, 0x10, + 0xd1, 0xa8, 0xad, 0xe4, 0xbe, 0x74, 0xd3, 0x80, 0xb0, 0x72, 0xc3, 0x62, 0x78, 0x0d, 0xc4, 0x33, 0x6d, 0x24, 0x5d, + 0x4b, 0x43, 0x6f, 0xcc, 0xc3, 0x69, 0x1c, 0xac, 0xa9, 0x15, 0xf2, 0xcc, 0x10, 0xb3, 0xf8, 0x87, 0x68, 0xce, 0x56, + 0x58, 0x91, 0x0d, 0x8f, 0x07, 0x97, 0x93, 0xcd, 0x15, 0x5f, 0x03, 0xf9, 0xd9, 0x64, 0x63, 0xb6, 0xa8, 0x1b, 0x2e, + 0x66, 0x9b, 0x1f, 0xa2, 0xf9, 0x64, 0x05, 0x3d, 0x6b, 0x0f, 0x98, 0xf7, 0x12, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, + 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x5b, 0xb6, 0xbe, 0x0c, 0x6e, 0xd8, 0x7a, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x06, + 0x16, 0x5f, 0xc4, 0xd6, 0x97, 0x26, 0x6d, 0xf3, 0x43, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xce, 0xbc, 0x15, + 0x83, 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0x6e, 0xf9, 0x0d, 0x4b, + 0xf8, 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x56, 0x28, 0x8b, 0x85, 0x51, 0xb9, 0x6f, + 0xc1, 0x01, 0x05, 0x69, 0x1b, 0x20, 0x48, 0xe2, 0xd9, 0x5d, 0x87, 0xeb, 0x8f, 0x52, 0x18, 0x70, 0x13, 0x98, 0x01, + 0x03, 0xd3, 0xcf, 0xe0, 0x87, 0x95, 0x2e, 0x11, 0xe2, 0xec, 0xa7, 0x94, 0x24, 0xf3, 0xfc, 0xbd, 0x48, 0x73, 0xb7, + 0x70, 0x9d, 0xc2, 0xac, 0x28, 0x50, 0xfd, 0x94, 0x94, 0x06, 0x16, 0x2a, 0x91, 0xa9, 0x14, 0xfc, 0xb2, 0x76, 0xda, + 0x75, 0x76, 0x8c, 0xce, 0x75, 0x7e, 0x39, 0x71, 0x4e, 0x27, 0x7d, 0xff, 0x81, 0x63, 0xd8, 0x42, 0x06, 0x2e, 0xfc, + 0xa9, 0x27, 0x8c, 0x53, 0x2b, 0x10, 0x53, 0xc9, 0xb3, 0xa7, 0xf0, 0x99, 0xd0, 0xea, 0xe8, 0xc2, 0xf7, 0x83, 0x42, + 0x9b, 0xa4, 0x5b, 0x90, 0xa4, 0xe0, 0x29, 0x7a, 0xce, 0x79, 0x1b, 0xa8, 0x14, 0x23, 0x5a, 0x10, 0x69, 0xeb, 0x36, + 0x73, 0x90, 0xb6, 0x34, 0xdf, 0x35, 0xf1, 0x73, 0x58, 0xc0, 0x45, 0xb4, 0xb0, 0x35, 0x3c, 0xaa, 0x62, 0xe5, 0xde, + 0xe4, 0x39, 0xc2, 0x19, 0x5d, 0xca, 0x04, 0xc0, 0xf5, 0x7e, 0x11, 0xd6, 0x0a, 0xaf, 0xa8, 0x59, 0xe4, 0x45, 0x4d, + 0x9f, 0x6c, 0x81, 0xfb, 0x58, 0x94, 0x28, 0x70, 0xd6, 0x82, 0x01, 0x5b, 0x61, 0xc9, 0x4e, 0x0a, 0x9b, 0xa2, 0x25, + 0xf4, 0xf6, 0xf8, 0xe9, 0xa0, 0x66, 0x32, 0x80, 0x26, 0x80, 0xc6, 0xe3, 0x5f, 0x00, 0x6a, 0xfa, 0xb1, 0x16, 0xeb, + 0x2a, 0x28, 0x95, 0x72, 0x13, 0x7e, 0x06, 0x86, 0x19, 0x7e, 0x28, 0xe4, 0x36, 0x51, 0x22, 0xe7, 0xc7, 0xa2, 0x14, + 0xcb, 0x52, 0x54, 0x49, 0xbb, 0xa1, 0xe0, 0x11, 0xe1, 0x36, 0x68, 0xcc, 0xdc, 0x9e, 0xe8, 0xa2, 0x15, 0xa1, 0x1c, + 0x9b, 0x75, 0x8c, 0x34, 0xca, 0xec, 0x64, 0xd7, 0xc9, 0x42, 0xfb, 0x7d, 0x95, 0x43, 0xd6, 0x01, 0x6b, 0x24, 0x5f, + 0xaf, 0x39, 0x74, 0xdb, 0x28, 0x2f, 0xee, 0x3d, 0x5f, 0xc1, 0x69, 0x8e, 0x27, 0x76, 0xd7, 0xeb, 0x4e, 0x91, 0x88, + 0x57, 0x38, 0xa9, 0xf2, 0x91, 0x2c, 0x1c, 0x77, 0xee, 0xb4, 0x16, 0xab, 0xca, 0x65, 0x3d, 0xb5, 0x38, 0x22, 0xf0, + 0xa9, 0x3c, 0xda, 0x0b, 0x6d, 0x8b, 0x62, 0x21, 0x8c, 0x1e, 0x9d, 0xf0, 0x93, 0x12, 0x58, 0x5f, 0x87, 0xc3, 0xd2, + 0x8f, 0x38, 0xfa, 0x9d, 0x46, 0xa3, 0x05, 0x21, 0x0d, 0x4f, 0xbd, 0x68, 0xb4, 0xa8, 0x8b, 0x3a, 0xcc, 0x9e, 0xe6, + 0x7a, 0xa0, 0x30, 0x8c, 0x40, 0xfd, 0xe0, 0x2a, 0x83, 0xcf, 0x22, 0x44, 0xcd, 0x03, 0xd3, 0x6c, 0x08, 0x47, 0x5d, + 0xe0, 0xa1, 0x15, 0xb4, 0x98, 0x99, 0x8f, 0x42, 0x0c, 0x1f, 0xd2, 0xc5, 0xf9, 0x13, 0xb2, 0xf2, 0x01, 0x76, 0x87, + 0xee, 0x42, 0x39, 0x67, 0x2a, 0x06, 0xf8, 0x51, 0x40, 0x3e, 0x4a, 0xc0, 0xcd, 0x00, 0xd9, 0x23, 0x4b, 0x00, 0xb1, + 0x62, 0x74, 0x34, 0xf9, 0xdc, 0xf7, 0x22, 0x05, 0xef, 0xec, 0xb3, 0x5c, 0x4d, 0x18, 0x0a, 0x9f, 0x18, 0xe8, 0xe6, + 0x37, 0x7e, 0x7b, 0xde, 0x82, 0x91, 0x5d, 0x92, 0xe2, 0xb5, 0x66, 0xb8, 0xdf, 0x80, 0xdb, 0x11, 0x50, 0xd6, 0x54, + 0xc7, 0x24, 0xdb, 0x34, 0x44, 0x32, 0x60, 0x46, 0x8c, 0x08, 0x2a, 0xcb, 0x85, 0xff, 0xdd, 0xcb, 0xa2, 0xc0, 0x01, + 0x5c, 0xcd, 0x64, 0xf0, 0xda, 0x85, 0x51, 0x01, 0x70, 0x4e, 0x43, 0xa7, 0xb4, 0x57, 0x55, 0x87, 0x64, 0xd5, 0xfc, + 0x60, 0x36, 0x6f, 0x1a, 0x26, 0x46, 0x04, 0xd1, 0x45, 0x38, 0xc1, 0xf4, 0x8a, 0xf4, 0xb5, 0x92, 0xd3, 0xd1, 0xaa, + 0xa3, 0xb5, 0xc4, 0xc4, 0x5c, 0x51, 0xfc, 0x35, 0xe0, 0x71, 0x83, 0x57, 0x27, 0x69, 0x3a, 0x51, 0x3d, 0x7a, 0xfc, + 0x3a, 0x4d, 0x27, 0x25, 0xee, 0x0a, 0xbf, 0x01, 0x17, 0xcd, 0x36, 0x1f, 0xfa, 0xf1, 0x0b, 0x8a, 0xb8, 0xa8, 0xc1, + 0x95, 0x77, 0xaa, 0xaf, 0x54, 0x1f, 0x41, 0x2d, 0x3c, 0x31, 0xb2, 0x16, 0x9e, 0x5c, 0xb2, 0xd6, 0x82, 0x60, 0x66, + 0x73, 0xe0, 0x42, 0x7e, 0xa5, 0x14, 0xf1, 0x26, 0x12, 0x6a, 0x31, 0x68, 0x3d, 0x66, 0xce, 0xaa, 0xd1, 0x42, 0x65, + 0x46, 0x68, 0xdf, 0xd6, 0xa2, 0xf3, 0x1b, 0xf9, 0x29, 0x4f, 0xed, 0xcb, 0xf6, 0x38, 0x1f, 0xef, 0xd1, 0x5d, 0x75, + 0x96, 0x99, 0x94, 0xf1, 0xc9, 0x2c, 0x41, 0xe1, 0x2e, 0xc1, 0x06, 0x24, 0xd9, 0x6f, 0x75, 0x80, 0x8c, 0xda, 0x6b, + 0xbf, 0xeb, 0x2c, 0x5f, 0xdd, 0x6c, 0x0d, 0x45, 0xa5, 0x56, 0x92, 0xe2, 0x20, 0xc3, 0x75, 0x5b, 0xf9, 0x70, 0x71, + 0x01, 0x3d, 0x63, 0x24, 0x32, 0xcf, 0x9f, 0xc8, 0x97, 0xe0, 0x9c, 0x71, 0x56, 0x08, 0x4c, 0x18, 0xab, 0x77, 0xad, + 0xa5, 0xd2, 0x90, 0x62, 0xec, 0x68, 0x94, 0x65, 0x95, 0xa5, 0xcb, 0x6c, 0x2d, 0x61, 0xcb, 0x2a, 0x72, 0x0b, 0xbb, + 0xcd, 0x64, 0x35, 0xdf, 0x55, 0xdc, 0x41, 0xf9, 0x66, 0xab, 0x8c, 0xef, 0x25, 0xb2, 0x77, 0x1b, 0x28, 0xe1, 0xe9, + 0xe8, 0x2f, 0x48, 0xbf, 0xcd, 0x30, 0x4e, 0xb9, 0xad, 0xa4, 0x05, 0x38, 0xfd, 0xc3, 0xe1, 0x5d, 0x85, 0x41, 0x83, + 0x23, 0x8c, 0x23, 0xeb, 0xf7, 0x17, 0x95, 0x57, 0x63, 0xa2, 0x8e, 0xcf, 0xea, 0xf7, 0x2b, 0x7a, 0x38, 0xad, 0x46, + 0xab, 0x74, 0x8b, 0xec, 0x84, 0x36, 0x56, 0x7e, 0x50, 0x2b, 0x60, 0xf6, 0xd6, 0xe7, 0xd3, 0x01, 0xe8, 0x58, 0x80, + 0x44, 0xb3, 0x99, 0x48, 0xcc, 0x49, 0xf7, 0x24, 0x3c, 0x3e, 0xb0, 0xc0, 0x01, 0xa6, 0xe2, 0xff, 0x12, 0xde, 0x0c, + 0x6c, 0xd0, 0x28, 0xd1, 0xd7, 0xe8, 0xaa, 0x36, 0x37, 0x3a, 0x5e, 0x7a, 0x0a, 0x89, 0xac, 0x60, 0xd5, 0xdc, 0x97, + 0x1b, 0x38, 0xed, 0xa1, 0xe6, 0x50, 0x59, 0x82, 0xbf, 0xfd, 0x32, 0x3f, 0x1c, 0x56, 0x19, 0x14, 0xb6, 0x5b, 0x0b, + 0xed, 0x8d, 0x59, 0xaa, 0xa1, 0x22, 0x1c, 0x74, 0xbe, 0x12, 0xb3, 0x7a, 0x44, 0x7f, 0xcf, 0x0f, 0x87, 0x15, 0x81, + 0x01, 0x87, 0xa5, 0xcc, 0x44, 0x0b, 0xc5, 0xd2, 0x3a, 0x9b, 0x51, 0x1d, 0x78, 0x60, 0x62, 0xce, 0xc2, 0x1d, 0x80, + 0x36, 0xa9, 0x55, 0xa0, 0x57, 0x11, 0xfd, 0xc4, 0xfd, 0xda, 0x7e, 0xbd, 0x1e, 0x99, 0xa5, 0x23, 0x37, 0xc6, 0x02, + 0x80, 0x03, 0xcf, 0x6b, 0x92, 0xe7, 0xe4, 0x6b, 0x68, 0xf7, 0xe4, 0x42, 0xfe, 0x04, 0x65, 0x0b, 0xcf, 0x55, 0xd3, + 0xca, 0x62, 0xc5, 0x55, 0xf5, 0xea, 0x82, 0x57, 0x26, 0xd3, 0x2a, 0xad, 0x44, 0xa5, 0x04, 0x03, 0xea, 0x12, 0xaf, + 0x35, 0xcd, 0x28, 0xb5, 0x51, 0x67, 0xa2, 0x06, 0x6c, 0xb0, 0x9f, 0xaa, 0x8d, 0x4e, 0xce, 0xe5, 0xf3, 0x4b, 0xe3, + 0xf0, 0x69, 0x57, 0x6f, 0x66, 0x2a, 0x07, 0xfe, 0x5a, 0xf9, 0xd0, 0xea, 0x31, 0xd0, 0x01, 0x39, 0xfd, 0x31, 0x2c, + 0x26, 0x76, 0x87, 0xe6, 0xed, 0xee, 0xb2, 0xba, 0x48, 0xef, 0x34, 0x25, 0xb3, 0x7a, 0xcb, 0x67, 0x56, 0x8f, 0x0e, + 0x78, 0xf1, 0x50, 0xef, 0x15, 0x66, 0x12, 0xc1, 0xc5, 0x50, 0x4d, 0x22, 0xbb, 0x03, 0xad, 0x79, 0x54, 0x31, 0x01, + 0x7e, 0x50, 0x6a, 0x4d, 0xef, 0xed, 0xae, 0x50, 0xa7, 0x14, 0x1e, 0xb7, 0x96, 0xfc, 0xc0, 0xdc, 0x69, 0xd7, 0x3a, + 0x1f, 0xcf, 0x2f, 0x7d, 0xbf, 0x91, 0x27, 0xb4, 0xd9, 0x99, 0x9c, 0xfe, 0xc9, 0x5b, 0xfd, 0xc3, 0x54, 0xdf, 0x42, + 0x77, 0x82, 0x3e, 0x43, 0x57, 0x55, 0x77, 0x25, 0xb6, 0x30, 0xd4, 0x13, 0x8b, 0xbc, 0x90, 0x27, 0xad, 0xb1, 0xe3, + 0x60, 0x6f, 0x80, 0x13, 0xbf, 0x3c, 0x1c, 0xc4, 0x55, 0xee, 0xb3, 0xf3, 0xae, 0x91, 0x95, 0x03, 0x58, 0x41, 0x14, + 0x8c, 0x5b, 0xf3, 0xb1, 0x0d, 0xd2, 0x25, 0xae, 0xc6, 0xc7, 0x6f, 0x28, 0x96, 0xc9, 0x26, 0xe2, 0xe2, 0x22, 0xff, + 0xe1, 0x09, 0x90, 0x96, 0xf5, 0xfb, 0xd1, 0xd3, 0xcb, 0xe9, 0x93, 0x61, 0x14, 0x80, 0x63, 0x97, 0xbd, 0xbc, 0x8c, + 0xf9, 0xea, 0x92, 0x59, 0xa6, 0xb0, 0xc8, 0x37, 0x03, 0xaa, 0x4b, 0x56, 0x4b, 0xd7, 0x2b, 0xc0, 0xd2, 0xe5, 0x37, + 0xf7, 0x61, 0x6a, 0x40, 0x23, 0x6b, 0xee, 0x4e, 0x73, 0x2d, 0x50, 0xea, 0x79, 0x3f, 0x33, 0xe4, 0xeb, 0x32, 0xe8, + 0x0a, 0xd2, 0x3d, 0x8f, 0x48, 0x2f, 0xf7, 0xd2, 0xe9, 0x7e, 0x5f, 0x0a, 0xb0, 0xd4, 0x97, 0xe2, 0x33, 0x28, 0x2c, + 0x1a, 0xdf, 0x08, 0xd0, 0xd6, 0x50, 0x4d, 0x7b, 0xa5, 0xa8, 0x7a, 0x41, 0xaf, 0x14, 0x9f, 0x7b, 0x7a, 0xa8, 0xcc, + 0x97, 0xa5, 0xa3, 0xff, 0x09, 0x35, 0x17, 0x9c, 0x10, 0x33, 0x31, 0x07, 0x50, 0x09, 0xda, 0xf8, 0x16, 0x47, 0x1b, + 0x9f, 0xea, 0x55, 0xdc, 0xf4, 0x79, 0x6d, 0x2d, 0x73, 0x42, 0xd8, 0x74, 0x2f, 0x01, 0x2a, 0xf2, 0x4a, 0x78, 0x04, + 0xcb, 0x2f, 0x7f, 0xc8, 0xd3, 0x15, 0xa2, 0x75, 0xdc, 0xb3, 0xcc, 0xa5, 0xb1, 0x7f, 0x69, 0x30, 0x7d, 0x7d, 0xbb, + 0x2d, 0xf2, 0x53, 0x13, 0x13, 0xd6, 0x63, 0x45, 0xdf, 0xbc, 0x0d, 0x57, 0x02, 0x05, 0x0e, 0x25, 0x12, 0xdb, 0x54, + 0xa1, 0x88, 0x07, 0x49, 0x9f, 0x2e, 0x5a, 0x9f, 0x06, 0x98, 0x5a, 0xcb, 0x81, 0x39, 0x84, 0xab, 0xb8, 0xf0, 0xd1, + 0xd3, 0xb7, 0x98, 0x85, 0xf3, 0x89, 0xf7, 0xc1, 0x2b, 0x46, 0xe6, 0xe3, 0x3e, 0x2a, 0x95, 0xf4, 0xcf, 0xc3, 0x61, + 0x56, 0xcd, 0x7d, 0x87, 0x3e, 0xd2, 0x43, 0x95, 0x0b, 0xca, 0xde, 0x18, 0x93, 0x08, 0x94, 0xc6, 0x78, 0x1f, 0x07, + 0xc7, 0x79, 0x9f, 0x06, 0x90, 0xda, 0x27, 0xde, 0x91, 0x92, 0xc3, 0x73, 0x8e, 0x39, 0xa1, 0xb4, 0x22, 0xac, 0xe2, + 0xdb, 0x0c, 0xe5, 0xba, 0x53, 0x0a, 0x26, 0x39, 0x24, 0x18, 0xfe, 0xaa, 0x79, 0x13, 0x2b, 0x10, 0x76, 0xcd, 0xbc, + 0x1a, 0x3d, 0xaa, 0x92, 0xb0, 0x14, 0x71, 0xbf, 0xbf, 0xcb, 0x3c, 0xc3, 0xde, 0xf0, 0xc8, 0x30, 0x72, 0xb0, 0xdc, + 0x1f, 0xd5, 0x89, 0xc8, 0x3d, 0xba, 0xc0, 0xa8, 0x2c, 0x3c, 0x6f, 0xe8, 0x4a, 0x83, 0x4a, 0xb2, 0xe3, 0xaf, 0xb8, + 0x06, 0xd4, 0xd6, 0x18, 0x31, 0x14, 0x30, 0x0a, 0x5e, 0xdb, 0x1f, 0x42, 0x16, 0x65, 0xeb, 0x37, 0x38, 0xe6, 0x83, + 0xfb, 0x88, 0xe3, 0x1d, 0xce, 0x42, 0x4b, 0xc8, 0x93, 0x3b, 0x06, 0x69, 0x1a, 0x4b, 0x23, 0xe0, 0x44, 0x24, 0xdb, + 0x58, 0x0a, 0x47, 0x00, 0x01, 0x81, 0x6e, 0xca, 0x0c, 0x63, 0x3a, 0x18, 0x79, 0x1e, 0xf5, 0x8c, 0xf7, 0x2a, 0x3c, + 0x85, 0x34, 0xd9, 0xbe, 0x9e, 0xbf, 0x37, 0x82, 0xac, 0xdc, 0x72, 0x8e, 0x87, 0xc5, 0x37, 0xce, 0xbe, 0xca, 0xc9, + 0x53, 0xcc, 0x32, 0xd2, 0x3b, 0xc5, 0xbc, 0x80, 0x3f, 0x95, 0xa5, 0x3e, 0x47, 0xe9, 0x2d, 0xf3, 0xc9, 0x2a, 0x92, + 0x2e, 0xbd, 0x4d, 0xbf, 0x1f, 0x8f, 0xd4, 0xa1, 0xe6, 0xef, 0xe3, 0x91, 0x3c, 0xc3, 0x36, 0x2c, 0x61, 0xa1, 0x55, + 0x30, 0x06, 0x90, 0xc4, 0x46, 0x44, 0x83, 0xd1, 0xde, 0x1c, 0x0e, 0xe7, 0x1b, 0x73, 0x96, 0xec, 0xc1, 0xf5, 0x95, + 0x27, 0xe6, 0x1d, 0xf8, 0x32, 0x8f, 0x09, 0x22, 0x36, 0xf3, 0x36, 0xac, 0x06, 0x0f, 0x76, 0x70, 0x7d, 0xc4, 0x16, + 0xc5, 0x5a, 0xc7, 0x52, 0x59, 0x07, 0xa7, 0x75, 0x6c, 0x9a, 0x91, 0x52, 0x64, 0x9f, 0x63, 0x7f, 0xef, 0x06, 0x57, + 0xd7, 0xc6, 0xa0, 0xd6, 0xb8, 0xc3, 0xdc, 0x39, 0x15, 0x50, 0x8f, 0xe9, 0x0a, 0xaa, 0x67, 0x15, 0xf9, 0xf2, 0x5b, + 0x3b, 0x07, 0x04, 0x8d, 0x40, 0xe0, 0xa2, 0xf1, 0xbf, 0xeb, 0x52, 0xce, 0xbb, 0x80, 0x10, 0xdf, 0xa5, 0xa0, 0x4f, + 0x67, 0xb0, 0x89, 0xcd, 0x27, 0x10, 0x8b, 0xa6, 0xfb, 0x5c, 0x6b, 0xe6, 0x8b, 0x11, 0xed, 0xcc, 0xba, 0x5b, 0xe4, + 0x56, 0x0b, 0x91, 0x8c, 0x9e, 0x6d, 0x26, 0xdc, 0x76, 0x28, 0x67, 0x24, 0x60, 0x82, 0xd6, 0x56, 0x4a, 0x3e, 0xd7, + 0xbd, 0x4e, 0xd0, 0x1e, 0x48, 0x5a, 0xf7, 0x6f, 0x16, 0x9d, 0x51, 0x72, 0x72, 0xbd, 0xc9, 0x19, 0xa4, 0x60, 0xc1, + 0xf6, 0x32, 0x27, 0xdc, 0x00, 0x1f, 0xd9, 0x2c, 0x39, 0x4d, 0x83, 0x3c, 0x16, 0xba, 0x66, 0xef, 0xdb, 0xfc, 0xb2, + 0x80, 0x0e, 0x25, 0x8b, 0x46, 0x88, 0x07, 0xd8, 0x39, 0x24, 0x57, 0x05, 0xea, 0xa6, 0x81, 0xae, 0x5c, 0x39, 0x53, + 0x4c, 0x81, 0x0b, 0xa1, 0x20, 0x6a, 0x47, 0x27, 0x51, 0x39, 0xef, 0x93, 0xea, 0x32, 0x9f, 0x16, 0xd2, 0x34, 0x90, + 0x4f, 0x2b, 0xc7, 0x3c, 0x70, 0x67, 0x1b, 0xd7, 0x04, 0x06, 0x3a, 0xb5, 0xaf, 0x45, 0x39, 0xc7, 0x2a, 0xa2, 0xf7, + 0xf9, 0xfb, 0xca, 0x9e, 0x3e, 0x88, 0xb0, 0x51, 0x81, 0xc6, 0x52, 0x62, 0x6c, 0xe4, 0xf8, 0xb7, 0x44, 0xd9, 0x90, + 0x21, 0x20, 0x84, 0xb4, 0x91, 0xd3, 0x0f, 0x3b, 0x68, 0x25, 0xd3, 0xfe, 0x9f, 0x24, 0x7e, 0x1b, 0xec, 0xe5, 0xd4, + 0x9f, 0x7a, 0xc4, 0xe3, 0xb5, 0x46, 0x8f, 0x29, 0xe9, 0x36, 0xc8, 0x53, 0xe5, 0x29, 0x48, 0x26, 0x8c, 0x25, 0x04, + 0x8b, 0x72, 0xc1, 0x73, 0x5e, 0x71, 0x09, 0xf7, 0x51, 0xcb, 0x8a, 0x08, 0x55, 0x89, 0x9c, 0x3e, 0x5f, 0x01, 0xcf, + 0x04, 0x04, 0x3a, 0xc6, 0x48, 0xa3, 0x0a, 0xbe, 0x04, 0xc6, 0x42, 0x52, 0x76, 0x9a, 0x91, 0xe0, 0xb2, 0xfb, 0x11, + 0x89, 0x52, 0x5f, 0x90, 0x92, 0xf4, 0x8d, 0xa8, 0xf1, 0x4a, 0xac, 0x22, 0x12, 0xc8, 0x50, 0x43, 0xc4, 0xaa, 0x7a, + 0xea, 0x5e, 0x15, 0x93, 0xc1, 0xa0, 0xf2, 0xe5, 0xf4, 0xc4, 0x1b, 0x1a, 0x2a, 0xef, 0xba, 0xa2, 0x9d, 0x9e, 0x69, + 0xa5, 0xbc, 0x85, 0xb4, 0x04, 0x4d, 0xc3, 0x48, 0x73, 0x28, 0x75, 0x25, 0xdd, 0x8d, 0x41, 0x7c, 0xc9, 0x44, 0xcf, + 0x76, 0x6a, 0x47, 0x69, 0x4b, 0xda, 0x43, 0x48, 0xcf, 0x5d, 0xf2, 0x31, 0x0b, 0xb9, 0xba, 0x53, 0x4e, 0xca, 0xab, + 0x10, 0x9d, 0xdc, 0xf7, 0x18, 0x12, 0x81, 0x3e, 0xe7, 0x18, 0xd6, 0x45, 0x43, 0x9d, 0xc3, 0x0a, 0x31, 0x5b, 0x28, + 0x61, 0xbe, 0x64, 0x3c, 0x95, 0x0c, 0x1a, 0x00, 0x19, 0xf0, 0xd9, 0xcb, 0xc0, 0xf2, 0x57, 0x10, 0x3f, 0xda, 0xf8, + 0x70, 0xf8, 0x52, 0x53, 0x88, 0xed, 0x17, 0xd8, 0x0c, 0xe1, 0x51, 0x3d, 0xe0, 0x99, 0x6f, 0xe2, 0x04, 0x2d, 0x47, + 0x9c, 0xcc, 0x8e, 0x26, 0xb2, 0x57, 0x3d, 0x84, 0x53, 0x59, 0x81, 0x3a, 0xca, 0x3a, 0x2b, 0xe1, 0x47, 0x98, 0xea, + 0x56, 0x62, 0x2d, 0xd0, 0xe6, 0x6a, 0xc5, 0x5a, 0x00, 0x07, 0x7e, 0x0e, 0xc1, 0x13, 0xf9, 0x1c, 0x5c, 0x0c, 0x0a, + 0xf0, 0x39, 0x00, 0x5e, 0xe4, 0x8e, 0xce, 0xfd, 0xe9, 0x81, 0x65, 0x35, 0xc2, 0x70, 0x54, 0x11, 0xeb, 0xd7, 0x6c, + 0x47, 0x3e, 0x70, 0x3b, 0xc6, 0xe7, 0xda, 0x63, 0xc9, 0x72, 0xc2, 0xcc, 0xdc, 0xab, 0x25, 0x7a, 0xde, 0xa4, 0x71, + 0x33, 0x7a, 0xb4, 0xaf, 0xe5, 0xff, 0x82, 0x5e, 0x06, 0xfd, 0x2d, 0xdc, 0xf2, 0x9a, 0x3f, 0x2c, 0xaf, 0x01, 0xd3, + 0x2b, 0x88, 0x94, 0x51, 0x23, 0x32, 0x86, 0xb0, 0x49, 0x75, 0x73, 0x9b, 0x54, 0x17, 0x02, 0x9e, 0x8e, 0x48, 0x75, + 0x2d, 0xa4, 0x8d, 0x7c, 0x5a, 0x07, 0x32, 0x16, 0xe9, 0xed, 0x4f, 0x7f, 0x7b, 0xf6, 0xe9, 0xd5, 0xaf, 0x3f, 0x2d, + 0x5e, 0xbd, 0x7d, 0xf9, 0xea, 0xed, 0xab, 0x4f, 0xbf, 0x13, 0x84, 0xc7, 0x54, 0xa8, 0x0c, 0xef, 0xdf, 0x7d, 0x7c, + 0xe5, 0x64, 0xb0, 0x61, 0xc6, 0xb2, 0xf6, 0x8d, 0x1c, 0x0c, 0x81, 0xc8, 0x06, 0x21, 0x83, 0xec, 0x94, 0xcc, 0x31, + 0x13, 0x73, 0x8c, 0xbd, 0x13, 0x98, 0x6c, 0x81, 0xef, 0x58, 0xe6, 0x25, 0x23, 0x72, 0x55, 0x68, 0xfd, 0x80, 0x16, + 0xbc, 0x01, 0x17, 0x99, 0x34, 0xbf, 0xfd, 0x95, 0x20, 0xf6, 0x69, 0x25, 0xe5, 0xbe, 0xda, 0xd6, 0x3c, 0xdf, 0xde, + 0xef, 0x25, 0x9c, 0xff, 0x5c, 0x1a, 0x51, 0x0b, 0x70, 0x00, 0x3e, 0x87, 0x3f, 0xae, 0xb4, 0x25, 0x4d, 0x66, 0xd1, + 0x7e, 0xc6, 0x10, 0x74, 0x69, 0xf0, 0x41, 0xec, 0x91, 0x97, 0xfa, 0x64, 0x21, 0x81, 0x3b, 0x62, 0xf8, 0xb4, 0x22, + 0xe8, 0x15, 0x23, 0x8a, 0x4b, 0xae, 0x50, 0x29, 0x25, 0xff, 0x46, 0xd9, 0x45, 0x85, 0x9c, 0x15, 0xec, 0x4e, 0x91, + 0x23, 0xe3, 0x07, 0xc1, 0xc4, 0x97, 0x83, 0xfb, 0x2f, 0xf1, 0x0e, 0x67, 0x8a, 0x23, 0x39, 0xe1, 0x1f, 0x33, 0x0c, + 0xec, 0xcf, 0xc1, 0xe7, 0xd5, 0x61, 0x5e, 0xde, 0xe8, 0x53, 0x6e, 0xc9, 0xc7, 0x93, 0xe5, 0x15, 0x18, 0xec, 0x97, + 0xaa, 0xb9, 0x6b, 0x5e, 0xcf, 0x96, 0x73, 0xb6, 0x9f, 0x45, 0xf3, 0xe0, 0x96, 0xcd, 0xb2, 0x79, 0xb0, 0x6a, 0xf8, + 0x9a, 0xdd, 0xf0, 0xb5, 0x55, 0xb5, 0xb5, 0x5d, 0xb5, 0xc9, 0x86, 0xdf, 0x80, 0x84, 0x70, 0x0d, 0x7e, 0xc9, 0x09, + 0xbb, 0xf5, 0xd9, 0x06, 0x24, 0xda, 0x15, 0xdb, 0xc0, 0x45, 0x6c, 0xcd, 0x5f, 0x55, 0xde, 0x86, 0x95, 0xec, 0x7c, + 0xcc, 0x72, 0x9c, 0x7f, 0x3e, 0x3c, 0xa0, 0xbd, 0x50, 0x3f, 0xbb, 0x54, 0xcf, 0x26, 0xca, 0x6e, 0xb6, 0x19, 0x2d, + 0xee, 0xd2, 0x6a, 0x13, 0x66, 0xe8, 0x59, 0x0e, 0x1f, 0x6d, 0xa5, 0xe0, 0xa7, 0x17, 0xf8, 0x25, 0x6b, 0xe2, 0xfc, + 0x9e, 0xb6, 0xed, 0xaa, 0xc4, 0x56, 0xd0, 0xa2, 0xc8, 0x6a, 0x85, 0x07, 0xe6, 0xfc, 0x29, 0x2c, 0x60, 0xec, 0x39, + 0xce, 0x79, 0xed, 0x8f, 0x90, 0xf1, 0xde, 0x01, 0x40, 0xcb, 0x1c, 0x07, 0x78, 0xc4, 0x8a, 0x51, 0x34, 0x78, 0xe7, + 0x97, 0xca, 0x6a, 0xa5, 0x39, 0x09, 0x6d, 0x23, 0x56, 0x2d, 0x47, 0xaa, 0x66, 0x44, 0xfa, 0x20, 0x3d, 0xef, 0x7b, + 0x44, 0x35, 0xd8, 0x93, 0x79, 0x1d, 0xd8, 0xa7, 0x77, 0xad, 0x55, 0xdd, 0xf9, 0x3d, 0x55, 0xba, 0xe4, 0xc8, 0x96, + 0x9f, 0x2e, 0xc3, 0x7b, 0xf5, 0xa7, 0xe4, 0xfa, 0x50, 0xe0, 0x08, 0x0f, 0x55, 0xc0, 0xf9, 0x7a, 0x25, 0xda, 0x9d, + 0x08, 0xbb, 0x72, 0x09, 0x08, 0xf1, 0x25, 0x4d, 0x73, 0x3c, 0x8e, 0x68, 0x22, 0xc2, 0x26, 0x46, 0x7f, 0x61, 0xf7, + 0xa1, 0xc4, 0x72, 0x9e, 0x6b, 0x50, 0x72, 0xc9, 0xe0, 0x3d, 0x69, 0xaf, 0x41, 0xb3, 0xbc, 0x2a, 0x35, 0x99, 0xc8, + 0x41, 0xf9, 0x70, 0x28, 0x60, 0x2f, 0x35, 0x7e, 0x9a, 0xf0, 0x13, 0x96, 0xb7, 0xf6, 0xd6, 0x94, 0xa2, 0x92, 0x06, + 0xa8, 0xc0, 0xc7, 0x0c, 0xfe, 0x77, 0x67, 0x88, 0x05, 0x53, 0x74, 0xfc, 0x70, 0x26, 0xe6, 0xd6, 0x73, 0xab, 0xac, + 0xa3, 0x6c, 0x8d, 0x76, 0x02, 0x4e, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, + 0xfb, 0x54, 0xe9, 0x60, 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x5b, 0x41, 0x04, 0x29, 0xb2, 0x11, + 0x25, 0x69, 0x1c, 0x8b, 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xb8, 0xf4, 0x04, + 0x22, 0xc2, 0xd1, 0xe1, 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xbe, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, + 0x05, 0x18, 0xc6, 0x7a, 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5b, 0x5b, 0x64, 0x30, + 0xd6, 0x96, 0x44, 0x02, 0xf8, 0x2d, 0x09, 0x19, 0xda, 0x36, 0x02, 0x33, 0x86, 0xb7, 0xb3, 0xe2, 0xd2, 0x75, 0xd8, + 0xe6, 0x1c, 0xbe, 0x90, 0x85, 0x66, 0x1d, 0x51, 0x9a, 0x20, 0xe4, 0x1f, 0x70, 0xb2, 0x50, 0x18, 0xcd, 0x8b, 0xa3, + 0x74, 0x92, 0x58, 0xdf, 0x75, 0x95, 0x0a, 0x36, 0x9b, 0x8f, 0xa8, 0x2f, 0x3b, 0x4a, 0xbe, 0x06, 0x27, 0x1d, 0x27, + 0x59, 0xe4, 0x20, 0x6a, 0x51, 0x39, 0x1f, 0x93, 0xb0, 0xb4, 0xab, 0x53, 0x6d, 0xd6, 0xeb, 0xa2, 0xac, 0xab, 0x17, + 0x22, 0x52, 0xf4, 0x3e, 0xea, 0xd1, 0x23, 0x09, 0xa9, 0xd0, 0xaa, 0xd4, 0x2e, 0x8f, 0xc0, 0x6d, 0x53, 0x2b, 0xb6, + 0xe5, 0x12, 0x96, 0xa8, 0xf1, 0x9f, 0xa0, 0x8f, 0x72, 0x71, 0x2f, 0x03, 0x34, 0x3a, 0x9e, 0x9a, 0xb7, 0x1e, 0x78, + 0xe5, 0x28, 0xbf, 0xb4, 0xda, 0xa4, 0x5f, 0x01, 0x99, 0xd1, 0xfe, 0xd1, 0x52, 0x02, 0x99, 0x81, 0x99, 0xb4, 0x34, + 0x24, 0x72, 0x14, 0xb3, 0x34, 0xff, 0x13, 0x57, 0x6c, 0x85, 0x48, 0xc3, 0x6a, 0xee, 0xf1, 0x9f, 0x2a, 0xaf, 0x96, + 0x6b, 0x99, 0x69, 0x6e, 0x96, 0x38, 0x56, 0x2c, 0x2e, 0xea, 0x75, 0x25, 0xb2, 0x40, 0x88, 0x23, 0x4c, 0x63, 0x3d, + 0xf5, 0x46, 0x69, 0xf5, 0x1e, 0x09, 0x65, 0x7e, 0xc2, 0xde, 0x8e, 0xbd, 0x1e, 0x64, 0x21, 0x8e, 0x2d, 0x07, 0x9b, + 0xad, 0xf7, 0xa9, 0x4c, 0x45, 0x7c, 0x56, 0x17, 0x67, 0x9b, 0x4a, 0x9c, 0xd5, 0x89, 0x38, 0xfb, 0x11, 0x72, 0xfe, + 0x78, 0x46, 0x45, 0x9f, 0xdd, 0xa7, 0x75, 0x52, 0x6c, 0x6a, 0x7a, 0xf2, 0x12, 0xcb, 0xf8, 0xf1, 0x8c, 0xb8, 0x6a, + 0xce, 0x68, 0x24, 0xe3, 0xd1, 0xd9, 0xfb, 0x0c, 0x48, 0x5e, 0xcf, 0xd2, 0x15, 0x0c, 0xde, 0x59, 0x98, 0xc7, 0x67, + 0xa5, 0xb8, 0x05, 0x8b, 0x53, 0xd9, 0xf9, 0x1e, 0x64, 0x58, 0x85, 0x7f, 0x8a, 0x33, 0x80, 0x76, 0x3d, 0x4b, 0xeb, + 0xb3, 0xb4, 0x3a, 0xcb, 0x8b, 0xfa, 0x4c, 0x49, 0xe1, 0x10, 0xc6, 0x0f, 0xef, 0xe9, 0x2b, 0xbb, 0xbc, 0xcd, 0xe2, + 0x2e, 0x8b, 0xfc, 0x29, 0x7a, 0x15, 0x11, 0x93, 0x46, 0x25, 0xbc, 0x76, 0x7f, 0xdb, 0xdc, 0x3f, 0xbc, 0x6e, 0xec, + 0x7e, 0x76, 0xc7, 0x88, 0x2e, 0xa8, 0xc7, 0x2b, 0x49, 0xa9, 0xa0, 0x80, 0xc0, 0x89, 0x66, 0x8d, 0x07, 0x77, 0x1c, + 0xf0, 0x6a, 0x60, 0x4b, 0xb6, 0xf6, 0xf9, 0xd3, 0x58, 0x86, 0x69, 0x6f, 0x02, 0xfc, 0xab, 0xec, 0x4d, 0xd7, 0xc1, + 0x12, 0xef, 0x5b, 0xc8, 0x36, 0xf4, 0xea, 0x05, 0x7f, 0xe6, 0xe5, 0xea, 0x6f, 0xf6, 0x3b, 0x00, 0x61, 0x40, 0xcc, + 0xaa, 0x8f, 0x26, 0xee, 0x9d, 0x95, 0x65, 0xe7, 0x64, 0xd9, 0xf5, 0xd0, 0xaf, 0x49, 0x8c, 0x4a, 0x2b, 0x4b, 0xe9, + 0x64, 0x29, 0x21, 0x0b, 0xf8, 0xc4, 0x68, 0x6a, 0x23, 0x80, 0xb0, 0x1d, 0xa5, 0xf2, 0x85, 0xca, 0x8b, 0x28, 0x9c, + 0x13, 0x3c, 0x4f, 0xc4, 0xe8, 0xce, 0x4a, 0x06, 0x0c, 0x87, 0x10, 0xcc, 0x41, 0x5b, 0xec, 0x0d, 0xdd, 0x44, 0xfc, + 0xf5, 0xb2, 0x28, 0x5f, 0xc5, 0xe4, 0x53, 0xb0, 0x3b, 0xf9, 0xb8, 0x84, 0xc7, 0xe5, 0xc9, 0xc7, 0x21, 0x7a, 0x24, + 0x9c, 0x7c, 0x0c, 0xbe, 0x47, 0x72, 0x5e, 0x77, 0x3d, 0x4e, 0x90, 0x5b, 0x48, 0xf7, 0xb7, 0x63, 0x12, 0xa0, 0x79, + 0x0d, 0xcb, 0x51, 0x53, 0x71, 0xcd, 0xcc, 0x18, 0xcf, 0x1b, 0xbd, 0x3f, 0x76, 0xbc, 0x65, 0x0a, 0xc5, 0x2c, 0xe6, + 0x35, 0xfc, 0x9e, 0x55, 0x81, 0xba, 0xeb, 0x6d, 0x92, 0x5b, 0x66, 0xf5, 0x1c, 0xed, 0xbe, 0xef, 0xea, 0x44, 0x50, + 0xfb, 0x3b, 0xec, 0x79, 0x66, 0xbd, 0xab, 0x62, 0xe0, 0x52, 0x25, 0x3b, 0x64, 0xaa, 0x9a, 0x1e, 0xa8, 0x94, 0x06, + 0x4f, 0x2f, 0xad, 0xcb, 0x97, 0x4a, 0x1b, 0x79, 0xa6, 0xf9, 0x0d, 0xe0, 0xc5, 0xd4, 0x65, 0xb1, 0xfb, 0xe6, 0xbe, + 0x82, 0xdb, 0x78, 0xbf, 0xbf, 0xae, 0x3c, 0xf3, 0x13, 0x17, 0x80, 0xbd, 0xa9, 0xd0, 0x3a, 0x81, 0x52, 0xc3, 0x3a, + 0xbc, 0x4e, 0x44, 0xf4, 0x67, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, + 0x8d, 0x3d, 0x20, 0xac, 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0xa3, 0x8f, 0x92, 0x3f, 0x41, 0xb3, 0xa2, 0xb9, 0x63, + 0xf2, 0x73, 0x7d, 0xa5, 0xf4, 0xf7, 0xeb, 0xca, 0x23, 0x73, 0x4a, 0xdb, 0x4c, 0x63, 0xb5, 0xa6, 0x12, 0x08, 0xaf, + 0xa8, 0x64, 0x15, 0x3e, 0x9b, 0x37, 0xa2, 0xdf, 0x97, 0x47, 0x78, 0x5a, 0xfd, 0xb4, 0xc5, 0xf8, 0x56, 0x40, 0x34, + 0x12, 0x7e, 0xbf, 0x5f, 0x01, 0xcc, 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, + 0xd3, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x36, + 0x69, 0x16, 0xbf, 0x2b, 0x7f, 0xc1, 0xb1, 0xd5, 0x75, 0x78, 0x60, 0xea, 0x74, 0xed, 0x3c, 0xd2, 0xda, 0x0b, 0x01, + 0x11, 0xed, 0x1a, 0x6a, 0xbd, 0xb0, 0xd0, 0x23, 0x3d, 0x11, 0xce, 0x49, 0xa2, 0xa6, 0x1d, 0x68, 0x69, 0x84, 0xbe, + 0xbe, 0xe6, 0xf4, 0x17, 0x06, 0x6b, 0x9f, 0x8f, 0x19, 0x90, 0x95, 0xe8, 0xc7, 0xea, 0xa1, 0xb1, 0x99, 0x43, 0xcf, + 0x5a, 0x95, 0x67, 0x5e, 0x75, 0x38, 0x20, 0x3e, 0x8c, 0xfe, 0x92, 0xdf, 0xef, 0xbf, 0xa0, 0xf9, 0xc7, 0x84, 0x1a, + 0x3f, 0xdb, 0x0c, 0xd0, 0xb5, 0xef, 0xca, 0x03, 0x51, 0xcf, 0xb5, 0x4a, 0x10, 0xe2, 0x0d, 0x62, 0xa2, 0x19, 0x31, + 0x07, 0xa7, 0x1d, 0x6a, 0xfe, 0x49, 0x6a, 0x40, 0x88, 0x12, 0xaf, 0x63, 0xca, 0x82, 0x9c, 0x36, 0x71, 0xa4, 0x1f, + 0x85, 0x13, 0xf9, 0x41, 0x54, 0x45, 0x76, 0x07, 0x17, 0x0c, 0xa6, 0xde, 0xd3, 0x7e, 0x89, 0x7e, 0x4b, 0x38, 0x72, + 0x8e, 0x56, 0x85, 0x20, 0x72, 0x42, 0x58, 0x6b, 0x08, 0x13, 0xc4, 0x06, 0xf1, 0xb2, 0xef, 0x92, 0x0c, 0x47, 0x0a, + 0x2e, 0xeb, 0xd8, 0x31, 0xe6, 0xea, 0xa8, 0x7a, 0x0d, 0x60, 0xbc, 0x72, 0x04, 0xcd, 0x46, 0x91, 0x5d, 0x42, 0x54, + 0x91, 0xe3, 0x09, 0xa8, 0x1d, 0x94, 0xc6, 0x66, 0x7a, 0x3e, 0x0e, 0xf2, 0xd1, 0xa2, 0x42, 0x9d, 0x13, 0xcb, 0x78, + 0x0d, 0xc0, 0xda, 0xb9, 0xea, 0xe7, 0x59, 0x0d, 0x9e, 0x34, 0xc4, 0xe7, 0x63, 0xb4, 0xbd, 0xb2, 0x39, 0xa8, 0xb6, + 0xd3, 0x59, 0x79, 0xc5, 0x74, 0x39, 0x30, 0xee, 0x1b, 0x5e, 0x51, 0x9c, 0xe1, 0x07, 0x0f, 0xb6, 0x38, 0x7f, 0xba, + 0xa1, 0xf6, 0x63, 0x6e, 0xd4, 0xc3, 0x40, 0x6b, 0xc1, 0x9b, 0x82, 0x58, 0x7f, 0xdf, 0x75, 0x64, 0x7b, 0xa7, 0x45, + 0x46, 0x93, 0xcf, 0x7e, 0xfe, 0xbe, 0x4c, 0x57, 0x29, 0xdc, 0x97, 0x9c, 0x2c, 0x9a, 0x79, 0x08, 0xec, 0x0d, 0x31, + 0x5c, 0x1f, 0x15, 0x1e, 0x51, 0xd6, 0xef, 0xc3, 0xef, 0xab, 0x0c, 0x4c, 0x31, 0x70, 0x5d, 0x21, 0x18, 0x0f, 0x81, + 0x20, 0x1e, 0xa6, 0xd1, 0xc9, 0xa0, 0x06, 0x6d, 0xf8, 0x06, 0x20, 0x33, 0xc0, 0x23, 0x73, 0xe9, 0x11, 0x70, 0x17, + 0xb8, 0xf6, 0x64, 0x3c, 0xf6, 0x27, 0xa6, 0xa1, 0x51, 0x53, 0x9a, 0xe9, 0xb9, 0xf1, 0x9b, 0x8e, 0x6a, 0xb9, 0x76, + 0xfe, 0xe3, 0x4b, 0x7e, 0x83, 0x5e, 0xd0, 0xf2, 0x72, 0x1f, 0xa9, 0xcb, 0x7d, 0x46, 0x71, 0x99, 0x48, 0x0e, 0x0b, + 0x62, 0x59, 0xc2, 0x81, 0xc7, 0xa8, 0x64, 0xb1, 0xa5, 0xc7, 0xaa, 0x68, 0xf9, 0xa2, 0xdc, 0x20, 0x1d, 0x3a, 0x21, + 0x58, 0xa2, 0x82, 0x60, 0x09, 0x8c, 0x8b, 0x58, 0xf3, 0xcd, 0x20, 0x67, 0xf1, 0x6c, 0x33, 0xe7, 0x48, 0x58, 0x97, + 0x1c, 0x0e, 0x85, 0x04, 0x9b, 0xc9, 0x66, 0xeb, 0x39, 0x5b, 0xfb, 0x0c, 0x94, 0x00, 0xa5, 0x4c, 0x13, 0x94, 0xa6, + 0x15, 0x5b, 0x71, 0xd3, 0x1a, 0xac, 0x56, 0x53, 0xb6, 0xaa, 0x29, 0x3b, 0xa7, 0x29, 0x47, 0x15, 0x94, 0x9c, 0x50, + 0x8a, 0x32, 0x0c, 0x60, 0xc4, 0x26, 0xd1, 0x55, 0x86, 0x3e, 0xde, 0x09, 0x8f, 0xa0, 0x8a, 0x88, 0x7c, 0xc2, 0x10, + 0x02, 0x13, 0x51, 0x5c, 0xa8, 0x42, 0x31, 0x40, 0x46, 0x24, 0x10, 0x4c, 0x54, 0xea, 0x14, 0x98, 0x8f, 0xa6, 0x8a, + 0x61, 0xd3, 0x9e, 0x28, 0xdf, 0x53, 0xc7, 0x3d, 0xca, 0x36, 0xff, 0x10, 0xbb, 0x20, 0x44, 0xee, 0xc6, 0x9d, 0xfa, + 0x19, 0xf1, 0xde, 0xee, 0x08, 0xe3, 0x27, 0x3b, 0x6e, 0x11, 0xae, 0x08, 0xb6, 0x54, 0x73, 0x88, 0xc5, 0xbc, 0x9a, + 0x24, 0xa8, 0x65, 0x49, 0xfc, 0x0d, 0x4f, 0x06, 0x39, 0x5b, 0x82, 0x07, 0xed, 0x9c, 0x65, 0x80, 0xbf, 0x62, 0xb5, + 0xe8, 0xf7, 0xda, 0x5b, 0x82, 0xfc, 0xb4, 0xb1, 0x1b, 0x85, 0x89, 0x11, 0x24, 0xea, 0x76, 0x65, 0x20, 0x3f, 0xbc, + 0xc7, 0xe9, 0x78, 0xec, 0x29, 0x63, 0x6e, 0x65, 0x7a, 0x99, 0xce, 0x95, 0x7c, 0x23, 0xf7, 0xd2, 0x87, 0x5e, 0x82, + 0x9d, 0x03, 0xde, 0x40, 0xda, 0xc0, 0x8f, 0xb0, 0x5d, 0x78, 0x6d, 0x90, 0x30, 0x23, 0xc0, 0x16, 0xc7, 0xc7, 0x48, + 0x09, 0x0c, 0xe1, 0x38, 0x4b, 0x01, 0x98, 0x46, 0x5f, 0x66, 0x2b, 0xfb, 0x32, 0xab, 0x35, 0x5b, 0x2a, 0xa7, 0x7b, + 0xe7, 0xd6, 0xed, 0x7c, 0x26, 0x01, 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0x87, 0x30, + 0xbf, 0x15, 0x2f, 0xcb, 0x62, 0xa5, 0xba, 0xa2, 0xed, 0x33, 0x93, 0xcf, 0x48, 0x27, 0xa1, 0x02, 0x0a, 0x0a, 0xb9, + 0xd6, 0xa7, 0x6f, 0xc3, 0xb7, 0x41, 0xa1, 0x81, 0xd9, 0x2a, 0xdc, 0xd3, 0x64, 0x8d, 0xd4, 0x1b, 0x55, 0xbf, 0x4f, + 0xae, 0x81, 0x54, 0x67, 0x0e, 0x2d, 0x7b, 0x56, 0x61, 0x80, 0xd8, 0x51, 0x9f, 0x91, 0x50, 0x07, 0x52, 0x0f, 0x18, + 0x42, 0xb4, 0x4d, 0x1f, 0x7f, 0x32, 0x24, 0xba, 0x00, 0x5b, 0x88, 0x36, 0xf0, 0xe3, 0x4f, 0xb0, 0xcf, 0x82, 0xf0, + 0x98, 0xe6, 0x6f, 0x20, 0xe9, 0xd8, 0xc0, 0x69, 0xf5, 0x29, 0xf8, 0x20, 0xc9, 0xc1, 0x44, 0x1d, 0xbc, 0xdc, 0x5f, + 0xfa, 0x7d, 0xd8, 0xb2, 0x73, 0x29, 0xd5, 0xb1, 0x52, 0x6f, 0xdb, 0xda, 0x0f, 0xa2, 0x2d, 0x38, 0xb2, 0x88, 0xbf, + 0xcf, 0x10, 0x11, 0xcc, 0x0c, 0x22, 0xec, 0x5a, 0xa8, 0xbb, 0x3d, 0xa5, 0x96, 0x45, 0xbd, 0xed, 0x29, 0xa5, 0x6e, + 0xc3, 0xf0, 0xdd, 0x04, 0x33, 0xc5, 0x0d, 0x7f, 0x93, 0x79, 0xa1, 0xde, 0x78, 0x8c, 0x63, 0xfc, 0xda, 0xf3, 0xf7, + 0x4b, 0x5e, 0xcd, 0x36, 0xca, 0x84, 0x79, 0xcb, 0x97, 0xb3, 0x50, 0x76, 0xb5, 0x34, 0xee, 0x7c, 0xf6, 0x96, 0x6a, + 0x3e, 0xf8, 0x87, 0x43, 0x02, 0xf1, 0x46, 0xf1, 0xd5, 0x6d, 0x23, 0xb7, 0xae, 0xc9, 0xe6, 0xaa, 0x04, 0xd4, 0xef, + 0xf3, 0x35, 0xee, 0xb7, 0x58, 0xff, 0xee, 0x69, 0x90, 0xb1, 0x9a, 0xe1, 0x8a, 0x29, 0x7c, 0x0a, 0x00, 0x83, 0xc3, + 0xa9, 0x20, 0x2d, 0xf0, 0x86, 0x97, 0xc3, 0xcb, 0xc9, 0x86, 0x4c, 0xba, 0x1b, 0x1f, 0xb9, 0xb3, 0x40, 0xd5, 0xfb, + 0x1d, 0xc5, 0x49, 0x83, 0x44, 0x63, 0xaf, 0xc1, 0x67, 0x59, 0x46, 0xb9, 0x68, 0xe2, 0x3e, 0x24, 0x5f, 0xe9, 0x01, + 0xcc, 0x55, 0x28, 0x01, 0xa2, 0xdf, 0x58, 0x16, 0x1b, 0xd1, 0xb6, 0xd8, 0xc0, 0x52, 0xaa, 0xe6, 0x7a, 0x35, 0x7d, + 0xf6, 0x4a, 0x34, 0xef, 0xa3, 0x19, 0xa7, 0x34, 0x1a, 0x70, 0x9c, 0x46, 0xe1, 0xf6, 0xdd, 0x9d, 0x28, 0x97, 0x19, + 0x58, 0xb2, 0x55, 0x38, 0xc5, 0x65, 0xa3, 0xce, 0x88, 0x67, 0x79, 0xac, 0x00, 0x3a, 0x1e, 0x12, 0x00, 0xd5, 0x05, + 0x01, 0x15, 0xd1, 0x52, 0x7a, 0x2b, 0xb4, 0x58, 0xa8, 0x37, 0x1c, 0xa5, 0xf0, 0x47, 0xfa, 0xf3, 0x20, 0x9f, 0x02, + 0x10, 0xbb, 0x3e, 0x8e, 0x5e, 0x16, 0x25, 0x7d, 0xaa, 0x98, 0xe5, 0x72, 0x30, 0x81, 0x5d, 0x9d, 0xc8, 0x50, 0x2b, + 0xc8, 0x5b, 0x75, 0xe5, 0xad, 0x4c, 0xde, 0xc6, 0x38, 0x25, 0x3f, 0x70, 0xd3, 0xb1, 0x46, 0x0c, 0xbc, 0xf2, 0xb4, + 0x4e, 0x13, 0xa4, 0xc9, 0x05, 0x30, 0x0c, 0xf1, 0xfb, 0xcc, 0x7b, 0xe6, 0x39, 0x52, 0x15, 0x24, 0xb3, 0xbb, 0xcc, + 0x53, 0x17, 0x51, 0x7d, 0xe5, 0xd4, 0xd2, 0x99, 0xd3, 0x8f, 0x00, 0xde, 0x63, 0x6a, 0xd2, 0x90, 0x8f, 0x70, 0x5b, + 0x8a, 0xaf, 0xb7, 0xea, 0x1a, 0x2f, 0x8d, 0xce, 0xdd, 0xcb, 0x97, 0xee, 0x34, 0xe8, 0xa7, 0x20, 0x28, 0xe7, 0xb3, + 0x52, 0xc0, 0x9e, 0x32, 0x9b, 0xeb, 0xd5, 0xaa, 0x15, 0x5a, 0x87, 0xc3, 0x58, 0x3b, 0x0a, 0x69, 0x75, 0x16, 0xb0, + 0xd5, 0x48, 0xa7, 0x04, 0x08, 0xc1, 0x71, 0x1a, 0x76, 0x82, 0x71, 0x97, 0x4e, 0x23, 0xb2, 0x5e, 0x29, 0x49, 0x17, + 0x66, 0x90, 0xfc, 0x93, 0xbc, 0x9e, 0x01, 0x2d, 0x01, 0x1c, 0x8a, 0x58, 0xc2, 0xc3, 0x49, 0x72, 0x05, 0xd0, 0xe9, + 0x70, 0x50, 0x69, 0x68, 0xce, 0x6a, 0x96, 0xcc, 0x27, 0xb1, 0x54, 0x55, 0x1e, 0x0e, 0x9e, 0x72, 0x33, 0xe8, 0xf7, + 0xb3, 0x69, 0xa9, 0x5c, 0x00, 0x82, 0x58, 0x17, 0x06, 0x88, 0x47, 0x5a, 0x78, 0xb2, 0xe8, 0x53, 0x12, 0xbf, 0x9c, + 0x25, 0x73, 0x93, 0x0d, 0xef, 0xc0, 0x08, 0x36, 0xe3, 0xba, 0xa4, 0x4c, 0x7b, 0x54, 0x7e, 0xcf, 0xe8, 0xa9, 0xed, + 0x6b, 0xad, 0xb6, 0x88, 0x75, 0x1d, 0x5c, 0x95, 0xa8, 0xa7, 0xf8, 0xa0, 0x24, 0xc1, 0xfb, 0x85, 0x73, 0x33, 0x52, + 0xbe, 0x16, 0xb9, 0x1f, 0xb4, 0x33, 0xb5, 0x72, 0xe0, 0x08, 0xe4, 0x58, 0x45, 0x25, 0xaf, 0x77, 0x1d, 0x82, 0x47, + 0x77, 0xa5, 0x02, 0xe5, 0xe0, 0xa7, 0x20, 0x46, 0xd7, 0x57, 0x9d, 0x35, 0xd4, 0x4c, 0xa3, 0xca, 0x23, 0xe8, 0xd4, + 0x01, 0x3c, 0x29, 0x78, 0xa9, 0xd5, 0x8f, 0x87, 0x83, 0x67, 0x7e, 0xf0, 0x77, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, + 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x9e, 0x57, 0xaa, 0x7c, 0x75, 0xaa, + 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x47, 0xb2, 0x02, + 0x1d, 0xc1, 0x56, 0x96, 0x92, 0x03, 0x3e, 0xa9, 0xee, 0xaa, 0x55, 0xeb, 0x73, 0xca, 0x36, 0xc2, 0x4d, 0x7e, 0x1d, + 0x3b, 0x38, 0x52, 0x7e, 0x83, 0xe7, 0x02, 0xd8, 0x6b, 0xc0, 0xde, 0x9c, 0xb3, 0xa2, 0x79, 0x70, 0x48, 0xdb, 0x02, + 0x8d, 0xcc, 0xdc, 0xce, 0xd5, 0x7d, 0x5b, 0x1e, 0xa5, 0x31, 0x44, 0xa6, 0x3d, 0x30, 0x1d, 0x6c, 0x46, 0xf9, 0xef, + 0x29, 0xbf, 0x55, 0x38, 0x06, 0xbe, 0x9d, 0x7a, 0x07, 0x50, 0xf5, 0xb4, 0x41, 0xc6, 0x9a, 0x61, 0x68, 0x65, 0x97, + 0x4b, 0xa1, 0x25, 0x68, 0xa9, 0x9b, 0x20, 0x38, 0x3f, 0x22, 0xca, 0x11, 0x80, 0x2e, 0x52, 0xc0, 0x04, 0x3f, 0xa5, + 0xed, 0xee, 0xf7, 0xd7, 0xa9, 0x47, 0xee, 0x5d, 0xa1, 0x46, 0x09, 0x25, 0x18, 0xfb, 0x89, 0xc6, 0x0c, 0x3a, 0xba, + 0x22, 0x27, 0x3c, 0x6b, 0x75, 0x58, 0xd7, 0x4d, 0x19, 0x94, 0xc5, 0x31, 0xaf, 0xa6, 0xb3, 0x3f, 0x1e, 0xed, 0xeb, + 0x06, 0x59, 0xc8, 0xff, 0x60, 0x3d, 0x24, 0x83, 0xee, 0x41, 0x28, 0x44, 0x6f, 0x1e, 0xcc, 0xf0, 0x3f, 0xb6, 0xe1, + 0xd9, 0x77, 0xdc, 0xa8, 0x13, 0xc4, 0x1c, 0x71, 0xbc, 0xf4, 0x14, 0x6d, 0x3d, 0xdc, 0x02, 0xd9, 0x1a, 0x2f, 0x6f, + 0xed, 0x35, 0x90, 0x53, 0x1c, 0xff, 0x2d, 0xcf, 0xd4, 0xca, 0x06, 0x3f, 0x3d, 0x65, 0x3b, 0xf0, 0xf0, 0x22, 0x04, + 0x14, 0xc3, 0xb2, 0xf1, 0xb7, 0x96, 0xe3, 0x8c, 0xfe, 0x9b, 0x47, 0x0c, 0x83, 0x45, 0xe4, 0xc7, 0x97, 0xa5, 0x10, + 0x5f, 0x85, 0xf7, 0xa9, 0xf2, 0x6e, 0xc9, 0x29, 0xf3, 0x56, 0x0f, 0xa3, 0xeb, 0x92, 0xf4, 0x5d, 0xf2, 0xb1, 0x35, + 0x6c, 0x7f, 0x68, 0xf7, 0x9b, 0x21, 0x82, 0x10, 0xca, 0xf1, 0x73, 0x46, 0x27, 0x34, 0x3e, 0xac, 0x66, 0xa7, 0xd7, + 0xef, 0x9d, 0xe3, 0x05, 0x5b, 0xa3, 0x01, 0x1e, 0x0f, 0x5d, 0xcc, 0x13, 0x35, 0x74, 0xba, 0xae, 0x9d, 0x83, 0x07, + 0x06, 0x59, 0x9e, 0x7c, 0xc7, 0xb0, 0xc4, 0xfe, 0x24, 0xe2, 0x49, 0x5b, 0xb5, 0xb1, 0x39, 0x52, 0x6d, 0xd4, 0x0c, + 0xfc, 0xe0, 0x15, 0x14, 0x18, 0x5d, 0x90, 0x16, 0x60, 0x1c, 0x8e, 0x00, 0x64, 0xc5, 0x38, 0x1e, 0x19, 0x4c, 0x60, + 0x48, 0x37, 0x14, 0x05, 0xe0, 0xe1, 0x71, 0x3c, 0x08, 0x19, 0x40, 0xba, 0xe0, 0xa1, 0x61, 0x9b, 0x84, 0x94, 0x9f, + 0xe7, 0x79, 0xad, 0x86, 0xd0, 0x77, 0x16, 0xaa, 0x63, 0x3f, 0xd2, 0x5e, 0xb1, 0xae, 0x55, 0xe9, 0xc8, 0x56, 0x07, + 0xe8, 0x1b, 0x32, 0xf0, 0xad, 0x63, 0x0b, 0x80, 0x68, 0x89, 0x2f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, + 0x61, 0xda, 0xf5, 0x42, 0x5a, 0x14, 0x50, 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf0, 0xae, 0xa3, 0x1d, 0x9f, + 0x9d, 0x1a, 0x5b, 0x42, 0x99, 0x5b, 0x3c, 0x91, 0xd5, 0xd1, 0x96, 0xea, 0x54, 0x1f, 0x70, 0xa9, 0x49, 0x75, 0x66, + 0x60, 0x78, 0x8d, 0x00, 0xe5, 0x16, 0x22, 0x69, 0x1c, 0xf6, 0xce, 0x27, 0x83, 0x82, 0xb9, 0x45, 0x02, 0x12, 0xd8, + 0xc6, 0xd6, 0x2e, 0x9a, 0xeb, 0xd7, 0x97, 0xd4, 0xab, 0xda, 0x54, 0xf5, 0xe0, 0x8d, 0x17, 0x38, 0x7b, 0xa7, 0xb5, + 0x80, 0x00, 0x0a, 0x5b, 0xcb, 0x72, 0x70, 0xee, 0x76, 0x55, 0x4b, 0x45, 0x19, 0xf5, 0xfb, 0xe7, 0x5f, 0x52, 0x54, + 0xc4, 0x9e, 0x2a, 0x4e, 0x59, 0xbf, 0xdd, 0x32, 0x17, 0x95, 0x25, 0x6f, 0x50, 0x45, 0x6b, 0x75, 0xd4, 0x54, 0xae, + 0x9b, 0xab, 0x96, 0x4c, 0x10, 0xa3, 0xfb, 0x74, 0xad, 0x73, 0xa7, 0xde, 0x7b, 0x15, 0x47, 0x0c, 0x04, 0x37, 0xdd, + 0xe3, 0x83, 0x83, 0xd0, 0xa8, 0x28, 0x17, 0xdc, 0x28, 0xad, 0x2a, 0x29, 0x85, 0xbc, 0x55, 0xd1, 0x9c, 0xe9, 0x23, + 0x00, 0x22, 0xc0, 0x2a, 0x51, 0xff, 0x87, 0x2f, 0x8d, 0xf1, 0xe0, 0x81, 0xaf, 0xc9, 0x75, 0x6c, 0xbd, 0x7f, 0x5a, + 0x23, 0xad, 0x36, 0x8e, 0x49, 0xad, 0x7a, 0xd9, 0x2a, 0x5e, 0x76, 0xaf, 0x53, 0x31, 0x78, 0xfe, 0x3f, 0xf7, 0x01, + 0x6a, 0x44, 0x4b, 0x19, 0xdc, 0xba, 0x1a, 0xa0, 0xf1, 0xe1, 0x58, 0xf8, 0xc6, 0x0f, 0x19, 0xe7, 0x83, 0x19, 0x3a, + 0xaa, 0xcd, 0xc1, 0x01, 0xc1, 0x51, 0xdd, 0xa3, 0x31, 0x61, 0x16, 0xce, 0x3d, 0x08, 0x54, 0x9f, 0xb8, 0xcf, 0xb8, + 0xf6, 0x82, 0x36, 0x81, 0x4f, 0xd6, 0x75, 0x4d, 0x11, 0xe0, 0x22, 0x36, 0x26, 0x62, 0x88, 0xcb, 0x26, 0x91, 0xfa, + 0x66, 0x0c, 0x0a, 0x80, 0xe2, 0x69, 0x45, 0x72, 0xe9, 0x22, 0xcd, 0x2b, 0x51, 0xd6, 0xba, 0x19, 0x15, 0x2b, 0x86, + 0x00, 0xf0, 0x10, 0x14, 0x57, 0x95, 0x99, 0xd0, 0x88, 0x0d, 0xa4, 0xb2, 0x14, 0xac, 0x1a, 0x16, 0x7e, 0xd3, 0x7e, + 0x93, 0x9c, 0xf4, 0xce, 0xc7, 0xad, 0x73, 0xc7, 0xbe, 0x77, 0x14, 0x52, 0xda, 0x43, 0x31, 0x41, 0x10, 0xfc, 0xb4, + 0x0e, 0xe7, 0xcf, 0xf8, 0x53, 0x02, 0x53, 0x91, 0xcd, 0x18, 0x70, 0x10, 0x22, 0x32, 0xe3, 0xf7, 0x1c, 0x3e, 0xe5, + 0xe5, 0x24, 0x1c, 0x0e, 0x7d, 0xd0, 0x87, 0xf2, 0x6c, 0x16, 0x0e, 0xc5, 0x5c, 0x7a, 0xaf, 0x83, 0xb5, 0x2e, 0xe4, + 0xf5, 0x24, 0x44, 0xb4, 0xd0, 0xd0, 0x07, 0xe7, 0x75, 0xd7, 0x1c, 0x61, 0x09, 0x40, 0x13, 0x47, 0x5f, 0xd6, 0xef, + 0x47, 0x9e, 0x36, 0xb4, 0x48, 0x71, 0xd1, 0x28, 0xb3, 0x59, 0x2e, 0x3b, 0x61, 0xe3, 0xda, 0x2d, 0x10, 0x8a, 0x87, + 0x69, 0x0b, 0x55, 0xeb, 0xa9, 0x5e, 0xcf, 0x4d, 0xbb, 0xef, 0x1e, 0x54, 0xab, 0x1c, 0xe9, 0xac, 0x4d, 0x57, 0x6a, + 0x75, 0xcb, 0xa8, 0x5a, 0x67, 0x69, 0x44, 0x95, 0x9b, 0xe4, 0xae, 0x51, 0x0b, 0x3e, 0xd9, 0xd0, 0x65, 0xca, 0xce, + 0xd6, 0xe0, 0xc4, 0x91, 0xe7, 0x92, 0x5b, 0xbe, 0x3b, 0xaf, 0xe8, 0xee, 0x54, 0xfb, 0x16, 0xe0, 0xde, 0x0c, 0x1b, + 0x32, 0xe7, 0x35, 0x76, 0x1a, 0x84, 0x49, 0xe0, 0x47, 0xec, 0x63, 0x86, 0x6c, 0x30, 0xa0, 0xa3, 0x90, 0xfe, 0xd7, + 0x96, 0x39, 0x12, 0x30, 0xf9, 0xeb, 0xb9, 0xdf, 0x2c, 0x8a, 0x1c, 0x16, 0xe3, 0xfb, 0x0d, 0x46, 0x1a, 0xab, 0x35, + 0x18, 0x96, 0xb7, 0x88, 0xfc, 0xa9, 0xdd, 0x31, 0x4d, 0x75, 0xbc, 0x59, 0xaf, 0x35, 0xbf, 0x7a, 0xfa, 0x54, 0xd7, + 0xe7, 0xbf, 0x7d, 0x7f, 0x19, 0xd6, 0xcc, 0xfe, 0x10, 0x84, 0xd2, 0xee, 0xdd, 0xe2, 0xdc, 0x91, 0xe8, 0x1d, 0x2b, + 0xcd, 0xec, 0xd2, 0x2e, 0xd9, 0xa5, 0x29, 0xed, 0x23, 0xb9, 0x5e, 0x7d, 0xa3, 0xbc, 0xb1, 0xf3, 0x8a, 0xe9, 0xfe, + 0xbd, 0xd0, 0x3b, 0xca, 0xa9, 0x9a, 0x40, 0x44, 0x93, 0x76, 0x24, 0x6e, 0xf7, 0xca, 0xf0, 0xc9, 0x24, 0x6f, 0x97, + 0x70, 0xd4, 0x35, 0x2c, 0x37, 0xdf, 0xfe, 0x25, 0xaf, 0x3a, 0x2b, 0xdc, 0x7e, 0x69, 0xcc, 0xda, 0x9f, 0x82, 0xb8, + 0xaa, 0x3f, 0xbd, 0xf7, 0x35, 0x53, 0xf2, 0x7f, 0xd5, 0x63, 0xe0, 0xea, 0x27, 0xd3, 0x8e, 0xee, 0x29, 0x84, 0x0d, + 0x66, 0x3f, 0x3f, 0x7e, 0x68, 0xd1, 0x35, 0xba, 0x40, 0x91, 0x1c, 0x40, 0xe7, 0x2e, 0x19, 0xe1, 0xfd, 0x8e, 0x71, + 0xee, 0x5f, 0xfd, 0xaa, 0x26, 0x47, 0x88, 0x68, 0x17, 0xe1, 0x00, 0x20, 0xee, 0x34, 0x95, 0x75, 0xa8, 0x01, 0xfa, + 0x80, 0xc0, 0x3a, 0xf4, 0x6d, 0x06, 0x70, 0xd0, 0x47, 0x9b, 0x67, 0x11, 0xc8, 0xeb, 0xde, 0x1d, 0xbb, 0x66, 0x3b, + 0x9f, 0x3f, 0x5d, 0xa5, 0xde, 0x1d, 0x3a, 0x04, 0x9f, 0x8f, 0xfd, 0xe9, 0x65, 0xa0, 0xd5, 0x9e, 0xd7, 0xec, 0xfa, + 0xb1, 0x60, 0x3b, 0xb6, 0x7b, 0x8c, 0x48, 0x45, 0xdd, 0xf9, 0x87, 0x97, 0x26, 0x7a, 0xde, 0x79, 0xe1, 0x96, 0x2f, + 0x01, 0x3c, 0x90, 0xc5, 0x80, 0xe2, 0xb3, 0xf4, 0x7e, 0x61, 0x09, 0xa8, 0xc9, 0x6f, 0xf8, 0xda, 0x7b, 0x4b, 0xa9, + 0x0b, 0xf8, 0x73, 0x40, 0xe9, 0x93, 0x9c, 0x7b, 0xb7, 0xc3, 0x1b, 0xff, 0xe2, 0x09, 0x38, 0x4f, 0xac, 0x86, 0x0b, + 0xf8, 0xab, 0xe0, 0x43, 0xef, 0x76, 0x80, 0x89, 0x25, 0x1f, 0x7a, 0xab, 0x01, 0xa4, 0x2a, 0x5c, 0x48, 0x8c, 0x7d, + 0xf8, 0x2d, 0xc8, 0x19, 0xfe, 0xf1, 0xbb, 0xc6, 0x60, 0xfd, 0x2d, 0x28, 0x34, 0x1a, 0x6b, 0xa9, 0x42, 0x96, 0x62, + 0x71, 0x26, 0xc0, 0x26, 0x1c, 0x77, 0xfb, 0x62, 0x55, 0x9b, 0xb5, 0xa0, 0x3f, 0x1f, 0xf0, 0x3d, 0x1a, 0xab, 0xab, + 0x72, 0x2e, 0xca, 0x0f, 0x48, 0x9f, 0xea, 0xf8, 0x18, 0x15, 0x9b, 0xba, 0x3b, 0x9d, 0x6a, 0xd5, 0x91, 0xf6, 0xbb, + 0x72, 0x0d, 0x76, 0xbc, 0x4e, 0x8e, 0x2c, 0x85, 0x67, 0x1d, 0x76, 0x5e, 0x3a, 0x25, 0x3a, 0x0c, 0xe3, 0xdd, 0x56, + 0x3d, 0x63, 0x28, 0xcf, 0x0d, 0xc6, 0x74, 0xc1, 0x23, 0xfe, 0x74, 0x90, 0xcb, 0xd0, 0x98, 0x77, 0xc8, 0x86, 0xa1, + 0x7c, 0x68, 0x91, 0x21, 0x21, 0xe2, 0x3d, 0x54, 0x02, 0xb6, 0x2d, 0x28, 0x93, 0x02, 0xce, 0xa2, 0xc1, 0xef, 0xb5, + 0x97, 0x03, 0xef, 0x41, 0xe4, 0x37, 0xd2, 0xa5, 0x5c, 0x62, 0xa3, 0x13, 0xc7, 0xb2, 0xd0, 0xce, 0xe3, 0xfa, 0xeb, + 0x18, 0xd4, 0xef, 0x95, 0x7e, 0x83, 0x72, 0xf6, 0x07, 0xc9, 0x3a, 0x6d, 0x3c, 0x31, 0xfe, 0xed, 0x2a, 0xff, 0x14, + 0x2d, 0xf5, 0xf0, 0xff, 0x19, 0x53, 0x28, 0xfd, 0x75, 0x5a, 0x46, 0x9b, 0xd5, 0x52, 0x94, 0x22, 0x8f, 0xc4, 0xc9, + 0xd7, 0x22, 0x3b, 0x97, 0xef, 0x7c, 0x0a, 0xfd, 0x02, 0xd0, 0xb2, 0x4f, 0x90, 0xd1, 0xbf, 0x32, 0xc1, 0x87, 0xbf, + 0x6a, 0xe7, 0xda, 0x9c, 0x8f, 0x27, 0xf9, 0x95, 0xb5, 0x77, 0x3b, 0x5e, 0x24, 0x46, 0x31, 0x96, 0xfb, 0xaa, 0x9b, + 0x95, 0x13, 0x95, 0x1c, 0x18, 0xe9, 0x9a, 0xec, 0xe5, 0x4a, 0xd6, 0xed, 0x74, 0x2b, 0x81, 0x88, 0x2a, 0xf0, 0x1e, + 0xe3, 0x2a, 0xf6, 0x11, 0x4c, 0xd7, 0x1d, 0x97, 0xd1, 0x8e, 0xf7, 0x8c, 0x57, 0x27, 0xca, 0x0a, 0x6e, 0x37, 0xa2, + 0x3d, 0xa1, 0xa3, 0x9f, 0x26, 0xb5, 0x65, 0xe1, 0x00, 0xe4, 0x2e, 0x61, 0x2c, 0x1b, 0x82, 0x15, 0x83, 0xd2, 0xd7, + 0x6b, 0x4a, 0x96, 0x05, 0x58, 0x74, 0x76, 0x19, 0x81, 0x18, 0xd6, 0x4d, 0x73, 0x42, 0xc7, 0x4b, 0x17, 0xe7, 0xbd, + 0x56, 0x91, 0x82, 0x67, 0xb4, 0xe8, 0x98, 0x9b, 0x8e, 0x74, 0x63, 0xb4, 0xb7, 0xcf, 0x0d, 0x42, 0x8a, 0xe7, 0x0f, + 0x6c, 0xb5, 0x2e, 0x2e, 0x12, 0xaf, 0x90, 0x89, 0x16, 0xc4, 0x52, 0x04, 0x66, 0xbc, 0xd0, 0x34, 0xc2, 0x04, 0x65, + 0x4a, 0xb0, 0x68, 0x8d, 0x0e, 0xed, 0x0f, 0x4b, 0xd8, 0x3d, 0xc6, 0x08, 0x10, 0xa8, 0x32, 0xfd, 0x1a, 0xb6, 0x26, + 0xcc, 0xa6, 0x2e, 0x36, 0x40, 0x5b, 0xc5, 0xd0, 0x20, 0xac, 0x0d, 0x31, 0x1f, 0xd2, 0xfc, 0xf6, 0x5f, 0x58, 0x8c, + 0xed, 0x09, 0xc4, 0xf6, 0x6e, 0xd7, 0x24, 0x4c, 0xf7, 0x5a, 0xdc, 0x58, 0x2f, 0xb7, 0xa7, 0x1c, 0x53, 0x3b, 0xd6, + 0x46, 0xed, 0x58, 0x4b, 0xbd, 0x63, 0xad, 0xf5, 0x8e, 0x75, 0xdb, 0xf0, 0x67, 0x99, 0x17, 0xb3, 0x04, 0xf4, 0xbb, + 0x2b, 0xae, 0x1a, 0x04, 0xcd, 0xd8, 0xb0, 0x1b, 0xf8, 0x2d, 0xb1, 0x76, 0x4b, 0xff, 0x62, 0xc9, 0x16, 0xa6, 0x0f, + 0x74, 0xeb, 0x00, 0xcb, 0x88, 0x9a, 0x7c, 0x87, 0xbc, 0x9b, 0xce, 0x8a, 0xc2, 0xed, 0x89, 0x2d, 0x7c, 0x76, 0x6d, + 0xde, 0xbc, 0x7b, 0x1c, 0x41, 0xee, 0x1d, 0xf7, 0xee, 0x86, 0xd7, 0xfe, 0x85, 0x6e, 0x81, 0x9c, 0xcc, 0x72, 0x06, + 0x52, 0x47, 0x7c, 0x82, 0x68, 0x65, 0x4f, 0xf9, 0x4e, 0xc8, 0x9d, 0x6d, 0xfd, 0xf8, 0xce, 0xdd, 0xd6, 0x6e, 0x1f, + 0xdf, 0xb1, 0x6a, 0x44, 0xb1, 0xe2, 0x34, 0x45, 0xc2, 0x2c, 0xda, 0x00, 0x4f, 0xbd, 0x7c, 0xbf, 0x63, 0xc7, 0x1c, + 0xee, 0x1e, 0x77, 0x74, 0xbc, 0x9c, 0x03, 0x76, 0xf7, 0x1f, 0x6d, 0xc2, 0xc6, 0x4a, 0xd7, 0x2a, 0x74, 0xb8, 0x7b, + 0x9c, 0x69, 0x3c, 0x87, 0x23, 0xf9, 0x74, 0xac, 0xb1, 0x41, 0x50, 0xd7, 0xe7, 0x0c, 0x6a, 0xc7, 0xee, 0x6b, 0xc2, + 0x2e, 0x3b, 0xe6, 0xb5, 0xae, 0x79, 0x7b, 0xe5, 0xa9, 0xd8, 0x10, 0xd0, 0xe1, 0x6b, 0x75, 0x83, 0xfc, 0x4b, 0xe0, + 0x14, 0x01, 0x20, 0x87, 0xe3, 0x25, 0x8f, 0x7d, 0x9f, 0x66, 0x69, 0xbd, 0x43, 0xad, 0x45, 0x65, 0x59, 0x86, 0xb5, + 0xf7, 0x83, 0x56, 0x0c, 0x4b, 0x4d, 0xff, 0x74, 0x1c, 0xb8, 0x9d, 0xed, 0x56, 0xc6, 0x2e, 0xe3, 0x71, 0x71, 0xf1, + 0xeb, 0x69, 0xa1, 0x5c, 0xbb, 0x79, 0x1b, 0xbf, 0x69, 0xb5, 0x64, 0x69, 0xad, 0x87, 0xbc, 0xb4, 0x2c, 0x22, 0x10, + 0xc0, 0x70, 0xa4, 0xec, 0x62, 0x09, 0xf7, 0x08, 0xab, 0x7b, 0x10, 0x4a, 0xe6, 0x85, 0x8b, 0x27, 0x2c, 0x86, 0x44, + 0x80, 0xed, 0x0e, 0x15, 0xdb, 0xc2, 0xc5, 0x13, 0xb6, 0xe1, 0x45, 0xbf, 0x9f, 0xa9, 0x4e, 0x21, 0xeb, 0xce, 0x92, + 0x6f, 0x54, 0x73, 0xac, 0xa1, 0x66, 0x6b, 0x93, 0x6c, 0x8d, 0x73, 0x5b, 0xf1, 0x71, 0xdb, 0x56, 0x7c, 0xac, 0xac, + 0x75, 0xe9, 0x5e, 0xef, 0x51, 0x5d, 0x00, 0x5b, 0xff, 0xcd, 0xf1, 0xca, 0xf5, 0x7c, 0x46, 0x00, 0x5f, 0x0b, 0x3e, + 0x9e, 0x2c, 0xd0, 0xab, 0x64, 0xe1, 0xdf, 0x0c, 0xd4, 0xf8, 0x3b, 0x9d, 0xbb, 0x00, 0xe8, 0x4a, 0xca, 0x2b, 0x20, + 0xef, 0x20, 0xc7, 0xdc, 0xb2, 0x2b, 0xef, 0x4e, 0xbe, 0xc3, 0xae, 0x79, 0x3d, 0x5b, 0xcc, 0xd9, 0x0e, 0x9c, 0x0a, + 0x92, 0x81, 0xbd, 0xac, 0xd8, 0x2e, 0x88, 0xed, 0x84, 0xdf, 0x09, 0x98, 0xf2, 0x19, 0x04, 0x71, 0x05, 0x37, 0x10, + 0x87, 0x27, 0xff, 0x1c, 0xdc, 0xb5, 0x36, 0xeb, 0x3b, 0x66, 0x75, 0x4e, 0xb0, 0x66, 0x56, 0x0f, 0x06, 0xcb, 0x66, + 0xb2, 0xea, 0xf7, 0xbd, 0x9d, 0x76, 0x7c, 0xba, 0x95, 0x3a, 0xb1, 0xd3, 0x5a, 0xad, 0x05, 0xbb, 0x96, 0x5a, 0x17, + 0x63, 0xe8, 0x01, 0xe2, 0xa7, 0x9b, 0x01, 0xbf, 0xeb, 0x58, 0x5b, 0xde, 0x35, 0x5b, 0xb0, 0x1d, 0x5c, 0x82, 0x9a, + 0xf6, 0xb2, 0x3f, 0xa9, 0x5c, 0xd0, 0x8e, 0x5d, 0x12, 0x0f, 0x67, 0xcc, 0x2a, 0x65, 0x66, 0x9d, 0x54, 0x57, 0xa2, + 0x33, 0xa6, 0xb3, 0xd6, 0xf3, 0xb9, 0x9a, 0x4f, 0x0a, 0x0d, 0xea, 0x77, 0x4e, 0x7c, 0x44, 0x45, 0xe7, 0x09, 0x6c, + 0x2d, 0x2b, 0x88, 0xd5, 0x3e, 0x07, 0x6b, 0xad, 0x76, 0xe9, 0xf7, 0xf2, 0x01, 0xb7, 0x29, 0x87, 0x75, 0x60, 0x50, + 0x73, 0x62, 0x45, 0x3d, 0x64, 0x3b, 0xc6, 0xcd, 0x4f, 0x2f, 0x7f, 0x70, 0xc2, 0x92, 0x15, 0xab, 0xfd, 0xe9, 0xaf, + 0x8f, 0x3d, 0xfd, 0x9d, 0xda, 0xbf, 0x10, 0x7e, 0x30, 0xfe, 0x4f, 0xed, 0xbe, 0xd6, 0x62, 0x54, 0xb6, 0xca, 0x11, + 0x1a, 0x77, 0x2b, 0x69, 0xb2, 0xfc, 0x24, 0x3c, 0x61, 0x2d, 0x78, 0x96, 0xeb, 0x25, 0x9a, 0x15, 0xb0, 0xc2, 0x5a, + 0x26, 0xe1, 0x0a, 0x63, 0xb5, 0xb4, 0xd5, 0xb7, 0x68, 0x9a, 0xe3, 0xc3, 0xb9, 0x36, 0x28, 0x53, 0xce, 0xce, 0x88, + 0xd5, 0x70, 0x19, 0x96, 0x26, 0x14, 0x21, 0xbb, 0xb7, 0x83, 0x1b, 0x3b, 0x65, 0x29, 0x65, 0x38, 0xc7, 0x60, 0xc2, + 0x23, 0x31, 0xaa, 0xf2, 0xfd, 0x7d, 0x49, 0x91, 0xd3, 0xb6, 0x1c, 0x54, 0x21, 0xec, 0x23, 0x89, 0x12, 0xb8, 0x15, + 0x69, 0xa1, 0x48, 0x59, 0xfc, 0xed, 0x00, 0x5d, 0xe0, 0x05, 0xd4, 0xd5, 0xa8, 0xdb, 0x1f, 0x8e, 0x78, 0xf8, 0xc0, + 0xd4, 0x07, 0x46, 0x2c, 0x09, 0xd4, 0xf6, 0x2c, 0x4b, 0x6f, 0x41, 0x85, 0xdf, 0xc3, 0xd5, 0x44, 0xec, 0xe7, 0x96, + 0x14, 0x15, 0xd9, 0x48, 0x6f, 0x68, 0x0d, 0x1e, 0xa1, 0x35, 0xe5, 0xb9, 0x93, 0x6a, 0x93, 0xce, 0x3b, 0x42, 0x8e, + 0xd5, 0xb7, 0x96, 0x30, 0xda, 0x15, 0xbd, 0xb8, 0x77, 0xf4, 0x9e, 0xa7, 0xab, 0x9e, 0xfb, 0x13, 0x57, 0xcc, 0x93, + 0xdb, 0x08, 0xd4, 0xad, 0xa0, 0xba, 0xbd, 0x53, 0x09, 0x16, 0x2c, 0x69, 0xf7, 0xf1, 0xdb, 0x59, 0x3b, 0x10, 0x95, + 0xb1, 0x4a, 0xdf, 0x92, 0x84, 0x3d, 0x31, 0xe8, 0x14, 0xaa, 0x72, 0xbb, 0x3b, 0xda, 0x02, 0xd7, 0x31, 0x4b, 0xd1, + 0x33, 0x5b, 0xe4, 0x6e, 0xf9, 0x77, 0xcf, 0x15, 0x39, 0xfb, 0x25, 0x20, 0x38, 0x35, 0xdf, 0x10, 0x5f, 0x8e, 0xf0, + 0xa8, 0xba, 0x05, 0x8e, 0xd3, 0x77, 0x00, 0xff, 0x70, 0xb8, 0x04, 0x4d, 0x40, 0x2c, 0x58, 0x2f, 0x8d, 0x7b, 0xac, + 0x17, 0x17, 0x9b, 0xdb, 0x24, 0xdf, 0x80, 0x33, 0x03, 0xa5, 0x5a, 0xfa, 0x81, 0x63, 0xb5, 0x80, 0x0a, 0x07, 0xb3, + 0x93, 0x7a, 0x61, 0x19, 0xf5, 0x98, 0x3e, 0x3f, 0x83, 0xbd, 0x23, 0x24, 0x00, 0xee, 0x97, 0x7d, 0x40, 0x02, 0x1e, + 0x3a, 0xb3, 0x03, 0xc2, 0x09, 0xb3, 0xa8, 0x0a, 0x24, 0x92, 0x23, 0xfd, 0xec, 0x31, 0x13, 0xc9, 0x1f, 0xcc, 0x7a, + 0xce, 0x29, 0xd1, 0x63, 0x3d, 0x75, 0x84, 0xf4, 0x58, 0xcf, 0x3a, 0x22, 0x7a, 0xac, 0x67, 0x1d, 0x1f, 0x3d, 0xd6, + 0x33, 0xc7, 0x4e, 0x0f, 0x02, 0x13, 0x20, 0xf2, 0x80, 0xf5, 0x68, 0x32, 0xf5, 0x14, 0xf7, 0x00, 0xd1, 0x20, 0xb0, + 0x9e, 0x14, 0xce, 0x7b, 0x80, 0x3c, 0x46, 0x62, 0x75, 0xd0, 0xfb, 0xcb, 0xf8, 0x87, 0x9e, 0x91, 0x91, 0xc7, 0xad, + 0xc3, 0xea, 0x7f, 0xfd, 0x15, 0x02, 0xe0, 0xf0, 0x6c, 0xea, 0x5d, 0x8e, 0x21, 0xab, 0x2c, 0x23, 0x90, 0xfc, 0xc4, + 0xe0, 0xcb, 0x17, 0x00, 0x55, 0x9f, 0xe9, 0x5a, 0x4d, 0x8e, 0xda, 0x63, 0x0e, 0x5d, 0x31, 0x00, 0x6c, 0xc3, 0x12, + 0x55, 0xb5, 0xb0, 0x09, 0x8b, 0xdb, 0xcf, 0x30, 0x9a, 0xcb, 0xa6, 0x17, 0x34, 0x50, 0x8f, 0x10, 0xfc, 0xd2, 0x7a, + 0x68, 0xad, 0x65, 0xca, 0xa1, 0x6b, 0xa3, 0xa8, 0xb2, 0xa1, 0x2e, 0x61, 0xb5, 0x16, 0x51, 0x4d, 0x14, 0x29, 0x97, + 0x8c, 0xa2, 0x58, 0xaa, 0x60, 0x9f, 0x89, 0x5b, 0x88, 0x9a, 0xa7, 0xad, 0xb6, 0x0a, 0xf6, 0xb7, 0x80, 0xb0, 0x16, + 0xd6, 0x42, 0x3a, 0x83, 0xda, 0x3b, 0xfd, 0x48, 0xf9, 0xcb, 0x0b, 0xb9, 0x9d, 0x5b, 0x28, 0xc2, 0xed, 0x39, 0x28, + 0x6f, 0xea, 0xaa, 0x54, 0x44, 0xa3, 0x25, 0x50, 0xca, 0x9c, 0x20, 0xb2, 0x00, 0x01, 0x1c, 0x37, 0x10, 0xf8, 0xbc, + 0xc6, 0x27, 0xd0, 0x28, 0x04, 0xf2, 0x03, 0xab, 0x70, 0xed, 0x21, 0x2d, 0xb5, 0x46, 0x44, 0x89, 0xf8, 0xd1, 0xd5, + 0x73, 0x6c, 0x5f, 0x3d, 0x8d, 0xb5, 0xa5, 0x34, 0x41, 0xfc, 0xc4, 0x62, 0x0b, 0x31, 0x41, 0x54, 0x87, 0xe8, 0x08, + 0x96, 0x13, 0x42, 0x14, 0xfe, 0x14, 0xfa, 0xa9, 0x81, 0xbf, 0x64, 0xcb, 0x22, 0xaf, 0x09, 0x16, 0xb3, 0x62, 0x80, + 0x56, 0x45, 0xe0, 0x99, 0xce, 0x96, 0xca, 0x9c, 0xe6, 0xd1, 0x91, 0x1d, 0x9c, 0x77, 0x1d, 0xec, 0xa5, 0x2f, 0x63, + 0x27, 0xcb, 0xa6, 0x51, 0x1b, 0x1b, 0x22, 0xe1, 0x15, 0xf9, 0x75, 0x96, 0x1a, 0xe7, 0xc8, 0x5c, 0xae, 0xef, 0xba, + 0xb8, 0xbd, 0xa5, 0x6d, 0xc2, 0x2a, 0x44, 0xa8, 0xdb, 0x86, 0xca, 0xa5, 0x30, 0x1b, 0x9b, 0xa6, 0x01, 0xbe, 0x50, + 0x54, 0x2a, 0x55, 0xa9, 0xad, 0x54, 0x72, 0xc2, 0xbb, 0xbe, 0xa9, 0x45, 0xea, 0x8a, 0x60, 0x1b, 0x33, 0xd4, 0x43, + 0xb9, 0x51, 0x63, 0xdf, 0x76, 0xac, 0xd2, 0x3b, 0x4c, 0x90, 0x33, 0xf2, 0x22, 0x07, 0x17, 0x25, 0x05, 0x99, 0xab, + 0x21, 0xcc, 0x1f, 0x34, 0x7c, 0x5a, 0x58, 0xee, 0xa1, 0x04, 0xcc, 0x8e, 0x1a, 0x1e, 0x45, 0x08, 0x44, 0x5c, 0x2a, + 0xfb, 0x8a, 0x89, 0xdf, 0x53, 0x30, 0x4b, 0x26, 0x74, 0x2f, 0x62, 0x59, 0x84, 0x36, 0x3e, 0x49, 0x92, 0xa9, 0xa7, + 0x29, 0xb8, 0x91, 0xcb, 0x30, 0x47, 0x23, 0xb4, 0xe4, 0x23, 0x07, 0xd2, 0xd7, 0x72, 0x2a, 0xc1, 0x47, 0xd4, 0x29, + 0xe0, 0x78, 0x7e, 0x5e, 0x58, 0x3f, 0x59, 0x2e, 0x31, 0x97, 0xb5, 0xf9, 0x2f, 0x3b, 0x3a, 0x06, 0xbb, 0x3c, 0x4d, + 0x1c, 0x57, 0xff, 0x51, 0x95, 0x14, 0xf7, 0xaf, 0xd3, 0x1c, 0x50, 0x04, 0x33, 0x7b, 0x8a, 0xf1, 0xb1, 0xcf, 0x32, + 0x05, 0xfc, 0xed, 0x7a, 0x6b, 0xc9, 0xc4, 0x2e, 0x69, 0x37, 0x57, 0xc6, 0x2f, 0xb5, 0x61, 0xc7, 0xc1, 0xb9, 0x01, + 0x28, 0xce, 0x1a, 0x1d, 0x96, 0xd7, 0xba, 0x6d, 0x55, 0xa8, 0x40, 0xad, 0xff, 0xb3, 0x5b, 0x98, 0xf2, 0x36, 0x2f, + 0x95, 0xb7, 0x79, 0x68, 0x02, 0x04, 0x22, 0x33, 0xe4, 0x59, 0xd3, 0x31, 0x49, 0xdc, 0x3b, 0x52, 0xd2, 0xbe, 0x23, + 0xc5, 0x0f, 0xde, 0x91, 0x90, 0x6f, 0x09, 0x1d, 0xd9, 0x97, 0x9c, 0x9c, 0x40, 0x99, 0xc1, 0x5e, 0x5e, 0x33, 0xd9, + 0x3f, 0xa0, 0xbd, 0x70, 0x2e, 0xcb, 0x2b, 0xfe, 0x46, 0x78, 0x6b, 0x7f, 0xba, 0x3e, 0xed, 0xaa, 0x7a, 0xf3, 0x8d, + 0x99, 0x79, 0x38, 0x14, 0x87, 0x43, 0x65, 0x82, 0x76, 0x17, 0x5c, 0x0c, 0x72, 0x76, 0xe7, 0xc6, 0xc7, 0x5f, 0x73, + 0x14, 0xb1, 0x95, 0xf2, 0x48, 0xba, 0x50, 0x89, 0xe1, 0xa5, 0x81, 0x87, 0xd9, 0xf1, 0xf1, 0x64, 0x77, 0x75, 0x37, + 0x19, 0x0c, 0x76, 0xaa, 0x6f, 0xb7, 0xbc, 0x9e, 0xed, 0xe6, 0xec, 0x9e, 0xdf, 0x4c, 0xb7, 0xc1, 0xbe, 0x81, 0x6d, + 0x77, 0x77, 0x25, 0x0e, 0x87, 0xdd, 0x53, 0xbe, 0xf0, 0xf7, 0xf7, 0x08, 0xe8, 0xcc, 0xcf, 0xc7, 0x6d, 0x8c, 0x9f, + 0x37, 0x6d, 0x57, 0xad, 0x1d, 0xc0, 0xd3, 0xbf, 0xf2, 0xde, 0xcc, 0x96, 0x73, 0x9f, 0xbd, 0xe7, 0xf7, 0xe0, 0x9f, + 0x8f, 0x9b, 0x24, 0x52, 0x9f, 0x68, 0x97, 0xc9, 0x37, 0xe0, 0x40, 0xbe, 0xf3, 0xd9, 0x27, 0x7e, 0x3f, 0x5b, 0xce, + 0x79, 0x71, 0x38, 0x3c, 0x9a, 0x86, 0x48, 0xd6, 0x14, 0x56, 0xc4, 0x92, 0xe2, 0xf9, 0x41, 0x78, 0xfc, 0x5e, 0x44, + 0x86, 0x48, 0xcb, 0xbd, 0x3b, 0x64, 0x6f, 0x58, 0xe4, 0x07, 0xf0, 0x41, 0xb6, 0xf3, 0x27, 0xb2, 0xa6, 0x74, 0xbf, + 0x78, 0xef, 0x1f, 0x0e, 0xf4, 0xd7, 0x27, 0xff, 0x70, 0x78, 0xc4, 0xee, 0x11, 0x1c, 0x9d, 0xef, 0xa0, 0x7f, 0xf4, + 0xad, 0x03, 0xaa, 0x32, 0xbc, 0x9e, 0x6d, 0xe6, 0xfe, 0xd3, 0x15, 0xbb, 0x05, 0x2e, 0x14, 0xe5, 0x85, 0xf6, 0x86, + 0xdd, 0xa3, 0xd7, 0x19, 0x39, 0x11, 0xcd, 0x76, 0x73, 0x9f, 0xc5, 0xf8, 0x5c, 0xdd, 0x17, 0x93, 0x6f, 0xde, 0x17, + 0x77, 0x6c, 0xdb, 0x7d, 0x5f, 0x94, 0x6f, 0xba, 0xeb, 0x67, 0xcb, 0x76, 0xec, 0x1e, 0x66, 0xd8, 0x35, 0x7f, 0xd3, + 0x1c, 0x3b, 0xc6, 0x7e, 0xf3, 0xc6, 0x08, 0xa0, 0xcc, 0x16, 0x2c, 0x16, 0x1c, 0x94, 0x6a, 0xd5, 0xb6, 0x24, 0xf2, + 0x4a, 0x07, 0xaa, 0xcd, 0x08, 0xee, 0xab, 0x85, 0x9c, 0x79, 0x66, 0xa0, 0x6f, 0x2b, 0x44, 0x0b, 0x87, 0x0d, 0xf8, + 0x1b, 0x6d, 0x1d, 0x63, 0x98, 0x66, 0x35, 0xd3, 0xb6, 0xa8, 0xcb, 0xef, 0x7b, 0xcf, 0xe4, 0x37, 0x32, 0xb0, 0x85, + 0x48, 0x0a, 0xc7, 0xf1, 0xc5, 0x93, 0x13, 0xfe, 0xab, 0x96, 0x47, 0xad, 0xf6, 0x0b, 0xa5, 0x3e, 0xbd, 0xa6, 0x23, + 0x9a, 0xb8, 0x17, 0x6d, 0x19, 0xd6, 0x28, 0x6b, 0x6a, 0xe9, 0x30, 0x8c, 0x6b, 0xd8, 0x97, 0x07, 0x0e, 0x7d, 0x07, + 0x04, 0xda, 0x2a, 0x95, 0x02, 0x2d, 0x1c, 0xc3, 0x28, 0xcc, 0x42, 0xca, 0xc3, 0xc2, 0x2c, 0xe5, 0x3d, 0x16, 0x68, + 0x71, 0xab, 0xee, 0x31, 0xb5, 0xdd, 0x82, 0x08, 0xab, 0xb7, 0x8c, 0xf3, 0xcb, 0x46, 0x15, 0x6e, 0x0b, 0x50, 0x14, + 0x41, 0x19, 0xec, 0x49, 0x6e, 0x5b, 0x28, 0x69, 0x36, 0x0a, 0x6b, 0x71, 0x5b, 0x94, 0xbb, 0x5e, 0xc3, 0x16, 0x78, + 0x41, 0xd5, 0x4f, 0x08, 0xdb, 0xb2, 0x67, 0x1d, 0xca, 0x45, 0xfa, 0x1f, 0x59, 0x7a, 0xbe, 0xdf, 0x9a, 0xf3, 0x3f, + 0x7d, 0x45, 0x1f, 0x95, 0xff, 0xf9, 0x25, 0xfd, 0x64, 0xb0, 0x8c, 0x9c, 0x52, 0xbf, 0x44, 0xa3, 0x9b, 0x34, 0x27, + 0x8c, 0x2d, 0x5f, 0x3f, 0xfd, 0x0e, 0x99, 0x82, 0xe4, 0x50, 0x4a, 0x55, 0x4e, 0xf6, 0xd0, 0x17, 0x5e, 0xf7, 0x61, + 0x26, 0x18, 0x80, 0xf0, 0x1a, 0x6d, 0xaa, 0x09, 0x93, 0x78, 0x70, 0x05, 0xff, 0x37, 0x82, 0x18, 0xb4, 0x4f, 0x14, + 0x75, 0x6c, 0x1b, 0xe9, 0xba, 0xed, 0x1c, 0x24, 0x77, 0xea, 0xca, 0x1f, 0x95, 0x93, 0xff, 0x44, 0x43, 0xe4, 0x15, + 0x57, 0x88, 0x95, 0x05, 0x97, 0x58, 0x0c, 0x15, 0x29, 0xc0, 0x35, 0x04, 0x91, 0xb2, 0x28, 0x29, 0xdc, 0x72, 0x50, + 0x15, 0x01, 0x18, 0x57, 0xab, 0xa3, 0x4e, 0x84, 0x8f, 0x5b, 0x6b, 0x11, 0x82, 0x15, 0x8d, 0x5a, 0x59, 0x2b, 0xf0, + 0x05, 0xe9, 0x4b, 0x87, 0x82, 0x98, 0x1e, 0x85, 0x54, 0x95, 0x0e, 0x05, 0xd2, 0x1c, 0x2a, 0xbe, 0x31, 0xd8, 0x28, + 0x2a, 0xd2, 0xf3, 0x97, 0x26, 0x25, 0x97, 0xc6, 0x8c, 0xf7, 0xa2, 0x8c, 0x44, 0x5e, 0x87, 0xb7, 0x62, 0x5a, 0x20, + 0xdf, 0xe8, 0xf1, 0x83, 0xe0, 0x12, 0xde, 0x0d, 0xb9, 0x57, 0x80, 0x2d, 0x01, 0x3b, 0xc0, 0xbd, 0x32, 0xa3, 0x5c, + 0xa7, 0x75, 0xfd, 0xd6, 0x7a, 0x28, 0x86, 0xe1, 0x63, 0x4b, 0x60, 0x3b, 0x5a, 0x47, 0x47, 0x7a, 0xf8, 0xf0, 0xbf, + 0xae, 0x6a, 0x8e, 0x3a, 0x95, 0xcb, 0xd9, 0xf1, 0x84, 0xa5, 0x88, 0x19, 0x74, 0x7f, 0xdd, 0x5e, 0x0b, 0xa0, 0xdb, + 0x65, 0x31, 0xcf, 0x46, 0x3b, 0xf9, 0xb7, 0x74, 0x63, 0x45, 0x69, 0x13, 0xef, 0xb2, 0xde, 0xd8, 0x1f, 0x8e, 0xfe, + 0xf2, 0xf8, 0xed, 0x84, 0x50, 0x75, 0x36, 0x6c, 0xad, 0xe3, 0x5c, 0xfe, 0xd7, 0x5f, 0xc7, 0x64, 0x05, 0x41, 0x41, + 0x58, 0x76, 0x8a, 0x89, 0x0a, 0x46, 0x91, 0x62, 0xcd, 0xc7, 0x93, 0x35, 0xea, 0x84, 0xd7, 0xfe, 0x52, 0xeb, 0x84, + 0x89, 0x91, 0x95, 0xca, 0x5f, 0xb3, 0x8a, 0xdd, 0xaa, 0xcc, 0x02, 0x32, 0x0f, 0xf2, 0xc9, 0xda, 0x68, 0x30, 0x57, + 0xbc, 0x9e, 0xad, 0xe7, 0x52, 0xf9, 0x0c, 0xa6, 0x9c, 0xe5, 0xe0, 0x64, 0x29, 0xec, 0x8e, 0x04, 0x8a, 0xd6, 0x0c, + 0x5d, 0xfb, 0x53, 0x6c, 0xd5, 0x8b, 0xb4, 0xaa, 0x01, 0x1e, 0x10, 0x62, 0x60, 0xa8, 0xbd, 0x5a, 0x78, 0x68, 0x2d, + 0x80, 0xb5, 0x3f, 0x2a, 0xfd, 0x60, 0x3c, 0x59, 0xf2, 0x05, 0xf2, 0x2f, 0x47, 0x8e, 0xda, 0xbd, 0xdf, 0xf7, 0xee, + 0x40, 0x0a, 0x8e, 0x5c, 0x0b, 0x05, 0x12, 0x01, 0x2d, 0xf8, 0xc6, 0x57, 0x3e, 0x18, 0xd7, 0xa8, 0xad, 0x06, 0x05, + 0xb5, 0xa3, 0x5b, 0x1e, 0x3b, 0x7a, 0xe7, 0xbb, 0x13, 0xfa, 0xea, 0x85, 0x16, 0x8e, 0xbf, 0x71, 0x46, 0xae, 0xd9, + 0xaa, 0x43, 0x8e, 0x68, 0x26, 0x1d, 0x42, 0xc4, 0x8a, 0xad, 0xd9, 0x35, 0xa9, 0x9c, 0x3b, 0x87, 0xec, 0xf4, 0x11, + 0xaa, 0xf4, 0x5a, 0x0f, 0x6f, 0x27, 0x4a, 0x77, 0x7b, 0xbc, 0x9b, 0x7c, 0xcf, 0x26, 0x22, 0x06, 0x03, 0xda, 0x20, + 0x9c, 0x91, 0x75, 0x88, 0x54, 0x3a, 0x40, 0x08, 0x1c, 0x13, 0xd0, 0xf4, 0xdf, 0xdf, 0x92, 0x28, 0xe0, 0x48, 0x1b, + 0x21, 0x6b, 0xd9, 0xe1, 0x90, 0x83, 0x46, 0xb9, 0xf9, 0xd3, 0x2b, 0xd4, 0x69, 0x0e, 0xcc, 0xd3, 0x25, 0xec, 0x39, + 0x78, 0xa4, 0x17, 0xc7, 0x47, 0xfa, 0x7f, 0x47, 0x13, 0x35, 0xfe, 0xcf, 0x35, 0x51, 0x4a, 0x8b, 0xe4, 0xa8, 0x96, + 0xbe, 0x4b, 0x1d, 0x05, 0x17, 0x79, 0x47, 0x2d, 0x64, 0xcf, 0xb2, 0x71, 0xa3, 0x9a, 0xf7, 0xff, 0x6b, 0x65, 0xfe, + 0xbf, 0xa6, 0x95, 0x61, 0x4a, 0x76, 0x2c, 0xd5, 0xcc, 0x03, 0xad, 0x62, 0x98, 0xbd, 0x26, 0x09, 0x91, 0xe1, 0xd2, + 0x80, 0x1f, 0x55, 0xb0, 0x8f, 0xd3, 0x6a, 0x9d, 0x85, 0x3b, 0x54, 0xa2, 0xde, 0x88, 0xdb, 0x34, 0x7f, 0x56, 0xff, + 0x5b, 0x94, 0x05, 0x4c, 0xed, 0xdb, 0x32, 0x8d, 0x03, 0xb2, 0xf0, 0x67, 0x61, 0x89, 0x93, 0x1b, 0xdb, 0xf8, 0x5a, + 0x8e, 0xa7, 0xfd, 0xaa, 0x33, 0xf3, 0x40, 0x02, 0x35, 0xb0, 0x94, 0xe4, 0x5c, 0x56, 0x16, 0xf7, 0x08, 0xdd, 0xfc, + 0x53, 0x59, 0x16, 0xa5, 0xd7, 0xfb, 0x94, 0xa4, 0xd5, 0xd9, 0x4a, 0xd4, 0x49, 0x11, 0x2b, 0x28, 0x9b, 0x14, 0x60, + 0xf4, 0x61, 0xe5, 0x89, 0x38, 0x38, 0x43, 0xa0, 0x86, 0xb3, 0x3a, 0x09, 0x01, 0x68, 0x58, 0x21, 0xec, 0x9f, 0x41, + 0x0b, 0xcf, 0xc2, 0x38, 0x5c, 0x03, 0x4c, 0x4e, 0x5a, 0x9d, 0xad, 0xcb, 0xe2, 0x2e, 0x8d, 0x45, 0x3c, 0xea, 0x29, + 0x4a, 0x96, 0xb7, 0xb9, 0x2b, 0xe7, 0xfa, 0xfb, 0x3f, 0x29, 0x80, 0xdd, 0x80, 0xd9, 0xb6, 0xc0, 0x0e, 0x00, 0x12, + 0x14, 0xc8, 0x16, 0xea, 0x34, 0x3a, 0x53, 0x4b, 0x05, 0xde, 0x73, 0x3d, 0xc0, 0xdf, 0xe6, 0x80, 0x65, 0x5c, 0x17, + 0x32, 0x60, 0x04, 0x01, 0x8c, 0xc0, 0x41, 0x09, 0x18, 0x3a, 0x43, 0xdc, 0x56, 0xe5, 0xac, 0x85, 0xe6, 0x4a, 0xb7, + 0x25, 0x37, 0x8d, 0x72, 0xb6, 0x12, 0x01, 0xf4, 0xd5, 0x4d, 0x89, 0xd3, 0xe5, 0xb2, 0x95, 0x84, 0x7d, 0xfb, 0xae, + 0x9d, 0x2a, 0xf2, 0xf8, 0x28, 0x0d, 0x79, 0x05, 0x7e, 0xca, 0x38, 0x92, 0x44, 0x89, 0xe0, 0x6d, 0xde, 0x98, 0x71, + 0x78, 0xd5, 0xa6, 0x9c, 0xda, 0x9b, 0xf5, 0x02, 0x70, 0x9e, 0xa0, 0x2d, 0x03, 0x8c, 0x05, 0x0c, 0xce, 0x85, 0x58, + 0xf2, 0x14, 0xc1, 0x2f, 0x9d, 0x48, 0x61, 0xdc, 0xe5, 0x30, 0xcc, 0x83, 0xa2, 0x77, 0x49, 0xfd, 0xd1, 0xef, 0xa3, + 0x36, 0x19, 0x0c, 0x41, 0x25, 0x80, 0xca, 0xba, 0x41, 0x62, 0x60, 0x55, 0x5a, 0x48, 0x5c, 0x42, 0xbc, 0xcc, 0x57, + 0xd3, 0x34, 0x0a, 0x1e, 0xd5, 0x13, 0x42, 0x38, 0xc1, 0xf8, 0x10, 0x37, 0x40, 0xc0, 0x60, 0x15, 0x17, 0x18, 0x24, + 0xcf, 0x25, 0xba, 0x3f, 0x9e, 0xef, 0x18, 0xe0, 0xca, 0x79, 0x4f, 0xb5, 0xab, 0x07, 0xf6, 0x72, 0x95, 0x2e, 0x19, + 0x21, 0xac, 0xf8, 0xbf, 0x88, 0xbc, 0x6f, 0x87, 0x09, 0xa8, 0x6d, 0xe4, 0x8f, 0x41, 0x62, 0x2e, 0x13, 0x45, 0x10, + 0x8f, 0xb2, 0x82, 0x25, 0x69, 0xb0, 0x19, 0x25, 0x29, 0x68, 0x34, 0x31, 0x86, 0x4c, 0x85, 0x76, 0x48, 0x1a, 0xcd, + 0xc6, 0x64, 0x1f, 0x43, 0x5e, 0xc3, 0xc5, 0x62, 0x81, 0xf7, 0xbd, 0x16, 0xaa, 0x83, 0x6d, 0x69, 0x0e, 0x01, 0x27, + 0x09, 0xf6, 0xd4, 0x15, 0x29, 0x09, 0xb3, 0xd1, 0xa7, 0x90, 0x73, 0x03, 0x3a, 0x4e, 0x1a, 0x43, 0xf5, 0x81, 0x49, + 0x78, 0x15, 0xa1, 0x93, 0xb2, 0x42, 0x58, 0xc0, 0x7d, 0x23, 0xa3, 0xd1, 0x4a, 0x1a, 0x04, 0xde, 0x66, 0xd8, 0x0a, + 0x6c, 0x42, 0xc3, 0x5f, 0x65, 0x1e, 0xa6, 0xd5, 0xac, 0x04, 0x73, 0xbe, 0x81, 0x4a, 0x8c, 0x27, 0xcb, 0x2b, 0xbe, + 0x71, 0xb1, 0x12, 0x93, 0xd9, 0x72, 0x3e, 0x59, 0x4b, 0xaa, 0xb9, 0xdc, 0x5b, 0xb3, 0x8c, 0x2d, 0x61, 0xff, 0x30, + 0xc8, 0x8f, 0x0e, 0xec, 0x68, 0xaa, 0x69, 0x93, 0x00, 0x93, 0xe9, 0x9c, 0xf3, 0xe1, 0x25, 0xa2, 0xc9, 0xea, 0xd4, + 0x9d, 0x4c, 0x55, 0x3b, 0xb8, 0x26, 0x67, 0x72, 0x7a, 0xa4, 0x9e, 0x6a, 0xdd, 0x4b, 0x3e, 0xda, 0x0e, 0xab, 0xd1, + 0xd6, 0x0f, 0xc0, 0xad, 0x53, 0xd8, 0xe9, 0xbb, 0x61, 0x35, 0xda, 0xf9, 0x1a, 0x76, 0x97, 0x14, 0x02, 0xd5, 0x97, + 0xb2, 0x26, 0x73, 0xf1, 0xba, 0xb8, 0xf7, 0x0a, 0xf6, 0xc4, 0x1f, 0xe8, 0x5f, 0x25, 0x7b, 0xe2, 0xdb, 0x4c, 0xae, + 0xbf, 0xa5, 0x5d, 0xa3, 0x31, 0xd3, 0xf1, 0xda, 0x15, 0x58, 0xa1, 0x01, 0xf2, 0x0b, 0x76, 0xb4, 0x57, 0x39, 0x08, + 0x04, 0xe8, 0x5e, 0x82, 0xa3, 0x28, 0x20, 0x6a, 0x5a, 0x55, 0x1e, 0x9d, 0xee, 0xfd, 0x3d, 0xbe, 0x11, 0x02, 0x36, + 0x79, 0x6a, 0xdd, 0x5b, 0xc6, 0xfe, 0xe1, 0x00, 0x21, 0xf4, 0x72, 0xfa, 0x8d, 0xb6, 0xac, 0x1e, 0xed, 0x58, 0xee, + 0x1b, 0x46, 0x3d, 0x05, 0x63, 0x18, 0xba, 0xb0, 0x8a, 0x91, 0x3c, 0x03, 0xb2, 0xc6, 0x6f, 0x10, 0x5d, 0xc0, 0xa2, + 0xd7, 0xfb, 0x74, 0x44, 0x83, 0x08, 0xa8, 0xf4, 0x9a, 0xa3, 0x16, 0xf9, 0x5c, 0x15, 0xa2, 0xf7, 0xde, 0xda, 0x79, + 0x33, 0x23, 0x59, 0x26, 0x8d, 0x54, 0xbb, 0x95, 0xc5, 0xba, 0xf2, 0x66, 0x27, 0xa4, 0x8b, 0x39, 0x86, 0xca, 0xe0, + 0x71, 0x00, 0x4a, 0xcf, 0x7f, 0x87, 0x5e, 0xc9, 0x90, 0x69, 0x96, 0x68, 0x66, 0x77, 0x8d, 0x3f, 0x59, 0xa5, 0x5e, + 0x8c, 0x88, 0xd9, 0xc0, 0x16, 0xe2, 0xb6, 0xa8, 0x74, 0x5b, 0x14, 0xca, 0x16, 0x45, 0xfa, 0x50, 0x3b, 0xd3, 0x9d, + 0x59, 0xf8, 0xac, 0xb2, 0x56, 0x4a, 0x66, 0xc6, 0x06, 0x68, 0xbb, 0x08, 0xdf, 0x40, 0x07, 0x2a, 0x84, 0xfc, 0x05, + 0x22, 0x22, 0x11, 0xb0, 0xcb, 0xa9, 0x3b, 0xb1, 0xe9, 0x90, 0xcc, 0x43, 0xcc, 0x0a, 0x35, 0xca, 0x4b, 0x9e, 0x1c, + 0x0d, 0x48, 0x45, 0xa8, 0xdb, 0xfd, 0xfe, 0xf9, 0xd2, 0x05, 0xb5, 0x5f, 0x53, 0xec, 0x18, 0xdd, 0x14, 0x70, 0x2e, + 0x78, 0x94, 0xf7, 0xdc, 0x3b, 0x07, 0x34, 0xc7, 0xf6, 0x14, 0x59, 0x03, 0x4e, 0x6f, 0xbb, 0x10, 0x60, 0xfb, 0xac, + 0xd9, 0xda, 0x9f, 0xac, 0xae, 0xa2, 0xa9, 0x57, 0xf2, 0x99, 0xee, 0xa2, 0xc4, 0xed, 0xa2, 0x58, 0x76, 0xd1, 0xa6, + 0x81, 0x60, 0xc7, 0x95, 0x1f, 0x00, 0x6f, 0x68, 0xd4, 0xef, 0x97, 0xad, 0x9e, 0x3d, 0xf9, 0xda, 0x71, 0xcf, 0x66, + 0x3e, 0x2b, 0x4d, 0xcf, 0xfe, 0x23, 0x75, 0x7b, 0x56, 0x4e, 0xf6, 0xa2, 0x73, 0xb2, 0x4f, 0x67, 0xf3, 0x40, 0x70, + 0xb9, 0x73, 0x9f, 0xe7, 0x53, 0x3d, 0xed, 0x2a, 0x3f, 0x68, 0x0d, 0x91, 0x35, 0x76, 0x55, 0xf7, 0xba, 0x82, 0x05, + 0x2c, 0xc1, 0xdd, 0x7a, 0x69, 0xfe, 0x1b, 0x76, 0x7f, 0x2f, 0xe8, 0xa5, 0xf9, 0xef, 0xf4, 0x27, 0x05, 0x70, 0x00, + 0x1a, 0x53, 0xbb, 0x05, 0x1e, 0x62, 0xa8, 0xa0, 0x70, 0x37, 0x2b, 0xe7, 0x5e, 0x0d, 0x70, 0x98, 0xa4, 0x6f, 0x68, + 0xf5, 0x4a, 0x8b, 0x5d, 0x2f, 0x93, 0xbd, 0x02, 0x3c, 0x54, 0x21, 0x0f, 0x0f, 0x87, 0xa8, 0x63, 0xd8, 0x41, 0x1d, + 0x01, 0xc3, 0x1e, 0x42, 0x63, 0x0b, 0x3c, 0x1f, 0x3f, 0x64, 0x7c, 0x2f, 0x40, 0x6d, 0x84, 0xf0, 0x78, 0xb5, 0x28, + 0x43, 0x6c, 0xd9, 0x2b, 0xa4, 0x92, 0x7a, 0x2d, 0x10, 0x65, 0xb4, 0x0a, 0x68, 0xab, 0x3d, 0x66, 0x69, 0xfc, 0x08, + 0xa1, 0x62, 0xa9, 0x8f, 0x21, 0x34, 0x70, 0xf8, 0x1d, 0x0e, 0x20, 0xc1, 0x97, 0x5c, 0x93, 0xcd, 0xbd, 0xca, 0xef, + 0x68, 0x9f, 0x3f, 0x1c, 0xce, 0x2f, 0x11, 0x94, 0x2e, 0x85, 0x8f, 0x54, 0x22, 0xaa, 0xa7, 0xb8, 0x29, 0x21, 0x9b, + 0x25, 0x2b, 0xfd, 0xe0, 0x1f, 0xea, 0x17, 0x00, 0xc8, 0x42, 0xa0, 0x4d, 0x64, 0xf6, 0xa7, 0x33, 0x15, 0x5d, 0x00, + 0x1c, 0xe2, 0x0f, 0x9f, 0x20, 0xfa, 0x86, 0x96, 0x69, 0xf9, 0x38, 0xe1, 0x21, 0x68, 0x6d, 0x49, 0x27, 0x11, 0x2b, + 0x05, 0x36, 0x44, 0xc2, 0xf7, 0xfb, 0xe7, 0xb1, 0xa4, 0x03, 0x8d, 0x5a, 0xdd, 0x1b, 0xb7, 0xba, 0x57, 0xbe, 0xae, + 0x3b, 0xb9, 0xf1, 0x41, 0xd1, 0x3e, 0x9b, 0x37, 0x2a, 0xdf, 0xf7, 0x75, 0xce, 0xee, 0x74, 0xef, 0xc8, 0x39, 0xf1, + 0xfd, 0x3d, 0x84, 0xa2, 0x87, 0xa6, 0xc8, 0xb2, 0x24, 0x0c, 0x68, 0xad, 0x5d, 0x7b, 0x96, 0xd1, 0xc1, 0x6b, 0xdf, + 0x10, 0x22, 0xf2, 0x14, 0x9f, 0x84, 0xdc, 0xe2, 0xf8, 0xa0, 0x40, 0xff, 0xcc, 0xf8, 0x33, 0x27, 0x7e, 0xd8, 0xea, + 0x17, 0xc0, 0xb9, 0xe9, 0xde, 0xbb, 0x13, 0xb3, 0x1e, 0x43, 0x29, 0x1b, 0xff, 0xf7, 0xfb, 0x44, 0x16, 0xe8, 0x74, + 0x44, 0xc3, 0x40, 0x70, 0x17, 0xd5, 0xff, 0xbd, 0xe2, 0x75, 0xcf, 0x5a, 0x9d, 0x2f, 0x3f, 0x75, 0x7a, 0xd2, 0xeb, + 0xa5, 0x5b, 0xe1, 0xcb, 0x30, 0xf1, 0x9d, 0xd7, 0xfd, 0x86, 0xed, 0xbe, 0xfb, 0xe5, 0xdd, 0xd1, 0xcb, 0xc0, 0x26, + 0x85, 0xef, 0x6c, 0x4a, 0x3e, 0xeb, 0x81, 0xc2, 0xaf, 0xc7, 0x7a, 0x75, 0xb1, 0xee, 0xb1, 0x1e, 0x6a, 0x01, 0xd1, + 0xc3, 0x02, 0xd4, 0x7f, 0x3d, 0xfb, 0x34, 0x14, 0x0e, 0xb2, 0x71, 0xaa, 0x40, 0x91, 0x05, 0x7f, 0x2a, 0x46, 0xeb, + 0x82, 0x00, 0x91, 0xcd, 0xf6, 0xf5, 0xa1, 0x3a, 0x99, 0x7d, 0x53, 0x6a, 0x49, 0x06, 0xdf, 0x04, 0x64, 0x76, 0x60, + 0xe5, 0x04, 0xa5, 0xe3, 0xd6, 0x80, 0x2b, 0x5b, 0xec, 0xed, 0xed, 0x4f, 0x83, 0xec, 0xac, 0x39, 0x69, 0xb4, 0x0f, + 0xfb, 0x34, 0x0f, 0x10, 0x88, 0x64, 0x2a, 0x82, 0x5c, 0x73, 0x6f, 0x49, 0x1f, 0x1d, 0xce, 0x79, 0x21, 0xff, 0x9c, + 0x4a, 0x1d, 0xe2, 0x50, 0x62, 0x0d, 0x04, 0x2a, 0xcf, 0x50, 0xe5, 0xb0, 0x41, 0x8e, 0x5f, 0x3a, 0x92, 0x99, 0xc4, + 0x64, 0x91, 0xbb, 0x35, 0x53, 0xe1, 0x07, 0x82, 0x8f, 0x59, 0xce, 0x81, 0x0b, 0x6c, 0x36, 0xf7, 0xd5, 0x14, 0x17, + 0x57, 0xe0, 0x8f, 0x29, 0xfc, 0x8a, 0xa7, 0xb0, 0xd3, 0xee, 0xd7, 0x45, 0x95, 0xa2, 0x6e, 0xa3, 0xb0, 0xa8, 0x64, + 0xc1, 0xb4, 0x86, 0x34, 0xd1, 0x61, 0xf4, 0x27, 0x39, 0x03, 0x05, 0x21, 0xbf, 0x6c, 0x1a, 0x60, 0xa4, 0x92, 0xcb, + 0x83, 0x2a, 0x09, 0xbc, 0x00, 0xdb, 0xa0, 0x62, 0xeb, 0x02, 0x82, 0x6c, 0x93, 0xa2, 0x4c, 0xbf, 0x16, 0x79, 0x1d, + 0x66, 0x41, 0x35, 0x4a, 0xab, 0x9f, 0xf5, 0x4f, 0x60, 0xde, 0xa6, 0x62, 0x54, 0xab, 0x98, 0xfc, 0x46, 0xbf, 0x5f, + 0x0c, 0x5a, 0x1f, 0x32, 0xf8, 0xe8, 0xb5, 0x69, 0xf0, 0x5b, 0xa7, 0xc1, 0x0e, 0x13, 0x8d, 0x00, 0x48, 0xe6, 0xd4, + 0x92, 0x87, 0xa2, 0x3f, 0x83, 0x1c, 0x6b, 0x54, 0x39, 0x05, 0x83, 0xf5, 0x1f, 0x8f, 0x76, 0x60, 0xea, 0xc5, 0xd1, + 0x96, 0xec, 0xa0, 0x95, 0x6f, 0x80, 0xfb, 0x35, 0xb2, 0xc5, 0x2c, 0x07, 0x68, 0xf6, 0x1a, 0x91, 0xf1, 0xc9, 0x0b, + 0x60, 0xcc, 0xd6, 0x59, 0x18, 0x89, 0x38, 0x18, 0xab, 0xc6, 0x8c, 0x19, 0x18, 0xb8, 0x40, 0xd7, 0x32, 0x29, 0x49, + 0x43, 0x3a, 0x18, 0xb0, 0x52, 0xb6, 0x70, 0xc0, 0x8b, 0xe6, 0xb8, 0x1d, 0x5f, 0x5b, 0x34, 0x1e, 0xd8, 0x2e, 0xb6, + 0xbf, 0x7b, 0x5e, 0x6c, 0xdf, 0x84, 0x5b, 0xd2, 0x2b, 0xe4, 0x2c, 0xa1, 0x9f, 0x3f, 0xcb, 0x3e, 0x6b, 0x38, 0x39, + 0x15, 0x9a, 0xa1, 0xa5, 0x48, 0x28, 0xc5, 0x3b, 0x3d, 0x29, 0x30, 0x96, 0xb1, 0xf0, 0xf7, 0xc0, 0x39, 0x5d, 0x28, + 0x22, 0x77, 0xe0, 0x38, 0xfe, 0x08, 0x15, 0x8c, 0x1a, 0x0e, 0x5e, 0xc6, 0xb0, 0x2d, 0x8a, 0x59, 0x48, 0x38, 0x85, + 0x70, 0xb1, 0xca, 0xfa, 0x7d, 0xf9, 0x8b, 0xba, 0xe8, 0x22, 0x93, 0x75, 0x9f, 0x84, 0x23, 0x33, 0x96, 0x53, 0x2f, + 0x24, 0xcf, 0x7b, 0x9e, 0x4c, 0x93, 0xc7, 0x79, 0x10, 0x01, 0xe4, 0x73, 0x78, 0x17, 0xa6, 0x19, 0x58, 0xa5, 0x49, + 0xf9, 0x11, 0x4a, 0x5f, 0x7c, 0x5e, 0xf9, 0x81, 0xce, 0x9e, 0x9b, 0x64, 0x78, 0xb3, 0x6a, 0xbd, 0x49, 0xad, 0xeb, + 0xe2, 0x01, 0xff, 0xec, 0x0c, 0x36, 0xce, 0x75, 0x26, 0x38, 0xf0, 0x22, 0xa9, 0xf5, 0x9a, 0xf1, 0xa7, 0x19, 0xae, + 0x4b, 0xd5, 0x46, 0x1f, 0x85, 0xe8, 0x1c, 0x32, 0x15, 0xa0, 0x50, 0xa4, 0xfd, 0x83, 0x52, 0x2b, 0x93, 0x4a, 0x1b, + 0x09, 0xa0, 0x7b, 0x98, 0x34, 0xd8, 0x62, 0x28, 0x63, 0x69, 0x12, 0xe5, 0x4e, 0x83, 0xb8, 0xb2, 0x1f, 0x2a, 0x89, + 0x43, 0xcb, 0x22, 0xf9, 0xf7, 0xae, 0xa7, 0xaf, 0x90, 0xba, 0x93, 0x05, 0x32, 0x63, 0x3c, 0xcb, 0xe3, 0x4f, 0x40, + 0x98, 0x0d, 0xda, 0xa8, 0x28, 0x84, 0x90, 0x0d, 0x62, 0xd0, 0x78, 0x96, 0xc7, 0xcf, 0x15, 0x8d, 0x87, 0x7c, 0x14, + 0xf9, 0xea, 0xaf, 0x52, 0xff, 0x15, 0xfa, 0xcc, 0x04, 0x8f, 0x50, 0x4d, 0xf4, 0xef, 0x9e, 0xcf, 0xee, 0x40, 0x6d, + 0x18, 0x85, 0x99, 0x29, 0xbf, 0xf2, 0x4d, 0x71, 0xf6, 0xfa, 0x2b, 0xba, 0xca, 0xb6, 0xee, 0x47, 0x2f, 0x8f, 0x08, + 0xac, 0x8d, 0xd1, 0x15, 0x37, 0x06, 0x90, 0xc3, 0xe4, 0xfd, 0x8a, 0xd2, 0x72, 0x48, 0x83, 0xd0, 0x41, 0x43, 0x18, + 0x2d, 0x89, 0x3e, 0x90, 0x58, 0xc4, 0x18, 0x5e, 0x88, 0x67, 0xa4, 0x26, 0x13, 0x0d, 0xf1, 0x8a, 0xd8, 0x0f, 0xd1, + 0x92, 0x53, 0x13, 0xdd, 0x08, 0x53, 0x0c, 0x24, 0x76, 0x06, 0xc9, 0x49, 0x52, 0x2b, 0xbf, 0x78, 0x26, 0x09, 0x4b, + 0xec, 0x3c, 0xc4, 0x60, 0x52, 0x4b, 0x77, 0x7a, 0x53, 0xa5, 0xe7, 0x47, 0x5a, 0x0e, 0xda, 0x07, 0x60, 0x97, 0x92, + 0xde, 0x3f, 0x29, 0x14, 0xf1, 0x3e, 0x8c, 0x63, 0x08, 0xdf, 0x22, 0xaa, 0x2b, 0x70, 0xae, 0x15, 0x68, 0xac, 0x06, + 0x1e, 0x9a, 0x59, 0x35, 0x1f, 0x72, 0xfa, 0xa9, 0xb4, 0xfc, 0x31, 0xa2, 0xb1, 0xd1, 0xba, 0x39, 0x1c, 0xf6, 0xb4, + 0xea, 0xa5, 0x73, 0xd0, 0x65, 0x33, 0x89, 0x89, 0x1b, 0x48, 0xd7, 0x8f, 0x7e, 0x33, 0x61, 0x2f, 0xa2, 0x42, 0x2e, + 0x85, 0xa0, 0xa0, 0xd5, 0x81, 0xc0, 0xa1, 0xf0, 0x16, 0x65, 0xbe, 0x88, 0x69, 0x03, 0x61, 0xf0, 0xf9, 0x81, 0xfc, + 0x7c, 0x53, 0x90, 0x8a, 0x1d, 0xeb, 0xda, 0xef, 0x2f, 0x4b, 0x0f, 0xf0, 0xe4, 0x4c, 0x92, 0xa7, 0xcd, 0x10, 0x56, + 0x04, 0xd0, 0x98, 0xd5, 0x64, 0x71, 0xc2, 0x95, 0x39, 0x7c, 0x59, 0x79, 0x25, 0x4b, 0x99, 0x3a, 0x4f, 0xf5, 0x02, + 0x88, 0x3a, 0xde, 0xa0, 0x15, 0xa9, 0x5f, 0xa1, 0xb3, 0xd7, 0xac, 0x84, 0x8c, 0x87, 0xe7, 0x9c, 0xa7, 0xa3, 0x7b, + 0x96, 0xf0, 0x08, 0xff, 0x4a, 0x26, 0xfa, 0xf0, 0xbb, 0xe7, 0x70, 0x33, 0x4e, 0x78, 0xe4, 0x36, 0x7b, 0x5f, 0x85, + 0x2b, 0xb8, 0x99, 0x16, 0x80, 0xe4, 0x16, 0x24, 0x4d, 0x40, 0x09, 0x89, 0x4c, 0xc8, 0xac, 0x29, 0xf9, 0x6b, 0x4b, + 0xdb, 0x60, 0x0d, 0x93, 0xce, 0x03, 0x5e, 0xb4, 0xfa, 0x68, 0x35, 0xd1, 0x2e, 0xb3, 0x7c, 0x3e, 0xc4, 0x19, 0xaa, + 0x39, 0xee, 0xce, 0xe0, 0xe7, 0x80, 0x57, 0xac, 0x6a, 0xd2, 0xd1, 0x6e, 0xc0, 0x85, 0x27, 0xd7, 0x79, 0x3a, 0xda, + 0xe2, 0x2f, 0xb9, 0x3f, 0x00, 0x74, 0x30, 0x75, 0x09, 0xfc, 0xa9, 0xda, 0x6a, 0x2a, 0xf5, 0x73, 0x6b, 0xbf, 0xae, + 0x3b, 0xab, 0x95, 0x7b, 0xd6, 0x65, 0x68, 0x8f, 0x0c, 0x39, 0x63, 0x06, 0xfc, 0x39, 0x63, 0xc9, 0x9f, 0x33, 0x56, + 0xfc, 0x39, 0xe3, 0xc6, 0xc8, 0x00, 0x4a, 0x70, 0x2f, 0xf9, 0xd3, 0x3d, 0x62, 0x86, 0x58, 0x0d, 0x2a, 0x81, 0x95, + 0xa5, 0x9c, 0xfb, 0xc8, 0x29, 0xa6, 0x9c, 0x32, 0xbc, 0x74, 0x3a, 0x73, 0x07, 0x72, 0x1e, 0xcc, 0xdc, 0x61, 0xb2, + 0xd7, 0xe7, 0x46, 0x1c, 0x4b, 0x63, 0x52, 0x54, 0x90, 0xce, 0xe9, 0x70, 0xf3, 0xea, 0x38, 0x4f, 0x58, 0xc6, 0xc7, + 0xed, 0x33, 0x05, 0x42, 0x6c, 0xf1, 0x0c, 0x89, 0x94, 0xaa, 0x59, 0x6e, 0xf3, 0x87, 0x43, 0x3d, 0xba, 0xd7, 0x3b, + 0x3d, 0xfc, 0x4a, 0xd8, 0xcf, 0x99, 0x67, 0x9f, 0x20, 0x80, 0x49, 0x22, 0xcf, 0x24, 0x1c, 0xfd, 0x58, 0x8e, 0xfe, + 0xa6, 0xe1, 0xcf, 0x33, 0x54, 0x77, 0x87, 0xc0, 0xc4, 0x96, 0x1d, 0x38, 0x04, 0xa7, 0xab, 0x4a, 0x24, 0xe0, 0x60, + 0xb3, 0x61, 0x91, 0xde, 0xe3, 0x21, 0xce, 0x07, 0x85, 0x8f, 0xd0, 0x30, 0xa3, 0xf7, 0xfb, 0x1b, 0xe1, 0x55, 0xb2, + 0x95, 0x87, 0x43, 0x62, 0x69, 0x80, 0x1c, 0x7d, 0x1c, 0xed, 0x51, 0x42, 0xed, 0x47, 0xb5, 0xde, 0x54, 0xea, 0x41, + 0x6e, 0x76, 0x21, 0x31, 0xa8, 0x58, 0xaa, 0x4f, 0xaf, 0x54, 0x1f, 0x6a, 0x96, 0x1c, 0x52, 0x1d, 0xf7, 0xa9, 0x18, + 0xad, 0xe5, 0x84, 0x00, 0xd7, 0x41, 0xa2, 0xd1, 0x01, 0x30, 0xce, 0x36, 0x5b, 0x5e, 0x6a, 0xeb, 0x44, 0xe9, 0x38, + 0xce, 0xf5, 0x71, 0x7c, 0x38, 0x48, 0x31, 0xe3, 0xf2, 0x48, 0xcc, 0xb8, 0x6c, 0x00, 0xde, 0xac, 0xf3, 0xa0, 0x3e, + 0x1c, 0x2e, 0xe9, 0x52, 0x64, 0x3a, 0xdb, 0x28, 0x3f, 0xeb, 0xd1, 0xfd, 0xe3, 0x04, 0xcd, 0xbd, 0x15, 0xf6, 0x5e, + 0x24, 0xdb, 0x33, 0x59, 0xa7, 0x5e, 0x46, 0x3e, 0xbd, 0x70, 0xcf, 0x2e, 0xb9, 0xfa, 0x61, 0xf5, 0xf5, 0xf4, 0x37, + 0xe1, 0x45, 0xac, 0xa2, 0xdd, 0xba, 0x64, 0xc2, 0xde, 0x52, 0x2a, 0x69, 0x95, 0x97, 0x4f, 0x37, 0x7e, 0x80, 0x99, + 0x69, 0x4f, 0x1f, 0x64, 0x23, 0xaa, 0x3f, 0x2b, 0x51, 0x2b, 0xc3, 0x64, 0xe1, 0xbc, 0x64, 0xea, 0xc9, 0x80, 0xc7, + 0xac, 0xe4, 0x91, 0xec, 0xf4, 0xc6, 0x20, 0x08, 0x60, 0x9d, 0x93, 0x56, 0x9d, 0x71, 0x34, 0x5a, 0x55, 0x2e, 0x4e, + 0x57, 0xb9, 0xc0, 0x70, 0xbb, 0x35, 0xdb, 0xa8, 0x3a, 0xcb, 0x4d, 0xad, 0x52, 0xbe, 0x03, 0xf8, 0x58, 0x56, 0xb9, + 0xa0, 0x63, 0xca, 0xd4, 0x79, 0x03, 0xc1, 0xd8, 0xaa, 0xc6, 0x85, 0x53, 0xe3, 0x82, 0x47, 0xd4, 0xee, 0xa6, 0xa9, + 0x47, 0x5b, 0x60, 0x29, 0x1d, 0xed, 0x78, 0x89, 0x2a, 0x85, 0x7f, 0x08, 0xbe, 0x0f, 0xe3, 0xf8, 0x79, 0xb1, 0x55, + 0x07, 0xe2, 0x4d, 0xb1, 0x45, 0xda, 0x17, 0xf9, 0x17, 0xe2, 0x80, 0xd7, 0xba, 0xa6, 0xbc, 0xb6, 0xe6, 0x34, 0xb0, + 0x35, 0x8c, 0x94, 0x14, 0xce, 0xcd, 0x9f, 0x87, 0x03, 0xad, 0xec, 0x5a, 0xdd, 0x15, 0x6a, 0x3d, 0xe6, 0xb0, 0x61, + 0x2f, 0xb2, 0x70, 0x27, 0x4a, 0x70, 0xe4, 0x92, 0x7f, 0x1d, 0x0e, 0x5a, 0x65, 0xa9, 0x8e, 0xf4, 0xd9, 0xfe, 0x6b, + 0x30, 0x66, 0xe8, 0xd2, 0x04, 0x2c, 0x1b, 0x23, 0xf9, 0x57, 0xd3, 0xcc, 0x1b, 0x26, 0x6b, 0xa6, 0x70, 0x1c, 0x1a, + 0x46, 0x48, 0x03, 0xba, 0x0d, 0x6a, 0xc3, 0x93, 0xf9, 0xa6, 0x2a, 0xbf, 0xba, 0x23, 0xd5, 0x7e, 0x30, 0xbc, 0x9c, + 0x88, 0x73, 0xba, 0x24, 0xa9, 0xa7, 0x12, 0x4a, 0x42, 0xb0, 0x4b, 0x1f, 0xc8, 0x89, 0x15, 0x90, 0xb5, 0x8c, 0xe5, + 0xb7, 0x7a, 0x40, 0xe8, 0x3f, 0xed, 0xd6, 0x0b, 0xfd, 0xa7, 0x69, 0xb6, 0x50, 0xd7, 0x1f, 0x26, 0xf7, 0x1d, 0xbd, + 0xfe, 0xe0, 0xf0, 0x4e, 0x5d, 0x55, 0x5c, 0xc5, 0xa3, 0xda, 0x30, 0xc9, 0x8d, 0xb2, 0x70, 0x57, 0x6c, 0x6a, 0xb5, + 0x3c, 0x1d, 0x87, 0x11, 0x98, 0x11, 0x14, 0x20, 0xeb, 0xba, 0x8d, 0x88, 0x61, 0x25, 0x97, 0x09, 0xf9, 0x84, 0x80, + 0x2c, 0x4a, 0x8d, 0xf3, 0x71, 0x0b, 0x54, 0x22, 0x18, 0x9c, 0x86, 0xd6, 0xaa, 0x9b, 0xfc, 0xac, 0xb2, 0xb1, 0x5b, + 0x20, 0x87, 0x24, 0x93, 0xc5, 0xed, 0xe8, 0x46, 0x2c, 0x8b, 0x52, 0xbc, 0xc6, 0x7a, 0xb8, 0x66, 0x0b, 0xf7, 0x19, + 0x10, 0xda, 0x4f, 0x94, 0xf6, 0x26, 0xd2, 0x04, 0xdd, 0xb7, 0x6c, 0x05, 0x20, 0x03, 0x28, 0xea, 0x6a, 0xb7, 0x3e, + 0xe7, 0xe7, 0x48, 0x9a, 0xe1, 0x30, 0xba, 0x7d, 0x7a, 0x1b, 0xdc, 0x0e, 0x2e, 0x51, 0x2b, 0x7d, 0xc9, 0xe2, 0x16, + 0x06, 0xd5, 0xde, 0x2c, 0xe1, 0xa0, 0x66, 0xd6, 0xda, 0x08, 0x04, 0x93, 0x3d, 0x14, 0x54, 0xcc, 0x15, 0xec, 0x83, + 0x82, 0xb5, 0xe4, 0x75, 0x70, 0xb8, 0xb5, 0x2f, 0x2b, 0xc5, 0xc5, 0x93, 0x8b, 0xa4, 0x75, 0x61, 0x29, 0x2f, 0x9e, + 0x34, 0x60, 0x70, 0x39, 0xc2, 0xa6, 0x02, 0x93, 0x04, 0x80, 0x6e, 0x45, 0x14, 0xf1, 0xa2, 0x14, 0xb6, 0xad, 0x7c, + 0xe6, 0x84, 0x0d, 0x36, 0xec, 0x1e, 0xee, 0x95, 0x41, 0xc9, 0xe0, 0x42, 0x8c, 0xdb, 0xcd, 0x2e, 0xc0, 0x15, 0x0c, + 0x85, 0xb1, 0x35, 0xff, 0x9a, 0x79, 0x91, 0x12, 0x70, 0x33, 0x44, 0xf9, 0xda, 0xc0, 0xc9, 0xa4, 0x27, 0xd7, 0x92, + 0xc5, 0x80, 0x05, 0x0d, 0xbe, 0xa3, 0xd6, 0xdf, 0x99, 0xfc, 0x1b, 0x4f, 0x0f, 0xfd, 0xe0, 0xd7, 0xcc, 0x5b, 0xfa, + 0xec, 0x6d, 0x25, 0xa3, 0x35, 0x49, 0x94, 0x57, 0x0f, 0x97, 0x20, 0x37, 0x2c, 0x47, 0xf7, 0x6c, 0x09, 0xe2, 0xc4, + 0x72, 0x94, 0x50, 0x46, 0x57, 0xb8, 0x57, 0x99, 0x2d, 0x13, 0x81, 0x14, 0x07, 0x96, 0x52, 0xee, 0x2d, 0xd6, 0xc1, + 0x12, 0xf7, 0x27, 0x92, 0x0b, 0x28, 0x79, 0x00, 0xe5, 0x4a, 0x01, 0x01, 0x9f, 0x0e, 0xa0, 0x7c, 0x29, 0x2f, 0xc2, + 0x9f, 0x38, 0x51, 0x83, 0xe5, 0xe8, 0xbe, 0x61, 0x3f, 0x7b, 0xa1, 0x65, 0x7f, 0xb8, 0xd5, 0x9a, 0x86, 0x15, 0xbf, + 0x85, 0x69, 0x31, 0x71, 0xfb, 0x72, 0x65, 0x57, 0xc5, 0x67, 0x2b, 0x75, 0x76, 0x53, 0x43, 0x12, 0xf6, 0x0d, 0x59, + 0x05, 0x38, 0x58, 0x15, 0x71, 0xcf, 0xba, 0xdc, 0x87, 0xd1, 0x97, 0x4d, 0x5a, 0x0a, 0x0b, 0x55, 0xd2, 0xdf, 0x37, + 0xa5, 0x40, 0x2a, 0x13, 0x9d, 0x68, 0x21, 0xb8, 0x02, 0x83, 0xc0, 0x9d, 0xc8, 0x6b, 0x00, 0x8c, 0x01, 0x97, 0x02, + 0x65, 0xd9, 0x96, 0x10, 0x52, 0xdd, 0xcf, 0x40, 0x6d, 0x27, 0xee, 0xd2, 0x88, 0xac, 0x85, 0xe8, 0xab, 0x60, 0xcc, + 0x9c, 0x97, 0xd2, 0x2d, 0x36, 0x5d, 0x6d, 0x56, 0x1f, 0xd1, 0xb9, 0xb4, 0xe5, 0xe6, 0x27, 0x6c, 0xb1, 0x56, 0xa0, + 0x6c, 0x42, 0xd2, 0x76, 0xce, 0x73, 0x94, 0x4d, 0x68, 0x69, 0xef, 0xa9, 0x47, 0x85, 0xea, 0x64, 0xeb, 0xa5, 0x6a, + 0x6a, 0x11, 0x56, 0x8b, 0x8b, 0xca, 0x0f, 0x40, 0x37, 0x95, 0x56, 0xcf, 0xea, 0x1a, 0x4d, 0xa1, 0x56, 0x0b, 0xc7, + 0x8d, 0x76, 0x36, 0x5d, 0xa6, 0xb7, 0x88, 0xb3, 0x2a, 0xed, 0xd0, 0xbf, 0x64, 0xda, 0xf5, 0xb2, 0xa3, 0xdf, 0x8c, + 0xab, 0x0b, 0x5c, 0x88, 0x0d, 0xf8, 0x9c, 0xfb, 0xcb, 0xeb, 0x3d, 0x89, 0x7b, 0xfe, 0xe1, 0x80, 0xec, 0x49, 0xed, + 0x0f, 0xd5, 0xc7, 0xae, 0x60, 0xc8, 0xc2, 0x28, 0xf5, 0x17, 0x29, 0xef, 0x3d, 0xc2, 0x71, 0xff, 0x5c, 0xf5, 0xd8, + 0xbf, 0x32, 0xbe, 0xaf, 0x8b, 0x4d, 0x94, 0x50, 0x54, 0x43, 0x6f, 0x55, 0x6c, 0x2a, 0x11, 0x17, 0xf7, 0x79, 0x8f, + 0x61, 0x32, 0x8c, 0x85, 0x4c, 0x85, 0x3f, 0x65, 0x2a, 0x78, 0x84, 0x50, 0xe2, 0x66, 0xdd, 0x23, 0xed, 0x26, 0xc4, + 0x29, 0xd5, 0xa2, 0x94, 0xc9, 0xf8, 0xb7, 0x7e, 0x02, 0xe5, 0x39, 0x45, 0xcb, 0xf4, 0xa3, 0xc2, 0x65, 0xfa, 0x66, + 0x7d, 0x5c, 0x7a, 0x26, 0x42, 0x9d, 0xb9, 0xd8, 0xd4, 0x3a, 0x1d, 0x63, 0xa7, 0x74, 0x6a, 0xc3, 0xbe, 0x56, 0x8a, + 0xcb, 0x8a, 0xc2, 0xbf, 0x91, 0xc8, 0xaa, 0x67, 0xc4, 0xf1, 0xdf, 0xb3, 0xf6, 0x19, 0x56, 0x81, 0x5f, 0x06, 0xf2, + 0x7e, 0x01, 0xf0, 0x71, 0x5d, 0x97, 0xe9, 0xcd, 0x06, 0x68, 0x43, 0x68, 0xf8, 0x7b, 0x3e, 0x32, 0x60, 0xba, 0x8f, + 0x70, 0x86, 0xf4, 0x50, 0xe7, 0x9c, 0xce, 0xca, 0x74, 0xce, 0x55, 0x58, 0x4b, 0xb0, 0x97, 0x93, 0x26, 0x97, 0xeb, + 0x12, 0xd4, 0x4c, 0xe0, 0xf6, 0xa1, 0x3d, 0x22, 0x84, 0xda, 0x94, 0xd5, 0xf4, 0x12, 0x6a, 0xde, 0xc9, 0x69, 0x47, + 0x93, 0x12, 0x5c, 0x35, 0x74, 0x56, 0xae, 0xff, 0x3a, 0x1c, 0x7a, 0x37, 0x59, 0x11, 0xfd, 0xd9, 0x43, 0x7f, 0xc7, + 0xed, 0xc7, 0xf4, 0x2b, 0x44, 0xcb, 0x58, 0x7f, 0x43, 0x06, 0x74, 0x3c, 0x19, 0xde, 0x14, 0xdb, 0x1e, 0xfb, 0x8a, + 0x1a, 0x2c, 0x7d, 0xfd, 0xf8, 0x08, 0x12, 0xaa, 0xae, 0x7d, 0x61, 0xf1, 0x84, 0x79, 0x4a, 0xb4, 0x2d, 0x7c, 0x08, + 0x0b, 0xfd, 0x0a, 0x91, 0x91, 0x10, 0x6e, 0x2a, 0xbb, 0x47, 0x49, 0xbb, 0xd0, 0x97, 0xbe, 0x96, 0x7d, 0xe5, 0x3b, + 0x17, 0x00, 0x2b, 0xfb, 0xc4, 0x86, 0x7b, 0xd2, 0x9f, 0x52, 0x7d, 0xd8, 0xfe, 0x96, 0x2c, 0xa0, 0xd0, 0xc2, 0x7a, + 0x2a, 0x67, 0xe7, 0x6d, 0xc9, 0xab, 0x6c, 0xba, 0x5f, 0xc3, 0x1e, 0x75, 0x87, 0x5e, 0x53, 0xc1, 0xf9, 0xa5, 0x19, + 0xbd, 0x2f, 0x86, 0x42, 0x75, 0xd4, 0xb9, 0x83, 0xdc, 0x96, 0xd6, 0x25, 0xe7, 0x37, 0x2b, 0x77, 0x14, 0xe6, 0x77, + 0x21, 0x78, 0x86, 0x75, 0xef, 0x2e, 0xce, 0x7b, 0xff, 0x68, 0xcd, 0x91, 0x7f, 0x65, 0xb3, 0x14, 0xb1, 0x48, 0xe6, + 0x60, 0xf5, 0x43, 0x3f, 0x8f, 0xfd, 0x36, 0xc8, 0xe1, 0xb8, 0x69, 0x40, 0x87, 0x0d, 0x99, 0xb5, 0x2f, 0x11, 0x38, + 0xd5, 0x08, 0xd2, 0xd4, 0x04, 0x35, 0xcb, 0x43, 0x24, 0xb6, 0x4b, 0xd9, 0x36, 0xc8, 0x75, 0x17, 0x4c, 0x73, 0xa4, + 0x3d, 0x83, 0xf7, 0x4d, 0x9a, 0xa4, 0x42, 0xb3, 0x68, 0x74, 0x25, 0xe3, 0xdf, 0x91, 0x36, 0x53, 0xb2, 0xc7, 0xd6, + 0xc0, 0x7b, 0x09, 0xca, 0xc9, 0x30, 0xc5, 0xf0, 0x1d, 0x5f, 0xef, 0x3c, 0xba, 0x88, 0xbf, 0x1d, 0xb3, 0x4d, 0xca, + 0x8e, 0x60, 0x92, 0x6c, 0x7c, 0x43, 0xf1, 0x86, 0xef, 0x6e, 0x2a, 0x51, 0x02, 0xe8, 0x65, 0xc1, 0x9f, 0x4a, 0x9b, + 0x2b, 0x74, 0xbb, 0x7b, 0x47, 0x29, 0xfc, 0x92, 0x97, 0x87, 0xc3, 0x36, 0xf5, 0x42, 0xe8, 0x7c, 0x11, 0xbf, 0x05, + 0x73, 0x18, 0x43, 0x6c, 0x46, 0x80, 0x30, 0xc7, 0x07, 0xd4, 0xc1, 0xfa, 0x11, 0x80, 0xc6, 0x09, 0x14, 0x60, 0xf4, + 0xd5, 0xb6, 0xa0, 0x6f, 0x79, 0x71, 0x11, 0x21, 0x6a, 0x14, 0x60, 0xa2, 0xa4, 0x59, 0x0c, 0xc3, 0x81, 0xce, 0xef, + 0x9b, 0x9b, 0xba, 0x14, 0x38, 0xf4, 0x8e, 0x65, 0xf8, 0x9f, 0xff, 0x63, 0x6d, 0x69, 0x55, 0xd9, 0x6e, 0x8d, 0xd3, + 0xcc, 0xff, 0x76, 0x5b, 0xa4, 0x5b, 0xa8, 0x50, 0x3c, 0xef, 0x78, 0xdd, 0xfe, 0x0c, 0xd1, 0xfb, 0xba, 0x95, 0xab, + 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x3e, 0xcd, 0xe3, 0xe2, 0x7e, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xe7, + 0xaa, 0xdf, 0xf7, 0x3e, 0x03, 0x19, 0xef, 0xb5, 0x30, 0x8e, 0x98, 0xc4, 0xc1, 0xb7, 0x17, 0xa3, 0x68, 0x53, 0xc2, + 0x86, 0xdc, 0x3e, 0x2d, 0x41, 0x33, 0xd3, 0xef, 0xa3, 0x44, 0x69, 0xcd, 0xf7, 0x7f, 0xcb, 0xf9, 0x7e, 0x2d, 0xe4, + 0xcd, 0x4a, 0x7e, 0xf8, 0x68, 0x85, 0x81, 0xef, 0x71, 0xfa, 0x55, 0xf4, 0xd8, 0xaa, 0xf4, 0xe1, 0xbb, 0xd2, 0xd2, + 0x67, 0x15, 0xf5, 0x77, 0x54, 0xd4, 0x5c, 0x8b, 0x11, 0x11, 0x0f, 0x82, 0x76, 0xb6, 0x5d, 0x6a, 0xd7, 0x12, 0xb4, + 0x0b, 0x36, 0x85, 0xd5, 0xc9, 0x43, 0x43, 0xde, 0xef, 0xbf, 0xcc, 0xbd, 0x16, 0xaf, 0xbb, 0x81, 0xbb, 0x2c, 0x3d, + 0x84, 0x00, 0xd6, 0x32, 0x50, 0xc6, 0x11, 0x26, 0x5d, 0xe4, 0x35, 0xca, 0xa6, 0x13, 0x81, 0x8f, 0x59, 0x76, 0xe5, + 0x24, 0xd3, 0x00, 0x33, 0xaa, 0x29, 0xcc, 0x04, 0x18, 0xa9, 0x0f, 0x58, 0x37, 0x3d, 0xad, 0x42, 0xcb, 0xd7, 0x10, + 0xac, 0x8b, 0x2c, 0xe3, 0x28, 0x66, 0x02, 0x80, 0xcd, 0x07, 0x90, 0xaf, 0xe8, 0xea, 0x90, 0xb4, 0x52, 0xe5, 0xfd, + 0x3a, 0x23, 0x32, 0x9a, 0x84, 0x68, 0x7e, 0x0b, 0x0f, 0xec, 0xdb, 0x66, 0x46, 0x95, 0x7a, 0x46, 0x55, 0x3e, 0xc3, + 0x61, 0x29, 0x1c, 0x23, 0xfe, 0xdf, 0x52, 0xd5, 0x23, 0x02, 0xbd, 0x2a, 0xd3, 0x2a, 0x2a, 0xf2, 0x5c, 0x44, 0x88, + 0x50, 0x2d, 0x9d, 0xc3, 0xa1, 0x1f, 0xfb, 0x7d, 0x1c, 0x08, 0xf3, 0xa2, 0x78, 0xa8, 0x2b, 0x6b, 0x5a, 0x2b, 0x29, + 0x70, 0x2a, 0x6a, 0x84, 0x08, 0xe1, 0xfd, 0x03, 0x78, 0x56, 0x53, 0xdf, 0x6f, 0x2c, 0x13, 0xdd, 0x97, 0x0c, 0x28, + 0x7f, 0x40, 0xbe, 0xae, 0xa4, 0x38, 0x93, 0x26, 0x0f, 0x89, 0x33, 0x0e, 0x40, 0xcc, 0xb7, 0x25, 0x1a, 0x8d, 0xfd, + 0x0f, 0x48, 0x30, 0x54, 0x3f, 0xd8, 0xe9, 0xa6, 0xde, 0xef, 0x99, 0xc4, 0x51, 0xf4, 0x69, 0x9b, 0x3c, 0x96, 0x2c, + 0x8d, 0x16, 0x8e, 0xde, 0x23, 0x86, 0x71, 0x38, 0x9d, 0x8f, 0x49, 0xb6, 0x31, 0x59, 0x05, 0x90, 0x4e, 0x66, 0xea, + 0x98, 0x52, 0x47, 0xe3, 0x5c, 0x2f, 0xa8, 0x42, 0x8f, 0x75, 0xc9, 0x73, 0xb0, 0x9e, 0xbc, 0xf2, 0x4a, 0x7f, 0x2a, + 0xe4, 0x1c, 0x36, 0x12, 0x41, 0xe1, 0x07, 0xb8, 0x1a, 0xac, 0x14, 0x30, 0x98, 0xfa, 0x16, 0xbe, 0x26, 0x9e, 0xa3, + 0xe0, 0x51, 0xd8, 0xc5, 0xd8, 0x5a, 0xf9, 0xce, 0x27, 0x05, 0xe5, 0x9e, 0x15, 0x73, 0x5e, 0x01, 0xe7, 0x32, 0x28, + 0x84, 0xe9, 0x78, 0x96, 0xff, 0x33, 0xc9, 0xeb, 0x89, 0x0d, 0x01, 0x32, 0xf8, 0x53, 0xe2, 0xb4, 0x74, 0x87, 0xee, + 0x3c, 0xf4, 0x2c, 0xe2, 0xb0, 0xd1, 0xa3, 0x75, 0x59, 0x6c, 0x53, 0xd4, 0x4b, 0x98, 0x1f, 0xc8, 0xcf, 0x5b, 0xf2, + 0x7d, 0x88, 0xe2, 0x6d, 0xf0, 0xb7, 0x8c, 0xc5, 0x02, 0xff, 0xfa, 0x67, 0xc6, 0x68, 0xa2, 0x05, 0x75, 0xd2, 0x20, + 0x51, 0xb1, 0x48, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe0, 0x9b, 0x15, 0xe8, + 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x74, 0x35, 0x52, 0x55, 0x8d, 0xbf, 0xa5, 0xaa, 0x1a, 0x7f, 0x4b, 0xa9, 0x1a, 0xbf, + 0x65, 0x14, 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0x5b, 0xb7, + 0x89, 0x3c, 0x33, 0x91, 0x42, 0xee, 0x0d, 0x40, 0xcd, 0xc4, 0x97, 0xb9, 0xe1, 0x94, 0x38, 0x3f, 0xf7, 0x70, 0xc5, + 0xa6, 0xd5, 0x35, 0x2d, 0x58, 0x60, 0xf3, 0x32, 0xcb, 0x33, 0x4f, 0x60, 0xdb, 0x94, 0x59, 0x3f, 0xe4, 0x1e, 0x40, + 0x30, 0x93, 0x9a, 0x00, 0x90, 0x16, 0xa2, 0x52, 0x88, 0xfc, 0x1a, 0x67, 0xf5, 0x39, 0xef, 0x6d, 0xf2, 0x98, 0x48, + 0xab, 0x7b, 0xfd, 0x7e, 0x7a, 0x96, 0xe6, 0x14, 0xd4, 0x70, 0x9c, 0x75, 0xfa, 0x4b, 0x16, 0xa4, 0x89, 0x5c, 0xa5, + 0xff, 0x74, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, 0x0b, 0x04, 0x77, 0x72, + 0xec, 0x27, 0xab, 0x52, 0x1e, 0x19, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, 0xfa, 0xbd, 0xd4, 0xd3, + 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, 0x87, 0xfb, 0xdc, 0x92, + 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, 0xfb, 0x7d, 0xf5, 0xf7, + 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, 0xb9, 0x8d, 0xa3, 0xad, + 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, 0x2b, 0x23, 0x2d, 0x3c, + 0x7f, 0x8a, 0xbf, 0x16, 0x75, 0x81, 0xe1, 0x19, 0xb4, 0x46, 0x2b, 0x08, 0x26, 0xf8, 0x67, 0x07, 0xea, 0xa5, 0x95, + 0xf6, 0x01, 0x74, 0x2b, 0xd0, 0x83, 0x86, 0x93, 0x38, 0x69, 0x5f, 0x48, 0xd4, 0xed, 0xad, 0x4e, 0xa3, 0x3f, 0x2b, + 0x96, 0xf3, 0x02, 0x26, 0x87, 0x1b, 0xfa, 0xb4, 0x0a, 0xb7, 0x9f, 0xe0, 0xe9, 0x6b, 0xa0, 0xdc, 0x3a, 0x1c, 0x72, + 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x2e, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x43, 0xd0, 0xde, 0x05, 0xe8, 0x80, + 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, 0x9e, 0xe5, 0x53, 0xb5, + 0xd2, 0xce, 0xa2, 0xc4, 0xab, 0x59, 0x06, 0xce, 0x02, 0x17, 0x95, 0xcf, 0x32, 0xad, 0x7a, 0x2a, 0x13, 0xf4, 0x79, + 0x25, 0x27, 0xb8, 0x12, 0x9c, 0x6c, 0x40, 0x7e, 0x01, 0x92, 0x34, 0xa5, 0xac, 0x29, 0x9f, 0x5e, 0xd2, 0x0d, 0x19, + 0x3d, 0xe7, 0x3d, 0x2f, 0x1a, 0x86, 0xfe, 0x85, 0x57, 0x42, 0xf8, 0x26, 0x6e, 0xdb, 0x28, 0x85, 0xfd, 0x4d, 0x60, + 0xf1, 0x09, 0x7b, 0xe5, 0x2d, 0xfd, 0xe9, 0x38, 0x08, 0x87, 0xc8, 0x0d, 0x15, 0x73, 0x60, 0x4f, 0x03, 0x16, 0x9b, + 0xf8, 0x6a, 0x33, 0x89, 0x07, 0x03, 0x5f, 0x67, 0x2c, 0x66, 0x31, 0xd0, 0x20, 0xc7, 0x83, 0xcb, 0xb9, 0x3e, 0x21, + 0xf4, 0xc3, 0x88, 0xca, 0x51, 0x81, 0xce, 0x41, 0x34, 0x58, 0x02, 0x9e, 0x7a, 0x2b, 0x1b, 0x24, 0x19, 0xc7, 0x90, + 0xc4, 0xb5, 0x26, 0xa9, 0x0e, 0x27, 0xb4, 0x0e, 0x74, 0x5c, 0x5d, 0x40, 0xe7, 0xe3, 0xba, 0xf7, 0xf1, 0x6a, 0xb8, + 0xa0, 0xd2, 0x2f, 0xc4, 0xc0, 0xab, 0xa7, 0xe3, 0xe0, 0x92, 0x6e, 0x85, 0x8b, 0x55, 0xb8, 0x7d, 0x2d, 0x1f, 0x38, + 0xee, 0xa8, 0xa4, 0x21, 0x30, 0x78, 0x7b, 0xe8, 0x6e, 0x66, 0xbc, 0x43, 0x8e, 0x0e, 0xe3, 0x4c, 0x0e, 0xb1, 0x6a, + 0xc5, 0x85, 0xf4, 0x46, 0xf0, 0xed, 0x42, 0x31, 0x96, 0x8d, 0x5d, 0x1a, 0x8a, 0xc2, 0xbf, 0x01, 0xd8, 0xa1, 0xf6, + 0x57, 0x2a, 0xf9, 0x18, 0x19, 0xd5, 0x34, 0xd0, 0x31, 0x00, 0x4b, 0x96, 0x26, 0x92, 0x2a, 0xd2, 0x48, 0xfc, 0x91, + 0x35, 0xd6, 0x4d, 0xd7, 0x17, 0x4c, 0x55, 0xc3, 0xa4, 0xdb, 0x99, 0xc4, 0x72, 0x22, 0x49, 0x6d, 0xf7, 0x11, 0x31, + 0x18, 0xf8, 0x60, 0x23, 0xa6, 0x99, 0x08, 0x47, 0x3c, 0x2a, 0x91, 0x45, 0x97, 0xdf, 0x46, 0x94, 0xb4, 0x7d, 0x59, + 0x91, 0x2d, 0x08, 0xa6, 0x27, 0xd1, 0x07, 0x49, 0xca, 0xa9, 0x48, 0xa4, 0x19, 0x21, 0xc0, 0x8f, 0x27, 0xe5, 0x95, + 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, 0x63, 0xd5, 0x60, 0x80, 0xe5, + 0x54, 0x8f, 0x1d, 0x93, 0xf4, 0xdf, 0x3a, 0x9d, 0xb0, 0x9f, 0x79, 0xb9, 0xad, 0xe5, 0x4d, 0x73, 0xef, 0x99, 0x57, + 0xb1, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, 0x3f, 0x80, 0xb4, 0x47, 0xba, + 0xbc, 0x6a, 0x98, 0x33, 0xc1, 0xa3, 0x0b, 0x6b, 0x1e, 0x44, 0x17, 0xc2, 0x47, 0x2e, 0xbb, 0x49, 0x72, 0x35, 0x9e, + 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0xb1, 0x90, 0x03, 0x69, 0x74, 0x54, 0x05, 0x58, + 0x2c, 0xb3, 0xab, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, 0xee, 0xb3, 0x13, 0x05, 0x59, + 0x6d, 0xce, 0x5a, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0x27, 0x46, 0x3e, 0xa2, 0x4e, 0x4f, 0x61, + 0x04, 0x04, 0xbf, 0x9c, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, 0x8a, 0xe1, 0x25, 0xb0, 0x8b, + 0xe7, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0xbb, 0x44, 0xa2, 0xa9, 0xc4, 0xd1, 0x18, 0x39, 0x95, 0xc6, 0xc8, 0x80, 0xd8, + 0xc5, 0xf1, 0xef, 0x29, 0x3d, 0x0a, 0x52, 0xf6, 0xbc, 0x32, 0xc4, 0xe1, 0x28, 0xbe, 0x82, 0x55, 0xe3, 0x70, 0xa8, + 0xcd, 0xeb, 0xe9, 0xac, 0x9e, 0x0f, 0x44, 0x00, 0xff, 0x0d, 0x05, 0xfb, 0x55, 0x53, 0x91, 0x1b, 0xa4, 0xce, 0xc3, + 0x21, 0x05, 0xf9, 0xd4, 0x58, 0x65, 0x2b, 0x77, 0x3f, 0x9d, 0xcd, 0xad, 0x39, 0x7a, 0x51, 0xe3, 0xba, 0xb5, 0xba, + 0xa1, 0x90, 0x68, 0x4d, 0x93, 0xe2, 0xaa, 0x9a, 0x14, 0x03, 0x9e, 0xfb, 0x42, 0x75, 0xb1, 0x35, 0x82, 0x85, 0x3f, + 0xb7, 0x40, 0x98, 0xf4, 0xb7, 0xe2, 0x0e, 0xa9, 0x1a, 0x77, 0x6d, 0xb5, 0xdb, 0x56, 0x36, 0xa4, 0x68, 0x3e, 0xbc, + 0x84, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0xba, 0x10, 0x79, 0x4c, 0xbf, 0x42, 0x7e, 0x29, + 0x86, 0x7f, 0x95, 0xee, 0xcd, 0xa9, 0x0d, 0x72, 0x00, 0xdb, 0xbd, 0x87, 0xdb, 0x31, 0x7a, 0x20, 0x83, 0x37, 0x42, + 0xce, 0x39, 0xbf, 0x9c, 0x5a, 0x33, 0x26, 0x1a, 0x16, 0xac, 0x1c, 0x46, 0x7e, 0x80, 0x8c, 0x97, 0x53, 0x60, 0x65, + 0x3f, 0x2a, 0xe2, 0xd2, 0x1f, 0x46, 0xfe, 0xc5, 0x93, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, + 0x4f, 0x58, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x4f, 0xcb, + 0x41, 0xe8, 0xfb, 0x66, 0xe7, 0x30, 0xc6, 0x64, 0x79, 0x84, 0xfd, 0x0c, 0x6e, 0xbb, 0x5a, 0x62, 0x06, 0x93, 0xcd, + 0x6d, 0xc4, 0x0c, 0xb6, 0xfc, 0xc5, 0x13, 0xc3, 0x25, 0x54, 0x3d, 0x95, 0x9a, 0x8d, 0x02, 0xcd, 0xc9, 0x15, 0x9a, + 0x93, 0x95, 0x50, 0x4b, 0x3e, 0xa9, 0x70, 0xc2, 0xce, 0x27, 0xb9, 0xb2, 0x1b, 0x8d, 0x31, 0x70, 0xd1, 0xde, 0x9a, + 0x84, 0x91, 0x99, 0xce, 0x52, 0x34, 0x60, 0xe1, 0x99, 0x38, 0xa5, 0x31, 0xa0, 0x7d, 0x39, 0xb0, 0xb4, 0x21, 0xbf, + 0xc8, 0x99, 0x81, 0xb6, 0x21, 0xa5, 0x51, 0x33, 0xf0, 0x67, 0x6a, 0xc2, 0xfc, 0x06, 0x56, 0x22, 0x88, 0xea, 0x02, + 0x4c, 0x92, 0x9c, 0x8c, 0x46, 0xca, 0x4a, 0x24, 0xe7, 0x80, 0xf7, 0x01, 0x3c, 0x59, 0xc4, 0xb6, 0xf6, 0xa7, 0xf4, + 0xbf, 0x3a, 0x7c, 0x2e, 0xfd, 0xc7, 0x02, 0x58, 0xc8, 0xa5, 0x41, 0x64, 0xa0, 0x70, 0x48, 0x2d, 0xc7, 0x98, 0xc4, + 0xf1, 0x0c, 0x7c, 0x09, 0x17, 0x68, 0x0a, 0xe8, 0x0f, 0x6a, 0x46, 0x11, 0x59, 0xf8, 0xab, 0x67, 0x37, 0x75, 0xad, + 0xe7, 0x99, 0xf3, 0x1a, 0x34, 0x33, 0x10, 0xd2, 0xe3, 0x54, 0xbd, 0x0d, 0x89, 0xce, 0xcb, 0xb7, 0xfa, 0x65, 0x42, + 0x24, 0x0b, 0x23, 0x4f, 0xdf, 0xe7, 0x60, 0x1e, 0x51, 0x84, 0x0e, 0xae, 0xcc, 0xc3, 0xe1, 0x5c, 0x50, 0xf8, 0x8e, + 0xf2, 0x7c, 0xc0, 0x69, 0x96, 0x24, 0xa0, 0x0d, 0x64, 0xb9, 0x29, 0x73, 0x95, 0xb4, 0x4c, 0xdd, 0x7b, 0xb0, 0x12, + 0x54, 0xe8, 0xe6, 0x14, 0x14, 0xca, 0x48, 0x50, 0x4a, 0xab, 0x41, 0x28, 0xd5, 0x61, 0x11, 0x44, 0x0e, 0x59, 0x08, + 0xb8, 0x99, 0x8a, 0x46, 0x4b, 0x1a, 0x1e, 0xe1, 0xdc, 0x40, 0x21, 0x00, 0x89, 0x3d, 0x55, 0x94, 0x71, 0x39, 0x04, + 0x7c, 0x94, 0x70, 0x88, 0xb3, 0x26, 0x6d, 0x79, 0x0e, 0xe2, 0x58, 0x2e, 0xf9, 0x6d, 0x85, 0x60, 0x10, 0xa1, 0xcf, + 0x90, 0x3f, 0x59, 0xce, 0xbf, 0x1b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xcc, 0x27, 0x10, + 0xdf, 0x72, 0x33, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xdb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, + 0xd3, 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x13, 0xc8, 0x1a, 0xac, 0xf9, 0xf3, 0x8a, + 0x9c, 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xed, 0xaa, 0x2c, 0x4f, 0x56, 0x65, 0xb8, + 0x1a, 0x74, 0x55, 0x65, 0xc9, 0x91, 0xda, 0x00, 0xad, 0xe9, 0x0a, 0x31, 0x14, 0xb2, 0x06, 0x4b, 0xab, 0x2a, 0x6b, + 0xea, 0x13, 0x08, 0xf4, 0x01, 0x96, 0x51, 0xb3, 0x9f, 0x0e, 0x7f, 0x09, 0x7e, 0x51, 0x21, 0x4b, 0x75, 0x5a, 0x67, + 0xe2, 0xb7, 0x60, 0xc9, 0xf0, 0x8f, 0xdf, 0x83, 0x35, 0x60, 0x09, 0x90, 0xe5, 0x6e, 0x63, 0xa3, 0xf5, 0xaa, 0xf8, + 0xb9, 0x5a, 0x5f, 0xf4, 0x5b, 0xb7, 0x89, 0x5a, 0x01, 0x46, 0x28, 0xb4, 0x08, 0xb0, 0xd5, 0x03, 0xf7, 0x14, 0xfc, + 0x40, 0x0c, 0xe7, 0x9a, 0xb4, 0xa6, 0x4e, 0x78, 0x9d, 0x8d, 0x23, 0x11, 0xd5, 0x5b, 0xb8, 0xb8, 0xd7, 0x5b, 0x8b, + 0xbf, 0x51, 0x81, 0x00, 0xc8, 0x62, 0x8a, 0xb5, 0xf3, 0x86, 0xf4, 0xca, 0xb0, 0x93, 0xd0, 0x7b, 0xc3, 0x4e, 0x20, + 0x2f, 0x0e, 0x3b, 0x85, 0x2e, 0xd1, 0x76, 0x8a, 0xd4, 0x44, 0xdb, 0x49, 0x8b, 0x55, 0x58, 0x42, 0xf0, 0xab, 0xf6, + 0xd6, 0x51, 0xb6, 0x2f, 0xb2, 0x84, 0x69, 0x0b, 0x18, 0xe5, 0x56, 0x7d, 0xe6, 0x14, 0xb1, 0x52, 0xf6, 0x4e, 0x27, + 0x55, 0xee, 0x22, 0x9f, 0x5a, 0x4d, 0x91, 0xc9, 0xcf, 0x8f, 0x5b, 0x24, 0x9f, 0xbc, 0x6e, 0x37, 0x4c, 0xa6, 0x7f, + 0x38, 0xfa, 0x02, 0xba, 0x22, 0x3b, 0x7d, 0x02, 0x01, 0x99, 0x0a, 0xaa, 0xd5, 0xad, 0x62, 0x9a, 0xb7, 0xab, 0xec, + 0xf6, 0x42, 0x89, 0xe1, 0x74, 0x76, 0x12, 0x1e, 0x6d, 0x86, 0x0c, 0x1c, 0x82, 0x40, 0x21, 0x54, 0x14, 0xc3, 0x23, + 0x50, 0x6b, 0x24, 0x1f, 0xe0, 0x47, 0xbb, 0x53, 0x41, 0xa4, 0x76, 0x53, 0x71, 0xe3, 0xe4, 0xa6, 0xeb, 0xa5, 0x40, + 0xad, 0x53, 0xb2, 0x02, 0x28, 0x21, 0xea, 0x4f, 0x62, 0x5b, 0x5f, 0xc3, 0x15, 0x9b, 0xef, 0x1b, 0x45, 0x4f, 0xae, + 0x4f, 0x51, 0xb7, 0xe2, 0xea, 0x34, 0x6d, 0x35, 0xc7, 0x8e, 0x33, 0xe4, 0xe0, 0x59, 0x41, 0xb0, 0x1d, 0x95, 0x28, + 0xdf, 0xb4, 0x9b, 0x8e, 0x89, 0xad, 0xfe, 0x59, 0x54, 0x9b, 0x5b, 0xa8, 0x88, 0x88, 0x8f, 0xb2, 0x9b, 0x27, 0xed, + 0x77, 0xb0, 0xc7, 0x5a, 0x0d, 0x22, 0xfb, 0x0c, 0xae, 0x72, 0x9d, 0x16, 0xb9, 0x2d, 0x83, 0xf3, 0x0f, 0xaf, 0x76, + 0x15, 0x36, 0x39, 0xd6, 0xd5, 0xd5, 0x4c, 0x75, 0x52, 0xb1, 0x81, 0xb1, 0xa6, 0xb5, 0x54, 0xf3, 0x18, 0x92, 0xee, + 0xca, 0xe2, 0xac, 0x4a, 0xba, 0xe9, 0xb9, 0x71, 0xa6, 0x10, 0x03, 0x67, 0xab, 0xd1, 0x72, 0x86, 0x21, 0xba, 0x3e, + 0xcc, 0x12, 0xbf, 0xd5, 0x53, 0xee, 0xf3, 0x70, 0xeb, 0x77, 0xf5, 0x82, 0x93, 0xc9, 0x7e, 0x72, 0x9c, 0xbb, 0x5d, + 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0xe2, 0x56, 0xd4, 0xbf, 0x54, 0x00, 0x34, 0xb8, 0xc9, 0x63, 0x89, + 0x52, 0xbf, 0x57, 0xd5, 0x0f, 0x6a, 0xa6, 0x6a, 0x1a, 0x08, 0xe6, 0x54, 0x0a, 0xf8, 0xc3, 0xed, 0xc2, 0x15, 0x8f, + 0xb8, 0x61, 0x61, 0xfc, 0xe2, 0xd5, 0xec, 0x54, 0x50, 0x19, 0xb8, 0x19, 0x7f, 0xf1, 0x04, 0x3b, 0x85, 0xb5, 0x02, + 0xb2, 0xc2, 0x17, 0x2f, 0x7f, 0xe0, 0xfd, 0x8a, 0x7f, 0xf1, 0xaa, 0x07, 0xde, 0x47, 0x9c, 0x97, 0x2f, 0x48, 0xea, + 0x84, 0xa8, 0x2e, 0x5f, 0x08, 0x53, 0x6c, 0x95, 0xe6, 0x2f, 0x48, 0xe1, 0x13, 0x7c, 0x06, 0xbe, 0xc3, 0x55, 0xb8, + 0x35, 0xbf, 0xc1, 0x63, 0xc7, 0x62, 0xdb, 0xa5, 0xbe, 0x80, 0x72, 0x04, 0x16, 0x91, 0xdb, 0x6f, 0x57, 0xf6, 0xab, + 0x85, 0x51, 0xc6, 0xd8, 0x7d, 0xc9, 0x4a, 0x94, 0xce, 0xfa, 0xfd, 0x42, 0x0a, 0x46, 0x76, 0x61, 0x8d, 0xf6, 0x28, + 0x55, 0xaf, 0xbe, 0x09, 0xeb, 0x28, 0x49, 0xf3, 0x5b, 0x19, 0x7d, 0x24, 0xc3, 0x8e, 0xf4, 0x95, 0x94, 0x68, 0xaf, + 0x55, 0x58, 0x8e, 0x66, 0xbf, 0x2e, 0x39, 0x50, 0x5e, 0xb7, 0x82, 0xf2, 0x55, 0x13, 0x40, 0xaf, 0x54, 0xfb, 0x0c, + 0xb4, 0x82, 0xc2, 0x52, 0x79, 0xb0, 0x12, 0xe7, 0xa2, 0xcf, 0x8a, 0xc3, 0x41, 0x5d, 0x0c, 0x09, 0x05, 0xaa, 0xc4, + 0x49, 0x68, 0xc4, 0x73, 0xb8, 0x10, 0x8a, 0xa7, 0x39, 0xc6, 0x56, 0xe4, 0xc0, 0x81, 0x0c, 0x3f, 0x20, 0xf0, 0x5e, + 0xf6, 0xaf, 0x60, 0x30, 0x4c, 0x70, 0x23, 0xa3, 0x4e, 0xce, 0xd9, 0x17, 0x0c, 0xcc, 0xa0, 0x9e, 0xd4, 0xee, 0xb3, + 0x7b, 0x15, 0xd8, 0x0b, 0x67, 0x40, 0x7b, 0x37, 0x46, 0x3f, 0xab, 0x62, 0xed, 0xa4, 0x7f, 0x2a, 0xd6, 0x90, 0x4c, + 0x87, 0xc5, 0xd1, 0x36, 0x0d, 0x8f, 0xe4, 0xc9, 0x71, 0xbc, 0xe9, 0x1f, 0x0e, 0x63, 0xfc, 0x38, 0xca, 0xaf, 0x2d, + 0xe0, 0x55, 0xdc, 0x42, 0x1a, 0x8b, 0x14, 0xbd, 0x03, 0x31, 0x87, 0xa2, 0x97, 0xec, 0xb7, 0x8c, 0x97, 0x13, 0x41, + 0x29, 0x49, 0x6c, 0x78, 0x47, 0x7a, 0x9a, 0xd6, 0xa3, 0xad, 0x0c, 0xd8, 0xaf, 0x47, 0x3b, 0xfa, 0x0b, 0x14, 0x8f, + 0x16, 0xfe, 0x92, 0xfe, 0x2e, 0xee, 0xe6, 0x9e, 0xf3, 0x4d, 0xe3, 0x3b, 0xe2, 0x02, 0xc5, 0x9a, 0xdd, 0x5f, 0xd3, + 0xd2, 0x59, 0x07, 0x82, 0x03, 0xde, 0x62, 0x17, 0xed, 0xfb, 0x8d, 0xeb, 0xf4, 0xb4, 0xff, 0xde, 0xad, 0x51, 0xbe, + 0xf7, 0x8b, 0x44, 0x39, 0xd8, 0xbf, 0x70, 0xd1, 0xfc, 0xed, 0xa7, 0x0c, 0x49, 0x85, 0xe6, 0x06, 0xdb, 0xc9, 0x16, + 0x61, 0x6d, 0x8c, 0x83, 0x8a, 0xdd, 0x96, 0x61, 0x04, 0x0c, 0xea, 0xd8, 0xff, 0xe8, 0xb3, 0x69, 0x43, 0xf6, 0x01, + 0xa0, 0x72, 0x15, 0x02, 0xf6, 0x00, 0x9c, 0x68, 0x84, 0x1b, 0xe0, 0x56, 0xa3, 0x25, 0x1d, 0xd4, 0x6d, 0xc1, 0x40, + 0xb4, 0x84, 0x8d, 0xbc, 0xed, 0xea, 0xf4, 0x0d, 0xe1, 0x43, 0xed, 0xa4, 0x74, 0x28, 0x7f, 0xf3, 0x9c, 0xfd, 0xcf, + 0x0e, 0x6b, 0x6a, 0xca, 0x47, 0xc0, 0xcc, 0x59, 0x89, 0xbc, 0x42, 0xe8, 0x14, 0xf9, 0xbd, 0xaa, 0x2b, 0x31, 0x5c, + 0xd6, 0xa2, 0xec, 0xcc, 0x6e, 0x9d, 0xe8, 0x9d, 0x53, 0x50, 0x4b, 0x65, 0x83, 0x9c, 0xa4, 0xda, 0x7c, 0x64, 0xad, + 0xa0, 0x44, 0x5d, 0xa3, 0xc0, 0xf1, 0x29, 0xd7, 0xee, 0xff, 0x9d, 0x33, 0x41, 0xcd, 0x36, 0xaa, 0xfb, 0x0b, 0xfd, + 0x54, 0xd5, 0x24, 0x16, 0xe0, 0x72, 0x92, 0xe6, 0x1d, 0x8f, 0xb0, 0xfa, 0xc7, 0xc9, 0x52, 0x04, 0xfa, 0x14, 0xd1, + 0xae, 0x04, 0x24, 0x68, 0x27, 0x67, 0xa1, 0x22, 0x50, 0xa0, 0xaf, 0x3f, 0xdf, 0xa4, 0x59, 0x2c, 0x57, 0xb3, 0x3d, + 0x4c, 0x94, 0xc5, 0x7a, 0x88, 0x20, 0x67, 0xa6, 0x0e, 0xf6, 0x7b, 0x9a, 0xd1, 0x2c, 0xbc, 0x32, 0x25, 0xb8, 0x14, + 0x57, 0x51, 0x91, 0x83, 0xcf, 0x21, 0xbe, 0xf0, 0xa9, 0x90, 0x1b, 0x44, 0x34, 0xfd, 0x59, 0xa2, 0xda, 0x91, 0x02, + 0x39, 0x94, 0xfc, 0x84, 0xf8, 0x4b, 0xd6, 0xc6, 0xb8, 0x5f, 0x3a, 0xd5, 0xbe, 0x56, 0x08, 0xee, 0xaf, 0x6d, 0xb1, + 0x51, 0xe5, 0x89, 0x1e, 0x7c, 0x8a, 0xf5, 0x3f, 0x59, 0x40, 0xa9, 0xee, 0xdb, 0xe0, 0x54, 0x3c, 0x0a, 0x37, 0x75, + 0xf1, 0x11, 0xa1, 0x05, 0xca, 0x51, 0x55, 0x6c, 0xca, 0x88, 0x38, 0x61, 0x37, 0x75, 0xd1, 0xd3, 0x1c, 0xe8, 0xd4, + 0x61, 0xe0, 0x80, 0x9a, 0x28, 0x11, 0xc5, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0x3c, 0x93, 0xa5, 0x83, 0xac, 0x13, + 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x65, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, + 0x65, 0xeb, 0xb7, 0x5a, 0xed, 0x8d, 0xd5, 0xa3, 0x92, 0x35, 0xc7, 0xd9, 0x84, 0xa4, 0xf4, 0x09, 0xdb, 0xcd, 0xa4, + 0x6b, 0x1d, 0x78, 0x12, 0x5c, 0x0e, 0x3d, 0x01, 0x15, 0x83, 0x26, 0xde, 0xee, 0x02, 0xf5, 0x08, 0x3c, 0x03, 0xe5, + 0x13, 0xb5, 0x0e, 0xf8, 0x79, 0xad, 0xe5, 0x29, 0x23, 0x0c, 0xab, 0x9d, 0x45, 0xcb, 0xc1, 0x79, 0xa7, 0x08, 0x5c, + 0xbb, 0x12, 0x78, 0x3e, 0x54, 0xef, 0x85, 0x80, 0xe1, 0xfe, 0xa9, 0x50, 0xd9, 0xec, 0x66, 0x38, 0x8f, 0x1a, 0xa7, + 0x07, 0xda, 0xdb, 0xae, 0xf5, 0x50, 0xef, 0xba, 0x9d, 0xdb, 0x4a, 0xf7, 0x7e, 0xed, 0x64, 0xd2, 0x05, 0xb4, 0x36, + 0x9f, 0x7d, 0x67, 0x57, 0x5a, 0x37, 0x3d, 0x67, 0x0f, 0xb6, 0x6e, 0x89, 0xce, 0x05, 0xd1, 0xe4, 0xf7, 0x03, 0xcf, + 0xda, 0x76, 0xf4, 0xdb, 0xb4, 0x63, 0x9b, 0x7b, 0xa8, 0x7b, 0x05, 0xb5, 0xde, 0xd0, 0xbc, 0x7f, 0xe6, 0xda, 0x76, + 0x7c, 0xf5, 0xeb, 0xba, 0xc3, 0x75, 0xde, 0x04, 0xc7, 0x4d, 0xd7, 0xb6, 0xda, 0xd9, 0xcf, 0xdd, 0xbd, 0xb5, 0x88, + 0xc2, 0x2c, 0xfb, 0xb9, 0x28, 0xfe, 0xac, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x3d, 0x61, + 0x3c, 0x79, 0xf5, 0x11, 0xd1, 0xad, 0xef, 0x33, 0xf7, 0x2b, 0xc0, 0x8d, 0xe0, 0x0e, 0xa2, 0xbd, 0x5b, 0xea, 0x93, + 0x5a, 0x7d, 0xad, 0xd7, 0xce, 0xd3, 0xf3, 0x9b, 0xce, 0xed, 0x77, 0xdf, 0x1c, 0x6d, 0xbd, 0xc7, 0x85, 0xb5, 0xb2, + 0xf4, 0x54, 0x15, 0xec, 0xcd, 0xf2, 0x54, 0x15, 0x4c, 0x1e, 0x78, 0xcd, 0x7e, 0x41, 0x83, 0x2b, 0x1d, 0x6d, 0xbc, + 0x27, 0x6a, 0xe0, 0x16, 0x85, 0xa5, 0xc3, 0x2f, 0xb9, 0x99, 0x5c, 0xe3, 0xfe, 0x52, 0x91, 0x8b, 0x7d, 0xe7, 0x8c, + 0xee, 0xcc, 0xac, 0x7b, 0x55, 0xe1, 0x6a, 0x41, 0xae, 0x0e, 0x6c, 0x2d, 0xbb, 0x38, 0xdc, 0xb0, 0x88, 0x02, 0x04, + 0x62, 0x7a, 0xa5, 0xd6, 0xfe, 0x88, 0x06, 0x21, 0x1f, 0x0c, 0xfc, 0x02, 0x83, 0x55, 0x81, 0xc2, 0x07, 0x8a, 0xe4, + 0x2f, 0x3c, 0x01, 0xbb, 0x78, 0x06, 0xe8, 0x56, 0x6c, 0x56, 0x8c, 0x10, 0x21, 0x93, 0xe5, 0xac, 0xa6, 0x33, 0xc8, + 0xa7, 0xbe, 0xf8, 0xce, 0x56, 0x9d, 0xce, 0xdb, 0x9a, 0x2a, 0xa7, 0x0e, 0x85, 0xee, 0x6e, 0xea, 0xce, 0xad, 0x8b, + 0x3c, 0x75, 0x08, 0xb9, 0x52, 0xb1, 0x12, 0xd3, 0x50, 0xf3, 0x24, 0xcd, 0xa8, 0xbf, 0xda, 0xfb, 0xbd, 0x46, 0xe1, + 0x94, 0x3f, 0x1d, 0x83, 0x2a, 0x5c, 0xd5, 0x10, 0xc7, 0x52, 0x15, 0x8f, 0x6c, 0x10, 0x68, 0x5e, 0xdd, 0xaa, 0xa4, + 0x09, 0x99, 0xdc, 0x08, 0x9f, 0x9a, 0x94, 0xf2, 0x34, 0x6d, 0xd2, 0x4a, 0x91, 0x3a, 0xf8, 0xa0, 0x4e, 0x35, 0x9e, + 0x9b, 0xd5, 0x53, 0x00, 0x33, 0xce, 0xaf, 0xf8, 0xa5, 0xe2, 0x32, 0x6a, 0x2b, 0x33, 0x69, 0x7f, 0x72, 0x34, 0x36, + 0xea, 0x72, 0xaa, 0xcc, 0x2b, 0x06, 0x7d, 0xfa, 0xb5, 0x3e, 0xff, 0x80, 0xc1, 0x9a, 0x27, 0xb0, 0x83, 0x89, 0x4a, + 0x79, 0x1f, 0x01, 0xf1, 0x75, 0x92, 0xde, 0x26, 0x90, 0x22, 0xfd, 0x4b, 0x97, 0x3c, 0x75, 0x18, 0x1b, 0x88, 0x31, + 0x2b, 0x66, 0x46, 0xff, 0x83, 0xbb, 0xa4, 0x3f, 0x09, 0x01, 0x70, 0x13, 0x4d, 0xa1, 0x53, 0xe7, 0xc9, 0x45, 0x1e, + 0x2c, 0x2f, 0x3c, 0xb4, 0x62, 0xc4, 0x83, 0xbf, 0x3e, 0x0d, 0x11, 0xc4, 0x1c, 0x53, 0x3c, 0xfd, 0xc2, 0xe8, 0x2f, + 0xc1, 0x25, 0x46, 0x10, 0xba, 0x7b, 0xe7, 0x30, 0x84, 0x9b, 0x3d, 0xc8, 0xa0, 0xfe, 0x50, 0x87, 0x44, 0x0d, 0x7f, + 0xa9, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, 0x7d, + 0xe2, 0xc7, 0xf1, 0x60, 0xf3, 0x78, 0x03, 0xd6, 0xba, 0x67, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, 0xa6, + 0xb5, 0xe7, 0xb5, 0xdb, 0x3d, 0xf8, 0xab, 0x7f, 0x11, 0x32, 0x60, 0xe2, 0xf4, 0x7d, 0xe6, 0x64, 0x8d, 0x2e, 0x32, + 0x99, 0x3e, 0x74, 0xd2, 0x37, 0x3a, 0xdd, 0x77, 0xc2, 0x3f, 0x2a, 0x66, 0xf1, 0xe1, 0x96, 0xbe, 0xd2, 0xa4, 0xb8, + 0x03, 0x56, 0x36, 0x0f, 0x0a, 0x42, 0x9d, 0x8b, 0xe8, 0x1b, 0x53, 0xbe, 0x25, 0xd4, 0xec, 0x1b, 0x4b, 0x4a, 0xe9, + 0x5e, 0x43, 0x2f, 0xd3, 0x5a, 0xbf, 0x8d, 0x12, 0x8c, 0x89, 0x8e, 0x27, 0x2f, 0xe3, 0xb1, 0xf2, 0x3e, 0x1e, 0x37, + 0x52, 0x21, 0x0f, 0x40, 0x04, 0x2a, 0xc6, 0x9f, 0xae, 0x3c, 0x39, 0xe9, 0x85, 0xf1, 0x2a, 0x94, 0x82, 0xc2, 0x80, + 0xae, 0x40, 0x0a, 0x78, 0xd4, 0x9e, 0xe8, 0x2c, 0xec, 0x12, 0xee, 0xd1, 0x4d, 0xc0, 0x58, 0x9f, 0x7f, 0x01, 0x34, + 0x77, 0xe1, 0x0e, 0x2f, 0x06, 0xa8, 0x4d, 0xbd, 0xba, 0xfb, 0xb8, 0x56, 0xe7, 0x70, 0x08, 0x0e, 0x56, 0x83, 0x08, + 0x4e, 0xe7, 0x53, 0x47, 0xb3, 0x2c, 0x40, 0xe5, 0x64, 0xb9, 0x91, 0x37, 0x8f, 0x16, 0xbd, 0xba, 0xef, 0x2d, 0xd3, + 0xb2, 0xaa, 0x83, 0x8c, 0x65, 0x61, 0x05, 0xb8, 0x3a, 0xb4, 0x7e, 0x10, 0x2e, 0x0b, 0xe7, 0x0f, 0x84, 0x20, 0x76, + 0xaf, 0xb6, 0x25, 0xcf, 0xd5, 0x1c, 0x7e, 0xfc, 0x84, 0xad, 0xb9, 0x44, 0x9d, 0x74, 0x26, 0x02, 0x10, 0x7b, 0x6a, + 0x56, 0xd1, 0x35, 0x90, 0xd4, 0x69, 0x56, 0xd1, 0x35, 0x35, 0xdb, 0x18, 0x07, 0xf2, 0xd1, 0x2a, 0x05, 0xec, 0xbb, + 0xe9, 0x38, 0x58, 0x3d, 0x8e, 0xe5, 0x75, 0xe8, 0xf6, 0xf1, 0x46, 0xf9, 0x0c, 0xea, 0x56, 0x1b, 0x63, 0x62, 0xbb, + 0xf9, 0x72, 0xae, 0xdf, 0x0c, 0x96, 0xbe, 0x1d, 0x34, 0xe7, 0x94, 0x7d, 0xab, 0xcb, 0x5e, 0xd9, 0x65, 0x53, 0xcf, + 0x1d, 0x15, 0xad, 0xc6, 0x80, 0xde, 0xc0, 0x82, 0xf5, 0xb9, 0x48, 0xb3, 0x55, 0xa9, 0x4a, 0xc0, 0x0b, 0x63, 0xc5, + 0x6e, 0xfd, 0x46, 0x66, 0x48, 0xc2, 0x3c, 0xce, 0xc4, 0x1b, 0xba, 0xd7, 0xc2, 0xe4, 0x38, 0x16, 0xc9, 0x94, 0xd0, + 0x29, 0xdd, 0xd9, 0x86, 0xce, 0x55, 0x18, 0x45, 0xb4, 0x56, 0x52, 0x69, 0x24, 0x30, 0x35, 0x03, 0x94, 0xcc, 0x15, + 0x38, 0xa5, 0xcb, 0xfd, 0xef, 0x48, 0x8c, 0x33, 0x5f, 0x94, 0xcc, 0x80, 0x6e, 0xf9, 0x75, 0xb1, 0x6e, 0xa5, 0xc8, + 0x08, 0xf3, 0xe6, 0xb8, 0xbd, 0xae, 0x0f, 0x81, 0x5c, 0x2d, 0x7b, 0x14, 0x8d, 0x83, 0x42, 0x87, 0x4b, 0x95, 0x00, + 0xfb, 0x22, 0xf1, 0x33, 0xc2, 0x96, 0xf6, 0x40, 0x6e, 0x8f, 0xce, 0x84, 0x39, 0xe7, 0xa4, 0x2c, 0x3b, 0x97, 0x66, + 0x70, 0x39, 0x71, 0x25, 0xb8, 0x48, 0x6f, 0xdb, 0xd3, 0xa4, 0xa5, 0xed, 0x63, 0xc3, 0x39, 0x1a, 0xda, 0x06, 0xdd, + 0xb1, 0x3f, 0x34, 0x17, 0x8b, 0xd8, 0xba, 0x58, 0x0c, 0x3b, 0xb3, 0x1f, 0x2d, 0x16, 0x20, 0x07, 0x80, 0xa3, 0x6e, + 0xc3, 0xc7, 0x6c, 0x09, 0x9c, 0x56, 0xd3, 0x6c, 0xea, 0x6d, 0x78, 0xf5, 0x58, 0xf5, 0xf4, 0x92, 0xe7, 0x8f, 0x85, + 0x19, 0x8b, 0x0d, 0xcf, 0x1f, 0x5b, 0x47, 0x4e, 0xf5, 0x58, 0x28, 0xd1, 0xba, 0x80, 0x66, 0xe0, 0x35, 0x05, 0x8c, + 0x58, 0x32, 0x99, 0x52, 0x45, 0x1e, 0xf7, 0xa6, 0x1b, 0x35, 0x78, 0x41, 0xe1, 0x10, 0x48, 0xe9, 0xf4, 0x8b, 0x27, + 0x4c, 0xbf, 0x77, 0xf1, 0xa4, 0x43, 0xd6, 0x36, 0x4c, 0x97, 0x9b, 0x61, 0x32, 0x28, 0xfd, 0xc7, 0x66, 0x62, 0x5c, + 0x58, 0x93, 0x04, 0x10, 0xff, 0xc6, 0x7e, 0x87, 0x14, 0x6e, 0xde, 0x5f, 0x0e, 0xe3, 0x07, 0xde, 0x8f, 0x91, 0x3d, + 0x49, 0x33, 0xc4, 0x9a, 0x49, 0x85, 0xdc, 0x7d, 0xb5, 0xfe, 0x31, 0xb1, 0x9b, 0xec, 0x81, 0x05, 0x20, 0xb6, 0xa6, + 0xad, 0x6e, 0x79, 0xbf, 0xef, 0x99, 0x22, 0xc0, 0x0f, 0xca, 0x3f, 0xba, 0x33, 0x24, 0x83, 0xb2, 0xeb, 0x86, 0x10, + 0x0f, 0xca, 0xa6, 0x69, 0xaf, 0xb7, 0xbd, 0x33, 0x8f, 0xd5, 0x75, 0xda, 0x59, 0x5c, 0x2d, 0x32, 0x48, 0xab, 0x0f, + 0xd9, 0x71, 0x66, 0x9f, 0x1d, 0x2d, 0x95, 0xee, 0xf7, 0x21, 0x22, 0xee, 0x28, 0x6b, 0xfb, 0xed, 0x16, 0x5c, 0xc3, + 0xd1, 0x20, 0x74, 0x65, 0x6f, 0x97, 0xd1, 0xc6, 0x85, 0x38, 0xee, 0x99, 0xce, 0x17, 0x7c, 0x79, 0x94, 0x76, 0x1e, + 0x9c, 0xea, 0x89, 0x3e, 0x37, 0xdd, 0x55, 0x26, 0xd7, 0x3a, 0xac, 0xc6, 0xa0, 0x36, 0x0b, 0x5b, 0xb8, 0x0b, 0xdb, + 0xe8, 0xa0, 0xb5, 0x2f, 0x0b, 0xfe, 0x29, 0x03, 0xf0, 0xa5, 0x67, 0xcb, 0xb6, 0xd7, 0xa4, 0xd5, 0x4b, 0x19, 0x85, + 0xd8, 0xd2, 0xf6, 0xea, 0xd3, 0x51, 0x3e, 0x6e, 0x4e, 0x28, 0x2e, 0xe4, 0x28, 0x3f, 0x78, 0x0d, 0x51, 0xd7, 0xba, + 0x8e, 0x8b, 0x45, 0x87, 0x1b, 0x57, 0xdd, 0x76, 0xe3, 0x7a, 0x85, 0x78, 0x6b, 0xb4, 0x49, 0xa1, 0x56, 0xc6, 0x8e, + 0xe0, 0x65, 0xf9, 0x70, 0xc8, 0xc4, 0x70, 0x28, 0x21, 0x53, 0x1f, 0xba, 0x37, 0x34, 0xed, 0xf3, 0xd3, 0xd6, 0x8f, + 0x58, 0x6a, 0x1c, 0xc5, 0x86, 0x77, 0xfa, 0xce, 0x63, 0x6b, 0x5c, 0xc9, 0x97, 0xc1, 0x6c, 0x57, 0x50, 0x6d, 0x8d, + 0x37, 0xec, 0xe5, 0xfc, 0xe7, 0x4a, 0x2a, 0xf9, 0xdb, 0x9f, 0xe1, 0x1a, 0xde, 0xda, 0xd2, 0x41, 0x53, 0xcd, 0x72, + 0x96, 0xeb, 0x7b, 0xc1, 0xf1, 0xc7, 0xdd, 0x2b, 0x82, 0xc1, 0xef, 0xe9, 0x28, 0xc8, 0xc5, 0x52, 0xad, 0x01, 0x05, + 0xe9, 0xc8, 0x8e, 0xa9, 0x2c, 0x30, 0x0c, 0xe0, 0x0d, 0x19, 0x20, 0x8f, 0x29, 0xdc, 0x0d, 0x15, 0x5e, 0xf8, 0x6b, + 0x45, 0x76, 0x09, 0x6c, 0x6b, 0xc6, 0xc7, 0x0c, 0x77, 0x10, 0xf2, 0x8f, 0x60, 0xb7, 0x6c, 0xc5, 0x6e, 0xd8, 0x82, + 0x21, 0xd9, 0x38, 0x0e, 0x63, 0xcc, 0xc7, 0x93, 0xf8, 0x4a, 0x4c, 0xe2, 0x01, 0x8f, 0xd0, 0x31, 0x62, 0xcd, 0xeb, + 0x59, 0x2c, 0x07, 0x90, 0xdd, 0x72, 0xa5, 0x03, 0x42, 0x68, 0x6c, 0x68, 0xc9, 0xcb, 0xc2, 0xe0, 0x62, 0xc7, 0x3e, + 0x23, 0x91, 0x8c, 0x43, 0xb0, 0x68, 0x55, 0x03, 0x0b, 0x13, 0xbb, 0xe1, 0xc5, 0x6c, 0x35, 0xc7, 0x7f, 0x0e, 0x07, + 0x04, 0xc0, 0x0e, 0xf6, 0x0d, 0xbb, 0x8d, 0x10, 0xe9, 0x6d, 0xc1, 0x6f, 0x2d, 0x4f, 0x17, 0x76, 0xc7, 0xaf, 0xf9, + 0x98, 0x9d, 0xbf, 0xf2, 0x20, 0x72, 0xf6, 0xfc, 0x03, 0xa0, 0x21, 0xde, 0xf1, 0x9b, 0xd4, 0xab, 0xd8, 0x0d, 0x51, + 0x10, 0xde, 0x80, 0x33, 0xd0, 0x1d, 0x44, 0xc0, 0x5e, 0xf3, 0x05, 0xc6, 0x8a, 0x9d, 0xa5, 0x4b, 0x0f, 0x33, 0x42, + 0xed, 0xe9, 0x7c, 0x59, 0xab, 0x49, 0xb8, 0xb9, 0x5a, 0x4e, 0x06, 0x83, 0x8d, 0xbf, 0xe3, 0x6b, 0xe0, 0x83, 0x39, + 0x7f, 0xe5, 0xed, 0xa8, 0x5c, 0xf8, 0xcf, 0xeb, 0x2c, 0x79, 0xe7, 0xb3, 0xeb, 0x01, 0x5f, 0x00, 0xde, 0x12, 0x3a, + 0x70, 0xdd, 0xf9, 0x4c, 0xe2, 0xb5, 0x5d, 0xeb, 0x6b, 0x04, 0x12, 0xf9, 0x02, 0x30, 0x62, 0x62, 0x7e, 0x5f, 0x43, + 0x04, 0xc6, 0x06, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0xf7, 0x3c, 0xd4, 0x3f, 0x13, + 0x9f, 0xbd, 0xe1, 0x8f, 0xf8, 0x53, 0x4f, 0x4a, 0xd2, 0xe5, 0xec, 0xd1, 0x1c, 0xae, 0x87, 0x52, 0x9e, 0x0e, 0xe9, + 0x67, 0x63, 0x30, 0x80, 0x50, 0xc8, 0x7c, 0xe3, 0x01, 0x6b, 0x52, 0x88, 0x7f, 0x01, 0xdf, 0x8e, 0x12, 0x36, 0xdf, + 0x78, 0x5b, 0x5f, 0xcb, 0x9b, 0x6f, 0xbc, 0x7b, 0x9f, 0xa2, 0x00, 0xab, 0xa0, 0x94, 0x05, 0x56, 0x41, 0xd8, 0x68, + 0x23, 0x8c, 0x81, 0xab, 0x77, 0x8d, 0xa1, 0xae, 0xe7, 0x88, 0x6d, 0x2b, 0x7d, 0x1b, 0xbe, 0x85, 0x0c, 0xf8, 0xe0, + 0x65, 0x51, 0x12, 0x7d, 0x4e, 0x4d, 0x91, 0xb4, 0xee, 0xb9, 0xdf, 0x5a, 0x77, 0xb4, 0xa6, 0xd4, 0x47, 0xae, 0xc6, + 0x87, 0x43, 0xfd, 0x54, 0x68, 0x91, 0x60, 0x0a, 0x1a, 0xd7, 0xa0, 0x2d, 0x40, 0xd0, 0xe7, 0x01, 0xb2, 0x96, 0x14, + 0x0b, 0xbe, 0xfd, 0x15, 0x62, 0xf0, 0xca, 0xf4, 0xce, 0xe5, 0x2a, 0x23, 0x61, 0x7b, 0xe1, 0x97, 0xc3, 0xda, 0x9f, + 0x38, 0xb5, 0xb0, 0xb4, 0x9a, 0x83, 0xfa, 0xb1, 0x2d, 0xc7, 0xe9, 0xaa, 0x45, 0x5e, 0x87, 0xd2, 0x72, 0x7a, 0x67, + 0xdf, 0x74, 0x99, 0x60, 0x63, 0x3f, 0xa0, 0xea, 0xc8, 0x6a, 0xd8, 0x7d, 0xa1, 0xbe, 0xe8, 0x29, 0x99, 0xd0, 0x7c, + 0x54, 0xd1, 0x3c, 0xb7, 0xbe, 0x79, 0x5c, 0xff, 0xe9, 0xe5, 0x50, 0x04, 0x48, 0x56, 0x69, 0xb1, 0x14, 0x39, 0x1b, + 0xfb, 0xf1, 0x30, 0xc9, 0x54, 0x78, 0x41, 0x3a, 0xba, 0xfb, 0x8d, 0xfb, 0x5b, 0x6e, 0x20, 0x2b, 0xb4, 0x6a, 0x83, + 0xb1, 0x52, 0xb4, 0x0c, 0xd6, 0x57, 0xe3, 0x7e, 0x5f, 0x5c, 0x8d, 0xa7, 0x22, 0xa8, 0x81, 0xb8, 0x48, 0x3c, 0x1d, + 0x4f, 0x6b, 0x62, 0x49, 0xed, 0x0a, 0x8c, 0xd1, 0xe3, 0xaa, 0xa8, 0x7d, 0xea, 0xa7, 0x10, 0x8a, 0x54, 0x6b, 0xe6, + 0x58, 0xe3, 0xc6, 0x88, 0xb8, 0xc3, 0xca, 0xb5, 0x53, 0x7b, 0x1d, 0x80, 0xe5, 0xd5, 0xb8, 0x20, 0xac, 0x93, 0x63, + 0xe7, 0x02, 0x56, 0xa3, 0x21, 0xd5, 0x6e, 0xb8, 0xf5, 0xb2, 0xf3, 0x9b, 0x2f, 0x13, 0x5b, 0x1b, 0xe1, 0x96, 0x02, + 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, 0x23, 0x4e, 0x5c, 0xc0, 0x72, 0xc3, 0x53, 0xab, + 0x6f, 0x62, 0x70, 0x22, 0x54, 0xad, 0x74, 0xb8, 0x93, 0x09, 0xc4, 0xfd, 0xea, 0xbe, 0xee, 0x95, 0xe0, 0x27, 0x21, + 0xaf, 0xdf, 0xf2, 0x0e, 0x00, 0x2b, 0x3e, 0xe4, 0xc5, 0xb4, 0x70, 0xb4, 0x2e, 0x83, 0x32, 0x40, 0x84, 0x66, 0x00, + 0x74, 0x72, 0x75, 0x10, 0xa5, 0x81, 0x2b, 0xee, 0x10, 0xe1, 0xa7, 0xd1, 0xe3, 0xfc, 0x69, 0xf8, 0xb8, 0x9a, 0x86, + 0x17, 0x79, 0x10, 0x5d, 0x54, 0x41, 0xf4, 0xb8, 0xba, 0x0a, 0x1f, 0xe7, 0xd3, 0xe8, 0x22, 0x0f, 0xc2, 0x8b, 0xaa, + 0xb1, 0xef, 0xda, 0xdd, 0x3d, 0x21, 0x6f, 0xbb, 0xfa, 0x23, 0xe7, 0xca, 0x9e, 0x32, 0x3d, 0x3f, 0xaf, 0xf5, 0x4a, + 0xed, 0x36, 0xd7, 0x6b, 0xd4, 0x4c, 0x7d, 0x94, 0xfd, 0xcd, 0x36, 0x16, 0x1e, 0xcd, 0x21, 0xf4, 0x19, 0x69, 0x31, + 0xf7, 0x38, 0xd7, 0x9b, 0x3d, 0x29, 0x0c, 0x8c, 0x98, 0x54, 0x32, 0x72, 0x7a, 0x81, 0x8b, 0x50, 0x85, 0x18, 0xd6, + 0xd2, 0xd5, 0x3e, 0xeb, 0xd2, 0x1b, 0xa8, 0x6b, 0x8a, 0x7d, 0x0d, 0x19, 0x78, 0xd1, 0xf4, 0x32, 0x18, 0x03, 0x72, + 0x04, 0xde, 0xf1, 0xd9, 0x12, 0x0e, 0xcc, 0x35, 0x40, 0xdf, 0x3c, 0xe8, 0xeb, 0x72, 0xcb, 0xd7, 0xaa, 0x6f, 0xa6, + 0xeb, 0x91, 0x52, 0x7e, 0xac, 0xf8, 0xed, 0xc5, 0x13, 0x76, 0xc3, 0x35, 0x2a, 0xca, 0x73, 0xbd, 0x58, 0xef, 0x80, + 0xab, 0xee, 0x39, 0xdc, 0x66, 0xf1, 0xd8, 0x95, 0x07, 0x2c, 0xdb, 0xb2, 0x7b, 0xf6, 0x86, 0x3d, 0x62, 0xef, 0xd9, + 0x27, 0xf6, 0x95, 0xd5, 0x08, 0x51, 0x5e, 0x2a, 0x29, 0xcf, 0x5f, 0xf0, 0x1b, 0x69, 0x7b, 0x94, 0xb0, 0x64, 0xf7, + 0xb6, 0x9d, 0x66, 0xb8, 0x61, 0x8f, 0xf8, 0x62, 0xb8, 0x62, 0x9f, 0x20, 0x1b, 0x0a, 0xc5, 0x83, 0x15, 0xab, 0xe1, + 0x0a, 0x4b, 0x19, 0xf4, 0x69, 0x58, 0x5a, 0xc2, 0xa2, 0x29, 0x14, 0xa5, 0xe8, 0x4f, 0xbc, 0x26, 0xec, 0xb4, 0x1a, + 0x0b, 0x91, 0x1f, 0x1a, 0xae, 0xd8, 0x3d, 0x5f, 0x0c, 0x56, 0xec, 0x91, 0xb6, 0x11, 0x0d, 0x36, 0x6e, 0x71, 0x04, + 0x66, 0xa5, 0x0b, 0x93, 0x02, 0xf5, 0xd6, 0xbe, 0x09, 0x6e, 0xd8, 0x1b, 0xac, 0xdf, 0x7b, 0x2c, 0x1a, 0x65, 0xfe, + 0xc1, 0x8a, 0x7d, 0xe5, 0x12, 0x43, 0xcd, 0x2d, 0x4f, 0x3a, 0x86, 0xea, 0x02, 0xe9, 0x8a, 0xf0, 0x9e, 0xd3, 0x8b, + 0xec, 0x2b, 0x96, 0x41, 0x5f, 0x19, 0xae, 0xd8, 0x16, 0x6b, 0xf7, 0xc6, 0x18, 0xb7, 0xac, 0xea, 0x49, 0x50, 0x60, + 0x94, 0x55, 0x4a, 0xcb, 0xc5, 0x11, 0xcb, 0xa6, 0x8e, 0x1a, 0xd4, 0x86, 0x01, 0x7d, 0x30, 0xfa, 0x8b, 0xaf, 0xdf, + 0x7d, 0xe7, 0x95, 0xfa, 0xe6, 0xfb, 0xdc, 0xf1, 0xae, 0x2c, 0xd1, 0xbb, 0xf2, 0x37, 0x5e, 0xce, 0x9e, 0xcf, 0x27, + 0xba, 0x96, 0xb4, 0xc9, 0x90, 0xbb, 0xe9, 0xec, 0x79, 0x87, 0xbf, 0xe5, 0x6f, 0xbe, 0xdf, 0x58, 0x7d, 0xac, 0xbe, + 0xab, 0xbb, 0xf7, 0x7e, 0xb0, 0x69, 0x9c, 0x8a, 0xef, 0x4e, 0x57, 0x1c, 0xdb, 0x59, 0x6b, 0xef, 0xcc, 0xff, 0xe1, + 0x5a, 0x6f, 0x71, 0xec, 0xde, 0xf0, 0xed, 0x70, 0x63, 0x0f, 0x83, 0xfc, 0xbe, 0x54, 0x1c, 0x67, 0x35, 0x7f, 0xe6, + 0x75, 0x4a, 0xb2, 0x80, 0x6a, 0xf4, 0xda, 0x48, 0x43, 0x97, 0xcc, 0xc4, 0x34, 0xc4, 0x17, 0x19, 0xa0, 0x73, 0x81, + 0x78, 0x76, 0xc7, 0xc7, 0x93, 0xbb, 0xab, 0x78, 0x72, 0x37, 0xe0, 0xaf, 0x4d, 0x0b, 0xda, 0x0b, 0xee, 0xce, 0x67, + 0xbf, 0xf1, 0xc2, 0x5e, 0x92, 0xcf, 0x7d, 0xf6, 0x56, 0xb8, 0xab, 0xf4, 0xb9, 0xcf, 0xbe, 0x0a, 0xfe, 0xdb, 0x48, + 0x93, 0x65, 0xb0, 0xaf, 0x35, 0xff, 0x6d, 0x84, 0xac, 0x1f, 0xec, 0xb3, 0xe0, 0x6f, 0xc1, 0xff, 0xbb, 0x4a, 0xd0, + 0x32, 0xfe, 0xb9, 0x56, 0x3f, 0xdf, 0xc9, 0xd8, 0x1c, 0x78, 0x13, 0x5a, 0x41, 0x6f, 0xde, 0xd4, 0xf2, 0x27, 0x71, + 0x71, 0xa4, 0xea, 0xa9, 0xe1, 0xa0, 0xc5, 0x62, 0x16, 0xf5, 0x51, 0x3a, 0x95, 0x37, 0xb9, 0xe6, 0xb1, 0xb4, 0x30, + 0xdf, 0x41, 0x38, 0xf0, 0xb5, 0x0d, 0x53, 0xb0, 0xe3, 0xb8, 0x19, 0x5c, 0x33, 0x80, 0x90, 0xcc, 0xa6, 0x5b, 0xfe, + 0x86, 0xbf, 0xe7, 0x5f, 0xf9, 0x2e, 0xb8, 0xe7, 0x8f, 0xf8, 0x27, 0x5e, 0xd7, 0x7c, 0xc7, 0x96, 0x12, 0xf2, 0xb4, + 0xde, 0x5e, 0x06, 0x5b, 0x56, 0xef, 0x2e, 0x83, 0x7b, 0x56, 0x6f, 0x9f, 0x04, 0x6f, 0x58, 0xbd, 0x7b, 0x12, 0x3c, + 0x62, 0xdb, 0xcb, 0xe0, 0x3d, 0xdb, 0x5d, 0x06, 0x9f, 0xd8, 0xf6, 0x49, 0xf0, 0x95, 0xed, 0x9e, 0x04, 0xb5, 0x42, + 0x7a, 0xf8, 0x2a, 0x24, 0xd3, 0xc9, 0xd7, 0x9a, 0x19, 0x56, 0xdd, 0xe0, 0xb3, 0xb0, 0x7e, 0x51, 0x2d, 0x83, 0xcf, + 0x35, 0xd3, 0x6d, 0x0e, 0x84, 0x60, 0xba, 0xc5, 0xc1, 0x0d, 0x3d, 0x31, 0xed, 0x0a, 0x52, 0xc1, 0xba, 0x5a, 0x1a, + 0x2c, 0xea, 0xa6, 0x75, 0x32, 0x3b, 0xde, 0x89, 0x71, 0x87, 0x77, 0xe2, 0x82, 0x2d, 0x9b, 0x4e, 0x57, 0x9d, 0xd3, + 0xe7, 0x81, 0x3e, 0x02, 0xf4, 0xde, 0x5f, 0x49, 0x0f, 0x9a, 0xa2, 0xe1, 0xb9, 0xd2, 0x1d, 0xb7, 0xf6, 0xfb, 0xd0, + 0xda, 0xef, 0x99, 0x54, 0xa4, 0x45, 0x2c, 0x2a, 0x8b, 0xaa, 0x42, 0x3e, 0xf1, 0x20, 0xd3, 0x5a, 0xb5, 0x84, 0x91, + 0x3a, 0x13, 0x30, 0xe9, 0x0b, 0x3a, 0x0c, 0x72, 0xb2, 0x2b, 0xb0, 0x25, 0xdf, 0x0c, 0x12, 0xb6, 0xe6, 0xf1, 0x74, + 0x98, 0x04, 0x4b, 0x76, 0xcb, 0x87, 0xdd, 0x62, 0xc1, 0x4a, 0x85, 0x31, 0xe9, 0xeb, 0xd3, 0xd1, 0xee, 0xce, 0x7b, + 0xab, 0x34, 0x8e, 0x33, 0x81, 0x3a, 0xb7, 0x4a, 0x6f, 0xf3, 0x5b, 0x67, 0x57, 0x5f, 0xab, 0x5d, 0x1e, 0x04, 0x86, + 0xdf, 0x80, 0x68, 0x87, 0x78, 0xef, 0xa0, 0xc6, 0x48, 0xb7, 0x64, 0xd6, 0x7d, 0x65, 0xef, 0xeb, 0x5b, 0xb3, 0x55, + 0xff, 0xa7, 0x45, 0xd0, 0x5e, 0x2e, 0x7b, 0xff, 0xb5, 0x79, 0xf5, 0xf7, 0x8e, 0x57, 0x37, 0xfe, 0xe4, 0x9e, 0xbf, + 0xc6, 0xe8, 0x04, 0x4c, 0x64, 0x3b, 0xfe, 0x7a, 0xb4, 0x6d, 0x9c, 0xf2, 0xe4, 0x5e, 0xfe, 0x7f, 0xa5, 0x40, 0x7b, + 0x37, 0xaf, 0xec, 0x4d, 0x71, 0xcb, 0x3b, 0xf6, 0xf2, 0xa5, 0xb5, 0x27, 0x1a, 0x84, 0x92, 0xd7, 0xdc, 0x0d, 0x8a, + 0x86, 0x3d, 0xf1, 0x39, 0xaf, 0x66, 0xaf, 0xe7, 0x93, 0x2d, 0x3f, 0xde, 0x11, 0x5f, 0x77, 0xec, 0x88, 0xcf, 0xfd, + 0xc1, 0xb2, 0xf9, 0x56, 0xaf, 0x76, 0xee, 0xe4, 0x4e, 0xa5, 0x77, 0xfc, 0x78, 0x1f, 0x1f, 0xfe, 0xc7, 0x95, 0xde, + 0x7d, 0x77, 0xa5, 0xed, 0x2a, 0x77, 0x77, 0xbe, 0xe9, 0xf8, 0x46, 0xd6, 0x1a, 0xc3, 0xcd, 0x8c, 0x82, 0x11, 0xa6, + 0x2d, 0x4c, 0xd3, 0x20, 0xb2, 0x14, 0x8b, 0x90, 0xa8, 0x51, 0x3a, 0x27, 0xfa, 0x2c, 0xe8, 0x14, 0x74, 0x71, 0xa3, + 0xbf, 0xe1, 0x63, 0xb6, 0x30, 0x2e, 0x9b, 0x37, 0x57, 0x8b, 0xc9, 0x60, 0x70, 0xe3, 0xef, 0xef, 0x78, 0x38, 0xbb, + 0x99, 0xb3, 0x6b, 0x7e, 0x47, 0xeb, 0x69, 0xa2, 0x1a, 0x5f, 0x3c, 0x24, 0x81, 0xdd, 0xf8, 0xfe, 0xc4, 0x22, 0x82, + 0xb5, 0x6f, 0x9c, 0x37, 0xfe, 0x40, 0x9a, 0xa5, 0xe5, 0xd6, 0xfe, 0xe8, 0x61, 0x0d, 0xc5, 0x0d, 0x08, 0x19, 0x8f, + 0x6c, 0x95, 0xc3, 0x27, 0xfe, 0xc1, 0xbb, 0xf6, 0xa7, 0xd7, 0x3a, 0xf8, 0x66, 0xa2, 0xce, 0xa5, 0x4f, 0x17, 0x4f, + 0xd8, 0x6f, 0xfc, 0xb5, 0x3c, 0x53, 0xde, 0x0a, 0x39, 0x6d, 0x3f, 0x22, 0x89, 0x13, 0x1d, 0x15, 0x5f, 0xdd, 0x44, + 0x02, 0x85, 0x80, 0x5d, 0xe1, 0x6b, 0xcd, 0xef, 0x27, 0xe5, 0xd4, 0xdb, 0x01, 0xc9, 0x2b, 0xb7, 0x15, 0xd1, 0x37, + 0x9c, 0xf3, 0xc5, 0xf0, 0x72, 0xfa, 0xb5, 0xdb, 0xb7, 0x47, 0x85, 0xb5, 0xa9, 0x88, 0xb7, 0x1b, 0x0c, 0xc2, 0x3a, + 0x99, 0x59, 0xe6, 0x92, 0x2f, 0x7d, 0xad, 0xcd, 0xdc, 0x63, 0x7a, 0xc7, 0x99, 0x66, 0xc8, 0xe8, 0x0b, 0xcc, 0x4c, + 0x87, 0xc3, 0xed, 0x39, 0x96, 0xc7, 0x87, 0x9f, 0x1e, 0xbf, 0x1f, 0xbc, 0xc7, 0x10, 0x2e, 0x2b, 0x2c, 0xe4, 0x2b, + 0x1f, 0x66, 0x75, 0xeb, 0xda, 0x71, 0xf1, 0x64, 0xf8, 0x1c, 0xf2, 0x06, 0x5d, 0x0f, 0x4d, 0x11, 0xad, 0xf2, 0x3b, + 0x8a, 0x3e, 0x51, 0x72, 0xd0, 0xf1, 0x04, 0x6a, 0x87, 0x5c, 0xb8, 0x5f, 0x1f, 0x73, 0x50, 0x74, 0x60, 0xa9, 0xfd, + 0xfe, 0xf9, 0x6b, 0x22, 0x94, 0x86, 0xf1, 0x7e, 0x1e, 0x46, 0x7f, 0xc6, 0x65, 0xb1, 0x86, 0x23, 0x76, 0x00, 0x9f, + 0x7b, 0xac, 0xaf, 0x61, 0xb7, 0xbe, 0xef, 0x07, 0xde, 0x96, 0xbf, 0x61, 0x5f, 0xb9, 0x77, 0x39, 0xfc, 0xe4, 0x3f, + 0x7e, 0x0f, 0xf2, 0x13, 0xe2, 0xa4, 0x60, 0x48, 0x6c, 0x47, 0x31, 0x6a, 0x1d, 0x7e, 0xae, 0x21, 0x56, 0xeb, 0x35, + 0x52, 0x77, 0x41, 0xfa, 0x7b, 0x85, 0xec, 0x27, 0x04, 0x56, 0x93, 0xf4, 0x29, 0x30, 0x89, 0x6f, 0x6a, 0x48, 0x20, + 0x4d, 0x0b, 0xc4, 0xe0, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x87, 0x9f, 0x49, 0xfe, 0x5b, 0xd4, 0x7c, 0x0c, 0x7f, 0xc3, + 0xd0, 0x4c, 0xaa, 0xfb, 0xb4, 0x86, 0x88, 0x68, 0x38, 0xf5, 0xc2, 0x4a, 0xa8, 0x93, 0x21, 0x48, 0xc5, 0x90, 0x0b, + 0x71, 0xf1, 0x64, 0x72, 0x53, 0x8a, 0xf0, 0xcf, 0x09, 0x3e, 0x93, 0x2b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, 0x2c, 0xe0, + 0x5e, 0xbe, 0x2f, 0x7b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x53, 0xbb, 0xef, 0xcb, 0x39, 0x41, 0x8f, 0xec, 0x07, 0x34, + 0x07, 0x03, 0x35, 0x03, 0x29, 0x43, 0x70, 0x03, 0x97, 0x7e, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, 0x32, 0x70, + 0x65, 0x41, 0x98, 0x72, 0xa9, 0x90, 0x02, 0xc7, 0x4d, 0x3d, 0xf8, 0xac, 0xd1, 0x49, 0x24, 0xf8, 0x94, 0x80, 0x24, + 0x69, 0x79, 0x20, 0x69, 0xc4, 0x74, 0x20, 0x2e, 0x94, 0xa6, 0x59, 0x49, 0x11, 0x87, 0xd8, 0x55, 0xaf, 0x91, 0xf0, + 0x2c, 0x78, 0xc4, 0x60, 0xed, 0x48, 0xd1, 0xe2, 0xab, 0x31, 0x1d, 0xeb, 0xb0, 0xa1, 0x5b, 0x59, 0xdc, 0x6f, 0x92, + 0x3a, 0x8d, 0xc4, 0x95, 0xb7, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x81, 0xf4, 0xae, 0x06, 0x62, 0x10, 0xfc, 0x00, 0xfd, + 0x07, 0x2c, 0x72, 0x10, 0x94, 0xea, 0x32, 0xcc, 0xab, 0x8c, 0x0a, 0x9c, 0xed, 0xd8, 0x76, 0xce, 0x54, 0xdd, 0x82, + 0xcf, 0xc2, 0x30, 0xa4, 0x9d, 0xad, 0x9a, 0x93, 0x5b, 0xbd, 0x81, 0x7a, 0x26, 0x71, 0xa4, 0x96, 0xe2, 0x48, 0x5b, + 0x73, 0x9f, 0x2e, 0xbd, 0x6e, 0x79, 0x41, 0xc3, 0x05, 0xe8, 0x45, 0xe9, 0xae, 0xf3, 0x09, 0x85, 0x2e, 0xab, 0x71, + 0x35, 0x14, 0x75, 0x28, 0xc7, 0x58, 0xfb, 0x73, 0x25, 0xcf, 0xef, 0xc0, 0x7a, 0x84, 0x86, 0xaf, 0x4a, 0x1d, 0xc4, + 0xf6, 0x13, 0xbd, 0xeb, 0x54, 0xea, 0x6f, 0x00, 0x18, 0x38, 0x75, 0x3c, 0xd4, 0x47, 0xed, 0x14, 0xb2, 0x9d, 0x7b, + 0x4b, 0x8c, 0xca, 0x95, 0xf0, 0x54, 0x69, 0x79, 0x4a, 0x59, 0xf5, 0xb5, 0xe0, 0x56, 0x76, 0x9f, 0x0d, 0x20, 0xa3, + 0x0d, 0x0a, 0xe4, 0x19, 0xb5, 0x35, 0x1e, 0xa4, 0x9a, 0x66, 0x89, 0x63, 0xf8, 0xa0, 0x48, 0xb3, 0x0a, 0x2c, 0x5e, + 0xe6, 0x92, 0x39, 0x28, 0x58, 0xae, 0x37, 0x9b, 0x69, 0xa6, 0xfa, 0x22, 0xb7, 0x37, 0x1a, 0x2f, 0xd3, 0x7f, 0xb3, + 0x64, 0xc0, 0xa3, 0x8b, 0x27, 0x7e, 0x00, 0x69, 0x92, 0xe2, 0x01, 0x92, 0x60, 0x7b, 0xb0, 0x8b, 0x1d, 0x86, 0xad, + 0x62, 0x65, 0x4f, 0x9e, 0x2e, 0x77, 0x68, 0xca, 0x25, 0xb8, 0xe4, 0xc4, 0x5c, 0x4e, 0x7d, 0x5f, 0xb2, 0xde, 0x50, + 0x9c, 0xb2, 0x69, 0x02, 0x4a, 0x02, 0xed, 0x16, 0xfc, 0x17, 0x3e, 0x35, 0x74, 0x5a, 0x80, 0xa5, 0xb6, 0x1b, 0xf0, + 0x5f, 0xe8, 0x17, 0xdb, 0x5d, 0xd4, 0x0f, 0xcc, 0x83, 0xbd, 0x59, 0x5c, 0x19, 0x03, 0x4e, 0x12, 0x57, 0x9a, 0x47, + 0xae, 0x1f, 0x14, 0x7d, 0xba, 0xac, 0x1d, 0x38, 0x53, 0x5c, 0x58, 0xa5, 0x36, 0x49, 0xaf, 0xfd, 0x96, 0x9a, 0x78, + 0x13, 0x25, 0x55, 0x61, 0x3b, 0xa4, 0xfd, 0x4b, 0xca, 0x99, 0x2a, 0xee, 0x10, 0x3d, 0xd9, 0x4d, 0x5c, 0x05, 0x5e, + 0x58, 0x55, 0x6c, 0x84, 0xda, 0x8c, 0x2c, 0x27, 0x70, 0xba, 0xc7, 0xea, 0x82, 0x8f, 0xed, 0x6a, 0x76, 0xc1, 0x4a, + 0xb6, 0x66, 0xd2, 0x7d, 0xde, 0x8e, 0xb9, 0x90, 0x57, 0x7a, 0x59, 0xb4, 0x02, 0xda, 0x83, 0xc0, 0xe1, 0xe7, 0x9a, + 0xee, 0xd1, 0xb3, 0xcd, 0x36, 0xb5, 0xd9, 0xd8, 0x5a, 0x84, 0x90, 0x81, 0x68, 0xe8, 0x0b, 0x39, 0xa3, 0xc8, 0x57, + 0x69, 0xb9, 0x56, 0x1b, 0xab, 0x8c, 0x17, 0x98, 0x08, 0x32, 0x9c, 0x85, 0x77, 0xe8, 0x69, 0x3d, 0xd2, 0x14, 0x93, + 0xe0, 0xa4, 0x8b, 0xbf, 0x00, 0x1b, 0xca, 0x93, 0xdc, 0x1c, 0x90, 0x03, 0xa8, 0x5c, 0x8a, 0x52, 0x29, 0x83, 0x5f, + 0xab, 0x3b, 0xb2, 0xad, 0xfa, 0xef, 0x34, 0x90, 0xc1, 0x1d, 0xe8, 0xdb, 0x5e, 0x68, 0xed, 0x68, 0xe7, 0xca, 0xd6, + 0xb4, 0x2d, 0xd3, 0x3c, 0x46, 0x16, 0x1b, 0x40, 0x3e, 0x91, 0xce, 0x81, 0xc8, 0x6b, 0xa2, 0xf1, 0xce, 0x9e, 0xf2, + 0xf1, 0x54, 0x3c, 0x24, 0xef, 0x55, 0xbe, 0x6f, 0xee, 0xf5, 0xc1, 0x18, 0xfb, 0x16, 0x94, 0x89, 0x0f, 0x56, 0x5b, + 0xeb, 0x12, 0xeb, 0xad, 0xd2, 0x24, 0xba, 0xe1, 0x0a, 0x3a, 0x8e, 0xc4, 0x0d, 0x62, 0x70, 0xcc, 0x78, 0x6d, 0x95, + 0xa5, 0xaf, 0xb0, 0xcc, 0x75, 0xcc, 0x92, 0x21, 0x93, 0x3a, 0x4f, 0x14, 0x3c, 0xf9, 0x79, 0x42, 0x32, 0x22, 0x6a, + 0xb6, 0xe5, 0x28, 0xe5, 0xa6, 0x05, 0x5c, 0x66, 0x64, 0x00, 0xdf, 0xa4, 0x09, 0x40, 0xb9, 0x7c, 0x09, 0x52, 0x69, + 0x88, 0xe0, 0x9a, 0xed, 0x25, 0xa3, 0x1b, 0x47, 0xeb, 0xa0, 0x4a, 0x32, 0x77, 0x70, 0x6e, 0x67, 0x91, 0x52, 0x6f, + 0x3e, 0xc2, 0xb0, 0x93, 0xf7, 0x61, 0x9d, 0xe0, 0xb7, 0x01, 0x35, 0xe9, 0x53, 0xe1, 0x45, 0x23, 0x40, 0x53, 0xdf, + 0xa9, 0x32, 0x3e, 0x15, 0x5e, 0x36, 0xda, 0xb2, 0x8c, 0x52, 0xa8, 0x2e, 0x98, 0xdd, 0x9a, 0x2e, 0xc4, 0xbc, 0xaa, + 0x06, 0xda, 0x20, 0xb7, 0xeb, 0x98, 0x01, 0x8d, 0xda, 0xae, 0x3c, 0xb2, 0x00, 0xb7, 0x66, 0x22, 0x30, 0x72, 0xfe, + 0x5d, 0x7e, 0xad, 0xc2, 0x79, 0xfa, 0xfd, 0xd0, 0xdb, 0x6f, 0x83, 0x68, 0xb4, 0xbd, 0x64, 0xbb, 0x20, 0x1a, 0xed, + 0x2e, 0x1b, 0x46, 0xbf, 0x9f, 0xd0, 0xef, 0x27, 0x0d, 0xa8, 0x4a, 0x84, 0x89, 0xb8, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, + 0x5a, 0xbf, 0x53, 0xcb, 0x97, 0x6a, 0x78, 0x6b, 0x4f, 0x22, 0x41, 0x64, 0x69, 0x6c, 0xee, 0x25, 0x5b, 0xaa, 0xa5, + 0xd2, 0x31, 0xaa, 0x8c, 0xa8, 0xa5, 0xb3, 0x39, 0x56, 0x8c, 0xb4, 0x73, 0x50, 0x32, 0x20, 0xd3, 0xe2, 0xaa, 0xc6, + 0x74, 0xb3, 0xa2, 0x25, 0x26, 0x23, 0xac, 0x6c, 0xcb, 0xdb, 0x4d, 0xaa, 0xa6, 0x73, 0x72, 0x73, 0xab, 0x94, 0x9b, + 0x5b, 0xc1, 0xf3, 0x6f, 0xe8, 0x96, 0x4b, 0xae, 0xbd, 0xcc, 0xa6, 0x85, 0xd2, 0x2d, 0xe3, 0x1a, 0x6c, 0xed, 0x9b, + 0x40, 0x96, 0xf9, 0x40, 0x51, 0x63, 0x7b, 0xd1, 0x28, 0xdf, 0x20, 0x5b, 0x11, 0xa3, 0x4e, 0x59, 0x30, 0xfe, 0x76, + 0x47, 0x0f, 0x64, 0xa0, 0xaa, 0xaa, 0x8d, 0x83, 0x3b, 0x2b, 0xfd, 0x61, 0x79, 0xf1, 0x84, 0x25, 0x56, 0x3a, 0xb9, + 0x50, 0x85, 0xfe, 0x20, 0x44, 0x37, 0x95, 0x0d, 0x07, 0x87, 0xba, 0xd8, 0xca, 0x80, 0xd0, 0xc3, 0xf4, 0xde, 0xc6, + 0x4a, 0x96, 0xbb, 0xa6, 0x7c, 0x31, 0xe3, 0x09, 0xc7, 0xd1, 0x97, 0xab, 0x45, 0x58, 0xab, 0x45, 0x76, 0x02, 0x3c, + 0xb4, 0x56, 0x4b, 0x21, 0x57, 0x8b, 0x70, 0x66, 0xba, 0x50, 0x33, 0x3d, 0x03, 0x05, 0xa4, 0x50, 0xb3, 0x3c, 0x01, + 0x58, 0x78, 0x61, 0x66, 0xb8, 0x30, 0x33, 0x1c, 0x87, 0xd4, 0xf8, 0x3f, 0xe8, 0xbd, 0xce, 0x3d, 0xb7, 0xdc, 0x8d, + 0x4e, 0x23, 0xbe, 0x1d, 0x6d, 0x30, 0xc7, 0x07, 0xe1, 0xa4, 0xea, 0xf7, 0xd3, 0x12, 0xb1, 0x7a, 0x0c, 0x8c, 0xa0, + 0x1c, 0x2a, 0x47, 0xfb, 0x65, 0x61, 0x49, 0x96, 0x84, 0x25, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x2e, 0x5e, 0x25, 0x81, + 0x48, 0x64, 0xbc, 0x94, 0x26, 0xf8, 0x84, 0x97, 0x23, 0x23, 0x35, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, 0x8d, 0x11, + 0xc3, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0xcf, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0xd7, 0xcb, 0x53, 0x67, 0x91, 0x23, + 0xe4, 0xd5, 0x48, 0x2a, 0x2c, 0xaf, 0x95, 0x7a, 0xfa, 0x12, 0x7c, 0x50, 0x77, 0x6f, 0x14, 0x00, 0x71, 0x91, 0x4b, + 0xff, 0xda, 0x12, 0x2e, 0x4d, 0xb9, 0x81, 0x41, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x04, 0x21, 0x29, 0xac, 0x1b, 0xf7, + 0xc5, 0x93, 0x89, 0xeb, 0xce, 0x62, 0x03, 0x13, 0x1c, 0x0e, 0x80, 0x78, 0x30, 0xf5, 0xa2, 0x01, 0x2f, 0xd5, 0x9c, + 0xf9, 0xe0, 0xe5, 0x04, 0x93, 0x01, 0xaa, 0x8a, 0x81, 0x53, 0xd6, 0x63, 0xf9, 0xc8, 0xb8, 0x99, 0xf9, 0x7e, 0x80, + 0xef, 0xd6, 0x85, 0x44, 0x7f, 0x50, 0x00, 0x05, 0x99, 0x02, 0x28, 0x48, 0x0c, 0x40, 0x41, 0x6c, 0x00, 0x0a, 0x36, + 0x0d, 0x5f, 0x49, 0x1d, 0x6e, 0x04, 0x74, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, 0x31, 0x2b, + 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x15, 0xb9, 0x4d, 0xbc, 0x90, 0x50, 0xe4, 0x9c, 0x1b, 0x89, + 0xba, 0xfb, 0xb9, 0xf7, 0x92, 0x8c, 0x25, 0xf3, 0x86, 0x46, 0x0d, 0xe6, 0x65, 0xd7, 0x01, 0x4c, 0x4b, 0xbe, 0x2d, + 0x68, 0x30, 0x9d, 0x2a, 0x8f, 0x48, 0x93, 0xa0, 0x76, 0x2e, 0x93, 0x22, 0x27, 0x84, 0x49, 0xd0, 0x2b, 0xc1, 0x6f, + 0x24, 0xca, 0xff, 0x37, 0x9d, 0xe0, 0x01, 0x8e, 0x89, 0x56, 0xc9, 0x57, 0x30, 0x60, 0xe6, 0xfc, 0x99, 0x74, 0xca, + 0x46, 0x28, 0xc6, 0x32, 0x8d, 0x47, 0x5f, 0xd9, 0x10, 0xa1, 0xad, 0x9e, 0xa1, 0x89, 0x09, 0xea, 0x00, 0x8f, 0xe8, + 0xaf, 0xd1, 0x57, 0x43, 0xa1, 0xd2, 0xd5, 0x48, 0x5d, 0xb3, 0x73, 0xce, 0xdf, 0xd6, 0x86, 0x13, 0x19, 0xd3, 0xa6, + 0xc0, 0x37, 0x20, 0x90, 0x6f, 0x20, 0x00, 0x5c, 0x35, 0x9d, 0xd9, 0x2b, 0x80, 0x73, 0x20, 0x80, 0xc7, 0x79, 0xc7, + 0xe3, 0x07, 0xfa, 0xab, 0x38, 0xee, 0x9d, 0xa6, 0x61, 0xfb, 0xaf, 0xc0, 0x58, 0x0c, 0xe5, 0x78, 0xbe, 0x53, 0x90, + 0xec, 0x51, 0xca, 0xd2, 0x55, 0x13, 0xd9, 0xa1, 0x58, 0x9f, 0xe6, 0x94, 0xb1, 0xb4, 0x2d, 0xc7, 0x68, 0xe3, 0xf5, + 0x43, 0x3c, 0xbe, 0xb9, 0xd1, 0x93, 0x0f, 0x7a, 0x70, 0x7b, 0x7b, 0xf5, 0xa2, 0xc7, 0x6c, 0xbe, 0x15, 0x8b, 0x67, + 0x45, 0x9c, 0x38, 0xad, 0x43, 0x0e, 0x70, 0x90, 0x93, 0x10, 0x48, 0xc7, 0xb8, 0xd4, 0xa2, 0x83, 0x9a, 0xe5, 0xbc, + 0x06, 0x96, 0x59, 0x04, 0xd9, 0x00, 0x51, 0x4d, 0x53, 0xb1, 0x1a, 0x1e, 0x94, 0xaa, 0x39, 0xa5, 0x52, 0xfb, 0x86, + 0xb3, 0xd5, 0xe9, 0x13, 0xab, 0x36, 0xe1, 0xd6, 0xbf, 0xd5, 0x9e, 0xa0, 0xad, 0xa4, 0x81, 0x50, 0xcf, 0x17, 0xe9, + 0x2d, 0x45, 0xf1, 0x38, 0x33, 0xf1, 0x54, 0x05, 0xc6, 0xbe, 0xb5, 0x23, 0x28, 0x48, 0x9a, 0xae, 0x03, 0x0e, 0xd3, + 0xe8, 0x84, 0xc5, 0x3f, 0xa5, 0x0f, 0xe5, 0x45, 0xad, 0xc0, 0x49, 0xfe, 0x29, 0x5c, 0x44, 0x12, 0x0b, 0xfd, 0x92, + 0x00, 0x48, 0x64, 0xf0, 0x6a, 0x54, 0xac, 0x85, 0x0a, 0x90, 0x53, 0x94, 0xde, 0x2a, 0x3e, 0x2e, 0x45, 0xa9, 0x52, + 0x2a, 0x73, 0xa3, 0x52, 0x40, 0x58, 0x1b, 0x38, 0xba, 0x80, 0x2f, 0x20, 0x68, 0x2d, 0x77, 0x6b, 0xdb, 0xf3, 0x46, + 0xe6, 0x33, 0xd3, 0x3c, 0xad, 0xde, 0xab, 0xbf, 0xdf, 0x2d, 0x31, 0xcc, 0xc6, 0xd3, 0xdf, 0xb7, 0x19, 0xc2, 0xcd, + 0xdf, 0x30, 0x44, 0xb7, 0x00, 0x8e, 0x59, 0xda, 0x43, 0x21, 0x0b, 0x26, 0x58, 0x43, 0x55, 0x9e, 0xf2, 0xd9, 0xcb, + 0x27, 0x3b, 0x40, 0x53, 0x43, 0x17, 0x37, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, 0x03, 0x4e, + 0x0d, 0x00, 0xc5, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x9e, 0xce, 0x79, 0xe1, 0x1f, 0xd1, + 0xaf, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xea, 0xf5, 0x24, 0xbc, 0x13, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, 0xe6, 0x22, + 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x08, 0x8f, 0x58, 0xb3, 0x1b, 0x40, 0x0c, 0x2c, 0x75, 0x48, 0xb2, 0xea, + 0xd8, 0x7e, 0xff, 0xe5, 0xc8, 0xf0, 0xa6, 0x23, 0x22, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, 0x76, 0x66, + 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, 0x9b, 0xe4, + 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x7c, 0xd4, 0x7c, 0x0e, 0xb8, 0x6c, 0x98, 0xfc, 0x72, 0x56, 0xcd, 0xfb, 0x7d, 0x4f, + 0x3e, 0x82, 0x5f, 0x48, 0x5c, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x45, 0x7c, 0x66, 0x06, 0xf1, 0xe8, 0xe6, 0x08, 0xea, + 0xeb, 0xa3, 0xf0, 0x3a, 0xe6, 0x0a, 0x9b, 0x89, 0xe9, 0x4b, 0x18, 0x3c, 0x4f, 0xf8, 0xe0, 0x2d, 0x47, 0x7f, 0x23, + 0x9d, 0x99, 0x82, 0x85, 0x9c, 0xfb, 0x93, 0x97, 0x08, 0x9d, 0x8c, 0x48, 0x0f, 0x3a, 0x9d, 0xa0, 0x21, 0xfb, 0xfd, + 0x05, 0x74, 0x66, 0x2b, 0x95, 0xb2, 0x55, 0x51, 0x99, 0xae, 0xeb, 0xa2, 0xac, 0xa0, 0x63, 0xe9, 0xe7, 0x8d, 0x90, + 0x99, 0xf5, 0x33, 0x0b, 0xf9, 0x69, 0x21, 0xb1, 0xa6, 0x6c, 0xfb, 0x44, 0x6d, 0x90, 0x66, 0x5d, 0xa8, 0x2e, 0x70, + 0xee, 0xac, 0xbd, 0xde, 0x08, 0xf5, 0xcf, 0xf9, 0x68, 0x5d, 0xac, 0x3d, 0x70, 0x89, 0x99, 0xa5, 0x73, 0xc5, 0xa1, + 0x91, 0xfb, 0xa3, 0xcf, 0x45, 0x9a, 0x53, 0x1e, 0xa0, 0x41, 0x14, 0x73, 0xfb, 0x2d, 0x90, 0x7e, 0xe8, 0x2d, 0x90, + 0x7d, 0x74, 0xce, 0xc9, 0x4b, 0x00, 0xa7, 0x43, 0x44, 0xdc, 0x8a, 0x04, 0x1d, 0xab, 0x86, 0x3b, 0x0b, 0xf7, 0xb4, + 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x03, 0xa0, 0x99, 0x22, 0x32, 0x3c, 0xce, 0xc8, 0x6d, 0xd2, 0x42, + 0x30, 0xa5, 0xfd, 0x57, 0x63, 0x48, 0x10, 0x08, 0xf8, 0x3f, 0x85, 0xf7, 0x1e, 0xd0, 0x36, 0x69, 0x03, 0xae, 0x7a, + 0x4c, 0x07, 0x66, 0x4b, 0xce, 0x56, 0x9d, 0x0d, 0x40, 0x39, 0x55, 0x5a, 0x4f, 0x79, 0x5c, 0x53, 0x44, 0xa4, 0xca, + 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x43, 0x8e, 0xca, 0xf4, 0xb6, 0x66, 0x84, 0xd8, 0xa5, 0x9f, 0x2f, + 0x60, 0xc9, 0xc6, 0x1f, 0x70, 0xf2, 0x96, 0x00, 0x69, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, 0x1c, 0x90, + 0x7c, 0xbd, 0xd1, 0x68, 0xa4, 0xfd, 0xe4, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xb6, 0x6e, 0x47, + 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xd7, 0xe6, 0xa3, 0x0f, 0x97, 0xca, 0xda, 0x75, 0xc4, 0xd7, 0x7f, 0x92, + 0xd5, 0xfa, 0x9e, 0x77, 0x55, 0x13, 0xf0, 0x45, 0x15, 0x5b, 0xfa, 0x1d, 0xef, 0xc9, 0xde, 0xc5, 0xd7, 0x3e, 0x62, + 0x97, 0x7c, 0xcf, 0x5b, 0xd4, 0x79, 0xbe, 0xf2, 0x75, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, 0xa3, 0xa6, + 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7a, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, 0x1a, 0xfa, + 0xd0, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0x87, 0xde, 0x92, 0x93, 0x43, 0x82, 0xc1, 0xa9, 0x31, + 0x7f, 0x78, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x89, 0xc9, 0x7c, 0x7a, 0x4c, 0x3b, 0x0a, 0x30, 0xa3, 0x4a, 0x6f, + 0x9f, 0x1e, 0xd8, 0x8e, 0x97, 0xf5, 0xd0, 0xd2, 0xbb, 0x27, 0x47, 0xb7, 0xe3, 0x55, 0x35, 0xbe, 0x94, 0x43, 0x9e, + 0xe7, 0xb3, 0xd1, 0x68, 0x24, 0x0c, 0x3a, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x19, 0x5c, 0x54, 0x1f, 0xca, 0xa5, 0xb7, + 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0x70, 0x4e, 0x0a, 0x25, 0x47, 0xc9, 0x5a, + 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x21, 0x1f, 0x82, 0x9f, 0x3d, 0x50, 0x8b, 0x3f, + 0xd5, 0x82, 0xd8, 0x43, 0x9f, 0x2a, 0xa5, 0x43, 0xbc, 0x2a, 0x20, 0x44, 0x18, 0xf0, 0x06, 0xda, 0x41, 0x09, 0x0e, + 0x3b, 0xdc, 0x7b, 0x44, 0x88, 0x7e, 0xe1, 0xe5, 0x33, 0x19, 0xae, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x88, 0x95, 0x3e, + 0x03, 0x17, 0x4c, 0x40, 0x3d, 0xc5, 0xa7, 0xe8, 0x5f, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x80, 0x8a, 0xe8, 0xd9, + 0xcf, 0xc7, 0x00, 0xde, 0xd9, 0xb5, 0x19, 0x69, 0x2f, 0x7f, 0x03, 0x0c, 0x2b, 0x25, 0x89, 0x76, 0x4e, 0x89, 0xc0, + 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x93, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, 0x01, 0x8f, + 0x0e, 0x40, 0xe5, 0x4a, 0x41, 0xee, 0x35, 0x47, 0x72, 0xc7, 0x8f, 0xbd, 0x1f, 0x07, 0xf5, 0xe0, 0xc7, 0xde, 0x59, + 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0x7e, 0x1c, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, 0x8b, 0xdc, + 0x6a, 0xa2, 0xc6, 0x4d, 0x78, 0x9b, 0x48, 0x1a, 0xa2, 0xbb, 0xce, 0x23, 0x62, 0x01, 0x20, 0x59, 0x7c, 0x36, 0x6f, + 0x28, 0xea, 0xdd, 0x84, 0x6f, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x55, 0x9e, 0xd6, 0x3d, 0x1d, 0x2a, 0x83, 0x2f, 0x48, + 0x35, 0x01, 0x1e, 0xed, 0x2f, 0xcc, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, 0x66, 0x3d, + 0x44, 0xe4, 0xce, 0x32, 0x63, 0x6f, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0xc2, 0xda, 0x4a, 0x02, + 0x74, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x01, 0x17, 0x1d, 0x5b, 0x0b, 0xc5, 0xc6, 0x0b, 0xd0, 0x97, + 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x71, 0x5b, 0x3e, 0x50, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, 0x66, 0xd1, + 0xee, 0xa7, 0x8a, 0x57, 0x88, 0x5b, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0xe8, 0xd2, 0x34, 0x03, + 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x02, 0x18, 0x17, 0x58, + 0xe9, 0x23, 0x1b, 0x19, 0x2c, 0xb6, 0x08, 0x70, 0xcb, 0x91, 0x3e, 0x4c, 0xc3, 0xc9, 0x36, 0x9a, 0xc3, 0x24, 0xcd, + 0xef, 0xc2, 0x2c, 0x95, 0xd0, 0x12, 0xaf, 0x64, 0x8d, 0x11, 0x0b, 0x48, 0xdf, 0xa7, 0x17, 0x45, 0x16, 0x13, 0x24, + 0x9c, 0xf5, 0xd4, 0x01, 0x54, 0x93, 0x73, 0xad, 0x69, 0xf5, 0xac, 0x36, 0x79, 0xc8, 0x02, 0x9d, 0x3d, 0x18, 0x93, + 0x5a, 0x6e, 0xe8, 0x91, 0xfd, 0x95, 0xe3, 0x19, 0xe1, 0xbb, 0x9e, 0xe1, 0xd4, 0x7f, 0x1f, 0x6b, 0x20, 0x65, 0x4a, + 0x00, 0x41, 0x06, 0x47, 0x13, 0x42, 0x79, 0x3a, 0x26, 0x53, 0x9b, 0x1f, 0x81, 0x70, 0x44, 0xf0, 0x0a, 0x9e, 0x1b, + 0x5a, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0xc8, 0xe2, 0x05, 0xbf, 0x07, 0x64, 0x4e, 0xbd, 0x2a, 0x64, 0xcf, + 0x9e, 0x8b, 0xe9, 0x6c, 0x1e, 0x7c, 0x4c, 0x68, 0xff, 0x62, 0xc2, 0x6f, 0xba, 0xab, 0xe4, 0xca, 0xd4, 0xba, 0x37, + 0xd1, 0x63, 0x2e, 0x77, 0xfa, 0xb4, 0xe2, 0x18, 0xf1, 0x0c, 0x56, 0x01, 0x39, 0x67, 0x43, 0xfe, 0xf4, 0x1c, 0xb0, + 0x5b, 0x56, 0xc2, 0x8b, 0xf8, 0xd3, 0x50, 0x56, 0x0b, 0x90, 0x1f, 0x39, 0x8f, 0xcc, 0x2f, 0x5f, 0x6d, 0x87, 0x72, + 0x4e, 0x51, 0x44, 0xcb, 0xa9, 0x69, 0x49, 0x21, 0x3b, 0xf4, 0x14, 0x4c, 0xa6, 0xb6, 0xfc, 0x7d, 0x9f, 0xb8, 0x24, + 0xdf, 0x4c, 0x22, 0xfb, 0x3a, 0xc0, 0x9a, 0xb5, 0xea, 0x1e, 0xba, 0x21, 0x18, 0x20, 0x32, 0x42, 0x99, 0xcd, 0xf5, + 0xdd, 0x7a, 0x30, 0x50, 0x30, 0xbf, 0x82, 0x6e, 0x5a, 0x74, 0x8a, 0x03, 0xe4, 0xac, 0x75, 0x8d, 0x4a, 0x55, 0x71, + 0xe8, 0x30, 0xef, 0x96, 0x55, 0xd9, 0x65, 0xe9, 0x85, 0x20, 0x35, 0xea, 0x2a, 0x58, 0xa4, 0x54, 0x44, 0xf1, 0x9e, + 0xfc, 0x1a, 0x98, 0x78, 0x66, 0xe5, 0x28, 0x8d, 0xe7, 0x80, 0x18, 0xa4, 0x80, 0x38, 0xe5, 0x57, 0x80, 0x26, 0xba, + 0x88, 0xc2, 0xec, 0x55, 0x5c, 0x05, 0xb5, 0xd5, 0xf4, 0x3f, 0x1d, 0xc8, 0xd8, 0xf3, 0xba, 0xdf, 0x4f, 0x89, 0xd1, + 0x0f, 0xa3, 0x30, 0xf0, 0xef, 0xf1, 0x74, 0xdf, 0x04, 0xa9, 0x79, 0xe5, 0x23, 0xbc, 0xa2, 0xcb, 0xad, 0x4d, 0xb9, + 0xa2, 0x71, 0xe1, 0xaf, 0x11, 0x1c, 0x3e, 0x75, 0x14, 0xdb, 0x6d, 0xaa, 0x9c, 0xda, 0x18, 0x0c, 0x42, 0xb8, 0x6f, + 0x65, 0xfc, 0xcf, 0xc4, 0xcb, 0x67, 0xd1, 0x1c, 0x14, 0xa5, 0x99, 0xe6, 0x0b, 0x29, 0xa4, 0x9b, 0x00, 0x7d, 0x34, + 0x08, 0xb5, 0xba, 0xf2, 0x4d, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, 0x32, + 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x8d, 0xd5, 0x0c, 0xd5, 0x8a, 0xa3, 0x26, 0xa8, 0x51, 0xfa, 0x08, 0x17, + 0xc0, 0x7f, 0xd0, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x31, 0x62, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, 0x5d, + 0x33, 0xfa, 0x7d, 0x19, 0x32, 0x64, 0x92, 0x90, 0xa7, 0x0f, 0x97, 0xeb, 0x07, 0x52, 0x5d, 0x00, 0xbf, 0x72, 0xc5, + 0x66, 0xbd, 0xde, 0x1c, 0xe0, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xfc, 0xae, 0xfa, 0x11, 0x66, + 0x19, 0x54, 0x01, 0x19, 0x7f, 0x2c, 0xa8, 0xe2, 0xdc, 0xc5, 0xa4, 0x7e, 0x39, 0x52, 0x17, 0x94, 0x59, 0x3a, 0xb7, + 0x38, 0x41, 0xc0, 0x79, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0xf0, 0xd9, 0xac, + 0x1f, 0xc2, 0xfe, 0x01, 0x91, 0x85, 0xfa, 0x9b, 0xd7, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xee, 0x63, 0x38, 0x35, + 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x64, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, 0xa3, + 0x14, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x6e, 0x73, 0x0b, 0xf2, 0xfa, 0x91, 0x8b, 0x5f, 0x9c, 0x22, 0x3d, 0x8b, 0x2e, + 0x30, 0xd0, 0x05, 0x99, 0x37, 0xfe, 0x55, 0xc1, 0xca, 0x05, 0xf4, 0x5e, 0x2a, 0x56, 0x72, 0xb2, 0xed, 0xd4, 0x1f, + 0xa5, 0xb2, 0xdf, 0x9e, 0x59, 0x13, 0xf8, 0x5d, 0x62, 0xbf, 0x44, 0x26, 0xdf, 0xf4, 0xd8, 0xe4, 0x2b, 0xc3, 0xa2, + 0x53, 0xcb, 0xe0, 0x9c, 0x1e, 0x19, 0x9c, 0x7b, 0x3b, 0xab, 0x36, 0x11, 0x0c, 0x05, 0x49, 0xa0, 0xe9, 0xd2, 0xc3, + 0xba, 0xe9, 0xcf, 0x4f, 0x5a, 0x54, 0x5b, 0xb5, 0x6f, 0xdd, 0x8f, 0x43, 0xec, 0xe2, 0x77, 0x89, 0x67, 0x88, 0x48, + 0x7d, 0xa0, 0x03, 0x93, 0xc1, 0x13, 0x97, 0xfd, 0x3e, 0x14, 0x36, 0x1b, 0xcf, 0x47, 0x75, 0xf1, 0xba, 0xb8, 0x07, + 0x54, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0x71, 0x1d, 0xe6, 0x20, 0xef, 0x68, + 0x78, 0x9c, 0x33, 0x10, 0xc3, 0xe0, 0xeb, 0x3f, 0x3e, 0xda, 0xa7, 0xcd, 0x8f, 0x67, 0xf0, 0xdd, 0xd1, 0xd9, 0x7b, + 0xa4, 0xbb, 0x39, 0x5b, 0x97, 0xc5, 0x5d, 0x1a, 0x8b, 0xb3, 0x1f, 0x21, 0xf5, 0xc7, 0xb3, 0xa2, 0x3c, 0xfb, 0x51, + 0x55, 0xe6, 0xc7, 0x33, 0x5a, 0x70, 0xa3, 0x3f, 0xac, 0x89, 0xf7, 0x7b, 0xa5, 0x19, 0xd0, 0x96, 0x10, 0x99, 0xa5, + 0xd5, 0x8f, 0xa0, 0x44, 0x54, 0xfc, 0xa8, 0x32, 0xaa, 0xd5, 0xda, 0x71, 0xde, 0x27, 0x1a, 0x29, 0x9b, 0x26, 0x24, + 0xae, 0x96, 0xb0, 0x0e, 0xf5, 0xec, 0xb4, 0xf9, 0x76, 0x9c, 0x07, 0xea, 0x80, 0xc8, 0xf9, 0xd3, 0x7c, 0xb4, 0xa5, + 0xaf, 0xc1, 0xb7, 0x0e, 0x87, 0x7c, 0xb4, 0x33, 0x3f, 0x7d, 0xb2, 0x56, 0xca, 0xb8, 0x23, 0xd9, 0x3b, 0x58, 0x5b, + 0xe0, 0x04, 0x01, 0x0e, 0x00, 0xff, 0x70, 0xa0, 0xdf, 0x3b, 0xf9, 0x5b, 0xed, 0x96, 0x56, 0x3d, 0x9f, 0xb5, 0xb8, + 0x33, 0x5e, 0xd5, 0x86, 0xa8, 0x6d, 0x2f, 0xb1, 0xa5, 0xf7, 0x4d, 0x83, 0x9a, 0x22, 0xfa, 0x09, 0xab, 0x89, 0x55, + 0x1c, 0x16, 0xa4, 0x84, 0x24, 0x86, 0x63, 0xb4, 0x43, 0x8f, 0xd3, 0xc5, 0xd2, 0x93, 0xfb, 0x0e, 0x2f, 0xb7, 0xbe, + 0x0f, 0x48, 0x5a, 0x85, 0xf3, 0x77, 0x5e, 0x68, 0xe0, 0xd1, 0x8b, 0xbc, 0x2a, 0x32, 0x31, 0x12, 0x34, 0xca, 0xaf, + 0x48, 0x9c, 0x39, 0xc3, 0x5a, 0x9c, 0x29, 0xb0, 0xb0, 0x90, 0x20, 0xc1, 0x8b, 0x92, 0xd2, 0x83, 0xb3, 0x47, 0xfb, + 0xb2, 0xf9, 0x83, 0xe0, 0x21, 0x46, 0x0b, 0x60, 0xc4, 0xd9, 0xb5, 0xcb, 0xbb, 0x0f, 0xcb, 0xdc, 0xfb, 0xe3, 0xd5, + 0x6d, 0x5e, 0x40, 0x88, 0xe6, 0x99, 0x54, 0xac, 0x96, 0x67, 0xc0, 0x98, 0x27, 0xe2, 0xb3, 0xb0, 0x92, 0xd3, 0xa0, + 0xea, 0x28, 0x56, 0x6d, 0xe3, 0x51, 0xee, 0x01, 0xc5, 0xf7, 0xfb, 0x04, 0xb8, 0xdc, 0x7d, 0xf6, 0x52, 0xb9, 0xa6, + 0x92, 0x1e, 0x79, 0x0e, 0xd1, 0x92, 0x8f, 0x12, 0xa0, 0x78, 0x86, 0x38, 0x49, 0x61, 0xf5, 0xdc, 0x04, 0xa9, 0xc8, + 0xd7, 0x27, 0x14, 0x5f, 0x34, 0x8f, 0xa2, 0x86, 0x85, 0x2c, 0x81, 0xe3, 0x21, 0x99, 0x65, 0x73, 0x64, 0x29, 0x4f, + 0xdb, 0x53, 0xa4, 0xa3, 0x13, 0x4b, 0xfc, 0xb6, 0xe6, 0xd7, 0x8b, 0x54, 0x04, 0x26, 0xed, 0x6c, 0x61, 0xee, 0x85, + 0x30, 0x54, 0x09, 0xf7, 0x5e, 0xd5, 0xb3, 0x50, 0x6e, 0x8a, 0x56, 0xc5, 0xec, 0x61, 0x4a, 0xcc, 0x30, 0xc5, 0xfa, + 0x0b, 0x1b, 0x7e, 0x9d, 0x78, 0x31, 0x18, 0xae, 0x97, 0xbc, 0x9c, 0x6d, 0xcc, 0x42, 0x38, 0x1c, 0x36, 0x93, 0x62, + 0xb6, 0x84, 0x30, 0xd7, 0xe5, 0xfc, 0x70, 0xe8, 0x6a, 0xd9, 0x5a, 0x78, 0xf0, 0x50, 0xb5, 0x70, 0xd3, 0xb0, 0x1c, + 0x7e, 0x26, 0xb3, 0x18, 0xdb, 0xd7, 0xf8, 0xcc, 0xfe, 0x7c, 0xd1, 0x3d, 0x4b, 0x90, 0x7c, 0x63, 0x0d, 0xb4, 0x63, + 0xb3, 0x76, 0x87, 0xab, 0x11, 0x90, 0x94, 0xee, 0x46, 0xe7, 0x58, 0x76, 0xf2, 0x94, 0x20, 0x77, 0xb4, 0x02, 0xfb, + 0xdd, 0x37, 0xfe, 0x44, 0x8b, 0x3d, 0x68, 0xb7, 0xb1, 0x25, 0x44, 0x35, 0xed, 0xb9, 0x5c, 0x29, 0x96, 0x6e, 0xb0, + 0xb4, 0xd1, 0xf3, 0x61, 0x7d, 0xee, 0x1b, 0x39, 0x50, 0x30, 0x46, 0x3c, 0xb5, 0x0e, 0xa2, 0xd9, 0x1c, 0x68, 0x30, + 0xd0, 0x3c, 0xc2, 0x53, 0x0b, 0x1d, 0x94, 0x59, 0x1b, 0xf6, 0x4f, 0xc9, 0xc9, 0xf2, 0x38, 0x7c, 0x0b, 0xff, 0xf2, + 0x19, 0x36, 0x89, 0x29, 0xb6, 0xc7, 0x2f, 0x95, 0xa2, 0xc2, 0x63, 0x3b, 0xe2, 0x5a, 0xfb, 0x28, 0x6a, 0x43, 0xe5, + 0xf0, 0x6f, 0x61, 0x1f, 0x61, 0x5f, 0xd0, 0x04, 0x61, 0xb0, 0xeb, 0xcf, 0x04, 0x42, 0xc4, 0x42, 0xbc, 0xe0, 0x97, + 0x4a, 0x52, 0xd1, 0x09, 0x9f, 0xed, 0x4a, 0xe0, 0xad, 0xc3, 0x80, 0x3e, 0x21, 0x3f, 0x13, 0x09, 0x43, 0x33, 0xa1, + 0x77, 0xf4, 0xdf, 0x89, 0x9d, 0x6c, 0x92, 0x5b, 0x21, 0x1f, 0x48, 0x2a, 0x09, 0x26, 0x58, 0x79, 0xa1, 0x7c, 0xe5, + 0x5e, 0x28, 0xb5, 0xd6, 0x82, 0xd6, 0x2f, 0xff, 0x29, 0xf1, 0x0c, 0xfe, 0x1e, 0xc8, 0x18, 0x74, 0x1b, 0x51, 0x4d, + 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x67, 0xeb, 0x2c, 0xac, 0x97, 0x45, 0xb9, 0x6a, 0x45, 0x8a, 0xca, + 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x22, 0x1f, 0x3c, 0x02, 0x60, 0x3c, 0xca, 0xd3, 0xaa, 0xa3, 0xb4, + 0x7e, 0x60, 0x19, 0x30, 0x02, 0x27, 0xca, 0x80, 0x47, 0x58, 0x06, 0xe6, 0x69, 0x97, 0xa1, 0x06, 0xb1, 0x46, 0xd5, + 0x95, 0xda, 0x60, 0x4e, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, 0x31, 0x34, 0x75, 0xe5, 0x91, 0xf5, 0x92, 0x13, 0xf6, + 0x64, 0x37, 0x90, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0x5d, 0xcb, 0x12, 0xe5, 0xa2, 0x5b, 0x46, 0x94, 0x89, 0x90, 0xfa, + 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0xb4, 0x6f, 0x8f, 0x14, 0xbd, 0x60, 0xd0, 0x3e, 0xed, 0x91, 0x52, 0xcf, + 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0xdf, 0xa0, 0x7c, 0x07, 0x33, 0xe3, 0x6c, 0xf6, 0x87, 0xde, 0xdc, + 0x1e, 0xed, 0xeb, 0xe6, 0x0f, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, 0x13, 0x9f, 0x29, 0x16, 0x2a, 0xab, 0x10, 0x2b, 0x48, + 0xfb, 0xdf, 0xc2, 0xfb, 0x03, 0xde, 0x1a, 0xa1, 0x59, 0x19, 0x0f, 0xf3, 0xd1, 0xa3, 0xbd, 0x68, 0xfe, 0xe8, 0x2c, + 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0x7f, 0x1c, 0x25, 0xcd, 0xd9, 0xc3, 0x35, 0x92, 0x3a, 0xc0, 0x87, 0xeb, 0x33, 0x7c, + 0xa0, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0x1f, 0xad, 0xe7, 0xf4, 0xf1, 0x63, 0x39, 0xdd, 0x92, 0x22, + 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xbc, 0x19, 0xd2, 0xbb, 0x6e, 0x95, 0xd4, 0x65, 0x8f, 0x12, 0x41, + 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, 0x9b, 0xd5, 0x9c, 0x00, 0x11, 0x01, 0xad, 0x55, 0xde, + 0x07, 0x8e, 0xf9, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x73, 0xa5, 0xbd, 0x92, 0x02, 0xfa, 0x39, 0xc8, 0xdc, 0x3e, + 0xba, 0xe5, 0xaa, 0x65, 0x9e, 0x4b, 0x5b, 0x0e, 0x58, 0xb4, 0x10, 0xa8, 0xd9, 0xb9, 0x74, 0x38, 0x50, 0x10, 0xea, + 0x4a, 0x54, 0x11, 0x57, 0x47, 0xd1, 0x42, 0xd4, 0x6a, 0xd5, 0x2e, 0x27, 0x9b, 0x0a, 0xd9, 0x92, 0x08, 0x32, 0x4a, + 0xf6, 0x4a, 0xa8, 0x8f, 0x72, 0xb5, 0x67, 0x1a, 0x0e, 0xd0, 0x04, 0x6c, 0xda, 0xe0, 0x6f, 0x81, 0x7b, 0x19, 0x9c, + 0x99, 0xf6, 0x69, 0x18, 0x01, 0xa7, 0x39, 0xc4, 0xfc, 0xf9, 0x5d, 0x0f, 0x2a, 0x78, 0xd0, 0x91, 0xfe, 0xaa, 0x9e, + 0x15, 0x78, 0xe6, 0x9e, 0x78, 0xfe, 0xf2, 0x44, 0x7a, 0x99, 0xc3, 0x03, 0x4d, 0x83, 0x98, 0xf1, 0x67, 0x65, 0x19, + 0xee, 0x46, 0xcb, 0xb2, 0x58, 0x79, 0x91, 0xde, 0xc7, 0x33, 0x29, 0x06, 0x12, 0x33, 0x66, 0x46, 0x57, 0xb1, 0x8e, + 0x73, 0x18, 0xf7, 0xf6, 0x24, 0xac, 0xd0, 0xfe, 0x59, 0x62, 0xaf, 0x0b, 0xc0, 0x72, 0xc8, 0x1a, 0xb4, 0xc2, 0x3b, + 0xdd, 0xde, 0xee, 0x71, 0xc9, 0x8e, 0xe2, 0x06, 0xd0, 0xcf, 0x6a, 0x68, 0x99, 0xa0, 0x96, 0x59, 0x77, 0x32, 0x99, + 0x22, 0xb9, 0x7c, 0x1b, 0xf6, 0x92, 0x95, 0xf9, 0xbc, 0x91, 0xdb, 0xc3, 0xdb, 0x70, 0x25, 0x62, 0x6d, 0x41, 0x27, + 0x1d, 0x19, 0x87, 0x7b, 0xa1, 0xb9, 0x91, 0xee, 0x1f, 0x55, 0x49, 0x58, 0x8a, 0x18, 0x6e, 0x81, 0x6c, 0xaf, 0xb6, + 0x95, 0xa0, 0x04, 0x3e, 0xd8, 0xf7, 0xa5, 0x58, 0xa6, 0x5b, 0x01, 0xb8, 0x0e, 0xfc, 0x37, 0x89, 0x48, 0xe8, 0xee, + 0x3c, 0x44, 0xb1, 0x46, 0xde, 0x37, 0x88, 0xc6, 0xfe, 0x09, 0xe4, 0x34, 0x20, 0x13, 0x29, 0x46, 0xb2, 0x60, 0xe0, + 0x03, 0xc8, 0xf9, 0x1a, 0x4c, 0x72, 0xd3, 0xdc, 0xf3, 0x83, 0x5c, 0x77, 0x30, 0xed, 0x83, 0xee, 0xc5, 0xb5, 0x66, + 0x39, 0x78, 0xc5, 0x44, 0xfc, 0x1f, 0xb5, 0x57, 0xb2, 0x9c, 0x65, 0x7e, 0x63, 0x2e, 0x3a, 0x19, 0x5c, 0x35, 0x84, + 0x5f, 0xcc, 0xb2, 0x39, 0x8f, 0x66, 0x99, 0x8e, 0xfa, 0x2f, 0x9a, 0xa3, 0x52, 0x00, 0x4e, 0x1d, 0x2f, 0xc0, 0x1a, + 0xfa, 0x4a, 0x37, 0xad, 0x78, 0xa0, 0x31, 0x46, 0x41, 0x85, 0x0e, 0x42, 0xff, 0xa8, 0x01, 0x69, 0x83, 0x49, 0x9a, + 0x84, 0xca, 0x07, 0x17, 0x74, 0xc3, 0xd8, 0x5c, 0xb9, 0x5c, 0x35, 0xa9, 0x5a, 0x7e, 0x39, 0xa2, 0xbe, 0xab, 0x25, + 0x97, 0x6a, 0xf3, 0xa9, 0x51, 0xd6, 0x08, 0x32, 0x39, 0x4a, 0xbf, 0x4f, 0xb9, 0x70, 0x2b, 0x63, 0xb2, 0x3e, 0x1c, + 0xbc, 0x82, 0x9b, 0x1a, 0xbf, 0xc8, 0x89, 0x50, 0xd4, 0x1e, 0x12, 0x61, 0x6b, 0xb7, 0x42, 0xf7, 0x1e, 0x37, 0x4a, + 0xf3, 0x28, 0xdb, 0xc4, 0xa2, 0xf2, 0x7a, 0x09, 0x58, 0x8b, 0x7b, 0xc0, 0x8b, 0x4a, 0x4b, 0xbf, 0x62, 0x05, 0xa0, + 0x07, 0x48, 0x61, 0xe3, 0x05, 0x32, 0x60, 0xbd, 0xf3, 0x52, 0xbf, 0xdf, 0x37, 0xa6, 0xfc, 0x77, 0xf7, 0x39, 0x90, + 0x14, 0x8a, 0xb2, 0xde, 0xc1, 0x04, 0x82, 0x6b, 0x27, 0x69, 0xcf, 0x6a, 0xfe, 0x74, 0x5d, 0x7b, 0xc0, 0x6f, 0xe5, + 0x5b, 0x24, 0x56, 0x9f, 0xec, 0x8b, 0xcd, 0x3e, 0xad, 0x3e, 0x1a, 0x8d, 0x83, 0x60, 0x69, 0xf5, 0x4a, 0xab, 0x1c, + 0xf2, 0x86, 0x17, 0x20, 0x52, 0x59, 0x57, 0xd7, 0xca, 0xb9, 0xba, 0x16, 0x1c, 0xb9, 0x64, 0x4b, 0x9e, 0xc3, 0x7f, + 0x21, 0xf7, 0xca, 0xc3, 0xa1, 0xf0, 0xfb, 0xfd, 0x74, 0x46, 0x5a, 0x59, 0x60, 0x4f, 0x5b, 0xd7, 0x5e, 0xe8, 0x1f, + 0x0e, 0x2f, 0xc0, 0x6b, 0xc4, 0x3f, 0x1c, 0xca, 0x7e, 0xff, 0x83, 0xb9, 0xc9, 0x9c, 0x8f, 0x95, 0x52, 0xf6, 0x12, + 0x95, 0xee, 0xaf, 0x13, 0xde, 0xfb, 0xdf, 0xa3, 0xff, 0x3d, 0xba, 0xec, 0xc9, 0xae, 0xff, 0x90, 0xf0, 0x19, 0xde, + 0xd0, 0x99, 0xba, 0x9c, 0x33, 0xe9, 0xee, 0xae, 0xfc, 0xd0, 0x7b, 0x1a, 0x2a, 0xbe, 0x37, 0x37, 0x6d, 0xfc, 0x47, + 0x75, 0xa4, 0x49, 0xe8, 0xb8, 0xe8, 0x1f, 0x0e, 0x1f, 0x12, 0xad, 0x4f, 0x4b, 0x95, 0x3e, 0x4d, 0xe1, 0x28, 0x19, + 0x72, 0x37, 0xb7, 0x30, 0x1d, 0xd8, 0x8f, 0x9b, 0xaf, 0x92, 0x17, 0x67, 0x29, 0x5c, 0x7b, 0xf3, 0x59, 0x3a, 0x9f, + 0x82, 0x75, 0x65, 0x98, 0xcf, 0xea, 0x79, 0x00, 0xa9, 0x43, 0x48, 0xb3, 0xa6, 0xe1, 0x3f, 0x2b, 0x57, 0xf0, 0xd6, + 0x1e, 0xef, 0x06, 0x2e, 0x4a, 0x1d, 0xe9, 0x93, 0x36, 0x9a, 0x2e, 0xa9, 0xe4, 0x3f, 0x88, 0x3c, 0xc6, 0x98, 0x8d, + 0x17, 0xc4, 0xfb, 0x59, 0xe4, 0xd7, 0x05, 0x60, 0x17, 0x01, 0x18, 0x72, 0x3a, 0x77, 0x24, 0xf1, 0x97, 0xc9, 0xf7, + 0x7f, 0x4c, 0x97, 0xf6, 0xbe, 0x2c, 0x6e, 0x4b, 0x51, 0x55, 0x47, 0xa5, 0x6d, 0x6d, 0xb9, 0x1e, 0x98, 0x44, 0xfb, + 0x7d, 0xc9, 0x24, 0x9a, 0x62, 0x28, 0x0a, 0xdc, 0x1a, 0x7b, 0xd3, 0x94, 0x2b, 0xc6, 0xea, 0x91, 0xb1, 0x7e, 0x3e, + 0xdf, 0xbd, 0x8a, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x94, 0x52, 0x8a, 0x7c, 0x70, 0x3e, 0xc3, 0x54, 0xa2, + 0xd6, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x57, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, + 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0xa7, 0xc2, 0xe2, 0xfb, 0xf5, 0xc9, 0x91, + 0xa0, 0x31, 0x93, 0xe5, 0xed, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, + 0x2c, 0x9e, 0x72, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x4f, 0x81, 0x8e, 0xf9, 0x29, + 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x5c, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0xaf, 0x16, 0xe5, 0x95, 0x5c, 0x10, 0xfa, + 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0xff, + 0x2e, 0x5a, 0x0c, 0x5e, 0x86, 0x75, 0x32, 0xca, 0xd2, 0xf5, 0x14, 0xf8, 0xf5, 0x02, 0x38, 0x8b, 0xcc, 0x2b, 0x9f, + 0x9d, 0x3d, 0x60, 0x8b, 0xc6, 0x53, 0x20, 0x47, 0xa5, 0x3f, 0xf2, 0xc6, 0xe8, 0xf4, 0x44, 0xbf, 0x9f, 0x4f, 0x29, + 0xe6, 0xeb, 0xef, 0x00, 0xcf, 0x55, 0xcb, 0x05, 0xe8, 0xcb, 0x50, 0x07, 0x95, 0x28, 0xb5, 0x62, 0x18, 0xb1, 0xf0, + 0x77, 0x81, 0x44, 0xce, 0x14, 0xd8, 0xac, 0xa2, 0x24, 0x54, 0xa2, 0x52, 0xb2, 0x35, 0x41, 0x2d, 0xbd, 0x2f, 0xca, + 0x7a, 0x5f, 0x81, 0xa3, 0x64, 0xa4, 0xcd, 0x72, 0xd2, 0x8c, 0x2b, 0x50, 0xe6, 0xa2, 0x1f, 0xec, 0xef, 0x95, 0xe7, + 0x37, 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, + 0x0b, 0xb6, 0xfd, 0x57, 0x09, 0x52, 0x2c, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0xbf, 0x21, 0xd4, 0x16, 0x07, 0xf6, 0xd8, + 0x85, 0x89, 0xf8, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, + 0x27, 0xf7, 0xb3, 0xfb, 0xb4, 0x4e, 0xce, 0x5e, 0xbd, 0x38, 0xfb, 0xb1, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0xfd, + 0x78, 0xb6, 0xda, 0x00, 0x5a, 0xa6, 0x38, 0x8b, 0xc9, 0x94, 0x26, 0xe2, 0x33, 0x32, 0x0c, 0x9e, 0xd5, 0x89, 0x38, + 0xa3, 0x89, 0xe9, 0xbe, 0x46, 0x69, 0xf2, 0xed, 0x28, 0xcc, 0xe1, 0xe5, 0x52, 0x6c, 0x2a, 0x11, 0x83, 0x9d, 0x52, + 0xcd, 0xb3, 0xbc, 0x7d, 0x16, 0xe7, 0xa3, 0x0e, 0x59, 0xa5, 0x03, 0x7f, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, + 0x1e, 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0xc8, 0x13, 0x08, 0xb5, 0x60, 0x4e, 0xa6, 0x11, 0xdd, 0x90, 0xae, 0xb1, + 0xcf, 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x43, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, + 0xeb, 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x22, 0x07, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, + 0x14, 0xfa, 0xa5, 0xe1, 0x28, 0x63, 0xfe, 0x3c, 0xd4, 0x1c, 0x01, 0xf5, 0x96, 0x87, 0x8a, 0x2e, 0x00, 0x97, 0x73, + 0xc4, 0x8c, 0xf3, 0x1e, 0x77, 0x81, 0x39, 0x15, 0x05, 0x85, 0xba, 0x0e, 0x96, 0x0a, 0x80, 0xde, 0xd4, 0x47, 0x7a, + 0x4e, 0xfe, 0x1f, 0xde, 0xde, 0x85, 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, + 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, + 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, + 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0x6c, 0x97, 0x60, + 0xf1, 0xdc, 0xc0, 0xe2, 0xd5, 0xc5, 0xa2, 0xba, 0xe2, 0x5a, 0x6e, 0x61, 0x53, 0xca, 0x2a, 0x86, 0x00, 0x02, 0xcd, + 0x98, 0x61, 0xb7, 0xdc, 0xe5, 0x48, 0xd6, 0x45, 0xc1, 0xc5, 0x5e, 0x60, 0xe8, 0x66, 0x5c, 0x32, 0x73, 0x70, 0x35, + 0xc3, 0x3a, 0xa9, 0x28, 0xc0, 0xae, 0x2e, 0x40, 0xf6, 0xc2, 0x50, 0xd7, 0xcd, 0x6c, 0xb9, 0x0e, 0x7c, 0x5d, 0xba, + 0xf0, 0x25, 0x05, 0x2f, 0x57, 0x52, 0x94, 0xd9, 0x35, 0xff, 0xc9, 0xbe, 0x6c, 0xc6, 0x92, 0x42, 0x3b, 0xd2, 0xd7, + 0xed, 0xee, 0x68, 0x31, 0x8e, 0x2d, 0xc7, 0xb7, 0x54, 0xba, 0xd6, 0xa3, 0xea, 0x85, 0xd0, 0xd6, 0xb9, 0x96, 0x59, + 0x9a, 0x72, 0xf1, 0x4a, 0xa4, 0x59, 0xe2, 0x25, 0xc7, 0x3a, 0x56, 0xb5, 0x0b, 0x82, 0xe5, 0xc2, 0x24, 0x3f, 0xcb, + 0x4a, 0x8c, 0x1d, 0xdc, 0x68, 0x54, 0x2b, 0xea, 0x94, 0x89, 0x81, 0x21, 0xdf, 0x63, 0xf0, 0x6d, 0x56, 0x24, 0xc0, + 0xf0, 0x63, 0xa2, 0xbe, 0xa4, 0xa7, 0x10, 0xf0, 0x41, 0x85, 0xe6, 0x7e, 0xc6, 0x11, 0xfc, 0xda, 0xaa, 0xcc, 0x81, + 0xc9, 0xd6, 0x2a, 0x48, 0xc4, 0xbd, 0xcb, 0xe6, 0x7a, 0x11, 0x2d, 0xd4, 0x5d, 0xa8, 0x17, 0xef, 0x76, 0xbd, 0x44, + 0xd1, 0x01, 0x27, 0x3f, 0x0d, 0x5e, 0xc4, 0x59, 0xce, 0xd3, 0x83, 0x4a, 0x1e, 0xa8, 0x0d, 0x75, 0xa0, 0x9c, 0x39, + 0x60, 0xe7, 0x7d, 0x5b, 0x1d, 0xe8, 0x35, 0x7d, 0xa0, 0xdb, 0x79, 0x00, 0x17, 0x0c, 0xdc, 0xb9, 0x97, 0xd9, 0x35, + 0x17, 0x07, 0xa0, 0x0c, 0xb4, 0xc6, 0x03, 0x75, 0x59, 0x8d, 0xd4, 0xc4, 0xe8, 0x18, 0xd6, 0x89, 0x3e, 0x98, 0x03, + 0xfa, 0x33, 0x84, 0xb5, 0x6f, 0xbd, 0x5d, 0xe9, 0x83, 0x36, 0xa0, 0x2f, 0x96, 0xa6, 0x0f, 0x3a, 0x70, 0xbc, 0x8a, + 0x0e, 0xdc, 0x18, 0x52, 0x0d, 0xda, 0x6a, 0x64, 0x15, 0x28, 0xde, 0xf0, 0x16, 0xef, 0xde, 0xb5, 0x64, 0xeb, 0xbd, + 0x44, 0x8c, 0xaf, 0x4c, 0x54, 0x71, 0x26, 0x4e, 0xbd, 0x54, 0x5e, 0x6b, 0x27, 0x19, 0x61, 0x7c, 0xcb, 0x4a, 0xea, + 0xef, 0x10, 0x73, 0x8b, 0x34, 0x87, 0xc1, 0xab, 0xb0, 0x22, 0x33, 0xde, 0xef, 0xcb, 0x99, 0x8c, 0xca, 0x99, 0x38, + 0x2c, 0x23, 0x05, 0xd6, 0x76, 0x97, 0x08, 0xe8, 0x5e, 0x09, 0x90, 0x2f, 0x00, 0xaa, 0xee, 0x13, 0xfe, 0xdc, 0x27, + 0xf5, 0xe9, 0x14, 0xfa, 0x14, 0xda, 0x7a, 0xc5, 0x15, 0xc4, 0xab, 0xba, 0x31, 0xb2, 0x8d, 0x0a, 0x5a, 0x3c, 0x96, + 0x67, 0xb5, 0x61, 0x6c, 0x4e, 0xad, 0x7f, 0xbd, 0xd9, 0x60, 0xca, 0xe6, 0x42, 0xad, 0xc2, 0x90, 0x44, 0x9f, 0x4a, + 0x2f, 0x92, 0x88, 0x85, 0xcd, 0x6a, 0x6d, 0x7e, 0x13, 0x06, 0x24, 0x13, 0x29, 0xee, 0x67, 0x4b, 0x9c, 0xbb, 0x78, + 0x3c, 0xaf, 0xfa, 0x5a, 0x4b, 0x8b, 0x4c, 0x9b, 0x6f, 0xf5, 0x65, 0x48, 0x53, 0x51, 0x43, 0x1a, 0x75, 0x66, 0xd0, + 0x7d, 0xbb, 0xbc, 0x65, 0x35, 0xc2, 0x04, 0x78, 0xa5, 0x33, 0xe8, 0x46, 0xe3, 0x81, 0x58, 0x56, 0xa3, 0x62, 0x2d, + 0x04, 0x02, 0x0f, 0x43, 0x8e, 0x99, 0x25, 0x24, 0xd9, 0x67, 0xfe, 0x83, 0x8a, 0xb3, 0x50, 0xc4, 0x37, 0x06, 0xd9, + 0xbb, 0xb2, 0xae, 0xdd, 0x75, 0xe4, 0xe7, 0xc4, 0xc2, 0x6a, 0xff, 0xa1, 0x79, 0xd4, 0x1a, 0x67, 0x01, 0x6d, 0x4d, + 0xab, 0x1b, 0x0e, 0xf7, 0xa8, 0x8e, 0x45, 0x69, 0xb0, 0x89, 0x3d, 0xb2, 0x5c, 0xb4, 0x8e, 0x19, 0x34, 0xa0, 0xbf, + 0xcd, 0xae, 0xd6, 0x57, 0x08, 0xe0, 0x56, 0x22, 0xeb, 0x24, 0x95, 0x7f, 0x49, 0x7b, 0xd4, 0xb5, 0x3d, 0x95, 0xff, + 0x6d, 0x9b, 0x2a, 0x87, 0x16, 0x53, 0x1e, 0xbb, 0x39, 0x0b, 0x54, 0x47, 0x82, 0x28, 0x50, 0x5b, 0x2f, 0x98, 0x7a, + 0xa7, 0x4c, 0xd1, 0x01, 0x02, 0x5d, 0x98, 0x33, 0xec, 0x2b, 0x8e, 0x18, 0xb3, 0x54, 0x62, 0x30, 0xf5, 0x31, 0x46, + 0x35, 0xad, 0x15, 0xa0, 0xeb, 0xa7, 0x5b, 0xf8, 0x13, 0x15, 0x35, 0x1a, 0x6a, 0x8d, 0xa4, 0x50, 0x34, 0x51, 0xa1, + 0xc8, 0xd2, 0x42, 0xc7, 0x55, 0xe8, 0x24, 0x12, 0x96, 0x80, 0x86, 0x09, 0xd1, 0x49, 0x05, 0xde, 0x1a, 0xc0, 0x99, + 0x8f, 0x8b, 0x72, 0x5d, 0x68, 0x83, 0xb9, 0x97, 0xf1, 0x35, 0x7f, 0xf5, 0xcc, 0x19, 0xd5, 0xb7, 0xac, 0xf5, 0x3d, + 0x2d, 0xc8, 0xcb, 0x90, 0x53, 0x74, 0x60, 0x62, 0x27, 0x5b, 0x34, 0xc6, 0x28, 0x6b, 0x1d, 0xf5, 0xe2, 0xad, 0x0e, + 0xc5, 0xa2, 0x4d, 0xf0, 0xee, 0xf1, 0x14, 0xd1, 0x86, 0x87, 0xc2, 0x58, 0x55, 0xe3, 0x53, 0xc9, 0x5a, 0x7a, 0xb0, + 0x82, 0xa7, 0xeb, 0x84, 0x87, 0xa0, 0x47, 0x22, 0xec, 0x24, 0x2c, 0xe6, 0xf1, 0x02, 0x8e, 0x93, 0x82, 0x80, 0xda, + 0x41, 0x5f, 0xc1, 0xe7, 0x0b, 0x74, 0x7f, 0x95, 0xe8, 0x01, 0x86, 0x16, 0xc4, 0xcd, 0x28, 0xa8, 0xa3, 0xab, 0x78, + 0xd5, 0x50, 0x91, 0xf0, 0x79, 0x01, 0xb6, 0x43, 0x4a, 0x3d, 0x05, 0x5a, 0xa8, 0x44, 0xe9, 0x87, 0x81, 0xef, 0xd0, + 0x18, 0xd8, 0x5a, 0x07, 0x68, 0xe8, 0x67, 0x4c, 0x53, 0xeb, 0x0c, 0x95, 0xcf, 0xbc, 0x7b, 0x66, 0xb4, 0x9c, 0x59, + 0x34, 0x06, 0x7d, 0x1b, 0x4d, 0x51, 0x9c, 0x93, 0xcf, 0x82, 0x22, 0x4e, 0xb3, 0x38, 0x07, 0xbf, 0xcd, 0xb8, 0xc0, + 0x8c, 0x49, 0x5c, 0xf1, 0x4b, 0x59, 0x80, 0xb6, 0x3b, 0x57, 0xa9, 0x75, 0x0d, 0x02, 0xb2, 0x97, 0x60, 0xf5, 0xd2, + 0xd0, 0x51, 0x39, 0xef, 0x2e, 0x6d, 0x0a, 0x91, 0x88, 0x10, 0x6c, 0x9a, 0xe9, 0x92, 0x9d, 0x86, 0x4a, 0x9b, 0x03, + 0xa1, 0x8e, 0xd0, 0xb8, 0x7f, 0x1a, 0xc6, 0x56, 0x53, 0x6c, 0xed, 0xde, 0x76, 0xbb, 0x7f, 0x96, 0x5e, 0x3a, 0xcd, + 0x49, 0x8f, 0xb1, 0x7f, 0x96, 0x61, 0x31, 0xb2, 0x1d, 0x21, 0xb0, 0xe4, 0xbc, 0x4f, 0xfd, 0x57, 0xb4, 0x9c, 0x27, + 0x60, 0x3a, 0xa2, 0x83, 0xe5, 0x02, 0x65, 0xc7, 0x80, 0xee, 0xc0, 0xe0, 0x8a, 0x7e, 0x1f, 0xac, 0x32, 0xcc, 0x85, + 0x64, 0x49, 0x52, 0x06, 0xcf, 0x53, 0x0f, 0x0e, 0x7e, 0xcd, 0x94, 0xb9, 0x8b, 0xb2, 0x3e, 0x5d, 0x92, 0x69, 0x8a, + 0x0c, 0xc4, 0x3a, 0xdc, 0x66, 0x69, 0x94, 0x28, 0x11, 0xd9, 0x12, 0xfd, 0x23, 0x0d, 0xc5, 0xd2, 0x91, 0x7b, 0x91, + 0x2a, 0x11, 0x2a, 0xe6, 0x29, 0x9e, 0xd4, 0x69, 0x9d, 0x8e, 0x30, 0xf4, 0x24, 0x28, 0xe5, 0x6a, 0x18, 0xa8, 0x92, + 0xea, 0xa5, 0xb0, 0x2d, 0x76, 0x3b, 0x7d, 0xb1, 0x12, 0xf3, 0x78, 0x81, 0x2f, 0x05, 0x8e, 0xe2, 0x3f, 0xb9, 0x17, + 0x76, 0x4a, 0x6d, 0x0f, 0x6a, 0x47, 0x94, 0xd0, 0x7f, 0x72, 0xb8, 0x48, 0xfc, 0x20, 0x75, 0x08, 0x40, 0xb4, 0x08, + 0x39, 0x53, 0x07, 0xa9, 0xe1, 0x86, 0xf6, 0x84, 0xff, 0x86, 0xeb, 0x33, 0xce, 0xe8, 0x4d, 0x35, 0xa3, 0x86, 0xf2, + 0xf5, 0xa0, 0x8d, 0x51, 0x9f, 0x0d, 0x1c, 0x56, 0x88, 0x42, 0x1b, 0x76, 0x52, 0x2a, 0xd1, 0xc2, 0x50, 0xaa, 0xbf, + 0x84, 0x8a, 0x13, 0xee, 0xcc, 0x28, 0x4b, 0xc6, 0xa7, 0xe5, 0xb1, 0x98, 0x0e, 0x06, 0x25, 0xa9, 0x8c, 0x85, 0x1e, + 0x5c, 0x0f, 0x3c, 0xff, 0x1e, 0xb8, 0x85, 0x78, 0xc8, 0xc8, 0x62, 0xc8, 0x0d, 0x4e, 0x7e, 0x8b, 0x93, 0xab, 0x46, + 0xa5, 0x8a, 0x63, 0x4d, 0x54, 0x0b, 0x7e, 0x2c, 0xc3, 0x00, 0x7d, 0x92, 0x02, 0x30, 0x19, 0x4c, 0xf9, 0x2d, 0x48, + 0x94, 0xce, 0xd4, 0x0d, 0xe9, 0x17, 0x51, 0xf0, 0x0b, 0x5e, 0x70, 0x91, 0xb8, 0x02, 0x2c, 0xef, 0x60, 0x7b, 0x1d, + 0x55, 0x54, 0x61, 0xf2, 0x9a, 0x1e, 0x47, 0xdc, 0x78, 0xff, 0x99, 0x1e, 0x5b, 0xcc, 0x56, 0xeb, 0xd8, 0xe0, 0x33, + 0xc7, 0xe0, 0x82, 0xae, 0x25, 0xb6, 0x86, 0x6a, 0x58, 0x11, 0x18, 0xb8, 0x80, 0x83, 0xb0, 0x44, 0x71, 0x6c, 0x25, + 0xaf, 0x48, 0x43, 0x4a, 0x7b, 0xcf, 0x70, 0xb4, 0x49, 0x8e, 0x6f, 0xb3, 0xec, 0x26, 0x70, 0xbe, 0xe8, 0x9c, 0x34, + 0x13, 0xd6, 0x06, 0xef, 0xf3, 0xe6, 0xfc, 0xba, 0x7b, 0x48, 0xa8, 0x8a, 0x7b, 0xc3, 0xdb, 0x71, 0x6f, 0x9c, 0xf0, + 0x6b, 0x2e, 0x16, 0x3a, 0x54, 0x8b, 0xb9, 0x64, 0xf9, 0xad, 0xf5, 0x6e, 0x49, 0x52, 0x2b, 0xa0, 0x7d, 0x96, 0x05, + 0x35, 0x11, 0x00, 0xf2, 0x87, 0xbf, 0x40, 0xe8, 0x0c, 0x7f, 0x7b, 0x0c, 0xae, 0x48, 0xe1, 0x9d, 0x43, 0x20, 0xac, + 0xe9, 0xe6, 0x5e, 0x6d, 0xc0, 0x17, 0xe3, 0xfe, 0x8c, 0xa9, 0xa7, 0xdf, 0x66, 0x72, 0x5f, 0xd7, 0xed, 0x91, 0x65, + 0xf8, 0x08, 0x57, 0x0a, 0xe0, 0x66, 0xc2, 0x5f, 0x0c, 0x33, 0xa9, 0x3e, 0x01, 0x4c, 0x35, 0x1d, 0xdc, 0x27, 0x08, + 0x0c, 0xa0, 0x12, 0x2d, 0x46, 0xd7, 0xca, 0x11, 0xcd, 0xc0, 0xad, 0xe9, 0x56, 0x18, 0x6f, 0x3d, 0x68, 0xa1, 0x67, + 0x1a, 0x4e, 0xfc, 0x07, 0xcd, 0xbc, 0x2a, 0x20, 0x80, 0x56, 0x46, 0xf0, 0xd6, 0xfa, 0x64, 0x8e, 0x10, 0x9f, 0xb0, + 0x24, 0x9a, 0xb0, 0x78, 0xa6, 0xf8, 0x31, 0xa1, 0xdb, 0xa6, 0xb6, 0xe9, 0x23, 0xd2, 0x5f, 0x5c, 0xb3, 0x7e, 0xca, + 0xb2, 0xf6, 0xed, 0xa1, 0xe2, 0xc5, 0xb4, 0x19, 0x07, 0x31, 0x51, 0xc5, 0xf8, 0x5f, 0x70, 0x5f, 0x6a, 0x05, 0x88, + 0xcc, 0x5d, 0xf5, 0xf4, 0xfb, 0xcd, 0x6c, 0x39, 0x10, 0x2a, 0xbf, 0x33, 0x48, 0xfa, 0x74, 0x68, 0x3f, 0xb0, 0x49, + 0xd4, 0x16, 0x7a, 0xfe, 0xb8, 0xd4, 0x4d, 0xbc, 0xbc, 0x36, 0x35, 0xa2, 0x15, 0x32, 0x54, 0xb6, 0x0e, 0x58, 0xdf, + 0x2f, 0xc3, 0xfd, 0x45, 0x4d, 0x43, 0xad, 0x7b, 0xee, 0x5a, 0x14, 0x9c, 0xf8, 0x03, 0x8c, 0xc5, 0x85, 0xa4, 0xd6, + 0xf1, 0x98, 0xf4, 0xa3, 0x85, 0x4c, 0x6e, 0xd4, 0xd5, 0xc9, 0x99, 0x62, 0x9e, 0xc0, 0x05, 0xb8, 0x6c, 0xfb, 0x2b, + 0x2a, 0x75, 0x29, 0xb7, 0x57, 0x94, 0xa6, 0x87, 0xb4, 0xbd, 0x8a, 0xf3, 0xb6, 0xe0, 0x82, 0x7f, 0xa5, 0xe0, 0xc2, + 0x3a, 0x58, 0x77, 0xdc, 0x29, 0x7b, 0xc2, 0x13, 0x65, 0x5a, 0x1b, 0xdc, 0x75, 0x83, 0x31, 0x31, 0xf6, 0xbb, 0x4b, + 0x9e, 0x7c, 0x42, 0x16, 0xfc, 0x87, 0x4c, 0x80, 0x67, 0xb2, 0x7b, 0xa5, 0xf2, 0xbf, 0xf4, 0xaf, 0xb6, 0xf6, 0x9d, + 0x35, 0xff, 0xf4, 0xac, 0x87, 0x3b, 0x87, 0xc9, 0x8f, 0xd5, 0x19, 0xd0, 0xed, 0x95, 0x4c, 0x39, 0x20, 0x03, 0x58, + 0x8b, 0x64, 0x34, 0xe0, 0x43, 0x2b, 0xcb, 0xb6, 0xef, 0xb4, 0xba, 0x20, 0xdc, 0x49, 0xe0, 0xa6, 0x77, 0xd7, 0x66, + 0x66, 0x4e, 0xd7, 0x4a, 0x34, 0x5d, 0x1a, 0x5b, 0xcb, 0x52, 0x85, 0xf1, 0x7e, 0xe7, 0x49, 0x36, 0xcd, 0x8f, 0x97, + 0xd3, 0xdc, 0x52, 0xb7, 0xad, 0x5b, 0x36, 0x80, 0x86, 0xd8, 0xb5, 0xb6, 0x72, 0xc0, 0xcb, 0xed, 0x41, 0x34, 0x5f, + 0x2b, 0x42, 0x4f, 0x95, 0x08, 0x7d, 0x9a, 0x36, 0xfb, 0x60, 0x57, 0xd5, 0xba, 0x11, 0xf2, 0x68, 0x90, 0x6a, 0x46, + 0xfe, 0xed, 0x35, 0x2f, 0x2e, 0x72, 0x79, 0x03, 0x70, 0xc8, 0xa4, 0x36, 0x0a, 0xcb, 0x2b, 0x70, 0xe7, 0x47, 0xc7, + 0x71, 0x26, 0x46, 0x39, 0xc6, 0x6d, 0x45, 0xa4, 0x64, 0x9d, 0x38, 0x03, 0x3c, 0x64, 0x7f, 0xd2, 0x74, 0x68, 0xd7, + 0x02, 0xc3, 0xfb, 0x02, 0x77, 0x95, 0xb3, 0x93, 0x6d, 0x6e, 0x17, 0x7d, 0x73, 0x86, 0x75, 0x47, 0x4a, 0x6b, 0x63, + 0xd1, 0x75, 0x07, 0x6b, 0xcd, 0xa0, 0x2d, 0x42, 0xc9, 0x87, 0xdc, 0x49, 0xfb, 0x39, 0xa0, 0xc1, 0x59, 0x96, 0xde, + 0x5a, 0xab, 0xfc, 0xad, 0x16, 0xe2, 0x44, 0x31, 0x75, 0xe2, 0x9b, 0x28, 0xd1, 0xe7, 0x67, 0x62, 0xdc, 0x40, 0x20, + 0xf5, 0x25, 0xc6, 0xd7, 0x28, 0xc2, 0x04, 0xae, 0x03, 0x51, 0x6c, 0x4f, 0xd4, 0xc6, 0x72, 0x04, 0x9d, 0x10, 0xe2, + 0x1d, 0x94, 0x61, 0xac, 0x2e, 0x0e, 0xb4, 0xc1, 0xd2, 0xd7, 0xad, 0x75, 0x6e, 0x08, 0x85, 0x71, 0x02, 0x53, 0x0c, + 0x92, 0x3a, 0xeb, 0x2c, 0x13, 0x54, 0xd9, 0x31, 0xe9, 0xbc, 0x0f, 0xd0, 0xfd, 0xb5, 0x68, 0x8a, 0xaf, 0x3b, 0x77, + 0xd0, 0x5d, 0x5c, 0xbf, 0xd6, 0x22, 0x37, 0xf8, 0xf3, 0x96, 0x08, 0x8b, 0xc0, 0x59, 0x6b, 0xf2, 0x55, 0x23, 0x1c, + 0x98, 0x92, 0x4c, 0xc3, 0x5e, 0xae, 0x6c, 0xba, 0x77, 0xbb, 0x5e, 0xef, 0x4e, 0x11, 0x57, 0x8f, 0xb1, 0xca, 0xbb, + 0x99, 0xdb, 0x3b, 0xd5, 0x5a, 0xec, 0xdf, 0xb4, 0xfd, 0x14, 0x3b, 0x6a, 0xad, 0xdd, 0x6e, 0x38, 0xa1, 0x86, 0x7c, + 0x2b, 0xaa, 0xb4, 0x3a, 0xdd, 0x18, 0xb4, 0x43, 0x68, 0x6b, 0x91, 0xc1, 0x8d, 0xf2, 0x99, 0x13, 0x3a, 0xa9, 0x90, + 0xab, 0x4e, 0x5d, 0xb0, 0xbd, 0xe2, 0xd5, 0x52, 0xa6, 0x91, 0xa0, 0x68, 0x73, 0x1e, 0x95, 0x34, 0x91, 0x6b, 0x51, + 0x45, 0xb2, 0x46, 0xbd, 0xa8, 0xd5, 0x18, 0x20, 0x20, 0xd3, 0x59, 0xd3, 0x83, 0x2a, 0x98, 0x0d, 0x65, 0x24, 0xa7, + 0x6f, 0xc0, 0xd2, 0x1e, 0x39, 0xd6, 0xfa, 0xae, 0x3a, 0x5b, 0x7c, 0xab, 0x27, 0x04, 0x53, 0x98, 0x3d, 0x10, 0x11, + 0xae, 0x69, 0x0c, 0x39, 0xed, 0x12, 0x97, 0x35, 0xdd, 0x12, 0xee, 0xe0, 0x76, 0x25, 0x3b, 0x71, 0xf3, 0xa4, 0xb9, + 0xb9, 0x82, 0x9d, 0x14, 0xf3, 0x31, 0x68, 0xbf, 0xa4, 0xba, 0x76, 0x69, 0x6e, 0x3d, 0x1e, 0x04, 0x34, 0x18, 0x14, + 0x86, 0x7f, 0x9d, 0x18, 0x0f, 0x4f, 0x1a, 0x10, 0x24, 0xe5, 0x22, 0x1c, 0xfb, 0x46, 0xf4, 0x93, 0xa9, 0x3c, 0xe6, + 0x68, 0xf1, 0x0e, 0xad, 0xce, 0x21, 0xa0, 0x97, 0x08, 0x25, 0x31, 0xaa, 0x42, 0x23, 0x82, 0xf2, 0xb4, 0xfc, 0xa5, + 0xaa, 0x0e, 0x01, 0x85, 0xb4, 0xaf, 0x28, 0x94, 0x6d, 0x12, 0x43, 0x33, 0xfc, 0x72, 0x3e, 0x59, 0xe8, 0x19, 0x18, + 0xc8, 0xf9, 0xd1, 0x42, 0xcf, 0xc2, 0x40, 0xce, 0x1f, 0x2d, 0x6a, 0xb7, 0x0e, 0x34, 0x01, 0xf1, 0x5c, 0x38, 0x3a, + 0x29, 0xad, 0xca, 0x16, 0xd0, 0xed, 0x7d, 0x04, 0xfd, 0x9f, 0xf6, 0x10, 0x74, 0x72, 0xa1, 0x3d, 0xb9, 0x01, 0x6d, + 0x87, 0x24, 0xb0, 0x57, 0x4c, 0x2a, 0x4c, 0x2c, 0xa2, 0x63, 0x36, 0x06, 0x43, 0x6c, 0xf5, 0xc1, 0x31, 0x1b, 0x4f, + 0x7d, 0x12, 0x04, 0x8c, 0xee, 0x4b, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, 0x93, 0xad, 0x40, 0x37, 0x7d, 0x77, 0x37, + 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, 0xd5, 0x6b, 0x88, 0x1b, 0xf2, 0x2b, 0xa3, + 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, 0xea, 0xd6, 0xb3, 0x05, 0x19, 0x66, 0x7a, + 0xcb, 0x64, 0x7d, 0x0f, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, 0xf7, 0x0f, 0xbe, 0xc9, 0xf8, 0x85, 0xc3, + 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, 0xc9, 0x97, 0x59, 0x28, + 0x6f, 0xbc, 0xa6, 0xff, 0xad, 0xd2, 0x9b, 0x1d, 0x0e, 0x39, 0x5d, 0xc1, 0x8a, 0x9b, 0x55, 0xa1, 0xe1, 0x67, 0x91, + 0x37, 0x8e, 0x78, 0x4d, 0xa2, 0xaa, 0xfb, 0xbc, 0xb7, 0x11, 0x4b, 0x3b, 0xc6, 0x01, 0xc0, 0x89, 0x5a, 0x35, 0xec, + 0x4b, 0xe3, 0x5a, 0x1d, 0xc4, 0x88, 0x94, 0xb0, 0x55, 0xe2, 0x48, 0x28, 0x7f, 0x03, 0x10, 0x16, 0x43, 0x71, 0xbc, + 0x35, 0xac, 0xf7, 0xb0, 0x1f, 0xba, 0x40, 0xd3, 0x9c, 0x52, 0xcd, 0x00, 0x20, 0x09, 0xf8, 0xa3, 0xa7, 0x9b, 0x86, + 0xca, 0x36, 0xcf, 0x43, 0xcb, 0xea, 0x0a, 0xee, 0xe9, 0xa9, 0x2b, 0x19, 0x18, 0x57, 0x75, 0xec, 0x6d, 0xef, 0x6e, + 0x8f, 0x56, 0x91, 0xef, 0x6d, 0x52, 0xd3, 0x2c, 0x80, 0x14, 0x8d, 0x4b, 0x5f, 0xe8, 0xe9, 0x04, 0x68, 0xbd, 0xb6, + 0x54, 0xb4, 0xdf, 0x47, 0x31, 0x6a, 0x5c, 0x28, 0xb0, 0x0a, 0x13, 0x14, 0x0e, 0x11, 0x46, 0x08, 0xfd, 0xb9, 0x0c, + 0xb7, 0xbe, 0x20, 0x83, 0x68, 0xb8, 0x16, 0x1d, 0x8a, 0xc8, 0xf1, 0xa2, 0x6d, 0xa9, 0xaa, 0x39, 0x69, 0xda, 0x12, + 0x78, 0x13, 0x19, 0xb0, 0x9d, 0x7f, 0xda, 0x10, 0xb9, 0x0a, 0x17, 0x30, 0x7c, 0x4f, 0x5c, 0x0b, 0xa2, 0x9b, 0xda, + 0xd4, 0xdb, 0xb0, 0x43, 0x74, 0x34, 0xc5, 0xa3, 0x43, 0xee, 0xb9, 0x7b, 0x6e, 0x8b, 0xf8, 0xe6, 0x0b, 0xe4, 0xae, + 0xe9, 0xec, 0xa5, 0x08, 0x83, 0xba, 0x65, 0x03, 0xc5, 0x3a, 0x76, 0x82, 0x02, 0x0c, 0xe0, 0xf2, 0x19, 0xe8, 0xd8, + 0x60, 0x50, 0x11, 0x7c, 0x52, 0xd8, 0x36, 0x0d, 0xf2, 0x47, 0xbc, 0x1b, 0x3a, 0xbc, 0xb6, 0xe4, 0x81, 0x78, 0x85, + 0x7d, 0xa1, 0x84, 0xbb, 0x17, 0x14, 0x74, 0x47, 0x79, 0xb9, 0x2a, 0x5c, 0x95, 0x06, 0xa0, 0xca, 0x9e, 0xe7, 0x5a, + 0x53, 0xd2, 0x02, 0x56, 0x4a, 0xea, 0xce, 0x6f, 0x82, 0xe3, 0x96, 0x4c, 0x85, 0x6f, 0xd5, 0x8d, 0x2a, 0x8f, 0x25, + 0x8a, 0x74, 0xec, 0xd9, 0xce, 0xc1, 0x1a, 0x00, 0x4f, 0x61, 0x7b, 0x71, 0x26, 0xe0, 0x73, 0xa7, 0x5d, 0xb6, 0xcc, + 0x25, 0x50, 0xd4, 0xf7, 0xe3, 0xbc, 0xec, 0xf9, 0x72, 0x77, 0xb4, 0xbd, 0x87, 0xde, 0x88, 0x8d, 0xf1, 0xfa, 0x3a, + 0x6a, 0xfa, 0xd5, 0x33, 0x5c, 0x59, 0x0a, 0x72, 0x4f, 0x53, 0x3d, 0xc2, 0xe8, 0x10, 0x98, 0xa6, 0xfc, 0x84, 0x8d, + 0xa7, 0xc3, 0xa1, 0x21, 0x83, 0x5e, 0x33, 0x31, 0x14, 0xd8, 0x57, 0xd0, 0x3a, 0x33, 0x71, 0x8d, 0x4f, 0xdb, 0x57, + 0xd0, 0xea, 0x16, 0x65, 0x72, 0x67, 0x60, 0xf8, 0x40, 0x4b, 0xa6, 0x60, 0xaa, 0xf0, 0x86, 0x48, 0x25, 0xfb, 0x73, + 0x69, 0x1d, 0xf6, 0xed, 0x42, 0xa1, 0x85, 0x26, 0x7e, 0x95, 0x21, 0x7e, 0xea, 0x3a, 0xf3, 0x1f, 0xd3, 0x3e, 0x35, + 0x88, 0x85, 0x23, 0x31, 0x88, 0xf8, 0xc5, 0xa9, 0xb2, 0x9d, 0x10, 0x2a, 0x36, 0x1e, 0xba, 0xd6, 0x8d, 0x23, 0xa9, + 0xc2, 0x50, 0x0a, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xe8, 0xf0, 0x75, 0x98, 0xc5, 0x6d, 0xd6, 0x48, 0x6a, 0x8c, 0x53, + 0x61, 0xe2, 0x54, 0xca, 0x55, 0x24, 0x30, 0x50, 0x9e, 0x2d, 0x0c, 0x02, 0x4c, 0x62, 0x92, 0xb1, 0xb5, 0x10, 0x26, + 0x8c, 0x9d, 0x2b, 0x4c, 0x53, 0x17, 0xa9, 0xdf, 0x0c, 0x4c, 0x16, 0x34, 0xe4, 0xf7, 0x68, 0xb4, 0xa6, 0x6a, 0x0a, + 0x30, 0x8c, 0xa3, 0x54, 0xe3, 0x3f, 0x22, 0xd4, 0x66, 0x18, 0x00, 0xd8, 0xe6, 0x9d, 0xcc, 0x44, 0xf5, 0x4a, 0x20, + 0x04, 0x9a, 0xb3, 0x9f, 0x8a, 0xab, 0xbd, 0x59, 0x30, 0x8a, 0x76, 0x7b, 0xe5, 0xf3, 0x81, 0x13, 0xca, 0x53, 0x75, + 0x81, 0x7a, 0x21, 0x8b, 0xd7, 0x32, 0xe5, 0xad, 0x10, 0x99, 0x07, 0x92, 0xbd, 0xcf, 0x47, 0x70, 0x5e, 0xa1, 0x53, + 0xb9, 0xd9, 0x26, 0xca, 0x2c, 0x49, 0x32, 0x16, 0x18, 0x9b, 0x97, 0x60, 0x26, 0x35, 0x33, 0x86, 0x5f, 0x43, 0x9c, + 0xb1, 0xbd, 0x93, 0x70, 0x7b, 0x37, 0x0f, 0x0c, 0x51, 0xca, 0x45, 0x4b, 0x34, 0x6c, 0xed, 0x78, 0x3d, 0xb9, 0x26, + 0xdc, 0x87, 0x8d, 0x58, 0x93, 0x31, 0xc6, 0xb5, 0xb9, 0x91, 0xf5, 0xa3, 0x05, 0x1e, 0x8c, 0x29, 0xeb, 0x4f, 0x20, + 0xd3, 0x4a, 0xca, 0x3a, 0x5f, 0x18, 0x31, 0x93, 0x4a, 0xf4, 0x6e, 0xdf, 0xf8, 0xac, 0xee, 0x22, 0xea, 0xb7, 0xf6, + 0x7b, 0x52, 0x0f, 0x1b, 0xff, 0x41, 0x61, 0x0d, 0x2a, 0x23, 0x2e, 0x23, 0xca, 0x33, 0x07, 0xba, 0x69, 0x52, 0xc4, + 0xe9, 0xd9, 0x2a, 0x2e, 0x4a, 0x9e, 0x42, 0xa5, 0x9a, 0xba, 0x45, 0xbd, 0x09, 0xd8, 0x1b, 0x22, 0x49, 0xb2, 0x96, + 0xc6, 0x56, 0xec, 0xd2, 0x20, 0x3d, 0x77, 0x46, 0x5c, 0x7a, 0x51, 0xa1, 0x21, 0x2d, 0xf5, 0xce, 0x42, 0x25, 0xf3, + 0x57, 0xfc, 0x67, 0x50, 0x2b, 0xd0, 0xd1, 0x26, 0xc5, 0x78, 0x0a, 0x8c, 0xf8, 0x7e, 0x30, 0xab, 0x7b, 0x88, 0x8b, + 0x26, 0x28, 0xf5, 0x9e, 0xd8, 0xf1, 0x4b, 0x93, 0x87, 0x77, 0x21, 0xe7, 0x0c, 0x3e, 0xbd, 0x9f, 0x25, 0x6a, 0xad, + 0x23, 0x31, 0x52, 0x33, 0x80, 0xa6, 0x83, 0x32, 0xe7, 0xb1, 0x08, 0x66, 0x3d, 0x93, 0x18, 0xf5, 0xb8, 0xfe, 0x05, + 0x1a, 0x6a, 0xbf, 0x59, 0x59, 0x9e, 0x55, 0x9b, 0xaf, 0xe1, 0xc0, 0xa6, 0xb6, 0x82, 0x1e, 0xaf, 0x2b, 0x79, 0x79, + 0xa9, 0xba, 0xed, 0x17, 0x62, 0xe4, 0x74, 0x8d, 0x6b, 0xe9, 0xbc, 0x5a, 0xb0, 0x5e, 0x77, 0xba, 0x59, 0xdc, 0xcd, + 0x32, 0x1a, 0x08, 0x6b, 0x7b, 0x9f, 0x68, 0xfe, 0xac, 0xd9, 0x76, 0x1f, 0x6f, 0x41, 0xcc, 0x02, 0x80, 0x48, 0x0f, + 0xa2, 0x60, 0x99, 0xa5, 0x3c, 0xa0, 0xf2, 0x2e, 0x8e, 0xb2, 0x50, 0x7a, 0x39, 0xcb, 0xf8, 0x69, 0xd3, 0x58, 0xeb, + 0xac, 0x50, 0x86, 0xd6, 0x46, 0x77, 0xba, 0xca, 0x10, 0xdb, 0x4f, 0xe2, 0x6c, 0x01, 0xee, 0x8f, 0x19, 0x0a, 0x0d, + 0x9d, 0x65, 0xa4, 0x89, 0x86, 0xef, 0xba, 0x63, 0x90, 0x51, 0x9c, 0xac, 0xf3, 0x4a, 0xba, 0xd5, 0x67, 0x6d, 0x24, + 0xcc, 0x3d, 0x44, 0xbf, 0x8a, 0xc1, 0xa3, 0xdc, 0xe7, 0xb5, 0xd1, 0xc9, 0xb4, 0x8c, 0xb4, 0x3b, 0x3f, 0xa9, 0x97, + 0x59, 0xaa, 0x75, 0xd8, 0x3e, 0xc3, 0xde, 0x1a, 0x93, 0xde, 0x84, 0xd4, 0x30, 0x12, 0x5f, 0xce, 0xa8, 0x11, 0x02, + 0xda, 0x72, 0xfc, 0x3d, 0x3e, 0xc3, 0xd0, 0x14, 0x58, 0xaa, 0xb8, 0x85, 0xdd, 0xf0, 0x35, 0x9f, 0xac, 0x5a, 0x00, + 0x82, 0x59, 0xf9, 0x7a, 0x17, 0xaf, 0x84, 0xfa, 0x4c, 0x9b, 0x01, 0x20, 0x0b, 0x4a, 0xb9, 0xe3, 0xa7, 0x54, 0x3a, + 0x58, 0xa2, 0x68, 0x7b, 0x39, 0x7d, 0xa3, 0x63, 0xe3, 0xfb, 0xf4, 0x5c, 0xc0, 0x76, 0x21, 0xbf, 0x75, 0xa7, 0x5e, + 0xa2, 0x22, 0xb5, 0x6d, 0xd6, 0x3d, 0x7c, 0xb9, 0x41, 0x93, 0x30, 0x82, 0x32, 0x65, 0x0a, 0x60, 0x70, 0x53, 0x8d, + 0x82, 0x49, 0xab, 0x91, 0xb0, 0xa5, 0x9e, 0x64, 0xb9, 0xe9, 0x83, 0x53, 0xdd, 0x21, 0xe8, 0xb9, 0x55, 0xce, 0x17, + 0x2d, 0xfb, 0xb5, 0x82, 0xa3, 0x93, 0xab, 0x21, 0x6a, 0xe6, 0xbd, 0xb6, 0x23, 0x43, 0xca, 0x65, 0x18, 0x08, 0xa6, + 0x1c, 0xf3, 0xf4, 0xd8, 0x7a, 0x46, 0x44, 0xf7, 0x9c, 0x7d, 0xa6, 0x5b, 0x75, 0x25, 0x01, 0xd1, 0xf1, 0xbb, 0xc7, + 0xaf, 0xae, 0xe2, 0x4b, 0x83, 0xa2, 0xd4, 0xb0, 0x88, 0x51, 0xa6, 0x7d, 0x95, 0x84, 0xc1, 0xfb, 0xe5, 0xfd, 0x4f, + 0x2a, 0x4b, 0xed, 0xf7, 0x60, 0x6b, 0x45, 0x55, 0xbf, 0x94, 0xbc, 0x68, 0x0a, 0xb0, 0xee, 0xb2, 0x44, 0x81, 0xdc, + 0xef, 0x6d, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, 0x6d, 0xc9, 0x8e, 0xac, 0x44, 0xce, + 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x2d, 0xaa, 0x52, 0xf1, 0x7b, 0x23, 0x82, 0x53, 0xc7, 0xaa, 0xc2, + 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, 0xfd, 0x8b, 0x15, 0xd4, 0xfc, 0xfe, + 0xb7, 0x31, 0xe4, 0x6b, 0x4a, 0x41, 0x25, 0x01, 0x3b, 0x83, 0x46, 0x4f, 0x95, 0x30, 0x90, 0x82, 0xe0, 0x09, 0x50, + 0xbe, 0x88, 0x1a, 0xab, 0xfd, 0xbe, 0x3a, 0x35, 0x46, 0x5b, 0x40, 0x68, 0x21, 0x3d, 0xba, 0xec, 0xe3, 0xb6, 0xd6, + 0x81, 0xc4, 0x83, 0x13, 0x6c, 0xe7, 0xea, 0x1a, 0x8d, 0x84, 0xe6, 0xf7, 0x8d, 0x06, 0xbc, 0xa6, 0x15, 0x28, 0xd4, + 0x73, 0x1c, 0x0d, 0x9d, 0x1d, 0x52, 0x10, 0xb1, 0x41, 0x0b, 0xfb, 0xee, 0xf8, 0xd0, 0xec, 0xeb, 0x79, 0xb2, 0x20, + 0x35, 0x95, 0xee, 0x73, 0xb7, 0x84, 0xac, 0x55, 0x87, 0xb2, 0xf2, 0x00, 0xc7, 0x0b, 0x25, 0xf3, 0x77, 0x98, 0xd4, + 0x28, 0x8d, 0x09, 0x8d, 0x11, 0x0b, 0x58, 0x12, 0xb4, 0xd7, 0x03, 0xf5, 0xcb, 0x20, 0x54, 0x38, 0xd3, 0x13, 0x89, + 0x4f, 0x29, 0x57, 0x9f, 0x16, 0xa4, 0x9e, 0x16, 0xcc, 0x81, 0x5e, 0xfa, 0x56, 0x7e, 0x65, 0xe3, 0xa3, 0xfd, 0xbd, + 0x6b, 0x2e, 0xac, 0x63, 0x88, 0x8b, 0x2d, 0xfc, 0xe6, 0xd4, 0x14, 0x80, 0x0d, 0x4f, 0x75, 0x59, 0xbe, 0x51, 0x13, + 0x99, 0xc5, 0x21, 0x89, 0x40, 0xb2, 0xdd, 0xdc, 0xdc, 0x46, 0xb0, 0xed, 0x2d, 0xd4, 0x86, 0xfa, 0xcb, 0xdb, 0xee, + 0x77, 0x0c, 0x2f, 0xf7, 0xe4, 0xde, 0x4d, 0x1b, 0xca, 0x97, 0x77, 0xaf, 0x92, 0xff, 0xab, 0x4a, 0xee, 0xb6, 0xca, + 0xac, 0xdb, 0xe2, 0xfd, 0xae, 0xe3, 0x96, 0x63, 0x34, 0x08, 0xac, 0x29, 0x30, 0x90, 0x9e, 0x34, 0xa6, 0x89, 0x8e, + 0xae, 0xcc, 0x98, 0xc1, 0xa3, 0x0b, 0xd0, 0x1c, 0xa6, 0xf3, 0x3c, 0x06, 0xe0, 0x00, 0xff, 0xc8, 0x23, 0xd4, 0x3f, + 0x9d, 0xe7, 0xc1, 0x59, 0x30, 0x28, 0x07, 0x81, 0xfe, 0xc4, 0x35, 0x27, 0x58, 0x80, 0xce, 0x2d, 0x66, 0x10, 0x77, + 0xd2, 0x9a, 0x39, 0xc4, 0xc7, 0xc9, 0x74, 0x30, 0x88, 0xc9, 0x16, 0x40, 0xfa, 0xe2, 0x85, 0x75, 0x0e, 0x2a, 0xf4, + 0x82, 0x6c, 0xd5, 0x5d, 0x34, 0x2b, 0xf6, 0xaa, 0x9d, 0xe6, 0xfd, 0x7e, 0x3e, 0x2f, 0x07, 0x41, 0xa3, 0xc2, 0xc2, + 0x78, 0xff, 0xd1, 0xe6, 0x97, 0x46, 0x27, 0x4d, 0x30, 0x62, 0xed, 0x29, 0xaa, 0x57, 0x3c, 0xcd, 0x68, 0xe3, 0x76, + 0xac, 0x94, 0x2f, 0x20, 0x8a, 0x07, 0x86, 0xac, 0x95, 0x77, 0xef, 0xe0, 0x75, 0xb9, 0xf1, 0xe6, 0x88, 0x02, 0xec, + 0xa6, 0x30, 0x4e, 0x6a, 0x2e, 0xba, 0xa8, 0x89, 0x67, 0xb0, 0xd3, 0xd5, 0x5b, 0x89, 0x56, 0xe3, 0xbd, 0x78, 0xdf, + 0x6c, 0xfc, 0x8d, 0x3c, 0xd0, 0x65, 0x1e, 0x5c, 0x00, 0xe2, 0xec, 0x41, 0x5c, 0x1d, 0x60, 0xa9, 0x07, 0xc1, 0xc0, + 0x22, 0x87, 0xb4, 0xab, 0xd5, 0x43, 0x11, 0xa9, 0xf3, 0x18, 0x0c, 0x98, 0x4c, 0x43, 0x6a, 0x32, 0xed, 0xc5, 0x0a, + 0xd2, 0xc6, 0x5a, 0x0b, 0x68, 0xc3, 0x61, 0xb1, 0x67, 0x37, 0xec, 0x4e, 0xb7, 0x0e, 0x85, 0x12, 0x06, 0xb2, 0xae, + 0x9b, 0x87, 0x5a, 0xc3, 0x13, 0x41, 0x0f, 0xaa, 0xd1, 0x7e, 0x7a, 0x28, 0x4f, 0xda, 0x63, 0x01, 0x2e, 0x7a, 0xf8, + 0xf2, 0xb9, 0xc0, 0x8b, 0xf6, 0x1e, 0xf2, 0x9c, 0xf9, 0x54, 0xf9, 0x20, 0x36, 0xdc, 0x32, 0x7c, 0x68, 0x1f, 0xdf, + 0x0a, 0x64, 0x52, 0x77, 0x34, 0xb5, 0xb5, 0x3b, 0x1a, 0xc7, 0x04, 0xfa, 0x4d, 0x39, 0x4a, 0x99, 0x98, 0x5a, 0x96, + 0xec, 0xa4, 0x97, 0x2b, 0x6f, 0xa8, 0x94, 0x9d, 0x2c, 0xdb, 0x9c, 0x5f, 0xda, 0x48, 0xe8, 0xf7, 0xb5, 0x3b, 0x10, + 0xbe, 0x51, 0xeb, 0x0d, 0x79, 0xd9, 0x10, 0xb1, 0x1c, 0x62, 0x06, 0x8e, 0x17, 0x52, 0xb9, 0x76, 0x17, 0x4d, 0x55, + 0xdd, 0xde, 0x56, 0x2e, 0x68, 0x89, 0xb7, 0x52, 0x60, 0x15, 0xa9, 0xd3, 0xeb, 0xa9, 0xc4, 0xbb, 0x3e, 0x8a, 0xed, + 0x47, 0xc0, 0x36, 0x36, 0x8e, 0xc6, 0xc6, 0x2d, 0x62, 0x8b, 0xaf, 0xa2, 0x8a, 0x16, 0x1c, 0x20, 0xb8, 0xdb, 0x92, + 0x5a, 0x9a, 0x39, 0xc4, 0x7d, 0xc5, 0x03, 0xb4, 0xef, 0xe2, 0x70, 0x26, 0x15, 0x60, 0x5b, 0xd7, 0x3a, 0x67, 0xb5, + 0x1c, 0xb0, 0x99, 0xe8, 0xf9, 0xa7, 0x55, 0x23, 0x11, 0xc3, 0x2a, 0x1b, 0x29, 0x2b, 0xb4, 0x7b, 0xa5, 0x4b, 0xb8, + 0xf8, 0x02, 0xbc, 0x6c, 0xdf, 0xad, 0xec, 0x3e, 0x5b, 0x62, 0xff, 0x30, 0xaf, 0x9a, 0xe0, 0x91, 0xd7, 0x78, 0x7b, + 0x0f, 0x13, 0x5f, 0x2b, 0x85, 0xf0, 0x2a, 0xa5, 0xa1, 0x04, 0x60, 0x90, 0x04, 0x35, 0x5c, 0x69, 0xdb, 0x0c, 0x52, + 0x19, 0xc3, 0xee, 0x57, 0x6f, 0xf5, 0x7f, 0x5a, 0x85, 0x8b, 0x4a, 0x16, 0x63, 0x12, 0xe8, 0x9c, 0x6a, 0xb9, 0x09, + 0x2c, 0x78, 0xb6, 0x4f, 0x8e, 0x40, 0x61, 0x27, 0x80, 0x1b, 0x4a, 0xd8, 0x5f, 0x78, 0x1b, 0xca, 0xd9, 0x67, 0x2b, + 0x79, 0x72, 0xfb, 0x92, 0x0a, 0x9a, 0x90, 0xa9, 0xb0, 0xfb, 0xb7, 0xb5, 0x61, 0x9f, 0x85, 0x72, 0x24, 0x05, 0x2e, + 0x0e, 0x3a, 0x07, 0xb0, 0x3f, 0xc8, 0x65, 0x6c, 0x3e, 0x93, 0x7e, 0x5f, 0xbd, 0x7f, 0x9a, 0x67, 0xc9, 0xa7, 0xbd, + 0xf7, 0x86, 0xa7, 0x59, 0x32, 0xa0, 0x12, 0x31, 0xb5, 0xae, 0x8a, 0xe1, 0x52, 0xbb, 0x18, 0x37, 0x48, 0x46, 0x7c, + 0x27, 0x75, 0x88, 0x11, 0xe3, 0x8b, 0xec, 0x91, 0x94, 0x9c, 0x2e, 0xeb, 0xce, 0x9e, 0x6b, 0xd1, 0x0c, 0x1a, 0xc3, + 0xed, 0x79, 0x2f, 0xe9, 0x15, 0xa0, 0x02, 0x44, 0xf7, 0x2c, 0x70, 0x0d, 0x6f, 0x2e, 0x89, 0xc6, 0x96, 0x9e, 0xb6, + 0x44, 0x03, 0x77, 0xca, 0x84, 0xa4, 0xda, 0x38, 0xc0, 0x22, 0xd6, 0xf5, 0xa7, 0xb0, 0x00, 0xa0, 0x56, 0x83, 0xf4, + 0x4a, 0x5f, 0x10, 0xaa, 0x92, 0x10, 0x8c, 0x4e, 0x24, 0xbc, 0x0c, 0x68, 0x9c, 0x99, 0x44, 0x0b, 0x1b, 0x1c, 0xd0, + 0x57, 0x95, 0x49, 0x34, 0x36, 0xe4, 0x01, 0xe5, 0x36, 0x0d, 0x60, 0xf0, 0x41, 0x92, 0x44, 0x7f, 0x5a, 0x9a, 0x24, + 0x10, 0x94, 0xa0, 0x7c, 0x83, 0xfe, 0x5e, 0x7a, 0x3e, 0x96, 0xff, 0xf0, 0x0e, 0xa5, 0x97, 0x61, 0x01, 0x32, 0x45, + 0x5d, 0x31, 0xcd, 0xd8, 0x49, 0xd6, 0x6d, 0x4c, 0xe2, 0x79, 0xda, 0x5d, 0x17, 0xca, 0xa5, 0x0b, 0xfc, 0xca, 0x32, + 0xc4, 0xb1, 0x7e, 0x1a, 0xaf, 0xd8, 0x69, 0xc8, 0x35, 0x5e, 0xfa, 0xd3, 0x78, 0x85, 0x33, 0x44, 0xab, 0x56, 0x02, + 0x51, 0xfe, 0xab, 0x36, 0x70, 0x88, 0xfb, 0x04, 0x83, 0x5c, 0x54, 0xde, 0x03, 0x81, 0xbc, 0xad, 0x20, 0x22, 0xcd, + 0xec, 0x3a, 0x8c, 0x48, 0xb5, 0x97, 0x64, 0xbe, 0xfc, 0x87, 0xcc, 0x84, 0xf7, 0x0d, 0x3c, 0x36, 0x9b, 0x65, 0x53, + 0xcc, 0x17, 0x2a, 0x98, 0x83, 0xfb, 0x44, 0xc5, 0xa5, 0xa8, 0xfc, 0x27, 0xec, 0x82, 0x17, 0xe3, 0xc1, 0xeb, 0x35, + 0x02, 0xec, 0x57, 0xfe, 0x93, 0x37, 0x66, 0x3f, 0x58, 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, + 0x1b, 0x2f, 0xd3, 0xaf, 0x0d, 0x28, 0x91, 0x51, 0x59, 0xf1, 0xd5, 0x8a, 0xa7, 0xb3, 0x9b, 0x24, 0xca, 0x46, 0x15, + 0x17, 0x30, 0xbd, 0xe0, 0x78, 0x97, 0xac, 0xcf, 0xb3, 0xe4, 0x15, 0xc4, 0x1e, 0x58, 0x49, 0x85, 0xc5, 0x0f, 0xcb, + 0x4c, 0x2d, 0x66, 0x21, 0x2b, 0x29, 0x78, 0x30, 0xfb, 0x94, 0x44, 0x3f, 0x2c, 0x3d, 0x10, 0x39, 0x33, 0x65, 0xdb, + 0xda, 0x11, 0x6a, 0xe3, 0xeb, 0x48, 0xb7, 0xda, 0x02, 0x00, 0xee, 0xd9, 0x22, 0x8d, 0x24, 0x13, 0xc3, 0x49, 0xcd, + 0xb8, 0x49, 0x2f, 0x30, 0x35, 0xae, 0x59, 0x45, 0x13, 0x67, 0x21, 0x03, 0x7a, 0x7f, 0x9a, 0xeb, 0xe7, 0x0c, 0xee, + 0x3f, 0x68, 0x0d, 0x5c, 0x1e, 0x17, 0xfd, 0xbe, 0x3c, 0x2e, 0x76, 0xbb, 0xf2, 0x24, 0xee, 0xf7, 0xe5, 0x49, 0x6c, + 0xf8, 0x07, 0xa5, 0xd8, 0x36, 0xe6, 0x06, 0x09, 0xcd, 0x25, 0x44, 0x2d, 0x1a, 0xc1, 0x1f, 0x9a, 0xe5, 0x5c, 0x44, + 0xf9, 0x71, 0xd2, 0xef, 0xf7, 0x96, 0x33, 0x31, 0xc8, 0x87, 0x49, 0x94, 0x0f, 0x13, 0xcf, 0x09, 0xf1, 0xa5, 0xe7, + 0x84, 0xa8, 0x68, 0xe0, 0x0a, 0xce, 0x0c, 0x40, 0x14, 0xf0, 0xe9, 0x1f, 0xd5, 0xb5, 0x14, 0xba, 0x96, 0x58, 0xd5, + 0x92, 0xe8, 0x0a, 0x6a, 0x76, 0x53, 0x84, 0x25, 0x96, 0x42, 0x97, 0xec, 0xd7, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0xb6, + 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6b, 0x7a, 0x41, 0x57, 0xf4, 0x12, + 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x66, 0xf9, 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, + 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0x9b, 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x29, 0x83, 0xf0, 0x7e, 0xe9, + 0x2c, 0xcc, 0x4c, 0x9c, 0x8f, 0xd5, 0xe8, 0x96, 0xae, 0x20, 0x7e, 0x0d, 0xdc, 0x48, 0x48, 0x04, 0x1d, 0xb9, 0xa4, + 0x2b, 0xba, 0xa6, 0xd2, 0xcc, 0x30, 0x46, 0xeb, 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, + 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, 0xf4, 0x4b, 0x7b, 0x90, 0x80, 0x11, 0x19, 0xa9, 0x81, 0x32, 0x23, + 0x23, 0xa9, 0x99, 0x54, 0x1c, 0x92, 0xd8, 0x1f, 0x12, 0x35, 0x0e, 0x89, 0x3f, 0x0e, 0xb9, 0x1e, 0x07, 0xe4, 0xee, + 0x97, 0x6c, 0x4c, 0x53, 0x36, 0xa6, 0x6b, 0x35, 0x2a, 0xf4, 0x8a, 0x9e, 0x6b, 0xea, 0x78, 0xc6, 0x9e, 0xc2, 0x81, + 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x1a, 0x3d, 0x25, 0xe4, 0x1b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0x02, 0x21, 0x5e, + 0x81, 0x73, 0xa9, 0x0b, 0x75, 0x72, 0x65, 0x76, 0x1c, 0x3e, 0x5d, 0x36, 0x9e, 0xce, 0x21, 0xa2, 0x0f, 0x5a, 0xa9, + 0xf4, 0xfb, 0xe1, 0x05, 0x2b, 0xe7, 0x67, 0xe1, 0x98, 0x00, 0x0e, 0x8f, 0x1e, 0xce, 0x8b, 0xd1, 0x2d, 0xbd, 0x18, + 0x6d, 0x08, 0x58, 0x78, 0x8d, 0xa7, 0xeb, 0x63, 0x16, 0x4f, 0x07, 0x83, 0x35, 0x52, 0x75, 0x95, 0x7b, 0x4d, 0x16, + 0xf4, 0x02, 0x27, 0x82, 0x00, 0x43, 0x9f, 0x89, 0xb5, 0xa1, 0xe1, 0x4f, 0x19, 0x7c, 0xbc, 0x61, 0x17, 0xa3, 0x0d, + 0xbd, 0x65, 0x4f, 0x77, 0xe3, 0x29, 0x30, 0x53, 0xab, 0x59, 0xb8, 0x39, 0xbe, 0x9c, 0x5d, 0xb2, 0x4d, 0xb4, 0x39, + 0x81, 0x86, 0x5e, 0xb1, 0x0d, 0x02, 0x2e, 0xa5, 0x0f, 0x97, 0x83, 0xa7, 0xe4, 0x70, 0x30, 0x48, 0x49, 0x14, 0x5e, + 0x87, 0x5e, 0x2b, 0x9f, 0xd2, 0x0d, 0xa1, 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0xb6, 0xa9, 0xaf, + 0x43, 0x6f, 0x37, 0xe7, 0xa2, 0x13, 0xc4, 0x08, 0x7d, 0x0d, 0x1c, 0xcd, 0x72, 0x61, 0x26, 0xe0, 0xc9, 0x5c, 0x64, + 0xb4, 0x28, 0x34, 0x03, 0x71, 0x56, 0x02, 0x62, 0x49, 0xd4, 0xfd, 0x66, 0xa3, 0x33, 0x58, 0xce, 0xfd, 0x7e, 0xaf, + 0x32, 0xf4, 0x00, 0x91, 0x33, 0x3b, 0xe9, 0x41, 0xcf, 0xa7, 0x07, 0xf8, 0x89, 0x5e, 0x35, 0x88, 0x93, 0xf9, 0xcb, + 0x32, 0x7a, 0xe9, 0xd1, 0x87, 0xdf, 0xba, 0x29, 0x8f, 0xcc, 0xff, 0x73, 0xca, 0x53, 0xe4, 0xd1, 0xeb, 0xca, 0x03, + 0x62, 0xf3, 0xd6, 0xa4, 0xd2, 0x48, 0x54, 0xa3, 0xb3, 0x55, 0x0c, 0xda, 0x48, 0xd4, 0x36, 0xe8, 0x27, 0xb4, 0xb0, + 0x82, 0x08, 0x39, 0x47, 0xcf, 0xc0, 0x20, 0x15, 0x42, 0xe5, 0xa8, 0x45, 0x89, 0x86, 0x20, 0xb9, 0x2c, 0xb9, 0x0a, + 0x9f, 0x43, 0xa8, 0x3a, 0x7d, 0x9c, 0x89, 0xb0, 0xa1, 0xc7, 0xa1, 0x0f, 0x00, 0xff, 0xd7, 0x1e, 0xb9, 0x28, 0xf9, + 0x25, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb0, 0x5c, 0x34, 0x43, 0xdb, 0x20, 0xf6, 0x63, 0x49, 0xb0, 0x1e, 0x49, 0xe3, + 0x51, 0x69, 0x8e, 0x08, 0x3f, 0x8a, 0x8f, 0xa2, 0xa7, 0xb1, 0x21, 0x91, 0x1c, 0x49, 0x24, 0x1f, 0x00, 0xe1, 0x24, + 0xe8, 0x2f, 0xee, 0x9a, 0xec, 0x5a, 0xa8, 0xbd, 0x7e, 0x0f, 0xfe, 0xb5, 0x64, 0x5a, 0x76, 0xaf, 0x7a, 0xec, 0x2b, + 0x82, 0x3c, 0x98, 0x00, 0xaf, 0x0f, 0xff, 0x5a, 0xe2, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0x99, 0x37, 0xb8, 0x91, + 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, 0xf1, 0x9c, 0xca, + 0xf5, 0xca, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, 0x57, 0xd2, 0x72, + 0xf4, 0x94, 0x72, 0xd5, 0x4c, 0xb9, 0x58, 0xe7, 0xf9, 0x4f, 0x7b, 0xa9, 0x38, 0xc5, 0xcd, 0x14, 0xa4, 0x4a, 0x2d, + 0x17, 0x50, 0x3d, 0x47, 0x2d, 0x77, 0x4b, 0xb3, 0x03, 0x9c, 0xdb, 0xa6, 0xfa, 0x58, 0x99, 0x5d, 0x78, 0xc9, 0x8d, + 0xfb, 0x93, 0x29, 0xc3, 0x82, 0x51, 0x68, 0xb3, 0xea, 0x4a, 0xdb, 0x17, 0x5a, 0xa7, 0x61, 0xb8, 0xf2, 0xe3, 0x05, + 0xa4, 0x0b, 0x18, 0xc7, 0x8b, 0x92, 0x89, 0x71, 0x7b, 0xf4, 0x56, 0x10, 0x5f, 0xb3, 0x15, 0x48, 0xbf, 0xdf, 0x13, + 0xde, 0xae, 0xeb, 0x68, 0xbb, 0x27, 0x4e, 0x19, 0x95, 0xab, 0x58, 0xfc, 0x18, 0xaf, 0x0c, 0x64, 0xb2, 0x3a, 0x1e, + 0x1b, 0x63, 0x3a, 0xfd, 0x39, 0x09, 0xfd, 0x42, 0x28, 0xf8, 0xac, 0x97, 0x56, 0x9e, 0xdc, 0x1e, 0x96, 0x71, 0x8d, + 0x5e, 0x89, 0x2b, 0xdd, 0x37, 0x23, 0x85, 0xd4, 0x23, 0x5f, 0x35, 0x05, 0xf4, 0x66, 0xec, 0x9b, 0xa9, 0x30, 0x6f, + 0x77, 0x8c, 0xb9, 0x42, 0xb0, 0x52, 0x65, 0xb7, 0xef, 0xd4, 0x98, 0x8a, 0x19, 0x4c, 0xb1, 0xed, 0x2c, 0x26, 0xdd, + 0xca, 0x3f, 0xed, 0xdc, 0xaf, 0xf3, 0x0e, 0x77, 0x45, 0xfd, 0x16, 0xb8, 0xd0, 0xac, 0x28, 0xab, 0xb6, 0x6c, 0xd8, + 0x36, 0xde, 0xc8, 0x42, 0xb1, 0x01, 0x96, 0x3d, 0xf7, 0x2d, 0x3c, 0x40, 0xdc, 0x84, 0x7b, 0x76, 0x51, 0xc3, 0x8d, + 0xe1, 0xeb, 0x4a, 0xf2, 0x5d, 0x69, 0xcc, 0xa5, 0x4f, 0x95, 0x26, 0x86, 0x93, 0xc5, 0x88, 0x8b, 0x74, 0x51, 0x67, + 0x76, 0x2d, 0x7c, 0xc1, 0xcb, 0x70, 0xce, 0x17, 0x46, 0x37, 0xa5, 0x4b, 0x2f, 0x98, 0x0e, 0x99, 0x42, 0xb7, 0x2b, + 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, + 0x1c, 0xdc, 0xc7, 0x7e, 0x43, 0x4c, 0x64, 0x13, 0x98, 0x14, 0x0d, 0x1d, 0xd0, 0xae, 0xba, 0xf0, 0xcd, 0xa8, 0x07, + 0x83, 0xdc, 0x92, 0x44, 0xac, 0x20, 0xc5, 0x0a, 0xd6, 0x35, 0x2b, 0xe6, 0xf9, 0x82, 0x5e, 0x30, 0x39, 0x4f, 0x17, + 0x74, 0xc5, 0xe4, 0x7c, 0x8d, 0x37, 0xa1, 0x0b, 0x38, 0x21, 0xc9, 0x36, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, + 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0x1c, 0x86, 0xab, + 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x75, 0x3e, 0x09, 0x15, 0xbb, 0x60, 0xf7, 0x02, 0x99, 0x5e, 0xcd, 0xf9, 0x42, 0x8d, + 0x84, 0x2e, 0xf8, 0xca, 0x1a, 0x9b, 0xc4, 0x9e, 0xa0, 0x65, 0x16, 0xcf, 0xc7, 0x8b, 0x28, 0xae, 0x61, 0x19, 0x7e, + 0x50, 0x33, 0xd3, 0x92, 0xff, 0xe4, 0x6a, 0x43, 0x13, 0x7d, 0x83, 0x55, 0xe4, 0x0f, 0x8f, 0x8f, 0x2e, 0x81, 0x8c, + 0x9d, 0x5d, 0xc9, 0xcc, 0x87, 0xbe, 0x8f, 0x0c, 0xee, 0xb9, 0x29, 0x67, 0x5c, 0x05, 0x89, 0x32, 0x70, 0xf7, 0x6a, + 0x96, 0x8c, 0xb5, 0x08, 0xdf, 0x3f, 0x2a, 0x8a, 0x3e, 0x93, 0xa6, 0x01, 0xdd, 0x47, 0x82, 0x39, 0xd0, 0x7b, 0x85, + 0x0e, 0x97, 0xd5, 0x36, 0x13, 0xf0, 0x17, 0x09, 0xf2, 0x5b, 0xa1, 0x57, 0x35, 0x06, 0x55, 0xb4, 0x8b, 0x58, 0xfa, + 0xf7, 0x11, 0x3f, 0xca, 0xe6, 0x3f, 0xcd, 0x3d, 0x5e, 0x49, 0x18, 0xfc, 0x90, 0x9a, 0x4d, 0x32, 0x6f, 0xaf, 0xd8, + 0x77, 0xd0, 0x51, 0x8f, 0x5a, 0xe3, 0x7d, 0xf5, 0x82, 0x53, 0x88, 0x51, 0x42, 0xd1, 0x49, 0x30, 0x80, 0xdb, 0x25, + 0xa4, 0xb8, 0x1b, 0xec, 0xb6, 0x79, 0xcd, 0x8b, 0x82, 0xf3, 0x75, 0x55, 0x05, 0x7e, 0x40, 0xc3, 0xf9, 0x62, 0x3f, + 0x84, 0xe1, 0x98, 0xb6, 0xae, 0x61, 0x10, 0x66, 0x0c, 0x23, 0x21, 0x78, 0xfd, 0x8b, 0x1e, 0xd1, 0x24, 0x5e, 0xfd, + 0xc0, 0x3f, 0x67, 0xbc, 0x50, 0x44, 0x1a, 0x44, 0x48, 0xdd, 0xc4, 0x37, 0x32, 0x4d, 0x0a, 0x28, 0x04, 0x18, 0x05, + 0x54, 0x62, 0x43, 0x53, 0xf1, 0xb7, 0x5a, 0x7c, 0xf0, 0x53, 0xd3, 0xf1, 0x68, 0x5c, 0xb7, 0x3a, 0xa3, 0x82, 0xce, + 0x40, 0x8f, 0x5a, 0x51, 0x4f, 0x83, 0x56, 0x82, 0x69, 0xa4, 0x79, 0xeb, 0x1e, 0x02, 0xaf, 0x4c, 0x8b, 0x77, 0x1e, + 0xd0, 0xed, 0x99, 0x0f, 0x9e, 0x3c, 0xa6, 0x67, 0x0e, 0x3d, 0xb9, 0x62, 0x27, 0x55, 0x0f, 0xb5, 0xf7, 0x66, 0x84, + 0x82, 0x7e, 0x1f, 0x53, 0xa0, 0x1b, 0x41, 0xed, 0x5d, 0xdd, 0x2b, 0xb9, 0xcf, 0xe1, 0x3b, 0xce, 0x72, 0x0b, 0x58, + 0x2a, 0xb2, 0x56, 0xe0, 0x51, 0x80, 0xba, 0x54, 0x86, 0xb0, 0xc5, 0x1c, 0x0e, 0x95, 0xdd, 0xaa, 0xd5, 0x50, 0x92, + 0xe3, 0x72, 0x04, 0x0e, 0xa1, 0xeb, 0x72, 0x50, 0x8e, 0x96, 0x59, 0xf5, 0x1e, 0x7f, 0x6b, 0xd6, 0x21, 0xc9, 0xee, + 0x62, 0x1d, 0xb8, 0x65, 0x1d, 0xa6, 0x9f, 0x0c, 0x52, 0x00, 0x9a, 0x6c, 0x04, 0x2e, 0x01, 0x78, 0x6f, 0xff, 0x11, + 0xa1, 0x56, 0xa6, 0x77, 0x32, 0x16, 0xea, 0xfb, 0x46, 0x12, 0x94, 0xd0, 0x4c, 0xa8, 0x1c, 0x4b, 0xc1, 0x3b, 0x8f, + 0x74, 0x4e, 0xea, 0x4c, 0xbc, 0x07, 0x71, 0x5a, 0x78, 0xcf, 0xde, 0x82, 0xe0, 0x9c, 0x05, 0xdd, 0xe0, 0x6d, 0x56, + 0x4b, 0x6d, 0xf4, 0x40, 0x01, 0xfc, 0x6e, 0xb0, 0x41, 0x90, 0xaf, 0xc6, 0x70, 0xad, 0xe4, 0x4d, 0xc8, 0x87, 0x05, + 0x3d, 0x22, 0x03, 0xfb, 0x2c, 0x86, 0x31, 0x3d, 0x22, 0xc7, 0xf6, 0x59, 0xba, 0x01, 0x1c, 0x48, 0x3d, 0xaa, 0xf4, + 0x08, 0x1a, 0xf4, 0x2f, 0xdb, 0x22, 0x77, 0x00, 0x4a, 0xa3, 0x88, 0x81, 0x2a, 0x41, 0x44, 0x2d, 0xfe, 0x7d, 0x6f, + 0xae, 0x0d, 0xe6, 0x02, 0x61, 0x0e, 0x06, 0x1c, 0xc4, 0x6d, 0x10, 0x9a, 0x03, 0x66, 0x7b, 0x1b, 0x09, 0xba, 0xb1, + 0x86, 0x99, 0x1d, 0xfd, 0xe1, 0x56, 0x82, 0x6f, 0xb2, 0xd6, 0xa8, 0xf3, 0xe2, 0x10, 0x08, 0x82, 0x37, 0x85, 0xaa, + 0xf6, 0xaa, 0x07, 0x36, 0xde, 0xaa, 0x1f, 0xbb, 0xdd, 0x78, 0x2a, 0xdc, 0xb5, 0x5f, 0x50, 0x38, 0xf9, 0x94, 0xfc, + 0xeb, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3c, + 0x52, 0xf4, 0xef, 0x4e, 0x59, 0xf9, 0xd4, 0x4e, 0xff, 0x6e, 0x67, 0xd6, 0xe7, 0xf1, 0x68, 0xb2, 0xdb, 0xf5, 0xe2, + 0x4a, 0x7b, 0xac, 0xe9, 0x05, 0x81, 0xce, 0xf5, 0xe4, 0xf0, 0x08, 0xa2, 0x22, 0x34, 0xe3, 0x6e, 0x96, 0x0d, 0x89, + 0x8c, 0x1f, 0xa7, 0xb3, 0x6c, 0x08, 0x76, 0xb8, 0x17, 0x95, 0xb8, 0x1c, 0xb5, 0x36, 0x38, 0xbd, 0x4d, 0x42, 0x08, + 0xe5, 0x80, 0x95, 0xdd, 0xaa, 0x3f, 0x1b, 0x65, 0x26, 0xa4, 0x26, 0xab, 0xdb, 0x29, 0xdd, 0xc3, 0x34, 0x3f, 0x30, + 0x23, 0x38, 0xe0, 0xde, 0xfe, 0xaa, 0x3f, 0x85, 0x49, 0xa6, 0xc9, 0x29, 0x92, 0x5f, 0xa4, 0xa7, 0x90, 0xb4, 0x47, + 0x4f, 0x15, 0x01, 0x9c, 0x50, 0xfb, 0x31, 0xfc, 0x86, 0x71, 0xff, 0xa1, 0xf9, 0xda, 0x4d, 0x45, 0xf4, 0x98, 0x62, + 0x99, 0x9a, 0x9c, 0x26, 0x59, 0x91, 0x40, 0xd4, 0x46, 0xd5, 0x8c, 0xe8, 0x91, 0x8b, 0xf9, 0xa8, 0x08, 0x9f, 0x57, + 0xeb, 0xff, 0x0c, 0xe1, 0x33, 0x92, 0x5d, 0x80, 0xcb, 0x2b, 0x2e, 0xcf, 0xc3, 0x27, 0x8f, 0xe9, 0xc1, 0xe4, 0xbb, + 0x23, 0x7a, 0x70, 0xf4, 0xe8, 0x09, 0x01, 0x58, 0xb4, 0xcb, 0xf3, 0xf0, 0xe8, 0xc9, 0x13, 0x7a, 0xf0, 0xfd, 0xf7, + 0xf4, 0x60, 0xf2, 0xe8, 0xa8, 0x91, 0x36, 0x79, 0xf2, 0x3d, 0x3d, 0xf8, 0xee, 0x71, 0x23, 0xed, 0x68, 0xfc, 0x84, + 0x1e, 0xfc, 0xfd, 0x3b, 0x93, 0xf6, 0x37, 0xc8, 0xf6, 0xfd, 0x11, 0xfe, 0x67, 0xd2, 0x26, 0x4f, 0x1e, 0xd1, 0x83, + 0xc9, 0x18, 0x2a, 0x79, 0xe2, 0x2a, 0x19, 0x4f, 0xe0, 0xe3, 0x47, 0xf0, 0xdf, 0xdf, 0x08, 0x6c, 0x02, 0xc9, 0x96, + 0x02, 0xf5, 0x67, 0x28, 0xe2, 0x44, 0xd5, 0x44, 0xc2, 0x43, 0xcc, 0xac, 0xbe, 0x89, 0xc3, 0x80, 0xb8, 0x74, 0x28, + 0x88, 0x1e, 0x8c, 0x47, 0x4f, 0x48, 0xe0, 0xc3, 0xd3, 0x7d, 0xf2, 0x41, 0xc6, 0x96, 0x62, 0x9e, 0x7d, 0xb3, 0x34, + 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x0f, 0x7e, 0x2e, 0x2e, 0xe7, 0xd9, 0x37, 0x5c, 0xee, 0xe7, 0xfa, 0xb1, 0x05, 0x28, + 0xef, 0xaf, 0x5a, 0xf6, 0xa9, 0x50, 0xa1, 0xd3, 0x5a, 0xa3, 0xcf, 0x3e, 0x60, 0xfa, 0x60, 0xe0, 0xdd, 0xb0, 0x7f, + 0xde, 0x2b, 0xa7, 0xf5, 0x8d, 0x46, 0xa1, 0x46, 0xe5, 0x21, 0x61, 0x27, 0x50, 0xf4, 0x60, 0x00, 0x3c, 0x81, 0x2b, + 0xe3, 0xf7, 0xff, 0xb0, 0x8c, 0x0f, 0x1d, 0x65, 0xfc, 0x03, 0x65, 0x08, 0x68, 0xd4, 0xc3, 0xec, 0xa6, 0x87, 0x8d, + 0x6e, 0xf5, 0x92, 0xa5, 0x3a, 0x99, 0x9a, 0x9e, 0xc1, 0xbe, 0xd6, 0xb5, 0x3c, 0x30, 0xa2, 0x68, 0x79, 0x71, 0x90, + 0xf2, 0x59, 0xc5, 0x7e, 0x5e, 0xa2, 0x7a, 0x2b, 0x6a, 0xbc, 0x91, 0xd9, 0xac, 0x62, 0xbf, 0x9b, 0x37, 0xc0, 0xcd, + 0xb0, 0x1f, 0xd5, 0x93, 0x1f, 0x38, 0x23, 0x93, 0xb6, 0x3d, 0xca, 0xc4, 0x08, 0xb0, 0x02, 0x32, 0x70, 0xe0, 0x01, + 0xd0, 0x41, 0x7f, 0xb4, 0x77, 0x3b, 0x95, 0xd2, 0xec, 0xb3, 0x85, 0x01, 0x34, 0xcc, 0xdb, 0xc4, 0x95, 0x5d, 0xa5, + 0xbe, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0xf6, 0x0a, 0x53, 0x71, 0x7b, 0x52, 0x06, 0x80, 0x03, 0x01, 0x06, 0x63, + 0x2d, 0x03, 0x6a, 0xb6, 0x7c, 0xb4, 0xe5, 0x4a, 0x3d, 0x09, 0x9c, 0xc1, 0x85, 0x2c, 0x12, 0xfe, 0x56, 0x8b, 0xfd, + 0xd1, 0xfa, 0xd1, 0xf7, 0xed, 0xf1, 0x60, 0xed, 0x7b, 0x7c, 0xa4, 0x3f, 0x6b, 0x5c, 0x07, 0xb6, 0x2d, 0xdf, 0x78, + 0x51, 0x5b, 0x89, 0x47, 0x09, 0xbc, 0x81, 0x89, 0x48, 0x61, 0x90, 0x6a, 0x81, 0x63, 0x50, 0xde, 0x58, 0x88, 0xa5, + 0xea, 0xea, 0x86, 0x6e, 0xc9, 0x10, 0x3c, 0xdc, 0xaa, 0x54, 0x05, 0x8e, 0xea, 0xf7, 0x33, 0xe9, 0xbb, 0x3d, 0x19, + 0x3b, 0x72, 0x9c, 0xfa, 0xa9, 0x70, 0xf0, 0xdf, 0xa4, 0xae, 0xf5, 0xcb, 0x2c, 0x65, 0x96, 0x65, 0x61, 0x27, 0xa1, + 0x96, 0x7b, 0x54, 0x1e, 0x24, 0x5f, 0xc8, 0x21, 0x92, 0x05, 0x46, 0xa1, 0x20, 0xc3, 0x09, 0x15, 0xa3, 0xb5, 0x28, + 0x97, 0xd9, 0x45, 0x15, 0x6e, 0x95, 0x42, 0x99, 0x53, 0xf4, 0xed, 0x06, 0x07, 0x12, 0x12, 0x65, 0xe5, 0x9b, 0xf8, + 0x4d, 0x88, 0x60, 0x75, 0x5c, 0xdb, 0x42, 0x71, 0x6f, 0x7f, 0x8a, 0xb4, 0x8b, 0x3f, 0x32, 0x2e, 0xa0, 0x2e, 0x16, + 0xd3, 0x70, 0x62, 0x63, 0x1f, 0xb8, 0x2f, 0xac, 0xa6, 0x07, 0xa0, 0xbe, 0x4b, 0x25, 0x46, 0x50, 0x5f, 0x19, 0xfb, + 0xd8, 0x1e, 0x63, 0x72, 0x06, 0xb1, 0x86, 0x75, 0xd9, 0xaa, 0x6f, 0x84, 0x9d, 0x00, 0x70, 0x23, 0xb4, 0x46, 0x47, + 0x26, 0xa9, 0x42, 0x3c, 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xb9, 0x46, 0x4a, 0x5f, 0x30, 0x68, + 0x8e, 0x6d, 0x1d, 0x85, 0xd5, 0x56, 0x96, 0x9d, 0x00, 0xdc, 0x40, 0x76, 0x6c, 0x2e, 0x9e, 0xb3, 0x6a, 0x9e, 0x2d, + 0x22, 0x13, 0x14, 0x30, 0x15, 0x96, 0x41, 0x7b, 0x73, 0x87, 0x6c, 0xc7, 0x21, 0x74, 0xc3, 0x7d, 0x04, 0xe3, 0x69, + 0x37, 0x05, 0x2b, 0x88, 0x46, 0x88, 0x87, 0x19, 0xb3, 0xf8, 0x5e, 0x69, 0xca, 0x53, 0xd5, 0x12, 0x08, 0x1c, 0x85, + 0x50, 0x17, 0xfb, 0x46, 0x09, 0x2e, 0x53, 0x23, 0x98, 0xc1, 0x9e, 0x1d, 0xa9, 0xed, 0x92, 0x73, 0x3a, 0x54, 0x53, + 0x5a, 0xea, 0x29, 0xd5, 0xbe, 0x86, 0x62, 0x5e, 0xa2, 0x87, 0x1e, 0xb8, 0x1e, 0x68, 0x87, 0xbc, 0x92, 0x4e, 0x4c, + 0x04, 0x9d, 0x56, 0x9b, 0xb0, 0x73, 0x23, 0xdd, 0xb2, 0x1a, 0x79, 0xc7, 0xd0, 0xec, 0x88, 0x57, 0x7e, 0xa0, 0x2e, + 0x80, 0x08, 0xb9, 0xb3, 0x45, 0x86, 0x38, 0xb3, 0xac, 0x7c, 0x01, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, + 0x93, 0x4b, 0x1e, 0x89, 0x14, 0x11, 0x01, 0x4f, 0x95, 0x76, 0x7d, 0xaf, 0x25, 0x84, 0x96, 0x29, 0x10, 0x37, 0x17, + 0xc5, 0xb9, 0xb6, 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x94, 0x5d, 0x79, 0xe1, 0x60, 0xb7, 0x57, 0x99, 0x78, 0xc6, 0x2f, + 0x32, 0xc1, 0x53, 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x03, 0x2c, 0x98, 0x32, 0xd4, + 0x4a, 0x89, 0x4c, 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0xeb, 0x4c, 0xbc, 0x8e, 0x6f, 0xc1, 0x9b, 0xa2, 0xc1, 0x4f, + 0x8f, 0xce, 0xf1, 0x4b, 0x44, 0x12, 0x85, 0x18, 0xb6, 0x18, 0x11, 0x0b, 0x91, 0x63, 0xc7, 0x84, 0x72, 0x25, 0x68, + 0x6d, 0x0d, 0x81, 0x17, 0x7f, 0x5a, 0x75, 0xef, 0x2a, 0x13, 0xc6, 0x3e, 0xe3, 0x2a, 0xbe, 0x65, 0xa5, 0x02, 0xb3, + 0xc0, 0x38, 0xf7, 0x6d, 0x29, 0xc9, 0x55, 0x26, 0x8c, 0x80, 0xe4, 0x2a, 0xbe, 0xa5, 0x4d, 0x19, 0x87, 0xb6, 0xa2, + 0xf3, 0xe2, 0xfc, 0xee, 0x0f, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, + 0xa9, 0xd1, 0x42, 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbf, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, + 0x08, 0x9d, 0x74, 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x12, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x31, + 0xe3, 0xd3, 0x62, 0x30, 0x20, 0xda, 0xa5, 0x70, 0x8b, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x42, + 0xaa, 0x90, 0xf4, 0x9e, 0x01, 0x89, 0x90, 0x2e, 0xd8, 0x2d, 0x48, 0x14, 0x3d, 0xff, 0x3b, 0xb5, 0x05, 0xf7, 0x3d, + 0x18, 0x9b, 0xd1, 0x7d, 0x3d, 0xe3, 0x3f, 0xd4, 0xb6, 0x20, 0xea, 0x53, 0xc9, 0x7a, 0x1d, 0x89, 0x2a, 0xe4, 0x22, + 0xfc, 0xec, 0x68, 0x88, 0x21, 0xaa, 0x3d, 0x16, 0x88, 0xf5, 0xd5, 0x39, 0x2f, 0x70, 0xfa, 0x99, 0xbb, 0x5c, 0xc1, + 0xb6, 0xa0, 0x95, 0xa1, 0x51, 0x6f, 0xe2, 0x37, 0x91, 0xbd, 0x2c, 0xe8, 0x22, 0x9f, 0xa1, 0x90, 0x35, 0x0f, 0xc3, + 0x6a, 0xd8, 0x1e, 0x44, 0x72, 0xd8, 0x9e, 0x84, 0x46, 0x63, 0x60, 0x81, 0xec, 0xd1, 0x08, 0x5c, 0x84, 0x56, 0xfe, + 0x76, 0x0c, 0x2e, 0x5c, 0x16, 0x91, 0x65, 0xa8, 0xe3, 0x37, 0xb5, 0x9b, 0xa0, 0x7a, 0x85, 0x4e, 0x53, 0x58, 0x95, + 0x32, 0xc9, 0x87, 0x5f, 0x2f, 0x64, 0x81, 0x99, 0xbc, 0x2e, 0x7b, 0xf4, 0xb5, 0xdd, 0xde, 0x81, 0x29, 0x58, 0xf7, + 0xc9, 0xfb, 0xfa, 0x61, 0x67, 0x4f, 0xc0, 0x28, 0x56, 0xe5, 0x68, 0x0a, 0x29, 0xb5, 0x0f, 0x4a, 0xfd, 0x29, 0x4c, + 0x85, 0xe6, 0xd8, 0x2d, 0x60, 0x12, 0xb0, 0xcf, 0x90, 0xea, 0x31, 0xed, 0xd8, 0xe7, 0x68, 0x0b, 0x4b, 0x02, 0x0e, + 0xff, 0x48, 0xc8, 0xda, 0xbf, 0xba, 0xcb, 0xb4, 0x19, 0xb2, 0x65, 0xbe, 0x00, 0x3e, 0x1f, 0x76, 0x6d, 0x54, 0xa2, + 0x6c, 0x22, 0x92, 0x14, 0xb6, 0x3c, 0x06, 0x69, 0x8f, 0x62, 0xba, 0x2a, 0x78, 0x92, 0xa1, 0x94, 0x22, 0xd1, 0x3e, + 0xc1, 0x39, 0xbc, 0xc1, 0xfd, 0xa8, 0x02, 0xc2, 0xab, 0x90, 0xd3, 0x51, 0x4a, 0xb5, 0x05, 0x8c, 0xa2, 0x1e, 0x20, + 0xca, 0xcb, 0x40, 0x8e, 0xb7, 0xdb, 0x4d, 0xe8, 0x8a, 0x2d, 0x87, 0x13, 0x8a, 0xa4, 0xe4, 0x12, 0xcb, 0xbd, 0x02, + 0x9d, 0xc7, 0x39, 0xeb, 0xbd, 0x02, 0x2c, 0x82, 0x33, 0xf8, 0x1b, 0x13, 0x7a, 0x0d, 0x7f, 0x73, 0x42, 0x9f, 0xb2, + 0xf0, 0x6a, 0x78, 0x49, 0x0e, 0xc3, 0x74, 0x30, 0x51, 0x82, 0xb1, 0x0d, 0x4b, 0xcb, 0x50, 0x25, 0xae, 0x0e, 0x2f, + 0xc8, 0xc3, 0x0b, 0x7a, 0x4b, 0x6f, 0xe8, 0x6b, 0xfa, 0x00, 0x08, 0xff, 0xe6, 0x78, 0xc2, 0x87, 0x93, 0xc7, 0xfd, + 0x7e, 0xef, 0xbc, 0xdf, 0xef, 0x9d, 0x19, 0x03, 0x0a, 0xbd, 0x8b, 0x2e, 0x6b, 0xaa, 0x7f, 0x5d, 0xd5, 0x8b, 0xe9, + 0x03, 0xb5, 0x71, 0x13, 0x9e, 0xe5, 0xe1, 0xd5, 0xe1, 0x86, 0x0c, 0xf1, 0xf1, 0x22, 0x97, 0xb2, 0x08, 0x2f, 0x0f, + 0x37, 0x84, 0x3e, 0x38, 0x01, 0xbd, 0x29, 0xd6, 0xf7, 0xe0, 0xe1, 0x46, 0xd7, 0x46, 0xe8, 0xab, 0x30, 0x81, 0x6d, + 0x72, 0xcb, 0xec, 0x5d, 0x7b, 0x32, 0x86, 0x58, 0x26, 0x1b, 0xaf, 0xbc, 0xcd, 0xc3, 0x5b, 0x72, 0x78, 0x0b, 0x9e, + 0xa2, 0x96, 0xfc, 0xcd, 0xc2, 0x1b, 0xd6, 0xaa, 0xe1, 0xe1, 0x86, 0xbe, 0x6e, 0x35, 0xe2, 0xe1, 0x86, 0x44, 0xe1, + 0x0d, 0xbb, 0xa4, 0xaf, 0xd9, 0x15, 0xa1, 0xe7, 0xfd, 0xfe, 0x59, 0xbf, 0x2f, 0xfb, 0xfd, 0x9f, 0xe3, 0x30, 0x8c, + 0x87, 0x05, 0x39, 0x94, 0x74, 0x73, 0x38, 0xe1, 0x8f, 0xc8, 0x2c, 0xd4, 0xcd, 0x57, 0x0b, 0xce, 0xaa, 0xbc, 0x55, + 0xae, 0x0d, 0x05, 0x6b, 0x85, 0x0d, 0x53, 0x4f, 0x0f, 0xe8, 0x0d, 0x2b, 0xe8, 0x6b, 0x16, 0x93, 0xe8, 0x1a, 0x5a, + 0x71, 0x3e, 0x2b, 0xa2, 0x1b, 0xfa, 0x9a, 0x9d, 0xcd, 0xe2, 0xe8, 0x35, 0x7d, 0xc0, 0xf2, 0xe1, 0x04, 0xf2, 0xbe, + 0x1e, 0xde, 0x90, 0xc3, 0x07, 0x24, 0x0a, 0x1f, 0xe8, 0xdf, 0x1b, 0x7a, 0xc9, 0xc3, 0x07, 0xd4, 0xab, 0xe6, 0x01, + 0x31, 0xd5, 0x37, 0x6a, 0x7f, 0x40, 0x22, 0x7f, 0x30, 0x1f, 0x58, 0x7b, 0x9a, 0x77, 0x8e, 0x36, 0xae, 0xcb, 0x70, + 0x43, 0xe8, 0xba, 0x0c, 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x2e, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, + 0xbd, 0xc1, 0x31, 0x34, 0x23, 0xa4, 0xfb, 0x89, 0x69, 0xb8, 0x0e, 0x3e, 0x6a, 0xb0, 0x8e, 0xf3, 0x7e, 0x3f, 0x5c, + 0xf7, 0xfb, 0x10, 0xe9, 0xbe, 0x98, 0x99, 0xd8, 0x6e, 0x8e, 0x6c, 0xd2, 0x1b, 0xd0, 0xfe, 0x7f, 0x1c, 0x0c, 0xa0, + 0x33, 0x5e, 0x49, 0xe1, 0xcd, 0xe0, 0xe3, 0xc3, 0x0d, 0x51, 0x75, 0x14, 0xb4, 0x94, 0x61, 0x41, 0x9f, 0xd2, 0x0c, + 0x00, 0xbf, 0x3e, 0x0e, 0x06, 0x24, 0x32, 0x9f, 0x91, 0xe9, 0xc7, 0xe3, 0x07, 0xd3, 0xc1, 0xe0, 0xa3, 0xd9, 0x26, + 0x9f, 0xd9, 0x1d, 0xa5, 0xc0, 0xfa, 0x3b, 0xeb, 0xf7, 0x3f, 0x9f, 0xc4, 0xe4, 0xbc, 0xe0, 0xf1, 0xa7, 0x69, 0xb3, + 0x2d, 0x9f, 0x5d, 0x54, 0xb5, 0xb3, 0x7e, 0x7f, 0xdd, 0xef, 0xbf, 0x06, 0xec, 0xa2, 0x99, 0xf3, 0xf5, 0x04, 0x69, + 0xcb, 0xdc, 0x51, 0x24, 0x4d, 0x72, 0x68, 0x0c, 0x6d, 0x8b, 0x55, 0xdb, 0x66, 0x1d, 0x19, 0x58, 0x1c, 0x35, 0x2b, + 0x8a, 0x6b, 0x12, 0x85, 0xbd, 0xb3, 0xdd, 0xee, 0x35, 0x63, 0x2c, 0x26, 0x20, 0xfd, 0xf0, 0x5f, 0xbf, 0xae, 0x1b, + 0x31, 0xc4, 0x4a, 0x25, 0xbe, 0xdb, 0x2e, 0xed, 0x21, 0x10, 0x71, 0xd8, 0xf4, 0xef, 0xcd, 0xbd, 0x5c, 0xd4, 0x8e, + 0x6f, 0xfd, 0x1d, 0x40, 0x88, 0x24, 0x0b, 0xf9, 0x0c, 0xc7, 0xa0, 0xcc, 0x00, 0xc8, 0x3c, 0x52, 0x33, 0x2f, 0x01, + 0x04, 0x98, 0xec, 0x76, 0xa3, 0xf1, 0x78, 0x42, 0x0b, 0x36, 0xfa, 0xdb, 0x93, 0x87, 0xd5, 0xc3, 0x30, 0x08, 0x06, + 0x19, 0x69, 0xe9, 0x29, 0xec, 0x62, 0xad, 0x0e, 0xc1, 0x08, 0x5e, 0xb3, 0x8f, 0xd7, 0xd9, 0x57, 0xb3, 0x8f, 0x48, + 0x58, 0x1b, 0x8c, 0x23, 0x17, 0x69, 0x4b, 0x6f, 0x77, 0x07, 0x83, 0xc9, 0x45, 0xfa, 0x05, 0xb6, 0xd3, 0xe7, 0xdf, + 0x3c, 0x18, 0x4f, 0x38, 0x18, 0xdd, 0x45, 0x41, 0x9f, 0x69, 0xbb, 0x5d, 0xe5, 0x5f, 0x02, 0xdf, 0x60, 0x2a, 0xe8, + 0xd8, 0x2c, 0x0b, 0x37, 0xa8, 0x88, 0x3a, 0x5a, 0x06, 0x55, 0xad, 0x6c, 0xe7, 0x80, 0x5a, 0x62, 0x55, 0x26, 0x6e, + 0x81, 0x61, 0xc8, 0x50, 0x97, 0x7b, 0x5a, 0xfd, 0xce, 0x0b, 0x69, 0xe0, 0x33, 0x9c, 0x88, 0xd0, 0xe3, 0xd6, 0xb8, + 0xcf, 0xad, 0x89, 0x2f, 0x70, 0x6b, 0x25, 0x92, 0x58, 0x03, 0x4b, 0x6a, 0x2e, 0x47, 0x09, 0x3b, 0x29, 0x19, 0x9f, + 0x95, 0x51, 0x42, 0x63, 0x78, 0x90, 0x4c, 0xcc, 0x64, 0x94, 0xa0, 0x7d, 0xa2, 0x8b, 0x30, 0xf8, 0x17, 0x60, 0xf6, + 0xd3, 0x1c, 0xfe, 0x4a, 0x32, 0x4d, 0x8e, 0x21, 0x20, 0xc4, 0xf1, 0x78, 0x16, 0x87, 0x63, 0x12, 0x25, 0x27, 0xf0, + 0x04, 0xff, 0x15, 0xe1, 0x98, 0xd4, 0xfa, 0x0e, 0x23, 0xd5, 0xe5, 0x36, 0x61, 0x00, 0x57, 0x36, 0x9e, 0x4d, 0x22, + 0x2b, 0xdd, 0x95, 0x0f, 0x47, 0xe3, 0x27, 0x64, 0x1a, 0x87, 0x72, 0x90, 0x10, 0x0a, 0xde, 0xbd, 0x61, 0x39, 0x4c, + 0x34, 0x3c, 0x1b, 0xb0, 0x79, 0xa5, 0x63, 0xf3, 0x24, 0x9c, 0x80, 0x30, 0x4c, 0xc8, 0xb1, 0xde, 0x81, 0x94, 0xa2, + 0xcf, 0x73, 0xec, 0xa7, 0x3e, 0x82, 0x30, 0x3b, 0x6a, 0xa9, 0xf8, 0x0a, 0x80, 0x2e, 0x71, 0x70, 0xa8, 0x3d, 0xf3, + 0xc5, 0x2c, 0x2c, 0x3d, 0x2a, 0x65, 0xaa, 0x3b, 0x14, 0x0d, 0xca, 0x6f, 0x1a, 0x74, 0x28, 0xc8, 0x60, 0x42, 0xcb, + 0x93, 0x09, 0x7f, 0x04, 0x01, 0x3c, 0x1a, 0x11, 0xbf, 0x14, 0x4e, 0x0c, 0x84, 0x57, 0x41, 0x06, 0x2a, 0xad, 0x55, + 0x63, 0x46, 0xb6, 0xe2, 0x03, 0x08, 0x93, 0x72, 0x70, 0x23, 0xd7, 0x79, 0x0a, 0x51, 0xc1, 0xd6, 0x79, 0x75, 0x70, + 0x09, 0x96, 0xec, 0x71, 0x05, 0x71, 0xc2, 0xd6, 0x2b, 0xc0, 0xce, 0x7d, 0xb0, 0x2d, 0xeb, 0x03, 0xf5, 0xdd, 0x01, + 0xb6, 0x1c, 0x5e, 0x55, 0xf2, 0x60, 0x32, 0x1e, 0x8f, 0x47, 0x7f, 0xc0, 0xd1, 0x01, 0x84, 0x96, 0x44, 0x86, 0x4f, + 0x06, 0x68, 0xdc, 0x75, 0xc5, 0xbd, 0x71, 0xa1, 0x28, 0x2b, 0x9d, 0x4c, 0x08, 0x88, 0x9f, 0x4d, 0xdf, 0x60, 0x5f, + 0x71, 0x1d, 0xff, 0x64, 0xff, 0x13, 0xb3, 0xa2, 0xd5, 0x4a, 0x1d, 0xbd, 0x7b, 0xfb, 0xe1, 0xd5, 0xc7, 0x57, 0xbf, + 0x3e, 0x3f, 0x7b, 0xf5, 0xe6, 0xc5, 0xab, 0x37, 0xaf, 0x3e, 0xfe, 0xfb, 0x1e, 0x06, 0xdb, 0xb7, 0x15, 0xb1, 0x63, + 0xef, 0xdd, 0x63, 0xbc, 0x5a, 0x7c, 0xe1, 0xec, 0x91, 0xbb, 0xc5, 0x02, 0x6c, 0x82, 0xe1, 0x16, 0x04, 0xd5, 0x8c, + 0x46, 0xa5, 0xef, 0x09, 0xc8, 0x68, 0x54, 0xc8, 0xc6, 0xc3, 0x8a, 0xad, 0x90, 0x8b, 0x77, 0x0c, 0x07, 0x1f, 0xd9, + 0xdf, 0x8a, 0x33, 0xe1, 0x76, 0xb4, 0x35, 0x2b, 0x02, 0x3e, 0x5f, 0x6b, 0x51, 0x79, 0x5c, 0x88, 0xda, 0xdb, 0xf6, + 0x39, 0x24, 0xd4, 0x23, 0x72, 0x1d, 0xbc, 0x6f, 0x83, 0xec, 0xf1, 0x91, 0xf7, 0xa4, 0x3c, 0x43, 0x7d, 0x8e, 0x86, + 0x8f, 0x1a, 0xcf, 0xe8, 0xc4, 0x5c, 0x1b, 0x1d, 0xea, 0x59, 0x01, 0xfb, 0x5b, 0x89, 0xb1, 0xc1, 0x1c, 0x3a, 0x45, + 0xac, 0x0f, 0xa7, 0xfb, 0xdd, 0xbf, 0x19, 0xfd, 0x0c, 0xc7, 0x8f, 0x52, 0x4d, 0x20, 0x2d, 0x0a, 0x94, 0xae, 0x0c, + 0xb9, 0xed, 0x59, 0x58, 0x98, 0x9f, 0x61, 0x83, 0x00, 0xda, 0xcb, 0x8e, 0x25, 0x81, 0x66, 0xf1, 0x5a, 0xd7, 0x3f, + 0x2f, 0x5f, 0x26, 0xda, 0xf9, 0xe2, 0x5b, 0x08, 0x31, 0xec, 0x5f, 0x11, 0x1a, 0x13, 0xee, 0x26, 0xd9, 0x5d, 0x5a, + 0xcc, 0xbd, 0xea, 0x2a, 0xc6, 0xe3, 0xee, 0x8e, 0x2b, 0x45, 0xf3, 0xd6, 0x05, 0xf6, 0x40, 0xcd, 0xeb, 0x78, 0xc9, + 0x42, 0xc0, 0x66, 0x3c, 0xb4, 0x8b, 0xc4, 0xf9, 0xbd, 0xd3, 0x09, 0x39, 0x3c, 0x9a, 0xf2, 0x21, 0x2b, 0xa9, 0x18, + 0xb0, 0xb2, 0xde, 0xa3, 0xe6, 0xbc, 0x4d, 0xc8, 0xc5, 0x3e, 0x0d, 0x17, 0x43, 0x7e, 0xdf, 0x25, 0xe9, 0x23, 0x6f, + 0x38, 0x54, 0xdb, 0xe6, 0x62, 0x48, 0x53, 0x4e, 0xf7, 0xa9, 0x0c, 0x08, 0x91, 0xae, 0xe2, 0x8a, 0xd4, 0xfa, 0xa8, + 0x5a, 0x3b, 0x49, 0xc7, 0x75, 0xb6, 0xfd, 0xc2, 0x25, 0x5b, 0xdd, 0xae, 0xfd, 0x6b, 0x75, 0xfb, 0xc2, 0x0c, 0xe4, + 0xef, 0x4f, 0x44, 0x35, 0x31, 0x10, 0x5d, 0x40, 0x05, 0xff, 0x04, 0x2f, 0x4f, 0x1e, 0x69, 0x05, 0xe8, 0x5d, 0x67, + 0x47, 0xd7, 0x1e, 0x6f, 0xcc, 0x62, 0x6b, 0x89, 0x73, 0x56, 0xf9, 0xce, 0xf2, 0xaa, 0x6c, 0x85, 0xae, 0x23, 0xd8, + 0xef, 0x61, 0x47, 0xdf, 0xbd, 0x6d, 0x00, 0x44, 0x29, 0xac, 0xdc, 0xd9, 0x2f, 0xbc, 0xb3, 0x5f, 0xd8, 0xb3, 0xdf, + 0x6e, 0x02, 0xe5, 0xc3, 0x0a, 0x2d, 0x7b, 0x21, 0x45, 0x65, 0x9a, 0x3c, 0x6e, 0xea, 0xb2, 0x90, 0x16, 0xf3, 0x43, + 0x4b, 0xbb, 0x1e, 0x8f, 0xa9, 0x44, 0xf5, 0xc8, 0x4b, 0x6c, 0xd5, 0x61, 0x49, 0xee, 0xbf, 0x67, 0xfe, 0xcf, 0xde, + 0x20, 0xef, 0xba, 0xdb, 0xfd, 0xdf, 0x5c, 0xe8, 0xe0, 0xb6, 0xb6, 0x16, 0x9e, 0xba, 0x3a, 0x2e, 0xf0, 0xae, 0xb6, + 0xbe, 0xff, 0xae, 0xf6, 0x36, 0xd3, 0xcb, 0xae, 0x02, 0xd4, 0x20, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0xd4, 0x56, 0xa1, + 0xf1, 0x80, 0x43, 0x68, 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x53, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0xfd, + 0x80, 0x87, 0x19, 0x19, 0xf8, 0x12, 0x3f, 0x29, 0x7d, 0x71, 0xf1, 0xe1, 0x5e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0x7b, + 0x21, 0xdb, 0x31, 0x3f, 0xfc, 0x2f, 0x30, 0x1a, 0x84, 0xd7, 0x96, 0xec, 0x50, 0x74, 0xcc, 0x72, 0x05, 0x47, 0x6d, + 0xe9, 0x95, 0xd9, 0xba, 0x7e, 0x56, 0xc3, 0x4c, 0x9f, 0x29, 0x0f, 0x40, 0xf6, 0x85, 0xdc, 0xfd, 0x54, 0x57, 0x2c, + 0xc8, 0xc9, 0x64, 0x3c, 0x25, 0x62, 0x30, 0x68, 0x25, 0x1f, 0x63, 0xf2, 0x70, 0xb8, 0xc7, 0x5c, 0x0a, 0xdd, 0x0f, + 0x2f, 0xf2, 0x2f, 0xd4, 0xd7, 0xd8, 0x92, 0x64, 0x5b, 0xb1, 0xbf, 0xc0, 0x2c, 0x16, 0x88, 0xa3, 0x83, 0x5f, 0x9c, + 0x2f, 0x68, 0x09, 0x6d, 0xa8, 0x0c, 0x7a, 0x72, 0x91, 0x2a, 0x1f, 0xd9, 0x82, 0xc9, 0xe3, 0xf1, 0xcc, 0xef, 0xb9, + 0x63, 0x70, 0x08, 0x89, 0x26, 0xd6, 0xf8, 0xc5, 0xcf, 0x82, 0x71, 0x1c, 0xca, 0x13, 0xd9, 0xf8, 0xae, 0x24, 0xd1, + 0xd8, 0x98, 0x2a, 0xeb, 0xab, 0x44, 0x35, 0x4c, 0xc8, 0xc3, 0x82, 0x1c, 0x16, 0x74, 0xe9, 0x8f, 0x25, 0xa6, 0x1f, + 0xc6, 0x87, 0x93, 0x31, 0x79, 0x18, 0x3f, 0x9c, 0x18, 0xb8, 0x61, 0x3f, 0x47, 0x3e, 0x5c, 0x92, 0xc3, 0x66, 0x95, + 0x60, 0x8a, 0x6a, 0x7a, 0xe6, 0x57, 0x92, 0x0c, 0x96, 0x83, 0xf4, 0x61, 0x2b, 0x2f, 0xd6, 0xaa, 0xc7, 0x7b, 0x7d, + 0xcc, 0xa7, 0x44, 0x34, 0x6e, 0x0c, 0x6b, 0x7a, 0x15, 0xff, 0x29, 0x8b, 0x48, 0x4a, 0x40, 0x24, 0x04, 0xf5, 0x76, + 0x76, 0x91, 0x25, 0xb1, 0x48, 0xa3, 0xb4, 0x26, 0x34, 0x3d, 0x61, 0x93, 0xf1, 0x2c, 0x65, 0xe9, 0xf1, 0xe4, 0xc9, + 0x6c, 0xf2, 0x24, 0x3a, 0x1a, 0x47, 0xe9, 0x60, 0x00, 0xc9, 0x47, 0x63, 0x70, 0xb1, 0x83, 0xdf, 0xec, 0x08, 0x86, + 0xee, 0x04, 0x59, 0xc2, 0x02, 0x9a, 0xf6, 0x75, 0x4d, 0xd2, 0xc3, 0x79, 0xa1, 0x7a, 0x12, 0xdf, 0xd2, 0xb5, 0xe7, + 0xe0, 0xe2, 0xb7, 0xf0, 0xc2, 0xb5, 0xf0, 0x62, 0xbf, 0x85, 0x42, 0x93, 0xed, 0x58, 0xfe, 0xff, 0x71, 0xc3, 0xb8, + 0xeb, 0x2e, 0x61, 0x16, 0xd7, 0x75, 0x36, 0x5a, 0x15, 0xb2, 0x92, 0x70, 0x9b, 0x50, 0xa2, 0xb0, 0x51, 0xbc, 0x5a, + 0xe5, 0xda, 0x45, 0x6c, 0x5e, 0x51, 0x00, 0x77, 0x81, 0x38, 0xc5, 0xc0, 0x42, 0x1b, 0x03, 0xb9, 0xcf, 0xbc, 0x90, + 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0xcf, 0x10, 0x8c, 0x51, 0xc5, 0xc9, 0x78, 0xa6, 0xb0, 0x2e, 0xbe, 0x24, 0xef, + 0xfd, 0x0f, 0x8e, 0x22, 0x7b, 0x34, 0x83, 0x9e, 0x20, 0x72, 0x1e, 0x71, 0xf6, 0x64, 0xf2, 0x32, 0x70, 0x3f, 0x83, + 0x95, 0xfe, 0xba, 0xdb, 0x8c, 0xb5, 0xed, 0xd1, 0xbd, 0x30, 0x42, 0xd1, 0xcf, 0xf8, 0xce, 0xd4, 0x0b, 0xb8, 0x84, + 0x6a, 0x60, 0xd7, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, 0xf4, 0xfb, 0xbd, 0x3f, 0x0d, 0x34, 0x69, 0xc9, 0x8b, + 0xd7, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x9f, 0x2a, 0xfb, 0x4c, 0xc7, 0x64, 0xe6, 0x3f, 0x0e, 0x27, + 0x24, 0x6a, 0xbe, 0x26, 0x5f, 0x38, 0x4d, 0xbf, 0x70, 0x45, 0xfb, 0x6f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, + 0x8e, 0x79, 0x32, 0x7a, 0x9d, 0x98, 0x9d, 0x08, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, + 0x61, 0xf6, 0x41, 0x8d, 0x28, 0x8e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, + 0xf8, 0xa9, 0x0a, 0xb1, 0x73, 0x90, 0xf6, 0xa9, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, + 0x7c, 0x5d, 0x62, 0x4a, 0xa1, 0x3e, 0xf8, 0xef, 0x48, 0xd5, 0x1d, 0xd3, 0xaf, 0xd6, 0x8f, 0x3f, 0x13, 0x8a, 0x4f, + 0x77, 0x29, 0xf1, 0x2d, 0x04, 0x77, 0x8e, 0x41, 0x07, 0x51, 0xa1, 0x19, 0xdb, 0xfd, 0xfc, 0xae, 0xb8, 0x9b, 0xdf, + 0x15, 0xff, 0xef, 0xf8, 0x5d, 0x71, 0x1f, 0x63, 0x58, 0x59, 0x68, 0xf8, 0x59, 0x30, 0x0e, 0xa2, 0xff, 0x3e, 0x9f, + 0x78, 0x27, 0x4f, 0x7d, 0x95, 0x89, 0xe9, 0x1d, 0x4c, 0xb3, 0x4f, 0x50, 0x10, 0x56, 0x71, 0x9f, 0x9e, 0xac, 0x2b, + 0x7b, 0x6b, 0x25, 0x43, 0xcc, 0x73, 0x0f, 0x6b, 0x14, 0x56, 0x1e, 0xd0, 0x3d, 0xaa, 0x36, 0x88, 0x13, 0xc1, 0xc3, + 0x98, 0x59, 0xe9, 0xfb, 0x6e, 0x67, 0x54, 0x98, 0xf7, 0x72, 0x51, 0x90, 0xdd, 0x7c, 0x3c, 0x1b, 0x47, 0x21, 0x36, + 0xe0, 0xbf, 0xcd, 0x58, 0x35, 0x64, 0xf3, 0x9d, 0x8c, 0xd4, 0x9e, 0xc9, 0xd3, 0x64, 0x9f, 0xf4, 0x0e, 0x78, 0x87, + 0xfc, 0xbc, 0xfe, 0x14, 0xc6, 0xd2, 0xf0, 0x5b, 0xf2, 0x32, 0x2e, 0xb2, 0x6a, 0x79, 0x95, 0x25, 0xc8, 0x74, 0xc1, + 0x8b, 0xaf, 0x66, 0xba, 0xbc, 0x8f, 0xf5, 0x01, 0xe3, 0x29, 0xc5, 0xeb, 0x86, 0x28, 0xfd, 0xa2, 0xe5, 0x59, 0xa1, + 0x2e, 0x4f, 0x2a, 0x66, 0x7b, 0x56, 0x82, 0xd3, 0x29, 0x98, 0xe0, 0xeb, 0x9f, 0xae, 0xf7, 0x09, 0xe0, 0x82, 0x42, + 0xcd, 0x69, 0x21, 0x57, 0x06, 0xcb, 0xc9, 0x42, 0x77, 0x02, 0x66, 0xa8, 0x14, 0x78, 0x81, 0x82, 0xbf, 0x68, 0x60, + 0x44, 0x5f, 0xb8, 0xdf, 0x64, 0x60, 0x90, 0x2e, 0xcd, 0x89, 0x30, 0x76, 0xdc, 0x4e, 0x92, 0xb6, 0xa2, 0x9c, 0x71, + 0xf6, 0x5e, 0x5d, 0x29, 0xc0, 0x00, 0x6f, 0x7b, 0x13, 0x6d, 0x12, 0xf4, 0x5a, 0x50, 0x3a, 0x6f, 0xe0, 0x6e, 0x96, + 0x91, 0x11, 0x2e, 0x3e, 0xac, 0x3c, 0x16, 0xdc, 0xb3, 0x5f, 0x48, 0xac, 0xad, 0x1f, 0x18, 0xb3, 0x79, 0xc1, 0x02, + 0x85, 0x0a, 0x14, 0x58, 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0x87, 0x47, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xe1, 0x51, + 0x1d, 0x65, 0xc7, 0x90, 0xe5, 0xc4, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xbd, 0xfa, 0xf2, 0xd4, 0x1f, + 0xd5, 0x2d, 0xb8, 0x7e, 0x00, 0x02, 0xd8, 0x00, 0x1c, 0x02, 0xd5, 0x60, 0x69, 0x44, 0xb0, 0x28, 0x53, 0x68, 0x5f, + 0x43, 0xef, 0x8d, 0x86, 0xff, 0x02, 0x77, 0x11, 0xb9, 0xf2, 0x3f, 0x41, 0xe0, 0xaf, 0x28, 0xd3, 0xca, 0x14, 0xff, + 0x13, 0xad, 0x5e, 0xa1, 0x9c, 0x35, 0xad, 0xf9, 0x20, 0x5a, 0x13, 0xa1, 0x9a, 0x31, 0x04, 0xff, 0x56, 0x96, 0x69, + 0x4b, 0x55, 0xa5, 0x3e, 0x34, 0x5e, 0x6b, 0x85, 0xb3, 0x7c, 0x1c, 0x79, 0xaf, 0x31, 0x74, 0x6c, 0xe2, 0x2c, 0xe5, + 0x54, 0xea, 0xec, 0xcd, 0xa1, 0x8c, 0x1c, 0xe0, 0x74, 0xc2, 0xc6, 0xd3, 0xe4, 0x58, 0x4e, 0x13, 0x07, 0x99, 0x9f, + 0x33, 0x8c, 0xac, 0x6a, 0x40, 0x58, 0x94, 0x0d, 0xa5, 0x2d, 0xc0, 0x24, 0x27, 0x84, 0x4c, 0x31, 0x14, 0x45, 0x3e, + 0xd2, 0xfd, 0xb0, 0xde, 0xac, 0xee, 0x8b, 0x77, 0x1a, 0xe0, 0x34, 0x4c, 0x20, 0x10, 0x78, 0x11, 0xdf, 0x64, 0xe2, + 0x12, 0x3c, 0x86, 0x07, 0xf0, 0x25, 0xb8, 0xc9, 0xa5, 0xec, 0x5f, 0x55, 0x98, 0xe3, 0xda, 0x02, 0x06, 0x0d, 0x56, + 0x0f, 0xa2, 0xc3, 0xa5, 0xb4, 0xd9, 0x55, 0x80, 0xd8, 0x98, 0x42, 0x2c, 0x0b, 0xb6, 0xb6, 0xec, 0xd9, 0xcf, 0xaa, + 0x69, 0x68, 0x9d, 0x70, 0x2a, 0x2e, 0x73, 0x88, 0xa2, 0x32, 0x88, 0xc1, 0x1d, 0xc9, 0xe3, 0xf3, 0x4e, 0x45, 0x78, + 0x41, 0xc0, 0xad, 0x2c, 0x91, 0xe1, 0x8a, 0x2e, 0x47, 0xb7, 0x74, 0x3d, 0xba, 0xa1, 0x63, 0x3a, 0xf9, 0xfb, 0x18, + 0x2d, 0xb2, 0x55, 0xea, 0x86, 0xae, 0x47, 0x4b, 0xfa, 0xfd, 0x98, 0x1e, 0xfd, 0x6d, 0x4c, 0xa6, 0x4b, 0x3c, 0x4c, + 0xe8, 0x05, 0x38, 0x76, 0x91, 0x1a, 0x3d, 0x35, 0x7d, 0x83, 0xc3, 0x6a, 0x94, 0x0f, 0xf9, 0x28, 0xa7, 0x7c, 0x54, + 0x0c, 0xab, 0x11, 0x78, 0x3a, 0x56, 0x43, 0x3e, 0xaa, 0x28, 0x1f, 0x9d, 0x0f, 0xab, 0xd1, 0x39, 0x69, 0x36, 0xfd, + 0x55, 0xc5, 0xaf, 0x4a, 0x76, 0x01, 0xdb, 0x02, 0x96, 0xaf, 0x5b, 0x65, 0xcb, 0xd4, 0x5f, 0xd5, 0xe6, 0x64, 0xb6, + 0x9c, 0xbd, 0xbd, 0xee, 0x72, 0x62, 0xf1, 0xb8, 0x6d, 0x3a, 0x5c, 0x7d, 0x39, 0x51, 0x27, 0xbd, 0x42, 0x7e, 0x18, + 0x4f, 0x85, 0x3a, 0x87, 0xc0, 0x4c, 0x62, 0x16, 0xc6, 0x0c, 0x9b, 0xa9, 0xd3, 0x40, 0x81, 0x93, 0x8d, 0x3c, 0x17, + 0xc5, 0x6c, 0x94, 0x53, 0x78, 0x1f, 0x13, 0x12, 0x09, 0x38, 0xab, 0x4e, 0xaa, 0x51, 0x01, 0x31, 0x47, 0x58, 0x88, + 0x8f, 0xd0, 0x2f, 0xf5, 0x91, 0x87, 0x04, 0x9e, 0x61, 0x5f, 0x8b, 0x41, 0x0c, 0x47, 0xbc, 0xad, 0xac, 0x9a, 0x85, + 0x09, 0x54, 0x56, 0x0d, 0x4b, 0x53, 0x59, 0x41, 0xb3, 0x51, 0xe5, 0x57, 0x56, 0xe1, 0x18, 0x25, 0x84, 0x44, 0xa5, + 0xae, 0x0c, 0xd4, 0x27, 0x09, 0x0b, 0x4b, 0x5d, 0xd9, 0xb9, 0xfa, 0xe8, 0xdc, 0xaf, 0xec, 0x1c, 0x5c, 0x48, 0x07, + 0x89, 0x7f, 0x95, 0x4a, 0xd3, 0xf6, 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x96, 0xdf, 0x56, 0x45, 0x1c, 0x95, 0xd4, 0xc5, + 0x80, 0xc6, 0x85, 0x11, 0x49, 0xaa, 0xd7, 0x28, 0xf8, 0x43, 0x82, 0xa8, 0x34, 0x06, 0xaf, 0xce, 0xa4, 0x6b, 0xa5, + 0x56, 0x54, 0x0c, 0xca, 0x41, 0x01, 0xf7, 0xa7, 0xbc, 0xb5, 0x90, 0x7e, 0x86, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x17, + 0x0c, 0x9e, 0xcc, 0xae, 0xd2, 0x30, 0x19, 0x6d, 0x68, 0x3c, 0x5a, 0x22, 0x1c, 0x0c, 0x5b, 0xa5, 0x0a, 0x6f, 0xfd, + 0x12, 0xd2, 0x6f, 0x69, 0x3c, 0xba, 0xa1, 0xa9, 0xb5, 0x39, 0x35, 0x50, 0x57, 0xbd, 0x31, 0xbd, 0x8d, 0xe0, 0xf5, + 0x26, 0x5a, 0x52, 0xd8, 0x4a, 0xa7, 0x79, 0x76, 0x29, 0xa2, 0x94, 0x22, 0x02, 0xe1, 0x1a, 0x91, 0x03, 0x97, 0x1a, + 0x6d, 0x70, 0x3d, 0x80, 0x32, 0x34, 0x5c, 0xe0, 0x72, 0x10, 0x8f, 0x96, 0x1e, 0x99, 0x5a, 0xeb, 0x8b, 0x2c, 0xc2, + 0x47, 0x3b, 0x1b, 0x2d, 0xc5, 0x33, 0x62, 0x61, 0x5c, 0xc1, 0x10, 0xea, 0xc2, 0x4a, 0x53, 0x90, 0x74, 0x81, 0x23, + 0x7b, 0x61, 0x5c, 0x85, 0x5b, 0x30, 0x2d, 0xda, 0x80, 0x79, 0x14, 0x28, 0x1c, 0x5c, 0x82, 0xf4, 0x13, 0xca, 0x76, + 0x8e, 0xd2, 0xe4, 0xf0, 0x26, 0xe8, 0x62, 0x6f, 0x82, 0x90, 0x76, 0x75, 0x93, 0x2d, 0xe9, 0x1b, 0x6c, 0xef, 0xd1, + 0xa9, 0xa8, 0xa0, 0xfa, 0xdc, 0x82, 0xc9, 0x92, 0x0d, 0xc2, 0x96, 0x30, 0x3d, 0xd3, 0x17, 0x80, 0x3d, 0x7d, 0x78, + 0xb4, 0x37, 0xdf, 0xc5, 0xec, 0xcd, 0x61, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, + 0xe3, 0x72, 0xba, 0x44, 0x62, 0x67, 0xe8, 0x16, 0xe3, 0xf3, 0xe5, 0x82, 0x26, 0x78, 0xb6, 0xb1, 0x6a, 0xbe, 0x34, + 0x68, 0x29, 0x29, 0xc3, 0xf5, 0xb6, 0x44, 0xff, 0x7f, 0x75, 0xf1, 0x4b, 0x01, 0x5e, 0x82, 0xb1, 0x00, 0x10, 0xee, + 0xc1, 0xb4, 0x20, 0xb5, 0x51, 0x36, 0xd6, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, + 0xd0, 0xa1, 0x76, 0x94, 0x56, 0x0d, 0x9b, 0x39, 0xe0, 0x91, 0xd4, 0x39, 0x36, 0xf9, 0xfb, 0x78, 0x16, 0xa8, 0x81, + 0x08, 0xa2, 0xec, 0x18, 0x1f, 0x31, 0x70, 0x51, 0xa4, 0xe3, 0x76, 0xba, 0x22, 0x2e, 0xf7, 0x8f, 0x59, 0x88, 0x93, + 0x84, 0xb9, 0x66, 0xd9, 0x90, 0x55, 0x11, 0x26, 0xe8, 0xc2, 0xc0, 0x7e, 0x6d, 0xc8, 0xaa, 0xc3, 0x23, 0x88, 0xd4, + 0x6a, 0xcb, 0xb8, 0xea, 0x2a, 0xe3, 0x7b, 0x00, 0xb2, 0x66, 0x8c, 0x1d, 0xfd, 0x6d, 0x3c, 0x53, 0xdf, 0x44, 0x21, + 0x3f, 0x39, 0xfa, 0x1b, 0x24, 0x1f, 0x7f, 0x8f, 0xcc, 0x1c, 0x24, 0x37, 0x0a, 0x3a, 0x6f, 0xce, 0xba, 0x86, 0xd2, + 0xc4, 0xb5, 0x57, 0xea, 0xb5, 0x27, 0xcd, 0xda, 0x2b, 0xd0, 0x9d, 0xda, 0xf0, 0x1e, 0xca, 0x76, 0x16, 0x4c, 0xd0, + 0xd1, 0xec, 0x0e, 0x74, 0xf0, 0x4e, 0x11, 0xf4, 0x2c, 0x09, 0x8d, 0x47, 0xa8, 0x32, 0xea, 0xc5, 0x78, 0x50, 0x9d, + 0xac, 0x4b, 0xe6, 0x19, 0x30, 0xc7, 0xf6, 0x1c, 0x12, 0xc3, 0x5c, 0x1d, 0xd4, 0x29, 0x2b, 0x87, 0x39, 0x1e, 0xc0, + 0x6b, 0x26, 0x87, 0x62, 0x90, 0x6b, 0x94, 0xef, 0x0b, 0x56, 0x0c, 0xcb, 0x41, 0xae, 0xb9, 0x99, 0x69, 0x33, 0x36, + 0x6d, 0xa2, 0xc3, 0x33, 0xaf, 0xd8, 0xc9, 0xaa, 0x07, 0x7c, 0x2c, 0x78, 0x32, 0xfb, 0x9e, 0x8f, 0x0f, 0x80, 0x93, + 0xd9, 0xde, 0x46, 0x4b, 0xba, 0x89, 0x52, 0x7a, 0x13, 0xad, 0xe9, 0x32, 0xba, 0x30, 0x26, 0xc6, 0x49, 0x0d, 0xe7, + 0x00, 0xb4, 0x0a, 0x20, 0xf1, 0xd4, 0xaf, 0xf7, 0x3c, 0xa9, 0xc2, 0x25, 0x4d, 0xc1, 0x6d, 0xd8, 0xb7, 0xcf, 0x3c, + 0xf3, 0x25, 0x52, 0x5b, 0xc4, 0x58, 0xb3, 0x86, 0x8a, 0x5b, 0x6f, 0xdd, 0x47, 0xa2, 0x86, 0x9d, 0xeb, 0x62, 0x13, + 0x55, 0xc3, 0xc9, 0xb4, 0x04, 0xc4, 0xd6, 0x72, 0x38, 0x74, 0x47, 0xc8, 0xfe, 0xf1, 0xa3, 0x03, 0x3d, 0xf7, 0xa4, + 0xc5, 0xb6, 0x6d, 0xf9, 0x03, 0x43, 0x98, 0xd2, 0x2f, 0x1f, 0xf9, 0x80, 0x58, 0x71, 0x0e, 0x67, 0x23, 0x50, 0x47, + 0x2b, 0x74, 0xfa, 0x57, 0x15, 0x16, 0xfa, 0x00, 0xdf, 0xde, 0x46, 0x09, 0xdd, 0x44, 0xb9, 0x47, 0xd6, 0x96, 0x35, + 0x93, 0xd3, 0xb3, 0x2c, 0xe4, 0xed, 0x03, 0xbd, 0x5c, 0x00, 0x88, 0xd6, 0x20, 0xf6, 0xa5, 0xae, 0x47, 0xe0, 0x34, + 0x84, 0x26, 0xa1, 0x11, 0x5c, 0x55, 0x10, 0x46, 0xc0, 0x95, 0x84, 0xbf, 0xc1, 0x44, 0x05, 0xbe, 0x00, 0x17, 0x99, + 0x34, 0xcd, 0x79, 0x50, 0xfb, 0x23, 0xf9, 0xba, 0x68, 0x7b, 0xbb, 0xc2, 0x68, 0x82, 0xb1, 0x27, 0xda, 0xe7, 0x91, + 0x72, 0x14, 0x17, 0x49, 0x98, 0x8d, 0x6e, 0xd5, 0x79, 0x4e, 0xb3, 0xd1, 0x46, 0xff, 0xaa, 0xe8, 0x98, 0xfe, 0xaa, + 0x03, 0xda, 0x28, 0xe9, 0x5b, 0xc7, 0xd9, 0x80, 0xd6, 0x8b, 0xa5, 0xf1, 0xbf, 0x96, 0xa3, 0x5b, 0x2a, 0x47, 0x1b, + 0xdf, 0x92, 0x6a, 0x32, 0x2d, 0x8e, 0x05, 0x1a, 0x52, 0x75, 0x7e, 0x5f, 0x00, 0x3f, 0x57, 0x1a, 0xdf, 0x69, 0xf3, + 0xbd, 0xd7, 0xfe, 0x4d, 0x27, 0x4f, 0xa0, 0x58, 0xa2, 0x82, 0x55, 0x23, 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0x61, 0x46, + 0x29, 0xa6, 0xd6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x05, 0xb8, 0x5a, 0x82, 0x93, 0x00, 0xc4, 0xd0, 0x84, 0x3d, + 0x3b, 0x86, 0xa8, 0xe7, 0xc6, 0x31, 0x4a, 0x36, 0xdc, 0x03, 0x62, 0x2d, 0xf3, 0x56, 0x2e, 0x01, 0x09, 0xbc, 0xf5, + 0x30, 0x29, 0x00, 0x63, 0xb0, 0x5c, 0x12, 0x9d, 0xc7, 0x43, 0x9f, 0x50, 0x2f, 0x34, 0xea, 0x84, 0x6c, 0x6c, 0x09, + 0x1c, 0x7f, 0x58, 0x1f, 0x02, 0xc1, 0xab, 0x3c, 0xd7, 0x5f, 0x69, 0x5d, 0x7f, 0xa9, 0xf4, 0xdc, 0xb1, 0xbc, 0xa8, + 0xd5, 0x6d, 0x6a, 0xf4, 0x02, 0x2c, 0x7c, 0xb7, 0xca, 0x3c, 0x92, 0x5b, 0x84, 0x54, 0x05, 0x56, 0xea, 0x16, 0x12, + 0xcc, 0xbf, 0x92, 0xb3, 0x55, 0x99, 0xaf, 0x1e, 0xb9, 0x57, 0xce, 0xa6, 0xa7, 0xbf, 0x21, 0x41, 0xdb, 0x74, 0xa4, + 0x79, 0xbc, 0x45, 0x87, 0xcf, 0xae, 0xb5, 0xc4, 0xdc, 0x4b, 0x54, 0x3c, 0x9f, 0x02, 0xb6, 0x7a, 0x96, 0x5d, 0x29, + 0x1f, 0xab, 0x7d, 0x1c, 0x3f, 0x73, 0xfe, 0x24, 0x55, 0x78, 0x21, 0x1a, 0x4a, 0x10, 0xf0, 0xe6, 0x30, 0x76, 0x85, + 0x2a, 0xa0, 0xa1, 0xb9, 0x81, 0xe3, 0x5c, 0x0d, 0x2b, 0x4d, 0xc0, 0xb4, 0x94, 0x47, 0x07, 0x38, 0x34, 0x79, 0xd4, + 0x6e, 0x1a, 0x56, 0x86, 0xae, 0x35, 0xfa, 0xdc, 0x56, 0x3a, 0xe3, 0xcd, 0x86, 0x1f, 0x1e, 0x0d, 0x2a, 0xfc, 0x49, + 0x9a, 0xa3, 0xd1, 0xce, 0x0d, 0x77, 0x1a, 0x81, 0x99, 0x2b, 0xb9, 0x22, 0xfb, 0xa3, 0xe4, 0xe5, 0xf7, 0xf4, 0xc2, + 0x02, 0xfa, 0xf3, 0xdf, 0x17, 0x13, 0x4e, 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x3d, 0xe5, 0x95, 0x7d, + 0x89, 0x97, 0xce, 0xf1, 0x7f, 0xae, 0xc7, 0xda, 0x57, 0x20, 0xb4, 0x3a, 0x79, 0xd8, 0x9e, 0x2c, 0x10, 0x35, 0xa0, + 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, 0xb2, 0x6d, 0xc8, 0x5c, 0xf7, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, + 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, 0x2d, 0x3f, 0x82, 0x67, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, + 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, 0xb9, 0xdb, 0x95, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, + 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8f, 0x4f, 0x2b, 0xd0, 0xf7, 0xf8, 0x2e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, + 0xcd, 0xd1, 0xc9, 0xb3, 0x3c, 0xd5, 0xf8, 0xfc, 0x4a, 0x76, 0xd6, 0xbc, 0x5b, 0x8d, 0x29, 0xfe, 0x23, 0x75, 0xfb, + 0xce, 0x65, 0x68, 0xa2, 0xbf, 0x96, 0x07, 0x2d, 0x85, 0x05, 0xc7, 0x6d, 0xe3, 0xaf, 0xdf, 0x66, 0x0e, 0x31, 0x2c, + 0x5d, 0x0e, 0x6f, 0x42, 0x87, 0xee, 0xae, 0xb2, 0x37, 0xd7, 0x47, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, + 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0xaf, 0x87, 0xe1, 0xde, 0x3c, 0x6a, 0x76, 0x77, 0xb7, 0x9b, 0x90, 0xb6, 0x7d, 0x30, + 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0x76, 0xf0, 0x73, 0x58, 0x3d, 0xe4, 0x83, 0xdf, 0x71, 0x9c, 0x61, 0xf4, 0x33, + 0x65, 0xe8, 0xf3, 0xa2, 0x90, 0x57, 0xaa, 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x26, 0x7e, 0xd3, 0x0a, 0x10, + 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, + 0x87, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, 0x21, 0xf7, 0xa5, 0x6b, 0xfb, 0x4d, 0xfc, 0x52, 0xd3, 0x0e, 0xf7, 0x07, + 0xba, 0xa3, 0x75, 0xf7, 0x37, 0xcf, 0xe6, 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x67, 0x5c, 0xf6, 0x0c, 0xf7, + 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, + 0xe4, 0x56, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, + 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x32, 0x10, 0xce, 0x2d, 0xd1, 0x33, 0x6a, 0x7b, 0xa8, 0xd5, 0xbd, 0x86, 0x57, 0xd9, + 0x44, 0x9e, 0xf5, 0x9b, 0x79, 0x69, 0xd8, 0x17, 0xbc, 0x96, 0x82, 0x43, 0x63, 0xbb, 0x15, 0x6e, 0xb1, 0x78, 0x47, + 0xab, 0x95, 0xb5, 0xb6, 0xda, 0x6b, 0xa5, 0xa2, 0x77, 0xaf, 0x39, 0x4e, 0x9c, 0xa5, 0xb0, 0xfd, 0xf0, 0xfe, 0x82, + 0x5d, 0x13, 0xc0, 0xa0, 0xc5, 0x64, 0x81, 0x12, 0x54, 0xb2, 0x56, 0xb5, 0xdb, 0x29, 0xf1, 0xcb, 0xfd, 0xaa, 0xcb, + 0x6c, 0xe7, 0xf1, 0xeb, 0x26, 0xed, 0x0b, 0x9f, 0xa3, 0x1f, 0xe6, 0x0f, 0xd6, 0x49, 0xc9, 0x19, 0xc6, 0xb5, 0xfc, + 0xff, 0x2a, 0x7a, 0x59, 0x64, 0x69, 0xb4, 0x35, 0x3c, 0x98, 0x0d, 0xb5, 0xe9, 0x43, 0x63, 0x54, 0x6e, 0xd9, 0x28, + 0x22, 0x5a, 0xdd, 0x82, 0x60, 0x46, 0x71, 0x5f, 0xa2, 0xcd, 0x2b, 0x55, 0x16, 0xde, 0xe1, 0x0b, 0x1b, 0xbd, 0x61, + 0x7b, 0x42, 0x28, 0xdf, 0x3f, 0x2d, 0xcc, 0xaa, 0xa5, 0xa2, 0xc1, 0x76, 0x09, 0xef, 0x62, 0x54, 0xe9, 0x27, 0x4c, + 0xb6, 0x2c, 0x98, 0xea, 0xff, 0x8f, 0x45, 0x96, 0xb6, 0x29, 0x3a, 0x30, 0x9d, 0x4d, 0x9f, 0x4e, 0xba, 0xc5, 0x75, + 0x06, 0x2c, 0x22, 0xd8, 0x52, 0xe1, 0x78, 0x94, 0xda, 0x0d, 0x12, 0x26, 0x82, 0x9b, 0xa8, 0x97, 0x1d, 0x2d, 0x53, + 0xb2, 0x2a, 0xe0, 0xf9, 0x95, 0xab, 0x4c, 0xc7, 0xd1, 0xd0, 0xef, 0x9f, 0xa5, 0x26, 0xf4, 0x2b, 0xf5, 0x52, 0x15, + 0xe7, 0x61, 0x54, 0x1d, 0x2a, 0x8c, 0xd1, 0x92, 0xa6, 0x70, 0x0c, 0x66, 0x17, 0x61, 0x8a, 0x97, 0xb3, 0x6d, 0xc2, + 0xbe, 0x62, 0x20, 0x97, 0xda, 0xa0, 0x5e, 0x53, 0xa2, 0x35, 0x6b, 0x6f, 0xe6, 0x94, 0xd0, 0x0b, 0x56, 0xfa, 0x77, + 0xa1, 0x35, 0x08, 0x14, 0x65, 0x33, 0x65, 0xba, 0xd1, 0xed, 0xbc, 0xa0, 0x09, 0x2d, 0xe8, 0x8a, 0xd4, 0xa0, 0xef, + 0x75, 0x72, 0x76, 0x74, 0xb2, 0x33, 0xb3, 0x1e, 0xb3, 0x62, 0x38, 0x99, 0xc6, 0x70, 0x4d, 0x8b, 0xdd, 0x35, 0x6d, + 0xd9, 0xbc, 0x71, 0x35, 0x36, 0x4e, 0x83, 0x76, 0x81, 0xb4, 0x4d, 0x73, 0xfb, 0xa9, 0xc7, 0xed, 0xaf, 0x6b, 0xb6, + 0x9c, 0xf6, 0xd6, 0xbb, 0x5d, 0x2f, 0x05, 0x1b, 0x51, 0x8f, 0x8f, 0x5f, 0x2b, 0xe9, 0xba, 0xe5, 0xf2, 0x53, 0x78, + 0xf6, 0xf8, 0xfa, 0xa5, 0x0f, 0x2e, 0x47, 0xab, 0x36, 0x77, 0xbf, 0xdc, 0x47, 0x96, 0xfb, 0xaa, 0xa1, 0xe5, 0x7a, + 0x86, 0x9a, 0xe4, 0xd9, 0x68, 0xef, 0x50, 0x0b, 0x96, 0xb3, 0x6e, 0xc2, 0x13, 0x83, 0x1d, 0x7b, 0xd5, 0xd8, 0x1c, + 0x95, 0xb9, 0x64, 0x35, 0x48, 0xa0, 0x4f, 0xf2, 0x4c, 0xd3, 0x3f, 0xca, 0x30, 0x1f, 0xdd, 0xd2, 0x1c, 0x70, 0xc5, + 0x2a, 0x7b, 0xc9, 0x20, 0x75, 0xd5, 0x5e, 0xe2, 0xca, 0x57, 0x38, 0x24, 0x5b, 0x7c, 0x32, 0x4c, 0xd5, 0x17, 0x97, + 0x3c, 0xf8, 0x7f, 0x5b, 0xb5, 0x4a, 0xcf, 0x4d, 0x72, 0xc3, 0xf1, 0xaf, 0x93, 0xb6, 0x8f, 0x89, 0x41, 0x02, 0x9e, + 0xda, 0xc5, 0x50, 0x8d, 0xaa, 0x22, 0x16, 0x65, 0x6e, 0x62, 0x8e, 0xdd, 0xd9, 0x35, 0x74, 0x50, 0x06, 0xbf, 0x6e, + 0xf8, 0xc4, 0xdc, 0x81, 0xad, 0x40, 0x47, 0x27, 0x9a, 0xcb, 0x30, 0x33, 0x97, 0x61, 0xda, 0xb5, 0x55, 0x60, 0x78, + 0xd5, 0x56, 0x49, 0x94, 0xab, 0x51, 0x8f, 0x9b, 0x59, 0x6a, 0xf6, 0x22, 0xef, 0x5e, 0x93, 0x9e, 0xc4, 0x9f, 0x2e, + 0x3d, 0x79, 0x3d, 0x0c, 0x88, 0xfc, 0x9a, 0xa5, 0xe1, 0x1a, 0x05, 0xc1, 0xa9, 0xd5, 0x0e, 0xa4, 0xf9, 0x08, 0x90, + 0xf9, 0x71, 0x1a, 0x7e, 0xd0, 0xe2, 0x1c, 0xb2, 0x55, 0x1a, 0x27, 0xb6, 0x34, 0xea, 0x21, 0xb8, 0xf3, 0x5e, 0xf1, + 0x18, 0x02, 0x1f, 0x7e, 0xc4, 0xcd, 0xa0, 0xa2, 0xdb, 0x12, 0x13, 0xa5, 0xcd, 0xa3, 0x6e, 0xf9, 0xa8, 0x21, 0x54, + 0xb2, 0x32, 0xbc, 0x04, 0xda, 0xbb, 0x27, 0x30, 0xaa, 0x9c, 0x40, 0x66, 0x58, 0x1c, 0x1e, 0x0d, 0x53, 0x25, 0x28, + 0x1a, 0xca, 0xe1, 0x12, 0xe5, 0x80, 0x98, 0x04, 0x02, 0xa3, 0x62, 0x90, 0xea, 0xca, 0xd4, 0x8b, 0x41, 0xaa, 0x6f, + 0x55, 0xa4, 0x3e, 0xcb, 0xc2, 0x8a, 0xea, 0x16, 0xd1, 0x31, 0x1d, 0x4a, 0xba, 0x34, 0x3b, 0x35, 0xd7, 0xd2, 0x0b, + 0xb5, 0x1c, 0x9f, 0xea, 0x34, 0x18, 0xc5, 0x0f, 0x2e, 0x45, 0xbf, 0x55, 0xfb, 0xd9, 0x7f, 0x8b, 0x29, 0x35, 0x62, + 0x53, 0x7b, 0x8b, 0x18, 0x56, 0xed, 0xc7, 0xac, 0xca, 0x41, 0xbb, 0x0b, 0xca, 0xc6, 0xca, 0x38, 0xcf, 0x37, 0x82, + 0x99, 0x83, 0xb6, 0xb1, 0x6a, 0xfa, 0xd0, 0x1b, 0x31, 0x6a, 0x6f, 0x4c, 0x35, 0xee, 0x09, 0xfc, 0xb4, 0x41, 0xd3, + 0xbd, 0xc8, 0x73, 0xd4, 0x23, 0xef, 0xfe, 0x67, 0x8e, 0xec, 0x4c, 0xbe, 0x88, 0x65, 0x52, 0xb7, 0x8f, 0x49, 0xb0, + 0x50, 0x75, 0x8c, 0x2e, 0xdc, 0xc8, 0x94, 0xf6, 0x73, 0x6f, 0xfa, 0x11, 0xcf, 0xe4, 0x7e, 0x3b, 0x34, 0xea, 0x4b, + 0xc3, 0x5a, 0x52, 0x44, 0x7d, 0x41, 0x6f, 0x4d, 0x75, 0x74, 0x44, 0xbd, 0x8e, 0xc0, 0xea, 0x8a, 0xb6, 0xa8, 0x01, + 0x98, 0x8c, 0x6b, 0x5b, 0x9b, 0xcf, 0xc1, 0xd4, 0x56, 0x55, 0xf0, 0x84, 0xee, 0x0b, 0xa5, 0x7b, 0x93, 0xba, 0x6e, + 0x0d, 0xb1, 0x05, 0x0c, 0x08, 0xdc, 0xe8, 0xa9, 0xe9, 0x0f, 0x9a, 0xa8, 0x00, 0x34, 0x68, 0xdc, 0xce, 0x74, 0x8e, + 0x44, 0xbf, 0x53, 0x9b, 0xb6, 0x99, 0xea, 0x55, 0xe5, 0x03, 0xa8, 0xf8, 0xb3, 0x74, 0x76, 0x61, 0x46, 0x2c, 0x80, + 0x71, 0x0f, 0x9c, 0xa9, 0xde, 0x69, 0x06, 0xd6, 0x13, 0x79, 0x9e, 0x95, 0x3c, 0x91, 0x02, 0x66, 0x44, 0x5e, 0x5d, + 0x49, 0x01, 0xc3, 0xa0, 0x06, 0x00, 0x2d, 0x9a, 0xcb, 0x68, 0xc2, 0x1f, 0xd5, 0xf4, 0xae, 0x3c, 0xfc, 0x91, 0xce, + 0xf5, 0xdd, 0xb8, 0x06, 0x43, 0xe5, 0x75, 0xc5, 0xf7, 0x32, 0x7d, 0xc7, 0x1f, 0x7b, 0x99, 0x96, 0x72, 0x5d, 0xec, + 0x65, 0x79, 0xf4, 0x1d, 0x7f, 0xa2, 0xf3, 0x1c, 0x3d, 0xae, 0x69, 0x1a, 0x6f, 0xf6, 0xb2, 0xfc, 0xfd, 0xbb, 0xc7, + 0x36, 0xcf, 0xa3, 0x71, 0x4d, 0x6f, 0x38, 0xff, 0xe4, 0x32, 0x4d, 0x74, 0x55, 0xe3, 0xc7, 0x7f, 0xb7, 0xb9, 0x1e, + 0xd7, 0xf4, 0x4a, 0x8a, 0x6a, 0xb9, 0x57, 0xd4, 0xd1, 0x77, 0x47, 0x7f, 0xe7, 0xdf, 0x99, 0xee, 0x1d, 0xd5, 0xf4, + 0xaf, 0x75, 0x5c, 0x54, 0xbc, 0xd8, 0x2b, 0xee, 0x6f, 0x7f, 0xff, 0xfb, 0x63, 0x9b, 0xf1, 0x71, 0x4d, 0x37, 0x3c, + 0xee, 0x68, 0xfb, 0xe4, 0xc9, 0x63, 0xfe, 0xb7, 0xba, 0xa6, 0xbf, 0x31, 0x3f, 0x38, 0xea, 0x69, 0xe6, 0xe9, 0xe1, + 0x73, 0xd9, 0x44, 0x0d, 0x18, 0x7a, 0x68, 0x00, 0x4b, 0x69, 0xd5, 0x34, 0x77, 0x78, 0xe5, 0x82, 0xdb, 0xf7, 0x59, + 0x9c, 0xc6, 0x2b, 0x38, 0x08, 0xb6, 0x68, 0x9c, 0x55, 0x00, 0xa7, 0x0a, 0xbc, 0x67, 0x54, 0xd2, 0xac, 0x94, 0xbf, + 0x71, 0xfe, 0x09, 0x06, 0x0d, 0x21, 0x6d, 0x54, 0x64, 0xa0, 0xb7, 0x2b, 0x1d, 0xd9, 0x08, 0xfd, 0x37, 0x9b, 0x71, + 0x70, 0x7c, 0x18, 0xbd, 0x7e, 0x3f, 0x2c, 0x98, 0x08, 0x0b, 0x42, 0xe8, 0x9f, 0x61, 0x01, 0x0e, 0x25, 0x05, 0xf3, + 0xf2, 0x19, 0xdf, 0x73, 0x6d, 0x14, 0x16, 0x82, 0xe8, 0x2e, 0xb2, 0x0f, 0xa8, 0x7a, 0xf4, 0x1d, 0xba, 0x21, 0x5e, + 0x56, 0x58, 0x30, 0xb4, 0xaa, 0x81, 0x19, 0x82, 0xe2, 0x5f, 0xf3, 0x50, 0x82, 0x4f, 0x3c, 0xc0, 0x47, 0x8f, 0xc9, + 0x8c, 0xab, 0x6b, 0xed, 0xdb, 0x8b, 0xb0, 0xa0, 0x81, 0x6e, 0x3b, 0x04, 0x1d, 0x88, 0xfc, 0x17, 0xe0, 0x29, 0x30, + 0xf0, 0x61, 0x61, 0xd7, 0x1d, 0x78, 0x3e, 0xbf, 0x19, 0xd6, 0xd1, 0x85, 0x1f, 0xfd, 0xcd, 0xba, 0xb0, 0x67, 0x64, + 0x2a, 0x8f, 0xcb, 0xe1, 0x64, 0x3a, 0x18, 0x48, 0x17, 0xc7, 0xed, 0x34, 0x9b, 0xff, 0x36, 0x97, 0x8b, 0x05, 0xea, + 0xbe, 0x71, 0x5e, 0x67, 0xfa, 0x6f, 0xa4, 0x9d, 0x0f, 0x5e, 0x9f, 0xfe, 0xeb, 0xec, 0xc3, 0xe9, 0x0b, 0x70, 0x3e, + 0xf8, 0xf8, 0xfc, 0xc7, 0xe7, 0xef, 0x55, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, 0x93, 0xfa, 0x84, 0x7c, 0x58, 0x91, + 0xc3, 0x30, 0x7e, 0x58, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, 0x51, 0xdb, 0xdf, 0xe5, 0x70, 0xe2, + 0x81, 0x59, 0x5c, 0x37, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x79, 0xe2, 0xf5, 0x83, 0x93, 0xa9, 0x74, 0x6c, + 0x61, 0xc1, 0xa0, 0x6c, 0x68, 0xd3, 0x69, 0x36, 0x2f, 0x16, 0xb6, 0x5d, 0x6e, 0x81, 0x8c, 0xd2, 0xec, 0xe2, 0x22, + 0x54, 0xd0, 0xd5, 0x27, 0xa0, 0x01, 0x30, 0x8d, 0x2a, 0x5c, 0x8b, 0xf8, 0xcc, 0x2f, 0x3f, 0x1a, 0x7b, 0xcd, 0xbb, + 0x41, 0xdd, 0x93, 0x69, 0x56, 0xd5, 0x18, 0xd0, 0xc1, 0x84, 0x72, 0x37, 0xe8, 0x26, 0x98, 0x8c, 0x6a, 0xcb, 0x6f, + 0xf3, 0x6a, 0x61, 0x9a, 0xe3, 0x86, 0xa1, 0xf2, 0x4a, 0xbe, 0x90, 0x0d, 0x44, 0x06, 0x92, 0x61, 0xd8, 0xa3, 0x31, + 0x8a, 0xd4, 0x0f, 0xf6, 0xbd, 0xe3, 0xb7, 0xb9, 0x84, 0x68, 0x8a, 0x19, 0x48, 0xe7, 0x9f, 0x0b, 0xe5, 0x5c, 0x2e, + 0x19, 0x9f, 0x8b, 0xc5, 0x09, 0xb8, 0x9d, 0xcf, 0xc5, 0x22, 0xc2, 0xa0, 0x7c, 0x19, 0xc4, 0x2a, 0x01, 0xbb, 0x17, + 0x07, 0x3d, 0xd2, 0x09, 0x6d, 0x60, 0x37, 0x90, 0x64, 0x83, 0xd2, 0xae, 0x34, 0x44, 0xb9, 0x53, 0x1e, 0x6d, 0x10, + 0x79, 0x88, 0x55, 0xf3, 0xaa, 0xed, 0xc9, 0x66, 0x2e, 0x26, 0xb8, 0xca, 0x62, 0x26, 0xa7, 0xf1, 0x31, 0x2b, 0xa6, + 0x31, 0x94, 0x12, 0xa7, 0x69, 0x18, 0xd3, 0x09, 0x15, 0x84, 0x24, 0x8c, 0xcf, 0xe3, 0x05, 0x4d, 0x50, 0x4a, 0x10, + 0x42, 0xc8, 0x8f, 0x11, 0xda, 0xe6, 0xc0, 0x92, 0xb7, 0xdb, 0xcf, 0x53, 0xf1, 0xed, 0x19, 0x2e, 0xa3, 0x22, 0x74, + 0x8b, 0xce, 0x1a, 0xfe, 0x8d, 0xa8, 0xa0, 0x31, 0x56, 0x0c, 0x41, 0xc0, 0x0b, 0x8c, 0x4a, 0x58, 0x90, 0x98, 0x55, + 0x10, 0x45, 0xa0, 0x9c, 0xc7, 0x0b, 0x56, 0xd0, 0xa6, 0xcd, 0x69, 0xac, 0x4d, 0x82, 0x7a, 0x0e, 0x4b, 0xed, 0x40, + 0x2a, 0x15, 0x62, 0x8f, 0xcf, 0x44, 0xf4, 0x49, 0x1b, 0x1a, 0x00, 0x0a, 0x94, 0x92, 0x8b, 0xdf, 0x7c, 0xbd, 0x87, + 0x9b, 0x82, 0xfe, 0x67, 0x5b, 0x13, 0xed, 0x2c, 0x57, 0x87, 0xde, 0x7c, 0x41, 0xe3, 0x3c, 0x87, 0x50, 0x6c, 0x06, + 0x81, 0x5c, 0x64, 0x15, 0x44, 0xb4, 0xd8, 0x04, 0x26, 0x24, 0x1c, 0xb4, 0xe9, 0x17, 0x48, 0x6d, 0x88, 0xc9, 0x95, + 0x27, 0x06, 0x76, 0x5b, 0x25, 0x08, 0x38, 0xd2, 0xf3, 0xec, 0x73, 0x13, 0x63, 0x4d, 0x53, 0x33, 0x13, 0x6f, 0x43, + 0x21, 0x1a, 0xb4, 0x20, 0x9a, 0xc1, 0xfb, 0xe7, 0x8a, 0xe3, 0x55, 0x07, 0x7e, 0xc0, 0x3b, 0x17, 0x67, 0x5e, 0xcd, + 0x3c, 0x22, 0xa7, 0x3e, 0xcf, 0x11, 0xfd, 0x92, 0x87, 0xd5, 0x48, 0x27, 0x63, 0xac, 0x24, 0x0e, 0x7a, 0x1b, 0x2c, + 0x98, 0x13, 0xba, 0xe2, 0xa1, 0xe5, 0xe3, 0x5f, 0x20, 0x93, 0x51, 0x52, 0x63, 0x45, 0x57, 0x5a, 0x8c, 0x38, 0xaf, + 0x61, 0x96, 0x26, 0x2b, 0xba, 0x58, 0x68, 0xd2, 0x2c, 0x94, 0x69, 0x80, 0x4f, 0xa0, 0xc5, 0xc8, 0x3d, 0xd4, 0xb4, + 0x81, 0xd0, 0xb0, 0x3f, 0x04, 0x7c, 0xe4, 0x1e, 0x3a, 0xfc, 0xff, 0x3c, 0xbb, 0x40, 0xa4, 0xbd, 0x4b, 0x13, 0x19, + 0x8f, 0xd4, 0x0d, 0x1c, 0x14, 0xe3, 0x63, 0xdf, 0x4c, 0xfc, 0xca, 0x19, 0xbd, 0x4f, 0x2a, 0xdf, 0xe1, 0x83, 0xe5, + 0x8f, 0x37, 0x35, 0xb3, 0x32, 0x82, 0xf5, 0xb0, 0xdb, 0xe1, 0x82, 0x68, 0xbb, 0x00, 0x52, 0xcf, 0x78, 0xb5, 0xf0, + 0x8d, 0x57, 0xe3, 0x3b, 0x8c, 0x57, 0x9d, 0xd5, 0x57, 0x98, 0x93, 0x2d, 0xea, 0xb3, 0x94, 0x3c, 0x3f, 0x47, 0x99, + 0x60, 0xd3, 0xe5, 0xac, 0xa4, 0x2a, 0x95, 0xd0, 0x5e, 0xec, 0x67, 0x8c, 0x6f, 0x09, 0xc6, 0x59, 0x71, 0x18, 0x09, + 0x54, 0xa5, 0x92, 0x3a, 0xec, 0x15, 0xa0, 0x1e, 0x83, 0xf7, 0x06, 0x43, 0xd4, 0xc8, 0xd8, 0x4d, 0x1b, 0x08, 0x0d, + 0x8d, 0xf5, 0x68, 0xcf, 0x5a, 0x8f, 0xee, 0x76, 0x95, 0xf1, 0xb7, 0x93, 0xeb, 0x22, 0x41, 0x54, 0x61, 0x35, 0x9a, + 0x00, 0x6f, 0x9a, 0xd8, 0xdb, 0x92, 0x53, 0x5a, 0x60, 0xf8, 0xec, 0x3f, 0xc3, 0xd2, 0xa9, 0x24, 0x4a, 0x32, 0x2b, + 0xa3, 0x81, 0x3b, 0x07, 0x9f, 0xc5, 0x15, 0xac, 0x01, 0x88, 0xe4, 0x88, 0x1e, 0xae, 0x7f, 0x86, 0xd2, 0x65, 0x96, + 0x64, 0x26, 0x21, 0x33, 0x17, 0x69, 0x3b, 0xeb, 0x60, 0xe2, 0x4c, 0x6a, 0xbd, 0xb1, 0x90, 0x43, 0x83, 0xfc, 0x00, + 0xca, 0x10, 0x87, 0x4f, 0x3e, 0x98, 0x50, 0xa9, 0x42, 0xa9, 0x36, 0xba, 0xd9, 0x0d, 0xbc, 0xf2, 0x31, 0xbb, 0xe2, + 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, 0x67, 0x77, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x79, 0xfe, 0xe3, 0x69, + 0xe3, 0xd5, 0x3e, 0xe2, 0x68, 0x08, 0xb6, 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, + 0x14, 0xf4, 0xdb, 0x5f, 0xeb, 0x09, 0x78, 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x01, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, + 0xac, 0xcc, 0xee, 0xec, 0x56, 0x64, 0xa6, 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, + 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xbb, 0x5d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, + 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x91, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, + 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, 0x81, 0xdd, 0xc9, 0x87, 0x4f, 0xd9, 0x6a, 0xb6, 0x06, 0xd4, 0xfc, 0xab, + 0x4c, 0x00, 0xcd, 0xb5, 0x6b, 0xc1, 0x36, 0x85, 0x36, 0xd7, 0xf5, 0xd3, 0x78, 0x15, 0x27, 0xa0, 0xba, 0x01, 0x6f, + 0x91, 0x6b, 0x2d, 0xba, 0x32, 0xe8, 0xa2, 0xf4, 0x9e, 0x72, 0x2c, 0x29, 0x74, 0xf4, 0xbd, 0x27, 0xd4, 0xb9, 0x67, + 0x00, 0x97, 0x34, 0x6a, 0x9e, 0x6a, 0x29, 0x63, 0x01, 0xb0, 0xd0, 0xc1, 0x4c, 0x91, 0xad, 0xe8, 0xc6, 0x60, 0x52, + 0xc0, 0x5b, 0x03, 0xfc, 0x21, 0xb2, 0x4a, 0xdd, 0x15, 0xcb, 0xb0, 0xf4, 0xec, 0xaf, 0xfb, 0xfd, 0xd8, 0xb3, 0xbf, + 0x5e, 0x69, 0x5a, 0x17, 0xb7, 0x1b, 0x40, 0x6a, 0x0c, 0x20, 0x72, 0xaa, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, + 0x9d, 0x9a, 0x2c, 0x0a, 0x84, 0x7e, 0xaf, 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x9d, 0x0c, 0xb4, 0xd9, 0x07, + 0x04, 0x44, 0xf5, 0x33, 0xb2, 0xf9, 0x42, 0x39, 0x17, 0xab, 0xf0, 0xe1, 0x63, 0x0a, 0x01, 0x85, 0x3b, 0x6a, 0x74, + 0xde, 0x86, 0x48, 0xa0, 0xac, 0x50, 0xc4, 0x9a, 0x17, 0x6b, 0x49, 0xc8, 0x7c, 0xbc, 0x40, 0xc1, 0x95, 0x03, 0x76, + 0xe5, 0x6c, 0x32, 0x2c, 0x23, 0xce, 0xc2, 0xbb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x7b, 0x99, + 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, 0x82, 0xc0, 0x70, 0xc3, 0xaf, 0xf8, 0xf8, 0x68, 0x41, 0x40, 0x45, 0x66, + 0xcd, 0x42, 0xcc, 0x8b, 0xe3, 0x47, 0x80, 0x1a, 0x33, 0x3a, 0x7a, 0x32, 0xe5, 0x0c, 0x0e, 0x51, 0x3a, 0x06, 0x19, + 0xad, 0x80, 0xdf, 0x42, 0xfd, 0x6e, 0x9d, 0xf8, 0x3e, 0xf4, 0xab, 0xa0, 0x17, 0x31, 0x30, 0x1c, 0xd1, 0xe4, 0x30, + 0xe4, 0x83, 0xc9, 0x00, 0xb4, 0x25, 0xde, 0xee, 0x6b, 0x69, 0xc5, 0xcd, 0xe9, 0xd2, 0xe9, 0xfe, 0x49, 0x9b, 0x20, + 0x89, 0x54, 0xb2, 0x52, 0x11, 0x03, 0x08, 0x65, 0xa9, 0xb6, 0xc9, 0x1a, 0x2c, 0x2b, 0xcc, 0x92, 0xe6, 0x06, 0x25, + 0x71, 0x7f, 0x33, 0x70, 0x8c, 0x9a, 0x75, 0x1a, 0x96, 0x2d, 0x37, 0x6a, 0x80, 0xcf, 0x49, 0x58, 0x61, 0x6f, 0x38, + 0x33, 0xe9, 0x9d, 0xe9, 0x70, 0x75, 0xcc, 0xd9, 0x6b, 0x8e, 0x60, 0x1c, 0x09, 0xde, 0x78, 0xe8, 0x92, 0x69, 0xa8, + 0xc8, 0x94, 0x71, 0x30, 0xed, 0x01, 0xee, 0x3d, 0x07, 0xe3, 0x30, 0x36, 0xa8, 0x2c, 0xa9, 0x4f, 0xbd, 0xbb, 0x10, + 0x08, 0xd2, 0x5a, 0x2f, 0xf3, 0x19, 0x9e, 0x9e, 0x11, 0xca, 0xfe, 0x90, 0xc3, 0x17, 0x60, 0x47, 0x41, 0x4e, 0x26, + 0xfc, 0xc9, 0xc3, 0xfd, 0x40, 0x55, 0x7c, 0x10, 0x1c, 0xc4, 0x22, 0x3d, 0x08, 0x06, 0x02, 0x7e, 0x15, 0xfc, 0xa0, + 0x92, 0xf2, 0xe0, 0x22, 0x2e, 0x0e, 0xe2, 0x55, 0x5c, 0x54, 0x07, 0x37, 0x59, 0xb5, 0x3c, 0x30, 0x1d, 0x02, 0x68, + 0xde, 0x60, 0x10, 0x0f, 0x82, 0x83, 0x60, 0x50, 0x98, 0xa9, 0x5d, 0xb1, 0xb2, 0x71, 0x9c, 0x99, 0x10, 0x65, 0x41, + 0x33, 0x40, 0x58, 0xe3, 0x34, 0x00, 0x3e, 0x75, 0xcd, 0x52, 0x7a, 0x81, 0xe1, 0x06, 0xc4, 0x74, 0x0d, 0x7d, 0x00, + 0x1e, 0x79, 0x4d, 0x63, 0x58, 0x02, 0x17, 0x83, 0x01, 0xb9, 0x80, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, + 0x65, 0xa7, 0xbd, 0x0f, 0xcc, 0xb4, 0xdb, 0x01, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, + 0x60, 0x7f, 0x55, 0x54, 0x61, 0x2e, 0x95, 0xe6, 0xfb, 0x92, 0x9d, 0x0c, 0x54, 0xc4, 0xe1, 0x3d, 0x47, 0x8a, 0x36, + 0x2a, 0x97, 0x65, 0x4f, 0x96, 0x0d, 0x5f, 0x89, 0x2b, 0xee, 0xfc, 0xb8, 0x2a, 0x29, 0xf3, 0x2a, 0x5b, 0x29, 0xf6, + 0x6f, 0xc6, 0x35, 0xf7, 0x07, 0xd6, 0x9f, 0xcd, 0x57, 0x70, 0x6d, 0xf5, 0xde, 0x35, 0xb9, 0x46, 0xe4, 0x2c, 0xa1, + 0x5c, 0x52, 0xdb, 0x3c, 0xbc, 0xa5, 0xef, 0xf3, 0xab, 0x6f, 0x33, 0x9d, 0xc6, 0x67, 0x15, 0x16, 0x2e, 0x44, 0x2b, + 0x82, 0x43, 0x43, 0x2e, 0x9a, 0x47, 0x80, 0xb9, 0xf6, 0xd9, 0x0a, 0x0a, 0x52, 0x9f, 0x55, 0xe8, 0xdd, 0x0a, 0x09, + 0x2f, 0x34, 0xbb, 0x74, 0x3f, 0x90, 0x32, 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, + 0xb3, 0x10, 0xa3, 0x17, 0x79, 0x76, 0x02, 0xc6, 0xba, 0x4b, 0x76, 0x36, 0x3c, 0xf1, 0x1b, 0x9e, 0xb3, 0x16, 0x8d, + 0xa6, 0x4b, 0x96, 0xf4, 0xfb, 0x31, 0x98, 0x78, 0xa7, 0x2c, 0x87, 0x5f, 0xf9, 0x82, 0xae, 0x19, 0x60, 0x8a, 0xd1, + 0x0b, 0x48, 0x48, 0x11, 0x89, 0x64, 0xad, 0x4e, 0x92, 0x2f, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, + 0xd3, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x58, 0x4c, 0x07, 0x03, 0x4e, + 0x34, 0xdc, 0x78, 0xa9, 0xc4, 0xb5, 0xba, 0xc5, 0x1d, 0xc3, 0x58, 0xea, 0xdb, 0x22, 0x06, 0x07, 0xec, 0xa2, 0x95, + 0xdd, 0x3e, 0xc0, 0xbe, 0x72, 0xbc, 0x4b, 0x95, 0xdd, 0xe9, 0x31, 0xd3, 0x5c, 0xb6, 0x9a, 0x74, 0x52, 0x71, 0x37, + 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x57, 0x38, 0xc2, + 0xdc, 0x5b, 0xb7, 0xf9, 0xe4, 0xd0, 0x14, 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0x87, 0x5d, 0xfd, + 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x5e, 0xc5, 0x0d, 0x3f, 0x26, 0xea, 0x74, 0xa6, 0x0d, 0xa1, 0x7f, 0x65, 0xc4, 0xfd, + 0xa5, 0x71, 0x15, 0x6f, 0x7a, 0x97, 0xcf, 0x38, 0xd4, 0xd9, 0x0d, 0xa1, 0x00, 0x5c, 0xb5, 0xa7, 0x53, 0x37, 0x86, + 0xf4, 0x4a, 0x89, 0x6e, 0x83, 0x83, 0xdd, 0xe9, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x43, 0x39, + 0x88, 0x1f, 0x16, 0x74, 0x19, 0x89, 0x87, 0xc5, 0x20, 0x7e, 0x28, 0xeb, 0x7a, 0xff, 0x5c, 0xb9, 0xbb, 0x8f, 0xc8, + 0xb3, 0xee, 0xed, 0xa5, 0x12, 0x36, 0x06, 0x9e, 0x5d, 0x0b, 0x08, 0xa7, 0xe0, 0x89, 0x6c, 0x2d, 0x7d, 0xe8, 0xdc, + 0xee, 0x63, 0xcb, 0x24, 0x41, 0xd0, 0xf3, 0x36, 0x9b, 0x44, 0xb1, 0xb3, 0xcd, 0xa3, 0x0f, 0xa7, 0x40, 0x42, 0xb7, + 0xdb, 0x66, 0x5d, 0xad, 0x01, 0xc5, 0x34, 0x1c, 0xf3, 0xc3, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0x1f, 0x16, 0xa3, 0x25, + 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x27, 0xe3, 0x59, 0x1c, 0x4d, 0xea, 0x8e, 0xd3, 0x42, 0xe3, 0x9f, 0x7a, 0xb7, 0x50, + 0x04, 0x4e, 0xc5, 0x08, 0x8e, 0x9c, 0x0a, 0xe5, 0xa4, 0xd4, 0xc0, 0xf0, 0x3f, 0xa8, 0xf6, 0xb4, 0x69, 0xaf, 0xe3, + 0x2a, 0x59, 0x66, 0xe2, 0x52, 0x87, 0x0f, 0xd7, 0xd1, 0xc5, 0x6d, 0x40, 0x3b, 0xef, 0x32, 0xed, 0xf8, 0x75, 0xd2, + 0xa0, 0x27, 0xae, 0x66, 0x06, 0xdc, 0xba, 0x1f, 0xa1, 0x19, 0x02, 0xa3, 0xe5, 0xf9, 0x3b, 0xc4, 0xdc, 0xfe, 0x55, + 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, + 0xec, 0xbf, 0xa6, 0xb8, 0x16, 0x4b, 0xef, 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xde, 0x6d, 0xa5, 0xc5, + 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, 0xc9, 0xdf, 0xd7, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xae, 0x3e, 0x2a, 0x81, + 0x93, 0x11, 0x37, 0x94, 0x18, 0xbd, 0xa0, 0xab, 0x13, 0xb9, 0x67, 0xa7, 0xe6, 0x4d, 0xc5, 0x4c, 0xc5, 0x95, 0x6f, + 0xf6, 0xcc, 0x7f, 0x30, 0x14, 0x54, 0x82, 0x81, 0xb7, 0x39, 0xe3, 0xd1, 0x81, 0xee, 0xc6, 0xe8, 0xb4, 0x60, 0xb3, + 0xa0, 0x2e, 0xeb, 0xa6, 0x8d, 0x07, 0x8d, 0x38, 0x28, 0x8a, 0x55, 0xa1, 0x46, 0xc2, 0x13, 0x81, 0x80, 0x29, 0xbb, + 0xe2, 0x91, 0x11, 0xd4, 0xf4, 0x26, 0x14, 0x36, 0x14, 0xfc, 0x55, 0xa2, 0x9a, 0xde, 0x84, 0x36, 0x99, 0x38, 0xcd, + 0x20, 0x82, 0x19, 0xb1, 0xdd, 0x6f, 0x01, 0x6d, 0x6e, 0xcd, 0x68, 0x5b, 0xd7, 0x56, 0x5b, 0x85, 0x5c, 0x52, 0xa4, + 0x2c, 0xff, 0x9d, 0x9a, 0x0a, 0x4a, 0x6a, 0xb9, 0xe8, 0x4d, 0x9a, 0x2e, 0x7a, 0x3c, 0x33, 0x92, 0x40, 0xe5, 0x96, + 0x3b, 0x46, 0x7f, 0x08, 0x0b, 0x3c, 0x62, 0xe2, 0xc4, 0x82, 0xb9, 0xd5, 0x09, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, + 0x08, 0x1b, 0x7c, 0xcc, 0xb2, 0x79, 0xa9, 0x1f, 0x42, 0x5f, 0x58, 0xfa, 0x00, 0xec, 0x62, 0x83, 0x95, 0x2c, 0x03, + 0xf0, 0xbd, 0xa0, 0xdb, 0x95, 0x2c, 0x23, 0xa9, 0xba, 0x1f, 0xd7, 0x58, 0x82, 0x4a, 0x2b, 0x54, 0x5a, 0x52, 0x63, + 0x41, 0xe0, 0xab, 0xaa, 0xcb, 0x87, 0x64, 0x57, 0x81, 0x7a, 0xea, 0xa8, 0x01, 0xa7, 0x40, 0x55, 0x81, 0x05, 0x49, + 0x50, 0x19, 0xba, 0x2a, 0x30, 0xad, 0xc0, 0x34, 0x53, 0x85, 0x8b, 0x32, 0x3b, 0x94, 0x66, 0xbd, 0xe4, 0xb3, 0x78, + 0x10, 0x26, 0xc3, 0x98, 0x3c, 0x44, 0xa8, 0xfd, 0xc3, 0x3c, 0x8a, 0xb5, 0x5c, 0xf2, 0xd2, 0xf9, 0xc5, 0xdf, 0x7c, + 0xc1, 0x5e, 0xf7, 0x0c, 0x83, 0x05, 0x38, 0x4b, 0xdb, 0xab, 0x4c, 0xbc, 0x93, 0xad, 0xe0, 0x38, 0x98, 0x45, 0x39, + 0xac, 0x7a, 0x72, 0x44, 0x73, 0x91, 0x6b, 0xef, 0x22, 0x44, 0x0e, 0x32, 0x7b, 0x0c, 0xb0, 0x1b, 0xe1, 0xeb, 0xd0, + 0xda, 0xdc, 0xea, 0x0a, 0xf1, 0x37, 0x4a, 0x24, 0x7e, 0x92, 0xf2, 0xd3, 0x7a, 0xa5, 0x72, 0x55, 0x06, 0x8f, 0x55, + 0x37, 0x83, 0x67, 0xda, 0xf7, 0x58, 0xfb, 0xb7, 0xb6, 0x9b, 0xe3, 0xbd, 0x07, 0x0f, 0x5a, 0xff, 0x5b, 0x4f, 0x42, + 0x68, 0xaf, 0x9c, 0xa4, 0xee, 0xa8, 0xd1, 0x33, 0x93, 0x35, 0xa2, 0x12, 0xa6, 0x76, 0xa7, 0x72, 0x0c, 0xd4, 0x74, + 0x00, 0xd7, 0x12, 0x35, 0x41, 0x4f, 0x0a, 0x36, 0x86, 0x23, 0xce, 0xe2, 0xa0, 0x1d, 0xc7, 0x28, 0x5e, 0xce, 0x95, + 0x78, 0x39, 0x3f, 0x61, 0x1c, 0xa0, 0xb5, 0x00, 0xa9, 0x5e, 0xc3, 0x7e, 0xe6, 0x0a, 0x16, 0xd8, 0xdc, 0xf9, 0x8e, + 0x2c, 0x90, 0x21, 0x4e, 0x36, 0xc7, 0xc9, 0x1e, 0xd7, 0x7a, 0xee, 0x05, 0x3e, 0x4e, 0xea, 0x85, 0x57, 0x57, 0xd9, + 0xae, 0x6b, 0xc9, 0xca, 0x79, 0x31, 0x98, 0x40, 0x50, 0x96, 0x72, 0x5e, 0x0c, 0x27, 0x0b, 0x9a, 0xc3, 0x8f, 0x45, + 0x03, 0x1d, 0x62, 0x39, 0x48, 0xe0, 0xd2, 0xd9, 0x63, 0xc0, 0x1b, 0x4a, 0x2d, 0xee, 0xc6, 0x3a, 0x72, 0xac, 0xa3, + 0x38, 0x0c, 0x63, 0xc0, 0x95, 0x75, 0x02, 0xef, 0xbb, 0xaf, 0x8f, 0x4d, 0x40, 0x56, 0xed, 0x0a, 0xaf, 0x46, 0xb9, + 0xeb, 0x4a, 0xa3, 0x2f, 0x29, 0x3d, 0xe1, 0x05, 0x4f, 0x25, 0xbb, 0x5d, 0xcf, 0xc0, 0xd9, 0x12, 0x0f, 0x89, 0x77, + 0x8c, 0xe8, 0xc5, 0xb4, 0x91, 0x99, 0x13, 0x38, 0xb3, 0xdd, 0x65, 0x1b, 0xf3, 0x63, 0x07, 0x38, 0x58, 0x04, 0x21, + 0x71, 0x43, 0x18, 0x26, 0x76, 0x52, 0x0e, 0xb5, 0x10, 0xae, 0x6b, 0xe1, 0x75, 0x9c, 0x96, 0x31, 0xb8, 0x48, 0x6b, + 0xdb, 0xc4, 0x3b, 0xe8, 0xba, 0xe7, 0xc7, 0xdc, 0xea, 0x18, 0x6d, 0x21, 0xfd, 0x76, 0x74, 0xfa, 0xc0, 0x61, 0x00, + 0x9a, 0x1e, 0xcc, 0xaa, 0xf6, 0x99, 0xc4, 0xcd, 0x69, 0x27, 0x08, 0x89, 0x40, 0x14, 0xa5, 0x33, 0xc2, 0xf4, 0xef, + 0x35, 0x97, 0x55, 0xb4, 0xba, 0x97, 0x67, 0x0e, 0x79, 0x16, 0x7a, 0xdb, 0x83, 0x56, 0xcd, 0xdd, 0x60, 0x9c, 0xb8, + 0xdd, 0xde, 0xf9, 0x7f, 0xcb, 0xba, 0xb6, 0x5a, 0x23, 0x1e, 0xb6, 0xab, 0x1f, 0x34, 0xf6, 0x6a, 0x4f, 0xc5, 0x80, + 0xb9, 0x94, 0xde, 0x19, 0x55, 0xf2, 0x22, 0xe3, 0x25, 0x9e, 0x54, 0x97, 0x0d, 0x1f, 0xef, 0x9b, 0x6c, 0x64, 0x1e, + 0xc8, 0x14, 0x10, 0xcf, 0x3f, 0xa4, 0x46, 0x7d, 0x9c, 0xa2, 0x04, 0xfc, 0x9d, 0x8e, 0x6f, 0x44, 0x5f, 0xdb, 0x17, + 0x97, 0xbc, 0x7a, 0x7b, 0x23, 0xcc, 0x8b, 0x67, 0x56, 0xe7, 0x4f, 0x9f, 0x16, 0x3e, 0x74, 0x38, 0x6a, 0xef, 0xa0, + 0xc8, 0x92, 0x89, 0x93, 0x89, 0x91, 0xb5, 0x89, 0xd9, 0x6b, 0x05, 0x17, 0x13, 0x55, 0xe8, 0x59, 0x67, 0x4f, 0x98, + 0x02, 0xf4, 0x8d, 0x63, 0x54, 0x32, 0x86, 0x05, 0x03, 0x75, 0x9a, 0x12, 0xa2, 0x87, 0x62, 0x86, 0xf1, 0x8a, 0x01, + 0x14, 0xa6, 0x50, 0x20, 0x8a, 0xce, 0x3e, 0x1c, 0x68, 0x42, 0xbf, 0xff, 0x21, 0xd5, 0x19, 0x68, 0x59, 0x4f, 0x0b, + 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x88, 0x0a, 0x9d, 0xd2, 0x32, 0xa3, 0xa9, 0xa0, 0x6b, 0x41, 0x93, 0x8c, 0x5e, 0x70, + 0x25, 0x2a, 0x5e, 0x09, 0xa6, 0x68, 0xbb, 0x21, 0xec, 0xff, 0x68, 0xd0, 0xf5, 0x56, 0xac, 0x35, 0xb4, 0x3b, 0x41, + 0x46, 0x68, 0xbe, 0xd0, 0x41, 0xc8, 0x50, 0x39, 0x09, 0x5d, 0xab, 0x34, 0x5e, 0x81, 0x4b, 0xa6, 0xd9, 0x68, 0x19, + 0x97, 0x61, 0x60, 0xbf, 0x0a, 0x2c, 0x26, 0x07, 0x26, 0x7d, 0x58, 0x9f, 0x3f, 0x95, 0x57, 0x2b, 0x29, 0xb8, 0xa8, + 0x14, 0x44, 0xbf, 0xc1, 0x7d, 0x37, 0x71, 0xd5, 0x59, 0xb3, 0x56, 0x7a, 0xdf, 0xb7, 0x3e, 0x6b, 0xe3, 0xbe, 0x30, + 0x38, 0x06, 0x7b, 0x1f, 0x11, 0x03, 0x69, 0x50, 0xe9, 0x16, 0x87, 0x26, 0x40, 0x97, 0x0e, 0x29, 0x64, 0xc9, 0x54, + 0xa6, 0x4a, 0x50, 0xf1, 0x8d, 0xdf, 0x4b, 0x59, 0x8d, 0xfe, 0x5a, 0xf3, 0x62, 0xf3, 0x81, 0xe7, 0x1c, 0xc7, 0x28, + 0x48, 0x62, 0x71, 0x1d, 0x97, 0x01, 0xf1, 0x2d, 0xaf, 0x82, 0xa3, 0xd4, 0x84, 0x8d, 0xd9, 0xab, 0x1a, 0xb5, 0x5e, + 0x05, 0xfa, 0xca, 0x28, 0xdf, 0x18, 0x0c, 0x4d, 0x44, 0x15, 0xf4, 0xbd, 0x56, 0xf7, 0xb4, 0xba, 0x61, 0x01, 0xf1, + 0xe7, 0x4a, 0x2f, 0xd4, 0x7a, 0xdd, 0x8c, 0xb9, 0x61, 0x22, 0x04, 0x8d, 0x1e, 0xd5, 0x0b, 0x87, 0x9f, 0xbf, 0x55, + 0x96, 0x44, 0xf0, 0x62, 0x9b, 0xae, 0x0b, 0x13, 0x4b, 0x83, 0xea, 0x80, 0xb9, 0xd1, 0x36, 0xe7, 0x97, 0x20, 0xfa, + 0x73, 0x56, 0x44, 0x93, 0xba, 0xa6, 0x0a, 0xc1, 0x30, 0xda, 0xde, 0x36, 0xd2, 0xe9, 0x06, 0xbc, 0xdc, 0x8c, 0x35, + 0x92, 0xf6, 0x74, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x44, 0x77, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, 0x2a, + 0xce, 0xc4, 0x69, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x2a, 0xd4, 0xc6, 0x38, 0xd8, 0x7a, 0x35, 0xea, 0x2a, 0x1c, 0xf2, + 0xab, 0x8b, 0xe7, 0xb7, 0xab, 0x58, 0xa4, 0x30, 0xea, 0xf5, 0x5d, 0x2f, 0x9a, 0xd3, 0xb1, 0x8a, 0x0b, 0x2e, 0x4c, + 0xd4, 0x62, 0x5a, 0xb1, 0x80, 0xeb, 0x8c, 0x01, 0xe5, 0x2a, 0x76, 0x67, 0xa6, 0x62, 0x19, 0xc6, 0x65, 0xf9, 0x53, + 0x56, 0xe2, 0x1d, 0x00, 0x5a, 0x03, 0xa7, 0xc5, 0xcc, 0x80, 0x80, 0x6c, 0x72, 0x83, 0x8b, 0xc0, 0x82, 0xa3, 0xc7, + 0xe3, 0xd5, 0x6d, 0x40, 0xbd, 0x37, 0x52, 0x5d, 0x0f, 0x59, 0x30, 0x1e, 0x3d, 0x09, 0x1c, 0x72, 0x88, 0xff, 0xd1, + 0xe3, 0xa3, 0xbb, 0xbf, 0x99, 0x04, 0xa4, 0x9e, 0x82, 0xaa, 0xc2, 0x28, 0x44, 0x61, 0xda, 0x5f, 0xaf, 0xd5, 0x2d, + 0xf7, 0xed, 0x79, 0xc9, 0x8b, 0x6b, 0xd8, 0x97, 0x64, 0x9a, 0x01, 0x39, 0x97, 0x2a, 0x01, 0x16, 0x45, 0x5c, 0x55, + 0x45, 0x76, 0x0e, 0x26, 0x4a, 0x68, 0x00, 0x66, 0x9e, 0x5e, 0xa0, 0xc3, 0x47, 0x34, 0x0f, 0xb0, 0x4f, 0xc1, 0xa2, + 0x26, 0x75, 0x09, 0x85, 0x25, 0x07, 0x18, 0xac, 0x4e, 0xc5, 0x95, 0x76, 0x00, 0xdf, 0xd5, 0x1f, 0xd1, 0x52, 0x62, + 0xac, 0x59, 0x3d, 0x4f, 0xf1, 0x79, 0x29, 0xf3, 0x75, 0x05, 0xda, 0xf3, 0x8b, 0x2a, 0x3a, 0x7a, 0xbc, 0xba, 0x9d, + 0xaa, 0x6e, 0x44, 0xd0, 0x8b, 0xa9, 0xc2, 0x79, 0x4b, 0xe2, 0x3c, 0x09, 0x27, 0xe3, 0xf1, 0x37, 0x07, 0xc3, 0x03, + 0x48, 0x26, 0xd3, 0xcf, 0x43, 0xe5, 0xc8, 0x35, 0x9c, 0x8c, 0xc7, 0xf5, 0x1f, 0xb5, 0x09, 0xf3, 0x6d, 0xea, 0xf9, + 0xf0, 0xc7, 0xb1, 0x5a, 0xff, 0x27, 0xc7, 0x87, 0xfa, 0xc7, 0x1f, 0x75, 0x3d, 0x7d, 0x5a, 0x84, 0xf3, 0x7f, 0x87, + 0x6a, 0x7d, 0x9f, 0x16, 0x45, 0xbc, 0xa9, 0xc9, 0x82, 0xae, 0x84, 0xf3, 0xae, 0xa1, 0x1e, 0x59, 0xa0, 0x47, 0x64, + 0xba, 0x12, 0x0c, 0xbe, 0x79, 0x5f, 0x85, 0x01, 0x2f, 0x57, 0x43, 0x2e, 0xaa, 0xac, 0xda, 0x0c, 0x31, 0x4f, 0x80, + 0x9f, 0x5a, 0x3c, 0xb3, 0xc2, 0x10, 0xdf, 0x8b, 0x82, 0xf3, 0xcf, 0x3c, 0x54, 0xc6, 0xe2, 0x63, 0x34, 0x16, 0x1f, + 0x53, 0xd5, 0x8d, 0xc9, 0x77, 0x54, 0xf7, 0x6d, 0xf2, 0x1d, 0x98, 0x64, 0x65, 0xed, 0x6f, 0x94, 0xb1, 0x66, 0x34, + 0xa6, 0xd7, 0x2f, 0xf2, 0x6c, 0x05, 0x97, 0x82, 0xa5, 0xfe, 0x51, 0x13, 0xfa, 0x9e, 0xb7, 0xb3, 0x8f, 0x46, 0xa3, + 0x07, 0x05, 0x1d, 0x8d, 0x46, 0x9f, 0xb2, 0x9a, 0xd0, 0x4b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xdd, 0x44, + 0x41, 0x40, 0x97, 0x59, 0x9a, 0x72, 0xa1, 0xca, 0x7a, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0x10, 0x92, 0x6e, 0x23, + 0x42, 0x32, 0x11, 0xfa, 0x76, 0xaf, 0x67, 0xa3, 0xd1, 0xe8, 0x69, 0x6a, 0xaa, 0x75, 0x17, 0x94, 0x07, 0x68, 0x4e, + 0xe1, 0xfc, 0x14, 0xc0, 0x1a, 0xc9, 0x44, 0x7f, 0x39, 0xfc, 0xaf, 0xe1, 0x6c, 0x3e, 0x1e, 0x7e, 0x3f, 0x5a, 0x3c, + 0x3c, 0xa4, 0x41, 0xe0, 0x87, 0x6e, 0x08, 0xb5, 0x75, 0xcb, 0xb4, 0x3c, 0x1e, 0x4f, 0x49, 0x39, 0x60, 0x8f, 0xad, + 0x6f, 0xd1, 0x37, 0x8f, 0x01, 0x99, 0x15, 0x45, 0xca, 0x81, 0x93, 0x86, 0xe2, 0xd5, 0xec, 0x95, 0x00, 0xbc, 0x38, + 0x1b, 0xd9, 0xc1, 0x68, 0x45, 0xc7, 0x11, 0x94, 0x57, 0x5b, 0x53, 0x91, 0x1e, 0x63, 0x99, 0x89, 0x92, 0x3a, 0x9e, + 0x96, 0x37, 0x59, 0x95, 0x2c, 0x31, 0xd0, 0x53, 0x5c, 0xf2, 0xe0, 0x9b, 0x20, 0x2a, 0xd9, 0xd1, 0x93, 0xa9, 0x82, + 0x3b, 0xc6, 0xa4, 0x94, 0x5f, 0x42, 0xe2, 0xf7, 0x63, 0x84, 0x84, 0x25, 0xda, 0x83, 0x13, 0x6b, 0x7c, 0x91, 0xcb, + 0x18, 0x3c, 0x5a, 0x4b, 0xcd, 0xc3, 0xd9, 0x93, 0xd1, 0xda, 0xa3, 0xb4, 0x9a, 0x23, 0xa1, 0x39, 0xa1, 0x64, 0xf2, + 0xb0, 0xa4, 0xf2, 0x9b, 0x09, 0x7a, 0x49, 0x81, 0x9b, 0x79, 0x04, 0xc7, 0xbf, 0xb5, 0xf4, 0x50, 0xbd, 0x7a, 0x9b, + 0xb2, 0xc3, 0xf9, 0xff, 0x29, 0xe9, 0x62, 0x70, 0xe8, 0x86, 0xe6, 0x9d, 0x76, 0xe7, 0xad, 0x90, 0x71, 0xac, 0xc2, + 0xb7, 0x29, 0xb1, 0xc6, 0xb8, 0x9c, 0x9d, 0x6c, 0x4d, 0x77, 0x46, 0x55, 0x91, 0x5d, 0x85, 0x44, 0xf7, 0xca, 0x81, + 0x84, 0x06, 0x51, 0x36, 0xc2, 0xf5, 0x03, 0xd6, 0x33, 0x5e, 0x27, 0xaf, 0x79, 0x51, 0x65, 0x89, 0x7a, 0x7f, 0xdd, + 0x78, 0x5f, 0xd7, 0x26, 0xa0, 0xea, 0xbb, 0x82, 0xc1, 0x3c, 0xbf, 0x2d, 0x00, 0xc4, 0x14, 0x69, 0x80, 0x4f, 0x30, + 0x83, 0xa0, 0x76, 0xcd, 0xbc, 0x6a, 0x04, 0xdf, 0x80, 0xaf, 0xde, 0x15, 0x80, 0x41, 0x12, 0x82, 0x14, 0x19, 0x42, + 0x03, 0x81, 0x40, 0xc3, 0x90, 0x0b, 0x0c, 0x7e, 0xe2, 0xc5, 0x91, 0x54, 0x4e, 0x89, 0x3c, 0x0c, 0xf0, 0x47, 0x40, + 0x55, 0x00, 0x12, 0xe3, 0x71, 0x08, 0x2f, 0xd4, 0x2f, 0xf7, 0x46, 0xed, 0x11, 0xf6, 0x20, 0x0d, 0x21, 0xd8, 0x10, + 0x3e, 0x04, 0xb0, 0xa4, 0x08, 0x7d, 0x87, 0x5c, 0x46, 0x18, 0x5c, 0xe4, 0xd9, 0x4a, 0x27, 0x55, 0xa3, 0x8e, 0xe6, + 0x43, 0xa9, 0x1d, 0xc9, 0x01, 0xf5, 0xd2, 0x63, 0x4c, 0x2f, 0x54, 0xba, 0x2a, 0xca, 0x19, 0xe5, 0x9c, 0xea, 0x89, + 0x71, 0x61, 0x0b, 0x39, 0x44, 0xc2, 0x79, 0x57, 0xa8, 0x50, 0x38, 0x7c, 0x01, 0x60, 0x60, 0x20, 0xed, 0xd8, 0x8f, + 0x77, 0xa3, 0xb2, 0x9f, 0x71, 0x76, 0xf8, 0x5f, 0xf3, 0x78, 0xf8, 0x79, 0x3c, 0xfc, 0x7e, 0x31, 0x08, 0x87, 0xf6, + 0x27, 0x79, 0xf8, 0xe0, 0x90, 0xbe, 0xe0, 0x96, 0x4b, 0x83, 0x85, 0xdf, 0x08, 0xf6, 0xa3, 0x56, 0x42, 0x10, 0x05, + 0x78, 0xc3, 0x72, 0xab, 0x71, 0x02, 0x80, 0x87, 0xc1, 0xff, 0x0e, 0xd0, 0x68, 0xca, 0x5d, 0xbc, 0x40, 0x5f, 0xa2, + 0x7e, 0x9f, 0x3c, 0x6a, 0x18, 0x0c, 0x82, 0xb8, 0x46, 0xc5, 0x84, 0x21, 0xba, 0x8c, 0x89, 0x82, 0x41, 0xb6, 0xd9, + 0x77, 0xbb, 0x5e, 0x5b, 0x12, 0x86, 0x5f, 0xfa, 0x99, 0x26, 0x66, 0xde, 0xe1, 0xc6, 0xb6, 0x92, 0xab, 0x10, 0xb1, + 0x02, 0xf5, 0xaf, 0x9c, 0x41, 0xec, 0xcd, 0xeb, 0x0c, 0x7c, 0x3a, 0xec, 0x17, 0xe3, 0x19, 0xb0, 0x51, 0x70, 0xe7, + 0x2b, 0xf8, 0x45, 0x06, 0x6e, 0xde, 0x22, 0x46, 0x81, 0x83, 0x5d, 0x12, 0xfd, 0x7e, 0x2f, 0xcf, 0xc2, 0x5c, 0xe3, + 0x4e, 0xe7, 0xb5, 0x51, 0x43, 0xa0, 0x8e, 0x1c, 0xd4, 0x0f, 0x7a, 0x08, 0x86, 0x6a, 0x08, 0x8a, 0x8e, 0xb6, 0xb8, + 0x7a, 0x6d, 0x3d, 0x85, 0xe9, 0xad, 0xaa, 0xaf, 0x18, 0xfd, 0x29, 0x33, 0x81, 0x85, 0xb4, 0x6b, 0x8e, 0x75, 0xcd, + 0x31, 0xd2, 0x9e, 0x7e, 0x5f, 0x34, 0xc8, 0x4f, 0x67, 0xe1, 0x41, 0xa0, 0x4a, 0x95, 0x7b, 0x65, 0x51, 0x6e, 0x4b, + 0xf3, 0xc6, 0xb0, 0xa6, 0x79, 0x66, 0xe3, 0xdc, 0xcc, 0x7a, 0xbd, 0x30, 0x44, 0x07, 0x4f, 0x2c, 0x15, 0x6b, 0x83, + 0x70, 0x47, 0x26, 0x61, 0x74, 0x05, 0xb2, 0xcb, 0xf0, 0x8c, 0x13, 0xe4, 0x53, 0x81, 0x7d, 0x50, 0xd5, 0x7a, 0x39, + 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x79, 0x0b, 0xb9, 0x72, 0x5b, + 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xd2, 0xc2, 0x92, 0x0f, 0x42, 0x7b, 0x9a, 0x56, 0x60, + 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0xc7, 0x4f, 0x40, 0x67, 0xd4, 0xb6, 0x84, 0x30, 0x76, 0x83, 0xb0, 0xf2, 0x9e, + 0xc8, 0x37, 0x8f, 0xbd, 0x8b, 0x41, 0xc8, 0xcd, 0x66, 0x16, 0x0d, 0x4c, 0xf7, 0x73, 0xd9, 0x6c, 0x9e, 0x6e, 0xae, + 0x17, 0x25, 0x54, 0xc0, 0x76, 0xbb, 0x14, 0x04, 0xff, 0x7e, 0xca, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, 0x21, 0xfe, + 0xe2, 0x18, 0xcc, 0x68, 0x2e, 0x16, 0xec, 0x13, 0xc8, 0x98, 0x48, 0x84, 0xa9, 0xca, 0x18, 0x90, 0x55, 0x60, 0x11, + 0x68, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xcc, 0xb9, 0x86, 0xbc, 0x6a, 0x8d, 0x53, 0x36, 0xca, 0x12, 0xe5, 0xca, + 0x91, 0x8d, 0xe2, 0x3c, 0x8b, 0x4b, 0x5e, 0xee, 0x76, 0xfa, 0x70, 0x4c, 0x0a, 0x0e, 0xec, 0xba, 0xa2, 0x52, 0x25, + 0xeb, 0x48, 0xf5, 0xc0, 0x4b, 0xc3, 0x02, 0xf7, 0x29, 0x9f, 0x17, 0x86, 0x46, 0x1c, 0x80, 0x30, 0x83, 0xa9, 0x5b, + 0x7a, 0x2f, 0x2c, 0xa0, 0x79, 0x25, 0x21, 0x5b, 0x4c, 0xf5, 0x2c, 0x7c, 0x63, 0x26, 0xe6, 0xc5, 0x02, 0xc2, 0xea, + 0x14, 0x0b, 0xcd, 0x6c, 0xd2, 0x84, 0xc5, 0x00, 0x9b, 0x17, 0x93, 0x29, 0xc4, 0x77, 0x57, 0xe5, 0xc4, 0x0b, 0x73, + 0xdf, 0x4e, 0x1c, 0x72, 0x08, 0xbc, 0xaa, 0x0d, 0xba, 0x9a, 0x6d, 0x38, 0xea, 0x48, 0x39, 0x31, 0xf9, 0xfd, 0x54, + 0x41, 0x88, 0x3b, 0x71, 0x24, 0x5c, 0xde, 0x6c, 0x17, 0x9e, 0x75, 0x20, 0xe8, 0xa8, 0xc1, 0x29, 0xbf, 0x30, 0x38, + 0x1a, 0x93, 0x74, 0xeb, 0x9d, 0x20, 0x45, 0x18, 0x93, 0xad, 0x64, 0xe7, 0x32, 0x14, 0xf3, 0x78, 0x01, 0xca, 0xcb, + 0x78, 0x01, 0x96, 0x46, 0xc6, 0x20, 0x15, 0xe4, 0x77, 0xdc, 0x0b, 0x85, 0x45, 0x71, 0x85, 0x48, 0xcf, 0xea, 0xf7, + 0xb4, 0x68, 0x87, 0x02, 0x41, 0x71, 0x87, 0x32, 0x4f, 0xce, 0x7a, 0x2c, 0x90, 0xd8, 0x10, 0x30, 0xbe, 0xd2, 0x69, + 0xaa, 0xb5, 0xee, 0x8d, 0x99, 0x07, 0x3e, 0xcd, 0x46, 0x42, 0x56, 0x67, 0x17, 0x20, 0x52, 0xf2, 0xd1, 0xf1, 0x91, + 0x5f, 0xc4, 0x9d, 0x65, 0xde, 0xda, 0x16, 0x95, 0xec, 0x64, 0x0b, 0xa0, 0x85, 0x3a, 0x7a, 0x96, 0x92, 0xdb, 0x94, + 0xa4, 0x76, 0x9b, 0x02, 0x56, 0x92, 0xbf, 0x80, 0x21, 0xf8, 0xda, 0x81, 0x70, 0x3a, 0x56, 0x88, 0xd7, 0x34, 0x45, + 0xa4, 0xc9, 0xb0, 0xa4, 0x38, 0xb6, 0x25, 0xa2, 0xa0, 0xda, 0xb2, 0xec, 0x60, 0x98, 0x28, 0xc1, 0x1f, 0x53, 0x8f, + 0x12, 0x05, 0x01, 0xd5, 0x43, 0x0e, 0x12, 0x6c, 0xdb, 0x40, 0x78, 0x40, 0x1e, 0xd1, 0x1b, 0xeb, 0x9f, 0xb3, 0xce, + 0xb3, 0x0b, 0xcd, 0x73, 0xb9, 0xde, 0x15, 0x66, 0x8c, 0xf0, 0x24, 0x33, 0x61, 0x03, 0xbc, 0xf3, 0xcc, 0xa8, 0x6d, + 0x7a, 0x1e, 0x5e, 0xdb, 0x73, 0x8c, 0xd0, 0x77, 0xc7, 0xa0, 0x9b, 0x60, 0x5e, 0x1d, 0x36, 0xeb, 0x95, 0x82, 0xd4, + 0x30, 0xb5, 0x68, 0x62, 0xd6, 0xb3, 0x06, 0xe5, 0xbb, 0x5d, 0x4f, 0xcf, 0xd5, 0xdd, 0x73, 0xb7, 0xdb, 0xf5, 0xb0, + 0x5b, 0x1f, 0xd3, 0x6e, 0xab, 0xf8, 0x4a, 0x7d, 0xd0, 0x1e, 0x7f, 0xee, 0xc6, 0x9f, 0x1b, 0x64, 0x93, 0xd2, 0xd1, + 0x4c, 0x5b, 0x1f, 0x84, 0x07, 0x4e, 0x37, 0x8d, 0x26, 0xfd, 0x9c, 0x85, 0x92, 0x5e, 0x8a, 0x46, 0x75, 0xb5, 0x33, + 0x31, 0xbd, 0x77, 0xfd, 0xdf, 0xbf, 0x0a, 0xf0, 0x88, 0x53, 0x3b, 0xfb, 0xce, 0x06, 0x15, 0x8d, 0xb6, 0x70, 0xa4, + 0x08, 0x3d, 0x20, 0x09, 0x77, 0xb5, 0xac, 0xc5, 0x6d, 0x7e, 0xc8, 0xee, 0xa7, 0x4f, 0x3f, 0xa5, 0xbe, 0x17, 0x82, + 0x5b, 0x66, 0x99, 0x39, 0xf0, 0x2a, 0x8a, 0x03, 0x1a, 0x75, 0xd1, 0xbe, 0xab, 0xac, 0x2c, 0xc1, 0xeb, 0x05, 0xee, + 0x95, 0x1f, 0xb8, 0x0f, 0xbf, 0x77, 0x59, 0x35, 0x37, 0xe9, 0x87, 0x6c, 0x9e, 0x2d, 0x76, 0xbb, 0x10, 0xff, 0x76, + 0xb5, 0xc8, 0xd1, 0xe4, 0x39, 0xe8, 0x34, 0x31, 0x92, 0x11, 0xd3, 0x8d, 0xf3, 0x36, 0xff, 0x67, 0xd1, 0x70, 0x9a, + 0x78, 0x0e, 0xf4, 0x62, 0x76, 0x0a, 0x32, 0x29, 0x03, 0x72, 0x20, 0x66, 0x7a, 0xcd, 0x40, 0x34, 0x32, 0x11, 0x01, + 0xae, 0x30, 0x36, 0x12, 0x8d, 0x4e, 0x38, 0xa9, 0x09, 0x58, 0xb0, 0xda, 0xf2, 0xde, 0x5b, 0xda, 0x56, 0x15, 0x1b, + 0x6f, 0x49, 0x73, 0x5c, 0x07, 0xce, 0xd7, 0xc1, 0x06, 0xbc, 0xd3, 0x65, 0x57, 0x0b, 0xe4, 0x7e, 0x79, 0x4d, 0x7b, + 0xe3, 0x3a, 0x81, 0x59, 0xdb, 0xd6, 0x96, 0xf1, 0xb3, 0xa5, 0xbf, 0xd0, 0x83, 0xab, 0x8c, 0xc1, 0xe6, 0xc6, 0x4a, + 0xc3, 0xee, 0x1b, 0xcf, 0x97, 0x02, 0xc2, 0xd3, 0xf9, 0xf4, 0xf8, 0x43, 0xe6, 0xd1, 0x63, 0x20, 0x3a, 0xe6, 0xa3, + 0xd2, 0x7d, 0x64, 0x77, 0xaf, 0x1f, 0x10, 0x70, 0x5e, 0xb5, 0x0b, 0x9a, 0x97, 0x0b, 0x08, 0xac, 0xea, 0x95, 0x57, + 0x58, 0x3e, 0x33, 0x66, 0x97, 0x40, 0x86, 0x0a, 0x02, 0x81, 0xbb, 0xbb, 0xce, 0x85, 0x58, 0x75, 0x58, 0x99, 0xd3, + 0x24, 0xec, 0x24, 0x44, 0xf3, 0xd6, 0x60, 0x16, 0xfc, 0xef, 0x60, 0x50, 0x0e, 0x82, 0x28, 0x88, 0x82, 0x80, 0x0c, + 0x0a, 0xf8, 0x85, 0xb8, 0x6b, 0x04, 0x63, 0xb6, 0x40, 0x87, 0xdf, 0x72, 0xe6, 0x33, 0x22, 0xaf, 0xfc, 0xb0, 0x9e, + 0xde, 0x00, 0x9c, 0x4b, 0x99, 0xf3, 0x18, 0x7d, 0x4e, 0xde, 0x72, 0x96, 0x11, 0xfa, 0xd6, 0x3b, 0x95, 0xdf, 0xf1, + 0x46, 0xb0, 0xbf, 0xfd, 0x61, 0x7b, 0x01, 0xf2, 0x8a, 0xde, 0x98, 0xbe, 0xe5, 0x24, 0xca, 0x1a, 0xce, 0xd4, 0x1c, + 0x7a, 0x56, 0x59, 0xd6, 0x8a, 0x1a, 0x72, 0x83, 0x62, 0x6e, 0x64, 0x99, 0x9c, 0x4c, 0x5b, 0xcd, 0xa9, 0xc0, 0x75, + 0x67, 0xd7, 0x0b, 0x48, 0x0e, 0x85, 0x66, 0xe9, 0x6c, 0x38, 0x6f, 0x77, 0x28, 0xb6, 0x4e, 0x21, 0xaf, 0x21, 0x2a, + 0x1a, 0xa4, 0x23, 0xa0, 0x86, 0x56, 0x5c, 0x56, 0xe0, 0xc2, 0x6c, 0xda, 0xc3, 0x4d, 0x7b, 0x4c, 0x33, 0xde, 0x43, + 0xcc, 0x3c, 0x8e, 0x2d, 0x03, 0x3b, 0x12, 0x87, 0xf4, 0xe4, 0x7c, 0x81, 0xf6, 0xe9, 0xad, 0xab, 0xc5, 0x23, 0xac, + 0x3d, 0x6f, 0x85, 0x84, 0x00, 0xf1, 0x69, 0x2a, 0xdd, 0xed, 0x82, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, 0x6a, + 0xd8, 0x49, 0x73, 0x6b, 0xb6, 0xc4, 0x5e, 0x51, 0x78, 0x0c, 0xcc, 0xa9, 0xf9, 0xcf, 0x20, 0xa0, 0x78, 0xee, 0x86, + 0x60, 0x6f, 0xca, 0x4e, 0xb6, 0x45, 0xbf, 0xff, 0xac, 0xc0, 0x07, 0x94, 0x0b, 0x83, 0x98, 0x5b, 0xc7, 0xf1, 0x30, + 0xec, 0x93, 0xfa, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x47, 0x58, 0x2a, 0x43, 0x58, 0xb8, 0x62, 0xa4, 0x83, 0x38, 0xa8, + 0x49, 0xe7, 0x60, 0x55, 0x2e, 0xf8, 0x72, 0xaf, 0xf7, 0x19, 0x60, 0xd2, 0x33, 0x6f, 0x58, 0xde, 0x78, 0x80, 0x68, + 0xbd, 0x1e, 0x2e, 0x14, 0x8f, 0x4c, 0x34, 0xd0, 0x38, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, 0x56, 0x32, 0x1a, 0x8d, + 0xaa, 0x5a, 0x49, 0x3e, 0xec, 0x77, 0x7f, 0xb6, 0x50, 0x3c, 0x65, 0x9c, 0xf2, 0x14, 0x2c, 0xdf, 0x0d, 0xa5, 0x9b, + 0x2f, 0xe8, 0x8a, 0x8b, 0x54, 0xfd, 0xf4, 0xd0, 0x37, 0x1b, 0xc4, 0x35, 0x6b, 0xea, 0x70, 0xec, 0xf0, 0x43, 0x00, + 0x4c, 0xfb, 0x30, 0x73, 0xe9, 0x1a, 0xa6, 0x17, 0xc4, 0xb3, 0x71, 0xc1, 0x43, 0x97, 0x07, 0xb0, 0x0f, 0xcd, 0x21, + 0x89, 0x9f, 0xc2, 0xcf, 0x99, 0x49, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xd5, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, + 0x41, 0x7a, 0x6e, 0x30, 0x14, 0xad, 0xbb, 0x0d, 0x5c, 0xf9, 0x2d, 0xbd, 0xf3, 0x69, 0x10, 0x60, 0x7d, 0x63, 0x31, + 0x00, 0xa0, 0x8a, 0x3f, 0x50, 0x75, 0x65, 0xae, 0x28, 0xa6, 0x61, 0x2a, 0xd1, 0xde, 0x71, 0x5c, 0x47, 0x8d, 0xeb, + 0xb0, 0x60, 0xa5, 0xb5, 0x6d, 0x76, 0x6f, 0x69, 0x61, 0x4b, 0x40, 0xb5, 0x20, 0xee, 0x04, 0xf0, 0xa1, 0x91, 0xea, + 0x40, 0x90, 0xdd, 0x07, 0x07, 0x00, 0xbc, 0xe1, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x55, 0x3f, 0x97, + 0xd3, 0x18, 0xce, 0xdd, 0x5c, 0xed, 0xf0, 0xd9, 0x12, 0x14, 0x9b, 0x6a, 0x4e, 0xcd, 0xe5, 0x2b, 0x6f, 0xec, 0xf7, + 0x98, 0x60, 0x1e, 0x33, 0xdb, 0xf0, 0x5b, 0x4f, 0xb7, 0xf5, 0x0d, 0x76, 0x03, 0x27, 0xed, 0x85, 0xd3, 0x5e, 0x6c, + 0x97, 0x06, 0xf2, 0xaf, 0x6e, 0x08, 0x11, 0x3e, 0x6a, 0x62, 0x91, 0x35, 0x64, 0x3a, 0x16, 0x2b, 0x44, 0xb5, 0xa9, + 0x78, 0xaa, 0x0d, 0x04, 0xca, 0xa9, 0xba, 0x30, 0xb5, 0x52, 0x99, 0x30, 0x88, 0x3b, 0x25, 0x2c, 0xaa, 0x0c, 0x30, + 0x0c, 0x2a, 0xa4, 0xb8, 0xb6, 0x9e, 0x1f, 0x70, 0xf9, 0x66, 0xa6, 0xcd, 0xf6, 0xd3, 0x17, 0x79, 0x7c, 0xb9, 0xdb, + 0x85, 0xdd, 0x2f, 0xc0, 0x1c, 0xb5, 0x54, 0x1a, 0x46, 0x70, 0x02, 0x51, 0x92, 0xeb, 0x3b, 0x72, 0x4e, 0x1c, 0x27, + 0xd7, 0x6e, 0xde, 0x6c, 0x2f, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0x49, 0x6a, 0x4f, 0x01, 0x6f, + 0xd3, 0x3b, 0x4a, 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, 0x83, 0x80, + 0xd3, 0x9e, 0x6e, 0xac, 0x55, 0x24, 0x9b, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0xb5, 0xbb, 0x6d, 0x55, 0xb6, + 0x50, 0x30, 0x0f, 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x17, 0xa4, 0xd0, 0x2b, 0x47, 0xab, + 0x9a, 0xf7, 0x25, 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xfb, 0x5a, 0xd6, 0x58, 0x5c, 0x39, 0x21, 0x85, 0x4d, + 0xf8, 0xda, 0x52, 0x2c, 0xcc, 0x62, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x8c, 0x36, 0x58, 0x37, + 0xbb, 0xdd, 0xc7, 0x22, 0x9c, 0x67, 0x0b, 0x2a, 0x47, 0x59, 0x8a, 0x90, 0x6a, 0xc6, 0x63, 0xd9, 0x76, 0xc1, 0x4c, + 0x0c, 0x75, 0xed, 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, 0x1e, 0xee, + 0xbf, 0xa6, 0x10, 0xd3, 0xce, 0xac, 0xbb, 0x97, 0x7b, 0x37, 0xc4, 0x5f, 0x21, 0xb0, 0x42, 0xc9, 0x3e, 0x16, 0xa3, + 0xf3, 0x0c, 0x82, 0xc1, 0x82, 0xac, 0x19, 0xa3, 0x04, 0xab, 0x75, 0xd0, 0x6c, 0xb9, 0xbd, 0x17, 0x5b, 0xa2, 0x00, + 0x71, 0x9e, 0x85, 0x66, 0x3c, 0x2b, 0x67, 0x39, 0x93, 0x51, 0x6c, 0x48, 0x54, 0x7a, 0x51, 0xe2, 0x7d, 0x9e, 0xc6, + 0xf4, 0xd0, 0xad, 0x41, 0x70, 0x5d, 0xdd, 0xdb, 0x48, 0xf3, 0x05, 0x21, 0x6a, 0x02, 0x24, 0x6c, 0x54, 0x73, 0x6a, + 0x5d, 0x89, 0xfb, 0x59, 0xe5, 0x8d, 0x3e, 0x88, 0xaf, 0x04, 0xf0, 0xb0, 0xde, 0xf6, 0x3e, 0x17, 0x1e, 0x6b, 0x83, + 0x6f, 0x77, 0xbb, 0x2b, 0x31, 0x0f, 0x02, 0x8f, 0xd1, 0xfc, 0x45, 0x49, 0xcc, 0x7b, 0x63, 0x0a, 0x2b, 0xde, 0x77, + 0xf1, 0xeb, 0x26, 0xb5, 0xd6, 0x22, 0x77, 0x8f, 0xeb, 0x03, 0x9e, 0xa7, 0xc4, 0xd1, 0x8e, 0xca, 0xa9, 0xb4, 0xb6, + 0x03, 0xd8, 0x15, 0x81, 0x81, 0xb2, 0x7f, 0x4b, 0xd9, 0x16, 0xcc, 0x13, 0xc1, 0xfa, 0x08, 0xfd, 0xb6, 0x94, 0xfe, + 0x64, 0x8c, 0xc6, 0x3d, 0x72, 0x5d, 0x45, 0x47, 0x5c, 0x47, 0xb3, 0xe7, 0xd1, 0xdf, 0x9e, 0x8c, 0x69, 0x11, 0x8b, + 0x54, 0x5e, 0x81, 0x0a, 0x02, 0x94, 0x21, 0xe8, 0x08, 0xa1, 0xa9, 0x01, 0x68, 0x10, 0xdc, 0x00, 0xfc, 0xbb, 0xd3, + 0x89, 0xd2, 0xd6, 0xe4, 0x63, 0xb4, 0xaa, 0x22, 0x67, 0x6d, 0x68, 0x37, 0x95, 0x1c, 0x92, 0x87, 0x25, 0xe0, 0x5b, + 0x62, 0xb3, 0x94, 0x0d, 0x8a, 0xda, 0x6c, 0xea, 0xb5, 0x62, 0x47, 0x6e, 0x1b, 0x45, 0x9b, 0xb5, 0xa8, 0xed, 0x46, + 0xe6, 0x8b, 0xe9, 0xad, 0x15, 0x06, 0x4e, 0x4d, 0x6b, 0x6e, 0xf6, 0xa0, 0xe4, 0x6c, 0x7d, 0x26, 0x37, 0x01, 0xe2, + 0x00, 0xc3, 0x75, 0x3b, 0xbf, 0x59, 0x10, 0x7a, 0xcb, 0x6e, 0xad, 0x58, 0xf5, 0xc6, 0xca, 0x45, 0x4c, 0xda, 0xcd, + 0x60, 0x02, 0x97, 0x71, 0x56, 0xd8, 0x17, 0x5a, 0xdd, 0x50, 0x74, 0xb4, 0x4d, 0xda, 0xcf, 0x3b, 0xda, 0x0d, 0x17, + 0x7c, 0x2b, 0xd6, 0x71, 0x6e, 0x59, 0x53, 0x85, 0xa6, 0x1d, 0xe8, 0xed, 0x10, 0xd0, 0x9c, 0x8d, 0xe9, 0x92, 0xa6, + 0x78, 0x81, 0xa6, 0x6b, 0x30, 0xd3, 0xb9, 0x80, 0xbe, 0x76, 0xfb, 0x68, 0x5f, 0xa8, 0x9e, 0x08, 0x6f, 0x89, 0x82, + 0x6f, 0x4b, 0x0a, 0x5e, 0x6a, 0x39, 0x8f, 0xcd, 0x1c, 0x02, 0x3e, 0x8d, 0x2a, 0xd1, 0x3b, 0x29, 0x2e, 0x41, 0x9b, + 0x09, 0x47, 0xa0, 0xa9, 0x1a, 0xb1, 0x95, 0x03, 0xdc, 0x5e, 0x3c, 0x0d, 0x08, 0x05, 0xa9, 0xee, 0xda, 0xae, 0xc8, + 0x5b, 0x76, 0xb2, 0xbd, 0x05, 0x33, 0xe1, 0x6a, 0x5d, 0xb6, 0xbe, 0xb2, 0xc9, 0xee, 0xe3, 0x9a, 0x60, 0xdb, 0x3d, + 0xd4, 0xd8, 0xf0, 0x96, 0xde, 0x90, 0xed, 0x4d, 0xbf, 0x1f, 0x42, 0x7f, 0x08, 0xd5, 0x1d, 0xba, 0xed, 0xec, 0xd0, + 0xad, 0xd7, 0xce, 0x73, 0xab, 0xe7, 0x53, 0xde, 0x21, 0x1f, 0xd1, 0x64, 0x8d, 0xae, 0xe2, 0x0d, 0x6c, 0xea, 0xa8, + 0xa2, 0xaa, 0xf2, 0x28, 0xa1, 0xa0, 0x12, 0xcf, 0x78, 0xf9, 0x81, 0x63, 0xac, 0x57, 0xfd, 0xf4, 0x4e, 0xf3, 0x6a, + 0x6b, 0xb3, 0x36, 0xcb, 0xf5, 0x39, 0x58, 0x48, 0x9c, 0xf3, 0xe8, 0x4a, 0xd3, 0x92, 0x4b, 0x1f, 0x54, 0x15, 0x47, + 0x25, 0xb8, 0x88, 0xb3, 0x1c, 0xd4, 0xb8, 0x17, 0xcd, 0xfe, 0x87, 0xda, 0x76, 0x6c, 0xd9, 0x38, 0x73, 0xaf, 0x43, + 0xb2, 0xfd, 0x1f, 0x1b, 0xa8, 0xa7, 0x21, 0x46, 0x88, 0x35, 0x0b, 0xfa, 0x01, 0x83, 0x58, 0xa1, 0x41, 0xb9, 0x4e, + 0x12, 0x5e, 0x96, 0x81, 0x51, 0x6a, 0xad, 0xd9, 0xda, 0x9c, 0x67, 0xef, 0xd8, 0xc9, 0xbb, 0x1e, 0x63, 0xb7, 0x84, + 0x26, 0x5a, 0x27, 0x64, 0x6a, 0x8c, 0x3c, 0x2d, 0x90, 0xee, 0x50, 0x94, 0x5d, 0x84, 0x0f, 0x50, 0xc8, 0xd2, 0xde, + 0xe7, 0xe6, 0x44, 0x56, 0xdf, 0x68, 0x23, 0x94, 0x48, 0x25, 0x82, 0x6c, 0xfc, 0x06, 0x01, 0x8c, 0xa1, 0xd9, 0x01, + 0xd9, 0x2e, 0xd9, 0x6b, 0x7a, 0x66, 0x4d, 0x82, 0xe0, 0xf5, 0x03, 0x95, 0x68, 0x46, 0x59, 0x11, 0x5d, 0x65, 0xf4, + 0xb3, 0x09, 0x49, 0x74, 0x16, 0x12, 0x3f, 0x37, 0x2c, 0xad, 0xeb, 0x10, 0xc5, 0xcc, 0x66, 0xc3, 0x6b, 0x45, 0x54, + 0x63, 0x5b, 0x19, 0x1f, 0xf3, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, 0x9a, 0x7e, 0xe0, + 0x2d, 0x05, 0x7f, 0xb1, 0x77, 0xa4, 0x4e, 0x58, 0x00, 0xf0, 0x8c, 0x39, 0xaf, 0x9a, 0x13, 0xf8, 0x8e, 0x9d, 0x6c, + 0xdf, 0x85, 0xaf, 0x1b, 0x33, 0xb7, 0x09, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, 0xb2, 0x5a, 0xf3, + 0x5b, 0x66, 0xf5, 0x09, 0x40, 0xa4, 0x6e, 0xad, 0x83, 0x2d, 0x7e, 0x6c, 0xba, 0x4c, 0xb6, 0x29, 0x6b, 0x33, 0x51, + 0x4a, 0x45, 0xd2, 0x5c, 0x04, 0xd0, 0x6f, 0x18, 0x8e, 0x1a, 0xe0, 0xce, 0xf5, 0xd8, 0x9b, 0xa1, 0xf1, 0xc6, 0xd4, + 0xd0, 0xb3, 0xad, 0x5e, 0xde, 0x8e, 0x42, 0x98, 0xb1, 0x88, 0x6e, 0xdd, 0xb1, 0x18, 0xbe, 0xa6, 0x0f, 0xa0, 0xc2, + 0xa7, 0x21, 0x46, 0x17, 0x26, 0x75, 0x3d, 0x5d, 0xab, 0xad, 0x74, 0x43, 0x68, 0x8e, 0x51, 0x8d, 0xbc, 0xb6, 0x6d, + 0xa8, 0x11, 0xda, 0x13, 0xca, 0xc3, 0x5b, 0x5a, 0xd1, 0x1b, 0xcb, 0x22, 0x38, 0xf9, 0xb1, 0x97, 0x9f, 0xd0, 0x73, + 0x37, 0x68, 0x3f, 0x15, 0x6d, 0x0d, 0xe0, 0x6f, 0xa8, 0x1f, 0xce, 0xea, 0xa9, 0x95, 0x72, 0x78, 0x0a, 0x5f, 0xb2, + 0x05, 0xb9, 0x82, 0x5e, 0xac, 0x31, 0x3b, 0x89, 0x41, 0x07, 0xb5, 0xb7, 0x3b, 0xbc, 0x49, 0x29, 0x43, 0xb4, 0x46, + 0x74, 0x90, 0x57, 0xff, 0x06, 0x4d, 0x1f, 0xa4, 0x85, 0x29, 0x5d, 0xa3, 0x80, 0x07, 0xf4, 0x4d, 0xfd, 0x7e, 0x8e, + 0xcf, 0xb5, 0x67, 0x99, 0xa6, 0x2c, 0x90, 0x09, 0x5d, 0xba, 0xd2, 0x40, 0x54, 0xbe, 0x75, 0xac, 0x02, 0xb0, 0x22, + 0x09, 0x34, 0x22, 0x01, 0xcb, 0x25, 0x4f, 0x5c, 0xb6, 0x45, 0x83, 0x9a, 0xa8, 0xa4, 0x90, 0x25, 0x92, 0xc0, 0x0f, + 0x23, 0x28, 0x53, 0x14, 0x83, 0xb8, 0x57, 0x2f, 0xaf, 0xb8, 0xa6, 0x06, 0xac, 0x29, 0x82, 0x09, 0xd6, 0xe9, 0x14, + 0x88, 0xad, 0x58, 0xaf, 0xc0, 0x13, 0xd5, 0x5d, 0x24, 0x91, 0x25, 0x40, 0x03, 0x3d, 0x5f, 0x3a, 0xed, 0x96, 0xb7, + 0x27, 0x5a, 0xaa, 0xd8, 0xdc, 0x7b, 0xb1, 0xb0, 0xdc, 0x63, 0xe5, 0x6f, 0x07, 0xda, 0x0b, 0xab, 0x3d, 0x11, 0x35, + 0x58, 0x1d, 0xb6, 0xed, 0xfc, 0x50, 0x1a, 0xaa, 0x7b, 0xe5, 0x98, 0x80, 0x8a, 0xae, 0xe2, 0x6a, 0x19, 0x65, 0x23, + 0xf8, 0xb3, 0xdb, 0x05, 0x87, 0x01, 0x58, 0x84, 0xfe, 0xf2, 0xfe, 0xa7, 0x08, 0xc3, 0x55, 0xfd, 0xf2, 0xfe, 0xa7, + 0xdd, 0xee, 0xc9, 0x78, 0x6c, 0xb8, 0x02, 0xa7, 0xd6, 0x01, 0xfe, 0xc0, 0xb0, 0x0d, 0x76, 0xc9, 0xee, 0x76, 0x4f, + 0x80, 0x83, 0x50, 0x6c, 0x83, 0xd9, 0xc5, 0xca, 0xb1, 0x4d, 0xb1, 0x1a, 0x7a, 0x47, 0x02, 0x76, 0xdf, 0x1e, 0x4b, + 0xb1, 0x4f, 0x7d, 0x54, 0x48, 0x4a, 0xbd, 0xe8, 0x9f, 0x77, 0x0a, 0x2c, 0x29, 0x98, 0xf2, 0x06, 0xcb, 0xaa, 0x5a, + 0x95, 0xd1, 0xe1, 0x61, 0xbc, 0xca, 0x46, 0x65, 0x06, 0xdb, 0xbc, 0xbc, 0xbe, 0x04, 0x80, 0x89, 0x80, 0x36, 0xde, + 0xad, 0x45, 0x66, 0x5e, 0x2c, 0xe8, 0x32, 0xc3, 0x35, 0x09, 0x66, 0x07, 0x39, 0xb7, 0xba, 0xc9, 0x29, 0xb1, 0x0f, + 0x60, 0x83, 0xb9, 0xdb, 0x35, 0xf8, 0x85, 0x93, 0xd1, 0x93, 0xd9, 0x32, 0xd3, 0x06, 0xae, 0xdc, 0xec, 0x7f, 0x12, + 0x79, 0x69, 0xa8, 0xf8, 0x24, 0xd3, 0xe7, 0x19, 0xf0, 0x79, 0xec, 0x4f, 0x11, 0xfa, 0x2c, 0x57, 0xa3, 0x35, 0xc0, + 0xc6, 0x66, 0x17, 0x9b, 0x51, 0xca, 0x21, 0x42, 0x47, 0x60, 0xd5, 0x35, 0xcb, 0x8c, 0xf8, 0x36, 0x15, 0xb7, 0x2d, + 0x55, 0xd8, 0x9f, 0xc2, 0x73, 0xde, 0xe1, 0xc6, 0x71, 0xa8, 0x37, 0x89, 0xc2, 0xe7, 0x28, 0x44, 0xe5, 0x68, 0x5c, + 0xe8, 0xe4, 0x6b, 0x99, 0xc7, 0x84, 0x62, 0x0e, 0xf7, 0xee, 0xaf, 0xd4, 0x99, 0xcb, 0xf8, 0xc2, 0xbd, 0xe7, 0xbe, + 0xcc, 0xe4, 0x5a, 0x02, 0x48, 0x94, 0xaa, 0xfd, 0xf7, 0x2f, 0x48, 0x8d, 0xff, 0x95, 0x6a, 0x0d, 0x40, 0xef, 0x77, + 0xa8, 0xc9, 0x11, 0x04, 0x6c, 0xc5, 0xd4, 0x8f, 0x2e, 0x60, 0x25, 0xf3, 0x3f, 0xa1, 0x6e, 0x47, 0xb0, 0xad, 0x8a, + 0x27, 0x14, 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0x36, 0x11, 0xaf, 0xa7, 0x58, 0x12, 0xb3, 0x11, 0xc3, + 0x7e, 0x6f, 0x76, 0xe1, 0x7d, 0xd1, 0x30, 0x89, 0xa7, 0xa5, 0xbf, 0xad, 0xbc, 0xcd, 0x64, 0x19, 0x67, 0x64, 0xca, + 0x15, 0x82, 0xb9, 0xd5, 0xf7, 0x98, 0x13, 0xfc, 0xf1, 0xd1, 0x63, 0x42, 0xaf, 0xe5, 0xb4, 0x44, 0x90, 0x3e, 0x91, + 0x5a, 0xd7, 0x55, 0xec, 0xd7, 0x14, 0xa2, 0x5a, 0x08, 0x06, 0xa1, 0x4c, 0x4d, 0xfb, 0x14, 0xdf, 0x67, 0xcb, 0xfe, + 0xd3, 0x94, 0x2d, 0xc9, 0x56, 0x40, 0xc7, 0xa4, 0xf3, 0x7e, 0xf5, 0xf6, 0xec, 0xcc, 0xfb, 0x0d, 0x9a, 0x70, 0x50, + 0xdd, 0x40, 0xbb, 0x0a, 0x32, 0x8d, 0x51, 0x6c, 0x16, 0x63, 0xed, 0xd6, 0x44, 0x04, 0x41, 0xb8, 0xcb, 0x59, 0xd8, + 0x6e, 0x27, 0xc4, 0xdb, 0x40, 0x02, 0x05, 0xae, 0x6d, 0x94, 0x93, 0x90, 0xa8, 0x0b, 0x99, 0x39, 0x26, 0x24, 0x0b, + 0xf4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0xb7, 0x4f, 0x01, 0x7d, 0x51, 0xb0, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x6f, 0x36, + 0xa0, 0x9f, 0xa4, 0x7a, 0x04, 0x8f, 0x69, 0x60, 0xb9, 0xe8, 0x9b, 0x82, 0x21, 0xcc, 0xd2, 0x3f, 0x53, 0x36, 0xf9, + 0xee, 0xef, 0x6e, 0x7e, 0xcf, 0xb4, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, 0x57, 0x60, 0x6d, + 0xae, 0x25, 0xde, 0x9e, 0xe4, 0x41, 0xf8, 0x72, 0x74, 0xfb, 0x49, 0x69, 0x3e, 0x81, 0xa0, 0x3d, 0x4e, 0x52, 0xee, + 0xbe, 0xfb, 0x20, 0x5d, 0x45, 0x30, 0x5a, 0x80, 0xe0, 0x77, 0x67, 0x25, 0x9b, 0xa6, 0xf0, 0x1f, 0xeb, 0x7c, 0x81, + 0xb1, 0x54, 0xe4, 0x07, 0x9c, 0xfe, 0x26, 0x38, 0xb8, 0x7f, 0x2b, 0xb3, 0x86, 0x44, 0x67, 0xea, 0x23, 0xa0, 0xff, + 0x63, 0x3d, 0x7e, 0xa7, 0x28, 0xe9, 0x4b, 0xe2, 0x1c, 0xe1, 0x9b, 0x78, 0x89, 0xa6, 0x8b, 0xbd, 0x71, 0x4d, 0x3f, + 0x17, 0xe6, 0x85, 0x56, 0x70, 0xd8, 0xb7, 0x46, 0xe1, 0x81, 0x67, 0xde, 0xaf, 0xa2, 0x21, 0xe8, 0xfe, 0x11, 0xf7, + 0xc6, 0xaf, 0x82, 0x65, 0x78, 0x53, 0xce, 0x32, 0x73, 0x87, 0xbb, 0xc9, 0x44, 0x2a, 0x6f, 0x18, 0x0b, 0xd6, 0x42, + 0x99, 0xf3, 0xa6, 0xc1, 0x6c, 0x5b, 0x47, 0x2a, 0xd9, 0x7d, 0xff, 0x67, 0xe3, 0x84, 0xcd, 0x06, 0xc1, 0x87, 0x4a, + 0x16, 0xf1, 0x25, 0x0f, 0xa6, 0x5a, 0x45, 0x91, 0x81, 0x5d, 0x21, 0x20, 0xe5, 0x38, 0xed, 0x1d, 0x3c, 0x59, 0x6a, + 0x66, 0x42, 0x7e, 0x5b, 0x9d, 0x05, 0xbc, 0x35, 0xa3, 0x79, 0x5a, 0xc1, 0x2e, 0xf3, 0x95, 0x14, 0x3f, 0xb4, 0x24, + 0xd9, 0x58, 0x7f, 0x43, 0x86, 0x6d, 0xe5, 0x33, 0x67, 0x80, 0xb9, 0xf3, 0x49, 0xaa, 0xa0, 0x7f, 0x3d, 0xc6, 0x6e, + 0x24, 0x12, 0x01, 0xe1, 0x2c, 0x26, 0x6e, 0x85, 0x09, 0x87, 0xe9, 0x02, 0x05, 0xc5, 0x18, 0x28, 0xe8, 0x83, 0x0c, + 0x39, 0x3d, 0xe5, 0x83, 0xa4, 0x31, 0x5b, 0x3f, 0xa8, 0x12, 0xe9, 0x8d, 0x24, 0x74, 0x03, 0xbf, 0xc7, 0x2d, 0x1e, + 0xa8, 0x11, 0xac, 0xd3, 0xdd, 0x9c, 0x0e, 0xdf, 0x14, 0x64, 0xf8, 0x4f, 0xf0, 0x76, 0x8b, 0xed, 0x65, 0x39, 0x81, + 0xc5, 0x1d, 0x7b, 0xc5, 0xd3, 0x5c, 0xb5, 0x38, 0x21, 0x1e, 0xb1, 0xc8, 0x7d, 0x62, 0x01, 0x23, 0x6a, 0x18, 0x8d, + 0x7f, 0x7c, 0x78, 0xfb, 0x46, 0x63, 0x58, 0xe5, 0xfe, 0x07, 0x30, 0xa2, 0x5a, 0xda, 0x6e, 0x07, 0x7c, 0x39, 0x42, + 0x03, 0xf6, 0xd4, 0x0d, 0x76, 0xbf, 0x6f, 0xd2, 0x4e, 0x4a, 0x2f, 0x9b, 0x13, 0x83, 0xee, 0x29, 0x6d, 0x96, 0xca, + 0xc0, 0xb8, 0xab, 0x70, 0x34, 0x27, 0x36, 0x62, 0x55, 0xef, 0xc3, 0x70, 0x49, 0x63, 0x2b, 0x2b, 0xb7, 0xbb, 0x09, + 0x47, 0x36, 0x01, 0xae, 0x4f, 0x41, 0x7b, 0x35, 0xe7, 0xa0, 0x05, 0x25, 0x0a, 0x1c, 0xd1, 0x6e, 0x17, 0x42, 0x44, + 0x92, 0x62, 0x38, 0x99, 0x85, 0xc5, 0x70, 0xa8, 0x06, 0xbe, 0x20, 0x24, 0xfa, 0x5c, 0xcc, 0xb3, 0x85, 0x42, 0x30, + 0xf2, 0x77, 0xd2, 0xaf, 0x85, 0xe2, 0x94, 0x7b, 0xbf, 0x0a, 0xb2, 0xfd, 0x31, 0xc5, 0x18, 0x8c, 0x4e, 0xb3, 0x99, + 0x81, 0x84, 0xf5, 0xb4, 0x22, 0x6a, 0x1d, 0xd9, 0xd9, 0x00, 0x55, 0x2c, 0x9a, 0x06, 0x83, 0xba, 0xc5, 0x13, 0xeb, + 0x19, 0xbd, 0x07, 0x95, 0x20, 0xaa, 0x05, 0xbb, 0x31, 0x5c, 0x6b, 0x9f, 0x45, 0x28, 0x29, 0x27, 0x4d, 0x66, 0xc6, + 0x8a, 0x06, 0x0b, 0x10, 0x92, 0xc6, 0x65, 0xf5, 0x5a, 0xa6, 0xd9, 0x45, 0x06, 0x08, 0x12, 0xce, 0x9f, 0x50, 0x36, + 0xde, 0x3c, 0x55, 0xf3, 0xd2, 0x95, 0x38, 0xb3, 0xb0, 0x27, 0x5d, 0x6f, 0x69, 0x41, 0xa2, 0x02, 0x68, 0x94, 0xaf, + 0xe5, 0xf9, 0x79, 0xcf, 0x2a, 0x64, 0xff, 0xc3, 0xa9, 0xb2, 0x1d, 0xe2, 0x27, 0xac, 0x22, 0xde, 0x69, 0x5d, 0x29, + 0x91, 0x46, 0x47, 0xdb, 0x80, 0x18, 0xb6, 0xec, 0x5b, 0xd4, 0xf0, 0x41, 0xd8, 0x45, 0x27, 0xf9, 0x41, 0x4f, 0xf1, + 0xd8, 0x1a, 0x48, 0xfa, 0x5a, 0x04, 0x5f, 0xa3, 0x23, 0x9d, 0x28, 0xd3, 0x48, 0x4c, 0x21, 0xd1, 0xaf, 0x17, 0x5a, + 0x63, 0x19, 0x65, 0x5f, 0x91, 0xff, 0xbb, 0xee, 0xde, 0xaf, 0x62, 0xb7, 0x83, 0x49, 0xf6, 0x3c, 0xd0, 0x60, 0x53, + 0xa3, 0x56, 0x08, 0x67, 0xe7, 0xb4, 0x42, 0xed, 0x58, 0x2f, 0x2c, 0x81, 0x3c, 0x80, 0xad, 0x48, 0x83, 0x32, 0x48, + 0xf6, 0xb9, 0x98, 0x8b, 0x85, 0x13, 0xe5, 0x48, 0x85, 0x7f, 0x26, 0x47, 0x29, 0x87, 0xab, 0x58, 0x58, 0x30, 0xe4, + 0x57, 0x47, 0x17, 0x85, 0xbc, 0x02, 0x49, 0x89, 0x61, 0xa8, 0x2c, 0xaf, 0x8b, 0xab, 0xb6, 0x24, 0xb4, 0xb7, 0x01, + 0x50, 0x9a, 0x02, 0x04, 0x2f, 0x8d, 0x1a, 0x62, 0xb6, 0x55, 0xbb, 0x2b, 0xba, 0x93, 0x1c, 0x50, 0xa7, 0xbb, 0x76, + 0xeb, 0x4d, 0xd9, 0xaa, 0x5b, 0x71, 0xe1, 0x0f, 0x50, 0xfa, 0x29, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, + 0x59, 0x76, 0xb1, 0xc1, 0xa5, 0x5f, 0x35, 0xc6, 0xaf, 0xdf, 0xef, 0xa9, 0x85, 0xd0, 0x48, 0x05, 0xe6, 0xdb, 0x67, + 0xa6, 0x2a, 0xa3, 0x29, 0xb5, 0x97, 0xe0, 0xca, 0xd9, 0x8f, 0xa0, 0x22, 0xae, 0x2b, 0x52, 0x9b, 0x1a, 0xa0, 0x03, + 0x2f, 0x2b, 0xdc, 0xca, 0x02, 0x3c, 0x76, 0x02, 0xb2, 0xdb, 0xf1, 0x30, 0xd0, 0x87, 0x4e, 0xe0, 0x6f, 0xc9, 0xd7, + 0xc8, 0xac, 0xd9, 0xc7, 0x7f, 0x68, 0xc1, 0x3f, 0xb6, 0xe0, 0x27, 0x14, 0x77, 0x5a, 0x99, 0x7f, 0x2b, 0xad, 0x5b, + 0xdc, 0xbf, 0x97, 0x69, 0x42, 0x51, 0x99, 0x50, 0xfb, 0x95, 0x56, 0x6b, 0xa3, 0xc6, 0xc0, 0xec, 0x1f, 0x25, 0x7c, + 0x30, 0x6b, 0x3c, 0xb1, 0xc6, 0x93, 0xe1, 0x74, 0x2b, 0x0d, 0xcb, 0x80, 0x42, 0x3f, 0x2f, 0x73, 0x45, 0xf5, 0xf3, + 0xcf, 0x6b, 0xbe, 0xe6, 0xcd, 0x16, 0xdb, 0xa4, 0x7b, 0x1a, 0xec, 0xe5, 0xd1, 0x94, 0xc2, 0x49, 0xd4, 0xb9, 0x91, + 0xa8, 0x8b, 0x9a, 0x65, 0xa8, 0x4e, 0xf0, 0x6a, 0x9e, 0xea, 0x61, 0x6f, 0x26, 0xa2, 0xb5, 0x92, 0xb2, 0xc4, 0x80, + 0xb5, 0x8e, 0x3c, 0x24, 0x77, 0x6b, 0x1d, 0x77, 0x1a, 0xea, 0xd2, 0x14, 0x6a, 0x82, 0x15, 0x2e, 0xc0, 0x11, 0xf4, + 0xbe, 0x08, 0x39, 0x5c, 0x53, 0x95, 0x7e, 0x41, 0x53, 0xf2, 0xc4, 0x53, 0xd4, 0x6a, 0x45, 0xba, 0xfd, 0x28, 0xc7, + 0x6e, 0xf8, 0xc6, 0x09, 0x39, 0x31, 0x42, 0x7f, 0x77, 0x2c, 0xe5, 0x0c, 0x2d, 0x1e, 0xd4, 0x09, 0xd6, 0xcb, 0x5b, + 0x0a, 0x14, 0x73, 0x74, 0x59, 0x75, 0xcd, 0x2b, 0xb4, 0x7d, 0x59, 0xf6, 0xfb, 0xb9, 0xad, 0x27, 0x65, 0x27, 0xdb, + 0xa5, 0xd9, 0x87, 0xa8, 0x98, 0xc2, 0x5d, 0x9f, 0x68, 0xfe, 0x2a, 0xd4, 0x57, 0x6d, 0x99, 0xf3, 0x11, 0x47, 0x9c, + 0x90, 0x9c, 0xd4, 0xff, 0x50, 0x53, 0xaf, 0xc4, 0xfd, 0xaa, 0x92, 0x97, 0xc2, 0x58, 0x31, 0x5a, 0x62, 0x88, 0x22, + 0xed, 0xde, 0x98, 0xbe, 0x2a, 0x00, 0xfe, 0x4a, 0xb0, 0x3f, 0xd3, 0x50, 0x2b, 0xbf, 0x45, 0x5b, 0xc0, 0xbf, 0x55, + 0xdc, 0x80, 0x55, 0x60, 0x80, 0xd1, 0x64, 0x7b, 0x4e, 0x13, 0x38, 0xe0, 0x84, 0x56, 0x51, 0x50, 0x61, 0x86, 0x86, + 0xda, 0xc2, 0xe8, 0x6b, 0x94, 0x71, 0xab, 0xcc, 0xde, 0x8d, 0xb1, 0xd3, 0x02, 0xaf, 0xe1, 0xdf, 0xe8, 0x85, 0x62, + 0x36, 0xea, 0x20, 0x3d, 0x3a, 0x89, 0xe9, 0x8f, 0x5b, 0x38, 0xb9, 0x59, 0x38, 0xcb, 0x9a, 0x25, 0xd0, 0x1d, 0xb8, + 0x20, 0xc6, 0xfd, 0x7e, 0x0e, 0x47, 0xa6, 0x19, 0xf9, 0x82, 0xe5, 0x34, 0x66, 0x4b, 0xaa, 0x3d, 0x0f, 0x2f, 0xab, + 0x30, 0xa7, 0x4b, 0x2b, 0xe3, 0x4d, 0x19, 0xa8, 0x8c, 0x76, 0xbb, 0x10, 0xfe, 0x74, 0x5b, 0xbb, 0xa4, 0xf3, 0x25, + 0x64, 0x80, 0x3f, 0x20, 0x11, 0x45, 0x2c, 0xf0, 0xff, 0xa8, 0x71, 0x4a, 0x4f, 0x94, 0xd6, 0x2c, 0x81, 0xe0, 0x71, + 0xaa, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdb, 0x85, 0xcd, 0x04, 0xa6, 0x39, 0x57, 0x32, 0xbd, 0x40, 0x9d, + 0x14, 0x50, 0xb1, 0xf0, 0x02, 0x97, 0x5f, 0x4a, 0x28, 0x34, 0x77, 0xbe, 0x5c, 0x18, 0x25, 0x26, 0xb4, 0x4a, 0x7e, + 0xfd, 0x50, 0x99, 0xaf, 0x8d, 0x87, 0x60, 0xb5, 0x0e, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0x2f, 0x41, 0x96, 0x23, + 0x00, 0xd7, 0xf3, 0xb5, 0xac, 0x29, 0x5f, 0x43, 0x5c, 0x78, 0x68, 0xd0, 0xbb, 0x42, 0x5e, 0x65, 0x25, 0x0f, 0xf1, + 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x36, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0xb6, 0x9e, 0x72, 0xbf, 0x7e, 0x29, 0xc2, + 0x39, 0x44, 0xef, 0x5c, 0x50, 0xad, 0xae, 0x76, 0x80, 0x5c, 0x9e, 0xed, 0xd5, 0x3b, 0x38, 0xdd, 0xf4, 0xf5, 0xad, + 0x0a, 0x9d, 0x39, 0x80, 0xb4, 0x87, 0x64, 0x5d, 0x73, 0xbd, 0x03, 0xdc, 0x91, 0x98, 0xad, 0x81, 0xc6, 0xba, 0xad, + 0xd9, 0x69, 0x8f, 0xe2, 0x31, 0x91, 0x99, 0xb1, 0x48, 0x31, 0xe6, 0x6e, 0x9d, 0x16, 0x45, 0x5b, 0x34, 0x43, 0xd8, + 0xbf, 0xeb, 0x88, 0x75, 0x2b, 0xe2, 0xfc, 0xdd, 0xb6, 0x2f, 0x30, 0x1a, 0xc6, 0x5c, 0xbb, 0xe7, 0x19, 0xba, 0x61, + 0x83, 0x6d, 0x24, 0x41, 0x44, 0x82, 0xcc, 0xd4, 0x81, 0x28, 0x6b, 0x6b, 0xc0, 0xf6, 0x8e, 0xeb, 0x4d, 0x0b, 0xfc, + 0xbc, 0x89, 0xc1, 0xdb, 0xb3, 0xc6, 0x29, 0xad, 0xaf, 0x71, 0xcd, 0x71, 0x55, 0x88, 0xa8, 0x2d, 0x52, 0x00, 0x0c, + 0x3b, 0x5f, 0xe0, 0xce, 0xac, 0x30, 0x98, 0x13, 0x96, 0x4a, 0xf6, 0x2a, 0xd7, 0x9f, 0xc3, 0x16, 0x07, 0xa9, 0x7c, + 0xe9, 0xf5, 0xf7, 0x1f, 0xbe, 0xf8, 0x02, 0xdd, 0xf6, 0x9c, 0x1f, 0x41, 0x90, 0x09, 0x74, 0x50, 0x53, 0xaa, 0xc7, + 0x97, 0x05, 0x50, 0x7b, 0x98, 0x87, 0x97, 0x05, 0x13, 0xf1, 0x75, 0x76, 0x19, 0x57, 0xb2, 0x18, 0x5d, 0x73, 0x91, + 0xca, 0xc2, 0x4a, 0x8d, 0x83, 0xd3, 0xd5, 0x2a, 0xe7, 0x01, 0x98, 0xca, 0x5b, 0x46, 0xd9, 0x09, 0x19, 0xf5, 0xe0, + 0x6a, 0x79, 0x7a, 0xa5, 0x45, 0xe7, 0xe5, 0xf5, 0x65, 0x10, 0xe1, 0xaf, 0x73, 0xf3, 0xe3, 0x2a, 0x2e, 0x3f, 0x05, + 0x91, 0xb5, 0xa9, 0x33, 0x3f, 0x50, 0x2a, 0x0f, 0xfe, 0x4e, 0x20, 0xd3, 0x7d, 0x59, 0x80, 0x65, 0xb6, 0xad, 0xf8, + 0x38, 0xc6, 0x5a, 0x87, 0x13, 0x32, 0x53, 0x25, 0x7a, 0xef, 0x92, 0x75, 0x01, 0xd6, 0x7e, 0x0a, 0xdb, 0x59, 0xe5, + 0x9a, 0x61, 0x65, 0xaa, 0x22, 0x63, 0x00, 0xbf, 0x66, 0x87, 0xa1, 0x75, 0xa2, 0x99, 0xa3, 0xb7, 0x80, 0x7e, 0x20, + 0x87, 0x97, 0xb4, 0x58, 0x33, 0xcf, 0xc7, 0xa6, 0xf1, 0xfa, 0xc1, 0xe1, 0xa5, 0x5b, 0xb0, 0xd7, 0xf6, 0x4e, 0x8e, + 0xc2, 0x44, 0xf0, 0x34, 0x36, 0xe3, 0x8b, 0x3c, 0x2b, 0x60, 0x07, 0x4d, 0xc6, 0x63, 0xea, 0x2d, 0xad, 0xd6, 0xcd, + 0xd1, 0x21, 0xdb, 0x66, 0x0f, 0xab, 0x87, 0x9c, 0x1c, 0xf2, 0x96, 0xa9, 0x6d, 0xdb, 0x3a, 0xce, 0xd3, 0xe4, 0x2b, + 0xd3, 0x7d, 0xb9, 0xb6, 0x11, 0xe2, 0x95, 0xb3, 0xa3, 0xf3, 0x92, 0x6e, 0x7d, 0x53, 0x1a, 0x7a, 0x2d, 0x01, 0x98, + 0x4f, 0x1b, 0xf0, 0x17, 0xac, 0x58, 0x8f, 0x2a, 0x5e, 0x56, 0x20, 0x61, 0x41, 0x11, 0xde, 0x14, 0x7b, 0x53, 0xb8, + 0x1b, 0xa7, 0xe7, 0xb0, 0x03, 0x17, 0x53, 0x74, 0xc7, 0x89, 0xc9, 0xac, 0x34, 0x5a, 0xd1, 0x48, 0xff, 0x72, 0x7d, + 0x89, 0x75, 0x5f, 0xb4, 0x32, 0xcf, 0xe6, 0x54, 0xd8, 0xf4, 0xae, 0x72, 0xe9, 0x44, 0xfd, 0x96, 0x09, 0x57, 0xae, + 0x04, 0x01, 0x99, 0x16, 0xac, 0x57, 0x98, 0x5d, 0x14, 0x23, 0x21, 0x03, 0xc3, 0xd7, 0x60, 0x2d, 0x4a, 0x6e, 0xac, + 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x2f, 0xad, 0x9b, 0xb7, 0xa3, 0x44, 0x19, 0xc4, + 0x27, 0xd7, 0x4e, 0x39, 0x48, 0x20, 0x00, 0x07, 0x56, 0x85, 0x24, 0x51, 0xa0, 0xf3, 0xe0, 0x6a, 0xc6, 0x11, 0x6c, + 0x5e, 0x39, 0x73, 0x71, 0x03, 0x38, 0xaf, 0xfc, 0xb9, 0x6c, 0xb0, 0x65, 0x3d, 0xa2, 0xca, 0x9c, 0x71, 0x8a, 0x41, + 0x9d, 0x2c, 0x41, 0x5f, 0x59, 0x4a, 0x7b, 0x09, 0x9a, 0xc6, 0x2b, 0xb6, 0x52, 0x3e, 0x00, 0xf4, 0x9c, 0xad, 0x94, + 0xb1, 0x3f, 0x7e, 0x7d, 0xc6, 0x56, 0x5a, 0x1a, 0x3c, 0xbd, 0x9a, 0x9d, 0xcf, 0xce, 0x06, 0xec, 0x28, 0x0a, 0xb5, + 0x01, 0x43, 0xe0, 0x22, 0x13, 0x04, 0x83, 0x50, 0xe3, 0xbf, 0x0c, 0x54, 0x80, 0x30, 0xe2, 0xf1, 0xd8, 0x88, 0x23, + 0x16, 0x8e, 0x87, 0x18, 0x0c, 0xac, 0xf9, 0x82, 0x04, 0x84, 0x9a, 0xd2, 0xd0, 0xd7, 0x33, 0x1c, 0x4e, 0x0e, 0x26, + 0x90, 0x8a, 0x99, 0x99, 0x2a, 0x8c, 0x8d, 0x49, 0x04, 0xf1, 0x5f, 0x3b, 0xeb, 0x85, 0x72, 0xbb, 0x6b, 0x34, 0x10, + 0x34, 0x83, 0xaf, 0xaa, 0x78, 0x72, 0x30, 0xec, 0xaa, 0x18, 0x47, 0xe1, 0xda, 0x28, 0xdf, 0xce, 0x8e, 0x01, 0xcc, + 0xf7, 0x6c, 0xe8, 0xcb, 0x25, 0xce, 0x0e, 0x1f, 0x93, 0x87, 0x8f, 0x09, 0x3d, 0x63, 0x67, 0xdf, 0x3c, 0xa6, 0x67, + 0x8a, 0x9c, 0x1c, 0x4c, 0xa2, 0x6b, 0x66, 0x31, 0x70, 0x8e, 0x54, 0x13, 0xe8, 0xe5, 0x68, 0x2d, 0xd4, 0x02, 0xd3, + 0x0e, 0x4d, 0xe1, 0xf7, 0xe3, 0x83, 0x60, 0x70, 0xdd, 0x6e, 0xfa, 0x75, 0xbb, 0xad, 0x9e, 0x57, 0xd7, 0xc1, 0x51, + 0xb4, 0x5f, 0xcc, 0xe4, 0xef, 0xe3, 0x03, 0x37, 0x07, 0x58, 0xdf, 0xfd, 0x63, 0x62, 0x9a, 0xb4, 0x37, 0x2a, 0x7e, + 0x4d, 0x8f, 0xb0, 0x0f, 0xcd, 0x22, 0x3b, 0xfa, 0x30, 0xfc, 0x8f, 0x3a, 0x51, 0x9f, 0x7d, 0x73, 0x04, 0xe4, 0x08, + 0x64, 0xa0, 0x58, 0x22, 0x98, 0xe1, 0x40, 0x53, 0x40, 0x41, 0xa6, 0xc7, 0x9d, 0xea, 0xe1, 0x57, 0xa3, 0xa6, 0x66, + 0xe4, 0x1a, 0xa6, 0x06, 0xdb, 0x82, 0x1f, 0xa8, 0x6e, 0xe8, 0x6f, 0x34, 0xda, 0x93, 0x76, 0x32, 0x33, 0x2f, 0xa9, + 0x8d, 0x73, 0x77, 0x0d, 0x01, 0x9d, 0x1d, 0xdc, 0xa2, 0x64, 0xdf, 0x1e, 0x5f, 0x1e, 0xe0, 0x2a, 0x02, 0xd4, 0x30, + 0x16, 0x7c, 0x3b, 0xb8, 0xd4, 0x9b, 0xfb, 0x20, 0x20, 0x83, 0x6f, 0x83, 0x93, 0x6f, 0x07, 0x72, 0x10, 0x1c, 0x1f, + 0x5e, 0x9e, 0x04, 0xce, 0xb8, 0x1f, 0x42, 0x5e, 0xaa, 0x8a, 0x62, 0x26, 0x4c, 0x15, 0x89, 0xad, 0x3d, 0xb7, 0xf5, + 0x2a, 0xe3, 0x33, 0x9a, 0x4e, 0x2d, 0x12, 0x7a, 0x98, 0xb2, 0xd8, 0xfc, 0x0e, 0x26, 0xfc, 0x2a, 0x88, 0x5c, 0x50, + 0xd8, 0x59, 0x1e, 0xc5, 0x74, 0xc9, 0xae, 0x45, 0x98, 0xd2, 0xe4, 0x30, 0x27, 0x24, 0x0a, 0x97, 0x0a, 0x4c, 0x50, + 0xbd, 0x4e, 0x20, 0xae, 0xad, 0xfb, 0xfc, 0x5a, 0x84, 0x4b, 0x9a, 0x1f, 0x26, 0xa4, 0x55, 0x84, 0x8b, 0x50, 0xb3, + 0xad, 0xe9, 0x05, 0x0b, 0x57, 0xf4, 0x12, 0x98, 0xa9, 0x78, 0x1d, 0x5e, 0x02, 0x97, 0xb7, 0x9e, 0xaf, 0x16, 0xec, + 0xb2, 0x21, 0x7d, 0x33, 0x7c, 0xf1, 0x85, 0xf5, 0xc9, 0x03, 0x1e, 0xd2, 0xf9, 0xe1, 0xa5, 0x60, 0x03, 0x70, 0x9d, + 0xf1, 0x9b, 0x1f, 0xe4, 0xad, 0x9e, 0x97, 0xf6, 0x14, 0xe3, 0xcc, 0xb4, 0x13, 0x93, 0x76, 0x42, 0xee, 0xdf, 0xb7, + 0x7d, 0xf7, 0xe2, 0xb5, 0x72, 0x59, 0xb5, 0x0c, 0x49, 0xb2, 0x56, 0xae, 0xd3, 0x28, 0x39, 0xb5, 0x02, 0x4f, 0x76, + 0xc1, 0xab, 0x64, 0xe9, 0x1f, 0x54, 0xd6, 0x6a, 0xc0, 0x1e, 0x23, 0x96, 0x85, 0xc2, 0xb1, 0x7f, 0x9d, 0xb1, 0x64, + 0xed, 0x0b, 0x34, 0x72, 0xe4, 0xde, 0x5e, 0x67, 0xcc, 0x8b, 0x41, 0xbb, 0x5c, 0x7b, 0xa1, 0xfb, 0xbc, 0xf4, 0xb4, + 0xc5, 0x7b, 0x39, 0xa5, 0x86, 0x91, 0x88, 0x1e, 0x8c, 0x95, 0x19, 0xa5, 0x4a, 0xd4, 0x1a, 0x34, 0x22, 0xd8, 0xd8, + 0x05, 0x03, 0x05, 0x27, 0x54, 0xee, 0xa9, 0xb3, 0x7d, 0x3b, 0xa5, 0xd2, 0x03, 0xda, 0xa5, 0x46, 0x55, 0xee, 0x96, + 0x99, 0x64, 0xd5, 0x20, 0x18, 0xfd, 0x59, 0x4a, 0x31, 0xc3, 0x3b, 0x23, 0x0b, 0xa6, 0x60, 0x25, 0xa8, 0x6a, 0x19, + 0x96, 0x43, 0x8e, 0x5a, 0x3c, 0xe3, 0x93, 0x2a, 0xf5, 0x8f, 0x8e, 0xa0, 0xc1, 0xeb, 0x75, 0x2b, 0x68, 0xf0, 0xe3, + 0xf1, 0x63, 0x3d, 0xd0, 0x17, 0x6b, 0xed, 0x78, 0xe8, 0xf3, 0xdb, 0x88, 0x37, 0xae, 0x7b, 0x4f, 0xb5, 0x56, 0xa1, + 0x0c, 0xb4, 0x58, 0x51, 0xb9, 0x52, 0x4b, 0x7a, 0xb7, 0x8b, 0x00, 0x58, 0xc4, 0xc6, 0x6c, 0xbc, 0x6f, 0x9b, 0x15, + 0x82, 0x46, 0x17, 0x96, 0xe2, 0x80, 0x25, 0xba, 0xb5, 0x83, 0x09, 0x8d, 0x4f, 0x58, 0xd9, 0xef, 0xe7, 0x27, 0x40, + 0x4f, 0xb5, 0x11, 0x53, 0x01, 0x47, 0xfe, 0xd7, 0x56, 0x64, 0x8a, 0x02, 0x9b, 0x35, 0x75, 0xb7, 0xc6, 0x32, 0x12, + 0x7d, 0x99, 0xd2, 0xe5, 0x09, 0xcf, 0x80, 0x69, 0xb5, 0x6e, 0x39, 0xae, 0xec, 0x2b, 0x8e, 0x3c, 0x15, 0x96, 0x15, + 0xe7, 0x55, 0x38, 0xde, 0x7a, 0x7c, 0x83, 0x43, 0xc3, 0xa6, 0x5d, 0xfa, 0x43, 0x08, 0x0b, 0xe1, 0x75, 0x06, 0xb7, + 0x11, 0x6d, 0x27, 0x81, 0xca, 0x1b, 0x73, 0x9d, 0x50, 0x36, 0xb7, 0xab, 0xb5, 0x67, 0x90, 0x4e, 0xcc, 0x81, 0x52, + 0x8d, 0xa0, 0x35, 0x9a, 0x05, 0x55, 0x23, 0x1e, 0x39, 0xf3, 0x2f, 0x67, 0x10, 0xab, 0xe5, 0x4b, 0x9a, 0x4a, 0xd1, + 0x00, 0x8c, 0x0b, 0xe0, 0xf2, 0xf4, 0xcb, 0xfb, 0x9f, 0x3e, 0xf0, 0xb8, 0x48, 0x96, 0xef, 0xe2, 0x22, 0xbe, 0x2a, + 0xc3, 0xad, 0x1a, 0xa3, 0xb8, 0x26, 0x53, 0x31, 0x60, 0xd2, 0xac, 0xa4, 0xe6, 0xae, 0xd4, 0x84, 0x18, 0xeb, 0x4c, + 0xd6, 0x65, 0x25, 0xaf, 0x1a, 0x95, 0xae, 0x8b, 0x0c, 0x3f, 0x6e, 0xf9, 0x9c, 0x1e, 0x02, 0xb0, 0xa9, 0x71, 0x21, + 0x8d, 0xa4, 0x2e, 0xc4, 0x98, 0x8b, 0x78, 0x5d, 0x1f, 0x8f, 0x1b, 0x5d, 0x2f, 0xd9, 0x93, 0xf1, 0xa3, 0xe9, 0xeb, + 0x2c, 0xcc, 0x06, 0x82, 0x8c, 0xaa, 0x25, 0x17, 0x2d, 0x53, 0x4e, 0x65, 0x12, 0x80, 0x3e, 0x9e, 0x3d, 0xc6, 0x8e, + 0xc6, 0x63, 0xb2, 0x6d, 0x8b, 0x07, 0x78, 0xb8, 0x5e, 0x87, 0x05, 0x99, 0xe9, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, 0x2a, + 0x00, 0x64, 0x4b, 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0x93, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, 0x37, + 0xf3, 0xd2, 0xf7, 0x28, 0x92, 0xc6, 0x65, 0x69, 0xaf, 0x52, 0xa9, 0xf6, 0xcc, 0xcc, 0x75, 0x0d, 0x62, 0x52, 0x84, + 0xba, 0xee, 0xd2, 0xab, 0x7b, 0xbf, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, 0xba, + 0x22, 0x6a, 0x7a, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0x17, 0x6b, 0x0a, 0x4a, 0xc1, 0xe8, 0x72, 0xed, 0x2d, + 0xdc, 0xa7, 0xb2, 0x71, 0x61, 0xc9, 0xf4, 0x6a, 0x51, 0x52, 0x42, 0x75, 0x53, 0x31, 0x52, 0xc2, 0x48, 0x69, 0x78, + 0x2a, 0xdf, 0x0b, 0x3c, 0xce, 0xf3, 0x20, 0x6a, 0x79, 0x81, 0x9d, 0x56, 0xe4, 0x14, 0x1c, 0xbd, 0x4c, 0x4e, 0x43, + 0x81, 0x2b, 0xa1, 0x40, 0x5d, 0x87, 0xea, 0x7e, 0x83, 0x9b, 0xff, 0xb7, 0x82, 0x05, 0x1e, 0xdf, 0x7a, 0x8e, 0xdb, + 0xe8, 0xb7, 0xc2, 0xa7, 0xa5, 0x0f, 0xa4, 0xef, 0xea, 0xe2, 0x49, 0x7b, 0xb3, 0x51, 0xb2, 0xcc, 0xf2, 0xf4, 0x8d, + 0x4c, 0x39, 0x88, 0xcc, 0xd0, 0x1a, 0x94, 0x9d, 0x88, 0xc6, 0x0d, 0x0f, 0x8c, 0x18, 0x1b, 0x37, 0xbe, 0x0a, 0x02, + 0x39, 0x02, 0x72, 0x3f, 0x67, 0xa9, 0x4c, 0xd6, 0x80, 0xb0, 0xa1, 0xe5, 0x27, 0x1a, 0x6f, 0x23, 0xd4, 0xd7, 0x2f, + 0x70, 0x9b, 0x2b, 0x7d, 0x9f, 0xf3, 0x4a, 0xd0, 0x4a, 0x00, 0xf0, 0x4b, 0xbc, 0x02, 0xb9, 0xc7, 0x53, 0xa8, 0x1b, + 0x61, 0x7b, 0x39, 0x06, 0x4b, 0x42, 0x74, 0x14, 0x51, 0xb1, 0x40, 0x41, 0x53, 0x18, 0x44, 0x11, 0x75, 0xc1, 0x1c, + 0x9e, 0xe7, 0x32, 0xf9, 0x34, 0x35, 0x3e, 0xf3, 0xc3, 0x18, 0x63, 0x48, 0x07, 0x83, 0xb0, 0x9a, 0x05, 0xc3, 0xf1, + 0x68, 0x72, 0xf4, 0x04, 0xce, 0xed, 0x60, 0x1c, 0x90, 0x41, 0x50, 0x97, 0xab, 0x58, 0xd0, 0xf2, 0xfa, 0xd2, 0x96, + 0x81, 0x1f, 0xd7, 0xc1, 0xe0, 0xb7, 0xc2, 0x8d, 0xca, 0xbf, 0x41, 0x73, 0xb2, 0x91, 0x61, 0x10, 0xd0, 0xab, 0x35, + 0x01, 0x49, 0x59, 0x4f, 0xf3, 0x93, 0xfa, 0x70, 0x63, 0x4a, 0xfb, 0x67, 0x0e, 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, + 0x34, 0x9e, 0x66, 0xa3, 0x57, 0x4a, 0x91, 0xfb, 0xae, 0xe0, 0x70, 0x67, 0xee, 0x39, 0xd3, 0x23, 0xa7, 0x90, 0x68, + 0x66, 0x01, 0x37, 0xf2, 0x57, 0xe2, 0x3a, 0xce, 0xb3, 0xf4, 0xa0, 0xf9, 0xe6, 0xa0, 0xdc, 0x88, 0x2a, 0xbe, 0x1d, + 0x05, 0xc6, 0x9a, 0x90, 0xfb, 0xaa, 0x27, 0x40, 0x4f, 0x80, 0x2d, 0x00, 0x06, 0xc4, 0x7b, 0x66, 0x26, 0x33, 0x1e, + 0x81, 0x47, 0x60, 0xd3, 0x07, 0xb2, 0xd8, 0x38, 0x97, 0x24, 0x7f, 0x33, 0x95, 0xf6, 0xaa, 0x57, 0xee, 0x15, 0x64, + 0xbd, 0xda, 0xca, 0x7d, 0xb7, 0x3e, 0xfb, 0xa6, 0xc3, 0x2b, 0xf0, 0x4c, 0x82, 0x5b, 0x64, 0xbf, 0xdf, 0x14, 0x54, + 0x0a, 0xa3, 0x22, 0xde, 0x4b, 0xae, 0xd1, 0xbf, 0xdd, 0x1b, 0x1b, 0x45, 0x72, 0xcb, 0xfb, 0x07, 0x50, 0x67, 0xf2, + 0xae, 0xb8, 0x9d, 0x43, 0xd4, 0xd6, 0xdd, 0x78, 0xe0, 0xbd, 0x41, 0xbb, 0xac, 0x39, 0x82, 0x2d, 0x2f, 0x0e, 0x32, + 0x18, 0x0b, 0x9c, 0x95, 0x91, 0x52, 0xe3, 0x1a, 0x52, 0x0b, 0x3e, 0xc9, 0xd3, 0x3b, 0xc8, 0x52, 0x4f, 0x82, 0x22, + 0xc7, 0xb3, 0x18, 0x32, 0x8d, 0xb7, 0x81, 0xd8, 0x6f, 0x65, 0x08, 0xd2, 0xb4, 0xdd, 0xae, 0x39, 0x02, 0x65, 0xf7, + 0xc0, 0x94, 0xa4, 0xae, 0x8d, 0xa9, 0x81, 0x86, 0x1e, 0x44, 0x8d, 0x54, 0xc4, 0xd9, 0xc9, 0x53, 0xd0, 0x21, 0x82, + 0xef, 0x77, 0x9a, 0x95, 0x1d, 0x2f, 0x26, 0x04, 0x4f, 0xde, 0xe7, 0xb7, 0x59, 0x59, 0x95, 0xd1, 0x9b, 0x14, 0x0d, + 0xa1, 0x12, 0x29, 0xa2, 0xcf, 0x10, 0x5f, 0xb0, 0xc4, 0xdf, 0x65, 0xf4, 0x22, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0xb3, + 0x02, 0x7e, 0x3e, 0x05, 0x94, 0x4b, 0xdc, 0x09, 0xd1, 0x99, 0x04, 0x7b, 0x35, 0x88, 0xee, 0x55, 0x71, 0xc0, 0x14, + 0x8d, 0xae, 0x05, 0x45, 0xcc, 0x3a, 0xcc, 0xfe, 0x4b, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x4b, 0x61, 0x1f, 0x22, 0xbe, + 0x86, 0x72, 0x4e, 0xdf, 0xbd, 0x32, 0x43, 0x1a, 0xdd, 0x4a, 0xaa, 0xb7, 0x36, 0x1e, 0x5b, 0x88, 0xd2, 0x13, 0x9d, + 0xaf, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x2d, 0xe0, 0x4f, 0xbc, 0x7b, 0xf5, 0x54, 0x59, 0x98, 0xbc, 0xca, 0x40, 0x71, + 0x70, 0xfa, 0xee, 0xd5, 0x6b, 0x99, 0xae, 0x73, 0x1e, 0x6d, 0x24, 0x92, 0xd6, 0xd3, 0x77, 0xaf, 0x7e, 0x46, 0x73, + 0xaf, 0xf7, 0x05, 0xbc, 0x7f, 0x01, 0xbc, 0x65, 0x94, 0xaf, 0xa1, 0x4f, 0xea, 0xf7, 0x72, 0x8d, 0x9d, 0xf2, 0x6a, + 0x2d, 0xa3, 0xbf, 0xd2, 0xda, 0x93, 0x56, 0xfd, 0x55, 0xf8, 0xd4, 0xce, 0x13, 0xf0, 0xdc, 0xe6, 0x99, 0xf8, 0x14, + 0x59, 0xd1, 0x4e, 0x10, 0x7d, 0x7b, 0x70, 0x7b, 0x95, 0x8b, 0x32, 0xc2, 0x17, 0x0c, 0xed, 0x82, 0xa2, 0xc3, 0xc3, + 0x9b, 0x9b, 0x9b, 0xd1, 0xcd, 0xa3, 0x91, 0x2c, 0x2e, 0x0f, 0x27, 0xdf, 0x7f, 0xff, 0xfd, 0x21, 0xbe, 0x0d, 0xbe, + 0x6d, 0xbb, 0xbd, 0x57, 0x84, 0x0f, 0x58, 0x80, 0x88, 0xdd, 0xdf, 0xc2, 0x15, 0x05, 0xb4, 0x70, 0x83, 0x6f, 0x83, + 0x6f, 0xf5, 0xa1, 0xf3, 0xed, 0x71, 0x79, 0x7d, 0xa9, 0xca, 0xef, 0x2a, 0xf9, 0x68, 0x3c, 0x1e, 0x1f, 0x82, 0x04, + 0xea, 0xdb, 0x01, 0x1f, 0x04, 0x27, 0xc1, 0x20, 0x83, 0x0b, 0x4d, 0x79, 0x7d, 0x79, 0x12, 0x78, 0x26, 0xaf, 0x0d, + 0x16, 0xd1, 0x81, 0xb8, 0x04, 0x87, 0x97, 0x34, 0xf8, 0x36, 0x20, 0x2e, 0xe5, 0x1b, 0x48, 0xf9, 0xe6, 0xe8, 0x89, + 0x9f, 0xf6, 0xbf, 0x54, 0xda, 0x23, 0x3f, 0xed, 0x18, 0xd3, 0x1e, 0x3d, 0xf5, 0xd3, 0x4e, 0x54, 0xda, 0x73, 0x3f, + 0xed, 0xff, 0x94, 0x03, 0x48, 0x3d, 0xf0, 0xad, 0xff, 0x36, 0x5e, 0x6b, 0xf0, 0x14, 0x8a, 0xb2, 0xab, 0xf8, 0x92, + 0x43, 0xa3, 0x07, 0xb7, 0x57, 0x39, 0x0d, 0x06, 0xd8, 0x5e, 0xcf, 0xc8, 0xc3, 0xfb, 0xe0, 0xdb, 0x75, 0x91, 0x87, + 0xc1, 0xb7, 0x03, 0x2c, 0x64, 0xf0, 0x6d, 0x40, 0xbe, 0x35, 0x06, 0x32, 0x82, 0x6d, 0x03, 0x17, 0x9a, 0x75, 0x68, + 0x03, 0xa6, 0xf9, 0xd2, 0xb8, 0x9a, 0xfe, 0xab, 0xe8, 0xce, 0x86, 0xb7, 0x44, 0xe5, 0xa6, 0x1b, 0xd4, 0xf4, 0x2d, + 0x78, 0x27, 0x40, 0xa3, 0xa2, 0xe0, 0x3a, 0x2e, 0xc2, 0xe1, 0xb0, 0xbc, 0xbe, 0x24, 0x60, 0x97, 0xb9, 0xe2, 0x71, + 0x15, 0x05, 0x42, 0x0e, 0xd5, 0xcf, 0x40, 0x45, 0x02, 0x0b, 0x10, 0xca, 0x08, 0xfe, 0x0b, 0x6a, 0xfa, 0x4e, 0xb2, + 0x6d, 0x30, 0xbc, 0xe1, 0xe7, 0x9f, 0xb2, 0x6a, 0xa8, 0x44, 0x8b, 0x37, 0x82, 0xc2, 0x0f, 0xf8, 0xeb, 0xaa, 0x8e, + 0xfe, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, 0xe9, 0x39, 0xb4, 0xc9, 0x79, 0xb6, 0x98, 0xb6, 0x0e, 0xf4, 0xb7, + 0x92, 0x54, 0xf3, 0x6c, 0x10, 0x0c, 0x83, 0x01, 0x5f, 0xb0, 0xb7, 0x72, 0xce, 0x3d, 0xf3, 0xa9, 0x53, 0xe9, 0x4f, + 0xf3, 0x2c, 0x1b, 0x80, 0x6f, 0x0a, 0xf2, 0x23, 0x87, 0xff, 0x35, 0x1f, 0xa2, 0xf0, 0x70, 0xf0, 0xe0, 0x90, 0xcc, + 0x82, 0xd5, 0x2d, 0x7a, 0x74, 0x46, 0x41, 0x26, 0x96, 0xbc, 0xc8, 0x2a, 0x6f, 0xa9, 0x5c, 0xaf, 0xdb, 0x5e, 0x1e, + 0x77, 0x9e, 0xcd, 0xab, 0x58, 0x04, 0xea, 0x9c, 0x03, 0xc5, 0x1b, 0xca, 0x9e, 0xca, 0xa6, 0x84, 0x54, 0x1b, 0xf2, + 0x86, 0xe5, 0x80, 0x05, 0xc7, 0xbd, 0xe1, 0xf0, 0x20, 0x18, 0x38, 0x75, 0xee, 0x20, 0x38, 0x18, 0x0e, 0x4f, 0x02, + 0x77, 0x1f, 0xca, 0x46, 0xee, 0xce, 0x48, 0x0b, 0xf6, 0x57, 0x11, 0x96, 0x14, 0xc4, 0x63, 0x52, 0x8b, 0xbf, 0x34, + 0xb8, 0xcc, 0x00, 0xa0, 0x8f, 0x94, 0x04, 0xcc, 0xc0, 0xca, 0x0c, 0x20, 0x54, 0x39, 0x8d, 0xd9, 0x2d, 0x30, 0x8f, + 0xc0, 0x31, 0x2b, 0x98, 0x2c, 0x40, 0x2c, 0x09, 0x70, 0xee, 0x82, 0x28, 0xd6, 0x85, 0x9c, 0x42, 0x10, 0x00, 0xfc, + 0x49, 0x4c, 0x29, 0x98, 0xa4, 0x63, 0x37, 0x82, 0x20, 0x8e, 0xcf, 0x6e, 0x44, 0x6b, 0x72, 0x96, 0xe8, 0x60, 0x46, + 0x12, 0x60, 0x43, 0x0c, 0x0c, 0x1f, 0xdc, 0xcf, 0x41, 0xe9, 0x61, 0xf5, 0x4e, 0xc8, 0x05, 0x6f, 0xb8, 0x63, 0xa1, + 0x6e, 0xe0, 0xea, 0x09, 0x07, 0xc1, 0x86, 0x6b, 0x16, 0x60, 0x54, 0x15, 0xeb, 0xb2, 0xe2, 0xe9, 0xc7, 0xcd, 0x0a, + 0x62, 0x01, 0xe2, 0x80, 0xbe, 0x93, 0x79, 0x96, 0x6c, 0x42, 0x67, 0xcf, 0xb5, 0x55, 0xe9, 0x2f, 0x3f, 0xbe, 0xfe, + 0x29, 0x02, 0x91, 0x63, 0x6d, 0x28, 0xfd, 0x86, 0xe3, 0xd9, 0xe4, 0x47, 0xbc, 0xf2, 0x37, 0xf6, 0x86, 0xdb, 0xd3, + 0xa3, 0xdf, 0x87, 0xba, 0xe9, 0x86, 0xcf, 0x36, 0x7c, 0xe4, 0x8a, 0x43, 0x75, 0x85, 0x67, 0x97, 0xb5, 0xf6, 0x8d, + 0x90, 0xee, 0x9f, 0x67, 0xca, 0x1b, 0xf3, 0xa3, 0x1d, 0x0c, 0x83, 0x60, 0xaa, 0x85, 0x92, 0x10, 0x85, 0x84, 0x29, + 0x01, 0x43, 0x74, 0xa0, 0x97, 0xd5, 0x14, 0x39, 0x37, 0x35, 0xb2, 0xf0, 0x7e, 0xc0, 0xb4, 0xd0, 0xa1, 0x91, 0x43, + 0xf9, 0xc1, 0xe1, 0x84, 0x31, 0x0b, 0xbf, 0x55, 0xc2, 0xf4, 0xab, 0x45, 0xe5, 0x1c, 0x44, 0x0f, 0xc0, 0x18, 0x57, + 0xf0, 0x02, 0xba, 0xc2, 0x3e, 0xad, 0x55, 0x94, 0x10, 0x04, 0xd3, 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, + 0xaa, 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, 0x06, 0x7e, 0xc9, 0x7e, 0x29, 0xd0, 0xb3, 0x7c, + 0x2a, 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0xb8, 0x7e, + 0x3c, 0x7d, 0x2d, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, 0xc5, 0x44, 0xc1, 0x3e, 0x40, 0xbf, 0xda, 0x36, + 0xfa, 0xec, 0x7a, 0xad, 0x37, 0x83, 0x12, 0x1d, 0xf3, 0x1a, 0x05, 0xd7, 0x4a, 0xa1, 0x60, 0xb4, 0xb7, 0xf1, 0x17, + 0x38, 0x72, 0xab, 0xdb, 0x43, 0xef, 0xb7, 0x2a, 0xbe, 0x7c, 0x83, 0xbe, 0x9d, 0xf6, 0xe7, 0xa8, 0x92, 0xbf, 0xac, + 0x56, 0xe0, 0x43, 0x05, 0x91, 0x56, 0x2c, 0x4e, 0x2f, 0xd4, 0xf3, 0xe1, 0xdd, 0xe9, 0x1b, 0xf0, 0xa3, 0xc4, 0xdf, + 0xbf, 0xfe, 0x18, 0xd4, 0x64, 0x1a, 0xcf, 0x0a, 0xf3, 0xa1, 0xcd, 0x01, 0xa1, 0x5a, 0x5c, 0x9a, 0x7d, 0x3f, 0x8b, + 0x9b, 0xec, 0xbb, 0x66, 0xeb, 0x69, 0xd1, 0x44, 0x92, 0x32, 0xdc, 0x3e, 0x18, 0x10, 0xe8, 0x03, 0x44, 0x71, 0xf6, + 0x05, 0x8d, 0x21, 0xcd, 0x67, 0xf6, 0xfd, 0x08, 0x81, 0xaf, 0xf6, 0x42, 0xaa, 0x71, 0x85, 0x45, 0xa3, 0x87, 0x7c, + 0xc6, 0x23, 0x65, 0x58, 0xf4, 0x1e, 0x13, 0x88, 0x33, 0x9c, 0x56, 0xef, 0x11, 0x03, 0x1a, 0xef, 0x06, 0x5a, 0xf6, + 0x10, 0x65, 0xd4, 0x65, 0x6f, 0x58, 0x7c, 0xbf, 0x5e, 0x87, 0x99, 0xb5, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x1b, 0x80, + 0x53, 0x8e, 0x2c, 0x5f, 0x65, 0x36, 0xba, 0x5a, 0x62, 0x7a, 0x13, 0x41, 0x6c, 0x22, 0x9d, 0x0e, 0x6b, 0x57, 0xa7, + 0xea, 0x5d, 0xed, 0x7c, 0x26, 0x7a, 0x15, 0x68, 0xe5, 0xda, 0xf6, 0x78, 0x08, 0xff, 0xa9, 0xa5, 0x15, 0x36, 0xc2, + 0x9e, 0x8b, 0x2f, 0x3c, 0xc7, 0xe6, 0x04, 0x34, 0xb8, 0x92, 0x29, 0x00, 0x67, 0x69, 0x35, 0x1a, 0x35, 0xc2, 0x3e, + 0x2b, 0xe7, 0x73, 0xd8, 0x5a, 0x88, 0xa7, 0x05, 0xe0, 0xc0, 0x4d, 0x4c, 0x4e, 0xde, 0x8d, 0xc9, 0x39, 0xfd, 0xa4, + 0xe0, 0xbe, 0x83, 0xb3, 0x72, 0x19, 0xa7, 0xf2, 0x06, 0xb0, 0x29, 0x03, 0x3f, 0x15, 0x4b, 0xf5, 0x12, 0x92, 0x25, + 0x4f, 0x3e, 0xa1, 0xd5, 0x46, 0x1a, 0x00, 0x57, 0x39, 0x35, 0x96, 0x7b, 0x0a, 0x34, 0xd5, 0x95, 0xa2, 0x12, 0xe2, + 0xaa, 0x8a, 0x93, 0xe5, 0x07, 0x4c, 0x0d, 0xb7, 0xd0, 0x8b, 0x28, 0x90, 0x2b, 0x2e, 0x80, 0xa4, 0xe7, 0xec, 0x1f, + 0x99, 0xc6, 0x5e, 0x7f, 0x20, 0x51, 0xc0, 0xa4, 0x51, 0x94, 0xb1, 0x52, 0xf6, 0x4a, 0x9a, 0xe8, 0x77, 0x41, 0x50, + 0xbb, 0x97, 0x7f, 0x41, 0xdd, 0x4f, 0xa1, 0x15, 0x61, 0x03, 0xbc, 0x50, 0x83, 0x1f, 0xa6, 0x76, 0xc9, 0x79, 0x40, + 0x86, 0xce, 0xfb, 0xac, 0xb6, 0x5b, 0xfd, 0xe9, 0x12, 0xb0, 0x5e, 0x53, 0xe3, 0x53, 0x18, 0x26, 0xc4, 0xc4, 0x4a, + 0xb6, 0xca, 0x4a, 0xbb, 0xa1, 0x4c, 0x3b, 0xe9, 0x92, 0x79, 0x2d, 0x9c, 0xe6, 0x3d, 0xc6, 0x96, 0x23, 0x95, 0xbb, + 0xdf, 0x0f, 0xcd, 0x4f, 0x96, 0xd3, 0x07, 0x3a, 0x84, 0xb5, 0x37, 0x1e, 0x34, 0x27, 0x5a, 0x5d, 0xd5, 0xd1, 0x0f, + 0xe8, 0x00, 0xcc, 0xb4, 0x45, 0xa8, 0x74, 0xc1, 0xb7, 0x7d, 0x25, 0x2a, 0x2e, 0x49, 0x58, 0x2a, 0x09, 0xec, 0xec, + 0xa6, 0x64, 0x67, 0x1b, 0x10, 0xcf, 0x70, 0xd7, 0xd3, 0x62, 0x27, 0xa4, 0x09, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, + 0x55, 0x97, 0x90, 0xad, 0x31, 0x74, 0xf1, 0x2f, 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x09, 0x0a, 0x55, 0xee, + 0xb7, 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, 0x37, 0xea, 0x66, 0xd4, 0x54, 0x75, 0xea, 0x25, 0xf8, 0x38, 0xcd, + 0xba, 0x0a, 0x32, 0x0b, 0xbb, 0x2a, 0xd6, 0x3c, 0xd0, 0xb1, 0xba, 0x94, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x23, + 0x63, 0x6c, 0x61, 0x0d, 0x47, 0xda, 0x1e, 0x37, 0x3d, 0x41, 0xe8, 0x27, 0x6c, 0x28, 0x81, 0x9b, 0xce, 0xf6, 0xd4, + 0x34, 0xf3, 0x01, 0x11, 0x87, 0x01, 0x05, 0x92, 0x8d, 0x43, 0x9a, 0x23, 0x7d, 0x41, 0xd2, 0x84, 0x81, 0xb2, 0x15, + 0xcf, 0x09, 0xb2, 0xa2, 0xd0, 0xb3, 0x75, 0x55, 0x43, 0xfc, 0x5c, 0x86, 0x39, 0x5a, 0x72, 0x2a, 0x3c, 0x4d, 0x90, + 0x89, 0xdd, 0xd1, 0x36, 0x33, 0x19, 0x8e, 0x92, 0x05, 0xe6, 0x57, 0x10, 0x25, 0xee, 0x4c, 0xb3, 0x2a, 0x07, 0xe3, + 0x02, 0x16, 0x68, 0xe5, 0x7b, 0x50, 0x37, 0xd6, 0xd0, 0x56, 0xc3, 0x32, 0xbb, 0xfd, 0x09, 0xf6, 0x6b, 0xed, 0xb4, + 0x2e, 0x53, 0x2c, 0x2f, 0x53, 0x88, 0xf6, 0x42, 0xe6, 0x37, 0x8a, 0x44, 0xf7, 0x8a, 0x30, 0x24, 0xac, 0xa3, 0xec, + 0x49, 0x9b, 0x1a, 0x40, 0x4f, 0xbd, 0x00, 0xf0, 0x9d, 0x6b, 0x19, 0x76, 0x91, 0xee, 0xaf, 0x0a, 0xc6, 0xa5, 0x1b, + 0x04, 0x29, 0x7a, 0x93, 0x82, 0x39, 0xaf, 0x47, 0x49, 0xbd, 0x39, 0x6d, 0x99, 0x51, 0x75, 0x54, 0x84, 0x94, 0x13, + 0xfc, 0x27, 0xaf, 0xa4, 0x26, 0x36, 0x61, 0x82, 0x07, 0x3e, 0xcc, 0x33, 0x6c, 0xe0, 0xdd, 0xee, 0x34, 0x0d, 0x93, + 0x36, 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0x09, 0x81, 0xca, 0x5e, 0xe1, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, + 0x1b, 0x0d, 0x4c, 0xdc, 0xea, 0x12, 0x60, 0x34, 0x13, 0x2e, 0xa9, 0x76, 0x76, 0xd2, 0xc2, 0xfa, 0xf6, 0xba, 0xbc, + 0xb0, 0x7d, 0xd0, 0xb1, 0xd4, 0xba, 0x86, 0x07, 0x9a, 0xd7, 0xec, 0xe2, 0x8a, 0x69, 0x9a, 0x68, 0xac, 0x87, 0x94, + 0x25, 0xc7, 0xba, 0x9e, 0xae, 0x70, 0xb5, 0xcc, 0x34, 0xd0, 0xbd, 0xc4, 0x0b, 0x3d, 0xe0, 0x83, 0x87, 0x2b, 0x12, + 0x5d, 0x60, 0xb3, 0xd9, 0xaa, 0x26, 0xd3, 0xfc, 0xae, 0x6c, 0xb9, 0x09, 0x90, 0x67, 0xa9, 0x6f, 0xee, 0x93, 0x63, + 0x4d, 0xdb, 0xfc, 0x24, 0xc0, 0x35, 0xf7, 0x0a, 0x48, 0x3a, 0x96, 0xa0, 0x8b, 0xf7, 0xe9, 0x0f, 0x22, 0x35, 0x53, + 0x41, 0xef, 0x9c, 0x2f, 0x52, 0x37, 0xbf, 0x00, 0xdb, 0xa8, 0xad, 0x35, 0xcd, 0x5a, 0x87, 0x89, 0xb2, 0xb0, 0x46, + 0x16, 0x72, 0x09, 0x3e, 0x98, 0xfb, 0x4d, 0x9d, 0x3e, 0xef, 0x20, 0xc2, 0x7e, 0x17, 0x3d, 0x1e, 0x61, 0xac, 0x58, + 0x83, 0xc4, 0xb0, 0x0a, 0x6b, 0xda, 0x5c, 0x0e, 0x51, 0x4e, 0xcd, 0x92, 0x89, 0x96, 0xd4, 0xa7, 0x14, 0x51, 0x0a, + 0xe6, 0xc6, 0xd3, 0xb2, 0x61, 0x4a, 0x88, 0x90, 0x15, 0xd2, 0x01, 0xd5, 0x5a, 0x68, 0xa9, 0x26, 0x08, 0x78, 0xe8, + 0x65, 0xa1, 0x31, 0x05, 0xd1, 0x47, 0x64, 0xb8, 0x11, 0x47, 0x46, 0xf7, 0xc7, 0x28, 0x26, 0x10, 0xba, 0xdb, 0xcb, + 0x0b, 0xab, 0x4f, 0xcb, 0xb6, 0x3a, 0x88, 0x6b, 0x4c, 0x93, 0x3b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, + 0x77, 0x11, 0xfa, 0x76, 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0x48, 0xeb, 0x35, 0x15, 0x03, 0xd4, 0xce, 0x63, 0x17, + 0xb1, 0x4a, 0x77, 0x0b, 0x51, 0xde, 0xa8, 0xac, 0x5f, 0xaf, 0x43, 0xb2, 0xdb, 0x61, 0x59, 0xe0, 0xcb, 0xfe, 0x74, + 0x7d, 0x07, 0x04, 0xfa, 0x83, 0xf5, 0x17, 0x21, 0xd0, 0x9f, 0x65, 0x5f, 0x03, 0x81, 0xfe, 0x60, 0xfd, 0x3f, 0x0d, + 0x81, 0xfe, 0x74, 0xed, 0x41, 0xa0, 0xab, 0xc1, 0xf8, 0x67, 0xc1, 0x82, 0xb7, 0x6f, 0x02, 0xfa, 0x4c, 0xb2, 0xe0, + 0xed, 0x8b, 0x17, 0x9e, 0x30, 0xfd, 0x63, 0xa6, 0x91, 0xfc, 0x8d, 0x2c, 0x18, 0x71, 0x5b, 0xe0, 0x15, 0x6a, 0x9d, + 0x7c, 0xa0, 0xa2, 0x0c, 0x80, 0xe8, 0xcb, 0xdf, 0xb2, 0x6a, 0x19, 0x06, 0x87, 0x01, 0x99, 0x39, 0x48, 0xd0, 0xe1, + 0xa4, 0x71, 0x7b, 0xfb, 0x45, 0x34, 0x84, 0x3a, 0x36, 0xf2, 0x00, 0x7c, 0xe5, 0x72, 0xbd, 0xf5, 0x6f, 0x88, 0xf8, + 0xc9, 0xcc, 0x82, 0x8e, 0x1e, 0x06, 0x04, 0x3c, 0x96, 0x32, 0x0f, 0x81, 0x73, 0xee, 0x87, 0x84, 0xfe, 0xb1, 0xf0, + 0x6c, 0x8b, 0x7e, 0x11, 0x61, 0x05, 0x3e, 0x77, 0x7f, 0xad, 0xf9, 0x59, 0x96, 0x12, 0x27, 0x0f, 0xe5, 0x22, 0x91, + 0x29, 0xff, 0xe5, 0xfd, 0x2b, 0x8b, 0x3c, 0x1e, 0x2a, 0xe8, 0x25, 0x82, 0x21, 0x8d, 0x53, 0x7e, 0x9d, 0x25, 0x7c, + 0xf6, 0xc7, 0x83, 0x6d, 0x67, 0x46, 0xf5, 0x9a, 0xd4, 0x87, 0x7f, 0x44, 0x41, 0xa0, 0xc7, 0xe0, 0x8f, 0x07, 0xdb, + 0xac, 0x3e, 0x7c, 0xb0, 0xad, 0x46, 0xa9, 0x04, 0x78, 0x6f, 0xf8, 0x2d, 0xeb, 0x07, 0xdb, 0x12, 0x7e, 0xf0, 0xfa, + 0x0f, 0x0f, 0x98, 0xcd, 0x36, 0xc8, 0xeb, 0x83, 0x55, 0x5e, 0x39, 0x4c, 0xd0, 0x7b, 0x0a, 0x16, 0xa6, 0x50, 0x87, + 0x47, 0xb5, 0xf6, 0xe4, 0x7e, 0x53, 0xdd, 0x75, 0x42, 0xe0, 0x1a, 0xe9, 0x06, 0x0e, 0xa1, 0xb2, 0x04, 0x3b, 0xe9, + 0xe8, 0x94, 0x20, 0xa6, 0xe6, 0xc3, 0x40, 0xd9, 0xfa, 0x7a, 0xc1, 0x8a, 0x5d, 0x33, 0x31, 0xbe, 0xd3, 0x18, 0xd8, + 0x70, 0xd1, 0xd5, 0x62, 0xce, 0xfe, 0x30, 0x3d, 0xde, 0xaf, 0x42, 0x12, 0xc4, 0xc8, 0xf6, 0xfb, 0xc4, 0xeb, 0x59, + 0xca, 0xab, 0x38, 0xcb, 0x59, 0x9c, 0xe7, 0x7f, 0xa0, 0x2c, 0xe2, 0xc7, 0xaf, 0x02, 0xdd, 0x1f, 0x8d, 0x46, 0x71, + 0x71, 0x89, 0x57, 0x7f, 0x43, 0x6e, 0x11, 0x16, 0x3b, 0xe3, 0xa5, 0x0d, 0xac, 0xb2, 0x8c, 0xcb, 0x33, 0x1d, 0xd1, + 0xa8, 0xb4, 0x04, 0xbb, 0x5c, 0xca, 0x9b, 0x33, 0x88, 0xee, 0x60, 0x29, 0x78, 0x8c, 0x03, 0xa8, 0xee, 0x4d, 0x3a, + 0xec, 0xf2, 0xe9, 0x5a, 0xbf, 0x3b, 0x8f, 0x4b, 0xfe, 0x2e, 0xae, 0x96, 0x0c, 0xf6, 0x82, 0xa6, 0xea, 0x85, 0x5c, + 0xaf, 0x5c, 0x25, 0x67, 0x6b, 0xf1, 0x49, 0xc8, 0x1b, 0xa1, 0x68, 0xef, 0x19, 0xbf, 0x86, 0x16, 0xb1, 0x2d, 0xea, + 0xac, 0x04, 0x4f, 0x2a, 0x8f, 0x13, 0x57, 0xb1, 0x00, 0x32, 0x6a, 0xa2, 0x01, 0x74, 0xe4, 0xa0, 0xa1, 0xdd, 0x6b, + 0xda, 0xb1, 0xdc, 0xa8, 0x2c, 0x32, 0xb0, 0x84, 0x7d, 0x0e, 0xa5, 0x03, 0x62, 0x3b, 0x84, 0x0b, 0x81, 0xab, 0x27, + 0x5e, 0x8d, 0x1a, 0x88, 0x3d, 0xb4, 0xf4, 0xdd, 0x85, 0x14, 0xab, 0x45, 0x30, 0xb0, 0x24, 0xac, 0xee, 0xb3, 0x2c, + 0x05, 0x30, 0xde, 0x2c, 0xd5, 0x9a, 0xf3, 0xc6, 0xc0, 0xe1, 0x85, 0x1b, 0x9d, 0x88, 0xd1, 0x1f, 0xda, 0x2d, 0x53, + 0xc6, 0x98, 0xb2, 0x41, 0x2b, 0x7a, 0x28, 0x1a, 0x93, 0xbe, 0xa6, 0x5a, 0x87, 0x98, 0xf3, 0x4c, 0xf4, 0xb6, 0xca, + 0xb9, 0x67, 0x0e, 0xe6, 0x61, 0x7e, 0xf9, 0x80, 0x16, 0x8a, 0x79, 0xcf, 0xc4, 0xfa, 0x8a, 0x17, 0x59, 0x72, 0xb6, + 0xcc, 0xca, 0x4a, 0x16, 0x9b, 0xc5, 0x34, 0xd6, 0x08, 0x93, 0x9a, 0x53, 0xa2, 0x5f, 0xf7, 0x1d, 0x78, 0x29, 0xaa, + 0x60, 0x26, 0xc3, 0x27, 0x63, 0x52, 0x6b, 0xcb, 0x79, 0xe8, 0x1e, 0xb5, 0xbf, 0x75, 0xaf, 0x5d, 0x82, 0xda, 0x44, + 0xee, 0xd9, 0xf6, 0x92, 0x36, 0x9d, 0x20, 0xda, 0x4d, 0xa0, 0x66, 0x9d, 0x15, 0xfc, 0xaf, 0x35, 0x37, 0xa1, 0x10, + 0x42, 0x07, 0xf3, 0x1d, 0x96, 0xc6, 0x0a, 0x46, 0xd1, 0x6f, 0x55, 0xb7, 0x22, 0xcd, 0xad, 0x17, 0xaa, 0x0d, 0x84, + 0xa8, 0xab, 0x64, 0x9a, 0x3e, 0x47, 0x44, 0x77, 0x10, 0xa1, 0xe0, 0xc6, 0xb3, 0x01, 0xc1, 0xba, 0xd6, 0xd6, 0x5c, + 0x2e, 0x66, 0xf7, 0xbe, 0x1d, 0x0c, 0xa2, 0x7b, 0xdf, 0xb3, 0xc9, 0x3d, 0x2b, 0x77, 0x2e, 0x17, 0xc7, 0xc6, 0x18, + 0x73, 0x8a, 0xb6, 0x2d, 0xe1, 0xbb, 0x75, 0xd8, 0xdc, 0x0c, 0x70, 0x1a, 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, + 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x14, 0xd9, 0xb1, 0x86, 0x30, 0xd2, 0xba, 0x9d, 0x5c, 0x5e, 0x86, 0x31, 0xc4, 0xb2, + 0x1e, 0xc9, 0x4f, 0x7b, 0x31, 0x3f, 0xff, 0x78, 0xf9, 0xf1, 0xe3, 0xbb, 0x03, 0x54, 0xff, 0xf4, 0x0e, 0x3e, 0x28, + 0x2c, 0x81, 0x83, 0x07, 0xdb, 0x58, 0x2b, 0xdc, 0xeb, 0x3f, 0xec, 0xc9, 0x15, 0xb7, 0xd4, 0xe5, 0xc6, 0xad, 0xce, + 0xab, 0xa2, 0x35, 0x8e, 0xb1, 0xd3, 0x69, 0xfb, 0x99, 0x95, 0xae, 0x29, 0x40, 0x4d, 0x8a, 0xaa, 0x39, 0x0a, 0x28, + 0xe4, 0x85, 0xb8, 0x0b, 0x61, 0x75, 0xc7, 0xc6, 0xab, 0xba, 0x36, 0x9e, 0x2c, 0xaa, 0x4c, 0x5c, 0x9e, 0x21, 0x2d, + 0xf8, 0x9a, 0x0d, 0x68, 0x63, 0xbc, 0x29, 0xea, 0xe1, 0xed, 0xb4, 0x82, 0x9d, 0x14, 0x4d, 0xe0, 0x32, 0x6d, 0xa2, + 0xbb, 0xd5, 0xb6, 0x2d, 0xa3, 0xd1, 0xa8, 0xac, 0xa7, 0xfe, 0xc7, 0xc6, 0x7e, 0xc4, 0x4f, 0x53, 0xb0, 0x6e, 0xc0, + 0x11, 0xc1, 0xce, 0x35, 0xed, 0xbb, 0x41, 0x29, 0xca, 0x71, 0xd2, 0x4a, 0x98, 0x0d, 0x27, 0xd1, 0x84, 0xd8, 0x68, + 0x13, 0x9a, 0xa2, 0xfd, 0x38, 0x7a, 0xfe, 0xe6, 0xe3, 0xab, 0x8f, 0xff, 0x3e, 0x7b, 0x7a, 0xfa, 0xf1, 0xf9, 0x8f, + 0x6f, 0xdf, 0xbf, 0x7a, 0xfe, 0x01, 0xcf, 0x0b, 0x0d, 0x5f, 0x19, 0x6e, 0xb5, 0x8d, 0x74, 0xb3, 0xac, 0x48, 0xd4, + 0xa4, 0xd9, 0x14, 0x85, 0x1f, 0x85, 0x99, 0x6d, 0x91, 0xbf, 0xbc, 0x79, 0xf6, 0xfc, 0xc5, 0xab, 0x37, 0xcf, 0x9f, + 0xb5, 0xbf, 0x1e, 0x4e, 0x6a, 0x52, 0xbb, 0x99, 0xd3, 0xf1, 0x52, 0xcc, 0xad, 0x00, 0x70, 0x06, 0x2c, 0xd9, 0xca, + 0x80, 0x6c, 0x99, 0x71, 0xec, 0xa0, 0x59, 0x88, 0x3d, 0xe6, 0xd3, 0xac, 0x4a, 0x8d, 0x64, 0xbf, 0x5f, 0xb9, 0x73, + 0x3f, 0xd3, 0x7b, 0x6f, 0xb7, 0x7b, 0xbb, 0x06, 0x27, 0x76, 0x0d, 0x03, 0x0c, 0x86, 0xad, 0x54, 0xbd, 0x89, 0x4a, + 0x6a, 0x0b, 0x89, 0x2a, 0xaa, 0x82, 0x2d, 0x9c, 0x25, 0x71, 0xc5, 0x2f, 0x65, 0xb1, 0x89, 0xb2, 0x51, 0x2b, 0x85, + 0x36, 0x16, 0x43, 0x14, 0xa2, 0x85, 0xb1, 0x9f, 0x44, 0x7a, 0x6a, 0xf7, 0x8b, 0xa8, 0x63, 0x84, 0xe7, 0x2e, 0x8e, + 0x40, 0xbb, 0x60, 0xb2, 0xd8, 0xed, 0x3a, 0x06, 0xb0, 0x93, 0x12, 0x46, 0xf3, 0x4c, 0x91, 0xc8, 0x45, 0x3d, 0x95, + 0x78, 0xf0, 0xa9, 0x53, 0x8d, 0x99, 0x83, 0xf0, 0x54, 0x31, 0xd4, 0xc0, 0xc7, 0x7a, 0xaf, 0x4d, 0xc8, 0x99, 0xff, + 0xaf, 0xbd, 0x67, 0x5b, 0x6e, 0xdb, 0x48, 0xf6, 0x3d, 0x5f, 0x01, 0xc1, 0x5e, 0x1b, 0xb0, 0x01, 0x08, 0x20, 0x75, + 0xa1, 0x49, 0x81, 0x4a, 0x6c, 0xcb, 0x49, 0x76, 0x95, 0x38, 0x65, 0x2b, 0xde, 0x8b, 0x56, 0x25, 0x82, 0xe4, 0x90, + 0xc4, 0x1a, 0x04, 0x58, 0x00, 0x28, 0x4a, 0xa1, 0xb1, 0xdf, 0xb2, 0x9f, 0x70, 0xbe, 0x61, 0xbf, 0xec, 0x54, 0x77, + 0xcf, 0x00, 0x83, 0x0b, 0x29, 0x2a, 0x76, 0xb2, 0x7b, 0xaa, 0x4e, 0x25, 0xb6, 0x89, 0xc1, 0xcc, 0xa0, 0xe7, 0xd6, + 0xdd, 0xd3, 0xd7, 0x32, 0xa5, 0xb4, 0x2b, 0xf8, 0x57, 0x58, 0x21, 0x57, 0x4a, 0x69, 0xcb, 0x81, 0x98, 0xd3, 0xed, + 0xe3, 0xaa, 0x81, 0x55, 0xa1, 0xb8, 0x27, 0x83, 0x99, 0x60, 0x65, 0xd7, 0x89, 0x79, 0x98, 0x75, 0x69, 0xc3, 0x1b, + 0x81, 0x0b, 0xa6, 0x87, 0x1b, 0x6a, 0x8d, 0xbb, 0x5e, 0x29, 0x14, 0x66, 0x5c, 0x9e, 0xd4, 0x13, 0xaf, 0xfc, 0x0c, + 0x5b, 0xba, 0x52, 0x05, 0x7c, 0x63, 0x2a, 0x95, 0x40, 0x0a, 0x16, 0x9c, 0xd2, 0xe7, 0xad, 0x34, 0x3a, 0x8f, 0x56, + 0x42, 0x70, 0x7c, 0xe2, 0x35, 0x14, 0xe2, 0x39, 0xe9, 0x8e, 0x4e, 0x02, 0xfa, 0xe1, 0x64, 0x1b, 0x28, 0x40, 0x56, + 0x4c, 0x70, 0xce, 0xb6, 0x0e, 0xe8, 0x32, 0x75, 0xfd, 0x78, 0x2d, 0xb6, 0x5c, 0x36, 0xf0, 0xf3, 0xb4, 0xb0, 0x25, + 0x96, 0x23, 0xe3, 0x53, 0x2f, 0x47, 0x21, 0x6d, 0xa8, 0xc6, 0xf7, 0x87, 0xeb, 0x37, 0xf2, 0x2d, 0x16, 0x3d, 0x32, + 0xa2, 0xe9, 0xcd, 0x55, 0xd8, 0x2d, 0x1b, 0x69, 0x4d, 0x80, 0x91, 0xe0, 0x49, 0x0c, 0x01, 0x03, 0x33, 0x23, 0xea, + 0xff, 0x36, 0xae, 0xa2, 0x7e, 0xb4, 0xbf, 0xcb, 0x91, 0xff, 0x4f, 0x6f, 0xdf, 0x5f, 0x80, 0x5e, 0xcb, 0x43, 0x45, + 0xf4, 0x5a, 0xe5, 0x36, 0x2c, 0x26, 0x68, 0x8a, 0xd4, 0xae, 0xea, 0x2d, 0x80, 0x3a, 0xe3, 0x8d, 0x61, 0xff, 0xd6, + 0x5c, 0xad, 0x56, 0x26, 0x58, 0xb4, 0x9a, 0xcb, 0x38, 0x20, 0xee, 0x70, 0xac, 0x66, 0x02, 0xa9, 0xb3, 0x0a, 0x52, + 0x87, 0x70, 0xb8, 0x3c, 0x9f, 0xca, 0xfb, 0x59, 0xb4, 0xfa, 0x26, 0x08, 0x64, 0xb1, 0x8d, 0x60, 0xe2, 0xb8, 0x24, + 0xa3, 0x84, 0x0c, 0x34, 0xd0, 0x3e, 0x59, 0x7e, 0x72, 0xcd, 0xed, 0x05, 0xc6, 0xd7, 0xc3, 0xbb, 0x6b, 0xae, 0x93, + 0xc8, 0xe3, 0x11, 0xbf, 0x1f, 0x9c, 0x8c, 0xfd, 0x1b, 0x05, 0x39, 0x4d, 0x57, 0x05, 0x67, 0xae, 0x80, 0x0d, 0x97, + 0x69, 0x1a, 0x85, 0x66, 0x1c, 0xad, 0xd4, 0xfe, 0x09, 0x3d, 0x88, 0x0a, 0x1e, 0x3d, 0xaa, 0xca, 0xd7, 0xa3, 0xc0, + 0x1f, 0x7d, 0x74, 0xd5, 0xc7, 0x6b, 0xdf, 0xed, 0x57, 0xf8, 0x49, 0x3b, 0x53, 0xfb, 0x00, 0xab, 0xf2, 0x4d, 0x10, + 0x9c, 0xec, 0x53, 0x8b, 0xfe, 0xc9, 0xfe, 0xd8, 0xbf, 0xe9, 0x4b, 0xa9, 0x61, 0xb8, 0xde, 0xd4, 0xe5, 0x21, 0x38, + 0x73, 0x4b, 0xb3, 0x04, 0x63, 0x3a, 0x8c, 0x98, 0x56, 0x5c, 0x7e, 0x21, 0xd6, 0x0c, 0xc1, 0xab, 0x8d, 0x50, 0x9c, + 0x1e, 0xc0, 0x55, 0xef, 0xd3, 0x27, 0x2d, 0xb7, 0x43, 0x9d, 0x49, 0x41, 0xda, 0x50, 0xcd, 0x87, 0x55, 0x0c, 0x8c, + 0x34, 0xa3, 0x6b, 0x22, 0x94, 0x5c, 0xa0, 0x1b, 0xa3, 0xcc, 0xc0, 0x0c, 0x3b, 0xde, 0x02, 0x34, 0x8e, 0xfc, 0xa7, + 0x74, 0x23, 0x1e, 0x41, 0x56, 0x6d, 0x09, 0x89, 0xeb, 0x92, 0xce, 0x85, 0x4e, 0x21, 0x8f, 0x13, 0x08, 0xca, 0x12, + 0xfc, 0x0e, 0xe9, 0x41, 0xb4, 0x40, 0x87, 0xac, 0x6e, 0x79, 0x70, 0x1e, 0x2f, 0x13, 0x79, 0xd4, 0xc4, 0xbc, 0x9c, + 0x96, 0x56, 0xa8, 0x5b, 0x5d, 0x2f, 0x11, 0x35, 0x72, 0x2f, 0xd9, 0xb4, 0x64, 0xa0, 0xc3, 0xd3, 0x52, 0xa3, 0x42, + 0x73, 0xc1, 0xab, 0x4f, 0x52, 0x1c, 0x31, 0x43, 0xbb, 0x4c, 0x8c, 0xe8, 0xaa, 0xa0, 0x53, 0x09, 0x21, 0xca, 0x6e, + 0x94, 0x15, 0x01, 0x9c, 0x69, 0xd5, 0xfb, 0x8f, 0xd7, 0x21, 0x12, 0xb6, 0xc4, 0xed, 0x97, 0xf7, 0x41, 0xea, 0x0d, + 0x4d, 0xda, 0xcc, 0xaa, 0xf2, 0xf5, 0x78, 0x18, 0xe4, 0x8b, 0x4d, 0x87, 0x60, 0xe6, 0x85, 0xe3, 0x80, 0x5d, 0x78, + 0xc3, 0xef, 0xb0, 0xce, 0xeb, 0x61, 0xf0, 0x0a, 0x2a, 0x64, 0x6a, 0xff, 0xf1, 0x9a, 0x48, 0x77, 0x13, 0xc2, 0xce, + 0x68, 0x0b, 0x54, 0xbf, 0xc3, 0x53, 0x2e, 0xb1, 0x98, 0x5a, 0x23, 0xb0, 0x44, 0x6e, 0x29, 0x8e, 0x6d, 0x19, 0x32, + 0x9e, 0xf2, 0x07, 0xf6, 0xa6, 0xc2, 0x4f, 0x2d, 0xc0, 0x15, 0x89, 0x13, 0x2c, 0xef, 0x4c, 0x19, 0x58, 0x22, 0xab, + 0xef, 0xa2, 0x95, 0x80, 0x94, 0x4f, 0x00, 0x85, 0xa8, 0x3c, 0x7d, 0x3f, 0x38, 0x91, 0xd5, 0x42, 0x28, 0x3b, 0xa7, + 0x7e, 0xe1, 0x57, 0xa6, 0x2a, 0x45, 0x02, 0xa8, 0xc5, 0xad, 0xda, 0x3f, 0xd9, 0x97, 0x6b, 0xf7, 0x07, 0xdd, 0x33, + 0x69, 0x70, 0xd8, 0xab, 0xb8, 0x37, 0x5f, 0x16, 0x0f, 0xd9, 0x95, 0x02, 0xb7, 0xe4, 0x0c, 0x4a, 0x60, 0x8e, 0xca, + 0x4d, 0x6a, 0xe4, 0x07, 0x52, 0x26, 0x16, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0x91, 0xde, 0xcd, 0x97, 0x90, 0x2c, + 0x33, 0x45, 0x6f, 0x03, 0xfe, 0x6f, 0x31, 0x25, 0x28, 0xe9, 0x66, 0x61, 0x12, 0xc5, 0x2a, 0x0c, 0xb3, 0x9a, 0x37, + 0x49, 0x91, 0xf2, 0xb5, 0xe1, 0x80, 0x1b, 0xc9, 0x2a, 0x4c, 0xd8, 0x7e, 0xb5, 0xa9, 0x34, 0xee, 0x81, 0x5e, 0xfc, + 0x50, 0xf8, 0x60, 0x2a, 0x48, 0x2b, 0x07, 0x70, 0x73, 0x3e, 0xaa, 0xcb, 0xc7, 0xbe, 0xf1, 0xe7, 0xc8, 0x18, 0x7a, + 0xc6, 0xb5, 0x67, 0xfc, 0x10, 0x5e, 0x65, 0x8d, 0x8b, 0x97, 0xe7, 0x92, 0x33, 0x58, 0x4f, 0x83, 0x08, 0x4c, 0xe5, + 0x4b, 0x85, 0x6f, 0x71, 0x9b, 0x91, 0x0b, 0x2f, 0x9e, 0x32, 0x91, 0xc2, 0x4d, 0xbc, 0x15, 0xb2, 0x03, 0x5d, 0x9a, + 0x16, 0x08, 0x4f, 0xb6, 0xc7, 0x4d, 0xeb, 0x7c, 0x6b, 0x94, 0xc6, 0xc1, 0x9f, 0xd8, 0x1d, 0xb0, 0x59, 0x49, 0x1a, + 0x2d, 0x40, 0x66, 0xe5, 0x4d, 0xb9, 0x0e, 0xc2, 0xd0, 0xd8, 0x6e, 0x9f, 0xfb, 0xf4, 0x89, 0x49, 0x59, 0xc5, 0xd2, + 0x68, 0x3a, 0x0d, 0x98, 0x26, 0x65, 0x1f, 0xcb, 0x3f, 0x73, 0xba, 0x67, 0x8b, 0xc8, 0xd5, 0x7a, 0xb6, 0xe9, 0x60, + 0x89, 0x11, 0xb3, 0x9c, 0x1b, 0x04, 0xc4, 0x45, 0xc6, 0x55, 0xc8, 0x90, 0x6b, 0xe2, 0x5c, 0x14, 0x07, 0xd7, 0x1c, + 0x47, 0xcb, 0x61, 0xc0, 0x4c, 0x3c, 0x0d, 0xf0, 0xc9, 0xf5, 0x70, 0x39, 0x1c, 0x06, 0x94, 0x2e, 0x0c, 0xe2, 0xaf, + 0x45, 0x09, 0xca, 0x45, 0x33, 0xbd, 0x07, 0x83, 0xb2, 0xd2, 0x2a, 0xf8, 0x60, 0x33, 0x09, 0x37, 0x07, 0xfa, 0x40, + 0x0a, 0x32, 0xd0, 0xfa, 0x99, 0x76, 0x55, 0xb8, 0xb1, 0xb0, 0x44, 0xed, 0x35, 0xb0, 0x74, 0xee, 0xa5, 0xfa, 0x1e, + 0x67, 0x58, 0xf1, 0xc2, 0xb1, 0xf2, 0x8a, 0xf6, 0xae, 0x6a, 0xa8, 0x64, 0xfa, 0xc5, 0xb3, 0xcb, 0xa9, 0x86, 0xfa, + 0xda, 0xf7, 0xa6, 0x61, 0x94, 0xa4, 0xfe, 0x48, 0xbd, 0xea, 0xbd, 0xf6, 0xb5, 0xcb, 0x79, 0xaa, 0xe9, 0x57, 0xc6, + 0xb7, 0x72, 0x1e, 0x30, 0x81, 0x29, 0x31, 0x0d, 0xd8, 0x86, 0x3a, 0xf2, 0xe9, 0xd9, 0x56, 0x4f, 0x60, 0x64, 0xac, + 0xf3, 0xad, 0x0b, 0xb5, 0x2a, 0x19, 0xc5, 0x30, 0x55, 0x24, 0x64, 0x14, 0xfb, 0x56, 0xef, 0x91, 0x10, 0xe6, 0x9b, + 0xe5, 0x1a, 0x99, 0x86, 0xb4, 0x20, 0xbe, 0x18, 0x04, 0x5f, 0x78, 0x8e, 0xd2, 0xf3, 0x9e, 0xec, 0xf5, 0x50, 0x22, + 0xe3, 0x83, 0x6f, 0xca, 0x1c, 0xc8, 0xe3, 0x75, 0x9a, 0x81, 0xc9, 0x61, 0x18, 0xa5, 0x0a, 0x44, 0x76, 0x83, 0x0f, + 0x0e, 0xaa, 0x56, 0xd2, 0xbc, 0x57, 0x4d, 0xcf, 0x38, 0x16, 0x78, 0x89, 0xb4, 0x14, 0x25, 0x97, 0x10, 0x88, 0x02, + 0x82, 0x94, 0x96, 0xe2, 0x38, 0x71, 0xdf, 0x3c, 0x58, 0xbe, 0x12, 0xff, 0x26, 0xe1, 0xfd, 0x32, 0x3d, 0x7f, 0xbc, + 0x4e, 0x4e, 0x05, 0x51, 0xff, 0x3e, 0xc1, 0xb5, 0x04, 0x76, 0x85, 0x53, 0xf9, 0x4c, 0x55, 0x4e, 0x05, 0x25, 0xc2, + 0xba, 0x25, 0xf4, 0xaa, 0x09, 0x76, 0x37, 0x16, 0x31, 0xf3, 0xb9, 0x18, 0x45, 0x30, 0x60, 0x95, 0xa3, 0x07, 0xc1, + 0x9a, 0x72, 0xde, 0x2a, 0x05, 0x8b, 0x6b, 0x24, 0x18, 0x80, 0xb9, 0x38, 0x8f, 0x30, 0xc8, 0xae, 0x81, 0x91, 0x84, + 0x08, 0x66, 0x62, 0x8c, 0x46, 0x24, 0x27, 0x91, 0xf3, 0xc3, 0xc5, 0x32, 0xc5, 0xc8, 0xf4, 0x00, 0x00, 0xcb, 0x54, + 0x05, 0x2f, 0x8c, 0x80, 0xeb, 0x8b, 0x0b, 0x4f, 0xa6, 0x2a, 0xfe, 0xb8, 0x5e, 0xc6, 0xa5, 0x33, 0x80, 0xe3, 0x70, + 0x18, 0xa8, 0xd7, 0x81, 0xc7, 0x98, 0x0f, 0x63, 0x64, 0x14, 0x69, 0x5d, 0xb4, 0x11, 0xda, 0x3f, 0x34, 0x20, 0x90, + 0x11, 0xf5, 0xd3, 0xd3, 0x82, 0xc6, 0xc1, 0x42, 0xb4, 0xea, 0xd2, 0x30, 0x07, 0x20, 0xa3, 0x3c, 0x85, 0xb9, 0x73, + 0xe1, 0x52, 0x2f, 0x4c, 0xeb, 0xd4, 0x0b, 0x95, 0xec, 0xea, 0x06, 0x38, 0x0d, 0x83, 0xec, 0xba, 0x70, 0x74, 0x2d, + 0xc6, 0x0b, 0x5b, 0x92, 0xca, 0x15, 0xb4, 0x74, 0x73, 0xb9, 0x3d, 0xdb, 0x22, 0xf6, 0xe7, 0x5e, 0x7c, 0x47, 0xe6, + 0x6f, 0x86, 0x6c, 0x23, 0xa7, 0xab, 0x0a, 0xd1, 0x03, 0x9a, 0x00, 0x22, 0x0d, 0xaa, 0xf2, 0x75, 0x5e, 0xc6, 0xf8, + 0x68, 0x73, 0x1b, 0x20, 0xf8, 0xd6, 0xb5, 0xfa, 0x9c, 0x59, 0x24, 0x7f, 0xa4, 0x26, 0x3d, 0x2d, 0xd9, 0x30, 0xbc, + 0xa4, 0x3c, 0xbc, 0xb0, 0xbc, 0xd1, 0x70, 0x30, 0x44, 0x29, 0x08, 0x6e, 0x1c, 0x19, 0x26, 0xc1, 0x6c, 0x5e, 0x51, + 0x7a, 0xf7, 0xbb, 0x2e, 0x07, 0x83, 0xe5, 0x08, 0x61, 0x39, 0x1a, 0x44, 0xb3, 0x9e, 0x58, 0x11, 0xe0, 0x45, 0x80, + 0x0b, 0x89, 0x91, 0x03, 0xa1, 0xfc, 0x98, 0x4a, 0xbe, 0x85, 0x62, 0x38, 0x1a, 0x04, 0x3b, 0x1d, 0x8d, 0xd8, 0x75, + 0x23, 0x6c, 0x15, 0x67, 0x27, 0xfb, 0x54, 0x9b, 0x88, 0x22, 0x55, 0x82, 0x69, 0x88, 0x61, 0x84, 0xc5, 0x2c, 0x40, + 0x82, 0x70, 0xd7, 0x29, 0x2e, 0x3a, 0xd6, 0x1c, 0xd5, 0xd2, 0xce, 0x69, 0x99, 0xe1, 0xc1, 0x56, 0x6a, 0xff, 0x04, + 0x53, 0x7e, 0x02, 0x59, 0x87, 0xa0, 0x58, 0x27, 0xfb, 0xf4, 0xa8, 0x54, 0x4e, 0x44, 0xd1, 0x89, 0x90, 0x41, 0x76, + 0x79, 0x07, 0x0f, 0x3a, 0x2a, 0x49, 0xca, 0x16, 0x50, 0xea, 0x65, 0xaa, 0x32, 0xe7, 0x0c, 0x16, 0x8f, 0xbe, 0x07, + 0xa1, 0x79, 0x6c, 0x70, 0x89, 0x50, 0x95, 0xb9, 0x77, 0x8b, 0x23, 0x17, 0x6f, 0xbc, 0x5b, 0xcd, 0xe1, 0xaf, 0x8a, + 0xb3, 0x96, 0x94, 0xcf, 0xda, 0xa8, 0x76, 0x43, 0x0e, 0xe0, 0x86, 0x3c, 0x6a, 0x5e, 0xdc, 0x99, 0x58, 0xdc, 0xf1, + 0x86, 0xc5, 0x1d, 0x6f, 0x59, 0xdc, 0x80, 0x2f, 0xa4, 0x92, 0x4f, 0x5d, 0x8c, 0xbe, 0xd4, 0xf9, 0xe4, 0x71, 0x7e, + 0xa4, 0xcb, 0xcf, 0x19, 0xce, 0x93, 0x99, 0x04, 0x60, 0x4b, 0xbc, 0x61, 0xae, 0x9a, 0xe6, 0x45, 0x9a, 0x88, 0xfa, + 0xc0, 0xf3, 0x53, 0x27, 0xc6, 0x0d, 0x29, 0xbc, 0xb5, 0xa0, 0x3a, 0x5e, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x1b, + 0x46, 0x3a, 0xdb, 0x32, 0xd2, 0x51, 0xe9, 0xe8, 0xf2, 0x61, 0xd3, 0x21, 0x94, 0x07, 0x05, 0x7b, 0x10, 0xfc, 0x2b, + 0x70, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x97, 0x24, 0xab, 0x28, 0x06, 0x03, 0x05, 0xe8, + 0xe6, 0x61, 0x5b, 0x6a, 0xee, 0x87, 0x3c, 0xf6, 0xd9, 0xc6, 0xcd, 0x54, 0xbc, 0x97, 0xb7, 0x54, 0xeb, 0xf0, 0x90, + 0x6a, 0x2c, 0xbc, 0x34, 0x65, 0x31, 0x4e, 0xba, 0x07, 0x49, 0x32, 0xfe, 0x4b, 0xb6, 0x59, 0x03, 0x0e, 0x09, 0x24, + 0xac, 0x8e, 0x18, 0x7a, 0x01, 0x2c, 0x18, 0x69, 0x24, 0x43, 0x7d, 0x2d, 0xc5, 0x51, 0x8d, 0xf3, 0x89, 0xff, 0x11, + 0x8f, 0xab, 0x16, 0x4b, 0x9e, 0xbe, 0xce, 0x91, 0x6e, 0x2d, 0xbc, 0xf1, 0x7b, 0xb0, 0x83, 0xd1, 0x5a, 0x06, 0xf8, + 0xb4, 0xc8, 0x51, 0x53, 0x63, 0xe2, 0x09, 0x47, 0x05, 0x92, 0x44, 0x2c, 0xc9, 0x2d, 0x86, 0x21, 0xd8, 0x80, 0x67, + 0x4e, 0xae, 0xd6, 0xad, 0x6c, 0x7f, 0xea, 0xeb, 0x35, 0xac, 0x09, 0xa8, 0x2d, 0x70, 0xfb, 0xb9, 0xd0, 0x2d, 0x30, + 0x9c, 0x23, 0x1d, 0x14, 0xa5, 0x97, 0x90, 0x0e, 0xdd, 0x16, 0x97, 0xe9, 0x41, 0x0c, 0x54, 0x0b, 0xd4, 0x8a, 0x4f, + 0xa6, 0xf8, 0xcb, 0xb9, 0xca, 0x9e, 0x0c, 0xf1, 0x57, 0xeb, 0x2a, 0x57, 0x62, 0x55, 0xa4, 0x08, 0xd2, 0x98, 0xd5, + 0x7e, 0x69, 0x3f, 0x91, 0xb9, 0xf6, 0x03, 0xb6, 0x0d, 0x5f, 0xe0, 0x47, 0x8f, 0xd7, 0x09, 0x04, 0x28, 0x90, 0xc7, + 0x10, 0x5a, 0xb1, 0x9e, 0x35, 0x96, 0x4f, 0x37, 0x94, 0x0f, 0xf5, 0xdf, 0x99, 0xf0, 0xe3, 0x2e, 0x89, 0x0a, 0x9a, + 0x52, 0x96, 0x81, 0x5c, 0x0f, 0xfd, 0xd0, 0x8b, 0xef, 0xae, 0xe9, 0x16, 0xa2, 0x09, 0x16, 0x3f, 0x97, 0xed, 0x10, + 0x2f, 0x5a, 0xb6, 0x0e, 0x49, 0x25, 0x45, 0xd5, 0x1d, 0x27, 0xf4, 0xee, 0x9f, 0x62, 0x89, 0xbf, 0x2b, 0x5d, 0x63, + 0xf9, 0x82, 0x94, 0x3e, 0x74, 0xfd, 0x78, 0xad, 0xb1, 0x7a, 0x37, 0x95, 0xd1, 0x56, 0x18, 0x48, 0x58, 0x1e, 0xbc, + 0x12, 0xcf, 0xc7, 0x7e, 0x17, 0xcd, 0x3f, 0x86, 0xd1, 0xad, 0xf9, 0x78, 0x9d, 0x9e, 0xaa, 0x73, 0x2f, 0xfe, 0xc8, + 0xc6, 0xe6, 0xc8, 0x8f, 0x47, 0x01, 0x30, 0x8f, 0xc3, 0xc0, 0x0b, 0x3f, 0xf2, 0x47, 0x33, 0x5a, 0xa6, 0x68, 0xd0, + 0x75, 0xef, 0x0d, 0x5a, 0xcc, 0x09, 0x09, 0x12, 0x91, 0xab, 0x6d, 0x98, 0x05, 0xe5, 0xfd, 0x40, 0x5c, 0xeb, 0x0b, + 0x46, 0xb1, 0xa8, 0x65, 0x80, 0x3f, 0x02, 0xd8, 0x98, 0x41, 0x80, 0x07, 0x43, 0xc5, 0xf5, 0x52, 0x0d, 0x79, 0xa8, + 0xa4, 0x55, 0xcb, 0x33, 0x14, 0x5f, 0x63, 0x0f, 0xbf, 0xfe, 0x73, 0x50, 0xf2, 0x90, 0xcf, 0xe5, 0xbd, 0x7c, 0xde, + 0x08, 0xa1, 0xd4, 0x24, 0xc7, 0xc2, 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0x2d, 0x37, 0xf6, 0x92, 0x64, 0x39, + 0x67, 0x63, 0x52, 0x89, 0x9d, 0x16, 0x40, 0x95, 0xef, 0x21, 0x32, 0x60, 0x7f, 0x5f, 0xb6, 0x8e, 0x0f, 0x5e, 0x81, + 0x81, 0x1f, 0x30, 0x94, 0xd1, 0x64, 0xa2, 0x16, 0xa2, 0x80, 0x7b, 0x9a, 0x39, 0x07, 0x7f, 0x5f, 0xbe, 0x39, 0xb3, + 0xdf, 0xe4, 0x8d, 0x43, 0x60, 0x8c, 0x85, 0xb5, 0x12, 0xe7, 0x8b, 0x25, 0x78, 0xc5, 0x88, 0x26, 0x5e, 0xb8, 0x79, + 0x38, 0x97, 0xa5, 0x2d, 0xbe, 0x60, 0x6c, 0x0c, 0x0c, 0xb7, 0x51, 0x2b, 0xbd, 0x0e, 0xd8, 0x0d, 0xcb, 0x2d, 0xa1, + 0xea, 0x1f, 0x6b, 0x68, 0x81, 0xa1, 0x5a, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0x06, 0x38, 0x06, 0x3e, 0x72, + 0xf9, 0x88, 0x55, 0x8e, 0xd4, 0xc0, 0x50, 0x25, 0x00, 0x36, 0x42, 0x76, 0xba, 0xa1, 0xbc, 0x0b, 0x88, 0x7a, 0x03, + 0x6c, 0x86, 0xa3, 0x77, 0x21, 0xb5, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0x36, 0xcd, 0x58, 0x93, + 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x0e, 0x40, 0x2f, 0x19, 0x21, 0xae, 0x6a, 0x5c, 0x1b, 0xa5, 0x3c, 0xf2, 0x21, + 0x26, 0x7e, 0x0f, 0x59, 0x92, 0x6c, 0x9c, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, 0xa2, 0xdc, 0xb0, + 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x9e, 0x73, 0xf3, 0xce, 0x78, 0x3a, 0x54, 0xb9, 0xe9, + 0xdd, 0xa6, 0xf7, 0x2b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0x8d, 0xa0, 0x69, 0x25, 0xd4, 0x5b, 0x93, 0x2a, 0x61, 0x07, + 0x02, 0xa6, 0x0a, 0x7e, 0x65, 0x93, 0x09, 0x1b, 0xa5, 0x89, 0x2e, 0x64, 0x4c, 0x79, 0xb0, 0x75, 0x70, 0xb2, 0xdd, + 0x73, 0xd5, 0x1f, 0x21, 0xe4, 0x8c, 0x88, 0x49, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xe6, 0x69, 0xa2, 0x1e, 0xcb, 0x53, + 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x86, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0x11, 0xe8, 0x76, 0x54, + 0xb4, 0xed, 0xf8, 0xae, 0x9d, 0x37, 0x87, 0x8e, 0x9d, 0xa9, 0x06, 0xb8, 0x3a, 0x7f, 0xac, 0x6c, 0x63, 0x22, 0x50, + 0xae, 0x7a, 0xfe, 0xf6, 0xd5, 0x9f, 0xce, 0x5e, 0xef, 0x8a, 0x11, 0xb0, 0xcb, 0x36, 0x74, 0xb9, 0x0c, 0xb7, 0x74, + 0xfa, 0xf3, 0x8f, 0x0f, 0xeb, 0xb6, 0xe5, 0xbc, 0x70, 0x54, 0x83, 0xac, 0xd3, 0x25, 0xbc, 0x38, 0x8a, 0x6e, 0x58, + 0xfc, 0xd9, 0xd3, 0x20, 0x77, 0xde, 0x0c, 0xee, 0xdb, 0x9f, 0xce, 0x7e, 0xdc, 0x19, 0xd4, 0x23, 0xc7, 0x06, 0xdc, + 0x9e, 0x46, 0x8b, 0x07, 0x8c, 0xae, 0xad, 0x1a, 0xea, 0x28, 0x88, 0x12, 0xb6, 0x01, 0x82, 0x57, 0xe7, 0x6f, 0xdf, + 0xe3, 0x74, 0x15, 0x2c, 0x08, 0x75, 0xf5, 0x79, 0x83, 0xff, 0xe9, 0xdd, 0xd9, 0xfb, 0xf7, 0xaa, 0x81, 0xc9, 0xba, + 0x13, 0xb9, 0x77, 0xbe, 0x89, 0xef, 0xa1, 0x38, 0x8d, 0x7b, 0x9d, 0xa8, 0x1a, 0x5d, 0xa4, 0xcb, 0xa3, 0xa1, 0xb2, + 0xda, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x3b, 0x8d, 0xab, 0x01, 0x1f, 0x6d, 0x27, 0xa9, 0xa5, 0x92, + 0xb9, 0x1f, 0x5e, 0x37, 0x94, 0x7a, 0xb7, 0x0d, 0xa5, 0x70, 0x7d, 0xac, 0xe1, 0xc7, 0x65, 0x34, 0x97, 0xd8, 0x11, + 0x76, 0x7b, 0xff, 0x74, 0x49, 0x77, 0xb8, 0xcf, 0x00, 0x9a, 0x27, 0x5b, 0xa9, 0x42, 0xdd, 0x50, 0xcc, 0x2f, 0x5e, + 0xf9, 0xdc, 0x8e, 0x02, 0xb0, 0xc9, 0x67, 0xb2, 0x1a, 0xb2, 0xcc, 0xaa, 0x72, 0x8f, 0x1a, 0xb7, 0x72, 0x2b, 0xa0, + 0x66, 0xa4, 0xba, 0xe1, 0x34, 0x65, 0xe1, 0x8d, 0xc1, 0xd0, 0xdd, 0x1c, 0x46, 0x69, 0x1a, 0xcd, 0xbb, 0x8e, 0xbd, + 0xb8, 0x55, 0x95, 0x9e, 0x10, 0x76, 0x70, 0x3b, 0xfc, 0xee, 0xbf, 0xff, 0x55, 0x41, 0xf3, 0x54, 0x7e, 0x9d, 0xb2, + 0xf9, 0x82, 0xc5, 0x5e, 0xba, 0x8c, 0x59, 0xa6, 0xfc, 0xfb, 0x7f, 0x5e, 0x55, 0x2e, 0xf6, 0x3d, 0xb9, 0x0d, 0xb1, + 0xf4, 0x72, 0x93, 0xeb, 0x20, 0x5a, 0xed, 0x15, 0x1e, 0x77, 0xf7, 0x54, 0x9e, 0xf9, 0xd3, 0x59, 0x5e, 0xfb, 0x34, + 0xdd, 0x32, 0x36, 0x01, 0x3d, 0xe9, 0x03, 0x94, 0xf3, 0x68, 0xd5, 0xfd, 0xf7, 0xbf, 0x72, 0x81, 0xcd, 0xbd, 0xbb, + 0xae, 0x19, 0xd0, 0xf2, 0x8a, 0x36, 0xd7, 0xa9, 0x2d, 0x31, 0xbc, 0xaf, 0x2d, 0x70, 0xad, 0x90, 0x76, 0x65, 0x5d, + 0x37, 0xb7, 0x65, 0x4c, 0xdf, 0xf9, 0xd3, 0xd9, 0xe7, 0x0e, 0x0a, 0x26, 0xf4, 0xde, 0x51, 0x41, 0xa5, 0x2f, 0x30, + 0xac, 0x41, 0x77, 0xf7, 0x05, 0xfb, 0xcc, 0x71, 0xdd, 0x37, 0xa4, 0x2f, 0x31, 0x1a, 0x2e, 0xb9, 0x7d, 0x3f, 0x18, + 0xe4, 0xc9, 0x6a, 0xe5, 0xf6, 0xe0, 0x33, 0x78, 0x5a, 0x2b, 0xe1, 0xec, 0x45, 0xd7, 0xd6, 0x29, 0x98, 0xcf, 0x0e, + 0x13, 0x82, 0xd6, 0xef, 0x0d, 0xd3, 0xb1, 0x19, 0x5f, 0x93, 0x13, 0x5b, 0xed, 0xdb, 0x35, 0x64, 0x0d, 0xa5, 0x98, + 0xe8, 0x34, 0xd7, 0x1a, 0x1a, 0xcd, 0xe0, 0xac, 0x62, 0x6f, 0x41, 0x4a, 0x02, 0x05, 0x35, 0x26, 0x20, 0x74, 0xa9, + 0xdc, 0xa2, 0x6f, 0xbc, 0xe0, 0x66, 0xb7, 0x0b, 0xd5, 0x66, 0x0a, 0x86, 0xa4, 0xf9, 0x3f, 0x47, 0xbc, 0x91, 0x2e, + 0x3f, 0x98, 0x76, 0xaf, 0xbc, 0x94, 0xc5, 0xd7, 0x33, 0xf0, 0xf6, 0x15, 0xd2, 0x03, 0x88, 0xa3, 0xbb, 0x0d, 0x29, + 0x97, 0xd8, 0xd2, 0x06, 0x34, 0x5a, 0x60, 0xb8, 0x5f, 0x87, 0xbb, 0xbf, 0x10, 0xe6, 0xee, 0x9e, 0x81, 0x3f, 0xe6, + 0x6f, 0x86, 0xbd, 0xb7, 0x51, 0xa6, 0xff, 0xc7, 0xde, 0xff, 0x8d, 0xd8, 0x7b, 0xeb, 0x77, 0x7e, 0xcd, 0xc2, 0xfe, + 0x1f, 0xc0, 0xf2, 0x5d, 0xe6, 0x9e, 0x71, 0x4c, 0xaf, 0x69, 0x9e, 0xab, 0xc5, 0xa5, 0xc3, 0x8b, 0x78, 0xb5, 0xa6, + 0x60, 0xe5, 0xc1, 0xd6, 0xb8, 0xe5, 0xa0, 0x87, 0xc8, 0x7e, 0xcb, 0x51, 0xfe, 0xed, 0x11, 0x7d, 0x42, 0x19, 0xaa, + 0x24, 0x4c, 0xdf, 0x3d, 0x33, 0x92, 0xd2, 0x48, 0xbc, 0x95, 0x77, 0xb7, 0x0b, 0xde, 0x11, 0xc0, 0x7e, 0xb3, 0xf2, + 0xee, 0x9a, 0x80, 0xdd, 0x88, 0x5e, 0xab, 0x1f, 0x3b, 0x05, 0x2f, 0x9f, 0x2e, 0xba, 0xf8, 0x18, 0x83, 0x84, 0xa5, + 0xa7, 0x50, 0xe8, 0x3e, 0x5e, 0xef, 0x55, 0x2b, 0x66, 0x03, 0xf0, 0x7f, 0x96, 0x00, 0x8f, 0x4a, 0x80, 0xfb, 0xc9, + 0x75, 0x14, 0x3e, 0x04, 0xf2, 0x9f, 0x40, 0xf8, 0xf3, 0xab, 0x41, 0xc7, 0xcf, 0xd5, 0x60, 0xc7, 0xd2, 0x2a, 0xf0, + 0x58, 0x58, 0x85, 0xbe, 0xd7, 0x2c, 0xab, 0xaf, 0x10, 0x5a, 0xa4, 0xb1, 0x8c, 0x08, 0xad, 0x02, 0x7a, 0x15, 0x05, + 0x74, 0x5c, 0x15, 0x92, 0xeb, 0x87, 0x93, 0xd8, 0x8b, 0xd9, 0x78, 0xf3, 0x15, 0xa0, 0x64, 0x9d, 0x7c, 0x67, 0x25, + 0xcb, 0xc5, 0x22, 0x8a, 0xd3, 0xe4, 0x1a, 0xe3, 0xb4, 0xcc, 0x7d, 0xb8, 0x50, 0x40, 0x46, 0xb1, 0x3c, 0x6a, 0xef, + 0x59, 0x93, 0x7c, 0xdb, 0x60, 0x6e, 0x39, 0xd9, 0x06, 0xf7, 0xbe, 0x31, 0xb8, 0xff, 0xce, 0x4c, 0xd2, 0x5f, 0xcc, + 0xac, 0x34, 0xf6, 0xe7, 0x9a, 0x6e, 0x38, 0xb6, 0xae, 0x0b, 0xf9, 0xca, 0xcc, 0xed, 0xef, 0x51, 0xb4, 0xe1, 0x99, + 0x0e, 0x51, 0x0b, 0xd1, 0xa3, 0x05, 0x6c, 0xe5, 0x5e, 0x2e, 0x27, 0x13, 0x16, 0x6b, 0x22, 0x2c, 0x23, 0xc4, 0x85, + 0x25, 0x63, 0x40, 0xf0, 0x73, 0xfc, 0xe0, 0xb3, 0x15, 0xe4, 0x7f, 0x2a, 0xc2, 0xaa, 0x83, 0xaf, 0x27, 0x99, 0x93, + 0x43, 0x6e, 0xb9, 0xb4, 0xdd, 0xd2, 0xc6, 0xcf, 0x0e, 0x8c, 0x19, 0x04, 0x63, 0x2a, 0xdc, 0xe3, 0x31, 0xce, 0x9f, + 0x1f, 0xa6, 0x1d, 0xfc, 0x02, 0x74, 0x00, 0x87, 0x37, 0x70, 0x73, 0xbf, 0x28, 0x65, 0x94, 0x77, 0x38, 0x73, 0xfb, + 0xc1, 0x73, 0x97, 0xf4, 0x3c, 0x68, 0xb7, 0xf7, 0x6a, 0xe6, 0xc5, 0xaf, 0xa2, 0x31, 0x43, 0x40, 0x87, 0x69, 0x04, + 0xde, 0x9a, 0x52, 0x18, 0x1e, 0x8c, 0xc2, 0x63, 0x96, 0x22, 0xf3, 0xec, 0x43, 0xd1, 0xb5, 0x5c, 0xe4, 0x3e, 0x7f, + 0xbc, 0x6f, 0xc0, 0x49, 0x6b, 0x5e, 0x69, 0xb1, 0x68, 0x7c, 0xa9, 0x1b, 0x5f, 0xc9, 0xbb, 0xf5, 0x95, 0x17, 0xc7, + 0x3e, 0x8b, 0x15, 0xed, 0xbb, 0x5f, 0x74, 0x79, 0xd3, 0x96, 0x14, 0x3a, 0x5c, 0xcb, 0xac, 0x60, 0x34, 0xba, 0x89, + 0xcf, 0x82, 0xb1, 0xab, 0x8e, 0xa8, 0x61, 0xae, 0xbc, 0x69, 0x77, 0x6c, 0xdb, 0xe6, 0x0a, 0x53, 0x87, 0x7e, 0x82, + 0xc2, 0x14, 0x7e, 0xc2, 0x43, 0x49, 0xbc, 0xd8, 0x21, 0x2e, 0xa2, 0x46, 0xce, 0x1a, 0x21, 0x7c, 0x47, 0xf1, 0x7c, + 0x1e, 0x02, 0x1b, 0x8f, 0xfb, 0x23, 0x40, 0x73, 0x04, 0x58, 0x05, 0x4c, 0x15, 0x80, 0x0e, 0x1f, 0x02, 0xd0, 0x85, + 0x3f, 0xf7, 0xc3, 0x69, 0xb2, 0x11, 0x22, 0x54, 0x9b, 0x96, 0xe0, 0x49, 0xa9, 0x85, 0xaa, 0xe0, 0x1a, 0xce, 0xa2, + 0x00, 0xf2, 0x10, 0xa9, 0xcc, 0x9a, 0x5a, 0xca, 0x0b, 0xdb, 0xb6, 0x0d, 0xf3, 0x00, 0x32, 0xfe, 0x1d, 0x1e, 0xd9, + 0x86, 0x09, 0x7f, 0x59, 0x96, 0xd5, 0x20, 0x8f, 0xed, 0xcd, 0xfd, 0xd0, 0xa4, 0xc7, 0x96, 0xbd, 0x1b, 0xbc, 0xf7, + 0x5a, 0xf5, 0x26, 0x5c, 0x37, 0x36, 0xcc, 0x5d, 0x47, 0xb5, 0xa1, 0x9b, 0x94, 0x6d, 0xdd, 0x2c, 0x0a, 0xb8, 0xc4, + 0xe3, 0x61, 0x54, 0x88, 0xd1, 0xb0, 0xfc, 0x16, 0xd9, 0xd2, 0xb8, 0x9a, 0xc7, 0x42, 0xfd, 0x9e, 0x83, 0xd5, 0x55, + 0x5e, 0x45, 0xcb, 0x60, 0x8c, 0xe6, 0x50, 0x60, 0xbb, 0xac, 0x14, 0x56, 0xa1, 0x95, 0x64, 0x53, 0x90, 0x4b, 0x1c, + 0x13, 0xad, 0xbd, 0x47, 0xe2, 0x14, 0xc5, 0xda, 0x53, 0x9c, 0xe2, 0xcb, 0xa6, 0x2d, 0x78, 0xf5, 0x14, 0xe2, 0x09, + 0xed, 0xd0, 0x80, 0xef, 0x0b, 0xa8, 0x1f, 0xec, 0x52, 0x5f, 0xac, 0xdb, 0xd5, 0x53, 0x0a, 0x3a, 0xeb, 0x7d, 0xfa, + 0xb4, 0x37, 0xfa, 0xf4, 0x69, 0xaf, 0x96, 0xa9, 0x63, 0xf3, 0x08, 0x69, 0x63, 0x30, 0x1e, 0x62, 0x04, 0xe2, 0x06, + 0x11, 0xd0, 0xdf, 0x43, 0x79, 0xd7, 0xe3, 0xd1, 0xaa, 0xe8, 0x69, 0x64, 0xf0, 0x0f, 0xd2, 0x63, 0x90, 0x55, 0x26, + 0x65, 0xe6, 0x7a, 0x24, 0xe6, 0xf9, 0xf4, 0x89, 0x1f, 0x37, 0x63, 0xec, 0x8e, 0xf2, 0x22, 0x47, 0x35, 0x96, 0x6e, + 0x90, 0x3f, 0xaa, 0x08, 0xf2, 0x92, 0x63, 0xcc, 0x02, 0xe2, 0x95, 0x17, 0x87, 0x32, 0xc0, 0x3f, 0x46, 0x0a, 0xff, + 0xac, 0xc2, 0x23, 0xa2, 0x8e, 0xab, 0xab, 0x31, 0x71, 0x99, 0xb6, 0x24, 0x1c, 0x28, 0x2c, 0xdd, 0xa4, 0x0e, 0x2e, + 0x04, 0xb6, 0xc7, 0xb4, 0xa8, 0x62, 0x80, 0xe8, 0x5f, 0x8d, 0x27, 0x77, 0x2c, 0x86, 0xf5, 0xce, 0x5b, 0x75, 0x97, + 0xe2, 0xe1, 0x8c, 0x4c, 0xe2, 0xbb, 0x93, 0xdc, 0x6f, 0x79, 0x41, 0x5e, 0x87, 0x53, 0xf7, 0xdb, 0x58, 0x5b, 0x18, + 0xa9, 0xa1, 0x0a, 0x32, 0xa2, 0xea, 0xc6, 0xbc, 0x29, 0xc0, 0x6a, 0x6f, 0xce, 0xc3, 0xcd, 0x68, 0x62, 0x2b, 0x5c, + 0x4f, 0xd0, 0x57, 0x21, 0x1c, 0xdd, 0x61, 0x00, 0xe5, 0xe2, 0x3d, 0x81, 0x72, 0xcd, 0xb3, 0xef, 0x8d, 0xe5, 0x57, + 0xb0, 0xe0, 0xaa, 0x31, 0xd1, 0x0d, 0xf2, 0x01, 0x98, 0x7e, 0x49, 0x73, 0x7f, 0x8a, 0xa9, 0x3c, 0x97, 0xc2, 0xbd, + 0x0a, 0x07, 0x80, 0xeb, 0x8a, 0x03, 0x40, 0xc3, 0x7c, 0x2a, 0x31, 0x4b, 0x16, 0x51, 0x08, 0x77, 0xc5, 0xeb, 0xc2, + 0xc3, 0xeb, 0xba, 0xee, 0xe1, 0xd5, 0xd0, 0x14, 0xdf, 0x50, 0x3b, 0x50, 0x49, 0x5f, 0xfc, 0xa5, 0x62, 0xa1, 0x2f, + 0x48, 0x3d, 0x66, 0x29, 0x3f, 0xdb, 0xe4, 0xd9, 0xfd, 0xfd, 0xfd, 0x9e, 0xdd, 0xe7, 0x3b, 0x79, 0x76, 0x7f, 0xff, + 0xc5, 0x3d, 0xbb, 0xcf, 0x64, 0xcf, 0x6e, 0x20, 0xc1, 0x67, 0x6c, 0x27, 0x47, 0x5a, 0xe1, 0xd2, 0x12, 0xad, 0x12, + 0xd7, 0xe1, 0x9a, 0xb5, 0x64, 0x34, 0x63, 0x60, 0xaa, 0xc0, 0x59, 0xdd, 0x20, 0x9a, 0x82, 0xbf, 0xeb, 0x66, 0x8f, + 0xd6, 0x2f, 0xe5, 0xcf, 0x1a, 0x44, 0x53, 0x55, 0xca, 0xd3, 0x16, 0x8a, 0x3c, 0x6d, 0x10, 0x9b, 0xee, 0xef, 0xb7, + 0xce, 0xcb, 0x4b, 0xa7, 0xd7, 0x76, 0x20, 0xce, 0x29, 0x68, 0x9f, 0xb1, 0xc0, 0xee, 0xb5, 0xdb, 0x50, 0xb0, 0x92, + 0x0a, 0x5a, 0x50, 0xe0, 0x4b, 0x05, 0x87, 0x50, 0x30, 0x92, 0x0a, 0x8e, 0xa0, 0x60, 0x2c, 0x15, 0x1c, 0x43, 0xc1, + 0x8d, 0x9a, 0x5d, 0x86, 0xb9, 0xdf, 0xfa, 0xb1, 0x7e, 0x55, 0x4a, 0xd1, 0x99, 0x9b, 0x4a, 0x88, 0x2a, 0xc7, 0x86, + 0xc8, 0x17, 0x61, 0x1e, 0xe8, 0x9c, 0x47, 0x1b, 0x7c, 0x35, 0x00, 0xcc, 0x0b, 0x96, 0x23, 0x06, 0xd8, 0xdd, 0x50, + 0xcd, 0xb6, 0x78, 0xad, 0x76, 0x73, 0x3f, 0x6f, 0xdb, 0x68, 0x09, 0xbf, 0xe9, 0x2e, 0x46, 0xf1, 0x10, 0x95, 0x0f, + 0x9f, 0xcf, 0xf2, 0xe0, 0xd1, 0x4b, 0xb7, 0x08, 0x86, 0xd3, 0x86, 0x14, 0x3a, 0x9c, 0x57, 0x63, 0x1a, 0xd8, 0xcb, + 0x40, 0xac, 0x13, 0x71, 0x8a, 0xc4, 0x07, 0x14, 0x74, 0x86, 0xef, 0x79, 0x05, 0x0f, 0xc7, 0x43, 0xad, 0x13, 0xf4, + 0xf3, 0x3c, 0x82, 0x35, 0xe9, 0x52, 0x97, 0x46, 0xea, 0x4d, 0xbb, 0x33, 0x83, 0x0c, 0xa9, 0xba, 0x53, 0x48, 0x49, + 0x72, 0x3a, 0xee, 0x2e, 0x8c, 0xd5, 0x8c, 0x85, 0xdd, 0x09, 0x77, 0x3b, 0x84, 0xf5, 0x27, 0x4f, 0x92, 0xb9, 0x2e, + 0x5c, 0xa0, 0x70, 0x4f, 0x14, 0x6f, 0x09, 0x4a, 0x33, 0xdf, 0x4a, 0x85, 0xf7, 0x8e, 0x26, 0x1b, 0x59, 0x7d, 0x09, + 0x5f, 0x8b, 0xd7, 0x6c, 0xb8, 0x9c, 0x2a, 0xe7, 0xd1, 0xf4, 0x5e, 0xbf, 0x0a, 0xf9, 0x15, 0x40, 0xa9, 0x92, 0x35, + 0xa9, 0x29, 0xb6, 0x37, 0xff, 0x16, 0x3d, 0x66, 0xe5, 0xfa, 0x29, 0xc0, 0xa6, 0xa4, 0xc4, 0x36, 0xc0, 0x77, 0x60, + 0xb6, 0x25, 0xcf, 0x85, 0x73, 0x98, 0x3f, 0xe9, 0xf9, 0xc2, 0x93, 0xe0, 0xe9, 0xff, 0xc0, 0x92, 0xc4, 0x9b, 0x32, + 0x19, 0xb5, 0x94, 0x3a, 0x07, 0x2c, 0x98, 0xab, 0x93, 0x71, 0x02, 0x81, 0xb1, 0xf7, 0x6b, 0xfe, 0x28, 0xe0, 0x32, + 0x0b, 0x7e, 0x5a, 0xb0, 0x68, 0x85, 0xf3, 0x86, 0x6f, 0xc1, 0xf2, 0x94, 0xfd, 0x28, 0x00, 0x89, 0xdc, 0xb0, 0xa0, + 0x5a, 0x98, 0x7a, 0xd3, 0x6a, 0x11, 0xad, 0x75, 0x56, 0x42, 0x7b, 0x7a, 0xe9, 0x51, 0xe0, 0xc2, 0xcf, 0xb0, 0xcb, + 0x0f, 0xa2, 0xe9, 0x6f, 0x6a, 0x94, 0xbf, 0xc5, 0x99, 0xe2, 0x87, 0xd0, 0x08, 0xd3, 0x81, 0x85, 0x73, 0xac, 0x58, + 0x30, 0x85, 0xdd, 0x30, 0x9d, 0x99, 0x18, 0x58, 0x4e, 0x6b, 0x85, 0xba, 0x61, 0xe1, 0xda, 0xae, 0xab, 0xe1, 0x34, + 0xbb, 0xf1, 0x74, 0xe8, 0x69, 0x4e, 0xeb, 0xd8, 0x10, 0x7f, 0x2c, 0xfb, 0x50, 0xcf, 0xb0, 0x07, 0x65, 0xec, 0xdf, + 0xac, 0x27, 0x51, 0x98, 0x9a, 0x13, 0x6f, 0xee, 0x07, 0x77, 0xdd, 0x79, 0x14, 0x46, 0xc9, 0xc2, 0x1b, 0xb1, 0x9e, + 0xc4, 0x8f, 0x62, 0xa0, 0x66, 0x1e, 0x2b, 0xd0, 0xb1, 0x5a, 0x31, 0x9b, 0x53, 0xeb, 0x3c, 0x0e, 0xf3, 0x24, 0x60, + 0xb7, 0x19, 0xff, 0x7c, 0xa9, 0x32, 0x55, 0xc5, 0x2d, 0x47, 0x2d, 0x80, 0x65, 0xe6, 0x41, 0x9e, 0x21, 0xb5, 0x41, + 0x8f, 0x4b, 0x1d, 0xbb, 0x56, 0xeb, 0x30, 0x66, 0x73, 0xc5, 0x3a, 0xdc, 0xd8, 0x79, 0x1c, 0xad, 0xfa, 0x00, 0x2d, + 0x36, 0x36, 0x13, 0x16, 0x4c, 0xf0, 0x8d, 0x89, 0x71, 0xa5, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, 0x6c, 0xde, + 0x83, 0xd7, 0xdd, 0x96, 0x62, 0x4b, 0xfc, 0xf4, 0xb1, 0xbd, 0x90, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, 0x75, 0x47, + 0xb1, 0x7b, 0xa0, 0x3f, 0x9e, 0x04, 0xd1, 0xaa, 0x3b, 0xf3, 0xc7, 0x63, 0x16, 0xf6, 0x10, 0xe6, 0xbc, 0x90, 0x05, + 0x81, 0xbf, 0x48, 0xfc, 0xa4, 0x37, 0xf7, 0x6e, 0x79, 0xaf, 0x07, 0x9b, 0x7a, 0x6d, 0xf3, 0x5e, 0xdb, 0x3b, 0xf7, + 0x2a, 0x75, 0x03, 0x31, 0xac, 0xa8, 0x1f, 0x0e, 0xda, 0xa1, 0x62, 0x57, 0xc6, 0xb9, 0x73, 0xaf, 0x8b, 0x98, 0xad, + 0xe7, 0x5e, 0x3c, 0xf5, 0xc3, 0xae, 0x9d, 0x59, 0x37, 0x6b, 0xda, 0x18, 0x8f, 0x3a, 0x9d, 0x4e, 0x66, 0x8d, 0xc5, + 0x93, 0x3d, 0x1e, 0x67, 0xd6, 0x48, 0x3c, 0x4d, 0x26, 0xb6, 0x3d, 0x99, 0x64, 0x96, 0x2f, 0x0a, 0xda, 0xad, 0xd1, + 0xb8, 0xdd, 0xca, 0xac, 0x95, 0x54, 0x23, 0xb3, 0x18, 0x7f, 0x8a, 0xd9, 0xb8, 0x87, 0x1b, 0x89, 0xfb, 0x3f, 0x1f, + 0xdb, 0x76, 0x86, 0x18, 0xe0, 0xb2, 0x84, 0x9b, 0xd0, 0x74, 0xe5, 0x6a, 0xbd, 0x73, 0x4d, 0xa5, 0xf8, 0xdc, 0x68, + 0xd4, 0x58, 0x6f, 0xec, 0xc5, 0x1f, 0xaf, 0x14, 0x69, 0x14, 0x9e, 0x47, 0xd5, 0xd6, 0x62, 0x1a, 0xcc, 0xdb, 0x2e, + 0x24, 0xec, 0xe8, 0x0d, 0xa3, 0x18, 0xce, 0x6c, 0xec, 0x8d, 0xfd, 0x65, 0xd2, 0x75, 0x5a, 0x8b, 0x5b, 0x51, 0xc4, + 0xf7, 0x7a, 0x51, 0x80, 0x67, 0xaf, 0x9b, 0x44, 0x81, 0x3f, 0x16, 0x45, 0x9b, 0xce, 0x92, 0xd3, 0xd2, 0x7b, 0xc8, + 0xbf, 0xfa, 0x18, 0x74, 0xd9, 0x0b, 0x02, 0xc5, 0x6a, 0x27, 0x0a, 0xf3, 0x12, 0x34, 0x97, 0x53, 0xec, 0x84, 0xe6, + 0x05, 0x43, 0xd3, 0x3a, 0x07, 0x8b, 0xdb, 0x7c, 0xcf, 0x3b, 0x47, 0x8b, 0xdb, 0xec, 0xeb, 0x39, 0x1b, 0xfb, 0x9e, + 0xa2, 0x15, 0xbb, 0xc9, 0xb1, 0xc1, 0xa4, 0x4e, 0x5f, 0x6f, 0xd8, 0xa6, 0xe2, 0x58, 0x40, 0x62, 0xa3, 0x3d, 0x7f, + 0x0e, 0x72, 0x18, 0x2f, 0x4c, 0xb3, 0x6c, 0x70, 0x95, 0x65, 0xbd, 0x73, 0x5f, 0xbb, 0xfc, 0xab, 0x46, 0xb4, 0x90, + 0x4c, 0x50, 0x33, 0xfd, 0xca, 0x38, 0x63, 0xb2, 0xbb, 0x0c, 0x90, 0x31, 0x74, 0x95, 0x91, 0x2b, 0x13, 0xbd, 0xad, + 0x57, 0xa6, 0x49, 0xce, 0xab, 0x93, 0xf7, 0x4d, 0xb9, 0x0a, 0x52, 0x20, 0xa8, 0x70, 0xc6, 0xdc, 0x73, 0xc9, 0xf7, + 0x06, 0x98, 0x1e, 0xac, 0x4c, 0x51, 0x85, 0x5e, 0x6f, 0xe2, 0x3d, 0x2f, 0xee, 0xe7, 0x3d, 0xff, 0x96, 0xee, 0xc2, + 0x7b, 0x5e, 0x7c, 0x71, 0xde, 0xf3, 0x75, 0x3d, 0xaa, 0xd0, 0x45, 0xe4, 0xaa, 0xb9, 0xc1, 0x24, 0x90, 0xa6, 0x98, + 0xe2, 0xf5, 0xbf, 0x4e, 0x7f, 0x6d, 0x78, 0x17, 0xd1, 0x1b, 0x12, 0x05, 0xce, 0xa7, 0x82, 0x98, 0xf5, 0x6d, 0xe8, + 0xfe, 0x29, 0x96, 0x9f, 0x27, 0x13, 0xf7, 0x75, 0x24, 0x15, 0xe4, 0x4f, 0xdc, 0x97, 0xa4, 0x14, 0x5b, 0x99, 0xde, + 0xe4, 0xde, 0x3e, 0x90, 0x7d, 0x1a, 0x42, 0xb3, 0x92, 0x6b, 0xf7, 0x38, 0xf7, 0xb9, 0xeb, 0x95, 0x41, 0xd0, 0x72, + 0x27, 0x57, 0x11, 0x80, 0xab, 0x66, 0x19, 0x35, 0x65, 0x42, 0x06, 0xf0, 0xf2, 0xee, 0xfb, 0xb1, 0x76, 0x11, 0xe9, + 0x99, 0x9f, 0xbc, 0xad, 0x86, 0xbf, 0x12, 0x7a, 0x2e, 0x79, 0x38, 0x19, 0xf7, 0x9b, 0x93, 0xa2, 0xdc, 0xe2, 0x6b, + 0x6a, 0x7e, 0x5a, 0x1a, 0x69, 0x57, 0x6e, 0xd8, 0xa3, 0x98, 0xdf, 0x35, 0x62, 0xcc, 0xc3, 0xc4, 0xac, 0x39, 0x97, + 0xb7, 0xc6, 0x67, 0x88, 0x1a, 0x3a, 0xa6, 0xe6, 0xfe, 0x38, 0xcb, 0xf4, 0x9e, 0x98, 0x08, 0x89, 0xd0, 0xb2, 0xfb, + 0x98, 0xb8, 0xa4, 0x10, 0x02, 0x71, 0x89, 0x0f, 0x59, 0x33, 0x5f, 0x80, 0x7f, 0x00, 0xb7, 0x7d, 0xe6, 0x73, 0xa6, + 0x2a, 0x34, 0x7d, 0xe4, 0x37, 0x22, 0x0d, 0x08, 0x0c, 0xda, 0x65, 0x6f, 0xab, 0xd2, 0x82, 0xd4, 0x1d, 0x5b, 0x69, + 0x72, 0xd0, 0xc1, 0x01, 0x62, 0xfc, 0x0a, 0xb1, 0x10, 0xa1, 0x1d, 0x5e, 0x07, 0x1f, 0x32, 0x35, 0xe7, 0xfd, 0x70, + 0xfb, 0xf5, 0x4f, 0xf6, 0xa1, 0x41, 0xbf, 0xa2, 0x74, 0xbb, 0xc7, 0x2f, 0x13, 0x58, 0x89, 0x64, 0x65, 0x58, 0xc9, + 0x4a, 0x79, 0xb6, 0x16, 0xf1, 0xb1, 0x53, 0x6f, 0x61, 0x82, 0x96, 0x07, 0x71, 0x2f, 0xc7, 0x78, 0x52, 0x28, 0xee, + 0xde, 0x32, 0x01, 0xdc, 0x88, 0x72, 0x14, 0xc4, 0x3f, 0xbd, 0xd1, 0x32, 0x4e, 0xa2, 0xb8, 0xbb, 0x88, 0xfc, 0x30, + 0x65, 0x71, 0x46, 0x82, 0x15, 0x9c, 0x1f, 0x31, 0x3d, 0x57, 0xeb, 0x68, 0xe1, 0x8d, 0xfc, 0xf4, 0xae, 0x6b, 0x73, + 0x96, 0xc2, 0xee, 0x71, 0xee, 0xc0, 0x6e, 0xac, 0xdf, 0xe5, 0xb3, 0xf9, 0x1c, 0x19, 0xbf, 0xb8, 0xce, 0xce, 0xc8, + 0xdb, 0xbc, 0x27, 0xbd, 0xa5, 0x08, 0xe1, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x05, 0x2c, 0x0f, 0x4b, 0x6d, 0x8f, 0xd9, + 0xd4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0x75, 0xa8, 0x2b, 0x76, 0x73, 0x31, 0x70, 0x3c, 0xfa, 0x2e, 0x90, + 0x75, 0xbd, 0x49, 0xca, 0x62, 0x63, 0x97, 0x9a, 0x43, 0x36, 0x89, 0x62, 0x46, 0xd9, 0xe4, 0x9c, 0xce, 0xe2, 0x76, + 0xf7, 0xee, 0xb7, 0x0f, 0xbf, 0xb9, 0x9f, 0x30, 0x4a, 0x35, 0xd1, 0x99, 0x7e, 0x4f, 0x6f, 0x75, 0x7a, 0x06, 0xac, + 0x21, 0xcd, 0xfc, 0x88, 0xa4, 0x20, 0x10, 0x09, 0xac, 0x31, 0x69, 0xc7, 0x22, 0xe2, 0x34, 0x2f, 0x66, 0x81, 0x97, + 0xfa, 0x37, 0x82, 0x67, 0x6c, 0x1f, 0x2d, 0x6e, 0xc5, 0x1a, 0x23, 0xc1, 0x7b, 0xc0, 0x22, 0x55, 0x40, 0x11, 0x8b, + 0x54, 0x2d, 0xc6, 0x45, 0xea, 0xd5, 0x46, 0x23, 0xe2, 0x58, 0x57, 0x28, 0xfd, 0xe1, 0xe2, 0x56, 0x26, 0xd1, 0x45, + 0xb3, 0x9c, 0x52, 0x57, 0x13, 0x90, 0xcc, 0xfd, 0xf1, 0x38, 0x60, 0x59, 0x69, 0xa1, 0xcb, 0x6b, 0x29, 0x4d, 0x4e, + 0x3e, 0x0f, 0xde, 0x30, 0x89, 0x82, 0x65, 0xca, 0x9a, 0xa7, 0x4b, 0x48, 0x74, 0x8b, 0xc9, 0xc1, 0xdf, 0x65, 0x58, + 0x0f, 0x81, 0xdd, 0x86, 0x6d, 0x62, 0xf7, 0x20, 0xdf, 0xa0, 0xd9, 0x2e, 0x83, 0x0e, 0xaf, 0x72, 0xa0, 0x8d, 0x86, + 0x81, 0x18, 0x40, 0x96, 0x08, 0x7b, 0x2b, 0x96, 0xc3, 0xcb, 0xf2, 0x9c, 0x6b, 0x79, 0x51, 0x56, 0x1e, 0xcc, 0x6f, + 0x73, 0xc6, 0x5e, 0x34, 0x9f, 0xb1, 0x17, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x8f, 0x26, 0x0e, 0xfc, 0xd7, 0x2b, 0x06, + 0xd4, 0xb5, 0x95, 0xf6, 0xe2, 0x56, 0x71, 0x16, 0xb7, 0x8a, 0xd9, 0x5a, 0xdc, 0x2a, 0xd8, 0x35, 0xba, 0xb7, 0x18, + 0x56, 0x4b, 0x37, 0x6c, 0x05, 0x0a, 0xe1, 0x8f, 0x5d, 0x7a, 0xe5, 0x1c, 0xc0, 0x3b, 0x68, 0x75, 0x58, 0x7f, 0xd7, + 0xda, 0x7e, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0xa9, 0x37, 0x1c, 0x82, 0x28, 0x33, 0x1a, 0x2d, 0x93, 0x7f, + 0x72, 0xf8, 0xf9, 0x24, 0x6e, 0x45, 0x04, 0x95, 0x7e, 0x44, 0x53, 0x50, 0x14, 0xde, 0x30, 0xd1, 0xc3, 0x3a, 0x5f, + 0xa7, 0x2e, 0x25, 0x47, 0x6c, 0x59, 0x07, 0x0d, 0x9b, 0xbc, 0x79, 0xa2, 0x7f, 0xb3, 0x55, 0xda, 0x8c, 0x62, 0x3e, + 0x63, 0x5a, 0xb6, 0x4e, 0xc7, 0xc3, 0x67, 0x83, 0xaf, 0xa6, 0xdd, 0x69, 0x06, 0xf7, 0x52, 0x7c, 0xe9, 0x4a, 0x10, + 0x15, 0x4e, 0xb7, 0x78, 0x28, 0x8e, 0xed, 0xbd, 0x6e, 0xda, 0x23, 0xb5, 0x5e, 0xb7, 0x10, 0x84, 0xa2, 0xee, 0x8e, + 0x58, 0xfe, 0xd1, 0x8b, 0x03, 0xf8, 0x8f, 0xb8, 0xfa, 0xbf, 0xa5, 0x4d, 0x8c, 0xfa, 0xeb, 0xb4, 0xc4, 0xa8, 0x13, + 0xab, 0x84, 0x8c, 0xf8, 0xee, 0xf5, 0x27, 0x93, 0x87, 0x35, 0xd8, 0xb9, 0x36, 0x79, 0x86, 0x55, 0x6b, 0xbf, 0x8c, + 0xa2, 0x80, 0x79, 0x61, 0xbd, 0xba, 0x98, 0x1e, 0x72, 0xf3, 0x4f, 0x5d, 0x68, 0x24, 0xee, 0x11, 0xe4, 0x94, 0xa0, + 0x62, 0x1b, 0xba, 0x4a, 0x9c, 0x6f, 0xba, 0x4a, 0xbc, 0xbb, 0xff, 0x2a, 0xf1, 0xc7, 0x9d, 0xae, 0x12, 0xef, 0xbe, + 0xf8, 0x55, 0xe2, 0xbc, 0x7e, 0x95, 0x38, 0x8f, 0x84, 0x3b, 0xb0, 0xf1, 0x66, 0xc9, 0x7f, 0x7e, 0x20, 0x7b, 0xdf, + 0x77, 0x91, 0x7b, 0x68, 0x53, 0xc2, 0xc3, 0x8b, 0x5f, 0x7d, 0xb1, 0xc0, 0x8d, 0xf8, 0x0e, 0xbd, 0xe3, 0x8a, 0xab, + 0x05, 0xc7, 0xec, 0xf8, 0x1d, 0xa9, 0x38, 0x88, 0xc2, 0xe9, 0x4f, 0x60, 0xef, 0x0d, 0xe2, 0xc0, 0x58, 0x7a, 0xe1, + 0x27, 0x3f, 0x45, 0x8b, 0xe5, 0x02, 0x15, 0x55, 0x1f, 0xfc, 0xc4, 0x1f, 0x06, 0x2c, 0x8f, 0x30, 0x49, 0x5a, 0x57, + 0x2e, 0x5b, 0x07, 0xc5, 0xab, 0xf8, 0xe9, 0xdd, 0x8a, 0x9f, 0xe8, 0x62, 0xcb, 0x7f, 0x93, 0x9b, 0xa0, 0xda, 0x7c, + 0x11, 0x11, 0x16, 0x62, 0x12, 0xd0, 0x0f, 0xbf, 0x8c, 0x9c, 0x8b, 0x58, 0x5e, 0xa5, 0x51, 0x0a, 0xf7, 0x8d, 0x8d, + 0xfd, 0xb0, 0x6a, 0x3f, 0x6f, 0x96, 0xba, 0x91, 0x27, 0xe0, 0xa8, 0x8b, 0xf3, 0xe7, 0xd1, 0x32, 0x61, 0xe3, 0x68, + 0x15, 0xaa, 0x46, 0xc8, 0xf5, 0xaa, 0x11, 0xca, 0xd4, 0xf3, 0x36, 0x65, 0x85, 0xa3, 0x6a, 0x2d, 0x60, 0x0e, 0x4d, + 0xd2, 0x60, 0x9b, 0x38, 0x44, 0x55, 0x84, 0x6c, 0xea, 0xed, 0x69, 0x5a, 0xe4, 0x3e, 0xac, 0xa5, 0xf0, 0x3c, 0x89, + 0x2c, 0x2e, 0x15, 0x4e, 0xb4, 0x50, 0x08, 0x17, 0x45, 0x14, 0xec, 0x86, 0x85, 0xe3, 0x6f, 0x28, 0x42, 0x64, 0xf1, + 0x16, 0x74, 0x55, 0xd9, 0x92, 0xaf, 0x07, 0x8f, 0x09, 0x4d, 0x8f, 0xaf, 0xa4, 0x69, 0x7c, 0x7b, 0xc3, 0xe2, 0xc0, + 0xbb, 0xd3, 0xf4, 0x2c, 0x0a, 0x7f, 0x80, 0x09, 0x78, 0x1d, 0xad, 0x42, 0xb9, 0x02, 0xa6, 0x6a, 0x6f, 0xd8, 0x4b, + 0x8d, 0xd1, 0xcb, 0x21, 0x66, 0x87, 0x04, 0x81, 0x6f, 0x2d, 0xbc, 0x29, 0xfb, 0x8b, 0x41, 0xff, 0xfe, 0x55, 0xcf, + 0x8c, 0x77, 0x51, 0xfe, 0xa1, 0x9f, 0x17, 0x3b, 0x7c, 0xe6, 0xc9, 0x93, 0xbd, 0xcd, 0xc3, 0xd6, 0x46, 0x01, 0xf3, + 0x62, 0x01, 0x45, 0x43, 0x6b, 0x7d, 0xe3, 0x29, 0x00, 0x28, 0x2e, 0xa2, 0xe5, 0x68, 0x86, 0x7e, 0xbb, 0x5f, 0x6e, + 0xbc, 0x29, 0xf4, 0xc9, 0x92, 0x4b, 0xfb, 0x2a, 0x1f, 0x7a, 0xa5, 0xa8, 0x98, 0x05, 0xfc, 0xfe, 0x19, 0xa4, 0xdf, + 0xfa, 0x0f, 0x4e, 0x43, 0x7d, 0xd7, 0xe4, 0x21, 0xbf, 0x1e, 0xb4, 0x79, 0x7b, 0x3e, 0x44, 0xe5, 0xa1, 0xc0, 0xd6, + 0x42, 0x49, 0xd7, 0x8c, 0x64, 0xb2, 0xea, 0xa4, 0xc9, 0x49, 0x64, 0x36, 0xe5, 0xc7, 0x11, 0x5f, 0x61, 0x56, 0xc9, + 0x6a, 0xc4, 0x60, 0x1c, 0x5b, 0x55, 0x90, 0x0c, 0xf7, 0xa6, 0x60, 0x88, 0xbe, 0xaa, 0xef, 0xe6, 0x7e, 0x68, 0x60, + 0x0e, 0xd8, 0xfa, 0x1b, 0xef, 0x16, 0xb2, 0x20, 0x02, 0x72, 0xab, 0xbe, 0x82, 0x42, 0x43, 0x8e, 0x16, 0xe4, 0x8d, + 0xc7, 0x9a, 0xda, 0x38, 0x13, 0x42, 0x1b, 0x38, 0xf8, 0x4a, 0x51, 0x14, 0x25, 0xbf, 0x46, 0x28, 0xf9, 0x3d, 0x02, + 0xcb, 0xf1, 0x3a, 0x00, 0xda, 0x92, 0x6c, 0x71, 0x4b, 0x25, 0x70, 0x33, 0x40, 0xfb, 0x69, 0x51, 0xc0, 0x13, 0xfd, + 0x80, 0x71, 0x0b, 0x15, 0x88, 0x0b, 0x3d, 0xa8, 0xbe, 0xbd, 0x18, 0xf2, 0x01, 0x76, 0x15, 0xbc, 0xb0, 0xe3, 0x5b, + 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, 0xf4, 0x58, 0x73, 0x46, 0x98, 0x50, 0xc2, 0x82, 0xa0, 0x75, 0xa8, 0x24, 0x78, + 0x34, 0x58, 0x03, 0x6e, 0xc4, 0x7b, 0xd1, 0x6d, 0x3a, 0x67, 0xe1, 0x52, 0x35, 0xc0, 0xea, 0x04, 0x33, 0xf4, 0x40, + 0x9d, 0xd7, 0xc4, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0x39, 0x23, 0x5a, 0x28, 0x4c, 0x55, 0x3c, 0x63, 0xc4, 0x03, 0xe0, + 0x24, 0x1c, 0xb7, 0x55, 0x29, 0x04, 0x5f, 0xd2, 0xa8, 0x8c, 0xcd, 0x79, 0xc8, 0x2b, 0xe4, 0x14, 0xc8, 0x46, 0x8c, + 0x8b, 0x8b, 0xc4, 0xb4, 0x6b, 0x5e, 0x75, 0xd1, 0x72, 0x8d, 0x8c, 0x57, 0x11, 0x14, 0xc5, 0x7a, 0xbd, 0x1b, 0x0e, + 0x27, 0xa4, 0x25, 0xd8, 0xd8, 0xcf, 0xa8, 0xd6, 0xcf, 0x86, 0x41, 0x7f, 0x64, 0x77, 0x44, 0x48, 0x68, 0xaa, 0x3e, + 0xb2, 0x3b, 0x30, 0x0e, 0x3f, 0x03, 0x69, 0x8a, 0xba, 0x05, 0x5d, 0x1b, 0x90, 0xe8, 0x77, 0x04, 0xa9, 0x2a, 0xb6, + 0x1c, 0x20, 0x3b, 0xdb, 0x82, 0xc5, 0x29, 0x1c, 0xa9, 0x91, 0xf4, 0xc4, 0x21, 0xe6, 0x11, 0x0b, 0xb4, 0xc6, 0x39, + 0x36, 0x1b, 0x8e, 0x86, 0xfe, 0xcc, 0xb1, 0xed, 0xfd, 0x5a, 0x7d, 0x10, 0x64, 0x37, 0xd5, 0xd6, 0x8d, 0xd4, 0x75, + 0x6c, 0xd3, 0x7f, 0x66, 0xb5, 0x7a, 0x35, 0x1a, 0x2d, 0x65, 0x92, 0x1a, 0xa0, 0xf8, 0xab, 0xff, 0x78, 0xad, 0xd5, + 0x0e, 0xa4, 0x5e, 0x8d, 0x00, 0x80, 0xb0, 0x65, 0x5c, 0xfe, 0x35, 0xa8, 0x93, 0x7e, 0xca, 0x63, 0x45, 0x59, 0xcd, + 0x07, 0x90, 0x0b, 0x51, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x41, 0x4f, 0x60, 0x14, + 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0xd6, 0x35, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, + 0xd8, 0xff, 0x06, 0xf2, 0x69, 0x0d, 0x21, 0xc6, 0x23, 0xd4, 0x80, 0xcc, 0xa9, 0xf7, 0x76, 0x08, 0xe1, 0x79, 0xe5, + 0xee, 0xca, 0x44, 0x72, 0xf7, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x99, 0xdc, 0x3d, 0xb0, 0x4b, 0x16, + 0x8e, 0xcb, 0x1d, 0x56, 0xe8, 0xd7, 0xee, 0xdd, 0x95, 0x30, 0x0a, 0xa4, 0x14, 0x8e, 0x1a, 0x30, 0x4a, 0x16, 0x85, + 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x3b, 0x71, 0x31, 0xd8, 0x80, 0xf2, 0x81, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0xe4, 0xad, + 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0x37, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x89, 0x6a, 0x57, + 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, 0x98, + 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x1a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, 0xb7, + 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x5e, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, 0xbf, + 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, 0x24, + 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, 0x6f, + 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, 0xe7, + 0x36, 0x10, 0x08, 0x64, 0x43, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x2d, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, 0x49, + 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x24, 0x09, 0x42, 0xd7, 0x56, 0xec, 0x5e, 0x03, 0x03, 0x80, 0xf4, 0xbf, + 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xad, 0x7f, + 0x93, 0xe4, 0x3d, 0x6b, 0x1e, 0x13, 0xa4, 0x2c, 0xce, 0xe7, 0x35, 0xba, 0x02, 0x0e, 0xbe, 0xcb, 0xe2, 0x65, 0x88, + 0x49, 0x70, 0xcd, 0x34, 0xf6, 0x46, 0x1f, 0xd7, 0xd2, 0xf7, 0xb8, 0x48, 0x14, 0xc4, 0xc5, 0x65, 0xa5, 0x42, 0xcf, + 0xc3, 0x9c, 0x51, 0xac, 0x6b, 0xb5, 0x12, 0x49, 0x50, 0xd3, 0x7d, 0x64, 0xb7, 0xbd, 0x17, 0x93, 0x83, 0x8a, 0xfc, + 0xb4, 0x75, 0x58, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa3, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, 0x66, + 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x5a, 0xc9, 0x26, 0xb0, 0x26, 0x7e, 0x10, + 0x98, 0x01, 0xb8, 0x31, 0xac, 0x3f, 0x6b, 0x78, 0xd8, 0xcf, 0x12, 0xb2, 0x15, 0x7e, 0x46, 0x3f, 0xe5, 0x9d, 0x92, + 0xce, 0x96, 0xf3, 0xe1, 0x5a, 0x16, 0x94, 0x4b, 0xf2, 0xf3, 0xba, 0xcc, 0x5c, 0xfe, 0xec, 0x64, 0x32, 0x29, 0x4b, + 0x8d, 0x6d, 0xe5, 0x00, 0x25, 0xbf, 0x8f, 0x6c, 0xdb, 0xae, 0xce, 0xef, 0xa6, 0x83, 0x42, 0x07, 0xc3, 0x44, 0x21, + 0x7c, 0xe7, 0xfe, 0x3d, 0xf5, 0x3b, 0x41, 0x4b, 0x5d, 0x6d, 0x3a, 0x8f, 0xb4, 0xd5, 0xfe, 0x2b, 0x40, 0x41, 0xd4, + 0x70, 0xdf, 0xf1, 0xaf, 0xef, 0x95, 0x2d, 0x3d, 0x55, 0x0f, 0xf0, 0xc3, 0x1a, 0xdf, 0xb3, 0xd7, 0x77, 0x68, 0xba, + 0x69, 0x7b, 0x67, 0x56, 0x41, 0x76, 0x4b, 0x36, 0x4b, 0x3d, 0xb2, 0x54, 0xf2, 0x53, 0x36, 0x4f, 0xba, 0x23, 0x86, + 0x0a, 0x52, 0x4b, 0xa2, 0xb6, 0x68, 0xd5, 0x63, 0x4e, 0xc1, 0x8e, 0xcb, 0x11, 0x78, 0xd8, 0x56, 0x50, 0x59, 0x55, + 0xd3, 0xac, 0x89, 0x8f, 0x20, 0x15, 0x5b, 0xd7, 0x15, 0x4e, 0xb8, 0x4d, 0x0f, 0xed, 0x3f, 0x94, 0xea, 0x29, 0xc0, + 0x9d, 0xae, 0x85, 0xb5, 0x09, 0x29, 0x4f, 0xf0, 0xef, 0x5c, 0x39, 0xf7, 0x62, 0x71, 0x5b, 0x36, 0xee, 0xea, 0x80, + 0xba, 0xa9, 0x20, 0x65, 0x04, 0x75, 0x13, 0xea, 0xcb, 0x4d, 0x80, 0x26, 0xb2, 0x75, 0x0b, 0x58, 0xd0, 0x88, 0x29, + 0xa8, 0xe8, 0x08, 0x73, 0x50, 0xf1, 0x3a, 0x0b, 0x3b, 0xaf, 0x90, 0xef, 0xe3, 0x2f, 0xc8, 0x52, 0x0e, 0xe9, 0x4e, + 0xfe, 0x60, 0x3c, 0xef, 0xa0, 0x72, 0xaf, 0xb4, 0x55, 0xd1, 0x54, 0x06, 0xf7, 0x80, 0xb8, 0x91, 0x2a, 0xcb, 0x38, + 0x30, 0x29, 0x71, 0xbd, 0xa6, 0xaf, 0xeb, 0xe3, 0xde, 0xdc, 0xbd, 0x73, 0x08, 0x7a, 0x8d, 0xfa, 0x54, 0xed, 0xa4, + 0xda, 0xab, 0xea, 0xb0, 0x05, 0x9c, 0xb0, 0x02, 0xe0, 0x33, 0xab, 0xa0, 0xd1, 0x90, 0x52, 0xc1, 0x7d, 0x34, 0xe8, + 0xfc, 0xad, 0x8c, 0xac, 0xc5, 0x38, 0xb1, 0xbb, 0xe6, 0x2a, 0xd4, 0xb7, 0xd0, 0x0c, 0xc2, 0xdc, 0x71, 0xec, 0x84, + 0xcf, 0x26, 0xec, 0x18, 0x19, 0x5d, 0x39, 0xb8, 0x83, 0xf0, 0x94, 0x9a, 0x94, 0xfc, 0x84, 0x4e, 0x29, 0xea, 0x12, + 0xfe, 0xd8, 0x28, 0xbc, 0xbf, 0x28, 0x49, 0xe3, 0x79, 0xd0, 0x89, 0x96, 0xbe, 0x53, 0xed, 0xb9, 0x1f, 0xee, 0x5e, + 0xd7, 0xbb, 0xdd, 0xb9, 0x2e, 0x30, 0x87, 0x3b, 0x57, 0x06, 0xee, 0x12, 0x2b, 0x5f, 0xa4, 0xee, 0x1f, 0x25, 0xe5, + 0x81, 0x1c, 0x30, 0x51, 0xc5, 0x56, 0x74, 0xa3, 0xff, 0x71, 0xe9, 0x0e, 0x4e, 0x4e, 0x6f, 0xe7, 0x81, 0x72, 0xc3, + 0xe2, 0x04, 0x12, 0x4a, 0xa8, 0x8e, 0x65, 0xab, 0x0a, 0x1a, 0xf4, 0xfb, 0xe1, 0xd4, 0x55, 0x7f, 0xbe, 0x78, 0x63, + 0x76, 0xd4, 0x53, 0x30, 0xc7, 0xb8, 0x99, 0x22, 0x8b, 0x7b, 0xee, 0xdd, 0xb1, 0xf8, 0xba, 0xc5, 0x3d, 0x7e, 0x88, + 0xb9, 0xc5, 0x32, 0xa5, 0xa5, 0xee, 0x90, 0x12, 0x5e, 0xb9, 0xf1, 0xd9, 0xea, 0x65, 0x74, 0xeb, 0xaa, 0x80, 0x58, + 0x9d, 0x56, 0x47, 0x71, 0x5a, 0x07, 0xd6, 0x51, 0x47, 0xed, 0x7f, 0xa5, 0x28, 0x27, 0x63, 0x36, 0x49, 0xfa, 0x28, + 0x8e, 0x39, 0x41, 0x7e, 0x90, 0x7e, 0x2b, 0x8a, 0x35, 0x0a, 0x12, 0xd3, 0x51, 0xd6, 0xfc, 0x51, 0x51, 0x00, 0x19, + 0x75, 0x95, 0x47, 0x93, 0xd6, 0xe4, 0x60, 0xf2, 0xa2, 0xc7, 0x8b, 0xb3, 0xaf, 0x4a, 0xd5, 0x0d, 0xfa, 0xb7, 0x25, + 0x35, 0x4b, 0xd2, 0x38, 0xfa, 0xc8, 0x38, 0x2f, 0xa9, 0xe4, 0x82, 0xa2, 0x6a, 0xd3, 0x56, 0xfd, 0x4b, 0x4e, 0x67, + 0x38, 0x9a, 0xb4, 0x8a, 0xea, 0x08, 0xe3, 0x7e, 0x0e, 0xe4, 0xc9, 0xbe, 0x00, 0xfd, 0x44, 0x9e, 0x26, 0xc7, 0x6c, + 0x9a, 0x28, 0x47, 0xe5, 0x63, 0x9c, 0x8a, 0xf1, 0x9d, 0x40, 0xc6, 0xb5, 0xc2, 0x7b, 0x31, 0xc1, 0x66, 0xae, 0xfa, + 0x83, 0xd3, 0xea, 0x18, 0x8e, 0x73, 0x64, 0x1d, 0x75, 0x46, 0xb6, 0x71, 0x60, 0x1d, 0x98, 0x6d, 0xeb, 0xc8, 0xe8, + 0x98, 0x1d, 0xa3, 0xf3, 0x5d, 0x67, 0x64, 0x1e, 0x58, 0x07, 0x86, 0x6d, 0x76, 0xa0, 0xd0, 0xec, 0x98, 0x9d, 0x1b, + 0xf3, 0xa0, 0x33, 0xb2, 0xb1, 0xb4, 0x65, 0x1d, 0x1e, 0x9a, 0x8e, 0x6d, 0x1d, 0x1e, 0x1a, 0x87, 0xd6, 0xd1, 0x91, + 0xe9, 0xb4, 0xad, 0xa3, 0xa3, 0xf3, 0xc3, 0x8e, 0xd5, 0x86, 0x77, 0xed, 0xf6, 0xa8, 0x6d, 0x39, 0x8e, 0x09, 0x7f, + 0x19, 0x1d, 0xab, 0x45, 0x3f, 0x1c, 0xc7, 0x6a, 0x3b, 0x86, 0x1d, 0x1c, 0xb6, 0xac, 0xa3, 0x17, 0x06, 0xfe, 0x8d, + 0xd5, 0x0c, 0xfc, 0x0b, 0xba, 0x31, 0x5e, 0x58, 0xad, 0x23, 0xfa, 0x85, 0x1d, 0xde, 0x1c, 0x74, 0xfe, 0xa6, 0xee, + 0x6f, 0x1c, 0x83, 0x43, 0x63, 0xe8, 0x1c, 0x5a, 0xed, 0xb6, 0x71, 0xe0, 0x58, 0x9d, 0xf6, 0xcc, 0x3c, 0x68, 0x59, + 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, 0x6c, 0x5b, 0x2d, 0xc3, 0xb1, 0x0e, 0xda, 0xf8, 0xa3, 0x6d, + 0xb5, 0x6e, 0x8e, 0x5f, 0x58, 0x47, 0x87, 0xb3, 0x23, 0xeb, 0xe0, 0xc3, 0x41, 0xc7, 0x6a, 0xb5, 0x67, 0xed, 0x23, + 0xab, 0x75, 0x7c, 0x73, 0x64, 0x1d, 0xcc, 0xcc, 0xd6, 0xd1, 0xd6, 0x96, 0x4e, 0xcb, 0x82, 0x39, 0xc2, 0xd7, 0xf0, + 0xc2, 0xe0, 0x2f, 0xe0, 0xcf, 0x0c, 0xdb, 0xfe, 0x8e, 0xdd, 0x24, 0xf5, 0xa6, 0x2f, 0xac, 0xce, 0xf1, 0x88, 0xaa, + 0x43, 0x81, 0x29, 0x6a, 0x40, 0x93, 0x1b, 0x93, 0x3e, 0x8b, 0xdd, 0x99, 0xa2, 0x23, 0xf1, 0x87, 0x7f, 0xec, 0xc6, + 0x84, 0x0f, 0xd3, 0x77, 0xff, 0xa3, 0xfd, 0xe4, 0x4b, 0x7e, 0xb2, 0x3f, 0xa5, 0xad, 0x3f, 0xed, 0x7f, 0x75, 0x02, + 0x87, 0xbb, 0x3f, 0x30, 0x7e, 0xd9, 0xa4, 0x94, 0xfc, 0xc7, 0xfd, 0x4a, 0xc9, 0x97, 0xcb, 0x5d, 0x94, 0x92, 0xff, + 0xf8, 0xe2, 0x4a, 0xc9, 0x5f, 0xaa, 0xbe, 0x35, 0x6f, 0xaa, 0x59, 0xa8, 0xff, 0xb8, 0xae, 0x8a, 0x1c, 0x12, 0x4f, + 0xbb, 0xfc, 0x71, 0x79, 0x05, 0xf1, 0xe3, 0xdf, 0x44, 0xee, 0xcb, 0x65, 0xc9, 0xe0, 0x33, 0x02, 0x1c, 0xfb, 0x26, + 0x22, 0x1c, 0xfb, 0x61, 0xe9, 0x82, 0x95, 0x19, 0x67, 0x73, 0xfc, 0xb1, 0x39, 0xf3, 0x82, 0x49, 0xce, 0x22, 0x41, + 0x49, 0x0f, 0x8b, 0xc1, 0x6f, 0x1e, 0xc8, 0x33, 0xdc, 0x64, 0x96, 0xf3, 0x30, 0x01, 0x8b, 0x60, 0xb0, 0xe4, 0x98, + 0xc4, 0x59, 0xa5, 0xb1, 0x25, 0x22, 0xee, 0x5f, 0x73, 0x8f, 0xe2, 0x8d, 0xef, 0xd1, 0x00, 0xb8, 0xb9, 0x77, 0xa7, + 0xde, 0xaf, 0x02, 0x96, 0x75, 0xc2, 0x40, 0x1a, 0xb8, 0xfd, 0xa6, 0xf7, 0x65, 0x33, 0xdc, 0x8a, 0xe1, 0xf5, 0x66, + 0x48, 0x01, 0x92, 0x6a, 0x7b, 0xa7, 0x6c, 0xc6, 0x7b, 0xdf, 0x30, 0x1b, 0x3e, 0x5f, 0x6a, 0xbe, 0xc5, 0x86, 0x38, + 0xef, 0xb8, 0x3a, 0x55, 0xeb, 0x12, 0x9f, 0xd6, 0x3c, 0x21, 0xc5, 0x05, 0xb5, 0x30, 0x34, 0x2e, 0x38, 0x55, 0x5b, + 0x41, 0x7e, 0xc7, 0x96, 0xde, 0x95, 0xfa, 0x94, 0x8d, 0x93, 0x9f, 0xad, 0xf1, 0x5e, 0xe1, 0xff, 0x02, 0x9c, 0x28, + 0xe7, 0x78, 0x86, 0x91, 0x3c, 0xcf, 0x6b, 0xa9, 0x5f, 0x92, 0x46, 0x64, 0x33, 0x67, 0x5d, 0xe7, 0x45, 0x37, 0xba, + 0x25, 0x38, 0x6c, 0x2e, 0xb8, 0x20, 0xfc, 0x3c, 0x39, 0x01, 0x64, 0xe4, 0xa8, 0x81, 0x7e, 0x0e, 0xdb, 0x3a, 0x13, + 0xf5, 0x1e, 0xc1, 0x26, 0xe6, 0x9e, 0x80, 0x8a, 0x1c, 0xd2, 0x74, 0x3d, 0x09, 0x22, 0x2f, 0xed, 0x22, 0x9b, 0x26, + 0xb1, 0xbc, 0x2d, 0xf4, 0x58, 0xe8, 0x6d, 0x31, 0xa6, 0x93, 0x3b, 0xe6, 0x9d, 0xa0, 0xe7, 0xc3, 0x36, 0xfb, 0xbb, + 0xdc, 0xe1, 0x6c, 0x5d, 0x32, 0x47, 0x71, 0x0e, 0x8f, 0x0d, 0xe7, 0xc8, 0xb0, 0x8e, 0x0f, 0xf5, 0x4c, 0x1c, 0x38, + 0xb9, 0xcb, 0xd2, 0x84, 0x80, 0x03, 0x44, 0x0e, 0xa6, 0x1f, 0xfa, 0xa9, 0xef, 0x05, 0x19, 0xf0, 0xc3, 0xe5, 0x4b, + 0xca, 0x3f, 0x96, 0x49, 0x0a, 0x63, 0x14, 0x4c, 0x2f, 0x3a, 0x7f, 0x98, 0x43, 0x96, 0xae, 0x18, 0x0b, 0x37, 0x18, + 0xc6, 0x54, 0x7d, 0x49, 0x7e, 0x3b, 0xcb, 0xfa, 0x8c, 0xac, 0xd6, 0x86, 0x69, 0xc8, 0xf7, 0x87, 0x70, 0x7c, 0xc8, + 0x06, 0xc6, 0x77, 0x9b, 0x10, 0xee, 0xcf, 0xf7, 0x23, 0xdc, 0x94, 0xed, 0x82, 0x70, 0x7f, 0xfe, 0xe2, 0x08, 0xf7, + 0x3b, 0x19, 0xe1, 0x96, 0xfc, 0x07, 0x0b, 0x0d, 0xd3, 0x7b, 0x7c, 0xd6, 0xc0, 0x45, 0xf6, 0xb9, 0xba, 0x4f, 0x0c, + 0xbc, 0xaa, 0x17, 0xd9, 0x6b, 0xff, 0xbc, 0x94, 0x2d, 0xa8, 0x51, 0x00, 0x8a, 0x79, 0x1d, 0x7d, 0x74, 0x5d, 0xf6, + 0xc1, 0xd5, 0x4d, 0x84, 0x61, 0x80, 0x3e, 0xbf, 0x0f, 0xd3, 0xc0, 0x7a, 0xc7, 0xef, 0x91, 0xa0, 0xd0, 0x7d, 0x13, + 0xc5, 0x73, 0x0f, 0x53, 0x8c, 0xa8, 0x3a, 0xb8, 0xd3, 0xc1, 0x83, 0x0d, 0x81, 0x40, 0x46, 0x51, 0x38, 0xce, 0xb5, + 0x92, 0xcc, 0xbd, 0x24, 0x8e, 0x5b, 0xbd, 0x63, 0x5e, 0xac, 0x1a, 0xf4, 0x1a, 0x16, 0xf7, 0x59, 0xdb, 0x7e, 0xd6, + 0x3a, 0x78, 0x76, 0x64, 0xc3, 0xff, 0x0e, 0x6b, 0x67, 0x06, 0xaf, 0x38, 0x8f, 0xc2, 0x74, 0x56, 0xd4, 0xdc, 0x54, + 0x6d, 0xc5, 0xd8, 0xc7, 0xa2, 0xd6, 0x71, 0x73, 0xa5, 0xb1, 0x77, 0x57, 0xd4, 0x69, 0xac, 0x31, 0x8b, 0x96, 0x12, + 0x58, 0x0d, 0xd0, 0xf8, 0xe1, 0x12, 0xe4, 0xec, 0x52, 0x0d, 0xf9, 0x35, 0x1f, 0x6e, 0x31, 0x2e, 0xd6, 0xce, 0xae, + 0x44, 0x0e, 0x05, 0xb5, 0x27, 0xd2, 0xea, 0xdd, 0x3b, 0x83, 0x5c, 0x45, 0x69, 0x63, 0xce, 0x29, 0xcc, 0x6c, 0x08, + 0x19, 0xa7, 0x98, 0x58, 0x20, 0x8f, 0x16, 0x28, 0x8d, 0x97, 0xe1, 0x48, 0xc3, 0x9f, 0xde, 0x30, 0xd1, 0xfc, 0xfd, + 0xd8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xbc, 0xbe, 0x5d, 0x24, 0x9d, 0x4f, 0xc4, 0xaa, 0x78, 0xcf, 0x52, 0x23, 0x46, + 0x3d, 0x36, 0x2d, 0xad, 0xe9, 0x7a, 0xcf, 0xf2, 0x86, 0xcf, 0x52, 0x23, 0x7c, 0x0e, 0xba, 0x4f, 0xd7, 0x7e, 0xf2, + 0x84, 0x6a, 0xed, 0xb9, 0x62, 0x58, 0xa7, 0xa3, 0x22, 0x33, 0x85, 0xe2, 0x4d, 0x23, 0x4a, 0x4e, 0xd1, 0x1d, 0x19, + 0xd1, 0xf3, 0xe7, 0x7d, 0xd7, 0xd1, 0x87, 0x31, 0xf3, 0x3e, 0x66, 0x22, 0xdc, 0x77, 0x88, 0xf9, 0x69, 0xcf, 0x77, + 0x33, 0x34, 0xd2, 0x1b, 0x5d, 0x69, 0x17, 0x70, 0x67, 0xb2, 0x85, 0x3b, 0x02, 0xc7, 0x5e, 0x90, 0xbb, 0x9e, 0x0c, + 0x0a, 0x3c, 0x61, 0xf0, 0x23, 0xea, 0xe4, 0xb7, 0xae, 0xb6, 0x65, 0x5b, 0xb6, 0x9a, 0x37, 0x9c, 0xf8, 0x53, 0x77, + 0x1d, 0xa5, 0x5e, 0x77, 0xcf, 0x31, 0x82, 0x68, 0x0a, 0x7e, 0x74, 0xa9, 0x9f, 0x06, 0xac, 0xab, 0xaa, 0xe0, 0x50, + 0x37, 0xa7, 0x7b, 0x79, 0xc6, 0xbd, 0x1b, 0xbc, 0x18, 0xd2, 0x96, 0xc7, 0x77, 0xc2, 0x15, 0x17, 0x83, 0xa5, 0xff, + 0x00, 0xc4, 0x50, 0x53, 0x35, 0x90, 0x0d, 0xb0, 0x38, 0x31, 0x65, 0x6f, 0xa1, 0xae, 0x02, 0x6d, 0x74, 0x95, 0x0f, + 0x62, 0x12, 0x7b, 0x73, 0xc8, 0xab, 0xbb, 0xce, 0x0c, 0x8e, 0x69, 0x55, 0x8e, 0x6a, 0x15, 0xe7, 0xc5, 0x91, 0xa1, + 0xb4, 0x1c, 0x43, 0xb1, 0x01, 0xdd, 0xaa, 0x99, 0xb1, 0xce, 0xae, 0x7a, 0xf7, 0x19, 0x3c, 0x10, 0x7e, 0x79, 0x44, + 0xe3, 0x20, 0x53, 0x07, 0xae, 0x4a, 0x4a, 0x29, 0x49, 0x8e, 0x26, 0x65, 0xd0, 0xf4, 0x49, 0xe9, 0x79, 0xc1, 0x6e, + 0x53, 0x1d, 0x34, 0x47, 0xa2, 0x8a, 0xaf, 0xaf, 0xd1, 0x61, 0xd8, 0x0f, 0x15, 0xff, 0xd3, 0x27, 0xcd, 0x07, 0x67, + 0x26, 0x57, 0x9a, 0x1f, 0x78, 0xd6, 0x4b, 0x13, 0xe6, 0x17, 0x6a, 0x7a, 0x9c, 0x2c, 0xf0, 0x34, 0x84, 0x7f, 0x8b, + 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0x81, 0x17, 0x4e, 0x01, 0xa5, 0x79, 0xe1, 0xb4, 0x66, 0x8e, 0x45, 0x3e, 0xcf, + 0x95, 0xd2, 0xa2, 0xab, 0xc2, 0x54, 0x2a, 0x79, 0x79, 0x77, 0xe1, 0x4d, 0x7f, 0xf4, 0xe6, 0x4c, 0x53, 0x81, 0xca, + 0xa1, 0x8b, 0x6e, 0xa1, 0xc9, 0x7d, 0xee, 0x3e, 0x3d, 0x99, 0xb3, 0xd4, 0x23, 0x35, 0x10, 0x5c, 0x7e, 0x81, 0x1d, + 0x50, 0x38, 0xa1, 0xe1, 0x01, 0x2f, 0x5c, 0xca, 0xa5, 0x45, 0x74, 0xc2, 0x50, 0x38, 0x9d, 0x32, 0xd1, 0xe2, 0xd3, + 0x75, 0x0c, 0x72, 0x38, 0x18, 0x79, 0x98, 0x4f, 0xc7, 0x0d, 0x23, 0xb5, 0xff, 0x34, 0xf7, 0xcd, 0xdc, 0xb4, 0x08, + 0x81, 0x1f, 0x7e, 0xbc, 0x8c, 0x59, 0xf0, 0x4f, 0xf7, 0x29, 0x10, 0xee, 0xa7, 0x57, 0xaa, 0xde, 0x4b, 0xad, 0x59, + 0xcc, 0x26, 0xee, 0x53, 0xb8, 0x90, 0x76, 0xd1, 0x3c, 0x16, 0xb8, 0xf6, 0xe7, 0xb7, 0xf3, 0xc0, 0xc0, 0xeb, 0x3d, + 0xc1, 0xa2, 0xb6, 0x5b, 0x45, 0x5c, 0xf3, 0xf6, 0x4e, 0x97, 0xfa, 0x3e, 0xbf, 0xad, 0xc3, 0x0d, 0x70, 0x5d, 0xba, + 0x63, 0x3b, 0x3d, 0xbc, 0x3f, 0x0f, 0x03, 0x6f, 0xf4, 0xb1, 0x47, 0x6f, 0x4a, 0x0f, 0x26, 0x50, 0xeb, 0x91, 0xb7, + 0xe8, 0x22, 0x79, 0x95, 0x0b, 0xc1, 0x7b, 0x9a, 0x4a, 0x73, 0xce, 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, + 0xf1, 0x53, 0xab, 0x99, 0x9f, 0x32, 0xf1, 0x29, 0x7c, 0xc8, 0x32, 0x71, 0x51, 0xa7, 0x2b, 0x2a, 0x5e, 0xac, 0xad, + 0xb6, 0xe2, 0x74, 0xbe, 0x3b, 0xbc, 0x71, 0xec, 0x59, 0xcb, 0xb1, 0x3a, 0x1f, 0x9c, 0xce, 0xac, 0x6d, 0x1d, 0x07, + 0x66, 0xdb, 0x3a, 0x86, 0x3f, 0x1f, 0x8e, 0xad, 0xce, 0xcc, 0x6c, 0x59, 0x07, 0x1f, 0x9c, 0x56, 0x60, 0x76, 0xac, + 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, + 0x89, 0xbc, 0x35, 0xe8, 0x75, 0x17, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0x7b, 0x5a, 0xe8, 0x32, 0x4a, 0x2a, 0x2b, + 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0xd9, 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x0c, 0x96, 0xba, 0xc8, 0x08, 0x8c, + 0xcf, 0x3f, 0x2f, 0x30, 0xfe, 0xba, 0x48, 0xc3, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x85, 0xb6, 0x15, + 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xcc, 0xd7, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, + 0x21, 0x67, 0x9f, 0x1c, 0xfb, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xe6, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, + 0x7c, 0xe3, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0x72, 0x2f, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, + 0x9c, 0x43, 0x20, 0xbb, 0x87, 0xac, 0xbd, 0xd5, 0xa6, 0x92, 0x6e, 0x3a, 0xdb, 0x7c, 0xab, 0x8b, 0x4c, 0x47, 0xc2, + 0x6e, 0x4a, 0x58, 0x6c, 0x6c, 0x34, 0xec, 0xac, 0xd9, 0x6b, 0x40, 0xaa, 0xb8, 0xca, 0x55, 0x47, 0xd5, 0x7b, 0xa1, + 0x30, 0x3f, 0x08, 0xb7, 0x24, 0x79, 0xe3, 0x77, 0x31, 0x15, 0xa6, 0x66, 0xcb, 0x38, 0xee, 0x71, 0x10, 0xff, 0x4f, + 0x0f, 0x02, 0x9d, 0x35, 0xc1, 0x5e, 0xa2, 0x72, 0x5a, 0x4b, 0xce, 0x7b, 0x39, 0x5d, 0x25, 0x82, 0xca, 0x92, 0x53, + 0x15, 0x8a, 0xd4, 0xae, 0x8a, 0x8e, 0x61, 0x6a, 0x6e, 0x2c, 0x9a, 0x53, 0x8b, 0xa2, 0xc0, 0xf0, 0x31, 0xa1, 0xa6, + 0x70, 0x1c, 0xd5, 0x9f, 0x3c, 0xd9, 0x48, 0x84, 0xc8, 0x38, 0x27, 0x61, 0xa9, 0x60, 0xd0, 0x35, 0x55, 0xc6, 0x6f, + 0xaa, 0x8c, 0x62, 0xf2, 0x7e, 0x11, 0x6b, 0x08, 0x1b, 0x57, 0xda, 0x7b, 0xf8, 0x73, 0xc8, 0xbc, 0xd4, 0xe2, 0xca, + 0x52, 0x4d, 0x22, 0xee, 0x86, 0xc3, 0xda, 0x60, 0xdd, 0xca, 0xd3, 0x34, 0xf0, 0x34, 0x28, 0x8f, 0xd7, 0x7f, 0x5e, + 0xf2, 0xa8, 0x0e, 0xd0, 0xc7, 0x27, 0xbb, 0x88, 0xc3, 0xf9, 0x36, 0xf5, 0x28, 0x0e, 0x9a, 0x4c, 0x72, 0xa3, 0xd4, + 0x23, 0x7b, 0x0e, 0x1f, 0x43, 0xd7, 0x34, 0x47, 0xe4, 0x92, 0x22, 0x3f, 0xf4, 0xdf, 0x5e, 0x7c, 0xa3, 0xf0, 0xfd, + 0x4f, 0xd6, 0x02, 0x78, 0x91, 0xa1, 0x78, 0x33, 0x2e, 0xc5, 0x9b, 0x51, 0x78, 0x26, 0x63, 0xc8, 0xb9, 0x9a, 0xed, + 0xd3, 0x0c, 0xa2, 0x00, 0x9a, 0x6c, 0x28, 0xe6, 0xcb, 0x20, 0xf5, 0x17, 0x5e, 0x9c, 0xee, 0x63, 0xb0, 0x19, 0x0c, + 0x5e, 0xb3, 0x29, 0x1e, 0x04, 0x99, 0x61, 0x88, 0xec, 0x20, 0x69, 0x28, 0xec, 0x30, 0x26, 0x7e, 0x90, 0x9b, 0x61, + 0x88, 0x0f, 0x78, 0xa3, 0x11, 0x5b, 0xa4, 0x6e, 0x29, 0xa8, 0x4d, 0x34, 0x4a, 0x59, 0x6a, 0x26, 0x69, 0xcc, 0xbc, + 0xb9, 0x9a, 0x07, 0xb9, 0xaa, 0xf7, 0x97, 0x2c, 0x87, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, + 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0xcf, 0xa3, 0x69, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x29, 0x26, 0x09, 0xa3, 0x9b, + 0x0c, 0x48, 0x8b, 0x47, 0x51, 0x70, 0xcd, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xfe, 0x09, 0xbf, 0xde, 0x2a, 0x18, + 0xbe, 0x45, 0x3d, 0xb4, 0x21, 0x0d, 0xda, 0xa6, 0xe8, 0x16, 0xfb, 0xbc, 0x32, 0x90, 0x26, 0xea, 0x19, 0x33, 0x59, + 0x12, 0x2c, 0x17, 0xc0, 0x08, 0x95, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x77, 0xa7, 0x44, 0xa8, 0x90, 0x57, 0xfa, 0xf4, + 0xe9, 0xfd, 0xe0, 0xdf, 0xff, 0x82, 0x74, 0x9b, 0x33, 0x47, 0xc4, 0x94, 0xb8, 0x94, 0x6b, 0x71, 0xee, 0xd3, 0x18, + 0xa0, 0xb1, 0x14, 0x1b, 0x8b, 0x68, 0x7f, 0x62, 0x6b, 0x65, 0x83, 0x2b, 0x11, 0xa7, 0x0e, 0x12, 0xf5, 0xea, 0x22, + 0xf2, 0xc5, 0x00, 0x96, 0x77, 0x20, 0x62, 0xa2, 0x28, 0x7f, 0xbf, 0x7d, 0x79, 0xac, 0x14, 0xe1, 0x13, 0x9b, 0x2c, + 0x7a, 0x68, 0x0f, 0xf5, 0x4f, 0x3c, 0x05, 0x99, 0x16, 0x64, 0x3f, 0x92, 0xee, 0x3e, 0x0c, 0x73, 0x16, 0xcd, 0x99, + 0xe5, 0x47, 0xfb, 0x2b, 0x36, 0x34, 0xbd, 0x85, 0x4f, 0x76, 0x39, 0x28, 0x77, 0x53, 0x88, 0xf3, 0xcb, 0xcd, 0x5d, + 0x88, 0xbf, 0xce, 0x8a, 0xa9, 0x8c, 0x2a, 0x81, 0xd0, 0x5a, 0x85, 0x1e, 0xf0, 0x80, 0x07, 0x19, 0x13, 0x35, 0xfb, + 0x27, 0xfb, 0x5e, 0xbf, 0x9c, 0x79, 0xc6, 0x12, 0x19, 0x54, 0xcb, 0x44, 0xe0, 0x94, 0x12, 0xc8, 0x88, 0x5c, 0x31, + 0xc5, 0x83, 0x19, 0x4d, 0x26, 0x72, 0xb6, 0x18, 0xab, 0x0c, 0x5e, 0x3e, 0x69, 0xc5, 0x96, 0x8e, 0x16, 0xf4, 0xa5, + 0xfa, 0x27, 0xf2, 0x9f, 0x6a, 0x17, 0xd3, 0x44, 0xc1, 0x98, 0xe1, 0xb8, 0xd7, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, + 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x81, 0x73, 0xd9, 0x73, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0xd8, + 0x90, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x75, 0x18, 0xf7, 0x3d, 0xb1, + 0xfd, 0x4a, 0x1b, 0x14, 0x36, 0x1e, 0x5f, 0x77, 0xc0, 0xef, 0xa2, 0x9f, 0x0a, 0x9a, 0x57, 0xbe, 0x26, 0x8c, 0x6e, + 0x06, 0xde, 0x5d, 0x24, 0x99, 0x31, 0xf1, 0x88, 0x26, 0xe7, 0x58, 0x7a, 0x21, 0x3c, 0x89, 0x6b, 0x07, 0x0d, 0x49, + 0x18, 0x64, 0xdd, 0xac, 0x1f, 0xb6, 0x82, 0xfe, 0x06, 0xec, 0xbe, 0xb3, 0x26, 0xd7, 0x2d, 0x0f, 0x06, 0x91, 0x67, + 0x56, 0x9c, 0xc3, 0xd2, 0x4b, 0x44, 0x0b, 0xd9, 0xc9, 0x3e, 0x8c, 0x0f, 0xa2, 0xb0, 0x94, 0x18, 0x27, 0x5f, 0x87, + 0x50, 0x2f, 0x5e, 0x42, 0xa6, 0x58, 0xdf, 0x8f, 0x05, 0xcf, 0x87, 0x17, 0x4b, 0x29, 0x97, 0xbc, 0x54, 0xa5, 0xce, + 0xcb, 0xd8, 0xcd, 0x4c, 0xe0, 0xfd, 0x29, 0x6a, 0x3f, 0x2c, 0x31, 0x3f, 0x6d, 0xd6, 0x4b, 0x99, 0x08, 0x72, 0x70, + 0x9e, 0x6e, 0x88, 0x83, 0xb0, 0xa9, 0x0a, 0xf1, 0xb3, 0x5b, 0x2a, 0x14, 0xfb, 0x78, 0x5b, 0xad, 0x82, 0x73, 0x2a, + 0xaa, 0x79, 0x9a, 0xfa, 0x08, 0x77, 0x7c, 0xad, 0x36, 0x96, 0x62, 0x74, 0x86, 0xd4, 0x85, 0xaa, 0x42, 0x16, 0xef, + 0x2d, 0x16, 0x54, 0x59, 0xef, 0x9d, 0xec, 0xd3, 0xb5, 0xb4, 0x4f, 0x3b, 0xac, 0x7f, 0x02, 0xa6, 0xdc, 0xb4, 0xe8, + 0xde, 0x62, 0xc1, 0x97, 0x94, 0x7e, 0xd1, 0x9b, 0xfd, 0x59, 0x3a, 0x0f, 0xfa, 0xff, 0x0b, 0x3a, 0x5f, 0xcc, 0x86, + 0x37, 0x7a, 0x03, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0x90, 0x7a, 0x53, 0xc1, 0x6e, 0xc1, 0x56, 0x6f, 0x00, 0x79, 0xaf, 0xf6, 0x6d, 0x2b, 0x05, 0x44, 0x11, 0x6c, - 0x9c, 0x06, 0x03, 0x82, 0x71, 0xa5, 0x64, 0xba, 0x39, 0x78, 0xe4, 0x76, 0x00, 0x6c, 0xbb, 0xaa, 0xb6, 0x41, 0xaa, - 0x9a, 0x70, 0x54, 0x0e, 0x31, 0xb1, 0x27, 0x5a, 0x0c, 0xe6, 0x4f, 0xe4, 0x1a, 0x89, 0x16, 0xe8, 0x24, 0x0c, 0xc4, - 0xa0, 0x60, 0x71, 0x7b, 0x07, 0x92, 0xb2, 0x62, 0xb6, 0x5c, 0x32, 0xac, 0x0d, 0x63, 0xd8, 0x38, 0xf8, 0xf0, 0x15, - 0xdd, 0xce, 0xfe, 0x4e, 0x15, 0x9d, 0xab, 0xfb, 0x0e, 0x21, 0x59, 0x85, 0x78, 0xe1, 0xae, 0xca, 0x1f, 0x7a, 0x37, - 0xc2, 0x07, 0x0d, 0xc2, 0x31, 0x1f, 0x88, 0x73, 0x48, 0x2a, 0x4c, 0xba, 0xd2, 0xbd, 0x41, 0xc1, 0xe2, 0x9d, 0x07, - 0x35, 0xb2, 0xf3, 0xee, 0xab, 0xbf, 0x18, 0xc2, 0xf6, 0xaa, 0xb0, 0x9f, 0xb5, 0xd2, 0xfa, 0x3f, 0xf6, 0x7d, 0x54, - 0x0b, 0xb3, 0xd2, 0xab, 0x5f, 0x04, 0x6e, 0xfc, 0x69, 0xbd, 0x97, 0x2e, 0xb2, 0x64, 0x16, 0xef, 0x3e, 0x91, 0x2b, - 0x71, 0x11, 0xbe, 0xcd, 0xb8, 0x53, 0x58, 0x09, 0xdb, 0x0f, 0x9b, 0x37, 0x7d, 0x0d, 0x07, 0x83, 0x1b, 0x9b, 0xc5, - 0xa1, 0xa2, 0xe7, 0xc8, 0x8e, 0x39, 0x27, 0x54, 0x9d, 0x10, 0x84, 0x65, 0x80, 0xed, 0x72, 0x63, 0x84, 0x60, 0x65, - 0x09, 0x3d, 0x91, 0xd0, 0x17, 0xe9, 0x5b, 0x6f, 0xa9, 0xff, 0x5f, 0xbf, 0x19, 0xbe, 0x8d, 0x2c, 0x45, 0xbe, 0xa4, - 0xee, 0xb2, 0x8e, 0xab, 0xf6, 0x25, 0xb1, 0x13, 0xcf, 0x4b, 0x29, 0x70, 0xf3, 0x70, 0x1a, 0x71, 0xeb, 0x60, 0x02, - 0x80, 0xb6, 0x64, 0x56, 0x7e, 0x96, 0xa9, 0xdf, 0x79, 0x7a, 0x39, 0xd9, 0x2f, 0x99, 0x06, 0xff, 0x44, 0x32, 0x0f, - 0x49, 0x5e, 0x9a, 0x51, 0x37, 0x3b, 0xfb, 0xea, 0x76, 0x1c, 0x8c, 0x90, 0x44, 0x3f, 0x06, 0x17, 0x50, 0x96, 0xaa, - 0xbd, 0x5f, 0x7a, 0xef, 0xaf, 0xf5, 0xfd, 0xd7, 0x2f, 0x5d, 0xbd, 0x98, 0x7a, 0x54, 0x54, 0x66, 0xf6, 0xc2, 0xc0, - 0xdd, 0x76, 0xe7, 0x2e, 0x2b, 0xed, 0xa5, 0x51, 0x22, 0x72, 0x9a, 0x0e, 0x3e, 0x12, 0x5b, 0x1c, 0xc8, 0x2c, 0x36, - 0xad, 0x5e, 0xff, 0xd9, 0xc6, 0xde, 0xf5, 0x2f, 0x57, 0xd3, 0x1a, 0x69, 0xe5, 0x0a, 0xe3, 0xd8, 0x0a, 0x88, 0x38, - 0x12, 0x2b, 0xcb, 0xa4, 0xf8, 0x6a, 0xf6, 0xed, 0x74, 0x85, 0x3d, 0xf9, 0x75, 0x53, 0x96, 0xb5, 0xff, 0x7b, 0xbe, - 0x86, 0x1b, 0x47, 0xce, 0x65, 0xb3, 0x5a, 0xcf, 0xc4, 0x52, 0x94, 0x87, 0x12, 0x77, 0x36, 0x60, 0xdf, 0x57, 0xb5, - 0xaf, 0xdf, 0x23, 0x5f, 0x9e, 0x0f, 0xce, 0x24, 0x3b, 0x36, 0x75, 0x59, 0x4e, 0x87, 0x73, 0xc9, 0x5b, 0x75, 0xaf, - 0xd5, 0xf9, 0xc5, 0xac, 0x8c, 0x54, 0x48, 0x14, 0x20, 0x21, 0xd0, 0x29, 0x79, 0xdf, 0x57, 0x7d, 0xff, 0xeb, 0x5b, - 0x3a, 0x29, 0x0a, 0x95, 0xb2, 0x2b, 0xa8, 0x63, 0xa2, 0xe3, 0x75, 0x6c, 0xdf, 0x39, 0xfc, 0x18, 0x1a, 0xb2, 0x94, - 0xc3, 0x80, 0xbe, 0x24, 0x95, 0x09, 0xf8, 0xff, 0xfa, 0x9a, 0xbd, 0xff, 0xef, 0x9f, 0x2f, 0x89, 0x68, 0x95, 0xd8, - 0xd4, 0x2a, 0x4a, 0xb2, 0xe7, 0x73, 0x48, 0xd2, 0xd3, 0x9b, 0xc7, 0x76, 0x85, 0xc0, 0xba, 0xdc, 0x6e, 0x7a, 0x80, - 0x0e, 0x40, 0x9e, 0xb2, 0xf6, 0x31, 0x97, 0x55, 0xf5, 0x16, 0x15, 0x12, 0xf1, 0xeb, 0xf6, 0xfd, 0x8c, 0xfb, 0x98, - 0x6e, 0x60, 0x06, 0xc3, 0x46, 0x9e, 0x13, 0x8c, 0xeb, 0xf9, 0x69, 0xea, 0xe7, 0xe9, 0x2a, 0x78, 0x61, 0x23, 0x4f, - 0x7e, 0x1c, 0x0f, 0xab, 0x28, 0x12, 0x09, 0xd3, 0xda, 0x39, 0x9d, 0xdb, 0xf5, 0xd3, 0xfa, 0xf6, 0x79, 0x78, 0x48, - 0x3e, 0xa0, 0x56, 0xdf, 0xf0, 0xfb, 0x5f, 0x6f, 0xba, 0xfe, 0xeb, 0xd7, 0xee, 0xe2, 0x89, 0x73, 0xd1, 0x91, 0x52, - 0x09, 0x6f, 0xbd, 0x9a, 0x4b, 0xb3, 0xac, 0xf5, 0xc8, 0x52, 0x38, 0xac, 0x2a, 0xd7, 0x60, 0xac, 0x26, 0xa3, 0x19, - 0x23, 0xbb, 0xd4, 0x9d, 0x41, 0xc1, 0x6a, 0xfb, 0xd4, 0xb7, 0xf7, 0x8b, 0x52, 0x6b, 0xaa, 0x86, 0x85, 0x26, 0x1a, - 0x47, 0xb6, 0x43, 0x90, 0x4d, 0xbc, 0xfd, 0x26, 0x09, 0x1e, 0x02, 0x5a, 0xc2, 0xec, 0xb0, 0x56, 0x0f, 0xbc, 0x2b, - 0x52, 0xd7, 0x76, 0xad, 0x70, 0xf9, 0xa6, 0xfa, 0x5f, 0xbf, 0x91, 0x87, 0x33, 0xa5, 0x7a, 0xd2, 0xed, 0x3b, 0xbe, - 0x94, 0x8b, 0xb9, 0xda, 0x9a, 0x8e, 0x5e, 0x22, 0xe7, 0xf2, 0x64, 0xd0, 0xc5, 0xcd, 0x04, 0x04, 0xf0, 0x76, 0x17, - 0x24, 0x20, 0x8d, 0x0b, 0x14, 0x36, 0x44, 0x82, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, 0x34, 0x55, 0x84, - 0xc8, 0x6e, 0x80, 0x1c, 0x67, 0xd8, 0xb2, 0x7e, 0xdf, 0x59, 0x59, 0x05, 0xaa, 0x01, 0x92, 0x3d, 0xce, 0xac, 0xa4, - 0xb5, 0x16, 0x9b, 0x8a, 0x6b, 0xde, 0x65, 0x7e, 0x17, 0x9d, 0xf1, 0xc3, 0xb0, 0xc2, 0x64, 0x36, 0xd2, 0xd5, 0xb0, - 0x6c, 0x57, 0x96, 0xd3, 0x00, 0x20, 0x78, 0xdf, 0xfb, 0x3f, 0x0a, 0xff, 0xff, 0xc8, 0xe2, 0x44, 0x44, 0x16, 0xa8, - 0xc8, 0xac, 0xe2, 0x9c, 0xac, 0x02, 0x66, 0x54, 0x05, 0x70, 0x46, 0x05, 0xb0, 0x8f, 0x0e, 0xc8, 0xb1, 0x20, 0x68, - 0x34, 0x4d, 0x77, 0x34, 0xec, 0x96, 0xf7, 0x2b, 0x2d, 0x56, 0x1c, 0xca, 0xf5, 0x8c, 0x6c, 0x4b, 0x7e, 0xb7, 0x03, - 0x65, 0xcd, 0x52, 0x5a, 0xe9, 0xe8, 0x7f, 0xd7, 0xd4, 0xb6, 0x1b, 0x3b, 0x02, 0xd5, 0x37, 0x95, 0x0a, 0x21, 0xfb, - 0x7f, 0x52, 0xf8, 0x29, 0x61, 0x52, 0x4c, 0x86, 0xb9, 0x1b, 0xdd, 0x8d, 0xd0, 0xcd, 0x4a, 0x04, 0x25, 0x66, 0x36, - 0x46, 0xe4, 0xa0, 0x24, 0x70, 0xa0, 0xfa, 0x5f, 0x21, 0xd9, 0x6c, 0xda, 0x6e, 0x43, 0xb5, 0x73, 0x33, 0x3b, 0xf2, - 0xf9, 0x15, 0x33, 0x96, 0x10, 0xd3, 0x20, 0x6c, 0xda, 0x73, 0xf4, 0xcd, 0x8f, 0xd6, 0x9e, 0xbe, 0xb3, 0x6a, 0x92, - 0xd4, 0x5d, 0x7e, 0x0b, 0xff, 0x61, 0x80, 0x61, 0xe0, 0xec, 0x5b, 0x16, 0xd3, 0xec, 0x26, 0xfe, 0xba, 0x16, 0x0d, - 0x21, 0x44, 0x08, 0xd4, 0xb6, 0x43, 0xe6, 0xfa, 0xef, 0xbc, 0xb5, 0x3d, 0x71, 0x77, 0x7f, 0x13, 0x42, 0x4a, 0x63, - 0x52, 0x2a, 0x98, 0x71, 0x5f, 0x4c, 0x7d, 0xea, 0xb9, 0x75, 0xdc, 0x34, 0xa9, 0x9b, 0x99, 0xd9, 0xad, 0x45, 0x51, - 0x14, 0xaf, 0x13, 0x04, 0x40, 0xe5, 0x2f, 0x63, 0x62, 0xfd, 0xe8, 0xba, 0xd1, 0xff, 0xad, 0xc8, 0x96, 0x11, 0x86, - 0x08, 0x49, 0xac, 0x6b, 0x25, 0xd8, 0xdc, 0x18, 0x45, 0x9c, 0x5b, 0x1b, 0xc0, 0x8e, 0x8e, 0xd1, 0x6c, 0x41, 0x55, - 0xa0, 0xb1, 0xcd, 0x1d, 0xfc, 0x7c, 0x51, 0x00, 0xa6, 0x91, 0x1e, 0x4a, 0xde, 0x19, 0x9f, 0x10, 0x43, 0x0f, 0x19, - 0x5c, 0x78, 0x74, 0xe4, 0x81, 0x49, 0x75, 0x60, 0x44, 0x7f, 0xe9, 0xe6, 0x96, 0xb0, 0x06, 0x9e, 0x69, 0xb9, 0xe4, - 0x37, 0x82, 0xde, 0xe9, 0x7b, 0x00, 0x62, 0x12, 0x28, 0xd5, 0xed, 0x17, 0x6c, 0x0b, 0x4c, 0x8f, 0x9c, 0xa7, 0xbd, - 0x21, 0x29, 0x78, 0x70, 0xdc, 0xfd, 0xba, 0x0b, 0xa4, 0x5d, 0xca, 0x57, 0xec, 0x92, 0x61, 0xd6, 0xd1, 0x8d, 0xef, - 0xa6, 0xe8, 0x0a, 0xcd, 0x59, 0x0a, 0xea, 0x9c, 0xbb, 0x9e, 0x1b, 0xcb, 0x2f, 0x5a, 0x72, 0xfa, 0xb7, 0xa5, 0x8f, - 0xd9, 0xfb, 0xd2, 0x2f, 0xd4, 0x55, 0xf3, 0x2d, 0x70, 0x12, 0x00, 0xc8, 0xb2, 0x0f, 0x31, 0x2d, 0xc8, 0x92, 0xea, - 0x6b, 0xf9, 0xb9, 0x19, 0x6f, 0x35, 0x0d, 0x26, 0x68, 0x44, 0x36, 0x28, 0x00, 0xd8, 0xbb, 0xef, 0x9e, 0xbd, 0x5b, - 0x59, 0x4a, 0xe9, 0xd3, 0xec, 0x2f, 0xf3, 0xc0, 0x4b, 0xb3, 0x6c, 0x40, 0x8a, 0xb6, 0xa5, 0x1b, 0xf9, 0x50, 0x82, - 0x88, 0x86, 0xcd, 0x05, 0xcf, 0x46, 0x77, 0x6c, 0xe3, 0x51, 0x8b, 0x2f, 0xd6, 0xa8, 0x1c, 0x43, 0x83, 0xf8, 0x7a, - 0xe7, 0xdd, 0x4a, 0x85, 0x96, 0x94, 0xd7, 0xf8, 0x8e, 0xf6, 0x03, 0x26, 0x77, 0x6e, 0xe0, 0x03, 0x8d, 0xeb, 0xcf, - 0xe1, 0xaf, 0xed, 0xb9, 0x1c, 0x9a, 0x44, 0xa6, 0x97, 0xd9, 0x31, 0xce, 0x78, 0x76, 0x3f, 0x22, 0x09, 0x12, 0x8d, - 0xbe, 0xa8, 0x67, 0xfa, 0xf9, 0x5a, 0x73, 0x44, 0x8a, 0x50, 0xdf, 0xdf, 0x63, 0x17, 0xc8, 0x0b, 0xa7, 0x0b, 0xca, - 0xed, 0x7b, 0xdc, 0xff, 0x1c, 0x38, 0xda, 0x47, 0xf7, 0xf8, 0xdd, 0xea, 0x6e, 0x66, 0xdf, 0xbc, 0xc0, 0x63, 0x41, - 0x48, 0x9b, 0x20, 0x61, 0x98, 0xf9, 0xdd, 0x37, 0x11, 0x16, 0xef, 0x7b, 0x0b, 0x62, 0x35, 0xea, 0x4f, 0x7f, 0xfd, - 0xcb, 0x3e, 0xdd, 0xed, 0xf5, 0x88, 0x5f, 0x7f, 0x38, 0x78, 0x7a, 0x6f, 0x98, 0x86, 0xd5, 0x14, 0xda, 0x9e, 0xf5, - 0xcc, 0xf8, 0xb6, 0xad, 0xc2, 0xbe, 0xff, 0xf2, 0xf5, 0xe0, 0xae, 0xe7, 0x30, 0xb4, 0xee, 0x4e, 0x94, 0xc5, 0x23, - 0x86, 0x7f, 0x13, 0x24, 0xfd, 0x33, 0x27, 0xfd, 0xc2, 0xe7, 0x56, 0x80, 0x01, 0xba, 0xa5, 0xe6, 0x43, 0x6b, 0x8c, - 0x17, 0xbe, 0x41, 0x37, 0xc2, 0xc4, 0xfc, 0x0a, 0x4b, 0x29, 0x76, 0xde, 0xbf, 0x18, 0xd3, 0x27, 0xd6, 0x45, 0x4d, - 0x00, 0x44, 0x4a, 0x66, 0x13, 0xc0, 0xa0, 0x44, 0x06, 0x38, 0x1b, 0xc6, 0x75, 0xe9, 0x2e, 0xf4, 0xc8, 0xea, 0x66, - 0xd8, 0xc2, 0xfe, 0xcf, 0x17, 0x38, 0xc0, 0x27, 0xd6, 0x41, 0xc7, 0xcb, 0x4c, 0xc8, 0x1d, 0xb3, 0xe2, 0xff, 0xc7, - 0x4f, 0x6a, 0x72, 0x21, 0x96, 0xc2, 0x66, 0xb6, 0x75, 0x77, 0x8d, 0xdd, 0x48, 0x95, 0x89, 0xad, 0xcc, 0x8a, 0xea, - 0x5b, 0xa8, 0xe4, 0xf7, 0x4e, 0xee, 0x45, 0x95, 0xa2, 0xfa, 0x16, 0xc8, 0x96, 0x67, 0x78, 0xc7, 0xf1, 0xf5, 0x4f, - 0x03, 0xe2, 0xad, 0x94, 0x1c, 0xa5, 0x6a, 0x60, 0xc9, 0x93, 0x43, 0x3f, 0x6d, 0x50, 0x1e, 0x67, 0xa4, 0x0d, 0x38, - 0x72, 0x25, 0x7a, 0x66, 0xd0, 0xc8, 0xbb, 0x4e, 0x1e, 0x8b, 0x2a, 0xff, 0x2e, 0xf1, 0xfb, 0x4a, 0x6a, 0x11, 0x2c, - 0x19, 0xc9, 0x1d, 0x41, 0xcc, 0x16, 0xaa, 0x08, 0xed, 0x28, 0x9c, 0x48, 0x2b, 0x1e, 0xf1, 0x82, 0xf7, 0x7c, 0xbf, - 0x6d, 0x7b, 0x83, 0x84, 0x0b, 0x6f, 0x61, 0xf1, 0x2d, 0x3e, 0xc8, 0xf9, 0xe7, 0x72, 0xb2, 0x96, 0x8a, 0x9e, 0xb2, - 0x79, 0x9a, 0xd8, 0x52, 0xa2, 0x4b, 0x86, 0x40, 0x17, 0x54, 0x47, 0x6e, 0x98, 0x5c, 0x2f, 0x78, 0x7f, 0x83, 0xdb, - 0xe6, 0x17, 0x0b, 0x29, 0x5f, 0xcf, 0xcc, 0x6e, 0xeb, 0x01, 0x50, 0x75, 0xd8, 0x00, 0x3c, 0x65, 0xff, 0xdd, 0xe3, - 0x6e, 0xf2, 0x12, 0x61, 0xe1, 0xb1, 0x5b, 0x22, 0xed, 0xb2, 0x8f, 0x93, 0xa1, 0x57, 0x07, 0xf0, 0xf6, 0x44, 0x05, - 0x10, 0xb9, 0x8a, 0x39, 0x37, 0x9c, 0x88, 0xa4, 0xfe, 0x7d, 0xfa, 0x2d, 0x5d, 0xd8, 0xb0, 0x0d, 0x4d, 0xd0, 0x57, - 0x09, 0xaf, 0xa2, 0xf5, 0x8d, 0x8a, 0x5d, 0x8e, 0x00, 0x64, 0xad, 0x82, 0x99, 0x75, 0xdb, 0x10, 0xab, 0x93, 0x54, - 0x6e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd3, 0x1c, 0xb9, 0xa1, 0xea, 0x18, 0xff, 0xca, 0xd8, 0x9c, 0x4d, 0x34, 0x55, - 0xc3, 0xe2, 0x6f, 0x0d, 0xf2, 0x10, 0x2f, 0xfb, 0x88, 0x06, 0x3d, 0xca, 0xba, 0xe0, 0x1a, 0xb8, 0x0a, 0xf4, 0x92, - 0x1c, 0x3c, 0x73, 0x8d, 0x06, 0xc3, 0x1b, 0x63, 0x07, 0x02, 0x60, 0x93, 0x10, 0xca, 0x02, 0x5b, 0x2b, 0x1d, 0x54, - 0x75, 0xc7, 0xd4, 0xbc, 0xdf, 0xbd, 0x65, 0xa2, 0x4f, 0x45, 0x0b, 0x97, 0xa8, 0xbe, 0x90, 0x58, 0xed, 0xa1, 0xf9, - 0x0f, 0xed, 0xc2, 0x6f, 0x90, 0x20, 0x3c, 0xaf, 0x1d, 0xd0, 0x4f, 0x49, 0x9b, 0x52, 0x85, 0x0a, 0xa3, 0x6c, 0xe3, - 0xca, 0x76, 0x77, 0x45, 0x33, 0x0b, 0xe1, 0x9b, 0x89, 0x66, 0xbd, 0xed, 0xf8, 0xc1, 0x1e, 0x0d, 0x9b, 0x00, 0x5a, - 0x81, 0x05, 0x20, 0xea, 0xcf, 0xd5, 0xb6, 0xfd, 0x2e, 0x6c, 0x06, 0x55, 0x51, 0x92, 0x55, 0xa1, 0x8d, 0xa0, 0x91, - 0x81, 0x41, 0x13, 0x4d, 0xbf, 0xe8, 0x1e, 0xfc, 0xc2, 0x85, 0xb8, 0xa0, 0xb0, 0xa1, 0x74, 0xeb, 0xfa, 0x25, 0x52, - 0x05, 0xa6, 0xb1, 0x72, 0xb9, 0xff, 0x7e, 0x07, 0x1d, 0x7f, 0x5d, 0xec, 0x94, 0x7a, 0xae, 0xaa, 0x09, 0x75, 0x77, - 0x42, 0x13, 0x08, 0x1e, 0x0e, 0xbd, 0x70, 0xfa, 0x47, 0xc2, 0x1d, 0x24, 0xe7, 0xe5, 0xfb, 0xbf, 0x42, 0x0d, 0xfe, - 0x3c, 0xa0, 0x80, 0xf6, 0xaa, 0x7c, 0xde, 0x1d, 0x21, 0x38, 0x51, 0xbf, 0x02, 0x3b, 0xa2, 0xd2, 0x94, 0x1c, 0x51, - 0x58, 0x9c, 0x21, 0xbe, 0x01, 0xba, 0xf9, 0xb6, 0x53, 0xfd, 0xf9, 0xdb, 0x85, 0x13, 0xf1, 0xab, 0x6f, 0x97, 0xec, - 0x6d, 0xa4, 0x44, 0xe0, 0xa1, 0x5a, 0x9f, 0x1b, 0x84, 0x92, 0x0d, 0x96, 0x28, 0x45, 0x5c, 0x26, 0xa2, 0x4a, 0x08, - 0x16, 0x6d, 0x35, 0x6a, 0xe8, 0xd7, 0xeb, 0x2e, 0xb2, 0xae, 0xf1, 0x54, 0x05, 0x5f, 0xa8, 0xdf, 0xf6, 0x0c, 0x9b, - 0x79, 0x4d, 0xe7, 0x62, 0xff, 0x2b, 0x74, 0x4e, 0x2e, 0xb4, 0x76, 0xe9, 0x29, 0x04, 0x10, 0x85, 0x3b, 0xd3, 0x96, - 0x15, 0xc9, 0xd0, 0xae, 0xc0, 0xec, 0x07, 0x06, 0x92, 0x09, 0xf2, 0xc9, 0xfe, 0x4c, 0x0e, 0x21, 0x4d, 0x3c, 0x4e, - 0x46, 0x30, 0xbc, 0xd2, 0x50, 0xfa, 0xe6, 0x62, 0x78, 0xab, 0x5c, 0x9f, 0xc2, 0x2e, 0x88, 0x32, 0x07, 0xbe, 0xed, - 0x72, 0x74, 0x2b, 0x62, 0xf0, 0x8c, 0xc7, 0x8c, 0xb9, 0x77, 0xeb, 0xbd, 0xfb, 0x23, 0x52, 0x1d, 0x0b, 0x41, 0x6a, - 0x18, 0xc8, 0xaf, 0xc5, 0x40, 0x0f, 0xa8, 0x0a, 0x22, 0xf4, 0xd9, 0x58, 0x01, 0x9c, 0xbf, 0x5f, 0x31, 0x46, 0x6e, - 0xa9, 0x9e, 0x4b, 0xab, 0xab, 0x67, 0x15, 0x50, 0xd0, 0x18, 0x1d, 0x4c, 0xdd, 0x1a, 0x84, 0xd3, 0x86, 0xf6, 0xc1, - 0xc3, 0x23, 0xd2, 0x6b, 0x28, 0x62, 0xb1, 0x70, 0x56, 0xb8, 0xd4, 0xea, 0x6a, 0x61, 0x2a, 0x47, 0x7a, 0x24, 0xb9, - 0x72, 0x3b, 0x70, 0xfb, 0xde, 0xb4, 0x06, 0x09, 0x70, 0x8e, 0x18, 0xe2, 0x82, 0x46, 0x78, 0x5c, 0x13, 0x24, 0x48, - 0x48, 0x6f, 0x0c, 0xc8, 0x22, 0xc1, 0x45, 0xa6, 0x24, 0x7a, 0x11, 0x94, 0xda, 0x3d, 0x1d, 0xe9, 0x53, 0x80, 0x8b, - 0x71, 0xb2, 0x5a, 0x80, 0x25, 0x84, 0xf1, 0xba, 0xe6, 0x22, 0xc0, 0x56, 0x06, 0xb8, 0xb1, 0x66, 0x54, 0x70, 0x2e, - 0xec, 0xd0, 0x68, 0xd7, 0xca, 0xcf, 0xef, 0xc7, 0x02, 0x5c, 0x7a, 0xd1, 0x2c, 0x20, 0x10, 0x67, 0x2e, 0xef, 0x03, - 0x08, 0x39, 0x48, 0x5b, 0xa3, 0x37, 0x2d, 0x61, 0xa3, 0x84, 0x7c, 0x5a, 0x74, 0xf9, 0x95, 0x0f, 0x8d, 0x78, 0x58, - 0x2b, 0x6a, 0x2a, 0x41, 0x9f, 0xb1, 0x0d, 0x3e, 0xb8, 0x51, 0x93, 0xae, 0x0f, 0x96, 0x00, 0xa4, 0xc7, 0x32, 0x19, - 0x70, 0x8f, 0xa6, 0x17, 0xbd, 0x06, 0x52, 0xfa, 0xae, 0x1c, 0x39, 0x0e, 0x51, 0x7c, 0xbe, 0x45, 0x31, 0xb8, 0x37, - 0xad, 0xf1, 0x18, 0xc4, 0x07, 0x59, 0x32, 0xbe, 0x59, 0x14, 0x73, 0xac, 0x38, 0x13, 0x21, 0x7f, 0xd9, 0x48, 0x1a, - 0x09, 0x2b, 0x9d, 0xb6, 0x4a, 0x9a, 0x0a, 0x1b, 0x1b, 0xa0, 0x10, 0xa9, 0x87, 0xa0, 0x27, 0xb0, 0xeb, 0x0d, 0x89, - 0x79, 0x38, 0xd2, 0x52, 0xa4, 0x2f, 0x45, 0x5f, 0x73, 0x76, 0xca, 0x80, 0x4d, 0x84, 0x73, 0x73, 0x49, 0xf0, 0xdf, - 0xc4, 0xb6, 0x2e, 0x2e, 0x50, 0x31, 0xa3, 0x95, 0xe0, 0x21, 0x2c, 0x86, 0x97, 0x45, 0x05, 0x22, 0xeb, 0x6d, 0x7a, - 0x99, 0xb4, 0x92, 0x56, 0x79, 0x2c, 0x01, 0xd4, 0x71, 0x4f, 0x56, 0x16, 0x7a, 0x32, 0x1c, 0x61, 0x1f, 0x64, 0x9c, - 0x62, 0x1c, 0xc7, 0x9a, 0xd4, 0x66, 0xe4, 0xba, 0x13, 0x2d, 0x16, 0x32, 0xe3, 0xa1, 0xae, 0xa2, 0x12, 0x12, 0x18, - 0xd5, 0x24, 0x5d, 0x04, 0xde, 0xfa, 0x89, 0xf7, 0x04, 0x90, 0x80, 0xe8, 0x13, 0x3e, 0xf2, 0x93, 0x0c, 0xad, 0x86, - 0x84, 0x62, 0x45, 0xae, 0x21, 0xe7, 0xc5, 0x1b, 0xe5, 0x28, 0x72, 0xa7, 0xd1, 0x89, 0xbf, 0x16, 0xed, 0x9b, 0xc2, - 0xe6, 0x10, 0x84, 0xc3, 0x47, 0x85, 0x5d, 0xe8, 0x49, 0x3b, 0x95, 0x6a, 0x63, 0xa3, 0x9e, 0x87, 0x03, 0xde, 0xda, - 0x94, 0x09, 0x1e, 0xff, 0x5b, 0x43, 0x0d, 0xd1, 0xe6, 0xaf, 0x63, 0x06, 0x6c, 0xb3, 0xcd, 0xf6, 0x74, 0x0b, 0xf8, - 0x93, 0x38, 0xd9, 0x67, 0x50, 0x53, 0x36, 0x0f, 0x16, 0xdb, 0x75, 0x5f, 0x4e, 0x7e, 0x26, 0x53, 0x01, 0xc4, 0x55, - 0x41, 0xd5, 0x63, 0x64, 0x38, 0x20, 0xed, 0xa5, 0xe1, 0x71, 0x31, 0x40, 0x8a, 0x8c, 0xab, 0x92, 0x02, 0x81, 0x66, - 0x33, 0xa2, 0xb8, 0x01, 0xf4, 0xd8, 0x8c, 0xa3, 0xc4, 0x28, 0xb8, 0x41, 0x9e, 0x34, 0xd8, 0x98, 0x03, 0x97, 0x6a, - 0xd1, 0xac, 0xd2, 0xe6, 0x10, 0xd9, 0x03, 0x8b, 0x02, 0xe2, 0xf8, 0xf3, 0x5a, 0x43, 0x82, 0xbc, 0xe1, 0x7c, 0x12, - 0xc2, 0x00, 0xb7, 0x61, 0x04, 0xd9, 0xc3, 0x38, 0x22, 0xa1, 0xb8, 0xa9, 0x23, 0x7d, 0xfd, 0xc8, 0xde, 0x54, 0xde, - 0xef, 0x5a, 0x60, 0x18, 0xc7, 0x83, 0x81, 0xde, 0xbc, 0xd0, 0x92, 0x6e, 0x50, 0x97, 0x10, 0xf3, 0xb3, 0xb3, 0x99, - 0x19, 0x67, 0x6b, 0x8e, 0xe1, 0x61, 0xd8, 0x5c, 0x94, 0xf7, 0xf7, 0x6e, 0x12, 0x20, 0xbf, 0x13, 0x56, 0x7d, 0x72, - 0x12, 0x4f, 0x54, 0xfd, 0x5e, 0xd6, 0x3f, 0x12, 0xaf, 0x7f, 0x18, 0x50, 0xb2, 0xe9, 0xa1, 0x5e, 0xa9, 0x7b, 0x8b, - 0xe5, 0xac, 0xec, 0x9a, 0x82, 0x4a, 0x4b, 0x97, 0x65, 0x8c, 0x03, 0x49, 0xa0, 0x82, 0x7e, 0x29, 0xfb, 0xbc, 0x55, - 0x38, 0x50, 0x41, 0x21, 0x5b, 0x3f, 0x0d, 0xea, 0xe2, 0xf4, 0x2a, 0xc5, 0x2c, 0xc5, 0x18, 0xcf, 0x4e, 0x6d, 0x7d, - 0x1b, 0x90, 0x4e, 0x9d, 0xd2, 0xc0, 0xf3, 0x13, 0xdb, 0xed, 0xf6, 0x89, 0x13, 0x02, 0xb1, 0x52, 0x38, 0x11, 0x9b, - 0x59, 0x6c, 0x7e, 0xd0, 0x88, 0x54, 0x7e, 0x30, 0x0e, 0xc8, 0xca, 0x39, 0x6c, 0x81, 0xec, 0xb9, 0x29, 0x3c, 0x30, - 0xe6, 0x78, 0xdf, 0xf2, 0xd0, 0xad, 0xbf, 0xc3, 0x9f, 0x90, 0x93, 0x19, 0x65, 0xa6, 0xcf, 0xeb, 0xc1, 0x74, 0x57, - 0xdd, 0xb3, 0xc4, 0xe6, 0xcd, 0x75, 0xd2, 0x8b, 0x64, 0xb1, 0x97, 0xa2, 0x49, 0xba, 0x0c, 0x66, 0xed, 0x32, 0x88, - 0x5a, 0x2a, 0x60, 0xda, 0xe9, 0x6d, 0xa6, 0x71, 0x56, 0x40, 0x9f, 0x01, 0x33, 0xbb, 0xbb, 0x04, 0x5c, 0x17, 0x19, - 0x2c, 0xb1, 0x52, 0x88, 0xc2, 0xe3, 0x29, 0xed, 0xde, 0x4f, 0x0c, 0x94, 0x3e, 0x76, 0x81, 0xec, 0xa5, 0xa3, 0x87, - 0xa4, 0x76, 0x84, 0x28, 0xa2, 0x96, 0xfd, 0x21, 0x82, 0x42, 0x8a, 0x33, 0xfc, 0x80, 0xe9, 0xce, 0x47, 0xc8, 0xb8, - 0x00, 0xf9, 0xd9, 0x4c, 0xb4, 0xd5, 0x77, 0x5b, 0xc4, 0xc0, 0xcb, 0x0f, 0x25, 0xee, 0x27, 0xbd, 0x95, 0x6f, 0xc2, - 0xe3, 0x58, 0x71, 0x16, 0xc8, 0x58, 0xa1, 0x30, 0x8c, 0xe6, 0xfc, 0x04, 0x49, 0xd2, 0x7b, 0x38, 0x8f, 0x02, 0xb8, - 0x0c, 0xc1, 0x88, 0x02, 0xb5, 0x8d, 0x60, 0xf6, 0xc2, 0x4c, 0x35, 0xa0, 0xcc, 0x2d, 0x9a, 0x29, 0xc9, 0x5a, 0x3b, - 0x99, 0xe3, 0xcc, 0x73, 0x3f, 0x53, 0x18, 0x00, 0x54, 0x6c, 0xfa, 0xbd, 0x6a, 0xc5, 0xf2, 0x3a, 0x1e, 0x66, 0x6d, - 0xe5, 0x84, 0x98, 0x75, 0xf6, 0xfb, 0x14, 0x4d, 0x52, 0x01, 0xc8, 0x0a, 0xac, 0x4e, 0x8d, 0x49, 0x2a, 0xe7, 0x03, - 0xa3, 0x9b, 0x3a, 0x18, 0x46, 0x2c, 0x43, 0x65, 0x69, 0x1a, 0x06, 0x87, 0x6d, 0xfb, 0x3e, 0xc8, 0xe8, 0xd0, 0xef, - 0x5b, 0xd9, 0x58, 0x0a, 0x81, 0x96, 0x05, 0x5a, 0x3e, 0x0c, 0x68, 0x52, 0x86, 0x2b, 0x45, 0x79, 0x22, 0x47, 0xca, - 0x3d, 0xb2, 0xe4, 0x24, 0xef, 0xfb, 0xa9, 0x69, 0x57, 0x97, 0x0c, 0x88, 0x66, 0x2e, 0x54, 0xc3, 0xd7, 0x2c, 0xf9, - 0x33, 0x4c, 0x98, 0xac, 0xbd, 0x71, 0x98, 0xd7, 0x64, 0x8d, 0x1c, 0x99, 0xaa, 0x0e, 0x18, 0x82, 0x6a, 0x74, 0x39, - 0x36, 0xc6, 0x4f, 0x2c, 0x1a, 0xb5, 0xa1, 0x30, 0xaf, 0x1d, 0x2b, 0x25, 0x67, 0x96, 0x8e, 0x98, 0x77, 0x37, 0x16, - 0x9d, 0xea, 0xa7, 0x07, 0xb2, 0x65, 0xfd, 0x00, 0xdf, 0x59, 0x22, 0xc2, 0x07, 0xcb, 0x1f, 0xce, 0x6f, 0x23, 0xbb, - 0x74, 0x2d, 0x74, 0x4c, 0x6b, 0xeb, 0xf0, 0xa7, 0x66, 0x93, 0x96, 0x2c, 0xf5, 0xdf, 0xcb, 0x00, 0x15, 0xe4, 0x29, - 0xa8, 0x42, 0x75, 0x54, 0x42, 0x94, 0xe1, 0x60, 0x53, 0xad, 0xab, 0xa3, 0xf2, 0xc6, 0xb9, 0xeb, 0x1d, 0xdc, 0xd9, - 0x81, 0x2c, 0xa9, 0x3b, 0xc2, 0x27, 0x17, 0x7d, 0x15, 0x21, 0x45, 0xd8, 0x32, 0x23, 0x77, 0xf6, 0xe5, 0xe9, 0x23, - 0xaf, 0x6f, 0xed, 0x3c, 0x1d, 0x3a, 0x5f, 0x61, 0x90, 0x5d, 0x7b, 0x74, 0x6c, 0x64, 0xcb, 0x8d, 0x68, 0xdb, 0x78, - 0xde, 0x1d, 0xa5, 0xd1, 0x4f, 0x4a, 0x89, 0x57, 0x6e, 0x82, 0xa8, 0xfd, 0xc1, 0x42, 0xf2, 0x19, 0x9e, 0x43, 0xb6, - 0x60, 0xb4, 0x68, 0x4c, 0x6c, 0x3c, 0x07, 0xdc, 0x23, 0x8a, 0xeb, 0x47, 0x8f, 0x05, 0x09, 0x17, 0x9c, 0x01, 0xf6, - 0xd2, 0x9c, 0xdd, 0xb6, 0x06, 0xd8, 0xe5, 0x62, 0xe2, 0x8a, 0x3e, 0x2e, 0xcc, 0xf1, 0xee, 0xfa, 0x85, 0xb2, 0x23, - 0xf1, 0xae, 0xb9, 0x6c, 0x6f, 0x79, 0x2d, 0xa2, 0x34, 0x15, 0x01, 0x4c, 0x13, 0x84, 0x86, 0x32, 0xc7, 0x14, 0xe9, - 0xcd, 0xf4, 0x6a, 0x98, 0x73, 0x27, 0x6b, 0x2e, 0x76, 0x65, 0x50, 0xa8, 0x01, 0x51, 0x19, 0xe2, 0x38, 0x39, 0x4e, - 0x18, 0xd8, 0x6d, 0x02, 0xd0, 0x11, 0xb4, 0x61, 0x48, 0xe8, 0xad, 0x13, 0x40, 0x0b, 0xb1, 0xc8, 0x1f, 0x32, 0x29, - 0x15, 0xa7, 0xbe, 0x97, 0x97, 0x79, 0xf3, 0x82, 0x1b, 0x14, 0x47, 0x08, 0xda, 0x8a, 0xe7, 0xc1, 0x15, 0x43, 0xb7, - 0x47, 0xe1, 0xd0, 0xc6, 0x56, 0xe6, 0x19, 0x7f, 0x96, 0xe8, 0x07, 0xca, 0x6e, 0xec, 0xf5, 0x90, 0x76, 0xaa, 0x39, - 0x28, 0xc7, 0x30, 0xf8, 0x96, 0xe9, 0x51, 0xd2, 0xba, 0x05, 0x2e, 0x86, 0xdf, 0x3c, 0xc4, 0x7b, 0xef, 0xb8, 0x3d, - 0x7d, 0xcc, 0xd3, 0xee, 0xef, 0xc3, 0x67, 0x83, 0xd9, 0x97, 0xf9, 0x80, 0x2e, 0x1e, 0x0e, 0x5c, 0x43, 0x02, 0x33, - 0x12, 0x10, 0xba, 0xd1, 0xf5, 0xd6, 0xbd, 0x43, 0xcd, 0xf3, 0xe0, 0xc4, 0x3d, 0xe5, 0x37, 0x2e, 0x49, 0x17, 0x49, - 0xd7, 0x08, 0x65, 0xef, 0xff, 0x45, 0x0e, 0x4b, 0xcf, 0x23, 0xe3, 0xd1, 0xa6, 0xa6, 0x38, 0x13, 0x9c, 0x5d, 0x0e, - 0xf6, 0x16, 0x24, 0x8c, 0x63, 0xe4, 0x92, 0xc1, 0x38, 0x67, 0x66, 0x4c, 0xc4, 0xd6, 0x1c, 0xa4, 0x8d, 0x0c, 0x79, - 0x9d, 0x22, 0xf7, 0xc5, 0x4e, 0x01, 0xfa, 0x50, 0xc8, 0x69, 0xb7, 0x15, 0xfa, 0x24, 0x60, 0xe0, 0xff, 0x4e, 0x4b, - 0xfb, 0x1e, 0xf9, 0x3e, 0x6d, 0x62, 0x89, 0x14, 0x9b, 0xb1, 0x51, 0xcf, 0xc5, 0xdc, 0x2a, 0x64, 0xc3, 0xfa, 0x45, - 0x84, 0xfa, 0xdd, 0xac, 0x3c, 0x3b, 0xe6, 0x27, 0x12, 0xc0, 0x69, 0xeb, 0x10, 0x6c, 0xe7, 0xf3, 0xad, 0xff, 0x26, - 0xe9, 0xfb, 0xcc, 0xa2, 0x87, 0x73, 0x9d, 0x8c, 0x35, 0x27, 0xb0, 0xa0, 0xd4, 0xdb, 0xb1, 0x73, 0x7d, 0xba, 0xc7, - 0x73, 0xd5, 0x2c, 0xca, 0x20, 0xb9, 0xb6, 0x8b, 0xa4, 0x48, 0x3c, 0xb9, 0x7a, 0xe3, 0x6c, 0xc6, 0xf8, 0x58, 0xfc, - 0xbd, 0x3d, 0x4e, 0xfb, 0x7e, 0xe3, 0x33, 0xda, 0xbb, 0xf4, 0x7f, 0xce, 0xa6, 0xd3, 0xdf, 0x21, 0xe3, 0xb9, 0xae, - 0xd9, 0x52, 0x35, 0x85, 0x54, 0x93, 0x2d, 0x02, 0x50, 0x8d, 0x38, 0xdf, 0x1d, 0x77, 0xfb, 0xef, 0x0a, 0xa2, 0x99, - 0xbf, 0x20, 0xee, 0xbe, 0xd7, 0x52, 0x3d, 0x6d, 0x71, 0x34, 0xe5, 0xac, 0xf7, 0xc8, 0x6e, 0xf6, 0x1e, 0xf0, 0xb6, - 0xb4, 0xfa, 0xa7, 0xfa, 0x4f, 0xf8, 0xdd, 0x62, 0xf3, 0xb7, 0xdd, 0x7c, 0xea, 0xc3, 0xf6, 0xa4, 0xae, 0xb6, 0x78, - 0xb3, 0xd6, 0xdf, 0xec, 0x79, 0xbb, 0xdb, 0x7c, 0xa0, 0xd3, 0xfa, 0x2f, 0xe5, 0x75, 0x35, 0x18, 0x97, 0xea, 0xaf, - 0x40, 0xe2, 0xdf, 0x2a, 0xf4, 0xee, 0x0e, 0x90, 0x2f, 0xd5, 0xec, 0x20, 0xc3, 0xcc, 0xf8, 0x60, 0xbc, 0x0b, 0x5d, - 0x68, 0xeb, 0xf1, 0x6e, 0x14, 0x26, 0x2a, 0xc4, 0xfd, 0xdc, 0x35, 0x33, 0xd5, 0xbb, 0xe4, 0x6a, 0xd2, 0xa5, 0x5f, - 0x1b, 0x14, 0xaf, 0x4d, 0x68, 0xb1, 0x66, 0xc4, 0x36, 0x35, 0xff, 0x05, 0x58, 0xfe, 0xb9, 0xe0, 0x19, 0xc6, 0x4d, - 0xda, 0x8f, 0x6a, 0xbb, 0x52, 0xf9, 0xfe, 0xa7, 0xf1, 0xd7, 0xa6, 0x9e, 0xb2, 0xce, 0x7f, 0xde, 0x7d, 0x5b, 0xfe, - 0x99, 0xcb, 0x8e, 0x4c, 0x55, 0xfd, 0x05, 0xf9, 0xc4, 0xa4, 0x2b, 0xe5, 0x78, 0x3d, 0xcb, 0xfe, 0x5f, 0x84, 0xbb, - 0x7f, 0x3b, 0xff, 0xf2, 0x9f, 0x66, 0xe1, 0x7d, 0x20, 0xcd, 0x4e, 0xc3, 0x17, 0x92, 0xdf, 0xd9, 0xb2, 0x7a, 0x7e, - 0xe7, 0x0b, 0xd4, 0x58, 0x71, 0x8f, 0xac, 0x2f, 0x65, 0x62, 0x55, 0x2e, 0xe0, 0xd6, 0x7f, 0x3b, 0xd5, 0x5f, 0x0f, - 0xe4, 0xf3, 0x9e, 0x92, 0xf9, 0x62, 0xf8, 0xb5, 0x79, 0x73, 0x4f, 0xa7, 0x7a, 0xd7, 0x2f, 0xfc, 0x78, 0x4c, 0x4a, - 0x7f, 0xd5, 0xe3, 0x32, 0xb8, 0xb9, 0x52, 0xff, 0xd5, 0xc2, 0xa7, 0x2b, 0x83, 0xf2, 0xcf, 0xc8, 0xc7, 0xe3, 0xf5, - 0xcd, 0xe2, 0x63, 0xf9, 0x3e, 0x0b, 0x18, 0x27, 0x38, 0xa3, 0xe6, 0x0b, 0xdc, 0x11, 0x54, 0x1f, 0xe2, 0x91, 0xac, - 0x3f, 0x99, 0x55, 0x3c, 0xdc, 0x2b, 0x70, 0xfc, 0x96, 0x57, 0x7e, 0xe6, 0xd2, 0x24, 0x5c, 0x30, 0x4e, 0x7f, 0xc4, - 0xa3, 0xef, 0x3b, 0x18, 0x7d, 0xd0, 0xbb, 0xf1, 0xdd, 0x8c, 0x3a, 0xe2, 0x63, 0xf3, 0xac, 0xab, 0x96, 0xc6, 0x5b, - 0x29, 0x39, 0x61, 0x1b, 0xfd, 0x55, 0xc0, 0x43, 0x0c, 0xda, 0xbe, 0xf7, 0xad, 0xf2, 0x37, 0x7e, 0x17, 0xa6, 0xf7, - 0xd6, 0x8f, 0xbf, 0xbf, 0x12, 0xef, 0xf6, 0xef, 0x0c, 0x13, 0x88, 0xf5, 0xc0, 0xbb, 0xe8, 0xff, 0xa8, 0x86, 0x4f, - 0x48, 0xe6, 0x44, 0x61, 0x4d, 0xdd, 0x2f, 0xd5, 0xf7, 0xe1, 0xe2, 0x41, 0x24, 0x5f, 0x16, 0xef, 0xfb, 0x44, 0x1e, - 0xee, 0xd1, 0xb3, 0xbc, 0x97, 0x46, 0x1c, 0x40, 0x0d, 0x05, 0xc8, 0x82, 0x7c, 0x32, 0x8c, 0xc0, 0xce, 0x73, 0x0a, - 0x3b, 0xa7, 0xaa, 0xcf, 0xee, 0x22, 0xd2, 0xbb, 0xd5, 0xdc, 0x9a, 0x3f, 0x01, 0x4a, 0x61, 0x9b, 0x08, 0xb0, 0xef, - 0xa7, 0x3b, 0x9a, 0xd4, 0x7a, 0x9d, 0x6e, 0xfd, 0xe9, 0xe4, 0x4a, 0x4d, 0xea, 0xb6, 0xba, 0xc8, 0x78, 0xe0, 0x79, - 0x93, 0x13, 0x9e, 0xdd, 0x98, 0xe8, 0x14, 0x63, 0x13, 0x0e, 0xda, 0x99, 0x29, 0xeb, 0xb1, 0x73, 0x1d, 0x12, 0x91, - 0xdd, 0xd0, 0x10, 0x77, 0x99, 0xdb, 0x23, 0xb8, 0x51, 0x11, 0x89, 0x5a, 0x42, 0x7d, 0xf1, 0x7b, 0x26, 0x93, 0x89, - 0x6f, 0xe5, 0x39, 0x1b, 0x7e, 0xe1, 0x7f, 0x56, 0xc9, 0x82, 0x01, 0xc8, 0xc9, 0xd4, 0xc9, 0x23, 0x50, 0xf1, 0x35, - 0x41, 0xb4, 0xf3, 0x59, 0x4e, 0xdc, 0x3b, 0x2c, 0xca, 0x53, 0xcd, 0xcc, 0xf3, 0xbf, 0x6b, 0x60, 0xcd, 0x42, 0x51, - 0xc4, 0x46, 0x34, 0xcb, 0xf6, 0x76, 0x33, 0x8b, 0x7a, 0x1e, 0xbe, 0x02, 0xe1, 0xec, 0x32, 0x00, 0x7d, 0x5b, 0xd5, - 0xb0, 0x96, 0x33, 0xf3, 0x97, 0xde, 0x08, 0x01, 0x6a, 0x1e, 0xf4, 0x30, 0x66, 0xef, 0x4d, 0xc9, 0xfe, 0x51, 0x90, - 0x53, 0x9e, 0x9b, 0x9a, 0xce, 0x19, 0x67, 0xc9, 0x73, 0x38, 0x93, 0x12, 0xd2, 0x4e, 0x7b, 0xa4, 0x22, 0xd2, 0xf0, - 0xda, 0xac, 0x5e, 0x2c, 0x65, 0x7d, 0xb8, 0xe5, 0x85, 0x29, 0x20, 0x0c, 0x48, 0x82, 0xd8, 0x53, 0xf8, 0x39, 0x58, - 0xf4, 0x21, 0x14, 0x45, 0x12, 0xbd, 0x52, 0x38, 0xbd, 0x9d, 0x98, 0xbd, 0x24, 0xa9, 0xd1, 0xe9, 0x11, 0xae, 0xff, - 0xbe, 0xb7, 0x73, 0x8e, 0x9e, 0x49, 0x16, 0xe9, 0xdb, 0xf4, 0x97, 0x51, 0xbb, 0x59, 0xa2, 0xa9, 0xed, 0x0d, 0x00, - 0xce, 0xb1, 0x52, 0xc3, 0xee, 0xfb, 0xa5, 0x91, 0xa2, 0x25, 0xbe, 0xbc, 0x20, 0xa3, 0xa2, 0x4b, 0x5a, 0xea, 0xbb, - 0x38, 0x5d, 0x54, 0x65, 0x1b, 0xfc, 0x3e, 0x39, 0xe0, 0xc5, 0x1b, 0x30, 0x49, 0x5f, 0x91, 0x3e, 0x12, 0x04, 0xa7, - 0xcd, 0xc6, 0x6c, 0x6f, 0xdd, 0x47, 0xf2, 0xd6, 0xc2, 0x7f, 0xd1, 0x5e, 0x58, 0xf5, 0xa2, 0x67, 0x2a, 0x03, 0xdc, - 0x22, 0x5f, 0x96, 0x71, 0x4e, 0x34, 0xad, 0x5a, 0xf0, 0xa2, 0x2b, 0xa8, 0x33, 0xf7, 0x34, 0x6f, 0xed, 0x22, 0xd8, - 0x10, 0xda, 0xe7, 0xc1, 0x2c, 0x59, 0x60, 0x85, 0x20, 0x94, 0xb7, 0x63, 0xeb, 0x19, 0xd7, 0x5f, 0x35, 0xf8, 0x65, - 0xe5, 0x62, 0x29, 0x74, 0x80, 0x61, 0xf2, 0xdb, 0x1a, 0x08, 0x9e, 0xfa, 0x12, 0xca, 0x02, 0xbd, 0x6d, 0xe1, 0xf1, - 0x9a, 0xee, 0xde, 0x9d, 0xe1, 0x84, 0x10, 0xdf, 0x6f, 0xc6, 0x42, 0x79, 0x1e, 0xfd, 0x92, 0xd1, 0x08, 0xcb, 0x1d, - 0x8e, 0x28, 0xa7, 0x47, 0x83, 0x6c, 0x70, 0x7c, 0x67, 0xeb, 0x51, 0x65, 0x59, 0xe6, 0x11, 0x16, 0x9f, 0x92, 0x05, - 0xf6, 0x82, 0xec, 0xe2, 0xfe, 0xd3, 0x75, 0x28, 0x4c, 0xb1, 0x07, 0x6a, 0x72, 0xab, 0xde, 0xa6, 0x5c, 0x3b, 0xfe, - 0x35, 0x5b, 0xe8, 0xc8, 0x6e, 0xf7, 0x90, 0x7e, 0x8b, 0x6b, 0x6b, 0x0c, 0x6d, 0xdf, 0x90, 0x44, 0xe9, 0x34, 0xdd, - 0x3d, 0x03, 0x0a, 0xf4, 0x3f, 0x26, 0x94, 0xfc, 0x85, 0x34, 0xd3, 0xac, 0x4b, 0xb1, 0xab, 0xfd, 0x12, 0xe7, 0x64, - 0xfa, 0xeb, 0x99, 0x87, 0x7a, 0xa9, 0xfe, 0xdf, 0xeb, 0x35, 0x0d, 0x98, 0xe8, 0x8d, 0x69, 0x04, 0x34, 0x90, 0x22, - 0x95, 0x98, 0x6f, 0x2c, 0xa3, 0x06, 0x49, 0x67, 0x99, 0x91, 0x52, 0xae, 0xa3, 0xfb, 0x8d, 0x0a, 0x85, 0x0b, 0xdd, - 0xbd, 0xad, 0xb8, 0x31, 0xa5, 0xb7, 0x45, 0x8f, 0xe2, 0x37, 0xe6, 0xbd, 0x19, 0xc7, 0x71, 0x73, 0x91, 0x21, 0xe1, - 0x02, 0x3d, 0x8b, 0x1e, 0x57, 0xe7, 0x88, 0xd7, 0x44, 0x39, 0x78, 0x04, 0xd1, 0x31, 0xd1, 0x13, 0xe2, 0x66, 0xbc, - 0xf5, 0x16, 0x7c, 0x62, 0x40, 0xbe, 0xe7, 0xcd, 0x12, 0x7c, 0x68, 0x5b, 0xe5, 0x39, 0x06, 0x1d, 0xf0, 0xab, 0xf5, - 0x6c, 0x29, 0x00, 0x0b, 0xb3, 0x29, 0xef, 0x6a, 0x29, 0xd0, 0x85, 0x86, 0xa4, 0xc9, 0xf3, 0x5d, 0x3d, 0x1d, 0xbf, - 0x44, 0xc3, 0x54, 0x24, 0x52, 0xd2, 0x9b, 0xf8, 0x86, 0xf3, 0x78, 0xa0, 0xad, 0x4e, 0x7d, 0x16, 0x7a, 0xb5, 0x55, - 0x9d, 0x9d, 0x77, 0x93, 0xd7, 0x61, 0x41, 0x17, 0x67, 0x1b, 0x50, 0x8e, 0x35, 0x93, 0x6e, 0x4a, 0x56, 0x55, 0x93, - 0xa2, 0x9c, 0x04, 0x86, 0x68, 0x17, 0xe1, 0x0a, 0xca, 0x9f, 0x57, 0x7d, 0x22, 0x95, 0xfa, 0x62, 0x16, 0x7f, 0x7a, - 0xb0, 0x52, 0x15, 0xf1, 0x3f, 0x38, 0xf2, 0x92, 0xed, 0x12, 0x29, 0x96, 0xa5, 0xa2, 0xf7, 0x33, 0x41, 0x5e, 0xfd, - 0xe1, 0x86, 0xe5, 0xba, 0x87, 0xfd, 0x2a, 0xd5, 0x1b, 0xe2, 0x69, 0xac, 0x18, 0x99, 0x5a, 0x5c, 0xf1, 0x96, 0xcb, - 0x53, 0x48, 0x8b, 0xf5, 0x98, 0x97, 0x2e, 0x69, 0xbc, 0x07, 0xde, 0x6e, 0x30, 0x41, 0x3f, 0x49, 0x6e, 0xd7, 0xb1, - 0x38, 0xa8, 0x45, 0x5d, 0xc8, 0xdb, 0x47, 0x63, 0x76, 0xe4, 0x72, 0x03, 0x1f, 0xbf, 0xb8, 0xd3, 0x39, 0x6f, 0xbc, - 0x56, 0xbe, 0xaa, 0x3b, 0xa1, 0xe0, 0xd7, 0x06, 0xa8, 0x26, 0x43, 0x6c, 0x11, 0xa2, 0x05, 0xdf, 0x7c, 0xb4, 0x59, - 0x9e, 0xd0, 0x12, 0x93, 0x66, 0xe5, 0xf2, 0xc5, 0x0b, 0xf3, 0xae, 0xd8, 0x1f, 0x2b, 0xe7, 0x66, 0x2a, 0xe3, 0x2b, - 0x7d, 0xed, 0x2a, 0x72, 0x59, 0x78, 0x8d, 0x42, 0x45, 0x28, 0xaa, 0x48, 0x1b, 0x17, 0xd8, 0xea, 0x66, 0xd8, 0xf2, - 0x99, 0x79, 0xa1, 0x69, 0xda, 0x98, 0x71, 0x52, 0x5c, 0x32, 0xc2, 0x3f, 0xe8, 0x08, 0xf6, 0x45, 0xab, 0x3c, 0xff, - 0xb1, 0x63, 0xb1, 0x70, 0x03, 0xed, 0x38, 0x7a, 0x21, 0x47, 0x25, 0xe9, 0xd1, 0x27, 0x85, 0xb2, 0xca, 0x34, 0xf2, - 0xae, 0xfa, 0xa4, 0xc2, 0x53, 0x74, 0x07, 0x45, 0x8e, 0xc2, 0x96, 0x0c, 0x6b, 0x65, 0x8c, 0xeb, 0x11, 0x7e, 0xd6, - 0xce, 0xde, 0x39, 0xdc, 0xec, 0x41, 0xec, 0xf0, 0x5f, 0x94, 0xe3, 0x73, 0x93, 0x25, 0x1e, 0x46, 0xfa, 0x2a, 0x79, - 0x9b, 0xa7, 0x13, 0x1f, 0xbe, 0xc9, 0x8c, 0xec, 0x96, 0xfa, 0x4f, 0xec, 0xf3, 0x3a, 0x42, 0x44, 0xce, 0xf3, 0x5d, - 0x45, 0x46, 0xa7, 0x70, 0x91, 0xeb, 0x94, 0xd2, 0x47, 0x95, 0x42, 0x02, 0x65, 0x49, 0xe3, 0x96, 0x65, 0xf7, 0x1f, - 0x7f, 0x50, 0xa1, 0xe5, 0x6b, 0x07, 0x66, 0xd2, 0x6d, 0x66, 0x96, 0x48, 0x16, 0x35, 0x46, 0x76, 0xa3, 0xe7, 0x1f, - 0x15, 0x89, 0x04, 0x49, 0x1a, 0x43, 0xa4, 0x73, 0x37, 0xdc, 0xe9, 0xff, 0x0e, 0xf7, 0xec, 0xc6, 0x92, 0xa2, 0x69, - 0x16, 0xca, 0xec, 0x0f, 0xf8, 0xa6, 0xdf, 0x21, 0x87, 0xa6, 0x8a, 0x92, 0x41, 0x0d, 0x6f, 0xe4, 0xdc, 0x86, 0x6e, - 0xcd, 0x83, 0xf5, 0xec, 0x17, 0xd0, 0x67, 0x8c, 0x06, 0x6a, 0xab, 0xd1, 0x4b, 0xd2, 0x37, 0x4a, 0xd4, 0x79, 0x1f, - 0x14, 0x14, 0xd4, 0xdb, 0x40, 0xe7, 0xa6, 0x26, 0x44, 0xbb, 0x5f, 0x04, 0x45, 0x90, 0x85, 0x68, 0xbc, 0xf0, 0xb1, - 0x7c, 0x91, 0xee, 0x49, 0x94, 0x48, 0xa8, 0x76, 0x5c, 0x7c, 0xcf, 0xa5, 0x34, 0x28, 0x78, 0xd4, 0x1a, 0x50, 0xec, - 0xba, 0x40, 0x7d, 0x80, 0x95, 0x55, 0xd6, 0x61, 0xde, 0x0a, 0x52, 0x35, 0x1a, 0x56, 0xdb, 0xcc, 0x2e, 0x4e, 0x9e, - 0x29, 0x32, 0x93, 0x84, 0x3d, 0xeb, 0xef, 0x2a, 0x5e, 0xe6, 0x48, 0x94, 0x95, 0x2d, 0x01, 0xeb, 0x5d, 0xb3, 0xc3, - 0xd1, 0x6c, 0x51, 0x5a, 0xbb, 0x16, 0xf6, 0xaf, 0x6c, 0x54, 0x49, 0x53, 0xaf, 0x63, 0x29, 0x71, 0x0d, 0x1b, 0xb9, - 0x4d, 0x06, 0xe2, 0x63, 0xf9, 0x6d, 0x92, 0x00, 0xe1, 0xbb, 0x78, 0xc4, 0x43, 0x37, 0x59, 0xb1, 0xa9, 0xec, 0x5c, - 0x59, 0xec, 0xf5, 0xe8, 0x05, 0x9c, 0x1e, 0x4d, 0xae, 0x24, 0x47, 0xb7, 0xc5, 0x79, 0x71, 0x57, 0xf1, 0x54, 0xe9, - 0xb2, 0xf8, 0x97, 0xfa, 0x0f, 0x54, 0x6e, 0x0f, 0x2b, 0x84, 0xfd, 0x2d, 0x91, 0xbb, 0x80, 0x94, 0x67, 0x81, 0x10, - 0x6a, 0x89, 0x08, 0x9b, 0x6f, 0x85, 0x28, 0xb0, 0x28, 0xb0, 0x49, 0xf3, 0x38, 0xc7, 0x6a, 0xbd, 0x15, 0x4d, 0x72, - 0x07, 0x92, 0x7b, 0xd8, 0x8d, 0x5b, 0x12, 0xca, 0xbd, 0xf2, 0xd8, 0xe6, 0x2f, 0x51, 0xd0, 0x07, 0x2d, 0x69, 0x5c, - 0x35, 0x02, 0x9c, 0x5e, 0xf2, 0xd5, 0x2b, 0xfd, 0xb6, 0xeb, 0x87, 0x1b, 0xe4, 0x9e, 0x65, 0x22, 0xd2, 0x2e, 0xc4, - 0xc4, 0xa7, 0xbe, 0xea, 0x3a, 0x1b, 0x07, 0xab, 0xb5, 0x8d, 0xf9, 0x78, 0x4a, 0x96, 0xad, 0x67, 0x97, 0x11, 0xbc, - 0xec, 0x38, 0x81, 0xc7, 0x77, 0x44, 0x17, 0x13, 0xd7, 0x48, 0x2a, 0x1a, 0x70, 0xc5, 0xd9, 0x46, 0x53, 0xbc, 0xef, - 0x53, 0xa0, 0xc3, 0xa2, 0xb9, 0x47, 0x65, 0xd0, 0x85, 0x80, 0x8e, 0x77, 0xee, 0x5e, 0x17, 0xc6, 0x6e, 0x9e, 0x28, - 0xad, 0xff, 0xc1, 0xad, 0x26, 0x2a, 0x0d, 0xeb, 0xb0, 0x04, 0x8a, 0x09, 0x39, 0xd1, 0x6e, 0xcc, 0xed, 0xd1, 0x43, - 0xc3, 0x67, 0x75, 0xd1, 0x68, 0x0d, 0xc4, 0x59, 0xe0, 0xf9, 0xdb, 0xb0, 0xb6, 0xb5, 0x11, 0x71, 0xff, 0x6b, 0x32, - 0x8a, 0x5a, 0x6e, 0x45, 0xe5, 0xcf, 0x3a, 0xc2, 0x45, 0x92, 0x81, 0xd9, 0x32, 0xfc, 0x46, 0x84, 0xd5, 0x1f, 0x21, - 0xe6, 0x1e, 0x87, 0x36, 0x21, 0xfd, 0xa5, 0x2d, 0xaf, 0xad, 0x87, 0x41, 0xc8, 0x87, 0x23, 0x9e, 0xa0, 0x88, 0x35, - 0xaa, 0x7b, 0x70, 0x32, 0x6c, 0x9c, 0x03, 0xab, 0xb6, 0x8b, 0x32, 0x0b, 0x67, 0x91, 0x91, 0x62, 0xe6, 0x33, 0xdb, - 0x04, 0x3e, 0x86, 0x0e, 0x3a, 0xa9, 0x3a, 0x75, 0x72, 0x50, 0x0d, 0x02, 0x30, 0x21, 0x0b, 0xed, 0x0b, 0x84, 0xae, - 0x11, 0x2c, 0xcb, 0x4a, 0xa5, 0xd5, 0x7a, 0x00, 0x8b, 0x8f, 0x50, 0xea, 0x17, 0x9f, 0xb8, 0xd5, 0x93, 0xce, 0xc1, - 0x28, 0xe2, 0xd0, 0x93, 0x5e, 0x8a, 0x3e, 0x45, 0x1e, 0x8b, 0x1d, 0x08, 0xb9, 0xb8, 0xf5, 0x4e, 0x36, 0x23, 0x1b, - 0x09, 0x5a, 0x09, 0xee, 0x01, 0x5a, 0xf7, 0xdc, 0x6a, 0x67, 0x3a, 0x21, 0xd0, 0x12, 0x69, 0x8c, 0x90, 0xe8, 0x1e, - 0x62, 0x0e, 0x89, 0x08, 0xf0, 0xa2, 0x60, 0x82, 0x29, 0x85, 0xb2, 0xb3, 0x1e, 0x52, 0xe8, 0xfd, 0x95, 0x65, 0x5c, - 0x4d, 0x64, 0x1e, 0x58, 0x61, 0x20, 0x8c, 0x33, 0x5f, 0x23, 0x0f, 0x09, 0x20, 0x67, 0x68, 0xfb, 0xa3, 0xa6, 0x47, - 0x6b, 0x33, 0x67, 0xda, 0xb8, 0x42, 0x36, 0x3e, 0x07, 0x45, 0xbc, 0x60, 0xc2, 0xf5, 0x59, 0xfd, 0xb8, 0xca, 0x75, - 0xa5, 0xe3, 0xd5, 0x8d, 0x94, 0xfb, 0x2a, 0xfe, 0xec, 0x12, 0x23, 0x59, 0x36, 0xbd, 0x69, 0x2a, 0x3d, 0x9d, 0x5a, - 0x7d, 0x67, 0x35, 0xd0, 0xb3, 0x3d, 0xc0, 0x13, 0x1e, 0x82, 0x4b, 0xcd, 0xc8, 0x2f, 0xb9, 0x04, 0x2d, 0xe0, 0x87, - 0x26, 0xa4, 0x23, 0x15, 0x0c, 0x8b, 0x79, 0x91, 0x96, 0xd3, 0xb2, 0xd8, 0x26, 0x35, 0x65, 0x60, 0x18, 0xc7, 0x64, - 0xa2, 0xc2, 0xa9, 0xfd, 0x03, 0xbf, 0xe7, 0xd9, 0x8c, 0x3c, 0xcd, 0x1a, 0x64, 0xf7, 0x6d, 0x9a, 0xc7, 0x2a, 0x17, - 0xd6, 0xda, 0x0a, 0x10, 0x7e, 0xc7, 0xbb, 0x82, 0xde, 0x48, 0xd1, 0x64, 0x98, 0xc1, 0x68, 0x69, 0xfc, 0xc8, 0xe0, - 0x7f, 0x97, 0x61, 0x55, 0xda, 0xa2, 0x06, 0x6e, 0x5f, 0xc4, 0x52, 0x1f, 0x94, 0x28, 0xd2, 0x56, 0x19, 0x62, 0xcb, - 0x63, 0x15, 0x7e, 0x57, 0x45, 0x47, 0x90, 0x61, 0xbb, 0x7e, 0xe6, 0xa8, 0xcd, 0xb1, 0x1f, 0x0e, 0x59, 0xb1, 0x27, - 0x73, 0x06, 0xc5, 0xc7, 0xfd, 0xc5, 0xa2, 0xab, 0x3a, 0x49, 0xcf, 0x16, 0x81, 0xba, 0x42, 0xc6, 0x53, 0xaf, 0x74, - 0x37, 0x52, 0x58, 0x6a, 0x64, 0x2b, 0xa0, 0x0c, 0x33, 0x54, 0x4b, 0x53, 0x74, 0xfb, 0x3d, 0x2b, 0x84, 0x44, 0x09, - 0x01, 0x46, 0x78, 0xef, 0x85, 0x2e, 0xfa, 0x7f, 0x9a, 0x37, 0xbe, 0x6f, 0x9d, 0x3a, 0x36, 0x0f, 0x47, 0x48, 0x09, - 0x10, 0x32, 0x29, 0xd7, 0xd0, 0x0f, 0x86, 0x82, 0xf1, 0x20, 0x51, 0x30, 0xf8, 0x39, 0xf6, 0x23, 0xe0, 0x66, 0x96, - 0x96, 0x47, 0x7e, 0x11, 0x4d, 0x4c, 0x89, 0xc7, 0x74, 0x46, 0x2a, 0xb7, 0xfb, 0x88, 0xab, 0x47, 0xba, 0x41, 0xf5, - 0x2d, 0x8a, 0x60, 0xf2, 0x2f, 0x35, 0x10, 0xde, 0xbd, 0x8e, 0xb9, 0x74, 0x9b, 0x9a, 0x37, 0x39, 0x00, 0xd3, 0xbd, - 0x2d, 0x51, 0xd7, 0x02, 0xa4, 0xde, 0x34, 0x85, 0x1f, 0xf6, 0x4f, 0x11, 0xb0, 0x38, 0x62, 0xb1, 0x49, 0x9d, 0x9e, - 0x53, 0xed, 0x7d, 0xb1, 0x6c, 0x04, 0xe1, 0xfe, 0x2a, 0xbb, 0xc8, 0x5d, 0x20, 0x90, 0xc9, 0x1a, 0x64, 0x10, 0x8e, - 0x35, 0xc3, 0x7a, 0x47, 0xab, 0xb2, 0xb1, 0x26, 0xad, 0xdd, 0xc7, 0xa5, 0xb4, 0xfb, 0x5a, 0x17, 0x0d, 0xa8, 0x81, - 0x21, 0xbc, 0xd6, 0xa2, 0x6d, 0x25, 0x60, 0x5e, 0xd5, 0xd8, 0x23, 0x98, 0x4b, 0x71, 0x29, 0xae, 0x25, 0x24, 0x1f, - 0x3f, 0x6a, 0x47, 0x8f, 0xd0, 0xd0, 0x64, 0xe3, 0xd3, 0x8d, 0x3c, 0x6d, 0xcf, 0x3f, 0xa8, 0x9d, 0xd8, 0xf7, 0xcb, - 0xe8, 0x40, 0xc8, 0xee, 0xd8, 0xfd, 0xe8, 0x87, 0x6f, 0x06, 0xce, 0x23, 0xda, 0xa9, 0xe1, 0xe1, 0xd0, 0x9b, 0x5c, - 0x2c, 0x99, 0xe6, 0x90, 0x3b, 0xa0, 0x29, 0xe3, 0x63, 0x6b, 0x03, 0x71, 0xad, 0x17, 0x12, 0x36, 0xd3, 0x10, 0x53, - 0xf9, 0x51, 0x63, 0x04, 0xc4, 0x28, 0x36, 0xd8, 0xc0, 0xb4, 0xef, 0x05, 0x6a, 0x36, 0x3f, 0x87, 0x55, 0x4e, 0x6d, - 0x11, 0x33, 0x4b, 0x72, 0x59, 0xa4, 0x05, 0x01, 0x2b, 0x8c, 0x81, 0xb3, 0x50, 0x95, 0x54, 0x2f, 0x4a, 0x24, 0x3d, - 0xc7, 0x11, 0x70, 0x50, 0x2e, 0xed, 0x3f, 0x0f, 0x82, 0x25, 0xa1, 0xf7, 0xb3, 0x30, 0x4b, 0x9b, 0xa5, 0xb4, 0x8c, - 0x2c, 0xa8, 0x84, 0x1a, 0xa9, 0x3e, 0x2f, 0x25, 0x79, 0x9c, 0x14, 0xfc, 0xce, 0xd8, 0x6c, 0x46, 0xf2, 0xe5, 0xe2, - 0xdd, 0xf8, 0x4b, 0xc5, 0xdf, 0x42, 0x32, 0x7d, 0x28, 0x80, 0x05, 0x34, 0x49, 0xaf, 0x31, 0xe8, 0xbe, 0x5e, 0xdc, - 0x96, 0x22, 0xfc, 0x6d, 0x00, 0x5a, 0xa5, 0x79, 0x9d, 0x1d, 0x4f, 0x19, 0xaf, 0x9d, 0xfc, 0x65, 0x9a, 0xa4, 0x29, - 0x18, 0xae, 0x03, 0xf3, 0x0c, 0xdd, 0x94, 0xa0, 0x1f, 0x31, 0x57, 0x5f, 0xaa, 0x97, 0x5c, 0x3c, 0x4d, 0x91, 0xb3, - 0x5b, 0xba, 0xde, 0x73, 0x36, 0x52, 0x81, 0x59, 0xa9, 0x7c, 0xff, 0x95, 0x34, 0x2b, 0xd0, 0xea, 0x13, 0xf7, 0x94, - 0x81, 0xd0, 0xd5, 0xa4, 0x44, 0xba, 0xbb, 0x85, 0x9a, 0x5e, 0x5b, 0x4c, 0x60, 0x2a, 0x55, 0xa8, 0xbd, 0x63, 0xd6, - 0x45, 0xdc, 0xfb, 0x77, 0x74, 0xed, 0x76, 0xe7, 0x56, 0xba, 0x08, 0xd8, 0x63, 0xc2, 0x18, 0x88, 0x1e, 0xc3, 0xa9, - 0x6b, 0xae, 0xb7, 0x95, 0x35, 0xd7, 0x05, 0x7e, 0x96, 0x08, 0xb2, 0x71, 0xe5, 0x0e, 0xac, 0xcc, 0x45, 0x10, 0x30, - 0x7f, 0xdb, 0xf8, 0x85, 0x27, 0x44, 0x26, 0x82, 0xb7, 0xec, 0xf8, 0x18, 0x2f, 0xeb, 0x7d, 0x76, 0xfc, 0x0a, 0xb6, - 0x4e, 0xad, 0x14, 0x36, 0x61, 0x20, 0x95, 0x00, 0xeb, 0xbb, 0xe4, 0xe9, 0x70, 0x61, 0xb6, 0x8a, 0xc2, 0xf5, 0x41, - 0x26, 0xe0, 0xb1, 0xa0, 0x94, 0xd4, 0x25, 0x7c, 0x1f, 0xc7, 0x07, 0x5f, 0x27, 0x0d, 0x58, 0x04, 0x2d, 0x09, 0x38, - 0x5b, 0x8f, 0x34, 0xd8, 0xd4, 0x8b, 0x6a, 0xc7, 0xb7, 0x28, 0x9c, 0xb7, 0x8c, 0xf5, 0x30, 0x08, 0xf7, 0xb8, 0x6d, - 0x5f, 0xe1, 0x00, 0xbf, 0x79, 0x43, 0x3d, 0x3e, 0xf0, 0xe1, 0x35, 0xba, 0x28, 0x3a, 0x54, 0x4d, 0xf1, 0xa7, 0x05, - 0x69, 0x5e, 0x1a, 0xe6, 0x70, 0x6f, 0x25, 0x5d, 0xf0, 0x82, 0xf1, 0x30, 0x22, 0x1a, 0x9b, 0xf4, 0xa0, 0x00, 0x9e, - 0xeb, 0xde, 0xcd, 0xbd, 0x7b, 0x2d, 0x49, 0xb5, 0x88, 0x36, 0x69, 0xe2, 0xbb, 0xb5, 0x66, 0x92, 0x35, 0x20, 0x49, - 0x69, 0xaf, 0xd8, 0x91, 0x50, 0xe2, 0xf5, 0x6f, 0xd2, 0xb3, 0x00, 0xc5, 0x77, 0xb3, 0xeb, 0x31, 0xe8, 0x52, 0xcf, - 0xd2, 0x0b, 0x56, 0x4b, 0xa0, 0x9a, 0xa9, 0x6a, 0xb2, 0xe1, 0x14, 0xd2, 0xd9, 0xd7, 0xc9, 0x2e, 0x3a, 0xa7, 0xa4, - 0x10, 0x4a, 0x19, 0xf5, 0x4c, 0xaa, 0x88, 0xe8, 0x58, 0x06, 0x3f, 0x2b, 0xcc, 0xa5, 0x3b, 0x68, 0x04, 0x16, 0x63, - 0x44, 0x6e, 0xc2, 0x61, 0xdf, 0xb7, 0x29, 0x01, 0xa1, 0x7e, 0xd7, 0x4e, 0x9c, 0xf5, 0x06, 0x07, 0x76, 0xbe, 0xff, - 0x03, 0x5f, 0x2b, 0x9f, 0x80, 0xd0, 0xc3, 0x89, 0x66, 0x49, 0xf1, 0x17, 0x2f, 0x3d, 0xf1, 0x4e, 0xac, 0xa4, 0x6e, - 0x3f, 0xf1, 0x87, 0x7f, 0x91, 0x2a, 0x6a, 0x1c, 0xc4, 0xb9, 0x75, 0x7f, 0x25, 0x0d, 0x8d, 0x1c, 0xad, 0x89, 0x7b, - 0x00, 0xb0, 0xd0, 0x84, 0x8a, 0xb0, 0x9c, 0x91, 0x34, 0xfc, 0x4c, 0xfd, 0xc4, 0x92, 0x27, 0x14, 0x2b, 0x04, 0x48, - 0xe0, 0xfb, 0xf7, 0x12, 0x5c, 0xb9, 0xef, 0x01, 0xfc, 0xc3, 0x62, 0x04, 0x5a, 0xc5, 0x12, 0x0d, 0x75, 0xf3, 0x91, - 0xf5, 0xdd, 0xe1, 0xa2, 0xd5, 0xd9, 0x46, 0x08, 0x2a, 0x74, 0xd7, 0x21, 0x40, 0xd8, 0xa7, 0x11, 0x78, 0xf2, 0xaf, - 0x92, 0xb8, 0xad, 0x64, 0x33, 0x1d, 0x76, 0xd7, 0x79, 0x05, 0xde, 0x3d, 0xe8, 0x17, 0x2b, 0xe3, 0x5d, 0xe5, 0x91, - 0xf5, 0xf1, 0xbf, 0x9f, 0x94, 0x5d, 0x52, 0x1b, 0x64, 0xa5, 0x00, 0xc4, 0x6a, 0xa4, 0xd7, 0x38, 0xd3, 0x54, 0xeb, - 0xd0, 0x5a, 0x93, 0x6d, 0x21, 0x6c, 0x87, 0xb0, 0x82, 0x07, 0xab, 0x19, 0x51, 0x27, 0x34, 0xb6, 0xb8, 0x97, 0x1e, - 0xba, 0xeb, 0xdd, 0x8b, 0xa0, 0xf2, 0x98, 0x1d, 0x32, 0x0f, 0x80, 0xef, 0x71, 0x63, 0x37, 0xc8, 0xac, 0xc0, 0x05, - 0x1c, 0x04, 0x8c, 0x5d, 0xcf, 0x5d, 0x30, 0xe4, 0x7a, 0x16, 0x37, 0x1c, 0xf6, 0x44, 0x03, 0x65, 0xd7, 0x01, 0x4d, - 0xa1, 0x75, 0x52, 0x91, 0xc6, 0xd0, 0x03, 0xbf, 0xaf, 0xc0, 0x3a, 0xeb, 0x51, 0x6c, 0x67, 0xd6, 0xe5, 0xb9, 0x54, - 0x78, 0x5a, 0xbc, 0x5e, 0xdb, 0xf4, 0x31, 0x1d, 0x9a, 0xad, 0x09, 0xdf, 0xeb, 0x2e, 0x60, 0x21, 0xac, 0xd4, 0x25, - 0x49, 0x5e, 0xd6, 0x1f, 0x2f, 0x32, 0x9a, 0x85, 0xc7, 0x5c, 0xda, 0x66, 0xf6, 0xdf, 0xef, 0x5f, 0xa0, 0xb5, 0x42, - 0xe1, 0xd3, 0x51, 0x40, 0x66, 0x25, 0x6d, 0x08, 0xde, 0xea, 0x6f, 0x36, 0xdb, 0x2c, 0xee, 0x5f, 0xdf, 0x55, 0xec, - 0xf5, 0xaf, 0x6f, 0xba, 0x71, 0x93, 0x02, 0xaf, 0x51, 0x50, 0x74, 0x6e, 0xb6, 0x27, 0x38, 0x21, 0xce, 0xad, 0x4a, - 0x58, 0xe7, 0x76, 0xfc, 0xb4, 0xa6, 0x4f, 0xff, 0xe0, 0x1d, 0x77, 0x80, 0x47, 0x2d, 0x4e, 0x96, 0x76, 0x4c, 0x3d, - 0x72, 0x16, 0x75, 0x2f, 0x3d, 0xec, 0x03, 0x9b, 0xc2, 0xe6, 0x96, 0xee, 0x7b, 0xfb, 0xd9, 0x73, 0x69, 0x8e, 0xb7, - 0xfa, 0xab, 0xfc, 0x95, 0xfb, 0xc6, 0x2a, 0x3b, 0x34, 0xac, 0xdd, 0x54, 0x49, 0x31, 0x5b, 0x7a, 0x99, 0xf5, 0x47, - 0xe1, 0x72, 0x9f, 0x3e, 0x17, 0x1a, 0xc5, 0x3d, 0x4e, 0x18, 0xb9, 0x09, 0x21, 0x1f, 0x7e, 0x49, 0x6c, 0x23, 0xf3, - 0x8f, 0x5b, 0x95, 0x31, 0x08, 0x22, 0xcf, 0x8e, 0x5a, 0x2f, 0xcb, 0x9c, 0x53, 0xe2, 0x62, 0x9e, 0x93, 0xe0, 0x17, - 0x34, 0xc2, 0xd1, 0x2a, 0xfb, 0x4b, 0x1d, 0xb6, 0x3b, 0x2c, 0x2b, 0x07, 0x1a, 0x37, 0xfb, 0x04, 0x9c, 0x11, 0x5d, - 0xab, 0xb0, 0xa3, 0xdd, 0xc8, 0xec, 0x62, 0xc3, 0xe1, 0xae, 0xb0, 0x04, 0xfc, 0xfc, 0x05, 0x8c, 0x41, 0xb7, 0x62, - 0xba, 0x52, 0xfb, 0x81, 0x41, 0xaa, 0x6a, 0x0f, 0xa5, 0xb8, 0x87, 0xe6, 0xca, 0xb4, 0x6b, 0xbd, 0xa3, 0x8e, 0x30, - 0xa0, 0x0e, 0xba, 0x0b, 0x1e, 0xb3, 0x02, 0x5c, 0xd7, 0x6d, 0xeb, 0xb8, 0xcb, 0x1a, 0x3b, 0xf1, 0x31, 0x5d, 0xfb, - 0xe7, 0xe0, 0xa8, 0x64, 0x47, 0xb7, 0x15, 0x27, 0xcc, 0xb0, 0xf2, 0xff, 0x14, 0x2e, 0x4f, 0x6f, 0x15, 0x6c, 0x0f, - 0x0d, 0xf5, 0xf9, 0x14, 0x6c, 0x75, 0x03, 0x1b, 0x1c, 0x41, 0x9b, 0x77, 0x72, 0x5d, 0xd2, 0x29, 0x13, 0xb2, 0xa6, - 0xb7, 0xa4, 0x29, 0x13, 0x9c, 0xe4, 0x5c, 0xc1, 0x7c, 0x2e, 0xce, 0x4c, 0x3e, 0x34, 0xa8, 0x15, 0x24, 0x6b, 0xc7, - 0x5e, 0x47, 0x5f, 0x88, 0xec, 0x7a, 0xce, 0xac, 0x75, 0xbf, 0x16, 0x9a, 0xc4, 0x72, 0xa8, 0x03, 0xe7, 0xeb, 0xdc, - 0xfc, 0x09, 0x0c, 0x01, 0x8f, 0xbf, 0xca, 0x18, 0xe7, 0x26, 0xed, 0x39, 0x33, 0xcb, 0x54, 0x2f, 0x15, 0x62, 0xd0, - 0xb7, 0x61, 0x42, 0x15, 0x8d, 0x17, 0xb3, 0xab, 0x54, 0x04, 0x46, 0x3e, 0x2c, 0x28, 0x43, 0x97, 0xe7, 0x1c, 0xe7, - 0x0d, 0xe5, 0x59, 0x64, 0x66, 0x00, 0x6c, 0xb4, 0x5d, 0x46, 0x09, 0xf7, 0x2e, 0xd3, 0x90, 0xd5, 0xa3, 0xb2, 0x79, - 0x8f, 0x3a, 0xbd, 0x68, 0x60, 0x05, 0xae, 0x9c, 0xae, 0x38, 0x9c, 0x14, 0x6a, 0x82, 0xb8, 0xcf, 0xfb, 0x84, 0x58, - 0x36, 0x2e, 0x31, 0x31, 0xcd, 0xb2, 0x2e, 0xef, 0xee, 0x77, 0x11, 0x34, 0x72, 0x42, 0x83, 0x85, 0x77, 0xf8, 0x0b, - 0xd8, 0x1d, 0xaf, 0xac, 0xc9, 0x0d, 0x86, 0xdf, 0x08, 0x24, 0xd3, 0x11, 0x42, 0x19, 0x4b, 0xe0, 0x76, 0xfa, 0xe9, - 0x7e, 0x0b, 0x6e, 0x1d, 0x22, 0x3d, 0x70, 0xb4, 0x10, 0x6c, 0xad, 0xb0, 0x36, 0x95, 0xe3, 0x86, 0x43, 0x71, 0x13, - 0x1a, 0x91, 0x8a, 0x68, 0x75, 0x89, 0x9e, 0xec, 0x0e, 0x41, 0xc4, 0xce, 0x21, 0x4b, 0x10, 0x41, 0x93, 0xa3, 0xfb, - 0x11, 0x5a, 0x96, 0x58, 0x22, 0x0d, 0x89, 0x5c, 0x77, 0x9e, 0xa1, 0x8a, 0x11, 0xd8, 0x76, 0x4a, 0x5d, 0x5b, 0x43, - 0xc1, 0x65, 0x6f, 0xd0, 0x75, 0x33, 0xc1, 0x89, 0x56, 0x42, 0x99, 0xd1, 0x29, 0xb9, 0x8f, 0xe9, 0x53, 0x3f, 0xca, - 0xc9, 0x28, 0x55, 0x37, 0xcc, 0xf5, 0x05, 0x42, 0x11, 0x88, 0x53, 0x97, 0x97, 0x53, 0xb5, 0x25, 0x65, 0xae, 0xb4, - 0x04, 0x73, 0xa4, 0xff, 0xb4, 0x47, 0x0d, 0xd9, 0x7a, 0x37, 0xec, 0xb4, 0xe9, 0x61, 0xd6, 0x42, 0x11, 0x8e, 0xb9, - 0x62, 0xb0, 0xda, 0xed, 0x23, 0x72, 0x6d, 0x83, 0xe9, 0x33, 0xbd, 0x9c, 0x86, 0x74, 0xa7, 0x57, 0x43, 0x33, 0x87, - 0x15, 0x7e, 0x28, 0xca, 0x3d, 0xe6, 0xe3, 0x76, 0x7f, 0x34, 0xf1, 0x59, 0x65, 0xdd, 0x7c, 0xc8, 0x7f, 0x85, 0xf4, - 0x73, 0x59, 0x8a, 0x93, 0xab, 0x1e, 0x78, 0xdb, 0x17, 0x06, 0x42, 0x2a, 0x57, 0x37, 0x9b, 0x5c, 0xc2, 0xb4, 0x13, - 0xb1, 0x4e, 0x64, 0x56, 0xbe, 0x89, 0x6c, 0x36, 0xda, 0x57, 0x7d, 0xaf, 0x5d, 0xbd, 0x29, 0x68, 0x5c, 0xab, 0x5f, - 0x74, 0x4b, 0x67, 0x7f, 0x6f, 0x95, 0x36, 0x74, 0x23, 0x1b, 0xe3, 0x0e, 0x44, 0xdb, 0xa5, 0x15, 0x45, 0x94, 0x5f, - 0x72, 0x72, 0x2f, 0x9d, 0x1f, 0x13, 0x1f, 0x8d, 0xef, 0xd2, 0x3e, 0x87, 0x23, 0x7c, 0x98, 0xfc, 0x0f, 0x27, 0x59, - 0x7f, 0xf7, 0x63, 0xd1, 0x9e, 0xf3, 0xbb, 0xad, 0x3b, 0xd8, 0x72, 0x3b, 0x96, 0x6e, 0xce, 0x65, 0x03, 0x7d, 0x17, - 0xe7, 0xf8, 0x2f, 0xbb, 0x9d, 0x94, 0xf5, 0xc1, 0x32, 0x85, 0x1c, 0x87, 0x09, 0x16, 0xa5, 0x9e, 0x14, 0xfa, 0x90, - 0x37, 0x34, 0xcd, 0x6a, 0x17, 0x93, 0xd7, 0x01, 0x02, 0x3f, 0x16, 0x75, 0xa1, 0x03, 0x99, 0x2a, 0xdd, 0x1a, 0x3f, - 0x1c, 0xd0, 0x47, 0x18, 0x13, 0xaa, 0x89, 0xe4, 0xb7, 0x04, 0x79, 0x17, 0x0a, 0xec, 0x71, 0x13, 0xb0, 0xa6, 0xd1, - 0x41, 0xa6, 0xae, 0x04, 0x49, 0xe4, 0x40, 0x2f, 0x7a, 0x07, 0xa1, 0x9d, 0x73, 0xd1, 0xe8, 0xaf, 0x57, 0xef, 0x9e, - 0x90, 0x9b, 0xad, 0xb2, 0xb3, 0x98, 0xb5, 0x87, 0x81, 0x58, 0xed, 0x4b, 0xdd, 0xf5, 0xba, 0x10, 0x18, 0x36, 0xfe, - 0x9b, 0x8d, 0x39, 0xc0, 0x76, 0x5e, 0x16, 0x7b, 0x57, 0xc0, 0x2f, 0xc1, 0x7f, 0xb5, 0x25, 0x0a, 0x4b, 0x74, 0x66, - 0x46, 0xe9, 0xe0, 0xee, 0x5b, 0xa8, 0x69, 0x08, 0x7a, 0x25, 0x2f, 0x69, 0xc4, 0xad, 0x94, 0xcb, 0x5b, 0x59, 0x63, - 0xf5, 0xd1, 0x30, 0xe5, 0xf1, 0x6b, 0x2d, 0xa0, 0x0b, 0x74, 0x81, 0x18, 0x1a, 0x52, 0x5b, 0xd2, 0x30, 0x05, 0x92, - 0x46, 0x6e, 0x1f, 0xb4, 0xb0, 0xc2, 0x69, 0xda, 0x46, 0x10, 0x27, 0xff, 0x0e, 0xc2, 0x70, 0xce, 0xef, 0xb6, 0x16, - 0x82, 0x1b, 0x88, 0xb4, 0x41, 0x56, 0x4e, 0x85, 0x5d, 0x01, 0xcd, 0xb7, 0x01, 0xa3, 0x15, 0x26, 0x19, 0x32, 0x49, - 0xf7, 0xe3, 0x3f, 0xf2, 0x0e, 0xbf, 0x3a, 0x73, 0x1e, 0x0a, 0x46, 0x0c, 0xb4, 0x43, 0x23, 0x1f, 0x14, 0xdc, 0x4e, - 0x96, 0xbd, 0xa0, 0x2e, 0x89, 0x59, 0xca, 0xe0, 0x14, 0x37, 0x85, 0xbe, 0x7c, 0x1c, 0x0e, 0x2a, 0x78, 0x63, 0x2c, - 0x0e, 0x74, 0x96, 0x82, 0x95, 0x0f, 0x7a, 0x96, 0x4e, 0x04, 0x98, 0x02, 0x9d, 0xc6, 0xd1, 0x6e, 0xc6, 0x5d, 0x29, - 0xdd, 0x0b, 0x50, 0x38, 0x2f, 0xa4, 0xd9, 0x08, 0x0a, 0x60, 0x37, 0x46, 0x4b, 0xf2, 0x8f, 0xbc, 0xc3, 0xf7, 0x33, - 0x71, 0x95, 0x5b, 0xe2, 0xd7, 0xca, 0x47, 0x0c, 0x64, 0x53, 0x7f, 0xb0, 0x7e, 0x4d, 0xcd, 0xd5, 0xee, 0x24, 0x1d, - 0x8e, 0xc3, 0x00, 0x38, 0xe6, 0x28, 0x96, 0x83, 0x58, 0x56, 0x20, 0xc9, 0x39, 0xb1, 0x5c, 0x3f, 0xe6, 0xcf, 0x49, - 0x62, 0x5f, 0xb5, 0x14, 0x57, 0xb8, 0x16, 0x4f, 0x8b, 0xe4, 0xc4, 0x1b, 0xfc, 0x2a, 0xfa, 0xef, 0xf6, 0x52, 0xc6, - 0x30, 0xf7, 0x53, 0x8c, 0x70, 0x43, 0xde, 0x32, 0x9f, 0x26, 0x81, 0x72, 0x56, 0x97, 0x83, 0x32, 0x9f, 0x5d, 0x2c, - 0x59, 0xe7, 0xd9, 0xf8, 0x4e, 0xce, 0x5b, 0xd7, 0xbd, 0xb0, 0x3f, 0x7a, 0x28, 0xdf, 0x1f, 0x2b, 0xff, 0x1e, 0x88, - 0x73, 0x28, 0x86, 0x11, 0x2b, 0x36, 0xea, 0xed, 0x49, 0xbe, 0x96, 0x0d, 0x74, 0xa4, 0x88, 0xf4, 0x95, 0x25, 0x3d, - 0x9f, 0x18, 0xd6, 0x45, 0x34, 0xf7, 0x6f, 0x30, 0x5d, 0x74, 0xf0, 0x0e, 0x13, 0x0c, 0xde, 0x2c, 0x4d, 0x5b, 0xdc, - 0x8f, 0x6d, 0x6a, 0x54, 0x28, 0x9c, 0x19, 0xd4, 0xb6, 0xc6, 0x0b, 0xec, 0x29, 0x5c, 0xfc, 0xc4, 0x39, 0x69, 0x5e, - 0x61, 0xb8, 0xb1, 0xa3, 0x95, 0x68, 0xa4, 0xb5, 0x1c, 0x1d, 0x74, 0xc8, 0xe4, 0xbd, 0x9c, 0x14, 0xb3, 0x48, 0x82, - 0x70, 0x5e, 0x2b, 0x1f, 0x4d, 0xbd, 0xb7, 0xb5, 0x6f, 0x30, 0xee, 0x02, 0x19, 0xb8, 0x4c, 0x16, 0x5a, 0x9a, 0x78, - 0xd9, 0x6d, 0xbe, 0x6d, 0xc3, 0x32, 0xe6, 0x56, 0x94, 0x55, 0x8c, 0x31, 0x89, 0x29, 0xda, 0xc5, 0xb2, 0xf1, 0x08, - 0xa6, 0x2e, 0x91, 0x24, 0x44, 0x96, 0xd1, 0x12, 0x8d, 0x6d, 0x50, 0xfa, 0x22, 0x66, 0x61, 0x30, 0xf2, 0x3f, 0xb3, - 0xf8, 0xcb, 0xb5, 0x7e, 0x2d, 0xcd, 0x14, 0xdd, 0x29, 0xf7, 0x6a, 0x6c, 0xdb, 0xe5, 0xf6, 0x6b, 0x3b, 0x44, 0x79, - 0xfd, 0x0a, 0x9e, 0x02, 0x4d, 0x8a, 0xe0, 0x10, 0x11, 0x68, 0x95, 0xf5, 0x45, 0x2d, 0x6d, 0x4b, 0x47, 0x7e, 0x4a, - 0x36, 0x11, 0xce, 0xf9, 0x21, 0xc4, 0xb3, 0x0a, 0xa2, 0x2e, 0x4b, 0x2f, 0x22, 0x1b, 0xb4, 0xb6, 0x3e, 0xd2, 0xa9, - 0x54, 0xc3, 0x07, 0x86, 0x22, 0xf2, 0x3d, 0xbc, 0x3a, 0x09, 0x5d, 0xda, 0x5a, 0x45, 0x49, 0xbc, 0x44, 0x3a, 0x7e, - 0x22, 0xab, 0x0e, 0x51, 0x24, 0xa8, 0x16, 0x0c, 0x6a, 0x05, 0xb8, 0x1c, 0x54, 0xb5, 0x37, 0x5b, 0x91, 0x08, 0x82, - 0x68, 0xb0, 0x8a, 0x0f, 0xd4, 0xed, 0x28, 0xc8, 0x24, 0xd2, 0x13, 0x63, 0x93, 0xf1, 0xe6, 0x85, 0xe4, 0x5e, 0x91, - 0x46, 0xa0, 0x4f, 0x9c, 0xd4, 0xb3, 0x71, 0x92, 0xf5, 0xfe, 0xa6, 0x8f, 0x1c, 0x1c, 0x37, 0x58, 0x4a, 0x8f, 0x62, - 0x07, 0xc7, 0x7a, 0x4e, 0x64, 0x2b, 0x29, 0xeb, 0x1c, 0x4a, 0x15, 0x6f, 0xc6, 0x28, 0x72, 0x2c, 0x63, 0x32, 0x70, - 0x36, 0x07, 0xd1, 0xb6, 0xa3, 0xf7, 0x94, 0xd8, 0xc8, 0x15, 0xf5, 0x02, 0xa5, 0x4e, 0xfc, 0xef, 0x13, 0xb4, 0xdf, - 0x6e, 0x4f, 0x08, 0xbd, 0x9d, 0x45, 0xb7, 0xf0, 0x45, 0xc7, 0x32, 0x6e, 0x0e, 0xdd, 0x49, 0x88, 0x63, 0x8a, 0x16, - 0x78, 0xc7, 0x0a, 0xc5, 0xb9, 0x68, 0x48, 0xec, 0x72, 0x6c, 0xd4, 0xfc, 0x54, 0x4d, 0x5d, 0xd6, 0x0a, 0xe9, 0x5d, - 0xfe, 0x1b, 0xf3, 0xbb, 0xfc, 0xf9, 0xf1, 0xa9, 0xca, 0xf5, 0x3a, 0x35, 0xc4, 0xe2, 0x0d, 0x2d, 0x13, 0x8d, 0x15, - 0x5e, 0x54, 0xc3, 0x1e, 0x25, 0x5b, 0x8b, 0xf4, 0x62, 0x65, 0xd5, 0x4c, 0xe4, 0x21, 0x09, 0x42, 0xd4, 0xe8, 0x84, - 0xba, 0x5b, 0xb8, 0xd0, 0xf8, 0x1d, 0x46, 0x26, 0x92, 0x01, 0x25, 0xdb, 0xea, 0x96, 0xfa, 0x51, 0x4b, 0x4f, 0x3d, - 0x9f, 0xcc, 0x06, 0x57, 0x4d, 0xa3, 0x71, 0x3a, 0xa6, 0xc6, 0x89, 0xb7, 0x8f, 0x66, 0x7a, 0x8d, 0x06, 0x0b, 0xbc, - 0xb0, 0xbb, 0xfe, 0x0d, 0x74, 0xc4, 0x2d, 0x34, 0x4a, 0x6c, 0x48, 0xd6, 0x18, 0x93, 0x96, 0x30, 0x6d, 0x29, 0xb3, - 0x96, 0x71, 0xd0, 0x06, 0x1c, 0xb6, 0x21, 0x47, 0x6d, 0xc4, 0x71, 0x1b, 0xf3, 0x4b, 0x8b, 0xca, 0xaf, 0x33, 0x7a, - 0x4e, 0x66, 0x0c, 0x9c, 0xce, 0x18, 0xb9, 0xd3, 0x62, 0xe2, 0xee, 0x8c, 0x99, 0x5c, 0xb4, 0xba, 0xa8, 0x8a, 0x6a, - 0x51, 0x95, 0x95, 0xb2, 0x6f, 0x58, 0x92, 0x1b, 0xff, 0xa2, 0x64, 0xd4, 0x87, 0x98, 0x72, 0xd9, 0xea, 0xfe, 0xde, - 0xd3, 0xc9, 0x74, 0xe7, 0x25, 0x4c, 0xbc, 0x89, 0x22, 0x55, 0xe7, 0x96, 0xa9, 0x01, 0xf3, 0xe4, 0x95, 0xf9, 0x0d, - 0x09, 0x0d, 0x2c, 0x29, 0xb6, 0xdb, 0x1f, 0xcf, 0xfe, 0xed, 0x89, 0xaf, 0xaa, 0xee, 0x1b, 0x6f, 0x97, 0x9c, 0x9c, - 0xfb, 0xe0, 0xb9, 0x03, 0x8d, 0xa7, 0xe7, 0x0d, 0x63, 0xf7, 0x7e, 0x65, 0xd1, 0x2d, 0xca, 0x3c, 0x78, 0xd2, 0xf1, - 0x17, 0xe1, 0x5a, 0x32, 0xe9, 0xef, 0xd0, 0x21, 0x59, 0x6a, 0xe4, 0x46, 0xfd, 0xcd, 0x35, 0x68, 0xb4, 0xd3, 0xcc, - 0xd3, 0x8a, 0xb1, 0x7f, 0xa8, 0xd9, 0x90, 0xea, 0xcb, 0xcc, 0x72, 0xbe, 0x1c, 0x2d, 0x2a, 0xe3, 0x9c, 0x56, 0xb8, - 0xb1, 0xe2, 0x98, 0x67, 0xc7, 0x16, 0xf3, 0x49, 0x93, 0x47, 0xd5, 0xf0, 0x98, 0x4b, 0x41, 0x46, 0x62, 0xa1, 0xf7, - 0xfc, 0xd0, 0x1f, 0xb7, 0x26, 0xc3, 0x27, 0x6b, 0xbd, 0xbd, 0x79, 0xf3, 0xe4, 0x8d, 0xa6, 0x09, 0x15, 0xe7, 0x92, - 0xa4, 0x92, 0xce, 0x2d, 0x96, 0x64, 0xde, 0x80, 0x8d, 0x9a, 0x1b, 0xe7, 0x86, 0x42, 0xde, 0x08, 0x8d, 0xdc, 0x4e, - 0x99, 0x84, 0xf4, 0xfe, 0xfa, 0xf7, 0xfa, 0x9b, 0xd5, 0xe3, 0x7c, 0xfa, 0x03, 0xc3, 0x66, 0x02, 0x00, 0x46, 0x4b, - 0xdf, 0xfb, 0xcf, 0xeb, 0x37, 0xd5, 0xd3, 0xca, 0xaf, 0xeb, 0xe7, 0x55, 0xa9, 0x3d, 0x87, 0xd0, 0xc1, 0x1c, 0x5f, - 0xe6, 0x9d, 0x27, 0x1b, 0xb7, 0x2b, 0xb8, 0xdb, 0x0c, 0xdd, 0xb3, 0xd8, 0xc4, 0xc6, 0x64, 0xba, 0xf8, 0xfc, 0xd3, - 0x55, 0x1f, 0x4d, 0x91, 0xda, 0xee, 0xcf, 0xf5, 0x38, 0x1f, 0xf7, 0xf8, 0x3b, 0xf1, 0xcd, 0x8e, 0x38, 0x8b, 0xc2, - 0xa9, 0xfc, 0xe7, 0xa1, 0xf4, 0xb8, 0xfc, 0xc4, 0x45, 0xad, 0xb0, 0x66, 0xf0, 0x2c, 0xbf, 0xf7, 0xb7, 0x11, 0x0f, - 0x3c, 0x35, 0xae, 0xfb, 0xf9, 0x33, 0x96, 0xff, 0x45, 0xc5, 0x2a, 0x0f, 0x8f, 0x6f, 0xf1, 0xdd, 0xac, 0xd6, 0x24, - 0xd2, 0x34, 0x08, 0xc2, 0x8a, 0xfc, 0x50, 0xfd, 0xb0, 0x3c, 0x27, 0x89, 0xae, 0xfd, 0xa7, 0xc7, 0x33, 0x08, 0x1d, - 0x83, 0x78, 0x75, 0x4d, 0x14, 0x0f, 0x3f, 0xa0, 0x7c, 0x3c, 0x04, 0x73, 0x08, 0xf4, 0x5f, 0xdf, 0x8d, 0x09, 0xc7, - 0xce, 0x11, 0x82, 0x08, 0x6b, 0xbd, 0x9f, 0x9f, 0xf9, 0x40, 0x81, 0x0f, 0xa3, 0xff, 0x66, 0x52, 0x4c, 0x01, 0x72, - 0xea, 0x44, 0x4c, 0xff, 0x66, 0xa0, 0x64, 0x05, 0x3a, 0xa8, 0xeb, 0x40, 0xf1, 0xa0, 0x06, 0xdd, 0x4d, 0x8e, 0xe1, - 0x76, 0xce, 0x32, 0x75, 0x76, 0xa9, 0xd3, 0xf3, 0x93, 0x26, 0x64, 0xa7, 0x97, 0x6a, 0x52, 0xc0, 0x65, 0xf9, 0x75, - 0x74, 0xf7, 0x05, 0x64, 0x2c, 0xd0, 0x8d, 0x87, 0xb6, 0x89, 0x6f, 0x0e, 0x72, 0x79, 0xde, 0x98, 0xd7, 0x88, 0x37, - 0xc6, 0x3f, 0x3b, 0x20, 0x1c, 0x72, 0x4f, 0x72, 0xcc, 0x7d, 0xc4, 0x73, 0xe8, 0xfe, 0x94, 0x74, 0x3f, 0x6c, 0xf6, - 0x4e, 0x8b, 0xff, 0xb1, 0xca, 0xd1, 0x85, 0x51, 0xf2, 0xbc, 0xde, 0xe7, 0xa1, 0xb1, 0xb3, 0x32, 0xb5, 0x7a, 0x26, - 0x6d, 0x08, 0x0d, 0x76, 0xfc, 0xbc, 0x39, 0xe5, 0xfe, 0x4c, 0x6c, 0x94, 0x18, 0xcd, 0x40, 0xec, 0x24, 0xd3, 0xa0, - 0x51, 0x44, 0xe0, 0xff, 0x20, 0x06, 0xb5, 0x8b, 0x35, 0x42, 0x21, 0xac, 0xe5, 0x53, 0x68, 0x79, 0x35, 0x8f, 0xde, - 0x48, 0x57, 0xe2, 0xc4, 0x72, 0xa6, 0x39, 0xe6, 0x5c, 0xc5, 0xcf, 0xc9, 0x8e, 0x15, 0xbc, 0xc8, 0xf4, 0x16, 0x8e, - 0xe7, 0x47, 0xcc, 0xf8, 0xdc, 0x43, 0x77, 0x5c, 0x1c, 0x59, 0xb3, 0x80, 0x36, 0xd5, 0x6e, 0x80, 0x6a, 0x90, 0xc0, - 0xb5, 0x08, 0xfd, 0x5e, 0x25, 0x38, 0xd2, 0x9c, 0x97, 0xb5, 0x18, 0xf5, 0x44, 0x1e, 0x39, 0x1b, 0x5c, 0x8c, 0x7a, - 0x52, 0x79, 0x01, 0xc1, 0xa7, 0xa0, 0xdb, 0x06, 0xd5, 0x64, 0xd9, 0xbf, 0x24, 0xcd, 0x61, 0xa0, 0xd7, 0x58, 0x80, - 0x59, 0xf3, 0x8f, 0x52, 0xff, 0xfb, 0x4d, 0xc9, 0xbd, 0x21, 0xfe, 0x03, 0x20, 0xe6, 0xea, 0xa6, 0xcd, 0xb3, 0x51, - 0x95, 0x0b, 0xed, 0x12, 0x4e, 0x2f, 0x55, 0xbc, 0x86, 0x4d, 0x85, 0x72, 0x4a, 0x02, 0x51, 0x27, 0x9c, 0x2d, 0x1d, - 0x21, 0x3c, 0x4f, 0xd6, 0x0e, 0x4d, 0xe8, 0x3d, 0x60, 0xeb, 0x5d, 0x4b, 0xfb, 0x28, 0xe7, 0xf2, 0xec, 0xeb, 0xfc, - 0x64, 0x5f, 0x4e, 0x32, 0x19, 0xff, 0x89, 0x9a, 0xc6, 0x2b, 0xd4, 0x27, 0x15, 0xbd, 0x7e, 0x3e, 0x56, 0x94, 0xa4, - 0xb1, 0x1d, 0xf1, 0xab, 0xad, 0xc0, 0xff, 0x4a, 0x5f, 0x8b, 0x58, 0x75, 0xfa, 0x46, 0x8f, 0xa3, 0x2e, 0xe7, 0xd2, - 0xbf, 0xbc, 0xb1, 0x64, 0x6d, 0x59, 0x02, 0x13, 0xdb, 0x3d, 0xdf, 0x96, 0xc1, 0xac, 0xb5, 0x8a, 0x4d, 0xde, 0x6d, - 0x45, 0xe9, 0x6b, 0x75, 0x6d, 0xd2, 0x6e, 0x3c, 0x80, 0xcb, 0x63, 0xb5, 0x52, 0x33, 0x92, 0x64, 0xa6, 0x77, 0xbe, - 0x7b, 0xce, 0xa5, 0x52, 0xa1, 0xc4, 0x1d, 0x32, 0xbe, 0x3b, 0x30, 0x76, 0x7f, 0xae, 0xa1, 0x1a, 0x9d, 0x1b, 0xe1, - 0x69, 0xe9, 0x10, 0x02, 0x4f, 0x1c, 0xf7, 0xc7, 0xbe, 0x6c, 0x1b, 0x9d, 0xd1, 0xe9, 0x1c, 0xad, 0x8b, 0xc6, 0x3f, - 0xba, 0x55, 0x34, 0x9b, 0xbd, 0xad, 0x2c, 0x36, 0x8f, 0xcd, 0xf2, 0x28, 0x73, 0xf1, 0x3f, 0xf1, 0xa7, 0xe1, 0x54, - 0xe7, 0x40, 0xb6, 0x74, 0x35, 0x65, 0x12, 0xc8, 0x11, 0x5e, 0xcf, 0xf5, 0x0e, 0x48, 0x3e, 0x77, 0x4b, 0xa0, 0x0c, - 0x45, 0x56, 0x33, 0x2a, 0xae, 0x8a, 0x15, 0x99, 0x67, 0xd6, 0x24, 0x78, 0xa1, 0x77, 0xa0, 0x39, 0x8b, 0x35, 0x6b, - 0x24, 0x71, 0xde, 0x43, 0xca, 0x8e, 0x7c, 0xd8, 0xc8, 0x1c, 0xc2, 0xc3, 0x26, 0x7e, 0xd6, 0x63, 0x02, 0x85, 0x13, - 0x03, 0xe8, 0xed, 0x2f, 0xc0, 0xea, 0xcf, 0x14, 0xeb, 0x83, 0xec, 0x74, 0xd6, 0xae, 0xe9, 0x0f, 0x97, 0x79, 0x9f, - 0xd8, 0xd3, 0xf5, 0xdb, 0xb0, 0x76, 0x4c, 0x2d, 0xed, 0x3c, 0xc0, 0xce, 0x6b, 0xf8, 0xae, 0x43, 0xb5, 0xaf, 0x11, - 0xba, 0x1f, 0xb9, 0xc9, 0x63, 0x0a, 0x1d, 0x7b, 0xfc, 0x27, 0xc0, 0x43, 0x0a, 0x5d, 0x05, 0xee, 0x53, 0x58, 0x3f, - 0x0e, 0xc0, 0x5d, 0x0a, 0xd5, 0x13, 0xb8, 0x4d, 0x61, 0x44, 0xfc, 0x5e, 0x79, 0x93, 0x82, 0x7d, 0x14, 0xee, 0xf2, - 0xbe, 0xac, 0xe8, 0xcd, 0xbb, 0x3e, 0xde, 0x3e, 0x2a, 0x57, 0xde, 0xd3, 0xfb, 0x7a, 0xbc, 0x5b, 0xbd, 0x09, 0x4c, - 0x9f, 0xa8, 0xc4, 0x9b, 0x02, 0xcf, 0x9f, 0xb0, 0xe2, 0x5d, 0x1e, 0xaf, 0x9b, 0x77, 0x71, 0xa5, 0x7b, 0x75, 0xff, - 0x3f, 0xb4, 0x35, 0xe6, 0xed, 0x1c, 0xdf, 0x6d, 0x2b, 0xe7, 0x59, 0xde, 0xee, 0x9d, 0xfd, 0xeb, 0x59, 0x3c, 0x80, - 0xd3, 0x14, 0x9a, 0x0a, 0x9c, 0xa4, 0x50, 0x56, 0xe0, 0x38, 0x85, 0x53, 0x6d, 0x9a, 0x16, 0xd8, 0x4d, 0x41, 0x37, - 0xe0, 0x28, 0x85, 0xcd, 0x37, 0xb0, 0x97, 0x42, 0xf1, 0xbc, 0xb5, 0xc0, 0x7e, 0x0a, 0x7a, 0x05, 0x0e, 0x04, 0xf2, - 0x2a, 0xef, 0xf0, 0x9f, 0x8d, 0xe3, 0x37, 0x18, 0x7b, 0xa8, 0xf6, 0x0c, 0x37, 0xfa, 0x1b, 0x18, 0xce, 0x5d, 0x8e, - 0x5d, 0x7d, 0x3a, 0x03, 0x97, 0xcc, 0xbf, 0x85, 0xd6, 0x9b, 0x44, 0xf8, 0x63, 0x40, 0x12, 0xab, 0xd3, 0x7d, 0x05, - 0xbc, 0xda, 0x1f, 0x7a, 0x3e, 0x67, 0x61, 0xee, 0xc2, 0x2b, 0x06, 0xac, 0x62, 0x51, 0x9e, 0xfa, 0xbf, 0x0c, 0x21, - 0xbb, 0x6d, 0x48, 0x32, 0x23, 0xdb, 0x0f, 0x8b, 0x13, 0xa3, 0x3e, 0x29, 0x4d, 0x6c, 0x55, 0x3a, 0x43, 0x45, 0x93, - 0x9b, 0xe0, 0x51, 0x52, 0xaa, 0xc0, 0xdc, 0x45, 0xf7, 0x44, 0xf8, 0x66, 0xbd, 0xc3, 0xf5, 0x53, 0x52, 0x21, 0x4a, - 0x86, 0xf4, 0xeb, 0xbf, 0x9c, 0x4d, 0x4f, 0xa9, 0xf5, 0xe4, 0x45, 0xfc, 0xc9, 0xf7, 0xd5, 0xb5, 0x29, 0x30, 0x79, - 0x66, 0x72, 0x99, 0xa7, 0x6d, 0xf5, 0x1e, 0xdb, 0x21, 0x59, 0xbb, 0x3d, 0x05, 0x2f, 0x89, 0xf5, 0x6f, 0x72, 0xcd, - 0x02, 0x7b, 0x4f, 0x30, 0xa7, 0x61, 0x89, 0x12, 0x25, 0x46, 0x62, 0xbc, 0xea, 0x41, 0x61, 0xcc, 0x70, 0x8d, 0xbf, - 0x4a, 0xed, 0xdf, 0xce, 0xa6, 0x3a, 0x01, 0x0b, 0x39, 0xd7, 0x61, 0x78, 0xe0, 0x24, 0xa4, 0x1c, 0xb2, 0x48, 0x68, - 0xa3, 0x99, 0x4e, 0xaa, 0xa7, 0x5a, 0x3d, 0xd8, 0x8d, 0x96, 0x27, 0xa2, 0x77, 0xed, 0xa8, 0x9c, 0x89, 0xa0, 0xbb, - 0x81, 0xd3, 0x1c, 0xfa, 0x63, 0x5a, 0xf2, 0x32, 0x80, 0x14, 0xbe, 0xf1, 0x76, 0x6a, 0xec, 0x5f, 0xe2, 0x3b, 0xb6, - 0xa2, 0x5c, 0xe1, 0x4f, 0xf0, 0x1b, 0xb6, 0x36, 0x9b, 0xbf, 0x61, 0x75, 0x79, 0xb8, 0x15, 0xb0, 0x02, 0x30, 0x7f, - 0x67, 0xcd, 0xf6, 0xe9, 0x08, 0x27, 0x93, 0xb7, 0x82, 0xb2, 0xd2, 0x80, 0x85, 0xf1, 0x36, 0x01, 0xbf, 0x15, 0x06, - 0x37, 0xdb, 0x9b, 0x33, 0x31, 0x77, 0x22, 0x5a, 0x5c, 0x06, 0x76, 0x0f, 0x6e, 0xd4, 0xc2, 0x4a, 0xdd, 0x1c, 0xf6, - 0xf7, 0xea, 0x06, 0x25, 0x2e, 0x82, 0xb0, 0x55, 0x75, 0x40, 0xd6, 0xb8, 0x8e, 0x22, 0x9f, 0x87, 0x7d, 0xb3, 0xdd, - 0x5b, 0xa9, 0x25, 0x5b, 0xde, 0xeb, 0xb5, 0xea, 0x27, 0x55, 0x4d, 0x9f, 0xce, 0xb1, 0xec, 0x34, 0x66, 0xc9, 0x4f, - 0x5b, 0x7b, 0x78, 0xc5, 0x15, 0x82, 0x68, 0xd5, 0x14, 0x33, 0xf3, 0x41, 0x1d, 0x34, 0x61, 0xae, 0xc2, 0xe3, 0x98, - 0x60, 0x80, 0xd9, 0x79, 0x78, 0x11, 0x42, 0x07, 0xc1, 0x76, 0xce, 0xc1, 0x56, 0xf1, 0xb4, 0x69, 0x2d, 0x0b, 0x68, - 0x1a, 0x8d, 0xfd, 0x28, 0x6b, 0xfc, 0x41, 0x36, 0x6a, 0x9d, 0x5a, 0xda, 0x1e, 0x47, 0x4f, 0x31, 0x7f, 0x1b, 0x50, - 0x11, 0xd0, 0x66, 0x90, 0xb3, 0x41, 0xa3, 0x72, 0xf1, 0xdf, 0x09, 0xa4, 0x33, 0xed, 0xdf, 0x70, 0x36, 0xa6, 0x35, - 0x68, 0xf6, 0x8d, 0xf6, 0x43, 0x4c, 0xdf, 0x17, 0x6c, 0x11, 0xbd, 0xe4, 0xb8, 0xe5, 0x29, 0x1a, 0xb8, 0x4a, 0xa6, - 0x4b, 0x70, 0x84, 0x2e, 0xca, 0xbd, 0xf7, 0x49, 0xf8, 0x93, 0x00, 0xd6, 0x8f, 0x3e, 0xa6, 0x53, 0xb6, 0x0e, 0x0e, - 0x95, 0xb1, 0x47, 0xcd, 0x32, 0x56, 0xf0, 0x4a, 0x7a, 0x23, 0x33, 0x00, 0x02, 0x01, 0xcf, 0x65, 0x87, 0x3f, 0xd5, - 0x07, 0xb9, 0x2a, 0xc0, 0x6a, 0xe9, 0x66, 0x3b, 0x1d, 0x6a, 0xcd, 0x8f, 0x79, 0x5b, 0xda, 0xd1, 0xa3, 0x77, 0xb4, - 0xbd, 0xac, 0xc1, 0x05, 0x39, 0x72, 0x09, 0x3a, 0x4b, 0x65, 0x54, 0xe1, 0x3a, 0x34, 0xe0, 0x7c, 0x29, 0xd4, 0x28, - 0x5a, 0xf4, 0x9b, 0x1b, 0x7d, 0xcb, 0x5e, 0x1e, 0x41, 0x63, 0xce, 0xfb, 0x4d, 0x36, 0x57, 0x2d, 0x10, 0x84, 0x39, - 0xb6, 0xa5, 0xf7, 0x1f, 0x13, 0x9c, 0x6f, 0x5f, 0xb0, 0xdd, 0x72, 0xcb, 0x03, 0xb6, 0xfe, 0x89, 0x47, 0x15, 0x8a, - 0x9d, 0x78, 0x56, 0x56, 0x67, 0x57, 0x6d, 0xad, 0x31, 0xa4, 0xff, 0x6a, 0xbd, 0x6b, 0x6b, 0x5a, 0x7b, 0x07, 0x3c, - 0x08, 0x84, 0x74, 0xb8, 0x1c, 0x48, 0xc4, 0x7a, 0x4b, 0x87, 0x87, 0x12, 0xe1, 0x80, 0xec, 0x01, 0xb3, 0x73, 0x1b, - 0xda, 0xb3, 0x87, 0x07, 0xb8, 0x97, 0x39, 0xd0, 0x80, 0x5c, 0x1e, 0x1e, 0xe5, 0xd9, 0xfd, 0x01, 0x09, 0xf0, 0x16, - 0x0a, 0x58, 0x6a, 0x80, 0x75, 0x47, 0x4c, 0xb8, 0x7c, 0x20, 0xcb, 0xce, 0x8b, 0x40, 0xc7, 0x95, 0xd3, 0xc0, 0x46, - 0x0f, 0x1e, 0x42, 0xf1, 0x64, 0x73, 0xac, 0x71, 0x6e, 0x4d, 0x7a, 0xe1, 0x08, 0xc9, 0x98, 0xb9, 0x47, 0x8c, 0x1c, - 0x52, 0x1f, 0x26, 0xa6, 0x8b, 0x49, 0x7a, 0x5c, 0xb1, 0x2e, 0x86, 0xc0, 0x8e, 0x60, 0xe9, 0x0b, 0xc4, 0xde, 0x64, - 0x2c, 0x61, 0x82, 0x58, 0x47, 0x83, 0x18, 0xc2, 0xc6, 0x1d, 0x96, 0xa6, 0x6e, 0x02, 0x16, 0x81, 0xeb, 0x45, 0x90, - 0x4b, 0x61, 0x8d, 0x67, 0xe1, 0xdd, 0x3b, 0x9f, 0xc6, 0xdb, 0xfd, 0xaf, 0xf8, 0xd0, 0xa8, 0x36, 0x5a, 0x94, 0xbe, - 0xee, 0x00, 0xc6, 0xec, 0x57, 0xe0, 0x33, 0x05, 0x42, 0x9c, 0xfb, 0xfb, 0x57, 0x58, 0xe6, 0xf0, 0xda, 0x06, 0x19, - 0x8c, 0xcc, 0xbe, 0x1c, 0xd8, 0xa4, 0x96, 0x48, 0xe6, 0x2b, 0x86, 0xb7, 0x80, 0x55, 0xe9, 0x4b, 0xa2, 0x36, 0xcc, - 0xdd, 0xf8, 0xae, 0x0e, 0x1a, 0x6d, 0xe5, 0x47, 0x68, 0x1c, 0x4c, 0xde, 0xea, 0xc4, 0x40, 0x86, 0x78, 0x12, 0xab, - 0xbe, 0xb8, 0x68, 0x6b, 0x90, 0x34, 0x3d, 0x06, 0x14, 0x8a, 0x5d, 0xbc, 0xbd, 0x60, 0xbb, 0xa4, 0x06, 0xb0, 0xb1, - 0x31, 0x69, 0x98, 0x1d, 0xb5, 0x26, 0xa6, 0xed, 0x3d, 0x3e, 0x4a, 0x9b, 0x23, 0x77, 0x0f, 0x6b, 0x2a, 0xdb, 0x9d, - 0x27, 0x4a, 0x1c, 0x73, 0x70, 0x86, 0x5f, 0x1f, 0x98, 0x80, 0x7c, 0x3f, 0x3e, 0x11, 0x87, 0x83, 0xaf, 0xc7, 0x09, - 0x94, 0x88, 0x42, 0x2d, 0xc0, 0x03, 0x11, 0x10, 0xc7, 0xee, 0x08, 0x20, 0xeb, 0x7d, 0xbc, 0x94, 0xad, 0x56, 0xbd, - 0x9c, 0x5e, 0x6c, 0x34, 0x01, 0x42, 0x7c, 0xca, 0x21, 0x48, 0xc9, 0xe2, 0xc1, 0x01, 0xc4, 0x0c, 0x54, 0x30, 0x65, - 0x37, 0xbc, 0x51, 0x18, 0x0b, 0x2d, 0x51, 0x9d, 0xc0, 0xc5, 0x11, 0xa8, 0xe9, 0x27, 0x3f, 0x64, 0x03, 0x18, 0x4a, - 0xa9, 0x09, 0x92, 0xae, 0x1c, 0x10, 0xa0, 0x4b, 0x44, 0x42, 0xfc, 0x72, 0x31, 0x40, 0x80, 0x0d, 0xd6, 0x9b, 0xe0, - 0xa6, 0x49, 0x8d, 0xe1, 0x70, 0xff, 0x94, 0x17, 0xad, 0xef, 0x53, 0x20, 0x1b, 0x13, 0x68, 0x5e, 0xfc, 0xe8, 0x48, - 0x2d, 0x74, 0x19, 0x1a, 0x2e, 0x29, 0xd6, 0xb2, 0x1f, 0xa6, 0xc5, 0x96, 0xa9, 0x41, 0x88, 0xa0, 0x1f, 0xfc, 0xfa, - 0x32, 0xa3, 0x91, 0x5c, 0x7c, 0x10, 0x7e, 0x08, 0xee, 0x05, 0x78, 0x1c, 0x19, 0x24, 0x29, 0x05, 0x9c, 0x46, 0x95, - 0x08, 0xf7, 0xb8, 0x0b, 0x39, 0x82, 0xe8, 0xf7, 0xb8, 0x4d, 0x8d, 0x16, 0x45, 0xaa, 0x70, 0xd3, 0xef, 0xdb, 0xdb, - 0x45, 0x7d, 0x0d, 0x0f, 0xf0, 0x23, 0x20, 0xbe, 0x26, 0x6e, 0x8c, 0x57, 0x21, 0x9f, 0x92, 0x01, 0x61, 0x02, 0x6a, - 0x42, 0x19, 0x73, 0x0e, 0x37, 0xe6, 0x8a, 0x2c, 0x14, 0x92, 0x41, 0xc3, 0x6d, 0x5d, 0xc2, 0x98, 0x14, 0xc7, 0x89, - 0x40, 0xfc, 0x9e, 0x12, 0x4b, 0x9e, 0x5a, 0x00, 0xf0, 0xad, 0xa2, 0xb9, 0x75, 0xd0, 0x26, 0x13, 0xc4, 0xc9, 0xbe, - 0xc7, 0xf2, 0xdd, 0x66, 0x7f, 0xc6, 0x5f, 0x48, 0x3a, 0x4e, 0x12, 0xf1, 0xae, 0xa7, 0x29, 0xc2, 0x3e, 0x87, 0xaa, - 0x2e, 0x38, 0x04, 0x58, 0xfc, 0x10, 0x16, 0x0c, 0xb2, 0xc1, 0x51, 0xac, 0x07, 0x82, 0xa0, 0x98, 0x84, 0xb6, 0xb3, - 0x10, 0xb7, 0xc1, 0xea, 0x18, 0x95, 0x35, 0x12, 0x24, 0x93, 0x35, 0x13, 0xa2, 0xa6, 0x7e, 0xa2, 0x37, 0x3c, 0xa9, - 0x1d, 0xcf, 0xdd, 0xc4, 0xf4, 0x1a, 0xf9, 0xb1, 0xba, 0x34, 0xd6, 0xe7, 0xbd, 0x85, 0xe4, 0x63, 0xc0, 0x27, 0x89, - 0x0d, 0xd1, 0xfc, 0xc3, 0xb0, 0x6c, 0x18, 0x27, 0x25, 0x1b, 0x4b, 0x35, 0x3a, 0xeb, 0xcc, 0xe3, 0x3d, 0x3f, 0xbf, - 0x5a, 0x0c, 0x49, 0x89, 0xef, 0xe1, 0x0b, 0x59, 0xdb, 0xd1, 0xfa, 0x53, 0xd6, 0x03, 0xa2, 0x3a, 0x13, 0xe0, 0x3d, - 0x56, 0xb3, 0x09, 0x8d, 0x82, 0x0c, 0xe2, 0x7a, 0x6b, 0xb4, 0xd7, 0x9b, 0x6c, 0xfb, 0x25, 0xb7, 0x47, 0xf5, 0x2b, - 0x88, 0xbc, 0xc2, 0xec, 0x7a, 0x3f, 0x6a, 0x87, 0x00, 0x1e, 0x2f, 0xb8, 0x5b, 0x03, 0xf7, 0x5c, 0xc5, 0x82, 0xe4, - 0xcd, 0x54, 0xe8, 0x9c, 0x73, 0x3f, 0xa4, 0xce, 0xd1, 0xbb, 0x71, 0xe3, 0xff, 0x34, 0x57, 0x96, 0x65, 0x96, 0xc2, - 0x64, 0x0c, 0x09, 0x95, 0x08, 0xcf, 0xdd, 0x16, 0xd6, 0x45, 0x79, 0x28, 0x8d, 0xae, 0x31, 0xa8, 0x47, 0x9d, 0x55, - 0x9a, 0x46, 0xb2, 0xf8, 0x1e, 0xed, 0x68, 0xbd, 0x30, 0x15, 0xa0, 0x59, 0x4a, 0xa9, 0x65, 0xd9, 0x3e, 0x97, 0x4b, - 0xa1, 0xef, 0xb4, 0x15, 0xfe, 0xfc, 0x0c, 0xf7, 0xdc, 0xa4, 0xdb, 0x0d, 0xf6, 0x1b, 0xdb, 0xc1, 0x8d, 0xc1, 0x34, - 0x7f, 0xfd, 0xbc, 0x19, 0x66, 0x83, 0x19, 0xcc, 0xc5, 0xb3, 0xbc, 0xc7, 0xb1, 0x2a, 0x6e, 0x5a, 0x1d, 0xf8, 0x27, - 0x37, 0x29, 0x36, 0x3f, 0x60, 0x86, 0x56, 0x7b, 0x97, 0x2b, 0x12, 0xce, 0xd7, 0xbc, 0x80, 0xbe, 0xc4, 0x2c, 0x26, - 0xcc, 0xe7, 0x7c, 0x1a, 0x10, 0x40, 0x55, 0x91, 0x3f, 0x4a, 0x29, 0x58, 0xd9, 0x12, 0xb9, 0x81, 0x0f, 0x54, 0x7b, - 0x40, 0xed, 0x64, 0xce, 0x57, 0x76, 0x48, 0x5d, 0x85, 0x5d, 0x81, 0x91, 0x9d, 0x93, 0x6b, 0x3b, 0x6e, 0xfb, 0x4f, - 0x97, 0x62, 0xbf, 0x58, 0x76, 0xd2, 0x73, 0xf4, 0x49, 0x2c, 0x9a, 0x85, 0x8e, 0x1e, 0xc9, 0xe9, 0x6b, 0xee, 0xef, - 0x8a, 0x48, 0x9e, 0xbf, 0xc1, 0xe5, 0x67, 0x29, 0x24, 0xf8, 0x47, 0x29, 0x6d, 0xb7, 0x23, 0xe6, 0x13, 0x5e, 0x43, - 0x69, 0xce, 0x42, 0xcb, 0x35, 0xd8, 0x00, 0x48, 0x18, 0x65, 0x34, 0x2a, 0xab, 0x6d, 0xfc, 0x75, 0x42, 0xa3, 0xfc, - 0x4b, 0x89, 0x05, 0x35, 0x98, 0x63, 0x44, 0xc5, 0x6b, 0x22, 0x84, 0xe7, 0xfe, 0x32, 0x17, 0xc7, 0x62, 0xd1, 0xe6, - 0xfe, 0x36, 0x67, 0x0b, 0x46, 0x65, 0xb6, 0x5a, 0x5f, 0x89, 0x1e, 0xda, 0x5d, 0x5d, 0xbc, 0x4c, 0xd7, 0xe6, 0xae, - 0x0f, 0x00, 0xe5, 0xa4, 0x0f, 0x96, 0x2e, 0xbc, 0x5e, 0x9f, 0x21, 0xc3, 0x06, 0xaf, 0x0b, 0xae, 0x22, 0xed, 0x07, - 0x48, 0xcd, 0x72, 0x6e, 0x6b, 0x57, 0x89, 0x9a, 0xec, 0x1b, 0x15, 0xa0, 0xef, 0x65, 0xce, 0x63, 0xa6, 0xd1, 0x47, - 0xad, 0x43, 0x8d, 0x18, 0x24, 0x42, 0xab, 0x88, 0xf8, 0xb3, 0xc9, 0x38, 0x0a, 0x45, 0xbc, 0x31, 0x61, 0xac, 0x50, - 0x20, 0x67, 0xf7, 0xdf, 0x3a, 0xbf, 0xba, 0xb2, 0x9f, 0x4e, 0x9a, 0xb2, 0x2e, 0x77, 0xed, 0x2e, 0xf8, 0xf4, 0xea, - 0x25, 0x26, 0x18, 0x17, 0x9f, 0xea, 0x95, 0xf7, 0x96, 0xbf, 0xea, 0x79, 0x7a, 0x77, 0x1d, 0x36, 0xf7, 0x11, 0xaa, - 0xc2, 0xaa, 0xb8, 0x63, 0xe6, 0x49, 0xd3, 0xfa, 0xcb, 0xf7, 0xa2, 0xf6, 0x8b, 0x1e, 0x1b, 0xe8, 0x65, 0x44, 0x71, - 0x3f, 0xd5, 0x5e, 0x3f, 0x28, 0x24, 0x8e, 0x5f, 0x27, 0x44, 0xc5, 0x55, 0xcb, 0xc2, 0xa7, 0x13, 0xac, 0x22, 0xab, - 0xe9, 0x9c, 0x44, 0x35, 0x10, 0xd9, 0x4c, 0x83, 0x00, 0x49, 0xe5, 0x29, 0xed, 0x21, 0xac, 0xdd, 0xd0, 0x2f, 0xef, - 0xc1, 0x08, 0x85, 0x0b, 0xd2, 0x4f, 0x32, 0xa7, 0xd4, 0xe6, 0x74, 0x46, 0x56, 0xe3, 0x80, 0x80, 0xdf, 0xff, 0xf7, - 0xcd, 0x57, 0xc2, 0xd4, 0x3e, 0x85, 0xf1, 0x59, 0xd1, 0x36, 0x41, 0x94, 0xdf, 0x43, 0x96, 0xb5, 0x17, 0xb9, 0xc8, - 0x2a, 0xd5, 0x65, 0xf2, 0x60, 0xcd, 0x6f, 0x62, 0x6c, 0xcb, 0xc3, 0x8d, 0x35, 0x5a, 0xc8, 0xe9, 0x36, 0x9a, 0x41, - 0xa1, 0x62, 0x4c, 0x7a, 0xf5, 0xe7, 0x15, 0x9b, 0xc7, 0x91, 0xc7, 0xaf, 0xf2, 0x29, 0x90, 0xc0, 0x6d, 0x62, 0x05, - 0x47, 0xcd, 0x4e, 0x45, 0x4d, 0x1f, 0x9e, 0xf3, 0xe5, 0xf1, 0x05, 0x50, 0x6d, 0xa8, 0x71, 0xc6, 0xbc, 0x56, 0x94, - 0x35, 0xa9, 0x23, 0x19, 0xcf, 0xbb, 0x0c, 0xb4, 0x9c, 0xa8, 0xe8, 0xbd, 0x5a, 0x52, 0xf4, 0x29, 0x5b, 0xbb, 0x0c, - 0xdf, 0x9a, 0x4c, 0xc8, 0x04, 0x05, 0x47, 0x20, 0xd2, 0xce, 0xc5, 0x0a, 0xed, 0xbf, 0x79, 0x52, 0xdf, 0x9b, 0xf1, - 0x49, 0x62, 0x44, 0x49, 0xc9, 0x77, 0x1f, 0x35, 0x5a, 0x08, 0xa2, 0xce, 0x86, 0x9b, 0xa4, 0x3f, 0xf3, 0xaa, 0x1c, - 0x13, 0x58, 0xe3, 0x48, 0x0c, 0xae, 0x2a, 0xfa, 0x09, 0x25, 0x5c, 0x21, 0xdd, 0x4e, 0x49, 0xc2, 0xd9, 0x23, 0xb4, - 0xa7, 0x79, 0xf5, 0xfd, 0x54, 0x95, 0x1f, 0x48, 0x04, 0x44, 0xb5, 0x19, 0x3a, 0x31, 0xf7, 0xf4, 0x75, 0xed, 0xd2, - 0x13, 0xfe, 0xfb, 0x52, 0xb9, 0x90, 0x3e, 0x8f, 0x17, 0xf3, 0xff, 0x7c, 0x33, 0xae, 0x23, 0x6d, 0xa3, 0xbe, 0xed, - 0x9a, 0x16, 0xed, 0xc8, 0xb2, 0x3e, 0x45, 0x0a, 0x0a, 0x43, 0x08, 0x25, 0x3f, 0x42, 0x58, 0x89, 0x6e, 0x8a, 0xae, - 0x22, 0x83, 0x35, 0x67, 0xc0, 0x0a, 0xaf, 0xea, 0xc0, 0xad, 0x22, 0x9f, 0xec, 0xbc, 0x62, 0x8b, 0xba, 0x4e, 0xa5, - 0x9b, 0x38, 0xe3, 0x77, 0x62, 0x82, 0x54, 0x6d, 0xdf, 0xf3, 0xc7, 0x3a, 0xa9, 0x39, 0xf9, 0x93, 0x8f, 0xf9, 0xd8, - 0x9d, 0xf4, 0xd7, 0x9d, 0xaf, 0xdb, 0x84, 0xb0, 0xe3, 0xa5, 0x4d, 0x4b, 0xb1, 0xc6, 0xdb, 0x60, 0x28, 0x5f, 0x89, - 0xa2, 0x4d, 0x7c, 0x8c, 0xc2, 0xbf, 0x29, 0xb4, 0x4f, 0x92, 0xb6, 0x59, 0x03, 0x45, 0x17, 0x6b, 0x7e, 0xfc, 0x6b, - 0x42, 0x83, 0x50, 0x0c, 0xd8, 0xd4, 0xf7, 0x32, 0x06, 0xed, 0xd3, 0x16, 0x0d, 0x1f, 0x7b, 0xf1, 0x01, 0x23, 0x4e, - 0x57, 0x3f, 0x06, 0xa8, 0x27, 0x8c, 0x63, 0x37, 0x4d, 0x2e, 0x92, 0x86, 0x51, 0xf1, 0x6a, 0x1c, 0xad, 0xdf, 0xdf, - 0xa7, 0xb1, 0x18, 0xfa, 0x6d, 0x06, 0x1f, 0x73, 0x73, 0x6e, 0xde, 0x1d, 0x93, 0x73, 0x72, 0x5e, 0x9e, 0x01, 0x39, - 0x74, 0x25, 0x78, 0x9c, 0x5c, 0x46, 0x69, 0x03, 0x6d, 0x3f, 0x6b, 0xec, 0x70, 0x28, 0xcb, 0xfb, 0xaa, 0x7a, 0x61, - 0xbf, 0xdb, 0xa4, 0xe0, 0x66, 0xcb, 0x37, 0xc5, 0xcf, 0xf2, 0xdf, 0xc0, 0x94, 0x30, 0x5f, 0x84, 0x24, 0xdf, 0x55, - 0xf9, 0xf5, 0xb1, 0x1f, 0x02, 0x78, 0x65, 0x94, 0x98, 0xb5, 0xab, 0xc2, 0xbc, 0x44, 0x3c, 0xc9, 0x9f, 0x2a, 0x42, - 0x10, 0x9d, 0x38, 0x64, 0xc9, 0xaf, 0x47, 0xc2, 0x66, 0x0c, 0x63, 0x73, 0x73, 0x91, 0x29, 0x7d, 0x4b, 0x93, 0x04, - 0x95, 0xe4, 0xa4, 0x02, 0x46, 0x2a, 0xc3, 0x19, 0xfe, 0x34, 0x97, 0x25, 0x7a, 0x8e, 0xd0, 0x7d, 0x8d, 0x6a, 0xdf, - 0x69, 0xdc, 0x26, 0xd7, 0x6a, 0x6e, 0xdc, 0x66, 0xfb, 0xee, 0xc9, 0x31, 0xf4, 0x38, 0xfb, 0x64, 0x42, 0xad, 0x3a, - 0xe1, 0xdc, 0xcd, 0xc3, 0xcb, 0xb8, 0x27, 0x7d, 0x43, 0x5b, 0x63, 0xe1, 0x6a, 0x0e, 0xf3, 0x23, 0xfd, 0x2e, 0xc6, - 0x90, 0xa7, 0xae, 0xb8, 0xdd, 0xa7, 0x71, 0xb4, 0x5e, 0x71, 0x0b, 0x32, 0x94, 0x5a, 0xf1, 0x01, 0x1b, 0xe5, 0x07, - 0x60, 0x8d, 0x0f, 0x01, 0xf9, 0xf6, 0x05, 0x17, 0xa8, 0x35, 0xcc, 0x2c, 0x2f, 0x3e, 0xbf, 0x98, 0x43, 0x38, 0xb9, - 0xa7, 0x4d, 0x0a, 0xb7, 0xdc, 0xa4, 0xe5, 0x6d, 0xd6, 0x4f, 0xd1, 0xf6, 0x90, 0xcb, 0x9e, 0xae, 0x3f, 0x61, 0x24, - 0x72, 0xe2, 0x84, 0xfb, 0xba, 0xb6, 0x58, 0xdf, 0x0f, 0xa3, 0xe2, 0xb4, 0x91, 0xeb, 0x91, 0x81, 0xab, 0x77, 0xf4, - 0x6e, 0x48, 0x3c, 0x55, 0xf3, 0x6b, 0xc5, 0xaa, 0x6e, 0x82, 0x7f, 0x1e, 0xab, 0x21, 0xed, 0x54, 0x5c, 0xec, 0xaf, - 0xce, 0x4e, 0xb2, 0xfc, 0x53, 0x0b, 0x48, 0x2f, 0x38, 0x76, 0x4d, 0x19, 0x6e, 0x21, 0xce, 0x77, 0x73, 0x3c, 0xbd, - 0xd4, 0xd2, 0x38, 0xa7, 0x88, 0x22, 0xa4, 0xb7, 0x82, 0xbf, 0xc7, 0xf0, 0xf5, 0x8c, 0xee, 0xa0, 0x11, 0x49, 0xce, - 0xbf, 0x3c, 0xa3, 0x59, 0xf9, 0xb5, 0xdd, 0x0a, 0x73, 0x07, 0x49, 0x5b, 0xc9, 0xe1, 0x0c, 0xd6, 0x86, 0x84, 0x0b, - 0xc9, 0x96, 0xa6, 0x4b, 0xaa, 0x3a, 0x60, 0x23, 0x7d, 0xd2, 0x27, 0x67, 0x1b, 0x9e, 0x88, 0x06, 0xc1, 0xf9, 0xf3, - 0x90, 0x0e, 0x96, 0xe3, 0xa5, 0x0d, 0x7d, 0x0a, 0x38, 0x5b, 0x36, 0x3e, 0xe8, 0xd4, 0x9a, 0x74, 0x3e, 0x52, 0x97, - 0x98, 0xe2, 0x27, 0xb6, 0xd2, 0x7d, 0x62, 0xbb, 0xd6, 0xa8, 0x7e, 0x5d, 0xdf, 0x6d, 0xea, 0x14, 0x99, 0x3a, 0x6d, - 0xca, 0x2d, 0xe4, 0xaa, 0xce, 0x77, 0x97, 0x1e, 0x6b, 0x19, 0xe4, 0xea, 0x97, 0x65, 0xbf, 0x49, 0xd0, 0xcd, 0xeb, - 0x7f, 0xca, 0xb5, 0xb3, 0xe5, 0x5a, 0xf9, 0x0c, 0x9a, 0xac, 0xae, 0xb5, 0xe9, 0xe6, 0x06, 0x56, 0x56, 0x48, 0x11, - 0x8a, 0x44, 0x48, 0x5b, 0x2d, 0xcf, 0x63, 0xf9, 0x12, 0x4e, 0xfc, 0xfd, 0x51, 0x30, 0x91, 0xa3, 0xa2, 0xb3, 0x50, - 0x37, 0xdb, 0x20, 0xa3, 0xe7, 0xe9, 0x01, 0xf7, 0x2a, 0xca, 0xd9, 0xc6, 0xed, 0x06, 0x51, 0x32, 0x7b, 0x5e, 0xc8, - 0x02, 0xf5, 0x58, 0xae, 0x5b, 0x61, 0xd3, 0xdd, 0x7c, 0xb6, 0x0b, 0x6a, 0x99, 0x2c, 0x8c, 0x9e, 0xb4, 0xc1, 0x42, - 0x22, 0x96, 0xdc, 0x02, 0x2b, 0xb2, 0x65, 0x90, 0xd5, 0xc5, 0x2b, 0xa0, 0x11, 0x6a, 0x5b, 0xf4, 0xc2, 0xe2, 0x0d, - 0x0a, 0x4c, 0x6e, 0x70, 0x16, 0x9d, 0x56, 0xbc, 0x35, 0x26, 0xfe, 0xd7, 0xee, 0x19, 0x37, 0x7d, 0xb8, 0x25, 0x5d, - 0x44, 0xb9, 0x71, 0x79, 0x5b, 0x53, 0xdf, 0xe6, 0x18, 0xe8, 0x7a, 0xcb, 0xab, 0x6a, 0xe4, 0x12, 0xb0, 0xc7, 0x65, - 0x68, 0x24, 0xdd, 0xfc, 0xbc, 0x06, 0x33, 0xa7, 0x33, 0x27, 0x90, 0xf0, 0xa2, 0x91, 0x51, 0x30, 0xf1, 0xf3, 0x85, - 0x68, 0x47, 0x35, 0x63, 0xa0, 0xc0, 0x07, 0xa4, 0xc1, 0x6d, 0x8e, 0x4b, 0xb3, 0x15, 0x9b, 0x45, 0x68, 0x4d, 0x99, - 0x63, 0xc2, 0xab, 0x6e, 0xc6, 0x51, 0x35, 0x06, 0xbb, 0x78, 0x18, 0x6d, 0xc6, 0x5b, 0xdb, 0x24, 0x01, 0x55, 0xd2, - 0x02, 0x38, 0xfd, 0x7c, 0x25, 0x52, 0xa3, 0xe4, 0x52, 0x40, 0xf0, 0x97, 0x53, 0xa0, 0x2d, 0xb7, 0x86, 0x6e, 0x62, - 0x10, 0x6e, 0x3a, 0x57, 0x70, 0xcb, 0x38, 0xf9, 0xc5, 0x70, 0x5a, 0x55, 0xf1, 0x82, 0x94, 0x89, 0x95, 0x1d, 0xf3, - 0x83, 0xad, 0x79, 0x9b, 0x6d, 0x97, 0xef, 0x03, 0xf9, 0x7d, 0xbf, 0xef, 0x5b, 0x6a, 0x5c, 0x9f, 0xef, 0xf2, 0x82, - 0x1d, 0x37, 0x91, 0xd6, 0x4a, 0x14, 0x59, 0x04, 0x8d, 0x76, 0x39, 0xb9, 0x80, 0xf7, 0xa0, 0xe6, 0xee, 0xce, 0xa8, - 0x8d, 0xac, 0xf0, 0x5e, 0xc1, 0xf6, 0x67, 0x99, 0xaf, 0x10, 0xe8, 0xe0, 0x01, 0x0c, 0xf5, 0x89, 0x22, 0x68, 0x24, - 0x42, 0x02, 0x58, 0x3f, 0x6f, 0x08, 0x30, 0x75, 0x8d, 0x92, 0x4d, 0xf0, 0x96, 0xf6, 0x47, 0x37, 0x1e, 0xb2, 0x74, - 0x19, 0xf1, 0x84, 0x48, 0x51, 0x78, 0x00, 0xed, 0xed, 0x23, 0x84, 0x19, 0xf3, 0x54, 0x8d, 0xf8, 0xf5, 0xd4, 0x9e, - 0x5e, 0x18, 0x67, 0xfb, 0x53, 0xfa, 0xff, 0xb9, 0x48, 0x55, 0x9e, 0x8f, 0xe9, 0xcc, 0x79, 0xfb, 0x43, 0xf1, 0xc1, - 0x93, 0x1b, 0x76, 0x0f, 0xe0, 0xd0, 0xb8, 0x9c, 0xac, 0x51, 0xd1, 0xfa, 0x4b, 0xc7, 0xa1, 0x89, 0xe7, 0xcf, 0xb2, - 0xaa, 0xf8, 0xd1, 0x7f, 0xaa, 0xe6, 0x3a, 0x9d, 0xb9, 0x88, 0xb3, 0x2b, 0xb9, 0x15, 0x94, 0x4e, 0xc0, 0x1f, 0xc6, - 0x6b, 0x8d, 0xb9, 0xc4, 0xbd, 0xe1, 0x66, 0xd7, 0xa3, 0xfa, 0xe3, 0x26, 0x03, 0xe3, 0xfd, 0x5b, 0xc9, 0x06, 0xe4, - 0x79, 0x5a, 0x8c, 0x39, 0x7a, 0xe1, 0x9d, 0x2e, 0x90, 0x81, 0xb0, 0x7b, 0xb6, 0xf1, 0x98, 0x28, 0x34, 0x7a, 0x89, - 0x14, 0x2e, 0xd8, 0x3b, 0xb6, 0x03, 0xb2, 0xdb, 0xcf, 0x77, 0xdb, 0x3a, 0xa0, 0xb4, 0x9b, 0xf0, 0xfa, 0x65, 0xcb, - 0x2a, 0x6f, 0x6e, 0xf9, 0x56, 0x99, 0x54, 0xdc, 0xd7, 0x36, 0xc4, 0x7a, 0xe4, 0x14, 0x3b, 0x80, 0x80, 0xc8, 0x62, - 0x09, 0x8d, 0x3b, 0x37, 0x17, 0x1e, 0x1f, 0x4f, 0x9e, 0x95, 0x8c, 0x3a, 0x57, 0xaf, 0xdf, 0xca, 0xba, 0x8a, 0x29, - 0xdb, 0x4b, 0xcf, 0x09, 0x7d, 0x3b, 0x05, 0xee, 0x89, 0x65, 0x34, 0x80, 0x56, 0x7a, 0xcc, 0x19, 0xb1, 0xc6, 0x89, - 0x47, 0xb4, 0x94, 0xc8, 0x3a, 0x94, 0x6f, 0x37, 0x62, 0x4b, 0x08, 0xd5, 0x2e, 0xb5, 0xd7, 0x8d, 0x06, 0x62, 0xfb, - 0x06, 0x10, 0x06, 0x90, 0xcc, 0x62, 0xcd, 0xf5, 0xa5, 0x90, 0x1e, 0xd7, 0x40, 0xa1, 0x76, 0xdf, 0x9c, 0xed, 0x35, - 0x29, 0x9f, 0x4b, 0x33, 0x07, 0xb4, 0xd4, 0xad, 0xf1, 0x7b, 0x60, 0x59, 0xac, 0xb7, 0x0e, 0xfb, 0x7e, 0x9c, 0x31, - 0xed, 0xc2, 0x68, 0x71, 0x6a, 0x3c, 0x41, 0x3d, 0xa8, 0x6b, 0x14, 0x84, 0x72, 0xb0, 0x95, 0xa4, 0x1d, 0xe0, 0x74, - 0x8a, 0xd9, 0x14, 0x80, 0xdb, 0xed, 0x48, 0x9e, 0x30, 0x49, 0x81, 0xe3, 0xb9, 0x86, 0x78, 0x12, 0x57, 0xf4, 0x97, - 0x40, 0xa1, 0x0a, 0x09, 0xc6, 0x8d, 0xf3, 0x48, 0xa8, 0x7f, 0x3f, 0x20, 0x92, 0xcb, 0x65, 0x92, 0x6c, 0x97, 0x2d, - 0x0d, 0x45, 0xad, 0xc0, 0x0f, 0xe8, 0xdb, 0xb8, 0x3d, 0xa4, 0xef, 0xc2, 0x87, 0xc3, 0xda, 0xda, 0x57, 0x1e, 0x61, - 0x16, 0x8e, 0x3d, 0x81, 0xdd, 0x19, 0x66, 0xc5, 0xfd, 0x9f, 0xcf, 0xf1, 0xeb, 0x0f, 0xef, 0x19, 0xd7, 0x1d, 0xfd, - 0x24, 0xf6, 0x7e, 0xd8, 0xd1, 0x71, 0xb3, 0x49, 0x71, 0x31, 0xb3, 0xdf, 0xb4, 0x91, 0xff, 0x75, 0xf1, 0x6c, 0xe2, - 0x9e, 0xde, 0xf1, 0x3b, 0x3d, 0x13, 0x7b, 0x39, 0x51, 0x55, 0xfe, 0xb8, 0x3f, 0x37, 0xf2, 0xfa, 0xac, 0xbf, 0xea, - 0x73, 0xd6, 0xe3, 0xda, 0xc3, 0x78, 0xfb, 0x8c, 0xeb, 0xa9, 0xe5, 0xf5, 0x61, 0xbf, 0x39, 0x1d, 0xf8, 0x3b, 0x0b, - 0x8a, 0xf7, 0xca, 0x15, 0xd3, 0x0a, 0x6d, 0xfc, 0x80, 0x72, 0x7a, 0xf0, 0x47, 0x6c, 0x88, 0x32, 0xb6, 0xc1, 0xf5, - 0x27, 0xb8, 0xce, 0x5a, 0xe1, 0x6c, 0xe0, 0x42, 0x94, 0x1e, 0xe9, 0xd7, 0x39, 0xbd, 0xd2, 0xf1, 0x30, 0x7e, 0xaa, - 0x6b, 0xe1, 0x58, 0xaa, 0x70, 0x66, 0x27, 0xe5, 0x78, 0xbb, 0x8d, 0xf5, 0x0c, 0xbe, 0x37, 0x0b, 0x4a, 0xaf, 0x32, - 0xd8, 0xc8, 0x15, 0xf3, 0x3e, 0x0e, 0x6a, 0xdb, 0x07, 0x1f, 0x8d, 0xf1, 0x6d, 0x9f, 0x8e, 0x2f, 0xda, 0xa4, 0x58, - 0xd9, 0xe3, 0x19, 0x03, 0x19, 0x1c, 0x7e, 0xc1, 0x88, 0x1d, 0xfa, 0xbf, 0x31, 0x55, 0xe9, 0x45, 0x54, 0x1d, 0x5b, - 0x99, 0x02, 0xd4, 0xc3, 0x36, 0x8e, 0x9f, 0xa8, 0x8d, 0xdd, 0x6a, 0x24, 0xe0, 0xf0, 0xda, 0xfd, 0x7a, 0x55, 0x10, - 0xc6, 0xf9, 0x7d, 0x80, 0xf7, 0x80, 0xca, 0xc2, 0x3e, 0x24, 0xee, 0xd0, 0x3e, 0x26, 0xe2, 0xfe, 0x5f, 0xfa, 0x1a, - 0x12, 0xd6, 0xab, 0xfd, 0x80, 0xaa, 0x86, 0x9f, 0x30, 0xc3, 0x9b, 0x2f, 0x97, 0xe3, 0x42, 0x2e, 0x42, 0x9e, 0xc7, - 0xca, 0xda, 0x59, 0xe7, 0xe6, 0x52, 0x16, 0x01, 0x97, 0x05, 0x58, 0xb1, 0xd5, 0xf7, 0x3f, 0xd6, 0x79, 0x4f, 0x03, - 0x88, 0xaf, 0x4b, 0x21, 0xc5, 0xd2, 0x8c, 0x4b, 0x2a, 0xa3, 0x4d, 0x45, 0xf4, 0x6f, 0x64, 0x48, 0x93, 0x39, 0x96, - 0x33, 0x67, 0xe9, 0x03, 0x09, 0x3e, 0x59, 0x30, 0xb0, 0x78, 0x0e, 0xaa, 0x95, 0xa4, 0x99, 0x10, 0x31, 0x91, 0x44, - 0x03, 0xd4, 0x3c, 0xa9, 0x2a, 0x28, 0x3c, 0xd5, 0x70, 0x6d, 0xf5, 0xc2, 0x29, 0x00, 0x24, 0x07, 0x44, 0x45, 0x2d, - 0x3c, 0xa5, 0xc5, 0x4b, 0x4d, 0xc7, 0x6f, 0xbb, 0xa5, 0x1d, 0x7b, 0x7b, 0x8f, 0xfc, 0x45, 0x4c, 0x4e, 0x44, 0xc5, - 0xd6, 0x26, 0x22, 0x81, 0xb7, 0x00, 0xb2, 0x39, 0x56, 0x8c, 0x03, 0x3a, 0x7e, 0xa3, 0x69, 0xb8, 0x8d, 0x1c, 0x95, - 0xf0, 0x0e, 0x46, 0xda, 0x62, 0x2e, 0x98, 0x6e, 0xa4, 0xd5, 0x10, 0x57, 0xaf, 0xd0, 0xaa, 0xb4, 0xd9, 0xc6, 0xc0, - 0x99, 0x6b, 0x31, 0x8a, 0xd7, 0x51, 0x31, 0x27, 0x64, 0x81, 0xf3, 0x70, 0x6e, 0x86, 0xb3, 0xb1, 0x06, 0xa5, 0x71, - 0xd4, 0x15, 0xa7, 0xf3, 0x6d, 0xb6, 0xee, 0xda, 0x77, 0x32, 0xcf, 0xb3, 0xc8, 0x26, 0xed, 0x66, 0x17, 0xd4, 0x38, - 0x57, 0x8c, 0xf9, 0x88, 0x1d, 0x9f, 0x71, 0xe9, 0xb9, 0x85, 0x61, 0x12, 0x1a, 0x8c, 0x9d, 0xd6, 0x2f, 0xd0, 0xf3, - 0x19, 0xdb, 0x15, 0x2e, 0xa0, 0x3c, 0x31, 0x16, 0xad, 0x20, 0x58, 0xbe, 0xad, 0x7f, 0x29, 0xf2, 0x30, 0x1b, 0x77, - 0x78, 0x60, 0x37, 0x4d, 0x3a, 0xf3, 0x7e, 0x78, 0x1e, 0x57, 0xd7, 0xb1, 0x9b, 0x65, 0x4f, 0x4c, 0x6e, 0x04, 0x54, - 0xac, 0x62, 0x9b, 0x97, 0x15, 0xf7, 0x50, 0x91, 0x4f, 0x5a, 0x28, 0xad, 0x52, 0xaa, 0x5e, 0x69, 0x4f, 0x46, 0x48, - 0x73, 0xb5, 0x9e, 0x81, 0x71, 0x21, 0xf0, 0x3e, 0x49, 0x2f, 0xbb, 0x6b, 0xcb, 0xdb, 0x74, 0x80, 0xb4, 0xf6, 0x36, - 0x7e, 0x79, 0x1d, 0x20, 0xce, 0xd5, 0xec, 0xa9, 0xe8, 0xf1, 0x8b, 0x20, 0x54, 0x9e, 0x4d, 0xd3, 0x0a, 0xea, 0xe2, - 0x8e, 0xae, 0xce, 0x61, 0x0d, 0x76, 0x9f, 0x7f, 0x16, 0xb6, 0x52, 0xf9, 0x7f, 0x7e, 0x93, 0xe8, 0x01, 0x3b, 0xec, - 0x21, 0x4d, 0x47, 0xf5, 0xa5, 0x9a, 0xdc, 0x05, 0x3e, 0x83, 0xd9, 0x8f, 0x1f, 0x74, 0x80, 0x65, 0xde, 0x9f, 0x8f, - 0x02, 0xbd, 0xb6, 0xda, 0x92, 0xf6, 0x64, 0x98, 0x6b, 0x82, 0xc1, 0x7d, 0xaf, 0x3b, 0x66, 0x2f, 0x9b, 0x8c, 0x4d, - 0x2c, 0x12, 0xe0, 0x83, 0xd0, 0x18, 0xc8, 0xfe, 0xc9, 0xfd, 0x9b, 0xa1, 0x2c, 0xcf, 0x7d, 0x38, 0x2b, 0xbc, 0x2e, - 0xdb, 0x67, 0xc2, 0x19, 0x6a, 0x91, 0x45, 0xca, 0x6a, 0x96, 0x5f, 0xda, 0x76, 0x0d, 0xd6, 0x4d, 0x59, 0xce, 0x5e, - 0xff, 0x98, 0xf2, 0x8d, 0x46, 0xa9, 0x4c, 0x86, 0xd5, 0x4e, 0x2a, 0x1d, 0x1e, 0x21, 0x90, 0x7a, 0x31, 0x96, 0x05, - 0xf3, 0x42, 0xf4, 0xf2, 0xf3, 0x91, 0x36, 0xb5, 0x17, 0x20, 0x08, 0xcc, 0xd5, 0x1e, 0x59, 0x2c, 0xf9, 0xba, 0x0d, - 0x80, 0xde, 0xb4, 0xd6, 0x57, 0x90, 0x50, 0xe5, 0xec, 0xb6, 0x60, 0x09, 0x7e, 0x92, 0xd6, 0x88, 0xc3, 0x8e, 0x2e, - 0xd8, 0x71, 0x1b, 0x73, 0x0c, 0xb0, 0x5c, 0xbb, 0xc9, 0x69, 0x38, 0x79, 0xc7, 0xdb, 0x8b, 0xe5, 0x64, 0x09, 0x2f, - 0xdc, 0xb8, 0x3d, 0x4c, 0xc3, 0x35, 0x6c, 0x6c, 0xf9, 0x24, 0x5d, 0x3c, 0xb5, 0xcb, 0xac, 0x49, 0xe8, 0xd3, 0x71, - 0xca, 0x77, 0x49, 0xc1, 0xf3, 0xdc, 0xc9, 0xec, 0xd0, 0xc5, 0xaa, 0x90, 0xcf, 0x5e, 0xdd, 0x0f, 0x2b, 0x0e, 0xab, - 0x07, 0x0f, 0xff, 0x87, 0xec, 0xda, 0x6c, 0x1e, 0x1a, 0x57, 0x6e, 0xb2, 0xec, 0x5c, 0x08, 0x91, 0x8e, 0x07, 0x62, - 0xa4, 0xfc, 0xd5, 0x3f, 0xa3, 0x2b, 0x77, 0x9a, 0xd9, 0xfe, 0xb5, 0x30, 0xc6, 0xc1, 0xdf, 0xd8, 0x56, 0x7b, 0xc8, - 0x1d, 0x54, 0xd7, 0x94, 0x9d, 0xd2, 0x7b, 0x76, 0x6c, 0xa3, 0x4f, 0x46, 0x34, 0xe8, 0x79, 0x7d, 0x33, 0x01, 0x72, - 0xde, 0x5f, 0xb4, 0x2d, 0x3e, 0x62, 0x04, 0xe4, 0x8d, 0x2e, 0x4f, 0xed, 0x3b, 0xc0, 0x70, 0x6d, 0xff, 0xb0, 0x02, - 0xa0, 0x9c, 0xb5, 0xa7, 0xb4, 0xc7, 0xed, 0xc3, 0x78, 0x20, 0x60, 0x61, 0x0d, 0xd6, 0x44, 0x65, 0x5f, 0x22, 0x5b, - 0x52, 0xb7, 0x40, 0x99, 0x0a, 0x0f, 0xb1, 0x63, 0x45, 0x38, 0x9f, 0xf4, 0x00, 0xb3, 0xb0, 0x74, 0xe6, 0x06, 0x1e, - 0x34, 0x83, 0x3a, 0xfe, 0x4e, 0x58, 0xb9, 0xee, 0x29, 0x75, 0x8f, 0x4c, 0x95, 0x31, 0x58, 0xea, 0x28, 0x95, 0x2c, - 0x78, 0x0e, 0xa6, 0x63, 0x09, 0x45, 0x8d, 0x6b, 0x97, 0x64, 0x10, 0x23, 0x5e, 0xbb, 0x80, 0x8e, 0x7e, 0x77, 0x73, - 0x70, 0x02, 0x3b, 0x24, 0xf3, 0x05, 0xc9, 0x6e, 0x1e, 0x21, 0x5b, 0x31, 0x1e, 0x99, 0xee, 0x46, 0x5c, 0xac, 0x58, - 0xb0, 0xc4, 0x12, 0xda, 0xa6, 0xe3, 0xbc, 0xe6, 0x0c, 0x64, 0x90, 0x47, 0x95, 0x8a, 0x52, 0xde, 0x6f, 0xc6, 0xf6, - 0x09, 0x49, 0xc3, 0x58, 0xfd, 0x04, 0xf3, 0x7a, 0xdc, 0x4a, 0x7c, 0x7a, 0x63, 0xa3, 0x67, 0x29, 0xea, 0x54, 0xa8, - 0x2f, 0xac, 0xa3, 0x62, 0x45, 0x24, 0xeb, 0x58, 0x6b, 0x2b, 0x0c, 0x8e, 0x0f, 0x33, 0x56, 0xe2, 0xb9, 0x27, 0xec, - 0x7f, 0x6c, 0xa4, 0xe1, 0xbe, 0x1b, 0x14, 0x72, 0x7d, 0xda, 0xb8, 0xb6, 0x62, 0x3e, 0x64, 0x69, 0x3a, 0x54, 0x9e, - 0x33, 0x5e, 0xdc, 0xc1, 0x83, 0x7c, 0x1f, 0x43, 0x9d, 0x09, 0xb2, 0x05, 0xa4, 0x2d, 0xc1, 0xa4, 0x85, 0xc9, 0xa4, - 0x80, 0xf5, 0x77, 0xa0, 0x36, 0x66, 0xf5, 0xc8, 0x93, 0x49, 0x14, 0xb4, 0xd1, 0x69, 0x5c, 0x56, 0xb3, 0x52, 0xcd, - 0xc8, 0x19, 0x27, 0x4f, 0x9c, 0x71, 0x8a, 0x9a, 0x1f, 0x06, 0x80, 0xf6, 0x7c, 0x18, 0x63, 0x90, 0x47, 0x08, 0x85, - 0xe2, 0xe3, 0x3a, 0x01, 0x69, 0xab, 0xb6, 0x59, 0x87, 0x04, 0x09, 0xfc, 0xa1, 0xd2, 0x34, 0x6a, 0x7b, 0x68, 0x34, - 0x41, 0x70, 0x9d, 0xd1, 0xad, 0x53, 0x3c, 0x60, 0x9a, 0x76, 0x74, 0x7b, 0xb7, 0xbc, 0xce, 0xf1, 0x88, 0xc4, 0x6c, - 0x95, 0xf9, 0xaa, 0x28, 0x91, 0xd8, 0x4c, 0x7b, 0x6c, 0x1c, 0x41, 0x38, 0xdd, 0xae, 0x0d, 0xda, 0x5d, 0xd5, 0x05, - 0x17, 0x68, 0xe2, 0x14, 0x85, 0x40, 0x6e, 0xae, 0x15, 0x3a, 0xa9, 0xc9, 0x51, 0x77, 0x40, 0x73, 0x53, 0x9d, 0x97, - 0x19, 0xb6, 0x7f, 0xc2, 0x9d, 0x4a, 0x2f, 0xc4, 0x22, 0x37, 0xf8, 0xab, 0x8f, 0xdc, 0xae, 0xb6, 0x41, 0x1b, 0xaf, - 0xd6, 0x49, 0x2b, 0xaf, 0xb6, 0xe1, 0x48, 0x56, 0x1a, 0x3a, 0x73, 0x19, 0xc6, 0xe6, 0xda, 0x4b, 0x19, 0x9d, 0xa7, - 0x17, 0x61, 0xdc, 0xa9, 0xcd, 0xf3, 0x11, 0x43, 0xce, 0x6d, 0xca, 0xc7, 0xf4, 0x6c, 0xbc, 0xfe, 0x67, 0xfe, 0xef, - 0xea, 0x84, 0x85, 0x0d, 0x6b, 0xbd, 0x13, 0x49, 0x23, 0x50, 0x49, 0x54, 0x8b, 0xbb, 0x0e, 0xda, 0x7b, 0x89, 0x71, - 0x6a, 0x9f, 0x1b, 0x0d, 0x92, 0xbe, 0x3f, 0x61, 0x24, 0x03, 0x41, 0xac, 0x29, 0x69, 0xf5, 0xfe, 0x75, 0x62, 0x2b, - 0xfa, 0x95, 0x20, 0xf1, 0x1f, 0xdf, 0x75, 0xbd, 0x95, 0x44, 0xa4, 0x41, 0xd3, 0x4e, 0x85, 0xcc, 0x06, 0xf0, 0xab, - 0x4f, 0x1f, 0x4a, 0x34, 0x31, 0x94, 0x9e, 0x5c, 0x21, 0xb0, 0x6b, 0x2f, 0x4e, 0xd7, 0x67, 0xde, 0xf0, 0xa6, 0xe2, - 0x0d, 0xc4, 0xe6, 0xaf, 0xfb, 0xc9, 0x9b, 0x95, 0x5f, 0x03, 0x5e, 0x16, 0xdc, 0xa1, 0xce, 0x6e, 0x54, 0xc2, 0x0f, - 0x1a, 0xce, 0x02, 0xe4, 0x28, 0x3f, 0xe9, 0x5f, 0x83, 0x0f, 0x1f, 0x0d, 0xde, 0xf0, 0xce, 0xa1, 0x7a, 0x53, 0x45, - 0x90, 0xe3, 0x92, 0x9c, 0x56, 0x16, 0x59, 0x1a, 0xae, 0x5b, 0xb0, 0x3a, 0x78, 0x83, 0x99, 0xa6, 0x6f, 0x6f, 0xc9, - 0xe9, 0x06, 0xa4, 0x15, 0xe1, 0x49, 0xec, 0x27, 0xd6, 0x29, 0x6c, 0xe2, 0x8b, 0x38, 0xdf, 0xaa, 0x68, 0x30, 0xde, - 0xde, 0xda, 0x89, 0x89, 0xd4, 0x07, 0xb0, 0x36, 0x2f, 0xde, 0x00, 0x6b, 0xbb, 0xf4, 0xcd, 0xef, 0x97, 0x59, 0xe4, - 0x12, 0x29, 0x73, 0x43, 0x1e, 0xee, 0x6b, 0x33, 0xa2, 0xae, 0x84, 0x42, 0x8e, 0xd0, 0xaa, 0x70, 0x95, 0x18, 0x51, - 0x72, 0x7a, 0xdb, 0xd5, 0xed, 0x24, 0x21, 0x16, 0x0a, 0xf5, 0x75, 0x25, 0x92, 0xd1, 0x4a, 0xc9, 0xf5, 0x3d, 0x72, - 0xa9, 0xaa, 0x3f, 0x82, 0x51, 0xaa, 0x6a, 0x68, 0xc8, 0xb5, 0x09, 0x08, 0xec, 0x6a, 0x2a, 0x2e, 0xe1, 0xc8, 0xb3, - 0xb6, 0x2c, 0xe1, 0xd2, 0x18, 0x94, 0x25, 0x5a, 0x0c, 0x32, 0xb5, 0xc8, 0x3b, 0x2f, 0xe9, 0x9a, 0xc7, 0x02, 0x9b, - 0x38, 0x62, 0xb1, 0x66, 0xfa, 0x31, 0x0f, 0xdb, 0x26, 0x5b, 0x0a, 0xda, 0x03, 0xbe, 0xe7, 0x26, 0x93, 0xf9, 0x4c, - 0xda, 0xeb, 0x9b, 0xf0, 0x92, 0x1b, 0x41, 0xa8, 0xed, 0xd1, 0x14, 0x11, 0x76, 0x7e, 0xe2, 0x0d, 0xce, 0xa0, 0x6a, - 0x9e, 0x89, 0xe5, 0x6a, 0xbd, 0xdd, 0x39, 0x83, 0xf4, 0x4d, 0xf8, 0xdb, 0x03, 0x79, 0xc0, 0x4d, 0xd9, 0x50, 0xe4, - 0xa4, 0x99, 0x27, 0x4e, 0x93, 0x27, 0xaa, 0xd5, 0x8f, 0x67, 0x28, 0xa3, 0x6e, 0x22, 0x62, 0xbd, 0xd9, 0xae, 0x14, - 0x29, 0xee, 0x25, 0xdd, 0xa5, 0x0e, 0xd7, 0x6e, 0x5e, 0x99, 0xd1, 0x8e, 0x42, 0x9f, 0xde, 0xad, 0x60, 0x85, 0x1a, - 0x6f, 0xfc, 0x98, 0x8d, 0x37, 0xe2, 0x82, 0x08, 0xf0, 0x21, 0x46, 0xcb, 0x82, 0x4e, 0x13, 0x2d, 0x66, 0x4f, 0x0f, - 0xca, 0xe7, 0x2e, 0xed, 0xd4, 0x55, 0xcb, 0xf8, 0x7a, 0xf8, 0xa0, 0x0d, 0x39, 0x6b, 0xd5, 0x18, 0xa7, 0xe5, 0x62, - 0x39, 0xbb, 0x3c, 0x42, 0x49, 0x71, 0xb8, 0x96, 0xdd, 0xfc, 0x2f, 0xda, 0xdc, 0xb0, 0xa1, 0xe6, 0x58, 0x38, 0xdd, - 0x69, 0x42, 0x63, 0x64, 0x37, 0x84, 0x83, 0xad, 0xa1, 0x16, 0x54, 0x10, 0xe9, 0x4f, 0xcc, 0xe1, 0xd9, 0xdb, 0x2c, - 0x05, 0x87, 0x8a, 0x11, 0x29, 0x1a, 0xf5, 0xd0, 0x29, 0x97, 0x89, 0x75, 0x8d, 0x5c, 0x4b, 0x8a, 0xf1, 0x27, 0xa3, - 0x9f, 0x48, 0xb3, 0xfc, 0x47, 0xe0, 0xe5, 0xd2, 0xb8, 0x34, 0xf8, 0x8d, 0xbf, 0x8d, 0xa1, 0x87, 0x27, 0x4f, 0x74, - 0x71, 0x61, 0xe3, 0xf0, 0x6f, 0xb8, 0xec, 0x42, 0x31, 0x66, 0x5b, 0x66, 0xbc, 0xb3, 0x5c, 0x9a, 0xbc, 0xa5, 0x0b, - 0x79, 0xca, 0x43, 0xe7, 0x0e, 0x9c, 0x10, 0x6d, 0x2c, 0x3b, 0xa0, 0xbe, 0x02, 0xe3, 0xdc, 0x87, 0xcc, 0xb8, 0xc8, - 0x16, 0x5d, 0xb9, 0xfe, 0x9a, 0x8b, 0x0e, 0x40, 0x2d, 0x12, 0x59, 0x5f, 0xd8, 0xc7, 0x58, 0xbb, 0x78, 0x5d, 0x6b, - 0xcf, 0x87, 0x28, 0xa6, 0x3e, 0xd7, 0x2b, 0x80, 0xa2, 0xc0, 0x68, 0xc3, 0x36, 0x76, 0x28, 0x21, 0x40, 0xba, 0x95, - 0x2d, 0xfa, 0x76, 0x8f, 0x46, 0x69, 0xa5, 0x54, 0x38, 0x67, 0x29, 0x1c, 0x95, 0xda, 0xc1, 0x22, 0x24, 0x16, 0xf1, - 0xa1, 0x74, 0x7e, 0x41, 0x24, 0x64, 0x3c, 0x67, 0x43, 0x54, 0x38, 0x49, 0x95, 0xe2, 0xf9, 0xb1, 0x9e, 0xb9, 0x6e, - 0x13, 0x8d, 0xd9, 0xa0, 0xfe, 0xc5, 0x67, 0xb7, 0xd4, 0xa9, 0x03, 0x88, 0x17, 0xbc, 0x73, 0x12, 0xfc, 0xb2, 0x00, - 0xe1, 0x9f, 0x1a, 0x17, 0xbd, 0xc8, 0xf2, 0x18, 0x8a, 0x94, 0x10, 0xe9, 0x9d, 0xc6, 0x4e, 0x64, 0xe8, 0xf4, 0x44, - 0x64, 0x01, 0xa3, 0x6b, 0x1b, 0xc8, 0x21, 0x1e, 0xfb, 0x31, 0xcb, 0x04, 0x2f, 0x40, 0x61, 0xa3, 0xd8, 0x44, 0x8b, - 0x7a, 0x59, 0xad, 0xa9, 0x59, 0x50, 0x13, 0x57, 0xa0, 0x47, 0xd3, 0x53, 0x5c, 0x07, 0x5e, 0xfb, 0xfa, 0x58, 0xc5, - 0xa2, 0x3d, 0x29, 0xd0, 0x04, 0x2b, 0x1c, 0xd0, 0x15, 0x8e, 0xc7, 0x0f, 0xe8, 0xdc, 0x3e, 0xa6, 0x1a, 0x9a, 0x58, - 0x15, 0xce, 0x6a, 0x8f, 0x39, 0x16, 0xd3, 0xda, 0x54, 0x79, 0xdd, 0x44, 0xa2, 0x41, 0x73, 0x5f, 0xd8, 0xc3, 0x67, - 0x7a, 0xb5, 0xd5, 0x62, 0x1c, 0x45, 0xfd, 0xe7, 0x5d, 0x84, 0x6f, 0xd0, 0xc6, 0xad, 0x16, 0xbe, 0x12, 0x54, 0xe5, - 0x05, 0x3a, 0x22, 0x20, 0x8e, 0xd6, 0x42, 0x64, 0xe6, 0x26, 0x05, 0x05, 0x55, 0x61, 0xbf, 0x67, 0x94, 0x57, 0x5f, - 0x6f, 0xca, 0xde, 0x8e, 0x33, 0xac, 0x37, 0x96, 0x1f, 0x8d, 0x11, 0xeb, 0x26, 0x24, 0x9c, 0x24, 0xbf, 0x83, 0xbf, - 0xa9, 0x19, 0xf4, 0x1f, 0xc0, 0xe9, 0xa3, 0x3e, 0xcc, 0xf8, 0x5d, 0x3d, 0x69, 0x02, 0x5d, 0x99, 0x6b, 0x06, 0xcf, - 0x8b, 0x53, 0x77, 0xa2, 0x90, 0x8d, 0x3d, 0xab, 0x65, 0x89, 0x1f, 0xb3, 0xa4, 0xeb, 0x35, 0xf1, 0xe8, 0x52, 0x66, - 0x50, 0x42, 0x28, 0x0d, 0x8c, 0xdd, 0x86, 0x22, 0xb3, 0xde, 0x03, 0xda, 0x1d, 0xb6, 0x31, 0x03, 0xeb, 0x29, 0x9a, - 0x24, 0x8d, 0xe3, 0x57, 0x9f, 0x7e, 0xa4, 0x36, 0x15, 0x43, 0x1a, 0xb6, 0x03, 0x94, 0x4d, 0x32, 0x14, 0x2b, 0xcc, - 0xfa, 0x6f, 0xd0, 0x7b, 0xbb, 0x6f, 0x87, 0xfd, 0x0a, 0xfe, 0xc8, 0x6f, 0x8f, 0x9a, 0x50, 0x36, 0x87, 0x15, 0x0e, - 0x1b, 0xb4, 0xe6, 0x5b, 0x32, 0x75, 0x50, 0x22, 0x0c, 0xe6, 0x05, 0x2a, 0x53, 0x3e, 0x0c, 0xe7, 0x24, 0x93, 0x90, - 0x19, 0x86, 0xbd, 0x9d, 0x58, 0x83, 0xb6, 0x7d, 0xb7, 0x52, 0x5a, 0xdd, 0xd5, 0xd3, 0x0c, 0x0e, 0x69, 0x96, 0xde, - 0xb6, 0x81, 0x81, 0x0e, 0xd7, 0xae, 0x58, 0xa1, 0x9f, 0x67, 0x13, 0x1a, 0x29, 0xc6, 0x80, 0x51, 0x4d, 0x80, 0xec, - 0x56, 0x71, 0xf3, 0x6c, 0xc3, 0x16, 0x49, 0xc4, 0xb4, 0x3f, 0xbd, 0x3a, 0x93, 0x83, 0x8a, 0xf6, 0x22, 0xfc, 0x96, - 0x85, 0x84, 0x70, 0x07, 0x7e, 0xd2, 0x8f, 0x5b, 0x49, 0xbd, 0x95, 0xd9, 0xe6, 0xd6, 0x1b, 0x6a, 0xe7, 0x96, 0x9a, - 0xb9, 0x93, 0x88, 0xf2, 0x64, 0x90, 0x01, 0x37, 0x60, 0xca, 0x46, 0x3f, 0x3a, 0x96, 0x4d, 0x89, 0x4e, 0x94, 0x07, - 0x8a, 0xcd, 0x5a, 0x06, 0xa1, 0x1b, 0x63, 0xba, 0x70, 0x8d, 0xd4, 0xc6, 0x04, 0xa0, 0x64, 0xc3, 0x6c, 0x31, 0x6d, - 0xfa, 0xdb, 0xe7, 0x22, 0xec, 0x0f, 0xf1, 0x40, 0x94, 0xdd, 0x83, 0xa8, 0x83, 0x8e, 0xe8, 0xbf, 0x2f, 0x60, 0x95, - 0xc1, 0x0b, 0xd6, 0x6f, 0x12, 0x1a, 0x3a, 0xe0, 0x2f, 0x6b, 0x2f, 0xd7, 0x22, 0xe5, 0xbc, 0xd5, 0x9d, 0x73, 0xf5, - 0x12, 0xae, 0xbf, 0xb5, 0x67, 0x4a, 0x88, 0x18, 0x2d, 0x4a, 0x40, 0x05, 0x0d, 0xca, 0x27, 0xb0, 0xba, 0x09, 0x54, - 0xf5, 0x36, 0xa5, 0x66, 0x2e, 0x2e, 0xec, 0xcf, 0xdf, 0x66, 0x83, 0x42, 0xeb, 0xe1, 0x83, 0x8c, 0x94, 0x47, 0x10, - 0x44, 0xaa, 0xc6, 0xc2, 0x37, 0x10, 0xf3, 0xaa, 0xa2, 0x74, 0x2d, 0xbe, 0x0d, 0x84, 0x7b, 0x9f, 0x52, 0xb3, 0xa0, - 0x1f, 0x44, 0x44, 0x17, 0xaa, 0xbd, 0x42, 0x46, 0x85, 0x78, 0x7e, 0x1b, 0x65, 0xc8, 0x92, 0x53, 0x53, 0x04, 0x6a, - 0x06, 0x4e, 0x5b, 0xeb, 0xf2, 0x60, 0xa3, 0xf1, 0x81, 0x79, 0x2a, 0xf8, 0xff, 0x3a, 0x7a, 0x09, 0xdf, 0xdd, 0x37, - 0x01, 0xc2, 0xda, 0x7f, 0x1e, 0xd5, 0x5d, 0xbd, 0x69, 0x2e, 0xc4, 0xec, 0x11, 0x7f, 0x1c, 0x02, 0x4f, 0xa7, 0xb9, - 0x77, 0xb1, 0x2a, 0xc1, 0xc0, 0x8e, 0x45, 0x0e, 0x7f, 0xd4, 0xf5, 0x34, 0x7f, 0xbe, 0xaa, 0x9a, 0xc4, 0xb2, 0x86, - 0x22, 0x7e, 0x8e, 0x67, 0x73, 0xa1, 0x3a, 0x51, 0x9a, 0x4c, 0x60, 0x84, 0x23, 0xad, 0x29, 0x49, 0x1e, 0xc1, 0xba, - 0xac, 0x3d, 0x34, 0x7b, 0xbf, 0xb5, 0x92, 0xe8, 0x19, 0x0f, 0xf9, 0xf9, 0x9b, 0xa1, 0x59, 0x9e, 0x8f, 0x28, 0x4f, - 0xbb, 0x97, 0x03, 0x1a, 0xf5, 0xce, 0x09, 0xab, 0xca, 0x05, 0xb1, 0x34, 0xf6, 0x11, 0x54, 0x73, 0x9e, 0xeb, 0x1a, - 0x0b, 0xc1, 0x55, 0x8f, 0xff, 0x06, 0x8e, 0x1a, 0xb5, 0xa1, 0xd2, 0xb3, 0x51, 0xb4, 0x36, 0xb8, 0x7c, 0x4b, 0x07, - 0x98, 0x02, 0x0a, 0x84, 0x5a, 0xb3, 0x3b, 0xaf, 0xdc, 0xf2, 0xc4, 0x03, 0xa9, 0xf7, 0xcc, 0x37, 0xce, 0xc0, 0x7c, - 0x95, 0xee, 0x5a, 0xe6, 0xb5, 0xdb, 0x54, 0xf1, 0x3d, 0xf4, 0x12, 0x54, 0x51, 0xc0, 0xdf, 0x85, 0x5d, 0x29, 0x89, - 0xac, 0xc3, 0x25, 0x88, 0xcb, 0xbe, 0x9d, 0xa1, 0x80, 0xd1, 0x7b, 0xc5, 0x15, 0xbb, 0xe1, 0x5d, 0xe7, 0x51, 0x99, - 0x43, 0x59, 0x93, 0x0f, 0xf0, 0x85, 0x97, 0xa3, 0xd5, 0xd7, 0xf6, 0x24, 0x19, 0x13, 0xfe, 0x1d, 0x90, 0x8c, 0x09, - 0x33, 0xa2, 0x12, 0xf3, 0x5c, 0x05, 0x1e, 0x98, 0x7f, 0xed, 0x21, 0xb7, 0xac, 0x47, 0xeb, 0xac, 0x03, 0xad, 0xe7, - 0xd4, 0xbb, 0x68, 0xe0, 0xf7, 0xa4, 0xb5, 0x03, 0x01, 0x00, 0xb2, 0x0e, 0x9d, 0x43, 0xcd, 0xad, 0x20, 0x5d, 0x55, - 0xb7, 0x87, 0x65, 0xe6, 0xb2, 0x6b, 0xb2, 0x66, 0x47, 0x8e, 0xf8, 0x25, 0x89, 0x2e, 0x50, 0x63, 0x7b, 0xca, 0x7b, - 0x7c, 0x9f, 0xd8, 0x16, 0xbc, 0x8c, 0xea, 0x0b, 0xe7, 0xa6, 0x09, 0x15, 0xf4, 0x83, 0x49, 0x15, 0xc4, 0x7a, 0x42, - 0x02, 0x66, 0xeb, 0xbe, 0x45, 0xd5, 0x7c, 0xcb, 0x57, 0xf6, 0xca, 0x84, 0x7c, 0xc2, 0xd5, 0xb3, 0xa2, 0x0a, 0x24, - 0xad, 0x2f, 0x06, 0x18, 0x0a, 0xe4, 0x12, 0x84, 0xe0, 0x12, 0x14, 0x1d, 0x8c, 0xf1, 0x04, 0x1c, 0x22, 0xce, 0x4b, - 0x8d, 0x87, 0xc9, 0xfd, 0x37, 0x6e, 0x62, 0x0d, 0x46, 0xc2, 0xe0, 0x8a, 0x0d, 0x80, 0x43, 0x2b, 0xd0, 0xea, 0x57, - 0xfb, 0xec, 0x0b, 0xdf, 0x0f, 0xd4, 0x25, 0xab, 0x09, 0xd9, 0x17, 0x51, 0x43, 0xf7, 0x02, 0x64, 0xf1, 0x2c, 0x8e, - 0x4b, 0xa2, 0x33, 0xbe, 0xf1, 0xd0, 0x43, 0x21, 0x0d, 0x42, 0xfe, 0x27, 0xa3, 0xe0, 0x04, 0xcc, 0x24, 0x2a, 0xda, - 0x12, 0x1e, 0xdd, 0xe8, 0x40, 0x03, 0xbb, 0xb1, 0x6e, 0x6a, 0xe1, 0x4e, 0x4c, 0xa5, 0xd5, 0x0d, 0x63, 0x58, 0x65, - 0x84, 0xa6, 0x91, 0xba, 0xdb, 0x9a, 0xb9, 0xba, 0x58, 0xed, 0x8e, 0x67, 0xdf, 0xff, 0x0d, 0x97, 0x32, 0x5b, 0x94, - 0x10, 0x67, 0x12, 0x63, 0xe2, 0x54, 0x2d, 0xbf, 0x11, 0x71, 0xe7, 0x7e, 0xa7, 0x00, 0x44, 0x9f, 0x71, 0x1a, 0x6d, - 0x36, 0x52, 0xd3, 0x03, 0x76, 0x07, 0x3c, 0x50, 0xfc, 0x21, 0xd8, 0xf8, 0x34, 0x79, 0xc8, 0xd6, 0x4a, 0x26, 0x97, - 0xb6, 0xae, 0x6b, 0x3b, 0xf5, 0x2e, 0x7e, 0xcc, 0xb1, 0xbd, 0xb5, 0x92, 0x3c, 0x15, 0x21, 0xe3, 0xe8, 0x93, 0x8d, - 0x27, 0xd4, 0x39, 0xe4, 0xe7, 0xc0, 0x00, 0xba, 0xf5, 0xba, 0xfe, 0x8f, 0x44, 0x84, 0xa7, 0x23, 0x06, 0x32, 0x4c, - 0x0c, 0x9e, 0x39, 0xc3, 0xa9, 0x57, 0x20, 0x3f, 0x86, 0x61, 0x9a, 0x00, 0x7d, 0x22, 0xc9, 0x15, 0xf8, 0x82, 0x60, - 0xf8, 0x48, 0x2d, 0x1b, 0xe2, 0x7d, 0x15, 0x3e, 0xac, 0xa6, 0x16, 0xc3, 0xa2, 0x07, 0x8b, 0x48, 0xe4, 0x81, 0x1c, - 0x60, 0x7d, 0x60, 0xc9, 0x0a, 0x23, 0x02, 0x1f, 0xb3, 0xbd, 0x71, 0xac, 0x00, 0x8c, 0x76, 0xc8, 0x75, 0xfe, 0xf2, - 0x29, 0xf8, 0x1b, 0x2f, 0x54, 0x8a, 0x7d, 0x43, 0x56, 0xfc, 0x23, 0x23, 0x58, 0x1c, 0x0f, 0xa3, 0x69, 0x74, 0x12, - 0xd0, 0x4c, 0x0e, 0xdd, 0x2a, 0x21, 0x86, 0xd9, 0x77, 0x01, 0xe3, 0xd2, 0x95, 0x93, 0xe4, 0xad, 0xfa, 0xc0, 0x58, - 0x90, 0x6e, 0x13, 0x0d, 0xb2, 0xf0, 0x97, 0x05, 0xad, 0xa4, 0x41, 0x5c, 0x93, 0xf7, 0x6e, 0xa6, 0x50, 0xda, 0x97, - 0xae, 0xc3, 0xd4, 0x5d, 0x49, 0xe0, 0xba, 0x12, 0x23, 0x81, 0x5f, 0x66, 0x0d, 0x8a, 0x7c, 0x8e, 0x98, 0xc7, 0xf1, - 0x0e, 0x80, 0x3b, 0x81, 0xe6, 0xc8, 0x21, 0x3b, 0x4f, 0xc4, 0xee, 0x9e, 0xc0, 0x1f, 0xcb, 0x1f, 0x89, 0xfa, 0xe5, - 0xf1, 0x28, 0x3b, 0xa0, 0x68, 0x7f, 0x93, 0x58, 0xaa, 0x42, 0x09, 0xa0, 0x91, 0x2d, 0x50, 0xe9, 0x0a, 0xe0, 0x32, - 0x70, 0x88, 0x58, 0x3d, 0xb3, 0x1e, 0x01, 0x3d, 0xf6, 0xf0, 0x67, 0xa7, 0xaf, 0x7d, 0x5d, 0x13, 0x56, 0x79, 0xdb, - 0x98, 0xac, 0xb3, 0x05, 0xe7, 0x5c, 0x57, 0x27, 0x69, 0xe6, 0xd5, 0x3d, 0x6d, 0xa8, 0x5f, 0x92, 0xb4, 0x6d, 0x2d, - 0xca, 0xc0, 0xf4, 0x73, 0x92, 0x86, 0x50, 0xe8, 0x8f, 0xe5, 0x99, 0x86, 0x52, 0xf3, 0x42, 0x77, 0x1e, 0xc5, 0xb7, - 0x54, 0x3b, 0xa4, 0x76, 0x5d, 0x9a, 0xf6, 0x11, 0xe1, 0x95, 0x34, 0xf6, 0x4c, 0x06, 0x1f, 0x41, 0x58, 0x1a, 0x8a, - 0x13, 0x73, 0x76, 0x09, 0x00, 0x09, 0x43, 0x0e, 0xee, 0x44, 0xde, 0xa6, 0xd8, 0x13, 0xd0, 0xd2, 0xa6, 0x76, 0xef, - 0xaa, 0xc1, 0x84, 0x2a, 0x51, 0xf2, 0xc0, 0xad, 0x6d, 0xf1, 0x58, 0x28, 0x93, 0xe8, 0x9f, 0x4d, 0x49, 0xa8, 0x24, - 0x7f, 0xea, 0xfc, 0x8f, 0x3f, 0x28, 0x22, 0x9d, 0x00, 0xb7, 0xac, 0x6a, 0xff, 0xdc, 0x89, 0x77, 0x32, 0xc4, 0x21, - 0x23, 0x23, 0xfc, 0x17, 0x95, 0xd1, 0xc7, 0x13, 0xb8, 0x24, 0x7c, 0xa4, 0x3d, 0xc8, 0x55, 0xf7, 0x44, 0x9d, 0x83, - 0x51, 0x1e, 0x6d, 0x60, 0x62, 0x7e, 0x9e, 0x86, 0xb3, 0x6e, 0x32, 0xb0, 0x30, 0xcb, 0x90, 0xcf, 0x8b, 0xed, 0xc1, - 0x01, 0x5f, 0x09, 0xc0, 0x17, 0x1a, 0x26, 0x1f, 0x73, 0x82, 0x6a, 0xc3, 0xc9, 0x94, 0xeb, 0xec, 0x6e, 0x9c, 0x6a, - 0xa9, 0x82, 0x76, 0x60, 0x42, 0x00, 0xf4, 0x5c, 0x70, 0x0b, 0x07, 0xcd, 0xcf, 0x9b, 0x7c, 0xc2, 0xc9, 0xa7, 0x7e, - 0x25, 0x7d, 0xd1, 0x18, 0x6a, 0x7d, 0x9e, 0x11, 0xb4, 0x34, 0x03, 0x6e, 0xe1, 0x72, 0x08, 0x5b, 0x38, 0x86, 0x05, - 0x19, 0x2f, 0x84, 0xf1, 0x02, 0x4a, 0xe0, 0xcb, 0x21, 0xc4, 0x00, 0xb6, 0x3f, 0x52, 0xb2, 0x9c, 0x50, 0xed, 0x59, - 0xd9, 0xa3, 0x00, 0x41, 0x64, 0xf2, 0xeb, 0x97, 0x8f, 0xff, 0x85, 0x22, 0xb0, 0x0a, 0xa8, 0x4d, 0x07, 0x90, 0xad, - 0x45, 0xc4, 0xb5, 0xf2, 0x54, 0x85, 0x79, 0xa5, 0x04, 0x93, 0xde, 0xf5, 0x0f, 0xaf, 0x7b, 0xab, 0xa0, 0x0f, 0x4b, - 0xcd, 0x31, 0x1b, 0x4d, 0x84, 0x4f, 0x19, 0xfd, 0x79, 0x6d, 0x1d, 0x20, 0xb7, 0x61, 0xf5, 0xc6, 0x95, 0x34, 0x0c, - 0x1a, 0xb5, 0x5f, 0xb2, 0x92, 0xd2, 0xea, 0x46, 0xce, 0x33, 0x4c, 0xbd, 0xe5, 0x1f, 0xee, 0x02, 0x3e, 0x06, 0xac, - 0x30, 0x3f, 0xd0, 0x4b, 0xed, 0x85, 0x57, 0x80, 0xdf, 0x18, 0x11, 0xe4, 0xbe, 0x6d, 0x89, 0x82, 0x4c, 0x6d, 0xbd, - 0x36, 0x95, 0x1e, 0xe6, 0x58, 0x4f, 0xbc, 0xcf, 0xc9, 0xbe, 0x78, 0xe7, 0x5e, 0x2b, 0xc1, 0x7c, 0x48, 0xe2, 0xbb, - 0x88, 0x28, 0x3d, 0x58, 0x4c, 0x8d, 0xa9, 0xf9, 0x03, 0xc0, 0x45, 0xe1, 0xe1, 0xd4, 0xfb, 0x37, 0xd9, 0x25, 0xaf, - 0x6d, 0x2f, 0x2f, 0x79, 0x1c, 0xf7, 0x77, 0x37, 0xfd, 0x86, 0x1f, 0x86, 0xaf, 0xd5, 0x8d, 0xa6, 0xc0, 0xf4, 0x2c, - 0x13, 0xc1, 0x35, 0xfc, 0x41, 0x52, 0x6e, 0x1f, 0x90, 0xb5, 0x0d, 0x9b, 0xe7, 0xd4, 0xda, 0x74, 0xed, 0x06, 0xbe, - 0x72, 0x3a, 0xbe, 0x7c, 0xf9, 0xfe, 0x03, 0x85, 0x72, 0x08, 0x3f, 0x1d, 0x13, 0x03, 0xa9, 0x2b, 0x74, 0x70, 0x27, - 0x9e, 0xe9, 0x71, 0x01, 0xfd, 0xe0, 0xd4, 0x06, 0xe4, 0x0f, 0xd7, 0xda, 0x0a, 0xbb, 0x35, 0xe3, 0x25, 0xea, 0x43, - 0x8f, 0xb0, 0xcd, 0xb2, 0xb0, 0xec, 0xb6, 0x6a, 0x00, 0x65, 0xc1, 0xe2, 0x1b, 0x38, 0x4d, 0x4d, 0x49, 0x0e, 0x9f, - 0xb5, 0xb7, 0x8b, 0x56, 0xdf, 0x63, 0x01, 0xee, 0x1f, 0x90, 0x14, 0x54, 0x08, 0xff, 0x5b, 0xb4, 0x7f, 0xd0, 0x14, - 0x88, 0x2f, 0x49, 0xa1, 0x06, 0xc3, 0x47, 0x9e, 0x60, 0xfd, 0x49, 0x11, 0x35, 0x56, 0xf2, 0xdc, 0x7b, 0x08, 0x68, - 0x5c, 0xde, 0x20, 0xf4, 0x1a, 0xbc, 0xaa, 0x1c, 0x1e, 0x94, 0x37, 0x51, 0xce, 0x78, 0x6a, 0xf2, 0xbe, 0x2e, 0x31, - 0xa1, 0xb7, 0xb7, 0x55, 0xaa, 0x78, 0xaa, 0x7a, 0xa4, 0x3c, 0x24, 0x01, 0xd2, 0x45, 0x81, 0x8b, 0x36, 0x1d, 0xe7, - 0x67, 0xc1, 0x9c, 0x15, 0xf8, 0x52, 0x6e, 0x24, 0xca, 0x2f, 0xc6, 0xcc, 0x6c, 0xe4, 0xaf, 0x37, 0x2e, 0x37, 0x5e, - 0xdd, 0xd6, 0x4a, 0x34, 0xd7, 0x92, 0x02, 0x5d, 0xae, 0xa3, 0xbf, 0xba, 0x11, 0x86, 0x72, 0x48, 0xf9, 0x4f, 0x28, - 0x4c, 0x6c, 0x81, 0x14, 0xe4, 0x25, 0x91, 0xff, 0x1e, 0x96, 0xb3, 0x85, 0xaf, 0x62, 0x1f, 0xa0, 0x6c, 0x24, 0xf6, - 0x07, 0x22, 0x45, 0xa6, 0xdd, 0x58, 0xb6, 0xfb, 0xbf, 0x16, 0x6f, 0xfe, 0x55, 0x95, 0x2f, 0xd5, 0xb3, 0x44, 0x14, - 0xea, 0x9c, 0x94, 0xcf, 0x30, 0xda, 0xe2, 0x7f, 0x86, 0x22, 0xad, 0x42, 0x0f, 0x6d, 0x0f, 0x3c, 0x0c, 0xad, 0x49, - 0x60, 0xcb, 0x7b, 0x3a, 0x04, 0x1b, 0x54, 0x9b, 0xd8, 0x72, 0x1a, 0x75, 0x56, 0xb4, 0x2a, 0xf7, 0xd8, 0x73, 0xed, - 0x19, 0xd4, 0xa3, 0x58, 0xe5, 0xa7, 0xe6, 0xd2, 0x80, 0x85, 0x01, 0x7f, 0x03, 0xf1, 0x55, 0xcc, 0xb9, 0xde, 0xad, - 0xe3, 0xb7, 0xcd, 0x4d, 0x58, 0x69, 0xa8, 0x5b, 0x00, 0x19, 0x17, 0x0c, 0x98, 0x3d, 0xf3, 0x04, 0x82, 0x62, 0x50, - 0x06, 0x03, 0x4e, 0xd3, 0xe7, 0x39, 0x67, 0x09, 0xf4, 0x91, 0xbd, 0x82, 0x03, 0x12, 0x42, 0xab, 0x58, 0x33, 0x91, - 0x2f, 0x40, 0x91, 0xae, 0xda, 0xe4, 0xcc, 0xb5, 0xa8, 0xa7, 0x09, 0xad, 0x02, 0x99, 0xc7, 0x0a, 0xa6, 0xcf, 0xbe, - 0x51, 0xc8, 0xa5, 0x30, 0x93, 0x3b, 0x7f, 0x41, 0xf3, 0x38, 0xcc, 0xd0, 0x45, 0x7e, 0x4a, 0x43, 0xb6, 0x73, 0x73, - 0xbf, 0x7d, 0x90, 0xc4, 0x27, 0xea, 0xc4, 0x7c, 0xc2, 0xfc, 0x57, 0x6f, 0xde, 0x75, 0x6f, 0x9a, 0xf3, 0xab, 0x69, - 0xfe, 0x5a, 0x41, 0xb3, 0x3f, 0x2e, 0xae, 0x50, 0xea, 0x8f, 0x58, 0xae, 0x9a, 0x56, 0x3e, 0xb2, 0x5f, 0x8d, 0x93, - 0x11, 0x91, 0xd0, 0x5e, 0x96, 0xd7, 0x31, 0x69, 0xf6, 0x9e, 0x5b, 0xb8, 0x6f, 0xc3, 0x4b, 0xc3, 0x62, 0xb9, 0x94, - 0x29, 0xad, 0x97, 0xc4, 0xfa, 0xc8, 0x05, 0xfe, 0x58, 0x22, 0x53, 0x1b, 0x6f, 0xf2, 0x8e, 0x74, 0x7e, 0x55, 0x77, - 0x79, 0x9c, 0x30, 0x98, 0xb9, 0x1b, 0x0b, 0x83, 0x3e, 0xd8, 0xcd, 0xd7, 0x91, 0xb7, 0x32, 0x04, 0xbd, 0x28, 0xdd, - 0xcd, 0x6e, 0x77, 0x9f, 0xa1, 0x60, 0xa5, 0x64, 0xc8, 0x96, 0x94, 0xf1, 0x47, 0x47, 0x0d, 0xf9, 0x4b, 0xa9, 0xcf, - 0xff, 0x4c, 0x22, 0x6e, 0xec, 0x7e, 0x79, 0xea, 0x44, 0x06, 0x5f, 0x90, 0xbb, 0x63, 0x24, 0xcb, 0xa7, 0x40, 0x21, - 0xec, 0x48, 0xb0, 0xf9, 0x4e, 0xb7, 0x09, 0x0e, 0x89, 0x34, 0x82, 0x86, 0xfa, 0xa8, 0x12, 0x81, 0x0a, 0xf1, 0x39, - 0x7d, 0x49, 0x1d, 0x3d, 0xeb, 0x5f, 0x8e, 0x7d, 0x06, 0x82, 0x56, 0x25, 0x32, 0x2a, 0x9d, 0x5c, 0x26, 0xa7, 0x30, - 0x82, 0x48, 0x50, 0x04, 0xb9, 0x49, 0x43, 0xf8, 0x70, 0x94, 0x5e, 0x3c, 0x29, 0x0d, 0x6b, 0x70, 0x0d, 0x1e, 0x4f, - 0x10, 0x93, 0x8c, 0x71, 0xeb, 0xdd, 0x6e, 0xdc, 0x9f, 0xde, 0x36, 0x60, 0xf5, 0x8f, 0x04, 0x9a, 0x20, 0xdc, 0x97, - 0x5c, 0xa0, 0x27, 0xe0, 0xb8, 0x16, 0x5c, 0xfb, 0x04, 0x86, 0x46, 0x07, 0x6a, 0xe9, 0xc8, 0x9d, 0x22, 0xff, 0x06, - 0x3c, 0xbb, 0x5b, 0x01, 0xe1, 0xda, 0xe5, 0x7d, 0x16, 0xd5, 0x12, 0x81, 0x5a, 0x67, 0x12, 0xcd, 0x6a, 0x11, 0xaa, - 0x6d, 0xbb, 0x01, 0x57, 0xc7, 0x50, 0xec, 0xa1, 0xf1, 0x17, 0xb0, 0xf0, 0x7c, 0xf2, 0xce, 0xc6, 0xc9, 0x78, 0x48, - 0x5f, 0xb5, 0x19, 0x2d, 0x9e, 0x7c, 0x6c, 0x39, 0xa6, 0xd2, 0x41, 0x0a, 0x1e, 0x2d, 0x08, 0xc2, 0x22, 0x7d, 0xe6, - 0x11, 0xb3, 0x1d, 0xe7, 0x7d, 0x00, 0x67, 0x71, 0x81, 0xee, 0x85, 0x11, 0x3c, 0x3c, 0xb6, 0x17, 0x07, 0x16, 0xb4, - 0x9f, 0x6b, 0x9d, 0xad, 0x48, 0x8b, 0x11, 0xee, 0x45, 0xcb, 0x5d, 0xc5, 0xb8, 0x8e, 0x3c, 0xc2, 0x97, 0xc1, 0xfb, - 0xee, 0x20, 0xc9, 0x73, 0x2b, 0x1c, 0x1c, 0x05, 0x3c, 0x90, 0x27, 0x46, 0x32, 0x46, 0x33, 0xf9, 0xf6, 0x67, 0x72, - 0xb7, 0x67, 0xbf, 0x19, 0x6e, 0x76, 0xc1, 0x45, 0x55, 0xa4, 0xcb, 0x6b, 0xbe, 0xee, 0xd6, 0xd1, 0xe5, 0x6b, 0x00, - 0xbe, 0x55, 0xf4, 0xa6, 0x2b, 0xac, 0x66, 0xb2, 0x11, 0x15, 0xce, 0xdf, 0xe5, 0x08, 0xae, 0x3c, 0xb7, 0x07, 0x15, - 0x63, 0xf0, 0x1e, 0x53, 0x9f, 0xd5, 0xda, 0xdb, 0x97, 0xba, 0x4d, 0x3f, 0xed, 0xb7, 0xdd, 0x68, 0x1a, 0xb5, 0xf8, - 0xfd, 0xf8, 0xc2, 0xa2, 0x63, 0x88, 0x74, 0x99, 0xf2, 0x65, 0xfa, 0x9b, 0x53, 0x56, 0x81, 0xb3, 0x50, 0x80, 0x6e, - 0xdd, 0x70, 0x31, 0x96, 0xf2, 0xdd, 0xd8, 0x42, 0xd4, 0xd7, 0x57, 0xa1, 0xb4, 0x27, 0xf6, 0xdc, 0xef, 0x1a, 0x0e, - 0x64, 0xf0, 0x6c, 0xbc, 0x0a, 0x3b, 0xba, 0x0a, 0xcf, 0x24, 0xde, 0xe7, 0xd7, 0xb9, 0xec, 0x3d, 0x53, 0x37, 0xef, - 0x10, 0xf8, 0x5f, 0x33, 0xbc, 0xf2, 0xb7, 0x4a, 0x98, 0xf3, 0x15, 0xff, 0x4a, 0xfc, 0xce, 0xd1, 0x0d, 0x17, 0xd1, - 0x65, 0xeb, 0x84, 0x56, 0xac, 0xf8, 0x75, 0xde, 0x7f, 0xfb, 0xf0, 0x29, 0x7a, 0x30, 0xae, 0x47, 0x86, 0x5f, 0xa5, - 0x3c, 0x87, 0x75, 0x9b, 0x46, 0x65, 0xfe, 0x54, 0xe0, 0xc5, 0x3a, 0x7f, 0x51, 0x30, 0xea, 0x4d, 0xf2, 0x57, 0xcf, - 0xbf, 0x4e, 0x5f, 0x3c, 0x90, 0x5c, 0xf8, 0x8f, 0x79, 0x7b, 0xb4, 0x1d, 0x81, 0x8b, 0xe7, 0x8f, 0x5e, 0x45, 0xe7, - 0xfa, 0xd3, 0xd6, 0x27, 0x31, 0x88, 0x7d, 0xa9, 0x8e, 0x30, 0x37, 0xde, 0xa3, 0x45, 0xd8, 0x67, 0xf4, 0x13, 0x7b, - 0x4a, 0x56, 0xaf, 0x40, 0xe4, 0x09, 0x5a, 0x9d, 0x9d, 0x23, 0x82, 0x3f, 0x44, 0x7f, 0xe4, 0x97, 0xa8, 0xd1, 0xce, - 0xb3, 0x7f, 0xd9, 0xd6, 0xff, 0xff, 0xa7, 0xeb, 0xb9, 0x19, 0x2d, 0x1a, 0xe0, 0xa5, 0xff, 0x0b, 0x44, 0xdb, 0xd9, - 0xde, 0x08, 0x52, 0x03, 0x17, 0x1e, 0xf1, 0xb3, 0x5b, 0xcb, 0xba, 0xfc, 0xf2, 0xb9, 0x9a, 0x2d, 0xa3, 0x09, 0x95, - 0x93, 0x0b, 0x4d, 0x93, 0xa4, 0x86, 0x0c, 0x5e, 0x33, 0x49, 0x7f, 0x4d, 0xcb, 0xc0, 0xbb, 0x2d, 0xa9, 0x45, 0xe6, - 0x24, 0x1f, 0x67, 0x48, 0xc5, 0xe2, 0x59, 0xb7, 0xa9, 0x36, 0x1e, 0x3d, 0x8d, 0xde, 0x0c, 0x08, 0x5f, 0x59, 0x40, - 0xcf, 0xc1, 0x52, 0xd3, 0x95, 0x1b, 0x3b, 0x4b, 0xf7, 0xb6, 0x19, 0x87, 0x22, 0x82, 0xa6, 0x6e, 0x5d, 0x6e, 0x5b, - 0x1f, 0x95, 0x54, 0x72, 0xe6, 0xcd, 0x01, 0x02, 0xbc, 0xf8, 0x7e, 0xbc, 0x2d, 0x7d, 0xde, 0x0f, 0x72, 0x95, 0x46, - 0x18, 0xd6, 0xf1, 0x52, 0x3a, 0x8b, 0x57, 0x9b, 0x55, 0x08, 0xda, 0x05, 0x10, 0x67, 0x2d, 0x74, 0x8d, 0x80, 0xa6, - 0x45, 0xbc, 0xc7, 0x95, 0x20, 0x9b, 0x1a, 0x54, 0xb2, 0x94, 0x86, 0x0f, 0xf4, 0x07, 0x10, 0x83, 0xae, 0xb6, 0x91, - 0x0a, 0x6e, 0x1c, 0xbb, 0x4f, 0x65, 0x20, 0x99, 0xc4, 0xf7, 0xaf, 0xb2, 0x4a, 0x58, 0x1b, 0xc5, 0x78, 0x29, 0xb4, - 0x4f, 0x7e, 0xcd, 0x6d, 0xaa, 0x26, 0x07, 0x3d, 0xfb, 0x8f, 0x7b, 0x81, 0xee, 0x89, 0xa2, 0xed, 0x8c, 0x31, 0x35, - 0xcf, 0xb9, 0x07, 0x66, 0x91, 0x02, 0x8d, 0x21, 0xf4, 0xa0, 0x7f, 0x4f, 0xe8, 0xa1, 0x9e, 0x54, 0x45, 0x79, 0xb1, - 0x62, 0x5c, 0xbe, 0x9a, 0x4e, 0x0b, 0x69, 0x67, 0x1c, 0xbb, 0x0e, 0x77, 0x03, 0xff, 0xbd, 0xfa, 0x57, 0x1f, 0xc6, - 0x67, 0xfb, 0x18, 0xd3, 0x9e, 0xcf, 0x54, 0x4d, 0xfd, 0x38, 0xad, 0xfa, 0x6d, 0x70, 0x56, 0x79, 0x3e, 0xdf, 0x2a, - 0x2d, 0x10, 0x89, 0x44, 0xa1, 0xcc, 0x3c, 0xcf, 0xb7, 0x7d, 0x1a, 0x2d, 0x13, 0xdb, 0xf8, 0xd6, 0x0d, 0x8a, 0x7a, - 0x2f, 0xaf, 0x26, 0x0a, 0x80, 0x6e, 0x2c, 0x29, 0xa4, 0x5b, 0x62, 0x0b, 0x20, 0x9d, 0xcf, 0xb1, 0x27, 0x09, 0xac, - 0xb6, 0x26, 0xf3, 0x00, 0x0a, 0x59, 0xa2, 0x4d, 0x12, 0x23, 0xd2, 0x2f, 0x00, 0xe2, 0x35, 0x42, 0x79, 0x91, 0xfd, - 0x02, 0x69, 0x80, 0x55, 0x11, 0xe5, 0x8d, 0x4a, 0xe4, 0x2c, 0x6f, 0x32, 0x46, 0x19, 0x2c, 0xff, 0x07, 0xfc, 0xca, - 0x7c, 0x89, 0x40, 0x89, 0xc9, 0x6b, 0x87, 0x96, 0xce, 0x22, 0x4f, 0x2b, 0x6c, 0xf7, 0x43, 0x98, 0xcf, 0xd8, 0xf5, - 0xd9, 0x74, 0x33, 0xb3, 0x24, 0xb6, 0xb8, 0x6a, 0x6e, 0x3e, 0x73, 0xb8, 0x6d, 0x0b, 0xc9, 0xb6, 0xd5, 0x03, 0x7b, - 0x92, 0xee, 0xea, 0x87, 0x9b, 0xa7, 0x36, 0xfd, 0x48, 0xe1, 0xbc, 0x9a, 0xc8, 0xbc, 0x1c, 0x3e, 0xf2, 0xba, 0x77, - 0x2d, 0x42, 0x8d, 0x8d, 0x27, 0xe1, 0xa1, 0xe6, 0xbd, 0x6b, 0x13, 0xbe, 0xf2, 0xbf, 0x8a, 0xe3, 0x69, 0x55, 0xd6, - 0xfd, 0x7a, 0x1e, 0x1b, 0x1f, 0x31, 0x3e, 0x6a, 0x6d, 0xca, 0x0c, 0xc8, 0x43, 0xb5, 0xe7, 0xba, 0x93, 0xa7, 0xb4, - 0xdd, 0x8c, 0x99, 0x6e, 0x39, 0x17, 0x8a, 0xcc, 0xcc, 0xf6, 0x28, 0x17, 0x3c, 0xad, 0xf9, 0x7a, 0x0b, 0xe5, 0x2c, - 0x2d, 0xc7, 0x99, 0xda, 0x29, 0x5d, 0xcf, 0xe5, 0xda, 0xa3, 0x9a, 0x40, 0x0e, 0x29, 0x36, 0xea, 0x5d, 0x26, 0x41, - 0x90, 0xf0, 0xb1, 0xb4, 0x74, 0xeb, 0x0c, 0x28, 0x9f, 0x57, 0xb9, 0x2f, 0xd1, 0xd4, 0xaf, 0xae, 0x5d, 0x90, 0x71, - 0xb7, 0x03, 0x91, 0xd8, 0x56, 0x32, 0xcc, 0x8a, 0x48, 0x03, 0x0f, 0x4e, 0x4d, 0x6d, 0xcf, 0xba, 0xec, 0xac, 0xda, - 0x9a, 0x39, 0xa0, 0x03, 0x26, 0x8f, 0x96, 0x61, 0x3e, 0xe6, 0x05, 0x7f, 0xae, 0x39, 0xdb, 0x68, 0xd4, 0x2f, 0x55, - 0xd8, 0xb6, 0x19, 0x16, 0x3d, 0x29, 0xc0, 0x3f, 0x94, 0xc0, 0x9b, 0x0a, 0x32, 0x00, 0x5c, 0xba, 0x36, 0x1c, 0xc1, - 0x65, 0xcb, 0x42, 0x42, 0xb2, 0xad, 0x5e, 0x7b, 0x0b, 0x10, 0x6c, 0xb6, 0xa4, 0x04, 0x0a, 0xc5, 0xcd, 0xa0, 0x79, - 0x8b, 0x6f, 0xb5, 0x47, 0x92, 0x36, 0xbe, 0x98, 0xe1, 0xee, 0x93, 0x20, 0xf0, 0xe6, 0x37, 0x07, 0xb6, 0xe8, 0x87, - 0x31, 0xce, 0x20, 0x0c, 0xcb, 0xba, 0xbf, 0x64, 0x46, 0x3c, 0xf7, 0x51, 0x7a, 0x1b, 0x7f, 0xbb, 0x08, 0xde, 0x44, - 0xf2, 0x6b, 0x0c, 0xd6, 0x68, 0x9c, 0xbc, 0xe0, 0x92, 0xf7, 0x62, 0x13, 0x78, 0xeb, 0xe7, 0x70, 0xc6, 0x34, 0x92, - 0xe7, 0xb1, 0xba, 0xf9, 0xd3, 0xd8, 0xad, 0x47, 0xbe, 0x7f, 0xf9, 0xfd, 0x2e, 0x94, 0xa4, 0x35, 0xf2, 0x20, 0x85, - 0x5c, 0x64, 0x80, 0x3a, 0x05, 0x2f, 0x5b, 0xa2, 0x6e, 0x65, 0x45, 0x9e, 0x1c, 0xf6, 0xf2, 0xfb, 0x1f, 0xcd, 0xed, - 0xf8, 0x72, 0x83, 0xb4, 0x89, 0x06, 0x88, 0xd1, 0xa9, 0x92, 0x2e, 0x11, 0xc7, 0xd7, 0xe1, 0x3f, 0xfe, 0x30, 0x9a, - 0x6f, 0x9c, 0x89, 0x77, 0xdb, 0x68, 0x11, 0xb5, 0x95, 0xe4, 0xf9, 0x71, 0xf8, 0xc8, 0x73, 0x0b, 0x6b, 0xff, 0x33, - 0x6d, 0x34, 0x8d, 0x79, 0xa1, 0x4e, 0x4f, 0x98, 0xf1, 0x77, 0x98, 0xf1, 0xff, 0xa5, 0xc7, 0x7f, 0x5e, 0xfd, 0xff, - 0xf6, 0xfe, 0x4b, 0xd0, 0xd5, 0xf1, 0xf2, 0xfe, 0xaf, 0x59, 0xfe, 0x35, 0x7f, 0x84, 0x75, 0xfc, 0x6e, 0x67, 0xf3, - 0xb5, 0x4a, 0xb3, 0x29, 0x1f, 0xad, 0xed, 0x3c, 0x21, 0x60, 0x34, 0xcf, 0x4a, 0x14, 0xcc, 0x73, 0x5c, 0x9d, 0x9b, - 0x51, 0xfe, 0xd8, 0x11, 0x16, 0x7e, 0x31, 0xbe, 0x8b, 0xce, 0x75, 0x70, 0x2f, 0xe7, 0xdf, 0x48, 0xe1, 0xbe, 0x38, - 0xa6, 0xd8, 0x56, 0xd6, 0x4a, 0xfa, 0x3e, 0x74, 0xec, 0x88, 0xc0, 0xf6, 0x73, 0xff, 0x95, 0x95, 0xb1, 0x27, 0x83, - 0xb7, 0x21, 0x35, 0x6b, 0xc6, 0xe0, 0x0b, 0x6d, 0xa6, 0x95, 0xc3, 0x15, 0xf7, 0x6a, 0x6c, 0x43, 0x1b, 0x94, 0xa6, - 0x1b, 0x80, 0x90, 0x54, 0xd0, 0x20, 0xac, 0xb3, 0xdf, 0xfe, 0x72, 0xd1, 0x7e, 0x84, 0x22, 0x9f, 0xfe, 0x00, 0xac, - 0x57, 0x8e, 0xaa, 0xc0, 0x91, 0x18, 0x64, 0xc6, 0x2e, 0x05, 0xbd, 0xc1, 0x0c, 0x0f, 0xf5, 0xf4, 0xb6, 0x60, 0xcd, - 0x67, 0x09, 0xad, 0xd1, 0xaf, 0xc8, 0x70, 0x7d, 0x89, 0x24, 0x41, 0x88, 0xd3, 0x50, 0xf9, 0x7f, 0xe2, 0x89, 0x48, - 0x9a, 0x4e, 0x13, 0x45, 0xe5, 0x94, 0x55, 0xfd, 0x2a, 0xd1, 0xec, 0x05, 0xcd, 0x99, 0xbd, 0x4c, 0x8a, 0x41, 0x67, - 0x41, 0x50, 0x5c, 0xd1, 0xe3, 0x92, 0xab, 0x72, 0x26, 0xc4, 0x43, 0xec, 0x8f, 0xb1, 0x4c, 0x2c, 0xcc, 0x39, 0x46, - 0x7b, 0xe7, 0x47, 0xc8, 0x4a, 0xb2, 0x16, 0x36, 0x64, 0x0f, 0xba, 0xd3, 0x47, 0x4f, 0xa0, 0x41, 0xd7, 0x7f, 0xbc, - 0x82, 0x20, 0x7c, 0xe0, 0xdd, 0xea, 0x66, 0x54, 0xde, 0x35, 0xa3, 0x75, 0xf0, 0xf1, 0x62, 0xe0, 0xe8, 0x22, 0x10, - 0x1c, 0x4a, 0xec, 0x57, 0x1f, 0x24, 0x95, 0x9f, 0x4c, 0x9b, 0xb0, 0x3e, 0x1c, 0x07, 0xed, 0xb7, 0x90, 0x9c, 0x21, - 0x87, 0x96, 0x4b, 0x47, 0x25, 0x10, 0x27, 0xf9, 0x73, 0x60, 0xd9, 0xb6, 0x57, 0x92, 0xd1, 0xe3, 0x4c, 0xba, 0x65, - 0xf3, 0xd9, 0x23, 0x11, 0x56, 0x12, 0xb1, 0x51, 0xc1, 0x51, 0xae, 0xca, 0xc4, 0xfc, 0xa2, 0x3d, 0x2c, 0x6d, 0xc4, - 0xa1, 0xde, 0x66, 0x36, 0xec, 0x22, 0xd0, 0xdf, 0xca, 0x21, 0x69, 0xc5, 0xab, 0xc0, 0x49, 0x21, 0xdd, 0xf3, 0x84, - 0x85, 0x5b, 0x98, 0xdf, 0x7d, 0xe1, 0x76, 0xd8, 0x77, 0xd1, 0x6f, 0x91, 0xbd, 0xd7, 0x83, 0x6e, 0x04, 0xbb, 0xae, - 0x7a, 0xfd, 0x7d, 0x1d, 0x07, 0xfc, 0xdf, 0x4b, 0x26, 0xa4, 0xc0, 0x22, 0xc8, 0x17, 0xbc, 0x3c, 0x00, 0x03, 0x3f, - 0xb0, 0xef, 0x60, 0x12, 0xb2, 0xff, 0x18, 0x26, 0x08, 0xd9, 0x4e, 0xaa, 0x87, 0x76, 0x2c, 0xb8, 0x32, 0x1d, 0xb6, - 0x98, 0xb7, 0x82, 0x34, 0x48, 0x75, 0xef, 0x58, 0x28, 0x51, 0x22, 0xe3, 0xcc, 0x93, 0x2d, 0x01, 0x68, 0xd5, 0x8a, - 0xf0, 0x32, 0x20, 0xbf, 0x6a, 0x14, 0x14, 0xf4, 0x07, 0x98, 0x4d, 0xc1, 0x27, 0xa0, 0x83, 0x8b, 0x09, 0x13, 0x53, - 0x26, 0x1d, 0xb7, 0xab, 0xa3, 0x01, 0xa2, 0xa1, 0x73, 0x1e, 0x16, 0xb3, 0x7c, 0x9a, 0xea, 0xa5, 0x67, 0xbf, 0x81, - 0x2e, 0xda, 0x6d, 0xb3, 0x4f, 0x67, 0x1b, 0x82, 0x85, 0x0d, 0xa4, 0x59, 0x75, 0x12, 0xe1, 0xf9, 0x43, 0x9f, 0x98, - 0x01, 0x69, 0x8e, 0xb7, 0x4d, 0xc8, 0xca, 0x29, 0x08, 0x99, 0xd6, 0xcb, 0x43, 0xfd, 0xd6, 0x79, 0x2f, 0x90, 0xdf, - 0xce, 0xf8, 0x84, 0x0b, 0x46, 0x6b, 0x85, 0xc7, 0x44, 0xa8, 0x60, 0x84, 0xc4, 0x46, 0x40, 0x02, 0xbc, 0xc1, 0x6c, - 0x80, 0xee, 0x27, 0xa5, 0xba, 0xd3, 0x99, 0x63, 0xdc, 0x10, 0x0e, 0xf6, 0xa9, 0x12, 0xb8, 0xc9, 0xa8, 0xd0, 0x3f, - 0x91, 0xa9, 0x21, 0xd9, 0x6b, 0x50, 0x8c, 0x8f, 0x80, 0x0b, 0x32, 0x0b, 0x4a, 0x75, 0x18, 0x20, 0xf7, 0xb8, 0x1f, - 0x88, 0x0f, 0x7e, 0x88, 0xba, 0x1f, 0x71, 0x47, 0x9e, 0x77, 0xd3, 0x42, 0xd3, 0x1e, 0x71, 0x17, 0x34, 0xd8, 0xe6, - 0xfd, 0xfd, 0x4c, 0xef, 0x4d, 0xe5, 0x68, 0x81, 0xbe, 0x4f, 0x41, 0xa6, 0x52, 0x8f, 0xd7, 0x32, 0x55, 0x7b, 0x58, - 0x41, 0x2a, 0x81, 0xb2, 0x8c, 0xd9, 0x3c, 0xce, 0x56, 0xed, 0xb5, 0xb7, 0x51, 0xc4, 0x2f, 0xd2, 0x68, 0x35, 0x6c, - 0x05, 0x38, 0xdb, 0x3c, 0xd1, 0xb5, 0x9b, 0xec, 0x38, 0x14, 0xd1, 0xd1, 0x13, 0xe6, 0xac, 0x4c, 0x10, 0x9b, 0xd7, - 0x5c, 0xcb, 0xcd, 0x3a, 0x3a, 0x1b, 0xf5, 0x1d, 0x97, 0x3e, 0xc9, 0x4d, 0x49, 0xc1, 0x25, 0x2f, 0xdf, 0x5f, 0x25, - 0xaa, 0xf2, 0xb2, 0xec, 0xfb, 0xb4, 0x3a, 0xf3, 0xcc, 0x98, 0x7d, 0xad, 0x92, 0x97, 0xdf, 0x6a, 0x5a, 0x26, 0xff, - 0x9a, 0x06, 0x5b, 0xc7, 0xbe, 0xad, 0x8a, 0xaa, 0xdf, 0x12, 0x87, 0xcc, 0x5b, 0x29, 0x59, 0x81, 0x13, 0x58, 0x13, - 0x17, 0x99, 0x4f, 0xd1, 0x0b, 0xd3, 0x1d, 0x9c, 0x03, 0x00, 0x65, 0xd0, 0x24, 0xf8, 0xbf, 0xf8, 0x1a, 0x63, 0xcc, - 0x57, 0x8c, 0xc6, 0x1c, 0x37, 0x2c, 0xcf, 0x6f, 0xcd, 0x17, 0x78, 0x0b, 0xc8, 0x42, 0x5b, 0xd8, 0xc1, 0x63, 0x4d, - 0xba, 0x1b, 0xd2, 0x4e, 0x7d, 0xfa, 0xde, 0x77, 0xf8, 0xef, 0x82, 0xc2, 0xa4, 0x52, 0x20, 0xc3, 0xe5, 0xaa, 0x9b, - 0x11, 0x5a, 0xad, 0x9b, 0xff, 0xed, 0xee, 0x66, 0x54, 0x1c, 0x99, 0xf7, 0x20, 0xc3, 0x0d, 0x64, 0xac, 0xc5, 0x30, - 0x6c, 0x9a, 0x49, 0xb6, 0x3c, 0x86, 0xe8, 0xa3, 0xa6, 0xae, 0xf1, 0xba, 0x2b, 0x77, 0x37, 0x87, 0x0e, 0x6d, 0x60, - 0x70, 0xd7, 0xfe, 0x1c, 0x1e, 0x06, 0xf2, 0xa2, 0x28, 0xe2, 0x36, 0x3a, 0x44, 0x84, 0x9b, 0x98, 0xb1, 0x5a, 0xf2, - 0xff, 0x15, 0x33, 0x4d, 0x3e, 0x33, 0x1b, 0x9c, 0xac, 0x9b, 0xba, 0x62, 0x05, 0xfd, 0xb3, 0x51, 0xda, 0xbf, 0xca, - 0x3a, 0x6f, 0x05, 0x7f, 0xb4, 0x4a, 0x8c, 0x7d, 0x26, 0x39, 0xb4, 0xbc, 0xd0, 0xc7, 0x11, 0x2f, 0xfa, 0xf7, 0x01, - 0x09, 0x77, 0xfe, 0xb1, 0x8a, 0xba, 0x3a, 0x79, 0xa9, 0xaf, 0x6f, 0x57, 0xc2, 0x1e, 0x12, 0x3d, 0x23, 0x0a, 0x0d, - 0xd7, 0x5c, 0xe7, 0xe5, 0xd2, 0x07, 0x1b, 0x51, 0x41, 0xe7, 0xcb, 0x24, 0x88, 0xc6, 0x86, 0x4d, 0x35, 0x55, 0x17, - 0x9d, 0x33, 0x89, 0x50, 0x46, 0x3c, 0x36, 0x81, 0x3e, 0x0c, 0x16, 0x4b, 0x8d, 0x55, 0xcb, 0xc7, 0x6f, 0xd5, 0xe8, - 0x4f, 0x72, 0x76, 0x89, 0x46, 0x39, 0x7f, 0xc3, 0xac, 0xcf, 0xfa, 0xf8, 0x90, 0xd1, 0xbd, 0x7f, 0x27, 0xb9, 0xac, - 0xbf, 0xec, 0x2b, 0x4d, 0xb0, 0x39, 0x77, 0xa3, 0x36, 0x8f, 0x5d, 0x38, 0xc6, 0x3e, 0x42, 0x40, 0xd0, 0x37, 0x94, - 0xd3, 0x42, 0x0f, 0x31, 0x1d, 0x2d, 0xf7, 0x20, 0xbf, 0xad, 0x88, 0x92, 0x68, 0xd8, 0x2d, 0x8e, 0x87, 0xf4, 0x66, - 0x5b, 0xdc, 0x65, 0x43, 0x1d, 0x07, 0xdd, 0x4a, 0x58, 0x02, 0x8d, 0x29, 0x0d, 0xdf, 0x43, 0x8f, 0x9d, 0x2d, 0x99, - 0x5e, 0xee, 0x8c, 0x62, 0x4f, 0xf0, 0x73, 0x42, 0x7d, 0x03, 0xee, 0x78, 0xe0, 0x4b, 0x1c, 0x6a, 0x69, 0x76, 0x23, - 0x2f, 0xd4, 0x0a, 0xd5, 0xa9, 0xd5, 0xe0, 0x0b, 0x35, 0x7e, 0x3c, 0x23, 0x09, 0xf6, 0xf4, 0x55, 0x8d, 0x8b, 0x8f, - 0xd7, 0x72, 0xa1, 0x1c, 0x5d, 0x64, 0x0b, 0x34, 0x3b, 0x4f, 0xd3, 0x8e, 0x50, 0x8f, 0x95, 0xd4, 0xd5, 0xa7, 0x13, - 0x40, 0x45, 0x28, 0x6e, 0xe5, 0x50, 0x90, 0x7e, 0x96, 0xb9, 0x7b, 0x9c, 0x63, 0xa1, 0x06, 0xd0, 0x99, 0x96, 0x49, - 0xa7, 0x2e, 0xa4, 0xc5, 0x3f, 0x24, 0x98, 0xd8, 0xfe, 0x81, 0xa2, 0x00, 0x4a, 0x52, 0xe7, 0xd0, 0xc8, 0xef, 0xeb, - 0x4e, 0x63, 0x8c, 0x39, 0x78, 0x06, 0x0e, 0x84, 0xf5, 0x94, 0xbc, 0xf6, 0x0c, 0xda, 0x35, 0x94, 0x34, 0xe8, 0xb6, - 0xed, 0x71, 0x69, 0xdd, 0x6f, 0x87, 0x26, 0x8b, 0x84, 0x16, 0xaa, 0x2b, 0xd4, 0xc6, 0xb2, 0x74, 0xd2, 0x9d, 0x75, - 0x43, 0x8a, 0x4f, 0x14, 0x6e, 0x61, 0x2e, 0x5b, 0x95, 0xaf, 0x9c, 0x1b, 0x2c, 0xe1, 0xd2, 0x28, 0xb1, 0xe4, 0xef, - 0x7b, 0x40, 0x10, 0x85, 0xaa, 0x3c, 0x13, 0x44, 0x48, 0x6a, 0x87, 0x03, 0x26, 0x8a, 0xf9, 0x7c, 0x13, 0x09, 0x1a, - 0x7c, 0xf5, 0xa3, 0x82, 0xa4, 0x50, 0x09, 0x08, 0x80, 0xc1, 0x40, 0x0a, 0x28, 0xbf, 0x78, 0x32, 0xee, 0x16, 0x3a, - 0xe7, 0x44, 0xfc, 0x40, 0x09, 0x32, 0xe4, 0xcf, 0x7f, 0x9a, 0x10, 0x06, 0x6d, 0x00, 0xc9, 0x59, 0x70, 0xc0, 0x0c, - 0x0b, 0xfd, 0x69, 0xa4, 0xab, 0x96, 0xc4, 0x52, 0x8b, 0x3d, 0x8f, 0xdb, 0x90, 0x5e, 0xb0, 0xe2, 0x12, 0x4a, 0xba, - 0x31, 0x7c, 0xec, 0x75, 0x48, 0x79, 0xd9, 0x6b, 0x7c, 0xc0, 0xc4, 0xc2, 0x70, 0x91, 0xab, 0x9c, 0xa6, 0xb0, 0x4d, - 0xc0, 0x63, 0x3e, 0x1c, 0xa4, 0xde, 0x10, 0x3c, 0x64, 0x95, 0x8d, 0x4e, 0x32, 0x03, 0x07, 0x7f, 0x9f, 0x0b, 0x09, - 0x29, 0x8c, 0x63, 0x18, 0xe2, 0x37, 0x89, 0xe5, 0x44, 0x36, 0xf3, 0x36, 0xce, 0xd0, 0xe9, 0x07, 0xec, 0x3a, 0x50, - 0x77, 0x36, 0x95, 0x10, 0xec, 0x25, 0x1d, 0x13, 0x51, 0x4a, 0x75, 0x19, 0x14, 0x9f, 0x11, 0xc5, 0xa5, 0x1f, 0xe1, - 0x4c, 0x87, 0x9f, 0xb8, 0x97, 0x01, 0x91, 0x98, 0x89, 0xc8, 0xd9, 0xe0, 0x48, 0x9e, 0xc9, 0x96, 0xb5, 0x74, 0x51, - 0xd3, 0xfe, 0x47, 0x82, 0xee, 0x88, 0x5c, 0x9c, 0x9f, 0x65, 0xa1, 0xee, 0xb4, 0xb2, 0xce, 0x26, 0x8b, 0xd3, 0x0f, - 0xde, 0x75, 0xb7, 0xaa, 0xa2, 0x84, 0xf7, 0x80, 0x06, 0x99, 0xdc, 0xb9, 0x55, 0xcb, 0xd8, 0xea, 0xf6, 0x9d, 0xab, - 0x83, 0xe6, 0xda, 0x41, 0x45, 0x12, 0xf9, 0xf9, 0x26, 0xcf, 0x12, 0x33, 0x8d, 0x3e, 0x40, 0xc9, 0x5a, 0x72, 0x70, - 0xa9, 0x01, 0x6a, 0x0c, 0xf8, 0x72, 0xcf, 0xa4, 0xf6, 0x51, 0x07, 0xbe, 0x13, 0x13, 0x22, 0x17, 0xb9, 0x57, 0x9a, - 0x46, 0x5e, 0x4e, 0xef, 0x36, 0x2c, 0xf2, 0x23, 0xbf, 0xfa, 0x39, 0xb3, 0x3c, 0xa5, 0x67, 0x95, 0x30, 0x8b, 0x15, - 0x1e, 0xd1, 0xcd, 0x30, 0x8f, 0xe0, 0xa3, 0xae, 0xfa, 0x73, 0x03, 0x68, 0xf5, 0xe0, 0x4d, 0x47, 0xa3, 0x08, 0xe0, - 0xb9, 0xe9, 0x2a, 0x71, 0x39, 0x3f, 0xe1, 0x06, 0x86, 0x3d, 0x4c, 0x30, 0x10, 0x12, 0x65, 0x26, 0x0c, 0x00, 0x76, - 0x0e, 0xf1, 0x5b, 0xcc, 0xef, 0x75, 0xc3, 0xa6, 0x5a, 0xe0, 0x9c, 0x29, 0x0b, 0xb8, 0x5e, 0x46, 0x9a, 0x0b, 0xa8, - 0x0b, 0xb2, 0x9f, 0xb4, 0x11, 0x63, 0xfb, 0x4c, 0x09, 0x27, 0x8c, 0x9b, 0x01, 0x8d, 0x0d, 0x9a, 0x95, 0x4f, 0xcc, - 0x4d, 0x02, 0x9f, 0x2a, 0x11, 0xb9, 0xb4, 0x47, 0x22, 0xf9, 0x0c, 0x25, 0x70, 0x84, 0x5f, 0xa4, 0xff, 0x03, 0x44, - 0x7a, 0x3b, 0x27, 0x68, 0x6f, 0x43, 0xc6, 0xfb, 0x52, 0x4b, 0x9c, 0xb4, 0x8c, 0xed, 0x1e, 0x8a, 0xc3, 0xeb, 0x60, - 0x44, 0xd7, 0x58, 0xae, 0x6b, 0x34, 0x7e, 0x49, 0xa9, 0x2e, 0xb6, 0xfb, 0x44, 0x0a, 0x0c, 0x00, 0xbd, 0x37, 0x82, - 0xc6, 0x5b, 0xff, 0xd7, 0x05, 0x0e, 0xb3, 0xba, 0x24, 0x94, 0xf6, 0x40, 0x7c, 0x93, 0x7f, 0x63, 0x1a, 0x0e, 0x0a, - 0xdc, 0xd4, 0x4a, 0xbc, 0xd7, 0x76, 0x77, 0xe9, 0x50, 0xf0, 0xf3, 0x75, 0x18, 0x32, 0x7f, 0xc1, 0x11, 0x36, 0x90, - 0xd3, 0x76, 0xfa, 0x55, 0x35, 0xd2, 0xce, 0x20, 0xc3, 0x15, 0x79, 0x41, 0x2a, 0x89, 0xfc, 0xa8, 0x27, 0xab, 0x4b, - 0x2c, 0xec, 0x14, 0x07, 0x80, 0xee, 0x38, 0x86, 0x4d, 0x1b, 0x1b, 0xcd, 0x13, 0xcf, 0xc1, 0x99, 0xeb, 0x14, 0x00, - 0x78, 0xdf, 0x89, 0xc1, 0x84, 0x39, 0xe6, 0x28, 0x5b, 0x81, 0x7a, 0x3c, 0xc9, 0x1c, 0x1c, 0xe7, 0xa3, 0xfa, 0xf8, - 0x84, 0x6d, 0x56, 0x5c, 0x5e, 0x00, 0xc4, 0xe1, 0x38, 0x29, 0x0c, 0x86, 0x44, 0xbd, 0x4f, 0x45, 0xd6, 0xd1, 0x74, - 0xd1, 0x3c, 0xb9, 0x69, 0xec, 0xde, 0x07, 0xa7, 0x86, 0x04, 0xa8, 0x0a, 0xa6, 0x61, 0xfd, 0x9f, 0x81, 0xe0, 0x25, - 0x7b, 0x57, 0xa0, 0xd9, 0x86, 0x83, 0x52, 0xf8, 0xc8, 0x21, 0xed, 0x90, 0x14, 0xea, 0x70, 0x2e, 0xa2, 0x79, 0x16, - 0x82, 0xa7, 0x0d, 0x64, 0x44, 0x5e, 0x4c, 0xde, 0x6b, 0x57, 0xb6, 0xeb, 0x72, 0x8f, 0xd2, 0x2d, 0xce, 0x1a, 0xab, - 0xd9, 0xa4, 0x47, 0xf4, 0xa0, 0x49, 0x15, 0x40, 0x36, 0x81, 0x0a, 0xaa, 0x90, 0x06, 0x1b, 0x3f, 0x07, 0x40, 0xbd, - 0xdc, 0xf0, 0xb6, 0xc6, 0xbd, 0x2c, 0x13, 0xba, 0xad, 0xd1, 0x50, 0x93, 0x30, 0xb8, 0x0f, 0x0c, 0x3a, 0x83, 0x38, - 0x51, 0x3b, 0xcf, 0x78, 0xe8, 0x24, 0x73, 0x21, 0xf4, 0xf8, 0x0b, 0xfc, 0x22, 0xf1, 0xc2, 0xaa, 0xcc, 0xad, 0xe0, - 0x59, 0x4a, 0xe9, 0x3d, 0x06, 0x6b, 0xf5, 0x6f, 0xf7, 0xb3, 0xa3, 0xd2, 0x40, 0x03, 0x9e, 0x23, 0xc9, 0xdd, 0xbc, - 0x3d, 0xd3, 0xa3, 0x3b, 0xfe, 0xf2, 0xea, 0x1b, 0x4f, 0x97, 0xd9, 0x68, 0x74, 0x54, 0x94, 0xf8, 0xc8, 0xe9, 0xc1, - 0x76, 0x66, 0x2d, 0x71, 0xfd, 0x06, 0x24, 0x80, 0x5d, 0x6d, 0x3c, 0x6d, 0xc3, 0xcb, 0x3a, 0xed, 0x49, 0x13, 0xe4, - 0xca, 0xfe, 0xa3, 0xb6, 0xa7, 0x8f, 0x78, 0xf4, 0xc4, 0x94, 0x23, 0x4a, 0x46, 0x11, 0xa8, 0x7e, 0xa0, 0x00, 0xf2, - 0x12, 0x9a, 0x92, 0x2e, 0x08, 0x7c, 0x65, 0x50, 0xb4, 0x1c, 0x30, 0x06, 0x28, 0x47, 0x7d, 0xa7, 0x39, 0x7d, 0xd3, - 0xb3, 0x5c, 0x09, 0x78, 0x6f, 0x51, 0x55, 0x9e, 0x5b, 0xd9, 0x86, 0x4b, 0x79, 0xed, 0xe2, 0xd0, 0x1a, 0xeb, 0x69, - 0xb5, 0xb6, 0xeb, 0x54, 0x3a, 0x7c, 0x8a, 0x63, 0xe4, 0xba, 0xc6, 0x33, 0x08, 0x68, 0x1e, 0x68, 0x92, 0x77, 0xda, - 0xae, 0xa3, 0x59, 0x0d, 0x87, 0x11, 0x7d, 0x5e, 0x51, 0xac, 0x82, 0x1b, 0x64, 0xbe, 0x55, 0xda, 0xa7, 0x35, 0x18, - 0xd6, 0x29, 0x29, 0x7d, 0x56, 0xbf, 0xd2, 0x13, 0x3f, 0xe5, 0x4d, 0xdf, 0x37, 0x25, 0xe1, 0xdb, 0xe4, 0x4b, 0xea, - 0xd4, 0xa5, 0xe9, 0x71, 0x7a, 0xe4, 0x50, 0x8e, 0x1d, 0xdc, 0xbd, 0xf2, 0x2b, 0xf4, 0x3a, 0x33, 0x50, 0x3f, 0x73, - 0x73, 0xda, 0x5d, 0x2b, 0x6a, 0xca, 0x92, 0xea, 0xe9, 0xeb, 0x5c, 0xbd, 0x0b, 0x6f, 0x6b, 0x22, 0x12, 0xdc, 0x9f, - 0xf1, 0x58, 0x91, 0xb9, 0x16, 0x46, 0x7e, 0x58, 0x45, 0x0d, 0x76, 0xad, 0xd4, 0x88, 0x3b, 0xb3, 0x84, 0x9e, 0x14, - 0xbb, 0xf9, 0x2a, 0x89, 0x60, 0x54, 0x19, 0x99, 0x3c, 0x9d, 0xe5, 0x84, 0xa0, 0x5f, 0x31, 0x88, 0x97, 0x75, 0x8d, - 0x17, 0xd7, 0x6a, 0xca, 0x3c, 0x75, 0xeb, 0x11, 0xd7, 0x9f, 0x6f, 0x43, 0xed, 0x7b, 0x02, 0xae, 0xb4, 0xa9, 0x63, - 0x1e, 0x8d, 0xe1, 0x4b, 0x46, 0x72, 0x5e, 0xd0, 0xd4, 0x04, 0xec, 0x17, 0x10, 0x41, 0x94, 0x7f, 0x34, 0xdb, 0x93, - 0x9c, 0x92, 0xed, 0x2f, 0x7c, 0x73, 0xdf, 0x2a, 0x3e, 0x68, 0x3d, 0xfd, 0xa3, 0x48, 0xd1, 0xf4, 0x92, 0x50, 0x54, - 0x54, 0x06, 0xcd, 0x5b, 0x4a, 0x7d, 0xce, 0xf3, 0x2f, 0x75, 0xc9, 0x92, 0x51, 0x98, 0x25, 0x99, 0x25, 0x7d, 0x00, - 0x34, 0xf5, 0x35, 0xe4, 0x8c, 0xa2, 0xf1, 0x33, 0x4a, 0xfe, 0x35, 0xfc, 0x38, 0xed, 0xee, 0xd1, 0x77, 0xef, 0x4a, - 0x1b, 0x92, 0x40, 0x95, 0xde, 0xd2, 0x1f, 0xd3, 0x52, 0x5f, 0x14, 0x8d, 0x2b, 0x45, 0x3b, 0xc3, 0xfc, 0xb4, 0x78, - 0xb6, 0xe0, 0x17, 0xcf, 0x16, 0xbc, 0xf6, 0x82, 0xb9, 0x89, 0x75, 0xab, 0x82, 0x97, 0xc7, 0xb8, 0xc6, 0x50, 0x62, - 0xa7, 0x76, 0xfc, 0x47, 0x47, 0x60, 0x4a, 0xff, 0xa9, 0x51, 0x06, 0xfa, 0x53, 0x06, 0x4e, 0x33, 0x37, 0xcc, 0x28, - 0xba, 0xf1, 0xc2, 0x08, 0x33, 0xe7, 0x49, 0x13, 0x7c, 0x4d, 0x63, 0x0d, 0x76, 0xb5, 0x9c, 0x65, 0x08, 0x45, 0x8c, - 0x1f, 0x15, 0xb6, 0xa0, 0xed, 0x4c, 0xf8, 0x09, 0x44, 0x2b, 0x40, 0xef, 0x39, 0x37, 0xc7, 0xd1, 0xce, 0x52, 0xdf, - 0x3a, 0xa7, 0x98, 0x3e, 0x9c, 0x88, 0xec, 0x81, 0xa6, 0xee, 0x39, 0x9d, 0xf8, 0x25, 0x91, 0xb1, 0xa8, 0xdf, 0x9f, - 0x43, 0xdb, 0x22, 0xdd, 0xab, 0x11, 0x38, 0x05, 0x20, 0x6f, 0x48, 0x18, 0xfe, 0x45, 0x43, 0x79, 0x8d, 0x3c, 0x52, - 0xa9, 0x4c, 0x9f, 0x77, 0x5a, 0xd3, 0x89, 0x2c, 0x2d, 0xb4, 0x93, 0x31, 0xb6, 0xac, 0x4a, 0x14, 0x5b, 0x99, 0xf7, - 0x0c, 0x12, 0xc9, 0xe7, 0x2f, 0x32, 0x5a, 0xac, 0xa9, 0x21, 0x40, 0xb3, 0x0a, 0xb5, 0x75, 0xe1, 0xe9, 0x15, 0x2a, - 0x06, 0x86, 0x82, 0xb2, 0xef, 0x87, 0xd8, 0x1a, 0x3e, 0xb0, 0x9f, 0xf5, 0x1e, 0x12, 0xaf, 0xbd, 0xc0, 0x44, 0x10, - 0xae, 0x37, 0x05, 0x71, 0x6b, 0x97, 0x64, 0x04, 0x37, 0x54, 0x2f, 0xd8, 0x98, 0x63, 0x67, 0xa7, 0x70, 0x76, 0xec, - 0xec, 0x24, 0x67, 0x16, 0x5d, 0xc9, 0x4c, 0xbd, 0x22, 0xb1, 0x64, 0x85, 0x1d, 0xbc, 0xfc, 0x3a, 0xaf, 0xe4, 0x10, - 0x0b, 0x40, 0x95, 0x96, 0x5c, 0x95, 0x16, 0xc4, 0xcc, 0x35, 0x90, 0x06, 0x75, 0x20, 0xf0, 0x12, 0xbf, 0x99, 0x7c, - 0x00, 0x8c, 0x1d, 0x9c, 0xa3, 0xa3, 0x72, 0xda, 0x18, 0xf6, 0xbb, 0x2a, 0x13, 0x28, 0xaa, 0xe6, 0x83, 0x29, 0xc9, - 0x1b, 0x3c, 0x33, 0x2d, 0xd9, 0x43, 0x21, 0x7c, 0xc1, 0xbb, 0x33, 0x63, 0x8a, 0xf9, 0xed, 0x1b, 0x15, 0xfd, 0xbc, - 0xa2, 0x51, 0xa8, 0x39, 0x54, 0x5f, 0x68, 0x9e, 0xe8, 0x01, 0x99, 0xa6, 0x38, 0xb9, 0xf8, 0x50, 0x0a, 0xf9, 0xf8, - 0x77, 0xf6, 0x05, 0xf1, 0xf6, 0x76, 0xb1, 0xad, 0xc0, 0x09, 0xab, 0xd8, 0x09, 0x6d, 0xae, 0xf9, 0x67, 0xea, 0x20, - 0x6b, 0x66, 0x35, 0xde, 0x19, 0x9f, 0x5f, 0xd5, 0xd8, 0x24, 0x9d, 0x21, 0xa8, 0xe0, 0x69, 0x67, 0x08, 0xda, 0xf2, - 0x93, 0xa4, 0x80, 0x08, 0x34, 0x0e, 0xd4, 0x65, 0x33, 0x91, 0x03, 0x73, 0x01, 0x95, 0x2c, 0x67, 0xb8, 0xe6, 0xb5, - 0x3f, 0x74, 0x2d, 0x32, 0x4f, 0xa0, 0x45, 0xf3, 0x68, 0xa7, 0xa7, 0xea, 0xc8, 0xd7, 0xde, 0xa5, 0xd6, 0x4d, 0x2d, - 0x96, 0x25, 0x5c, 0xcf, 0xc8, 0x4d, 0xac, 0xcb, 0xdb, 0x00, 0xcd, 0xe4, 0xd3, 0x28, 0xfc, 0x89, 0xa9, 0x29, 0x35, - 0x91, 0x31, 0x64, 0x5b, 0x48, 0x55, 0xdb, 0x28, 0xd1, 0x36, 0xa4, 0xdd, 0xce, 0x4f, 0x5b, 0x48, 0xf1, 0x53, 0x5b, - 0x16, 0xd2, 0xfe, 0xf5, 0x0a, 0x4a, 0x49, 0xf8, 0x20, 0x5c, 0x4c, 0x00, 0x84, 0xfb, 0xd0, 0x29, 0x0b, 0x70, 0xe1, - 0x8e, 0xa3, 0xb0, 0xd7, 0x3b, 0x6b, 0xae, 0xa6, 0xc5, 0xe6, 0x07, 0xdd, 0xe7, 0x61, 0x50, 0x8e, 0xf3, 0x9a, 0x3c, - 0x15, 0xdc, 0xf8, 0x23, 0x0b, 0x85, 0x82, 0xf1, 0x6e, 0x22, 0x66, 0xa5, 0xe8, 0xb5, 0x25, 0xc5, 0xda, 0xa9, 0x80, - 0x1a, 0x84, 0xdd, 0x40, 0x55, 0x33, 0xa6, 0x34, 0x95, 0x96, 0x60, 0xf9, 0xbc, 0xd3, 0xf4, 0x9f, 0xd3, 0xf6, 0x47, - 0x42, 0x48, 0xad, 0x6c, 0x43, 0xe1, 0x01, 0x94, 0xe8, 0xb4, 0xcf, 0xfd, 0x45, 0xf0, 0xea, 0xab, 0x4f, 0xd7, 0xd1, - 0x48, 0x8e, 0x12, 0xb3, 0xa8, 0xbb, 0x76, 0x73, 0x7a, 0xfd, 0x9f, 0x91, 0xbc, 0x14, 0xcd, 0x36, 0x4c, 0x03, 0xc5, - 0xcd, 0x5c, 0xf3, 0x5c, 0xd0, 0x45, 0xce, 0x71, 0x41, 0xc5, 0x0b, 0xc7, 0xb5, 0xac, 0xa9, 0xc6, 0x57, 0xba, 0x8a, - 0x41, 0xa5, 0x8c, 0x87, 0x0d, 0x9e, 0x13, 0x8d, 0x30, 0x5c, 0xaf, 0x1c, 0x36, 0x15, 0x4a, 0x5f, 0x09, 0x1c, 0x36, - 0xb5, 0x11, 0x22, 0x59, 0xc3, 0x51, 0xc3, 0x9d, 0x61, 0x49, 0x2b, 0x7d, 0xe5, 0x36, 0x88, 0x76, 0xeb, 0xd3, 0x1c, - 0x3c, 0x0a, 0x3e, 0xb3, 0xc3, 0x23, 0x3c, 0xa9, 0x49, 0x4e, 0x11, 0x3c, 0xc8, 0x93, 0x87, 0xfa, 0x40, 0x77, 0x7e, - 0x29, 0xd1, 0x5e, 0xc1, 0x22, 0xe3, 0x31, 0xcd, 0xf3, 0x10, 0x3a, 0xa6, 0x5b, 0x09, 0x6d, 0xd7, 0x0b, 0xf6, 0xc2, - 0xb8, 0x7a, 0x48, 0x11, 0x4d, 0x09, 0xf4, 0x3f, 0x8d, 0x31, 0x3b, 0xab, 0x97, 0x0f, 0xef, 0x33, 0x66, 0x60, 0x3b, - 0xae, 0xdd, 0x40, 0x81, 0xec, 0xfb, 0xbf, 0x8e, 0xc2, 0x9b, 0x58, 0xf8, 0x69, 0x9f, 0xd4, 0x6f, 0x9d, 0x75, 0x8e, - 0xfd, 0x0b, 0xbb, 0x4d, 0x96, 0x5e, 0x39, 0x8a, 0x6b, 0x14, 0x60, 0x72, 0x2c, 0x3d, 0xaa, 0xef, 0x45, 0xc1, 0x9e, - 0xf0, 0x40, 0x9c, 0xac, 0x62, 0xff, 0x90, 0x5e, 0x1b, 0x00, 0x4c, 0x61, 0x72, 0x9f, 0x56, 0xf6, 0xab, 0x1f, 0x6e, - 0x6c, 0xb0, 0xe5, 0x4a, 0x85, 0x7d, 0x0d, 0x87, 0xeb, 0x55, 0x42, 0xb0, 0xdb, 0xaa, 0xeb, 0x81, 0x90, 0x9b, 0x8c, - 0x37, 0xc5, 0xe0, 0xad, 0x05, 0x5e, 0xb0, 0x5d, 0xc7, 0xc2, 0x9b, 0xd8, 0x6c, 0x7d, 0xa1, 0xf6, 0x82, 0x8f, 0xf2, - 0xa8, 0x3f, 0xcb, 0x83, 0xfe, 0x3c, 0xd6, 0x01, 0xfc, 0xe1, 0x39, 0x61, 0x95, 0x7f, 0x92, 0x18, 0x1c, 0x61, 0x61, - 0xcd, 0x6c, 0x34, 0x34, 0x17, 0xc6, 0x8d, 0x19, 0x3d, 0xf5, 0xc9, 0xc5, 0xa1, 0xb8, 0xd9, 0x5a, 0x02, 0x97, 0xe8, - 0xd4, 0x2c, 0xfd, 0xf7, 0x06, 0x4f, 0x42, 0xa4, 0xbc, 0x55, 0xfa, 0x03, 0xb4, 0x8b, 0xd5, 0x97, 0xff, 0xd3, 0x4a, - 0x38, 0x60, 0x9c, 0x46, 0xe9, 0x22, 0x7e, 0xbf, 0x82, 0x1b, 0xf9, 0x27, 0x5b, 0x58, 0xbd, 0x13, 0x7f, 0xd4, 0xa6, - 0xf6, 0xf4, 0x69, 0x58, 0xe8, 0x0b, 0x63, 0x94, 0xb0, 0x18, 0xc6, 0x4b, 0x63, 0x77, 0x07, 0x33, 0x36, 0x6c, 0x9f, - 0x6f, 0x24, 0x7c, 0xe8, 0x9f, 0x17, 0x82, 0x3a, 0xce, 0xa9, 0xd9, 0xd2, 0x8a, 0x46, 0xbf, 0x5d, 0xc2, 0xd6, 0x40, - 0x02, 0xcc, 0x33, 0xbf, 0x84, 0xc0, 0xc9, 0x24, 0x6a, 0x12, 0x12, 0x58, 0xed, 0x4c, 0xff, 0x6a, 0x55, 0xf1, 0xfb, - 0x7c, 0xe8, 0x10, 0xde, 0xd6, 0xae, 0xe2, 0xfb, 0x42, 0xb8, 0x99, 0xd4, 0xcd, 0x06, 0xe9, 0xc7, 0xb2, 0x4d, 0x63, - 0xe7, 0x00, 0xbe, 0x52, 0x3d, 0x14, 0x90, 0x13, 0xd4, 0x3b, 0x9d, 0xd7, 0x1d, 0xea, 0x88, 0x83, 0x74, 0x31, 0xdb, - 0xa0, 0xa9, 0x37, 0x2b, 0xdf, 0x76, 0xdc, 0x68, 0x46, 0x43, 0xe3, 0xdc, 0x20, 0x85, 0x83, 0x6f, 0x04, 0xe8, 0x6c, - 0xba, 0xc7, 0x0d, 0xd2, 0x49, 0x33, 0x34, 0xfd, 0xd6, 0x11, 0xa5, 0x9a, 0x84, 0xd9, 0x64, 0x0b, 0x8b, 0xa3, 0xb4, - 0xa3, 0xd6, 0x5d, 0xe1, 0xf6, 0xcd, 0x85, 0x83, 0x96, 0x53, 0xb4, 0x49, 0x24, 0x8a, 0xc4, 0x51, 0xcb, 0x29, 0x7d, - 0x74, 0x8a, 0x62, 0x84, 0x8e, 0xb3, 0x8b, 0xcd, 0xab, 0x98, 0x69, 0xb8, 0x12, 0x15, 0x73, 0x7f, 0x81, 0xef, 0xc6, - 0xba, 0x7b, 0x8a, 0x49, 0xa9, 0x74, 0x49, 0x75, 0x17, 0xb3, 0x05, 0xbe, 0x8e, 0xf9, 0x0b, 0xab, 0x57, 0x17, 0xaf, - 0x17, 0x56, 0x93, 0xe9, 0x16, 0xfc, 0xb4, 0x69, 0xfd, 0x16, 0x92, 0x96, 0x03, 0x42, 0x15, 0xff, 0x4c, 0xa6, 0x78, - 0xd5, 0x58, 0x43, 0x4a, 0x36, 0x47, 0x9a, 0x7e, 0xaf, 0xd0, 0xe4, 0x23, 0x8d, 0xce, 0xd2, 0xd5, 0xa9, 0x58, 0xa5, - 0x9f, 0xaa, 0x14, 0xf1, 0xad, 0xda, 0x84, 0x51, 0x41, 0x2b, 0x73, 0x47, 0x75, 0x6f, 0xdf, 0xae, 0x23, 0x44, 0x9f, - 0x97, 0x84, 0x72, 0xec, 0x72, 0xa9, 0x03, 0x1d, 0x20, 0xbe, 0xed, 0x14, 0x30, 0x2f, 0xc7, 0xa8, 0xdd, 0xbc, 0x1b, - 0x0b, 0x09, 0xf9, 0x87, 0xa4, 0x8e, 0x93, 0xd1, 0xa5, 0xf8, 0xb9, 0xee, 0xf9, 0x59, 0xde, 0x89, 0x60, 0x3e, 0xfa, - 0x36, 0x62, 0x50, 0x96, 0x60, 0xf3, 0x5f, 0xe7, 0x81, 0x02, 0x93, 0x40, 0x93, 0x6b, 0x23, 0x4e, 0x35, 0xa9, 0xfa, - 0x5a, 0x82, 0xc2, 0x34, 0xbd, 0xaa, 0x15, 0xb9, 0xa9, 0x96, 0x11, 0x0b, 0xf6, 0x80, 0x3a, 0x53, 0x74, 0x0b, 0xc0, - 0x22, 0x8c, 0xcf, 0xc4, 0xd9, 0xf2, 0x45, 0xa6, 0xd4, 0x58, 0x0e, 0x15, 0x3b, 0xf6, 0xeb, 0xd9, 0xfd, 0xf5, 0x1f, - 0xcd, 0xdf, 0xfe, 0xfa, 0xda, 0xab, 0x47, 0x59, 0x3a, 0x84, 0xfb, 0x9d, 0x75, 0x0c, 0x83, 0x02, 0x44, 0x65, 0xfb, - 0x6d, 0x89, 0xbf, 0xe6, 0x55, 0x94, 0x74, 0xd6, 0xc6, 0xbd, 0x49, 0xc2, 0xa7, 0x35, 0x23, 0xdf, 0x06, 0x16, 0x7c, - 0x6b, 0x98, 0x5d, 0xea, 0xe0, 0x39, 0xd5, 0xa3, 0x9d, 0x02, 0x8e, 0x83, 0xc1, 0xbf, 0x91, 0xda, 0x26, 0x0c, 0x30, - 0xe4, 0x24, 0x9a, 0x2f, 0x74, 0x65, 0x79, 0x9e, 0xa5, 0x64, 0x47, 0x4c, 0xdf, 0x73, 0xc1, 0x8f, 0xbc, 0x2e, 0xf1, - 0x16, 0x6e, 0x08, 0xb0, 0x09, 0xca, 0x1a, 0x03, 0xc7, 0x29, 0x6e, 0xe4, 0xdb, 0x0a, 0xef, 0x21, 0xb0, 0x33, 0x85, - 0x5b, 0x3c, 0xbf, 0xdb, 0x8b, 0x23, 0x04, 0xa7, 0xe0, 0x93, 0x95, 0xd9, 0xac, 0xe8, 0xa5, 0x7f, 0x99, 0x95, 0xf4, - 0xc8, 0x28, 0x77, 0x9b, 0x3c, 0x6d, 0xd9, 0x9a, 0x02, 0x30, 0x83, 0x67, 0x0c, 0x58, 0x70, 0xa7, 0x98, 0xc6, 0x9f, - 0xde, 0xf7, 0x11, 0x6b, 0x75, 0xcb, 0x97, 0xd3, 0x3a, 0x76, 0xef, 0x53, 0x92, 0x40, 0x8d, 0xb3, 0xeb, 0xc7, 0xcb, - 0xb8, 0x6e, 0xdd, 0x67, 0x56, 0xb7, 0x1e, 0x4b, 0xf1, 0xdf, 0x57, 0xab, 0xf3, 0x25, 0x7a, 0x95, 0xf0, 0x26, 0x15, - 0xf5, 0xa4, 0x92, 0x73, 0x8b, 0xbc, 0xbc, 0x72, 0x2e, 0x06, 0xe4, 0xd9, 0x51, 0xbb, 0x51, 0x85, 0x16, 0x5b, 0x63, - 0xb1, 0x3e, 0xcd, 0x24, 0x43, 0x7d, 0xaf, 0xe1, 0x5e, 0x9f, 0x5e, 0xae, 0xc2, 0xf2, 0x34, 0xaa, 0x5d, 0x5a, 0x5f, - 0x6e, 0x94, 0xe4, 0xba, 0xf8, 0x81, 0xb5, 0xb5, 0xf0, 0xe6, 0x60, 0xa3, 0x65, 0x4c, 0xb4, 0x92, 0xd5, 0xd3, 0x4a, - 0x56, 0x4e, 0x13, 0x97, 0x7b, 0xbd, 0xe8, 0x02, 0x39, 0xfe, 0x60, 0xd0, 0xaa, 0xe5, 0x83, 0xc6, 0xac, 0xb6, 0x0f, - 0x3a, 0xa5, 0x5a, 0x9f, 0x14, 0x16, 0xf1, 0xc8, 0x1a, 0x70, 0xb0, 0xb1, 0x56, 0x4a, 0xa6, 0x95, 0x6d, 0x32, 0xae, - 0xd0, 0x0f, 0xa9, 0x6a, 0xd5, 0xfb, 0x1f, 0xa6, 0xb8, 0xc1, 0xd5, 0xc6, 0x9f, 0x05, 0xb9, 0xfe, 0x53, 0x61, 0x47, - 0x39, 0xe8, 0x28, 0xb4, 0xfe, 0xe6, 0x7f, 0xa8, 0xf9, 0x11, 0xdc, 0x0c, 0xb1, 0x95, 0xd9, 0x5b, 0x10, 0xb5, 0x2b, - 0x09, 0xe4, 0x7b, 0xc0, 0xb5, 0x02, 0xa4, 0x62, 0xaf, 0x57, 0xa2, 0x75, 0x9a, 0x04, 0x63, 0x43, 0x90, 0x39, 0x8b, - 0xd8, 0x05, 0xa9, 0x1d, 0xdd, 0x66, 0x46, 0x75, 0xf3, 0x13, 0xaf, 0xf1, 0xa7, 0x4a, 0xa8, 0xbe, 0x7c, 0xa3, 0xb0, - 0x78, 0xc2, 0x03, 0x6a, 0x9f, 0x82, 0x46, 0x75, 0xad, 0x29, 0xa6, 0xb4, 0x20, 0x32, 0x91, 0x31, 0xf8, 0x20, 0x43, - 0x83, 0xb8, 0x5d, 0xb6, 0x5e, 0x90, 0xee, 0xc9, 0xbb, 0xdd, 0xaf, 0x92, 0x5e, 0xda, 0x27, 0x90, 0xfa, 0x16, 0x4d, - 0x60, 0xb6, 0x52, 0xd0, 0x6e, 0x61, 0xbd, 0xbd, 0x60, 0xee, 0x85, 0xb8, 0x72, 0xe1, 0xc0, 0x9a, 0x30, 0xd6, 0xbb, - 0x9a, 0xe7, 0x86, 0xf5, 0xaf, 0x7f, 0xb6, 0x57, 0x8d, 0x5c, 0x54, 0xa6, 0x75, 0x5e, 0x06, 0xc8, 0x4e, 0x5c, 0xe6, - 0xf6, 0x59, 0xca, 0x7b, 0x16, 0x11, 0x34, 0xe4, 0x99, 0x5b, 0xf1, 0x25, 0x6c, 0xfa, 0x1a, 0x36, 0xdf, 0xb5, 0x4f, - 0x6d, 0xb5, 0x62, 0x92, 0x54, 0xa3, 0x3c, 0x71, 0xdd, 0x05, 0x06, 0xed, 0x0f, 0x2e, 0xcd, 0x4e, 0xe7, 0xee, 0x67, - 0xda, 0x03, 0x8e, 0x59, 0x8b, 0xde, 0x36, 0xe0, 0xc8, 0x87, 0xf4, 0x90, 0xba, 0x3b, 0xb9, 0xcd, 0x2d, 0x80, 0xdb, - 0x42, 0x5f, 0x5a, 0x5a, 0xe6, 0x9b, 0x58, 0x6e, 0xae, 0xce, 0x8b, 0x34, 0xbd, 0x50, 0xd6, 0x6d, 0x2f, 0xc1, 0xd1, - 0x26, 0xcf, 0x65, 0x83, 0x6b, 0x54, 0x0a, 0x97, 0x81, 0xff, 0x17, 0x25, 0x45, 0xbf, 0x16, 0x03, 0xc1, 0xd8, 0x31, - 0xe9, 0x2b, 0xbd, 0x3a, 0xe2, 0x4a, 0x89, 0x0e, 0xfc, 0x11, 0x54, 0x27, 0x7b, 0x03, 0x4d, 0xea, 0xcc, 0xde, 0x25, - 0x25, 0x42, 0xbb, 0xa7, 0x69, 0x73, 0x29, 0xa1, 0xfe, 0x7a, 0xc1, 0x87, 0xb7, 0xfd, 0xe2, 0xf6, 0x6c, 0xef, 0x2b, - 0xf7, 0x9e, 0x77, 0x2b, 0x55, 0xb3, 0x3f, 0xcb, 0x89, 0x3d, 0x3b, 0xf6, 0xd3, 0x34, 0x1f, 0xf4, 0xf4, 0x93, 0xfb, - 0x0f, 0x2f, 0xcc, 0x79, 0xc2, 0x0e, 0xb4, 0x76, 0x7b, 0x5c, 0xf3, 0x55, 0x28, 0x15, 0x9c, 0x08, 0x1b, 0x5f, 0x16, - 0xbd, 0x35, 0xe4, 0x82, 0x93, 0x72, 0x12, 0xc5, 0xd4, 0x5e, 0x34, 0xc7, 0x5b, 0x70, 0x93, 0x9f, 0x76, 0x17, 0x81, - 0x14, 0x5a, 0xe5, 0xb9, 0xfa, 0x5f, 0xec, 0x18, 0x8b, 0x97, 0xb9, 0xeb, 0x30, 0xb7, 0x13, 0xaa, 0x88, 0x3f, 0xb7, - 0x44, 0x93, 0xff, 0x70, 0xfc, 0xaf, 0xa3, 0x3f, 0xb5, 0x24, 0x1f, 0x79, 0x3b, 0xa1, 0xe3, 0x89, 0xab, 0x64, 0xf7, - 0x1a, 0x65, 0x76, 0x16, 0x53, 0x4f, 0x55, 0xe7, 0x33, 0x49, 0x66, 0x5d, 0xe5, 0x13, 0xc2, 0xe1, 0xd1, 0xfc, 0x10, - 0xee, 0x96, 0xc5, 0x9a, 0xac, 0xcc, 0x15, 0x65, 0x57, 0x68, 0x9f, 0x53, 0x0f, 0xc4, 0xd6, 0x64, 0x7e, 0xa0, 0x73, - 0x2f, 0x92, 0x91, 0x49, 0xa5, 0x2c, 0x6b, 0x87, 0x48, 0xc3, 0xcb, 0x5d, 0x9e, 0xf2, 0x3e, 0x3f, 0x54, 0x54, 0xb6, - 0x43, 0xe6, 0xb9, 0xfb, 0x3a, 0x33, 0x40, 0xa3, 0x98, 0xa3, 0x2b, 0xe0, 0x96, 0x80, 0x79, 0x6a, 0x34, 0x7b, 0xd6, - 0x5c, 0x95, 0x4c, 0xda, 0xcb, 0x35, 0xf4, 0xb9, 0x67, 0x9a, 0xc9, 0x36, 0x76, 0x11, 0x32, 0x2d, 0x57, 0x65, 0x6b, - 0xe9, 0x33, 0x5f, 0x73, 0xe7, 0x99, 0x07, 0xfc, 0xf4, 0x55, 0x72, 0x89, 0xfa, 0x7a, 0xda, 0x9a, 0xb4, 0x3c, 0x5b, - 0x50, 0xa8, 0x71, 0x8a, 0xc2, 0x1b, 0x28, 0x26, 0x1a, 0xaa, 0xc2, 0x3c, 0x9e, 0xfc, 0x0c, 0x7b, 0x6a, 0xc9, 0xc1, - 0x74, 0xc6, 0x97, 0x9a, 0xee, 0xa7, 0xe6, 0xac, 0x3e, 0x23, 0x07, 0xad, 0xb1, 0x3a, 0xdb, 0x7e, 0xf1, 0xdc, 0x1f, - 0xbc, 0x3f, 0x0d, 0x90, 0xf8, 0x7a, 0x98, 0x7c, 0x8d, 0xad, 0xd4, 0xe4, 0xcf, 0xd7, 0xdf, 0xd7, 0xab, 0x40, 0xb2, - 0x39, 0xdf, 0xbb, 0xbe, 0x0b, 0x16, 0x4a, 0x7f, 0x18, 0x58, 0x31, 0xbb, 0x31, 0x7a, 0x94, 0x22, 0x44, 0xe1, 0x1e, - 0x4b, 0x11, 0x79, 0xab, 0x87, 0xc1, 0xdf, 0x12, 0x71, 0x32, 0x5c, 0xa2, 0x80, 0xc6, 0xe7, 0xd3, 0x4c, 0x2b, 0xae, - 0x88, 0x22, 0x81, 0xbd, 0x16, 0x35, 0x93, 0x6c, 0x13, 0x8c, 0xa0, 0x45, 0x2d, 0x07, 0x32, 0x9c, 0xc5, 0x82, 0x2f, - 0x18, 0x69, 0xce, 0xed, 0x9a, 0xc5, 0xc4, 0x85, 0x8c, 0xb7, 0x57, 0x11, 0x33, 0xda, 0xad, 0x07, 0x0c, 0xe7, 0x33, - 0x03, 0xcd, 0xc5, 0xb8, 0x22, 0x36, 0x7f, 0x84, 0x23, 0x4a, 0xee, 0xb5, 0x90, 0x7d, 0x3f, 0x23, 0xf5, 0x09, 0x43, - 0xc6, 0x24, 0x63, 0xbb, 0x61, 0xc6, 0xe4, 0x7d, 0x91, 0xa7, 0xab, 0xc1, 0xa2, 0xfb, 0x60, 0xb7, 0x16, 0xae, 0x2d, - 0x20, 0xeb, 0x70, 0x18, 0x7a, 0x5f, 0xde, 0x47, 0x81, 0xd2, 0x6c, 0x5f, 0x5f, 0x3d, 0xc0, 0xfe, 0x6e, 0x45, 0x26, - 0x06, 0x24, 0x69, 0x1b, 0x50, 0x78, 0xdc, 0x52, 0xdf, 0xd6, 0xa8, 0xf5, 0x2c, 0xab, 0xb9, 0x97, 0x25, 0xd5, 0x68, - 0xe3, 0x8b, 0x45, 0x7f, 0x31, 0x25, 0x12, 0xc9, 0x3c, 0x08, 0xd6, 0x48, 0xf8, 0x9b, 0xf7, 0x24, 0x75, 0xc5, 0x79, - 0xea, 0x7d, 0xc2, 0x45, 0x4c, 0xa4, 0x37, 0x50, 0xa4, 0x4c, 0x5b, 0x2f, 0xfe, 0xdd, 0x57, 0xe8, 0xf4, 0xe6, 0x63, - 0x13, 0x2b, 0x17, 0x03, 0x40, 0x98, 0x89, 0x16, 0xf1, 0x38, 0xf4, 0xb4, 0x87, 0x58, 0xa4, 0x27, 0x4b, 0xbd, 0xc4, - 0x65, 0x3a, 0x2e, 0x94, 0x2f, 0x57, 0x0b, 0x41, 0xda, 0x50, 0xa4, 0xbe, 0x0b, 0xf9, 0xc2, 0x07, 0x57, 0x82, 0x55, - 0xf2, 0x0d, 0x93, 0xc9, 0xf9, 0xb3, 0xbc, 0x6f, 0x7e, 0x0b, 0x2c, 0x7e, 0xd7, 0xe0, 0x25, 0xee, 0x7d, 0x1f, 0x7c, - 0x8d, 0x06, 0x5a, 0xfd, 0xcf, 0x56, 0x8c, 0x62, 0x88, 0x65, 0xb5, 0x08, 0x3e, 0xd5, 0x6e, 0x7a, 0x8a, 0x96, 0x7c, - 0xc9, 0x93, 0xbb, 0xf0, 0x92, 0xd4, 0xda, 0xc6, 0x61, 0xd6, 0xde, 0xa3, 0xdc, 0xd0, 0x7b, 0xad, 0x16, 0xa4, 0x43, - 0xcc, 0xae, 0xe0, 0x32, 0xe3, 0x05, 0x26, 0xeb, 0xcf, 0x52, 0x58, 0x2c, 0xf2, 0x8b, 0x2a, 0xd2, 0x9e, 0xb2, 0xcc, - 0x87, 0x6c, 0xa6, 0x75, 0x4d, 0xc9, 0xa2, 0x80, 0x4b, 0x94, 0x95, 0x42, 0x6c, 0xe4, 0xe2, 0xb3, 0x56, 0x80, 0x35, - 0xf0, 0x0a, 0x84, 0x62, 0x92, 0x9a, 0xbc, 0x71, 0xf5, 0xdf, 0x9a, 0xfc, 0xab, 0x3a, 0xe6, 0xdf, 0x54, 0x32, 0xff, - 0xfa, 0x7c, 0x4d, 0x1b, 0x7f, 0x6f, 0xf4, 0x25, 0xf1, 0xad, 0x94, 0x80, 0x12, 0x5b, 0x29, 0xbe, 0x23, 0x70, 0x1a, - 0x5d, 0x19, 0xec, 0xc6, 0x03, 0x0b, 0x2b, 0x21, 0xcf, 0x4d, 0x4e, 0x33, 0xad, 0x47, 0xb6, 0xa8, 0xfe, 0xce, 0x1e, - 0x38, 0x49, 0x7a, 0x2d, 0xfd, 0xbb, 0x19, 0x4f, 0x51, 0x20, 0x59, 0xe4, 0x12, 0x3b, 0x91, 0x87, 0xd8, 0x20, 0x40, - 0x90, 0x8b, 0x1c, 0xd0, 0x61, 0xaa, 0x26, 0x12, 0x91, 0xfa, 0xcf, 0x40, 0x0e, 0x2b, 0x60, 0xc0, 0x21, 0x90, 0x23, - 0x31, 0x30, 0x92, 0xe3, 0x13, 0x11, 0x17, 0x92, 0x77, 0x22, 0x2b, 0x42, 0xac, 0x06, 0x76, 0xbc, 0x41, 0x19, 0x6e, - 0x8b, 0xe4, 0x39, 0x0a, 0x14, 0x65, 0xe5, 0x8c, 0x65, 0xc4, 0xd6, 0xea, 0x59, 0xe7, 0xb4, 0x5e, 0xad, 0xa9, 0x73, - 0xc9, 0xd4, 0x69, 0x76, 0xe9, 0x64, 0xbe, 0x00, 0xf6, 0xb5, 0x28, 0x03, 0x7b, 0xd6, 0x01, 0xec, 0xd4, 0x8a, 0x13, - 0x53, 0x71, 0xd9, 0x73, 0xd6, 0x00, 0xd0, 0xd1, 0xb3, 0x06, 0x31, 0x33, 0xe8, 0x5c, 0xb3, 0x5c, 0x83, 0x04, 0x2e, - 0x5c, 0xa2, 0x5e, 0x1a, 0x4a, 0x5b, 0xcf, 0x2c, 0x0a, 0xbf, 0x45, 0xf9, 0xfc, 0x1c, 0x9a, 0x70, 0x11, 0x25, 0xec, - 0xb2, 0xb8, 0xfc, 0x29, 0x5e, 0xe3, 0xa3, 0x5a, 0xd3, 0xca, 0x4b, 0xbb, 0x35, 0xa6, 0xe7, 0x92, 0x82, 0x2d, 0xba, - 0xaa, 0xcf, 0x7b, 0xba, 0xa4, 0x8b, 0xb8, 0x8f, 0x9e, 0x12, 0x05, 0xca, 0xda, 0x15, 0x07, 0x0c, 0x2d, 0xd9, 0x89, - 0xc6, 0xa6, 0x68, 0xe9, 0xed, 0xdd, 0x76, 0xe9, 0xb6, 0x26, 0x43, 0x8e, 0x03, 0x85, 0x1d, 0x01, 0x51, 0x53, 0xdc, - 0x09, 0x8a, 0xba, 0xf2, 0xe1, 0x06, 0xa7, 0x39, 0x9d, 0x19, 0xbe, 0x15, 0x24, 0x9b, 0x08, 0x7c, 0xce, 0x8f, 0xde, - 0x4b, 0xa9, 0xab, 0xaf, 0x74, 0x3a, 0xf4, 0xb0, 0xd9, 0xc0, 0x41, 0x5e, 0xb0, 0x7d, 0x22, 0x75, 0x5a, 0x11, 0x52, - 0x11, 0x7f, 0x5f, 0xf0, 0x55, 0xba, 0xd7, 0x69, 0x43, 0x99, 0xaf, 0x59, 0xb1, 0x03, 0xd9, 0x88, 0xb5, 0x37, 0x52, - 0xde, 0xf6, 0x98, 0x9a, 0xf6, 0x9f, 0x18, 0xb8, 0x3f, 0xb7, 0xbc, 0x5e, 0x3c, 0x85, 0x29, 0x5e, 0x61, 0xa4, 0x6a, - 0xb1, 0x19, 0x8e, 0x39, 0x37, 0xee, 0xe5, 0x9a, 0x3d, 0xeb, 0xa9, 0x14, 0x50, 0x2c, 0x2b, 0x7c, 0xae, 0xca, 0xec, - 0x4d, 0xbe, 0x84, 0x5e, 0x58, 0xde, 0x7d, 0x9f, 0xf5, 0xf5, 0xaa, 0xf3, 0xad, 0x82, 0x57, 0xf5, 0x3b, 0xed, 0x17, - 0xcb, 0x29, 0x0d, 0xaf, 0x7a, 0x34, 0x71, 0x35, 0x98, 0x9d, 0x47, 0xa7, 0x80, 0x9a, 0x29, 0x00, 0x3e, 0x62, 0x53, - 0xd0, 0x15, 0xca, 0x23, 0x70, 0xde, 0x48, 0x98, 0xbd, 0x11, 0x10, 0xbd, 0x59, 0x33, 0x45, 0xf2, 0x45, 0xfb, 0x13, - 0x9b, 0x2e, 0x2e, 0x51, 0xb6, 0xf2, 0x21, 0xed, 0x0e, 0xf1, 0x42, 0x8e, 0x33, 0x2b, 0xa1, 0x6b, 0xc9, 0x6e, 0x9b, - 0xc9, 0xd6, 0x24, 0x4c, 0x00, 0xb0, 0x22, 0x67, 0x91, 0x2f, 0x5d, 0x9f, 0xd9, 0x86, 0xb2, 0x35, 0xc1, 0x08, 0x43, - 0xc3, 0x27, 0xea, 0xde, 0xf9, 0x53, 0xb3, 0xe2, 0xed, 0xc0, 0x88, 0x49, 0xf1, 0x9c, 0x31, 0xfc, 0x3c, 0xfc, 0xf2, - 0xad, 0x4e, 0x59, 0x63, 0x2f, 0xac, 0xcc, 0x0a, 0x22, 0x1e, 0x30, 0x13, 0x20, 0xf9, 0xdf, 0xe5, 0x32, 0xea, 0x8d, - 0xf2, 0x54, 0x62, 0x72, 0x6f, 0x17, 0x18, 0x2a, 0x40, 0x9c, 0x53, 0x4d, 0xa7, 0x14, 0x6f, 0x56, 0x07, 0x61, 0x76, - 0x3e, 0x28, 0x39, 0x62, 0x83, 0x25, 0x0c, 0xf5, 0x61, 0xd7, 0x62, 0x73, 0x89, 0x6b, 0xd9, 0x51, 0x27, 0xb1, 0x16, - 0xca, 0x14, 0x7f, 0xb8, 0xac, 0x30, 0x22, 0xc4, 0x45, 0x4d, 0x27, 0xe2, 0xa3, 0x29, 0xda, 0xd1, 0x6a, 0x02, 0xee, - 0x7a, 0x3a, 0xe5, 0xe3, 0xba, 0xbe, 0xb8, 0x74, 0x0d, 0x32, 0x71, 0x51, 0x60, 0x29, 0x2f, 0x93, 0x5f, 0x19, 0x3f, - 0x02, 0x5b, 0x78, 0xa0, 0x13, 0x1e, 0x27, 0x59, 0x9d, 0x20, 0xc6, 0x40, 0x34, 0x8b, 0xf0, 0x2a, 0x7a, 0x01, 0x92, - 0x9a, 0xe9, 0x32, 0x38, 0x6d, 0x5b, 0xae, 0x18, 0x49, 0xfb, 0xba, 0x12, 0x5d, 0x4b, 0xbe, 0x54, 0x84, 0x7c, 0xd9, - 0x0e, 0x67, 0x77, 0x1e, 0x9d, 0x6e, 0x67, 0x56, 0xc4, 0x8d, 0x4f, 0x3a, 0x09, 0x2e, 0x83, 0xbe, 0x21, 0xd9, 0xa1, - 0x3c, 0xa0, 0xad, 0x5f, 0xe6, 0x64, 0x4c, 0xbe, 0xe2, 0x6c, 0x43, 0x8a, 0x4a, 0x9e, 0x29, 0xdd, 0xce, 0x47, 0x57, - 0x71, 0xaa, 0x37, 0x58, 0x0f, 0x42, 0xe5, 0x00, 0x43, 0x6a, 0x12, 0x7e, 0xc4, 0xad, 0xdc, 0x58, 0xfb, 0xae, 0x4e, - 0x2a, 0xbc, 0x82, 0x33, 0x1d, 0xca, 0xb6, 0x95, 0xb9, 0xcb, 0x6c, 0x94, 0x64, 0xcb, 0x92, 0xe0, 0xbf, 0x5b, 0x45, - 0xb1, 0xe6, 0xc1, 0x79, 0x18, 0x95, 0xef, 0x8b, 0x5c, 0x3d, 0xac, 0xa7, 0xec, 0xed, 0x24, 0x94, 0xf0, 0x89, 0xa5, - 0xe3, 0xf4, 0xdb, 0x01, 0xe3, 0x94, 0x9d, 0x48, 0x5a, 0x20, 0xa7, 0xff, 0xc2, 0xb7, 0x9d, 0x06, 0x21, 0xc4, 0x3b, - 0x65, 0xbd, 0x5a, 0x00, 0x38, 0x97, 0x32, 0x3e, 0xab, 0xff, 0x02, 0x54, 0xb2, 0xeb, 0x8b, 0x71, 0x3f, 0xe0, 0xd1, - 0xa6, 0x95, 0xdf, 0x8e, 0x24, 0xcc, 0xee, 0xba, 0x7c, 0x03, 0x3d, 0x8e, 0x65, 0x07, 0x2b, 0xec, 0xab, 0x04, 0x79, - 0xe6, 0xb9, 0x48, 0x81, 0x65, 0x13, 0xc5, 0xfc, 0xa6, 0xa1, 0x4f, 0xc0, 0xc1, 0x4c, 0x77, 0x06, 0x8d, 0xd9, 0x55, - 0xad, 0xbe, 0xc6, 0xf1, 0xa2, 0x2c, 0x09, 0x5e, 0xa4, 0x31, 0x0a, 0xab, 0xb9, 0x9c, 0x87, 0xaa, 0x42, 0xe5, 0xcc, - 0x75, 0x33, 0xd6, 0xd5, 0x6d, 0xb6, 0xbb, 0x47, 0x9b, 0x13, 0xa0, 0x4a, 0x6f, 0xcc, 0x58, 0x82, 0x8a, 0xe8, 0xa0, - 0x9f, 0xb1, 0xbb, 0xca, 0xa0, 0xe3, 0x95, 0x35, 0x9f, 0x88, 0x01, 0xb7, 0x36, 0xa3, 0x22, 0x4a, 0x28, 0x1a, 0xeb, - 0xac, 0x42, 0xb5, 0xd7, 0x83, 0x6d, 0xab, 0x36, 0x10, 0x6d, 0x32, 0xa9, 0x40, 0x52, 0x11, 0xfe, 0xa2, 0xfc, 0xda, - 0xd2, 0x5e, 0xcf, 0x74, 0x46, 0x3a, 0xa8, 0x4a, 0x73, 0xce, 0x9c, 0x33, 0x3b, 0x60, 0x31, 0x5e, 0x1f, 0x6f, 0x84, - 0xa7, 0x80, 0x6c, 0x11, 0xde, 0x1c, 0xc0, 0xed, 0x6d, 0x2b, 0x0a, 0x07, 0xbb, 0xe9, 0x21, 0xaf, 0xd2, 0x36, 0x8e, - 0x80, 0x01, 0x79, 0x89, 0x93, 0xb9, 0x05, 0x12, 0x15, 0x06, 0x7e, 0x85, 0x60, 0x83, 0x25, 0x3b, 0x29, 0x2d, 0x2e, - 0x8f, 0xed, 0x62, 0x87, 0x4f, 0xcb, 0x7a, 0xb9, 0xf6, 0x06, 0xfd, 0xb5, 0xc6, 0x39, 0xf8, 0xd8, 0x21, 0x74, 0xf9, - 0xc7, 0x6c, 0x95, 0x26, 0xe9, 0xdf, 0x8a, 0x31, 0x2d, 0x2f, 0x92, 0x9c, 0x66, 0xdc, 0xe9, 0x5b, 0xe3, 0xc2, 0x47, - 0xef, 0xb9, 0x64, 0xf1, 0xbd, 0xdc, 0x1e, 0x89, 0x7e, 0x25, 0x18, 0xfa, 0xcb, 0xfa, 0x7a, 0x32, 0x88, 0xb6, 0x9d, - 0xa6, 0x0b, 0xcd, 0x2b, 0xb8, 0x94, 0xa2, 0xe2, 0x56, 0xc3, 0x0f, 0x05, 0x14, 0x49, 0xf9, 0xa8, 0x7d, 0x2c, 0x91, - 0xb5, 0x58, 0x39, 0x93, 0xed, 0x3f, 0xcb, 0x71, 0x86, 0x21, 0xef, 0xac, 0x55, 0x65, 0x55, 0xf9, 0x44, 0x17, 0xb6, - 0x45, 0xaf, 0xd4, 0x0b, 0xb9, 0xec, 0x18, 0x76, 0xbe, 0xb5, 0x37, 0x40, 0x89, 0xff, 0xe5, 0x96, 0xb7, 0xe1, 0x4c, - 0xb0, 0x0b, 0x59, 0x1d, 0x80, 0x0f, 0x8a, 0x52, 0xb2, 0xcd, 0x0b, 0x81, 0x48, 0xd7, 0x5d, 0x30, 0x8f, 0x3a, 0x62, - 0x51, 0xf0, 0x4b, 0xf7, 0x2a, 0xbc, 0xea, 0x27, 0x67, 0x51, 0x19, 0xa0, 0x59, 0x9e, 0xc7, 0x23, 0xd7, 0xc4, 0xc2, - 0xa2, 0xe4, 0xa5, 0x9a, 0xaf, 0xc6, 0x27, 0x36, 0x85, 0xad, 0x16, 0x14, 0xa7, 0xc9, 0x26, 0xe9, 0xfe, 0x40, 0x61, - 0x14, 0x16, 0xf8, 0x8f, 0x6b, 0x9f, 0x98, 0x67, 0x90, 0x68, 0x2e, 0x00, 0xa5, 0xc4, 0xfb, 0x42, 0xbd, 0x1e, 0x55, - 0x59, 0x72, 0xa0, 0xb0, 0xe3, 0x1b, 0x59, 0xbd, 0xf2, 0x3b, 0x95, 0x1a, 0x15, 0xf4, 0xfa, 0xa7, 0xb2, 0xcb, 0x02, - 0xa0, 0xed, 0xa0, 0x5a, 0x4d, 0x2d, 0xeb, 0x29, 0x17, 0xdd, 0xe1, 0x0e, 0x5e, 0xf9, 0x4e, 0xeb, 0x39, 0x9a, 0x0b, - 0x4b, 0x88, 0xb3, 0xef, 0xb1, 0x2c, 0x59, 0xce, 0x7e, 0xd6, 0xbc, 0xd0, 0x8d, 0x32, 0x7d, 0xb9, 0xd7, 0xf3, 0x99, - 0x2c, 0x5c, 0x95, 0x00, 0x33, 0xf2, 0xea, 0x72, 0x00, 0xe0, 0x13, 0x53, 0xba, 0xc2, 0x68, 0x1d, 0x47, 0x59, 0xe6, - 0x98, 0xc6, 0x3e, 0xf7, 0x90, 0xa6, 0x6f, 0x4e, 0xdc, 0x22, 0x97, 0xda, 0x6b, 0xb3, 0x0a, 0xc7, 0xc9, 0xc4, 0x3a, - 0xbe, 0xc8, 0x74, 0xa6, 0x07, 0x49, 0x97, 0x5e, 0xce, 0x80, 0x4c, 0xad, 0xee, 0xc0, 0x5c, 0x35, 0x09, 0xa0, 0xa7, - 0xef, 0x8a, 0x2c, 0x8f, 0xc9, 0xfe, 0xbc, 0x37, 0xbb, 0xf8, 0x8c, 0x74, 0xa3, 0x53, 0xf4, 0xd9, 0x31, 0x2d, 0xd7, - 0xac, 0x48, 0x00, 0x28, 0x17, 0x84, 0xbd, 0x71, 0x4c, 0x62, 0x0b, 0x5a, 0xb6, 0xeb, 0x05, 0x08, 0x1d, 0x01, 0x48, - 0xee, 0x8b, 0x02, 0xdf, 0xcf, 0xce, 0x35, 0x2f, 0x86, 0x2c, 0x7c, 0x9e, 0xa1, 0x5f, 0x0f, 0xb8, 0x2e, 0x13, 0x82, - 0x89, 0x7c, 0x86, 0x86, 0xbf, 0xca, 0xbc, 0x89, 0xb3, 0x11, 0xd1, 0xb5, 0xbf, 0x4f, 0xe9, 0xe3, 0x0a, 0x8e, 0x1f, - 0x2a, 0xe0, 0xf7, 0x03, 0xb3, 0x37, 0xd4, 0x3f, 0x7a, 0x31, 0xa8, 0x86, 0x47, 0x96, 0x9f, 0x2a, 0x30, 0x9a, 0x39, - 0xf0, 0x00, 0x11, 0x44, 0x92, 0xd9, 0x57, 0x71, 0x5b, 0xda, 0x1d, 0x46, 0x01, 0x01, 0x8c, 0x59, 0x93, 0x5d, 0x08, - 0x13, 0x80, 0x75, 0xee, 0x9b, 0xd1, 0x45, 0x0f, 0x7a, 0x6c, 0xf3, 0x51, 0xb9, 0x16, 0xe5, 0x18, 0x8c, 0x69, 0xcc, - 0x17, 0x36, 0xec, 0x09, 0xb6, 0xd1, 0x08, 0x47, 0xaf, 0x60, 0x08, 0x97, 0x34, 0xee, 0x55, 0x3a, 0x17, 0xbe, 0xf7, - 0x2a, 0xca, 0x82, 0x18, 0xbb, 0x6f, 0xc6, 0xa9, 0x01, 0xb2, 0x64, 0xff, 0xb4, 0x60, 0xc9, 0xa9, 0xb3, 0xaf, 0xe9, - 0xe4, 0xd9, 0xc7, 0xdc, 0xf0, 0x4e, 0x9e, 0x83, 0x43, 0xd3, 0x52, 0x4f, 0xeb, 0xfc, 0x0d, 0x5a, 0x68, 0x05, 0xf3, - 0x82, 0x76, 0x76, 0x06, 0x58, 0x5a, 0xa1, 0xb6, 0xa6, 0xb6, 0xe4, 0x0d, 0xfb, 0xa1, 0x95, 0x95, 0x62, 0x30, 0x0d, - 0x20, 0x89, 0x1d, 0x88, 0x46, 0xa1, 0xfd, 0xd0, 0xf7, 0xb7, 0xb9, 0xef, 0x65, 0x89, 0xdf, 0xba, 0xbe, 0x8e, 0x95, - 0x56, 0x8f, 0x7f, 0x3e, 0x0f, 0x97, 0x24, 0x62, 0xbf, 0x56, 0xc1, 0xca, 0x64, 0x63, 0x05, 0x2e, 0xaa, 0xcf, 0x38, - 0x96, 0x7c, 0x28, 0x38, 0xe5, 0x66, 0x85, 0x94, 0x99, 0xec, 0xf3, 0xb0, 0x80, 0xc6, 0xda, 0x8c, 0x6a, 0x50, 0x2b, - 0xe6, 0x60, 0x4e, 0x8f, 0x0a, 0x84, 0xc7, 0x14, 0x40, 0x95, 0x2f, 0x4e, 0x7d, 0xf9, 0x75, 0xce, 0x91, 0x90, 0x4b, - 0xd3, 0xd4, 0xfd, 0xef, 0x52, 0x91, 0xf3, 0x0e, 0x82, 0x10, 0xc3, 0x23, 0xe8, 0x1b, 0x94, 0x5f, 0xfc, 0x89, 0xbf, - 0xf8, 0xba, 0xf8, 0xb9, 0x60, 0xe6, 0x9b, 0x66, 0x39, 0xb3, 0x78, 0x8b, 0x59, 0x6f, 0x1d, 0xb2, 0x15, 0x61, 0x91, - 0xd2, 0x4c, 0x43, 0xce, 0x04, 0xcd, 0xb3, 0xa0, 0x80, 0xcd, 0x7c, 0xae, 0xf5, 0x26, 0x20, 0x3d, 0x90, 0x04, 0xf7, - 0xaf, 0x12, 0x5d, 0x0e, 0x54, 0x4d, 0x47, 0x51, 0x0a, 0x1e, 0x80, 0x9b, 0x4a, 0xa8, 0x01, 0xea, 0xa4, 0xe1, 0x29, - 0xb4, 0x62, 0x2c, 0xc1, 0xb3, 0x2c, 0x62, 0x9d, 0x06, 0x30, 0x1a, 0x49, 0x3c, 0xac, 0x51, 0xb8, 0x3a, 0xcf, 0x26, - 0x63, 0x56, 0xc7, 0xbc, 0xad, 0x2e, 0xb2, 0x3b, 0xd2, 0x04, 0x9f, 0xb9, 0x4e, 0xc5, 0xde, 0xee, 0x38, 0x60, 0x4a, - 0x4d, 0x03, 0x07, 0x99, 0x4a, 0xf3, 0x40, 0xa1, 0x69, 0x5c, 0x0b, 0x30, 0xd0, 0xc9, 0x59, 0x2d, 0x4a, 0x88, 0xad, - 0xb8, 0x01, 0x10, 0x47, 0x3a, 0xfa, 0x20, 0x85, 0x0d, 0x3f, 0x30, 0x96, 0xfc, 0x11, 0xf0, 0x98, 0x3f, 0x78, 0x08, - 0x08, 0x51, 0xda, 0x08, 0x79, 0x62, 0x0d, 0x5a, 0x59, 0x2c, 0x0c, 0x7e, 0x2b, 0xda, 0xcb, 0x9e, 0xe2, 0xf3, 0x8d, - 0xba, 0x1f, 0x08, 0x51, 0xb7, 0xc1, 0x9a, 0x45, 0x46, 0x73, 0x37, 0xf8, 0xaf, 0xf9, 0x3d, 0x49, 0xa4, 0x50, 0x2c, - 0x15, 0xb9, 0x8f, 0x28, 0x6f, 0x31, 0x6e, 0x21, 0x6f, 0xed, 0xe0, 0xe3, 0x56, 0x18, 0xa8, 0x23, 0xad, 0x16, 0x92, - 0xf2, 0x16, 0x53, 0xcd, 0xb8, 0xa3, 0x60, 0x35, 0x51, 0x6a, 0xf8, 0x1c, 0x49, 0xba, 0x7a, 0x8e, 0xcd, 0x4c, 0xfc, - 0x63, 0x66, 0x9a, 0xa7, 0x26, 0x1f, 0x15, 0x75, 0x93, 0xd9, 0xb8, 0xb1, 0xe0, 0xe8, 0x09, 0xcf, 0x84, 0xbc, 0x4b, - 0x1d, 0xed, 0x54, 0x6f, 0x21, 0xe5, 0x21, 0xc3, 0x14, 0xc4, 0x7a, 0x40, 0xef, 0x68, 0x6a, 0x74, 0xeb, 0x6e, 0x4c, - 0x0f, 0x12, 0x88, 0xd5, 0xa9, 0x1d, 0xa1, 0x2d, 0x6e, 0x0f, 0x31, 0x5c, 0x56, 0x5d, 0x0a, 0x14, 0xa9, 0x55, 0x9e, - 0xf2, 0x59, 0x82, 0x12, 0xb0, 0x49, 0x51, 0x9f, 0x73, 0x1c, 0xd6, 0x45, 0x41, 0xed, 0x33, 0x85, 0x48, 0x16, 0xca, - 0x34, 0x5f, 0x06, 0x5f, 0x44, 0x33, 0x68, 0x00, 0xc9, 0x80, 0xaf, 0xf6, 0x9b, 0x6b, 0xe8, 0x46, 0x20, 0x6f, 0xb3, - 0x26, 0xca, 0xe6, 0xc3, 0x39, 0xc4, 0xb6, 0xb6, 0xf7, 0x1b, 0xb4, 0x9e, 0x85, 0x7a, 0x97, 0xf2, 0xac, 0xb0, 0xad, - 0x5c, 0x05, 0x5a, 0x72, 0x72, 0xb2, 0x91, 0xc7, 0x40, 0x1d, 0x61, 0xdb, 0x63, 0x64, 0x4e, 0xe0, 0x5f, 0x6a, 0xb3, - 0x16, 0x84, 0x67, 0x36, 0xb2, 0xe0, 0x0f, 0x74, 0x31, 0xd8, 0x30, 0xde, 0xc4, 0x3f, 0xa3, 0xec, 0xb9, 0x7b, 0xed, - 0x25, 0xab, 0xa0, 0x1e, 0x8e, 0xda, 0x09, 0x9d, 0xb6, 0xc9, 0xb7, 0x2d, 0x08, 0x84, 0xe4, 0xe3, 0xa5, 0x88, 0xee, - 0x84, 0x59, 0xd2, 0xaa, 0x96, 0xd8, 0xf3, 0xe6, 0xa7, 0xf1, 0x9e, 0xd7, 0xfb, 0x82, 0x85, 0xa8, 0xb9, 0x37, 0x1b, - 0xd6, 0xf5, 0xc6, 0xf2, 0xee, 0xbd, 0x32, 0xb3, 0xe8, 0x6c, 0xcc, 0x65, 0x01, 0x93, 0xea, 0x9e, 0x40, 0x2f, 0x96, - 0x27, 0xfd, 0xb1, 0xcd, 0x54, 0xe3, 0x58, 0x24, 0xf3, 0x28, 0x4e, 0x09, 0x6f, 0x0c, 0x68, 0xf4, 0x6b, 0x8a, 0x24, - 0x91, 0x79, 0x06, 0x8b, 0xcc, 0x58, 0x79, 0x1b, 0x7c, 0x43, 0xcc, 0x4c, 0x44, 0x34, 0xc8, 0x4e, 0x60, 0x8e, 0xc6, - 0x02, 0xe1, 0x0f, 0x71, 0x86, 0x26, 0xbe, 0xa3, 0x9b, 0x97, 0x9c, 0x4c, 0x5d, 0x80, 0x0b, 0x70, 0xbb, 0x7a, 0x06, - 0xfd, 0x70, 0xb3, 0x55, 0x84, 0x94, 0x92, 0x0a, 0x5c, 0x74, 0xac, 0x35, 0xf9, 0x3b, 0xa5, 0x98, 0x68, 0xdd, 0x88, - 0xea, 0x4b, 0x07, 0x60, 0xdf, 0x1d, 0xd4, 0xe7, 0x96, 0x34, 0x56, 0x92, 0xcf, 0x83, 0x2e, 0x35, 0x7d, 0x10, 0x2b, - 0xe4, 0x19, 0x9f, 0x1c, 0x81, 0x70, 0x87, 0xdf, 0x5d, 0xda, 0x4c, 0xd0, 0xdb, 0x44, 0x1b, 0x97, 0x0c, 0xf0, 0x8b, - 0x1c, 0x23, 0xec, 0x62, 0x86, 0x9c, 0xad, 0x19, 0xbf, 0x4c, 0x8e, 0x8c, 0x17, 0x84, 0x3f, 0x15, 0x9e, 0x97, 0x76, - 0xd3, 0x04, 0xc4, 0x3f, 0x10, 0x5d, 0x34, 0x18, 0x9d, 0x04, 0xf3, 0xcc, 0xcb, 0x65, 0x71, 0x51, 0x55, 0xd0, 0x60, - 0x9f, 0xbb, 0x5e, 0xc9, 0x96, 0x6f, 0xcf, 0xff, 0x71, 0x6e, 0x75, 0x53, 0xe2, 0xc8, 0x43, 0x57, 0xe2, 0xaa, 0x97, - 0x7b, 0x7e, 0xd2, 0xbd, 0xd5, 0x4e, 0xb8, 0xdf, 0xc8, 0x55, 0x5f, 0x21, 0x84, 0x7f, 0xf2, 0x07, 0x0d, 0xc1, 0xca, - 0x23, 0x58, 0xb3, 0x94, 0x72, 0xc7, 0xd5, 0x72, 0xdb, 0x0f, 0xf6, 0x3e, 0x60, 0xa5, 0x73, 0x17, 0x16, 0xe3, 0x09, - 0x12, 0x94, 0x17, 0xca, 0xd7, 0x62, 0x8c, 0xb3, 0xdd, 0xac, 0xc6, 0xa1, 0x15, 0xc4, 0x63, 0xcf, 0x72, 0xb8, 0xa8, - 0x43, 0x84, 0x2e, 0x1d, 0x5c, 0x5e, 0xc9, 0xe2, 0x81, 0xa3, 0x4c, 0xd3, 0x18, 0xcf, 0x56, 0x20, 0x39, 0x79, 0xfa, - 0xf0, 0x40, 0x8f, 0x90, 0x80, 0xd1, 0xe7, 0xce, 0x5b, 0x4a, 0x86, 0x6d, 0xd5, 0xb7, 0x09, 0xa0, 0xcd, 0x17, 0x34, - 0x87, 0x68, 0xc5, 0xc8, 0x34, 0x78, 0xed, 0x5d, 0x6c, 0xb5, 0x92, 0x39, 0x09, 0xad, 0x46, 0xac, 0x41, 0x52, 0xbf, - 0xd3, 0xa4, 0x0f, 0xe6, 0x67, 0xb9, 0x85, 0xda, 0xc9, 0x58, 0xed, 0x84, 0x33, 0x3b, 0x9d, 0xf3, 0x2d, 0xfb, 0xf5, - 0x8c, 0xe9, 0x3c, 0x47, 0x36, 0x5f, 0x7a, 0xcd, 0xd7, 0x9f, 0x87, 0xfc, 0xd3, 0x53, 0x79, 0x9b, 0xb0, 0x80, 0xfd, - 0x36, 0x35, 0xa8, 0x27, 0xd6, 0xed, 0x92, 0x6a, 0x29, 0x9a, 0x63, 0x71, 0x44, 0x11, 0xb1, 0x5d, 0xc0, 0x11, 0x7a, - 0x1f, 0xf1, 0x6b, 0x56, 0x67, 0xa2, 0xe4, 0x3c, 0x83, 0x77, 0x0a, 0x63, 0x25, 0x92, 0xbc, 0x22, 0x8d, 0x4c, 0xa4, - 0x75, 0x43, 0xde, 0x26, 0x79, 0xa9, 0xc9, 0xe9, 0xe8, 0x74, 0xec, 0x3d, 0xfe, 0x67, 0x40, 0x25, 0x21, 0x50, 0x81, - 0xd2, 0x3e, 0xdf, 0x1d, 0x31, 0x44, 0x93, 0x29, 0x4a, 0x91, 0xac, 0xa5, 0xe8, 0x2f, 0x31, 0x2b, 0x4d, 0x59, 0xdd, - 0x9d, 0x80, 0xeb, 0x36, 0x4e, 0x12, 0x77, 0x1b, 0x33, 0x99, 0x87, 0x13, 0xd8, 0x9f, 0xcb, 0x75, 0x7e, 0x88, 0xc1, - 0x96, 0x87, 0xa7, 0x25, 0x82, 0x5f, 0x47, 0x15, 0xbc, 0x1e, 0x44, 0x10, 0x1c, 0x67, 0x23, 0x22, 0xf6, 0x9b, 0x21, - 0x7b, 0x27, 0x2f, 0x00, 0x28, 0xce, 0xef, 0xe3, 0xe6, 0x79, 0x9d, 0x9f, 0x00, 0x45, 0x38, 0x2a, 0xfc, 0xb0, 0x33, - 0x82, 0x41, 0x15, 0xde, 0xc9, 0x22, 0x6b, 0xcc, 0x8e, 0x97, 0x2b, 0x9a, 0x73, 0x32, 0xb3, 0x55, 0x4f, 0x48, 0x22, - 0x48, 0x33, 0xcc, 0x7a, 0x10, 0x8c, 0x18, 0xbf, 0xac, 0x27, 0x83, 0xd1, 0x59, 0x92, 0x2c, 0x6c, 0x1a, 0x4e, 0xa4, - 0x6d, 0x84, 0x18, 0xc9, 0x76, 0x29, 0xc5, 0xa4, 0x6b, 0xcf, 0x36, 0x67, 0xcd, 0x17, 0x42, 0x51, 0xc0, 0x6e, 0x29, - 0x81, 0x18, 0xe7, 0x50, 0x42, 0xc3, 0x68, 0xca, 0x9f, 0x8b, 0x13, 0xc4, 0x3a, 0xf2, 0xd2, 0x54, 0x68, 0xb3, 0xc1, - 0x9d, 0x0f, 0x48, 0x11, 0xc6, 0xfd, 0x19, 0x38, 0x66, 0xb2, 0x52, 0x5c, 0x32, 0x87, 0xb7, 0x3b, 0x52, 0xac, 0x63, - 0xf6, 0x82, 0x60, 0xf0, 0x1c, 0x5b, 0x98, 0x58, 0xa4, 0xa2, 0x8f, 0x24, 0x15, 0x5c, 0x96, 0xea, 0xfe, 0x3d, 0x6c, - 0xbb, 0x6d, 0x0a, 0x62, 0x9b, 0x93, 0x30, 0x53, 0x8d, 0xc7, 0xd5, 0xa3, 0x0d, 0xb8, 0xfe, 0x1c, 0xa0, 0x91, 0x26, - 0xab, 0x74, 0x65, 0x7d, 0x73, 0xbf, 0xa9, 0xc7, 0x8a, 0x79, 0x7c, 0xf0, 0x89, 0x80, 0x35, 0xee, 0x80, 0x29, 0x6b, - 0x30, 0x24, 0x1c, 0x8a, 0xb0, 0xd9, 0x01, 0x98, 0x62, 0xfd, 0x28, 0x22, 0x71, 0xef, 0xa2, 0x4d, 0x02, 0x32, 0x2d, - 0xd7, 0x39, 0x37, 0x4b, 0xfd, 0xce, 0x24, 0xfc, 0x24, 0x86, 0x30, 0xc6, 0x21, 0x8e, 0x10, 0x8d, 0x25, 0xea, 0xf5, - 0x6b, 0x3c, 0xf6, 0xd2, 0x92, 0xff, 0xc9, 0xc6, 0xf9, 0x9d, 0x12, 0x9a, 0x63, 0xcb, 0xa6, 0xcd, 0x16, 0x74, 0xfb, - 0x5a, 0xd2, 0x52, 0xec, 0x2a, 0x8a, 0x4f, 0x1e, 0xf9, 0x41, 0x65, 0x78, 0x7f, 0x77, 0x49, 0xac, 0x07, 0xad, 0x24, - 0xb8, 0x35, 0x23, 0xbc, 0xbf, 0x4b, 0x27, 0xfc, 0x70, 0x10, 0xf1, 0x6e, 0x91, 0xd1, 0xb6, 0x98, 0x9a, 0x6d, 0x60, - 0x71, 0xe9, 0x43, 0x05, 0xb0, 0x8b, 0x0c, 0xeb, 0xf4, 0x1a, 0x77, 0xbb, 0xd2, 0xec, 0x1e, 0x21, 0x3c, 0x49, 0x95, - 0x9d, 0x6b, 0xb3, 0x98, 0xcb, 0x02, 0x3a, 0x49, 0xa5, 0x22, 0x9a, 0x49, 0xe3, 0xd0, 0x52, 0xe1, 0xdf, 0x05, 0x49, - 0x6a, 0x63, 0xdc, 0xfd, 0xd9, 0x19, 0x46, 0x54, 0x41, 0x4d, 0x49, 0x49, 0x1d, 0xc6, 0x64, 0xc7, 0x20, 0xfe, 0xb7, - 0xc7, 0x1e, 0x52, 0xaf, 0x59, 0x68, 0x99, 0x51, 0x1e, 0x7f, 0x37, 0x4c, 0x3b, 0x59, 0xe3, 0x91, 0xd7, 0xf5, 0x4e, - 0xd1, 0xd6, 0xb7, 0x70, 0xb6, 0xa1, 0x1b, 0xde, 0x74, 0xf5, 0x0c, 0xe3, 0xf1, 0x15, 0xfc, 0xbc, 0x81, 0x49, 0x4f, - 0xa4, 0x26, 0xee, 0x7c, 0x53, 0x72, 0x62, 0xab, 0x9e, 0x2a, 0xb0, 0x14, 0x4f, 0xc4, 0x6a, 0x57, 0x51, 0x32, 0xb5, - 0x51, 0x83, 0xe1, 0x8c, 0x35, 0xf4, 0xc9, 0xa9, 0xe1, 0x9c, 0x67, 0x80, 0x87, 0x97, 0xae, 0x4f, 0x21, 0x53, 0x3f, - 0x8d, 0x71, 0x29, 0x20, 0x4e, 0xc4, 0xb3, 0x0b, 0x2f, 0x31, 0xbe, 0x71, 0x7d, 0x0a, 0xf6, 0xd6, 0xa4, 0xab, 0x78, - 0x6a, 0x58, 0x85, 0x53, 0x9b, 0xab, 0xe1, 0xd4, 0xd6, 0x59, 0x0f, 0xfb, 0xb7, 0x14, 0xb9, 0x12, 0x50, 0x94, 0x1c, - 0x65, 0x2a, 0xae, 0x5c, 0x1b, 0xc6, 0xed, 0xb5, 0xf3, 0xc7, 0x54, 0x5d, 0x62, 0x28, 0x29, 0x51, 0xda, 0x3c, 0xb1, - 0x2d, 0x30, 0x92, 0x75, 0x13, 0xdc, 0xd2, 0x6b, 0xb9, 0xb4, 0xfb, 0xe2, 0x0e, 0x49, 0xa1, 0x96, 0xb4, 0xf6, 0x3c, - 0x89, 0x3e, 0xd6, 0xdc, 0xd2, 0xc6, 0x43, 0x62, 0xef, 0xf4, 0x58, 0x45, 0xfa, 0xf9, 0x52, 0x1d, 0x6a, 0x77, 0x20, - 0xe0, 0x32, 0x6d, 0x20, 0xbf, 0x6c, 0x0b, 0x44, 0xf6, 0x7c, 0x45, 0xb2, 0xf1, 0x87, 0x0a, 0x38, 0x1d, 0x38, 0xc5, - 0x04, 0x60, 0x65, 0x2a, 0x94, 0x4e, 0x12, 0x58, 0x16, 0x1f, 0xa1, 0x6a, 0x31, 0x37, 0x2d, 0xae, 0x0f, 0x8c, 0x78, - 0x7e, 0x9b, 0x10, 0x0f, 0x00, 0x71, 0x3d, 0x43, 0xd4, 0x15, 0x88, 0xfa, 0xcc, 0x8c, 0x81, 0x84, 0x1e, 0xb2, 0xef, - 0x0f, 0x98, 0xb9, 0x63, 0x3a, 0xf1, 0x52, 0xa5, 0xdc, 0x46, 0xcb, 0xc7, 0x72, 0x58, 0xa5, 0x99, 0x26, 0xc5, 0x35, - 0x09, 0x55, 0xf2, 0x8a, 0x06, 0x56, 0xb9, 0x6c, 0xf7, 0x5f, 0x7d, 0xe0, 0x35, 0x6c, 0x73, 0x3e, 0x5e, 0x3c, 0xc6, - 0xb7, 0x02, 0x45, 0xa3, 0x8a, 0xd9, 0x2a, 0x37, 0x18, 0x13, 0xd3, 0x8b, 0x03, 0xb1, 0xd4, 0xac, 0xe9, 0xce, 0x3c, - 0x87, 0xf6, 0x4d, 0xf1, 0xa0, 0x4c, 0xa5, 0x0a, 0x54, 0x70, 0x8d, 0x30, 0x56, 0x59, 0xb3, 0xa8, 0x4b, 0xc4, 0xfb, - 0xed, 0xd0, 0xbc, 0x94, 0x25, 0xa6, 0x88, 0x1d, 0x54, 0xd4, 0x19, 0x3e, 0xe7, 0xe1, 0xd6, 0xde, 0x7d, 0x76, 0x64, - 0x43, 0xc5, 0xc4, 0x94, 0x84, 0xf4, 0x64, 0x63, 0x4a, 0x92, 0x45, 0xe3, 0x99, 0xba, 0xa9, 0xbe, 0x86, 0xf1, 0x08, - 0x07, 0x6b, 0x3f, 0x66, 0x37, 0x40, 0x15, 0xd2, 0xe6, 0xa6, 0xda, 0xcc, 0xc1, 0x67, 0xb5, 0xe5, 0xdf, 0x96, 0x9e, - 0xde, 0x96, 0x2e, 0x7c, 0xd1, 0x2d, 0xe9, 0xe0, 0xd7, 0xf8, 0xd7, 0xa6, 0x09, 0x3f, 0xdd, 0x0c, 0x90, 0x9e, 0xef, - 0x72, 0x81, 0x28, 0x71, 0xad, 0x19, 0x03, 0xc5, 0x1b, 0xa4, 0x89, 0xa6, 0xc0, 0x1c, 0x8c, 0x76, 0xe0, 0x1f, 0x04, - 0x35, 0xa0, 0x12, 0x7a, 0x73, 0x45, 0x59, 0x5c, 0x7b, 0x9e, 0x0d, 0xfd, 0x18, 0x3a, 0x91, 0xbc, 0xfb, 0xa5, 0xd1, - 0x18, 0x05, 0xed, 0x7e, 0x89, 0x65, 0x02, 0x8e, 0xec, 0xa2, 0x95, 0x05, 0x33, 0x01, 0x6b, 0x81, 0x1d, 0x9a, 0x47, - 0x17, 0x7c, 0xbb, 0x2e, 0x19, 0x30, 0xa4, 0xcc, 0x5a, 0xfb, 0x74, 0xd5, 0xd1, 0xf8, 0x5a, 0x43, 0xb1, 0xd2, 0xb8, - 0x00, 0x86, 0x44, 0x15, 0x75, 0x3c, 0x59, 0x17, 0x1d, 0x30, 0x36, 0x97, 0x7c, 0x33, 0x44, 0x64, 0xce, 0x63, 0x83, - 0x41, 0x4c, 0x58, 0x3b, 0x56, 0x7f, 0xbe, 0xd0, 0x72, 0xa0, 0x69, 0x3e, 0x1f, 0x48, 0x94, 0xb6, 0x73, 0x08, 0x6d, - 0x27, 0x4a, 0xd7, 0x8d, 0x68, 0x0e, 0x84, 0x7b, 0xbf, 0x88, 0xc6, 0x19, 0x36, 0xde, 0xb9, 0x2c, 0xae, 0xaf, 0xba, - 0xba, 0x1f, 0x55, 0x23, 0x1e, 0x06, 0x5c, 0xbb, 0x85, 0x48, 0x9a, 0xf5, 0x77, 0xd4, 0x5b, 0x65, 0x94, 0x3e, 0x1d, - 0xef, 0x96, 0xbc, 0x6c, 0xed, 0x97, 0xfd, 0x9f, 0xcc, 0x3c, 0xe4, 0xf7, 0x85, 0x29, 0x54, 0x1f, 0x0d, 0x3d, 0xa2, - 0x6e, 0x1c, 0xe0, 0x7c, 0x6b, 0x13, 0x32, 0xb4, 0x60, 0x11, 0x19, 0x8f, 0xc0, 0xdc, 0x94, 0xa3, 0xbb, 0xde, 0x57, - 0x6c, 0xf8, 0x66, 0xc9, 0xbe, 0xd0, 0x95, 0x68, 0x5a, 0x47, 0xb8, 0x8b, 0x56, 0x92, 0x38, 0xa3, 0x91, 0x0e, 0x9d, - 0x51, 0xfd, 0x12, 0x3d, 0xef, 0x52, 0x60, 0x6b, 0xb9, 0xda, 0xf9, 0x9d, 0x95, 0x7c, 0x08, 0xa7, 0x63, 0x5c, 0x9b, - 0x0b, 0x48, 0xe3, 0x32, 0x71, 0x72, 0x58, 0x00, 0xcb, 0xde, 0xde, 0x2b, 0xe9, 0x70, 0x40, 0x6a, 0x3c, 0x16, 0xb3, - 0x43, 0x8a, 0x70, 0x03, 0x3a, 0x87, 0x06, 0x4b, 0x54, 0x09, 0xc7, 0x45, 0xec, 0xfa, 0xa6, 0xe2, 0x95, 0xab, 0xa0, - 0x0c, 0xca, 0x84, 0x75, 0x5b, 0xfe, 0x6d, 0xc9, 0xe7, 0xbe, 0x0d, 0x42, 0xce, 0x85, 0x0c, 0xee, 0x55, 0x09, 0x14, - 0x9b, 0x37, 0x82, 0xd8, 0x1a, 0xd3, 0x3d, 0xb0, 0x52, 0x9d, 0xb2, 0x58, 0x4f, 0x6c, 0xb6, 0x05, 0xf5, 0xa4, 0x61, - 0xe6, 0xf6, 0x1c, 0x41, 0x74, 0x07, 0xa1, 0x8f, 0xf7, 0xae, 0x8f, 0x52, 0x5e, 0xf9, 0xe5, 0xf9, 0x3e, 0x64, 0x85, - 0x62, 0x63, 0x0b, 0x3d, 0xa9, 0xf3, 0x70, 0x93, 0x07, 0x2d, 0xa2, 0x48, 0xf5, 0x5a, 0xac, 0x58, 0x01, 0x3b, 0xa2, - 0x0c, 0xff, 0x1e, 0x5c, 0x60, 0x1b, 0x58, 0x87, 0x4b, 0x00, 0x73, 0x37, 0xc6, 0xed, 0xd4, 0x53, 0xe5, 0x27, 0x1a, - 0x3f, 0x23, 0x82, 0x8b, 0x30, 0x45, 0x24, 0xb4, 0x4f, 0x15, 0x5f, 0xd1, 0x81, 0xc7, 0xb2, 0x7c, 0x6a, 0xc6, 0x9b, - 0x7c, 0xa9, 0x58, 0xaf, 0xfc, 0xf2, 0x90, 0xbd, 0xd0, 0xf8, 0x79, 0xd2, 0x12, 0xe2, 0xf2, 0x25, 0x82, 0x55, 0x25, - 0x5f, 0x8d, 0xd0, 0x47, 0xde, 0xc3, 0x97, 0x1b, 0x76, 0xd0, 0xf9, 0x80, 0x4a, 0xa6, 0x71, 0x81, 0x6f, 0x38, 0x2f, - 0xcd, 0xaa, 0x09, 0x33, 0x44, 0xf8, 0xc4, 0x69, 0x03, 0xc7, 0x57, 0xbe, 0x34, 0x74, 0x29, 0x3e, 0x15, 0x00, 0x7b, - 0x92, 0x74, 0x0e, 0x65, 0x32, 0xc7, 0x52, 0x24, 0x0e, 0x26, 0x95, 0xd9, 0x13, 0x48, 0x30, 0x5b, 0xac, 0xd2, 0x55, - 0xe7, 0x56, 0x8c, 0x6b, 0x32, 0x01, 0x30, 0xc6, 0x39, 0xd0, 0x9c, 0x99, 0xad, 0xd8, 0x21, 0x73, 0x62, 0x45, 0x05, - 0xf6, 0x7f, 0x8c, 0xbd, 0xc2, 0xdd, 0x67, 0xa6, 0x1f, 0xb3, 0x31, 0xdf, 0xf4, 0x3a, 0x34, 0x9b, 0xdc, 0x70, 0x79, - 0xb7, 0x5e, 0xcc, 0x89, 0x30, 0x5b, 0x40, 0x79, 0x1a, 0xd9, 0x48, 0x74, 0xd4, 0x40, 0xea, 0x1a, 0x48, 0x76, 0xf6, - 0xcd, 0x65, 0x6f, 0xf5, 0x59, 0x01, 0x31, 0xd1, 0xcd, 0x0c, 0xd4, 0xed, 0x2f, 0xf8, 0xb6, 0x3a, 0x15, 0x4c, 0x10, - 0xc0, 0x63, 0xd7, 0x86, 0x73, 0x21, 0x0b, 0xd5, 0xe9, 0xf6, 0xd3, 0x0e, 0x29, 0xfb, 0x59, 0x67, 0x52, 0xfe, 0x42, - 0x5b, 0x84, 0x11, 0x45, 0xa8, 0xae, 0x43, 0xcc, 0xb6, 0xa5, 0x1f, 0x84, 0x13, 0x70, 0xdc, 0x85, 0xd2, 0xf1, 0x01, - 0x5f, 0x52, 0x81, 0x08, 0xb9, 0x16, 0xe2, 0x6e, 0xd3, 0xd0, 0xb2, 0x82, 0xb7, 0xcd, 0x86, 0xd4, 0x4d, 0x3a, 0x7a, - 0x03, 0xaf, 0xe8, 0x66, 0xdd, 0xcb, 0xf4, 0x00, 0x64, 0x3c, 0x9a, 0x89, 0x81, 0x33, 0x6e, 0xdf, 0xde, 0x76, 0x2e, - 0x4d, 0x98, 0x17, 0x9d, 0x6c, 0x06, 0xaf, 0xe6, 0xc6, 0x9d, 0xb5, 0x0b, 0x67, 0xe3, 0xc3, 0x86, 0x66, 0x9b, 0xc7, - 0x1b, 0x6d, 0x1f, 0x66, 0xd7, 0xb3, 0xae, 0x5e, 0x96, 0x79, 0x99, 0x3e, 0xeb, 0xbb, 0x93, 0x5b, 0x35, 0x7f, 0x86, - 0x68, 0xb0, 0x19, 0xc8, 0x4c, 0x31, 0x49, 0xc2, 0x00, 0x30, 0x5a, 0x70, 0x7b, 0x13, 0xcd, 0xa0, 0x0b, 0x18, 0x28, - 0x4b, 0x93, 0xee, 0xe6, 0x8a, 0xe3, 0x97, 0x79, 0xaf, 0x54, 0xed, 0x85, 0x1b, 0x24, 0x0a, 0x4e, 0x83, 0xfd, 0x27, - 0x7e, 0xf7, 0x1f, 0x45, 0xdc, 0xcc, 0xf0, 0x95, 0x04, 0xa0, 0xb5, 0x60, 0xe1, 0x71, 0x62, 0x8b, 0xcd, 0xb2, 0x06, - 0x92, 0x52, 0x8b, 0xca, 0x7f, 0xd0, 0xf8, 0x51, 0x41, 0x5e, 0x9d, 0x6e, 0x0e, 0x31, 0xe0, 0x18, 0x8d, 0xda, 0x32, - 0xfd, 0xb8, 0x29, 0xc9, 0x70, 0x8a, 0x36, 0xb9, 0x8c, 0x68, 0x3e, 0x21, 0x1b, 0x0e, 0x01, 0x00, 0x4a, 0x95, 0x61, - 0x8d, 0xa4, 0x57, 0x93, 0xc4, 0xad, 0x0c, 0x47, 0x18, 0xa9, 0x02, 0xa3, 0x6f, 0xd6, 0x98, 0x5a, 0x08, 0xb5, 0x38, - 0x12, 0xc6, 0x76, 0x06, 0x29, 0xc7, 0xc0, 0x1c, 0xc4, 0x15, 0xf0, 0xec, 0xe4, 0x93, 0xda, 0x93, 0x96, 0x25, 0x14, - 0xfb, 0x4e, 0xc9, 0xd9, 0x6b, 0x3a, 0x28, 0x60, 0xd4, 0x75, 0xde, 0x86, 0xd3, 0x3c, 0x23, 0x4c, 0xf9, 0xd2, 0x8f, - 0xfe, 0x60, 0xdb, 0x03, 0xcf, 0x10, 0xaa, 0x02, 0xe1, 0xe3, 0x5c, 0x4d, 0x45, 0x54, 0xaa, 0x9c, 0x8b, 0xb4, 0xfd, - 0xf1, 0x88, 0x24, 0xdb, 0xc4, 0x7f, 0x40, 0x2c, 0xa5, 0x40, 0xf1, 0xf7, 0x9d, 0x13, 0x4d, 0x96, 0x98, 0x25, 0xf9, - 0x52, 0x9d, 0x26, 0x79, 0xf3, 0x35, 0x9c, 0x63, 0x35, 0x15, 0xff, 0x19, 0xa2, 0xa0, 0x69, 0x20, 0x84, 0xd6, 0x5b, - 0x9a, 0x6d, 0x40, 0xe9, 0xd6, 0x99, 0x6d, 0xe1, 0x9c, 0x07, 0x3c, 0x03, 0xb8, 0x98, 0x6d, 0xc6, 0x5d, 0x2a, 0x8d, - 0xa8, 0xf5, 0xca, 0x40, 0xba, 0x9d, 0x02, 0x0e, 0x51, 0x5b, 0x1f, 0xcc, 0x0e, 0x45, 0xef, 0x82, 0x17, 0x4c, 0x7e, - 0x06, 0x1f, 0x0a, 0x2a, 0xb5, 0xa0, 0xdb, 0x8b, 0xd9, 0x97, 0xd4, 0xa8, 0xca, 0x4b, 0xb3, 0xa1, 0xb6, 0xce, 0x5f, - 0x6b, 0x31, 0xe5, 0x2e, 0x00, 0x9d, 0xd0, 0x86, 0xad, 0x43, 0x06, 0x9e, 0xac, 0xe9, 0x53, 0x6e, 0x9a, 0x71, 0xc9, - 0xbe, 0x28, 0xc3, 0xdc, 0x8f, 0x88, 0xcd, 0xd8, 0xf7, 0xbe, 0x49, 0xad, 0xf9, 0x39, 0x87, 0xa7, 0xd6, 0xd5, 0x5a, - 0xc1, 0xd8, 0x3a, 0x7d, 0xd9, 0x38, 0x8a, 0x57, 0xf5, 0x4f, 0x80, 0x77, 0xf1, 0x79, 0xcd, 0xc8, 0xf4, 0xb5, 0x38, - 0x34, 0x22, 0x14, 0xb9, 0xde, 0x30, 0x04, 0x66, 0x22, 0x0c, 0xaf, 0xbb, 0x0b, 0xc1, 0xf4, 0xba, 0x52, 0x90, 0xe0, - 0xe0, 0xc6, 0x52, 0xec, 0x37, 0x7a, 0x7e, 0x65, 0xff, 0x50, 0x44, 0x43, 0x33, 0x15, 0xc0, 0x67, 0x33, 0x09, 0xd1, - 0x8f, 0x33, 0xb3, 0xe1, 0xc9, 0x83, 0xed, 0x6d, 0x44, 0x6d, 0x22, 0x81, 0x49, 0xe2, 0x32, 0x24, 0x51, 0xde, 0x25, - 0x5a, 0x90, 0xba, 0x84, 0xeb, 0x4f, 0x23, 0xf3, 0x4d, 0xa9, 0xca, 0x7c, 0x45, 0xe2, 0x5b, 0xd3, 0xb8, 0x7f, 0x08, - 0xa7, 0x79, 0x7d, 0x75, 0xfb, 0xbc, 0x65, 0xdd, 0x97, 0x7b, 0xb0, 0x95, 0x85, 0xff, 0x42, 0xdb, 0x98, 0xba, 0x6a, - 0x9d, 0x2e, 0x27, 0x62, 0xfc, 0x25, 0xea, 0x65, 0xec, 0x60, 0xbc, 0xed, 0x37, 0xb8, 0xd5, 0x08, 0x53, 0x7b, 0xf3, - 0x6b, 0x8e, 0x4c, 0x3d, 0x48, 0xdd, 0x00, 0x0d, 0x2b, 0x76, 0xa9, 0xca, 0x52, 0x5b, 0xfe, 0xd9, 0xad, 0xe7, 0x3b, - 0x19, 0x8e, 0x0e, 0x9f, 0x43, 0x1a, 0xf3, 0x5d, 0x6f, 0xbe, 0x79, 0xcd, 0xa4, 0x67, 0x9d, 0x46, 0x11, 0xdd, 0x8a, - 0x61, 0x3b, 0x46, 0x87, 0x43, 0x52, 0xb8, 0x2b, 0x49, 0x35, 0xc1, 0x3e, 0x51, 0x54, 0x8e, 0x06, 0x42, 0x18, 0x30, - 0xb1, 0x27, 0x61, 0xbb, 0x2f, 0x14, 0x70, 0xda, 0xd0, 0xbd, 0xab, 0x0e, 0x54, 0x42, 0x89, 0x8c, 0xbd, 0xac, 0xc6, - 0x37, 0xa5, 0x8a, 0x7c, 0x88, 0x57, 0xf0, 0xb0, 0xf4, 0x9a, 0x72, 0x97, 0x0c, 0x20, 0xf7, 0xea, 0xf4, 0xe6, 0x9f, - 0xb3, 0x7b, 0xee, 0xb3, 0x90, 0x6f, 0x7c, 0xed, 0xaf, 0x76, 0xdf, 0x5f, 0xe8, 0x60, 0x5e, 0xc1, 0x2a, 0xee, 0x5f, - 0xfe, 0x50, 0x29, 0x0a, 0x35, 0xea, 0x07, 0x79, 0x60, 0x7b, 0xe9, 0x71, 0x53, 0x16, 0xd6, 0x02, 0x13, 0x72, 0xe5, - 0xcd, 0x99, 0x06, 0xc2, 0x38, 0x8e, 0x7f, 0xcd, 0x29, 0xa4, 0x6c, 0xdc, 0x9c, 0x3c, 0xe3, 0xd1, 0x58, 0x11, 0xea, - 0x50, 0x97, 0x9b, 0x79, 0xd7, 0x71, 0x46, 0x8e, 0xbb, 0xa6, 0xe8, 0x8f, 0xe6, 0xe2, 0x5f, 0xcd, 0x3e, 0x43, 0xf8, - 0x15, 0x70, 0x3a, 0xe0, 0x3a, 0x65, 0xc6, 0x2e, 0x18, 0xed, 0x2e, 0x49, 0xc3, 0xc3, 0xc7, 0x76, 0xb0, 0xb5, 0xff, - 0xf1, 0xda, 0x83, 0x8a, 0x08, 0x21, 0x87, 0x9f, 0x1d, 0x3a, 0x39, 0xe8, 0xc3, 0xaa, 0x72, 0x7a, 0xd1, 0x17, 0x2c, - 0x2b, 0xd8, 0x42, 0x0d, 0x30, 0x25, 0xe8, 0x7e, 0x85, 0x96, 0x17, 0xbb, 0xa6, 0x7f, 0x78, 0xe6, 0xf3, 0x2c, 0xf2, - 0xc1, 0x02, 0x7e, 0x77, 0xa8, 0x92, 0x47, 0x6d, 0x2c, 0x5f, 0x68, 0xc9, 0xb7, 0x86, 0x14, 0x18, 0x55, 0x90, 0x36, - 0xc4, 0xc3, 0x51, 0x75, 0x39, 0x17, 0x5c, 0xa0, 0xfa, 0xd1, 0xa3, 0xb8, 0x4c, 0x51, 0x00, 0x58, 0xae, 0xb4, 0x40, - 0x38, 0x1f, 0x20, 0x42, 0xa1, 0x61, 0x35, 0x09, 0x99, 0x7e, 0x9e, 0xed, 0xa6, 0x06, 0xa1, 0xf1, 0xbe, 0xb4, 0xf6, - 0x23, 0xca, 0xc8, 0x9c, 0xa2, 0x29, 0x5d, 0xa5, 0xb6, 0x19, 0xf2, 0xc0, 0xb7, 0xb4, 0x2c, 0x00, 0x46, 0x4b, 0x24, - 0x1f, 0x36, 0x16, 0x91, 0xb5, 0xaf, 0xe7, 0x84, 0xbb, 0xcc, 0x7e, 0xf4, 0x4d, 0xcd, 0x2f, 0xb6, 0x4d, 0x83, 0xf3, - 0x87, 0xc8, 0x75, 0xee, 0x06, 0xc9, 0xc6, 0x26, 0x5e, 0xb9, 0x8d, 0x6f, 0x47, 0xf4, 0x87, 0x76, 0x59, 0x7f, 0xcb, - 0x30, 0x01, 0x75, 0x26, 0x2d, 0xe1, 0x1a, 0x80, 0x72, 0x18, 0xc2, 0xd3, 0x38, 0x14, 0x2f, 0x97, 0x3c, 0x44, 0x13, - 0x8d, 0x04, 0x4a, 0x60, 0x85, 0x37, 0xec, 0xa2, 0xaa, 0x7e, 0x3d, 0xf0, 0xff, 0x1b, 0x68, 0xaa, 0xfa, 0x36, 0xb3, - 0xd4, 0x4d, 0x4b, 0x40, 0xdb, 0x86, 0x04, 0xab, 0xa0, 0xc2, 0x11, 0xb6, 0x96, 0xa4, 0x32, 0x18, 0xb6, 0x9e, 0x7c, - 0xd8, 0x10, 0xb1, 0x99, 0x8c, 0x33, 0xad, 0xdf, 0x0e, 0x33, 0xdb, 0x2f, 0x05, 0xde, 0x10, 0x8b, 0xc6, 0x5c, 0xd4, - 0xb8, 0xf6, 0x34, 0x42, 0x20, 0x13, 0xa4, 0xd1, 0x9d, 0xd1, 0xd6, 0xc5, 0xf8, 0xda, 0xba, 0x24, 0x9f, 0x91, 0x75, - 0x72, 0xba, 0xc3, 0x07, 0x03, 0x21, 0xee, 0xa3, 0x5c, 0x30, 0xa3, 0xd4, 0x56, 0xe2, 0x6a, 0x88, 0x65, 0xd1, 0x4e, - 0x64, 0x11, 0x00, 0x23, 0xc0, 0xfe, 0x60, 0x5e, 0x6b, 0xd2, 0xe4, 0x0d, 0xe1, 0xcb, 0xd5, 0x38, 0x1d, 0x6b, 0xfd, - 0x36, 0x2c, 0x9b, 0x0e, 0x4c, 0xe1, 0x7a, 0x58, 0x9d, 0xc6, 0xb3, 0xf7, 0x6a, 0x8b, 0xd1, 0x9f, 0xf7, 0xe8, 0x05, - 0xbc, 0x41, 0x90, 0xc1, 0xa9, 0x98, 0x6c, 0x69, 0x7c, 0xd8, 0x43, 0xbc, 0x90, 0xea, 0x7c, 0x10, 0xb4, 0x1d, 0xd5, - 0x1e, 0x50, 0xce, 0x5f, 0x0b, 0xd4, 0x7d, 0x24, 0x3c, 0x13, 0x20, 0x23, 0x05, 0xe5, 0x89, 0xd6, 0xa7, 0xe8, 0xa1, - 0x07, 0x3e, 0xe9, 0xea, 0x9a, 0xb5, 0xa0, 0x93, 0x20, 0xd1, 0x10, 0x27, 0x27, 0x31, 0xfa, 0xe6, 0xc5, 0x03, 0x08, - 0xd2, 0x72, 0x4d, 0x86, 0xd2, 0x42, 0x1b, 0xc5, 0x19, 0x9b, 0xc4, 0x14, 0xd6, 0xff, 0xdc, 0x4e, 0x73, 0xa4, 0xe1, - 0xe0, 0x12, 0x25, 0x6f, 0x35, 0x91, 0x42, 0x82, 0x75, 0x52, 0x27, 0xbd, 0x9f, 0xb0, 0x1b, 0xdc, 0xf5, 0x8e, 0x0f, - 0x25, 0x11, 0x82, 0x09, 0xa1, 0x90, 0x9f, 0x96, 0xe1, 0xfc, 0x51, 0xe0, 0x37, 0x35, 0x0a, 0xce, 0x78, 0x5c, 0xc9, - 0x86, 0xa0, 0xd0, 0xef, 0xd9, 0x83, 0x5d, 0x38, 0x41, 0xd8, 0x74, 0xf8, 0xd0, 0x95, 0xb2, 0x0c, 0x82, 0x94, 0xde, - 0xeb, 0xbc, 0x0d, 0x15, 0xc9, 0x04, 0xd4, 0x42, 0xbb, 0x1e, 0x67, 0x15, 0x76, 0x73, 0x84, 0x7e, 0x2b, 0x36, 0xf8, - 0xb2, 0xb3, 0x05, 0x04, 0xd7, 0xd0, 0xc2, 0xe0, 0xa2, 0x42, 0x66, 0xb7, 0x88, 0x9e, 0x60, 0x72, 0x16, 0xb9, 0xc3, - 0x97, 0xb4, 0x50, 0xb9, 0x64, 0x25, 0x3d, 0x97, 0x3e, 0xf8, 0x5d, 0x76, 0xb4, 0x8a, 0x1b, 0x67, 0x6d, 0x94, 0x6a, - 0x74, 0x8b, 0x99, 0xef, 0x1f, 0x31, 0xc7, 0x25, 0xb1, 0x51, 0x0b, 0x2e, 0x19, 0xba, 0x32, 0x65, 0x29, 0x0b, 0x1c, - 0x71, 0x20, 0x82, 0xba, 0xcd, 0x77, 0xc4, 0x2b, 0xaa, 0x3b, 0xd9, 0x6b, 0x83, 0x0d, 0x5a, 0x87, 0xac, 0x95, 0xc2, - 0x9b, 0xb4, 0x42, 0x17, 0xb1, 0x8a, 0x19, 0xb8, 0x1c, 0x6f, 0xbf, 0x34, 0x19, 0xa0, 0x9b, 0x23, 0x71, 0xe7, 0x74, - 0x06, 0x45, 0x66, 0x78, 0xd1, 0xbf, 0x92, 0x56, 0x69, 0x50, 0xd6, 0x5b, 0xc9, 0x61, 0xac, 0xa3, 0xf9, 0x61, 0xb8, - 0xbf, 0x8a, 0x5f, 0xd3, 0x1d, 0xe5, 0xbf, 0x55, 0x7f, 0x39, 0x50, 0x55, 0x5e, 0x68, 0x15, 0x87, 0x6a, 0x1b, 0x27, - 0x21, 0xa1, 0x9f, 0x6c, 0xdf, 0xb7, 0xef, 0xbf, 0x19, 0x71, 0x8d, 0x5b, 0xda, 0x38, 0xdc, 0x6b, 0x71, 0xd0, 0xa2, - 0xbc, 0xff, 0x0f, 0xa5, 0x99, 0x01, 0x6c, 0xd2, 0xa1, 0x19, 0x32, 0x57, 0x1e, 0x7d, 0xa5, 0x5f, 0x8d, 0x19, 0x09, - 0x33, 0x7b, 0xcd, 0x18, 0xe3, 0xb5, 0xef, 0xfe, 0x9e, 0xa2, 0x85, 0x45, 0x93, 0x3c, 0x39, 0x2f, 0x05, 0xe3, 0xaa, - 0x2e, 0x7e, 0x76, 0xc7, 0x93, 0xf0, 0x3f, 0xa8, 0xda, 0xbe, 0x3c, 0x08, 0x31, 0x77, 0x3d, 0x85, 0x68, 0x83, 0x59, - 0xf2, 0x29, 0x6f, 0x7a, 0xba, 0xc6, 0x92, 0xc6, 0x4f, 0x66, 0xe5, 0xba, 0x75, 0xcd, 0x4e, 0x02, 0x60, 0xdc, 0x1f, - 0x9b, 0x3f, 0x2c, 0x2a, 0xf4, 0xed, 0x66, 0x2a, 0x81, 0xaf, 0x0c, 0xb3, 0x79, 0x9f, 0x05, 0xe0, 0x6f, 0x70, 0x96, - 0xd3, 0x72, 0x9e, 0x5a, 0x52, 0x3c, 0xf5, 0x4b, 0x6c, 0xd5, 0xaf, 0x1c, 0xd9, 0x50, 0x1e, 0x7f, 0xdd, 0xb0, 0x12, - 0xa8, 0xb8, 0x1b, 0x98, 0x60, 0xfa, 0xf7, 0xc9, 0xc8, 0x71, 0x14, 0x36, 0xb6, 0x51, 0x40, 0x56, 0x1f, 0x6f, 0x7e, - 0x3f, 0xcb, 0x36, 0xfc, 0xe3, 0x71, 0xb2, 0x6e, 0x20, 0x50, 0x83, 0x45, 0xd6, 0xdd, 0xf5, 0x9e, 0x05, 0x48, 0x65, - 0x77, 0x2b, 0xea, 0x8b, 0xc3, 0xd0, 0x7f, 0xfc, 0xdc, 0x19, 0xd5, 0xbb, 0x70, 0x8e, 0x71, 0x84, 0xd4, 0x2f, 0x61, - 0x7f, 0xff, 0x64, 0xd2, 0x2f, 0xcf, 0x9c, 0xff, 0x24, 0xea, 0x17, 0xa9, 0x7a, 0x43, 0x17, 0x12, 0xc7, 0x3e, 0x6c, - 0x7e, 0x9a, 0x23, 0x0f, 0x76, 0x3e, 0xcf, 0x44, 0x6a, 0xac, 0xc7, 0x52, 0x1d, 0x57, 0xc9, 0xca, 0x0f, 0x3e, 0x5c, - 0x6a, 0x5f, 0x2c, 0x59, 0x5a, 0xed, 0x5e, 0xd1, 0xf7, 0x68, 0x6e, 0xa0, 0xf5, 0xd8, 0x07, 0xef, 0xa6, 0x4f, 0xb5, - 0xfb, 0x18, 0xdd, 0x3d, 0xbd, 0x92, 0x38, 0xdb, 0x2a, 0x4d, 0x6c, 0xe1, 0xb3, 0xa3, 0xd7, 0x89, 0xb4, 0x14, 0x5a, - 0x19, 0x61, 0x7a, 0xca, 0x1e, 0xc1, 0x12, 0x24, 0x4b, 0xab, 0xde, 0xb1, 0x6b, 0x2e, 0xd2, 0x98, 0xfe, 0xf4, 0xc4, - 0x4a, 0x8f, 0x7b, 0xcd, 0x6a, 0x7a, 0x98, 0x5f, 0x19, 0x33, 0xe3, 0x0c, 0x09, 0x9e, 0x42, 0x24, 0xa0, 0xb3, 0x05, - 0xe5, 0x13, 0x4d, 0x66, 0x25, 0xac, 0xbe, 0x3a, 0x53, 0x82, 0x30, 0x2b, 0x1b, 0x77, 0x29, 0x67, 0xda, 0xe8, 0x34, - 0xc7, 0x72, 0x5d, 0x3a, 0x8f, 0xcb, 0xd5, 0x71, 0x50, 0xff, 0xa6, 0x43, 0x18, 0xce, 0x36, 0x9c, 0x1f, 0xa9, 0x9e, - 0x18, 0x25, 0x5f, 0x90, 0x7f, 0x11, 0x2a, 0xd8, 0xa8, 0xbe, 0x79, 0x82, 0x0e, 0x64, 0x52, 0xef, 0x8f, 0xdf, 0xed, - 0x8f, 0xef, 0x61, 0x0c, 0xc3, 0x36, 0x68, 0x2b, 0x28, 0x55, 0x45, 0xb9, 0x14, 0x6d, 0x9c, 0x77, 0x3d, 0x2e, 0xbb, - 0xfc, 0xa6, 0x0f, 0x34, 0xfa, 0xe5, 0x79, 0xe7, 0x5a, 0x5a, 0x7a, 0x44, 0xa6, 0x5e, 0x24, 0x0a, 0x31, 0xd6, 0x52, - 0x78, 0xb3, 0x74, 0xa2, 0xe2, 0x80, 0xe1, 0xae, 0xc9, 0xc8, 0x33, 0x73, 0xc6, 0x6e, 0x25, 0xed, 0x08, 0x16, 0x86, - 0x75, 0xd3, 0xb5, 0x94, 0x64, 0x99, 0xf5, 0xe9, 0x5e, 0x9d, 0x08, 0x2b, 0x38, 0xbc, 0x11, 0xdb, 0x13, 0xd2, 0xfc, - 0x69, 0x22, 0x99, 0x93, 0xd7, 0xfb, 0x12, 0x30, 0x4b, 0x5c, 0x3a, 0x9b, 0x7c, 0x46, 0x9a, 0xe2, 0x5f, 0x07, 0x95, - 0xe9, 0x8b, 0x6f, 0xac, 0x26, 0xd4, 0xbe, 0x4a, 0x56, 0xa9, 0x38, 0xc7, 0x17, 0x14, 0x29, 0xf6, 0x8c, 0xf6, 0x4c, - 0x76, 0xe8, 0x46, 0x63, 0x6f, 0x73, 0x4f, 0x29, 0xa4, 0xcc, 0x62, 0xdf, 0x4b, 0xd0, 0xbf, 0x22, 0xcc, 0x30, 0x09, - 0x4a, 0xf0, 0xf2, 0x3f, 0xe0, 0xc6, 0x1c, 0x38, 0xa2, 0xde, 0x3b, 0x8f, 0x89, 0x45, 0x0b, 0x75, 0xe8, 0x86, 0x0c, - 0xab, 0x74, 0x22, 0x7e, 0xbd, 0x44, 0xd1, 0xb4, 0x0f, 0x6b, 0x84, 0x79, 0xe1, 0x2b, 0xed, 0x6f, 0x13, 0x01, 0x34, - 0x08, 0x4b, 0x43, 0x0c, 0xec, 0xea, 0x26, 0x6d, 0x61, 0xb8, 0xd5, 0x13, 0x68, 0x0a, 0x17, 0xaf, 0xe9, 0x78, 0xfa, - 0x5a, 0xa4, 0x13, 0x4a, 0x7a, 0x94, 0x8b, 0xc9, 0xb1, 0x16, 0xcb, 0x31, 0x7b, 0x2c, 0x7f, 0x27, 0xd7, 0xcb, 0xb3, - 0x08, 0x4d, 0x4f, 0x05, 0x16, 0x39, 0x08, 0x9c, 0x71, 0x69, 0xa5, 0x54, 0xef, 0x30, 0x78, 0x99, 0x99, 0x28, 0xfc, - 0x40, 0x5e, 0x06, 0x0b, 0xa5, 0x93, 0x1f, 0xb4, 0xea, 0xef, 0x3d, 0x45, 0x61, 0xf6, 0xf4, 0x10, 0x45, 0xc7, 0xa8, - 0xb3, 0xbb, 0x8e, 0x41, 0xf5, 0xa7, 0x35, 0xf5, 0x6b, 0xf8, 0x05, 0xa3, 0x0b, 0x24, 0x32, 0x73, 0x0c, 0x24, 0x8f, - 0xc0, 0x1f, 0xef, 0xb0, 0xc9, 0x7d, 0xe6, 0x6c, 0x87, 0xe4, 0xf1, 0xea, 0x6d, 0xc5, 0x01, 0x5d, 0x32, 0x56, 0x4b, - 0x1e, 0xa2, 0xf6, 0xaa, 0x96, 0xf5, 0xa7, 0xe5, 0x98, 0x77, 0x0b, 0xb7, 0xa3, 0xc7, 0x53, 0x1c, 0xb0, 0xbd, 0xdf, - 0x9d, 0x09, 0x8b, 0x43, 0x9c, 0x1f, 0x1b, 0xd5, 0xed, 0x18, 0x5d, 0x96, 0x01, 0x3e, 0xad, 0x0f, 0xb4, 0x41, 0x10, - 0xd7, 0x67, 0x07, 0xaa, 0x3b, 0xf7, 0x15, 0x2f, 0x4c, 0x8f, 0xd7, 0x24, 0x94, 0x96, 0xf2, 0x64, 0x6c, 0xc8, 0x3a, - 0x80, 0xa2, 0x51, 0xcc, 0x51, 0x10, 0xa2, 0x08, 0x10, 0x72, 0x48, 0x49, 0xf2, 0x6a, 0x0f, 0x40, 0x11, 0x6b, 0xa1, - 0x72, 0xd0, 0x1c, 0xf7, 0x7e, 0x10, 0xc4, 0x30, 0x63, 0xfa, 0x0f, 0xf1, 0x43, 0x78, 0xb6, 0xc3, 0x32, 0x96, 0x19, - 0xaf, 0x71, 0x95, 0xae, 0xcf, 0x81, 0x72, 0xe9, 0xe6, 0xad, 0xfa, 0x4d, 0x4f, 0x80, 0x69, 0x7d, 0x16, 0x84, 0x2d, - 0x22, 0x77, 0x09, 0x42, 0x64, 0xd7, 0x05, 0x7a, 0xf5, 0x40, 0xb6, 0x3b, 0xf4, 0x43, 0xaf, 0x20, 0x52, 0xfa, 0x5a, - 0x10, 0x7e, 0x45, 0x7e, 0x10, 0x16, 0x3c, 0xdf, 0x50, 0x94, 0x06, 0x88, 0x9e, 0x42, 0xad, 0x3b, 0x7d, 0xab, 0xe2, - 0x1c, 0x3b, 0xa8, 0xdb, 0xcc, 0xc2, 0xf6, 0xa7, 0x13, 0xf1, 0xb1, 0xac, 0x8b, 0x97, 0x74, 0xe9, 0xae, 0xde, 0xb7, - 0x0c, 0x7b, 0x00, 0xc4, 0x52, 0x85, 0x9d, 0xa1, 0x12, 0x81, 0xaf, 0xf3, 0x82, 0x87, 0x14, 0xbd, 0x4a, 0xb6, 0xf7, - 0xdd, 0xef, 0xbd, 0x42, 0x47, 0x7c, 0xd9, 0x16, 0x7d, 0xc2, 0x57, 0xd5, 0x24, 0x5e, 0x5f, 0xd9, 0x2b, 0xf7, 0xb6, - 0xea, 0xf9, 0xf3, 0x61, 0x14, 0x67, 0xf1, 0x8e, 0xa6, 0x4b, 0x8d, 0xde, 0x27, 0xab, 0xbf, 0x03, 0xb5, 0xa8, 0x7d, - 0x97, 0xe8, 0xf4, 0x72, 0xe4, 0x98, 0xf9, 0xa2, 0xa4, 0x69, 0xdd, 0xe1, 0x34, 0x7f, 0x95, 0x59, 0x8f, 0xaf, 0xf4, - 0x9c, 0x59, 0xcd, 0xf4, 0xc1, 0xcf, 0x54, 0xdb, 0x73, 0x19, 0x00, 0x5b, 0xc7, 0xa7, 0xcf, 0xc7, 0xbd, 0x0d, 0xab, - 0xd5, 0x17, 0xfd, 0x88, 0x75, 0xd1, 0x0d, 0x3d, 0xd7, 0x13, 0x84, 0xf4, 0x9c, 0xee, 0x1d, 0x58, 0xa5, 0x1f, 0x1b, - 0x29, 0xfa, 0x36, 0xc5, 0xbe, 0x67, 0x45, 0x2e, 0x48, 0xc7, 0xae, 0x7a, 0xc3, 0x6d, 0x16, 0xfa, 0x66, 0xda, 0x52, - 0x5f, 0xd4, 0xa8, 0x6d, 0x89, 0xcf, 0x67, 0xa9, 0x64, 0x22, 0xea, 0x17, 0x37, 0x5c, 0x59, 0xdf, 0x79, 0x07, 0xc9, - 0x6a, 0x95, 0xc0, 0x5d, 0x91, 0x5c, 0xe9, 0xd2, 0x7f, 0x1f, 0x46, 0xcf, 0x53, 0x0e, 0xab, 0xa5, 0x9c, 0xa6, 0xa7, - 0xa8, 0xec, 0x8d, 0x9d, 0x94, 0xf9, 0x49, 0xf2, 0xef, 0xfc, 0xf0, 0x64, 0xb1, 0x9b, 0x18, 0xf5, 0xf9, 0x88, 0xd7, - 0xf9, 0xfb, 0x2a, 0x63, 0x14, 0xc4, 0xd0, 0xee, 0xab, 0x9c, 0x26, 0x6d, 0x95, 0xf8, 0xd8, 0x7b, 0x45, 0xb1, 0xc9, - 0xf2, 0xe8, 0xa9, 0xc2, 0x24, 0xf8, 0x69, 0x44, 0xce, 0xfc, 0x5c, 0x4d, 0xc2, 0xc4, 0x78, 0xba, 0xb4, 0xfa, 0x1e, - 0x9e, 0xba, 0x0b, 0x67, 0xbd, 0xc7, 0x08, 0x69, 0x8c, 0xff, 0x39, 0x66, 0x58, 0xe2, 0xd5, 0x99, 0xe5, 0xdb, 0xe0, - 0xc6, 0x74, 0x58, 0x4a, 0x1a, 0xce, 0x71, 0x30, 0xa1, 0x1b, 0x8c, 0x7a, 0xab, 0x04, 0x35, 0x54, 0x84, 0x83, 0x02, - 0x22, 0xfb, 0x88, 0x66, 0x51, 0x56, 0x24, 0x40, 0x91, 0x69, 0xf1, 0xb7, 0x39, 0xb6, 0xc8, 0x0f, 0x2d, 0xf6, 0xcb, - 0xf2, 0xbd, 0xbe, 0x0a, 0xa2, 0xfe, 0x36, 0x01, 0x45, 0xa8, 0x0d, 0x59, 0x9b, 0x80, 0x29, 0x44, 0x31, 0x35, 0xc1, - 0xa7, 0x05, 0x45, 0xa1, 0x32, 0xf1, 0x2a, 0x6c, 0x0d, 0x16, 0x0e, 0xb5, 0xb4, 0xa8, 0x35, 0xe9, 0xbc, 0x05, 0xe4, - 0x68, 0xbf, 0x75, 0xf1, 0x5c, 0x76, 0x6a, 0x3c, 0x4c, 0xaa, 0x3d, 0x24, 0x22, 0xc1, 0x3c, 0xce, 0x46, 0xc0, 0x6e, - 0xf3, 0x29, 0xbe, 0x14, 0xd0, 0x64, 0x49, 0xdd, 0xc5, 0x6f, 0xba, 0xed, 0x04, 0x54, 0x46, 0x2b, 0x0d, 0x05, 0x09, - 0xdf, 0x1d, 0x8d, 0x07, 0xaa, 0x0a, 0xd9, 0x65, 0xbc, 0xc3, 0x25, 0x37, 0x22, 0xcc, 0x52, 0x74, 0x87, 0x5f, 0x92, - 0xfe, 0xdd, 0x51, 0x99, 0x93, 0x9d, 0xd6, 0xb4, 0x77, 0x1b, 0x06, 0x5f, 0xc4, 0xe8, 0xcc, 0x00, 0x47, 0xf6, 0x3a, - 0xc0, 0x06, 0xce, 0x63, 0x84, 0x09, 0x38, 0x5e, 0x54, 0x64, 0xb2, 0xce, 0x2f, 0xd9, 0xbd, 0xb8, 0xca, 0x1c, 0x1c, - 0x08, 0x51, 0x0b, 0x3f, 0xe0, 0x46, 0x0b, 0xc8, 0x70, 0x30, 0x4b, 0xe8, 0xb1, 0x50, 0x3c, 0x37, 0x00, 0xef, 0x95, - 0x36, 0x90, 0x80, 0xdc, 0xec, 0x49, 0x01, 0xc9, 0xfc, 0x85, 0x59, 0x03, 0xc2, 0x87, 0x64, 0x26, 0x73, 0x72, 0x06, - 0xa5, 0xc4, 0x1a, 0x00, 0x45, 0xc8, 0x2c, 0x00, 0x9f, 0x35, 0xef, 0x37, 0x6f, 0x5f, 0x4e, 0x15, 0x3b, 0x1d, 0x80, - 0x7f, 0x50, 0x8a, 0x4c, 0x6e, 0x46, 0x42, 0x19, 0x38, 0xbf, 0x00, 0x93, 0x0d, 0x58, 0xfd, 0x18, 0x86, 0xdf, 0xf5, - 0x0c, 0x23, 0x97, 0xd1, 0xc2, 0xea, 0x42, 0x52, 0x94, 0xee, 0xad, 0x0b, 0x91, 0x2a, 0x65, 0x33, 0x6a, 0x43, 0x86, - 0x2d, 0xf8, 0x3c, 0x55, 0x9f, 0x78, 0xad, 0x4c, 0x8e, 0x9a, 0x85, 0xcd, 0x3a, 0xb1, 0x85, 0x4c, 0x58, 0x9c, 0x26, - 0xe7, 0xe6, 0x2d, 0x4f, 0xb3, 0x88, 0x57, 0x2e, 0x49, 0x93, 0x96, 0x45, 0x85, 0xd8, 0xc6, 0x4c, 0x95, 0x0d, 0x7f, - 0x72, 0x9c, 0xc7, 0xb3, 0x01, 0x23, 0x7f, 0xb6, 0xa0, 0xeb, 0xed, 0x43, 0x2c, 0x12, 0x72, 0x56, 0x5b, 0xf3, 0xcd, - 0x2e, 0xb5, 0xcd, 0xbd, 0xb1, 0x73, 0xfa, 0xd8, 0xfa, 0xcb, 0x47, 0x32, 0x3b, 0x57, 0x54, 0x84, 0xdd, 0x71, 0x90, - 0x74, 0x89, 0xa9, 0x8a, 0x2b, 0xa7, 0x3e, 0x1b, 0x2e, 0x89, 0xf3, 0x1a, 0xdf, 0x5d, 0x82, 0x5d, 0xde, 0xe4, 0xff, - 0x92, 0xe2, 0xf8, 0x02, 0xb8, 0xa2, 0x08, 0x9c, 0x96, 0x5a, 0x28, 0xa2, 0x78, 0xca, 0x99, 0xe5, 0x16, 0x68, 0xd5, - 0x53, 0xb5, 0xb6, 0xd4, 0x5d, 0x31, 0xc2, 0xb3, 0xd8, 0x0a, 0x43, 0x20, 0xd3, 0x59, 0x90, 0xe5, 0x24, 0x36, 0x38, - 0xe8, 0x73, 0x41, 0x90, 0xcc, 0x85, 0x72, 0x37, 0xee, 0xb1, 0x8d, 0x35, 0x1b, 0x8c, 0x76, 0x96, 0x5a, 0x24, 0xe7, - 0x51, 0x91, 0xbd, 0x2f, 0x77, 0x0b, 0xf6, 0x6d, 0x07, 0x14, 0x25, 0x52, 0x59, 0xfa, 0x3a, 0x52, 0xc2, 0x63, 0xde, - 0xda, 0x4c, 0x23, 0x8c, 0x61, 0xc1, 0x8e, 0x36, 0xb6, 0xcd, 0x65, 0x48, 0x2c, 0x6b, 0x1b, 0x46, 0x95, 0xa1, 0xd9, - 0x88, 0x3c, 0x85, 0xf2, 0xa8, 0xbe, 0x09, 0xda, 0x90, 0x4a, 0xf6, 0xf0, 0xae, 0xa1, 0xb0, 0x48, 0xe9, 0x23, 0xd8, - 0xa2, 0xf9, 0x22, 0xd1, 0xed, 0x51, 0x63, 0x43, 0x76, 0xac, 0x92, 0x1c, 0xa6, 0xcb, 0x06, 0xe9, 0xf3, 0x28, 0x50, - 0xea, 0x2a, 0x91, 0x10, 0x14, 0x12, 0xe6, 0xd9, 0x1b, 0x3e, 0x35, 0x2d, 0xf7, 0x08, 0x08, 0x66, 0x9f, 0x57, 0xbd, - 0xa8, 0x1b, 0x21, 0xe2, 0x43, 0x11, 0x39, 0x7e, 0xaf, 0x1c, 0x86, 0xee, 0x6d, 0x2a, 0x86, 0x5b, 0x1b, 0x1f, 0x4f, - 0x92, 0x29, 0xd1, 0xb4, 0x43, 0xa4, 0x0b, 0x24, 0x56, 0x00, 0xb1, 0x2c, 0x9d, 0x4a, 0x50, 0x0a, 0x3d, 0x05, 0x3b, - 0x9e, 0x8f, 0x37, 0xe9, 0xb4, 0xc5, 0x48, 0x73, 0x59, 0x9a, 0xff, 0xe6, 0xc3, 0x30, 0x3d, 0x4d, 0xec, 0xae, 0xfe, - 0xc2, 0xfd, 0xdc, 0x7d, 0xb3, 0x61, 0x88, 0x62, 0x97, 0x6c, 0x10, 0x81, 0xf0, 0x77, 0xd1, 0xb4, 0xb0, 0x60, 0x2a, - 0xb4, 0x1b, 0xc7, 0xc6, 0x2f, 0x93, 0x61, 0xcf, 0x74, 0xba, 0x23, 0x50, 0xfc, 0x1a, 0x42, 0x87, 0x2b, 0xa0, 0x01, - 0x21, 0x50, 0x3f, 0x8b, 0x5c, 0x0b, 0xe3, 0xde, 0xe6, 0x3f, 0xa2, 0x98, 0x83, 0x01, 0x02, 0x39, 0x15, 0xe4, 0x5e, - 0x70, 0x46, 0x12, 0x67, 0x1d, 0x69, 0x59, 0x7f, 0xea, 0xba, 0x4d, 0xe9, 0xc8, 0xde, 0xb7, 0x82, 0x03, 0x45, 0x7b, - 0xb9, 0x95, 0xe9, 0x3f, 0x80, 0xbd, 0xb0, 0x2b, 0xcb, 0x7f, 0x3c, 0x17, 0x4d, 0x15, 0x19, 0xf5, 0xd4, 0x55, 0xf5, - 0x76, 0x64, 0xcc, 0x4c, 0x66, 0xe3, 0x91, 0x5f, 0x06, 0xed, 0xbe, 0x15, 0xc1, 0xc6, 0x2b, 0xd7, 0xf1, 0xf1, 0xc9, - 0xc8, 0x20, 0xb6, 0xab, 0x0b, 0xd5, 0x8c, 0x09, 0x44, 0x1e, 0xa6, 0xd2, 0x6e, 0x6c, 0xf3, 0x3a, 0xfd, 0xe4, 0x6e, - 0xfd, 0xf6, 0x9b, 0x54, 0x71, 0x6e, 0x85, 0x4d, 0x32, 0xdd, 0xc4, 0x0b, 0xf7, 0xdc, 0xef, 0xda, 0x66, 0xf3, 0xb6, - 0xdb, 0xa5, 0x88, 0xae, 0x6d, 0x04, 0x9d, 0x0f, 0xb5, 0xdd, 0x40, 0xe3, 0x67, 0xda, 0xc4, 0xd7, 0xf9, 0x4f, 0x55, - 0x03, 0x1d, 0xff, 0x89, 0x53, 0xb6, 0x45, 0x1c, 0xb5, 0xe5, 0x52, 0x0a, 0xdf, 0xe0, 0x2b, 0x13, 0xbe, 0x02, 0x77, - 0xe5, 0xc4, 0xf0, 0xec, 0x55, 0xe9, 0x6d, 0x67, 0x3f, 0xfa, 0xc9, 0x9a, 0x7a, 0x12, 0x83, 0xd2, 0x57, 0xc1, 0x3e, - 0x40, 0x5f, 0xa8, 0x1a, 0x22, 0x75, 0xf7, 0xee, 0x2b, 0x81, 0x13, 0x15, 0xe2, 0x3f, 0x08, 0x06, 0x46, 0x69, 0x53, - 0xaa, 0x5f, 0x6c, 0x1d, 0x31, 0xdb, 0x51, 0xe5, 0xb4, 0x7a, 0xd6, 0x07, 0x8f, 0x9f, 0x7b, 0xbf, 0xf9, 0x8f, 0xd4, - 0x3a, 0xc0, 0x2a, 0xab, 0xc3, 0x2f, 0xcb, 0x39, 0x6d, 0xbf, 0xd2, 0xcd, 0x85, 0x62, 0x7a, 0xa1, 0xf5, 0x26, 0x6e, - 0xbd, 0xce, 0xe6, 0xc3, 0xb9, 0x56, 0x84, 0x96, 0x97, 0xfa, 0xe2, 0xd3, 0xf3, 0xbf, 0x1d, 0x8d, 0x75, 0xbf, 0xb7, - 0xdd, 0x56, 0xaa, 0xf6, 0x36, 0x12, 0x46, 0xaa, 0xac, 0x77, 0x8c, 0x1d, 0xba, 0xc6, 0x78, 0x34, 0x86, 0x44, 0xb2, - 0x58, 0x9d, 0x02, 0x0e, 0x9d, 0x10, 0xf9, 0x3a, 0x89, 0x3b, 0x75, 0x12, 0xcd, 0x2c, 0x17, 0x41, 0x22, 0x45, 0xfa, - 0x36, 0x20, 0x6a, 0xe1, 0x90, 0x01, 0x0f, 0xe3, 0xd6, 0x64, 0x10, 0xd6, 0x75, 0x2c, 0x13, 0xa1, 0xda, 0xe1, 0xf5, - 0x29, 0xf5, 0x0a, 0x06, 0xd6, 0x14, 0x49, 0x1b, 0x89, 0x68, 0x4b, 0xdd, 0x7f, 0x35, 0xdd, 0x0f, 0xea, 0xcd, 0x8d, - 0xfd, 0x94, 0xb7, 0x51, 0x8b, 0xe6, 0x5e, 0xd4, 0x30, 0xac, 0x46, 0xd6, 0xcc, 0xb0, 0xcd, 0x23, 0xff, 0x23, 0x29, - 0x70, 0xe8, 0x3a, 0x00, 0xd0, 0x7e, 0x80, 0x36, 0x28, 0x86, 0x11, 0x98, 0xfd, 0xb8, 0x68, 0x23, 0xb5, 0x29, 0xbf, - 0x30, 0xab, 0x6e, 0x39, 0xb2, 0x5b, 0x04, 0x61, 0x4d, 0x96, 0x01, 0xe0, 0x2b, 0x1b, 0x6e, 0x03, 0x50, 0x34, 0x82, - 0xb2, 0xa9, 0x17, 0xb8, 0x2d, 0xfe, 0x1d, 0x9a, 0x35, 0x8f, 0x07, 0x45, 0xcf, 0x88, 0x0a, 0x2a, 0xcb, 0x08, 0xcf, - 0xbf, 0xba, 0x50, 0xae, 0xa4, 0xe1, 0x5b, 0x7a, 0x6e, 0x65, 0x6b, 0xce, 0x7b, 0xbb, 0x8a, 0xfe, 0xb9, 0x5d, 0xcf, - 0xaf, 0xd9, 0x06, 0xcb, 0x08, 0x8f, 0xdc, 0x7e, 0xf9, 0x91, 0x6e, 0xc2, 0xb1, 0x8f, 0x22, 0x3b, 0x2c, 0x4c, 0x41, - 0x70, 0xa8, 0x35, 0xda, 0x94, 0xfc, 0x62, 0x0f, 0x28, 0xcc, 0x1e, 0x36, 0x1c, 0x30, 0xd8, 0x54, 0x19, 0x26, 0x91, - 0x3d, 0x05, 0xbf, 0x6c, 0x83, 0x18, 0x4c, 0xa2, 0xa1, 0x24, 0xe0, 0xa6, 0x74, 0xcd, 0x09, 0xd9, 0x99, 0x53, 0xff, - 0x51, 0x23, 0xac, 0xe7, 0x09, 0x43, 0xd4, 0xc3, 0x34, 0xd3, 0xca, 0xaa, 0x59, 0x78, 0x6b, 0x58, 0xea, 0x1a, 0x82, - 0x94, 0xb2, 0x48, 0xe8, 0x7d, 0xeb, 0x04, 0xb5, 0x81, 0x09, 0xd3, 0x3d, 0x2a, 0xe3, 0xf0, 0x71, 0x9d, 0x16, 0x67, - 0xa2, 0x18, 0xad, 0xac, 0xd7, 0x18, 0xcb, 0xdc, 0x78, 0xcd, 0xcb, 0xa2, 0x99, 0x17, 0xbd, 0x3e, 0xd9, 0x90, 0xf0, - 0xfc, 0x39, 0x14, 0x89, 0x62, 0x63, 0x86, 0xda, 0x8d, 0xe7, 0xc4, 0xa7, 0xf9, 0x46, 0x53, 0x24, 0xb6, 0xf4, 0x9a, - 0x61, 0x25, 0xb3, 0x95, 0x30, 0xbd, 0x5a, 0x95, 0x19, 0xe1, 0xba, 0xc3, 0xb1, 0xcf, 0xf4, 0x70, 0x34, 0x05, 0x3f, - 0x02, 0x6c, 0xee, 0x74, 0xe4, 0xc6, 0xc3, 0xff, 0x01, 0xf2, 0xa8, 0xe6, 0xd1, 0x0a, 0xb9, 0x5c, 0x1e, 0x62, 0x13, - 0x0f, 0x35, 0xc7, 0xee, 0xaf, 0x61, 0xfd, 0xe7, 0x2d, 0xba, 0xa2, 0xed, 0x85, 0x56, 0x29, 0x91, 0x83, 0x36, 0xb1, - 0x2e, 0xdb, 0xc3, 0xa0, 0xb5, 0x88, 0x84, 0x13, 0x55, 0x9d, 0xf5, 0xc2, 0x3c, 0xce, 0xa5, 0xff, 0xc7, 0x4f, 0xb5, - 0x15, 0x04, 0x01, 0x61, 0x7e, 0x17, 0xbb, 0x13, 0x48, 0x71, 0x3e, 0x6b, 0xc8, 0x8c, 0x13, 0xfe, 0x95, 0x27, 0x7c, - 0x4f, 0x33, 0xb2, 0x92, 0xf9, 0x97, 0x32, 0x89, 0x4e, 0x71, 0xd5, 0x1c, 0xf1, 0x3a, 0x65, 0x0c, 0xa6, 0xb7, 0x0c, - 0x72, 0x2e, 0xc8, 0x67, 0x68, 0xca, 0xb9, 0x23, 0xeb, 0x4d, 0x81, 0xa7, 0x11, 0x18, 0x43, 0x01, 0xb2, 0x42, 0x57, - 0x99, 0x9d, 0x76, 0x86, 0x31, 0x30, 0xe4, 0x5e, 0x01, 0x1e, 0x5c, 0x09, 0xa0, 0x92, 0x81, 0x5f, 0xc5, 0x9e, 0x95, - 0x98, 0x7f, 0xb9, 0xa8, 0xd0, 0xee, 0x35, 0xc0, 0x5f, 0xa1, 0xe0, 0x12, 0xd5, 0x42, 0x81, 0x13, 0x01, 0x5d, 0x12, - 0x5c, 0xa0, 0x39, 0x89, 0x10, 0x5b, 0x0d, 0x08, 0x6a, 0x1b, 0xb7, 0x5c, 0x1c, 0xf0, 0xce, 0x7b, 0x59, 0xf1, 0xd5, - 0x75, 0x01, 0x1c, 0x0f, 0xf3, 0xfc, 0xdb, 0xca, 0x5c, 0xf6, 0x73, 0x02, 0x11, 0x17, 0x16, 0x66, 0x8e, 0x28, 0xe7, - 0xb4, 0x20, 0xcb, 0x5c, 0x84, 0x32, 0x5e, 0x6b, 0x98, 0xec, 0x84, 0xb3, 0x8c, 0xb4, 0xfb, 0xd0, 0x99, 0x48, 0x5f, - 0xbc, 0xcb, 0x20, 0xec, 0x90, 0xb5, 0x27, 0x52, 0xb9, 0x9d, 0x45, 0x13, 0xd0, 0xe7, 0x5b, 0x5f, 0xbb, 0xbe, 0xa7, - 0x8d, 0x35, 0x98, 0xbc, 0x6b, 0x36, 0x45, 0x0c, 0xa5, 0xf9, 0x62, 0x82, 0x99, 0xa7, 0xfd, 0x31, 0xcf, 0xc1, 0x22, - 0x7d, 0x99, 0xf4, 0xb2, 0x62, 0xa2, 0x3e, 0xb2, 0x83, 0x60, 0x91, 0x24, 0x86, 0xdc, 0x1a, 0x74, 0x14, 0x54, 0xe4, - 0x6d, 0xb4, 0x90, 0x15, 0xcb, 0x9a, 0x83, 0x9d, 0xf7, 0xdf, 0xb9, 0x62, 0x65, 0x62, 0x60, 0xc7, 0x18, 0x63, 0x9e, - 0x3c, 0x5a, 0xe3, 0xad, 0xdd, 0x5b, 0xae, 0xd0, 0x31, 0x69, 0xc0, 0x49, 0x21, 0x32, 0x2e, 0x5d, 0x62, 0xae, 0xad, - 0x99, 0x2d, 0x6b, 0x6a, 0xe1, 0x3f, 0x3d, 0x2b, 0x63, 0x60, 0xcc, 0x13, 0x41, 0x7e, 0x2e, 0xad, 0x76, 0xcc, 0x9b, - 0xb0, 0x57, 0x02, 0x4e, 0x9d, 0xcb, 0x5c, 0x12, 0x01, 0x5e, 0x2a, 0xfd, 0x4f, 0xdf, 0xfd, 0x0a, 0x09, 0x30, 0x28, - 0x1b, 0x7d, 0x91, 0x56, 0x04, 0x8f, 0x56, 0x83, 0x2f, 0x06, 0x96, 0x88, 0x82, 0x0b, 0xa3, 0x05, 0xde, 0x32, 0xfa, - 0xc2, 0x46, 0x1b, 0x5c, 0xa1, 0x19, 0xe9, 0xb8, 0x4c, 0xed, 0xa3, 0x7d, 0x1f, 0xc0, 0xae, 0x80, 0xd9, 0xda, 0x35, - 0x20, 0x88, 0x96, 0xba, 0x30, 0xa8, 0x48, 0xe1, 0x5a, 0xeb, 0x84, 0xf1, 0x3a, 0x71, 0xdb, 0x38, 0xdc, 0x87, 0x00, - 0x8c, 0xc0, 0x5d, 0xd1, 0x03, 0x0b, 0x44, 0xa5, 0x1e, 0x1d, 0x8d, 0x4b, 0x79, 0x51, 0x97, 0x18, 0xc9, 0x74, 0xdd, - 0x0f, 0xdb, 0xdf, 0xbb, 0x87, 0xbd, 0xf8, 0x94, 0xae, 0x07, 0xda, 0x6d, 0xe9, 0xa5, 0xe8, 0xa1, 0x87, 0xd6, 0x3d, - 0x68, 0x5e, 0x81, 0xde, 0xcb, 0x66, 0x93, 0x44, 0xdd, 0x17, 0xf4, 0xb6, 0x61, 0xfb, 0x5f, 0xda, 0xd0, 0xc0, 0x50, - 0xb5, 0x98, 0x89, 0x52, 0x91, 0x05, 0x61, 0x2c, 0xf4, 0xf7, 0x31, 0xdd, 0x2b, 0xb3, 0x23, 0x5f, 0x31, 0x37, 0xe3, - 0x30, 0x0f, 0x1a, 0xbd, 0x4b, 0xd5, 0x1f, 0x8c, 0xb9, 0x33, 0x34, 0x04, 0x3d, 0x28, 0x0f, 0x90, 0x06, 0x89, 0x41, - 0xab, 0x52, 0x28, 0xe0, 0x12, 0x52, 0xc9, 0x7e, 0x77, 0xf4, 0xcb, 0x4d, 0xbb, 0x6a, 0x0c, 0xc1, 0xa7, 0x77, 0x0e, - 0x10, 0x50, 0xb0, 0x8a, 0x83, 0x34, 0x48, 0xde, 0x90, 0xc3, 0x88, 0xe9, 0x3b, 0x0e, 0x70, 0x75, 0xe0, 0x77, 0xa5, - 0xc4, 0x79, 0x46, 0x08, 0x3d, 0xfe, 0x2f, 0x54, 0xbd, 0x6f, 0x2f, 0x85, 0x19, 0x94, 0x0d, 0xcf, 0x6b, 0x6a, 0x7a, - 0x36, 0xb4, 0x85, 0xfd, 0xbf, 0x4b, 0xc5, 0xfc, 0x96, 0x79, 0xa9, 0xc4, 0x96, 0xca, 0x07, 0x8c, 0xc1, 0x0f, 0x7f, - 0x78, 0x53, 0x73, 0xb1, 0xe4, 0x8d, 0x92, 0xca, 0x82, 0xda, 0xb9, 0xb9, 0xce, 0x6c, 0x60, 0x4f, 0x39, 0x29, 0xb6, - 0xa1, 0x9f, 0x86, 0xfb, 0x21, 0xe7, 0x0a, 0xe8, 0x38, 0xd5, 0x18, 0x2e, 0x24, 0xc1, 0xae, 0x83, 0x9d, 0x8c, 0x6a, - 0x73, 0xc3, 0xe0, 0x5a, 0x89, 0xef, 0x80, 0xb7, 0x03, 0x4c, 0x81, 0xef, 0xe7, 0x7b, 0xf9, 0x33, 0x42, 0xec, 0xb1, - 0x4c, 0x24, 0x01, 0x54, 0x62, 0x45, 0x4f, 0x39, 0x94, 0xb7, 0x8a, 0x6f, 0x65, 0x9e, 0x6a, 0xee, 0xcd, 0xd5, 0x65, - 0x06, 0x5a, 0x2c, 0x32, 0x8a, 0x2f, 0xc0, 0x8e, 0xea, 0x59, 0xfc, 0x17, 0xfa, 0x09, 0x8c, 0xe8, 0xc2, 0xc9, 0x4d, - 0x05, 0x8c, 0x6d, 0x23, 0x1d, 0x4e, 0x75, 0x2f, 0x51, 0xc4, 0x65, 0xa3, 0x11, 0x83, 0x37, 0x58, 0xe2, 0x95, 0x56, - 0x69, 0x7b, 0x4c, 0x82, 0x97, 0x8a, 0x09, 0x5b, 0x8c, 0x0a, 0xda, 0x48, 0x5f, 0x8c, 0x34, 0xd7, 0xa8, 0xdf, 0x8f, - 0xd7, 0xf6, 0x4b, 0x2b, 0x74, 0xcf, 0xe6, 0xa3, 0x82, 0xa0, 0xf1, 0x86, 0x00, 0x02, 0xec, 0x5e, 0x82, 0xae, 0xb8, - 0x63, 0xc8, 0x54, 0xc9, 0xe0, 0x3b, 0x85, 0x47, 0xac, 0xfa, 0xd3, 0xcd, 0xcf, 0xe5, 0x96, 0x95, 0x21, 0x65, 0xdb, - 0xdb, 0xdc, 0xbc, 0x1f, 0x61, 0xd3, 0x38, 0xc3, 0x88, 0x19, 0xf5, 0x0c, 0x18, 0xc3, 0x12, 0x00, 0xab, 0xb8, 0xa0, - 0xde, 0x3c, 0x74, 0x99, 0xdd, 0x30, 0xbd, 0x5e, 0xe9, 0x69, 0x1a, 0x44, 0xb0, 0xb7, 0xec, 0x4d, 0x12, 0xb6, 0x2b, - 0x1b, 0x2f, 0xa1, 0x63, 0xde, 0x7a, 0xc8, 0x59, 0x42, 0xdc, 0x10, 0xd6, 0xc2, 0xdd, 0x4b, 0xc4, 0x7d, 0xee, 0x62, - 0x7d, 0x22, 0x12, 0x1e, 0xf5, 0x02, 0xdd, 0xcb, 0x97, 0x15, 0xc8, 0x99, 0x66, 0xe9, 0xfd, 0x2f, 0x58, 0xeb, 0xca, - 0x65, 0x83, 0x66, 0xa0, 0x47, 0x07, 0xc5, 0x44, 0xcb, 0xe0, 0x02, 0x54, 0x14, 0xbb, 0x9a, 0x58, 0xe6, 0xd1, 0x04, - 0x28, 0xa4, 0x2c, 0x29, 0x4d, 0x26, 0x33, 0x56, 0x50, 0x60, 0x1a, 0xec, 0xbc, 0x78, 0xc0, 0xa0, 0x62, 0x93, 0xa9, - 0x4c, 0xac, 0x2c, 0x24, 0x09, 0x0e, 0x66, 0x85, 0xe6, 0x7a, 0x95, 0xdb, 0x41, 0x08, 0x59, 0x1d, 0x60, 0xdf, 0xac, - 0x64, 0x02, 0x6a, 0x1f, 0xe6, 0xb1, 0x63, 0x54, 0x52, 0x40, 0xbf, 0x10, 0x42, 0x6e, 0x77, 0x87, 0x3b, 0x6a, 0x8e, - 0x4e, 0x2f, 0x72, 0x97, 0x0c, 0x29, 0xf2, 0xdd, 0x17, 0x81, 0x63, 0x66, 0xe4, 0x32, 0xab, 0x84, 0xa8, 0x7b, 0x2b, - 0x5a, 0xc6, 0x2f, 0xe8, 0xef, 0x5c, 0xfa, 0x84, 0xd2, 0x82, 0x58, 0x74, 0x38, 0xa8, 0x01, 0xb2, 0xcd, 0x0e, 0x73, - 0x58, 0xda, 0xcd, 0x0b, 0x4b, 0xf0, 0x59, 0xfe, 0x36, 0xf6, 0xec, 0x27, 0x4f, 0xd7, 0xd5, 0x37, 0x5f, 0xc3, 0x28, - 0xe6, 0x5e, 0x6f, 0x34, 0x79, 0xbb, 0xc3, 0x08, 0xe1, 0x44, 0xda, 0xed, 0xf6, 0xd0, 0xc3, 0x15, 0x24, 0x60, 0x83, - 0x83, 0x4b, 0xaf, 0x6e, 0x9f, 0xac, 0x7f, 0xd5, 0x85, 0x39, 0xff, 0x99, 0x06, 0x70, 0x08, 0x19, 0x42, 0xda, 0x04, - 0x41, 0x0f, 0x43, 0x05, 0x6b, 0x2a, 0xb6, 0x32, 0x96, 0x25, 0xfd, 0x80, 0x58, 0xdf, 0xe0, 0xb2, 0x95, 0x65, 0xd4, - 0x42, 0xf0, 0xfc, 0x17, 0x07, 0x08, 0xde, 0x16, 0x9c, 0xfd, 0xd7, 0xc8, 0xc2, 0xf7, 0x8e, 0x0d, 0x52, 0xfa, 0x58, - 0x79, 0x67, 0xb8, 0x6c, 0xaa, 0xd9, 0xc0, 0x8e, 0xac, 0x5c, 0xef, 0xe9, 0x4d, 0x85, 0x32, 0xda, 0x8c, 0x1a, 0xd5, - 0xa6, 0xcc, 0xd2, 0x18, 0xbe, 0x47, 0xb3, 0xa8, 0x4f, 0x52, 0xbd, 0x61, 0x6f, 0xb6, 0x16, 0xb5, 0x83, 0xa9, 0xc6, - 0xf0, 0xde, 0xfe, 0xa9, 0xd9, 0x04, 0x81, 0xd2, 0x09, 0x76, 0xdc, 0x81, 0x8f, 0x94, 0x9e, 0x22, 0xa6, 0x1d, 0x44, - 0xfc, 0xbd, 0x95, 0xec, 0xe8, 0xf7, 0x38, 0x8a, 0x9f, 0x91, 0x31, 0x00, 0x31, 0xba, 0x2d, 0x4c, 0x41, 0xa4, 0x84, - 0xe6, 0x07, 0x2f, 0x14, 0xc4, 0x53, 0xa2, 0x01, 0x50, 0x76, 0x9b, 0xba, 0x02, 0xfb, 0x8c, 0x2f, 0x59, 0x5b, 0xcd, - 0x61, 0x3a, 0xd0, 0xb2, 0x60, 0xbd, 0xcb, 0xe9, 0x39, 0x53, 0x96, 0x5c, 0x6b, 0x37, 0x28, 0xc4, 0xfd, 0x57, 0xcb, - 0xbb, 0x05, 0x96, 0xb3, 0xc7, 0xbf, 0xdf, 0xc8, 0x4f, 0xdc, 0x2a, 0x1b, 0xc2, 0xac, 0x87, 0x4c, 0x91, 0x25, 0x39, - 0x0c, 0x32, 0xad, 0xa5, 0xfb, 0x07, 0x32, 0x68, 0x6e, 0xb7, 0xf5, 0x14, 0xd6, 0xe4, 0xf9, 0xe0, 0xcb, 0x0e, 0x64, - 0x67, 0x0a, 0x61, 0xa0, 0x7f, 0xd9, 0xde, 0x5e, 0x80, 0xce, 0x4d, 0x86, 0xb8, 0xbb, 0xe2, 0x8d, 0x73, 0x51, 0xde, - 0xf8, 0xe5, 0xb6, 0x13, 0x56, 0xd0, 0xb6, 0x88, 0xa6, 0x41, 0xb5, 0xfc, 0x3d, 0xa2, 0xbc, 0xd8, 0xac, 0xb6, 0x7c, - 0x3e, 0x55, 0x46, 0x4f, 0x2f, 0x41, 0x37, 0xe8, 0x07, 0x43, 0xc4, 0xb7, 0x9f, 0xb5, 0xe3, 0x23, 0xd3, 0x96, 0x3f, - 0xb5, 0xed, 0x19, 0x22, 0xfa, 0xd9, 0xee, 0x11, 0xed, 0xd8, 0x03, 0x68, 0x78, 0x58, 0xa9, 0xa1, 0x83, 0xde, 0x43, - 0xc1, 0x3c, 0xc5, 0x5b, 0x90, 0xc3, 0xe6, 0xc1, 0xf2, 0x0e, 0x10, 0xd9, 0x42, 0xb9, 0x64, 0x6f, 0x21, 0xbd, 0xf3, - 0xf6, 0xcc, 0xc9, 0xe0, 0x91, 0x9e, 0x20, 0x9e, 0x22, 0x80, 0x74, 0x0c, 0x26, 0xbb, 0x75, 0xa9, 0xf5, 0x6c, 0xa2, - 0x00, 0x3b, 0xa7, 0x70, 0x1a, 0xf3, 0x5c, 0xd2, 0x08, 0x82, 0x3d, 0x6b, 0x12, 0x69, 0x09, 0x51, 0xe8, 0xa3, 0xb3, - 0x6d, 0xfb, 0x24, 0x2f, 0x23, 0x5f, 0x87, 0xd8, 0xac, 0xd2, 0xdf, 0x58, 0xe5, 0xc4, 0xd5, 0x23, 0x9f, 0xcf, 0x5d, - 0xe8, 0xe7, 0xcc, 0x20, 0x42, 0xbb, 0xb0, 0x92, 0xd1, 0xa8, 0xc8, 0x34, 0x7a, 0x45, 0xb2, 0x97, 0x0a, 0x21, 0x19, - 0x46, 0x37, 0x46, 0xb1, 0x87, 0x23, 0x67, 0x53, 0xc9, 0x12, 0x76, 0x61, 0x89, 0xf3, 0x5f, 0xea, 0x0c, 0xf4, 0x52, - 0x15, 0x4d, 0xe6, 0xa2, 0x9c, 0x6b, 0x87, 0x34, 0x19, 0x00, 0x43, 0x8d, 0xb7, 0x09, 0x9e, 0xf6, 0xa8, 0xc6, 0xab, - 0x56, 0xe4, 0x48, 0xd8, 0x7c, 0x5c, 0xc4, 0x8e, 0xf1, 0x80, 0x3c, 0x62, 0x1c, 0x0f, 0x3e, 0xc7, 0x83, 0x06, 0x48, - 0xfe, 0x44, 0x0a, 0x3e, 0x7a, 0x5e, 0x31, 0x07, 0xb3, 0x0d, 0x6c, 0xcf, 0x44, 0x53, 0x05, 0xb3, 0x93, 0xf5, 0x1e, - 0x50, 0x47, 0xc5, 0x50, 0x38, 0x32, 0xec, 0xc1, 0x70, 0xa6, 0xde, 0xb1, 0xf5, 0x39, 0x3b, 0x68, 0x79, 0x50, 0x25, - 0x19, 0x08, 0x5c, 0x7c, 0x18, 0x71, 0x8d, 0x4f, 0xea, 0x05, 0xd0, 0x1c, 0x79, 0xa5, 0xc5, 0xc7, 0xa3, 0x61, 0xc2, - 0x11, 0x43, 0x46, 0x7f, 0xb4, 0x31, 0xd5, 0x90, 0x6e, 0x97, 0xae, 0x77, 0x13, 0xbe, 0x4a, 0xc9, 0xd2, 0xcd, 0x51, - 0xf6, 0x9a, 0xc6, 0x03, 0xcd, 0x75, 0x33, 0xdb, 0x97, 0x7f, 0xc7, 0x74, 0x8e, 0xcc, 0x45, 0xc2, 0xba, 0x29, 0xb7, - 0xa8, 0xe3, 0x2e, 0x3e, 0x1c, 0x8e, 0x8c, 0x61, 0x7b, 0xf0, 0x44, 0xee, 0x30, 0xc7, 0xb1, 0xbf, 0xb2, 0xe0, 0x46, - 0xe9, 0x25, 0xc7, 0xe2, 0xab, 0xd9, 0x84, 0x2c, 0x66, 0x29, 0x50, 0xb1, 0xea, 0xb7, 0x01, 0xb6, 0xd8, 0x8a, 0x5a, - 0x27, 0x51, 0xef, 0x33, 0x8d, 0x98, 0x5b, 0xb6, 0x3c, 0x22, 0x08, 0xf2, 0x8d, 0xac, 0xa6, 0x79, 0xd4, 0x58, 0x06, - 0xa8, 0x6b, 0x12, 0x8b, 0x5a, 0xee, 0x50, 0x90, 0x59, 0xe8, 0x20, 0xa4, 0xd7, 0x29, 0x8c, 0x47, 0x2e, 0x57, 0xc8, - 0x74, 0xa9, 0xf3, 0x80, 0x17, 0x2b, 0xc7, 0x46, 0xbf, 0xfe, 0x78, 0x20, 0xaf, 0x48, 0xc4, 0x72, 0x82, 0x2f, 0xe1, - 0xd2, 0x98, 0x31, 0x90, 0x4c, 0xb4, 0x4f, 0x45, 0x2b, 0xf6, 0x63, 0x44, 0x5d, 0x48, 0xf4, 0x58, 0x70, 0x44, 0xb2, - 0x23, 0x61, 0x7f, 0x28, 0x8a, 0x21, 0x89, 0xc7, 0x9c, 0x63, 0x1a, 0x78, 0xdf, 0x16, 0xbd, 0xed, 0x70, 0x68, 0x5b, - 0x94, 0xd7, 0x8a, 0x0b, 0x74, 0xca, 0x92, 0x1b, 0xe0, 0x25, 0xaf, 0x7e, 0xc2, 0xee, 0x1a, 0x07, 0xe5, 0xeb, 0xe2, - 0xee, 0xed, 0x26, 0xc1, 0xc0, 0x3b, 0x88, 0xf3, 0x7a, 0x19, 0xc5, 0xf1, 0xbb, 0x5d, 0xf0, 0xea, 0x98, 0xcf, 0x08, - 0x18, 0x3c, 0x42, 0x3a, 0x91, 0xed, 0x35, 0x27, 0x78, 0xf8, 0xa1, 0xd4, 0x1f, 0x0b, 0x28, 0x67, 0x85, 0xbf, 0x51, - 0xa6, 0xb6, 0x8d, 0x2e, 0xa4, 0xe4, 0xe3, 0x52, 0x7a, 0x17, 0x62, 0xc4, 0x80, 0x5c, 0xed, 0xca, 0xf7, 0x62, 0x55, - 0x7a, 0x54, 0x6a, 0xc4, 0x17, 0xf4, 0x8a, 0xa1, 0x35, 0x46, 0xbd, 0xe3, 0x66, 0x9d, 0x08, 0x13, 0x83, 0xaf, 0xa8, - 0x9d, 0xb4, 0xcd, 0x98, 0x08, 0x81, 0x34, 0x59, 0xb4, 0x7e, 0xb2, 0x88, 0xc2, 0x42, 0x28, 0x62, 0xc2, 0x12, 0x2d, - 0x87, 0x04, 0x04, 0x91, 0x21, 0x8d, 0xf0, 0x98, 0xbb, 0x96, 0x03, 0xe3, 0x01, 0x8c, 0xa5, 0xb8, 0xf7, 0x8f, 0xaf, - 0x46, 0x30, 0x05, 0x11, 0x3c, 0xd5, 0x95, 0x17, 0x49, 0x43, 0x63, 0x35, 0xcc, 0x43, 0x73, 0x21, 0x47, 0x19, 0x78, - 0x33, 0x27, 0x58, 0x5c, 0xb5, 0x32, 0xc2, 0x4d, 0x7f, 0xb6, 0xfb, 0x50, 0xcf, 0x9d, 0x83, 0x36, 0x27, 0xcb, 0x59, - 0xb2, 0xd2, 0x1f, 0x6d, 0x4f, 0x10, 0x81, 0xc8, 0x60, 0x06, 0x52, 0x57, 0x04, 0x42, 0x42, 0x1c, 0x45, 0x92, 0x9b, - 0x27, 0x87, 0x08, 0xc4, 0xe7, 0xe5, 0x17, 0xfa, 0x20, 0x03, 0x4a, 0x64, 0xbd, 0xbe, 0x59, 0x01, 0xd3, 0x13, 0x4e, - 0x21, 0xc5, 0x1e, 0xab, 0x82, 0x41, 0x46, 0x24, 0xcc, 0x16, 0x27, 0x0c, 0x99, 0xd7, 0x57, 0xbf, 0x77, 0x38, 0x35, - 0x3c, 0xe8, 0x00, 0x30, 0xaa, 0x1c, 0x41, 0x21, 0x92, 0x3f, 0x29, 0x60, 0x58, 0x21, 0xe1, 0xdd, 0x9b, 0xe4, 0xc2, - 0x89, 0x6c, 0x63, 0x55, 0x79, 0x25, 0xac, 0x7e, 0xa8, 0x81, 0x67, 0x24, 0x04, 0xa6, 0xa8, 0x18, 0xdb, 0xbf, 0xff, - 0x59, 0x55, 0x49, 0x1a, 0x2f, 0x92, 0x94, 0x7e, 0xed, 0x71, 0x5b, 0xa8, 0x85, 0x86, 0x49, 0x9a, 0x1d, 0xea, 0x6d, - 0x67, 0x12, 0x39, 0xe3, 0x10, 0x72, 0x16, 0x62, 0x00, 0x88, 0x97, 0xc1, 0xe0, 0x43, 0xeb, 0x63, 0xda, 0x01, 0xa7, - 0x5f, 0xbb, 0x67, 0x65, 0xf4, 0xa3, 0x35, 0xcf, 0xe8, 0xc2, 0xf9, 0xe9, 0x51, 0xad, 0x26, 0x7e, 0x48, 0xe0, 0xac, - 0x84, 0x5e, 0x8a, 0x59, 0x35, 0x1e, 0x67, 0xae, 0xf8, 0x7a, 0x74, 0x6a, 0xab, 0x40, 0xac, 0x2a, 0x0d, 0x37, 0xc2, - 0x78, 0xf6, 0x40, 0xb2, 0x79, 0x14, 0x7e, 0xa4, 0x92, 0x71, 0xaf, 0x38, 0xc2, 0x0c, 0xd1, 0x06, 0x7a, 0xce, 0x0b, - 0x58, 0xce, 0xca, 0x22, 0x19, 0x79, 0x1d, 0x0a, 0x9a, 0xde, 0x38, 0xe4, 0x21, 0x53, 0x1c, 0x9c, 0xc9, 0x0a, 0x9f, - 0xd3, 0xa3, 0xe6, 0xc6, 0x28, 0xab, 0x60, 0x63, 0x34, 0x9f, 0x96, 0x9e, 0x3c, 0x90, 0x4d, 0x63, 0x9a, 0xd2, 0xa2, - 0xa4, 0x21, 0x71, 0xa9, 0x6a, 0xe6, 0x68, 0x1e, 0x98, 0x43, 0xac, 0x6f, 0x5f, 0x70, 0xf6, 0x88, 0xe7, 0xe3, 0x82, - 0x14, 0xa4, 0xcd, 0xf4, 0xa8, 0xe4, 0xfa, 0xf3, 0x33, 0x20, 0xac, 0xbc, 0x7d, 0xb0, 0xe1, 0xd7, 0x15, 0x12, 0xd9, - 0xde, 0xbc, 0x1c, 0xa0, 0x68, 0xc2, 0xaf, 0x1d, 0x6c, 0xd6, 0x57, 0x96, 0x38, 0xbe, 0x35, 0x5b, 0x15, 0x44, 0x4e, - 0x66, 0x46, 0xbf, 0xee, 0x05, 0xac, 0x15, 0x61, 0xca, 0xd9, 0xd9, 0xe6, 0x1a, 0xa0, 0xa5, 0xe0, 0x38, 0x2a, 0x46, - 0x7c, 0x54, 0xcf, 0x48, 0x65, 0x26, 0xbd, 0xc6, 0x42, 0x97, 0xe1, 0x0b, 0x35, 0xf5, 0x5a, 0xd4, 0x7c, 0xe4, 0x43, - 0x46, 0x84, 0x9d, 0x46, 0xb8, 0xf8, 0xc6, 0xc0, 0x6b, 0x79, 0x1a, 0x9d, 0x07, 0x7a, 0x2f, 0x36, 0x5b, 0x9e, 0xf8, - 0xee, 0xba, 0x4d, 0x8e, 0x8f, 0xb1, 0x35, 0x5b, 0x36, 0x63, 0xf9, 0xe9, 0xf5, 0x27, 0xa3, 0x2a, 0xa1, 0x66, 0xeb, - 0xbe, 0x9f, 0xba, 0x7e, 0x3d, 0x34, 0xcf, 0xf3, 0x36, 0x6d, 0x1b, 0xe7, 0xe6, 0xde, 0x80, 0x6c, 0x2f, 0x0a, 0xe6, - 0xb9, 0xd0, 0x9c, 0x36, 0xb4, 0x3e, 0xbd, 0x84, 0x59, 0x99, 0xd9, 0xd0, 0x76, 0x7d, 0xad, 0x7f, 0xa9, 0x28, 0x8c, - 0xd8, 0xfa, 0x80, 0x13, 0x51, 0x4a, 0x54, 0x5a, 0xe5, 0xe7, 0x4b, 0x6f, 0x45, 0x48, 0x9e, 0xcb, 0x7e, 0x19, 0x4d, - 0xff, 0x09, 0xbd, 0x56, 0x26, 0x42, 0xf1, 0x35, 0x73, 0xee, 0x59, 0x2d, 0xf9, 0xd7, 0x52, 0xb1, 0x74, 0xac, 0x71, - 0xd5, 0x7a, 0x5e, 0xc6, 0x93, 0x6b, 0xb8, 0x3e, 0x4e, 0xd1, 0x7a, 0xc6, 0x48, 0x7f, 0x0e, 0xae, 0x44, 0xa4, 0x16, - 0x97, 0xbe, 0x03, 0x73, 0x25, 0x0a, 0xc9, 0xd5, 0x54, 0x7a, 0xf6, 0x56, 0xf5, 0x38, 0xd1, 0x3c, 0x23, 0x73, 0xef, - 0xca, 0xbe, 0x59, 0x95, 0xd6, 0x5e, 0x93, 0x57, 0x29, 0x1c, 0x9f, 0xe0, 0x3a, 0xb9, 0x77, 0x4f, 0x31, 0x25, 0x88, - 0x10, 0xba, 0x38, 0xed, 0x0b, 0xbf, 0x42, 0x38, 0xe0, 0xf5, 0xd4, 0x69, 0xdd, 0x5e, 0x52, 0x2d, 0x41, 0x9c, 0xab, - 0x3b, 0x9c, 0xb3, 0x5b, 0x73, 0xb6, 0x90, 0x1d, 0x67, 0x59, 0xa1, 0x9e, 0x6e, 0x0e, 0x19, 0x76, 0x28, 0x78, 0x86, - 0x5c, 0xb7, 0x57, 0xd3, 0x67, 0x23, 0x32, 0x71, 0xab, 0xdd, 0xbe, 0x45, 0x72, 0x79, 0x1a, 0x00, 0xc1, 0x18, 0xfe, - 0x79, 0xd1, 0x9e, 0x8c, 0xce, 0x84, 0x05, 0xb3, 0x21, 0x90, 0x06, 0x8c, 0x19, 0x24, 0xc2, 0xe3, 0x3f, 0x91, 0xff, - 0x57, 0x93, 0xdf, 0x78, 0x31, 0xce, 0xa9, 0xe3, 0x37, 0xef, 0x35, 0xa0, 0x24, 0x66, 0xc1, 0x89, 0x0d, 0xaf, 0x82, - 0x6c, 0x99, 0xb6, 0x81, 0x63, 0xb0, 0x4c, 0x7f, 0x0c, 0xca, 0xd8, 0x0b, 0x48, 0x32, 0xf1, 0x8e, 0x84, 0xea, 0x74, - 0xd6, 0x5e, 0x1c, 0x09, 0x5c, 0xce, 0x99, 0xe4, 0xe8, 0x02, 0x1b, 0x33, 0xc1, 0xd3, 0xee, 0x30, 0xd2, 0xcf, 0x50, - 0xbc, 0x96, 0xab, 0xdb, 0xc8, 0x00, 0xa1, 0x04, 0x13, 0xea, 0x13, 0xd2, 0xfe, 0xed, 0xe1, 0x88, 0x81, 0x44, 0x81, - 0x26, 0x0b, 0x76, 0x80, 0x4d, 0xa1, 0xae, 0xdd, 0x3c, 0x96, 0x36, 0xc6, 0x23, 0x69, 0x94, 0x61, 0x71, 0x59, 0x91, - 0xd1, 0x4a, 0x5f, 0x39, 0x9a, 0x2d, 0x1c, 0xfb, 0xce, 0x62, 0xb0, 0xd0, 0x86, 0xab, 0x97, 0x09, 0xba, 0x9f, 0x3a, - 0xf2, 0xca, 0xff, 0x6a, 0xb2, 0xea, 0xd6, 0x67, 0x6f, 0xf2, 0x95, 0x43, 0x46, 0xdc, 0x5e, 0x3d, 0x7f, 0x8c, 0x47, - 0x4f, 0xb5, 0xd2, 0x87, 0x11, 0x67, 0x18, 0x54, 0xb9, 0x2d, 0x08, 0xcf, 0x6a, 0x32, 0x6c, 0x74, 0x14, 0xf4, 0x03, - 0x4d, 0x09, 0x66, 0xec, 0xc7, 0xd4, 0x04, 0x58, 0xf2, 0xa4, 0xb3, 0xb0, 0xf2, 0x7a, 0x76, 0x1d, 0x6f, 0x73, 0x81, - 0xe5, 0x13, 0x8e, 0x3d, 0xd8, 0xc4, 0x0a, 0x9b, 0x0a, 0x9b, 0x24, 0x2e, 0x3c, 0xb1, 0xb2, 0x8c, 0x78, 0xe1, 0x0a, - 0x5b, 0xa7, 0x3c, 0x95, 0xc2, 0x6e, 0xe8, 0xca, 0xaf, 0xf5, 0xca, 0x8b, 0xd1, 0x79, 0x1d, 0xa3, 0x9b, 0xe4, 0x26, - 0x86, 0x60, 0x30, 0xec, 0x46, 0x4e, 0xfa, 0xf6, 0x40, 0xc9, 0xe0, 0x06, 0x0d, 0xca, 0xd7, 0x91, 0xb5, 0x42, 0x3c, - 0xd7, 0x95, 0x0b, 0x67, 0x9e, 0x00, 0x98, 0x2f, 0xaf, 0x17, 0xda, 0x44, 0x07, 0x3b, 0xbe, 0x9f, 0xf7, 0x05, 0x0b, - 0x78, 0xd9, 0x21, 0x96, 0x95, 0x37, 0x3b, 0xfd, 0x05, 0x6e, 0x38, 0x73, 0x6d, 0x9b, 0x51, 0x6d, 0xa1, 0x97, 0xe8, - 0xc8, 0xdc, 0xb3, 0x64, 0xab, 0x89, 0x80, 0xb3, 0x03, 0xc1, 0xa2, 0x24, 0xe6, 0x09, 0x82, 0x25, 0x7e, 0xc2, 0x03, - 0x59, 0xd8, 0x2f, 0xcd, 0xa5, 0xe8, 0x89, 0xf6, 0xfa, 0xa5, 0xf9, 0x9c, 0x5f, 0x84, 0x43, 0x7c, 0xae, 0x28, 0xeb, - 0xa1, 0xce, 0xe3, 0x20, 0x8a, 0xa3, 0x5f, 0x33, 0x95, 0xd0, 0xfe, 0x31, 0x5a, 0x94, 0x34, 0x76, 0x59, 0xb8, 0xd2, - 0xca, 0x9a, 0x70, 0x95, 0x76, 0x93, 0x41, 0x5e, 0x89, 0x67, 0x5e, 0x65, 0x5d, 0xd6, 0x1c, 0xdf, 0x83, 0xba, 0x1d, - 0x39, 0xfb, 0xac, 0xa1, 0x4a, 0x0e, 0xd0, 0xfe, 0xe0, 0xa1, 0xb3, 0x08, 0x6a, 0x08, 0xae, 0x6e, 0x7c, 0x82, 0x38, - 0xe0, 0x32, 0x08, 0xa9, 0x0c, 0xfb, 0x52, 0xc9, 0xbf, 0x91, 0x32, 0x8a, 0xff, 0xab, 0x34, 0xaf, 0x1e, 0x18, 0x84, - 0xaf, 0xbb, 0x9b, 0x5f, 0x01, 0xb2, 0xb5, 0x30, 0x33, 0xb8, 0xc9, 0x6d, 0x13, 0xf7, 0x45, 0x39, 0x68, 0x1b, 0xac, - 0x97, 0x16, 0xa1, 0x0f, 0x1a, 0x8f, 0x34, 0x61, 0xf5, 0x39, 0x5c, 0x0b, 0x02, 0x37, 0x75, 0xfe, 0x78, 0x3c, 0xc9, - 0xd4, 0x14, 0x9a, 0xc6, 0xee, 0x4c, 0x5a, 0x8e, 0x30, 0x90, 0x30, 0x40, 0x36, 0x3e, 0xb0, 0x6d, 0xe9, 0xf6, 0x66, - 0x11, 0x5c, 0xaf, 0x41, 0x50, 0xca, 0x96, 0x45, 0x07, 0x47, 0x63, 0xb6, 0xc1, 0x9c, 0xee, 0x13, 0x8d, 0xc8, 0xae, - 0x60, 0x38, 0x0b, 0x23, 0xd7, 0x5f, 0x9c, 0x35, 0xeb, 0x2e, 0x28, 0x52, 0x3d, 0xf2, 0xa1, 0xd8, 0x46, 0x00, 0x4f, - 0xa8, 0xf4, 0xf1, 0xc0, 0x23, 0x8a, 0x56, 0x87, 0x14, 0x1e, 0x16, 0x85, 0x43, 0xbe, 0xc1, 0x38, 0x1d, 0xa1, 0x3e, - 0x39, 0x82, 0x31, 0x45, 0x7e, 0xf8, 0x8b, 0x85, 0xf1, 0xb5, 0x7c, 0x81, 0x79, 0x5a, 0x69, 0x11, 0x77, 0x3d, 0xe5, - 0xb6, 0xcf, 0xed, 0xe1, 0x13, 0x2f, 0x21, 0x1b, 0xa1, 0xdf, 0x47, 0x7e, 0xd4, 0x6c, 0xfd, 0xe7, 0x01, 0xe6, 0xdb, - 0xc1, 0x1a, 0x4c, 0x38, 0x2a, 0x78, 0xa4, 0x1f, 0x5d, 0x99, 0x76, 0x83, 0x82, 0xf5, 0x21, 0x94, 0x32, 0x3a, 0x71, - 0xd0, 0xed, 0x6a, 0xe6, 0xbf, 0x3c, 0x76, 0x31, 0x02, 0x59, 0x48, 0xe2, 0xe7, 0xa5, 0xec, 0xdb, 0xba, 0x0c, 0x6b, - 0x69, 0xe9, 0xe6, 0x69, 0x22, 0x86, 0xcb, 0x24, 0xa8, 0xbc, 0xea, 0x11, 0x11, 0x23, 0x52, 0x16, 0x4c, 0xbd, 0x8c, - 0xbf, 0xe3, 0x3b, 0x63, 0x17, 0xb5, 0x6e, 0x23, 0xb5, 0x6e, 0xaf, 0x7a, 0xb3, 0xb5, 0xeb, 0xc3, 0x36, 0x0e, 0xf0, - 0xde, 0xd2, 0x4f, 0x50, 0xa0, 0xf1, 0x4a, 0x3b, 0xfa, 0xed, 0x40, 0x4c, 0xf8, 0x87, 0xd8, 0x35, 0x89, 0xee, 0x0b, - 0x86, 0x2b, 0xb5, 0xc9, 0xda, 0x06, 0xc6, 0x08, 0xc5, 0x5a, 0x9e, 0x47, 0x70, 0x9e, 0x8d, 0x1c, 0x15, 0xda, 0x65, - 0x8c, 0xcf, 0xc8, 0x8e, 0xf1, 0x4f, 0xc8, 0xca, 0x16, 0x46, 0x70, 0x4f, 0x72, 0x2a, 0x92, 0xe8, 0xfc, 0x14, 0x05, - 0xf2, 0x46, 0xeb, 0x12, 0x1d, 0x78, 0x7d, 0xd1, 0x2c, 0x1e, 0xfe, 0x1e, 0x2d, 0x29, 0x44, 0x38, 0x78, 0x7c, 0x47, - 0x84, 0x50, 0xab, 0x29, 0x54, 0x47, 0x5b, 0x0c, 0x32, 0x7b, 0x7c, 0x4a, 0x36, 0x5f, 0x64, 0x1b, 0x1c, 0xb1, 0x04, - 0x3f, 0xa9, 0xec, 0xc7, 0x95, 0x4d, 0xfc, 0x48, 0xff, 0x43, 0x69, 0xc9, 0xa9, 0x8e, 0xd7, 0x74, 0x55, 0x43, 0x53, - 0xe8, 0x0a, 0xb5, 0x11, 0x1d, 0x87, 0xfd, 0x2b, 0x94, 0x49, 0x9d, 0x6a, 0xda, 0x20, 0x6a, 0x1d, 0xf4, 0x3d, 0x5a, - 0x70, 0xbf, 0xf2, 0x3a, 0xf2, 0x45, 0x0c, 0x22, 0x27, 0xe8, 0x57, 0x62, 0x73, 0x25, 0x9f, 0xa7, 0xd1, 0x9d, 0xb7, - 0x54, 0xb2, 0xb1, 0x11, 0x2a, 0xca, 0xda, 0xdb, 0xe4, 0x52, 0xca, 0x5b, 0x4f, 0xe8, 0x29, 0xf7, 0xf2, 0xc1, 0x6c, - 0x93, 0xc6, 0x22, 0x22, 0x4e, 0x36, 0x1e, 0xae, 0xe3, 0x0d, 0x79, 0xa1, 0xd8, 0x82, 0x91, 0x0a, 0x5a, 0x83, 0x97, - 0x9d, 0xb3, 0x8c, 0xf2, 0x95, 0x38, 0x5e, 0xe4, 0x6f, 0xbb, 0xd9, 0x20, 0x9e, 0x1f, 0x06, 0xde, 0x47, 0x12, 0xea, - 0xac, 0x40, 0xc2, 0x1c, 0x77, 0x90, 0x05, 0xcb, 0x73, 0x25, 0x8f, 0x40, 0x32, 0x30, 0x52, 0xb4, 0x0d, 0xd3, 0xb9, - 0x14, 0x1f, 0xb4, 0x83, 0x8d, 0xb3, 0x41, 0x10, 0x1c, 0xd8, 0xf9, 0xfd, 0xfc, 0xeb, 0x5b, 0x1a, 0x83, 0xd3, 0xdb, - 0x2d, 0xc3, 0xff, 0x13, 0x5c, 0x9a, 0x45, 0xb4, 0x9c, 0xfe, 0x14, 0x63, 0xbe, 0xfc, 0x3f, 0xb9, 0x5b, 0x68, 0x1d, - 0xb4, 0xf0, 0x81, 0xed, 0x8e, 0x56, 0xdd, 0x46, 0x92, 0xda, 0xda, 0x0d, 0x06, 0x14, 0x66, 0x48, 0x39, 0x29, 0xa3, - 0x7a, 0x87, 0x46, 0x2f, 0x9c, 0x6e, 0x8e, 0x02, 0x30, 0xf7, 0xc1, 0xca, 0x7b, 0xca, 0x93, 0xdd, 0xbd, 0x02, 0x2b, - 0xb1, 0x1e, 0x0d, 0x90, 0xa3, 0xd4, 0xfe, 0x7d, 0xe1, 0xd4, 0xba, 0xa7, 0x25, 0xab, 0x6c, 0x38, 0x7f, 0xd1, 0x55, - 0x82, 0xb0, 0xc1, 0xd5, 0x53, 0xae, 0xcb, 0x2d, 0x7d, 0x5a, 0xa9, 0xca, 0x18, 0x1f, 0x0a, 0x09, 0x60, 0xa7, 0xaa, - 0x64, 0xdd, 0x19, 0xbf, 0x94, 0x62, 0x77, 0xac, 0xd9, 0xc9, 0x5f, 0x6f, 0x80, 0xdf, 0x2b, 0xe6, 0x75, 0x57, 0x8f, - 0xd6, 0x13, 0xd8, 0x93, 0x4b, 0x8f, 0xa1, 0x42, 0x60, 0x87, 0x97, 0x34, 0xd8, 0x7d, 0x90, 0x36, 0x0b, 0x93, 0x03, - 0x87, 0xe8, 0x34, 0x12, 0x3c, 0x57, 0x69, 0x69, 0xe4, 0xc4, 0x5b, 0x79, 0x62, 0xb7, 0x2e, 0x6e, 0xd2, 0x54, 0xc2, - 0x21, 0xa3, 0x90, 0x67, 0xf0, 0x86, 0x73, 0x89, 0xd2, 0xb3, 0xd9, 0xb4, 0xc9, 0x68, 0xc2, 0x79, 0x9a, 0xdf, 0x87, - 0x93, 0x6b, 0xac, 0x3e, 0xea, 0x98, 0xf4, 0x02, 0x38, 0x4b, 0xd1, 0x1a, 0xf1, 0xab, 0x03, 0x03, 0x0d, 0x2e, 0x2f, - 0xec, 0x25, 0x0b, 0xc1, 0x18, 0x6d, 0x63, 0x8f, 0x49, 0x07, 0x0e, 0xa1, 0xbe, 0x4e, 0x19, 0xc2, 0x0c, 0x2b, 0x88, - 0x60, 0x9a, 0xe2, 0xcc, 0xe1, 0x37, 0x70, 0xcf, 0x0a, 0x8c, 0x0a, 0xb9, 0x89, 0x0e, 0x23, 0xe0, 0x0a, 0xb7, 0x03, - 0x44, 0x76, 0xe6, 0x63, 0xc6, 0x6c, 0x9d, 0x71, 0xd8, 0xaf, 0x5c, 0x62, 0xd3, 0x1e, 0xa9, 0xfe, 0x8e, 0xdb, 0x7e, - 0x3b, 0xe1, 0xcf, 0x05, 0x8e, 0x62, 0x03, 0x71, 0x4f, 0xcb, 0x59, 0x4a, 0x2d, 0x1c, 0x1f, 0x47, 0x33, 0x8c, 0x43, - 0xe9, 0x9c, 0x32, 0xc9, 0x36, 0x0a, 0x9b, 0x01, 0xa4, 0xed, 0xe6, 0x90, 0x4c, 0x99, 0xa4, 0xb1, 0x38, 0x11, 0x85, - 0x2c, 0xfc, 0x12, 0xac, 0xcd, 0x2f, 0x36, 0x9f, 0xc0, 0x51, 0x85, 0xb9, 0xba, 0x23, 0xf0, 0x6e, 0xa1, 0xcc, 0x4b, - 0xe9, 0x28, 0xf4, 0x28, 0x4c, 0x9d, 0xb1, 0xd5, 0x0b, 0xeb, 0x94, 0x21, 0x64, 0x23, 0x5b, 0x67, 0x89, 0x16, 0x65, - 0x83, 0x7f, 0x1c, 0xff, 0x6b, 0x90, 0xd8, 0xf6, 0x20, 0xd8, 0xde, 0x32, 0x65, 0xa7, 0xef, 0x2d, 0xbf, 0xfb, 0x44, - 0x4f, 0x74, 0x07, 0x1c, 0x06, 0x5c, 0x75, 0x7a, 0xee, 0xa7, 0x3e, 0xbc, 0xcb, 0x06, 0xff, 0x0d, 0x37, 0x7e, 0x0a, - 0x5f, 0xa5, 0x8f, 0x0a, 0xe7, 0xfa, 0xca, 0x7b, 0x43, 0x1e, 0x6d, 0x53, 0xf3, 0x3b, 0x4f, 0x54, 0xbc, 0x21, 0xdf, - 0x4d, 0xbc, 0x9a, 0x13, 0xef, 0xc9, 0xe7, 0x9c, 0x6f, 0xa7, 0x4e, 0xc0, 0x62, 0xb0, 0x07, 0x3b, 0x64, 0xd7, 0x7b, - 0x6d, 0x54, 0x8c, 0x5f, 0x99, 0xdb, 0xfb, 0x1f, 0x59, 0xef, 0x65, 0x11, 0x0d, 0x74, 0x03, 0x98, 0xc0, 0x69, 0xeb, - 0x10, 0xe5, 0x86, 0x2c, 0xb1, 0xec, 0x50, 0xa5, 0x89, 0x0e, 0x15, 0x21, 0x5d, 0x02, 0xb0, 0x7c, 0xe2, 0xf8, 0xc3, - 0x8a, 0xd3, 0x4a, 0xd2, 0x60, 0x88, 0xb5, 0x98, 0xdd, 0xa6, 0xd3, 0xfa, 0x71, 0xca, 0xe4, 0x5f, 0x01, 0xe3, 0x75, - 0x82, 0xb7, 0x48, 0x7f, 0xbe, 0x7c, 0x67, 0xf9, 0x39, 0xd1, 0x6f, 0xe4, 0x42, 0xff, 0x53, 0xf8, 0xba, 0x90, 0x26, - 0xf5, 0x3a, 0xff, 0x6c, 0xa7, 0xfa, 0x1d, 0x4a, 0x4b, 0x96, 0x83, 0xbc, 0x54, 0xdf, 0xd7, 0x9d, 0xfe, 0x43, 0xf9, - 0xfa, 0xd8, 0xc9, 0x06, 0x82, 0x5b, 0x9e, 0xfd, 0x64, 0x45, 0x44, 0xcf, 0xb6, 0x3f, 0x70, 0x32, 0x93, 0xdc, 0xcd, - 0xf5, 0xc8, 0xea, 0x24, 0xab, 0x82, 0x87, 0xbd, 0x4a, 0xdf, 0x33, 0xd3, 0xc3, 0x3d, 0x37, 0xe5, 0x9f, 0x44, 0x2a, - 0xf0, 0x44, 0x43, 0x63, 0x33, 0x54, 0x23, 0x14, 0x8f, 0xd3, 0x80, 0xcd, 0x9f, 0x34, 0xaf, 0x07, 0x0d, 0x56, 0x2e, - 0x15, 0x28, 0xaa, 0xd6, 0x9e, 0xa0, 0x03, 0x53, 0x50, 0x38, 0xda, 0x12, 0x02, 0x54, 0xb0, 0x2c, 0x6a, 0x48, 0xf4, - 0x23, 0x0d, 0x56, 0xb8, 0xd1, 0xc1, 0xdf, 0x82, 0x15, 0x41, 0x50, 0xb7, 0x36, 0xe6, 0x75, 0x57, 0x63, 0x28, 0x8c, - 0xfa, 0x31, 0x98, 0xa0, 0xfc, 0x0d, 0xd4, 0x4b, 0x5b, 0x0c, 0x57, 0xab, 0x06, 0x7c, 0x50, 0xcd, 0x49, 0xbc, 0x6c, - 0xb6, 0x09, 0x9b, 0xdc, 0x20, 0x65, 0x91, 0xc3, 0x1e, 0xfa, 0x04, 0xd5, 0x51, 0xa4, 0x72, 0x11, 0x17, 0xb3, 0xe6, - 0xc2, 0x6c, 0x4a, 0x76, 0xf3, 0xc0, 0x65, 0x6f, 0xe4, 0x99, 0x44, 0xaf, 0xf6, 0xfe, 0x1b, 0x89, 0xe8, 0x80, 0x25, - 0x40, 0xbc, 0x62, 0x61, 0xca, 0x60, 0x60, 0x08, 0xd1, 0xb6, 0x68, 0x1c, 0x8c, 0x5e, 0xf3, 0xe5, 0x6a, 0x31, 0xdf, - 0xcd, 0x66, 0x24, 0x1b, 0x8d, 0x7e, 0x2d, 0xa0, 0x55, 0x3d, 0x6d, 0xfa, 0x37, 0x2c, 0xee, 0x27, 0xf9, 0xe1, 0x53, - 0xef, 0x3c, 0x8b, 0xe8, 0xa9, 0x07, 0xf8, 0xf2, 0x3c, 0x10, 0xc2, 0xf4, 0xfc, 0x05, 0xf4, 0x40, 0x88, 0xb6, 0x31, - 0x17, 0x96, 0x3c, 0x52, 0xe5, 0x7f, 0x5e, 0x95, 0x4f, 0xb0, 0xa0, 0x0e, 0x4d, 0xc2, 0x44, 0x01, 0xb3, 0x46, 0xce, - 0x62, 0xf3, 0x19, 0xf3, 0xbc, 0x4e, 0xb3, 0x77, 0x9d, 0xc4, 0x0d, 0xcb, 0x73, 0xf9, 0x6b, 0xcc, 0x13, 0xae, 0x1f, - 0xb2, 0x33, 0x2c, 0xea, 0x44, 0xd5, 0x80, 0x5f, 0x96, 0x16, 0x3f, 0x81, 0xd6, 0xa5, 0x81, 0x90, 0x58, 0x79, 0x85, - 0xcd, 0x63, 0xa9, 0xd2, 0x37, 0xe4, 0x35, 0xd2, 0x1d, 0x0e, 0x9e, 0x8f, 0xe1, 0xbe, 0x3b, 0xc0, 0x73, 0x52, 0xfd, - 0xfc, 0x89, 0x78, 0x4c, 0x04, 0x61, 0x1b, 0x84, 0xe8, 0xf6, 0xe5, 0x3a, 0xbd, 0xfd, 0x6d, 0x34, 0xe6, 0x46, 0x69, - 0x25, 0xdc, 0x3a, 0xb9, 0xea, 0xc4, 0x78, 0x79, 0x89, 0x9a, 0x13, 0xb7, 0xd3, 0xce, 0xe3, 0x20, 0x52, 0x5a, 0x8d, - 0x65, 0x1b, 0xe3, 0x34, 0x45, 0xe1, 0x91, 0x47, 0x02, 0x76, 0xe4, 0x25, 0x9c, 0x04, 0x54, 0xff, 0x63, 0x7c, 0xe6, - 0x9d, 0x25, 0xb0, 0x02, 0x89, 0x3f, 0x5f, 0xdc, 0x7a, 0xd4, 0xff, 0x33, 0x68, 0xad, 0x7a, 0x26, 0xbd, 0x33, 0x49, - 0x26, 0x7c, 0x76, 0x37, 0xe0, 0x5d, 0xd7, 0x46, 0x4c, 0x3e, 0x51, 0x31, 0x36, 0x20, 0xb5, 0xdf, 0xc6, 0xbe, 0x36, - 0xa3, 0xf4, 0xe6, 0x23, 0x7a, 0x06, 0xae, 0x7e, 0x44, 0xb8, 0xac, 0xd7, 0xd6, 0x7e, 0x07, 0x02, 0x74, 0x82, 0xe5, - 0x74, 0xe0, 0xb4, 0xcb, 0x17, 0xed, 0x93, 0x30, 0x5a, 0x00, 0xa9, 0xdc, 0x40, 0x66, 0x3c, 0xa2, 0x3a, 0x93, 0x31, - 0x36, 0x49, 0x8f, 0x1e, 0x74, 0xc2, 0xee, 0xdf, 0x01, 0x6b, 0x79, 0xc5, 0xb1, 0x76, 0xee, 0x20, 0x78, 0x92, 0x9c, - 0xbc, 0xaa, 0x67, 0x17, 0x6c, 0x69, 0x19, 0xcb, 0x43, 0x7f, 0x1e, 0x82, 0x98, 0x2e, 0xef, 0x6d, 0x23, 0x28, 0xa1, - 0x72, 0xf5, 0x07, 0x41, 0xa1, 0xcf, 0xfa, 0x17, 0x5b, 0x65, 0x53, 0x9d, 0xc7, 0x3e, 0xec, 0xbd, 0xeb, 0xab, 0xc2, - 0xc9, 0x45, 0xf3, 0x7e, 0x14, 0x87, 0x54, 0x75, 0x54, 0xbe, 0xb5, 0x58, 0xf6, 0xda, 0xec, 0x64, 0xa1, 0x3d, 0xf2, - 0x45, 0xfb, 0xd4, 0x1a, 0xb4, 0xd2, 0xb2, 0x28, 0xa4, 0xcd, 0x5c, 0xf4, 0xce, 0x67, 0xcc, 0x22, 0x8e, 0x88, 0xc0, - 0x72, 0xeb, 0x17, 0xf9, 0x23, 0xb6, 0x74, 0x44, 0x59, 0xf8, 0x46, 0x68, 0xea, 0x98, 0x93, 0x87, 0x13, 0x70, 0x5b, - 0x19, 0xde, 0x66, 0x20, 0x46, 0xb5, 0xc8, 0x21, 0x02, 0xfd, 0x8b, 0x63, 0x89, 0x38, 0x57, 0xbf, 0x50, 0x63, 0xe4, - 0x42, 0x0d, 0x42, 0x88, 0x5e, 0x0b, 0x65, 0xe6, 0xe3, 0xbc, 0x4b, 0xb2, 0x36, 0x66, 0x5f, 0xa1, 0x55, 0x63, 0x66, - 0xb6, 0x7a, 0x38, 0xb0, 0x45, 0xd0, 0xed, 0x25, 0x7e, 0x3b, 0x3b, 0x08, 0xdf, 0x4f, 0x45, 0x2e, 0xae, 0x05, 0x73, - 0xb1, 0x8f, 0x53, 0xe3, 0xd3, 0xfd, 0x87, 0x81, 0x62, 0x04, 0x87, 0xab, 0xf2, 0x8a, 0xd6, 0xb3, 0xe1, 0xfd, 0xc0, - 0xd7, 0xb1, 0x39, 0x26, 0xf3, 0xcc, 0x38, 0x58, 0xb1, 0x76, 0xc1, 0xbb, 0x1a, 0x26, 0xac, 0x22, 0x46, 0xb8, 0x5c, - 0x35, 0xc5, 0xda, 0x7c, 0x06, 0xeb, 0x23, 0x48, 0xe2, 0xca, 0x57, 0xe8, 0x8c, 0x0c, 0x0e, 0x66, 0x35, 0x1a, 0xf4, - 0xf3, 0xbe, 0xb4, 0xee, 0x11, 0x08, 0x73, 0x01, 0xb8, 0x7b, 0x73, 0x41, 0x81, 0x1c, 0x40, 0x76, 0xdf, 0x47, 0x00, - 0x19, 0x09, 0xcc, 0x4c, 0x24, 0x48, 0xd2, 0xaa, 0xb5, 0x8f, 0x79, 0x71, 0x09, 0x89, 0x1e, 0x02, 0x82, 0x59, 0x2b, - 0x77, 0x89, 0xea, 0x95, 0xd8, 0x9c, 0x30, 0x04, 0x5a, 0x7b, 0x56, 0x44, 0x4f, 0xd9, 0xfd, 0xab, 0x23, 0x10, 0xfe, - 0xa9, 0xb0, 0x78, 0xd6, 0x39, 0x53, 0x8c, 0xe7, 0x91, 0x65, 0xb6, 0xe0, 0xdf, 0x16, 0x96, 0x8b, 0xf7, 0x50, 0xcc, - 0xa1, 0x1b, 0x93, 0x39, 0x09, 0xbb, 0xef, 0x71, 0x50, 0x12, 0xa8, 0x7f, 0x14, 0xe6, 0x6e, 0x9c, 0xa3, 0x18, 0x3b, - 0x19, 0xe7, 0x12, 0x6a, 0xc5, 0x52, 0xb3, 0x11, 0x58, 0x73, 0xf2, 0x5c, 0x98, 0x4c, 0x2d, 0xf5, 0x49, 0x85, 0x12, - 0x76, 0x66, 0x4a, 0x52, 0x26, 0xe7, 0x45, 0xc1, 0x51, 0x53, 0x51, 0x99, 0xe2, 0x20, 0x94, 0x9f, 0xce, 0xfa, 0xc5, - 0xee, 0xf9, 0x11, 0xdb, 0xf1, 0x6a, 0x70, 0xdb, 0x90, 0xa9, 0x51, 0x53, 0xe0, 0xcf, 0x8c, 0x87, 0xe9, 0xff, 0xe4, - 0x20, 0x9d, 0x87, 0xf0, 0xce, 0xf4, 0xcb, 0x29, 0xb7, 0x81, 0x18, 0x3f, 0xd0, 0xc2, 0x5b, 0x5a, 0x8d, 0x12, 0xa9, - 0xff, 0x4a, 0xe2, 0x73, 0x74, 0xc2, 0x4a, 0x28, 0x25, 0x89, 0x4b, 0x38, 0xa4, 0xba, 0x63, 0xcc, 0xa8, 0x8c, 0x6e, - 0x41, 0x14, 0x34, 0xae, 0xd3, 0x88, 0x2c, 0xdc, 0x2a, 0x3a, 0xba, 0xf8, 0xc5, 0x9f, 0xd9, 0x87, 0xc1, 0x97, 0xc1, - 0x81, 0x40, 0x8e, 0x06, 0x41, 0xfb, 0xc3, 0x2b, 0x6c, 0x78, 0xd9, 0x79, 0xa1, 0x8e, 0x05, 0xe2, 0x51, 0xa7, 0x5e, - 0x42, 0x26, 0x21, 0xff, 0xd0, 0xa9, 0x12, 0x08, 0xe4, 0xcd, 0x0e, 0xab, 0xdf, 0xa0, 0x9f, 0x77, 0xda, 0x2d, 0x37, - 0x75, 0x13, 0x7a, 0x22, 0x84, 0x00, 0x48, 0x6c, 0x8d, 0x04, 0x91, 0xb7, 0x1a, 0x44, 0x52, 0x1d, 0x76, 0x5f, 0xe9, - 0x85, 0x20, 0xe0, 0x46, 0x6d, 0x34, 0x1a, 0x21, 0xf3, 0x0a, 0xb6, 0xc3, 0x4c, 0xc0, 0x38, 0x97, 0x51, 0xc6, 0x2f, - 0xf0, 0x50, 0x78, 0x25, 0x09, 0xbe, 0xa6, 0x4c, 0x7b, 0x0e, 0xa2, 0x5b, 0x6e, 0x2e, 0x3a, 0x1e, 0xc0, 0x20, 0x7a, - 0x02, 0xe6, 0x4f, 0xe6, 0xbf, 0x65, 0x67, 0xa4, 0x68, 0x20, 0x57, 0x7b, 0x87, 0x4b, 0xc6, 0xfc, 0xa9, 0xe4, 0x49, - 0x75, 0x4b, 0x81, 0x21, 0x72, 0xf1, 0xb2, 0xeb, 0x8f, 0x61, 0xae, 0xa8, 0x1d, 0xe0, 0x7d, 0xa2, 0x61, 0xf5, 0x62, - 0x3d, 0xa9, 0x6f, 0x8d, 0xc4, 0x7f, 0x51, 0x19, 0x1b, 0xe3, 0xa8, 0xf4, 0x42, 0x3c, 0xe9, 0x6e, 0xef, 0xac, 0xde, - 0x45, 0xae, 0xd6, 0xc4, 0x83, 0xc1, 0x5a, 0xb7, 0x42, 0x2b, 0xa7, 0xb6, 0xfc, 0x36, 0x87, 0x4b, 0x5f, 0x99, 0xb8, - 0x35, 0x5d, 0x20, 0x86, 0x82, 0xd2, 0xf1, 0xb8, 0xfc, 0x0c, 0x4f, 0x76, 0xf2, 0xa4, 0x33, 0x66, 0x66, 0x21, 0x3e, - 0xdd, 0xd9, 0x3c, 0xd3, 0x1f, 0x87, 0x2c, 0x21, 0x65, 0xaa, 0x9b, 0x9f, 0xe6, 0x85, 0x2f, 0x66, 0x3e, 0xcf, 0x27, - 0x9c, 0x71, 0x0b, 0x2b, 0xb4, 0x5e, 0x33, 0x7e, 0x4e, 0x18, 0x0e, 0xef, 0x2c, 0x4d, 0x94, 0x25, 0xa3, 0xe1, 0x1f, - 0x3f, 0xdf, 0x2d, 0x6d, 0xbe, 0xf3, 0xd3, 0xf1, 0x76, 0x12, 0x93, 0x02, 0x1b, 0xa5, 0x03, 0xc1, 0xf7, 0x80, 0xb2, - 0x97, 0xef, 0x6c, 0xcc, 0xe4, 0x7e, 0xd0, 0x41, 0x81, 0x61, 0x0b, 0x81, 0x0b, 0xad, 0x3f, 0xe4, 0x3d, 0xd6, 0x3b, - 0x55, 0x9e, 0xed, 0xa7, 0xe9, 0xbe, 0x2a, 0x0a, 0x05, 0x3f, 0xbb, 0xf5, 0xd8, 0x5b, 0x07, 0xcd, 0x91, 0x96, 0x30, - 0x79, 0x26, 0xd5, 0xe4, 0x67, 0x62, 0xaa, 0x08, 0x96, 0xbf, 0xfe, 0x32, 0xb9, 0xc8, 0x5d, 0xaf, 0x71, 0x10, 0xa6, - 0x66, 0xc2, 0xd4, 0xaf, 0x95, 0xb7, 0x23, 0xf5, 0x4f, 0xe9, 0xbb, 0x2b, 0x50, 0x57, 0x64, 0x2d, 0x40, 0xa4, 0x34, - 0x0c, 0xa9, 0x56, 0x87, 0x15, 0xa7, 0x6e, 0x83, 0x95, 0x1d, 0xbe, 0x80, 0x1b, 0x25, 0x67, 0x09, 0x51, 0xd1, 0xa6, - 0x26, 0x03, 0x87, 0x41, 0xa0, 0x30, 0x54, 0x14, 0x87, 0x47, 0x58, 0x7c, 0xd9, 0xe1, 0x45, 0xd3, 0x45, 0xb1, 0xe1, - 0xd5, 0x7e, 0xa2, 0x8c, 0x33, 0xb6, 0x8b, 0x0a, 0x40, 0x2d, 0x22, 0xfc, 0xf8, 0x34, 0xc0, 0xca, 0x9f, 0xf0, 0xb1, - 0x7b, 0x12, 0x96, 0x1e, 0x74, 0x29, 0x6a, 0xd9, 0x52, 0x4a, 0x53, 0x5b, 0xd4, 0x35, 0xce, 0x50, 0x71, 0xec, 0xf0, - 0xc8, 0x7a, 0x84, 0xf1, 0xdc, 0xe9, 0x22, 0xf8, 0x2c, 0x36, 0xc8, 0x23, 0x95, 0x20, 0xca, 0xdd, 0x32, 0x6e, 0x3d, - 0xe8, 0x63, 0x2e, 0x07, 0x61, 0xfb, 0x0c, 0xa5, 0x72, 0x11, 0x2b, 0x09, 0x2e, 0x83, 0xf2, 0x8f, 0x1e, 0xaa, 0x4c, - 0x74, 0xf2, 0x9e, 0x3a, 0xb6, 0x1d, 0x68, 0xac, 0xe9, 0x21, 0x89, 0x36, 0x6e, 0xd5, 0x62, 0x5c, 0x31, 0x75, 0x7a, - 0x6e, 0x89, 0x29, 0x41, 0x7e, 0x73, 0x39, 0xda, 0x9a, 0xba, 0x04, 0x62, 0x49, 0x89, 0xf8, 0x94, 0x4b, 0xfe, 0xae, - 0xeb, 0x24, 0xbe, 0x60, 0x2b, 0xb2, 0x64, 0xdc, 0xaa, 0xdd, 0x46, 0x5a, 0xcf, 0x05, 0x21, 0xf3, 0x2f, 0x35, 0x08, - 0x07, 0x9f, 0x2e, 0x58, 0xae, 0xc5, 0x47, 0xeb, 0xaf, 0x69, 0xd2, 0xa6, 0x07, 0x15, 0xb4, 0xd4, 0x41, 0x25, 0x2f, - 0x6b, 0xe6, 0x11, 0x57, 0xb3, 0x30, 0xbe, 0xa6, 0xdf, 0x5d, 0x72, 0x50, 0xd9, 0x19, 0x04, 0xf1, 0xe9, 0x20, 0xad, - 0x15, 0x79, 0xaa, 0x70, 0xaf, 0xd4, 0x5f, 0x89, 0x53, 0x0d, 0xa4, 0xf3, 0x02, 0x56, 0x08, 0xb9, 0x8e, 0x1f, 0xb8, - 0xda, 0x44, 0x80, 0x65, 0x99, 0xde, 0x6f, 0x2e, 0xa5, 0xd4, 0xf9, 0x01, 0xc0, 0xb3, 0xed, 0xa2, 0x5f, 0xa0, 0x39, - 0x01, 0x8c, 0x28, 0x50, 0x77, 0x21, 0xde, 0xea, 0x86, 0x8c, 0xb1, 0xfd, 0x92, 0xf6, 0xb0, 0x65, 0x3b, 0x06, 0x48, - 0x80, 0x91, 0x65, 0x58, 0xdc, 0x7b, 0x94, 0x8a, 0xd6, 0x74, 0x66, 0x63, 0x54, 0x95, 0xb4, 0x62, 0x7f, 0x79, 0x93, - 0xc8, 0xec, 0xd7, 0x8d, 0x8b, 0xa6, 0xbc, 0xb6, 0x48, 0x25, 0x8a, 0x13, 0x64, 0x65, 0xaa, 0xc8, 0x28, 0x8c, 0xb5, - 0xa3, 0x64, 0x81, 0xc7, 0xc5, 0x9e, 0x30, 0xa6, 0xff, 0x34, 0x15, 0x28, 0xdf, 0xbf, 0x6b, 0x1a, 0xa9, 0x50, 0x21, - 0xec, 0xc9, 0x72, 0x1a, 0x5b, 0xd1, 0xa7, 0xe2, 0x64, 0x4d, 0x22, 0xfd, 0xb7, 0x01, 0x06, 0x53, 0x1b, 0xf0, 0xe4, - 0x06, 0x29, 0x96, 0x10, 0x3e, 0x29, 0xdd, 0x67, 0x4d, 0x74, 0xa3, 0x32, 0xc0, 0x99, 0x1b, 0x37, 0x67, 0x2b, 0x0d, - 0x5c, 0xd9, 0x3a, 0x08, 0x53, 0x61, 0xe1, 0xce, 0xa6, 0x41, 0x8a, 0x4b, 0x8e, 0x94, 0x4c, 0xbf, 0x16, 0xc4, 0x8b, - 0x23, 0xfc, 0x2a, 0x7f, 0x72, 0x8b, 0x4c, 0x57, 0xa8, 0x2a, 0xa5, 0x53, 0xcc, 0x61, 0x7a, 0x98, 0x96, 0x2e, 0xe9, - 0xe5, 0x84, 0x77, 0x9e, 0x1f, 0xce, 0x05, 0x3d, 0x6d, 0xd5, 0x6a, 0xd5, 0x50, 0x18, 0xd0, 0x49, 0x47, 0x80, 0x78, - 0xd4, 0xf4, 0x97, 0xf0, 0xba, 0x92, 0x9b, 0x17, 0x71, 0x4d, 0x81, 0xe3, 0xb4, 0x7d, 0xed, 0xdc, 0x5f, 0x2e, 0xab, - 0x85, 0x1c, 0x24, 0x60, 0x2c, 0xa3, 0x0f, 0x81, 0xdc, 0xe9, 0xe9, 0xb3, 0xd2, 0xb2, 0x46, 0xd6, 0x27, 0x9b, 0x2d, - 0x3e, 0x79, 0x3f, 0x78, 0x81, 0x25, 0xdb, 0xe0, 0xe1, 0xad, 0xbe, 0xa6, 0xed, 0x64, 0x83, 0xb0, 0x16, 0x8d, 0x83, - 0x28, 0x56, 0xa0, 0x1d, 0xd9, 0x8a, 0xac, 0xcb, 0x9c, 0x64, 0x5f, 0x5f, 0xe4, 0x3f, 0xcf, 0x8a, 0x50, 0xa2, 0x05, - 0x8d, 0x9c, 0xc3, 0x1a, 0x2e, 0xe8, 0xa0, 0x34, 0x01, 0x83, 0x32, 0x00, 0x1b, 0x65, 0xec, 0xea, 0x34, 0x14, 0xf0, - 0x31, 0x46, 0x14, 0xca, 0x99, 0xcb, 0xd9, 0x5b, 0x5c, 0x58, 0x8b, 0x53, 0x66, 0x56, 0x9a, 0x7e, 0xa6, 0x85, 0xf9, - 0x7a, 0x23, 0x49, 0x10, 0xd9, 0x5a, 0x4e, 0x57, 0xae, 0x4b, 0xf4, 0xf4, 0x28, 0x28, 0x50, 0x59, 0x49, 0xc9, 0xb9, - 0x7c, 0x5e, 0xa1, 0xb3, 0x92, 0xf2, 0x2b, 0x4b, 0x4c, 0xc0, 0xd8, 0x26, 0x76, 0x8f, 0x9f, 0xcb, 0xca, 0xa7, 0x3c, - 0x66, 0x7c, 0xfa, 0xd3, 0xb6, 0xbe, 0x53, 0x58, 0x40, 0xa0, 0xe6, 0x0f, 0x6b, 0xae, 0xf4, 0xda, 0x8c, 0x81, 0x58, - 0x38, 0x31, 0xc0, 0xe7, 0xf0, 0x51, 0x01, 0xa3, 0xd4, 0x6c, 0x07, 0x13, 0x29, 0xd1, 0x92, 0x90, 0xc8, 0xb4, 0x1d, - 0xb4, 0x3e, 0x8b, 0x41, 0x59, 0x31, 0xc1, 0x35, 0xc5, 0x15, 0x6f, 0x57, 0x3b, 0x6a, 0x68, 0x5d, 0x23, 0x83, 0x78, - 0xa8, 0xa4, 0x3f, 0x3b, 0xde, 0x8f, 0x50, 0x10, 0x67, 0xa5, 0xc2, 0x5b, 0x9c, 0x6d, 0xed, 0xf8, 0x19, 0x05, 0xf7, - 0xc2, 0x5b, 0xb0, 0x31, 0x86, 0xa6, 0x6c, 0xb2, 0x62, 0xff, 0x6c, 0x06, 0xc4, 0x5e, 0xdf, 0x46, 0x86, 0xbb, 0xcd, - 0x8a, 0xc3, 0x07, 0xb3, 0xe5, 0x1f, 0xb1, 0xc7, 0xee, 0x3e, 0x79, 0x51, 0xac, 0x71, 0x6a, 0x0f, 0x6b, 0xc6, 0xb7, - 0xdf, 0x5b, 0x2e, 0x48, 0x8f, 0xe6, 0xda, 0x12, 0xd1, 0x13, 0xd3, 0x13, 0x0c, 0x0b, 0xa4, 0xc8, 0xea, 0x55, 0xca, - 0x54, 0xdb, 0x1b, 0xd6, 0x5e, 0x5a, 0x72, 0x55, 0x68, 0x0f, 0xc5, 0xec, 0xb2, 0x97, 0xe7, 0xb2, 0xe3, 0xeb, 0xe2, - 0xa3, 0x32, 0x6b, 0x8e, 0x95, 0x5f, 0x08, 0x53, 0x61, 0xaf, 0x0a, 0x72, 0x4a, 0x07, 0xeb, 0x08, 0xd5, 0x61, 0x98, - 0x2a, 0x1e, 0x3d, 0xb7, 0x25, 0xa4, 0x06, 0xbc, 0x1f, 0x5e, 0xe4, 0xf9, 0x55, 0xb4, 0xab, 0x00, 0x86, 0x4b, 0x01, - 0x07, 0x8f, 0x26, 0x08, 0x5c, 0x92, 0x10, 0x78, 0x9b, 0x41, 0x1f, 0xae, 0xdf, 0xbc, 0x7d, 0x0d, 0x65, 0x96, 0x33, - 0x6c, 0xa9, 0x38, 0xfb, 0x40, 0x7a, 0xb6, 0x2b, 0x92, 0xfa, 0x9e, 0x9a, 0xad, 0xb8, 0x35, 0xa6, 0x29, 0x12, 0x03, - 0xca, 0xae, 0x5a, 0xd3, 0xbd, 0x52, 0xd7, 0xf4, 0xec, 0x3c, 0x58, 0xd7, 0x12, 0xed, 0x0a, 0xa2, 0x52, 0x7f, 0x40, - 0xa2, 0xaf, 0x14, 0xda, 0x39, 0xb6, 0xae, 0x87, 0x3a, 0xaa, 0xa0, 0x5a, 0xc7, 0x08, 0xa9, 0xb6, 0xa5, 0x54, 0xfd, - 0x52, 0xeb, 0x70, 0xe9, 0x35, 0xc1, 0x70, 0xf4, 0xe0, 0x61, 0xbc, 0x4b, 0xd4, 0xa4, 0xdc, 0x5f, 0xf8, 0x12, 0xd6, - 0xdd, 0xee, 0x35, 0xf6, 0x7f, 0x51, 0xcf, 0xd6, 0x45, 0x37, 0xf1, 0x3e, 0xc8, 0xff, 0x57, 0x0f, 0x18, 0x99, 0x3c, - 0x7c, 0x38, 0xae, 0xb2, 0xde, 0x66, 0x31, 0x35, 0x25, 0x7f, 0x9d, 0x6b, 0xfa, 0x6a, 0xa5, 0x9d, 0x9a, 0xbb, 0x3b, - 0x39, 0xfb, 0x0d, 0x9b, 0x13, 0x87, 0x30, 0x4c, 0x94, 0xc8, 0xdd, 0x95, 0xc9, 0xa6, 0xeb, 0x72, 0xa9, 0xc1, 0x77, - 0x4b, 0x83, 0x90, 0xbc, 0x46, 0xe3, 0x87, 0x30, 0xcb, 0xa5, 0x44, 0x6c, 0x00, 0xcf, 0x9c, 0x99, 0xa8, 0x87, 0x8d, - 0x2d, 0x25, 0x88, 0xb2, 0x2a, 0x16, 0x5f, 0x65, 0x6a, 0xe7, 0xa8, 0x2a, 0x8d, 0xe2, 0xb9, 0x7b, 0xc3, 0x03, 0x86, - 0x64, 0xe2, 0xec, 0x57, 0xd0, 0xbb, 0xd0, 0x40, 0xba, 0x1d, 0xbb, 0x1f, 0xf0, 0x13, 0x29, 0xd1, 0xe7, 0xc1, 0x58, - 0x80, 0xd8, 0x22, 0x99, 0x65, 0x50, 0x28, 0x7e, 0x71, 0x2b, 0x5c, 0x25, 0x6a, 0x33, 0xde, 0xb3, 0x97, 0x2a, 0x6e, - 0x03, 0x33, 0xab, 0x96, 0x8f, 0x4c, 0x85, 0x10, 0x7b, 0xd5, 0x89, 0x7a, 0x96, 0x50, 0x36, 0xa3, 0x1e, 0xfe, 0xbe, - 0xa3, 0x1c, 0x8d, 0x28, 0xed, 0x68, 0x50, 0x8d, 0x85, 0xf7, 0x3b, 0x63, 0x7c, 0x67, 0xb6, 0x3f, 0x46, 0x88, 0x39, - 0xaf, 0x88, 0x83, 0x43, 0x38, 0x61, 0x78, 0xb5, 0xb5, 0x1c, 0x95, 0x21, 0x28, 0xdc, 0xf3, 0x4d, 0xcf, 0xcd, 0x46, - 0x59, 0x88, 0x19, 0x6f, 0xeb, 0xbc, 0x8f, 0x73, 0x19, 0xb9, 0x91, 0x99, 0x69, 0x18, 0x9b, 0x92, 0xe0, 0x1e, 0x70, - 0xa1, 0x24, 0xb0, 0x9c, 0xcb, 0xbf, 0x04, 0xc3, 0x9c, 0xd8, 0xfa, 0x07, 0xb6, 0xce, 0xf4, 0x3e, 0x1a, 0xc8, 0x55, - 0x8b, 0xfc, 0x8f, 0x76, 0xa5, 0xe9, 0x5f, 0x3a, 0x6b, 0x35, 0xcf, 0xd8, 0xc0, 0x0a, 0x1f, 0x50, 0x1d, 0x38, 0x40, - 0xaa, 0x17, 0x25, 0x41, 0xdc, 0x14, 0x5a, 0xf4, 0x32, 0x57, 0x9d, 0x68, 0xb4, 0x57, 0x6c, 0xc5, 0x38, 0xaf, 0xfd, - 0x97, 0xdb, 0x3d, 0x11, 0x73, 0x14, 0xa9, 0xa3, 0x86, 0x64, 0x2b, 0xf6, 0x87, 0xab, 0x4c, 0xe5, 0x9d, 0xe7, 0x2b, - 0x5f, 0xc1, 0x4b, 0xed, 0xef, 0xc8, 0x30, 0x24, 0xea, 0x42, 0xf5, 0xac, 0x80, 0xd7, 0xc7, 0x3f, 0x82, 0x7b, 0xa3, - 0x80, 0x28, 0xf8, 0x59, 0x21, 0xec, 0x9e, 0xcd, 0x6e, 0x3d, 0x1e, 0xfc, 0x3a, 0xae, 0xad, 0x75, 0x83, 0x67, 0x8a, - 0xff, 0xf8, 0x60, 0x15, 0x0e, 0x79, 0xe0, 0x7c, 0xa2, 0x77, 0xf7, 0xf3, 0xcb, 0x2f, 0x35, 0x7a, 0xfe, 0x42, 0xd8, - 0xcb, 0x56, 0x3a, 0x50, 0xd7, 0x28, 0x7e, 0xe2, 0x70, 0xac, 0x14, 0x35, 0xfc, 0x63, 0x9c, 0x38, 0x1f, 0xae, 0x8f, - 0x92, 0x69, 0x01, 0x16, 0x62, 0x1a, 0xba, 0x25, 0x71, 0x5e, 0x14, 0x67, 0xbd, 0xbb, 0x80, 0x9a, 0x4e, 0x7b, 0x80, - 0x52, 0x52, 0xcc, 0x13, 0x29, 0xd1, 0x5d, 0xfc, 0x9e, 0x9b, 0x4e, 0xee, 0xdc, 0xbe, 0x38, 0xac, 0x0f, 0x86, 0x6d, - 0x37, 0x19, 0xe3, 0x4f, 0x55, 0x9e, 0x30, 0xe2, 0x85, 0xb1, 0x2a, 0xe4, 0xf7, 0x08, 0x03, 0xfa, 0x7d, 0x38, 0x51, - 0x11, 0x7d, 0x3f, 0x00, 0xb8, 0xa7, 0x6e, 0x02, 0xaa, 0xf5, 0xf9, 0x4d, 0xef, 0x0a, 0x88, 0x26, 0x78, 0x51, 0xc9, - 0x6b, 0x80, 0x84, 0x5c, 0x5c, 0x9b, 0x72, 0x78, 0x37, 0x54, 0x24, 0xf4, 0xa1, 0x74, 0xce, 0xf4, 0x46, 0x06, 0x88, - 0xca, 0x31, 0x22, 0xbc, 0xe9, 0x4e, 0xf4, 0xa6, 0xbe, 0x87, 0x3f, 0x37, 0x63, 0xcf, 0x05, 0x86, 0x75, 0x6b, 0x7a, - 0xa6, 0x9f, 0x81, 0x6a, 0xc6, 0x9f, 0x7b, 0xd1, 0xd2, 0x53, 0xdb, 0x9a, 0x55, 0x8c, 0xc3, 0x5f, 0xcc, 0x83, 0x91, - 0xac, 0x2f, 0x2e, 0x22, 0xcc, 0x08, 0x6e, 0x56, 0x51, 0x2f, 0x2f, 0x59, 0xc2, 0xec, 0x6c, 0xd5, 0x38, 0xd0, 0x8c, - 0xb6, 0xa5, 0x07, 0xd7, 0xf9, 0x21, 0x96, 0xf1, 0x50, 0x1d, 0x5a, 0x3b, 0x8e, 0x6b, 0x9f, 0x41, 0x71, 0xb5, 0xc4, - 0x3f, 0x97, 0xf3, 0x25, 0xae, 0xf7, 0xcf, 0xfd, 0xb4, 0xd2, 0xdb, 0x54, 0xb3, 0x8f, 0xb9, 0xa5, 0x97, 0x24, 0xa4, - 0xef, 0x76, 0x18, 0xb0, 0x34, 0x19, 0x4c, 0xbe, 0x21, 0x39, 0xb0, 0x41, 0x95, 0x7c, 0x7a, 0xa0, 0xe7, 0x42, 0x07, - 0x2b, 0xa0, 0x1d, 0xf8, 0x0d, 0xcf, 0xeb, 0xb5, 0x10, 0x39, 0xdc, 0x20, 0x99, 0x00, 0x9d, 0x91, 0xc9, 0x85, 0xac, - 0xaa, 0x30, 0x81, 0x68, 0x2e, 0x21, 0x1a, 0xd4, 0x6d, 0x03, 0x67, 0x7c, 0x30, 0x29, 0x61, 0x3a, 0xdd, 0x2d, 0x95, - 0xce, 0x2b, 0x92, 0xa8, 0xeb, 0xfd, 0x30, 0xde, 0x0f, 0xcf, 0x3c, 0xc2, 0xbc, 0xdc, 0xee, 0x75, 0x91, 0xe5, 0xe5, - 0xd4, 0x42, 0xbb, 0x8f, 0xd9, 0xd1, 0x34, 0x5c, 0xea, 0x2e, 0xd8, 0x79, 0x60, 0x52, 0x5d, 0xd8, 0x83, 0x7d, 0x94, - 0x22, 0x4c, 0x73, 0xc9, 0xc8, 0xb2, 0xe8, 0xd2, 0x0c, 0xde, 0xe9, 0x00, 0x4f, 0x4b, 0xc4, 0x93, 0x20, 0xd2, 0xa4, - 0x17, 0x1b, 0x56, 0xd1, 0xe0, 0x6e, 0xd0, 0x9d, 0x19, 0x34, 0x54, 0x2c, 0x96, 0xea, 0xd1, 0x95, 0x72, 0x77, 0x62, - 0x69, 0x56, 0xd4, 0xf3, 0x81, 0x98, 0xec, 0xf9, 0x7a, 0x43, 0xaa, 0x14, 0x13, 0x16, 0xd1, 0xe8, 0xd3, 0x0f, 0x59, - 0xc5, 0x51, 0xc2, 0x62, 0xa5, 0xb8, 0xaa, 0xc8, 0xa9, 0xf1, 0xe6, 0x65, 0x56, 0x22, 0xed, 0xb0, 0x4c, 0x3c, 0x85, - 0x7c, 0x47, 0xd3, 0x4e, 0xcb, 0xac, 0xad, 0x62, 0x31, 0x7b, 0x02, 0x29, 0x11, 0x87, 0x75, 0x86, 0xb7, 0x65, 0x8e, - 0xd3, 0x60, 0x6d, 0xc9, 0xa9, 0x5f, 0xd0, 0x97, 0x30, 0xfb, 0x8c, 0xd5, 0x27, 0xa9, 0xd7, 0x91, 0x04, 0x28, 0xfe, - 0x4d, 0x1f, 0x04, 0x85, 0x5b, 0xfa, 0x7f, 0x7b, 0x6d, 0x38, 0x54, 0x0f, 0x75, 0xcf, 0x10, 0xab, 0x22, 0x15, 0xce, - 0xdd, 0x57, 0xe7, 0x93, 0x42, 0x3a, 0x99, 0x39, 0xe6, 0x91, 0x68, 0x2b, 0x2e, 0x07, 0x37, 0x2a, 0x23, 0x6a, 0x3a, - 0x7d, 0x50, 0x9d, 0xe1, 0xae, 0xde, 0xe7, 0x1a, 0xc2, 0xeb, 0x6a, 0x9f, 0xbb, 0xd3, 0x5b, 0xb1, 0xc5, 0x63, 0xae, - 0x4e, 0xdb, 0x89, 0x4b, 0xbb, 0xd4, 0xe9, 0x87, 0x23, 0xa8, 0xb8, 0x4c, 0xc4, 0x6c, 0x82, 0x0e, 0x2e, 0x8b, 0xa6, - 0x28, 0x75, 0xe9, 0x76, 0x92, 0x6b, 0x70, 0x07, 0x42, 0xaa, 0x72, 0x97, 0x19, 0x6e, 0xba, 0x10, 0x29, 0x3e, 0x93, - 0xae, 0x21, 0x92, 0xa2, 0x34, 0xbd, 0xe0, 0x34, 0x32, 0x72, 0xb7, 0x53, 0x99, 0x49, 0xeb, 0x90, 0x1a, 0xc7, 0x94, - 0x13, 0xf6, 0x32, 0x46, 0x70, 0xd0, 0xaa, 0x2f, 0x4b, 0x55, 0xe8, 0xfa, 0xa6, 0x67, 0xcb, 0x75, 0xfd, 0x87, 0x8f, - 0xc7, 0xcb, 0x51, 0x88, 0x2e, 0x6c, 0xaf, 0x94, 0x8e, 0x2c, 0xbd, 0x97, 0x8c, 0xb8, 0xe0, 0x50, 0xce, 0x5e, 0x0d, - 0x09, 0xb8, 0xa5, 0x57, 0x2c, 0xd2, 0xba, 0x71, 0x2d, 0xcb, 0xb4, 0x7b, 0xe5, 0x94, 0x49, 0x21, 0x56, 0xc6, 0x1a, - 0xc1, 0xfb, 0x69, 0xc4, 0xb0, 0xe9, 0x4d, 0xd8, 0x90, 0x4c, 0xcd, 0x5c, 0x6f, 0x28, 0x73, 0xf9, 0xa9, 0xf1, 0x23, - 0x36, 0x1a, 0x87, 0x60, 0xe8, 0xcc, 0x75, 0x1e, 0x0b, 0xe3, 0x0a, 0x66, 0x54, 0x23, 0xcb, 0x81, 0xb5, 0xd5, 0xda, - 0x0b, 0xb7, 0xa3, 0xde, 0x1c, 0x48, 0x7e, 0xe7, 0x65, 0xa6, 0x1a, 0xe3, 0xa0, 0xc5, 0x66, 0xed, 0x48, 0x23, 0x0a, - 0xbc, 0x78, 0x7a, 0x15, 0x41, 0xd1, 0xef, 0x49, 0x33, 0xc8, 0x41, 0x4b, 0xf5, 0xf5, 0xcf, 0x49, 0x89, 0xed, 0x98, - 0xa6, 0x05, 0x86, 0x59, 0xa5, 0x81, 0xbf, 0x26, 0x95, 0x86, 0x17, 0x36, 0x9f, 0x1f, 0xed, 0x12, 0xb9, 0xdc, 0xf3, - 0xac, 0xe6, 0x00, 0xc3, 0x74, 0xcc, 0x8d, 0x7f, 0x8f, 0xa2, 0x9f, 0x6c, 0x1c, 0x83, 0xd1, 0xd3, 0x2f, 0x4a, 0x3d, - 0x9b, 0x49, 0x7b, 0x5e, 0x53, 0x17, 0x70, 0x3c, 0x19, 0xe9, 0x00, 0x3c, 0x48, 0x27, 0x76, 0x1f, 0xc0, 0x25, 0x63, - 0x2f, 0x41, 0x17, 0xbb, 0xaf, 0x01, 0x48, 0xb6, 0x63, 0x8b, 0xdc, 0x8a, 0x91, 0xaf, 0x92, 0x4a, 0x79, 0x29, 0x7f, - 0x25, 0xb3, 0x11, 0xc0, 0xbe, 0x4a, 0x2f, 0x0f, 0xb8, 0x1b, 0xa5, 0xb7, 0x03, 0x82, 0xdd, 0x02, 0x61, 0xdf, 0x6d, - 0xd5, 0xa8, 0x81, 0xdd, 0x5f, 0x98, 0xb1, 0x69, 0x01, 0x1b, 0x19, 0xfa, 0xc3, 0xad, 0x4f, 0x94, 0x53, 0x10, 0x7e, - 0xff, 0xd2, 0xdc, 0x8d, 0x2b, 0x33, 0x18, 0x25, 0xb6, 0x43, 0x60, 0x3e, 0x53, 0xf9, 0x12, 0xe5, 0x27, 0xe1, 0xe5, - 0x6a, 0xd7, 0x9f, 0x95, 0x73, 0x29, 0xe6, 0xce, 0x35, 0xfc, 0x36, 0x1a, 0x3f, 0x2a, 0xed, 0x3a, 0xcf, 0xa2, 0x4b, - 0xdc, 0xe7, 0xfe, 0x3e, 0x80, 0x23, 0x6f, 0xcc, 0x87, 0x89, 0x7c, 0x27, 0x19, 0x56, 0x68, 0xf3, 0x76, 0x23, 0x3d, - 0xfc, 0xf6, 0x8d, 0xd4, 0x23, 0x7e, 0xac, 0x8a, 0xe0, 0xd7, 0x4d, 0x01, 0x6c, 0x82, 0x53, 0xcf, 0x5f, 0x37, 0xa9, - 0xe3, 0xc7, 0x4b, 0x48, 0xfa, 0x26, 0xcc, 0xdd, 0xbb, 0xd9, 0xe0, 0xe9, 0x10, 0x9e, 0x65, 0x44, 0x07, 0x03, 0x99, - 0x5b, 0x93, 0x1b, 0xf4, 0x5f, 0x30, 0xcd, 0xb7, 0x83, 0xc0, 0x26, 0x9e, 0x25, 0x15, 0x5f, 0x74, 0xf7, 0x36, 0x34, - 0x75, 0x10, 0x15, 0x0d, 0xc4, 0x25, 0x1b, 0xb8, 0xd9, 0x0a, 0xca, 0x73, 0x63, 0xa8, 0xb3, 0xe7, 0x88, 0xdd, 0x56, - 0xda, 0xbd, 0x95, 0x8b, 0x57, 0x94, 0xa8, 0x11, 0x50, 0x21, 0xe8, 0x2e, 0x7f, 0x28, 0xf7, 0x25, 0xdd, 0x59, 0x69, - 0xca, 0x5c, 0x24, 0x98, 0xd7, 0x05, 0x55, 0x3f, 0x80, 0x04, 0xb4, 0x0f, 0x09, 0xa8, 0xd0, 0x7d, 0xf9, 0x35, 0x93, - 0x79, 0xeb, 0x49, 0xac, 0xab, 0xf0, 0xc3, 0x00, 0x0e, 0xff, 0xa5, 0x21, 0x23, 0x21, 0x7b, 0xb9, 0x5f, 0xd7, 0x43, - 0xdd, 0xd2, 0x71, 0x1b, 0xab, 0x79, 0xa0, 0xac, 0x23, 0x1c, 0x27, 0x56, 0xdb, 0xef, 0x06, 0xa4, 0xe5, 0xb8, 0xbf, - 0xaa, 0xe9, 0xd2, 0x6e, 0x5e, 0x87, 0x61, 0x1d, 0xb6, 0x86, 0xe5, 0x17, 0xe6, 0x8a, 0x87, 0xf6, 0x1c, 0xfe, 0xdb, - 0x57, 0xc6, 0x97, 0x34, 0xfb, 0xbf, 0x15, 0x4f, 0x83, 0x44, 0xd3, 0x67, 0x29, 0x92, 0x30, 0x4a, 0xf7, 0x27, 0x12, - 0x25, 0x0d, 0x24, 0x72, 0x70, 0x2f, 0xdf, 0xd2, 0xf8, 0x57, 0xa5, 0x2c, 0x43, 0x87, 0xcb, 0x66, 0x07, 0x32, 0x6f, - 0x9d, 0xbb, 0xbf, 0x1c, 0x7a, 0x0b, 0x54, 0xe9, 0x14, 0x26, 0x2f, 0x3d, 0x5c, 0xb1, 0x65, 0xcf, 0x62, 0xe8, 0xa7, - 0x60, 0x2a, 0x46, 0xb2, 0x19, 0x26, 0xe6, 0x2a, 0x85, 0xc8, 0x2f, 0x8f, 0x3a, 0xb9, 0xbb, 0xe5, 0x6f, 0x6e, 0x7d, - 0xbc, 0x28, 0x79, 0x63, 0x76, 0x66, 0x7b, 0x3e, 0x76, 0xfb, 0x3d, 0x2b, 0x72, 0x27, 0xec, 0x74, 0xf4, 0x0e, 0xb9, - 0xe6, 0x4e, 0x68, 0x2a, 0x60, 0xb9, 0x38, 0x4f, 0xad, 0xd4, 0xc4, 0xa0, 0x44, 0x28, 0x23, 0xf1, 0x0f, 0xd1, 0x36, - 0xec, 0x25, 0x55, 0xf7, 0x1e, 0x84, 0x62, 0xdb, 0x23, 0x11, 0x48, 0xf1, 0x8f, 0x82, 0x52, 0x4a, 0x58, 0x97, 0x46, - 0x99, 0x29, 0x3f, 0xa1, 0xb0, 0x03, 0x07, 0x01, 0x1f, 0x12, 0x68, 0x69, 0x28, 0xeb, 0xbf, 0xdf, 0x30, 0xea, 0xb2, - 0x1f, 0x4b, 0xf2, 0x57, 0x8d, 0xea, 0x5a, 0xa2, 0x7f, 0xbc, 0xcc, 0x4f, 0x69, 0x0a, 0x1e, 0x14, 0x7a, 0x5d, 0x3b, - 0xdd, 0x27, 0x4c, 0x6d, 0x57, 0x2e, 0x12, 0x5f, 0xda, 0x53, 0xfe, 0x08, 0x6a, 0xd3, 0xd4, 0xd8, 0x5c, 0x2f, 0x54, - 0x33, 0xa5, 0x28, 0x2b, 0xbc, 0x6a, 0x2c, 0xb4, 0xe2, 0x90, 0x54, 0x49, 0x9c, 0x33, 0xf7, 0xd8, 0xd5, 0x9b, 0xf0, - 0x82, 0x30, 0x50, 0x60, 0x92, 0x59, 0x6c, 0x44, 0x5f, 0xa1, 0x2f, 0xe9, 0xcb, 0x74, 0xb5, 0x1f, 0x19, 0xf0, 0x06, - 0x87, 0xa3, 0x55, 0x0d, 0xf9, 0x2a, 0x25, 0xaa, 0x44, 0x31, 0x88, 0x52, 0xc7, 0x6f, 0x60, 0x0b, 0xcc, 0xcf, 0x27, - 0x0b, 0xfa, 0xba, 0xac, 0x39, 0x65, 0xbf, 0x59, 0xf3, 0x27, 0x43, 0x7e, 0x3c, 0x6e, 0x91, 0xbb, 0x8e, 0xc8, 0x25, - 0x42, 0xd4, 0x9f, 0xdf, 0x76, 0xad, 0x27, 0x22, 0x9f, 0xd7, 0x66, 0xb1, 0xd8, 0xe5, 0x02, 0xf6, 0x9b, 0xb3, 0x72, - 0xe3, 0xc4, 0xae, 0x3f, 0xf2, 0xc4, 0x33, 0xf9, 0xc4, 0x6d, 0x18, 0x28, 0xef, 0x61, 0xbd, 0xb0, 0x74, 0x4d, 0x02, - 0x50, 0x62, 0xe8, 0xd3, 0xaf, 0x50, 0xad, 0xec, 0x58, 0x6c, 0x2e, 0x79, 0x52, 0x86, 0x40, 0xf1, 0xf5, 0xfd, 0x25, - 0xf9, 0x34, 0x56, 0x20, 0xa5, 0x61, 0x1e, 0x81, 0x45, 0x31, 0x14, 0x35, 0xd4, 0x72, 0xf1, 0x06, 0x6f, 0x60, 0x08, - 0x5f, 0x68, 0x75, 0xb8, 0x6c, 0x37, 0x08, 0x77, 0xc9, 0x8e, 0x95, 0x4e, 0x29, 0x57, 0xe3, 0x00, 0x84, 0x97, 0x3f, - 0x02, 0x50, 0x17, 0x6a, 0x4d, 0xb0, 0xb7, 0x72, 0xb2, 0xdf, 0xdc, 0x11, 0x34, 0xc0, 0x7b, 0xff, 0x2c, 0xfe, 0x74, - 0xfc, 0x41, 0x21, 0x75, 0x27, 0xe5, 0xb5, 0x54, 0xba, 0xd5, 0x7a, 0x4b, 0xba, 0x57, 0xb0, 0xdd, 0x5c, 0xf5, 0x26, - 0xa3, 0x54, 0xeb, 0xfc, 0x3e, 0x19, 0x28, 0x30, 0x53, 0x4d, 0x28, 0x5d, 0x1c, 0x49, 0xed, 0x92, 0x9e, 0x2e, 0x6b, - 0xe8, 0x6f, 0x39, 0xb1, 0x15, 0xec, 0x8f, 0xab, 0x63, 0xc9, 0xb7, 0xf8, 0xfc, 0x2b, 0xc0, 0xde, 0x95, 0x1f, 0xfe, - 0x24, 0xcc, 0xcf, 0x45, 0x97, 0x36, 0xea, 0x91, 0xa3, 0x9e, 0xf7, 0xb7, 0x3c, 0xfa, 0x09, 0xb2, 0x1d, 0x9b, 0x87, - 0xbc, 0xdf, 0xbf, 0xf9, 0xb5, 0x6b, 0xfc, 0xd4, 0x4e, 0x36, 0xa1, 0xd9, 0xb5, 0xf2, 0x5e, 0x7e, 0x0f, 0xfe, 0xe4, - 0x76, 0x8f, 0x4c, 0xaa, 0x61, 0x75, 0x06, 0x7e, 0x18, 0x64, 0x85, 0x5e, 0xfd, 0xb4, 0x67, 0x98, 0x93, 0x7d, 0x88, - 0x1a, 0xdc, 0xe4, 0x86, 0xc6, 0xae, 0x19, 0xd3, 0xb0, 0xad, 0xaf, 0xf1, 0x5c, 0xa3, 0x9c, 0xef, 0x6b, 0xd5, 0x90, - 0xeb, 0xac, 0xa7, 0xd5, 0xf3, 0x8d, 0x09, 0x9c, 0x01, 0x6e, 0x75, 0xc5, 0x2c, 0xa4, 0x20, 0xf9, 0xd6, 0x9e, 0x83, - 0xdb, 0x6a, 0x20, 0xe4, 0x9d, 0x73, 0x9f, 0x48, 0x81, 0x3f, 0xed, 0x7a, 0x27, 0x93, 0x55, 0xbf, 0xf1, 0xad, 0xda, - 0x6d, 0xff, 0xef, 0x46, 0xfc, 0xa3, 0x90, 0x3a, 0x7d, 0xce, 0x9f, 0x42, 0x58, 0x88, 0x6f, 0x74, 0x82, 0x2b, 0xe8, - 0x56, 0x95, 0xc2, 0xbc, 0x97, 0x36, 0xe7, 0xbd, 0x32, 0x07, 0x2d, 0x29, 0xe3, 0x09, 0x5b, 0x5c, 0xd4, 0xdb, 0x6e, - 0x46, 0xe9, 0x16, 0xe6, 0x47, 0x57, 0x2a, 0xb0, 0x20, 0x21, 0x49, 0x53, 0x64, 0xf0, 0x4f, 0x72, 0xe4, 0xb9, 0x0a, - 0x21, 0xdd, 0x68, 0xd2, 0x51, 0x67, 0xb5, 0xb8, 0xa9, 0xe3, 0x93, 0xf8, 0xb4, 0x46, 0xbb, 0xd6, 0x09, 0xff, 0x40, - 0xff, 0x3a, 0xd5, 0x4a, 0xfe, 0xfb, 0x54, 0x37, 0xf2, 0x5f, 0x67, 0x3a, 0x91, 0xff, 0x3e, 0xd3, 0xae, 0x87, 0x57, - 0x8f, 0xac, 0xab, 0x27, 0xd6, 0xd5, 0x33, 0x6b, 0xcc, 0x90, 0x1e, 0x5a, 0xe7, 0x3a, 0xff, 0xec, 0xc4, 0xf9, 0xa4, - 0xb5, 0x64, 0x9f, 0x6f, 0x95, 0xc2, 0x92, 0xf5, 0x6f, 0x27, 0xcd, 0x7c, 0x56, 0x4d, 0xe5, 0xe3, 0x01, 0x2a, 0x4f, - 0x3e, 0x0e, 0xea, 0x5c, 0x45, 0x44, 0x8d, 0x59, 0x51, 0x7b, 0xca, 0xec, 0xee, 0x9d, 0x78, 0x32, 0x7d, 0x88, 0xe8, - 0x6d, 0xe9, 0x66, 0xa8, 0xf4, 0x40, 0x7e, 0x6a, 0xd8, 0xb1, 0x11, 0xf5, 0xa0, 0xf1, 0xd2, 0xdd, 0x23, 0x31, 0xbe, - 0x5f, 0x0a, 0x11, 0x2b, 0xd2, 0x0a, 0x8a, 0x6f, 0x30, 0xf5, 0x50, 0xab, 0x16, 0x7b, 0xee, 0xc7, 0x6c, 0xe9, 0x5e, - 0x52, 0x62, 0x10, 0xc6, 0x76, 0x85, 0xff, 0x2c, 0xc0, 0xaa, 0xf8, 0x99, 0x59, 0x3a, 0x6d, 0xe6, 0x68, 0xe9, 0xf4, - 0x4b, 0xb6, 0x20, 0x5e, 0x86, 0x31, 0xdd, 0x91, 0x64, 0xec, 0x2e, 0x14, 0x5c, 0x41, 0x36, 0x7f, 0x8c, 0x8a, 0x7f, - 0x8a, 0xd5, 0xc3, 0xd3, 0x07, 0x65, 0x18, 0xfc, 0x4f, 0x13, 0xed, 0xa0, 0x1d, 0xa1, 0x8e, 0x71, 0xba, 0x25, 0x15, - 0xee, 0x0b, 0x14, 0xaf, 0xe7, 0xfe, 0x14, 0x55, 0xdf, 0x3a, 0x25, 0x24, 0x2e, 0x67, 0xdb, 0xcf, 0xdd, 0x1c, 0x7a, - 0xb2, 0xcf, 0x8f, 0x29, 0xc8, 0x4d, 0x37, 0xfc, 0x26, 0x58, 0x65, 0xf3, 0xc6, 0x6a, 0x57, 0x4f, 0xe2, 0xf2, 0x97, - 0xff, 0xd3, 0x7e, 0x9e, 0x40, 0xfb, 0xfd, 0x49, 0x3f, 0xf2, 0xd3, 0xe3, 0x18, 0x9d, 0x78, 0x33, 0x47, 0x1f, 0x7e, - 0x2e, 0xca, 0x37, 0xfb, 0x54, 0x3d, 0x4e, 0x76, 0xf3, 0x47, 0xf4, 0x1c, 0xfd, 0xd4, 0x6d, 0x35, 0xfd, 0xc7, 0x09, - 0xb4, 0xcf, 0x9f, 0xf5, 0xe3, 0xb3, 0x3b, 0x68, 0xfa, 0x23, 0xd3, 0xe4, 0x91, 0xcd, 0xf2, 0x95, 0xc5, 0x47, 0x59, - 0xd7, 0x38, 0xdc, 0x4c, 0x73, 0xad, 0x2b, 0x3c, 0xbd, 0xe9, 0x78, 0xa8, 0x8a, 0xc5, 0x31, 0x3e, 0x3d, 0x9e, 0xe0, - 0x43, 0x36, 0xfa, 0xcc, 0xe8, 0x52, 0x44, 0xef, 0xc9, 0x31, 0x44, 0x97, 0xcd, 0xa7, 0xe4, 0x2c, 0x9e, 0x3b, 0x47, - 0x5b, 0xe5, 0x1a, 0x59, 0x18, 0xb5, 0x86, 0xa7, 0xb8, 0x31, 0xfc, 0x9e, 0x53, 0x0e, 0x0c, 0x56, 0x22, 0xb5, 0x87, - 0xa9, 0x62, 0x7a, 0x4b, 0xa2, 0x4f, 0x4a, 0x71, 0xd4, 0x7e, 0x1b, 0x5d, 0x0d, 0x85, 0x27, 0x0f, 0x1c, 0xd5, 0x55, - 0x39, 0x7c, 0xc6, 0x49, 0xef, 0xdc, 0x88, 0xfa, 0xcb, 0xe0, 0x9b, 0x38, 0xd3, 0xa5, 0xeb, 0x4f, 0xd7, 0x91, 0x4f, - 0xba, 0x49, 0x53, 0x56, 0x6f, 0xab, 0xe9, 0x62, 0x8c, 0xce, 0x24, 0xcf, 0x82, 0x94, 0x10, 0x61, 0xac, 0xf0, 0xfc, - 0xf3, 0x69, 0xdb, 0x84, 0x09, 0xdb, 0x24, 0xaf, 0x05, 0x55, 0x44, 0xff, 0xf1, 0x90, 0x3a, 0x1c, 0xc4, 0x86, 0xea, - 0x5d, 0xdf, 0x1e, 0x33, 0xac, 0xcd, 0x8c, 0x78, 0xab, 0xc8, 0x3d, 0x0e, 0x92, 0x59, 0x16, 0x1f, 0x54, 0x9b, 0xe2, - 0xf7, 0xea, 0xc4, 0x38, 0x8d, 0x1a, 0x8f, 0x70, 0x66, 0xa6, 0xcd, 0xd9, 0x8e, 0x17, 0xf5, 0xae, 0xd6, 0x2f, 0x4f, - 0xc7, 0x87, 0xfe, 0xe1, 0x10, 0x2e, 0xe5, 0x61, 0x41, 0x7c, 0x5a, 0x3c, 0x8b, 0x1d, 0x1b, 0x27, 0xe3, 0xf0, 0x3f, - 0xb5, 0x23, 0xe3, 0x4e, 0x51, 0xc2, 0xa9, 0x7e, 0x9a, 0xd2, 0x59, 0xee, 0xa3, 0xe2, 0x1e, 0xb0, 0x1d, 0xce, 0x85, - 0xdb, 0x3d, 0x8f, 0x8c, 0xe8, 0x40, 0x55, 0x5f, 0xbf, 0x83, 0xe6, 0x5f, 0xe3, 0xfa, 0x0e, 0x14, 0xb1, 0xbe, 0xbf, - 0x9c, 0x62, 0x4e, 0x57, 0xe0, 0x98, 0x6f, 0xf9, 0x8e, 0x55, 0x13, 0xcf, 0xea, 0xaf, 0x87, 0xa7, 0x58, 0x85, 0x43, - 0xc1, 0x49, 0xc1, 0x21, 0xb1, 0x69, 0xca, 0x50, 0x38, 0xac, 0x11, 0x7e, 0xf5, 0x69, 0xea, 0x74, 0x71, 0x02, 0xe7, - 0x06, 0xc1, 0x54, 0x0b, 0xda, 0xf3, 0x63, 0x24, 0xde, 0x96, 0xa7, 0x85, 0x22, 0x1b, 0x9c, 0xa3, 0xf2, 0xd7, 0xcc, - 0x62, 0xe7, 0x70, 0x91, 0xff, 0xf3, 0x84, 0x3f, 0x1c, 0x43, 0xd0, 0xc8, 0xb2, 0x63, 0xf1, 0x9b, 0x49, 0x19, 0xde, - 0x3e, 0xe6, 0x5a, 0xb1, 0xa9, 0x27, 0xe3, 0x1f, 0x0e, 0x69, 0x66, 0x1f, 0x3d, 0xa2, 0xac, 0x40, 0xb4, 0xdd, 0xd9, - 0x56, 0x3f, 0x19, 0xa2, 0x96, 0x67, 0xca, 0x93, 0xfd, 0x04, 0xef, 0xd2, 0x0f, 0xf6, 0x83, 0x71, 0x3c, 0x48, 0x42, - 0x43, 0x65, 0xa5, 0x3f, 0x46, 0x85, 0x22, 0x9d, 0xaf, 0xf5, 0xa9, 0x0e, 0x5c, 0x09, 0x05, 0x4c, 0xb9, 0xd6, 0x5c, - 0x33, 0x1c, 0xdb, 0xf2, 0x2c, 0x2f, 0x8c, 0x2d, 0xc0, 0xa7, 0xfc, 0x2a, 0x44, 0x1b, 0x9c, 0x1b, 0x51, 0x16, 0xc8, - 0x44, 0x17, 0x45, 0x5f, 0xb3, 0x38, 0x34, 0xbb, 0x6a, 0x30, 0x4e, 0x43, 0x7f, 0xbd, 0x76, 0x3d, 0xd7, 0x29, 0x65, - 0x2d, 0x72, 0xe7, 0xa6, 0x63, 0x19, 0x36, 0x14, 0x39, 0xe5, 0x66, 0x3e, 0x91, 0x42, 0xdd, 0x40, 0x6f, 0x01, 0xae, - 0x9b, 0xf1, 0xc7, 0x2c, 0x90, 0xc4, 0x6a, 0x00, 0x06, 0x59, 0xfc, 0x8e, 0x00, 0x40, 0x49, 0x5f, 0x94, 0x81, 0x37, - 0x1c, 0x6e, 0x78, 0x5d, 0xd0, 0x5b, 0xed, 0xca, 0xe5, 0x29, 0x16, 0xee, 0xec, 0xf6, 0x3f, 0xaa, 0x27, 0xcf, 0xa1, - 0xb2, 0x23, 0xf3, 0xe9, 0xac, 0xb9, 0x87, 0xb8, 0x95, 0x21, 0xbf, 0x20, 0xe0, 0x02, 0x24, 0x50, 0x3a, 0xc2, 0x39, - 0xe3, 0x92, 0x6b, 0xdc, 0x55, 0xb3, 0x84, 0x12, 0x2c, 0xa1, 0xe3, 0xe7, 0x56, 0xd1, 0x81, 0x7a, 0x57, 0x4f, 0xb7, - 0xee, 0x41, 0x4a, 0xc9, 0xa7, 0x15, 0xeb, 0xc4, 0xf1, 0xfa, 0x35, 0x89, 0xe8, 0xc9, 0x43, 0x79, 0x9a, 0x73, 0x01, - 0xf9, 0x2d, 0x1b, 0x15, 0x33, 0xf3, 0x54, 0x8f, 0xfc, 0xd4, 0x14, 0xeb, 0xf6, 0x70, 0x07, 0xf4, 0xb4, 0x81, 0xf8, - 0x41, 0x71, 0x3f, 0x8b, 0xbc, 0xc6, 0xc3, 0x2c, 0x30, 0x8b, 0x98, 0x5a, 0x8d, 0x34, 0x3b, 0x52, 0x12, 0xd6, 0x42, - 0x26, 0x68, 0xae, 0x33, 0xb2, 0x69, 0xd7, 0x68, 0x17, 0x05, 0x46, 0x34, 0x1d, 0x6c, 0xaf, 0x91, 0x0c, 0xba, 0x8d, - 0xeb, 0x88, 0x10, 0x43, 0x05, 0xe8, 0xe3, 0x20, 0x14, 0xca, 0x3e, 0xa3, 0xf2, 0x22, 0x37, 0xeb, 0xe7, 0x42, 0x30, - 0x5a, 0x98, 0xa1, 0xaa, 0x1c, 0xbb, 0xa6, 0x40, 0xbe, 0x88, 0x8d, 0x20, 0x3b, 0xe5, 0xe3, 0x65, 0x3b, 0x55, 0x3d, - 0xdc, 0x44, 0xd5, 0x3f, 0xb0, 0xde, 0x5e, 0xb4, 0x7d, 0xc0, 0x2f, 0xb5, 0x23, 0xb7, 0x05, 0xae, 0x46, 0xe3, 0x9c, - 0x24, 0x8e, 0xdc, 0x3c, 0xce, 0xf5, 0x83, 0x59, 0x9f, 0xb4, 0xd6, 0x0e, 0xf2, 0x29, 0x02, 0x56, 0x29, 0x75, 0x92, - 0x5e, 0xfb, 0x28, 0xe3, 0xf1, 0x20, 0x21, 0x29, 0x5f, 0x30, 0x3e, 0x9b, 0x7d, 0xe6, 0x45, 0xc9, 0x02, 0xb3, 0x88, - 0x4a, 0xac, 0xc1, 0x74, 0x6c, 0x97, 0xc8, 0x48, 0x77, 0x02, 0xa7, 0x72, 0xac, 0x28, 0xec, 0x6e, 0x57, 0xb3, 0x6f, - 0x26, 0x6f, 0x4d, 0xea, 0x3b, 0xc6, 0x5c, 0xd0, 0x6b, 0xa3, 0xb4, 0x01, 0xb4, 0x07, 0x03, 0x87, 0xd5, 0x85, 0xd9, - 0x69, 0x35, 0xdb, 0xd4, 0x33, 0x62, 0x73, 0xd3, 0xd3, 0xd5, 0x44, 0x3f, 0x43, 0xc0, 0x38, 0x36, 0x8a, 0x7b, 0x6c, - 0x11, 0x6b, 0xe4, 0x35, 0xb5, 0x84, 0xd9, 0xb2, 0x70, 0x2b, 0x46, 0x73, 0x02, 0x63, 0x8c, 0xc9, 0x41, 0x0c, 0x9e, - 0x9b, 0xc3, 0x66, 0x4d, 0x4c, 0xa0, 0x6a, 0x7f, 0x53, 0x46, 0x96, 0xac, 0x62, 0x96, 0x06, 0x32, 0x2c, 0x03, 0x65, - 0xef, 0x85, 0x96, 0x3e, 0xda, 0xb9, 0x10, 0x6a, 0xda, 0xb6, 0xec, 0x36, 0x74, 0x48, 0x81, 0x0f, 0x4c, 0xb7, 0x3b, - 0x07, 0xae, 0xd8, 0xa3, 0xe0, 0x9d, 0xc1, 0xe3, 0x0f, 0xb3, 0x67, 0xc9, 0xef, 0x79, 0xa1, 0xca, 0xf5, 0x89, 0x8e, - 0x76, 0x0b, 0xc8, 0xc4, 0xec, 0xda, 0x96, 0x8f, 0xf6, 0x39, 0x3d, 0x64, 0xb8, 0x82, 0x8c, 0x23, 0x49, 0x11, 0x95, - 0xaf, 0xf4, 0x2a, 0xcb, 0x58, 0xb0, 0xcc, 0x65, 0xcc, 0x92, 0x9a, 0x4c, 0xaa, 0xbd, 0x9b, 0xc1, 0x93, 0xd7, 0x2c, - 0x4c, 0xa6, 0xb0, 0x66, 0x9b, 0x5d, 0x29, 0x47, 0x13, 0x44, 0x26, 0x71, 0x92, 0x64, 0x74, 0x06, 0x1f, 0x04, 0xa2, - 0xe4, 0x44, 0x50, 0xcd, 0xbe, 0x1f, 0xd5, 0x64, 0xad, 0x83, 0x51, 0x49, 0x95, 0xc1, 0xeb, 0x26, 0x45, 0x84, 0x26, - 0x49, 0xbe, 0x76, 0xc4, 0x64, 0x5b, 0xc7, 0xb9, 0x62, 0x95, 0x65, 0x1b, 0x47, 0x16, 0xb9, 0xd2, 0x90, 0x4a, 0x13, - 0xbd, 0xa0, 0x74, 0xe5, 0x5d, 0x28, 0x80, 0x88, 0x43, 0x2b, 0xc8, 0xed, 0xa5, 0x31, 0x13, 0x88, 0xf4, 0xc8, 0xfa, - 0x70, 0x64, 0x2b, 0xe9, 0x62, 0xa3, 0x14, 0x2c, 0x9e, 0x10, 0x16, 0x19, 0x7b, 0xc6, 0xea, 0x6f, 0xbf, 0x6b, 0x8a, - 0xb5, 0xdf, 0x1e, 0xd8, 0x9e, 0xff, 0xdd, 0xfb, 0xfd, 0x48, 0x01, 0x18, 0x71, 0x2f, 0x47, 0x44, 0xfc, 0x56, 0xe7, - 0xb7, 0x88, 0xdf, 0x7c, 0xfe, 0x6d, 0x78, 0x81, 0xae, 0x6b, 0x6c, 0x98, 0x69, 0xe7, 0x56, 0x95, 0x8e, 0xd8, 0x10, - 0x0b, 0xef, 0xf5, 0x29, 0xe9, 0x69, 0x22, 0xc3, 0xfe, 0xd1, 0xcc, 0x0a, 0xd5, 0xf4, 0x29, 0x21, 0xda, 0xc0, 0x64, - 0x84, 0x94, 0xbd, 0x14, 0xcc, 0xba, 0x75, 0xea, 0xe6, 0xb6, 0x18, 0x9f, 0x8f, 0x89, 0x75, 0xcb, 0xbf, 0xd2, 0xc5, - 0xc5, 0x84, 0x61, 0xd0, 0x15, 0x6f, 0xde, 0xb3, 0xe1, 0x50, 0xaa, 0x30, 0x06, 0x9a, 0xc3, 0x59, 0x54, 0x11, 0xa3, - 0x96, 0x71, 0xe7, 0x0e, 0xb8, 0x8e, 0x1e, 0xf0, 0x1b, 0xaa, 0x6a, 0x2c, 0x19, 0x9d, 0xbe, 0xad, 0x63, 0xc8, 0xd7, - 0x91, 0x55, 0x1c, 0xbf, 0xce, 0x53, 0xd0, 0xfb, 0x6e, 0x2a, 0xd7, 0xae, 0x2a, 0x88, 0x7e, 0x96, 0x20, 0xb1, 0x26, - 0x1f, 0x77, 0x6c, 0x95, 0x1b, 0x7f, 0x3e, 0xd5, 0x54, 0xdb, 0x20, 0xb4, 0x2c, 0xc5, 0x82, 0x9d, 0x88, 0x05, 0x2b, - 0xc2, 0xa7, 0x2f, 0x62, 0xd0, 0x38, 0xab, 0x02, 0x67, 0x1f, 0xac, 0x5c, 0xc5, 0x87, 0x2f, 0x01, 0x3a, 0xa9, 0xea, - 0xff, 0x20, 0x71, 0x9d, 0x9d, 0x6e, 0xc9, 0x5f, 0xfb, 0x33, 0x25, 0x82, 0x49, 0x4b, 0x08, 0x81, 0x33, 0xe2, 0xb7, - 0xbe, 0x3c, 0x41, 0x06, 0xb0, 0x66, 0xb4, 0x6b, 0xbf, 0x9c, 0x0c, 0xd3, 0x90, 0x10, 0x35, 0x6b, 0xd8, 0xbb, 0x78, - 0x85, 0x0e, 0x44, 0x62, 0xd0, 0xe4, 0x4d, 0xf0, 0x2b, 0xd5, 0x52, 0xb9, 0xe6, 0x9f, 0x77, 0x73, 0xb9, 0x38, 0xb2, - 0x71, 0x64, 0x65, 0xa1, 0xc0, 0xd7, 0x01, 0xf4, 0x09, 0x9a, 0x13, 0x17, 0xfe, 0x38, 0x4b, 0x5a, 0x64, 0x67, 0xf2, - 0x40, 0xdd, 0x40, 0xc9, 0x62, 0xa5, 0x78, 0x5f, 0x02, 0x1f, 0x94, 0xc1, 0x36, 0x7c, 0x26, 0x71, 0x51, 0x65, 0x4d, - 0xab, 0x7e, 0x8c, 0x5b, 0x88, 0x98, 0x09, 0x65, 0x20, 0x24, 0x39, 0x2b, 0x71, 0x43, 0x65, 0xc5, 0xd1, 0x9d, 0xc5, - 0x02, 0x4c, 0x90, 0xcc, 0x46, 0x04, 0xfe, 0x25, 0x2c, 0x9e, 0x8b, 0x9f, 0xe9, 0xbd, 0x0d, 0x34, 0x31, 0x22, 0x92, - 0x5d, 0xf4, 0x6a, 0x45, 0x0f, 0x76, 0x69, 0x0c, 0x1f, 0x12, 0xc5, 0xb1, 0x7d, 0xde, 0x0f, 0x1a, 0x35, 0x00, 0x0a, - 0x16, 0xdb, 0x92, 0xba, 0x64, 0xde, 0x5e, 0x7b, 0xb9, 0xab, 0xc3, 0xdd, 0x55, 0x08, 0x0a, 0x7c, 0xb6, 0x99, 0x54, - 0x1e, 0x09, 0x64, 0x8d, 0x2d, 0xe6, 0x89, 0xe8, 0x15, 0xd3, 0x95, 0xd1, 0x45, 0x91, 0xad, 0xe3, 0x37, 0x04, 0x8a, - 0x9c, 0x5d, 0x22, 0x31, 0x65, 0x3f, 0x47, 0xb9, 0xe4, 0x42, 0x63, 0x75, 0x24, 0x2f, 0x76, 0x35, 0x88, 0x97, 0xa9, - 0x09, 0x30, 0x05, 0x79, 0x67, 0x46, 0x23, 0x44, 0x54, 0x92, 0x48, 0x11, 0x90, 0x98, 0x4b, 0x3e, 0xc5, 0x43, 0xc8, - 0x4f, 0x15, 0x12, 0x5a, 0x32, 0x94, 0xff, 0xe1, 0x3a, 0xc1, 0xb7, 0x0a, 0x78, 0x91, 0xd4, 0x2f, 0x3c, 0x70, 0x5b, - 0xda, 0xeb, 0x94, 0x0d, 0x12, 0xf0, 0xfd, 0xf4, 0xf0, 0x59, 0x67, 0x0f, 0xe2, 0x27, 0x45, 0x40, 0xf0, 0x41, 0xaf, - 0x6a, 0xb7, 0x4c, 0xa1, 0x92, 0x6a, 0x48, 0xb9, 0x1f, 0x5d, 0x72, 0x3a, 0xe1, 0xf0, 0x02, 0xfe, 0xf1, 0xfd, 0x7c, - 0x03, 0x73, 0xf0, 0x95, 0xae, 0x9a, 0x48, 0xde, 0x0d, 0x83, 0x3d, 0x85, 0xf4, 0x12, 0x0e, 0x6d, 0x5f, 0x23, 0xcc, - 0x76, 0xae, 0xb5, 0xd9, 0xfe, 0xc4, 0x50, 0xa7, 0xd3, 0x8f, 0xdf, 0xc4, 0x46, 0x8d, 0x14, 0xb7, 0x4e, 0xc4, 0x42, - 0x49, 0x3f, 0x7b, 0x72, 0x63, 0x69, 0x3a, 0x56, 0x6f, 0x43, 0xcd, 0xe3, 0x9b, 0x63, 0x3d, 0x79, 0xb3, 0x6c, 0xc9, - 0x07, 0x98, 0x70, 0xcc, 0xb7, 0xa2, 0xe7, 0x59, 0xd9, 0x0b, 0xa6, 0xd6, 0x1f, 0x34, 0x42, 0x62, 0xa8, 0x22, 0xa9, - 0xd7, 0xc0, 0xfb, 0x3a, 0xad, 0x3d, 0xab, 0x67, 0x44, 0xe9, 0xd4, 0x54, 0xac, 0x79, 0xa1, 0x5e, 0x28, 0x53, 0x95, - 0x5a, 0xe6, 0xce, 0x56, 0xd9, 0x53, 0x2c, 0x2f, 0x65, 0x32, 0xc2, 0x7e, 0x02, 0x51, 0x89, 0xef, 0xa1, 0x9e, 0xc4, - 0xba, 0x33, 0xa7, 0x4f, 0xcc, 0xa4, 0x81, 0xf1, 0x11, 0x31, 0x02, 0xab, 0x78, 0x1b, 0x18, 0x26, 0x6a, 0x8d, 0x0b, - 0xdd, 0x91, 0xd1, 0x3a, 0x7c, 0xc3, 0x3d, 0x61, 0x7d, 0x2f, 0xc8, 0x6e, 0xf8, 0xef, 0x99, 0x70, 0xdb, 0xcb, 0x3c, - 0x9a, 0x29, 0xbd, 0x79, 0x7c, 0x1c, 0xd1, 0xf4, 0x96, 0xca, 0x91, 0x2d, 0xe8, 0xae, 0xd7, 0xb0, 0xf1, 0x47, 0x41, - 0xf5, 0x58, 0xba, 0x19, 0x19, 0x31, 0x8e, 0x07, 0x83, 0x24, 0xe8, 0x43, 0xce, 0xaf, 0xa4, 0xe5, 0x79, 0x48, 0x5b, - 0x4c, 0xd8, 0x83, 0xe5, 0x14, 0x99, 0x18, 0x2e, 0xc1, 0xdc, 0xe6, 0x6c, 0xde, 0x7c, 0xe3, 0x8f, 0xc3, 0x9e, 0x4a, - 0x54, 0xc8, 0x83, 0x73, 0xdf, 0xca, 0x38, 0x4d, 0x1a, 0x28, 0x96, 0x31, 0x97, 0xf9, 0x61, 0x53, 0x47, 0xdb, 0xa1, - 0x50, 0x4d, 0xed, 0x9c, 0x7e, 0x9d, 0xec, 0xd3, 0x5e, 0x1d, 0xc9, 0x00, 0x59, 0x03, 0xa1, 0x0a, 0x02, 0x3e, 0xaf, - 0x29, 0x02, 0xc0, 0x72, 0x04, 0x8f, 0xf8, 0x83, 0x30, 0x7e, 0xfa, 0x46, 0xd2, 0x49, 0x58, 0xec, 0x7a, 0x01, 0x47, - 0xaf, 0x03, 0x68, 0xa3, 0x9e, 0xdb, 0x7e, 0x04, 0xa0, 0x5c, 0xac, 0xaf, 0x12, 0x6d, 0x23, 0x75, 0x08, 0xfb, 0xbe, - 0x35, 0xdb, 0xd1, 0x46, 0x9b, 0xe7, 0xd2, 0x68, 0x34, 0xb4, 0x59, 0x1d, 0xe8, 0x1e, 0xa9, 0x00, 0xd0, 0x65, 0x43, - 0xe1, 0xeb, 0xfb, 0x87, 0x28, 0xdd, 0x08, 0x76, 0xc1, 0x19, 0x7c, 0xb9, 0x74, 0xcc, 0xb7, 0x70, 0x34, 0x9f, 0x99, - 0x7a, 0x2b, 0x3f, 0x83, 0xfa, 0xba, 0xdb, 0x05, 0xe0, 0x57, 0x2e, 0x72, 0xc0, 0xf4, 0x3b, 0x9b, 0xe2, 0xa0, 0xb7, - 0x1c, 0xbd, 0xc6, 0xe9, 0xcc, 0x0c, 0x58, 0xc8, 0xb3, 0x6b, 0xe5, 0x43, 0x72, 0x03, 0x59, 0x5c, 0x40, 0x43, 0x76, - 0x0b, 0xb8, 0xf2, 0x4c, 0x97, 0x28, 0x49, 0x13, 0x84, 0x9e, 0xc0, 0x63, 0x35, 0x73, 0xb0, 0xec, 0x7d, 0x39, 0xd1, - 0xf3, 0x5c, 0x3e, 0x05, 0x8d, 0x14, 0xa8, 0x74, 0x5e, 0x52, 0x16, 0x90, 0x73, 0xa8, 0x83, 0x10, 0x33, 0x1d, 0xf4, - 0x92, 0xa9, 0xa6, 0x32, 0x87, 0x46, 0x48, 0x7e, 0x50, 0x90, 0x9c, 0xc0, 0xb9, 0xf9, 0x6a, 0x1d, 0xf5, 0xcb, 0x45, - 0x65, 0xbd, 0xa8, 0xc8, 0x04, 0xb7, 0x12, 0x1f, 0xb2, 0xfa, 0xc6, 0xc8, 0xe8, 0x68, 0x1d, 0x56, 0x9e, 0xc6, 0xf9, - 0x81, 0x07, 0x87, 0xe0, 0xc8, 0x1e, 0x62, 0x01, 0xa0, 0x89, 0xdb, 0x1c, 0xc2, 0x9f, 0xf9, 0xc8, 0x14, 0xb8, 0x35, - 0x0c, 0x09, 0x02, 0x02, 0x3e, 0xb1, 0x04, 0x8e, 0x99, 0x41, 0xc4, 0xb1, 0xd5, 0xe6, 0x0f, 0x98, 0x48, 0xab, 0xbc, - 0x31, 0x62, 0x13, 0x4e, 0x5c, 0xe3, 0x12, 0x29, 0x64, 0x6f, 0x4d, 0x76, 0xc2, 0x22, 0x0b, 0x1b, 0x72, 0xe4, 0x63, - 0xed, 0x65, 0x92, 0xf7, 0x65, 0x16, 0x2d, 0x29, 0x51, 0x77, 0x29, 0x52, 0xbc, 0x6e, 0x1f, 0xa2, 0xd5, 0x5a, 0xb5, - 0xd4, 0x71, 0xe8, 0x2e, 0x58, 0xcf, 0xfb, 0xbf, 0x7e, 0x2b, 0xa5, 0x7e, 0x72, 0x3e, 0x06, 0x55, 0xdc, 0x05, 0x85, - 0x35, 0x47, 0xc2, 0xd6, 0x4d, 0x93, 0x35, 0x79, 0x68, 0xbf, 0xec, 0x85, 0xae, 0xbb, 0x8d, 0xa8, 0x6a, 0x29, 0xf5, - 0x98, 0x17, 0x22, 0x1f, 0x86, 0x3e, 0x56, 0x8c, 0x50, 0x15, 0x1a, 0x5b, 0x3a, 0xe4, 0x71, 0x62, 0xe9, 0xf4, 0x41, - 0xe8, 0x5d, 0x0e, 0xf7, 0x21, 0x96, 0x87, 0x95, 0x24, 0xca, 0x8c, 0xa9, 0x44, 0x34, 0x8e, 0x80, 0xd1, 0xc6, 0xd8, - 0x6d, 0x04, 0x4e, 0x09, 0x36, 0x67, 0xd6, 0xbf, 0x62, 0x3c, 0xf1, 0x35, 0x74, 0x24, 0x19, 0x34, 0xe3, 0x87, 0x98, - 0xcf, 0x78, 0x23, 0x3a, 0x0c, 0x0d, 0x9a, 0xfe, 0x61, 0x9b, 0x8f, 0xbd, 0x96, 0xd0, 0x8f, 0x38, 0x84, 0x73, 0xde, - 0xf9, 0xa1, 0xfd, 0x62, 0x35, 0xe4, 0x6b, 0xd8, 0xbf, 0xf2, 0x94, 0xbf, 0xf2, 0x35, 0xdc, 0x87, 0x3c, 0xe5, 0x43, - 0xbe, 0x86, 0xfc, 0x90, 0x27, 0xc9, 0xe0, 0xf4, 0x7c, 0xa5, 0x3e, 0xf7, 0xd7, 0x42, 0x9d, 0x5c, 0x9e, 0x09, 0xad, - 0xe4, 0xa0, 0x17, 0xdf, 0x25, 0xda, 0x67, 0x02, 0x19, 0x3e, 0x2e, 0xa6, 0x44, 0x88, 0x43, 0x56, 0x96, 0x2e, 0x01, - 0x74, 0x1a, 0xe0, 0xdd, 0xeb, 0xeb, 0xbb, 0xfe, 0x15, 0xb6, 0x48, 0x1a, 0x03, 0xf1, 0xb8, 0x0f, 0xfa, 0xa9, 0x4e, - 0xdd, 0x78, 0x6e, 0x2b, 0x20, 0xe4, 0xca, 0x91, 0x80, 0x93, 0x8c, 0x76, 0x84, 0x10, 0xbd, 0x73, 0xbf, 0x67, 0x66, - 0xe6, 0xdb, 0xf7, 0xd0, 0x6b, 0xe1, 0x30, 0x87, 0x00, 0x39, 0xcb, 0x92, 0xc1, 0x5e, 0xec, 0x5f, 0xaf, 0x3e, 0x46, - 0xfa, 0xd4, 0x0c, 0x50, 0xd1, 0xa0, 0x6a, 0xb2, 0x3f, 0xe6, 0xc8, 0x48, 0x7a, 0xf9, 0x8f, 0x79, 0x97, 0x94, 0xa5, - 0xcb, 0x64, 0x08, 0xdc, 0x13, 0xb4, 0xdc, 0xcf, 0x82, 0x84, 0x4c, 0x33, 0xcb, 0x06, 0x51, 0x5b, 0x4e, 0x33, 0xe6, - 0x91, 0x1e, 0x4b, 0xb5, 0x54, 0x16, 0xee, 0x7c, 0xc7, 0xcf, 0xf8, 0x3f, 0x98, 0x84, 0xe6, 0x57, 0x83, 0xf2, 0x45, - 0xce, 0xac, 0xbb, 0x2b, 0x6c, 0x69, 0x0d, 0xa6, 0x25, 0x92, 0xa5, 0xc5, 0xb9, 0xd5, 0x98, 0x56, 0x90, 0xd6, 0x23, - 0x4f, 0x43, 0x34, 0xba, 0x49, 0x22, 0x36, 0x72, 0x6a, 0x3d, 0xe9, 0xda, 0x52, 0x93, 0xcc, 0x8a, 0xa5, 0x57, 0xb2, - 0xf7, 0xcd, 0x37, 0xd4, 0xa7, 0xe6, 0x72, 0x39, 0xc0, 0x26, 0xd3, 0x4d, 0xb1, 0x35, 0x05, 0xde, 0x25, 0x49, 0x11, - 0x1a, 0x02, 0xe5, 0xa8, 0x6d, 0x26, 0xbb, 0x4b, 0x55, 0x2d, 0xa7, 0x6a, 0x84, 0x48, 0x7d, 0x55, 0x61, 0xa9, 0x8e, - 0xe2, 0xe1, 0xc5, 0xbe, 0x88, 0xdd, 0x07, 0x71, 0x9d, 0xa5, 0x69, 0xb4, 0x59, 0xab, 0xad, 0x85, 0x3c, 0x06, 0x5f, - 0xee, 0x1a, 0x62, 0x00, 0xeb, 0x88, 0x46, 0x67, 0xf1, 0xe5, 0xd9, 0x35, 0x3c, 0x76, 0x68, 0xbf, 0xf6, 0xc1, 0x49, - 0x8b, 0xed, 0xa9, 0x14, 0x6e, 0x7d, 0x46, 0x06, 0x81, 0x44, 0xe2, 0x03, 0x00, 0x06, 0x00, 0x98, 0xea, 0x25, 0x45, - 0x35, 0x32, 0x68, 0x25, 0x0a, 0xf4, 0x48, 0xc1, 0x7d, 0x74, 0x19, 0x5a, 0x0e, 0x0e, 0x7f, 0x44, 0x4a, 0xab, 0x1d, - 0xb2, 0xc4, 0x44, 0xa6, 0x85, 0x92, 0x39, 0x4c, 0x68, 0xa5, 0xc5, 0x18, 0xb4, 0x44, 0xe1, 0x3d, 0x41, 0x3a, 0x6a, - 0x49, 0x80, 0xfa, 0xf2, 0xe8, 0x40, 0xc2, 0xe9, 0xbd, 0x79, 0xbe, 0x36, 0x7e, 0x2d, 0x6f, 0x9b, 0xe5, 0xba, 0x23, - 0x5b, 0xc1, 0x14, 0x92, 0x21, 0xd8, 0xe5, 0x6c, 0x95, 0x33, 0xfa, 0x08, 0x71, 0x12, 0xcb, 0x92, 0xd7, 0x56, 0xb9, - 0x59, 0x8c, 0x3e, 0x74, 0xcd, 0x7d, 0xd1, 0x0f, 0x75, 0xcf, 0x8f, 0x40, 0x70, 0x44, 0xb0, 0x08, 0x9e, 0xe3, 0xb4, - 0x6e, 0xf2, 0x52, 0x52, 0x13, 0xa4, 0x28, 0xf0, 0x21, 0xfd, 0xfc, 0x06, 0x43, 0x05, 0xdb, 0x6c, 0xc3, 0x21, 0x47, - 0x03, 0xcd, 0x77, 0x35, 0xfe, 0x7a, 0x75, 0x02, 0xd6, 0x92, 0xce, 0x53, 0xdb, 0xb6, 0x89, 0x3d, 0xe6, 0x8a, 0xb4, - 0xd3, 0x56, 0x08, 0xf5, 0xb9, 0xf8, 0xec, 0x67, 0xcf, 0x89, 0xaa, 0xfb, 0xf2, 0x43, 0xf0, 0xbd, 0x5d, 0x54, 0xed, - 0xb5, 0x05, 0x94, 0x1f, 0x67, 0x52, 0x6a, 0xb6, 0x0e, 0x8a, 0xd2, 0xe3, 0xd1, 0x88, 0x16, 0xb7, 0xb7, 0x94, 0xbd, - 0x1f, 0x24, 0xc1, 0x4d, 0xa6, 0x56, 0xfe, 0xdb, 0xbb, 0xdb, 0x93, 0x7c, 0x8f, 0x82, 0xcc, 0xbd, 0x16, 0xce, 0x33, - 0x73, 0x09, 0x41, 0x01, 0x22, 0x23, 0x28, 0xb3, 0x31, 0x6f, 0x03, 0xf3, 0x0e, 0xcc, 0x2f, 0xe8, 0x51, 0xa9, 0x38, - 0x90, 0x9c, 0xd5, 0xc5, 0xa8, 0x98, 0x94, 0x03, 0x2f, 0x71, 0xfd, 0x5d, 0x1a, 0x12, 0x10, 0xb8, 0x46, 0x5d, 0x06, - 0x8b, 0xc4, 0x3e, 0x51, 0x7c, 0x04, 0x67, 0xfb, 0xc6, 0x0e, 0x32, 0xbb, 0xe1, 0x7d, 0x5d, 0x5c, 0xc0, 0x1d, 0x84, - 0xcf, 0xd2, 0x53, 0x10, 0xa1, 0xa9, 0xfb, 0xdf, 0xb8, 0xa8, 0x14, 0xbe, 0xd9, 0x20, 0x63, 0xcf, 0x2f, 0xeb, 0x00, - 0xe4, 0xd2, 0x34, 0x0a, 0x83, 0x19, 0x7f, 0x72, 0xa4, 0x5f, 0x85, 0x1e, 0x52, 0x5d, 0x8b, 0xba, 0x4b, 0x72, 0x3f, - 0x74, 0xec, 0x1c, 0x8a, 0x54, 0xb1, 0xad, 0xc3, 0xf9, 0xa2, 0x91, 0xa9, 0x49, 0xff, 0xc2, 0xe3, 0x9d, 0x4d, 0xb7, - 0xdf, 0x60, 0x2e, 0x85, 0x40, 0x36, 0x32, 0xb1, 0xe9, 0xa4, 0x1d, 0x95, 0xea, 0xca, 0x9d, 0x17, 0x15, 0xea, 0xad, - 0x65, 0x2f, 0xe9, 0xe8, 0xc3, 0x8a, 0x5c, 0x4a, 0xd8, 0x12, 0x49, 0x53, 0xb8, 0x54, 0xc6, 0x58, 0x3a, 0x33, 0x77, - 0xe7, 0xbb, 0xb8, 0x92, 0xc6, 0x01, 0x3e, 0x86, 0xa1, 0x6c, 0xc4, 0xdf, 0x0f, 0x90, 0x86, 0x6a, 0x6a, 0xdd, 0x0a, - 0x64, 0x82, 0x65, 0x85, 0x12, 0x3a, 0x54, 0x50, 0x7c, 0xe0, 0xfb, 0xce, 0xe0, 0xc6, 0x49, 0xc9, 0xc6, 0xdf, 0x37, - 0xeb, 0x1e, 0x93, 0x87, 0x33, 0x93, 0xbb, 0x00, 0xaa, 0xd8, 0x6b, 0x05, 0xce, 0x0c, 0xa1, 0x70, 0x72, 0x1c, 0xd7, - 0x32, 0x27, 0xc8, 0x3a, 0x7a, 0xdb, 0x03, 0x6f, 0x91, 0x76, 0xd7, 0x45, 0x9a, 0x52, 0xed, 0x28, 0xd8, 0xc6, 0x09, - 0x38, 0xeb, 0xfb, 0x0f, 0x4a, 0xe3, 0x4a, 0xea, 0xf2, 0x79, 0x5a, 0x64, 0xdb, 0x33, 0xe2, 0x60, 0x57, 0xb5, 0x29, - 0xca, 0xa2, 0x08, 0x23, 0x0c, 0x46, 0x08, 0x5b, 0x96, 0x18, 0xc7, 0x44, 0x6c, 0x12, 0x0a, 0xa3, 0x8f, 0xca, 0x6a, - 0xe5, 0x3a, 0x96, 0x7e, 0xd5, 0x59, 0x21, 0x75, 0x44, 0x7b, 0x1f, 0xbc, 0xc4, 0x24, 0x65, 0x79, 0x4e, 0xb6, 0xf8, - 0xf4, 0x42, 0xad, 0x4f, 0xa9, 0xf6, 0xc0, 0xde, 0xdc, 0x1c, 0x24, 0x4d, 0xbe, 0x27, 0x21, 0x1e, 0x16, 0x9d, 0xd7, - 0x06, 0xe7, 0xe5, 0x69, 0xdc, 0xfd, 0x59, 0x37, 0x2d, 0x5b, 0x17, 0xe2, 0x14, 0x55, 0x47, 0xbd, 0xc9, 0xe9, 0xb5, - 0xcf, 0x3f, 0x11, 0xea, 0x84, 0x41, 0xc3, 0xcc, 0x69, 0x89, 0x89, 0x48, 0xd7, 0x65, 0x1e, 0x98, 0x08, 0xee, 0x3d, - 0x83, 0x61, 0x87, 0xe4, 0x71, 0xb2, 0x30, 0x9d, 0xb0, 0x0b, 0x51, 0xd9, 0x26, 0x67, 0xbe, 0xe7, 0xe6, 0x5f, 0x0f, - 0x64, 0x18, 0xf6, 0x69, 0x41, 0xcb, 0x79, 0xfd, 0xa6, 0x77, 0x7f, 0xb9, 0xe8, 0xa9, 0x3f, 0x06, 0xd7, 0x15, 0x9a, - 0xb0, 0x78, 0x4d, 0x87, 0xfd, 0x2f, 0xa2, 0x9f, 0xb8, 0xcf, 0xf2, 0x9e, 0x46, 0x33, 0x86, 0xc6, 0xac, 0x89, 0xfa, - 0x9d, 0x99, 0x1d, 0x85, 0x20, 0x39, 0xb1, 0x93, 0xb3, 0xfa, 0x11, 0x90, 0x88, 0x31, 0xb5, 0x9b, 0x83, 0x61, 0x76, - 0x8c, 0xb3, 0xb0, 0x68, 0xd1, 0x97, 0x87, 0x9c, 0x56, 0x00, 0x86, 0x97, 0xca, 0x2f, 0xbb, 0x76, 0x68, 0xca, 0xe3, - 0x84, 0x5a, 0x2b, 0xb8, 0x16, 0x32, 0x47, 0x55, 0x6d, 0xa2, 0xb5, 0x14, 0x81, 0x59, 0x1c, 0xeb, 0xf6, 0x53, 0x5d, - 0xff, 0x01, 0x46, 0x5f, 0xf3, 0xb0, 0x3d, 0x7f, 0x92, 0xd8, 0x52, 0xeb, 0x73, 0xbe, 0x25, 0x7a, 0x19, 0x7b, 0xaf, - 0x13, 0xb5, 0x09, 0x96, 0x6c, 0xc9, 0xca, 0x35, 0x45, 0xb8, 0x89, 0xa1, 0xea, 0x1a, 0x42, 0xb9, 0x41, 0xe2, 0x1b, - 0x32, 0x81, 0xd5, 0xf9, 0xa5, 0xce, 0xd2, 0xb3, 0x84, 0x76, 0x79, 0xa0, 0x9d, 0x9d, 0x30, 0xd2, 0x45, 0xe1, 0xff, - 0x4e, 0x26, 0x84, 0xe0, 0xca, 0x86, 0x67, 0x4b, 0xa8, 0x8b, 0xe2, 0xe2, 0xaa, 0x5d, 0x40, 0xf1, 0xeb, 0xf5, 0xbb, - 0xf5, 0xbf, 0xa5, 0xef, 0x70, 0xd9, 0x20, 0xf6, 0xd7, 0x88, 0x7a, 0x9a, 0xcc, 0xb0, 0xda, 0xe8, 0x16, 0xc3, 0xfe, - 0xd1, 0xf4, 0x8d, 0x24, 0x76, 0x0a, 0x17, 0xdf, 0x77, 0x4a, 0x1c, 0xef, 0xa6, 0x29, 0x6b, 0xa2, 0xf1, 0xbf, 0x51, - 0xd3, 0xe0, 0x14, 0xbe, 0xbe, 0xc1, 0xa9, 0xe0, 0x61, 0xd7, 0xd4, 0x50, 0xec, 0xee, 0x17, 0x2b, 0x9a, 0xd6, 0x5a, - 0x57, 0x18, 0xa0, 0x0a, 0x1f, 0x41, 0x4e, 0x45, 0xbe, 0x97, 0xfb, 0x8a, 0x2f, 0xf2, 0x47, 0xdf, 0xbc, 0x74, 0x84, - 0x35, 0x97, 0x42, 0xcd, 0xad, 0x4c, 0xf2, 0xd3, 0xf2, 0x22, 0xe9, 0x96, 0x18, 0x94, 0x73, 0xcb, 0xfc, 0x7a, 0x07, - 0x8a, 0x4a, 0xcc, 0xb6, 0x2b, 0x37, 0x08, 0xd3, 0x3a, 0x17, 0xe1, 0xbd, 0xb6, 0x12, 0x29, 0x6a, 0x8d, 0x59, 0xce, - 0xb4, 0xa4, 0x1e, 0x9b, 0xcf, 0x44, 0x1d, 0xb8, 0x01, 0x31, 0xfa, 0x9e, 0x29, 0x79, 0x0d, 0x08, 0xbb, 0xe7, 0xe1, - 0xfb, 0x64, 0x79, 0x19, 0xe6, 0x5a, 0x59, 0x52, 0x4d, 0xd6, 0x3d, 0x55, 0x48, 0x1a, 0x13, 0x7a, 0x6b, 0x97, 0x79, - 0xb9, 0x55, 0x67, 0x78, 0xb2, 0x4e, 0xef, 0x59, 0xea, 0x07, 0x78, 0x5d, 0x25, 0x0f, 0x15, 0x1e, 0x2c, 0xdc, 0xb8, - 0x00, 0x5a, 0x56, 0xde, 0xea, 0x1c, 0x47, 0xb7, 0x79, 0x4a, 0xd6, 0x66, 0x83, 0xd7, 0x44, 0x2c, 0xa0, 0x64, 0x7b, - 0xb0, 0xdd, 0xc6, 0xca, 0x21, 0x1a, 0x6f, 0x1f, 0x59, 0x48, 0xd1, 0x75, 0x83, 0x36, 0x2f, 0x0f, 0x98, 0xc3, 0x51, - 0x75, 0x75, 0xa3, 0x9c, 0xbd, 0xc4, 0xfc, 0x60, 0xa4, 0x40, 0x41, 0x23, 0x7b, 0xc1, 0xa2, 0x4a, 0xbd, 0x8f, 0xad, - 0x57, 0x7d, 0xbb, 0x16, 0x7e, 0x24, 0x82, 0x91, 0xda, 0x28, 0xe1, 0x79, 0x8a, 0xe4, 0xd9, 0xb1, 0x9b, 0x27, 0x27, - 0x64, 0x64, 0x5e, 0xba, 0x02, 0x92, 0xb0, 0xe0, 0xa1, 0x09, 0xc2, 0xe2, 0x54, 0x32, 0x82, 0x88, 0x7d, 0xce, 0xdc, - 0x40, 0xa8, 0x1a, 0xae, 0x22, 0xc0, 0xcd, 0x93, 0x5e, 0xd2, 0x3c, 0x96, 0xdb, 0x62, 0xcc, 0xea, 0x34, 0x13, 0x6a, - 0x79, 0x26, 0xa2, 0x44, 0x7e, 0x5e, 0x0f, 0xf9, 0x08, 0xe8, 0xd0, 0x6d, 0xc2, 0xb9, 0x58, 0x63, 0x27, 0x56, 0xa9, - 0xb5, 0xa0, 0xf0, 0xdb, 0xb1, 0xc9, 0xda, 0x6f, 0x32, 0xa3, 0x67, 0x30, 0xff, 0x2c, 0x46, 0xb2, 0x9b, 0x3e, 0x8a, - 0xe3, 0x3e, 0x40, 0x01, 0x99, 0x6f, 0xe8, 0x20, 0xf9, 0x6d, 0xa9, 0x1e, 0xd7, 0xbb, 0x51, 0x2e, 0xc4, 0x93, 0x2c, - 0xf2, 0x40, 0xaa, 0x9d, 0xaf, 0x72, 0x5c, 0x7a, 0xe4, 0xd6, 0x0f, 0x54, 0x03, 0x42, 0x20, 0xcb, 0x0d, 0xa4, 0xf0, - 0x06, 0x07, 0xce, 0x9b, 0x38, 0x22, 0xa1, 0xac, 0x67, 0x22, 0x98, 0x2c, 0x4a, 0xf1, 0x5e, 0xfc, 0xe2, 0xd7, 0xee, - 0x2f, 0x16, 0x67, 0x7d, 0xb1, 0x87, 0xcd, 0xf2, 0xc5, 0x7b, 0x0d, 0xc4, 0x56, 0x15, 0x1e, 0x2c, 0x59, 0x4c, 0x0f, - 0x5e, 0xef, 0x11, 0x36, 0xf6, 0x0c, 0xef, 0xc1, 0x27, 0xfd, 0x5a, 0x42, 0xa5, 0xcd, 0xa5, 0xe8, 0x80, 0xfd, 0x30, - 0xdc, 0x64, 0xdf, 0x08, 0x13, 0xd2, 0xc5, 0xfa, 0x44, 0xff, 0x19, 0x24, 0x79, 0xb7, 0xeb, 0xef, 0xeb, 0x45, 0xe4, - 0x06, 0x2b, 0x05, 0xd9, 0xd8, 0x6d, 0x76, 0x90, 0x35, 0x64, 0x25, 0x53, 0x63, 0x82, 0x50, 0x06, 0xe9, 0x0b, 0x51, - 0x97, 0xf7, 0x57, 0x6d, 0x78, 0x98, 0xae, 0xb6, 0x96, 0x15, 0xc5, 0xb7, 0xf2, 0x5f, 0x85, 0xee, 0x78, 0x8e, 0x8e, - 0xa4, 0xbe, 0x73, 0x88, 0x3f, 0x7b, 0x1d, 0x34, 0x11, 0xaa, 0x02, 0xf2, 0xd7, 0xda, 0x0b, 0xe7, 0xd6, 0x53, 0x4e, - 0xee, 0xce, 0xa7, 0x5b, 0xb9, 0x08, 0xe9, 0x07, 0x86, 0x5e, 0xb6, 0xd8, 0xe8, 0xc5, 0x63, 0x3a, 0xd6, 0xa1, 0x25, - 0x12, 0xe3, 0x73, 0x60, 0xa6, 0x4e, 0x5d, 0x63, 0x62, 0x3a, 0xeb, 0x8f, 0x91, 0x15, 0x58, 0x80, 0x31, 0xd6, 0xc2, - 0x4f, 0x57, 0xe1, 0xdb, 0xe9, 0x37, 0x84, 0x20, 0x70, 0x9b, 0x34, 0xf1, 0xd3, 0xd5, 0x53, 0x6c, 0x7e, 0x53, 0x31, - 0x57, 0xc4, 0xb6, 0x1c, 0x68, 0xd1, 0xaa, 0x86, 0x3a, 0xb3, 0x13, 0x14, 0x84, 0x29, 0x12, 0x85, 0x31, 0x57, 0x47, - 0x89, 0x41, 0xd4, 0x72, 0xea, 0x2e, 0x64, 0x9b, 0x0a, 0xb5, 0x25, 0xb9, 0x28, 0x28, 0xe1, 0x88, 0x4d, 0xe2, 0x4c, - 0x35, 0x07, 0xa8, 0x5f, 0xdb, 0xb4, 0x09, 0x67, 0xbd, 0xe0, 0xde, 0xa9, 0xa0, 0x50, 0x53, 0xc3, 0xe0, 0x15, 0x1b, - 0x83, 0x57, 0xe5, 0x0c, 0xed, 0xf0, 0x22, 0xfd, 0xbe, 0xf9, 0x44, 0x5b, 0x4b, 0x73, 0xb3, 0xec, 0xdf, 0xcb, 0xc3, - 0x1f, 0x0d, 0x6f, 0xbf, 0x73, 0x26, 0xc4, 0x45, 0xf3, 0xa1, 0xa7, 0x5e, 0xe2, 0x71, 0x83, 0x62, 0x0f, 0xcd, 0x8c, - 0x19, 0x76, 0x9f, 0x69, 0xe9, 0x30, 0xc6, 0xed, 0xc4, 0x2d, 0xed, 0x41, 0x37, 0x2a, 0x8c, 0x3d, 0x3d, 0xdf, 0x40, - 0xeb, 0xad, 0xf0, 0xb6, 0xb5, 0x3b, 0x6d, 0x7c, 0x3e, 0x1d, 0x03, 0xe8, 0x1b, 0x6d, 0xba, 0x6c, 0x1e, 0xba, 0x4c, - 0xc6, 0x22, 0xd1, 0x76, 0xc8, 0x17, 0xcb, 0xc3, 0xef, 0xbd, 0xad, 0x4d, 0x7b, 0x0b, 0xd7, 0x91, 0x21, 0x83, 0xb4, - 0x54, 0x89, 0x54, 0xd1, 0xa3, 0x0b, 0xe4, 0xd5, 0x4c, 0xb4, 0x72, 0x8d, 0x3a, 0xe3, 0xf5, 0xed, 0x52, 0x65, 0xf9, - 0x63, 0x0b, 0x51, 0xa5, 0x97, 0xff, 0x02, 0x31, 0xcf, 0x0e, 0x93, 0x81, 0xe1, 0x14, 0x42, 0x63, 0xf7, 0x7f, 0x80, - 0xd3, 0x2e, 0x03, 0x6a, 0x42, 0xcd, 0xcb, 0x45, 0x17, 0x49, 0x71, 0xf9, 0xe9, 0x7e, 0x37, 0x04, 0xf1, 0x7c, 0x75, - 0x16, 0x5c, 0x7b, 0x49, 0x92, 0x4a, 0xfc, 0xa5, 0x34, 0x4d, 0x38, 0xc9, 0xb6, 0x22, 0x7e, 0x55, 0x9f, 0x00, 0x48, - 0x21, 0x5e, 0x69, 0x16, 0x69, 0xe2, 0x2d, 0xe9, 0xaa, 0x90, 0x51, 0xf1, 0x21, 0x85, 0x6f, 0x65, 0xb4, 0x3d, 0x9a, - 0x61, 0x74, 0x8d, 0x25, 0x76, 0x10, 0xba, 0x61, 0x9a, 0x30, 0x02, 0x1d, 0xd8, 0xc9, 0x00, 0x89, 0xbc, 0x53, 0x0e, - 0x31, 0x57, 0x4d, 0x4c, 0xc1, 0x0f, 0x49, 0xbd, 0x97, 0x20, 0xb7, 0xa0, 0x79, 0x56, 0xd6, 0x84, 0xd8, 0xe4, 0xc8, - 0xfd, 0x3e, 0x39, 0xe0, 0x7a, 0x61, 0x73, 0xb0, 0x51, 0xe9, 0x38, 0xb9, 0xcf, 0xf0, 0x6f, 0x3b, 0x49, 0x01, 0xb5, - 0x5b, 0xc5, 0x5c, 0x8e, 0xd3, 0x5c, 0xd0, 0x62, 0xfa, 0x6f, 0x06, 0x92, 0x83, 0xfe, 0x91, 0xa0, 0x81, 0xa5, 0xc3, - 0x4f, 0x74, 0x6b, 0xf0, 0x2f, 0x6c, 0x35, 0xcd, 0x4a, 0x64, 0xb5, 0xa7, 0x58, 0x7b, 0xe6, 0x65, 0xf2, 0xed, 0xa4, - 0xfe, 0x35, 0xaf, 0x49, 0xac, 0x7e, 0xe2, 0xa6, 0x16, 0x8f, 0x5c, 0x9f, 0x72, 0x70, 0x7a, 0xaa, 0xc7, 0x5e, 0xd8, - 0x75, 0x9a, 0x95, 0x0c, 0x51, 0x9c, 0x4b, 0xb6, 0xeb, 0xe2, 0x6f, 0x2f, 0x12, 0x41, 0x79, 0x9b, 0x80, 0x11, 0x12, - 0x10, 0xb9, 0x60, 0xf6, 0x34, 0x64, 0x72, 0xd4, 0x57, 0x9b, 0x87, 0xc3, 0x0a, 0x81, 0xe6, 0xa1, 0x70, 0x3f, 0xcc, - 0x54, 0xca, 0x2e, 0x0e, 0x01, 0x55, 0xba, 0x7f, 0x8d, 0x69, 0x35, 0xff, 0x9b, 0x24, 0xf1, 0x27, 0xab, 0x3f, 0x6c, - 0x55, 0x0d, 0xd1, 0x10, 0x17, 0x46, 0x29, 0x1a, 0x4f, 0x19, 0x0b, 0x3d, 0xa3, 0x67, 0x4e, 0x22, 0x4b, 0x41, 0xff, - 0xec, 0x3c, 0x9c, 0xd7, 0xfa, 0xb4, 0x45, 0x35, 0x70, 0x94, 0x44, 0xb1, 0x65, 0x06, 0x46, 0xbc, 0x00, 0x24, 0x66, - 0x7a, 0x90, 0x15, 0x2d, 0xf8, 0xda, 0x76, 0x65, 0xc5, 0x9c, 0x65, 0x60, 0xf5, 0x43, 0xd4, 0x1f, 0x6e, 0xda, 0x1b, - 0x7a, 0x4b, 0x2b, 0xe3, 0x2d, 0x3d, 0xde, 0xd3, 0x66, 0xd6, 0x2f, 0x6d, 0xa0, 0xe9, 0x52, 0x95, 0x3c, 0x7d, 0x7f, - 0xdf, 0xf7, 0xc5, 0xfd, 0x79, 0x3f, 0x15, 0x57, 0x6c, 0xef, 0xe7, 0x81, 0x4a, 0x4e, 0xfc, 0x73, 0xd4, 0xaf, 0x27, - 0x33, 0xaa, 0x09, 0xd7, 0x6d, 0xdd, 0xb7, 0xc2, 0x23, 0x5f, 0x4f, 0x2c, 0x1c, 0x49, 0x5d, 0xa1, 0xe4, 0x3d, 0x69, - 0xd9, 0xa0, 0x7b, 0x8a, 0x20, 0xdf, 0x57, 0x40, 0x29, 0x05, 0x34, 0x1f, 0x5c, 0x22, 0x44, 0x69, 0x6a, 0x5d, 0xba, - 0xf1, 0x86, 0xca, 0xcd, 0x07, 0x66, 0x39, 0x1b, 0x82, 0x8f, 0x13, 0xf0, 0x8b, 0x79, 0x50, 0x3f, 0xae, 0xc2, 0x34, - 0x33, 0x54, 0xf6, 0x80, 0x6c, 0x82, 0x92, 0x13, 0xa9, 0x47, 0x5f, 0xd4, 0x91, 0x40, 0xa3, 0xa8, 0x57, 0x9e, 0x75, - 0xbf, 0xd0, 0x45, 0xae, 0x34, 0xff, 0xbf, 0x84, 0x92, 0x0d, 0xf5, 0xe7, 0xe3, 0x4b, 0x69, 0xb0, 0x40, 0xdf, 0x2f, - 0xfc, 0xf6, 0xf2, 0xa2, 0xd1, 0xe3, 0xd2, 0x77, 0x37, 0x64, 0xb9, 0xc1, 0x71, 0x6f, 0x9e, 0xcd, 0x4b, 0x29, 0x05, - 0xe1, 0xb9, 0xe9, 0xaf, 0xcc, 0xd6, 0x89, 0x82, 0xb0, 0xd9, 0x5c, 0x70, 0x10, 0xa0, 0x6a, 0xd9, 0x03, 0x4c, 0xb5, - 0x42, 0x76, 0xea, 0x18, 0x84, 0xf2, 0xdb, 0xc4, 0x7b, 0xf9, 0x7e, 0x7e, 0xbd, 0xe3, 0x91, 0xb9, 0x72, 0xc8, 0x13, - 0x55, 0x76, 0x51, 0x74, 0xb7, 0x08, 0x8f, 0x05, 0xc2, 0x9b, 0x3f, 0x4c, 0x63, 0xbe, 0xae, 0x7b, 0x0a, 0x80, 0x19, - 0x00, 0x9f, 0x10, 0x22, 0x28, 0xd8, 0xcc, 0x74, 0x73, 0x3f, 0xdc, 0xab, 0xa4, 0x6a, 0x78, 0x0a, 0x6c, 0x22, 0x28, - 0xb8, 0xce, 0xd4, 0x63, 0x71, 0x06, 0x9b, 0x7e, 0x44, 0x84, 0x50, 0x9a, 0xe5, 0xb8, 0x19, 0x37, 0xc0, 0x3c, 0x17, - 0x6d, 0xcc, 0xf0, 0x34, 0xd6, 0x84, 0x78, 0x9f, 0xd8, 0x64, 0x4a, 0xc7, 0x05, 0xf9, 0xb2, 0x8b, 0x57, 0xee, 0xfc, - 0x18, 0x65, 0xee, 0x89, 0xc1, 0xb7, 0xc8, 0x1d, 0x73, 0x3f, 0xe2, 0x13, 0x56, 0xd9, 0xb4, 0xbe, 0x04, 0x36, 0x6e, - 0x69, 0x5d, 0x98, 0x68, 0xfe, 0x5b, 0x68, 0x49, 0xe4, 0x0b, 0x76, 0x6d, 0x33, 0x1e, 0xa1, 0xbe, 0xf2, 0xc9, 0xe0, - 0x81, 0x37, 0xff, 0xda, 0xa3, 0xfb, 0x8b, 0x09, 0x84, 0x62, 0x78, 0x2f, 0xdb, 0xc9, 0x5a, 0xde, 0xcb, 0x52, 0x81, - 0xeb, 0x55, 0xbc, 0x26, 0x8f, 0xe9, 0x38, 0x8c, 0xc4, 0xe8, 0x68, 0x50, 0x00, 0xf7, 0x4d, 0xd1, 0xdb, 0x88, 0x71, - 0xa2, 0xa0, 0x0a, 0x55, 0xce, 0xf4, 0x32, 0x8e, 0xb2, 0xbc, 0x4a, 0x1a, 0xfc, 0x6d, 0x3f, 0x6f, 0x52, 0x04, 0x04, - 0x1f, 0xe8, 0x80, 0x9b, 0xfd, 0xd9, 0x98, 0xd3, 0x9a, 0xb6, 0xa4, 0x62, 0x8d, 0x07, 0x44, 0x8e, 0xe8, 0xff, 0x38, - 0x64, 0xb9, 0x66, 0xe8, 0x3e, 0x1a, 0x74, 0x43, 0xc8, 0x1b, 0x11, 0x19, 0x19, 0x0c, 0x90, 0xcd, 0x57, 0x9b, 0xb9, - 0x86, 0x81, 0x30, 0x09, 0xeb, 0x16, 0x0f, 0xfd, 0x12, 0x70, 0x94, 0x8f, 0xb9, 0xdb, 0xbe, 0x60, 0x98, 0xc8, 0x2b, - 0xca, 0x2f, 0x29, 0x38, 0x17, 0x9a, 0x99, 0xb7, 0x1c, 0x80, 0x39, 0xcd, 0x14, 0x14, 0xa6, 0x38, 0x18, 0x95, 0x6d, - 0xad, 0x1f, 0xd2, 0xbc, 0x16, 0xa8, 0x52, 0x30, 0x5c, 0x91, 0xb9, 0xa8, 0x92, 0xbb, 0x9a, 0x77, 0x13, 0x11, 0xa1, - 0xe3, 0xd8, 0x31, 0x67, 0x58, 0x67, 0x0a, 0x32, 0x32, 0x4d, 0x91, 0x6f, 0x1f, 0x21, 0x09, 0x97, 0x88, 0x5a, 0x44, - 0xf7, 0xcb, 0xb9, 0x36, 0xbb, 0x35, 0xa6, 0xa9, 0xae, 0x1d, 0xd2, 0x84, 0x4d, 0x0c, 0x6a, 0xfa, 0x12, 0xc5, 0x87, - 0xd2, 0xf8, 0xed, 0x4e, 0xfb, 0x18, 0x46, 0xb2, 0xb1, 0xf4, 0xdc, 0x38, 0x5c, 0x8d, 0x23, 0xea, 0x58, 0x3d, 0x95, - 0xa2, 0xc6, 0x56, 0x65, 0x0a, 0x6d, 0x91, 0x45, 0x08, 0x80, 0xf3, 0x95, 0xb9, 0x9a, 0xdf, 0x0a, 0x1f, 0x34, 0x67, - 0x9a, 0x55, 0x2a, 0x15, 0x9f, 0x68, 0xd1, 0x54, 0x46, 0x62, 0x71, 0x9b, 0xcb, 0x7d, 0x62, 0xfc, 0xae, 0x95, 0x1b, - 0xc0, 0x6f, 0xd1, 0x2d, 0x77, 0xd5, 0x0c, 0xdc, 0x64, 0x6f, 0xf4, 0x9c, 0x55, 0x06, 0x72, 0x17, 0x32, 0x6f, 0xd0, - 0x70, 0x2d, 0xd9, 0x6e, 0xcd, 0xfb, 0xba, 0x2c, 0xf4, 0x65, 0xec, 0xf2, 0xdb, 0x5c, 0x83, 0x56, 0x7f, 0x1a, 0x76, - 0x57, 0x1a, 0x8e, 0xac, 0x04, 0x3d, 0x0d, 0xe6, 0x80, 0x94, 0xd7, 0xba, 0x7f, 0xbb, 0xaa, 0x00, 0xf8, 0x9b, 0xe9, - 0x22, 0xd1, 0x7c, 0x09, 0xdf, 0x40, 0x63, 0xa0, 0x74, 0x1e, 0xd8, 0xca, 0xd7, 0xb3, 0x76, 0x18, 0xf4, 0xbe, 0x9a, - 0x49, 0x0b, 0xaf, 0xcb, 0x9b, 0x10, 0xf6, 0x0a, 0x97, 0x24, 0xd6, 0x78, 0x58, 0xcd, 0x60, 0x61, 0x1e, 0xee, 0xb0, - 0x52, 0x9b, 0xca, 0x9f, 0x10, 0xd5, 0x25, 0xda, 0xf3, 0xba, 0x8b, 0x25, 0x36, 0x2e, 0xec, 0xfb, 0x25, 0xb9, 0xa0, - 0x3a, 0x50, 0xf4, 0x41, 0x32, 0x31, 0xc7, 0x96, 0x1d, 0x08, 0x5e, 0x1e, 0x56, 0x62, 0x40, 0xc1, 0xbe, 0xe5, 0xa8, - 0x4f, 0x54, 0x1c, 0x40, 0x52, 0x8a, 0x91, 0xf4, 0x8a, 0x57, 0xc4, 0xde, 0xb4, 0x0a, 0x28, 0xfb, 0xdd, 0xba, 0xef, - 0xd9, 0x2a, 0x7f, 0x32, 0xd7, 0xfa, 0xa4, 0xdf, 0x23, 0xe9, 0xbd, 0xa2, 0x7e, 0x1c, 0x80, 0x33, 0xdb, 0xac, 0x7d, - 0x02, 0x67, 0x1e, 0x4b, 0xf7, 0xda, 0x70, 0xd1, 0xee, 0xab, 0x02, 0x98, 0x10, 0x4c, 0x87, 0xaa, 0x35, 0xe3, 0x73, - 0xf9, 0xc4, 0x96, 0xed, 0x9e, 0xf4, 0x9d, 0x14, 0x43, 0x6c, 0x90, 0x31, 0x3c, 0x4b, 0xe4, 0x9c, 0x9a, 0xc7, 0xd3, - 0xa7, 0xa7, 0x7a, 0x26, 0xa5, 0xe7, 0xd9, 0x47, 0x47, 0x1c, 0x28, 0x51, 0x23, 0x4b, 0x86, 0xb6, 0x6f, 0xf5, 0xd1, - 0x0b, 0x5e, 0x0b, 0x80, 0x14, 0x4b, 0x20, 0x4d, 0x33, 0x2a, 0xce, 0xf1, 0xc9, 0x07, 0x09, 0x92, 0xc1, 0x5d, 0x49, - 0xe8, 0x93, 0x16, 0x6a, 0x0d, 0x7e, 0x20, 0x2f, 0xca, 0x8d, 0x03, 0x40, 0xed, 0x1e, 0x32, 0x45, 0xb1, 0x9c, 0x37, - 0xb2, 0x13, 0xee, 0x21, 0x1a, 0x87, 0x7a, 0x54, 0x9a, 0xa7, 0x9c, 0x5e, 0x40, 0xb4, 0x5c, 0xe6, 0xc9, 0x8c, 0x3d, - 0x7b, 0xbe, 0x41, 0xc3, 0x29, 0xb4, 0xf1, 0x25, 0x4e, 0x5b, 0xa7, 0xfe, 0x54, 0x43, 0x71, 0x79, 0x36, 0x5f, 0x26, - 0xea, 0x88, 0x3d, 0xa2, 0x0b, 0xcd, 0xe8, 0x82, 0xde, 0x98, 0xcb, 0x9d, 0xfb, 0x59, 0x01, 0x02, 0x1d, 0x95, 0x17, - 0x43, 0x27, 0x31, 0xc6, 0xab, 0xf4, 0x84, 0x3b, 0x5e, 0x28, 0xa5, 0xfa, 0x00, 0x3e, 0x7f, 0x08, 0xc2, 0x5f, 0x89, - 0xf7, 0x8e, 0x5a, 0x7d, 0xe3, 0x16, 0x27, 0x26, 0x3c, 0x28, 0xc0, 0x4c, 0x87, 0x48, 0x8d, 0x24, 0x74, 0x04, 0xda, - 0x47, 0x81, 0x90, 0xac, 0xa4, 0x5b, 0x53, 0x5e, 0x87, 0x75, 0xea, 0x30, 0x07, 0x3f, 0x2e, 0x18, 0xaf, 0xe5, 0x4d, - 0x37, 0xa2, 0xb7, 0xbe, 0x6e, 0x05, 0xd9, 0x79, 0xdc, 0x83, 0xc8, 0xf8, 0x62, 0x67, 0x8c, 0x29, 0xda, 0x29, 0xa6, - 0x25, 0x15, 0xb3, 0x8f, 0x14, 0xa1, 0xbf, 0x5c, 0x17, 0x67, 0xb6, 0xa6, 0x84, 0xda, 0xc1, 0x04, 0x09, 0xa1, 0xa7, - 0x0a, 0x25, 0x58, 0xb2, 0xfa, 0xe0, 0x25, 0x2e, 0xd2, 0xc1, 0xb6, 0x2a, 0x82, 0x27, 0xf5, 0x7c, 0xf8, 0x6b, 0x47, - 0x84, 0x70, 0x9a, 0xa5, 0x48, 0x88, 0xc5, 0xf6, 0xb1, 0x9a, 0x48, 0x2a, 0x18, 0xd3, 0x3c, 0xe5, 0x03, 0xf6, 0xa0, - 0xf6, 0xe1, 0x26, 0xf5, 0x55, 0xdc, 0x8f, 0xae, 0x97, 0xf8, 0x73, 0x5d, 0x38, 0x0f, 0x86, 0x1a, 0x6f, 0xa9, 0x9c, - 0xb9, 0x1e, 0x35, 0x41, 0x63, 0xe0, 0xd2, 0xa8, 0x3f, 0x43, 0xea, 0xa0, 0xca, 0xc2, 0x78, 0x16, 0xbf, 0x04, 0x71, - 0x6e, 0x8d, 0x29, 0xf7, 0x67, 0x48, 0xe2, 0x71, 0x6f, 0xd4, 0x9f, 0x3d, 0xba, 0xcb, 0x74, 0x85, 0x00, 0xbb, 0x56, - 0xcb, 0x76, 0xd5, 0x5e, 0x42, 0x2e, 0x76, 0xe2, 0x76, 0xa6, 0x55, 0x49, 0xc0, 0x68, 0x4e, 0x53, 0xfd, 0x3d, 0x3e, - 0x0d, 0xf1, 0x2b, 0xd8, 0x70, 0x9f, 0x12, 0x54, 0x4b, 0x32, 0x9f, 0xbe, 0x44, 0x39, 0x7d, 0xa8, 0xb5, 0x6b, 0x83, - 0xc8, 0xa5, 0xeb, 0x08, 0x4f, 0x96, 0x0b, 0x39, 0x3b, 0x4e, 0xe8, 0xde, 0xfc, 0x05, 0x71, 0xa6, 0xa8, 0x45, 0x4d, - 0x81, 0x64, 0xa3, 0xc5, 0x77, 0x3a, 0xb7, 0xd0, 0x72, 0xb9, 0x1c, 0x85, 0x67, 0xdd, 0xfb, 0xb4, 0x5f, 0x91, 0x74, - 0xb5, 0x5e, 0x1b, 0xdd, 0x46, 0x77, 0x2d, 0x55, 0x64, 0x41, 0x1d, 0x1f, 0x29, 0xe3, 0xe5, 0xd0, 0x4a, 0x71, 0xf3, - 0xaa, 0x2c, 0x98, 0xe7, 0x94, 0x7a, 0x75, 0xd9, 0xf7, 0xe7, 0xb7, 0x3e, 0x41, 0x98, 0xb0, 0x47, 0xb5, 0x82, 0x5e, - 0x61, 0xbb, 0x95, 0xb7, 0x15, 0xac, 0x36, 0x69, 0x91, 0xb2, 0x33, 0xa0, 0x2d, 0x8e, 0x4f, 0x31, 0xed, 0x14, 0x05, - 0x8f, 0x3a, 0x6d, 0x74, 0x55, 0x08, 0x13, 0x9e, 0x54, 0xfc, 0xb7, 0x03, 0x33, 0x71, 0x84, 0x73, 0x43, 0x6e, 0x6f, - 0x2b, 0xb9, 0x3e, 0x1e, 0x8c, 0x9e, 0x4e, 0x84, 0x84, 0x06, 0x6d, 0x0c, 0x5e, 0xe5, 0xe0, 0xaf, 0xbf, 0x0b, 0xb1, - 0xc2, 0x87, 0x04, 0x2e, 0x87, 0x6e, 0x94, 0xeb, 0x81, 0x71, 0xcd, 0x17, 0xe8, 0x84, 0x5c, 0x3c, 0x70, 0x90, 0xd9, - 0x91, 0x4f, 0xc8, 0xc8, 0x6f, 0xcc, 0x20, 0x70, 0x4e, 0x4e, 0x56, 0x8c, 0x22, 0x84, 0x0e, 0x76, 0x1e, 0x05, 0x3a, - 0x86, 0x24, 0xe1, 0x57, 0xc7, 0x89, 0xa4, 0xb5, 0xce, 0x7b, 0x5a, 0x7f, 0x78, 0x51, 0x40, 0xf2, 0x0e, 0x62, 0xea, - 0xbe, 0x26, 0x61, 0xf2, 0x1a, 0x13, 0xb7, 0x15, 0xa3, 0xff, 0xcc, 0x4d, 0x60, 0xb6, 0xca, 0xc0, 0x06, 0x2b, 0x73, - 0x3c, 0x9d, 0x89, 0xc2, 0xb3, 0x54, 0x81, 0x79, 0x76, 0xe4, 0xac, 0x94, 0x28, 0x10, 0x28, 0x4a, 0x2d, 0x6d, 0x56, - 0xeb, 0x70, 0x45, 0x39, 0x76, 0x9f, 0x65, 0x0b, 0x95, 0x80, 0x54, 0x47, 0x93, 0x69, 0x6d, 0xf0, 0x81, 0xbb, 0xb3, - 0x5b, 0xc9, 0x28, 0x58, 0x2e, 0xfc, 0x5b, 0xa1, 0x77, 0xa8, 0xa6, 0x22, 0xa6, 0x48, 0xeb, 0xd6, 0x2a, 0x25, 0x45, - 0xd2, 0x00, 0xad, 0xb3, 0x2c, 0x28, 0x82, 0x90, 0x1e, 0xf1, 0x55, 0xb3, 0x80, 0x07, 0xb3, 0xda, 0x22, 0x9b, 0x15, - 0xdc, 0x13, 0xc1, 0xd9, 0x9a, 0x42, 0x89, 0x59, 0xcb, 0x6c, 0xdf, 0x9e, 0x6e, 0xd2, 0xd6, 0x6d, 0x45, 0xcb, 0xa0, - 0x09, 0x7d, 0x4a, 0xd3, 0xe4, 0xdf, 0xb5, 0xd9, 0xc2, 0xe1, 0x03, 0x63, 0x0e, 0x2f, 0x5d, 0x33, 0x0f, 0x00, 0x95, - 0x5a, 0xf4, 0xeb, 0x44, 0x9f, 0x7e, 0xa5, 0x91, 0x1b, 0x52, 0x80, 0x1e, 0x94, 0x82, 0x6c, 0xe4, 0x6b, 0xea, 0xc0, - 0x9d, 0x12, 0x6d, 0x02, 0xcb, 0xad, 0x88, 0x65, 0xc1, 0xea, 0xae, 0xf8, 0xfb, 0x0b, 0xd0, 0xa0, 0x2f, 0x6f, 0x18, - 0xd0, 0x4f, 0xd4, 0xde, 0x1f, 0xea, 0x50, 0x29, 0xc9, 0xed, 0xe9, 0xd2, 0xed, 0x88, 0x02, 0x6a, 0xad, 0x5e, 0x15, - 0x15, 0x9c, 0x67, 0xca, 0x00, 0xd2, 0x0e, 0x69, 0xb0, 0x61, 0x30, 0xea, 0x23, 0xf0, 0xc1, 0x7a, 0x1d, 0xc7, 0x6d, - 0x7b, 0x29, 0xba, 0x97, 0xb3, 0x3b, 0x36, 0x6a, 0x90, 0x09, 0x56, 0x4e, 0x8c, 0x61, 0x74, 0x9f, 0x77, 0xbd, 0xa7, - 0x8e, 0x89, 0x97, 0x4d, 0xaa, 0xa7, 0x98, 0x00, 0x2c, 0x98, 0x29, 0xd8, 0xa6, 0x92, 0x5a, 0x99, 0x10, 0xb4, 0x2d, - 0xe7, 0xca, 0x9a, 0x33, 0x45, 0x39, 0x7b, 0x73, 0xc8, 0xcb, 0x73, 0x73, 0x69, 0x1d, 0x45, 0x14, 0x35, 0x42, 0xda, - 0x2e, 0x8a, 0x97, 0x62, 0xc5, 0xc5, 0x47, 0x02, 0xf7, 0x46, 0xa8, 0x4c, 0x39, 0xee, 0xb8, 0x2a, 0x53, 0xfa, 0xe0, - 0x16, 0xbf, 0x67, 0x4c, 0x22, 0x9e, 0xc0, 0xe4, 0x33, 0x66, 0xc1, 0xf9, 0x42, 0x3f, 0xe2, 0x5d, 0x22, 0xbf, 0xf0, - 0xba, 0x68, 0x2b, 0xfb, 0x4c, 0x8b, 0xa0, 0xd5, 0x7b, 0x38, 0xdd, 0x9a, 0xac, 0xb9, 0x3a, 0x23, 0x47, 0x80, 0xef, - 0x58, 0xb2, 0x47, 0x32, 0x76, 0xe0, 0xb3, 0x58, 0xf4, 0xe0, 0x18, 0x12, 0x9e, 0x31, 0x82, 0xdb, 0x63, 0x9e, 0xcd, - 0xb8, 0x1c, 0x9f, 0xb5, 0x2e, 0x9e, 0xf3, 0xda, 0xeb, 0x5a, 0x91, 0x9e, 0x92, 0xd9, 0x3c, 0xe2, 0x4d, 0x43, 0xd2, - 0x79, 0xff, 0xb9, 0x47, 0x38, 0xe7, 0x1a, 0x58, 0xc5, 0x9d, 0x70, 0x5d, 0xaa, 0xd0, 0xe7, 0xe7, 0x7b, 0xe8, 0xb3, - 0x51, 0xd2, 0x5d, 0x5c, 0xa7, 0x3c, 0x9a, 0x7e, 0xb6, 0x24, 0x1e, 0xf6, 0x38, 0x1e, 0x5f, 0xd2, 0xdf, 0xd6, 0x36, - 0x40, 0xd9, 0x6a, 0x1b, 0x23, 0xd4, 0xa6, 0x39, 0x05, 0x7e, 0xbf, 0xcf, 0x71, 0x74, 0x34, 0x9e, 0xda, 0x35, 0xf0, - 0xe9, 0x7d, 0x01, 0xba, 0xaa, 0xb4, 0x7a, 0xe7, 0xe9, 0x1d, 0x2e, 0xcc, 0x06, 0xb9, 0xd7, 0x88, 0x2c, 0x83, 0xb9, - 0x5c, 0x70, 0xb2, 0xab, 0x7e, 0x48, 0xa5, 0xb4, 0x9f, 0xf9, 0xef, 0x07, 0x5d, 0x4e, 0xf7, 0xc9, 0x61, 0x1b, 0xc8, - 0x95, 0x38, 0x33, 0x2a, 0xac, 0xbe, 0x69, 0x69, 0x49, 0x3f, 0xe3, 0x32, 0x0c, 0x04, 0x44, 0xf9, 0xbf, 0x78, 0x38, - 0x48, 0xc8, 0x5b, 0x27, 0x24, 0x45, 0xd5, 0x9a, 0xd5, 0x24, 0x2f, 0xf6, 0x23, 0xa4, 0xe0, 0x50, 0x24, 0x4b, 0x5f, - 0xb4, 0x3f, 0x97, 0x88, 0x42, 0x06, 0x81, 0x51, 0x06, 0x49, 0x10, 0xad, 0xa3, 0x5b, 0x3d, 0xed, 0x24, 0xbd, 0x3c, - 0x40, 0x5f, 0xe9, 0xf9, 0xfb, 0x11, 0x0e, 0x41, 0x59, 0x73, 0xfd, 0xdc, 0x8a, 0x6c, 0xe7, 0xcf, 0x5d, 0x55, 0x58, - 0x07, 0x44, 0x2c, 0x66, 0x39, 0x5a, 0xcc, 0x8b, 0xa2, 0x64, 0xef, 0xba, 0x03, 0xf8, 0x15, 0xde, 0x99, 0x73, 0x55, - 0x5c, 0xc8, 0x31, 0x7d, 0x25, 0xae, 0xe8, 0x1c, 0x1e, 0xd1, 0x4a, 0xda, 0x96, 0xc8, 0xfe, 0x72, 0x68, 0x97, 0x9c, - 0x50, 0xa1, 0x15, 0x6e, 0x69, 0x36, 0xa7, 0xe7, 0x00, 0xc2, 0x8a, 0x2f, 0x08, 0xa5, 0xdc, 0xf3, 0x4a, 0xa7, 0x0e, - 0x86, 0xce, 0xdc, 0xa4, 0x08, 0x7d, 0x37, 0x66, 0x4e, 0x25, 0xf9, 0xd1, 0x8f, 0xed, 0xa2, 0x0a, 0xfb, 0x9f, 0xc3, - 0x95, 0x12, 0xc9, 0x7d, 0xef, 0x56, 0xb7, 0x24, 0xda, 0xf4, 0xb2, 0x22, 0x99, 0x63, 0x1d, 0xed, 0x73, 0x5a, 0x16, - 0xef, 0xae, 0x04, 0x23, 0x98, 0x3d, 0x30, 0x23, 0x9c, 0x8b, 0x41, 0x31, 0x6e, 0x99, 0x0a, 0x0b, 0xe6, 0x21, 0x72, - 0xbb, 0xeb, 0xa2, 0xca, 0x9d, 0x4c, 0x6e, 0xce, 0xf3, 0xf0, 0xb2, 0xb0, 0x62, 0xa1, 0x14, 0xbb, 0x38, 0xb7, 0x7e, - 0xe3, 0xde, 0xb7, 0xd4, 0x85, 0x25, 0xff, 0x1a, 0x4f, 0x23, 0x3c, 0x3d, 0xc2, 0xa8, 0xfc, 0x00, 0xbb, 0xb1, 0x13, - 0x7d, 0x25, 0x06, 0xe8, 0xf1, 0x9e, 0x1c, 0xbf, 0x5c, 0xde, 0x8b, 0x8e, 0x33, 0x9c, 0x30, 0xd2, 0xb8, 0xcd, 0x17, - 0xc4, 0xe9, 0x30, 0x37, 0x69, 0xc6, 0x8a, 0x7a, 0x24, 0x82, 0xf1, 0xd2, 0xfa, 0xb7, 0x2d, 0x4f, 0xf3, 0xf7, 0xf9, - 0x33, 0xc9, 0x17, 0xd3, 0x15, 0xf0, 0xf5, 0xe0, 0xcf, 0xd3, 0xfe, 0x40, 0x22, 0x10, 0x3d, 0x84, 0x23, 0x3d, 0xa6, - 0x65, 0x69, 0xf7, 0xec, 0xd8, 0x22, 0xf4, 0xfa, 0xb3, 0x44, 0x50, 0xea, 0x85, 0x52, 0xea, 0x0d, 0xca, 0x38, 0x25, - 0x81, 0x4d, 0x97, 0x42, 0x88, 0xf2, 0xfd, 0xdf, 0x38, 0x79, 0x8a, 0xf0, 0xb3, 0xe6, 0x94, 0xf6, 0x2a, 0x6a, 0x0a, - 0xea, 0x8c, 0x02, 0x60, 0x25, 0xee, 0xe3, 0x01, 0xb4, 0x6c, 0xa8, 0x0b, 0xae, 0x30, 0xa8, 0x5a, 0x95, 0x93, 0x40, - 0x9d, 0x6c, 0x14, 0x11, 0xb9, 0x29, 0xbe, 0x8b, 0x88, 0xc8, 0x1a, 0x06, 0xe5, 0x1c, 0x6c, 0x99, 0xce, 0x25, 0xc3, - 0xee, 0x36, 0xb5, 0xbc, 0xf0, 0x5e, 0x4d, 0x7a, 0xcc, 0xca, 0x76, 0xb8, 0x8f, 0x1c, 0x1d, 0x67, 0xb7, 0x7c, 0x91, - 0x38, 0x4c, 0xe2, 0x5a, 0xbd, 0xb7, 0x87, 0xac, 0xdd, 0x21, 0xe9, 0xaf, 0x05, 0x37, 0xdd, 0x21, 0xb3, 0x50, 0xda, - 0xbe, 0x3e, 0xfb, 0xa9, 0xba, 0xc3, 0xc0, 0x1b, 0x00, 0x4f, 0x31, 0xee, 0xfe, 0x6a, 0x6e, 0x43, 0xf5, 0xf8, 0x67, - 0x0f, 0x5d, 0x91, 0x48, 0x0b, 0xcc, 0x62, 0x0f, 0x87, 0x75, 0xd9, 0x4a, 0xdd, 0xb5, 0x71, 0x6e, 0x03, 0xe2, 0x8c, - 0x94, 0x90, 0x54, 0x0e, 0xd9, 0x28, 0x59, 0x1e, 0x51, 0x06, 0x6b, 0xbd, 0xbd, 0x74, 0x17, 0x73, 0x0f, 0xc3, 0x05, - 0x80, 0x92, 0x80, 0x65, 0x7b, 0xac, 0xb5, 0xfb, 0x00, 0x30, 0x42, 0xab, 0xc6, 0xcc, 0xe8, 0x55, 0xdc, 0x2a, 0xeb, - 0xc5, 0x8a, 0xcc, 0xa8, 0x1f, 0x6a, 0x22, 0x77, 0x07, 0x52, 0xd1, 0x56, 0xa8, 0x2c, 0xbf, 0x94, 0x4a, 0x4f, 0xab, - 0x02, 0xad, 0xd4, 0xd5, 0x8a, 0x0e, 0xba, 0x91, 0x92, 0xa2, 0x44, 0xdb, 0xb9, 0x00, 0xb9, 0xf2, 0x66, 0x18, 0x78, - 0x13, 0xd8, 0x2a, 0x32, 0x22, 0x81, 0x6b, 0xe1, 0xa9, 0x88, 0x24, 0x2f, 0xea, 0xae, 0x55, 0x35, 0x29, 0x8d, 0xb3, - 0x06, 0x9e, 0x6e, 0x29, 0xf2, 0x0b, 0x8d, 0x30, 0x2d, 0xf5, 0x41, 0x06, 0x89, 0xb4, 0x48, 0xe4, 0x7c, 0x5e, 0xbb, - 0x1f, 0xa2, 0x8e, 0x53, 0x74, 0x3c, 0x24, 0xdb, 0x6e, 0xbb, 0x14, 0x25, 0x87, 0x89, 0xee, 0x24, 0x16, 0xd3, 0x11, - 0x03, 0x95, 0xb2, 0x21, 0xc7, 0xd2, 0x6b, 0xd7, 0x8a, 0x13, 0xb8, 0xf8, 0x0f, 0xf9, 0xd8, 0xe6, 0xd9, 0x86, 0x61, - 0x0b, 0x2d, 0xcb, 0x11, 0xfd, 0xe5, 0xa5, 0x84, 0x0e, 0xd2, 0x12, 0x3d, 0xe4, 0x07, 0xc5, 0xb2, 0xab, 0x90, 0x35, - 0xe8, 0xa0, 0x71, 0xee, 0x4c, 0x66, 0x0b, 0x89, 0x94, 0x69, 0x52, 0x6b, 0x5a, 0x6c, 0x42, 0xc4, 0x33, 0x3f, 0x58, - 0x15, 0xa2, 0x46, 0x3c, 0xc8, 0x54, 0x58, 0x0a, 0xce, 0x16, 0x41, 0xe2, 0x4b, 0x9c, 0x1d, 0xce, 0x8b, 0xdd, 0x60, - 0x91, 0x45, 0xef, 0x30, 0xea, 0xcb, 0x61, 0x5f, 0xb7, 0x22, 0x36, 0xbd, 0x35, 0x2e, 0x3c, 0xaf, 0x99, 0xb5, 0x6a, - 0x47, 0x8c, 0x39, 0x43, 0x18, 0x29, 0x04, 0xf9, 0xe8, 0xd3, 0x11, 0xce, 0x8a, 0x53, 0x81, 0x0d, 0x1b, 0xd7, 0xb1, - 0xc3, 0xd9, 0x87, 0xba, 0x8b, 0xa0, 0xe1, 0xb9, 0x3a, 0x22, 0x48, 0xcc, 0x78, 0x83, 0x51, 0x2b, 0x34, 0xdf, 0xe8, - 0x3a, 0x6f, 0xcd, 0x74, 0xf3, 0x8d, 0xa4, 0x47, 0x69, 0xe1, 0x91, 0xdf, 0x62, 0x52, 0x71, 0xe6, 0xd6, 0x7e, 0x90, - 0x25, 0xd6, 0xfd, 0x0f, 0x41, 0xfc, 0x8a, 0x80, 0xea, 0x24, 0x21, 0x20, 0x40, 0x43, 0xeb, 0x7a, 0xa1, 0xd9, 0x56, - 0x58, 0x09, 0x0a, 0xcf, 0x55, 0xf0, 0x5f, 0x92, 0xa2, 0x61, 0xd2, 0x84, 0x26, 0x1e, 0x95, 0xfb, 0xb1, 0x83, 0x05, - 0xe2, 0x2c, 0x20, 0x8a, 0xc1, 0x49, 0x50, 0x09, 0x09, 0xb7, 0x54, 0x42, 0x7b, 0xa1, 0x15, 0x13, 0x2c, 0x80, 0x69, - 0x4f, 0x5c, 0x4a, 0x81, 0x62, 0xda, 0x8a, 0xa3, 0x39, 0x56, 0x43, 0x80, 0x61, 0x90, 0x51, 0x7f, 0x04, 0x5d, 0xac, - 0x61, 0x9a, 0x8c, 0xf7, 0xbb, 0x78, 0xe1, 0xe9, 0xe6, 0x74, 0x85, 0x52, 0x16, 0xf9, 0x2c, 0xc0, 0x09, 0xcd, 0xf8, - 0xa4, 0x00, 0xf5, 0x45, 0xbd, 0xb4, 0xf1, 0xdc, 0x3a, 0x9e, 0x83, 0x27, 0xe7, 0x8d, 0xe0, 0x6d, 0x1c, 0x54, 0xee, - 0x60, 0x0f, 0x60, 0x91, 0xd7, 0x5c, 0x33, 0x92, 0xcc, 0x18, 0x1e, 0x0d, 0xf3, 0x8c, 0xb9, 0x53, 0x42, 0xdb, 0x33, - 0xb9, 0x09, 0x5c, 0x9b, 0x06, 0xab, 0x86, 0xa5, 0x1f, 0xaf, 0xae, 0xd7, 0x5c, 0x1f, 0x40, 0xee, 0xdb, 0x96, 0x12, - 0x76, 0x37, 0x22, 0x8d, 0x31, 0x60, 0x9b, 0x50, 0xbd, 0x3f, 0x21, 0x9b, 0xa6, 0x5a, 0xd6, 0xc1, 0x61, 0xce, 0x2f, - 0x12, 0x54, 0xee, 0x41, 0xdb, 0x54, 0x16, 0xa1, 0xd7, 0x3c, 0xee, 0x89, 0x3e, 0x4f, 0xb8, 0x21, 0x58, 0x83, 0xd4, - 0x89, 0x8b, 0xab, 0xf2, 0x24, 0x41, 0x37, 0x5a, 0x6a, 0x2b, 0x96, 0x07, 0x03, 0x2e, 0xca, 0xb1, 0x1b, 0x92, 0x52, - 0xc1, 0x51, 0x92, 0xf4, 0x34, 0x96, 0x6a, 0x97, 0xdb, 0x6f, 0x33, 0x2e, 0xf5, 0x8e, 0x12, 0x9a, 0xd0, 0x69, 0x21, - 0x23, 0x0d, 0x84, 0x02, 0xb5, 0xb9, 0xbf, 0x4c, 0xdf, 0x8c, 0x3e, 0xc3, 0xb0, 0x91, 0x8b, 0xe1, 0x01, 0x94, 0xb3, - 0xda, 0x71, 0x38, 0xc7, 0xc3, 0xb2, 0x90, 0x5e, 0x30, 0x99, 0x21, 0xb2, 0x44, 0x2e, 0x7f, 0xd4, 0xa4, 0xe4, 0x02, - 0x1d, 0x4b, 0x6b, 0x1e, 0xd0, 0xae, 0x4e, 0x70, 0xa0, 0x3b, 0x7c, 0xd5, 0xc9, 0x57, 0x75, 0x14, 0xc9, 0x1c, 0x43, - 0xe7, 0xc0, 0xe2, 0x54, 0xcb, 0xb3, 0x91, 0x9d, 0xee, 0x0e, 0x70, 0x5e, 0x4a, 0xb7, 0x0b, 0x70, 0xd7, 0xfe, 0xc5, - 0x89, 0x8b, 0xe7, 0xb6, 0xd5, 0x60, 0x8b, 0xce, 0x74, 0x08, 0xe7, 0xcf, 0xd4, 0xcd, 0x09, 0x6f, 0xa1, 0xcb, 0xa9, - 0xfd, 0xb9, 0xe0, 0xfa, 0xe3, 0x15, 0xdd, 0x6e, 0xeb, 0x82, 0xc3, 0x72, 0x94, 0xb3, 0x2e, 0x89, 0x54, 0xb2, 0xd2, - 0x1b, 0x7d, 0x3e, 0x90, 0xa7, 0x0d, 0xb6, 0x5f, 0x28, 0x98, 0x39, 0x75, 0x50, 0xac, 0x62, 0x92, 0xd9, 0xe1, 0xc1, - 0xe4, 0xbb, 0xb2, 0x58, 0x32, 0x56, 0x27, 0xb3, 0xdc, 0x81, 0x71, 0x4b, 0x6b, 0xef, 0x57, 0x76, 0x29, 0xe3, 0xcb, - 0x88, 0x72, 0x2b, 0xaf, 0x8d, 0x83, 0x4c, 0xdb, 0x25, 0xb2, 0xdc, 0xd6, 0xb7, 0xcb, 0x34, 0x7b, 0x48, 0xd2, 0xed, - 0x04, 0xc9, 0x77, 0x06, 0x9f, 0x18, 0x52, 0xa2, 0x17, 0x52, 0xeb, 0xf1, 0xb5, 0x77, 0x95, 0x38, 0x45, 0xbc, 0x2a, - 0x06, 0x61, 0x65, 0x7d, 0x8e, 0x2d, 0x69, 0x16, 0xa8, 0x63, 0x15, 0x49, 0xdc, 0x2a, 0x24, 0x7e, 0x69, 0xf5, 0x17, - 0xb6, 0xdc, 0xa8, 0xfc, 0x14, 0x89, 0x77, 0x88, 0xfe, 0x72, 0x5c, 0xa2, 0x7b, 0xad, 0x0a, 0x44, 0x19, 0xe6, 0xa9, - 0x9c, 0xb1, 0x60, 0xe9, 0xe6, 0x89, 0x2c, 0x9a, 0x3d, 0x5f, 0x6e, 0xa0, 0x49, 0x94, 0x88, 0xcd, 0x85, 0x5e, 0xe6, - 0xce, 0x19, 0xe8, 0xe8, 0x24, 0xac, 0x53, 0xab, 0xc9, 0xc4, 0x1e, 0x83, 0xb3, 0x97, 0xac, 0xe8, 0x09, 0xae, 0x7b, - 0xce, 0x3b, 0xfb, 0xaf, 0xb9, 0x70, 0x3a, 0x34, 0xfb, 0xe9, 0xfc, 0x98, 0x61, 0x96, 0x8e, 0x14, 0xb8, 0x25, 0x76, - 0xab, 0x3b, 0x11, 0x65, 0x4c, 0xfb, 0xc4, 0x58, 0x5d, 0xdf, 0x76, 0x8a, 0x8e, 0xc9, 0xbf, 0x99, 0xa7, 0xe1, 0xdc, - 0x39, 0x51, 0x62, 0x37, 0x39, 0x61, 0xb7, 0xd6, 0xdd, 0xf3, 0xe0, 0x67, 0x84, 0x18, 0xa5, 0x14, 0x6c, 0x82, 0x7a, - 0xab, 0xaa, 0x02, 0xe6, 0x69, 0x58, 0x34, 0x63, 0x4f, 0x14, 0x91, 0x5d, 0x7f, 0x27, 0x66, 0x8e, 0x29, 0x8b, 0x2e, - 0x59, 0x93, 0xc1, 0x54, 0x4d, 0xa9, 0x3b, 0x92, 0x1a, 0xb9, 0x83, 0x84, 0xec, 0x6f, 0x8d, 0x14, 0x81, 0x7a, 0xa3, - 0x71, 0x71, 0x6f, 0x0d, 0x8c, 0x69, 0xa0, 0xd9, 0xd6, 0x2c, 0x1d, 0xa8, 0x03, 0x37, 0xda, 0xd6, 0x85, 0x4a, 0xd5, - 0x76, 0xe1, 0xeb, 0x57, 0xfb, 0xbc, 0xcf, 0xac, 0x05, 0x6d, 0x18, 0xfa, 0x19, 0xd8, 0x26, 0xc5, 0xfd, 0x17, 0x22, - 0x4d, 0x15, 0xa5, 0xd8, 0x77, 0x20, 0x9b, 0x75, 0x6f, 0xad, 0x82, 0x90, 0x93, 0xaa, 0xf4, 0x7d, 0x9a, 0xf5, 0xa4, - 0xd3, 0x95, 0x65, 0x65, 0xb6, 0x8d, 0xdf, 0xee, 0x86, 0xed, 0x83, 0x85, 0xcd, 0x2b, 0x95, 0x4e, 0xa4, 0x83, 0x08, - 0x0c, 0x83, 0xe7, 0xd0, 0x97, 0x7e, 0xa0, 0xf2, 0x7b, 0xa0, 0xfa, 0xac, 0x8c, 0x1d, 0xae, 0xbd, 0xd0, 0x78, 0x01, - 0x5d, 0x90, 0x70, 0x3f, 0x4d, 0x2a, 0xa7, 0x61, 0x52, 0x83, 0x8e, 0xb6, 0xba, 0x4e, 0x2c, 0x0f, 0x44, 0x80, 0x7f, - 0x28, 0x50, 0x8d, 0x99, 0x01, 0x76, 0x3d, 0x09, 0x6c, 0xab, 0x59, 0xd6, 0x43, 0x2f, 0x38, 0x9c, 0xae, 0xa0, 0xbb, - 0x97, 0x5f, 0x31, 0x0e, 0x72, 0x87, 0x5d, 0x29, 0xb0, 0x3e, 0x39, 0x72, 0x2c, 0x50, 0x3b, 0x47, 0x0d, 0x0c, 0xbb, - 0x45, 0x6d, 0xb8, 0xef, 0x53, 0x6a, 0x76, 0x43, 0xb8, 0x1b, 0x1c, 0xb8, 0xa5, 0x62, 0xdb, 0xf2, 0xa8, 0xd2, 0xfc, - 0x65, 0x3b, 0x50, 0x46, 0xeb, 0x8d, 0x51, 0xef, 0xed, 0xee, 0x43, 0x49, 0x4a, 0xdb, 0xcf, 0x97, 0xf9, 0x24, 0xd9, - 0x7b, 0x65, 0x96, 0xba, 0x7a, 0x3f, 0x35, 0xb9, 0x5d, 0xad, 0xa9, 0xd2, 0x99, 0x0a, 0x0e, 0x85, 0x72, 0x9e, 0x5d, - 0xb9, 0x93, 0x12, 0x2b, 0x6c, 0xee, 0xa5, 0x1b, 0x41, 0x7a, 0xec, 0x24, 0x53, 0x62, 0x42, 0x48, 0x9d, 0xfd, 0x76, - 0x67, 0xee, 0x0f, 0x57, 0xdf, 0x92, 0xa2, 0xbe, 0xe3, 0xa6, 0xe5, 0x78, 0xe9, 0xb7, 0xcb, 0x8d, 0x32, 0x98, 0x46, - 0xd1, 0x60, 0x69, 0x19, 0x1c, 0x74, 0xd7, 0x32, 0xc0, 0xb9, 0x4b, 0xfc, 0x5d, 0x3f, 0xae, 0x68, 0xda, 0x00, 0x5d, - 0x16, 0xfb, 0x84, 0x72, 0x49, 0x1c, 0x94, 0xf0, 0x48, 0xd3, 0x26, 0x4d, 0x88, 0x14, 0x39, 0xd8, 0xb6, 0x90, 0x81, - 0x21, 0x59, 0x88, 0x62, 0x50, 0xf9, 0x55, 0xae, 0x4e, 0x78, 0x9d, 0xcf, 0x16, 0xbc, 0x84, 0x28, 0x5c, 0x95, 0x71, - 0x75, 0xa3, 0x66, 0x31, 0xaf, 0x0e, 0x3b, 0xa9, 0xa6, 0x0d, 0x0d, 0x63, 0xd4, 0x11, 0xb9, 0xdb, 0xf8, 0xe0, 0x9d, - 0x2d, 0xd4, 0x0c, 0x16, 0xdf, 0xa9, 0x09, 0xf8, 0x6b, 0x7d, 0xf1, 0x16, 0x42, 0x0e, 0x71, 0x9e, 0x56, 0x68, 0x78, - 0xa1, 0xac, 0xd1, 0xb8, 0x17, 0xb2, 0x1a, 0xfb, 0xb9, 0xcb, 0x20, 0x6d, 0x38, 0x19, 0x94, 0x8e, 0xc3, 0xa5, 0x7c, - 0x97, 0xd4, 0x2d, 0xbd, 0x41, 0x89, 0xb8, 0x0e, 0x60, 0x27, 0x6a, 0xa9, 0x74, 0x51, 0x49, 0xeb, 0xa7, 0x86, 0xf2, - 0x64, 0xd8, 0x4b, 0xe7, 0x64, 0x60, 0xcc, 0xe8, 0x3c, 0xd4, 0x8c, 0x41, 0xb4, 0x86, 0x65, 0xd8, 0xa0, 0x7d, 0xac, - 0x5e, 0x20, 0xfb, 0x44, 0xd3, 0xaa, 0x33, 0x74, 0xd8, 0xc9, 0x84, 0x5f, 0xaa, 0x53, 0x31, 0x65, 0xfe, 0x95, 0x99, - 0xb6, 0xcd, 0xfb, 0x6e, 0x34, 0x94, 0x37, 0x97, 0x7e, 0xcc, 0xf9, 0x15, 0x97, 0x02, 0x97, 0x0b, 0x68, 0x0d, 0xf7, - 0x90, 0x7f, 0xc3, 0xbc, 0xec, 0xd7, 0x76, 0x60, 0x02, 0x11, 0xa7, 0x1a, 0x8d, 0x73, 0x4a, 0x8e, 0xa6, 0x3a, 0xe7, - 0x7d, 0x13, 0xce, 0x28, 0x95, 0x06, 0x64, 0xd4, 0xb2, 0x48, 0x26, 0xc1, 0x4c, 0x07, 0xcd, 0x0b, 0x67, 0x1b, 0xed, - 0xa4, 0xd1, 0xc1, 0xeb, 0x4d, 0xdc, 0x75, 0x41, 0x93, 0x5e, 0x11, 0x3f, 0x76, 0xd4, 0x56, 0x8c, 0x53, 0x17, 0x2e, - 0x02, 0xcf, 0xe4, 0x2c, 0x8b, 0x43, 0x99, 0xf4, 0x7a, 0x45, 0xd5, 0xb2, 0xa4, 0xb3, 0x54, 0x0f, 0xe8, 0x12, 0xd4, - 0xe3, 0xd3, 0xa2, 0xbc, 0x62, 0x35, 0x98, 0xef, 0x40, 0xd9, 0x6b, 0x97, 0xd0, 0xf3, 0x7d, 0xa1, 0x0e, 0x32, 0x1a, - 0xbb, 0xf3, 0xf9, 0x92, 0x1a, 0x93, 0x03, 0xe7, 0x4d, 0xf3, 0x0a, 0x67, 0xd7, 0x5b, 0x52, 0x0b, 0xa1, 0x4f, 0xda, - 0xa0, 0x67, 0x89, 0x84, 0xbf, 0x83, 0x3a, 0x9c, 0xdd, 0x20, 0xa9, 0x33, 0x6c, 0xca, 0xe9, 0xa7, 0xa0, 0x35, 0xe1, - 0x62, 0x23, 0x0b, 0xdb, 0x87, 0x1e, 0x54, 0x9b, 0x47, 0x76, 0x71, 0xb8, 0xa3, 0x98, 0x36, 0x83, 0xb0, 0x96, 0xe0, - 0xa1, 0x34, 0xf4, 0x16, 0x9b, 0xfe, 0x7c, 0x23, 0xc3, 0xe5, 0x26, 0xc9, 0xc2, 0x95, 0xe9, 0xd1, 0x10, 0x60, 0xd7, - 0xee, 0xf7, 0xb6, 0x3a, 0x05, 0x7f, 0x09, 0x0f, 0x46, 0x31, 0x7d, 0x3e, 0x7b, 0x65, 0x80, 0xfd, 0x44, 0x4f, 0xa7, - 0xfb, 0xa6, 0x50, 0x3a, 0x87, 0x5c, 0x62, 0x5d, 0x18, 0x63, 0x8c, 0xa3, 0x7a, 0xb7, 0xa3, 0x8c, 0xbd, 0xe4, 0xd8, - 0x01, 0x0f, 0x85, 0x0f, 0x77, 0x94, 0xf2, 0xaa, 0x1d, 0x6b, 0x37, 0xb9, 0xe6, 0x1b, 0xf9, 0x88, 0x1c, 0xbd, 0xa4, - 0x18, 0xa4, 0x65, 0x23, 0xa0, 0x19, 0x83, 0x97, 0x48, 0x0b, 0xd2, 0x36, 0xf4, 0xb3, 0xcc, 0x75, 0x42, 0xa1, 0x05, - 0x9c, 0x9e, 0x31, 0xa8, 0x28, 0x2c, 0x3a, 0xaa, 0xa4, 0xfd, 0x87, 0x03, 0x42, 0x06, 0xa3, 0xd5, 0xda, 0x6c, 0xcb, - 0xf6, 0xa6, 0xc9, 0x1f, 0x6c, 0x3f, 0xd1, 0x9b, 0xe9, 0x43, 0x7e, 0x7a, 0x1c, 0x03, 0x5f, 0x35, 0xb7, 0x6b, 0x3c, - 0xaf, 0xf7, 0x5e, 0x55, 0x93, 0x6f, 0xfd, 0x55, 0x8e, 0x8f, 0xa1, 0x86, 0x64, 0xe9, 0x44, 0xe9, 0xf2, 0xb0, 0xf7, - 0xb3, 0x3e, 0xb1, 0x4f, 0x16, 0x26, 0xd3, 0x3b, 0x93, 0xd8, 0x8c, 0xd7, 0x9d, 0x6f, 0x30, 0xae, 0x8c, 0x78, 0x65, - 0xfd, 0x56, 0x9f, 0xc9, 0xc1, 0xf6, 0x12, 0x30, 0x52, 0xaf, 0x2c, 0x05, 0x0e, 0x0a, 0x3a, 0x71, 0x08, 0x1e, 0x22, - 0xcf, 0x71, 0xe6, 0x86, 0x2f, 0x6a, 0x5d, 0x93, 0x88, 0xc8, 0x97, 0xf5, 0x2c, 0x4f, 0x21, 0x73, 0x24, 0x6c, 0xb9, - 0x9e, 0x3e, 0x06, 0x4e, 0x95, 0xb6, 0xec, 0x2f, 0x9b, 0xad, 0xe6, 0xfa, 0x10, 0xfc, 0x23, 0xd2, 0x5d, 0xfc, 0x1a, - 0xc7, 0x23, 0x8d, 0x64, 0x21, 0x55, 0xb5, 0x90, 0x5b, 0x16, 0x0d, 0x16, 0x32, 0x8c, 0x2f, 0x2b, 0x53, 0xd9, 0x8b, - 0x3b, 0x50, 0x22, 0x5f, 0xdf, 0xc2, 0x19, 0x0e, 0x87, 0xd0, 0xf9, 0xeb, 0x9b, 0x2a, 0x43, 0x56, 0x3f, 0xef, 0xd9, - 0x88, 0x63, 0xac, 0x8f, 0xad, 0xb7, 0x37, 0xbd, 0x5b, 0x81, 0xc8, 0x19, 0x27, 0xdb, 0xa7, 0x5f, 0x71, 0xbf, 0x56, - 0xf8, 0x7a, 0xd8, 0x54, 0xf8, 0xf5, 0xd6, 0xc5, 0x81, 0xac, 0x20, 0xe3, 0x09, 0x0b, 0x46, 0x20, 0xc5, 0x63, 0x83, - 0x0e, 0x1a, 0xa7, 0x0c, 0xa8, 0x37, 0xb0, 0xaf, 0x9b, 0x3a, 0xf2, 0xf5, 0x65, 0xf6, 0xb7, 0xe9, 0xb2, 0x1f, 0x40, - 0x96, 0x7d, 0xfe, 0x01, 0x1b, 0xb6, 0xa5, 0xbb, 0x01, 0xb3, 0x37, 0x90, 0x19, 0x99, 0xf6, 0x4b, 0xa4, 0x8f, 0x30, - 0x68, 0x9b, 0xcb, 0x00, 0xae, 0x4d, 0xfa, 0xf3, 0xf9, 0x18, 0x42, 0x0c, 0x21, 0x2c, 0xe3, 0x9d, 0x1b, 0xef, 0x46, - 0xfa, 0xa6, 0xd1, 0x2d, 0x52, 0xfc, 0x17, 0xf1, 0x2c, 0x0b, 0x38, 0x0f, 0x91, 0x3a, 0xc1, 0x55, 0xbd, 0x6c, 0x4f, - 0x90, 0x2a, 0xd7, 0xe2, 0xf5, 0xe1, 0x1b, 0x89, 0xc5, 0x9e, 0x88, 0x8f, 0x39, 0xd4, 0x39, 0x64, 0x3a, 0x89, 0x66, - 0xe9, 0x2b, 0x75, 0x40, 0x28, 0x27, 0x60, 0x7e, 0x96, 0x58, 0xeb, 0x94, 0x1c, 0xc2, 0xdb, 0x37, 0xff, 0x26, 0xca, - 0x3d, 0x78, 0x2c, 0x29, 0x86, 0x29, 0x5a, 0x88, 0x31, 0x8e, 0x8b, 0xa7, 0x75, 0x9d, 0x90, 0x11, 0xeb, 0xcf, 0xcf, - 0x56, 0x99, 0xad, 0x81, 0x1a, 0x49, 0x43, 0xe1, 0x90, 0x1b, 0x1d, 0x33, 0x0b, 0x93, 0x0b, 0xe3, 0x6c, 0xdd, 0x16, - 0xef, 0x24, 0xf2, 0xa8, 0x7c, 0x33, 0x0e, 0x8f, 0xd4, 0xe3, 0x90, 0x8d, 0xb4, 0xca, 0x92, 0x4e, 0xb8, 0x13, 0x0c, - 0x87, 0xc9, 0xa2, 0x8c, 0xcd, 0x2c, 0xa4, 0x10, 0xad, 0xe4, 0x04, 0x20, 0x7b, 0x38, 0x41, 0x2d, 0x04, 0x66, 0x95, - 0x61, 0x65, 0x28, 0x0c, 0x88, 0x38, 0x08, 0x77, 0x9f, 0xfc, 0xb1, 0xc0, 0xfe, 0x56, 0x1e, 0x43, 0xf2, 0xe1, 0x97, - 0x38, 0x42, 0x0f, 0xc6, 0xb5, 0x50, 0x06, 0x13, 0x21, 0x7a, 0xcb, 0x18, 0xce, 0x53, 0x9d, 0x78, 0x8b, 0xde, 0x3a, - 0xd1, 0x0d, 0x24, 0x04, 0x71, 0xb3, 0x96, 0xf3, 0x0d, 0xac, 0x28, 0x0b, 0x1c, 0x34, 0x61, 0x9d, 0x15, 0x5b, 0xb1, - 0x4d, 0xc1, 0x43, 0x94, 0xe4, 0x00, 0xf8, 0x32, 0x40, 0xae, 0x4e, 0xb2, 0x2b, 0x25, 0xb0, 0x0e, 0xe1, 0xa4, 0x60, - 0xa6, 0x31, 0xb2, 0xe6, 0xd5, 0xa6, 0xf6, 0x61, 0x56, 0x8d, 0x6f, 0x00, 0xa6, 0xbe, 0x72, 0x4e, 0xd8, 0x66, 0x97, - 0x8e, 0x6a, 0xb1, 0x2d, 0x16, 0xfd, 0x8f, 0x7b, 0x51, 0x03, 0x5e, 0xbd, 0x1e, 0x67, 0xff, 0x0b, 0x46, 0xe7, 0x0e, - 0x88, 0x7e, 0x75, 0xef, 0xb0, 0xcd, 0x01, 0x9b, 0x64, 0x55, 0xdb, 0x48, 0x9c, 0x0e, 0x78, 0x4e, 0xaa, 0x75, 0x92, - 0x46, 0x41, 0xf5, 0xc4, 0xa6, 0x7b, 0x1d, 0x59, 0x71, 0xd6, 0x44, 0x01, 0x5b, 0xc5, 0x1a, 0xe1, 0x82, 0xf1, 0xe5, - 0x42, 0xdc, 0x6c, 0xbb, 0x00, 0x86, 0x30, 0xd6, 0xac, 0xb8, 0xc6, 0x07, 0xbf, 0x3d, 0x05, 0xd4, 0x13, 0x96, 0x78, - 0x08, 0xfb, 0x1a, 0x84, 0x93, 0xf9, 0xf0, 0xb3, 0x59, 0xdf, 0x7c, 0x83, 0xaa, 0xcb, 0x10, 0xf3, 0xfc, 0x24, 0xa7, - 0xc7, 0xdf, 0x2e, 0x3f, 0x74, 0x3a, 0x4b, 0x3f, 0xe3, 0x3a, 0x4b, 0x84, 0x79, 0xf7, 0xd3, 0x1f, 0x4d, 0x6b, 0x03, - 0x6f, 0xd1, 0x55, 0x73, 0x51, 0x33, 0xce, 0x9d, 0x3d, 0x27, 0x9b, 0x08, 0x7b, 0x4a, 0x80, 0x4a, 0x35, 0x57, 0xf5, - 0x9b, 0x22, 0xf5, 0x31, 0xb6, 0xa9, 0xe2, 0xe3, 0x09, 0xd0, 0x52, 0xbe, 0xb9, 0xa3, 0x0b, 0x26, 0x41, 0xd6, 0xfd, - 0x7c, 0xcb, 0xa8, 0xd0, 0xc0, 0xb0, 0x1f, 0x13, 0xc2, 0x79, 0xfa, 0x89, 0x80, 0x91, 0xb4, 0x93, 0x4d, 0xfa, 0x20, - 0xe9, 0xb1, 0x89, 0x22, 0xe7, 0x4c, 0xc3, 0xf8, 0x8c, 0x13, 0x68, 0x0c, 0x58, 0x5a, 0x16, 0x1d, 0xca, 0x4a, 0xdb, - 0xc4, 0x9f, 0xc8, 0x77, 0x63, 0x13, 0x5b, 0x0d, 0x41, 0x1a, 0x4c, 0x80, 0x36, 0xc3, 0xe9, 0x0c, 0x74, 0x41, 0x17, - 0xbd, 0xb9, 0x79, 0x6f, 0xb9, 0xf9, 0x30, 0x32, 0x0f, 0x5d, 0xfe, 0x9c, 0xd8, 0x8a, 0xb7, 0x26, 0x75, 0x4e, 0xd5, - 0xb5, 0x2e, 0xe9, 0x4c, 0x7f, 0xc2, 0xb6, 0x12, 0x4b, 0x88, 0xbc, 0xa3, 0xfd, 0x21, 0x3c, 0x84, 0xb4, 0x45, 0xc9, - 0x89, 0xed, 0x9f, 0x14, 0x2b, 0x39, 0x9e, 0x6c, 0x2c, 0xfb, 0x69, 0x53, 0xfb, 0x5b, 0xa4, 0x83, 0xdd, 0x57, 0xea, - 0x87, 0x55, 0x5c, 0x12, 0x35, 0x5c, 0x8b, 0x2e, 0x28, 0xfd, 0x0b, 0xd3, 0x49, 0x62, 0xd5, 0xe5, 0x18, 0xf7, 0x2c, - 0x99, 0x63, 0x7d, 0x0c, 0x0a, 0x4f, 0x57, 0x91, 0x4c, 0xe8, 0xbc, 0x86, 0xba, 0x34, 0xbd, 0xeb, 0xea, 0x14, 0xe1, - 0x0d, 0x65, 0xce, 0x5b, 0x6d, 0x89, 0xda, 0xe9, 0x7d, 0xcd, 0xff, 0x6e, 0x50, 0x64, 0x93, 0x91, 0x9c, 0x07, 0xce, - 0x60, 0x2d, 0xc9, 0xe0, 0x51, 0x89, 0x28, 0x2a, 0x1f, 0x62, 0xf3, 0x45, 0xae, 0xa0, 0x97, 0xa7, 0x88, 0x8a, 0xbb, - 0x65, 0xb1, 0xf3, 0x31, 0x7f, 0x50, 0x5b, 0xa2, 0x0e, 0x4b, 0x2a, 0x4a, 0x60, 0x65, 0xdd, 0x4f, 0x23, 0x2e, 0xf5, - 0x9f, 0xe2, 0xf6, 0xfb, 0x95, 0xc7, 0x70, 0x45, 0xde, 0xdb, 0x14, 0x5d, 0xd1, 0x0e, 0x8e, 0xba, 0x61, 0xd9, 0x2d, - 0x7f, 0x48, 0x03, 0x92, 0x3d, 0xb7, 0x7a, 0x78, 0x08, 0x9f, 0x27, 0xff, 0xb0, 0xac, 0xfd, 0x65, 0x55, 0x49, 0x0f, - 0xa5, 0x91, 0x42, 0x1f, 0xa9, 0xe6, 0xc7, 0x15, 0xdd, 0xde, 0x4f, 0xad, 0x5b, 0xaf, 0x1f, 0x60, 0xf6, 0x51, 0x86, - 0xc8, 0xda, 0x2c, 0x5b, 0xf5, 0x01, 0x2a, 0x18, 0x5a, 0xf1, 0x19, 0xf4, 0x44, 0xd3, 0xa4, 0x5e, 0x79, 0x33, 0x3a, - 0x33, 0x73, 0x90, 0x71, 0x68, 0xb9, 0xfc, 0xf1, 0x1b, 0x11, 0x13, 0x93, 0xaa, 0xa5, 0xb6, 0x28, 0xc3, 0xf5, 0x82, - 0x93, 0x28, 0x11, 0x4f, 0x30, 0xa7, 0xdf, 0xa5, 0xf4, 0x82, 0x39, 0x14, 0xac, 0x70, 0x8e, 0x3e, 0x9f, 0x95, 0x72, - 0x29, 0x09, 0xf9, 0xb6, 0x84, 0x6c, 0xa1, 0x21, 0x94, 0x52, 0x6e, 0x39, 0x1a, 0x97, 0x73, 0x38, 0x65, 0x6c, 0xf6, - 0x14, 0x26, 0x3e, 0x15, 0xaf, 0x62, 0xde, 0xe8, 0xf5, 0x35, 0x62, 0x91, 0x72, 0xd9, 0x05, 0x09, 0x0b, 0x67, 0x24, - 0x97, 0x18, 0xd9, 0x04, 0x2b, 0x9c, 0x5b, 0xa8, 0x06, 0xb3, 0xae, 0x0d, 0x94, 0xaa, 0x6f, 0x40, 0x8f, 0x86, 0x7c, - 0xd5, 0xd4, 0xb9, 0xea, 0x7f, 0x3a, 0xa1, 0x11, 0x2f, 0x0b, 0xdf, 0x71, 0x1f, 0x4a, 0x4f, 0xaf, 0x90, 0x11, 0xd7, - 0x6d, 0x27, 0x1d, 0x68, 0xc6, 0xc8, 0x48, 0x98, 0xa3, 0x45, 0x9d, 0x8b, 0x06, 0xda, 0x28, 0xc4, 0x95, 0x04, 0x2d, - 0xa4, 0x11, 0x92, 0x54, 0xec, 0x5c, 0x06, 0x4e, 0x1a, 0x48, 0x4f, 0x12, 0x14, 0x32, 0xe4, 0x61, 0xee, 0x7f, 0x25, - 0x65, 0xd1, 0xd4, 0xc2, 0x25, 0xe6, 0xb7, 0xf2, 0xfd, 0xa9, 0x2d, 0x5a, 0xb5, 0x0e, 0x14, 0x90, 0xca, 0x23, 0xd6, - 0x2c, 0x9b, 0x71, 0xaf, 0x38, 0x2a, 0xc7, 0xa3, 0xd2, 0xd6, 0x94, 0x9a, 0xae, 0x68, 0x1e, 0x34, 0xa5, 0x87, 0xe9, - 0x94, 0xd8, 0x1a, 0xcb, 0xab, 0x53, 0x4b, 0xa5, 0xfa, 0xf7, 0x99, 0xa5, 0xba, 0x38, 0x6a, 0xf9, 0x26, 0xb0, 0xd8, - 0x9d, 0x83, 0x09, 0x0d, 0xf7, 0x99, 0xcd, 0xa7, 0x30, 0x2c, 0xa7, 0xcc, 0xb2, 0xec, 0xc1, 0xd2, 0x66, 0x42, 0xd0, - 0xe6, 0x3b, 0x8c, 0x13, 0xf2, 0x8c, 0x18, 0x50, 0x48, 0xa9, 0x91, 0xaf, 0xcd, 0x06, 0x31, 0xf8, 0x89, 0xdb, 0x9f, - 0xe8, 0x22, 0x41, 0xc1, 0x11, 0x3d, 0x1f, 0x1c, 0x72, 0x3c, 0x7e, 0x90, 0xa9, 0x19, 0x46, 0xb0, 0x14, 0x2f, 0x67, - 0xd6, 0xd3, 0x12, 0x10, 0x10, 0x4d, 0xf2, 0x5e, 0xbd, 0x11, 0x81, 0x9a, 0x59, 0x09, 0x51, 0x07, 0x27, 0x0c, 0xbf, - 0x08, 0x31, 0xe0, 0x8c, 0x02, 0x10, 0x8e, 0x39, 0x3d, 0x20, 0x87, 0xaf, 0x73, 0x96, 0x7e, 0x4b, 0x4b, 0xe5, 0xa8, - 0xed, 0x45, 0x61, 0x9a, 0x3e, 0x8e, 0x05, 0x0e, 0x95, 0x04, 0xd5, 0x4b, 0x61, 0xb4, 0xd8, 0xf0, 0x7b, 0xe1, 0xea, - 0xd0, 0x27, 0x6f, 0xee, 0xc3, 0x6b, 0xce, 0x3a, 0x7c, 0x4c, 0xc2, 0x8e, 0x49, 0xc1, 0x85, 0x9d, 0xba, 0x6c, 0xe4, - 0x40, 0x00, 0x60, 0x6f, 0xeb, 0xcf, 0x13, 0xde, 0x66, 0xcb, 0x58, 0xd0, 0xf1, 0xf6, 0x0d, 0x3e, 0x1c, 0x02, 0x3f, - 0xea, 0xed, 0x68, 0x99, 0xa4, 0x7b, 0xd2, 0x90, 0xba, 0x97, 0x35, 0x6c, 0xc1, 0xe4, 0x9c, 0x5f, 0xa0, 0xa3, 0xb7, - 0x99, 0xa3, 0xe4, 0xbe, 0xe8, 0xeb, 0x01, 0x21, 0x8d, 0x07, 0x65, 0x70, 0x84, 0x35, 0x9e, 0x31, 0x23, 0x6f, 0xf5, - 0xcd, 0x76, 0xce, 0x5a, 0x60, 0x2b, 0xb4, 0xb6, 0xda, 0x20, 0x66, 0xa1, 0xfa, 0xb7, 0x37, 0x95, 0x00, 0x46, 0xd0, - 0xb0, 0xcf, 0x4b, 0xfa, 0x46, 0xd5, 0xa9, 0x7f, 0x9f, 0x7b, 0x73, 0x51, 0x64, 0x98, 0x93, 0x28, 0xc6, 0x57, 0xcc, - 0x29, 0xfa, 0x45, 0x29, 0x52, 0x03, 0xb7, 0x79, 0x99, 0x95, 0x58, 0x73, 0x46, 0x3d, 0xc2, 0x73, 0x4a, 0x32, 0x07, - 0x6c, 0xc5, 0xbf, 0x8d, 0x76, 0x2a, 0x94, 0x7c, 0x54, 0xff, 0x15, 0x7f, 0x90, 0xa0, 0x80, 0x91, 0xe1, 0x4e, 0x07, - 0x61, 0xd5, 0xb2, 0xee, 0x74, 0xdb, 0x83, 0x8f, 0x2b, 0xa2, 0xa5, 0xb3, 0xd5, 0x95, 0xd7, 0x63, 0xe7, 0x6f, 0x8f, - 0xbf, 0xfd, 0x67, 0x63, 0x11, 0x33, 0x8e, 0x37, 0xe0, 0xa7, 0x88, 0xdb, 0x50, 0x0a, 0x1a, 0xe1, 0xcb, 0xf0, 0x71, - 0x64, 0x98, 0x7f, 0x93, 0x79, 0x37, 0xed, 0xf5, 0x7d, 0xb1, 0xe7, 0xe9, 0x2c, 0xa8, 0xd6, 0xc6, 0x49, 0xce, 0x4a, - 0x5c, 0xae, 0xe4, 0xc8, 0x87, 0xaf, 0xc4, 0xad, 0xe3, 0x7b, 0xab, 0x12, 0xce, 0xf5, 0xf8, 0x46, 0x8e, 0x95, 0x61, - 0x50, 0xba, 0x45, 0xe7, 0x40, 0x2c, 0xc3, 0xd7, 0x12, 0x09, 0xd9, 0xe9, 0x07, 0x84, 0x61, 0xf4, 0x8b, 0x9f, 0x1f, - 0x4d, 0x98, 0x59, 0xed, 0x1f, 0x39, 0x18, 0x8e, 0x5d, 0x4c, 0x23, 0x30, 0x42, 0x2c, 0xa1, 0x90, 0xd2, 0x41, 0x1f, - 0xc1, 0x95, 0x54, 0xd9, 0x07, 0xdc, 0xce, 0x7c, 0x42, 0x65, 0x7f, 0x64, 0x67, 0x7d, 0xef, 0x44, 0x7c, 0x52, 0xb3, - 0xfb, 0xbd, 0x56, 0x55, 0x7b, 0x77, 0xbd, 0x16, 0x59, 0x62, 0x07, 0x4b, 0x60, 0x87, 0xc5, 0x8c, 0xc5, 0x96, 0x18, - 0x2e, 0x68, 0xcf, 0xea, 0x78, 0x0f, 0x4c, 0xc6, 0xf0, 0x63, 0x15, 0xb3, 0x4c, 0x0e, 0xd2, 0x6d, 0x95, 0xe9, 0xd9, - 0x1e, 0x95, 0x9b, 0x3f, 0x54, 0x96, 0xec, 0xe1, 0xff, 0x33, 0x3f, 0xce, 0x60, 0x8e, 0xe2, 0xeb, 0x45, 0x96, 0xe4, - 0x86, 0x7a, 0xcd, 0x7e, 0xfc, 0xab, 0xb1, 0xed, 0x31, 0x24, 0x82, 0xcd, 0xdd, 0x6a, 0x6b, 0x3f, 0x03, 0x14, 0xa7, - 0xac, 0x02, 0x29, 0x4a, 0xa6, 0x63, 0x8e, 0x6c, 0xd0, 0xa1, 0x38, 0x18, 0x04, 0x8f, 0xbb, 0x4f, 0xad, 0x5a, 0xe0, - 0xe9, 0x0a, 0x57, 0x20, 0x63, 0x37, 0x96, 0xb5, 0xd5, 0xcf, 0xda, 0x78, 0x3f, 0xa2, 0x27, 0x21, 0xb0, 0x64, 0xbd, - 0x0f, 0xf0, 0x51, 0xb0, 0x97, 0x0d, 0x00, 0xca, 0x5b, 0xbe, 0xb6, 0x6f, 0x9f, 0x9f, 0x53, 0xa7, 0xb9, 0x6c, 0x3f, - 0xb1, 0x77, 0xe2, 0x33, 0x67, 0xae, 0xaa, 0xb3, 0xdc, 0xd2, 0x7d, 0x0c, 0x81, 0x20, 0x46, 0xc3, 0x03, 0x42, 0x06, - 0x8c, 0x9e, 0xe2, 0x1d, 0x67, 0xc6, 0x3f, 0x9b, 0x27, 0x35, 0x4e, 0xf6, 0x1f, 0xde, 0x58, 0x78, 0x2d, 0x2d, 0x81, - 0xde, 0x45, 0xf8, 0xdf, 0xde, 0x95, 0x67, 0x1d, 0x13, 0x4d, 0x50, 0x75, 0x70, 0xb5, 0x53, 0x5f, 0xf5, 0x26, 0x37, - 0x6f, 0x15, 0x63, 0xcf, 0xfb, 0xd8, 0x16, 0x3e, 0x12, 0x0a, 0x4d, 0xe1, 0xa3, 0x2d, 0x9b, 0xaf, 0xca, 0x75, 0xe8, - 0x07, 0xb3, 0x6c, 0x74, 0x49, 0xd6, 0x10, 0x4e, 0xef, 0x13, 0x59, 0x6c, 0x3b, 0x99, 0x4d, 0xc4, 0xf5, 0x47, 0xc0, - 0x00, 0x1e, 0xeb, 0xa2, 0xf6, 0x54, 0xdd, 0x96, 0x7a, 0xd4, 0xa5, 0x9e, 0xfb, 0x9d, 0xe6, 0xed, 0xb9, 0xb8, 0xd9, - 0xa6, 0xf7, 0x05, 0x9f, 0x5a, 0x8b, 0x8e, 0x20, 0xdf, 0xd2, 0x8d, 0x72, 0x01, 0x80, 0x0c, 0xf0, 0xc2, 0xb8, 0x89, - 0x2e, 0xab, 0xfd, 0xb1, 0xf7, 0xa3, 0x35, 0xb6, 0xc7, 0x66, 0x53, 0x6e, 0x64, 0x87, 0xd9, 0xc5, 0x81, 0xb2, 0xe3, - 0xd8, 0xf8, 0x0e, 0x7b, 0x8d, 0x87, 0x17, 0x6a, 0x46, 0x0a, 0x6b, 0x89, 0xde, 0x9b, 0x3a, 0xa9, 0x67, 0x9f, 0x1b, - 0x9c, 0x15, 0xee, 0x8b, 0xb9, 0x14, 0xde, 0x27, 0x8e, 0x5a, 0x1d, 0x00, 0x98, 0x6e, 0x60, 0x82, 0x23, 0x3a, 0xfd, - 0x58, 0x12, 0xfc, 0x77, 0x1d, 0x74, 0x2b, 0x4e, 0xe0, 0xb6, 0x14, 0x77, 0xa3, 0x96, 0xcb, 0xf7, 0xb3, 0x83, 0x90, - 0x52, 0x5c, 0x75, 0x76, 0x20, 0xf2, 0x3a, 0x50, 0x11, 0x72, 0x0a, 0x09, 0x01, 0x87, 0x4b, 0xd9, 0xa5, 0x60, 0x92, - 0x04, 0xf4, 0x53, 0xe1, 0xbe, 0x50, 0xf6, 0x92, 0xdb, 0x8d, 0xda, 0xf2, 0x47, 0x32, 0x04, 0x54, 0xcd, 0xc5, 0xb4, - 0xb6, 0x45, 0x70, 0x3c, 0x75, 0xc4, 0x7c, 0x7a, 0xac, 0xbf, 0x39, 0x90, 0xf4, 0x34, 0xf0, 0xc8, 0xc0, 0xe2, 0x6d, - 0x89, 0xd1, 0xd5, 0x8e, 0x37, 0xac, 0xec, 0x1d, 0x17, 0x5b, 0xcc, 0x41, 0x3d, 0xb1, 0xc2, 0x80, 0xf7, 0x31, 0x32, - 0x35, 0xe9, 0xc1, 0x55, 0xec, 0x54, 0x58, 0x0e, 0xcb, 0xc9, 0x02, 0xc4, 0x51, 0xea, 0x97, 0x2f, 0x73, 0xde, 0xe8, - 0x6b, 0xd6, 0x12, 0xca, 0xb0, 0x94, 0x63, 0x75, 0xb9, 0x4c, 0x1e, 0x36, 0x86, 0xac, 0x38, 0x9f, 0xb6, 0x9d, 0xa5, - 0xa2, 0x09, 0x2b, 0x88, 0x76, 0x5c, 0x23, 0x84, 0x64, 0xbf, 0x90, 0x4e, 0xd6, 0xec, 0xf0, 0x0b, 0x96, 0xd5, 0x92, - 0xd2, 0xb9, 0x25, 0xd9, 0x93, 0x19, 0xf0, 0x73, 0x04, 0x19, 0x49, 0x4a, 0x4c, 0xec, 0xa4, 0x0b, 0xc1, 0x63, 0x0d, - 0xc3, 0xd3, 0xa2, 0xac, 0x97, 0xc9, 0xa2, 0xd5, 0x8d, 0x4e, 0x3d, 0x29, 0x1e, 0x18, 0x74, 0x90, 0x58, 0x52, 0x73, - 0x88, 0xc8, 0x3f, 0x99, 0xa8, 0x0b, 0x41, 0x84, 0x64, 0xd3, 0x91, 0x4c, 0x25, 0x25, 0xeb, 0x45, 0x88, 0x23, 0x1f, - 0x90, 0x2b, 0x79, 0x44, 0x96, 0xe4, 0xd5, 0x77, 0x90, 0xc9, 0x3b, 0xd1, 0x4a, 0x8a, 0xed, 0x6c, 0x08, 0x71, 0xcf, - 0xdc, 0x64, 0x0c, 0x41, 0x26, 0x3c, 0x4f, 0xc9, 0xd8, 0x1a, 0x19, 0xe9, 0x13, 0xf2, 0xe4, 0xc0, 0x42, 0xa9, 0xbd, - 0x4a, 0x0a, 0x2c, 0x4b, 0x90, 0x85, 0x76, 0xf2, 0xa7, 0x2c, 0xa9, 0xe5, 0x91, 0x03, 0xdb, 0xa7, 0xf5, 0x84, 0x82, - 0x4c, 0x11, 0x21, 0xc7, 0x3e, 0x37, 0x02, 0x18, 0xe5, 0x61, 0x05, 0x4a, 0xe7, 0x39, 0xe1, 0x45, 0x9e, 0x23, 0x4a, - 0xe4, 0xc5, 0xc0, 0x1a, 0x55, 0xbc, 0xab, 0x91, 0xfa, 0x2b, 0x08, 0xb9, 0x50, 0xe0, 0xe1, 0x5e, 0x74, 0x7a, 0x9e, - 0xdf, 0x14, 0xeb, 0x2f, 0x18, 0x6f, 0xca, 0xea, 0xa2, 0x95, 0x1b, 0x46, 0x8a, 0x66, 0xc4, 0xf9, 0x99, 0xbb, 0x78, - 0x82, 0x4f, 0x95, 0x8c, 0xa8, 0x1c, 0xc5, 0x8c, 0x0b, 0xdf, 0x87, 0xc9, 0xbf, 0x8b, 0x6e, 0x41, 0xd1, 0x7d, 0xdb, - 0xac, 0x8d, 0x44, 0x43, 0x5c, 0x95, 0x93, 0xcf, 0x7b, 0xa4, 0xa6, 0xc1, 0x50, 0x71, 0x8b, 0xe7, 0x99, 0x51, 0xef, - 0x21, 0x3e, 0x33, 0x0a, 0x6a, 0x93, 0x84, 0x2b, 0x39, 0xc1, 0xc6, 0x84, 0x97, 0x7c, 0xa9, 0x16, 0x19, 0xc5, 0xec, - 0xbe, 0x52, 0xf9, 0xe5, 0x42, 0xd1, 0x3c, 0x4d, 0x50, 0x50, 0x4a, 0x4b, 0xd5, 0x88, 0xbe, 0x1a, 0x78, 0x88, 0x9c, - 0x6e, 0x74, 0x7e, 0x1b, 0xb9, 0x70, 0x08, 0x64, 0x8b, 0x57, 0x5e, 0xf8, 0x4c, 0xc3, 0x52, 0xed, 0xd0, 0x3e, 0x83, - 0x25, 0x4e, 0x95, 0xd1, 0x11, 0xfe, 0x67, 0x22, 0x58, 0xb4, 0xb9, 0x11, 0x78, 0x4b, 0x59, 0x49, 0x1d, 0xa7, 0x7e, - 0x83, 0xf2, 0x9e, 0x8e, 0xf2, 0x5a, 0xf9, 0xca, 0x24, 0x99, 0x31, 0x57, 0xa3, 0x31, 0x28, 0xc8, 0xc7, 0x8b, 0xf9, - 0x26, 0x00, 0x93, 0xe8, 0x76, 0x62, 0x33, 0x68, 0x87, 0xc8, 0xaa, 0x3c, 0x14, 0x77, 0x9a, 0xaf, 0xa7, 0xf3, 0x46, - 0x9e, 0x43, 0xb8, 0x85, 0xda, 0x44, 0xa3, 0x6e, 0xa2, 0xab, 0x26, 0xa0, 0x4c, 0xf2, 0x73, 0xd8, 0x01, 0x5e, 0xca, - 0x9c, 0x00, 0xac, 0x47, 0x6a, 0x4c, 0x70, 0x3b, 0x10, 0x7f, 0xa9, 0x75, 0xf5, 0x9c, 0x72, 0xba, 0xad, 0x9a, 0x55, - 0x0b, 0x14, 0x7b, 0x00, 0x2a, 0xcf, 0x9f, 0xdf, 0x9e, 0x7a, 0x1b, 0xc1, 0x56, 0xec, 0x60, 0x54, 0x32, 0xe7, 0x2a, - 0xcb, 0x06, 0xa5, 0x76, 0xcb, 0xb9, 0x69, 0x20, 0xbe, 0x7b, 0x50, 0x5d, 0xbd, 0xe0, 0x8f, 0x3b, 0x6b, 0xe3, 0x1d, - 0x07, 0xa8, 0x3d, 0xf2, 0x93, 0x17, 0x9a, 0xf4, 0x01, 0xc1, 0x1b, 0x4e, 0xd7, 0x09, 0xab, 0x09, 0x63, 0x24, 0x62, - 0x86, 0x02, 0x32, 0xa5, 0xfe, 0xb9, 0x0b, 0x34, 0xe7, 0x5f, 0xbc, 0xef, 0x40, 0xc1, 0xa1, 0x68, 0xe0, 0x3a, 0xaf, - 0x1e, 0x5e, 0xfa, 0x94, 0x1d, 0xc5, 0x18, 0xf7, 0x2d, 0xd7, 0x5b, 0xac, 0xb9, 0xd6, 0x8a, 0xf3, 0xbb, 0x74, 0x3f, - 0xb4, 0x9b, 0xe2, 0xf9, 0x06, 0xdd, 0x27, 0xb7, 0x8f, 0x73, 0xe0, 0x4f, 0x54, 0xc9, 0xa4, 0x58, 0x57, 0x38, 0xf2, - 0xa8, 0x02, 0x4d, 0xbd, 0xb7, 0x6d, 0xe3, 0x0d, 0xc6, 0x1b, 0x10, 0xfd, 0x3d, 0xa8, 0xe2, 0xa6, 0x33, 0xdc, 0xb7, - 0xba, 0xe5, 0xa4, 0x09, 0x14, 0x5a, 0x45, 0x10, 0x57, 0x5c, 0xe0, 0xe7, 0xbd, 0x00, 0x39, 0xc0, 0x1e, 0x20, 0x0d, - 0xf0, 0x68, 0x45, 0x0f, 0x21, 0x63, 0x4c, 0x6c, 0x4b, 0x2d, 0x39, 0x8b, 0x1d, 0x7b, 0x38, 0x69, 0xf2, 0x26, 0x59, - 0x1b, 0xb7, 0xf4, 0xb0, 0x10, 0x6d, 0x7d, 0xc5, 0xb3, 0x7e, 0x13, 0x72, 0x12, 0x20, 0x56, 0x5b, 0x7c, 0x4a, 0xa6, - 0x1c, 0xb7, 0xfb, 0x2b, 0x89, 0x1f, 0x7d, 0x9c, 0xd8, 0x71, 0x08, 0xa4, 0xf6, 0xa9, 0x29, 0x5c, 0x6f, 0x77, 0xd1, - 0x77, 0xaf, 0x1f, 0x7f, 0x4b, 0x57, 0xd1, 0xf5, 0xa7, 0x69, 0x77, 0xdd, 0xe9, 0xed, 0x7b, 0x2d, 0xc9, 0xb2, 0xcc, - 0x7a, 0xd7, 0x9f, 0x26, 0x77, 0x8c, 0x1b, 0xaf, 0x28, 0x07, 0x1a, 0x58, 0xef, 0xdf, 0xa0, 0xb4, 0x3b, 0xb4, 0xd0, - 0x37, 0xab, 0x0f, 0xa3, 0x02, 0x9b, 0xaa, 0xc1, 0x66, 0x87, 0x93, 0x9c, 0xcc, 0x89, 0x62, 0xe8, 0x0f, 0xa2, 0x13, - 0xb0, 0x0e, 0x5f, 0xb2, 0xa5, 0xf9, 0x03, 0x1c, 0xe0, 0xfa, 0xc2, 0x07, 0x4c, 0x68, 0xa2, 0xcd, 0x06, 0x5b, 0xeb, - 0x7f, 0xf7, 0xa9, 0x77, 0x8e, 0xd1, 0x8f, 0x6b, 0xfb, 0xcd, 0x3f, 0x1d, 0x6f, 0x71, 0x8e, 0x77, 0x45, 0xd2, 0x0e, - 0xe4, 0xc8, 0x19, 0x92, 0xdc, 0xee, 0xe2, 0xb0, 0x9f, 0xd9, 0xe5, 0x69, 0xee, 0xbe, 0xfb, 0xa9, 0x98, 0x60, 0x72, - 0x27, 0x67, 0xa9, 0x02, 0xf1, 0xef, 0x06, 0x01, 0x70, 0xb7, 0xec, 0xd7, 0x51, 0xd3, 0xd6, 0x4b, 0xee, 0x3c, 0xab, - 0x5a, 0x8d, 0xf5, 0x76, 0xeb, 0x00, 0xff, 0x5d, 0xf8, 0x00, 0x69, 0xac, 0xe7, 0xbe, 0xc7, 0xba, 0x66, 0x64, 0x0d, - 0x82, 0xdd, 0xe6, 0x61, 0x54, 0x95, 0x70, 0x88, 0x41, 0x3c, 0x91, 0x07, 0x7f, 0x01, 0xa2, 0xdf, 0xed, 0xcd, 0xfe, - 0xd3, 0xe1, 0x00, 0xe8, 0xe0, 0x8f, 0x37, 0x59, 0x73, 0x88, 0x3d, 0x81, 0x75, 0x07, 0x8c, 0x73, 0xa3, 0x49, 0x74, - 0x02, 0x5c, 0xf2, 0xae, 0x3c, 0x59, 0x74, 0xf9, 0xdc, 0xc7, 0x40, 0xe8, 0x7a, 0x8f, 0x84, 0x25, 0xd0, 0x58, 0x60, - 0x0d, 0x6c, 0xfc, 0xa0, 0x58, 0xfe, 0xb5, 0xb7, 0x54, 0x3d, 0x5d, 0xb7, 0x86, 0x79, 0xad, 0xe3, 0xf2, 0x8d, 0x38, - 0xda, 0x29, 0xc4, 0xb3, 0x5e, 0xca, 0x6b, 0xa2, 0x37, 0x0d, 0x7e, 0x6e, 0x1a, 0x7b, 0xa0, 0xe0, 0x23, 0xbe, 0xb8, - 0x30, 0x6f, 0x58, 0xef, 0xf6, 0xb3, 0x03, 0x98, 0x35, 0xe2, 0x30, 0x60, 0xa7, 0x05, 0xbf, 0xe9, 0x61, 0x3c, 0x27, - 0x66, 0x2b, 0x28, 0x08, 0x31, 0x57, 0x4f, 0x5e, 0x73, 0xcd, 0x6b, 0xb3, 0x22, 0x6b, 0x89, 0xcf, 0xb8, 0x76, 0x01, - 0xa0, 0x25, 0x1a, 0x65, 0xee, 0x5b, 0x90, 0x3a, 0xe5, 0xf5, 0xb2, 0x9c, 0x09, 0x8e, 0x05, 0xad, 0x9d, 0x80, 0xa7, - 0xc3, 0xb9, 0x98, 0x37, 0x29, 0x1c, 0x7d, 0xc5, 0xa2, 0xdb, 0x57, 0x21, 0x95, 0x58, 0x28, 0x0b, 0x1f, 0x3e, 0x8b, - 0x29, 0xd9, 0xec, 0x0d, 0x10, 0x58, 0x0c, 0xde, 0x77, 0x41, 0x7b, 0xdd, 0x30, 0x64, 0xe9, 0xe0, 0x60, 0x25, 0xee, - 0xf2, 0x6e, 0x44, 0x94, 0x3f, 0x7e, 0xfc, 0xcf, 0x4a, 0x76, 0x23, 0x97, 0x61, 0x78, 0x91, 0xd8, 0x3d, 0xcb, 0x36, - 0xdf, 0xa6, 0x31, 0x6a, 0xc8, 0x69, 0xf9, 0x87, 0x3a, 0x6e, 0x69, 0x46, 0x8a, 0x33, 0x1f, 0x40, 0xbe, 0x2d, 0xbb, - 0x08, 0x01, 0x06, 0xf3, 0x96, 0x44, 0x6c, 0xd3, 0xaf, 0x47, 0x88, 0x35, 0xfb, 0x7c, 0x03, 0xc9, 0x9d, 0xd6, 0x14, - 0xda, 0x12, 0x45, 0xce, 0x05, 0x15, 0x5d, 0x32, 0xce, 0xd7, 0x15, 0x36, 0xba, 0xc7, 0x31, 0x52, 0x29, 0x63, 0xdc, - 0xe4, 0x89, 0xa6, 0xfc, 0xc6, 0x42, 0x35, 0xf8, 0xcb, 0xec, 0x89, 0xb1, 0x3c, 0x1f, 0x0f, 0x89, 0x3e, 0x12, 0xfe, - 0x3a, 0x4e, 0xcc, 0xa0, 0xee, 0xee, 0xaf, 0x74, 0x09, 0xb3, 0x65, 0xea, 0xb5, 0xc1, 0x48, 0x54, 0x6e, 0x64, 0xef, - 0x2f, 0xe2, 0x10, 0x2b, 0xf3, 0x9c, 0x2f, 0x08, 0x0f, 0xbc, 0xd7, 0x28, 0x5e, 0x90, 0x3a, 0xff, 0x91, 0xcc, 0xf1, - 0x50, 0xa2, 0xe0, 0x35, 0xcc, 0x73, 0xef, 0x1d, 0x21, 0x40, 0xdb, 0x56, 0xc0, 0xc9, 0x3c, 0x49, 0x0e, 0xed, 0x2f, - 0x01, 0x75, 0xa5, 0x1b, 0xe4, 0x41, 0xb8, 0xd8, 0x5a, 0x93, 0x10, 0xdf, 0xff, 0xc4, 0xad, 0x44, 0x42, 0x74, 0x36, - 0xec, 0x68, 0x0a, 0x80, 0x3d, 0xe4, 0x0c, 0x26, 0xac, 0x69, 0x7f, 0x3a, 0x4e, 0x98, 0x55, 0x39, 0xeb, 0x5d, 0xa8, - 0xaa, 0x58, 0x39, 0x55, 0x03, 0x25, 0x01, 0x8d, 0x66, 0xda, 0x46, 0x8e, 0x44, 0x43, 0x94, 0x17, 0x0d, 0x70, 0x74, - 0x60, 0xdb, 0x04, 0x99, 0xd4, 0xe1, 0xdb, 0x0c, 0x8a, 0x24, 0xb0, 0xff, 0x6b, 0x28, 0x84, 0xe2, 0xb6, 0xec, 0x17, - 0xb1, 0xf0, 0xda, 0x34, 0xd8, 0xd7, 0x4e, 0xf6, 0x9c, 0x73, 0x8e, 0x76, 0x41, 0x34, 0x93, 0xb0, 0x7d, 0xbc, 0x88, - 0xf9, 0xa8, 0x61, 0x9a, 0xab, 0x3c, 0x55, 0x63, 0xbf, 0x09, 0x5d, 0x76, 0x07, 0xbd, 0x26, 0x47, 0x69, 0xc9, 0xa8, - 0xfd, 0x08, 0x6c, 0xd8, 0xc1, 0xf8, 0x2b, 0x5a, 0x17, 0x39, 0x3d, 0xad, 0x36, 0xfa, 0x66, 0x11, 0x09, 0xa0, 0x09, - 0xc1, 0xea, 0xd3, 0x04, 0xde, 0xc3, 0x25, 0x7a, 0x79, 0xcf, 0xd8, 0x06, 0x52, 0x79, 0x6f, 0x82, 0xa3, 0x31, 0x50, - 0x9f, 0xe4, 0x1c, 0x68, 0x11, 0x53, 0x2d, 0x66, 0x77, 0xa9, 0x45, 0x0a, 0x77, 0xa9, 0xeb, 0xb0, 0x02, 0x6a, 0x71, - 0xfc, 0x33, 0x02, 0xf7, 0x0c, 0x82, 0x31, 0x90, 0x68, 0x56, 0x33, 0x41, 0x72, 0xfb, 0xfe, 0x80, 0x11, 0x58, 0x49, - 0xcf, 0xda, 0x53, 0xf3, 0x52, 0x24, 0xe4, 0x23, 0x98, 0x86, 0xdf, 0x33, 0x83, 0x14, 0x92, 0xbe, 0xb0, 0x0d, 0x90, - 0x24, 0x00, 0x5d, 0x56, 0x82, 0xc6, 0x99, 0x09, 0x4e, 0xe4, 0x62, 0x4d, 0xc7, 0x3d, 0x37, 0x76, 0x2c, 0x64, 0xeb, - 0xe9, 0x62, 0xa6, 0x17, 0x98, 0x25, 0xf9, 0x0b, 0x7f, 0x23, 0x33, 0x8e, 0x9a, 0xff, 0x75, 0x0d, 0xf1, 0xf0, 0xcb, - 0x24, 0x4e, 0x99, 0xf2, 0x8e, 0xb4, 0x38, 0x2e, 0x67, 0x31, 0x35, 0x88, 0xdf, 0x0b, 0x94, 0x13, 0xb8, 0x78, 0x23, - 0x52, 0x1f, 0x83, 0xdb, 0x75, 0x34, 0x00, 0xa0, 0x34, 0xd6, 0x67, 0xde, 0xbf, 0x94, 0xc7, 0x78, 0x3b, 0x36, 0xcf, - 0x0c, 0x89, 0x08, 0x2a, 0x2d, 0xee, 0xe0, 0x9a, 0x76, 0x1d, 0xfc, 0x8b, 0x72, 0x9a, 0x2b, 0x77, 0x5e, 0x50, 0xce, - 0x7c, 0x8f, 0x94, 0x20, 0xb3, 0x97, 0xed, 0x5e, 0xb6, 0x02, 0x1d, 0x84, 0xd6, 0x16, 0x56, 0x1e, 0xd3, 0x16, 0x7f, - 0x3e, 0x8d, 0xd5, 0x26, 0xf0, 0x9b, 0x21, 0x55, 0x5d, 0x3d, 0x37, 0x68, 0xd4, 0x3f, 0x22, 0x8b, 0xde, 0x26, 0x84, - 0xdd, 0x1a, 0x9f, 0xcf, 0x0a, 0x40, 0x0b, 0xc4, 0x5e, 0xfd, 0x6f, 0x09, 0x16, 0xfa, 0x1a, 0x3f, 0x8f, 0x75, 0x75, - 0x71, 0xf9, 0x24, 0x19, 0x59, 0xf1, 0x43, 0x2f, 0x93, 0x6a, 0x59, 0x58, 0x2a, 0xa6, 0x01, 0xc8, 0x86, 0xdf, 0xef, - 0xaa, 0x67, 0xd9, 0x4f, 0xa7, 0x36, 0x5f, 0xf4, 0x74, 0x15, 0x3f, 0x07, 0x19, 0x96, 0x3c, 0x65, 0xf0, 0xdf, 0xe2, - 0xd6, 0xe0, 0x14, 0xfd, 0xdb, 0xe0, 0x87, 0x89, 0xed, 0xb3, 0x12, 0x24, 0x54, 0x84, 0xe7, 0x36, 0xea, 0xbb, 0x04, - 0xa4, 0x88, 0xee, 0x50, 0xe6, 0x55, 0x8d, 0x1d, 0x25, 0x1b, 0x6a, 0xfb, 0x19, 0x12, 0x6a, 0xe2, 0xa8, 0x86, 0x5f, - 0xdc, 0x38, 0xfc, 0x42, 0xc8, 0x21, 0xce, 0xd1, 0x93, 0x43, 0xc7, 0x26, 0xf3, 0x9b, 0xe1, 0xb2, 0x79, 0x1c, 0x2e, - 0xb7, 0xb0, 0xef, 0x23, 0x93, 0x9e, 0x2b, 0x1a, 0xcf, 0xf1, 0xec, 0xd1, 0xa2, 0x58, 0xce, 0xea, 0xde, 0x4a, 0x20, - 0x46, 0x36, 0x51, 0x5f, 0xcb, 0x0b, 0x5e, 0x9e, 0xcd, 0xac, 0x7e, 0x49, 0xe2, 0xdd, 0xd1, 0x5f, 0xdf, 0x0e, 0xd7, - 0x81, 0x1f, 0x69, 0xb8, 0x61, 0x5b, 0xc6, 0x93, 0x2d, 0xcc, 0x0e, 0x23, 0xd7, 0xc5, 0xea, 0x32, 0xcb, 0x90, 0xb7, - 0x50, 0xfc, 0xec, 0x0f, 0xa3, 0x5c, 0x32, 0x35, 0x06, 0x3f, 0xba, 0xdc, 0x8f, 0x69, 0x38, 0x95, 0x18, 0xa2, 0x95, - 0x9c, 0x74, 0x8f, 0xb5, 0x1d, 0x2b, 0x20, 0xcb, 0xde, 0x3f, 0x1a, 0x9d, 0xbb, 0x98, 0x97, 0x12, 0x75, 0x1c, 0x34, - 0xcf, 0x53, 0x1e, 0x94, 0xdb, 0x85, 0xb6, 0xd9, 0x3b, 0xe2, 0xd3, 0xd6, 0xc6, 0x05, 0xd0, 0x6e, 0x0d, 0x5d, 0x68, - 0x5d, 0xb0, 0x80, 0x84, 0xbe, 0x4b, 0xed, 0x16, 0x58, 0x49, 0xd6, 0x32, 0x86, 0x2e, 0x39, 0xbb, 0x4e, 0x5c, 0x43, - 0x95, 0xc3, 0x86, 0x4b, 0x96, 0x93, 0x2c, 0x11, 0x93, 0xed, 0xff, 0xcb, 0x1b, 0x94, 0x30, 0xd2, 0xcb, 0x12, 0x3a, - 0xde, 0x14, 0xbe, 0xb0, 0xc8, 0x02, 0x1e, 0xb7, 0xc8, 0xe8, 0x79, 0xf9, 0x90, 0x44, 0xc1, 0xa1, 0xb8, 0xe0, 0x7e, - 0xf8, 0xf2, 0x5d, 0x1d, 0xf7, 0xd6, 0xec, 0x63, 0xca, 0x91, 0xbf, 0xaa, 0x0a, 0x44, 0x5b, 0x97, 0x45, 0x4c, 0xfe, - 0x4f, 0x24, 0x67, 0x45, 0xd6, 0xa2, 0xa3, 0x03, 0x68, 0x6e, 0xe7, 0x4c, 0xb6, 0x84, 0xa5, 0x90, 0xcc, 0x43, 0x97, - 0x66, 0x0e, 0x16, 0x80, 0xae, 0x68, 0x81, 0x5d, 0x3c, 0x66, 0xcc, 0xbd, 0xcb, 0x92, 0xd3, 0xda, 0x65, 0x1e, 0x2d, - 0xa0, 0xb9, 0x70, 0x4b, 0xa2, 0x09, 0x44, 0x37, 0x52, 0x82, 0x35, 0xb6, 0x9d, 0xdb, 0x73, 0xff, 0x3e, 0x8e, 0xa8, - 0x2f, 0x0f, 0x38, 0x27, 0xc4, 0xe1, 0xdb, 0x51, 0x6e, 0x9a, 0x7e, 0xe0, 0x65, 0xab, 0x33, 0x07, 0x13, 0x17, 0xf3, - 0xeb, 0x01, 0x3c, 0x49, 0xbb, 0xce, 0xa6, 0xe8, 0xf6, 0x69, 0xed, 0xf1, 0x97, 0x84, 0x2e, 0x29, 0x96, 0x35, 0x64, - 0x32, 0x7d, 0x24, 0x61, 0xce, 0xf7, 0x3a, 0xef, 0xc3, 0x40, 0x73, 0x13, 0x70, 0x37, 0x29, 0x14, 0xbd, 0xb9, 0xcf, - 0x27, 0x1c, 0x07, 0x64, 0xb5, 0x37, 0x8a, 0xe9, 0xd1, 0x03, 0xdd, 0xe4, 0x02, 0x87, 0xe7, 0x23, 0x08, 0x91, 0x30, - 0x2b, 0xb8, 0xd5, 0xb5, 0xea, 0x1a, 0xe8, 0xa7, 0xf0, 0x63, 0x9d, 0x09, 0x0c, 0x4b, 0xf6, 0x72, 0x74, 0xae, 0xcb, - 0x50, 0x72, 0x47, 0x5c, 0xe6, 0x50, 0xf0, 0xee, 0x29, 0xf2, 0xe4, 0xfc, 0xf1, 0xdf, 0x33, 0x01, 0x43, 0xcd, 0x22, - 0x27, 0x7f, 0xcf, 0xb4, 0xf3, 0x53, 0xc0, 0x89, 0xa9, 0x30, 0xb5, 0xd8, 0xaa, 0xbc, 0x01, 0x9a, 0x53, 0x12, 0x14, - 0x1c, 0x56, 0xd1, 0xf9, 0x1d, 0x85, 0xc5, 0x25, 0xfe, 0xb0, 0x90, 0x19, 0x34, 0xb2, 0xe9, 0x75, 0x50, 0xa9, 0x74, - 0xfb, 0x04, 0xb1, 0x87, 0xaa, 0x7d, 0x6f, 0xcf, 0xd6, 0x84, 0x99, 0x1d, 0x8a, 0x02, 0xea, 0x46, 0xf1, 0xa6, 0x1f, - 0x5a, 0x6f, 0x81, 0x97, 0x05, 0xb0, 0x92, 0x4c, 0x3f, 0x1b, 0x20, 0x25, 0xe1, 0xc7, 0xca, 0x19, 0xdc, 0x70, 0x58, - 0xb9, 0x80, 0x5b, 0xbe, 0x5c, 0x3e, 0x20, 0xbb, 0xa6, 0x3b, 0x22, 0x02, 0x5d, 0x3f, 0x59, 0xb2, 0x6b, 0xc5, 0x94, - 0xc1, 0xe8, 0x46, 0x71, 0x17, 0xfa, 0x34, 0xca, 0x2e, 0x57, 0x56, 0xa0, 0xc6, 0x58, 0x9f, 0xa2, 0x26, 0xbf, 0x1f, - 0x2f, 0x9b, 0xca, 0xf5, 0x0f, 0x2e, 0x27, 0x72, 0x92, 0x8c, 0x32, 0x74, 0x67, 0xd2, 0xe7, 0x6c, 0x8e, 0x9a, 0x05, - 0xfc, 0x9f, 0x56, 0xab, 0x9e, 0x7b, 0xb8, 0x7d, 0x98, 0xf4, 0x42, 0x04, 0x03, 0xbd, 0xc2, 0xb2, 0xe9, 0x76, 0x23, - 0xdb, 0x56, 0xf8, 0xb6, 0x48, 0x81, 0xf8, 0x04, 0x68, 0x7e, 0x8d, 0x44, 0x80, 0x33, 0xf3, 0xcb, 0xbe, 0x04, 0x50, - 0x63, 0xe5, 0xe2, 0xf8, 0x83, 0x0a, 0x82, 0xe7, 0xb3, 0x9e, 0x7b, 0x01, 0x8b, 0x0b, 0x84, 0xcc, 0xbd, 0x27, 0x0a, - 0x6c, 0x6b, 0xe2, 0x4c, 0xfc, 0x66, 0x90, 0xeb, 0xf8, 0x6b, 0x35, 0xbd, 0xb5, 0x61, 0xa1, 0xb3, 0x92, 0xc2, 0xf2, - 0xa0, 0x47, 0xbb, 0x87, 0x88, 0x91, 0xae, 0xcf, 0x37, 0xe9, 0x37, 0x44, 0x23, 0xfa, 0x2d, 0x2a, 0x9e, 0x7e, 0x30, - 0x20, 0x90, 0x2c, 0x0b, 0xb7, 0xb7, 0xe9, 0x51, 0x51, 0x10, 0xd4, 0x7b, 0x18, 0xfc, 0x57, 0x23, 0xea, 0x4d, 0x1f, - 0x42, 0x80, 0xbf, 0x6a, 0x83, 0x7e, 0xea, 0x9f, 0x2c, 0x72, 0xd7, 0x0c, 0xd8, 0xb5, 0x87, 0xb0, 0xec, 0x0c, 0x1f, - 0x98, 0x41, 0x93, 0x62, 0xb2, 0x87, 0x70, 0x69, 0x4e, 0x13, 0x30, 0xa8, 0x77, 0x13, 0xcb, 0x9f, 0xb8, 0xa7, 0x9c, - 0x88, 0x3e, 0xe4, 0x77, 0x53, 0x8a, 0x00, 0xa7, 0xf9, 0xd2, 0x1c, 0xc1, 0x15, 0x81, 0x53, 0x5c, 0x60, 0xb6, 0x30, - 0x7f, 0xf2, 0xf5, 0x4d, 0x29, 0x60, 0x84, 0xcf, 0x17, 0x28, 0x03, 0x72, 0x46, 0x64, 0xe6, 0x90, 0xd1, 0xac, 0xea, - 0x08, 0xa1, 0x03, 0x72, 0x50, 0xa8, 0xdf, 0x8b, 0x59, 0x30, 0x62, 0xd8, 0x2f, 0x75, 0x22, 0xc9, 0x87, 0xc0, 0x88, - 0xd8, 0x42, 0xf3, 0xd6, 0xe4, 0x0e, 0x12, 0x44, 0x0f, 0x72, 0xa6, 0x51, 0x41, 0x79, 0x57, 0xc9, 0xcb, 0x29, 0x52, - 0x13, 0x0f, 0x7b, 0x13, 0x94, 0x53, 0x2d, 0x6f, 0x56, 0xd0, 0x7b, 0x70, 0xca, 0xe7, 0xfd, 0x93, 0xbc, 0x33, 0x60, - 0x81, 0x38, 0xaa, 0xec, 0x38, 0xb1, 0x5a, 0xe5, 0x6a, 0x1b, 0x47, 0x4e, 0x55, 0xc1, 0x95, 0x68, 0xa5, 0xbd, 0x9b, - 0xe7, 0x3f, 0x95, 0x17, 0x9b, 0x22, 0x6b, 0x62, 0xf2, 0x83, 0xe0, 0xc2, 0x23, 0xaf, 0xe0, 0xa3, 0x51, 0x87, 0xc3, - 0xaf, 0x95, 0x16, 0x82, 0x58, 0x20, 0x0c, 0x97, 0x6f, 0x7b, 0x85, 0xfd, 0x0a, 0x57, 0xe4, 0xb8, 0x84, 0xd6, 0x85, - 0xae, 0x1e, 0x7f, 0x49, 0x16, 0x13, 0xe4, 0xc8, 0x9c, 0xfd, 0xca, 0x8d, 0x18, 0xc1, 0x2c, 0x78, 0x49, 0x8f, 0x76, - 0x3c, 0xa6, 0x15, 0x41, 0x82, 0x10, 0x8a, 0xcc, 0xf3, 0x63, 0xe8, 0x26, 0xb1, 0x99, 0x50, 0xa4, 0x4d, 0x16, 0x83, - 0x06, 0x9c, 0x71, 0xb5, 0x21, 0x8a, 0x35, 0xc7, 0xa7, 0x7c, 0xdf, 0x43, 0x5c, 0x44, 0xde, 0xf5, 0xe8, 0x66, 0x38, - 0x80, 0x36, 0xdc, 0xac, 0x54, 0xf4, 0xa7, 0x88, 0x74, 0xf5, 0xd7, 0xca, 0xfb, 0xd0, 0x77, 0x88, 0x93, 0x79, 0x5c, - 0x2d, 0xbf, 0x82, 0x43, 0xa9, 0xe4, 0x13, 0xb8, 0xc2, 0x4f, 0x71, 0x08, 0x0b, 0x51, 0x91, 0x5e, 0x59, 0x88, 0x50, - 0xde, 0x0a, 0xf2, 0x56, 0x91, 0x4f, 0x4a, 0x1f, 0x34, 0xb1, 0x7d, 0xcb, 0x6e, 0xb6, 0xaf, 0x4a, 0xb8, 0x7d, 0x9f, - 0x9e, 0x8c, 0x05, 0xe7, 0x80, 0x46, 0x8f, 0x61, 0xd1, 0x64, 0xd0, 0x62, 0xac, 0xd2, 0xc0, 0x5d, 0x91, 0xc5, 0xa7, - 0xfe, 0xc0, 0x92, 0xf4, 0xc5, 0x67, 0x1a, 0x68, 0x1e, 0xa9, 0xff, 0x26, 0x14, 0xc6, 0xb1, 0xfc, 0xa3, 0x2f, 0x9f, - 0x89, 0x44, 0xd5, 0xd5, 0x1d, 0xc5, 0x1a, 0xc5, 0x3c, 0x1b, 0x98, 0x75, 0xba, 0xa3, 0x81, 0x55, 0x47, 0xf1, 0x4a, - 0xcd, 0x6d, 0x4c, 0x39, 0x14, 0x50, 0x57, 0xbd, 0xdd, 0x40, 0x54, 0xfa, 0x6a, 0x35, 0x5f, 0x11, 0x4e, 0x0b, 0x67, - 0x64, 0x12, 0xe7, 0xd6, 0xa8, 0x42, 0x1b, 0x9c, 0x59, 0xbd, 0xa7, 0xfd, 0x7a, 0xa5, 0x3a, 0xd6, 0xfa, 0x3b, 0xec, - 0x17, 0x37, 0x0e, 0xc8, 0xcf, 0x0f, 0x04, 0xce, 0x30, 0x80, 0x62, 0x0b, 0x8c, 0x43, 0xa1, 0x9c, 0x4d, 0x1c, 0x79, - 0x79, 0x89, 0x72, 0x82, 0xe2, 0x4e, 0x9f, 0x06, 0x07, 0x25, 0x70, 0x82, 0x95, 0x86, 0x8c, 0x85, 0xb0, 0x1c, 0x68, - 0xb9, 0x0b, 0xc5, 0x5d, 0x59, 0xa2, 0xad, 0x25, 0x36, 0x9d, 0x5b, 0x3c, 0x35, 0x50, 0x67, 0xba, 0x05, 0x81, 0x55, - 0x94, 0x88, 0xad, 0x55, 0xe4, 0xd2, 0x6f, 0x7d, 0x69, 0x30, 0x8c, 0xa3, 0x7b, 0x5f, 0xeb, 0x69, 0x37, 0x95, 0x38, - 0xf6, 0xe0, 0x2d, 0xf3, 0xfc, 0x9c, 0xe8, 0xc5, 0x54, 0x23, 0x3b, 0x13, 0x6f, 0x11, 0x0b, 0x46, 0x83, 0x92, 0xb6, - 0xad, 0x5a, 0xda, 0xc2, 0xd6, 0x01, 0xf4, 0x6f, 0x41, 0x1d, 0xff, 0x6f, 0xb8, 0x41, 0xd9, 0x41, 0xe8, 0x14, 0xaa, - 0xd5, 0xfa, 0x3c, 0xcb, 0xc6, 0xc6, 0x7a, 0xc7, 0x1c, 0x09, 0x44, 0x04, 0x2f, 0x61, 0x94, 0xc2, 0xcc, 0x1c, 0x2f, - 0xb1, 0xa5, 0x4a, 0x6d, 0xa7, 0x63, 0xf3, 0xe1, 0x6c, 0xac, 0x3a, 0x90, 0x43, 0x4d, 0x74, 0xde, 0xb4, 0x11, 0x0d, - 0x55, 0x4a, 0x94, 0x17, 0xc9, 0xac, 0x46, 0x5a, 0xf3, 0xe1, 0x25, 0xb0, 0x45, 0xc4, 0xec, 0xc0, 0xa6, 0x20, 0x06, - 0x2b, 0x66, 0xc8, 0xa9, 0x1a, 0x27, 0xbd, 0x45, 0x2f, 0x97, 0x59, 0x63, 0xeb, 0xd1, 0xa6, 0xe3, 0x98, 0x9f, 0x6e, - 0x3d, 0x16, 0x0f, 0x84, 0xb7, 0xe7, 0x7f, 0x2a, 0x94, 0xb2, 0x1f, 0xc7, 0xce, 0xda, 0xef, 0xcd, 0x71, 0x21, 0x16, - 0xcd, 0xf3, 0x83, 0xc8, 0x0d, 0xbf, 0x54, 0x08, 0x5f, 0x04, 0xc0, 0x8b, 0x6d, 0xf0, 0xaa, 0x21, 0xa8, 0x7d, 0x7f, - 0x45, 0x41, 0x8e, 0x3b, 0xf5, 0xde, 0x83, 0xd0, 0xb2, 0x2e, 0xf6, 0xf2, 0x8c, 0xd5, 0x25, 0x1d, 0x5a, 0x63, 0x88, - 0x44, 0x4f, 0x44, 0xb1, 0xf6, 0x1f, 0x37, 0xaf, 0xb2, 0xa0, 0x3e, 0x12, 0x2e, 0x71, 0xd1, 0x43, 0xf1, 0xf1, 0x57, - 0x49, 0x33, 0x37, 0x6d, 0x54, 0xa6, 0x67, 0xae, 0x9c, 0xfc, 0x0b, 0x1c, 0x5b, 0x56, 0x57, 0x28, 0x0f, 0xd7, 0x0d, - 0x4c, 0xf8, 0x7b, 0x73, 0xe3, 0xd7, 0xb8, 0xb2, 0xc6, 0xa5, 0x8b, 0xf1, 0x4e, 0xe9, 0x62, 0xc5, 0xdb, 0xc6, 0x15, - 0x4b, 0x45, 0xc6, 0x1c, 0x34, 0xb5, 0xfa, 0x67, 0x06, 0xb9, 0xfd, 0x59, 0x98, 0xfe, 0x2d, 0x85, 0x0e, 0x12, 0x0f, - 0xb3, 0xbb, 0x10, 0x1f, 0xaf, 0x0b, 0xb9, 0x9a, 0xe0, 0x92, 0x84, 0xa4, 0x24, 0x3f, 0x86, 0x6d, 0xdf, 0x71, 0xf2, - 0x9c, 0x29, 0x1c, 0x8d, 0xb8, 0x5d, 0x26, 0xf9, 0x95, 0xf0, 0x3f, 0x95, 0x8d, 0xeb, 0x4e, 0x9b, 0x35, 0x07, 0x0a, - 0xf0, 0x79, 0x97, 0x85, 0x09, 0xd1, 0xd1, 0xda, 0x46, 0xed, 0x45, 0xb8, 0xf1, 0x2b, 0x45, 0x82, 0xfe, 0x25, 0xa3, - 0x50, 0xd8, 0xbc, 0x47, 0x2e, 0xb0, 0x4d, 0xc1, 0xd3, 0x6f, 0xc1, 0xb5, 0x4a, 0x19, 0x30, 0xf1, 0x2b, 0xd8, 0x26, - 0x9f, 0x98, 0xb9, 0x9b, 0xf4, 0x82, 0xa8, 0x2f, 0xab, 0x68, 0x82, 0xeb, 0xca, 0x85, 0xd5, 0x95, 0xf1, 0x3d, 0x75, - 0x7d, 0x04, 0xb9, 0x78, 0x7c, 0x9a, 0xe7, 0x77, 0xa9, 0x69, 0x03, 0xf6, 0x5e, 0x8c, 0x63, 0xfc, 0x75, 0xc5, 0x3c, - 0xb3, 0x7a, 0x52, 0x55, 0xa6, 0x80, 0xf7, 0xf4, 0xe3, 0x2b, 0xee, 0xf1, 0x9b, 0x87, 0x6d, 0xb0, 0xf4, 0x3f, 0xfa, - 0x99, 0x27, 0xa0, 0x2c, 0xd1, 0x8e, 0x2b, 0x8d, 0xdd, 0x32, 0xc6, 0x96, 0x0a, 0xc2, 0x05, 0x2c, 0x48, 0x45, 0x8d, - 0x5d, 0x1e, 0x6a, 0xd9, 0x7c, 0xdb, 0x1c, 0x9a, 0x90, 0x66, 0xfd, 0x71, 0xd6, 0x73, 0x33, 0x30, 0xaa, 0x68, 0xc3, - 0x03, 0x66, 0x85, 0x36, 0x24, 0xe0, 0x60, 0xa1, 0xc1, 0xa4, 0x08, 0x02, 0xe9, 0x6e, 0xd0, 0xe3, 0x82, 0x3e, 0x51, - 0x08, 0x6c, 0xbc, 0x8b, 0x16, 0x24, 0xd0, 0xfe, 0x9f, 0x02, 0x7d, 0x12, 0x1b, 0xfa, 0x7b, 0xcc, 0xc6, 0xb1, 0xe1, - 0x58, 0xca, 0xe8, 0xde, 0x23, 0x95, 0xc0, 0x49, 0xea, 0x1e, 0xe9, 0xfc, 0x54, 0x1e, 0xa9, 0xed, 0xdc, 0x92, 0xbf, - 0x44, 0x3f, 0x8e, 0xc6, 0xd8, 0xf9, 0xed, 0xe7, 0xa8, 0x26, 0xa6, 0xf3, 0x16, 0xb6, 0xb8, 0xf6, 0xc8, 0x32, 0x3f, - 0xab, 0x33, 0xd0, 0x81, 0x84, 0x93, 0x58, 0x29, 0xbb, 0x54, 0x2e, 0xf9, 0x7f, 0xc8, 0xd3, 0x26, 0x97, 0xd6, 0x08, - 0xe2, 0x4b, 0x56, 0x7d, 0x47, 0x10, 0x19, 0x53, 0xcd, 0xaa, 0x8a, 0xde, 0x23, 0x29, 0x62, 0xa5, 0xda, 0x55, 0x8d, - 0xd7, 0x6c, 0x33, 0x3b, 0x1b, 0x9d, 0x7b, 0xa1, 0x7e, 0x2f, 0x2c, 0x45, 0x57, 0xb4, 0xdf, 0xc5, 0x36, 0x52, 0x65, - 0x13, 0x11, 0x66, 0x70, 0x87, 0xa3, 0x11, 0x62, 0x4b, 0xa9, 0xa4, 0xcf, 0x76, 0x41, 0xba, 0xe7, 0x65, 0xaa, 0x26, - 0x5c, 0x8e, 0x84, 0x45, 0x6c, 0xa9, 0x8d, 0x57, 0xb2, 0xd3, 0x83, 0x27, 0xb7, 0xb8, 0x1d, 0xcb, 0xdd, 0x80, 0xe0, - 0x34, 0x64, 0xe9, 0x89, 0x63, 0x65, 0x22, 0xdd, 0xc9, 0xae, 0x73, 0x4d, 0x91, 0x62, 0xf7, 0x99, 0x74, 0xfb, 0xa1, - 0x94, 0x7e, 0xaa, 0x34, 0xe6, 0xc0, 0x35, 0x8e, 0xc0, 0x45, 0xc3, 0x88, 0x3e, 0x5e, 0x93, 0xf9, 0xd4, 0x07, 0xe9, - 0x49, 0x2d, 0x00, 0xc7, 0x41, 0xe9, 0x2c, 0x71, 0xb9, 0xc4, 0x0e, 0xfc, 0x24, 0xec, 0xac, 0x7a, 0x76, 0x1e, 0x0b, - 0xf9, 0x4c, 0xb5, 0xd9, 0x3a, 0x48, 0xe4, 0x9b, 0x9a, 0x87, 0x62, 0xd5, 0x0e, 0x0b, 0x0f, 0x7c, 0xbc, 0xc3, 0xe7, - 0xc7, 0xbb, 0xab, 0x6c, 0xc5, 0xcb, 0xc6, 0x39, 0x0d, 0x16, 0x97, 0x38, 0xd1, 0xf2, 0xcb, 0x65, 0x65, 0x83, 0x85, - 0x27, 0xf1, 0xe8, 0x7f, 0x53, 0x65, 0xfc, 0x4a, 0x86, 0x62, 0x39, 0x68, 0xbd, 0x2a, 0xab, 0xa4, 0xb8, 0x75, 0x7b, - 0x64, 0x91, 0x44, 0xf4, 0x30, 0x29, 0x97, 0x3a, 0xad, 0x6a, 0xa5, 0xc3, 0xdf, 0x4f, 0xe8, 0x8e, 0xb2, 0x0a, 0x00, - 0x53, 0x09, 0xfd, 0x83, 0x15, 0xdf, 0x65, 0xd4, 0xe8, 0xb0, 0x17, 0x2c, 0x96, 0x7d, 0x8e, 0xe2, 0x5f, 0xdb, 0xf3, - 0x30, 0x2c, 0x4b, 0xd2, 0x5d, 0xbd, 0x85, 0xd8, 0x0b, 0xfe, 0xf0, 0xc0, 0x69, 0x14, 0xa9, 0xc5, 0x8b, 0xab, 0xd0, - 0x24, 0xde, 0x21, 0x1d, 0x3f, 0x6d, 0x2d, 0xff, 0x26, 0xac, 0x24, 0xf6, 0x79, 0x5c, 0xcd, 0xb5, 0x6a, 0xd7, 0x52, - 0xb4, 0x38, 0x94, 0xd6, 0x48, 0x2f, 0x43, 0x7d, 0x0d, 0xf1, 0x26, 0xb7, 0xb6, 0xc4, 0x23, 0xee, 0x5e, 0x4a, 0xcf, - 0xb8, 0x68, 0x17, 0x72, 0xbe, 0xdf, 0x4a, 0x4a, 0x28, 0xee, 0xe4, 0xb1, 0x51, 0x3c, 0xb1, 0x9f, 0x5d, 0x92, 0x7c, - 0x20, 0x48, 0x71, 0xb1, 0xd2, 0xe9, 0x77, 0xce, 0x0e, 0xcf, 0x4a, 0x1d, 0x96, 0x68, 0x75, 0x6a, 0x3b, 0xb0, 0x12, - 0xef, 0xd9, 0xd7, 0x78, 0x13, 0xab, 0x04, 0xf4, 0xce, 0x85, 0x46, 0x5c, 0xba, 0x19, 0x11, 0xba, 0x48, 0xa7, 0x09, - 0x84, 0xbf, 0xdc, 0xfa, 0x25, 0xf1, 0xec, 0x7e, 0x2e, 0x07, 0x12, 0x35, 0xd4, 0x81, 0x43, 0x28, 0x2c, 0x5f, 0x44, - 0x33, 0x63, 0x2a, 0xd1, 0x1b, 0xb6, 0xab, 0x59, 0xea, 0x0e, 0x5f, 0x98, 0x4d, 0x4f, 0x7e, 0x95, 0xa3, 0x0d, 0x71, - 0x78, 0x26, 0xec, 0x8f, 0xdd, 0xe3, 0xff, 0x4a, 0x93, 0xe5, 0x45, 0xd3, 0xd1, 0x11, 0xc8, 0x16, 0x2d, 0x6b, 0x7c, - 0x63, 0x73, 0x0d, 0x5a, 0xc1, 0xce, 0xbc, 0x12, 0x28, 0x19, 0xda, 0xd2, 0x1d, 0x7d, 0x4f, 0x5e, 0x93, 0x00, 0xc6, - 0x32, 0xb5, 0x6e, 0x67, 0xbb, 0xf2, 0x2c, 0x18, 0x45, 0xb9, 0xe5, 0xc0, 0x1a, 0xb8, 0x6e, 0x0c, 0x8d, 0x9d, 0x31, - 0xba, 0xe6, 0xff, 0xac, 0x14, 0xd3, 0x15, 0x73, 0x90, 0x04, 0x5b, 0x5e, 0x1e, 0x06, 0xa9, 0xd9, 0xa7, 0x96, 0xae, - 0x33, 0xb5, 0x44, 0x50, 0x98, 0x15, 0x4f, 0x4d, 0x1a, 0xfa, 0x05, 0xec, 0xdf, 0xde, 0x98, 0x0e, 0x82, 0x7c, 0x2b, - 0x99, 0xc6, 0x68, 0x50, 0x39, 0x2f, 0xd4, 0x43, 0x6f, 0xbe, 0x70, 0x20, 0xbb, 0x5d, 0x59, 0x64, 0x54, 0x3b, 0xd4, - 0x0b, 0xb3, 0xe9, 0x9d, 0x81, 0x19, 0x89, 0x08, 0xb0, 0x11, 0x1f, 0xf5, 0x57, 0x84, 0x62, 0x89, 0x89, 0xb4, 0xf2, - 0x46, 0x9f, 0xdf, 0xe7, 0xc2, 0x42, 0xe7, 0x09, 0x36, 0xbd, 0x59, 0x34, 0xa3, 0x91, 0x00, 0x23, 0xe8, 0x8b, 0x9c, - 0xe5, 0x9c, 0xd5, 0x20, 0xb4, 0x3a, 0xa5, 0xe1, 0x16, 0x9c, 0x1e, 0x77, 0xad, 0x09, 0x94, 0xdb, 0x5f, 0x3a, 0x7b, - 0xab, 0xd7, 0xc2, 0xf6, 0xd6, 0x23, 0xd5, 0x8b, 0x3a, 0x1f, 0x7f, 0x70, 0x65, 0xe6, 0xf2, 0xef, 0x6d, 0x66, 0x22, - 0xa9, 0xfc, 0xf9, 0x0a, 0x89, 0xa0, 0xf2, 0xf0, 0x56, 0x1b, 0xc1, 0x85, 0xec, 0xe8, 0x19, 0xb3, 0x75, 0xd2, 0x0a, - 0xb6, 0x7f, 0x53, 0xfc, 0x40, 0x64, 0xf8, 0x17, 0x33, 0x70, 0xc4, 0x59, 0xc8, 0xb2, 0xa3, 0x40, 0x2b, 0xca, 0x03, - 0x35, 0x4e, 0xbc, 0x98, 0x8f, 0xe5, 0xba, 0x7c, 0x7b, 0x73, 0xa2, 0x82, 0xac, 0xb1, 0x08, 0x1e, 0xd6, 0xcb, 0x37, - 0x29, 0x93, 0x65, 0xc7, 0xa7, 0x37, 0x3d, 0x6e, 0xcf, 0x8d, 0x08, 0x48, 0x8b, 0x67, 0xc8, 0xe7, 0x4a, 0x24, 0x66, - 0x37, 0x1a, 0x2f, 0x39, 0x62, 0x31, 0x96, 0x12, 0x51, 0x2a, 0x74, 0x5c, 0x0b, 0x87, 0x28, 0xc4, 0x2a, 0x8c, 0x24, - 0xa8, 0xfc, 0x72, 0x61, 0x69, 0x16, 0x61, 0x62, 0x1f, 0x8b, 0x2b, 0x39, 0x4c, 0xb1, 0x87, 0x36, 0xd3, 0x7e, 0x52, - 0xd7, 0xf8, 0x8f, 0x51, 0xd7, 0xd7, 0x13, 0xea, 0x15, 0x43, 0x7b, 0x0d, 0xa5, 0xa9, 0x4e, 0x26, 0x56, 0x2c, 0x78, - 0xa4, 0x46, 0xe3, 0x3e, 0x34, 0x02, 0x84, 0xe2, 0xf6, 0x71, 0xd0, 0xb1, 0xad, 0x58, 0x62, 0xc4, 0x69, 0x51, 0x32, - 0xb3, 0xb4, 0xe9, 0xd8, 0xad, 0xa4, 0x43, 0x5a, 0x5e, 0xea, 0xf0, 0xfc, 0xc6, 0xbe, 0xee, 0x0a, 0x23, 0x8d, 0x79, - 0x37, 0x70, 0xbb, 0xdc, 0x74, 0x45, 0x45, 0xd1, 0x66, 0x64, 0x43, 0x5d, 0x0f, 0x88, 0x42, 0x88, 0x0d, 0x73, 0x6b, - 0x28, 0x4e, 0x46, 0x3b, 0xda, 0x61, 0x81, 0x79, 0x6c, 0x60, 0x1c, 0x83, 0x59, 0x47, 0xb5, 0xb1, 0x13, 0x59, 0xd6, - 0xbf, 0xe7, 0xb5, 0x8d, 0xf8, 0x7c, 0xb9, 0x26, 0x40, 0x40, 0xe3, 0x41, 0x2f, 0x7b, 0x45, 0xe4, 0xa0, 0x97, 0x21, - 0x97, 0xd8, 0x38, 0x21, 0x43, 0x63, 0xe3, 0xfb, 0x83, 0xd9, 0x93, 0x99, 0xe3, 0xe7, 0x33, 0x83, 0xb1, 0x8f, 0xd5, - 0xfc, 0xc8, 0x82, 0x43, 0x99, 0x34, 0x5d, 0x3f, 0x72, 0x44, 0xef, 0x99, 0x56, 0xdc, 0x77, 0x38, 0x58, 0x26, 0x65, - 0x96, 0x4c, 0xba, 0x19, 0x40, 0x65, 0xb0, 0x92, 0x77, 0x3b, 0x3f, 0x5c, 0x69, 0x88, 0x7e, 0x68, 0x2e, 0x16, 0x53, - 0xd9, 0x0e, 0xce, 0x53, 0x43, 0xa4, 0x2c, 0x0d, 0x6f, 0x8e, 0x06, 0x21, 0xc4, 0xf5, 0x69, 0xbe, 0xfe, 0x75, 0x54, - 0x3b, 0x9b, 0x4d, 0x4d, 0x91, 0x34, 0x15, 0x4c, 0xcf, 0x58, 0x29, 0x0d, 0x8e, 0x41, 0x80, 0x01, 0x27, 0x0b, 0x39, - 0x6f, 0x7b, 0xe4, 0xfc, 0xd3, 0x20, 0xd6, 0x03, 0x5a, 0xeb, 0x5e, 0x64, 0x44, 0x62, 0x1f, 0xda, 0x8a, 0x4b, 0x54, - 0x9d, 0xca, 0x06, 0xa0, 0xa2, 0xfe, 0xda, 0xeb, 0xd1, 0x0a, 0xfe, 0x9e, 0x83, 0xae, 0x7a, 0x8d, 0x2f, 0xda, 0x7b, - 0xa2, 0xdf, 0x34, 0xf5, 0x7f, 0xa2, 0x0c, 0xc2, 0xf6, 0x32, 0xa1, 0x03, 0x6f, 0x20, 0x0b, 0x08, 0xf8, 0x9d, 0x1e, - 0xf4, 0x05, 0xe0, 0x91, 0x18, 0x72, 0x40, 0x8e, 0x9f, 0x5b, 0x03, 0x35, 0xae, 0xf6, 0x3a, 0xf7, 0xfd, 0x37, 0x1f, - 0x1c, 0xe9, 0x83, 0x6b, 0x1c, 0xba, 0xc7, 0x27, 0x12, 0x59, 0xc8, 0x8e, 0xb3, 0x74, 0x78, 0x21, 0xa7, 0xdb, 0xfa, - 0xa8, 0xa4, 0xdb, 0xf1, 0x44, 0xe1, 0x1f, 0x5a, 0x90, 0xbc, 0xcd, 0xe3, 0xd9, 0x81, 0xa6, 0xfa, 0x76, 0x26, 0x35, - 0x62, 0xd3, 0xdd, 0x4e, 0xa9, 0x4f, 0xb2, 0x12, 0x8e, 0x85, 0xc1, 0x36, 0x06, 0xe3, 0x2a, 0xb7, 0x73, 0x2b, 0xb7, - 0x39, 0xac, 0x35, 0x7d, 0xf1, 0xed, 0x6e, 0x6f, 0x5a, 0xe8, 0xfd, 0x4b, 0xfb, 0x9c, 0x8e, 0xa1, 0x99, 0x3b, 0x0c, - 0x08, 0x0a, 0x5f, 0x28, 0x4e, 0x2f, 0xd3, 0xd7, 0xb7, 0xc3, 0xf8, 0x18, 0xda, 0xf9, 0xaa, 0xd8, 0x09, 0x32, 0x8f, - 0xca, 0x45, 0x6a, 0xf3, 0x99, 0x71, 0x59, 0x4d, 0x6e, 0x8b, 0xf3, 0xdb, 0x53, 0x32, 0xef, 0xf9, 0x15, 0x34, 0xa8, - 0xc7, 0xfe, 0xa3, 0x86, 0xbf, 0x3c, 0xad, 0x61, 0x5d, 0x29, 0xca, 0x80, 0xdd, 0xd6, 0x35, 0x20, 0x9b, 0x9c, 0xf3, - 0xe0, 0xb8, 0x56, 0x38, 0xf0, 0x6a, 0x17, 0x9d, 0x43, 0x5c, 0x56, 0xc6, 0xf5, 0xa6, 0x4f, 0xbb, 0xdc, 0xcf, 0xb8, - 0x53, 0xd8, 0x75, 0x70, 0x12, 0xb1, 0x81, 0x07, 0x15, 0x7d, 0x40, 0x77, 0xd2, 0x87, 0x7a, 0xd8, 0xab, 0x06, 0x42, - 0x08, 0x8c, 0x6f, 0xbe, 0x50, 0xe6, 0xcf, 0xd2, 0xea, 0xbb, 0xac, 0x55, 0x31, 0x96, 0x64, 0x0d, 0x9c, 0x9d, 0xde, - 0x1f, 0x71, 0x18, 0x62, 0xc7, 0x9b, 0x04, 0xc4, 0x59, 0xe6, 0x46, 0xcc, 0x49, 0x10, 0x7d, 0xc8, 0x3a, 0xea, 0xe9, - 0x47, 0xf3, 0x1f, 0x10, 0x01, 0x02, 0x16, 0x1c, 0x27, 0x02, 0x61, 0xc8, 0x7c, 0x85, 0xf0, 0x9d, 0xbe, 0xfd, 0xf0, - 0x0b, 0xa6, 0xb6, 0x6f, 0x74, 0xd7, 0xc8, 0xff, 0x6b, 0x38, 0xe4, 0xf6, 0x57, 0x9e, 0x2e, 0x0f, 0xf9, 0x93, 0xcb, - 0x3e, 0x7f, 0xbb, 0x77, 0xd3, 0xe4, 0xee, 0xe4, 0xe6, 0x63, 0x05, 0xd4, 0xfa, 0x7c, 0x95, 0x1e, 0xa1, 0x62, 0x44, - 0x19, 0x73, 0xa7, 0x87, 0x31, 0x6d, 0x96, 0x9d, 0x0d, 0x2e, 0x11, 0xfb, 0x35, 0x2e, 0x4f, 0xbd, 0x86, 0x09, 0x6c, - 0x57, 0xe1, 0x5a, 0x3a, 0x97, 0x49, 0xd6, 0x3c, 0x53, 0xe6, 0xa8, 0x60, 0x2c, 0x6c, 0x4c, 0x00, 0x6f, 0x60, 0xa7, - 0xcb, 0x77, 0xfa, 0xd6, 0x8b, 0xbe, 0x94, 0x07, 0x09, 0x6a, 0x1e, 0x70, 0x11, 0xe8, 0xea, 0x99, 0x6d, 0xb1, 0xf1, - 0xfb, 0x39, 0xd1, 0xd1, 0x04, 0x92, 0xfa, 0xe3, 0x31, 0x6a, 0xaf, 0x72, 0x57, 0xda, 0x2a, 0xaa, 0x85, 0x9e, 0xed, - 0x89, 0xd0, 0xa7, 0x4c, 0x26, 0x03, 0x76, 0x01, 0x5f, 0xf5, 0x92, 0xbe, 0xb4, 0x35, 0xe4, 0x53, 0xe5, 0x29, 0x17, - 0x2c, 0x1c, 0x4f, 0x70, 0x9c, 0xf6, 0xa8, 0x3e, 0x10, 0x4c, 0xe2, 0x2a, 0x58, 0xc3, 0xbe, 0x64, 0x55, 0xe9, 0x45, - 0x73, 0x32, 0x0c, 0x2e, 0xa7, 0xc9, 0xfa, 0x37, 0xb6, 0xc5, 0xd2, 0xf7, 0x24, 0xd0, 0x6e, 0xd1, 0xc8, 0x66, 0x8c, - 0x85, 0x0c, 0x65, 0x3a, 0x68, 0x03, 0x09, 0x40, 0x67, 0x4d, 0x67, 0xc5, 0xa7, 0xa9, 0xa5, 0x70, 0x6e, 0x92, 0x18, - 0x0b, 0x97, 0xe6, 0x48, 0x36, 0x53, 0x30, 0xe1, 0x75, 0x4b, 0x7b, 0x9e, 0x4d, 0x32, 0xef, 0xcb, 0x24, 0xa6, 0x7c, - 0x2f, 0x70, 0xef, 0x20, 0x9c, 0x48, 0xe8, 0x55, 0xc8, 0x52, 0x28, 0xb5, 0x04, 0xdb, 0x98, 0xb9, 0xf0, 0x37, 0x00, - 0xa2, 0x7c, 0x1a, 0x63, 0x03, 0xf6, 0xaf, 0xd1, 0x10, 0x3a, 0xb1, 0xfd, 0xc1, 0x5a, 0x49, 0x61, 0x06, 0xaa, 0x2c, - 0x94, 0xd8, 0x9c, 0x25, 0x7b, 0x71, 0xf8, 0x06, 0x17, 0x3a, 0x77, 0x4a, 0x61, 0x9f, 0xd3, 0x39, 0xc1, 0x54, 0x55, - 0xce, 0x1b, 0x72, 0x13, 0xe2, 0xf9, 0x46, 0x92, 0x46, 0xcb, 0x21, 0x76, 0x11, 0x73, 0xbd, 0xf8, 0xed, 0xdf, 0x47, - 0xb8, 0xd9, 0x94, 0x16, 0x9b, 0xd9, 0xce, 0x08, 0xcf, 0x3b, 0x38, 0x3a, 0x23, 0x8f, 0x5d, 0x8f, 0x2c, 0x0d, 0xfe, - 0xf1, 0x4d, 0x6e, 0x97, 0xeb, 0x9d, 0x13, 0x40, 0x3d, 0xf9, 0xef, 0x45, 0xed, 0x6a, 0x72, 0x1a, 0x89, 0xa1, 0xb1, - 0x91, 0x91, 0x05, 0x00, 0x12, 0x18, 0x6b, 0x3a, 0x36, 0xb3, 0x29, 0xda, 0x76, 0x82, 0x68, 0xf6, 0xf3, 0x47, 0x5c, - 0xbf, 0x37, 0x1b, 0xbe, 0xc0, 0x7d, 0xdc, 0xb1, 0x51, 0x5c, 0x3e, 0xb0, 0x89, 0x1c, 0xfa, 0xad, 0x16, 0x33, 0xfa, - 0x46, 0x26, 0xdc, 0x88, 0xf5, 0x39, 0xb4, 0xdb, 0xa0, 0xc2, 0x01, 0x90, 0xf9, 0x93, 0x7c, 0x3c, 0xff, 0x57, 0xaa, - 0xb9, 0x13, 0xc6, 0xac, 0xb1, 0x72, 0x69, 0x4c, 0xe2, 0xe4, 0xd0, 0x5e, 0x70, 0xd4, 0x9c, 0xd0, 0x3e, 0xac, 0x08, - 0x7a, 0x8c, 0xb6, 0x31, 0x99, 0x81, 0xd0, 0x90, 0x62, 0x05, 0x63, 0xb0, 0x1f, 0x56, 0x9f, 0x5d, 0x77, 0xbf, 0x40, - 0x8a, 0x7b, 0xe3, 0x3a, 0x33, 0x9e, 0x9b, 0x4c, 0x66, 0x3a, 0x8f, 0x2d, 0x78, 0x4b, 0x5c, 0x34, 0xad, 0x56, 0x3e, - 0x6b, 0x77, 0x4c, 0xdb, 0xbe, 0x63, 0xba, 0x8a, 0x5f, 0xc7, 0x87, 0x64, 0xb6, 0x37, 0xe7, 0x10, 0x40, 0x8b, 0xfa, - 0xec, 0x13, 0xfc, 0xe4, 0xa2, 0xd3, 0xd4, 0x9b, 0x6d, 0x68, 0x68, 0xbb, 0x5c, 0x9f, 0x1f, 0xb4, 0x3a, 0x41, 0xc7, - 0x90, 0xb3, 0x66, 0x50, 0xf4, 0x3e, 0xb1, 0xf3, 0x12, 0x9f, 0x58, 0xa7, 0x82, 0x71, 0xd2, 0x80, 0x7e, 0x9c, 0x93, - 0x97, 0xbb, 0xdc, 0x3c, 0x06, 0xf2, 0x53, 0x8a, 0x23, 0x74, 0xc3, 0xe8, 0x61, 0x4d, 0xf4, 0xbd, 0x47, 0x8f, 0x2d, - 0x5b, 0xb3, 0x0d, 0x40, 0x63, 0x72, 0x85, 0x2b, 0x4b, 0xb2, 0x4d, 0xf8, 0x98, 0x1e, 0x5c, 0xa3, 0x05, 0x4d, 0x9f, - 0x7d, 0xf6, 0x37, 0x17, 0xd0, 0xd9, 0x63, 0x02, 0xb5, 0xc4, 0xb3, 0x74, 0x50, 0x2f, 0x14, 0xca, 0x73, 0x04, 0x46, - 0x5e, 0x62, 0x9e, 0x55, 0xd3, 0xa1, 0xa6, 0x75, 0x8f, 0x4e, 0x4f, 0x5d, 0x6a, 0x2d, 0xbb, 0x98, 0xb1, 0x40, 0x34, - 0x47, 0x2b, 0xb3, 0xaf, 0x04, 0xfd, 0x50, 0x83, 0x8d, 0x99, 0x05, 0xf0, 0x8a, 0x5c, 0x6f, 0xa4, 0xa6, 0x27, 0xf1, - 0x1e, 0xe1, 0x8a, 0x40, 0xb8, 0x23, 0x8a, 0x94, 0xf1, 0x14, 0x88, 0xa3, 0x75, 0xbc, 0x9e, 0x4e, 0xec, 0x38, 0x78, - 0x52, 0x90, 0x17, 0x7e, 0x6b, 0x46, 0x02, 0x9e, 0xfd, 0x11, 0x48, 0xca, 0x5e, 0x07, 0x21, 0xba, 0xca, 0x12, 0xdb, - 0x5b, 0x35, 0x16, 0x77, 0x1f, 0x36, 0x2d, 0x32, 0x77, 0xc5, 0x90, 0x9d, 0x85, 0x73, 0x45, 0xeb, 0x62, 0xd9, 0x76, - 0x4f, 0xe4, 0xee, 0x6c, 0xc5, 0x41, 0x62, 0xe1, 0x7a, 0xe7, 0x13, 0x32, 0xe5, 0xc3, 0x98, 0xd2, 0xf5, 0xda, 0xa8, - 0x55, 0xbb, 0xcc, 0x91, 0x17, 0x29, 0xe2, 0xed, 0x5a, 0x48, 0x11, 0x8b, 0x53, 0x11, 0xad, 0x09, 0x5f, 0x1d, 0x24, - 0x0d, 0x6a, 0x7d, 0xbf, 0xee, 0x6c, 0xf6, 0x83, 0x3c, 0xb7, 0x4e, 0x25, 0xe5, 0xe1, 0xf0, 0xd7, 0xe6, 0xdb, 0x11, - 0xf7, 0xa2, 0x41, 0xf1, 0xa5, 0xea, 0x2a, 0x12, 0xcd, 0xed, 0x95, 0xea, 0x4c, 0x17, 0xc5, 0xef, 0x53, 0x76, 0xca, - 0x61, 0x8a, 0xf1, 0xd9, 0x74, 0xda, 0xdd, 0x27, 0x0f, 0x42, 0xc7, 0xee, 0xba, 0xdc, 0x99, 0xf9, 0x7a, 0xc7, 0xde, - 0x9c, 0x70, 0xfa, 0x9f, 0xca, 0x8a, 0xb3, 0x11, 0xd1, 0xff, 0xfa, 0x37, 0x2f, 0xc0, 0xb7, 0x4e, 0xbb, 0x2e, 0x9d, - 0x1a, 0x48, 0xa1, 0x85, 0x35, 0x6d, 0xec, 0x5f, 0xfc, 0x44, 0x0a, 0x01, 0xa1, 0x77, 0x9e, 0x57, 0x57, 0x48, 0x60, - 0x9b, 0xda, 0xc5, 0xd4, 0xed, 0xbe, 0xd6, 0x4b, 0x4c, 0xca, 0x12, 0xd7, 0x75, 0xf8, 0x85, 0xa5, 0x9f, 0x84, 0x69, - 0xc8, 0xbd, 0xd3, 0xa6, 0xd1, 0x86, 0x18, 0x41, 0x39, 0xbb, 0x17, 0x4b, 0x4d, 0x08, 0x5d, 0xdc, 0x51, 0x16, 0x60, - 0xd7, 0x3f, 0x9e, 0xa2, 0xc9, 0x95, 0x08, 0xf5, 0xc7, 0x78, 0x13, 0xb6, 0x5c, 0xdd, 0x29, 0x4d, 0x61, 0x3b, 0x4c, - 0xd9, 0x67, 0x08, 0xf4, 0x1a, 0x31, 0xf8, 0x7c, 0x7b, 0x0b, 0x07, 0x7b, 0x23, 0x34, 0x91, 0x49, 0xb7, 0x10, 0xb3, - 0xa3, 0xf1, 0xdb, 0x9f, 0xa9, 0xc6, 0xfc, 0xdc, 0xb7, 0x58, 0xee, 0x90, 0x9e, 0x00, 0x47, 0x3a, 0xe0, 0xf1, 0x3c, - 0x1d, 0x29, 0xbe, 0x0d, 0xfa, 0xb5, 0x49, 0xfe, 0xd7, 0xb8, 0xe1, 0x1b, 0x4d, 0x37, 0x84, 0xa7, 0xab, 0xc2, 0x0e, - 0x7d, 0xce, 0x60, 0x2e, 0xa9, 0x4b, 0xfa, 0xf0, 0x4f, 0x27, 0x9d, 0x71, 0x7d, 0x53, 0x44, 0x06, 0x03, 0x97, 0x05, - 0x93, 0xb3, 0xeb, 0x0e, 0xf3, 0xd2, 0xf7, 0x04, 0x32, 0x30, 0x78, 0x18, 0x47, 0x48, 0x22, 0x93, 0x81, 0xbd, 0xc1, - 0x84, 0xbe, 0xba, 0x94, 0x70, 0xc6, 0x6b, 0x4a, 0xd3, 0xa1, 0xea, 0xb8, 0xd9, 0xf4, 0x42, 0x81, 0x71, 0x04, 0xa1, - 0xc4, 0x33, 0x60, 0x15, 0xa8, 0x48, 0xcf, 0x99, 0xe5, 0x9c, 0xf2, 0x5b, 0xe7, 0xb0, 0x75, 0x9d, 0xd5, 0xa8, 0x3e, - 0x3f, 0x97, 0x85, 0x00, 0x91, 0xe6, 0xda, 0x99, 0xb4, 0x94, 0x7a, 0xfa, 0xe1, 0x91, 0x94, 0xc3, 0xff, 0x20, 0x89, - 0x57, 0x79, 0x3e, 0xfe, 0xf5, 0xe3, 0x44, 0x55, 0x3d, 0xf8, 0x76, 0xd1, 0x07, 0xba, 0x6f, 0x5e, 0x8f, 0x6a, 0xe5, - 0xf9, 0x8a, 0xfd, 0xe2, 0x22, 0xe3, 0xc2, 0xfc, 0x13, 0x83, 0x30, 0x06, 0x3a, 0xb3, 0xe0, 0x2b, 0x62, 0xc5, 0xaf, - 0xf9, 0xec, 0xb4, 0x07, 0x6a, 0x8e, 0xe4, 0x4c, 0xa6, 0x28, 0xab, 0x75, 0xeb, 0xdd, 0x4e, 0x0d, 0x88, 0x48, 0x47, - 0x6f, 0xc6, 0xe9, 0x06, 0x2e, 0x70, 0x5a, 0x75, 0x86, 0xfa, 0x59, 0xb0, 0x22, 0xb9, 0xfd, 0x0d, 0x59, 0xbc, 0xeb, - 0xbe, 0xdf, 0x51, 0xb9, 0x72, 0x12, 0x87, 0x26, 0xd6, 0x7e, 0xda, 0x29, 0x80, 0x99, 0xba, 0xb3, 0x4d, 0xd1, 0x73, - 0x1d, 0x1d, 0x1c, 0x53, 0x06, 0x0e, 0xa7, 0x9e, 0x1f, 0x24, 0x34, 0x7c, 0x15, 0xbe, 0xe8, 0xa3, 0x6e, 0xf7, 0x47, - 0x0c, 0xa4, 0x20, 0x23, 0xb9, 0xb3, 0x27, 0x96, 0x57, 0x21, 0x6f, 0xa2, 0xc6, 0x71, 0x31, 0xa3, 0x42, 0x28, 0xfb, - 0xd7, 0xf2, 0x72, 0x3f, 0x0c, 0xc9, 0x5d, 0x93, 0x12, 0x6f, 0x76, 0xae, 0x91, 0x72, 0x96, 0x60, 0x6e, 0x47, 0x2c, - 0x47, 0x33, 0xa8, 0xd7, 0x7d, 0x7a, 0xd7, 0xe1, 0x33, 0x34, 0x45, 0x8f, 0x1b, 0x74, 0xa1, 0xd0, 0xa8, 0x5b, 0x5b, - 0xa3, 0x6d, 0x1a, 0xa5, 0x89, 0xc8, 0xa9, 0x22, 0xa4, 0x0f, 0xf3, 0xcd, 0xe4, 0x9b, 0x1d, 0x90, 0x32, 0x06, 0x0f, - 0xd0, 0xa4, 0x7a, 0x05, 0x10, 0x69, 0xbe, 0x7c, 0xaa, 0xa4, 0xdb, 0xcf, 0x5e, 0x24, 0xfd, 0x04, 0x34, 0x4e, 0x34, - 0xe9, 0x1a, 0x3f, 0xa1, 0x4c, 0x6b, 0x8a, 0xa3, 0x09, 0x49, 0x34, 0x5a, 0x26, 0xcf, 0x86, 0xda, 0x91, 0xd7, 0x82, - 0x95, 0xa1, 0x27, 0x0d, 0x16, 0x81, 0xe0, 0x00, 0x89, 0x24, 0x5c, 0x53, 0x92, 0x61, 0x8c, 0x0b, 0x84, 0xd1, 0xbf, - 0xb0, 0x25, 0x1d, 0x62, 0xed, 0x66, 0xc1, 0x84, 0x8c, 0xee, 0xcf, 0xf8, 0x25, 0x0c, 0x0d, 0xab, 0x66, 0x18, 0x4f, - 0xd2, 0x71, 0xaa, 0x35, 0x46, 0x51, 0x5a, 0x9c, 0x05, 0x93, 0x5a, 0xc8, 0xa1, 0xc6, 0x00, 0xdb, 0x8d, 0xe3, 0x69, - 0x4d, 0xd9, 0x32, 0x62, 0x26, 0xdd, 0xdb, 0xda, 0x51, 0xa7, 0xb9, 0xa5, 0x9f, 0x7b, 0x21, 0xb3, 0x0d, 0x39, 0xe6, - 0xbc, 0xa5, 0x5f, 0x36, 0xd1, 0x87, 0x16, 0xeb, 0x66, 0x1c, 0x08, 0x33, 0xfc, 0xb9, 0xe5, 0x90, 0x78, 0x54, 0x30, - 0xa8, 0xf2, 0xa4, 0x46, 0x2b, 0xd2, 0xf6, 0xbe, 0xaf, 0x8e, 0xe6, 0xb6, 0xa9, 0x48, 0x1a, 0x82, 0xdc, 0x08, 0x4d, - 0x04, 0x8e, 0x5d, 0xe9, 0x1f, 0x67, 0x75, 0xff, 0xdd, 0x43, 0x1f, 0x49, 0x83, 0xf0, 0xe5, 0x9a, 0xe9, 0x20, 0x14, - 0x30, 0x57, 0xad, 0xdb, 0xd4, 0x67, 0x71, 0x35, 0xa2, 0xbf, 0x22, 0x64, 0xcc, 0x38, 0x56, 0xfd, 0x98, 0x66, 0xe4, - 0x77, 0xfa, 0x1a, 0x39, 0x26, 0xef, 0xc7, 0xcc, 0x6a, 0x55, 0xf2, 0xe1, 0xa9, 0x3b, 0x5d, 0xc9, 0x68, 0x46, 0xca, - 0xb3, 0xba, 0xc3, 0xd2, 0x56, 0x88, 0x39, 0x8b, 0xf7, 0xe4, 0x7a, 0x36, 0x5d, 0x65, 0x2b, 0xf1, 0x43, 0x7a, 0x70, - 0xaf, 0x8f, 0x99, 0xa4, 0xc3, 0x0f, 0x59, 0x7e, 0xdd, 0x9d, 0x00, 0x21, 0x4f, 0x4f, 0xc0, 0xac, 0x6e, 0x5d, 0xd9, - 0x69, 0xad, 0xb8, 0xef, 0x24, 0xdb, 0x36, 0x5c, 0xbf, 0xe6, 0x8f, 0x79, 0xf0, 0x70, 0xef, 0xcb, 0x36, 0x17, 0x4f, - 0xc3, 0xc7, 0xc9, 0x52, 0x0b, 0x21, 0xf1, 0x55, 0x97, 0x42, 0x15, 0xa3, 0xe0, 0x0d, 0xe3, 0x41, 0x5c, 0xc8, 0x1f, - 0xe7, 0xb4, 0x35, 0x2d, 0x3b, 0xb5, 0x92, 0x78, 0xac, 0xab, 0x30, 0x2d, 0xf9, 0x75, 0x51, 0xcd, 0x79, 0x66, 0xe2, - 0x55, 0xa7, 0x9e, 0xa1, 0x39, 0x8d, 0xc9, 0xf5, 0xf0, 0x9e, 0x97, 0x68, 0x64, 0xd9, 0xf0, 0x6e, 0xc2, 0x5b, 0xb1, - 0x57, 0x9e, 0xa1, 0xdc, 0x1d, 0x29, 0x35, 0x84, 0x02, 0x62, 0x04, 0x1a, 0x57, 0xe7, 0x2e, 0xad, 0xa4, 0xb3, 0xe4, - 0x51, 0x63, 0xe0, 0x8b, 0x39, 0x8f, 0x5b, 0x63, 0xa1, 0x1c, 0x6b, 0x0e, 0x61, 0x46, 0xaa, 0x70, 0x32, 0xd5, 0x0d, - 0xe0, 0xce, 0x34, 0x43, 0x88, 0x26, 0x4a, 0xcd, 0x29, 0xee, 0xe2, 0x6b, 0x34, 0x99, 0x6c, 0xe8, 0x18, 0xf4, 0x2c, - 0xaf, 0xc8, 0x34, 0x1e, 0x07, 0xd0, 0x7d, 0xe0, 0xeb, 0x06, 0x89, 0x05, 0xdb, 0xb2, 0x4e, 0xf8, 0x2a, 0x70, 0xe2, - 0x28, 0xab, 0x12, 0x53, 0xc3, 0xb3, 0xa1, 0xdb, 0x1f, 0xe8, 0x88, 0xb5, 0xa2, 0xa6, 0xbb, 0x23, 0x26, 0x28, 0xf8, - 0xee, 0xfb, 0x2f, 0x78, 0x77, 0x64, 0xe2, 0x38, 0x83, 0x38, 0xae, 0x5d, 0x78, 0x9b, 0x74, 0x04, 0x4d, 0x30, 0x56, - 0x96, 0x63, 0x9e, 0x72, 0x49, 0xa1, 0xf6, 0xfc, 0x97, 0x86, 0x23, 0x54, 0xc9, 0x35, 0x44, 0x6f, 0x19, 0xba, 0x43, - 0xb0, 0x6b, 0x1f, 0xa2, 0x53, 0x11, 0x1f, 0x78, 0x7f, 0x81, 0x48, 0x98, 0x4b, 0xa1, 0xcc, 0xb2, 0x5e, 0xed, 0xb1, - 0x80, 0x3a, 0xef, 0x29, 0xc7, 0x46, 0x01, 0x2b, 0x4b, 0xaf, 0x58, 0xab, 0x4e, 0xd9, 0xe1, 0xd7, 0x3a, 0x12, 0x62, - 0x63, 0xae, 0x1b, 0x1a, 0x3f, 0x91, 0xae, 0x02, 0x89, 0xcd, 0x7b, 0xb5, 0x9c, 0x8d, 0xa2, 0x50, 0x1f, 0xbe, 0xe4, - 0x93, 0xb6, 0x52, 0x3f, 0x41, 0x82, 0x3f, 0xe1, 0x90, 0x88, 0xf9, 0x94, 0x1f, 0x24, 0x56, 0x75, 0xb9, 0xa9, 0x59, - 0x66, 0xdb, 0x21, 0xf9, 0x97, 0x5f, 0x88, 0x3f, 0x7b, 0x8f, 0x25, 0x78, 0xac, 0x30, 0x43, 0xc2, 0x18, 0xa3, 0xd4, - 0x4b, 0xfe, 0x68, 0x81, 0x8f, 0xe7, 0x6e, 0x7e, 0xf5, 0xdb, 0x59, 0x3b, 0xfc, 0x82, 0x81, 0x42, 0x8c, 0xfa, 0x42, - 0x4b, 0x0a, 0xf6, 0xee, 0x64, 0x71, 0xbb, 0x20, 0x27, 0xa1, 0x48, 0x45, 0x89, 0x12, 0xc6, 0x90, 0xb6, 0x01, 0xd0, - 0x4d, 0x80, 0x4a, 0x94, 0x6a, 0x1a, 0xd1, 0x23, 0xf8, 0x01, 0x9f, 0x6d, 0xde, 0x1e, 0x64, 0x1d, 0x4c, 0xa4, 0x36, - 0x2e, 0x63, 0x03, 0x98, 0xe2, 0xb9, 0xb5, 0xc3, 0xfb, 0x65, 0x04, 0xad, 0x75, 0xac, 0xd4, 0x10, 0xea, 0x22, 0xe7, - 0x7e, 0xf0, 0x19, 0x75, 0x37, 0xd9, 0x39, 0xcc, 0xd3, 0x0c, 0x0c, 0xe4, 0x78, 0x40, 0xb3, 0x6d, 0x4c, 0x96, 0x28, - 0x66, 0xd9, 0x0c, 0xbf, 0x54, 0x2f, 0x6f, 0xb4, 0xa5, 0x20, 0x69, 0xad, 0xce, 0x9e, 0x29, 0x86, 0x09, 0x1b, 0x58, - 0x60, 0x3e, 0x40, 0xd8, 0xc2, 0x12, 0xb6, 0x8e, 0x3d, 0x87, 0xfe, 0x68, 0x6c, 0xce, 0x71, 0x76, 0xb2, 0xe9, 0x5c, - 0xcb, 0xc6, 0x93, 0x1f, 0x15, 0xe7, 0x3c, 0x4d, 0xca, 0x41, 0x25, 0x54, 0x5b, 0xb1, 0x40, 0x87, 0xe8, 0x56, 0x1f, - 0x2a, 0x9d, 0x33, 0xf7, 0x9c, 0x90, 0x88, 0xa7, 0x73, 0xcc, 0xb5, 0xc7, 0xfb, 0x15, 0x25, 0x10, 0x2a, 0xbc, 0x75, - 0xf1, 0x31, 0x3b, 0x40, 0x56, 0x1e, 0x0a, 0x4f, 0xb6, 0x9c, 0x96, 0x48, 0x09, 0x4e, 0xbf, 0x79, 0x9d, 0x3c, 0x15, - 0x18, 0x19, 0x8a, 0x35, 0x26, 0xd5, 0x90, 0x78, 0x83, 0x11, 0x7a, 0x71, 0x11, 0xc9, 0x15, 0x98, 0x3b, 0x97, 0x66, - 0xea, 0x7a, 0x21, 0x67, 0x2c, 0xcf, 0x3d, 0xd8, 0xe3, 0xa5, 0xa7, 0x96, 0x5d, 0x78, 0xec, 0x5e, 0x32, 0xc7, 0xeb, - 0xf3, 0x90, 0x66, 0xb0, 0x3b, 0x85, 0xb5, 0x7a, 0xac, 0x8a, 0x82, 0x01, 0x58, 0x57, 0xc8, 0xca, 0xce, 0x34, 0x29, - 0x07, 0xca, 0x4f, 0x50, 0xdb, 0x41, 0xfd, 0x1b, 0x23, 0x11, 0x8c, 0xdf, 0x6d, 0xdd, 0xd7, 0x6e, 0xc9, 0x84, 0x99, - 0x8f, 0x02, 0x1b, 0xa2, 0xc7, 0x14, 0x66, 0x6c, 0x98, 0x2a, 0x63, 0xdc, 0x79, 0x0f, 0x83, 0xae, 0x2e, 0xdb, 0x4c, - 0xe5, 0x68, 0x7c, 0xb1, 0x8c, 0xab, 0x61, 0xa6, 0xef, 0xde, 0x03, 0x66, 0xbc, 0xda, 0xf3, 0x28, 0xe2, 0xd8, 0x49, - 0xcc, 0xa9, 0x9e, 0x51, 0xed, 0x6b, 0x2f, 0xdb, 0x74, 0x87, 0x98, 0xf0, 0xee, 0x0e, 0xde, 0x3b, 0x86, 0x99, 0x4c, - 0xe8, 0xe4, 0x40, 0x66, 0x42, 0xca, 0x1e, 0xa0, 0x89, 0x0c, 0x1d, 0x1e, 0x37, 0xe6, 0xa2, 0x3c, 0x4b, 0x32, 0x0b, - 0x0b, 0x17, 0xf6, 0x4d, 0xfa, 0x6f, 0xb8, 0x98, 0xfb, 0x22, 0xd0, 0xe6, 0x30, 0x5d, 0x37, 0xd9, 0xbc, 0x67, 0x15, - 0x9b, 0x2c, 0x1d, 0xb2, 0xd6, 0xa8, 0x12, 0xfd, 0x22, 0x31, 0x29, 0x3b, 0x84, 0x1e, 0x86, 0x6e, 0x10, 0xc5, 0x82, - 0xc5, 0xbe, 0xd1, 0x45, 0x3b, 0xc0, 0x47, 0x27, 0xe1, 0xb1, 0xf8, 0x9e, 0xee, 0x5c, 0x69, 0xce, 0xb7, 0xbb, 0x93, - 0xdf, 0xa8, 0x68, 0xd4, 0x34, 0x12, 0x1b, 0x95, 0xf8, 0x58, 0xec, 0xe5, 0xa6, 0xd2, 0x76, 0xf9, 0xd8, 0xd3, 0x5f, - 0xcc, 0xc8, 0x28, 0x1d, 0xcc, 0x99, 0x0e, 0x1e, 0xc2, 0xab, 0x79, 0x25, 0x8a, 0x7b, 0xae, 0x94, 0x70, 0x82, 0x9a, - 0x0b, 0x4e, 0x1d, 0x54, 0x29, 0x3c, 0x41, 0xa0, 0xd0, 0xfa, 0xc7, 0x75, 0xfd, 0x00, 0x48, 0xdb, 0xb3, 0x63, 0x30, - 0xf7, 0x55, 0x2f, 0x51, 0xa6, 0xee, 0x99, 0xd4, 0x0a, 0x68, 0x63, 0xab, 0xb8, 0x07, 0x12, 0xf4, 0x2d, 0x87, 0x94, - 0x90, 0x95, 0x79, 0x50, 0xd8, 0x2c, 0xa7, 0x27, 0xc9, 0x54, 0xe9, 0xcc, 0x5a, 0x51, 0x2e, 0xee, 0x89, 0x0a, 0xe1, - 0xd6, 0xfa, 0xfb, 0x80, 0x10, 0xa3, 0x94, 0xc1, 0x68, 0x62, 0xe2, 0x32, 0x42, 0x06, 0x8c, 0x0b, 0xc9, 0xb0, 0x82, - 0x48, 0x61, 0x97, 0x33, 0x8c, 0xc7, 0x74, 0x79, 0xd6, 0x9e, 0x9d, 0x87, 0xed, 0x7b, 0x6e, 0xc8, 0x1d, 0x82, 0xce, - 0xc6, 0x89, 0x4d, 0xe3, 0xe7, 0x67, 0xe2, 0x7d, 0x04, 0x37, 0x2a, 0x87, 0x35, 0x1a, 0x38, 0x35, 0xe6, 0x39, 0x8b, - 0xaf, 0xe2, 0x63, 0xbc, 0xad, 0x67, 0x4b, 0xae, 0x74, 0xec, 0x98, 0x3b, 0xf2, 0x63, 0x77, 0xa5, 0xb4, 0x29, 0x48, - 0xa2, 0x9e, 0xf6, 0xb4, 0x31, 0xe8, 0x76, 0xc8, 0xcd, 0x97, 0x0b, 0x0b, 0x7d, 0x83, 0xae, 0x8f, 0xf6, 0x01, 0xf7, - 0xe9, 0x20, 0xa2, 0x6a, 0xf1, 0x5d, 0x8b, 0x2f, 0x52, 0x10, 0x68, 0x89, 0x7d, 0x40, 0xde, 0xbb, 0x13, 0xe7, 0xbe, - 0x8b, 0x81, 0x1b, 0xfa, 0x07, 0x60, 0x21, 0xdd, 0x8a, 0xfb, 0xc9, 0xdb, 0x48, 0xd2, 0x0a, 0x80, 0x55, 0x9b, 0xc6, - 0x81, 0x23, 0x61, 0xfa, 0x02, 0x4b, 0xf6, 0x45, 0xce, 0x25, 0x9f, 0x14, 0x8a, 0xee, 0xf0, 0xb7, 0xf0, 0xe2, 0xf9, - 0x09, 0xe7, 0x64, 0xdd, 0xd2, 0xf1, 0x5d, 0xb5, 0x29, 0x91, 0x6a, 0xa9, 0x18, 0x24, 0x30, 0x23, 0x14, 0x39, 0x0f, - 0xd2, 0xb7, 0x17, 0xd9, 0x23, 0xfe, 0x01, 0xef, 0xf1, 0x0c, 0xdc, 0x74, 0x10, 0x26, 0xb3, 0xd9, 0x23, 0x1a, 0xaf, - 0x6f, 0x55, 0x27, 0xec, 0x02, 0x95, 0xc2, 0x68, 0x98, 0xc4, 0xf9, 0x4c, 0x95, 0x64, 0x38, 0xbe, 0xa9, 0x12, 0x52, - 0x38, 0xf1, 0x09, 0x88, 0xdb, 0x98, 0xdc, 0x8b, 0xb9, 0x12, 0xd5, 0xe9, 0xb6, 0x63, 0x68, 0xad, 0xfe, 0xfb, 0xf7, - 0x37, 0xe1, 0x7f, 0x90, 0x6c, 0xfa, 0x1b, 0x5f, 0x65, 0xe7, 0x9d, 0x13, 0xc1, 0xec, 0x21, 0x09, 0xdf, 0x38, 0xb3, - 0xac, 0x47, 0xbc, 0x26, 0x56, 0x48, 0xf7, 0xd4, 0xc9, 0xc2, 0x6e, 0x18, 0x72, 0xd5, 0x14, 0x9b, 0x4f, 0xbb, 0x54, - 0x80, 0x3e, 0xf6, 0x92, 0xad, 0x9a, 0x50, 0x4e, 0x00, 0x4a, 0x65, 0x3c, 0xb3, 0x52, 0x47, 0x83, 0x9a, 0x8d, 0xf2, - 0x32, 0x72, 0x46, 0x1f, 0x0b, 0xdd, 0x56, 0xb3, 0x20, 0x4b, 0x56, 0xe9, 0xa6, 0x86, 0x3a, 0x6b, 0xd6, 0xee, 0xcd, - 0xe7, 0xff, 0x6e, 0x3d, 0x2b, 0x13, 0x44, 0xf5, 0x46, 0x8d, 0xfe, 0xac, 0x97, 0x70, 0x45, 0x1c, 0xc7, 0xeb, 0x1d, - 0x9f, 0xd5, 0x7f, 0xb7, 0xf8, 0x47, 0xab, 0x5a, 0xf7, 0x12, 0x08, 0xcd, 0xcb, 0x5a, 0x00, 0xb3, 0x8a, 0x21, 0xbd, - 0x9e, 0x75, 0xe2, 0xc8, 0x86, 0x00, 0x7c, 0xf8, 0x13, 0xb7, 0x6b, 0xf7, 0x7e, 0x67, 0xa2, 0x6d, 0x7b, 0xe2, 0x8c, - 0x55, 0x05, 0x94, 0x27, 0xba, 0x79, 0x4c, 0x34, 0x63, 0x55, 0x77, 0x85, 0x69, 0xf6, 0x7f, 0x52, 0x4e, 0xfa, 0xcb, - 0x92, 0xb9, 0x9a, 0x11, 0x00, 0xe2, 0x34, 0x8f, 0x89, 0xaa, 0x77, 0x33, 0xed, 0xbd, 0xab, 0xe7, 0xf4, 0xda, 0xa2, - 0xb5, 0xcf, 0x64, 0x2b, 0x35, 0x8c, 0x41, 0xd7, 0x3c, 0x51, 0x7d, 0x53, 0x72, 0x19, 0x69, 0x15, 0x6d, 0xcc, 0x1b, - 0x7f, 0x6a, 0x4d, 0xae, 0xde, 0xa5, 0xae, 0x30, 0x42, 0x64, 0xd6, 0xdf, 0x19, 0xc9, 0x97, 0x37, 0x7f, 0x38, 0xb1, - 0x17, 0xcb, 0x24, 0x2c, 0x6f, 0xd4, 0x8a, 0xb0, 0x31, 0x56, 0x81, 0x85, 0x7c, 0xf9, 0x16, 0xcd, 0x34, 0x85, 0xa5, - 0x4d, 0x24, 0x67, 0x94, 0xfe, 0x28, 0x2e, 0xeb, 0x54, 0xed, 0x5d, 0x88, 0x95, 0xbd, 0x16, 0xda, 0x4f, 0x7f, 0x95, - 0xd4, 0x63, 0xd9, 0x59, 0x04, 0x9d, 0x0c, 0xa0, 0xa1, 0x5a, 0xb5, 0xe7, 0x88, 0x5d, 0x70, 0xc6, 0x66, 0xf1, 0xd2, - 0x19, 0xe6, 0x9d, 0x61, 0x10, 0x82, 0xd3, 0x24, 0xc7, 0x82, 0x9b, 0x8c, 0x73, 0x00, 0x6d, 0x55, 0xa3, 0x9e, 0xab, - 0x14, 0x4f, 0x9f, 0xf7, 0x42, 0x59, 0xf8, 0x39, 0xa0, 0xba, 0x73, 0x47, 0x12, 0x6e, 0xe1, 0xe8, 0xf8, 0x89, 0xab, - 0xe2, 0xb2, 0x86, 0xee, 0x51, 0xcc, 0x9c, 0xb7, 0xcf, 0x84, 0x2b, 0xb6, 0xe1, 0xb4, 0x12, 0xcc, 0x09, 0x00, 0xd6, - 0x4d, 0xb0, 0x6e, 0xbe, 0x81, 0xaa, 0x2e, 0x9d, 0x4b, 0x46, 0x72, 0x7d, 0x80, 0x0b, 0xe1, 0x65, 0xbe, 0xf1, 0x1e, - 0x38, 0x09, 0x2a, 0x2d, 0x78, 0x30, 0x7b, 0x0c, 0xe6, 0xd5, 0x34, 0xf8, 0x43, 0x70, 0x67, 0xa6, 0x8e, 0x50, 0x1c, - 0x79, 0x4e, 0xad, 0x97, 0xee, 0xa5, 0x1d, 0x1f, 0xac, 0x54, 0x4f, 0x9c, 0x43, 0x19, 0xd7, 0x39, 0xd8, 0x3e, 0xea, - 0xbd, 0xd0, 0x7e, 0xc1, 0xac, 0x0f, 0xbc, 0xa6, 0x09, 0x8f, 0x03, 0xaf, 0x73, 0x45, 0xb5, 0x33, 0x5a, 0xe9, 0xb5, - 0x42, 0x8c, 0x70, 0xe8, 0x14, 0xf3, 0xe7, 0x37, 0x31, 0xca, 0xa0, 0xb7, 0x28, 0xb9, 0x57, 0xb5, 0xc4, 0x69, 0xf7, - 0xbb, 0x21, 0xe9, 0xdf, 0x55, 0x40, 0xfd, 0x9f, 0x19, 0x0f, 0x77, 0xbf, 0xba, 0x97, 0xb3, 0x17, 0xd1, 0xe6, 0xcd, - 0xb8, 0xba, 0x98, 0xd1, 0x2e, 0x40, 0x69, 0x60, 0xf1, 0xad, 0x9b, 0xfd, 0x98, 0xc7, 0x59, 0x8d, 0x31, 0x86, 0x26, - 0xa1, 0xb1, 0x89, 0x60, 0x63, 0xbc, 0x49, 0x6c, 0x05, 0x2f, 0x45, 0x10, 0x8b, 0xc9, 0xe4, 0x47, 0x1d, 0x06, 0xd7, - 0x8c, 0x3c, 0xfd, 0x86, 0x14, 0xe7, 0xa2, 0x68, 0xa5, 0xc7, 0x93, 0x1f, 0xc5, 0x96, 0x84, 0x7b, 0xb5, 0xdf, 0x2c, - 0x49, 0xb9, 0xe7, 0x25, 0xa5, 0xc5, 0xba, 0x60, 0x2b, 0xd9, 0x5a, 0x6b, 0xea, 0x9f, 0xda, 0x35, 0x51, 0xd1, 0x78, - 0x1a, 0xde, 0xa8, 0x7e, 0x90, 0x5f, 0x67, 0x37, 0x36, 0x0b, 0xb9, 0x56, 0x38, 0x68, 0xfa, 0x91, 0x5e, 0x74, 0xdd, - 0x86, 0x36, 0xee, 0xf4, 0x44, 0xeb, 0x18, 0x22, 0xde, 0xc1, 0x25, 0x5e, 0x30, 0x2f, 0x47, 0xb9, 0x5d, 0xc4, 0x5c, - 0x65, 0x4e, 0xec, 0xae, 0x25, 0xf3, 0xcc, 0xa2, 0xb2, 0x3c, 0xe9, 0x34, 0x79, 0x41, 0x02, 0x49, 0x7b, 0x0e, 0x0e, - 0xc0, 0xdf, 0xd2, 0x35, 0x6f, 0x76, 0xa0, 0x6b, 0xb9, 0xe9, 0xd5, 0x21, 0xde, 0xb5, 0x1f, 0x1e, 0xc9, 0xb4, 0x8d, - 0x80, 0xc6, 0x37, 0x34, 0x0e, 0x80, 0x4c, 0x57, 0x34, 0x6d, 0x6c, 0x1c, 0x04, 0x98, 0x50, 0x91, 0xbd, 0x4b, 0x04, - 0x9c, 0x0a, 0xde, 0x07, 0x32, 0x56, 0x64, 0xd2, 0xae, 0xfd, 0xb3, 0x41, 0x26, 0x21, 0x2d, 0x64, 0xa3, 0x3e, 0x6d, - 0x6a, 0x6f, 0x26, 0xff, 0x76, 0x2b, 0x77, 0x49, 0xc5, 0xd6, 0x92, 0x9d, 0x6d, 0x41, 0x4e, 0x0b, 0x49, 0x3e, 0x56, - 0x01, 0xe1, 0x58, 0xb3, 0xd8, 0xc8, 0x0f, 0x05, 0x4f, 0x80, 0x62, 0x28, 0x5a, 0x42, 0x33, 0x76, 0xb3, 0x3d, 0xd8, - 0x5e, 0x47, 0x0f, 0x89, 0x7b, 0x40, 0xca, 0x39, 0x32, 0x17, 0x79, 0x4c, 0x77, 0xef, 0x6c, 0x5b, 0x8f, 0xad, 0x6b, - 0xf1, 0x59, 0x1d, 0x6c, 0x6e, 0xbd, 0xa2, 0xca, 0xff, 0x3f, 0x74, 0x35, 0x7f, 0x1e, 0x07, 0x70, 0xf0, 0xee, 0x83, - 0x4e, 0x21, 0xb5, 0xa1, 0x56, 0x6f, 0xb7, 0x35, 0x51, 0x88, 0x26, 0x7a, 0xfe, 0x58, 0xb1, 0x4a, 0x2f, 0x31, 0xca, - 0xc2, 0x97, 0x54, 0xe2, 0x74, 0xbb, 0xfc, 0xa9, 0x4b, 0x86, 0xb3, 0xab, 0x64, 0xfd, 0xd9, 0x30, 0x8f, 0x7e, 0x13, - 0x43, 0x5c, 0xe5, 0xc5, 0x6d, 0x04, 0x43, 0x28, 0xf4, 0xd8, 0xf9, 0x07, 0x74, 0x52, 0xd6, 0x7c, 0x22, 0x81, 0x62, - 0x79, 0xaa, 0x0c, 0x0d, 0x28, 0xd2, 0xdb, 0x0c, 0x51, 0x4d, 0x14, 0xa3, 0x9d, 0xb5, 0x42, 0x90, 0x46, 0x37, 0xfa, - 0x2f, 0x03, 0x9b, 0x34, 0xcb, 0xea, 0x73, 0xe2, 0x04, 0xd9, 0xbe, 0x3b, 0xe9, 0x33, 0x96, 0x0b, 0xbe, 0x1e, 0xc7, - 0x65, 0x23, 0x78, 0x1b, 0x8a, 0xd0, 0x39, 0x66, 0x50, 0x9b, 0x3a, 0xaf, 0xda, 0x19, 0x42, 0x39, 0x8e, 0x03, 0xb9, - 0xa6, 0xa5, 0xdd, 0x01, 0x5a, 0xc4, 0x73, 0x9e, 0x4e, 0xf0, 0x98, 0xa4, 0xf9, 0x3e, 0x07, 0x79, 0x37, 0x09, 0x82, - 0x26, 0xfa, 0xba, 0x83, 0x0b, 0xf2, 0x58, 0xd1, 0xb5, 0x83, 0xd9, 0x1b, 0xeb, 0xef, 0xea, 0xb0, 0x88, 0xe7, 0x18, - 0x42, 0xc6, 0x0d, 0x29, 0x72, 0xc5, 0xdd, 0xac, 0x54, 0x99, 0xc2, 0xcb, 0x85, 0x1f, 0x98, 0x07, 0xb6, 0xad, 0x3a, - 0xa2, 0x66, 0x27, 0x71, 0x95, 0x1a, 0xed, 0xe9, 0xf7, 0x69, 0x9b, 0x58, 0xa3, 0xe3, 0x33, 0xe3, 0xd7, 0xe8, 0xa3, - 0xf6, 0xe2, 0xb1, 0x06, 0xe6, 0x22, 0x8b, 0x12, 0xf6, 0x25, 0xc8, 0x39, 0x52, 0x4c, 0x7d, 0xef, 0x26, 0x96, 0xfe, - 0x0c, 0x6c, 0xd0, 0x5e, 0xd3, 0x4a, 0xaa, 0x0f, 0xdc, 0xa0, 0xdf, 0x1e, 0x0d, 0x1a, 0xf4, 0x12, 0xcf, 0x30, 0x77, - 0x09, 0x1e, 0xdf, 0xcc, 0x29, 0x51, 0xbf, 0x03, 0xf2, 0x72, 0xac, 0xc1, 0x16, 0x0b, 0xc2, 0x02, 0xc2, 0x88, 0xda, - 0xaf, 0xf7, 0x5f, 0x6a, 0xde, 0xe5, 0xeb, 0x39, 0x42, 0xac, 0x60, 0x3f, 0xa2, 0x9c, 0x8c, 0x77, 0x2a, 0x9a, 0x99, - 0x7b, 0x66, 0xde, 0xdf, 0xf3, 0x74, 0x4f, 0x37, 0x37, 0xf3, 0x4a, 0xeb, 0xb3, 0xee, 0xa9, 0x3e, 0x55, 0x91, 0x26, - 0x66, 0xf5, 0x65, 0x87, 0xf2, 0xc1, 0x3c, 0xb8, 0x73, 0x95, 0xed, 0xdc, 0x01, 0x1d, 0x74, 0xd6, 0x1d, 0xfc, 0x30, - 0xf7, 0x8a, 0x0f, 0x4d, 0x81, 0xd3, 0xff, 0x97, 0x80, 0x87, 0x06, 0x43, 0xd1, 0x92, 0x66, 0x8a, 0x79, 0x0d, 0x36, - 0x2f, 0xb4, 0x58, 0x89, 0x8d, 0xfb, 0x3d, 0x8d, 0xc7, 0x36, 0x9f, 0x2b, 0x94, 0x3d, 0xfc, 0x67, 0x0f, 0x05, 0x94, - 0xc5, 0x51, 0xcc, 0xce, 0x66, 0xa1, 0xa2, 0xd8, 0x25, 0xc0, 0x14, 0xc1, 0x77, 0x97, 0x2c, 0x36, 0x73, 0x42, 0x9b, - 0xaf, 0x60, 0xad, 0xe9, 0xd3, 0xc4, 0x74, 0xbe, 0x0a, 0x41, 0x05, 0xb3, 0x58, 0x33, 0xbc, 0x24, 0xe9, 0xa1, 0x23, - 0x35, 0xed, 0x63, 0x46, 0x3d, 0x35, 0x94, 0xd1, 0xd6, 0xfd, 0xad, 0xa7, 0x14, 0x1e, 0x49, 0x93, 0x0b, 0x5d, 0x93, - 0x50, 0x00, 0xff, 0x4f, 0xb5, 0x91, 0x4a, 0x93, 0x89, 0xb0, 0x59, 0x55, 0x64, 0xcb, 0xe9, 0xc8, 0x3f, 0xfe, 0xaa, - 0xd6, 0xc5, 0x90, 0xf8, 0xe1, 0x44, 0xdd, 0x93, 0x98, 0x83, 0x1c, 0xb4, 0x38, 0x85, 0x19, 0x68, 0x8d, 0x6c, 0x9b, - 0xa3, 0x9a, 0x25, 0x79, 0x79, 0x27, 0x81, 0xa7, 0x87, 0x26, 0xfa, 0xd5, 0x57, 0x69, 0xdb, 0xac, 0x3d, 0xef, 0x82, - 0x74, 0x00, 0xe1, 0xe0, 0x98, 0x19, 0x2f, 0x36, 0x7a, 0x7b, 0x09, 0xbe, 0xdf, 0x47, 0xb5, 0xb3, 0x0b, 0x94, 0x09, - 0xb5, 0x6f, 0x74, 0xe8, 0xf5, 0x6d, 0xae, 0x39, 0x61, 0x37, 0xa6, 0x32, 0xff, 0x28, 0x34, 0x4f, 0x67, 0xa5, 0xc7, - 0xc7, 0xdf, 0xa9, 0x9d, 0xe8, 0x18, 0x45, 0x4b, 0x82, 0xc4, 0xde, 0x82, 0x6a, 0xb4, 0xac, 0x35, 0xdb, 0x58, 0xf8, - 0x4c, 0x86, 0x05, 0xc6, 0x04, 0xdf, 0x26, 0xf3, 0xfe, 0x86, 0x48, 0x08, 0xf3, 0x85, 0x50, 0x1c, 0x4c, 0xdd, 0x69, - 0xbc, 0xd2, 0x5c, 0x2a, 0x5b, 0xd3, 0x25, 0xfe, 0xc1, 0xcc, 0x82, 0x42, 0xe6, 0x13, 0x05, 0xbf, 0xcc, 0xe1, 0xb8, - 0x6b, 0x84, 0xad, 0x67, 0x50, 0xf0, 0x81, 0x39, 0x0c, 0x10, 0x29, 0x8c, 0x6e, 0xeb, 0x29, 0x1e, 0x20, 0xb3, 0x2e, - 0x43, 0x9a, 0x61, 0xbf, 0x09, 0x18, 0x81, 0x57, 0x94, 0x37, 0x2b, 0xa0, 0xbc, 0x91, 0xe6, 0x6d, 0x57, 0x1e, 0x01, - 0xca, 0x5d, 0x48, 0x3a, 0x28, 0xa1, 0x17, 0x53, 0xfb, 0xa0, 0xb2, 0x7a, 0x82, 0x56, 0x31, 0x93, 0x1b, 0xac, 0xe6, - 0x46, 0x90, 0x49, 0x42, 0x1c, 0x9f, 0xd3, 0x80, 0xe1, 0x4e, 0xc2, 0x0b, 0xc4, 0x1c, 0x46, 0x04, 0xe9, 0xe4, 0x76, - 0xde, 0x2a, 0x53, 0x74, 0xe5, 0x42, 0xda, 0x22, 0x59, 0xe6, 0xa3, 0x06, 0xf2, 0x59, 0x82, 0x05, 0xf0, 0x0f, 0x0c, - 0x8a, 0x3d, 0x12, 0x36, 0x73, 0x2c, 0xb9, 0x86, 0x41, 0xa4, 0xf4, 0xf4, 0x56, 0x99, 0xa2, 0x0e, 0x57, 0x54, 0x42, - 0xc8, 0x0c, 0x98, 0xe0, 0x4b, 0x38, 0xbe, 0xd5, 0xa0, 0xc1, 0xd0, 0x9d, 0x82, 0xda, 0x67, 0xc0, 0x49, 0x53, 0x6a, - 0x96, 0xc4, 0x9e, 0x52, 0xf8, 0xd3, 0x8c, 0x45, 0xd8, 0x34, 0x0f, 0x94, 0xef, 0x9a, 0xa9, 0x62, 0xc1, 0x1b, 0xf9, - 0x13, 0xf8, 0x0e, 0x93, 0xae, 0x28, 0x81, 0xef, 0xe3, 0x61, 0xbc, 0xc3, 0x28, 0xc4, 0x3f, 0x66, 0xba, 0x0d, 0x09, - 0xcb, 0x62, 0x86, 0x00, 0xa4, 0xdf, 0xb8, 0x2b, 0x3e, 0x2c, 0xcf, 0x9a, 0x49, 0xe2, 0xd6, 0xef, 0xf7, 0xff, 0x69, - 0x20, 0xb3, 0x0f, 0x3d, 0x91, 0xcd, 0xe6, 0x30, 0x06, 0x14, 0x9d, 0x4c, 0xd8, 0xa3, 0x71, 0xe2, 0x41, 0x01, 0xd7, - 0xa3, 0x73, 0x5d, 0x49, 0x6d, 0x3d, 0xc4, 0x7b, 0x10, 0x26, 0xac, 0xac, 0x1a, 0xc5, 0xb3, 0xbf, 0x6f, 0xba, 0xe9, - 0xd4, 0x71, 0xa0, 0x80, 0xd9, 0x5f, 0x77, 0xaa, 0x43, 0x77, 0x77, 0x83, 0xc4, 0xb5, 0x44, 0xdb, 0x70, 0xc4, 0xfb, - 0xa1, 0x01, 0x4c, 0xd9, 0xc9, 0x79, 0x71, 0x1e, 0xa6, 0x97, 0xbf, 0x1c, 0x3a, 0x2a, 0x39, 0xeb, 0x12, 0x91, 0x49, - 0xb6, 0x92, 0x6c, 0xc6, 0x5e, 0xcc, 0xad, 0x8c, 0xfe, 0x84, 0x27, 0xe8, 0xac, 0xf3, 0x30, 0x0a, 0x0a, 0x15, 0xe1, - 0x2d, 0x80, 0xc2, 0x59, 0xb6, 0xe9, 0x74, 0xf0, 0x5a, 0xc4, 0x34, 0x08, 0xd7, 0x75, 0x07, 0x54, 0xfa, 0x96, 0x92, - 0x21, 0x33, 0x05, 0x70, 0x11, 0xc5, 0x58, 0x8c, 0x04, 0xa5, 0x8c, 0x23, 0x0e, 0x95, 0xf5, 0xed, 0xe6, 0x48, 0x61, - 0x10, 0x7d, 0xb4, 0x43, 0xd7, 0xa1, 0x45, 0xd1, 0x7f, 0x8b, 0x45, 0xc8, 0xf7, 0x14, 0xa7, 0x84, 0x9b, 0x34, 0x35, - 0xf9, 0xa1, 0x0f, 0x2f, 0x60, 0x71, 0x06, 0x46, 0x77, 0x67, 0xb7, 0x3c, 0x8a, 0xbb, 0x1b, 0xfa, 0x18, 0x7e, 0xd1, - 0xcf, 0x32, 0x3b, 0xa7, 0xa6, 0xf0, 0x55, 0xec, 0xe2, 0x7b, 0x22, 0x90, 0x63, 0xce, 0x36, 0xcc, 0xf3, 0x0f, 0xb6, - 0xaf, 0x05, 0x89, 0xd5, 0xad, 0xc0, 0x29, 0x05, 0xdb, 0x7a, 0xa5, 0x01, 0x9d, 0x5d, 0x89, 0xf0, 0xfe, 0x8d, 0xef, - 0x81, 0x16, 0x51, 0x49, 0x76, 0x8a, 0x47, 0x4e, 0x7f, 0x0b, 0xe2, 0xcc, 0x81, 0x9c, 0xa2, 0x7a, 0x32, 0x82, 0x5e, - 0x40, 0x5b, 0x3e, 0x8f, 0x2e, 0x39, 0x19, 0xd6, 0x45, 0xf9, 0x44, 0x7b, 0x8e, 0xc9, 0xce, 0xa2, 0x14, 0x86, 0xa4, - 0xf4, 0x3d, 0xcc, 0x06, 0x07, 0x20, 0x3b, 0xaa, 0x7e, 0x58, 0x24, 0x61, 0xf3, 0xce, 0x24, 0x33, 0x17, 0x21, 0x39, - 0xa7, 0xf5, 0xca, 0xbd, 0x88, 0xcc, 0x5c, 0x3b, 0x8a, 0xb2, 0x8e, 0xab, 0x49, 0xd2, 0xcd, 0x66, 0x96, 0x3a, 0xa5, - 0x1a, 0x63, 0x24, 0x21, 0xa3, 0x13, 0xaf, 0x7a, 0x91, 0x94, 0x41, 0xd6, 0x44, 0xc5, 0xb2, 0xa6, 0x21, 0x59, 0x04, - 0xf4, 0x21, 0xf6, 0xba, 0xa8, 0x5c, 0xd4, 0xae, 0xa2, 0x55, 0xa9, 0xb2, 0x73, 0x50, 0xcf, 0x73, 0x13, 0xf4, 0x40, - 0xca, 0x26, 0xbb, 0xdf, 0x6e, 0x45, 0x97, 0x90, 0x43, 0x67, 0x38, 0xad, 0x66, 0x20, 0x8c, 0x97, 0xb1, 0xd6, 0xb1, - 0x2f, 0x50, 0xd4, 0xc0, 0xb5, 0xd3, 0xa0, 0xcb, 0xdb, 0xad, 0xd1, 0xc5, 0xe4, 0x51, 0x60, 0x4a, 0x56, 0xe5, 0xd2, - 0x54, 0xe1, 0x6c, 0x9e, 0x5f, 0xf6, 0x77, 0xc6, 0xb7, 0x5d, 0x3a, 0x0e, 0x54, 0x30, 0xc3, 0xbb, 0x60, 0x0f, 0x13, - 0xaf, 0x71, 0x82, 0x9c, 0x98, 0x3a, 0xf6, 0x11, 0x21, 0xd1, 0x56, 0xff, 0x7a, 0xad, 0x99, 0xf9, 0x63, 0x3f, 0xa6, - 0xdc, 0x3d, 0xd0, 0xcb, 0x91, 0xdd, 0x6c, 0xe1, 0xa5, 0x7c, 0x58, 0x42, 0x7c, 0xe1, 0x6c, 0x2e, 0xdd, 0x66, 0xe8, - 0xd2, 0xe7, 0x2f, 0x87, 0x31, 0x15, 0x5b, 0x22, 0x39, 0x1c, 0x88, 0xcd, 0xed, 0x3a, 0x27, 0x49, 0x14, 0xf0, 0x3e, - 0xcf, 0x11, 0x01, 0xcf, 0x5c, 0xf6, 0x9c, 0x49, 0x94, 0x16, 0xe9, 0x68, 0xa4, 0x4f, 0xc7, 0xa0, 0xe2, 0x53, 0xa1, - 0x84, 0xc1, 0x7d, 0x66, 0x13, 0x83, 0xfc, 0xf9, 0xb1, 0x48, 0xb7, 0xa9, 0x31, 0x6c, 0xf8, 0x0a, 0x6e, 0x15, 0x54, - 0x7e, 0xff, 0x13, 0x8d, 0xbb, 0xe6, 0x87, 0xd5, 0xd1, 0x7b, 0xfc, 0x5c, 0x41, 0x1b, 0x3c, 0xba, 0x3a, 0x0f, 0xdb, - 0x78, 0x07, 0x80, 0xe6, 0xdc, 0x16, 0x4c, 0x11, 0x6c, 0xbc, 0x75, 0x89, 0x5f, 0x86, 0xa4, 0xd6, 0xf8, 0x84, 0x40, - 0x7d, 0x36, 0xcc, 0xc3, 0xe4, 0x7d, 0xf2, 0x23, 0x1c, 0x99, 0x67, 0xa7, 0x04, 0xbc, 0x51, 0x76, 0xe5, 0x91, 0x7e, - 0x94, 0xa7, 0xbb, 0x2f, 0xbe, 0x9f, 0x5b, 0x58, 0x7f, 0x80, 0xe3, 0xf8, 0x45, 0xfd, 0xfd, 0xf0, 0x90, 0xed, 0x0f, - 0x5b, 0xff, 0xfd, 0x89, 0x92, 0xdf, 0x2a, 0x0d, 0xde, 0xfc, 0xf1, 0x42, 0x08, 0x4e, 0x0d, 0x6a, 0x98, 0xc5, 0xc8, - 0x70, 0xe9, 0x17, 0x51, 0x8a, 0x49, 0xd6, 0x18, 0xad, 0xa4, 0xa5, 0x85, 0xf7, 0x4a, 0x9b, 0xb3, 0x2b, 0xb7, 0x57, - 0x05, 0x71, 0x67, 0x69, 0xea, 0x83, 0x02, 0x93, 0x51, 0x45, 0xe0, 0x48, 0xa1, 0x6a, 0x2d, 0x61, 0x91, 0xfa, 0x8d, - 0x80, 0xae, 0xd5, 0x6b, 0x65, 0x60, 0x9c, 0xaf, 0x77, 0xb6, 0xc9, 0x3c, 0x23, 0x5b, 0xd0, 0x3c, 0xf2, 0xd2, 0x9a, - 0xb7, 0x22, 0xaa, 0xaa, 0xd6, 0x1d, 0xb6, 0x7a, 0x11, 0x23, 0xd6, 0xdd, 0x3c, 0x05, 0xc6, 0x3b, 0xc2, 0x03, 0xdc, - 0xdc, 0x30, 0x0a, 0xed, 0x56, 0x4f, 0xca, 0xd3, 0xec, 0xdd, 0x21, 0xdd, 0x68, 0x32, 0x85, 0xc6, 0x82, 0x2d, 0x5d, - 0x45, 0x87, 0xc4, 0x31, 0xe5, 0x90, 0x90, 0x33, 0xb4, 0x6f, 0xb0, 0x64, 0xd3, 0xa9, 0xda, 0x0c, 0xd7, 0x68, 0xc7, - 0x13, 0x0d, 0x31, 0x1d, 0x74, 0x45, 0x3a, 0x44, 0x0f, 0xc0, 0x14, 0x33, 0x9e, 0x26, 0x1d, 0x2d, 0xec, 0xae, 0xd5, - 0x88, 0x33, 0x4a, 0x07, 0xa3, 0x81, 0x51, 0xa2, 0xab, 0xe8, 0xf5, 0x0d, 0x42, 0xe7, 0x44, 0x76, 0x7b, 0xca, 0x5b, - 0xa5, 0x86, 0xf5, 0x99, 0xa1, 0x75, 0xa9, 0x12, 0x61, 0xa5, 0x38, 0xb1, 0xec, 0xae, 0x4c, 0xfb, 0x4a, 0x8b, 0xab, - 0xdc, 0xd0, 0xb6, 0x01, 0x50, 0x3d, 0x2d, 0xf1, 0x7a, 0xf2, 0x9a, 0xaf, 0xf6, 0xf4, 0xa4, 0x4d, 0x9f, 0x5b, 0x50, - 0xd3, 0x2e, 0x05, 0xe6, 0xf5, 0x6e, 0xa3, 0xee, 0x2b, 0xd3, 0xf0, 0xae, 0x2a, 0x26, 0x89, 0xbf, 0xb4, 0x0f, 0x71, - 0xa5, 0x43, 0xd2, 0xb0, 0x17, 0x5d, 0xc1, 0x6a, 0x71, 0x09, 0x9b, 0xf2, 0x04, 0x04, 0x46, 0x4b, 0x5a, 0x52, 0x70, - 0x83, 0xaa, 0xa2, 0xaf, 0x84, 0x57, 0xcf, 0xa7, 0xd3, 0x14, 0xac, 0xfb, 0xcd, 0xc4, 0x26, 0x8b, 0x3e, 0xcf, 0x5d, - 0x59, 0x73, 0xde, 0x1b, 0x1e, 0x55, 0x1d, 0xdb, 0x9c, 0x02, 0x74, 0xb7, 0xd3, 0x16, 0xda, 0xe2, 0x47, 0xb6, 0xc9, - 0x34, 0x6a, 0xad, 0x15, 0x95, 0xfc, 0xcc, 0x3b, 0xae, 0xfc, 0x2b, 0x65, 0xab, 0x02, 0xd5, 0x26, 0x24, 0x26, 0xe6, - 0xa3, 0x15, 0x88, 0x1d, 0x74, 0x3e, 0xe6, 0x2f, 0x74, 0x95, 0x2c, 0xce, 0x78, 0x6e, 0x72, 0x64, 0x52, 0x63, 0x78, - 0x68, 0x42, 0xd1, 0xf6, 0x71, 0xb0, 0xe9, 0x60, 0xed, 0x2f, 0xe9, 0xd4, 0xbc, 0x26, 0x0a, 0xfe, 0x9c, 0x08, 0x3b, - 0x41, 0xe3, 0xcb, 0x98, 0xe8, 0xd2, 0xe6, 0xa7, 0xfc, 0xad, 0xdb, 0x07, 0xd9, 0x7a, 0x05, 0xab, 0xf5, 0xd0, 0xea, - 0xf6, 0xec, 0x22, 0x3c, 0x37, 0x44, 0x59, 0x9f, 0x72, 0x8d, 0x79, 0xbd, 0x8a, 0x0d, 0x24, 0x8f, 0xc8, 0x41, 0x85, - 0x57, 0x4e, 0x3f, 0x06, 0x05, 0xe0, 0xe7, 0x4d, 0x76, 0x84, 0x5f, 0xb5, 0x30, 0x0f, 0xfb, 0x04, 0x56, 0x8e, 0x07, - 0x8f, 0x6e, 0x3a, 0x73, 0x5e, 0x43, 0x58, 0x20, 0x7f, 0x39, 0x4f, 0xc6, 0x23, 0xc6, 0xb2, 0x43, 0xea, 0x8a, 0xb4, - 0x27, 0x00, 0x90, 0x52, 0x34, 0x1c, 0x44, 0xc5, 0xc6, 0xc9, 0x0f, 0x94, 0xa6, 0x05, 0x44, 0x81, 0x3a, 0x9d, 0x71, - 0x0c, 0xd4, 0x0d, 0xda, 0xb1, 0x6d, 0x66, 0x4b, 0x8d, 0xc5, 0x6b, 0xb4, 0x9f, 0x9a, 0xf4, 0x2c, 0xba, 0x04, 0x6f, - 0xd1, 0x22, 0xc6, 0x2f, 0xc6, 0xb4, 0x66, 0x8b, 0x1b, 0xfd, 0xc4, 0x4e, 0xc0, 0x8d, 0xd1, 0x6d, 0x9c, 0xdd, 0xb2, - 0xb3, 0x44, 0xa5, 0x37, 0xdf, 0x40, 0xf0, 0xae, 0xb7, 0x5b, 0xbb, 0xb1, 0xd2, 0xfe, 0x33, 0x05, 0xe3, 0x2a, 0x99, - 0x1b, 0x88, 0x20, 0x55, 0x8f, 0x96, 0xfc, 0x59, 0x20, 0xb1, 0xf5, 0x5c, 0xda, 0x5a, 0x00, 0x83, 0xef, 0xf6, 0xe1, - 0x35, 0xd3, 0xb3, 0x96, 0xc3, 0x6a, 0xf0, 0xbd, 0x6f, 0xdf, 0x8c, 0xd6, 0xc7, 0x74, 0xb7, 0xbd, 0xdb, 0xc7, 0x0e, - 0x7d, 0x52, 0x4a, 0x89, 0x1b, 0x00, 0xce, 0x7d, 0xbe, 0x83, 0x49, 0xb6, 0xd9, 0x6b, 0x96, 0x0a, 0x9e, 0xab, 0xdd, - 0x9e, 0x30, 0x40, 0xdc, 0xcf, 0xb9, 0xde, 0x48, 0x18, 0xc1, 0x31, 0xe7, 0x75, 0xf3, 0x92, 0x64, 0xcc, 0x20, 0x8d, - 0x8d, 0xa1, 0x83, 0xba, 0xb6, 0x15, 0xb0, 0x20, 0xca, 0x89, 0x0b, 0x3e, 0x2d, 0x86, 0x0d, 0x22, 0x95, 0x19, 0x4d, - 0x44, 0x41, 0x35, 0x44, 0xf7, 0x72, 0xf0, 0xda, 0x81, 0x8e, 0x13, 0x07, 0x03, 0xe6, 0x5f, 0x7d, 0x02, 0xdb, 0xc7, - 0x0e, 0xb7, 0x07, 0x85, 0x38, 0xf6, 0x82, 0xa4, 0x22, 0x9d, 0xb6, 0x2e, 0x99, 0xeb, 0xe0, 0xad, 0xab, 0x96, 0x66, - 0x6f, 0xaa, 0x0f, 0xd4, 0xd7, 0xd0, 0xe3, 0x78, 0xea, 0xe7, 0x83, 0xb9, 0x03, 0xab, 0xa2, 0x2e, 0xca, 0x04, 0xc0, - 0x75, 0x6d, 0x28, 0x6d, 0x6b, 0x20, 0x60, 0x33, 0x79, 0x5a, 0x49, 0xe6, 0x0a, 0x2f, 0xe7, 0x66, 0xf3, 0x33, 0x9f, - 0x23, 0xf4, 0x9a, 0xf7, 0xab, 0xb7, 0xaa, 0xf6, 0x79, 0x69, 0x1e, 0x9e, 0xaa, 0x42, 0x05, 0xaa, 0x59, 0x67, 0xec, - 0x79, 0x06, 0x1b, 0x24, 0xc8, 0xd6, 0xb8, 0xed, 0xe3, 0xe1, 0x6f, 0x26, 0x16, 0xd3, 0x85, 0x6d, 0xe8, 0x25, 0x26, - 0x6f, 0xbf, 0xcb, 0x6c, 0x01, 0xa4, 0x48, 0x49, 0x7d, 0xc6, 0x97, 0x8c, 0x68, 0x52, 0xaf, 0x97, 0x5a, 0xd5, 0xf8, - 0x48, 0xab, 0x56, 0xfb, 0x07, 0x86, 0xac, 0x9f, 0x7f, 0xf4, 0x4f, 0xc6, 0x6e, 0x2f, 0xfe, 0x7d, 0xf3, 0xe4, 0xb5, - 0xdb, 0xc7, 0xd6, 0x62, 0xeb, 0x3f, 0x76, 0x26, 0xea, 0x86, 0x9e, 0xe7, 0xb5, 0x7f, 0xb7, 0x0a, 0x34, 0x78, 0x4f, - 0x85, 0x2f, 0x0c, 0x83, 0x3b, 0xf9, 0x66, 0x80, 0x17, 0x90, 0xad, 0xcc, 0xa2, 0xad, 0x83, 0x6b, 0x5c, 0xe3, 0xff, - 0xb8, 0x42, 0x8c, 0xe9, 0xa5, 0xda, 0x78, 0x80, 0xfe, 0xbc, 0xa3, 0xe5, 0xa6, 0xc1, 0xb7, 0x1d, 0x36, 0x65, 0x9e, - 0x89, 0x0b, 0xeb, 0x87, 0x75, 0x4a, 0x9a, 0x6b, 0x8e, 0xd7, 0x4d, 0xe7, 0xdd, 0x25, 0x8f, 0xa6, 0x30, 0xe0, 0x32, - 0x97, 0xa1, 0xdb, 0x5c, 0x38, 0x74, 0xbe, 0x89, 0xad, 0x9f, 0x54, 0xa2, 0xd2, 0x54, 0x02, 0x55, 0xfd, 0xda, 0x52, - 0x45, 0x19, 0xea, 0xd8, 0xfa, 0xb7, 0x0d, 0x2f, 0x56, 0xe5, 0xde, 0xc4, 0x03, 0xcc, 0xc8, 0x56, 0x20, 0x86, 0x0b, - 0x7e, 0x86, 0xa9, 0x35, 0xae, 0x1c, 0x68, 0xcc, 0x0e, 0xff, 0x8b, 0x48, 0x2a, 0x41, 0x40, 0x5b, 0x38, 0xd8, 0xc7, - 0xcc, 0xb8, 0x27, 0x3a, 0xa6, 0x0e, 0x3a, 0xb3, 0x93, 0x0f, 0x4e, 0x71, 0xf0, 0x5d, 0xbb, 0xdb, 0xa1, 0xdb, 0x0c, - 0xdb, 0x3b, 0x45, 0x4f, 0x9d, 0x14, 0x5b, 0x49, 0xe1, 0xae, 0xae, 0xa8, 0x1d, 0xe9, 0x74, 0xbe, 0x76, 0x57, 0x08, - 0x6a, 0x76, 0x05, 0xd1, 0x34, 0xbe, 0x36, 0x9e, 0x68, 0x72, 0xf0, 0x17, 0xfe, 0x25, 0x24, 0xf0, 0x65, 0x6f, 0x62, - 0x90, 0xbe, 0xce, 0xd0, 0x5d, 0xba, 0x8a, 0xee, 0x42, 0xba, 0xaa, 0x1f, 0x61, 0x15, 0xb3, 0x1f, 0xc1, 0x7d, 0xa2, - 0xf7, 0xe2, 0xcd, 0x86, 0xa1, 0xb1, 0xc2, 0x64, 0x68, 0x73, 0x1b, 0x32, 0xcc, 0xf9, 0x6d, 0x48, 0xd1, 0xc6, 0xa6, - 0x1b, 0x90, 0x57, 0xe4, 0x64, 0x76, 0x4d, 0x94, 0x4d, 0x97, 0x2e, 0x22, 0x38, 0x08, 0xf7, 0xa1, 0x9a, 0xd0, 0x9e, - 0x3d, 0x09, 0x3e, 0xcd, 0xca, 0x34, 0x61, 0xa9, 0xe6, 0x72, 0x5c, 0x20, 0x33, 0xd9, 0xc4, 0x00, 0xe6, 0xc3, 0xd8, - 0xe5, 0xb3, 0xc7, 0x1d, 0xd8, 0x7b, 0xb1, 0xe3, 0xa1, 0xdb, 0x1e, 0x94, 0xed, 0xa3, 0x83, 0xd5, 0xe7, 0xf3, 0xfe, - 0x2a, 0xb3, 0xdd, 0xeb, 0xbd, 0x74, 0x1b, 0x66, 0xe9, 0x31, 0xcf, 0x66, 0x8b, 0xa5, 0x9e, 0xdf, 0x20, 0xaf, 0x66, - 0xa7, 0x4a, 0x71, 0x29, 0x9e, 0x00, 0xf0, 0xbb, 0xac, 0xe1, 0x07, 0x92, 0x16, 0xcf, 0xea, 0xf4, 0xfc, 0x48, 0x9b, - 0xb6, 0x92, 0xc5, 0x10, 0x10, 0x9d, 0xca, 0x29, 0xea, 0xc6, 0xd6, 0x66, 0x50, 0xa4, 0xd3, 0xee, 0xcc, 0x66, 0x48, - 0xe1, 0x59, 0xf9, 0xcf, 0x66, 0xce, 0x3e, 0x74, 0xd2, 0xa0, 0xdc, 0x1e, 0x1c, 0xdc, 0x2a, 0x95, 0x49, 0x47, 0xa2, - 0xf0, 0x52, 0x51, 0x20, 0x44, 0x10, 0xe7, 0x41, 0xaf, 0xbc, 0xa4, 0x35, 0xa2, 0x62, 0x4d, 0x88, 0x1f, 0xb5, 0x06, - 0xd7, 0xe0, 0xd6, 0xfe, 0xf6, 0x3c, 0xc0, 0x0d, 0x1c, 0x72, 0x94, 0xf7, 0x29, 0xcf, 0x9b, 0xdc, 0xb1, 0xa2, 0xfb, - 0x89, 0xc1, 0x5c, 0x03, 0x03, 0x2a, 0x29, 0xdf, 0x2b, 0x6e, 0xc6, 0x98, 0x3f, 0xfd, 0x7e, 0x15, 0xc2, 0x4a, 0x7d, - 0xb1, 0xca, 0x61, 0x07, 0xe4, 0xdb, 0xaf, 0x20, 0x68, 0x51, 0x36, 0x51, 0xf8, 0x9a, 0xaf, 0xf0, 0xec, 0xd6, 0x66, - 0xa9, 0xff, 0xc7, 0x3d, 0x49, 0xcd, 0x5c, 0xfc, 0xbb, 0x4b, 0x47, 0x8d, 0x6f, 0x36, 0x7e, 0xa5, 0x5b, 0x99, 0xd5, - 0x48, 0x51, 0xd6, 0xae, 0xc9, 0x46, 0xf3, 0x33, 0x30, 0x4e, 0xd0, 0x8b, 0xaf, 0xd8, 0x81, 0x9f, 0x77, 0x49, 0xaa, - 0xd2, 0xad, 0xa5, 0x9f, 0xfb, 0x2b, 0xc9, 0x78, 0xca, 0xe8, 0x57, 0x19, 0x6e, 0x14, 0x34, 0x27, 0x5f, 0xfa, 0x3f, - 0x0c, 0xe0, 0x1d, 0x28, 0xc3, 0xd9, 0x0a, 0x7f, 0xad, 0xe3, 0x2e, 0x7e, 0xdd, 0x85, 0x9b, 0xf9, 0xb2, 0x11, 0x06, - 0xda, 0x43, 0x20, 0xa7, 0xea, 0xf7, 0x39, 0x9e, 0xb8, 0x0c, 0xd3, 0x99, 0x26, 0xbc, 0x8a, 0x82, 0xe5, 0xce, 0x7b, - 0xed, 0x9b, 0x34, 0x1b, 0x8f, 0x17, 0x24, 0x16, 0x27, 0x78, 0x45, 0xd8, 0xea, 0x42, 0xc9, 0xb7, 0xb9, 0x85, 0xa6, - 0xc0, 0x2b, 0xdd, 0xec, 0x41, 0xda, 0x2f, 0x93, 0x9d, 0x25, 0xab, 0x9e, 0x33, 0x84, 0x11, 0x1b, 0x7b, 0x74, 0x95, - 0x26, 0xf5, 0x59, 0x69, 0x8d, 0x36, 0x34, 0x63, 0x4d, 0xa7, 0xe6, 0x72, 0x40, 0xaa, 0x55, 0xb5, 0xc2, 0x59, 0x57, - 0xb9, 0xc0, 0x36, 0x73, 0x4a, 0xd1, 0x67, 0x07, 0x05, 0x9e, 0x25, 0xac, 0xeb, 0x1c, 0xb8, 0x86, 0x12, 0x0d, 0xce, - 0x6b, 0x76, 0xdb, 0x80, 0xac, 0x44, 0x7e, 0x61, 0x40, 0x09, 0x1b, 0x8f, 0x7f, 0xb1, 0x43, 0xf1, 0xed, 0xd9, 0x6a, - 0x19, 0xc1, 0xc8, 0x8a, 0x49, 0xfd, 0x9d, 0x23, 0xb1, 0x3f, 0x3f, 0xa3, 0xb4, 0xb7, 0x5c, 0x4c, 0xa8, 0x5b, 0x36, - 0xab, 0xd8, 0x6f, 0xa5, 0x84, 0xa3, 0x69, 0xaa, 0x96, 0x78, 0x7a, 0x1f, 0x29, 0xab, 0xd6, 0x5b, 0xc0, 0x06, 0x2d, - 0xaa, 0x36, 0x22, 0x5e, 0x30, 0x21, 0x7e, 0xff, 0xc1, 0x46, 0x80, 0x47, 0xa4, 0x64, 0xb2, 0xe5, 0x38, 0xab, 0x14, - 0xc3, 0xf9, 0xe6, 0x63, 0xb3, 0x5d, 0x4f, 0x58, 0xe4, 0x23, 0x8c, 0x58, 0xb7, 0x54, 0xc1, 0xba, 0x1f, 0xf6, 0x24, - 0xf5, 0xe8, 0x39, 0x3a, 0xc2, 0x61, 0x54, 0x41, 0x2b, 0x7a, 0x73, 0xf6, 0x0a, 0x49, 0x53, 0xc8, 0x44, 0x90, 0x7c, - 0x18, 0x97, 0x62, 0xc8, 0xad, 0x7d, 0x23, 0x4f, 0x95, 0xef, 0x1b, 0x30, 0x54, 0xde, 0xb7, 0x84, 0x26, 0xc8, 0x9a, - 0x9f, 0xa2, 0xa2, 0xe7, 0xce, 0x6e, 0x45, 0xb0, 0x5a, 0x74, 0x72, 0x52, 0x95, 0x69, 0x7e, 0x02, 0xa1, 0x65, 0x2e, - 0xc8, 0x66, 0xbf, 0xae, 0x86, 0xfc, 0xe8, 0xe4, 0xbc, 0x8d, 0x19, 0x67, 0x33, 0x64, 0x1b, 0x2b, 0xce, 0x94, 0xd3, - 0xe2, 0x5b, 0x73, 0xb7, 0x87, 0xbc, 0xec, 0xae, 0x03, 0x05, 0x0f, 0x87, 0x12, 0x9a, 0xf1, 0xe7, 0xea, 0x9f, 0x27, - 0x41, 0x55, 0xe5, 0x84, 0x36, 0xfe, 0x59, 0x7c, 0xc6, 0xe7, 0x6a, 0xc1, 0x97, 0x70, 0xd8, 0x31, 0x00, 0x54, 0x02, - 0xeb, 0x62, 0xa8, 0xfd, 0x54, 0x80, 0xdd, 0xef, 0x0d, 0x69, 0x7c, 0xef, 0x9c, 0xa4, 0x59, 0xd8, 0xc7, 0xae, 0xbd, - 0x69, 0x72, 0x90, 0xa3, 0xed, 0x5a, 0x85, 0x37, 0xea, 0xab, 0x3e, 0xd6, 0x33, 0xcb, 0xf0, 0x03, 0x08, 0x2d, 0xcd, - 0x25, 0x90, 0x63, 0x18, 0x83, 0x7e, 0xf1, 0xe6, 0x7f, 0xfd, 0x02, 0x5c, 0x40, 0xb0, 0x45, 0xc1, 0xf3, 0x6d, 0xaf, - 0x7c, 0xc2, 0xb4, 0x94, 0x4a, 0x21, 0x38, 0x67, 0xfd, 0x47, 0xb0, 0x21, 0x2e, 0xed, 0x4e, 0x6d, 0x32, 0x61, 0x38, - 0x25, 0x15, 0xd1, 0x06, 0x8d, 0xd9, 0xce, 0x73, 0x4e, 0xf3, 0x60, 0xf3, 0xcf, 0x82, 0x8b, 0x92, 0xef, 0x9b, 0x99, - 0x9e, 0x3d, 0x50, 0x75, 0xe6, 0xda, 0x6a, 0x7a, 0x82, 0x1e, 0xa4, 0xce, 0x5f, 0x8b, 0x65, 0xac, 0xee, 0x77, 0x4b, - 0x4a, 0x22, 0x1b, 0x13, 0x0a, 0x36, 0xb4, 0xa1, 0xbb, 0x26, 0x88, 0x39, 0x8d, 0x6b, 0xbb, 0x15, 0xfd, 0xde, 0x89, - 0x66, 0x20, 0xdd, 0x28, 0x87, 0x65, 0x98, 0x32, 0x84, 0xe4, 0x96, 0xf1, 0x1d, 0x59, 0x97, 0x5d, 0xd9, 0x58, 0x84, - 0xb2, 0x7f, 0xb7, 0xe5, 0x70, 0x4a, 0xa1, 0x6a, 0xd4, 0x17, 0x60, 0x48, 0x89, 0x69, 0x9b, 0x2c, 0x8b, 0xb8, 0xb3, - 0x05, 0x05, 0xcd, 0x94, 0x8d, 0x9d, 0xda, 0x75, 0x84, 0x21, 0x73, 0xf8, 0x35, 0xb2, 0x27, 0x1d, 0x99, 0xa7, 0xc8, - 0x65, 0x93, 0x9e, 0xf5, 0xfa, 0x73, 0x07, 0x28, 0x6c, 0x5f, 0xe0, 0x94, 0x3c, 0xcf, 0x69, 0xaa, 0xa1, 0x96, 0x1b, - 0xd2, 0x45, 0x51, 0x25, 0x38, 0x3a, 0x27, 0x78, 0x81, 0x23, 0x84, 0xca, 0x96, 0x92, 0xa0, 0x1e, 0x0f, 0xa1, 0x4a, - 0x24, 0x47, 0xc7, 0x09, 0xcc, 0x75, 0xbc, 0x9a, 0x6b, 0xfc, 0x37, 0x24, 0x8f, 0x36, 0x7e, 0x80, 0xb8, 0x96, 0xd9, - 0xc8, 0xc7, 0x43, 0x6a, 0x98, 0xc2, 0x58, 0x1f, 0x29, 0xf8, 0x6a, 0x1a, 0xc2, 0xa2, 0xc9, 0x40, 0x1a, 0x18, 0x9c, - 0x02, 0xff, 0x2d, 0x5c, 0x33, 0x56, 0x5e, 0xb9, 0x0e, 0x15, 0xab, 0xb4, 0x6b, 0xfa, 0x55, 0xff, 0xcc, 0xd8, 0x8b, - 0xa8, 0x6f, 0x77, 0x18, 0x7b, 0x96, 0x6a, 0x05, 0x3f, 0xcf, 0xb5, 0x61, 0x7c, 0x37, 0x74, 0x9a, 0x74, 0x9e, 0x53, - 0x5f, 0x39, 0x70, 0x51, 0x6c, 0xa2, 0x68, 0x33, 0x7a, 0x4d, 0x9d, 0x9a, 0x25, 0x9c, 0xea, 0xb8, 0x49, 0xb2, 0x2e, - 0x31, 0x8e, 0xa4, 0x17, 0xfb, 0xfa, 0x46, 0x63, 0xaa, 0x68, 0x25, 0xbe, 0x53, 0x51, 0xae, 0x80, 0xb3, 0x10, 0x84, - 0x56, 0xec, 0x89, 0x57, 0xcb, 0xca, 0x4a, 0x7c, 0xa4, 0x05, 0xf3, 0x46, 0x54, 0x20, 0xc8, 0x13, 0xd2, 0x3a, 0x71, - 0x27, 0x46, 0x66, 0x15, 0x72, 0xb7, 0x21, 0xc9, 0x08, 0x11, 0x5d, 0xb0, 0x97, 0xd0, 0xdb, 0xa5, 0xab, 0xb3, 0xa7, - 0x00, 0x2f, 0x10, 0x23, 0xfa, 0x07, 0xd3, 0xc2, 0x72, 0xd4, 0x4e, 0x94, 0xe8, 0x4e, 0xf6, 0x6f, 0x36, 0xff, 0x7e, - 0xac, 0x4a, 0x50, 0xa8, 0xbd, 0x0e, 0x01, 0xb3, 0x16, 0x93, 0x9e, 0xa4, 0x6d, 0x93, 0x02, 0x28, 0x96, 0xa0, 0x0d, - 0x7e, 0x5d, 0x0d, 0xa4, 0xbb, 0xf6, 0xde, 0x97, 0x46, 0x4c, 0xb8, 0x7c, 0x96, 0x92, 0x57, 0x19, 0xd5, 0x32, 0x7b, - 0xde, 0xb5, 0x17, 0x94, 0x96, 0xc0, 0xd5, 0x2f, 0x31, 0xa7, 0x3f, 0xef, 0x60, 0x46, 0x26, 0xc4, 0xb4, 0x67, 0xcc, - 0xcb, 0x66, 0x3d, 0xa6, 0xbe, 0xad, 0x63, 0xb1, 0xb5, 0x59, 0x3b, 0x7c, 0xf0, 0xc7, 0xd1, 0x9d, 0xa2, 0x35, 0xee, - 0x9f, 0xcb, 0x7f, 0xdb, 0x70, 0xdf, 0x7a, 0x67, 0xab, 0xd0, 0x5c, 0x5d, 0x27, 0xdb, 0xe8, 0xbe, 0x57, 0x3b, 0xc7, - 0x8a, 0x58, 0x7c, 0x1b, 0x63, 0xd7, 0x1d, 0xa0, 0xe3, 0xbb, 0x46, 0x81, 0xfb, 0x13, 0xd8, 0xe5, 0xf3, 0xe3, 0xf3, - 0x6a, 0x41, 0x8c, 0x23, 0xd9, 0x7a, 0x36, 0xf3, 0x0f, 0x97, 0x44, 0x77, 0xb7, 0xf4, 0x1e, 0x45, 0x20, 0xfa, 0x3e, - 0xa9, 0x97, 0x75, 0x26, 0xe3, 0x0b, 0xf2, 0xc8, 0xea, 0x15, 0xf8, 0xcd, 0x74, 0xd7, 0x1e, 0xdb, 0x89, 0x33, 0xc7, - 0xe6, 0x97, 0xcf, 0xf0, 0x48, 0x90, 0xe1, 0x9c, 0x21, 0xc6, 0x29, 0xea, 0xf8, 0x51, 0x2f, 0xe6, 0x4c, 0x3e, 0x92, - 0x02, 0xbe, 0xde, 0x74, 0x4e, 0x71, 0xa8, 0xa6, 0x30, 0x17, 0x1a, 0x4d, 0x3a, 0xb1, 0x8f, 0x14, 0x00, 0xda, 0x9e, - 0x98, 0x12, 0x33, 0x71, 0x39, 0xbd, 0x01, 0x75, 0xbd, 0x07, 0x29, 0x95, 0xf3, 0x17, 0x31, 0x99, 0x71, 0xea, 0x39, - 0x98, 0x55, 0x7d, 0x51, 0xcc, 0x3f, 0xc1, 0xcc, 0xd4, 0xa8, 0x4d, 0x01, 0x4f, 0x8b, 0x19, 0x35, 0x3d, 0xb6, 0xdf, - 0x08, 0x49, 0xda, 0x6b, 0x96, 0x70, 0xb1, 0x33, 0x3e, 0x77, 0x50, 0x0a, 0xff, 0x56, 0x01, 0x3c, 0xa3, 0xd5, 0x67, - 0x55, 0xf2, 0x1c, 0x50, 0x16, 0xc3, 0xf6, 0xa5, 0x17, 0x7b, 0x1a, 0x5f, 0x05, 0xd7, 0x9f, 0x15, 0xc4, 0x56, 0xfc, - 0xfb, 0x97, 0x9b, 0xbe, 0xae, 0xf6, 0x16, 0xa2, 0x4f, 0x9d, 0x85, 0x27, 0x27, 0xbc, 0xde, 0x09, 0xe2, 0x74, 0x83, - 0xfd, 0x29, 0x6b, 0x89, 0xc1, 0xc9, 0x82, 0x7f, 0x6c, 0x45, 0x11, 0xaa, 0x8e, 0xfa, 0x98, 0xc5, 0x9d, 0x84, 0x2c, - 0x2b, 0x18, 0x86, 0x91, 0x41, 0xa6, 0x03, 0xfc, 0xd9, 0x97, 0xea, 0x8b, 0x8b, 0x68, 0xe0, 0xa5, 0x35, 0xfb, 0x9d, - 0x4f, 0xe1, 0x58, 0xd1, 0x85, 0x4f, 0xe1, 0xa7, 0x77, 0xa1, 0x02, 0x6c, 0x7d, 0x2d, 0x93, 0x33, 0x49, 0xf4, 0x65, - 0xd8, 0x57, 0x0c, 0x97, 0x34, 0x25, 0x8f, 0xbb, 0xa8, 0x92, 0xf3, 0xbf, 0xca, 0x75, 0x3f, 0xa3, 0x2f, 0xa9, 0xc6, - 0x3a, 0x0a, 0x46, 0xdd, 0xd5, 0x36, 0xa5, 0x77, 0x9c, 0x29, 0x29, 0xca, 0xd5, 0x0b, 0x4d, 0xfb, 0xfa, 0x93, 0xab, - 0xaf, 0xf4, 0x55, 0xd2, 0x4e, 0x35, 0x7a, 0xc2, 0x4b, 0x75, 0xd3, 0x81, 0x7f, 0xcb, 0xc9, 0xbd, 0x78, 0x2b, 0x35, - 0xb2, 0x37, 0xfd, 0x0f, 0xb6, 0x5d, 0x93, 0x73, 0x25, 0x4e, 0xb9, 0x60, 0x07, 0xe5, 0xd0, 0xe5, 0x38, 0x9e, 0xc4, - 0xb6, 0x55, 0x34, 0x8a, 0x2d, 0xe5, 0x96, 0x05, 0xce, 0x8d, 0x79, 0x22, 0x13, 0x24, 0x6a, 0x19, 0xae, 0x19, 0x5e, - 0x53, 0x80, 0x70, 0xba, 0x94, 0xe0, 0x66, 0xc0, 0x74, 0xea, 0x76, 0x4c, 0xe4, 0x74, 0xec, 0x35, 0x7e, 0x68, 0x84, - 0x10, 0x95, 0x72, 0xbe, 0x4d, 0x19, 0x51, 0xf5, 0x59, 0x76, 0x57, 0xf2, 0x56, 0x29, 0xd1, 0xb6, 0xea, 0x98, 0x8b, - 0x72, 0x60, 0xd1, 0x0b, 0x06, 0xad, 0x9c, 0x39, 0x89, 0xf5, 0xe9, 0x39, 0x69, 0xe3, 0x7f, 0xd9, 0x89, 0x1d, 0xe6, - 0xc8, 0xfb, 0x28, 0x75, 0x67, 0x0c, 0xe2, 0x9b, 0x3a, 0x49, 0x82, 0xbe, 0xb8, 0xea, 0x06, 0x4e, 0x59, 0x9c, 0x9a, - 0x5a, 0x5d, 0x03, 0xb0, 0x45, 0x0b, 0xad, 0x3e, 0x50, 0xf5, 0x40, 0xec, 0x57, 0xb5, 0xc1, 0x5f, 0x2b, 0x5e, 0xa6, - 0xf3, 0xb4, 0x0f, 0x15, 0x6b, 0xa4, 0x03, 0x43, 0x0e, 0xee, 0x4c, 0xb0, 0x06, 0xa1, 0x40, 0xc9, 0xe2, 0x5c, 0xc9, - 0x23, 0x8c, 0x8d, 0xe3, 0x88, 0xb5, 0x04, 0xc5, 0x94, 0xb7, 0x7d, 0x60, 0x07, 0x17, 0x88, 0x6e, 0xc4, 0x85, 0x65, - 0x1b, 0x51, 0xb4, 0x20, 0x29, 0x4a, 0x8e, 0x15, 0xea, 0x05, 0xdf, 0x08, 0xb1, 0x18, 0xc0, 0x5c, 0xd2, 0x37, 0x8b, - 0x89, 0x82, 0x0a, 0xc6, 0xe1, 0x0d, 0xfe, 0x6d, 0xe2, 0x12, 0xa1, 0x2f, 0xc4, 0x6b, 0xe3, 0x5b, 0x32, 0x5f, 0x60, - 0x4f, 0xa7, 0x20, 0xeb, 0x25, 0xbe, 0xdd, 0x7c, 0xf6, 0x1b, 0x56, 0xbf, 0x81, 0xb9, 0x9a, 0x5f, 0x26, 0xce, 0x59, - 0x4d, 0x79, 0xe7, 0xba, 0x3d, 0xcb, 0x02, 0xcd, 0xd9, 0xf8, 0xde, 0xa1, 0x6a, 0x82, 0x66, 0x7c, 0x41, 0xd3, 0x9b, - 0x8b, 0xb1, 0x2e, 0xd0, 0xdf, 0x5b, 0xcd, 0x2d, 0x30, 0x89, 0x0b, 0xd6, 0x53, 0xde, 0xe7, 0xf7, 0xa6, 0x4d, 0x03, - 0xeb, 0xc5, 0x9c, 0x03, 0x34, 0x2f, 0xc3, 0xa7, 0xd3, 0x4a, 0x7b, 0x46, 0x93, 0x82, 0x3f, 0xdc, 0xe0, 0xd0, 0x32, - 0xed, 0xd7, 0xcf, 0x5e, 0xf4, 0xba, 0xe1, 0x5f, 0x2e, 0x03, 0x38, 0xea, 0x5f, 0x46, 0x42, 0xc7, 0xde, 0x19, 0xe7, - 0x56, 0x41, 0x1c, 0x8d, 0xb1, 0x21, 0xf4, 0x3f, 0x12, 0xe7, 0x33, 0x32, 0x78, 0x06, 0x76, 0x41, 0x05, 0x42, 0x92, - 0x7e, 0xb1, 0xa2, 0x39, 0x2c, 0x6f, 0x31, 0x6d, 0xd4, 0x72, 0xc1, 0xb4, 0x65, 0xb8, 0xc5, 0xcb, 0x56, 0x1b, 0x8b, - 0xea, 0xcb, 0xe7, 0xc2, 0x60, 0x12, 0x56, 0x91, 0xfb, 0x3f, 0xce, 0x00, 0xd4, 0x4f, 0x20, 0x79, 0x0c, 0x5b, 0xdf, - 0x2e, 0xfa, 0xd5, 0xb2, 0x40, 0xaf, 0xcc, 0x93, 0x0d, 0x5a, 0xe3, 0x32, 0x46, 0xd4, 0x85, 0xe9, 0x75, 0x6d, 0xae, - 0xa1, 0x7b, 0x63, 0x7d, 0x1a, 0x09, 0x7d, 0x07, 0x0b, 0xf1, 0xed, 0xc7, 0xb4, 0xd1, 0x71, 0x07, 0x71, 0x53, 0xd8, - 0x6f, 0x55, 0x9b, 0xc8, 0x59, 0xeb, 0xb9, 0x89, 0x82, 0xe2, 0x1a, 0x51, 0x7d, 0x93, 0x73, 0x87, 0x8f, 0x6e, 0xa2, - 0xa3, 0xf2, 0x1a, 0xef, 0x2d, 0xd5, 0xd4, 0xd7, 0x00, 0x2d, 0xd4, 0x1d, 0x6a, 0xa0, 0xe7, 0xc5, 0xab, 0x22, 0x02, - 0x9e, 0xa9, 0x73, 0xfc, 0x25, 0x2a, 0x78, 0x04, 0x1f, 0xcd, 0xab, 0x52, 0xaa, 0xda, 0x37, 0x21, 0xab, 0x83, 0x5c, - 0x93, 0x07, 0x7e, 0x48, 0x75, 0x1d, 0xde, 0x46, 0x01, 0x1a, 0x3c, 0xa2, 0x1a, 0x3c, 0xb2, 0xfe, 0xbc, 0x38, 0x4f, - 0x31, 0x7e, 0x3a, 0x05, 0x4b, 0x37, 0x02, 0x4b, 0x1b, 0xfb, 0xf2, 0xe2, 0xb0, 0xb9, 0x64, 0x55, 0x00, 0x92, 0x19, - 0xf5, 0x52, 0x2c, 0x7e, 0x26, 0x15, 0x9e, 0x37, 0xaa, 0xac, 0x6e, 0xb3, 0xa3, 0x8f, 0x74, 0x6e, 0x2b, 0x13, 0x10, - 0x0a, 0xfd, 0xfe, 0x91, 0x09, 0x95, 0x78, 0x55, 0x68, 0x04, 0x01, 0x7a, 0xab, 0xc1, 0x79, 0x35, 0xca, 0x7e, 0xfe, - 0x75, 0xeb, 0x3e, 0x2d, 0x5e, 0xa2, 0x61, 0x2f, 0xdd, 0xa8, 0xb1, 0xa0, 0x93, 0x60, 0x30, 0x25, 0x8c, 0x82, 0xdc, - 0x82, 0x76, 0xa4, 0x77, 0x12, 0xbd, 0x19, 0xa8, 0x4f, 0x0b, 0xaa, 0xfe, 0xdf, 0xee, 0xa7, 0x54, 0xf4, 0x13, 0x81, - 0x16, 0xf2, 0x64, 0xeb, 0x01, 0x5f, 0x1b, 0xbe, 0xc5, 0xf9, 0xab, 0x46, 0xba, 0x90, 0x5c, 0x52, 0x10, 0x1b, 0x99, - 0xb2, 0x19, 0x69, 0x90, 0x56, 0x3c, 0x73, 0x4d, 0xea, 0x42, 0x4a, 0xbb, 0x69, 0xf0, 0xb3, 0x95, 0xd7, 0x20, 0xd5, - 0xe4, 0xd1, 0x15, 0x6b, 0x2f, 0x6e, 0x5c, 0xc6, 0x1b, 0x67, 0xd7, 0x47, 0xb4, 0x2a, 0xb4, 0x2c, 0x54, 0x2b, 0xd2, - 0xa5, 0xd4, 0x77, 0x66, 0x79, 0x89, 0x00, 0xf6, 0x88, 0xbd, 0x0b, 0x17, 0xed, 0x9b, 0x65, 0x16, 0x39, 0xb0, 0xcd, - 0x3d, 0x0b, 0xdb, 0x5e, 0x1f, 0x12, 0xf9, 0x52, 0xfc, 0xcc, 0x8c, 0xea, 0x62, 0xd5, 0x34, 0x9f, 0x1d, 0x0c, 0x12, - 0xad, 0x36, 0x11, 0x67, 0xe2, 0xa4, 0x47, 0x20, 0x0a, 0x53, 0xa2, 0x9f, 0x45, 0xb1, 0x8c, 0x20, 0xfb, 0x47, 0xf6, - 0x86, 0x23, 0xdd, 0x84, 0x15, 0x87, 0xef, 0x01, 0xfb, 0x37, 0xfb, 0x6f, 0x1b, 0x46, 0x30, 0xad, 0xe0, 0xbc, 0x10, - 0x2c, 0x42, 0xe3, 0x2d, 0x86, 0x46, 0xb8, 0x9f, 0x04, 0x24, 0xde, 0x48, 0x71, 0x82, 0xfa, 0xdc, 0x8e, 0xaf, 0x5e, - 0x1d, 0xd2, 0x23, 0xcc, 0x50, 0x78, 0x36, 0xe5, 0x94, 0x67, 0xb0, 0x8f, 0xe7, 0xa2, 0xfb, 0x97, 0xea, 0x10, 0x1b, - 0x05, 0x47, 0xca, 0x52, 0xab, 0x42, 0xd6, 0x71, 0xdd, 0xbf, 0x5b, 0x1d, 0x73, 0x36, 0x36, 0x7d, 0xe5, 0x25, 0x0d, - 0x5a, 0x69, 0x48, 0xf4, 0x80, 0x1d, 0xe3, 0xd9, 0x86, 0x24, 0x3b, 0x56, 0x9a, 0x84, 0x18, 0xcd, 0x24, 0xd6, 0xc1, - 0xb4, 0x7f, 0xf4, 0xca, 0xb3, 0x56, 0xec, 0xba, 0xe6, 0x74, 0x6d, 0x06, 0xa9, 0xd0, 0x36, 0x22, 0xac, 0x26, 0xa6, - 0xbb, 0x88, 0x76, 0xfa, 0x33, 0x55, 0xbf, 0x1e, 0x29, 0xd3, 0xd8, 0x4f, 0x50, 0x28, 0x4f, 0xf0, 0x66, 0xbb, 0x2b, - 0x27, 0x77, 0x09, 0x00, 0x4d, 0xff, 0x72, 0xdd, 0x85, 0x73, 0xa6, 0x8a, 0x56, 0x3d, 0xf0, 0x69, 0xd2, 0x35, 0x2f, - 0xe1, 0x50, 0xcd, 0x68, 0x04, 0xe0, 0x3c, 0x09, 0xa1, 0xcb, 0xd9, 0x9e, 0x6b, 0x08, 0x9a, 0xd6, 0xf3, 0xb4, 0xce, - 0x9e, 0x11, 0x3d, 0xff, 0xa9, 0xcf, 0x7c, 0x21, 0x5d, 0x51, 0x14, 0xb5, 0x29, 0x6b, 0x8a, 0xa1, 0xa1, 0x8d, 0x33, - 0xb9, 0xe1, 0xb4, 0x8b, 0x16, 0x21, 0x9d, 0xd9, 0x4b, 0x7d, 0x8a, 0x75, 0xa5, 0xdb, 0xce, 0x06, 0x16, 0x96, 0x06, - 0x26, 0x50, 0x72, 0x54, 0x69, 0x71, 0x9d, 0x59, 0xbe, 0x54, 0x5b, 0xb7, 0x74, 0x9e, 0xcb, 0x17, 0x79, 0x1a, 0xc6, - 0xe7, 0x5f, 0x01, 0x77, 0x72, 0xe4, 0x02, 0xcb, 0xbc, 0xa2, 0x5a, 0x42, 0xfa, 0x94, 0x5f, 0xc3, 0x68, 0xe1, 0xb1, - 0xf1, 0xc0, 0xb4, 0xba, 0x7f, 0xb0, 0x54, 0x95, 0xf3, 0x82, 0xa9, 0x31, 0x8f, 0x49, 0x93, 0x02, 0x37, 0xb9, 0x0d, - 0xea, 0x4a, 0x0c, 0xb0, 0x4d, 0x91, 0x7f, 0xf2, 0xa3, 0x20, 0x43, 0x3c, 0x90, 0xd1, 0xa8, 0x06, 0xea, 0x34, 0x73, - 0xbc, 0xb3, 0x4b, 0x5d, 0xac, 0xda, 0xde, 0x82, 0x62, 0x78, 0x5b, 0xea, 0x82, 0xe1, 0x99, 0xe2, 0xa9, 0x84, 0x37, - 0xe5, 0x0a, 0xf6, 0xaf, 0x12, 0xa1, 0xa1, 0x72, 0xa1, 0xf6, 0xc3, 0x31, 0x6c, 0xb5, 0x0b, 0x81, 0xd2, 0x6f, 0x1a, - 0x1a, 0x85, 0x86, 0xac, 0x57, 0xcd, 0xab, 0xba, 0xb7, 0x79, 0xab, 0x36, 0x84, 0xa1, 0x29, 0xd2, 0xb9, 0x60, 0xdb, - 0xc5, 0x1e, 0xee, 0xff, 0x14, 0x43, 0x11, 0x52, 0x2b, 0xe7, 0xe2, 0x43, 0x3e, 0xee, 0x20, 0x60, 0x7e, 0x52, 0x0f, - 0xfe, 0xfa, 0xa3, 0x30, 0xe4, 0x7f, 0x56, 0x7a, 0xa0, 0xe2, 0x87, 0xfd, 0x22, 0xfc, 0x2a, 0xf3, 0xb7, 0x86, 0x94, - 0x93, 0x77, 0x7d, 0xdb, 0x05, 0x00, 0x2d, 0x5f, 0xc8, 0x81, 0xbc, 0xeb, 0xcc, 0x8d, 0x91, 0xb5, 0x6d, 0x32, 0xaf, - 0xd6, 0xf1, 0x2b, 0x81, 0x82, 0xd8, 0xf8, 0x2d, 0x94, 0xfd, 0xd9, 0x90, 0x1b, 0xfe, 0xc3, 0xc1, 0xdc, 0x52, 0x42, - 0x57, 0x59, 0x93, 0x53, 0xca, 0x0e, 0x19, 0x01, 0xd2, 0x08, 0x1c, 0x47, 0x3e, 0x33, 0xa0, 0xbf, 0x8d, 0x2b, 0xfa, - 0xe9, 0x15, 0xb7, 0xa1, 0x58, 0x4d, 0x4f, 0x75, 0x8d, 0x90, 0x87, 0xe9, 0x42, 0x76, 0x33, 0xa1, 0x89, 0x58, 0x38, - 0x2e, 0x47, 0x02, 0xd9, 0x9b, 0xc8, 0x74, 0x02, 0x2d, 0xd8, 0x9a, 0xe5, 0xd6, 0x48, 0xae, 0x6a, 0x2b, 0xa7, 0xcb, - 0xfa, 0xe4, 0x48, 0xea, 0x55, 0x81, 0x1b, 0x79, 0xeb, 0x7c, 0x51, 0x67, 0x47, 0x45, 0xa5, 0x67, 0xc8, 0xdb, 0xdc, - 0xc2, 0x89, 0xe5, 0x93, 0xe2, 0x37, 0x9c, 0xe4, 0xee, 0xd5, 0x7a, 0xa0, 0x48, 0xc2, 0x54, 0x28, 0xb3, 0x17, 0x39, - 0xdb, 0x6e, 0xf4, 0xe0, 0xbd, 0xa5, 0xa0, 0x57, 0x90, 0x0d, 0xb6, 0xdc, 0x5d, 0xdd, 0x29, 0xbd, 0xc0, 0xb3, 0x12, - 0x4e, 0x9b, 0x71, 0xed, 0x85, 0x46, 0x66, 0x49, 0x96, 0x90, 0xf6, 0xbf, 0xba, 0xc7, 0x90, 0x58, 0x5e, 0x6e, 0xc4, - 0xbe, 0xf9, 0xba, 0x0b, 0x43, 0xc9, 0x42, 0x87, 0x0f, 0xec, 0xc1, 0x7b, 0x4c, 0xc5, 0x9b, 0xae, 0x06, 0x3c, 0xf4, - 0x20, 0xa1, 0x94, 0xef, 0xa2, 0xd4, 0xc7, 0xdf, 0x30, 0x7d, 0x7d, 0xef, 0x56, 0x6c, 0xf6, 0x80, 0x17, 0x81, 0x81, - 0xd1, 0xb3, 0x6d, 0xd2, 0xe3, 0x53, 0xd7, 0x11, 0xaa, 0x06, 0x5c, 0xcd, 0xbf, 0xee, 0xa4, 0x37, 0xbb, 0x7d, 0x1a, - 0xf7, 0x76, 0x3f, 0xc4, 0xef, 0x65, 0x63, 0x2a, 0x0f, 0xf5, 0x44, 0xb1, 0xae, 0xcf, 0x5b, 0x62, 0x44, 0x11, 0x27, - 0x1e, 0xd6, 0x7d, 0x6e, 0x54, 0x67, 0x1d, 0x49, 0xf7, 0x6e, 0xc0, 0x8e, 0x92, 0x36, 0x9d, 0x7d, 0xda, 0xe9, 0xb2, - 0x7c, 0x4d, 0x6b, 0x0f, 0x5f, 0x1f, 0x78, 0xe9, 0x36, 0xbf, 0xee, 0x14, 0xb5, 0x31, 0xdb, 0xa2, 0xc9, 0xba, 0xbe, - 0xe3, 0xe2, 0x45, 0xf3, 0xe2, 0x47, 0xcd, 0x6d, 0x55, 0x1d, 0x99, 0x16, 0xb3, 0x7c, 0x9e, 0x0f, 0x90, 0xfc, 0x3e, - 0x3d, 0x05, 0x27, 0x4f, 0xf1, 0xdb, 0xee, 0x1b, 0xde, 0x82, 0x8f, 0xee, 0x5e, 0x8d, 0x4b, 0x59, 0xef, 0x3f, 0xf3, - 0x5b, 0x5e, 0x62, 0xfd, 0xa2, 0x6a, 0xdb, 0xab, 0x41, 0x51, 0xda, 0xd4, 0xfb, 0x2d, 0xff, 0xbc, 0x33, 0x43, 0x46, - 0xfe, 0x99, 0xda, 0xd9, 0x64, 0x2c, 0x01, 0xf4, 0x5f, 0x95, 0xaa, 0x9d, 0x59, 0xe0, 0x8d, 0x67, 0x30, 0x11, 0x0f, - 0x04, 0xaa, 0x5f, 0x50, 0xc8, 0x4c, 0xf1, 0x9d, 0xc6, 0x80, 0xf7, 0x78, 0x74, 0x2a, 0x3c, 0x5e, 0xf6, 0x7e, 0x15, - 0xe3, 0xe0, 0x19, 0x46, 0xec, 0xf6, 0x3f, 0x0e, 0xa2, 0x40, 0x2a, 0x1c, 0x0c, 0xd2, 0x15, 0xce, 0x74, 0xfc, 0xc9, - 0xc0, 0xfe, 0x25, 0xfd, 0x53, 0x75, 0x86, 0xf1, 0x31, 0xbe, 0x72, 0x63, 0xd4, 0x12, 0x5f, 0xa2, 0x7d, 0x9b, 0x2c, - 0xc2, 0xda, 0xf3, 0x64, 0xaf, 0xee, 0xf2, 0x6a, 0x83, 0x88, 0xea, 0xc9, 0x64, 0x79, 0xdc, 0xac, 0x22, 0x4c, 0x00, - 0x45, 0xaa, 0x97, 0x07, 0x2e, 0x43, 0x7e, 0x9f, 0x3f, 0x3f, 0x21, 0xce, 0x2d, 0x9e, 0x11, 0x3f, 0x98, 0x4f, 0x4e, - 0xf8, 0xa8, 0x7b, 0x6d, 0xfd, 0x6d, 0x22, 0x80, 0x2e, 0x99, 0xda, 0x36, 0x39, 0x60, 0x38, 0x70, 0x90, 0xf4, 0xee, - 0xf0, 0xe6, 0x5f, 0x0d, 0x41, 0x28, 0x5f, 0xad, 0x60, 0x69, 0xf5, 0x27, 0x88, 0xd9, 0xd2, 0x98, 0x84, 0x9c, 0x40, - 0x10, 0xae, 0x8d, 0x8f, 0x1d, 0x64, 0x1e, 0xd8, 0x54, 0x0b, 0x2c, 0x2d, 0x39, 0x05, 0xa2, 0x36, 0xee, 0x55, 0xcd, - 0xbd, 0x48, 0x73, 0x32, 0xca, 0xd4, 0xe6, 0x19, 0xab, 0xd6, 0x52, 0x4d, 0x06, 0xfe, 0xc3, 0xbc, 0xc6, 0xfe, 0xac, - 0x70, 0x41, 0x5f, 0xba, 0x79, 0x72, 0xf0, 0xb0, 0x48, 0x30, 0x07, 0x1f, 0x05, 0x30, 0x94, 0x11, 0xfc, 0xa7, 0x96, - 0x5b, 0x39, 0x8f, 0x81, 0x77, 0x28, 0xa9, 0x6a, 0xb1, 0xfb, 0xd2, 0x68, 0x06, 0xce, 0xca, 0xe8, 0x07, 0xf2, 0xbd, - 0xe4, 0x16, 0xf6, 0xf1, 0x23, 0x5f, 0xd0, 0x76, 0x94, 0x33, 0x55, 0x24, 0x54, 0x8d, 0xf7, 0xb6, 0x7f, 0xcb, 0x8a, - 0xfe, 0x95, 0xf7, 0x97, 0x72, 0xc6, 0xab, 0x02, 0x9f, 0x78, 0xc6, 0xa7, 0xf9, 0x72, 0x5a, 0x3c, 0x2a, 0xae, 0x58, - 0x48, 0xb2, 0xa8, 0xf2, 0xd0, 0xeb, 0x3f, 0x89, 0x15, 0x0a, 0x5e, 0xd1, 0xd9, 0x0a, 0x60, 0x8b, 0x18, 0x1d, 0x54, - 0x2a, 0xab, 0x7d, 0x95, 0x47, 0xc6, 0xbc, 0x79, 0xe7, 0x47, 0x61, 0x80, 0x5c, 0xb6, 0xa1, 0xaa, 0x7b, 0x2a, 0xfa, - 0x1a, 0x52, 0x61, 0xd9, 0x8a, 0x4d, 0xef, 0x19, 0x9e, 0x3a, 0x98, 0x7c, 0x4f, 0x2c, 0x77, 0x1f, 0x50, 0x1c, 0xc6, - 0x9a, 0x53, 0xaa, 0x2a, 0x33, 0x3e, 0x8f, 0x9c, 0x7e, 0x3e, 0x85, 0x67, 0xf4, 0x58, 0x64, 0xab, 0xbf, 0xe6, 0xc3, - 0x5a, 0xd8, 0xc2, 0xb7, 0x85, 0x50, 0x83, 0x5e, 0xe8, 0x05, 0xd7, 0xeb, 0x4b, 0x38, 0x88, 0x99, 0x11, 0x37, 0xef, - 0x6b, 0x93, 0x08, 0x64, 0xfd, 0x6c, 0xc4, 0x35, 0xd9, 0xfa, 0xc2, 0xc2, 0x7e, 0x8b, 0xf0, 0x8d, 0x84, 0xe8, 0x4f, - 0xe4, 0x31, 0xeb, 0x07, 0xc9, 0x74, 0xdd, 0x4e, 0x4e, 0xd5, 0x3f, 0x14, 0xf0, 0x6a, 0xc4, 0xfd, 0x15, 0x10, 0x3e, - 0x1f, 0xcb, 0xf5, 0x38, 0x13, 0x04, 0x05, 0x8f, 0xb5, 0x0a, 0x42, 0x79, 0x1b, 0xb5, 0x25, 0xb4, 0xde, 0x2a, 0x08, - 0x60, 0x33, 0xd6, 0xb1, 0x8b, 0x9f, 0x8e, 0xa5, 0x3f, 0x97, 0xfb, 0x3b, 0xa7, 0xf4, 0xc0, 0x8d, 0x0b, 0x0f, 0xf0, - 0x85, 0xef, 0x11, 0xbb, 0xd0, 0x88, 0x67, 0x0d, 0x62, 0x3f, 0x8e, 0xb7, 0x9a, 0xde, 0xd6, 0xa9, 0x76, 0xd8, 0x5c, - 0xa1, 0x54, 0x57, 0xde, 0x4b, 0x78, 0x1b, 0xe6, 0x3c, 0x4f, 0x22, 0xcf, 0x8f, 0x62, 0x1e, 0x38, 0xae, 0x94, 0xc4, - 0x99, 0x94, 0x86, 0xe0, 0xc7, 0x51, 0x27, 0x58, 0xf9, 0x31, 0x33, 0xf6, 0x59, 0x58, 0xdf, 0xf7, 0x0c, 0x3b, 0xf6, - 0x27, 0x5e, 0x07, 0x47, 0x27, 0x2c, 0xa7, 0xe6, 0x66, 0x07, 0xc6, 0x4f, 0x81, 0x2a, 0x4f, 0x08, 0xc2, 0xd6, 0xac, - 0xdc, 0x9b, 0xdc, 0xbe, 0xee, 0x12, 0xa2, 0xd9, 0x10, 0x55, 0x8f, 0x5d, 0xe0, 0xea, 0x65, 0x49, 0xa5, 0x2a, 0xd5, - 0x53, 0x85, 0x0a, 0x43, 0x6b, 0xb5, 0x2d, 0x66, 0x9c, 0xde, 0xbb, 0x11, 0x5c, 0xb8, 0x34, 0xd2, 0x0c, 0x2f, 0x04, - 0x16, 0x58, 0x3b, 0x3d, 0x55, 0xca, 0x68, 0xa5, 0x50, 0x17, 0xf5, 0x79, 0x5c, 0xbf, 0x86, 0x2e, 0x7b, 0xe1, 0x4d, - 0x65, 0x6d, 0x53, 0x34, 0x2c, 0xd8, 0x86, 0x89, 0xae, 0xd3, 0x95, 0xba, 0x9c, 0x7d, 0xf4, 0x57, 0xf5, 0x8c, 0xe6, - 0x58, 0x75, 0xec, 0x49, 0x08, 0xb5, 0x50, 0x83, 0x42, 0xa4, 0xd7, 0xdb, 0x01, 0x88, 0xdc, 0x13, 0xd2, 0xe0, 0x1c, - 0x0b, 0x36, 0x92, 0xed, 0x5c, 0xc1, 0xa6, 0xcd, 0x01, 0x71, 0xe2, 0xe7, 0x7e, 0x10, 0x07, 0x3e, 0x69, 0x43, 0x9a, - 0xf3, 0xb8, 0xfd, 0xd2, 0xdd, 0x1e, 0x58, 0xc9, 0x53, 0x56, 0x28, 0x32, 0x66, 0xbb, 0xab, 0x42, 0x4c, 0x7e, 0x4e, - 0xa6, 0x1e, 0x7c, 0x37, 0x60, 0xfd, 0xab, 0xe1, 0xcc, 0x09, 0xaf, 0x4b, 0x91, 0x45, 0x11, 0x64, 0xff, 0x3a, 0x8e, - 0x1c, 0x01, 0xec, 0x17, 0x5c, 0xa7, 0x58, 0xf7, 0x2d, 0xd5, 0x7c, 0x69, 0xa5, 0xc4, 0xcb, 0xfb, 0xa9, 0xc4, 0x8e, - 0x45, 0xc1, 0x07, 0x01, 0x69, 0xb0, 0xe2, 0xe3, 0x38, 0x06, 0x34, 0x95, 0x0d, 0xb8, 0xee, 0x61, 0x86, 0x15, 0xa5, - 0xdb, 0x3d, 0xbe, 0x8f, 0x4f, 0x71, 0x42, 0xc0, 0x1f, 0x9d, 0x39, 0x58, 0xa4, 0x15, 0x6c, 0xe9, 0x71, 0x78, 0x71, - 0xb0, 0xea, 0x69, 0x9b, 0xa4, 0xb8, 0xe6, 0xc7, 0x6f, 0x8e, 0xd5, 0x5c, 0xb6, 0x34, 0x6b, 0xbd, 0x74, 0xf7, 0xc7, - 0x8b, 0x03, 0x6a, 0x2b, 0x6c, 0x64, 0x81, 0xa8, 0x06, 0x15, 0xb4, 0x0e, 0xb2, 0xaf, 0xd3, 0x4e, 0xa9, 0x81, 0x66, - 0xb4, 0x98, 0xca, 0x3e, 0xa9, 0xe7, 0x93, 0xb1, 0xb5, 0x68, 0x3c, 0xad, 0xc3, 0x26, 0xec, 0x98, 0x9c, 0xa7, 0x60, - 0x64, 0x92, 0xe2, 0xb9, 0x9c, 0xe1, 0x33, 0x0a, 0x20, 0x8a, 0xba, 0x2a, 0x01, 0x5a, 0x5d, 0x28, 0xf6, 0xda, 0x98, - 0x29, 0x01, 0x52, 0xe1, 0xcf, 0x2b, 0xad, 0xcb, 0x08, 0xc5, 0x91, 0xd7, 0x36, 0xaf, 0x34, 0x5f, 0x27, 0xb4, 0x0e, - 0x71, 0xec, 0xf5, 0x64, 0xbd, 0xad, 0x60, 0x0a, 0x50, 0x43, 0x86, 0xae, 0xa9, 0x03, 0xbe, 0xfb, 0xdd, 0x0c, 0x80, - 0x3f, 0x88, 0x3c, 0xb2, 0x4e, 0x34, 0x1b, 0x1e, 0x92, 0x47, 0xc0, 0xd9, 0x43, 0xe5, 0x2a, 0xae, 0xac, 0xec, 0x62, - 0xdd, 0x16, 0xb8, 0x57, 0xb2, 0xf1, 0x65, 0x13, 0xe4, 0x94, 0x3d, 0x67, 0xa9, 0x65, 0x43, 0xc4, 0x81, 0x4a, 0x52, - 0x9b, 0x6c, 0xb0, 0x94, 0x66, 0xf3, 0x2d, 0x2a, 0xcd, 0xf5, 0xd6, 0xf9, 0xc7, 0x80, 0x34, 0x9a, 0xab, 0xd2, 0xdc, - 0x01, 0x0a, 0x00, 0x93, 0x76, 0xf1, 0x4c, 0x93, 0x23, 0x0a, 0x51, 0x58, 0xc0, 0xa0, 0x82, 0xab, 0xb1, 0x77, 0xd4, - 0xec, 0xcc, 0x0e, 0x80, 0x1d, 0x77, 0x75, 0x2b, 0x76, 0xa9, 0x60, 0xbc, 0x89, 0x81, 0xea, 0x57, 0xe3, 0x40, 0xd1, - 0xa6, 0xa3, 0xcb, 0xa2, 0xe8, 0x42, 0x32, 0x57, 0x97, 0x2a, 0x4f, 0xf0, 0x10, 0x95, 0x29, 0x36, 0x6a, 0x22, 0x1c, - 0x40, 0xae, 0x57, 0xbe, 0x6e, 0x7c, 0xad, 0xe3, 0xeb, 0x41, 0x10, 0x70, 0x3f, 0x91, 0x34, 0x92, 0x80, 0x8d, 0xbc, - 0xc2, 0x3e, 0xae, 0x40, 0x5f, 0x7c, 0x6a, 0x2b, 0x72, 0x72, 0xa9, 0xd7, 0x92, 0xc9, 0x92, 0xd5, 0x6c, 0x7f, 0x93, - 0x13, 0x84, 0x3e, 0x25, 0x29, 0x85, 0x9c, 0x4e, 0x77, 0x50, 0x75, 0xc8, 0xe3, 0x75, 0x2c, 0x60, 0x92, 0x8d, 0x5e, - 0xba, 0xad, 0x2d, 0xac, 0xb9, 0x10, 0xde, 0x28, 0x1b, 0x61, 0x4e, 0xac, 0x2b, 0x52, 0xf3, 0x0b, 0x34, 0x5e, 0xbc, - 0xf1, 0x57, 0x2c, 0xb4, 0x7e, 0xe0, 0x2b, 0xd5, 0x89, 0x65, 0xb1, 0x9b, 0x39, 0x19, 0x2a, 0x25, 0x8b, 0xdb, 0xad, - 0x75, 0x08, 0x91, 0xa7, 0x49, 0x9b, 0x81, 0x5c, 0x02, 0x16, 0xc1, 0x13, 0x44, 0x58, 0x74, 0x18, 0x0a, 0x9b, 0xe6, - 0x3a, 0x7e, 0x1e, 0x3e, 0x9a, 0x10, 0x4b, 0xed, 0x8a, 0xa5, 0x25, 0x11, 0x7e, 0xf8, 0xcd, 0x36, 0x56, 0x89, 0xba, - 0xb5, 0x30, 0x49, 0x58, 0x9a, 0xde, 0xfb, 0x45, 0xdd, 0xa5, 0xaf, 0x80, 0x74, 0x58, 0x86, 0xad, 0x88, 0xdd, 0x8b, - 0xd1, 0xdd, 0xb8, 0x04, 0x48, 0x38, 0x92, 0x4e, 0x0a, 0xcd, 0x4b, 0x4a, 0xca, 0xcf, 0x5c, 0xdd, 0xa8, 0xd2, 0x0c, - 0xa2, 0x94, 0xf3, 0x3a, 0x51, 0x68, 0xb9, 0x27, 0x36, 0x09, 0x11, 0x19, 0x3e, 0x2f, 0x12, 0xe4, 0xad, 0xd6, 0x6f, - 0x7b, 0xe8, 0x20, 0xc0, 0x86, 0x4e, 0x01, 0x7a, 0x8c, 0x92, 0x61, 0x10, 0x98, 0x0d, 0x85, 0x3d, 0x1b, 0x54, 0x94, - 0x20, 0xb4, 0x2d, 0x98, 0x13, 0xa1, 0xcb, 0x37, 0x99, 0x66, 0x98, 0xfc, 0x3c, 0xed, 0xf2, 0xf1, 0xdd, 0x19, 0x2e, - 0x8f, 0x95, 0x77, 0x36, 0x9a, 0xf7, 0x80, 0xf4, 0x9c, 0xb4, 0xe9, 0xa1, 0x34, 0x51, 0x7a, 0x0f, 0x51, 0x4f, 0x0e, - 0xaf, 0x09, 0x56, 0xa1, 0x25, 0x4c, 0x8d, 0xe9, 0x56, 0xbb, 0xfb, 0x42, 0xa2, 0x77, 0x6d, 0xae, 0x10, 0xa5, 0xb5, - 0x1b, 0x6a, 0xb5, 0x87, 0xe6, 0x99, 0xa4, 0x79, 0xda, 0x95, 0xfa, 0x8e, 0x6b, 0x0a, 0x70, 0xda, 0x66, 0x7d, 0x4e, - 0xa0, 0x35, 0x00, 0x2d, 0x48, 0x0d, 0x12, 0x23, 0xe8, 0x89, 0x31, 0x4f, 0xc5, 0xde, 0x38, 0x5f, 0x53, 0x64, 0x15, - 0x13, 0x9a, 0x04, 0xbc, 0xed, 0xbd, 0x84, 0x70, 0x06, 0x81, 0x90, 0x48, 0xc7, 0xa3, 0x14, 0xab, 0xee, 0x17, 0xef, - 0x24, 0xc2, 0x96, 0x13, 0x35, 0x8c, 0x10, 0xce, 0x41, 0x83, 0x58, 0x80, 0x0a, 0x53, 0x1a, 0x06, 0x87, 0x01, 0x6b, - 0x06, 0x19, 0xd0, 0x79, 0x2b, 0xa5, 0x48, 0xb8, 0x20, 0x87, 0x44, 0xd1, 0x77, 0x25, 0xc4, 0x21, 0x2b, 0x72, 0x69, - 0xa0, 0xda, 0x3b, 0x18, 0x8d, 0x37, 0xe3, 0xb4, 0x94, 0x2e, 0x71, 0x46, 0x7d, 0x8c, 0x62, 0xa6, 0x80, 0x73, 0xfb, - 0x11, 0x73, 0xdd, 0x8d, 0xc8, 0xc5, 0xd0, 0xc7, 0x75, 0x5b, 0x69, 0x89, 0xeb, 0xe1, 0x9c, 0x22, 0x41, 0x15, 0x8d, - 0x0a, 0x6e, 0x1b, 0x85, 0xc8, 0x4e, 0x5d, 0x30, 0xaa, 0x42, 0x88, 0xc4, 0x10, 0xd5, 0x56, 0x85, 0xc5, 0x15, 0xb7, - 0x98, 0x24, 0xcc, 0x38, 0x8b, 0x88, 0x16, 0xf0, 0x3c, 0xdb, 0xff, 0x29, 0x8a, 0xde, 0x3c, 0xf2, 0x05, 0x55, 0xa0, - 0xff, 0xf6, 0x04, 0x63, 0xfc, 0xf8, 0xd6, 0x0f, 0x1f, 0xf7, 0x14, 0x4f, 0x3f, 0xef, 0xa9, 0x5f, 0x7f, 0xe2, 0xe3, - 0x48, 0x9e, 0xf1, 0x8b, 0xfd, 0x5b, 0x0c, 0x96, 0x19, 0x30, 0x65, 0x05, 0xcb, 0xfe, 0x6e, 0x65, 0x7a, 0xe7, 0x84, - 0x9c, 0xb6, 0xe1, 0x62, 0xcb, 0x78, 0x6c, 0x75, 0xb2, 0x06, 0x2a, 0xb2, 0x38, 0x56, 0xb0, 0x32, 0xcb, 0xd7, 0x3c, - 0xd7, 0x67, 0x97, 0xde, 0x9e, 0xb8, 0x23, 0x51, 0x25, 0x77, 0x1e, 0x80, 0x93, 0x92, 0xf5, 0xa3, 0x6f, 0x23, 0xff, - 0x11, 0xd5, 0x6e, 0x3b, 0x28, 0x11, 0x4a, 0x2c, 0xc9, 0x7e, 0x55, 0x5a, 0xd3, 0xaf, 0xb7, 0x98, 0xb3, 0xa6, 0x96, - 0x1b, 0x86, 0x87, 0x51, 0xfe, 0x48, 0xbe, 0xdc, 0xb1, 0x3e, 0x34, 0x8d, 0xe7, 0xe4, 0x69, 0xe8, 0xa5, 0x8b, 0x88, - 0x55, 0x58, 0xd0, 0xff, 0xab, 0xa7, 0xff, 0xbf, 0x18, 0x24, 0xd2, 0xe1, 0xb7, 0x41, 0x8f, 0x37, 0x0c, 0x10, 0x93, - 0x73, 0xbe, 0xd1, 0xc7, 0x3b, 0xf1, 0xaf, 0x3c, 0xcc, 0x9f, 0xb3, 0xfd, 0xdd, 0xe0, 0xef, 0xeb, 0xb2, 0xef, 0xfa, - 0xb5, 0x69, 0x0b, 0x69, 0x37, 0x48, 0xe3, 0x95, 0x1a, 0x13, 0x34, 0xab, 0xc6, 0x91, 0xd1, 0x54, 0x8f, 0x47, 0x55, - 0x88, 0xac, 0x29, 0xc7, 0x4e, 0x7f, 0x08, 0x3a, 0x28, 0x78, 0x1c, 0x0d, 0x95, 0xe5, 0x99, 0x34, 0x47, 0xb5, 0x0d, - 0x4c, 0xf6, 0x66, 0xd4, 0x56, 0x2c, 0x16, 0xd6, 0xd6, 0x6c, 0xe2, 0xd9, 0xa3, 0xf1, 0xae, 0x56, 0xc6, 0xc6, 0x03, - 0xa9, 0x27, 0x17, 0xa7, 0x19, 0x91, 0x58, 0x8c, 0x91, 0x6d, 0xb9, 0xa9, 0x2f, 0x7b, 0xe5, 0x2d, 0xfa, 0xf3, 0x8a, - 0x3f, 0x9a, 0x9b, 0xba, 0x88, 0x51, 0xaf, 0x07, 0xdd, 0x1f, 0x9e, 0x2b, 0x71, 0x71, 0x58, 0xec, 0x7c, 0x8d, 0x0f, - 0x87, 0x1d, 0xbf, 0xda, 0x9c, 0x63, 0xea, 0x25, 0xc1, 0x86, 0x7e, 0x1a, 0x1c, 0xcd, 0xfd, 0xa3, 0xc1, 0x15, 0x03, - 0x7a, 0x20, 0x95, 0x9b, 0x22, 0xcd, 0x08, 0x30, 0x51, 0x3c, 0xd6, 0x5c, 0xaf, 0x73, 0x0f, 0xf1, 0xd5, 0xb6, 0x40, - 0x62, 0xc4, 0xe9, 0xf4, 0x62, 0x48, 0x24, 0x98, 0x98, 0x9e, 0xd2, 0x5e, 0x5c, 0x3e, 0x19, 0xde, 0x22, 0x3a, 0x1b, - 0xd7, 0xde, 0xde, 0xf9, 0xcc, 0x77, 0x89, 0x6b, 0x7c, 0x61, 0xb9, 0xcc, 0x2e, 0x30, 0x8d, 0x78, 0x0d, 0x54, 0x88, - 0x71, 0x60, 0x28, 0x7e, 0x82, 0xfe, 0x72, 0x21, 0x02, 0xb5, 0xcc, 0x68, 0x97, 0xb6, 0x37, 0x69, 0xec, 0xd8, 0x79, - 0x2e, 0x77, 0x09, 0x94, 0x38, 0x2e, 0x52, 0x6b, 0xbe, 0x73, 0x3f, 0x38, 0xd6, 0x85, 0xe1, 0xbe, 0x6e, 0xa3, 0xe4, - 0xdb, 0xca, 0xa9, 0x6e, 0x79, 0x14, 0xee, 0x88, 0xe1, 0x68, 0x6c, 0x53, 0xfa, 0x99, 0x2d, 0x72, 0xa3, 0x7c, 0xd2, - 0x0b, 0x51, 0xfe, 0x04, 0xd8, 0x9a, 0xe1, 0x2e, 0x58, 0xaf, 0xcf, 0x01, 0xa2, 0xae, 0xae, 0xd6, 0xf6, 0x7c, 0x31, - 0xfa, 0x5d, 0xe1, 0xde, 0xf2, 0x20, 0xc1, 0x98, 0xb6, 0x39, 0x9e, 0xc8, 0xbe, 0x72, 0x5a, 0x09, 0x5d, 0xe7, 0xe0, - 0x34, 0x71, 0x7f, 0x3c, 0x87, 0x9e, 0xab, 0x91, 0xbc, 0x4b, 0x09, 0x97, 0x29, 0x53, 0x92, 0x31, 0xbd, 0xbb, 0x3a, - 0xc0, 0x76, 0xe8, 0xa0, 0x48, 0xb3, 0x0e, 0xc2, 0x20, 0xe1, 0xa9, 0x0d, 0x3e, 0xdd, 0x33, 0x06, 0x1f, 0x3f, 0x53, - 0xce, 0x2b, 0x5a, 0x55, 0x09, 0x9f, 0x57, 0x1f, 0xf2, 0xfb, 0xef, 0x50, 0x41, 0xd6, 0x37, 0x6b, 0x64, 0xc3, 0xae, - 0x2c, 0x0f, 0x10, 0xe7, 0x51, 0x84, 0xfd, 0x80, 0xce, 0x7e, 0xcc, 0xc2, 0xa6, 0x7d, 0x18, 0x3f, 0xf9, 0xa6, 0xe9, - 0x7a, 0xde, 0x99, 0xd6, 0x9c, 0x1f, 0x7c, 0xd8, 0x2b, 0xe1, 0x40, 0xb7, 0xb3, 0xf4, 0xbf, 0x88, 0x18, 0x20, 0x18, - 0x6c, 0xfe, 0xbe, 0x9c, 0x0f, 0xcf, 0x1e, 0xf2, 0x73, 0x44, 0xe4, 0x0e, 0x37, 0xb1, 0x77, 0xfc, 0x2e, 0xaf, 0x2a, - 0xc3, 0x06, 0xf2, 0x8a, 0x73, 0x19, 0xe1, 0xf2, 0xd6, 0xba, 0x6b, 0xc5, 0xb6, 0x24, 0x0b, 0xae, 0x25, 0x40, 0x61, - 0x64, 0x72, 0xc8, 0xed, 0xf2, 0x3f, 0x2b, 0xb6, 0x20, 0x21, 0xaa, 0x9d, 0xd4, 0x5d, 0xbd, 0x77, 0xae, 0x36, 0x55, - 0x1e, 0xfb, 0x87, 0x8f, 0x72, 0xe6, 0x0c, 0xa3, 0x0a, 0x77, 0x6c, 0xb3, 0x87, 0x2a, 0xa3, 0x36, 0x19, 0x13, 0x87, - 0x2a, 0xed, 0xac, 0xef, 0xa9, 0x58, 0x7a, 0x8c, 0x58, 0x62, 0x20, 0x23, 0x33, 0x1b, 0x92, 0xf6, 0xde, 0xec, 0x17, - 0x5e, 0x2f, 0xae, 0xb8, 0x4c, 0x08, 0x20, 0x6b, 0x63, 0xa0, 0xab, 0xad, 0x34, 0xec, 0xed, 0xf6, 0x7e, 0xfa, 0x28, - 0xbb, 0x3e, 0xe8, 0x1f, 0xe6, 0x0f, 0x5c, 0xaa, 0x35, 0x2b, 0xa7, 0xd6, 0xb2, 0xed, 0x15, 0xed, 0xd0, 0xeb, 0x2d, - 0xb3, 0xe9, 0x12, 0xd6, 0x23, 0xc9, 0xa2, 0xa5, 0x3c, 0xae, 0xaa, 0x4e, 0xd5, 0xb0, 0xdb, 0x34, 0x75, 0x9f, 0x39, - 0xbe, 0x43, 0x0a, 0x65, 0x59, 0x99, 0xd2, 0x27, 0xcf, 0x9c, 0x78, 0xaa, 0x28, 0x83, 0x39, 0x13, 0xdc, 0x96, 0x93, - 0x11, 0xa9, 0x88, 0xd7, 0x18, 0xcd, 0x0f, 0x01, 0xab, 0xb8, 0xae, 0x9f, 0x78, 0x14, 0x97, 0x0e, 0xae, 0xb3, 0xa1, - 0x6e, 0x3e, 0x5f, 0x13, 0x92, 0x96, 0x89, 0xf3, 0x69, 0xc0, 0xd7, 0x40, 0xd7, 0x47, 0x91, 0x02, 0xc0, 0x71, 0x26, - 0x93, 0xca, 0x7e, 0xd4, 0x91, 0xf3, 0x7e, 0xd3, 0x7c, 0xb5, 0x3e, 0xbb, 0xc8, 0xd7, 0xad, 0xf1, 0xab, 0xe1, 0x34, - 0x8f, 0x9e, 0x96, 0x9e, 0xf6, 0xf5, 0x79, 0xa6, 0x12, 0xc5, 0xfe, 0xca, 0x99, 0xbd, 0x51, 0xde, 0x15, 0xab, 0xec, - 0x2e, 0x7a, 0x78, 0xd7, 0xcf, 0x09, 0x70, 0xf8, 0x6e, 0x57, 0x20, 0xf2, 0xc3, 0xb2, 0x79, 0x8a, 0xcb, 0xa9, 0xb1, - 0x53, 0x94, 0x82, 0x19, 0x8d, 0xad, 0x88, 0x67, 0x6a, 0x26, 0xb0, 0x5e, 0xed, 0xe5, 0x61, 0x5a, 0x36, 0xa4, 0x19, - 0x7f, 0x58, 0x8b, 0xd1, 0x0e, 0x93, 0x07, 0x59, 0x06, 0xb3, 0xc8, 0xfa, 0xd0, 0x1c, 0x9d, 0xba, 0x62, 0xd2, 0xf6, - 0xd4, 0x29, 0x0b, 0xb7, 0x0f, 0xd6, 0xd8, 0x25, 0xe5, 0x50, 0x95, 0xe7, 0xef, 0xd7, 0x78, 0xe5, 0xb9, 0x48, 0xc6, - 0x3b, 0x70, 0xde, 0xb2, 0xdf, 0xc6, 0x09, 0x62, 0xdc, 0xd8, 0x6a, 0x7c, 0x16, 0x1b, 0x77, 0x82, 0x96, 0x09, 0xe4, - 0xec, 0xc1, 0x02, 0x9c, 0x86, 0x37, 0x45, 0xa6, 0xb5, 0xfc, 0x6c, 0x08, 0x78, 0x6f, 0xe8, 0x77, 0x75, 0x0b, 0x00, - 0x8b, 0xc8, 0x7b, 0xbd, 0x52, 0x9c, 0x2e, 0x8d, 0xc3, 0xc7, 0xdd, 0x95, 0xe2, 0x51, 0xda, 0x4d, 0x74, 0x77, 0xca, - 0x33, 0x48, 0x41, 0xbc, 0x7c, 0xa5, 0x5a, 0x8c, 0xaa, 0x97, 0xc8, 0x09, 0x04, 0x2c, 0x52, 0x8a, 0xff, 0xac, 0x7b, - 0x02, 0x2b, 0xd5, 0x77, 0xfc, 0xaa, 0x7a, 0x41, 0xac, 0x01, 0xbb, 0x6d, 0xb9, 0x85, 0x9e, 0x2a, 0x81, 0x7c, 0x00, - 0x99, 0x0b, 0xc0, 0xc0, 0xfd, 0xbb, 0x6e, 0xc2, 0xf5, 0x9f, 0x47, 0x99, 0x6f, 0x75, 0x5b, 0xae, 0xcf, 0xe6, 0xd1, - 0xd9, 0x8c, 0x9d, 0x90, 0x2f, 0x27, 0x7d, 0x09, 0x8a, 0xc9, 0xa6, 0x80, 0xfa, 0x21, 0xb3, 0x0f, 0xdb, 0xae, 0x72, - 0x46, 0x40, 0xb5, 0x7d, 0xae, 0x20, 0x61, 0xa0, 0xe5, 0x9e, 0xac, 0xcd, 0x47, 0xbe, 0xd2, 0xe6, 0xed, 0xfc, 0xfc, - 0xef, 0xbc, 0xe5, 0xa1, 0x83, 0xba, 0xff, 0x8a, 0xc5, 0x55, 0xfe, 0x4e, 0x46, 0x91, 0xed, 0xc3, 0x76, 0xf3, 0x6e, - 0x24, 0xc4, 0x05, 0xa7, 0xfc, 0x07, 0x9f, 0xbf, 0x94, 0x2e, 0xbc, 0xde, 0xc5, 0xa0, 0xf4, 0x11, 0x6a, 0xdc, 0x98, - 0xdb, 0x22, 0x91, 0xeb, 0x4a, 0x20, 0xf2, 0xd8, 0xc1, 0xa8, 0xe7, 0xb5, 0x4b, 0x6e, 0x00, 0xa3, 0x6e, 0xc7, 0xc3, - 0x03, 0x6d, 0x4a, 0x7f, 0x32, 0xe1, 0x46, 0x0b, 0x55, 0xc4, 0x1d, 0xa3, 0xe6, 0x03, 0x45, 0xe2, 0x15, 0x06, 0x08, - 0xd0, 0xad, 0xcf, 0xa3, 0xe8, 0x6d, 0x9a, 0xf7, 0x43, 0xb1, 0x9d, 0xa6, 0x2c, 0x50, 0xc0, 0x78, 0x32, 0x47, 0xb4, - 0xec, 0x89, 0x7d, 0xba, 0x3b, 0x1d, 0x56, 0x46, 0x6f, 0x71, 0x6d, 0xea, 0x72, 0xaf, 0xaf, 0xda, 0xce, 0xd6, 0x09, - 0xf7, 0x34, 0x6c, 0xe3, 0x0a, 0x12, 0x36, 0x72, 0x2a, 0x7a, 0xae, 0xe8, 0x6b, 0x3a, 0x2b, 0xe1, 0x1a, 0xf3, 0x2d, - 0x02, 0x60, 0x4d, 0x06, 0xf9, 0x4b, 0x31, 0x3d, 0x43, 0x45, 0xde, 0xb3, 0x39, 0x7b, 0x27, 0xd3, 0x29, 0x7b, 0x6b, - 0x48, 0x29, 0x17, 0x98, 0xcf, 0x1e, 0x10, 0xa6, 0x79, 0xe8, 0x6d, 0x24, 0xc9, 0xcc, 0xd3, 0x96, 0xbc, 0xa9, 0xee, - 0x69, 0x22, 0x78, 0x50, 0xca, 0xb3, 0xde, 0x4f, 0xde, 0x0d, 0xeb, 0x82, 0xf1, 0xbc, 0x23, 0x1c, 0x28, 0x3e, 0x97, - 0xbd, 0x09, 0xee, 0x3e, 0xcf, 0x7f, 0x34, 0x27, 0xdb, 0x5a, 0x1b, 0xe4, 0xe6, 0x27, 0x59, 0xbf, 0x90, 0xf3, 0x89, - 0x27, 0xbd, 0xfa, 0xf8, 0x93, 0x7e, 0x91, 0x08, 0x65, 0xd7, 0xa9, 0x09, 0xf6, 0x88, 0x3f, 0x4f, 0x30, 0x80, 0xcd, - 0x62, 0xb2, 0xa4, 0x1a, 0x2d, 0xab, 0x28, 0x6f, 0xe9, 0xb4, 0x99, 0xe2, 0x97, 0xda, 0xd3, 0x69, 0xac, 0xf0, 0x56, - 0x0b, 0xcf, 0xd8, 0x6e, 0xc1, 0xda, 0x66, 0xda, 0x92, 0x25, 0xa7, 0x74, 0xed, 0x83, 0x1d, 0x7f, 0x58, 0x03, 0xa8, - 0x22, 0xca, 0x95, 0xf4, 0xb2, 0x12, 0x7f, 0xe0, 0xb3, 0x5d, 0x84, 0x57, 0x03, 0xaf, 0xaa, 0x99, 0xa7, 0x5a, 0x3d, - 0xb0, 0xdd, 0xf4, 0x69, 0x6f, 0x25, 0x3b, 0xde, 0x51, 0x9c, 0xf0, 0x2a, 0xa1, 0xe3, 0x5c, 0xb6, 0xd0, 0xf5, 0xd3, - 0x5d, 0x58, 0xd8, 0xf7, 0x5f, 0xa0, 0x47, 0x0e, 0x26, 0x6e, 0xe7, 0x67, 0xf6, 0x0a, 0x5a, 0x07, 0x8a, 0x6c, 0x0f, - 0xaf, 0x3b, 0x2b, 0x2c, 0xc2, 0x08, 0x29, 0xff, 0xa5, 0xe1, 0x2d, 0xda, 0xbd, 0x2a, 0x2d, 0xc1, 0xf8, 0xec, 0x5d, - 0xd5, 0xd8, 0xb6, 0x03, 0x65, 0x3a, 0x5b, 0x47, 0xca, 0x05, 0xed, 0x80, 0x91, 0x82, 0xd3, 0x9d, 0x55, 0xdf, 0xff, - 0x3a, 0x99, 0x6a, 0x75, 0x8f, 0xed, 0x70, 0x26, 0xba, 0x53, 0x8c, 0x03, 0x68, 0x09, 0x85, 0xac, 0xad, 0x4e, 0xfd, - 0x7b, 0x9f, 0xad, 0xd7, 0xbc, 0x63, 0x5a, 0xac, 0x34, 0x2f, 0x78, 0x42, 0x6b, 0x1b, 0x9e, 0xb4, 0x18, 0xf7, 0x56, - 0x29, 0x27, 0x42, 0x82, 0x86, 0x6e, 0x39, 0x1f, 0xe4, 0x15, 0x1e, 0xd4, 0x40, 0x25, 0xb8, 0x36, 0x0e, 0xa1, 0x0e, - 0xad, 0x2d, 0xeb, 0xdd, 0x95, 0x18, 0xb7, 0xc0, 0xb5, 0xec, 0xc6, 0xd9, 0x1d, 0xce, 0xad, 0xc3, 0x46, 0xab, 0x91, - 0xdd, 0xe8, 0x0f, 0x43, 0x0f, 0x22, 0x85, 0x9b, 0x1d, 0x4d, 0xb7, 0x1d, 0x46, 0x7b, 0x0e, 0x9d, 0x17, 0x6d, 0x8c, - 0x89, 0x30, 0x33, 0x69, 0x33, 0xdf, 0xc5, 0xe5, 0x4c, 0x1b, 0x96, 0xf2, 0x01, 0x5a, 0x03, 0x08, 0x88, 0xb2, 0x50, - 0xd1, 0x2e, 0x72, 0x9a, 0xed, 0x42, 0x6d, 0xb8, 0xa1, 0x44, 0x2c, 0x82, 0x40, 0xde, 0x40, 0xc8, 0x9f, 0x6a, 0x17, - 0x7e, 0x4d, 0xb0, 0x51, 0x30, 0x83, 0x39, 0xd1, 0x50, 0x63, 0x42, 0x90, 0x3e, 0xb5, 0x52, 0x96, 0x3e, 0xe4, 0x8c, - 0x84, 0xd0, 0x82, 0x1a, 0x55, 0xcb, 0x23, 0x72, 0x9b, 0x6e, 0xe6, 0xf0, 0xb9, 0xa8, 0x38, 0x2a, 0xbd, 0x74, 0x9b, - 0x79, 0x06, 0x1f, 0x75, 0x18, 0x7b, 0x2e, 0xc0, 0x38, 0xd8, 0x39, 0x09, 0xe0, 0x2f, 0xe2, 0x7f, 0x0d, 0xc0, 0x13, - 0x2c, 0x2a, 0xd3, 0x5a, 0x57, 0x6f, 0x60, 0xca, 0x29, 0x8a, 0xd9, 0xf2, 0x14, 0xbd, 0x89, 0xbd, 0xd6, 0xbe, 0x0c, - 0xa4, 0xc4, 0x47, 0x16, 0x3a, 0x7a, 0xeb, 0xc9, 0x4e, 0xcf, 0x40, 0x64, 0xfc, 0x6a, 0xec, 0xfd, 0x71, 0x73, 0xb5, - 0x1b, 0x86, 0xf8, 0x16, 0x05, 0xec, 0xcc, 0x7b, 0xe7, 0xf8, 0xe4, 0xb3, 0x38, 0x4c, 0xe8, 0xcd, 0x41, 0x68, 0x5c, - 0xcf, 0x42, 0xc9, 0xf8, 0xc8, 0xcb, 0x85, 0xfb, 0xb2, 0x0d, 0xb6, 0x33, 0x3e, 0xf9, 0xf4, 0xd0, 0x07, 0x82, 0x87, - 0x4c, 0x49, 0x50, 0x73, 0xa0, 0xbb, 0x36, 0x8d, 0x80, 0xa5, 0x37, 0x79, 0xa1, 0x99, 0xd7, 0xc1, 0xb2, 0x67, 0x28, - 0x40, 0x08, 0x70, 0x20, 0x47, 0xa0, 0x68, 0x7a, 0x37, 0x1a, 0x70, 0x11, 0x7c, 0x58, 0xe4, 0x1c, 0xfe, 0x37, 0x0d, - 0xf7, 0x5d, 0xee, 0xf9, 0xeb, 0x5c, 0x0c, 0x3e, 0xb5, 0x43, 0xdf, 0xb7, 0x03, 0xe1, 0xca, 0xef, 0x78, 0x11, 0x7c, - 0x72, 0x89, 0x90, 0xae, 0x0d, 0x5e, 0x63, 0xe2, 0xdd, 0x8d, 0x90, 0xfb, 0x50, 0x78, 0xb9, 0xc4, 0x03, 0xe6, 0xda, - 0xf4, 0xc6, 0x9c, 0xf9, 0xad, 0xe8, 0x4d, 0x33, 0x47, 0x07, 0xa3, 0x23, 0xbb, 0x1f, 0x61, 0x6d, 0xe7, 0x5f, 0xfa, - 0x57, 0x60, 0x8d, 0xee, 0x67, 0x91, 0x7c, 0x3a, 0xde, 0x56, 0x00, 0x4b, 0x83, 0x0f, 0x64, 0x38, 0xaf, 0x63, 0x0c, - 0x6b, 0xe8, 0x3e, 0xea, 0x7e, 0x25, 0xc0, 0x86, 0x30, 0x0e, 0x95, 0x81, 0xa9, 0x37, 0x30, 0x45, 0xee, 0xff, 0xb3, - 0x8a, 0xfa, 0xb8, 0x61, 0x62, 0x2e, 0x87, 0x34, 0x00, 0x12, 0x0a, 0x7e, 0xee, 0x1e, 0x13, 0xad, 0xd8, 0x43, 0x46, - 0x6b, 0x94, 0x89, 0x47, 0xb2, 0xc9, 0xaf, 0x7a, 0x77, 0xa4, 0xac, 0x0f, 0x7c, 0x2f, 0x9b, 0xbc, 0x4f, 0x98, 0x7b, - 0xce, 0xdf, 0x69, 0x03, 0xa8, 0x5c, 0x8a, 0xb3, 0x8a, 0x7a, 0x09, 0x58, 0x13, 0x39, 0x7e, 0x5a, 0x98, 0x0c, 0x37, - 0x6a, 0x7e, 0x93, 0x45, 0xe0, 0x1e, 0x90, 0xa6, 0xd0, 0x2c, 0x28, 0x57, 0xc8, 0x22, 0xf9, 0x90, 0x9c, 0x3e, 0x20, - 0xd6, 0x85, 0xbc, 0x0d, 0xb5, 0xc5, 0x32, 0x12, 0x93, 0x7b, 0x89, 0x89, 0x57, 0xde, 0x32, 0xb6, 0xc4, 0x58, 0xb4, - 0xa6, 0xec, 0x52, 0x88, 0xbc, 0x51, 0x65, 0xd8, 0xd4, 0x65, 0x06, 0x13, 0xa5, 0x75, 0x3f, 0x3c, 0xc6, 0x51, 0x95, - 0x9e, 0x49, 0x8f, 0x80, 0xad, 0x70, 0xb6, 0x98, 0xd4, 0x55, 0x90, 0xc0, 0xf9, 0x40, 0x78, 0x28, 0x1f, 0x88, 0x15, - 0xaa, 0xb8, 0xf8, 0x13, 0x0e, 0x27, 0xd0, 0x2d, 0xc9, 0x2d, 0xab, 0x8e, 0xeb, 0x78, 0x9f, 0x43, 0x8e, 0x22, 0x51, - 0x02, 0x6d, 0xf0, 0x3b, 0x15, 0xd2, 0x43, 0x06, 0x0b, 0x50, 0x0e, 0x03, 0x3a, 0x3c, 0x18, 0x25, 0xa6, 0xe0, 0xf0, - 0xf0, 0x20, 0x12, 0x79, 0x59, 0xc8, 0x9f, 0x0e, 0xce, 0x3a, 0x54, 0x7d, 0x65, 0xf0, 0xdf, 0xc1, 0xb5, 0x45, 0x28, - 0x4e, 0x4c, 0xac, 0x63, 0x14, 0x1c, 0xdc, 0xba, 0x4d, 0x65, 0xc3, 0x9f, 0x7a, 0x7f, 0xad, 0xf0, 0x68, 0xe9, 0xc1, - 0xea, 0xbc, 0xad, 0x02, 0x9e, 0x0d, 0x4a, 0x8f, 0x35, 0x4f, 0xac, 0x7d, 0xc5, 0xc9, 0x81, 0x04, 0xa6, 0x49, 0x6f, - 0x6b, 0xcb, 0xf8, 0x05, 0xf1, 0xcb, 0x3d, 0x0b, 0x2f, 0xfc, 0x76, 0xd4, 0x12, 0x8b, 0xf5, 0xa9, 0x14, 0x7b, 0x2d, - 0x0d, 0x37, 0xd2, 0x06, 0x59, 0xbf, 0xd3, 0x3a, 0xcf, 0x8d, 0x45, 0x7a, 0x63, 0xff, 0x48, 0xc4, 0xdb, 0x19, 0xea, - 0x53, 0x28, 0xb1, 0x9e, 0x41, 0xf4, 0x6a, 0x48, 0x7d, 0xd1, 0x1a, 0x91, 0xa2, 0x70, 0xd9, 0xea, 0xf2, 0x22, 0x66, - 0x60, 0x8c, 0x68, 0xf5, 0x8a, 0x2d, 0x25, 0x86, 0xf7, 0x42, 0xa4, 0x56, 0xe9, 0xa9, 0xee, 0x8a, 0x62, 0xd3, 0x25, - 0x65, 0xd3, 0x46, 0x68, 0x2b, 0x0a, 0xec, 0x20, 0x94, 0xa2, 0x40, 0x2b, 0xe3, 0xb0, 0x87, 0x7a, 0x8b, 0xcc, 0x68, - 0xa3, 0x14, 0x36, 0xf3, 0x34, 0x02, 0xb8, 0xb9, 0x55, 0x13, 0x69, 0x17, 0x25, 0xce, 0x65, 0xb4, 0x4c, 0xb2, 0xde, - 0xb2, 0x52, 0xb8, 0x2f, 0x64, 0x38, 0x31, 0x3a, 0x36, 0xc0, 0x97, 0xc7, 0xff, 0xef, 0x0f, 0x60, 0xcd, 0xd2, 0x61, - 0x48, 0x5e, 0x43, 0x75, 0x84, 0xd0, 0x8c, 0x3d, 0xea, 0x72, 0x80, 0x22, 0x75, 0x6d, 0xa9, 0x65, 0x6e, 0x47, 0x39, - 0xc6, 0x85, 0x2b, 0xcf, 0xdb, 0xc5, 0x82, 0x0e, 0x0b, 0x23, 0x3e, 0xcc, 0x37, 0x18, 0x4b, 0xae, 0x14, 0xdd, 0x32, - 0x19, 0x81, 0x49, 0x75, 0xc5, 0x0b, 0xe7, 0x0b, 0x5e, 0xc9, 0xf4, 0x07, 0xf9, 0x48, 0x4e, 0xa5, 0x31, 0x1b, 0xab, - 0x0d, 0xa1, 0x26, 0x82, 0x36, 0x4f, 0x4b, 0xa4, 0xdb, 0x2e, 0x4d, 0x2c, 0x50, 0x18, 0x96, 0x46, 0xe8, 0xaa, 0x49, - 0x58, 0xf3, 0xb3, 0xab, 0x05, 0x89, 0x87, 0x49, 0x57, 0xcd, 0x55, 0x70, 0x6e, 0xed, 0xb1, 0xd3, 0x47, 0x7a, 0x2c, - 0x82, 0x56, 0xb3, 0x0b, 0xa5, 0x35, 0x68, 0xcd, 0x2d, 0xb3, 0x36, 0x6c, 0xc0, 0x2b, 0xe7, 0x32, 0xc5, 0x19, 0x35, - 0xbc, 0xb1, 0x31, 0x84, 0xc9, 0x4f, 0xc5, 0x79, 0xf2, 0x7f, 0x66, 0x0b, 0x97, 0xa6, 0x6e, 0xdd, 0x14, 0x57, 0x1c, - 0x48, 0x31, 0x1f, 0xc4, 0xc3, 0x79, 0x11, 0xc9, 0x9b, 0xeb, 0x5e, 0x46, 0x9c, 0x0e, 0xf4, 0x82, 0xac, 0x62, 0x87, - 0xbe, 0x93, 0x1f, 0xf5, 0xa8, 0xc4, 0x19, 0x8c, 0x65, 0x03, 0xb1, 0x04, 0x82, 0xf8, 0xae, 0x7d, 0x88, 0xe4, 0xc6, - 0xa5, 0x5a, 0x97, 0x07, 0xb2, 0xe5, 0x45, 0x90, 0x78, 0xe7, 0xee, 0x5e, 0x33, 0xc6, 0x4b, 0x7c, 0x42, 0x3e, 0x5e, - 0x10, 0xbc, 0x72, 0x0b, 0xe4, 0x0e, 0xd7, 0xc1, 0x03, 0xf1, 0x51, 0x82, 0x17, 0x23, 0x89, 0x7b, 0xa9, 0x43, 0x85, - 0xa0, 0x45, 0x4f, 0x30, 0x22, 0x91, 0x7c, 0xb5, 0xb6, 0x2e, 0x88, 0x02, 0x4d, 0xb0, 0x5e, 0x3c, 0x8a, 0x9a, 0x56, - 0x9f, 0xa0, 0xcc, 0x08, 0xb9, 0x63, 0xab, 0x83, 0x1e, 0xdf, 0xe7, 0xa1, 0x60, 0xf6, 0xae, 0x49, 0x84, 0xfb, 0x5d, - 0x56, 0xb7, 0x3b, 0x20, 0x19, 0xfe, 0xa4, 0x55, 0xf7, 0x72, 0x0a, 0x69, 0x48, 0x43, 0x59, 0x7c, 0xf0, 0x56, 0x09, - 0x4e, 0x1e, 0xb2, 0xac, 0x4f, 0x8b, 0x31, 0x23, 0x25, 0x05, 0x25, 0x86, 0xe5, 0x52, 0x49, 0xd9, 0xe1, 0x10, 0x5b, - 0x62, 0x2f, 0xba, 0x3e, 0xfc, 0xbe, 0xa5, 0x0f, 0x00, 0x0f, 0xe5, 0x66, 0xfa, 0xda, 0x42, 0x54, 0xc0, 0xd0, 0xcc, - 0x7e, 0xca, 0xa7, 0xf5, 0xec, 0x7f, 0x3f, 0x60, 0x1f, 0x33, 0xf6, 0x9b, 0xc7, 0x38, 0xe0, 0xa7, 0x3c, 0xb4, 0x7c, - 0x8d, 0x8a, 0xee, 0x71, 0x5a, 0xcd, 0x7d, 0x69, 0x86, 0x18, 0x38, 0x09, 0x1e, 0xee, 0x72, 0x48, 0x83, 0xfc, 0xb3, - 0x35, 0x24, 0x9b, 0x60, 0x69, 0x2c, 0xb0, 0x42, 0xd6, 0x7c, 0xba, 0x0b, 0x2e, 0xb6, 0x92, 0x82, 0x27, 0x35, 0xb0, - 0xca, 0xf5, 0x26, 0xe6, 0xdc, 0xa4, 0x66, 0x77, 0x04, 0x12, 0xc8, 0x26, 0xb3, 0xbd, 0xa4, 0xe4, 0xaf, 0x89, 0x29, - 0xe9, 0xf7, 0x8d, 0x84, 0x08, 0x80, 0x95, 0x3e, 0x21, 0xba, 0xe0, 0xab, 0x58, 0x93, 0x4c, 0x3a, 0x96, 0x1a, 0xd5, - 0x56, 0x0a, 0xe8, 0x7a, 0xe1, 0x9f, 0xbd, 0xb9, 0x19, 0xcd, 0xa6, 0xe4, 0x4e, 0xe5, 0x0d, 0xf9, 0x14, 0xfc, 0xb5, - 0x19, 0x6d, 0xad, 0x86, 0x89, 0xa1, 0x8f, 0x01, 0xb4, 0xf7, 0x07, 0x78, 0xe1, 0xd1, 0x0a, 0x4b, 0x0a, 0x74, 0x8a, - 0x85, 0xce, 0x4b, 0x98, 0x7b, 0x58, 0x70, 0x54, 0xf2, 0xdd, 0x3b, 0xcc, 0xe3, 0xfa, 0xd6, 0x11, 0x24, 0x65, 0x3b, - 0xd3, 0xe9, 0x52, 0x2b, 0x12, 0xd0, 0xeb, 0x8c, 0x55, 0x22, 0xae, 0x49, 0x4e, 0x6e, 0xf8, 0xca, 0xc8, 0x68, 0x11, - 0x63, 0x1c, 0x53, 0x41, 0x1f, 0x2f, 0xbd, 0xcd, 0x0b, 0xc3, 0xbb, 0x3d, 0xa6, 0x95, 0x1e, 0x39, 0xc0, 0x55, 0xc2, - 0x4c, 0x19, 0xb4, 0x89, 0x78, 0xdc, 0x0f, 0x10, 0x05, 0x62, 0xa1, 0xd3, 0xc8, 0x51, 0x6a, 0xec, 0xfe, 0x88, 0xbd, - 0x80, 0x32, 0xaf, 0x99, 0x41, 0xd1, 0xf0, 0x5b, 0xfd, 0x95, 0xff, 0x8f, 0x1f, 0x67, 0x5e, 0xed, 0x47, 0x6f, 0x52, - 0x56, 0x9a, 0x03, 0xd5, 0xc8, 0x01, 0x77, 0x8f, 0xdb, 0x3b, 0xd7, 0x10, 0x61, 0x78, 0x2e, 0xab, 0xf1, 0x4e, 0x0f, - 0xed, 0xf6, 0x39, 0xfc, 0x9c, 0xdd, 0xae, 0xf9, 0xdd, 0xef, 0xfe, 0x44, 0x1e, 0x74, 0x0d, 0x17, 0x11, 0x1d, 0x30, - 0x5e, 0x5e, 0x6d, 0xd0, 0x9c, 0x67, 0xf9, 0x01, 0xec, 0x3d, 0xbe, 0x35, 0x52, 0x7d, 0xaa, 0x78, 0x85, 0x08, 0xc8, - 0x5b, 0xa5, 0xba, 0x4a, 0xc4, 0xbe, 0xc0, 0x66, 0x91, 0x01, 0x7d, 0xd6, 0xa1, 0x6b, 0xb5, 0x53, 0xc4, 0xcb, 0xcb, - 0x39, 0xe1, 0x87, 0x9b, 0x4e, 0x40, 0x93, 0xdc, 0x79, 0xcb, 0x3b, 0x5b, 0xe2, 0xac, 0xa7, 0x8c, 0x76, 0x9d, 0x5c, - 0x35, 0x0a, 0x48, 0x3b, 0x26, 0x22, 0xd3, 0xd6, 0xdc, 0x76, 0xed, 0xf8, 0x4a, 0xa1, 0xdf, 0xe1, 0xd5, 0xe5, 0x86, - 0x47, 0x43, 0x39, 0xa9, 0x36, 0xc9, 0xab, 0x2d, 0x9b, 0xc9, 0x49, 0x3f, 0xda, 0xda, 0x43, 0xf0, 0xd1, 0x0d, 0x1f, - 0x67, 0xca, 0x7e, 0xa7, 0x61, 0x9f, 0x67, 0xad, 0xfd, 0x55, 0xc2, 0x70, 0x2f, 0x9f, 0xa4, 0x09, 0xda, 0x38, 0xa7, - 0x54, 0x62, 0x0e, 0x78, 0x89, 0xde, 0xf2, 0x20, 0x6c, 0xa6, 0x29, 0xd5, 0xab, 0xca, 0xe5, 0x66, 0x4a, 0xe4, 0x9c, - 0xe8, 0xb1, 0xdb, 0x2c, 0x6e, 0x8a, 0x6b, 0xb0, 0x33, 0x03, 0x26, 0xa1, 0xb5, 0xef, 0xb6, 0x23, 0x3b, 0x38, 0xb7, - 0xfd, 0x61, 0xfc, 0x17, 0x98, 0x27, 0xf2, 0x7c, 0x8e, 0x15, 0x1b, 0xaf, 0xe7, 0xef, 0xfe, 0x1e, 0x03, 0xf6, 0xf9, - 0x98, 0x0d, 0x79, 0xe9, 0xed, 0xc7, 0xd1, 0x3c, 0xee, 0xc7, 0xc3, 0xc0, 0x37, 0x0c, 0x65, 0x38, 0xe0, 0xd1, 0x32, - 0xdd, 0xe9, 0x30, 0xb5, 0x19, 0xd9, 0x13, 0xea, 0xee, 0x9c, 0xb9, 0xe1, 0xe3, 0x4f, 0x22, 0x6c, 0x86, 0xb3, 0x75, - 0x19, 0x24, 0xfa, 0x0a, 0x01, 0xc5, 0x38, 0x8d, 0x18, 0xd7, 0x3b, 0x9f, 0x36, 0xa1, 0xb6, 0x95, 0xa4, 0x67, 0xb7, - 0x40, 0x4d, 0x80, 0xaa, 0x94, 0x2f, 0xd7, 0x45, 0x34, 0x34, 0xf3, 0x24, 0x94, 0x5e, 0xee, 0xe9, 0x73, 0xb4, 0x63, - 0x03, 0x7b, 0x39, 0xa7, 0xa1, 0x94, 0xf4, 0xb2, 0xab, 0x06, 0x37, 0xb0, 0x95, 0xa8, 0xf1, 0x22, 0xe2, 0xdd, 0x66, - 0x0f, 0x25, 0x03, 0xcb, 0x53, 0x12, 0x73, 0xc0, 0xb4, 0x9b, 0x14, 0x55, 0xf6, 0x0c, 0xab, 0x21, 0x98, 0xc7, 0xdd, - 0x7e, 0x66, 0x87, 0xd7, 0x52, 0x54, 0xcd, 0x2d, 0xb6, 0x00, 0x6b, 0x8b, 0x14, 0xe2, 0x70, 0x44, 0x49, 0xd3, 0x11, - 0xe9, 0xc8, 0xf8, 0x93, 0xa6, 0x44, 0x02, 0x10, 0x1d, 0xfe, 0x33, 0xcd, 0xf4, 0x50, 0xf4, 0xdf, 0x8b, 0x57, 0x6b, - 0x73, 0xaf, 0x5d, 0x30, 0x72, 0x9a, 0x7f, 0x38, 0x1d, 0x6f, 0xfa, 0xb9, 0xb5, 0x8f, 0x33, 0xd7, 0xab, 0x5b, 0x1b, - 0x73, 0xbd, 0xb0, 0xe7, 0xfe, 0x49, 0x24, 0xcf, 0x0a, 0x94, 0x6f, 0x47, 0x60, 0x54, 0x41, 0xb8, 0x97, 0x01, 0x76, - 0xbf, 0x17, 0xae, 0xff, 0x5f, 0xe5, 0x9d, 0x1f, 0xe4, 0xf7, 0xff, 0xb6, 0x86, 0xff, 0xcb, 0x6e, 0xba, 0xda, 0x60, - 0xff, 0x5b, 0x03, 0x94, 0xdf, 0x66, 0xa9, 0x1d, 0x48, 0xff, 0xd6, 0x09, 0xe1, 0x22, 0x4e, 0x27, 0x77, 0x02, 0x2b, - 0x3d, 0x4d, 0xce, 0xc1, 0xc0, 0x03, 0xfb, 0xff, 0x59, 0x0e, 0x40, 0x2f, 0xe0, 0x8b, 0x27, 0xd9, 0xb6, 0x9f, 0xe1, - 0x05, 0xb8, 0x53, 0xa2, 0x8c, 0x70, 0xc8, 0xeb, 0xca, 0xaf, 0xf8, 0xfa, 0x39, 0x24, 0x78, 0x75, 0x0a, 0xe6, 0xa7, - 0x93, 0x50, 0x59, 0x9e, 0x20, 0xee, 0xbb, 0x78, 0xb2, 0xd5, 0xa5, 0x84, 0x0f, 0x54, 0xeb, 0x43, 0x97, 0xe2, 0x23, - 0x7e, 0x47, 0xdd, 0x48, 0xe2, 0x27, 0xda, 0x3f, 0x6a, 0xf3, 0x91, 0xa7, 0x76, 0x41, 0xbc, 0x37, 0xb9, 0xf5, 0x17, - 0x11, 0xce, 0x3d, 0x21, 0xa9, 0x35, 0x09, 0x55, 0xe7, 0x24, 0x71, 0xc4, 0xd9, 0x1d, 0xda, 0x6a, 0x98, 0x93, 0xf0, - 0x9f, 0xaa, 0x2f, 0xb5, 0x4e, 0xae, 0x03, 0x11, 0x4d, 0xef, 0xb1, 0xd3, 0x65, 0x10, 0xa0, 0x06, 0xeb, 0xb3, 0xbc, - 0xa5, 0xdf, 0xf9, 0x1c, 0x9f, 0xaf, 0x26, 0xba, 0xb3, 0xa1, 0x7b, 0x34, 0xf2, 0x65, 0xfc, 0xf6, 0x21, 0x24, 0xd5, - 0xa4, 0x86, 0x1c, 0x4c, 0x24, 0x3a, 0xe7, 0xeb, 0xf4, 0x8b, 0xa8, 0xee, 0x5b, 0x0b, 0x8e, 0xb5, 0x39, 0xeb, 0x20, - 0x63, 0x98, 0x31, 0x18, 0x56, 0xd0, 0x00, 0x16, 0x63, 0x1c, 0x32, 0xef, 0xe8, 0x6e, 0x3f, 0x5a, 0xdb, 0xff, 0xfb, - 0x3c, 0x33, 0x20, 0xed, 0xf9, 0xc0, 0x5b, 0xd5, 0x47, 0xe1, 0x90, 0xb6, 0xef, 0xe9, 0xc1, 0xbe, 0x45, 0xa4, 0x17, - 0x31, 0xfd, 0x1a, 0xde, 0x9a, 0xc7, 0xcf, 0x47, 0x45, 0x69, 0x51, 0x47, 0x65, 0xf1, 0xc2, 0x1d, 0x1a, 0xf7, 0xd7, - 0xf0, 0xd9, 0x98, 0x77, 0x67, 0x83, 0x00, 0x32, 0x26, 0x5a, 0xc7, 0x6b, 0xb1, 0xff, 0xc5, 0x73, 0x3a, 0x0f, 0xe6, - 0xdb, 0x83, 0x63, 0x15, 0xb1, 0xf9, 0xd8, 0x4a, 0x2d, 0xd1, 0x37, 0x59, 0x9c, 0x6d, 0x21, 0x74, 0x65, 0x3b, 0x78, - 0xf6, 0xa4, 0x26, 0xaa, 0xce, 0x4e, 0xc8, 0x7b, 0x6a, 0xf3, 0xa2, 0xcb, 0x36, 0x7b, 0xb0, 0x49, 0x1b, 0x43, 0xe3, - 0x29, 0x75, 0x95, 0x6d, 0x5b, 0x19, 0x5f, 0x9b, 0xee, 0xeb, 0xef, 0x5f, 0x62, 0x69, 0xed, 0x04, 0x1d, 0x0a, 0x67, - 0x33, 0x62, 0xa6, 0xe0, 0x07, 0x14, 0x48, 0xb8, 0x61, 0x28, 0x89, 0x37, 0xc1, 0xaf, 0xa3, 0x36, 0x99, 0x12, 0x4c, - 0xc3, 0x68, 0xf6, 0xfd, 0x6b, 0x0f, 0x37, 0x3b, 0x7a, 0x11, 0x50, 0xe7, 0x8f, 0xac, 0xdb, 0x70, 0x32, 0x24, 0x84, - 0x8b, 0xbb, 0x75, 0x72, 0x0b, 0x3a, 0x26, 0xf2, 0x88, 0x23, 0x69, 0xc9, 0xdd, 0x79, 0xff, 0x88, 0x65, 0x3f, 0x5b, - 0xff, 0x89, 0x77, 0xb5, 0xa9, 0xec, 0x85, 0x92, 0x4d, 0xed, 0x67, 0xe8, 0x58, 0x94, 0x00, 0x4a, 0xa8, 0xbc, 0xb3, - 0x36, 0x67, 0x8f, 0xc6, 0xaa, 0xca, 0xe8, 0xb7, 0xbc, 0xae, 0x66, 0xc5, 0x82, 0xc7, 0xdd, 0xe2, 0x38, 0x8e, 0x8f, - 0xd5, 0x43, 0xdb, 0xfb, 0x15, 0x32, 0x95, 0xef, 0xf0, 0xb9, 0x7a, 0x23, 0x9f, 0x36, 0x16, 0xc9, 0xab, 0x87, 0x87, - 0x2c, 0xe4, 0xf3, 0xba, 0x39, 0x3a, 0xd1, 0xe4, 0x72, 0x8c, 0x4a, 0x16, 0x6b, 0xf9, 0x10, 0x69, 0x3b, 0x8b, 0x9d, - 0x44, 0x2f, 0xa5, 0x55, 0x67, 0x2c, 0x2c, 0x05, 0xdc, 0x97, 0x51, 0xb9, 0x42, 0x5d, 0x4d, 0x4a, 0x1d, 0x06, 0x72, - 0x1d, 0xa8, 0x0a, 0x36, 0xb4, 0x78, 0x64, 0x66, 0x05, 0xbf, 0xf0, 0xe9, 0x11, 0x11, 0x0c, 0x6c, 0x7b, 0x81, 0x8f, - 0xa7, 0xa9, 0xc5, 0xdc, 0xe0, 0x0b, 0x55, 0xc6, 0x3b, 0x5f, 0xf2, 0x39, 0x3a, 0x6b, 0x54, 0x48, 0x16, 0x43, 0x8e, - 0x46, 0x71, 0x8b, 0x56, 0xd2, 0xfe, 0x4b, 0xf2, 0x3e, 0x73, 0x4a, 0x89, 0x96, 0x5a, 0x82, 0x02, 0xd2, 0x34, 0x4d, - 0x77, 0x4d, 0xe9, 0x7b, 0xf1, 0x68, 0x9e, 0xd6, 0x68, 0x9b, 0xdb, 0x59, 0x0a, 0x09, 0xa2, 0x9b, 0xa2, 0x13, 0x8d, - 0xf4, 0x62, 0x00, 0x52, 0xae, 0x1f, 0x7a, 0x23, 0x64, 0xef, 0x74, 0xa6, 0x96, 0xf0, 0xe0, 0x94, 0x03, 0x61, 0xe5, - 0x9d, 0x35, 0x76, 0x9a, 0x46, 0xd7, 0x4a, 0xf6, 0x8e, 0xdf, 0xca, 0xe9, 0xa6, 0x39, 0x88, 0xaf, 0xa1, 0x7d, 0xed, - 0x55, 0x0a, 0x6c, 0x71, 0xad, 0xb6, 0x36, 0x17, 0xca, 0xba, 0xf4, 0x41, 0x8e, 0xdc, 0x2c, 0x30, 0x36, 0xe9, 0xad, - 0x73, 0xd9, 0xbb, 0x2e, 0x4a, 0x65, 0x0b, 0xbf, 0x56, 0xa5, 0x3d, 0xc1, 0x8a, 0x81, 0xe0, 0x38, 0x7e, 0x55, 0x10, - 0xcb, 0x6a, 0x54, 0xdb, 0xf1, 0x12, 0x2f, 0x0e, 0x8c, 0x55, 0xa8, 0xe7, 0xe8, 0x9d, 0x77, 0x84, 0x1a, 0xac, 0x27, - 0xa9, 0x50, 0xb2, 0xc9, 0x2c, 0x50, 0xac, 0xe2, 0x2e, 0x07, 0xf6, 0x4b, 0x50, 0x06, 0xe0, 0x7f, 0x32, 0x55, 0x76, - 0x7f, 0xaa, 0x39, 0x39, 0xb7, 0x4c, 0xed, 0x97, 0x92, 0x5c, 0xf3, 0xf3, 0xcc, 0xfa, 0x69, 0x30, 0xca, 0x68, 0x06, - 0x98, 0x97, 0xea, 0x5a, 0x76, 0x9e, 0xce, 0x14, 0xd7, 0xe0, 0x0f, 0x26, 0x49, 0x4f, 0xfb, 0xcf, 0x43, 0x0e, 0x7d, - 0x76, 0xea, 0xf9, 0xbd, 0x43, 0xce, 0x54, 0x7e, 0xfb, 0x69, 0x1e, 0x3c, 0xfd, 0xe3, 0x13, 0xfe, 0xfa, 0xf1, 0x5f, - 0xfa, 0x14, 0x9d, 0xe0, 0xcf, 0xd9, 0x4b, 0xe8, 0xa3, 0xda, 0x25, 0xdc, 0x8f, 0x56, 0xed, 0x01, 0x1a, 0x7d, 0x76, - 0xc1, 0x92, 0x57, 0x17, 0x8c, 0x03, 0x4a, 0xb5, 0x66, 0x2c, 0xb7, 0xfa, 0x9e, 0xb8, 0x7e, 0xb2, 0xd9, 0x2b, 0x5d, - 0x1a, 0xb8, 0x35, 0xb6, 0x9f, 0x97, 0x55, 0x0b, 0xd7, 0xbd, 0x32, 0xc9, 0xeb, 0xf7, 0x67, 0xd8, 0x13, 0xff, 0x3b, - 0x04, 0xc8, 0x0f, 0x08, 0x3c, 0x5a, 0x8d, 0x4b, 0x5f, 0xaa, 0x61, 0xa9, 0xaa, 0xe6, 0xa5, 0xa2, 0x5a, 0x96, 0x16, - 0xd5, 0xed, 0xe1, 0xe7, 0x27, 0x7e, 0xcf, 0x63, 0x5d, 0x98, 0x77, 0x25, 0xc8, 0xd9, 0xa6, 0x97, 0xa1, 0x92, 0x1b, - 0xee, 0x0a, 0x76, 0x2b, 0x85, 0x1f, 0xed, 0xe2, 0xd3, 0xbb, 0x1b, 0xf0, 0x56, 0x09, 0x7a, 0x35, 0xd3, 0x1c, 0x4f, - 0xd0, 0x2d, 0x26, 0x11, 0x20, 0x66, 0xa5, 0xa3, 0xbd, 0x0f, 0x1d, 0x0a, 0xca, 0x83, 0xec, 0x5a, 0x73, 0x8b, 0xfb, - 0x09, 0x26, 0xd4, 0xdf, 0x30, 0x01, 0x25, 0x63, 0x41, 0x54, 0x23, 0xa1, 0x46, 0x13, 0xde, 0x8a, 0x44, 0x00, 0xc4, - 0xfb, 0xa5, 0x4e, 0x72, 0x2f, 0x97, 0xa9, 0x50, 0x9d, 0x7b, 0x0b, 0x20, 0xf5, 0x54, 0x53, 0x5a, 0xea, 0x8b, 0x1a, - 0x06, 0xa9, 0xb8, 0xa6, 0x8c, 0x54, 0x09, 0x57, 0x7d, 0xc0, 0xfa, 0x86, 0xc5, 0xbc, 0xa2, 0x97, 0xac, 0x0d, 0x97, - 0xff, 0xd3, 0xfc, 0xe5, 0x98, 0x2d, 0xe4, 0x65, 0x27, 0x64, 0x8e, 0x65, 0x59, 0x8f, 0xac, 0x52, 0x8d, 0x97, 0xd6, - 0xe7, 0xb1, 0x97, 0xbf, 0xac, 0x05, 0xa2, 0x10, 0xd1, 0xe7, 0x75, 0x8c, 0xaa, 0x5c, 0x85, 0xbd, 0x0a, 0x64, 0x19, - 0x42, 0x6e, 0xd2, 0x50, 0x5a, 0x6f, 0x11, 0x8b, 0x16, 0x4b, 0x3c, 0x7d, 0x3f, 0xc8, 0xad, 0x19, 0x04, 0x6f, 0x03, - 0x88, 0x03, 0xba, 0xad, 0x4b, 0x2e, 0xf8, 0xff, 0xa8, 0x7f, 0x7a, 0x79, 0xf6, 0x3f, 0xa5, 0xba, 0x32, 0x22, 0xcf, - 0xd0, 0x77, 0x9a, 0x3c, 0x01, 0x0a, 0x62, 0xb0, 0x43, 0x34, 0x90, 0xf7, 0x53, 0xdf, 0xa1, 0x47, 0x20, 0x3c, 0x0e, - 0x05, 0x67, 0x30, 0x34, 0x55, 0x78, 0xa3, 0x41, 0x66, 0x3c, 0x1c, 0x3a, 0x11, 0x32, 0x34, 0x51, 0xe7, 0x74, 0x28, - 0x4b, 0x75, 0x25, 0xb3, 0xe6, 0x5f, 0x57, 0x31, 0x06, 0xfb, 0xf1, 0x72, 0xe5, 0xcb, 0x07, 0xed, 0x7e, 0xcf, 0xfe, - 0x64, 0x2e, 0x4c, 0xd1, 0x3b, 0xa9, 0x5b, 0x63, 0xd6, 0x1c, 0xf1, 0xc0, 0xb0, 0x3c, 0x8c, 0x1e, 0xf5, 0x84, 0xd8, - 0x6c, 0x87, 0x1e, 0x37, 0xed, 0x9b, 0x2c, 0xc3, 0x3c, 0xdc, 0x1f, 0x14, 0x76, 0x3f, 0x66, 0xde, 0xe5, 0xae, 0xc7, - 0x05, 0xbb, 0x3d, 0x1c, 0xd4, 0xaf, 0x41, 0xc1, 0x7f, 0xe4, 0x1d, 0x6b, 0x7b, 0x8c, 0xad, 0x47, 0x5e, 0x78, 0x9b, - 0x32, 0x5d, 0xd1, 0xca, 0x11, 0x0b, 0x27, 0x26, 0xd4, 0x18, 0x24, 0x31, 0x5c, 0xe5, 0x99, 0x7b, 0x0f, 0x41, 0x9c, - 0x71, 0x4e, 0x44, 0x7e, 0x22, 0x5b, 0x64, 0x7c, 0x5e, 0x7a, 0x6d, 0xb6, 0x6b, 0x42, 0x39, 0x46, 0xa8, 0x1c, 0x08, - 0xde, 0x05, 0x95, 0x43, 0xfb, 0xf1, 0xea, 0xa3, 0xcc, 0x16, 0xf5, 0x4f, 0xaf, 0x0c, 0xab, 0xe2, 0x2b, 0x7d, 0xdc, - 0xaa, 0x7f, 0x76, 0x74, 0x00, 0xaa, 0x7f, 0x40, 0xfa, 0x3d, 0xa5, 0xbc, 0x2e, 0x24, 0x1f, 0x99, 0x44, 0x73, 0xb3, - 0xa5, 0xc5, 0xba, 0x0b, 0x4b, 0x6d, 0x25, 0x8b, 0x43, 0x9d, 0xb7, 0x86, 0xd7, 0xb5, 0x6f, 0x4d, 0x8f, 0x0e, 0xf5, - 0x8b, 0xd4, 0xd6, 0xe7, 0xbf, 0xc3, 0x7d, 0xfd, 0x86, 0x51, 0xad, 0xb6, 0xc6, 0xa5, 0x27, 0xe9, 0xd3, 0x62, 0x51, - 0xd1, 0xd0, 0xc5, 0x3e, 0xfd, 0x2e, 0x1a, 0x1a, 0xe8, 0xd8, 0xb3, 0xb6, 0x5e, 0x69, 0x9c, 0xee, 0x0b, 0x74, 0xd0, - 0x69, 0x39, 0x42, 0xd2, 0xbd, 0x61, 0x60, 0x10, 0xa0, 0x98, 0xc1, 0x26, 0xc4, 0x74, 0xcb, 0xcf, 0x4e, 0xa3, 0x99, - 0xbb, 0x13, 0x6e, 0x7f, 0xb1, 0x3e, 0x01, 0xd5, 0x2f, 0xf3, 0x77, 0xaa, 0x68, 0x3e, 0xe2, 0x8f, 0x78, 0xd0, 0x86, - 0x44, 0xbe, 0x0e, 0x89, 0xf5, 0xb4, 0x31, 0x96, 0x6e, 0x88, 0xd8, 0xae, 0xab, 0x27, 0x0f, 0x2b, 0xaf, 0x6d, 0x34, - 0x75, 0xf9, 0x95, 0x6d, 0x5b, 0xfa, 0xbc, 0xf2, 0x80, 0x81, 0xe3, 0xae, 0x87, 0x0e, 0x7c, 0x25, 0xc9, 0xd8, 0x82, - 0xf7, 0x4a, 0xe2, 0x7f, 0x89, 0xfd, 0x3b, 0x39, 0x62, 0x9b, 0x1a, 0xa8, 0x59, 0xea, 0xee, 0x04, 0x9b, 0x35, 0xb5, - 0x90, 0x34, 0x47, 0x8f, 0x69, 0xf5, 0xd3, 0xf2, 0x98, 0xef, 0x76, 0x1e, 0x5b, 0x3f, 0xfb, 0x28, 0x0b, 0x2a, 0x4c, - 0xcf, 0xd8, 0x21, 0x70, 0xc6, 0xb0, 0xa8, 0x8c, 0x45, 0x99, 0xdc, 0xdb, 0x94, 0x13, 0x69, 0xb2, 0x7c, 0x1f, 0x7e, - 0xe7, 0x82, 0x0a, 0xe8, 0x35, 0x3e, 0x8f, 0xee, 0x50, 0x7e, 0x5c, 0xf6, 0x06, 0x3c, 0x3d, 0x48, 0x99, 0xea, 0x0e, - 0x3a, 0xa5, 0xe9, 0xd3, 0xbc, 0xfe, 0xb8, 0x1f, 0xfd, 0x84, 0xeb, 0x1f, 0xff, 0x93, 0x4c, 0x8f, 0x5f, 0x43, 0x32, - 0x4c, 0x82, 0xd3, 0x14, 0x76, 0xb5, 0xf2, 0xff, 0xdd, 0x32, 0xf5, 0x4a, 0x5c, 0x0c, 0x6f, 0xea, 0xf8, 0x01, 0x51, - 0x34, 0xeb, 0x23, 0xcb, 0x98, 0x4f, 0xdb, 0xf2, 0xc3, 0xb6, 0x54, 0x87, 0xb8, 0xc8, 0x9d, 0xcb, 0x92, 0xd8, 0x35, - 0x28, 0xd3, 0x1a, 0x29, 0xed, 0x33, 0xe6, 0xb0, 0x37, 0x93, 0x76, 0x2f, 0x2d, 0x6d, 0x29, 0xa4, 0xe0, 0x68, 0x8a, - 0x33, 0x1a, 0xc0, 0x7d, 0xac, 0x49, 0xdf, 0xda, 0x35, 0x7a, 0x3e, 0x1e, 0xcb, 0x4a, 0xae, 0x24, 0x9d, 0xcb, 0x52, - 0x0e, 0x1f, 0x71, 0x2b, 0xf7, 0x11, 0x23, 0x20, 0xe6, 0xc5, 0xaa, 0xd2, 0x02, 0x33, 0x44, 0x0d, 0x2e, 0x95, 0x8e, - 0xb1, 0x54, 0x06, 0x13, 0xb5, 0xbe, 0xbc, 0xa0, 0x5d, 0xbe, 0x81, 0x03, 0xa9, 0x3b, 0xef, 0x61, 0x75, 0x62, 0xa9, - 0xd0, 0xe5, 0xd0, 0xde, 0x96, 0xf4, 0xc4, 0xe5, 0x7c, 0x24, 0x90, 0xc6, 0x02, 0x54, 0x78, 0x6c, 0x5f, 0xe2, 0xcf, - 0x22, 0xf2, 0x47, 0x61, 0xf3, 0x22, 0xce, 0x06, 0x9a, 0x82, 0x56, 0x50, 0x8d, 0x69, 0xf4, 0x5f, 0x56, 0x09, 0x41, - 0x4a, 0xc1, 0x56, 0xd4, 0x1c, 0xf0, 0x0c, 0xd9, 0x38, 0x89, 0x44, 0x60, 0x87, 0xe9, 0xe0, 0x42, 0xdb, 0x2f, 0x64, - 0x89, 0xd6, 0x4f, 0x23, 0x63, 0x0f, 0x49, 0x78, 0xf8, 0x72, 0x99, 0xe8, 0x95, 0x38, 0x13, 0x6f, 0xe9, 0x5b, 0x0b, - 0xfe, 0x79, 0x5d, 0x0b, 0xf6, 0xd9, 0x20, 0x7b, 0x89, 0x8f, 0x3c, 0x0c, 0xf1, 0x74, 0x85, 0xdb, 0xee, 0x41, 0xe5, - 0x5e, 0x12, 0x0f, 0x6b, 0x7b, 0x7b, 0x70, 0xbe, 0xb3, 0xf6, 0xb4, 0x56, 0xad, 0x0f, 0x94, 0x6b, 0x4c, 0xfb, 0xe1, - 0xf5, 0x97, 0xf7, 0xad, 0x29, 0x95, 0x7e, 0x14, 0xba, 0x99, 0x84, 0xb1, 0xf2, 0x6c, 0xef, 0x4c, 0xf6, 0x61, 0x48, - 0x4f, 0xf5, 0x80, 0xd3, 0x8e, 0x12, 0xb7, 0x64, 0x35, 0x1e, 0x65, 0x6f, 0x12, 0xf4, 0xa9, 0xac, 0x68, 0x20, 0xa2, - 0x9a, 0x7f, 0x3f, 0x19, 0x0b, 0xcc, 0x0c, 0xc4, 0xe0, 0xe3, 0xb9, 0x6d, 0xc9, 0x2c, 0xe0, 0x7e, 0xcc, 0xdf, 0x36, - 0xd1, 0xa4, 0x1d, 0x3b, 0x08, 0x87, 0x51, 0x30, 0xef, 0xd5, 0x5b, 0xc2, 0xfd, 0x50, 0xca, 0xcf, 0xc0, 0xcf, 0x8e, - 0x81, 0x13, 0x9c, 0x15, 0xf1, 0x32, 0xb4, 0xdf, 0x10, 0xce, 0xc8, 0x44, 0xf0, 0xa3, 0xe2, 0xee, 0x00, 0xdb, 0x4d, - 0x73, 0xb8, 0xc7, 0x3f, 0x3d, 0x1b, 0x70, 0x27, 0x29, 0x7d, 0xc9, 0x24, 0x07, 0xef, 0x56, 0x19, 0x92, 0x2d, 0x15, - 0x39, 0xd9, 0xc4, 0x72, 0xda, 0x53, 0x8e, 0x70, 0x7b, 0xa7, 0x4b, 0xbf, 0xa7, 0x3c, 0x3a, 0xef, 0xc5, 0xa5, 0xde, - 0x43, 0x3c, 0x7a, 0xea, 0x6d, 0x83, 0xb6, 0xcd, 0xd2, 0xd2, 0x9c, 0x94, 0x2e, 0x75, 0xa6, 0x6b, 0x97, 0x89, 0xd1, - 0x95, 0x2f, 0x9a, 0x77, 0xc8, 0x15, 0x86, 0x28, 0x3d, 0x75, 0x60, 0xb3, 0xda, 0xa7, 0x44, 0x89, 0xd4, 0x61, 0x95, - 0x48, 0x7a, 0x14, 0x29, 0xc4, 0x27, 0x67, 0x89, 0xa0, 0xf7, 0x69, 0x6c, 0x01, 0xa5, 0x65, 0x35, 0x79, 0x14, 0xbd, - 0x62, 0xde, 0x8b, 0xdb, 0xd8, 0x29, 0x34, 0x8b, 0x4d, 0x36, 0x9b, 0xc9, 0xde, 0x4b, 0xff, 0xf5, 0xdf, 0xb9, 0xae, - 0xa0, 0xdf, 0x8f, 0xe9, 0x12, 0xff, 0x7a, 0x0d, 0xf0, 0x5e, 0x8d, 0x82, 0xe8, 0x61, 0x8a, 0xba, 0x2b, 0xe6, 0x80, - 0x2e, 0x84, 0xf0, 0x55, 0xa4, 0xab, 0x1a, 0x79, 0xba, 0x54, 0xfc, 0x49, 0xb2, 0xdb, 0x08, 0x9b, 0x3a, 0x6d, 0x4b, - 0x06, 0x68, 0x5f, 0x81, 0xeb, 0x24, 0xeb, 0x35, 0x8a, 0xc8, 0x1d, 0x14, 0xfd, 0x27, 0x7f, 0xd6, 0xc4, 0xcf, 0x16, - 0xf1, 0x63, 0x98, 0xf2, 0xb1, 0x4f, 0x32, 0xc6, 0x20, 0xe6, 0x14, 0x72, 0x13, 0x88, 0x77, 0x63, 0xc2, 0x96, 0x3c, - 0x83, 0x46, 0xbf, 0x37, 0x4d, 0x29, 0x55, 0x59, 0x2f, 0xab, 0xb6, 0x64, 0xd7, 0x8e, 0x5b, 0x7b, 0x16, 0xd3, 0xfc, - 0x18, 0x58, 0x8d, 0xdf, 0x8b, 0x14, 0xaf, 0x1c, 0x15, 0x76, 0xb7, 0xb8, 0x2a, 0x8e, 0x21, 0x78, 0xfd, 0xf8, 0xf3, - 0x20, 0x70, 0x22, 0x3b, 0xdd, 0x5b, 0x02, 0xe5, 0xbb, 0x6b, 0xe3, 0xf4, 0x37, 0xf9, 0xea, 0xf7, 0x7d, 0x74, 0x8f, - 0xfa, 0x33, 0xa6, 0xce, 0x5e, 0x25, 0x9c, 0x6e, 0x11, 0xfd, 0xcf, 0xa1, 0x2d, 0x2f, 0xb7, 0xe6, 0x8e, 0xaa, 0x70, - 0x9f, 0x18, 0xdf, 0x7b, 0x52, 0x26, 0xa3, 0x3d, 0xf8, 0xdb, 0x9d, 0x7a, 0xfe, 0xc7, 0x84, 0x23, 0x08, 0x6f, 0xba, - 0xf1, 0x41, 0xbf, 0xa7, 0x74, 0xfc, 0x34, 0x2f, 0x9f, 0xfe, 0xe1, 0x09, 0x97, 0x3f, 0xfe, 0x27, 0x39, 0xf6, 0x8e, - 0xb9, 0x34, 0xef, 0x80, 0xdd, 0x7d, 0x16, 0xf1, 0x74, 0xf2, 0x5a, 0x2e, 0x91, 0x3f, 0x55, 0x3d, 0x5e, 0x09, 0x2f, - 0x0f, 0x76, 0x02, 0x16, 0x68, 0x11, 0x79, 0xcf, 0xe6, 0x25, 0x68, 0xc1, 0x90, 0x1d, 0xc5, 0xd1, 0xc4, 0x9b, 0x01, - 0xa6, 0x42, 0x6a, 0x35, 0x88, 0x0e, 0xcc, 0x77, 0xdf, 0xc9, 0x7c, 0x20, 0xcc, 0x1a, 0x26, 0x54, 0x71, 0x27, 0xde, - 0xa5, 0x1e, 0x49, 0x4a, 0x75, 0x55, 0xef, 0x45, 0xa2, 0xcc, 0x7e, 0x40, 0x7a, 0xcc, 0x02, 0x63, 0x26, 0x42, 0x03, - 0xf0, 0x0c, 0x01, 0x91, 0xc3, 0x48, 0x4e, 0x92, 0xbe, 0xd5, 0x81, 0x11, 0xef, 0x38, 0x4d, 0x95, 0xaf, 0x04, 0x90, - 0x9f, 0x65, 0xe5, 0xf1, 0xdd, 0x5d, 0x9a, 0xd9, 0x70, 0x47, 0xe7, 0x5b, 0xef, 0x82, 0x6f, 0x68, 0xd2, 0x55, 0xb9, - 0xa7, 0x02, 0xc2, 0xc6, 0xd5, 0x25, 0x64, 0xc4, 0x39, 0xe4, 0x50, 0xa6, 0x60, 0x07, 0x52, 0x89, 0x75, 0xe8, 0xc9, - 0xc0, 0x1f, 0xbd, 0x2e, 0x01, 0x11, 0x4b, 0x29, 0x79, 0x92, 0xb3, 0xdd, 0x18, 0x8e, 0x4d, 0xe4, 0xe2, 0x3d, 0xa9, - 0x7b, 0x6f, 0x70, 0xbc, 0x86, 0x2a, 0x89, 0x54, 0x6b, 0x21, 0xad, 0x4a, 0xba, 0xef, 0x6c, 0x0f, 0x37, 0x9c, 0xfc, - 0x63, 0x6d, 0xe4, 0x8f, 0x4c, 0xee, 0xf1, 0x9e, 0x31, 0x69, 0x1e, 0x70, 0x96, 0xcd, 0xa2, 0x00, 0x46, 0x99, 0x6a, - 0x97, 0x9c, 0x75, 0x94, 0x4b, 0x2d, 0x4a, 0x5a, 0x06, 0xbe, 0x42, 0x91, 0xe4, 0xe6, 0x37, 0x7a, 0xbd, 0xe9, 0x7b, - 0x34, 0x97, 0x10, 0xe8, 0x95, 0x7e, 0xce, 0xd7, 0x7b, 0xba, 0x7a, 0xdf, 0x55, 0xb6, 0xb3, 0x0b, 0x56, 0x69, 0xac, - 0xf7, 0x86, 0x5b, 0x01, 0xc8, 0x02, 0xb1, 0xce, 0x0d, 0xcb, 0xed, 0xbe, 0x47, 0xd4, 0xeb, 0x33, 0x9f, 0xd8, 0x13, - 0x19, 0x51, 0xba, 0x45, 0x24, 0xba, 0x20, 0xe2, 0xff, 0x3f, 0xf7, 0x69, 0x2c, 0x26, 0xb7, 0xad, 0x91, 0x2a, 0xbf, - 0x6e, 0x9d, 0xe5, 0xc5, 0xfe, 0x2d, 0xd7, 0x15, 0x82, 0x62, 0x64, 0x06, 0x32, 0x45, 0xd3, 0x34, 0xbb, 0x0f, 0x93, - 0x19, 0x5b, 0x22, 0x34, 0xa2, 0x4c, 0x4a, 0xcb, 0x35, 0xd2, 0x42, 0x42, 0x2b, 0x07, 0x90, 0x61, 0x52, 0xda, 0x85, - 0x16, 0xd7, 0x3a, 0x24, 0x83, 0xe7, 0xb3, 0x49, 0x8f, 0xa7, 0x84, 0x24, 0x70, 0x73, 0xad, 0x22, 0xc2, 0x1c, 0xd5, - 0x16, 0x84, 0xf0, 0x63, 0x7f, 0x01, 0x3a, 0x61, 0x52, 0x03, 0xdf, 0x68, 0xf1, 0x2e, 0x08, 0x02, 0xb4, 0x78, 0x42, - 0x72, 0x0c, 0x0e, 0x40, 0x6a, 0xc9, 0x4a, 0x7f, 0x90, 0xa4, 0xeb, 0xb0, 0x3f, 0x1f, 0x33, 0x6e, 0xce, 0xa7, 0x9d, - 0xe9, 0xc9, 0x04, 0xe8, 0xd5, 0x07, 0x0e, 0xc3, 0x76, 0xc7, 0xc0, 0xf0, 0x28, 0xe8, 0xd3, 0x44, 0xf7, 0x7b, 0xb8, - 0xe9, 0xb2, 0xdd, 0x97, 0x43, 0x4c, 0x04, 0x8b, 0x99, 0xec, 0x66, 0x1c, 0xe1, 0xec, 0x86, 0x8d, 0xf6, 0x48, 0xb5, - 0xc6, 0x7e, 0x1f, 0x94, 0x2a, 0x36, 0x34, 0xdd, 0x49, 0xcf, 0x2c, 0xc3, 0xec, 0x16, 0x9a, 0xac, 0x2a, 0x03, 0x4e, - 0xa2, 0x02, 0x9c, 0x48, 0x61, 0xdb, 0xe8, 0xd8, 0xf0, 0xa6, 0x28, 0x81, 0xe6, 0xa1, 0x25, 0x46, 0x9f, 0x02, 0xef, - 0x52, 0x52, 0xf1, 0x8b, 0xd5, 0x98, 0x4a, 0xb2, 0xa1, 0x49, 0x8a, 0xcc, 0x72, 0x7c, 0xba, 0x8b, 0xdc, 0xb0, 0x3c, - 0x61, 0x3a, 0xb5, 0x66, 0x59, 0x91, 0x49, 0xd1, 0xfd, 0x7f, 0xf5, 0xe4, 0x90, 0x90, 0x56, 0xd5, 0xdc, 0x4d, 0x95, - 0x72, 0xf8, 0x8c, 0x5b, 0xc9, 0x04, 0xae, 0x89, 0x2f, 0xf4, 0x6c, 0x67, 0xdf, 0x80, 0xee, 0x94, 0x1a, 0x14, 0x77, - 0x21, 0x07, 0x85, 0x19, 0x35, 0xd8, 0xfb, 0x0b, 0xa2, 0xc7, 0xa3, 0xe4, 0xa6, 0xf1, 0x77, 0x0e, 0x57, 0xa8, 0x7a, - 0x23, 0xe9, 0xb4, 0x7f, 0xe0, 0x22, 0x70, 0x54, 0xa7, 0xc6, 0x98, 0x77, 0x37, 0x5a, 0xb7, 0x17, 0x55, 0xdc, 0x21, - 0x03, 0xec, 0x6b, 0x79, 0xd7, 0x02, 0x6b, 0xaf, 0x78, 0xd3, 0x48, 0x6e, 0x91, 0x8f, 0xff, 0xda, 0x67, 0xb7, 0xc5, - 0x2d, 0x5a, 0x64, 0x6a, 0xbb, 0x3c, 0x58, 0xf4, 0x65, 0x1b, 0x36, 0xa3, 0xd3, 0xb3, 0xbf, 0xb9, 0x90, 0xcd, 0x67, - 0x06, 0xb5, 0xc3, 0x4f, 0x1f, 0x4f, 0x5d, 0x1c, 0x38, 0x45, 0x2c, 0xf1, 0x10, 0x4e, 0xda, 0x56, 0xab, 0xcb, 0x14, - 0xbd, 0xec, 0xbe, 0x05, 0x92, 0x60, 0x16, 0xe7, 0x53, 0x0f, 0x5f, 0x88, 0x57, 0x28, 0x38, 0x6c, 0x1f, 0xf6, 0x57, - 0x71, 0x24, 0x6f, 0xfd, 0x53, 0xbd, 0x71, 0xd0, 0xf2, 0xab, 0x9c, 0xbb, 0x97, 0xeb, 0x77, 0x5d, 0x9b, 0xf2, 0x2a, - 0xee, 0xd7, 0xad, 0x7f, 0xda, 0x10, 0xa5, 0x62, 0x4f, 0x26, 0x3d, 0x9f, 0x9b, 0xe5, 0xc7, 0xef, 0x57, 0x26, 0x94, - 0x2f, 0x46, 0x18, 0x50, 0xab, 0x1f, 0xc2, 0x4c, 0x47, 0x8a, 0x6f, 0x92, 0x9a, 0xb2, 0x06, 0xad, 0x50, 0x4c, 0x59, - 0x6d, 0xe2, 0x7c, 0xe8, 0xa0, 0xd9, 0x48, 0x87, 0xc3, 0x6e, 0x49, 0xac, 0xf5, 0xd3, 0x54, 0x4f, 0x23, 0x70, 0x08, - 0x82, 0xf3, 0x83, 0x4a, 0x2d, 0x39, 0xc6, 0x73, 0x6e, 0xd5, 0x33, 0x64, 0x31, 0xa2, 0xca, 0x64, 0xcc, 0xe4, 0xe6, - 0x0d, 0x15, 0x46, 0x95, 0x79, 0xe8, 0x00, 0x0a, 0x47, 0x32, 0xdb, 0x71, 0xe3, 0x8b, 0xc7, 0x4c, 0x53, 0xd5, 0x0b, - 0x22, 0xbe, 0x7f, 0x5d, 0xe7, 0x8e, 0x84, 0x0e, 0xa4, 0xee, 0x1d, 0x91, 0xa9, 0x55, 0x9b, 0x8c, 0x0e, 0x68, 0xe8, - 0x3a, 0x8a, 0xcc, 0x8f, 0x55, 0x55, 0x91, 0x4d, 0xd5, 0xae, 0x4c, 0x46, 0x91, 0x43, 0xac, 0x3b, 0x4a, 0x59, 0x4e, - 0x96, 0xb5, 0xd1, 0xb5, 0x89, 0xc8, 0x6a, 0xb7, 0x25, 0x91, 0x6a, 0x3f, 0x48, 0x83, 0xd3, 0xd0, 0x7b, 0x0a, 0xb0, - 0xf9, 0xd4, 0x92, 0xa4, 0x5d, 0x4b, 0xd1, 0xf0, 0xb1, 0xf3, 0xd2, 0x5d, 0x77, 0x17, 0x96, 0x23, 0x84, 0x71, 0x4a, - 0x70, 0x0a, 0x2a, 0x2d, 0xe8, 0x18, 0x84, 0x37, 0x62, 0xba, 0x68, 0xf7, 0x00, 0xe0, 0xd9, 0xb9, 0xcc, 0x5e, 0x01, - 0x40, 0xca, 0xac, 0x02, 0x4d, 0xf3, 0xc7, 0x8d, 0x38, 0x94, 0x39, 0xd9, 0x91, 0x6a, 0x8a, 0x98, 0x14, 0xdf, 0x13, - 0x0d, 0x75, 0x82, 0xec, 0xc7, 0x94, 0x46, 0xfc, 0x41, 0x1e, 0x6c, 0xcb, 0xce, 0xb9, 0xdd, 0x98, 0x22, 0xc7, 0xc4, - 0x93, 0xa1, 0x15, 0xb9, 0x41, 0x3c, 0xe9, 0x7b, 0x7c, 0xad, 0xba, 0x70, 0xe5, 0xc1, 0xec, 0xf2, 0xe2, 0xfd, 0x31, - 0xff, 0x77, 0x1b, 0x85, 0xda, 0xe4, 0x61, 0xc5, 0x9f, 0x02, 0xb2, 0x3b, 0xa4, 0xcb, 0x63, 0x73, 0x89, 0x7f, 0xe5, - 0xc2, 0x0f, 0x9b, 0xd0, 0x61, 0x17, 0xd3, 0x69, 0x46, 0x2f, 0x83, 0x14, 0x84, 0x3d, 0x0b, 0x9f, 0x96, 0x4c, 0xe3, - 0x26, 0xc9, 0x24, 0xad, 0x7f, 0xb7, 0x29, 0xad, 0x69, 0xa4, 0xc6, 0x51, 0x77, 0x83, 0xf2, 0x84, 0x9f, 0xdf, 0x45, - 0xcd, 0x8f, 0xbd, 0xdb, 0xa6, 0x20, 0x9a, 0x60, 0x15, 0x86, 0x88, 0x72, 0xfa, 0xcd, 0x12, 0x67, 0x6e, 0x09, 0x7b, - 0x48, 0x79, 0xb5, 0x8d, 0x35, 0x3e, 0xdd, 0xbc, 0x54, 0x5b, 0x1f, 0x74, 0x4f, 0x55, 0xf5, 0x37, 0xdb, 0x86, 0xa2, - 0xd1, 0x29, 0xe1, 0x15, 0x45, 0x23, 0x3b, 0xf5, 0xc3, 0x21, 0x5b, 0x8d, 0xa2, 0x10, 0x59, 0xcc, 0xe2, 0x87, 0x5d, - 0x2a, 0x02, 0x1a, 0x86, 0xd9, 0xfc, 0xd3, 0xec, 0x4a, 0x46, 0x9e, 0x44, 0xb3, 0x6f, 0x3d, 0x63, 0xdb, 0xae, 0xdf, - 0xda, 0x67, 0x76, 0xeb, 0x3d, 0x66, 0x6b, 0x67, 0x77, 0x28, 0xa4, 0x83, 0x18, 0xf7, 0x6b, 0xd7, 0x16, 0x73, 0xf5, - 0x34, 0x64, 0x95, 0x8f, 0x2b, 0x46, 0x38, 0xfc, 0x1a, 0xe8, 0xe2, 0x33, 0x66, 0x41, 0x68, 0xd7, 0x38, 0x6d, 0x1f, - 0x0e, 0xd0, 0x9a, 0x1e, 0xcc, 0xf4, 0x4c, 0x0f, 0xd0, 0x6e, 0x4e, 0x10, 0xa0, 0x81, 0x12, 0x4f, 0xf0, 0xbf, 0x92, - 0x38, 0x57, 0xd9, 0xed, 0xfc, 0x5a, 0x23, 0x2b, 0xae, 0x3f, 0xa4, 0x82, 0x3e, 0x8d, 0x36, 0x13, 0x3a, 0x77, 0x4b, - 0xc5, 0x3b, 0x50, 0x5c, 0x2b, 0xc3, 0xee, 0x26, 0xa0, 0xcd, 0x53, 0xf1, 0xfb, 0xaa, 0xff, 0x28, 0xa0, 0x86, 0x1e, - 0x9b, 0xa3, 0xc4, 0x3d, 0xdb, 0xaa, 0x62, 0x56, 0x19, 0xb4, 0x03, 0x06, 0x83, 0xbf, 0xb6, 0x9a, 0xd6, 0xc8, 0xe6, - 0xe9, 0xef, 0x22, 0x7a, 0x4d, 0xdd, 0x19, 0xb9, 0x5f, 0xc1, 0x75, 0x1f, 0x59, 0xab, 0x86, 0x4e, 0xda, 0x73, 0xa7, - 0x61, 0x1b, 0x79, 0x82, 0x09, 0x74, 0x50, 0xb1, 0xa9, 0xc1, 0x05, 0xfb, 0x48, 0xd1, 0xb2, 0x56, 0x83, 0x66, 0x51, - 0x27, 0x72, 0x97, 0x81, 0x0a, 0xf1, 0x6d, 0x52, 0x06, 0xcb, 0x32, 0xb4, 0x8a, 0x38, 0x1e, 0x65, 0x36, 0xb8, 0x02, - 0x53, 0xe0, 0xad, 0x34, 0x94, 0xcd, 0x9e, 0xe0, 0x89, 0xd2, 0x12, 0x4e, 0x7e, 0x78, 0xe2, 0x35, 0x6a, 0x09, 0x3e, - 0x87, 0xa6, 0xfd, 0x07, 0x69, 0x69, 0xe6, 0xfa, 0x93, 0x23, 0x3d, 0x78, 0x0e, 0x6f, 0xcd, 0x04, 0xbe, 0x4b, 0x3c, - 0x1d, 0xb9, 0xf6, 0xfc, 0x43, 0xe2, 0x81, 0x5d, 0x61, 0x22, 0x24, 0x21, 0x2c, 0x5c, 0x7b, 0xa7, 0xad, 0xc5, 0xff, - 0x70, 0x06, 0x8c, 0x11, 0x23, 0x6c, 0x07, 0x05, 0x4e, 0x1f, 0xb6, 0x51, 0x84, 0x30, 0x5f, 0x7e, 0xcd, 0x8e, 0x91, - 0xdc, 0x54, 0x5e, 0x5c, 0xc4, 0x18, 0xc1, 0x56, 0xce, 0x4a, 0xfc, 0x80, 0x88, 0x4c, 0xe6, 0x05, 0xc3, 0x36, 0xfc, - 0x1e, 0xdf, 0xf5, 0xdd, 0xc4, 0xf7, 0x80, 0xf5, 0x8c, 0x0f, 0xd5, 0x73, 0xdf, 0xcf, 0x91, 0x44, 0xeb, 0x69, 0xfb, - 0x83, 0x20, 0x58, 0x6c, 0xba, 0xb5, 0x33, 0xb5, 0x86, 0xfe, 0x41, 0x98, 0xe0, 0xf6, 0xbc, 0xa9, 0x28, 0x56, 0xe2, - 0xf2, 0xfa, 0x82, 0x37, 0x3c, 0x1e, 0x60, 0x9f, 0xde, 0x59, 0xbb, 0x7b, 0x73, 0x97, 0xde, 0x8d, 0x3b, 0xf1, 0xa4, - 0x7f, 0x47, 0x3d, 0xe4, 0x6b, 0x9e, 0x31, 0xa3, 0x5d, 0x95, 0x65, 0xbf, 0xa4, 0xdf, 0x39, 0xa7, 0x33, 0x1d, 0xc1, - 0x44, 0xfa, 0x1b, 0xf8, 0xfa, 0x58, 0x6c, 0x7f, 0x21, 0x39, 0x46, 0xd3, 0x05, 0x66, 0x8d, 0xd4, 0x0b, 0x0b, 0x6d, - 0xda, 0x17, 0xdd, 0x2d, 0x40, 0xc5, 0x02, 0x55, 0x78, 0xe0, 0xed, 0xc8, 0x1f, 0x71, 0xbb, 0xd2, 0x8b, 0x81, 0x65, - 0xf6, 0x8f, 0x9c, 0xfd, 0xc9, 0xeb, 0x50, 0x89, 0xbe, 0x88, 0xd6, 0x27, 0x94, 0xa9, 0xb0, 0x4b, 0x44, 0x39, 0x72, - 0x23, 0x8e, 0x3e, 0x1d, 0x3d, 0x89, 0x80, 0x0d, 0x52, 0x37, 0x22, 0xac, 0xb8, 0x27, 0x9f, 0x45, 0x69, 0x40, 0x2f, - 0x80, 0xd4, 0x0f, 0x67, 0x1c, 0xea, 0xfa, 0x37, 0x61, 0x26, 0x5a, 0x1c, 0xc6, 0x73, 0x5f, 0x66, 0x55, 0x68, 0xdd, - 0xf3, 0x28, 0x3e, 0x49, 0xe4, 0x7b, 0xf7, 0xd8, 0xe2, 0x48, 0x70, 0xe6, 0x9b, 0xa0, 0x17, 0xf2, 0xa4, 0xbf, 0x65, - 0x41, 0x74, 0xe7, 0x17, 0x52, 0xab, 0x12, 0xb9, 0xb9, 0xc0, 0xb1, 0x60, 0x99, 0x43, 0x0e, 0x7f, 0xd6, 0x9e, 0xa5, - 0xf5, 0x3b, 0x18, 0xd5, 0x30, 0x8f, 0xff, 0x5c, 0x7c, 0xca, 0x42, 0x91, 0xa9, 0x17, 0x8f, 0x3f, 0x45, 0x69, 0x10, - 0xdd, 0x9e, 0x44, 0x28, 0xb6, 0x91, 0xba, 0x44, 0x90, 0x28, 0x1c, 0x67, 0x6a, 0xdf, 0xdf, 0xe5, 0xd9, 0x70, 0x17, - 0xcd, 0x3f, 0x0d, 0xa0, 0x27, 0xbf, 0x4a, 0xeb, 0xef, 0x17, 0x7f, 0x4a, 0x8a, 0xe0, 0xf6, 0xac, 0x9f, 0xce, 0xfc, - 0xd8, 0x59, 0xe9, 0x62, 0x10, 0x3d, 0x82, 0xd5, 0xb8, 0xa2, 0x4a, 0x7e, 0x06, 0x3f, 0xb1, 0xfd, 0x61, 0xe1, 0x66, - 0xc4, 0xbf, 0x8f, 0x4f, 0xee, 0xe2, 0x7c, 0x3a, 0x57, 0x58, 0x75, 0x38, 0x03, 0xa2, 0x86, 0xd1, 0xa5, 0xea, 0x62, - 0xc7, 0x91, 0xf9, 0x97, 0x05, 0x6b, 0x3c, 0x8b, 0x04, 0xa6, 0xf3, 0x0f, 0x2f, 0x3f, 0x62, 0xe4, 0xc9, 0x62, 0xb2, - 0xbf, 0xf8, 0x42, 0x9d, 0x38, 0xb8, 0xa7, 0xdd, 0xd6, 0xaf, 0x44, 0xc9, 0xa7, 0xf9, 0xe3, 0xe3, 0xfe, 0xba, 0x9f, - 0xf0, 0xe3, 0xc7, 0xbf, 0xf4, 0x57, 0xd9, 0x9a, 0x67, 0xdf, 0x85, 0x33, 0xca, 0x61, 0xb7, 0x17, 0x31, 0x3b, 0xd9, - 0xbf, 0xd7, 0x1f, 0x5f, 0x63, 0x4f, 0xee, 0xef, 0x19, 0x3e, 0xfd, 0xf6, 0xf2, 0xfe, 0x5d, 0x78, 0xb7, 0x90, 0xcb, - 0x8c, 0xbd, 0x39, 0x37, 0xd7, 0xa5, 0xac, 0xa5, 0xd9, 0x7a, 0x91, 0x80, 0x24, 0x88, 0x89, 0x0d, 0x2a, 0xf0, 0x44, - 0x12, 0x2d, 0xcb, 0x20, 0x47, 0x30, 0xe4, 0xe4, 0x38, 0xec, 0xce, 0x79, 0xc6, 0x82, 0x54, 0x19, 0x51, 0x5e, 0xa2, - 0x38, 0xdb, 0x7a, 0xcc, 0x00, 0x9c, 0x81, 0xf7, 0x11, 0xc8, 0xef, 0x6a, 0x10, 0x07, 0x4d, 0x06, 0x69, 0xf0, 0xed, - 0xa7, 0xae, 0x77, 0x64, 0xc3, 0x75, 0x65, 0xbc, 0xde, 0xbb, 0x97, 0x89, 0x93, 0x7d, 0x09, 0x66, 0xe3, 0x1d, 0x4a, - 0x99, 0x29, 0xc2, 0xdb, 0xcc, 0x33, 0xe7, 0x21, 0x16, 0x8e, 0x47, 0x92, 0x39, 0x88, 0x3f, 0x2d, 0x5d, 0xc1, 0xe9, - 0x38, 0xc9, 0x21, 0x3e, 0x55, 0xc1, 0x17, 0x0c, 0xbd, 0xce, 0xe6, 0xd3, 0xca, 0x9c, 0x9c, 0xac, 0xda, 0x70, 0x05, - 0xbe, 0xbd, 0xf5, 0x39, 0xbe, 0x6a, 0x61, 0xf3, 0x03, 0xbf, 0x73, 0xe1, 0xc1, 0xf6, 0xf1, 0xf5, 0x6b, 0xbf, 0x68, - 0xc6, 0x62, 0x09, 0x6b, 0xff, 0x58, 0xfa, 0x82, 0x50, 0x78, 0x2a, 0x04, 0x10, 0xfa, 0x82, 0x1a, 0x58, 0xce, 0x21, - 0x33, 0x67, 0x86, 0x9e, 0xbf, 0x66, 0x89, 0x23, 0x5a, 0xb0, 0xf1, 0x6b, 0xc3, 0xc2, 0x02, 0x4b, 0xed, 0xe5, 0x0d, - 0x58, 0x89, 0x85, 0x3d, 0xc6, 0x99, 0xe9, 0x6c, 0x8e, 0x99, 0x13, 0xf0, 0xb6, 0x65, 0x66, 0xa2, 0x0a, 0x9c, 0xe5, - 0x07, 0x5a, 0x9f, 0xa0, 0x5a, 0xc9, 0xbf, 0xba, 0x30, 0xae, 0x68, 0x83, 0xb3, 0xb9, 0xb4, 0x35, 0x04, 0xae, 0x4a, - 0x9a, 0x7c, 0x4c, 0xd6, 0x71, 0x27, 0x07, 0x3f, 0x4b, 0x03, 0x3e, 0x6b, 0x7c, 0x16, 0xe2, 0xb2, 0x24, 0xef, 0xd1, - 0x9c, 0xf5, 0xa1, 0x73, 0xad, 0x0d, 0x16, 0x6e, 0xec, 0x87, 0x29, 0xf8, 0xf0, 0x9a, 0x6c, 0xb7, 0xb5, 0x0f, 0x70, - 0x9f, 0xe6, 0xcd, 0xc7, 0x1d, 0xf4, 0x84, 0x9b, 0x1f, 0xff, 0x13, 0xf6, 0xed, 0xf2, 0x83, 0x2a, 0x85, 0x29, 0xf8, - 0xb8, 0xec, 0x8b, 0x22, 0xb2, 0xfd, 0x1e, 0xfa, 0x1e, 0xf8, 0x71, 0xd0, 0x70, 0xa1, 0x5f, 0xba, 0xcb, 0x18, 0x8d, - 0xe7, 0x4e, 0xb0, 0xda, 0x43, 0xe3, 0xba, 0x1e, 0x8c, 0xaa, 0x6c, 0x83, 0x61, 0x8d, 0x90, 0xa0, 0xcb, 0x63, 0x2b, - 0xfb, 0x2c, 0xc8, 0x06, 0x63, 0x25, 0x7b, 0x40, 0x09, 0x7b, 0xd0, 0x96, 0xd3, 0x00, 0x2c, 0x24, 0x1f, 0x37, 0xed, - 0x10, 0x68, 0xc8, 0x6a, 0x30, 0xdc, 0xe7, 0xaf, 0x89, 0xae, 0x2c, 0xad, 0x03, 0xfd, 0x07, 0xf7, 0x3d, 0x9a, 0x29, - 0xe2, 0xbe, 0x3c, 0xab, 0x29, 0xcb, 0x9d, 0xf6, 0xc9, 0x52, 0x1e, 0x7b, 0x18, 0x9e, 0x67, 0x0a, 0x39, 0x9d, 0xd3, - 0xaf, 0xb3, 0x35, 0x0e, 0xd2, 0x4a, 0x79, 0xd2, 0xbe, 0x4e, 0x5b, 0x5f, 0xf6, 0x9d, 0x88, 0xd5, 0x09, 0xee, 0x6a, - 0xa8, 0xd5, 0x4b, 0xaf, 0x0d, 0x86, 0xd3, 0x41, 0xfb, 0x0d, 0xe8, 0x6e, 0x69, 0x7d, 0x3b, 0xa9, 0x96, 0x48, 0x9c, - 0x1e, 0xe2, 0x76, 0x30, 0x9b, 0xa1, 0xb0, 0xb3, 0xad, 0xae, 0x2e, 0x09, 0x1c, 0xa0, 0xa9, 0x15, 0xf8, 0x70, 0xb7, - 0x88, 0xd5, 0x54, 0x1e, 0xe2, 0x63, 0x20, 0x77, 0x08, 0x38, 0x2f, 0xab, 0x90, 0xf3, 0x91, 0x61, 0x2d, 0xd6, 0x34, - 0xc3, 0x01, 0x53, 0x52, 0x07, 0x35, 0xdc, 0x28, 0x6b, 0xac, 0x8a, 0x96, 0x29, 0xb6, 0x3a, 0xfc, 0xba, 0xfd, 0xf3, - 0x35, 0x42, 0x90, 0xf5, 0x9b, 0x1f, 0x0b, 0xa2, 0x93, 0x41, 0x76, 0x8f, 0x38, 0x3e, 0x47, 0xc7, 0x5e, 0xae, 0xd6, - 0x5d, 0x94, 0x76, 0x27, 0x9b, 0xa9, 0xf2, 0xf9, 0x08, 0xf4, 0x92, 0x63, 0x70, 0xd8, 0x0e, 0x92, 0xe1, 0xc7, 0xd0, - 0x91, 0x50, 0x97, 0x97, 0xd4, 0x9a, 0x75, 0xf8, 0x61, 0xcf, 0xab, 0x5e, 0xce, 0x62, 0x37, 0x3d, 0x03, 0x8c, 0x53, - 0x6e, 0x7a, 0x7b, 0xac, 0x06, 0x00, 0x5b, 0x28, 0xbe, 0x86, 0x7d, 0x48, 0xc0, 0x3b, 0x14, 0xfd, 0xc1, 0xce, 0xc3, - 0x70, 0x51, 0x5c, 0xaa, 0x2c, 0x1d, 0x3f, 0x4e, 0xa3, 0x3a, 0x40, 0xf0, 0xf7, 0x78, 0xc2, 0xca, 0xd2, 0x42, 0x0d, - 0xee, 0x5c, 0x9a, 0xb8, 0x50, 0x04, 0xe2, 0x10, 0xfb, 0x59, 0xab, 0xea, 0xfe, 0x7d, 0xed, 0x8a, 0x00, 0xd4, 0xbe, - 0xa4, 0x83, 0x7b, 0x61, 0x87, 0xf9, 0x01, 0x6b, 0x5d, 0x23, 0x7c, 0x5e, 0xab, 0x29, 0x33, 0x3c, 0x10, 0x7c, 0x09, - 0xcf, 0xd5, 0x41, 0x59, 0x1d, 0xe4, 0x18, 0x29, 0x20, 0x59, 0x41, 0x74, 0x49, 0x90, 0x12, 0x3d, 0x11, 0x9b, 0xd1, - 0x3a, 0x32, 0x15, 0xd8, 0xb8, 0xb1, 0xc0, 0x30, 0xec, 0x12, 0x08, 0xf6, 0xc0, 0xb2, 0xe6, 0xe4, 0x95, 0xfe, 0xc0, - 0x6f, 0x11, 0x35, 0xac, 0x43, 0x94, 0x10, 0x6a, 0x56, 0x53, 0x11, 0x08, 0xaf, 0x8a, 0x98, 0x27, 0x93, 0xc9, 0x09, - 0xf0, 0xae, 0x3d, 0x51, 0xf4, 0x74, 0x67, 0xc7, 0xa2, 0x32, 0xcf, 0x2e, 0x52, 0xe1, 0x2a, 0x03, 0xaa, 0xc5, 0x81, - 0x2b, 0x87, 0x45, 0x74, 0x55, 0x4a, 0xee, 0x81, 0xcd, 0x7c, 0x03, 0xe7, 0x3a, 0x0d, 0xda, 0xca, 0xb1, 0x43, 0xc3, - 0x15, 0x5e, 0x14, 0x14, 0x0e, 0x94, 0xb2, 0x3b, 0x45, 0x98, 0xe6, 0xd6, 0x53, 0x91, 0x05, 0x0e, 0x60, 0x01, 0xf7, - 0xe6, 0xee, 0x22, 0x03, 0xb6, 0x8f, 0x86, 0x70, 0x6a, 0x01, 0x7a, 0x6f, 0xf3, 0x9f, 0xba, 0xcc, 0x69, 0xf3, 0x5f, - 0xbe, 0xa1, 0x6e, 0xad, 0x99, 0x4c, 0x8b, 0x5e, 0x86, 0xe4, 0x9b, 0xde, 0xaa, 0xbf, 0x7b, 0x31, 0x83, 0xc1, 0x7b, - 0x92, 0xcb, 0xac, 0x4f, 0x02, 0x4e, 0xbd, 0x0d, 0x1f, 0xa8, 0x8f, 0xb6, 0xa1, 0x75, 0x08, 0x01, 0x16, 0x87, 0x30, - 0x76, 0x82, 0x3d, 0xfc, 0x8c, 0x98, 0x4b, 0x11, 0xc6, 0x6b, 0xec, 0x05, 0x5f, 0xba, 0xd6, 0x9b, 0x9b, 0x62, 0xcf, - 0xce, 0xab, 0x45, 0x08, 0xa5, 0xa7, 0x69, 0x12, 0x9f, 0x5d, 0xba, 0x5d, 0xc6, 0x73, 0xd0, 0x44, 0x46, 0xa1, 0x10, - 0x91, 0x3c, 0x17, 0x34, 0x2d, 0xb4, 0xbd, 0x03, 0xea, 0x18, 0x44, 0xa5, 0x80, 0xf5, 0xf0, 0xa0, 0xd0, 0xe2, 0xeb, - 0xa7, 0xd9, 0x33, 0xd4, 0x9f, 0xd8, 0x39, 0xe1, 0x5f, 0x1d, 0xf8, 0x29, 0x11, 0xfb, 0x2d, 0x5a, 0xe0, 0xdc, 0xfc, - 0x6a, 0x28, 0xc0, 0xfe, 0x88, 0x09, 0x7f, 0x85, 0x01, 0x8c, 0x8c, 0xe0, 0xff, 0xf2, 0x4b, 0x56, 0x54, 0x30, 0xcc, - 0x4b, 0xe1, 0x9d, 0xe2, 0x23, 0x14, 0xd0, 0xf3, 0x92, 0x26, 0x5b, 0xc0, 0x79, 0x4b, 0x4d, 0xd7, 0x05, 0x90, 0x31, - 0x06, 0x20, 0x10, 0x57, 0x9f, 0x30, 0xef, 0x56, 0xa3, 0x64, 0x6f, 0xd3, 0x6f, 0x06, 0x68, 0xc6, 0xcd, 0x88, 0xd9, - 0x64, 0x68, 0xc1, 0xd2, 0x71, 0x34, 0xc2, 0x4f, 0xa3, 0x58, 0xff, 0xfa, 0x54, 0x09, 0xa8, 0xa4, 0x7b, 0x01, 0x7f, - 0x9b, 0x96, 0x78, 0x4b, 0xe3, 0xfc, 0x5e, 0xe3, 0x5b, 0xb7, 0x6f, 0xfd, 0xf2, 0xf1, 0xc3, 0xd5, 0x42, 0x58, 0xad, - 0x4f, 0x3e, 0xa5, 0xad, 0x73, 0x83, 0xe8, 0x51, 0xa8, 0x71, 0x28, 0x84, 0x46, 0xf2, 0x38, 0xc9, 0xc8, 0x66, 0xb3, - 0xac, 0x77, 0x21, 0xff, 0xd8, 0xd5, 0x7b, 0xc9, 0x95, 0x0d, 0xf2, 0xee, 0x2e, 0x30, 0x3b, 0xbb, 0xb5, 0x25, 0x6b, - 0x9e, 0xca, 0xa1, 0x1b, 0x3c, 0x53, 0x2d, 0x1d, 0x29, 0x2c, 0xf0, 0x48, 0xcb, 0xd8, 0x99, 0x3d, 0xbf, 0x06, 0x34, - 0x15, 0xe7, 0x0a, 0xea, 0x9c, 0x05, 0xa5, 0x41, 0xc1, 0x9f, 0xf4, 0x46, 0xde, 0xec, 0xb0, 0xd8, 0xbd, 0x83, 0xac, - 0x8e, 0xff, 0x37, 0xd2, 0xa8, 0xee, 0x12, 0x1a, 0x85, 0x67, 0xd1, 0x5b, 0xab, 0x0a, 0xdd, 0x3b, 0xdc, 0x55, 0x72, - 0x50, 0xfb, 0xda, 0xa6, 0x18, 0xad, 0x61, 0xae, 0xd6, 0xbe, 0xde, 0x65, 0xda, 0xcb, 0x3b, 0xe2, 0x1f, 0x7e, 0xb2, - 0x39, 0x42, 0x08, 0x99, 0xec, 0x9e, 0xfa, 0x14, 0x00, 0xbe, 0x15, 0x00, 0xc4, 0x08, 0xbf, 0x60, 0xdd, 0xe0, 0x29, - 0x76, 0x8f, 0x67, 0xb7, 0xa5, 0x16, 0xee, 0x23, 0xc4, 0x58, 0x3b, 0xee, 0xd7, 0x12, 0x1e, 0x09, 0xfc, 0xb6, 0x75, - 0xea, 0x71, 0xa8, 0x77, 0xf6, 0xd3, 0x4e, 0x22, 0x3e, 0xc6, 0x46, 0x5a, 0x0f, 0xe7, 0xd8, 0x92, 0xdf, 0x50, 0x3b, - 0x71, 0x72, 0xd7, 0xd2, 0x59, 0xf4, 0x0b, 0x01, 0xfc, 0xe5, 0xb7, 0x95, 0x35, 0x3f, 0x5c, 0xd8, 0xfe, 0x4b, 0xff, - 0x65, 0x61, 0xff, 0x39, 0xb7, 0x80, 0x8d, 0x04, 0x8c, 0x58, 0xdf, 0x8c, 0x1b, 0x0f, 0x18, 0xb1, 0x63, 0x00, 0xa4, - 0x83, 0x18, 0x01, 0x4d, 0x79, 0x28, 0x04, 0x2f, 0xa2, 0x37, 0x8a, 0xce, 0xcd, 0x98, 0x06, 0xb2, 0xf2, 0x9a, 0x4c, - 0xf5, 0x41, 0xd8, 0xf8, 0x59, 0xb7, 0xb6, 0x70, 0x93, 0x0f, 0x63, 0xbd, 0xb4, 0xe6, 0xcc, 0x02, 0xd0, 0xa7, 0xb8, - 0xbf, 0x55, 0xa9, 0xcd, 0x35, 0xf6, 0xe6, 0xb4, 0x93, 0x1f, 0x7e, 0x0e, 0x7b, 0xbb, 0xe3, 0xcf, 0x85, 0xb9, 0x74, - 0xf4, 0xf9, 0xe5, 0xcc, 0x98, 0x5a, 0xd7, 0xda, 0xfd, 0xd1, 0xc2, 0x03, 0x6f, 0x50, 0xd9, 0x28, 0xdb, 0xe7, 0x12, - 0xa4, 0x8d, 0x84, 0x71, 0x27, 0x4e, 0x83, 0xad, 0x7c, 0x23, 0x59, 0x4a, 0xdd, 0xda, 0xcc, 0x00, 0xb6, 0x9b, 0xe0, - 0x2d, 0xa3, 0x8b, 0xde, 0x17, 0x96, 0xe9, 0xe9, 0x2e, 0xae, 0xdd, 0x22, 0xda, 0xa1, 0x5c, 0xb3, 0x88, 0x67, 0x6a, - 0xc1, 0x93, 0xe4, 0x62, 0x0e, 0xb8, 0x81, 0x32, 0xb1, 0xa4, 0x7d, 0x9d, 0x39, 0x43, 0x64, 0x45, 0x7e, 0xa5, 0x9f, - 0x1a, 0x7f, 0xbf, 0x8d, 0xbf, 0x9a, 0xdb, 0x6c, 0xd7, 0xaf, 0xeb, 0x94, 0x28, 0xd4, 0xb4, 0xd8, 0xf7, 0xd9, 0xa2, - 0x27, 0x8c, 0xed, 0x63, 0x4e, 0x8c, 0xd5, 0x5a, 0xf3, 0xee, 0x7b, 0x3d, 0x75, 0x9e, 0x6a, 0x1f, 0x51, 0xf3, 0x05, - 0xf6, 0xfb, 0xa0, 0xbd, 0xeb, 0xf5, 0x67, 0xf1, 0xa1, 0x6f, 0x2f, 0xbe, 0x7c, 0x5c, 0xaa, 0x4f, 0x4c, 0xcd, 0xd1, - 0x43, 0x76, 0xa8, 0x3c, 0xc1, 0x14, 0x3e, 0x50, 0x26, 0xa2, 0x02, 0xde, 0xbb, 0xcd, 0xfb, 0xec, 0x45, 0xd7, 0x92, - 0xff, 0xa8, 0x41, 0x0b, 0x09, 0x6b, 0xee, 0x50, 0x15, 0xac, 0x3b, 0xe2, 0xbf, 0xce, 0x79, 0xad, 0x2c, 0x6b, 0x2b, - 0x42, 0xcb, 0x87, 0x1d, 0xbe, 0xf3, 0x54, 0xeb, 0x63, 0xdc, 0x62, 0x27, 0xb9, 0xdd, 0xf2, 0x4c, 0x14, 0xb7, 0xa0, - 0xea, 0x72, 0x04, 0x82, 0xb4, 0x01, 0x19, 0x69, 0x2b, 0x46, 0x2d, 0xdc, 0x27, 0xed, 0xd7, 0xf6, 0xbb, 0x10, 0x4b, - 0x4f, 0x6b, 0x9a, 0xb2, 0xd2, 0x4d, 0xec, 0x45, 0x4a, 0x11, 0x42, 0x66, 0x7d, 0xf0, 0xfa, 0x93, 0x9a, 0x61, 0x73, - 0x77, 0xb7, 0x3a, 0x23, 0x3a, 0x16, 0xae, 0x51, 0x22, 0x2b, 0xe2, 0x6e, 0xe3, 0x30, 0x8b, 0xcf, 0xa5, 0x7f, 0x96, - 0xe7, 0x60, 0xce, 0x09, 0xed, 0xa6, 0x78, 0xa1, 0x19, 0xba, 0xe9, 0x1c, 0x3f, 0x30, 0x0c, 0x24, 0xbd, 0x40, 0xfe, - 0x3a, 0x95, 0xe3, 0x94, 0x23, 0x6a, 0x2d, 0x2b, 0xd1, 0xb6, 0xa0, 0x60, 0xf1, 0xd8, 0xdc, 0x01, 0xbe, 0x1b, 0x7e, - 0x5c, 0x60, 0xbe, 0x79, 0xf7, 0x19, 0xa2, 0x87, 0xf2, 0x40, 0xcd, 0x3b, 0xab, 0x95, 0x09, 0xde, 0x90, 0xc6, 0x9f, - 0x4a, 0x12, 0xbb, 0x37, 0x34, 0x69, 0x75, 0xd3, 0xbd, 0xb1, 0xd9, 0x2d, 0x65, 0x0e, 0xf3, 0xb0, 0xe9, 0x8a, 0x62, - 0x14, 0xf0, 0xac, 0x7b, 0x3b, 0x94, 0x95, 0x02, 0x16, 0xe0, 0x04, 0xea, 0x83, 0x5a, 0x58, 0x2c, 0x8f, 0x13, 0xf5, - 0x98, 0x59, 0x0e, 0x7c, 0x6d, 0xf0, 0xb2, 0x8f, 0xce, 0x12, 0xb0, 0x94, 0x6a, 0x21, 0x6d, 0x2a, 0x29, 0x7e, 0x99, - 0x93, 0xd3, 0xdb, 0x54, 0x13, 0xb5, 0xc9, 0xed, 0x7e, 0xdf, 0x71, 0x06, 0xad, 0xe4, 0xe0, 0x0e, 0x8e, 0xbd, 0x1e, - 0x84, 0x6c, 0x54, 0x40, 0xa6, 0xd9, 0x9f, 0xf2, 0xc8, 0x4e, 0x4b, 0xf9, 0x9c, 0xd4, 0xb4, 0x29, 0x02, 0xd6, 0x6c, - 0xbc, 0x9b, 0x36, 0x92, 0x62, 0xed, 0x0c, 0x47, 0x3c, 0x37, 0x8d, 0x8b, 0xef, 0xf3, 0x1f, 0x7b, 0xca, 0x16, 0xc2, - 0xea, 0x69, 0x7c, 0xd4, 0x3b, 0xbd, 0x32, 0xad, 0x1a, 0x2a, 0x73, 0x36, 0x96, 0xf0, 0x01}; + 0x5b, 0x36, 0x7a, 0x53, 0xc2, 0x36, 0x06, 0x5a, 0x1f, 0xd4, 0x4e, 0x00, 0xb3, 0xd6, 0xea, 0xff, 0x0a, 0xab, 0x51, + 0x94, 0xb1, 0xe6, 0xb0, 0x2e, 0x61, 0xbb, 0x1a, 0x70, 0x3b, 0xd8, 0x06, 0xfd, 0x7d, 0x2f, 0x1a, 0x00, 0x55, 0x35, + 0xe3, 0xa8, 0x1c, 0x62, 0xca, 0xd3, 0xb4, 0x00, 0xdb, 0x5e, 0x43, 0xa7, 0x14, 0x08, 0xa4, 0x51, 0x99, 0x96, 0xb6, + 0xf5, 0x0e, 0x99, 0x80, 0x52, 0x31, 0xe8, 0x10, 0x27, 0x1c, 0x04, 0x11, 0x58, 0xc5, 0x1c, 0xcc, 0xd4, 0x74, 0x4c, + 0x33, 0x11, 0xbb, 0xdb, 0xb0, 0xb4, 0x0a, 0x87, 0x13, 0x12, 0xb4, 0x8f, 0xe7, 0xd1, 0xc8, 0x85, 0x26, 0x07, 0xab, + 0x2e, 0x7a, 0x6e, 0x93, 0xb9, 0x4c, 0xb4, 0x84, 0x5b, 0x59, 0xda, 0xde, 0x2f, 0x74, 0x88, 0x3c, 0x53, 0x3b, 0xfd, + 0x28, 0xf8, 0x60, 0x4b, 0xf2, 0xc2, 0x03, 0xda, 0x33, 0x59, 0xe4, 0x2a, 0x48, 0x26, 0xde, 0x20, 0x6e, 0xcb, 0x83, + 0xef, 0x81, 0x7a, 0x6b, 0x36, 0x9a, 0x3f, 0x38, 0x8e, 0xfd, 0xf9, 0x7e, 0x73, 0xab, 0x6e, 0x85, 0xf0, 0x62, 0xe0, + 0x60, 0x60, 0x23, 0x1b, 0x11, 0xaf, 0x39, 0x32, 0xed, 0x79, 0x20, 0x27, 0x04, 0x1f, 0x6b, 0xf4, 0xd9, 0x97, 0x2f, + 0x38, 0xe4, 0x5b, 0x75, 0xbb, 0xb4, 0xfe, 0xd5, 0xfb, 0x5f, 0xa5, 0xc2, 0x5c, 0x88, 0xc6, 0xdf, 0xd0, 0x1e, 0x10, + 0xa7, 0x44, 0x3b, 0xdd, 0xb8, 0xbd, 0x2c, 0x7a, 0x10, 0x61, 0xbe, 0x8b, 0xbb, 0x3c, 0x10, 0x0e, 0x5f, 0x06, 0xc6, + 0xe0, 0xf2, 0xe6, 0x88, 0xa8, 0xb8, 0xa2, 0xab, 0xf7, 0x6b, 0xab, 0xe9, 0xfb, 0xbd, 0xa6, 0xfe, 0xd7, 0xef, 0x23, + 0xd3, 0x86, 0xa9, 0xdc, 0x57, 0x3a, 0xf7, 0xb8, 0x49, 0x6e, 0x45, 0x76, 0xda, 0xa6, 0x21, 0xc3, 0x2b, 0x0f, 0xac, + 0xc9, 0x85, 0x03, 0x60, 0xdd, 0x28, 0x5d, 0xe5, 0x3b, 0xfb, 0xf3, 0xbb, 0xdc, 0xc2, 0x94, 0xab, 0x90, 0x2b, 0x05, + 0xc8, 0x64, 0x3f, 0x3f, 0xc8, 0x1a, 0xe3, 0xef, 0x17, 0x88, 0x77, 0x9f, 0x18, 0x8d, 0xda, 0xd2, 0xc0, 0xb8, 0x5b, + 0x99, 0x6e, 0xd9, 0x12, 0xaa, 0xdc, 0x2f, 0xeb, 0xff, 0xff, 0xfb, 0x4e, 0xff, 0xbf, 0x7e, 0xed, 0x55, 0x22, 0xe6, + 0x8a, 0x96, 0x64, 0x4c, 0xdf, 0x4b, 0x2c, 0xef, 0x43, 0x42, 0x69, 0x18, 0x37, 0x29, 0x19, 0x40, 0x1f, 0x19, 0x8a, + 0x6b, 0x84, 0xb5, 0x31, 0x6a, 0x1d, 0xd9, 0x57, 0x5b, 0x04, 0xbb, 0xd6, 0xde, 0xfa, 0x52, 0xfd, 0xbe, 0x7e, 0x1f, + 0xe7, 0x5d, 0xc3, 0x72, 0xc9, 0x69, 0x3a, 0x6f, 0xf7, 0x1e, 0x6d, 0x29, 0x74, 0xce, 0x4b, 0xde, 0x98, 0xe5, 0x62, + 0x40, 0x34, 0x7a, 0xba, 0x6d, 0x0c, 0x30, 0x01, 0xd0, 0x92, 0x98, 0x29, 0xed, 0xfb, 0xea, 0xeb, 0x7f, 0xfd, 0x56, + 0x3a, 0x29, 0x0a, 0x1f, 0xd9, 0xb7, 0x84, 0x3a, 0x26, 0xfa, 0xd6, 0xce, 0x76, 0x3a, 0x32, 0x19, 0x0a, 0xb2, 0x94, + 0xc7, 0x80, 0xbe, 0x24, 0x74, 0x27, 0x0a, 0xff, 0x5f, 0x5f, 0xd3, 0xfa, 0xfa, 0x95, 0x08, 0xbb, 0xcc, 0xa5, 0x4e, + 0x51, 0xa8, 0x7b, 0x7f, 0x4f, 0x49, 0xce, 0xb2, 0xec, 0x9e, 0x0a, 0x41, 0xcb, 0xb4, 0x8d, 0x17, 0xe1, 0x00, 0xdc, + 0x13, 0x13, 0x59, 0xf7, 0x30, 0x55, 0xeb, 0xbf, 0x9f, 0x97, 0x0d, 0x67, 0x15, 0x30, 0x14, 0x61, 0x0c, 0x48, 0xaa, + 0xd8, 0x41, 0x5a, 0x75, 0x4b, 0xd3, 0x16, 0xa5, 0xc1, 0xd4, 0xc8, 0x9c, 0x84, 0x1c, 0x78, 0x01, 0xe8, 0x24, 0x45, + 0xca, 0xff, 0x73, 0xbe, 0x2d, 0xad, 0xfe, 0x74, 0x75, 0x79, 0xa2, 0xba, 0x1f, 0x6a, 0x09, 0x10, 0xc6, 0x50, 0xb3, + 0x6c, 0x4a, 0xe7, 0x9f, 0x5d, 0xbf, 0x26, 0x78, 0xa6, 0x37, 0x07, 0xce, 0xa5, 0x55, 0xaf, 0xef, 0x06, 0xd4, 0x72, + 0x4f, 0x48, 0xdf, 0x15, 0x1b, 0xec, 0xd7, 0x48, 0xa6, 0xe5, 0xbd, 0xf3, 0x85, 0x88, 0xaa, 0x1c, 0x80, 0x11, 0xb4, + 0x51, 0x68, 0xa0, 0xbc, 0xbd, 0xf6, 0xaa, 0x6f, 0x55, 0x94, 0x8e, 0x0d, 0x8c, 0xc0, 0x32, 0xcb, 0xaf, 0x77, 0x27, + 0x94, 0x5c, 0xad, 0xbd, 0x6f, 0x92, 0xf0, 0x18, 0x70, 0x5a, 0x6c, 0x58, 0x38, 0x2f, 0xd9, 0x90, 0xa8, 0xf9, 0x9a, + 0xad, 0xc0, 0x05, 0x0a, 0xeb, 0x98, 0xcb, 0xaa, 0x7a, 0x8b, 0x0a, 0x89, 0xf8, 0x75, 0xfb, 0x7e, 0xc6, 0x7d, 0x4c, + 0x37, 0xc3, 0x0c, 0x86, 0x8d, 0x82, 0x27, 0x18, 0xd7, 0x33, 0xb5, 0x4c, 0x5f, 0x6f, 0xa7, 0x52, 0x3e, 0xdd, 0x19, + 0x97, 0x57, 0x40, 0x5b, 0x29, 0xed, 0xd9, 0x0b, 0xb1, 0xcb, 0x58, 0x04, 0x08, 0x0d, 0x20, 0x51, 0xe9, 0x1b, 0x22, + 0xf6, 0x9a, 0x6f, 0xe8, 0xe9, 0xbc, 0x01, 0x2c, 0x70, 0xf8, 0x86, 0x54, 0x72, 0xa5, 0x38, 0x22, 0xd0, 0xcb, 0x95, + 0xe1, 0xc1, 0xb5, 0xb9, 0x59, 0x01, 0xae, 0xd5, 0x5a, 0x4a, 0xfa, 0x13, 0x37, 0x9b, 0xd6, 0xff, 0x3e, 0x2f, 0xce, + 0xdb, 0xec, 0x44, 0xba, 0xfe, 0x92, 0xe3, 0xe4, 0x4a, 0xe9, 0xd9, 0x82, 0x09, 0x25, 0xcc, 0xb0, 0x86, 0x01, 0x93, + 0xa6, 0xd5, 0x3e, 0x3c, 0x24, 0x1f, 0x50, 0xab, 0x6f, 0xf8, 0x83, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, + 0x74, 0x20, 0x44, 0xf6, 0x00, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xcc, 0x2a, 0x50, 0x0d, 0x90, 0x6c, 0x59, + 0xbf, 0xd6, 0x62, 0x53, 0x71, 0xcd, 0xbb, 0xcc, 0xef, 0xa2, 0x33, 0x7e, 0x18, 0x56, 0x64, 0x44, 0x66, 0x23, 0x5d, + 0x0d, 0xcb, 0x36, 0xb2, 0x9c, 0x06, 0xf6, 0xbe, 0xf7, 0x7f, 0x14, 0xfe, 0xff, 0x91, 0xc5, 0x89, 0x88, 0x2c, 0x50, + 0x91, 0x59, 0xc5, 0x39, 0x99, 0x05, 0xcc, 0xa8, 0x0a, 0xe0, 0x8c, 0x0a, 0x60, 0x1f, 0x1d, 0x90, 0x63, 0x41, 0xd0, + 0x68, 0x9a, 0x6c, 0xf6, 0xd1, 0x90, 0x2d, 0x6f, 0x77, 0x5a, 0xac, 0x38, 0x94, 0xeb, 0x19, 0xd9, 0x96, 0xfc, 0x6e, + 0x07, 0xca, 0x9a, 0xa5, 0xb4, 0xd2, 0xd1, 0x7d, 0x73, 0x6f, 0x76, 0xca, 0xa9, 0x23, 0x50, 0x69, 0xd5, 0x56, 0x08, + 0xd7, 0xcc, 0xec, 0x06, 0x76, 0x3f, 0xe7, 0x97, 0x36, 0x1f, 0x37, 0xc5, 0xa4, 0x98, 0x94, 0xe0, 0x80, 0xe4, 0x19, + 0x7b, 0xc6, 0x12, 0x0a, 0xc7, 0xf2, 0xde, 0xa9, 0x3f, 0x86, 0xdf, 0x43, 0x69, 0x61, 0x30, 0x75, 0xa6, 0x69, 0xfa, + 0xef, 0xb6, 0x31, 0xab, 0x2f, 0xd7, 0xca, 0xcc, 0x2d, 0xcd, 0x10, 0x42, 0x0a, 0xa0, 0xa2, 0xeb, 0xff, 0x36, 0xbe, + 0xd6, 0x57, 0x8e, 0xda, 0xfa, 0x75, 0xd4, 0xdd, 0x7e, 0x5c, 0x67, 0x08, 0x10, 0x02, 0xed, 0x3c, 0x64, 0x4a, 0x75, + 0xdb, 0x71, 0x9e, 0x3d, 0x4d, 0x08, 0x21, 0x04, 0xe2, 0xa8, 0xe2, 0xf8, 0x5f, 0x23, 0x9d, 0x4a, 0x1b, 0x02, 0x0d, + 0xa4, 0x48, 0xfd, 0x1b, 0xeb, 0x6f, 0x0d, 0xdb, 0xf7, 0xf4, 0x10, 0x9d, 0xd8, 0xd3, 0x00, 0xa1, 0x36, 0x49, 0xbe, + 0xd8, 0x9a, 0xa7, 0xb5, 0x6d, 0x74, 0x2c, 0x43, 0x2d, 0x7f, 0xdf, 0x4c, 0xbf, 0x6d, 0x30, 0x06, 0x2c, 0x33, 0x25, + 0x81, 0x19, 0xf2, 0xb9, 0x6e, 0x04, 0xf7, 0xcf, 0x4c, 0x26, 0xce, 0x1e, 0x07, 0x80, 0xd3, 0xb1, 0x47, 0x5b, 0x88, + 0x19, 0x28, 0xc7, 0xb9, 0x83, 0x9b, 0x5b, 0x23, 0x98, 0xf6, 0xf6, 0x50, 0xb2, 0xdd, 0x47, 0x21, 0xd6, 0x20, 0x5a, + 0x78, 0x61, 0x76, 0xf4, 0x81, 0xc9, 0xdb, 0x4e, 0x15, 0xbd, 0xa5, 0x5b, 0x7e, 0xc2, 0x1c, 0x81, 0x66, 0xf4, 0x92, + 0x5f, 0x04, 0xf0, 0xbe, 0x7d, 0x0f, 0x45, 0x99, 0x04, 0xca, 0xfe, 0xfa, 0xc9, 0x96, 0x91, 0x9d, 0x9f, 0xb8, 0x6b, + 0x7b, 0xc3, 0xe6, 0xe0, 0x21, 0x83, 0x27, 0x75, 0x98, 0xd9, 0x7e, 0x29, 0x3f, 0xe1, 0x6a, 0x19, 0xe6, 0x36, 0xe6, + 0xf3, 0xfd, 0x14, 0x5d, 0xa1, 0x21, 0x63, 0x41, 0xea, 0xb9, 0xf7, 0x87, 0xc6, 0xf2, 0xc7, 0x64, 0x59, 0x06, 0x6e, + 0xcb, 0x89, 0xc7, 0x92, 0xfa, 0xc5, 0x52, 0x4d, 0xdf, 0x93, 0x26, 0x01, 0x80, 0xac, 0xb5, 0x0d, 0xfd, 0x08, 0x57, + 0x71, 0x7d, 0xad, 0x5c, 0x14, 0xe3, 0x9a, 0x6f, 0x87, 0x09, 0x06, 0x92, 0xf5, 0x13, 0x28, 0x6e, 0x7b, 0xf7, 0x6f, + 0xcf, 0x6e, 0x6d, 0x59, 0x64, 0xd4, 0x74, 0x38, 0xbb, 0x0f, 0x9d, 0x69, 0x03, 0x8a, 0xb8, 0xc3, 0xdd, 0xa7, 0x63, + 0x4d, 0x41, 0x62, 0xc3, 0x21, 0x83, 0xe7, 0x02, 0x1d, 0xcb, 0x3e, 0xa9, 0xa5, 0x24, 0x6b, 0x72, 0xe6, 0xd2, 0x10, + 0x66, 0xa3, 0x73, 0x76, 0x1b, 0x4b, 0x07, 0xdc, 0x96, 0x33, 0xda, 0x45, 0x26, 0xf7, 0xbc, 0x89, 0xef, 0x68, 0xcc, + 0x2f, 0xbb, 0xc0, 0xde, 0xfa, 0x20, 0xdb, 0x42, 0xd0, 0x6c, 0xcc, 0xec, 0xc0, 0x37, 0xde, 0x77, 0xd3, 0x21, 0x09, + 0x12, 0x4d, 0xdf, 0xb7, 0xa0, 0x79, 0x31, 0xfa, 0xb8, 0xee, 0x61, 0xab, 0x50, 0xdf, 0xfe, 0x88, 0x87, 0x19, 0x9e, + 0x78, 0x39, 0x23, 0x5f, 0xef, 0xdd, 0xe6, 0x65, 0xe7, 0xd1, 0x17, 0x31, 0xbe, 0x3d, 0xbb, 0x7d, 0xb9, 0x79, 0x64, + 0xf7, 0x11, 0xd6, 0xbe, 0x1b, 0x12, 0x76, 0x35, 0xbf, 0x77, 0x1b, 0x7e, 0xf4, 0xda, 0x4b, 0x35, 0xab, 0xc9, 0x7f, + 0xfa, 0xfe, 0x13, 0xda, 0xa8, 0x1d, 0xdc, 0xc3, 0xfd, 0x05, 0xc2, 0xb3, 0xa6, 0x38, 0x17, 0x58, 0x73, 0x18, 0x7f, + 0xb6, 0x66, 0xc9, 0x3f, 0x3b, 0x22, 0xf4, 0x39, 0xcc, 0xd7, 0x39, 0x6f, 0xcf, 0x62, 0x6a, 0xfd, 0x4a, 0x44, 0x61, + 0x22, 0x2a, 0x83, 0x26, 0x28, 0xca, 0x2b, 0x27, 0x7d, 0xc7, 0x45, 0x49, 0x20, 0x91, 0xdd, 0x52, 0x2b, 0xa5, 0x75, + 0xe1, 0xe4, 0xde, 0xef, 0x00, 0x02, 0xfd, 0x39, 0xb6, 0x2c, 0xbb, 0xe4, 0xf5, 0x4b, 0x49, 0x7d, 0xc7, 0x3c, 0xcd, + 0x3d, 0x00, 0x91, 0x0a, 0xdd, 0x2c, 0x65, 0x61, 0x89, 0x12, 0x79, 0x36, 0x9e, 0xeb, 0xbc, 0xca, 0xd0, 0x43, 0xb7, + 0xef, 0xdb, 0x25, 0xf2, 0xf0, 0x7c, 0x86, 0x03, 0x7c, 0xc7, 0x9c, 0x53, 0xbd, 0xc2, 0x84, 0xbc, 0x72, 0x56, 0xdc, + 0x8f, 0xa1, 0xd4, 0x68, 0x22, 0x56, 0xe4, 0x66, 0x34, 0xc8, 0x7b, 0x46, 0x6e, 0xaa, 0xfd, 0x52, 0x5b, 0x33, 0x33, + 0xd7, 0xb7, 0xad, 0x96, 0x71, 0x86, 0x72, 0x2f, 0xaa, 0x3a, 0xaa, 0xef, 0x49, 0x20, 0x3d, 0xcb, 0x19, 0xd7, 0x37, + 0x6f, 0x56, 0x94, 0x5f, 0x2b, 0x95, 0x50, 0xf6, 0x0d, 0x35, 0x79, 0xcd, 0xec, 0x4b, 0xea, 0x1a, 0xe6, 0x29, 0xd2, + 0x76, 0x3a, 0xf2, 0x5c, 0x14, 0x32, 0x68, 0x05, 0x7b, 0x9e, 0x3c, 0xba, 0xf6, 0x65, 0x5e, 0xe2, 0x2f, 0x2b, 0xcb, + 0x88, 0x04, 0x68, 0xe4, 0x5f, 0x10, 0xcd, 0x0c, 0x54, 0xc5, 0xd3, 0x64, 0xe1, 0x24, 0x68, 0x71, 0xa2, 0x0d, 0x9e, + 0xfd, 0x7e, 0xdb, 0xec, 0x83, 0x12, 0x2e, 0xaa, 0xd4, 0x7d, 0x4f, 0x13, 0xf2, 0xf0, 0x73, 0x91, 0xac, 0x65, 0xa0, + 0xd7, 0x60, 0x9e, 0x26, 0x20, 0x15, 0x96, 0xc9, 0x58, 0xe8, 0x82, 0x9a, 0xd1, 0x4d, 0x93, 0xe9, 0x11, 0x5f, 0xde, + 0xe2, 0xa2, 0xb8, 0xd5, 0x6a, 0xcb, 0x37, 0xb3, 0xb4, 0x63, 0xda, 0x02, 0xda, 0x1f, 0x3a, 0x81, 0x27, 0x6c, 0x1e, + 0x0b, 0xef, 0x26, 0x27, 0x23, 0x8c, 0x3f, 0xf7, 0x72, 0xa4, 0x1d, 0x6a, 0x77, 0x42, 0xf4, 0xea, 0x40, 0xe0, 0xbe, + 0x50, 0xb6, 0x62, 0xec, 0x4d, 0x12, 0x51, 0xdd, 0x7f, 0x40, 0xb7, 0xf6, 0xbf, 0x59, 0xbb, 0xf4, 0x45, 0xd0, 0x58, + 0x09, 0x47, 0xd2, 0xfa, 0x6d, 0xa8, 0x3d, 0x44, 0x00, 0x4e, 0xaf, 0x82, 0x19, 0x76, 0xdb, 0x80, 0xd9, 0x71, 0x51, + 0x8e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd0, 0x32, 0xba, 0xa9, 0xfd, 0x71, 0xfc, 0x21, 0x63, 0x96, 0xb6, 0x30, 0xb5, + 0xaf, 0x1a, 0x7f, 0x69, 0xd0, 0x48, 0xc5, 0x79, 0xed, 0xd0, 0xc0, 0x4f, 0xec, 0x0b, 0x96, 0x83, 0x23, 0x41, 0x2f, + 0xf3, 0xc1, 0x33, 0x97, 0x6a, 0xb0, 0xbc, 0x39, 0x72, 0xa0, 0x10, 0xb6, 0x14, 0xa1, 0x6c, 0xb0, 0xb5, 0xd2, 0x8a, + 0x55, 0x4f, 0x18, 0x9b, 0xf7, 0xa7, 0xb7, 0x26, 0xb2, 0x29, 0x5b, 0x38, 0x4c, 0xf5, 0x85, 0x82, 0x64, 0x7f, 0x16, + 0x77, 0x59, 0x26, 0xc0, 0x41, 0xc2, 0xf0, 0x82, 0x8e, 0x24, 0xdf, 0x07, 0x6f, 0xfa, 0x2c, 0x58, 0x18, 0x6d, 0x9b, + 0x1f, 0x6d, 0xbd, 0x17, 0xcf, 0x2c, 0x88, 0x6f, 0x16, 0x14, 0xdb, 0xb2, 0xe2, 0x08, 0x4b, 0x35, 0x6c, 0x42, 0x68, + 0x05, 0x11, 0xa8, 0xa9, 0x3f, 0xd7, 0x83, 0x6d, 0xd6, 0xbe, 0x6a, 0x55, 0xa5, 0xb3, 0x24, 0xd5, 0x38, 0x82, 0x42, + 0x0e, 0x06, 0x45, 0x10, 0xba, 0xb3, 0x7b, 0xf0, 0x13, 0x07, 0xe3, 0x42, 0xe0, 0x86, 0x96, 0xa7, 0xae, 0x5b, 0xc7, + 0x2d, 0x03, 0x53, 0x7d, 0xb9, 0xd2, 0x3c, 0xee, 0xa1, 0x75, 0xb0, 0x6b, 0x3b, 0x92, 0xcf, 0xb5, 0x78, 0x42, 0xdf, + 0x9d, 0xe8, 0x04, 0x86, 0x87, 0x23, 0x4f, 0xbc, 0x3c, 0x90, 0x80, 0x87, 0x00, 0xb3, 0xf2, 0xdd, 0x0f, 0xa1, 0x7a, + 0x7d, 0x11, 0x50, 0x40, 0x7c, 0x55, 0x6e, 0xfb, 0x03, 0x04, 0x2b, 0xea, 0x58, 0x00, 0x27, 0x2a, 0x4e, 0xc9, 0x01, + 0x09, 0xc6, 0x11, 0xea, 0x1b, 0xa0, 0x9b, 0x0f, 0x95, 0xf2, 0x2f, 0x5c, 0x4f, 0xbc, 0x28, 0xcf, 0xfa, 0xf9, 0x96, + 0x7c, 0xba, 0x6a, 0x51, 0x70, 0xaa, 0xb6, 0x49, 0xa6, 0x50, 0xba, 0xc1, 0x61, 0x4a, 0x11, 0xa7, 0x89, 0x44, 0x2d, + 0x04, 0x60, 0x5b, 0x45, 0xb4, 0xf4, 0xeb, 0x75, 0xd8, 0xd1, 0x52, 0xd8, 0xb2, 0xe0, 0x0b, 0xf5, 0x43, 0x8d, 0xb0, + 0xd8, 0xa8, 0xed, 0x5c, 0x6a, 0xfe, 0xf3, 0x35, 0xc9, 0x86, 0xd6, 0x2e, 0x7b, 0x0b, 0x41, 0x4d, 0xe1, 0x02, 0xb5, + 0xe5, 0x45, 0x32, 0xb5, 0x83, 0x98, 0xfd, 0xc8, 0x44, 0x72, 0x62, 0x79, 0x65, 0x6f, 0x2a, 0x5b, 0xd7, 0xa6, 0xdd, + 0x37, 0x25, 0x18, 0x7e, 0xd4, 0x52, 0x7a, 0x36, 0xec, 0xfc, 0x5a, 0x59, 0x7a, 0x0c, 0x6b, 0x67, 0x4a, 0x20, 0x70, + 0xf9, 0x17, 0xa7, 0xed, 0x02, 0x93, 0x5b, 0x3d, 0xa6, 0xf4, 0x52, 0x8f, 0xf9, 0xee, 0x75, 0x48, 0x95, 0x2c, 0x04, + 0xc9, 0x61, 0xa0, 0xbf, 0x16, 0x13, 0xa5, 0x40, 0x0b, 0x89, 0x50, 0x6e, 0x23, 0x09, 0x70, 0xff, 0x5e, 0x95, 0x31, + 0xc0, 0xb6, 0x0e, 0x3f, 0x4b, 0xb3, 0xab, 0xe7, 0x62, 0x40, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x11, 0xc2, 0x49, 0x53, + 0x7b, 0xe7, 0x2a, 0x12, 0xc9, 0x51, 0x8a, 0x58, 0x6c, 0x9c, 0x95, 0x2e, 0x35, 0xc2, 0x5a, 0x18, 0xcb, 0xb1, 0x02, + 0x92, 0x33, 0xb7, 0x59, 0x79, 0x7c, 0xdb, 0x1c, 0x24, 0xc0, 0x3d, 0xe2, 0xe2, 0x1f, 0x9c, 0x04, 0xc8, 0x35, 0x41, + 0x82, 0x84, 0xf6, 0xd9, 0x80, 0x4c, 0x18, 0x90, 0x91, 0x31, 0x89, 0x6e, 0x04, 0x92, 0x7b, 0x4d, 0xa7, 0xfa, 0x18, + 0x60, 0x2a, 0x27, 0xab, 0x09, 0x44, 0x42, 0x1c, 0x6f, 0x6a, 0xc3, 0x4e, 0x60, 0x2c, 0x03, 0xec, 0xb8, 0x74, 0x54, + 0x72, 0x2e, 0x0e, 0x30, 0xac, 0x9a, 0xf9, 0x85, 0x4d, 0x97, 0xc0, 0x10, 0x47, 0xb4, 0x0b, 0x28, 0xc8, 0xa9, 0xeb, + 0x73, 0x0b, 0x46, 0x0e, 0x12, 0xd7, 0xe8, 0x4e, 0x8b, 0x64, 0x14, 0x91, 0x97, 0xc4, 0xb8, 0xf8, 0x75, 0x4c, 0x93, + 0xb8, 0x58, 0x4f, 0x73, 0x9f, 0x8a, 0xde, 0xb9, 0x0d, 0xfe, 0x71, 0xa3, 0x27, 0x5d, 0x27, 0x2c, 0x01, 0x58, 0x8f, + 0x94, 0x64, 0xc0, 0xa5, 0x9a, 0x9e, 0xfc, 0x3a, 0x48, 0x09, 0xbc, 0x72, 0xd0, 0x39, 0xc4, 0xf1, 0x85, 0x12, 0xd1, + 0xe0, 0xdf, 0xe4, 0xc8, 0x23, 0xf0, 0xeb, 0x67, 0xcc, 0x30, 0xcd, 0x12, 0xd8, 0x63, 0xe5, 0x99, 0x88, 0xf9, 0xab, + 0x46, 0xd2, 0x48, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x05, 0xc2, 0x1e, 0x80, 0xa6, 0x00, 0xde, + 0x1b, 0x12, 0xf3, 0xe5, 0xa9, 0xa6, 0x24, 0xe5, 0x29, 0x3a, 0x9b, 0xb3, 0x60, 0xfa, 0x2c, 0x2c, 0xa0, 0x9b, 0x63, + 0xca, 0xc3, 0x4d, 0x2c, 0xf3, 0x32, 0xcc, 0x94, 0xcc, 0xa8, 0x25, 0x98, 0x08, 0x93, 0xe1, 0x75, 0x72, 0x01, 0xcb, + 0x7b, 0x9b, 0x66, 0xc6, 0x2d, 0xa3, 0x57, 0xae, 0x4f, 0xa0, 0x79, 0xdc, 0x93, 0x65, 0x91, 0xa6, 0x0c, 0x57, 0x38, + 0x00, 0xe9, 0xaf, 0x98, 0xc7, 0xc2, 0x29, 0x35, 0x2b, 0xb9, 0x71, 0xc3, 0xc5, 0x42, 0x6a, 0x5c, 0xdd, 0x95, 0x77, + 0x22, 0x04, 0x48, 0x65, 0x4b, 0x27, 0x83, 0x67, 0x40, 0xf1, 0x9e, 0x00, 0x02, 0x11, 0x8d, 0xc2, 0x67, 0x7e, 0x92, + 0xa3, 0x55, 0x4e, 0x10, 0x0b, 0x73, 0x55, 0x3b, 0x2f, 0xde, 0x2a, 0x44, 0x94, 0x0b, 0x8e, 0x36, 0x00, 0x5b, 0xb4, + 0x2f, 0x72, 0x9f, 0x41, 0xc0, 0xb7, 0x8f, 0x33, 0xc3, 0x5c, 0x9a, 0x76, 0x48, 0x95, 0xcf, 0xc6, 0xe1, 0xe7, 0xb2, + 0xc0, 0x33, 0x4e, 0x99, 0xd8, 0xfd, 0x67, 0xab, 0xba, 0x21, 0xea, 0xfc, 0x35, 0x75, 0xc0, 0xa9, 0xb6, 0xd9, 0xd9, + 0x8d, 0x41, 0x97, 0xc5, 0xc9, 0x01, 0x93, 0xb2, 0xb3, 0x75, 0xb0, 0xa2, 0x1c, 0xff, 0x72, 0xf2, 0x03, 0x19, 0x0b, + 0x34, 0x5e, 0x15, 0x44, 0x45, 0x46, 0xa6, 0x03, 0x41, 0xbc, 0x34, 0x7c, 0x2e, 0x06, 0x68, 0x91, 0x79, 0x55, 0x52, + 0xa0, 0xd0, 0xac, 0x46, 0x94, 0x37, 0xd0, 0x20, 0x9b, 0xbb, 0x9a, 0x6a, 0x14, 0x1c, 0x21, 0x8f, 0x5a, 0x6c, 0x4c, + 0x8f, 0xc5, 0x52, 0x4c, 0xcb, 0xb4, 0x39, 0x45, 0x12, 0x81, 0xc5, 0x01, 0x71, 0xfd, 0x59, 0xa9, 0xb1, 0x41, 0x94, + 0x79, 0xde, 0x8c, 0x30, 0xe8, 0x6e, 0xe8, 0x49, 0x36, 0x31, 0xd6, 0x4a, 0x10, 0x39, 0x75, 0xd0, 0xd8, 0x8f, 0x5d, + 0x9f, 0xc8, 0xdb, 0x5d, 0x53, 0x4c, 0x75, 0xb9, 0x3f, 0x51, 0x4c, 0x0c, 0x2d, 0xed, 0xfa, 0x79, 0x06, 0x51, 0x3f, + 0x3d, 0x78, 0x9a, 0x72, 0xb6, 0xf6, 0x18, 0x1e, 0xaa, 0xce, 0x25, 0x79, 0xbf, 0xd4, 0x0d, 0x01, 0xf9, 0xb5, 0xc0, + 0xea, 0x91, 0x93, 0x88, 0x22, 0x10, 0xf6, 0xb3, 0xfe, 0x96, 0x30, 0xfa, 0x9b, 0x81, 0x25, 0xbb, 0x1e, 0x6c, 0x4b, + 0x5d, 0x62, 0x2c, 0x6b, 0x65, 0xcd, 0x29, 0x30, 0x5c, 0xba, 0x54, 0x4e, 0x1e, 0x48, 0x3c, 0x54, 0x0e, 0x16, 0xd3, + 0xe7, 0xe9, 0xc2, 0x01, 0x23, 0x85, 0xec, 0xfd, 0x34, 0xc8, 0x8b, 0xd3, 0x8b, 0x24, 0xb5, 0x18, 0x31, 0x76, 0xa9, + 0xb6, 0xb1, 0xf4, 0x08, 0xab, 0xb6, 0x36, 0xf0, 0xfc, 0xc4, 0x76, 0xbb, 0xdd, 0xb0, 0x53, 0x41, 0x56, 0x52, 0x27, + 0x72, 0x33, 0x8b, 0xce, 0x8f, 0x26, 0x91, 0xca, 0x13, 0x46, 0x01, 0x79, 0x39, 0x63, 0x5b, 0x20, 0x8b, 0x6e, 0x8a, + 0x5e, 0x18, 0xe3, 0xd6, 0xb3, 0x5c, 0x7d, 0xeb, 0x37, 0x38, 0x14, 0x92, 0x32, 0x35, 0xcd, 0x94, 0x7b, 0x9d, 0xcd, + 0x77, 0x55, 0x44, 0x8b, 0x72, 0xd6, 0x5c, 0x9b, 0x5f, 0x24, 0xab, 0xbd, 0x14, 0xd9, 0xd2, 0xe9, 0x30, 0x7b, 0x97, + 0x8a, 0xd4, 0x92, 0x04, 0xaa, 0x1d, 0xc7, 0x66, 0x1c, 0xe7, 0x18, 0xf4, 0x56, 0x30, 0xb3, 0x86, 0x97, 0x80, 0xec, + 0x22, 0x85, 0x45, 0x56, 0x5a, 0xbc, 0xd1, 0x2d, 0x25, 0xef, 0x07, 0x89, 0xca, 0xd2, 0xc3, 0x30, 0x93, 0xbe, 0x14, + 0xf6, 0x80, 0x14, 0x8f, 0x50, 0x45, 0x98, 0xbb, 0xdf, 0x45, 0x50, 0xa0, 0x3a, 0xc3, 0x13, 0x98, 0xf6, 0x7c, 0x94, + 0x8e, 0x0b, 0x98, 0x9f, 0xcd, 0x44, 0xbb, 0x7a, 0xb5, 0x06, 0x2c, 0xbc, 0xfa, 0x90, 0xe2, 0x3a, 0xa5, 0xb7, 0xf2, + 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x18, 0x23, 0x49, 0x9a, 0x0f, 0xe7, 0xde, + 0xa0, 0x9b, 0x21, 0x28, 0x11, 0x53, 0xdc, 0x10, 0x62, 0x31, 0xcc, 0x58, 0x03, 0xca, 0xdd, 0xa2, 0x99, 0x93, 0xac, + 0xb9, 0x93, 0x49, 0xce, 0x7c, 0xf7, 0x95, 0x5e, 0xa5, 0x94, 0x10, 0x4d, 0xc7, 0x57, 0x39, 0x59, 0x3e, 0x46, 0xc3, + 0x2c, 0xae, 0x1c, 0x13, 0xb4, 0x4e, 0xe2, 0x84, 0xa2, 0x70, 0x48, 0x50, 0x5b, 0x61, 0xba, 0x53, 0x23, 0x9c, 0x0a, + 0x7a, 0x3f, 0xe9, 0xe6, 0x0e, 0xba, 0x13, 0xdb, 0x50, 0xd1, 0x9a, 0x86, 0x0a, 0x62, 0xdb, 0xbf, 0xf7, 0x33, 0x3a, + 0x74, 0xfc, 0x56, 0x34, 0xa6, 0x42, 0xa0, 0x66, 0x0e, 0x97, 0xe7, 0xbe, 0x98, 0x14, 0xe2, 0x4a, 0x5a, 0x9e, 0x08, + 0x92, 0xb4, 0x8f, 0x8d, 0x79, 0xb1, 0xb7, 0x83, 0xc2, 0x34, 0xac, 0xcb, 0x06, 0x44, 0xad, 0x17, 0x2a, 0xf3, 0xeb, + 0xb6, 0x8c, 0x3b, 0x4d, 0x18, 0xaf, 0x9b, 0x81, 0x98, 0xd7, 0xa0, 0x8d, 0x18, 0x8c, 0x55, 0x3b, 0x0e, 0x40, 0x39, + 0x3a, 0x2d, 0x1b, 0xeb, 0x4b, 0xab, 0x46, 0x6f, 0x68, 0x0c, 0x6c, 0xd7, 0x62, 0x91, 0x04, 0xa4, 0x30, 0x66, 0xdd, + 0x8d, 0x49, 0xa7, 0x0a, 0xea, 0x81, 0xec, 0x59, 0x9f, 0x75, 0x3c, 0x4b, 0x4c, 0xf8, 0x25, 0x03, 0x47, 0xf3, 0xe9, + 0xa4, 0x97, 0xae, 0x89, 0x8e, 0x68, 0x6d, 0x21, 0xfe, 0xd4, 0xe0, 0xd6, 0xe2, 0xa5, 0x0e, 0x7c, 0x05, 0xa0, 0x16, + 0x99, 0x0a, 0x21, 0x51, 0x25, 0x15, 0x57, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x2a, 0xac, 0x7c, 0x72, 0xef, 0x7a, 0x07, + 0x7f, 0xb6, 0x07, 0x4b, 0xeb, 0x0e, 0xf3, 0xc1, 0xc9, 0x5f, 0x45, 0x48, 0x11, 0xf6, 0xcc, 0xd0, 0xc1, 0xc6, 0x3c, + 0x73, 0xe4, 0xe3, 0xb5, 0x1d, 0xf1, 0xad, 0x0b, 0x6f, 0x98, 0xe4, 0xee, 0x3d, 0x72, 0x19, 0xda, 0x52, 0x40, 0xd4, + 0x6d, 0x6e, 0xfb, 0x83, 0x74, 0xfc, 0x49, 0x4a, 0xf1, 0xef, 0x5d, 0x05, 0x51, 0xbb, 0x68, 0x21, 0x79, 0xa7, 0xe7, + 0xc0, 0x1a, 0x8c, 0x26, 0x8d, 0x11, 0x4c, 0xef, 0x01, 0x97, 0x8a, 0xe2, 0xfc, 0xd1, 0x49, 0x98, 0x70, 0xe2, 0x19, + 0xe0, 0x2f, 0x8d, 0x49, 0xd8, 0x16, 0x01, 0x77, 0xbb, 0x18, 0xff, 0xa2, 0xdd, 0x84, 0x41, 0xde, 0x5d, 0xdf, 0x91, + 0x7e, 0xc4, 0x3d, 0x6c, 0x2e, 0xfb, 0x5b, 0x5e, 0x8a, 0x56, 0xa2, 0x8a, 0x10, 0xa6, 0x46, 0x42, 0x43, 0x9d, 0x23, + 0x81, 0x38, 0xa6, 0x89, 0x35, 0xcc, 0xf6, 0x93, 0xf5, 0x61, 0x97, 0x0a, 0xa1, 0x50, 0x04, 0xa2, 0x33, 0x84, 0x1b, + 0x75, 0x9e, 0x30, 0xc0, 0x3b, 0x04, 0xa0, 0x25, 0xe8, 0xc7, 0x10, 0x9f, 0x5b, 0x27, 0x84, 0xe6, 0x62, 0x9e, 0x3e, + 0x66, 0x0a, 0x4a, 0x52, 0x7d, 0x2d, 0x6f, 0xb3, 0xe6, 0x05, 0x67, 0x2a, 0x2e, 0xa0, 0x68, 0x2b, 0x9e, 0xfa, 0xef, + 0x98, 0x8a, 0x3e, 0x8a, 0x4e, 0x6d, 0xcc, 0x69, 0x9e, 0x30, 0xe7, 0x88, 0x7e, 0xa0, 0xee, 0xc6, 0xf5, 0x6e, 0xc3, + 0x9d, 0xca, 0x12, 0xca, 0x32, 0xf4, 0xba, 0x65, 0xba, 0x94, 0xe4, 0x70, 0x8e, 0xf3, 0xfc, 0x57, 0x0c, 0x71, 0xff, + 0x35, 0xc7, 0xa7, 0xf7, 0x59, 0xda, 0x65, 0x7e, 0xf4, 0xe0, 0xa5, 0x05, 0x66, 0x76, 0xc6, 0x6e, 0x1e, 0xf6, 0x58, + 0x47, 0x02, 0x3b, 0xe2, 0x18, 0xea, 0x1a, 0x67, 0xbc, 0xde, 0x8a, 0x78, 0xa0, 0xb6, 0x1e, 0x6c, 0xbc, 0xa7, 0x34, + 0x4c, 0xb7, 0xa4, 0x8b, 0xac, 0x6b, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0xbb, 0xa7, 0xc7, 0x93, 0x3a, 0x69, 0x53, 0x54, + 0x2c, 0x81, 0xce, 0x8d, 0x43, 0xff, 0xe4, 0x2c, 0xcc, 0x63, 0xe8, 0x98, 0xc9, 0x38, 0x5b, 0x67, 0x8c, 0xe7, 0xf6, + 0x33, 0x89, 0xb4, 0x93, 0x81, 0xdf, 0x29, 0x92, 0x9f, 0x7f, 0x58, 0x80, 0x46, 0x14, 0x82, 0xda, 0xed, 0x07, 0x0a, + 0xc5, 0xb1, 0xef, 0x7f, 0x84, 0xb5, 0x7d, 0x8f, 0xd8, 0x85, 0x5d, 0x2c, 0x01, 0xc4, 0x6e, 0x6c, 0xec, 0xff, 0x75, + 0x77, 0xab, 0x91, 0x0d, 0xab, 0x0f, 0x24, 0xd4, 0x57, 0x7b, 0xe6, 0xd9, 0x35, 0xcf, 0x8d, 0x08, 0xce, 0x44, 0x47, + 0xa0, 0x5e, 0xb5, 0xb9, 0xfe, 0x9b, 0xa4, 0xbb, 0x88, 0x22, 0x08, 0x56, 0xd6, 0x20, 0x6b, 0x36, 0xb2, 0xa0, 0x54, + 0xdc, 0x91, 0x1b, 0x7b, 0xbc, 0xc7, 0xf7, 0x76, 0x12, 0x4d, 0x19, 0x25, 0xd7, 0xaa, 0x29, 0x27, 0x0e, 0x63, 0x77, + 0x6f, 0x3c, 0x6b, 0x35, 0x5e, 0x28, 0xfe, 0xa6, 0x06, 0x61, 0xc5, 0x8d, 0xe3, 0x66, 0x83, 0x70, 0xff, 0x6c, 0x51, + 0xa7, 0x6b, 0x91, 0xf1, 0xbc, 0x5a, 0xaf, 0x7d, 0xb6, 0x1b, 0xa9, 0x26, 0xb5, 0x27, 0x34, 0x37, 0x62, 0x9b, 0x77, + 0xdc, 0x6d, 0xc0, 0xe7, 0xc0, 0xc5, 0xd4, 0x91, 0x78, 0xef, 0x51, 0x2f, 0x59, 0xb3, 0xd7, 0x5b, 0x13, 0x1e, 0x1c, + 0x7a, 0x65, 0xb7, 0x7a, 0x22, 0x3e, 0x9f, 0x56, 0xff, 0x74, 0x7f, 0x27, 0x3f, 0xbb, 0x97, 0xb7, 0x6a, 0xca, 0x51, + 0xfa, 0xd4, 0xc4, 0x26, 0x7b, 0x3d, 0x6b, 0x1c, 0xde, 0x6a, 0xdc, 0xee, 0xa4, 0x1b, 0x4d, 0xfb, 0x2f, 0x97, 0x32, + 0x5b, 0xd0, 0x2c, 0x0f, 0x7e, 0x0e, 0x16, 0xdf, 0xb3, 0xd0, 0x7b, 0x15, 0x31, 0xa7, 0x6c, 0x70, 0x48, 0x55, 0x33, + 0xfd, 0x30, 0xde, 0x89, 0x26, 0x6e, 0x3d, 0xda, 0x25, 0xee, 0xa2, 0x46, 0x9c, 0xe4, 0x01, 0xd6, 0x5c, 0xef, 0x0a, + 0xa6, 0xd4, 0x2e, 0xff, 0x04, 0xd2, 0xe2, 0xa5, 0x09, 0x9b, 0xb4, 0xa9, 0xb5, 0x4d, 0x1b, 0xae, 0x02, 0xcb, 0x3f, + 0x16, 0xdb, 0x7c, 0x57, 0xf5, 0x9b, 0x6e, 0xae, 0xf2, 0xf5, 0xcf, 0xe0, 0xc7, 0x6a, 0xaf, 0xe5, 0xa7, 0xff, 0xe1, + 0xfb, 0xff, 0x6a, 0xdc, 0x09, 0x66, 0xbb, 0x39, 0x0b, 0xbe, 0x6a, 0x70, 0x91, 0x65, 0xc3, 0xe7, 0x49, 0xf9, 0xff, + 0xea, 0x7a, 0xf7, 0x8f, 0xab, 0x7f, 0xbf, 0x68, 0x06, 0xf3, 0x11, 0x57, 0x9e, 0x49, 0x5d, 0x9c, 0xfd, 0x37, 0xc4, + 0xd5, 0xd3, 0x7b, 0x1f, 0xb1, 0xc6, 0x15, 0xfb, 0xcd, 0x6e, 0xb2, 0x6c, 0x16, 0x55, 0x96, 0xf0, 0xd4, 0xab, 0x9a, + 0x5d, 0x41, 0x90, 0xcf, 0x7b, 0x9d, 0xcd, 0x47, 0x87, 0x8f, 0x35, 0xa6, 0x7d, 0xa6, 0xdc, 0xfb, 0xfc, 0xc2, 0xf3, + 0x8b, 0x59, 0x39, 0x9e, 0xf7, 0xbc, 0xf4, 0x6a, 0xae, 0xec, 0xc7, 0x9a, 0xe4, 0x4c, 0x67, 0x70, 0xfe, 0x59, 0x39, + 0xbf, 0xf8, 0x7c, 0x7f, 0x76, 0x5f, 0xbe, 0xcc, 0x50, 0xc3, 0x31, 0xcf, 0xac, 0xf9, 0x88, 0x77, 0xa2, 0x56, 0x67, + 0xf1, 0xad, 0xd9, 0xcd, 0xf1, 0x64, 0xc5, 0x11, 0xae, 0xd0, 0x63, 0x3b, 0xac, 0xfc, 0x5d, 0x4f, 0x0d, 0x71, 0xc1, + 0xd0, 0x04, 0x12, 0x0f, 0xfd, 0xdf, 0xc1, 0xd0, 0x0f, 0xbd, 0x97, 0x9f, 0x4d, 0x1a, 0x0e, 0x80, 0xb0, 0xab, 0x96, + 0xc2, 0x6b, 0xa5, 0x3a, 0x62, 0x1b, 0x75, 0x54, 0xf8, 0x40, 0x45, 0x3b, 0x47, 0xdf, 0x5b, 0xde, 0xeb, 0x77, 0xa1, + 0xf4, 0xe0, 0xfa, 0xe1, 0xf1, 0x6b, 0xb1, 0x2e, 0x03, 0xc8, 0x16, 0xc1, 0xe9, 0x86, 0x77, 0xdb, 0xdb, 0x86, 0xe1, + 0x14, 0xaa, 0x3a, 0x51, 0x59, 0x53, 0xeb, 0xcc, 0xbe, 0x8f, 0x16, 0xdd, 0x00, 0x3c, 0x1f, 0xef, 0x13, 0x42, 0xf6, + 0x2e, 0xd2, 0x73, 0xd2, 0x09, 0x23, 0x10, 0xd8, 0x22, 0x0a, 0x6c, 0x1a, 0xe4, 0x7d, 0x7c, 0x87, 0x6e, 0x48, 0xcb, + 0xcf, 0x68, 0xae, 0x3e, 0x77, 0x31, 0xa5, 0xec, 0xe1, 0x6a, 0x6e, 0xb5, 0x4f, 0x01, 0x24, 0xb1, 0x4d, 0x08, 0x58, + 0xfe, 0x93, 0xc7, 0x4d, 0xc3, 0xd6, 0x9b, 0x74, 0xe9, 0x85, 0xd4, 0x9d, 0x9a, 0x34, 0x65, 0x84, 0x91, 0xe9, 0x85, + 0xe7, 0x15, 0x9d, 0x70, 0x97, 0x63, 0xa2, 0x57, 0x8c, 0x8c, 0x59, 0x71, 0xa7, 0xde, 0xb6, 0xbc, 0xfe, 0x5c, 0x07, + 0x41, 0x48, 0x37, 0x36, 0xa4, 0xcb, 0xcc, 0xdd, 0x2b, 0xb8, 0x99, 0x11, 0xb0, 0x79, 0x09, 0x75, 0xc6, 0xef, 0x99, + 0x24, 0xd1, 0x9d, 0x35, 0x4d, 0x9c, 0xf1, 0xb7, 0xd5, 0x6c, 0xa1, 0x8a, 0xc4, 0x0b, 0x73, 0x03, 0x12, 0x84, 0xfa, + 0x86, 0x5a, 0x61, 0xd5, 0x37, 0x98, 0xb4, 0x1f, 0x38, 0x39, 0xcf, 0x34, 0x83, 0x4e, 0xe3, 0x7d, 0x1d, 0x33, 0x26, + 0xba, 0x9a, 0xa2, 0x50, 0x18, 0x6d, 0xe7, 0xcf, 0xe2, 0x66, 0x96, 0xf5, 0x60, 0x02, 0xf0, 0x36, 0x0f, 0xa0, 0x9f, + 0xd7, 0x0a, 0x66, 0xf2, 0x06, 0x3f, 0xfc, 0x12, 0x06, 0x64, 0x7c, 0xe8, 0x41, 0xce, 0xe6, 0x27, 0x05, 0xfd, 0xc7, + 0x20, 0x5e, 0x77, 0x96, 0xb3, 0x5b, 0x42, 0x6b, 0x29, 0xd6, 0x8a, 0x71, 0x96, 0x91, 0xeb, 0xd4, 0x6f, 0xea, 0x2a, + 0x99, 0xaf, 0xed, 0xea, 0x72, 0xf1, 0x6d, 0x4f, 0xee, 0x30, 0x38, 0x05, 0xbc, 0xa0, 0xa1, 0x20, 0x66, 0x2a, 0x3f, + 0xaf, 0xce, 0x6e, 0x28, 0xf5, 0x41, 0x32, 0x7d, 0xae, 0xf0, 0xaa, 0x1a, 0xff, 0x85, 0x45, 0x5f, 0x6a, 0x25, 0xf4, + 0x17, 0x60, 0xf8, 0xd0, 0xb6, 0xcd, 0x84, 0x67, 0x67, 0x0b, 0xf7, 0x34, 0xf9, 0x54, 0x73, 0xb7, 0xda, 0x88, 0x39, + 0xcf, 0x01, 0x81, 0xb4, 0x50, 0x6a, 0xfc, 0x89, 0xd3, 0x12, 0x24, 0xb9, 0xf1, 0xb3, 0x85, 0x32, 0x3a, 0xba, 0xe2, + 0x14, 0xa7, 0x8b, 0xd7, 0x82, 0x55, 0xd4, 0xfe, 0xb6, 0xa9, 0xe3, 0x8b, 0xef, 0xd2, 0xb1, 0x6d, 0xb9, 0x7f, 0x37, + 0x7d, 0xdb, 0xa0, 0x38, 0x13, 0x36, 0x06, 0x7f, 0xe9, 0xbe, 0x6d, 0x0e, 0x34, 0x7c, 0x88, 0x3e, 0x77, 0xaf, 0xfe, + 0xb8, 0x26, 0x5d, 0x81, 0x6e, 0x89, 0xa7, 0x67, 0x3a, 0x28, 0x9a, 0x87, 0x92, 0x8b, 0x17, 0x25, 0xb0, 0x56, 0x30, + 0x9a, 0xce, 0x78, 0x11, 0x9c, 0x14, 0xda, 0xe7, 0x0d, 0x93, 0x9f, 0x16, 0x5c, 0xfb, 0x51, 0x49, 0xef, 0x14, 0x6a, + 0x8c, 0xef, 0xaf, 0x9b, 0x6c, 0xbd, 0x6b, 0x5e, 0x4b, 0xaa, 0x28, 0x8c, 0x7e, 0x87, 0x01, 0xf2, 0xd5, 0x97, 0x25, + 0x32, 0xfa, 0xf6, 0x4e, 0xdd, 0x6a, 0xbe, 0x77, 0x39, 0xd3, 0x19, 0x81, 0x3f, 0xdf, 0x8c, 0x59, 0xd3, 0x74, 0x33, + 0x46, 0x36, 0x02, 0x73, 0x17, 0x10, 0xa5, 0x89, 0x34, 0x28, 0x2b, 0xc8, 0x77, 0x57, 0xc3, 0x56, 0xa9, 0xcd, 0xde, + 0x9f, 0xfd, 0xdf, 0x4f, 0x0b, 0xee, 0x91, 0xf4, 0xe2, 0x8f, 0x1e, 0xaf, 0x63, 0x21, 0xcd, 0xbd, 0x50, 0xe3, 0x67, + 0xed, 0x71, 0xca, 0x6d, 0x3c, 0x40, 0xb3, 0x86, 0x0e, 0x0d, 0xdb, 0x87, 0x74, 0x5c, 0x1c, 0x5f, 0x63, 0xe8, 0xfb, + 0x06, 0x52, 0xc2, 0xd4, 0xe4, 0x3d, 0xa5, 0x15, 0x75, 0x60, 0x04, 0x15, 0xe5, 0x85, 0x72, 0x62, 0xd6, 0x56, 0xf4, + 0x6e, 0xc3, 0xc4, 0xd9, 0xa0, 0xfe, 0x66, 0xcb, 0xcb, 0x1e, 0x7b, 0x1f, 0xf0, 0xf5, 0x4c, 0x01, 0xc7, 0x38, 0xa1, + 0x46, 0xb0, 0x1d, 0xa4, 0xc8, 0x22, 0xf0, 0x09, 0x33, 0x6a, 0x08, 0x65, 0xcd, 0xd4, 0x96, 0xf2, 0x24, 0x48, 0xaf, + 0x2b, 0x2b, 0x5d, 0xd8, 0xe5, 0xdb, 0x2a, 0xba, 0x39, 0xbd, 0x83, 0x3d, 0xf9, 0x5e, 0xf3, 0xde, 0x7a, 0xa9, 0xd4, + 0x6a, 0xda, 0x90, 0xb0, 0x90, 0xb5, 0xc0, 0xae, 0x5b, 0xe7, 0x47, 0xd7, 0x31, 0x66, 0xf1, 0x08, 0x3e, 0x23, 0xd8, + 0x0b, 0x72, 0x53, 0xe7, 0xd6, 0xce, 0x60, 0x61, 0x42, 0xbe, 0xcf, 0xcf, 0x12, 0xb0, 0xb4, 0x63, 0xd3, 0x74, 0x70, + 0x3e, 0xa4, 0xef, 0xa1, 0x77, 0x4b, 0x01, 0x59, 0x38, 0x35, 0x7b, 0x57, 0x8b, 0x02, 0x4f, 0x1c, 0x92, 0x1a, 0xd0, + 0xf7, 0xec, 0x75, 0xfc, 0x46, 0x9f, 0x58, 0x24, 0x52, 0xd3, 0xdb, 0xf8, 0x9b, 0x67, 0xdf, 0xe8, 0xab, 0x53, 0xcf, + 0x84, 0xaf, 0x3e, 0x94, 0x5a, 0xcd, 0x86, 0x06, 0xec, 0x30, 0xd3, 0xc6, 0xb9, 0x0e, 0x4a, 0x7d, 0x33, 0x61, 0x27, + 0xe4, 0x65, 0x71, 0xe3, 0x28, 0x0d, 0xc1, 0x40, 0x7a, 0x11, 0x8f, 0xa2, 0xfc, 0xbe, 0xea, 0xc9, 0xcc, 0xfa, 0x08, + 0x4f, 0x2f, 0x1f, 0xfe, 0xf1, 0xb5, 0x2a, 0xbe, 0xbc, 0xb7, 0x1b, 0xf9, 0xc9, 0x4e, 0x41, 0xe2, 0xd0, 0x54, 0xec, + 0x01, 0x4d, 0x0e, 0x1c, 0x02, 0x71, 0x43, 0x79, 0xec, 0xc3, 0xfe, 0x5c, 0xf3, 0x0d, 0x01, 0x35, 0x56, 0x12, 0x54, + 0x4b, 0x67, 0xfe, 0x72, 0x25, 0x17, 0x2e, 0xde, 0x5d, 0x3c, 0xb7, 0x28, 0x7b, 0xff, 0xf3, 0x96, 0xfe, 0xd1, 0x7e, + 0x6f, 0x28, 0xb7, 0x97, 0x33, 0xff, 0xef, 0x35, 0x85, 0x0b, 0x81, 0x07, 0x24, 0xa9, 0x85, 0xe4, 0x4a, 0x87, 0x8f, + 0xdf, 0x1c, 0xea, 0xbc, 0xc7, 0x74, 0x5f, 0x61, 0x56, 0x17, 0x44, 0xc1, 0xc7, 0x07, 0xa8, 0x6c, 0x03, 0xc5, 0x08, + 0xe1, 0x02, 0x46, 0x1f, 0xee, 0xeb, 0x46, 0x2d, 0x02, 0x69, 0x57, 0xae, 0xfe, 0x78, 0x61, 0xe0, 0x95, 0xc3, 0x6f, + 0x2d, 0xb9, 0x2f, 0x25, 0xbe, 0xd0, 0xd8, 0x9e, 0x5c, 0x4b, 0xe3, 0x89, 0x8c, 0x8a, 0x50, 0x55, 0x91, 0x7c, 0xce, + 0xbd, 0x5a, 0x7d, 0x31, 0x8c, 0x7c, 0x26, 0x30, 0xd7, 0x9b, 0x36, 0x76, 0x9c, 0x54, 0x97, 0xfc, 0xa7, 0x1e, 0x60, + 0x30, 0xd8, 0x97, 0x6d, 0xd3, 0xf4, 0x7e, 0xe7, 0xa4, 0xe1, 0x09, 0x92, 0xc0, 0x1a, 0x0c, 0x5c, 0x95, 0x24, 0x48, + 0x6f, 0xcc, 0x8a, 0x2e, 0x4d, 0xc9, 0x7b, 0xea, 0x29, 0xd9, 0x88, 0xe4, 0x21, 0xa0, 0x23, 0xc1, 0x45, 0xff, 0x51, + 0x6b, 0x23, 0x5c, 0x6b, 0xf9, 0x39, 0x9f, 0x6c, 0xe8, 0x74, 0xb3, 0x2b, 0xb2, 0xa3, 0x0f, 0xa3, 0x3c, 0x9c, 0x3b, + 0x19, 0xe6, 0x61, 0x24, 0xb0, 0x92, 0xb9, 0x79, 0xdc, 0x00, 0xf1, 0x4d, 0x96, 0x64, 0xb7, 0xe4, 0x7f, 0xfc, 0x29, + 0xaf, 0x23, 0xa4, 0x64, 0x5b, 0xdf, 0x55, 0x34, 0x3a, 0x85, 0x93, 0x5c, 0xa7, 0x65, 0x79, 0x21, 0x9c, 0x50, 0x20, + 0x6c, 0x69, 0xd4, 0x48, 0x7e, 0xff, 0xfe, 0xc7, 0x10, 0x2c, 0xfa, 0xf8, 0xa6, 0x99, 0x75, 0x5b, 0x81, 0x31, 0x82, + 0x46, 0x9d, 0x99, 0xdd, 0xe8, 0xf4, 0x26, 0x23, 0x11, 0x28, 0x49, 0x63, 0x8a, 0xb4, 0x87, 0xc3, 0xdd, 0xe6, 0xab, + 0x3f, 0xb2, 0x1d, 0x4b, 0xaa, 0xb6, 0x59, 0xa8, 0x2d, 0x40, 0x80, 0x51, 0xbf, 0x37, 0x10, 0x4d, 0x34, 0x05, 0x05, + 0x2b, 0x6f, 0xe8, 0xdc, 0x8e, 0x6e, 0xcd, 0x6e, 0x41, 0xfb, 0x55, 0xfd, 0x19, 0xa1, 0x83, 0xdb, 0x4a, 0x7a, 0x4e, + 0x4a, 0x55, 0xa4, 0x2e, 0x38, 0xa7, 0x20, 0xb1, 0xb5, 0x0d, 0xb4, 0x7d, 0x6a, 0x4c, 0xe4, 0xfd, 0x45, 0xc5, 0x55, + 0x44, 0x00, 0x02, 0x84, 0x97, 0xe5, 0x5d, 0xc2, 0x27, 0xa3, 0x04, 0x00, 0xd3, 0xe3, 0xd2, 0x4b, 0xc6, 0x52, 0xd1, + 0xf0, 0xb0, 0x55, 0x50, 0x6d, 0xbb, 0x40, 0xe5, 0x80, 0x0b, 0xac, 0xac, 0xc3, 0x3c, 0x13, 0x52, 0x35, 0x29, 0x2e, + 0xba, 0x99, 0x5d, 0xa4, 0x3c, 0xdd, 0xa7, 0xa9, 0x24, 0x6c, 0x5a, 0x7f, 0x67, 0x7c, 0x19, 0x87, 0x68, 0x96, 0xbe, + 0x38, 0x6e, 0x3c, 0x5a, 0xde, 0x8e, 0xa6, 0x03, 0xd3, 0xda, 0x79, 0x12, 0x01, 0xca, 0x4e, 0x95, 0x70, 0xf5, 0x3c, + 0x04, 0x45, 0xa8, 0xf1, 0x43, 0xb7, 0x41, 0xc1, 0x6f, 0xe4, 0xe7, 0xa7, 0x86, 0x02, 0x84, 0xf1, 0xd2, 0x01, 0x0f, + 0xdd, 0xe4, 0xc5, 0x96, 0xb2, 0x73, 0xc0, 0xd8, 0x1b, 0xd1, 0x0b, 0x48, 0x6b, 0x62, 0xea, 0x4e, 0x72, 0x14, 0x5d, + 0x9c, 0x53, 0x5e, 0xc5, 0x2d, 0xd3, 0x65, 0xe9, 0x63, 0xea, 0x9d, 0x08, 0x9f, 0x13, 0x2b, 0x84, 0xff, 0x1d, 0x91, + 0xc3, 0xac, 0x94, 0x69, 0x81, 0x11, 0x6b, 0x89, 0x17, 0x38, 0xdf, 0x09, 0xd1, 0x4c, 0xd5, 0x4c, 0x57, 0x84, 0x79, + 0xaa, 0xaf, 0xf5, 0x9e, 0x3c, 0xc9, 0x1e, 0xa8, 0xf2, 0x61, 0xaf, 0xbb, 0x24, 0x98, 0xd7, 0xb2, 0xa9, 0xb7, 0x61, + 0xa2, 0xb0, 0x0f, 0x16, 0xf2, 0xb8, 0x6a, 0x08, 0x38, 0x3d, 0xf5, 0xab, 0x6f, 0xf5, 0x61, 0xdd, 0xb4, 0x2b, 0x04, + 0x9f, 0x93, 0x44, 0x84, 0x9f, 0xdb, 0x25, 0xce, 0xca, 0xab, 0xeb, 0xec, 0xb3, 0x58, 0xad, 0x41, 0xe6, 0xe5, 0x29, + 0xd1, 0xb6, 0xff, 0xd9, 0x41, 0x79, 0xde, 0x4d, 0x12, 0x3c, 0x4c, 0x47, 0x14, 0x33, 0x71, 0x8e, 0xa4, 0x21, 0x13, + 0xcf, 0xf9, 0xe2, 0x8b, 0x1a, 0xbd, 0x9f, 0x13, 0x4a, 0xc7, 0xa4, 0xf9, 0x8d, 0x0a, 0xa1, 0x0b, 0x09, 0x1d, 0x3f, + 0x74, 0xf9, 0xba, 0xb0, 0x76, 0xf3, 0x89, 0x88, 0xf5, 0x1f, 0xdc, 0x88, 0xa2, 0xd2, 0x79, 0x2c, 0x96, 0x40, 0x32, + 0xc6, 0x4f, 0xf4, 0x1b, 0x33, 0x4f, 0xba, 0x7a, 0xf8, 0x0c, 0x1b, 0x0d, 0xc7, 0x41, 0x9c, 0x03, 0x9e, 0xbf, 0x0c, + 0x7b, 0x5b, 0x1f, 0x15, 0xbf, 0x7f, 0x7d, 0x40, 0x54, 0x6b, 0xb8, 0xa2, 0xf4, 0x67, 0x1c, 0xe2, 0x12, 0xc9, 0x40, + 0x8b, 0x19, 0x7e, 0x21, 0xd2, 0xea, 0x7f, 0x45, 0xce, 0x3d, 0x0e, 0xec, 0x84, 0xfc, 0x17, 0xb7, 0xbd, 0x07, 0x5d, + 0x15, 0x42, 0xde, 0x8e, 0xa8, 0x91, 0x22, 0x0e, 0xef, 0xee, 0xcd, 0xd7, 0xd6, 0x22, 0xe7, 0xc0, 0xac, 0xdd, 0x4d, + 0x99, 0x85, 0xbb, 0x48, 0x6d, 0x31, 0x6d, 0x9a, 0x6d, 0x82, 0x97, 0x61, 0x27, 0x9d, 0x2c, 0x3e, 0xb5, 0x81, 0x50, + 0x55, 0x04, 0x48, 0x25, 0x0b, 0xfd, 0x0b, 0x94, 0xae, 0x5a, 0x2c, 0x43, 0x4b, 0x25, 0xe7, 0xba, 0x12, 0x4b, 0x3f, + 0xa1, 0xc0, 0x20, 0xfd, 0xe2, 0x56, 0x69, 0x3a, 0x2b, 0xa4, 0x88, 0x44, 0x8f, 0xd7, 0x96, 0xdd, 0x5d, 0xa8, 0x3c, + 0x92, 0xee, 0x33, 0x39, 0xc0, 0xf5, 0x4e, 0xaa, 0x8e, 0x95, 0x04, 0xed, 0x40, 0xf7, 0x00, 0xa5, 0x7e, 0x6a, 0x3d, + 0x44, 0x5a, 0x21, 0xf0, 0x12, 0x6e, 0xcc, 0x90, 0x68, 0x1f, 0xa8, 0x87, 0xc4, 0x04, 0xa0, 0x29, 0x38, 0xc1, 0x96, + 0x42, 0xdb, 0xb9, 0x91, 0x5c, 0xa1, 0x80, 0x95, 0xb1, 0x46, 0x35, 0x66, 0x1e, 0x5a, 0x61, 0x22, 0x8e, 0xb3, 0xcd, + 0xc8, 0x43, 0x1c, 0xa9, 0x43, 0xb4, 0xfd, 0x42, 0xe2, 0xa0, 0xc5, 0x99, 0x33, 0x8d, 0x5c, 0x21, 0x1c, 0x9f, 0x82, + 0x34, 0x8c, 0x60, 0xc3, 0xf5, 0x51, 0x6d, 0xac, 0x32, 0x21, 0x72, 0xab, 0x6e, 0x24, 0xed, 0xd7, 0xf1, 0x3b, 0x97, + 0x58, 0xc9, 0xb2, 0xe2, 0x9b, 0xa6, 0xd4, 0x33, 0xe5, 0xd5, 0x67, 0x56, 0x26, 0xbd, 0xdc, 0x47, 0x79, 0xc4, 0x5b, + 0xb0, 0xb8, 0x29, 0xf9, 0x21, 0xa6, 0xa0, 0x06, 0xf0, 0x68, 0x5c, 0x3b, 0x5c, 0x41, 0xb1, 0x18, 0x18, 0x69, 0x3a, + 0xad, 0x1c, 0xf3, 0xa5, 0x9a, 0x0d, 0x0c, 0xf3, 0x18, 0x4f, 0x2c, 0x74, 0x62, 0x7f, 0xcd, 0xf3, 0xb9, 0x45, 0x23, + 0x4f, 0xd3, 0x06, 0x59, 0x7e, 0x9b, 0xd6, 0x6b, 0x95, 0xe3, 0xf1, 0xb6, 0x02, 0x88, 0xdf, 0x41, 0x59, 0x50, 0x0c, + 0x15, 0x4d, 0x8a, 0x19, 0x0c, 0x97, 0xc6, 0x0b, 0x32, 0x01, 0xba, 0x0c, 0x33, 0x6b, 0x8b, 0xaa, 0xbc, 0x3d, 0x16, + 0xc3, 0x7d, 0x50, 0xaa, 0x48, 0x7e, 0xa5, 0x9a, 0x2d, 0x8f, 0x2a, 0xfc, 0xc7, 0x50, 0x1d, 0x43, 0xa4, 0x9d, 0xfc, + 0xab, 0xa3, 0x46, 0xc7, 0x7d, 0x71, 0xc8, 0x8e, 0x3d, 0x3f, 0x63, 0x20, 0x42, 0x4e, 0xba, 0x15, 0x6e, 0xf1, 0x49, + 0x7a, 0xd4, 0x08, 0xf4, 0x15, 0x04, 0x57, 0x6b, 0xde, 0x9d, 0x51, 0x61, 0xab, 0x51, 0x8e, 0x82, 0x32, 0x0c, 0x51, + 0x0d, 0x4f, 0xd1, 0x38, 0xf0, 0xb2, 0xc0, 0x01, 0x13, 0x01, 0x28, 0xe1, 0xb9, 0x24, 0xba, 0xe8, 0x7f, 0x4b, 0x73, + 0xf4, 0x86, 0x15, 0xec, 0xc8, 0x7c, 0xe9, 0x40, 0x8a, 0x80, 0x90, 0x4a, 0xb9, 0xaa, 0x7f, 0x30, 0x10, 0x8e, 0x87, + 0x91, 0xc1, 0xe4, 0x67, 0xc8, 0x87, 0xf2, 0x66, 0x86, 0x97, 0x47, 0x6e, 0x20, 0x4d, 0x4c, 0xa9, 0xc7, 0xb4, 0x46, + 0x6a, 0xb7, 0xdb, 0xc1, 0x55, 0x2a, 0xdd, 0xa0, 0xc6, 0x17, 0x45, 0x30, 0xfa, 0x97, 0x1b, 0x08, 0x3f, 0xfc, 0x2f, + 0x6e, 0x4b, 0xb0, 0x29, 0x7a, 0x8b, 0x03, 0x90, 0xf6, 0x6d, 0xa9, 0xba, 0x1e, 0x20, 0xc6, 0x96, 0x05, 0xfc, 0xe7, + 0xe0, 0x14, 0x11, 0x4b, 0x67, 0x2c, 0x66, 0xab, 0x53, 0x18, 0x72, 0xff, 0x8b, 0xa1, 0x23, 0x08, 0xfb, 0xd7, 0x19, + 0x76, 0x0c, 0x33, 0x40, 0x26, 0x7b, 0x90, 0x8a, 0x38, 0x52, 0x4c, 0x63, 0x1e, 0xad, 0x05, 0x8e, 0x14, 0x69, 0xf1, + 0x3e, 0x2a, 0x15, 0xdd, 0x97, 0x3c, 0x70, 0x40, 0x55, 0x0e, 0xe1, 0xb7, 0x16, 0x7d, 0x2b, 0x21, 0xf3, 0xba, 0xc9, + 0x02, 0x50, 0x17, 0x63, 0x31, 0xd6, 0x13, 0x92, 0x91, 0x9f, 0xb4, 0xa3, 0xc7, 0x68, 0x68, 0xf2, 0xf1, 0xa9, 0xee, + 0xb8, 0xe9, 0x9e, 0xbf, 0x51, 0x43, 0xb1, 0x7f, 0x2f, 0x13, 0x7d, 0x23, 0x8b, 0x64, 0xef, 0xec, 0xb3, 0xd9, 0x19, + 0xe6, 0xa6, 0xa7, 0xc6, 0x48, 0x37, 0xab, 0x3b, 0x9b, 0x2d, 0x53, 0x3b, 0x72, 0x07, 0x34, 0x67, 0x7c, 0x9d, 0xde, + 0x40, 0x1c, 0xef, 0x85, 0xc4, 0xcd, 0x74, 0xc4, 0x94, 0x7e, 0xdc, 0x88, 0x80, 0x1a, 0x45, 0x07, 0x1b, 0x99, 0xf6, + 0x6f, 0x81, 0x9c, 0x4d, 0xd0, 0x41, 0x15, 0x54, 0x5b, 0xcc, 0x4c, 0x0b, 0x39, 0x34, 0xd2, 0x82, 0x82, 0x95, 0xc6, + 0x60, 0xb0, 0x52, 0x95, 0x64, 0x2f, 0x4a, 0x2c, 0x3d, 0xcb, 0x59, 0xe8, 0x50, 0x36, 0x1d, 0x3c, 0x5f, 0x0a, 0x97, + 0x44, 0xbc, 0xac, 0x85, 0x61, 0xda, 0x6c, 0xa5, 0xa5, 0x65, 0x45, 0x25, 0xec, 0xe4, 0xfa, 0xbc, 0x94, 0x85, 0x79, + 0xa2, 0xb6, 0xf1, 0x8c, 0xdc, 0xcc, 0x50, 0xbe, 0x52, 0xfd, 0x30, 0xbd, 0x5f, 0xf8, 0x77, 0x90, 0x40, 0x9f, 0x22, + 0x60, 0x05, 0x5d, 0x12, 0x6c, 0xa4, 0xf4, 0xcf, 0x17, 0x97, 0x35, 0x0a, 0x7f, 0x7a, 0x01, 0xaf, 0xd2, 0xbd, 0x6e, + 0x87, 0xa1, 0xc8, 0xd7, 0x9e, 0x7c, 0x35, 0x9d, 0xfc, 0x91, 0xc2, 0xe1, 0xba, 0x92, 0x9e, 0x4b, 0x6f, 0x16, 0xf4, + 0x73, 0xeb, 0xd5, 0x57, 0xea, 0x2d, 0x54, 0x4f, 0x93, 0x88, 0xdd, 0x2d, 0xbd, 0x8f, 0x9e, 0x8d, 0x42, 0x68, 0x56, + 0xde, 0x7c, 0xff, 0x90, 0xb4, 0x4c, 0xd4, 0x2a, 0x17, 0x77, 0xb3, 0x81, 0xd0, 0xd6, 0x38, 0x47, 0xd8, 0xbb, 0x71, + 0xee, 0x5f, 0x5a, 0x92, 0x00, 0x55, 0x4c, 0x28, 0xbe, 0xa3, 0xd3, 0x40, 0xee, 0x83, 0x3b, 0x3a, 0x7e, 0xbb, 0xf3, + 0xb5, 0x9a, 0x06, 0xf6, 0x08, 0x53, 0x0f, 0xa2, 0xbf, 0xc1, 0xaa, 0x97, 0x5e, 0x2f, 0x17, 0xd8, 0x9c, 0x97, 0x3c, + 0xb0, 0x54, 0x90, 0x95, 0x57, 0xee, 0xc0, 0xa4, 0xf6, 0x08, 0x02, 0xe8, 0x2f, 0x1b, 0x37, 0xf7, 0x77, 0x22, 0x15, + 0xc1, 0x5d, 0x76, 0x9c, 0x8c, 0xd6, 0xf4, 0x3b, 0x3b, 0x8e, 0x05, 0x63, 0xa7, 0x97, 0x09, 0xab, 0x30, 0xd0, 0x8a, + 0xa3, 0xf5, 0x55, 0xf2, 0x8f, 0x2a, 0xc3, 0xac, 0x15, 0x05, 0xec, 0xfd, 0x52, 0x85, 0xf5, 0x41, 0x29, 0xaa, 0x8b, + 0x78, 0x42, 0xc7, 0x93, 0x66, 0xc3, 0x01, 0x8b, 0xa1, 0x45, 0x8c, 0x2d, 0xf6, 0x48, 0x87, 0xcd, 0x38, 0xa9, 0x77, + 0x7c, 0x56, 0xe1, 0xbc, 0x71, 0x1c, 0xb7, 0xc1, 0x6b, 0x8d, 0xca, 0xf2, 0x05, 0x6e, 0xe0, 0x17, 0xaf, 0x54, 0x8f, + 0x7f, 0xf8, 0xf6, 0xba, 0xb8, 0xa8, 0x3a, 0x0c, 0x6d, 0xf1, 0xa7, 0x0d, 0x69, 0x4c, 0x1a, 0xf6, 0x70, 0xfd, 0x4a, + 0x9a, 0x7c, 0xc1, 0xa8, 0xef, 0x90, 0x8d, 0xd9, 0xba, 0x5f, 0x00, 0x8f, 0x79, 0xef, 0x7a, 0xa9, 0x5f, 0x4a, 0x52, + 0x35, 0xa2, 0x15, 0x35, 0xf1, 0xcd, 0x1a, 0x37, 0xc9, 0x5a, 0x90, 0x84, 0xb6, 0x47, 0xed, 0x88, 0x0f, 0xf1, 0xfb, + 0xb7, 0x29, 0x54, 0x81, 0x78, 0x6f, 0x76, 0x5d, 0x06, 0xbb, 0xd5, 0xb3, 0x94, 0x84, 0x95, 0x1b, 0x30, 0x35, 0xd5, + 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0x4c, 0xd2, 0x9a, 0x74, 0x4e, 0x69, 0x21, 0xd4, 0x32, 0xec, 0x9f, 0x92, 0x45, + 0xc4, 0xc7, 0x32, 0xf8, 0xbc, 0x90, 0x53, 0x77, 0xd0, 0x88, 0x2c, 0x46, 0xad, 0xdc, 0x82, 0xdd, 0x8e, 0xd6, 0x3e, + 0x55, 0x09, 0x88, 0xf5, 0xbb, 0x66, 0xe3, 0x6c, 0x14, 0xd8, 0x43, 0xe8, 0x07, 0xdf, 0xf1, 0x36, 0xcb, 0x5d, 0x60, + 0x4a, 0x79, 0xa4, 0xda, 0x52, 0xfa, 0x8c, 0x17, 0x3f, 0xf2, 0x1e, 0x5a, 0xca, 0xdd, 0x7d, 0xc5, 0x1f, 0x3f, 0x5d, + 0xe7, 0xb5, 0x98, 0x4e, 0xe2, 0x5c, 0x9a, 0x63, 0x49, 0xd9, 0x23, 0xc7, 0x71, 0x71, 0xf7, 0x29, 0x14, 0x9a, 0x51, + 0x11, 0x86, 0x34, 0x12, 0x94, 0x9f, 0x29, 0xae, 0xb8, 0xf6, 0x09, 0xad, 0x25, 0x02, 0x64, 0xf0, 0xfd, 0xa3, 0x4c, + 0x57, 0xee, 0xf3, 0x00, 0x7f, 0xb7, 0x68, 0x95, 0xb0, 0x66, 0x51, 0x84, 0x6d, 0x02, 0x92, 0xf5, 0xdd, 0x61, 0x87, + 0xec, 0xec, 0x86, 0x08, 0x02, 0x75, 0xd7, 0x21, 0x40, 0x18, 0xaf, 0x11, 0xca, 0xe5, 0x5f, 0x2b, 0xe3, 0x76, 0x25, + 0x13, 0xea, 0x30, 0xca, 0x2e, 0x28, 0xf0, 0xde, 0x8b, 0x7e, 0xe9, 0x6d, 0x95, 0x1b, 0x5a, 0x4e, 0xd6, 0x47, 0x2f, + 0x3f, 0x29, 0xbb, 0x24, 0x7f, 0xc8, 0x68, 0x01, 0x48, 0xd9, 0x98, 0x66, 0xe3, 0x98, 0xae, 0x5a, 0xb7, 0xcc, 0x47, + 0xd9, 0x06, 0xc3, 0x76, 0x88, 0x51, 0x3c, 0x68, 0xd5, 0x90, 0x5c, 0xb1, 0x69, 0x8f, 0x7b, 0xe9, 0xc1, 0x6d, 0xf7, + 0x7e, 0x38, 0x38, 0x17, 0xf2, 0x88, 0xd9, 0x4b, 0x98, 0x8f, 0x1a, 0xbb, 0x42, 0xa6, 0x19, 0x0e, 0xe2, 0x20, 0x07, + 0xd9, 0x76, 0xdd, 0x05, 0x53, 0x8e, 0x69, 0x71, 0xbb, 0xc5, 0x46, 0x36, 0x90, 0x11, 0x5a, 0xb0, 0xc9, 0xf8, 0x50, + 0x2c, 0xd3, 0xa1, 0x74, 0xdf, 0x63, 0x02, 0xc6, 0x5a, 0x0f, 0x13, 0xbf, 0x66, 0x1d, 0xa2, 0x4b, 0x16, 0xa4, 0xa9, + 0xd1, 0xe3, 0x9b, 0x3e, 0xa5, 0x5b, 0x66, 0x43, 0xc3, 0xf7, 0x3a, 0xcc, 0x1a, 0x0c, 0x2b, 0xf6, 0x89, 0xb2, 0x57, + 0xf5, 0xc7, 0xdb, 0x71, 0x50, 0x4b, 0x39, 0x73, 0x79, 0x9b, 0xd1, 0xbf, 0x99, 0xc3, 0x40, 0xe3, 0x85, 0xc2, 0x7b, + 0x39, 0x81, 0x9a, 0x96, 0x34, 0x29, 0x78, 0xbb, 0xbc, 0x5a, 0x6d, 0xc2, 0xb8, 0x7f, 0xf7, 0xa1, 0x54, 0x5c, 0xff, + 0xee, 0x7d, 0xdd, 0x55, 0xbd, 0x2f, 0x6f, 0x94, 0x4b, 0x3a, 0xaf, 0xd6, 0x57, 0x10, 0xa0, 0xd2, 0x5b, 0x99, 0xb2, + 0x21, 0xdb, 0x83, 0xd7, 0x75, 0xbd, 0x77, 0x55, 0x7e, 0xdc, 0x81, 0xdd, 0x6d, 0x72, 0x16, 0x6b, 0x0b, 0xea, 0xa9, + 0xd3, 0xb8, 0x7b, 0x29, 0xe5, 0x86, 0x83, 0x53, 0x8a, 0xba, 0xc5, 0x37, 0xbc, 0x3f, 0x67, 0xd7, 0xa9, 0x4b, 0xbd, + 0xd5, 0x6f, 0xd7, 0xbf, 0xf2, 0xd4, 0x58, 0xe5, 0xa0, 0x86, 0xf5, 0xab, 0xf6, 0x35, 0x99, 0x5d, 0x83, 0x99, 0x31, + 0x48, 0xe1, 0x72, 0xae, 0x3e, 0x1b, 0x1c, 0x85, 0x79, 0x4e, 0xa8, 0x60, 0x0b, 0x42, 0xfd, 0xf8, 0x25, 0x31, 0x95, + 0xcc, 0x3f, 0x1c, 0x57, 0x46, 0x3f, 0x08, 0x7d, 0xbb, 0x6a, 0xbd, 0x0c, 0x75, 0x4e, 0x91, 0x8f, 0xb9, 0x9a, 0xe0, + 0x97, 0xd4, 0xc1, 0xd1, 0x2c, 0xfc, 0x53, 0x1d, 0xb6, 0x3b, 0x9c, 0x8f, 0x1e, 0x68, 0x5c, 0xed, 0x1b, 0xf0, 0x46, + 0xb4, 0xb3, 0xb0, 0xe3, 0xdd, 0xa7, 0x69, 0xac, 0xc3, 0xe1, 0xcc, 0xb0, 0xa4, 0x8c, 0x38, 0x0c, 0x98, 0x87, 0x6e, + 0xc9, 0x76, 0xb9, 0x6e, 0x93, 0x83, 0x94, 0xf5, 0x1e, 0x4a, 0x31, 0x8f, 0xe6, 0xb9, 0x69, 0xef, 0x79, 0x2f, 0xba, + 0xc2, 0x70, 0x79, 0x30, 0x32, 0x1f, 0xb3, 0x42, 0xaa, 0xae, 0x53, 0xd7, 0x71, 0xa6, 0x35, 0x46, 0xe4, 0x23, 0xc6, + 0xcd, 0xf7, 0x96, 0xb0, 0x68, 0x57, 0xb7, 0x2b, 0x88, 0x33, 0xac, 0xfc, 0x5f, 0x19, 0x9b, 0xa9, 0xa7, 0x0b, 0xb6, + 0xa7, 0x16, 0xfc, 0x79, 0x93, 0xb2, 0xa2, 0x82, 0x1b, 0x1d, 0x41, 0xa9, 0x7f, 0x7c, 0x5e, 0xd4, 0xaa, 0x66, 0x64, + 0xcd, 0x6f, 0x89, 0x77, 0xc6, 0x78, 0x5d, 0xd7, 0x15, 0xb2, 0xdf, 0xc5, 0xa9, 0xd1, 0x87, 0x26, 0x35, 0x8a, 0x64, + 0xfd, 0xa5, 0x68, 0x0e, 0x0c, 0x61, 0x84, 0xc6, 0x9b, 0xb5, 0xce, 0xc9, 0xe0, 0x24, 0xce, 0xaf, 0x3a, 0xb0, 0xde, + 0xce, 0xb1, 0xbd, 0x82, 0x41, 0x10, 0xf8, 0x57, 0x11, 0xa3, 0x55, 0xfd, 0xbc, 0x33, 0x33, 0x54, 0xf5, 0x72, 0x9a, + 0xac, 0x6c, 0xfe, 0x18, 0x53, 0x0d, 0xca, 0x4b, 0xd9, 0x55, 0xf6, 0x89, 0x8c, 0xfa, 0xb1, 0xa0, 0x1e, 0x5d, 0x9e, + 0x33, 0x94, 0xb7, 0x60, 0xcf, 0x52, 0x6f, 0x06, 0x08, 0x91, 0xb6, 0xab, 0x61, 0xc2, 0x31, 0xcc, 0xe9, 0xc8, 0x8a, + 0x55, 0x99, 0xc0, 0x47, 0x11, 0x5f, 0x34, 0xa7, 0x05, 0xce, 0xac, 0x2e, 0x3b, 0xbc, 0x15, 0xa2, 0xa2, 0xb8, 0xe3, + 0x7e, 0x42, 0x6b, 0x3e, 0x0e, 0x33, 0x31, 0x5e, 0xb3, 0x78, 0xde, 0xfd, 0x05, 0x04, 0x4d, 0x9d, 0xd0, 0x60, 0xe1, + 0xdd, 0x0f, 0x05, 0x44, 0xc9, 0x6b, 0x2b, 0x72, 0x92, 0xe1, 0xb7, 0x02, 0xc9, 0x74, 0x84, 0xd0, 0xc2, 0x25, 0x70, + 0xb3, 0xfd, 0x74, 0xdc, 0x05, 0xc7, 0x48, 0x91, 0x58, 0x38, 0x9e, 0x26, 0x6c, 0x3e, 0xb1, 0x26, 0x96, 0xe3, 0xa4, + 0x43, 0xe9, 0x2a, 0x34, 0xd5, 0x2a, 0x06, 0xad, 0xab, 0xfa, 0xc9, 0xde, 0x29, 0x88, 0xdb, 0x96, 0x20, 0xa2, 0x26, + 0xc7, 0x37, 0x1d, 0xb4, 0x3d, 0xb1, 0xc8, 0x1a, 0x65, 0x14, 0xbe, 0xf3, 0x08, 0x65, 0x8c, 0xc0, 0x7d, 0x95, 0x1a, + 0x63, 0x43, 0x59, 0x66, 0x7f, 0x30, 0x7d, 0x33, 0xc1, 0x44, 0x2f, 0xa1, 0xcc, 0x68, 0x95, 0x9c, 0x20, 0xfa, 0x34, + 0x97, 0x72, 0x3c, 0x22, 0xfa, 0x86, 0x85, 0xbf, 0xc4, 0xe2, 0x2a, 0xe6, 0xdd, 0xe5, 0xed, 0x74, 0x6d, 0x91, 0xcf, + 0xd4, 0x16, 0x63, 0x97, 0xcc, 0xa1, 0xf6, 0xb0, 0x21, 0x3b, 0xf1, 0x86, 0x9d, 0x16, 0xa5, 0x7c, 0x3b, 0x4a, 0x11, + 0xf6, 0x5d, 0xd1, 0xbf, 0x5d, 0x6f, 0x0a, 0x73, 0xed, 0x8a, 0xc9, 0xdf, 0xea, 0xeb, 0x19, 0x5a, 0x4f, 0x7c, 0x35, + 0x74, 0x73, 0x58, 0xf3, 0xc7, 0x02, 0xdf, 0x22, 0x2c, 0xb7, 0xb7, 0xd1, 0xc4, 0xb6, 0xce, 0x4b, 0x4f, 0x60, 0xb0, + 0x10, 0x7e, 0x37, 0x4b, 0xf1, 0x80, 0xd5, 0x83, 0xe8, 0x83, 0x02, 0x13, 0x53, 0xb9, 0x7a, 0xb5, 0x62, 0x8f, 0xd0, + 0x1e, 0xc6, 0x3a, 0x91, 0x5a, 0xf9, 0x36, 0xb8, 0x5a, 0xe1, 0x95, 0xbe, 0xde, 0x14, 0xb1, 0x5e, 0x79, 0x58, 0xdb, + 0xea, 0x97, 0xdc, 0xc2, 0xe5, 0xdf, 0xb6, 0x2a, 0x02, 0x7c, 0xc2, 0x55, 0x88, 0x23, 0xd0, 0x77, 0x69, 0x15, 0x05, + 0xf5, 0x97, 0x1c, 0x72, 0xea, 0xfc, 0x88, 0x70, 0x3e, 0x5f, 0x57, 0xf5, 0x1c, 0x47, 0x78, 0xab, 0xfc, 0x0f, 0x96, + 0x26, 0x6f, 0xe2, 0x7a, 0xb4, 0xe7, 0x25, 0x1d, 0x3e, 0xc1, 0xa5, 0x3b, 0x0a, 0x23, 0xbc, 0x94, 0x31, 0x8d, 0x17, + 0xe7, 0x1a, 0x30, 0x7b, 0x83, 0xe4, 0xf5, 0x38, 0x10, 0x95, 0x1c, 0x87, 0x2d, 0x16, 0xb5, 0x9e, 0x14, 0x1a, 0x91, + 0x37, 0xac, 0xca, 0x50, 0x44, 0x4b, 0x62, 0x07, 0x88, 0xfc, 0x58, 0x14, 0x86, 0x0e, 0xd5, 0x22, 0xb4, 0x6b, 0x7c, + 0xbf, 0xa9, 0x8f, 0xd0, 0x12, 0xab, 0x89, 0xf0, 0x61, 0x41, 0xde, 0x03, 0x0c, 0x73, 0x98, 0x24, 0xad, 0xa3, 0x74, + 0x90, 0xe3, 0x2b, 0x41, 0x32, 0x39, 0x30, 0x93, 0xde, 0x41, 0x6c, 0xe7, 0x7c, 0x31, 0x79, 0xbf, 0x11, 0x3f, 0x85, + 0x34, 0x74, 0x95, 0xbd, 0xc6, 0x22, 0xfb, 0x60, 0x82, 0xb5, 0x2f, 0x0f, 0x97, 0x99, 0xd7, 0xe0, 0x27, 0xfc, 0xff, + 0x34, 0x4b, 0x0a, 0xba, 0x0b, 0xb8, 0x98, 0xbd, 0x0f, 0xc3, 0x04, 0x3e, 0x19, 0x4d, 0x54, 0x96, 0xe8, 0x85, 0x05, + 0x4a, 0xd9, 0xef, 0xb7, 0xd0, 0xe0, 0x10, 0xcc, 0x4b, 0xde, 0xf9, 0xaa, 0x5b, 0x29, 0xaf, 0xef, 0xe4, 0xc8, 0xe4, + 0xf3, 0x29, 0xda, 0x1a, 0xb6, 0x56, 0xc0, 0x4b, 0x08, 0x03, 0x41, 0x34, 0xa4, 0xb8, 0xa4, 0xc3, 0x15, 0xc8, 0x1a, + 0xb9, 0x63, 0xd1, 0x4a, 0x19, 0x4e, 0x1b, 0x37, 0x13, 0xb5, 0xfb, 0xb4, 0x10, 0xc3, 0x79, 0x49, 0x87, 0xb1, 0xa4, + 0x0f, 0x4c, 0xb8, 0xc1, 0xb2, 0xad, 0x0a, 0xec, 0x80, 0xe6, 0x79, 0xd1, 0x68, 0x95, 0x9a, 0x0c, 0xa9, 0xa4, 0x93, + 0xf0, 0x11, 0xaf, 0x1d, 0x29, 0x19, 0xeb, 0x44, 0x4e, 0x13, 0x86, 0xb0, 0xfd, 0xd0, 0x48, 0xd4, 0x41, 0x61, 0x4d, + 0x21, 0x38, 0x2f, 0x34, 0xe0, 0xa6, 0x8d, 0xee, 0x07, 0xa8, 0xba, 0xd0, 0x48, 0xb3, 0xd2, 0x16, 0xb9, 0x6e, 0x2c, + 0x0e, 0xca, 0x8f, 0x78, 0x6d, 0x5e, 0x67, 0x55, 0x61, 0x23, 0x91, 0x7b, 0x28, 0x86, 0xb0, 0x19, 0xd3, 0x1f, 0xae, + 0xdc, 0xe3, 0x12, 0xeb, 0xb8, 0xc7, 0x80, 0x2d, 0xaf, 0x90, 0xc6, 0xec, 0x55, 0x72, 0x60, 0x21, 0x03, 0x34, 0xaf, + 0xc4, 0xf0, 0xbe, 0xf5, 0xcb, 0xa1, 0xf1, 0xad, 0x5a, 0x99, 0x4b, 0xcf, 0x84, 0x89, 0x11, 0x1e, 0x08, 0x83, 0x5f, + 0xab, 0x3f, 0x9d, 0xf6, 0xb2, 0x4e, 0x71, 0xbf, 0xca, 0x21, 0x37, 0x27, 0x2c, 0x1a, 0xe8, 0xa0, 0x4c, 0x4e, 0x17, + 0x39, 0x07, 0xf5, 0xcd, 0xdd, 0x82, 0xbc, 0x40, 0x1c, 0x6b, 0x3c, 0x8e, 0x5c, 0xf7, 0x62, 0xde, 0x66, 0x22, 0xd8, + 0x9b, 0x0a, 0xfe, 0x39, 0xc4, 0x29, 0x21, 0x80, 0x35, 0x48, 0x6c, 0xd6, 0xe5, 0x1e, 0xdb, 0xcb, 0xd8, 0xae, 0x13, + 0x99, 0xa2, 0xb2, 0x82, 0xe4, 0xe7, 0x11, 0x76, 0x81, 0x1a, 0x0f, 0x36, 0x49, 0x0f, 0xb2, 0x32, 0x0d, 0x23, 0x96, + 0x6f, 0x57, 0xc5, 0x29, 0xcc, 0x6b, 0xb5, 0x0e, 0x85, 0x20, 0x99, 0xd9, 0x6d, 0x23, 0x9f, 0x33, 0x4f, 0xc2, 0xa0, + 0x63, 0x47, 0x69, 0x83, 0x0a, 0xe5, 0xd8, 0x56, 0xf3, 0x68, 0x82, 0x5e, 0xf6, 0xd6, 0x39, 0x24, 0x73, 0x5b, 0x4e, + 0x0b, 0x56, 0x04, 0x24, 0x1e, 0xd7, 0xe2, 0xa3, 0xa9, 0xbb, 0xa1, 0xce, 0x11, 0x16, 0x39, 0x30, 0xcb, 0x96, 0x89, + 0xa8, 0xc5, 0xa5, 0x67, 0x6e, 0x1a, 0x6c, 0x2a, 0xcb, 0x4c, 0x7a, 0x11, 0xb2, 0x68, 0xa5, 0x89, 0x2d, 0xcc, 0xc5, + 0x38, 0x33, 0x07, 0x96, 0xf6, 0x11, 0x1a, 0x06, 0xcb, 0x48, 0x48, 0x63, 0x4b, 0x96, 0xb7, 0xc8, 0xa9, 0xc0, 0xd1, + 0xfe, 0x67, 0x96, 0x3b, 0x62, 0x2b, 0xf7, 0xd0, 0x82, 0xef, 0xf7, 0x57, 0x51, 0xc3, 0xd0, 0xf6, 0x57, 0xfe, 0xbd, + 0xe4, 0x22, 0xa8, 0x57, 0x90, 0x0f, 0x49, 0x26, 0x15, 0x38, 0x28, 0x0c, 0xd4, 0xc9, 0xb8, 0x11, 0xad, 0x4d, 0x78, + 0x24, 0x87, 0x48, 0x13, 0x79, 0x6d, 0x29, 0x2a, 0x87, 0x22, 0x6b, 0xaf, 0xd4, 0x2a, 0x21, 0x00, 0xbd, 0xf5, 0x4e, + 0xb7, 0x1a, 0x0d, 0x6f, 0xd4, 0x24, 0xca, 0x41, 0x7c, 0x38, 0x0d, 0x4f, 0xda, 0xe8, 0x8a, 0xf3, 0x72, 0xe2, 0x33, + 0x75, 0x77, 0x40, 0xa0, 0x81, 0xb3, 0x80, 0xc3, 0x0b, 0x83, 0x59, 0x5d, 0x55, 0x56, 0xdb, 0x05, 0x09, 0xb2, 0xa9, + 0x7f, 0x41, 0x7f, 0x58, 0x9b, 0x23, 0xb5, 0x49, 0x30, 0x1a, 0x47, 0x93, 0xf5, 0xbf, 0x8b, 0x09, 0xbc, 0xa2, 0x2e, + 0xd0, 0x1e, 0x9f, 0xb6, 0x73, 0x2a, 0x4a, 0xb6, 0xfd, 0xe7, 0x43, 0x39, 0x81, 0xfd, 0x5e, 0x76, 0x62, 0x76, 0x78, + 0x2a, 0x47, 0x3d, 0xbd, 0x4a, 0xc5, 0xd8, 0x43, 0x0c, 0xf5, 0x76, 0x04, 0x2c, 0xeb, 0x1b, 0x6b, 0x96, 0xcd, 0x76, + 0x24, 0x5b, 0x73, 0xf4, 0x72, 0x96, 0x48, 0xee, 0x1e, 0x34, 0x58, 0xce, 0xc4, 0x96, 0xcf, 0xe8, 0x79, 0xbb, 0xb5, + 0xc7, 0xe4, 0xed, 0x2c, 0x3b, 0x82, 0x2f, 0x5a, 0xdf, 0xd8, 0xd5, 0x5e, 0xf4, 0xc8, 0x75, 0xec, 0xc3, 0x04, 0x92, + 0x60, 0xb1, 0x00, 0x17, 0x71, 0xcf, 0x27, 0x67, 0xd6, 0x62, 0x9f, 0x8a, 0xd8, 0x45, 0x5a, 0xa8, 0x9f, 0xd2, 0x32, + 0x22, 0xe9, 0xf0, 0xf2, 0x63, 0xcf, 0x48, 0x1e, 0xd7, 0x51, 0xaa, 0xd4, 0x6f, 0x3d, 0x8e, 0x32, 0xb2, 0xc8, 0x51, + 0x27, 0x5c, 0xc2, 0x63, 0xdb, 0xc9, 0x4e, 0x77, 0xac, 0x5a, 0xc8, 0x3e, 0x80, 0x00, 0x49, 0xc8, 0x96, 0xb4, 0xdd, + 0x45, 0x6a, 0xe4, 0xef, 0x71, 0x31, 0x2c, 0x46, 0x84, 0xf0, 0xb0, 0x6e, 0xf0, 0x4f, 0xba, 0xcc, 0xd4, 0xdb, 0xa9, + 0x7c, 0xf0, 0x82, 0x38, 0x1a, 0x0f, 0x8f, 0xd4, 0x28, 0xb4, 0xfa, 0x64, 0x1c, 0x35, 0x29, 0x9c, 0xa1, 0x95, 0xd3, + 0xf6, 0x6f, 0xa0, 0xb7, 0x53, 0xd3, 0x45, 0xa0, 0x45, 0xe1, 0x8b, 0x47, 0x28, 0x01, 0xb1, 0x44, 0x58, 0x31, 0xa4, + 0x92, 0x30, 0x95, 0x09, 0xb9, 0x64, 0xcc, 0x65, 0xc6, 0x9d, 0x5a, 0x05, 0x77, 0x59, 0x15, 0xf7, 0x58, 0x3d, 0xee, + 0xb3, 0x06, 0x3c, 0xa8, 0x35, 0xe2, 0x21, 0xab, 0xe1, 0x1c, 0xa2, 0x7a, 0x51, 0xbd, 0xac, 0x5e, 0x55, 0xd7, 0xca, + 0x75, 0xaf, 0x43, 0x26, 0x30, 0xfe, 0x25, 0x49, 0xb4, 0xfa, 0x10, 0x2d, 0x4d, 0x79, 0xbe, 0x73, 0xf7, 0xde, 0xfd, + 0x07, 0x0f, 0xc7, 0x05, 0x2a, 0x71, 0x56, 0xf7, 0x6d, 0x59, 0xd2, 0x00, 0xb6, 0x50, 0x3a, 0x7d, 0x4b, 0x49, 0x83, + 0x89, 0x42, 0xdb, 0xf9, 0x93, 0xa5, 0xbf, 0x3c, 0xfe, 0xa0, 0xea, 0xb9, 0x79, 0x56, 0xac, 0xbc, 0xf5, 0x88, 0xd3, + 0x02, 0x2d, 0x9e, 0x5e, 0xb0, 0x90, 0x4e, 0x07, 0x1d, 0xf3, 0x6a, 0x1e, 0xf3, 0x90, 0x51, 0x8f, 0xad, 0x85, 0xa7, + 0x5a, 0xc9, 0xf2, 0x07, 0x1d, 0xc0, 0xb1, 0x38, 0x9e, 0xc9, 0xbe, 0x79, 0x24, 0x66, 0xa2, 0x69, 0xda, 0x6a, 0x42, + 0xd5, 0x3f, 0xdc, 0xba, 0xa1, 0xea, 0xc0, 0xc6, 0xec, 0xf8, 0xed, 0x27, 0x0a, 0xb0, 0x4c, 0x13, 0x98, 0x70, 0xe3, + 0x38, 0x6b, 0x16, 0x2e, 0x66, 0xcb, 0xe6, 0xf9, 0x88, 0x01, 0xea, 0x99, 0x0a, 0xa0, 0x92, 0x1e, 0xf8, 0x67, 0xc7, + 0xfe, 0x74, 0xee, 0x2e, 0x6c, 0x18, 0xfd, 0xce, 0xec, 0x7e, 0xf5, 0x1b, 0x71, 0x02, 0xa9, 0xc7, 0xa2, 0xb2, 0x52, + 0xcd, 0xc4, 0x8b, 0x6a, 0x6f, 0xc4, 0xd1, 0xcd, 0x4c, 0x73, 0x63, 0x6f, 0x6f, 0x82, 0xd1, 0xee, 0xc8, 0x00, 0x88, + 0x40, 0xfd, 0xe7, 0xf4, 0x94, 0xd5, 0xfa, 0x76, 0xfa, 0x4d, 0xca, 0xa6, 0x48, 0x09, 0x3e, 0x2d, 0xfe, 0xe0, 0x9f, + 0xba, 0x6f, 0x5a, 0x6c, 0x85, 0x36, 0xf2, 0xb9, 0xca, 0x89, 0x23, 0x91, 0x27, 0xbe, 0x63, 0xeb, 0xac, 0xf2, 0xb0, + 0xf1, 0x53, 0x58, 0xde, 0x66, 0x5a, 0x5c, 0x8a, 0x63, 0x6d, 0x9c, 0xc3, 0x22, 0x37, 0xff, 0x4c, 0xb5, 0xa3, 0xf1, + 0x8b, 0x7d, 0xfb, 0x2b, 0x53, 0xe5, 0x61, 0x39, 0xbe, 0xf2, 0xef, 0xf2, 0x73, 0xf4, 0x38, 0x2f, 0x72, 0xb5, 0xfe, + 0x3e, 0x35, 0xcb, 0x96, 0x0f, 0x4f, 0x72, 0x5f, 0x71, 0x99, 0xa7, 0xa6, 0xf9, 0xa5, 0xaf, 0x86, 0x3c, 0x77, 0xad, + 0xe9, 0xdd, 0xcd, 0xcf, 0x58, 0xfe, 0x49, 0x35, 0xab, 0xf6, 0xa0, 0x7f, 0x95, 0x3d, 0x3b, 0x9e, 0x8a, 0x11, 0x99, + 0x1a, 0x2b, 0x73, 0x40, 0x75, 0x7f, 0x7e, 0x16, 0x09, 0x6e, 0xfc, 0xa7, 0xc7, 0x25, 0x3d, 0x83, 0xa4, 0xb7, 0x75, + 0xfe, 0x42, 0xe8, 0xa6, 0x9e, 0xf4, 0xe0, 0x10, 0xd4, 0x2b, 0xfe, 0x37, 0x0f, 0xe1, 0x0b, 0x4c, 0x5d, 0x20, 0x10, + 0x6f, 0x60, 0x2a, 0xf4, 0xf3, 0xcb, 0xe8, 0x34, 0xd1, 0xdd, 0xa4, 0x65, 0xaa, 0xa2, 0xa6, 0x94, 0x13, 0x3b, 0x42, + 0xc1, 0xb7, 0x93, 0x91, 0x5e, 0x32, 0xda, 0x3a, 0x7f, 0x2d, 0x74, 0x4b, 0x91, 0xdd, 0x4d, 0xbc, 0x55, 0xe7, 0x3d, + 0x2b, 0xe7, 0xcf, 0xf5, 0x74, 0x7b, 0x82, 0x5d, 0x7d, 0x06, 0x54, 0xcb, 0x02, 0x9c, 0x97, 0x6f, 0x60, 0xda, 0x2f, + 0x02, 0x94, 0xd1, 0x62, 0x35, 0xf4, 0x1b, 0xf5, 0x96, 0xc9, 0xfa, 0xdb, 0x8f, 0x6b, 0x0d, 0xd8, 0x39, 0xfc, 0x73, + 0x03, 0x86, 0xe7, 0x48, 0xf4, 0x1c, 0x41, 0x97, 0xae, 0x31, 0x97, 0x35, 0xda, 0x90, 0x3d, 0xd5, 0xd8, 0xbc, 0x05, + 0x97, 0x82, 0xf0, 0xb6, 0x61, 0x36, 0xcd, 0x7c, 0xac, 0x62, 0xae, 0xce, 0x65, 0x9e, 0x3e, 0x23, 0x21, 0xdf, 0xb7, + 0xac, 0x8d, 0x05, 0x53, 0x10, 0xcc, 0x6c, 0x98, 0x32, 0x96, 0xaf, 0x8b, 0xa6, 0x14, 0x7e, 0x1f, 0xc5, 0xb0, 0xee, + 0x19, 0x8b, 0xa4, 0x60, 0x5d, 0xf9, 0x2f, 0x39, 0xe6, 0x31, 0x8f, 0xa5, 0x83, 0x9e, 0x1b, 0xe6, 0xd1, 0x0c, 0x7c, + 0xcc, 0xa8, 0x4a, 0x9c, 0xc1, 0x8e, 0x17, 0xcf, 0x88, 0x82, 0x16, 0xcd, 0xf5, 0xc7, 0xb6, 0xd6, 0x87, 0x4c, 0xdd, + 0xad, 0x98, 0xcd, 0xcf, 0xf4, 0x6d, 0xb6, 0xe9, 0x80, 0xc9, 0x12, 0x41, 0x98, 0x43, 0xf3, 0x7b, 0xf5, 0xa1, 0xb2, + 0x93, 0x5b, 0xa3, 0xb5, 0x76, 0x46, 0xe3, 0x7c, 0xa8, 0x48, 0x75, 0x0e, 0x7d, 0x91, 0xa8, 0xcb, 0x88, 0x71, 0x93, + 0x2d, 0xbd, 0xdb, 0x2f, 0x4b, 0xe3, 0xbf, 0x96, 0xad, 0x32, 0xe2, 0xa9, 0xb9, 0x02, 0xba, 0xcb, 0x35, 0x5c, 0x56, + 0xc4, 0x64, 0x8a, 0x79, 0xb8, 0x6d, 0xe5, 0x6c, 0x16, 0x72, 0x69, 0x3e, 0x81, 0x33, 0xa0, 0x0a, 0xd7, 0x98, 0x05, + 0xd1, 0x5c, 0xb0, 0x00, 0xd6, 0x02, 0xa7, 0x97, 0x27, 0x73, 0x79, 0xd6, 0x31, 0x4a, 0x8c, 0x65, 0xed, 0x1f, 0x2f, + 0x2f, 0x0d, 0xfa, 0x49, 0x16, 0xf2, 0xcc, 0x77, 0xdc, 0xa9, 0xda, 0xa7, 0x78, 0x3a, 0xfa, 0xdd, 0x4f, 0xf9, 0x7b, + 0x0e, 0xdd, 0x76, 0x49, 0xb6, 0x6f, 0x9f, 0x3a, 0x14, 0xe0, 0x48, 0x17, 0xf2, 0x6b, 0x5b, 0xec, 0xb9, 0x5b, 0xf6, + 0x21, 0xa6, 0x85, 0xb0, 0x31, 0xf3, 0x68, 0x11, 0x70, 0x59, 0xde, 0xbb, 0x51, 0xeb, 0x79, 0x4b, 0x02, 0x2e, 0xf1, + 0x9e, 0x9f, 0xea, 0x68, 0x29, 0x6d, 0x47, 0xee, 0xb3, 0x83, 0x28, 0x67, 0x57, 0x5d, 0x3f, 0x31, 0x37, 0xfe, 0xdb, + 0x9d, 0x3d, 0x53, 0x6b, 0xb5, 0x20, 0x29, 0x97, 0x7e, 0x9e, 0x1f, 0x9a, 0x99, 0x4a, 0x26, 0xf0, 0xf0, 0x02, 0x12, + 0xbf, 0xf0, 0xd3, 0xbf, 0x1f, 0xa8, 0xb2, 0xae, 0x1c, 0x22, 0x3d, 0x03, 0x92, 0xe7, 0xe3, 0xc7, 0xd7, 0x85, 0xc7, + 0x3b, 0xa2, 0x4b, 0xbd, 0x9e, 0xe7, 0x16, 0x12, 0xe7, 0x49, 0x77, 0x4e, 0x5c, 0xad, 0x5c, 0xa0, 0x67, 0xa6, 0x21, + 0xe1, 0x5c, 0xf5, 0x8f, 0x0f, 0x81, 0x7f, 0x05, 0x0e, 0x24, 0xa9, 0xab, 0x0b, 0x15, 0x02, 0x9d, 0xd0, 0x7e, 0xde, + 0x12, 0x48, 0x78, 0xf7, 0x22, 0xd8, 0x62, 0x90, 0x7b, 0x2d, 0xa8, 0xa8, 0x2a, 0x54, 0x30, 0x6f, 0x44, 0x25, 0x78, + 0xe4, 0x1f, 0x30, 0x68, 0x9e, 0x98, 0x99, 0xe1, 0x3c, 0x82, 0x88, 0x24, 0x39, 0xb1, 0x45, 0x7c, 0x00, 0xa0, 0x8e, + 0x77, 0x82, 0xf1, 0x4a, 0xe2, 0x30, 0x42, 0x09, 0x2e, 0xbf, 0x17, 0xad, 0x47, 0x71, 0x67, 0x87, 0x83, 0x7f, 0x41, + 0x9a, 0xc7, 0xed, 0xde, 0x1f, 0x43, 0x7f, 0xf6, 0x01, 0xcd, 0xd0, 0xee, 0x04, 0xf4, 0x71, 0xb7, 0x26, 0xed, 0x7e, + 0x33, 0x3d, 0x13, 0x6d, 0xb7, 0x49, 0x62, 0x73, 0x20, 0x63, 0xde, 0x9e, 0x88, 0x0d, 0x6d, 0xfc, 0x01, 0x7e, 0x6b, + 0x6c, 0x56, 0x5d, 0x26, 0x9e, 0x59, 0x3d, 0x3c, 0x9e, 0x89, 0x27, 0x56, 0xab, 0x8d, 0xd8, 0xb1, 0xfa, 0x3f, 0xd4, + 0xf7, 0xf8, 0x96, 0x55, 0x78, 0x54, 0xfd, 0x17, 0xda, 0x81, 0x87, 0xb0, 0xb1, 0x36, 0x8f, 0x9e, 0x35, 0x6c, 0xf0, + 0x60, 0x75, 0x09, 0x3a, 0xf8, 0xf1, 0x57, 0x06, 0x8f, 0x88, 0xdd, 0x0f, 0x06, 0x2b, 0xab, 0x29, 0xb0, 0x3c, 0xde, + 0x1f, 0xdd, 0xff, 0x3f, 0x6f, 0x1a, 0x1e, 0xba, 0xd6, 0xd3, 0x1a, 0x2c, 0x2a, 0xa1, 0xc2, 0xfc, 0x7f, 0x56, 0x0f, + 0x62, 0xc6, 0x6a, 0x9d, 0x89, 0x29, 0xab, 0x3a, 0x13, 0x13, 0x56, 0xfb, 0xbc, 0x5e, 0x6f, 0x88, 0x1e, 0x2b, 0x5f, + 0x88, 0x31, 0xab, 0xe5, 0x9d, 0xe8, 0xb3, 0xaa, 0xb6, 0x7f, 0x03, 0x31, 0x60, 0xe5, 0x13, 0x31, 0x8c, 0x0c, 0x56, + 0x30, 0xfa, 0x1b, 0x2f, 0x77, 0x32, 0xb4, 0x5b, 0x3d, 0xb7, 0xc6, 0xff, 0x45, 0x27, 0xea, 0xd3, 0xe5, 0xc4, 0x95, + 0x67, 0x12, 0x70, 0xd1, 0xfe, 0x5b, 0x78, 0xbd, 0x09, 0x8f, 0x79, 0x60, 0xa4, 0x62, 0x69, 0x06, 0xc0, 0x38, 0x3f, + 0xfc, 0x4f, 0x77, 0x84, 0xb9, 0x91, 0x04, 0x46, 0x56, 0x29, 0x6b, 0xa3, 0xff, 0x97, 0xae, 0x20, 0x2a, 0x83, 0x6c, + 0xfb, 0xf0, 0xb6, 0x3a, 0x35, 0x7a, 0x0d, 0x6d, 0x18, 0xbd, 0xbc, 0xce, 0x59, 0x17, 0xd0, 0x51, 0x4b, 0x0a, 0xa1, + 0xeb, 0xba, 0x7b, 0x62, 0x7a, 0x5b, 0xbc, 0x23, 0x98, 0x11, 0xd4, 0x44, 0x04, 0x49, 0xd3, 0xfe, 0x4f, 0xce, 0xb6, + 0xe5, 0x58, 0x7b, 0xca, 0x62, 0xf9, 0xf0, 0x7d, 0x75, 0x75, 0x2a, 0x4c, 0x99, 0x09, 0x2e, 0xf3, 0xb0, 0xad, 0xde, + 0x53, 0x3d, 0x8c, 0xa5, 0xdb, 0xd3, 0xf0, 0x12, 0x31, 0x7c, 0x4b, 0xae, 0x5a, 0x10, 0xef, 0x09, 0xe6, 0xd8, 0x2d, + 0x81, 0x58, 0x29, 0x5c, 0x8d, 0xd7, 0x2d, 0x24, 0x8e, 0x19, 0xa9, 0xf1, 0x57, 0xeb, 0xfd, 0xdb, 0xcd, 0x14, 0xa7, + 0xc0, 0xa1, 0xe8, 0x36, 0xe0, 0x1d, 0x11, 0xe5, 0x94, 0x43, 0x96, 0x3c, 0xe2, 0x60, 0x87, 0x13, 0x07, 0x64, 0x99, + 0x26, 0xda, 0xac, 0x95, 0xd7, 0x04, 0xef, 0xea, 0xd1, 0x29, 0x93, 0x63, 0x6b, 0x03, 0xc7, 0x20, 0xf9, 0x17, 0xbc, + 0xea, 0x15, 0xa0, 0x0f, 0xd6, 0x54, 0x5d, 0xe8, 0xdb, 0x97, 0xf3, 0x3b, 0xd5, 0xa6, 0x5d, 0xe1, 0x95, 0xfd, 0x86, + 0xad, 0xce, 0xea, 0x1b, 0x41, 0x6a, 0xdd, 0x6d, 0xa4, 0x21, 0x40, 0xf7, 0x43, 0xbe, 0xbb, 0xa7, 0x23, 0x9c, 0x6c, + 0xed, 0x1c, 0x61, 0xa1, 0x99, 0x11, 0xfa, 0xdb, 0x08, 0xb8, 0x43, 0x01, 0x55, 0xdc, 0xda, 0x33, 0xa3, 0x48, 0x44, + 0xb4, 0x24, 0x15, 0xf1, 0x1e, 0x5c, 0xcf, 0xc6, 0xb0, 0x6c, 0xa4, 0x9d, 0xbd, 0xbe, 0xc9, 0xb6, 0x28, 0x82, 0xb0, + 0x75, 0xbd, 0x23, 0x0c, 0xe4, 0x2f, 0x03, 0xff, 0xd7, 0xea, 0xbd, 0xb4, 0x5a, 0xba, 0xa9, 0x7b, 0x7c, 0x0b, 0x7e, + 0xa8, 0x4b, 0xf9, 0x99, 0xa4, 0x98, 0x9d, 0x26, 0x3e, 0xf5, 0x49, 0x79, 0x8a, 0x97, 0x5d, 0x06, 0x40, 0xe4, 0x7a, + 0x4e, 0xc1, 0x87, 0xbc, 0xdb, 0x4c, 0xa9, 0x8b, 0xcc, 0x63, 0x82, 0x01, 0x66, 0x97, 0xd2, 0xc5, 0x3a, 0x35, 0x5c, + 0x6c, 0xa4, 0x1c, 0x6e, 0x3a, 0x9c, 0x36, 0xf4, 0xaa, 0x18, 0x17, 0x91, 0x1d, 0xdf, 0x35, 0x8d, 0x6f, 0x72, 0x23, + 0xf4, 0xde, 0xb9, 0xe1, 0xa9, 0xcf, 0x18, 0xf3, 0xb7, 0x82, 0x50, 0x19, 0x63, 0x3b, 0x9c, 0xad, 0x28, 0xd5, 0x4a, + 0x7e, 0x39, 0x6c, 0x73, 0xd8, 0xbf, 0xc9, 0xad, 0x6d, 0x0c, 0x18, 0xf1, 0x05, 0xe3, 0xbb, 0x10, 0xbf, 0x2f, 0x58, + 0x23, 0x7a, 0xc1, 0x25, 0xcb, 0x53, 0xb0, 0xf0, 0x50, 0x02, 0x53, 0xb6, 0x87, 0x26, 0xe0, 0xde, 0xe7, 0x26, 0x7e, + 0x3b, 0xe4, 0xe6, 0xd1, 0x87, 0x78, 0x2d, 0x94, 0x2a, 0x11, 0xf6, 0xad, 0x78, 0xd6, 0xa8, 0xe0, 0x99, 0x9b, 0x95, + 0xcc, 0x00, 0x28, 0x04, 0xba, 0xd5, 0x1c, 0xbe, 0xeb, 0x8f, 0x7b, 0x75, 0x80, 0xce, 0x6a, 0x5f, 0xce, 0x84, 0x8c, + 0x91, 0xe7, 0xf4, 0x20, 0xe8, 0xe9, 0xa3, 0x77, 0xbc, 0xbd, 0xac, 0x2a, 0x43, 0x8e, 0xc5, 0xc8, 0xa1, 0x99, 0x3c, + 0x2a, 0x4b, 0x1a, 0xb2, 0xe0, 0x72, 0x2a, 0xd7, 0xa4, 0x5a, 0xf5, 0x25, 0xe9, 0x7d, 0xcd, 0xd9, 0x0e, 0x68, 0xec, + 0x79, 0xbf, 0x85, 0xe0, 0x18, 0x84, 0x90, 0x30, 0x27, 0x36, 0xf7, 0xfe, 0xce, 0x00, 0xe7, 0xdb, 0x97, 0x50, 0x6f, + 0xbe, 0xf9, 0x81, 0x5b, 0xf4, 0x13, 0x8e, 0xa1, 0xb4, 0x38, 0xd5, 0x84, 0xab, 0xa3, 0x37, 0xb2, 0x36, 0x52, 0xd2, + 0x79, 0x1d, 0xbd, 0x1b, 0x1b, 0xc5, 0x78, 0xc7, 0x40, 0x54, 0x44, 0x79, 0xb8, 0x1f, 0x4b, 0xa2, 0x72, 0x73, 0x82, + 0x6b, 0x8a, 0x48, 0x44, 0xe1, 0x20, 0xdd, 0xc5, 0xd5, 0xf8, 0xc2, 0xa1, 0xc6, 0x34, 0x33, 0x07, 0x06, 0x48, 0xaa, + 0x43, 0x5d, 0x9b, 0xdd, 0x37, 0x02, 0xe1, 0x25, 0x17, 0xb0, 0x5c, 0x81, 0xcb, 0x43, 0xfe, 0x22, 0xf5, 0x5d, 0xcc, + 0x3b, 0x6d, 0x42, 0x24, 0xe7, 0xce, 0x80, 0x18, 0x38, 0xa4, 0x08, 0x25, 0xd3, 0x8d, 0x4b, 0x4e, 0xe2, 0xd6, 0x6c, + 0xce, 0x5c, 0x28, 0x19, 0x33, 0xf7, 0x88, 0xfe, 0x83, 0xf7, 0x36, 0x21, 0x5e, 0x70, 0x90, 0x45, 0x25, 0x3a, 0x1b, + 0x46, 0x3a, 0x91, 0xf0, 0x6b, 0x2c, 0xde, 0x60, 0x47, 0x96, 0x06, 0xd1, 0x4d, 0x91, 0x31, 0x84, 0x4d, 0x3b, 0xac, + 0x0e, 0xcd, 0x46, 0x49, 0x42, 0x0e, 0x08, 0xb5, 0xf3, 0x24, 0x27, 0x1d, 0xe1, 0xdd, 0xbb, 0xdc, 0xa6, 0xea, 0xc5, + 0xaf, 0x32, 0xd1, 0xa8, 0x36, 0x11, 0x2b, 0xbf, 0x9e, 0xc8, 0xca, 0xc2, 0x97, 0x02, 0x9a, 0x02, 0x25, 0x49, 0xfe, + 0xf6, 0xd7, 0xb4, 0xcc, 0xd3, 0x6b, 0x1d, 0x64, 0x30, 0x98, 0x7c, 0x25, 0x72, 0x8d, 0x1a, 0xd9, 0xe0, 0x3b, 0xe9, + 0x5c, 0xc6, 0x2a, 0xf7, 0x65, 0x88, 0x78, 0x9a, 0x9b, 0xfe, 0xa5, 0x0f, 0x2a, 0xd4, 0xea, 0x43, 0x23, 0xbb, 0x93, + 0xb6, 0x3e, 0x49, 0xd1, 0x48, 0x56, 0xec, 0xe2, 0x8b, 0x4b, 0x34, 0x5a, 0x32, 0x15, 0x4f, 0xca, 0x22, 0x63, 0x93, + 0x6b, 0xaf, 0x8d, 0x4d, 0xd4, 0x1d, 0x8c, 0x25, 0xb2, 0x34, 0x7c, 0x3b, 0x3d, 0xda, 0x10, 0xb7, 0xf7, 0x50, 0x57, + 0x37, 0x65, 0x1f, 0xde, 0xcd, 0xa8, 0x42, 0x73, 0xb3, 0x4a, 0x9d, 0x71, 0x70, 0x86, 0x5f, 0xaf, 0x50, 0x68, 0x4e, + 0x9f, 0x1a, 0x92, 0xe3, 0xec, 0x6b, 0x69, 0x00, 0xed, 0xab, 0xc9, 0x28, 0x16, 0x61, 0x21, 0xc4, 0x25, 0x1c, 0x80, + 0x5c, 0x3e, 0x4c, 0x97, 0x58, 0x6b, 0x95, 0x2b, 0xe9, 0x95, 0x48, 0x16, 0x28, 0xf1, 0x51, 0x9d, 0x5a, 0xa9, 0xac, + 0xe6, 0x4c, 0x62, 0x06, 0x0a, 0x98, 0xbc, 0x35, 0xbd, 0x91, 0x9e, 0xe5, 0x96, 0xb9, 0x4c, 0x70, 0xe6, 0x42, 0xb4, + 0xe6, 0x87, 0x6f, 0x72, 0x43, 0x56, 0x54, 0xd3, 0x88, 0x14, 0x3f, 0x38, 0x33, 0x10, 0x13, 0x20, 0x96, 0x31, 0xd7, + 0x27, 0x98, 0x60, 0x83, 0xf5, 0x66, 0x4d, 0xd7, 0xb0, 0xa1, 0xfc, 0x74, 0xff, 0xe4, 0x17, 0x63, 0x9e, 0x23, 0x80, + 0x95, 0x99, 0x78, 0x5e, 0xf2, 0xe9, 0x54, 0x29, 0x74, 0x89, 0x28, 0xce, 0x68, 0xd1, 0xd8, 0x99, 0x86, 0x65, 0x6c, + 0x23, 0x43, 0x00, 0xb4, 0x37, 0xf9, 0xf5, 0x65, 0x16, 0x25, 0xb5, 0x32, 0x21, 0xf2, 0x11, 0xd3, 0x8c, 0x3c, 0x39, + 0xd5, 0x21, 0x6b, 0x0d, 0x1e, 0x46, 0x95, 0x48, 0xfe, 0x78, 0x2a, 0xb9, 0x90, 0x44, 0xef, 0x61, 0x3b, 0x54, 0x59, + 0xb2, 0x60, 0xc5, 0x2a, 0x7a, 0xdf, 0xde, 0xee, 0xfa, 0x6b, 0x64, 0xc2, 0x5e, 0x00, 0xa2, 0xd7, 0x1e, 0x1c, 0xe3, + 0x95, 0xc9, 0x27, 0x57, 0x19, 0x2c, 0x28, 0x25, 0x42, 0x4d, 0x38, 0xda, 0x98, 0xcb, 0x32, 0x53, 0x70, 0xd5, 0x23, + 0xd9, 0xb2, 0x94, 0x39, 0xc9, 0xb0, 0xde, 0x06, 0x92, 0xf1, 0x11, 0xb5, 0xfc, 0xb5, 0x60, 0x6f, 0x1d, 0xd4, 0x29, + 0x04, 0x71, 0x92, 0xff, 0xe6, 0xf1, 0xba, 0xc5, 0xf7, 0xcb, 0x4f, 0x9b, 0x2c, 0x46, 0x92, 0xbd, 0x48, 0x53, 0xe9, + 0xbf, 0xd0, 0x2c, 0x0d, 0x0e, 0x4a, 0x4b, 0x6f, 0xcf, 0x05, 0x57, 0x7a, 0x21, 0x8a, 0x59, 0x00, 0x4f, 0x48, 0xa9, + 0x37, 0xba, 0x92, 0x68, 0x9d, 0x61, 0x75, 0x2c, 0xce, 0x6a, 0x11, 0x7a, 0x95, 0x4e, 0x88, 0xc5, 0x53, 0x23, 0xf2, + 0x9b, 0xac, 0x38, 0x47, 0xf7, 0xc6, 0xe3, 0x6b, 0x76, 0xbe, 0x2c, 0x43, 0x65, 0xea, 0x47, 0x88, 0xbe, 0x14, 0x1c, + 0x21, 0x36, 0x12, 0x75, 0x1b, 0x56, 0x8c, 0x10, 0x4c, 0x78, 0x75, 0x62, 0x96, 0x4b, 0xf4, 0xda, 0xfa, 0xe3, 0x7d, + 0xba, 0x67, 0xd5, 0x30, 0x7a, 0x65, 0x3e, 0xfe, 0x25, 0x91, 0xcd, 0x30, 0xfa, 0x13, 0xf8, 0x81, 0xc5, 0x9d, 0x9b, + 0xe9, 0x41, 0x38, 0x31, 0x4f, 0x4a, 0x2a, 0xb3, 0xf9, 0x83, 0xbd, 0xc3, 0x30, 0xba, 0xa0, 0xfb, 0xc1, 0x9b, 0x4e, + 0xad, 0x76, 0xbf, 0x21, 0xba, 0x8a, 0xa7, 0xdd, 0xfd, 0xaa, 0x3f, 0x98, 0x24, 0x0a, 0xd1, 0x8b, 0x06, 0x00, 0x3c, + 0xcd, 0x80, 0x67, 0x92, 0x62, 0x63, 0xf2, 0x66, 0x96, 0xae, 0x9c, 0x13, 0x5f, 0x50, 0xe7, 0xd9, 0x86, 0xac, 0xc9, + 0xbd, 0x24, 0xc8, 0x29, 0x55, 0x6e, 0x0d, 0xca, 0x18, 0x15, 0x55, 0x62, 0x78, 0x9a, 0x46, 0xb0, 0x01, 0x72, 0x4b, + 0x5b, 0x74, 0x3d, 0x23, 0x35, 0xa7, 0x73, 0x48, 0xd5, 0xca, 0x12, 0xdf, 0xa3, 0x3f, 0xca, 0xd0, 0x78, 0x48, 0xc4, + 0x56, 0x5d, 0xd3, 0xdc, 0xaf, 0xeb, 0x5d, 0x3a, 0x6e, 0xf8, 0x9d, 0x89, 0xc2, 0x6f, 0x5e, 0xe0, 0x3d, 0xb7, 0xd0, + 0xd1, 0x06, 0x37, 0x8e, 0xec, 0xe0, 0xcf, 0x60, 0x02, 0x63, 0x3f, 0x6f, 0x86, 0x83, 0xcb, 0x19, 0x9a, 0xaf, 0xa7, + 0xb9, 0xc7, 0xbd, 0x23, 0x6e, 0xd9, 0x5c, 0xe3, 0x7f, 0x73, 0x0b, 0x05, 0xe5, 0xfb, 0xcc, 0xb0, 0xa4, 0xd9, 0xde, + 0x8a, 0xa4, 0xf2, 0x35, 0x03, 0xd8, 0x85, 0x94, 0x9a, 0x0a, 0xb3, 0x69, 0x36, 0x99, 0x60, 0x00, 0x74, 0x91, 0xdf, + 0x5a, 0x2a, 0x88, 0x70, 0x89, 0xc6, 0x80, 0x1b, 0x40, 0x7d, 0x00, 0x86, 0x32, 0xe7, 0x10, 0x1e, 0x82, 0xaf, 0xb0, + 0x91, 0x18, 0xd9, 0x25, 0x18, 0xe3, 0x71, 0xdb, 0xc7, 0xaf, 0xc5, 0x5e, 0xd3, 0xec, 0x94, 0xef, 0x31, 0x36, 0xb1, + 0x79, 0x16, 0x1e, 0xd2, 0x07, 0x39, 0xf3, 0x9d, 0x19, 0x2b, 0xa2, 0x75, 0x7e, 0x2e, 0xec, 0x2f, 0x2d, 0x91, 0x60, + 0xd2, 0x52, 0xdb, 0x1b, 0x90, 0xf2, 0x89, 0x80, 0xa5, 0x34, 0x2f, 0x42, 0x5b, 0x35, 0xc8, 0x03, 0x25, 0xf4, 0x76, + 0x1a, 0xb5, 0xd7, 0x36, 0xeb, 0x85, 0x62, 0x5d, 0x70, 0xdc, 0x6a, 0x01, 0x43, 0x66, 0x38, 0x62, 0x03, 0xd6, 0x81, + 0x2b, 0x99, 0xa9, 0x66, 0xe2, 0x42, 0x9c, 0xd7, 0x99, 0xd1, 0x8c, 0x9f, 0xf3, 0xd4, 0x6e, 0xab, 0xcd, 0x95, 0x38, + 0x43, 0xff, 0xae, 0x5e, 0xbd, 0x99, 0xc6, 0xe8, 0x6e, 0x4c, 0x20, 0xdb, 0x4a, 0x1f, 0x0d, 0x7f, 0x3c, 0x9c, 0xa5, + 0x18, 0x06, 0xdc, 0x9f, 0x53, 0x15, 0xb4, 0xbf, 0x40, 0x79, 0x96, 0x97, 0x36, 0x76, 0x88, 0xd4, 0x64, 0xa0, 0x54, + 0x79, 0xbe, 0x97, 0x6c, 0x95, 0x48, 0xd0, 0x20, 0xb9, 0x91, 0x27, 0xcf, 0xe1, 0x0b, 0x32, 0xe2, 0x8f, 0xc6, 0xef, + 0x2f, 0x20, 0xc2, 0xce, 0x30, 0x93, 0x07, 0x06, 0x33, 0x77, 0x67, 0x03, 0x4f, 0x92, 0xd6, 0x9f, 0x8e, 0x12, 0xcd, + 0x97, 0x9b, 0xbb, 0x92, 0x4c, 0x71, 0x42, 0xf3, 0x93, 0x0f, 0x33, 0x54, 0x14, 0x97, 0x7f, 0xe0, 0x7a, 0xd6, 0x9e, + 0xa4, 0xc0, 0xf5, 0x7e, 0x08, 0x59, 0x11, 0xa9, 0xa8, 0x05, 0xf5, 0xd0, 0x8c, 0xc6, 0xf2, 0x43, 0x73, 0xfb, 0x45, + 0xaf, 0x08, 0x6c, 0xe2, 0x51, 0x8d, 0x9f, 0xf4, 0x5f, 0x3f, 0x30, 0x20, 0xe6, 0xbf, 0x4b, 0x62, 0x45, 0x55, 0xe3, + 0xdc, 0x65, 0x89, 0xaf, 0x60, 0xd5, 0x9f, 0x87, 0x44, 0x11, 0x64, 0xb7, 0x52, 0x84, 0x10, 0x9a, 0x2a, 0x62, 0xda, + 0x03, 0x38, 0xbd, 0x41, 0xdf, 0x51, 0x84, 0x85, 0x0a, 0x37, 0xa6, 0x9f, 0x90, 0x9a, 0x04, 0xa3, 0xd3, 0xd1, 0x40, + 0xe5, 0x80, 0xa4, 0x6f, 0x77, 0xbe, 0xbd, 0x47, 0x26, 0x59, 0xab, 0x5b, 0x99, 0xa4, 0x00, 0x81, 0x36, 0x7c, 0xc8, + 0xed, 0xed, 0x79, 0x9e, 0xe7, 0x2a, 0xab, 0xd7, 0xf1, 0x67, 0x1b, 0x0e, 0x13, 0xdb, 0xb1, 0x35, 0x3c, 0x78, 0xa2, + 0x85, 0x74, 0xfc, 0x45, 0x53, 0x34, 0xe8, 0x1a, 0xf1, 0x11, 0x05, 0xfa, 0x9c, 0x5d, 0x48, 0x1a, 0x37, 0xef, 0xca, + 0x75, 0xe0, 0x32, 0xb8, 0x29, 0x19, 0x1c, 0xd8, 0x9d, 0x0a, 0x99, 0x39, 0x35, 0x17, 0x54, 0x1e, 0x0f, 0xa4, 0xfe, + 0x90, 0xca, 0x8d, 0x59, 0xaa, 0x10, 0x1b, 0x54, 0xa7, 0x06, 0x7c, 0xd9, 0x13, 0x41, 0xcb, 0x13, 0xc8, 0xde, 0xab, + 0x21, 0xc5, 0x98, 0xe4, 0x72, 0x97, 0x03, 0xb6, 0xa1, 0x03, 0xd5, 0xa0, 0xe9, 0x18, 0x40, 0xb8, 0xbb, 0xf8, 0x96, + 0xf4, 0xbf, 0x7d, 0x9c, 0x7e, 0xaa, 0xee, 0x3c, 0x02, 0x4d, 0xb2, 0x56, 0x74, 0xbf, 0xd4, 0xa2, 0x21, 0x48, 0x78, + 0x1b, 0x1e, 0x22, 0xfe, 0xf4, 0x77, 0xe4, 0xd2, 0xc0, 0x5a, 0xd7, 0xa1, 0xff, 0x8e, 0x6c, 0xa6, 0x50, 0xa6, 0x15, + 0x52, 0xea, 0x54, 0x2d, 0x9c, 0x3b, 0x45, 0x59, 0x1a, 0x54, 0x3f, 0x48, 0x65, 0x85, 0x03, 0x09, 0x89, 0x44, 0x45, + 0x19, 0x26, 0x15, 0xaf, 0x69, 0x7d, 0x9f, 0x62, 0x13, 0x9e, 0xdd, 0xad, 0xfc, 0x90, 0x39, 0x88, 0x97, 0xc2, 0x1f, + 0x0f, 0xc6, 0xd7, 0x48, 0x6b, 0xa8, 0x67, 0x87, 0x87, 0x23, 0xcc, 0x51, 0xc4, 0xfa, 0x14, 0x65, 0xa8, 0x04, 0x72, + 0x29, 0xc5, 0x13, 0x86, 0x97, 0x98, 0xa8, 0xe8, 0x1c, 0x72, 0xd0, 0xe6, 0x7c, 0x80, 0x85, 0x87, 0x5e, 0xf0, 0xaf, + 0xe8, 0x21, 0x77, 0xaf, 0x8c, 0x88, 0xa6, 0x32, 0xa5, 0xdb, 0x3a, 0xe5, 0x1e, 0x3a, 0x5b, 0x04, 0xbd, 0x7d, 0xcf, + 0x3f, 0x7d, 0xa7, 0xef, 0xd4, 0xcf, 0x3e, 0xe5, 0x63, 0x7d, 0xca, 0xbf, 0xee, 0xfe, 0x63, 0xdb, 0x21, 0xff, 0x78, + 0xc9, 0xa6, 0x6d, 0x58, 0xd3, 0x6e, 0x4a, 0x54, 0xba, 0x4f, 0x14, 0x66, 0xe2, 0xa5, 0x18, 0xff, 0xb6, 0x28, 0x6b, + 0x7d, 0xb9, 0xb0, 0x82, 0x74, 0x32, 0x9b, 0xf0, 0xf5, 0xaf, 0x0b, 0x47, 0x08, 0x2d, 0x02, 0x3b, 0x49, 0xe9, 0x7c, + 0x92, 0xb5, 0x05, 0x34, 0x97, 0xa4, 0xb3, 0x84, 0x59, 0xc2, 0xd6, 0xf9, 0x04, 0xf4, 0x40, 0xb3, 0xa9, 0x5e, 0xe0, + 0x3a, 0x72, 0x0c, 0xc5, 0xf1, 0x6a, 0xe7, 0xa3, 0xdf, 0xde, 0x8a, 0x6f, 0x31, 0xd8, 0x85, 0xa5, 0x16, 0xd4, 0x8c, + 0x9a, 0x55, 0x0b, 0x38, 0x83, 0xb3, 0x78, 0x16, 0x14, 0xe8, 0xe7, 0x82, 0x21, 0xb8, 0x80, 0xd6, 0x06, 0xfa, 0x60, + 0xda, 0x78, 0x84, 0x45, 0x59, 0xe4, 0x1d, 0xf5, 0xe2, 0x66, 0x5d, 0xf5, 0xde, 0xdf, 0x56, 0x8c, 0x4a, 0xbc, 0xe5, + 0x7f, 0x05, 0x55, 0x22, 0xe9, 0xae, 0x90, 0xc8, 0xbb, 0x2a, 0x3e, 0x5e, 0x9b, 0xd6, 0x07, 0xb1, 0xac, 0xda, 0xb2, + 0xfe, 0x8e, 0xb0, 0x33, 0xe1, 0x71, 0xe8, 0x9e, 0xaa, 0x50, 0x10, 0xd3, 0x38, 0x77, 0xc9, 0xf7, 0x43, 0xbe, 0xea, + 0x7c, 0x37, 0xfc, 0x5b, 0x54, 0xcb, 0x5c, 0xcf, 0x24, 0x02, 0xa2, 0x9c, 0x74, 0xc1, 0xca, 0x61, 0x78, 0xe2, 0x9e, + 0xe6, 0x75, 0x91, 0x9c, 0x17, 0xd4, 0x33, 0x2c, 0x6e, 0xdf, 0xcb, 0x5f, 0x84, 0x6d, 0x8a, 0xca, 0x5f, 0xd8, 0x8c, + 0x3d, 0x1c, 0x51, 0x4d, 0xb7, 0x4f, 0xa8, 0xa0, 0x55, 0xa5, 0x1c, 0x4f, 0xbb, 0xf0, 0x22, 0x72, 0xb6, 0x37, 0xb0, + 0x53, 0xe6, 0xb6, 0x66, 0xdb, 0x1d, 0xe9, 0xef, 0x62, 0x15, 0x45, 0xec, 0x8a, 0xc3, 0x3e, 0xad, 0xa4, 0xeb, 0x8a, + 0x9a, 0xc3, 0x10, 0x8d, 0xe3, 0x0d, 0x14, 0xe5, 0xdb, 0x00, 0x1b, 0x1d, 0x20, 0xf4, 0xdb, 0x06, 0x4f, 0x80, 0x39, + 0xcc, 0xac, 0x36, 0x2e, 0x5e, 0xcd, 0x96, 0x4a, 0xee, 0xa9, 0xea, 0xfd, 0x5b, 0x0e, 0x8c, 0xbd, 0xcd, 0xfe, 0x29, + 0x46, 0x1f, 0xf1, 0xd9, 0xfb, 0xdb, 0x4f, 0x18, 0x82, 0x3c, 0x73, 0xe5, 0x7d, 0xdd, 0x83, 0x98, 0x94, 0xd9, 0x2a, + 0x35, 0x6d, 0x2b, 0x5c, 0x32, 0x08, 0xaf, 0x1d, 0x6d, 0x58, 0xa2, 0x4e, 0x61, 0x7f, 0xad, 0x92, 0xd5, 0x4d, 0x80, + 0xcf, 0x93, 0x5a, 0x62, 0x4e, 0x95, 0xc7, 0xfe, 0xea, 0xc5, 0x49, 0x26, 0x7f, 0x62, 0x02, 0x75, 0x06, 0x97, 0xb0, + 0x29, 0xcb, 0x1f, 0xc4, 0xfe, 0xdd, 0xec, 0x6f, 0x97, 0x46, 0xfe, 0xe6, 0x28, 0xb1, 0x08, 0x29, 0xac, 0x60, 0x5c, + 0xca, 0xd7, 0x4b, 0x3a, 0x80, 0x46, 0x36, 0x29, 0x46, 0x2f, 0x68, 0x5f, 0x7e, 0xee, 0xbe, 0xc2, 0xdc, 0x53, 0x32, + 0x76, 0x71, 0x30, 0xcb, 0xb5, 0x45, 0xe1, 0x48, 0x83, 0x65, 0xf0, 0xa2, 0xb7, 0x3a, 0xc2, 0x47, 0xe6, 0x88, 0x8f, + 0xcf, 0xfb, 0xe5, 0x82, 0x68, 0x51, 0x9a, 0x3f, 0x0e, 0x9e, 0x06, 0x74, 0x5c, 0x6a, 0xdb, 0xf4, 0x1e, 0x39, 0x75, + 0x40, 0xe8, 0x1a, 0x9b, 0x4c, 0x3f, 0x56, 0x28, 0x25, 0x35, 0x4b, 0xdb, 0xe9, 0xb1, 0xb1, 0x53, 0x53, 0xa2, 0xf8, + 0xae, 0xef, 0xba, 0x3b, 0x45, 0xb5, 0xae, 0x9f, 0x72, 0x44, 0x3e, 0xea, 0x82, 0x78, 0x35, 0x72, 0x6d, 0x87, 0x5c, + 0x7d, 0xd9, 0xa9, 0xea, 0x41, 0x5d, 0xec, 0x7f, 0xc8, 0x95, 0x9c, 0x66, 0xe3, 0x5b, 0x6f, 0xd0, 0xea, 0x26, 0x0d, + 0x3d, 0xe4, 0xc0, 0x02, 0x87, 0x14, 0xe1, 0x46, 0x0c, 0x6d, 0x6b, 0x24, 0x78, 0xac, 0x98, 0xc2, 0x83, 0xb8, 0x3f, + 0x8e, 0x4c, 0x80, 0xaa, 0xe8, 0x45, 0xa8, 0x8d, 0x6d, 0x0e, 0x3d, 0x03, 0x5c, 0x0f, 0xe9, 0xaf, 0x82, 0x9c, 0xef, + 0xe0, 0x6e, 0x30, 0x5a, 0x67, 0xcf, 0x8b, 0xf2, 0x81, 0x6a, 0x5c, 0x6f, 0xdb, 0xe1, 0x90, 0x5d, 0x63, 0xb7, 0x8b, + 0xa4, 0x76, 0x59, 0xe8, 0x33, 0x5b, 0x83, 0x91, 0x62, 0x6c, 0xbd, 0x05, 0xbe, 0xd9, 0x96, 0x41, 0x65, 0xd7, 0x7e, + 0x23, 0x29, 0xa1, 0xd1, 0xc5, 0xd0, 0x60, 0xbc, 0x81, 0x40, 0x55, 0xb0, 0x3c, 0x8b, 0x69, 0x2b, 0x61, 0x34, 0x1a, + 0xf7, 0xb4, 0x9f, 0x46, 0xf5, 0xb1, 0xfc, 0x91, 0x6e, 0xa6, 0xdc, 0x48, 0x97, 0x1f, 0xa6, 0xcb, 0x3d, 0x04, 0x53, + 0x61, 0xf9, 0x52, 0xad, 0x24, 0x02, 0x6e, 0xb9, 0x82, 0xd2, 0x60, 0x7f, 0x3f, 0xaf, 0xc0, 0xcc, 0x4b, 0x9e, 0x63, + 0x68, 0x78, 0xb1, 0x51, 0xb1, 0x71, 0xe2, 0xa7, 0xbb, 0x44, 0xcb, 0xa9, 0x19, 0x3c, 0x45, 0x3c, 0x20, 0xd5, 0x6d, + 0x0b, 0x5e, 0x1e, 0x3c, 0x46, 0x23, 0x4b, 0x57, 0xca, 0x2e, 0x93, 0x67, 0xf5, 0x50, 0x8e, 0x2a, 0x71, 0xd0, 0x4b, + 0xa4, 0x51, 0x57, 0xde, 0xfa, 0xc6, 0x4b, 0x60, 0x95, 0xb4, 0x4c, 0x4e, 0xbf, 0xef, 0x88, 0x34, 0x48, 0xb8, 0x94, + 0x42, 0xf1, 0x57, 0x89, 0x90, 0x7a, 0x6f, 0x0d, 0x1d, 0xc3, 0xc0, 0xfd, 0x75, 0x3e, 0xe2, 0xac, 0xf8, 0xec, 0x17, + 0x07, 0xd0, 0xa5, 0x2a, 0x1b, 0xa4, 0x5d, 0xac, 0xdc, 0x99, 0xef, 0xf7, 0xe8, 0x6d, 0x95, 0x62, 0xf1, 0x2d, 0xa3, + 0x9f, 0x58, 0xbc, 0x15, 0x32, 0xd8, 0x3d, 0x3f, 0xc0, 0x83, 0x1d, 0x9a, 0x48, 0x5d, 0x25, 0x04, 0x30, 0x41, 0x27, + 0xbd, 0x9c, 0xbc, 0x42, 0x14, 0xa1, 0x05, 0xee, 0xc9, 0xa1, 0x8d, 0x4a, 0x61, 0xbe, 0x82, 0xf0, 0x8f, 0x72, 0xf9, + 0x1e, 0x03, 0xd3, 0xe0, 0x12, 0x0d, 0xe5, 0x03, 0x22, 0xd2, 0x93, 0x91, 0x14, 0x81, 0x17, 0xf2, 0x3e, 0x11, 0x4c, + 0x5c, 0xa3, 0x75, 0x13, 0xbc, 0xa7, 0xc5, 0xd1, 0x4d, 0xf3, 0xd4, 0xc2, 0x8c, 0xf8, 0x19, 0x13, 0x46, 0xe1, 0x32, + 0xc4, 0x77, 0x16, 0x14, 0x9e, 0x60, 0xa7, 0x1a, 0x54, 0xaf, 0x8f, 0xda, 0xf4, 0x62, 0x37, 0xf8, 0x2b, 0x37, 0x1f, + 0xcf, 0x45, 0x3a, 0xf2, 0x42, 0x5c, 0xf2, 0xdc, 0xf9, 0x01, 0x9a, 0x10, 0x9e, 0xbb, 0x61, 0x77, 0x89, 0x0e, 0xac, + 0x93, 0xc9, 0x86, 0x15, 0x4d, 0xdc, 0x74, 0x02, 0x0c, 0xf2, 0xdc, 0x39, 0xb4, 0x6a, 0xe2, 0xe9, 0x3f, 0x55, 0xb9, + 0x5d, 0xf2, 0xbc, 0xc3, 0xee, 0x9a, 0xda, 0x35, 0x36, 0x06, 0x22, 0xe2, 0x62, 0x34, 0xc7, 0xd2, 0x4b, 0xfc, 0x1c, + 0xee, 0xdc, 0x7b, 0x5c, 0x3f, 0xc5, 0x18, 0x20, 0x1f, 0xde, 0x42, 0xb6, 0x80, 0x9e, 0xc5, 0x79, 0x9f, 0xa1, 0x17, + 0xde, 0xed, 0x25, 0x66, 0x44, 0x72, 0x7f, 0xa6, 0xf5, 0x91, 0x28, 0x47, 0x7a, 0x09, 0x29, 0x4e, 0x70, 0x94, 0xec, + 0x44, 0xc0, 0xfe, 0xbf, 0x10, 0x6d, 0x27, 0x88, 0xf2, 0x6d, 0xc2, 0xcd, 0xdd, 0xed, 0x58, 0xb9, 0x7d, 0xcb, 0x13, + 0x42, 0xa9, 0xf8, 0x84, 0x71, 0x88, 0x69, 0x27, 0x13, 0xbb, 0x23, 0x43, 0x44, 0x0f, 0x4b, 0x70, 0x1d, 0xb8, 0x19, + 0x7e, 0x74, 0xf6, 0x36, 0x8e, 0xe4, 0xe2, 0x73, 0xf5, 0xf3, 0x67, 0xdb, 0x60, 0x71, 0xed, 0xf6, 0xf2, 0x02, 0xc8, + 0x44, 0x3e, 0xea, 0x48, 0xbc, 0xa2, 0x01, 0x1a, 0xa7, 0xd7, 0x80, 0x11, 0xa7, 0x2c, 0x7d, 0x41, 0x87, 0x89, 0xca, + 0x23, 0xf5, 0xa0, 0x11, 0x3f, 0xc2, 0x90, 0xed, 0xb2, 0xac, 0x89, 0xb4, 0x30, 0xda, 0xb7, 0x40, 0xe1, 0x04, 0x58, + 0xb9, 0x0d, 0x0b, 0xf4, 0x6b, 0x21, 0x23, 0xaf, 0x81, 0x86, 0xfa, 0x7c, 0xf3, 0xda, 0xdf, 0x4f, 0xf4, 0x4f, 0x8b, + 0xe6, 0x90, 0x96, 0xd4, 0x23, 0xbf, 0x0f, 0xb6, 0xc7, 0xd6, 0xe2, 0xe7, 0x9d, 0xaf, 0x32, 0xa6, 0x25, 0x18, 0x91, + 0x77, 0x63, 0x08, 0xf9, 0x20, 0xc7, 0x2a, 0x08, 0x25, 0x5f, 0xab, 0x5a, 0x3b, 0xc4, 0x7a, 0xca, 0xdb, 0x14, 0x79, + 0xdb, 0x7c, 0x54, 0x51, 0x58, 0xad, 0xc0, 0xfe, 0xaa, 0xa1, 0xac, 0xc4, 0x0b, 0xfd, 0x57, 0x42, 0xa2, 0x0a, 0x89, + 0x45, 0x07, 0x3d, 0x12, 0xce, 0x3f, 0x08, 0x51, 0xd0, 0xe5, 0x96, 0x6a, 0xd9, 0x6e, 0x5f, 0x1a, 0x0a, 0x57, 0x81, + 0x58, 0x60, 0xb7, 0xf1, 0xbc, 0xad, 0xe3, 0x45, 0x1c, 0x97, 0x99, 0xb5, 0x6f, 0xbc, 0xe2, 0x2b, 0xec, 0x05, 0x81, + 0xfd, 0x1a, 0xce, 0x9a, 0xfc, 0xdf, 0xcf, 0xf0, 0x9a, 0x99, 0xc5, 0xcd, 0xc5, 0xf0, 0x6f, 0x67, 0xb3, 0xfc, 0x62, + 0x78, 0xb3, 0xd9, 0x21, 0xb5, 0x98, 0xd3, 0x68, 0xda, 0x7c, 0x78, 0xfd, 0xf0, 0xf2, 0x20, 0x9d, 0xde, 0xf3, 0x93, + 0xbc, 0x75, 0x76, 0x71, 0x0c, 0x59, 0xf0, 0x09, 0x3f, 0x6b, 0xb0, 0x39, 0xfb, 0xaf, 0xad, 0xd0, 0x1e, 0xd7, 0xde, + 0x33, 0xbb, 0x12, 0xab, 0xd3, 0xd8, 0xeb, 0xed, 0xbe, 0x9a, 0x02, 0xfe, 0x13, 0x81, 0x26, 0xbe, 0xf2, 0xc9, 0xa4, + 0x14, 0x07, 0x40, 0xa0, 0xba, 0x35, 0xf8, 0x7b, 0x18, 0x8c, 0x32, 0x92, 0xf1, 0xf6, 0x13, 0x92, 0xc8, 0xc6, 0xe1, + 0xe9, 0xdc, 0x42, 0xb1, 0x1e, 0xe9, 0xfb, 0x3c, 0xcd, 0xb4, 0x7e, 0x5b, 0x46, 0xd5, 0xa9, 0x81, 0x2c, 0x68, 0x9c, + 0x69, 0x10, 0xac, 0x7f, 0xdb, 0x58, 0x9d, 0x59, 0xf8, 0x66, 0x21, 0xa2, 0x59, 0x16, 0xff, 0x78, 0x4e, 0xb6, 0xd0, + 0xa0, 0xc0, 0x8f, 0x9a, 0x66, 0xde, 0xb5, 0x6e, 0x75, 0x01, 0x21, 0xef, 0x96, 0xa7, 0xf5, 0xa5, 0x3f, 0xff, 0x82, + 0x35, 0xbb, 0xf1, 0x5f, 0x5d, 0x8f, 0xd6, 0x8b, 0x10, 0x25, 0x5b, 0x81, 0x00, 0x71, 0xb1, 0x8d, 0xe3, 0x2d, 0x79, + 0xe3, 0x34, 0x17, 0xc9, 0x3c, 0x7c, 0x75, 0x92, 0x66, 0x05, 0xa1, 0x9a, 0xdf, 0x26, 0xf1, 0x0a, 0xd4, 0x59, 0x89, + 0x8f, 0x8a, 0x77, 0xe3, 0xde, 0xf5, 0xc4, 0xf6, 0xbf, 0xf2, 0x25, 0x14, 0xc4, 0xf7, 0xfb, 0x16, 0xe8, 0x86, 0x9f, + 0x30, 0xc5, 0xdb, 0x8f, 0xd7, 0xe3, 0x37, 0xf9, 0xad, 0xc0, 0x3d, 0x16, 0x78, 0x67, 0xbd, 0x34, 0x97, 0xf2, 0x24, + 0x41, 0x66, 0x05, 0xae, 0xb8, 0xec, 0x07, 0x0f, 0x96, 0x2d, 0x4d, 0x80, 0x66, 0xab, 0xc8, 0x00, 0x19, 0xca, 0x25, + 0x08, 0x69, 0x83, 0x8c, 0xfe, 0x2d, 0x88, 0xa2, 0x24, 0xc7, 0xa7, 0xb3, 0x27, 0xd1, 0x0d, 0x95, 0x3e, 0x39, 0x32, + 0xb0, 0xb2, 0x0e, 0x50, 0x4b, 0x32, 0x54, 0x88, 0x84, 0x90, 0x64, 0x02, 0x60, 0x9f, 0x14, 0x1a, 0x0a, 0x9f, 0x6b, + 0x39, 0xed, 0xfc, 0xc2, 0xb7, 0x4c, 0x90, 0x78, 0x4c, 0x8e, 0x5a, 0xc9, 0x84, 0xb6, 0x7b, 0xad, 0xf9, 0xe8, 0xee, + 0xe2, 0xa9, 0x5d, 0x1c, 0x63, 0x3e, 0xf2, 0x3f, 0x4a, 0x73, 0x22, 0xf2, 0xb5, 0x0e, 0xc0, 0x4a, 0xde, 0x0a, 0x94, + 0x2d, 0x6f, 0x98, 0x17, 0x58, 0xfc, 0x56, 0x4b, 0x76, 0xf5, 0x0c, 0x02, 0xb4, 0x21, 0x9c, 0xb4, 0xe3, 0x5c, 0xe1, + 0xba, 0x99, 0x62, 0x0d, 0xe5, 0xf5, 0x0a, 0x47, 0x15, 0x9a, 0x26, 0xc6, 0x74, 0x73, 0x2d, 0x7a, 0x31, 0xf5, 0x9a, + 0x7a, 0x42, 0x92, 0xbc, 0x08, 0x67, 0xd5, 0x9e, 0xae, 0xfd, 0x67, 0x06, 0x48, 0x3d, 0x27, 0x17, 0xca, 0x36, 0x17, + 0xe3, 0xbb, 0x79, 0xe3, 0x59, 0xc6, 0xcd, 0xbd, 0x57, 0x6b, 0xaf, 0x9e, 0x67, 0xb7, 0x98, 0x8f, 0x25, 0xe4, 0xd3, + 0x0e, 0x31, 0x37, 0xb2, 0x50, 0x72, 0x84, 0x71, 0xd7, 0x86, 0x21, 0x13, 0x37, 0x2e, 0x2c, 0x98, 0x90, 0x1e, 0x1b, + 0x89, 0x71, 0x90, 0x35, 0xdf, 0xd5, 0x7e, 0x71, 0x7c, 0xfb, 0xa3, 0xb8, 0x48, 0x0b, 0xf6, 0xf0, 0xa4, 0xb3, 0x5f, + 0xf9, 0x4c, 0xa3, 0x6e, 0x23, 0x47, 0x02, 0x51, 0x0c, 0x44, 0x02, 0xba, 0x56, 0xa9, 0xd0, 0xcb, 0x8a, 0x79, 0xa8, + 0xc0, 0x67, 0x2d, 0xb4, 0x51, 0xc1, 0xaa, 0x57, 0xf8, 0x89, 0x08, 0x65, 0xa6, 0xd6, 0x6b, 0x80, 0x5c, 0x64, 0x6b, + 0xad, 0x9f, 0xf5, 0x76, 0x6d, 0xb8, 0x9c, 0x27, 0xf0, 0x57, 0xef, 0xe2, 0xd6, 0xc7, 0x04, 0x5d, 0x6e, 0xed, 0x9f, + 0x68, 0xcf, 0x32, 0x46, 0x12, 0x55, 0x9e, 0xc3, 0xd3, 0x0a, 0xe4, 0xeb, 0x8e, 0x34, 0x5e, 0x62, 0x43, 0xf6, 0x16, + 0xa5, 0x9f, 0x52, 0xc6, 0xbd, 0xfc, 0xa4, 0xd8, 0x03, 0xf6, 0xdc, 0x03, 0x82, 0x35, 0xfb, 0x5a, 0x5f, 0x6e, 0x4d, + 0xd3, 0x60, 0xff, 0xa3, 0x03, 0x4f, 0x40, 0xd9, 0xbe, 0x1c, 0x47, 0x18, 0x8f, 0xdc, 0x92, 0x31, 0x65, 0x08, 0x39, + 0xc1, 0x62, 0xbb, 0xd7, 0x1d, 0x6b, 0x68, 0x39, 0x95, 0x28, 0x16, 0x49, 0xee, 0x7e, 0x94, 0xce, 0x68, 0xff, 0xd4, + 0x4e, 0x25, 0xb4, 0xf5, 0xb7, 0x9a, 0x9d, 0x14, 0x4d, 0xd7, 0xf5, 0x0e, 0xe8, 0x3c, 0x4a, 0x94, 0x4f, 0x2c, 0x8f, + 0x5d, 0x7e, 0x79, 0xb7, 0x6b, 0x64, 0xbb, 0x29, 0xb7, 0xb5, 0x37, 0x1a, 0xa9, 0x18, 0x69, 0xe8, 0x81, 0xed, 0x70, + 0xd9, 0x29, 0x6d, 0x02, 0x22, 0x64, 0x54, 0x2f, 0x8e, 0xa4, 0x96, 0xfa, 0x42, 0x9c, 0x75, 0xe7, 0x23, 0xad, 0x68, + 0x2f, 0x82, 0x02, 0x10, 0x5a, 0x1d, 0xa9, 0x92, 0x35, 0x5c, 0x97, 0x11, 0x6c, 0x0f, 0xe3, 0xf5, 0x0d, 0x14, 0x55, + 0x79, 0x7a, 0x2d, 0xd8, 0x8a, 0x1f, 0xc7, 0xa6, 0xf0, 0xb0, 0x8b, 0x0c, 0xf6, 0xe0, 0x66, 0x8e, 0x13, 0x3c, 0x5d, + 0x9b, 0xd3, 0x92, 0x3d, 0xd9, 0x20, 0xb3, 0xe6, 0xeb, 0xdb, 0x21, 0x5e, 0xb8, 0x71, 0x3d, 0x2c, 0xd9, 0x25, 0x1c, + 0x5c, 0xfa, 0x04, 0x3e, 0xf8, 0xb5, 0x1d, 0xb3, 0x41, 0xa1, 0xab, 0xcb, 0x09, 0xf6, 0x92, 0xc6, 0xe7, 0xf9, 0x6f, + 0x66, 0x73, 0x51, 0xb2, 0x02, 0xac, 0xbd, 0xba, 0x6f, 0x11, 0x2e, 0x73, 0x07, 0x5f, 0xfe, 0x3f, 0x75, 0xd4, 0x76, + 0xf3, 0xf9, 0x2d, 0x9c, 0x9b, 0x1c, 0x3c, 0xc3, 0x21, 0xea, 0xf2, 0x40, 0xae, 0x5c, 0xbf, 0xfa, 0x4f, 0xa0, 0xe4, + 0x9d, 0x4e, 0x9a, 0x7f, 0xdd, 0x77, 0x61, 0x31, 0x36, 0x76, 0xd9, 0x3e, 0xe2, 0x84, 0xd1, 0x75, 0xa2, 0xd0, 0x7e, + 0xcf, 0xc4, 0xb6, 0x1a, 0x64, 0x04, 0x8b, 0x90, 0xd7, 0x77, 0xb6, 0x00, 0xf4, 0xfd, 0x65, 0x0f, 0x8b, 0xb7, 0x7e, + 0x45, 0xe2, 0x4d, 0xb1, 0xf0, 0xef, 0x47, 0x64, 0xe1, 0xda, 0xfe, 0x8a, 0x03, 0x04, 0xdb, 0x5a, 0xfb, 0x5a, 0xdc, + 0x72, 0xfb, 0xe8, 0x04, 0x20, 0x28, 0x61, 0x2d, 0x9e, 0x44, 0xed, 0x5f, 0x22, 0x23, 0x52, 0xf7, 0x19, 0x33, 0x35, + 0x4c, 0xc4, 0x9d, 0x15, 0xc7, 0xb0, 0xd2, 0x7d, 0x74, 0xe5, 0x36, 0xb9, 0x1a, 0x44, 0xd1, 0x1e, 0x9a, 0x88, 0x3b, + 0x36, 0x04, 0x79, 0x4f, 0xc8, 0x63, 0x81, 0xaa, 0xac, 0xc2, 0x96, 0x47, 0x29, 0x82, 0xe1, 0x39, 0x74, 0x01, 0xb6, + 0x52, 0xd4, 0x3a, 0x73, 0xc9, 0xe2, 0xc4, 0x81, 0xd7, 0x8f, 0x07, 0xbc, 0x1a, 0xdd, 0xcd, 0x91, 0x40, 0xdc, 0x49, + 0xb2, 0x5b, 0x50, 0xf5, 0xe6, 0x65, 0xe8, 0x56, 0x3c, 0xaf, 0x14, 0x77, 0xa3, 0xad, 0xbe, 0x0d, 0x21, 0x22, 0x0e, + 0xd1, 0xae, 0x1d, 0xa5, 0x07, 0x74, 0x20, 0x8b, 0x2e, 0xaa, 0x9a, 0x94, 0xe0, 0xbf, 0x29, 0xb3, 0x36, 0xa1, 0x86, + 0x09, 0x05, 0x05, 0xe7, 0x6c, 0xdc, 0x4a, 0xf8, 0xf4, 0x46, 0xc6, 0xdc, 0x52, 0xe0, 0x55, 0x68, 0x6e, 0xaa, 0x03, + 0xb9, 0x22, 0x1a, 0x74, 0xc9, 0xb5, 0xed, 0x32, 0xc7, 0x87, 0x59, 0xbb, 0xf0, 0xfc, 0xb9, 0xd8, 0x2f, 0x95, 0x52, + 0xe4, 0xa5, 0xa0, 0x10, 0x71, 0x6a, 0xa3, 0x12, 0x9a, 0xfa, 0x00, 0xd6, 0x74, 0x44, 0x70, 0x67, 0x3c, 0x7a, 0x87, + 0x48, 0xf2, 0x3f, 0x95, 0x52, 0x67, 0x23, 0x79, 0x04, 0x4c, 0xeb, 0x81, 0x49, 0xfd, 0x92, 0x6d, 0x81, 0xe0, 0xf0, + 0x40, 0x7f, 0x0c, 0x14, 0xc9, 0x13, 0x89, 0x58, 0x50, 0xc7, 0xd3, 0xa8, 0x6f, 0xec, 0x4b, 0xb5, 0x27, 0xf7, 0x76, + 0x7c, 0xd6, 0x1e, 0x7b, 0x88, 0x24, 0x63, 0x7e, 0x10, 0x41, 0x12, 0x24, 0xc2, 0x18, 0x8b, 0x3c, 0xc4, 0x40, 0x34, + 0x3f, 0xb9, 0xc1, 0xe0, 0x54, 0x53, 0x6d, 0xfd, 0x58, 0xa2, 0x23, 0x10, 0xa8, 0xcb, 0x34, 0xaa, 0xd8, 0xaa, 0x4c, + 0x10, 0xcc, 0x67, 0xfd, 0xbb, 0x76, 0x44, 0x60, 0xa6, 0x1d, 0x03, 0xb4, 0xc9, 0x1b, 0xcc, 0x47, 0x44, 0x66, 0xcb, + 0xce, 0x27, 0x89, 0x09, 0xa6, 0xae, 0xda, 0x23, 0xb3, 0x71, 0xc6, 0xc9, 0xa6, 0xe9, 0xd4, 0xee, 0xaa, 0x32, 0xb8, + 0x08, 0x2f, 0x5e, 0xa2, 0x11, 0x80, 0xe8, 0x5a, 0xbe, 0x16, 0x9e, 0x1c, 0x08, 0x20, 0xcc, 0x2d, 0x0d, 0xfc, 0x96, + 0x69, 0xfb, 0x27, 0x5d, 0xab, 0x1b, 0x22, 0x36, 0x0a, 0x11, 0xfe, 0xd3, 0x04, 0xd9, 0xf5, 0x5b, 0xab, 0x1d, 0xfb, + 0xfb, 0x4e, 0x5b, 0xf6, 0x5b, 0x8b, 0x59, 0x4a, 0x43, 0x17, 0xc2, 0x86, 0x61, 0x6b, 0x35, 0x14, 0x56, 0xcb, 0x59, + 0x73, 0xe8, 0x80, 0xcc, 0xbc, 0x10, 0x90, 0x65, 0xee, 0x57, 0x3e, 0x42, 0x67, 0x07, 0xf6, 0x3f, 0xf2, 0x9d, 0xe4, + 0x1c, 0x1b, 0x76, 0x88, 0xaf, 0x77, 0xc1, 0xa2, 0x89, 0xac, 0x24, 0x94, 0x8f, 0xa0, 0x7c, 0xae, 0x5d, 0x5a, 0x47, + 0x6a, 0xe7, 0x46, 0x87, 0x46, 0x06, 0xfc, 0xc1, 0x98, 0x09, 0x1c, 0x88, 0x40, 0x2f, 0x05, 0xdd, 0x87, 0xef, 0x3b, + 0x26, 0xd3, 0x6f, 0x0d, 0x04, 0xff, 0xfe, 0x8d, 0xfb, 0x2d, 0x25, 0x60, 0x09, 0x88, 0x3b, 0x2d, 0xa0, 0x1b, 0xc4, + 0xfc, 0x7a, 0x69, 0x88, 0xc9, 0x8b, 0x43, 0x1b, 0xbd, 0x2c, 0x64, 0x78, 0xed, 0xc1, 0xc3, 0xe7, 0x99, 0xf7, 0xb2, + 0x53, 0x71, 0x86, 0x6b, 0xb3, 0x9b, 0x5e, 0xe2, 0xb6, 0xe3, 0xd7, 0x23, 0xbf, 0x45, 0xdc, 0xc0, 0xcd, 0x6e, 0x50, + 0xe6, 0x21, 0xcc, 0x3c, 0x0b, 0xdc, 0xa3, 0x61, 0x4a, 0x7f, 0xc3, 0x42, 0xac, 0x1b, 0xb2, 0xf5, 0x99, 0xc1, 0xea, + 0xb6, 0x8a, 0x41, 0x2c, 0x4f, 0x72, 0x3c, 0xc1, 0xc8, 0x42, 0xba, 0x61, 0x91, 0x93, 0x84, 0x37, 0x49, 0x1c, 0x71, + 0xaf, 0x8d, 0xd9, 0x56, 0x60, 0xea, 0x10, 0x1a, 0x72, 0x7b, 0xfc, 0xbe, 0x0b, 0x09, 0x66, 0x1e, 0x67, 0xa9, 0x8a, + 0x46, 0xea, 0xed, 0x5f, 0x3c, 0xb1, 0x47, 0xf5, 0x11, 0x6a, 0x7b, 0xcb, 0x92, 0xdb, 0xd5, 0xbf, 0xf7, 0xad, 0xd3, + 0x80, 0x5e, 0x30, 0x73, 0xc3, 0x70, 0xdc, 0x37, 0x36, 0x00, 0xd9, 0x48, 0x0a, 0x0c, 0x84, 0xd5, 0x08, 0x56, 0xd2, + 0x62, 0xec, 0xe9, 0x5d, 0xfd, 0xec, 0x18, 0x01, 0x2e, 0x81, 0xf5, 0x63, 0xa5, 0xb0, 0xe1, 0x14, 0xec, 0x7a, 0x03, + 0xf4, 0xdd, 0x76, 0x7b, 0x14, 0x4a, 0x93, 0x1b, 0x1a, 0x78, 0x9f, 0x0d, 0x04, 0x36, 0xfd, 0x14, 0xcf, 0xa1, 0x77, + 0x5d, 0xbf, 0xee, 0xfd, 0xbd, 0x31, 0x10, 0x21, 0xad, 0x91, 0xa0, 0xb5, 0xef, 0x7b, 0x2f, 0x69, 0x66, 0x65, 0x94, + 0xa1, 0x29, 0xdb, 0x54, 0xfb, 0x69, 0x38, 0xb6, 0x2d, 0x8b, 0x40, 0xed, 0x00, 0xaf, 0x5c, 0xe7, 0xe0, 0x3a, 0x53, + 0x14, 0xba, 0x12, 0x1f, 0x4a, 0x27, 0x78, 0xb7, 0x8d, 0x62, 0x12, 0x10, 0xe7, 0x07, 0x2b, 0xb8, 0x41, 0xc8, 0x59, + 0x23, 0x04, 0xd6, 0x66, 0xbb, 0xeb, 0x23, 0xd3, 0x95, 0xf8, 0xb5, 0x07, 0x59, 0x43, 0xa5, 0xa8, 0x14, 0xb8, 0xb4, + 0x38, 0x25, 0x79, 0xd2, 0x60, 0x78, 0x5d, 0x3f, 0xad, 0x69, 0x55, 0x25, 0xbe, 0xd6, 0xc5, 0x4e, 0xa9, 0x80, 0xb9, + 0xcf, 0xe9, 0xa9, 0x75, 0xa4, 0x78, 0x6b, 0xad, 0xad, 0x4f, 0x18, 0xe6, 0xf6, 0xde, 0x69, 0x0f, 0x20, 0x7f, 0xcc, + 0x67, 0x26, 0xc1, 0xc0, 0x88, 0x30, 0xc0, 0x5b, 0xa2, 0x97, 0x33, 0x26, 0x4f, 0xd0, 0x4c, 0x5f, 0xdc, 0xa3, 0xdc, + 0xbb, 0xdc, 0x7d, 0xca, 0x37, 0x2a, 0xb3, 0x47, 0x37, 0x5d, 0x04, 0xb4, 0xd6, 0x4d, 0x94, 0x1a, 0x1e, 0xc7, 0xb5, + 0xcb, 0x0b, 0xb1, 0x94, 0xc4, 0xeb, 0x10, 0xcd, 0xbf, 0xcb, 0x4f, 0x0e, 0x9b, 0x94, 0x95, 0x25, 0xdf, 0x19, 0x4b, + 0xc3, 0x8f, 0x15, 0xf2, 0xc2, 0x46, 0xaa, 0x01, 0x14, 0x57, 0x7a, 0x1d, 0xed, 0x64, 0xed, 0x5d, 0x56, 0x41, 0xa3, + 0x54, 0xc8, 0xd1, 0xa3, 0x35, 0x70, 0x94, 0x3a, 0x21, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xaf, 0x0c, 0x4e, 0x01, 0xb5, + 0xf2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x9a, 0xfc, 0x4c, 0xde, 0x8d, 0xc0, 0x78, 0xca, 0x07, 0x9e, 0xb8, 0xb0, 0x4c, + 0xfc, 0xb7, 0xec, 0x0f, 0x10, 0x95, 0x4c, 0x06, 0x15, 0x08, 0x4c, 0x83, 0x5d, 0x7c, 0x2d, 0x8d, 0xd4, 0x7a, 0x08, + 0xc1, 0xc9, 0xd5, 0x46, 0x7f, 0x30, 0xeb, 0x6b, 0x40, 0xa9, 0x7a, 0x83, 0x8a, 0x46, 0xec, 0xca, 0xf6, 0xd3, 0xbc, + 0x3e, 0x98, 0xa8, 0x7d, 0xa3, 0x81, 0x1b, 0xb6, 0xf9, 0xd5, 0x1e, 0xc5, 0xae, 0x8d, 0xe7, 0x4b, 0x60, 0x13, 0xb5, + 0xbc, 0x65, 0x52, 0x14, 0x1c, 0xda, 0x34, 0xa8, 0x76, 0x04, 0x23, 0x66, 0xba, 0x83, 0xce, 0x5b, 0xdb, 0x20, 0x3a, + 0x1d, 0x9c, 0x46, 0xd0, 0x19, 0x8c, 0x8b, 0x53, 0x5b, 0x35, 0x42, 0x49, 0x8c, 0x2f, 0xc7, 0xd0, 0x2f, 0xb2, 0x78, + 0xa3, 0x66, 0xda, 0x00, 0x5d, 0x49, 0x05, 0xf3, 0x6c, 0xc4, 0x4c, 0x0a, 0xb7, 0xec, 0xb9, 0x5d, 0x8a, 0xff, 0xa5, + 0x3b, 0xd7, 0xf7, 0x3c, 0x11, 0xe4, 0x03, 0x59, 0x3a, 0x0e, 0xfe, 0xb5, 0x98, 0xe1, 0xe7, 0x19, 0x8c, 0x5e, 0x64, + 0xd6, 0xc6, 0x2c, 0xc9, 0x17, 0x7c, 0x67, 0xf8, 0xa5, 0x06, 0x93, 0x9f, 0xb0, 0x9c, 0x21, 0xfa, 0x1a, 0x04, 0x38, + 0x72, 0xb5, 0xeb, 0x69, 0xc3, 0x78, 0x07, 0x8b, 0x17, 0xc5, 0x02, 0x51, 0xd4, 0xfb, 0x6a, 0x8e, 0xc3, 0xe2, 0x9c, + 0xa4, 0x04, 0x33, 0x9b, 0x1a, 0x49, 0x21, 0x64, 0xef, 0x9b, 0x93, 0x57, 0x56, 0x1a, 0x52, 0x9c, 0xc0, 0xcb, 0x81, + 0x5e, 0x23, 0xd2, 0xf1, 0xb1, 0x3a, 0x6b, 0x28, 0x4e, 0x1a, 0x99, 0x62, 0x36, 0xb1, 0x90, 0xce, 0xaa, 0x07, 0x1b, + 0xf3, 0x69, 0x91, 0x2b, 0xaf, 0xeb, 0x08, 0x7f, 0xad, 0xc2, 0x70, 0x96, 0x5e, 0x6f, 0xbe, 0x18, 0x06, 0x1d, 0xfe, + 0xaf, 0xd5, 0x84, 0x6f, 0xf0, 0x6d, 0x3f, 0x5f, 0x44, 0x44, 0xa8, 0xca, 0x0f, 0x74, 0xa2, 0x1d, 0xea, 0xe8, 0x34, + 0xf4, 0xd0, 0xcc, 0x56, 0x50, 0xb0, 0x48, 0xfb, 0x7d, 0x37, 0xbd, 0xf5, 0x35, 0x39, 0x7b, 0xe7, 0xba, 0xa6, 0x35, + 0xc1, 0xfc, 0xf8, 0x35, 0xd0, 0x9a, 0x8d, 0x84, 0x93, 0xe5, 0xf7, 0xc8, 0xde, 0x6c, 0xaf, 0x76, 0x67, 0xd4, 0xbe, + 0x3e, 0x1a, 0xde, 0x34, 0x8f, 0x19, 0x1f, 0x65, 0x93, 0x26, 0x6a, 0x3a, 0x73, 0x2d, 0xe0, 0x73, 0x6a, 0xea, 0x4e, + 0x24, 0x3a, 0x70, 0x76, 0xb5, 0x3c, 0xc5, 0x6f, 0x45, 0x64, 0xfa, 0x35, 0x89, 0xea, 0x96, 0x66, 0x50, 0xe4, 0x52, + 0x5a, 0xa8, 0xba, 0xad, 0x2a, 0x80, 0x7d, 0x8d, 0xa8, 0x19, 0xa8, 0x31, 0x0b, 0xdd, 0x29, 0x1a, 0x21, 0x8d, 0xb5, + 0x8c, 0xed, 0x87, 0x9a, 0x76, 0xa5, 0xaa, 0x1e, 0xdb, 0x25, 0x0e, 0x45, 0x03, 0x34, 0x2d, 0xcc, 0xf5, 0x6f, 0x76, + 0x75, 0xb3, 0x6d, 0x4b, 0xbd, 0x41, 0x5c, 0xf2, 0x9f, 0x87, 0x2d, 0xac, 0x9d, 0x29, 0x85, 0xc3, 0x15, 0xad, 0xe8, + 0x91, 0x6c, 0x1c, 0xb4, 0x0a, 0x83, 0xa8, 0x51, 0x65, 0xda, 0x88, 0x61, 0x44, 0xc2, 0x08, 0x85, 0x42, 0xe1, 0x3e, + 0x62, 0x5d, 0x6c, 0xca, 0xa3, 0x87, 0xd2, 0xea, 0x92, 0x1f, 0xb3, 0x58, 0xa3, 0x79, 0x5a, 0x7b, 0x2c, 0x64, 0xa9, + 0xc3, 0xc7, 0x2b, 0xc1, 0xe8, 0xf7, 0xcb, 0x84, 0x56, 0x6e, 0x31, 0x41, 0xa9, 0x0e, 0x24, 0x76, 0x3b, 0x79, 0x8b, + 0xf4, 0x63, 0x8b, 0x42, 0x12, 0xb2, 0x3f, 0xbd, 0x2c, 0x93, 0xa7, 0x8a, 0xe1, 0x55, 0xe4, 0x2c, 0x47, 0x09, 0xf1, + 0x0e, 0xfc, 0xa4, 0x5f, 0x7f, 0x92, 0x7a, 0xad, 0xba, 0xad, 0x75, 0x54, 0xd4, 0xce, 0x6d, 0xe9, 0x86, 0x71, 0x9d, + 0x0c, 0xaa, 0xe0, 0x06, 0x4c, 0xd2, 0xe8, 0x5b, 0x27, 0xa8, 0x4f, 0x31, 0x9a, 0xf2, 0x6a, 0x07, 0x65, 0x2d, 0xc3, + 0x60, 0x8d, 0xf1, 0x61, 0xf8, 0xc0, 0x64, 0xc6, 0x18, 0x61, 0x6c, 0xc3, 0x1c, 0xf9, 0x6c, 0xfa, 0xeb, 0x17, 0x42, + 0xea, 0x4d, 0x12, 0x11, 0x81, 0x7c, 0x90, 0x7c, 0x30, 0x22, 0xfd, 0xa7, 0x25, 0x56, 0x3b, 0xbc, 0x70, 0x48, 0x9f, + 0xc4, 0x16, 0x0e, 0x84, 0xcd, 0xfa, 0xd1, 0x6f, 0x98, 0x64, 0xde, 0xbe, 0x38, 0x41, 0x7e, 0x09, 0x6e, 0xd8, 0xde, + 0x6a, 0x08, 0xaa, 0x18, 0xad, 0x10, 0xc4, 0x0a, 0x1a, 0x21, 0x9e, 0xc0, 0xf9, 0x26, 0x63, 0xd5, 0xab, 0x25, 0x2e, + 0x73, 0x45, 0x83, 0x7f, 0xf6, 0x6d, 0x5a, 0x24, 0x3d, 0x88, 0xf7, 0x03, 0x59, 0xcf, 0xb0, 0x87, 0xa0, 0xc7, 0xc2, + 0x8a, 0xe4, 0xbb, 0x42, 0x96, 0xae, 0xe3, 0xd3, 0x49, 0xaa, 0xf7, 0xa4, 0x5f, 0x3f, 0xc0, 0x1e, 0xb4, 0xa9, 0x2d, + 0x34, 0x7f, 0x85, 0xaa, 0x0a, 0xf3, 0x7a, 0x33, 0xca, 0xa3, 0x25, 0x9b, 0xee, 0x08, 0x74, 0x10, 0x08, 0xb5, 0xd6, + 0x4b, 0x03, 0x8c, 0xe3, 0xfb, 0xb0, 0x19, 0x3d, 0x7e, 0x5d, 0xc4, 0x84, 0xab, 0x97, 0x2d, 0x45, 0x69, 0x93, 0x46, + 0x8f, 0xfb, 0xae, 0x59, 0x76, 0x19, 0x22, 0x88, 0xc4, 0x1f, 0x47, 0xd0, 0x66, 0x5c, 0x0b, 0x17, 0xd1, 0x09, 0x86, + 0x96, 0x2b, 0x9e, 0xb8, 0x47, 0xdd, 0x2f, 0xbb, 0xe7, 0xdb, 0xe6, 0x49, 0x0c, 0x58, 0x8a, 0xf8, 0xae, 0xac, 0xcd, + 0x39, 0x94, 0xa2, 0x74, 0x9b, 0xc0, 0x2c, 0x47, 0x7a, 0x8c, 0x47, 0xf2, 0x48, 0xd4, 0x01, 0x83, 0x68, 0x54, 0x7c, + 0x67, 0x65, 0xe0, 0x6e, 0xad, 0xb5, 0xf8, 0xf2, 0xf7, 0x7e, 0xfd, 0x7a, 0xb7, 0x42, 0xbd, 0x0c, 0x5e, 0x4e, 0xed, + 0x19, 0xef, 0xbc, 0x20, 0xa5, 0xbe, 0x88, 0xc1, 0xeb, 0xc7, 0xbc, 0x8a, 0x66, 0xdf, 0x35, 0x04, 0xa1, 0x85, 0xcb, + 0x7f, 0x0b, 0x8f, 0x3a, 0x2d, 0xd3, 0xa5, 0xa7, 0xaf, 0xa6, 0x9b, 0x4e, 0x97, 0xef, 0xe8, 0xc1, 0xad, 0x10, 0x21, + 0x61, 0x54, 0x63, 0xed, 0x93, 0x73, 0x8b, 0xc9, 0x97, 0xd1, 0xda, 0xa5, 0x55, 0x51, 0xc1, 0xe7, 0x1c, 0xdd, 0x0d, + 0xaa, 0x5b, 0xb8, 0xa9, 0x72, 0xfb, 0xe8, 0xad, 0xa8, 0xa2, 0xa1, 0x87, 0x0b, 0xa7, 0x44, 0x12, 0x85, 0xc8, 0x4b, + 0x98, 0xd8, 0x7d, 0x37, 0xa4, 0x81, 0x71, 0x75, 0x75, 0x4a, 0x75, 0x83, 0xc7, 0xd0, 0xc3, 0x10, 0x24, 0xae, 0xd9, + 0xf9, 0xff, 0xd2, 0xeb, 0xc1, 0x9b, 0x97, 0x3e, 0x25, 0x99, 0x17, 0xfe, 0x5d, 0x5a, 0xb8, 0xc5, 0x17, 0xfc, 0x8c, + 0x96, 0xa0, 0x65, 0xcb, 0xa3, 0xb2, 0x03, 0xeb, 0xa1, 0x3d, 0xd0, 0xbf, 0xae, 0x27, 0x9b, 0x55, 0x00, 0x5a, 0x5b, + 0x9e, 0x64, 0x34, 0x31, 0x7a, 0x72, 0xde, 0xa1, 0x50, 0x44, 0x42, 0x0e, 0xa3, 0x44, 0xad, 0x75, 0x20, 0xc3, 0x55, + 0x77, 0x5a, 0x0a, 0xb7, 0xb1, 0xbb, 0x9e, 0x59, 0x88, 0xe8, 0x48, 0x2f, 0x49, 0x66, 0x2e, 0x34, 0x21, 0xa8, 0x92, + 0xc8, 0x0f, 0x88, 0x6d, 0x81, 0xe3, 0x41, 0x73, 0x62, 0xeb, 0xa3, 0xd0, 0x52, 0x40, 0x18, 0xb7, 0x57, 0xf1, 0x35, + 0x01, 0x84, 0xd2, 0xba, 0xf3, 0x66, 0xbb, 0x70, 0xf9, 0x37, 0x6d, 0x65, 0x0c, 0x36, 0x3a, 0x77, 0x56, 0x71, 0x81, + 0x5b, 0xdd, 0x8b, 0x21, 0x88, 0x02, 0x25, 0x05, 0x31, 0x9c, 0x04, 0xd5, 0x07, 0x73, 0x20, 0x01, 0x97, 0xc8, 0x83, + 0x52, 0xe3, 0x5c, 0xb8, 0xf1, 0x46, 0x21, 0xc4, 0x62, 0x24, 0xaa, 0x62, 0xb2, 0x41, 0x70, 0x4c, 0x05, 0xda, 0xfd, + 0xf4, 0xdc, 0x7b, 0xe1, 0xfe, 0xa1, 0xa6, 0x56, 0x73, 0xa1, 0x08, 0xa3, 0xdd, 0xc9, 0xbd, 0xa0, 0x85, 0x64, 0xab, + 0x5e, 0xae, 0x91, 0xbd, 0xf0, 0xcd, 0x73, 0xef, 0x2b, 0x25, 0x20, 0xec, 0xdf, 0x19, 0x07, 0x02, 0x60, 0x2e, 0xed, + 0x6a, 0x2d, 0xd1, 0xdf, 0x9e, 0x48, 0xb3, 0xa1, 0xa5, 0x58, 0x37, 0xf3, 0x50, 0x01, 0xd6, 0xd4, 0xea, 0x09, 0x4b, + 0x59, 0xe5, 0x8d, 0x66, 0xa7, 0x86, 0xb7, 0x1d, 0x74, 0x75, 0x92, 0xc2, 0x93, 0xee, 0xff, 0xbd, 0x1f, 0x5e, 0xab, + 0x6e, 0x85, 0xa0, 0x3a, 0x93, 0x74, 0x16, 0x32, 0xd5, 0x7a, 0x1a, 0x53, 0x9c, 0xa4, 0xef, 0x04, 0x45, 0x45, 0x68, + 0xfc, 0x53, 0xd1, 0xd9, 0xf8, 0xa9, 0xeb, 0x03, 0xf7, 0x03, 0x2e, 0x28, 0xbe, 0xc9, 0x3a, 0x7e, 0x98, 0x45, 0x44, + 0x64, 0xe5, 0x67, 0xbb, 0xbc, 0x76, 0xdd, 0xa6, 0x33, 0xf3, 0xd2, 0x6d, 0x74, 0x9b, 0x7f, 0x83, 0x25, 0x1f, 0x8a, + 0x92, 0x97, 0xb4, 0x85, 0xa3, 0x5f, 0xe0, 0x7a, 0x28, 0xd3, 0x81, 0x21, 0x73, 0xeb, 0xba, 0xfe, 0x51, 0x31, 0xd2, + 0xd4, 0x11, 0x4f, 0x99, 0x43, 0x05, 0x9e, 0x9a, 0x9b, 0x4a, 0x0e, 0x94, 0xce, 0x30, 0x5f, 0x13, 0xe1, 0xcd, 0xde, + 0x31, 0xfd, 0x73, 0x41, 0x74, 0x7c, 0x04, 0xd3, 0x86, 0x7c, 0x58, 0x85, 0xe7, 0xe2, 0x58, 0xfd, 0x60, 0x35, 0x89, + 0x3c, 0x89, 0x03, 0xbc, 0x0f, 0x2c, 0x52, 0x61, 0x62, 0xe0, 0x6b, 0x76, 0x3b, 0xce, 0x17, 0x80, 0x19, 0x0f, 0xb9, + 0x4f, 0x77, 0xfc, 0x10, 0x04, 0x8e, 0x17, 0xaa, 0xc5, 0xcd, 0xe1, 0x2d, 0x08, 0x80, 0x8c, 0x59, 0x71, 0x5a, 0x8c, + 0xf2, 0x24, 0x25, 0xe0, 0x99, 0x5c, 0xba, 0x55, 0x43, 0x2a, 0xb3, 0x3f, 0x04, 0x94, 0x4b, 0xd7, 0x42, 0x0a, 0x6e, + 0xd5, 0x17, 0xa6, 0x84, 0x74, 0xd7, 0x68, 0xb0, 0x85, 0x7f, 0x2c, 0x88, 0x25, 0x0d, 0xea, 0x1a, 0xbf, 0xed, 0x57, + 0xee, 0xa4, 0x73, 0xe2, 0x3a, 0x4a, 0x5d, 0x22, 0x89, 0xfb, 0x3c, 0x8c, 0x04, 0x82, 0x99, 0x3d, 0x21, 0xb2, 0x18, + 0x62, 0x1f, 0x47, 0x3b, 0x02, 0xf0, 0x04, 0xa2, 0x23, 0xcf, 0xec, 0x5e, 0x40, 0x7c, 0x7a, 0x82, 0xb0, 0x2c, 0x7f, + 0x23, 0xe3, 0xd7, 0xd7, 0xc3, 0xec, 0x89, 0x62, 0x78, 0x25, 0xf1, 0x54, 0xc5, 0x12, 0x49, 0x43, 0x6b, 0xc0, 0xd2, + 0x15, 0xc9, 0x65, 0xe4, 0x19, 0x71, 0x7e, 0x66, 0x7d, 0x02, 0x7e, 0xec, 0x63, 0x38, 0xf0, 0xeb, 0x40, 0x5f, 0xa4, + 0x54, 0xf9, 0x36, 0x12, 0xe7, 0xd5, 0x7b, 0x73, 0xfd, 0x70, 0x27, 0xe9, 0xea, 0xd5, 0xa3, 0x6d, 0x68, 0x6c, 0x92, + 0xf4, 0x6f, 0xcd, 0x43, 0x80, 0x63, 0x9d, 0xa4, 0x33, 0x14, 0xc6, 0x64, 0x79, 0xd8, 0xb0, 0xea, 0x62, 0xe8, 0xce, + 0x03, 0xee, 0xa6, 0xba, 0x23, 0x75, 0xf8, 0xd2, 0xa4, 0x27, 0x85, 0x59, 0xd2, 0xd8, 0x25, 0xe9, 0xdf, 0xaa, 0x74, + 0x38, 0x54, 0x29, 0x46, 0xe4, 0xb2, 0x22, 0x46, 0xa6, 0x1d, 0xdc, 0x49, 0xfc, 0xb6, 0xe4, 0x9d, 0x80, 0x97, 0x36, + 0xf5, 0x79, 0x57, 0x2b, 0x26, 0xb4, 0x8c, 0xc9, 0x93, 0xb7, 0x76, 0x58, 0x69, 0xa1, 0x54, 0xb2, 0x40, 0x36, 0x65, + 0xa1, 0x51, 0xf0, 0x53, 0xdf, 0xfc, 0xf0, 0x83, 0xa2, 0x32, 0x10, 0x70, 0x3b, 0x58, 0xfd, 0xe3, 0x83, 0x78, 0x19, + 0x43, 0x3c, 0x32, 0x32, 0xa6, 0x7f, 0xc9, 0x50, 0xf7, 0x4f, 0x20, 0x93, 0xf0, 0x75, 0x76, 0xbf, 0x34, 0xf7, 0x17, + 0x6a, 0x1d, 0x8c, 0xeb, 0x68, 0x43, 0x13, 0xf8, 0x26, 0x14, 0xee, 0x87, 0xca, 0xc0, 0x46, 0x29, 0x43, 0xbe, 0x2f, + 0x6d, 0x9e, 0x7b, 0xe2, 0x27, 0x41, 0xf1, 0x69, 0x86, 0x59, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x32, 0xe9, 0xba, 0x43, + 0x6d, 0x7b, 0xab, 0xa9, 0x74, 0x76, 0xd4, 0x31, 0x41, 0xce, 0xf3, 0xa3, 0x19, 0x56, 0x9e, 0xbf, 0x36, 0xf9, 0x06, + 0x81, 0xcf, 0x9d, 0xf7, 0xa6, 0x5a, 0x07, 0x6a, 0xbf, 0x9c, 0x11, 0xb4, 0x2d, 0x03, 0x1c, 0xa9, 0x72, 0xa8, 0x8e, + 0x54, 0x0c, 0x2b, 0x33, 0xde, 0x98, 0xe2, 0xc5, 0x16, 0x7b, 0x9c, 0x2f, 0x21, 0x15, 0xb0, 0x1f, 0x90, 0xb2, 0xe4, + 0x98, 0xd5, 0x22, 0x65, 0x6f, 0x22, 0x05, 0x11, 0xca, 0x6f, 0x5e, 0x1e, 0xfc, 0xdd, 0x64, 0x84, 0x15, 0x58, 0xab, + 0x8e, 0x24, 0x5b, 0x9b, 0xc8, 0x69, 0x2d, 0xa9, 0x8a, 0xf3, 0x46, 0x19, 0x66, 0xbf, 0xeb, 0xcf, 0xcb, 0x26, 0x98, + 0xda, 0xc5, 0xa7, 0xe6, 0x60, 0x8d, 0x16, 0xa6, 0xa7, 0xc2, 0xfe, 0x82, 0x0f, 0x3d, 0x21, 0xbf, 0x19, 0xfc, 0xb2, + 0xaf, 0x6d, 0x18, 0x3c, 0x6a, 0x5f, 0x61, 0x43, 0xa5, 0x75, 0x31, 0xf5, 0xa2, 0x61, 0xb2, 0x2d, 0x7f, 0x7e, 0x2a, + 0xf7, 0x18, 0xb9, 0xc2, 0x8c, 0xc0, 0x1a, 0x95, 0x77, 0xc1, 0x01, 0xe1, 0x63, 0x44, 0x91, 0x1b, 0xb6, 0x45, 0x06, + 0x05, 0xdb, 0x46, 0xd3, 0xae, 0xf4, 0x31, 0x07, 0x79, 0x12, 0x84, 0x4e, 0x76, 0xc2, 0x3b, 0x5f, 0xbd, 0x32, 0x2c, + 0x8b, 0x24, 0xcd, 0x8b, 0xa8, 0xd2, 0x87, 0x55, 0xd5, 0x48, 0xe3, 0xbf, 0x00, 0x60, 0x14, 0xce, 0x97, 0xc2, 0xbf, + 0x29, 0x5c, 0xe3, 0x9d, 0xde, 0xaa, 0x91, 0x72, 0x8e, 0xc7, 0xbc, 0x9b, 0xb1, 0xc3, 0x0f, 0xc2, 0x97, 0xdc, 0xcf, + 0xa8, 0xc0, 0x3c, 0x2d, 0x0b, 0xb3, 0x35, 0xfc, 0x5a, 0x81, 0xdc, 0x3e, 0x12, 0xe7, 0x36, 0x6c, 0xa6, 0x53, 0x7b, + 0xd3, 0x97, 0x1b, 0x84, 0xcc, 0x19, 0xcd, 0xf2, 0xf5, 0x87, 0x87, 0x01, 0x75, 0x11, 0x7e, 0x3b, 0x16, 0xea, 0x51, + 0xb6, 0x74, 0xf0, 0x02, 0x1e, 0xae, 0x69, 0x29, 0x7a, 0xbe, 0xa9, 0x9d, 0xc8, 0x1f, 0x6f, 0x7c, 0x00, 0x6d, 0xef, + 0x75, 0x8c, 0x36, 0xd1, 0x43, 0x4a, 0x01, 0x22, 0x0b, 0x6d, 0xab, 0xaa, 0x66, 0xc8, 0xb2, 0x60, 0xb9, 0x0d, 0xbc, + 0xa7, 0x96, 0x08, 0x87, 0xef, 0xda, 0xd3, 0x85, 0x35, 0xfe, 0x58, 0x00, 0xfc, 0xfb, 0x8c, 0x88, 0x0a, 0xe5, 0x7f, + 0x87, 0xed, 0x19, 0x26, 0x22, 0xee, 0x08, 0xc9, 0x60, 0xc0, 0xc8, 0x43, 0x36, 0x23, 0x29, 0xd8, 0x6a, 0xa5, 0x00, + 0xbe, 0x87, 0x40, 0xe3, 0xba, 0x06, 0x21, 0xd8, 0xa0, 0xd7, 0x40, 0x3c, 0x1c, 0x2f, 0xa8, 0x6b, 0xbc, 0x36, 0x7e, + 0xbb, 0xd6, 0x9a, 0x30, 0xe2, 0xdb, 0xaa, 0x59, 0xbc, 0x56, 0x3d, 0x52, 0x39, 0x92, 0x10, 0x79, 0xa3, 0xa0, 0xd5, + 0x9b, 0x4e, 0xf7, 0xd3, 0x64, 0x44, 0x0a, 0x6a, 0x9d, 0x1b, 0x91, 0xf2, 0x4b, 0xb1, 0x39, 0xf5, 0x87, 0x94, 0x87, + 0x2c, 0x8f, 0xb9, 0x12, 0xd5, 0xb5, 0x08, 0x61, 0xd8, 0x75, 0xf4, 0xaf, 0xa1, 0x84, 0x21, 0x5f, 0x52, 0x19, 0x14, + 0x32, 0x53, 0x59, 0x20, 0x0d, 0xe5, 0x49, 0xe4, 0xee, 0x87, 0xe9, 0xea, 0xdd, 0xab, 0xdc, 0x27, 0xa9, 0x28, 0x89, + 0xdd, 0x85, 0x48, 0x93, 0x89, 0x37, 0xa6, 0xfd, 0xf6, 0x3f, 0x23, 0xe5, 0xdf, 0x54, 0x1d, 0x53, 0x8d, 0x25, 0xb1, + 0xd0, 0x00, 0xa5, 0x7c, 0xc4, 0xd3, 0x36, 0x5d, 0x8e, 0xa2, 0xad, 0xd2, 0x1e, 0x6a, 0x1e, 0x78, 0x58, 0x58, 0x13, + 0xc7, 0x11, 0xf4, 0x74, 0x84, 0xd8, 0x92, 0xda, 0x42, 0xd7, 0xa7, 0x99, 0x67, 0x45, 0x6d, 0x76, 0x8f, 0x54, 0xcb, + 0xe8, 0xa0, 0x35, 0x91, 0x34, 0xfb, 0xa9, 0xcb, 0x34, 0x90, 0x0a, 0x81, 0xef, 0x82, 0xdc, 0x2a, 0x4a, 0x5c, 0xaf, + 0xee, 0xdd, 0x43, 0xb5, 0xf2, 0x3b, 0xff, 0x74, 0x0b, 0x22, 0x23, 0x81, 0x81, 0x14, 0xd1, 0xbc, 0xa0, 0x9f, 0x18, + 0x96, 0xc1, 0x90, 0x33, 0x25, 0xb3, 0x9c, 0xb7, 0x00, 0xed, 0x91, 0xb6, 0x82, 0x0b, 0x12, 0x46, 0xe7, 0x58, 0x2b, + 0x83, 0xcf, 0x91, 0x22, 0x5f, 0xb5, 0xc5, 0xcc, 0x5e, 0xdd, 0xd3, 0x02, 0x53, 0x01, 0xac, 0x2b, 0x05, 0xcb, 0x59, + 0xdf, 0x28, 0xaa, 0xd8, 0xc8, 0xe4, 0xc7, 0x5f, 0xd0, 0x3d, 0xa5, 0x0c, 0x9d, 0x15, 0xae, 0x34, 0x6d, 0x3b, 0x97, + 0xc7, 0xee, 0x83, 0x02, 0x7c, 0xa2, 0x81, 0xcc, 0x4b, 0xf2, 0x9f, 0x9d, 0x6d, 0xd8, 0x7d, 0x52, 0xce, 0x77, 0x13, + 0xfd, 0xde, 0x48, 0xb3, 0xbf, 0x2e, 0x75, 0x28, 0xdb, 0xaf, 0x3c, 0xae, 0x5a, 0xe6, 0x3d, 0xd2, 0xe7, 0xc6, 0x64, + 0x44, 0x26, 0xb4, 0xcb, 0xfa, 0x36, 0xc2, 0xcd, 0xed, 0x33, 0x85, 0xc7, 0x37, 0xbc, 0x9c, 0x3f, 0x69, 0xc5, 0x36, + 0xa5, 0x8e, 0x94, 0xd8, 0x48, 0x14, 0x18, 0x64, 0x91, 0x9f, 0x78, 0x8a, 0x6e, 0xef, 0xa8, 0xad, 0x77, 0xea, 0xae, + 0x93, 0x13, 0x71, 0xe6, 0xea, 0x46, 0x52, 0xa5, 0x11, 0x76, 0xf3, 0x3c, 0xf2, 0xb2, 0x56, 0xd0, 0x8c, 0xd2, 0x43, + 0xed, 0xf6, 0x8e, 0x11, 0x1a, 0x56, 0x4a, 0x8a, 0x6c, 0x51, 0x1b, 0x2d, 0x07, 0x7a, 0xc8, 0x5f, 0x6b, 0x7e, 0xfe, + 0x67, 0x0b, 0x71, 0xe3, 0x70, 0xfa, 0x8a, 0x44, 0x44, 0x61, 0x10, 0xa7, 0x55, 0x24, 0xdb, 0x99, 0x40, 0x61, 0x1c, + 0x4c, 0xb0, 0x75, 0xa3, 0xa9, 0x87, 0x45, 0xa2, 0x96, 0x48, 0xc3, 0xf6, 0x28, 0x0f, 0x81, 0x2a, 0x09, 0x3d, 0x6d, + 0xad, 0x4e, 0xa2, 0xf5, 0x87, 0x6b, 0x9f, 0x11, 0xa1, 0x55, 0x8a, 0xac, 0xca, 0x2b, 0x57, 0x68, 0x04, 0x26, 0x12, + 0x89, 0x8e, 0x20, 0x0e, 0x4d, 0x08, 0x1f, 0x1e, 0xd2, 0x4b, 0xab, 0x22, 0x86, 0x56, 0x5c, 0x43, 0x66, 0x01, 0xc4, + 0x26, 0x63, 0xfa, 0x7a, 0xbf, 0x63, 0x19, 0xd7, 0xcb, 0x83, 0x56, 0xff, 0x91, 0x88, 0x13, 0xa4, 0xfb, 0xa2, 0x03, + 0x8c, 0x06, 0x1c, 0x55, 0xc1, 0xb7, 0x8f, 0xa1, 0xa8, 0x74, 0xa0, 0x5e, 0x8e, 0xdc, 0x22, 0xf2, 0x2b, 0xe0, 0xda, + 0xdd, 0x8a, 0x08, 0xdf, 0x2e, 0x9f, 0xd3, 0xac, 0x96, 0x11, 0xd4, 0xbe, 0x8f, 0x68, 0x95, 0x89, 0xb0, 0xb9, 0xb8, + 0xeb, 0xb1, 0x5c, 0x43, 0xd5, 0x87, 0x56, 0x5c, 0x44, 0xe1, 0xcd, 0x1c, 0xa4, 0x8d, 0xc9, 0x78, 0x49, 0x3f, 0xb5, + 0x1d, 0x95, 0x80, 0x5e, 0x28, 0x0b, 0x4d, 0x06, 0x49, 0xc1, 0xa3, 0xf7, 0x40, 0x98, 0xa4, 0x57, 0xce, 0x98, 0xfd, + 0x94, 0xa7, 0x24, 0x4e, 0xdf, 0x82, 0x76, 0x36, 0x45, 0xf0, 0x70, 0xd5, 0x5e, 0xda, 0x53, 0xd0, 0x7e, 0xcf, 0x74, + 0xb6, 0xbd, 0xac, 0x91, 0x78, 0x2f, 0x3a, 0xf0, 0x2a, 0xfa, 0x3c, 0x32, 0xc3, 0x98, 0xc1, 0xfd, 0x90, 0x90, 0xe4, + 0xb3, 0x94, 0x0a, 0x66, 0x41, 0x0f, 0xe4, 0x51, 0x91, 0x8c, 0xd2, 0x4c, 0xb7, 0xfd, 0x91, 0xe8, 0xfa, 0x69, 0xaa, + 0x76, 0xb5, 0xf6, 0x14, 0x55, 0x5e, 0xbe, 0x5e, 0xf8, 0xed, 0xf4, 0x8c, 0xae, 0xdc, 0x01, 0xc9, 0x7a, 0x46, 0x6f, + 0x5a, 0xb0, 0x5a, 0x28, 0x1d, 0xa9, 0x20, 0xf6, 0x3e, 0x27, 0xb0, 0x18, 0xd7, 0x43, 0x1a, 0xd6, 0xe0, 0x03, 0xa6, + 0x27, 0xab, 0xd3, 0x77, 0xce, 0x7d, 0xd9, 0xff, 0xf6, 0xdd, 0x76, 0x83, 0x35, 0x73, 0xf1, 0x07, 0xb9, 0x4b, 0x40, + 0xcd, 0x21, 0xd3, 0x64, 0xd2, 0x57, 0x69, 0x37, 0x27, 0xaf, 0x12, 0xb3, 0x70, 0x80, 0xfe, 0xdd, 0x1c, 0x72, 0xc2, + 0x3a, 0xde, 0xb8, 0x44, 0xf4, 0xd4, 0xbb, 0x70, 0xda, 0x13, 0x07, 0xf0, 0x2f, 0x18, 0x26, 0x4a, 0x88, 0x64, 0x2e, + 0xe1, 0x61, 0x5e, 0xc2, 0x51, 0xf2, 0x43, 0xb6, 0xcd, 0x54, 0xef, 0xa8, 0x6e, 0xde, 0x14, 0xd8, 0xf3, 0x14, 0x17, + 0xbb, 0x55, 0xc2, 0x8c, 0x55, 0xec, 0xb5, 0xd8, 0x43, 0x8f, 0x37, 0x28, 0x92, 0xcc, 0xf6, 0x19, 0x0d, 0x9d, 0xf9, + 0x4d, 0x7e, 0x7d, 0x71, 0x73, 0x37, 0xfd, 0x7f, 0x5c, 0x9d, 0x18, 0x87, 0x15, 0x7c, 0x36, 0xf4, 0x65, 0xbf, 0x2a, + 0xcb, 0xe7, 0x12, 0x5f, 0xad, 0x96, 0x77, 0x94, 0x8c, 0x7b, 0x9b, 0xf8, 0xc1, 0x00, 0x06, 0x6f, 0x5a, 0x48, 0x1e, + 0x4a, 0x14, 0x61, 0x64, 0xde, 0x1f, 0x2e, 0x29, 0xf0, 0x72, 0xf9, 0x55, 0x70, 0x91, 0x98, 0xfe, 0xb6, 0xf5, 0x4a, + 0x2a, 0xe2, 0x90, 0xaa, 0x23, 0xde, 0x4d, 0x10, 0x69, 0x51, 0x0e, 0x1d, 0xfd, 0xc4, 0x01, 0x93, 0x35, 0x38, 0x10, + 0x81, 0x82, 0xce, 0x67, 0x2f, 0x89, 0xc4, 0x8f, 0xd0, 0x5f, 0x79, 0x16, 0x75, 0xda, 0x8b, 0xf6, 0xb3, 0xed, 0x85, + 0xff, 0x7f, 0xba, 0xb4, 0xaa, 0x73, 0x6c, 0x40, 0xb0, 0xfe, 0x2f, 0x90, 0xb8, 0xd0, 0x0e, 0x4a, 0x90, 0xee, 0x53, + 0xf8, 0xc4, 0x9f, 0xdd, 0x69, 0x96, 0x13, 0x96, 0xaf, 0xd5, 0x6a, 0x19, 0x4f, 0xe8, 0x9c, 0x5c, 0x68, 0x1c, 0x27, + 0x6a, 0xca, 0x10, 0x3c, 0xe3, 0xe8, 0xed, 0xb5, 0x0c, 0xbd, 0xdb, 0x98, 0x4a, 0x82, 0x4e, 0xe2, 0x71, 0xc5, 0x52, + 0xac, 0xa2, 0x75, 0xbf, 0x6a, 0x63, 0xb6, 0x99, 0xc1, 0x19, 0x30, 0xce, 0xb2, 0x80, 0xd1, 0x83, 0xa5, 0x7a, 0x38, + 0x37, 0x0e, 0x98, 0x5e, 0xcb, 0x6b, 0x4c, 0x47, 0x04, 0x8d, 0xdd, 0xf2, 0xf5, 0x7a, 0x14, 0x51, 0x49, 0x26, 0x22, + 0xde, 0x2d, 0xf0, 0x40, 0x2f, 0x7e, 0x3e, 0x56, 0xbd, 0xf6, 0xa4, 0x6e, 0xe5, 0x2b, 0x15, 0x61, 0x59, 0x47, 0x53, + 0x19, 0x30, 0x5e, 0xdd, 0xac, 0x8a, 0xd0, 0xae, 0x84, 0xb8, 0x78, 0x21, 0x7b, 0x02, 0x31, 0x31, 0x92, 0x8f, 0x38, + 0x93, 0x60, 0x93, 0x83, 0x4c, 0x05, 0xe5, 0xe3, 0x43, 0xcd, 0x16, 0x04, 0xa1, 0xab, 0xdb, 0x50, 0x0b, 0x72, 0x2c, + 0x9c, 0x27, 0x92, 0x11, 0x4d, 0x12, 0x03, 0x57, 0x59, 0x49, 0xb0, 0x6a, 0x26, 0xe3, 0x65, 0xd6, 0x9d, 0x15, 0x7b, + 0x60, 0x53, 0xad, 0x39, 0x18, 0xdd, 0xff, 0x98, 0x17, 0x18, 0xa2, 0x28, 0x5a, 0xcf, 0x12, 0xc5, 0xf3, 0x88, 0x79, + 0xc0, 0x2c, 0x4b, 0xa0, 0x51, 0x84, 0x22, 0xf4, 0x6f, 0x89, 0x3d, 0xd4, 0x67, 0x95, 0x91, 0x58, 0x58, 0x0c, 0x27, + 0x54, 0xc5, 0xe9, 0x28, 0xed, 0x95, 0x85, 0xf7, 0xc1, 0x6e, 0x10, 0xc6, 0x57, 0xff, 0xd7, 0xf8, 0xee, 0x6d, 0x0f, + 0xa9, 0xed, 0xf9, 0x38, 0x9b, 0x99, 0x8f, 0xe9, 0x46, 0xef, 0xf6, 0x4f, 0x37, 0x22, 0x36, 0xbb, 0xad, 0x6c, 0x03, + 0x91, 0x4c, 0x14, 0x94, 0x9a, 0x3f, 0xb3, 0xdb, 0x03, 0xb6, 0xe2, 0xa0, 0x78, 0xdd, 0xa9, 0xa8, 0xcf, 0xd6, 0x6a, + 0x2c, 0x01, 0x08, 0xc7, 0x92, 0x46, 0xda, 0x25, 0xb6, 0x20, 0xd2, 0xfa, 0x1c, 0x19, 0x12, 0xbc, 0xb6, 0xce, 0xf3, + 0x00, 0x0e, 0x59, 0x32, 0x4d, 0x04, 0x2b, 0xd2, 0x4b, 0x00, 0x69, 0x1b, 0x21, 0xbd, 0xc8, 0x9e, 0x41, 0x09, 0xc0, + 0xab, 0x88, 0xf6, 0x46, 0x65, 0x22, 0x92, 0x37, 0x59, 0xa3, 0x14, 0xb6, 0xe3, 0x03, 0xe1, 0x65, 0x7e, 0x44, 0xb0, + 0xc4, 0xd4, 0x68, 0xcf, 0x96, 0x4e, 0x13, 0x50, 0x8b, 0xed, 0x34, 0x42, 0x98, 0xef, 0xd7, 0x8d, 0xc1, 0xc3, 0xe1, + 0x62, 0x49, 0x8a, 0x71, 0xb5, 0xde, 0x7c, 0x2c, 0xe5, 0x76, 0xe4, 0x5a, 0xec, 0x98, 0x3b, 0x70, 0x34, 0xe9, 0x9e, + 0xa6, 0x5d, 0xbd, 0xd1, 0xcd, 0xaf, 0xf8, 0xcd, 0xeb, 0x69, 0x89, 0x97, 0xc7, 0x47, 0x42, 0xf7, 0xae, 0x46, 0xa0, + 0xb9, 0x71, 0xce, 0x0f, 0xfd, 0xee, 0x5d, 0x9d, 0xe0, 0x8d, 0xff, 0x95, 0x1a, 0x4f, 0xca, 0xe4, 0xe4, 0x6f, 0xe6, + 0xd0, 0xf8, 0x8c, 0xf1, 0xb4, 0xb8, 0xa9, 0x40, 0xa0, 0x40, 0xd5, 0x01, 0xec, 0xce, 0xa2, 0xd2, 0x7f, 0x33, 0x62, + 0x7c, 0x04, 0x5c, 0x28, 0x3a, 0x35, 0xf8, 0x69, 0x49, 0x78, 0xc6, 0xf3, 0xd9, 0x2d, 0xd4, 0x22, 0x69, 0xa5, 0xce, + 0xc4, 0x4e, 0x1d, 0x7e, 0x2e, 0xf6, 0x0f, 0x2b, 0x22, 0x3a, 0x14, 0xf1, 0x61, 0x37, 0x05, 0x05, 0x41, 0xc3, 0x0b, + 0x62, 0x99, 0xa0, 0x0b, 0xa1, 0x7c, 0xd4, 0xec, 0xbe, 0x4c, 0x52, 0xfd, 0xc3, 0xfe, 0x82, 0x9f, 0x7b, 0xdb, 0xd7, + 0x22, 0x17, 0x4b, 0xa1, 0x59, 0xd9, 0x48, 0x27, 0x0f, 0x2e, 0x15, 0x6d, 0xaf, 0x82, 0xec, 0x6c, 0xde, 0x9a, 0x35, + 0x99, 0x03, 0xc9, 0x22, 0x2d, 0xc2, 0xfa, 0xc8, 0x73, 0xfe, 0xd9, 0xe2, 0x73, 0xba, 0x74, 0xdf, 0x37, 0x63, 0xdb, + 0x64, 0x98, 0xf4, 0x24, 0x81, 0x30, 0x51, 0x82, 0x6f, 0xcb, 0xe8, 0x01, 0x60, 0x7d, 0x6d, 0x39, 0xa2, 0xcc, 0x56, + 0x01, 0x99, 0xc9, 0x76, 0x7e, 0xed, 0x29, 0x20, 0xea, 0x6c, 0x05, 0x12, 0x31, 0x94, 0x3e, 0x03, 0x17, 0x34, 0x3e, + 0xb5, 0x20, 0x49, 0x89, 0x09, 0xc9, 0x0c, 0x1f, 0x01, 0x99, 0x02, 0x6e, 0xbe, 0xf3, 0x64, 0x0b, 0xfd, 0x54, 0xc6, + 0x29, 0xb0, 0x61, 0x5a, 0x0f, 0xe6, 0x2c, 0x8c, 0x67, 0x1a, 0x32, 0xe2, 0xf8, 0xe7, 0x1b, 0x81, 0xd5, 0x88, 0x3c, + 0x8f, 0xcc, 0x6c, 0x24, 0x2e, 0x60, 0x70, 0xd9, 0xf7, 0x92, 0x26, 0x10, 0xd7, 0xaf, 0x71, 0x8d, 0xf9, 0x24, 0x8f, + 0xd7, 0xea, 0xe6, 0xb7, 0xe6, 0x6f, 0x3d, 0x94, 0x67, 0xf9, 0xe2, 0xa4, 0x36, 0xad, 0x15, 0xf4, 0xcb, 0xb5, 0x56, + 0x1b, 0xa0, 0x56, 0xc1, 0xcc, 0x96, 0x8c, 0x5b, 0x69, 0x51, 0x04, 0x8e, 0x9a, 0xe5, 0xad, 0xd9, 0x1d, 0xdf, 0x6e, + 0x90, 0x3f, 0xd1, 0x10, 0x31, 0x3e, 0x55, 0x81, 0x4b, 0xd4, 0xf1, 0x73, 0xf4, 0x36, 0x87, 0x76, 0x18, 0xaf, 0xe2, + 0x87, 0x6d, 0xbc, 0xc8, 0xd8, 0xca, 0xf2, 0xf2, 0x75, 0x74, 0x88, 0x2b, 0x47, 0xeb, 0x30, 0x34, 0xfd, 0x34, 0x8d, + 0x39, 0x52, 0xa8, 0x27, 0xec, 0xf8, 0x7b, 0x0c, 0xf8, 0x4f, 0xed, 0xf1, 0xab, 0xfe, 0x93, 0xe3, 0x5f, 0x86, 0x5d, + 0xe5, 0x65, 0xfe, 0x63, 0x90, 0xbf, 0x87, 0x4f, 0xa9, 0xf2, 0xb3, 0x89, 0x2c, 0x54, 0x9b, 0x43, 0xf2, 0x68, 0x2d, + 0x87, 0x05, 0xfa, 0xea, 0xc3, 0xc9, 0xe9, 0x04, 0xc3, 0x9a, 0x53, 0xe7, 0x07, 0xa4, 0xaf, 0x6b, 0xe2, 0xc2, 0x2f, + 0xc6, 0xa7, 0xab, 0xb9, 0x0c, 0xdd, 0x74, 0xb9, 0x87, 0x54, 0xee, 0x8b, 0x4c, 0xb5, 0xad, 0xac, 0x9d, 0xfd, 0xfd, + 0x60, 0x70, 0x47, 0x04, 0x36, 0x9c, 0x7b, 0xf3, 0x85, 0xe7, 0x9f, 0xf4, 0x9f, 0xee, 0x29, 0x5a, 0x33, 0x16, 0x5f, + 0xe8, 0x33, 0xad, 0x5c, 0xbe, 0x71, 0x6d, 0xca, 0x36, 0xf4, 0x99, 0xda, 0x74, 0x03, 0x20, 0x26, 0x15, 0x34, 0x28, + 0xeb, 0xdc, 0xc7, 0x1f, 0x14, 0x7d, 0x48, 0x28, 0xfa, 0xd2, 0xe7, 0xa3, 0xda, 0x17, 0x06, 0x11, 0x00, 0x49, 0x0c, + 0x33, 0xf3, 0x97, 0x82, 0xee, 0x84, 0x86, 0x07, 0xfa, 0xe6, 0xe9, 0x27, 0x4e, 0x7d, 0x06, 0xde, 0x1a, 0xf5, 0x0f, + 0x52, 0x5c, 0x5f, 0x81, 0x04, 0xb0, 0x70, 0x9e, 0x2e, 0xff, 0x4f, 0x5e, 0x10, 0x42, 0xd2, 0x9c, 0x2c, 0x6a, 0x3b, + 0x57, 0xdd, 0xff, 0x98, 0x6c, 0xf0, 0x11, 0x1b, 0x24, 0xf8, 0x38, 0x29, 0x26, 0x9e, 0x05, 0x41, 0x75, 0x45, 0xcf, + 0x4d, 0xae, 0xfa, 0xb3, 0x8c, 0x43, 0xfe, 0xf7, 0xb1, 0x3c, 0x5f, 0x40, 0xce, 0x63, 0xc6, 0x77, 0x7e, 0x88, 0xb0, + 0x24, 0xa7, 0x61, 0x67, 0x76, 0x5f, 0xed, 0xcf, 0xa3, 0x81, 0xfa, 0x6a, 0x77, 0x7e, 0x03, 0x09, 0xf8, 0xc2, 0x0f, + 0x6b, 0xa8, 0x51, 0xf9, 0xa3, 0x39, 0xad, 0xbd, 0x4a, 0x1b, 0x7d, 0x42, 0x25, 0x22, 0xb8, 0x94, 0x1c, 0xa0, 0xbe, + 0x48, 0x3a, 0x3f, 0x99, 0x38, 0x66, 0xda, 0x94, 0x1c, 0x74, 0xe3, 0x5c, 0x72, 0xa1, 0x1c, 0x5a, 0x49, 0x1d, 0xa5, + 0x80, 0x9c, 0x94, 0xd1, 0x81, 0x15, 0xdd, 0x5e, 0x4a, 0xc6, 0x8f, 0x8a, 0xd0, 0x2e, 0x9b, 0xcd, 0x35, 0x2b, 0x8b, + 0x99, 0x44, 0x8c, 0x54, 0x70, 0x59, 0xb2, 0x32, 0x41, 0xbf, 0xa8, 0x8d, 0xa9, 0x8d, 0x64, 0xba, 0xb7, 0x59, 0x9d, + 0xba, 0x08, 0x34, 0xb8, 0x72, 0x40, 0x5e, 0xf1, 0x2a, 0x60, 0x4b, 0x48, 0x26, 0xcc, 0x22, 0x56, 0x70, 0xa1, 0xdc, + 0xf7, 0x99, 0xfb, 0x60, 0x7f, 0x9c, 0x04, 0xe7, 0x5b, 0x6f, 0xd1, 0xef, 0x12, 0x9c, 0x82, 0xea, 0xf5, 0xe7, 0xd4, + 0xb5, 0xb8, 0xbc, 0x62, 0x0a, 0x0a, 0x1c, 0x83, 0x7c, 0xba, 0xcb, 0x03, 0x22, 0xf0, 0x43, 0xfb, 0xa4, 0x8e, 0xd3, + 0xd6, 0x7f, 0x46, 0xc7, 0x0c, 0xb2, 0x81, 0x54, 0xe7, 0xbe, 0x2c, 0xb0, 0x9d, 0x2e, 0x5b, 0x22, 0xb7, 0x02, 0x77, + 0x4a, 0x75, 0xdb, 0x0b, 0x94, 0x29, 0xd1, 0x51, 0x11, 0x81, 0x6d, 0x06, 0xd0, 0xb3, 0x15, 0xc1, 0x4b, 0x1f, 0x79, + 0xd6, 0x2c, 0x68, 0xe8, 0x8f, 0x88, 0x34, 0x99, 0xd0, 0x80, 0x41, 0x2e, 0x26, 0x5e, 0x4c, 0xbd, 0xf4, 0x98, 0x45, + 0xc7, 0x19, 0x70, 0x67, 0xe7, 0x2c, 0x2c, 0xe6, 0xf5, 0x34, 0xe5, 0x4b, 0x8f, 0x7e, 0x33, 0xbc, 0xec, 0x5e, 0xba, + 0xf9, 0xe9, 0x73, 0xba, 0xc1, 0xc4, 0x06, 0xba, 0x6b, 0x75, 0x1c, 0xcd, 0x83, 0x87, 0x16, 0x30, 0x93, 0xd2, 0x1c, + 0xef, 0x5b, 0xd0, 0xd2, 0xb9, 0x08, 0x99, 0xc8, 0xcb, 0x83, 0x9e, 0xed, 0x1b, 0xd2, 0x50, 0xb3, 0x13, 0xe0, 0xb3, + 0xb3, 0x34, 0x9a, 0x2b, 0x5e, 0xd0, 0x42, 0x09, 0x23, 0xc4, 0x65, 0xfd, 0x13, 0xe0, 0x81, 0xaf, 0x01, 0xca, 0x9f, + 0x94, 0xeb, 0x81, 0x67, 0x8e, 0xb9, 0x43, 0x38, 0xe1, 0xa7, 0x8a, 0xc0, 0xdd, 0x45, 0x85, 0xfe, 0xc9, 0x8c, 0x21, + 0x85, 0x01, 0x5f, 0x15, 0xe3, 0x29, 0xe1, 0x15, 0x68, 0x1a, 0x94, 0x07, 0x87, 0x01, 0xaa, 0x51, 0xf7, 0x7d, 0xed, + 0x53, 0x38, 0xa2, 0x09, 0x0f, 0x79, 0x87, 0xbc, 0x1a, 0xaa, 0x85, 0x26, 0x3e, 0xe4, 0x1d, 0x93, 0xe0, 0x9b, 0x0f, + 0xf7, 0x32, 0x7d, 0x44, 0x95, 0xa3, 0x17, 0xfa, 0x84, 0x05, 0x92, 0x53, 0x3d, 0x5e, 0x4b, 0xd1, 0x5e, 0xd1, 0x1c, + 0x5a, 0x09, 0x54, 0x6c, 0x4c, 0x87, 0x70, 0xe9, 0xd9, 0x5e, 0x7f, 0x7a, 0x93, 0xf8, 0x8b, 0x38, 0x63, 0x0d, 0x7b, + 0x02, 0xce, 0x99, 0x0d, 0xaa, 0xef, 0x64, 0x97, 0xb0, 0x48, 0x92, 0x9e, 0x67, 0x4e, 0xc7, 0x04, 0xb9, 0x79, 0xcd, + 0x1d, 0xdc, 0xcc, 0x43, 0xb9, 0xaa, 0x4f, 0x44, 0xa1, 0x49, 0xdd, 0x49, 0x41, 0xc4, 0x5b, 0xf7, 0xd7, 0x09, 0x6a, + 0x19, 0x75, 0x75, 0xd3, 0xdf, 0x8a, 0x78, 0x64, 0xcc, 0xbf, 0x56, 0x91, 0xd1, 0x2a, 0xf7, 0xdb, 0xd6, 0x5f, 0x57, + 0x66, 0x0f, 0xd9, 0xcf, 0xab, 0x5a, 0xf7, 0x3f, 0x6b, 0xd8, 0x6b, 0x5e, 0x2b, 0x45, 0x11, 0xce, 0x5c, 0x4d, 0x7a, + 0x64, 0xbe, 0x41, 0x2f, 0xee, 0xf6, 0xf0, 0x9c, 0x04, 0x28, 0x13, 0x27, 0x21, 0x0e, 0x24, 0xe4, 0x18, 0x6b, 0xbe, + 0xa2, 0x3d, 0xe6, 0xba, 0x61, 0x51, 0x99, 0x6b, 0x7e, 0x20, 0x68, 0x40, 0x05, 0xf4, 0x87, 0x1d, 0x4e, 0x73, 0x6f, + 0x42, 0xc3, 0x6f, 0x42, 0x3e, 0x43, 0xf0, 0xbb, 0xfc, 0x63, 0x81, 0xa1, 0xd0, 0x52, 0x43, 0x86, 0xeb, 0x54, 0x37, + 0x63, 0xb2, 0xda, 0x04, 0xfe, 0xb7, 0xb4, 0x9b, 0x51, 0x43, 0x64, 0x41, 0x84, 0x0c, 0x30, 0x90, 0xd1, 0x16, 0x03, + 0xaf, 0x69, 0xa6, 0xd9, 0x6a, 0x30, 0x56, 0x1f, 0x36, 0x59, 0x0a, 0x76, 0xaf, 0x9c, 0xa9, 0x1c, 0x06, 0xb5, 0x81, + 0xe1, 0x5d, 0xfa, 0xde, 0x3e, 0x2c, 0xe3, 0x45, 0xad, 0x90, 0xfb, 0xe9, 0x10, 0x19, 0x6e, 0x52, 0xc7, 0x6a, 0xa6, + 0xff, 0x19, 0x33, 0x31, 0x3e, 0x35, 0x38, 0x04, 0x36, 0x8c, 0x5d, 0xd5, 0x82, 0x61, 0xda, 0x28, 0xed, 0x9d, 0xb2, + 0x2e, 0x68, 0x21, 0x2c, 0xad, 0x5a, 0xe3, 0x80, 0x71, 0x4e, 0x2f, 0x2f, 0xd4, 0xe9, 0xc4, 0x9b, 0xfa, 0xdb, 0xc8, + 0x84, 0x0f, 0xfe, 0x35, 0x87, 0xba, 0x5a, 0x18, 0x85, 0xe3, 0xe1, 0xa3, 0x94, 0x07, 0x49, 0x68, 0x89, 0x85, 0xa6, + 0x6c, 0x6e, 0x48, 0x54, 0x87, 0x62, 0x23, 0x28, 0xf8, 0x7c, 0x85, 0x08, 0xb8, 0xc3, 0x61, 0x4b, 0x49, 0xf7, 0x16, + 0xcf, 0x90, 0x24, 0x2a, 0x23, 0x17, 0x9b, 0x60, 0x0f, 0x04, 0xc7, 0xa5, 0xa6, 0xac, 0xe5, 0xf9, 0xaf, 0x92, 0xe8, + 0x9f, 0xa0, 0xe0, 0x25, 0x29, 0xe5, 0xfc, 0x3b, 0x16, 0x7f, 0xd6, 0xd7, 0xc7, 0x88, 0xde, 0xfb, 0x0b, 0xc9, 0x67, + 0x7d, 0xb6, 0x6d, 0x1b, 0x23, 0xf3, 0xf2, 0x66, 0xae, 0x1f, 0xeb, 0xb8, 0x8c, 0x5d, 0xa2, 0x80, 0xe8, 0x6f, 0x58, + 0x2e, 0xd3, 0x3c, 0xc0, 0xf2, 0xb0, 0x3c, 0x8a, 0xfc, 0xb6, 0x22, 0x59, 0xa2, 0x81, 0xb7, 0x38, 0x2d, 0xd2, 0xbb, + 0xed, 0x78, 0x97, 0x2b, 0x75, 0x3a, 0x74, 0x2b, 0x63, 0x49, 0x34, 0xaa, 0x94, 0x43, 0x10, 0x03, 0x77, 0xba, 0x38, + 0x06, 0xbb, 0x33, 0x99, 0x3d, 0x4e, 0xdb, 0x98, 0xea, 0x4e, 0xdc, 0xd1, 0x13, 0xbc, 0xc4, 0x27, 0x2d, 0x35, 0xbb, + 0xa3, 0x17, 0x5a, 0x86, 0x4a, 0xc8, 0xea, 0xf4, 0x85, 0x56, 0x3f, 0x8a, 0x90, 0x24, 0x07, 0xfc, 0xaa, 0xf2, 0x97, + 0xaf, 0xd7, 0x63, 0xa1, 0x52, 0x5d, 0x54, 0x14, 0x68, 0x7e, 0x9e, 0x26, 0x1e, 0xa3, 0xdd, 0x6f, 0xa5, 0xaf, 0xce, + 0x1b, 0xc2, 0x07, 0xa0, 0x02, 0x92, 0x5b, 0x39, 0x34, 0xa4, 0xa1, 0x65, 0x3e, 0x3c, 0xce, 0x50, 0x28, 0x02, 0x74, + 0x26, 0x75, 0xe1, 0xa9, 0x8b, 0xf3, 0xea, 0x1f, 0x13, 0x54, 0x6c, 0x3f, 0xa7, 0x0c, 0x80, 0x93, 0x34, 0x40, 0x34, + 0x1a, 0xcf, 0x59, 0xa7, 0xd1, 0x85, 0x52, 0x3c, 0x03, 0x47, 0xc0, 0x7a, 0x89, 0x5c, 0x7b, 0x45, 0xeb, 0x5a, 0x86, + 0x34, 0xe9, 0xfe, 0xed, 0x51, 0xbf, 0x0d, 0xc1, 0x1d, 0x98, 0x34, 0x12, 0x3a, 0xaa, 0xae, 0x98, 0x1b, 0xc9, 0x38, + 0x50, 0x77, 0xda, 0x4d, 0x29, 0x37, 0x56, 0xd8, 0xcb, 0x5c, 0xb6, 0xaa, 0x63, 0xb9, 0x44, 0x58, 0xc4, 0xc5, 0x51, + 0x62, 0x45, 0x80, 0xef, 0x91, 0x41, 0x54, 0xaa, 0xf2, 0x24, 0x8a, 0x90, 0xe4, 0x0d, 0x16, 0x18, 0x73, 0x0b, 0xfd, + 0x26, 0x12, 0x3c, 0xf8, 0xfa, 0xa7, 0x15, 0x49, 0xa1, 0x12, 0x10, 0x40, 0x83, 0x81, 0x16, 0x50, 0xcd, 0xfc, 0xa3, + 0x51, 0xb7, 0x18, 0x3a, 0xcf, 0xe2, 0x39, 0x25, 0xc9, 0xa0, 0x3f, 0xfe, 0xfb, 0x09, 0x61, 0xd0, 0x06, 0xb0, 0x90, + 0x11, 0x07, 0xdc, 0x30, 0xd7, 0x9b, 0x44, 0xfa, 0x6c, 0x51, 0x2c, 0xb6, 0xd8, 0xcb, 0xb9, 0x4d, 0xe9, 0x05, 0x8d, + 0x97, 0x50, 0xf2, 0x8e, 0xe1, 0x2b, 0xaf, 0x83, 0x99, 0xb7, 0xbc, 0xc6, 0x0d, 0x16, 0xfa, 0x05, 0x8b, 0xae, 0x4a, + 0x72, 0xef, 0x97, 0x3d, 0x00, 0x99, 0x4f, 0x27, 0xaa, 0x37, 0x04, 0x0f, 0x21, 0x65, 0x63, 0xcc, 0x98, 0x73, 0x83, + 0x7b, 0xe7, 0x53, 0x45, 0x0a, 0x23, 0x17, 0x86, 0x00, 0x4e, 0x62, 0x94, 0xd1, 0xa6, 0x9e, 0xce, 0x42, 0x9d, 0x7e, + 0xe1, 0xad, 0x03, 0xf5, 0x6b, 0x53, 0x09, 0xc5, 0x5e, 0xd6, 0x03, 0x22, 0x6a, 0xaa, 0xae, 0x04, 0xe5, 0xa6, 0x44, + 0xf5, 0xed, 0x27, 0x78, 0xa6, 0xe3, 0x50, 0xfc, 0xcc, 0xc0, 0x48, 0x4c, 0x84, 0xe4, 0x6c, 0x90, 0x24, 0x4f, 0xd2, + 0x65, 0x2d, 0x09, 0xea, 0xda, 0xaf, 0x12, 0xc2, 0x23, 0x92, 0x71, 0x7e, 0xd6, 0x87, 0x7a, 0xe0, 0xca, 0x06, 0xbb, + 0x1c, 0x4f, 0xbf, 0x08, 0xd7, 0xdd, 0xa6, 0x3d, 0x35, 0xbc, 0xfb, 0x54, 0x64, 0x72, 0xcb, 0x56, 0xcd, 0x62, 0x63, + 0x82, 0x9f, 0xf8, 0x3c, 0xe8, 0x3e, 0xee, 0x37, 0x24, 0xa1, 0x9f, 0x6f, 0x73, 0x3f, 0xb1, 0xd2, 0xe8, 0x03, 0x78, + 0xd0, 0x58, 0x8a, 0x4b, 0x2b, 0x50, 0x63, 0xc1, 0x97, 0xdb, 0x92, 0xbc, 0xcd, 0x3c, 0xf0, 0x9d, 0xb8, 0x10, 0xba, + 0xc8, 0x7d, 0xe4, 0x6b, 0xe4, 0xad, 0xf4, 0x6e, 0xd5, 0x46, 0xfe, 0xe0, 0x57, 0x7f, 0xc8, 0x4a, 0x4f, 0xe9, 0x8f, + 0xca, 0x9c, 0xc5, 0x37, 0x5c, 0xa2, 0x9b, 0x81, 0x1d, 0xc1, 0x49, 0x5d, 0xf5, 0xe1, 0x0d, 0xa0, 0xb5, 0x85, 0xb7, + 0x1c, 0x4d, 0x13, 0x81, 0xe7, 0x66, 0xb8, 0xc4, 0x15, 0xd9, 0xe0, 0x06, 0x8a, 0x3d, 0x28, 0x60, 0x20, 0x36, 0xca, + 0x74, 0x3c, 0x00, 0xfc, 0x1c, 0xe2, 0x6e, 0xcc, 0xcf, 0xba, 0x66, 0x1b, 0x2d, 0x70, 0x4e, 0x91, 0x05, 0x64, 0x2f, + 0x43, 0x03, 0x0a, 0xd0, 0x09, 0x45, 0x50, 0xda, 0xac, 0xb1, 0x03, 0x26, 0x84, 0x15, 0x46, 0xd3, 0x00, 0xc7, 0x86, + 0x98, 0xb3, 0x97, 0xe6, 0x16, 0x81, 0x2f, 0x97, 0x88, 0x5c, 0xd3, 0x23, 0xa1, 0x7c, 0x86, 0x14, 0x38, 0xd1, 0xcf, + 0xd3, 0x7f, 0x03, 0x26, 0xbd, 0x9b, 0x13, 0xb4, 0xa7, 0x83, 0x69, 0xbf, 0xd4, 0x10, 0x28, 0x2d, 0x23, 0xf7, 0x87, + 0xe6, 0xf9, 0x7a, 0x31, 0xa6, 0x6b, 0xac, 0x76, 0x1b, 0xcd, 0x3f, 0xc5, 0xf5, 0x3c, 0x19, 0xb7, 0x88, 0x5c, 0x18, + 0x00, 0x7e, 0x6f, 0x06, 0x8d, 0xb7, 0xde, 0x4f, 0x2a, 0x3c, 0x67, 0x0d, 0x4b, 0x28, 0xdd, 0x23, 0xf2, 0x6d, 0xfe, + 0x87, 0x69, 0x3a, 0x28, 0x82, 0x53, 0x1b, 0xf2, 0xde, 0x83, 0x7b, 0x58, 0x87, 0x82, 0xa1, 0xaf, 0xc3, 0x94, 0xf9, + 0xc9, 0xce, 0xb2, 0x81, 0xd2, 0xb6, 0xb3, 0x5d, 0x35, 0x25, 0xed, 0x42, 0x32, 0x5c, 0x91, 0x18, 0xa4, 0xda, 0xc8, + 0x8f, 0xb6, 0xb2, 0xb2, 0x66, 0x6e, 0xa7, 0x38, 0xf2, 0x73, 0xa7, 0x33, 0xec, 0xde, 0xd8, 0xac, 0x1b, 0x1e, 0x80, + 0x34, 0xd7, 0x29, 0x00, 0x08, 0xc2, 0xa5, 0x6c, 0xe2, 0x1d, 0x4b, 0x95, 0xed, 0x40, 0x7d, 0xb0, 0xd0, 0x1c, 0x5c, + 0xe7, 0xa3, 0x09, 0xf9, 0xb8, 0xd9, 0xac, 0xf4, 0x3c, 0x07, 0x88, 0xc7, 0x71, 0x52, 0x19, 0x0c, 0x91, 0x82, 0x9f, + 0x4a, 0xb0, 0xc3, 0xd1, 0xe2, 0x3c, 0xfa, 0x6b, 0xe4, 0xbc, 0x4f, 0x50, 0x0d, 0x15, 0x58, 0x15, 0x6c, 0xc3, 0xc6, + 0xd3, 0x8b, 0xc4, 0x65, 0xbb, 0x53, 0xa1, 0x45, 0x87, 0x83, 0x5a, 0xf8, 0xd0, 0x01, 0xfd, 0x90, 0x14, 0x0a, 0x71, + 0x2e, 0xc2, 0x79, 0x16, 0x92, 0xa7, 0x0d, 0x14, 0x46, 0x5e, 0x8c, 0xdf, 0xc6, 0x70, 0xb6, 0xeb, 0x16, 0x23, 0x4b, + 0xd7, 0x74, 0x6b, 0x9c, 0x67, 0x93, 0x1f, 0xd1, 0x13, 0x27, 0x55, 0x24, 0xd9, 0x44, 0x2a, 0xa8, 0x51, 0x1a, 0x6c, + 0xfc, 0x15, 0x00, 0x05, 0x73, 0xc3, 0x6b, 0x1a, 0x8f, 0xb4, 0x4c, 0xc4, 0x5d, 0x8e, 0x06, 0x9b, 0xcc, 0xc1, 0xe3, + 0x60, 0xd0, 0x2b, 0xc4, 0x19, 0xda, 0x05, 0x4e, 0x72, 0xab, 0xc4, 0x1e, 0x7f, 0x91, 0xef, 0x25, 0x5e, 0xd8, 0x94, + 0xa1, 0x47, 0x3c, 0x48, 0x2c, 0x9b, 0x8f, 0xc1, 0xea, 0xfc, 0xbb, 0xfd, 0x90, 0x68, 0x34, 0xd0, 0x01, 0xe8, 0xc8, + 0x97, 0x70, 0xde, 0x13, 0xd3, 0xa4, 0x7b, 0xac, 0xbb, 0xf8, 0xd6, 0xfd, 0xf5, 0x69, 0xf0, 0xdd, 0x21, 0xa3, 0x2f, + 0x70, 0x3b, 0x69, 0xc2, 0x76, 0x6e, 0x5a, 0xeb, 0xfa, 0x03, 0x58, 0x00, 0xa7, 0xcc, 0x78, 0x26, 0x86, 0x97, 0x0d, + 0xfa, 0x46, 0x17, 0xe4, 0xb9, 0xbb, 0x73, 0x1d, 0xf7, 0xe7, 0xb8, 0xf5, 0xe2, 0x94, 0x43, 0x6a, 0x61, 0x11, 0xa8, + 0x19, 0x40, 0x05, 0xe4, 0x65, 0x34, 0x25, 0x5d, 0x10, 0xfc, 0xda, 0xa0, 0xe8, 0x7c, 0x87, 0x31, 0x40, 0xbd, 0xea, + 0x39, 0xcd, 0xfb, 0x5b, 0x4e, 0xf2, 0x42, 0xc4, 0x7b, 0x9b, 0xa6, 0xfa, 0xa7, 0x95, 0x7d, 0xca, 0x94, 0xd7, 0x2f, + 0xcd, 0xd1, 0xd9, 0x84, 0xaa, 0xad, 0xdd, 0xa6, 0x1a, 0xe2, 0x73, 0xbc, 0x64, 0x1e, 0x51, 0xbc, 0x80, 0x81, 0xe6, + 0x81, 0x1f, 0x79, 0xaf, 0xed, 0xdd, 0x68, 0x56, 0x5e, 0xa7, 0x0b, 0xfa, 0x7e, 0x4e, 0xb3, 0x12, 0xbc, 0x67, 0x67, + 0xab, 0x4a, 0xf5, 0x92, 0x0a, 0x86, 0x79, 0xd7, 0x2b, 0x7f, 0x46, 0xbf, 0xd1, 0x13, 0x3f, 0xe5, 0x4d, 0xe3, 0x37, + 0x25, 0xf3, 0xdb, 0x24, 0x4c, 0xea, 0x1c, 0xd6, 0xf4, 0x28, 0xdd, 0x4e, 0x28, 0xe7, 0x41, 0xee, 0x5e, 0xf6, 0x35, + 0xb2, 0xdd, 0x78, 0xa5, 0xfc, 0xe2, 0x8b, 0x96, 0x7f, 0xd7, 0xab, 0xba, 0xd2, 0xa4, 0x79, 0x1a, 0x3b, 0x57, 0x0f, + 0xf5, 0xe9, 0x43, 0x47, 0xa6, 0xfb, 0x23, 0xbe, 0xcc, 0xc8, 0xd0, 0x22, 0x33, 0xdf, 0x55, 0x56, 0x43, 0x5c, 0x6b, + 0x35, 0xf1, 0xee, 0x54, 0xe6, 0xcc, 0x8e, 0xdd, 0x78, 0x91, 0x64, 0x30, 0xaa, 0x8e, 0x4c, 0x0d, 0x89, 0xe4, 0x84, + 0xa8, 0x5f, 0x31, 0x08, 0x98, 0x75, 0x8d, 0x7f, 0xb5, 0xaf, 0x29, 0xb7, 0xe5, 0x5b, 0x8f, 0xb9, 0xfe, 0x36, 0x4e, + 0xb7, 0x5f, 0x13, 0x60, 0xdb, 0x56, 0x5c, 0xea, 0xc5, 0x28, 0xb6, 0x36, 0x32, 0xb1, 0x82, 0x96, 0x27, 0xe0, 0xf0, + 0x80, 0x44, 0xa2, 0xc2, 0xa4, 0xd9, 0x37, 0x92, 0x4a, 0x76, 0xd8, 0xf0, 0xcd, 0x7d, 0xab, 0xb8, 0xa0, 0x8f, 0xf6, + 0x8f, 0x3a, 0x55, 0xd3, 0xcb, 0x42, 0x51, 0x55, 0x1d, 0xf4, 0xa0, 0x29, 0x95, 0xd2, 0xe7, 0x5f, 0xee, 0x4c, 0x12, + 0x10, 0x59, 0x25, 0x81, 0x31, 0x7d, 0x80, 0x62, 0x2a, 0xed, 0x5a, 0x03, 0xa2, 0xc6, 0xbf, 0x21, 0xe1, 0xb7, 0xfa, + 0x31, 0x3d, 0xba, 0x47, 0xdf, 0xfd, 0x5c, 0xda, 0xb5, 0x08, 0x56, 0xe9, 0xad, 0xfe, 0x25, 0x3f, 0xf5, 0x44, 0xd5, + 0xbc, 0x52, 0xbd, 0x33, 0xb4, 0xa7, 0xf9, 0xd3, 0x39, 0x3f, 0x7f, 0x3a, 0xe7, 0x75, 0x30, 0xcc, 0x8c, 0xad, 0x5b, + 0x15, 0xbc, 0x5c, 0xe0, 0xba, 0x84, 0x32, 0x3c, 0xf5, 0xe5, 0x3f, 0x3c, 0x0b, 0x53, 0x19, 0x90, 0x9a, 0x6c, 0x60, + 0x4c, 0x65, 0xe0, 0x74, 0x73, 0x43, 0x47, 0xd3, 0x8d, 0x56, 0x26, 0x9a, 0x19, 0x4f, 0x86, 0x1a, 0x72, 0x1a, 0x73, + 0xb0, 0xa7, 0x87, 0x8c, 0x43, 0xad, 0x66, 0xfc, 0x68, 0xb4, 0x05, 0x6d, 0x40, 0xe1, 0x67, 0x30, 0x53, 0x01, 0x06, + 0xd1, 0xf9, 0x36, 0xce, 0x3e, 0x49, 0x7f, 0x67, 0x99, 0xf3, 0x7c, 0xd9, 0x10, 0xc1, 0xaf, 0x34, 0xe9, 0x76, 0x59, + 0x04, 0xfc, 0x98, 0xd1, 0x58, 0xc6, 0xef, 0xc5, 0xa0, 0x7f, 0x91, 0x3e, 0xaa, 0x11, 0x38, 0x17, 0x20, 0xaf, 0x46, + 0x98, 0x06, 0x8a, 0x86, 0xf6, 0x1a, 0xfa, 0x42, 0xa9, 0x32, 0x7d, 0xed, 0x69, 0x4d, 0x2b, 0xb2, 0xb4, 0xd2, 0x4f, + 0xc6, 0x14, 0xb3, 0x2a, 0x71, 0xec, 0x69, 0xde, 0x37, 0xc8, 0x24, 0x5f, 0x38, 0xcb, 0x68, 0x29, 0xa7, 0xc6, 0x02, + 0xdd, 0x2a, 0xd4, 0xda, 0x85, 0xa7, 0x37, 0x68, 0x1c, 0x18, 0x2a, 0xca, 0xbe, 0x5f, 0x62, 0x8f, 0x78, 0xdf, 0x7e, + 0xc0, 0x47, 0x28, 0xb8, 0xed, 0x39, 0x49, 0x18, 0xa9, 0xfa, 0x5e, 0x51, 0xbc, 0xef, 0x9b, 0x64, 0x24, 0x37, 0x34, + 0x31, 0xd8, 0xa8, 0x85, 0xd3, 0xd3, 0x38, 0x5d, 0x38, 0x3d, 0xc5, 0xa9, 0x45, 0x5b, 0x32, 0xd3, 0xc8, 0x48, 0xac, + 0x5d, 0xe1, 0x44, 0x2d, 0xbf, 0xc9, 0xaf, 0xb2, 0x0d, 0x09, 0x14, 0x95, 0xd6, 0x5e, 0x95, 0x1e, 0xf4, 0x02, 0x36, + 0xe0, 0x4e, 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x2d, 0x40, 0x00, 0x46, 0xf7, 0x3f, 0x58, 0x4d, 0xe9, 0xb4, 0xd1, 0x6e, + 0x4e, 0x39, 0x26, 0x50, 0x72, 0xcd, 0x07, 0x93, 0x90, 0x37, 0x38, 0x71, 0x5e, 0x43, 0xa0, 0x42, 0x1c, 0x43, 0x90, + 0x67, 0xc6, 0x16, 0xf3, 0xfb, 0xb7, 0xaa, 0xfa, 0xa1, 0xa2, 0x53, 0xa8, 0x21, 0x66, 0x5f, 0x68, 0x9e, 0xf0, 0x2b, + 0x72, 0x5e, 0xe6, 0xe4, 0xd2, 0x73, 0x8f, 0xe4, 0xe3, 0xd1, 0xd9, 0x63, 0x24, 0xe8, 0xdb, 0xd5, 0x8e, 0xe6, 0x26, + 0x2c, 0xc5, 0x97, 0xec, 0x67, 0x2a, 0xff, 0x54, 0x2d, 0x14, 0xcf, 0xac, 0xce, 0x3b, 0x65, 0xb1, 0xab, 0x2a, 0x76, + 0x49, 0x67, 0xd0, 0x29, 0x78, 0x33, 0x20, 0x82, 0x8e, 0xe0, 0x24, 0x49, 0x20, 0x11, 0x8d, 0x02, 0xed, 0xd9, 0x4c, + 0x24, 0xc1, 0x5c, 0x80, 0x25, 0xcb, 0x1b, 0x2e, 0x76, 0xed, 0x2f, 0xdd, 0x92, 0xcc, 0x13, 0x70, 0xd1, 0x3c, 0xd3, + 0xe9, 0xe5, 0x3a, 0xf2, 0x39, 0xc2, 0xd4, 0xba, 0xa9, 0xcd, 0xab, 0x84, 0xf3, 0x55, 0xb9, 0x89, 0x95, 0x78, 0x1b, + 0xa8, 0x19, 0xaf, 0x56, 0x2a, 0x7f, 0x62, 0x72, 0x4a, 0x6b, 0x64, 0xa4, 0xb0, 0x3f, 0xa4, 0xaa, 0x6d, 0x94, 0x70, + 0x1b, 0xd2, 0x6f, 0xe7, 0xa7, 0xed, 0x42, 0xf1, 0x5b, 0x3b, 0x18, 0xf2, 0xff, 0xf5, 0x1a, 0xdb, 0x85, 0xa8, 0x51, + 0x60, 0x84, 0x70, 0xb1, 0x08, 0x10, 0x9e, 0x0b, 0xa7, 0x6c, 0x88, 0x85, 0x07, 0x8f, 0xc2, 0xd9, 0xeb, 0xac, 0xab, + 0xde, 0x6f, 0xfe, 0x3e, 0xa8, 0xbf, 0x8f, 0x42, 0xe3, 0x5c, 0xaf, 0xf1, 0x6f, 0x15, 0x3f, 0xfe, 0xd0, 0x42, 0xb1, + 0x81, 0x11, 0x6e, 0x22, 0x68, 0xa5, 0x68, 0xb6, 0x25, 0xd5, 0xfa, 0xaa, 0x80, 0x22, 0x84, 0xdd, 0x49, 0x55, 0x0b, + 0x26, 0xac, 0x3b, 0x3d, 0xc1, 0xf2, 0xf9, 0xc0, 0xe9, 0x3f, 0xa6, 0xed, 0x39, 0x49, 0x54, 0xfa, 0xac, 0x4f, 0x85, + 0x27, 0x4f, 0xa2, 0xd5, 0x3e, 0xf3, 0x2f, 0xc1, 0xad, 0xaf, 0x7e, 0xb5, 0xac, 0x46, 0xca, 0x4c, 0x31, 0x8b, 0xc2, + 0x6b, 0xb7, 0x86, 0x99, 0xf1, 0x8a, 0x62, 0xd2, 0x34, 0x7b, 0x58, 0x0a, 0x8a, 0xbb, 0xba, 0x66, 0x65, 0x4e, 0xe7, + 0x65, 0x46, 0xe6, 0x54, 0x82, 0x71, 0x54, 0x7c, 0x8f, 0x33, 0x7e, 0xa3, 0xad, 0x18, 0x18, 0x75, 0x3c, 0xec, 0xf4, + 0x1c, 0xeb, 0x84, 0x01, 0x7a, 0xe5, 0xb9, 0x89, 0xf0, 0x1a, 0x2f, 0x81, 0x53, 0xa7, 0x36, 0x7d, 0x10, 0x69, 0xe5, + 0xa8, 0x29, 0xcf, 0xb0, 0xc5, 0x94, 0x5e, 0xe3, 0x36, 0x91, 0x76, 0xfb, 0x2f, 0x76, 0x5e, 0x05, 0x9f, 0xd8, 0xd3, + 0x11, 0x1e, 0xd1, 0xa4, 0xb4, 0x08, 0x5e, 0x24, 0xca, 0xc3, 0xf6, 0xc0, 0x73, 0x7e, 0x25, 0xd6, 0x5e, 0x4e, 0x94, + 0xf2, 0x7c, 0xe6, 0x39, 0x88, 0x21, 0x33, 0xb4, 0x84, 0x8e, 0xcf, 0x05, 0x47, 0x62, 0x5c, 0xbd, 0x4f, 0x90, 0xc4, + 0x49, 0xb0, 0xf7, 0xd7, 0x3e, 0x17, 0x69, 0x75, 0xfc, 0xf2, 0x3e, 0x61, 0x21, 0xb6, 0x6b, 0xda, 0x05, 0x2a, 0x64, + 0x3f, 0xf8, 0x53, 0x02, 0x5e, 0x13, 0xf2, 0xb2, 0xef, 0xd4, 0x6e, 0x9d, 0x75, 0xce, 0xff, 0x0b, 0x87, 0x43, 0x8f, + 0x5e, 0x39, 0x9a, 0x6b, 0x26, 0x60, 0x72, 0xc0, 0x51, 0xd5, 0xf7, 0xa2, 0xc4, 0xd1, 0xf0, 0x40, 0xa0, 0xac, 0x12, + 0xff, 0xb0, 0x7e, 0x30, 0x24, 0xa0, 0xf2, 0x88, 0xfb, 0xee, 0xd6, 0xee, 0x9a, 0x76, 0x65, 0x13, 0x2e, 0x57, 0x32, + 0xfe, 0x1b, 0x10, 0xa6, 0xef, 0x03, 0xce, 0xe1, 0xe8, 0xac, 0xfb, 0x02, 0x6e, 0x32, 0xe7, 0x14, 0xa3, 0xb8, 0x96, + 0x7c, 0xc1, 0xf6, 0x94, 0x90, 0xd7, 0xc4, 0x2e, 0xbf, 0x58, 0x47, 0xa1, 0x57, 0x9d, 0xd4, 0xcb, 0xb2, 0xe8, 0xbf, + 0x80, 0x75, 0x82, 0x78, 0x79, 0x9e, 0xe9, 0xb2, 0x6f, 0x12, 0x87, 0x2b, 0xac, 0xb0, 0x99, 0x95, 0x86, 0x66, 0x61, + 0xfa, 0x98, 0xd2, 0x75, 0x2c, 0x30, 0x0e, 0x55, 0xce, 0x76, 0x09, 0x6c, 0x49, 0xaa, 0x99, 0xc6, 0xfb, 0x0d, 0x59, + 0x85, 0x49, 0x4b, 0x2b, 0x8d, 0x17, 0xe8, 0x1e, 0x6b, 0x3c, 0xff, 0x4b, 0x30, 0x4c, 0x18, 0x67, 0x2f, 0xc3, 0xc4, + 0x4f, 0x2a, 0xb8, 0xaa, 0x79, 0x82, 0xc3, 0xe6, 0x9d, 0xf9, 0xab, 0xb6, 0x75, 0xc0, 0x4f, 0xb2, 0x2f, 0x1a, 0xc3, + 0x98, 0x2c, 0x2c, 0x06, 0xee, 0xd2, 0xd8, 0xcf, 0xc1, 0xc2, 0x0d, 0xfb, 0xe8, 0x1b, 0x05, 0x5f, 0xfa, 0xf7, 0x77, + 0xa0, 0x4e, 0x62, 0xd4, 0x75, 0x69, 0x25, 0xa5, 0xbf, 0x46, 0xbe, 0x68, 0x03, 0x88, 0x34, 0x4f, 0x7d, 0x8c, 0x85, + 0x53, 0x41, 0xc4, 0x92, 0x12, 0x61, 0xed, 0x8c, 0x30, 0x6b, 0x65, 0xf9, 0xfe, 0x6c, 0xea, 0x08, 0x05, 0x5d, 0x3b, + 0xcb, 0x9f, 0x73, 0xe9, 0x66, 0x11, 0x5d, 0x37, 0xc0, 0x58, 0x96, 0x1d, 0x51, 0x0e, 0x9e, 0x60, 0xdb, 0xea, 0xae, + 0x88, 0xbc, 0xa1, 0x3e, 0x49, 0xac, 0x4e, 0xe8, 0x23, 0x8e, 0xd6, 0xf9, 0x68, 0x13, 0x4d, 0xbe, 0x59, 0xe5, 0xf2, + 0xd3, 0x26, 0xe6, 0x34, 0xd4, 0xc5, 0x0c, 0x62, 0x38, 0xf8, 0x4e, 0x84, 0xce, 0xa6, 0x7d, 0xdc, 0xa0, 0xcd, 0xc2, + 0x19, 0x9a, 0x86, 0xeb, 0x10, 0x6f, 0x2a, 0x61, 0x51, 0xd9, 0x42, 0xd3, 0x29, 0x9d, 0x70, 0x75, 0x57, 0x98, 0x9b, + 0x73, 0xee, 0xa9, 0xe5, 0x1a, 0xba, 0x26, 0x02, 0x85, 0xe2, 0xb1, 0xe5, 0x1a, 0x7d, 0x75, 0x50, 0xa9, 0x42, 0xa7, + 0xdb, 0x79, 0xf6, 0x2a, 0x16, 0x1c, 0xae, 0x8c, 0xc5, 0x1c, 0x60, 0xe0, 0xa7, 0x71, 0xf2, 0xbe, 0x8a, 0xec, 0x54, + 0x5a, 0x72, 0xde, 0xa5, 0xe4, 0xc0, 0x25, 0xf5, 0xcf, 0x6d, 0x5e, 0x9d, 0x2f, 0x73, 0x9b, 0x29, 0x78, 0x0b, 0x6e, + 0xe9, 0xb4, 0x1e, 0x87, 0xa2, 0xed, 0x10, 0x53, 0xe5, 0x5e, 0x29, 0x25, 0xcf, 0x9a, 0x6a, 0x28, 0x59, 0xe7, 0x18, + 0xeb, 0x8f, 0x0e, 0x51, 0x3e, 0xc4, 0x34, 0xe2, 0x70, 0xa7, 0x62, 0x55, 0xf2, 0x64, 0x25, 0x48, 0x88, 0xd5, 0x36, + 0xcc, 0x0c, 0x5a, 0x59, 0x26, 0xaa, 0x7d, 0x77, 0x9e, 0x47, 0x89, 0x31, 0xbe, 0x32, 0xcb, 0xc2, 0xd7, 0xe5, 0x0e, + 0x74, 0x82, 0x34, 0xb7, 0x9b, 0xc0, 0xb2, 0x5e, 0xa3, 0x11, 0xe6, 0xd3, 0x38, 0x4a, 0x48, 0x40, 0x24, 0xd5, 0x2f, + 0x48, 0x97, 0x12, 0xee, 0x7a, 0xf4, 0x67, 0xf9, 0x20, 0x84, 0xf9, 0xf0, 0xe5, 0x84, 0x53, 0x97, 0x60, 0x3b, 0xde, + 0xe4, 0xb5, 0x02, 0x95, 0x44, 0xd3, 0x6b, 0x2b, 0x4e, 0x75, 0xa9, 0x7a, 0x5b, 0x8c, 0xe2, 0x34, 0xfd, 0xaa, 0x27, + 0xb9, 0xd9, 0x62, 0x61, 0x2c, 0x18, 0x04, 0x1a, 0x50, 0xd1, 0x4d, 0x00, 0xab, 0x31, 0x16, 0x11, 0xaf, 0xcb, 0x0f, + 0x99, 0x54, 0x53, 0x3a, 0x54, 0xed, 0xda, 0xef, 0x0f, 0xee, 0xdd, 0xf0, 0x70, 0xfc, 0xf8, 0x9f, 0xfb, 0xbd, 0x1e, + 0x54, 0x41, 0x97, 0xf0, 0x71, 0x67, 0x3b, 0xa6, 0x42, 0x01, 0xb2, 0xb2, 0x7d, 0x79, 0x01, 0x50, 0x63, 0x2a, 0x4e, + 0xba, 0x6b, 0xeb, 0xde, 0xb4, 0xe0, 0xd3, 0xba, 0x09, 0xdf, 0xfb, 0xe6, 0x7c, 0x6f, 0x98, 0x5a, 0x77, 0xf8, 0xdc, + 0xe5, 0x33, 0x9e, 0x02, 0x99, 0x0b, 0x83, 0xf7, 0x90, 0xe2, 0x26, 0x4c, 0x32, 0xe4, 0x6c, 0x9a, 0x77, 0xda, 0xb2, + 0xbc, 0xd6, 0x52, 0xb2, 0x23, 0x26, 0xec, 0xb9, 0xf2, 0x47, 0xde, 0x93, 0xf8, 0x48, 0x35, 0x04, 0xe0, 0x04, 0xa5, + 0x8d, 0xc0, 0x5c, 0xc5, 0xcd, 0xfc, 0xa9, 0x21, 0x88, 0x08, 0xf4, 0x4c, 0xe1, 0xde, 0xce, 0x1f, 0xce, 0xc6, 0x08, + 0x41, 0x2a, 0xf8, 0x66, 0xa5, 0x36, 0x6b, 0x78, 0xe9, 0x3f, 0x66, 0x67, 0x3b, 0x32, 0xd3, 0xdd, 0x26, 0x51, 0x5b, + 0xb6, 0xa6, 0x02, 0xcc, 0x20, 0x1a, 0x03, 0x17, 0x3c, 0x30, 0xa6, 0xf1, 0xd1, 0x9b, 0x71, 0x62, 0xad, 0xdd, 0xf2, + 0xe5, 0x8c, 0x8f, 0x1c, 0x7d, 0x4e, 0x16, 0xa8, 0x71, 0x77, 0x18, 0xcb, 0xcb, 0xf8, 0x6e, 0x3d, 0x6e, 0x56, 0xf7, + 0x20, 0x0b, 0x08, 0xd0, 0x6b, 0xb1, 0xae, 0x99, 0xe8, 0x55, 0xc2, 0x9d, 0x54, 0x9a, 0x27, 0x95, 0x98, 0x59, 0xe5, + 0xe5, 0xb5, 0xd3, 0xcb, 0x90, 0xbc, 0x0c, 0xd6, 0x6e, 0x54, 0xa1, 0xc7, 0xd6, 0x58, 0xe3, 0xb8, 0x66, 0x92, 0xa5, + 0xf1, 0xd7, 0xf0, 0x51, 0x3f, 0xbc, 0x5c, 0x45, 0xeb, 0xa6, 0x5a, 0xb4, 0x5e, 0x5b, 0x39, 0xcc, 0x97, 0xbc, 0xf8, + 0x85, 0x2d, 0xb6, 0xf0, 0x7a, 0xb1, 0xb9, 0x8f, 0xa8, 0x4c, 0x25, 0xaa, 0xd3, 0x4a, 0x54, 0xa6, 0x89, 0xc9, 0xcf, + 0x9e, 0x77, 0x01, 0x5c, 0x7f, 0xd4, 0xa9, 0x55, 0xfc, 0xa8, 0x32, 0xaa, 0xfc, 0x51, 0x23, 0x54, 0xeb, 0x13, 0x40, + 0x94, 0xc0, 0xac, 0x91, 0x87, 0x99, 0xb5, 0x61, 0x32, 0x29, 0xeb, 0x0b, 0x72, 0x85, 0xc3, 0xb4, 0xaa, 0x56, 0xbd, + 0xff, 0xe5, 0x86, 0xeb, 0x2f, 0x9b, 0xfc, 0x6e, 0xc6, 0xf5, 0xbe, 0x92, 0xfd, 0x60, 0x39, 0x18, 0x2c, 0xb4, 0xf1, + 0xe3, 0x16, 0xea, 0x7e, 0x8c, 0x1e, 0x86, 0xe0, 0xca, 0xf4, 0x35, 0x88, 0xfa, 0x95, 0x20, 0xf3, 0x23, 0xf2, 0x5a, + 0x01, 0x72, 0xb1, 0xd7, 0x37, 0xd2, 0xbb, 0xd6, 0x20, 0x1a, 0x1b, 0x12, 0xa9, 0xb3, 0x48, 0x86, 0x21, 0xb5, 0x7d, + 0xb8, 0xce, 0xe8, 0x68, 0xde, 0xe4, 0x2d, 0xbe, 0xa9, 0x86, 0x26, 0xcc, 0xb7, 0x0a, 0xab, 0x91, 0x9e, 0x93, 0xa6, + 0x29, 0x69, 0x56, 0xf6, 0x4d, 0xd0, 0xaf, 0x5e, 0x44, 0x26, 0x34, 0x06, 0x5f, 0x64, 0x70, 0xe0, 0xb7, 0x2b, 0x3a, + 0x0a, 0xd1, 0x4f, 0x79, 0x73, 0xff, 0x55, 0x30, 0x4a, 0xfd, 0x00, 0xb1, 0x6f, 0xd1, 0x05, 0x66, 0x67, 0x05, 0x7c, + 0x0b, 0xeb, 0xed, 0x05, 0x79, 0x94, 0xc6, 0xce, 0xc2, 0x11, 0x35, 0x61, 0xad, 0xf7, 0xb0, 0x31, 0xb2, 0xde, 0xf9, + 0xe7, 0xba, 0x2b, 0x51, 0x84, 0x4b, 0xcf, 0x65, 0x82, 0xea, 0xc0, 0x45, 0xe5, 0x5b, 0x6a, 0x2f, 0xa5, 0x09, 0xa7, + 0x22, 0x5f, 0x0c, 0x1b, 0xde, 0x87, 0xc3, 0xbe, 0x86, 0xc3, 0x0f, 0x7c, 0xd3, 0x5a, 0x6b, 0x26, 0x5b, 0x35, 0xb2, + 0x0b, 0x2e, 0xb8, 0xc0, 0xb0, 0x83, 0x81, 0xf5, 0xec, 0x7d, 0x1e, 0x82, 0xa6, 0x03, 0x61, 0xc1, 0x58, 0x34, 0xb7, + 0x01, 0x4f, 0x3e, 0x60, 0xa0, 0xd4, 0xcd, 0xdb, 0x6d, 0xd9, 0x22, 0xb9, 0x0d, 0x0c, 0xa9, 0xc5, 0x38, 0xcb, 0xe2, + 0xc0, 0x99, 0x3a, 0x9b, 0xe7, 0xfa, 0x46, 0x19, 0x77, 0xad, 0x44, 0x49, 0x1b, 0xbf, 0x9e, 0x0d, 0xee, 0x19, 0x29, + 0x74, 0x93, 0xff, 0x2f, 0x21, 0xe5, 0x5d, 0xae, 0x0a, 0x82, 0x6e, 0x70, 0xd2, 0xd7, 0x5a, 0xba, 0xc8, 0x4c, 0x44, + 0x77, 0x80, 0x2b, 0x68, 0x52, 0xae, 0x3d, 0x41, 0xd2, 0x67, 0x2b, 0xb7, 0x39, 0x11, 0xdb, 0x3d, 0x23, 0x9d, 0xd9, + 0x12, 0xea, 0xf3, 0x0b, 0x56, 0x97, 0x77, 0xee, 0x28, 0xe5, 0x73, 0x65, 0xcc, 0x78, 0x24, 0xcd, 0xb3, 0x3f, 0x4a, + 0x21, 0x4d, 0xc6, 0xf5, 0x22, 0x32, 0x9f, 0x97, 0xdb, 0x5b, 0x81, 0x07, 0x9e, 0xaa, 0xc0, 0x10, 0xb4, 0xde, 0x4b, + 0x7c, 0xf3, 0x55, 0x0d, 0xca, 0x3a, 0x19, 0x3f, 0x3e, 0x56, 0xbf, 0x35, 0xf6, 0xa2, 0xd2, 0xe4, 0x10, 0xcd, 0xd4, + 0x76, 0x5a, 0xe7, 0x2d, 0xa8, 0x65, 0x6a, 0xd7, 0x09, 0xa4, 0xd1, 0x39, 0xcf, 0x56, 0x91, 0x98, 0x6a, 0xfe, 0x6b, + 0xa6, 0x84, 0xbe, 0xaf, 0x50, 0x25, 0xfe, 0x19, 0x17, 0x89, 0x30, 0xe2, 0x3c, 0x50, 0x0f, 0x61, 0xd5, 0x12, 0x87, + 0xca, 0xbb, 0x31, 0x8c, 0x0b, 0x66, 0xe1, 0x10, 0x1b, 0x65, 0x7e, 0x16, 0x93, 0x4f, 0x97, 0x05, 0x4f, 0xce, 0xaf, + 0x64, 0x99, 0x75, 0xb3, 0x4f, 0x88, 0x87, 0x47, 0xed, 0x21, 0xd5, 0x2d, 0x0b, 0xad, 0x59, 0x59, 0x2f, 0xca, 0x6e, + 0xd4, 0x3e, 0x8b, 0x2f, 0xc8, 0x68, 0xd2, 0x1e, 0x78, 0xdc, 0x4b, 0x12, 0x48, 0x55, 0x2d, 0xdb, 0xcc, 0x21, 0xf2, + 0xf0, 0xf2, 0x21, 0x4f, 0xf9, 0xac, 0x4c, 0x54, 0x94, 0xb6, 0xc3, 0xe0, 0x81, 0xfb, 0x3a, 0x9a, 0xa0, 0x53, 0xac, + 0xd3, 0x15, 0x44, 0x6f, 0xc0, 0xac, 0x37, 0x8a, 0x3d, 0xab, 0xac, 0x4a, 0x36, 0xed, 0xe5, 0x1a, 0xbf, 0x71, 0x90, + 0x16, 0xdc, 0xd8, 0xe3, 0x48, 0x5d, 0x2f, 0x4a, 0xd7, 0xf5, 0x66, 0x6f, 0xb9, 0xd3, 0xea, 0x03, 0x3e, 0xfd, 0x94, + 0x6c, 0xc9, 0x5f, 0x2f, 0x5d, 0x93, 0x56, 0x6e, 0x0b, 0x1a, 0x35, 0xd6, 0x64, 0xbc, 0xe9, 0x4b, 0x10, 0x15, 0x55, + 0x09, 0x9e, 0x53, 0x7e, 0x36, 0x8c, 0x46, 0x32, 0xd1, 0x80, 0x7c, 0x69, 0xed, 0x7e, 0xae, 0x55, 0xbc, 0xb5, 0x3a, + 0x74, 0xca, 0xea, 0xe0, 0xf8, 0xd2, 0xb9, 0xd9, 0xba, 0x28, 0x14, 0x20, 0x01, 0xf6, 0x50, 0x43, 0x8e, 0x9d, 0xd5, + 0x8c, 0xdb, 0xdb, 0x6f, 0x1b, 0x31, 0x90, 0x62, 0x2e, 0xfb, 0xae, 0x1f, 0x22, 0x64, 0x32, 0x23, 0x4c, 0xac, 0x91, + 0xdd, 0x18, 0xa3, 0x09, 0x09, 0xc9, 0x78, 0x2d, 0x84, 0x84, 0xde, 0xea, 0x3c, 0x01, 0x5c, 0x12, 0x4f, 0x06, 0x6b, + 0x0a, 0x66, 0x45, 0x5e, 0x57, 0x5b, 0x71, 0x25, 0x16, 0x89, 0xf0, 0x75, 0x51, 0x23, 0xdb, 0x26, 0x58, 0x41, 0x8b, + 0x62, 0x0e, 0x14, 0x3a, 0xf3, 0x0d, 0x5f, 0x30, 0xe1, 0x9c, 0xdf, 0x75, 0x6b, 0x94, 0x96, 0x99, 0xa0, 0xaf, 0x1a, + 0x16, 0xb6, 0xdb, 0x2f, 0x10, 0xd7, 0x34, 0x03, 0x03, 0x8a, 0xb2, 0x43, 0x35, 0xbf, 0x03, 0x4b, 0x94, 0x9c, 0xb4, + 0x91, 0x9b, 0x5f, 0xa1, 0x63, 0x82, 0x18, 0x58, 0x68, 0x6c, 0x2f, 0x64, 0x2b, 0xd1, 0x9a, 0x1a, 0xb2, 0x11, 0x36, + 0xc1, 0x07, 0xa7, 0xa7, 0x70, 0x6d, 0x02, 0x55, 0xd3, 0x94, 0x46, 0x60, 0x9e, 0xf0, 0x40, 0x69, 0xbe, 0x9f, 0x5d, + 0x10, 0xd8, 0x98, 0xb7, 0x22, 0x8b, 0x03, 0x92, 0x12, 0x1b, 0x58, 0x78, 0xd4, 0x58, 0x2f, 0xef, 0x34, 0x8e, 0x2e, + 0xab, 0x51, 0x57, 0xa4, 0x58, 0x2a, 0x69, 0xc6, 0xa2, 0xc1, 0x98, 0x92, 0x90, 0x64, 0x2d, 0x04, 0x6b, 0x36, 0xfc, + 0xcd, 0x7b, 0x54, 0x7f, 0x6b, 0x2e, 0x60, 0x4f, 0x30, 0xdb, 0x79, 0x31, 0xbd, 0xbe, 0x1a, 0x65, 0xdb, 0xba, 0x85, + 0x79, 0x4f, 0x61, 0xd0, 0x9c, 0x8f, 0x29, 0x65, 0xce, 0x33, 0x40, 0x99, 0x49, 0x16, 0x01, 0x39, 0x0c, 0xb8, 0x07, + 0xa4, 0x2b, 0x2f, 0x0e, 0x7b, 0x19, 0xad, 0x9c, 0xb9, 0xf0, 0xf2, 0x72, 0x75, 0x34, 0x41, 0x39, 0x50, 0xe4, 0xc0, + 0x8b, 0xeb, 0x17, 0x4f, 0x73, 0x2d, 0x56, 0x59, 0x6f, 0x58, 0xa8, 0xae, 0xb7, 0xf4, 0xb9, 0xf5, 0x31, 0xf0, 0xf9, + 0xb5, 0x96, 0x5a, 0x34, 0x7f, 0xe8, 0xb5, 0xd5, 0xa4, 0xa0, 0xdd, 0xbf, 0xf5, 0x64, 0x14, 0x39, 0xa5, 0xd5, 0xb2, + 0xf8, 0x54, 0xbb, 0xe8, 0x29, 0x5a, 0xca, 0x26, 0xef, 0xb2, 0x87, 0xaa, 0x0b, 0xb3, 0xd6, 0x51, 0x98, 0xd5, 0xf6, + 0x28, 0xef, 0xec, 0xbd, 0x36, 0x0b, 0xca, 0x94, 0x56, 0x9f, 0x70, 0xbd, 0xf1, 0x02, 0xaa, 0xf9, 0x96, 0x1a, 0x8b, + 0x63, 0x7e, 0x49, 0x5d, 0xd9, 0x28, 0x7b, 0x9e, 0xd6, 0xb8, 0xbc, 0xeb, 0xa2, 0x17, 0x53, 0xc0, 0x29, 0xca, 0x4a, + 0x17, 0x37, 0x72, 0x09, 0x5d, 0x2b, 0xd2, 0x1a, 0xf8, 0x0c, 0x8c, 0x62, 0xb2, 0x9a, 0x7c, 0x90, 0xf4, 0xdf, 0x99, + 0xf5, 0x57, 0x9d, 0xb9, 0xfe, 0xa6, 0x17, 0xae, 0xbf, 0x5e, 0x54, 0x56, 0x85, 0x7d, 0x63, 0xec, 0x19, 0x70, 0x05, + 0x93, 0x4a, 0x7c, 0xa5, 0x73, 0x8e, 0x08, 0x6a, 0x0c, 0x15, 0xb2, 0x9b, 0x2f, 0x2c, 0x6c, 0x88, 0x3c, 0x3b, 0xbb, + 0xcc, 0xd2, 0x35, 0xd6, 0x98, 0xdc, 0xdf, 0xbb, 0x82, 0x59, 0x17, 0x56, 0x2d, 0xe3, 0x55, 0xce, 0xa5, 0x28, 0x92, + 0x62, 0x72, 0x91, 0x83, 0x14, 0x21, 0x80, 0x90, 0x8b, 0x24, 0xd0, 0x51, 0xda, 0xa2, 0x68, 0x24, 0x14, 0x80, 0xfa, + 0x72, 0xbe, 0x05, 0x08, 0x1c, 0x82, 0x39, 0x21, 0x08, 0x46, 0xf2, 0x2c, 0x20, 0x72, 0x42, 0xf6, 0x4e, 0x54, 0x88, + 0x30, 0xab, 0x83, 0x13, 0x68, 0x50, 0x16, 0xd8, 0xa2, 0x79, 0x99, 0x09, 0x8a, 0x2a, 0x44, 0x84, 0x65, 0xc5, 0xe5, + 0xea, 0x8f, 0x2e, 0x6d, 0xbd, 0x5c, 0x53, 0xe8, 0x92, 0xe5, 0xd3, 0xec, 0x1a, 0xca, 0xfc, 0x00, 0xfc, 0x6b, 0x51, + 0x07, 0xf6, 0xb4, 0x83, 0x34, 0xb0, 0x15, 0x17, 0xa7, 0xe2, 0xfa, 0xe7, 0x9c, 0x02, 0x42, 0x49, 0x4f, 0x2b, 0xc4, + 0x5c, 0xa0, 0x73, 0x0f, 0x71, 0x0d, 0x0a, 0x80, 0xe1, 0x92, 0xf1, 0xc2, 0x50, 0xdb, 0x7a, 0x7a, 0xea, 0xfc, 0x1e, + 0xc9, 0x35, 0x3a, 0x34, 0xf1, 0x22, 0xca, 0xdc, 0x65, 0x61, 0x3b, 0x52, 0xbc, 0xe7, 0x46, 0xb5, 0xc7, 0x94, 0x97, + 0xe7, 0x7b, 0xe8, 0x2f, 0xc4, 0xbc, 0x6d, 0x82, 0xaa, 0xa7, 0x7b, 0x6f, 0xad, 0x8b, 0xc0, 0x8f, 0x5e, 0x16, 0x05, + 0xea, 0xdb, 0x15, 0x23, 0x0d, 0x3d, 0xd9, 0xb1, 0x42, 0x97, 0x69, 0x59, 0xdb, 0xbb, 0xcd, 0xfa, 0xb6, 0x06, 0x83, + 0x8c, 0x7d, 0xa5, 0x78, 0x05, 0x84, 0x4d, 0xf1, 0x64, 0x26, 0xda, 0x6a, 0x08, 0x4e, 0x10, 0xca, 0xe9, 0xea, 0xf0, + 0xad, 0x20, 0x45, 0x45, 0x60, 0xeb, 0x7e, 0xac, 0x3d, 0xd4, 0xbe, 0x1b, 0x4a, 0xa7, 0x67, 0x8f, 0x1a, 0x1c, 0x3d, + 0xe5, 0x05, 0x3b, 0x34, 0x52, 0x97, 0x16, 0x21, 0x55, 0xf1, 0xb6, 0x01, 0xab, 0xf4, 0xe0, 0xd3, 0x06, 0x33, 0x9f, + 0xb1, 0xe2, 0x0e, 0x72, 0x15, 0x1b, 0xd1, 0x08, 0x05, 0xdd, 0x23, 0xf2, 0xf3, 0xfe, 0x82, 0x3d, 0x37, 0xe6, 0x56, + 0xf0, 0x4b, 0xc0, 0x30, 0xd5, 0x2b, 0x4c, 0x58, 0x2d, 0x8d, 0x16, 0x60, 0xe9, 0x8d, 0x67, 0xab, 0x66, 0xaf, 0x7c, + 0x2a, 0x95, 0x14, 0xab, 0x10, 0xbe, 0x53, 0x65, 0x05, 0x27, 0x1f, 0x62, 0x30, 0xc4, 0x4f, 0xdf, 0x56, 0x7e, 0xbd, + 0xea, 0xe6, 0x50, 0xf1, 0xa8, 0xb1, 0xa7, 0x3d, 0x8c, 0x92, 0xda, 0xf0, 0xaa, 0xc3, 0x10, 0x77, 0x67, 0xd9, 0x99, + 0x3d, 0x45, 0xd6, 0x54, 0x02, 0xf8, 0x15, 0x9b, 0xa2, 0x2e, 0x83, 0x8f, 0x88, 0x79, 0x23, 0x60, 0xfe, 0x66, 0x50, + 0x8c, 0xe6, 0x4d, 0x15, 0xad, 0x16, 0xf7, 0x26, 0x74, 0xc9, 0xb8, 0x44, 0xd9, 0xd3, 0x87, 0xf4, 0x3b, 0x24, 0x18, + 0x39, 0xdd, 0xac, 0xb8, 0xaf, 0x07, 0x87, 0x63, 0x1f, 0x5b, 0x97, 0x30, 0x05, 0x40, 0x8b, 0x5c, 0x4c, 0x80, 0xe9, + 0x7a, 0xcd, 0xb1, 0x90, 0xad, 0x0b, 0x49, 0x34, 0x34, 0x85, 0xa2, 0x6e, 0x41, 0x30, 0x31, 0x2a, 0xed, 0xf6, 0x83, + 0xb4, 0x30, 0x9e, 0x33, 0x95, 0x5f, 0x90, 0x1f, 0x4e, 0x7d, 0xd9, 0x1a, 0x7b, 0xa3, 0x63, 0x56, 0x34, 0xf1, 0xa4, + 0x99, 0x80, 0x48, 0x00, 0x2f, 0x17, 0xd1, 0x66, 0x9c, 0xa7, 0x92, 0x9a, 0xd7, 0x76, 0x81, 0x98, 0x01, 0x02, 0x9d, + 0x6a, 0x49, 0xa5, 0x78, 0x73, 0x3e, 0x48, 0x71, 0x10, 0x80, 0xb2, 0x63, 0x36, 0xb4, 0xa5, 0xa0, 0x1e, 0x32, 0xb4, + 0xd9, 0x5c, 0xdb, 0x5a, 0xee, 0xd4, 0xd9, 0xac, 0x45, 0x6d, 0x99, 0x3f, 0xdc, 0xe6, 0x17, 0x11, 0xe3, 0xa2, 0xee, + 0x13, 0x09, 0xd5, 0x14, 0x23, 0xd0, 0x79, 0x02, 0xf2, 0x7a, 0x38, 0xe1, 0xcd, 0x7d, 0xbf, 0x6f, 0xe9, 0x9a, 0x64, + 0xf1, 0xa2, 0xc0, 0xb9, 0x2f, 0x53, 0x78, 0x99, 0x70, 0x02, 0x97, 0x78, 0xa8, 0x33, 0x1f, 0x67, 0x5b, 0x9d, 0x29, + 0x46, 0xa0, 0xa4, 0x16, 0x91, 0x4d, 0x7a, 0x43, 0x90, 0x9a, 0xf1, 0x32, 0x10, 0x6a, 0x47, 0xa9, 0x01, 0xc9, 0xfb, + 0xba, 0x32, 0x5e, 0x4b, 0xb6, 0x2e, 0x42, 0xd9, 0x6c, 0xc7, 0xb5, 0xbb, 0x9c, 0x4e, 0x77, 0x37, 0x2b, 0xe4, 0x0e, + 0x28, 0x9d, 0x0d, 0x97, 0x11, 0xdf, 0xd0, 0xec, 0x40, 0x81, 0xd0, 0x6e, 0xdf, 0x66, 0x65, 0xcc, 0xc2, 0xe2, 0x75, + 0x43, 0x8e, 0x4a, 0xfe, 0x50, 0xde, 0x9d, 0xf5, 0x6e, 0xc3, 0x53, 0xdb, 0xc1, 0x7a, 0x50, 0x28, 0xfb, 0xd8, 0xa7, + 0x46, 0xe1, 0x0f, 0xdc, 0x2a, 0x91, 0x75, 0x08, 0xeb, 0xec, 0xc2, 0x3b, 0x2a, 0xd3, 0x31, 0x6d, 0x3b, 0x9b, 0x87, + 0xcd, 0x46, 0x41, 0xba, 0x2c, 0xe1, 0x78, 0x6d, 0xa5, 0xee, 0xd4, 0xc3, 0x73, 0x37, 0x4a, 0xdf, 0x97, 0x58, 0x5e, + 0xb6, 0x51, 0xf7, 0x76, 0x12, 0x4b, 0xf8, 0xcc, 0x3a, 0x71, 0x09, 0xee, 0x80, 0xb9, 0xca, 0x4e, 0x44, 0x2d, 0x90, + 0xd4, 0x7f, 0xe1, 0xe5, 0x8f, 0x06, 0xe3, 0x92, 0x93, 0xab, 0x5e, 0x4d, 0x20, 0x31, 0x13, 0x32, 0x47, 0xab, 0x77, + 0x03, 0x9a, 0x82, 0xae, 0x6b, 0x91, 0x03, 0x02, 0x4f, 0x6c, 0x7a, 0xf9, 0xed, 0x08, 0xe2, 0xec, 0x2e, 0x27, 0x34, + 0xac, 0xe1, 0x59, 0x76, 0xb1, 0x92, 0xb1, 0x6b, 0x8f, 0xa7, 0xc7, 0x2e, 0x95, 0x96, 0x4d, 0x18, 0xf3, 0xdb, 0xba, + 0xde, 0x28, 0x9e, 0x22, 0xa6, 0x5d, 0x9c, 0xca, 0x18, 0xae, 0x56, 0x9f, 0xe3, 0x79, 0x51, 0x05, 0x49, 0x5c, 0x12, + 0xa5, 0x37, 0xd6, 0x6f, 0xb9, 0x1c, 0x55, 0x15, 0xcb, 0xd9, 0xf9, 0x6d, 0xca, 0xab, 0xdf, 0x83, 0x7f, 0x7c, 0x95, + 0xb1, 0x08, 0xaa, 0x8c, 0xc8, 0x8c, 0x7d, 0x74, 0x11, 0x2d, 0xf4, 0xb3, 0xb6, 0x74, 0x15, 0x5d, 0xaf, 0xcc, 0x6b, + 0x88, 0x20, 0x70, 0xab, 0xea, 0x14, 0x52, 0x66, 0xd1, 0x98, 0x67, 0x15, 0xb3, 0x6b, 0x3d, 0xc6, 0x31, 0x67, 0x03, + 0xe1, 0x26, 0x93, 0x13, 0x24, 0x27, 0xe1, 0x33, 0x95, 0xd9, 0x96, 0x11, 0xf5, 0xc8, 0x6b, 0xa4, 0x8b, 0x9a, 0x35, + 0xe7, 0x6d, 0xd7, 0x59, 0xbc, 0x60, 0x71, 0xde, 0xaf, 0x6e, 0x44, 0x42, 0x80, 0x70, 0x11, 0xfe, 0x1c, 0xc0, 0xff, + 0x6d, 0x33, 0xc5, 0xfd, 0xdd, 0xfc, 0x92, 0x77, 0x4d, 0x1b, 0x07, 0xe0, 0x80, 0x82, 0xc5, 0xc9, 0xe0, 0x02, 0xc9, + 0x08, 0x43, 0xbd, 0x42, 0xb4, 0xc1, 0x52, 0x31, 0xce, 0x2d, 0x3d, 0x8f, 0xec, 0x68, 0xd0, 0xa7, 0xe5, 0xc4, 0x5c, + 0x79, 0x83, 0x31, 0x5b, 0xa3, 0x12, 0x42, 0xed, 0x08, 0x31, 0x85, 0xc9, 0x74, 0x56, 0x16, 0x25, 0x7f, 0x15, 0x26, + 0xb4, 0x82, 0x49, 0x4a, 0x9b, 0x51, 0x63, 0x88, 0x8d, 0x8a, 0x50, 0xbd, 0xe7, 0x94, 0x35, 0x04, 0x73, 0x7b, 0x42, + 0xfa, 0x35, 0x44, 0xd7, 0x3f, 0xd6, 0xcf, 0x13, 0x4e, 0x6a, 0xdb, 0xf9, 0xba, 0xd0, 0x82, 0x83, 0x6b, 0x2a, 0xaa, + 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0xd4, 0x91, 0x3a, 0xd4, 0x12, 0x59, 0x9b, 0x55, 0x3a, 0xd9, 0x61, 0xb4, 0x9c, + 0x4c, 0x89, 0x2b, 0x48, 0x6b, 0x5d, 0x39, 0x57, 0xbe, 0xd1, 0x97, 0x6d, 0xd0, 0x1b, 0x8d, 0x44, 0x2e, 0x3b, 0x8f, + 0x3f, 0xdf, 0xfa, 0x1c, 0xa0, 0xd6, 0xff, 0x6a, 0xed, 0x72, 0xc9, 0x02, 0x76, 0xb1, 0xab, 0x23, 0xf1, 0x7e, 0xde, + 0x0a, 0xb8, 0xbe, 0x10, 0x08, 0x75, 0xdd, 0x85, 0x72, 0xd2, 0x15, 0xab, 0xa2, 0x5f, 0xbe, 0x47, 0xd1, 0xac, 0xb7, + 0x11, 0x94, 0x4d, 0x90, 0xd6, 0xbb, 0x3a, 0x0e, 0x29, 0x21, 0x51, 0x59, 0x4c, 0x75, 0x61, 0x8d, 0x1e, 0xe8, 0x0e, + 0x5b, 0x45, 0x34, 0xa7, 0xe9, 0x26, 0xfb, 0xfe, 0x50, 0xa1, 0x04, 0x22, 0xfc, 0xbf, 0x7b, 0xd3, 0x33, 0xd0, 0x20, + 0x49, 0x5d, 0x80, 0x4a, 0x49, 0xfb, 0x85, 0xd3, 0xfe, 0x50, 0x65, 0x0b, 0x80, 0xc2, 0x1e, 0x6f, 0x14, 0x6d, 0xcb, + 0xef, 0x66, 0x3d, 0x28, 0xd1, 0xfa, 0x3f, 0x2a, 0x43, 0x16, 0x10, 0x6d, 0x47, 0xd7, 0x6a, 0xe9, 0x95, 0x4f, 0x52, + 0x0c, 0x47, 0x13, 0x62, 0xfb, 0x9d, 0xbe, 0x7c, 0x87, 0xea, 0xc2, 0x5a, 0xe2, 0xdc, 0x4b, 0x6a, 0x4b, 0x16, 0xb0, + 0x9f, 0x31, 0x62, 0xba, 0x51, 0xc1, 0x2f, 0x1f, 0x75, 0xb9, 0x9a, 0x85, 0xab, 0x21, 0x60, 0x66, 0x5f, 0x5d, 0xf1, + 0x20, 0x58, 0xc0, 0xd4, 0xb0, 0x30, 0x63, 0xc7, 0x51, 0x9f, 0x39, 0x96, 0xb2, 0xcf, 0x7d, 0x46, 0xd7, 0x37, 0xc7, + 0xfe, 0x11, 0xeb, 0xf6, 0x5b, 0xec, 0x8a, 0x71, 0x3c, 0xb0, 0xaf, 0x2e, 0xb2, 0x81, 0x69, 0x42, 0x92, 0xf5, 0xcb, + 0x29, 0x90, 0xaa, 0xd5, 0x83, 0x98, 0xab, 0x3a, 0x01, 0x8c, 0xf6, 0x5d, 0x51, 0xf0, 0x88, 0x1c, 0x7f, 0x22, 0x8d, + 0x0e, 0x98, 0xe2, 0x0e, 0x84, 0x30, 0x74, 0x47, 0xbc, 0xd9, 0x5b, 0x81, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xf3, + 0x12, 0x5b, 0xd0, 0x36, 0x5a, 0x2f, 0x02, 0x68, 0x88, 0x44, 0xf2, 0x63, 0xe4, 0xf9, 0x70, 0x76, 0xee, 0x41, 0x31, + 0xdc, 0xa4, 0x2e, 0x88, 0xeb, 0xe9, 0x05, 0xdb, 0x65, 0x42, 0x32, 0x51, 0xe8, 0xd0, 0x14, 0x58, 0x59, 0x3b, 0x71, + 0x3a, 0xc0, 0x87, 0xf7, 0xf7, 0xf0, 0xc0, 0x76, 0x54, 0xfc, 0x40, 0x02, 0xb7, 0x2f, 0xac, 0xe0, 0x50, 0x67, 0xc1, + 0x0c, 0x3a, 0xe0, 0x91, 0xde, 0xa7, 0x46, 0x8c, 0x66, 0xd6, 0x3b, 0x40, 0x14, 0x11, 0x65, 0xb6, 0x4d, 0x6e, 0x87, + 0xbb, 0xe3, 0x29, 0x10, 0x20, 0x63, 0x5a, 0x15, 0x96, 0x61, 0x26, 0xb0, 0xc4, 0x7c, 0x33, 0xbe, 0x68, 0xd1, 0x8f, + 0xfd, 0x3e, 0xaa, 0xe4, 0xa2, 0x52, 0x83, 0xb1, 0x8d, 0x79, 0x63, 0x8b, 0x9e, 0xe0, 0x1b, 0x8d, 0x74, 0xf4, 0x0c, + 0x63, 0xb9, 0x84, 0x39, 0x58, 0xe9, 0x1c, 0xf5, 0x23, 0x58, 0x51, 0x05, 0x88, 0xb3, 0x1f, 0xa7, 0x48, 0x0d, 0x98, + 0x25, 0x3f, 0xa4, 0x45, 0x4d, 0x4e, 0x03, 0x7e, 0xcd, 0x40, 0xcf, 0x1e, 0x55, 0xc6, 0x3d, 0x79, 0x09, 0x5c, 0x9a, + 0xde, 0x7a, 0xda, 0x77, 0x6f, 0xc0, 0x31, 0x16, 0xe4, 0x0d, 0xe6, 0xec, 0x4e, 0x30, 0xc5, 0x8a, 0x6d, 0x5d, 0x2d, + 0xf3, 0x6a, 0xfd, 0x40, 0x67, 0x25, 0x18, 0x4e, 0x93, 0x48, 0xe2, 0x04, 0x4c, 0xa3, 0x18, 0x7f, 0x60, 0xbb, 0xbc, + 0xdb, 0xea, 0x13, 0xbf, 0x0d, 0x7f, 0x1d, 0x29, 0x55, 0x9f, 0x7f, 0x12, 0x0b, 0x33, 0x99, 0xd8, 0x6f, 0xe4, 0xe8, + 0x0c, 0x32, 0x2b, 0xf0, 0x55, 0x3d, 0xe3, 0x59, 0xf2, 0x5c, 0x79, 0xca, 0xcd, 0x8a, 0x2d, 0xb3, 0xe0, 0xe7, 0x51, + 0x49, 0x8d, 0xbd, 0x19, 0xd5, 0xa9, 0x56, 0x8c, 0x51, 0x9d, 0x9e, 0x1c, 0x08, 0x97, 0x29, 0xc0, 0x2a, 0x3b, 0x80, + 0xc6, 0xf3, 0xeb, 0xd2, 0x23, 0x11, 0xd9, 0x2a, 0xa6, 0x1e, 0x83, 0x97, 0x8a, 0xa0, 0x77, 0x10, 0x85, 0x18, 0x1c, + 0x49, 0xdf, 0x68, 0xf5, 0xc5, 0x9f, 0xf8, 0x7d, 0xaf, 0x97, 0x70, 0x17, 0xec, 0x7c, 0x53, 0x63, 0xe9, 0x2c, 0x41, + 0x63, 0xf6, 0x3f, 0x87, 0xac, 0x45, 0x58, 0xe4, 0x34, 0xd3, 0x10, 0x34, 0x41, 0xf1, 0x47, 0xd0, 0xc0, 0x66, 0x4d, + 0xd7, 0x7a, 0x13, 0x94, 0x51, 0x48, 0x82, 0xff, 0x57, 0x19, 0x2f, 0x87, 0x2a, 0x27, 0x93, 0xa8, 0x05, 0xf7, 0x89, + 0x9b, 0x6a, 0x68, 0x05, 0xea, 0xec, 0xe1, 0x29, 0xf4, 0x64, 0x2c, 0xa2, 0x67, 0x58, 0xc4, 0x46, 0x9b, 0xc0, 0x78, + 0x24, 0xf3, 0xb0, 0x2e, 0xa2, 0xdd, 0x72, 0x36, 0xc5, 0x57, 0x76, 0xcc, 0xdb, 0x6e, 0x1f, 0xbb, 0x09, 0x95, 0x78, + 0xfa, 0x7d, 0x57, 0xcc, 0xbe, 0xc7, 0xbe, 0x94, 0xd2, 0x3d, 0x70, 0x58, 0x4a, 0xeb, 0x22, 0x28, 0x9c, 0x3a, 0xd8, + 0x02, 0x9a, 0xec, 0xe4, 0x6c, 0x1a, 0x25, 0x58, 0x9c, 0xb9, 0x49, 0xc0, 0xaf, 0x74, 0x12, 0x42, 0x2a, 0x1b, 0xbe, + 0x63, 0x2d, 0xf9, 0x2b, 0x90, 0x6b, 0xfe, 0xe2, 0x69, 0x20, 0x44, 0x6d, 0x23, 0x14, 0x01, 0x6b, 0xe2, 0xca, 0xbc, + 0x33, 0x08, 0xae, 0xe8, 0x2f, 0x7b, 0x0d, 0xff, 0xdc, 0x98, 0xf6, 0xad, 0x90, 0xda, 0xd0, 0xc1, 0x5a, 0x44, 0xc6, + 0xf3, 0x50, 0xf8, 0x6f, 0xf8, 0xd8, 0x73, 0x84, 0x48, 0x22, 0x17, 0xc9, 0x8f, 0x28, 0x6e, 0x31, 0xdd, 0x42, 0xb9, + 0xb5, 0x9d, 0x8f, 0x23, 0x61, 0xd0, 0x3c, 0x6a, 0xf5, 0x92, 0x94, 0xf7, 0xd4, 0x6a, 0xe6, 0x1e, 0x05, 0xb7, 0x8b, + 0xa5, 0x86, 0x17, 0x88, 0xd2, 0xd5, 0x0f, 0x0a, 0xcd, 0xe2, 0x3f, 0x66, 0xb5, 0x79, 0xea, 0xf6, 0x51, 0xc9, 0x37, + 0xc9, 0xca, 0x91, 0x05, 0x27, 0x51, 0xf8, 0x43, 0x08, 0xbc, 0xd4, 0x19, 0x4f, 0xf5, 0x36, 0x62, 0x1e, 0x0a, 0x4d, + 0x41, 0xae, 0x07, 0xed, 0x13, 0x4d, 0x8e, 0xdc, 0x90, 0x63, 0x7a, 0xd0, 0x3e, 0xac, 0x81, 0xed, 0x08, 0x71, 0x71, + 0x9f, 0x88, 0xe1, 0xb4, 0xea, 0x72, 0x02, 0xe4, 0xce, 0x79, 0xd2, 0x32, 0x04, 0x35, 0x72, 0x13, 0xd4, 0xb8, 0x73, + 0x9c, 0xda, 0x45, 0xd1, 0xed, 0x4b, 0x2e, 0x91, 0x62, 0x94, 0xe9, 0xbe, 0xf4, 0xdf, 0xab, 0xad, 0xa2, 0x01, 0x64, + 0x03, 0xbe, 0xde, 0x7b, 0xc7, 0xe8, 0x00, 0xf5, 0x72, 0xeb, 0xa6, 0x6c, 0x5e, 0x9e, 0xd3, 0x6c, 0x6b, 0xb8, 0xc7, + 0xd0, 0xfe, 0x12, 0xea, 0x9c, 0xfb, 0xac, 0xf8, 0xad, 0xbc, 0x0b, 0xc4, 0xe4, 0xe4, 0x66, 0x23, 0x4f, 0x93, 0x75, + 0x84, 0x75, 0x8f, 0xa1, 0xb9, 0x88, 0x7f, 0x69, 0xac, 0x5c, 0x10, 0x9e, 0x58, 0xc9, 0x82, 0xbf, 0x30, 0xcc, 0x60, + 0x53, 0x79, 0x4d, 0x7f, 0x87, 0x39, 0x80, 0xf7, 0xdb, 0xcd, 0x5a, 0x41, 0x3e, 0x25, 0xb5, 0xe3, 0x6b, 0xad, 0xe3, + 0x97, 0x6f, 0xd0, 0x83, 0xd4, 0xc4, 0x63, 0x51, 0x3d, 0x10, 0xb3, 0xa4, 0x37, 0x2f, 0x71, 0xf4, 0xcd, 0x4f, 0x9b, + 0x67, 0x5c, 0xe3, 0xb9, 0x08, 0xc9, 0x80, 0xb5, 0xc1, 0xa5, 0xbd, 0x37, 0x12, 0x77, 0x9f, 0x95, 0xa9, 0x45, 0x6b, + 0x63, 0x26, 0x0a, 0xb4, 0xb0, 0xee, 0x12, 0xf1, 0x7c, 0xf9, 0xa6, 0xbf, 0x76, 0xa4, 0x58, 0x9a, 0x8f, 0x64, 0x1e, + 0x55, 0x29, 0xe1, 0x8f, 0x01, 0x8d, 0x7f, 0x43, 0x5e, 0x24, 0x31, 0xd0, 0x60, 0x91, 0x1a, 0x2b, 0xef, 0x13, 0x70, + 0x88, 0xa1, 0x89, 0xa8, 0x4d, 0xb4, 0x13, 0xb8, 0xa3, 0xf1, 0x89, 0xa4, 0x3e, 0x26, 0x95, 0x34, 0x01, 0x1e, 0xdd, + 0xc5, 0xe4, 0x64, 0xec, 0x02, 0x7c, 0x81, 0xc7, 0xc7, 0xd3, 0x6f, 0xda, 0xd5, 0xd1, 0x0d, 0x52, 0x6e, 0x2a, 0xc8, + 0x26, 0x60, 0xad, 0x05, 0xe0, 0x29, 0xd7, 0x44, 0xf3, 0x8e, 0x54, 0xbf, 0x0c, 0x02, 0xf6, 0xbb, 0x8b, 0x7a, 0xee, + 0x4d, 0x63, 0x65, 0xf9, 0x38, 0xf1, 0x52, 0xd3, 0x08, 0xb1, 0x62, 0x9f, 0x71, 0xca, 0x11, 0x11, 0xef, 0xf0, 0x6b, + 0xeb, 0xcd, 0x22, 0xbd, 0x4d, 0x8a, 0x73, 0x93, 0x01, 0x86, 0x91, 0x6b, 0x84, 0x5f, 0xcc, 0xb4, 0xb3, 0x75, 0xe5, + 0xc3, 0x02, 0xc9, 0x68, 0x29, 0xfc, 0xad, 0xc8, 0xac, 0xb6, 0x59, 0x8b, 0x10, 0xff, 0x50, 0xf4, 0xb3, 0x43, 0x69, + 0x14, 0x90, 0x57, 0x5f, 0x2e, 0x2b, 0x36, 0x39, 0x05, 0x9d, 0xf6, 0xb9, 0x79, 0x67, 0x59, 0x7e, 0xfc, 0xf9, 0x8f, + 0x73, 0x3b, 0x61, 0x8b, 0x99, 0x27, 0x6e, 0xb1, 0x8c, 0xb2, 0xf2, 0xa2, 0xd5, 0x79, 0x4b, 0xd6, 0xcd, 0xec, 0xba, + 0x40, 0x09, 0xff, 0xd4, 0x8f, 0x0e, 0x67, 0xe5, 0x0c, 0x7a, 0x85, 0x56, 0x16, 0xf6, 0x28, 0x6d, 0xdf, 0xda, 0x97, + 0x03, 0x9d, 0xc6, 0x5d, 0xd8, 0x1c, 0x27, 0x48, 0x52, 0x79, 0x28, 0x3f, 0xf3, 0x14, 0x67, 0xdf, 0x59, 0x4d, 0x47, + 0x3b, 0x7a, 0xc7, 0xd1, 0xe5, 0x60, 0xb1, 0x43, 0x94, 0xac, 0x0f, 0xce, 0xb6, 0x59, 0x7c, 0x70, 0x94, 0x69, 0x3e, + 0xe3, 0x15, 0x0b, 0xa4, 0x34, 0x4f, 0x9f, 0x22, 0xe8, 0x09, 0x64, 0x62, 0x0c, 0xbd, 0x0b, 0x36, 0x4d, 0x81, 0x63, + 0xce, 0xb7, 0x89, 0xa0, 0xcd, 0x32, 0x9a, 0x45, 0xf4, 0x62, 0x64, 0x29, 0xbc, 0xf6, 0x8e, 0x7a, 0xae, 0x64, 0x5d, + 0x42, 0xab, 0x23, 0xab, 0x1f, 0x6c, 0xf7, 0x69, 0xe1, 0x07, 0xf3, 0xbb, 0xd5, 0x42, 0x7d, 0x65, 0xac, 0x7e, 0x8c, + 0xcc, 0x52, 0xe7, 0x2c, 0x67, 0xb7, 0xd3, 0xd8, 0xc0, 0xeb, 0x64, 0xb3, 0xf5, 0xeb, 0x76, 0x7f, 0xb9, 0xe4, 0xdf, + 0x66, 0xca, 0xdb, 0x24, 0x47, 0xd8, 0xef, 0x13, 0x59, 0x03, 0xb2, 0x3e, 0x6d, 0x71, 0x96, 0x92, 0x3a, 0x56, 0x49, + 0x94, 0x18, 0xdb, 0x09, 0x5c, 0x61, 0x10, 0x12, 0xcf, 0x66, 0x75, 0x25, 0x4c, 0xce, 0xab, 0x78, 0xa7, 0x30, 0x57, + 0x22, 0x59, 0x2c, 0xf2, 0x04, 0x45, 0xda, 0x37, 0xcb, 0xe5, 0xa5, 0x3c, 0x35, 0xa5, 0x1d, 0x09, 0x8d, 0xbc, 0xa4, + 0xff, 0x0c, 0xb8, 0x24, 0x44, 0x2a, 0x50, 0x89, 0xcf, 0x7d, 0x47, 0x2a, 0xd1, 0xa4, 0x8a, 0x52, 0x14, 0xd4, 0xca, + 0xf4, 0x8f, 0x98, 0x97, 0xa6, 0xb4, 0xee, 0x81, 0xc0, 0x75, 0x9b, 0x2b, 0x89, 0xa7, 0x7f, 0x99, 0xcc, 0x2e, 0x00, + 0xe7, 0x65, 0xb9, 0xc1, 0x2f, 0x63, 0xc2, 0xe5, 0xd1, 0x65, 0x4d, 0x20, 0xd8, 0xf1, 0x06, 0x7e, 0x98, 0x48, 0x10, + 0x1c, 0x57, 0x24, 0x22, 0x16, 0x9c, 0xa1, 0x88, 0xa7, 0x60, 0x00, 0x48, 0xce, 0xbf, 0x4f, 0x9f, 0x17, 0x34, 0x7f, + 0x40, 0x54, 0xe1, 0xa8, 0x02, 0xc4, 0x01, 0x09, 0x06, 0x5d, 0x78, 0x27, 0x8b, 0x6c, 0x35, 0x3b, 0x5e, 0x9e, 0x93, + 0xce, 0x9d, 0x45, 0x44, 0x7a, 0x51, 0x12, 0x41, 0x9c, 0x61, 0xf1, 0x83, 0xa0, 0xc4, 0xe8, 0xf5, 0xba, 0x20, 0x8c, + 0x2e, 0x96, 0x64, 0xa3, 0xd1, 0x20, 0x20, 0xfd, 0x23, 0xc4, 0x4c, 0xb6, 0x4b, 0x39, 0x66, 0x5f, 0x7b, 0xc5, 0x39, + 0x6b, 0xcd, 0x10, 0x4a, 0x06, 0x76, 0x6f, 0x09, 0xa4, 0x3a, 0x87, 0x32, 0x9a, 0x4a, 0x53, 0x7e, 0x21, 0x47, 0x50, + 0xeb, 0xd0, 0x6b, 0x93, 0xa1, 0xdf, 0x06, 0x4f, 0x22, 0x20, 0x45, 0x0a, 0xcf, 0x4b, 0x60, 0xc1, 0x64, 0xe7, 0xb6, + 0x64, 0x16, 0x1f, 0x3f, 0xa4, 0x38, 0xc9, 0x9c, 0xcd, 0x40, 0xff, 0x42, 0x13, 0x5c, 0x2c, 0xd2, 0x11, 0x23, 0xab, + 0xe0, 0x72, 0x58, 0xf7, 0xbf, 0xed, 0x72, 0xe8, 0xa6, 0x20, 0xb7, 0x39, 0x1b, 0x33, 0xe5, 0x78, 0xdc, 0xcd, 0x59, + 0x5f, 0xfa, 0xcb, 0x24, 0x8d, 0x34, 0x15, 0x4a, 0x67, 0xd6, 0x77, 0xf7, 0xbb, 0x7a, 0xec, 0x96, 0x47, 0xf7, 0x16, + 0x10, 0xd0, 0xc6, 0x1d, 0x39, 0x65, 0x05, 0x96, 0x84, 0x63, 0x12, 0x0e, 0x1f, 0x00, 0x73, 0xad, 0x1f, 0x44, 0x25, + 0xfd, 0x5d, 0xb2, 0x4f, 0x07, 0x22, 0x3f, 0xd7, 0x65, 0x7d, 0x96, 0xfa, 0x93, 0x69, 0xf7, 0x71, 0xec, 0xe3, 0x19, + 0xa7, 0x39, 0x42, 0x52, 0x96, 0xe4, 0xd7, 0xcb, 0xcd, 0x71, 0xb6, 0x95, 0xfc, 0x4f, 0x28, 0xce, 0x1f, 0x94, 0xd1, + 0x3a, 0x5b, 0x36, 0x7d, 0xb6, 0x60, 0x38, 0x67, 0x92, 0x96, 0xe0, 0x94, 0x4f, 0xfc, 0x4b, 0xd5, 0xe1, 0xf1, 0x69, + 0x8f, 0x58, 0x0f, 0x22, 0x49, 0xf0, 0x5f, 0x73, 0xc2, 0xe3, 0x53, 0x33, 0xe1, 0x87, 0x67, 0x88, 0x4f, 0x6f, 0x8c, + 0x8e, 0xa9, 0xd4, 0x1c, 0xcb, 0x8a, 0x4b, 0x2f, 0x2a, 0x82, 0x53, 0x5d, 0xd8, 0xe0, 0xd9, 0x9d, 0x3e, 0xa5, 0x39, + 0xcd, 0x41, 0x78, 0x92, 0x66, 0x3b, 0xb7, 0x68, 0xb1, 0xa4, 0x05, 0x94, 0x92, 0xca, 0x49, 0xb4, 0x9a, 0xc6, 0x91, + 0xad, 0x23, 0xcc, 0x0b, 0x9c, 0xdd, 0x46, 0x62, 0x84, 0xb5, 0x33, 0x9e, 0xa8, 0x91, 0x9a, 0x92, 0x9b, 0x3a, 0x22, + 0x59, 0x8f, 0xc1, 0xfc, 0x9f, 0x1f, 0x7b, 0x5c, 0x63, 0x66, 0x67, 0xe1, 0x8a, 0x72, 0xfb, 0x6a, 0xaa, 0x76, 0xb2, + 0xa5, 0x2b, 0xaf, 0x5b, 0x3b, 0xa7, 0xd2, 0xe6, 0xc2, 0x15, 0x87, 0x6e, 0xb8, 0x7a, 0x6d, 0x17, 0x24, 0xd7, 0xcf, + 0x91, 0xdf, 0x0c, 0x83, 0x25, 0x89, 0xd4, 0xcd, 0x9d, 0x27, 0x65, 0x4b, 0xa9, 0xba, 0xaf, 0xc0, 0xe2, 0xb0, 0x34, + 0x54, 0xbb, 0x0a, 0xca, 0xf2, 0x46, 0x0d, 0x61, 0x11, 0xd6, 0xd4, 0x0b, 0x0e, 0xa7, 0x74, 0x9e, 0x05, 0x35, 0xb5, + 0x38, 0x3f, 0x69, 0xd4, 0x5e, 0x52, 0xe4, 0x54, 0x40, 0xbc, 0x89, 0x22, 0x17, 0x2f, 0x51, 0xaf, 0xf2, 0xb8, 0x82, + 0xfd, 0x91, 0x92, 0xaa, 0x9d, 0x5e, 0xa8, 0xc2, 0xe9, 0x99, 0x2a, 0x9f, 0x5e, 0x9e, 0xae, 0x70, 0x98, 0x4b, 0xb5, + 0x2b, 0x91, 0x45, 0x59, 0x52, 0x96, 0xe3, 0xca, 0x95, 0xf1, 0xdc, 0x9e, 0xbb, 0x8c, 0x4c, 0xd5, 0x29, 0x06, 0x93, + 0x32, 0xa5, 0xd5, 0x63, 0xdb, 0x11, 0x43, 0xc3, 0x04, 0x82, 0x5d, 0xd6, 0xca, 0x68, 0x7d, 0xbf, 0x78, 0x62, 0x51, + 0xa8, 0x2d, 0xad, 0x4f, 0x4f, 0x92, 0x90, 0xb5, 0xbe, 0xb4, 0x09, 0x94, 0xd8, 0x79, 0x3f, 0x56, 0xd1, 0x5e, 0x3c, + 0x77, 0xcf, 0xda, 0x83, 0x08, 0xb8, 0x5e, 0xeb, 0xcb, 0x0f, 0xc7, 0xf4, 0x90, 0xbd, 0x6c, 0x91, 0xa2, 0xfc, 0x81, + 0x04, 0xce, 0x07, 0x84, 0x30, 0x13, 0x58, 0x05, 0x0b, 0xe5, 0x95, 0x04, 0x56, 0x81, 0x8f, 0x18, 0xb5, 0x98, 0x9d, + 0x96, 0xde, 0xfb, 0xa4, 0x58, 0xe3, 0x26, 0xc4, 0x0b, 0x40, 0x5e, 0x4f, 0x21, 0xb2, 0x85, 0x28, 0xd0, 0x4c, 0x11, + 0x24, 0xfc, 0x80, 0x7d, 0x78, 0x81, 0xd6, 0x8f, 0xe9, 0xc8, 0x57, 0xb3, 0x72, 0x07, 0x6d, 0x3d, 0xb6, 0xa7, 0x2a, + 0x5d, 0x35, 0x29, 0x3e, 0x4a, 0xbc, 0x93, 0x58, 0x34, 0xf0, 0xca, 0x15, 0x3b, 0xbd, 0xf3, 0x81, 0xdf, 0xb0, 0x2d, + 0x73, 0xfc, 0xf2, 0x34, 0xc7, 0x15, 0xa8, 0x1a, 0x55, 0x68, 0xbb, 0x3d, 0x40, 0xa6, 0xa6, 0x57, 0x09, 0xe2, 0xb0, + 0x69, 0x1a, 0x2e, 0x40, 0x07, 0x0e, 0x51, 0x09, 0xa4, 0x4c, 0x35, 0x0b, 0x34, 0x72, 0x8d, 0x14, 0x36, 0x5b, 0xb3, + 0xa8, 0x4d, 0xd8, 0xe7, 0xdf, 0xd0, 0xbc, 0xb6, 0x2d, 0x9f, 0x88, 0x3b, 0x54, 0xf2, 0x19, 0xbc, 0xf4, 0xe1, 0x1e, + 0xdf, 0x03, 0x76, 0xe4, 0x4a, 0xc5, 0xc8, 0x94, 0xc4, 0xf6, 0x78, 0x41, 0xb5, 0xc9, 0x3c, 0x79, 0x54, 0xa7, 0x26, + 0x6c, 0x28, 0x57, 0x38, 0x61, 0xfb, 0x11, 0xbb, 0x80, 0x77, 0x28, 0x31, 0x37, 0xd5, 0x6f, 0x0e, 0xa1, 0xab, 0x3d, + 0xf0, 0xae, 0x8c, 0x7e, 0x79, 0xf9, 0x62, 0x8b, 0xb7, 0xb9, 0x83, 0xbf, 0xa6, 0xc1, 0xb6, 0x50, 0x1c, 0xea, 0xae, + 0x80, 0xf4, 0xb2, 0x97, 0x2b, 0x45, 0x49, 0x6f, 0xcd, 0xe0, 0xa9, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd2, + 0x83, 0x30, 0x21, 0xc8, 0x01, 0x95, 0xd1, 0xbb, 0x2b, 0xd9, 0xe2, 0x5e, 0xf0, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, + 0xd3, 0x28, 0x8d, 0xba, 0x64, 0x68, 0x8f, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x57, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, + 0xec, 0xd9, 0x3c, 0x86, 0xe1, 0xdb, 0xed, 0xc9, 0x80, 0xb1, 0x65, 0xf6, 0xbe, 0xa7, 0x9b, 0x8f, 0x26, 0xe4, 0x1a, + 0x6a, 0x0d, 0xc7, 0x39, 0x30, 0x64, 0xaa, 0x68, 0xf0, 0xc9, 0x86, 0x68, 0xc2, 0xda, 0x5c, 0x76, 0x5d, 0x08, 0x61, + 0xd0, 0x63, 0x53, 0x58, 0x41, 0x5c, 0x3b, 0xd6, 0xb0, 0xbe, 0x58, 0x46, 0xa0, 0x69, 0x4d, 0x1f, 0xc8, 0x98, 0xb6, + 0x97, 0x08, 0x75, 0x27, 0xca, 0x37, 0xcc, 0x69, 0x16, 0xc4, 0x7d, 0xaf, 0xcb, 0xe7, 0x1a, 0x36, 0x7e, 0xa2, 0x62, + 0xae, 0xa7, 0xba, 0x85, 0x01, 0xea, 0x40, 0x5c, 0x0c, 0xf8, 0x78, 0x1b, 0x42, 0x5f, 0xf9, 0x77, 0xd8, 0xf7, 0x4a, + 0x29, 0x8f, 0x3a, 0x3e, 0x2d, 0x35, 0x72, 0xd4, 0x5e, 0xf6, 0x7f, 0xb2, 0xfa, 0x90, 0x3f, 0x56, 0xa8, 0xd0, 0x84, + 0x34, 0x34, 0x89, 0xba, 0x79, 0x02, 0xb1, 0xed, 0x7b, 0xae, 0xd0, 0x8b, 0x45, 0xa4, 0x3c, 0x02, 0xba, 0x29, 0x8f, + 0x77, 0xab, 0x19, 0x46, 0x7c, 0xab, 0xd7, 0xda, 0x68, 0x4b, 0x34, 0x8b, 0x23, 0xde, 0x45, 0x3b, 0x3b, 0x9c, 0xca, + 0x48, 0xcf, 0x4e, 0xe1, 0x38, 0x27, 0xd1, 0xbb, 0x74, 0xd8, 0x69, 0xae, 0xbe, 0x7e, 0x67, 0x43, 0x1f, 0xe2, 0x6a, + 0x21, 0x6a, 0x7b, 0xce, 0x68, 0x6e, 0x26, 0x2e, 0x10, 0x0b, 0xa0, 0xd9, 0xbb, 0x57, 0xa9, 0xa6, 0xc9, 0x98, 0x71, + 0x59, 0xcc, 0x12, 0x29, 0xc2, 0x0e, 0xe8, 0x25, 0x9a, 0x30, 0x51, 0x75, 0x9c, 0x1b, 0xb1, 0xe7, 0xa3, 0xba, 0x29, + 0x77, 0x25, 0x19, 0x94, 0x45, 0xeb, 0xb6, 0xeb, 0xe5, 0x25, 0xf4, 0x7e, 0x1e, 0x70, 0x5d, 0x1b, 0x2b, 0x38, 0x61, + 0x0b, 0x13, 0x9f, 0x25, 0x41, 0x6e, 0x8d, 0x24, 0x5b, 0x84, 0xa5, 0x7a, 0x67, 0xfe, 0x69, 0xe9, 0xd5, 0x76, 0xa4, + 0x5e, 0x38, 0xcc, 0xdc, 0x9e, 0x85, 0xe5, 0x57, 0xc0, 0xe3, 0xbc, 0xf7, 0xbc, 0x11, 0x9a, 0xf2, 0xc7, 0xab, 0x3d, + 0xa8, 0x88, 0x66, 0x63, 0x47, 0x3d, 0x91, 0x6b, 0xba, 0xa9, 0x82, 0x6b, 0x32, 0xd1, 0xea, 0x41, 0x9c, 0x59, 0xd1, + 0x76, 0x62, 0x19, 0xfc, 0x33, 0xd8, 0xe0, 0x1b, 0xd8, 0x17, 0x4b, 0x00, 0xeb, 0x37, 0xc6, 0x57, 0x21, 0x0f, 0xcb, + 0xf7, 0x74, 0x7e, 0x86, 0xb0, 0xaf, 0x30, 0x57, 0x24, 0x2c, 0x4f, 0x95, 0x5a, 0xc9, 0x41, 0xc5, 0xb4, 0x7c, 0x6e, + 0xc1, 0x27, 0xd5, 0x56, 0x29, 0x5e, 0xff, 0x55, 0x5c, 0xab, 0xd0, 0xf9, 0x79, 0xa2, 0x10, 0xe2, 0xfe, 0x23, 0x12, + 0x55, 0x94, 0x9f, 0x86, 0xdb, 0x66, 0xdf, 0xc3, 0x8f, 0x1b, 0x7e, 0xd0, 0x65, 0x81, 0xca, 0xaa, 0x71, 0x83, 0x71, + 0xb8, 0x3c, 0xcd, 0xaa, 0x11, 0x0b, 0x45, 0xf8, 0xc6, 0xa5, 0x03, 0x47, 0x6f, 0x63, 0xab, 0xe6, 0x52, 0x85, 0x2a, + 0x20, 0xf6, 0x14, 0x7a, 0xde, 0x44, 0x35, 0x52, 0x2a, 0x12, 0x08, 0x93, 0x06, 0xed, 0x12, 0x17, 0xec, 0x16, 0xab, + 0x76, 0xb5, 0xbb, 0x15, 0xf3, 0x9a, 0x4c, 0x04, 0x8c, 0xf1, 0x0e, 0xb4, 0x6e, 0x66, 0x4b, 0x06, 0x74, 0x4e, 0xec, + 0xa8, 0xc0, 0x79, 0x8c, 0x71, 0x70, 0xb8, 0xc7, 0xcd, 0xf4, 0xa4, 0x92, 0x1d, 0x66, 0xe4, 0xa1, 0x39, 0x74, 0x86, + 0x2b, 0x0f, 0xe5, 0x21, 0x2b, 0x71, 0xb6, 0xc0, 0xcb, 0x35, 0x72, 0x95, 0xe8, 0xaa, 0x25, 0x68, 0x78, 0x20, 0xb9, + 0xdb, 0x37, 0xdf, 0xbd, 0xd3, 0xbb, 0x01, 0xa7, 0xd2, 0xdf, 0x0c, 0xd8, 0x1d, 0x2c, 0x78, 0xb7, 0x3a, 0x1d, 0x4b, + 0x0c, 0x00, 0x64, 0xd7, 0xf4, 0x83, 0xb0, 0x85, 0xee, 0x74, 0x87, 0x6b, 0xc7, 0x55, 0x04, 0x6d, 0x88, 0xaa, 0x8c, + 0xa1, 0x23, 0xbb, 0x88, 0x04, 0xb2, 0xeb, 0x88, 0x15, 0xdd, 0x32, 0x16, 0xc2, 0x09, 0x3c, 0xee, 0x01, 0xf5, 0x83, + 0x23, 0xa4, 0x54, 0x44, 0x42, 0xc9, 0x85, 0xf8, 0xdb, 0x34, 0xd4, 0xac, 0xe0, 0x6e, 0xb3, 0x21, 0x76, 0x93, 0x88, + 0xfe, 0xa0, 0x2a, 0xbc, 0x39, 0x8f, 0xf2, 0xad, 0x03, 0x0a, 0x1f, 0xcd, 0xc8, 0xc0, 0x59, 0xda, 0xb7, 0xa7, 0x5d, + 0x7b, 0x37, 0xe6, 0xa5, 0xb4, 0x94, 0x0a, 0xc1, 0xcd, 0x1d, 0x3c, 0xeb, 0x1f, 0x5c, 0x49, 0x13, 0x9b, 0x9a, 0x7d, + 0x99, 0x73, 0xb4, 0x33, 0xe5, 0x79, 0x14, 0x5f, 0x6b, 0xd9, 0xf3, 0xb6, 0x79, 0x36, 0x76, 0x67, 0xb7, 0x8b, 0xfd, + 0x0c, 0x49, 0x61, 0x8b, 0x19, 0xcc, 0x35, 0x89, 0x62, 0x12, 0x18, 0x6d, 0x80, 0xbd, 0x89, 0x66, 0xd8, 0x45, 0x0b, + 0x94, 0xbd, 0x5b, 0x77, 0x6b, 0xc3, 0xf1, 0xdb, 0xcc, 0xd7, 0xaa, 0xf6, 0xc2, 0x9d, 0x12, 0x05, 0xe7, 0xc3, 0xde, + 0x39, 0xaf, 0xff, 0xa3, 0xc4, 0x9b, 0x19, 0xc6, 0x92, 0x48, 0xb4, 0x36, 0x10, 0x3c, 0x4a, 0xeb, 0xb5, 0x59, 0x96, + 0x20, 0x3b, 0xb5, 0xbc, 0xfd, 0x07, 0x1d, 0x20, 0x15, 0xe3, 0xdd, 0xe2, 0xe6, 0x0c, 0x0b, 0x8e, 0x49, 0xa9, 0x2d, + 0x37, 0xbf, 0xfe, 0x49, 0x32, 0xa5, 0xa2, 0x4d, 0xae, 0x27, 0x9a, 0xe7, 0xe2, 0xca, 0x01, 0x80, 0x40, 0x69, 0x36, + 0xac, 0x8b, 0xeb, 0xcd, 0x64, 0x73, 0xab, 0xd0, 0x11, 0x66, 0xaa, 0xc0, 0xf8, 0x9b, 0x55, 0x4a, 0x4f, 0xa9, 0x56, + 0x49, 0xc2, 0xdc, 0x4e, 0x5f, 0xab, 0x44, 0x68, 0x3f, 0x06, 0xe2, 0xdb, 0xc9, 0x77, 0xf5, 0xa7, 0x6c, 0x8b, 0x3c, + 0x8e, 0x03, 0x93, 0xb3, 0xb7, 0x76, 0x50, 0xd0, 0xa8, 0xed, 0x5c, 0x8e, 0xd7, 0x3c, 0x2b, 0xa8, 0x7d, 0xe5, 0x57, + 0xb3, 0xb5, 0xc7, 0x17, 0xee, 0x08, 0xb2, 0x02, 0xa9, 0xc7, 0xe4, 0xc1, 0x34, 0x46, 0xa5, 0xd9, 0x39, 0x2f, 0x76, + 0x58, 0x1e, 0x93, 0x64, 0xd7, 0xf8, 0xcf, 0xc8, 0xa5, 0x14, 0x48, 0xfe, 0xc4, 0xb9, 0x13, 0x2a, 0x16, 0xb3, 0x64, + 0x61, 0x6a, 0xd7, 0x24, 0x2f, 0xdf, 0xc5, 0x75, 0x3c, 0x2d, 0xc7, 0x7f, 0x56, 0x4c, 0xf4, 0x24, 0x10, 0x52, 0xeb, + 0x1d, 0x0d, 0x1e, 0x40, 0xdd, 0x3a, 0x83, 0x6f, 0x64, 0xf3, 0x50, 0x24, 0x83, 0x8c, 0xd9, 0x56, 0xdd, 0xa5, 0x1a, + 0x89, 0x7a, 0xb0, 0x0c, 0xb4, 0xdb, 0x49, 0xe0, 0x12, 0xb5, 0xf6, 0x10, 0x1c, 0x54, 0xf4, 0x3e, 0x54, 0xc1, 0x52, + 0x33, 0x58, 0xaa, 0xac, 0xd4, 0x06, 0x6b, 0x2f, 0xd5, 0xda, 0x32, 0xa3, 0x2b, 0x2f, 0x0f, 0x8e, 0x39, 0x0e, 0x00, + 0x5b, 0xcf, 0xa5, 0x0e, 0x03, 0xe8, 0x44, 0x36, 0x70, 0x03, 0x32, 0x00, 0x65, 0x2d, 0xa1, 0x72, 0xd3, 0x82, 0x73, + 0xad, 0x4d, 0x29, 0x96, 0x80, 0x44, 0x70, 0xc6, 0xfe, 0xe8, 0x51, 0xe9, 0xed, 0xc8, 0x11, 0xae, 0x5a, 0x37, 0x6d, + 0x05, 0x6b, 0xeb, 0x0c, 0x69, 0xe3, 0x31, 0xde, 0x65, 0x3f, 0x01, 0xdf, 0xc5, 0x8b, 0xd6, 0x91, 0x19, 0x6f, 0x71, + 0xa4, 0x20, 0x14, 0xba, 0xde, 0x31, 0x16, 0xa6, 0x04, 0x86, 0xd9, 0xdd, 0x15, 0x61, 0x7a, 0x7b, 0x29, 0x20, 0x58, + 0xb8, 0xb1, 0x16, 0x37, 0x0e, 0xcf, 0x6f, 0x1c, 0x26, 0x8a, 0x70, 0x68, 0xa6, 0x4a, 0xf8, 0x5c, 0xaa, 0x0c, 0x05, + 0x39, 0x35, 0x38, 0x0a, 0xdc, 0xdf, 0xbe, 0x77, 0xb4, 0x28, 0x12, 0x82, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x75, 0xc6, + 0x05, 0xe9, 0xcb, 0xe1, 0xfe, 0x62, 0x6e, 0x87, 0xa9, 0x59, 0x99, 0xb7, 0x48, 0x7c, 0x6f, 0x5a, 0x8c, 0x11, 0xe1, + 0x7c, 0xaf, 0x5d, 0x60, 0x8b, 0xb5, 0xec, 0x6f, 0x3f, 0xee, 0x09, 0x57, 0x16, 0x0e, 0x0c, 0x5d, 0x64, 0xda, 0xab, + 0x75, 0xb7, 0x52, 0xc4, 0xf9, 0x47, 0xf4, 0xc8, 0xfc, 0xc1, 0x38, 0x8e, 0x1d, 0xdc, 0xee, 0x84, 0xda, 0xe7, 0xfc, + 0x86, 0x85, 0x3a, 0xa2, 0xd5, 0x0d, 0xd4, 0xb0, 0x06, 0x97, 0xca, 0x2c, 0x2d, 0xe6, 0x9f, 0xdd, 0xdc, 0x3c, 0x25, + 0xe0, 0x24, 0xf1, 0x05, 0x24, 0xd9, 0xe1, 0x7a, 0xf7, 0xe9, 0x2d, 0x93, 0xbe, 0x0d, 0x92, 0x12, 0xbb, 0x95, 0xca, + 0x76, 0x49, 0xd3, 0x94, 0x1d, 0xee, 0x8a, 0xaa, 0x35, 0xd8, 0x13, 0x13, 0xa5, 0xa3, 0xbe, 0x10, 0x26, 0x4d, 0xec, + 0x4b, 0x18, 0xef, 0x8b, 0x09, 0x9c, 0x37, 0x0c, 0xf1, 0xaa, 0x03, 0xa5, 0x50, 0x22, 0x65, 0x2f, 0xbb, 0xe3, 0x4d, + 0x69, 0x26, 0x1f, 0x51, 0xc5, 0x81, 0x96, 0xde, 0x5a, 0xee, 0x4a, 0x00, 0xd0, 0xbd, 0xba, 0xbc, 0xfc, 0xfd, 0xc1, + 0x7d, 0x8c, 0x95, 0xc8, 0x37, 0xef, 0xf7, 0xc3, 0xd3, 0xfd, 0x17, 0x12, 0xc1, 0x81, 0xe6, 0x71, 0x7a, 0xf9, 0x5d, + 0xa5, 0x8b, 0x5b, 0xd5, 0xf7, 0xab, 0xa0, 0x8c, 0xd4, 0xe3, 0xee, 0x2c, 0x6c, 0x09, 0x26, 0xac, 0x0d, 0x38, 0x67, + 0x3e, 0x08, 0x65, 0x2e, 0xff, 0xfa, 0x2c, 0xce, 0xdd, 0x78, 0x58, 0x78, 0x26, 0xb0, 0xb1, 0x31, 0xd4, 0x61, 0xae, + 0x3b, 0xf3, 0xe9, 0xe0, 0x19, 0xb9, 0xee, 0x1a, 0x32, 0x2c, 0x8d, 0x03, 0xbe, 0xde, 0xfa, 0xf1, 0xfe, 0x3f, 0x8f, + 0x5f, 0x06, 0xe6, 0x81, 0x99, 0xf1, 0x1c, 0x95, 0xf6, 0xb0, 0xa4, 0xc1, 0x61, 0x64, 0x3b, 0xea, 0xda, 0xbf, 0x47, + 0x23, 0x82, 0x8c, 0x10, 0x21, 0xc7, 0xa1, 0x1d, 0x43, 0x39, 0x3d, 0x8e, 0x55, 0x95, 0xf6, 0xa2, 0x37, 0x18, 0x37, + 0xb2, 0x85, 0x22, 0x60, 0x4a, 0xf4, 0xfd, 0xea, 0xac, 0x2a, 0xee, 0x4d, 0xff, 0xf2, 0xe8, 0x8b, 0xec, 0xaa, 0x51, + 0x03, 0xe1, 0x77, 0x24, 0xaa, 0xa2, 0x37, 0x96, 0xef, 0xb4, 0x05, 0x5b, 0x43, 0x0e, 0x8c, 0x1a, 0x49, 0x9b, 0x11, + 0x3b, 0x6f, 0x32, 0xe7, 0x92, 0x2f, 0xd4, 0x58, 0x7a, 0x94, 0x93, 0x65, 0x0a, 0x00, 0xd3, 0x95, 0x16, 0x11, 0x17, + 0x18, 0x82, 0x2b, 0x0e, 0xab, 0x5b, 0xc8, 0x8c, 0xf5, 0x6c, 0x77, 0x16, 0x8d, 0x26, 0x08, 0xd3, 0xfa, 0x90, 0xa8, + 0x30, 0x73, 0xca, 0xa4, 0x0c, 0x97, 0xda, 0x09, 0xc8, 0x93, 0xdf, 0xd2, 0x8a, 0x01, 0x98, 0x31, 0x91, 0x5c, 0x6e, + 0x6c, 0x22, 0xeb, 0x90, 0xcf, 0x49, 0xbf, 0x99, 0xf3, 0xe1, 0x9b, 0x18, 0x1f, 0x5c, 0x9c, 0x06, 0xeb, 0x0f, 0x50, + 0xf2, 0xdc, 0x0d, 0x97, 0xab, 0x4d, 0xda, 0x72, 0x5b, 0xd1, 0x16, 0x8c, 0x89, 0x76, 0x79, 0x61, 0x9b, 0xa8, 0x40, + 0x9f, 0x49, 0x6f, 0xb8, 0x06, 0xa2, 0x1c, 0x06, 0xf1, 0x52, 0x0e, 0xc5, 0xcd, 0xda, 0x23, 0x54, 0x69, 0x2c, 0x50, + 0x03, 0x2b, 0x7c, 0xc2, 0x30, 0xaa, 0x26, 0xd8, 0x7d, 0xff, 0xd8, 0xe0, 0xcb, 0xd5, 0xb7, 0x83, 0x35, 0x6f, 0x5a, + 0x26, 0xda, 0x21, 0x3a, 0x9c, 0x83, 0x8a, 0x87, 0xd8, 0x69, 0x92, 0xd3, 0x60, 0xea, 0x7a, 0x72, 0xb9, 0x21, 0x63, + 0x33, 0x19, 0x69, 0x7a, 0xc0, 0x1d, 0xe6, 0xb6, 0x1f, 0x1a, 0xcc, 0x21, 0x8e, 0x8d, 0xa3, 0xba, 0x71, 0x9d, 0x31, + 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcb, 0x8b, 0xf2, 0xd6, 0xda, 0x34, 0x74, 0x64, 0xdf, 0x9a, 0xee, 0x38, + 0xc2, 0x88, 0x88, 0xc7, 0x4c, 0x17, 0x2c, 0x2c, 0xb5, 0xb3, 0xb8, 0x29, 0x62, 0x39, 0xb6, 0x23, 0xac, 0x06, 0x60, + 0x16, 0xd8, 0xef, 0xcc, 0x4b, 0xef, 0x35, 0x7a, 0x21, 0x7c, 0xb0, 0x91, 0xf3, 0xb2, 0x98, 0x91, 0xb9, 0xef, 0xd0, + 0x14, 0x1e, 0xb8, 0x3f, 0x55, 0xa7, 0x15, 0x1c, 0xc4, 0xda, 0x71, 0xf4, 0xf7, 0x03, 0x6a, 0x89, 0x17, 0x04, 0x21, + 0x9c, 0x8a, 0xcd, 0x96, 0x0e, 0x88, 0x7d, 0x88, 0x65, 0x6a, 0x00, 0x42, 0x50, 0x0e, 0x56, 0xbb, 0x4f, 0x3b, 0x7d, + 0x8f, 0xd0, 0xf7, 0x11, 0xf3, 0x4d, 0x80, 0xcc, 0x14, 0x94, 0x27, 0x6a, 0x9f, 0x92, 0x88, 0x9e, 0xfc, 0xa4, 0x9b, + 0x6c, 0xd6, 0xa6, 0x4e, 0x02, 0xa5, 0x23, 0x4e, 0xde, 0x62, 0x14, 0xce, 0x8b, 0x13, 0x06, 0x74, 0xbd, 0x14, 0x83, + 0x69, 0xe3, 0x8b, 0xe2, 0x95, 0x2d, 0xa7, 0x86, 0xfd, 0x38, 0xb7, 0x35, 0x27, 0x1c, 0x8e, 0x32, 0x51, 0xf6, 0x4e, + 0x95, 0x1e, 0x0a, 0xac, 0x9b, 0x06, 0xea, 0xfd, 0x84, 0x5d, 0x70, 0xb7, 0x3d, 0x3e, 0xa6, 0x72, 0x04, 0x15, 0x42, + 0x21, 0x41, 0x2d, 0x53, 0xfa, 0x23, 0xe6, 0x39, 0x35, 0x62, 0xaf, 0x3c, 0x2a, 0x65, 0x22, 0x88, 0xc7, 0x3e, 0x7b, + 0xb0, 0xc7, 0x16, 0x08, 0x87, 0x1d, 0x4e, 0x74, 0xa5, 0x80, 0x7e, 0x90, 0x36, 0x82, 0x9d, 0x8f, 0x85, 0x22, 0x59, + 0x80, 0x62, 0x68, 0x37, 0xe2, 0xa4, 0xca, 0xee, 0x92, 0xd0, 0xef, 0xc5, 0x02, 0x67, 0x76, 0x2e, 0x81, 0xe4, 0x3a, + 0x5b, 0x18, 0x64, 0x54, 0x08, 0xed, 0x16, 0x12, 0x10, 0xa6, 0x74, 0x91, 0x0f, 0xf8, 0x91, 0x5e, 0x2a, 0x97, 0x0a, + 0xc9, 0xd3, 0xa5, 0xcf, 0xe1, 0x97, 0x1d, 0xb5, 0xe2, 0xc6, 0x5b, 0x1b, 0xe5, 0x1a, 0xe5, 0x62, 0xd6, 0xfc, 0x47, + 0xec, 0x71, 0x89, 0x74, 0x6c, 0x81, 0xb5, 0xa1, 0x1b, 0x54, 0x96, 0xd2, 0xc0, 0x89, 0x07, 0x12, 0xa9, 0xdb, 0x0e, + 0x47, 0xda, 0xa2, 0xf6, 0x93, 0xbd, 0x57, 0xd7, 0xa0, 0xf4, 0xcc, 0x7a, 0x2b, 0x71, 0x68, 0x2a, 0x64, 0x91, 0x55, + 0xd5, 0x80, 0x95, 0x7c, 0x1c, 0xd2, 0x64, 0x88, 0xee, 0x92, 0xc4, 0x93, 0xcc, 0xe9, 0x37, 0x99, 0xe9, 0x45, 0xff, + 0xa3, 0x12, 0x95, 0x0f, 0x65, 0xff, 0x93, 0x1c, 0xcf, 0x3a, 0xa9, 0x1f, 0x85, 0xd3, 0x90, 0xc6, 0x26, 0x13, 0x30, + 0x80, 0xd5, 0x86, 0x39, 0x94, 0x19, 0x2d, 0x5b, 0xc5, 0xb9, 0xdb, 0x46, 0x4a, 0x6c, 0xe8, 0x27, 0x3b, 0x06, 0xec, + 0x8f, 0xbf, 0x02, 0x71, 0xc0, 0x23, 0x66, 0x1c, 0xec, 0xad, 0x98, 0xb4, 0xa9, 0x28, 0xf8, 0x5d, 0x69, 0x34, 0x81, + 0x6b, 0x3a, 0xa4, 0x69, 0x73, 0xe5, 0x18, 0x32, 0xbd, 0x6c, 0xcc, 0x84, 0x98, 0x39, 0x78, 0x46, 0x28, 0xf6, 0xdf, + 0xfd, 0x77, 0x09, 0x8e, 0x16, 0x8d, 0xf2, 0xe4, 0xb4, 0x0e, 0xe6, 0x56, 0x5d, 0x7a, 0xe7, 0x7e, 0x08, 0x69, 0x03, + 0x80, 0xca, 0x9d, 0xed, 0x59, 0x88, 0xbb, 0xdb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, 0x93, 0xf2, 0xae, 0x97, 0x6c, 0x2c, + 0x61, 0x9e, 0x32, 0x2b, 0x87, 0xd6, 0x81, 0x9d, 0xfd, 0x63, 0xfa, 0x1f, 0xc9, 0xf7, 0x9b, 0xfc, 0x7c, 0xb7, 0x46, + 0x14, 0x98, 0x91, 0x57, 0xf4, 0x3e, 0x07, 0xa0, 0xde, 0x40, 0x24, 0x97, 0xe5, 0x3d, 0x5c, 0xd4, 0x3d, 0xfc, 0x65, + 0x2e, 0x1a, 0x1f, 0x78, 0xcc, 0x57, 0x94, 0xdb, 0x0f, 0x1b, 0x1e, 0x08, 0x44, 0xee, 0x02, 0x23, 0x4c, 0xff, 0x3e, + 0x39, 0xe6, 0xe3, 0xa9, 0xf0, 0xca, 0xab, 0x17, 0xb0, 0xea, 0x89, 0x0f, 0xaf, 0xcf, 0xb0, 0xb5, 0xff, 0x44, 0x66, + 0x15, 0x97, 0x60, 0x66, 0xb0, 0xa8, 0xb8, 0x5f, 0x73, 0x65, 0x07, 0x17, 0xad, 0xee, 0x3b, 0x19, 0xff, 0x7c, 0x19, + 0xee, 0xbe, 0x7e, 0xee, 0x14, 0x8d, 0x73, 0x78, 0x8f, 0x71, 0xc4, 0x35, 0x2e, 0xe1, 0xed, 0xc7, 0x67, 0x55, 0x37, + 0xf7, 0x8c, 0x7d, 0xd6, 0x74, 0x63, 0x55, 0x33, 0xb4, 0x21, 0x71, 0xfe, 0xc3, 0xd6, 0x5f, 0x2c, 0xbc, 0xd8, 0xfd, + 0xc4, 0x4e, 0x8a, 0xac, 0x0b, 0x5a, 0xb7, 0x5d, 0xab, 0xf2, 0x83, 0x01, 0x97, 0x3a, 0x1e, 0x4b, 0xb6, 0x3a, 0xbb, + 0x5f, 0x8c, 0x3f, 0x9a, 0x09, 0xb4, 0x3f, 0xfa, 0xe0, 0x66, 0x09, 0x55, 0x7b, 0x9c, 0xd1, 0xdd, 0xb7, 0x3f, 0x7b, + 0x39, 0x76, 0x59, 0x9a, 0xf8, 0xdc, 0x27, 0xc7, 0xc8, 0x13, 0xe9, 0x2d, 0xb4, 0x0a, 0xc3, 0xf4, 0xdc, 0x3d, 0x44, + 0x6a, 0x91, 0x2c, 0x3d, 0x7b, 0x0b, 0x97, 0x9c, 0xd0, 0x99, 0x7e, 0x29, 0x09, 0x75, 0xdb, 0x6b, 0xc5, 0x25, 0x62, + 0x7e, 0x8d, 0xd4, 0xc0, 0x55, 0x12, 0x3c, 0x44, 0x44, 0xa0, 0xb3, 0x17, 0xe5, 0x33, 0x45, 0x75, 0x85, 0x57, 0x7f, + 0x8d, 0xb2, 0x80, 0x57, 0x66, 0xe3, 0x61, 0xe5, 0x4c, 0x1f, 0x9d, 0xd6, 0x59, 0xae, 0xcb, 0x00, 0x72, 0x71, 0x01, + 0x4e, 0xec, 0xdf, 0x72, 0x06, 0xc3, 0xda, 0x86, 0xfb, 0x23, 0x35, 0x1a, 0xa3, 0xe4, 0x1b, 0x02, 0x30, 0x0a, 0x8a, + 0x36, 0xb3, 0xef, 0x36, 0xa4, 0x0b, 0x19, 0xd5, 0xfb, 0xfd, 0xf7, 0xfc, 0xe5, 0xd1, 0x77, 0xbe, 0x5d, 0x7a, 0xad, + 0x85, 0x49, 0x65, 0x91, 0xad, 0xa3, 0x83, 0xec, 0xae, 0x87, 0x6d, 0x90, 0xdf, 0x74, 0x9f, 0x49, 0x37, 0x2f, 0x06, + 0xd8, 0xd2, 0xf6, 0x23, 0x32, 0x8d, 0x24, 0x51, 0xc8, 0xb1, 0x96, 0x22, 0xa8, 0x65, 0x20, 0x15, 0x47, 0x0e, 0x0f, + 0x4f, 0x46, 0xbe, 0x99, 0x33, 0x0e, 0x2d, 0x69, 0x0b, 0xd8, 0x18, 0xd6, 0xdd, 0xd7, 0x52, 0x9b, 0x65, 0xd6, 0xab, + 0x47, 0x76, 0x22, 0xbc, 0xe0, 0x08, 0x4a, 0xec, 0x53, 0x48, 0x0b, 0xab, 0xb1, 0x0c, 0x6e, 0x5e, 0x4f, 0x28, 0xa0, + 0x6d, 0x2e, 0x9d, 0x53, 0xab, 0xc8, 0x57, 0xfc, 0x7c, 0x58, 0x83, 0x21, 0xf9, 0xd6, 0x4a, 0xc1, 0xc6, 0xae, 0x55, + 0xa5, 0xf1, 0x1c, 0x6f, 0x68, 0x52, 0x1c, 0x1d, 0xed, 0x51, 0x76, 0x08, 0x47, 0x63, 0x70, 0x73, 0x6f, 0xa8, 0xa4, + 0x4c, 0x63, 0xdf, 0x4b, 0xd2, 0xbf, 0xea, 0xcb, 0x50, 0x25, 0x24, 0x8a, 0xf9, 0x1f, 0x54, 0x63, 0x0e, 0x3c, 0x52, + 0x1f, 0xbd, 0xc8, 0x04, 0xa3, 0x85, 0x42, 0x74, 0x83, 0x87, 0x9d, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xd2, 0xbd, + 0x24, 0x9a, 0x17, 0xfe, 0xd9, 0x6f, 0x9e, 0x7b, 0x01, 0xd0, 0x29, 0x2c, 0x9d, 0x31, 0x70, 0xca, 0x9a, 0x74, 0xa4, + 0xe0, 0xd6, 0x68, 0xa0, 0x09, 0x6c, 0xc1, 0xd3, 0xa9, 0x0c, 0xb9, 0x28, 0x67, 0x96, 0xf4, 0x64, 0x17, 0x53, 0x6a, + 0xcd, 0xf7, 0x85, 0xb2, 0xb0, 0x7e, 0xb7, 0x79, 0x94, 0x3b, 0x47, 0x66, 0x25, 0x82, 0x45, 0x9e, 0x02, 0xaf, 0x5c, + 0xde, 0x78, 0xd1, 0xe8, 0x39, 0x78, 0x99, 0x9a, 0x79, 0x0e, 0x07, 0x79, 0xe9, 0x2f, 0xbc, 0x78, 0xfb, 0x7e, 0x0f, + 0xfa, 0x1a, 0xb9, 0x0a, 0x8b, 0xa8, 0x07, 0xe4, 0xbc, 0xe3, 0xa8, 0xbb, 0xfb, 0xe0, 0x93, 0x8e, 0x97, 0x5c, 0x35, + 0x3e, 0x84, 0xbf, 0xa4, 0xd1, 0x17, 0x92, 0xa0, 0x39, 0x15, 0x52, 0x60, 0xe0, 0xaf, 0x5b, 0xd8, 0xf8, 0x3e, 0x4b, + 0xb7, 0x23, 0x26, 0x7f, 0xf5, 0xbe, 0xd2, 0x93, 0x5d, 0x8f, 0x49, 0x3d, 0x05, 0x8a, 0x3a, 0x3b, 0x5a, 0x36, 0x23, + 0xad, 0xd4, 0xbc, 0x5b, 0xb8, 0xf5, 0x81, 0x4f, 0xe9, 0xc0, 0x8e, 0x02, 0x77, 0x41, 0x2c, 0x9e, 0x71, 0x7e, 0x6d, + 0x66, 0xb7, 0x3e, 0xfb, 0x2e, 0x03, 0x8c, 0x5a, 0x4f, 0xf4, 0x41, 0x10, 0xdf, 0x67, 0x47, 0xac, 0xbb, 0x04, 0x96, + 0x60, 0x4c, 0x4f, 0xdb, 0x24, 0x9c, 0x96, 0xfb, 0x64, 0x7e, 0xc8, 0xc6, 0x04, 0x8a, 0x4a, 0x31, 0x57, 0x81, 0x4f, + 0x26, 0x40, 0xcc, 0x21, 0x25, 0xdb, 0xab, 0x33, 0xf9, 0x44, 0xcc, 0x85, 0x2a, 0x45, 0x73, 0x31, 0x02, 0x42, 0x90, + 0xc3, 0x8c, 0xed, 0x3f, 0xc2, 0x85, 0x08, 0x70, 0x87, 0x83, 0x2c, 0x73, 0xde, 0xe0, 0xaa, 0xcc, 0x2f, 0x00, 0x73, + 0x19, 0xea, 0xad, 0xc6, 0x4e, 0x8f, 0x61, 0xf9, 0x7d, 0x1a, 0x64, 0xbd, 0x22, 0x77, 0x61, 0x19, 0xc2, 0xeb, 0xa2, + 0x54, 0x8d, 0x40, 0xba, 0x3b, 0x8c, 0xd3, 0xaf, 0x20, 0x61, 0xfa, 0x59, 0x02, 0x9e, 0xa3, 0x38, 0x11, 0x0b, 0xfe, + 0xdc, 0xd0, 0xa5, 0x13, 0xe4, 0x80, 0xa1, 0x1e, 0x9e, 0x5e, 0x51, 0xf7, 0x92, 0x1d, 0xdd, 0x6d, 0x59, 0xa5, 0xec, + 0x6f, 0x27, 0xf2, 0x63, 0xd9, 0x39, 0x5e, 0xf2, 0xa6, 0xbb, 0x89, 0xdf, 0x22, 0x8e, 0x02, 0x88, 0x63, 0x55, 0x76, + 0xa1, 0x4a, 0x44, 0xbe, 0x2e, 0x9c, 0x39, 0xe5, 0x79, 0x64, 0xc9, 0xce, 0xdb, 0xdd, 0x77, 0xa6, 0xd8, 0x91, 0x66, + 0x76, 0xce, 0x7b, 0xc5, 0x4f, 0x95, 0x12, 0xd3, 0x37, 0x0e, 0xce, 0xfd, 0x9d, 0xf4, 0xfd, 0xf1, 0x70, 0x2c, 0xb1, + 0x9e, 0x5f, 0x73, 0xd5, 0xf6, 0x94, 0xaa, 0x65, 0xad, 0xbf, 0x53, 0xbe, 0xa6, 0x6c, 0xdd, 0xec, 0x67, 0xb0, 0x23, + 0xd7, 0xcc, 0x97, 0x2e, 0xa4, 0x77, 0x7d, 0x39, 0xc9, 0xae, 0x0a, 0xec, 0xd1, 0x07, 0x06, 0xd0, 0xb4, 0xae, 0x0c, + 0xc5, 0x57, 0x6a, 0x19, 0xb9, 0x4c, 0x80, 0xd7, 0xc1, 0x4f, 0x5f, 0xcc, 0x7c, 0x39, 0x66, 0xab, 0x77, 0xde, 0x1f, + 0x31, 0x2f, 0xba, 0xb3, 0xe7, 0x7a, 0x87, 0xb8, 0x18, 0xe7, 0x7d, 0x07, 0x66, 0xe9, 0xb7, 0x1e, 0xf3, 0x79, 0x7f, + 0x9d, 0x60, 0x7f, 0x64, 0x45, 0x30, 0xc8, 0xe0, 0xae, 0x7a, 0xc1, 0x71, 0x16, 0x86, 0x68, 0xda, 0x76, 0x5f, 0xd4, + 0xcc, 0x6d, 0x49, 0xd3, 0xe7, 0xbc, 0xa5, 0x12, 0xf6, 0x8b, 0x3b, 0xce, 0xac, 0xef, 0xbc, 0x83, 0xac, 0xb5, 0xea, + 0xd0, 0xaf, 0x48, 0xbd, 0x0c, 0xeb, 0x3f, 0x81, 0x62, 0xbc, 0xec, 0xb0, 0xda, 0x5a, 0x69, 0x7a, 0xae, 0xca, 0xde, + 0xe1, 0x49, 0x05, 0xa0, 0x14, 0x01, 0x9d, 0x75, 0xe3, 0xb8, 0x9b, 0x02, 0xf5, 0xc5, 0x29, 0xda, 0xf5, 0xf7, 0xd7, + 0xc0, 0x28, 0x88, 0xd4, 0xf7, 0xab, 0xbc, 0x27, 0xfd, 0x95, 0xf8, 0x58, 0x78, 0x45, 0xa1, 0xdb, 0xf2, 0xf8, 0x2f, + 0x8a, 0x94, 0xe9, 0x27, 0x21, 0xdc, 0xf9, 0xb9, 0xba, 0x85, 0x89, 0xf9, 0x74, 0xe9, 0xf9, 0x3d, 0x5a, 0x87, 0x2b, + 0x68, 0x7d, 0xe6, 0x07, 0x69, 0xcc, 0xff, 0x39, 0x56, 0x59, 0xe2, 0x1d, 0x9a, 0xe5, 0xdb, 0x04, 0xc7, 0x74, 0x78, + 0x4a, 0x3a, 0xcf, 0x71, 0x42, 0xa1, 0x1b, 0x94, 0x7a, 0xa7, 0x0e, 0x35, 0x93, 0xc0, 0x42, 0x81, 0x93, 0x7e, 0x44, + 0xf3, 0xa8, 0x38, 0x12, 0xc0, 0xc8, 0xf4, 0xfa, 0xdb, 0x5c, 0x5b, 0xe4, 0xc3, 0x5e, 0xfb, 0x65, 0xe3, 0x5e, 0x1f, + 0x05, 0xc9, 0x7f, 0xc7, 0x01, 0x12, 0x6b, 0x43, 0xf6, 0x26, 0x60, 0x19, 0x51, 0xcc, 0x51, 0xf0, 0x6d, 0x41, 0x52, + 0xa8, 0x54, 0x82, 0x0b, 0x7b, 0x84, 0x85, 0x4b, 0x2d, 0x2d, 0x63, 0x2d, 0x3c, 0x6f, 0x01, 0x3a, 0x3a, 0x7c, 0x5d, + 0x7c, 0x97, 0x9d, 0x5e, 0x0c, 0x92, 0x73, 0x8f, 0x10, 0x24, 0xa8, 0xc7, 0x45, 0x09, 0xb8, 0x6f, 0x56, 0xe3, 0x6b, + 0x41, 0x4d, 0x9a, 0xd4, 0x5d, 0x05, 0xa7, 0xbb, 0x50, 0xc0, 0x65, 0x74, 0xd6, 0x40, 0xd0, 0xf0, 0xdd, 0x91, 0x0c, + 0xb0, 0x2a, 0x48, 0x90, 0xb8, 0xe4, 0x87, 0xc4, 0x4a, 0x45, 0x77, 0x78, 0x47, 0x63, 0xbc, 0xa3, 0xb6, 0x2e, 0x3b, + 0xed, 0x6b, 0xef, 0x36, 0x0c, 0xc2, 0x88, 0xf1, 0x99, 0x81, 0x8e, 0xec, 0xed, 0x80, 0x4d, 0x9e, 0x9d, 0xb0, 0x01, + 0x8f, 0xe5, 0x8e, 0x8c, 0xd6, 0xf9, 0x35, 0xcb, 0x17, 0x7b, 0xda, 0xe7, 0x9e, 0x84, 0x8c, 0x8d, 0x23, 0x70, 0xa3, + 0x06, 0x64, 0x4a, 0x98, 0x25, 0xfc, 0xc8, 0xa1, 0xfa, 0x2c, 0x09, 0xfe, 0x2b, 0x6d, 0x40, 0x01, 0x39, 0xda, 0x93, + 0x4a, 0x92, 0x79, 0x0c, 0xb3, 0x26, 0x85, 0x0f, 0xc8, 0x50, 0xe6, 0xf8, 0x69, 0xa8, 0x29, 0xd6, 0x89, 0xa1, 0x1a, + 0x99, 0x26, 0x86, 0xef, 0x1a, 0xf3, 0x57, 0xdc, 0xfc, 0xd9, 0xab, 0xaa, 0xa7, 0x43, 0xf0, 0x10, 0x4a, 0x09, 0xca, + 0xcd, 0x4c, 0x28, 0x03, 0xe8, 0x17, 0x69, 0xb2, 0x01, 0xad, 0x1f, 0xa1, 0xc3, 0xf7, 0x9b, 0x23, 0x38, 0xb9, 0x2c, + 0x55, 0x58, 0x17, 0x3f, 0xfe, 0x4a, 0x60, 0xef, 0xdd, 0x61, 0xba, 0x51, 0xce, 0xe6, 0xd4, 0x96, 0x4c, 0x5d, 0xf0, + 0x75, 0xb9, 0x3e, 0x09, 0x5e, 0x59, 0x20, 0x35, 0x0b, 0xab, 0x75, 0xe2, 0x12, 0x59, 0xb4, 0x38, 0x4d, 0xde, 0xcd, + 0x5f, 0x9e, 0x66, 0x13, 0xaf, 0x5c, 0x0a, 0x4c, 0x7e, 0x16, 0x55, 0xe2, 0x22, 0xb3, 0x5c, 0x36, 0xfc, 0xcd, 0x01, + 0x9f, 0x67, 0x7d, 0x3d, 0xf0, 0xbb, 0xfe, 0x5c, 0xdf, 0x1e, 0xf2, 0x90, 0x50, 0x8b, 0xdb, 0x1a, 0x67, 0x4e, 0x8d, + 0x6d, 0xe6, 0xbd, 0x5d, 0xda, 0xc7, 0x71, 0xcc, 0x7c, 0x44, 0x45, 0xba, 0xa2, 0x24, 0xec, 0x4e, 0x87, 0xa4, 0x53, + 0x4c, 0x56, 0x9c, 0x39, 0xf5, 0x54, 0xb8, 0x2d, 0xce, 0x6b, 0x7c, 0xb8, 0x44, 0x74, 0x82, 0xa9, 0x03, 0x24, 0xd7, + 0xb1, 0x25, 0xb8, 0xab, 0x08, 0x5c, 0x9a, 0x5a, 0xa8, 0xa2, 0x78, 0xc6, 0x59, 0xec, 0x16, 0x52, 0xf3, 0x53, 0xf5, + 0xb8, 0xd4, 0xad, 0x2a, 0xe1, 0x95, 0x6c, 0x85, 0x29, 0x90, 0xc9, 0x8a, 0xa4, 0x39, 0x89, 0x15, 0x0e, 0xfa, 0x9e, + 0x43, 0x92, 0xbd, 0x58, 0xf6, 0xb6, 0x7f, 0xeb, 0x6a, 0xcd, 0x0a, 0xa3, 0x5d, 0xac, 0x16, 0xc5, 0x8b, 0x54, 0x6d, + 0x1f, 0xa8, 0xbb, 0xca, 0x7d, 0xc7, 0x40, 0xa3, 0x46, 0x2a, 0x5b, 0x51, 0x47, 0x6a, 0x78, 0xcc, 0x5f, 0x9b, 0xe9, + 0x88, 0x31, 0x6c, 0xd8, 0xd1, 0x41, 0xb3, 0xb9, 0x0c, 0x8a, 0xa9, 0xc5, 0x61, 0x54, 0x1a, 0xba, 0x8d, 0xc8, 0x57, + 0x28, 0xcf, 0xec, 0x1b, 0x63, 0x43, 0x2c, 0xd9, 0x53, 0xbc, 0x06, 0xc2, 0x24, 0xa5, 0xcf, 0x62, 0x8b, 0xc2, 0xa6, + 0xcd, 0xed, 0x99, 0x63, 0x03, 0x0e, 0xae, 0x92, 0x52, 0xa6, 0xab, 0xc2, 0xab, 0x40, 0x29, 0xac, 0x44, 0x67, 0x09, + 0x21, 0x63, 0x9e, 0xbd, 0xf3, 0x53, 0xd3, 0x73, 0x8f, 0x80, 0x68, 0xf6, 0x05, 0x1c, 0x05, 0x1f, 0xc4, 0x88, 0x8f, + 0x34, 0xe4, 0x1c, 0xbe, 0x72, 0x98, 0xbe, 0xb7, 0x85, 0xe4, 0x47, 0x3f, 0x1f, 0x2f, 0x94, 0x29, 0x49, 0xb5, 0x83, + 0xd0, 0x06, 0x12, 0x67, 0x80, 0x78, 0x96, 0x81, 0x25, 0x28, 0x8d, 0x01, 0x83, 0x83, 0xcf, 0x47, 0xbb, 0x22, 0xd4, + 0x12, 0xa1, 0xbb, 0x2c, 0x5d, 0x80, 0xb3, 0x6e, 0x90, 0xd1, 0x26, 0xf6, 0x70, 0x7f, 0xe1, 0x80, 0xee, 0xc4, 0xe0, + 0xc8, 0xc9, 0xec, 0xb2, 0x25, 0xc1, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, 0x25, 0x52, 0x21, 0xde, 0x58, 0x3a, 0xc0, 0x4c, + 0xa1, 0x3d, 0x55, 0xeb, 0x8e, 0x48, 0xf1, 0x1b, 0xe0, 0x41, 0x34, 0x42, 0x03, 0x47, 0xa2, 0x7e, 0x1e, 0xa3, 0x25, + 0xc6, 0x23, 0xce, 0x7f, 0x4c, 0x2d, 0x07, 0x93, 0x04, 0x72, 0x18, 0xed, 0x1e, 0x3b, 0x13, 0x8a, 0xb3, 0x9d, 0xb4, + 0x6c, 0x3d, 0xfd, 0xdc, 0xa6, 0x0f, 0x66, 0xef, 0x15, 0xde, 0x10, 0x5c, 0x28, 0xfa, 0xcb, 0x2d, 0xcf, 0x30, 0x02, + 0x0c, 0x86, 0xdd, 0x60, 0xfe, 0xfd, 0xe9, 0x24, 0x3a, 0x3c, 0xaa, 0x1f, 0xae, 0x7a, 0x3b, 0x98, 0x3a, 0x93, 0xc1, + 0xf9, 0xe4, 0x97, 0x89, 0xbb, 0xef, 0x44, 0xf2, 0xc5, 0x94, 0x79, 0x8e, 0x7c, 0xd2, 0x09, 0xcc, 0x76, 0x0d, 0xa3, + 0x9a, 0x5a, 0x02, 0x91, 0x88, 0xa9, 0xd0, 0x8d, 0x94, 0xf3, 0x72, 0x7b, 0x4b, 0xe1, 0xfb, 0x6d, 0xaa, 0x52, 0xa5, + 0x46, 0x11, 0x96, 0x9b, 0xf4, 0x83, 0x83, 0xee, 0xf7, 0xa5, 0xbc, 0x5c, 0x4e, 0x6b, 0x91, 0xc7, 0x43, 0x21, 0xea, + 0x7c, 0xa4, 0xbd, 0x7f, 0xa2, 0xf3, 0x33, 0x49, 0xc8, 0xae, 0xff, 0x54, 0x11, 0x60, 0xfc, 0x15, 0xa2, 0xae, 0x4d, + 0x32, 0xa8, 0xd4, 0x4b, 0x2b, 0xbc, 0x83, 0xaf, 0x88, 0xdc, 0x0a, 0xfa, 0x95, 0x51, 0xe5, 0xad, 0x57, 0x6d, 0x97, + 0xb3, 0x2f, 0xb0, 0x60, 0xd3, 0x9a, 0x0e, 0x5e, 0xf9, 0xeb, 0xe0, 0xa8, 0xa0, 0x37, 0x9c, 0x3a, 0x23, 0xf5, 0x10, + 0xef, 0xe7, 0x02, 0x05, 0x27, 0xc4, 0x3f, 0x0a, 0x86, 0x46, 0xe9, 0x5a, 0x6a, 0x63, 0x6c, 0x0f, 0x98, 0xaf, 0x57, + 0x95, 0x71, 0x95, 0xdd, 0x09, 0x1e, 0x3b, 0x37, 0x3e, 0x85, 0x91, 0xb4, 0x3c, 0xc0, 0x39, 0xab, 0x43, 0x07, 0xce, + 0x6b, 0xf6, 0x85, 0x6a, 0x3d, 0x14, 0x33, 0x12, 0x6d, 0x4d, 0xb0, 0x8c, 0x3c, 0x9b, 0xb5, 0xe7, 0xa9, 0x49, 0x66, + 0x35, 0xd2, 0x66, 0x7c, 0x6a, 0xfa, 0xaf, 0x01, 0xb1, 0x1e, 0x74, 0xf9, 0x6d, 0xa5, 0xfa, 0x5a, 0x21, 0xeb, 0x11, + 0xc7, 0x4a, 0x95, 0x6d, 0x83, 0x63, 0x07, 0x6e, 0x35, 0x1e, 0x0f, 0xbe, 0x17, 0xd2, 0x58, 0x9d, 0x04, 0x2e, 0x9d, + 0x50, 0xf9, 0x86, 0x2b, 0x06, 0x76, 0x12, 0xdd, 0x2c, 0x17, 0x51, 0x22, 0x45, 0xfe, 0x36, 0x70, 0x8a, 0xe1, 0x50, + 0x08, 0x0f, 0xe2, 0xdf, 0x24, 0x09, 0xf3, 0x3a, 0x52, 0x9d, 0x58, 0xed, 0xe0, 0x7a, 0x95, 0x1e, 0x05, 0x07, 0x6b, + 0xaa, 0xa4, 0x0d, 0x25, 0xea, 0x52, 0x8f, 0x61, 0x4d, 0x0f, 0x87, 0x7a, 0x71, 0xe3, 0x70, 0xe5, 0x63, 0xcd, 0xa2, + 0xf5, 0x17, 0x35, 0x1c, 0xab, 0x11, 0x36, 0x53, 0x11, 0xcd, 0xec, 0xff, 0x88, 0x2b, 0x1d, 0xb2, 0x0b, 0x80, 0xda, + 0x8f, 0xf8, 0x06, 0x55, 0x31, 0x02, 0xb4, 0x9f, 0x96, 0x6f, 0xa4, 0x3e, 0xe5, 0x19, 0x8b, 0xeb, 0x16, 0x51, 0xe4, + 0x22, 0x18, 0x6b, 0x8a, 0x0d, 0x00, 0x61, 0xd9, 0x02, 0x1b, 0x88, 0xa2, 0x59, 0x94, 0x4d, 0xdd, 0x60, 0xb7, 0x78, + 0x01, 0xd1, 0x9a, 0xc7, 0x67, 0x62, 0xcd, 0x9c, 0x1b, 0xa9, 0x2c, 0x2b, 0x7c, 0xff, 0xea, 0x8a, 0xb9, 0x42, 0x83, + 0xf7, 0xf6, 0xdc, 0xca, 0x1e, 0x9d, 0x0f, 0x76, 0x33, 0xfd, 0x0b, 0xbb, 0x0e, 0x6f, 0xd9, 0x26, 0xcc, 0x08, 0x9f, + 0xdc, 0x3e, 0xfe, 0x8a, 0x35, 0xe1, 0xfc, 0x47, 0x51, 0x31, 0x28, 0x5c, 0x41, 0xb0, 0xa8, 0x35, 0xe3, 0x94, 0xc2, + 0x63, 0x1f, 0xa8, 0xd0, 0x1e, 0x24, 0x26, 0x08, 0xa3, 0x2a, 0x53, 0x25, 0xb2, 0xe7, 0xe2, 0x57, 0x6d, 0x22, 0x83, + 0xc9, 0x38, 0x94, 0x0d, 0xdc, 0xd4, 0xae, 0x39, 0x33, 0x3b, 0x4b, 0xeb, 0xdf, 0x6b, 0x8e, 0x75, 0x58, 0xb0, 0x44, + 0x6b, 0xa8, 0x99, 0x5e, 0x56, 0x2d, 0xc2, 0x5b, 0xc3, 0x74, 0x78, 0x08, 0x52, 0xcb, 0x22, 0xe1, 0x0f, 0xdd, 0x77, + 0xd0, 0x22, 0x18, 0xa3, 0x11, 0x58, 0x19, 0xa7, 0x90, 0xeb, 0xfc, 0x38, 0x25, 0x0a, 0xd4, 0xb2, 0xde, 0x67, 0x2c, + 0x73, 0xe4, 0x35, 0x2b, 0xf3, 0x34, 0x2b, 0x7a, 0x8f, 0xb2, 0xa1, 0xe3, 0xfa, 0x73, 0x26, 0x1a, 0x49, 0x87, 0x86, + 0x3a, 0x1d, 0xe7, 0xc4, 0x95, 0x35, 0x47, 0x53, 0x24, 0xb7, 0xf5, 0x40, 0xda, 0xcd, 0x6c, 0x25, 0x4c, 0xb6, 0xd8, + 0x6c, 0x46, 0xd8, 0xee, 0x68, 0xec, 0x33, 0x4f, 0x1c, 0xd7, 0x10, 0x3d, 0xd0, 0xe6, 0xce, 0x4b, 0x6e, 0x5c, 0xfc, + 0xef, 0xa0, 0x88, 0x6e, 0x1e, 0x8e, 0x08, 0xe6, 0x72, 0x4e, 0x51, 0x3c, 0xdd, 0x1c, 0x87, 0xc0, 0x86, 0xf5, 0x9f, + 0x9b, 0xe8, 0x4a, 0x8e, 0xe7, 0xa8, 0xd2, 0x23, 0x05, 0x71, 0x62, 0x7b, 0x76, 0x0d, 0x49, 0xfb, 0x11, 0x09, 0xcf, + 0x29, 0xeb, 0x6c, 0x74, 0xae, 0x73, 0x5d, 0x7a, 0x1f, 0x7f, 0x25, 0x3d, 0x21, 0x08, 0x0c, 0xf3, 0xa7, 0xb8, 0x9f, + 0xc0, 0x8a, 0x0b, 0xab, 0x52, 0xae, 0x78, 0xe1, 0x5f, 0x73, 0xc6, 0xf7, 0xb4, 0x2a, 0x2b, 0xd9, 0x71, 0x79, 0xa5, + 0x73, 0xd6, 0x50, 0xa5, 0x63, 0xa6, 0xcb, 0x8a, 0xc5, 0xf4, 0x8e, 0xfd, 0xba, 0x36, 0x04, 0x34, 0x74, 0xe7, 0xdc, + 0x51, 0x31, 0x93, 0xe0, 0x69, 0x88, 0xa5, 0x52, 0x80, 0xae, 0xd0, 0x67, 0xe6, 0xe4, 0x9b, 0x61, 0x1e, 0x0c, 0xf9, + 0x59, 0x00, 0x08, 0x57, 0x26, 0xa8, 0xac, 0xc0, 0xb3, 0xe2, 0x5a, 0xd1, 0x79, 0x0d, 0xe6, 0x22, 0xa2, 0xde, 0x6b, + 0xa4, 0xff, 0x00, 0x09, 0x97, 0x60, 0x2f, 0x05, 0x2e, 0x06, 0x74, 0xf9, 0xcc, 0x1d, 0x5a, 0x97, 0x08, 0x31, 0xd6, + 0x80, 0xa4, 0xb6, 0xf1, 0xcb, 0xc5, 0x84, 0x7b, 0xde, 0xcf, 0x03, 0xce, 0xba, 0x7e, 0x06, 0x90, 0x07, 0xf9, 0xf3, + 0x57, 0xb7, 0x72, 0x39, 0xc8, 0x09, 0x48, 0x5c, 0x5c, 0xb8, 0xf2, 0x88, 0x76, 0x4e, 0x8b, 0xb6, 0xcc, 0xd5, 0x28, + 0xe3, 0xb6, 0x06, 0x29, 0x52, 0xb8, 0xd8, 0x48, 0xfb, 0x18, 0xb8, 0x20, 0xe9, 0x89, 0x0d, 0x85, 0x84, 0x1d, 0xbb, + 0xf6, 0x62, 0x2a, 0xb7, 0x33, 0xea, 0x06, 0xfa, 0x62, 0xeb, 0x6f, 0x34, 0xfe, 0xb4, 0xb1, 0x76, 0xa6, 0xef, 0x19, + 0x5c, 0x11, 0xa9, 0x46, 0x9f, 0x57, 0x58, 0x7d, 0xda, 0xef, 0xca, 0x1d, 0xac, 0xd6, 0x97, 0xd1, 0x57, 0x15, 0x1b, + 0xf5, 0x89, 0x0d, 0x82, 0x49, 0x92, 0x54, 0x72, 0x6b, 0x50, 0x52, 0xd0, 0x98, 0xb7, 0x51, 0x43, 0x56, 0x4a, 0x6b, + 0x26, 0x7b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, 0xb1, 0xa5, 0x3e, 0x79, 0xf4, 0xc4, 0x5b, 0xeb, 0xf7, + 0x9c, 0xa1, 0x63, 0xf6, 0x00, 0x81, 0x42, 0x60, 0x5e, 0xba, 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xcb, 0x7f, + 0x66, 0x57, 0xba, 0xc0, 0xd8, 0x27, 0x82, 0xfe, 0x5c, 0xda, 0xed, 0xd4, 0x37, 0x66, 0xef, 0x06, 0x9c, 0x06, 0x98, + 0xb9, 0x78, 0x53, 0xe9, 0xdd, 0xd5, 0xe6, 0x11, 0x0b, 0x60, 0x72, 0x36, 0xfa, 0x97, 0xa6, 0x22, 0xf8, 0xcb, 0xa3, + 0xb3, 0x17, 0xeb, 0x23, 0x0a, 0x05, 0x5f, 0x46, 0x23, 0xde, 0x65, 0xf4, 0x2f, 0x1a, 0x5a, 0xff, 0x03, 0xfb, 0x60, + 0x1b, 0x97, 0x61, 0x0f, 0xed, 0xc3, 0x24, 0x76, 0x45, 0xd0, 0xd6, 0xc6, 0x82, 0x20, 0x6b, 0xea, 0x72, 0x60, 0x44, + 0x8a, 0xdf, 0x5a, 0x27, 0x9d, 0xd7, 0xb1, 0xef, 0xda, 0x89, 0xf3, 0x21, 0x11, 0x23, 0xf0, 0x5b, 0xf4, 0x7c, 0x24, + 0xa1, 0x82, 0x4b, 0x47, 0x2f, 0x13, 0x3c, 0xea, 0x12, 0x27, 0xd5, 0xae, 0x97, 0xa3, 0xf6, 0xcf, 0xfa, 0x66, 0x3f, + 0x18, 0x94, 0xae, 0x1b, 0x86, 0x6f, 0xe9, 0xb5, 0xcc, 0x91, 0x87, 0x77, 0x7d, 0xa3, 0xb5, 0x05, 0xd6, 0xba, 0x6c, + 0x0b, 0x45, 0x9d, 0xf0, 0xfa, 0x5d, 0xe3, 0xf8, 0xbf, 0x94, 0x59, 0xc1, 0x50, 0x98, 0xcc, 0x44, 0xbd, 0xd9, 0x82, + 0x74, 0x16, 0x7a, 0x7b, 0xd7, 0xbf, 0x54, 0x9a, 0x03, 0xb6, 0x98, 0x31, 0x38, 0xd5, 0x83, 0x66, 0xf0, 0x12, 0x0a, + 0x84, 0xb9, 0x77, 0x86, 0xce, 0xa0, 0xfb, 0xd5, 0x09, 0xca, 0x44, 0x31, 0xe8, 0x59, 0x0a, 0x25, 0x6d, 0x42, 0x6a, + 0xdd, 0xef, 0x0d, 0x6e, 0x7d, 0xe8, 0xdf, 0xcc, 0x28, 0xa2, 0x51, 0xef, 0x9c, 0x24, 0xa0, 0xe8, 0x15, 0x07, 0x3a, + 0x51, 0xde, 0x6c, 0x89, 0x11, 0xeb, 0x78, 0x9c, 0xe4, 0xea, 0xe0, 0xf1, 0x4a, 0xc9, 0xf1, 0xaa, 0x10, 0x7a, 0x0e, + 0x60, 0x88, 0x23, 0x70, 0x2f, 0x87, 0x05, 0x74, 0x01, 0xcf, 0xf4, 0x8e, 0x7a, 0x36, 0x73, 0xb4, 0xfb, 0x7f, 0x97, + 0x7b, 0xd4, 0x5b, 0x3c, 0xdb, 0x24, 0x0e, 0x58, 0xd6, 0x34, 0x02, 0xdf, 0xfc, 0xf4, 0xae, 0xd6, 0x63, 0xc9, 0x9b, + 0x2d, 0x95, 0x39, 0xd8, 0x10, 0x5d, 0xa7, 0x45, 0xd2, 0xa7, 0x5c, 0x1d, 0xdb, 0x14, 0x50, 0xc3, 0xfd, 0xb4, 0x73, + 0x45, 0x78, 0x9c, 0xb0, 0x86, 0x73, 0x2a, 0x1c, 0x76, 0x70, 0xb4, 0x11, 0x46, 0x37, 0xe4, 0x18, 0x4b, 0xea, 0x20, + 0xbe, 0x1d, 0xe0, 0x13, 0x7c, 0xbf, 0x30, 0xca, 0x97, 0x0e, 0xf1, 0x47, 0x06, 0x8d, 0x0e, 0x72, 0x89, 0x95, 0x3c, + 0x61, 0xea, 0xaf, 0x95, 0xda, 0xca, 0x75, 0xb9, 0xb9, 0xb7, 0x57, 0xb7, 0x92, 0x59, 0x38, 0xc9, 0x28, 0x3e, 0x92, + 0x1e, 0xd5, 0x2b, 0xf9, 0xcf, 0xed, 0xc6, 0x20, 0x99, 0xb9, 0xbd, 0x7b, 0x27, 0x30, 0x76, 0xa8, 0x74, 0xa2, 0xe0, + 0x5f, 0x22, 0xe1, 0x67, 0xa3, 0x11, 0x29, 0x28, 0x2c, 0xb9, 0x0a, 0x55, 0x68, 0x9f, 0xb9, 0xe9, 0xa5, 0xa2, 0x72, + 0x8c, 0x51, 0x31, 0x9b, 0xf1, 0x8b, 0xa1, 0x1a, 0x23, 0xf5, 0xd3, 0x9c, 0x6d, 0xbf, 0xf5, 0x44, 0xaf, 0x45, 0x73, + 0x20, 0x09, 0x1a, 0x57, 0x02, 0x14, 0xe0, 0x10, 0x13, 0x8c, 0xc9, 0x5d, 0x62, 0xd0, 0x34, 0xc3, 0xf3, 0x14, 0xea, + 0x5a, 0x8d, 0x27, 0x95, 0x6f, 0x6d, 0x97, 0x95, 0x54, 0xb6, 0x13, 0xa3, 0x79, 0x27, 0x41, 0xe2, 0xa8, 0x71, 0x8a, + 0x82, 0x55, 0xf5, 0x0c, 0x29, 0xc3, 0x12, 0x20, 0xad, 0x38, 0x87, 0x6f, 0xcf, 0x43, 0x66, 0x17, 0x96, 0xd8, 0x2b, + 0xdd, 0x2c, 0x85, 0x08, 0x6e, 0x17, 0x15, 0x09, 0xb9, 0xbe, 0x65, 0x93, 0x2c, 0x74, 0xe9, 0x5b, 0x67, 0xe8, 0x12, + 0xd2, 0x87, 0x1c, 0xf5, 0xdb, 0xbd, 0x04, 0x9c, 0x20, 0x8c, 0x8d, 0x09, 0xd9, 0x7c, 0xd4, 0x0b, 0xf2, 0x28, 0x6f, + 0x05, 0x8d, 0xab, 0xcd, 0xd2, 0xfb, 0x9f, 0x30, 0x1a, 0xca, 0x65, 0x43, 0x26, 0xb3, 0xa2, 0x83, 0xe6, 0xab, 0x65, + 0x6c, 0x0e, 0x2a, 0xc8, 0x31, 0x27, 0x01, 0x7a, 0x5c, 0x81, 0xe7, 0x96, 0x45, 0xbd, 0x49, 0xf5, 0x67, 0xc5, 0x0b, + 0x5d, 0x83, 0xdd, 0xd7, 0x0e, 0x62, 0xc7, 0x26, 0x53, 0xbb, 0x58, 0x05, 0x4a, 0xe2, 0x88, 0x6e, 0x85, 0x3e, 0x85, + 0x2a, 0x77, 0xa4, 0x10, 0xc3, 0x3a, 0xc0, 0xc2, 0x59, 0xc9, 0x4c, 0xd8, 0x3e, 0xcc, 0xe7, 0x8f, 0x51, 0x6b, 0x01, + 0xd3, 0x43, 0x08, 0xf5, 0xdd, 0x1d, 0xee, 0x28, 0x3a, 0x3a, 0x93, 0xc9, 0x5d, 0x56, 0xc8, 0xa0, 0x5f, 0xf8, 0x58, + 0xc0, 0x05, 0x57, 0xe4, 0x92, 0xb1, 0xa0, 0xe9, 0x14, 0x4c, 0xcb, 0xd4, 0xb9, 0xfc, 0xdd, 0xfb, 0x98, 0x40, 0x2d, + 0x88, 0x45, 0xd3, 0x84, 0x13, 0xd4, 0xd0, 0x1d, 0x44, 0x6b, 0xda, 0x93, 0xc7, 0x8b, 0xec, 0x19, 0xc6, 0xca, 0x09, + 0xfe, 0xd4, 0xe5, 0xba, 0xfa, 0xf2, 0x5d, 0x90, 0x4a, 0xef, 0x8d, 0x4e, 0x4b, 0xd2, 0x3b, 0xca, 0x11, 0xd1, 0xa4, + 0xe3, 0x6f, 0x1f, 0x91, 0xb7, 0x20, 0x13, 0x1b, 0x3e, 0x5c, 0xd6, 0x9a, 0xf7, 0x5f, 0x51, 0xb0, 0x4a, 0x11, 0xce, + 0x7e, 0xa2, 0x49, 0x1c, 0xb2, 0x15, 0x21, 0xed, 0x8b, 0x60, 0xa4, 0xa3, 0x82, 0xd8, 0x8a, 0xed, 0x6a, 0x6d, 0xb9, + 0x87, 0x40, 0xc4, 0x39, 0xb8, 0x42, 0x66, 0x19, 0x9c, 0x63, 0xaf, 0x7e, 0x79, 0x80, 0xe0, 0xf2, 0x14, 0xf5, 0xbf, + 0x5e, 0x16, 0x7e, 0xf4, 0x70, 0xa0, 0x75, 0x64, 0x65, 0x65, 0x4e, 0xbd, 0x54, 0x1f, 0xcb, 0x3a, 0x1e, 0xad, 0xfa, + 0x9a, 0x7e, 0xa3, 0x94, 0x46, 0x9b, 0x41, 0x8b, 0xdb, 0x94, 0x95, 0x1a, 0xc3, 0x9f, 0x59, 0x2d, 0xea, 0xa1, 0xc2, + 0x1d, 0xae, 0x0d, 0xde, 0xb3, 0x77, 0x30, 0x91, 0x22, 0xef, 0xdb, 0x3f, 0x35, 0xb8, 0x21, 0x61, 0x3a, 0xe1, 0x90, + 0x3b, 0x70, 0x05, 0xd3, 0x93, 0x4e, 0xdd, 0x35, 0xc4, 0xd7, 0x22, 0xc9, 0x8e, 0xfe, 0x1b, 0x05, 0xcf, 0x17, 0x32, + 0xd6, 0x84, 0x8c, 0x6e, 0x0b, 0x6b, 0x11, 0x69, 0xa5, 0xc1, 0xc4, 0x18, 0xc5, 0x7c, 0x4a, 0x94, 0x88, 0x65, 0xb7, + 0x25, 0x23, 0xb1, 0xcf, 0xd6, 0x96, 0xbd, 0xd5, 0x4d, 0x4b, 0x82, 0x96, 0xa5, 0x20, 0x5e, 0x2e, 0xcf, 0x44, 0x15, + 0xd0, 0xb5, 0x71, 0x03, 0x22, 0x4e, 0xef, 0xac, 0xf6, 0x16, 0x04, 0xd0, 0x3e, 0xff, 0xfb, 0x4a, 0xe9, 0xe2, 0x56, + 0x85, 0x12, 0x82, 0x1f, 0xb2, 0x4c, 0x96, 0x40, 0x19, 0xe4, 0x63, 0xcb, 0x07, 0xf7, 0x15, 0x56, 0xeb, 0xbb, 0xf5, + 0x10, 0xb1, 0x79, 0x3e, 0x84, 0xb4, 0x83, 0xe1, 0x99, 0x02, 0x4f, 0xf6, 0x2f, 0xdb, 0x87, 0x0d, 0xd0, 0xba, 0xc9, + 0x50, 0x7e, 0x57, 0xaa, 0x89, 0x32, 0x82, 0x8f, 0x5f, 0xed, 0x70, 0x61, 0x43, 0xed, 0xc0, 0x68, 0x1a, 0x76, 0xcb, + 0x3f, 0x20, 0x56, 0x48, 0xe8, 0xea, 0x08, 0x60, 0xeb, 0x32, 0x26, 0x7c, 0xc9, 0xbe, 0x41, 0x18, 0x00, 0x89, 0xdf, + 0xfe, 0xaa, 0x1d, 0x9f, 0x98, 0xeb, 0xf2, 0xfb, 0xb6, 0xbd, 0x4a, 0x44, 0xef, 0x63, 0x27, 0x66, 0x3b, 0xf6, 0x01, + 0x2b, 0x1e, 0x56, 0x8d, 0xe8, 0xd8, 0xf3, 0xa1, 0x70, 0x9f, 0xe2, 0xd1, 0xd6, 0x21, 0xfa, 0x9d, 0x28, 0xb2, 0xc5, + 0x76, 0xc9, 0xfe, 0x42, 0x4b, 0xe7, 0xd3, 0x07, 0x9a, 0x41, 0xdd, 0x1e, 0x23, 0xaf, 0x22, 0x80, 0x78, 0x0c, 0x76, + 0xe1, 0xeb, 0x32, 0xef, 0x99, 0xbc, 0x02, 0xfc, 0x9c, 0x72, 0xf2, 0x97, 0xe7, 0x8b, 0x26, 0x22, 0xe8, 0xb3, 0x2e, + 0x49, 0x02, 0x22, 0xe2, 0x71, 0x3a, 0x3b, 0x36, 0x4d, 0x7a, 0x19, 0x39, 0x3c, 0x62, 0x33, 0x2b, 0xdf, 0xb1, 0xaa, + 0x8b, 0xb3, 0x5b, 0x3e, 0xda, 0x5f, 0xe8, 0x41, 0x67, 0x90, 0xa8, 0x5d, 0x9c, 0xc9, 0x68, 0x76, 0x64, 0x1a, 0x63, + 0x43, 0xb4, 0x97, 0x8a, 0x29, 0x19, 0x66, 0x39, 0x46, 0x1d, 0xd7, 0x46, 0x4e, 0x97, 0x93, 0x25, 0x0e, 0xc3, 0x12, + 0xe3, 0x7d, 0x1a, 0x10, 0xf4, 0x72, 0x05, 0x1d, 0xec, 0xe2, 0x5c, 0x6f, 0x87, 0x1c, 0x1a, 0x10, 0x97, 0x1a, 0xef, + 0xe2, 0x5c, 0xf7, 0xa0, 0xca, 0x53, 0x64, 0xc5, 0xc3, 0x9f, 0x52, 0xbf, 0x54, 0x8e, 0xf1, 0x9e, 0x81, 0xc4, 0xd8, + 0x6f, 0x6c, 0xcf, 0xfd, 0x26, 0x28, 0x66, 0x99, 0xa2, 0x91, 0x9e, 0x17, 0xee, 0xc1, 0x6c, 0x4f, 0xdb, 0xab, 0xd1, + 0x54, 0xc1, 0xcc, 0xa2, 0x13, 0xc0, 0xe6, 0x0f, 0xc4, 0x54, 0x45, 0x57, 0x3c, 0x52, 0x08, 0xc2, 0x70, 0xb5, 0xde, + 0x91, 0xed, 0xb3, 0x42, 0x68, 0xb9, 0x63, 0x26, 0x19, 0xf8, 0xb9, 0xf1, 0x61, 0xd6, 0x35, 0xbe, 0xa8, 0x27, 0x40, + 0x33, 0x71, 0xe5, 0xc3, 0xc7, 0xc9, 0x42, 0x61, 0x82, 0x92, 0xd1, 0x4f, 0xae, 0xa6, 0x5a, 0xd2, 0x9d, 0x74, 0xd8, + 0x9b, 0x2d, 0x5f, 0x27, 0x65, 0x1d, 0x76, 0x29, 0xfb, 0x58, 0xca, 0x03, 0xed, 0x76, 0x33, 0xdb, 0xc3, 0xdf, 0x70, + 0xf3, 0x01, 0xa0, 0x8b, 0x84, 0x95, 0x49, 0x6e, 0xd1, 0x80, 0x5f, 0x7c, 0x30, 0x38, 0x19, 0xc3, 0xf6, 0xe0, 0xc5, + 0xdc, 0x61, 0x9d, 0x63, 0xff, 0xd6, 0x91, 0x9b, 0x38, 0x0a, 0xa4, 0xe4, 0xab, 0x85, 0x45, 0x15, 0xa2, 0xc3, 0x40, + 0xe3, 0xaa, 0xcf, 0x13, 0xb0, 0x90, 0x33, 0xb5, 0x26, 0xd9, 0xfc, 0x53, 0x05, 0xc4, 0xf3, 0xd9, 0x72, 0x08, 0x24, + 0xc8, 0xb7, 0xb2, 0x5a, 0x16, 0xaf, 0x09, 0x27, 0xb0, 0x3d, 0x82, 0x45, 0x63, 0x77, 0x04, 0x00, 0x5a, 0xe8, 0x20, + 0xa4, 0xd4, 0x85, 0x0b, 0x65, 0x2f, 0xd7, 0xc8, 0x86, 0xa9, 0x6b, 0x81, 0x17, 0xdf, 0x4e, 0x38, 0xfa, 0xf7, 0x47, + 0x43, 0xb2, 0x8e, 0x00, 0x2e, 0x27, 0x78, 0x1f, 0x36, 0x8d, 0x3d, 0x03, 0xce, 0x48, 0xfb, 0xa2, 0x70, 0x45, 0x3f, + 0x0c, 0xac, 0x0b, 0xf1, 0x2c, 0x38, 0x47, 0x26, 0xbb, 0x12, 0xfa, 0x45, 0xd1, 0x0c, 0x09, 0x5e, 0x30, 0x8e, 0x6d, + 0xe0, 0x73, 0x07, 0xf4, 0xd3, 0x98, 0x8b, 0xb6, 0x05, 0x1e, 0x2b, 0xaa, 0xcc, 0x29, 0x87, 0x6e, 0x10, 0xad, 0xbd, + 0xfa, 0x5c, 0xea, 0x3b, 0x9c, 0x95, 0xce, 0x8a, 0x7b, 0x97, 0x55, 0x0f, 0x05, 0x9f, 0x20, 0xc7, 0xfb, 0x57, 0x14, + 0xfb, 0x9f, 0x36, 0xe2, 0x68, 0xc1, 0xa6, 0x00, 0x0c, 0x20, 0x21, 0xd3, 0x08, 0xdb, 0x3a, 0x09, 0x3a, 0x7e, 0x28, + 0x3d, 0x46, 0x1c, 0x4a, 0x5a, 0x61, 0x70, 0x98, 0xaa, 0x6f, 0x83, 0x0c, 0x29, 0x79, 0xb9, 0x94, 0x1e, 0x86, 0x18, + 0x39, 0x20, 0x95, 0xb9, 0xf2, 0x3d, 0x7b, 0x55, 0x3c, 0x51, 0xea, 0xc4, 0x07, 0x10, 0x8b, 0xa1, 0x47, 0x46, 0x7d, + 0x20, 0x53, 0x5d, 0x80, 0x26, 0x86, 0x90, 0x51, 0x02, 0x88, 0x8d, 0xa1, 0x11, 0x02, 0x25, 0xe4, 0xd8, 0xfa, 0xc5, + 0xac, 0x0a, 0x12, 0xa1, 0x88, 0x45, 0x4b, 0xb4, 0x38, 0x62, 0x14, 0x60, 0x86, 0x34, 0xd0, 0x63, 0xee, 0x9a, 0x0e, + 0x8c, 0x0b, 0x30, 0xa6, 0xe2, 0x1e, 0x40, 0x7e, 0x33, 0x86, 0xb1, 0x88, 0xe0, 0xe5, 0xae, 0x3c, 0x4f, 0x1a, 0x35, + 0x58, 0xc3, 0x5a, 0x34, 0x17, 0xab, 0xb7, 0x81, 0x99, 0x72, 0x0c, 0xc9, 0x55, 0xab, 0x52, 0xd8, 0xe9, 0xcd, 0x7e, + 0x1f, 0xf2, 0xb9, 0x83, 0xd0, 0xd6, 0xc1, 0x99, 0x25, 0x28, 0x33, 0x12, 0xdb, 0x98, 0x50, 0x40, 0x32, 0xd0, 0x81, + 0xd4, 0x15, 0x88, 0x90, 0x90, 0x64, 0x92, 0x84, 0xe6, 0x64, 0x8a, 0x44, 0x7c, 0x71, 0xc2, 0x5c, 0x1f, 0xc4, 0xc9, + 0x12, 0xd9, 0xbc, 0x6f, 0x97, 0xc0, 0xfc, 0x81, 0x91, 0x59, 0x91, 0xab, 0xaa, 0xa0, 0x01, 0x12, 0x09, 0xa3, 0xd5, + 0x09, 0x43, 0xe7, 0xf5, 0xd9, 0xdf, 0x07, 0x8c, 0x2d, 0x4c, 0xe8, 0x40, 0x30, 0x0c, 0x65, 0x51, 0xa8, 0xe4, 0x4f, + 0x0a, 0x1c, 0x56, 0x68, 0x78, 0x7f, 0x16, 0x7c, 0xf1, 0xd4, 0x62, 0x61, 0x15, 0x1e, 0x09, 0xb9, 0x1f, 0x6a, 0x89, + 0xb3, 0x02, 0x92, 0x13, 0x84, 0x56, 0xf7, 0xef, 0x7f, 0x77, 0x54, 0x12, 0xe6, 0x45, 0x8b, 0xd2, 0xab, 0x23, 0x6e, + 0x73, 0xb5, 0xc0, 0xd0, 0xa4, 0xd9, 0x21, 0xdf, 0x3e, 0x55, 0x22, 0x6e, 0x14, 0x5c, 0xee, 0x42, 0x2c, 0x01, 0x69, + 0x33, 0x18, 0x7c, 0x69, 0x3d, 0xa5, 0x1f, 0x20, 0xf4, 0x8d, 0x7b, 0x76, 0xfa, 0x38, 0x46, 0x32, 0x26, 0x17, 0xd6, + 0xcf, 0xac, 0x6a, 0x35, 0x71, 0x44, 0x42, 0xce, 0x59, 0xe8, 0x50, 0xec, 0xab, 0x61, 0x39, 0x73, 0xc5, 0xd9, 0xc3, + 0xc3, 0x68, 0x05, 0x24, 0x1d, 0x69, 0xb8, 0x21, 0xc7, 0xb3, 0x0f, 0x50, 0xe7, 0x51, 0x30, 0x92, 0x4a, 0xe6, 0xbd, + 0x62, 0x38, 0x6f, 0x88, 0xb6, 0xd4, 0xb3, 0xd6, 0x20, 0x70, 0x4e, 0x16, 0x49, 0xc9, 0x9b, 0x20, 0xb5, 0xf2, 0xf2, + 0x64, 0x1e, 0x31, 0xc5, 0xe9, 0x54, 0x59, 0x61, 0x74, 0x72, 0xd1, 0x73, 0x64, 0x94, 0x5d, 0xb0, 0xa1, 0x9a, 0x4f, + 0x4b, 0x53, 0xee, 0x2b, 0xac, 0x94, 0xae, 0xb4, 0xc0, 0x74, 0x24, 0xc6, 0xea, 0x66, 0x8e, 0xea, 0x81, 0x41, 0xc4, + 0x7a, 0xf9, 0x06, 0x91, 0x87, 0x34, 0xbf, 0x70, 0xa4, 0x22, 0x6d, 0x09, 0xcf, 0x4a, 0x3e, 0x60, 0x36, 0x03, 0xd2, + 0xca, 0xfb, 0x04, 0x5c, 0xf9, 0x4d, 0x81, 0x82, 0xe4, 0x8b, 0xf3, 0x04, 0xcd, 0x20, 0x7e, 0x1d, 0x64, 0xb3, 0xb1, + 0x11, 0xe3, 0xf9, 0xd6, 0xe0, 0xd5, 0x10, 0x39, 0x58, 0x1d, 0xfd, 0xba, 0x1b, 0xb0, 0x75, 0xb8, 0x4d, 0xa7, 0x67, + 0x5f, 0x6a, 0x81, 0x16, 0x83, 0xe3, 0xa9, 0x98, 0xe2, 0xa4, 0x7a, 0x44, 0x2c, 0x53, 0x61, 0x1a, 0x13, 0x5d, 0x21, + 0x6b, 0x6c, 0x29, 0xd8, 0x7c, 0xcb, 0x7b, 0x5e, 0x64, 0x48, 0xb8, 0x6b, 0x44, 0x17, 0xc3, 0x18, 0x04, 0x2f, 0x2f, + 0xa5, 0x73, 0x5f, 0x1b, 0x25, 0x56, 0xcc, 0x13, 0x1f, 0x5e, 0x37, 0x49, 0xf2, 0x82, 0xb4, 0x66, 0xcf, 0x6a, 0x2c, + 0x7f, 0x78, 0xf3, 0x83, 0xa9, 0x4a, 0xac, 0xd9, 0xc9, 0x4f, 0x52, 0xb6, 0xef, 0x87, 0xa6, 0x41, 0xde, 0x56, 0x2c, + 0x7e, 0x69, 0xf2, 0x0d, 0xa2, 0x0b, 0x46, 0xc9, 0x4e, 0x17, 0x8b, 0x75, 0x03, 0xf7, 0xeb, 0x25, 0xe8, 0xca, 0x0c, + 0x83, 0x76, 0xef, 0x6b, 0xdd, 0x2f, 0x8a, 0x48, 0x8f, 0xb1, 0x0f, 0x19, 0x29, 0x5a, 0x89, 0x5a, 0xcb, 0xfc, 0x6c, + 0x5b, 0xeb, 0x08, 0x09, 0x33, 0xd1, 0x4b, 0x73, 0xb4, 0x43, 0x22, 0x56, 0x33, 0x13, 0xa1, 0xc1, 0xba, 0x19, 0x79, + 0x57, 0x53, 0xfe, 0xb4, 0x84, 0x0e, 0x8f, 0xb5, 0xae, 0xda, 0xdc, 0xcb, 0x68, 0x3a, 0x23, 0xae, 0xe7, 0x69, 0xea, + 0x9a, 0xd2, 0xd3, 0xa0, 0xc3, 0x9d, 0x14, 0xb1, 0xc5, 0xad, 0xff, 0xc0, 0x4c, 0x8b, 0x42, 0x42, 0x35, 0x94, 0xb9, + 0xbd, 0xae, 0x1e, 0x4b, 0xd5, 0x53, 0xb2, 0xfb, 0x9e, 0xe8, 0x6b, 0xac, 0xd2, 0xbe, 0x46, 0xb2, 0x6a, 0x85, 0xc7, + 0xc6, 0xb8, 0x0e, 0x9e, 0xf5, 0x1b, 0xdc, 0x24, 0x8a, 0x10, 0xc3, 0xb8, 0xf4, 0x0b, 0x1f, 0xe1, 0x5c, 0xe0, 0xf5, + 0x30, 0x6d, 0xdd, 0x0e, 0xa9, 0xa6, 0x20, 0x8e, 0xdd, 0x16, 0xce, 0xd9, 0xad, 0x39, 0x78, 0xe8, 0x8e, 0xa3, 0xbc, + 0x50, 0x8f, 0xf3, 0x0e, 0x85, 0x76, 0x28, 0x69, 0x78, 0x5c, 0xb7, 0xa3, 0xc9, 0x83, 0x23, 0x9a, 0xb8, 0x5d, 0x6e, + 0x7f, 0x26, 0x94, 0x79, 0x1a, 0x20, 0xa2, 0x31, 0xfc, 0xfb, 0x92, 0x3d, 0x19, 0xd3, 0x09, 0x49, 0x64, 0x43, 0x66, + 0x1b, 0x30, 0xf6, 0x90, 0x48, 0x8f, 0xbf, 0x22, 0xf7, 0x6f, 0x8d, 0x82, 0xe3, 0xa5, 0xb8, 0xa1, 0xa4, 0x3f, 0x2c, + 0xc2, 0x4c, 0x27, 0x31, 0x4d, 0x3c, 0x90, 0xc5, 0x55, 0x00, 0x2e, 0xd3, 0xae, 0xb0, 0x40, 0x96, 0x0b, 0x2c, 0x90, + 0xb2, 0xfa, 0x1c, 0x25, 0x91, 0xb8, 0x47, 0x42, 0x76, 0x3a, 0x79, 0x2f, 0x8e, 0x71, 0xc1, 0x73, 0x35, 0x39, 0xba, + 0xe0, 0xc5, 0x4c, 0x10, 0xb5, 0x3b, 0x8d, 0xf4, 0x22, 0x34, 0xef, 0xe5, 0xea, 0x3a, 0xd2, 0xa7, 0xd0, 0x82, 0x0a, + 0xf5, 0x0b, 0x69, 0xbf, 0x7f, 0x9d, 0xc8, 0x80, 0xa3, 0x41, 0x93, 0x0d, 0x3b, 0x24, 0xac, 0x90, 0xd7, 0x2e, 0xbe, + 0x10, 0x3a, 0x22, 0x33, 0x7a, 0x94, 0x61, 0x7a, 0x99, 0x8f, 0xd1, 0xce, 0x5b, 0x39, 0x9a, 0x2e, 0x1c, 0xfc, 0xe7, + 0xb0, 0xb7, 0x40, 0x87, 0xab, 0xe3, 0x22, 0xdd, 0x4f, 0xce, 0x5c, 0xfc, 0x0f, 0xa6, 0xab, 0xae, 0x7d, 0x36, 0x13, + 0x5f, 0xc9, 0x63, 0x44, 0x7d, 0xd5, 0x0b, 0xa7, 0x34, 0x1b, 0xd5, 0x4c, 0x1f, 0x45, 0xe4, 0x79, 0xa8, 0x72, 0x5b, + 0x30, 0x9e, 0xd6, 0x60, 0xf8, 0xe8, 0x28, 0xe1, 0x10, 0x34, 0xc1, 0x99, 0xb9, 0x1f, 0x51, 0x65, 0x64, 0x09, 0xe3, + 0xc6, 0x02, 0xcb, 0x9b, 0xe9, 0x3c, 0x8e, 0x4b, 0xa1, 0xe5, 0x33, 0xc6, 0xdf, 0xdf, 0xa2, 0xcf, 0x4f, 0x85, 0xcd, + 0x12, 0x17, 0x3f, 0xe8, 0xc4, 0x51, 0x2f, 0x5c, 0x69, 0xeb, 0x14, 0xab, 0x52, 0xd9, 0x4d, 0xed, 0x7c, 0x6c, 0x5b, + 0x5e, 0x4a, 0xc6, 0xa7, 0x14, 0xe5, 0x24, 0xd7, 0x14, 0x8a, 0xc1, 0xc0, 0x1b, 0x59, 0xf5, 0xe7, 0x0b, 0x98, 0xc9, + 0x0d, 0x78, 0xa6, 0xaf, 0x63, 0xbd, 0x03, 0x3c, 0xd8, 0x73, 0x0b, 0x33, 0x57, 0x90, 0xc8, 0xe3, 0xf1, 0x1c, 0x8f, + 0x75, 0xc0, 0xf9, 0x83, 0xdc, 0x3b, 0x0a, 0xf8, 0x6e, 0x00, 0x62, 0x76, 0xde, 0x08, 0xf0, 0x0b, 0xec, 0x70, 0xb6, + 0xc4, 0x12, 0x54, 0x29, 0xd4, 0x82, 0x1d, 0x19, 0x7c, 0x96, 0x60, 0x35, 0x13, 0x70, 0x96, 0x20, 0x28, 0xca, 0x62, + 0xbe, 0x20, 0x28, 0x71, 0x14, 0x4a, 0x66, 0x2e, 0x3f, 0x35, 0x9b, 0xa2, 0x28, 0x12, 0xe1, 0xa7, 0x76, 0x70, 0x9e, + 0x11, 0x2e, 0xf1, 0xb5, 0xa2, 0xca, 0x07, 0x06, 0x5f, 0x10, 0x68, 0x80, 0xfe, 0xcd, 0x54, 0x44, 0xfb, 0x73, 0xd2, + 0x28, 0x29, 0xdc, 0xb3, 0xb0, 0x18, 0x67, 0x9d, 0x59, 0xd2, 0x6f, 0xb2, 0xcc, 0x6b, 0xd1, 0xcc, 0xaf, 0x6c, 0xc8, + 0x5a, 0xe7, 0xbb, 0x9f, 0xf7, 0x03, 0xa5, 0x9d, 0xf5, 0xcc, 0x92, 0x7d, 0xb4, 0x67, 0x9a, 0x36, 0x0b, 0x87, 0x9e, + 0xc5, 0xd5, 0x0d, 0x53, 0x10, 0x07, 0x5e, 0x9e, 0x46, 0x2a, 0x03, 0x7f, 0x2a, 0x0a, 0x38, 0x52, 0x4e, 0xf1, 0x5b, + 0x4a, 0x78, 0x37, 0xbf, 0x20, 0x8e, 0xdd, 0x5d, 0xfd, 0x0a, 0x90, 0xb5, 0x85, 0xd5, 0xc1, 0x4d, 0x8e, 0x9b, 0xa8, + 0x21, 0xca, 0xc1, 0xdb, 0x40, 0xbe, 0x34, 0x4f, 0x5a, 0xe2, 0xa8, 0x97, 0x45, 0xab, 0xcf, 0xd3, 0xdc, 0x10, 0xf8, + 0xa9, 0x0b, 0xc7, 0xe3, 0x3c, 0xfa, 0xe6, 0xd0, 0x34, 0xf2, 0x63, 0xd2, 0xf6, 0x80, 0x81, 0xa4, 0x99, 0x68, 0xe3, + 0x23, 0x5b, 0x4e, 0x77, 0x3b, 0x0b, 0xe9, 0x7a, 0x3d, 0x0d, 0xa5, 0xb0, 0x58, 0xb8, 0x70, 0x34, 0x66, 0x9f, 0xd0, + 0xe9, 0xd6, 0x6c, 0x48, 0x74, 0x07, 0xc3, 0x95, 0x18, 0xb9, 0x0e, 0xe3, 0x9c, 0xd9, 0x70, 0x84, 0x95, 0xea, 0xb1, + 0x37, 0x6e, 0x1b, 0x12, 0x3c, 0xa1, 0xe2, 0xc8, 0x03, 0x8f, 0xf0, 0x59, 0x1d, 0x74, 0x78, 0x98, 0x07, 0x2e, 0xf9, + 0x06, 0x73, 0x75, 0x04, 0x03, 0xe5, 0x08, 0x42, 0x11, 0xf9, 0xfe, 0x0e, 0x73, 0xe1, 0xb1, 0x7c, 0x83, 0x99, 0x5a, + 0x79, 0xe1, 0x73, 0xbd, 0xe4, 0x76, 0xc0, 0xf3, 0xf6, 0x13, 0x2f, 0xe9, 0x1a, 0xc1, 0xe1, 0x47, 0x7e, 0xd5, 0x62, + 0xfd, 0x75, 0x1f, 0xf3, 0xe7, 0x41, 0xaa, 0x4b, 0xb8, 0x2a, 0x0c, 0x80, 0x3f, 0xba, 0x32, 0xee, 0x06, 0x0c, 0xeb, + 0x23, 0x44, 0x8d, 0xf0, 0x88, 0xfd, 0xe1, 0xa9, 0x17, 0x00, 0xca, 0x9d, 0x9b, 0x81, 0xc8, 0x42, 0x34, 0x3f, 0x2f, + 0x57, 0xdb, 0xe6, 0x65, 0x68, 0x4b, 0x4b, 0x37, 0x8f, 0x13, 0x49, 0xd8, 0x4c, 0x9c, 0x5a, 0xa8, 0x5e, 0x11, 0x31, + 0x45, 0xcc, 0x02, 0xad, 0x97, 0xf1, 0x7b, 0x7c, 0x67, 0x08, 0xa3, 0x36, 0x6c, 0x84, 0xd7, 0xed, 0x68, 0x6d, 0xf0, + 0x7e, 0xbf, 0xd6, 0x46, 0x21, 0xd8, 0xb7, 0xf4, 0x0b, 0x14, 0x69, 0xd8, 0xd2, 0x8e, 0xff, 0x79, 0xc0, 0x17, 0xfd, + 0x43, 0x08, 0x9b, 0xc4, 0x06, 0x05, 0x85, 0x97, 0xda, 0x64, 0x6f, 0x03, 0x25, 0x4c, 0x62, 0xad, 0xd6, 0x13, 0xf0, + 0xa2, 0x0d, 0x20, 0x15, 0xba, 0x67, 0xcc, 0xaf, 0xc8, 0xe4, 0xf9, 0x13, 0xd2, 0xb2, 0x85, 0x71, 0xca, 0x27, 0xd1, + 0x8e, 0x04, 0x3b, 0x3f, 0x45, 0x91, 0xbc, 0xe2, 0xbb, 0x44, 0x92, 0xaf, 0x4f, 0xbb, 0xf9, 0xcb, 0xdd, 0x83, 0x26, + 0x85, 0x40, 0x07, 0x8f, 0xee, 0x08, 0x19, 0x6a, 0xb5, 0x8c, 0xea, 0xf0, 0x18, 0x8b, 0x4c, 0xcf, 0x1f, 0xce, 0xea, + 0x8b, 0x0c, 0x03, 0x27, 0x96, 0xc0, 0x28, 0x95, 0x5d, 0x6e, 0xd9, 0xd8, 0x9f, 0xf4, 0xde, 0x78, 0x89, 0x52, 0x75, + 0x3c, 0xc7, 0xad, 0x1a, 0xba, 0x43, 0x57, 0xc4, 0x1b, 0x3e, 0xf0, 0xd8, 0xbf, 0xba, 0x31, 0xa8, 0x63, 0x4d, 0x9b, + 0x08, 0x5e, 0x07, 0xfd, 0xcc, 0x14, 0x9c, 0x6c, 0x7c, 0x4a, 0x74, 0x0a, 0x83, 0x04, 0x0a, 0x66, 0x28, 0xf6, 0x99, + 0x96, 0x8f, 0x4b, 0xe9, 0xce, 0x5a, 0x2a, 0xea, 0xd8, 0x38, 0x33, 0xca, 0xfa, 0xe5, 0x72, 0x69, 0xe3, 0x6d, 0x04, + 0xf4, 0x92, 0x7b, 0x79, 0x7f, 0xc5, 0x49, 0xe3, 0x18, 0x91, 0x2c, 0x38, 0x1e, 0x1e, 0xc7, 0x1c, 0xf2, 0xc6, 0xad, + 0x05, 0x1d, 0x26, 0xb4, 0x06, 0x36, 0x3b, 0x67, 0x39, 0xe5, 0x6b, 0x11, 0xce, 0xb2, 0xcb, 0x6f, 0x36, 0x40, 0x04, + 0x84, 0x9e, 0x16, 0x91, 0x04, 0x3e, 0x2b, 0x90, 0x31, 0x47, 0x4e, 0x72, 0x64, 0x79, 0xad, 0xe4, 0x11, 0x48, 0x26, + 0x46, 0x8a, 0xb7, 0xe1, 0xa6, 0x9f, 0xa2, 0x4b, 0x76, 0xb0, 0x51, 0x37, 0x08, 0xa2, 0x04, 0x3b, 0xc0, 0x5f, 0xf8, + 0xf3, 0xa1, 0xef, 0xfc, 0xe9, 0xb7, 0x5b, 0x87, 0xff, 0x27, 0xb8, 0xb4, 0x8f, 0x18, 0x3b, 0xfd, 0x25, 0x56, 0x7d, + 0xf5, 0x7f, 0x73, 0xd7, 0xd0, 0x3a, 0xf0, 0xe1, 0x03, 0x17, 0x1e, 0x7f, 0x1b, 0x96, 0xd0, 0x6a, 0x6b, 0x77, 0x58, + 0x52, 0x88, 0x13, 0xe5, 0xc4, 0x8e, 0xea, 0x3d, 0x8a, 0xf6, 0xc5, 0xd3, 0xfb, 0x23, 0x01, 0xac, 0xbf, 0x7f, 0xe3, + 0x51, 0x69, 0xa4, 0xbb, 0x5f, 0x82, 0x4c, 0x6c, 0xad, 0x4d, 0x90, 0xab, 0xd4, 0x7e, 0x7e, 0xee, 0x5b, 0xeb, 0xa8, + 0xa5, 0xab, 0x6c, 0x70, 0x7f, 0xd1, 0x55, 0x7b, 0xb0, 0xc9, 0xf2, 0x61, 0xbb, 0xb9, 0xb5, 0x4f, 0x2b, 0x57, 0x19, + 0xe1, 0x43, 0x01, 0x02, 0xec, 0x54, 0x99, 0x9c, 0x3c, 0xe3, 0xb7, 0x52, 0xf0, 0x8e, 0xa5, 0x9e, 0xf6, 0x37, 0x9b, + 0xe0, 0xef, 0x0d, 0x6b, 0xbb, 0xab, 0x47, 0xeb, 0x03, 0x08, 0xca, 0xa5, 0xd7, 0x50, 0xc1, 0x21, 0xc4, 0x4b, 0x0a, + 0x12, 0x72, 0x18, 0xce, 0x5c, 0x74, 0x92, 0x43, 0x4c, 0x1b, 0x31, 0xac, 0xab, 0xb4, 0x55, 0x71, 0xe2, 0xb5, 0x3c, + 0xb0, 0x5b, 0x18, 0xb7, 0x60, 0x61, 0x58, 0x64, 0x30, 0xf2, 0x0c, 0xec, 0x70, 0x2e, 0x1e, 0x7a, 0x35, 0x0b, 0x5e, + 0x90, 0x26, 0x5c, 0x96, 0xfa, 0x7d, 0xb0, 0x38, 0x66, 0xf5, 0x55, 0x0b, 0x7e, 0xcd, 0xc1, 0xa9, 0x29, 0x6a, 0x43, + 0x7e, 0xb5, 0x6f, 0x66, 0x84, 0xcb, 0x0b, 0xb9, 0xc7, 0x42, 0x10, 0x2a, 0xdb, 0xb8, 0x65, 0xd2, 0xc1, 0xc9, 0x50, + 0xdf, 0xa7, 0x0d, 0x61, 0x84, 0x17, 0x04, 0x32, 0x4d, 0x51, 0xca, 0xf0, 0x5b, 0xb8, 0xaf, 0x1d, 0xca, 0x06, 0xb9, + 0x99, 0x0e, 0x23, 0xe1, 0x8a, 0xec, 0x38, 0xf0, 0x2c, 0xcd, 0xa7, 0x6a, 0x7f, 0x6c, 0x5d, 0x07, 0xfd, 0xce, 0x25, + 0x44, 0xed, 0x91, 0x9a, 0xf1, 0x31, 0x9b, 0x76, 0x0a, 0xfe, 0xe6, 0x73, 0x29, 0x36, 0x10, 0x1f, 0x69, 0xb9, 0x4b, + 0xa9, 0x89, 0x63, 0xb9, 0xb4, 0xca, 0x38, 0xd4, 0xd0, 0x29, 0x0b, 0x6d, 0x23, 0x97, 0x19, 0x44, 0xda, 0x2e, 0x4e, + 0x49, 0x95, 0x49, 0x1e, 0x8b, 0x13, 0x62, 0xc8, 0x42, 0xbf, 0xc0, 0xda, 0xfe, 0x72, 0xf3, 0x4b, 0x32, 0x54, 0x21, + 0x76, 0xee, 0x10, 0xfa, 0xb0, 0xc0, 0xe6, 0xa5, 0xb4, 0x14, 0x46, 0x15, 0xa6, 0xae, 0xda, 0xea, 0xb9, 0xa5, 0x6d, + 0x48, 0x32, 0x90, 0xcc, 0xb2, 0x84, 0x8f, 0xb2, 0x81, 0x41, 0x8e, 0xff, 0x6d, 0x00, 0xd9, 0xf6, 0x20, 0xd8, 0xde, + 0x32, 0x65, 0xa9, 0xef, 0x2d, 0x7e, 0x9a, 0x84, 0x4f, 0x4c, 0x08, 0x5c, 0x06, 0x5c, 0x75, 0xfe, 0x6c, 0x76, 0x8d, + 0xff, 0x10, 0x06, 0xfe, 0x1b, 0x6e, 0xf4, 0x0d, 0xbe, 0x4a, 0x3f, 0x77, 0xc9, 0xfd, 0xc8, 0xfb, 0x91, 0x3c, 0xdb, + 0x96, 0xc6, 0x4f, 0x5c, 0xac, 0x78, 0x53, 0x7e, 0x0a, 0x7f, 0x33, 0x9a, 0xef, 0xcb, 0xfa, 0xce, 0xb6, 0xd3, 0x47, + 0x60, 0x33, 0xd8, 0x23, 0x3b, 0x74, 0xd7, 0x47, 0xa3, 0x54, 0xcc, 0x1c, 0xf1, 0xed, 0xc3, 0x9f, 0xdb, 0xda, 0x2f, + 0xce, 0x86, 0xe8, 0x3a, 0x30, 0x85, 0xd3, 0xd7, 0x01, 0xca, 0x0e, 0x59, 0x62, 0xda, 0x81, 0x4a, 0x14, 0x1d, 0x74, + 0x66, 0x5d, 0x0a, 0xb0, 0x7c, 0xe3, 0xe8, 0x67, 0x0d, 0xae, 0x95, 0xa4, 0xc3, 0x50, 0x6b, 0x11, 0x9f, 0x4d, 0xa7, + 0xf7, 0xa3, 0x58, 0x51, 0xc0, 0x02, 0xe6, 0xeb, 0x04, 0x76, 0x91, 0xde, 0xbc, 0x3c, 0x92, 0xe0, 0x9c, 0x70, 0x38, + 0x72, 0x81, 0x00, 0x2a, 0xb4, 0x5d, 0x48, 0x13, 0x7e, 0x9d, 0x3b, 0xba, 0xb6, 0x9f, 0x90, 0x5a, 0xb2, 0x1c, 0xe8, + 0xa5, 0xfa, 0xbf, 0xee, 0xee, 0x7e, 0x51, 0x1e, 0x2f, 0xec, 0xed, 0x89, 0x70, 0xcb, 0xb3, 0xaf, 0xac, 0xb0, 0xea, + 0x15, 0xf7, 0xfb, 0x24, 0x13, 0xad, 0xdd, 0x5c, 0x1f, 0xac, 0x4e, 0xd4, 0x2a, 0x78, 0xe8, 0xab, 0xf4, 0x3f, 0x33, + 0xbd, 0xdc, 0x73, 0x53, 0x1e, 0x4a, 0x84, 0x03, 0x5f, 0x34, 0x34, 0x3e, 0x43, 0x35, 0x44, 0xf1, 0x58, 0x0d, 0x38, + 0x8c, 0x49, 0x73, 0xdc, 0x27, 0x58, 0xc9, 0xd4, 0x89, 0x51, 0xb5, 0x11, 0x05, 0x24, 0x98, 0x82, 0xce, 0xa5, 0x2d, + 0xa1, 0x40, 0x05, 0xcd, 0xa2, 0x84, 0x46, 0xdf, 0xf3, 0x61, 0x45, 0x1a, 0x1d, 0xdc, 0x13, 0xc8, 0x08, 0x82, 0xca, + 0xb2, 0xf9, 0xcd, 0x76, 0x35, 0x8a, 0xc2, 0xa9, 0xef, 0x13, 0x0a, 0xca, 0x7f, 0x9c, 0xf9, 0xd2, 0x66, 0xc7, 0xdd, + 0xa3, 0x81, 0x50, 0x54, 0xeb, 0x12, 0x2f, 0x5b, 0x6d, 0xe4, 0x26, 0x37, 0x45, 0xa4, 0x09, 0xc4, 0x1e, 0xfe, 0x04, + 0x4d, 0x52, 0xc4, 0x74, 0x11, 0x37, 0x97, 0xe6, 0xe2, 0xe0, 0x4a, 0xe9, 0xea, 0x81, 0xdb, 0xd0, 0xc8, 0xab, 0x89, + 0x5e, 0xed, 0xe2, 0x0f, 0x02, 0xd1, 0x09, 0x4b, 0x26, 0xf2, 0x8a, 0x81, 0x48, 0x82, 0x81, 0x02, 0x45, 0xdb, 0x82, + 0x29, 0x0a, 0xbd, 0x6e, 0xeb, 0xc5, 0x71, 0x7e, 0x21, 0x53, 0x11, 0x64, 0x2a, 0x6d, 0x6e, 0x80, 0xab, 0x9f, 0xb6, + 0xec, 0x07, 0x1a, 0xff, 0x93, 0x9c, 0x70, 0xd3, 0x43, 0xcf, 0x42, 0x7c, 0xea, 0x3e, 0xb6, 0xde, 0x55, 0xa0, 0x30, + 0xbd, 0x78, 0x11, 0x2d, 0x90, 0xa2, 0x6e, 0xcc, 0x89, 0x25, 0x9f, 0xab, 0x16, 0xdf, 0x57, 0xe5, 0x97, 0x54, 0x50, + 0x43, 0x40, 0x98, 0x09, 0x20, 0x2b, 0xb1, 0x92, 0xcd, 0x2b, 0x72, 0xee, 0x4b, 0xb6, 0x61, 0x27, 0x78, 0x53, 0x6b, + 0x6e, 0x77, 0x46, 0x8c, 0xe0, 0xfd, 0x10, 0x01, 0x21, 0xaa, 0x15, 0x99, 0x25, 0xbf, 0x2a, 0x45, 0x9b, 0x01, 0x0f, + 0xa1, 0x20, 0x2c, 0xce, 0x5e, 0x21, 0xf3, 0x58, 0x2c, 0xf4, 0x03, 0x72, 0x8d, 0xb8, 0x87, 0x43, 0x04, 0x60, 0xd8, + 0xef, 0xee, 0x11, 0x31, 0xd2, 0xe1, 0xc2, 0x44, 0x0c, 0x03, 0x48, 0xd8, 0x06, 0x2e, 0xb3, 0xf3, 0xf1, 0xbe, 0x7b, + 0xff, 0xc7, 0x18, 0xce, 0x0d, 0xd6, 0x4a, 0xb8, 0x75, 0x74, 0xd5, 0x09, 0xf2, 0xf2, 0x3e, 0xe2, 0xd3, 0xdc, 0x8e, + 0xa8, 0x97, 0x03, 0x51, 0x69, 0x35, 0x9e, 0x6d, 0x84, 0x87, 0x65, 0x0a, 0x8f, 0x7d, 0x2e, 0x28, 0x9d, 0x79, 0x09, + 0x2e, 0x01, 0xd5, 0x07, 0x19, 0x5f, 0x79, 0x23, 0xd1, 0xab, 0xcc, 0xc6, 0x9f, 0xc7, 0xf3, 0x3d, 0x6c, 0xd3, 0x45, + 0x1b, 0xd7, 0xd3, 0xe9, 0x1d, 0x4a, 0x32, 0xc1, 0xb4, 0xbb, 0x49, 0x36, 0xec, 0xfa, 0x89, 0xc9, 0x37, 0x2a, 0xe2, + 0x06, 0xa4, 0xf6, 0xdd, 0x38, 0xd0, 0x54, 0xb0, 0xde, 0x7c, 0x4a, 0xa2, 0x81, 0xe9, 0x11, 0xc9, 0xdc, 0xac, 0xd7, + 0xf6, 0x66, 0x0d, 0x01, 0x20, 0x05, 0x8b, 0x96, 0xe0, 0xbd, 0x2b, 0x67, 0x4d, 0x93, 0x12, 0x5b, 0x00, 0x31, 0xdd, + 0x40, 0xe2, 0x38, 0xa2, 0x5a, 0xe3, 0xee, 0x9b, 0xa5, 0x87, 0xf7, 0x3b, 0x62, 0xf7, 0xee, 0x48, 0x6a, 0x7a, 0xe5, + 0x84, 0xed, 0xde, 0x91, 0x53, 0xa3, 0x1c, 0x1f, 0xd5, 0xb3, 0x1b, 0xb6, 0xb4, 0x8e, 0xe5, 0xc9, 0x8c, 0x1e, 0x05, + 0xbe, 0x64, 0xde, 0xbb, 0x7a, 0x50, 0x92, 0x70, 0xf6, 0x0b, 0x01, 0xe2, 0x68, 0xfd, 0x4b, 0xad, 0xd2, 0xa5, 0xe6, + 0x94, 0xfb, 0xbd, 0x0d, 0xfb, 0xaa, 0xb0, 0x72, 0x49, 0x2d, 0x7a, 0x39, 0x99, 0xaa, 0x9e, 0xca, 0xd7, 0x5e, 0xcb, + 0x35, 0xce, 0x86, 0x1a, 0xda, 0x43, 0xef, 0x35, 0x4d, 0xd5, 0xb2, 0x15, 0xce, 0xa2, 0x98, 0xb6, 0x77, 0xd1, 0x9d, + 0x42, 0x63, 0x1f, 0x39, 0x91, 0x38, 0x61, 0x6e, 0xfd, 0x55, 0x1e, 0x89, 0x1d, 0x1e, 0xc1, 0x16, 0xbe, 0x91, 0x74, + 0x48, 0xca, 0x41, 0xc7, 0x09, 0xb8, 0xad, 0x0c, 0x4f, 0x33, 0x10, 0xb1, 0x5a, 0x44, 0x9a, 0xcc, 0x00, 0xc6, 0x31, + 0x45, 0x5c, 0xab, 0x60, 0xa8, 0x41, 0x72, 0xae, 0x06, 0xc1, 0x4c, 0xc7, 0x82, 0x9d, 0xf9, 0x28, 0x3f, 0x41, 0x5b, + 0x1b, 0xb3, 0xb0, 0xd0, 0xb3, 0x31, 0x35, 0xbb, 0x29, 0x01, 0xac, 0x11, 0x74, 0x7b, 0x49, 0x77, 0xcf, 0x0d, 0xc2, + 0xfb, 0xe5, 0xc8, 0xe5, 0x8c, 0xc1, 0x7a, 0xec, 0xa3, 0x6c, 0x71, 0xea, 0xc1, 0x83, 0x00, 0x33, 0x82, 0xc3, 0x56, + 0xb9, 0x81, 0xf6, 0x6c, 0xe8, 0x3f, 0xf0, 0x4d, 0x34, 0xfb, 0xa2, 0xc6, 0x82, 0x83, 0x33, 0xeb, 0xb3, 0x78, 0x57, + 0xc5, 0x04, 0x59, 0xc4, 0x90, 0x24, 0x67, 0x4d, 0x31, 0x37, 0xeb, 0x62, 0x3d, 0x83, 0x40, 0xb0, 0x7c, 0x85, 0xc9, + 0x00, 0xe1, 0x60, 0x76, 0xa3, 0x21, 0x26, 0xd6, 0x93, 0x77, 0xfd, 0x08, 0x80, 0xc0, 0x00, 0xdc, 0xc5, 0xb9, 0xd0, + 0x26, 0x3a, 0x80, 0x22, 0xbf, 0x07, 0x07, 0x40, 0x12, 0x98, 0xa1, 0x48, 0x50, 0xd0, 0xab, 0xd6, 0xbe, 0xe6, 0xc5, + 0x18, 0x0a, 0x2d, 0x24, 0x04, 0xc1, 0x56, 0xee, 0x92, 0x35, 0x2a, 0xb3, 0x75, 0xd0, 0x90, 0xf0, 0xed, 0x59, 0x51, + 0x49, 0x8a, 0x90, 0x5f, 0xe7, 0x81, 0xf4, 0x4f, 0x07, 0x34, 0xf6, 0x1c, 0x25, 0xa7, 0x9b, 0x4c, 0xcc, 0x1a, 0xe2, + 0xe5, 0x69, 0x3d, 0x5b, 0x84, 0x62, 0x0f, 0xdd, 0xa0, 0xcc, 0xc9, 0xd8, 0x89, 0x2f, 0xa8, 0x11, 0x49, 0xfd, 0xe3, + 0x14, 0xd5, 0x83, 0x7a, 0x14, 0x23, 0x93, 0x71, 0x3d, 0xa1, 0x96, 0xaf, 0xb5, 0x1b, 0x81, 0x36, 0x29, 0xcf, 0xb8, + 0xc9, 0xd8, 0x52, 0xbf, 0x54, 0xa8, 0x65, 0xa7, 0xa6, 0x14, 0xec, 0xe4, 0x3c, 0x2f, 0x38, 0x7a, 0x2a, 0x76, 0xc2, + 0x38, 0x08, 0xf6, 0xa7, 0xd3, 0x6e, 0x8d, 0xf7, 0x7c, 0x82, 0x78, 0xbc, 0xea, 0xdc, 0x3e, 0x64, 0x6a, 0xd5, 0xd4, + 0x14, 0x68, 0xc6, 0xd3, 0xf4, 0xfe, 0x3f, 0x80, 0x3e, 0x0f, 0xc1, 0x9e, 0xe9, 0xa3, 0x10, 0xb7, 0x83, 0x18, 0x7f, + 0xd0, 0xc2, 0x4f, 0xf8, 0x1a, 0x25, 0x5c, 0xff, 0x2d, 0x09, 0xd0, 0xf1, 0x83, 0x56, 0x82, 0x2d, 0x49, 0x9c, 0xce, + 0x45, 0xaa, 0x3b, 0xc7, 0x0c, 0xab, 0x20, 0x17, 0x44, 0x8e, 0xe7, 0x3a, 0x8d, 0xca, 0x42, 0x96, 0x22, 0xe1, 0xc6, + 0x2f, 0x7e, 0xcd, 0x96, 0x0a, 0x3f, 0x06, 0x0e, 0x02, 0x51, 0x01, 0x24, 0xec, 0xa7, 0x97, 0xda, 0x73, 0x66, 0xe7, + 0x01, 0x43, 0x16, 0x48, 0x4b, 0x1d, 0xfb, 0x0a, 0x9d, 0x04, 0x00, 0x44, 0xc7, 0xc4, 0x18, 0xc8, 0xab, 0x1d, 0x55, + 0x7f, 0x80, 0x43, 0xef, 0xa4, 0x63, 0x6d, 0xee, 0x26, 0x10, 0x45, 0x08, 0x08, 0x90, 0x58, 0x1b, 0x0a, 0x22, 0x6b, + 0x39, 0x88, 0xa0, 0x4a, 0xec, 0x04, 0x8e, 0xd2, 0x66, 0xc1, 0x8d, 0x78, 0x44, 0x1a, 0x01, 0xf4, 0x0a, 0x2e, 0xc4, + 0x8c, 0xc0, 0x28, 0xcb, 0x48, 0xe3, 0x17, 0x58, 0x68, 0x5c, 0x04, 0xc1, 0xe7, 0x94, 0xb5, 0xde, 0x83, 0x78, 0x3e, + 0xb7, 0x8a, 0xe6, 0x63, 0x42, 0x88, 0x35, 0x00, 0x6b, 0x28, 0xf3, 0xdf, 0xb2, 0x18, 0x30, 0x1a, 0x28, 0xd9, 0xde, + 0xe3, 0xcc, 0x54, 0x2f, 0x2d, 0x57, 0x55, 0x98, 0x32, 0x8f, 0xc8, 0xa5, 0xf3, 0xae, 0x3f, 0x85, 0xf5, 0xa2, 0x76, + 0x41, 0xd3, 0x84, 0xc7, 0xea, 0xa5, 0x7a, 0xd6, 0xc8, 0x0d, 0xc5, 0x7f, 0x52, 0x9a, 0x1b, 0xe3, 0xa8, 0xfc, 0x62, + 0x5a, 0xf5, 0xc9, 0xe8, 0xb0, 0xde, 0x45, 0x76, 0xa7, 0xa2, 0x02, 0xe0, 0xb4, 0x5b, 0x61, 0x9c, 0xd3, 0x2b, 0x7f, + 0xb5, 0xc3, 0x47, 0xab, 0xcc, 0xdc, 0xa2, 0x2e, 0xb3, 0x86, 0x82, 0xf2, 0xd1, 0x54, 0x7e, 0x87, 0xab, 0xbb, 0x3c, + 0x61, 0xf4, 0xa9, 0x2c, 0x8a, 0x53, 0x77, 0x0f, 0x47, 0xfe, 0x75, 0xd8, 0x12, 0x62, 0xa7, 0xba, 0xf5, 0x17, 0x17, + 0x1e, 0x4c, 0x7d, 0xe2, 0x15, 0x6e, 0xdc, 0x42, 0x9f, 0xb1, 0xd7, 0x8c, 0xa1, 0x13, 0x02, 0xc0, 0x3b, 0x4b, 0x14, + 0x65, 0x41, 0xf8, 0xf7, 0x47, 0x9b, 0xa7, 0x45, 0x34, 0x4f, 0xfa, 0x36, 0xde, 0x4e, 0x40, 0x53, 0x60, 0x83, 0x75, + 0x20, 0x30, 0x1f, 0xd0, 0xbf, 0x19, 0x6c, 0xa3, 0xc6, 0xf7, 0xad, 0x2e, 0x8a, 0x10, 0x5b, 0x18, 0x7c, 0x69, 0xfd, + 0xa5, 0x20, 0xb2, 0x3e, 0xa9, 0x01, 0x6d, 0x3f, 0x4d, 0xd6, 0x5d, 0x61, 0x28, 0x79, 0xda, 0xad, 0x87, 0x11, 0x3b, + 0x68, 0x96, 0xf4, 0x86, 0xc9, 0x1f, 0xd2, 0x41, 0xe1, 0x26, 0x26, 0x8b, 0x44, 0xf9, 0xbb, 0x1f, 0x53, 0x92, 0xdc, + 0xf5, 0x0e, 0x67, 0x29, 0xea, 0x2a, 0x4c, 0xfd, 0x59, 0x79, 0xbf, 0x52, 0xff, 0x96, 0xde, 0xd8, 0x42, 0xc3, 0x91, + 0xb5, 0x20, 0x91, 0xd3, 0x30, 0xe4, 0x5a, 0x1d, 0xce, 0x9c, 0xb8, 0xb5, 0xce, 0x76, 0x84, 0x04, 0x1e, 0x96, 0x9c, + 0x25, 0x4c, 0xd5, 0x9b, 0x5a, 0x10, 0x1c, 0x26, 0x82, 0xc2, 0x74, 0x51, 0x9c, 0x22, 0x61, 0xf1, 0x66, 0x87, 0x16, + 0xa7, 0xcb, 0x60, 0xe7, 0xab, 0xfd, 0x44, 0x85, 0x67, 0x6c, 0x16, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x78, 0x31, 0xc0, + 0xee, 0x9f, 0xf0, 0xb1, 0x74, 0x12, 0xb6, 0x1e, 0x74, 0x4d, 0x6a, 0xb9, 0x54, 0x6a, 0x54, 0x5b, 0xc6, 0x35, 0xd7, + 0x50, 0x71, 0xed, 0xf0, 0xd0, 0x76, 0xf8, 0xee, 0x83, 0xf7, 0x45, 0xe2, 0x19, 0x4c, 0xe5, 0x91, 0x43, 0x10, 0x2d, + 0x6e, 0x59, 0xb7, 0x3e, 0x0c, 0x35, 0x97, 0xa7, 0xb0, 0x8f, 0x86, 0x72, 0xba, 0x88, 0x97, 0x24, 0xdf, 0x41, 0x1d, + 0x48, 0x0f, 0x1d, 0x26, 0x7a, 0x7b, 0x5f, 0x35, 0xeb, 0x0e, 0x34, 0xdf, 0xf4, 0x88, 0x40, 0x9b, 0xbb, 0x6a, 0x31, + 0xaf, 0x98, 0xba, 0x44, 0xb7, 0xa4, 0x96, 0x20, 0xee, 0xba, 0x3c, 0x6e, 0x2d, 0x5f, 0x02, 0x29, 0xa5, 0x84, 0x43, + 0xcb, 0xa5, 0xe6, 0xae, 0xf7, 0x1d, 0x87, 0x84, 0xad, 0xd0, 0x92, 0x75, 0xeb, 0x70, 0x1b, 0x6b, 0xfd, 0x29, 0x30, + 0xa9, 0x7f, 0x69, 0x45, 0x38, 0x78, 0x75, 0xc1, 0xba, 0x2d, 0x3e, 0x78, 0x61, 0x5d, 0x83, 0xae, 0x3d, 0xac, 0x44, + 0x87, 0x1d, 0x56, 0xa1, 0xd5, 0x66, 0x2d, 0x71, 0xb5, 0x12, 0xe3, 0x1b, 0xfa, 0xc3, 0x05, 0x27, 0x96, 0x9d, 0x65, + 0x48, 0xe3, 0x91, 0x93, 0xde, 0x8a, 0x3c, 0x55, 0x64, 0xbf, 0x62, 0x46, 0xc5, 0x4f, 0xd7, 0x91, 0xd6, 0x0b, 0x38, + 0x23, 0x94, 0xbd, 0xfc, 0x80, 0x8d, 0x63, 0x0e, 0xb6, 0x65, 0xd6, 0xde, 0xbb, 0x90, 0x56, 0x62, 0x87, 0x08, 0x5e, + 0x71, 0x17, 0xc3, 0x03, 0xcd, 0x0a, 0xc8, 0x98, 0x82, 0x98, 0x50, 0xf0, 0xf7, 0xba, 0x22, 0x64, 0xec, 0xf0, 0xa4, + 0x73, 0x6c, 0xd9, 0xf1, 0x09, 0x0a, 0x70, 0x64, 0x19, 0x18, 0x8f, 0x51, 0xa5, 0xa2, 0x3d, 0x9d, 0xe1, 0x18, 0xd5, + 0x2c, 0xad, 0x98, 0x5f, 0xc5, 0x02, 0x59, 0x01, 0xbb, 0x71, 0xd6, 0xb2, 0xd7, 0x16, 0xb9, 0x44, 0xf1, 0x86, 0xec, + 0x4e, 0x15, 0x99, 0x85, 0xb1, 0x4e, 0x95, 0x2c, 0xb0, 0xf4, 0xb8, 0x26, 0x94, 0xf1, 0x3f, 0x4d, 0x09, 0xca, 0xb7, + 0xfb, 0x9a, 0x4e, 0x2a, 0x34, 0x0a, 0xd7, 0x64, 0x7d, 0x9a, 0x5f, 0xd1, 0x13, 0xb9, 0xc0, 0xba, 0x24, 0x09, 0xe3, + 0x06, 0x31, 0xaa, 0xda, 0x84, 0x80, 0x6e, 0x08, 0xc5, 0x9b, 0x82, 0xd0, 0x94, 0x21, 0xb4, 0x9c, 0xe4, 0xa8, 0x1e, + 0x70, 0x96, 0xc8, 0xcd, 0xc1, 0x6b, 0x04, 0x57, 0xd1, 0x0e, 0x52, 0x54, 0x61, 0xb8, 0x8b, 0x6a, 0x90, 0xe6, 0xda, + 0x23, 0xa5, 0xe0, 0xaf, 0x09, 0xd0, 0x01, 0x08, 0xc3, 0xca, 0xdf, 0xdc, 0xa8, 0xe0, 0x15, 0xca, 0x4a, 0xe9, 0x54, + 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x46, 0x3a, 0xe1, 0x07, 0xaf, 0x11, 0xe7, 0x82, 0xa0, 0xb6, 0xab, 0xc5, 0x6a, + 0x30, 0x4c, 0xea, 0xa4, 0x2b, 0x40, 0x3e, 0x6a, 0x1a, 0x4c, 0x68, 0xb7, 0x94, 0xe8, 0x45, 0xd8, 0x2b, 0xb0, 0x9c, + 0x76, 0xb3, 0x5d, 0x03, 0x88, 0xd5, 0x5a, 0xd8, 0x41, 0x06, 0xc6, 0x32, 0xfe, 0x08, 0xc8, 0x03, 0x9f, 0x3e, 0x2f, + 0xad, 0x78, 0x64, 0xbd, 0x72, 0xf8, 0xe1, 0xe3, 0xaf, 0x29, 0x18, 0x2c, 0x15, 0x0d, 0x39, 0xbd, 0xd7, 0xe7, 0xf4, + 0x9d, 0x6c, 0x30, 0xd6, 0xa2, 0x73, 0x10, 0xf9, 0x2e, 0xb4, 0x23, 0xdd, 0x95, 0x75, 0x99, 0x91, 0xed, 0xeb, 0x81, + 0x2c, 0xf4, 0x5c, 0x5f, 0x8a, 0x20, 0xd5, 0x82, 0xc2, 0xdf, 0x01, 0x8a, 0x4b, 0x43, 0x28, 0x0d, 0xe5, 0xa0, 0x8c, + 0x14, 0x8e, 0x32, 0x19, 0xee, 0x34, 0x90, 0x02, 0x32, 0x22, 0x10, 0xcc, 0x99, 0x65, 0xed, 0x2d, 0x16, 0xd8, 0x92, + 0x9d, 0xa9, 0x5b, 0xb5, 0x6b, 0x4c, 0x98, 0x97, 0x39, 0x34, 0x7a, 0xe0, 0xd4, 0x96, 0xd3, 0xa3, 0x68, 0xa9, 0x9e, + 0x4e, 0x86, 0xa2, 0x99, 0x95, 0xa4, 0xb3, 0x97, 0xcf, 0xab, 0x86, 0x56, 0x92, 0x7e, 0x67, 0xa1, 0x06, 0xa4, 0x38, + 0x81, 0x3f, 0xbe, 0x08, 0x21, 0x5f, 0x72, 0x1f, 0xee, 0xe9, 0x2f, 0x3b, 0x0b, 0x4e, 0x2f, 0x51, 0x83, 0x9a, 0xbf, + 0x2c, 0x9c, 0xe9, 0x8d, 0x29, 0x1d, 0x94, 0x38, 0x16, 0x84, 0x3d, 0xbc, 0x97, 0xbe, 0xa8, 0x46, 0xdb, 0x45, 0x45, + 0xc1, 0x74, 0x00, 0xa8, 0x68, 0x1a, 0x0e, 0x1d, 0xd7, 0x9a, 0xa4, 0xac, 0xa4, 0xe2, 0xda, 0xcd, 0x15, 0x9f, 0x3e, + 0x76, 0x8c, 0xd4, 0xba, 0x03, 0x93, 0x78, 0x00, 0xcb, 0x3f, 0x07, 0xde, 0x8f, 0x09, 0x20, 0x5c, 0x4a, 0x79, 0x7e, + 0x71, 0x36, 0xe8, 0xf1, 0xdb, 0xad, 0xb8, 0x17, 0xde, 0xab, 0x8e, 0x31, 0x22, 0x66, 0x0b, 0x21, 0x79, 0xc8, 0x96, + 0x48, 0x6c, 0x36, 0x37, 0x4e, 0xba, 0xdb, 0x1c, 0x75, 0x78, 0x7f, 0xf0, 0x7a, 0xc9, 0x3b, 0x76, 0xa7, 0x69, 0xf0, + 0x41, 0xab, 0x53, 0x23, 0xad, 0xe9, 0x3f, 0xf8, 0xb7, 0x72, 0x91, 0x4e, 0xea, 0x1a, 0x90, 0xe8, 0x7c, 0x09, 0x09, + 0xf6, 0x07, 0x49, 0x91, 0x15, 0x5d, 0x2a, 0x65, 0x1b, 0x15, 0xeb, 0x97, 0x66, 0x39, 0x0b, 0xd7, 0x9b, 0x92, 0x7e, + 0xd9, 0xa5, 0x9b, 0x9c, 0x81, 0x75, 0xc1, 0xaa, 0xec, 0x39, 0xc7, 0xe2, 0x19, 0x32, 0xb1, 0xb0, 0xd7, 0x25, 0xca, + 0x52, 0x17, 0x36, 0x90, 0x64, 0xc7, 0xf0, 0x96, 0xf1, 0xe8, 0x4f, 0x9b, 0xc3, 0xbb, 0x9f, 0xf6, 0xed, 0x83, 0xfc, + 0x79, 0x1d, 0xed, 0x0c, 0x0a, 0x71, 0x29, 0xe9, 0xc2, 0xc3, 0x45, 0x0d, 0x2e, 0x09, 0x2d, 0xbc, 0x2d, 0x21, 0x2e, + 0x1e, 0xc3, 0x79, 0xfb, 0x0e, 0x41, 0xad, 0xac, 0xd8, 0xde, 0x71, 0xc4, 0x42, 0x3a, 0xeb, 0x95, 0x00, 0xfa, 0x2d, + 0x95, 0xb5, 0xb8, 0x23, 0xa7, 0x05, 0x94, 0x44, 0xca, 0x2e, 0xd1, 0xd3, 0xd1, 0xa9, 0xad, 0x3d, 0x9b, 0x0f, 0x6b, + 0x4b, 0xd1, 0x36, 0x12, 0x55, 0x9c, 0x43, 0x1c, 0xa3, 0x61, 0x68, 0x73, 0x6d, 0x6d, 0x8b, 0x3a, 0xcc, 0x50, 0x1d, + 0x6b, 0x08, 0x9b, 0x6e, 0x29, 0xe6, 0x5f, 0xaa, 0x1d, 0x97, 0x6e, 0x0d, 0x86, 0x09, 0xc9, 0x83, 0xa0, 0x4c, 0xc2, + 0xa5, 0xbc, 0xbd, 0xf0, 0x21, 0xdd, 0xd7, 0xeb, 0x77, 0x28, 0xff, 0x6e, 0x41, 0x5b, 0x8b, 0x6f, 0x9a, 0xff, 0x20, + 0xff, 0x2f, 0x1b, 0x30, 0x34, 0xe6, 0xf1, 0xe1, 0x58, 0xd2, 0x46, 0x19, 0x2d, 0xe5, 0x14, 0x1e, 0x3b, 0xd3, 0xf4, + 0x12, 0x4b, 0x87, 0x70, 0x77, 0x27, 0x99, 0x05, 0x87, 0x2d, 0x9b, 0x03, 0x24, 0x28, 0xc1, 0xe4, 0xcd, 0xc5, 0x68, + 0xd3, 0x63, 0xba, 0xc2, 0xe1, 0xbb, 0x15, 0x49, 0x36, 0x7b, 0x8d, 0x8b, 0x18, 0x20, 0x3d, 0x57, 0x30, 0x81, 0x02, + 0xfe, 0x30, 0x43, 0x51, 0x77, 0xe3, 0x5a, 0x4a, 0x31, 0x65, 0x8d, 0x20, 0x98, 0xe5, 0x2d, 0x9e, 0x63, 0xc8, 0xb4, + 0xad, 0x9e, 0xbb, 0x4f, 0x7a, 0xc0, 0x80, 0x13, 0x39, 0xfb, 0xd5, 0x62, 0x43, 0xa8, 0x6a, 0xdd, 0xae, 0xbd, 0x26, + 0xba, 0x42, 0x24, 0x7a, 0x72, 0xd2, 0x69, 0x40, 0x6c, 0x8b, 0x30, 0xe4, 0x50, 0xc8, 0xf8, 0xb8, 0x15, 0x39, 0x93, + 0xf0, 0x19, 0xdf, 0xb2, 0x4b, 0x16, 0x77, 0xa2, 0x99, 0x63, 0xc8, 0x67, 0x26, 0x41, 0xc4, 0xe8, 0x5a, 0x2a, 0xe7, + 0x84, 0x14, 0x5d, 0xa9, 0x47, 0xdf, 0x0f, 0xc8, 0xd2, 0x48, 0x82, 0x38, 0x3a, 0x55, 0x63, 0x9e, 0xff, 0x9d, 0x59, + 0x44, 0x67, 0xf0, 0x0f, 0xe3, 0xcc, 0xb3, 0xaf, 0x88, 0x7d, 0x96, 0x70, 0x32, 0xe9, 0xd5, 0xd6, 0x7a, 0x18, 0x44, + 0x20, 0xe0, 0xf3, 0xdd, 0xe8, 0xcd, 0x46, 0x5b, 0x37, 0x68, 0xbc, 0xa3, 0x79, 0x3a, 0xec, 0xcf, 0xc8, 0xdd, 0xa0, + 0x99, 0xd6, 0x6a, 0x53, 0xe2, 0x33, 0x08, 0x9c, 0xcb, 0x48, 0x35, 0x67, 0x19, 0x98, 0x60, 0xbf, 0x5f, 0x6c, 0x7d, + 0x01, 0xd5, 0x99, 0x11, 0x48, 0xfd, 0xae, 0x7a, 0xa9, 0x55, 0x9a, 0x31, 0xa6, 0xd3, 0x45, 0x6d, 0xaf, 0x0d, 0x1c, + 0xf8, 0x3e, 0xd9, 0xc4, 0xa4, 0xad, 0x5e, 0xe2, 0x04, 0x45, 0x77, 0x68, 0xd1, 0xf9, 0x5e, 0x35, 0xd1, 0x54, 0x66, + 0xec, 0xc9, 0xb8, 0x90, 0xed, 0xeb, 0xed, 0x7e, 0x43, 0xe6, 0xe8, 0x5a, 0xc7, 0x48, 0xc9, 0x45, 0x7d, 0x8e, 0xb8, + 0xca, 0x90, 0x7f, 0x5e, 0xc8, 0x62, 0x47, 0x1c, 0x6e, 0x7f, 0x87, 0x87, 0xd5, 0xa2, 0x2e, 0x66, 0xc7, 0x81, 0x38, + 0x46, 0xfe, 0x21, 0x72, 0x7e, 0x14, 0xb0, 0x19, 0x7e, 0x9a, 0xe1, 0x33, 0x68, 0xb3, 0x37, 0xfb, 0xc9, 0x36, 0xbf, + 0xf5, 0xd8, 0xf5, 0xef, 0x1a, 0x5e, 0xf9, 0xc6, 0x2a, 0x1c, 0x76, 0xdf, 0x76, 0x62, 0xcc, 0xfb, 0xf3, 0xd3, 0xaf, + 0x35, 0x46, 0xde, 0x10, 0xb0, 0xd9, 0xc1, 0xfb, 0x38, 0x67, 0xbf, 0xa5, 0xc3, 0x42, 0x2f, 0x6a, 0x15, 0x90, 0x51, + 0xe7, 0x3e, 0x71, 0x7d, 0x0b, 0x90, 0x56, 0x68, 0xa1, 0xd5, 0xa3, 0x5b, 0x42, 0xf7, 0x12, 0x21, 0xeb, 0x9b, 0x4b, + 0xb1, 0xe9, 0xb4, 0x67, 0x4d, 0x25, 0x25, 0x4d, 0xf1, 0x96, 0x14, 0x8a, 0xdf, 0xcf, 0xa8, 0x93, 0x07, 0xb8, 0xcf, + 0xa7, 0x8d, 0x64, 0xa6, 0xee, 0x26, 0xeb, 0xf9, 0x93, 0xd9, 0x13, 0x4a, 0xdb, 0x30, 0x9a, 0x43, 0x7e, 0xd3, 0x68, + 0x40, 0x8f, 0x47, 0x8b, 0x89, 0xd8, 0x0f, 0x02, 0x14, 0x7c, 0x1a, 0x2a, 0xa0, 0x7a, 0xa0, 0xdf, 0xf6, 0xd7, 0x01, + 0x27, 0x15, 0x31, 0x06, 0x7b, 0x03, 0x50, 0x30, 0x44, 0xb6, 0x91, 0xc5, 0x7b, 0xa1, 0x43, 0xd1, 0x27, 0x09, 0x9d, + 0xe9, 0x85, 0x12, 0x91, 0xd0, 0x23, 0x88, 0xce, 0xe9, 0xae, 0xf8, 0xc6, 0xe6, 0xc3, 0xeb, 0x58, 0xec, 0x59, 0x26, + 0xdf, 0x61, 0xb3, 0xb2, 0x0e, 0xf5, 0x35, 0x93, 0x86, 0xee, 0x45, 0xfb, 0xa8, 0x71, 0xeb, 0x45, 0x42, 0xc7, 0x5f, + 0xce, 0xeb, 0x91, 0x55, 0x6f, 0x89, 0x18, 0xa6, 0x98, 0x79, 0xcf, 0xa2, 0xde, 0xba, 0x68, 0x09, 0xd7, 0xac, 0xab, + 0x0e, 0x82, 0xa6, 0xc4, 0xd3, 0x7a, 0x70, 0x9d, 0x0b, 0xb1, 0xf8, 0xc9, 0x24, 0x5a, 0x3f, 0xf9, 0x6d, 0xdc, 0xa0, + 0xe4, 0x5c, 0x68, 0xd0, 0x85, 0x02, 0xa1, 0xf7, 0xde, 0x7b, 0x9b, 0x8f, 0xf6, 0x36, 0x35, 0xfd, 0x85, 0x79, 0xf1, + 0x47, 0x72, 0xd6, 0x6f, 0x76, 0x39, 0x70, 0x10, 0x4a, 0x9c, 0x30, 0x22, 0x5c, 0xd8, 0x34, 0x97, 0xbc, 0x94, 0x59, + 0xb9, 0x70, 0x86, 0x03, 0xd1, 0x19, 0xf1, 0x0d, 0x3f, 0xd8, 0xb6, 0x40, 0x20, 0x6e, 0xb5, 0x4c, 0x14, 0xcf, 0x88, + 0x38, 0x91, 0x65, 0x0e, 0x93, 0x9a, 0xe6, 0x72, 0xa6, 0x15, 0xbb, 0x6d, 0x05, 0x8d, 0x6f, 0x8c, 0x73, 0x2c, 0x81, + 0xde, 0xac, 0xd0, 0xce, 0xa5, 0x92, 0x8f, 0xfd, 0x8e, 0xaa, 0x9d, 0xeb, 0x2f, 0xaf, 0x65, 0x5e, 0xee, 0x3c, 0xbb, + 0x36, 0xcd, 0xcb, 0x35, 0x86, 0xce, 0x40, 0x66, 0x47, 0x75, 0x95, 0xa9, 0xbb, 0xd8, 0xe0, 0x8e, 0x42, 0x75, 0xb5, + 0x20, 0x1c, 0x80, 0x22, 0x9a, 0xe6, 0x98, 0x1b, 0xcc, 0xa2, 0xaf, 0xae, 0xf0, 0x4e, 0x07, 0x6d, 0xb5, 0xb4, 0x01, + 0x25, 0x20, 0x9c, 0x74, 0xd1, 0x61, 0x89, 0x07, 0x77, 0xa7, 0xee, 0x54, 0xd2, 0x60, 0x5c, 0x2c, 0xce, 0xc3, 0xb3, + 0x28, 0xee, 0x0a, 0xd3, 0xcc, 0x68, 0xf4, 0x03, 0x4d, 0xb4, 0xe7, 0x9b, 0xa5, 0xc4, 0x92, 0x0b, 0x76, 0xb9, 0xc7, + 0xf6, 0x03, 0x45, 0xe2, 0xa5, 0x3c, 0x56, 0x3a, 0xa5, 0xc4, 0x4e, 0x4d, 0x3b, 0x2b, 0xd3, 0x1c, 0x7a, 0x96, 0x65, + 0xe2, 0xb9, 0xf4, 0x3b, 0xaa, 0x67, 0x5b, 0x66, 0x7d, 0x53, 0xb8, 0xdb, 0x3b, 0x91, 0x12, 0x3f, 0x38, 0xd6, 0xf0, + 0xb6, 0xe8, 0x76, 0x9a, 0xbe, 0x2d, 0xdc, 0xfa, 0x05, 0x63, 0x0f, 0x8b, 0x55, 0xac, 0xbe, 0x28, 0x8e, 0x26, 0x14, + 0xd8, 0xea, 0xdf, 0xe4, 0x24, 0x4d, 0xdc, 0x4a, 0xe3, 0xaf, 0x69, 0x09, 0x53, 0x75, 0xaa, 0x7b, 0x2f, 0xb1, 0x8a, + 0xb0, 0x70, 0xff, 0x7d, 0xf5, 0x70, 0x28, 0x64, 0xb6, 0x79, 0xd6, 0x3c, 0x42, 0xba, 0x92, 0x7b, 0xc8, 0xa7, 0x4a, + 0xa6, 0xe6, 0x93, 0x93, 0xec, 0x86, 0xbb, 0x56, 0xab, 0x56, 0xc2, 0x9b, 0x66, 0xab, 0xc3, 0x75, 0xae, 0xd8, 0x68, + 0x99, 0x4d, 0x6a, 0xbb, 0x82, 0xe9, 0xdc, 0x3a, 0xf1, 0x38, 0x44, 0x22, 0x94, 0xb1, 0xbb, 0xbd, 0x51, 0x07, 0x17, + 0xb0, 0x29, 0xc1, 0x5d, 0x29, 0x38, 0x37, 0xd9, 0xe0, 0x2e, 0x88, 0xd4, 0x28, 0xae, 0x74, 0xdc, 0xdb, 0x86, 0x48, + 0xc1, 0x4e, 0x7a, 0xa4, 0x88, 0xc5, 0x69, 0xba, 0xf0, 0x34, 0xbe, 0xf2, 0x66, 0xd7, 0x34, 0x53, 0xdf, 0xa1, 0x46, + 0x8e, 0x68, 0x54, 0xee, 0x65, 0x48, 0x4c, 0x81, 0x87, 0x56, 0xe3, 0x59, 0xaa, 0x42, 0x6e, 0x30, 0xa3, 0x5b, 0xae, + 0xdb, 0xfd, 0xe2, 0xe3, 0x71, 0x39, 0x13, 0xd1, 0x85, 0xf1, 0x95, 0x1a, 0x92, 0x95, 0xec, 0x27, 0x22, 0x2f, 0x38, + 0xa6, 0xb3, 0x37, 0x45, 0x02, 0x6e, 0xe9, 0x8d, 0x8b, 0xb4, 0xa1, 0x5c, 0xcb, 0x06, 0x9d, 0x26, 0x39, 0x15, 0x54, + 0x88, 0x99, 0xb1, 0x66, 0xf1, 0xbe, 0x04, 0x09, 0x87, 0x3d, 0x85, 0x03, 0xd9, 0xd4, 0xcc, 0x6d, 0x87, 0x32, 0xd7, + 0xa1, 0x1a, 0x47, 0x62, 0xa3, 0x72, 0x08, 0x8e, 0xce, 0xdc, 0xee, 0xb1, 0xb0, 0xae, 0x60, 0x4e, 0x15, 0x59, 0x1e, + 0x9c, 0xae, 0xf6, 0x5f, 0xb8, 0x23, 0xfa, 0x62, 0x20, 0xfa, 0x9d, 0x56, 0x4d, 0xb4, 0xc0, 0x43, 0x8b, 0xeb, 0xda, + 0x42, 0x63, 0x0a, 0xe2, 0x80, 0xf4, 0x66, 0x82, 0xa2, 0xe1, 0x93, 0x66, 0x98, 0x83, 0x9e, 0xea, 0x9b, 0x9f, 0x3b, + 0x75, 0xf6, 0x65, 0x9a, 0x5e, 0x18, 0x66, 0x97, 0x06, 0xee, 0x8c, 0xa3, 0xa6, 0x18, 0x36, 0x5f, 0x8c, 0xbe, 0x89, + 0x5c, 0x9e, 0x7b, 0x56, 0x33, 0xc1, 0x34, 0x1d, 0x73, 0xe4, 0xbf, 0xc6, 0xf3, 0x7e, 0xc1, 0x71, 0x8c, 0x4a, 0x2f, + 0xbf, 0x28, 0x73, 0xa6, 0x25, 0x1b, 0xef, 0xab, 0x0b, 0xb8, 0x9e, 0x8c, 0x72, 0x24, 0x1e, 0x96, 0x59, 0x2c, 0x3f, + 0x80, 0x6f, 0x46, 0x2e, 0x41, 0x1b, 0xbb, 0x97, 0x89, 0x01, 0xc0, 0xb2, 0x5d, 0x73, 0x52, 0xbb, 0x46, 0xbe, 0x0a, + 0xb5, 0x55, 0xd7, 0xee, 0x24, 0xf3, 0x95, 0x08, 0xf6, 0x55, 0xfa, 0xe3, 0xa7, 0xa8, 0x07, 0xb5, 0xb7, 0x43, 0x92, + 0xab, 0x4d, 0xc2, 0xbe, 0x5f, 0x56, 0xa7, 0x27, 0xde, 0xbf, 0xc2, 0xe3, 0xe0, 0x02, 0x36, 0x3d, 0xf4, 0xf5, 0xb6, + 0x19, 0x89, 0x51, 0x77, 0x0d, 0xfe, 0xa0, 0xea, 0x21, 0x99, 0x1e, 0x74, 0x92, 0x47, 0x22, 0x30, 0xeb, 0xa9, 0x8e, + 0x89, 0xfc, 0x93, 0xf0, 0x73, 0xb5, 0xe7, 0xff, 0xf2, 0xf5, 0xd2, 0xcc, 0x9e, 0x21, 0xbc, 0x3b, 0xbc, 0xf9, 0xaa, + 0xd0, 0x75, 0xc6, 0xe5, 0xb1, 0x08, 0xe7, 0xce, 0xdf, 0x03, 0x70, 0xe5, 0x75, 0x79, 0xbb, 0x98, 0xef, 0x38, 0xed, + 0x2e, 0x6d, 0xde, 0xad, 0xa3, 0x86, 0x9f, 0x7f, 0xb0, 0x8d, 0x8a, 0x1f, 0xa9, 0x22, 0xfa, 0x75, 0x93, 0x05, 0x45, + 0x20, 0xe4, 0xe9, 0xeb, 0x84, 0x18, 0xff, 0x0c, 0x68, 0xfa, 0xa6, 0x50, 0xd9, 0x7f, 0xc3, 0x15, 0xa6, 0x0e, 0xe1, + 0x8f, 0xcc, 0xea, 0x60, 0x40, 0x73, 0x5b, 0xb8, 0x27, 0xfd, 0x17, 0x88, 0x35, 0x77, 0x10, 0xe0, 0x44, 0x91, 0xa4, + 0xe2, 0x87, 0x3e, 0xbc, 0x82, 0x26, 0xf7, 0x89, 0x14, 0xd4, 0x0c, 0xc5, 0x6d, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x47, + 0x87, 0xa8, 0x73, 0xf4, 0x88, 0xdd, 0x5f, 0xda, 0x9d, 0xc9, 0xc3, 0x37, 0x94, 0xac, 0x89, 0x50, 0x31, 0x98, 0x50, + 0xfe, 0x5c, 0xf7, 0x4b, 0xde, 0xb3, 0xf2, 0x95, 0xb1, 0x28, 0xb8, 0xd8, 0x1b, 0x54, 0xfd, 0x00, 0x16, 0xd0, 0x59, + 0x24, 0xa0, 0x62, 0xb7, 0x13, 0xd6, 0xa9, 0xc6, 0xf1, 0x93, 0x58, 0x36, 0xf1, 0xc3, 0xf2, 0x0d, 0xff, 0xa5, 0x21, + 0x24, 0xa1, 0x88, 0x39, 0xa9, 0xc3, 0x60, 0x47, 0x2c, 0x6e, 0x63, 0x36, 0x0f, 0xa5, 0xe6, 0x61, 0x39, 0x71, 0xde, + 0x41, 0x0b, 0x10, 0x97, 0xa3, 0xee, 0xaa, 0xb5, 0x4b, 0xa7, 0x6b, 0x1d, 0x86, 0x93, 0xd8, 0x29, 0x56, 0x78, 0x18, + 0x5b, 0x8f, 0x1c, 0x23, 0xfc, 0x77, 0x20, 0x8f, 0x2f, 0x69, 0x7e, 0x78, 0x7b, 0x47, 0x83, 0x24, 0x1a, 0x2b, 0x15, + 0xa9, 0x78, 0x4a, 0x0f, 0x2b, 0x92, 0x21, 0x4d, 0x24, 0x7a, 0x78, 0x2f, 0xdf, 0xd2, 0x78, 0x58, 0xa5, 0x62, 0x43, + 0xc7, 0xcd, 0x56, 0x07, 0x92, 0x8f, 0xb2, 0xdd, 0x5f, 0x2f, 0xbd, 0x15, 0x9a, 0x75, 0x0a, 0x9b, 0x97, 0x1e, 0xb7, + 0xd8, 0xbb, 0x67, 0x31, 0xf5, 0x53, 0xa0, 0xc6, 0x91, 0x1c, 0x88, 0x89, 0xb1, 0xa9, 0x80, 0x3c, 0xf3, 0xe4, 0xe4, + 0xfd, 0xe0, 0xf5, 0x87, 0x63, 0x1f, 0x4f, 0xa4, 0x7c, 0xcc, 0xce, 0x70, 0xcf, 0xa7, 0x5e, 0x7e, 0xa6, 0x59, 0x1e, + 0x88, 0x9d, 0x8e, 0xe2, 0x21, 0x1f, 0xdd, 0x89, 0x50, 0x23, 0x2c, 0x27, 0x6b, 0xd5, 0x4a, 0x6b, 0x0c, 0x6a, 0x85, + 0x32, 0x97, 0xfb, 0x58, 0xdc, 0xda, 0xfd, 0x68, 0x93, 0xef, 0x7e, 0xa6, 0x88, 0xe7, 0x24, 0x02, 0xb9, 0xfe, 0x61, + 0x90, 0x96, 0x82, 0x79, 0x69, 0xa4, 0x95, 0xfa, 0x13, 0x4a, 0x39, 0xf0, 0x10, 0xf0, 0x25, 0x11, 0x97, 0x86, 0xb6, + 0xfe, 0x07, 0x4c, 0x5e, 0xd7, 0xbd, 0x6f, 0x25, 0xce, 0x9a, 0x70, 0x6e, 0x89, 0x7b, 0xac, 0xe5, 0x27, 0xb5, 0x24, + 0x0f, 0x0a, 0xa3, 0xbd, 0x9d, 0x1e, 0x1a, 0xa6, 0xc5, 0x2b, 0x16, 0xc5, 0x27, 0x7d, 0x2a, 0xbf, 0x07, 0xb5, 0xeb, + 0x2c, 0x75, 0xd9, 0x0b, 0xe5, 0x4c, 0xa9, 0xce, 0x0a, 0xbf, 0x76, 0x18, 0x5a, 0xe9, 0x48, 0x9a, 0x25, 0xce, 0xd5, + 0x7b, 0xec, 0x26, 0x4e, 0xb8, 0x21, 0x0d, 0x14, 0xa8, 0x64, 0x36, 0x1c, 0xd1, 0x53, 0x18, 0xdb, 0xfa, 0x32, 0xc3, + 0xed, 0x87, 0x32, 0xee, 0xe0, 0x68, 0xb2, 0x9a, 0x22, 0x5f, 0x27, 0x45, 0x2c, 0x14, 0x49, 0xd8, 0x85, 0x4b, 0x3b, + 0xbf, 0xc1, 0x5a, 0x69, 0x7e, 0x31, 0x5e, 0x30, 0xde, 0x65, 0x5d, 0xc9, 0x87, 0xcf, 0xba, 0x3b, 0x47, 0x04, 0xc8, + 0xa3, 0x9c, 0xd4, 0x3c, 0x82, 0xdb, 0x84, 0xa8, 0xb7, 0xb7, 0x3d, 0xb9, 0xe1, 0xcc, 0xb6, 0x45, 0x8b, 0x55, 0x2f, + 0x57, 0xb2, 0xdf, 0x9e, 0x95, 0x85, 0x82, 0xec, 0x6e, 0xe0, 0xc8, 0x9d, 0xe9, 0xc4, 0x6f, 0x18, 0x48, 0xef, 0x41, + 0x2d, 0x38, 0xba, 0x6e, 0x01, 0xa8, 0x35, 0xb4, 0x91, 0x4e, 0x5f, 0x23, 0xdb, 0xc8, 0xb8, 0xbc, 0x77, 0x1c, 0x41, + 0x71, 0xc0, 0xf8, 0xfa, 0xde, 0x31, 0x9d, 0x96, 0x80, 0xa4, 0x8f, 0x98, 0x0f, 0x03, 0x8c, 0x82, 0x18, 0x03, 0xd5, + 0xea, 0xf1, 0x01, 0x4f, 0x40, 0xc4, 0x91, 0xad, 0x0e, 0x6e, 0xdc, 0x20, 0x6f, 0x1d, 0x19, 0x07, 0x9f, 0x90, 0x6e, + 0x28, 0x61, 0x30, 0x5e, 0xfe, 0xc8, 0x40, 0x75, 0xa1, 0x8e, 0x0d, 0xae, 0x6d, 0x14, 0x34, 0xce, 0x0c, 0x10, 0x08, + 0x3e, 0xbd, 0x5d, 0xe9, 0xaf, 0xe3, 0x0f, 0x3a, 0xab, 0x37, 0x05, 0xa9, 0x95, 0xd3, 0xa3, 0x36, 0x5b, 0xe8, 0x2a, + 0xa0, 0x70, 0xa6, 0x7a, 0xc2, 0x80, 0xeb, 0x0f, 0x1b, 0x06, 0xe6, 0x3d, 0x27, 0x94, 0xd9, 0x1c, 0x09, 0x7f, 0x49, + 0xb3, 0x6f, 0xd6, 0x30, 0xcf, 0xe5, 0xd8, 0x83, 0x1d, 0x02, 0xb9, 0x7a, 0x18, 0xfb, 0x2d, 0xb6, 0x4d, 0x10, 0xe6, + 0xb0, 0xfc, 0xf8, 0x9f, 0x0a, 0xb5, 0x15, 0x4a, 0xed, 0xcd, 0x8f, 0x1c, 0xd6, 0xce, 0x73, 0x79, 0xfc, 0x4f, 0x28, + 0xf2, 0xd9, 0x3c, 0xe4, 0x79, 0xb2, 0xd8, 0x36, 0x88, 0x3f, 0x3d, 0xb2, 0x77, 0x36, 0xbb, 0xd6, 0x3e, 0xc8, 0xcf, + 0x60, 0x97, 0x7f, 0x0f, 0x09, 0xd5, 0xb0, 0x65, 0x05, 0x3f, 0x8c, 0x47, 0x04, 0x80, 0x85, 0x5e, 0xbf, 0xd9, 0x37, + 0xe4, 0x66, 0x1f, 0x90, 0x19, 0xf4, 0x39, 0xa2, 0x91, 0x67, 0xc6, 0x35, 0xec, 0xcc, 0x73, 0x3e, 0xf7, 0x0c, 0xe7, + 0x07, 0xca, 0x7a, 0xca, 0x9c, 0xe7, 0x25, 0x1b, 0xf7, 0xb6, 0x70, 0x06, 0xba, 0xd5, 0x8c, 0x5d, 0xd8, 0x82, 0xe5, + 0x3b, 0x6b, 0xc1, 0xa9, 0x1b, 0x30, 0x7b, 0x7b, 0xee, 0x4f, 0x74, 0xe0, 0xcf, 0x50, 0xde, 0xc9, 0xa8, 0xd5, 0x6f, + 0xbe, 0x75, 0x3b, 0x8d, 0x01, 0x6f, 0x84, 0xa7, 0x8a, 0xea, 0xcc, 0x39, 0x7b, 0x0a, 0x72, 0x21, 0xfe, 0xa2, 0x1b, + 0x7c, 0x42, 0xb7, 0x2a, 0x0a, 0x01, 0x5f, 0xda, 0x62, 0x44, 0xc8, 0x3a, 0xb4, 0xa4, 0x94, 0x27, 0x6d, 0x3e, 0x51, + 0x73, 0xa7, 0xe8, 0x34, 0xb7, 0x32, 0x3f, 0x9c, 0x39, 0x81, 0x0d, 0x02, 0x49, 0x48, 0x11, 0xc2, 0x3f, 0xc5, 0x8e, + 0x7b, 0x67, 0x6c, 0xb9, 0x91, 0xd0, 0xa0, 0x5d, 0x94, 0x8a, 0x18, 0x1f, 0x95, 0x4e, 0x23, 0xae, 0x7b, 0x8f, 0xf0, + 0x0f, 0xf6, 0x3f, 0xd3, 0xa8, 0x4c, 0xff, 0x9d, 0x46, 0x61, 0xfa, 0xcf, 0x69, 0x08, 0xa6, 0xff, 0x9e, 0x06, 0xbb, + 0x4b, 0xad, 0x0e, 0xec, 0xab, 0x23, 0xfb, 0xea, 0xce, 0x1e, 0xa7, 0xd9, 0x1e, 0x5a, 0x7b, 0x5f, 0x83, 0x76, 0x6c, + 0x3f, 0xf1, 0x2d, 0x39, 0xe0, 0xad, 0x63, 0x59, 0xb2, 0xf1, 0x76, 0x8a, 0xbd, 0xcf, 0xe9, 0xd2, 0xe5, 0x71, 0x1f, + 0xc5, 0x53, 0x1e, 0x87, 0xd5, 0x74, 0x56, 0x51, 0x67, 0x5a, 0xa6, 0x91, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x6a, 0x3e, + 0x42, 0xde, 0xad, 0x25, 0x9c, 0x81, 0xd2, 0x04, 0xf9, 0xad, 0xe7, 0x8f, 0x8d, 0x62, 0x2f, 0x1a, 0x6f, 0xbb, 0xfb, + 0x99, 0x21, 0xce, 0x5f, 0x0c, 0x91, 0x54, 0xa6, 0x15, 0x26, 0xda, 0xc1, 0xd4, 0x6d, 0xcd, 0x5a, 0xac, 0x29, 0x20, + 0xb3, 0x3d, 0x8f, 0xb2, 0x25, 0x08, 0xe1, 0xb9, 0x6d, 0xe1, 0x3f, 0x0b, 0x58, 0x75, 0xb1, 0x85, 0x5e, 0x73, 0x39, + 0xe8, 0xb4, 0x52, 0xe9, 0x3e, 0x6b, 0x10, 0xbb, 0xa1, 0x4c, 0x77, 0x84, 0x8c, 0xe1, 0x05, 0x8b, 0x2b, 0x28, 0xea, + 0x17, 0x62, 0x71, 0x17, 0xb3, 0x87, 0xe7, 0x27, 0x65, 0x1a, 0xfc, 0xbf, 0x16, 0xdb, 0x41, 0x77, 0x42, 0x53, 0xe3, + 0x92, 0x4b, 0x2a, 0xec, 0x17, 0x62, 0xdc, 0x9e, 0xdb, 0x45, 0xd7, 0xb7, 0x4e, 0x19, 0x89, 0xcf, 0xf9, 0x0c, 0xe4, + 0x7a, 0xe9, 0xa7, 0xfa, 0xf4, 0x88, 0x0b, 0xb2, 0xa8, 0xa7, 0x39, 0xc1, 0xaa, 0x10, 0x33, 0x52, 0x87, 0x9a, 0x12, + 0x9f, 0xbf, 0xfa, 0x9f, 0xf6, 0x6b, 0x49, 0x3c, 0x68, 0xa7, 0x5f, 0xf9, 0xf5, 0xb1, 0x10, 0x97, 0xf6, 0x33, 0xf1, + 0xe3, 0xad, 0x62, 0xed, 0x0f, 0xa8, 0x7a, 0x9c, 0xaa, 0xff, 0x3d, 0x6a, 0xd1, 0xaf, 0xc3, 0x65, 0xd3, 0x7f, 0x2d, + 0x89, 0x07, 0xec, 0xf5, 0xeb, 0xf3, 0x3b, 0x18, 0xfc, 0x13, 0x43, 0xf2, 0xc8, 0x76, 0x02, 0x94, 0xe3, 0x47, 0xd1, + 0xe4, 0x38, 0xe4, 0x4c, 0x53, 0xae, 0x2b, 0x3c, 0xbd, 0xea, 0x68, 0x4c, 0x95, 0x8b, 0x23, 0xe9, 0xf4, 0x7c, 0x02, + 0x13, 0xd9, 0xf0, 0x96, 0xd9, 0xa5, 0xc8, 0xde, 0xc3, 0x11, 0x64, 0xb7, 0xcd, 0x27, 0x31, 0xcb, 0x67, 0x11, 0x2d, + 0xdb, 0x35, 0xd8, 0xe8, 0x94, 0xc3, 0x54, 0x5c, 0x38, 0xc0, 0xbe, 0xb7, 0x5c, 0x18, 0xec, 0x46, 0x6a, 0x1f, 0xa2, + 0x72, 0x7a, 0x1b, 0xd1, 0x6f, 0xca, 0x71, 0xf4, 0x7e, 0x1b, 0xac, 0x96, 0xc2, 0xc3, 0x43, 0x83, 0x58, 0xb5, 0xc3, + 0x2b, 0x46, 0xfd, 0xe2, 0x3a, 0xd4, 0x6e, 0x00, 0x4e, 0x9c, 0x69, 0xd3, 0xf5, 0xe3, 0xfc, 0xc2, 0x9f, 0xea, 0xd3, + 0x95, 0xd5, 0x53, 0x0f, 0x5d, 0xc4, 0xd1, 0x19, 0x97, 0x9d, 0x83, 0x12, 0x23, 0x8c, 0x19, 0x9e, 0xbf, 0x37, 0x2b, + 0x4b, 0x28, 0x48, 0x0b, 0xbd, 0x16, 0x54, 0x19, 0xfd, 0xfb, 0x03, 0xc5, 0xb9, 0xbc, 0x7f, 0xae, 0x7b, 0xff, 0x1e, + 0x33, 0xb4, 0xcd, 0x8c, 0x7a, 0xab, 0xe0, 0x3e, 0x9f, 0x24, 0xb0, 0x48, 0x96, 0x58, 0xdb, 0xe2, 0xff, 0xea, 0x12, + 0xeb, 0x34, 0xaa, 0xbd, 0xc2, 0xd5, 0x99, 0xb6, 0xe6, 0xab, 0xfa, 0x52, 0x73, 0xaf, 0xee, 0x47, 0x3f, 0xd8, 0x30, + 0x8d, 0x4b, 0x7b, 0x5a, 0x90, 0x9b, 0x64, 0xcf, 0xa2, 0xc7, 0xe6, 0x64, 0x1c, 0x5a, 0xf5, 0x43, 0x93, 0x00, 0x51, + 0xc6, 0xa9, 0x47, 0x9a, 0xf2, 0x59, 0xee, 0xc3, 0x12, 0x2f, 0xb8, 0x10, 0xd7, 0xc3, 0xed, 0xee, 0x9e, 0x91, 0x1d, + 0xa8, 0xf2, 0x9b, 0x77, 0x87, 0xf7, 0x7d, 0xa4, 0xfc, 0x0e, 0x54, 0xb3, 0xbe, 0x59, 0xa9, 0x08, 0xd4, 0x15, 0x28, + 0x02, 0x5c, 0xbe, 0x67, 0x95, 0xe0, 0xae, 0xe6, 0x79, 0x18, 0xb1, 0x92, 0x84, 0x9a, 0x2b, 0x05, 0x87, 0xc5, 0xa6, + 0x29, 0x45, 0x61, 0xb1, 0x26, 0xfa, 0x75, 0xcd, 0xa6, 0xd3, 0x45, 0x0d, 0x9c, 0x1b, 0x98, 0xa5, 0x9b, 0x35, 0xa2, + 0x1f, 0x12, 0xf2, 0x0e, 0x9e, 0x66, 0x8b, 0x6d, 0x20, 0x86, 0x5a, 0x5c, 0x63, 0x60, 0x7b, 0xf8, 0x90, 0x07, 0xf4, + 0xa4, 0xff, 0x74, 0x0d, 0xd1, 0x23, 0xdb, 0x80, 0xc5, 0x6f, 0x26, 0x75, 0x78, 0xf7, 0x30, 0x3d, 0xe3, 0xa5, 0x4f, + 0xc6, 0x2f, 0x0e, 0x6d, 0x86, 0x9f, 0x1e, 0x51, 0x54, 0x24, 0x2a, 0x77, 0x76, 0xd9, 0xcf, 0x86, 0x4c, 0xed, 0xe9, + 0x78, 0xb2, 0xbf, 0x60, 0x6e, 0xfd, 0x60, 0x7f, 0x18, 0xc7, 0x83, 0x04, 0x35, 0x14, 0x1b, 0xfe, 0x71, 0xa3, 0x58, + 0x24, 0x3d, 0x5b, 0x6f, 0xfb, 0xe0, 0x95, 0x50, 0xce, 0x2b, 0xd7, 0x32, 0x3d, 0xd3, 0xb1, 0x83, 0x67, 0xfa, 0xc1, + 0xea, 0x32, 0x01, 0x95, 0xdf, 0x85, 0x89, 0x81, 0x73, 0x24, 0xca, 0x11, 0x19, 0xf1, 0xa2, 0xe8, 0x4b, 0x36, 0x87, + 0x56, 0x58, 0x0d, 0xba, 0xa5, 0xe8, 0xaf, 0x57, 0x76, 0x97, 0xfa, 0xae, 0xcf, 0x5e, 0xe4, 0xf6, 0xe6, 0x63, 0x19, + 0x3a, 0x14, 0x29, 0x25, 0xa7, 0xfe, 0x64, 0x0c, 0x79, 0x7d, 0x3d, 0x75, 0xa6, 0xf8, 0xcf, 0x6c, 0x90, 0xc4, 0x6c, + 0x00, 0x0a, 0x59, 0x34, 0x8f, 0x00, 0x60, 0x49, 0x5f, 0x24, 0x81, 0x37, 0xfc, 0x43, 0xac, 0x59, 0x37, 0x44, 0xcc, + 0x57, 0xfb, 0xe6, 0xe2, 0x32, 0x0b, 0x77, 0x76, 0xec, 0xd1, 0x3d, 0x79, 0x10, 0x95, 0x25, 0x99, 0x4d, 0x67, 0xed, + 0x3d, 0xa4, 0xaf, 0x0c, 0x79, 0x06, 0x99, 0x32, 0x40, 0x02, 0xa6, 0x23, 0xac, 0x33, 0x3c, 0xb9, 0xe6, 0xdc, 0x6a, + 0xb2, 0x50, 0x82, 0x43, 0x74, 0x1c, 0xdd, 0x0a, 0x49, 0xd6, 0xdc, 0x6b, 0xbe, 0xd4, 0x0f, 0x52, 0x4e, 0x3e, 0xad, + 0x98, 0x27, 0x8e, 0xe3, 0x37, 0x24, 0xa2, 0x27, 0x11, 0xe5, 0x69, 0xd7, 0x39, 0xe4, 0xb7, 0xac, 0x54, 0xcc, 0x0c, + 0x54, 0x3d, 0xf2, 0x54, 0x13, 0xac, 0xbb, 0xc5, 0x1d, 0x88, 0xa7, 0x0f, 0x44, 0x13, 0x8a, 0x93, 0xac, 0xf2, 0x5a, + 0x0f, 0xb3, 0xe1, 0x2b, 0x62, 0x73, 0x35, 0xda, 0xec, 0x58, 0xcc, 0xd8, 0x0a, 0x9a, 0x60, 0x40, 0x9d, 0x11, 0x4e, + 0xbb, 0x76, 0xf7, 0x28, 0x30, 0xb2, 0xe9, 0x94, 0x7e, 0x8c, 0xa8, 0xd0, 0x6d, 0xbe, 0x8c, 0x0a, 0x71, 0x54, 0x84, + 0x9e, 0x87, 0xa1, 0x50, 0xfa, 0x69, 0x59, 0x14, 0xf1, 0x59, 0x3f, 0xe7, 0xae, 0xc6, 0x18, 0x53, 0x34, 0x95, 0x65, + 0xd7, 0x15, 0xc8, 0x1b, 0xb1, 0x35, 0x44, 0x80, 0x3c, 0x5f, 0x35, 0xed, 0xea, 0xd7, 0x9b, 0xa8, 0xfc, 0x3b, 0x36, + 0xba, 0x8d, 0x76, 0x13, 0x78, 0x56, 0x9c, 0xb9, 0x2d, 0x80, 0x35, 0x3a, 0xd7, 0x25, 0x71, 0xe4, 0xe8, 0x71, 0xbd, + 0x1f, 0xcc, 0xfe, 0xa4, 0xb5, 0x78, 0x90, 0x6f, 0x91, 0xa9, 0x95, 0x52, 0x17, 0xea, 0xb5, 0x65, 0x1a, 0xcf, 0x07, + 0x99, 0x49, 0xf9, 0x84, 0xd1, 0xf9, 0xd2, 0x4d, 0xf3, 0xc2, 0x66, 0x81, 0xc9, 0x44, 0x25, 0x4e, 0x61, 0x3a, 0xb7, + 0x4b, 0x84, 0xa4, 0x3b, 0x82, 0x53, 0x59, 0x56, 0x14, 0x77, 0xb7, 0xad, 0xd9, 0x37, 0x93, 0xbf, 0x26, 0x3d, 0x1c, + 0xe3, 0x2e, 0xe8, 0xd8, 0x28, 0x6f, 0x26, 0xdb, 0x83, 0xc9, 0xc3, 0xea, 0x42, 0xe9, 0xb4, 0x9a, 0x6e, 0xea, 0x19, + 0xb9, 0xb9, 0x71, 0xea, 0x6a, 0xa2, 0xeb, 0x12, 0x30, 0x9e, 0x8d, 0xe2, 0x1e, 0x5b, 0xe4, 0x1a, 0x79, 0x6d, 0x2d, + 0x41, 0xb7, 0x2c, 0x14, 0x8b, 0xd1, 0xd4, 0xc0, 0x18, 0x61, 0x52, 0x11, 0x83, 0xd7, 0xe7, 0xb0, 0xc9, 0x13, 0x13, + 0xa8, 0xea, 0xdf, 0x94, 0x93, 0x25, 0xbb, 0x98, 0xa5, 0x91, 0x0c, 0xcb, 0x41, 0xd9, 0x7b, 0xa2, 0xa5, 0x8f, 0x78, + 0x2e, 0x70, 0x6d, 0xdb, 0xf6, 0x61, 0x6d, 0x6b, 0xc0, 0xc0, 0xfb, 0xa6, 0x7d, 0x07, 0xc1, 0x15, 0xbb, 0xd5, 0x9c, + 0x67, 0xf0, 0x78, 0xc0, 0xec, 0x5b, 0xf2, 0x7c, 0x5e, 0xa8, 0xb2, 0x7d, 0xa2, 0xb3, 0xfb, 0x02, 0x42, 0x31, 0xbb, + 0xd1, 0xe5, 0xd9, 0x6e, 0xbb, 0x87, 0x0c, 0x59, 0x90, 0xb1, 0x24, 0x29, 0x3c, 0xf2, 0x9d, 0x5e, 0x6d, 0x19, 0x6b, + 0x3e, 0x73, 0x19, 0xb7, 0xa4, 0x16, 0x94, 0x6a, 0x0f, 0x6d, 0x8a, 0xf2, 0x5a, 0x84, 0x49, 0x15, 0xd6, 0x6e, 0xf3, + 0x99, 0xca, 0xd1, 0x16, 0x91, 0x09, 0x1e, 0x17, 0x12, 0x3b, 0x83, 0x25, 0x82, 0x0c, 0x9d, 0x26, 0x68, 0x6a, 0x9f, + 0x44, 0xb3, 0xb8, 0xe6, 0xc1, 0xa8, 0xa6, 0xca, 0xe1, 0x75, 0x13, 0x26, 0xcc, 0xe3, 0x42, 0xda, 0x76, 0xc4, 0x24, + 0x5d, 0xc7, 0xf9, 0x6a, 0x25, 0xeb, 0x51, 0x8e, 0xcc, 0x73, 0xa5, 0xb3, 0x95, 0x2e, 0xe6, 0x41, 0x29, 0xca, 0xcb, + 0x50, 0x20, 0x91, 0x93, 0xad, 0x66, 0x6f, 0x2f, 0x8d, 0xd5, 0x40, 0xa4, 0x57, 0xd6, 0xc7, 0x23, 0x58, 0x4c, 0x17, + 0x29, 0xa5, 0x60, 0x03, 0x85, 0xb0, 0xd1, 0xd8, 0xb3, 0x56, 0xfe, 0xf9, 0xb9, 0xa6, 0x5a, 0xf5, 0x67, 0x84, 0x6d, + 0xf6, 0x8b, 0xf7, 0xe5, 0x58, 0x05, 0x18, 0x75, 0x2f, 0xb2, 0x22, 0x79, 0xab, 0xcb, 0x5b, 0x24, 0x6f, 0xbe, 0xbc, + 0x32, 0x71, 0xc2, 0xf3, 0xb5, 0xd6, 0x86, 0x09, 0x77, 0x6e, 0x55, 0xeb, 0x88, 0x2b, 0x31, 0xd7, 0x7e, 0xdf, 0xa0, + 0x9f, 0x26, 0xa2, 0xec, 0x5f, 0xcd, 0xa8, 0x90, 0x4d, 0x9f, 0x12, 0xaa, 0xcd, 0xbc, 0x8c, 0x90, 0xbb, 0x17, 0x83, + 0x49, 0xa9, 0x4e, 0x5d, 0xdd, 0xe6, 0xe3, 0x8b, 0x31, 0xb1, 0x7e, 0xf9, 0xd7, 0xb8, 0x38, 0x5f, 0x30, 0x1c, 0xba, + 0xe2, 0xce, 0x7b, 0xd6, 0x0a, 0xe5, 0x0a, 0x73, 0xc0, 0x39, 0x5a, 0xaa, 0x2a, 0x63, 0xd4, 0xb6, 0xea, 0xdc, 0x01, + 0x8f, 0x23, 0x08, 0xfc, 0x8e, 0xae, 0x1a, 0x49, 0x46, 0xa9, 0xef, 0xea, 0x18, 0xfc, 0x65, 0xa4, 0xf1, 0xe1, 0xf7, + 0x05, 0x11, 0xf4, 0xd2, 0x55, 0xe5, 0xda, 0xa3, 0x2a, 0xa2, 0xac, 0x82, 0x24, 0xe6, 0x64, 0xb9, 0x0b, 0x47, 0xb9, + 0xf1, 0xe7, 0x93, 0x5d, 0xad, 0x0d, 0x42, 0xcc, 0x62, 0xcc, 0xd9, 0x52, 0xcc, 0x59, 0x11, 0xbe, 0x7d, 0x1e, 0xfd, + 0xce, 0x55, 0x25, 0x10, 0xf9, 0x68, 0xe3, 0x51, 0x7c, 0xf9, 0x22, 0xe0, 0x69, 0x55, 0x7d, 0x20, 0x24, 0xbe, 0xb3, + 0xd3, 0x2e, 0xf9, 0x6b, 0x7f, 0xa6, 0x44, 0x32, 0x69, 0x89, 0x21, 0x70, 0x47, 0xfc, 0xce, 0x75, 0x03, 0x19, 0x80, + 0x9c, 0xd1, 0xae, 0x01, 0x73, 0x12, 0x4d, 0x43, 0x42, 0xd5, 0xb4, 0x96, 0x77, 0xf3, 0x0a, 0x7d, 0x22, 0x89, 0x7e, + 0x97, 0x37, 0xc3, 0xaf, 0xb4, 0x48, 0xe5, 0x9c, 0xbf, 0xef, 0xe2, 0x57, 0x75, 0x64, 0xe7, 0x4c, 0x63, 0xa5, 0xc0, + 0x97, 0x01, 0xb8, 0x81, 0x76, 0xc5, 0x8d, 0x38, 0xce, 0x92, 0x1e, 0xd9, 0x19, 0x3d, 0x50, 0xdb, 0x57, 0xb2, 0x68, + 0x29, 0x5e, 0x98, 0xa6, 0x10, 0xca, 0xe0, 0x22, 0x3e, 0x91, 0xb9, 0xa8, 0xb2, 0xe6, 0x55, 0x5f, 0xe0, 0x36, 0x22, + 0x66, 0x44, 0x79, 0x22, 0x92, 0x9c, 0x95, 0xba, 0xa1, 0xc1, 0xe2, 0xe8, 0xd2, 0x62, 0x4d, 0x4e, 0x90, 0xcc, 0x97, + 0x88, 0xe0, 0x5f, 0x2e, 0xd5, 0xb3, 0xfb, 0x9b, 0xb5, 0x67, 0x85, 0xb6, 0x46, 0x60, 0xb2, 0x8b, 0x5e, 0xbd, 0xe8, + 0x35, 0xb7, 0x86, 0xf2, 0x21, 0x51, 0xc8, 0xef, 0x49, 0xdd, 0x1a, 0xd6, 0x4c, 0x52, 0x30, 0xdf, 0x17, 0xb5, 0x45, + 0xeb, 0xce, 0xb1, 0x97, 0x3f, 0xea, 0x71, 0xf7, 0x54, 0x82, 0x82, 0xd0, 0x6d, 0x26, 0xb5, 0x40, 0x24, 0x59, 0x63, + 0x8b, 0x7d, 0x22, 0x7a, 0xc7, 0x74, 0xa5, 0x74, 0x71, 0x64, 0xfb, 0xe5, 0x1d, 0x32, 0x93, 0x9c, 0x5d, 0x2a, 0x31, + 0xe5, 0x3f, 0x47, 0xd9, 0xe4, 0x62, 0x67, 0x8b, 0x3e, 0x73, 0x90, 0x36, 0x53, 0x13, 0x61, 0x0a, 0xf6, 0xce, 0xcc, + 0x46, 0x08, 0x8f, 0x24, 0x93, 0xc2, 0x28, 0xb1, 0x97, 0x7c, 0x8a, 0xa7, 0x90, 0xdf, 0x2a, 0x34, 0xb4, 0xe4, 0x99, + 0xfe, 0x07, 0xeb, 0x08, 0xdf, 0x4a, 0xe0, 0x20, 0xc9, 0x3f, 0x60, 0xc1, 0x6d, 0xe9, 0x7a, 0xc7, 0x6c, 0x90, 0x84, + 0xfb, 0x67, 0x96, 0xcf, 0x76, 0x7b, 0x10, 0xbf, 0x29, 0x12, 0x82, 0x2f, 0x3a, 0xaa, 0x5d, 0xb2, 0x8c, 0x4a, 0xaa, + 0x45, 0xe5, 0x7e, 0x7c, 0xcc, 0xcb, 0x23, 0x2a, 0x2f, 0xe0, 0x97, 0xef, 0xd6, 0x1c, 0x98, 0x81, 0xaf, 0xb4, 0xd5, + 0x44, 0xc2, 0x5e, 0x18, 0xec, 0x29, 0x94, 0x2c, 0xe2, 0xc0, 0x6e, 0x36, 0xc4, 0x5c, 0xe8, 0x5a, 0x9b, 0xed, 0xc3, + 0x18, 0x6a, 0x75, 0xca, 0xf4, 0x26, 0xae, 0x6a, 0x84, 0xb9, 0x4d, 0x23, 0x8e, 0x4a, 0x66, 0xda, 0x97, 0x1b, 0x4c, + 0xd3, 0x21, 0x7b, 0x1b, 0x68, 0x2d, 0xdf, 0x1c, 0xeb, 0xca, 0x9b, 0x69, 0x8f, 0x42, 0xc0, 0x18, 0xb1, 0xe6, 0x8a, + 0x5e, 0x6b, 0x65, 0x3f, 0x48, 0xb1, 0x3f, 0xaa, 0x05, 0x22, 0xaa, 0x22, 0xa9, 0xd9, 0xb0, 0xcb, 0x5e, 0xad, 0xbd, + 0xac, 0x0b, 0xb0, 0x74, 0x6a, 0x39, 0xd6, 0xbc, 0x60, 0x30, 0x94, 0xa9, 0x5a, 0x2d, 0x73, 0x87, 0xab, 0xec, 0xa9, + 0x96, 0x97, 0xb2, 0x20, 0x61, 0x2f, 0x81, 0xe8, 0xc4, 0xf7, 0x74, 0x4f, 0x22, 0xdf, 0x99, 0xd3, 0x37, 0x66, 0x32, + 0xc4, 0xe8, 0xac, 0x58, 0x81, 0x55, 0xbd, 0x0d, 0x0c, 0x15, 0xb5, 0xc6, 0x86, 0xee, 0xf2, 0x98, 0x7d, 0x8e, 0xc3, + 0x7d, 0x61, 0xbf, 0x2d, 0xc8, 0x7d, 0xf8, 0xef, 0x59, 0x7e, 0xdb, 0xd8, 0x2c, 0xcc, 0xb2, 0xde, 0x3c, 0x46, 0x8e, + 0xf0, 0x7a, 0x4b, 0xa5, 0xca, 0x16, 0x0c, 0xd9, 0x6b, 0x58, 0xf7, 0xab, 0x99, 0xba, 0x90, 0x6e, 0x62, 0x46, 0x8c, + 0xda, 0x9d, 0x48, 0x12, 0xf4, 0x14, 0x33, 0x28, 0xa1, 0x79, 0x91, 0xd6, 0x66, 0x23, 0xf7, 0x60, 0x9d, 0x8e, 0x4c, + 0x44, 0x97, 0x60, 0x8a, 0x73, 0x36, 0xdf, 0xdf, 0x61, 0xc8, 0x61, 0x8f, 0x25, 0xaa, 0xe4, 0x41, 0xbd, 0x6f, 0x65, + 0xa5, 0xa6, 0xd8, 0x74, 0x2c, 0x23, 0x2e, 0x37, 0x80, 0x83, 0x1d, 0x6d, 0xa7, 0x86, 0x39, 0xb5, 0x73, 0x09, 0x76, + 0x72, 0x53, 0x7b, 0xb7, 0x22, 0x03, 0x4b, 0x1e, 0x08, 0x55, 0x18, 0xf0, 0x69, 0x5f, 0x11, 0x00, 0x9a, 0xe3, 0x14, + 0x89, 0x3f, 0x8c, 0xe4, 0xef, 0x77, 0x24, 0x9d, 0x84, 0xe3, 0x6e, 0x24, 0x70, 0x7a, 0x1c, 0xc0, 0x28, 0xf5, 0x64, + 0xf3, 0x03, 0x10, 0xe5, 0x22, 0x7f, 0x95, 0x18, 0x1d, 0x31, 0x44, 0x38, 0xf0, 0x53, 0x71, 0x21, 0x6d, 0xbd, 0x59, + 0x2e, 0x8e, 0x46, 0x41, 0xd7, 0xd5, 0x01, 0xf7, 0x91, 0x0a, 0x00, 0x6d, 0x36, 0xe4, 0xba, 0xbe, 0x77, 0x88, 0xd8, + 0x7d, 0x5a, 0xb8, 0x41, 0x04, 0x7e, 0x5c, 0xa6, 0xe6, 0x5b, 0x38, 0x5c, 0xd3, 0x4c, 0xbd, 0x95, 0xc7, 0xd3, 0x7d, + 0xdd, 0xed, 0x0c, 0xf0, 0x2f, 0x97, 0x38, 0x60, 0xfe, 0x3b, 0xa9, 0xe2, 0x60, 0xc4, 0x1c, 0x1d, 0xe3, 0x92, 0x66, + 0x66, 0x6a, 0xc8, 0x73, 0x73, 0xe5, 0x29, 0xca, 0x81, 0xcc, 0x27, 0xd3, 0x43, 0x76, 0x13, 0xf8, 0x35, 0x40, 0x5d, + 0x3c, 0x24, 0x54, 0x80, 0x7a, 0x82, 0xc0, 0xd5, 0x04, 0xc2, 0xb2, 0xf9, 0x73, 0x6c, 0xee, 0x99, 0x68, 0x02, 0x1a, + 0x3a, 0x50, 0xe9, 0xf4, 0xa4, 0x2c, 0x80, 0x7a, 0xa8, 0xfd, 0x10, 0x09, 0x0f, 0x7a, 0xd9, 0x74, 0xd0, 0xb8, 0x8e, + 0x46, 0x48, 0x9a, 0x50, 0x90, 0xb8, 0xc0, 0x29, 0xfa, 0x6a, 0xc9, 0xfc, 0x55, 0x22, 0xdf, 0xa8, 0x72, 0xd1, 0xe0, + 0x5f, 0xa2, 0x45, 0x56, 0xcf, 0x18, 0x99, 0x1d, 0x6d, 0xca, 0x4a, 0x65, 0xbc, 0x00, 0xf0, 0xe1, 0x10, 0x1c, 0x49, + 0x44, 0x2c, 0x93, 0x68, 0x22, 0x1b, 0x87, 0xf2, 0xa7, 0x97, 0x77, 0x0a, 0xe0, 0x7a, 0x1e, 0x09, 0x9a, 0x08, 0x7c, + 0x6c, 0x09, 0x38, 0x33, 0x83, 0x00, 0x67, 0xab, 0x4d, 0x23, 0x30, 0x11, 0x5a, 0x79, 0x6a, 0xd8, 0xc7, 0x48, 0x94, + 0xe3, 0x12, 0x61, 0xe4, 0x76, 0x4d, 0x19, 0xb9, 0x44, 0x24, 0x36, 0xe6, 0xc8, 0x73, 0xfd, 0x51, 0x0a, 0xfd, 0xcb, + 0x2c, 0x7c, 0x52, 0xa2, 0xfa, 0xd2, 0xa0, 0x78, 0xd3, 0xc6, 0x07, 0x3b, 0x18, 0xd7, 0x52, 0xcb, 0x61, 0xc2, 0x60, + 0xbe, 0xf6, 0xff, 0xc6, 0xd7, 0x4a, 0xf5, 0x95, 0xf3, 0x11, 0x5d, 0xf1, 0x18, 0x1c, 0xd6, 0x89, 0x9c, 0x5f, 0x37, + 0x4d, 0xe4, 0xf8, 0x73, 0x79, 0xb7, 0x37, 0x9e, 0xee, 0x36, 0x82, 0xca, 0xa5, 0x34, 0x67, 0x9e, 0x11, 0x7d, 0x18, + 0x58, 0xbe, 0x58, 0xa3, 0xca, 0x34, 0xbe, 0x74, 0x40, 0xb9, 0xe2, 0xf0, 0xf4, 0x24, 0x10, 0x2f, 0x07, 0x7b, 0x8a, + 0x03, 0x62, 0x45, 0x89, 0xb2, 0x67, 0x2a, 0x22, 0x8d, 0x43, 0x60, 0xbd, 0x11, 0x19, 0x19, 0x02, 0x52, 0x86, 0xed, + 0x9a, 0xf5, 0xaf, 0x58, 0x51, 0x7c, 0x0e, 0xc9, 0x26, 0xcb, 0x66, 0x7c, 0x8a, 0x1d, 0x8d, 0x57, 0x22, 0xa9, 0x68, + 0xd9, 0xf4, 0xa7, 0x6d, 0x47, 0xf6, 0x5e, 0x82, 0x43, 0xe2, 0x00, 0xa7, 0xf4, 0xce, 0x9f, 0xcb, 0x3b, 0xab, 0x23, + 0xdf, 0x83, 0xfe, 0x95, 0x97, 0xfc, 0x95, 0xef, 0xc1, 0x9e, 0xf2, 0x92, 0xa7, 0x7c, 0x0f, 0xf8, 0x94, 0x17, 0x89, + 0xe2, 0x34, 0x7d, 0xe5, 0x70, 0x1e, 0x8c, 0x11, 0x43, 0xb9, 0x3c, 0x91, 0xad, 0xe4, 0xe0, 0x17, 0xef, 0x13, 0xee, + 0xb3, 0x81, 0x94, 0x3c, 0x66, 0xa6, 0x58, 0x89, 0x4a, 0x56, 0x96, 0x49, 0x01, 0x7c, 0xea, 0xdb, 0xc5, 0x99, 0xed, + 0x17, 0xfc, 0xe1, 0x97, 0x48, 0x1a, 0x03, 0x71, 0xa7, 0x04, 0x5d, 0xbb, 0xd3, 0xd7, 0x9e, 0xdb, 0x8a, 0x08, 0xca, + 0x72, 0xc4, 0xe8, 0x44, 0xa5, 0x1d, 0x67, 0x89, 0xde, 0xbd, 0x55, 0x18, 0x08, 0xfa, 0x76, 0xa1, 0x8f, 0xc8, 0x61, + 0xfd, 0xfd, 0x17, 0x20, 0x64, 0x5c, 0x12, 0x88, 0xc0, 0x3e, 0xf6, 0xea, 0x39, 0xd4, 0xda, 0xf3, 0xa4, 0x8a, 0x06, + 0x5c, 0x93, 0x83, 0x71, 0x8b, 0x90, 0xa4, 0xa7, 0xff, 0x88, 0x1f, 0x92, 0xb3, 0x74, 0xd1, 0x3c, 0x0b, 0xf7, 0x18, + 0x2d, 0x07, 0x34, 0x27, 0x41, 0xd5, 0xcc, 0x72, 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xe0, 0x64, 0xa9, 0xb6, 0xae, + 0xc2, 0x9d, 0xf7, 0xf8, 0x19, 0x9f, 0xd1, 0x71, 0x9a, 0x1e, 0x19, 0xb0, 0x2f, 0x72, 0x7a, 0x1f, 0x5c, 0xe1, 0x58, + 0x6b, 0x30, 0x3d, 0x91, 0x6c, 0x2d, 0xae, 0xaf, 0xc6, 0xf8, 0x82, 0xb4, 0xca, 0xfb, 0x52, 0x44, 0xc3, 0x4f, 0xc9, + 0xc4, 0x66, 0xa4, 0xa5, 0x21, 0x5f, 0x5b, 0x6a, 0xb4, 0x59, 0xb1, 0x04, 0x4b, 0x6e, 0xbf, 0x75, 0x85, 0x4d, 0xdf, + 0x64, 0x2e, 0x92, 0x6c, 0x54, 0xdd, 0x14, 0x69, 0x53, 0xe0, 0x53, 0x92, 0x15, 0xc1, 0x23, 0x50, 0x64, 0xee, 0x48, + 0x72, 0xbc, 0x74, 0xd4, 0x72, 0xaa, 0x4a, 0x88, 0xc2, 0x67, 0x15, 0x56, 0xb5, 0x14, 0x1d, 0x2f, 0x0e, 0x44, 0x08, + 0x39, 0x8c, 0x4b, 0xa7, 0xa6, 0xd1, 0x75, 0xad, 0xf6, 0x16, 0xf2, 0x1c, 0x7c, 0xf9, 0x69, 0x88, 0x25, 0x2c, 0x59, + 0x8d, 0x31, 0xe0, 0xcc, 0xb3, 0x1b, 0x7a, 0xe4, 0xb9, 0xbc, 0x1f, 0x80, 0xa3, 0x17, 0xbb, 0x16, 0x8a, 0xb9, 0xeb, + 0x33, 0x12, 0x09, 0x24, 0x32, 0x5f, 0x00, 0x70, 0x00, 0xc0, 0x55, 0x2f, 0xab, 0x3a, 0x80, 0x41, 0x2b, 0x55, 0xa0, + 0x67, 0x0a, 0x6e, 0x81, 0xcc, 0xd0, 0x72, 0x50, 0xf9, 0x23, 0x0a, 0x7c, 0xed, 0x90, 0x2c, 0x26, 0xb2, 0x34, 0x94, + 0xac, 0x63, 0x42, 0x3b, 0x1f, 0xc6, 0xd3, 0x4b, 0x14, 0xee, 0x22, 0xa5, 0xa3, 0xb6, 0xe8, 0xa7, 0x67, 0x8f, 0x7a, + 0x5a, 0x38, 0x2d, 0x22, 0x2f, 0xc7, 0xc6, 0xbf, 0xe5, 0xed, 0xba, 0x5c, 0x7f, 0x64, 0x2b, 0x9a, 0x82, 0x36, 0x04, + 0x9f, 0x3d, 0x5b, 0xf5, 0x8c, 0xbe, 0x42, 0x4e, 0x8b, 0xe5, 0xd0, 0xeb, 0xb7, 0x59, 0x6d, 0x0e, 0x1f, 0x9e, 0xd1, + 0x03, 0xd1, 0xa5, 0xbb, 0xd7, 0x48, 0xa0, 0xb9, 0x44, 0xb0, 0x18, 0x9e, 0xe3, 0xd2, 0x6e, 0x72, 0x28, 0x29, 0x0a, + 0x62, 0x15, 0xf8, 0x80, 0xde, 0xde, 0xc1, 0x90, 0xc1, 0xae, 0xdb, 0x18, 0xc0, 0xd5, 0x40, 0xf3, 0xac, 0xc5, 0x61, + 0xaf, 0x4f, 0xc0, 0xc6, 0xd2, 0xf9, 0x6a, 0xdb, 0x45, 0xb1, 0xd7, 0x5c, 0x91, 0xee, 0xda, 0x0a, 0x81, 0x3f, 0x17, + 0x9f, 0xfc, 0xed, 0x79, 0xd1, 0xfe, 0xd6, 0x7f, 0x29, 0xbd, 0x77, 0xaa, 0xf6, 0x7b, 0xa3, 0x01, 0xf5, 0xc7, 0xa9, + 0x65, 0xa9, 0x2c, 0x87, 0x59, 0xe9, 0xf9, 0x68, 0x54, 0x8b, 0xdb, 0x6b, 0x8a, 0x88, 0x8f, 0x92, 0xe0, 0x66, 0x53, + 0x2b, 0x0f, 0xee, 0x9d, 0xed, 0x85, 0xbe, 0x87, 0x81, 0xea, 0x5e, 0x0b, 0x4d, 0x77, 0x2e, 0x25, 0xa8, 0xc9, 0xc8, + 0x68, 0xa6, 0xd9, 0x98, 0xb7, 0xbe, 0xf9, 0x61, 0xaa, 0x5f, 0xd0, 0xa7, 0x52, 0x72, 0x20, 0x3b, 0xab, 0x8b, 0x52, + 0xb1, 0x2a, 0x09, 0xc1, 0xe2, 0xfa, 0xbb, 0x38, 0x24, 0x30, 0x70, 0xad, 0xba, 0x0c, 0x18, 0x89, 0x7d, 0xb1, 0xf8, + 0xa8, 0xe8, 0xf8, 0xad, 0x1d, 0x64, 0x70, 0xb3, 0xcb, 0xbc, 0x0c, 0x33, 0xfc, 0x20, 0xac, 0xd3, 0x9a, 0x82, 0x40, + 0x4d, 0x9d, 0xbc, 0x4a, 0x82, 0x62, 0xf9, 0x66, 0x4f, 0x1b, 0x7b, 0x61, 0x6c, 0x03, 0xe8, 0xd9, 0xa6, 0x91, 0x18, + 0x4c, 0xfc, 0x93, 0x63, 0xf7, 0x57, 0xa1, 0xd2, 0xaa, 0x6b, 0x51, 0x7b, 0x51, 0x1e, 0x84, 0x0e, 0xa1, 0x43, 0x51, + 0x2b, 0xb7, 0x75, 0x58, 0x9f, 0xd7, 0xb2, 0x3c, 0xe9, 0x9f, 0x78, 0xbb, 0x48, 0xd7, 0xc5, 0x1d, 0x0c, 0x35, 0x12, + 0xc8, 0x8e, 0x2a, 0x36, 0x69, 0xdc, 0x51, 0xa9, 0xb2, 0xdc, 0x7d, 0xd8, 0xa0, 0x5e, 0x5b, 0x44, 0x90, 0xa9, 0x3e, + 0xae, 0x08, 0x35, 0x86, 0x3d, 0xa1, 0x34, 0x05, 0x4c, 0x65, 0x95, 0xc5, 0x53, 0x73, 0x77, 0x7e, 0xc8, 0x99, 0xd2, + 0x70, 0xc0, 0xc7, 0xb0, 0x98, 0x0d, 0xfc, 0xfb, 0x21, 0xd2, 0xc0, 0x4d, 0xad, 0x67, 0xa1, 0x4c, 0x20, 0xad, 0x50, + 0xcc, 0x47, 0x32, 0x0a, 0x13, 0x7c, 0xcf, 0x19, 0x14, 0x39, 0x29, 0xd9, 0x68, 0xfc, 0x66, 0xdd, 0x63, 0xe8, 0x38, + 0x33, 0x3e, 0xcc, 0xd3, 0x15, 0x7b, 0xa5, 0xc0, 0xd5, 0x21, 0x14, 0x5c, 0x8e, 0xa3, 0x1a, 0xd7, 0x05, 0xd9, 0x40, + 0x49, 0x5e, 0x78, 0x8f, 0x24, 0xa4, 0x2e, 0xf4, 0x94, 0x6a, 0x47, 0x21, 0x19, 0x96, 0x60, 0x7a, 0xdc, 0x9d, 0xb1, + 0x8d, 0x2b, 0x69, 0xdb, 0xd9, 0x69, 0xa1, 0x6e, 0xcf, 0xc0, 0x83, 0x5d, 0xd5, 0x3b, 0x28, 0x47, 0x56, 0x06, 0x1a, + 0x8c, 0x80, 0xb6, 0x2c, 0x49, 0xaa, 0x89, 0xd8, 0x68, 0x14, 0x46, 0x0d, 0xa5, 0xb5, 0x92, 0x9d, 0x9c, 0xdf, 0xeb, + 0xaa, 0x98, 0x26, 0xeb, 0x50, 0x1c, 0xf4, 0xc4, 0x24, 0xa5, 0x79, 0x5d, 0xb6, 0x78, 0x7f, 0xa0, 0xf6, 0x8b, 0x54, + 0x7b, 0x62, 0x6f, 0x6e, 0x24, 0x4a, 0xb3, 0xef, 0x29, 0x94, 0x87, 0x46, 0xe7, 0xb5, 0xd1, 0x79, 0x79, 0x1d, 0xa5, + 0xff, 0x9b, 0xa8, 0x65, 0xca, 0xc6, 0x98, 0xa2, 0x0e, 0x68, 0x3e, 0x31, 0x82, 0xf6, 0xfd, 0x4b, 0xa1, 0x8e, 0x50, + 0x34, 0x4c, 0x3d, 0xce, 0xb0, 0x18, 0xe9, 0x06, 0xcf, 0x97, 0x84, 0x04, 0xf7, 0xee, 0xc0, 0xc0, 0x23, 0xc2, 0x3c, + 0x91, 0x31, 0x9d, 0x20, 0x0c, 0x51, 0x59, 0x27, 0x67, 0xde, 0xe7, 0xe6, 0xdf, 0x6e, 0x4a, 0xdb, 0x6e, 0xfa, 0x0d, + 0x26, 0xe7, 0xfd, 0x94, 0xde, 0x7b, 0x79, 0xb4, 0x69, 0x7f, 0x31, 0xb2, 0x5b, 0xf0, 0xc2, 0xe2, 0x3d, 0x16, 0xf6, + 0x2f, 0x65, 0x3e, 0x73, 0xac, 0xf4, 0x36, 0x63, 0x20, 0x83, 0x67, 0xd6, 0x58, 0xfe, 0x4a, 0xd0, 0x8e, 0x42, 0xa0, + 0x9d, 0xd8, 0x09, 0x59, 0x05, 0x09, 0x88, 0xc4, 0x58, 0xdb, 0xce, 0xc1, 0x40, 0x3b, 0xd6, 0x99, 0x5b, 0xb4, 0xf4, + 0xdd, 0x53, 0x4e, 0x4a, 0x00, 0xca, 0x4b, 0xe5, 0x9f, 0x5d, 0x9c, 0x1a, 0xfb, 0x38, 0xc1, 0xd8, 0x0a, 0xec, 0x43, + 0x02, 0xa9, 0x2a, 0x26, 0x74, 0x9a, 0x22, 0xa0, 0x8b, 0x63, 0x13, 0x7f, 0x6e, 0xdc, 0x9d, 0xc1, 0xea, 0x69, 0xbe, + 0x64, 0x9b, 0xdd, 0x4b, 0x8c, 0xa9, 0xcd, 0x3a, 0xdb, 0x16, 0xf3, 0x8c, 0xdc, 0x95, 0xc5, 0xda, 0x04, 0x52, 0xb6, + 0xe4, 0xca, 0xb5, 0x45, 0xc8, 0x84, 0x21, 0xeb, 0x1a, 0x42, 0x52, 0x20, 0xf8, 0x2d, 0x25, 0x81, 0xd5, 0xfb, 0xa5, + 0xae, 0xd4, 0xb3, 0x88, 0x76, 0x99, 0xa0, 0x1d, 0x1c, 0x39, 0xd2, 0x79, 0xe1, 0xff, 0xb7, 0x12, 0x42, 0x38, 0xd3, + 0x86, 0x6e, 0x4b, 0x68, 0x92, 0xe2, 0xe8, 0x2a, 0x5a, 0x40, 0xbe, 0xeb, 0xf5, 0x2f, 0x8d, 0xcd, 0xfb, 0x0e, 0x9e, + 0x0d, 0x22, 0x81, 0x8d, 0xa8, 0xa9, 0x51, 0x0d, 0xab, 0xad, 0x6e, 0xda, 0x6e, 0x1e, 0xdd, 0xde, 0xc8, 0xc7, 0x50, + 0xe1, 0xe8, 0xe7, 0x40, 0x89, 0xe3, 0xde, 0x34, 0xa5, 0x4d, 0x54, 0xfe, 0x17, 0xaa, 0x05, 0x4e, 0xe1, 0x93, 0x1b, + 0x9c, 0x0a, 0x4e, 0xbb, 0xa7, 0x86, 0xe2, 0x7e, 0xbf, 0x54, 0xd1, 0xf5, 0x71, 0x73, 0x95, 0x01, 0x9a, 0xf0, 0x08, + 0x72, 0x39, 0xf2, 0xfd, 0xbc, 0xae, 0xfc, 0x22, 0xbf, 0xf4, 0xed, 0x6b, 0x47, 0xd8, 0x42, 0x8d, 0xb4, 0xd0, 0xe3, + 0x24, 0xbf, 0x2c, 0x6f, 0x92, 0xee, 0x90, 0x81, 0xeb, 0x2f, 0x6b, 0xec, 0x1d, 0xaa, 0xf2, 0xd8, 0x6d, 0x8f, 0x14, + 0x08, 0xd3, 0x49, 0x97, 0xca, 0x5d, 0x29, 0x25, 0x62, 0xd4, 0x86, 0xb3, 0x4e, 0xd5, 0xa2, 0xb6, 0xb0, 0x9e, 0x2d, + 0x74, 0x93, 0x0a, 0x08, 0xd5, 0xf7, 0x94, 0x87, 0x63, 0x60, 0xd8, 0x3b, 0x5f, 0x1e, 0x27, 0x0b, 0xe7, 0x53, 0x5d, + 0x2b, 0xe7, 0xa9, 0xb6, 0xeb, 0xbe, 0xce, 0x50, 0x60, 0x6c, 0xe9, 0x1d, 0xbb, 0x0c, 0xe7, 0xb7, 0xea, 0x0a, 0x4f, + 0x96, 0x11, 0x3c, 0x4b, 0x7d, 0x42, 0xf0, 0x55, 0xf2, 0x48, 0xe1, 0xc1, 0xd1, 0xcd, 0x59, 0x40, 0x07, 0xd3, 0x49, + 0xe0, 0xc1, 0xf1, 0xb6, 0x56, 0xc9, 0xfa, 0xe0, 0xe5, 0x98, 0x10, 0x06, 0x94, 0xac, 0x0f, 0xb6, 0xdd, 0x58, 0xb9, + 0x44, 0xe3, 0xf5, 0x23, 0x0b, 0x2d, 0xba, 0x7e, 0xd0, 0xa6, 0xe7, 0x01, 0x53, 0x39, 0xaa, 0xae, 0xe7, 0x29, 0x67, + 0x87, 0x98, 0x27, 0x8c, 0x74, 0x62, 0xd0, 0xc8, 0x0e, 0x98, 0x47, 0xa9, 0xf9, 0xa9, 0x75, 0x9b, 0x6f, 0xf6, 0xe1, + 0x33, 0x61, 0xac, 0xd5, 0x46, 0x91, 0xcf, 0x53, 0x68, 0xcf, 0x8e, 0xbc, 0xdf, 0xa8, 0x21, 0x23, 0x6b, 0xd3, 0x15, + 0x90, 0x8c, 0x05, 0x7f, 0x36, 0x43, 0x58, 0xd4, 0x4a, 0xc6, 0x69, 0x62, 0x9f, 0x4d, 0x37, 0x91, 0xae, 0xf2, 0x55, + 0x04, 0x78, 0xbf, 0xe1, 0x4c, 0x9a, 0xc7, 0x96, 0x5b, 0x8c, 0x98, 0xbc, 0xd4, 0x84, 0xda, 0xa2, 0x89, 0x28, 0x01, + 0xa0, 0xd7, 0xc3, 0x3e, 0x02, 0x95, 0xbe, 0x43, 0x38, 0x37, 0x4f, 0x6c, 0x69, 0x93, 0x9a, 0x0b, 0x0a, 0xc3, 0x1d, + 0x3b, 0xd9, 0x8b, 0x4d, 0x26, 0xf6, 0x0c, 0xe6, 0xa1, 0xc5, 0x5a, 0x76, 0xf3, 0x47, 0xb1, 0xe3, 0x07, 0x34, 0x90, + 0xf9, 0x01, 0x0b, 0x92, 0x3f, 0x96, 0x0e, 0x71, 0x2e, 0x04, 0xc5, 0x43, 0x5a, 0xc9, 0x22, 0x16, 0xa4, 0xdb, 0xf1, + 0x22, 0xce, 0x65, 0x4e, 0x6e, 0x01, 0x41, 0x75, 0x20, 0x16, 0xb2, 0xdc, 0x40, 0x1a, 0x6f, 0x70, 0xe1, 0xbc, 0xc9, + 0x89, 0x24, 0xb0, 0xf5, 0x4c, 0x24, 0x93, 0x45, 0x39, 0x16, 0x81, 0xdf, 0x7c, 0xec, 0xfe, 0x66, 0x3e, 0x36, 0x1b, + 0x7b, 0xda, 0x2c, 0xdf, 0x2c, 0xc2, 0xcc, 0xda, 0xaa, 0xc2, 0x84, 0x25, 0x92, 0x71, 0xc2, 0x5b, 0x7b, 0xf8, 0xca, + 0xad, 0xe1, 0x33, 0xf8, 0xdd, 0xcc, 0x16, 0x73, 0x69, 0x3b, 0x5b, 0x24, 0xe9, 0x20, 0x4c, 0x37, 0xe1, 0x1f, 0x62, + 0x64, 0xba, 0xd8, 0xac, 0xe8, 0x47, 0x83, 0x44, 0xf1, 0x76, 0xe3, 0xe5, 0xe1, 0xb7, 0x08, 0x0e, 0x76, 0x0b, 0xb2, + 0xb9, 0xfb, 0x72, 0xa4, 0xe2, 0x21, 0x2b, 0xaa, 0x1a, 0x63, 0x84, 0x52, 0x88, 0x63, 0x88, 0xba, 0xdc, 0xbe, 0x6a, + 0xcb, 0x43, 0xba, 0xfa, 0x5a, 0x64, 0x14, 0xde, 0xca, 0x7f, 0x63, 0xbe, 0xe3, 0x9f, 0x31, 0x95, 0xd4, 0x79, 0x0e, + 0xf0, 0xb5, 0xdf, 0xc1, 0x20, 0x21, 0x2a, 0x22, 0x7f, 0x2d, 0x11, 0x20, 0x66, 0xbd, 0xc4, 0x00, 0xee, 0xbc, 0xba, + 0x95, 0x93, 0x90, 0xbe, 0x60, 0xe8, 0x6d, 0x8b, 0x85, 0x79, 0x3c, 0x92, 0x7c, 0x87, 0xb1, 0x88, 0x9d, 0xf5, 0xc1, + 0x8c, 0x9d, 0xba, 0xe6, 0xc3, 0x74, 0xf6, 0x1f, 0x23, 0x2c, 0x70, 0x04, 0x43, 0xad, 0x85, 0x9f, 0xae, 0x02, 0xb8, + 0xd3, 0x7f, 0x08, 0x52, 0xe0, 0x36, 0x7a, 0xe2, 0x67, 0xba, 0x17, 0xd8, 0x04, 0xa7, 0x62, 0xaf, 0x88, 0xed, 0x39, + 0xd0, 0xab, 0x55, 0x0d, 0xa5, 0xbb, 0x73, 0x3a, 0x08, 0x53, 0x2c, 0x0a, 0x63, 0xbd, 0x8e, 0x12, 0x9b, 0x55, 0xcb, + 0x69, 0xc2, 0x90, 0xed, 0x2a, 0xd4, 0x9e, 0xe4, 0xc2, 0xa2, 0x84, 0x23, 0x37, 0x89, 0x37, 0xd5, 0x3a, 0xa0, 0x7e, + 0xeb, 0xd7, 0x26, 0xb8, 0xf5, 0x82, 0xa5, 0x63, 0x41, 0xa1, 0xa5, 0x88, 0xc1, 0x23, 0x44, 0x06, 0xaf, 0xcb, 0x15, + 0xe2, 0xf4, 0x22, 0xfd, 0xbe, 0x75, 0x57, 0x4a, 0x4b, 0x77, 0xb3, 0x88, 0xd9, 0xcf, 0xe9, 0xaf, 0x86, 0x97, 0xd7, + 0x9c, 0x91, 0x71, 0xd1, 0xb4, 0xe8, 0xa9, 0xd7, 0xb8, 0xdc, 0x80, 0xd9, 0x43, 0xab, 0x63, 0x86, 0xfd, 0x33, 0x2d, + 0x2d, 0xc6, 0xf8, 0x9d, 0x28, 0xa6, 0xdd, 0xef, 0x3e, 0x75, 0xe2, 0x9e, 0x5e, 0xe8, 0xa0, 0xf7, 0x96, 0x78, 0xdb, + 0xe9, 0x9d, 0xae, 0x3e, 0x9b, 0x8e, 0x41, 0xf4, 0x8d, 0x32, 0x7d, 0x37, 0x0b, 0x5d, 0x2e, 0x63, 0xd6, 0x68, 0x93, + 0xf6, 0xe5, 0x72, 0xfa, 0xa5, 0x97, 0xb9, 0xf1, 0x6f, 0xe1, 0x7a, 0x32, 0x24, 0x92, 0x96, 0x2a, 0x95, 0x2a, 0x9c, + 0x74, 0x81, 0xc4, 0x9a, 0x89, 0x5a, 0xae, 0x51, 0x67, 0x1c, 0x0f, 0x97, 0x0e, 0xcb, 0xef, 0x9b, 0x0f, 0x2a, 0xbd, + 0x7c, 0x1f, 0x88, 0x7d, 0x76, 0x25, 0x19, 0x50, 0x4e, 0xe1, 0x8c, 0xec, 0xfe, 0x73, 0x58, 0xed, 0x0a, 0xa0, 0x66, + 0x18, 0xbd, 0x5c, 0x1a, 0x76, 0x50, 0x94, 0x7e, 0x3a, 0xe9, 0xa6, 0x20, 0xac, 0xaf, 0xce, 0xc2, 0xeb, 0x5a, 0x92, + 0xe8, 0x12, 0x7f, 0x25, 0xdd, 0x4f, 0x38, 0xc9, 0xbe, 0x43, 0x7d, 0x55, 0x97, 0x00, 0xd0, 0x21, 0x5e, 0xa9, 0x40, + 0x9a, 0x79, 0x4b, 0xba, 0x4a, 0x64, 0x5d, 0x7c, 0x48, 0x01, 0x5c, 0x59, 0x6f, 0x9f, 0x66, 0x21, 0x5d, 0x6b, 0x89, + 0x9d, 0x84, 0x6e, 0xb8, 0x9f, 0x30, 0x02, 0x24, 0xd8, 0xf1, 0x00, 0x9a, 0xbc, 0x13, 0x9e, 0x63, 0xbd, 0x9a, 0x58, + 0x83, 0x20, 0xa2, 0x7b, 0x2f, 0xc1, 0x6e, 0x4e, 0xf3, 0xac, 0xb0, 0x09, 0xd1, 0xec, 0xc8, 0x7d, 0x3f, 0x39, 0xf0, + 0x7a, 0x61, 0x53, 0xb1, 0x51, 0x99, 0x3a, 0xb9, 0xc5, 0x38, 0xc0, 0x3e, 0x2d, 0x05, 0xd4, 0x70, 0x15, 0xa5, 0x2c, + 0xa7, 0x29, 0xa1, 0xc5, 0x38, 0xe0, 0xf4, 0x25, 0x07, 0xff, 0x27, 0x82, 0x26, 0x64, 0x1d, 0x7e, 0xfc, 0xb1, 0x05, + 0x7f, 0x24, 0xad, 0x69, 0x56, 0x44, 0xab, 0x3d, 0xc5, 0x1a, 0x34, 0x2f, 0x93, 0x8f, 0x0d, 0x03, 0xd8, 0xbc, 0x16, + 0xb2, 0xfa, 0x89, 0x9b, 0x56, 0x3c, 0x50, 0x7e, 0xca, 0x41, 0xed, 0xa9, 0x35, 0xf6, 0x42, 0xb2, 0xd3, 0xac, 0xa8, + 0x88, 0xe2, 0x7a, 0xb2, 0x5d, 0x17, 0xef, 0xbe, 0x48, 0x54, 0xfc, 0xe9, 0x06, 0x62, 0x48, 0x40, 0x02, 0x83, 0x15, + 0xd4, 0x90, 0xd0, 0x51, 0x5f, 0x6f, 0xbe, 0xbc, 0xd5, 0x20, 0xd0, 0x7c, 0xe9, 0x14, 0x10, 0x33, 0x15, 0xb3, 0xf3, + 0x21, 0xa0, 0x8a, 0xf7, 0x6f, 0x30, 0x69, 0x36, 0x7e, 0xb7, 0x8e, 0x6b, 0x5d, 0x38, 0xff, 0x51, 0xab, 0x66, 0xc0, + 0x86, 0xb8, 0xa0, 0x4a, 0xd1, 0xb0, 0xca, 0x58, 0x20, 0x1a, 0x3d, 0x7d, 0x1c, 0x59, 0x0a, 0xfb, 0xe7, 0xe6, 0xcb, + 0x67, 0xad, 0x4e, 0x6d, 0x5e, 0xcd, 0x5c, 0x4a, 0xa2, 0xe0, 0x32, 0x7d, 0xc3, 0x57, 0x00, 0x20, 0x33, 0x6b, 0x10, + 0x14, 0x34, 0xf8, 0x1a, 0x7c, 0x6e, 0x45, 0xc8, 0x38, 0xd0, 0xfd, 0x90, 0xf1, 0x87, 0x9b, 0xf6, 0x8a, 0xde, 0xd2, + 0xca, 0x7c, 0x4b, 0xaf, 0xf7, 0xb4, 0xd5, 0xf5, 0x4b, 0x8b, 0x19, 0x75, 0xa9, 0x5a, 0x9e, 0x7e, 0xde, 0xee, 0x7b, + 0xe2, 0xd6, 0xda, 0x9f, 0x8a, 0x32, 0xb6, 0x27, 0xe5, 0xa0, 0x31, 0x37, 0xfe, 0x05, 0xea, 0x35, 0x0d, 0x8d, 0x8a, + 0x42, 0x79, 0x5b, 0xf7, 0xad, 0x50, 0xe6, 0xed, 0x89, 0x8c, 0x23, 0xa9, 0x3b, 0x86, 0xbc, 0x2f, 0x6d, 0xe3, 0xf3, + 0x9a, 0x22, 0x50, 0xf8, 0x95, 0xe9, 0x94, 0x02, 0x5d, 0x13, 0x2e, 0x11, 0x3c, 0xb4, 0xbc, 0x2e, 0xdd, 0x98, 0x41, + 0xe5, 0xe8, 0x03, 0xbd, 0xa5, 0x0d, 0xc1, 0x8f, 0x8b, 0xf0, 0x8b, 0x9d, 0xd0, 0x4c, 0xae, 0x02, 0x35, 0x13, 0x55, + 0xf6, 0x90, 0xac, 0x0c, 0x96, 0x13, 0xa9, 0x49, 0xdf, 0xd4, 0x99, 0x40, 0x83, 0xa9, 0x57, 0x3e, 0xeb, 0x82, 0xa1, + 0x8b, 0x5d, 0x69, 0x61, 0x60, 0x11, 0x26, 0x5f, 0x84, 0x5f, 0x1f, 0x7d, 0x2d, 0x8d, 0x16, 0x18, 0x02, 0x84, 0xe6, + 0x5e, 0x5e, 0x34, 0x0a, 0xb6, 0xbf, 0xbb, 0x69, 0xaf, 0x57, 0x78, 0xf0, 0xed, 0x83, 0x79, 0x89, 0xc5, 0x81, 0x9e, + 0x9b, 0xfc, 0x71, 0x27, 0xed, 0x44, 0x41, 0x48, 0x6d, 0x2e, 0x70, 0x08, 0x50, 0xd5, 0xec, 0x21, 0xce, 0x56, 0x29, + 0x3b, 0x71, 0x04, 0x64, 0xf9, 0x6d, 0x04, 0xbe, 0x7c, 0xb7, 0xc6, 0xde, 0x63, 0x91, 0xb9, 0x28, 0xed, 0xf1, 0xb7, + 0xbb, 0x0b, 0xab, 0xbb, 0x79, 0x78, 0x2c, 0x28, 0xec, 0xfc, 0xe1, 0x3c, 0xee, 0xeb, 0xba, 0x7b, 0x00, 0x98, 0x81, + 0xf0, 0x71, 0x21, 0x1c, 0x02, 0xd1, 0x4c, 0x37, 0xeb, 0xf6, 0xa3, 0x4a, 0xaa, 0x8a, 0xa7, 0x00, 0x27, 0x1c, 0x02, + 0xef, 0x4c, 0x3d, 0x36, 0x4b, 0xb0, 0xd9, 0x0e, 0xc0, 0x10, 0x4a, 0xd3, 0x1c, 0x37, 0xe5, 0x06, 0xc8, 0x77, 0x11, + 0xc3, 0x14, 0xf7, 0x62, 0x8f, 0x86, 0x0f, 0x28, 0x8a, 0x68, 0xe9, 0xbc, 0x20, 0xdf, 0x76, 0x11, 0xcb, 0x9d, 0x27, + 0xa3, 0x0c, 0x3e, 0x11, 0xf9, 0x16, 0x29, 0x64, 0xee, 0x47, 0x9a, 0xc2, 0x6a, 0x9b, 0xd6, 0x8f, 0x01, 0x91, 0x5b, + 0x5a, 0x37, 0x26, 0x5a, 0x03, 0x17, 0x7a, 0x13, 0xf9, 0x02, 0x5a, 0xdb, 0x2a, 0x76, 0x9f, 0x5f, 0x89, 0x64, 0xf0, + 0x40, 0x98, 0x7f, 0xe3, 0xe1, 0xad, 0xd1, 0x31, 0xa5, 0x66, 0x76, 0x49, 0xfb, 0xe3, 0xbd, 0xb5, 0x97, 0xad, 0xfb, + 0xd6, 0xbb, 0x6a, 0x4d, 0x9e, 0xd3, 0x21, 0x95, 0xd8, 0x49, 0x05, 0x50, 0x04, 0x1f, 0x5b, 0x3e, 0x3f, 0x07, 0xa8, + 0x13, 0x05, 0x5c, 0xa8, 0x72, 0xe2, 0xcc, 0x38, 0xcc, 0xf2, 0x2b, 0x69, 0x73, 0x70, 0xfb, 0x79, 0x93, 0x62, 0x20, + 0x84, 0x42, 0x07, 0x64, 0xea, 0x0d, 0x4e, 0x6a, 0x6b, 0xda, 0x02, 0x8b, 0x39, 0x2c, 0x10, 0x39, 0x82, 0x00, 0xe4, + 0x10, 0xe9, 0x5a, 0xa5, 0xfb, 0x78, 0xd0, 0x0d, 0x28, 0x6f, 0x04, 0x66, 0xa4, 0x3f, 0x80, 0xd8, 0xb1, 0xb6, 0x73, + 0x95, 0x88, 0x30, 0x89, 0x34, 0x16, 0x1e, 0xfe, 0x25, 0x53, 0x52, 0x3e, 0x62, 0xb1, 0x1b, 0x82, 0x69, 0x31, 0xaf, + 0x48, 0x0e, 0x29, 0x48, 0x17, 0xea, 0xea, 0x5b, 0x8e, 0xc9, 0x39, 0xcd, 0x32, 0x14, 0xa6, 0x48, 0x18, 0x39, 0x9b, + 0x36, 0x13, 0x59, 0x40, 0x33, 0x56, 0x45, 0xa0, 0x5c, 0x91, 0xf5, 0xa8, 0x92, 0x3f, 0x72, 0xfe, 0x4d, 0x58, 0x05, + 0x97, 0x63, 0xc7, 0xba, 0x61, 0x9d, 0x9d, 0x17, 0x95, 0x69, 0x99, 0x7c, 0x5b, 0x96, 0x24, 0x5e, 0xc2, 0x63, 0x21, + 0xde, 0x2f, 0xfa, 0x6d, 0xf5, 0x14, 0xfa, 0xe5, 0xae, 0x1d, 0x42, 0x85, 0x54, 0x0c, 0x6a, 0x09, 0x13, 0x45, 0x8b, + 0xd2, 0xf8, 0xbd, 0x00, 0x5b, 0x1e, 0x03, 0xda, 0x58, 0xfa, 0xc1, 0x4a, 0x5c, 0x95, 0x23, 0x6a, 0x59, 0xbd, 0x95, + 0xa2, 0x93, 0xcb, 0xca, 0x32, 0xda, 0x22, 0x92, 0x80, 0x00, 0xe7, 0x2b, 0x65, 0x35, 0xbf, 0xe4, 0x3a, 0xac, 0x5b, + 0xbf, 0xb2, 0x54, 0x2a, 0x4c, 0xd1, 0x62, 0xb0, 0x8c, 0x08, 0xe3, 0x36, 0xd7, 0xba, 0x38, 0x7e, 0xd7, 0xfc, 0x0d, + 0xe8, 0xb7, 0x70, 0x97, 0xbb, 0x6a, 0x05, 0x6e, 0x5e, 0x44, 0x74, 0x41, 0x2e, 0x03, 0xb9, 0x0b, 0xaa, 0x37, 0x68, + 0xc1, 0x96, 0xac, 0xb7, 0xe6, 0x32, 0x2f, 0x0f, 0x7d, 0x15, 0x83, 0x3c, 0x7d, 0xa8, 0x68, 0x75, 0xa8, 0xf5, 0x71, + 0x6f, 0xff, 0x69, 0xaf, 0xda, 0x69, 0x40, 0x07, 0xe4, 0xbe, 0xd6, 0xf1, 0x75, 0x97, 0xff, 0xf9, 0x87, 0xdb, 0x22, + 0x91, 0xfb, 0x25, 0x75, 0x03, 0x1d, 0x82, 0xd2, 0x81, 0x60, 0x3b, 0x5e, 0x5a, 0x7e, 0x72, 0xd0, 0x0b, 0x6b, 0x42, + 0x2d, 0xbc, 0x29, 0x4f, 0x83, 0x11, 0x21, 0x94, 0x92, 0x58, 0xe7, 0xb4, 0xd9, 0xc3, 0x82, 0x3e, 0xdc, 0xe1, 0xac, + 0x36, 0xa6, 0x3f, 0x21, 0xaa, 0x4c, 0xb4, 0x07, 0x76, 0x17, 0x4d, 0x6c, 0x78, 0xd8, 0x0f, 0x4a, 0x52, 0x42, 0xb5, + 0xaf, 0xe8, 0x03, 0x65, 0x62, 0x8e, 0x2f, 0x3b, 0x14, 0xfc, 0x55, 0x6a, 0x89, 0x4d, 0x0c, 0xf6, 0x1d, 0x87, 0x25, + 0x51, 0x31, 0x80, 0xcd, 0x65, 0x8c, 0x59, 0x5f, 0x60, 0x8b, 0xd8, 0x9f, 0x56, 0x03, 0x65, 0xbf, 0x5b, 0xf7, 0x7d, + 0x67, 0x05, 0x50, 0xe6, 0x9a, 0x9f, 0xf4, 0x7b, 0xe4, 0x7b, 0xb0, 0xa8, 0x5f, 0x87, 0xa0, 0x45, 0xd7, 0xb5, 0x35, + 0x71, 0xe6, 0xb3, 0x74, 0xcf, 0x0d, 0x17, 0xfe, 0xbe, 0x2a, 0x90, 0x09, 0xd2, 0x74, 0xa8, 0x62, 0x33, 0x2e, 0xca, + 0x28, 0xb6, 0x0c, 0xf7, 0xc2, 0xef, 0xa4, 0x20, 0x42, 0x84, 0x8c, 0x61, 0x5a, 0x22, 0xe8, 0xd4, 0x7c, 0x9e, 0x36, + 0x02, 0xd5, 0x35, 0x29, 0x73, 0x4f, 0x97, 0x3b, 0xe2, 0x41, 0x89, 0x1e, 0x59, 0x02, 0xf4, 0x7f, 0xab, 0xe7, 0x1a, + 0xb7, 0x9c, 0x11, 0xa4, 0x59, 0x10, 0x19, 0x9c, 0xc1, 0x71, 0x8e, 0x1b, 0x2d, 0x24, 0x48, 0x14, 0x77, 0x27, 0xa1, + 0x4f, 0xda, 0x38, 0x35, 0xf8, 0x05, 0xb9, 0x28, 0x37, 0x2a, 0x00, 0xb5, 0x7b, 0x88, 0x16, 0x05, 0x73, 0x66, 0xc8, + 0x8e, 0xbc, 0x87, 0x18, 0x1e, 0xda, 0x52, 0x69, 0x1e, 0x73, 0x72, 0x02, 0x51, 0x73, 0x99, 0x27, 0x35, 0xf6, 0x0a, + 0xfa, 0x06, 0x14, 0xa7, 0xd0, 0xc6, 0x98, 0x38, 0x5d, 0x9e, 0xfa, 0x54, 0x0d, 0x44, 0xe9, 0xd9, 0x7c, 0x5d, 0xac, + 0x23, 0x76, 0xc0, 0x2e, 0x34, 0x63, 0x0c, 0x7e, 0x23, 0x94, 0x02, 0x0e, 0x32, 0x9f, 0x08, 0x3a, 0xf2, 0x83, 0x81, + 0x93, 0x19, 0xe3, 0x5d, 0xd6, 0x84, 0x03, 0x3d, 0x94, 0x52, 0x7d, 0x01, 0x9b, 0x21, 0x04, 0xe8, 0xaf, 0xc4, 0x7b, + 0x67, 0xad, 0x9e, 0x51, 0x89, 0x17, 0x13, 0x39, 0x28, 0xc2, 0x84, 0x87, 0x48, 0x8d, 0x28, 0x74, 0x24, 0xda, 0x43, + 0x05, 0xb3, 0xec, 0x6c, 0x5b, 0x53, 0xde, 0x17, 0x75, 0xea, 0x34, 0x07, 0xbf, 0xbe, 0x17, 0x6f, 0xe4, 0xea, 0x31, + 0xa0, 0xc7, 0xbe, 0x6e, 0x09, 0xd9, 0xbd, 0x53, 0x40, 0x80, 0x7c, 0xb1, 0x43, 0xc6, 0x84, 0xe8, 0x58, 0xd3, 0x92, + 0xaa, 0xd9, 0x47, 0x8b, 0xd0, 0x5f, 0xae, 0x8f, 0x33, 0x2c, 0x13, 0x42, 0x6d, 0x61, 0x02, 0x88, 0xd0, 0x93, 0x4e, + 0x09, 0x96, 0xe4, 0x3e, 0x78, 0xd9, 0xb0, 0xc3, 0xc1, 0x76, 0x55, 0x0c, 0x4f, 0x0e, 0x3f, 0x0f, 0x81, 0xed, 0x98, + 0x80, 0x4e, 0xb3, 0x14, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x33, 0x49, 0x05, 0x31, 0x4d, 0x54, 0x3e, 0xe0, 0x0f, 0x6a, + 0x23, 0x6e, 0xd2, 0x8e, 0xe2, 0xdd, 0x08, 0x7b, 0x89, 0x43, 0x37, 0x84, 0xeb, 0x80, 0xa8, 0xd1, 0x3e, 0x97, 0x35, + 0x37, 0xa2, 0xcd, 0x33, 0x32, 0x70, 0x89, 0xd4, 0x5f, 0xa1, 0x75, 0x50, 0x69, 0x41, 0x3d, 0x8b, 0xdf, 0x02, 0x3c, + 0xb7, 0x86, 0x96, 0xfb, 0x15, 0x92, 0xb8, 0x53, 0x8c, 0x66, 0xb4, 0x47, 0x78, 0x99, 0xee, 0x10, 0xe0, 0xde, 0x6a, + 0xdd, 0x69, 0xba, 0x1e, 0xa0, 0x8c, 0x9d, 0xb8, 0xe9, 0xb6, 0xca, 0x49, 0x1a, 0x03, 0x6a, 0xcc, 0xbf, 0x47, 0xef, + 0x07, 0xdf, 0x73, 0xa4, 0xe3, 0x76, 0x59, 0xe8, 0x5a, 0xa1, 0xf9, 0xf4, 0x39, 0xd9, 0x69, 0xe9, 0x16, 0xf7, 0x26, + 0x11, 0xea, 0xf0, 0x11, 0x5e, 0x30, 0x17, 0x4a, 0x77, 0x5c, 0xd4, 0xbd, 0xf9, 0xc9, 0xc2, 0x4d, 0x51, 0x53, 0x98, + 0x42, 0xc9, 0x66, 0xc3, 0x2b, 0x89, 0x59, 0xa0, 0xb9, 0x5c, 0x29, 0x84, 0x96, 0xf7, 0x40, 0xed, 0x35, 0x24, 0x6e, + 0xad, 0xd7, 0x16, 0x6e, 0xd3, 0x45, 0x6b, 0x35, 0x59, 0xd0, 0xc6, 0x48, 0xca, 0x98, 0x39, 0x74, 0x56, 0x64, 0xba, + 0x2a, 0x0a, 0x86, 0x35, 0xb5, 0x5e, 0x5d, 0x3b, 0x7e, 0x7e, 0x69, 0x7a, 0x08, 0x13, 0x0e, 0xac, 0x56, 0xd0, 0x3b, + 0xec, 0x34, 0x7f, 0x7a, 0xe1, 0x6a, 0x0b, 0x83, 0x44, 0x01, 0x01, 0x5d, 0x72, 0xf4, 0x3e, 0x96, 0x9e, 0xa2, 0x20, + 0x52, 0xa7, 0xab, 0xae, 0x32, 0x12, 0x82, 0x95, 0x8a, 0xff, 0x76, 0x60, 0x42, 0x8e, 0x70, 0x8e, 0xc8, 0xed, 0x75, + 0x25, 0xe7, 0xc7, 0x03, 0xd2, 0xd3, 0x11, 0x91, 0xd0, 0xd3, 0x1b, 0x43, 0x70, 0x39, 0x68, 0xec, 0xef, 0x02, 0xae, + 0xf0, 0x01, 0x86, 0xaf, 0x87, 0xae, 0x94, 0x1b, 0x2c, 0xec, 0xfb, 0x02, 0x69, 0xca, 0x45, 0x04, 0x07, 0xaa, 0x1d, + 0xf9, 0x9c, 0x1d, 0xf9, 0xad, 0x79, 0x15, 0x38, 0x37, 0x27, 0xbb, 0x46, 0x11, 0xca, 0x14, 0xbb, 0xb7, 0x03, 0x23, + 0x51, 0x92, 0xf0, 0xbb, 0x43, 0x42, 0x6b, 0xad, 0xf3, 0x3b, 0xee, 0x07, 0xbc, 0x28, 0x22, 0xf9, 0x07, 0xb1, 0x79, + 0x4f, 0x93, 0xf3, 0xf2, 0x1a, 0x5b, 0xb7, 0x15, 0x23, 0x00, 0xcd, 0x4d, 0xe6, 0x6d, 0x95, 0xc1, 0x0d, 0x56, 0x06, + 0x79, 0xb2, 0x24, 0x18, 0xcf, 0x52, 0x0d, 0xe6, 0xd9, 0xb1, 0x93, 0x96, 0x05, 0x0b, 0x81, 0x22, 0xd7, 0xd4, 0x66, + 0x75, 0x12, 0x57, 0xb4, 0x63, 0xf7, 0x5b, 0xb6, 0xc0, 0x09, 0x48, 0x3d, 0x71, 0xb2, 0xb4, 0x0d, 0x3e, 0x50, 0x48, + 0x76, 0x67, 0x19, 0x06, 0xd9, 0x85, 0xff, 0x2a, 0xe8, 0x07, 0x54, 0x57, 0x21, 0x54, 0xa4, 0x4d, 0x6c, 0x95, 0x94, + 0x22, 0x6b, 0x84, 0xd6, 0xd9, 0x16, 0x64, 0xc5, 0xd9, 0x1e, 0xf1, 0xa8, 0x99, 0xc0, 0x83, 0xc9, 0x6d, 0x91, 0xcd, + 0x19, 0xee, 0x89, 0x40, 0xc7, 0xa6, 0x50, 0x66, 0xda, 0x84, 0x6d, 0xdc, 0x93, 0xcd, 0xda, 0xbb, 0xad, 0xa8, 0x19, + 0x34, 0xa2, 0x6f, 0x69, 0x9a, 0xfd, 0x7b, 0x7d, 0xf0, 0x59, 0x89, 0xbe, 0x91, 0x43, 0x4c, 0xd7, 0x6d, 0xa4, 0x49, + 0x95, 0x5a, 0xe2, 0xd7, 0x6d, 0x3e, 0xbd, 0xa7, 0xa1, 0x1c, 0x52, 0x00, 0x27, 0x94, 0x02, 0x33, 0xe4, 0x73, 0x0c, + 0xc1, 0x9d, 0x82, 0x6d, 0x24, 0xcb, 0xad, 0xc8, 0x65, 0xd6, 0x58, 0xdd, 0xf1, 0x0f, 0x16, 0x80, 0x42, 0x5f, 0xde, + 0xa1, 0xa0, 0x1f, 0x6b, 0xbd, 0x4f, 0xd4, 0x91, 0x12, 0x93, 0xe2, 0xd3, 0xa5, 0x9b, 0xac, 0x02, 0x6a, 0xae, 0x5e, + 0x17, 0x0d, 0xe8, 0x35, 0x61, 0x00, 0xa1, 0x47, 0x74, 0xd8, 0x42, 0x18, 0xfd, 0xd1, 0x14, 0xc2, 0x7a, 0x5f, 0xc5, + 0x6d, 0xb7, 0x29, 0xba, 0xa7, 0xb3, 0x3b, 0x46, 0x6a, 0x90, 0x99, 0x56, 0x34, 0xc7, 0x70, 0x7a, 0xc0, 0x9d, 0xe2, + 0xb1, 0x63, 0x81, 0xcd, 0x26, 0xd5, 0x63, 0x8c, 0x01, 0x8e, 0xcc, 0x58, 0x6c, 0x53, 0x69, 0xad, 0x8c, 0x91, 0xda, + 0x16, 0xfd, 0xb2, 0xe6, 0x4e, 0x51, 0xdc, 0xfe, 0x08, 0x80, 0x79, 0x6e, 0x32, 0xad, 0xa3, 0x98, 0xa2, 0x46, 0x49, + 0xdb, 0xc5, 0xf1, 0x52, 0x54, 0x5e, 0x7c, 0x22, 0x70, 0x6f, 0x84, 0xca, 0x95, 0xa3, 0x03, 0xab, 0x33, 0xa5, 0x1f, + 0x6e, 0xf1, 0x98, 0x39, 0x89, 0x78, 0x01, 0xa3, 0xcf, 0x98, 0x0d, 0xe7, 0x0b, 0xef, 0x88, 0xb9, 0x45, 0x4e, 0xe1, + 0x5d, 0xf1, 0x56, 0xf8, 0xa5, 0x0b, 0xa8, 0xee, 0x41, 0x9c, 0xee, 0x54, 0xd6, 0x7a, 0x9d, 0x11, 0x21, 0xe1, 0x3b, + 0x92, 0xec, 0x95, 0x8c, 0x9d, 0xf8, 0x2c, 0x32, 0x3d, 0x38, 0x86, 0x85, 0x67, 0x8c, 0xe4, 0xf6, 0x99, 0x3a, 0x9a, + 0xb3, 0xc7, 0x3a, 0xd7, 0x45, 0x77, 0x5e, 0x7b, 0x6f, 0x2b, 0xd2, 0x53, 0x33, 0x9b, 0x4e, 0xbc, 0x69, 0x80, 0x3a, + 0x1f, 0xbc, 0xf6, 0x48, 0xe7, 0x7c, 0x07, 0x47, 0x71, 0x28, 0x5c, 0xb7, 0x6a, 0xf4, 0xd9, 0xf5, 0x1e, 0x72, 0x35, + 0x6c, 0xba, 0x8b, 0xc7, 0x65, 0x8f, 0x26, 0x7f, 0xb1, 0x22, 0x10, 0xfb, 0x18, 0x1e, 0x9f, 0xd3, 0xe0, 0xd6, 0xda, + 0xce, 0xb4, 0xd5, 0x36, 0x02, 0xd5, 0xa6, 0xa9, 0x05, 0x7e, 0xd2, 0xd5, 0x71, 0x3e, 0x71, 0xbc, 0xbc, 0x6b, 0xe0, + 0x4b, 0xfc, 0x02, 0x84, 0x55, 0xe9, 0xf5, 0xee, 0xf1, 0x1d, 0x67, 0x99, 0x2d, 0x73, 0xaf, 0x01, 0x59, 0x0e, 0x73, + 0x9d, 0xc5, 0xf1, 0xae, 0x3a, 0x22, 0x95, 0xda, 0xbe, 0xf2, 0xbf, 0x33, 0xe3, 0x42, 0x97, 0x1d, 0x41, 0x1c, 0xc8, + 0x15, 0x39, 0x53, 0x2a, 0xac, 0xc2, 0x69, 0x69, 0x4d, 0x43, 0xe3, 0x3a, 0x14, 0x04, 0x64, 0xf8, 0x7f, 0x20, 0x1c, + 0x44, 0xe6, 0xad, 0x13, 0x92, 0xaa, 0x6a, 0x03, 0x6b, 0xb4, 0x17, 0x7b, 0x01, 0x52, 0x78, 0x28, 0x92, 0xad, 0x2f, + 0xda, 0xaf, 0x4b, 0x64, 0x21, 0x03, 0xc1, 0x28, 0x93, 0x24, 0xc0, 0xd6, 0xd1, 0xad, 0x9e, 0xee, 0x92, 0x5e, 0x26, + 0xa0, 0xef, 0xf4, 0x3c, 0xfe, 0x10, 0x87, 0xa2, 0xac, 0x39, 0x7f, 0x6e, 0x49, 0xb6, 0xf3, 0xe8, 0xae, 0x6a, 0xac, + 0x43, 0x2c, 0x36, 0x97, 0x1c, 0x1d, 0xe7, 0x45, 0x81, 0xb3, 0x0c, 0x7d, 0x07, 0x8c, 0x85, 0x77, 0x36, 0x0c, 0xd5, + 0x5c, 0x48, 0x35, 0x7d, 0xc5, 0xa7, 0x70, 0x1d, 0x1e, 0x52, 0x4a, 0xdb, 0x16, 0xeb, 0xc1, 0x72, 0x88, 0x97, 0xdc, + 0x50, 0xa1, 0x71, 0xb5, 0x34, 0x9b, 0xd4, 0x73, 0x98, 0xc6, 0x8a, 0x2f, 0xd0, 0xa4, 0xdc, 0x45, 0xc5, 0x53, 0x07, + 0x53, 0x87, 0x6e, 0x52, 0x88, 0x7e, 0x3a, 0x32, 0x27, 0x92, 0x34, 0xe9, 0xc7, 0xb6, 0x51, 0x05, 0x01, 0xd0, 0xd1, + 0x5a, 0x16, 0xb4, 0xfb, 0xde, 0xaf, 0x7e, 0x65, 0xa3, 0x4d, 0x8f, 0x1a, 0x92, 0xb9, 0xd6, 0xe1, 0xd6, 0xd7, 0x72, + 0x7c, 0x77, 0x45, 0x18, 0xcd, 0xdb, 0x03, 0xab, 0xc2, 0xb9, 0x88, 0x14, 0xe3, 0x16, 0xad, 0x20, 0x61, 0x1e, 0x20, + 0xc7, 0xbb, 0x61, 0xda, 0x9f, 0x2b, 0x93, 0xa3, 0xf3, 0x3c, 0x3c, 0x6f, 0xae, 0x58, 0x68, 0x45, 0x2f, 0xce, 0xb1, + 0xdf, 0xb8, 0xf7, 0xbd, 0x8c, 0xa9, 0xe7, 0x61, 0xe3, 0xdd, 0x28, 0x4f, 0x4f, 0x30, 0x3a, 0x3f, 0x44, 0x37, 0x77, + 0xa4, 0xaf, 0xec, 0x02, 0xf4, 0x7a, 0x4f, 0x8e, 0xef, 0x67, 0xdf, 0x8b, 0x8e, 0x33, 0xb8, 0x30, 0xd2, 0x28, 0xce, + 0x17, 0x84, 0x96, 0x98, 0xa3, 0x34, 0xe3, 0x45, 0x3d, 0x11, 0x8e, 0x78, 0x79, 0x0a, 0x76, 0x2c, 0xec, 0xa6, 0x3f, + 0x17, 0xbe, 0xb0, 0xf0, 0xd7, 0xe9, 0x4c, 0xe0, 0x71, 0xff, 0x6f, 0x93, 0xfd, 0x82, 0x44, 0x22, 0x7a, 0x18, 0x47, + 0x7a, 0x6c, 0xcb, 0x42, 0xef, 0x99, 0xd8, 0x22, 0xf5, 0xfa, 0xfd, 0x84, 0x50, 0xea, 0x86, 0x52, 0xea, 0x0e, 0xca, + 0x64, 0x59, 0x02, 0x1b, 0x37, 0x85, 0x10, 0x72, 0xfc, 0x33, 0x6e, 0x9e, 0x22, 0x7c, 0xd6, 0x88, 0xd2, 0xac, 0xa6, + 0xa6, 0xe0, 0xce, 0x60, 0x00, 0x56, 0xe2, 0x04, 0x07, 0x88, 0xf2, 0xa1, 0x2e, 0xbc, 0xc2, 0xc4, 0x6a, 0x55, 0x56, + 0x02, 0xb5, 0xc2, 0x50, 0x82, 0x08, 0x4e, 0x68, 0x2f, 0x22, 0xac, 0xeb, 0x98, 0x94, 0x7b, 0xb0, 0x45, 0x3b, 0xb7, + 0xf0, 0xba, 0xdb, 0xc2, 0xca, 0xc3, 0x7b, 0x35, 0xeb, 0xb1, 0x2b, 0xbb, 0xe3, 0x01, 0x72, 0x94, 0x9c, 0xfd, 0x04, + 0x88, 0xe0, 0x41, 0x12, 0xd8, 0xea, 0xad, 0x3d, 0x6c, 0xed, 0x0e, 0xa1, 0xdf, 0x16, 0xf8, 0x74, 0x07, 0xcc, 0x46, + 0x69, 0x37, 0xfb, 0xfc, 0xa7, 0x0e, 0x0e, 0x4b, 0x6f, 0x02, 0x7c, 0x9d, 0xea, 0x4e, 0xd6, 0x74, 0x1b, 0xb8, 0xc7, + 0x3f, 0x7b, 0xe8, 0x8a, 0x44, 0x3a, 0x62, 0x16, 0xb7, 0x38, 0xaa, 0xcb, 0xce, 0xea, 0xae, 0x91, 0x73, 0x5b, 0x12, + 0x57, 0xa5, 0x84, 0xec, 0x72, 0x44, 0xa5, 0x24, 0x7b, 0x44, 0x19, 0x9c, 0xf6, 0xf6, 0xf2, 0xdc, 0x98, 0x7b, 0x18, + 0x67, 0x01, 0xa8, 0x09, 0x58, 0x2e, 0xc8, 0xc6, 0x3b, 0x01, 0x80, 0x51, 0x5a, 0x35, 0x75, 0x46, 0xef, 0xe2, 0x56, + 0x5d, 0x6f, 0x1e, 0x64, 0x46, 0x33, 0x51, 0x33, 0xb9, 0x3b, 0xa0, 0x8a, 0xd1, 0xc2, 0x20, 0xfb, 0xa5, 0x54, 0x7c, + 0x5a, 0x95, 0x68, 0xa5, 0x43, 0xcd, 0x68, 0xbf, 0xfb, 0x34, 0xd0, 0x51, 0x22, 0xb6, 0x5c, 0x4c, 0xbb, 0xf2, 0x76, + 0x98, 0x78, 0x1a, 0xd8, 0x2a, 0x33, 0x22, 0x4d, 0xd9, 0xc2, 0xcb, 0x11, 0x49, 0x7e, 0xd4, 0x5d, 0xb3, 0x6a, 0x52, + 0x1b, 0x67, 0x2d, 0x3c, 0xdd, 0x52, 0xe4, 0x14, 0x0a, 0x2e, 0xda, 0xee, 0x83, 0x0c, 0x82, 0x69, 0xd3, 0xc6, 0x59, + 0x6f, 0xbb, 0x2f, 0xa2, 0x8e, 0x57, 0x74, 0x5c, 0x24, 0x6c, 0x6e, 0xf7, 0x14, 0x65, 0x07, 0x89, 0xf2, 0x24, 0x26, + 0xd3, 0x91, 0x03, 0x95, 0xb4, 0xa1, 0xd4, 0xd2, 0x7b, 0xc9, 0x8a, 0x8b, 0xb8, 0xf8, 0xbf, 0xca, 0xb2, 0xad, 0x2f, + 0xbe, 0x48, 0xb0, 0xa0, 0x83, 0x39, 0xa2, 0xc0, 0x3c, 0x97, 0xd2, 0x41, 0x89, 0x44, 0x11, 0xf9, 0x49, 0xc1, 0xec, + 0xaa, 0x64, 0x0d, 0x3e, 0x68, 0xa5, 0x3b, 0x93, 0x49, 0x43, 0x22, 0xe5, 0x9a, 0xd4, 0xda, 0x16, 0x1b, 0x19, 0xf1, + 0xcc, 0x0f, 0x56, 0x89, 0x30, 0x12, 0x0f, 0x32, 0x25, 0x96, 0xc2, 0xb3, 0x85, 0x94, 0xf8, 0x22, 0x67, 0x9f, 0xeb, + 0xc5, 0x6e, 0xb4, 0xc8, 0x62, 0x7e, 0x98, 0xf9, 0xe5, 0x70, 0xb3, 0x5b, 0x11, 0xa3, 0xde, 0x9a, 0xb3, 0x3c, 0x2b, + 0x99, 0x8d, 0x6b, 0x47, 0x8e, 0xb9, 0x04, 0x1a, 0x29, 0x04, 0x0a, 0xe9, 0x93, 0x81, 0x53, 0x8b, 0xcb, 0x81, 0x0d, + 0x1a, 0xdf, 0xf1, 0xc9, 0xb3, 0xa5, 0xbb, 0x8b, 0xa1, 0x61, 0xdb, 0x21, 0x11, 0x44, 0x68, 0xbc, 0x21, 0xd1, 0x32, + 0x34, 0x3f, 0x78, 0x3a, 0xef, 0xcc, 0xf4, 0xea, 0x8e, 0xa4, 0x67, 0x69, 0xe1, 0x11, 0xe0, 0x7c, 0x52, 0x91, 0xe6, + 0xd6, 0x3e, 0xc9, 0x21, 0xeb, 0xfe, 0x45, 0xb3, 0x7e, 0x45, 0x00, 0x77, 0x92, 0x80, 0x10, 0xa0, 0xe1, 0x75, 0x6b, + 0x21, 0x8c, 0x25, 0xcc, 0x38, 0x84, 0xee, 0x2a, 0xf8, 0x6f, 0x12, 0xa6, 0xe7, 0xa5, 0x09, 0x8d, 0x2f, 0x4a, 0xc5, + 0x60, 0x27, 0x0b, 0x84, 0x5b, 0x40, 0x14, 0x04, 0x81, 0x20, 0x63, 0x16, 0x8a, 0xa9, 0x84, 0x76, 0xa0, 0x15, 0x14, + 0x48, 0x80, 0x89, 0x37, 0x4e, 0x85, 0x41, 0x55, 0x6d, 0xc5, 0xd3, 0x1c, 0xb3, 0xe1, 0xa4, 0x61, 0x50, 0x58, 0x7f, + 0x02, 0x5d, 0x9c, 0x62, 0x92, 0x0c, 0xfb, 0xbb, 0x78, 0xe3, 0xc9, 0xba, 0x9d, 0x89, 0x52, 0x29, 0xf6, 0x59, 0x93, + 0x27, 0x34, 0xc3, 0x79, 0x21, 0xea, 0xcb, 0xba, 0xb4, 0xee, 0x83, 0xd5, 0x74, 0x07, 0x4f, 0x9e, 0x75, 0xa4, 0xb7, + 0x71, 0x60, 0xb9, 0x83, 0x44, 0x80, 0x45, 0xda, 0x03, 0xcd, 0xc8, 0x32, 0x64, 0xa8, 0x02, 0xac, 0x35, 0xe6, 0x4e, + 0x0d, 0x6d, 0x0f, 0xe5, 0x46, 0x72, 0x6d, 0x12, 0xac, 0x1e, 0x96, 0xbe, 0xbc, 0xba, 0x6e, 0x73, 0x63, 0x00, 0xbb, + 0xef, 0xd8, 0xb2, 0xa0, 0xcb, 0x11, 0x19, 0x8e, 0x27, 0xb7, 0x09, 0xd5, 0x03, 0x14, 0x8a, 0x6a, 0xaa, 0x69, 0xed, + 0x1f, 0x7e, 0xe6, 0x9d, 0x38, 0xd4, 0x39, 0x21, 0x36, 0x2a, 0x8f, 0xd0, 0x31, 0x8f, 0x7d, 0xa2, 0xcf, 0x25, 0xef, + 0x69, 0xbe, 0x41, 0xea, 0xc8, 0xc5, 0xd5, 0x79, 0x92, 0xa8, 0x1b, 0x63, 0xb5, 0x15, 0x5b, 0x84, 0x01, 0x16, 0x73, + 0x0c, 0x87, 0xe8, 0x54, 0x70, 0xb4, 0x24, 0xbd, 0x8d, 0xa5, 0xea, 0xe5, 0xf6, 0xdb, 0xaa, 0x4b, 0x6b, 0xa7, 0x09, + 0x83, 0xe8, 0xf4, 0x90, 0x01, 0x07, 0x42, 0xc6, 0xda, 0x3e, 0x58, 0xc6, 0x71, 0x46, 0xeb, 0x32, 0x68, 0x04, 0x63, + 0xe8, 0x00, 0xe5, 0xac, 0x7a, 0x1c, 0xec, 0x04, 0x62, 0x79, 0x48, 0x6f, 0x9a, 0xcc, 0x00, 0xd9, 0x22, 0x97, 0x5f, + 0x6a, 0xa2, 0x9d, 0x85, 0x8e, 0x2d, 0xfb, 0x1e, 0xd0, 0xae, 0x03, 0x47, 0x5f, 0x07, 0x1c, 0x75, 0xe2, 0x45, 0x2d, + 0x85, 0x36, 0xc7, 0xc0, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x68, 0xc7, 0xbd, 0x03, 0xbc, 0x98, 0xd2, 0xf5, 0x02, + 0xfc, 0x76, 0x70, 0x19, 0xf8, 0xc4, 0x83, 0xdb, 0xea, 0xb0, 0x63, 0x67, 0x92, 0xc6, 0x79, 0x34, 0x75, 0x73, 0xce, + 0xb9, 0xd0, 0xe5, 0xdc, 0xff, 0x9e, 0x6e, 0xfd, 0xfe, 0x8a, 0xf1, 0x69, 0xad, 0x3d, 0x61, 0xb9, 0xca, 0x69, 0x97, + 0x45, 0x2c, 0x59, 0x71, 0x8e, 0xbe, 0x10, 0xc8, 0xd7, 0xeb, 0xfc, 0x7e, 0xa1, 0x41, 0xe7, 0xd4, 0x41, 0x74, 0x8e, + 0x71, 0xb2, 0xd3, 0x83, 0xc9, 0x7b, 0x65, 0x71, 0x68, 0xac, 0x52, 0x66, 0xf1, 0x7d, 0xe3, 0x96, 0xde, 0x9e, 0x50, + 0x76, 0x29, 0x85, 0x14, 0xca, 0xb2, 0xe1, 0xb6, 0xc7, 0x81, 0xa6, 0xed, 0x36, 0x92, 0xdd, 0xd6, 0xb7, 0xef, 0x34, + 0x89, 0x48, 0xd2, 0xdd, 0x05, 0x51, 0x78, 0x86, 0xd0, 0x18, 0x50, 0xb0, 0x37, 0xa7, 0xd6, 0xe5, 0x6b, 0x2f, 0x2b, + 0xf1, 0x8a, 0x78, 0x57, 0x0c, 0xc6, 0xca, 0x09, 0x1d, 0x2c, 0xd2, 0x34, 0x50, 0xc7, 0x4e, 0x92, 0xb8, 0x55, 0x49, + 0xfc, 0xd0, 0xf2, 0x2f, 0xa4, 0xb9, 0x51, 0x79, 0x2a, 0xe2, 0xeb, 0x10, 0x7d, 0xe6, 0xb8, 0x54, 0xf7, 0x46, 0x35, + 0x83, 0x72, 0xcc, 0x93, 0x79, 0xc3, 0x5c, 0xa6, 0xdb, 0x29, 0x32, 0x4f, 0xf6, 0xbc, 0xb9, 0x99, 0x51, 0xa2, 0x44, + 0xa4, 0x2e, 0xf4, 0x32, 0xd7, 0x56, 0xa1, 0x23, 0x8d, 0xd8, 0xb4, 0x56, 0xb3, 0x89, 0x3d, 0x0e, 0x67, 0x3f, 0x59, + 0xd9, 0x13, 0xbc, 0xeb, 0x3d, 0xef, 0xec, 0xc3, 0xe6, 0x82, 0xeb, 0xd0, 0x88, 0x21, 0x33, 0x60, 0xa6, 0x59, 0x3a, + 0x53, 0x20, 0x8b, 0xb8, 0xaf, 0xee, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0x75, 0x7d, 0xad, 0x54, 0x1d, 0x93, 0x1f, + 0xbe, 0xa3, 0x6b, 0x38, 0x77, 0x50, 0x94, 0x18, 0x4e, 0x34, 0xed, 0xe6, 0x52, 0x03, 0x10, 0x7e, 0x67, 0x87, 0x51, + 0x58, 0xc1, 0xb6, 0xa8, 0xb7, 0xea, 0x2a, 0x60, 0xa0, 0x86, 0x79, 0x32, 0xf6, 0x46, 0x11, 0x19, 0xf5, 0x1b, 0x76, + 0x23, 0xaf, 0x2c, 0xba, 0x65, 0x8d, 0xcf, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x0e, 0x0b, 0xe4, 0x86, 0xeb, + 0x42, 0x21, 0xa9, 0x37, 0x1c, 0x9b, 0x6d, 0x6b, 0xe6, 0x99, 0x06, 0xba, 0x6d, 0x4d, 0xef, 0x13, 0x3b, 0x70, 0xc3, + 0x6d, 0xdd, 0x30, 0x55, 0x6d, 0x3b, 0x8f, 0x5f, 0xef, 0xd3, 0x22, 0xac, 0x09, 0x6d, 0x18, 0xc6, 0x1a, 0xd8, 0xb6, + 0x45, 0x31, 0x17, 0x83, 0x98, 0xf6, 0xd8, 0x62, 0xdf, 0x81, 0x6c, 0xdf, 0xfd, 0xb5, 0x4a, 0x42, 0x4e, 0xae, 0xd2, + 0xf9, 0x35, 0xf9, 0x49, 0x27, 0x8b, 0x44, 0x66, 0x76, 0x91, 0xbf, 0xc6, 0x95, 0xfd, 0xa3, 0x95, 0xdd, 0xab, 0x95, + 0x2e, 0x52, 0x40, 0x14, 0xa6, 0xc2, 0x73, 0x08, 0x4c, 0x97, 0xac, 0xfc, 0x1f, 0xe8, 0x38, 0x27, 0x63, 0x4a, 0x68, + 0x6f, 0x34, 0x9a, 0x40, 0x37, 0x24, 0x14, 0x43, 0x0b, 0xcb, 0xe9, 0x79, 0xa9, 0x41, 0x57, 0x3b, 0x5c, 0x47, 0x96, + 0xfb, 0x22, 0xc0, 0x4f, 0x14, 0x50, 0x67, 0x6a, 0x82, 0xdd, 0x4f, 0x02, 0x63, 0x69, 0xd6, 0x59, 0xfa, 0x45, 0x87, + 0xd3, 0x15, 0x75, 0xf7, 0xf4, 0x2b, 0x86, 0x44, 0x77, 0xf8, 0x95, 0x42, 0xeb, 0x13, 0x33, 0x73, 0x81, 0x46, 0x3a, + 0x6e, 0x60, 0x10, 0x2e, 0x6a, 0x0b, 0xfe, 0x80, 0x5c, 0xc5, 0x4d, 0xe1, 0x6e, 0x72, 0x00, 0x97, 0xca, 0x6d, 0xcb, + 0xb3, 0x4a, 0x13, 0x98, 0x7d, 0x92, 0x32, 0x3a, 0x71, 0x8c, 0xba, 0x6f, 0x77, 0x3f, 0x4a, 0x52, 0xde, 0x3e, 0x7d, + 0xf3, 0x7a, 0x95, 0x35, 0xca, 0xde, 0x33, 0xb3, 0xd4, 0x55, 0xfc, 0xa9, 0x49, 0xee, 0x6a, 0xee, 0x3b, 0xe9, 0x56, + 0x20, 0x30, 0xca, 0x79, 0x85, 0xe5, 0xce, 0xb2, 0x90, 0xc3, 0xe6, 0x5e, 0xba, 0x4f, 0x4b, 0x9a, 0xec, 0x44, 0x55, + 0x62, 0x8c, 0x49, 0xa1, 0xfd, 0xf2, 0x74, 0xee, 0x8f, 0x0e, 0xdf, 0xa3, 0xa3, 0xbe, 0x4b, 0xd3, 0x72, 0xda, 0x8a, + 0xed, 0xf2, 0xc4, 0x0e, 0xa6, 0xe1, 0x9a, 0x30, 0x2d, 0x03, 0x84, 0xee, 0xea, 0x03, 0xe8, 0x5f, 0xe2, 0x1f, 0xfa, + 0xf1, 0x9c, 0xa2, 0x0f, 0xd0, 0x83, 0xd9, 0x9a, 0xca, 0x25, 0x6a, 0x50, 0x22, 0xb2, 0x4d, 0xbb, 0x34, 0x01, 0x53, + 0xe4, 0x20, 0xdd, 0x42, 0x06, 0xa2, 0x64, 0x21, 0x98, 0x41, 0xe5, 0x17, 0xf1, 0x3a, 0xf1, 0x75, 0xbe, 0x5a, 0xf0, + 0x92, 0x9e, 0x70, 0x55, 0xc8, 0xd5, 0x0d, 0xa3, 0xc5, 0xbc, 0x3a, 0xed, 0xa4, 0xda, 0x38, 0x34, 0xa8, 0x51, 0x87, + 0x48, 0xd7, 0xf1, 0xfe, 0x6f, 0x36, 0x52, 0x37, 0x18, 0xfd, 0xe4, 0x24, 0xe0, 0xfb, 0xc6, 0x48, 0xa5, 0xb3, 0x87, + 0x38, 0xb5, 0x16, 0x3c, 0x5e, 0x28, 0x7b, 0x34, 0xea, 0x11, 0xb5, 0xc6, 0x5e, 0x0e, 0x32, 0xad, 0x0d, 0x27, 0x85, + 0xd2, 0x79, 0xb8, 0x94, 0x77, 0x49, 0xe1, 0xd2, 0x1b, 0x95, 0x88, 0xf2, 0x00, 0x76, 0xc2, 0x96, 0x8a, 0x1b, 0x95, + 0xb4, 0x80, 0xea, 0x99, 0x9e, 0x0c, 0x89, 0xe9, 0x9c, 0x44, 0x8c, 0x19, 0x9e, 0xd2, 0xcd, 0x38, 0x44, 0x6b, 0x68, + 0x86, 0x3d, 0xbd, 0x8f, 0xd5, 0x13, 0xe4, 0x80, 0x9d, 0x8d, 0xeb, 0x0c, 0x21, 0x76, 0x52, 0xe1, 0x67, 0x6a, 0x55, + 0x6c, 0x99, 0x7f, 0x24, 0xa8, 0x6d, 0xf3, 0xb6, 0x8f, 0x88, 0xf2, 0xd6, 0xd2, 0x37, 0xb9, 0xbf, 0xe2, 0xca, 0x78, + 0x25, 0x81, 0x66, 0x96, 0x97, 0xfc, 0x1c, 0xe6, 0x67, 0xbf, 0xb1, 0x03, 0x13, 0x88, 0x38, 0xdb, 0x68, 0xd4, 0x53, + 0x72, 0x34, 0xd7, 0x39, 0xef, 0x5b, 0x70, 0x46, 0xc9, 0x34, 0x10, 0x62, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, 0x71, + 0x56, 0x38, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7a, 0x6f, 0x22, 0xf7, 0x45, 0x4d, 0x7a, 0x06, 0xfe, 0xd8, 0x51, 0x63, + 0x31, 0x8a, 0x6e, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0x43, 0xbd, 0xf4, 0x66, 0xae, 0xfd, 0xd2, 0xd3, 0x5a, 0xaa, + 0x0b, 0x74, 0x71, 0xe8, 0x31, 0x6a, 0x51, 0x5e, 0x41, 0x1a, 0x4c, 0x7b, 0xa0, 0xec, 0x35, 0x4c, 0xe8, 0x01, 0xbf, + 0x54, 0x82, 0x8c, 0x06, 0xef, 0x7c, 0xb4, 0xc5, 0xc5, 0x74, 0x92, 0xf3, 0x66, 0x01, 0x05, 0xb7, 0xeb, 0x2d, 0xa9, + 0x89, 0xd0, 0x1a, 0x37, 0x28, 0x6c, 0x91, 0xf0, 0x4f, 0x34, 0x87, 0xb3, 0x2b, 0x24, 0x75, 0x88, 0x4d, 0x31, 0xc2, + 0x04, 0xb4, 0x66, 0x5c, 0x6c, 0x68, 0x61, 0x37, 0xd1, 0x03, 0x6b, 0xf3, 0x20, 0x19, 0x87, 0x3b, 0x9a, 0x69, 0x33, + 0x90, 0x6b, 0x09, 0xfe, 0x2c, 0x11, 0xbd, 0xc3, 0xae, 0x0f, 0x77, 0x64, 0xd8, 0xdc, 0x12, 0xb2, 0x52, 0x66, 0x7a, + 0x78, 0x09, 0xb4, 0xeb, 0xb7, 0x8a, 0xed, 0x50, 0xc1, 0x9f, 0x22, 0x87, 0xa4, 0x98, 0x7e, 0x9f, 0xbd, 0x3a, 0x80, + 0x18, 0xc4, 0xa9, 0xd3, 0x7d, 0x53, 0x60, 0x9d, 0x43, 0x49, 0xb1, 0x21, 0x8c, 0x71, 0xc6, 0x51, 0xbb, 0xdb, 0xd1, + 0xc6, 0x7e, 0x24, 0x86, 0x40, 0xe9, 0xf0, 0xe5, 0x8e, 0x56, 0x5e, 0xb7, 0xb3, 0x75, 0xdb, 0x6b, 0xda, 0x91, 0x0f, + 0xc9, 0x11, 0x4c, 0x8a, 0x48, 0x5a, 0x36, 0x10, 0x9a, 0x31, 0x78, 0x8b, 0xb4, 0x60, 0x6d, 0xcf, 0x80, 0x96, 0xb9, + 0x5e, 0x28, 0xb4, 0xc0, 0xb3, 0x66, 0x0c, 0x4c, 0x0a, 0x8b, 0x0e, 0x2e, 0x69, 0xef, 0x74, 0x82, 0xd9, 0x40, 0xb5, + 0x5a, 0xdb, 0x6d, 0x59, 0xdf, 0x34, 0x0a, 0x84, 0xed, 0xbb, 0x72, 0x33, 0xfd, 0xc8, 0xcf, 0xac, 0x05, 0xf0, 0x55, + 0x6c, 0xbb, 0xce, 0x83, 0x76, 0x5f, 0x5b, 0xe5, 0xde, 0xc7, 0xfe, 0x5a, 0xe2, 0xc7, 0x50, 0xc3, 0xb2, 0x74, 0xc2, + 0x74, 0x65, 0x50, 0xbc, 0xe5, 0x9a, 0xfb, 0xc2, 0xc6, 0x64, 0x7a, 0x87, 0x12, 0x9b, 0xf8, 0xba, 0xb3, 0x1b, 0xcc, + 0x2d, 0x23, 0x7a, 0x59, 0xbf, 0xd3, 0xb7, 0xb2, 0xb5, 0xeb, 0x01, 0x88, 0xa9, 0x57, 0x96, 0x8c, 0x87, 0x19, 0x5d, + 0x3c, 0x04, 0xa5, 0xc9, 0x6b, 0x54, 0x92, 0xc1, 0x67, 0xf5, 0xae, 0x85, 0x44, 0xe4, 0xdb, 0x7a, 0x95, 0x27, 0xb3, + 0x91, 0x0d, 0xc7, 0xae, 0xa7, 0xe5, 0x81, 0x90, 0x32, 0x9a, 0xfd, 0x6d, 0x93, 0xd6, 0x5c, 0x4b, 0xc3, 0x2f, 0x91, + 0xe2, 0xa2, 0xd9, 0x38, 0xca, 0x36, 0x12, 0x04, 0x5d, 0xd5, 0x42, 0xb2, 0x58, 0x78, 0x58, 0xc8, 0x50, 0xbe, 0xac, + 0x84, 0x65, 0x2f, 0xee, 0xa6, 0x13, 0xf9, 0xe6, 0xc6, 0xcd, 0x8f, 0x42, 0xdb, 0xad, 0xaf, 0xdd, 0xf5, 0x43, 0x1b, + 0x51, 0x56, 0xbf, 0xe8, 0xc1, 0x57, 0xaa, 0xb1, 0x3e, 0xb2, 0xfe, 0xff, 0xa1, 0x9f, 0xd4, 0x89, 0xe4, 0xcc, 0x69, + 0x3b, 0x60, 0x7b, 0xa6, 0x80, 0xad, 0xd0, 0xf6, 0xb0, 0xa9, 0xf4, 0xfe, 0xce, 0x25, 0x81, 0x5c, 0x88, 0xf8, 0x84, + 0x85, 0x40, 0x92, 0xe2, 0x91, 0x4e, 0x03, 0x4c, 0x2d, 0x03, 0xea, 0x11, 0xec, 0xfb, 0xc1, 0x8e, 0x7c, 0xf3, 0x92, + 0xed, 0xf2, 0xb6, 0xee, 0x27, 0x28, 0xeb, 0x3e, 0x0f, 0x81, 0x8d, 0xdb, 0xd2, 0xe5, 0x80, 0x49, 0x1c, 0xc8, 0xc4, + 0x4c, 0xfb, 0x65, 0x6a, 0x2f, 0xdf, 0x2a, 0x67, 0x9c, 0xa0, 0x5b, 0x8a, 0x5a, 0x0e, 0x29, 0x71, 0x48, 0x5b, 0x79, + 0xe7, 0x86, 0xbd, 0x91, 0x7e, 0x88, 0x73, 0x8b, 0x1e, 0x07, 0x46, 0xd4, 0x69, 0xce, 0x66, 0x21, 0x42, 0x4d, 0xae, + 0x1a, 0xe5, 0xf1, 0x03, 0x57, 0xe9, 0x5a, 0xaa, 0xee, 0x2b, 0x94, 0xcc, 0x9e, 0x08, 0x93, 0x39, 0xb4, 0x3b, 0x64, + 0x49, 0x89, 0x66, 0x1f, 0xbb, 0x75, 0x40, 0x60, 0x27, 0x60, 0x9e, 0x96, 0xc8, 0xeb, 0x94, 0x4c, 0xfc, 0xf6, 0xed, + 0x3f, 0xca, 0xeb, 0x08, 0x86, 0xbd, 0xe4, 0x30, 0xa7, 0x02, 0x11, 0xc7, 0x71, 0xfe, 0xbc, 0x91, 0x0b, 0x12, 0x63, + 0xfd, 0xf9, 0x6b, 0xac, 0x5c, 0x23, 0x81, 0x56, 0x49, 0x43, 0xe1, 0x99, 0x1b, 0x67, 0xae, 0xec, 0xd4, 0xb3, 0x8c, + 0x2b, 0x76, 0x5b, 0xf4, 0x93, 0xc8, 0xa3, 0x16, 0xcd, 0x94, 0x1e, 0xa9, 0x72, 0x91, 0x94, 0xb4, 0xca, 0xa1, 0x96, + 0x6c, 0x05, 0xca, 0x61, 0x72, 0x2c, 0xe3, 0x3a, 0x73, 0x1a, 0x9a, 0xb3, 0x2c, 0x01, 0x72, 0x8b, 0x25, 0x38, 0xc7, + 0x4c, 0x2e, 0xc3, 0x4a, 0x2a, 0x24, 0x60, 0x1c, 0x84, 0xc2, 0x4f, 0xfe, 0xb1, 0xd2, 0xfe, 0x4e, 0x86, 0x5c, 0x62, + 0xf8, 0x0b, 0x1f, 0x93, 0x9e, 0x2b, 0x1f, 0x0a, 0x66, 0xb0, 0x18, 0xa2, 0xb7, 0x8c, 0x60, 0x5b, 0xee, 0xc4, 0x5b, + 0x34, 0xcb, 0xd2, 0xb9, 0x7f, 0x81, 0x66, 0xdd, 0xac, 0xd5, 0x7d, 0x8b, 0x22, 0xaf, 0x67, 0x4c, 0x9a, 0x70, 0xd2, + 0x4a, 0xa9, 0x94, 0xa6, 0xa0, 0x23, 0x4a, 0x32, 0x01, 0xcc, 0x0c, 0x50, 0xb2, 0x93, 0x8c, 0x4a, 0x0f, 0xca, 0xc9, + 0x70, 0x62, 0x31, 0xd3, 0xe8, 0x2c, 0x06, 0xac, 0x5e, 0x35, 0x3e, 0xce, 0x27, 0x1d, 0xff, 0x03, 0x40, 0xf5, 0xb5, + 0xd7, 0x82, 0xd7, 0x3c, 0x97, 0x93, 0xae, 0xe9, 0xba, 0x3a, 0xf6, 0x3f, 0xee, 0x45, 0x57, 0x50, 0x35, 0x66, 0xbf, + 0xd8, 0x5f, 0xd2, 0x38, 0x0c, 0x13, 0x62, 0x7c, 0x70, 0x1f, 0x70, 0xd4, 0x01, 0x5b, 0xac, 0x7a, 0x72, 0x91, 0x64, + 0x96, 0xa4, 0xb7, 0xb9, 0xe8, 0x3a, 0x7e, 0x70, 0x60, 0xa8, 0x2e, 0x6d, 0xba, 0xe7, 0x91, 0x15, 0x6f, 0x8d, 0x25, + 0xc0, 0x52, 0xcc, 0x81, 0x2e, 0x18, 0x1d, 0xaf, 0x08, 0xce, 0xb6, 0x13, 0x20, 0x0a, 0x63, 0x2d, 0x8a, 0x2c, 0x4e, + 0xf8, 0x5b, 0xd2, 0x26, 0x60, 0x4b, 0xc6, 0x28, 0x8d, 0x7d, 0x0e, 0xce, 0x95, 0xf9, 0xe0, 0xb1, 0xea, 0x17, 0x75, + 0xba, 0xba, 0x0c, 0xb1, 0xcf, 0x4f, 0x72, 0x79, 0xfd, 0x1d, 0xea, 0x4b, 0xbf, 0x8d, 0xd2, 0x17, 0x78, 0x67, 0x09, + 0x39, 0xef, 0x5e, 0xff, 0x54, 0xb4, 0x38, 0x30, 0x0b, 0x5d, 0xc5, 0x16, 0xb5, 0xe0, 0xfc, 0xe9, 0x85, 0x44, 0x14, + 0x65, 0x8f, 0x09, 0x90, 0xa9, 0xa6, 0xac, 0x7e, 0x53, 0xa4, 0x40, 0xc6, 0x45, 0x55, 0x9c, 0x3c, 0x06, 0xdf, 0xce, + 0x37, 0x77, 0x94, 0xc1, 0x68, 0xc8, 0xba, 0x5f, 0xef, 0xd8, 0xc4, 0x6f, 0xc4, 0xfc, 0x8f, 0x09, 0x27, 0xbd, 0x7a, + 0x4a, 0x80, 0x4a, 0xda, 0x49, 0x2a, 0x7d, 0x50, 0xe0, 0x85, 0x89, 0x26, 0x67, 0xa8, 0x41, 0x56, 0x78, 0x02, 0x9d, + 0x01, 0xcb, 0xd8, 0x62, 0x4a, 0xd9, 0x6d, 0x9b, 0xf8, 0x19, 0x85, 0x37, 0xb6, 0xb5, 0xd5, 0x18, 0xa4, 0xa7, 0x0a, + 0xd0, 0xf6, 0x38, 0x53, 0x85, 0x67, 0xd1, 0x85, 0x73, 0x6e, 0xde, 0x39, 0x70, 0x3e, 0xac, 0xcd, 0xc3, 0x97, 0xbf, + 0x20, 0x07, 0x85, 0x5d, 0x93, 0x3a, 0xa8, 0xea, 0x9a, 0x97, 0x74, 0xc2, 0x3f, 0x61, 0x7b, 0x89, 0xc5, 0x4c, 0x5e, + 0xd2, 0x7e, 0x0a, 0x1d, 0x21, 0x6d, 0x1e, 0x3a, 0xcd, 0xf6, 0x6f, 0x8a, 0x99, 0x1c, 0x2f, 0xb6, 0x9a, 0xfd, 0xb2, + 0x31, 0xfe, 0x2d, 0x92, 0x02, 0xee, 0x2b, 0xe7, 0xc3, 0x2a, 0x32, 0x89, 0x3a, 0xae, 0x8d, 0x17, 0x94, 0x3e, 0x86, + 0xe9, 0x68, 0xb1, 0xea, 0xb2, 0x8c, 0x7b, 0xa5, 0xcc, 0x91, 0x51, 0x82, 0xc3, 0x53, 0x55, 0x44, 0x15, 0x3a, 0xaf, + 0x21, 0x2f, 0xcd, 0xfc, 0xba, 0x4a, 0x45, 0xe8, 0x43, 0x99, 0x73, 0xce, 0x5b, 0xa2, 0xee, 0x7a, 0xa2, 0xf8, 0x71, + 0x81, 0x42, 0x5b, 0x22, 0x8c, 0x7c, 0x70, 0x06, 0xa7, 0x49, 0x82, 0x47, 0x26, 0x22, 0x8f, 0x3c, 0xc5, 0xf5, 0x8b, + 0x51, 0x49, 0x2f, 0x2f, 0xe1, 0x91, 0x73, 0x97, 0xc5, 0xdd, 0x47, 0xfc, 0x5a, 0x7d, 0x89, 0x3e, 0x2c, 0xe1, 0x28, + 0x88, 0x95, 0x76, 0xbf, 0x0c, 0x9f, 0xd4, 0x81, 0xca, 0xf9, 0x3f, 0xa8, 0xbf, 0x86, 0x2c, 0xb2, 0x88, 0x26, 0xeb, + 0x0a, 0x73, 0x70, 0xd4, 0x0f, 0x8b, 0x10, 0xf9, 0x22, 0x43, 0x48, 0x16, 0xdd, 0xea, 0xe5, 0x21, 0xb4, 0x9e, 0xfc, + 0xdd, 0x32, 0xf7, 0xfb, 0xbb, 0x6a, 0x7a, 0x38, 0x8d, 0x14, 0xfc, 0x48, 0x45, 0x5f, 0x76, 0x75, 0x7b, 0x12, 0xdf, + 0xf5, 0x7c, 0x0f, 0x01, 0xb3, 0x8f, 0x34, 0x44, 0xf2, 0x66, 0xd9, 0x3a, 0xf4, 0x4d, 0x6c, 0x71, 0x45, 0x6b, 0xd0, + 0xa5, 0xd4, 0xf4, 0x51, 0x81, 0x33, 0xbc, 0x12, 0x74, 0x90, 0xe1, 0x68, 0xb9, 0xf2, 0xa6, 0x42, 0xb0, 0x38, 0xa9, + 0xda, 0x6e, 0x8b, 0x32, 0xdb, 0x33, 0x38, 0x89, 0x16, 0x51, 0x93, 0x99, 0xfc, 0x3e, 0x7d, 0x14, 0xab, 0xdc, 0x28, + 0x82, 0x3b, 0xfa, 0xc2, 0x2a, 0xad, 0xbd, 0x34, 0xe4, 0x97, 0x5a, 0xb2, 0x85, 0x06, 0x54, 0x4a, 0x79, 0xa1, 0x6a, + 0x5c, 0x2e, 0x85, 0x2b, 0x63, 0x6b, 0xf4, 0x30, 0xd3, 0xaa, 0x78, 0x15, 0x57, 0x48, 0xc7, 0xd7, 0x88, 0x45, 0xe8, + 0xb2, 0x0c, 0x12, 0x1e, 0xce, 0x72, 0x2e, 0x79, 0x72, 0x0d, 0x56, 0x3c, 0xb7, 0x60, 0x0e, 0x66, 0x5d, 0xab, 0x27, + 0xd5, 0xd8, 0x80, 0x91, 0x14, 0xf9, 0x2a, 0xa6, 0x73, 0xd5, 0x01, 0x75, 0x5c, 0x43, 0x60, 0x16, 0xee, 0x23, 0x3f, + 0x4a, 0x49, 0xaf, 0x94, 0x91, 0x33, 0xdc, 0x56, 0x49, 0x36, 0xe3, 0x64, 0x24, 0xdc, 0xd1, 0xc6, 0xce, 0x45, 0x01, + 0x3f, 0x0a, 0x39, 0x53, 0x02, 0x1a, 0xd2, 0x10, 0x49, 0x2e, 0x76, 0xcf, 0x13, 0xab, 0x21, 0xd2, 0x93, 0x05, 0x05, + 0x10, 0x79, 0x58, 0xfb, 0x60, 0x49, 0x79, 0x34, 0xb5, 0x80, 0x89, 0x79, 0xae, 0xfc, 0xa8, 0xbd, 0x85, 0xaf, 0xd6, + 0xa1, 0x04, 0xcc, 0xe1, 0xcb, 0x24, 0xd6, 0x4a, 0x9b, 0xf1, 0xb8, 0x2c, 0x8f, 0xca, 0x5b, 0xcb, 0x6a, 0xba, 0xa2, + 0x7a, 0xd0, 0x98, 0x1e, 0xae, 0x53, 0x62, 0x6c, 0x2c, 0xb3, 0x4e, 0x5c, 0x2a, 0xe6, 0xbf, 0x4f, 0x5f, 0xaa, 0x8b, + 0xaa, 0x96, 0x6f, 0x23, 0xae, 0x67, 0x8c, 0x6a, 0x51, 0xc3, 0x03, 0xe6, 0x5f, 0x96, 0x31, 0x2c, 0xd7, 0x04, 0xb3, + 0x5c, 0x13, 0xbd, 0xad, 0x86, 0xa0, 0xed, 0x78, 0x14, 0x95, 0xa0, 0x1b, 0x31, 0xa0, 0x91, 0x52, 0x23, 0x60, 0x9b, + 0x14, 0x62, 0xf0, 0x1b, 0xb0, 0x3f, 0x76, 0x08, 0x48, 0x05, 0x47, 0xf0, 0x80, 0x70, 0xc9, 0x71, 0xf9, 0x61, 0xd2, + 0xdd, 0x42, 0x02, 0xa9, 0x78, 0x39, 0x2b, 0x9f, 0x96, 0x08, 0x46, 0x31, 0x28, 0x8b, 0xd0, 0x0c, 0x91, 0x52, 0x37, + 0x2b, 0x32, 0xea, 0xe0, 0x8d, 0xc1, 0x37, 0x22, 0x06, 0xbc, 0x52, 0x50, 0xc8, 0x63, 0x4e, 0x4e, 0x96, 0xcb, 0xd7, + 0xb9, 0x4b, 0x7f, 0x47, 0x4f, 0xe5, 0x38, 0x75, 0x47, 0xd0, 0xa6, 0x8f, 0x62, 0x9c, 0x8b, 0x4a, 0x82, 0xeb, 0xe5, + 0xb4, 0xf7, 0x98, 0xd1, 0x7c, 0xe1, 0xea, 0x69, 0x3c, 0x68, 0x8b, 0xdf, 0x8f, 0x39, 0xfb, 0xf0, 0x29, 0x35, 0xba, + 0x80, 0x02, 0x0f, 0x3b, 0x75, 0xdb, 0xc8, 0x29, 0x46, 0x80, 0xbf, 0xad, 0xaf, 0xc7, 0xa3, 0xcd, 0x96, 0xb9, 0x20, + 0x35, 0xec, 0x1b, 0x7c, 0x39, 0x18, 0x7f, 0x45, 0xb4, 0xc3, 0xd7, 0x64, 0xdd, 0x43, 0x83, 0xee, 0x5e, 0xd6, 0xf0, + 0x05, 0x0b, 0x74, 0x7e, 0x89, 0x21, 0x6f, 0xd9, 0x81, 0xe5, 0x3e, 0xcf, 0xf5, 0x04, 0x99, 0xc6, 0xc3, 0x78, 0x0d, + 0xc8, 0x35, 0x9e, 0xe5, 0xbd, 0x1b, 0xf5, 0x7b, 0xb6, 0x9c, 0x77, 0xc4, 0xd6, 0xd4, 0xbb, 0x6c, 0x03, 0x8c, 0xa3, + 0xea, 0x7f, 0xdf, 0x54, 0x22, 0x18, 0x99, 0xa1, 0x7d, 0x5a, 0xeb, 0xa3, 0xca, 0xd3, 0xff, 0x37, 0xb3, 0x75, 0x61, + 0x65, 0x98, 0x43, 0x30, 0xe3, 0x2b, 0x7c, 0x9a, 0x71, 0x1e, 0x44, 0x78, 0x20, 0xed, 0x5e, 0x66, 0x37, 0xd6, 0x9c, + 0xd1, 0x8f, 0xd0, 0x9d, 0x92, 0xec, 0x02, 0xc7, 0xf1, 0x6f, 0x83, 0x9e, 0x0a, 0xb5, 0x1f, 0xd5, 0x81, 0xc5, 0xdf, + 0x05, 0xa9, 0x09, 0xc9, 0x50, 0x80, 0x03, 0xb9, 0x6a, 0xd9, 0x7b, 0xba, 0x9d, 0x5d, 0x4c, 0x13, 0xc4, 0xa5, 0xb3, + 0xd5, 0x97, 0xd7, 0xad, 0x17, 0x68, 0xdf, 0xec, 0xfd, 0x68, 0x63, 0xa6, 0x98, 0xc7, 0xeb, 0xbb, 0xa6, 0xe3, 0x37, + 0x14, 0x86, 0xd6, 0xf8, 0x2a, 0x62, 0xba, 0x6f, 0x68, 0xde, 0xcb, 0xb5, 0x37, 0xed, 0x3d, 0x7e, 0xb1, 0xd7, 0xea, + 0x2c, 0xb0, 0xf1, 0x46, 0x01, 0x57, 0x26, 0x2e, 0x67, 0x94, 0xe4, 0xc3, 0x0d, 0x82, 0xeb, 0xf8, 0xd1, 0xaa, 0x19, + 0xee, 0x7a, 0x7c, 0xa3, 0x13, 0x96, 0x61, 0x60, 0xba, 0x85, 0xeb, 0x40, 0x8c, 0x61, 0x6c, 0x11, 0x42, 0x91, 0xfa, + 0x91, 0xc6, 0x30, 0x0a, 0xc6, 0xcf, 0x4f, 0xd6, 0x98, 0xd9, 0xf1, 0x1f, 0x51, 0x00, 0xae, 0x5d, 0x84, 0x23, 0x30, + 0xcc, 0x2c, 0xa8, 0x50, 0xe1, 0x42, 0x1f, 0x89, 0x2b, 0x9b, 0xb2, 0xa7, 0xf0, 0x02, 0xf2, 0x25, 0xa6, 0xfd, 0x51, + 0xd7, 0xf9, 0x83, 0x13, 0xf9, 0x49, 0xed, 0xee, 0xf7, 0x4a, 0xb7, 0x17, 0xe1, 0x32, 0xd3, 0x75, 0xc4, 0x00, 0xc9, + 0x63, 0x30, 0xc1, 0x68, 0x31, 0x64, 0xc7, 0x4d, 0xed, 0x59, 0x9d, 0xce, 0xc9, 0xf1, 0xe0, 0x7f, 0xad, 0x82, 0xd9, + 0xf8, 0x28, 0xde, 0x56, 0x8d, 0x9c, 0xed, 0x49, 0xba, 0xf9, 0x63, 0xa5, 0xc9, 0xec, 0xff, 0x61, 0x7e, 0x9d, 0x05, + 0x0b, 0xe6, 0x8b, 0x45, 0x8b, 0xac, 0x21, 0x6a, 0x80, 0x1f, 0xee, 0x34, 0xa6, 0x7c, 0x46, 0x19, 0x61, 0xab, 0x5a, + 0x2b, 0x6d, 0x68, 0x80, 0xe6, 0x94, 0x9d, 0x20, 0x45, 0x09, 0x24, 0xef, 0x58, 0x85, 0x91, 0xf9, 0xc0, 0x30, 0x78, + 0xec, 0x7d, 0x6a, 0xdd, 0x9a, 0xa2, 0xae, 0xf0, 0x3e, 0xd1, 0xd8, 0x8d, 0x59, 0x29, 0xf5, 0x73, 0x2b, 0xf4, 0x1f, + 0xd1, 0x0b, 0x11, 0x58, 0x22, 0x3f, 0x04, 0xf5, 0x93, 0xa0, 0x96, 0xf5, 0x27, 0x95, 0xb7, 0x7c, 0x6e, 0xcf, 0x2e, + 0xb6, 0xe5, 0xd3, 0x5c, 0x67, 0x20, 0xb1, 0x33, 0xbe, 0xa9, 0x2f, 0xbe, 0x48, 0xb5, 0x96, 0x5b, 0xba, 0xe5, 0xd1, + 0x34, 0xc4, 0xe8, 0x00, 0x80, 0x94, 0x01, 0xe3, 0x27, 0xf8, 0x81, 0x3a, 0xe3, 0x9f, 0xcf, 0x6f, 0xea, 0x9c, 0xea, + 0xaf, 0xde, 0x48, 0xe8, 0x2d, 0x2d, 0x01, 0xdf, 0x85, 0xfc, 0xdf, 0xfe, 0x95, 0x6e, 0x1d, 0x63, 0x45, 0x60, 0x76, + 0x70, 0x75, 0x92, 0x9d, 0xe9, 0x69, 0x6b, 0xe2, 0x2a, 0x06, 0xef, 0x87, 0x68, 0x9d, 0xfb, 0x91, 0xc0, 0x68, 0x0a, + 0x6f, 0xb3, 0xd8, 0xb4, 0x55, 0xae, 0x57, 0x33, 0x61, 0xb6, 0x8d, 0x2e, 0x91, 0x1a, 0x82, 0xeb, 0x7d, 0x2c, 0xa3, + 0x8b, 0x27, 0x83, 0xb3, 0xba, 0xbe, 0x64, 0x2a, 0xc0, 0x85, 0x14, 0xf5, 0x27, 0xca, 0xb2, 0xdd, 0xa3, 0x2e, 0x35, + 0xdd, 0x1f, 0xb4, 0x76, 0xcf, 0xa5, 0xc5, 0x36, 0x5d, 0x36, 0x7d, 0x6a, 0x3d, 0x10, 0xc1, 0xbe, 0xa5, 0x1b, 0xf6, + 0x02, 0x00, 0x1d, 0xe0, 0x85, 0x6a, 0x13, 0x5d, 0x57, 0xfd, 0x63, 0x0f, 0x48, 0x6b, 0x7c, 0x8f, 0x4d, 0xaa, 0xdc, + 0xc8, 0xa4, 0xda, 0x45, 0x82, 0xb2, 0xc3, 0xf8, 0xf8, 0x0e, 0x7b, 0xad, 0x87, 0x17, 0x6a, 0x55, 0x0a, 0x6b, 0xcb, + 0xdc, 0x9b, 0x31, 0xa9, 0x69, 0xeb, 0x0f, 0x5e, 0x0b, 0xeb, 0x86, 0x2e, 0x85, 0xcb, 0xe2, 0x51, 0xab, 0x03, 0x90, + 0x93, 0x0d, 0x84, 0x70, 0xc4, 0xd3, 0x3f, 0x92, 0x9c, 0x02, 0xbc, 0x0e, 0xdc, 0x15, 0xc7, 0xec, 0xb2, 0x1d, 0x77, + 0xc3, 0x96, 0x5b, 0xf8, 0xb3, 0x5b, 0x20, 0xc5, 0xba, 0xea, 0xdc, 0xb0, 0x83, 0xd7, 0x65, 0x8a, 0xa0, 0x54, 0x48, + 0x40, 0x38, 0x5c, 0xce, 0x2e, 0x05, 0xa1, 0x24, 0x60, 0xac, 0x0a, 0xf7, 0x87, 0xb2, 0xb7, 0xdd, 0x6e, 0xd8, 0x92, + 0x47, 0x92, 0x61, 0xa0, 0x6a, 0x3d, 0xa6, 0xf5, 0xaf, 0x76, 0x3a, 0x81, 0x4a, 0xd6, 0x6c, 0x7a, 0xa4, 0x7f, 0x58, + 0x8f, 0xf4, 0x52, 0xf0, 0x48, 0xc4, 0xe2, 0x1d, 0x19, 0xa3, 0xab, 0x1f, 0x2f, 0x90, 0xd9, 0x3b, 0x2e, 0x7e, 0x98, + 0xc3, 0xda, 0xb0, 0xcb, 0x80, 0x27, 0x98, 0x49, 0x83, 0x7a, 0xd5, 0x55, 0xf4, 0x54, 0x90, 0x0e, 0x8b, 0x86, 0x81, + 0x85, 0x53, 0xea, 0x57, 0xe9, 0x2d, 0x6f, 0x74, 0x16, 0x34, 0x86, 0x12, 0x2d, 0x65, 0xa1, 0x2c, 0x37, 0x93, 0x87, + 0x0d, 0x25, 0x2b, 0xae, 0xa9, 0x6d, 0x67, 0xab, 0x68, 0xd1, 0x0a, 0xc2, 0x1f, 0xd7, 0x30, 0x23, 0xea, 0x2f, 0x64, + 0x9a, 0x75, 0x3b, 0xfc, 0x0c, 0x69, 0xb5, 0xa4, 0x76, 0x6e, 0x81, 0xf6, 0x82, 0x06, 0xfc, 0x1a, 0x82, 0xd6, 0x92, + 0x52, 0x13, 0x9f, 0xd6, 0xb9, 0xe0, 0xf1, 0x86, 0xe1, 0xd3, 0x26, 0xa9, 0x97, 0xd9, 0xc6, 0xd5, 0x0d, 0x4f, 0x73, + 0x29, 0x3a, 0x18, 0x74, 0x90, 0x90, 0x52, 0x73, 0xa8, 0xc8, 0xdf, 0x5d, 0xac, 0x0b, 0xa7, 0x09, 0xc9, 0x66, 0x2a, + 0x59, 0x4e, 0x4a, 0xf6, 0x8c, 0x10, 0x47, 0x3f, 0x20, 0x65, 0xf2, 0x08, 0x35, 0xc9, 0xab, 0x17, 0x90, 0xc9, 0xeb, + 0x51, 0x4b, 0x8a, 0x0b, 0x6d, 0x32, 0xb1, 0x14, 0x70, 0x32, 0x8e, 0x20, 0x13, 0xac, 0xa7, 0x64, 0x75, 0x0d, 0x90, + 0xf4, 0x92, 0x3c, 0x35, 0xb0, 0x60, 0x6a, 0xef, 0x94, 0x02, 0x8b, 0x14, 0x80, 0xa1, 0x9d, 0x34, 0x2a, 0x4b, 0xf2, + 0x58, 0x76, 0xdf, 0x96, 0x65, 0x4f, 0xa1, 0xa0, 0x60, 0xc4, 0xd9, 0x63, 0x9f, 0x9d, 0x05, 0x82, 0xf2, 0x70, 0x06, + 0x65, 0xfa, 0x9c, 0x60, 0x23, 0xcf, 0x11, 0x2c, 0xf2, 0x62, 0x40, 0x8e, 0x2a, 0x5e, 0xd6, 0x08, 0xff, 0xd5, 0x02, + 0xb9, 0xc0, 0xe0, 0xe1, 0x9e, 0x74, 0x7a, 0xad, 0xdf, 0x94, 0x53, 0x50, 0x30, 0xfa, 0x94, 0xd5, 0xcd, 0x38, 0x37, + 0xd4, 0x32, 0x9a, 0x31, 0xf5, 0x67, 0xee, 0xe2, 0x49, 0xbe, 0x55, 0x32, 0xa3, 0x22, 0x93, 0x89, 0x17, 0x7e, 0x00, + 0x3b, 0x3f, 0x2f, 0x26, 0x06, 0x85, 0x27, 0x2e, 0xea, 0x98, 0x11, 0x87, 0xb8, 0x2a, 0x27, 0xbf, 0x2d, 0xc0, 0xa8, + 0xc1, 0x60, 0x72, 0x8b, 0x7a, 0x4d, 0xa9, 0xf7, 0x50, 0x9f, 0x19, 0x0c, 0xb5, 0x71, 0xac, 0x57, 0x56, 0x82, 0x0d, + 0x0d, 0x2f, 0xf9, 0x54, 0xcd, 0x3a, 0x8c, 0x15, 0x7e, 0xa5, 0x02, 0xcc, 0x05, 0xa6, 0x79, 0x1a, 0x87, 0x80, 0x95, + 0x96, 0x6a, 0x18, 0x7d, 0x75, 0xee, 0x10, 0x4a, 0xdd, 0xe8, 0x05, 0x6c, 0x00, 0xc3, 0x21, 0xa2, 0x2d, 0x7a, 0x79, + 0xe1, 0x2b, 0x0d, 0x52, 0xb5, 0x23, 0x4b, 0x5e, 0x1d, 0x72, 0x22, 0x8f, 0x27, 0xe2, 0x7f, 0x26, 0x0c, 0x49, 0x9b, + 0x1b, 0x88, 0xb7, 0x94, 0xdd, 0xd4, 0x71, 0x9a, 0x39, 0x48, 0xef, 0xe9, 0x60, 0xaf, 0x95, 0xaf, 0x6c, 0x93, 0x19, + 0x7a, 0x35, 0x1a, 0x87, 0x82, 0xb4, 0xbc, 0x98, 0x2d, 0x32, 0x69, 0x12, 0xdd, 0x96, 0x16, 0x03, 0x7a, 0x88, 0xec, + 0xcc, 0x43, 0xb1, 0xe2, 0x7d, 0x3d, 0x99, 0x16, 0x14, 0x1d, 0xc2, 0x2d, 0xe4, 0x26, 0x1a, 0xf5, 0x13, 0x5d, 0xb5, + 0x2b, 0x94, 0xd9, 0x7e, 0x26, 0x74, 0x80, 0x97, 0x16, 0x27, 0x00, 0xec, 0xd1, 0x34, 0x2e, 0xb8, 0x6d, 0x09, 0xc3, + 0xd4, 0x86, 0x6a, 0x2e, 0x3b, 0xdd, 0xd6, 0x99, 0x5c, 0x0b, 0x14, 0x83, 0x00, 0x3a, 0xcf, 0x37, 0xef, 0x4f, 0x5e, + 0xfe, 0x0c, 0xc7, 0xb1, 0x83, 0xd1, 0xc9, 0x8c, 0xaa, 0xb8, 0x4d, 0xa2, 0xde, 0x6f, 0xe9, 0xa6, 0x81, 0xbc, 0xef, + 0x41, 0x35, 0x7b, 0xd6, 0xef, 0x4e, 0xd7, 0xc6, 0x3b, 0xf5, 0x9b, 0xd9, 0x00, 0xa0, 0xbc, 0x48, 0x9a, 0x0f, 0x70, + 0xdc, 0xe0, 0xe7, 0x19, 0xab, 0x15, 0x6a, 0x24, 0x22, 0x88, 0x02, 0x12, 0xa6, 0xfe, 0x59, 0x38, 0xbc, 0xc7, 0x77, + 0x2c, 0x3b, 0x51, 0x70, 0x48, 0xea, 0xab, 0xc1, 0xd1, 0x83, 0x6e, 0x4c, 0x05, 0xc3, 0x1a, 0xe3, 0x84, 0x9b, 0x6f, + 0xb1, 0xef, 0x5a, 0x2b, 0x8a, 0xeb, 0xc2, 0x3e, 0xf7, 0x9d, 0xa2, 0x9e, 0x7d, 0x76, 0x43, 0x8f, 0xf3, 0xe0, 0x15, + 0x53, 0x56, 0x29, 0xd6, 0x5d, 0x8e, 0x3c, 0x3e, 0x01, 0x52, 0xf3, 0x5d, 0xc9, 0xdf, 0x60, 0xac, 0x20, 0x0a, 0xbc, + 0x5f, 0x6d, 0x8a, 0x74, 0x39, 0xb1, 0x22, 0x0a, 0x83, 0x20, 0xf3, 0x2a, 0x42, 0xbc, 0xa2, 0x92, 0xdf, 0xb7, 0x03, + 0x38, 0x81, 0x3c, 0x1c, 0xb6, 0x09, 0xbe, 0xdf, 0xd1, 0x40, 0xa8, 0x18, 0x37, 0xd2, 0x76, 0x4b, 0x4e, 0x37, 0x8c, + 0x7b, 0x3a, 0x69, 0xf6, 0x26, 0x91, 0x9b, 0x44, 0x0d, 0x47, 0x11, 0xcb, 0xd7, 0x64, 0x77, 0x45, 0x81, 0x42, 0x80, + 0xc8, 0x2e, 0xf9, 0x1c, 0x96, 0x9a, 0xca, 0xf5, 0xb5, 0xe4, 0x17, 0x48, 0x82, 0x8c, 0xdb, 0x40, 0xea, 0x9f, 0x14, + 0xa1, 0xec, 0x1c, 0xb5, 0x61, 0xc7, 0x8f, 0x26, 0xaa, 0x0e, 0x76, 0xa7, 0x55, 0x9b, 0x1d, 0x8d, 0x60, 0xdf, 0x6b, + 0x85, 0x96, 0x83, 0xd6, 0x59, 0x9f, 0x9a, 0xdc, 0x10, 0x3f, 0x3e, 0xe7, 0x72, 0x80, 0x00, 0x3a, 0x59, 0xa0, 0xc2, + 0xfd, 0xd0, 0x51, 0xdf, 0xae, 0x0e, 0x69, 0x02, 0x45, 0xe5, 0xa0, 0xb8, 0xe3, 0x38, 0x85, 0x5d, 0x91, 0x1d, 0xfd, + 0x42, 0x34, 0x4e, 0xd8, 0xe1, 0x23, 0x6b, 0x9a, 0x3f, 0xc4, 0x09, 0xca, 0x17, 0xf3, 0x50, 0x70, 0x89, 0x3a, 0x1b, + 0x52, 0x46, 0x00, 0x74, 0x47, 0xbb, 0xf5, 0x90, 0x7e, 0x5c, 0xdb, 0x14, 0x7b, 0xee, 0x09, 0xfa, 0xbc, 0x6f, 0x60, + 0xdc, 0x11, 0xd8, 0xd1, 0x40, 0x12, 0xda, 0x47, 0x95, 0xfa, 0x33, 0x8f, 0xc5, 0x98, 0xd9, 0xa7, 0xdb, 0x66, 0x82, + 0xca, 0x9d, 0xec, 0x52, 0x09, 0xd2, 0xe0, 0x0d, 0xf2, 0x70, 0xd8, 0xd7, 0xfd, 0x5e, 0x6a, 0xda, 0xe6, 0xc9, 0xed, + 0x2b, 0xab, 0xd5, 0x94, 0xef, 0x76, 0x99, 0x40, 0x7c, 0x71, 0x0e, 0x65, 0xbc, 0xe7, 0x81, 0xaa, 0xef, 0x1b, 0x59, + 0x43, 0xc0, 0x7d, 0xb3, 0x30, 0xcc, 0x09, 0x3a, 0xc2, 0x20, 0x69, 0xe6, 0xc1, 0x9f, 0x00, 0x6d, 0xde, 0xcb, 0xeb, + 0x55, 0x88, 0x73, 0x40, 0x77, 0xf8, 0xf2, 0x84, 0xb5, 0x8e, 0xd8, 0xe3, 0x83, 0x79, 0xc6, 0x28, 0x37, 0xbc, 0x44, + 0xc7, 0x88, 0xdb, 0xde, 0x95, 0x17, 0x32, 0x5d, 0x3e, 0xfb, 0x96, 0x04, 0xbe, 0x31, 0x52, 0x81, 0x14, 0x68, 0xc4, + 0xb1, 0x0f, 0x36, 0xdf, 0x87, 0x43, 0xb3, 0x5f, 0xe8, 0x8d, 0xc2, 0xf4, 0x72, 0xfc, 0xe5, 0xc6, 0xfc, 0x16, 0x8e, + 0xb8, 0xda, 0x2a, 0xc4, 0xc3, 0x5e, 0x8e, 0xb9, 0xd0, 0x9a, 0x07, 0xbf, 0x30, 0x27, 0xcb, 0x42, 0xe2, 0xdd, 0x45, + 0x7d, 0xc3, 0x7a, 0xcd, 0x96, 0x3d, 0x93, 0x59, 0x13, 0x0f, 0x92, 0xf5, 0xb4, 0xf2, 0x70, 0x7a, 0x2a, 0xcf, 0xb1, + 0xd9, 0x0b, 0x0b, 0xb2, 0xa1, 0xab, 0xa7, 0xb6, 0x5c, 0xf7, 0xd6, 0x34, 0x24, 0x2f, 0xf1, 0x8b, 0xab, 0x68, 0x01, + 0x4a, 0x4c, 0xd4, 0xce, 0xac, 0x5d, 0x90, 0x0a, 0xf6, 0x7a, 0x59, 0x40, 0x83, 0x63, 0xe5, 0xd8, 0x96, 0xd0, 0x53, + 0x91, 0x19, 0x9f, 0x55, 0x29, 0x20, 0x7d, 0x4d, 0xd4, 0xed, 0x45, 0x54, 0x5a, 0x42, 0x82, 0xc0, 0xc7, 0x4f, 0x92, + 0x52, 0xec, 0xcb, 0x0d, 0x20, 0x30, 0x54, 0xbc, 0xef, 0x02, 0xbe, 0xbf, 0xa9, 0x48, 0x64, 0x72, 0xb0, 0x92, 0xf7, + 0x44, 0x97, 0x14, 0xf8, 0x9f, 0x9f, 0xef, 0xac, 0x54, 0x2a, 0x72, 0x39, 0x86, 0x11, 0xc5, 0x5e, 0x33, 0x45, 0x61, + 0x6e, 0x1a, 0xa1, 0x20, 0x50, 0xcb, 0x3f, 0x5c, 0x7f, 0xa1, 0xbf, 0xa4, 0x04, 0xa7, 0x96, 0x40, 0x5c, 0x5e, 0x9d, + 0x87, 0x04, 0x67, 0xf5, 0x16, 0x79, 0xac, 0x20, 0xd8, 0x63, 0xae, 0x35, 0x3b, 0xcc, 0x81, 0x64, 0x57, 0x0b, 0x8c, + 0xb6, 0x44, 0x29, 0xf5, 0x02, 0x62, 0x97, 0x4c, 0xf7, 0x75, 0x45, 0x91, 0xee, 0x51, 0xf4, 0x98, 0xca, 0x68, 0x39, + 0x3e, 0xd1, 0xd8, 0xdf, 0x18, 0xaa, 0x96, 0xfa, 0x2a, 0x7b, 0xc2, 0xd7, 0xbb, 0xc3, 0x17, 0x1b, 0x3f, 0x12, 0xfe, + 0x3e, 0x57, 0x4c, 0x3f, 0x67, 0xf7, 0xa3, 0x5d, 0xc2, 0x68, 0xa0, 0x7a, 0xae, 0x39, 0x6e, 0x2c, 0x37, 0x5e, 0x6e, + 0x5f, 0x74, 0xc5, 0x56, 0x99, 0x9f, 0xbb, 0x05, 0xb9, 0x26, 0xdd, 0x6b, 0x32, 0xcf, 0x49, 0x6e, 0xf0, 0xce, 0xf4, + 0x20, 0x9d, 0x08, 0xae, 0xfd, 0xcb, 0xf3, 0xaf, 0x3b, 0x5c, 0x85, 0x6d, 0x5b, 0x91, 0x57, 0x66, 0x40, 0x39, 0xb4, + 0xdb, 0x04, 0xd4, 0x97, 0x6e, 0xd2, 0x1d, 0xd1, 0x36, 0xb6, 0xf0, 0x12, 0xe2, 0x35, 0x50, 0xdc, 0xd2, 0xc4, 0x57, + 0x67, 0xa3, 0x90, 0xa6, 0x64, 0xb2, 0x07, 0x84, 0x62, 0xc2, 0x02, 0xfd, 0xd3, 0x71, 0xd2, 0xac, 0x0a, 0x5a, 0xef, + 0x95, 0xaa, 0x8e, 0x95, 0xd3, 0xd5, 0x57, 0x61, 0x66, 0xa3, 0x19, 0xf1, 0x20, 0x27, 0x1b, 0x87, 0x28, 0x77, 0x9d, + 0xe9, 0xe8, 0x50, 0x3c, 0xa6, 0xdc, 0x49, 0x9d, 0x5c, 0x9c, 0xb3, 0x23, 0x09, 0xc5, 0x7f, 0xeb, 0x9c, 0x08, 0x85, + 0x6f, 0x61, 0x2b, 0x02, 0xf9, 0xda, 0xb4, 0xfc, 0xaf, 0x1d, 0xf5, 0x39, 0xe1, 0x8e, 0x76, 0xe5, 0x6a, 0xc6, 0x29, + 0xb2, 0xe1, 0x40, 0xe6, 0xe3, 0x46, 0x05, 0xaf, 0x3c, 0x55, 0x65, 0xbf, 0x8d, 0x98, 0xf4, 0x89, 0x3d, 0x9b, 0x1c, + 0x26, 0xa5, 0xa3, 0xf6, 0x13, 0x5c, 0x16, 0x1d, 0x4c, 0xc3, 0xa2, 0x0d, 0x11, 0x20, 0x6a, 0xb5, 0xd1, 0x0e, 0x8b, + 0x88, 0x04, 0x8d, 0x2f, 0x56, 0x2f, 0xe3, 0x81, 0x8f, 0xe6, 0x18, 0xc5, 0x3e, 0x6d, 0x6b, 0x49, 0xf6, 0xbd, 0x31, + 0x46, 0xca, 0x40, 0x7d, 0xa2, 0x73, 0xa0, 0x4c, 0x2c, 0xf2, 0x31, 0xc9, 0x4b, 0x2d, 0x56, 0xb8, 0x4b, 0x5e, 0x47, + 0x25, 0x60, 0x45, 0xf2, 0x57, 0x70, 0x19, 0x25, 0x08, 0x46, 0x8f, 0xa2, 0x2f, 0xfd, 0x12, 0xdc, 0x72, 0xdf, 0x1f, + 0x32, 0x05, 0x76, 0x8a, 0xb1, 0x8f, 0x18, 0xbd, 0x94, 0x22, 0xf3, 0x21, 0x12, 0x8f, 0xdf, 0xb3, 0x04, 0x29, 0x28, + 0x7d, 0x69, 0x1b, 0x60, 0x70, 0x13, 0xe8, 0xb2, 0x6e, 0x6a, 0x9c, 0x01, 0x72, 0x22, 0x57, 0xd4, 0x76, 0xdc, 0xf3, + 0xc9, 0x0e, 0x05, 0x6d, 0x0d, 0x32, 0x66, 0x7a, 0xa1, 0x59, 0xa2, 0xc0, 0xf0, 0xfd, 0x56, 0xe3, 0x28, 0x18, 0xb0, + 0x6b, 0xac, 0x47, 0xbf, 0x52, 0xd2, 0x21, 0x53, 0xfa, 0x91, 0x16, 0xce, 0xe5, 0x4c, 0xa6, 0x7a, 0xf3, 0x7b, 0x21, + 0x05, 0x10, 0x17, 0x6f, 0x25, 0xa2, 0xb7, 0x64, 0x7f, 0x1d, 0x14, 0xa0, 0x60, 0x1a, 0x19, 0x23, 0xfd, 0x5f, 0x2c, + 0x0b, 0x72, 0x3b, 0x0a, 0x6b, 0x86, 0x04, 0x06, 0x15, 0x1f, 0x77, 0x68, 0x8e, 0xbf, 0x0e, 0xff, 0x6b, 0x03, 0x50, + 0x57, 0xee, 0xbc, 0xa1, 0xac, 0xf9, 0x01, 0x29, 0x45, 0x66, 0x2f, 0xdf, 0xbd, 0x6a, 0x85, 0x3a, 0x68, 0xb1, 0xcd, + 0x75, 0x9e, 0xd7, 0x16, 0xbf, 0x9e, 0x42, 0xb7, 0x37, 0xf9, 0xcd, 0x6c, 0x57, 0x5d, 0x3d, 0x36, 0x6a, 0xd4, 0x1b, + 0x04, 0xa3, 0xb7, 0x37, 0xc3, 0x6e, 0x9d, 0x0f, 0x67, 0x25, 0xa0, 0x95, 0xcd, 0x5e, 0xfd, 0x9b, 0x08, 0x0a, 0x7d, + 0xad, 0x9f, 0x47, 0xba, 0xca, 0xb8, 0x7c, 0x96, 0x80, 0x97, 0xc6, 0x87, 0x46, 0x95, 0x6a, 0x59, 0x58, 0xb2, 0x26, + 0x11, 0x08, 0x0e, 0x7f, 0xd0, 0xac, 0x67, 0xda, 0x8f, 0xea, 0x36, 0xdf, 0xd4, 0x75, 0x15, 0x41, 0xfb, 0x11, 0xd6, + 0x74, 0xa5, 0xff, 0x37, 0x71, 0x78, 0x38, 0x45, 0xff, 0xa3, 0xf9, 0x83, 0x82, 0xed, 0xdd, 0x66, 0x53, 0x42, 0x85, + 0x6b, 0xe6, 0x5e, 0x3d, 0xc5, 0x33, 0x45, 0x62, 0x17, 0xa5, 0x67, 0x55, 0xdb, 0xc1, 0xb2, 0xa1, 0xb6, 0xd7, 0x90, + 0xb0, 0x45, 0x90, 0x6a, 0x0a, 0xc6, 0xcd, 0xd3, 0x3b, 0xdc, 0x1d, 0x71, 0xcc, 0xa0, 0x1c, 0x1a, 0x45, 0x99, 0xdf, + 0x0e, 0x93, 0xe6, 0x54, 0x6d, 0x6f, 0x51, 0xe0, 0x47, 0x00, 0x9f, 0x2b, 0x6a, 0x07, 0xf2, 0xf4, 0x61, 0x94, 0xaf, + 0x27, 0xb9, 0xef, 0xc4, 0x11, 0x09, 0xd6, 0x0e, 0x6c, 0x79, 0xc9, 0xab, 0xd3, 0x95, 0xd5, 0x3d, 0x89, 0xaf, 0x3b, + 0xc6, 0xf9, 0x21, 0x71, 0xed, 0x47, 0x4f, 0x53, 0x0e, 0xdb, 0xa2, 0x9e, 0xe0, 0xb0, 0x38, 0xb4, 0xdd, 0x10, 0xdd, + 0x76, 0x96, 0x46, 0xef, 0x00, 0x6d, 0xb1, 0xc9, 0x8b, 0x27, 0x9d, 0x63, 0x5c, 0x1f, 0x2e, 0x27, 0x69, 0xd9, 0x3f, + 0x95, 0x1a, 0xa2, 0xbe, 0xa5, 0x74, 0x8f, 0xd4, 0x1d, 0x1d, 0x6c, 0xcd, 0xde, 0x3f, 0x16, 0xcd, 0x43, 0xe4, 0xb5, + 0x1c, 0x36, 0x6d, 0x52, 0xce, 0x87, 0x2f, 0x1b, 0x7d, 0x59, 0x5e, 0x6d, 0x4a, 0xb6, 0x41, 0xea, 0x4c, 0xb4, 0x79, + 0x0c, 0xa8, 0x6f, 0x0d, 0xbd, 0x0a, 0xbe, 0x60, 0xcd, 0x16, 0xfa, 0xe6, 0xbc, 0x5b, 0x60, 0x2c, 0xc1, 0x67, 0x0c, + 0x6d, 0x73, 0xee, 0xbe, 0x93, 0xee, 0xb3, 0x1c, 0xa6, 0x5c, 0x54, 0x4e, 0x51, 0x22, 0x89, 0xba, 0xff, 0x2f, 0xaf, + 0xf7, 0x52, 0x46, 0x7a, 0x79, 0x42, 0x87, 0x9d, 0xc2, 0xc3, 0x25, 0xab, 0x80, 0x62, 0xac, 0xad, 0xf4, 0xbc, 0x72, + 0x0a, 0x52, 0xa3, 0xa3, 0xb8, 0xd0, 0x7f, 0xf8, 0xca, 0x5d, 0xef, 0x36, 0xd6, 0xf4, 0x63, 0xca, 0x92, 0xbf, 0xf6, + 0x8d, 0x04, 0x6d, 0x5d, 0x11, 0x99, 0xfc, 0x9f, 0x48, 0x4c, 0x8e, 0x2c, 0xc4, 0xa3, 0x03, 0x68, 0x60, 0xa7, 0x4e, + 0xb6, 0xa0, 0xc5, 0x24, 0x09, 0x88, 0x2e, 0xd1, 0x1c, 0x4e, 0x00, 0x6d, 0xd2, 0x12, 0x4c, 0xc8, 0x6f, 0xf4, 0xbe, + 0xcb, 0x98, 0x27, 0xfc, 0x65, 0x1e, 0x4e, 0xa0, 0xfb, 0xe0, 0xd0, 0xa2, 0x09, 0x58, 0x45, 0x92, 0x86, 0xb5, 0xb6, + 0x9d, 0x0f, 0x27, 0xdb, 0x09, 0x49, 0xaa, 0xf7, 0xfb, 0xdc, 0x90, 0x42, 0xc8, 0xed, 0x28, 0x45, 0x4d, 0xe7, 0x7c, + 0xd5, 0xea, 0xcd, 0x21, 0xd6, 0xc5, 0x0c, 0x75, 0xcf, 0x40, 0x49, 0xdb, 0xce, 0x16, 0xe8, 0xf6, 0x09, 0xff, 0xf8, + 0xcb, 0x40, 0x13, 0x14, 0xcd, 0x1a, 0xb0, 0xa4, 0x00, 0xdc, 0xc6, 0x9c, 0xef, 0x35, 0x4f, 0xa9, 0xa2, 0xba, 0x83, + 0x30, 0x77, 0xd8, 0x90, 0x62, 0x54, 0xf7, 0xe1, 0x84, 0x05, 0x41, 0xbc, 0xf6, 0x44, 0x0e, 0x22, 0x3d, 0xa8, 0x4f, + 0x3a, 0x10, 0x32, 0xeb, 0x81, 0xb3, 0x86, 0x55, 0xd2, 0xad, 0xae, 0x59, 0xd7, 0x19, 0x7f, 0xf2, 0x43, 0xd6, 0xd9, + 0x40, 0xff, 0x64, 0xa3, 0xa4, 0x73, 0x5d, 0x44, 0x04, 0x4f, 0xe2, 0x65, 0x0e, 0x94, 0xe7, 0x3d, 0x4d, 0x39, 0xb5, + 0xfc, 0xf8, 0xef, 0x5b, 0x32, 0x87, 0xfa, 0x92, 0x35, 0xf9, 0x7b, 0xa7, 0x3f, 0x59, 0x44, 0x5e, 0x31, 0x35, 0x5f, + 0x2d, 0x26, 0x2b, 0x2f, 0x32, 0xce, 0x29, 0x91, 0x0a, 0x4e, 0xad, 0xe8, 0x7c, 0x22, 0x97, 0xd8, 0xc6, 0x1f, 0x04, + 0x32, 0x67, 0x8f, 0xec, 0x3d, 0x3b, 0xa8, 0x18, 0x2d, 0xa1, 0x20, 0x66, 0x51, 0x35, 0xf0, 0xed, 0xc1, 0x9b, 0x31, + 0xb3, 0xe7, 0xa4, 0x40, 0x8b, 0x51, 0x60, 0xcb, 0x85, 0x18, 0x0d, 0xf1, 0xaa, 0x64, 0xae, 0x24, 0xe1, 0xcf, 0x96, + 0x99, 0x12, 0x3f, 0x64, 0xa5, 0x0e, 0xee, 0xbc, 0x58, 0xb9, 0x64, 0xb9, 0x7c, 0x7e, 0xfd, 0x08, 0xec, 0x7a, 0xef, + 0x11, 0x31, 0xe3, 0xf5, 0x93, 0x05, 0xbb, 0x56, 0x80, 0x12, 0x19, 0xdd, 0x30, 0xee, 0x22, 0xa1, 0x46, 0xd9, 0x61, + 0x74, 0x05, 0x2a, 0x8e, 0x75, 0x2a, 0x0a, 0x00, 0xfe, 0x78, 0x3d, 0x54, 0x2e, 0x70, 0x7f, 0x3c, 0x11, 0x80, 0x32, + 0xca, 0xf4, 0x9d, 0xc9, 0x18, 0x10, 0x1d, 0x35, 0x13, 0xf8, 0x37, 0x61, 0xac, 0x9e, 0xfb, 0xec, 0xf8, 0x28, 0xee, + 0x65, 0x23, 0x0c, 0x34, 0x96, 0x65, 0x93, 0xcd, 0xba, 0x75, 0x5b, 0xe1, 0x4f, 0xc5, 0x0a, 0xa4, 0x29, 0x40, 0xf3, + 0x31, 0x6d, 0x04, 0x9c, 0x81, 0x31, 0xfb, 0x32, 0x81, 0x9a, 0x2a, 0x18, 0x47, 0x5f, 0x5b, 0x36, 0x3c, 0x1f, 0xd5, + 0xdd, 0x0f, 0x2e, 0x73, 0x81, 0x50, 0x16, 0x0b, 0x6c, 0x7b, 0xa1, 0x4e, 0xfc, 0x56, 0x90, 0x79, 0x7c, 0x5f, 0x0d, + 0x8b, 0x36, 0x1d, 0x2d, 0x2b, 0x2b, 0xac, 0x0f, 0x7a, 0xb4, 0x47, 0xb0, 0x1a, 0x29, 0x5a, 0xcf, 0x71, 0xb7, 0x02, + 0x1b, 0xd1, 0xe3, 0xd4, 0x60, 0xf5, 0x83, 0x49, 0x81, 0xe4, 0x60, 0xc8, 0xb6, 0x23, 0x96, 0x1a, 0x18, 0x82, 0x9a, + 0x97, 0xa7, 0x00, 0x6b, 0xa4, 0x76, 0xd3, 0xd2, 0x68, 0xf2, 0xaf, 0xda, 0xa2, 0xdf, 0xfa, 0x37, 0xb3, 0xde, 0x35, + 0x42, 0x24, 0xdb, 0xc3, 0xf9, 0xec, 0x0c, 0x2d, 0x98, 0x41, 0xa3, 0x22, 0xb4, 0x87, 0x50, 0x6a, 0x4e, 0x23, 0x31, + 0xa8, 0x85, 0x10, 0xd9, 0x9f, 0xb8, 0xb7, 0x9c, 0xf0, 0x3c, 0xe0, 0x1e, 0x9e, 0x95, 0x34, 0xe9, 0x34, 0x5f, 0x2a, + 0x23, 0xb8, 0x2b, 0x70, 0x8a, 0x12, 0xcc, 0x16, 0xf4, 0x4f, 0x7e, 0x7b, 0x57, 0x8a, 0x18, 0xae, 0x0b, 0x08, 0xa5, + 0xcf, 0x9e, 0x11, 0x45, 0xbb, 0xc8, 0x88, 0x56, 0x25, 0x4b, 0x70, 0x81, 0xec, 0x23, 0xdb, 0xcf, 0x46, 0x16, 0xcc, + 0x1a, 0xf6, 0x53, 0xdd, 0x88, 0xf6, 0x21, 0x30, 0x23, 0x36, 0xc7, 0x5e, 0x4f, 0x9e, 0x40, 0x43, 0xf4, 0xb0, 0x64, + 0x5a, 0x17, 0xb4, 0x74, 0x95, 0x62, 0xa5, 0x42, 0x37, 0xf1, 0xa8, 0x1f, 0xa9, 0x51, 0xab, 0xe5, 0xed, 0x10, 0x7d, + 0x04, 0x6b, 0x5e, 0xef, 0x9f, 0xe2, 0x5d, 0x43, 0x81, 0x98, 0x85, 0x3b, 0x56, 0xd6, 0x58, 0xd9, 0x63, 0x61, 0xe2, + 0xf0, 0x8d, 0x10, 0x0b, 0x4f, 0x85, 0xde, 0x4f, 0xf3, 0xbf, 0x36, 0x78, 0xf5, 0xb5, 0x50, 0xd6, 0x04, 0xe5, 0x87, + 0xc1, 0xc2, 0x99, 0x0b, 0x7c, 0x8c, 0xb1, 0xd3, 0xe1, 0x37, 0x8a, 0x68, 0x83, 0x44, 0x4b, 0x8a, 0x61, 0x0b, 0xb7, + 0x57, 0x12, 0x57, 0x49, 0x15, 0x1c, 0x45, 0x18, 0x5f, 0x70, 0xeb, 0xf1, 0x4b, 0xd6, 0x18, 0x13, 0x8e, 0xce, 0x39, + 0x28, 0x5b, 0x11, 0x12, 0xcc, 0x02, 0x9b, 0xf4, 0x70, 0x83, 0x65, 0x5a, 0x21, 0x25, 0x08, 0x31, 0xc9, 0x74, 0x3f, + 0x86, 0xa1, 0x12, 0x5b, 0x05, 0x41, 0x46, 0x65, 0x76, 0xe8, 0xc4, 0x19, 0x6d, 0x71, 0x98, 0x62, 0x8d, 0xf0, 0xa9, + 0xa6, 0x17, 0x21, 0x4a, 0x22, 0xef, 0x99, 0x5d, 0x63, 0x98, 0x40, 0x2b, 0x32, 0x55, 0x32, 0xfa, 0x2a, 0x06, 0xdc, + 0xfa, 0x6b, 0xed, 0x43, 0xc1, 0x3a, 0xb8, 0x86, 0x5e, 0xaa, 0xe2, 0xaf, 0x4e, 0xa1, 0x55, 0xea, 0x92, 0x54, 0x49, + 0x4f, 0xa6, 0x90, 0xe6, 0xbc, 0x82, 0x1e, 0xce, 0x79, 0x88, 0xb7, 0x02, 0xde, 0x2a, 0xf8, 0x04, 0x5a, 0xd2, 0x08, + 0xf7, 0x2d, 0xbb, 0xda, 0x3e, 0x2b, 0x91, 0xed, 0xe7, 0xe6, 0x64, 0xc4, 0xb9, 0x0e, 0x34, 0x7a, 0x0e, 0x0b, 0x2f, + 0x83, 0x16, 0x7d, 0xa7, 0x06, 0xee, 0x4a, 0x44, 0xdf, 0xfa, 0x43, 0x0b, 0x8a, 0x35, 0xab, 0x54, 0xc0, 0x9e, 0xa9, + 0xf7, 0x23, 0x21, 0xf1, 0x58, 0xfe, 0xb1, 0xa7, 0xc7, 0x24, 0x51, 0xb5, 0x3c, 0x81, 0x91, 0x08, 0x51, 0x93, 0x41, + 0xd6, 0xfa, 0x04, 0x83, 0xae, 0x59, 0xae, 0x52, 0x73, 0x85, 0x30, 0x87, 0x32, 0xdd, 0xd5, 0xda, 0x2e, 0x00, 0x4e, + 0x5f, 0xad, 0xe7, 0x2b, 0xd0, 0x69, 0x61, 0x06, 0x28, 0x71, 0xa6, 0x47, 0x75, 0xc6, 0xc1, 0xa9, 0x6e, 0x11, 0xff, + 0xeb, 0x95, 0x4a, 0x58, 0x7b, 0xf0, 0x70, 0x50, 0xf1, 0xa4, 0x82, 0xfc, 0x6c, 0xa0, 0x29, 0x0d, 0x03, 0x52, 0x70, + 0x4e, 0x62, 0x57, 0x2c, 0xa7, 0x8b, 0x47, 0x5e, 0x19, 0x23, 0x9c, 0xc0, 0xba, 0xd3, 0xa7, 0xd3, 0x41, 0x31, 0x2e, + 0xd1, 0x52, 0x17, 0x35, 0xe7, 0xd6, 0x49, 0x5a, 0xee, 0x40, 0xf1, 0x57, 0x96, 0xa8, 0x6b, 0x91, 0x4e, 0x96, 0x2d, + 0xae, 0xea, 0xab, 0x31, 0xed, 0x82, 0x08, 0x2b, 0x6a, 0xe4, 0xd6, 0x42, 0x9d, 0xed, 0x77, 0x5e, 0xde, 0x50, 0x8c, + 0xe3, 0x39, 0xbf, 0xd6, 0xca, 0xc3, 0xb3, 0x96, 0x52, 0x2f, 0xde, 0x32, 0x47, 0xd3, 0x89, 0x35, 0x5f, 0x6a, 0x84, + 0x67, 0xe2, 0x2e, 0x22, 0xc3, 0x68, 0x80, 0xe9, 0xdb, 0xaa, 0x45, 0x2c, 0xa4, 0x1d, 0x40, 0x3f, 0x17, 0xd4, 0x39, + 0x00, 0x0c, 0x45, 0x28, 0x3b, 0x00, 0xae, 0x42, 0xb5, 0x5e, 0xcf, 0x2b, 0x6d, 0x6c, 0xf6, 0x27, 0x72, 0x42, 0x10, + 0x56, 0xbc, 0xa4, 0x50, 0x0a, 0x99, 0x40, 0x5e, 0xe2, 0x52, 0x95, 0xdc, 0x4e, 0xcb, 0x66, 0xd3, 0xb9, 0xc3, 0x37, + 0xd2, 0x00, 0x44, 0x4d, 0x5a, 0x66, 0xb2, 0x81, 0x0d, 0x55, 0xca, 0x94, 0xa7, 0x49, 0xad, 0x06, 0x5c, 0xf3, 0xc1, + 0x35, 0x70, 0x24, 0xe0, 0xec, 0xc0, 0xb5, 0x20, 0x0e, 0xbb, 0x66, 0xc8, 0x35, 0x75, 0x4e, 0x79, 0x8c, 0xfe, 0x6b, + 0xab, 0x35, 0xb6, 0x5f, 0x7d, 0x2d, 0x4d, 0xde, 0x4f, 0xc7, 0x48, 0x2b, 0x03, 0x52, 0x3b, 0xf9, 0xbf, 0x36, 0xa4, + 0x9c, 0xfd, 0x58, 0x88, 0xb5, 0xff, 0x9b, 0x91, 0x39, 0x9f, 0x57, 0xcf, 0x0e, 0x13, 0x37, 0x18, 0x53, 0x21, 0x8e, + 0x71, 0x12, 0x5e, 0x6c, 0x87, 0x57, 0x8d, 0x41, 0xed, 0xd7, 0x0b, 0x18, 0x72, 0xdc, 0xb1, 0xf7, 0x1e, 0x18, 0xce, + 0xbe, 0xd8, 0x5b, 0x34, 0x56, 0x87, 0xb4, 0x28, 0x96, 0x7d, 0x00, 0xe9, 0x67, 0xf9, 0xfe, 0x7f, 0xdc, 0xdc, 0xa5, + 0x41, 0x2d, 0x23, 0x2f, 0x71, 0xc9, 0x42, 0xb3, 0xfc, 0x5e, 0x52, 0xac, 0x4f, 0x1b, 0xe1, 0x12, 0xcd, 0x95, 0xd5, + 0xff, 0x82, 0x65, 0xcb, 0xea, 0x2e, 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8d, 0x6f, 0x6e, 0x7c, 0x4c, 0x9d, 0x35, 0x95, + 0x6e, 0xc6, 0xbb, 0x38, 0xc4, 0xae, 0xb7, 0x8d, 0x2a, 0xb6, 0x8b, 0x8c, 0xa9, 0x68, 0x6a, 0xf5, 0xd1, 0x0c, 0x22, + 0x37, 0xb4, 0xa0, 0xfd, 0x5b, 0x4c, 0x3a, 0x58, 0x3c, 0x28, 0xc3, 0xa5, 0xd1, 0xf2, 0xba, 0x10, 0x3b, 0x0a, 0x2e, + 0xc9, 0x48, 0x4a, 0x12, 0x64, 0x48, 0xf7, 0x1d, 0x17, 0x0f, 0x9a, 0x42, 0xd5, 0x88, 0xdb, 0x95, 0x64, 0xbf, 0xe2, + 0xfe, 0xa5, 0x7e, 0xdc, 0x30, 0xea, 0xca, 0x39, 0x50, 0x89, 0xcf, 0x9a, 0x6c, 0x4e, 0x88, 0x8e, 0xda, 0x36, 0xeb, + 0x28, 0xca, 0x91, 0x5f, 0x29, 0x25, 0xea, 0x5f, 0xd1, 0x1b, 0x48, 0xb6, 0x08, 0x60, 0x60, 0x1b, 0x80, 0xd5, 0x6f, + 0xd6, 0x2c, 0xd5, 0x32, 0x40, 0xe3, 0x57, 0xb0, 0x6b, 0x3e, 0x3e, 0x75, 0x37, 0xfa, 0x05, 0xd1, 0xd8, 0x5a, 0xd1, + 0x04, 0x97, 0xdd, 0x0b, 0xab, 0x37, 0xe2, 0xf7, 0xd4, 0xdb, 0x23, 0x88, 0x0d, 0xe4, 0xd3, 0x74, 0xbf, 0x4b, 0x4d, + 0x1f, 0x90, 0xf4, 0x3d, 0x18, 0x63, 0x1f, 0x83, 0x5d, 0x51, 0x4f, 0xad, 0xde, 0x54, 0x95, 0x43, 0x20, 0xf7, 0x74, + 0x35, 0x2a, 0xe6, 0xf1, 0x57, 0xb4, 0x5b, 0x6b, 0xd9, 0x61, 0x78, 0x95, 0x2f, 0xa0, 0x6c, 0xd1, 0xae, 0x29, 0x22, + 0xc9, 0x65, 0x8c, 0x4b, 0x15, 0x80, 0x12, 0x58, 0x90, 0x93, 0x1a, 0xbb, 0x3a, 0xdd, 0xb2, 0x79, 0xf9, 0x3a, 0x9a, + 0x90, 0x6f, 0xfd, 0xb4, 0xf2, 0xb9, 0x19, 0x1c, 0x55, 0xd4, 0x21, 0x02, 0xd3, 0x40, 0x1d, 0x16, 0x70, 0x18, 0xa9, + 0xf3, 0x52, 0x04, 0x0e, 0x78, 0x37, 0xe8, 0x73, 0xcd, 0x40, 0x51, 0x70, 0x88, 0xbc, 0x8b, 0x1a, 0x2c, 0xf0, 0x1c, + 0x3c, 0x49, 0xb4, 0x71, 0x74, 0xf8, 0xef, 0x82, 0x8e, 0xa2, 0x43, 0xb2, 0x94, 0xf5, 0xbd, 0x32, 0x15, 0xc9, 0x49, + 0xea, 0x22, 0xe9, 0xfc, 0x54, 0x9e, 0xa9, 0x4d, 0x6e, 0xcd, 0x5f, 0x24, 0x9f, 0xc6, 0xc9, 0xd8, 0x0b, 0xd8, 0xaf, + 0x61, 0xc4, 0xae, 0xf3, 0x17, 0x36, 0x9f, 0xf6, 0xcc, 0xb2, 0x46, 0xab, 0x33, 0xe0, 0x81, 0xa4, 0x13, 0x61, 0x29, + 0xbb, 0x64, 0x2e, 0x65, 0x00, 0x28, 0xd7, 0xc6, 0xcb, 0xbb, 0x21, 0xc4, 0xe7, 0xe2, 0xfa, 0x8e, 0x48, 0xa8, 0x4c, + 0x35, 0x33, 0xe3, 0xb9, 0x47, 0x11, 0x21, 0x2c, 0xd5, 0xce, 0x2c, 0x6e, 0xb3, 0xed, 0xed, 0x6c, 0x78, 0x5e, 0xb3, + 0xfd, 0xb1, 0xc0, 0x14, 0xf5, 0xa0, 0xbf, 0x8b, 0x8b, 0xa4, 0xca, 0x20, 0x44, 0xcc, 0xe0, 0x03, 0xae, 0x86, 0xb0, + 0x4b, 0xa5, 0xa2, 0x3f, 0xdb, 0x25, 0x8a, 0x9f, 0x5e, 0xa5, 0xaa, 0xc2, 0xe5, 0x48, 0xc8, 0xc4, 0x96, 0xda, 0x80, + 0x25, 0x02, 0x3c, 0xf2, 0xe4, 0x16, 0xb7, 0x65, 0xb9, 0x1b, 0x11, 0x9c, 0x16, 0x2d, 0x9d, 0x9c, 0xb0, 0x4c, 0xe8, + 0x3b, 0xd9, 0xf5, 0xae, 0x29, 0xc2, 0xec, 0x7e, 0x93, 0x6e, 0x7f, 0x94, 0xd2, 0x57, 0x95, 0xc6, 0x1d, 0xb8, 0xc6, + 0x12, 0xb8, 0xf0, 0x18, 0xd1, 0x6a, 0x68, 0x54, 0x9f, 0x7a, 0x44, 0xf1, 0xa8, 0xd6, 0x24, 0xc7, 0x41, 0xeb, 0x30, + 0x71, 0xa5, 0xa5, 0x81, 0xe2, 0x42, 0xec, 0xac, 0x43, 0x76, 0x3a, 0x0b, 0xf9, 0x92, 0x73, 0xb3, 0x75, 0x92, 0xc8, + 0x17, 0xb5, 0x0f, 0x45, 0x33, 0x12, 0x73, 0xf5, 0x5d, 0x7e, 0xce, 0xd1, 0x8f, 0x77, 0x57, 0xf9, 0x8a, 0xb7, 0x8e, + 0x73, 0x92, 0xcc, 0x27, 0xf1, 0xa2, 0xe5, 0x9f, 0xcb, 0xd2, 0x46, 0x0b, 0x4f, 0xe2, 0xd1, 0x0f, 0xa7, 0x8a, 0xfa, + 0x35, 0x12, 0x9a, 0x75, 0x52, 0xeb, 0x59, 0x79, 0x25, 0xe5, 0x7c, 0xb7, 0x47, 0x8a, 0x25, 0x62, 0x8e, 0x71, 0xb9, + 0xe4, 0x69, 0x55, 0x2d, 0x1d, 0x7d, 0x7f, 0x86, 0xe7, 0x52, 0x76, 0x02, 0x60, 0x22, 0xa9, 0x8f, 0xb0, 0xa2, 0xbd, + 0x8c, 0x1a, 0x21, 0xf6, 0x82, 0xd1, 0xb2, 0x84, 0x17, 0xfb, 0xcd, 0xad, 0x07, 0x21, 0x5b, 0x92, 0xee, 0xee, 0x2d, + 0x08, 0x5f, 0xf0, 0xd3, 0x03, 0xa7, 0x75, 0xa4, 0x26, 0x2f, 0xce, 0x42, 0x94, 0x78, 0x89, 0x74, 0x18, 0xb5, 0xb5, + 0x9c, 0x9b, 0xb0, 0x92, 0x34, 0x86, 0xdc, 0x1a, 0x65, 0xd5, 0xb0, 0xa5, 0x18, 0x73, 0x20, 0xe3, 0x91, 0x79, 0x06, + 0xfa, 0x1e, 0xe0, 0x4d, 0x6e, 0x6d, 0x49, 0xb2, 0xee, 0x9e, 0xca, 0xc8, 0xbc, 0xe8, 0xb3, 0xe4, 0xfc, 0xb8, 0x95, + 0xd8, 0x50, 0xdc, 0x49, 0xb9, 0x62, 0x3d, 0x71, 0x90, 0x5d, 0x9a, 0xbc, 0x2f, 0x51, 0x44, 0xc9, 0x4a, 0xa7, 0xff, + 0x39, 0x37, 0x1c, 0x77, 0x3a, 0x34, 0xd1, 0xea, 0xd8, 0x76, 0x68, 0x25, 0xe6, 0xe1, 0xd7, 0xe5, 0x9a, 0xaa, 0x05, + 0xb4, 0x80, 0x39, 0x22, 0x4a, 0xdd, 0x0c, 0x71, 0x93, 0xa4, 0xe3, 0x05, 0xc2, 0xdf, 0x6e, 0x33, 0x13, 0x5f, 0x76, + 0x7f, 0x97, 0x23, 0x34, 0x35, 0x94, 0xe4, 0x01, 0x14, 0x97, 0x6f, 0xc2, 0x9b, 0x31, 0x15, 0xf1, 0x0d, 0xfb, 0xcc, + 0x59, 0x6a, 0x0f, 0x5e, 0xa0, 0x4d, 0x4f, 0x82, 0xd5, 0x89, 0x1b, 0x40, 0x89, 0x4c, 0x10, 0x20, 0xbb, 0xc7, 0x00, + 0x96, 0x06, 0xd9, 0x8b, 0x26, 0xd3, 0x00, 0x22, 0x5b, 0x8c, 0xad, 0x61, 0x8e, 0xcd, 0x15, 0xa0, 0x05, 0x3b, 0xf3, + 0x4b, 0xa0, 0x6c, 0x60, 0x87, 0x77, 0xf4, 0x3f, 0x79, 0x43, 0x0c, 0x31, 0xa6, 0xa9, 0x4d, 0x3b, 0xeb, 0x55, 0x90, + 0xbd, 0xeb, 0x63, 0x16, 0x07, 0xe4, 0xc0, 0x75, 0x43, 0x69, 0xec, 0x8c, 0xd5, 0x35, 0x0d, 0x68, 0xa5, 0xa8, 0xae, + 0x08, 0x84, 0x24, 0x10, 0xf3, 0xf2, 0x50, 0x48, 0x4d, 0x42, 0xb5, 0x74, 0xd3, 0xa9, 0x6d, 0x82, 0xc2, 0xec, 0x78, + 0x6a, 0xf2, 0xd0, 0x4b, 0xe0, 0xed, 0xdb, 0x5b, 0x8b, 0x01, 0x47, 0xe1, 0x4a, 0x96, 0x32, 0xea, 0x57, 0xe6, 0xcd, + 0x7a, 0x58, 0xcb, 0x5f, 0x1c, 0xd0, 0x6e, 0x57, 0x8e, 0x19, 0xd5, 0x4e, 0xf5, 0x42, 0x70, 0x7a, 0x67, 0x80, 0x46, + 0x44, 0x02, 0x6c, 0xe0, 0x47, 0xfd, 0x8e, 0x54, 0x2c, 0x51, 0xd6, 0x56, 0x5e, 0xcd, 0xfa, 0x03, 0x16, 0x22, 0x8d, + 0x2b, 0x6c, 0x9c, 0xb3, 0x68, 0x55, 0x23, 0x99, 0x90, 0xa0, 0x07, 0x32, 0xb2, 0x73, 0x56, 0x93, 0xe0, 0xeb, 0x94, + 0x06, 0x5f, 0x70, 0x7a, 0xfc, 0xb5, 0x0e, 0x50, 0x8e, 0x7f, 0x71, 0xf6, 0xba, 0x57, 0xe1, 0x88, 0xeb, 0x11, 0xf3, + 0x45, 0x9d, 0x97, 0x3f, 0xdc, 0x19, 0x39, 0xfd, 0x7b, 0xcb, 0x0c, 0x40, 0x95, 0xbf, 0x58, 0x26, 0x80, 0x54, 0x1e, + 0xdc, 0x79, 0x23, 0x3a, 0x4b, 0x76, 0x14, 0x8d, 0x59, 0x3b, 0x69, 0x09, 0x3b, 0x98, 0x15, 0x47, 0x10, 0x2a, 0xfe, + 0xc5, 0x08, 0x20, 0x71, 0x14, 0xb4, 0xec, 0x68, 0xd0, 0x8a, 0xf6, 0x40, 0x9d, 0x93, 0x12, 0x61, 0x63, 0x5e, 0x88, + 0x0d, 0xf9, 0xfa, 0xe6, 0x04, 0x07, 0x59, 0x43, 0x12, 0x3c, 0xa8, 0xb7, 0x6f, 0x8a, 0x6c, 0x97, 0x1d, 0xa6, 0xde, + 0xf4, 0xf8, 0x3d, 0x97, 0x80, 0x90, 0x16, 0x0f, 0x91, 0x8f, 0xdd, 0x48, 0xcc, 0x6e, 0x3d, 0xde, 0x76, 0xc4, 0xa2, + 0x6f, 0x27, 0xa2, 0x54, 0xea, 0xb8, 0x36, 0x0f, 0x51, 0x10, 0x56, 0x18, 0x4a, 0x70, 0xf9, 0x55, 0x40, 0x6c, 0xa2, + 0xa0, 0xb1, 0x8f, 0xe5, 0x4c, 0x39, 0x6c, 0xb2, 0x0f, 0xe7, 0x2f, 0x75, 0xad, 0xff, 0x08, 0xb5, 0xce, 0x9e, 0xc0, + 0xaf, 0x18, 0xd8, 0x7b, 0x28, 0x83, 0x75, 0x4a, 0xdc, 0xb5, 0xe0, 0xa1, 0x0c, 0xca, 0x7d, 0x18, 0x48, 0x08, 0xc5, + 0xf5, 0x71, 0xd8, 0x14, 0xbb, 0x96, 0x18, 0x01, 0x3e, 0x4a, 0x66, 0xa5, 0x36, 0x1d, 0xc3, 0x95, 0x30, 0xe0, 0xf2, + 0x52, 0x8f, 0xe7, 0xa3, 0x9b, 0xdd, 0x95, 0x46, 0x1a, 0xfa, 0x6e, 0xe0, 0x78, 0xb9, 0x39, 0x4c, 0x95, 0x45, 0x5b, + 0x37, 0x25, 0x2c, 0x75, 0x81, 0xc8, 0x8c, 0x10, 0x31, 0xb7, 0x6c, 0xd2, 0x90, 0x38, 0xdb, 0xe9, 0x04, 0x7d, 0x6c, + 0x60, 0x38, 0x83, 0xd9, 0x54, 0xb5, 0xb5, 0x7b, 0x53, 0x58, 0xff, 0xcc, 0xb2, 0x0d, 0xfc, 0x7c, 0x39, 0x23, 0x21, + 0xa0, 0x61, 0xa1, 0x17, 0x11, 0xc2, 0x7a, 0x38, 0xca, 0xb3, 0x97, 0xd8, 0x70, 0x21, 0x43, 0x87, 0xe3, 0x87, 0x63, + 0xb3, 0x17, 0x34, 0xc7, 0xcf, 0xa7, 0xc7, 0xc6, 0xbe, 0x56, 0xd3, 0x24, 0x0b, 0x2e, 0x65, 0xe1, 0x74, 0xfd, 0xc8, + 0x11, 0xc5, 0x67, 0xda, 0x75, 0xdf, 0xc1, 0xe6, 0x33, 0x29, 0x73, 0x52, 0xe9, 0x26, 0x02, 0x95, 0x81, 0x4c, 0xde, + 0xed, 0x05, 0xc0, 0xb6, 0x01, 0xfa, 0xa2, 0xb9, 0xc8, 0x4c, 0x65, 0x9f, 0x74, 0x5e, 0x1e, 0x22, 0x65, 0x7b, 0x78, + 0x73, 0x58, 0x86, 0x80, 0xd7, 0xa7, 0x35, 0xfb, 0x37, 0x3c, 0x0d, 0xd2, 0x75, 0xb4, 0x31, 0x2a, 0x92, 0xe6, 0x82, + 0xc9, 0x35, 0x2a, 0xa6, 0xc1, 0x43, 0x38, 0x69, 0xc0, 0xa9, 0x52, 0x4e, 0xb8, 0x20, 0x79, 0x81, 0x49, 0x2a, 0xf6, + 0x04, 0x5a, 0xdb, 0x40, 0x44, 0x45, 0x0d, 0x3f, 0xba, 0x8c, 0x8b, 0x47, 0x69, 0x67, 0x4f, 0xa2, 0xa2, 0xfe, 0xda, + 0x7b, 0xd2, 0x0a, 0x61, 0x9f, 0x53, 0xdd, 0xf5, 0x1a, 0x8f, 0xcd, 0x08, 0x8a, 0x5e, 0xd3, 0xd4, 0xff, 0x65, 0x18, + 0x84, 0xbb, 0xcb, 0x76, 0x0e, 0x82, 0x82, 0x1c, 0x21, 0xc0, 0x4f, 0x5e, 0xd0, 0x97, 0x00, 0x6b, 0xe8, 0x88, 0x03, + 0x79, 0x7e, 0x6d, 0x8f, 0xa4, 0x73, 0xf5, 0xd5, 0xb9, 0xef, 0x7f, 0xc5, 0xd1, 0x1a, 0xef, 0x9f, 0x61, 0xec, 0x1f, + 0x9f, 0x29, 0x6d, 0xce, 0x1e, 0x33, 0xf1, 0xe8, 0x44, 0xf6, 0xb7, 0x8d, 0x49, 0x8a, 0xb7, 0xc7, 0x4a, 0x81, 0x7f, + 0xf8, 0x40, 0xf2, 0x36, 0x0b, 0xe7, 0x46, 0x12, 0xf3, 0xdb, 0xd9, 0xaa, 0x93, 0x9f, 0x1c, 0xd7, 0xca, 0x7d, 0xd6, + 0x24, 0x7f, 0xcc, 0xa5, 0x1d, 0xf0, 0x9d, 0xab, 0xce, 0xce, 0xad, 0xe4, 0xd6, 0x38, 0xe7, 0xf8, 0xcd, 0xb7, 0xbb, + 0x55, 0xea, 0xcd, 0xff, 0x95, 0xd5, 0xe2, 0x3a, 0x75, 0xc3, 0x25, 0xde, 0x40, 0x41, 0x50, 0xb8, 0xc3, 0x3a, 0xbd, + 0xcc, 0x5d, 0xe3, 0x0e, 0xa3, 0xc1, 0xda, 0xfa, 0xaa, 0xc8, 0x3c, 0x32, 0x17, 0x31, 0xce, 0x67, 0xe2, 0x65, 0x35, + 0x65, 0xdb, 0xa0, 0xdf, 0x35, 0x15, 0xe6, 0x3f, 0xbf, 0x86, 0x3a, 0xdb, 0xb1, 0xf9, 0x53, 0xe5, 0xdf, 0x80, 0x6b, + 0xe8, 0x50, 0x8e, 0xa2, 0xe0, 0xc4, 0x75, 0xcd, 0xb4, 0x4d, 0xce, 0xb5, 0x70, 0x5c, 0xbb, 0x1c, 0x78, 0xb5, 0x49, + 0x9c, 0x41, 0x94, 0x56, 0xc6, 0x3d, 0xa7, 0x4f, 0xbb, 0xfc, 0xce, 0xb8, 0x63, 0xd8, 0x75, 0x30, 0x0a, 0x82, 0x01, + 0x25, 0x16, 0x6d, 0x50, 0x77, 0x32, 0xba, 0x9a, 0xd8, 0xb3, 0x06, 0x62, 0x09, 0xac, 0x68, 0x7e, 0xab, 0x04, 0xa0, + 0xa5, 0x1d, 0x78, 0x59, 0xaf, 0x12, 0xc9, 0x92, 0xd5, 0x37, 0x0e, 0xe6, 0x7f, 0x88, 0x50, 0x04, 0xe7, 0xdb, 0x38, + 0xc4, 0x8b, 0x4a, 0x91, 0x98, 0x53, 0xec, 0xd1, 0x9b, 0xec, 0xa3, 0x5e, 0x82, 0x34, 0xff, 0x06, 0x18, 0x20, 0x60, + 0xc3, 0x71, 0x2c, 0x10, 0x94, 0xcc, 0xcf, 0xf1, 0xe5, 0xce, 0x5e, 0xbe, 0xf9, 0x04, 0x53, 0xfb, 0x37, 0x9e, 0xdb, + 0xc8, 0xfd, 0xdb, 0x50, 0xc9, 0xed, 0xcf, 0x2c, 0xee, 0xff, 0x2c, 0x9e, 0xdd, 0xbf, 0xe5, 0x1f, 0xbf, 0x6e, 0x5a, + 0xe0, 0x9d, 0xce, 0xfb, 0x48, 0x02, 0x35, 0x3f, 0x5f, 0x67, 0xa4, 0x60, 0x18, 0x11, 0x7c, 0xed, 0xf8, 0x30, 0xa2, + 0xfb, 0xad, 0x67, 0x03, 0x6b, 0x62, 0x1f, 0xe3, 0x16, 0xd5, 0xeb, 0x79, 0x81, 0xed, 0x6a, 0x5c, 0xcb, 0xf4, 0xb2, + 0xd0, 0x9a, 0xa7, 0xca, 0x2e, 0x15, 0x1a, 0x09, 0x07, 0x5b, 0xc0, 0x3b, 0xb8, 0xeb, 0xca, 0x9d, 0xbd, 0xb4, 0x66, + 0x36, 0xe5, 0x49, 0x82, 0x9c, 0x0e, 0x5c, 0x34, 0x7d, 0xf5, 0xd4, 0xb6, 0xc4, 0x18, 0xfe, 0x9c, 0x37, 0xd5, 0x18, + 0x15, 0x3d, 0x46, 0x23, 0x19, 0xb1, 0x72, 0x56, 0x46, 0xcb, 0x8b, 0x61, 0x68, 0x4b, 0xc6, 0xc5, 0xac, 0xb2, 0xa0, + 0x0c, 0xb8, 0x07, 0x42, 0xd6, 0x0b, 0xfa, 0xd6, 0x4e, 0x91, 0x0f, 0xd5, 0x27, 0x1c, 0xb0, 0x79, 0x3c, 0xc1, 0x71, + 0xe9, 0xa3, 0x7a, 0x40, 0x9a, 0xc4, 0x55, 0xb8, 0x86, 0xb3, 0xc9, 0xaa, 0x8a, 0xe7, 0xcd, 0x4f, 0xdb, 0x00, 0x73, + 0x5a, 0xb0, 0x7f, 0x73, 0x5b, 0xa2, 0xdc, 0x4f, 0x82, 0xda, 0x2e, 0x1a, 0x55, 0x8d, 0xb2, 0x00, 0xa2, 0x4c, 0x9f, + 0xde, 0x40, 0x02, 0xd1, 0x39, 0xd5, 0x8b, 0xe6, 0xdb, 0xd4, 0x76, 0x38, 0x37, 0x45, 0xa0, 0x16, 0x2e, 0x8d, 0xd1, + 0x6c, 0xa6, 0x70, 0xc2, 0x7b, 0x97, 0xf6, 0x3c, 0x5d, 0x20, 0x4f, 0xb6, 0x80, 0x49, 0xdf, 0x0b, 0x3c, 0x6b, 0x00, + 0x0f, 0x08, 0xf4, 0x28, 0xaa, 0xd0, 0xc0, 0x9a, 0x82, 0x1d, 0x8c, 0x8a, 0x34, 0x0e, 0x80, 0x64, 0x9f, 0x46, 0xdc, + 0x80, 0x83, 0x73, 0x34, 0x86, 0x8e, 0x6d, 0xcf, 0xe4, 0x95, 0x14, 0x82, 0xa0, 0xca, 0x66, 0x89, 0xcd, 0x68, 0xb2, + 0x17, 0x95, 0x6f, 0x70, 0xb3, 0x73, 0x27, 0x18, 0xfb, 0x9d, 0xce, 0x00, 0xa6, 0xac, 0xa2, 0x77, 0x48, 0xcd, 0x88, + 0x17, 0x3a, 0x29, 0x9a, 0x1c, 0x88, 0x48, 0x46, 0xcc, 0x75, 0xe3, 0xb7, 0x7f, 0x1e, 0xe5, 0x66, 0x63, 0x5b, 0x6c, + 0x56, 0x3c, 0x23, 0x58, 0xef, 0xe0, 0xea, 0x2c, 0xbc, 0xd6, 0x33, 0xb2, 0x50, 0xf8, 0xc7, 0x30, 0xb9, 0x53, 0xdf, + 0xf7, 0xc4, 0x88, 0xe6, 0xf2, 0x7f, 0x97, 0xb1, 0xab, 0xca, 0x69, 0x34, 0x86, 0x86, 0x48, 0x46, 0x36, 0x01, 0x48, + 0xe6, 0x59, 0xd3, 0x31, 0x9a, 0x8d, 0xd5, 0xb6, 0x73, 0x9a, 0x66, 0x3f, 0x7e, 0xe5, 0xf4, 0xd7, 0x06, 0xc7, 0x03, + 0xe4, 0xe7, 0xce, 0x8d, 0x72, 0xf6, 0x03, 0x5b, 0xcc, 0xa1, 0xc7, 0xb9, 0x5c, 0xd5, 0x37, 0x8a, 0x5c, 0x8d, 0x90, + 0x8b, 0x41, 0xdf, 0x0d, 0x2a, 0x1e, 0x10, 0x40, 0x7f, 0x02, 0x5f, 0x79, 0x79, 0xfe, 0x5f, 0xa3, 0xb9, 0xe3, 0x91, + 0x60, 0x63, 0xe5, 0x32, 0x9c, 0xc4, 0xcb, 0x61, 0x3c, 0xe0, 0xe8, 0x39, 0x91, 0xf8, 0xb4, 0x22, 0xe9, 0x11, 0x89, + 0x0c, 0xe3, 0x91, 0x59, 0x1a, 0x52, 0x9c, 0x61, 0x84, 0xe2, 0x2f, 0xab, 0xdf, 0xae, 0xbb, 0x6f, 0x20, 0xc5, 0xbf, + 0x71, 0x5d, 0x1d, 0xcf, 0x8d, 0x2a, 0x33, 0xe9, 0x65, 0x73, 0xdc, 0x92, 0xb3, 0x9a, 0x56, 0x33, 0x9f, 0xb5, 0x4b, + 0xa6, 0xed, 0xe6, 0xb1, 0x9c, 0x19, 0x3f, 0x4f, 0x13, 0xc9, 0xe0, 0x6f, 0xce, 0x61, 0x80, 0x16, 0x06, 0xda, 0x4b, + 0xec, 0xd4, 0xa0, 0xd3, 0xd5, 0x9b, 0x0d, 0x31, 0xda, 0xae, 0xd6, 0xe9, 0x07, 0x5c, 0x2f, 0xe8, 0x18, 0x76, 0xd6, + 0x74, 0xf2, 0x9c, 0x10, 0xbb, 0x28, 0xf8, 0xf1, 0xfb, 0xae, 0xa0, 0xd4, 0x34, 0xa0, 0x5f, 0xe7, 0xe5, 0xe5, 0xae, + 0x76, 0x91, 0x81, 0x9a, 0x09, 0xe8, 0x90, 0xdd, 0x30, 0xe6, 0x58, 0x17, 0x63, 0x0f, 0xd2, 0x85, 0x71, 0x6b, 0xf6, + 0x41, 0x68, 0x8c, 0xb2, 0x70, 0x65, 0x4c, 0x2e, 0x0a, 0x5f, 0x93, 0x93, 0x6b, 0xb8, 0xa0, 0x25, 0xb4, 0xcf, 0xbd, + 0x77, 0x0e, 0xd3, 0x3d, 0xc2, 0x51, 0x5b, 0x7a, 0x91, 0x16, 0xea, 0xcd, 0x42, 0x79, 0x56, 0x80, 0x16, 0x2c, 0x52, + 0x4f, 0xab, 0xe5, 0xc8, 0xe5, 0x5d, 0x3f, 0x3a, 0x3d, 0x75, 0xab, 0xb5, 0xdc, 0x63, 0x4a, 0x03, 0xe1, 0x1d, 0xad, + 0xec, 0xbf, 0xe2, 0x25, 0x47, 0x2a, 0x6c, 0xd5, 0x2c, 0x93, 0xaf, 0xc8, 0xf5, 0x3f, 0x6a, 0x7a, 0x13, 0xef, 0x13, + 0xae, 0x0a, 0x84, 0x3b, 0x12, 0xa1, 0x33, 0x9e, 0x32, 0xeb, 0x68, 0x1d, 0xaf, 0xa9, 0x13, 0x3b, 0x1e, 0x1e, 0x17, + 0x28, 0x86, 0xdf, 0x9a, 0xd1, 0x80, 0xe7, 0xbe, 0x78, 0x11, 0xec, 0x5e, 0xfb, 0x2e, 0x39, 0x33, 0x8b, 0x6c, 0x7f, + 0xd5, 0x6a, 0xdc, 0x85, 0xd8, 0xb4, 0xca, 0xdc, 0x15, 0xfb, 0xec, 0x30, 0x9c, 0x6b, 0xc6, 0x17, 0x07, 0xb7, 0x7b, + 0x23, 0x77, 0x07, 0x6f, 0x9e, 0x12, 0x47, 0xd7, 0x02, 0x1e, 0x97, 0x9b, 0xbc, 0x5b, 0x55, 0xba, 0x5f, 0x1b, 0xf5, + 0x6a, 0x5f, 0x23, 0xfb, 0x92, 0x80, 0xe4, 0x71, 0x3d, 0xa4, 0x88, 0xe3, 0xa9, 0xc8, 0xd6, 0x84, 0xb1, 0x0e, 0x0a, + 0x1e, 0x6a, 0x3d, 0xb7, 0xed, 0xa4, 0xf6, 0x83, 0x72, 0xb7, 0x2e, 0xca, 0xca, 0xc3, 0xe1, 0xb7, 0xcd, 0x8f, 0x07, + 0xee, 0x25, 0x85, 0xe2, 0xa1, 0xfa, 0x2a, 0x02, 0x03, 0xee, 0x57, 0xd4, 0x9a, 0xcc, 0x8a, 0xe3, 0x27, 0xec, 0x94, + 0xca, 0x14, 0xa3, 0x83, 0x9b, 0xb6, 0x3b, 0x4d, 0x03, 0x18, 0x1d, 0xd3, 0x75, 0xb2, 0x33, 0xf5, 0xf8, 0x84, 0x88, + 0x1c, 0x53, 0xfb, 0x9f, 0xca, 0x8b, 0xd3, 0x01, 0xde, 0x07, 0xfb, 0xaf, 0x98, 0x40, 0x6c, 0xad, 0xbb, 0x49, 0x9d, + 0x86, 0x48, 0xc1, 0x87, 0x35, 0x6d, 0xfc, 0x5f, 0x7c, 0x2e, 0x8c, 0x26, 0xa2, 0x77, 0xea, 0xad, 0x2b, 0x25, 0xb0, + 0x5d, 0xed, 0x52, 0xe8, 0xb6, 0xb7, 0xba, 0x89, 0x71, 0x59, 0xf0, 0x86, 0x4e, 0xef, 0xc8, 0xfa, 0x49, 0xd0, 0x86, + 0xdc, 0x3b, 0x75, 0x19, 0x71, 0x88, 0x91, 0x94, 0xb3, 0x8b, 0xb1, 0xd4, 0x86, 0xd0, 0xc5, 0x16, 0x65, 0x4d, 0xee, + 0xfa, 0xfb, 0x53, 0x74, 0x18, 0x5a, 0x22, 0x8d, 0xf2, 0xbc, 0x03, 0xb6, 0x5e, 0xdd, 0x29, 0xaa, 0xb8, 0x1d, 0xae, + 0x6c, 0x5d, 0x02, 0xbd, 0x4e, 0x0c, 0xbe, 0xd8, 0x51, 0x83, 0x02, 0xde, 0x08, 0xdd, 0x64, 0xd2, 0x35, 0xc4, 0x70, + 0x36, 0xce, 0x3e, 0xa6, 0x1c, 0xf3, 0x73, 0xbf, 0x34, 0x5f, 0x56, 0x52, 0x3b, 0x41, 0x4c, 0x18, 0x90, 0xeb, 0x59, + 0x71, 0xa4, 0xfa, 0xf6, 0xf4, 0xaf, 0x4d, 0xe1, 0xff, 0x8e, 0x0d, 0xdf, 0xea, 0x30, 0x22, 0x19, 0xf5, 0x0a, 0x3b, + 0x04, 0x3a, 0x83, 0xba, 0xa4, 0x30, 0xe9, 0x43, 0x40, 0x9d, 0xb8, 0xc6, 0xf5, 0x54, 0x1e, 0x21, 0xf4, 0x4d, 0x1a, + 0x54, 0xce, 0x6d, 0x3b, 0xd4, 0x5b, 0xdf, 0x13, 0x51, 0x02, 0x84, 0x47, 0xa3, 0x00, 0x5a, 0x64, 0x32, 0xb8, 0x37, + 0x38, 0x80, 0xb0, 0x2e, 0xa5, 0x9c, 0xd1, 0x5a, 0xd2, 0x75, 0x68, 0x3e, 0x6e, 0xb1, 0xbe, 0xd5, 0x09, 0x39, 0x82, + 0x54, 0xea, 0xe9, 0x53, 0x35, 0x5d, 0xa4, 0x97, 0x98, 0x2d, 0x9d, 0xf2, 0x79, 0x80, 0xd8, 0x86, 0x5e, 0x58, 0x74, + 0x9f, 0xcf, 0xe5, 0x21, 0x40, 0xa6, 0xb9, 0x04, 0x24, 0x5c, 0x52, 0x50, 0x3f, 0x02, 0x93, 0x72, 0xf9, 0x1f, 0x15, + 0xd2, 0xeb, 0xdc, 0x1d, 0xbe, 0x7a, 0xbd, 0x58, 0xd5, 0x1a, 0x59, 0xbf, 0xf1, 0x03, 0x5d, 0xe5, 0xf5, 0xaa, 0xd6, + 0x9e, 0x2f, 0xd8, 0x8c, 0x0e, 0xd2, 0x8d, 0xf4, 0x3f, 0xf9, 0x07, 0x63, 0xa9, 0xb3, 0x23, 0xfa, 0x16, 0x57, 0xe2, + 0xba, 0xaf, 0xa7, 0xf7, 0x50, 0x5e, 0x3c, 0x49, 0x93, 0x65, 0xca, 0x6a, 0xd3, 0xfa, 0xb0, 0x53, 0x04, 0x42, 0xd4, + 0xd1, 0xcb, 0xb8, 0xe4, 0xc0, 0x45, 0x59, 0xba, 0x5e, 0x80, 0x7f, 0xf6, 0x0f, 0xa3, 0x13, 0x68, 0xa0, 0xd8, 0xb0, + 0xfb, 0x7e, 0x47, 0x65, 0xe7, 0x42, 0x0e, 0x4d, 0xf4, 0xbe, 0xda, 0x29, 0x93, 0x33, 0x75, 0x67, 0x9f, 0x93, 0xe8, + 0x86, 0x3a, 0x90, 0x57, 0x06, 0x1c, 0xa7, 0x5e, 0xec, 0xf7, 0x60, 0x98, 0x15, 0xbe, 0xec, 0x59, 0xb7, 0xfd, 0x09, + 0x83, 0x29, 0xc8, 0x5a, 0xee, 0x2c, 0x8a, 0xe5, 0x5d, 0xc8, 0xab, 0xa8, 0xb1, 0x5c, 0x4c, 0xac, 0x10, 0xca, 0x02, + 0xb6, 0x9c, 0xdc, 0x8f, 0x42, 0x90, 0x7b, 0x9c, 0xe3, 0xcd, 0xce, 0x39, 0x52, 0xee, 0x12, 0xcc, 0xee, 0xb0, 0xc5, + 0x69, 0x22, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x4a, 0x54, 0x51, 0xe4, 0xa6, 0x98, 0xa8, 0xe2, 0xa8, 0x6b, 0x7b, + 0xa3, 0x6d, 0x23, 0x65, 0x90, 0xc8, 0x30, 0x23, 0xa4, 0xa7, 0xf9, 0xe1, 0xee, 0xcd, 0x3e, 0x99, 0x32, 0x06, 0x11, + 0xd0, 0xa8, 0x7a, 0x06, 0x10, 0x7a, 0xbe, 0xac, 0x5d, 0xf2, 0x58, 0x56, 0x30, 0x92, 0xbe, 0x02, 0x1a, 0x2e, 0x9a, + 0x74, 0xc3, 0x2f, 0xc1, 0x49, 0xac, 0x78, 0x9a, 0x00, 0x45, 0xa3, 0xad, 0xf2, 0x6c, 0x88, 0xaf, 0x3c, 0x0e, 0x3a, + 0x51, 0x4f, 0x1a, 0x14, 0xc1, 0x60, 0x9a, 0x8d, 0x24, 0xdc, 0x52, 0x93, 0x41, 0xac, 0x0c, 0xc4, 0xd1, 0xbf, 0xb4, + 0x52, 0xa6, 0x54, 0xbb, 0x5a, 0x30, 0x32, 0xa3, 0x07, 0xd3, 0xdf, 0x85, 0xa8, 0x61, 0xd5, 0x08, 0xfd, 0x45, 0xa6, + 0x4e, 0x75, 0xca, 0xc8, 0x4b, 0x8c, 0xd3, 0xc4, 0xc0, 0x18, 0x72, 0xa0, 0x71, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, + 0xb6, 0x8c, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, 0x6e, 0xe9, 0xfa, 0xcf, 0x65, 0xb6, 0x61, 0xc7, 0x9c, 0xbf, + 0xf4, 0xd3, 0x6e, 0xfa, 0x30, 0xc6, 0xbc, 0x19, 0x07, 0xc3, 0x0c, 0xae, 0xbf, 0x48, 0x8b, 0x47, 0x45, 0x83, 0x2c, + 0x5f, 0x6a, 0x8c, 0x23, 0xed, 0xef, 0x07, 0xaa, 0xb7, 0xbb, 0x8d, 0x49, 0xd2, 0x00, 0x28, 0x47, 0x68, 0x44, 0x70, + 0xec, 0x8a, 0xff, 0x38, 0xaa, 0xfc, 0xef, 0xee, 0x7a, 0x8b, 0x1e, 0x84, 0x2f, 0xf6, 0xa6, 0x4f, 0xa3, 0x80, 0x39, + 0x6b, 0xdd, 0xae, 0x3e, 0x8d, 0xa9, 0x21, 0xfd, 0x35, 0x01, 0xe3, 0xc6, 0xb1, 0xfa, 0xc7, 0x34, 0x25, 0xbf, 0xd7, + 0x63, 0x12, 0x5f, 0x2c, 0xfa, 0xca, 0x1a, 0x55, 0xea, 0xd1, 0x65, 0x38, 0x6d, 0xc9, 0x68, 0x4f, 0xca, 0xb7, 0xba, + 0xc3, 0xd3, 0xb6, 0x4b, 0x6a, 0x36, 0xef, 0x89, 0xf9, 0xec, 0xba, 0xda, 0x56, 0xe2, 0x88, 0xf4, 0x20, 0x5f, 0x4f, + 0x19, 0xa5, 0xa3, 0x4f, 0xd1, 0xde, 0xef, 0x8e, 0x03, 0x99, 0xa7, 0xc7, 0xa1, 0x56, 0xd7, 0xae, 0xec, 0xf8, 0x56, + 0x9c, 0x98, 0xd4, 0x58, 0x86, 0xec, 0xd7, 0xb8, 0x11, 0x0d, 0x3a, 0xee, 0x7d, 0xd5, 0x7a, 0xdd, 0xd4, 0x98, 0x0e, + 0x4e, 0x31, 0x04, 0xcd, 0x57, 0x5d, 0x12, 0x55, 0xc4, 0x82, 0x37, 0xc4, 0x07, 0x71, 0x01, 0x80, 0x9c, 0x93, 0x16, + 0xb5, 0xec, 0x18, 0x4b, 0xa2, 0x7c, 0x57, 0x81, 0x5a, 0xf2, 0xec, 0xa2, 0xa2, 0x53, 0x77, 0xa2, 0x57, 0xa7, 0x5e, + 0xa5, 0x39, 0x8d, 0xd0, 0xf5, 0xf0, 0x99, 0xe7, 0xa8, 0x64, 0x59, 0xf7, 0xae, 0x42, 0x5f, 0xb1, 0xd7, 0x5e, 0x49, + 0xc9, 0x3b, 0x52, 0x1a, 0x0a, 0x19, 0xc5, 0x1a, 0x34, 0xb6, 0xce, 0x5d, 0x62, 0x49, 0x27, 0xcb, 0xa3, 0x86, 0xc2, + 0x17, 0x73, 0x1f, 0xb7, 0xc6, 0x51, 0x39, 0xe6, 0x1c, 0xc0, 0x9e, 0x54, 0xe9, 0x64, 0xaa, 0x1c, 0xc0, 0xaf, 0x69, + 0x16, 0x11, 0x83, 0x94, 0xda, 0xe9, 0xb8, 0x8b, 0xb3, 0x64, 0x3b, 0x61, 0xd0, 0xb1, 0xe8, 0x39, 0x7a, 0x20, 0xd2, + 0x79, 0x1c, 0x44, 0xf7, 0x91, 0xc7, 0x0d, 0x32, 0x0c, 0xb6, 0x67, 0x2d, 0x79, 0x94, 0xb9, 0xe2, 0x28, 0xbb, 0x12, + 0x53, 0xcb, 0xb3, 0xa9, 0xdb, 0x33, 0xba, 0x62, 0xad, 0xac, 0xe9, 0xee, 0x88, 0x4c, 0x05, 0xf7, 0x7d, 0x7b, 0x86, + 0x4f, 0x47, 0x46, 0x8e, 0x33, 0x89, 0xa3, 0x3a, 0x84, 0xb9, 0x71, 0x22, 0x78, 0x82, 0xd1, 0xb2, 0x25, 0xf3, 0x94, + 0x53, 0x0a, 0xb5, 0xf7, 0xbf, 0x34, 0x1e, 0xa1, 0x6a, 0xae, 0x61, 0x7a, 0xcb, 0xd0, 0x1d, 0xc2, 0x76, 0xfd, 0x43, + 0x74, 0x32, 0xa2, 0x05, 0xef, 0x2f, 0x92, 0x0a, 0xc6, 0x5a, 0x5a, 0x95, 0xb6, 0xbe, 0xdd, 0x43, 0x02, 0x96, 0xa7, + 0x56, 0x9d, 0xa1, 0x80, 0x15, 0xa6, 0xcf, 0xf9, 0x9b, 0xb9, 0xc6, 0x21, 0x77, 0x2d, 0x11, 0x10, 0x1b, 0x81, 0xdd, + 0xd0, 0x09, 0x12, 0x18, 0xaa, 0x10, 0xfb, 0xac, 0x55, 0xf1, 0x9c, 0x37, 0x85, 0x1e, 0xf0, 0x23, 0x9f, 0xc4, 0x92, + 0xfa, 0x09, 0x92, 0xfc, 0x09, 0x97, 0x84, 0xd0, 0xa7, 0xfc, 0x22, 0xf6, 0xaa, 0xc9, 0x4d, 0xad, 0x34, 0xdb, 0x0e, + 0xc5, 0xcf, 0xfc, 0x62, 0xdc, 0xdd, 0x68, 0x88, 0x21, 0x62, 0x85, 0x11, 0x0a, 0xc6, 0x9c, 0xa0, 0x6e, 0xf2, 0x57, + 0xa4, 0xf8, 0x74, 0xce, 0xe6, 0x5b, 0xf8, 0x4e, 0xdb, 0xe9, 0x1d, 0x14, 0x0a, 0x31, 0xea, 0x0c, 0x2d, 0x61, 0xd8, + 0xc3, 0x93, 0xf9, 0xec, 0xc2, 0x9c, 0x84, 0x24, 0x15, 0x2d, 0x4a, 0x38, 0x43, 0xfc, 0x06, 0xc0, 0x04, 0x9a, 0xac, + 0x44, 0xa9, 0xa8, 0x81, 0x3d, 0x82, 0x5f, 0xb8, 0xd9, 0xe6, 0xf3, 0x56, 0xe4, 0xe1, 0x40, 0x1a, 0xe5, 0x0a, 0x6d, + 0x20, 0xa6, 0x7a, 0x6e, 0x23, 0xb1, 0x18, 0x19, 0x45, 0x6b, 0xc9, 0x97, 0x5a, 0x42, 0x5d, 0xec, 0x3c, 0x08, 0xd6, + 0x55, 0x77, 0x95, 0x9d, 0xa1, 0x59, 0x31, 0x83, 0x03, 0x39, 0x2e, 0xd0, 0x30, 0x44, 0xba, 0x31, 0xd9, 0xa6, 0x98, + 0x65, 0x23, 0x7c, 0x5f, 0xc5, 0xbc, 0xc9, 0x6b, 0x21, 0xf2, 0x5a, 0x9d, 0x49, 0xb0, 0x86, 0x09, 0x79, 0x6a, 0x60, + 0x96, 0x24, 0xa4, 0x61, 0x09, 0xcb, 0x13, 0x3e, 0x43, 0xbd, 0x64, 0x98, 0x66, 0x64, 0xfa, 0xe0, 0x49, 0xbf, 0x65, + 0xfd, 0x89, 0x37, 0xf2, 0xf3, 0x46, 0x13, 0x78, 0x51, 0x09, 0x55, 0x2e, 0xb6, 0x19, 0x22, 0xba, 0xd5, 0x52, 0xc3, + 0x73, 0xea, 0x96, 0x27, 0x40, 0xe2, 0x49, 0x9f, 0x19, 0x7e, 0xb4, 0xcd, 0x08, 0x81, 0x54, 0xe9, 0xad, 0x8b, 0x90, + 0xd9, 0x27, 0x65, 0xe5, 0xe1, 0xf0, 0xe4, 0xd2, 0x69, 0x09, 0x95, 0xc0, 0xf5, 0x9b, 0xd7, 0x05, 0x54, 0x81, 0x99, + 0xa1, 0x58, 0x63, 0x53, 0x3d, 0x1b, 0x6f, 0x90, 0x66, 0x30, 0x2e, 0x22, 0xa1, 0x42, 0xe6, 0xce, 0x25, 0x9a, 0xba, + 0x5e, 0xcc, 0x19, 0xcb, 0xcb, 0x3e, 0xec, 0xf9, 0xd2, 0x53, 0xcc, 0x2e, 0xbc, 0xd6, 0x2f, 0x99, 0xe3, 0xf6, 0x59, + 0x48, 0xb3, 0xdc, 0x9d, 0x22, 0x35, 0x7b, 0xac, 0x92, 0x9a, 0x07, 0xb0, 0xae, 0xb3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, + 0x61, 0x7f, 0x82, 0x3b, 0x80, 0x63, 0x04, 0x43, 0x12, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0x30, 0xf2, 0xcd, 0xc7, 0x41, + 0x1b, 0x82, 0xc8, 0x04, 0x89, 0x10, 0x31, 0x91, 0xc7, 0xf0, 0xf3, 0x01, 0xce, 0xbe, 0xba, 0x4c, 0x34, 0x51, 0xbc, + 0x11, 0x8a, 0x69, 0x78, 0x0d, 0x77, 0xeb, 0xc0, 0x8c, 0xce, 0x7b, 0x3a, 0x45, 0x57, 0xd0, 0x24, 0xa6, 0x56, 0x4f, + 0x9b, 0xf7, 0xdc, 0x23, 0xc2, 0x2f, 0x74, 0x51, 0xdc, 0xdd, 0xc1, 0x7a, 0xbd, 0x80, 0x25, 0x13, 0xf9, 0x96, 0x33, + 0xf3, 0x66, 0xca, 0x1e, 0x92, 0x63, 0x9f, 0x3e, 0x3c, 0x6e, 0x17, 0xfb, 0xe4, 0x39, 0x2e, 0xb2, 0x5e, 0x52, 0x85, + 0x3d, 0x29, 0xff, 0x9b, 0x32, 0xe6, 0x44, 0x04, 0x35, 0x95, 0xe9, 0xda, 0xa2, 0xe3, 0xcf, 0x2a, 0x9a, 0x2c, 0x8d, + 0x60, 0x6b, 0x54, 0x91, 0x7e, 0x69, 0x94, 0x52, 0x1d, 0x51, 0x0f, 0x43, 0x9b, 0x48, 0xb1, 0xd0, 0x28, 0x70, 0x74, + 0xa9, 0x4d, 0xf0, 0x6c, 0x15, 0xf4, 0x48, 0x7c, 0xa4, 0x9d, 0xd8, 0xe6, 0xfc, 0x7c, 0x4f, 0xf1, 0x4d, 0xf2, 0x5b, + 0xfa, 0x5b, 0x70, 0x93, 0x42, 0x93, 0xc5, 0xb5, 0xbc, 0xb5, 0x72, 0x8b, 0xdf, 0xe5, 0x63, 0x5f, 0xa3, 0x8b, 0x83, + 0x51, 0x3a, 0x99, 0xf3, 0x5e, 0x78, 0xc8, 0xb5, 0x93, 0x57, 0x62, 0xaf, 0x66, 0x2b, 0xc5, 0x95, 0x60, 0xe1, 0xc1, + 0xa9, 0x2b, 0x99, 0x8a, 0x56, 0x10, 0xc8, 0xbc, 0x71, 0xdb, 0xaf, 0x7f, 0x20, 0xa3, 0x6d, 0x08, 0x19, 0xcc, 0xda, + 0xea, 0x25, 0xa6, 0xf3, 0xbe, 0x45, 0xbe, 0x64, 0x6f, 0x6c, 0x59, 0xf7, 0x10, 0x88, 0xfe, 0xe4, 0x78, 0x37, 0x64, + 0x05, 0x16, 0x0a, 0xfb, 0x12, 0xd0, 0x93, 0xa8, 0xaa, 0xd4, 0x5e, 0xea, 0x50, 0xae, 0xab, 0x19, 0x2a, 0x54, 0xcb, + 0xeb, 0x1f, 0x40, 0x22, 0x8e, 0x52, 0x06, 0xed, 0xe9, 0xa2, 0x2a, 0x23, 0x82, 0xc0, 0xb8, 0x08, 0x0d, 0x2b, 0xc4, + 0x14, 0x76, 0x59, 0xc5, 0x38, 0x4e, 0x57, 0xf7, 0xf5, 0x8b, 0x53, 0x88, 0xbd, 0xee, 0x86, 0xac, 0x12, 0x74, 0xee, + 0xba, 0xec, 0xd3, 0x1c, 0xfa, 0x99, 0xae, 0x7f, 0x04, 0x37, 0x39, 0x87, 0x35, 0x29, 0x38, 0x35, 0xf5, 0x39, 0x8b, + 0x25, 0xdf, 0x08, 0x15, 0x4e, 0x5b, 0x32, 0xda, 0xb1, 0x63, 0x56, 0xe5, 0xc7, 0x2e, 0x4b, 0x69, 0x60, 0x48, 0xa2, + 0xba, 0x36, 0xe8, 0x18, 0xb4, 0x24, 0x72, 0xf3, 0xea, 0x70, 0x49, 0x7b, 0x43, 0xc8, 0x0f, 0x37, 0xa7, 0xfb, 0x94, + 0xd0, 0xc6, 0x6a, 0xf1, 0xca, 0xc5, 0x97, 0x44, 0xa4, 0xbc, 0xe0, 0x1e, 0x01, 0xeb, 0x77, 0x22, 0xfc, 0xbb, 0xe8, + 0xc1, 0x81, 0x47, 0x00, 0x8b, 0xf0, 0x56, 0xdc, 0x57, 0xde, 0x26, 0x94, 0x56, 0xa0, 0x2e, 0xd7, 0xa6, 0x51, 0x82, + 0x37, 0xa4, 0xff, 0xf0, 0xc8, 0xbe, 0xcc, 0x13, 0xb6, 0x51, 0x21, 0xf1, 0x0e, 0xbf, 0xf3, 0x77, 0x4f, 0xc7, 0x9c, + 0x00, 0xbb, 0xa5, 0xd3, 0xbc, 0x6a, 0x0b, 0x90, 0x16, 0x5d, 0x0c, 0x62, 0x9c, 0x82, 0xe5, 0x95, 0x00, 0xe9, 0x87, + 0x57, 0x61, 0xa1, 0xeb, 0xf9, 0x7b, 0x4d, 0xf7, 0xca, 0x5e, 0x87, 0x69, 0xf2, 0x65, 0xef, 0x88, 0x46, 0xd0, 0xcb, + 0xd5, 0xc9, 0xe5, 0xfb, 0x94, 0x72, 0xe1, 0x5f, 0xd2, 0xd5, 0xcf, 0x54, 0x89, 0xe6, 0xaa, 0x6f, 0xaa, 0xf8, 0x94, + 0xab, 0xf1, 0x09, 0xa4, 0xda, 0x9c, 0x57, 0x13, 0xe6, 0xca, 0x55, 0x9f, 0xdc, 0x77, 0x17, 0x98, 0x56, 0x6f, 0xfd, + 0xdb, 0xfd, 0x30, 0xd0, 0x9f, 0xdd, 0xdf, 0x1c, 0x7c, 0x9d, 0x5d, 0x74, 0x76, 0x3a, 0xf6, 0x2f, 0xe4, 0xc7, 0x11, + 0xba, 0xac, 0x87, 0xa2, 0x26, 0x72, 0xc2, 0x7b, 0xea, 0xa8, 0x61, 0x2f, 0xb7, 0x94, 0x79, 0x31, 0x7d, 0x2f, 0x59, + 0x05, 0x94, 0xdf, 0xb7, 0xd9, 0xa5, 0xd5, 0x84, 0xe2, 0x02, 0x92, 0x2e, 0x73, 0x9a, 0x95, 0x6e, 0xa4, 0x50, 0xb3, + 0xc9, 0x5e, 0x46, 0x56, 0xe9, 0xb5, 0x12, 0xec, 0x57, 0x8b, 0x60, 0x58, 0x56, 0xe9, 0x2a, 0x8f, 0x3a, 0x6c, 0xd6, + 0xae, 0xad, 0xd3, 0x7f, 0xb9, 0xb9, 0x9c, 0x09, 0xa2, 0xec, 0xa0, 0x56, 0xf2, 0x8c, 0x2b, 0x7d, 0xce, 0xb5, 0x52, + 0x77, 0x3a, 0xde, 0xab, 0x3f, 0x57, 0xcd, 0x27, 0x4b, 0x4b, 0xf7, 0xbd, 0x0e, 0xff, 0xd9, 0x95, 0xb5, 0x14, 0x41, + 0x16, 0x43, 0xea, 0x3d, 0x63, 0x67, 0x25, 0x53, 0x42, 0x01, 0xc4, 0x2f, 0x3c, 0xae, 0x5d, 0x07, 0xcd, 0xbb, 0xd2, + 0xed, 0xa7, 0xab, 0xd6, 0xaa, 0x90, 0xf2, 0x78, 0x63, 0x19, 0x51, 0x98, 0xb8, 0xaa, 0x95, 0x61, 0x9a, 0x37, 0x7f, + 0xef, 0x9e, 0xf4, 0x57, 0xc5, 0xcb, 0x6a, 0x22, 0x8a, 0x98, 0xae, 0x79, 0xbc, 0xb1, 0x7a, 0x37, 0x87, 0xb5, 0x79, + 0xf1, 0x5c, 0x8d, 0x2f, 0x5a, 0xff, 0x5c, 0x75, 0x6c, 0x0d, 0x63, 0x52, 0x39, 0xcf, 0x3b, 0xbf, 0x29, 0x29, 0x8d, + 0xb4, 0x8c, 0x36, 0x4e, 0x8a, 0x99, 0x0a, 0x2f, 0x57, 0xef, 0x54, 0x27, 0xaa, 0x10, 0x19, 0x1c, 0x3c, 0x23, 0xb8, + 0xbf, 0xfd, 0xf3, 0x51, 0x59, 0xb7, 0xb6, 0x8d, 0xe5, 0x8d, 0xbc, 0x92, 0x68, 0xfc, 0x2e, 0x96, 0xcb, 0x16, 0xe6, + 0x5b, 0xfb, 0xa6, 0x29, 0x97, 0xb5, 0x89, 0xa4, 0x8e, 0xd2, 0x27, 0xc5, 0x65, 0xa4, 0x2a, 0xbd, 0x4f, 0x40, 0xa2, + 0x97, 0x46, 0xfa, 0x0c, 0x23, 0xa5, 0x1e, 0xc9, 0x8e, 0x10, 0x21, 0x40, 0x80, 0x66, 0xe7, 0xaa, 0xbd, 0x4c, 0x97, + 0x0c, 0xce, 0xc8, 0xa4, 0x40, 0x9f, 0x61, 0x76, 0x35, 0x17, 0x09, 0xc1, 0x19, 0xa1, 0x03, 0xe9, 0x26, 0x63, 0x25, + 0xf8, 0x67, 0xa4, 0x1a, 0x35, 0x6d, 0xa6, 0xae, 0xb1, 0xf3, 0xb5, 0xb0, 0xe6, 0x87, 0x0e, 0xd9, 0xc5, 0x89, 0x45, + 0x89, 0xbe, 0x70, 0x24, 0x66, 0xe9, 0x49, 0x5d, 0x69, 0x0d, 0xdd, 0x85, 0x5b, 0x5c, 0xef, 0x5c, 0x76, 0xc9, 0x2f, + 0xe3, 0x4d, 0x2b, 0xd2, 0x1c, 0x53, 0x74, 0xf9, 0x26, 0x58, 0x0b, 0x70, 0xa0, 0xcc, 0xcb, 0x57, 0x3d, 0x02, 0x57, + 0x7e, 0x80, 0x8b, 0xe8, 0x65, 0x3e, 0x82, 0x08, 0xce, 0x4d, 0x95, 0x16, 0x5a, 0x98, 0x3d, 0x02, 0x3c, 0xd6, 0x6b, + 0xfe, 0x14, 0xfa, 0x99, 0x29, 0x5e, 0x0a, 0x27, 0xcf, 0x5a, 0xa3, 0x76, 0x0f, 0x31, 0xf8, 0x94, 0xac, 0xd6, 0xc4, + 0x22, 0xa7, 0x71, 0x9d, 0x53, 0x8f, 0x8f, 0x66, 0xcb, 0x7c, 0x90, 0x98, 0x15, 0xc0, 0xe4, 0x34, 0xae, 0x51, 0xe2, + 0x6d, 0xa6, 0xaa, 0x76, 0x46, 0x39, 0x8d, 0x2f, 0xc4, 0x90, 0x4c, 0x52, 0x31, 0xdf, 0x3e, 0x90, 0x51, 0x86, 0xc4, + 0x45, 0xc9, 0xad, 0xd5, 0x14, 0xa7, 0xad, 0x79, 0x43, 0x52, 0x7e, 0xc1, 0x28, 0xeb, 0xe6, 0xef, 0x52, 0x5f, 0xef, + 0xfe, 0x28, 0xa6, 0x4b, 0x8f, 0xab, 0xc3, 0x9b, 0x79, 0x75, 0x34, 0x91, 0x9e, 0xe6, 0xd4, 0x20, 0xf1, 0x5b, 0x0b, + 0xfe, 0x98, 0x1f, 0x2f, 0x35, 0xa6, 0x1a, 0x9a, 0xf8, 0xc8, 0x66, 0x8b, 0x2e, 0x2b, 0xbc, 0x71, 0x6e, 0x85, 0x2f, + 0xb5, 0x29, 0x16, 0xe3, 0xb3, 0xcf, 0x3b, 0x0d, 0xae, 0xa3, 0x78, 0x0f, 0x87, 0xd4, 0xd5, 0x8b, 0xa2, 0xa5, 0x3f, + 0x36, 0xfb, 0x3c, 0x8e, 0xf8, 0xc3, 0x9b, 0xfd, 0xb0, 0x04, 0xe6, 0xee, 0xd0, 0x4a, 0x8b, 0x03, 0x69, 0x2b, 0x39, + 0x5a, 0xef, 0xda, 0x7e, 0x8a, 0xd6, 0x44, 0x56, 0x63, 0x53, 0x41, 0xa9, 0x5e, 0x90, 0xff, 0xef, 0x6d, 0x6c, 0x55, + 0x32, 0x55, 0x3a, 0xe8, 0x3d, 0x24, 0xbd, 0x34, 0xf4, 0x15, 0x7d, 0xee, 0xe9, 0xb1, 0xde, 0xa9, 0x44, 0xbc, 0x8b, + 0xcb, 0x9c, 0x61, 0x36, 0x1b, 0xe6, 0xe6, 0x11, 0xbd, 0x95, 0x5e, 0xb1, 0xdb, 0x98, 0xf4, 0x34, 0x88, 0x65, 0x79, + 0x99, 0x53, 0xf7, 0x39, 0x09, 0x24, 0xfe, 0x39, 0x3c, 0x00, 0xff, 0xa4, 0x6b, 0xd0, 0x1c, 0x49, 0xe5, 0x72, 0x53, + 0xaf, 0x43, 0xbc, 0x6b, 0x77, 0x3c, 0x16, 0xe9, 0xeb, 0x26, 0x1a, 0xdf, 0xd0, 0x0d, 0xa5, 0xa8, 0xa9, 0x8c, 0x3a, + 0x8e, 0x0c, 0x97, 0x8c, 0xbc, 0x59, 0x91, 0x6b, 0xbf, 0x02, 0x79, 0x55, 0x00, 0x21, 0x48, 0x6b, 0x11, 0x4d, 0x4c, + 0xf6, 0x57, 0x43, 0xcd, 0x51, 0x9a, 0xd9, 0x26, 0x7f, 0xda, 0xc4, 0xee, 0xba, 0x05, 0xdc, 0xad, 0x1c, 0xa2, 0x8b, + 0xed, 0x31, 0x0f, 0x79, 0x04, 0xa3, 0x2d, 0x24, 0x0a, 0x59, 0x15, 0xa2, 0x85, 0xd3, 0xfc, 0x49, 0x3e, 0x55, 0x9e, + 0x02, 0x3c, 0x44, 0x41, 0x13, 0x96, 0xb2, 0x9b, 0xee, 0x4b, 0xb2, 0x74, 0xf4, 0x3c, 0x82, 0x0f, 0x50, 0x09, 0x0e, + 0xd0, 0x45, 0xce, 0xeb, 0xee, 0xc5, 0xb6, 0x11, 0xd9, 0xc8, 0xd6, 0x75, 0x4f, 0x07, 0x59, 0x6e, 0x2d, 0x2d, 0xfc, + 0xef, 0x8f, 0xbd, 0xaf, 0xee, 0x82, 0x1d, 0x60, 0x28, 0xef, 0x3e, 0x84, 0x16, 0xee, 0x38, 0xd4, 0xea, 0xc5, 0x8a, + 0x12, 0x05, 0x4f, 0x22, 0xf3, 0xc7, 0x4a, 0x76, 0xba, 0xc7, 0x56, 0x24, 0xde, 0x53, 0x37, 0xa8, 0xdb, 0xe5, 0x56, + 0x5d, 0x35, 0x7b, 0xb9, 0x2a, 0xec, 0x3f, 0x1b, 0xfa, 0xd1, 0x54, 0xc1, 0x07, 0x4c, 0x2f, 0x6e, 0x23, 0x2e, 0x0a, + 0x85, 0x35, 0x72, 0xfe, 0x01, 0x8c, 0xca, 0x9a, 0x17, 0x6e, 0x52, 0x2c, 0x83, 0xcb, 0xd0, 0x28, 0xee, 0xc4, 0x2d, + 0x86, 0x1a, 0x0f, 0x06, 0x3d, 0x0b, 0x4b, 0x90, 0x46, 0xf7, 0xe9, 0x3d, 0xce, 0x70, 0x12, 0xa4, 0xd5, 0xe7, 0xcd, + 0x09, 0x72, 0x8d, 0x77, 0x52, 0x6b, 0x44, 0x22, 0xcd, 0x1e, 0x47, 0x65, 0x6d, 0xf8, 0x18, 0xa6, 0xd1, 0x39, 0xa0, + 0xa8, 0x4d, 0x85, 0xad, 0x76, 0x8a, 0x50, 0xaa, 0xe3, 0x20, 0xb0, 0x69, 0xe9, 0xe3, 0x24, 0x2d, 0xe2, 0x40, 0x4f, + 0x25, 0x78, 0x5e, 0xd2, 0xfc, 0x96, 0x8a, 0xbc, 0x9f, 0x77, 0x82, 0x66, 0xfa, 0xbd, 0x82, 0x48, 0x79, 0xac, 0x44, + 0x1a, 0x46, 0x1d, 0x0c, 0x76, 0x6c, 0xc3, 0xab, 0x03, 0x18, 0xcf, 0x91, 0x4a, 0x46, 0x0d, 0x5c, 0xb9, 0xe2, 0xee, + 0x4b, 0x9b, 0x32, 0xe5, 0xda, 0x2a, 0xfc, 0xc8, 0x7c, 0xc9, 0x10, 0x2b, 0x5f, 0x35, 0x43, 0x89, 0xab, 0xd4, 0xb0, + 0xf6, 0x8b, 0xa9, 0x9b, 0x58, 0x5b, 0xc8, 0xe7, 0x8b, 0xbf, 0x46, 0x87, 0xb0, 0x0f, 0x20, 0xab, 0x9f, 0x2e, 0xc4, + 0x94, 0x5c, 0xc2, 0x04, 0x39, 0x57, 0x8c, 0x89, 0x77, 0x93, 0xc9, 0xa5, 0x3f, 0xcd, 0x16, 0xd8, 0x67, 0xd3, 0x4a, + 0xba, 0x5f, 0x92, 0x42, 0xfc, 0x1e, 0x0f, 0x1a, 0xd2, 0x13, 0x84, 0x98, 0x3d, 0x05, 0x8f, 0x6e, 0x56, 0x6e, 0xd4, + 0x1b, 0x49, 0xd0, 0x8e, 0xad, 0xd8, 0x02, 0x24, 0x38, 0xa0, 0x9e, 0xa8, 0xf1, 0x7d, 0xf0, 0x52, 0xe5, 0x97, 0x2f, + 0x0f, 0x11, 0x6a, 0x06, 0xe3, 0x89, 0xa4, 0x19, 0x3b, 0x54, 0x24, 0xf3, 0x15, 0x34, 0xf3, 0xe1, 0xae, 0xa7, 0x23, + 0xde, 0xec, 0xd0, 0x2b, 0x6d, 0xdc, 0xba, 0x27, 0xba, 0xb8, 0x22, 0x61, 0x68, 0xf5, 0xf1, 0xa0, 0xf2, 0xfe, 0x7c, + 0x39, 0x94, 0x57, 0xb6, 0xf2, 0x83, 0x70, 0x98, 0xb5, 0x3b, 0x78, 0xbe, 0x8e, 0x8c, 0x0f, 0x33, 0x92, 0xb3, 0x0c, + 0x16, 0x81, 0x07, 0x73, 0x96, 0xa2, 0x85, 0x6f, 0xca, 0x32, 0x1b, 0x64, 0x6a, 0xb4, 0x80, 0xc5, 0x8b, 0xfc, 0x1b, + 0x1b, 0x5f, 0x96, 0xd9, 0x58, 0xc1, 0xec, 0x75, 0x20, 0x3b, 0x25, 0x90, 0x98, 0xa3, 0xda, 0x9d, 0x0d, 0xa8, 0xa2, + 0x87, 0x27, 0x00, 0x57, 0xf0, 0x87, 0xc7, 0x2c, 0xd0, 0x39, 0x35, 0xce, 0xd7, 0xb0, 0x56, 0x1e, 0x35, 0x36, 0x59, + 0xd7, 0x44, 0x50, 0xa4, 0x16, 0xab, 0xd0, 0x4b, 0x92, 0x48, 0x1d, 0xaa, 0xfc, 0x8f, 0x2f, 0x9c, 0x53, 0x73, 0xef, + 0x68, 0xeb, 0x31, 0xd7, 0x13, 0xd2, 0x56, 0x51, 0x93, 0x33, 0x3d, 0x2e, 0xa1, 0xa0, 0xfc, 0x9c, 0x0a, 0x95, 0xe2, + 0xcb, 0x74, 0xe7, 0x66, 0x55, 0xc1, 0x00, 0x6a, 0x06, 0x30, 0xfa, 0x51, 0x40, 0x46, 0x6a, 0xfc, 0x78, 0xa2, 0x5e, + 0xf7, 0x31, 0x37, 0x74, 0xd0, 0xe2, 0x4c, 0x37, 0xb0, 0x47, 0xb2, 0x1d, 0x8e, 0x6a, 0x80, 0xf2, 0x21, 0x9e, 0x04, + 0x9e, 0x22, 0x9a, 0xa4, 0x59, 0x5f, 0xf1, 0xb7, 0xe9, 0xdc, 0xf6, 0x64, 0x1d, 0x00, 0x2d, 0x2c, 0x98, 0x41, 0xb3, + 0x49, 0xdf, 0x4b, 0xd0, 0x80, 0x1f, 0xc6, 0xce, 0x30, 0xdf, 0x3b, 0xa1, 0xf6, 0xce, 0x0e, 0xbd, 0x9e, 0x7d, 0xe5, + 0x9c, 0x70, 0x3e, 0x53, 0x2f, 0xc6, 0x51, 0xd8, 0x45, 0x9d, 0xc5, 0x93, 0x3f, 0x7c, 0xa6, 0xc2, 0x78, 0x4c, 0xc4, + 0x45, 0x2c, 0x35, 0xb8, 0x20, 0x89, 0x2d, 0x9b, 0xcd, 0x32, 0x0e, 0x7e, 0x26, 0xc3, 0x41, 0xc6, 0x04, 0x2f, 0x27, + 0xf4, 0xfe, 0x96, 0x48, 0x08, 0xb2, 0x21, 0x94, 0x4c, 0xd3, 0x90, 0x1a, 0xaf, 0x36, 0x97, 0x71, 0x99, 0xd1, 0x25, + 0xe3, 0xff, 0x66, 0x17, 0x14, 0xea, 0xb5, 0xa2, 0xe0, 0xfb, 0x2d, 0xdc, 0xf6, 0x1a, 0x9d, 0xb1, 0x67, 0xc8, 0xf4, + 0xa1, 0x39, 0x4c, 0x19, 0x29, 0x0c, 0x77, 0xed, 0x29, 0x48, 0x90, 0x99, 0x97, 0xe1, 0xfd, 0x86, 0xfd, 0x36, 0x60, + 0x0a, 0x1e, 0xdf, 0xfb, 0x66, 0x05, 0xd8, 0x1c, 0x69, 0xa8, 0x7b, 0xee, 0x29, 0xa0, 0x1c, 0xe6, 0xc2, 0xc3, 0x1c, + 0xba, 0x42, 0xb5, 0x0f, 0xb9, 0xab, 0xa7, 0x7a, 0x15, 0x0b, 0xcb, 0xc1, 0xa6, 0x6e, 0x54, 0x9b, 0x84, 0xea, 0xb8, + 0x5c, 0x03, 0xd2, 0x9e, 0xd0, 0x0c, 0xb4, 0x1e, 0x46, 0x54, 0xeb, 0x64, 0x97, 0xde, 0x4a, 0x30, 0xba, 0x24, 0x91, + 0x06, 0x26, 0xcb, 0x9c, 0xd4, 0x00, 0xa6, 0x45, 0x98, 0x03, 0xbf, 0x23, 0x39, 0xae, 0x91, 0x80, 0xce, 0x71, 0xd8, + 0x35, 0xac, 0x26, 0xa5, 0xf3, 0x5c, 0xb5, 0x24, 0x15, 0xa4, 0x22, 0x42, 0x25, 0x53, 0x25, 0xa5, 0x63, 0xc2, 0x39, + 0xae, 0x06, 0x24, 0xc3, 0x94, 0x0a, 0x6a, 0x6f, 0xa3, 0x52, 0x1a, 0xcb, 0x59, 0x18, 0x3e, 0x71, 0xf9, 0x33, 0xaa, + 0xf9, 0xb2, 0x65, 0x23, 0x89, 0xec, 0x35, 0xd3, 0xc5, 0x82, 0x3b, 0xf3, 0x27, 0x70, 0x07, 0xbe, 0xfb, 0x8a, 0x9a, + 0xf2, 0xbe, 0x3c, 0x18, 0x25, 0x26, 0x32, 0x7e, 0x4d, 0xf5, 0x15, 0xcc, 0x65, 0x3e, 0x43, 0x28, 0xd3, 0x6f, 0x3d, + 0x56, 0x67, 0x0b, 0x61, 0x53, 0x49, 0xec, 0xfe, 0xfd, 0xe4, 0x87, 0x02, 0x5e, 0xf0, 0x43, 0x8f, 0xcf, 0x56, 0x13, + 0x04, 0x89, 0x45, 0xb3, 0x0a, 0x7b, 0x8b, 0x9c, 0x18, 0x40, 0x54, 0xf6, 0x68, 0x6e, 0x2f, 0xa9, 0xa1, 0x23, 0x52, + 0x8f, 0x3b, 0x27, 0xac, 0xec, 0x6d, 0x4b, 0x9e, 0xbd, 0x5a, 0xd5, 0x53, 0xaa, 0x63, 0xc2, 0x80, 0x9b, 0xbf, 0xf1, + 0x75, 0x6e, 0xeb, 0xbb, 0x1b, 0x30, 0xd8, 0x12, 0xed, 0xc7, 0x91, 0x22, 0x80, 0x9d, 0x60, 0x8a, 0x43, 0xce, 0xf9, + 0xf1, 0xa6, 0x7a, 0xf9, 0xbf, 0x27, 0x47, 0x15, 0xae, 0xcf, 0x11, 0xb8, 0xc4, 0xe8, 0x74, 0x33, 0x76, 0xee, 0xee, + 0xa8, 0xf4, 0x0d, 0x1f, 0x80, 0x5d, 0x67, 0x10, 0xf4, 0x90, 0x7b, 0x12, 0xde, 0x52, 0x2a, 0x9c, 0xf6, 0x4d, 0x67, + 0xa4, 0xc7, 0xa2, 0xe5, 0x43, 0x78, 0x6c, 0x77, 0x10, 0xac, 0x67, 0xcb, 0xb2, 0xa0, 0xa9, 0x04, 0x68, 0xa6, 0x18, + 0xe0, 0xc8, 0x43, 0xec, 0x1c, 0xc9, 0xac, 0x1c, 0xe3, 0x6e, 0x8e, 0xf7, 0x32, 0x88, 0x0e, 0xd1, 0x11, 0x4f, 0xa5, + 0x25, 0xb2, 0x8c, 0x6d, 0xa9, 0xc2, 0xb5, 0x4f, 0x71, 0x5a, 0xd8, 0xa2, 0xab, 0xca, 0x44, 0xbf, 0xfc, 0x08, 0xc4, + 0xd3, 0x37, 0x7a, 0x5e, 0xbb, 0xd9, 0x24, 0xb2, 0x37, 0x74, 0xb5, 0xfc, 0x92, 0x5b, 0x94, 0x56, 0xae, 0xc6, 0x00, + 0x2b, 0xf6, 0x3a, 0xef, 0x09, 0x84, 0x33, 0x25, 0x0e, 0xb7, 0xf9, 0x9d, 0x61, 0xb6, 0xb4, 0xb1, 0xba, 0x19, 0x9d, + 0x62, 0xdc, 0xd6, 0xdb, 0xfd, 0x40, 0x67, 0x37, 0x24, 0x7c, 0x78, 0xe3, 0xfb, 0xd0, 0x03, 0xa9, 0x24, 0xb8, 0xe2, + 0xee, 0xca, 0x7b, 0x0b, 0xc2, 0xec, 0x81, 0x9c, 0x3e, 0x7a, 0x42, 0x82, 0x5e, 0xc0, 0xfe, 0x7c, 0x1e, 0x1e, 0xf3, + 0x92, 0x38, 0x36, 0xca, 0xc7, 0x1f, 0xd6, 0x58, 0xe1, 0x96, 0xe8, 0x70, 0x89, 0x48, 0xdf, 0xc3, 0xe0, 0xc5, 0x13, + 0x86, 0xa4, 0xea, 0x7f, 0xbc, 0x91, 0x50, 0xc5, 0x33, 0x85, 0xce, 0xed, 0xb4, 0x39, 0x27, 0x88, 0xe5, 0xce, 0x55, + 0x66, 0xaf, 0x1d, 0x85, 0xbd, 0xe3, 0xea, 0x96, 0x74, 0x5f, 0xf6, 0x95, 0x9a, 0x5b, 0x8d, 0x48, 0xb0, 0x91, 0xe1, + 0x79, 0x6e, 0xf5, 0x22, 0xb3, 0x43, 0xd6, 0x45, 0x0e, 0xb0, 0xe9, 0x4c, 0x16, 0x47, 0xed, 0xcd, 0xe8, 0x8b, 0xea, + 0x8a, 0xed, 0xaa, 0x6a, 0x95, 0xc6, 0x25, 0x1d, 0xb4, 0xe6, 0x54, 0xc9, 0x0f, 0xc0, 0x36, 0x22, 0x7f, 0xa7, 0x47, + 0x9d, 0xa9, 0x87, 0x4a, 0x39, 0xad, 0x75, 0x20, 0x8c, 0x87, 0x91, 0xde, 0xcf, 0xc0, 0x40, 0x51, 0x09, 0x6c, 0xb7, + 0x43, 0xe7, 0xa7, 0x5b, 0x93, 0x92, 0x91, 0x53, 0x50, 0x52, 0x56, 0x03, 0xd3, 0x44, 0x91, 0x75, 0x9e, 0x63, 0xf6, + 0x77, 0xc7, 0xd3, 0x9f, 0x3b, 0x0e, 0x1a, 0x31, 0xb3, 0x0b, 0x63, 0xff, 0xb8, 0x77, 0x4d, 0x36, 0xa4, 0x70, 0xea, + 0xc0, 0x24, 0xce, 0x92, 0xb4, 0xfe, 0x7d, 0xad, 0x99, 0xfe, 0xba, 0xe9, 0x7a, 0x09, 0x1f, 0xe8, 0xe1, 0xd8, 0x6e, + 0xb5, 0xf9, 0xa1, 0x7c, 0x60, 0x25, 0xbe, 0xf0, 0xdb, 0x35, 0x1d, 0xbe, 0x0c, 0x3d, 0xf7, 0x39, 0xcc, 0x61, 0x6d, + 0xc5, 0xde, 0x48, 0xa6, 0x05, 0x81, 0xde, 0x6e, 0x77, 0x12, 0xc6, 0x80, 0xfb, 0x7a, 0x8e, 0xa8, 0x7c, 0xe6, 0x72, + 0xf4, 0x4c, 0xa2, 0x04, 0xa6, 0xa3, 0xc1, 0xa3, 0x16, 0xa0, 0xe2, 0x13, 0x8b, 0xd3, 0xe1, 0x01, 0x36, 0x38, 0xb8, + 0x3b, 0x8c, 0xd1, 0x8f, 0x75, 0xf7, 0x6d, 0xea, 0xb3, 0x6c, 0xf8, 0x1a, 0x8e, 0x45, 0x5d, 0xfe, 0x70, 0x55, 0x1b, + 0xc7, 0xa2, 0xc7, 0xea, 0x2a, 0x3e, 0x1a, 0x17, 0xf5, 0x06, 0x43, 0xac, 0xce, 0x03, 0x1c, 0x55, 0xa4, 0x6c, 0xce, + 0x6c, 0xa1, 0x24, 0x81, 0xea, 0xad, 0xd5, 0xfc, 0x32, 0xb0, 0x5b, 0x83, 0x0d, 0xd1, 0xfc, 0x6c, 0xbd, 0x87, 0xef, + 0xe2, 0x27, 0x9f, 0x6d, 0xc9, 0x7c, 0x9b, 0x9d, 0x00, 0x77, 0x96, 0x5d, 0x79, 0x92, 0xd5, 0x8a, 0x77, 0x5b, 0x5f, + 0xbc, 0xef, 0x5f, 0x58, 0x2f, 0x84, 0x84, 0xf3, 0x4b, 0x7a, 0xbb, 0x96, 0x43, 0x1a, 0xc4, 0xf6, 0xaf, 0x26, 0x90, + 0x7f, 0x4a, 0x33, 0x77, 0xfe, 0x58, 0x19, 0x82, 0x63, 0x84, 0x1a, 0x6f, 0x09, 0x16, 0x5c, 0x7a, 0x45, 0x4a, 0xb1, + 0xcd, 0x6a, 0xa7, 0x95, 0x8c, 0xb5, 0xe6, 0xbe, 0xd2, 0x96, 0xb4, 0xca, 0x9d, 0x55, 0x40, 0x5c, 0x5d, 0x9a, 0xf8, + 0x50, 0x60, 0x35, 0x7b, 0x52, 0x96, 0xa4, 0x50, 0x1a, 0x2f, 0xfe, 0x91, 0x78, 0x47, 0x40, 0xe5, 0xea, 0x25, 0x42, + 0x30, 0xae, 0xbf, 0xef, 0xec, 0x2c, 0x3b, 0xcd, 0x1e, 0x32, 0xd5, 0x23, 0x2f, 0x2f, 0xc3, 0x39, 0x8a, 0x52, 0xa5, + 0xf1, 0x1d, 0x9c, 0x71, 0x23, 0x46, 0xbd, 0x7b, 0xf6, 0x14, 0x21, 0xef, 0xc8, 0x6f, 0x64, 0x92, 0xc3, 0x30, 0xef, + 0xbe, 0x3a, 0x19, 0x91, 0xe6, 0xf6, 0x0e, 0xe8, 0x62, 0x93, 0x29, 0xeb, 0x2c, 0xd8, 0x92, 0x0a, 0x12, 0x09, 0xd1, + 0xed, 0x90, 0x90, 0xbd, 0xb4, 0x6f, 0x48, 0x51, 0x54, 0xa7, 0x7a, 0xc8, 0x50, 0x4f, 0x3b, 0x7e, 0x5c, 0x47, 0x4c, + 0xc7, 0xda, 0x22, 0x1d, 0x91, 0x0c, 0x20, 0x18, 0x33, 0x5e, 0x42, 0xa6, 0x5a, 0x33, 0xbc, 0x56, 0x13, 0x4f, 0x19, + 0xdd, 0x59, 0x0f, 0x0c, 0x13, 0xa9, 0x20, 0x76, 0xde, 0xd7, 0x24, 0x52, 0x76, 0xeb, 0xc5, 0x67, 0xa5, 0x0c, 0xcb, + 0x7b, 0x78, 0xd6, 0xb5, 0xa7, 0x6c, 0x52, 0x06, 0x24, 0x96, 0xfb, 0x95, 0x8d, 0x5f, 0xeb, 0xe8, 0x4a, 0x9e, 0xd1, + 0xce, 0x03, 0x00, 0xa6, 0x96, 0xf8, 0x7d, 0xea, 0x32, 0x5f, 0xba, 0xd5, 0x8b, 0xed, 0x35, 0xba, 0x05, 0xb8, 0xf6, + 0xa8, 0x66, 0x9e, 0xf6, 0x16, 0xbb, 0xa7, 0x42, 0x07, 0x74, 0xd5, 0x30, 0x5b, 0xfc, 0xe5, 0x8d, 0x0f, 0xb7, 0xc4, + 0xbd, 0x3a, 0x95, 0xe8, 0x63, 0x7e, 0x2d, 0x2e, 0xfc, 0xa7, 0xdc, 0x91, 0x80, 0xd1, 0x31, 0x3e, 0x29, 0xa4, 0x0d, + 0xab, 0x22, 0x64, 0x42, 0x75, 0xbf, 0x38, 0x4d, 0xe0, 0x00, 0x03, 0xd3, 0xb9, 0xc9, 0x62, 0x96, 0xee, 0xae, 0x9c, + 0xea, 0x3e, 0x18, 0xc0, 0xaa, 0x76, 0xda, 0x9c, 0x7a, 0xea, 0x6e, 0x43, 0xeb, 0x18, 0x17, 0xdf, 0x42, 0x4d, 0x86, + 0xb0, 0xb5, 0x5e, 0xa8, 0x48, 0xd3, 0xbc, 0xc5, 0xca, 0x9f, 0x64, 0xdb, 0x1b, 0x60, 0xe8, 0x42, 0x62, 0x6b, 0x3e, + 0x28, 0x41, 0x7c, 0x50, 0x17, 0xc2, 0xbe, 0xa3, 0x81, 0x68, 0x71, 0x86, 0x75, 0x93, 0x2a, 0xd3, 0x7e, 0x46, 0x8e, + 0x26, 0xd4, 0xfa, 0x3e, 0xf6, 0xcf, 0xba, 0x73, 0xfa, 0x57, 0x24, 0xb5, 0x4c, 0xd3, 0x1c, 0xc9, 0xe8, 0x44, 0xd8, + 0xd8, 0x60, 0x20, 0x8d, 0x11, 0x2f, 0x3d, 0xfd, 0x9c, 0xbb, 0x75, 0xcd, 0x28, 0xb0, 0x7e, 0x83, 0xf1, 0x7a, 0xe0, + 0xe4, 0x9a, 0x5c, 0x04, 0x7a, 0x26, 0x46, 0x59, 0x0f, 0xa9, 0x67, 0x5e, 0x2f, 0xd5, 0xfb, 0x9c, 0x8b, 0x09, 0x42, + 0x85, 0xd7, 0x1c, 0x87, 0xf4, 0x13, 0xc0, 0xe3, 0x26, 0x5b, 0x24, 0x3f, 0x6a, 0x70, 0x1e, 0xf6, 0x49, 0xac, 0x2c, + 0x0e, 0x2f, 0x68, 0x7a, 0xf6, 0xbc, 0x0a, 0xf3, 0x03, 0xf9, 0xd3, 0xb9, 0x32, 0xc0, 0x18, 0xc9, 0xdd, 0xc4, 0xae, + 0x08, 0x4d, 0x01, 0x1c, 0x2a, 0xb5, 0x8e, 0x83, 0x68, 0x80, 0x39, 0xec, 0xfb, 0x72, 0x4b, 0x94, 0x91, 0x02, 0x58, + 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x25, 0xd9, 0x31, 0xd6, 0x62, 0x64, 0x01, 0x8f, 0x86, 0xab, 0x89, 0xd3, 0xa2, 0xda, + 0x8b, 0x8b, 0x31, 0x31, 0xf0, 0x18, 0xd1, 0x32, 0x69, 0xdc, 0x0c, 0xa6, 0xb9, 0x21, 0xe8, 0x66, 0x87, 0xce, 0xdc, + 0xdc, 0xb6, 0xb3, 0x08, 0x4e, 0x6f, 0x7f, 0x06, 0xce, 0x0f, 0xe2, 0xbe, 0x76, 0x45, 0xc4, 0xfd, 0x2b, 0x19, 0x70, + 0x25, 0x85, 0xe7, 0x6c, 0x82, 0xa0, 0x1f, 0xad, 0x7d, 0xa6, 0x41, 0x3c, 0x63, 0xcf, 0xa5, 0x4e, 0x05, 0x0c, 0xfe, + 0xa2, 0x11, 0xaf, 0x53, 0x4f, 0x4c, 0x87, 0x45, 0xf4, 0x3d, 0xd1, 0x6c, 0xa0, 0x31, 0x32, 0xdd, 0x6d, 0xef, 0x9a, + 0x21, 0x44, 0x9f, 0x98, 0x52, 0x96, 0x08, 0x80, 0xf3, 0x2f, 0x2b, 0x84, 0xfb, 0xb7, 0x82, 0x84, 0x05, 0x92, 0xe7, + 0x6a, 0xd7, 0xc4, 0x0d, 0xb0, 0x56, 0xcb, 0x19, 0x77, 0x24, 0x82, 0xd9, 0x98, 0xcb, 0x4c, 0xf4, 0x48, 0x12, 0x67, + 0x90, 0xca, 0x66, 0x5b, 0xc3, 0xdc, 0xdb, 0x06, 0x33, 0x21, 0xca, 0x11, 0x0c, 0xde, 0xbd, 0x85, 0x0d, 0x26, 0xb5, + 0x29, 0x25, 0x4e, 0x43, 0x35, 0x24, 0xf9, 0xb2, 0x17, 0xdb, 0xd5, 0x9d, 0x74, 0x1b, 0x68, 0x32, 0x7f, 0xf7, 0xc5, + 0xc1, 0x7d, 0x64, 0xfb, 0xbc, 0x55, 0xec, 0x85, 0x49, 0xb5, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, 0xb8, 0x46, 0x2f, + 0x4d, 0x5f, 0xb5, 0xdf, 0x58, 0x9f, 0xe7, 0x20, 0x47, 0x45, 0x9f, 0xf7, 0x97, 0x0b, 0x08, 0x9a, 0xba, 0x8c, 0x3b, + 0x01, 0x2e, 0x18, 0x51, 0x7a, 0xae, 0x33, 0x02, 0x5b, 0xc2, 0x3c, 0x2d, 0x9b, 0x2b, 0xbc, 0x3c, 0x3f, 0x38, 0x4d, + 0xa8, 0x54, 0xe8, 0x35, 0xbf, 0xaf, 0xde, 0xab, 0xb5, 0xc7, 0xe5, 0x61, 0xff, 0xbd, 0x48, 0xce, 0x40, 0x91, 0x76, + 0x46, 0x7e, 0xb4, 0xac, 0x83, 0x78, 0xdb, 0x9a, 0xbe, 0xbd, 0x96, 0x3f, 0x4c, 0x48, 0xa6, 0xca, 0x6d, 0x08, 0x16, + 0x93, 0xbe, 0xdf, 0x65, 0xf0, 0x93, 0x6c, 0x45, 0x4a, 0x0c, 0x34, 0x8a, 0x5d, 0xc6, 0x3c, 0xd9, 0xa4, 0x5e, 0x37, + 0x15, 0xdd, 0xf8, 0x50, 0xcf, 0x76, 0x18, 0x6f, 0xe0, 0xb1, 0x9e, 0x7c, 0x34, 0x77, 0xaa, 0xee, 0x5a, 0xf8, 0xba, + 0xba, 0x13, 0xda, 0xed, 0xed, 0xeb, 0x45, 0x69, 0x5e, 0x77, 0x27, 0xda, 0x3a, 0x45, 0xcf, 0xeb, 0xff, 0xeb, 0x39, + 0xe3, 0xe0, 0x6d, 0x0a, 0xef, 0x05, 0xf8, 0x76, 0x7c, 0xf6, 0x3c, 0x03, 0x8a, 0x96, 0x59, 0xb4, 0x32, 0xb9, 0xc6, + 0x39, 0x0e, 0x18, 0x55, 0xa8, 0xf3, 0x9a, 0xa9, 0x36, 0x4e, 0x6c, 0x58, 0xef, 0x78, 0x79, 0x55, 0x00, 0x71, 0x87, + 0x6b, 0x59, 0x6e, 0xe2, 0xc2, 0xfc, 0xe6, 0x99, 0x12, 0x92, 0xcd, 0x63, 0x6d, 0xd5, 0xe9, 0x77, 0x49, 0x49, 0x0e, + 0x03, 0x6e, 0x73, 0xe9, 0xc3, 0x4d, 0xe5, 0xa1, 0x0b, 0xdd, 0x2e, 0xca, 0x09, 0x22, 0x95, 0xba, 0x13, 0xa8, 0x70, + 0x6c, 0x8b, 0x15, 0x75, 0xa9, 0xed, 0x1b, 0xdf, 0x17, 0xfc, 0xb2, 0x10, 0x7c, 0x63, 0x27, 0x36, 0x31, 0x5b, 0xa9, + 0x66, 0x24, 0xe1, 0x67, 0x10, 0xcc, 0x71, 0xe5, 0x99, 0xda, 0xed, 0xf0, 0x7f, 0x14, 0x4d, 0x45, 0x0a, 0xe8, 0x12, + 0x87, 0x08, 0x99, 0x99, 0x63, 0x8a, 0x1e, 0xac, 0x10, 0x3a, 0x8b, 0x94, 0x0f, 0x76, 0x73, 0xf0, 0x7d, 0xeb, 0xe7, + 0xb6, 0xae, 0xda, 0xe5, 0x5e, 0xd1, 0xd3, 0x34, 0x25, 0x5a, 0x52, 0xa8, 0xa4, 0x91, 0xb5, 0x43, 0x7d, 0xad, 0xaf, + 0xdd, 0x48, 0x41, 0x2d, 0xb2, 0x20, 0x7a, 0x9d, 0xaf, 0x0d, 0x20, 0x4d, 0x2a, 0xfe, 0xc2, 0xbf, 0x7f, 0x16, 0x89, + 0x37, 0xb5, 0x88, 0x86, 0xfa, 0x3a, 0x6d, 0x5d, 0x7d, 0x15, 0x8f, 0x0d, 0xd7, 0x56, 0xfd, 0x18, 0xe5, 0xe6, 0x46, + 0xca, 0xfb, 0x89, 0xf9, 0xf3, 0xaf, 0x36, 0x0d, 0x8d, 0xc0, 0x49, 0xf3, 0xe6, 0x76, 0xee, 0x30, 0xe7, 0x9e, 0x23, + 0x35, 0x1c, 0xb2, 0x6f, 0x40, 0x6e, 0x91, 0x2f, 0xb5, 0x6b, 0x22, 0x71, 0x81, 0xb0, 0x89, 0x60, 0x43, 0xdc, 0x47, + 0xc6, 0x8c, 0x6e, 0x5d, 0xe3, 0xe0, 0xdd, 0xa5, 0x4c, 0x9d, 0x96, 0x6a, 0x2e, 0xa7, 0x42, 0x99, 0x49, 0x2a, 0xfa, + 0xd5, 0x46, 0x7f, 0x76, 0xe5, 0x94, 0xb8, 0x0e, 0x2a, 0xbf, 0x8d, 0x38, 0x75, 0x1b, 0xcd, 0xb4, 0xbf, 0x95, 0xaf, + 0x7a, 0x5c, 0xd4, 0x5f, 0xd2, 0xe3, 0xbd, 0xb5, 0x47, 0x6e, 0x4d, 0x2d, 0x3d, 0xe2, 0xfe, 0x6a, 0xbb, 0xaf, 0xf2, + 0x39, 0x0e, 0x22, 0x54, 0x3b, 0x21, 0xc6, 0xa5, 0x88, 0x02, 0x0e, 0xe0, 0x15, 0xf1, 0x5f, 0x90, 0xeb, 0xf1, 0xac, + 0x4e, 0xd1, 0x8f, 0x3d, 0xd0, 0xde, 0x6d, 0x9e, 0x03, 0x4e, 0xa9, 0x72, 0xca, 0xbe, 0x23, 0x6b, 0xb3, 0x2c, 0xd2, + 0xae, 0x77, 0x66, 0xb3, 0xa8, 0x58, 0x11, 0x00, 0xc8, 0xde, 0xe9, 0x53, 0x97, 0x75, 0x28, 0xb7, 0x1b, 0x08, 0xb7, + 0x4a, 0x66, 0xc2, 0x4c, 0x14, 0xfe, 0xba, 0x63, 0xc0, 0x0b, 0x21, 0xce, 0x0d, 0x5f, 0x79, 0x49, 0xe3, 0x44, 0x45, + 0x6c, 0x88, 0x1f, 0x94, 0x07, 0xc7, 0xe1, 0xd6, 0xfe, 0xb0, 0x6d, 0x64, 0x22, 0x87, 0xe8, 0x60, 0x35, 0x4a, 0xf7, + 0xc6, 0x77, 0x44, 0x76, 0x3f, 0xde, 0x5f, 0x6b, 0x89, 0x40, 0x4b, 0xcb, 0xf7, 0x6a, 0x57, 0x13, 0xce, 0x9f, 0xde, + 0x76, 0x15, 0x9b, 0x94, 0x19, 0xc5, 0xb7, 0x54, 0xb6, 0xaf, 0xbe, 0xff, 0x8a, 0x7e, 0x16, 0x25, 0x99, 0xc2, 0xd7, + 0xb2, 0x85, 0xe7, 0xd6, 0x32, 0x23, 0x0d, 0x00, 0x55, 0x24, 0x46, 0x73, 0xc9, 0xd3, 0x2e, 0xe9, 0x30, 0x10, 0x6d, + 0xfc, 0x58, 0x6c, 0x9a, 0x45, 0xa8, 0x28, 0x7b, 0xc0, 0x66, 0xa3, 0x1b, 0x32, 0x08, 0x4f, 0xd0, 0x8b, 0x7f, 0xa5, + 0x03, 0x2f, 0x2a, 0xe7, 0xca, 0xd2, 0xad, 0x2f, 0x6f, 0xeb, 0x6f, 0xd2, 0xf5, 0xa4, 0xd6, 0xbb, 0x32, 0x5c, 0x2c, + 0x68, 0x46, 0xbe, 0xf2, 0x5f, 0x0d, 0xe0, 0x75, 0x48, 0xd3, 0x19, 0x0b, 0x7f, 0x62, 0xea, 0x1e, 0x79, 0x5b, 0x99, + 0xf7, 0xdb, 0x65, 0x73, 0x3e, 0x68, 0x1f, 0xbc, 0xa4, 0xaa, 0x3f, 0xe0, 0xf8, 0xc8, 0x79, 0xb8, 0xbf, 0x8a, 0x69, + 0x6e, 0x45, 0xc1, 0x80, 0xe7, 0xa3, 0x15, 0x4d, 0xba, 0xab, 0x47, 0x2b, 0x22, 0x8c, 0x25, 0x4e, 0x2d, 0x6e, 0x75, + 0x21, 0x93, 0xa3, 0xdc, 0x42, 0xdf, 0xc9, 0xcb, 0xdc, 0xe2, 0x3a, 0xda, 0xcb, 0xcc, 0xf4, 0x94, 0x55, 0xf7, 0x1b, + 0xc2, 0xa8, 0x8f, 0xcc, 0x2e, 0x5a, 0x05, 0xa7, 0x95, 0x46, 0xb8, 0xa1, 0x5e, 0x6b, 0x8a, 0x05, 0xce, 0x8d, 0x82, + 0x5a, 0xd5, 0x3b, 0x4f, 0xbb, 0xc6, 0x41, 0xb6, 0x99, 0xd3, 0x8a, 0xd0, 0xed, 0x57, 0xb8, 0xa7, 0xb0, 0xae, 0xf3, + 0xe0, 0x6a, 0x4e, 0x34, 0x38, 0x8d, 0xdb, 0x6d, 0xb3, 0x88, 0x16, 0xb2, 0x8b, 0x15, 0xfd, 0x7a, 0x00, 0xfe, 0x8b, + 0x1d, 0x8a, 0x0f, 0x5b, 0xa9, 0xb1, 0x15, 0x23, 0x2b, 0x34, 0xf5, 0x76, 0x8e, 0x08, 0xff, 0xc2, 0xb7, 0xe4, 0x76, + 0x5b, 0xaa, 0x08, 0x35, 0x75, 0xb3, 0x6a, 0x7b, 0xed, 0x64, 0xbf, 0x34, 0x49, 0xfb, 0x61, 0x9e, 0x9e, 0x10, 0x2a, + 0x51, 0x7b, 0x73, 0x68, 0x88, 0x25, 0xd7, 0x46, 0x9c, 0x1b, 0x4c, 0x48, 0xe3, 0xbf, 0xbf, 0x11, 0x90, 0x13, 0x29, + 0xe9, 0x70, 0x39, 0xf6, 0x2c, 0xc5, 0x48, 0xa2, 0xf9, 0xc8, 0xe0, 0x75, 0x0a, 0x8b, 0xb4, 0x95, 0x27, 0xd7, 0x2d, + 0x75, 0x43, 0xdd, 0x35, 0x7d, 0x92, 0xaa, 0xe3, 0xbc, 0x38, 0xc2, 0xdd, 0xa9, 0x82, 0x46, 0xf5, 0xe6, 0xe4, 0x0c, + 0x49, 0xdb, 0x99, 0x17, 0x42, 0xf2, 0x41, 0xbc, 0x96, 0x44, 0x8a, 0xed, 0x27, 0x59, 0xea, 0x3e, 0xbe, 0x39, 0x88, + 0x0a, 0x84, 0x8b, 0x70, 0x8c, 0xc4, 0xfe, 0x14, 0x63, 0x8a, 0xee, 0x2c, 0x4a, 0x82, 0x4d, 0xd5, 0xc9, 0x19, 0x3a, + 0xd3, 0x7c, 0x02, 0x81, 0x65, 0x37, 0xc8, 0xe8, 0xa0, 0x2e, 0x62, 0x7e, 0xf4, 0xed, 0x10, 0x37, 0xbf, 0xe5, 0xe0, + 0x1a, 0x6d, 0xcf, 0x8c, 0x33, 0xa5, 0xb6, 0xf8, 0xa7, 0x39, 0x5c, 0x9f, 0xc0, 0xec, 0xee, 0x50, 0xc2, 0x89, 0x38, + 0x92, 0x50, 0xaf, 0x3f, 0x57, 0x3f, 0x6c, 0x22, 0x85, 0xce, 0x09, 0xad, 0x0d, 0xb4, 0xf8, 0x34, 0xa7, 0xab, 0x05, + 0x1f, 0xc6, 0x61, 0xc7, 0x90, 0xa9, 0x92, 0xfc, 0x2e, 0xfa, 0xdc, 0xcf, 0x05, 0x18, 0xde, 0x43, 0x5c, 0xe7, 0x7b, + 0x67, 0x47, 0xcd, 0xc2, 0x2d, 0x84, 0xed, 0x4f, 0xa3, 0x84, 0x1c, 0xf4, 0x6b, 0xe5, 0xe7, 0x88, 0x5f, 0x7d, 0xa4, + 0x67, 0xb2, 0xe1, 0x87, 0x43, 0xb4, 0xb8, 0x96, 0xb0, 0x24, 0xc3, 0xe8, 0xfd, 0x8b, 0x57, 0x18, 0xf6, 0x12, 0x18, + 0x3c, 0x83, 0xbd, 0x05, 0x02, 0xe0, 0xf6, 0xe8, 0x27, 0x0c, 0xb5, 0x54, 0x0a, 0xc2, 0xb9, 0xe4, 0x21, 0x41, 0x62, + 0x5c, 0xca, 0xd5, 0xda, 0xa4, 0x4f, 0xc0, 0x5a, 0x3b, 0x4e, 0x1d, 0x34, 0x26, 0x3d, 0xcf, 0x92, 0xe6, 0xcb, 0x98, + 0x3f, 0x0b, 0x14, 0x2c, 0x3f, 0x34, 0x35, 0xdd, 0x83, 0xa0, 0xea, 0xca, 0x18, 0x6b, 0xba, 0xa3, 0x1d, 0x04, 0xef, + 0xaf, 0xd5, 0x33, 0xa2, 0xfc, 0xdd, 0x1a, 0x93, 0x1d, 0x04, 0x85, 0x82, 0x2d, 0x6e, 0xc8, 0xa1, 0x10, 0x62, 0x57, + 0xe3, 0xce, 0xbe, 0x8b, 0x4e, 0x65, 0xa9, 0x99, 0xdc, 0x6e, 0x94, 0x4d, 0x33, 0x4c, 0x98, 0x62, 0x87, 0x56, 0xf2, + 0x05, 0x45, 0x89, 0x5d, 0xbb, 0x5a, 0x94, 0x33, 0xbf, 0xdb, 0xfa, 0x38, 0xb6, 0x50, 0x58, 0xf5, 0x39, 0x98, 0xe5, + 0xc4, 0xb4, 0x6d, 0x97, 0x81, 0xdc, 0xd9, 0x1b, 0x64, 0xaa, 0x29, 0x1b, 0x43, 0x98, 0x77, 0xcc, 0x47, 0xe6, 0xf0, + 0x3d, 0xb2, 0x3b, 0x0f, 0x99, 0xbb, 0xc9, 0x65, 0x2f, 0x3f, 0xeb, 0xf5, 0xcf, 0x1c, 0xa0, 0x90, 0xc6, 0xc0, 0xb1, + 0x79, 0xde, 0x10, 0x6b, 0x99, 0x98, 0x2e, 0x3b, 0x56, 0xba, 0x83, 0x41, 0xc1, 0xeb, 0x1c, 0x28, 0x54, 0xd2, 0x94, + 0x38, 0x71, 0x3d, 0x84, 0x35, 0xa2, 0x1c, 0xde, 0x3b, 0x31, 0xd7, 0xc9, 0x44, 0xb2, 0xf1, 0xaf, 0xf6, 0x3e, 0x5c, + 0xb4, 0x01, 0xfa, 0x78, 0x66, 0xa3, 0x16, 0x16, 0x89, 0x38, 0x85, 0x21, 0x3f, 0xaa, 0x79, 0xac, 0x49, 0xe8, 0x03, + 0x27, 0x03, 0xa9, 0xa0, 0x97, 0x0a, 0xfc, 0x6f, 0x91, 0x9c, 0xb1, 0x72, 0x4a, 0x01, 0x2a, 0xa2, 0xb5, 0x6b, 0xfe, + 0x75, 0xef, 0x7a, 0x4c, 0x82, 0x7a, 0xb5, 0x00, 0x6e, 0x2d, 0x25, 0x92, 0x9f, 0xfb, 0xdb, 0x30, 0x3a, 0xcc, 0x8c, + 0x93, 0xce, 0xf3, 0xea, 0x57, 0x4f, 0x2e, 0x22, 0x99, 0xa2, 0x2d, 0x04, 0x4f, 0x5d, 0x0c, 0x4c, 0xe4, 0x21, 0x9e, + 0x9b, 0x76, 0xd0, 0xa5, 0xc6, 0xa1, 0xfc, 0xcb, 0xae, 0xe3, 0x68, 0x6c, 0x16, 0xe3, 0x04, 0x42, 0x95, 0xea, 0xf2, + 0x3c, 0x73, 0x5d, 0xd6, 0x8b, 0x3d, 0x69, 0xa2, 0xae, 0xac, 0xf4, 0x5b, 0xa8, 0x98, 0x37, 0xba, 0x3a, 0x45, 0x6d, + 0x31, 0xad, 0x93, 0x97, 0x6d, 0x56, 0x66, 0xd5, 0x04, 0x6f, 0x43, 0xb6, 0x11, 0x4e, 0x76, 0xc1, 0x7e, 0x3a, 0xc7, + 0x4b, 0x77, 0x0d, 0x8d, 0x12, 0xbc, 0x84, 0x54, 0xd1, 0xdf, 0x99, 0x16, 0x0e, 0x24, 0x5a, 0x51, 0xb2, 0xf6, 0xa5, + 0xff, 0x66, 0x37, 0x9c, 0xe4, 0x5c, 0x47, 0xef, 0x50, 0x7b, 0x1c, 0x8a, 0x66, 0x3c, 0x26, 0x6b, 0x9c, 0xe7, 0x74, + 0x29, 0x70, 0xc9, 0x92, 0x72, 0xee, 0x05, 0xbb, 0x2b, 0x90, 0xf2, 0xfa, 0xcb, 0x16, 0x09, 0x99, 0x70, 0xfb, 0x3c, + 0x19, 0xb8, 0x8c, 0x09, 0xd2, 0x83, 0xde, 0xf5, 0x03, 0xd5, 0x58, 0xe0, 0xee, 0x97, 0x39, 0xe7, 0x7f, 0xae, 0x48, + 0x92, 0x86, 0x78, 0x68, 0x11, 0x1c, 0xa6, 0xda, 0xaf, 0xc0, 0xad, 0x63, 0xc0, 0xb5, 0x59, 0x99, 0x3e, 0xf8, 0xf5, + 0xf8, 0x40, 0x34, 0x02, 0xff, 0xf9, 0xf8, 0x2b, 0xe2, 0xd0, 0x83, 0x67, 0x2b, 0x42, 0xb2, 0xae, 0x87, 0x8b, 0x34, + 0xff, 0xd5, 0xee, 0x13, 0x80, 0x45, 0xb8, 0x91, 0x74, 0x2c, 0x01, 0x1d, 0xdf, 0x0d, 0x0b, 0xcc, 0x53, 0x60, 0x97, + 0xd1, 0x1f, 0xb3, 0x87, 0x95, 0x6b, 0x1c, 0x2a, 0x4e, 0xb4, 0x85, 0x71, 0xb8, 0x24, 0x58, 0xde, 0xd2, 0xb9, 0x8a, + 0x40, 0x06, 0x07, 0xa4, 0x5e, 0xde, 0x19, 0xc7, 0x23, 0xf7, 0x91, 0x15, 0x1c, 0xf8, 0x66, 0x58, 0xb6, 0x47, 0x06, + 0x1c, 0xea, 0x88, 0x1e, 0xd0, 0xe1, 0xd6, 0x20, 0x43, 0x4d, 0x14, 0x63, 0x0b, 0x3e, 0x3e, 0xaa, 0xc7, 0x0c, 0xf2, + 0x5c, 0x0e, 0xf8, 0xfa, 0xc0, 0xa0, 0xe2, 0x30, 0x81, 0xfc, 0x5d, 0x08, 0x83, 0x3a, 0xec, 0xad, 0x05, 0x80, 0xd2, + 0x27, 0x88, 0xa1, 0x13, 0x87, 0xd4, 0x1b, 0xd0, 0xe4, 0x7b, 0x90, 0xd2, 0x08, 0xfe, 0xa2, 0x22, 0x33, 0x1a, 0x3d, + 0x15, 0xb3, 0x50, 0x18, 0x45, 0x2b, 0x64, 0xa8, 0x4d, 0x88, 0x34, 0x75, 0xf7, 0x96, 0x11, 0xf9, 0xb1, 0x3d, 0xf0, + 0x65, 0x69, 0xaf, 0x45, 0x22, 0x55, 0xce, 0x78, 0x1f, 0x40, 0xa9, 0x39, 0xb8, 0x0a, 0xd4, 0x3d, 0x53, 0x7d, 0x4e, + 0xc5, 0xda, 0xcc, 0xb2, 0x58, 0x78, 0x20, 0x1f, 0xe2, 0x62, 0x7c, 0x15, 0x5d, 0xbe, 0xad, 0x28, 0x9e, 0xc5, 0xdf, + 0xfd, 0xba, 0xe9, 0x43, 0x0a, 0xff, 0x52, 0xf0, 0xd5, 0x59, 0x73, 0xe5, 0x84, 0x75, 0x9e, 0x20, 0x5d, 0x37, 0x18, + 0x74, 0x5b, 0x4b, 0x2c, 0x4f, 0xce, 0xf4, 0xeb, 0x76, 0x31, 0xa5, 0x6a, 0xaa, 0xde, 0xce, 0x03, 0x08, 0xa4, 0xf6, + 0x9d, 0x49, 0x67, 0xd0, 0x2c, 0x24, 0xcb, 0x0c, 0x13, 0xfc, 0xb9, 0xc3, 0x6e, 0x50, 0x91, 0x06, 0x5e, 0xb6, 0x96, + 0x5e, 0xe1, 0x73, 0x3c, 0xae, 0xe8, 0x25, 0xa7, 0xf1, 0xb7, 0x77, 0xa4, 0x3c, 0x6d, 0xfd, 0x54, 0x2e, 0xe7, 0x65, + 0xd1, 0x97, 0xa6, 0x5f, 0xd1, 0x6f, 0x52, 0xb7, 0x3c, 0xee, 0x22, 0x02, 0xe9, 0xff, 0x2a, 0xd7, 0x35, 0x8d, 0xbe, + 0x0a, 0x7b, 0xb1, 0x8b, 0x60, 0xf4, 0xec, 0xb6, 0x6e, 0x0e, 0x39, 0x53, 0x5a, 0x94, 0x1a, 0x0c, 0x4d, 0x3a, 0xfe, + 0x32, 0x0a, 0x4b, 0xd7, 0x94, 0x76, 0xee, 0xa7, 0x3b, 0xbd, 0x54, 0x47, 0x26, 0xfe, 0x6d, 0x2f, 0x7f, 0xc8, 0x3a, + 0x6a, 0x44, 0x17, 0xfe, 0x0f, 0xfe, 0x3c, 0xa2, 0x9c, 0x2f, 0x75, 0x4a, 0xa5, 0x1d, 0xd4, 0x47, 0x55, 0x72, 0x3c, + 0x1d, 0x07, 0xca, 0x68, 0x14, 0xcf, 0xd4, 0xf1, 0xcc, 0x69, 0x26, 0xe8, 0x89, 0x6e, 0x90, 0xac, 0xe5, 0x00, 0x2d, + 0x80, 0x9a, 0x92, 0x11, 0xa7, 0xea, 0x04, 0x37, 0x13, 0xa7, 0xd7, 0x45, 0x27, 0x48, 0x4e, 0x0b, 0xc7, 0xe8, 0x73, + 0x59, 0x0c, 0x51, 0x29, 0xeb, 0xdb, 0xab, 0x23, 0xaa, 0x1e, 0x65, 0xdb, 0xd2, 0xb7, 0x8a, 0x8d, 0x76, 0xa8, 0x83, + 0x15, 0x73, 0x60, 0x97, 0x97, 0xcc, 0xd4, 0x72, 0xe6, 0x60, 0xe6, 0xa7, 0x67, 0xc0, 0x9e, 0x03, 0x66, 0xe7, 0x0c, + 0x31, 0x47, 0x11, 0xaa, 0xc4, 0xd2, 0x18, 0x14, 0x17, 0x76, 0x92, 0x48, 0x7d, 0x3e, 0xef, 0x8e, 0x52, 0x15, 0x73, + 0x6a, 0x2a, 0xaf, 0x07, 0xb0, 0x2d, 0xb1, 0xf2, 0x57, 0x34, 0xa1, 0x1f, 0xe9, 0x16, 0x23, 0xfc, 0x8d, 0x8a, 0xe3, + 0xfc, 0x7e, 0x7e, 0x9b, 0x9a, 0x29, 0x01, 0x13, 0x43, 0x4e, 0x5d, 0x9d, 0x60, 0x5d, 0xa5, 0x98, 0x96, 0xc5, 0x99, + 0x96, 0xe7, 0x7c, 0x36, 0xb6, 0x25, 0xd6, 0x42, 0x38, 0x5b, 0xde, 0xf6, 0xc6, 0x5d, 0x5e, 0x30, 0x26, 0x92, 0x24, + 0x96, 0x6d, 0x5e, 0x4d, 0x07, 0x20, 0xc1, 0x1d, 0x62, 0x9b, 0x7e, 0xc1, 0xb7, 0xa2, 0x88, 0x07, 0xb0, 0x9b, 0xcc, + 0xce, 0x62, 0xab, 0x4c, 0x07, 0xe3, 0xe0, 0x96, 0xff, 0xd5, 0xb6, 0x86, 0x02, 0x21, 0x11, 0x9f, 0x08, 0x70, 0x49, + 0x74, 0x36, 0x83, 0x3a, 0x85, 0x0c, 0x37, 0xf1, 0x9d, 0xa2, 0xc9, 0x77, 0xb4, 0xfa, 0x8e, 0x88, 0xec, 0xdb, 0xab, + 0x88, 0x28, 0x4a, 0xb9, 0x3c, 0x6a, 0xc5, 0x49, 0x8e, 0x68, 0x4e, 0xc6, 0x97, 0x8e, 0xa4, 0x9d, 0x34, 0xe3, 0x4a, + 0x4d, 0x6f, 0x8f, 0xdf, 0x65, 0x10, 0xe9, 0x57, 0xe7, 0xb9, 0x15, 0xc7, 0x79, 0x21, 0x0a, 0xca, 0x07, 0xdc, 0x86, + 0x51, 0x8d, 0x56, 0xbe, 0x99, 0xf3, 0x80, 0x76, 0x66, 0x78, 0x38, 0x9d, 0xb5, 0x6f, 0xb6, 0x2d, 0xf8, 0x72, 0x1c, + 0x0e, 0x63, 0xd3, 0xbe, 0x7f, 0xfe, 0xae, 0x7e, 0x6f, 0xc6, 0x87, 0x57, 0xde, 0x49, 0xea, 0x1d, 0x0f, 0x60, 0xea, + 0xda, 0x98, 0xad, 0x73, 0x70, 0x9e, 0xc6, 0xd8, 0x22, 0xfa, 0x5f, 0xda, 0xc6, 0x67, 0xa5, 0x7f, 0x02, 0xee, 0xc1, + 0x9d, 0x64, 0x59, 0xfa, 0xc5, 0x99, 0x46, 0x8b, 0xfc, 0x89, 0xe5, 0x49, 0xad, 0x1e, 0x74, 0x5c, 0x9a, 0x5c, 0xbc, + 0x42, 0xba, 0x3c, 0x4b, 0xbf, 0x9c, 0x2d, 0xf4, 0x8f, 0xd3, 0x55, 0x00, 0xff, 0x8f, 0x73, 0xa4, 0xb8, 0x3f, 0xa6, + 0xd9, 0x8b, 0x74, 0xe3, 0xfb, 0xb3, 0x9b, 0xd5, 0xeb, 0x82, 0x3d, 0x3a, 0x4f, 0xb6, 0x6c, 0x5d, 0x0b, 0xad, 0xa9, + 0x1b, 0x17, 0xd4, 0x9d, 0xdd, 0x66, 0xed, 0x1b, 0xeb, 0x53, 0x6b, 0xe8, 0xbb, 0x98, 0x48, 0x3f, 0x7f, 0x44, 0x3f, + 0x5d, 0x7b, 0x8a, 0x0b, 0xc3, 0x7e, 0xa7, 0xba, 0x1e, 0x35, 0x33, 0x9d, 0x0a, 0x12, 0x9a, 0x97, 0x3c, 0xdd, 0x37, + 0x39, 0xaf, 0xe5, 0xf8, 0x72, 0xf4, 0x34, 0xa2, 0xa6, 0x7d, 0x47, 0x19, 0xdd, 0x4b, 0x82, 0x31, 0xea, 0x2a, 0x35, + 0x30, 0xfa, 0xe2, 0x55, 0x05, 0x06, 0x01, 0xaa, 0xf3, 0xfa, 0x40, 0x8a, 0xc0, 0xe0, 0xc3, 0x21, 0x8f, 0xe5, 0x06, + 0x03, 0x27, 0x4b, 0xeb, 0x20, 0xf5, 0xf2, 0x20, 0x1c, 0xa9, 0xea, 0xe2, 0x6d, 0x26, 0xa0, 0xc0, 0xeb, 0xa9, 0xfe, + 0x1b, 0xdd, 0x9c, 0x1b, 0xe7, 0x69, 0xc6, 0x87, 0x73, 0x43, 0xe9, 0x52, 0x71, 0xf1, 0xda, 0xae, 0x62, 0x1c, 0x16, + 0xd5, 0x56, 0x25, 0x53, 0x32, 0x65, 0x0e, 0x13, 0xf3, 0x33, 0x41, 0x7a, 0xde, 0xa8, 0x43, 0xee, 0x97, 0x4f, 0xf2, + 0x9a, 0x2e, 0x71, 0x65, 0x92, 0x8d, 0x42, 0xf8, 0x3f, 0x34, 0x55, 0x6b, 0x0e, 0xa4, 0x46, 0xe0, 0x72, 0x70, 0xb5, + 0x54, 0xde, 0xb6, 0xb4, 0x9f, 0x3f, 0x2e, 0xdf, 0xa7, 0xb7, 0x95, 0x24, 0xf9, 0x2f, 0x4d, 0xd8, 0x98, 0xf3, 0xc9, + 0x28, 0xb4, 0x29, 0xc4, 0x0d, 0x4c, 0x45, 0x3b, 0xc6, 0x4f, 0x0a, 0x2f, 0x08, 0xea, 0xf3, 0x0e, 0x45, 0x03, 0xb0, + 0x79, 0x95, 0x8a, 0xdc, 0x19, 0x68, 0x59, 0xa2, 0x6c, 0xdd, 0xe8, 0x6b, 0xc3, 0xf7, 0x38, 0x78, 0xd5, 0x70, 0xeb, + 0xde, 0xcb, 0xa6, 0x0a, 0x94, 0x4d, 0x5b, 0x59, 0xbc, 0x0a, 0x25, 0xcf, 0xd4, 0x4b, 0x9d, 0x2b, 0x69, 0x17, 0x0e, + 0x7e, 0xa6, 0xe2, 0xe8, 0x57, 0x12, 0x81, 0x5d, 0x39, 0xc8, 0x00, 0xc7, 0xed, 0x36, 0xc7, 0x19, 0x02, 0x11, 0x94, + 0x85, 0x56, 0x20, 0xd4, 0x22, 0x55, 0xa7, 0xbe, 0x33, 0x62, 0x35, 0x01, 0xe4, 0x8a, 0xbd, 0x8b, 0x56, 0xc8, 0x9f, + 0x65, 0x06, 0x3a, 0xb0, 0xa3, 0x3d, 0x37, 0x2e, 0xbe, 0x3e, 0x25, 0xe8, 0xd7, 0x12, 0x7b, 0x67, 0x54, 0xc7, 0xc8, + 0x69, 0x3e, 0x3f, 0x58, 0x26, 0xc6, 0x6d, 0x31, 0xde, 0xb6, 0x91, 0x39, 0x81, 0x29, 0x50, 0x89, 0x99, 0xd6, 0xaa, + 0x65, 0x04, 0x39, 0x4c, 0xb2, 0x13, 0x8f, 0x34, 0x19, 0x2b, 0x96, 0xf7, 0x40, 0x60, 0xce, 0x30, 0x6e, 0xd3, 0x98, + 0x55, 0x2b, 0xa4, 0x60, 0x04, 0xc3, 0xd0, 0xf8, 0x60, 0x31, 0x12, 0xe6, 0x95, 0x80, 0x0c, 0x1c, 0x29, 0x52, 0x10, + 0xdf, 0xed, 0x68, 0x7e, 0x30, 0xa5, 0x47, 0x9c, 0xa8, 0x70, 0x8f, 0xca, 0x29, 0xdd, 0x60, 0xa8, 0xe7, 0x82, 0x05, + 0x4c, 0x31, 0xc5, 0x46, 0x72, 0xa0, 0x32, 0xdc, 0xaa, 0x90, 0xb1, 0x5c, 0xf7, 0xb6, 0x3f, 0xbd, 0x97, 0x34, 0x6c, + 0xfa, 0x4a, 0x48, 0x1a, 0xd4, 0x5a, 0x71, 0xe1, 0x03, 0x76, 0xd1, 0xb3, 0xf7, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, + 0xda, 0x4b, 0xa2, 0x7c, 0x69, 0x7f, 0xac, 0x15, 0x5b, 0x63, 0x80, 0xab, 0xde, 0xe9, 0xfa, 0x84, 0x9c, 0xf2, 0x4e, + 0x8b, 0x82, 0x0c, 0x32, 0x2c, 0x23, 0xfa, 0xf0, 0x9f, 0x2e, 0xf2, 0xcd, 0x58, 0x3f, 0x4b, 0xa8, 0x53, 0x93, 0xd6, + 0x2f, 0x7a, 0xb3, 0xcd, 0xce, 0xc9, 0x6c, 0x01, 0xa0, 0xf0, 0x5f, 0xad, 0x3f, 0xb1, 0x35, 0x22, 0xd4, 0x50, 0x04, + 0x2f, 0x01, 0x57, 0x1c, 0xf0, 0xa8, 0xf6, 0x34, 0x42, 0xe1, 0x20, 0x09, 0x4d, 0x99, 0xb3, 0xdd, 0xdf, 0x10, 0xb4, + 0x71, 0x4d, 0x41, 0x87, 0x3e, 0x85, 0xa6, 0xff, 0xea, 0xb3, 0x5f, 0xa0, 0x5a, 0x45, 0xd1, 0x26, 0x76, 0x4d, 0xb1, + 0x38, 0xa4, 0x70, 0x93, 0x6b, 0x87, 0x77, 0x89, 0x10, 0xe0, 0xec, 0x5f, 0xcc, 0x29, 0x4e, 0x16, 0xd6, 0x9d, 0x4d, + 0x08, 0x96, 0x0a, 0x46, 0x52, 0xa2, 0x43, 0x19, 0x73, 0x9d, 0x39, 0x1e, 0x56, 0xe3, 0x97, 0x2e, 0xe8, 0xe1, 0x10, + 0x5e, 0xc7, 0xf8, 0xfc, 0xe1, 0x79, 0xc7, 0x3b, 0x56, 0x68, 0x99, 0xb5, 0x84, 0x29, 0xa4, 0x87, 0x7c, 0x0f, 0x83, + 0xca, 0x63, 0xcf, 0x05, 0xd3, 0xea, 0xfe, 0xa1, 0x54, 0x68, 0xe7, 0x39, 0xa8, 0xa9, 0x17, 0xc0, 0xc4, 0xc2, 0x4d, + 0x29, 0x0d, 0xbb, 0x92, 0x40, 0x6a, 0x53, 0x04, 0x30, 0xfe, 0xe4, 0x13, 0x22, 0x1e, 0xc4, 0x41, 0xa9, 0x96, 0xd0, + 0xf1, 0xe6, 0x68, 0xa3, 0x56, 0x77, 0xb1, 0x30, 0xbe, 0x05, 0x2b, 0x80, 0xb6, 0xc4, 0x86, 0xe1, 0x61, 0xf1, 0xa9, + 0x94, 0x37, 0x21, 0x01, 0xb5, 0xab, 0x20, 0x85, 0x95, 0x83, 0xb5, 0x1f, 0x4c, 0x80, 0xaa, 0x5d, 0x93, 0x28, 0xfd, + 0xb6, 0x52, 0x44, 0x0a, 0x8b, 0x42, 0x35, 0x8f, 0xec, 0xde, 0x96, 0x75, 0xda, 0x50, 0x35, 0x4f, 0x91, 0x2e, 0x95, + 0xda, 0x2e, 0x71, 0x6d, 0xff, 0xa7, 0x99, 0x42, 0xe6, 0x3e, 0x3b, 0x61, 0xf5, 0xb6, 0xf6, 0x14, 0xea, 0x64, 0x54, + 0x4f, 0xf1, 0xf2, 0x51, 0xb5, 0xc2, 0xdf, 0x56, 0xe6, 0xa0, 0x01, 0x0f, 0xc6, 0x45, 0xfa, 0x67, 0xef, 0xc3, 0x35, + 0xe4, 0x9e, 0xbc, 0x6f, 0x55, 0xa1, 0x48, 0x8e, 0x07, 0x33, 0xec, 0x2f, 0x3a, 0x81, 0xe3, 0x09, 0xdb, 0x36, 0x09, + 0x58, 0xeb, 0xf8, 0x1e, 0x49, 0x41, 0x8a, 0xfc, 0x36, 0xd6, 0x86, 0xc4, 0xdc, 0xf0, 0xa3, 0x44, 0x71, 0x4b, 0x29, + 0x5d, 0x25, 0x4f, 0x4e, 0x6d, 0xbb, 0x82, 0x52, 0x13, 0x47, 0xe0, 0xd8, 0xfa, 0xca, 0x11, 0xff, 0x6c, 0xfb, 0x6a, + 0x97, 0x2b, 0x89, 0x43, 0xb1, 0xc8, 0x4f, 0x75, 0x3f, 0x29, 0x0f, 0x93, 0x01, 0xac, 0x26, 0xd4, 0x19, 0x0b, 0x47, + 0x95, 0x24, 0x80, 0xc0, 0x04, 0xa8, 0x25, 0x3c, 0x17, 0x6a, 0x91, 0xdb, 0x30, 0xa9, 0xd9, 0x56, 0xce, 0x55, 0xfb, + 0x64, 0x6b, 0x6a, 0xcd, 0xc0, 0xcd, 0xc5, 0xc6, 0x71, 0x75, 0x67, 0x07, 0xb2, 0xd2, 0x43, 0x02, 0x9d, 0x7b, 0x53, + 0x62, 0x41, 0x53, 0xe0, 0xc3, 0xd1, 0xee, 0xbe, 0x03, 0x10, 0x45, 0x23, 0x46, 0xff, 0x59, 0xc1, 0xe4, 0xa4, 0xdf, + 0xe8, 0x06, 0x7c, 0x4b, 0x95, 0x79, 0x41, 0xd9, 0xe0, 0x72, 0x77, 0x7e, 0x63, 0xd5, 0x03, 0xcf, 0x4c, 0x98, 0x93, + 0x72, 0xed, 0xc1, 0x46, 0x66, 0x89, 0x9a, 0x70, 0xfd, 0x7f, 0x35, 0xd7, 0x90, 0x1c, 0x80, 0x5c, 0x8c, 0x7d, 0xab, + 0xac, 0xc0, 0xd5, 0x2c, 0x74, 0x40, 0x61, 0x1f, 0x0c, 0x9c, 0x0a, 0x1b, 0x76, 0x03, 0x6e, 0x7e, 0x90, 0xa6, 0x95, + 0xef, 0x12, 0xe8, 0xfe, 0xa7, 0x58, 0x63, 0xdf, 0xbb, 0x25, 0x6b, 0xd8, 0xe8, 0x4d, 0x41, 0xd3, 0xe8, 0x5e, 0x33, + 0x59, 0xd3, 0xd9, 0xca, 0x0c, 0x55, 0x23, 0xaf, 0xd6, 0x8f, 0x45, 0xdc, 0x1a, 0x9e, 0x9f, 0xc9, 0x79, 0xbd, 0x8f, + 0xe9, 0xa5, 0x6e, 0x3c, 0xf6, 0x45, 0xdd, 0xe1, 0xab, 0x1b, 0xd1, 0x86, 0xb3, 0xa2, 0x88, 0x9d, 0x0f, 0xeb, 0x9e, + 0x8a, 0xb4, 0x5b, 0x47, 0xbb, 0x78, 0x5b, 0x30, 0xa7, 0x64, 0x54, 0x67, 0xd0, 0x14, 0xba, 0x0a, 0xc7, 0xba, 0x7e, + 0xbe, 0xb8, 0x02, 0xeb, 0x8e, 0x96, 0x55, 0x82, 0x37, 0x26, 0x5d, 0xd4, 0x61, 0xd7, 0xf7, 0x8c, 0x0f, 0x89, 0xaa, + 0x8f, 0x46, 0xeb, 0x34, 0xf7, 0x05, 0x34, 0xa0, 0xe5, 0x0b, 0x3a, 0xb4, 0x21, 0xab, 0xd1, 0x5d, 0x69, 0xf2, 0xa4, + 0x56, 0xd5, 0x6f, 0x79, 0x0c, 0xde, 0xb1, 0x7c, 0x35, 0x56, 0x9d, 0x8e, 0x7f, 0x19, 0xbe, 0xbc, 0xac, 0xee, 0x90, + 0xf4, 0xb9, 0x97, 0x01, 0x60, 0xda, 0xe6, 0x93, 0x41, 0xbf, 0x2f, 0x02, 0x91, 0x91, 0xdf, 0x62, 0x3c, 0x7b, 0x29, + 0x4b, 0x00, 0x1d, 0x57, 0x05, 0xbd, 0x33, 0x4d, 0x7a, 0x79, 0x4f, 0x24, 0xe2, 0xc6, 0xc0, 0x78, 0x83, 0x42, 0x15, + 0x52, 0xef, 0x34, 0x81, 0xb8, 0x47, 0x1d, 0x13, 0xe9, 0x45, 0xd5, 0xf7, 0xab, 0x04, 0x07, 0xcf, 0xa2, 0xd5, 0x6e, + 0xff, 0xb3, 0x68, 0x0a, 0xe4, 0xc4, 0xc1, 0x44, 0x5d, 0xe1, 0x84, 0xc7, 0x3f, 0x9e, 0x68, 0xbf, 0x64, 0x47, 0xaa, + 0xe9, 0x30, 0x5f, 0xc5, 0x57, 0x76, 0xaa, 0x5a, 0xf1, 0xcb, 0xbc, 0xef, 0x67, 0x8b, 0xb4, 0xf1, 0x32, 0xd2, 0xab, + 0xd9, 0x5e, 0xed, 0x6c, 0xa2, 0xba, 0x53, 0x58, 0x1e, 0x35, 0x59, 0x51, 0x1d, 0x13, 0xab, 0x56, 0x5f, 0x1d, 0x7a, + 0xe5, 0xed, 0x65, 0xf6, 0x9b, 0x25, 0x61, 0xe6, 0xec, 0x69, 0xe1, 0xde, 0xec, 0x6c, 0xc9, 0x83, 0xee, 0xe7, 0xe0, + 0xbf, 0xc7, 0x46, 0x8a, 0x2d, 0x53, 0xbb, 0x28, 0x47, 0x02, 0x00, 0x0e, 0x12, 0xbf, 0x3a, 0xbd, 0xf9, 0x7b, 0x2d, + 0x2a, 0x75, 0xb3, 0xda, 0x69, 0x71, 0xe9, 0x1f, 0x23, 0x4a, 0x4b, 0xe3, 0x38, 0xe5, 0x08, 0xa2, 0x71, 0x6d, 0x7e, + 0xc1, 0x24, 0x73, 0xdf, 0x62, 0xb5, 0x12, 0x6b, 0xc9, 0x09, 0x14, 0x18, 0xb9, 0xd7, 0x35, 0xcf, 0x5d, 0xab, 0x53, + 0x58, 0xa6, 0xb6, 0xe6, 0xb0, 0xb5, 0xc3, 0xbe, 0x83, 0xaa, 0xaf, 0xa9, 0xc3, 0x55, 0x16, 0xbe, 0xad, 0x78, 0x21, + 0x5f, 0x4a, 0x79, 0x72, 0xea, 0xe6, 0x8d, 0x60, 0x29, 0x3e, 0x0a, 0x54, 0x73, 0x46, 0xf0, 0xa2, 0x56, 0x5f, 0x59, + 0xc4, 0x4a, 0x7e, 0x28, 0x09, 0xbd, 0xd8, 0x3d, 0x17, 0xd9, 0x80, 0xab, 0xb2, 0xfe, 0xbe, 0xfa, 0xdc, 0x23, 0x95, + 0x7d, 0x74, 0x61, 0x95, 0xda, 0x8e, 0x63, 0x6e, 0xa3, 0xa6, 0x2a, 0x78, 0xf3, 0xde, 0x35, 0xd8, 0x35, 0xb0, 0x3c, + 0x19, 0xcb, 0x25, 0x46, 0x06, 0x3e, 0xd6, 0xd6, 0x53, 0x7d, 0x65, 0x5e, 0x3d, 0x5a, 0xc9, 0x58, 0x48, 0xca, 0x2b, + 0x04, 0xa2, 0xd7, 0x7f, 0x96, 0x2b, 0x35, 0xac, 0xd5, 0xd9, 0x0a, 0x25, 0x1a, 0x31, 0xda, 0xbb, 0x54, 0x4e, 0x76, + 0x4d, 0x8f, 0x8c, 0xe9, 0xf3, 0xee, 0x47, 0xd5, 0xd2, 0x92, 0xd9, 0x86, 0x16, 0xff, 0x54, 0x64, 0x2c, 0xa9, 0x88, + 0x6d, 0xc5, 0x16, 0x7b, 0x16, 0x77, 0x01, 0x4c, 0x3e, 0x5d, 0x30, 0x77, 0x9f, 0x50, 0x0e, 0xc6, 0xea, 0x57, 0xaa, + 0x2a, 0x37, 0x3e, 0x4f, 0xbc, 0xbe, 0x6f, 0x60, 0x26, 0x91, 0x45, 0x1e, 0x05, 0x36, 0x2b, 0xeb, 0x69, 0x4f, 0x6f, + 0x73, 0x52, 0xa3, 0x5f, 0x18, 0x85, 0x56, 0x79, 0xc0, 0xe7, 0x9a, 0x79, 0xf2, 0xe6, 0x7d, 0xa7, 0x1b, 0x41, 0x86, + 0xa3, 0x8d, 0xb4, 0x41, 0xdb, 0x6d, 0x48, 0x7a, 0x8b, 0xf8, 0x0f, 0x29, 0xd3, 0x5f, 0x94, 0xf9, 0xea, 0xfb, 0xe1, + 0x7c, 0x5d, 0x4e, 0x50, 0x35, 0x7b, 0xc0, 0xe1, 0xd1, 0x58, 0x02, 0x2c, 0x20, 0x8e, 0x3e, 0x12, 0xb2, 0xb6, 0x26, + 0x28, 0x27, 0x3c, 0x52, 0xe5, 0x6c, 0x94, 0x77, 0x26, 0x7a, 0x42, 0xab, 0xca, 0xd9, 0x00, 0x5b, 0xd0, 0x8d, 0x5d, + 0xf2, 0x6d, 0x2c, 0x3c, 0x5d, 0xee, 0x77, 0x8e, 0xed, 0x81, 0x2b, 0xd7, 0x5c, 0xc0, 0x17, 0xde, 0x03, 0x77, 0xa1, + 0x5a, 0x40, 0x6b, 0x10, 0xff, 0x51, 0x54, 0xd9, 0xdd, 0xe6, 0xdc, 0x48, 0x24, 0x59, 0x28, 0x13, 0x2a, 0x6b, 0xf1, + 0x73, 0x83, 0x9c, 0xeb, 0x71, 0xe0, 0x1c, 0x29, 0x01, 0x82, 0x63, 0xc4, 0x24, 0xf6, 0xa6, 0x34, 0x54, 0x70, 0x8e, + 0x3e, 0x79, 0x2d, 0xbf, 0x60, 0xca, 0xd0, 0x05, 0x3a, 0x3d, 0xcf, 0x42, 0xc1, 0x7e, 0x60, 0x5d, 0x38, 0x3a, 0x69, + 0x39, 0xeb, 0x9f, 0x1d, 0x18, 0x01, 0xf2, 0x58, 0x79, 0x99, 0x24, 0x6c, 0x2d, 0x5a, 0xbd, 0xc9, 0xfb, 0x71, 0xa5, + 0x10, 0x2d, 0x16, 0xa8, 0xba, 0xfd, 0x02, 0x17, 0xa7, 0x25, 0x95, 0xac, 0x14, 0xb7, 0x0a, 0x15, 0x88, 0xd6, 0x9b, + 0x50, 0xf5, 0x3a, 0x7d, 0x6d, 0xdb, 0x51, 0x79, 0x69, 0x28, 0x36, 0x31, 0x04, 0x86, 0x58, 0x1f, 0x7e, 0xaa, 0xb6, + 0xe1, 0xb6, 0xb3, 0x2e, 0xee, 0x73, 0xdb, 0x7e, 0x0d, 0x5f, 0x8f, 0xc4, 0x9b, 0xca, 0xdb, 0xa6, 0x78, 0x58, 0x20, + 0xe2, 0x44, 0xd7, 0x6b, 0x0d, 0x9b, 0x93, 0x4f, 0x7f, 0x55, 0xa7, 0x4c, 0x8e, 0xe8, 0x63, 0x0f, 0x21, 0xe6, 0x42, + 0x44, 0x85, 0x48, 0xbf, 0x6f, 0x47, 0xe7, 0xca, 0x3d, 0x23, 0x44, 0xe7, 0xd8, 0x88, 0x75, 0x6c, 0x27, 0x81, 0xa7, + 0xb6, 0x14, 0xc4, 0x09, 0xdc, 0x7d, 0x27, 0x16, 0x7c, 0xf2, 0x85, 0x34, 0xe7, 0xe1, 0xf9, 0xcb, 0xdf, 0xfe, 0x4a, + 0x56, 0xea, 0xb9, 0xee, 0x2c, 0xba, 0xa6, 0xbb, 0xa4, 0x52, 0x97, 0xcf, 0x71, 0x17, 0xb3, 0xf0, 0x26, 0x6b, 0xff, + 0x7a, 0x78, 0x4b, 0x37, 0x6d, 0x48, 0x91, 0x4c, 0x51, 0xee, 0xfe, 0x4d, 0x3c, 0x35, 0x22, 0xc3, 0x5f, 0xf0, 0x8c, + 0xb1, 0xee, 0xcb, 0xaa, 0xf9, 0x60, 0xac, 0x04, 0xec, 0x3d, 0x27, 0x23, 0x73, 0x51, 0x70, 0xa3, 0x28, 0x44, 0x2b, + 0xd6, 0x83, 0xed, 0x40, 0x53, 0xf9, 0x80, 0xf1, 0x0f, 0x53, 0x6a, 0xb9, 0x8b, 0xcd, 0xf5, 0xfd, 0xd8, 0xf4, 0x38, + 0x26, 0x25, 0x23, 0x9d, 0x39, 0x1a, 0xa8, 0x15, 0xd8, 0xf6, 0x58, 0x7e, 0x39, 0x44, 0xe7, 0xb4, 0x2d, 0xb0, 0x4d, + 0xcb, 0xc7, 0x37, 0x87, 0x6c, 0x2e, 0x5f, 0x9a, 0xf1, 0x5e, 0xba, 0x79, 0xf2, 0x62, 0x99, 0xde, 0x0a, 0x7b, 0xc2, + 0x40, 0x14, 0x51, 0x05, 0x9d, 0x84, 0x22, 0xec, 0xb4, 0x5b, 0x7b, 0x82, 0x94, 0x16, 0x83, 0xf0, 0x13, 0x5c, 0x9f, + 0xb4, 0xaf, 0x45, 0x6d, 0x6a, 0x1d, 0x35, 0x41, 0xed, 0x72, 0x9e, 0x06, 0x48, 0x47, 0xc5, 0x73, 0x0b, 0xa1, 0xcf, + 0x28, 0xd0, 0x16, 0x34, 0x59, 0x29, 0xd2, 0x08, 0x43, 0x91, 0x73, 0x63, 0xaa, 0x26, 0x73, 0xb1, 0x5c, 0xf8, 0xb3, + 0x46, 0x9b, 0x34, 0xc4, 0x24, 0xe4, 0xda, 0x96, 0x5d, 0xe6, 0xeb, 0x04, 0xeb, 0x2b, 0x6b, 0x7f, 0x3d, 0xf9, 0x5b, + 0x41, 0x32, 0x05, 0xec, 0x47, 0x16, 0xaf, 0xdb, 0x97, 0xb8, 0x02, 0xde, 0xd4, 0x40, 0x51, 0x03, 0xca, 0xac, 0x3a, + 0xad, 0xdb, 0xf0, 0x80, 0x32, 0xfb, 0xcd, 0x40, 0x95, 0x9a, 0x5c, 0x59, 0xc5, 0xb7, 0xba, 0x8d, 0xb8, 0x5e, 0xb2, + 0x81, 0xb4, 0xf1, 0x76, 0xca, 0xad, 0xd3, 0x54, 0xb9, 0x12, 0xe7, 0x41, 0x25, 0xa9, 0x71, 0x0f, 0x30, 0x98, 0xe6, + 0xe9, 0x3b, 0x34, 0xe6, 0xdf, 0x8a, 0x83, 0x49, 0x5f, 0x18, 0x24, 0xab, 0xb4, 0x63, 0x01, 0x20, 0x40, 0xb7, 0x5d, + 0x72, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x88, 0xec, 0x1d, 0xd8, 0x9d, 0xe9, 0xc3, 0xc0, 0xcc, + 0xbb, 0x9a, 0x92, 0x5d, 0x8a, 0xc2, 0x37, 0xd1, 0x37, 0xdb, 0xc5, 0x4a, 0x00, 0xdc, 0x30, 0xbb, 0xcc, 0x17, 0xaa, + 0x4c, 0xe6, 0x62, 0xab, 0xf2, 0x90, 0x9b, 0xa9, 0x4c, 0x71, 0x55, 0x13, 0x3c, 0x08, 0x82, 0x80, 0x82, 0xbc, 0x81, + 0x5c, 0xc7, 0x17, 0x0d, 0x20, 0xe8, 0x41, 0x58, 0x0c, 0x13, 0xcf, 0x8d, 0xb2, 0xbb, 0x3e, 0xaa, 0x98, 0xc2, 0xf8, + 0x54, 0x4a, 0x72, 0x72, 0xee, 0xf5, 0xc9, 0x64, 0xd8, 0x6a, 0x36, 0xec, 0xe4, 0x24, 0x21, 0xb4, 0x24, 0xb6, 0x90, + 0x53, 0xea, 0xf6, 0xae, 0x0e, 0xbd, 0x3c, 0x96, 0x05, 0x8c, 0xb6, 0x11, 0xac, 0x3b, 0x1c, 0xed, 0x3d, 0x25, 0xc2, + 0x8b, 0x65, 0x63, 0xbe, 0x13, 0xf1, 0x45, 0xaa, 0x8f, 0x81, 0x06, 0xcc, 0x9b, 0x3f, 0x07, 0xb2, 0x9a, 0xe0, 0x6f, + 0xc2, 0x8b, 0x65, 0x71, 0x9f, 0x39, 0x21, 0x2a, 0x36, 0x8b, 0xfb, 0x67, 0x1b, 0x14, 0x98, 0xae, 0x09, 0xdd, 0x40, + 0xaa, 0x81, 0x45, 0xc3, 0x1d, 0x3d, 0x58, 0xb4, 0x3f, 0xa2, 0xab, 0x62, 0x59, 0x61, 0xf4, 0xe8, 0xc1, 0x51, 0x3d, + 0x95, 0x1d, 0x4b, 0x6b, 0xa4, 0x39, 0xe2, 0x37, 0xcf, 0x11, 0x2d, 0xea, 0x36, 0xc6, 0x44, 0x63, 0x69, 0xe6, 0x1f, + 0x44, 0x79, 0xb4, 0xaf, 0x41, 0xd8, 0x3f, 0x83, 0x4d, 0xe2, 0x63, 0xc6, 0x20, 0x6f, 0x8e, 0x06, 0xf6, 0x72, 0x40, + 0x1d, 0x07, 0xcb, 0x93, 0x92, 0x82, 0x9b, 0x8b, 0x95, 0x2a, 0xcd, 0x32, 0x8a, 0x3d, 0xaf, 0x13, 0x59, 0xcb, 0x1e, + 0xe1, 0x24, 0x23, 0x26, 0xfa, 0x3c, 0x50, 0x90, 0x77, 0x5a, 0x2f, 0xff, 0xd3, 0x0a, 0xcc, 0x3a, 0x74, 0x32, 0xd6, + 0x64, 0x94, 0x2c, 0x84, 0x08, 0x6d, 0x08, 0xb7, 0x36, 0x24, 0xd7, 0x22, 0xb4, 0x1d, 0x99, 0x43, 0x1f, 0xe6, 0x4b, + 0xc1, 0x19, 0x5e, 0x82, 0x9e, 0x76, 0xb9, 0x7d, 0x71, 0xfa, 0xcd, 0x85, 0x72, 0x67, 0x83, 0x83, 0x08, 0xa4, 0xe8, + 0x5c, 0x9f, 0x1e, 0x8a, 0x17, 0x85, 0x83, 0x88, 0xb8, 0x39, 0xbc, 0x1e, 0xac, 0x3e, 0x26, 0x74, 0x56, 0x75, 0x4f, + 0x7b, 0xff, 0x85, 0x0b, 0xdf, 0xb5, 0xb5, 0x22, 0x8a, 0xd3, 0x1b, 0xb6, 0x1e, 0xa5, 0x79, 0x26, 0xad, 0x1e, 0xbb, + 0x62, 0xe0, 0x51, 0xa6, 0x22, 0xc7, 0x6f, 0xd6, 0x63, 0x8c, 0x6d, 0x08, 0x28, 0x43, 0xaa, 0xb7, 0x18, 0x02, 0x20, + 0x63, 0x9e, 0x8e, 0xfd, 0x71, 0xce, 0x26, 0xc8, 0x7b, 0x8d, 0x31, 0x17, 0xf1, 0x76, 0xed, 0x4f, 0xe0, 0xa1, 0x50, + 0x36, 0x12, 0xd7, 0xf2, 0x28, 0xc5, 0xb9, 0x07, 0x15, 0x9f, 0x46, 0xc4, 0xd6, 0x61, 0xea, 0x7c, 0x42, 0x18, 0xb2, + 0x07, 0x31, 0x66, 0x17, 0x26, 0x74, 0x7a, 0x89, 0xbe, 0x32, 0xbd, 0x0d, 0xa8, 0xbe, 0x15, 0x5b, 0x24, 0x9a, 0x97, + 0x44, 0xa2, 0xe8, 0xec, 0x84, 0xd8, 0x6c, 0x45, 0x8e, 0x1a, 0xab, 0xbd, 0x83, 0xc1, 0xe5, 0x33, 0x4e, 0x6b, 0xeb, + 0x0a, 0x30, 0xf9, 0x63, 0x98, 0x0a, 0x06, 0x9c, 0x1b, 0x4e, 0x2c, 0x79, 0x37, 0xa2, 0x1f, 0x7d, 0x20, 0xe3, 0xb7, + 0xd2, 0x22, 0xd8, 0xa3, 0x81, 0x18, 0xa9, 0x8a, 0x61, 0x05, 0xd3, 0x47, 0x21, 0xc1, 0x53, 0x17, 0x8e, 0xaa, 0x3a, + 0xf4, 0x0b, 0x22, 0xaa, 0x9d, 0x0b, 0xbb, 0x56, 0x0c, 0x98, 0x68, 0xcc, 0x1c, 0x1a, 0x2d, 0x5c, 0xc0, 0xf3, 0x74, + 0xfc, 0x7e, 0xe2, 0x7e, 0x76, 0xfe, 0xa0, 0x19, 0xf4, 0xbf, 0x26, 0xa3, 0xce, 0xf1, 0xd3, 0xfb, 0xdb, 0xf6, 0x69, + 0xbf, 0xb6, 0x33, 0xf7, 0x07, 0xea, 0xfb, 0x4f, 0xfc, 0xcb, 0x24, 0x80, 0xfc, 0x52, 0xc7, 0x6e, 0xc3, 0xf5, 0x53, + 0xe2, 0x35, 0x78, 0xb8, 0x7e, 0x72, 0x89, 0x50, 0xef, 0x00, 0xed, 0x8d, 0x4a, 0xdb, 0x86, 0x4b, 0x4c, 0xe2, 0x91, + 0xf2, 0x64, 0x35, 0x56, 0x64, 0x49, 0xad, 0x60, 0x65, 0x92, 0x6f, 0xe4, 0xae, 0xcf, 0x2e, 0xc1, 0x3d, 0xbe, 0x15, + 0xd9, 0x53, 0xae, 0x3e, 0x00, 0x17, 0xa5, 0xf3, 0x57, 0xcc, 0x3b, 0xff, 0x13, 0x55, 0xd6, 0x1d, 0xd4, 0x0c, 0xb5, + 0x96, 0x44, 0xad, 0x9a, 0x59, 0x5d, 0xb0, 0xb7, 0x04, 0xb4, 0xa6, 0x56, 0x1f, 0xca, 0xcd, 0x21, 0x7f, 0x6c, 0xb1, + 0x2e, 0x8c, 0x13, 0x4d, 0x93, 0x01, 0x79, 0x6a, 0x7e, 0xe9, 0x12, 0x43, 0x92, 0x41, 0xfd, 0xbf, 0xbe, 0x7b, 0x77, + 0x74, 0xd0, 0x4c, 0x5a, 0xde, 0x85, 0x3d, 0xde, 0xab, 0xa2, 0x62, 0x49, 0xe7, 0x1b, 0x7d, 0x7c, 0x90, 0x3c, 0xc9, + 0xc3, 0xf6, 0x79, 0xea, 0xcf, 0x0e, 0xfc, 0xd8, 0x80, 0xbe, 0xe3, 0x6d, 0xd3, 0x8e, 0xd2, 0xc7, 0x21, 0x04, 0x2c, + 0xd5, 0x2e, 0x68, 0x56, 0xc3, 0x23, 0x34, 0x58, 0xb7, 0x49, 0x55, 0x38, 0x8a, 0xa7, 0x1c, 0x1f, 0xfe, 0x03, 0xd0, + 0x41, 0x02, 0x3c, 0x6a, 0x2e, 0xcb, 0xc3, 0xb4, 0x03, 0x6b, 0x23, 0x6c, 0xf7, 0x26, 0x44, 0x2f, 0x16, 0x47, 0x6b, + 0xa7, 0x36, 0x61, 0x11, 0x69, 0xbc, 0x2b, 0x09, 0x5d, 0xdd, 0x07, 0xbd, 0x1e, 0x75, 0x9a, 0x35, 0x09, 0xa1, 0x9d, + 0x6c, 0xeb, 0xb8, 0x7a, 0xd0, 0xab, 0xac, 0xcf, 0x5f, 0x30, 0xfd, 0x58, 0xdf, 0xe3, 0x23, 0x86, 0xf5, 0x1b, 0xde, + 0x1f, 0x5c, 0x4a, 0x70, 0xb1, 0x69, 0xec, 0x7c, 0x33, 0x27, 0x0e, 0xbb, 0x59, 0x0a, 0x0b, 0x09, 0xa6, 0x97, 0x48, + 0x1b, 0xc6, 0x6a, 0x70, 0x7c, 0x11, 0x1f, 0xeb, 0xf9, 0x62, 0x40, 0x20, 0x52, 0xd9, 0x29, 0xf2, 0xc2, 0x00, 0x13, + 0xf5, 0xed, 0xcd, 0x87, 0xd4, 0xff, 0x10, 0xdf, 0xec, 0x03, 0xa9, 0x93, 0xe4, 0xd1, 0x8b, 0x45, 0x51, 0x24, 0x54, + 0xf4, 0x14, 0xff, 0xe2, 0x10, 0xca, 0xf0, 0x32, 0xd1, 0xd9, 0xa4, 0xe8, 0xf6, 0xce, 0x2d, 0x5f, 0x24, 0xbc, 0x71, + 0xe5, 0x72, 0xe9, 0x61, 0x60, 0xda, 0x02, 0x36, 0x50, 0x41, 0xc6, 0x31, 0x4b, 0xf1, 0x63, 0xe4, 0x2a, 0x43, 0x94, + 0xdd, 0xea, 0x31, 0xd4, 0x70, 0x11, 0x98, 0x3b, 0x94, 0x49, 0xc2, 0x68, 0xa1, 0x9e, 0xdb, 0xc0, 0xd3, 0x73, 0x66, + 0xe7, 0xe9, 0xdc, 0xde, 0xab, 0x62, 0xc7, 0x84, 0x89, 0x0c, 0x8a, 0xe8, 0xb1, 0xc2, 0x86, 0x5a, 0xcd, 0x97, 0x99, + 0x53, 0x6c, 0x7a, 0xe4, 0x0f, 0x43, 0x2d, 0x37, 0xe9, 0x96, 0x1d, 0xbd, 0xd2, 0x47, 0xfd, 0xd1, 0xa2, 0x13, 0x0c, + 0xd1, 0xe2, 0xee, 0xac, 0x8d, 0x72, 0xc4, 0x28, 0x6c, 0xde, 0x17, 0x80, 0xd9, 0xb7, 0x6e, 0x4b, 0xba, 0xfa, 0xc4, + 0xd5, 0xf7, 0xc2, 0xdc, 0xf3, 0x00, 0x62, 0x24, 0xcf, 0xe5, 0xc8, 0x45, 0x91, 0x03, 0x92, 0xbc, 0xab, 0x23, 0x2d, + 0x91, 0x8a, 0x10, 0x4e, 0x67, 0x1c, 0x0c, 0x8b, 0xd3, 0xb9, 0x6a, 0xea, 0xbb, 0x2c, 0x10, 0x09, 0x65, 0xb2, 0x9f, + 0xa2, 0x67, 0x7b, 0xa3, 0x71, 0x47, 0x87, 0xb5, 0x76, 0xeb, 0x20, 0x14, 0xae, 0x4c, 0xb5, 0x99, 0x70, 0xf7, 0x8c, + 0xfe, 0xeb, 0x8d, 0x97, 0x14, 0xab, 0x8e, 0x7b, 0xef, 0x53, 0x7d, 0xf9, 0x6b, 0x5e, 0x00, 0xf5, 0xfb, 0x81, 0xb3, + 0x21, 0x7f, 0xcb, 0x7d, 0xb0, 0x98, 0x32, 0x40, 0x80, 0x8f, 0x68, 0x86, 0x3a, 0xed, 0xab, 0xd9, 0x8d, 0x6f, 0x88, + 0xd9, 0xb3, 0xda, 0xd0, 0x77, 0x7e, 0xf8, 0xae, 0xae, 0xa0, 0xc1, 0x45, 0x65, 0xf4, 0x7f, 0x9e, 0x2a, 0x20, 0x98, + 0x0a, 0xfe, 0x3e, 0x6e, 0x87, 0xe3, 0x5b, 0xf0, 0x1c, 0x46, 0x7d, 0x1c, 0x69, 0xa2, 0x7b, 0x27, 0xee, 0x52, 0xaf, + 0x32, 0x4d, 0x32, 0xaf, 0x68, 0x97, 0x35, 0x2e, 0x58, 0xd6, 0x35, 0x5d, 0x5b, 0x76, 0xb0, 0x66, 0x5f, 0x02, 0x20, + 0x23, 0xdb, 0x9b, 0xaa, 0xa6, 0xf0, 0xeb, 0x4b, 0xb1, 0x08, 0x24, 0xf0, 0x9d, 0xb2, 0xbf, 0xba, 0x76, 0x7d, 0xd3, + 0xae, 0x16, 0xf1, 0xc1, 0xc0, 0x81, 0x50, 0xae, 0xf3, 0x86, 0x7b, 0x59, 0xa1, 0xcd, 0xf3, 0x25, 0xe7, 0xc6, 0xcb, + 0x88, 0x4a, 0x43, 0x21, 0x89, 0xda, 0x40, 0x9f, 0x8e, 0x3d, 0x0d, 0x10, 0x1e, 0x12, 0x4b, 0x1d, 0x64, 0x65, 0xfa, + 0x47, 0xd2, 0xde, 0x9b, 0x1b, 0xc3, 0xeb, 0xe1, 0x16, 0x97, 0x19, 0x45, 0x14, 0x76, 0x0c, 0x3c, 0x72, 0x2b, 0x56, + 0x7b, 0xb7, 0xfe, 0xe1, 0xc1, 0xd3, 0xbb, 0xab, 0x8f, 0x9f, 0x16, 0xb7, 0x43, 0xaa, 0xd5, 0x4f, 0xa7, 0xd6, 0xb2, + 0xe6, 0x93, 0x76, 0x98, 0xf7, 0x8e, 0x15, 0xbb, 0x84, 0x13, 0x69, 0x07, 0x31, 0x56, 0x6e, 0x26, 0x55, 0xa7, 0x09, + 0x70, 0x20, 0x35, 0x75, 0x9f, 0x3d, 0x73, 0xcd, 0x94, 0x3c, 0x36, 0xe8, 0x25, 0x51, 0x57, 0xa5, 0x11, 0x58, 0xa6, + 0xfd, 0xe3, 0xf1, 0xd2, 0x4b, 0x3d, 0x4d, 0xb0, 0x89, 0x6e, 0x18, 0x88, 0xc3, 0xdf, 0xb1, 0xc1, 0xaf, 0x67, 0xf7, + 0x64, 0x49, 0xa0, 0x70, 0x69, 0xeb, 0x86, 0x32, 0x0d, 0xda, 0x52, 0x21, 0x38, 0x2e, 0x5e, 0xdc, 0x2a, 0xc6, 0x93, + 0xac, 0xa9, 0x16, 0xc5, 0x43, 0x24, 0x1a, 0x70, 0x19, 0x5b, 0xca, 0x4d, 0xbe, 0x8d, 0x01, 0x0e, 0xd2, 0x11, 0xca, + 0xf5, 0xb2, 0x0a, 0xb0, 0xdb, 0xf0, 0xd7, 0xe3, 0x69, 0x1e, 0x80, 0x98, 0x1e, 0x1b, 0xf6, 0x74, 0x6f, 0xa3, 0xc9, + 0xad, 0xb9, 0x93, 0x12, 0x3f, 0x4a, 0xd9, 0x62, 0x4b, 0x0c, 0x83, 0x73, 0xa5, 0x13, 0x20, 0xa0, 0xe5, 0x6e, 0x09, + 0x20, 0xb5, 0x2c, 0x39, 0x89, 0x83, 0x85, 0x13, 0xd9, 0xde, 0x62, 0xbc, 0xdd, 0x93, 0x9e, 0x1a, 0xcf, 0xdc, 0x46, + 0xc6, 0xa4, 0xac, 0x7c, 0xbf, 0x20, 0x93, 0xf7, 0x79, 0x06, 0x16, 0xcd, 0x65, 0xf4, 0xf4, 0x5d, 0x71, 0x2a, 0x7e, + 0x98, 0x45, 0xe7, 0xe1, 0x69, 0xd4, 0xcd, 0x61, 0x96, 0x78, 0xc0, 0x4e, 0x38, 0xd3, 0x6a, 0x60, 0xac, 0x5d, 0xda, + 0x8e, 0xb4, 0x3b, 0xfb, 0x02, 0x29, 0x61, 0xcd, 0x6e, 0x76, 0x82, 0x63, 0x46, 0x5c, 0x0e, 0xba, 0xd7, 0x1b, 0x30, + 0xac, 0x6c, 0x17, 0x73, 0x73, 0x4f, 0xee, 0xa4, 0xd5, 0x53, 0x81, 0x9c, 0x81, 0x2c, 0x59, 0xd7, 0xf0, 0xbe, 0x40, + 0xb5, 0xbe, 0x78, 0x70, 0xf0, 0x76, 0x6f, 0x19, 0x77, 0x4d, 0x19, 0x65, 0x3b, 0xa2, 0x08, 0x7e, 0x65, 0x40, 0xba, + 0x56, 0xf6, 0x23, 0x77, 0x37, 0x4b, 0x1d, 0xa4, 0x14, 0xfa, 0x74, 0x3d, 0x5d, 0x1b, 0x09, 0x6f, 0x66, 0xaa, 0xe3, + 0x08, 0xf9, 0x44, 0x87, 0x41, 0x59, 0x49, 0x8a, 0xfe, 0x9f, 0xb1, 0xdf, 0x81, 0x82, 0x7a, 0xe0, 0xd7, 0xbf, 0x0b, + 0x12, 0x1c, 0xd8, 0x9d, 0xa0, 0xb5, 0xe2, 0x63, 0x09, 0xb2, 0x5b, 0x85, 0xb9, 0xa0, 0x44, 0xad, 0x7f, 0xcf, 0xcd, + 0xf5, 0xfa, 0xfb, 0x4b, 0x56, 0xaa, 0x75, 0x27, 0xdb, 0xb6, 0xf5, 0x4d, 0xae, 0x19, 0x3b, 0x62, 0x5f, 0x0e, 0x7c, + 0x70, 0x9a, 0xc9, 0xb5, 0x80, 0xa4, 0x21, 0xd3, 0xe7, 0x6e, 0x8d, 0xba, 0x91, 0x8c, 0xdc, 0x01, 0x09, 0x44, 0x08, + 0x34, 0x18, 0x94, 0x75, 0xbb, 0x2f, 0xc6, 0xe1, 0xbc, 0xb3, 0x78, 0xff, 0x73, 0x41, 0x97, 0xe8, 0xb0, 0xae, 0xce, + 0x62, 0xc9, 0x7f, 0xbf, 0x53, 0x8c, 0x64, 0x7b, 0xb4, 0xbd, 0x7f, 0x31, 0x9a, 0xe2, 0x4a, 0xa6, 0xfd, 0x83, 0xbf, + 0xbf, 0xe8, 0x2d, 0xbc, 0xd9, 0xd1, 0xc1, 0xea, 0x3e, 0x4f, 0xb9, 0x79, 0xd2, 0x17, 0x33, 0xf9, 0xae, 0x8c, 0x4c, + 0x6e, 0x10, 0x18, 0x75, 0x67, 0x75, 0xa9, 0xcb, 0xc3, 0xc8, 0xc5, 0x7a, 0xb8, 0x19, 0x4e, 0xe1, 0x36, 0x13, 0x59, + 0xb5, 0x50, 0x05, 0xe0, 0x11, 0x3a, 0x29, 0x51, 0x24, 0x49, 0x62, 0x80, 0xe8, 0xde, 0xc6, 0x3c, 0x80, 0x17, 0x35, + 0x9f, 0x35, 0xd4, 0x76, 0x46, 0x36, 0xc7, 0x01, 0xad, 0xcd, 0x1c, 0xd3, 0xb2, 0x29, 0x41, 0xe7, 0xee, 0x74, 0x84, + 0x0e, 0xbd, 0xa5, 0xf5, 0x54, 0x97, 0x8a, 0x7d, 0xd3, 0xb3, 0xb6, 0x8e, 0xc8, 0x27, 0x71, 0x6b, 0x75, 0x90, 0xe6, + 0x2a, 0xa7, 0xe2, 0x66, 0xaa, 0x9e, 0xa3, 0x77, 0x16, 0x8e, 0x40, 0xdf, 0x5a, 0x1e, 0xac, 0x71, 0x11, 0x6c, 0x8a, + 0xee, 0x2c, 0x15, 0x55, 0xc5, 0x96, 0xfb, 0x9d, 0x4c, 0xa7, 0xed, 0x9d, 0x01, 0xb2, 0x4e, 0x98, 0xee, 0x1e, 0x12, + 0x48, 0x3c, 0x7a, 0x17, 0x60, 0xb0, 0x67, 0x52, 0x4c, 0xab, 0xea, 0xbc, 0x62, 0x82, 0x87, 0xa5, 0x3c, 0xf3, 0xbd, + 0xd9, 0xb3, 0xc3, 0xa8, 0x61, 0x3c, 0x76, 0xf8, 0x05, 0x25, 0x05, 0xb3, 0x37, 0xd1, 0xcd, 0xdf, 0xcb, 0xd7, 0xf5, + 0x09, 0xb7, 0x46, 0x0e, 0xb9, 0x75, 0x07, 0xd7, 0xef, 0xf4, 0x7d, 0xe6, 0x62, 0x56, 0xdf, 0x7e, 0x36, 0x2e, 0x66, + 0x46, 0xc9, 0x77, 0x6a, 0xa4, 0x3d, 0x24, 0xde, 0x6b, 0x00, 0xb6, 0x00, 0xca, 0x92, 0x09, 0xe8, 0x60, 0xb5, 0x2e, + 0x97, 0x4e, 0xd7, 0x29, 0x69, 0xaa, 0x3d, 0xf3, 0x6a, 0xbb, 0xb1, 0xcd, 0x85, 0x67, 0x4c, 0xb6, 0x58, 0x9b, 0x4e, + 0x5b, 0xc2, 0xe4, 0xb5, 0xae, 0xdf, 0xe8, 0xfa, 0x97, 0x15, 0x81, 0x9a, 0xa9, 0x5c, 0x71, 0x5f, 0x2b, 0x6b, 0x08, + 0x3e, 0x85, 0x45, 0x98, 0x0a, 0xf0, 0xac, 0x3a, 0x81, 0xaa, 0xf5, 0x43, 0xdb, 0xfb, 0x1b, 0x16, 0xdb, 0xb3, 0x9d, + 0x76, 0x01, 0x14, 0x9e, 0x25, 0xee, 0x9c, 0x2b, 0x77, 0x74, 0xe3, 0x74, 0x13, 0x53, 0xf6, 0xe3, 0x17, 0xa8, 0x93, + 0x83, 0x99, 0xdb, 0x0b, 0x1a, 0x4b, 0xc0, 0x93, 0x22, 0x13, 0xc4, 0xe4, 0xe7, 0x40, 0x08, 0x6d, 0xa4, 0xd2, 0x99, + 0x86, 0xc7, 0x68, 0xf7, 0x5a, 0x29, 0x0b, 0xa6, 0x76, 0xef, 0xc9, 0x6d, 0xd8, 0x74, 0x04, 0xaa, 0xb3, 0xef, 0xa4, + 0xdc, 0xa8, 0x97, 0x30, 0x02, 0x3a, 0xdd, 0x6b, 0xf5, 0xe3, 0x9f, 0x93, 0xb9, 0x86, 0x7d, 0x64, 0xc7, 0x1b, 0xd1, + 0x0d, 0x40, 0x0e, 0x87, 0x4b, 0x28, 0x65, 0xed, 0x93, 0xea, 0xdf, 0xfb, 0xb2, 0xd1, 0xf0, 0x09, 0xc3, 0x38, 0x49, + 0x54, 0x71, 0xda, 0xe6, 0xd6, 0x40, 0xe9, 0x4f, 0xee, 0x9d, 0x12, 0xa6, 0x20, 0x10, 0x4d, 0xb2, 0x72, 0x3e, 0x05, + 0x2c, 0x3c, 0xe5, 0x81, 0x4a, 0x98, 0x46, 0x2c, 0xd1, 0x0e, 0xad, 0x34, 0x1b, 0x5d, 0x82, 0x19, 0x06, 0x5c, 0xfb, + 0x0b, 0x8d, 0xd6, 0x9d, 0xec, 0xad, 0xa3, 0x06, 0x6f, 0xd0, 0xd2, 0xe8, 0x77, 0x43, 0x93, 0x00, 0x84, 0x9c, 0x1e, + 0xdc, 0xf7, 0x2c, 0x46, 0xc7, 0x15, 0x9d, 0x47, 0x0f, 0x64, 0x22, 0xd4, 0x94, 0xeb, 0x4e, 0x0e, 0x80, 0x39, 0xdd, + 0x72, 0x69, 0xa8, 0xc7, 0x60, 0x9a, 0x5e, 0x40, 0x54, 0xc0, 0x8a, 0x0e, 0xa0, 0xd3, 0xd8, 0x0d, 0x65, 0x79, 0xc3, + 0x0c, 0x05, 0x08, 0x82, 0xec, 0x1b, 0x84, 0xfd, 0xa9, 0x3a, 0xe6, 0x6a, 0x86, 0x5d, 0x86, 0x19, 0x1c, 0x87, 0x86, + 0xf6, 0x14, 0xfc, 0x04, 0x6c, 0xa2, 0x09, 0x08, 0x50, 0x6e, 0x12, 0x62, 0x0f, 0x6a, 0xfe, 0x2b, 0x0f, 0x49, 0x7b, + 0xdd, 0x34, 0xf5, 0x09, 0xa6, 0x38, 0x2c, 0x83, 0x75, 0x5b, 0xb6, 0x57, 0xb7, 0xaa, 0x8c, 0xe3, 0x1a, 0x60, 0x6c, + 0xe9, 0x1c, 0x47, 0x61, 0x1a, 0xe2, 0x7f, 0x0d, 0xa8, 0x0b, 0x73, 0xab, 0x76, 0x13, 0xfa, 0x66, 0x49, 0x53, 0x3e, + 0x9a, 0xdc, 0x1f, 0x1b, 0x9a, 0x13, 0xfd, 0xbe, 0xc0, 0x8c, 0x6b, 0x89, 0x4b, 0x16, 0x7a, 0xda, 0x06, 0x65, 0xa7, + 0x6b, 0x5c, 0x65, 0xfc, 0x6a, 0xf4, 0xcb, 0xb7, 0xab, 0x57, 0x31, 0xc4, 0x8c, 0x28, 0x60, 0x6b, 0xde, 0x59, 0xc7, + 0x27, 0xda, 0x7d, 0x37, 0xe6, 0x97, 0xa7, 0xa8, 0x71, 0xa3, 0x94, 0x58, 0x2c, 0x92, 0xf7, 0x15, 0x6e, 0x6b, 0x3e, + 0xd8, 0x5e, 0xf9, 0xf8, 0xeb, 0x79, 0x28, 0x04, 0x4f, 0xa8, 0x92, 0x20, 0xd1, 0x40, 0x37, 0xad, 0xd7, 0x82, 0x96, + 0xde, 0x97, 0x94, 0x66, 0x9e, 0xfb, 0xcb, 0xa6, 0x5d, 0x02, 0x42, 0x55, 0x03, 0x39, 0x3f, 0x45, 0x93, 0x2f, 0xa6, + 0xd3, 0x31, 0x82, 0x4f, 0x9a, 0x9c, 0x23, 0x0c, 0xa7, 0xdd, 0x7e, 0x97, 0x9f, 0xfe, 0x26, 0x47, 0x07, 0x9e, 0xfb, + 0x49, 0xea, 0xdb, 0xa1, 0xf0, 0xe9, 0x77, 0xbd, 0x18, 0x7d, 0xf5, 0x8d, 0x90, 0xbe, 0xed, 0xc4, 0xc6, 0x41, 0x90, + 0x37, 0xf2, 0x42, 0x84, 0x08, 0x76, 0x49, 0x20, 0xcc, 0x65, 0xfd, 0x46, 0xbc, 0x85, 0xaf, 0xe8, 0x2d, 0x35, 0x47, + 0x4f, 0xa3, 0x03, 0x3d, 0x9c, 0xb0, 0xbe, 0x8b, 0x0f, 0xa3, 0x2f, 0xb0, 0xe6, 0xe1, 0xb3, 0x00, 0x90, 0x8e, 0x61, + 0x15, 0xc0, 0xda, 0x60, 0xee, 0x18, 0x6e, 0xeb, 0xf4, 0xc4, 0x5a, 0xe6, 0x00, 0xbb, 0xdc, 0xc9, 0x71, 0x43, 0x77, + 0x0e, 0x41, 0xc1, 0xbc, 0x1d, 0x58, 0x23, 0xff, 0xcf, 0xb4, 0xa1, 0x3b, 0xab, 0x98, 0x58, 0x06, 0x22, 0xcd, 0x11, + 0x09, 0x0d, 0x5f, 0x77, 0x2f, 0x02, 0x07, 0xf0, 0x11, 0x83, 0xaf, 0x41, 0xc5, 0xf3, 0xdc, 0xe4, 0x57, 0xf5, 0xf3, + 0x4b, 0xc4, 0xde, 0x14, 0xaf, 0xeb, 0xa9, 0xbb, 0x2b, 0x0f, 0x7f, 0xa7, 0x14, 0x00, 0xbd, 0x54, 0x76, 0x15, 0x98, + 0xc9, 0xc1, 0x26, 0x32, 0xfc, 0x5c, 0x2f, 0xa1, 0x32, 0x6d, 0xf6, 0x84, 0x10, 0x2e, 0x48, 0x39, 0xb9, 0x1e, 0x2f, + 0x46, 0x7e, 0x02, 0x2a, 0x02, 0x6d, 0x02, 0xc8, 0xb2, 0x3f, 0x82, 0x45, 0xca, 0x01, 0x81, 0x78, 0x17, 0x17, 0x7d, + 0xea, 0x2d, 0x0d, 0x92, 0x98, 0xdd, 0x4b, 0x11, 0x30, 0x88, 0xcb, 0x84, 0x12, 0x34, 0x6c, 0x4d, 0xd9, 0xb7, 0x10, + 0xb9, 0x23, 0x74, 0xd8, 0x11, 0x66, 0x06, 0x5d, 0x25, 0xf2, 0x1f, 0x1d, 0x2d, 0xa9, 0x82, 0x87, 0xe9, 0xc9, 0xb3, + 0x15, 0xcd, 0x86, 0x93, 0x06, 0x12, 0x12, 0xf8, 0x50, 0x88, 0x03, 0x1b, 0x6f, 0x48, 0xa2, 0x60, 0x3d, 0x48, 0xfe, + 0x74, 0xd9, 0xf2, 0xba, 0xf3, 0x2c, 0x3b, 0xbe, 0x63, 0x68, 0x0e, 0x79, 0x8c, 0x44, 0x11, 0x94, 0xc2, 0xef, 0xa0, + 0xa4, 0x45, 0xa6, 0x12, 0x50, 0xae, 0x15, 0xd9, 0xe1, 0xa9, 0x2a, 0x31, 0x01, 0x5a, 0xa0, 0x07, 0xd1, 0xbd, 0xcb, + 0x42, 0xd3, 0x74, 0xf0, 0xda, 0xa1, 0x61, 0x2c, 0x83, 0xa9, 0x0e, 0x2e, 0x5b, 0xa1, 0x38, 0x32, 0xe9, 0x90, 0x51, + 0x70, 0x72, 0xeb, 0xac, 0xcb, 0x26, 0x37, 0xbf, 0xbd, 0x57, 0x74, 0x74, 0x0c, 0x64, 0x75, 0x9e, 0xde, 0x3c, 0xcf, + 0x66, 0x08, 0x06, 0xe9, 0xe3, 0x69, 0x57, 0xf1, 0x72, 0x9a, 0x81, 0x69, 0xd5, 0xf6, 0x6d, 0x19, 0x2e, 0x37, 0xb1, + 0xe4, 0xaa, 0xdb, 0x87, 0xb9, 0xcc, 0x67, 0xa7, 0x93, 0xec, 0xb7, 0xd6, 0xe0, 0xc8, 0x69, 0x66, 0xfd, 0x46, 0xf9, + 0x3c, 0x3f, 0x32, 0x95, 0x6f, 0x0e, 0x93, 0x44, 0x6a, 0xd7, 0x50, 0xad, 0xc2, 0x0c, 0x3f, 0x19, 0x44, 0xbd, 0x06, + 0x54, 0x1b, 0xad, 0x18, 0x6e, 0xe0, 0xc5, 0xe6, 0xc9, 0xd2, 0x75, 0xcc, 0x8c, 0xab, 0xc0, 0x2c, 0x26, 0x95, 0x18, + 0xdf, 0x8b, 0x04, 0x19, 0xb4, 0xa7, 0xfb, 0x54, 0x34, 0xd6, 0x97, 0x40, 0x27, 0x8b, 0x68, 0x03, 0x06, 0xe6, 0x10, + 0xea, 0x58, 0xa0, 0xb1, 0x71, 0x98, 0x45, 0x6d, 0x2b, 0x33, 0x9a, 0x2a, 0x83, 0x61, 0x0c, 0xb5, 0x01, 0x5c, 0xdd, + 0xaa, 0x85, 0x94, 0x8c, 0xb2, 0xee, 0x32, 0x1a, 0x28, 0xa1, 0x63, 0x19, 0x2b, 0x3c, 0x52, 0x32, 0x5c, 0x19, 0x71, + 0x1a, 0xe0, 0xcb, 0xd3, 0xff, 0xf7, 0x27, 0x32, 0x6a, 0xe9, 0xee, 0x48, 0xde, 0xb9, 0xec, 0xe8, 0x4a, 0x33, 0x9e, + 0xa7, 0xcb, 0xe9, 0x8b, 0xd4, 0x6d, 0xa9, 0x96, 0xf9, 0xc3, 0xe8, 0x18, 0x85, 0xaf, 0xed, 0xdb, 0x6d, 0x25, 0x1a, + 0xce, 0x30, 0x62, 0xae, 0x7c, 0xe3, 0x16, 0xf5, 0x5a, 0x8a, 0xee, 0xb7, 0x8c, 0x9c, 0x4a, 0x75, 0xc7, 0x1b, 0x97, + 0x1a, 0x5e, 0x29, 0xfd, 0x87, 0x79, 0x5e, 0xcc, 0xb1, 0xdd, 0xf6, 0x71, 0xb5, 0xb2, 0xcb, 0x89, 0xce, 0x9b, 0xe7, + 0x24, 0xe1, 0x6d, 0x8f, 0x63, 0x2b, 0x91, 0xe2, 0xb1, 0x34, 0x7f, 0x57, 0x4d, 0xb6, 0x9b, 0x5f, 0x7d, 0x2e, 0xc8, + 0x5a, 0x4c, 0xba, 0xd5, 0x56, 0xa5, 0x35, 0xf3, 0xe0, 0xdd, 0x9e, 0x39, 0xd2, 0x53, 0x12, 0x34, 0xdc, 0x2e, 0xe4, + 0xd3, 0x20, 0xd2, 0x5b, 0x66, 0x74, 0x58, 0x93, 0x57, 0xbe, 0xb1, 0x09, 0x0e, 0xe1, 0x78, 0x6b, 0x34, 0x0f, 0x93, + 0x9d, 0x4e, 0xea, 0xc5, 0xff, 0x33, 0x5b, 0xf8, 0x36, 0x75, 0xf2, 0x57, 0x5c, 0xe9, 0x20, 0xc5, 0xc5, 0x14, 0x1f, + 0x8e, 0x11, 0xcc, 0x97, 0xf4, 0x1d, 0x0a, 0x8f, 0xa6, 0x9c, 0x06, 0x06, 0x21, 0x66, 0xcf, 0xbe, 0x73, 0xf7, 0x76, + 0xbc, 0x25, 0xce, 0xa8, 0x2c, 0x6b, 0x8a, 0x25, 0x18, 0xa4, 0x79, 0x1d, 0x10, 0x00, 0x57, 0x2e, 0x88, 0x5d, 0x81, + 0xc8, 0x96, 0x17, 0xd1, 0xe2, 0xdd, 0x2f, 0x4b, 0xa3, 0xb8, 0x29, 0xf1, 0x99, 0xec, 0xf6, 0x44, 0x30, 0xc0, 0x2d, + 0xc8, 0x0e, 0xc7, 0x0e, 0x16, 0xc4, 0x1c, 0x09, 0xde, 0x15, 0x65, 0x58, 0x92, 0x3a, 0x50, 0x2c, 0x5a, 0xd4, 0x05, + 0x13, 0x13, 0x29, 0x64, 0x6b, 0xab, 0x84, 0x00, 0x69, 0xa2, 0xf6, 0x12, 0x58, 0xd4, 0x34, 0x7b, 0xa2, 0xea, 0x62, + 0x92, 0xbb, 0x21, 0xf7, 0x34, 0x1e, 0xfc, 0x3c, 0x94, 0xcc, 0xb1, 0x37, 0x89, 0x90, 0x7f, 0xbd, 0xd9, 0xfa, 0x05, + 0xf6, 0x0e, 0x7e, 0xd1, 0x10, 0xbe, 0x9a, 0xc2, 0x1a, 0x92, 0x30, 0xab, 0x5c, 0x78, 0xab, 0x24, 0x40, 0x81, 0xb2, + 0xac, 0x4f, 0x8b, 0x03, 0x46, 0x1f, 0x0a, 0xca, 0x16, 0xcb, 0x39, 0x89, 0xd9, 0x71, 0x11, 0x5b, 0x72, 0x2f, 0xfa, + 0xfc, 0xfc, 0x65, 0x1c, 0xef, 0x11, 0x81, 0xca, 0xad, 0xf2, 0xfe, 0x48, 0xc9, 0x01, 0x03, 0x33, 0xfd, 0x29, 0x8d, + 0xe8, 0xdc, 0x7f, 0x3f, 0xd5, 0x0f, 0x39, 0xf0, 0x4b, 0xe0, 0x38, 0xd0, 0xa7, 0x2c, 0x5a, 0xce, 0x06, 0xaa, 0x7b, + 0x9c, 0x53, 0xfb, 0x58, 0x5c, 0x22, 0xae, 0x4c, 0x42, 0xa0, 0xbb, 0x5c, 0x48, 0x82, 0xc5, 0xa7, 0x60, 0x48, 0x36, + 0x01, 0xd3, 0x58, 0x61, 0x73, 0xad, 0x79, 0x77, 0x80, 0x2e, 0x36, 0x58, 0xc1, 0x2b, 0x1c, 0x0c, 0xbd, 0xb6, 0x66, + 0x4e, 0x6b, 0x35, 0xbd, 0x13, 0x25, 0x89, 0x6c, 0xb2, 0xdb, 0x8f, 0x23, 0x7b, 0x43, 0x1a, 0x22, 0xfc, 0xb9, 0x51, + 0x5a, 0x14, 0x8a, 0xe6, 0x6a, 0x85, 0x88, 0x7d, 0xaf, 0x52, 0x4e, 0x32, 0xa9, 0x5a, 0x6a, 0x72, 0x5b, 0x29, 0x21, + 0xd6, 0x85, 0x7f, 0x14, 0xd4, 0xcd, 0xa8, 0x3f, 0x25, 0x37, 0xd0, 0x37, 0xe2, 0x4d, 0x02, 0x6f, 0xac, 0xf5, 0x21, + 0x28, 0x9a, 0x68, 0xfc, 0x08, 0x8a, 0xc5, 0xc1, 0x04, 0x4f, 0x3c, 0x97, 0x61, 0x09, 0x48, 0xa7, 0x78, 0xe8, 0xc5, + 0x84, 0x8b, 0x40, 0x0b, 0xce, 0x59, 0xbe, 0x7b, 0xa7, 0x79, 0xa0, 0xd3, 0x7a, 0x21, 0x89, 0xd9, 0x5e, 0x75, 0xba, + 0xf4, 0x8a, 0x81, 0xf3, 0xeb, 0x4c, 0x59, 0x22, 0xee, 0x49, 0x5e, 0x6e, 0x37, 0x96, 0xd1, 0xc6, 0x22, 0xe6, 0x74, + 0xa6, 0x82, 0x3f, 0x9b, 0x7a, 0x5b, 0x27, 0x16, 0xbf, 0x1d, 0x4f, 0xad, 0x8c, 0xd7, 0x01, 0xee, 0x12, 0x6f, 0xca, + 0xa0, 0x54, 0xc4, 0xeb, 0x41, 0x84, 0x48, 0x90, 0x12, 0x9d, 0x46, 0x86, 0xd2, 0x63, 0x3f, 0x48, 0xcc, 0x06, 0xd4, + 0x88, 0x1d, 0xd8, 0x39, 0xca, 0x6e, 0x85, 0x9f, 0xfb, 0xbb, 0xf5, 0xf0, 0x7b, 0x95, 0x3e, 0xe9, 0x2d, 0xcc, 0x4a, + 0xf3, 0xa4, 0x1a, 0x56, 0x60, 0xd9, 0x71, 0xfb, 0x97, 0x67, 0xae, 0xc2, 0xe0, 0xdc, 0x56, 0xc3, 0x9d, 0x3e, 0x97, + 0xef, 0x2f, 0xe0, 0xef, 0x4f, 0xbf, 0xaf, 0xf9, 0x02, 0xb3, 0x8e, 0x94, 0x50, 0xd7, 0x6e, 0x23, 0x22, 0xee, 0xc5, + 0xab, 0xab, 0x14, 0x5a, 0x80, 0x2c, 0xbf, 0x80, 0x67, 0xc7, 0xb7, 0x46, 0xba, 0x4f, 0x8e, 0x54, 0x20, 0x11, 0xf2, + 0x56, 0x41, 0x58, 0x09, 0x38, 0x52, 0xd8, 0x2c, 0xb2, 0xa0, 0x4f, 0x25, 0x74, 0x0d, 0x3f, 0x25, 0xbe, 0xbc, 0x9a, + 0x2b, 0x7e, 0x0c, 0xe9, 0x04, 0x74, 0xd8, 0x9d, 0x0f, 0x22, 0xb0, 0x41, 0xce, 0x7a, 0xc9, 0x68, 0xde, 0xc9, 0x67, + 0xa3, 0xc8, 0xb4, 0x63, 0xa5, 0xfd, 0xda, 0xa8, 0xdb, 0x3e, 0x1e, 0xdf, 0x29, 0x06, 0x3c, 0x38, 0x6c, 0x6e, 0x37, + 0x69, 0x20, 0x6f, 0xd5, 0xde, 0xfb, 0x7a, 0xc7, 0xb5, 0x5d, 0x90, 0x7c, 0xb2, 0xb4, 0x83, 0x28, 0xa4, 0xdb, 0x8d, + 0x9c, 0x2a, 0xea, 0x17, 0x45, 0xfb, 0x22, 0x2d, 0xef, 0xee, 0x12, 0x8f, 0x7b, 0xf5, 0x24, 0x4e, 0x2e, 0x8e, 0x73, + 0x4d, 0x25, 0xe2, 0xc8, 0x97, 0xa8, 0x2f, 0x4f, 0xd1, 0x66, 0x5a, 0x53, 0x83, 0xab, 0x5c, 0xab, 0xa6, 0x44, 0x5e, + 0x8a, 0x9e, 0xd9, 0xcd, 0xe2, 0xaf, 0xb8, 0xa6, 0x42, 0x33, 0xe0, 0xfc, 0x59, 0xfb, 0xe6, 0xcf, 0x04, 0x0f, 0x2e, + 0x8b, 0x7f, 0x94, 0xfe, 0x97, 0x53, 0x4f, 0x64, 0xf9, 0x05, 0xfe, 0x6a, 0xbc, 0x59, 0xbc, 0xf9, 0xef, 0x2e, 0x72, + 0x9f, 0x2f, 0xd8, 0x51, 0xb0, 0xde, 0x5e, 0x8e, 0x2f, 0x72, 0x7d, 0x39, 0x49, 0x7c, 0x83, 0x30, 0x80, 0xd3, 0x21, + 0x2d, 0xeb, 0x9d, 0xd6, 0x04, 0x9f, 0x81, 0x80, 0x90, 0x6c, 0xe7, 0xec, 0xc4, 0xd6, 0x1f, 0x49, 0xb4, 0x19, 0xcc, + 0xe4, 0x65, 0x90, 0xec, 0x6b, 0x24, 0x00, 0x72, 0x6a, 0x33, 0xd2, 0x71, 0x3e, 0x6d, 0x02, 0x6d, 0x32, 0x49, 0xdd, + 0x6e, 0x01, 0x5c, 0x80, 0x54, 0x94, 0xaf, 0xd6, 0x4d, 0x14, 0x35, 0xf3, 0x2a, 0x14, 0x5f, 0xed, 0xf5, 0x0b, 0xb4, + 0x53, 0x4d, 0x7b, 0x35, 0xd7, 0x81, 0xc0, 0x7a, 0xd5, 0x21, 0x42, 0x4b, 0xb6, 0x82, 0x1e, 0x7f, 0x4f, 0x7c, 0xb7, + 0xf9, 0x80, 0x7a, 0x83, 0xe5, 0x6e, 0xaf, 0x39, 0x9d, 0xda, 0xcd, 0x90, 0x1a, 0xf4, 0x19, 0x54, 0x51, 0xb0, 0x04, + 0xbc, 0xfd, 0xcc, 0xee, 0x66, 0x4b, 0x45, 0x36, 0xb7, 0xf8, 0xe2, 0x60, 0x5b, 0x24, 0x90, 0x8e, 0x23, 0x60, 0x4d, + 0x66, 0xa4, 0x24, 0xb3, 0x53, 0x9a, 0x32, 0x0a, 0x40, 0x06, 0xf0, 0x62, 0x12, 0xf6, 0x98, 0xf4, 0xdf, 0x87, 0x57, + 0x69, 0xfd, 0xd5, 0xfb, 0x62, 0xe4, 0x3d, 0xff, 0x68, 0x7a, 0xe0, 0xf4, 0x7b, 0x6b, 0x97, 0xb3, 0xd7, 0xa9, 0x47, + 0x8d, 0x25, 0xdf, 0x38, 0x80, 0xff, 0x84, 0xa7, 0xce, 0xea, 0x30, 0xdf, 0x8e, 0x9c, 0x52, 0xe5, 0xca, 0xbd, 0x0a, + 0xee, 0xf7, 0x07, 0xe1, 0xfe, 0xff, 0x55, 0xed, 0x66, 0xf8, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, 0x75, 0x58, 0x6b, + 0xee, 0x7f, 0x6b, 0x70, 0xe9, 0x77, 0x14, 0xd4, 0x75, 0xed, 0xdf, 0x79, 0x10, 0x68, 0x05, 0x5e, 0x17, 0x77, 0x26, + 0x2b, 0x3d, 0x4d, 0xe9, 0xc1, 0x20, 0x3a, 0xf8, 0xff, 0xb3, 0x6c, 0x8e, 0xbd, 0x38, 0x61, 0xb2, 0xb2, 0xfd, 0x7e, + 0x1a, 0x0b, 0xb0, 0x9c, 0x44, 0x69, 0xe3, 0x80, 0xf7, 0x95, 0x1f, 0xd7, 0xe8, 0xe7, 0x80, 0x4e, 0xac, 0x53, 0x40, + 0xdf, 0xd5, 0xf4, 0x09, 0xe2, 0xb1, 0x87, 0xd7, 0x90, 0x7b, 0x47, 0x70, 0x5f, 0x6b, 0x1c, 0x2e, 0x28, 0x3f, 0x14, + 0x77, 0x72, 0x31, 0x95, 0xfc, 0x52, 0xfa, 0xbd, 0x66, 0xf7, 0x45, 0x29, 0x37, 0xc4, 0x50, 0x93, 0x5b, 0x7f, 0x13, + 0x21, 0xdd, 0x2b, 0x92, 0xc8, 0x6a, 0x51, 0x77, 0xae, 0x92, 0x4e, 0x9c, 0xdd, 0xb3, 0xad, 0xca, 0x0c, 0xc0, 0x8b, + 0x2a, 0x97, 0x92, 0xb7, 0xeb, 0x40, 0x19, 0xd3, 0x7b, 0xec, 0x7c, 0x1d, 0x0d, 0xa8, 0xa5, 0xf4, 0x55, 0xde, 0xf0, + 0xef, 0xfc, 0x02, 0xf3, 0xae, 0xc6, 0xba, 0xf1, 0xc4, 0x3e, 0x1a, 0xda, 0x4d, 0xe3, 0x3e, 0x42, 0x40, 0x1d, 0x6e, + 0xc8, 0xa9, 0x46, 0xa2, 0x6b, 0x3e, 0xcb, 0xc3, 0x88, 0xb2, 0x91, 0xb7, 0xe0, 0x4c, 0x9c, 0xb3, 0x4e, 0x41, 0x86, + 0x99, 0xa1, 0x61, 0x05, 0x4d, 0x6f, 0x31, 0xc6, 0xf6, 0xf2, 0x8e, 0xef, 0x8e, 0xb2, 0xb5, 0xfd, 0xfa, 0xcb, 0x02, + 0x81, 0x74, 0x5c, 0x04, 0xef, 0x14, 0x5f, 0xe0, 0x91, 0x34, 0x32, 0xf5, 0x60, 0xdf, 0x5f, 0xd2, 0x8b, 0xb0, 0xff, + 0xd6, 0x9c, 0x26, 0x97, 0x2f, 0xe7, 0x4c, 0x69, 0x51, 0xe7, 0x6c, 0xf1, 0xe2, 0xb6, 0x71, 0xff, 0xd3, 0xe4, 0xda, + 0x98, 0xf5, 0xe7, 0x9c, 0x14, 0x15, 0x4e, 0xb4, 0xce, 0xe6, 0x62, 0xef, 0xbd, 0xe7, 0xbc, 0x1e, 0x2c, 0xbb, 0x07, + 0x67, 0x32, 0x62, 0xeb, 0xad, 0x2e, 0xbc, 0x64, 0xdf, 0x26, 0x6e, 0x9b, 0x0a, 0xae, 0x29, 0x1e, 0xbc, 0x7a, 0x99, + 0xde, 0x5d, 0x9d, 0x2c, 0x59, 0xac, 0x59, 0x7e, 0x34, 0xa0, 0x9b, 0x7d, 0x58, 0xb7, 0x8d, 0xc6, 0xf1, 0x9a, 0x4a, + 0x6c, 0x9b, 0x58, 0xc6, 0xac, 0xa6, 0x13, 0xc1, 0xfd, 0x5f, 0x36, 0xb8, 0x76, 0xa6, 0x0e, 0xc5, 0xb5, 0x19, 0x85, + 0x52, 0xf0, 0xa3, 0x04, 0x24, 0x5c, 0x32, 0x96, 0x0c, 0x9c, 0xe0, 0xdb, 0x39, 0x9d, 0x4c, 0x99, 0xa6, 0xe1, 0x74, + 0xf3, 0xc3, 0x69, 0x07, 0xdf, 0x76, 0x12, 0x23, 0x20, 0xb9, 0x1f, 0x19, 0xb9, 0xc1, 0x64, 0x49, 0xa8, 0x11, 0x77, + 0xeb, 0xe4, 0x17, 0x74, 0xcc, 0x64, 0x89, 0xa7, 0x52, 0x93, 0x87, 0xf3, 0xf1, 0x09, 0xfb, 0xf9, 0x67, 0xeb, 0x6f, + 0xd6, 0x37, 0xed, 0x2a, 0xdc, 0x28, 0xeb, 0xd4, 0x7e, 0x86, 0x3d, 0xab, 0x12, 0x42, 0xde, 0x94, 0xf7, 0xf6, 0x96, + 0xda, 0xa7, 0xdf, 0x37, 0x22, 0xb8, 0xfa, 0xce, 0xd0, 0xea, 0xcf, 0x29, 0x82, 0xe5, 0x6e, 0xd7, 0x4a, 0xa5, 0xc9, + 0xea, 0x89, 0xef, 0xfd, 0x1a, 0x6f, 0x45, 0xce, 0x83, 0x97, 0xec, 0x8d, 0x38, 0x7f, 0x2c, 0x8a, 0xef, 0x9e, 0x3f, + 0x22, 0x16, 0x97, 0x77, 0x73, 0x0c, 0xb1, 0xc9, 0xe5, 0x21, 0x95, 0xc4, 0x34, 0xf8, 0x04, 0x6a, 0x3b, 0xab, 0xa1, + 0x44, 0x57, 0x52, 0xab, 0x2b, 0xbe, 0x94, 0x02, 0x96, 0xca, 0xa8, 0x92, 0xa1, 0xae, 0x0e, 0xa7, 0x8e, 0xd2, 0xf2, + 0xc3, 0xab, 0x0a, 0x2e, 0x95, 0x79, 0x68, 0x69, 0x0c, 0xbf, 0xf4, 0xe9, 0x05, 0x63, 0x18, 0xd9, 0x66, 0x03, 0x97, + 0xa7, 0xe8, 0x44, 0xef, 0xe0, 0x0b, 0xa1, 0xe3, 0x43, 0x33, 0xf9, 0x02, 0x8d, 0xd7, 0x50, 0x92, 0xe1, 0x90, 0x73, + 0x55, 0xdc, 0xa2, 0x96, 0xb8, 0x7f, 0x45, 0xd6, 0x53, 0x4d, 0x69, 0xd1, 0x9e, 0x96, 0xa1, 0xa0, 0xb4, 0x4e, 0x72, + 0x5d, 0x61, 0x7a, 0x99, 0x74, 0x52, 0x4f, 0x6b, 0x70, 0x2b, 0x77, 0x8e, 0x44, 0x66, 0xf7, 0x4d, 0xd3, 0x91, 0x42, + 0x6e, 0x57, 0x40, 0xd2, 0xae, 0x3f, 0x8f, 0x55, 0xc8, 0x3e, 0x24, 0x4d, 0x2d, 0xe9, 0xfe, 0xcc, 0x0e, 0x84, 0x96, + 0xf7, 0xdd, 0xd8, 0xa9, 0x23, 0xdd, 0x83, 0x60, 0xec, 0xfc, 0x56, 0x69, 0x37, 0xcd, 0x49, 0xbc, 0x71, 0xf1, 0x6b, + 0x8f, 0x02, 0xb2, 0xa5, 0x19, 0x7c, 0x6d, 0x4d, 0x40, 0xbb, 0x7c, 0x03, 0x6b, 0x2d, 0x76, 0x30, 0xde, 0xe7, 0x6d, + 0xe8, 0xa1, 0x0f, 0x6c, 0x94, 0x6a, 0x1e, 0x7e, 0xa3, 0x54, 0xfd, 0x8e, 0x9c, 0x42, 0xd5, 0x73, 0xfe, 0xba, 0x24, + 0x8e, 0x8d, 0xac, 0xb6, 0x8b, 0x23, 0x06, 0x1b, 0x18, 0xe3, 0x50, 0x5f, 0x20, 0x62, 0xde, 0x31, 0x32, 0x40, 0x87, + 0xa4, 0x43, 0x59, 0x27, 0xd3, 0x44, 0x42, 0xcc, 0x03, 0x12, 0xec, 0x1d, 0x40, 0x3d, 0x80, 0xff, 0xc9, 0xa4, 0x45, + 0xfe, 0xa9, 0x5d, 0xe5, 0xdc, 0x31, 0xc7, 0x5f, 0x6a, 0x76, 0xcd, 0x46, 0x99, 0xd5, 0xd4, 0xe0, 0x7e, 0xd1, 0x14, + 0x11, 0xd5, 0xf2, 0x5a, 0x36, 0x4a, 0x67, 0x8e, 0xa4, 0xf8, 0x8b, 0xd9, 0xd2, 0x93, 0xfe, 0xf6, 0xbe, 0x94, 0x3e, + 0x7b, 0xf7, 0xfc, 0xce, 0x22, 0x67, 0xaa, 0xdd, 0xfd, 0x14, 0x87, 0x4f, 0x7d, 0xb2, 0xe4, 0x5f, 0x3f, 0xfe, 0x8b, + 0x7f, 0x41, 0x6f, 0xf8, 0x0b, 0xd6, 0xa5, 0x11, 0xac, 0x5d, 0xf6, 0xf5, 0x25, 0xd8, 0xf1, 0xa1, 0xd1, 0xa7, 0x0c, + 0x2c, 0x05, 0x77, 0x41, 0x4b, 0xf0, 0x10, 0x60, 0xb2, 0xd5, 0x6a, 0xfd, 0x40, 0xdc, 0x3f, 0xbb, 0xae, 0x2b, 0x5f, + 0x2c, 0xdc, 0x57, 0xdb, 0xf7, 0x45, 0xaa, 0xd5, 0xe7, 0xdd, 0x4e, 0x26, 0xc7, 0xbb, 0xff, 0x42, 0x0d, 0xfa, 0x46, + 0x84, 0xc2, 0x33, 0x3b, 0x3d, 0x5d, 0x0d, 0x8b, 0xd7, 0x55, 0xbf, 0x98, 0xaa, 0xb6, 0xb8, 0xa9, 0xa6, 0xc5, 0x8b, + 0xea, 0xf4, 0xe0, 0xff, 0xae, 0x78, 0xc9, 0x33, 0x61, 0x98, 0x0f, 0x34, 0xc8, 0xd9, 0xe3, 0x97, 0xa1, 0x96, 0x1b, + 0x1f, 0x28, 0x76, 0xab, 0xa2, 0x70, 0xda, 0xa5, 0xef, 0x7f, 0xdc, 0x67, 0xf0, 0x46, 0x0a, 0x7a, 0x19, 0xd3, 0x1e, + 0x2d, 0x69, 0xd0, 0x4c, 0x22, 0x48, 0xec, 0xeb, 0x4e, 0x7b, 0x27, 0x1d, 0x48, 0x18, 0xf4, 0xeb, 0x6d, 0xcb, 0x35, + 0x1e, 0x45, 0x98, 0x30, 0x79, 0xcb, 0x40, 0x1c, 0x0a, 0xbe, 0x42, 0x35, 0x22, 0xda, 0x3b, 0x61, 0x9b, 0x24, 0x82, + 0x20, 0x86, 0x2e, 0x75, 0x52, 0x07, 0xbb, 0x4c, 0x73, 0xeb, 0x3c, 0x96, 0x00, 0x69, 0xc5, 0x9a, 0xf2, 0x53, 0x5f, + 0xb4, 0x62, 0x92, 0x8a, 0xda, 0x5c, 0x98, 0x2a, 0xa1, 0x9b, 0x11, 0x62, 0x7d, 0xcb, 0x05, 0xdf, 0xe6, 0x75, 0x2d, + 0x02, 0x2d, 0x37, 0x6b, 0x06, 0xe4, 0x8c, 0x2e, 0xe4, 0x8d, 0xb9, 0x90, 0x2d, 0x96, 0x69, 0xbd, 0x30, 0x4e, 0x35, + 0x6d, 0xda, 0x88, 0xc8, 0x5e, 0xfd, 0xfa, 0x16, 0x88, 0xec, 0x43, 0x5f, 0xd4, 0x99, 0xde, 0xd4, 0xad, 0xb0, 0x89, + 0x41, 0xa6, 0xa1, 0x2a, 0x51, 0x1a, 0xa2, 0x11, 0x17, 0xf1, 0x68, 0x57, 0x89, 0xb0, 0xf1, 0x93, 0xfc, 0x9a, 0x49, + 0x0a, 0x3a, 0x80, 0x58, 0xa0, 0xe2, 0xba, 0xf6, 0x02, 0xe2, 0x90, 0x95, 0xde, 0x37, 0xfd, 0x53, 0x6e, 0xee, 0x8c, + 0x72, 0x33, 0xf4, 0x93, 0x26, 0x57, 0x70, 0x09, 0x31, 0xea, 0x21, 0x8a, 0xc8, 0x47, 0xb1, 0xef, 0x50, 0x27, 0x90, + 0x02, 0x4e, 0x14, 0x67, 0xd0, 0x38, 0x53, 0x81, 0x03, 0xf6, 0x81, 0x16, 0x71, 0x0c, 0x45, 0xf6, 0xa3, 0xae, 0x3a, + 0xd7, 0x23, 0x93, 0x54, 0x77, 0xd2, 0x6f, 0xfe, 0x73, 0x55, 0x65, 0xb0, 0x97, 0x57, 0xab, 0x6c, 0x3e, 0x28, 0xf9, + 0x07, 0xf6, 0x37, 0x73, 0x85, 0x8a, 0xb5, 0xf3, 0x36, 0x9c, 0xd1, 0xe6, 0x88, 0xb1, 0x85, 0xe5, 0x71, 0x6e, 0xa9, + 0x27, 0x70, 0xad, 0xbf, 0x03, 0xcf, 0x70, 0xf6, 0x2d, 0x61, 0x64, 0x5e, 0x4e, 0x26, 0x0b, 0xdd, 0xcc, 0x6e, 0x77, + 0x79, 0xe4, 0x6c, 0x98, 0xd4, 0x9e, 0x2c, 0xea, 0xd7, 0x00, 0xe3, 0x47, 0xbc, 0xe6, 0xc1, 0x9e, 0x81, 0xeb, 0x91, + 0x48, 0xc1, 0x66, 0x80, 0x77, 0x32, 0x76, 0xc4, 0xca, 0x89, 0xb3, 0x34, 0x06, 0x9d, 0x0b, 0x57, 0xa5, 0xe9, 0xef, + 0x2d, 0x51, 0x4a, 0x00, 0x98, 0x41, 0xe8, 0xfd, 0xdc, 0x36, 0xf7, 0xad, 0xa8, 0x4d, 0x49, 0x1a, 0xe2, 0x0c, 0xa2, + 0x72, 0xa0, 0x62, 0x17, 0x34, 0x1d, 0xed, 0x5b, 0x2a, 0xc7, 0xc9, 0x0c, 0x12, 0xa6, 0x5e, 0x19, 0x77, 0xc5, 0x5f, + 0xfa, 0xac, 0x56, 0xff, 0xfc, 0xc8, 0xf4, 0x54, 0xff, 0x88, 0xec, 0xf6, 0x55, 0xf1, 0x3c, 0x57, 0x7e, 0x62, 0x4a, + 0xcd, 0xd5, 0x76, 0x27, 0x43, 0xbc, 0xb1, 0xf4, 0x56, 0xcc, 0x1c, 0xb0, 0xde, 0x1a, 0x9e, 0xd7, 0xbb, 0x5e, 0xcc, + 0x1d, 0xf5, 0x4b, 0xba, 0xaf, 0xcf, 0xff, 0x26, 0x03, 0xfb, 0x0d, 0x93, 0x9c, 0xfb, 0x9a, 0xf6, 0x3c, 0xa1, 0xaf, + 0x16, 0xf3, 0x9a, 0x26, 0x36, 0xf6, 0x99, 0x67, 0xde, 0xd2, 0x34, 0xc8, 0x9e, 0xee, 0xeb, 0x95, 0xd6, 0x99, 0x39, + 0xc7, 0x87, 0x83, 0xe6, 0xf3, 0x27, 0xdd, 0x1b, 0x07, 0xdd, 0x15, 0x28, 0x2e, 0xdd, 0x27, 0xdf, 0x51, 0xf8, 0xc2, + 0x5c, 0x30, 0xed, 0x5c, 0x22, 0xe4, 0xc1, 0xcd, 0xf2, 0x04, 0xa4, 0xbc, 0xcc, 0x27, 0x90, 0x34, 0xcf, 0xcf, 0x97, + 0x98, 0x95, 0x22, 0xc1, 0xcd, 0x84, 0x59, 0x4f, 0x9b, 0x81, 0xe9, 0x66, 0x37, 0x9b, 0x77, 0xf5, 0xe4, 0x49, 0xe7, + 0xb5, 0x83, 0xa6, 0xce, 0xbf, 0xb2, 0xd9, 0xa7, 0x2f, 0x2a, 0xf5, 0x34, 0xad, 0xdc, 0xf5, 0x24, 0x7f, 0xaf, 0x44, + 0x99, 0x05, 0xf0, 0x5e, 0x4a, 0xe4, 0x29, 0x9e, 0xee, 0xe4, 0xa4, 0x89, 0x6a, 0x80, 0x14, 0xab, 0xbb, 0x13, 0xc3, + 0x46, 0xd5, 0x42, 0xa7, 0x1c, 0x3d, 0xe3, 0xd5, 0xcf, 0xd8, 0x23, 0xbe, 0x88, 0xd8, 0x89, 0x8d, 0xc2, 0x8f, 0x8a, + 0xa1, 0xc2, 0xfa, 0xb4, 0x2e, 0x83, 0x57, 0x86, 0xd5, 0x65, 0x2c, 0x06, 0xe4, 0xe7, 0xa6, 0x5c, 0x48, 0xa1, 0xe5, + 0xe7, 0xe8, 0x3e, 0x34, 0x35, 0x50, 0x6f, 0x7c, 0x1e, 0xef, 0xf2, 0xd9, 0xa4, 0xfe, 0x0d, 0x04, 0x7c, 0x90, 0x01, + 0xb5, 0x2c, 0x74, 0x5a, 0xcf, 0x9e, 0xe2, 0xc7, 0x4f, 0xfb, 0xdf, 0x58, 0xf2, 0xf1, 0xc7, 0xff, 0x14, 0xcf, 0x1e, + 0xfb, 0xa8, 0x52, 0x68, 0x12, 0xbc, 0xa7, 0xb0, 0x6f, 0xb3, 0xff, 0xef, 0x91, 0x67, 0xd1, 0xc4, 0x8b, 0xe1, 0x51, + 0x9d, 0x5d, 0x20, 0x4a, 0x6a, 0x7d, 0xe8, 0x8b, 0xd8, 0x71, 0xdf, 0xf7, 0x60, 0x59, 0xba, 0x47, 0xdc, 0xe4, 0xc1, + 0xf5, 0x49, 0xec, 0xf6, 0x95, 0x89, 0x54, 0x6a, 0xfc, 0x8c, 0x5c, 0xc0, 0x58, 0x27, 0xed, 0x31, 0x5c, 0xda, 0xd2, + 0x48, 0xc1, 0xa6, 0x14, 0x67, 0x52, 0x80, 0xfb, 0x4c, 0x94, 0xbe, 0xb3, 0x8f, 0x20, 0xa9, 0xf7, 0x2f, 0x4d, 0x60, + 0x49, 0x5e, 0x97, 0x05, 0x12, 0x9f, 0x8f, 0x2b, 0xf7, 0xf9, 0x24, 0x20, 0x2e, 0x8a, 0x0b, 0x68, 0x0b, 0xc4, 0x18, + 0x15, 0xb9, 0x14, 0x3d, 0x64, 0x69, 0x2a, 0x26, 0xaa, 0x43, 0x7a, 0xc1, 0x6e, 0xdf, 0x0d, 0x94, 0x32, 0x2d, 0x74, + 0xfc, 0xd5, 0x89, 0x18, 0x28, 0x5d, 0x9e, 0xed, 0x6d, 0x61, 0x40, 0x2e, 0x17, 0x13, 0x82, 0x34, 0xbe, 0x9e, 0xc2, + 0xb2, 0xf3, 0x11, 0x5d, 0x25, 0x00, 0x29, 0xbc, 0x5b, 0xc4, 0xcd, 0xa0, 0xa0, 0xa4, 0x81, 0xaa, 0xa9, 0x8d, 0x1e, + 0x08, 0xb1, 0xec, 0x4c, 0xa9, 0xdc, 0x8a, 0x0a, 0x04, 0x01, 0x22, 0x1b, 0x7b, 0x90, 0xc8, 0xe9, 0x61, 0x7a, 0xb8, + 0xa3, 0x2d, 0x4a, 0xa6, 0x68, 0x04, 0x35, 0xda, 0xf4, 0x90, 0xa4, 0x07, 0xaf, 0x9b, 0x89, 0xc1, 0x89, 0xb3, 0xe1, + 0x17, 0xbc, 0xd7, 0x93, 0x7b, 0xbb, 0x36, 0xb2, 0xcf, 0x25, 0xe9, 0x10, 0x73, 0x78, 0xd8, 0xd5, 0xd3, 0xcd, 0x71, + 0xbb, 0xa7, 0x9c, 0x7b, 0x89, 0x9d, 0x80, 0xf6, 0xf6, 0xd4, 0x7d, 0x67, 0x25, 0x6a, 0x5d, 0xf0, 0x08, 0x29, 0xd7, + 0x49, 0xd7, 0x93, 0xef, 0x2f, 0xef, 0x6a, 0x53, 0x2a, 0x9b, 0x88, 0x54, 0x34, 0x99, 0x2a, 0x10, 0x53, 0x82, 0x34, + 0x96, 0x51, 0x2f, 0xb7, 0x73, 0xc4, 0x9e, 0x0e, 0xa3, 0xb8, 0x85, 0x37, 0xb3, 0x55, 0xf6, 0x26, 0xad, 0xaf, 0xb0, + 0x82, 0x69, 0x8a, 0x6a, 0xfe, 0xfb, 0x59, 0x56, 0xb4, 0x33, 0x10, 0x41, 0xa8, 0xe7, 0xb6, 0x25, 0xbb, 0x80, 0x46, + 0x39, 0x7f, 0xdb, 0x40, 0x9b, 0x0e, 0xfb, 0x20, 0xe4, 0x39, 0x32, 0xef, 0xe5, 0x5b, 0x22, 0xc4, 0x40, 0x4a, 0x90, + 0x81, 0xaf, 0x5d, 0x44, 0xd4, 0x1c, 0x16, 0xcd, 0x6d, 0xe0, 0xf0, 0x21, 0x5c, 0x91, 0x99, 0x60, 0x32, 0xc5, 0xdd, + 0x85, 0x38, 0xed, 0xb8, 0xc3, 0x3d, 0x3b, 0xea, 0x59, 0x93, 0x3b, 0x65, 0x1a, 0x69, 0x26, 0x79, 0x7a, 0xb7, 0x4a, + 0xa3, 0x6c, 0xe9, 0xc8, 0xc5, 0x26, 0x92, 0x4b, 0xb9, 0x85, 0x88, 0xdb, 0xb2, 0x76, 0xfa, 0xf6, 0xfb, 0xb2, 0x79, + 0x74, 0x2f, 0xbe, 0xf5, 0x3e, 0xec, 0xdc, 0xaa, 0xb7, 0x35, 0xdb, 0xd6, 0x4f, 0x4b, 0x81, 0x52, 0x06, 0xdc, 0x99, + 0xae, 0x64, 0x26, 0x55, 0x57, 0xbe, 0x68, 0xdb, 0x21, 0x5f, 0x98, 0xc0, 0xf4, 0x34, 0xbc, 0xcd, 0x6a, 0x9d, 0x50, + 0x94, 0xd2, 0x07, 0x62, 0x91, 0xf8, 0x30, 0x00, 0xc6, 0x07, 0xaf, 0x89, 0x5c, 0xf0, 0x33, 0xfc, 0x5c, 0x2a, 0xfd, + 0xae, 0xc9, 0x52, 0x14, 0x80, 0x3e, 0x88, 0xf6, 0xec, 0x34, 0xaa, 0xf9, 0x2a, 0x9b, 0xe9, 0xe4, 0x20, 0xa6, 0x7f, + 0xfc, 0xff, 0x5c, 0x05, 0xea, 0xb7, 0x23, 0x3d, 0x84, 0xf7, 0x9b, 0x04, 0xae, 0xd5, 0xc2, 0x98, 0x9e, 0xc4, 0xa8, + 0x7b, 0x58, 0x12, 0xe1, 0x40, 0x00, 0x5f, 0x45, 0x4d, 0xdc, 0x48, 0xe3, 0xad, 0xa2, 0xa7, 0xa8, 0x6f, 0xc3, 0x5b, + 0x77, 0xb2, 0x4f, 0xc6, 0xe1, 0x7e, 0x8e, 0xb9, 0x17, 0x25, 0xcb, 0x32, 0x88, 0x86, 0x41, 0xd1, 0x2d, 0x0c, 0xac, + 0x90, 0x9f, 0x2f, 0xe0, 0xcb, 0x30, 0xe7, 0x33, 0xa3, 0x64, 0xb4, 0x42, 0xf4, 0x2a, 0xa4, 0x0e, 0x12, 0xef, 0x66, + 0x98, 0x0d, 0x7a, 0x06, 0xc5, 0xfe, 0x60, 0xea, 0x54, 0x2a, 0x68, 0xaf, 0xaa, 0xd2, 0x64, 0x57, 0x92, 0x5b, 0x7b, + 0x15, 0x1d, 0xfd, 0x14, 0x44, 0x8e, 0x97, 0xa2, 0xc5, 0x17, 0x1e, 0x0b, 0xfb, 0x5d, 0xdc, 0x1c, 0xc7, 0x00, 0x3c, + 0x7f, 0xfa, 0xa9, 0x17, 0xb7, 0x22, 0x3b, 0xfd, 0x5b, 0xe2, 0xd2, 0x77, 0x8f, 0xa6, 0xf1, 0xff, 0x29, 0x64, 0x7f, + 0xe0, 0xb7, 0x08, 0xac, 0x3f, 0xed, 0x31, 0x38, 0xb8, 0x84, 0xeb, 0x2d, 0x62, 0xf3, 0x05, 0x2c, 0xcb, 0xdb, 0xad, + 0x79, 0x20, 0x24, 0xee, 0x0b, 0x63, 0x66, 0x4f, 0xca, 0x6a, 0x94, 0x08, 0xff, 0xba, 0x8f, 0x61, 0xff, 0x35, 0x71, + 0x09, 0xc2, 0x70, 0x6e, 0x5c, 0xe8, 0xef, 0xb4, 0xce, 0x9e, 0xe2, 0xfb, 0xa7, 0xfe, 0x66, 0xc9, 0xfb, 0x1f, 0xff, + 0x53, 0x9c, 0x79, 0x67, 0x5c, 0xa3, 0xb7, 0x4f, 0x6f, 0x6e, 0x22, 0x46, 0x4d, 0x5e, 0xcb, 0x0a, 0x67, 0x3f, 0x8b, + 0x9c, 0xcd, 0x84, 0x57, 0x27, 0x72, 0x81, 0x86, 0x91, 0x8f, 0x7b, 0x5e, 0xa2, 0x17, 0xec, 0xba, 0xa3, 0x58, 0x9a, + 0x68, 0xcb, 0x22, 0x54, 0xe8, 0xa7, 0x06, 0x49, 0x82, 0xf9, 0xfe, 0x27, 0x31, 0x3b, 0x6a, 0xab, 0x61, 0x66, 0x15, + 0x0f, 0xf1, 0x5d, 0x5a, 0x99, 0xa4, 0x9c, 0x57, 0xf5, 0x4e, 0x25, 0xca, 0xe6, 0x47, 0x64, 0x87, 0xc5, 0x60, 0xcc, + 0x4a, 0x08, 0xfb, 0x9d, 0x21, 0x32, 0x72, 0xd4, 0x97, 0x38, 0x49, 0xfc, 0x56, 0x47, 0x48, 0xbc, 0xb3, 0x34, 0x48, + 0x5f, 0x4b, 0x80, 0x7c, 0x2d, 0xbb, 0x3e, 0xf6, 0x62, 0x4a, 0x27, 0x1c, 0xee, 0x24, 0x7d, 0xeb, 0x3d, 0xf2, 0x8d, + 0x30, 0x6f, 0x95, 0xc6, 0x31, 0x20, 0xec, 0x5c, 0x03, 0x46, 0x46, 0xec, 0x40, 0x0e, 0x31, 0x17, 0x3b, 0x40, 0x30, + 0xeb, 0x6a, 0x9c, 0x03, 0xbf, 0xf7, 0x0e, 0xa5, 0xf4, 0x62, 0x2d, 0xb5, 0x4f, 0x72, 0x7e, 0x90, 0xc3, 0x31, 0x27, + 0x30, 0xde, 0x93, 0x39, 0x1d, 0x68, 0x1e, 0x93, 0x52, 0x2b, 0x91, 0x8a, 0x06, 0xe4, 0x57, 0xc9, 0xe0, 0x9e, 0xed, + 0xc9, 0x88, 0x93, 0x7f, 0xa1, 0x94, 0xfc, 0xe1, 0xc6, 0x3d, 0x9a, 0x09, 0xce, 0xcb, 0x03, 0x76, 0xb1, 0x59, 0x94, + 0x40, 0x3b, 0x53, 0xcd, 0x93, 0xb3, 0x05, 0x73, 0x69, 0x49, 0x49, 0xcb, 0xc2, 0x27, 0x64, 0x46, 0x6e, 0xfe, 0xc5, + 0xeb, 0x9b, 0xfe, 0x91, 0x61, 0x05, 0xc1, 0x5e, 0xeb, 0xaf, 0xf5, 0x7e, 0x4f, 0xa7, 0x83, 0x43, 0xd0, 0x9d, 0x03, + 0xb4, 0x4a, 0xe3, 0x61, 0x7f, 0xc6, 0x26, 0x80, 0x4c, 0x10, 0x3f, 0xdc, 0xb0, 0xee, 0xee, 0x07, 0x04, 0x66, 0x3f, + 0xf1, 0x8b, 0xe3, 0x94, 0x11, 0xf0, 0xad, 0xdd, 0xa2, 0x12, 0x22, 0x87, 0xff, 0xe7, 0xbe, 0x92, 0xc5, 0xea, 0x36, + 0x39, 0xd2, 0xec, 0xd7, 0xad, 0x33, 0xc0, 0x38, 0xfa, 0xe5, 0x3a, 0xa1, 0x12, 0x46, 0x66, 0x87, 0xa6, 0xd8, 0x15, + 0xce, 0x1e, 0xe1, 0x64, 0xc6, 0x7e, 0x0a, 0x8d, 0x48, 0xe3, 0x60, 0x25, 0x47, 0x5a, 0x80, 0x8b, 0xe5, 0x70, 0x68, + 0x98, 0x84, 0x0e, 0xb0, 0xc5, 0x45, 0x8e, 0xfb, 0xe1, 0xf9, 0x4c, 0xb2, 0xc3, 0x4b, 0x02, 0xe8, 0xc0, 0xb9, 0x88, + 0x89, 0x20, 0x07, 0x2d, 0x06, 0xa1, 0x1b, 0x72, 0xb0, 0x16, 0xaa, 0x61, 0x72, 0x04, 0xcf, 0xbe, 0xfe, 0x31, 0xfa, + 0x49, 0xc3, 0xe0, 0x25, 0x24, 0xc3, 0x28, 0x01, 0xe4, 0x98, 0xac, 0xf4, 0x1b, 0xf7, 0x76, 0x7b, 0xeb, 0xae, 0x0b, + 0x89, 0x3b, 0xfb, 0x69, 0xd7, 0x72, 0x31, 0x91, 0x7a, 0xf5, 0xd1, 0xc0, 0xb0, 0x73, 0xc0, 0x16, 0x78, 0x15, 0x44, + 0x67, 0xa2, 0xc7, 0x3d, 0xdc, 0x9f, 0x42, 0xaf, 0x30, 0x47, 0x60, 0x02, 0x7c, 0x63, 0xb2, 0x3b, 0x79, 0x84, 0xab, + 0xdb, 0x7d, 0xb4, 0xe7, 0xb1, 0x35, 0x8e, 0x0a, 0xa1, 0x34, 0xe2, 0x2d, 0xd3, 0x9d, 0x64, 0xc2, 0x3a, 0xac, 0xfe, + 0xa1, 0x29, 0xae, 0xd2, 0x77, 0xd2, 0x34, 0x82, 0x13, 0xb1, 0xfb, 0x36, 0xdc, 0x6a, 0xe0, 0x04, 0x47, 0x2e, 0x7a, + 0xf8, 0x8e, 0x08, 0x43, 0x0b, 0x7c, 0xc0, 0x49, 0xc5, 0x6c, 0x3c, 0x26, 0x06, 0x4e, 0xe3, 0x24, 0x57, 0x66, 0x39, + 0x37, 0x39, 0x24, 0xae, 0x58, 0xae, 0xb0, 0x9e, 0x5e, 0xb3, 0x6c, 0x93, 0x09, 0xf0, 0xde, 0x4f, 0xdd, 0x7b, 0x26, + 0xa4, 0x5c, 0x35, 0x6a, 0xcb, 0xdd, 0x59, 0xf1, 0x69, 0xb4, 0x92, 0xc9, 0xc9, 0x26, 0xfe, 0x30, 0xc0, 0x9d, 0xdd, + 0x12, 0xdd, 0xa9, 0xee, 0x2e, 0xb9, 0x0b, 0x8d, 0x27, 0xcc, 0x9c, 0xc2, 0x3e, 0x58, 0x4b, 0x75, 0x1e, 0x86, 0xd6, + 0xe3, 0xef, 0x9a, 0x99, 0x80, 0xc8, 0x4e, 0xa6, 0xb3, 0xf8, 0xa1, 0x1b, 0x90, 0xd2, 0x12, 0x47, 0x17, 0x25, 0xab, + 0x3f, 0xad, 0x7b, 0x93, 0x2a, 0xee, 0xd0, 0xf6, 0xf5, 0x8d, 0x1c, 0xef, 0x24, 0x2b, 0xb1, 0x04, 0xd5, 0x48, 0x7e, + 0x91, 0xa4, 0x81, 0x1d, 0x90, 0x0e, 0xb9, 0x46, 0xc3, 0x4c, 0x3d, 0x9b, 0x07, 0xaf, 0x23, 0xdd, 0x06, 0xab, 0x74, + 0x66, 0xf7, 0xf2, 0x03, 0x69, 0x85, 0xa6, 0x8c, 0x49, 0x31, 0xc9, 0xc7, 0x8b, 0x2e, 0x4e, 0x9c, 0xa2, 0x96, 0x7c, + 0x72, 0xe5, 0xa4, 0xe7, 0xb5, 0x3a, 0xe4, 0xea, 0x65, 0x0f, 0x31, 0x90, 0x24, 0xb3, 0x78, 0xa1, 0x7a, 0x72, 0x43, + 0xbc, 0x46, 0x03, 0x9c, 0xb6, 0xc7, 0xee, 0x2e, 0x1e, 0xe5, 0xad, 0x7f, 0xaa, 0xb7, 0x15, 0x5a, 0xfe, 0x94, 0x97, + 0xf7, 0x6a, 0xfd, 0x6d, 0x14, 0x21, 0xbf, 0x8b, 0x1f, 0x76, 0xeb, 0x9f, 0xb6, 0xab, 0x52, 0xa1, 0x53, 0xf9, 0x35, + 0x69, 0x8b, 0x05, 0xc0, 0x9f, 0xd7, 0xa6, 0x29, 0x24, 0x23, 0x8c, 0xa8, 0x4f, 0x10, 0x61, 0xaa, 0x13, 0xc6, 0xb7, + 0xa2, 0x86, 0xbc, 0x15, 0xad, 0x48, 0xaf, 0x19, 0x4d, 0xe3, 0xec, 0xe7, 0x8e, 0x11, 0x76, 0x32, 0x1c, 0xb1, 0x5b, + 0x92, 0x72, 0xfd, 0x14, 0xe9, 0x29, 0x24, 0x8e, 0x45, 0x70, 0x99, 0x50, 0x69, 0x29, 0xc7, 0x04, 0xd0, 0xad, 0xb6, + 0x86, 0x2c, 0x86, 0xd4, 0xa0, 0x8c, 0x59, 0xdd, 0x3c, 0x22, 0x70, 0xd4, 0xa0, 0x87, 0x8e, 0xa4, 0x70, 0x42, 0xb3, + 0x9d, 0x3e, 0x3e, 0x7f, 0xc6, 0xb4, 0x55, 0xdb, 0x20, 0x12, 0x03, 0xd0, 0xed, 0xee, 0x48, 0x0c, 0x41, 0xda, 0xdf, + 0x11, 0xd9, 0x5a, 0x2d, 0xca, 0xe8, 0xc8, 0x86, 0x6e, 0xa7, 0xc8, 0xfc, 0x5a, 0xcd, 0x15, 0xd9, 0xd4, 0xed, 0x06, + 0x65, 0x14, 0x19, 0xa4, 0xbc, 0xa3, 0xb4, 0xe5, 0x62, 0x19, 0x1d, 0xdd, 0xa2, 0x88, 0x50, 0x71, 0x1b, 0x14, 0x69, + 0xfa, 0x83, 0x14, 0x39, 0x0d, 0x11, 0xa7, 0x00, 0xef, 0x4e, 0x2d, 0x89, 0xda, 0x2d, 0x15, 0x0d, 0x9e, 0x42, 0x2f, + 0x83, 0x79, 0x77, 0xe1, 0x40, 0x42, 0x68, 0x73, 0x83, 0x53, 0x10, 0x6d, 0x41, 0xa7, 0x22, 0xbc, 0x15, 0xe9, 0x41, + 0x6a, 0x20, 0x00, 0xaf, 0xce, 0x7d, 0x1c, 0x1c, 0x00, 0xf4, 0xc9, 0x2a, 0xe8, 0x7c, 0x7f, 0xb4, 0xc8, 0x21, 0x96, + 0x66, 0x47, 0xea, 0x29, 0xe2, 0x52, 0x9a, 0x4f, 0xc4, 0xed, 0x82, 0x1c, 0x44, 0x9a, 0x56, 0xfc, 0x87, 0x5c, 0xd8, + 0xa4, 0x9d, 0x0f, 0x33, 0x04, 0x5f, 0x6a, 0xe2, 0x89, 0xd4, 0x7d, 0x8e, 0xc5, 0x94, 0x91, 0xc9, 0xd7, 0xba, 0x0b, + 0xab, 0x1d, 0xcc, 0x01, 0x31, 0x9e, 0x54, 0xf2, 0xd3, 0x29, 0xb2, 0xb3, 0xc9, 0x62, 0xa5, 0xa1, 0x02, 0x5a, 0x3a, + 0xa4, 0xcb, 0x65, 0xab, 0xc7, 0x01, 0x77, 0xfc, 0xa8, 0x09, 0x1f, 0x0d, 0x71, 0x5d, 0xfa, 0xf4, 0x2a, 0x48, 0x43, + 0xf8, 0x60, 0x29, 0xa4, 0x65, 0xd5, 0xb8, 0xf7, 0x66, 0x92, 0xda, 0xbf, 0xdb, 0x2c, 0xad, 0x69, 0xb0, 0xc3, 0xb6, + 0xe8, 0x19, 0x44, 0xe1, 0xeb, 0xaf, 0xa7, 0xd5, 0x47, 0xe7, 0x36, 0x2d, 0x88, 0xd0, 0x57, 0x05, 0x4e, 0x2c, 0xa7, + 0xbf, 0x2c, 0xe9, 0xe6, 0x96, 0xd0, 0x47, 0x2c, 0x7f, 0x94, 0x29, 0xc7, 0x67, 0x86, 0x17, 0x6b, 0xe8, 0x7e, 0x07, + 0x5a, 0x44, 0x8d, 0xb3, 0x59, 0x16, 0x8d, 0x6c, 0x09, 0xaf, 0xa9, 0x98, 0x98, 0xab, 0x1f, 0x0d, 0x19, 0x6b, 0x64, + 0x82, 0xc8, 0xa2, 0x1f, 0x3f, 0xea, 0xd2, 0x11, 0xe7, 0x61, 0x10, 0x27, 0x20, 0xcd, 0xbc, 0x64, 0xe4, 0x4d, 0x14, + 0xfc, 0xd6, 0x73, 0x60, 0x9b, 0xf7, 0x5b, 0xfb, 0xcc, 0x6e, 0xc4, 0x47, 0xfa, 0xda, 0xeb, 0x1d, 0x08, 0x25, 0x21, + 0x46, 0xe5, 0x9e, 0x8f, 0x8b, 0x25, 0x7b, 0x1a, 0x78, 0x53, 0x96, 0x2b, 0x06, 0xb7, 0xf8, 0x0d, 0xe8, 0x41, 0x0d, + 0xef, 0x20, 0xb4, 0x8f, 0x9c, 0x76, 0x84, 0x07, 0x68, 0x54, 0x0f, 0xd7, 0x72, 0x44, 0x17, 0x10, 0x64, 0x4e, 0xd0, + 0xa3, 0x81, 0x32, 0x50, 0xf0, 0x95, 0x64, 0xd0, 0x55, 0x66, 0xbb, 0xcc, 0xd6, 0xd0, 0x8c, 0x09, 0x10, 0xa9, 0xce, + 0x9f, 0x46, 0x70, 0x09, 0x5d, 0xc2, 0xa5, 0xa2, 0x0e, 0x64, 0xd4, 0xca, 0x70, 0x30, 0x0a, 0x68, 0xfa, 0x54, 0x1a, + 0xbf, 0x1a, 0x5d, 0x0a, 0xc0, 0xb1, 0xc6, 0xe7, 0x49, 0x06, 0x9f, 0x6d, 0x5c, 0xb1, 0xb8, 0x0c, 0x9a, 0x03, 0x83, + 0x6b, 0x5f, 0xdb, 0xab, 0xae, 0xc1, 0xce, 0xeb, 0xef, 0xa2, 0x33, 0x86, 0x3d, 0xa3, 0x10, 0x2b, 0x80, 0x0e, 0x90, + 0x28, 0xd7, 0xc0, 0xd9, 0x7b, 0xee, 0x7c, 0x6c, 0x23, 0x57, 0xd0, 0x85, 0x0e, 0x08, 0xae, 0x35, 0xb8, 0xdc, 0x3f, + 0x02, 0x5c, 0x68, 0x68, 0xe7, 0x59, 0x60, 0x45, 0x2e, 0x33, 0x50, 0x23, 0xfe, 0x4d, 0xee, 0x60, 0x59, 0x8d, 0x74, + 0x11, 0x8f, 0x15, 0xb5, 0xed, 0x64, 0x81, 0x4e, 0xb0, 0x4d, 0x0d, 0xb1, 0x03, 0x14, 0xbc, 0x50, 0x7e, 0xc2, 0xa9, + 0x47, 0x4b, 0x37, 0xa8, 0x2c, 0xf8, 0x1c, 0x98, 0xc5, 0xef, 0xa4, 0xde, 0xc2, 0xfd, 0x27, 0x47, 0x76, 0x10, 0x40, + 0xbc, 0x35, 0x2b, 0x84, 0x30, 0xf1, 0x72, 0x6c, 0x13, 0x76, 0x94, 0x81, 0x60, 0x37, 0x9a, 0x08, 0xd9, 0x08, 0x73, + 0x1b, 0xef, 0xa2, 0xf5, 0x7a, 0x1f, 0xbb, 0xbf, 0x18, 0x85, 0xc1, 0x76, 0x81, 0x61, 0xfc, 0x58, 0x8c, 0x22, 0xd4, + 0xf6, 0xf2, 0x5b, 0x91, 0x8c, 0xe4, 0x67, 0x15, 0xcc, 0x45, 0xdc, 0x0e, 0x6c, 0x5d, 0x99, 0x5a, 0x3f, 0x20, 0x2a, + 0xef, 0xf7, 0x92, 0x41, 0xbb, 0x85, 0x8f, 0x6f, 0x46, 0x76, 0xe2, 0x2b, 0xc7, 0xf5, 0xac, 0xfa, 0xfc, 0xfe, 0x39, + 0x22, 0x6b, 0x1e, 0x6f, 0xdd, 0x19, 0x8d, 0xce, 0x6a, 0x2d, 0x87, 0x8d, 0xda, 0xc0, 0x30, 0x21, 0xac, 0xf0, 0xfd, + 0xbc, 0x5c, 0xfb, 0x80, 0x30, 0xfc, 0xba, 0xe1, 0x37, 0x9e, 0x2d, 0xb0, 0x97, 0x1e, 0x1c, 0x2d, 0x6f, 0x5d, 0x57, + 0xd7, 0xd3, 0x4a, 0x34, 0x1e, 0x61, 0x12, 0xe2, 0x75, 0xde, 0x30, 0xa5, 0x03, 0x99, 0xe5, 0xf0, 0xa4, 0x7f, 0x70, + 0x4d, 0x67, 0x3e, 0xc4, 0x88, 0xf6, 0x17, 0x80, 0x7c, 0xd1, 0x94, 0x8f, 0x48, 0x9e, 0xd1, 0xe4, 0x06, 0x9b, 0x46, + 0xfa, 0x85, 0x33, 0xa5, 0x3a, 0x10, 0xdc, 0x77, 0x00, 0x00, 0x03, 0x75, 0x58, 0xf0, 0xfb, 0xd8, 0x56, 0xe2, 0xba, + 0x06, 0x63, 0x30, 0x30, 0xfd, 0x47, 0xbf, 0xa8, 0xf3, 0xa3, 0xcf, 0x50, 0x4d, 0xac, 0xf9, 0x52, 0x23, 0x32, 0xbb, + 0x92, 0x15, 0xd9, 0x4d, 0x90, 0x1f, 0xe7, 0xcb, 0x82, 0xdc, 0x84, 0xb8, 0x09, 0x41, 0xc5, 0x3d, 0xf1, 0xb5, 0xa8, + 0x02, 0x7d, 0x03, 0x94, 0x7f, 0x38, 0xeb, 0x40, 0xd0, 0x5f, 0x04, 0xc6, 0x9a, 0x1c, 0x84, 0xf3, 0xcf, 0x2d, 0x33, + 0x91, 0x3f, 0x8f, 0xc2, 0x65, 0xc9, 0x5f, 0xdd, 0xb2, 0x8d, 0xcc, 0xb8, 0xf1, 0x6d, 0x54, 0x99, 0x14, 0xf2, 0xba, + 0xf6, 0xac, 0x33, 0xbe, 0x90, 0x6a, 0x15, 0xc8, 0xd5, 0x45, 0xcc, 0x8c, 0x69, 0x0b, 0x39, 0xfd, 0x59, 0xfb, 0x5a, + 0xe5, 0x7f, 0xc6, 0x1d, 0x1c, 0xb3, 0xf0, 0xcf, 0xc7, 0x6d, 0x63, 0x0a, 0x88, 0xca, 0x1e, 0xf6, 0x45, 0xe5, 0x59, + 0xa7, 0xcb, 0x02, 0xd8, 0x26, 0x88, 0x2b, 0x19, 0xa1, 0xcc, 0x61, 0xa3, 0xf6, 0xfe, 0xbb, 0x7d, 0x1d, 0xcf, 0xac, + 0xb6, 0x1f, 0xd1, 0x4f, 0xfc, 0x11, 0xf3, 0x6f, 0x17, 0xf6, 0x65, 0x62, 0x9c, 0xbe, 0xce, 0x33, 0xd5, 0x9f, 0xba, + 0x49, 0x5d, 0xf0, 0xac, 0x4e, 0x40, 0x05, 0x09, 0xab, 0xe0, 0x67, 0xb0, 0x67, 0xff, 0xa3, 0xc2, 0xd5, 0x90, 0x4f, + 0xcb, 0x67, 0x67, 0xf6, 0x1a, 0xba, 0x56, 0x50, 0x75, 0xb8, 0x01, 0x22, 0x87, 0xc5, 0xad, 0xea, 0x62, 0xc7, 0x99, + 0xf9, 0x2f, 0x0b, 0xd8, 0xf8, 0x5a, 0x08, 0x4e, 0xd7, 0x1f, 0x5d, 0xbe, 0x44, 0xdb, 0x93, 0xb3, 0x89, 0x19, 0xc6, + 0x97, 0x34, 0xc4, 0x83, 0x7b, 0x4a, 0x87, 0x1f, 0x19, 0x93, 0x4f, 0xf1, 0xc7, 0xa7, 0xfd, 0x64, 0x2e, 0xf9, 0xf1, + 0xe3, 0x5f, 0xfa, 0xab, 0x7e, 0xcd, 0x33, 0xbf, 0x50, 0x67, 0xb2, 0xc3, 0x7b, 0x45, 0xd1, 0xf3, 0x8b, 0xb9, 0x18, + 0x11, 0x5b, 0x31, 0xfe, 0x30, 0x0b, 0x7d, 0xfa, 0xed, 0xed, 0xc3, 0x3d, 0x78, 0x33, 0x28, 0x69, 0xc6, 0x41, 0x9d, + 0x9b, 0xeb, 0x1c, 0x5b, 0x69, 0xca, 0x60, 0x12, 0xec, 0x0d, 0x2c, 0x91, 0x41, 0xda, 0x9d, 0x08, 0x11, 0xa8, 0x0c, + 0x4a, 0x05, 0x43, 0x69, 0x8e, 0xa3, 0xae, 0x83, 0x70, 0x20, 0x28, 0x97, 0x11, 0x5d, 0xd5, 0x2a, 0xce, 0x46, 0x07, + 0x0b, 0x01, 0x67, 0x10, 0x61, 0x08, 0xf0, 0xbd, 0x9a, 0x28, 0x81, 0x29, 0x24, 0x0d, 0x21, 0xfe, 0x54, 0x3a, 0x8e, + 0xa2, 0xb8, 0xae, 0xc2, 0xd7, 0xfb, 0x17, 0xd9, 0x38, 0xf9, 0x28, 0x81, 0xa2, 0xbc, 0x03, 0x81, 0x9a, 0x22, 0x05, + 0x9b, 0x8b, 0xcc, 0xe5, 0x88, 0x85, 0xf3, 0xa1, 0xa0, 0x17, 0x12, 0x56, 0x4b, 0x07, 0x3a, 0x1d, 0x7b, 0x38, 0x24, + 0xb4, 0x2a, 0xd8, 0x84, 0xa1, 0xc9, 0x6d, 0x7e, 0xad, 0x02, 0xca, 0xc9, 0x64, 0x17, 0xb7, 0xc0, 0x37, 0xbf, 0x3e, + 0x47, 0x77, 0x2d, 0x74, 0x9e, 0xf9, 0x9e, 0xf1, 0xf7, 0xef, 0x6f, 0x8e, 0xbf, 0xc2, 0xa3, 0x19, 0xab, 0x26, 0xac, + 0xff, 0xf5, 0x4d, 0x48, 0x08, 0xa5, 0x40, 0x15, 0x01, 0x42, 0xa9, 0xac, 0x81, 0x75, 0x1d, 0x32, 0x73, 0x68, 0xe8, + 0xfa, 0x47, 0x06, 0x39, 0x82, 0x1d, 0x36, 0xf6, 0x6d, 0x58, 0xf8, 0x5a, 0xa9, 0x83, 0xbd, 0x81, 0xa9, 0xb5, 0xb0, + 0x4f, 0x5b, 0xa0, 0xce, 0xe6, 0x9c, 0x39, 0x82, 0xa0, 0x5b, 0x66, 0x66, 0xaa, 0xd2, 0x59, 0x9e, 0x69, 0x7e, 0x46, + 0x7b, 0xc5, 0x7e, 0x5d, 0x02, 0x17, 0x64, 0xe9, 0x6c, 0x6e, 0x6d, 0x45, 0x81, 0xbb, 0x92, 0x2a, 0x9f, 0xb1, 0x75, + 0x3c, 0x04, 0xc2, 0xcf, 0x13, 0x63, 0xbb, 0xc6, 0xe7, 0xc1, 0xd6, 0x27, 0xf9, 0x80, 0x96, 0xae, 0x0f, 0x5d, 0x72, + 0xad, 0x8f, 0x11, 0xcc, 0x88, 0xa9, 0xfc, 0xf0, 0x86, 0xfa, 0x6e, 0x38, 0x70, 0x74, 0x9f, 0xe2, 0xa7, 0x4f, 0x3b, + 0xe9, 0x92, 0x4f, 0x3f, 0xfe, 0x4b, 0x5e, 0xd9, 0x75, 0x08, 0x55, 0x2e, 0x53, 0xf0, 0x63, 0x9f, 0xaf, 0xab, 0xc9, + 0xf6, 0xa6, 0xe2, 0x38, 0x10, 0x3f, 0xaa, 0x34, 0x99, 0xe8, 0x17, 0x77, 0x99, 0xc1, 0xf1, 0x3c, 0x44, 0x56, 0x7b, + 0xe2, 0x5c, 0xd7, 0x93, 0x39, 0x97, 0x6d, 0x70, 0xa1, 0x11, 0x32, 0x75, 0x79, 0xe6, 0x65, 0x9f, 0x13, 0x58, 0xd4, + 0x4c, 0xca, 0xee, 0x6b, 0x8c, 0xc7, 0xd7, 0x96, 0xd3, 0xf4, 0x2c, 0xa4, 0x50, 0x37, 0x1d, 0x2e, 0x68, 0x08, 0x15, + 0xd0, 0xe0, 0xe7, 0x6f, 0x4a, 0xd9, 0x98, 0xb8, 0x19, 0xc9, 0x7f, 0xf0, 0xc8, 0xa4, 0x99, 0x32, 0x1e, 0xe9, 0xb3, + 0x5a, 0xb3, 0x3c, 0xe8, 0x88, 0x2d, 0x65, 0xd9, 0xc7, 0xf8, 0x3a, 0xb5, 0x90, 0xfd, 0x35, 0xfd, 0x3e, 0xdd, 0x62, + 0x94, 0x5a, 0xca, 0x93, 0x8e, 0x84, 0xda, 0xfa, 0xb2, 0x1f, 0x44, 0xa4, 0x2e, 0xf0, 0x50, 0x13, 0xb1, 0x5e, 0xc6, + 0x74, 0x30, 0x98, 0x2a, 0xda, 0x6f, 0x4f, 0x77, 0xab, 0xd3, 0x37, 0x9b, 0x6a, 0x11, 0xe2, 0xfa, 0x40, 0xea, 0x63, + 0x58, 0x4d, 0x94, 0x9d, 0x1d, 0x7a, 0x09, 0x07, 0xc1, 0x03, 0xa3, 0x73, 0x05, 0x37, 0x19, 0x2e, 0x62, 0xd6, 0x99, + 0x07, 0xdc, 0x25, 0xe5, 0x70, 0x82, 0x38, 0xaf, 0xd0, 0xd5, 0xba, 0x0b, 0xe3, 0x5a, 0xbe, 0xc9, 0xbb, 0xd3, 0xa9, + 0xa4, 0x4e, 0x79, 0xb8, 0x01, 0x6d, 0xa4, 0x36, 0xbd, 0x53, 0x6c, 0x1f, 0xb8, 0x55, 0xfb, 0xef, 0x37, 0x20, 0x93, + 0xbd, 0xcf, 0x1f, 0x38, 0xa0, 0x21, 0x08, 0xd9, 0xe3, 0xe5, 0xf8, 0x02, 0x9d, 0x45, 0xdd, 0x5a, 0x77, 0x75, 0xda, + 0x5d, 0x6f, 0xa1, 0x2a, 0xeb, 0x23, 0x2e, 0x98, 0x9c, 0xa1, 0xc3, 0xb6, 0x95, 0x42, 0x3f, 0x86, 0x9e, 0xc4, 0xbc, + 0xbc, 0xb2, 0x36, 0xac, 0x93, 0x13, 0x7b, 0xc1, 0xd5, 0xbe, 0xf9, 0x83, 0xf8, 0x0c, 0x30, 0x8b, 0xb9, 0xe9, 0xcd, + 0xb3, 0xea, 0x0b, 0x31, 0x44, 0xc6, 0x35, 0x1c, 0x61, 0x02, 0x3e, 0xa0, 0xfa, 0x0f, 0x0e, 0x2d, 0x86, 0xab, 0xe3, + 0x52, 0x83, 0xe9, 0xf8, 0xc1, 0x17, 0xd5, 0x11, 0x12, 0xd3, 0x8e, 0xc7, 0x06, 0xac, 0x31, 0xd4, 0xa0, 0x83, 0x5b, + 0xd3, 0x28, 0x40, 0x10, 0xdb, 0xd7, 0xcf, 0x0d, 0x6e, 0xbf, 0x7b, 0xd7, 0xbb, 0x22, 0xe1, 0xdc, 0xbe, 0x6c, 0x80, + 0x39, 0x61, 0x30, 0x3a, 0x9d, 0xad, 0x6b, 0xa2, 0x2f, 0xea, 0xf7, 0x85, 0x2d, 0xf4, 0x40, 0x6e, 0x4c, 0x78, 0x04, + 0x0b, 0x15, 0x77, 0x90, 0x33, 0xa8, 0x80, 0xfb, 0x0b, 0x7a, 0xc0, 0x82, 0x94, 0xf1, 0x89, 0x78, 0x87, 0xd6, 0x31, + 0x42, 0x0d, 0x2c, 0x38, 0x56, 0x1a, 0x86, 0x03, 0x06, 0xc1, 0xf1, 0x59, 0xd6, 0x88, 0xbc, 0x53, 0x23, 0xf8, 0x2b, + 0x1a, 0x45, 0xeb, 0x58, 0x4a, 0x0a, 0x15, 0xac, 0xe9, 0xec, 0x6b, 0x45, 0xc4, 0xab, 0x29, 0xe8, 0x04, 0x18, 0xd2, + 0x9e, 0x38, 0xfb, 0x74, 0x17, 0xc9, 0xa2, 0x7a, 0xcf, 0x2e, 0x12, 0xe1, 0x2e, 0x03, 0x52, 0xc4, 0x81, 0x4f, 0x87, + 0xd5, 0x74, 0x55, 0x6e, 0xee, 0xa1, 0xad, 0xbd, 0x8b, 0x1d, 0x9d, 0x06, 0xc1, 0xe4, 0xd8, 0xb3, 0xe1, 0x46, 0x2f, + 0x0a, 0x0e, 0x5b, 0x49, 0xd9, 0xaf, 0x22, 0x9c, 0x70, 0xeb, 0xb9, 0x16, 0x2a, 0x1d, 0x34, 0x17, 0x7f, 0xba, 0x42, + 0x2f, 0x21, 0xd4, 0xf6, 0x4c, 0x23, 0x4e, 0x2f, 0xc1, 0xd8, 0x6e, 0xfe, 0x53, 0xb7, 0x0c, 0xda, 0xdc, 0xda, 0xbb, + 0xf4, 0xd6, 0x86, 0xb3, 0x49, 0x65, 0x56, 0x0e, 0xba, 0x17, 0xa5, 0xbb, 0x1c, 0xe3, 0x0c, 0x46, 0xf1, 0x49, 0x3e, + 0xd3, 0xaa, 0xf4, 0xd8, 0xef, 0x36, 0x78, 0xc4, 0x3e, 0xda, 0xc6, 0xd8, 0x21, 0x16, 0x58, 0xe4, 0x78, 0x76, 0x02, + 0x35, 0x0e, 0x8d, 0x78, 0x4d, 0x11, 0x5a, 0x52, 0x7b, 0x87, 0x8f, 0x3e, 0xf6, 0xd6, 0xca, 0x77, 0xe4, 0xc5, 0x5a, + 0x04, 0x50, 0x83, 0x9a, 0x56, 0x09, 0xdd, 0xa5, 0x9b, 0x67, 0xbc, 0x06, 0x2c, 0x3a, 0x0a, 0x87, 0x28, 0xdf, 0x39, + 0x57, 0xd0, 0x8e, 0xb6, 0x48, 0x64, 0x1d, 0xa3, 0xa9, 0x14, 0xb9, 0xfe, 0xc3, 0x32, 0x0d, 0x9a, 0x1f, 0xdb, 0x57, + 0x90, 0xbd, 0x39, 0x1f, 0xf3, 0x3f, 0x9e, 0xb3, 0x2f, 0xd9, 0x5e, 0x17, 0x00, 0xae, 0x9f, 0xfd, 0x63, 0x62, 0xf2, + 0x67, 0x16, 0x86, 0xf9, 0x0f, 0xf5, 0x09, 0x6f, 0x02, 0xff, 0x04, 0xcf, 0x59, 0x62, 0xbc, 0x97, 0xe2, 0x3c, 0xc5, + 0x33, 0x97, 0x40, 0x6f, 0x4b, 0xbe, 0x6c, 0x01, 0xbc, 0xb8, 0xd4, 0xbc, 0x5d, 0x70, 0x36, 0x46, 0x14, 0xa8, 0xbe, + 0xd5, 0x93, 0x5c, 0x0e, 0xba, 0x51, 0x8a, 0xb8, 0xe9, 0xb7, 0x0a, 0x34, 0xa3, 0x55, 0x62, 0x76, 0x19, 0x7a, 0xb1, + 0x74, 0x9c, 0xab, 0xf0, 0x33, 0x19, 0x6c, 0x83, 0x7d, 0x22, 0xc2, 0x65, 0xd2, 0x63, 0x84, 0xbf, 0x4d, 0x91, 0x7c, + 0xab, 0xc3, 0xf5, 0x83, 0xc6, 0xbf, 0xee, 0xfd, 0xfa, 0xd5, 0xe3, 0x8b, 0x9b, 0x86, 0xb0, 0x7a, 0xa0, 0x7c, 0x72, + 0xb6, 0xde, 0xed, 0x4c, 0x0f, 0x03, 0xc5, 0x43, 0x61, 0x34, 0x3a, 0xc6, 0x49, 0x61, 0x36, 0x9b, 0x75, 0xfd, 0xd0, + 0xf5, 0x1f, 0x39, 0x1d, 0x48, 0xb0, 0x0c, 0xe5, 0xde, 0x9d, 0x81, 0x79, 0xbd, 0x35, 0x90, 0xb5, 0x5c, 0xe5, 0xc0, + 0x9d, 0x9e, 0xa9, 0xde, 0x8e, 0x14, 0x8e, 0x78, 0xa4, 0x15, 0xee, 0xcc, 0x5e, 0x66, 0x03, 0xba, 0x8b, 0x73, 0x45, + 0x77, 0xce, 0x29, 0x59, 0x44, 0x96, 0x9f, 0xf4, 0x8e, 0xde, 0xec, 0xf8, 0xd8, 0xbd, 0x2b, 0x09, 0x2c, 0xff, 0x6f, + 0xd4, 0xa1, 0x7a, 0x48, 0x8c, 0x14, 0x9e, 0x45, 0xb1, 0xb1, 0x2a, 0x86, 0xef, 0xf0, 0x5b, 0xc9, 0x53, 0xed, 0x15, + 0xc3, 0x02, 0xdf, 0x35, 0xcc, 0xdd, 0x3a, 0x12, 0xbc, 0x4c, 0xc7, 0x80, 0x47, 0x62, 0xc0, 0x6f, 0x36, 0x8f, 0x08, + 0x5d, 0x27, 0x7b, 0x1c, 0x3f, 0x05, 0xe1, 0xc6, 0x15, 0x94, 0x33, 0x23, 0x7c, 0x83, 0x91, 0x83, 0xa7, 0x98, 0x3f, + 0xde, 0xdc, 0x41, 0xf5, 0xf1, 0xc3, 0xbe, 0x58, 0x7b, 0xf0, 0xd7, 0x02, 0xac, 0x81, 0x3c, 0xda, 0x50, 0x3d, 0x4b, + 0xf5, 0xce, 0xfd, 0x35, 0x4f, 0x0b, 0x7e, 0x46, 0x6e, 0x74, 0x5b, 0x9c, 0x23, 0x5f, 0xe2, 0xed, 0xb6, 0x13, 0x6f, + 0x77, 0x7d, 0x6b, 0x7e, 0xd4, 0x08, 0x10, 0x36, 0xbf, 0x2d, 0xdb, 0xfa, 0xc3, 0xc5, 0xed, 0x97, 0xf6, 0xce, 0x60, + 0x07, 0xb8, 0xc4, 0x80, 0x8d, 0xae, 0x8b, 0xd8, 0xe6, 0x8c, 0x1b, 0x63, 0x17, 0x71, 0xd8, 0x00, 0xa4, 0x8a, 0x98, + 0x08, 0x4d, 0xe5, 0x28, 0x04, 0x83, 0xa1, 0x37, 0x7d, 0x1f, 0xef, 0x33, 0x0f, 0xb0, 0x01, 0x9b, 0x4c, 0x6d, 0x42, + 0xd8, 0x98, 0x54, 0xb7, 0x7e, 0x1d, 0xa1, 0x2c, 0xc6, 0xc6, 0xd2, 0x9a, 0x2b, 0x0b, 0x42, 0x9f, 0xb7, 0xfe, 0x56, + 0xc3, 0x36, 0xd7, 0xf8, 0xb7, 0x58, 0x44, 0xfc, 0x98, 0x72, 0xd8, 0x5f, 0xc2, 0xa7, 0x0b, 0xc7, 0xe8, 0xe8, 0x93, + 0xc6, 0x99, 0x71, 0xaa, 0xae, 0x95, 0xfe, 0x56, 0xc6, 0x43, 0x1f, 0xdf, 0xdd, 0x98, 0x2a, 0x3b, 0xf4, 0x12, 0x2c, + 0x3a, 0x0a, 0xe3, 0x21, 0x9e, 0x06, 0x75, 0x1d, 0x47, 0x32, 0x98, 0xba, 0xc7, 0x99, 0xbe, 0xda, 0xce, 0xa2, 0xb8, + 0x8c, 0xd8, 0x79, 0x5f, 0x5a, 0x2d, 0xe3, 0xa0, 0x5a, 0xb8, 0x88, 0x8e, 0x19, 0xd4, 0x22, 0xe2, 0x9d, 0x7a, 0xf1, + 0x24, 0xf9, 0x98, 0xd3, 0x71, 0xa0, 0x74, 0x2d, 0x69, 0x8f, 0x05, 0x34, 0x44, 0x66, 0x14, 0x5e, 0xfa, 0xa9, 0x9b, + 0xfd, 0xd3, 0xf8, 0x7f, 0x5d, 0x6e, 0xb6, 0xdb, 0x63, 0xbb, 0x12, 0x85, 0x39, 0x4d, 0x0e, 0x81, 0xb6, 0xe0, 0x3b, + 0x6e, 0xf5, 0x31, 0x47, 0xc6, 0x78, 0xad, 0x4b, 0xfa, 0xa5, 0xad, 0x3a, 0x8f, 0xda, 0x35, 0x5a, 0xbf, 0xc0, 0x51, + 0x21, 0xb4, 0xd3, 0x6c, 0xb4, 0x8b, 0x0f, 0x7c, 0xde, 0x3c, 0x98, 0x86, 0x26, 0x14, 0x53, 0x4b, 0xf5, 0x90, 0x39, + 0x2a, 0x9f, 0xe3, 0xf4, 0x1e, 0x80, 0x8a, 0x48, 0x7b, 0xf7, 0x7e, 0xa6, 0xde, 0x5f, 0x6b, 0x86, 0xee, 0xa3, 0x56, + 0xca, 0x48, 0xf8, 0x6d, 0x87, 0x90, 0xb0, 0x0a, 0x49, 0x18, 0x3b, 0x27, 0xca, 0x59, 0xd6, 0x36, 0x86, 0x96, 0xf7, + 0x87, 0x83, 0xe7, 0x89, 0x56, 0xcb, 0xb8, 0xc5, 0x23, 0x72, 0xbb, 0xf7, 0x99, 0x48, 0xf5, 0xa2, 0xea, 0xf2, 0x08, + 0x82, 0x45, 0x27, 0x32, 0xd2, 0x5f, 0x8c, 0xda, 0x71, 0x02, 0xfd, 0x7b, 0xf9, 0x53, 0x50, 0x52, 0xd4, 0x0a, 0xa7, + 0x8c, 0x75, 0x13, 0x9d, 0x68, 0x29, 0xc2, 0xc8, 0xa6, 0xaf, 0x82, 0xff, 0x04, 0x37, 0x58, 0x79, 0x77, 0xcf, 0x33, + 0xa2, 0x6a, 0xe1, 0x11, 0x45, 0x32, 0x26, 0xee, 0x7e, 0x0e, 0xb3, 0x84, 0x5e, 0x7a, 0x77, 0xad, 0x75, 0xea, 0x9c, + 0x2e, 0xde, 0x04, 0x51, 0x0a, 0xa2, 0xbb, 0xcf, 0xf1, 0x13, 0xe3, 0x00, 0xe9, 0x06, 0xf8, 0xe7, 0x04, 0xc9, 0x29, + 0x4f, 0x54, 0x5e, 0x06, 0xd3, 0x36, 0xa4, 0x60, 0xf8, 0x58, 0xef, 0xc1, 0x8d, 0x37, 0x7c, 0xb9, 0x9c, 0xfa, 0xe6, + 0xcd, 0x23, 0x57, 0x3d, 0xc4, 0xd3, 0x38, 0xef, 0x6c, 0x5a, 0x26, 0xf8, 0x48, 0x12, 0xff, 0xac, 0x4d, 0xec, 0xb6, + 0x6c, 0xd2, 0xf3, 0xa6, 0xdb, 0xc2, 0xd9, 0xbd, 0x65, 0x0e, 0xb2, 0xd8, 0xf4, 0x05, 0x20, 0xe5, 0x80, 0xd6, 0xc5, + 0x2e, 0x0a, 0x05, 0x71, 0x1a, 0xe0, 0x02, 0x30, 0x42, 0x4b, 0x2c, 0x56, 0xe0, 0x89, 0xc6, 0xd3, 0x2c, 0xa7, 0xc5, + 0x36, 0x78, 0x37, 0x82, 0x67, 0x89, 0x5c, 0x4a, 0xd3, 0x90, 0x36, 0xb5, 0x94, 0xf0, 0xcc, 0xa9, 0xf5, 0x6d, 0x9a, + 0x6e, 0x6a, 0x93, 0xd9, 0x7c, 0xec, 0x8a, 0x15, 0x6d, 0xe8, 0xe0, 0x0e, 0x26, 0xd1, 0x16, 0x42, 0x36, 0x6a, 0x20, + 0xdb, 0xec, 0x4f, 0x59, 0xb2, 0xd3, 0x54, 0xa1, 0x27, 0xb5, 0x6e, 0x89, 0x16, 0x47, 0xa6, 0xde, 0xcd, 0x02, 0x49, + 0xb0, 0x85, 0x86, 0x63, 0x61, 0x45, 0xd3, 0xe3, 0x7b, 0xee, 0xa3, 0x63, 0x60, 0xa1, 0x96, 0x9e, 0xc6, 0x1c, 0xbd, + 0x33, 0x88, 0x69, 0xd6, 0x32, 0xb2, 0x65, 0xe3, 0xf3, 0x1e}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From f084d320fcdd78568e4432e92429b0177c117488 Mon Sep 17 00:00:00 2001 From: Stuart Parmenter Date: Tue, 27 Jan 2026 11:24:13 -0800 Subject: [PATCH 0389/2030] [hub75] Update esp-hub75 to 0.3.2 (#13572) Co-authored-by: Claude --- esphome/components/hub75/display.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 0eeb4bba33..f1e6ef4243 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -587,7 +587,7 @@ def _build_config_struct( async def to_code(config: ConfigType) -> None: add_idf_component( name="esphome/esp-hub75", - ref="0.3.0", + ref="0.3.2", ) # Set compile-time configuration via build flags (so external library sees them) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 9be787d0cd..b4a2c9b909 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -32,7 +32,7 @@ dependencies: rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: - version: 0.3.0 + version: 0.3.2 rules: - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" esp32async/asynctcp: From f9687a2a31befe705f1c4086f0bfbdb8d3479fcb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 15:02:19 -1000 Subject: [PATCH 0390/2030] [web_server_idf] Replace heap-allocated url() with stack-based url_to() (#13407) --- .../captive_portal/captive_portal.cpp | 10 ++++++-- .../prometheus/prometheus_handler.h | 14 ++++++----- .../web_server/ota/ota_web_server.cpp | 11 +++++++-- esphome/components/web_server/web_server.cpp | 18 +++++++++++---- .../web_server_idf/web_server_idf.cpp | 23 ++++++++----------- .../web_server_idf/web_server_idf.h | 17 ++++++++++++-- 6 files changed, 63 insertions(+), 30 deletions(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index bf65ae67c0..8d88a10b27 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -96,10 +96,16 @@ void CaptivePortal::start() { } void CaptivePortal::handleRequest(AsyncWebServerRequest *req) { - if (req->url() == ESPHOME_F("/config.json")) { +#ifdef USE_ESP32 + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + StringRef url = req->url_to(url_buf); +#else + const auto &url = req->url(); +#endif + if (url == ESPHOME_F("/config.json")) { this->handle_config(req); return; - } else if (req->url() == ESPHOME_F("/wifisave")) { + } else if (url == ESPHOME_F("/wifisave")) { this->handle_wifisave(req); return; } diff --git a/esphome/components/prometheus/prometheus_handler.h b/esphome/components/prometheus/prometheus_handler.h index fc48ad67e3..7aecab99d1 100644 --- a/esphome/components/prometheus/prometheus_handler.h +++ b/esphome/components/prometheus/prometheus_handler.h @@ -41,12 +41,14 @@ class PrometheusHandler : public AsyncWebHandler, public Component { void add_label_name(EntityBase *obj, const std::string &value) { relabel_map_name_.insert({obj, value}); } bool canHandle(AsyncWebServerRequest *request) const override { - if (request->method() == HTTP_GET) { - if (request->url() == "/metrics") - return true; - } - - return false; + if (request->method() != HTTP_GET) + return false; +#ifdef USE_ESP32 + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + return request->url_to(url_buf) == "/metrics"; +#else + return request->url() == ESPHOME_F("/metrics"); +#endif } void handleRequest(AsyncWebServerRequest *req) override; diff --git a/esphome/components/web_server/ota/ota_web_server.cpp b/esphome/components/web_server/ota/ota_web_server.cpp index 3793f01eb5..4be162ccd3 100644 --- a/esphome/components/web_server/ota/ota_web_server.cpp +++ b/esphome/components/web_server/ota/ota_web_server.cpp @@ -32,8 +32,15 @@ class OTARequestHandler : public AsyncWebHandler { void handleUpload(AsyncWebServerRequest *request, const PlatformString &filename, size_t index, uint8_t *data, size_t len, bool final) override; bool canHandle(AsyncWebServerRequest *request) const override { - // Check if this is an OTA update request - bool is_ota_request = request->url() == "/update" && request->method() == HTTP_POST; + if (request->method() != HTTP_POST) + return false; + // Check if this is an OTA update request +#ifdef USE_ESP32 + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + bool is_ota_request = request->url_to(url_buf) == "/update"; +#else + bool is_ota_request = request->url() == ESPHOME_F("/update"); +#endif #if defined(USE_WEBSERVER_OTA_DISABLED) && defined(USE_CAPTIVE_PORTAL) // IMPORTANT: USE_WEBSERVER_OTA_DISABLED only disables OTA for the web_server component diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index a19c1c9b17..d30cb524f4 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -2187,7 +2187,12 @@ std::string WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_ #endif bool WebServer::canHandle(AsyncWebServerRequest *request) const { +#ifdef USE_ESP32 + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + StringRef url = request->url_to(url_buf); +#else const auto &url = request->url(); +#endif const auto method = request->method(); // Static URL checks - use ESPHOME_F to keep strings in flash on ESP8266 @@ -2323,30 +2328,35 @@ bool WebServer::canHandle(AsyncWebServerRequest *request) const { return false; } void WebServer::handleRequest(AsyncWebServerRequest *request) { +#ifdef USE_ESP32 + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + StringRef url = request->url_to(url_buf); +#else const auto &url = request->url(); +#endif // Handle static routes first - if (url == "/") { + if (url == ESPHOME_F("/")) { this->handle_index_request(request); return; } #if !defined(USE_ESP32) && defined(USE_ARDUINO) - if (url == "/events") { + if (url == ESPHOME_F("/events")) { this->events_.add_new_client(this, request); return; } #endif #ifdef USE_WEBSERVER_CSS_INCLUDE - if (url == "/0.css") { + if (url == ESPHOME_F("/0.css")) { this->handle_css_request(request); return; } #endif #ifdef USE_WEBSERVER_JS_INCLUDE - if (url == "/0.js") { + if (url == ESPHOME_F("/0.js")) { this->handle_js_request(request); return; } diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index abeda5fc46..2e5a74cbef 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -246,21 +246,16 @@ optional AsyncWebServerRequest::get_header(const char *name) const return request_get_header(*this, name); } -std::string AsyncWebServerRequest::url() const { - auto *query_start = strchr(this->req_->uri, '?'); - std::string result; - if (query_start == nullptr) { - result = this->req_->uri; - } else { - result = std::string(this->req_->uri, query_start - this->req_->uri); - } +StringRef AsyncWebServerRequest::url_to(std::span buffer) const { + const char *uri = this->req_->uri; + const char *query_start = strchr(uri, '?'); + size_t uri_len = query_start ? static_cast(query_start - uri) : strlen(uri); + size_t copy_len = std::min(uri_len, URL_BUF_SIZE - 1); + memcpy(buffer.data(), uri, copy_len); + buffer[copy_len] = '\0'; // Decode URL-encoded characters in-place (e.g., %20 -> space) - // This matches AsyncWebServer behavior on Arduino - if (!result.empty()) { - size_t new_len = url_decode(&result[0]); - result.resize(new_len); - } - return result; + size_t decoded_len = url_decode(buffer.data()); + return StringRef(buffer.data(), decoded_len); } std::string AsyncWebServerRequest::host() const { return this->get_header("Host").value(); } diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index a6c984792a..e38913ef4a 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -3,12 +3,14 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" +#include "esphome/core/string_ref.h" #include #include #include #include #include +#include #include #include #include @@ -110,7 +112,15 @@ class AsyncWebServerRequest { ~AsyncWebServerRequest(); http_method method() const { return static_cast(this->req_->method); } - std::string url() const; + static constexpr size_t URL_BUF_SIZE = CONFIG_HTTPD_MAX_URI_LEN + 1; ///< Buffer size for url_to() + /// Write URL (without query string) to buffer, returns StringRef pointing to buffer. + /// URL is decoded (e.g., %20 -> space). + StringRef url_to(std::span buffer) const; + /// Get URL as std::string. Prefer url_to() to avoid heap allocation. + std::string url() const { + char buffer[URL_BUF_SIZE]; + return std::string(this->url_to(buffer)); + } std::string host() const; // NOLINTNEXTLINE(readability-identifier-naming) size_t contentLength() const { return this->req_->content_len; } @@ -306,7 +316,10 @@ class AsyncEventSource : public AsyncWebHandler { // NOLINTNEXTLINE(readability-identifier-naming) bool canHandle(AsyncWebServerRequest *request) const override { - return request->method() == HTTP_GET && request->url() == this->url_; + if (request->method() != HTTP_GET) + return false; + char url_buf[AsyncWebServerRequest::URL_BUF_SIZE]; + return request->url_to(url_buf) == this->url_; } // NOLINTNEXTLINE(readability-identifier-naming) void handleRequest(AsyncWebServerRequest *request) override; From f87aa384d02bebfba7d20fb5b56aa2ddab9906b1 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 28 Jan 2026 03:31:00 +0100 Subject: [PATCH 0391/2030] [nextion] Fix alternative code path for `dump_device_info` (#13566) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 15 ++++++--------- tests/components/nextion/common.yaml | 10 ++++++---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 4bba33f961..e57a258edb 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -150,27 +150,24 @@ void Nextion::dump_config() { #ifdef USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE ESP_LOGCONFIG(TAG, " Skip handshake: YES"); #else // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE - ESP_LOGCONFIG(TAG, #ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO + ESP_LOGCONFIG(TAG, " Device Model: %s\n" " FW Version: %s\n" " Serial Number: %s\n" " Flash Size: %s\n" " Max queue age: %u ms\n" " Startup override: %u ms\n", + this->device_model_.c_str(), this->firmware_version_.c_str(), this->serial_number_.c_str(), + this->flash_size_.c_str(), this->max_q_age_ms_, this->startup_override_ms_); #endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO #ifdef USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START - " Exit reparse: YES\n" + ESP_LOGCONFIG(TAG, " Exit reparse: YES\n"); #endif // USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START + ESP_LOGCONFIG(TAG, " Wake On Touch: %s\n" " Touch Timeout: %" PRIu16, -#ifdef USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - this->device_model_.c_str(), this->firmware_version_.c_str(), this->serial_number_.c_str(), - this->flash_size_.c_str(), this->max_q_age_ms_, - this->startup_override_ms_ -#endif // USE_NEXTION_CONFIG_DUMP_DEVICE_INFO - YESNO(this->connection_state_.auto_wake_on_touch_), - this->touch_sleep_timeout_); + YESNO(this->connection_state_.auto_wake_on_touch_), this->touch_sleep_timeout_); #endif // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP diff --git a/tests/components/nextion/common.yaml b/tests/components/nextion/common.yaml index 48a7292f43..4373fe5462 100644 --- a/tests/components/nextion/common.yaml +++ b/tests/components/nextion/common.yaml @@ -273,12 +273,9 @@ text_sensor: display: - platform: nextion id: main_lcd - update_interval: 5s - command_spacing: 5ms max_commands_per_loop: 20 max_queue_size: 50 - startup_override_ms: 10000ms # Wait 10s for display ready - max_queue_age: 5000ms # Remove queue items after 5s + update_interval: 5s on_sleep: then: lambda: 'ESP_LOGD("display","Display went to sleep");' @@ -294,3 +291,8 @@ display: on_buffer_overflow: then: logger.log: "Nextion reported a buffer overflow!" + + command_spacing: 5ms + dump_device_info: true + max_queue_age: 5000ms # Remove queue items after 5s + startup_override_ms: 10000ms # Wait 10s for display ready From f73c539ea7942d9f609bf5975423940e2895bb23 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 17:18:31 -1000 Subject: [PATCH 0392/2030] [web_server] Add RP2040 platform support (#13576) --- .clang-tidy.hash | 2 +- esphome/components/async_tcp/__init__.py | 6 ++++-- esphome/components/async_tcp/async_tcp.h | 4 ++-- esphome/components/web_server/__init__.py | 2 ++ esphome/components/web_server_base/__init__.py | 5 +++++ platformio.ini | 1 + tests/components/web_server/test.rp2040-ard.yaml | 1 + 7 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 tests/components/web_server/test.rp2040-ard.yaml diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 55239f961c..a1dcdf5799 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -a172e2f65981e98354cc6b5ecf69bdb055dd13602226042ab2c7acd037a2bf41 +08c21fa4c044fd80c8f3296371f30c4f5ff3418f1bc1efe63c5bad938301f122 diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index 1ff4805f03..2a07903b68 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -38,8 +38,10 @@ async def to_code(config): # https://github.com/ESP32Async/ESPAsyncTCP cg.add_library("ESP32Async/ESPAsyncTCP", "2.0.0") elif CORE.is_rp2040: - # https://github.com/khoih-prog/AsyncTCP_RP2040W - cg.add_library("khoih-prog/AsyncTCP_RP2040W", "1.2.0") + # https://github.com/ayushsharma82/RPAsyncTCP + # RPAsyncTCP is a drop-in replacement for AsyncTCP_RP2040W with better + # ESPAsyncWebServer compatibility + cg.add_library("ayushsharma82/RPAsyncTCP", "1.3.2") # Other platforms (host, etc) use socket-based implementation diff --git a/esphome/components/async_tcp/async_tcp.h b/esphome/components/async_tcp/async_tcp.h index 6d9211f023..21fcfe239f 100644 --- a/esphome/components/async_tcp/async_tcp.h +++ b/esphome/components/async_tcp/async_tcp.h @@ -8,8 +8,8 @@ // Use ESPAsyncTCP library for ESP8266 (always Arduino) #include #elif defined(USE_RP2040) -// Use AsyncTCP_RP2040W library for RP2040 -#include +// Use RPAsyncTCP library for RP2040 +#include #else // Use socket-based implementation for other platforms #include "async_tcp_socket.h" diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 3f1e094afc..8b02a6baee 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -31,6 +31,7 @@ from esphome.const import ( PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_LN882X, + PLATFORM_RP2040, PLATFORM_RTL87XX, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority @@ -213,6 +214,7 @@ CONFIG_SCHEMA = cv.All( PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_LN882X, + PLATFORM_RP2040, PLATFORM_RTL87XX, ] ), diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index e0eec7dedb..6c756575d4 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -47,5 +47,10 @@ async def to_code(config): cg.add_library("ESP8266WiFi", None) if CORE.is_libretiny: CORE.add_platformio_option("lib_ignore", ["ESPAsyncTCP", "RPAsyncTCP"]) + if CORE.is_rp2040: + # Ignore bundled AsyncTCP libraries - we use RPAsyncTCP from async_tcp component + CORE.add_platformio_option( + "lib_ignore", ["ESPAsyncTCP", "AsyncTCP", "AsyncTCP_RP2040W"] + ) # https://github.com/ESP32Async/ESPAsyncWebServer/blob/main/library.json cg.add_library("ESP32Async/ESPAsyncWebServer", "3.9.5") diff --git a/platformio.ini b/platformio.ini index accc40ecf2..c5a6768ad2 100644 --- a/platformio.ini +++ b/platformio.ini @@ -200,6 +200,7 @@ platform_packages = framework = arduino lib_deps = ${common:arduino.lib_deps} + ayushsharma82/RPAsyncTCP@1.3.2 ; async_tcp bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base build_flags = diff --git a/tests/components/web_server/test.rp2040-ard.yaml b/tests/components/web_server/test.rp2040-ard.yaml new file mode 100644 index 0000000000..7e6658e20e --- /dev/null +++ b/tests/components/web_server/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common_v2.yaml From fe6f27c5261ad26f67438a357670697c3490b7ef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 17:33:46 -1000 Subject: [PATCH 0393/2030] [text_sensor] Use in-place mutation for filters to reduce heap allocations (#13475) --- esphome/components/text_sensor/filter.cpp | 50 ++++++++++++----------- esphome/components/text_sensor/filter.h | 43 ++++++++++--------- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/esphome/components/text_sensor/filter.cpp b/esphome/components/text_sensor/filter.cpp index 4cace372ae..4ee12e8602 100644 --- a/esphome/components/text_sensor/filter.cpp +++ b/esphome/components/text_sensor/filter.cpp @@ -9,19 +9,18 @@ namespace text_sensor { static const char *const TAG = "text_sensor.filter"; // Filter -void Filter::input(const std::string &value) { +void Filter::input(std::string value) { ESP_LOGVV(TAG, "Filter(%p)::input(%s)", this, value.c_str()); - optional out = this->new_value(value); - if (out.has_value()) - this->output(*out); + if (this->new_value(value)) + this->output(value); } -void Filter::output(const std::string &value) { +void Filter::output(std::string &value) { if (this->next_ == nullptr) { ESP_LOGVV(TAG, "Filter(%p)::output(%s) -> SENSOR", this, value.c_str()); this->parent_->internal_send_state_to_frontend(value); } else { ESP_LOGVV(TAG, "Filter(%p)::output(%s) -> %p", this, value.c_str(), this->next_); - this->next_->input(value); + this->next_->input(std::move(value)); } } void Filter::initialize(TextSensor *parent, Filter *next) { @@ -35,43 +34,48 @@ LambdaFilter::LambdaFilter(lambda_filter_t lambda_filter) : lambda_filter_(std:: const lambda_filter_t &LambdaFilter::get_lambda_filter() const { return this->lambda_filter_; } void LambdaFilter::set_lambda_filter(const lambda_filter_t &lambda_filter) { this->lambda_filter_ = lambda_filter; } -optional LambdaFilter::new_value(std::string value) { - auto it = this->lambda_filter_(value); - ESP_LOGVV(TAG, "LambdaFilter(%p)::new_value(%s) -> %s", this, value.c_str(), it.value_or("").c_str()); - return it; +bool LambdaFilter::new_value(std::string &value) { + auto result = this->lambda_filter_(value); + if (result.has_value()) { + ESP_LOGVV(TAG, "LambdaFilter(%p)::new_value(%s) -> %s (continue)", this, value.c_str(), result->c_str()); + value = std::move(*result); + return true; + } + ESP_LOGVV(TAG, "LambdaFilter(%p)::new_value(%s) -> (stop)", this, value.c_str()); + return false; } // ToUpperFilter -optional ToUpperFilter::new_value(std::string value) { +bool ToUpperFilter::new_value(std::string &value) { for (char &c : value) c = ::toupper(c); - return value; + return true; } // ToLowerFilter -optional ToLowerFilter::new_value(std::string value) { +bool ToLowerFilter::new_value(std::string &value) { for (char &c : value) c = ::tolower(c); - return value; + return true; } // Append -optional AppendFilter::new_value(std::string value) { +bool AppendFilter::new_value(std::string &value) { value.append(this->suffix_); - return value; + return true; } // Prepend -optional PrependFilter::new_value(std::string value) { +bool PrependFilter::new_value(std::string &value) { value.insert(0, this->prefix_); - return value; + return true; } // Substitute SubstituteFilter::SubstituteFilter(const std::initializer_list &substitutions) : substitutions_(substitutions) {} -optional SubstituteFilter::new_value(std::string value) { +bool SubstituteFilter::new_value(std::string &value) { for (const auto &sub : this->substitutions_) { // Compute lengths once per substitution (strlen is fast, called infrequently) const size_t from_len = strlen(sub.from); @@ -84,20 +88,20 @@ optional SubstituteFilter::new_value(std::string value) { pos += to_len; } } - return value; + return true; } // Map MapFilter::MapFilter(const std::initializer_list &mappings) : mappings_(mappings) {} -optional MapFilter::new_value(std::string value) { +bool MapFilter::new_value(std::string &value) { for (const auto &mapping : this->mappings_) { if (value == mapping.from) { value.assign(mapping.to); - return value; + return true; } } - return value; // Pass through if no match + return true; // Pass through if no match } } // namespace text_sensor diff --git a/esphome/components/text_sensor/filter.h b/esphome/components/text_sensor/filter.h index 0f66b753b4..1922b503ca 100644 --- a/esphome/components/text_sensor/filter.h +++ b/esphome/components/text_sensor/filter.h @@ -17,21 +17,20 @@ class Filter { public: /** This will be called every time the filter receives a new value. * - * It can return an empty optional to indicate that the filter chain - * should stop, otherwise the value in the filter will be passed down - * the chain. + * Modify the value in place. Return false to stop the filter chain + * (value will not be published), or true to continue. * - * @param value The new value. - * @return An optional string, the new value that should be pushed out. + * @param value The value to filter (modified in place). + * @return True to continue the filter chain, false to stop. */ - virtual optional new_value(std::string value) = 0; + virtual bool new_value(std::string &value) = 0; /// Initialize this filter, please note this can be called more than once. virtual void initialize(TextSensor *parent, Filter *next); - void input(const std::string &value); + void input(std::string value); - void output(const std::string &value); + void output(std::string &value); protected: friend TextSensor; @@ -45,15 +44,14 @@ using lambda_filter_t = std::function(std::string)>; /** This class allows for creation of simple template filters. * * The constructor accepts a lambda of the form std::string -> optional. - * It will be called with each new value in the filter chain and returns the modified - * value that shall be passed down the filter chain. Returning an empty Optional - * means that the value shall be discarded. + * Return a modified string to continue the chain, or return {} to stop + * (value will not be published). */ class LambdaFilter : public Filter { public: explicit LambdaFilter(lambda_filter_t lambda_filter); - optional new_value(std::string value) override; + bool new_value(std::string &value) override; const lambda_filter_t &get_lambda_filter() const; void set_lambda_filter(const lambda_filter_t &lambda_filter); @@ -71,7 +69,14 @@ class StatelessLambdaFilter : public Filter { public: explicit StatelessLambdaFilter(optional (*lambda_filter)(std::string)) : lambda_filter_(lambda_filter) {} - optional new_value(std::string value) override { return this->lambda_filter_(value); } + bool new_value(std::string &value) override { + auto result = this->lambda_filter_(value); + if (result.has_value()) { + value = std::move(*result); + return true; + } + return false; + } protected: optional (*lambda_filter_)(std::string); @@ -80,20 +85,20 @@ class StatelessLambdaFilter : public Filter { /// A simple filter that converts all text to uppercase class ToUpperFilter : public Filter { public: - optional new_value(std::string value) override; + bool new_value(std::string &value) override; }; /// A simple filter that converts all text to lowercase class ToLowerFilter : public Filter { public: - optional new_value(std::string value) override; + bool new_value(std::string &value) override; }; /// A simple filter that adds a string to the end of another string class AppendFilter : public Filter { public: explicit AppendFilter(const char *suffix) : suffix_(suffix) {} - optional new_value(std::string value) override; + bool new_value(std::string &value) override; protected: const char *suffix_; @@ -103,7 +108,7 @@ class AppendFilter : public Filter { class PrependFilter : public Filter { public: explicit PrependFilter(const char *prefix) : prefix_(prefix) {} - optional new_value(std::string value) override; + bool new_value(std::string &value) override; protected: const char *prefix_; @@ -118,7 +123,7 @@ struct Substitution { class SubstituteFilter : public Filter { public: explicit SubstituteFilter(const std::initializer_list &substitutions); - optional new_value(std::string value) override; + bool new_value(std::string &value) override; protected: FixedVector substitutions_; @@ -151,7 +156,7 @@ class SubstituteFilter : public Filter { class MapFilter : public Filter { public: explicit MapFilter(const std::initializer_list &mappings); - optional new_value(std::string value) override; + bool new_value(std::string &value) override; protected: FixedVector mappings_; From 73a249c0753c39dce3aed103cd19d951c45cd63f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 18:02:01 -1000 Subject: [PATCH 0394/2030] [esp32] Default to CMN certificate bundle, saving ~51KB flash (#13574) --- esphome/components/esp32/__init__.py | 29 +++++++++++++++++++++ esphome/components/esp32/const.py | 1 + esphome/components/http_request/__init__.py | 10 +++++++ tests/components/esp32/test.esp32-idf.yaml | 1 + 4 files changed, 41 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b7faccaed6..fccf0ed09f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -55,6 +55,7 @@ from .const import ( # noqa KEY_ESP32, KEY_EXTRA_BUILD_FILES, KEY_FLASH_SIZE, + KEY_FULL_CERT_BUNDLE, KEY_PATH, KEY_REF, KEY_REPO, @@ -670,6 +671,7 @@ CONF_FREERTOS_IN_IRAM = "freertos_in_iram" CONF_RINGBUF_IN_IRAM = "ringbuf_in_iram" CONF_HEAP_IN_IRAM = "heap_in_iram" CONF_LOOP_TASK_STACK_SIZE = "loop_task_stack_size" +CONF_USE_FULL_CERTIFICATE_BUNDLE = "use_full_certificate_bundle" # VFS requirement tracking # Components that need VFS features can call require_vfs_select() or require_vfs_dir() @@ -695,6 +697,18 @@ def require_vfs_dir() -> None: CORE.data[KEY_VFS_DIR_REQUIRED] = True +def require_full_certificate_bundle() -> None: + """Request the full certificate bundle instead of the common-CAs-only bundle. + + By default, ESPHome uses CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN which + includes only CAs with >1% market share (~51 KB smaller than full bundle). + This covers ~99% of websites including Let's Encrypt, DigiCert, Google, Amazon. + + Call this from components that need to connect to services using uncommon CAs. + """ + CORE.data[KEY_ESP32][KEY_FULL_CERT_BUNDLE] = True + + def _parse_idf_component(value: str) -> ConfigType: """Parse IDF component shorthand syntax like 'owner/component^version'""" # Match operator followed by version-like string (digit or *) @@ -776,6 +790,9 @@ FRAMEWORK_SCHEMA = cv.Schema( min=8192, max=32768 ), cv.Optional(CONF_ENABLE_OTA_ROLLBACK, default=True): cv.boolean, + cv.Optional( + CONF_USE_FULL_CERTIFICATE_BUNDLE, default=False + ): cv.boolean, } ), cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list( @@ -1093,6 +1110,18 @@ async def to_code(config): cg.add_build_flag("-Wno-nonnull-compare") + # Use CMN (common CAs) bundle by default to save ~51KB flash + # CMN covers CAs with >1% market share (~99% of websites) + # Components needing uncommon CAs can call require_full_certificate_bundle() + use_full_bundle = conf[CONF_ADVANCED].get( + CONF_USE_FULL_CERTIFICATE_BUNDLE, False + ) or CORE.data[KEY_ESP32].get(KEY_FULL_CERT_BUNDLE, False) + add_idf_sdkconfig_option( + "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL", use_full_bundle + ) + if not use_full_bundle: + add_idf_sdkconfig_option("CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN", True) + add_idf_sdkconfig_option(f"CONFIG_IDF_TARGET_{variant}", True) add_idf_sdkconfig_option( f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index 2a9456db23..9f8165818b 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -12,6 +12,7 @@ KEY_REFRESH = "refresh" KEY_PATH = "path" KEY_SUBMODULES = "submodules" KEY_EXTRA_BUILD_FILES = "extra_build_files" +KEY_FULL_CERT_BUNDLE = "full_cert_bundle" VARIANT_ESP32 = "ESP32" VARIANT_ESP32C2 = "ESP32C2" diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 7347b8ebf7..07bc758037 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -165,6 +165,16 @@ async def to_code(config): ca_cert_content = f.read() cg.add(var.set_ca_certificate(ca_cert_content)) else: + # Uses the certificate bundle configured in esp32 component. + # By default, ESPHome uses the CMN (common CAs) bundle which covers + # ~99% of websites including GitHub, Let's Encrypt, DigiCert, etc. + # If connecting to services with uncommon CAs, components can call: + # esp32.require_full_certificate_bundle() + # Or users can set in their config: + # esp32: + # framework: + # advanced: + # use_full_certificate_bundle: true esp32.add_idf_sdkconfig_option( "CONFIG_MBEDTLS_CERTIFICATE_BUNDLE", True ) diff --git a/tests/components/esp32/test.esp32-idf.yaml b/tests/components/esp32/test.esp32-idf.yaml index 0e220623a1..d38cdfe2fd 100644 --- a/tests/components/esp32/test.esp32-idf.yaml +++ b/tests/components/esp32/test.esp32-idf.yaml @@ -7,6 +7,7 @@ esp32: enable_lwip_mdns_queries: true enable_lwip_bridge_interface: true disable_libc_locks_in_iram: false # Test explicit opt-out of RAM optimization + use_full_certificate_bundle: false # Test CMN bundle (default) wifi: ssid: MySSID From ded835ab63a3a7abf7a68bde0d618cd9254732a4 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 28 Jan 2026 05:51:18 +0100 Subject: [PATCH 0395/2030] [nrf52] Move toolchain to platform (#13498) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .clang-tidy.hash | 2 +- esphome/components/nrf52/__init__.py | 23 ++++++++++++++----- platformio.ini | 5 ++-- .../components/nrf52/test.nrf52-adafruit.yaml | 2 +- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index a1dcdf5799..1cb5f98c28 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -08c21fa4c044fd80c8f3296371f30c4f5ff3418f1bc1efe63c5bad938301f122 +cf3d341206b4184ec8b7fe85141aef4fe4696aa720c3f8a06d4e57930574bdab diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 5fb8abddfc..7d3d59f0ad 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -69,9 +69,21 @@ def set_core_data(config: ConfigType) -> ConfigType: def set_framework(config: ConfigType) -> ConfigType: - version = cv.Version.parse(cv.version_number(config[CONF_FRAMEWORK][CONF_VERSION])) - CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = version - return config + framework_ver = cv.Version.parse( + cv.version_number(config[CONF_FRAMEWORK][CONF_VERSION]) + ) + CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = framework_ver + if framework_ver < cv.Version(2, 9, 2): + return cv.require_framework_version( + nrf52_zephyr=cv.Version(2, 6, 1, "a"), + )(config) + if framework_ver < cv.Version(3, 2, 0): + return cv.require_framework_version( + nrf52_zephyr=cv.Version(2, 9, 2, "2"), + )(config) + return cv.require_framework_version( + nrf52_zephyr=cv.Version(3, 2, 0, "1"), + )(config) BOOTLOADERS = [ @@ -140,7 +152,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean, } ), - cv.Optional(CONF_FRAMEWORK, default={CONF_VERSION: "2.6.1-7"}): cv.Schema( + cv.Optional(CONF_FRAMEWORK, default={CONF_VERSION: "2.6.1-a"}): cv.Schema( { cv.Required(CONF_VERSION): cv.string_strict, } @@ -181,13 +193,12 @@ async def to_code(config: ConfigType) -> None: cg.add_platformio_option(CONF_FRAMEWORK, CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK]) cg.add_platformio_option( "platform", - "https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-1.zip", + "https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-5.zip", ) cg.add_platformio_option( "platform_packages", [ f"platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v{CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}.zip", - "platformio/toolchain-gccarmnoneeabi@https://github.com/tomaszduda23/toolchain-sdk-ng/archive/refs/tags/v0.17.4-0.zip", ], ) diff --git a/platformio.ini b/platformio.ini index c5a6768ad2..0f5bf2f8fb 100644 --- a/platformio.ini +++ b/platformio.ini @@ -230,11 +230,10 @@ build_src_flags = -include Arduino.h ; This is the common settings for the nRF52 using Zephyr. [common:nrf52-zephyr] extends = common -platform = https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-1.zip +platform = https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-5.zip framework = zephyr platform_packages = - platformio/framework-zephyr @ https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v2.6.1-7.zip - platformio/toolchain-gccarmnoneeabi@https://github.com/tomaszduda23/toolchain-sdk-ng/archive/refs/tags/v0.17.4-0.zip + platformio/framework-zephyr @ https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v2.6.1-a.zip build_flags = ${common.build_flags} -DUSE_ZEPHYR diff --git a/tests/components/nrf52/test.nrf52-adafruit.yaml b/tests/components/nrf52/test.nrf52-adafruit.yaml index 0ad31993ae..300cb7b5d7 100644 --- a/tests/components/nrf52/test.nrf52-adafruit.yaml +++ b/tests/components/nrf52/test.nrf52-adafruit.yaml @@ -20,4 +20,4 @@ nrf52: voltage: 2.1V uicr_erase: true framework: - version: "2.6.1-7" + version: "2.6.1-a" From b4f63fd992b1fb77a2bdc09b71034dcfd021ba81 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 19:11:30 -1000 Subject: [PATCH 0396/2030] [core] Add LOG_ENTITY_ICON/DEVICE_CLASS/UNIT_OF_MEASUREMENT macros (#13578) --- .../components/binary_sensor/binary_sensor.cpp | 5 +---- esphome/components/button/button.cpp | 5 +---- esphome/components/cover/cover.h | 4 +--- esphome/components/datetime/date_entity.h | 4 +--- esphome/components/datetime/datetime_entity.h | 4 +--- esphome/components/datetime/time_entity.h | 4 +--- esphome/components/event/event.h | 8 ++------ esphome/components/lock/lock.h | 4 +--- esphome/components/number/number.cpp | 15 +++------------ esphome/components/select/select.h | 4 +--- esphome/components/sensor/sensor.cpp | 9 ++------- esphome/components/switch/switch.cpp | 8 ++------ esphome/components/text/text.h | 4 +--- esphome/components/text_sensor/text_sensor.cpp | 10 ++-------- esphome/components/valve/valve.h | 4 +--- esphome/core/entity_base.cpp | 18 ++++++++++++++++++ esphome/core/entity_base.h | 10 ++++++++++ 17 files changed, 49 insertions(+), 71 deletions(-) diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index 4fe2a019e0..7c3b06970d 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -14,10 +14,7 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi } ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); - - if (!obj->get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); - } + LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj); } void BinarySensor::publish_state(bool new_state) { diff --git a/esphome/components/button/button.cpp b/esphome/components/button/button.cpp index 87a222776e..8c06cfe59b 100644 --- a/esphome/components/button/button.cpp +++ b/esphome/components/button/button.cpp @@ -12,10 +12,7 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o } ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); - - if (!obj->get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str()); - } + LOG_ENTITY_ICON(tag, prefix, *obj); } void Button::press() { diff --git a/esphome/components/cover/cover.h b/esphome/components/cover/cover.h index e710915a0e..e5427ceaa8 100644 --- a/esphome/components/cover/cover.h +++ b/esphome/components/cover/cover.h @@ -20,9 +20,7 @@ const extern float COVER_CLOSED; if (traits_.get_is_assumed_state()) { \ ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \ } \ - if (!(obj)->get_device_class_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ - } \ + LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \ } class Cover; diff --git a/esphome/components/datetime/date_entity.h b/esphome/components/datetime/date_entity.h index 955fd92c45..cbf2b85506 100644 --- a/esphome/components/datetime/date_entity.h +++ b/esphome/components/datetime/date_entity.h @@ -15,9 +15,7 @@ namespace esphome::datetime { #define LOG_DATETIME_DATE(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ } class DateCall; diff --git a/esphome/components/datetime/datetime_entity.h b/esphome/components/datetime/datetime_entity.h index b5b8cd677e..b1b8a77846 100644 --- a/esphome/components/datetime/datetime_entity.h +++ b/esphome/components/datetime/datetime_entity.h @@ -15,9 +15,7 @@ namespace esphome::datetime { #define LOG_DATETIME_DATETIME(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ } class DateTimeCall; diff --git a/esphome/components/datetime/time_entity.h b/esphome/components/datetime/time_entity.h index e4bb113eb5..3f224684bb 100644 --- a/esphome/components/datetime/time_entity.h +++ b/esphome/components/datetime/time_entity.h @@ -15,9 +15,7 @@ namespace esphome::datetime { #define LOG_DATETIME_TIME(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ } class TimeCall; diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index b5519a0520..a7451407bb 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -16,12 +16,8 @@ namespace event { #define LOG_EVENT(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ - if (!(obj)->get_device_class_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ + LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \ } class Event : public EntityBase, public EntityBase_DeviceClass { diff --git a/esphome/components/lock/lock.h b/esphome/components/lock/lock.h index b518c8b846..69fc405713 100644 --- a/esphome/components/lock/lock.h +++ b/esphome/components/lock/lock.h @@ -14,9 +14,7 @@ class Lock; #define LOG_LOCK(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ if ((obj)->traits.get_assumed_state()) { \ ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \ } \ diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index b0af604189..1c4126496c 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -14,18 +14,9 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o } ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); - - if (!obj->get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str()); - } - - if (!obj->traits.get_unit_of_measurement_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Unit of Measurement: '%s'", prefix, obj->traits.get_unit_of_measurement_ref().c_str()); - } - - if (!obj->traits.get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->traits.get_device_class_ref().c_str()); - } + LOG_ENTITY_ICON(tag, prefix, *obj); + LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, obj->traits); + LOG_ENTITY_DEVICE_CLASS(tag, prefix, obj->traits); } void Number::publish_state(float state) { diff --git a/esphome/components/select/select.h b/esphome/components/select/select.h index 8b05487704..c91acd1e19 100644 --- a/esphome/components/select/select.h +++ b/esphome/components/select/select.h @@ -12,9 +12,7 @@ namespace esphome::select { #define LOG_SELECT(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ } #define SUB_SELECT(name) \ diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index 9fdb7bbafd..3f2be02af2 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -22,13 +22,8 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o LOG_STR_ARG(state_class_to_string(obj->get_state_class())), prefix, obj->get_unit_of_measurement_ref().c_str(), prefix, obj->get_accuracy_decimals()); - if (!obj->get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); - } - - if (!obj->get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str()); - } + LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj); + LOG_ENTITY_ICON(tag, prefix, *obj); if (obj->get_force_update()) { ESP_LOGV(tag, "%s Force Update: YES", prefix); diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index d880139c5f..61a273d25c 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -96,18 +96,14 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o LOG_STR_ARG(onoff)); // Add optional fields separately - if (!obj->get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str()); - } + LOG_ENTITY_ICON(tag, prefix, *obj); if (obj->assumed_state()) { ESP_LOGCONFIG(tag, "%s Assumed State: YES", prefix); } if (obj->is_inverted()) { ESP_LOGCONFIG(tag, "%s Inverted: YES", prefix); } - if (!obj->get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); - } + LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj); } } diff --git a/esphome/components/text/text.h b/esphome/components/text/text.h index e4ad64334b..3a1bea56cb 100644 --- a/esphome/components/text/text.h +++ b/esphome/components/text/text.h @@ -12,9 +12,7 @@ namespace text { #define LOG_TEXT(prefix, type, obj) \ if ((obj) != nullptr) { \ ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \ - if (!(obj)->get_icon_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Icon: '%s'", prefix, (obj)->get_icon_ref().c_str()); \ - } \ + LOG_ENTITY_ICON(TAG, prefix, *(obj)); \ } /** Base-class for all text inputs. diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 86e2387dc7..c48bdf4b82 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -15,14 +15,8 @@ void log_text_sensor(const char *tag, const char *prefix, const char *type, Text } ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); - - if (!obj->get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj->get_device_class_ref().c_str()); - } - - if (!obj->get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj->get_icon_ref().c_str()); - } + LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj); + LOG_ENTITY_ICON(tag, prefix, *obj); } void TextSensor::publish_state(const std::string &state) { this->publish_state(state.data(), state.size()); } diff --git a/esphome/components/valve/valve.h b/esphome/components/valve/valve.h index 2b3419b67a..cd46144372 100644 --- a/esphome/components/valve/valve.h +++ b/esphome/components/valve/valve.h @@ -20,9 +20,7 @@ const extern float VALVE_CLOSED; if (traits_.get_is_assumed_state()) { \ ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \ } \ - if (!(obj)->get_device_class_ref().empty()) { \ - ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, (obj)->get_device_class_ref().c_str()); \ - } \ + LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \ } class Valve; diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 7d7878f53a..811b856b5e 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -152,4 +152,22 @@ void EntityBase_UnitOfMeasurement::set_unit_of_measurement(const char *unit_of_m this->unit_of_measurement_ = unit_of_measurement; } +void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) { + if (!obj.get_icon_ref().empty()) { + ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj.get_icon_ref().c_str()); + } +} + +void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj) { + if (!obj.get_device_class_ref().empty()) { + ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj.get_device_class_ref().c_str()); + } +} + +void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase_UnitOfMeasurement &obj) { + if (!obj.get_unit_of_measurement_ref().empty()) { + ESP_LOGCONFIG(tag, "%s Unit of Measurement: '%s'", prefix, obj.get_unit_of_measurement_ref().c_str()); + } +} + } // namespace esphome diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 0b75b25817..86cb75495b 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -230,6 +230,16 @@ class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming) const char *unit_of_measurement_{nullptr}; ///< Unit of measurement override }; +/// Log entity icon if set (for use in dump_config) +#define LOG_ENTITY_ICON(tag, prefix, obj) log_entity_icon(tag, prefix, obj) +void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj); +/// Log entity device class if set (for use in dump_config) +#define LOG_ENTITY_DEVICE_CLASS(tag, prefix, obj) log_entity_device_class(tag, prefix, obj) +void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj); +/// Log entity unit of measurement if set (for use in dump_config) +#define LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, obj) log_entity_unit_of_measurement(tag, prefix, obj) +void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase_UnitOfMeasurement &obj); + /** * An entity that has a state. * @tparam T The type of the state From 22e0a8ce2e330af01e4fe6c06c03794b7d2a91e4 Mon Sep 17 00:00:00 2001 From: Hypothalamus Date: Wed, 28 Jan 2026 07:10:49 +0100 Subject: [PATCH 0397/2030] [hub75] Add Huidu HD-WF1 board configuration (#13341) --- esphome/components/hub75/boards/huidu.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/esphome/components/hub75/boards/huidu.py b/esphome/components/hub75/boards/huidu.py index 52744d397e..c4e4c3c135 100644 --- a/esphome/components/hub75/boards/huidu.py +++ b/esphome/components/hub75/boards/huidu.py @@ -2,6 +2,25 @@ from . import BoardConfig +# Huidu HD-WF1 +BoardConfig( + "huidu-hd-wf1", + r1_pin=2, + g1_pin=6, + b1_pin=3, + r2_pin=4, + g2_pin=8, + b2_pin=5, + a_pin=39, + b_pin=38, + c_pin=37, + d_pin=36, + e_pin=12, + lat_pin=33, + oe_pin=35, + clk_pin=34, +) + # Huidu HD-WF2 BoardConfig( "huidu-hd-wf2", From 10dfd95ff20e0d334fbcd8f7c31163a35f316c44 Mon Sep 17 00:00:00 2001 From: Dan Schafer Date: Wed, 28 Jan 2026 06:50:19 -0800 Subject: [PATCH 0398/2030] [esp32] Add pin definitions for adafruit_feather_esp32s3_reversetft (#13273) --- esphome/components/esp32/boards.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 8a7a9428db..8b066064f2 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -175,6 +175,32 @@ ESP32_BOARD_PINS = { "LED": 13, "LED_BUILTIN": 13, }, + "adafruit_feather_esp32s3_reversetft": { + "BUTTON": 0, + "A0": 18, + "A1": 17, + "A2": 16, + "A3": 15, + "A4": 14, + "A5": 8, + "SCK": 36, + "MOSI": 35, + "MISO": 37, + "RX": 38, + "TX": 39, + "SCL": 4, + "SDA": 3, + "NEOPIXEL": 33, + "PIN_NEOPIXEL": 33, + "NEOPIXEL_POWER": 21, + "TFT_I2C_POWER": 7, + "TFT_CS": 42, + "TFT_DC": 40, + "TFT_RESET": 41, + "TFT_BACKLIGHT": 45, + "LED": 13, + "LED_BUILTIN": 13, + }, "adafruit_feather_esp32s3_tft": { "BUTTON": 0, "A0": 18, From 051604f284b57cd9017468403dcadc9f17cbc1ea Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 05:37:05 -1000 Subject: [PATCH 0399/2030] [wifi] Filter scan results to only store matching networks (#13409) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/wifi/wifi_component.cpp | 124 ++++++++++++++---- esphome/components/wifi/wifi_component.h | 18 ++- .../wifi/wifi_component_esp8266.cpp | 29 +++- .../wifi/wifi_component_esp_idf.cpp | 37 ++++-- .../wifi/wifi_component_libretiny.cpp | 41 ++++-- .../components/wifi/wifi_component_pico_w.cpp | 20 ++- 6 files changed, 211 insertions(+), 58 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index ec9978da79..65c653a62a 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -39,6 +39,10 @@ #include "esphome/components/esp32_improv/esp32_improv_component.h" #endif +#ifdef USE_IMPROV_SERIAL +#include "esphome/components/improv_serial/improv_serial_component.h" +#endif + namespace esphome::wifi { static const char *const TAG = "wifi"; @@ -365,6 +369,75 @@ bool WiFiComponent::ssid_was_seen_in_scan_(const std::string &ssid) const { return false; } +bool WiFiComponent::needs_full_scan_results_() const { + // Components that require full scan results (for example, scan result listeners) + // are expected to call request_wifi_scan_results(), which sets keep_scan_results_. + if (this->keep_scan_results_) { + return true; + } + +#ifdef USE_CAPTIVE_PORTAL + // Captive portal needs full results when active (showing network list to user) + if (captive_portal::global_captive_portal != nullptr && captive_portal::global_captive_portal->is_active()) { + return true; + } +#endif + +#ifdef USE_IMPROV_SERIAL + // Improv serial needs results during provisioning (before connected) + if (improv_serial::global_improv_serial_component != nullptr && !this->is_connected()) { + return true; + } +#endif + +#ifdef USE_IMPROV + // BLE improv also needs results during provisioning + if (esp32_improv::global_improv_component != nullptr && esp32_improv::global_improv_component->is_active()) { + return true; + } +#endif + + return false; +} + +bool WiFiComponent::matches_configured_network_(const char *ssid, const uint8_t *bssid) const { + // Hidden networks in scan results have empty SSIDs - skip them + if (ssid[0] == '\0') { + return false; + } + for (const auto &sta : this->sta_) { + // Skip hidden network configs (they don't appear in normal scans) + if (sta.get_hidden()) { + continue; + } + // For BSSID-only configs (empty SSID), match by BSSID + if (sta.get_ssid().empty()) { + if (sta.has_bssid() && std::memcmp(sta.get_bssid().data(), bssid, 6) == 0) { + return true; + } + continue; + } + // Match by SSID + if (sta.get_ssid() == ssid) { + return true; + } + } + return false; +} + +void WiFiComponent::log_discarded_scan_result_(const char *ssid, const uint8_t *bssid, int8_t rssi, uint8_t channel) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + // Skip logging during roaming scans to avoid log buffer overflow + // (roaming scans typically find many networks but only care about same-SSID APs) + if (this->roaming_state_ == RoamingState::SCANNING) { + return; + } + char bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(bssid, bssid_s); + ESP_LOGV(TAG, "- " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") " %ddB Ch:%u", ssid, bssid_s, rssi, channel); +#endif +} + int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) { // Find next SSID to try in RETRY_HIDDEN phase. // @@ -656,8 +729,12 @@ void WiFiComponent::loop() { ESP_LOGI(TAG, "Starting fallback AP"); this->setup_ap_config_(); #ifdef USE_CAPTIVE_PORTAL - if (captive_portal::global_captive_portal != nullptr) + if (captive_portal::global_captive_portal != nullptr) { + // Reset so we force one full scan after captive portal starts + // (previous scans were filtered because captive portal wasn't active yet) + this->has_completed_scan_after_captive_portal_start_ = false; captive_portal::global_captive_portal->start(); + } #endif } } @@ -1195,7 +1272,7 @@ template static void insertion_sort_scan_results(VectorType // has overhead from UART transmission, so combining INFO+DEBUG into one line halves // the blocking time. Do NOT split this into separate ESP_LOGI/ESP_LOGD calls. __attribute__((noinline)) static void log_scan_result(const WiFiScanResult &res) { - char bssid_s[18]; + char bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; auto bssid = res.get_bssid(); format_mac_addr_upper(bssid.data(), bssid_s); @@ -1211,18 +1288,6 @@ __attribute__((noinline)) static void log_scan_result(const WiFiScanResult &res) #endif } -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE -// Helper function to log non-matching scan results at verbose level -__attribute__((noinline)) static void log_scan_result_non_matching(const WiFiScanResult &res) { - char bssid_s[18]; - auto bssid = res.get_bssid(); - format_mac_addr_upper(bssid.data(), bssid_s); - - ESP_LOGV(TAG, "- " LOG_SECRET("'%s'") " " LOG_SECRET("(%s) ") "%s", res.get_ssid().c_str(), bssid_s, - LOG_STR_ARG(get_signal_bars(res.get_rssi()))); -} -#endif - void WiFiComponent::check_scanning_finished() { if (!this->scan_done_) { if (millis() - this->action_started_ > WIFI_SCAN_TIMEOUT_MS) { @@ -1232,6 +1297,8 @@ void WiFiComponent::check_scanning_finished() { return; } this->scan_done_ = false; + this->has_completed_scan_after_captive_portal_start_ = + true; // Track that we've done a scan since captive portal started this->retry_hidden_mode_ = RetryHiddenMode::SCAN_BASED; if (this->scan_result_.empty()) { @@ -1259,21 +1326,12 @@ void WiFiComponent::check_scanning_finished() { // Sort scan results using insertion sort for better memory efficiency insertion_sort_scan_results(this->scan_result_); - size_t non_matching_count = 0; + // Log matching networks (non-matching already logged at VERBOSE in scan callback) for (auto &res : this->scan_result_) { if (res.get_matches()) { log_scan_result(res); - } else { -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE - log_scan_result_non_matching(res); -#else - non_matching_count++; -#endif } } - if (non_matching_count > 0) { - ESP_LOGD(TAG, "- %zu non-matching (VERBOSE to show)", non_matching_count); - } // SYNCHRONIZATION POINT: Establish link between scan_result_[0] and selected_sta_index_ // After sorting, scan_result_[0] contains the best network. Now find which sta_[i] config @@ -1532,7 +1590,10 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() { if (this->went_through_explicit_hidden_phase_()) { return WiFiRetryPhase::EXPLICIT_HIDDEN; } - // Skip scanning when captive portal/improv is active to avoid disrupting AP. + // Skip scanning when captive portal/improv is active to avoid disrupting AP, + // BUT only if we've already completed at least one scan AFTER the portal started. + // When captive portal first starts, scan results may be filtered/stale, so we need + // to do one full scan to populate available networks for the captive portal UI. // // WHY SCANNING DISRUPTS AP MODE: // WiFi scanning requires the radio to leave the AP's channel and hop through @@ -1549,7 +1610,16 @@ WiFiRetryPhase WiFiComponent::determine_next_phase_() { // // This allows users to configure WiFi via captive portal while the device keeps // attempting to connect to all configured networks in sequence. - if (this->is_captive_portal_active_() || this->is_esp32_improv_active_()) { + // Captive portal needs scan results to show available networks. + // If captive portal is active, only skip scanning if we've done a scan after it started. + // If only improv is active (no captive portal), skip scanning since improv doesn't need results. + if (this->is_captive_portal_active_()) { + if (this->has_completed_scan_after_captive_portal_start_) { + return WiFiRetryPhase::RETRY_HIDDEN; + } + // Need to scan for captive portal + } else if (this->is_esp32_improv_active_()) { + // Improv doesn't need scan results return WiFiRetryPhase::RETRY_HIDDEN; } return WiFiRetryPhase::SCAN_CONNECTING; @@ -2096,7 +2166,7 @@ void WiFiComponent::clear_roaming_state_() { void WiFiComponent::release_scan_results_() { if (!this->keep_scan_results_) { -#ifdef USE_RP2040 +#if defined(USE_RP2040) || defined(USE_ESP32) // std::vector - use swap trick since shrink_to_fit is non-binding decltype(this->scan_result_)().swap(this->scan_result_); #else diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index dfc91fb5da..f27c522a1b 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -161,9 +161,12 @@ struct EAPAuth { using bssid_t = std::array; -// Use std::vector for RP2040 since scan count is unknown (callback-based) -// Use FixedVector for other platforms where count is queried first -#ifdef USE_RP2040 +/// Initial reserve size for filtered scan results (typical: 1-3 matching networks per SSID) +static constexpr size_t WIFI_SCAN_RESULT_FILTERED_RESERVE = 8; + +// Use std::vector for RP2040 (callback-based) and ESP32 (destructive scan API) +// Use FixedVector for ESP8266 and LibreTiny where two-pass exact allocation is possible +#if defined(USE_RP2040) || defined(USE_ESP32) template using wifi_scan_vector_t = std::vector; #else template using wifi_scan_vector_t = FixedVector; @@ -539,6 +542,13 @@ class WiFiComponent : public Component { /// Check if an SSID was seen in the most recent scan results /// Used to skip hidden mode for SSIDs we know are visible bool ssid_was_seen_in_scan_(const std::string &ssid) const; + /// Check if full scan results are needed (captive portal active, improv, listeners) + bool needs_full_scan_results_() const; + /// Check if network matches any configured network (for scan result filtering) + /// Matches by SSID when configured, or by BSSID for BSSID-only configs + bool matches_configured_network_(const char *ssid, const uint8_t *bssid) const; + /// Log a discarded scan result at VERBOSE level (skipped during roaming scans to avoid log overflow) + void log_discarded_scan_result_(const char *ssid, const uint8_t *bssid, int8_t rssi, uint8_t channel); /// Find next SSID that wasn't in scan results (might be hidden) /// Returns index of next potentially hidden SSID, or -1 if none found /// @param start_index Start searching from index after this (-1 to start from beginning) @@ -710,6 +720,8 @@ class WiFiComponent : public Component { bool enable_on_boot_{true}; bool got_ipv4_address_{false}; bool keep_scan_results_{false}; + bool has_completed_scan_after_captive_portal_start_{ + false}; // Tracks if we've completed a scan after captive portal started RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; bool skip_cooldown_next_cycle_{false}; bool post_connect_roaming_{true}; // Enabled by default diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 91db7ae0eb..be54038af8 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -760,20 +760,35 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { return; } - // Count the number of results first auto *head = reinterpret_cast(arg); + bool needs_full = this->needs_full_scan_results_(); + + // First pass: count matching networks (linked list is non-destructive) + size_t total = 0; size_t count = 0; for (bss_info *it = head; it != nullptr; it = STAILQ_NEXT(it, next)) { - count++; + total++; + const char *ssid_cstr = reinterpret_cast(it->ssid); + if (needs_full || this->matches_configured_network_(ssid_cstr, it->bssid)) { + count++; + } } - this->scan_result_.init(count); + this->scan_result_.init(count); // Exact allocation + + // Second pass: store matching networks for (bss_info *it = head; it != nullptr; it = STAILQ_NEXT(it, next)) { - this->scan_result_.emplace_back( - bssid_t{it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]}, - std::string(reinterpret_cast(it->ssid), it->ssid_len), it->channel, it->rssi, it->authmode != AUTH_OPEN, - it->is_hidden != 0); + const char *ssid_cstr = reinterpret_cast(it->ssid); + if (needs_full || this->matches_configured_network_(ssid_cstr, it->bssid)) { + this->scan_result_.emplace_back( + bssid_t{it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]}, + std::string(ssid_cstr, it->ssid_len), it->channel, it->rssi, it->authmode != AUTH_OPEN, it->is_hidden != 0); + } else { + this->log_discarded_scan_result_(ssid_cstr, it->bssid, it->rssi, it->channel); + } } + ESP_LOGV(TAG, "Scan complete: %zu found, %zu stored%s", total, this->scan_result_.size(), + needs_full ? "" : " (filtered)"); this->scan_done_ = true; #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : global_wifi_component->scan_results_listeners_) { diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 15fd407e3c..a32232a758 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -828,11 +828,21 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } uint16_t number = it.number; - scan_result_.init(number); + bool needs_full = this->needs_full_scan_results_(); + + // Smart reserve: full capacity if needed, small reserve otherwise + if (needs_full) { + this->scan_result_.reserve(number); + } else { + this->scan_result_.reserve(WIFI_SCAN_RESULT_FILTERED_RESERVE); + } + #ifdef USE_ESP32_HOSTED // getting records one at a time fails on P4 with hosted esp32 WiFi coprocessor // Presumably an upstream bug, work-around by getting all records at once - auto records = std::make_unique(number); + // Use stack buffer (3904 bytes / ~80 bytes per record = ~48 records) with heap fallback + static constexpr size_t SCAN_RECORD_STACK_COUNT = 3904 / sizeof(wifi_ap_record_t); + SmallBufferWithHeapFallback records(number); err = esp_wifi_scan_get_ap_records(&number, records.get()); if (err != ESP_OK) { esp_wifi_clear_ap_list(); @@ -840,7 +850,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { return; } for (uint16_t i = 0; i < number; i++) { - wifi_ap_record_t &record = records[i]; + wifi_ap_record_t &record = records.get()[i]; #else // Process one record at a time to avoid large buffer allocation for (uint16_t i = 0; i < number; i++) { @@ -852,12 +862,23 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { break; } #endif // USE_ESP32_HOSTED - bssid_t bssid; - std::copy(record.bssid, record.bssid + 6, bssid.begin()); - std::string ssid(reinterpret_cast(record.ssid)); - scan_result_.emplace_back(bssid, ssid, record.primary, record.rssi, record.authmode != WIFI_AUTH_OPEN, - ssid.empty()); + + // Check C string first - avoid std::string construction for non-matching networks + const char *ssid_cstr = reinterpret_cast(record.ssid); + + // Only construct std::string and store if needed + if (needs_full || this->matches_configured_network_(ssid_cstr, record.bssid)) { + bssid_t bssid; + std::copy(record.bssid, record.bssid + 6, bssid.begin()); + std::string ssid(ssid_cstr); + this->scan_result_.emplace_back(bssid, std::move(ssid), record.primary, record.rssi, + record.authmode != WIFI_AUTH_OPEN, ssid_cstr[0] == '\0'); + } else { + this->log_discarded_scan_result_(ssid_cstr, record.bssid, record.rssi, record.primary); + } } + ESP_LOGV(TAG, "Scan complete: %u found, %zu stored%s", number, this->scan_result_.size(), + needs_full ? "" : " (filtered)"); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { listener->on_wifi_scan_results(this->scan_result_); diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 20cd32fa8f..af2b82c3c6 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -670,18 +670,39 @@ void WiFiComponent::wifi_scan_done_callback_() { if (num < 0) return; - this->scan_result_.init(static_cast(num)); - for (int i = 0; i < num; i++) { - String ssid = WiFi.SSID(i); - wifi_auth_mode_t authmode = WiFi.encryptionType(i); - int32_t rssi = WiFi.RSSI(i); - uint8_t *bssid = WiFi.BSSID(i); - int32_t channel = WiFi.channel(i); + bool needs_full = this->needs_full_scan_results_(); - this->scan_result_.emplace_back(bssid_t{bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]}, - std::string(ssid.c_str()), channel, rssi, authmode != WIFI_AUTH_OPEN, - ssid.length() == 0); + // Access scan results directly via WiFi.scan struct to avoid Arduino String allocations + // WiFi.scan is public in LibreTiny for WiFiEvents & WiFiScan static handlers + auto *scan = WiFi.scan; + + // First pass: count matching networks + size_t count = 0; + for (int i = 0; i < num; i++) { + const char *ssid_cstr = scan->ap[i].ssid; + if (needs_full || this->matches_configured_network_(ssid_cstr, scan->ap[i].bssid.addr)) { + count++; + } } + + this->scan_result_.init(count); // Exact allocation + + // Second pass: store matching networks + for (int i = 0; i < num; i++) { + const char *ssid_cstr = scan->ap[i].ssid; + if (needs_full || this->matches_configured_network_(ssid_cstr, scan->ap[i].bssid.addr)) { + auto &ap = scan->ap[i]; + this->scan_result_.emplace_back(bssid_t{ap.bssid.addr[0], ap.bssid.addr[1], ap.bssid.addr[2], ap.bssid.addr[3], + ap.bssid.addr[4], ap.bssid.addr[5]}, + std::string(ssid_cstr), ap.channel, ap.rssi, ap.auth != WIFI_AUTH_OPEN, + ssid_cstr[0] == '\0'); + } else { + auto &ap = scan->ap[i]; + this->log_discarded_scan_result_(ssid_cstr, ap.bssid.addr, ap.rssi, ap.channel); + } + } + ESP_LOGV(TAG, "Scan complete: %d found, %zu stored%s", num, this->scan_result_.size(), + needs_full ? "" : " (filtered)"); WiFi.scanDelete(); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 29ac096d94..84c10d5d43 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -21,6 +21,7 @@ static const char *const TAG = "wifi_pico_w"; // Track previous state for detecting changes static bool s_sta_was_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static bool s_sta_had_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static size_t s_scan_result_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) bool WiFiComponent::wifi_mode_(optional sta, optional ap) { if (sta.has_value()) { @@ -137,10 +138,20 @@ int WiFiComponent::s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *r } void WiFiComponent::wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result) { + s_scan_result_count++; + const char *ssid_cstr = reinterpret_cast(result->ssid); + + // Skip networks that don't match any configured network (unless full results needed) + if (!this->needs_full_scan_results_() && !this->matches_configured_network_(ssid_cstr, result->bssid)) { + this->log_discarded_scan_result_(ssid_cstr, result->bssid, result->rssi, result->channel); + return; + } + bssid_t bssid; std::copy(result->bssid, result->bssid + 6, bssid.begin()); - std::string ssid(reinterpret_cast(result->ssid)); - WiFiScanResult res(bssid, ssid, result->channel, result->rssi, result->auth_mode != CYW43_AUTH_OPEN, ssid.empty()); + std::string ssid(ssid_cstr); + WiFiScanResult res(bssid, std::move(ssid), result->channel, result->rssi, result->auth_mode != CYW43_AUTH_OPEN, + ssid_cstr[0] == '\0'); if (std::find(this->scan_result_.begin(), this->scan_result_.end(), res) == this->scan_result_.end()) { this->scan_result_.push_back(res); } @@ -149,6 +160,7 @@ void WiFiComponent::wifi_scan_result(void *env, const cyw43_ev_scan_result_t *re bool WiFiComponent::wifi_scan_start_(bool passive) { this->scan_result_.clear(); this->scan_done_ = false; + s_scan_result_count = 0; cyw43_wifi_scan_options_t scan_options = {0}; scan_options.scan_type = passive ? 1 : 0; int err = cyw43_wifi_scan(&cyw43_state, &scan_options, nullptr, &s_wifi_scan_result); @@ -244,7 +256,9 @@ void WiFiComponent::wifi_loop_() { // Handle scan completion if (this->state_ == WIFI_COMPONENT_STATE_STA_SCANNING && !cyw43_wifi_scan_active(&cyw43_state)) { this->scan_done_ = true; - ESP_LOGV(TAG, "Scan done"); + bool needs_full = this->needs_full_scan_results_(); + ESP_LOGV(TAG, "Scan complete: %zu found, %zu stored%s", s_scan_result_count, this->scan_result_.size(), + needs_full ? "" : " (filtered)"); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS for (auto *listener : this->scan_results_listeners_) { listener->on_wifi_scan_results(this->scan_result_); From 3bd6ec4ec73484bdbcecac24b33e05198ef6ab9d Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 28 Jan 2026 16:51:17 +0100 Subject: [PATCH 0400/2030] [nrf52,zigbee] Time synchronization (#12236) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/time/real_time_clock.cpp | 3 + esphome/components/zigbee/__init__.py | 2 +- esphome/components/zigbee/time/__init__.py | 86 ++++++++++++++++++ .../zigbee/time/zigbee_time_zephyr.cpp | 87 +++++++++++++++++++ .../zigbee/time/zigbee_time_zephyr.h | 38 ++++++++ .../zigbee/zigbee_binary_sensor_zephyr.cpp | 2 +- .../zigbee/zigbee_sensor_zephyr.cpp | 2 +- .../zigbee/zigbee_switch_zephyr.cpp | 7 +- esphome/components/zigbee/zigbee_zephyr.cpp | 10 +-- esphome/components/zigbee/zigbee_zephyr.h | 4 +- esphome/components/zigbee/zigbee_zephyr.py | 8 +- esphome/core/helpers.h | 1 - tests/components/zigbee/common.yaml | 9 +- 13 files changed, 238 insertions(+), 21 deletions(-) create mode 100644 esphome/components/zigbee/time/__init__.py create mode 100644 esphome/components/zigbee/time/zigbee_time_zephyr.cpp create mode 100644 esphome/components/zigbee/time/zigbee_time_zephyr.h diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index f53a0a7cf7..8a78186178 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -27,6 +27,9 @@ void RealTimeClock::dump_config() { #ifdef USE_TIME_TIMEZONE ESP_LOGCONFIG(TAG, "Timezone: '%s'", this->timezone_.c_str()); #endif + auto time = this->now(); + ESP_LOGCONFIG(TAG, "Current time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, + time.minute, time.second); } void RealTimeClock::synchronize_epoch_(uint32_t epoch) { diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 2281dd38a9..8179220507 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -120,7 +120,7 @@ async def setup_switch(entity: cg.MockObj, config: ConfigType) -> None: def consume_endpoint(config: ConfigType) -> ConfigType: if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): return config - if " " in config[CONF_NAME]: + if CONF_NAME in config and " " in config[CONF_NAME]: _LOGGER.warning( "Spaces in '%s' work with ZHA but not Zigbee2MQTT. For Zigbee2MQTT use '%s'", config[CONF_NAME], diff --git a/esphome/components/zigbee/time/__init__.py b/esphome/components/zigbee/time/__init__.py new file mode 100644 index 0000000000..82f94c8372 --- /dev/null +++ b/esphome/components/zigbee/time/__init__.py @@ -0,0 +1,86 @@ +import esphome.codegen as cg +from esphome.components import time as time_ +import esphome.config_validation as cv +from esphome.const import CONF_ID +from esphome.core import CORE +from esphome.types import ConfigType + +from .. import consume_endpoint +from ..const_zephyr import CONF_ZIGBEE_ID, zigbee_ns +from ..zigbee_zephyr import ( + ZigbeeClusterDesc, + ZigbeeComponent, + get_slot_index, + zigbee_new_attr_list, + zigbee_new_cluster_list, + zigbee_new_variable, + zigbee_register_ep, +) + +DEPENDENCIES = ["zigbee"] + +ZigbeeTime = zigbee_ns.class_("ZigbeeTime", time_.RealTimeClock) + +CONFIG_SCHEMA = cv.All( + time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ZigbeeTime), + cv.OnlyWith(CONF_ZIGBEE_ID, ["nrf52", "zigbee"]): cv.use_id( + ZigbeeComponent + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(cv.polling_component_schema("1s")), + consume_endpoint, +) + + +async def to_code(config: ConfigType) -> None: + CORE.add_job(_add_time, config) + + +async def _add_time(config: ConfigType) -> None: + slot_index = get_slot_index() + + # Create unique names for this sensor's variables based on slot index + prefix = f"zigbee_ep{slot_index + 1}" + attrs_name = f"{prefix}_time_attrs" + attr_list_name = f"{prefix}_time_attrib_list" + cluster_list_name = f"{prefix}_cluster_list" + ep_name = f"{prefix}_ep" + + # Create the binary attributes structure + time_attrs = zigbee_new_variable(attrs_name, "zb_zcl_time_attrs_t") + attr_list = zigbee_new_attr_list( + attr_list_name, + "ZB_ZCL_DECLARE_TIME_ATTR_LIST", + str(time_attrs), + ) + + # Create cluster list and register endpoint + cluster_list_name, clusters = zigbee_new_cluster_list( + cluster_list_name, + [ + ZigbeeClusterDesc("ZB_ZCL_CLUSTER_ID_TIME", attr_list), + ZigbeeClusterDesc("ZB_ZCL_CLUSTER_ID_TIME"), + ], + ) + zigbee_register_ep( + ep_name, + cluster_list_name, + 0, + clusters, + slot_index, + "ZB_HA_CUSTOM_ATTR_DEVICE_ID", + ) + + # Create the ZigbeeTime component + var = cg.new_Pvariable(config[CONF_ID]) + await time_.register_time(var, config) + await cg.register_component(var, config) + + cg.add(var.set_endpoint(slot_index + 1)) + cg.add(var.set_cluster_attributes(time_attrs)) + hub = await cg.get_variable(config[CONF_ZIGBEE_ID]) + cg.add(var.set_parent(hub)) diff --git a/esphome/components/zigbee/time/zigbee_time_zephyr.cpp b/esphome/components/zigbee/time/zigbee_time_zephyr.cpp new file mode 100644 index 0000000000..70ceb60abe --- /dev/null +++ b/esphome/components/zigbee/time/zigbee_time_zephyr.cpp @@ -0,0 +1,87 @@ +#include "zigbee_time_zephyr.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_TIME) +#include "esphome/core/log.h" + +namespace esphome::zigbee { + +static const char *const TAG = "zigbee.time"; + +// This time standard is the number of +// seconds since 0 hrs 0 mins 0 sec on 1st January 2000 UTC (Universal Coordinated Time). +constexpr time_t EPOCH_2000 = 946684800; + +ZigbeeTime *global_time = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +void ZigbeeTime::sync_time(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t short_addr, zb_uint8_t endpoint, + zb_uint32_t nw_time) { + if (status == RET_OK && auth_level >= ZB_ZCL_TIME_HAS_SYNCHRONIZED_BIT) { + global_time->set_epoch_time(nw_time + EPOCH_2000); + } else if (status != RET_TIMEOUT || !global_time->has_time_) { + ESP_LOGE(TAG, "Status: %d, auth_level: %u, short_addr: %d, endpoint: %d, nw_time: %u", status, auth_level, + short_addr, endpoint, nw_time); + } +} + +void ZigbeeTime::setup() { + global_time = this; + this->parent_->add_callback(this->endpoint_, [this](zb_bufid_t bufid) { this->zcl_device_cb_(bufid); }); + synchronize_epoch_(EPOCH_2000); + this->parent_->add_join_callback([this]() { zb_zcl_time_server_synchronize(this->endpoint_, sync_time); }); +} + +void ZigbeeTime::dump_config() { + ESP_LOGCONFIG(TAG, + "Zigbee Time\n" + " Endpoint: %d", + this->endpoint_); + RealTimeClock::dump_config(); +} + +void ZigbeeTime::update() { + time_t time = timestamp_now(); + this->cluster_attributes_->time = time - EPOCH_2000; +} + +void ZigbeeTime::set_epoch_time(uint32_t epoch) { + this->defer([this, epoch]() { + this->synchronize_epoch_(epoch); + this->has_time_ = true; + }); +} + +void ZigbeeTime::zcl_device_cb_(zb_bufid_t bufid) { + zb_zcl_device_callback_param_t *p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); + zb_zcl_device_callback_id_t device_cb_id = p_device_cb_param->device_cb_id; + zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; + zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; + + switch (device_cb_id) { + /* ZCL set attribute value */ + case ZB_ZCL_SET_ATTR_VALUE_CB_ID: + if (cluster_id == ZB_ZCL_CLUSTER_ID_TIME) { + if (attr_id == ZB_ZCL_ATTR_TIME_TIME_ID) { + zb_uint32_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data32; + ESP_LOGI(TAG, "Synchronize time to %u", value); + this->defer([this, value]() { synchronize_epoch_(value + EPOCH_2000); }); + } else if (attr_id == ZB_ZCL_ATTR_TIME_TIME_STATUS_ID) { + zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8; + ESP_LOGI(TAG, "Time status %hd", value); + this->defer([this, value]() { this->has_time_ = ZB_ZCL_TIME_TIME_STATUS_SYNCHRONIZED_BIT_IS_SET(value); }); + } + } else { + /* other clusters attribute handled here */ + ESP_LOGI(TAG, "Unhandled cluster attribute id: %d", cluster_id); + p_device_cb_param->status = RET_NOT_IMPLEMENTED; + } + break; + default: + p_device_cb_param->status = RET_NOT_IMPLEMENTED; + break; + } + + ESP_LOGD(TAG, "Zcl_device_cb_ status: %hd", p_device_cb_param->status); +} + +} // namespace esphome::zigbee + +#endif diff --git a/esphome/components/zigbee/time/zigbee_time_zephyr.h b/esphome/components/zigbee/time/zigbee_time_zephyr.h new file mode 100644 index 0000000000..3c2adc4b5f --- /dev/null +++ b/esphome/components/zigbee/time/zigbee_time_zephyr.h @@ -0,0 +1,38 @@ +#pragma once +#include "esphome/core/defines.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_TIME) +#include "esphome/core/component.h" +#include "esphome/components/time/real_time_clock.h" +#include "esphome/components/zigbee/zigbee_zephyr.h" + +extern "C" { +#include +#include +} + +namespace esphome::zigbee { + +class ZigbeeTime : public time::RealTimeClock, public ZigbeeEntity { + public: + void setup() override; + void dump_config() override; + void update() override; + + void set_cluster_attributes(zb_zcl_time_attrs_t &cluster_attributes) { + this->cluster_attributes_ = &cluster_attributes; + } + + void set_epoch_time(uint32_t epoch); + + protected: + static void sync_time(zb_ret_t status, zb_uint32_t auth_level, zb_uint16_t short_addr, zb_uint8_t endpoint, + zb_uint32_t nw_time); + void zcl_device_cb_(zb_bufid_t bufid); + zb_zcl_time_attrs_t *cluster_attributes_{nullptr}; + + bool has_time_{false}; +}; + +} // namespace esphome::zigbee + +#endif diff --git a/esphome/components/zigbee/zigbee_binary_sensor_zephyr.cpp b/esphome/components/zigbee/zigbee_binary_sensor_zephyr.cpp index 8b7aff70a8..464cc04d62 100644 --- a/esphome/components/zigbee/zigbee_binary_sensor_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_binary_sensor_zephyr.cpp @@ -22,7 +22,7 @@ void ZigbeeBinarySensor::setup() { ZB_ZCL_SET_ATTRIBUTE(this->endpoint_, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_BINARY_INPUT_PRESENT_VALUE_ID, &this->cluster_attributes_->present_value, ZB_FALSE); - this->parent_->flush(); + this->parent_->force_report(); }); } diff --git a/esphome/components/zigbee/zigbee_sensor_zephyr.cpp b/esphome/components/zigbee/zigbee_sensor_zephyr.cpp index 74550d6487..25e1e083e0 100644 --- a/esphome/components/zigbee/zigbee_sensor_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_sensor_zephyr.cpp @@ -21,7 +21,7 @@ void ZigbeeSensor::setup() { ZB_ZCL_SET_ATTRIBUTE(this->endpoint_, ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_ANALOG_INPUT_PRESENT_VALUE_ID, (zb_uint8_t *) &this->cluster_attributes_->present_value, ZB_FALSE); - this->parent_->flush(); + this->parent_->force_report(); }); } diff --git a/esphome/components/zigbee/zigbee_switch_zephyr.cpp b/esphome/components/zigbee/zigbee_switch_zephyr.cpp index 5454f262f9..fef02e5a0c 100644 --- a/esphome/components/zigbee/zigbee_switch_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_switch_zephyr.cpp @@ -31,7 +31,7 @@ void ZigbeeSwitch::setup() { ZB_ZCL_SET_ATTRIBUTE(this->endpoint_, ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID, &this->cluster_attributes_->present_value, ZB_FALSE); - this->parent_->flush(); + this->parent_->force_report(); }); } @@ -41,8 +41,6 @@ void ZigbeeSwitch::zcl_device_cb_(zb_bufid_t bufid) { zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; - p_device_cb_param->status = RET_OK; - switch (device_cb_id) { /* ZCL set attribute value */ case ZB_ZCL_SET_ATTR_VALUE_CB_ID: @@ -58,10 +56,11 @@ void ZigbeeSwitch::zcl_device_cb_(zb_bufid_t bufid) { } else { /* other clusters attribute handled here */ ESP_LOGI(TAG, "Unhandled cluster attribute id: %d", cluster_id); + p_device_cb_param->status = RET_NOT_IMPLEMENTED; } break; default: - p_device_cb_param->status = RET_ERROR; + p_device_cb_param->status = RET_NOT_IMPLEMENTED; break; } diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index e43ab8f84d..eabf5c30d4 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -112,10 +112,10 @@ void ZigbeeComponent::zcl_device_cb(zb_bufid_t bufid) { const auto &cb = global_zigbee->callbacks_[endpoint - 1]; if (cb) { cb(bufid); + return; } - return; } - p_device_cb_param->status = RET_ERROR; + p_device_cb_param->status = RET_NOT_IMPLEMENTED; } void ZigbeeComponent::on_join_() { @@ -230,11 +230,11 @@ static void send_attribute_report(zb_bufid_t bufid, zb_uint16_t cmd_id) { zb_buf_free(bufid); } -void ZigbeeComponent::flush() { this->need_flush_ = true; } +void ZigbeeComponent::force_report() { this->force_report_ = true; } void ZigbeeComponent::loop() { - if (this->need_flush_) { - this->need_flush_ = false; + if (this->force_report_) { + this->force_report_ = false; zb_buf_get_out_delayed_ext(send_attribute_report, 0, 0); } } diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index d5f1257f9c..b75c192c1a 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -72,7 +72,7 @@ class ZigbeeComponent : public Component { void zboss_signal_handler_esphome(zb_bufid_t bufid); void factory_reset(); Trigger<> *get_join_trigger() { return &this->join_trigger_; }; - void flush(); + void force_report(); void loop() override; protected: @@ -84,7 +84,7 @@ class ZigbeeComponent : public Component { std::array, ZIGBEE_ENDPOINTS_COUNT> callbacks_{}; CallbackManager join_cb_; Trigger<> join_trigger_; - bool need_flush_{false}; + bool force_report_{false}; }; class ZigbeeEntity { diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index 7f1f7dc57f..67a11d3685 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -336,14 +336,14 @@ async def zephyr_setup_switch(entity: cg.MockObj, config: ConfigType) -> None: CORE.add_job(_add_switch, entity, config) -def _slot_index() -> int: - """Find the next available endpoint slot""" +def get_slot_index() -> int: + """Find the next available endpoint slot.""" slot = next( (i for i, v in enumerate(CORE.data[KEY_ZIGBEE][KEY_EP_NUMBER]) if v == ""), None ) if slot is None: raise cv.Invalid( - f"Not found empty slot, size ({len(CORE.data[KEY_ZIGBEE][KEY_EP_NUMBER])})" + f"No available Zigbee endpoint slots ({len(CORE.data[KEY_ZIGBEE][KEY_EP_NUMBER])} in use)" ) return slot @@ -358,7 +358,7 @@ async def _add_zigbee_ep( app_device_id: str, extra_field_values: dict[str, int] | None = None, ) -> None: - slot_index = _slot_index() + slot_index = get_slot_index() prefix = f"zigbee_ep{slot_index + 1}" attrs_name = f"{prefix}_attrs" diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 6c5904ef25..9c7060cd1d 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -16,7 +16,6 @@ #include #include #include - #include #include "esphome/core/optional.h" diff --git a/tests/components/zigbee/common.yaml b/tests/components/zigbee/common.yaml index 11100e1e0c..e4dee5f74a 100644 --- a/tests/components/zigbee/common.yaml +++ b/tests/components/zigbee/common.yaml @@ -8,8 +8,6 @@ binary_sensor: name: "Garage Door Open 3" - platform: template name: "Garage Door Open 4" - - platform: template - name: "Garage Door Open 5" - platform: template name: "Garage Door Internal" internal: True @@ -21,6 +19,10 @@ sensor: - platform: template name: "Analog 2" lambda: return 11.0; + - platform: template + name: "Analog 3" + lambda: return 12.0; + internal: True zigbee: wipe_on_boot: true @@ -35,6 +37,9 @@ output: write_action: - zigbee.factory_reset +time: + - platform: zigbee + switch: - platform: template name: "Template Switch" From 7385c4cf3d6092f24fc96f60499817a177661b4b Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Wed, 28 Jan 2026 09:04:43 -0700 Subject: [PATCH 0401/2030] [ld2450] preserve precision of angle (#13600) --- esphome/components/ld2450/ld2450.cpp | 2 +- esphome/components/ld2450/sensor.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 07809023cd..ca8d918441 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -451,7 +451,7 @@ void LD2450Component::handle_periodic_data_() { int16_t ty = 0; int16_t td = 0; int16_t ts = 0; - int16_t angle = 0; + float angle = 0; uint8_t index = 0; Direction direction{DIRECTION_UNDEFINED}; bool is_moving = false; diff --git a/esphome/components/ld2450/sensor.py b/esphome/components/ld2450/sensor.py index 3dee8bf470..ce58cedf11 100644 --- a/esphome/components/ld2450/sensor.py +++ b/esphome/components/ld2450/sensor.py @@ -143,6 +143,7 @@ CONFIG_SCHEMA = CONFIG_SCHEMA.extend( ], icon=ICON_FORMAT_TEXT_ROTATION_ANGLE_UP, unit_of_measurement=UNIT_DEGREES, + accuracy_decimals=1, ), cv.Optional(CONF_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, From e1355de4cb85ccdcc716e812880dcfcc256a3115 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 06:06:33 -1000 Subject: [PATCH 0402/2030] [runtime_stats] Eliminate heap churn by using stack-allocated buffer for sorting (#13586) --- .../runtime_stats/runtime_stats.cpp | 59 ++++++++++++------- .../components/runtime_stats/runtime_stats.h | 12 ---- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index 9a1e1a109a..410695da04 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -27,46 +27,61 @@ void RuntimeStatsCollector::record_component_time(Component *component, uint32_t } void RuntimeStatsCollector::log_stats_() { + // First pass: count active components + size_t count = 0; + for (const auto &it : this->component_stats_) { + if (it.second.get_period_count() > 0) { + count++; + } + } + ESP_LOGI(TAG, "Component Runtime Statistics\n" - " Period stats (last %" PRIu32 "ms):", - this->log_interval_); + " Period stats (last %" PRIu32 "ms): %zu active components", + this->log_interval_, count); - // First collect stats we want to display - std::vector stats_to_display; + if (count == 0) { + return; + } + // Stack buffer sized to actual active count (up to 256 components), heap fallback for larger + SmallBufferWithHeapFallback<256, Component *> buffer(count); + Component **sorted = buffer.get(); + + // Second pass: fill buffer with active components + size_t idx = 0; for (const auto &it : this->component_stats_) { - Component *component = it.first; - const ComponentRuntimeStats &stats = it.second; - if (stats.get_period_count() > 0) { - ComponentStatPair pair = {component, &stats}; - stats_to_display.push_back(pair); + if (it.second.get_period_count() > 0) { + sorted[idx++] = it.first; } } // Sort by period runtime (descending) - std::sort(stats_to_display.begin(), stats_to_display.end(), std::greater()); + std::sort(sorted, sorted + count, [this](Component *a, Component *b) { + return this->component_stats_[a].get_period_time_ms() > this->component_stats_[b].get_period_time_ms(); + }); // Log top components by period runtime - for (const auto &it : stats_to_display) { + for (size_t i = 0; i < count; i++) { + const auto &stats = this->component_stats_[sorted[i]]; ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", - LOG_STR_ARG(it.component->get_component_log_str()), it.stats->get_period_count(), - it.stats->get_period_avg_time_ms(), it.stats->get_period_max_time_ms(), it.stats->get_period_time_ms()); + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_period_count(), stats.get_period_avg_time_ms(), + stats.get_period_max_time_ms(), stats.get_period_time_ms()); } - // Log total stats since boot - ESP_LOGI(TAG, " Total stats (since boot):"); + // Log total stats since boot (only for active components - idle ones haven't changed) + ESP_LOGI(TAG, " Total stats (since boot): %zu active components", count); // Re-sort by total runtime for all-time stats - std::sort(stats_to_display.begin(), stats_to_display.end(), - [](const ComponentStatPair &a, const ComponentStatPair &b) { - return a.stats->get_total_time_ms() > b.stats->get_total_time_ms(); - }); + std::sort(sorted, sorted + count, [this](Component *a, Component *b) { + return this->component_stats_[a].get_total_time_ms() > this->component_stats_[b].get_total_time_ms(); + }); - for (const auto &it : stats_to_display) { + for (size_t i = 0; i < count; i++) { + const auto &stats = this->component_stats_[sorted[i]]; ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", - LOG_STR_ARG(it.component->get_component_log_str()), it.stats->get_total_count(), - it.stats->get_total_avg_time_ms(), it.stats->get_total_max_time_ms(), it.stats->get_total_time_ms()); + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_total_count(), stats.get_total_avg_time_ms(), + stats.get_total_max_time_ms(), stats.get_total_time_ms()); } } diff --git a/esphome/components/runtime_stats/runtime_stats.h b/esphome/components/runtime_stats/runtime_stats.h index 56122364c2..c7fea7474b 100644 --- a/esphome/components/runtime_stats/runtime_stats.h +++ b/esphome/components/runtime_stats/runtime_stats.h @@ -5,7 +5,6 @@ #ifdef USE_RUNTIME_STATS #include -#include #include #include #include "esphome/core/helpers.h" @@ -77,17 +76,6 @@ class ComponentRuntimeStats { uint32_t total_max_time_ms_; }; -// For sorting components by run time -struct ComponentStatPair { - Component *component; - const ComponentRuntimeStats *stats; - - bool operator>(const ComponentStatPair &other) const { - // Sort by period time as that's what we're displaying in the logs - return stats->get_period_time_ms() > other.stats->get_period_time_ms(); - } -}; - class RuntimeStatsCollector { public: RuntimeStatsCollector(); From d86048cc2d238fe8339f6a637bd2e24d7ca61254 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 28 Jan 2026 17:41:04 +0100 Subject: [PATCH 0403/2030] [nrf52,zigbee] Address change (#13580) --- esphome/components/zigbee/__init__.py | 8 ++++++++ esphome/components/zigbee/const_zephyr.py | 1 + esphome/components/zigbee/zigbee_zephyr.py | 8 ++++++++ tests/components/zigbee/test.nrf52-xiao-ble.yaml | 1 + 4 files changed, 18 insertions(+) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 8179220507..1b1da78308 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -12,6 +12,7 @@ from esphome.core import CORE from esphome.types import ConfigType from .const_zephyr import ( + CONF_IEEE802154_VENDOR_OUI, CONF_MAX_EP_NUMBER, CONF_ON_JOIN, CONF_POWER_SOURCE, @@ -58,6 +59,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_POWER_SOURCE, default="DC_SOURCE"): cv.enum( POWER_SOURCE, upper=True ), + cv.Optional(CONF_IEEE802154_VENDOR_OUI): cv.All( + cv.Any( + cv.int_range(min=0x000000, max=0xFFFFFF), + cv.one_of(*["random"], lower=True), + ), + cv.requires_component("nrf52"), + ), } ).extend(cv.COMPONENT_SCHEMA), zigbee_set_core_data, diff --git a/esphome/components/zigbee/const_zephyr.py b/esphome/components/zigbee/const_zephyr.py index 0372f22593..03c1bb546f 100644 --- a/esphome/components/zigbee/const_zephyr.py +++ b/esphome/components/zigbee/const_zephyr.py @@ -22,6 +22,7 @@ POWER_SOURCE = { "EMERGENCY_MAINS_CONST": "ZB_ZCL_BASIC_POWER_SOURCE_EMERGENCY_MAINS_CONST", "EMERGENCY_MAINS_TRANSF": "ZB_ZCL_BASIC_POWER_SOURCE_EMERGENCY_MAINS_TRANSF", } +CONF_IEEE802154_VENDOR_OUI = "ieee802154_vendor_oui" # Keys for CORE.data storage KEY_ZIGBEE = "zigbee" diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index 67a11d3685..b3bd10bfab 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -49,6 +49,7 @@ from esphome.cpp_generator import ( from esphome.types import ConfigType from .const_zephyr import ( + CONF_IEEE802154_VENDOR_OUI, CONF_ON_JOIN, CONF_POWER_SOURCE, CONF_WIPE_ON_BOOT, @@ -152,6 +153,13 @@ async def zephyr_to_code(config: ConfigType) -> None: zephyr_add_prj_conf("NET_IP_ADDR_CHECK", False) zephyr_add_prj_conf("NET_UDP", False) + if CONF_IEEE802154_VENDOR_OUI in config: + zephyr_add_prj_conf("IEEE802154_VENDOR_OUI_ENABLE", True) + random_number = config[CONF_IEEE802154_VENDOR_OUI] + if random_number == "random": + random_number = random.randint(0x000000, 0xFFFFFF) + zephyr_add_prj_conf("IEEE802154_VENDOR_OUI", random_number) + if config[CONF_WIPE_ON_BOOT]: if config[CONF_WIPE_ON_BOOT] == "once": cg.add_define( diff --git a/tests/components/zigbee/test.nrf52-xiao-ble.yaml b/tests/components/zigbee/test.nrf52-xiao-ble.yaml index d2ce552de3..254f370ca7 100644 --- a/tests/components/zigbee/test.nrf52-xiao-ble.yaml +++ b/tests/components/zigbee/test.nrf52-xiao-ble.yaml @@ -3,3 +3,4 @@ zigbee: wipe_on_boot: once power_source: battery + ieee802154_vendor_oui: 0x231 From 87fcfc9d76a148807012742c35a6cb13a99f395f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 09:40:00 -1000 Subject: [PATCH 0404/2030] [wifi] Fix ESP8266 yield panic when WiFi scan fails (#13603) --- esphome/components/wifi/wifi_component_esp8266.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index be54038af8..c714afaad3 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -756,7 +756,10 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { if (status != OK) { ESP_LOGV(TAG, "Scan failed: %d", status); - this->retry_connect(); + // Don't call retry_connect() here - this callback runs in SDK system context + // where yield() cannot be called. Instead, just set scan_done_ and let + // check_scanning_finished() handle the empty scan_result_ from loop context. + this->scan_done_ = true; return; } From 455ade0dcad9ee029cdf3049538a53ab87b74c9b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 09:41:42 -1000 Subject: [PATCH 0405/2030] [http_request] Fix empty body for chunked transfer encoding responses (#13599) --- .../http_request/http_request_arduino.cpp | 18 +++++++++++---- .../http_request/http_request_idf.cpp | 22 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 8ec4d2bc4b..82538b2cb3 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -131,6 +131,10 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur } } + // HTTPClient::getSize() returns -1 for chunked transfer encoding (no Content-Length). + // When cast to size_t, -1 becomes SIZE_MAX (4294967295 on 32-bit). + // The read() method handles this: bytes_read_ can never reach SIZE_MAX, so the + // early return check (bytes_read_ >= content_length) will never trigger. int content_length = container->client_.getSize(); ESP_LOGD(TAG, "Content-Length: %d", content_length); container->content_length = (size_t) content_length; @@ -167,17 +171,23 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { } int available_data = stream_ptr->available(); - int bufsize = std::min(max_len, std::min(this->content_length - this->bytes_read_, (size_t) available_data)); + // For chunked transfer encoding, HTTPClient::getSize() returns -1, which becomes SIZE_MAX when + // cast to size_t. SIZE_MAX - bytes_read_ is still huge, so it won't limit the read. + size_t remaining = (this->content_length > 0) ? (this->content_length - this->bytes_read_) : max_len; + int bufsize = std::min(max_len, std::min(remaining, (size_t) available_data)); if (bufsize == 0) { this->duration_ms += (millis() - start); - // Check if we've read all expected content - if (this->bytes_read_ >= this->content_length) { + // Check if we've read all expected content (only valid when content_length is known and not SIZE_MAX) + // For chunked encoding (content_length == SIZE_MAX), we can't use this check + if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { return 0; // All content read successfully } // No data available - check if connection is still open + // For chunked encoding, !connected() after reading means EOF (all chunks received) + // For known content_length with bytes_read_ < content_length, it means connection dropped if (!stream_ptr->connected()) { - return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed prematurely + return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed or EOF for chunked } return 0; // No data yet, caller should retry } diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 680ae6c801..2b4dee953a 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -157,6 +157,8 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c } container->feed_wdt(); + // esp_http_client_fetch_headers() returns 0 for chunked transfer encoding (no Content-Length header). + // The read() method handles content_length == 0 specially to support chunked responses. container->content_length = esp_http_client_fetch_headers(client); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); @@ -225,14 +227,22 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c // // We normalize to HttpContainer::read() contract: // > 0: bytes read -// 0: no data yet / all content read (caller should check bytes_read vs content_length) +// 0: all content read (only returned when content_length is known and fully read) // < 0: error/connection closed +// +// Note on chunked transfer encoding: +// esp_http_client_fetch_headers() returns 0 for chunked responses (no Content-Length header). +// We handle this by skipping the content_length check when content_length is 0, +// allowing esp_http_client_read() to handle chunked decoding internally and signal EOF +// by returning 0. int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); // Check if we've already read all expected content - if (this->bytes_read_ >= this->content_length) { + // Skip this check when content_length is 0 (chunked transfer encoding or unknown length) + // For chunked responses, esp_http_client_read() will return 0 when all data is received + if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { return 0; // All content read successfully } @@ -247,7 +257,13 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { return read_len_or_error; } - // Connection closed by server before all content received + // esp_http_client_read() returns 0 in two cases: + // 1. Known content_length: connection closed before all data received (error) + // 2. Chunked encoding (content_length == 0): end of stream reached (EOF) + // For case 1, returning HTTP_ERROR_CONNECTION_CLOSED is correct. + // For case 2, 0 indicates that all chunked data has already been delivered + // in previous successful read() calls, so treating this as a closed + // connection does not cause any loss of response data. if (read_len_or_error == 0) { return HTTP_ERROR_CONNECTION_CLOSED; } From 6f22509883c7e6d044269fc6f6c65b8d7d1ce4e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:42:05 -1000 Subject: [PATCH 0406/2030] Bump docker/login-action from 3.6.0 to 3.7.0 in the docker-actions group (#13606) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5cd8db6181..479b01ee37 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,12 +102,12 @@ jobs: uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to docker hub - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -182,13 +182,13 @@ jobs: - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry if: matrix.registry == 'ghcr' - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} From 6a3205f4db225c997543140f91309eb9399b366d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 10:35:26 -1000 Subject: [PATCH 0407/2030] [globals] Convert restoring globals to PollingComponent to reduce CPU usage (#13345) --- esphome/components/globals/__init__.py | 42 +++++++++++++++---- .../components/globals/globals_component.h | 28 ++++++------- tests/components/globals/common.yaml | 1 + 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index 633ccea66b..fc400c5dd1 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -9,30 +9,56 @@ from esphome.const import ( CONF_VALUE, ) from esphome.core import CoroPriority, coroutine_with_priority +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core"] globals_ns = cg.esphome_ns.namespace("globals") GlobalsComponent = globals_ns.class_("GlobalsComponent", cg.Component) -RestoringGlobalsComponent = globals_ns.class_("RestoringGlobalsComponent", cg.Component) +RestoringGlobalsComponent = globals_ns.class_( + "RestoringGlobalsComponent", cg.PollingComponent +) RestoringGlobalStringComponent = globals_ns.class_( - "RestoringGlobalStringComponent", cg.Component + "RestoringGlobalStringComponent", cg.PollingComponent ) GlobalVarSetAction = globals_ns.class_("GlobalVarSetAction", automation.Action) CONF_MAX_RESTORE_DATA_LENGTH = "max_restore_data_length" +# Base schema fields shared by both variants +_BASE_SCHEMA = { + cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), + cv.Required(CONF_TYPE): cv.string_strict, + cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, + cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), +} -MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema( +# Non-restoring globals: regular Component (no polling needed) +_NON_RESTORING_SCHEMA = cv.Schema( { - cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), - cv.Required(CONF_TYPE): cv.string_strict, - cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, + **_BASE_SCHEMA, cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, - cv.Optional(CONF_MAX_RESTORE_DATA_LENGTH): cv.int_range(0, 254), } ).extend(cv.COMPONENT_SCHEMA) +# Restoring globals: PollingComponent with configurable update_interval +_RESTORING_SCHEMA = cv.Schema( + { + **_BASE_SCHEMA, + cv.Optional(CONF_RESTORE_VALUE, default=True): cv.boolean, + } +).extend(cv.polling_component_schema("1s")) + + +def _globals_schema(config: ConfigType) -> ConfigType: + """Select schema based on restore_value setting.""" + if config.get(CONF_RESTORE_VALUE, False): + return _RESTORING_SCHEMA(config) + return _NON_RESTORING_SCHEMA(config) + + +MULTI_CONF = True +CONFIG_SCHEMA = _globals_schema + # Run with low priority so that namespaces are registered first @coroutine_with_priority(CoroPriority.LATE) diff --git a/esphome/components/globals/globals_component.h b/esphome/components/globals/globals_component.h index 1d2a08937e..3db29bea35 100644 --- a/esphome/components/globals/globals_component.h +++ b/esphome/components/globals/globals_component.h @@ -5,8 +5,7 @@ #include "esphome/core/helpers.h" #include -namespace esphome { -namespace globals { +namespace esphome::globals { template class GlobalsComponent : public Component { public: @@ -24,13 +23,14 @@ template class GlobalsComponent : public Component { T value_{}; }; -template class RestoringGlobalsComponent : public Component { +template class RestoringGlobalsComponent : public PollingComponent { public: using value_type = T; - explicit RestoringGlobalsComponent() = default; - explicit RestoringGlobalsComponent(T initial_value) : value_(initial_value) {} + explicit RestoringGlobalsComponent() : PollingComponent(1000) {} + explicit RestoringGlobalsComponent(T initial_value) : PollingComponent(1000), value_(initial_value) {} explicit RestoringGlobalsComponent( - std::array::type, std::extent::value> initial_value) { + std::array::type, std::extent::value> initial_value) + : PollingComponent(1000) { memcpy(this->value_, initial_value.data(), sizeof(T)); } @@ -44,7 +44,7 @@ template class RestoringGlobalsComponent : public Component { float get_setup_priority() const override { return setup_priority::HARDWARE; } - void loop() override { store_value_(); } + void update() override { store_value_(); } void on_shutdown() override { store_value_(); } @@ -66,13 +66,14 @@ template class RestoringGlobalsComponent : public Component { }; // Use with string or subclasses of strings -template class RestoringGlobalStringComponent : public Component { +template class RestoringGlobalStringComponent : public PollingComponent { public: using value_type = T; - explicit RestoringGlobalStringComponent() = default; - explicit RestoringGlobalStringComponent(T initial_value) { this->value_ = initial_value; } + explicit RestoringGlobalStringComponent() : PollingComponent(1000) {} + explicit RestoringGlobalStringComponent(T initial_value) : PollingComponent(1000) { this->value_ = initial_value; } explicit RestoringGlobalStringComponent( - std::array::type, std::extent::value> initial_value) { + std::array::type, std::extent::value> initial_value) + : PollingComponent(1000) { memcpy(this->value_, initial_value.data(), sizeof(T)); } @@ -90,7 +91,7 @@ template class RestoringGlobalStringComponent : public C float get_setup_priority() const override { return setup_priority::HARDWARE; } - void loop() override { store_value_(); } + void update() override { store_value_(); } void on_shutdown() override { store_value_(); } @@ -144,5 +145,4 @@ template T &id(GlobalsComponent *value) { return value->value(); template T &id(RestoringGlobalsComponent *value) { return value->value(); } template T &id(RestoringGlobalStringComponent *value) { return value->value(); } -} // namespace globals -} // namespace esphome +} // namespace esphome::globals diff --git a/tests/components/globals/common.yaml b/tests/components/globals/common.yaml index 224a91a270..efa3cba076 100644 --- a/tests/components/globals/common.yaml +++ b/tests/components/globals/common.yaml @@ -10,6 +10,7 @@ globals: type: int restore_value: true initial_value: "0" + update_interval: 5s - id: glob_float type: float restore_value: true From 6d8294c2d32234f4fd300af2f963347dee25952a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 29 Jan 2026 07:42:55 +1100 Subject: [PATCH 0408/2030] [workflows] Refactor auto-label-pr script into modular JS (#13582) --- .github/scripts/auto-label-pr/constants.js | 36 ++ .github/scripts/auto-label-pr/detectors.js | 302 ++++++++++ .github/scripts/auto-label-pr/index.js | 179 ++++++ .github/scripts/auto-label-pr/labels.js | 41 ++ .github/scripts/auto-label-pr/reviews.js | 124 ++++ .github/workflows/auto-label-pr.yml | 632 +-------------------- 6 files changed, 684 insertions(+), 630 deletions(-) create mode 100644 .github/scripts/auto-label-pr/constants.js create mode 100644 .github/scripts/auto-label-pr/detectors.js create mode 100644 .github/scripts/auto-label-pr/index.js create mode 100644 .github/scripts/auto-label-pr/labels.js create mode 100644 .github/scripts/auto-label-pr/reviews.js diff --git a/.github/scripts/auto-label-pr/constants.js b/.github/scripts/auto-label-pr/constants.js new file mode 100644 index 0000000000..d5e42fa1b9 --- /dev/null +++ b/.github/scripts/auto-label-pr/constants.js @@ -0,0 +1,36 @@ +// Constants and markers for PR auto-labeling +module.exports = { + BOT_COMMENT_MARKER: '', + CODEOWNERS_MARKER: '', + TOO_BIG_MARKER: '', + + MANAGED_LABELS: [ + 'new-component', + 'new-platform', + 'new-target-platform', + 'merging-to-release', + 'merging-to-beta', + 'chained-pr', + 'core', + 'small-pr', + 'dashboard', + 'github-actions', + 'by-code-owner', + 'has-tests', + 'needs-tests', + 'needs-docs', + 'needs-codeowners', + 'too-big', + 'labeller-recheck', + 'bugfix', + 'new-feature', + 'breaking-change', + 'developer-breaking-change', + 'code-quality', + ], + + DOCS_PR_PATTERNS: [ + /https:\/\/github\.com\/esphome\/esphome-docs\/pull\/\d+/, + /esphome\/esphome-docs#\d+/ + ] +}; diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js new file mode 100644 index 0000000000..79025988dd --- /dev/null +++ b/.github/scripts/auto-label-pr/detectors.js @@ -0,0 +1,302 @@ +const fs = require('fs'); +const { DOCS_PR_PATTERNS } = require('./constants'); + +// Strategy: Merge branch detection +async function detectMergeBranch(context) { + const labels = new Set(); + const baseRef = context.payload.pull_request.base.ref; + + if (baseRef === 'release') { + labels.add('merging-to-release'); + } else if (baseRef === 'beta') { + labels.add('merging-to-beta'); + } else if (baseRef !== 'dev') { + labels.add('chained-pr'); + } + + return labels; +} + +// Strategy: Component and platform labeling +async function detectComponentPlatforms(changedFiles, apiData) { + const labels = new Set(); + const componentRegex = /^esphome\/components\/([^\/]+)\//; + const targetPlatformRegex = new RegExp(`^esphome\/components\/(${apiData.targetPlatforms.join('|')})/`); + + for (const file of changedFiles) { + const componentMatch = file.match(componentRegex); + if (componentMatch) { + labels.add(`component: ${componentMatch[1]}`); + } + + const platformMatch = file.match(targetPlatformRegex); + if (platformMatch) { + labels.add(`platform: ${platformMatch[1]}`); + } + } + + return labels; +} + +// Strategy: New component detection +async function detectNewComponents(prFiles) { + const labels = new Set(); + const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename); + + for (const file of addedFiles) { + const componentMatch = file.match(/^esphome\/components\/([^\/]+)\/__init__\.py$/); + if (componentMatch) { + try { + const content = fs.readFileSync(file, 'utf8'); + if (content.includes('IS_TARGET_PLATFORM = True')) { + labels.add('new-target-platform'); + } + } catch (error) { + console.log(`Failed to read content of ${file}:`, error.message); + } + labels.add('new-component'); + } + } + + return labels; +} + +// Strategy: New platform detection +async function detectNewPlatforms(prFiles, apiData) { + const labels = new Set(); + const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename); + + for (const file of addedFiles) { + const platformFileMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\.py$/); + if (platformFileMatch) { + const [, component, platform] = platformFileMatch; + if (apiData.platformComponents.includes(platform)) { + labels.add('new-platform'); + } + } + + const platformDirMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\/__init__\.py$/); + if (platformDirMatch) { + const [, component, platform] = platformDirMatch; + if (apiData.platformComponents.includes(platform)) { + labels.add('new-platform'); + } + } + } + + return labels; +} + +// Strategy: Core files detection +async function detectCoreChanges(changedFiles) { + const labels = new Set(); + const coreFiles = changedFiles.filter(file => + file.startsWith('esphome/core/') || + (file.startsWith('esphome/') && file.split('/').length === 2) + ); + + if (coreFiles.length > 0) { + labels.add('core'); + } + + return labels; +} + +// Strategy: PR size detection +async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, TOO_BIG_THRESHOLD) { + const labels = new Set(); + + if (totalChanges <= SMALL_PR_THRESHOLD) { + labels.add('small-pr'); + return labels; + } + + const testAdditions = prFiles + .filter(file => file.filename.startsWith('tests/')) + .reduce((sum, file) => sum + (file.additions || 0), 0); + const testDeletions = prFiles + .filter(file => file.filename.startsWith('tests/')) + .reduce((sum, file) => sum + (file.deletions || 0), 0); + + const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions); + + // Don't add too-big if mega-pr label is already present + if (nonTestChanges > TOO_BIG_THRESHOLD && !isMegaPR) { + labels.add('too-big'); + } + + return labels; +} + +// Strategy: Dashboard changes +async function detectDashboardChanges(changedFiles) { + const labels = new Set(); + const dashboardFiles = changedFiles.filter(file => + file.startsWith('esphome/dashboard/') || + file.startsWith('esphome/components/dashboard_import/') + ); + + if (dashboardFiles.length > 0) { + labels.add('dashboard'); + } + + return labels; +} + +// Strategy: GitHub Actions changes +async function detectGitHubActionsChanges(changedFiles) { + const labels = new Set(); + const githubActionsFiles = changedFiles.filter(file => + file.startsWith('.github/workflows/') + ); + + if (githubActionsFiles.length > 0) { + labels.add('github-actions'); + } + + return labels; +} + +// Strategy: Code owner detection +async function detectCodeOwner(github, context, changedFiles) { + const labels = new Set(); + const { owner, repo } = context.repo; + + try { + const { data: codeownersFile } = await github.rest.repos.getContent({ + owner, + repo, + path: 'CODEOWNERS', + }); + + const codeownersContent = Buffer.from(codeownersFile.content, 'base64').toString('utf8'); + const prAuthor = context.payload.pull_request.user.login; + + const codeownersLines = codeownersContent.split('\n') + .map(line => line.trim()) + .filter(line => line && !line.startsWith('#')); + + const codeownersRegexes = codeownersLines.map(line => { + const parts = line.split(/\s+/); + const pattern = parts[0]; + const owners = parts.slice(1); + + let regex; + if (pattern.endsWith('*')) { + const dir = pattern.slice(0, -1); + regex = new RegExp(`^${dir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`); + } else if (pattern.includes('*')) { + // First escape all regex special chars except *, then replace * with .* + const regexPattern = pattern + .replace(/[.+?^${}()|[\]\\]/g, '\\$&') + .replace(/\*/g, '.*'); + regex = new RegExp(`^${regexPattern}$`); + } else { + regex = new RegExp(`^${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`); + } + + return { regex, owners }; + }); + + for (const file of changedFiles) { + for (const { regex, owners } of codeownersRegexes) { + if (regex.test(file) && owners.some(owner => owner === `@${prAuthor}`)) { + labels.add('by-code-owner'); + return labels; + } + } + } + } catch (error) { + console.log('Failed to read or parse CODEOWNERS file:', error.message); + } + + return labels; +} + +// Strategy: Test detection +async function detectTests(changedFiles) { + const labels = new Set(); + const testFiles = changedFiles.filter(file => file.startsWith('tests/')); + + if (testFiles.length > 0) { + labels.add('has-tests'); + } + + return labels; +} + +// Strategy: PR Template Checkbox detection +async function detectPRTemplateCheckboxes(context) { + const labels = new Set(); + const prBody = context.payload.pull_request.body || ''; + + console.log('Checking PR template checkboxes...'); + + // Check for checked checkboxes in the "Types of changes" section + const checkboxPatterns = [ + { pattern: /- \[x\] Bugfix \(non-breaking change which fixes an issue\)/i, label: 'bugfix' }, + { pattern: /- \[x\] New feature \(non-breaking change which adds functionality\)/i, label: 'new-feature' }, + { pattern: /- \[x\] Breaking change \(fix or feature that would cause existing functionality to not work as expected\)/i, label: 'breaking-change' }, + { pattern: /- \[x\] Developer breaking change \(an API change that could break external components\)/i, label: 'developer-breaking-change' }, + { pattern: /- \[x\] Code quality improvements to existing code or addition of tests/i, label: 'code-quality' } + ]; + + for (const { pattern, label } of checkboxPatterns) { + if (pattern.test(prBody)) { + console.log(`Found checked checkbox for: ${label}`); + labels.add(label); + } + } + + return labels; +} + +// Strategy: Requirements detection +async function detectRequirements(allLabels, prFiles, context) { + const labels = new Set(); + + // Check for missing tests + if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) && !allLabels.has('has-tests')) { + labels.add('needs-tests'); + } + + // Check for missing docs + if (allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) { + const prBody = context.payload.pull_request.body || ''; + const hasDocsLink = DOCS_PR_PATTERNS.some(pattern => pattern.test(prBody)); + + if (!hasDocsLink) { + labels.add('needs-docs'); + } + } + + // Check for missing CODEOWNERS + if (allLabels.has('new-component')) { + const codeownersModified = prFiles.some(file => + file.filename === 'CODEOWNERS' && + (file.status === 'modified' || file.status === 'added') && + (file.additions || 0) > 0 + ); + + if (!codeownersModified) { + labels.add('needs-codeowners'); + } + } + + return labels; +} + +module.exports = { + detectMergeBranch, + detectComponentPlatforms, + detectNewComponents, + detectNewPlatforms, + detectCoreChanges, + detectPRSize, + detectDashboardChanges, + detectGitHubActionsChanges, + detectCodeOwner, + detectTests, + detectPRTemplateCheckboxes, + detectRequirements +}; diff --git a/.github/scripts/auto-label-pr/index.js b/.github/scripts/auto-label-pr/index.js new file mode 100644 index 0000000000..95ecfc4e33 --- /dev/null +++ b/.github/scripts/auto-label-pr/index.js @@ -0,0 +1,179 @@ +const { MANAGED_LABELS } = require('./constants'); +const { + detectMergeBranch, + detectComponentPlatforms, + detectNewComponents, + detectNewPlatforms, + detectCoreChanges, + detectPRSize, + detectDashboardChanges, + detectGitHubActionsChanges, + detectCodeOwner, + detectTests, + detectPRTemplateCheckboxes, + detectRequirements +} = require('./detectors'); +const { handleReviews } = require('./reviews'); +const { applyLabels, removeOldLabels } = require('./labels'); + +// Fetch API data +async function fetchApiData() { + try { + const response = await fetch('https://data.esphome.io/components.json'); + const componentsData = await response.json(); + return { + targetPlatforms: componentsData.target_platforms || [], + platformComponents: componentsData.platform_components || [] + }; + } catch (error) { + console.log('Failed to fetch components data from API:', error.message); + return { targetPlatforms: [], platformComponents: [] }; + } +} + +module.exports = async ({ github, context }) => { + // Environment variables + const SMALL_PR_THRESHOLD = parseInt(process.env.SMALL_PR_THRESHOLD); + const MAX_LABELS = parseInt(process.env.MAX_LABELS); + const TOO_BIG_THRESHOLD = parseInt(process.env.TOO_BIG_THRESHOLD); + const COMPONENT_LABEL_THRESHOLD = parseInt(process.env.COMPONENT_LABEL_THRESHOLD); + + // Global state + const { owner, repo } = context.repo; + const pr_number = context.issue.number; + + // Get current labels and PR data + const { data: currentLabelsData } = await github.rest.issues.listLabelsOnIssue({ + owner, + repo, + issue_number: pr_number + }); + const currentLabels = currentLabelsData.map(label => label.name); + const managedLabels = currentLabels.filter(label => + label.startsWith('component: ') || MANAGED_LABELS.includes(label) + ); + + // Check for mega-PR early - if present, skip most automatic labeling + const isMegaPR = currentLabels.includes('mega-pr'); + + // Get all PR files with automatic pagination + const prFiles = await github.paginate( + github.rest.pulls.listFiles, + { + owner, + repo, + pull_number: pr_number + } + ); + + // Calculate data from PR files + const changedFiles = prFiles.map(file => file.filename); + const totalAdditions = prFiles.reduce((sum, file) => sum + (file.additions || 0), 0); + const totalDeletions = prFiles.reduce((sum, file) => sum + (file.deletions || 0), 0); + const totalChanges = totalAdditions + totalDeletions; + + console.log('Current labels:', currentLabels.join(', ')); + console.log('Changed files:', changedFiles.length); + console.log('Total changes:', totalChanges); + if (isMegaPR) { + console.log('Mega-PR detected - applying limited labeling logic'); + } + + // Fetch API data + const apiData = await fetchApiData(); + const baseRef = context.payload.pull_request.base.ref; + + // Early exit for release and beta branches only + if (baseRef === 'release' || baseRef === 'beta') { + const branchLabels = await detectMergeBranch(context); + const finalLabels = Array.from(branchLabels); + + console.log('Computed labels (merge branch only):', finalLabels.join(', ')); + + // Apply labels + await applyLabels(github, context, finalLabels); + + // Remove old managed labels + await removeOldLabels(github, context, managedLabels, finalLabels); + + return; + } + + // Run all strategies + const [ + branchLabels, + componentLabels, + newComponentLabels, + newPlatformLabels, + coreLabels, + sizeLabels, + dashboardLabels, + actionsLabels, + codeOwnerLabels, + testLabels, + checkboxLabels, + ] = await Promise.all([ + detectMergeBranch(context), + detectComponentPlatforms(changedFiles, apiData), + detectNewComponents(prFiles), + detectNewPlatforms(prFiles, apiData), + detectCoreChanges(changedFiles), + detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, TOO_BIG_THRESHOLD), + detectDashboardChanges(changedFiles), + detectGitHubActionsChanges(changedFiles), + detectCodeOwner(github, context, changedFiles), + detectTests(changedFiles), + detectPRTemplateCheckboxes(context), + ]); + + // Combine all labels + const allLabels = new Set([ + ...branchLabels, + ...componentLabels, + ...newComponentLabels, + ...newPlatformLabels, + ...coreLabels, + ...sizeLabels, + ...dashboardLabels, + ...actionsLabels, + ...codeOwnerLabels, + ...testLabels, + ...checkboxLabels, + ]); + + // Detect requirements based on all other labels + const requirementLabels = await detectRequirements(allLabels, prFiles, context); + for (const label of requirementLabels) { + allLabels.add(label); + } + + let finalLabels = Array.from(allLabels); + + // For mega-PRs, exclude component labels if there are too many + if (isMegaPR) { + const componentLabels = finalLabels.filter(label => label.startsWith('component: ')); + if (componentLabels.length > COMPONENT_LABEL_THRESHOLD) { + finalLabels = finalLabels.filter(label => !label.startsWith('component: ')); + console.log(`Mega-PR detected - excluding ${componentLabels.length} component labels (threshold: ${COMPONENT_LABEL_THRESHOLD})`); + } + } + + // Handle too many labels (only for non-mega PRs) + const tooManyLabels = finalLabels.length > MAX_LABELS; + const originalLabelCount = finalLabels.length; + + if (tooManyLabels && !isMegaPR && !finalLabels.includes('too-big')) { + finalLabels = ['too-big']; + } + + console.log('Computed labels:', finalLabels.join(', ')); + + // Handle reviews + await handleReviews(github, context, finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD); + + // Apply labels + await applyLabels(github, context, finalLabels); + + // Remove old managed labels + await removeOldLabels(github, context, managedLabels, finalLabels); +}; diff --git a/.github/scripts/auto-label-pr/labels.js b/.github/scripts/auto-label-pr/labels.js new file mode 100644 index 0000000000..2268f7ded9 --- /dev/null +++ b/.github/scripts/auto-label-pr/labels.js @@ -0,0 +1,41 @@ +// Apply labels to PR +async function applyLabels(github, context, finalLabels) { + const { owner, repo } = context.repo; + const pr_number = context.issue.number; + + if (finalLabels.length > 0) { + console.log(`Adding labels: ${finalLabels.join(', ')}`); + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: pr_number, + labels: finalLabels + }); + } +} + +// Remove old managed labels +async function removeOldLabels(github, context, managedLabels, finalLabels) { + const { owner, repo } = context.repo; + const pr_number = context.issue.number; + + const labelsToRemove = managedLabels.filter(label => !finalLabels.includes(label)); + for (const label of labelsToRemove) { + console.log(`Removing label: ${label}`); + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: pr_number, + name: label + }); + } catch (error) { + console.log(`Failed to remove label ${label}:`, error.message); + } + } +} + +module.exports = { + applyLabels, + removeOldLabels +}; diff --git a/.github/scripts/auto-label-pr/reviews.js b/.github/scripts/auto-label-pr/reviews.js new file mode 100644 index 0000000000..a84e9ae5aa --- /dev/null +++ b/.github/scripts/auto-label-pr/reviews.js @@ -0,0 +1,124 @@ +const { + BOT_COMMENT_MARKER, + CODEOWNERS_MARKER, + TOO_BIG_MARKER, +} = require('./constants'); + +// Generate review messages +function generateReviewMessages(finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD) { + const messages = []; + + // Too big message + if (finalLabels.includes('too-big')) { + const testAdditions = prFiles + .filter(file => file.filename.startsWith('tests/')) + .reduce((sum, file) => sum + (file.additions || 0), 0); + const testDeletions = prFiles + .filter(file => file.filename.startsWith('tests/')) + .reduce((sum, file) => sum + (file.deletions || 0), 0); + const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions); + + const tooManyLabels = originalLabelCount > MAX_LABELS; + const tooManyChanges = nonTestChanges > TOO_BIG_THRESHOLD; + + let message = `${TOO_BIG_MARKER}\n### 📦 Pull Request Size\n\n`; + + if (tooManyLabels && tooManyChanges) { + message += `This PR is too large with ${nonTestChanges} line changes (excluding tests) and affects ${originalLabelCount} different components/areas.`; + } else if (tooManyLabels) { + message += `This PR affects ${originalLabelCount} different components/areas.`; + } else { + message += `This PR is too large with ${nonTestChanges} line changes (excluding tests).`; + } + + message += ` Please consider breaking it down into smaller, focused PRs to make review easier and reduce the risk of conflicts.\n\n`; + message += `For guidance on breaking down large PRs, see: https://developers.esphome.io/contributing/submitting-your-work/#how-to-approach-large-submissions`; + + messages.push(message); + } + + // CODEOWNERS message + if (finalLabels.includes('needs-codeowners')) { + const message = `${CODEOWNERS_MARKER}\n### 👥 Code Ownership\n\n` + + `Hey there @${prAuthor},\n` + + `Thanks for submitting this pull request! Can you add yourself as a codeowner for this integration? ` + + `This way we can notify you if a bug report for this integration is reported.\n\n` + + `In \`__init__.py\` of the integration, please add:\n\n` + + `\`\`\`python\nCODEOWNERS = ["@${prAuthor}"]\n\`\`\`\n\n` + + `And run \`script/build_codeowners.py\``; + + messages.push(message); + } + + return messages; +} + +// Handle reviews +async function handleReviews(github, context, finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD) { + const { owner, repo } = context.repo; + const pr_number = context.issue.number; + const prAuthor = context.payload.pull_request.user.login; + + const reviewMessages = generateReviewMessages(finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD); + const hasReviewableLabels = finalLabels.some(label => + ['too-big', 'needs-codeowners'].includes(label) + ); + + const { data: reviews } = await github.rest.pulls.listReviews({ + owner, + repo, + pull_number: pr_number + }); + + const botReviews = reviews.filter(review => + review.user.type === 'Bot' && + review.state === 'CHANGES_REQUESTED' && + review.body && review.body.includes(BOT_COMMENT_MARKER) + ); + + if (hasReviewableLabels) { + const reviewBody = `${BOT_COMMENT_MARKER}\n\n${reviewMessages.join('\n\n---\n\n')}`; + + if (botReviews.length > 0) { + // Update existing review + await github.rest.pulls.updateReview({ + owner, + repo, + pull_number: pr_number, + review_id: botReviews[0].id, + body: reviewBody + }); + console.log('Updated existing bot review'); + } else { + // Create new review + await github.rest.pulls.createReview({ + owner, + repo, + pull_number: pr_number, + body: reviewBody, + event: 'REQUEST_CHANGES' + }); + console.log('Created new bot review'); + } + } else if (botReviews.length > 0) { + // Dismiss existing reviews + for (const review of botReviews) { + try { + await github.rest.pulls.dismissReview({ + owner, + repo, + pull_number: pr_number, + review_id: review.id, + message: 'Review dismissed: All requirements have been met' + }); + console.log(`Dismissed bot review ${review.id}`); + } catch (error) { + console.log(`Failed to dismiss review ${review.id}:`, error.message); + } + } + } +} + +module.exports = { + handleReviews +}; diff --git a/.github/workflows/auto-label-pr.yml b/.github/workflows/auto-label-pr.yml index d32d8e01c2..6fcb50b70a 100644 --- a/.github/workflows/auto-label-pr.yml +++ b/.github/workflows/auto-label-pr.yml @@ -36,633 +36,5 @@ jobs: with: github-token: ${{ steps.generate-token.outputs.token }} script: | - const fs = require('fs'); - - // Constants - const SMALL_PR_THRESHOLD = parseInt('${{ env.SMALL_PR_THRESHOLD }}'); - const MAX_LABELS = parseInt('${{ env.MAX_LABELS }}'); - const TOO_BIG_THRESHOLD = parseInt('${{ env.TOO_BIG_THRESHOLD }}'); - const COMPONENT_LABEL_THRESHOLD = parseInt('${{ env.COMPONENT_LABEL_THRESHOLD }}'); - const BOT_COMMENT_MARKER = ''; - const CODEOWNERS_MARKER = ''; - const TOO_BIG_MARKER = ''; - - const MANAGED_LABELS = [ - 'new-component', - 'new-platform', - 'new-target-platform', - 'merging-to-release', - 'merging-to-beta', - 'chained-pr', - 'core', - 'small-pr', - 'dashboard', - 'github-actions', - 'by-code-owner', - 'has-tests', - 'needs-tests', - 'needs-docs', - 'needs-codeowners', - 'too-big', - 'labeller-recheck', - 'bugfix', - 'new-feature', - 'breaking-change', - 'developer-breaking-change', - 'code-quality' - ]; - - const DOCS_PR_PATTERNS = [ - /https:\/\/github\.com\/esphome\/esphome-docs\/pull\/\d+/, - /esphome\/esphome-docs#\d+/ - ]; - - // Global state - const { owner, repo } = context.repo; - const pr_number = context.issue.number; - - // Get current labels and PR data - const { data: currentLabelsData } = await github.rest.issues.listLabelsOnIssue({ - owner, - repo, - issue_number: pr_number - }); - const currentLabels = currentLabelsData.map(label => label.name); - const managedLabels = currentLabels.filter(label => - label.startsWith('component: ') || MANAGED_LABELS.includes(label) - ); - - // Check for mega-PR early - if present, skip most automatic labeling - const isMegaPR = currentLabels.includes('mega-pr'); - - // Get all PR files with automatic pagination - const prFiles = await github.paginate( - github.rest.pulls.listFiles, - { - owner, - repo, - pull_number: pr_number - } - ); - - // Calculate data from PR files - const changedFiles = prFiles.map(file => file.filename); - const totalAdditions = prFiles.reduce((sum, file) => sum + (file.additions || 0), 0); - const totalDeletions = prFiles.reduce((sum, file) => sum + (file.deletions || 0), 0); - const totalChanges = totalAdditions + totalDeletions; - - console.log('Current labels:', currentLabels.join(', ')); - console.log('Changed files:', changedFiles.length); - console.log('Total changes:', totalChanges); - if (isMegaPR) { - console.log('Mega-PR detected - applying limited labeling logic'); - } - - // Fetch API data - async function fetchApiData() { - try { - const response = await fetch('https://data.esphome.io/components.json'); - const componentsData = await response.json(); - return { - targetPlatforms: componentsData.target_platforms || [], - platformComponents: componentsData.platform_components || [] - }; - } catch (error) { - console.log('Failed to fetch components data from API:', error.message); - return { targetPlatforms: [], platformComponents: [] }; - } - } - - // Strategy: Merge branch detection - async function detectMergeBranch() { - const labels = new Set(); - const baseRef = context.payload.pull_request.base.ref; - - if (baseRef === 'release') { - labels.add('merging-to-release'); - } else if (baseRef === 'beta') { - labels.add('merging-to-beta'); - } else if (baseRef !== 'dev') { - labels.add('chained-pr'); - } - - return labels; - } - - // Strategy: Component and platform labeling - async function detectComponentPlatforms(apiData) { - const labels = new Set(); - const componentRegex = /^esphome\/components\/([^\/]+)\//; - const targetPlatformRegex = new RegExp(`^esphome\/components\/(${apiData.targetPlatforms.join('|')})/`); - - for (const file of changedFiles) { - const componentMatch = file.match(componentRegex); - if (componentMatch) { - labels.add(`component: ${componentMatch[1]}`); - } - - const platformMatch = file.match(targetPlatformRegex); - if (platformMatch) { - labels.add(`platform: ${platformMatch[1]}`); - } - } - - return labels; - } - - // Strategy: New component detection - async function detectNewComponents() { - const labels = new Set(); - const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename); - - for (const file of addedFiles) { - const componentMatch = file.match(/^esphome\/components\/([^\/]+)\/__init__\.py$/); - if (componentMatch) { - try { - const content = fs.readFileSync(file, 'utf8'); - if (content.includes('IS_TARGET_PLATFORM = True')) { - labels.add('new-target-platform'); - } - } catch (error) { - console.log(`Failed to read content of ${file}:`, error.message); - } - labels.add('new-component'); - } - } - - return labels; - } - - // Strategy: New platform detection - async function detectNewPlatforms(apiData) { - const labels = new Set(); - const addedFiles = prFiles.filter(file => file.status === 'added').map(file => file.filename); - - for (const file of addedFiles) { - const platformFileMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\.py$/); - if (platformFileMatch) { - const [, component, platform] = platformFileMatch; - if (apiData.platformComponents.includes(platform)) { - labels.add('new-platform'); - } - } - - const platformDirMatch = file.match(/^esphome\/components\/([^\/]+)\/([^\/]+)\/__init__\.py$/); - if (platformDirMatch) { - const [, component, platform] = platformDirMatch; - if (apiData.platformComponents.includes(platform)) { - labels.add('new-platform'); - } - } - } - - return labels; - } - - // Strategy: Core files detection - async function detectCoreChanges() { - const labels = new Set(); - const coreFiles = changedFiles.filter(file => - file.startsWith('esphome/core/') || - (file.startsWith('esphome/') && file.split('/').length === 2) - ); - - if (coreFiles.length > 0) { - labels.add('core'); - } - - return labels; - } - - // Strategy: PR size detection - async function detectPRSize() { - const labels = new Set(); - - if (totalChanges <= SMALL_PR_THRESHOLD) { - labels.add('small-pr'); - return labels; - } - - const testAdditions = prFiles - .filter(file => file.filename.startsWith('tests/')) - .reduce((sum, file) => sum + (file.additions || 0), 0); - const testDeletions = prFiles - .filter(file => file.filename.startsWith('tests/')) - .reduce((sum, file) => sum + (file.deletions || 0), 0); - - const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions); - - // Don't add too-big if mega-pr label is already present - if (nonTestChanges > TOO_BIG_THRESHOLD && !isMegaPR) { - labels.add('too-big'); - } - - return labels; - } - - // Strategy: Dashboard changes - async function detectDashboardChanges() { - const labels = new Set(); - const dashboardFiles = changedFiles.filter(file => - file.startsWith('esphome/dashboard/') || - file.startsWith('esphome/components/dashboard_import/') - ); - - if (dashboardFiles.length > 0) { - labels.add('dashboard'); - } - - return labels; - } - - // Strategy: GitHub Actions changes - async function detectGitHubActionsChanges() { - const labels = new Set(); - const githubActionsFiles = changedFiles.filter(file => - file.startsWith('.github/workflows/') - ); - - if (githubActionsFiles.length > 0) { - labels.add('github-actions'); - } - - return labels; - } - - // Strategy: Code owner detection - async function detectCodeOwner() { - const labels = new Set(); - - try { - const { data: codeownersFile } = await github.rest.repos.getContent({ - owner, - repo, - path: 'CODEOWNERS', - }); - - const codeownersContent = Buffer.from(codeownersFile.content, 'base64').toString('utf8'); - const prAuthor = context.payload.pull_request.user.login; - - const codeownersLines = codeownersContent.split('\n') - .map(line => line.trim()) - .filter(line => line && !line.startsWith('#')); - - const codeownersRegexes = codeownersLines.map(line => { - const parts = line.split(/\s+/); - const pattern = parts[0]; - const owners = parts.slice(1); - - let regex; - if (pattern.endsWith('*')) { - const dir = pattern.slice(0, -1); - regex = new RegExp(`^${dir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`); - } else if (pattern.includes('*')) { - // First escape all regex special chars except *, then replace * with .* - const regexPattern = pattern - .replace(/[.+?^${}()|[\]\\]/g, '\\$&') - .replace(/\*/g, '.*'); - regex = new RegExp(`^${regexPattern}$`); - } else { - regex = new RegExp(`^${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`); - } - - return { regex, owners }; - }); - - for (const file of changedFiles) { - for (const { regex, owners } of codeownersRegexes) { - if (regex.test(file) && owners.some(owner => owner === `@${prAuthor}`)) { - labels.add('by-code-owner'); - return labels; - } - } - } - } catch (error) { - console.log('Failed to read or parse CODEOWNERS file:', error.message); - } - - return labels; - } - - // Strategy: Test detection - async function detectTests() { - const labels = new Set(); - const testFiles = changedFiles.filter(file => file.startsWith('tests/')); - - if (testFiles.length > 0) { - labels.add('has-tests'); - } - - return labels; - } - - // Strategy: PR Template Checkbox detection - async function detectPRTemplateCheckboxes() { - const labels = new Set(); - const prBody = context.payload.pull_request.body || ''; - - console.log('Checking PR template checkboxes...'); - - // Check for checked checkboxes in the "Types of changes" section - const checkboxPatterns = [ - { pattern: /- \[x\] Bugfix \(non-breaking change which fixes an issue\)/i, label: 'bugfix' }, - { pattern: /- \[x\] New feature \(non-breaking change which adds functionality\)/i, label: 'new-feature' }, - { pattern: /- \[x\] Breaking change \(fix or feature that would cause existing functionality to not work as expected\)/i, label: 'breaking-change' }, - { pattern: /- \[x\] Developer breaking change \(an API change that could break external components\)/i, label: 'developer-breaking-change' }, - { pattern: /- \[x\] Code quality improvements to existing code or addition of tests/i, label: 'code-quality' } - ]; - - for (const { pattern, label } of checkboxPatterns) { - if (pattern.test(prBody)) { - console.log(`Found checked checkbox for: ${label}`); - labels.add(label); - } - } - - return labels; - } - - // Strategy: Requirements detection - async function detectRequirements(allLabels) { - const labels = new Set(); - - // Check for missing tests - if ((allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) && !allLabels.has('has-tests')) { - labels.add('needs-tests'); - } - - // Check for missing docs - if (allLabels.has('new-component') || allLabels.has('new-platform') || allLabels.has('new-feature')) { - const prBody = context.payload.pull_request.body || ''; - const hasDocsLink = DOCS_PR_PATTERNS.some(pattern => pattern.test(prBody)); - - if (!hasDocsLink) { - labels.add('needs-docs'); - } - } - - // Check for missing CODEOWNERS - if (allLabels.has('new-component')) { - const codeownersModified = prFiles.some(file => - file.filename === 'CODEOWNERS' && - (file.status === 'modified' || file.status === 'added') && - (file.additions || 0) > 0 - ); - - if (!codeownersModified) { - labels.add('needs-codeowners'); - } - } - - return labels; - } - - // Generate review messages - function generateReviewMessages(finalLabels, originalLabelCount) { - const messages = []; - const prAuthor = context.payload.pull_request.user.login; - - // Too big message - if (finalLabels.includes('too-big')) { - const testAdditions = prFiles - .filter(file => file.filename.startsWith('tests/')) - .reduce((sum, file) => sum + (file.additions || 0), 0); - const testDeletions = prFiles - .filter(file => file.filename.startsWith('tests/')) - .reduce((sum, file) => sum + (file.deletions || 0), 0); - const nonTestChanges = (totalAdditions - testAdditions) - (totalDeletions - testDeletions); - - const tooManyLabels = originalLabelCount > MAX_LABELS; - const tooManyChanges = nonTestChanges > TOO_BIG_THRESHOLD; - - let message = `${TOO_BIG_MARKER}\n### 📦 Pull Request Size\n\n`; - - if (tooManyLabels && tooManyChanges) { - message += `This PR is too large with ${nonTestChanges} line changes (excluding tests) and affects ${originalLabelCount} different components/areas.`; - } else if (tooManyLabels) { - message += `This PR affects ${originalLabelCount} different components/areas.`; - } else { - message += `This PR is too large with ${nonTestChanges} line changes (excluding tests).`; - } - - message += ` Please consider breaking it down into smaller, focused PRs to make review easier and reduce the risk of conflicts.\n\n`; - message += `For guidance on breaking down large PRs, see: https://developers.esphome.io/contributing/submitting-your-work/#how-to-approach-large-submissions`; - - messages.push(message); - } - - // CODEOWNERS message - if (finalLabels.includes('needs-codeowners')) { - const message = `${CODEOWNERS_MARKER}\n### 👥 Code Ownership\n\n` + - `Hey there @${prAuthor},\n` + - `Thanks for submitting this pull request! Can you add yourself as a codeowner for this integration? ` + - `This way we can notify you if a bug report for this integration is reported.\n\n` + - `In \`__init__.py\` of the integration, please add:\n\n` + - `\`\`\`python\nCODEOWNERS = ["@${prAuthor}"]\n\`\`\`\n\n` + - `And run \`script/build_codeowners.py\``; - - messages.push(message); - } - - return messages; - } - - // Handle reviews - async function handleReviews(finalLabels, originalLabelCount) { - const reviewMessages = generateReviewMessages(finalLabels, originalLabelCount); - const hasReviewableLabels = finalLabels.some(label => - ['too-big', 'needs-codeowners'].includes(label) - ); - - const { data: reviews } = await github.rest.pulls.listReviews({ - owner, - repo, - pull_number: pr_number - }); - - const botReviews = reviews.filter(review => - review.user.type === 'Bot' && - review.state === 'CHANGES_REQUESTED' && - review.body && review.body.includes(BOT_COMMENT_MARKER) - ); - - if (hasReviewableLabels) { - const reviewBody = `${BOT_COMMENT_MARKER}\n\n${reviewMessages.join('\n\n---\n\n')}`; - - if (botReviews.length > 0) { - // Update existing review - await github.rest.pulls.updateReview({ - owner, - repo, - pull_number: pr_number, - review_id: botReviews[0].id, - body: reviewBody - }); - console.log('Updated existing bot review'); - } else { - // Create new review - await github.rest.pulls.createReview({ - owner, - repo, - pull_number: pr_number, - body: reviewBody, - event: 'REQUEST_CHANGES' - }); - console.log('Created new bot review'); - } - } else if (botReviews.length > 0) { - // Dismiss existing reviews - for (const review of botReviews) { - try { - await github.rest.pulls.dismissReview({ - owner, - repo, - pull_number: pr_number, - review_id: review.id, - message: 'Review dismissed: All requirements have been met' - }); - console.log(`Dismissed bot review ${review.id}`); - } catch (error) { - console.log(`Failed to dismiss review ${review.id}:`, error.message); - } - } - } - } - - // Main execution - const apiData = await fetchApiData(); - const baseRef = context.payload.pull_request.base.ref; - - // Early exit for release and beta branches only - if (baseRef === 'release' || baseRef === 'beta') { - const branchLabels = await detectMergeBranch(); - const finalLabels = Array.from(branchLabels); - - console.log('Computed labels (merge branch only):', finalLabels.join(', ')); - - // Apply labels - if (finalLabels.length > 0) { - await github.rest.issues.addLabels({ - owner, - repo, - issue_number: pr_number, - labels: finalLabels - }); - } - - // Remove old managed labels - const labelsToRemove = managedLabels.filter(label => !finalLabels.includes(label)); - for (const label of labelsToRemove) { - try { - await github.rest.issues.removeLabel({ - owner, - repo, - issue_number: pr_number, - name: label - }); - } catch (error) { - console.log(`Failed to remove label ${label}:`, error.message); - } - } - - return; - } - - // Run all strategies - const [ - branchLabels, - componentLabels, - newComponentLabels, - newPlatformLabels, - coreLabels, - sizeLabels, - dashboardLabels, - actionsLabels, - codeOwnerLabels, - testLabels, - checkboxLabels - ] = await Promise.all([ - detectMergeBranch(), - detectComponentPlatforms(apiData), - detectNewComponents(), - detectNewPlatforms(apiData), - detectCoreChanges(), - detectPRSize(), - detectDashboardChanges(), - detectGitHubActionsChanges(), - detectCodeOwner(), - detectTests(), - detectPRTemplateCheckboxes() - ]); - - // Combine all labels - const allLabels = new Set([ - ...branchLabels, - ...componentLabels, - ...newComponentLabels, - ...newPlatformLabels, - ...coreLabels, - ...sizeLabels, - ...dashboardLabels, - ...actionsLabels, - ...codeOwnerLabels, - ...testLabels, - ...checkboxLabels - ]); - - // Detect requirements based on all other labels - const requirementLabels = await detectRequirements(allLabels); - for (const label of requirementLabels) { - allLabels.add(label); - } - - let finalLabels = Array.from(allLabels); - - // For mega-PRs, exclude component labels if there are too many - if (isMegaPR) { - const componentLabels = finalLabels.filter(label => label.startsWith('component: ')); - if (componentLabels.length > COMPONENT_LABEL_THRESHOLD) { - finalLabels = finalLabels.filter(label => !label.startsWith('component: ')); - console.log(`Mega-PR detected - excluding ${componentLabels.length} component labels (threshold: ${COMPONENT_LABEL_THRESHOLD})`); - } - } - - // Handle too many labels (only for non-mega PRs) - const tooManyLabels = finalLabels.length > MAX_LABELS; - const originalLabelCount = finalLabels.length; - - if (tooManyLabels && !isMegaPR && !finalLabels.includes('too-big')) { - finalLabels = ['too-big']; - } - - console.log('Computed labels:', finalLabels.join(', ')); - - // Handle reviews - await handleReviews(finalLabels, originalLabelCount); - - // Apply labels - if (finalLabels.length > 0) { - console.log(`Adding labels: ${finalLabels.join(', ')}`); - await github.rest.issues.addLabels({ - owner, - repo, - issue_number: pr_number, - labels: finalLabels - }); - } - - // Remove old managed labels - const labelsToRemove = managedLabels.filter(label => !finalLabels.includes(label)); - for (const label of labelsToRemove) { - console.log(`Removing label: ${label}`); - try { - await github.rest.issues.removeLabel({ - owner, - repo, - issue_number: pr_number, - name: label - }); - } catch (error) { - console.log(`Failed to remove label ${label}:`, error.message); - } - } + const script = require('./.github/scripts/auto-label-pr/index.js'); + await script({ github, context }); From 03cfd87b163637fa225ce8da990394248a23c333 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 29 Jan 2026 07:44:21 +1100 Subject: [PATCH 0409/2030] [waveshare_epaper] Add deprecation message (#13583) --- esphome/components/waveshare_epaper/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/waveshare_epaper/__init__.py b/esphome/components/waveshare_epaper/__init__.py index c58ce8a01e..b410406a58 100644 --- a/esphome/components/waveshare_epaper/__init__.py +++ b/esphome/components/waveshare_epaper/__init__.py @@ -1 +1,6 @@ CODEOWNERS = ["@clydebarrow"] + +DEPRECATED_COMPONENT = """ +The 'waveshare_epaper' component is deprecated and no new models will be added to it. +New model PRs should target the newer and more performant 'epaper_spi' component. +""" From a382383d83d6d375e1b042dab2e13cde172f2b5a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 29 Jan 2026 10:08:45 +1100 Subject: [PATCH 0410/2030] [workflows] Add deprecation check (#13584) --- .github/scripts/auto-label-pr/constants.js | 2 + .github/scripts/auto-label-pr/detectors.js | 71 ++++++++++++++++++++++ .github/scripts/auto-label-pr/index.js | 10 ++- .github/scripts/auto-label-pr/reviews.js | 25 ++++++-- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/.github/scripts/auto-label-pr/constants.js b/.github/scripts/auto-label-pr/constants.js index d5e42fa1b9..bd60d8c766 100644 --- a/.github/scripts/auto-label-pr/constants.js +++ b/.github/scripts/auto-label-pr/constants.js @@ -3,6 +3,7 @@ module.exports = { BOT_COMMENT_MARKER: '', CODEOWNERS_MARKER: '', TOO_BIG_MARKER: '', + DEPRECATED_COMPONENT_MARKER: '', MANAGED_LABELS: [ 'new-component', @@ -27,6 +28,7 @@ module.exports = { 'breaking-change', 'developer-breaking-change', 'code-quality', + 'deprecated-component' ], DOCS_PR_PATTERNS: [ diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index 79025988dd..f502a85666 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -251,6 +251,76 @@ async function detectPRTemplateCheckboxes(context) { return labels; } +// Strategy: Deprecated component detection +async function detectDeprecatedComponents(github, context, changedFiles) { + const labels = new Set(); + const deprecatedInfo = []; + const { owner, repo } = context.repo; + + // Compile regex once for better performance + const componentFileRegex = /^esphome\/components\/([^\/]+)\//; + + // Get files that are modified or added in components directory + const componentFiles = changedFiles.filter(file => componentFileRegex.test(file)); + + if (componentFiles.length === 0) { + return { labels, deprecatedInfo }; + } + + // Extract unique component names using the same regex + const components = new Set(); + for (const file of componentFiles) { + const match = file.match(componentFileRegex); + if (match) { + components.add(match[1]); + } + } + + // Get PR head to fetch files from the PR branch + const prNumber = context.payload.pull_request.number; + + // Check each component's __init__.py for DEPRECATED_COMPONENT constant + for (const component of components) { + const initFile = `esphome/components/${component}/__init__.py`; + try { + // Fetch file content from PR head using GitHub API + const { data: fileData } = await github.rest.repos.getContent({ + owner, + repo, + path: initFile, + ref: `refs/pull/${prNumber}/head` + }); + + // Decode base64 content + const content = Buffer.from(fileData.content, 'base64').toString('utf8'); + + // Look for DEPRECATED_COMPONENT = "message" or DEPRECATED_COMPONENT = 'message' + // Support single quotes, double quotes, and triple quotes (for multiline) + const doubleQuoteMatch = content.match(/DEPRECATED_COMPONENT\s*=\s*"""([\s\S]*?)"""/s) || + content.match(/DEPRECATED_COMPONENT\s*=\s*"((?:[^"\\]|\\.)*)"/); + const singleQuoteMatch = content.match(/DEPRECATED_COMPONENT\s*=\s*'''([\s\S]*?)'''/s) || + content.match(/DEPRECATED_COMPONENT\s*=\s*'((?:[^'\\]|\\.)*)'/); + const deprecatedMatch = doubleQuoteMatch || singleQuoteMatch; + + if (deprecatedMatch) { + labels.add('deprecated-component'); + deprecatedInfo.push({ + component: component, + message: deprecatedMatch[1].trim() + }); + console.log(`Found deprecated component: ${component}`); + } + } catch (error) { + // Only log if it's not a simple "file not found" error (404) + if (error.status !== 404) { + console.log(`Error reading ${initFile}:`, error.message); + } + } + } + + return { labels, deprecatedInfo }; +} + // Strategy: Requirements detection async function detectRequirements(allLabels, prFiles, context) { const labels = new Set(); @@ -298,5 +368,6 @@ module.exports = { detectCodeOwner, detectTests, detectPRTemplateCheckboxes, + detectDeprecatedComponents, detectRequirements }; diff --git a/.github/scripts/auto-label-pr/index.js b/.github/scripts/auto-label-pr/index.js index 95ecfc4e33..483d2cb626 100644 --- a/.github/scripts/auto-label-pr/index.js +++ b/.github/scripts/auto-label-pr/index.js @@ -11,6 +11,7 @@ const { detectCodeOwner, detectTests, detectPRTemplateCheckboxes, + detectDeprecatedComponents, detectRequirements } = require('./detectors'); const { handleReviews } = require('./reviews'); @@ -112,6 +113,7 @@ module.exports = async ({ github, context }) => { codeOwnerLabels, testLabels, checkboxLabels, + deprecatedResult ] = await Promise.all([ detectMergeBranch(context), detectComponentPlatforms(changedFiles, apiData), @@ -124,8 +126,13 @@ module.exports = async ({ github, context }) => { detectCodeOwner(github, context, changedFiles), detectTests(changedFiles), detectPRTemplateCheckboxes(context), + detectDeprecatedComponents(github, context, changedFiles) ]); + // Extract deprecated component info + const deprecatedLabels = deprecatedResult.labels; + const deprecatedInfo = deprecatedResult.deprecatedInfo; + // Combine all labels const allLabels = new Set([ ...branchLabels, @@ -139,6 +146,7 @@ module.exports = async ({ github, context }) => { ...codeOwnerLabels, ...testLabels, ...checkboxLabels, + ...deprecatedLabels ]); // Detect requirements based on all other labels @@ -169,7 +177,7 @@ module.exports = async ({ github, context }) => { console.log('Computed labels:', finalLabels.join(', ')); // Handle reviews - await handleReviews(github, context, finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD); + await handleReviews(github, context, finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD); // Apply labels await applyLabels(github, context, finalLabels); diff --git a/.github/scripts/auto-label-pr/reviews.js b/.github/scripts/auto-label-pr/reviews.js index a84e9ae5aa..906e2c456a 100644 --- a/.github/scripts/auto-label-pr/reviews.js +++ b/.github/scripts/auto-label-pr/reviews.js @@ -2,12 +2,29 @@ const { BOT_COMMENT_MARKER, CODEOWNERS_MARKER, TOO_BIG_MARKER, + DEPRECATED_COMPONENT_MARKER } = require('./constants'); // Generate review messages -function generateReviewMessages(finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD) { +function generateReviewMessages(finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD) { const messages = []; + // Deprecated component message + if (finalLabels.includes('deprecated-component') && deprecatedInfo && deprecatedInfo.length > 0) { + let message = `${DEPRECATED_COMPONENT_MARKER}\n### ⚠️ Deprecated Component\n\n`; + message += `Hey there @${prAuthor},\n`; + message += `This PR modifies one or more deprecated components. Please be aware:\n\n`; + + for (const info of deprecatedInfo) { + message += `#### Component: \`${info.component}\`\n`; + message += `${info.message}\n\n`; + } + + message += `Consider migrating to the recommended alternative if applicable.`; + + messages.push(message); + } + // Too big message if (finalLabels.includes('too-big')) { const testAdditions = prFiles @@ -54,14 +71,14 @@ function generateReviewMessages(finalLabels, originalLabelCount, prFiles, totalA } // Handle reviews -async function handleReviews(github, context, finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD) { +async function handleReviews(github, context, finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, MAX_LABELS, TOO_BIG_THRESHOLD) { const { owner, repo } = context.repo; const pr_number = context.issue.number; const prAuthor = context.payload.pull_request.user.login; - const reviewMessages = generateReviewMessages(finalLabels, originalLabelCount, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD); + const reviewMessages = generateReviewMessages(finalLabels, originalLabelCount, deprecatedInfo, prFiles, totalAdditions, totalDeletions, prAuthor, MAX_LABELS, TOO_BIG_THRESHOLD); const hasReviewableLabels = finalLabels.some(label => - ['too-big', 'needs-codeowners'].includes(label) + ['too-big', 'needs-codeowners', 'deprecated-component'].includes(label) ); const { data: reviews } = await github.rest.pulls.listReviews({ From a5f60750c244cc00d2e38064e7fa4b5d930f1358 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 17:07:41 -1000 Subject: [PATCH 0411/2030] [tx20] Eliminate heap allocations in wind sensor (#13298) --- esphome/components/tx20/tx20.cpp | 46 +++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/esphome/components/tx20/tx20.cpp b/esphome/components/tx20/tx20.cpp index fd7b5fb03f..a6df61c053 100644 --- a/esphome/components/tx20/tx20.cpp +++ b/esphome/components/tx20/tx20.cpp @@ -2,7 +2,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include +#include namespace esphome { namespace tx20 { @@ -45,25 +45,25 @@ std::string Tx20Component::get_wind_cardinal_direction() const { return this->wi void Tx20Component::decode_and_publish_() { ESP_LOGVV(TAG, "Decode Tx20"); - std::string string_buffer; - std::string string_buffer_2; - std::vector bit_buffer; + std::array bit_buffer{}; + size_t bit_pos = 0; bool current_bit = true; + // Cap at MAX_BUFFER_SIZE - 1 to prevent out-of-bounds access (buffer_index can exceed MAX_BUFFER_SIZE in ISR) + const int max_buffer_index = + std::min(static_cast(this->store_.buffer_index), static_cast(MAX_BUFFER_SIZE - 1)); - for (int i = 1; i <= this->store_.buffer_index; i++) { - string_buffer_2 += to_string(this->store_.buffer[i]) + ", "; + for (int i = 1; i <= max_buffer_index; i++) { uint8_t repeat = this->store_.buffer[i] / TX20_BIT_TIME; // ignore segments at the end that were too short - string_buffer.append(repeat, current_bit ? '1' : '0'); - bit_buffer.insert(bit_buffer.end(), repeat, current_bit); + for (uint8_t j = 0; j < repeat && bit_pos < MAX_BUFFER_SIZE; j++) { + bit_buffer[bit_pos++] = current_bit; + } current_bit = !current_bit; } current_bit = !current_bit; - if (string_buffer.length() < MAX_BUFFER_SIZE) { - uint8_t remain = MAX_BUFFER_SIZE - string_buffer.length(); - string_buffer_2 += to_string(remain) + ", "; - string_buffer.append(remain, current_bit ? '1' : '0'); - bit_buffer.insert(bit_buffer.end(), remain, current_bit); + size_t bits_before_padding = bit_pos; + while (bit_pos < MAX_BUFFER_SIZE) { + bit_buffer[bit_pos++] = current_bit; } uint8_t tx20_sa = 0; @@ -108,8 +108,24 @@ void Tx20Component::decode_and_publish_() { // 2. Check received checksum matches calculated checksum // 3. Check that Wind Direction matches Wind Direction (Inverted) // 4. Check that Wind Speed matches Wind Speed (Inverted) - ESP_LOGVV(TAG, "BUFFER %s", string_buffer_2.c_str()); - ESP_LOGVV(TAG, "Decoded bits %s", string_buffer.c_str()); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + // Build debug strings from completed data + char debug_buf[320]; // buffer values: max 40 entries * 7 chars each + size_t debug_pos = 0; + for (int i = 1; i <= max_buffer_index; i++) { + debug_pos = buf_append_printf(debug_buf, sizeof(debug_buf), debug_pos, "%u, ", this->store_.buffer[i]); + } + if (bits_before_padding < MAX_BUFFER_SIZE) { + buf_append_printf(debug_buf, sizeof(debug_buf), debug_pos, "%zu, ", MAX_BUFFER_SIZE - bits_before_padding); + } + char bits_buf[MAX_BUFFER_SIZE + 1]; + for (size_t i = 0; i < MAX_BUFFER_SIZE; i++) { + bits_buf[i] = bit_buffer[i] ? '1' : '0'; + } + bits_buf[MAX_BUFFER_SIZE] = '\0'; + ESP_LOGVV(TAG, "BUFFER %s", debug_buf); + ESP_LOGVV(TAG, "Decoded bits %s", bits_buf); +#endif if (tx20_sa == 4) { if (chk == tx20_sd) { From 084113926cbb1ac70bc4cb758b86798e760256bb Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 28 Jan 2026 22:03:50 -0600 Subject: [PATCH 0412/2030] [es8156] Add `bits_per_sample` validation, comment code (#13612) --- esphome/components/es8156/audio_dac.py | 28 ++++++++++++++++++- esphome/components/es8156/es8156.cpp | 37 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/esphome/components/es8156/audio_dac.py b/esphome/components/es8156/audio_dac.py index b9d8eae6b0..a805fb3f70 100644 --- a/esphome/components/es8156/audio_dac.py +++ b/esphome/components/es8156/audio_dac.py @@ -2,11 +2,14 @@ import esphome.codegen as cg from esphome.components import i2c from esphome.components.audio_dac import AudioDac import esphome.config_validation as cv -from esphome.const import CONF_ID +from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID +import esphome.final_validate as fv CODEOWNERS = ["@kbx81"] DEPENDENCIES = ["i2c"] +CONF_AUDIO_DAC = "audio_dac" + es8156_ns = cg.esphome_ns.namespace("es8156") ES8156 = es8156_ns.class_("ES8156", AudioDac, cg.Component, i2c.I2CDevice) @@ -21,6 +24,29 @@ CONFIG_SCHEMA = ( ) +def _final_validate(config): + full_config = fv.full_config.get() + + # Check all speaker configurations for ones that reference this es8156 + speaker_configs = full_config.get("speaker", []) + for speaker_config in speaker_configs: + audio_dac_id = speaker_config.get(CONF_AUDIO_DAC) + if ( + audio_dac_id is not None + and audio_dac_id == config[CONF_ID] + and (bits_per_sample := speaker_config.get(CONF_BITS_PER_SAMPLE)) + is not None + and bits_per_sample > 24 + ): + raise cv.Invalid( + f"ES8156 does not support more than 24 bits per sample. " + f"The speaker referencing this audio_dac has bits_per_sample set to {bits_per_sample}." + ) + + +FINAL_VALIDATE_SCHEMA = _final_validate + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/es8156/es8156.cpp b/esphome/components/es8156/es8156.cpp index e84252efe2..961dc24b29 100644 --- a/esphome/components/es8156/es8156.cpp +++ b/esphome/components/es8156/es8156.cpp @@ -17,24 +17,61 @@ static const char *const TAG = "es8156"; } void ES8156::setup() { + // REG02 MODE CONFIG 1: Enable software mode for I2C control of volume/mute + // Bit 2: SOFT_MODE_SEL=1 (software mode enabled) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG02_SCLK_MODE, 0x04)); + + // Analog system configuration (active-low power down bits, active-high enables) + // REG20 ANALOG SYSTEM: Configure analog signal path ES8156_ERROR_FAILED(this->write_byte(ES8156_REG20_ANALOG_SYS1, 0x2A)); + + // REG21 ANALOG SYSTEM: VSEL=0x1C (bias level ~120%), normal VREF ramp speed ES8156_ERROR_FAILED(this->write_byte(ES8156_REG21_ANALOG_SYS2, 0x3C)); + + // REG22 ANALOG SYSTEM: Line out mode (HPSW=0), OUT_MUTE=0 (not muted) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG22_ANALOG_SYS3, 0x00)); + + // REG24 ANALOG SYSTEM: Low power mode for VREFBUF, HPCOM, DACVRP; DAC normal power + // Bits 2:0 = 0x07: LPVREFBUF=1, LPHPCOM=1, LPDACVRP=1, LPDAC=0 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG24_ANALOG_LP, 0x07)); + + // REG23 ANALOG SYSTEM: Lowest bias (IBIAS_SW=0), VMIDLVL=VDDA/2, normal impedance ES8156_ERROR_FAILED(this->write_byte(ES8156_REG23_ANALOG_SYS4, 0x00)); + // Timing and interface configuration + // REG0A/0B TIME CONTROL: Fast state machine transitions ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0A_TIME_CONTROL1, 0x01)); ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0B_TIME_CONTROL2, 0x01)); + + // REG11 SDP INTERFACE CONFIG: Default I2S format (24-bit, I2S mode) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG11_DAC_SDP, 0x00)); + + // REG19 EQ CONTROL 1: EQ disabled (EQ_ON=0), EQ_BAND_NUM=2 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG19_EQ_CONTROL1, 0x20)); + // REG0D P2S CONTROL: Parallel-to-serial converter settings ES8156_ERROR_FAILED(this->write_byte(ES8156_REG0D_P2S_CONTROL, 0x14)); + + // REG09 MISC CONTROL 2: Default settings ES8156_ERROR_FAILED(this->write_byte(ES8156_REG09_MISC_CONTROL2, 0x00)); + + // REG18 MISC CONTROL 3: Stereo channel routing, no inversion + // Bits 5:4 CHN_CROSS: 0=L→L/R→R, 1=L to both, 2=R to both, 3=swap L/R + // Bits 3:2: LCH_INV/RCH_INV channel inversion ES8156_ERROR_FAILED(this->write_byte(ES8156_REG18_MISC_CONTROL3, 0x00)); + + // REG08 CLOCK OFF: Enable all internal clocks (0x3F = all clock gates open) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG08_CLOCK_ON_OFF, 0x3F)); + + // REG00 RESET CONTROL: Reset sequence + // First: RST_DIG=1 (assert digital reset) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x02)); + // Then: CSM_ON=1 (enable chip state machine), RST_DIG=1 ES8156_ERROR_FAILED(this->write_byte(ES8156_REG00_RESET, 0x03)); + + // REG25 ANALOG SYSTEM: Power up analog blocks + // VMIDSEL=2 (normal VMID operation), PDN_ANA=0, ENREFR=0, ENHPCOM=0 + // PDN_DACVREFGEN=0, PDN_VREFBUF=0, PDN_DAC=0 (all enabled) ES8156_ERROR_FAILED(this->write_byte(ES8156_REG25_ANALOG_SYS5, 0x20)); } From 3e9a6c582ee9ba8b74568c1deed35c96ed1162a2 Mon Sep 17 00:00:00 2001 From: rwrozelle Date: Wed, 28 Jan 2026 23:16:59 -0500 Subject: [PATCH 0413/2030] [mdns] Do not broadcast registration when using openthread component (#13592) --- esphome/components/mdns/mdns_esp32.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/mdns/mdns_esp32.cpp b/esphome/components/mdns/mdns_esp32.cpp index 3123f3b604..3e997402bc 100644 --- a/esphome/components/mdns/mdns_esp32.cpp +++ b/esphome/components/mdns/mdns_esp32.cpp @@ -12,6 +12,10 @@ namespace esphome::mdns { static const char *const TAG = "mdns"; static void register_esp32(MDNSComponent *comp, StaticVector &services) { +#ifdef USE_OPENTHREAD + // OpenThread handles service registration via SRP client + // Services are compiled by MDNSComponent::compile_records_() and consumed by OpenThreadSrpComponent +#else esp_err_t err = mdns_init(); if (err != ESP_OK) { ESP_LOGW(TAG, "Init failed: %s", esp_err_to_name(err)); @@ -41,13 +45,16 @@ static void register_esp32(MDNSComponent *comp, StaticVectorsetup_buffers_and_register_(register_esp32); } void MDNSComponent::on_shutdown() { +#ifndef USE_OPENTHREAD mdns_free(); delay(40); // Allow the mdns packets announcing service removal to be sent +#endif } } // namespace esphome::mdns From 74c84c874721806603cd9a2c9f18968bbbe25ed1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 18:20:39 -1000 Subject: [PATCH 0414/2030] [esp32] Add advanced sdkconfig options to reduce build time and binary size (#13611) --- esphome/components/esp32/__init__.py | 116 ++++++++++++++++++ tests/components/esp32/test.esp32-idf.yaml | 8 ++ tests/components/esp32/test.esp32-p4-idf.yaml | 8 ++ tests/components/esp32/test.esp32-s3-idf.yaml | 8 ++ 4 files changed, 140 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index fccf0ed09f..4e425792dc 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -672,11 +672,25 @@ CONF_RINGBUF_IN_IRAM = "ringbuf_in_iram" CONF_HEAP_IN_IRAM = "heap_in_iram" CONF_LOOP_TASK_STACK_SIZE = "loop_task_stack_size" CONF_USE_FULL_CERTIFICATE_BUNDLE = "use_full_certificate_bundle" +CONF_DISABLE_DEBUG_STUBS = "disable_debug_stubs" +CONF_DISABLE_OCD_AWARE = "disable_ocd_aware" +CONF_DISABLE_USB_SERIAL_JTAG_SECONDARY = "disable_usb_serial_jtag_secondary" +CONF_DISABLE_DEV_NULL_VFS = "disable_dev_null_vfs" +CONF_DISABLE_MBEDTLS_PEER_CERT = "disable_mbedtls_peer_cert" +CONF_DISABLE_MBEDTLS_PKCS7 = "disable_mbedtls_pkcs7" +CONF_DISABLE_REGI2C_IN_IRAM = "disable_regi2c_in_iram" +CONF_DISABLE_FATFS = "disable_fatfs" # VFS requirement tracking # Components that need VFS features can call require_vfs_select() or require_vfs_dir() KEY_VFS_SELECT_REQUIRED = "vfs_select_required" KEY_VFS_DIR_REQUIRED = "vfs_dir_required" +# Feature requirement tracking - components can call require_* functions to re-enable +# These are stored in CORE.data[KEY_ESP32] dict +KEY_USB_SERIAL_JTAG_SECONDARY_REQUIRED = "usb_serial_jtag_secondary_required" +KEY_MBEDTLS_PEER_CERT_REQUIRED = "mbedtls_peer_cert_required" +KEY_MBEDTLS_PKCS7_REQUIRED = "mbedtls_pkcs7_required" +KEY_FATFS_REQUIRED = "fatfs_required" def require_vfs_select() -> None: @@ -709,6 +723,43 @@ def require_full_certificate_bundle() -> None: CORE.data[KEY_ESP32][KEY_FULL_CERT_BUNDLE] = True +def require_usb_serial_jtag_secondary() -> None: + """Mark that USB Serial/JTAG secondary console is required by a component. + + Call this from components (e.g., logger) that need USB Serial/JTAG console output. + This prevents CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG from being disabled. + """ + CORE.data[KEY_ESP32][KEY_USB_SERIAL_JTAG_SECONDARY_REQUIRED] = True + + +def require_mbedtls_peer_cert() -> None: + """Mark that mbedTLS peer certificate retention is required by a component. + + Call this from components that need access to the peer certificate after + the TLS handshake is complete. This prevents CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + from being disabled. + """ + CORE.data[KEY_ESP32][KEY_MBEDTLS_PEER_CERT_REQUIRED] = True + + +def require_mbedtls_pkcs7() -> None: + """Mark that mbedTLS PKCS#7 support is required by a component. + + Call this from components that need PKCS#7 certificate validation. + This prevents CONFIG_MBEDTLS_PKCS7_C from being disabled. + """ + CORE.data[KEY_ESP32][KEY_MBEDTLS_PKCS7_REQUIRED] = True + + +def require_fatfs() -> None: + """Mark that FATFS support is required by a component. + + Call this from components that use FATFS (e.g., SD card, storage components). + This prevents FATFS from being disabled when disable_fatfs is set. + """ + CORE.data[KEY_ESP32][KEY_FATFS_REQUIRED] = True + + def _parse_idf_component(value: str) -> ConfigType: """Parse IDF component shorthand syntax like 'owner/component^version'""" # Match operator followed by version-like string (digit or *) @@ -793,6 +844,16 @@ FRAMEWORK_SCHEMA = cv.Schema( cv.Optional( CONF_USE_FULL_CERTIFICATE_BUNDLE, default=False ): cv.boolean, + cv.Optional(CONF_DISABLE_DEBUG_STUBS, default=True): cv.boolean, + cv.Optional(CONF_DISABLE_OCD_AWARE, default=True): cv.boolean, + cv.Optional( + CONF_DISABLE_USB_SERIAL_JTAG_SECONDARY, default=True + ): cv.boolean, + cv.Optional(CONF_DISABLE_DEV_NULL_VFS, default=True): cv.boolean, + cv.Optional(CONF_DISABLE_MBEDTLS_PEER_CERT, default=True): cv.boolean, + cv.Optional(CONF_DISABLE_MBEDTLS_PKCS7, default=True): cv.boolean, + cv.Optional(CONF_DISABLE_REGI2C_IN_IRAM, default=True): cv.boolean, + cv.Optional(CONF_DISABLE_FATFS, default=True): cv.boolean, } ), cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list( @@ -1316,6 +1377,61 @@ async def to_code(config): add_idf_sdkconfig_option(f"CONFIG_LOG_DEFAULT_LEVEL_{conf[CONF_LOG_LEVEL]}", True) + # Disable OpenOCD debug stubs to save code size + # These are used for on-chip debugging with OpenOCD/JTAG, rarely needed for ESPHome + if advanced[CONF_DISABLE_DEBUG_STUBS]: + add_idf_sdkconfig_option("CONFIG_ESP_DEBUG_STUBS_ENABLE", False) + + # Disable OCD-aware exception handlers + # When enabled, the panic handler detects JTAG debugger and halts instead of resetting + # Most ESPHome users don't use JTAG debugging + if advanced[CONF_DISABLE_OCD_AWARE]: + add_idf_sdkconfig_option("CONFIG_ESP_DEBUG_OCDAWARE", False) + + # Disable USB Serial/JTAG secondary console + # Components like logger can call require_usb_serial_jtag_secondary() to re-enable + if CORE.data[KEY_ESP32].get(KEY_USB_SERIAL_JTAG_SECONDARY_REQUIRED, False): + add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG", True) + elif advanced[CONF_DISABLE_USB_SERIAL_JTAG_SECONDARY]: + add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_SECONDARY_NONE", True) + + # Disable /dev/null VFS initialization + # ESPHome doesn't typically need /dev/null + if advanced[CONF_DISABLE_DEV_NULL_VFS]: + add_idf_sdkconfig_option("CONFIG_VFS_INITIALIZE_DEV_NULL", False) + + # Disable keeping peer certificate after TLS handshake + # Saves ~4KB heap per connection, but prevents certificate inspection after handshake + # Components that need it can call require_mbedtls_peer_cert() + if CORE.data[KEY_ESP32].get(KEY_MBEDTLS_PEER_CERT_REQUIRED, False): + add_idf_sdkconfig_option("CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", True) + elif advanced[CONF_DISABLE_MBEDTLS_PEER_CERT]: + add_idf_sdkconfig_option("CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", False) + + # Disable PKCS#7 support in mbedTLS + # Only needed for specific certificate validation scenarios + # Components that need it can call require_mbedtls_pkcs7() + if CORE.data[KEY_ESP32].get(KEY_MBEDTLS_PKCS7_REQUIRED, False): + # Component called require_mbedtls_pkcs7() - enable regardless of user setting + add_idf_sdkconfig_option("CONFIG_MBEDTLS_PKCS7_C", True) + elif advanced[CONF_DISABLE_MBEDTLS_PKCS7]: + add_idf_sdkconfig_option("CONFIG_MBEDTLS_PKCS7_C", False) + + # Disable regi2c control functions in IRAM + # Only needed if using analog peripherals (ADC, DAC, etc.) from ISRs while cache is disabled + if advanced[CONF_DISABLE_REGI2C_IN_IRAM]: + add_idf_sdkconfig_option("CONFIG_ESP_REGI2C_CTRL_FUNC_IN_IRAM", False) + + # Disable FATFS support + # Components that need FATFS (SD card, etc.) can call require_fatfs() + if CORE.data[KEY_ESP32].get(KEY_FATFS_REQUIRED, False): + # Component called require_fatfs() - enable regardless of user setting + add_idf_sdkconfig_option("CONFIG_FATFS_LFN_NONE", False) + add_idf_sdkconfig_option("CONFIG_FATFS_VOLUME_COUNT", 2) + elif advanced[CONF_DISABLE_FATFS]: + add_idf_sdkconfig_option("CONFIG_FATFS_LFN_NONE", True) + add_idf_sdkconfig_option("CONFIG_FATFS_VOLUME_COUNT", 0) + for name, value in conf[CONF_SDKCONFIG_OPTIONS].items(): add_idf_sdkconfig_option(name, RawSdkconfigValue(value)) diff --git a/tests/components/esp32/test.esp32-idf.yaml b/tests/components/esp32/test.esp32-idf.yaml index d38cdfe2fd..d4ab6b4a87 100644 --- a/tests/components/esp32/test.esp32-idf.yaml +++ b/tests/components/esp32/test.esp32-idf.yaml @@ -8,6 +8,14 @@ esp32: enable_lwip_bridge_interface: true disable_libc_locks_in_iram: false # Test explicit opt-out of RAM optimization use_full_certificate_bundle: false # Test CMN bundle (default) + disable_debug_stubs: true + disable_ocd_aware: true + disable_usb_serial_jtag_secondary: true + disable_dev_null_vfs: true + disable_mbedtls_peer_cert: true + disable_mbedtls_pkcs7: true + disable_regi2c_in_iram: true + disable_fatfs: true wifi: ssid: MySSID diff --git a/tests/components/esp32/test.esp32-p4-idf.yaml b/tests/components/esp32/test.esp32-p4-idf.yaml index 00a4ceec27..d67787b3d5 100644 --- a/tests/components/esp32/test.esp32-p4-idf.yaml +++ b/tests/components/esp32/test.esp32-p4-idf.yaml @@ -10,6 +10,14 @@ esp32: ref: 2.7.0 advanced: enable_idf_experimental_features: yes + disable_debug_stubs: true + disable_ocd_aware: true + disable_usb_serial_jtag_secondary: true + disable_dev_null_vfs: true + disable_mbedtls_peer_cert: true + disable_mbedtls_pkcs7: true + disable_regi2c_in_iram: true + disable_fatfs: true ota: platform: esphome diff --git a/tests/components/esp32/test.esp32-s3-idf.yaml b/tests/components/esp32/test.esp32-s3-idf.yaml index 4ae5e6b999..7a3bbe55b3 100644 --- a/tests/components/esp32/test.esp32-s3-idf.yaml +++ b/tests/components/esp32/test.esp32-s3-idf.yaml @@ -5,6 +5,14 @@ esp32: advanced: execute_from_psram: true disable_libc_locks_in_iram: true # Test default RAM optimization enabled + disable_debug_stubs: true + disable_ocd_aware: true + disable_usb_serial_jtag_secondary: true + disable_dev_null_vfs: true + disable_mbedtls_peer_cert: true + disable_mbedtls_pkcs7: true + disable_regi2c_in_iram: true + disable_fatfs: true psram: mode: octal From 0843ec6ae8c9fc94ef61b54abc6fd03054460157 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Wed, 28 Jan 2026 22:39:40 -0600 Subject: [PATCH 0415/2030] [const] Move `CONF_AUDIO_DAC` (#13614) --- esphome/components/es8156/audio_dac.py | 4 +--- esphome/components/speaker/__init__.py | 4 +--- esphome/const.py | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/esphome/components/es8156/audio_dac.py b/esphome/components/es8156/audio_dac.py index a805fb3f70..c5fb6096da 100644 --- a/esphome/components/es8156/audio_dac.py +++ b/esphome/components/es8156/audio_dac.py @@ -2,14 +2,12 @@ import esphome.codegen as cg from esphome.components import i2c from esphome.components.audio_dac import AudioDac import esphome.config_validation as cv -from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID +from esphome.const import CONF_AUDIO_DAC, CONF_BITS_PER_SAMPLE, CONF_ID import esphome.final_validate as fv CODEOWNERS = ["@kbx81"] DEPENDENCIES = ["i2c"] -CONF_AUDIO_DAC = "audio_dac" - es8156_ns = cg.esphome_ns.namespace("es8156") ES8156 = es8156_ns.class_("ES8156", AudioDac, cg.Component, i2c.I2CDevice) diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index 18e1d9782c..10ee6d5212 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -2,7 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import audio, audio_dac import esphome.config_validation as cv -from esphome.const import CONF_DATA, CONF_ID, CONF_VOLUME +from esphome.const import CONF_AUDIO_DAC, CONF_DATA, CONF_ID, CONF_VOLUME from esphome.core import CORE, ID from esphome.coroutine import CoroPriority, coroutine_with_priority @@ -11,8 +11,6 @@ CODEOWNERS = ["@jesserockz", "@kahrendt"] IS_PLATFORM_COMPONENT = True -CONF_AUDIO_DAC = "audio_dac" - speaker_ns = cg.esphome_ns.namespace("speaker") Speaker = speaker_ns.class_("Speaker") diff --git a/esphome/const.py b/esphome/const.py index 4243b2e25d..4bf47b8f83 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -149,6 +149,7 @@ CONF_ASSUMED_STATE = "assumed_state" CONF_AT = "at" CONF_ATTENUATION = "attenuation" CONF_ATTRIBUTE = "attribute" +CONF_AUDIO_DAC = "audio_dac" CONF_AUTH = "auth" CONF_AUTO_CLEAR_ENABLED = "auto_clear_enabled" CONF_AUTO_MODE = "auto_mode" From 6a17db885764f4bbb0439a28ca3d6ae3023796d1 Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Thu, 29 Jan 2026 17:52:46 +0100 Subject: [PATCH 0416/2030] [nrf52,zigbee] Support for number component (#13581) --- esphome/components/number/__init__.py | 6 +- esphome/components/zigbee/__init__.py | 27 +++- esphome/components/zigbee/const_zephyr.py | 3 + .../zigbee/zigbee_number_zephyr.cpp | 111 ++++++++++++++++ .../components/zigbee/zigbee_number_zephyr.h | 118 ++++++++++++++++++ .../zigbee/zigbee_switch_zephyr.cpp | 2 +- esphome/components/zigbee/zigbee_zephyr.cpp | 4 +- esphome/components/zigbee/zigbee_zephyr.h | 6 + esphome/components/zigbee/zigbee_zephyr.py | 51 ++++++++ tests/components/zigbee/common.yaml | 10 +- 10 files changed, 331 insertions(+), 7 deletions(-) create mode 100644 esphome/components/zigbee/zigbee_number_zephyr.cpp create mode 100644 esphome/components/zigbee/zigbee_number_zephyr.h diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 368b431d7b..b23da7799f 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -1,6 +1,6 @@ from esphome import automation import esphome.codegen as cg -from esphome.components import mqtt, web_server +from esphome.components import mqtt, web_server, zigbee import esphome.config_validation as cv from esphome.const import ( CONF_ABOVE, @@ -189,6 +189,7 @@ validate_unit_of_measurement = cv.string_strict _NUMBER_SCHEMA = ( cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) + .extend(zigbee.NUMBER_SCHEMA) .extend( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTNumberComponent), @@ -214,6 +215,7 @@ _NUMBER_SCHEMA = ( _NUMBER_SCHEMA.add_extra(entity_duplicate_validator("number")) +_NUMBER_SCHEMA.add_extra(zigbee.validate_number) def number_schema( @@ -277,6 +279,8 @@ async def setup_number_core_( if web_server_config := config.get(CONF_WEB_SERVER): await web_server.add_entity_config(var, web_server_config) + await zigbee.setup_number(var, config, min_value, max_value, step) + async def register_number( var, config, *, min_value: float, max_value: float, step: float diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 1b1da78308..c044148b32 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -24,7 +24,12 @@ from .const_zephyr import ( ZigbeeComponent, zigbee_ns, ) -from .zigbee_zephyr import zephyr_binary_sensor, zephyr_sensor, zephyr_switch +from .zigbee_zephyr import ( + zephyr_binary_sensor, + zephyr_number, + zephyr_sensor, + zephyr_switch, +) _LOGGER = logging.getLogger(__name__) @@ -43,6 +48,7 @@ def zigbee_set_core_data(config: ConfigType) -> ConfigType: BINARY_SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_binary_sensor) SENSOR_SCHEMA = cv.Schema({}).extend(zephyr_sensor) SWITCH_SCHEMA = cv.Schema({}).extend(zephyr_switch) +NUMBER_SCHEMA = cv.Schema({}).extend(zephyr_number) CONFIG_SCHEMA = cv.All( cv.Schema( @@ -125,6 +131,21 @@ async def setup_switch(entity: cg.MockObj, config: ConfigType) -> None: await zephyr_setup_switch(entity, config) +async def setup_number( + entity: cg.MockObj, + config: ConfigType, + min_value: float, + max_value: float, + step: float, +) -> None: + if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): + return + if CORE.using_zephyr: + from .zigbee_zephyr import zephyr_setup_number + + await zephyr_setup_number(entity, config, min_value, max_value, step) + + def consume_endpoint(config: ConfigType) -> ConfigType: if not config.get(CONF_ZIGBEE_ID) or config.get(CONF_INTERNAL): return config @@ -152,6 +173,10 @@ def validate_switch(config: ConfigType) -> ConfigType: return consume_endpoint(config) +def validate_number(config: ConfigType) -> ConfigType: + return consume_endpoint(config) + + ZIGBEE_ACTION_SCHEMA = automation.maybe_simple_id( cv.Schema( { diff --git a/esphome/components/zigbee/const_zephyr.py b/esphome/components/zigbee/const_zephyr.py index 03c1bb546f..2d233755ac 100644 --- a/esphome/components/zigbee/const_zephyr.py +++ b/esphome/components/zigbee/const_zephyr.py @@ -4,6 +4,7 @@ zigbee_ns = cg.esphome_ns.namespace("zigbee") ZigbeeComponent = zigbee_ns.class_("ZigbeeComponent", cg.Component) BinaryAttrs = zigbee_ns.struct("BinaryAttrs") AnalogAttrs = zigbee_ns.struct("AnalogAttrs") +AnalogAttrsOutput = zigbee_ns.struct("AnalogAttrsOutput") CONF_MAX_EP_NUMBER = 8 CONF_ZIGBEE_ID = "zigbee_id" @@ -12,6 +13,7 @@ CONF_WIPE_ON_BOOT = "wipe_on_boot" CONF_ZIGBEE_BINARY_SENSOR = "zigbee_binary_sensor" CONF_ZIGBEE_SENSOR = "zigbee_sensor" CONF_ZIGBEE_SWITCH = "zigbee_switch" +CONF_ZIGBEE_NUMBER = "zigbee_number" CONF_POWER_SOURCE = "power_source" POWER_SOURCE = { "UNKNOWN": "ZB_ZCL_BASIC_POWER_SOURCE_UNKNOWN", @@ -38,3 +40,4 @@ ZB_ZCL_CLUSTER_ID_IDENTIFY = "ZB_ZCL_CLUSTER_ID_IDENTIFY" ZB_ZCL_CLUSTER_ID_BINARY_INPUT = "ZB_ZCL_CLUSTER_ID_BINARY_INPUT" ZB_ZCL_CLUSTER_ID_ANALOG_INPUT = "ZB_ZCL_CLUSTER_ID_ANALOG_INPUT" ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT = "ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT" +ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT = "ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT" diff --git a/esphome/components/zigbee/zigbee_number_zephyr.cpp b/esphome/components/zigbee/zigbee_number_zephyr.cpp new file mode 100644 index 0000000000..ceb318480c --- /dev/null +++ b/esphome/components/zigbee/zigbee_number_zephyr.cpp @@ -0,0 +1,111 @@ +#include "zigbee_number_zephyr.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_NUMBER) +#include "esphome/core/log.h" +extern "C" { +#include +#include +#include +#include +#include +} +namespace esphome::zigbee { + +static const char *const TAG = "zigbee.number"; + +void ZigbeeNumber::setup() { + this->parent_->add_callback(this->endpoint_, [this](zb_bufid_t bufid) { this->zcl_device_cb_(bufid); }); + this->number_->add_on_state_callback([this](float state) { + this->cluster_attributes_->present_value = state; + ESP_LOGD(TAG, "Set attribute endpoint: %d, present_value %f", this->endpoint_, + this->cluster_attributes_->present_value); + ZB_ZCL_SET_ATTRIBUTE(this->endpoint_, ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, + ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID, (zb_uint8_t *) &cluster_attributes_->present_value, + ZB_FALSE); + this->parent_->force_report(); + }); +} + +void ZigbeeNumber::dump_config() { + ESP_LOGCONFIG(TAG, + "Zigbee Number\n" + " Endpoint: %d, present_value %f", + this->endpoint_, this->cluster_attributes_->present_value); +} + +void ZigbeeNumber::zcl_device_cb_(zb_bufid_t bufid) { + zb_zcl_device_callback_param_t *p_device_cb_param = ZB_BUF_GET_PARAM(bufid, zb_zcl_device_callback_param_t); + zb_zcl_device_callback_id_t device_cb_id = p_device_cb_param->device_cb_id; + zb_uint16_t cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; + zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; + + switch (device_cb_id) { + /* ZCL set attribute value */ + case ZB_ZCL_SET_ATTR_VALUE_CB_ID: + if (cluster_id == ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT) { + ESP_LOGI(TAG, "Analog output attribute setting"); + if (attr_id == ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID) { + float value = + *reinterpret_cast(&p_device_cb_param->cb_param.set_attr_value_param.values.data32); + this->defer([this, value]() { + this->cluster_attributes_->present_value = value; + auto call = this->number_->make_call(); + call.set_value(value); + call.perform(); + }); + } + } else { + /* other clusters attribute handled here */ + ESP_LOGI(TAG, "Unhandled cluster attribute id: %d", cluster_id); + p_device_cb_param->status = RET_NOT_IMPLEMENTED; + } + break; + default: + p_device_cb_param->status = RET_NOT_IMPLEMENTED; + break; + } + + ESP_LOGD(TAG, "%s status: %hd", __func__, p_device_cb_param->status); +} + +const zb_uint8_t ZB_ZCL_ANALOG_OUTPUT_STATUS_FLAG_MAX_VALUE = 0x0F; + +static zb_ret_t check_value_analog_server(zb_uint16_t attr_id, zb_uint8_t endpoint, + zb_uint8_t *value) { // NOLINT(readability-non-const-parameter) + zb_ret_t ret = RET_OK; + ZVUNUSED(endpoint); + + switch (attr_id) { + case ZB_ZCL_ATTR_ANALOG_OUTPUT_OUT_OF_SERVICE_ID: + ret = ZB_ZCL_CHECK_BOOL_VALUE(*value) ? RET_OK : RET_ERROR; + break; + case ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID: + break; + + case ZB_ZCL_ATTR_ANALOG_OUTPUT_STATUS_FLAG_ID: + if (*value > ZB_ZCL_ANALOG_OUTPUT_STATUS_FLAG_MAX_VALUE) { + ret = RET_ERROR; + } + break; + + default: + break; + } + + return ret; +} + +} // namespace esphome::zigbee + +void zb_zcl_analog_output_init_server() { + zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ZB_ZCL_CLUSTER_SERVER_ROLE, + esphome::zigbee::check_value_analog_server, (zb_zcl_cluster_write_attr_hook_t) NULL, + (zb_zcl_cluster_handler_t) NULL); +} + +void zb_zcl_analog_output_init_client() { + zb_zcl_add_cluster_handlers(ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ZB_ZCL_CLUSTER_CLIENT_ROLE, + (zb_zcl_cluster_check_value_t) NULL, (zb_zcl_cluster_write_attr_hook_t) NULL, + (zb_zcl_cluster_handler_t) NULL); +} + +#endif diff --git a/esphome/components/zigbee/zigbee_number_zephyr.h b/esphome/components/zigbee/zigbee_number_zephyr.h new file mode 100644 index 0000000000..aabb0392be --- /dev/null +++ b/esphome/components/zigbee/zigbee_number_zephyr.h @@ -0,0 +1,118 @@ +#pragma once + +#include "esphome/core/defines.h" +#if defined(USE_ZIGBEE) && defined(USE_NRF52) && defined(USE_NUMBER) +#include "esphome/components/zigbee/zigbee_zephyr.h" +#include "esphome/core/component.h" +#include "esphome/components/number/number.h" +extern "C" { +#include +#include +} + +enum { + ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID = 0x001C, + ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID = 0x0041, + ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID = 0x0045, + ZB_ZCL_ATTR_ANALOG_OUTPUT_OUT_OF_SERVICE_ID = 0x0051, + ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID = 0x0055, + ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID = 0x006A, + ZB_ZCL_ATTR_ANALOG_OUTPUT_STATUS_FLAG_ID = 0x006F, + ZB_ZCL_ATTR_ANALOG_OUTPUT_ENGINEERING_UNITS_ID = 0x0075, +}; + +#define ZB_ZCL_ANALOG_OUTPUT_CLUSTER_REVISION_DEFAULT ((zb_uint16_t) 0x0001u) + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, ZB_ZCL_ATTR_TYPE_CHAR_STRING, ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ + (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_OUT_OF_SERVICE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_OUT_OF_SERVICE_ID, ZB_ZCL_ATTR_TYPE_BOOL, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } +// PresentValue +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID, ZB_ZCL_ATTR_TYPE_SINGLE, \ + ZB_ZCL_ATTR_ACCESS_READ_WRITE | ZB_ZCL_ATTR_ACCESS_REPORTING, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } +// MaxPresentValue +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID, ZB_ZCL_ATTR_TYPE_SINGLE, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } +// MinPresentValue +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID, ZB_ZCL_ATTR_TYPE_SINGLE, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } +// Resolution +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID, ZB_ZCL_ATTR_TYPE_SINGLE, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_WRITE_OPTIONAL, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_STATUS_FLAG_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_STATUS_FLAG_ID, ZB_ZCL_ATTR_TYPE_8BITMAP, \ + ZB_ZCL_ATTR_ACCESS_READ_ONLY | ZB_ZCL_ATTR_ACCESS_REPORTING, (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), \ + (void *) (data_ptr) \ + } + +#define ZB_SET_ATTR_DESCR_WITH_ZB_ZCL_ATTR_ANALOG_OUTPUT_ENGINEERING_UNITS_ID(data_ptr) \ + { \ + ZB_ZCL_ATTR_ANALOG_OUTPUT_ENGINEERING_UNITS_ID, ZB_ZCL_ATTR_TYPE_16BIT_ENUM, ZB_ZCL_ATTR_ACCESS_READ_ONLY, \ + (ZB_ZCL_NON_MANUFACTURER_SPECIFIC), (void *) (data_ptr) \ + } + +#define ESPHOME_ZB_ZCL_DECLARE_ANALOG_OUTPUT_ATTRIB_LIST(attr_list, out_of_service, present_value, status_flag, \ + max_present_value, min_present_value, resolution, \ + engineering_units, description) \ + ZB_ZCL_START_DECLARE_ATTRIB_LIST_CLUSTER_REVISION(attr_list, ZB_ZCL_ANALOG_OUTPUT) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_OUT_OF_SERVICE_ID, (out_of_service)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_PRESENT_VALUE_ID, (present_value)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_STATUS_FLAG_ID, (status_flag)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_MAX_PRESENT_VALUE_ID, (max_present_value)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_MIN_PRESENT_VALUE_ID, (min_present_value)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_RESOLUTION_ID, (resolution)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_ENGINEERING_UNITS_ID, (engineering_units)) \ + ZB_ZCL_SET_ATTR_DESC(ZB_ZCL_ATTR_ANALOG_OUTPUT_DESCRIPTION_ID, (description)) \ + ZB_ZCL_FINISH_DECLARE_ATTRIB_LIST + +void zb_zcl_analog_output_init_server(); +void zb_zcl_analog_output_init_client(); +#define ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT_SERVER_ROLE_INIT zb_zcl_analog_output_init_server +#define ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT_CLIENT_ROLE_INIT zb_zcl_analog_output_init_client + +namespace esphome::zigbee { + +class ZigbeeNumber : public ZigbeeEntity, public Component { + public: + ZigbeeNumber(number::Number *n) : number_(n) {} + void set_cluster_attributes(AnalogAttrsOutput &cluster_attributes) { + this->cluster_attributes_ = &cluster_attributes; + } + + void setup() override; + void dump_config() override; + + protected: + number::Number *number_; + AnalogAttrsOutput *cluster_attributes_{nullptr}; + void zcl_device_cb_(zb_bufid_t bufid); +}; + +} // namespace esphome::zigbee +#endif diff --git a/esphome/components/zigbee/zigbee_switch_zephyr.cpp b/esphome/components/zigbee/zigbee_switch_zephyr.cpp index fef02e5a0c..935140e9df 100644 --- a/esphome/components/zigbee/zigbee_switch_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_switch_zephyr.cpp @@ -50,7 +50,7 @@ void ZigbeeSwitch::zcl_device_cb_(zb_bufid_t bufid) { if (attr_id == ZB_ZCL_ATTR_BINARY_OUTPUT_PRESENT_VALUE_ID) { this->defer([this, value]() { this->cluster_attributes_->present_value = value ? ZB_TRUE : ZB_FALSE; - this->switch_->publish_state(value); + this->switch_->control(value); }); } } else { diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index eabf5c30d4..4763943e88 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -101,8 +101,8 @@ void ZigbeeComponent::zcl_device_cb(zb_bufid_t bufid) { zb_uint16_t attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; auto endpoint = p_device_cb_param->endpoint; - ESP_LOGI(TAG, "Zcl_device_cb %s id %hd, cluster_id %d, attr_id %d, endpoint: %d", __func__, device_cb_id, cluster_id, - attr_id, endpoint); + ESP_LOGI(TAG, "%s id %hd, cluster_id %d, attr_id %d, endpoint: %d", __func__, device_cb_id, cluster_id, attr_id, + endpoint); /* Set default response value. */ p_device_cb_param->status = RET_OK; diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index b75c192c1a..05895e8e61 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -60,6 +60,12 @@ struct AnalogAttrs { zb_uchar_t description[ZB_ZCL_MAX_STRING_SIZE]; }; +struct AnalogAttrsOutput : AnalogAttrs { + float max_present_value; + float min_present_value; + float resolution; +}; + class ZigbeeComponent : public Component { public: void setup() override; diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index b3bd10bfab..0b6daa9476 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -55,6 +55,7 @@ from .const_zephyr import ( CONF_WIPE_ON_BOOT, CONF_ZIGBEE_BINARY_SENSOR, CONF_ZIGBEE_ID, + CONF_ZIGBEE_NUMBER, CONF_ZIGBEE_SENSOR, CONF_ZIGBEE_SWITCH, KEY_EP_NUMBER, @@ -62,12 +63,14 @@ from .const_zephyr import ( POWER_SOURCE, ZB_ZCL_BASIC_ATTRS_EXT_T, ZB_ZCL_CLUSTER_ID_ANALOG_INPUT, + ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, ZB_ZCL_CLUSTER_ID_BASIC, ZB_ZCL_CLUSTER_ID_BINARY_INPUT, ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, ZB_ZCL_CLUSTER_ID_IDENTIFY, ZB_ZCL_IDENTIFY_ATTRS_T, AnalogAttrs, + AnalogAttrsOutput, BinaryAttrs, ZigbeeComponent, zigbee_ns, @@ -76,6 +79,7 @@ from .const_zephyr import ( ZigbeeBinarySensor = zigbee_ns.class_("ZigbeeBinarySensor", cg.Component) ZigbeeSensor = zigbee_ns.class_("ZigbeeSensor", cg.Component) ZigbeeSwitch = zigbee_ns.class_("ZigbeeSwitch", cg.Component) +ZigbeeNumber = zigbee_ns.class_("ZigbeeNumber", cg.Component) # BACnet engineering units mapping (ZCL uses BACnet unit codes) # See: https://github.com/zigpy/zha/blob/dev/zha/application/platforms/number/bacnet.py @@ -139,6 +143,15 @@ zephyr_switch = cv.Schema( } ) +zephyr_number = cv.Schema( + { + cv.OnlyWith(CONF_ZIGBEE_ID, ["nrf52", "zigbee"]): cv.use_id(ZigbeeComponent), + cv.OnlyWith(CONF_ZIGBEE_NUMBER, ["nrf52", "zigbee"]): cv.declare_id( + ZigbeeNumber + ), + } +) + async def zephyr_to_code(config: ConfigType) -> None: zephyr_add_prj_conf("ZIGBEE", True) @@ -344,6 +357,16 @@ async def zephyr_setup_switch(entity: cg.MockObj, config: ConfigType) -> None: CORE.add_job(_add_switch, entity, config) +async def zephyr_setup_number( + entity: cg.MockObj, + config: ConfigType, + min_value: float, + max_value: float, + step: float, +) -> None: + CORE.add_job(_add_number, entity, config, min_value, max_value, step) + + def get_slot_index() -> int: """Find the next available endpoint slot.""" slot = next( @@ -451,3 +474,31 @@ async def _add_switch(entity: cg.MockObj, config: ConfigType) -> None: ZB_ZCL_CLUSTER_ID_BINARY_OUTPUT, "ZB_HA_CUSTOM_ATTR_DEVICE_ID", ) + + +async def _add_number( + entity: cg.MockObj, + config: ConfigType, + min_value: float, + max_value: float, + step: float, +) -> None: + # Get BACnet engineering unit from unit_of_measurement + unit = config.get(CONF_UNIT_OF_MEASUREMENT, "") + bacnet_unit = BACNET_UNITS.get(unit, BACNET_UNIT_NO_UNITS) + + await _add_zigbee_ep( + entity, + config, + CONF_ZIGBEE_NUMBER, + AnalogAttrsOutput, + "ESPHOME_ZB_ZCL_DECLARE_ANALOG_OUTPUT_ATTRIB_LIST", + ZB_ZCL_CLUSTER_ID_ANALOG_OUTPUT, + "ZB_HA_CUSTOM_ATTR_DEVICE_ID", + extra_field_values={ + "max_present_value": max_value, + "min_present_value": min_value, + "resolution": step, + "engineering_units": bacnet_unit, + }, + ) diff --git a/tests/components/zigbee/common.yaml b/tests/components/zigbee/common.yaml index e4dee5f74a..2af35ff148 100644 --- a/tests/components/zigbee/common.yaml +++ b/tests/components/zigbee/common.yaml @@ -6,8 +6,6 @@ binary_sensor: name: "Garage Door Open 2" - platform: template name: "Garage Door Open 3" - - platform: template - name: "Garage Door Open 4" - platform: template name: "Garage Door Internal" internal: True @@ -44,3 +42,11 @@ switch: - platform: template name: "Template Switch" optimistic: true + +number: + - platform: template + name: "Template number" + optimistic: true + min_value: 2 + max_value: 100 + step: 1 From ecc0b366b3320131d53df133fd175c612776b5c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 29 Jan 2026 09:21:12 -1000 Subject: [PATCH 0417/2030] [esp32] Reduce compile time by excluding unused IDF components (#13610) --- esphome/components/adc/sensor.py | 5 +- esphome/components/audio/__init__.py | 5 +- esphome/components/display/__init__.py | 7 +- esphome/components/esp32/__init__.py | 83 +++++++++++++++++++ esphome/components/esp32/const.py | 1 + .../components/esp32_rmt_led_strip/light.py | 4 + esphome/components/esp32_touch/__init__.py | 4 + esphome/components/ethernet/__init__.py | 4 + esphome/components/http_request/__init__.py | 3 + esphome/components/i2s_audio/__init__.py | 11 ++- esphome/components/mqtt/__init__.py | 7 +- esphome/components/neopixelbus/light.py | 11 ++- esphome/components/nextion/display.py | 2 + .../components/remote_receiver/__init__.py | 3 + .../components/remote_transmitter/__init__.py | 3 + tests/components/esp32/test.esp32-idf.yaml | 2 + 16 files changed, 148 insertions(+), 7 deletions(-) diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index 64dd22b0c3..bab2762f00 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -2,7 +2,7 @@ import logging import esphome.codegen as cg from esphome.components import sensor, voltage_sampler -from esphome.components.esp32 import get_esp32_variant +from esphome.components.esp32 import get_esp32_variant, include_builtin_idf_component from esphome.components.nrf52.const import AIN_TO_GPIO, EXTRA_ADC from esphome.components.zephyr import ( zephyr_add_overlay, @@ -118,6 +118,9 @@ async def to_code(config): cg.add(var.set_sampling_mode(config[CONF_SAMPLING_MODE])) if CORE.is_esp32: + # Re-enable ESP-IDF's ADC driver (excluded by default to save compile time) + include_builtin_idf_component("esp_adc") + if attenuation := config.get(CONF_ATTENUATION): if attenuation == "auto": cg.add(var.set_autorange(cg.global_ns.true)) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index 6c721652e1..f48b776ddd 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -1,5 +1,5 @@ import esphome.codegen as cg -from esphome.components.esp32 import add_idf_component +from esphome.components.esp32 import add_idf_component, include_builtin_idf_component import esphome.config_validation as cv from esphome.const import CONF_BITS_PER_SAMPLE, CONF_NUM_CHANNELS, CONF_SAMPLE_RATE import esphome.final_validate as fv @@ -166,6 +166,9 @@ def final_validate_audio_schema( async def to_code(config): + # Re-enable ESP-IDF's HTTP client (excluded by default to save compile time) + include_builtin_idf_component("esp_http_client") + add_idf_component( name="esphome/esp-audio-libs", ref="2.0.3", diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index ccbeedcd2f..695e7cde47 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -15,7 +15,7 @@ from esphome.const import ( CONF_UPDATE_INTERVAL, SCHEDULER_DONT_RUN, ) -from esphome.core import CoroPriority, coroutine_with_priority +from esphome.core import CORE, CoroPriority, coroutine_with_priority IS_PLATFORM_COMPONENT = True @@ -222,3 +222,8 @@ async def display_is_displaying_page_to_code(config, condition_id, template_arg, async def to_code(config): cg.add_global(display_ns.using) cg.add_define("USE_DISPLAY") + if CORE.is_esp32: + # Re-enable ESP-IDF's LCD driver (excluded by default to save compile time) + from esphome.components.esp32 import include_builtin_idf_component + + include_builtin_idf_component("esp_lcd") diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 4e425792dc..1d7ea5395f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -53,6 +53,7 @@ from .const import ( # noqa KEY_BOARD, KEY_COMPONENTS, KEY_ESP32, + KEY_EXCLUDE_COMPONENTS, KEY_EXTRA_BUILD_FILES, KEY_FLASH_SIZE, KEY_FULL_CERT_BUNDLE, @@ -86,6 +87,7 @@ IS_TARGET_PLATFORM = True CONF_ASSERTION_LEVEL = "assertion_level" CONF_COMPILER_OPTIMIZATION = "compiler_optimization" CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features" +CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components" CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" @@ -114,6 +116,36 @@ COMPILER_OPTIMIZATIONS = { "SIZE": "CONFIG_COMPILER_OPTIMIZATION_SIZE", } +# ESP-IDF components excluded by default to reduce compile time. +# Components can be re-enabled by calling include_builtin_idf_component() in to_code(). +# +# Cannot be excluded (dependencies of required components): +# - "console": espressif/mdns unconditionally depends on it +# - "sdmmc": driver -> esp_driver_sdmmc -> sdmmc dependency chain +DEFAULT_EXCLUDED_IDF_COMPONENTS = ( + "cmock", # Unit testing mock framework - ESPHome doesn't use IDF's testing + "esp_adc", # ADC driver - only needed by adc component + "esp_driver_i2s", # I2S driver - only needed by i2s_audio component + "esp_driver_rmt", # RMT driver - only needed by remote_transmitter/receiver, neopixelbus + "esp_driver_touch_sens", # Touch sensor driver - only needed by esp32_touch + "esp_eth", # Ethernet driver - only needed by ethernet component + "esp_hid", # HID host/device support - ESPHome doesn't implement HID functionality + "esp_http_client", # HTTP client - only needed by http_request component + "esp_https_ota", # ESP-IDF HTTPS OTA - ESPHome has its own OTA implementation + "esp_https_server", # HTTPS server - ESPHome has its own web server + "esp_lcd", # LCD controller drivers - only needed by display component + "esp_local_ctrl", # Local control over HTTPS/BLE - ESPHome has native API + "espcoredump", # Core dump support - ESPHome has its own debug component + "fatfs", # FAT filesystem - ESPHome doesn't use filesystem storage + "mqtt", # ESP-IDF MQTT library - ESPHome has its own MQTT implementation + "perfmon", # Xtensa performance monitor - ESPHome has its own debug component + "protocomm", # Protocol communication for provisioning - unused by ESPHome + "spiffs", # SPIFFS filesystem - ESPHome doesn't use filesystem storage (IDF only) + "unity", # Unit testing framework - ESPHome doesn't use IDF's testing + "wear_levelling", # Flash wear levelling for fatfs - unused since fatfs unused + "wifi_provisioning", # WiFi provisioning - ESPHome uses its own improv implementation +) + # ESP32 (original) chip revision options # Setting minimum revision to 3.0 or higher: # - Reduces flash size by excluding workaround code for older chip bugs @@ -203,6 +235,9 @@ def set_core_data(config): ) CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] = {} CORE.data[KEY_ESP32][KEY_COMPONENTS] = {} + # Initialize with default exclusions - components can call include_builtin_idf_component() + # to re-enable any they need + CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = set(DEFAULT_EXCLUDED_IDF_COMPONENTS) CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( config[CONF_FRAMEWORK][CONF_VERSION] ) @@ -328,6 +363,28 @@ def add_idf_component( } +def exclude_builtin_idf_component(name: str) -> None: + """Exclude an ESP-IDF component from the build. + + This reduces compile time by skipping components that are not needed. + The component will be passed to ESP-IDF's EXCLUDE_COMPONENTS cmake variable. + + Note: Components that are dependencies of other required components + cannot be excluded - ESP-IDF will still build them. + """ + CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS].add(name) + + +def include_builtin_idf_component(name: str) -> None: + """Remove an ESP-IDF component from the exclusion list. + + Call this from components that need an ESP-IDF component that is + excluded by default in DEFAULT_EXCLUDED_IDF_COMPONENTS. This ensures the + component will be built when needed. + """ + CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS].discard(name) + + def add_extra_script(stage: str, filename: str, path: Path): """Add an extra script to the project.""" key = f"{stage}:{filename}" @@ -844,6 +901,9 @@ FRAMEWORK_SCHEMA = cv.Schema( cv.Optional( CONF_USE_FULL_CERTIFICATE_BUNDLE, default=False ): cv.boolean, + cv.Optional( + CONF_INCLUDE_BUILTIN_IDF_COMPONENTS, default=[] + ): cv.ensure_list(cv.string_strict), cv.Optional(CONF_DISABLE_DEBUG_STUBS, default=True): cv.boolean, cv.Optional(CONF_DISABLE_OCD_AWARE, default=True): cv.boolean, cv.Optional( @@ -1043,6 +1103,19 @@ def _configure_lwip_max_sockets(conf: dict) -> None: add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", max_sockets) +@coroutine_with_priority(CoroPriority.FINAL) +async def _write_exclude_components() -> None: + """Write EXCLUDE_COMPONENTS cmake arg after all components have registered exclusions.""" + if KEY_ESP32 not in CORE.data: + return + excluded = CORE.data[KEY_ESP32].get(KEY_EXCLUDE_COMPONENTS) + if excluded: + exclude_list = ";".join(sorted(excluded)) + cg.add_platformio_option( + "board_build.cmake_extra_args", f"-DEXCLUDE_COMPONENTS={exclude_list}" + ) + + @coroutine_with_priority(CoroPriority.FINAL) async def _add_yaml_idf_components(components: list[ConfigType]): """Add IDF components from YAML config with final priority to override code-added components.""" @@ -1256,6 +1329,11 @@ async def to_code(config): # Apply LWIP optimization settings advanced = conf[CONF_ADVANCED] + + # Re-include any IDF components the user explicitly requested + for component_name in advanced.get(CONF_INCLUDE_BUILTIN_IDF_COMPONENTS, []): + include_builtin_idf_component(component_name) + # DHCP server: only disable if explicitly set to false # WiFi component handles its own optimization when AP mode is not used # When using Arduino with Ethernet, DHCP server functions must be available @@ -1440,6 +1518,11 @@ async def to_code(config): if conf[CONF_COMPONENTS]: CORE.add_job(_add_yaml_idf_components, conf[CONF_COMPONENTS]) + # Write EXCLUDE_COMPONENTS at FINAL priority after all components have had + # a chance to call include_builtin_idf_component() to re-enable components they need. + # Default exclusions are added in set_core_data() during config validation. + CORE.add_job(_write_exclude_components) + APP_PARTITION_SIZES = { "2MB": 0x0C0000, # 768 KB diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index 9f8165818b..db3eddebd5 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -6,6 +6,7 @@ KEY_FLASH_SIZE = "flash_size" KEY_VARIANT = "variant" KEY_SDKCONFIG_OPTIONS = "sdkconfig_options" KEY_COMPONENTS = "components" +KEY_EXCLUDE_COMPONENTS = "exclude_components" KEY_REPO = "repo" KEY_REF = "ref" KEY_REFRESH = "refresh" diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 3be3c758f1..6d41f6b5b8 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -5,6 +5,7 @@ from esphome import pins import esphome.codegen as cg from esphome.components import esp32, light from esphome.components.const import CONF_USE_PSRAM +from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv from esphome.const import ( CONF_CHIPSET, @@ -129,6 +130,9 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): + # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) + include_builtin_idf_component("esp_driver_rmt") + var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) await light.register_light(var, config) await cg.register_component(var, config) diff --git a/esphome/components/esp32_touch/__init__.py b/esphome/components/esp32_touch/__init__.py index c54ed8b9ea..6accb89c35 100644 --- a/esphome/components/esp32_touch/__init__.py +++ b/esphome/components/esp32_touch/__init__.py @@ -6,6 +6,7 @@ from esphome.components.esp32 import ( VARIANT_ESP32S3, get_esp32_variant, gpio, + include_builtin_idf_component, ) import esphome.config_validation as cv from esphome.const import ( @@ -266,6 +267,9 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): + # Re-enable ESP-IDF's touch sensor driver (excluded by default to save compile time) + include_builtin_idf_component("esp_driver_touch_sens") + touch = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(touch, config) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 1f2fe61fe1..8d4a1aaf8e 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -14,6 +14,7 @@ from esphome.components.esp32 import ( add_idf_component, add_idf_sdkconfig_option, get_esp32_variant, + include_builtin_idf_component, ) from esphome.components.network import ip_address_literal from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface @@ -419,6 +420,9 @@ async def to_code(config): # Also disable WiFi/BT coexistence since WiFi is disabled add_idf_sdkconfig_option("CONFIG_SW_COEXIST_ENABLE", False) + # Re-enable ESP-IDF's Ethernet driver (excluded by default to save compile time) + include_builtin_idf_component("esp_eth") + if config[CONF_TYPE] == "LAN8670": # Add LAN867x 10BASE-T1S PHY support component add_idf_component(name="espressif/lan867x", ref="2.0.0") diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 07bc758037..64d74323d6 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -155,6 +155,9 @@ async def to_code(config): cg.add(var.set_watchdog_timeout(timeout_ms)) if CORE.is_esp32: + # Re-enable ESP-IDF's HTTP client (excluded by default to save compile time) + esp32.include_builtin_idf_component("esp_http_client") + cg.add(var.set_buffer_size_rx(config[CONF_BUFFER_SIZE_RX])) cg.add(var.set_buffer_size_tx(config[CONF_BUFFER_SIZE_TX])) cg.add(var.set_verify_ssl(config[CONF_VERIFY_SSL])) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index d3128c5f4c..1cd2e97a5e 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -1,6 +1,11 @@ from esphome import pins import esphome.codegen as cg from esphome.components.esp32 import ( + add_idf_sdkconfig_option, + get_esp32_variant, + include_builtin_idf_component, +) +from esphome.components.esp32.const import ( VARIANT_ESP32, VARIANT_ESP32C3, VARIANT_ESP32C5, @@ -10,8 +15,6 @@ from esphome.components.esp32 import ( VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, - add_idf_sdkconfig_option, - get_esp32_variant, ) import esphome.config_validation as cv from esphome.const import CONF_BITS_PER_SAMPLE, CONF_CHANNEL, CONF_ID, CONF_SAMPLE_RATE @@ -272,6 +275,10 @@ FINAL_VALIDATE_SCHEMA = _final_validate async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + + # Re-enable ESP-IDF's I2S driver (excluded by default to save compile time) + include_builtin_idf_component("esp_driver_i2s") + if use_legacy(): cg.add_define("USE_I2S_LEGACY") diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index f53df5564c..fe153fedfa 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -4,7 +4,10 @@ from esphome import automation from esphome.automation import Condition import esphome.codegen as cg from esphome.components import logger, socket -from esphome.components.esp32 import add_idf_sdkconfig_option +from esphome.components.esp32 import ( + add_idf_sdkconfig_option, + include_builtin_idf_component, +) from esphome.config_helpers import filter_source_files_from_platform import esphome.config_validation as cv from esphome.const import ( @@ -360,6 +363,8 @@ async def to_code(config): # This enables low-latency MQTT event processing instead of waiting for select() timeout if CORE.is_esp32: socket.require_wake_loop_threadsafe() + # Re-enable ESP-IDF's mqtt component (excluded by default to save compile time) + include_builtin_idf_component("mqtt") cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) diff --git a/esphome/components/neopixelbus/light.py b/esphome/components/neopixelbus/light.py index c77217243c..104762c69e 100644 --- a/esphome/components/neopixelbus/light.py +++ b/esphome/components/neopixelbus/light.py @@ -1,7 +1,12 @@ from esphome import pins import esphome.codegen as cg from esphome.components import light -from esphome.components.esp32 import VARIANT_ESP32C3, VARIANT_ESP32S3, get_esp32_variant +from esphome.components.esp32 import ( + VARIANT_ESP32C3, + VARIANT_ESP32S3, + get_esp32_variant, + include_builtin_idf_component, +) import esphome.config_validation as cv from esphome.const import ( CONF_CHANNEL, @@ -205,6 +210,10 @@ async def to_code(config): has_white = "W" in config[CONF_TYPE] method = config[CONF_METHOD] + # Re-enable ESP-IDF's RMT driver if using RMT method (excluded by default) + if CORE.is_esp32 and method[CONF_TYPE] == METHOD_ESP32_RMT: + include_builtin_idf_component("esp_driver_rmt") + method_template = METHODS[method[CONF_TYPE]].to_code( method, config[CONF_VARIANT], config[CONF_INVERT] ) diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index ffc509fc64..3bfcc95995 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -177,6 +177,8 @@ async def to_code(config): cg.add_define("USE_NEXTION_TFT_UPLOAD") cg.add(var.set_tft_url(config[CONF_TFT_URL])) if CORE.is_esp32: + # Re-enable ESP-IDF's HTTP client (excluded by default to save compile time) + esp32.include_builtin_idf_component("esp_http_client") esp32.add_idf_sdkconfig_option("CONFIG_ESP_TLS_INSECURE", True) esp32.add_idf_sdkconfig_option( "CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY", True diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index f5d89f2f0f..b3dc213c5f 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -170,6 +170,9 @@ CONFIG_SCHEMA = remote_base.validate_triggers( async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) if CORE.is_esp32: + # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) + esp32.include_builtin_idf_component("esp_driver_rmt") + var = cg.new_Pvariable(config[CONF_ID], pin) cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS])) cg.add(var.set_receive_symbols(config[CONF_RECEIVE_SYMBOLS])) diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index f182a1ec0d..8383b9dd75 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -112,6 +112,9 @@ async def digital_write_action_to_code(config, action_id, template_arg, args): async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) if CORE.is_esp32: + # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) + esp32.include_builtin_idf_component("esp_driver_rmt") + var = cg.new_Pvariable(config[CONF_ID], pin) cg.add(var.set_rmt_symbols(config[CONF_RMT_SYMBOLS])) cg.add(var.set_non_blocking(config[CONF_NON_BLOCKING])) diff --git a/tests/components/esp32/test.esp32-idf.yaml b/tests/components/esp32/test.esp32-idf.yaml index d4ab6b4a87..f80c854de5 100644 --- a/tests/components/esp32/test.esp32-idf.yaml +++ b/tests/components/esp32/test.esp32-idf.yaml @@ -8,6 +8,8 @@ esp32: enable_lwip_bridge_interface: true disable_libc_locks_in_iram: false # Test explicit opt-out of RAM optimization use_full_certificate_bundle: false # Test CMN bundle (default) + include_builtin_idf_components: + - freertos # Test escape hatch (freertos is always included anyway) disable_debug_stubs: true disable_ocd_aware: true disable_usb_serial_jtag_secondary: true From cd43f8474e7941ffe220b7fc0cf1bdf4a2d7365e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:35:32 -0600 Subject: [PATCH 0418/2030] Bump actions/cache from 5.0.2 to 5.0.3 (#13621) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f521b07bae..841c297bce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv # yamllint disable-line rule:line-length @@ -157,7 +157,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Save Python virtual environment cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv key: ${{ runner.os }}-${{ steps.restore-python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -193,7 +193,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Restore components graph cache - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -223,7 +223,7 @@ jobs: echo "component-test-batches=$(echo "$output" | jq -c '.component_test_batches')" >> $GITHUB_OUTPUT - name: Save components graph cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -245,7 +245,7 @@ jobs: python-version: "3.13" - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -334,14 +334,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} @@ -413,14 +413,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -502,14 +502,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -735,7 +735,7 @@ jobs: - name: Restore cached memory analysis id: cache-memory-analysis if: steps.check-script.outputs.skip != 'true' - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -759,7 +759,7 @@ jobs: - name: Cache platformio if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} @@ -800,7 +800,7 @@ jobs: - name: Save memory analysis to cache if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success' - uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -847,7 +847,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} From 6de2049076574ff6a7e1eb09a8abde7928dafd76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Jan 2026 14:35:52 -0600 Subject: [PATCH 0419/2030] Bump actions/cache from 5.0.2 to 5.0.3 in /.github/actions/restore-python (#13622) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/restore-python/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index e178610a97..6d7d4f8c12 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -22,7 +22,7 @@ runs: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2 + uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: venv # yamllint disable-line rule:line-length From 823b5ac1ab4f8e18439b1012ec191025a32a1bcb Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 29 Jan 2026 15:16:15 -0800 Subject: [PATCH 0420/2030] [ch423] Add CH423 I/O expander component (#13079) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/ch423/__init__.py | 103 +++++++++++++ esphome/components/ch423/ch423.cpp | 148 +++++++++++++++++++ esphome/components/ch423/ch423.h | 67 +++++++++ tests/components/ch423/common.yaml | 36 +++++ tests/components/ch423/test.esp32-idf.yaml | 4 + tests/components/ch423/test.esp8266-ard.yaml | 4 + tests/components/ch423/test.rp2040-ard.yaml | 4 + tests/unit_tests/components/test_ch423.py | 58 ++++++++ 9 files changed, 425 insertions(+) create mode 100644 esphome/components/ch423/__init__.py create mode 100644 esphome/components/ch423/ch423.cpp create mode 100644 esphome/components/ch423/ch423.h create mode 100644 tests/components/ch423/common.yaml create mode 100644 tests/components/ch423/test.esp32-idf.yaml create mode 100644 tests/components/ch423/test.esp8266-ard.yaml create mode 100644 tests/components/ch423/test.rp2040-ard.yaml create mode 100644 tests/unit_tests/components/test_ch423.py diff --git a/CODEOWNERS b/CODEOWNERS index 00a22fed7c..b7675f9406 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -104,6 +104,7 @@ esphome/components/cc1101/* @gabest11 @lygris esphome/components/ccs811/* @habbie esphome/components/cd74hc4067/* @asoehlke esphome/components/ch422g/* @clydebarrow @jesterret +esphome/components/ch423/* @dwmw2 esphome/components/chsc6x/* @kkosik20 esphome/components/climate/* @esphome/core esphome/components/climate_ir/* @glmnet diff --git a/esphome/components/ch423/__init__.py b/esphome/components/ch423/__init__.py new file mode 100644 index 0000000000..e3990ee631 --- /dev/null +++ b/esphome/components/ch423/__init__.py @@ -0,0 +1,103 @@ +from esphome import pins +import esphome.codegen as cg +from esphome.components import i2c +from esphome.components.i2c import I2CBus +import esphome.config_validation as cv +from esphome.const import ( + CONF_I2C_ID, + CONF_ID, + CONF_INPUT, + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_OPEN_DRAIN, + CONF_OUTPUT, +) +from esphome.core import CORE + +CODEOWNERS = ["@dwmw2"] +DEPENDENCIES = ["i2c"] +MULTI_CONF = True +ch423_ns = cg.esphome_ns.namespace("ch423") + +CH423Component = ch423_ns.class_("CH423Component", cg.Component, i2c.I2CDevice) +CH423GPIOPin = ch423_ns.class_( + "CH423GPIOPin", cg.GPIOPin, cg.Parented.template(CH423Component) +) + +CONF_CH423 = "ch423" + +# Note that no address is configurable - each register in the CH423 has a dedicated i2c address +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(CH423Component), + cv.GenerateID(CONF_I2C_ID): cv.use_id(I2CBus), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + # Can't use register_i2c_device because there is no CONF_ADDRESS + parent = await cg.get_variable(config[CONF_I2C_ID]) + cg.add(var.set_i2c_bus(parent)) + + +# This is used as a final validation step so that modes have been fully transformed. +def pin_mode_check(pin_config, _): + if pin_config[CONF_MODE][CONF_INPUT] and pin_config[CONF_NUMBER] >= 8: + raise cv.Invalid("CH423 only supports input on pins 0-7") + if pin_config[CONF_MODE][CONF_OPEN_DRAIN] and pin_config[CONF_NUMBER] < 8: + raise cv.Invalid("CH423 only supports open drain output on pins 8-23") + + ch423_id = pin_config[CONF_CH423] + pin_num = pin_config[CONF_NUMBER] + is_output = pin_config[CONF_MODE][CONF_OUTPUT] + is_open_drain = pin_config[CONF_MODE][CONF_OPEN_DRAIN] + + # Track pin modes per CH423 instance in CORE.data + ch423_modes = CORE.data.setdefault(CONF_CH423, {}) + if ch423_id not in ch423_modes: + ch423_modes[ch423_id] = {"gpio_output": None, "gpo_open_drain": None} + + if pin_num < 8: + # GPIO pins (0-7): all must have same direction + if ch423_modes[ch423_id]["gpio_output"] is None: + ch423_modes[ch423_id]["gpio_output"] = is_output + elif ch423_modes[ch423_id]["gpio_output"] != is_output: + raise cv.Invalid( + "CH423 GPIO pins (0-7) must all be configured as input or all as output" + ) + # GPO pins (8-23): all must have same open-drain setting + elif ch423_modes[ch423_id]["gpo_open_drain"] is None: + ch423_modes[ch423_id]["gpo_open_drain"] = is_open_drain + elif ch423_modes[ch423_id]["gpo_open_drain"] != is_open_drain: + raise cv.Invalid( + "CH423 GPO pins (8-23) must all be configured as push-pull or all as open-drain" + ) + + +CH423_PIN_SCHEMA = pins.gpio_base_schema( + CH423GPIOPin, + cv.int_range(min=0, max=23), + modes=[CONF_INPUT, CONF_OUTPUT, CONF_OPEN_DRAIN], +).extend( + { + cv.Required(CONF_CH423): cv.use_id(CH423Component), + } +) + + +@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH423, CH423_PIN_SCHEMA, pin_mode_check) +async def ch423_pin_to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + parent = await cg.get_variable(config[CONF_CH423]) + + cg.add(var.set_parent(parent)) + + num = config[CONF_NUMBER] + cg.add(var.set_pin(num)) + cg.add(var.set_inverted(config[CONF_INVERTED])) + cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE]))) + return var diff --git a/esphome/components/ch423/ch423.cpp b/esphome/components/ch423/ch423.cpp new file mode 100644 index 0000000000..4abbbe7adf --- /dev/null +++ b/esphome/components/ch423/ch423.cpp @@ -0,0 +1,148 @@ +#include "ch423.h" +#include "esphome/core/log.h" +#include "esphome/core/progmem.h" + +namespace esphome::ch423 { + +static constexpr uint8_t CH423_REG_SYS = 0x24; // Set system parameters (0x48 >> 1) +static constexpr uint8_t CH423_SYS_IO_OE = 0x01; // IO output enable +static constexpr uint8_t CH423_SYS_OD_EN = 0x04; // Open drain enable for OC pins +static constexpr uint8_t CH423_REG_IO = 0x30; // Write/read IO7-IO0 (0x60 >> 1) +static constexpr uint8_t CH423_REG_IO_RD = 0x26; // Read IO7-IO0 (0x4D >> 1, rounded down) +static constexpr uint8_t CH423_REG_OCL = 0x22; // Write OC7-OC0 (0x44 >> 1) +static constexpr uint8_t CH423_REG_OCH = 0x23; // Write OC15-OC8 (0x46 >> 1) + +static const char *const TAG = "ch423"; + +void CH423Component::setup() { + // set outputs before mode + this->write_outputs_(); + // Set system parameters and check for errors + bool success = this->write_reg_(CH423_REG_SYS, this->sys_params_); + // Only read inputs if pins are configured for input (IO_OE not set) + if (success && !(this->sys_params_ & CH423_SYS_IO_OE)) { + success = this->read_inputs_(); + } + if (!success) { + ESP_LOGE(TAG, "CH423 not detected"); + this->mark_failed(); + return; + } + + ESP_LOGCONFIG(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), + this->status_has_error()); +} + +void CH423Component::loop() { + // Clear all the previously read flags. + this->pin_read_flags_ = 0x00; +} + +void CH423Component::dump_config() { + ESP_LOGCONFIG(TAG, "CH423:"); + if (this->is_failed()) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + } +} + +void CH423Component::pin_mode(uint8_t pin, gpio::Flags flags) { + if (pin < 8) { + if (flags & gpio::FLAG_OUTPUT) { + this->sys_params_ |= CH423_SYS_IO_OE; + } + } else if (pin >= 8 && pin < 24) { + if (flags & gpio::FLAG_OPEN_DRAIN) { + this->sys_params_ |= CH423_SYS_OD_EN; + } + } +} + +bool CH423Component::digital_read(uint8_t pin) { + if (this->pin_read_flags_ == 0 || this->pin_read_flags_ & (1 << pin)) { + // Read values on first access or in case it's being read again in the same loop + this->read_inputs_(); + } + + this->pin_read_flags_ |= (1 << pin); + return (this->input_bits_ & (1 << pin)) != 0; +} + +void CH423Component::digital_write(uint8_t pin, bool value) { + if (value) { + this->output_bits_ |= (1 << pin); + } else { + this->output_bits_ &= ~(1 << pin); + } + this->write_outputs_(); +} + +bool CH423Component::read_inputs_() { + if (this->is_failed()) { + return false; + } + // reading inputs requires IO_OE to be 0 + if (this->sys_params_ & CH423_SYS_IO_OE) { + return false; + } + uint8_t result = this->read_reg_(CH423_REG_IO_RD); + this->input_bits_ = result; + this->status_clear_warning(); + return true; +} + +// Write a register. Can't use the standard write_byte() method because there is no single pre-configured i2c address. +bool CH423Component::write_reg_(uint8_t reg, uint8_t value) { + auto err = this->bus_->write_readv(reg, &value, 1, nullptr, 0); + if (err != i2c::ERROR_OK) { + char buf[64]; + ESPHOME_snprintf_P(buf, sizeof(buf), ESPHOME_PSTR("write failed for register 0x%X, error %d"), reg, err); + this->status_set_warning(buf); + return false; + } + this->status_clear_warning(); + return true; +} + +uint8_t CH423Component::read_reg_(uint8_t reg) { + uint8_t value; + auto err = this->bus_->write_readv(reg, nullptr, 0, &value, 1); + if (err != i2c::ERROR_OK) { + char buf[64]; + ESPHOME_snprintf_P(buf, sizeof(buf), ESPHOME_PSTR("read failed for register 0x%X, error %d"), reg, err); + this->status_set_warning(buf); + return 0; + } + this->status_clear_warning(); + return value; +} + +bool CH423Component::write_outputs_() { + bool success = true; + // Write IO7-IO0 + success &= this->write_reg_(CH423_REG_IO, static_cast(this->output_bits_)); + // Write OC7-OC0 + success &= this->write_reg_(CH423_REG_OCL, static_cast(this->output_bits_ >> 8)); + // Write OC15-OC8 + success &= this->write_reg_(CH423_REG_OCH, static_cast(this->output_bits_ >> 16)); + return success; +} + +float CH423Component::get_setup_priority() const { return setup_priority::IO; } + +// Run our loop() method very early in the loop, so that we cache read values +// before other components call our digital_read() method. +float CH423Component::get_loop_priority() const { return 9.0f; } // Just after WIFI + +void CH423GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } +bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } + +void CH423GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); } +size_t CH423GPIOPin::dump_summary(char *buffer, size_t len) const { + return snprintf(buffer, len, "EXIO%u via CH423", this->pin_); +} +void CH423GPIOPin::set_flags(gpio::Flags flags) { + flags_ = flags; + this->parent_->pin_mode(this->pin_, flags); +} + +} // namespace esphome::ch423 diff --git a/esphome/components/ch423/ch423.h b/esphome/components/ch423/ch423.h new file mode 100644 index 0000000000..7adc7de6a1 --- /dev/null +++ b/esphome/components/ch423/ch423.h @@ -0,0 +1,67 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome::ch423 { + +class CH423Component : public Component, public i2c::I2CDevice { + public: + CH423Component() = default; + + /// Check i2c availability and setup masks + void setup() override; + /// Poll for input changes periodically + void loop() override; + /// Helper function to read the value of a pin. + bool digital_read(uint8_t pin); + /// Helper function to write the value of a pin. + void digital_write(uint8_t pin, bool value); + /// Helper function to set the pin mode of a pin. + void pin_mode(uint8_t pin, gpio::Flags flags); + + float get_setup_priority() const override; + float get_loop_priority() const override; + void dump_config() override; + + protected: + bool write_reg_(uint8_t reg, uint8_t value); + uint8_t read_reg_(uint8_t reg); + bool read_inputs_(); + bool write_outputs_(); + + /// The mask to write as output state - 1 means HIGH, 0 means LOW + uint32_t output_bits_{0x00}; + /// Flags to check if read previously during this loop + uint8_t pin_read_flags_{0x00}; + /// Copy of last read values + uint8_t input_bits_{0x00}; + /// System parameters + uint8_t sys_params_{0x00}; +}; + +/// Helper class to expose a CH423 pin as a GPIO pin. +class CH423GPIOPin : public GPIOPin { + public: + void setup() override{}; + void pin_mode(gpio::Flags flags) override; + bool digital_read() override; + void digital_write(bool value) override; + size_t dump_summary(char *buffer, size_t len) const override; + + void set_parent(CH423Component *parent) { parent_ = parent; } + void set_pin(uint8_t pin) { pin_ = pin; } + void set_inverted(bool inverted) { inverted_ = inverted; } + void set_flags(gpio::Flags flags); + + gpio::Flags get_flags() const override { return this->flags_; } + + protected: + CH423Component *parent_{}; + uint8_t pin_{}; + bool inverted_{}; + gpio::Flags flags_{}; +}; + +} // namespace esphome::ch423 diff --git a/tests/components/ch423/common.yaml b/tests/components/ch423/common.yaml new file mode 100644 index 0000000000..ccf9170bd0 --- /dev/null +++ b/tests/components/ch423/common.yaml @@ -0,0 +1,36 @@ +ch423: + - id: ch423_hub + i2c_id: i2c_bus + +binary_sensor: + - platform: gpio + id: ch423_input + name: CH423 Binary Sensor + pin: + ch423: ch423_hub + number: 1 + mode: INPUT + inverted: true + - platform: gpio + id: ch423_input_2 + name: CH423 Binary Sensor 2 + pin: + ch423: ch423_hub + number: 0 + mode: INPUT + inverted: false +output: + - platform: gpio + id: ch423_out_11 + pin: + ch423: ch423_hub + number: 11 + mode: OUTPUT_OPEN_DRAIN + inverted: true + - platform: gpio + id: ch423_out_23 + pin: + ch423: ch423_hub + number: 23 + mode: OUTPUT_OPEN_DRAIN + inverted: false diff --git a/tests/components/ch423/test.esp32-idf.yaml b/tests/components/ch423/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/ch423/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/ch423/test.esp8266-ard.yaml b/tests/components/ch423/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/ch423/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/ch423/test.rp2040-ard.yaml b/tests/components/ch423/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/ch423/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml diff --git a/tests/unit_tests/components/test_ch423.py b/tests/unit_tests/components/test_ch423.py new file mode 100644 index 0000000000..ac79fe48fe --- /dev/null +++ b/tests/unit_tests/components/test_ch423.py @@ -0,0 +1,58 @@ +"""Tests for ch423 component validation.""" + +from unittest.mock import patch + +from esphome import config, yaml_util +from esphome.core import CORE + + +def test_ch423_mixed_gpio_modes_fails(tmp_path, capsys): + """Test that mixing input/output on GPIO pins 0-7 fails validation.""" + test_file = tmp_path / "test.yaml" + test_file.write_text(""" +esphome: + name: test + +esp8266: + board: esp01_1m + +i2c: + sda: GPIO4 + scl: GPIO5 + +ch423: + - id: ch423_hub + +binary_sensor: + - platform: gpio + name: "CH423 Input 0" + pin: + ch423: ch423_hub + number: 0 + mode: input + +switch: + - platform: gpio + name: "CH423 Output 1" + pin: + ch423: ch423_hub + number: 1 + mode: output +""") + + parsed_yaml = yaml_util.load_yaml(test_file) + + with ( + patch.object(yaml_util, "load_yaml", return_value=parsed_yaml), + patch.object(CORE, "config_path", test_file), + ): + result = config.read_config({}) + + assert result is None, "Expected validation to fail with mixed GPIO modes" + + # Check that the error message mentions the GPIO pin restriction + captured = capsys.readouterr() + assert ( + "GPIO pins (0-7) must all be configured as input or all as output" + in captured.out + ) From ed9a672f44327dd1e03e8d85bb05e671d729e6b0 Mon Sep 17 00:00:00 2001 From: esphomebot Date: Fri, 23 Jan 2026 10:15:42 +1300 Subject: [PATCH 0421/2030] Update webserver local assets to 20260122-204614 (#13455) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/web_server/server_index_v2.h | 2528 +-- .../components/web_server/server_index_v3.h | 15257 ++++++++-------- 2 files changed, 8961 insertions(+), 8824 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index b224354a6b..7c24ae28c6 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,1239 +10,1307 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xdb, 0x72, 0xe3, 0x46, 0x96, 0xe0, 0xf3, - 0xfa, 0x2b, 0x20, 0x58, 0x2d, 0x23, 0x9b, 0x49, 0xf0, 0x22, 0xa9, 0x4a, 0x05, 0x32, 0xc9, 0x56, 0xa9, 0xca, 0x5d, - 0x76, 0xd7, 0xcd, 0xa5, 0xb2, 0xdd, 0x6e, 0x5a, 0x2d, 0x42, 0x40, 0x92, 0x48, 0x17, 0x08, 0xd0, 0x40, 0x52, 0x17, - 0x93, 0x98, 0xd8, 0x0f, 0xd8, 0x88, 0x8d, 0xd8, 0xa7, 0x7d, 0xd9, 0xd8, 0x79, 0xd8, 0x8f, 0xd8, 0xe7, 0xf9, 0x94, - 0xf9, 0x81, 0xdd, 0x4f, 0xd8, 0x38, 0x79, 0x01, 0x12, 0xbc, 0xa8, 0x54, 0xb6, 0x7b, 0x66, 0x1e, 0x36, 0x1c, 0x56, - 0x11, 0x89, 0xbc, 0x9c, 0x3c, 0x79, 0xf2, 0xdc, 0x33, 0xd1, 0xdf, 0x0b, 0xd3, 0x80, 0xdf, 0xcd, 0xa9, 0x15, 0xf1, - 0x59, 0x3c, 0xe8, 0xab, 0xbf, 0xd4, 0x0f, 0x07, 0xfd, 0x98, 0x25, 0x1f, 0xac, 0x8c, 0xc6, 0x84, 0x05, 0x69, 0x62, - 0x45, 0x19, 0x9d, 0x90, 0xd0, 0xe7, 0xbe, 0xc7, 0x66, 0xfe, 0x94, 0x5a, 0xad, 0x41, 0x7f, 0x46, 0xb9, 0x6f, 0x05, - 0x91, 0x9f, 0xe5, 0x94, 0x93, 0x6f, 0xdf, 0x7f, 0xd9, 0x3c, 0x19, 0xf4, 0xf3, 0x20, 0x63, 0x73, 0x6e, 0x41, 0x97, - 0x64, 0x96, 0x86, 0x8b, 0x98, 0x0e, 0x5a, 0xad, 0x9b, 0x9b, 0x1b, 0xf7, 0xa7, 0xfc, 0xb3, 0x20, 0x4d, 0x72, 0x6e, - 0xbd, 0x24, 0x37, 0x2c, 0x09, 0xd3, 0x1b, 0xcc, 0x38, 0x79, 0xe9, 0x9e, 0x47, 0x7e, 0x98, 0xde, 0xbc, 0x4b, 0x53, - 0x7e, 0x70, 0xe0, 0xc8, 0xc7, 0xbb, 0xb3, 0xf3, 0x73, 0x42, 0xc8, 0x75, 0xca, 0x42, 0xab, 0xbd, 0x5a, 0x55, 0x85, - 0x6e, 0xe2, 0x73, 0x76, 0x4d, 0x65, 0x13, 0x74, 0x70, 0x60, 0xfb, 0x61, 0x3a, 0xe7, 0x34, 0x3c, 0xe7, 0x77, 0x31, - 0x3d, 0x8f, 0x28, 0xe5, 0xb9, 0xcd, 0x12, 0xeb, 0x59, 0x1a, 0x2c, 0x66, 0x34, 0xe1, 0xee, 0x3c, 0x4b, 0x79, 0x0a, - 0x90, 0x1c, 0x1c, 0xd8, 0x19, 0x9d, 0xc7, 0x7e, 0x40, 0xe1, 0xfd, 0xd9, 0xf9, 0x79, 0xd5, 0xa2, 0xaa, 0x84, 0x73, - 0x4e, 0xce, 0xef, 0x66, 0x57, 0x69, 0xec, 0x20, 0x1c, 0x73, 0x92, 0xd0, 0x1b, 0xeb, 0x7b, 0xea, 0x7f, 0x78, 0xe5, - 0xcf, 0x7b, 0x41, 0xec, 0xe7, 0xb9, 0x75, 0xcb, 0x97, 0x62, 0x0a, 0xd9, 0x22, 0xe0, 0x69, 0xe6, 0x70, 0x4c, 0x31, - 0x43, 0x4b, 0x36, 0x71, 0x78, 0xc4, 0x72, 0xf7, 0x72, 0x3f, 0xc8, 0xf3, 0x77, 0x34, 0x5f, 0xc4, 0x7c, 0x9f, 0xec, - 0xb5, 0x31, 0xdb, 0x23, 0x24, 0xe7, 0x88, 0x47, 0x59, 0x7a, 0x63, 0x3d, 0xcf, 0xb2, 0x34, 0x73, 0xec, 0xb3, 0xf3, - 0x73, 0x59, 0xc3, 0x62, 0xb9, 0x95, 0xa4, 0xdc, 0x2a, 0xfb, 0xf3, 0xaf, 0x62, 0xea, 0x5a, 0xdf, 0xe6, 0xd4, 0x1a, - 0x2f, 0x92, 0xdc, 0x9f, 0xd0, 0xb3, 0xf3, 0xf3, 0xb1, 0x95, 0x66, 0xd6, 0x38, 0xc8, 0xf3, 0xb1, 0xc5, 0x92, 0x9c, - 0x53, 0x3f, 0x74, 0x6d, 0xd4, 0x13, 0x83, 0x05, 0x79, 0xfe, 0x9e, 0xde, 0x72, 0xc2, 0xb1, 0x78, 0xe4, 0x84, 0x16, - 0x53, 0xca, 0xad, 0xbc, 0x9c, 0x97, 0x83, 0x96, 0x31, 0xe5, 0x16, 0x27, 0xe2, 0x7d, 0xda, 0x93, 0xb8, 0xa7, 0xf2, - 0x91, 0xf7, 0xd8, 0xc4, 0x61, 0xfc, 0xe0, 0x80, 0x97, 0x78, 0x46, 0x72, 0x6a, 0x16, 0x23, 0x74, 0x4f, 0x97, 0x1d, - 0x1c, 0x50, 0x37, 0xa6, 0xc9, 0x94, 0x47, 0x84, 0x90, 0x4e, 0x8f, 0x1d, 0x1c, 0x38, 0x9c, 0xc4, 0xdc, 0x9d, 0x52, - 0xee, 0x50, 0x84, 0x70, 0xd5, 0xfa, 0xe0, 0xc0, 0x91, 0x48, 0x48, 0x89, 0x44, 0x5c, 0x0d, 0xc7, 0xc8, 0x55, 0xd8, - 0x3f, 0xbf, 0x4b, 0x02, 0xc7, 0x84, 0x1f, 0x61, 0x76, 0x70, 0x10, 0x73, 0x37, 0x87, 0x1e, 0x31, 0x47, 0xa8, 0xc8, - 0x28, 0x5f, 0x64, 0x89, 0xc5, 0x0b, 0x9e, 0x9e, 0xf3, 0x8c, 0x25, 0x53, 0x07, 0x2d, 0x75, 0x99, 0xd1, 0xb0, 0x28, - 0x24, 0xb8, 0xaf, 0x39, 0x49, 0xc8, 0x00, 0x46, 0xbc, 0xe5, 0x0e, 0xac, 0x62, 0x3a, 0xb1, 0x12, 0x42, 0xec, 0x5c, - 0xb4, 0xb5, 0x87, 0x89, 0x97, 0x34, 0x6c, 0x1b, 0x4b, 0x28, 0x71, 0xce, 0x11, 0xfe, 0x40, 0x9c, 0x04, 0xbb, 0xae, - 0xcb, 0x11, 0x19, 0x2c, 0x35, 0x56, 0x12, 0x63, 0x9e, 0xc3, 0x64, 0xd4, 0xbe, 0xf0, 0xb8, 0x9b, 0xd1, 0x70, 0x11, - 0x50, 0xc7, 0x61, 0x38, 0xc7, 0x19, 0x22, 0x03, 0xd6, 0x70, 0x52, 0x32, 0x80, 0xe5, 0x4e, 0xeb, 0x6b, 0x4d, 0xc8, - 0x5e, 0x1b, 0x29, 0x18, 0x53, 0x0d, 0x20, 0x60, 0x58, 0xc1, 0x93, 0x12, 0x62, 0x27, 0x8b, 0xd9, 0x15, 0xcd, 0xec, - 0xb2, 0x5a, 0xaf, 0x46, 0x16, 0x8b, 0x9c, 0x5a, 0x41, 0x9e, 0x5b, 0x93, 0x45, 0x12, 0x70, 0x96, 0x26, 0x96, 0xdd, - 0x48, 0x1b, 0xb6, 0x24, 0x87, 0x92, 0x1a, 0x6c, 0x54, 0x20, 0x27, 0x47, 0x8d, 0x64, 0x94, 0x35, 0x3a, 0x17, 0x18, - 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0xef, 0x38, 0xcc, 0x52, 0x4c, 0x91, 0xf1, - 0x61, 0xe2, 0x6e, 0x6e, 0x14, 0xc2, 0xdd, 0x99, 0x3f, 0x77, 0x28, 0x19, 0x50, 0x41, 0x5c, 0x7e, 0x12, 0x00, 0xac, - 0xb5, 0x75, 0x1b, 0x52, 0x8f, 0xba, 0x15, 0x49, 0x21, 0x8f, 0xbb, 0x93, 0x34, 0x7b, 0xee, 0x07, 0x11, 0xb4, 0x2b, - 0x09, 0x26, 0xd4, 0xfb, 0x2d, 0xc8, 0xa8, 0xcf, 0xe9, 0xf3, 0x98, 0xc2, 0x93, 0x63, 0x8b, 0x96, 0x36, 0xc2, 0x39, - 0x79, 0xe9, 0xc6, 0x8c, 0xbf, 0x4e, 0x93, 0x80, 0xf6, 0x72, 0x83, 0xba, 0x18, 0xac, 0xfb, 0x29, 0xe7, 0x19, 0xbb, - 0x5a, 0x70, 0xea, 0xd8, 0x09, 0xd4, 0xb0, 0x71, 0x8e, 0x30, 0x73, 0x39, 0xbd, 0xe5, 0x67, 0x69, 0xc2, 0x69, 0xc2, - 0x09, 0xd5, 0x48, 0xc5, 0x89, 0xeb, 0xcf, 0xe7, 0x34, 0x09, 0xcf, 0x22, 0x16, 0x87, 0x0e, 0x43, 0x05, 0x2a, 0x70, - 0xc4, 0x09, 0xcc, 0x91, 0x0c, 0x12, 0x0f, 0xfe, 0xec, 0x9e, 0x8d, 0xc3, 0xc9, 0x40, 0x6c, 0x0a, 0x4a, 0x6c, 0xbb, - 0x37, 0x49, 0x33, 0x47, 0xcd, 0xc0, 0x4a, 0x27, 0x16, 0x87, 0x31, 0xde, 0x2d, 0x62, 0x9a, 0x23, 0xda, 0x20, 0xac, - 0x5c, 0x46, 0x85, 0xe0, 0xd7, 0x40, 0xf1, 0x05, 0x72, 0x12, 0xe4, 0x25, 0xbd, 0x6b, 0x3f, 0xb3, 0xbe, 0x57, 0x3b, - 0xea, 0x99, 0xe6, 0x66, 0x01, 0x27, 0xcf, 0x5c, 0x9e, 0x2d, 0x72, 0x4e, 0xc3, 0xf7, 0x77, 0x73, 0x9a, 0xe3, 0xa7, - 0x9c, 0x04, 0x7c, 0x18, 0x70, 0x97, 0xce, 0xe6, 0xfc, 0xee, 0x5c, 0x30, 0x46, 0xcf, 0xb6, 0x71, 0x08, 0x35, 0x33, - 0xea, 0x07, 0xc0, 0xcc, 0x14, 0xb6, 0xde, 0xa6, 0xf1, 0xdd, 0x84, 0xc5, 0xf1, 0xf9, 0x62, 0x3e, 0x4f, 0x33, 0x8e, - 0xff, 0x4a, 0x96, 0x3c, 0xad, 0x50, 0x03, 0x6b, 0xb9, 0xcc, 0x6f, 0x18, 0x0f, 0x22, 0x87, 0xa3, 0x65, 0xe0, 0xe7, - 0xd4, 0x7a, 0x9a, 0xa6, 0x31, 0xf5, 0x61, 0xd2, 0xc9, 0xf0, 0x29, 0xf7, 0x92, 0x45, 0x1c, 0xf7, 0xae, 0x32, 0xea, - 0x7f, 0xe8, 0x89, 0xd7, 0x6f, 0xae, 0x7e, 0xa2, 0x01, 0xf7, 0xc4, 0xef, 0xd3, 0x2c, 0xf3, 0xef, 0xa0, 0x22, 0x21, - 0x50, 0x6d, 0x98, 0x78, 0x5f, 0x9f, 0xbf, 0x79, 0xed, 0xca, 0x4d, 0xc2, 0x26, 0x77, 0x4e, 0x52, 0x6e, 0xbc, 0xa4, - 0xc0, 0x93, 0x2c, 0x9d, 0xad, 0x0d, 0x2d, 0xb1, 0x96, 0xf4, 0x76, 0x80, 0x40, 0x49, 0xb2, 0x27, 0xbb, 0x36, 0x21, - 0x78, 0x2d, 0x68, 0x1e, 0x5e, 0x12, 0x3d, 0xee, 0x22, 0x8e, 0x3d, 0x59, 0xec, 0x24, 0xe8, 0x7e, 0x68, 0x79, 0x76, - 0xb7, 0xa4, 0x44, 0xc0, 0x39, 0x07, 0x09, 0x03, 0x30, 0x06, 0x3e, 0x0f, 0xa2, 0x25, 0x15, 0x9d, 0x15, 0x1a, 0x62, - 0x5a, 0x14, 0xf8, 0xb4, 0xa4, 0x77, 0x0e, 0x80, 0x08, 0x46, 0x45, 0xf8, 0x6a, 0x05, 0x13, 0x46, 0xf8, 0x6f, 0x64, - 0xe9, 0xeb, 0xf9, 0x78, 0x7b, 0x6d, 0x0c, 0xfb, 0xd2, 0x93, 0xdc, 0x05, 0x07, 0x69, 0x72, 0x4d, 0x33, 0x4e, 0x33, - 0xef, 0xaf, 0x38, 0xa3, 0x93, 0x18, 0xa0, 0xd8, 0xeb, 0xe0, 0xc8, 0xcf, 0xcf, 0x22, 0x3f, 0x99, 0xd2, 0xd0, 0x3b, - 0xe5, 0x05, 0xe6, 0x9c, 0xd8, 0x13, 0x96, 0xf8, 0x31, 0xfb, 0x85, 0x86, 0xb6, 0x12, 0x07, 0xcf, 0x2d, 0x7a, 0xcb, - 0x69, 0x12, 0xe6, 0xd6, 0x8b, 0xf7, 0xaf, 0x5e, 0xaa, 0x85, 0xac, 0x49, 0x08, 0xb4, 0xcc, 0x17, 0x73, 0x9a, 0x39, - 0x08, 0x2b, 0x09, 0xf1, 0x9c, 0x09, 0xee, 0xf8, 0xca, 0x9f, 0xcb, 0x12, 0x96, 0x7f, 0x3b, 0x0f, 0x7d, 0x4e, 0xdf, - 0xd2, 0x24, 0x64, 0xc9, 0x94, 0xec, 0x75, 0x64, 0x79, 0xe4, 0xab, 0x17, 0x61, 0x59, 0x74, 0xb9, 0xff, 0x3c, 0x16, - 0x13, 0x2f, 0x1f, 0x17, 0x0e, 0x2a, 0x72, 0xee, 0x73, 0x16, 0x58, 0x7e, 0x18, 0x7e, 0x95, 0x30, 0xce, 0x04, 0x80, - 0x19, 0xac, 0x0f, 0xd0, 0x28, 0x95, 0xb2, 0x42, 0x03, 0xee, 0x20, 0xec, 0x38, 0x4a, 0x02, 0x44, 0x48, 0x2d, 0xd8, - 0xc1, 0x41, 0xc5, 0xef, 0x87, 0xd4, 0x93, 0x2f, 0xc9, 0xe8, 0x02, 0xb9, 0xf3, 0x45, 0x0e, 0x2b, 0xad, 0x87, 0x00, - 0xf1, 0x92, 0x5e, 0xe5, 0x34, 0xbb, 0xa6, 0x61, 0x49, 0x1d, 0xb9, 0x83, 0x96, 0x6b, 0x63, 0xa8, 0x7d, 0xc1, 0xc9, - 0xe8, 0xa2, 0x67, 0x32, 0x6e, 0xaa, 0x08, 0x3d, 0x4b, 0xe7, 0x34, 0xe3, 0x8c, 0xe6, 0x25, 0x2f, 0x71, 0x40, 0x8c, - 0x96, 0xfc, 0x24, 0x27, 0x7a, 0x7e, 0x73, 0x87, 0x61, 0x8a, 0x6a, 0x1c, 0x43, 0x4b, 0xda, 0xe7, 0xd7, 0x42, 0x64, - 0xe4, 0x98, 0x21, 0xcc, 0x25, 0xa4, 0x39, 0x42, 0x05, 0xc2, 0x5c, 0x83, 0x2b, 0x79, 0x91, 0x1a, 0xed, 0x0e, 0x64, - 0x35, 0xf9, 0x9b, 0x90, 0xd5, 0xc0, 0xd1, 0x7c, 0x4e, 0x0f, 0x0e, 0x1c, 0xea, 0x96, 0x54, 0x41, 0xf6, 0x3a, 0x6a, - 0x8d, 0x0c, 0x64, 0xed, 0x00, 0x1b, 0x06, 0xe6, 0x98, 0x22, 0xbc, 0x47, 0xdd, 0x24, 0x3d, 0x0d, 0x02, 0x9a, 0xe7, - 0x69, 0x76, 0x70, 0xb0, 0x27, 0xea, 0x97, 0xea, 0x04, 0xac, 0xe1, 0x9b, 0x9b, 0xa4, 0x82, 0x00, 0x55, 0x22, 0x56, - 0x09, 0x06, 0x0e, 0x82, 0x4a, 0x68, 0x1c, 0xf6, 0x50, 0x6b, 0x1e, 0x9e, 0x7d, 0x79, 0x69, 0x37, 0x38, 0x56, 0x68, - 0x98, 0x52, 0x3d, 0xf4, 0xdd, 0x33, 0x2a, 0x75, 0x2b, 0xa1, 0x79, 0x6c, 0x60, 0x46, 0x6e, 0x20, 0x37, 0xa4, 0x13, - 0x96, 0x18, 0xd3, 0xae, 0x81, 0x84, 0x39, 0xce, 0x51, 0x61, 0x2c, 0xe8, 0xd6, 0xae, 0x85, 0x52, 0x23, 0x57, 0x6e, - 0x39, 0x15, 0x8a, 0x84, 0xb1, 0x8c, 0x23, 0x7a, 0x51, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x4c, 0x00, 0x3a, 0xe2, 0x17, - 0x3d, 0xf5, 0x9e, 0xe4, 0x12, 0x73, 0x19, 0xfd, 0x79, 0x41, 0x73, 0x2e, 0xe9, 0xd8, 0xe1, 0x38, 0xc3, 0x0c, 0x15, - 0xb0, 0xdf, 0x26, 0x6c, 0xba, 0xc8, 0x40, 0xdf, 0x81, 0xbd, 0x48, 0x93, 0xc5, 0x8c, 0xea, 0xa7, 0x6d, 0xb0, 0xbd, - 0x99, 0x83, 0x44, 0xcc, 0x81, 0xa6, 0xef, 0x27, 0x27, 0x80, 0x95, 0xa3, 0xd5, 0xea, 0x6f, 0xba, 0x93, 0x6a, 0x29, - 0x4b, 0x1d, 0x6d, 0x7d, 0x4d, 0x38, 0x52, 0x12, 0x79, 0xaf, 0x23, 0xc1, 0xe7, 0xfc, 0x82, 0xec, 0xb5, 0x4b, 0x1a, - 0x56, 0x58, 0x95, 0xe0, 0x48, 0x24, 0xbe, 0x91, 0x5d, 0x21, 0x21, 0xe0, 0x6b, 0xe4, 0xe2, 0x46, 0x1b, 0x94, 0x1a, - 0x91, 0x11, 0xa8, 0x1a, 0x6e, 0x74, 0xb1, 0x8b, 0x9c, 0x34, 0x3f, 0x70, 0xf8, 0xe6, 0xbb, 0x8a, 0x6d, 0x5c, 0xd7, - 0xd9, 0xc6, 0xda, 0x34, 0xec, 0x79, 0xd9, 0xc4, 0x2e, 0xa9, 0x4c, 0x6d, 0xf4, 0xea, 0x15, 0x66, 0x02, 0x98, 0x6a, - 0x4a, 0x46, 0x17, 0xaf, 0xfd, 0x19, 0xcd, 0x1d, 0x8a, 0xf0, 0xae, 0x0a, 0x92, 0x3c, 0xa1, 0xca, 0x85, 0x21, 0x39, - 0x73, 0x90, 0x9c, 0x0c, 0x49, 0xc5, 0xac, 0xbe, 0xe1, 0x72, 0x4c, 0x47, 0xf9, 0x45, 0xa5, 0xcf, 0x19, 0x93, 0x17, - 0x22, 0x59, 0xd1, 0xb7, 0xc6, 0x9f, 0x2c, 0x93, 0x48, 0x13, 0x7a, 0x43, 0x8e, 0xf0, 0x5e, 0x7b, 0x7d, 0x25, 0x75, - 0xad, 0x6a, 0x8e, 0xa3, 0x0b, 0x58, 0x07, 0x21, 0x31, 0x5c, 0x96, 0x8b, 0x7f, 0x6b, 0x3b, 0x0d, 0xd0, 0x76, 0x0e, - 0x84, 0xe1, 0x4e, 0x62, 0x9f, 0x3b, 0x9d, 0x56, 0x1b, 0x94, 0xd1, 0x6b, 0x0a, 0x02, 0x05, 0xa1, 0xcd, 0xa9, 0x50, - 0x77, 0x91, 0xe4, 0x11, 0x9b, 0x70, 0x27, 0xe2, 0x82, 0xa5, 0xd0, 0x38, 0xa7, 0x16, 0xaf, 0xa9, 0xc4, 0x82, 0xdd, - 0x44, 0x40, 0x6c, 0xa5, 0xfe, 0x45, 0x35, 0xa4, 0x82, 0x6d, 0x01, 0x77, 0xa8, 0xd4, 0xe9, 0x8a, 0xcb, 0xe8, 0xda, - 0x0c, 0x54, 0xc6, 0xce, 0x50, 0xf6, 0xe8, 0x29, 0x66, 0xc0, 0x0c, 0xad, 0x95, 0x79, 0x26, 0x87, 0x50, 0x85, 0xdc, - 0xe5, 0xe9, 0xcb, 0xf4, 0x86, 0x66, 0x67, 0x3e, 0x00, 0xef, 0xc9, 0xe6, 0x85, 0x14, 0x04, 0x82, 0xdf, 0xf3, 0x9e, - 0xa6, 0x97, 0x4b, 0x31, 0xf1, 0xb7, 0x59, 0x3a, 0x63, 0x39, 0x05, 0x65, 0x4d, 0xe2, 0x3f, 0x81, 0x7d, 0x26, 0x36, - 0x24, 0x08, 0x1b, 0x5a, 0xd2, 0xd7, 0xe9, 0xcb, 0x3a, 0x7d, 0x5d, 0xee, 0x3f, 0x9f, 0x6a, 0x06, 0x58, 0xdf, 0xc6, - 0x08, 0x3b, 0xca, 0xa4, 0x30, 0xe4, 0x9c, 0x1b, 0x21, 0x25, 0xe1, 0x57, 0x2b, 0x6e, 0x58, 0x6e, 0x35, 0x75, 0x91, - 0xca, 0x6d, 0x83, 0x0a, 0x3f, 0x0c, 0x41, 0xb1, 0xcb, 0xd2, 0x38, 0x36, 0x44, 0x15, 0x66, 0xbd, 0x52, 0x38, 0x5d, - 0xee, 0x3f, 0x3f, 0xbf, 0x4f, 0x3e, 0xc1, 0x7b, 0x53, 0x44, 0x69, 0x40, 0x93, 0x90, 0x66, 0x60, 0x49, 0x1a, 0xab, - 0xa5, 0xa4, 0xec, 0x59, 0x9a, 0x24, 0x34, 0xe0, 0x34, 0x04, 0x43, 0x85, 0x11, 0xee, 0x46, 0x69, 0xce, 0xcb, 0xc2, - 0x0a, 0x7a, 0x66, 0x40, 0xcf, 0xdc, 0xc0, 0x8f, 0x63, 0x47, 0x1a, 0x25, 0xb3, 0xf4, 0x9a, 0x6e, 0x81, 0xba, 0x57, - 0x03, 0xb9, 0xec, 0x86, 0x1a, 0xdd, 0x50, 0x37, 0x9f, 0xc7, 0x2c, 0xa0, 0xa5, 0xe8, 0x3a, 0x77, 0x59, 0x12, 0xd2, - 0x5b, 0xe0, 0x23, 0x68, 0x30, 0x18, 0xb4, 0x71, 0x07, 0x15, 0x12, 0xe1, 0xcb, 0x0d, 0xc4, 0xde, 0x23, 0x34, 0x81, - 0xc8, 0xc8, 0x60, 0xb9, 0x8d, 0x1f, 0x50, 0x64, 0x48, 0x4a, 0xa6, 0x8d, 0x2b, 0xc9, 0x9d, 0x11, 0x0e, 0x69, 0x4c, - 0x39, 0xd5, 0xdc, 0x1c, 0x54, 0x68, 0xb9, 0x75, 0xdf, 0x95, 0xf8, 0x2b, 0xc9, 0x49, 0xef, 0x32, 0xbd, 0xe6, 0x79, - 0x69, 0xac, 0x57, 0xcb, 0x53, 0x61, 0x7b, 0xc8, 0xe5, 0xf2, 0xf8, 0x9c, 0xfb, 0x41, 0x24, 0xad, 0x74, 0x67, 0x63, - 0x4a, 0x55, 0x1f, 0x8a, 0xb3, 0x97, 0x9b, 0xe8, 0x9d, 0x06, 0x73, 0x1b, 0x0a, 0xce, 0x15, 0x53, 0xa0, 0x60, 0xf8, - 0xc9, 0x65, 0x3b, 0xf3, 0xe3, 0xf8, 0xca, 0x0f, 0x3e, 0xd4, 0xa9, 0xbf, 0x22, 0x03, 0xb2, 0xce, 0x8d, 0x8d, 0x57, - 0x06, 0xcb, 0x32, 0xe7, 0xad, 0xb9, 0x74, 0x6d, 0xa3, 0x38, 0x7b, 0xed, 0x8a, 0xec, 0xeb, 0x0b, 0xbd, 0x93, 0xda, - 0x05, 0x44, 0x4c, 0xcd, 0xcc, 0x01, 0x2e, 0xf0, 0x51, 0x8a, 0xd3, 0xfc, 0x40, 0xd1, 0x1d, 0x98, 0x1b, 0xc5, 0x1a, - 0x20, 0x1c, 0x2d, 0x8b, 0x90, 0xe5, 0xbb, 0x31, 0xf0, 0xbb, 0x40, 0xf9, 0xcc, 0x18, 0xe1, 0xa1, 0x80, 0x96, 0x3c, - 0x4e, 0x69, 0xcd, 0x25, 0x64, 0x4a, 0x9f, 0xd0, 0x8c, 0xe6, 0x2f, 0xa0, 0xbb, 0x08, 0x7a, 0x7f, 0x23, 0x5f, 0x81, - 0x56, 0x06, 0x50, 0xe4, 0x3d, 0x53, 0x9d, 0xa8, 0x51, 0x80, 0xe2, 0xa9, 0x4c, 0x88, 0xdc, 0xac, 0x66, 0x3f, 0x2a, - 0x8d, 0x5d, 0x9a, 0xe0, 0x8a, 0xe5, 0xa6, 0xc4, 0x71, 0x9c, 0x1c, 0x4c, 0x38, 0xad, 0xda, 0x57, 0x93, 0xc8, 0x37, - 0x26, 0x91, 0xbb, 0x86, 0x9d, 0x85, 0x2a, 0x5a, 0x36, 0x9a, 0x7b, 0x7f, 0x45, 0x66, 0x25, 0x50, 0x57, 0x5d, 0xe0, - 0xcf, 0xa8, 0x64, 0xb7, 0x31, 0xe1, 0x38, 0x55, 0x36, 0x8e, 0xa2, 0x34, 0x60, 0x18, 0x55, 0x93, 0x0c, 0xc9, 0xad, - 0x51, 0xb3, 0x77, 0x33, 0x9c, 0xa2, 0x35, 0xdd, 0xbe, 0x28, 0x14, 0x8e, 0x28, 0x52, 0x6b, 0x53, 0x53, 0x8a, 0x0d, - 0xac, 0xe0, 0x8c, 0x28, 0x45, 0x58, 0xea, 0x3d, 0xeb, 0xb8, 0x29, 0xfb, 0xdd, 0x23, 0x24, 0xab, 0x50, 0x53, 0xd3, - 0x28, 0xb5, 0x6a, 0x95, 0x21, 0x1c, 0x69, 0x9d, 0x34, 0xad, 0xe6, 0x4d, 0x88, 0xad, 0x1d, 0x12, 0xf6, 0x70, 0x59, - 0xb3, 0x0a, 0x3d, 0xa3, 0x5a, 0xe1, 0x01, 0x4b, 0x4d, 0xb7, 0xa1, 0x7b, 0x1b, 0xcd, 0xd4, 0xfa, 0x31, 0x10, 0x9e, - 0x9a, 0x08, 0x37, 0x30, 0x9b, 0x49, 0xce, 0x95, 0x5d, 0x90, 0xa8, 0xde, 0xd6, 0xa1, 0x38, 0x95, 0xeb, 0xb0, 0x81, - 0xc4, 0x75, 0xd5, 0x53, 0x90, 0x20, 0xd8, 0xb0, 0x39, 0x28, 0x77, 0xa6, 0x7c, 0x70, 0x00, 0x76, 0xb6, 0x5a, 0x6d, - 0x10, 0xdd, 0x56, 0x0d, 0x14, 0xb9, 0x95, 0x5d, 0xb8, 0x5a, 0x9d, 0x72, 0xe4, 0x28, 0xdd, 0x17, 0x53, 0x34, 0xd4, - 0x1c, 0xf7, 0xf4, 0x25, 0xd4, 0x12, 0xaa, 0x68, 0x55, 0x52, 0x1a, 0x0d, 0x75, 0x9a, 0xad, 0xaf, 0x13, 0x37, 0xd8, - 0xf6, 0xd9, 0x06, 0xf7, 0x12, 0x85, 0x4a, 0x4c, 0x57, 0x53, 0x3e, 0x53, 0x5d, 0x33, 0x84, 0x90, 0x97, 0x0b, 0x3b, - 0x66, 0x6f, 0x9b, 0x69, 0x79, 0x70, 0x90, 0x1b, 0x1d, 0x5d, 0x96, 0x6c, 0xe2, 0x27, 0x07, 0x44, 0x72, 0x7e, 0x97, - 0x08, 0xdd, 0xe5, 0x27, 0x2d, 0x84, 0x36, 0x0c, 0xd3, 0x76, 0x0f, 0x0c, 0x72, 0xff, 0xc6, 0x67, 0xdc, 0x2a, 0x7b, - 0x91, 0x06, 0xb9, 0x43, 0xd1, 0x52, 0xa9, 0x1a, 0x6e, 0x46, 0x41, 0x79, 0x04, 0x9e, 0xa0, 0x55, 0x68, 0x49, 0xf7, - 0x41, 0x44, 0xc1, 0x17, 0xac, 0xb5, 0x88, 0xd2, 0x32, 0xdc, 0x53, 0x52, 0x44, 0x75, 0xbc, 0x1d, 0xf6, 0x62, 0xbd, - 0x79, 0xcd, 0x12, 0x98, 0xd3, 0x6c, 0x92, 0x66, 0x33, 0xfd, 0xae, 0x58, 0x7b, 0x56, 0x9c, 0x91, 0x4d, 0x9c, 0xad, - 0x7d, 0x2b, 0xfd, 0xbf, 0xb7, 0x66, 0x76, 0x57, 0x06, 0x7b, 0x4d, 0x94, 0x96, 0xd2, 0x57, 0xba, 0x04, 0x35, 0x65, - 0xe6, 0xa6, 0x81, 0xaf, 0xfc, 0xa9, 0x3d, 0xe9, 0x33, 0xd9, 0xeb, 0xf4, 0x4a, 0xab, 0x4f, 0x53, 0x43, 0x4f, 0xfa, - 0x36, 0x94, 0x48, 0x4d, 0x17, 0x71, 0xa8, 0x80, 0x65, 0x08, 0x53, 0x45, 0x47, 0x37, 0x2c, 0x8e, 0xab, 0xd2, 0x4f, - 0xe1, 0xeb, 0xb9, 0xe2, 0xeb, 0x99, 0xe6, 0xeb, 0xc0, 0x29, 0x80, 0xaf, 0xcb, 0xee, 0xaa, 0xe6, 0xd9, 0xc6, 0xee, - 0xcc, 0x24, 0x47, 0xcf, 0x85, 0x25, 0x0d, 0xe3, 0x2d, 0x34, 0x04, 0xa8, 0xd4, 0xbc, 0x3e, 0x38, 0xca, 0x0f, 0x03, - 0x26, 0xa0, 0xf4, 0x62, 0x52, 0xd3, 0x49, 0xf1, 0xc1, 0x41, 0x38, 0x2f, 0x68, 0x49, 0xd9, 0xa7, 0xcf, 0xc1, 0x4f, - 0x67, 0x4c, 0x07, 0x84, 0x98, 0x28, 0xfe, 0x24, 0x25, 0x4a, 0xcf, 0x8e, 0xa9, 0xd9, 0xe5, 0x7a, 0x76, 0xc0, 0xe9, - 0xab, 0xd9, 0x85, 0xf7, 0xf3, 0x7a, 0x31, 0x3d, 0x56, 0x4e, 0xaf, 0x5a, 0xef, 0xd5, 0xca, 0x59, 0x2b, 0x01, 0x17, - 0xbe, 0x32, 0x51, 0xb2, 0xb2, 0x77, 0xe0, 0x01, 0x26, 0x66, 0xa0, 0xa0, 0x90, 0x93, 0x2e, 0x45, 0xdc, 0xcb, 0x8f, - 0xb9, 0x78, 0x84, 0xa7, 0x5e, 0xb6, 0x3f, 0x4b, 0x67, 0x73, 0xd0, 0xc6, 0xd6, 0x48, 0x7a, 0x4a, 0xd5, 0x80, 0xd5, - 0xfb, 0x62, 0x4b, 0x59, 0xad, 0x8d, 0xd8, 0x8f, 0x35, 0x6a, 0x2a, 0x2d, 0xe6, 0xbd, 0x76, 0xb1, 0x28, 0x8b, 0x4a, - 0xc6, 0xb1, 0xcd, 0xad, 0x72, 0xb6, 0xee, 0x94, 0xd1, 0x2f, 0xde, 0x38, 0x4c, 0xf2, 0x61, 0x06, 0xbc, 0xce, 0x60, - 0x3f, 0x9a, 0xdc, 0xcd, 0xf5, 0x2f, 0x2a, 0xe4, 0x2c, 0x8b, 0x35, 0xf4, 0x2d, 0x8b, 0xe2, 0xb9, 0xb2, 0xb2, 0xf1, - 0xf3, 0xdd, 0xe6, 0x70, 0xf5, 0x4e, 0x59, 0x8b, 0xa3, 0x0b, 0xfc, 0x7c, 0x53, 0x77, 0x24, 0xcb, 0x59, 0x1a, 0x52, - 0xcf, 0x4e, 0xe7, 0x34, 0xb1, 0x0b, 0xf0, 0xac, 0xaa, 0xc5, 0x0f, 0xb9, 0xb3, 0x7c, 0x57, 0x77, 0xb1, 0x7a, 0xcf, - 0x0b, 0x70, 0x80, 0x7d, 0xbf, 0xe9, 0x7c, 0xfd, 0x8e, 0x66, 0xb9, 0xd0, 0x44, 0x4b, 0xa5, 0xf6, 0xfb, 0x4a, 0x2e, - 0x7d, 0xef, 0xed, 0xac, 0x5f, 0xd9, 0x20, 0x76, 0xc7, 0x7d, 0xe4, 0x1e, 0xda, 0x48, 0xb8, 0x86, 0xbf, 0x56, 0x3b, - 0xfe, 0x27, 0xed, 0x1a, 0x3e, 0x27, 0x3f, 0xd5, 0x3d, 0xc3, 0x0b, 0x4e, 0xce, 0x87, 0xe7, 0xda, 0x64, 0x4e, 0x63, - 0x16, 0xdc, 0x39, 0x76, 0xcc, 0x78, 0x13, 0xc2, 0x6f, 0x36, 0x5e, 0xca, 0x17, 0xe0, 0x55, 0x14, 0x2e, 0xed, 0x42, - 0x1b, 0x7b, 0x98, 0x72, 0x62, 0xef, 0xc7, 0x8c, 0xef, 0xdb, 0x78, 0x42, 0xc6, 0xf0, 0x63, 0x7f, 0xe9, 0xbc, 0xf2, - 0x79, 0xe4, 0x66, 0x7e, 0x12, 0xa6, 0x33, 0x07, 0x35, 0x6c, 0x1b, 0xb9, 0xb9, 0x30, 0x38, 0x9e, 0xa0, 0x62, 0x7f, - 0x8c, 0x9f, 0x73, 0x62, 0x0f, 0xed, 0xc6, 0x04, 0xbf, 0xe0, 0x64, 0xdc, 0xdf, 0x5f, 0x3e, 0xe7, 0xc5, 0x60, 0x8c, - 0x6f, 0x4b, 0xaf, 0x3d, 0xfe, 0x96, 0x38, 0x88, 0x0c, 0x6e, 0x15, 0x34, 0x67, 0xe9, 0x4c, 0x7a, 0xef, 0x6d, 0x84, - 0xdf, 0x8b, 0xd8, 0x4a, 0xc5, 0x6e, 0x54, 0x78, 0x65, 0x8f, 0xd8, 0xa9, 0xf0, 0x11, 0xd8, 0x07, 0x07, 0x46, 0x59, - 0xa9, 0x2b, 0xe0, 0x73, 0x4e, 0x6a, 0x16, 0x39, 0x7e, 0x25, 0xa2, 0x34, 0xe7, 0xdc, 0x49, 0x90, 0xee, 0xc6, 0xd1, - 0xbe, 0x68, 0xb5, 0x37, 0x93, 0x91, 0x74, 0x31, 0xb8, 0x8c, 0xd3, 0xcc, 0xe7, 0x69, 0x76, 0x81, 0x4c, 0xfd, 0x03, - 0xff, 0x85, 0x8c, 0x47, 0xd6, 0x7f, 0xfa, 0xec, 0xc7, 0xc9, 0x8f, 0xd9, 0xc5, 0x18, 0xbf, 0x25, 0xad, 0xbe, 0x33, - 0xf4, 0x9c, 0xbd, 0x66, 0x73, 0xf5, 0x63, 0x6b, 0xf4, 0x77, 0xbf, 0xf9, 0xcb, 0x69, 0xf3, 0x6f, 0x17, 0x68, 0xe5, - 0xfc, 0xd8, 0x1a, 0x8e, 0xd4, 0xd3, 0xe8, 0xef, 0x83, 0x1f, 0xf3, 0x8b, 0x3f, 0xca, 0xc2, 0x7d, 0x84, 0x5a, 0x53, - 0x3c, 0xe7, 0xa4, 0xd5, 0x6c, 0x0e, 0x5a, 0x53, 0x3c, 0xe5, 0xa4, 0x05, 0xff, 0x5e, 0x91, 0x77, 0x74, 0xfa, 0xfc, - 0x76, 0xee, 0x8c, 0x07, 0xab, 0xfd, 0xe5, 0x5f, 0x0a, 0xe8, 0x75, 0xf4, 0xf7, 0x1f, 0x7f, 0xcc, 0xed, 0x2f, 0x06, - 0xa4, 0x75, 0xd1, 0x40, 0x0e, 0x94, 0xfe, 0x91, 0x88, 0xbf, 0xce, 0xd0, 0x1b, 0xfd, 0x5d, 0x41, 0x61, 0x7f, 0xf1, - 0xe3, 0xb8, 0x3f, 0x20, 0x17, 0x2b, 0xc7, 0x5e, 0x7d, 0x81, 0x56, 0x08, 0xad, 0xf6, 0xd1, 0x18, 0xdb, 0x53, 0x1b, - 0xe1, 0x4b, 0x4e, 0x5a, 0x5f, 0xb4, 0xa6, 0xf8, 0x9a, 0x93, 0x96, 0xdd, 0x9a, 0xe2, 0x33, 0x4e, 0x5a, 0x7f, 0x77, - 0x86, 0x9e, 0x74, 0xb2, 0xad, 0x84, 0x7f, 0x63, 0x05, 0x01, 0x0e, 0x3f, 0xa3, 0xfe, 0x8a, 0x33, 0x1e, 0x53, 0xb4, - 0xdf, 0x62, 0xf8, 0x8d, 0x40, 0x93, 0xc3, 0xc1, 0x0b, 0x03, 0xc6, 0x9d, 0xb3, 0xbc, 0x84, 0xc5, 0x06, 0x9a, 0xd9, - 0xf7, 0x20, 0xb2, 0x03, 0x8e, 0x80, 0xdc, 0xe3, 0xf8, 0xda, 0x8f, 0x17, 0x34, 0xf7, 0x68, 0x81, 0x70, 0x4c, 0xde, - 0x70, 0xa7, 0x83, 0xf0, 0x4b, 0x0e, 0x3f, 0xba, 0x08, 0x9f, 0xa9, 0x20, 0x26, 0xec, 0x64, 0x49, 0x54, 0x49, 0x2a, - 0x55, 0x16, 0x1b, 0xe1, 0xf9, 0x96, 0x97, 0x3c, 0x02, 0xf7, 0x02, 0xc2, 0xfb, 0xb5, 0x90, 0x27, 0xbe, 0x21, 0x9a, - 0x24, 0xde, 0x67, 0x94, 0x7e, 0xef, 0xc7, 0x1f, 0x68, 0xe6, 0xdc, 0xe2, 0x4e, 0xf7, 0x09, 0x16, 0x5e, 0xe8, 0xbd, - 0x0e, 0xea, 0x95, 0xf1, 0xaa, 0x0f, 0x5c, 0xc6, 0x09, 0x40, 0xca, 0xd6, 0x9d, 0x31, 0xb0, 0xe2, 0x7b, 0xc9, 0x86, - 0xc7, 0x2a, 0xf3, 0x6f, 0x6c, 0x54, 0x8f, 0x8d, 0xb2, 0xe4, 0xda, 0x8f, 0x59, 0x68, 0x71, 0x3a, 0x9b, 0xc7, 0x3e, - 0xa7, 0x96, 0x9a, 0xaf, 0xe5, 0x43, 0x47, 0x76, 0xa9, 0x33, 0x2c, 0x0c, 0x8b, 0x73, 0xa1, 0x83, 0x4e, 0xb0, 0x57, - 0x1c, 0x88, 0x50, 0x29, 0xbd, 0xe3, 0x59, 0x15, 0x00, 0x5b, 0x8f, 0xf1, 0x35, 0x3b, 0xe0, 0x09, 0xbb, 0x10, 0xf2, - 0x39, 0xc7, 0x19, 0x01, 0x29, 0xda, 0x1d, 0xda, 0xfd, 0xfc, 0x7a, 0x3a, 0xb0, 0x21, 0x3e, 0x93, 0x92, 0xb7, 0xc2, - 0x31, 0x04, 0x15, 0x22, 0xd2, 0xee, 0x45, 0x7d, 0xda, 0x8b, 0x1a, 0x0d, 0xad, 0x44, 0xfb, 0x24, 0x19, 0x45, 0xb2, - 0x79, 0x80, 0x43, 0xbc, 0x20, 0xcd, 0x0e, 0x9e, 0x92, 0xb6, 0x68, 0xd2, 0x9b, 0xf6, 0x7d, 0x35, 0xcc, 0xc1, 0x81, - 0x93, 0xba, 0xb1, 0x9f, 0xf3, 0xaf, 0xc0, 0xda, 0x27, 0x53, 0x1c, 0x92, 0xd4, 0xa5, 0xb7, 0x34, 0x70, 0x7c, 0x84, - 0x43, 0xc5, 0x69, 0x50, 0x0f, 0x4d, 0x89, 0x51, 0x0d, 0xac, 0x08, 0xf2, 0x76, 0x18, 0x8e, 0x3a, 0x17, 0x84, 0x10, - 0x7b, 0xaf, 0xd9, 0xb4, 0x87, 0x29, 0x99, 0x73, 0x0f, 0x4a, 0x0c, 0x5d, 0x99, 0x4c, 0xa1, 0xa8, 0x6b, 0x14, 0x39, - 0x67, 0xdc, 0xe5, 0x34, 0xe7, 0x0e, 0x14, 0x83, 0xfd, 0x9f, 0x6b, 0xc2, 0xb6, 0xfb, 0x2d, 0xbb, 0x01, 0xa5, 0x82, - 0x38, 0x11, 0x4e, 0xc9, 0x15, 0xf2, 0xc2, 0xd1, 0xe1, 0x85, 0x29, 0x00, 0x44, 0x21, 0x0c, 0x7e, 0x35, 0x0c, 0x47, - 0x6d, 0x31, 0xf8, 0xc0, 0x1e, 0x3a, 0x29, 0xc9, 0xa5, 0x86, 0x36, 0xcc, 0xbd, 0xb7, 0x62, 0xaa, 0xc8, 0x53, 0xc0, - 0xe9, 0x15, 0x20, 0xcd, 0xae, 0xe7, 0x2c, 0xcc, 0x49, 0x34, 0x61, 0x30, 0x85, 0x05, 0x1c, 0x10, 0xa8, 0x8f, 0x53, - 0x02, 0x23, 0x56, 0xcd, 0xae, 0x3c, 0xf5, 0xfc, 0x85, 0xfd, 0xc5, 0xf0, 0x9a, 0x7b, 0x97, 0x5c, 0x0e, 0x7f, 0xcd, - 0x57, 0x2b, 0xf8, 0xf7, 0x92, 0x0f, 0x53, 0x72, 0x25, 0x8a, 0xe6, 0xaa, 0x68, 0x0a, 0x45, 0x6f, 0x3d, 0x00, 0x15, - 0xe7, 0xa5, 0x96, 0x25, 0xd7, 0xe4, 0x92, 0x08, 0xd8, 0x0f, 0x0e, 0x92, 0x51, 0xd4, 0xe8, 0x5c, 0x80, 0x8b, 0x3f, - 0xe3, 0xf9, 0xf7, 0x8c, 0x47, 0x8e, 0xdd, 0x1a, 0xd8, 0x68, 0x68, 0x5b, 0xb0, 0xb4, 0xbd, 0xac, 0x41, 0x24, 0x86, - 0xfd, 0xc6, 0x0b, 0xee, 0x2d, 0x06, 0xa4, 0x3d, 0x74, 0x98, 0x64, 0xe1, 0x01, 0xc2, 0xbe, 0x62, 0x9c, 0x6d, 0xbc, - 0x40, 0x0d, 0xca, 0x1b, 0xfa, 0x79, 0x81, 0x1a, 0x93, 0xc6, 0x25, 0xf2, 0xfc, 0xc6, 0xa4, 0xe1, 0x2c, 0x08, 0x21, - 0xcd, 0x6e, 0xd9, 0x4c, 0x8b, 0xbf, 0x08, 0x79, 0x97, 0xda, 0xdb, 0x39, 0x12, 0xdb, 0x21, 0x6b, 0x38, 0xc9, 0x88, - 0x5e, 0xac, 0x56, 0x76, 0x7f, 0x38, 0xb0, 0x51, 0xc3, 0xd1, 0x84, 0xd6, 0xd2, 0x94, 0x86, 0x10, 0x66, 0x17, 0x85, - 0x8a, 0x26, 0xbd, 0xae, 0x45, 0x8e, 0x96, 0xd5, 0x66, 0x37, 0x78, 0x00, 0x2d, 0x4a, 0x43, 0x46, 0x2a, 0xac, 0x73, - 0x98, 0xa6, 0x26, 0xe6, 0x8c, 0xb4, 0x71, 0x4a, 0xb4, 0xf3, 0x3a, 0x22, 0xbc, 0x22, 0x78, 0x9f, 0x54, 0xd5, 0xf1, - 0x28, 0xc0, 0xe1, 0x05, 0x79, 0x26, 0x0d, 0x92, 0x9e, 0x76, 0x8d, 0xd3, 0x98, 0xbc, 0x5e, 0x8b, 0xe0, 0x06, 0x10, - 0x5e, 0xb9, 0x71, 0x83, 0x45, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcd, - 0x62, 0x50, 0xd2, 0xba, 0x7a, 0x67, 0x2c, 0x36, 0x5e, 0x4f, 0xc9, 0x42, 0xea, 0x4f, 0x22, 0x60, 0xdb, 0x9b, 0x2a, - 0xc3, 0xd8, 0x41, 0x78, 0xa1, 0x22, 0xb9, 0x8e, 0xeb, 0xba, 0x53, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, - 0x8f, 0x9c, 0x9c, 0xdc, 0xb8, 0x09, 0xbd, 0x15, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0xf5, 0xa3, 0x9e, 0x60, - 0x37, 0xb9, 0x9b, 0xa4, 0x21, 0x05, 0xf4, 0x40, 0xec, 0x5e, 0x15, 0x45, 0x7e, 0x6e, 0x86, 0xa8, 0x2a, 0xf8, 0x46, - 0xa6, 0xf7, 0x7a, 0x0a, 0x2e, 0x5f, 0xa1, 0x6c, 0x95, 0x95, 0xa5, 0x1f, 0x1c, 0x21, 0x36, 0x71, 0xa6, 0x2e, 0x84, - 0xf6, 0x04, 0x09, 0x51, 0xb0, 0xe5, 0xa6, 0x26, 0x51, 0x4d, 0xca, 0x3e, 0x2f, 0x49, 0x38, 0x4a, 0x1b, 0x0d, 0xe1, - 0x86, 0x5e, 0x48, 0x92, 0x98, 0x22, 0x7c, 0x59, 0xee, 0x2d, 0x5d, 0xef, 0x3b, 0x52, 0x1f, 0xc9, 0xb9, 0xac, 0xbb, - 0x73, 0x1b, 0x90, 0x26, 0x01, 0x9e, 0x42, 0xee, 0x4c, 0x10, 0x3e, 0x25, 0x2d, 0x67, 0xe4, 0x0e, 0xff, 0x74, 0x81, - 0x86, 0x8e, 0xfb, 0x47, 0xd4, 0x92, 0x8c, 0xe3, 0x12, 0xf5, 0x7c, 0x39, 0xc4, 0x52, 0x84, 0x30, 0x3b, 0x58, 0x78, - 0x12, 0xbd, 0x0c, 0x27, 0xfe, 0x8c, 0x7a, 0xa7, 0xb0, 0xc7, 0x35, 0xdd, 0x7c, 0x87, 0x81, 0x8e, 0xbc, 0x53, 0xc5, - 0x49, 0x5c, 0x7b, 0xf8, 0x15, 0x2f, 0x9f, 0x86, 0xf6, 0xf0, 0x97, 0xea, 0xe9, 0x4f, 0xf6, 0xf0, 0x4b, 0xee, 0xfd, - 0x52, 0x28, 0x67, 0x77, 0x6d, 0x88, 0x47, 0x7a, 0x88, 0x42, 0x2e, 0x8c, 0x81, 0xb9, 0x05, 0xda, 0xf4, 0x73, 0x4c, - 0x51, 0xc1, 0x26, 0x25, 0x2b, 0xca, 0x5d, 0xee, 0x4f, 0x01, 0xa5, 0xc6, 0x0a, 0xe4, 0x66, 0x64, 0xbf, 0x9a, 0x30, - 0x10, 0x8a, 0xa6, 0x56, 0x40, 0xe5, 0x74, 0xd0, 0x46, 0xcb, 0x5a, 0x5d, 0xa1, 0x31, 0xd5, 0x23, 0xe9, 0x25, 0x97, - 0xbe, 0x24, 0xed, 0xde, 0x65, 0x7f, 0xda, 0xbb, 0x6c, 0x34, 0x50, 0xae, 0x09, 0x6b, 0x31, 0xba, 0xbc, 0xc0, 0xdf, - 0x82, 0x4f, 0xcf, 0xa4, 0x24, 0x5c, 0x9b, 0x5e, 0x57, 0x4d, 0xaf, 0xd1, 0xc8, 0x0a, 0xd4, 0x33, 0x9a, 0x4e, 0x65, - 0xd3, 0xa2, 0x90, 0x38, 0x59, 0x27, 0xb4, 0x13, 0x24, 0x4a, 0x20, 0x1d, 0x8a, 0x10, 0xf2, 0x9c, 0xa3, 0xad, 0xbd, - 0x42, 0x9f, 0xd0, 0x5c, 0xec, 0x58, 0x60, 0x9e, 0x52, 0x46, 0x38, 0x80, 0x05, 0x68, 0x5a, 0x3a, 0x82, 0x27, 0x78, - 0xd1, 0xe8, 0x08, 0x22, 0x6f, 0x76, 0x7a, 0xf5, 0xbe, 0x1e, 0x57, 0x7d, 0xe1, 0x45, 0x83, 0x4c, 0x4a, 0x2c, 0x15, - 0x59, 0xa3, 0x51, 0xd4, 0xa3, 0x9d, 0x7a, 0xdf, 0xd6, 0xe2, 0x0f, 0xb7, 0xeb, 0x69, 0x19, 0x5a, 0xbe, 0x56, 0x12, - 0x95, 0xb9, 0x2c, 0x49, 0x68, 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, - 0x12, 0xe0, 0x3b, 0xc2, 0xec, 0xc2, 0x19, 0x4e, 0x71, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x4c, 0x27, 0xb4, 0x70, 0xc1, - 0x81, 0x7c, 0xc2, 0x0c, 0x89, 0x94, 0x13, 0xea, 0x5e, 0xee, 0x9f, 0xa5, 0xf7, 0x9a, 0x64, 0x23, 0x76, 0xe1, 0x89, - 0x6a, 0xb1, 0xe2, 0x5b, 0x01, 0x79, 0xef, 0x70, 0x54, 0x06, 0x47, 0x5c, 0xc1, 0xfe, 0x9e, 0xb1, 0x8c, 0x0a, 0x0d, - 0x7c, 0x5f, 0x9b, 0x7d, 0x7e, 0x5d, 0x7d, 0xf4, 0x4d, 0xe7, 0x0d, 0x20, 0x32, 0x00, 0xdf, 0x4e, 0x46, 0x36, 0xaa, - 0x5d, 0xee, 0x9f, 0xbe, 0xd9, 0x66, 0x02, 0xaf, 0x56, 0xca, 0xf8, 0xf5, 0x41, 0xb3, 0xc1, 0x41, 0x05, 0xa9, 0xaf, - 0x7e, 0x78, 0x8e, 0x2f, 0x14, 0xa4, 0xc0, 0x49, 0x80, 0x8a, 0x2e, 0xf7, 0x4f, 0xdf, 0x3b, 0x89, 0x70, 0x2d, 0x21, - 0x6c, 0x4e, 0xdb, 0x49, 0x89, 0x13, 0x11, 0x8a, 0xe4, 0xdc, 0x4b, 0xc6, 0x95, 0x1a, 0xe2, 0xdb, 0x8b, 0xc4, 0x4b, - 0xb0, 0x1f, 0x46, 0xec, 0x82, 0xf8, 0x0a, 0x03, 0xc4, 0x47, 0xd8, 0xaf, 0x99, 0x65, 0x04, 0x16, 0x40, 0x8c, 0x75, - 0x0e, 0x2b, 0xe1, 0x4a, 0xc5, 0x0f, 0x61, 0x5f, 0x8c, 0xca, 0x0b, 0x29, 0x3a, 0x7e, 0xda, 0xc8, 0x4b, 0xab, 0xac, - 0xd1, 0xef, 0xc0, 0x72, 0xd2, 0x0f, 0xaf, 0x55, 0xd7, 0x65, 0xc1, 0x33, 0x9d, 0x40, 0x76, 0xb9, 0x7f, 0xfa, 0x4a, - 0xe5, 0x90, 0xcd, 0x7d, 0xcd, 0xed, 0x37, 0x2c, 0xcc, 0xd3, 0x57, 0x6e, 0xf5, 0x56, 0x54, 0xbe, 0xdc, 0x3f, 0xfd, - 0x76, 0x5b, 0x35, 0x28, 0x2f, 0x16, 0x95, 0x89, 0x2f, 0xe0, 0x5b, 0xd2, 0xd8, 0x5b, 0x2a, 0xd1, 0xe0, 0xb1, 0x02, - 0x0b, 0x71, 0xe4, 0xe5, 0x45, 0xe9, 0x19, 0x79, 0x86, 0x33, 0x22, 0xa2, 0x40, 0xf5, 0x55, 0x53, 0x4a, 0x1e, 0x4b, - 0x93, 0xf3, 0x20, 0x9d, 0xd3, 0x1d, 0xa1, 0xa1, 0x5b, 0xe4, 0xb2, 0x19, 0x24, 0xcf, 0x08, 0xd0, 0x19, 0xde, 0x6b, - 0xa3, 0x5e, 0x5d, 0x78, 0x65, 0x82, 0x48, 0xd3, 0x9a, 0x64, 0xc1, 0x11, 0x69, 0x63, 0x9f, 0xb4, 0x71, 0x40, 0xf2, - 0x51, 0x5b, 0x8a, 0x87, 0x5e, 0x50, 0xf6, 0x2b, 0x85, 0x0c, 0xe4, 0x85, 0x05, 0x72, 0xb7, 0x4a, 0xf1, 0x1b, 0xf6, - 0x02, 0xe1, 0x7a, 0x14, 0x12, 0x3d, 0x14, 0x64, 0xf1, 0xd4, 0x49, 0x71, 0x2a, 0x3a, 0x3e, 0x67, 0x57, 0x31, 0xa4, - 0x96, 0xc0, 0xac, 0x30, 0x47, 0x5e, 0x59, 0xb5, 0xa3, 0xaa, 0x06, 0xae, 0x58, 0xa7, 0x14, 0x07, 0x2e, 0x30, 0x6e, - 0x1c, 0xa8, 0x4c, 0x9c, 0x7c, 0xb3, 0xc9, 0xa3, 0x83, 0x03, 0x47, 0x36, 0xfa, 0x8e, 0x3b, 0xa9, 0x7e, 0x5f, 0x05, - 0xee, 0xbe, 0x93, 0xbc, 0x22, 0x44, 0x02, 0xfe, 0x46, 0xc3, 0xbf, 0x28, 0x20, 0x0a, 0xed, 0x04, 0x75, 0x0c, 0x6a, - 0xe0, 0x85, 0xa6, 0x57, 0x9f, 0x7e, 0xa3, 0x51, 0x06, 0x69, 0xeb, 0xd8, 0xba, 0xc5, 0x59, 0x71, 0xed, 0x94, 0xc9, - 0x3f, 0xed, 0x8d, 0x8c, 0x29, 0x0d, 0x02, 0x62, 0x26, 0xcd, 0x32, 0x3d, 0x19, 0x63, 0x4b, 0x30, 0xa8, 0xf7, 0x95, - 0x4a, 0x5b, 0xc0, 0x22, 0xbf, 0x4a, 0x55, 0xd2, 0xec, 0xac, 0x8b, 0x3c, 0x5d, 0x09, 0x82, 0x52, 0x50, 0xa9, 0x51, - 0x28, 0xf2, 0x7e, 0xba, 0x99, 0x75, 0x89, 0x73, 0xa4, 0x7c, 0x5c, 0x02, 0x0a, 0x81, 0xac, 0x6e, 0x89, 0x94, 0x17, - 0x64, 0xbe, 0x9b, 0xe4, 0x4f, 0x0d, 0x92, 0x7f, 0x4a, 0xa8, 0x41, 0xfe, 0xd2, 0xc3, 0xe1, 0xa6, 0xca, 0xb5, 0x90, - 0xeb, 0x57, 0x67, 0x73, 0x02, 0x3e, 0xb4, 0x3a, 0x46, 0x6b, 0x51, 0xc5, 0x1d, 0x0c, 0xc5, 0xdc, 0x21, 0xc2, 0x0b, - 0x89, 0x75, 0x08, 0xd8, 0xa9, 0x62, 0x6a, 0x30, 0xf4, 0x36, 0x97, 0x9e, 0xc9, 0x01, 0x4f, 0xbf, 0xbd, 0x3f, 0x1c, - 0x7a, 0x36, 0xdf, 0xdc, 0xb9, 0x46, 0xf6, 0x27, 0xcc, 0xda, 0xd8, 0xb8, 0xf5, 0x5c, 0x50, 0x18, 0xbf, 0x0c, 0x63, - 0xd7, 0x99, 0xcf, 0xda, 0x26, 0xd4, 0xf2, 0x0f, 0xa0, 0xed, 0x74, 0x44, 0x0d, 0x6a, 0x74, 0x0b, 0xfc, 0x48, 0xe6, - 0xa0, 0xfa, 0xd9, 0x0e, 0xf6, 0x71, 0x2a, 0x2a, 0xd0, 0x24, 0xdc, 0xfe, 0xfa, 0x69, 0xa1, 0xc8, 0x44, 0x82, 0x86, - 0x96, 0xc0, 0xff, 0x24, 0xc9, 0x03, 0xdd, 0x08, 0xb9, 0x00, 0x08, 0x9a, 0x0b, 0x3c, 0x55, 0x08, 0xb3, 0xed, 0xca, - 0xf9, 0xfe, 0x62, 0x8f, 0x90, 0x79, 0xe5, 0x7c, 0x7c, 0x57, 0xe5, 0x5e, 0x01, 0x59, 0x20, 0x0f, 0x8c, 0xc7, 0xb2, - 0x40, 0x46, 0x2f, 0xcf, 0x74, 0x75, 0x61, 0x40, 0xba, 0x95, 0xbe, 0x6d, 0x44, 0x36, 0x85, 0x57, 0x4e, 0xbe, 0xd7, - 0x68, 0x58, 0x7b, 0xbb, 0x0f, 0x6f, 0x5f, 0x71, 0x01, 0x23, 0x3c, 0xbf, 0x17, 0xb5, 0x75, 0xbf, 0xc5, 0x87, 0xf5, - 0x04, 0x96, 0xb5, 0x45, 0x71, 0x59, 0x92, 0xd3, 0x8c, 0x3f, 0xa5, 0x93, 0x34, 0x83, 0x90, 0x45, 0x89, 0x13, 0x54, - 0xec, 0x1b, 0x6e, 0x3b, 0x31, 0x3f, 0x23, 0x4e, 0xb0, 0x36, 0x41, 0xf1, 0xeb, 0x83, 0x88, 0x59, 0x5f, 0xae, 0xb7, - 0x9a, 0x1f, 0x1c, 0xbc, 0xaf, 0xd0, 0xa4, 0xa0, 0x14, 0x50, 0x18, 0x4c, 0x4b, 0xaa, 0x34, 0x2a, 0x90, 0xbb, 0xef, - 0x94, 0x2e, 0x00, 0xcd, 0x30, 0x4c, 0xde, 0xf3, 0x82, 0xf0, 0x62, 0xba, 0xce, 0xe2, 0x95, 0x6b, 0x82, 0x99, 0x66, - 0x0b, 0x70, 0x78, 0x30, 0xb4, 0xa5, 0xaf, 0x28, 0xaf, 0xd2, 0x61, 0x4b, 0x18, 0xce, 0x00, 0x59, 0x8e, 0x30, 0x42, - 0x0c, 0x0a, 0xdc, 0x6a, 0x94, 0x7c, 0x00, 0xbd, 0x32, 0xc2, 0xb9, 0x1b, 0x41, 0x02, 0x6c, 0x6d, 0xcb, 0x22, 0x84, - 0x65, 0x5e, 0x8e, 0x91, 0x49, 0x70, 0xfa, 0x62, 0x9b, 0x47, 0x59, 0x13, 0x35, 0x15, 0x52, 0x07, 0x6a, 0x64, 0xa8, - 0x6c, 0xe0, 0x5e, 0x3b, 0x4c, 0x29, 0x6e, 0x3a, 0x6c, 0x06, 0x0c, 0xf8, 0x27, 0xee, 0xc8, 0x58, 0x14, 0xc8, 0x8c, - 0xd4, 0x5d, 0x38, 0xb5, 0xa1, 0x7b, 0xa9, 0x68, 0x86, 0x15, 0xe2, 0x22, 0x13, 0x4d, 0xa9, 0x08, 0xeb, 0x9d, 0x55, - 0xbc, 0x74, 0x5f, 0xe6, 0x50, 0x73, 0xcd, 0x05, 0xab, 0x3c, 0x12, 0x63, 0xfa, 0xfb, 0x32, 0x2d, 0xba, 0xac, 0x04, - 0x6a, 0x18, 0xbd, 0xb1, 0x5e, 0x8b, 0x35, 0xa0, 0x05, 0xd0, 0xd7, 0xf2, 0x9c, 0x1b, 0x2b, 0xaa, 0x7d, 0xd8, 0x62, - 0x4c, 0x43, 0xea, 0xbf, 0x83, 0x4c, 0x97, 0xf5, 0x3d, 0xff, 0x42, 0xc8, 0x42, 0x86, 0xf3, 0x1a, 0x63, 0xcf, 0x04, - 0x63, 0x47, 0xa0, 0xa7, 0xe9, 0xd4, 0xef, 0xa1, 0x4a, 0x78, 0x61, 0x4a, 0xca, 0x29, 0x12, 0xfb, 0xb6, 0x0c, 0x96, - 0x1b, 0xbf, 0xd7, 0x56, 0xc3, 0x63, 0x04, 0x92, 0x80, 0xb0, 0xe2, 0xec, 0x19, 0xc2, 0x79, 0xa3, 0xd1, 0xcb, 0xfb, - 0xb4, 0x72, 0x91, 0x54, 0x30, 0x32, 0x88, 0xe7, 0x02, 0xc1, 0xd7, 0x64, 0x28, 0x44, 0xfc, 0x75, 0x6e, 0x76, 0x0e, - 0xae, 0xf6, 0xd3, 0x77, 0x8e, 0xc9, 0xd5, 0xcc, 0xba, 0x65, 0xcc, 0x14, 0xe6, 0xe3, 0x54, 0xf1, 0x96, 0xb7, 0xf7, - 0xe7, 0x77, 0x00, 0xdc, 0x7b, 0x1d, 0x0c, 0xb9, 0x68, 0xa8, 0xc7, 0x25, 0x4b, 0x28, 0x77, 0x5f, 0x0f, 0x55, 0x69, - 0x89, 0xe6, 0x60, 0x3d, 0x5e, 0x99, 0xb2, 0x9c, 0xe4, 0x45, 0x91, 0xd3, 0x2a, 0xba, 0xbf, 0x96, 0x7f, 0x29, 0x84, - 0xcb, 0xa6, 0xb3, 0xfd, 0x6c, 0x4e, 0x38, 0x36, 0x08, 0xf5, 0xed, 0xae, 0xd0, 0x47, 0x05, 0x26, 0xec, 0x6b, 0x25, - 0x14, 0x7f, 0xd9, 0x26, 0x14, 0x71, 0xa6, 0xb6, 0xbc, 0x10, 0x88, 0x9d, 0x07, 0x08, 0x44, 0xe5, 0x64, 0xd7, 0x32, - 0x11, 0xd4, 0x91, 0x9a, 0x4c, 0xac, 0x2f, 0x29, 0xc9, 0x30, 0x53, 0xab, 0x31, 0xe8, 0xae, 0x56, 0x6c, 0xd4, 0x06, - 0x27, 0x92, 0x6d, 0xc3, 0xcf, 0x8e, 0xfc, 0x69, 0x70, 0x62, 0xe9, 0x04, 0x76, 0x58, 0x69, 0xb2, 0x20, 0x17, 0x52, - 0x9c, 0x1d, 0x91, 0x93, 0x25, 0x68, 0x5a, 0x51, 0x90, 0x22, 0x70, 0xc2, 0xca, 0x28, 0x13, 0x40, 0x2c, 0x64, 0x85, - 0x32, 0x20, 0x9d, 0xad, 0xc9, 0x7f, 0xda, 0xbc, 0xfc, 0xb8, 0x26, 0x5a, 0x93, 0x2b, 0x52, 0x7d, 0xa8, 0xa5, 0x1b, - 0x28, 0x08, 0x94, 0x7e, 0xb8, 0x27, 0x4c, 0xd0, 0x4a, 0x94, 0x23, 0x53, 0x0e, 0xe1, 0x36, 0xb8, 0xd0, 0xf6, 0xde, - 0xcb, 0x00, 0xef, 0x16, 0x69, 0x82, 0x53, 0x83, 0xae, 0x5f, 0x10, 0x5e, 0x63, 0x25, 0x11, 0x51, 0x96, 0x12, 0x0e, - 0x04, 0x99, 0x72, 0x92, 0x8d, 0xda, 0x17, 0xa0, 0x80, 0xf6, 0xfc, 0x7e, 0x56, 0x99, 0xc0, 0x7e, 0xa3, 0x81, 0x02, - 0x3d, 0x6a, 0x34, 0x62, 0x0d, 0xff, 0x02, 0x53, 0xec, 0x4b, 0xc3, 0xe4, 0xec, 0xe0, 0xc0, 0x09, 0xaa, 0x71, 0x47, - 0xfe, 0x05, 0xc2, 0xe9, 0x6a, 0xe5, 0x08, 0xb0, 0x02, 0xb4, 0x5a, 0x05, 0x26, 0x58, 0xe2, 0x35, 0x34, 0x9b, 0x0f, - 0x39, 0x99, 0x0b, 0x01, 0x38, 0x07, 0x08, 0x1b, 0xc4, 0x09, 0x94, 0x73, 0x2f, 0x00, 0x67, 0x54, 0x23, 0x1b, 0xf9, - 0x8d, 0xce, 0x85, 0xc1, 0xb8, 0x46, 0xfe, 0x05, 0x09, 0x8a, 0xf4, 0xe0, 0x60, 0x2f, 0x57, 0x22, 0xf2, 0x27, 0x10, - 0x65, 0x3f, 0x09, 0xc9, 0x22, 0x3b, 0x34, 0x57, 0x63, 0xdd, 0x19, 0x50, 0x52, 0x94, 0x5a, 0x56, 0x5d, 0xaf, 0x96, - 0x04, 0x51, 0x56, 0xc2, 0x2a, 0x16, 0x3c, 0x04, 0xcb, 0xbe, 0x24, 0xf3, 0xaf, 0x78, 0x99, 0x64, 0xfd, 0xcb, 0xd6, - 0xd4, 0x6a, 0xd7, 0x75, 0xfd, 0x6c, 0x2a, 0x22, 0x19, 0x3a, 0x0a, 0x2b, 0x88, 0xff, 0x50, 0x81, 0x69, 0x0c, 0x3c, - 0x2a, 0xc7, 0xba, 0x20, 0x12, 0x7c, 0xad, 0xda, 0xe8, 0xd3, 0x24, 0x3f, 0x6f, 0xf5, 0x32, 0xa8, 0x0d, 0xf7, 0x6b, - 0x21, 0x39, 0x52, 0x90, 0x48, 0xf2, 0x58, 0xc3, 0xd9, 0x0e, 0x5c, 0xfc, 0xcc, 0xd7, 0x70, 0xb6, 0x1b, 0xb7, 0x1a, - 0x53, 0x5f, 0xee, 0x82, 0xcf, 0xe0, 0x0d, 0x12, 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x78, 0x5d, 0xf7, 0x92, 0xac, 0x14, - 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0xcd, 0x91, 0xe1, 0x12, 0xa8, 0x67, - 0xae, 0x00, 0x39, 0x29, 0x5f, 0xfb, 0xfc, 0xe0, 0x00, 0x6c, 0x03, 0x50, 0xe2, 0xdc, 0xc0, 0x9f, 0xf3, 0x45, 0x06, - 0xaa, 0x54, 0xae, 0x7f, 0x43, 0x31, 0x9c, 0x03, 0x11, 0x65, 0xf0, 0x03, 0x0a, 0xe6, 0x7e, 0x9e, 0xb3, 0x6b, 0x59, - 0xa6, 0x7e, 0xe3, 0x94, 0x68, 0x52, 0xce, 0xa5, 0x4e, 0x98, 0xa1, 0x5e, 0xa6, 0xe8, 0xb4, 0x8e, 0xb6, 0xe7, 0xd7, - 0x34, 0xe1, 0x2f, 0x59, 0xce, 0x69, 0x02, 0xd3, 0xaf, 0x28, 0x0e, 0x66, 0x94, 0x23, 0xd8, 0xb0, 0xb5, 0x56, 0x7e, - 0x18, 0xde, 0xdb, 0x84, 0xd7, 0x75, 0xa0, 0xc8, 0x4f, 0xc2, 0x58, 0x0e, 0x62, 0xa6, 0x33, 0xea, 0x14, 0xce, 0xb2, - 0xa6, 0x99, 0x4e, 0x53, 0x29, 0x1b, 0x82, 0xbb, 0x3b, 0x8c, 0x68, 0x49, 0xa0, 0xa5, 0xe7, 0xbd, 0x5a, 0x0b, 0x04, - 0xbc, 0x77, 0x2c, 0x82, 0x39, 0x13, 0xcc, 0x0d, 0x8e, 0xea, 0xd6, 0xe1, 0xd4, 0x74, 0xf3, 0xdd, 0xd6, 0x43, 0x6d, - 0xdb, 0x84, 0x83, 0xa0, 0x93, 0x47, 0xbb, 0x2d, 0xab, 0x57, 0x5a, 0x72, 0x68, 0x69, 0xc1, 0x1e, 0xca, 0x98, 0xd1, - 0x52, 0x93, 0x17, 0xd2, 0x5b, 0x71, 0xc6, 0xc9, 0x4f, 0x70, 0x6a, 0xe8, 0x05, 0x9f, 0xc5, 0x6b, 0x87, 0x63, 0x7a, - 0xb3, 0x52, 0xfb, 0x9f, 0x71, 0xe7, 0x35, 0x7e, 0x0a, 0x61, 0xdd, 0xaf, 0xab, 0xea, 0x9b, 0xe1, 0xdc, 0xaf, 0x2b, - 0x04, 0x7d, 0xed, 0x6d, 0xd4, 0x33, 0xc2, 0xb8, 0x5d, 0xf7, 0xc4, 0x6d, 0xdb, 0x5a, 0x5b, 0xfa, 0x5e, 0x06, 0x91, - 0x64, 0xa2, 0xa5, 0xd8, 0x0f, 0xb8, 0x4a, 0x53, 0x83, 0x74, 0xb9, 0xba, 0x85, 0x44, 0x55, 0x82, 0xa1, 0xd4, 0xe1, - 0x77, 0x2d, 0x8f, 0x92, 0x31, 0x99, 0xb4, 0x33, 0xde, 0xfa, 0x19, 0xdf, 0x87, 0x5d, 0x96, 0x6e, 0x9c, 0xc4, 0x8b, - 0x08, 0x78, 0xd0, 0x1e, 0x36, 0x84, 0x61, 0x6c, 0xe7, 0xf2, 0x24, 0x90, 0xd9, 0x3f, 0x49, 0xb5, 0xee, 0x56, 0xb7, - 0x32, 0xbe, 0x05, 0xfb, 0x1f, 0xe1, 0x48, 0x1f, 0x8f, 0xa3, 0x8a, 0x03, 0x53, 0x6f, 0x59, 0x94, 0x4e, 0x81, 0x54, - 0x2a, 0x6f, 0x09, 0xc2, 0x69, 0x21, 0xc2, 0xdb, 0xdf, 0xe0, 0x1f, 0x14, 0x4b, 0xbc, 0x2e, 0x39, 0xce, 0xf3, 0x87, - 0x72, 0x44, 0x09, 0x7e, 0x19, 0xbd, 0x07, 0x3a, 0x16, 0x14, 0x5a, 0x68, 0x2a, 0x7a, 0x96, 0xaa, 0x89, 0xec, 0xcc, - 0x4a, 0xc5, 0xb4, 0xcc, 0xa8, 0x11, 0xc3, 0x6c, 0x49, 0xe3, 0xd4, 0x56, 0x36, 0x2f, 0x77, 0x55, 0x6d, 0x5c, 0xb4, - 0x03, 0x8b, 0x55, 0x60, 0x71, 0xb5, 0x72, 0xea, 0xa8, 0x26, 0xcc, 0x88, 0x63, 0x20, 0xcc, 0x8c, 0x84, 0x8a, 0x9a, - 0x66, 0x2d, 0xdb, 0x38, 0x68, 0x3d, 0x9f, 0x48, 0xeb, 0xe6, 0x35, 0x38, 0x4c, 0x17, 0x82, 0x6c, 0x6e, 0xfa, 0x14, - 0xb0, 0x9c, 0x5d, 0x39, 0x90, 0x81, 0xa1, 0xef, 0xcb, 0x4c, 0xd9, 0x2a, 0xa5, 0x75, 0x0b, 0x7e, 0xd1, 0x3d, 0xb9, - 0xb2, 0x0a, 0x75, 0x9b, 0xef, 0x8d, 0x5c, 0xa3, 0x67, 0xe9, 0xae, 0x5c, 0xa3, 0x9a, 0xb6, 0xbb, 0xd7, 0x46, 0xf7, - 0x67, 0xa5, 0xca, 0xb1, 0xb6, 0x57, 0xf9, 0x15, 0xc3, 0x75, 0x80, 0x36, 0x25, 0x9a, 0x35, 0x57, 0x39, 0x2b, 0x8a, - 0xeb, 0xf2, 0x2c, 0x81, 0x48, 0xdd, 0xb9, 0x96, 0xf4, 0xaf, 0xac, 0x46, 0x71, 0x20, 0xd7, 0xf9, 0x86, 0x4c, 0xe3, - 0xf4, 0xca, 0x8f, 0xdf, 0xc3, 0x78, 0xd5, 0xcb, 0x17, 0x77, 0x61, 0xe6, 0x73, 0xaa, 0xb8, 0x4b, 0x05, 0xc3, 0x37, - 0x06, 0x0c, 0xdf, 0x48, 0x3e, 0x5d, 0xb5, 0xc7, 0xcb, 0x97, 0x65, 0x07, 0xde, 0x75, 0xa1, 0x59, 0xc6, 0x84, 0x6f, - 0x1f, 0x63, 0x9d, 0x85, 0x4d, 0x4a, 0x16, 0x36, 0xe1, 0xce, 0x7a, 0x57, 0x8e, 0xf3, 0xc3, 0xf6, 0x5e, 0x36, 0x39, - 0xdb, 0x0f, 0xd5, 0xc6, 0xff, 0xc1, 0xbb, 0xb7, 0x8d, 0xc1, 0xe5, 0x0e, 0xdd, 0x43, 0x91, 0xac, 0x22, 0x41, 0x7e, - 0x01, 0x49, 0x07, 0x9c, 0x0c, 0x8c, 0x23, 0x07, 0x95, 0x9c, 0xd2, 0x79, 0x40, 0x4e, 0xb0, 0xc8, 0x79, 0x3a, 0x53, - 0x7d, 0xe6, 0xea, 0x9c, 0x91, 0x78, 0x09, 0xae, 0x68, 0x11, 0x6b, 0xf7, 0xea, 0x27, 0xb9, 0x96, 0x1f, 0x58, 0x12, - 0x7a, 0x39, 0x56, 0x52, 0x24, 0xf7, 0xb2, 0x82, 0xe8, 0x5c, 0xe3, 0xcd, 0x77, 0x78, 0xc2, 0x12, 0x96, 0x47, 0x34, - 0x73, 0x52, 0xb4, 0xdc, 0x35, 0x58, 0x0a, 0x01, 0x19, 0x39, 0x18, 0xfe, 0x5b, 0x75, 0xe4, 0xcf, 0x85, 0xde, 0xc0, - 0x0f, 0x34, 0xa3, 0x3c, 0x4a, 0x43, 0x48, 0x4b, 0x71, 0xc3, 0xf2, 0x48, 0xd3, 0xc1, 0xc1, 0x9e, 0x63, 0x0b, 0xb7, - 0x04, 0x1c, 0xfe, 0x36, 0xdf, 0xa0, 0xe1, 0x12, 0x4e, 0xe7, 0x54, 0x43, 0x53, 0xb4, 0xa4, 0xeb, 0x07, 0x59, 0xb8, - 0xfb, 0x81, 0xde, 0xe1, 0x04, 0x15, 0x85, 0x27, 0xa1, 0xb6, 0x27, 0x8c, 0xc6, 0xa1, 0x8d, 0x3f, 0xd0, 0x3b, 0xaf, - 0x3c, 0x2f, 0x2e, 0x8e, 0x37, 0x8b, 0x05, 0xb4, 0xd3, 0x9b, 0xc4, 0xc6, 0xd5, 0x20, 0xde, 0xb2, 0xc0, 0x69, 0xc6, - 0xa6, 0x40, 0x9c, 0x7f, 0xa1, 0x77, 0x9e, 0xec, 0x8f, 0x19, 0xa7, 0xf5, 0xd0, 0x52, 0xa3, 0xde, 0x35, 0x8a, 0xcd, - 0x65, 0x50, 0x06, 0xc5, 0x48, 0xb4, 0xbd, 0x20, 0xb5, 0x7a, 0x95, 0x79, 0x88, 0x50, 0xf1, 0xd0, 0xa9, 0xe0, 0xaf, - 0x4d, 0xd1, 0xc6, 0x6b, 0x99, 0xaf, 0x6b, 0x8d, 0x28, 0x34, 0xa8, 0x32, 0x3d, 0x66, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, - 0x82, 0x60, 0x38, 0xc2, 0xbe, 0xe6, 0xaa, 0x53, 0xef, 0x6f, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xaa, 0xda, 0x59, - 0x33, 0x07, 0xf0, 0x0e, 0x09, 0x2d, 0xbe, 0x38, 0x90, 0x59, 0xe8, 0x6c, 0xd1, 0xbf, 0x70, 0xe2, 0x2c, 0xf5, 0x14, - 0xbc, 0xc4, 0xc4, 0x22, 0x2f, 0x80, 0x0a, 0x15, 0x7d, 0xc9, 0x04, 0x40, 0x38, 0xc3, 0xbe, 0x21, 0x35, 0x33, 0x21, - 0x35, 0x5d, 0x03, 0xe3, 0x3b, 0xa4, 0x24, 0x15, 0xc8, 0x10, 0x4a, 0xa4, 0x10, 0x7a, 0x6a, 0x71, 0x15, 0x09, 0x99, - 0x0b, 0x5a, 0x9e, 0x9f, 0x93, 0x6b, 0x9e, 0xd5, 0xc0, 0x72, 0x44, 0x3f, 0xa8, 0xf0, 0x60, 0x4a, 0x54, 0x56, 0x28, - 0xca, 0x63, 0xd9, 0x3a, 0xbd, 0xd5, 0x49, 0x5d, 0x3d, 0x2d, 0xa2, 0x51, 0xe2, 0x44, 0x68, 0x99, 0x38, 0x11, 0xce, - 0x20, 0x1d, 0x31, 0x2d, 0x4a, 0xf8, 0xa9, 0xb9, 0x1a, 0xb5, 0x64, 0xe5, 0xed, 0x67, 0xfc, 0x40, 0x99, 0xe7, 0x90, - 0xa2, 0x89, 0x13, 0xcd, 0x53, 0x12, 0x47, 0x1c, 0xb6, 0x33, 0x96, 0xed, 0x1b, 0x95, 0xa0, 0xa3, 0x00, 0xfb, 0x0b, - 0x77, 0x96, 0xc6, 0x2c, 0xcc, 0xd3, 0xdc, 0xea, 0xcc, 0x9f, 0x0a, 0xf6, 0x55, 0x39, 0xa4, 0x4e, 0x4e, 0xd6, 0x24, - 0xce, 0xfd, 0xa9, 0x96, 0x3f, 0x2f, 0x68, 0x76, 0x77, 0x4e, 0x21, 0xd5, 0x39, 0x85, 0xd3, 0xbe, 0xd5, 0x32, 0x54, - 0x69, 0xea, 0xc3, 0x4c, 0x28, 0x2b, 0x45, 0xfd, 0x14, 0xe0, 0xfa, 0x19, 0xc1, 0x42, 0x44, 0x1b, 0x0d, 0x47, 0x8c, - 0xdc, 0x2d, 0x74, 0xe7, 0xe9, 0x49, 0xda, 0x63, 0xe0, 0x5f, 0xab, 0x30, 0xad, 0x82, 0x05, 0x38, 0x35, 0x4f, 0xa4, - 0x8e, 0xf2, 0x8b, 0x75, 0xaf, 0x0c, 0x14, 0x41, 0xf8, 0x2e, 0xdb, 0x3d, 0xd5, 0x6d, 0x49, 0xb3, 0xbb, 0xa7, 0x5a, - 0x0b, 0xfa, 0x89, 0x84, 0x1f, 0xac, 0xc6, 0x29, 0x8f, 0x2f, 0xb3, 0xa2, 0x40, 0x05, 0x80, 0xf7, 0xe7, 0x9e, 0xe3, - 0xfc, 0x59, 0xa5, 0x0c, 0xba, 0x10, 0x8b, 0x3d, 0x8f, 0x53, 0xcd, 0xc4, 0xab, 0xf1, 0xff, 0xbc, 0x31, 0xfe, 0x9f, - 0x8d, 0x33, 0xa7, 0x60, 0x1a, 0x4d, 0x13, 0x1a, 0x6a, 0xd6, 0x89, 0x24, 0x01, 0x0a, 0xbd, 0x2d, 0xe1, 0xe4, 0xc3, - 0xd8, 0x03, 0x8d, 0x6b, 0x39, 0x49, 0x13, 0xde, 0x9c, 0xf8, 0x33, 0x16, 0xdf, 0x79, 0x0b, 0xd6, 0x9c, 0xa5, 0x49, - 0x9a, 0xcf, 0xfd, 0x80, 0xe2, 0xfc, 0x2e, 0xe7, 0x74, 0xd6, 0x5c, 0x30, 0xfc, 0x82, 0xc6, 0xd7, 0x94, 0xb3, 0xc0, - 0xc7, 0xf6, 0x69, 0xc6, 0xfc, 0xd8, 0x7a, 0xed, 0x67, 0x59, 0x7a, 0x63, 0xe3, 0x77, 0xe9, 0x55, 0xca, 0x53, 0xfc, - 0xe6, 0xf6, 0x6e, 0x4a, 0x13, 0xfc, 0xed, 0xd5, 0x22, 0xe1, 0x0b, 0x9c, 0xfb, 0x49, 0xde, 0xcc, 0x69, 0xc6, 0x26, - 0xbd, 0x20, 0x8d, 0xd3, 0xac, 0x09, 0x19, 0xdb, 0x33, 0xea, 0xc5, 0x6c, 0x1a, 0x71, 0x2b, 0xf4, 0xb3, 0x0f, 0xbd, - 0x66, 0x73, 0x9e, 0xb1, 0x99, 0x9f, 0xdd, 0x35, 0x45, 0x0d, 0xef, 0xf3, 0xf6, 0xa1, 0xff, 0x64, 0x72, 0xd4, 0xe3, - 0x99, 0x9f, 0xe4, 0x0c, 0x96, 0xc9, 0xf3, 0xe3, 0xd8, 0x3a, 0x3c, 0x6e, 0xcf, 0xf2, 0x3d, 0x19, 0xc8, 0xf3, 0x13, - 0x5e, 0x8c, 0xf1, 0x5b, 0x80, 0xdb, 0xbd, 0xe2, 0x09, 0xbe, 0x5a, 0x70, 0x9e, 0x26, 0xcb, 0x60, 0x91, 0xe5, 0x69, - 0xe6, 0xcd, 0x53, 0x96, 0x70, 0x9a, 0xf5, 0xae, 0xd2, 0x2c, 0xa4, 0x59, 0x33, 0xf3, 0x43, 0xb6, 0xc8, 0xbd, 0xa3, - 0xf9, 0x6d, 0x0f, 0x34, 0x8b, 0x69, 0x96, 0x2e, 0x92, 0x50, 0x8d, 0xc5, 0x92, 0x88, 0x66, 0x8c, 0x9b, 0x2f, 0xc4, - 0x25, 0x26, 0x5e, 0xcc, 0x12, 0xea, 0x67, 0xcd, 0x29, 0x34, 0x06, 0xb3, 0xa8, 0x1d, 0xd2, 0x29, 0xce, 0xa6, 0x57, - 0xbe, 0xd3, 0xe9, 0x3e, 0xc6, 0xfa, 0x7f, 0xf7, 0x18, 0x59, 0xed, 0xed, 0xc5, 0x9d, 0x76, 0xfb, 0x0f, 0xa8, 0xb7, - 0x36, 0x8a, 0x00, 0xc8, 0xeb, 0xcc, 0x6f, 0xad, 0x3c, 0x85, 0x8c, 0xb6, 0x6d, 0x2d, 0x7b, 0x73, 0x3f, 0x84, 0x7c, - 0x60, 0xaf, 0x3b, 0xbf, 0x2d, 0x60, 0x76, 0x9e, 0x4c, 0x31, 0x55, 0x93, 0x54, 0x4f, 0xcb, 0x5f, 0x0b, 0xf1, 0xc9, - 0x76, 0x88, 0xbb, 0x1a, 0xe2, 0x0a, 0xeb, 0xcd, 0x70, 0x91, 0x89, 0xd8, 0xaa, 0xd7, 0xc9, 0x25, 0x20, 0x51, 0x7a, - 0x4d, 0x33, 0x0d, 0x87, 0x78, 0xf8, 0xd5, 0x60, 0x74, 0xb7, 0x83, 0x71, 0xf2, 0x31, 0x30, 0xb2, 0x24, 0x5c, 0xd6, - 0xd7, 0xb5, 0x93, 0xd1, 0x59, 0x2f, 0xa2, 0x40, 0x4f, 0x5e, 0x17, 0x7e, 0xdf, 0xb0, 0x90, 0x47, 0xf2, 0xa7, 0x20, - 0xe7, 0x1b, 0xf9, 0xee, 0xb8, 0xdd, 0x96, 0xcf, 0x39, 0xfb, 0x85, 0x7a, 0x1d, 0x17, 0x2a, 0x14, 0x63, 0xfc, 0x43, - 0x79, 0x96, 0xb7, 0xce, 0x3d, 0xf1, 0x9f, 0xcd, 0x43, 0xbe, 0x46, 0x8a, 0x62, 0x75, 0x24, 0x1a, 0x67, 0x5a, 0x56, - 0x4a, 0xe1, 0x03, 0x6e, 0x3b, 0xc1, 0x1d, 0x09, 0x1b, 0x94, 0x87, 0x38, 0xd9, 0xf0, 0xcf, 0x32, 0xef, 0xc2, 0x83, - 0x48, 0x87, 0x91, 0x6a, 0x98, 0xf6, 0xb2, 0x01, 0x69, 0xf7, 0xb2, 0x66, 0x13, 0x39, 0x29, 0x49, 0x46, 0x99, 0x4a, - 0xce, 0x73, 0xd8, 0x30, 0x15, 0xc6, 0x76, 0x8e, 0xbc, 0x14, 0x4e, 0x9a, 0xae, 0x56, 0x55, 0x18, 0x80, 0x89, 0xd3, - 0x1a, 0x3f, 0x70, 0x55, 0x01, 0xe7, 0x06, 0x27, 0x4f, 0xf5, 0xd5, 0x2e, 0x89, 0xe6, 0x15, 0x71, 0x1a, 0x08, 0xcc, - 0xb9, 0x73, 0x9f, 0x47, 0xe0, 0xa5, 0x28, 0xc5, 0x4f, 0x95, 0xc2, 0x64, 0xb7, 0x6c, 0x34, 0x4c, 0xca, 0xfc, 0x36, - 0xc8, 0xe3, 0x4b, 0x0a, 0xe8, 0xe5, 0x8e, 0x13, 0x61, 0x31, 0x95, 0xfd, 0x7f, 0xcb, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, - 0x09, 0xe2, 0x45, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xff, 0x6a, 0xd6, 0x12, 0x4d, 0xa0, 0x77, 0x91, 0xcd, 0x03, - 0x15, 0xe1, 0x06, 0x95, 0xf2, 0xb9, 0x29, 0x9e, 0xab, 0xb6, 0xfa, 0x52, 0x09, 0x36, 0x71, 0xa0, 0xa5, 0xbb, 0x48, - 0xd8, 0xcf, 0x0b, 0x7a, 0xc9, 0x42, 0xe3, 0xdc, 0x2e, 0x4d, 0x82, 0x34, 0xa4, 0xdf, 0xbe, 0xfb, 0x0a, 0xb2, 0xdd, - 0xd3, 0x04, 0x48, 0x2c, 0x91, 0xfe, 0x2e, 0x9c, 0x93, 0xc4, 0x0d, 0xe9, 0x35, 0x0b, 0xe8, 0x70, 0xbc, 0xbf, 0xdc, - 0x5a, 0x51, 0xbe, 0x46, 0x45, 0x6b, 0x2c, 0x92, 0xfe, 0x04, 0x94, 0xe3, 0xfd, 0xe5, 0x1d, 0x2f, 0x5a, 0xfb, 0xcb, - 0xc4, 0x0d, 0xd3, 0x99, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xfb, 0x4b, 0x06, 0x3f, 0x78, 0x31, 0x2e, 0xaa, 0x44, 0xd1, - 0x12, 0x22, 0x63, 0x0a, 0x0a, 0x77, 0x1d, 0xe4, 0xfe, 0x94, 0xb2, 0x44, 0x14, 0xdd, 0xd7, 0x33, 0xd5, 0xbd, 0x02, - 0x92, 0xbf, 0x22, 0xd2, 0x60, 0xd6, 0xe6, 0xf2, 0xf5, 0x43, 0xcd, 0x65, 0x9a, 0x70, 0x26, 0xd2, 0xe2, 0x75, 0x38, - 0x27, 0xf2, 0xf3, 0xcb, 0x40, 0x9e, 0x43, 0xcd, 0xab, 0x53, 0x17, 0xbe, 0x40, 0xac, 0xb4, 0x80, 0x69, 0x26, 0x8c, - 0x7d, 0xba, 0xfb, 0xa0, 0x64, 0x72, 0x9f, 0xf1, 0x57, 0x52, 0x55, 0x9e, 0x2e, 0xb2, 0x00, 0x62, 0xbd, 0x4a, 0xa5, - 0xd8, 0xf4, 0x8a, 0xd9, 0x42, 0x7f, 0xb3, 0x31, 0x37, 0x92, 0x6c, 0x39, 0x66, 0xe6, 0x9d, 0x1d, 0x54, 0xc4, 0x13, - 0xe5, 0x59, 0x18, 0xa5, 0x3f, 0xe8, 0x29, 0x81, 0x42, 0x14, 0x8a, 0x7c, 0x51, 0x27, 0x23, 0x83, 0xac, 0xc2, 0x39, - 0x21, 0x84, 0xb9, 0x2c, 0x14, 0x81, 0x3c, 0x50, 0x2c, 0x9a, 0x1d, 0x88, 0x0c, 0xb1, 0xb0, 0xd2, 0xf0, 0x98, 0xc2, - 0xf3, 0x6a, 0xf5, 0x57, 0xee, 0xc8, 0xba, 0xd2, 0xa9, 0x02, 0x3a, 0x18, 0xc3, 0xf2, 0xa5, 0x97, 0xe1, 0xb2, 0x4b, - 0x0f, 0x2a, 0x15, 0xbd, 0x54, 0xa0, 0x4f, 0x22, 0x8b, 0x68, 0x74, 0x9e, 0x4a, 0x15, 0x21, 0x45, 0xd8, 0x7c, 0x5d, - 0x1e, 0xe0, 0xaf, 0xe1, 0xbb, 0xbd, 0xb6, 0x2c, 0xd2, 0x9e, 0x4a, 0xd7, 0x4b, 0xf3, 0x34, 0xe3, 0x8e, 0x13, 0x61, - 0x1f, 0x91, 0x41, 0x24, 0xa8, 0xb6, 0xef, 0x8b, 0x7f, 0x86, 0xcd, 0x8e, 0xd7, 0x29, 0x3d, 0x21, 0xb5, 0x73, 0xd5, - 0x32, 0xcf, 0x4c, 0x9d, 0xcd, 0x05, 0x70, 0x71, 0xf9, 0x5b, 0xce, 0xa7, 0x7a, 0x2e, 0xa7, 0x85, 0x15, 0xe7, 0x92, - 0x52, 0xdf, 0xa9, 0x01, 0x21, 0xe2, 0x6e, 0x3b, 0x86, 0x42, 0x45, 0x35, 0xef, 0x72, 0x17, 0x8f, 0xa5, 0xb6, 0x73, - 0x69, 0x90, 0xf1, 0x98, 0x69, 0x7f, 0x5d, 0x9d, 0xc0, 0x0a, 0x85, 0x11, 0x83, 0x05, 0x6c, 0xab, 0x26, 0x61, 0xb9, - 0x23, 0xc9, 0x56, 0x2a, 0x75, 0xe5, 0x23, 0x95, 0xba, 0xd6, 0xf6, 0x2a, 0x22, 0xeb, 0x71, 0x1b, 0x60, 0xe0, 0x01, - 0xc8, 0xb9, 0x9e, 0x02, 0x30, 0x93, 0x09, 0x15, 0x17, 0xd3, 0x48, 0xd6, 0x82, 0x97, 0x52, 0x8d, 0xf7, 0xec, 0xb7, - 0x6f, 0xce, 0xdf, 0xdb, 0x18, 0xee, 0x33, 0xa3, 0x59, 0xee, 0x2d, 0x6d, 0x95, 0x4c, 0xd8, 0x84, 0xc0, 0xb4, 0xed, - 0xd9, 0xfe, 0x1c, 0xce, 0x66, 0x0b, 0xee, 0xd9, 0xba, 0x6d, 0xde, 0xdc, 0xdc, 0x34, 0xe1, 0xe8, 0x58, 0x73, 0x91, - 0xc5, 0x92, 0xaf, 0x84, 0x76, 0x51, 0x20, 0x97, 0x47, 0x34, 0x29, 0x6f, 0x3c, 0x4a, 0x63, 0xea, 0xc6, 0xe9, 0x54, - 0x1e, 0x7b, 0x5d, 0xf7, 0x43, 0xc4, 0xe3, 0xbe, 0xb8, 0xc9, 0x6b, 0xd0, 0xe7, 0xf2, 0x0e, 0x35, 0x9e, 0xc1, 0xcf, - 0x01, 0x44, 0xa9, 0xfa, 0x2d, 0x1e, 0x89, 0x87, 0x73, 0xd8, 0x36, 0xe2, 0x69, 0x7f, 0xb9, 0x41, 0x64, 0x43, 0xe8, - 0x22, 0x1a, 0xc8, 0xa9, 0xe5, 0xa2, 0xd6, 0xd8, 0x8b, 0xc7, 0xe3, 0xa2, 0xdf, 0x82, 0xbe, 0x5a, 0xba, 0xdf, 0xab, - 0x34, 0xbc, 0xd3, 0xed, 0x4b, 0xc2, 0x83, 0x1b, 0x9d, 0x12, 0x32, 0x80, 0x2e, 0x60, 0xdc, 0x70, 0x20, 0x70, 0xa6, - 0x78, 0xe5, 0xa8, 0x7a, 0x28, 0x2e, 0x2c, 0xe0, 0x8c, 0x05, 0x94, 0x00, 0x5d, 0x42, 0xe7, 0x61, 0xd9, 0x40, 0x6c, - 0x6b, 0x59, 0xb4, 0x0b, 0x40, 0x59, 0xb1, 0xda, 0x2e, 0xd2, 0x9f, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, 0x1f, - 0x23, 0xf8, 0x57, 0x00, 0xde, 0x6f, 0x49, 0x34, 0x8d, 0xcd, 0xdb, 0x65, 0xe4, 0xbd, 0x0f, 0x25, 0x32, 0x47, 0x09, - 0xc7, 0x6f, 0x39, 0xfe, 0x30, 0x16, 0x55, 0xb5, 0x3a, 0x00, 0x7a, 0x2a, 0xa8, 0x4d, 0x6d, 0xad, 0xf7, 0x05, 0x69, - 0x1c, 0xfb, 0xf3, 0x9c, 0x7a, 0xfa, 0x87, 0xd2, 0x0c, 0x40, 0xc1, 0xd8, 0x54, 0xc5, 0x54, 0x82, 0xd3, 0x19, 0x28, - 0x6c, 0x9b, 0x7a, 0xe2, 0xb5, 0x9f, 0x39, 0xcd, 0x66, 0xd0, 0xbc, 0x9a, 0xa2, 0x82, 0x47, 0x4b, 0x53, 0xaf, 0x78, - 0xd4, 0x6e, 0xf7, 0x20, 0x1b, 0xb5, 0xe9, 0xc7, 0x6c, 0x9a, 0x78, 0x31, 0x9d, 0xf0, 0x82, 0xc3, 0x31, 0xc1, 0xa5, - 0x56, 0xe4, 0xdc, 0xee, 0x71, 0x46, 0x67, 0x96, 0x0b, 0x7f, 0xef, 0x1f, 0xb8, 0xe0, 0xa1, 0x97, 0xf0, 0xa8, 0x29, - 0xb2, 0x9e, 0xe1, 0xcc, 0x06, 0x8f, 0x6a, 0xcf, 0x4b, 0x63, 0xa0, 0x80, 0x82, 0x92, 0x5b, 0xf0, 0xcc, 0xe2, 0x11, - 0xe6, 0x99, 0x59, 0x2f, 0x41, 0xcb, 0x8d, 0x19, 0x6c, 0xea, 0x5a, 0x87, 0xa8, 0xc8, 0x85, 0x69, 0xb2, 0x59, 0x59, - 0x2b, 0xac, 0xf5, 0xa7, 0x0d, 0xf4, 0x19, 0xaa, 0x75, 0x21, 0x5d, 0xfb, 0x4b, 0xd9, 0xe2, 0x21, 0xc8, 0xac, 0x29, - 0xfd, 0xd8, 0x6c, 0x81, 0x0a, 0x96, 0xcc, 0x17, 0x7c, 0x24, 0xc2, 0x0a, 0x19, 0x1c, 0x50, 0xb9, 0xc0, 0x46, 0x09, - 0xe0, 0xe0, 0x62, 0x29, 0x81, 0x09, 0xfc, 0x38, 0x70, 0x00, 0x22, 0xab, 0x69, 0x9d, 0x64, 0x74, 0x86, 0x7a, 0x33, - 0x96, 0x34, 0xe5, 0xbb, 0x63, 0x43, 0x31, 0x74, 0x1f, 0xc3, 0x53, 0xe1, 0x8a, 0xde, 0xb0, 0xc8, 0x1e, 0xde, 0x82, - 0xcb, 0xf1, 0x45, 0x51, 0xf4, 0x32, 0xee, 0x8c, 0x5e, 0x39, 0xe8, 0x02, 0x7f, 0x65, 0xdc, 0x8f, 0x63, 0xeb, 0x9d, - 0x64, 0xe3, 0x2e, 0xda, 0x51, 0xc5, 0xdc, 0x0b, 0xa2, 0xda, 0x57, 0x04, 0x2a, 0xbe, 0x70, 0x6c, 0x9a, 0xcf, 0x9b, - 0x92, 0xe5, 0x35, 0x05, 0xc9, 0xda, 0xd0, 0x14, 0x29, 0x5f, 0x39, 0xa5, 0x4b, 0xc1, 0xcd, 0xd4, 0x21, 0x19, 0xe9, - 0xce, 0xb9, 0x28, 0x0f, 0x55, 0xa9, 0x67, 0xf3, 0x18, 0x15, 0xaa, 0xb1, 0x9b, 0xf1, 0x69, 0x9d, 0x35, 0x82, 0x72, - 0x51, 0x5e, 0x22, 0xe8, 0xc7, 0x31, 0x0c, 0x38, 0xd6, 0x1a, 0x89, 0x79, 0xeb, 0xca, 0x88, 0x5f, 0x38, 0xa8, 0x50, - 0xfb, 0xf4, 0xa9, 0x50, 0xea, 0x8d, 0x9b, 0x0b, 0xf7, 0xb8, 0x0e, 0xd7, 0x49, 0x11, 0xcd, 0x20, 0xe1, 0xa0, 0x96, - 0x98, 0xde, 0xab, 0x58, 0x9b, 0x34, 0x09, 0x2c, 0x31, 0x21, 0x62, 0x67, 0x49, 0x68, 0x5b, 0x7f, 0x0a, 0x62, 0x16, - 0x7c, 0x20, 0xf6, 0xfe, 0xd2, 0x41, 0x9b, 0xe7, 0x4e, 0x05, 0x57, 0xd0, 0x7c, 0x1e, 0xd5, 0x43, 0x19, 0x99, 0x6b, - 0xb0, 0x70, 0x79, 0x31, 0x91, 0x3d, 0x00, 0xbd, 0xa9, 0xdf, 0x92, 0xe3, 0x0c, 0xc6, 0xc5, 0x65, 0x75, 0xdf, 0x58, - 0x05, 0x05, 0xa0, 0x59, 0x96, 0x5b, 0x82, 0xa8, 0x88, 0xfd, 0x51, 0x4a, 0xb3, 0x2d, 0xc9, 0xd4, 0x00, 0x4e, 0xae, - 0xf8, 0x9b, 0x6d, 0xfd, 0xa9, 0x2c, 0xa3, 0xa5, 0x4f, 0x49, 0x24, 0xc5, 0x10, 0x1b, 0xc6, 0x02, 0x47, 0x82, 0x1b, - 0x52, 0xee, 0xb3, 0x58, 0x36, 0xe9, 0x69, 0x17, 0xc8, 0xda, 0x8c, 0x56, 0xab, 0xbc, 0x3e, 0x17, 0x56, 0xc7, 0xa0, - 0x98, 0x59, 0xbf, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0xa4, 0x19, 0x9c, 0xad, 0x66, 0x28, 0xdf, 0x59, 0x7f, 0x0a, - 0xc4, 0xb1, 0x2d, 0x00, 0x30, 0x55, 0x00, 0x42, 0xda, 0x80, 0x3c, 0x96, 0xe4, 0xf8, 0x24, 0x75, 0xb9, 0x9f, 0x4d, - 0x29, 0x5f, 0x43, 0xac, 0x2f, 0xb3, 0x84, 0x7b, 0x3a, 0x45, 0x60, 0x03, 0xda, 0xa0, 0x0e, 0x2d, 0x28, 0xd1, 0xc5, - 0x10, 0xf4, 0x60, 0xb2, 0x55, 0x9d, 0x8e, 0x10, 0xc8, 0x5b, 0xb1, 0x38, 0x52, 0xc2, 0xa4, 0x42, 0xc2, 0x48, 0x4e, - 0x60, 0x89, 0xb1, 0x04, 0x88, 0x85, 0x6d, 0x0d, 0x25, 0xe4, 0x34, 0x94, 0x30, 0x93, 0x4c, 0xb4, 0x4a, 0x8b, 0x7e, - 0x4b, 0xd6, 0x96, 0x22, 0x40, 0x56, 0x02, 0x24, 0x88, 0x7d, 0x5a, 0xe1, 0x00, 0x32, 0xcb, 0x4d, 0x3c, 0x84, 0xec, - 0xba, 0x24, 0x36, 0x71, 0x80, 0x6d, 0xd0, 0x8f, 0xfd, 0x2b, 0x1a, 0x0f, 0xf6, 0x97, 0xd9, 0x6a, 0xd5, 0x2e, 0xfa, - 0x2d, 0xf9, 0x68, 0xf5, 0x05, 0xdf, 0x90, 0x97, 0x8e, 0x8a, 0x25, 0x86, 0x53, 0xa1, 0x90, 0x6f, 0xab, 0x13, 0xcd, - 0x3c, 0xd5, 0x41, 0x61, 0x5b, 0x22, 0xc5, 0x45, 0x54, 0x2a, 0xf5, 0xa8, 0xc2, 0xb6, 0x58, 0xb8, 0x59, 0x96, 0x73, - 0x3a, 0x87, 0xd2, 0x68, 0xb5, 0xea, 0x14, 0xb6, 0x35, 0x63, 0x09, 0x3c, 0x65, 0xab, 0x95, 0x38, 0x70, 0x39, 0x63, - 0x89, 0xd3, 0x06, 0xb2, 0xb5, 0xad, 0x99, 0x7f, 0x2b, 0x26, 0xac, 0xdf, 0xf8, 0xb7, 0x4e, 0x47, 0xbd, 0x72, 0x4b, - 0xfc, 0xe4, 0x40, 0x71, 0xd5, 0x8a, 0xfa, 0x6a, 0x45, 0x43, 0xbc, 0x90, 0x47, 0xc9, 0x88, 0x13, 0x12, 0x7f, 0xfb, - 0x8a, 0x86, 0x7a, 0x45, 0x17, 0x3b, 0x56, 0x74, 0x71, 0xcf, 0x8a, 0x06, 0x6a, 0xf5, 0xac, 0x12, 0x77, 0xe9, 0x6a, - 0xd5, 0x69, 0x57, 0xd8, 0xeb, 0xb7, 0x42, 0x76, 0x0d, 0xab, 0x01, 0xda, 0x21, 0x67, 0x33, 0xba, 0x9d, 0x28, 0xeb, - 0x28, 0xa6, 0x9f, 0x84, 0xc9, 0x0a, 0x0b, 0x59, 0x1d, 0x0b, 0x26, 0x5d, 0x97, 0x51, 0xcf, 0xdf, 0x93, 0xb2, 0x19, - 0xe0, 0x21, 0x07, 0x3c, 0x44, 0xfa, 0x12, 0x52, 0xc7, 0x7e, 0x6f, 0x63, 0xdb, 0xb2, 0x35, 0x59, 0x8f, 0x8b, 0x4b, - 0x90, 0x11, 0x62, 0x7e, 0x0f, 0xa2, 0x45, 0xa8, 0x6d, 0x0f, 0x76, 0xd3, 0x1c, 0x24, 0x28, 0xdc, 0xa4, 0x59, 0x68, - 0x7b, 0xb2, 0xea, 0x27, 0xa1, 0x6a, 0xc6, 0x12, 0x95, 0xee, 0xb6, 0x93, 0xd6, 0xaa, 0xf7, 0x26, 0xc5, 0x75, 0x8f, - 0x8f, 0x65, 0x8d, 0xb9, 0xcf, 0x39, 0xcd, 0x12, 0x45, 0xb9, 0xb6, 0xfd, 0x1f, 0x82, 0x0a, 0xb7, 0xf0, 0x95, 0x40, - 0x2f, 0x80, 0x26, 0x40, 0xa5, 0xe7, 0x2b, 0x9e, 0x2f, 0xc5, 0xd3, 0x5e, 0xa5, 0xe0, 0xde, 0x21, 0xd3, 0xd6, 0x90, - 0x45, 0x60, 0xfa, 0x2c, 0x66, 0x34, 0xbc, 0x14, 0x0c, 0x7a, 0x18, 0x8f, 0x95, 0xc2, 0xba, 0x26, 0xee, 0xaa, 0x06, - 0xd8, 0xfe, 0x71, 0xd1, 0x7d, 0x7c, 0x74, 0x66, 0x63, 0xc9, 0xe3, 0xd3, 0xc9, 0xc4, 0x46, 0x85, 0xf5, 0xb0, 0x66, - 0x9d, 0xa3, 0x1f, 0x17, 0x5f, 0x3e, 0x6f, 0x7f, 0x59, 0x36, 0x4e, 0x80, 0x88, 0x54, 0x86, 0x85, 0x16, 0x55, 0x06, - 0xbc, 0x7a, 0x46, 0x13, 0x3f, 0xd9, 0x3d, 0x9d, 0x91, 0x39, 0x9d, 0x7c, 0x4e, 0x69, 0x08, 0xc4, 0x89, 0x37, 0x4a, - 0x2f, 0x63, 0x7a, 0x4d, 0xf5, 0xe5, 0x8f, 0x5b, 0x06, 0xdb, 0xd2, 0x22, 0x48, 0x17, 0x09, 0x57, 0xa9, 0x26, 0x8a, - 0xd5, 0x1a, 0x53, 0x1a, 0x8b, 0x39, 0x98, 0x26, 0xc4, 0x9d, 0x94, 0x73, 0x75, 0xe9, 0x55, 0x8c, 0xb1, 0x6d, 0x00, - 0xb0, 0x13, 0xb2, 0xe1, 0x8e, 0x72, 0xaf, 0x8d, 0xdb, 0xbb, 0x60, 0xc3, 0x1d, 0xe4, 0xd9, 0xf6, 0x85, 0xc6, 0x93, - 0xf0, 0x16, 0xd7, 0x6e, 0xec, 0xd8, 0x89, 0xaf, 0x8f, 0x62, 0xe0, 0x2a, 0x83, 0xce, 0x12, 0x9a, 0xe7, 0x3b, 0x11, - 0x50, 0x2e, 0x22, 0xb6, 0xab, 0xda, 0xf6, 0x8e, 0x5e, 0x70, 0x1b, 0xc3, 0x0e, 0x13, 0x00, 0x97, 0x31, 0x6b, 0x55, - 0x8b, 0x4e, 0x26, 0x34, 0x28, 0x9d, 0xed, 0x10, 0x7d, 0x9c, 0xb0, 0x98, 0x43, 0x10, 0x4e, 0x44, 0xc7, 0xec, 0xd7, - 0x69, 0x42, 0x6d, 0xa4, 0xf3, 0x69, 0x15, 0xfc, 0x4a, 0xfe, 0x6f, 0x87, 0x47, 0xf6, 0x58, 0x87, 0x45, 0x8d, 0xb2, - 0x5a, 0x69, 0x5f, 0x50, 0xad, 0xbc, 0x8e, 0xc8, 0x54, 0x38, 0x7b, 0x76, 0x6d, 0xa0, 0x87, 0x6d, 0x93, 0x65, 0xe7, - 0xcb, 0xe3, 0x4e, 0xbb, 0xb0, 0xb1, 0x0d, 0xdd, 0x3d, 0x74, 0x97, 0x88, 0x56, 0x87, 0xd0, 0x6a, 0x91, 0x7c, 0x4a, - 0xbb, 0x6e, 0xe7, 0x49, 0xc7, 0xc6, 0xf2, 0x22, 0x07, 0x54, 0x94, 0xcc, 0x20, 0x00, 0xf7, 0xf3, 0x6f, 0x9e, 0x4a, - 0xbd, 0xf3, 0x87, 0xc1, 0xf3, 0xa8, 0xd3, 0xb6, 0xb1, 0x9d, 0xf3, 0x74, 0xfe, 0x09, 0x53, 0x38, 0xb4, 0xb1, 0x1d, - 0xc4, 0x69, 0x4e, 0xcd, 0x39, 0x48, 0x75, 0xf6, 0xb7, 0x4f, 0x42, 0x42, 0x34, 0xcf, 0x68, 0x9e, 0x5b, 0x66, 0xff, - 0x8a, 0x94, 0x3e, 0xc2, 0x30, 0xb7, 0x52, 0x5c, 0x4e, 0xb9, 0xc0, 0x8b, 0xbc, 0x63, 0xc1, 0xa4, 0x2a, 0x59, 0xb6, - 0x41, 0x6c, 0x42, 0x04, 0x94, 0x8c, 0x4d, 0x6a, 0x57, 0x1f, 0x1d, 0x79, 0xcb, 0xd6, 0x93, 0x03, 0xcb, 0xa8, 0xfc, - 0xe6, 0x00, 0xb5, 0x92, 0x19, 0x4b, 0x2e, 0xb7, 0x94, 0xfa, 0xb7, 0x5b, 0x4a, 0x41, 0x65, 0x2b, 0xa1, 0x53, 0xf7, - 0xff, 0x7c, 0x1c, 0xeb, 0x95, 0xe2, 0x63, 0x82, 0x18, 0x0a, 0xe7, 0xe6, 0x47, 0x20, 0x35, 0x96, 0x41, 0xf4, 0xf0, - 0xeb, 0x87, 0x83, 0x92, 0x4f, 0x19, 0xae, 0xec, 0xe5, 0xb7, 0xcd, 0x10, 0x4a, 0x9b, 0x10, 0x41, 0x88, 0x3f, 0x69, - 0xae, 0xf4, 0xf6, 0xe3, 0x04, 0x67, 0x68, 0x55, 0xbf, 0x61, 0xe9, 0xd5, 0x3d, 0x02, 0xeb, 0x6b, 0xbf, 0xa5, 0x58, - 0x29, 0x3e, 0xe5, 0xfa, 0x07, 0x31, 0x9b, 0x55, 0x24, 0xb0, 0x09, 0xa6, 0xd0, 0x78, 0x20, 0x9d, 0xcc, 0xec, 0x44, - 0xaa, 0x3e, 0x97, 0x70, 0x48, 0x16, 0xee, 0x21, 0x59, 0x64, 0xf4, 0x32, 0x4e, 0x6f, 0xd6, 0x2f, 0x56, 0xdb, 0x5d, - 0x39, 0x62, 0xd3, 0xc8, 0x38, 0xf9, 0x46, 0x49, 0xb9, 0x08, 0xf7, 0x0e, 0x50, 0xfc, 0xcb, 0x3f, 0xbb, 0xee, 0xbf, - 0xfc, 0xf3, 0x47, 0xab, 0x42, 0xf7, 0xc5, 0x18, 0xf3, 0xaa, 0xdb, 0xdd, 0xbb, 0x6b, 0xfb, 0x48, 0x75, 0x9c, 0x6f, - 0xaf, 0xb3, 0xb1, 0x08, 0xf0, 0x7e, 0x63, 0x09, 0x36, 0x0a, 0xe5, 0xee, 0xb3, 0x7e, 0x0d, 0x60, 0x30, 0xaf, 0x8f, - 0x42, 0x06, 0x95, 0x7e, 0x13, 0x68, 0x63, 0xe4, 0x3d, 0x68, 0x45, 0x7e, 0x3d, 0x86, 0x3f, 0x36, 0x87, 0xdf, 0x08, - 0xbe, 0xf2, 0x4f, 0xc4, 0xe3, 0x71, 0x99, 0xe2, 0x68, 0x36, 0x85, 0x0b, 0x14, 0x86, 0x1b, 0x25, 0x4a, 0xf1, 0xf0, - 0xda, 0x68, 0x20, 0x0e, 0x68, 0x92, 0x78, 0xfc, 0x0a, 0x6e, 0x4d, 0xea, 0x5f, 0x65, 0xda, 0xc1, 0x7b, 0x8f, 0x70, - 0x80, 0x2e, 0xea, 0xb3, 0x12, 0x9d, 0x6e, 0x48, 0x06, 0x28, 0x05, 0x73, 0x03, 0xc0, 0xc4, 0xf1, 0x58, 0x59, 0x9b, - 0x67, 0xd2, 0x0d, 0xe3, 0xad, 0x93, 0xb6, 0x72, 0xcf, 0xd4, 0x90, 0x8e, 0xad, 0xf7, 0x02, 0x5f, 0xa2, 0x32, 0xad, - 0xac, 0x7b, 0xe1, 0xea, 0x02, 0x3b, 0xa2, 0x64, 0x3f, 0xd7, 0x7e, 0x7c, 0xfd, 0x30, 0xc6, 0xb7, 0x5b, 0xa0, 0xae, - 0xac, 0xd5, 0x3f, 0x5a, 0x25, 0x58, 0x35, 0x57, 0xdb, 0xf4, 0x81, 0x1b, 0x9f, 0xd3, 0xec, 0x32, 0x82, 0x2c, 0xab, - 0xec, 0x23, 0xcc, 0x09, 0x56, 0x1a, 0x53, 0xf1, 0x97, 0x11, 0x75, 0x47, 0xf5, 0x3f, 0x88, 0x53, 0x31, 0x48, 0x91, - 0x84, 0xa1, 0x8c, 0x45, 0xf8, 0xff, 0x7c, 0xeb, 0x3f, 0x0c, 0xdf, 0xba, 0x7f, 0x88, 0xda, 0x01, 0xec, 0x4f, 0x5e, - 0xc8, 0xff, 0xd8, 0xec, 0x2e, 0x17, 0xec, 0xee, 0x57, 0x30, 0xba, 0xfc, 0x1f, 0xc3, 0xe8, 0x84, 0x8d, 0xac, 0x39, - 0x9d, 0xba, 0x78, 0xc7, 0x7c, 0xef, 0xdf, 0xf8, 0x77, 0xd5, 0xbe, 0x8a, 0xc7, 0xa7, 0x37, 0xfe, 0x5d, 0xb5, 0x08, - 0xbb, 0xd9, 0xc5, 0x7a, 0x1f, 0x43, 0xfb, 0xcd, 0x6b, 0xdb, 0xb3, 0xdf, 0x7c, 0xf9, 0xa5, 0x8d, 0xc7, 0x39, 0xe5, - 0x43, 0x28, 0x24, 0xfb, 0xcb, 0xbd, 0xf5, 0x8a, 0xe0, 0x46, 0x81, 0x29, 0x8a, 0x50, 0x1b, 0x64, 0x34, 0x1a, 0xef, - 0x59, 0x7e, 0x99, 0x26, 0x26, 0x34, 0x6f, 0xc1, 0xb2, 0xff, 0x54, 0x70, 0x44, 0x2f, 0x1b, 0xf0, 0x88, 0xd2, 0x75, - 0x80, 0x44, 0x61, 0x0d, 0xa2, 0xea, 0x3e, 0xa2, 0xfb, 0xf9, 0x7f, 0x75, 0xe7, 0x82, 0xbc, 0x4a, 0x24, 0x1a, 0xc6, - 0xe3, 0x4f, 0x11, 0x1f, 0x72, 0xb0, 0xca, 0x63, 0xa7, 0xdd, 0x9d, 0x7e, 0xb1, 0xbf, 0x8c, 0x0e, 0x0e, 0xd8, 0xd0, - 0xc6, 0xe2, 0x12, 0xa8, 0x62, 0x9b, 0x70, 0xc9, 0xe1, 0x4f, 0x06, 0x7f, 0xd2, 0x62, 0x5c, 0x88, 0x7c, 0x3c, 0x46, - 0x77, 0xa4, 0x0c, 0xe5, 0xf4, 0xa3, 0x29, 0x43, 0xfe, 0x83, 0x52, 0x86, 0x72, 0xfa, 0x7b, 0xa7, 0x0c, 0x31, 0x6a, - 0xa4, 0x0c, 0x01, 0x1a, 0x7f, 0x7e, 0x50, 0xe6, 0x89, 0xce, 0x13, 0x48, 0x6f, 0x72, 0xd2, 0x51, 0xde, 0x9a, 0x38, - 0x9d, 0x42, 0xda, 0xc9, 0x3f, 0x3e, 0x8b, 0x24, 0x4e, 0xa7, 0x66, 0x0e, 0x09, 0xdc, 0xce, 0x0e, 0x49, 0x23, 0x38, - 0x23, 0x4b, 0xfb, 0xc7, 0xdb, 0xce, 0xd3, 0x51, 0xa7, 0x77, 0xd8, 0x99, 0xd9, 0x9e, 0x0d, 0xe6, 0x91, 0x28, 0x68, - 0xf7, 0x0e, 0x0f, 0xa1, 0xe0, 0xc6, 0x28, 0xe8, 0x42, 0x01, 0x33, 0x0a, 0x8e, 0xa1, 0x20, 0x30, 0x0a, 0x1e, 0x41, - 0x41, 0x68, 0x14, 0x3c, 0x86, 0x82, 0x6b, 0xbb, 0x18, 0xb1, 0x32, 0x2f, 0xea, 0x31, 0x12, 0x17, 0x39, 0xed, 0x65, - 0xf5, 0x43, 0x6c, 0x11, 0xd1, 0x55, 0x1e, 0x97, 0x07, 0x60, 0x9b, 0x47, 0xfa, 0xbe, 0xa6, 0xf1, 0x67, 0x63, 0x84, - 0x7d, 0x02, 0xe7, 0xd1, 0x31, 0x78, 0x4f, 0x65, 0xcd, 0x43, 0xfd, 0xda, 0xf6, 0xca, 0xe4, 0xa1, 0x36, 0xee, 0xea, - 0xf4, 0x21, 0xcf, 0x46, 0x78, 0x51, 0x56, 0x3e, 0x6e, 0x84, 0xaa, 0x5b, 0xb8, 0x0a, 0xa9, 0xba, 0x87, 0xec, 0x10, - 0x61, 0x79, 0x95, 0xff, 0x33, 0x61, 0xc8, 0xb8, 0x3c, 0x7d, 0xcf, 0x66, 0x54, 0x7f, 0x18, 0x4b, 0x0f, 0x60, 0x89, - 0x04, 0xab, 0x5e, 0x54, 0x5d, 0xde, 0xf9, 0x1d, 0x3e, 0xad, 0xae, 0xbe, 0x7b, 0xcf, 0x89, 0xbc, 0x4b, 0x28, 0xc3, - 0xd2, 0x23, 0x37, 0xc5, 0xdc, 0x9f, 0x7a, 0x90, 0x61, 0x02, 0xc1, 0x2d, 0xef, 0x94, 0x10, 0xd2, 0x1e, 0x2e, 0xbc, - 0xef, 0xf0, 0x4d, 0x44, 0x13, 0xef, 0xb2, 0xe8, 0x95, 0x04, 0x20, 0x13, 0x5c, 0xde, 0xf3, 0xf2, 0xc6, 0x54, 0x41, - 0x15, 0xd5, 0x6b, 0x09, 0x67, 0xb3, 0xa4, 0x9e, 0x1d, 0x39, 0x11, 0x86, 0xf3, 0x7c, 0x12, 0xa7, 0x37, 0xcd, 0x5b, - 0x7b, 0xb0, 0x3d, 0x4f, 0x02, 0x66, 0x57, 0xe6, 0x49, 0xbc, 0x04, 0x60, 0xcb, 0xa7, 0xf7, 0xfe, 0xb4, 0xfc, 0xfd, - 0x8a, 0xe6, 0xb9, 0x3f, 0x55, 0x35, 0x77, 0xe7, 0x45, 0x08, 0x10, 0xcd, 0x9c, 0x08, 0x0d, 0x04, 0x24, 0x2f, 0x00, - 0x46, 0xc0, 0xf9, 0xac, 0x72, 0x19, 0x60, 0xea, 0xf5, 0x34, 0x08, 0x81, 0xab, 0x7a, 0x11, 0xf7, 0xa7, 0x55, 0x41, - 0x7f, 0x9e, 0x51, 0x95, 0x60, 0x01, 0x68, 0x2c, 0xfa, 0x2d, 0x28, 0x90, 0xaf, 0x77, 0xa4, 0x3b, 0x68, 0x4f, 0xf7, - 0xee, 0xa4, 0x07, 0x4b, 0xa7, 0x3b, 0x98, 0x29, 0xba, 0x65, 0x7e, 0xee, 0x66, 0x90, 0xfd, 0xf3, 0x4e, 0x00, 0xff, - 0xa9, 0x10, 0xfe, 0xe7, 0x93, 0xc9, 0xe4, 0xde, 0xf4, 0x87, 0xcf, 0xc3, 0x09, 0xed, 0xd2, 0xe3, 0x1e, 0xa4, 0x6f, - 0x36, 0x55, 0xd0, 0xbc, 0x53, 0x08, 0xdc, 0x2d, 0x1f, 0x56, 0x19, 0xe2, 0xeb, 0x3c, 0x5a, 0x3e, 0x3c, 0x15, 0xa2, - 0x98, 0x67, 0x74, 0x39, 0xf3, 0xb3, 0x29, 0x4b, 0xbc, 0x76, 0xe1, 0x5e, 0xab, 0xdc, 0x81, 0xcf, 0x4f, 0x4e, 0x4e, - 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x59, 0x4e, 0xa3, 0xdd, 0x9e, 0x4c, 0x0a, 0x97, 0xe9, 0x82, - 0xc3, 0x6e, 0x10, 0x1e, 0x76, 0x0b, 0xf7, 0xc6, 0xa8, 0x51, 0xb8, 0x54, 0x3d, 0x65, 0x34, 0xac, 0xe5, 0x80, 0x3e, - 0x6e, 0xb7, 0x0b, 0x57, 0x12, 0xda, 0x12, 0xfc, 0x87, 0xf2, 0xa7, 0xe7, 0x2f, 0xb8, 0x60, 0xee, 0x3d, 0x9f, 0x3b, - 0xa3, 0x99, 0xba, 0x5f, 0x4b, 0x7e, 0x8d, 0xaa, 0x40, 0x17, 0xf8, 0x67, 0x33, 0xca, 0x0f, 0xc4, 0x2c, 0xa2, 0xfb, - 0xbe, 0x4e, 0x02, 0xa8, 0xbd, 0x06, 0xca, 0x12, 0xaf, 0x7f, 0x26, 0x7e, 0x15, 0xfc, 0x07, 0x4e, 0x06, 0x35, 0xe5, - 0x35, 0xb0, 0xc9, 0x2e, 0xf9, 0x91, 0x7d, 0x5c, 0x7e, 0xdc, 0x3d, 0x44, 0x7c, 0x64, 0xbf, 0xbb, 0xf8, 0x48, 0x4c, - 0xf1, 0x21, 0x99, 0xc7, 0x15, 0x27, 0x76, 0x10, 0xd1, 0xe0, 0xc3, 0x55, 0x7a, 0xdb, 0x84, 0x2d, 0x91, 0xd9, 0x42, - 0xb0, 0xec, 0xff, 0xda, 0x94, 0x46, 0xdd, 0x99, 0xf1, 0x2d, 0x2b, 0x21, 0x8a, 0xdf, 0x24, 0xc4, 0x7e, 0xa3, 0x9d, - 0x90, 0xb2, 0x64, 0x32, 0x21, 0xf6, 0x9b, 0xc9, 0xc4, 0xd6, 0xb7, 0x04, 0xf8, 0x9c, 0x8a, 0x5a, 0xaf, 0x6b, 0x25, - 0xa2, 0x16, 0x28, 0x25, 0x55, 0x99, 0x59, 0xa0, 0x72, 0x04, 0xcc, 0x7c, 0x00, 0xf5, 0x26, 0x64, 0x39, 0x6c, 0x35, - 0xf8, 0xc4, 0x56, 0xfd, 0x96, 0xe2, 0xa4, 0xf6, 0x41, 0x89, 0x12, 0xe0, 0x2d, 0x5f, 0xc1, 0x58, 0xbf, 0x22, 0x67, - 0x4a, 0x75, 0xc6, 0xfe, 0xd3, 0xbb, 0xaf, 0x42, 0xe7, 0x8a, 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0xb5, 0xe3, 0xaf, 0x12, - 0x46, 0x42, 0xcc, 0x69, 0x15, 0x3c, 0x9d, 0x4e, 0x63, 0xf8, 0xca, 0xd9, 0xb2, 0x76, 0x73, 0xba, 0x6c, 0x3e, 0xac, - 0xcd, 0xd7, 0x33, 0x1b, 0xaa, 0x7b, 0xc6, 0xc5, 0x47, 0x17, 0xe5, 0xb1, 0xa9, 0x6b, 0xf5, 0xf5, 0x3d, 0xe1, 0xbf, - 0x5c, 0x2a, 0x26, 0xbf, 0x94, 0x87, 0x6d, 0x38, 0x66, 0xa1, 0x6c, 0xce, 0xc2, 0xa2, 0x50, 0xc7, 0x14, 0x43, 0x96, - 0xcf, 0xe1, 0x46, 0x6f, 0xd9, 0x92, 0x7e, 0x8c, 0x85, 0xe7, 0x37, 0x46, 0x20, 0xbe, 0xb6, 0x5c, 0x85, 0x8e, 0xc4, - 0xcb, 0xc8, 0xe6, 0x15, 0x2f, 0x6c, 0x15, 0x20, 0xd5, 0x48, 0xb4, 0x2d, 0x89, 0x4f, 0x99, 0x22, 0x60, 0xcc, 0x10, - 0xa2, 0x94, 0xe5, 0x82, 0xe8, 0x57, 0xba, 0xa0, 0x30, 0x13, 0x4d, 0xc4, 0x1b, 0x89, 0x2d, 0x11, 0xd6, 0xce, 0xe7, - 0x7e, 0x22, 0xd9, 0x28, 0xb1, 0x25, 0x3f, 0xd8, 0x5f, 0x56, 0x2b, 0x5f, 0xd8, 0x1a, 0x6c, 0x49, 0xbc, 0x83, 0x7e, - 0x0b, 0x1a, 0x0c, 0xac, 0x1a, 0xe8, 0xc9, 0x46, 0x34, 0xfc, 0xfe, 0xbc, 0xb4, 0x0f, 0x63, 0x37, 0xbf, 0xc1, 0x6e, - 0x7e, 0x63, 0xfd, 0x71, 0xd9, 0xbc, 0xa1, 0x57, 0x1f, 0x18, 0x6f, 0x72, 0x7f, 0xde, 0x04, 0x4b, 0x4f, 0x44, 0xb1, - 0x14, 0x7b, 0x16, 0xf9, 0xed, 0xf2, 0x92, 0x9f, 0xde, 0x22, 0x87, 0xf4, 0x35, 0x61, 0x7e, 0x78, 0x49, 0x9a, 0xd0, - 0x5e, 0xfd, 0x1c, 0x83, 0x99, 0x0d, 0xa5, 0xb1, 0x75, 0xb1, 0x4c, 0x21, 0xdd, 0x8d, 0xdf, 0x79, 0x6d, 0xc5, 0xd6, - 0xdb, 0x3a, 0xd5, 0xa9, 0xbd, 0xb5, 0xbe, 0xa7, 0x90, 0xdb, 0x10, 0xd2, 0x2b, 0xdb, 0x4c, 0xf9, 0xda, 0x95, 0xb2, - 0xf5, 0xb1, 0xac, 0x7e, 0x88, 0x7d, 0xe9, 0xff, 0x8d, 0xe3, 0x10, 0xeb, 0xc5, 0x22, 0xab, 0xff, 0x21, 0x90, 0x79, - 0xfe, 0x84, 0xd3, 0x0c, 0x3f, 0xa4, 0xe6, 0x95, 0x38, 0x80, 0xbb, 0x04, 0x31, 0xe3, 0x75, 0x4e, 0xe6, 0xb7, 0x0f, - 0xef, 0xfe, 0xfe, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x42, 0x3a, 0xdb, 0xee, 0xc1, 0x46, 0x88, 0xfd, 0x3b, 0x8f, 0x25, - 0x42, 0xe6, 0x5d, 0x41, 0x00, 0xab, 0x37, 0x4f, 0xd5, 0xf1, 0x94, 0x8c, 0xc6, 0xe2, 0xfb, 0xb3, 0x6a, 0x29, 0x0e, - 0x1f, 0xcd, 0x6f, 0xf5, 0x6a, 0x74, 0xd6, 0x8e, 0x9d, 0xfc, 0xae, 0xa7, 0x4b, 0x76, 0x1f, 0x67, 0xa9, 0x9f, 0x90, - 0x38, 0x9e, 0xdf, 0xf6, 0xa4, 0xa0, 0x6d, 0x66, 0x12, 0xaa, 0xf6, 0xfc, 0xd6, 0x3c, 0x5f, 0x53, 0x75, 0x64, 0xb9, - 0x87, 0xb9, 0x45, 0xfd, 0x9c, 0xf6, 0xe0, 0x8b, 0x1b, 0x2c, 0xf0, 0x63, 0x25, 0xcc, 0x67, 0x2c, 0x0c, 0x63, 0xda, - 0xd3, 0xf2, 0xda, 0xea, 0x3c, 0x82, 0xe3, 0x29, 0xe6, 0x92, 0xd5, 0x57, 0xc5, 0x40, 0x5e, 0x89, 0x27, 0xff, 0x2a, - 0x4f, 0x63, 0xf8, 0xdc, 0xd5, 0x56, 0x74, 0xaa, 0x73, 0x1b, 0xed, 0x0a, 0x79, 0xe2, 0x77, 0x7d, 0x2e, 0xc7, 0xed, - 0x3f, 0xf4, 0xc4, 0x82, 0xb7, 0x7b, 0x3c, 0x9d, 0x7b, 0xcd, 0xc3, 0xfa, 0x44, 0xe0, 0x55, 0x39, 0x05, 0xbc, 0x65, - 0x5a, 0x18, 0xa4, 0x95, 0xe4, 0xd3, 0x96, 0xdb, 0x51, 0x65, 0xa2, 0x03, 0xc8, 0xef, 0x2d, 0x8b, 0x8a, 0xfa, 0x64, - 0xfe, 0x31, 0xbb, 0xe5, 0xc9, 0xf6, 0xdd, 0xf2, 0x44, 0xef, 0x96, 0xfb, 0x29, 0xf6, 0xf3, 0x49, 0x07, 0xfe, 0xeb, - 0x55, 0x13, 0xf2, 0xda, 0xd6, 0xe1, 0xfc, 0xd6, 0x02, 0x3d, 0xad, 0xd9, 0x9d, 0xdf, 0xca, 0xd3, 0x45, 0x10, 0x64, - 0x6f, 0xc3, 0x79, 0x1b, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, 0x75, 0x8e, 0xe0, 0x1d, 0xb4, 0x3a, 0xde, - 0x7c, 0xd7, 0xbd, 0x7f, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, 0xe4, 0x72, 0xff, 0xea, 0x8a, 0x86, 0xde, - 0x24, 0x0d, 0x16, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdd, 0xd2, 0x6b, 0xfd, 0xe8, 0xa6, 0xf2, 0xac, 0x93, - 0xee, 0x61, 0x59, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, 0xb4, 0x65, 0x13, 0xfc, 0x9b, 0xac, 0xcd, - 0xd6, 0xc9, 0xfc, 0x56, 0x64, 0xdc, 0x8b, 0x84, 0x4f, 0xc2, 0x81, 0xb9, 0x86, 0xed, 0x93, 0xed, 0xe0, 0x8e, 0xf4, - 0x48, 0x17, 0x5a, 0x28, 0x28, 0xb9, 0x13, 0xd2, 0x89, 0xbf, 0x88, 0xf9, 0xfd, 0xbd, 0xee, 0xa2, 0x8c, 0x8d, 0x5e, - 0xef, 0x61, 0xe8, 0x55, 0xdd, 0x07, 0x72, 0xe9, 0xcf, 0x9f, 0x1c, 0xc1, 0x7f, 0x32, 0x51, 0xf7, 0xae, 0xd2, 0xd5, - 0xa5, 0xdd, 0x0b, 0xba, 0xfa, 0x7e, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, 0x83, - 0xaa, 0x2b, 0x2d, 0xeb, 0x93, 0x6a, 0x7f, 0x5a, 0xe7, 0x0f, 0xac, 0x1b, 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x80, - 0x77, 0xa3, 0xb2, 0xc6, 0xb8, 0xa8, 0xbf, 0x4f, 0xee, 0x4a, 0x13, 0x45, 0xa6, 0xcd, 0x80, 0x95, 0xb2, 0x2f, 0xad, - 0x94, 0x94, 0x92, 0x71, 0x7f, 0x78, 0x3b, 0x8b, 0xad, 0x6b, 0x79, 0x51, 0x00, 0xb1, 0x3b, 0x6e, 0xdb, 0xb6, 0x44, - 0xc2, 0x16, 0x7c, 0xaf, 0xc4, 0x16, 0x1f, 0x76, 0xb7, 0x87, 0xa0, 0x69, 0x5d, 0x4f, 0x85, 0x66, 0xf7, 0xd2, 0xbf, - 0xa3, 0xd9, 0x65, 0xd7, 0xb6, 0xc0, 0x4f, 0xd3, 0x94, 0xb9, 0x6d, 0xa2, 0xcc, 0xea, 0xda, 0xd6, 0xed, 0x2c, 0x4e, - 0x72, 0x62, 0x47, 0x9c, 0xcf, 0x3d, 0xf9, 0xe5, 0xf7, 0x9b, 0x43, 0x37, 0xcd, 0xa6, 0xad, 0x6e, 0xbb, 0xdd, 0x86, - 0xab, 0xcf, 0x6d, 0xeb, 0x9a, 0xd1, 0x9b, 0xa7, 0xe9, 0x2d, 0xb1, 0xdb, 0x56, 0xdb, 0xea, 0x74, 0x4f, 0xac, 0x4e, - 0xf7, 0xc8, 0x7d, 0x74, 0x62, 0x0f, 0x3e, 0xb3, 0xac, 0x7e, 0x48, 0x27, 0x39, 0xfc, 0xb0, 0xac, 0xbe, 0x50, 0xbc, - 0xe4, 0x6f, 0xcb, 0x72, 0x83, 0x38, 0x6f, 0x76, 0xac, 0xa5, 0x7a, 0xb4, 0x2c, 0xb8, 0x4e, 0xc1, 0xb3, 0x3e, 0x9f, - 0x74, 0x27, 0x47, 0x93, 0x27, 0x3d, 0x55, 0x5c, 0x7c, 0x56, 0xab, 0x8e, 0xe5, 0xbf, 0x5d, 0xa3, 0x59, 0xce, 0xb3, - 0xf4, 0x03, 0x55, 0xc9, 0xe3, 0x16, 0x88, 0x9e, 0xad, 0x4d, 0xbb, 0x9b, 0x23, 0x75, 0x4e, 0xae, 0x82, 0x49, 0xb7, - 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0xf6, 0x5b, 0x1a, 0xf4, 0xbe, 0x89, 0xa6, 0x4e, 0x73, 0x1b, 0xa2, 0x3a, 0xb6, - 0x9a, 0xe3, 0x54, 0xcf, 0xaf, 0x0f, 0xa7, 0xf7, 0xb4, 0xae, 0x2a, 0x20, 0xb0, 0xad, 0x90, 0xd8, 0xaf, 0x3a, 0xdd, - 0x13, 0xdc, 0xe9, 0x3c, 0x72, 0x1f, 0x9d, 0x04, 0x6d, 0x7c, 0xe4, 0x1e, 0x35, 0x0f, 0xdd, 0x47, 0xf8, 0xa4, 0x79, - 0x82, 0x4f, 0x5e, 0x9c, 0x04, 0xcd, 0x23, 0xf7, 0x08, 0xb7, 0x9b, 0x27, 0x50, 0xd8, 0x3c, 0x69, 0x9e, 0x5c, 0x37, - 0x8f, 0x4e, 0x82, 0xb6, 0x28, 0xed, 0xba, 0xc7, 0xc7, 0xcd, 0x4e, 0xdb, 0x3d, 0x3e, 0xc6, 0xc7, 0xee, 0xa3, 0x47, - 0xcd, 0xce, 0xa1, 0xfb, 0xe8, 0xd1, 0xcb, 0xe3, 0x13, 0xf7, 0x10, 0xde, 0x1d, 0x1e, 0x06, 0x87, 0x6e, 0xa7, 0xd3, - 0x84, 0x3f, 0xf8, 0xc4, 0xed, 0xca, 0x1f, 0x9d, 0x8e, 0x7b, 0xd8, 0xc1, 0xed, 0xf8, 0xb8, 0xeb, 0x3e, 0x7a, 0x82, - 0xc5, 0x5f, 0x51, 0x0d, 0x8b, 0x3f, 0xd0, 0x0d, 0x7e, 0xe2, 0x76, 0x1f, 0xc9, 0x5f, 0xa2, 0xc3, 0xeb, 0xa3, 0x93, - 0xbf, 0xd9, 0xad, 0x9d, 0x73, 0xe8, 0xc8, 0x39, 0x9c, 0x1c, 0xbb, 0x87, 0x87, 0xf8, 0xa8, 0xe3, 0x9e, 0x1c, 0x46, - 0xcd, 0xa3, 0xae, 0xfb, 0xe8, 0x71, 0xd0, 0xec, 0xb8, 0x8f, 0x1f, 0xe3, 0x76, 0xf3, 0xd0, 0xed, 0xe2, 0x8e, 0x7b, - 0x74, 0x28, 0x7e, 0x1c, 0xba, 0xdd, 0xeb, 0xc7, 0x4f, 0xdc, 0x47, 0xc7, 0xd1, 0x23, 0xf7, 0xe8, 0xbb, 0xa3, 0x13, - 0xb7, 0x7b, 0x18, 0x1d, 0x3e, 0x72, 0xbb, 0x8f, 0xaf, 0x1f, 0xb9, 0x47, 0x51, 0xb3, 0xfb, 0xe8, 0xde, 0x96, 0x9d, - 0xae, 0x0b, 0x38, 0x12, 0xaf, 0xe1, 0x05, 0x56, 0x2f, 0xe0, 0xff, 0x48, 0xb4, 0xfd, 0x37, 0xec, 0x26, 0xdf, 0x6c, - 0xfa, 0xc4, 0x3d, 0x79, 0x1c, 0xc8, 0xea, 0x50, 0xd0, 0xd4, 0x35, 0xa0, 0xc9, 0x75, 0x53, 0x0e, 0x2b, 0xba, 0x6b, - 0xea, 0x8e, 0xf4, 0xff, 0x6a, 0xb0, 0xeb, 0x26, 0x0c, 0x2c, 0xc7, 0xfd, 0x77, 0xed, 0xa7, 0x5c, 0xf2, 0x7e, 0x6b, - 0x2a, 0x49, 0x7f, 0x3a, 0xf8, 0x4c, 0x7e, 0xd7, 0xe0, 0xb3, 0x31, 0xf6, 0x77, 0x39, 0x3e, 0xe2, 0x8f, 0x3b, 0x3e, - 0x22, 0xfa, 0x10, 0xcf, 0x47, 0xfc, 0xbb, 0x7b, 0x3e, 0xfc, 0x75, 0xc7, 0xf9, 0x0d, 0xdf, 0x70, 0x70, 0xac, 0x5b, - 0xc5, 0x2f, 0xb9, 0x33, 0x4a, 0xe1, 0x0b, 0x9a, 0x45, 0xef, 0x86, 0x93, 0x88, 0x9a, 0x7e, 0xa0, 0x14, 0x58, 0xec, - 0x0d, 0x97, 0x3c, 0x36, 0xd8, 0x85, 0x90, 0xf0, 0xe3, 0x08, 0xf9, 0xf2, 0x21, 0xf8, 0x08, 0x7f, 0x77, 0x7c, 0x04, - 0x26, 0x3e, 0x6a, 0xbe, 0x7c, 0xe1, 0x69, 0x10, 0x9e, 0x82, 0x73, 0xf1, 0xec, 0xc0, 0xf1, 0xe1, 0x86, 0xdd, 0xa2, - 0x50, 0x94, 0xdb, 0x32, 0x22, 0xf6, 0xee, 0x53, 0xc2, 0x0e, 0xf2, 0xae, 0x00, 0x62, 0x2b, 0xb7, 0xcc, 0x5c, 0x48, - 0x1d, 0xf5, 0x50, 0x0a, 0xa5, 0xae, 0xdb, 0x76, 0xdb, 0xa5, 0x4b, 0x07, 0xee, 0x87, 0x20, 0xcb, 0x94, 0xfb, 0xf0, - 0xad, 0xf6, 0x38, 0x9d, 0x8a, 0xaf, 0xba, 0xc3, 0x77, 0x74, 0x20, 0x3b, 0x33, 0x90, 0x9f, 0x30, 0x82, 0x50, 0x8f, - 0x72, 0xf4, 0xf8, 0xd9, 0x87, 0x6f, 0xe0, 0x8e, 0x06, 0x1d, 0x95, 0x98, 0x81, 0xb7, 0xe3, 0x15, 0x0d, 0x99, 0xef, - 0xd8, 0xce, 0x3c, 0xa3, 0x13, 0x9a, 0xe5, 0xcd, 0xda, 0xc5, 0x05, 0xe2, 0xce, 0x02, 0x64, 0xeb, 0x8f, 0x82, 0x67, - 0xf0, 0x5d, 0x08, 0x32, 0x52, 0xfe, 0x46, 0x5b, 0x19, 0x60, 0x76, 0x81, 0x75, 0x49, 0x06, 0xb2, 0xb6, 0x52, 0xda, - 0x6c, 0xa9, 0xb5, 0x75, 0xdc, 0xee, 0x31, 0xb2, 0x44, 0x31, 0xdc, 0xb8, 0xff, 0x83, 0xd3, 0x3c, 0x6c, 0xff, 0x01, - 0x19, 0xcd, 0xca, 0x8e, 0x2e, 0x94, 0xbb, 0x2d, 0x29, 0xbf, 0xcb, 0xb4, 0x76, 0xab, 0x84, 0x2d, 0x29, 0xe2, 0x73, - 0x39, 0x77, 0x1b, 0xf5, 0x12, 0x15, 0xe0, 0x97, 0x77, 0x23, 0x4d, 0xd8, 0xd4, 0x31, 0xce, 0xdd, 0x26, 0xf2, 0x46, - 0x7f, 0xb8, 0xb6, 0x17, 0xa1, 0xa2, 0xaa, 0x92, 0xa0, 0xa5, 0x88, 0xb7, 0xb0, 0xc4, 0x4a, 0x56, 0x2b, 0x27, 0x01, - 0x17, 0x39, 0x31, 0x70, 0x0a, 0xcf, 0xa8, 0x86, 0xe4, 0x04, 0x97, 0x00, 0x09, 0x04, 0x93, 0x44, 0xfe, 0x5b, 0x15, - 0xeb, 0x1f, 0xca, 0xf1, 0xe5, 0xc6, 0x7e, 0x32, 0x05, 0x2a, 0xf4, 0x93, 0xe9, 0x86, 0x5b, 0x4d, 0x86, 0x8c, 0xd6, - 0x4a, 0xab, 0xae, 0x2a, 0xf7, 0x59, 0xfe, 0xf4, 0xee, 0xbd, 0xba, 0xfa, 0xd3, 0x06, 0xef, 0xb4, 0x88, 0x70, 0x54, - 0x9f, 0x29, 0x68, 0x90, 0x2f, 0xfa, 0x33, 0xca, 0x7d, 0x99, 0x58, 0x0f, 0xfa, 0x04, 0xdc, 0x17, 0x61, 0x29, 0x6b, - 0x94, 0xd8, 0x42, 0xba, 0x13, 0x79, 0xd8, 0x51, 0x8a, 0x7a, 0x6c, 0xa9, 0x3b, 0x73, 0x9a, 0x62, 0x69, 0x48, 0x07, - 0x4b, 0x7f, 0x4c, 0xe0, 0x8b, 0xa3, 0x53, 0x24, 0x49, 0xed, 0xc1, 0x17, 0xe5, 0x77, 0xbf, 0x77, 0x2d, 0x42, 0xcc, - 0x92, 0x0f, 0xa3, 0x8c, 0xc6, 0xff, 0x44, 0xbe, 0x60, 0x41, 0x9a, 0x7c, 0x71, 0x61, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, - 0x4e, 0xc8, 0x17, 0x20, 0xe3, 0x3d, 0x61, 0x7d, 0x00, 0x23, 0x6c, 0xdc, 0xce, 0x62, 0x2c, 0x34, 0xa6, 0x07, 0x28, - 0x44, 0x12, 0x5c, 0xbb, 0x7b, 0x6c, 0x5b, 0xd2, 0x26, 0x16, 0xbf, 0x07, 0x52, 0x9c, 0x0a, 0x25, 0xc0, 0xea, 0x74, - 0xdd, 0xe3, 0xa8, 0xeb, 0x3e, 0xb9, 0x7e, 0xec, 0x9e, 0x44, 0x9d, 0xc7, 0xd7, 0x4d, 0xf8, 0xb7, 0xeb, 0x3e, 0x89, - 0x9b, 0x5d, 0xf7, 0x09, 0xfc, 0xff, 0xdd, 0x91, 0x7b, 0x1c, 0x35, 0x3b, 0xee, 0xc9, 0xf5, 0xa1, 0x7b, 0xf8, 0xb2, - 0xd3, 0x75, 0x0f, 0xad, 0x8e, 0x25, 0xdb, 0x01, 0xbb, 0x96, 0xdc, 0xf9, 0x8b, 0xb5, 0x0d, 0xb1, 0x25, 0x1c, 0x27, - 0x0f, 0x07, 0xd8, 0xd8, 0x29, 0xbf, 0x2e, 0xac, 0xf6, 0xa7, 0x72, 0xd6, 0x3d, 0xf3, 0x33, 0xf8, 0xc4, 0x5b, 0x7d, - 0xef, 0xd6, 0xde, 0xe1, 0x1a, 0xbf, 0xd8, 0x32, 0x04, 0xec, 0x70, 0x1b, 0x9b, 0x97, 0xce, 0xc0, 0x8d, 0x2d, 0xe2, - 0x8b, 0x18, 0xfa, 0x62, 0xe0, 0xdd, 0xa4, 0x2d, 0x2b, 0xea, 0xcb, 0x87, 0x05, 0xb3, 0x60, 0xe2, 0xdb, 0x43, 0x62, - 0x90, 0xaf, 0xc2, 0x62, 0x7d, 0x7c, 0x38, 0xa3, 0x90, 0xa5, 0xc6, 0xbd, 0x3b, 0xb4, 0x3a, 0x59, 0x17, 0x32, 0xb8, - 0x29, 0xa9, 0x28, 0x34, 0xe8, 0x35, 0x37, 0x6d, 0x85, 0x25, 0xc1, 0x2f, 0x68, 0x3e, 0xb4, 0xa1, 0xc8, 0xf6, 0x6c, - 0xe1, 0xe2, 0xb3, 0xcb, 0xcf, 0xdc, 0x95, 0x84, 0x5d, 0x15, 0x60, 0x71, 0x3a, 0x16, 0x76, 0x2d, 0xe0, 0xc7, 0x46, - 0x07, 0x07, 0x3b, 0xf7, 0x8b, 0x50, 0x20, 0x61, 0xae, 0xd5, 0xd7, 0xb1, 0x4c, 0x56, 0x64, 0x9b, 0x88, 0x2e, 0xfb, - 0x15, 0x28, 0x44, 0x0a, 0x4f, 0x57, 0xd4, 0xe7, 0xae, 0x9f, 0xc8, 0x6c, 0x47, 0x83, 0x61, 0xe1, 0x0e, 0x3d, 0x44, - 0x45, 0xca, 0x7d, 0x99, 0x65, 0x64, 0xee, 0xf3, 0x94, 0xfb, 0xfa, 0x16, 0x09, 0xe3, 0xc2, 0x3c, 0x70, 0xf4, 0x46, - 0xdd, 0xc1, 0x9b, 0xf7, 0xa7, 0x96, 0xdc, 0x9e, 0xfd, 0x56, 0xd4, 0x1d, 0xf4, 0x85, 0xcf, 0x44, 0x9e, 0xa8, 0x26, - 0xf2, 0x44, 0xb5, 0xa5, 0x0e, 0xd1, 0x43, 0x24, 0xad, 0x68, 0xc9, 0x69, 0x0b, 0x9b, 0x41, 0x7a, 0x7b, 0x67, 0x8b, - 0x98, 0x33, 0xf8, 0xba, 0x43, 0x4b, 0x1c, 0xa7, 0x86, 0x05, 0x2b, 0x0f, 0xcc, 0x28, 0xed, 0xf0, 0x8a, 0x27, 0xda, - 0x37, 0x3c, 0x61, 0x31, 0xd5, 0x47, 0x64, 0x54, 0x57, 0xe5, 0x91, 0xae, 0xcd, 0xda, 0xf9, 0xe2, 0x6a, 0xc6, 0xb8, - 0xad, 0x0f, 0x9e, 0x7d, 0xab, 0x1a, 0xf4, 0xc5, 0x50, 0x83, 0x71, 0xa1, 0x9c, 0xd7, 0xfa, 0x3b, 0x76, 0xf5, 0x25, - 0x55, 0xb3, 0x57, 0x12, 0x02, 0x8e, 0x32, 0x47, 0x87, 0x83, 0xd2, 0x5d, 0x6c, 0xbe, 0x2b, 0xfa, 0xad, 0xe8, 0x70, - 0x30, 0xf6, 0xe6, 0xaa, 0xbf, 0x97, 0xe9, 0x74, 0x7b, 0x5f, 0x71, 0x3a, 0x1d, 0x8a, 0x33, 0x7b, 0xf2, 0x72, 0x0b, - 0xad, 0xfc, 0xa6, 0xb1, 0x3d, 0xe8, 0x2b, 0x65, 0xc0, 0x12, 0x81, 0x75, 0xfb, 0xb8, 0xad, 0x8f, 0x01, 0xc6, 0xe9, - 0x14, 0x36, 0xa4, 0x6c, 0x62, 0x0c, 0x52, 0xf3, 0xb8, 0x47, 0x9d, 0x41, 0xdf, 0xb7, 0x04, 0x6f, 0x11, 0xcc, 0x23, - 0xf7, 0x5a, 0xd0, 0x38, 0x4a, 0x67, 0xd4, 0x65, 0x69, 0xeb, 0x86, 0x5e, 0x35, 0xfd, 0x39, 0xab, 0xdc, 0xdb, 0xa0, - 0x74, 0x94, 0x43, 0xa6, 0xda, 0x23, 0xae, 0x0e, 0xc9, 0x76, 0x2b, 0x77, 0xdb, 0x11, 0xd8, 0x3c, 0xda, 0x35, 0x27, - 0x7c, 0x72, 0x06, 0x58, 0xe9, 0xa0, 0xdf, 0xf2, 0xd7, 0x30, 0x22, 0xf8, 0x7d, 0xa1, 0x1c, 0xed, 0x60, 0xd8, 0x00, - 0xbd, 0xd9, 0x96, 0x14, 0x07, 0xda, 0x21, 0xaf, 0x04, 0x75, 0x61, 0x0f, 0xfe, 0xf5, 0x7f, 0xfc, 0x2f, 0xe5, 0x63, - 0xef, 0xb7, 0xa2, 0x8e, 0xee, 0x6b, 0x6d, 0x55, 0x8a, 0x3e, 0x1c, 0xe4, 0xaf, 0x82, 0xc2, 0xf4, 0xb6, 0x39, 0xcd, - 0x58, 0xd8, 0x8c, 0xfc, 0x78, 0x62, 0x0f, 0x76, 0x63, 0xd3, 0x3c, 0x5f, 0xab, 0xa0, 0xae, 0x17, 0x01, 0xbd, 0xfe, - 0xaa, 0x13, 0xa2, 0xfa, 0xa0, 0xa1, 0xd8, 0xda, 0xe6, 0x79, 0xd1, 0x6a, 0xf7, 0xd5, 0xce, 0x8c, 0x26, 0xea, 0xe3, - 0x98, 0x8a, 0x03, 0x26, 0xb5, 0xa3, 0xa2, 0x85, 0x6d, 0x95, 0x41, 0xad, 0xff, 0xfb, 0x3f, 0xff, 0xcb, 0x7f, 0xd3, - 0x8f, 0x10, 0xab, 0xfa, 0xd7, 0xff, 0xfe, 0x9f, 0xff, 0xcf, 0xff, 0xfe, 0xaf, 0x70, 0xbc, 0x50, 0xc5, 0xb3, 0x04, - 0x53, 0xb1, 0xaa, 0x60, 0x96, 0xe4, 0x2e, 0x16, 0x64, 0xe0, 0xcf, 0x58, 0xce, 0x59, 0x50, 0x3f, 0x3c, 0x7a, 0x2e, - 0x06, 0x14, 0x3b, 0x53, 0x41, 0x27, 0x76, 0x78, 0x51, 0x11, 0x54, 0x0d, 0xe5, 0x82, 0x70, 0x8b, 0x7e, 0x0b, 0xf0, - 0xfd, 0xb0, 0xf3, 0xf6, 0x6e, 0xb9, 0x1c, 0x4b, 0x4d, 0x26, 0x50, 0x52, 0x54, 0xe5, 0x16, 0xc4, 0x56, 0x96, 0xf0, - 0xe8, 0x75, 0x8d, 0x62, 0xb1, 0x7a, 0xb5, 0x36, 0xbd, 0x9f, 0x16, 0x39, 0x67, 0x13, 0x40, 0xb9, 0xf4, 0x13, 0x8b, - 0x30, 0x76, 0x13, 0x74, 0xc5, 0xf8, 0xae, 0x10, 0xbd, 0x48, 0x02, 0x3d, 0x3a, 0xf9, 0x43, 0xf1, 0xa7, 0x19, 0x68, - 0x64, 0x96, 0x33, 0xf3, 0x6f, 0x95, 0x79, 0xfe, 0xa8, 0xdd, 0x9e, 0xdf, 0xa2, 0x65, 0x35, 0x02, 0xde, 0x35, 0x98, - 0xa0, 0x63, 0xb3, 0x43, 0x11, 0xff, 0x2e, 0xdd, 0xd8, 0x6d, 0x0b, 0x7c, 0xe1, 0x56, 0xbb, 0x28, 0xfe, 0xb8, 0x14, - 0x9e, 0x54, 0xf6, 0x0b, 0xc4, 0xa9, 0x95, 0xd3, 0xf9, 0x2a, 0x35, 0x27, 0xb7, 0x34, 0x5a, 0x75, 0x65, 0xab, 0xa8, - 0xb3, 0x79, 0x8c, 0xdc, 0x8c, 0xb3, 0x9b, 0x11, 0xf2, 0x23, 0x88, 0x79, 0x47, 0x1d, 0x1c, 0x75, 0x97, 0x65, 0xf7, - 0x9c, 0xa7, 0x33, 0x33, 0xb0, 0x4e, 0x7d, 0x1a, 0xd0, 0x89, 0x76, 0xd6, 0xab, 0xf7, 0x32, 0x68, 0x5e, 0x44, 0x87, - 0x5b, 0xc6, 0x52, 0x20, 0x89, 0x80, 0xba, 0xd5, 0x2e, 0x3e, 0x87, 0x1d, 0xb8, 0x9c, 0xc4, 0xa9, 0xcf, 0x3d, 0x41, - 0xb0, 0x3d, 0x33, 0x3c, 0xef, 0x03, 0x4f, 0x4a, 0x97, 0x06, 0x3c, 0x3d, 0x59, 0x15, 0xdc, 0xe6, 0xf5, 0xc3, 0xfe, - 0x85, 0x2b, 0x9a, 0x9b, 0x5d, 0x49, 0xaf, 0xdb, 0x97, 0x2a, 0xea, 0xfd, 0xae, 0xe6, 0xae, 0x52, 0x02, 0xa9, 0x8b, - 0xb6, 0xbf, 0x97, 0x72, 0x5d, 0xbe, 0xfd, 0x86, 0x3b, 0xb6, 0x00, 0xd3, 0x5e, 0xaf, 0x25, 0x0a, 0xa1, 0xd6, 0x3b, - 0xf2, 0x65, 0x69, 0x32, 0xf9, 0xf3, 0xb9, 0xa8, 0x88, 0x7a, 0xfd, 0x96, 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, - 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, 0x68, 0xea, 0xe0, 0xff, 0x01, 0x0b, 0x95, - 0x29, 0x52, 0xc9, 0x90, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdc, 0x48, 0xb6, 0xd8, 0xb3, + 0xe7, 0x2b, 0x40, 0x34, 0x2f, 0x85, 0x1c, 0x66, 0xa1, 0x16, 0x92, 0x12, 0x85, 0x62, 0x56, 0x0d, 0x45, 0xa9, 0x47, + 0x3d, 0xad, 0x6d, 0x44, 0xa9, 0x7b, 0xa6, 0xd9, 0x1c, 0x12, 0x04, 0xb2, 0x0a, 0xd9, 0x42, 0x01, 0xd5, 0x89, 0x2c, + 0x2e, 0x5d, 0x85, 0x1b, 0xfe, 0x00, 0x47, 0x38, 0xc2, 0x4f, 0x7e, 0x71, 0xf8, 0x3e, 0xf8, 0x23, 0xfc, 0x7c, 0x3f, + 0xc5, 0x3f, 0x60, 0x7f, 0x82, 0xe3, 0xe4, 0x02, 0x24, 0x6a, 0xa1, 0xa8, 0x9e, 0x9e, 0xeb, 0xfb, 0xe0, 0xe8, 0x68, + 0xaa, 0x90, 0xc8, 0xe5, 0xe4, 0xc9, 0x93, 0x67, 0xcf, 0xc4, 0xd1, 0x56, 0x9c, 0x47, 0xe2, 0x6e, 0x4a, 0x9d, 0x44, + 0x4c, 0xd2, 0xc1, 0x91, 0xfe, 0x4b, 0xc3, 0x78, 0x70, 0x94, 0xb2, 0xec, 0x93, 0xc3, 0x69, 0x4a, 0x58, 0x94, 0x67, + 0x4e, 0xc2, 0xe9, 0x88, 0xc4, 0xa1, 0x08, 0x03, 0x36, 0x09, 0xc7, 0xd4, 0x69, 0x0f, 0x8e, 0x26, 0x54, 0x84, 0x4e, + 0x94, 0x84, 0xbc, 0xa0, 0x82, 0x7c, 0xfc, 0xf0, 0x75, 0xeb, 0x70, 0x70, 0x54, 0x44, 0x9c, 0x4d, 0x85, 0x03, 0x5d, + 0x92, 0x49, 0x1e, 0xcf, 0x52, 0x3a, 0x68, 0xb7, 0x6f, 0x6e, 0x6e, 0xfc, 0x9f, 0x8a, 0xdf, 0x45, 0x79, 0x56, 0x08, + 0xe7, 0x39, 0xb9, 0x61, 0x59, 0x9c, 0xdf, 0x60, 0x2e, 0xc8, 0x73, 0xff, 0x34, 0x09, 0xe3, 0xfc, 0xe6, 0x7d, 0x9e, + 0x8b, 0x9d, 0x1d, 0x4f, 0x3d, 0xde, 0x9d, 0x9c, 0x9e, 0x12, 0x42, 0xae, 0x73, 0x16, 0x3b, 0x9d, 0xc5, 0xa2, 0x2e, + 0xf4, 0xb3, 0x50, 0xb0, 0x6b, 0xaa, 0x9a, 0xa0, 0x9d, 0x1d, 0x37, 0x8c, 0xf3, 0xa9, 0xa0, 0xf1, 0xa9, 0xb8, 0x4b, + 0xe9, 0x69, 0x42, 0xa9, 0x28, 0x5c, 0x96, 0x39, 0xcf, 0xf3, 0x68, 0x36, 0xa1, 0x99, 0xf0, 0xa7, 0x3c, 0x17, 0x39, + 0x40, 0xb2, 0xb3, 0xe3, 0x72, 0x3a, 0x4d, 0xc3, 0x88, 0xc2, 0xfb, 0x93, 0xd3, 0xd3, 0xba, 0x45, 0x5d, 0x09, 0x67, + 0x82, 0x9c, 0xde, 0x4d, 0xae, 0xf2, 0xd4, 0x43, 0x38, 0x11, 0x24, 0xa3, 0x37, 0xce, 0xf7, 0x34, 0xfc, 0xf4, 0x3a, + 0x9c, 0xf6, 0xa3, 0x34, 0x2c, 0x0a, 0xe7, 0x58, 0xcc, 0xe5, 0x14, 0xf8, 0x2c, 0x12, 0x39, 0xf7, 0x04, 0xa6, 0x98, + 0xa1, 0x39, 0x1b, 0x79, 0x22, 0x61, 0x85, 0x7f, 0xb1, 0x1d, 0x15, 0xc5, 0x7b, 0x5a, 0xcc, 0x52, 0xb1, 0x4d, 0xb6, + 0x3a, 0x98, 0x6d, 0x11, 0x92, 0x09, 0x24, 0x12, 0x9e, 0xdf, 0x38, 0x2f, 0x38, 0xcf, 0xb9, 0xe7, 0x9e, 0x9c, 0x9e, + 0xaa, 0x1a, 0x0e, 0x2b, 0x9c, 0x2c, 0x17, 0x4e, 0xd5, 0x5f, 0x78, 0x95, 0x52, 0xdf, 0xf9, 0x58, 0x50, 0xe7, 0x72, + 0x96, 0x15, 0xe1, 0x88, 0x9e, 0x9c, 0x9e, 0x5e, 0x3a, 0x39, 0x77, 0x2e, 0xa3, 0xa2, 0xb8, 0x74, 0x58, 0x56, 0x08, + 0x1a, 0xc6, 0xbe, 0x8b, 0xfa, 0x72, 0xb0, 0xa8, 0x28, 0x3e, 0xd0, 0x5b, 0x41, 0x04, 0x96, 0x8f, 0x82, 0xd0, 0x72, + 0x4c, 0x85, 0x53, 0x54, 0xf3, 0xf2, 0xd0, 0x3c, 0xa5, 0xc2, 0x11, 0x44, 0xbe, 0xcf, 0xfb, 0x0a, 0xf7, 0x54, 0x3d, + 0x8a, 0x3e, 0x1b, 0x79, 0x5c, 0xec, 0xec, 0x88, 0x0a, 0xcf, 0x48, 0x4d, 0xcd, 0x61, 0x84, 0x6e, 0x99, 0xb2, 0x9d, + 0x1d, 0xea, 0xa7, 0x34, 0x1b, 0x8b, 0x84, 0x10, 0xd2, 0xed, 0xb3, 0x9d, 0x1d, 0x4f, 0x90, 0x44, 0xf8, 0x63, 0x2a, + 0x3c, 0x8a, 0x10, 0xae, 0x5b, 0xef, 0xec, 0x78, 0x0a, 0x09, 0x39, 0x51, 0x88, 0x6b, 0xe0, 0x18, 0xf9, 0x1a, 0xfb, + 0xa7, 0x77, 0x59, 0xe4, 0xd9, 0xf0, 0x23, 0xcc, 0x76, 0x76, 0x12, 0xe1, 0x17, 0xd0, 0x23, 0x16, 0x08, 0x95, 0x9c, + 0x8a, 0x19, 0xcf, 0x1c, 0x51, 0x8a, 0xfc, 0x54, 0x70, 0x96, 0x8d, 0x3d, 0x34, 0x37, 0x65, 0x56, 0xc3, 0xb2, 0x54, + 0xe0, 0xbe, 0x17, 0x24, 0x23, 0x03, 0x18, 0xf1, 0x58, 0x78, 0xb0, 0x8a, 0xf9, 0xc8, 0xc9, 0x08, 0x71, 0x0b, 0xd9, + 0xd6, 0x1d, 0x66, 0x41, 0xb6, 0xeb, 0xba, 0x58, 0x41, 0x89, 0x33, 0x81, 0xf0, 0x27, 0xe2, 0x65, 0xd8, 0xf7, 0x7d, + 0x81, 0xc8, 0x60, 0x6e, 0xb0, 0x92, 0x59, 0xf3, 0x1c, 0x66, 0x67, 0x9d, 0xf3, 0x40, 0xf8, 0x9c, 0xc6, 0xb3, 0x88, + 0x7a, 0x1e, 0xc3, 0x1c, 0xe7, 0x88, 0x0c, 0xd8, 0xae, 0x57, 0x90, 0x01, 0x2c, 0xf7, 0xd2, 0x5a, 0x13, 0xb2, 0xd5, + 0x41, 0x1a, 0xc6, 0x0a, 0x40, 0xc0, 0xb0, 0x86, 0xa7, 0x20, 0xc4, 0xcd, 0x66, 0x93, 0x2b, 0xca, 0xdd, 0xaa, 0x5a, + 0xbf, 0x41, 0x16, 0xb3, 0x82, 0x3a, 0x51, 0x51, 0x38, 0xa3, 0x59, 0x16, 0x09, 0x96, 0x67, 0x8e, 0xbb, 0x5b, 0xec, + 0xba, 0x8a, 0x1c, 0x2a, 0x6a, 0x70, 0x51, 0x89, 0x3c, 0x8e, 0x76, 0xb3, 0xb3, 0x7c, 0xb7, 0x7b, 0x8e, 0x01, 0x4a, + 0xd4, 0xd7, 0xfd, 0x69, 0x04, 0x50, 0x9c, 0xc1, 0x1c, 0x4b, 0xfc, 0x4c, 0xc0, 0x2c, 0xe5, 0x14, 0xb9, 0x18, 0x66, + 0xfe, 0xea, 0x46, 0x21, 0xc2, 0x9f, 0x84, 0x53, 0x8f, 0x92, 0x01, 0x95, 0xc4, 0x15, 0x66, 0x11, 0xc0, 0xda, 0x58, + 0xb7, 0x21, 0x0d, 0xa8, 0x5f, 0x93, 0x14, 0x0a, 0x84, 0x3f, 0xca, 0xf9, 0x8b, 0x30, 0x4a, 0xa0, 0x5d, 0x45, 0x30, + 0xb1, 0xd9, 0x6f, 0x11, 0xa7, 0xa1, 0xa0, 0x2f, 0x52, 0x0a, 0x4f, 0x9e, 0x2b, 0x5b, 0xba, 0x08, 0x73, 0xf2, 0xdc, + 0x4f, 0x99, 0x78, 0x93, 0x67, 0x11, 0xed, 0x73, 0x8b, 0xba, 0x18, 0xac, 0xfb, 0xb1, 0x10, 0x9c, 0x5d, 0xcd, 0x04, + 0xf5, 0xdc, 0x0c, 0x6a, 0xb8, 0x98, 0x23, 0xcc, 0x7c, 0x41, 0x6f, 0xc5, 0x49, 0x9e, 0x09, 0x9a, 0x09, 0x42, 0x0d, + 0x52, 0x71, 0xe6, 0x87, 0xd3, 0x29, 0xcd, 0xe2, 0x93, 0x84, 0xa5, 0xb1, 0xc7, 0x50, 0x89, 0x4a, 0x1c, 0x09, 0x02, + 0x73, 0x24, 0x83, 0x2c, 0x80, 0x3f, 0x9b, 0x67, 0xe3, 0x09, 0x32, 0x90, 0x9b, 0x82, 0x12, 0xd7, 0xed, 0x8f, 0x72, + 0xee, 0xe9, 0x19, 0x38, 0xf9, 0xc8, 0x11, 0x30, 0xc6, 0xfb, 0x59, 0x4a, 0x0b, 0x44, 0x77, 0x09, 0xab, 0x96, 0x51, + 0x23, 0xf8, 0x3d, 0x50, 0x7c, 0x89, 0xbc, 0x0c, 0x05, 0x59, 0xff, 0x3a, 0xe4, 0xce, 0x0f, 0x7a, 0x47, 0xfd, 0x64, + 0xb8, 0x59, 0x2c, 0xc8, 0x4f, 0xbe, 0xe0, 0xb3, 0x42, 0xd0, 0xf8, 0xc3, 0xdd, 0x94, 0x16, 0xf8, 0xa5, 0x20, 0xb1, + 0x18, 0xc6, 0xc2, 0xa7, 0x93, 0xa9, 0xb8, 0x3b, 0x95, 0x8c, 0x31, 0x70, 0x5d, 0x3c, 0x83, 0x9a, 0x9c, 0x86, 0x11, + 0x30, 0x33, 0x8d, 0xad, 0x77, 0x79, 0x7a, 0x37, 0x62, 0x69, 0x7a, 0x3a, 0x9b, 0x4e, 0x73, 0x2e, 0xb0, 0x10, 0x64, + 0x2e, 0xf2, 0x1a, 0x37, 0xb0, 0x98, 0xf3, 0xe2, 0x86, 0x89, 0x28, 0xf1, 0x04, 0x9a, 0x47, 0x61, 0x41, 0x9d, 0x67, + 0x79, 0x9e, 0xd2, 0x10, 0x66, 0x9d, 0x0d, 0x5f, 0x8a, 0x20, 0x9b, 0xa5, 0x69, 0xff, 0x8a, 0xd3, 0xf0, 0x53, 0x5f, + 0xbe, 0x7e, 0x7b, 0xf5, 0x13, 0x8d, 0x44, 0x20, 0x7f, 0x1f, 0x73, 0x1e, 0xde, 0x41, 0x45, 0x42, 0xa0, 0xda, 0x30, + 0x0b, 0xfe, 0x74, 0xfa, 0xf6, 0x8d, 0xaf, 0x76, 0x09, 0x1b, 0xdd, 0x79, 0x59, 0xb5, 0xf3, 0xb2, 0x12, 0x8f, 0x78, + 0x3e, 0x59, 0x1a, 0x5a, 0xa1, 0x2d, 0xeb, 0x6f, 0x00, 0x81, 0x92, 0x6c, 0x4b, 0x75, 0x6d, 0x43, 0xf0, 0x46, 0x12, + 0x3d, 0xbc, 0x24, 0x66, 0xdc, 0x59, 0x9a, 0x06, 0xaa, 0xd8, 0xcb, 0xd0, 0xfd, 0xd0, 0x0a, 0x7e, 0x37, 0xa7, 0x44, + 0xc2, 0x39, 0x05, 0x11, 0x03, 0x30, 0x46, 0xa1, 0x88, 0x92, 0x39, 0x95, 0x9d, 0x95, 0x06, 0x62, 0x5a, 0x96, 0xf8, + 0x45, 0x45, 0xf0, 0x02, 0x00, 0x91, 0x9c, 0x8a, 0x88, 0xc5, 0x02, 0x26, 0x8c, 0xf0, 0x9f, 0xc8, 0x3c, 0x34, 0xf3, + 0x09, 0xb6, 0x3a, 0x18, 0x36, 0x66, 0xa0, 0xd8, 0x0b, 0x8e, 0xf2, 0xec, 0x9a, 0x72, 0x41, 0x79, 0x20, 0x04, 0xe6, + 0x74, 0x94, 0x02, 0x18, 0x5b, 0x5d, 0x9c, 0x84, 0xc5, 0x49, 0x12, 0x66, 0x63, 0x1a, 0x07, 0x2f, 0x44, 0x89, 0xa9, + 0x20, 0xee, 0x88, 0x65, 0x61, 0xca, 0x7e, 0xa1, 0xb1, 0xab, 0x05, 0xc2, 0x0b, 0x87, 0xde, 0x0a, 0x9a, 0xc5, 0x85, + 0xf3, 0xf2, 0xc3, 0xeb, 0x57, 0x7a, 0x29, 0x1b, 0x32, 0x02, 0xcd, 0x8b, 0xd9, 0x94, 0x72, 0x0f, 0x61, 0x2d, 0x23, + 0x5e, 0x30, 0xc9, 0x1f, 0x5f, 0x87, 0x53, 0x55, 0xc2, 0x8a, 0x8f, 0xd3, 0x38, 0x14, 0xf4, 0x1d, 0xcd, 0x62, 0x96, + 0x8d, 0xc9, 0x56, 0x57, 0x95, 0x27, 0xa1, 0x7e, 0x11, 0x57, 0x45, 0x17, 0xdb, 0x2f, 0x52, 0x39, 0xf3, 0xea, 0x71, + 0xe6, 0xa1, 0xb2, 0x10, 0xa1, 0x60, 0x91, 0x13, 0xc6, 0xf1, 0x37, 0x19, 0x13, 0x4c, 0x02, 0xc8, 0x61, 0x81, 0x80, + 0x4a, 0xa9, 0x92, 0x16, 0x06, 0x70, 0x0f, 0x61, 0xcf, 0xd3, 0x32, 0x20, 0x41, 0x7a, 0xc5, 0x76, 0x76, 0x6a, 0x8e, + 0x3f, 0xa4, 0x81, 0x7a, 0x49, 0xce, 0xce, 0x91, 0x3f, 0x9d, 0x15, 0xb0, 0xd4, 0x66, 0x08, 0x10, 0x30, 0xf9, 0x55, + 0x41, 0xf9, 0x35, 0x8d, 0x2b, 0xf2, 0x28, 0x3c, 0x34, 0x5f, 0x1a, 0x43, 0xef, 0x0c, 0x41, 0xce, 0xce, 0xfb, 0x36, + 0xeb, 0xa6, 0x9a, 0xd4, 0x79, 0x3e, 0xa5, 0x5c, 0x30, 0x5a, 0x54, 0xdc, 0xc4, 0x03, 0x41, 0x5a, 0x71, 0x14, 0x4e, + 0xcc, 0xfc, 0xa6, 0x1e, 0xc3, 0x14, 0x35, 0x78, 0x86, 0x91, 0xb5, 0x2f, 0xae, 0xa5, 0xd0, 0xe0, 0x98, 0x21, 0x2c, + 0x14, 0xa4, 0x1c, 0xa1, 0x12, 0x61, 0x61, 0xc0, 0x55, 0xdc, 0x48, 0x8f, 0x76, 0x07, 0xd2, 0x9a, 0xfc, 0x49, 0x4a, + 0x6b, 0xe0, 0x69, 0xa1, 0xa0, 0x3b, 0x3b, 0x1e, 0xf5, 0x2b, 0xb2, 0x20, 0x5b, 0x5d, 0xbd, 0x46, 0x16, 0xb2, 0x36, + 0x80, 0x0d, 0x03, 0x0b, 0x4c, 0x11, 0xde, 0xa2, 0x7e, 0x96, 0x1f, 0x47, 0x11, 0x2d, 0x8a, 0x9c, 0xef, 0xec, 0x6c, + 0xc9, 0xfa, 0x95, 0x42, 0x01, 0x6b, 0xf8, 0xf6, 0x26, 0xab, 0x21, 0x40, 0xb5, 0x90, 0xd5, 0xa2, 0x41, 0x80, 0xa8, + 0x92, 0x3a, 0x87, 0x3b, 0x34, 0xba, 0x47, 0xe0, 0x5e, 0x5c, 0xb8, 0xbb, 0x02, 0x6b, 0x34, 0x8c, 0xa9, 0x19, 0xfa, + 0xee, 0x39, 0x55, 0xda, 0x95, 0xd4, 0x3d, 0x56, 0x30, 0xa3, 0x76, 0x90, 0x1f, 0xd3, 0x11, 0xcb, 0xac, 0x69, 0x37, + 0x40, 0xc2, 0x02, 0x73, 0x54, 0x5a, 0x0b, 0xba, 0xb6, 0x6b, 0xa9, 0xd6, 0xa8, 0x95, 0x9b, 0x8f, 0xa5, 0x2a, 0x61, + 0x2d, 0xe3, 0x19, 0x3d, 0x2f, 0xb1, 0x44, 0xbd, 0x99, 0x4d, 0x2e, 0x01, 0x3d, 0x13, 0xe7, 0x7d, 0xfd, 0x9e, 0x70, + 0x85, 0x39, 0x4e, 0x7f, 0x9e, 0xd1, 0x42, 0x28, 0x3a, 0xf6, 0x04, 0xce, 0x31, 0x03, 0x7e, 0x9d, 0x67, 0x23, 0x36, + 0x9e, 0x71, 0xd0, 0x78, 0x60, 0x33, 0xd2, 0x6c, 0x36, 0xa1, 0xe6, 0x69, 0x1d, 0x6c, 0x6f, 0xa7, 0x20, 0x13, 0x0b, + 0xa0, 0xe9, 0xfb, 0xc9, 0x09, 0x60, 0x15, 0x68, 0xb1, 0xf8, 0x93, 0xe9, 0xa4, 0x5e, 0xca, 0x4a, 0x4b, 0x5b, 0x5a, + 0x13, 0x2a, 0x90, 0x96, 0xc9, 0x5b, 0x5d, 0x0d, 0xbe, 0x38, 0x27, 0x5b, 0x9d, 0x8a, 0x86, 0x35, 0x56, 0x15, 0x38, + 0x0a, 0x89, 0x6f, 0x55, 0x57, 0x48, 0x8a, 0xf8, 0x06, 0xb9, 0xf8, 0xc9, 0x0a, 0xa5, 0x26, 0xe4, 0x0c, 0x94, 0x0d, + 0x3f, 0x39, 0xdf, 0x44, 0x4e, 0x86, 0x1f, 0x78, 0x62, 0xf5, 0x5d, 0xcd, 0x36, 0xae, 0x9b, 0x6c, 0x63, 0x69, 0x1a, + 0xee, 0xb4, 0x6a, 0xe2, 0x56, 0x54, 0xa6, 0x37, 0x7a, 0xfd, 0x0a, 0x33, 0x09, 0x4c, 0x3d, 0x25, 0xab, 0x8b, 0x37, + 0xe1, 0x84, 0x16, 0x1e, 0x45, 0x78, 0x53, 0x05, 0x45, 0x9e, 0x50, 0xe5, 0xdc, 0x92, 0x9d, 0x1c, 0x64, 0x27, 0x43, + 0x4a, 0x35, 0x6b, 0x6e, 0x38, 0x8e, 0xe9, 0x19, 0x3f, 0xaf, 0x35, 0x3a, 0x6b, 0xf2, 0x52, 0x28, 0x17, 0xa4, 0xb1, + 0xdd, 0x54, 0x99, 0x42, 0x9a, 0xd4, 0x1c, 0x0a, 0x84, 0xb7, 0x3a, 0xcb, 0x2b, 0x69, 0x6a, 0xd5, 0x73, 0x3c, 0x3b, + 0x87, 0x75, 0x90, 0x22, 0xc3, 0x67, 0x85, 0xfc, 0xb7, 0xb1, 0xd3, 0x00, 0x6d, 0xa7, 0x40, 0x18, 0xfe, 0x28, 0x0d, + 0x85, 0xd7, 0x6d, 0x77, 0x40, 0x1d, 0xbd, 0xa6, 0x20, 0x51, 0x10, 0x5a, 0x9d, 0x0a, 0xf5, 0x67, 0x59, 0x91, 0xb0, + 0x91, 0xf0, 0x22, 0x21, 0x59, 0x0a, 0x4d, 0x0b, 0xea, 0x88, 0x86, 0x52, 0x2c, 0xd9, 0x4d, 0x04, 0xc4, 0x56, 0x69, + 0x60, 0xd4, 0x40, 0x2a, 0xd9, 0x16, 0x70, 0x87, 0x5a, 0xa1, 0xae, 0xb9, 0x8c, 0xa9, 0xcd, 0x40, 0x69, 0xec, 0x0e, + 0x55, 0x8f, 0x81, 0x66, 0x06, 0xcc, 0xd2, 0x5b, 0x59, 0x60, 0x73, 0x08, 0x5d, 0x28, 0x7c, 0x91, 0xbf, 0xca, 0x6f, + 0x28, 0x3f, 0x09, 0x01, 0xf8, 0x40, 0x35, 0x2f, 0x95, 0x20, 0x90, 0xfc, 0x5e, 0xf4, 0x0d, 0xbd, 0x5c, 0xc8, 0x89, + 0xbf, 0xe3, 0xf9, 0x84, 0x15, 0x14, 0xd4, 0x35, 0x85, 0xff, 0x0c, 0xf6, 0x99, 0xdc, 0x90, 0x20, 0x6c, 0x68, 0x45, + 0x5f, 0xc7, 0xaf, 0x9a, 0xf4, 0x75, 0xb1, 0xfd, 0x62, 0x6c, 0x18, 0x60, 0x73, 0x1b, 0x23, 0xec, 0x69, 0xa3, 0xc2, + 0x92, 0x73, 0x7e, 0x82, 0xb4, 0x88, 0x5f, 0x2c, 0x84, 0x65, 0xbb, 0x35, 0x14, 0x46, 0xaa, 0xb6, 0x0d, 0x2a, 0xc3, + 0x38, 0x06, 0xd5, 0x8e, 0xe7, 0x69, 0x6a, 0x89, 0x2a, 0xcc, 0xfa, 0x95, 0x70, 0xba, 0xd8, 0x7e, 0x71, 0x7a, 0x9f, + 0x7c, 0x82, 0xf7, 0xb6, 0x88, 0x32, 0x80, 0x66, 0x31, 0xe5, 0x60, 0x4b, 0x5a, 0xab, 0xa5, 0xa5, 0xec, 0x49, 0x9e, + 0x65, 0x34, 0x12, 0x34, 0x06, 0x53, 0x85, 0x11, 0xe1, 0x27, 0x79, 0x21, 0xaa, 0xc2, 0x1a, 0x7a, 0x66, 0x41, 0xcf, + 0xfc, 0x28, 0x4c, 0x53, 0x4f, 0x99, 0x25, 0x93, 0xfc, 0x9a, 0xae, 0x81, 0xba, 0xdf, 0x00, 0xb9, 0xea, 0x86, 0x5a, + 0xdd, 0x50, 0xbf, 0x98, 0xa6, 0x2c, 0xa2, 0x95, 0xe8, 0x3a, 0xf5, 0x59, 0x16, 0xd3, 0x5b, 0xe0, 0x23, 0x68, 0x30, + 0x18, 0x74, 0x70, 0x17, 0x95, 0x0a, 0xe1, 0xf3, 0x15, 0xc4, 0xde, 0x23, 0x34, 0x81, 0xc8, 0xc8, 0x60, 0xbe, 0x96, + 0xad, 0x21, 0x4b, 0x52, 0x32, 0x63, 0x5e, 0x29, 0xee, 0x8c, 0x70, 0x4c, 0x53, 0x2a, 0xa8, 0xe1, 0xe6, 0xa0, 0x44, + 0xab, 0xad, 0xfb, 0xbe, 0xc2, 0x5f, 0x45, 0x4e, 0x66, 0x97, 0x99, 0x35, 0x2f, 0x2a, 0x73, 0xbd, 0x5e, 0x9e, 0x1a, + 0xdb, 0x43, 0xa1, 0x96, 0x27, 0x14, 0x22, 0x8c, 0x12, 0x65, 0xa7, 0x7b, 0x2b, 0x53, 0xaa, 0xfb, 0xd0, 0x9c, 0xbd, + 0xda, 0x44, 0xcf, 0x0c, 0x98, 0xeb, 0x50, 0x70, 0xaa, 0x99, 0x02, 0x05, 0xd3, 0x4f, 0x2d, 0xdb, 0x49, 0x98, 0xa6, + 0x57, 0x61, 0xf4, 0xa9, 0x49, 0xfd, 0x35, 0x19, 0x90, 0x65, 0x6e, 0x6c, 0xbd, 0xb2, 0x58, 0x96, 0x3d, 0x6f, 0xc3, + 0xa5, 0x1b, 0x1b, 0xc5, 0xdb, 0xea, 0xd4, 0x64, 0xdf, 0x5c, 0xe8, 0x8d, 0xd4, 0x2e, 0x21, 0x62, 0x7a, 0x66, 0x1e, + 0x70, 0x81, 0xcf, 0x52, 0x9c, 0xe1, 0x07, 0x9a, 0xee, 0xc0, 0xe0, 0x28, 0x97, 0x00, 0x11, 0x68, 0x5e, 0xc6, 0xac, + 0xd8, 0x8c, 0x81, 0xdf, 0x04, 0xca, 0xe7, 0xd6, 0x08, 0x0f, 0x05, 0xb4, 0xe2, 0x71, 0x5a, 0x6b, 0xae, 0x20, 0xd3, + 0xfa, 0x84, 0x61, 0x34, 0xdf, 0x82, 0xee, 0x22, 0xe9, 0xfd, 0xad, 0x7a, 0x05, 0x5a, 0x19, 0x40, 0xc1, 0xfb, 0xb6, + 0x3a, 0xd1, 0xa0, 0x00, 0xcd, 0x53, 0x99, 0x14, 0xb9, 0x79, 0xc3, 0x82, 0xd4, 0x1a, 0xbb, 0x32, 0xc2, 0x35, 0xcb, + 0x2d, 0x88, 0xe7, 0x79, 0x1c, 0x8c, 0x38, 0xa3, 0xdb, 0xd7, 0x93, 0xe0, 0x2b, 0x93, 0xe0, 0xbe, 0x65, 0x68, 0xa1, + 0x9a, 0x96, 0xad, 0xe6, 0x81, 0x10, 0xc8, 0xae, 0x05, 0xfa, 0xaa, 0x0f, 0x0c, 0x1a, 0x55, 0xfc, 0x36, 0x25, 0x02, + 0x17, 0xda, 0xca, 0xd1, 0xa4, 0x06, 0x1c, 0xa3, 0x6e, 0x92, 0x23, 0xb5, 0x37, 0x1a, 0x26, 0x6f, 0x8e, 0x2d, 0x11, + 0x9f, 0x6a, 0xb3, 0x46, 0x23, 0x89, 0x22, 0xbd, 0x38, 0x0d, 0xad, 0xd8, 0x42, 0x0b, 0xce, 0x09, 0x57, 0x9a, 0xb0, + 0x52, 0x7c, 0x96, 0x91, 0x53, 0xf5, 0xbb, 0x45, 0x48, 0x5e, 0xe3, 0x86, 0xfb, 0x6b, 0x74, 0xab, 0x1c, 0xe1, 0xc8, + 0x28, 0xa5, 0x45, 0x3d, 0x71, 0x42, 0x5c, 0xe3, 0x93, 0x70, 0x87, 0xf3, 0x86, 0x5d, 0x18, 0x58, 0xd5, 0xca, 0x00, + 0x78, 0x6a, 0xb1, 0x0e, 0xdf, 0xeb, 0x88, 0xa6, 0xd1, 0x8f, 0x85, 0xf1, 0xa2, 0x81, 0x71, 0x0b, 0xb5, 0xb9, 0xe2, + 0x5d, 0xf9, 0x39, 0x89, 0x9a, 0x8d, 0x3d, 0x8a, 0x0b, 0xb5, 0x10, 0x2b, 0x58, 0x5c, 0x56, 0x3e, 0x25, 0x11, 0x82, + 0x19, 0xcb, 0x41, 0xbd, 0xb3, 0x25, 0x84, 0x07, 0xc0, 0xb3, 0xc5, 0x62, 0x85, 0xec, 0xd6, 0xea, 0xa0, 0xc8, 0xaf, + 0x2d, 0xc3, 0xc5, 0xe2, 0x85, 0x40, 0x9e, 0xd6, 0x7e, 0x31, 0x45, 0x43, 0xc3, 0x73, 0x8f, 0x5f, 0x41, 0x2d, 0xa9, + 0x8c, 0xd6, 0x25, 0x95, 0xd9, 0xd0, 0xa4, 0xda, 0xe6, 0x42, 0x09, 0x8b, 0x71, 0x9f, 0xac, 0xf0, 0x2f, 0x59, 0xa8, + 0x05, 0x75, 0x3d, 0xe5, 0x13, 0xdd, 0x35, 0x43, 0x08, 0x05, 0x5c, 0x5a, 0x32, 0x5b, 0xeb, 0x8c, 0xcb, 0x9d, 0x1d, + 0x6e, 0x75, 0x74, 0x51, 0x31, 0x8a, 0x9f, 0x3c, 0x10, 0xca, 0xc5, 0x5d, 0x26, 0xb5, 0x97, 0x9f, 0x8c, 0x18, 0x5a, + 0x31, 0x4d, 0x3b, 0x7d, 0xb0, 0xc9, 0xc3, 0x9b, 0x90, 0x09, 0xa7, 0xea, 0x45, 0xd9, 0xe4, 0x1e, 0x45, 0x73, 0xad, + 0x6c, 0xf8, 0x9c, 0x82, 0xfa, 0x08, 0x5c, 0xc1, 0x28, 0xd1, 0x8a, 0xf0, 0xa3, 0x84, 0x82, 0x3f, 0xd8, 0xe8, 0x11, + 0x95, 0x6d, 0xb8, 0xa5, 0xe5, 0x88, 0xee, 0x78, 0x3d, 0xec, 0xe5, 0x72, 0xf3, 0x86, 0x2d, 0x30, 0xa5, 0x7c, 0x94, + 0xf3, 0x89, 0x79, 0x57, 0x2e, 0x3d, 0x6b, 0xde, 0xc8, 0x46, 0xde, 0xda, 0xbe, 0xb5, 0x05, 0xd0, 0x5f, 0x32, 0xbc, + 0x6b, 0x93, 0xbd, 0x21, 0x4c, 0x2b, 0xf9, 0xab, 0xdc, 0x82, 0x86, 0x32, 0xb9, 0x6d, 0xe2, 0x6b, 0x9f, 0x6a, 0x5f, + 0xb9, 0x4d, 0xb6, 0xba, 0xfd, 0xca, 0xee, 0x33, 0xd4, 0xd0, 0x57, 0xee, 0x0d, 0x2d, 0x54, 0xf3, 0x59, 0x1a, 0x6b, + 0x60, 0x19, 0xc2, 0x54, 0xd3, 0xd1, 0x0d, 0x4b, 0xd3, 0xba, 0xf4, 0x4b, 0x38, 0x3b, 0xd7, 0x9c, 0x3d, 0x37, 0x9c, + 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd5, 0x5d, 0xdd, 0x3c, 0x5f, 0xd9, 0x9e, 0xb9, 0xe2, 0xe9, 0x5c, 0xda, 0xd2, 0x30, + 0xde, 0xcc, 0x40, 0x80, 0x2a, 0xdd, 0xeb, 0x93, 0xa7, 0x5d, 0x31, 0x60, 0x04, 0x2a, 0x4f, 0x26, 0xb5, 0xdd, 0x14, + 0x9f, 0x3c, 0x84, 0x79, 0x49, 0x2b, 0xca, 0x3e, 0x7e, 0x01, 0xbe, 0x3a, 0x6b, 0x3a, 0x20, 0xc6, 0x64, 0xf1, 0x17, + 0xa9, 0x51, 0x66, 0x76, 0x4c, 0xcf, 0x8e, 0x9b, 0xd9, 0x01, 0xaf, 0xaf, 0x67, 0x17, 0xdf, 0xcf, 0xed, 0xe5, 0xf4, + 0x58, 0x35, 0xbd, 0x7a, 0xbd, 0x17, 0x0b, 0x6f, 0xa9, 0x04, 0xdc, 0xf8, 0xda, 0x48, 0xe1, 0x55, 0xef, 0xc0, 0x03, + 0x6c, 0xcc, 0x40, 0x41, 0xa9, 0x26, 0x5d, 0x09, 0xb9, 0x57, 0x9f, 0x73, 0xf2, 0x48, 0x6f, 0xbd, 0x6a, 0x7f, 0x92, + 0x4f, 0xa6, 0xa0, 0x8f, 0x2d, 0x91, 0xf4, 0x98, 0xea, 0x01, 0xeb, 0xf7, 0xe5, 0x9a, 0xb2, 0x46, 0x1b, 0xb9, 0x1f, + 0x1b, 0xd4, 0x54, 0xd9, 0xcc, 0x5b, 0x9d, 0x72, 0x56, 0x15, 0x55, 0x8c, 0x63, 0x9d, 0x63, 0xe5, 0x64, 0xd9, 0x2d, + 0x63, 0x5e, 0xbc, 0xf5, 0x98, 0xe2, 0xc3, 0x0c, 0x78, 0x9d, 0xc5, 0x7e, 0x0c, 0xb9, 0xdb, 0xeb, 0x5f, 0xd6, 0xc8, + 0x99, 0x97, 0x4b, 0xe8, 0x9b, 0x97, 0xe5, 0x0b, 0x6d, 0x67, 0xe3, 0x17, 0x9b, 0x0d, 0xe2, 0xfa, 0x9d, 0xb6, 0x17, + 0xcf, 0xce, 0xf1, 0x8b, 0x55, 0xed, 0x91, 0xcc, 0x27, 0x79, 0x4c, 0x03, 0x37, 0x9f, 0xd2, 0xcc, 0x2d, 0xc1, 0xbb, + 0xaa, 0x17, 0x7f, 0x26, 0xbc, 0xf9, 0xfb, 0xa6, 0x9b, 0x35, 0x78, 0x51, 0x82, 0x0b, 0xec, 0x87, 0x55, 0x07, 0xec, + 0x77, 0x94, 0x17, 0x52, 0x17, 0xad, 0xd4, 0xda, 0x1f, 0x6a, 0xc1, 0xf4, 0x43, 0xb0, 0xb1, 0x7e, 0x6d, 0x85, 0xb8, + 0x5d, 0xff, 0xb1, 0xbf, 0xe7, 0x22, 0xe9, 0x1e, 0xfe, 0x56, 0xef, 0xf8, 0x9f, 0x8d, 0x7b, 0xf8, 0x94, 0xfc, 0xdc, + 0xf4, 0x0e, 0x4f, 0x05, 0x39, 0x1d, 0x9e, 0x1a, 0xa3, 0x39, 0x4f, 0x59, 0x74, 0xe7, 0xb9, 0x29, 0x13, 0x2d, 0x08, + 0xc1, 0xb9, 0x78, 0xae, 0x5e, 0x80, 0x5f, 0x51, 0xba, 0xb5, 0x4b, 0x63, 0xee, 0x61, 0x26, 0x88, 0xbb, 0x9d, 0x32, + 0xb1, 0xed, 0xe2, 0x3b, 0x72, 0x09, 0x3f, 0xb6, 0xe7, 0xde, 0xeb, 0x50, 0x24, 0x3e, 0x0f, 0xb3, 0x38, 0x9f, 0x78, + 0x68, 0xd7, 0x75, 0x91, 0x5f, 0x48, 0x93, 0xe3, 0x29, 0x2a, 0xb7, 0x2f, 0xf1, 0xa9, 0x20, 0xee, 0xd0, 0xdd, 0xbd, + 0xc3, 0xaf, 0x05, 0xb9, 0x3c, 0xda, 0x9e, 0x9f, 0x8a, 0x72, 0x70, 0x89, 0x8f, 0x2b, 0xcf, 0x3d, 0x7e, 0x43, 0x3c, + 0x44, 0x06, 0xc7, 0x1a, 0x9a, 0x93, 0x7c, 0xa2, 0x3c, 0xf8, 0x2e, 0xc2, 0xef, 0x65, 0x7c, 0xa5, 0x66, 0x37, 0x3a, + 0xc4, 0xb2, 0x45, 0xdc, 0x5c, 0x7a, 0x09, 0xdc, 0x9d, 0x1d, 0xab, 0xac, 0x52, 0x16, 0xf0, 0x89, 0x20, 0x0d, 0x9b, + 0x1c, 0xbf, 0x92, 0x91, 0x9a, 0x13, 0xe1, 0x65, 0xc8, 0x74, 0xe3, 0x19, 0x77, 0xb4, 0xde, 0x9b, 0xd9, 0x99, 0x72, + 0x32, 0xf8, 0x4c, 0x50, 0x1e, 0x8a, 0x9c, 0x9f, 0x23, 0x5b, 0x01, 0xc1, 0x7f, 0x26, 0x97, 0x67, 0xce, 0x7f, 0xf8, + 0xdd, 0x8f, 0xa3, 0x1f, 0xf9, 0xf9, 0x25, 0xfe, 0x48, 0xda, 0x47, 0xde, 0x30, 0xf0, 0xb6, 0x5a, 0xad, 0xc5, 0x8f, + 0xed, 0xb3, 0xbf, 0x85, 0xad, 0x5f, 0x8e, 0x5b, 0x3f, 0x9c, 0xa3, 0x85, 0xf7, 0x63, 0x7b, 0x78, 0xa6, 0x9f, 0xce, + 0xfe, 0x36, 0xf8, 0xb1, 0x38, 0xff, 0xbd, 0x2a, 0xdc, 0x46, 0xa8, 0x3d, 0xc6, 0x63, 0x41, 0xda, 0xad, 0xd6, 0xa0, + 0x3d, 0xc6, 0x13, 0x41, 0xda, 0xf0, 0xef, 0x0d, 0x79, 0x4f, 0xc7, 0x2f, 0x6e, 0xa7, 0xde, 0xe5, 0x60, 0xb1, 0x3d, + 0xff, 0x73, 0x09, 0xbd, 0x9e, 0xfd, 0xed, 0xc7, 0x1f, 0x0b, 0xf7, 0xd1, 0x80, 0xb4, 0xcf, 0x77, 0x91, 0x07, 0xa5, + 0xbf, 0x27, 0xf2, 0xaf, 0x37, 0x0c, 0xce, 0xfe, 0xa6, 0xa1, 0x70, 0x1f, 0xfd, 0x78, 0x79, 0x34, 0x20, 0xe7, 0x0b, + 0xcf, 0x5d, 0x3c, 0x42, 0x0b, 0x84, 0x16, 0xdb, 0xe8, 0x12, 0xbb, 0x63, 0x17, 0xe1, 0x91, 0x20, 0xed, 0x47, 0xed, + 0x31, 0xbe, 0x10, 0xa4, 0xed, 0xb6, 0xc7, 0xf8, 0xad, 0x20, 0xed, 0xbf, 0x79, 0xc3, 0x40, 0xb9, 0xd9, 0x16, 0xd2, + 0xc3, 0xb1, 0x80, 0x20, 0x47, 0xc8, 0x69, 0xb8, 0x10, 0x4c, 0xa4, 0x14, 0x6d, 0xb7, 0x19, 0xfe, 0x24, 0xd1, 0xe4, + 0x09, 0xf0, 0xc3, 0x80, 0x79, 0xe7, 0xcd, 0x2f, 0x60, 0xb1, 0x81, 0x66, 0xb6, 0x83, 0x0c, 0x2b, 0x57, 0x40, 0x11, + 0x08, 0x7c, 0x1d, 0xa6, 0x33, 0x5a, 0x04, 0xb4, 0x44, 0x38, 0x25, 0x9f, 0x84, 0xd7, 0x45, 0xf8, 0x1b, 0x01, 0x3f, + 0x7a, 0x08, 0x9f, 0xe8, 0x40, 0x26, 0xec, 0x64, 0x45, 0x54, 0x59, 0xae, 0x54, 0x16, 0x17, 0xe1, 0xf1, 0x9a, 0x97, + 0x22, 0x01, 0x07, 0x03, 0xc2, 0xd7, 0x8d, 0xb0, 0x27, 0xbe, 0x25, 0x86, 0x24, 0x3e, 0x70, 0x4a, 0xbf, 0x0f, 0xd3, + 0x4f, 0x94, 0x7b, 0xc7, 0xb8, 0xdb, 0x7b, 0x8a, 0xa5, 0x1f, 0x7a, 0xab, 0x8b, 0xfa, 0x55, 0xcc, 0xea, 0x9d, 0x50, + 0xa1, 0x02, 0x90, 0xb2, 0x4d, 0x77, 0x0c, 0xac, 0xf8, 0x56, 0xb6, 0xe2, 0xb3, 0xe2, 0xe1, 0x8d, 0x8b, 0x9a, 0xf1, + 0x51, 0x96, 0x5d, 0x87, 0x29, 0x8b, 0x1d, 0x41, 0x27, 0xd3, 0x34, 0x14, 0xd4, 0xd1, 0xf3, 0x75, 0x42, 0xe8, 0xc8, + 0xad, 0x74, 0x86, 0xa9, 0x65, 0x73, 0x4e, 0x4d, 0xe0, 0x09, 0xf6, 0x8a, 0x07, 0x51, 0x2a, 0xad, 0x77, 0x3c, 0xaf, + 0x83, 0x60, 0xcb, 0x71, 0xbe, 0x56, 0x17, 0x7c, 0x61, 0xe7, 0x52, 0x3e, 0x83, 0x1e, 0x0d, 0x52, 0xb4, 0x37, 0x74, + 0x8f, 0x8a, 0xeb, 0xf1, 0xc0, 0x85, 0x18, 0x4d, 0x41, 0x3e, 0x4a, 0xd7, 0x10, 0x54, 0x88, 0x48, 0xa7, 0x1f, 0x1d, + 0xd1, 0x7e, 0xb4, 0xbb, 0x6b, 0xb4, 0xe8, 0x90, 0x64, 0x67, 0x91, 0x6a, 0x9e, 0xe0, 0x18, 0xcf, 0x48, 0xab, 0x8b, + 0xa7, 0xa4, 0x23, 0x9b, 0xf4, 0xa7, 0x47, 0xa1, 0x1e, 0x66, 0x67, 0xc7, 0x2b, 0xfc, 0x34, 0x2c, 0xc4, 0x37, 0x60, + 0xef, 0x93, 0x29, 0x8e, 0x49, 0xe1, 0xd3, 0x5b, 0x1a, 0x79, 0x21, 0xc2, 0xb1, 0xe6, 0x34, 0xa8, 0x8f, 0xa6, 0xc4, + 0xaa, 0x06, 0x66, 0x04, 0xf9, 0x38, 0x8c, 0xcf, 0xba, 0xe7, 0x84, 0x10, 0x77, 0xab, 0xd5, 0x72, 0x87, 0x05, 0x19, + 0x8b, 0x00, 0x4a, 0x2c, 0x65, 0x99, 0x4c, 0xa0, 0xa8, 0x67, 0x15, 0x79, 0x6f, 0x85, 0x2f, 0x68, 0x21, 0x3c, 0x28, + 0x06, 0x0f, 0x00, 0x37, 0x84, 0xed, 0x1e, 0xb5, 0xdd, 0x5d, 0x28, 0x95, 0xc4, 0x89, 0x70, 0x41, 0x6e, 0x50, 0x10, + 0x9f, 0xed, 0x9d, 0xdb, 0x02, 0x40, 0x16, 0xc2, 0xe0, 0x37, 0xc3, 0xf8, 0xac, 0x23, 0x07, 0x1f, 0xb8, 0x43, 0xaf, + 0x20, 0x5c, 0x69, 0x68, 0x43, 0x1e, 0x7c, 0x94, 0x53, 0x45, 0x81, 0x06, 0x4e, 0x8f, 0x3b, 0x23, 0xad, 0x5e, 0xe0, + 0xcd, 0xec, 0x49, 0xb4, 0x60, 0x30, 0x8d, 0x05, 0x9c, 0x10, 0xa8, 0x8f, 0x0b, 0x02, 0x23, 0xd6, 0xcd, 0x6e, 0x02, + 0xfd, 0xfc, 0xc8, 0x7d, 0x34, 0xbc, 0x10, 0xc1, 0x48, 0xa8, 0xe1, 0x2f, 0xc4, 0x62, 0x01, 0xff, 0x8e, 0xc4, 0xb0, + 0x20, 0x37, 0xb2, 0x68, 0xac, 0x8b, 0x26, 0x50, 0xf4, 0x31, 0x00, 0x50, 0x31, 0xaf, 0xb4, 0x2c, 0xb5, 0x26, 0x13, + 0x22, 0x61, 0xdf, 0xd9, 0xc9, 0xce, 0xa2, 0xdd, 0xee, 0x39, 0x38, 0xf9, 0xb9, 0x28, 0xbe, 0x67, 0x22, 0xf1, 0xdc, + 0xf6, 0xc0, 0x45, 0x43, 0xd7, 0x81, 0xa5, 0xed, 0xe7, 0xbb, 0x44, 0x61, 0x38, 0xdc, 0x7d, 0x2d, 0x82, 0xd9, 0x80, + 0x74, 0x86, 0x1e, 0x53, 0x2c, 0x3c, 0x41, 0x38, 0xd4, 0x8c, 0xb3, 0x83, 0x67, 0x68, 0x97, 0x89, 0x5d, 0xf3, 0x3c, + 0x43, 0xbb, 0x77, 0xbb, 0x13, 0x14, 0x84, 0xbb, 0x77, 0xbb, 0xde, 0x8c, 0x10, 0xd2, 0xea, 0x55, 0xcd, 0x8c, 0xf8, + 0x8b, 0x50, 0x30, 0x31, 0xfe, 0xce, 0x33, 0xb9, 0x1d, 0xf2, 0x5d, 0x2f, 0x3b, 0xa3, 0xe7, 0x8b, 0x85, 0x7b, 0x34, + 0x1c, 0xb8, 0x68, 0xd7, 0x33, 0x84, 0xd6, 0x36, 0x94, 0x86, 0x10, 0x66, 0xe7, 0xa5, 0x8e, 0x27, 0x3d, 0x6b, 0xc4, + 0x8e, 0xe6, 0xf5, 0x66, 0xb7, 0x78, 0x00, 0x2d, 0x2b, 0x43, 0x46, 0x29, 0xac, 0x53, 0x98, 0xa6, 0x21, 0xe6, 0x9c, + 0x74, 0x70, 0x41, 0x8c, 0xfb, 0x3a, 0x22, 0xa2, 0x26, 0xf8, 0x90, 0xd4, 0xd5, 0xf1, 0x59, 0x82, 0xe3, 0x73, 0xf2, + 0x5c, 0x19, 0x24, 0x7d, 0xe3, 0x1c, 0xa7, 0x29, 0x79, 0xb6, 0x14, 0xc5, 0x4d, 0x20, 0xc0, 0x72, 0xeb, 0x47, 0x33, + 0xce, 0x69, 0x26, 0xde, 0xe4, 0xb1, 0xd6, 0xd3, 0x68, 0x0a, 0xa6, 0x12, 0x84, 0x67, 0x31, 0x28, 0x69, 0x3d, 0xb3, + 0x33, 0x66, 0x2b, 0xaf, 0xa7, 0x64, 0xa6, 0xf4, 0x27, 0x19, 0xb4, 0xed, 0x4f, 0xb5, 0x65, 0xec, 0x21, 0x3c, 0xd3, + 0xd1, 0x5c, 0xcf, 0xf7, 0xfd, 0xa9, 0x1f, 0xc1, 0x6b, 0x18, 0xa0, 0x40, 0xa5, 0xdc, 0x47, 0x1e, 0x27, 0xb7, 0x7e, + 0x46, 0x6f, 0xe5, 0xa8, 0x1e, 0xaa, 0x25, 0xb3, 0xd9, 0x5e, 0x47, 0x51, 0x5f, 0xb2, 0x1b, 0xee, 0x67, 0x79, 0x4c, + 0x01, 0x3d, 0x10, 0xbf, 0xd7, 0x45, 0x49, 0x58, 0xd8, 0x41, 0xaa, 0x1a, 0xbe, 0x33, 0xdb, 0x7f, 0x3d, 0x05, 0xa7, + 0xaf, 0xb4, 0xf4, 0xaa, 0xca, 0xca, 0x13, 0x8e, 0x10, 0x1b, 0x79, 0x53, 0x1f, 0x82, 0x7b, 0x92, 0x84, 0x18, 0xd8, + 0x72, 0x53, 0x9b, 0xa8, 0xee, 0xaa, 0x3e, 0x27, 0x24, 0x3e, 0x2b, 0x76, 0x77, 0xa5, 0x23, 0x7a, 0xa6, 0x48, 0x62, + 0x8a, 0xf0, 0xa4, 0xda, 0x5b, 0xa6, 0xde, 0x3b, 0xd2, 0x1c, 0xc9, 0x9b, 0x34, 0x1d, 0xba, 0xbb, 0x4c, 0x20, 0xe9, + 0x2b, 0x14, 0xde, 0x1d, 0xc2, 0x23, 0xd2, 0xf6, 0xce, 0xfc, 0xe1, 0x1f, 0xce, 0xd1, 0xd0, 0xf3, 0x7f, 0x8f, 0xda, + 0x8a, 0x71, 0x4c, 0x50, 0x3f, 0x54, 0x43, 0xcc, 0x65, 0x14, 0xb3, 0x8b, 0xa5, 0x2f, 0x31, 0xc8, 0x71, 0x16, 0x4e, + 0x68, 0x30, 0x82, 0x3d, 0x6e, 0xe8, 0xe6, 0x1d, 0x06, 0x3a, 0x0a, 0x46, 0x9a, 0x93, 0xf8, 0xee, 0xf0, 0x67, 0x51, + 0x3d, 0x0d, 0xdd, 0xe1, 0xd7, 0xf5, 0xd3, 0x1f, 0xdc, 0xe1, 0x77, 0x22, 0xf8, 0xae, 0xd4, 0xee, 0xee, 0xc6, 0x10, + 0x8f, 0xcd, 0x10, 0xa5, 0x5a, 0x18, 0x0b, 0x73, 0x33, 0xc4, 0x57, 0x1c, 0x1d, 0x53, 0x54, 0xb2, 0x51, 0xc5, 0x8a, + 0xb8, 0x2f, 0xc2, 0x31, 0xa0, 0xd4, 0x5a, 0x01, 0x6e, 0x47, 0xf7, 0xeb, 0x09, 0x03, 0xa1, 0x18, 0x6a, 0x05, 0x54, + 0x4e, 0x07, 0x1d, 0x34, 0x6f, 0xd4, 0x95, 0x1a, 0x53, 0x33, 0x9a, 0x5e, 0x71, 0xe9, 0x09, 0xe9, 0xf4, 0x27, 0x47, + 0xd3, 0xfe, 0x64, 0x77, 0x17, 0x71, 0x43, 0x58, 0xb3, 0xb3, 0xc9, 0x39, 0x7e, 0x03, 0x5e, 0x3d, 0x9b, 0x92, 0x70, + 0x63, 0x7a, 0x3d, 0x3d, 0xbd, 0xdd, 0xdd, 0xbc, 0x44, 0x7d, 0xab, 0xe9, 0x54, 0x35, 0x2d, 0x4b, 0x85, 0x93, 0x65, + 0x42, 0x3b, 0x44, 0xb2, 0x04, 0x52, 0xa2, 0x08, 0x21, 0xa7, 0x02, 0xad, 0xed, 0x15, 0xfa, 0x84, 0xe6, 0x72, 0xc7, + 0x02, 0xf3, 0x54, 0x32, 0xc2, 0x03, 0x2c, 0x40, 0xd3, 0xca, 0x15, 0x7c, 0x87, 0x67, 0xbb, 0x5d, 0x49, 0xe4, 0xad, + 0x6e, 0xbf, 0xd9, 0xd7, 0x93, 0xba, 0x2f, 0x3c, 0xdb, 0x25, 0x77, 0x15, 0x96, 0xca, 0x7c, 0x77, 0xb7, 0x6c, 0xc6, + 0x3b, 0xcd, 0xbe, 0x6d, 0x44, 0x20, 0x8e, 0x97, 0x53, 0x33, 0x8c, 0x7c, 0xad, 0x25, 0x2a, 0xf3, 0x59, 0x96, 0x51, + 0x0e, 0x32, 0x94, 0x08, 0xcc, 0xca, 0xb2, 0x92, 0xeb, 0x6f, 0x41, 0x88, 0x62, 0x4a, 0x32, 0xe0, 0x3b, 0xd2, 0xec, + 0xc2, 0x39, 0x2e, 0x70, 0x24, 0xb9, 0x06, 0x21, 0xe4, 0xc4, 0x24, 0xb5, 0x08, 0xc9, 0x81, 0x42, 0xc2, 0x2c, 0x89, + 0xc4, 0x09, 0xf5, 0x2f, 0xb6, 0x4f, 0xf2, 0x7b, 0x4d, 0xb2, 0x33, 0x76, 0x1e, 0xc8, 0x6a, 0xa9, 0xe6, 0x5b, 0x09, + 0x79, 0xef, 0x09, 0x54, 0x85, 0x47, 0x7c, 0xc9, 0xfe, 0x9e, 0x33, 0x4e, 0xa5, 0x06, 0xbe, 0x6d, 0xcc, 0xbe, 0xb0, + 0xa9, 0x3e, 0x86, 0xb6, 0xf3, 0x06, 0x10, 0x09, 0xf2, 0xd7, 0xcb, 0xc9, 0x4a, 0xb5, 0x8b, 0xed, 0xe3, 0xb7, 0xeb, + 0x4c, 0xe0, 0xc5, 0x42, 0x1b, 0xbf, 0x21, 0x68, 0x36, 0x38, 0xa9, 0x21, 0x0d, 0xf5, 0x8f, 0xc0, 0x0b, 0xa5, 0x82, + 0x94, 0x78, 0x19, 0x50, 0xd1, 0xc5, 0xf6, 0xf1, 0x07, 0x2f, 0x93, 0xae, 0x25, 0x84, 0xed, 0x69, 0x7b, 0x05, 0xf1, + 0x22, 0x42, 0x91, 0x9a, 0x7b, 0xc5, 0xb8, 0x0a, 0x4b, 0x7c, 0x07, 0x91, 0x7c, 0x09, 0xf6, 0xc3, 0x19, 0x3b, 0x27, + 0xa1, 0xc6, 0x00, 0x09, 0x11, 0x0e, 0x1b, 0x66, 0x19, 0x81, 0x05, 0x90, 0x63, 0x9d, 0xc2, 0x4a, 0xf8, 0x4a, 0xf1, + 0x43, 0x38, 0x94, 0xa3, 0x8a, 0x52, 0x89, 0x8e, 0x9f, 0x56, 0x72, 0xd3, 0x6a, 0x6b, 0xf4, 0x3b, 0xb0, 0x9c, 0xcc, + 0xc3, 0x1b, 0xdd, 0x75, 0x55, 0xf0, 0xdc, 0x24, 0x91, 0x5d, 0x6c, 0x1f, 0xbf, 0xd6, 0x79, 0x64, 0xd3, 0xd0, 0x70, + 0xfb, 0x15, 0x0b, 0xf3, 0xf8, 0xb5, 0x5f, 0xbf, 0x95, 0x95, 0x2f, 0xb6, 0x8f, 0x3f, 0xae, 0xab, 0x06, 0xe5, 0xe5, + 0xac, 0x36, 0xf1, 0x25, 0x7c, 0x73, 0x9a, 0x06, 0x73, 0x2d, 0x1a, 0x02, 0x56, 0x62, 0x29, 0x8e, 0x02, 0x5e, 0x56, + 0x9e, 0x91, 0xe7, 0x38, 0x27, 0x32, 0x0e, 0xd4, 0x5c, 0x35, 0xad, 0xe4, 0xb1, 0x3c, 0x3b, 0x8d, 0xf2, 0x29, 0xdd, + 0x10, 0x1c, 0x3a, 0x46, 0x3e, 0x9b, 0x40, 0x02, 0x8d, 0x04, 0x9d, 0xe1, 0xad, 0x0e, 0xea, 0x37, 0x85, 0x57, 0x2e, + 0x89, 0xb4, 0x68, 0x48, 0x16, 0x1c, 0x91, 0x0e, 0x0e, 0x49, 0x07, 0x27, 0x84, 0x9f, 0x75, 0x94, 0x78, 0xe8, 0xd7, + 0xa1, 0x5c, 0x25, 0x64, 0x22, 0x42, 0x48, 0xa2, 0x76, 0xab, 0x12, 0xbf, 0x71, 0x3f, 0x91, 0xae, 0x47, 0x29, 0xd1, + 0x63, 0x65, 0xb4, 0x7a, 0x05, 0x2e, 0x64, 0xc7, 0xa7, 0xec, 0x2a, 0x85, 0xec, 0x12, 0x98, 0x15, 0x16, 0x28, 0xa8, + 0xaa, 0x76, 0x75, 0xd5, 0xc4, 0x97, 0xeb, 0x54, 0xe0, 0xc4, 0x07, 0xc6, 0x8d, 0x13, 0x9d, 0x8c, 0x53, 0xac, 0x36, + 0x79, 0xbc, 0xb3, 0xe3, 0xa9, 0x46, 0xdf, 0x0b, 0xaf, 0x7a, 0x5f, 0x87, 0xee, 0xbe, 0x53, 0xbc, 0x22, 0x46, 0x12, + 0xfe, 0xdd, 0xdd, 0xf0, 0xbc, 0x8c, 0xb6, 0x08, 0xf1, 0x92, 0x26, 0x06, 0x0d, 0xf0, 0x52, 0xd3, 0x6b, 0x4e, 0x7f, + 0x77, 0xb7, 0x0a, 0xd3, 0x36, 0xb1, 0x75, 0x8c, 0xf3, 0xf2, 0xda, 0xab, 0xf2, 0x7f, 0x3a, 0x2b, 0x59, 0x53, 0x06, + 0x04, 0xc4, 0x6c, 0x9a, 0x65, 0x66, 0x32, 0xd6, 0x96, 0x60, 0x50, 0xef, 0x1b, 0x9d, 0xb8, 0x80, 0x65, 0x8e, 0x95, + 0xae, 0x64, 0xd8, 0x59, 0x0f, 0x05, 0xa6, 0x12, 0x84, 0xa5, 0xa0, 0xd2, 0x6e, 0xa9, 0xc9, 0xfb, 0xf5, 0x6a, 0xe6, + 0x25, 0xe6, 0x48, 0xfb, 0xb8, 0x24, 0x14, 0x12, 0x59, 0xbd, 0x0a, 0x29, 0x2f, 0xc9, 0x78, 0x33, 0xc9, 0x1f, 0x5b, + 0x24, 0xff, 0x8c, 0x50, 0x8b, 0xfc, 0x95, 0x87, 0xc3, 0xcf, 0xb5, 0x6b, 0x81, 0x9b, 0x57, 0x27, 0x53, 0x02, 0x3e, + 0xb4, 0x26, 0x46, 0xb9, 0x1d, 0x57, 0xdc, 0xc0, 0x50, 0xec, 0x1d, 0x22, 0xbd, 0x90, 0xd8, 0x04, 0x81, 0xbd, 0x3a, + 0xaa, 0x06, 0x43, 0xaf, 0x73, 0xe9, 0xd9, 0x1c, 0xf0, 0xf8, 0xe3, 0xfd, 0x01, 0xd1, 0x93, 0xe9, 0xea, 0xce, 0xb5, + 0x32, 0x40, 0x61, 0xd6, 0xd6, 0xc6, 0x6d, 0xe6, 0x83, 0xc2, 0xf8, 0x55, 0x20, 0xbb, 0xc9, 0x7c, 0x96, 0x36, 0xa1, + 0x91, 0x7f, 0x00, 0x6d, 0xb7, 0x2b, 0x6b, 0x50, 0xab, 0x5b, 0xe0, 0x47, 0x2a, 0x0f, 0x35, 0xe4, 0x1b, 0xd8, 0xc7, + 0xb1, 0xac, 0x40, 0xb3, 0x78, 0xfd, 0xeb, 0x67, 0xa5, 0x26, 0x13, 0x05, 0x1a, 0x9a, 0x03, 0xff, 0x53, 0x24, 0x0f, + 0x74, 0x23, 0xe5, 0x02, 0x20, 0x68, 0x2c, 0xf1, 0x54, 0x23, 0xcc, 0x75, 0x6b, 0xe7, 0xfb, 0xcb, 0x2d, 0x42, 0xc6, + 0xb5, 0xf3, 0xf1, 0x7d, 0x9d, 0x7d, 0x05, 0x64, 0x81, 0x02, 0x30, 0x1e, 0xab, 0x02, 0x15, 0xbf, 0x3c, 0x31, 0xd5, + 0xa5, 0x01, 0xe9, 0xd7, 0xfa, 0xb6, 0x15, 0xdb, 0x94, 0x5e, 0x39, 0xf5, 0xde, 0xa0, 0x61, 0xe9, 0xed, 0x36, 0xbc, + 0x7d, 0x25, 0x24, 0x8c, 0xf0, 0xfc, 0x41, 0xd6, 0x36, 0xfd, 0x96, 0x9f, 0x96, 0x53, 0x58, 0x96, 0x16, 0xc5, 0x67, + 0x59, 0x41, 0xb9, 0x78, 0x46, 0x47, 0x39, 0x87, 0x90, 0x45, 0x85, 0x13, 0x54, 0x6e, 0x5b, 0x6e, 0x3b, 0x39, 0x3f, + 0x2b, 0x4e, 0xb0, 0x34, 0x41, 0xf9, 0xeb, 0x93, 0x8c, 0x5a, 0x5f, 0x2c, 0xb7, 0x1a, 0xef, 0xec, 0xbc, 0xaf, 0xd1, + 0xa4, 0xa1, 0x94, 0x50, 0x58, 0x4c, 0x4b, 0xa9, 0x34, 0x3a, 0x94, 0xbb, 0xed, 0x55, 0x2e, 0x00, 0xc3, 0x30, 0x6c, + 0xde, 0xf3, 0x92, 0x88, 0x72, 0xbc, 0xcc, 0xe2, 0xb5, 0x6b, 0x82, 0xd9, 0x66, 0x0b, 0x70, 0x78, 0x30, 0xb4, 0x95, + 0xaf, 0x88, 0xd7, 0x29, 0xb1, 0x15, 0x0c, 0x27, 0x80, 0x2c, 0x0f, 0xc2, 0xbd, 0x76, 0xd8, 0x83, 0xaf, 0x33, 0x4a, + 0xde, 0x81, 0x5e, 0x99, 0x60, 0xee, 0x27, 0x90, 0x04, 0xdb, 0xd8, 0xb2, 0x08, 0x61, 0x2e, 0x0d, 0x1a, 0x2b, 0x97, + 0xe0, 0xf8, 0xe5, 0x3a, 0x8f, 0xb2, 0x21, 0x6a, 0x2a, 0xa5, 0x0e, 0xd4, 0xc8, 0x51, 0xd5, 0xc0, 0xbf, 0xf6, 0x98, + 0x56, 0xdc, 0x4c, 0xdc, 0x0c, 0x18, 0xf0, 0x4f, 0xc2, 0x53, 0xb1, 0x28, 0x90, 0x19, 0x85, 0x3f, 0xf3, 0x1a, 0x43, + 0xf7, 0x0b, 0xd9, 0x0c, 0x6b, 0xc4, 0x45, 0x36, 0x9a, 0x0a, 0x19, 0xd7, 0x3b, 0xa9, 0x79, 0xe9, 0xb5, 0xca, 0xa3, + 0x16, 0x86, 0x0b, 0xd6, 0x99, 0x24, 0xd6, 0xf4, 0xaf, 0x55, 0x6a, 0x74, 0x55, 0x09, 0xd4, 0x30, 0x7a, 0xe3, 0x3c, + 0x93, 0x6b, 0x40, 0x4b, 0xa0, 0xaf, 0xf9, 0x89, 0xb0, 0x56, 0xd4, 0xf8, 0xb0, 0xe5, 0x98, 0x96, 0xd4, 0x7f, 0x0f, + 0xb9, 0x2e, 0xcb, 0x7b, 0xfe, 0xa5, 0x94, 0x85, 0x0c, 0xf3, 0x06, 0x63, 0xcf, 0x25, 0x63, 0x47, 0xa0, 0xa7, 0x99, + 0xf4, 0xef, 0xa1, 0x4e, 0x79, 0xd1, 0xb9, 0x8b, 0x9e, 0x26, 0xb1, 0x37, 0x55, 0xb8, 0xdc, 0xfa, 0xbd, 0xb4, 0x1a, + 0x01, 0x23, 0x90, 0x06, 0x84, 0x35, 0x67, 0xcf, 0x11, 0xe6, 0xbb, 0xbb, 0x7d, 0x7e, 0x44, 0x6b, 0x17, 0x49, 0x0d, + 0x23, 0x83, 0x88, 0x2e, 0x10, 0x7c, 0x43, 0x86, 0x72, 0x84, 0xab, 0x3c, 0x74, 0x0e, 0xae, 0xf6, 0xe3, 0xf7, 0x9e, + 0xcd, 0xd5, 0xec, 0xba, 0x55, 0xd0, 0x14, 0xe6, 0xe3, 0xd5, 0xf1, 0x96, 0x77, 0xf7, 0x67, 0x78, 0x00, 0xdc, 0x5b, + 0x5d, 0x0c, 0xd9, 0x68, 0xa8, 0x2f, 0x14, 0x4b, 0xa8, 0x76, 0x5f, 0x1f, 0xd5, 0x89, 0x89, 0xf6, 0x60, 0x7d, 0x51, + 0x9b, 0xb2, 0x82, 0xf0, 0xb2, 0x2c, 0x68, 0x1d, 0xdf, 0x5f, 0xca, 0xc0, 0x94, 0xc2, 0x65, 0xd5, 0xd9, 0x7e, 0x32, + 0x25, 0x02, 0x5b, 0x84, 0xfa, 0x6e, 0x53, 0xe8, 0xa3, 0x06, 0x13, 0xf6, 0xb5, 0x16, 0x8a, 0xdf, 0xad, 0x13, 0x8a, + 0x38, 0xd7, 0x5b, 0x5e, 0x0a, 0xc4, 0xee, 0x03, 0x04, 0xa2, 0x76, 0xb2, 0x1b, 0x99, 0x08, 0xea, 0x48, 0x43, 0x26, + 0xf2, 0xa6, 0x4c, 0xcc, 0x31, 0xd3, 0xab, 0x31, 0xe8, 0x2d, 0x16, 0xec, 0xac, 0x03, 0x4e, 0x24, 0xd7, 0x85, 0x9f, + 0x5d, 0xf5, 0xd3, 0xe2, 0xc4, 0xca, 0x09, 0xec, 0xb1, 0xca, 0x64, 0x41, 0x3e, 0xa4, 0x39, 0x7b, 0x32, 0x2b, 0x4b, + 0xd2, 0xb4, 0xa6, 0x20, 0x4d, 0xe0, 0x84, 0x55, 0x51, 0x26, 0x80, 0x58, 0xca, 0x0a, 0x6d, 0x40, 0x7a, 0x6b, 0xd3, + 0xff, 0x8c, 0x79, 0xf9, 0x79, 0x4d, 0xb4, 0x21, 0x57, 0x94, 0xfa, 0xd0, 0x48, 0x38, 0xd0, 0x10, 0x68, 0xfd, 0x70, + 0x4b, 0x9a, 0xa0, 0xb5, 0x28, 0x47, 0xb6, 0x1c, 0xc2, 0x1d, 0x70, 0xa1, 0x6d, 0xbd, 0x57, 0x01, 0xde, 0x35, 0xd2, + 0x04, 0x17, 0x16, 0x5d, 0xbf, 0x24, 0xa2, 0xc1, 0x4a, 0x22, 0xa2, 0x2d, 0x25, 0x9c, 0x48, 0x32, 0x15, 0x24, 0x3f, + 0xeb, 0x9c, 0x83, 0x02, 0xda, 0x0f, 0x8f, 0xf2, 0xda, 0x04, 0x0e, 0x77, 0x77, 0x51, 0x62, 0x46, 0x8d, 0xce, 0xd8, + 0x6e, 0x78, 0x8e, 0x29, 0x0e, 0x95, 0x61, 0x72, 0xb2, 0xb3, 0xe3, 0x25, 0xf5, 0xb8, 0x67, 0xe1, 0x39, 0xc2, 0xc5, + 0x62, 0xe1, 0x49, 0xb0, 0x12, 0xb4, 0x58, 0x24, 0x36, 0x58, 0xf2, 0x35, 0x34, 0x1b, 0x0f, 0x05, 0x19, 0x4b, 0x01, + 0x38, 0x06, 0x08, 0x77, 0x89, 0x97, 0x68, 0xe7, 0x5e, 0x02, 0xce, 0xa8, 0xdd, 0xfc, 0x2c, 0xdc, 0xed, 0x9e, 0x5b, + 0x8c, 0xeb, 0x2c, 0x3c, 0x27, 0x49, 0x59, 0xec, 0xec, 0x6c, 0x71, 0x2d, 0x22, 0x7f, 0x02, 0x51, 0xf6, 0x93, 0x94, + 0x2c, 0xaa, 0x43, 0x7b, 0x35, 0x96, 0x9d, 0x01, 0x15, 0x45, 0xe9, 0x65, 0x35, 0xf5, 0x1a, 0x59, 0x10, 0x55, 0x25, + 0xac, 0x63, 0xc1, 0x43, 0xb0, 0xec, 0x2b, 0x32, 0xff, 0x59, 0x54, 0x69, 0xd6, 0xdf, 0xad, 0x4d, 0xae, 0xf6, 0x7d, + 0x3f, 0xe4, 0x63, 0x19, 0xc9, 0x30, 0xe9, 0x14, 0x92, 0xf8, 0xf7, 0x34, 0x98, 0xd6, 0xc0, 0x67, 0xd5, 0x58, 0xe7, + 0x44, 0x81, 0x6f, 0x54, 0x1b, 0x73, 0xa2, 0xe4, 0x97, 0xb5, 0x5e, 0x06, 0x05, 0xc9, 0xd7, 0xbf, 0x16, 0x92, 0x7d, + 0x0d, 0x89, 0x22, 0x8f, 0x25, 0x9c, 0x6d, 0xc0, 0xc5, 0x2f, 0x62, 0x09, 0x67, 0x9b, 0x71, 0x5b, 0x31, 0x84, 0x4d, + 0xf0, 0x59, 0xbc, 0x41, 0x01, 0x5a, 0x17, 0x58, 0x50, 0x1e, 0x2c, 0xeb, 0x5e, 0x8a, 0x95, 0x82, 0x30, 0x15, 0xc4, + 0x63, 0xcd, 0x0d, 0x50, 0x6b, 0xa3, 0x96, 0xe1, 0xcb, 0x82, 0x31, 0xb2, 0x5c, 0x02, 0xcd, 0xd4, 0x15, 0x20, 0x27, + 0xed, 0x6b, 0x87, 0x54, 0x84, 0x2d, 0xa5, 0xc4, 0xf9, 0x51, 0x38, 0x15, 0x33, 0x0e, 0xaa, 0x14, 0x37, 0xbf, 0xa1, + 0x18, 0xce, 0x82, 0xc8, 0x32, 0xf8, 0x01, 0x05, 0xd3, 0xb0, 0x28, 0xd8, 0xb5, 0x2a, 0xd3, 0xbf, 0x71, 0x41, 0x0c, + 0x29, 0x73, 0xa5, 0x13, 0xe6, 0xa8, 0x9f, 0x6b, 0x3a, 0x6d, 0xa2, 0xed, 0xc5, 0x35, 0xcd, 0xc4, 0x2b, 0x56, 0x08, + 0x9a, 0xc1, 0xf4, 0x6b, 0x8a, 0x83, 0x19, 0x71, 0x04, 0x1b, 0xb6, 0xd1, 0x2a, 0x8c, 0xe3, 0x7b, 0x9b, 0x88, 0xa6, + 0x0e, 0x94, 0x84, 0x59, 0x9c, 0xaa, 0x41, 0xec, 0x84, 0x46, 0x93, 0xc4, 0x59, 0xd5, 0xb4, 0xf3, 0x69, 0x6a, 0x65, + 0x43, 0x72, 0x77, 0x8f, 0x11, 0x23, 0x09, 0x8c, 0xf4, 0xbc, 0x57, 0x6b, 0x81, 0x80, 0xf7, 0x86, 0x45, 0xb0, 0x67, + 0x82, 0x85, 0xc5, 0x51, 0xfd, 0x26, 0x9c, 0x86, 0x6e, 0xbe, 0x5f, 0x7b, 0xb0, 0x6d, 0x9d, 0x70, 0x90, 0x74, 0xf2, + 0x78, 0xb3, 0x65, 0xf5, 0xda, 0x48, 0x0e, 0x23, 0x2d, 0xd8, 0x43, 0x19, 0x33, 0x9a, 0x1b, 0xf2, 0x42, 0x66, 0x2b, + 0x6e, 0x0b, 0xf2, 0x33, 0x9c, 0x1c, 0x7a, 0x29, 0x26, 0xe9, 0xd2, 0x01, 0x99, 0xfe, 0x76, 0xa5, 0xfd, 0x6f, 0x0b, + 0xef, 0x19, 0x7e, 0x0d, 0x61, 0xdd, 0x6f, 0xeb, 0xea, 0xab, 0xe1, 0xdc, 0x6f, 0x6b, 0x04, 0x7d, 0x1b, 0xac, 0xd4, + 0xb3, 0xc2, 0xb8, 0x3d, 0xff, 0xd0, 0xef, 0xb8, 0x46, 0x5b, 0xfa, 0x41, 0x05, 0x91, 0x54, 0xaa, 0xa5, 0xdc, 0x0f, + 0xb8, 0x4e, 0x54, 0x83, 0x84, 0xb9, 0xa6, 0x85, 0x44, 0x75, 0x8a, 0xa1, 0xd2, 0xe1, 0x37, 0x2d, 0x8f, 0x96, 0x31, + 0xb9, 0xb2, 0x33, 0xde, 0x85, 0x5c, 0x6c, 0xc3, 0x2e, 0x2b, 0x56, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0x0f, 0x1b, + 0xa2, 0x3e, 0x0b, 0x30, 0xe4, 0xea, 0x30, 0x90, 0xdd, 0x3f, 0x29, 0x8c, 0xee, 0xd6, 0xb4, 0x32, 0xde, 0x80, 0xfd, + 0x8f, 0x70, 0x64, 0x8e, 0xc8, 0x51, 0xcd, 0x81, 0x69, 0x30, 0x2f, 0x2b, 0xa7, 0x40, 0xa1, 0x94, 0xb7, 0x0c, 0xe1, + 0xa2, 0x94, 0xe1, 0xed, 0xbf, 0xe0, 0xbf, 0x6a, 0x96, 0x78, 0x51, 0x71, 0x9c, 0x17, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, + 0x2a, 0x7a, 0x0f, 0x74, 0x2c, 0x29, 0xb4, 0x34, 0x54, 0xf4, 0x3c, 0xd7, 0x13, 0xd9, 0x98, 0x97, 0x8a, 0x69, 0x95, + 0x51, 0x23, 0x87, 0x59, 0x93, 0xc8, 0x69, 0xac, 0x6c, 0x51, 0xed, 0xaa, 0xc6, 0xb8, 0x68, 0x03, 0x16, 0xeb, 0xc0, + 0xe2, 0x62, 0xe1, 0x35, 0x51, 0x4d, 0x98, 0x15, 0xc7, 0x40, 0x98, 0x59, 0x09, 0x15, 0x0d, 0xcd, 0x5a, 0xb5, 0xf1, + 0xd0, 0x72, 0x3e, 0x91, 0xd1, 0xcd, 0x1b, 0x70, 0xd8, 0x2e, 0x04, 0xd5, 0xdc, 0xf6, 0x29, 0x60, 0x35, 0xbb, 0x6a, + 0x20, 0x0b, 0x43, 0x3f, 0x54, 0xb9, 0xb2, 0x75, 0x52, 0xeb, 0x1a, 0xfc, 0xa2, 0x7b, 0xb2, 0x65, 0x35, 0xea, 0x56, + 0xdf, 0x5b, 0xb9, 0x46, 0xcf, 0xf3, 0x4d, 0xb9, 0x46, 0x0d, 0x6d, 0x77, 0xab, 0x83, 0xee, 0xcf, 0x4b, 0x55, 0x63, + 0xad, 0xaf, 0xf2, 0x2b, 0x86, 0xeb, 0x02, 0x6d, 0x2a, 0x34, 0x1b, 0xae, 0x72, 0x52, 0x96, 0x17, 0xd5, 0x69, 0x02, + 0x99, 0xba, 0x73, 0xa1, 0xe8, 0x5f, 0x5b, 0x8d, 0xf2, 0x50, 0xae, 0xf7, 0x17, 0x32, 0x4e, 0xf3, 0xab, 0x30, 0xfd, + 0x00, 0xe3, 0xd5, 0x2f, 0x5f, 0xde, 0xc5, 0x3c, 0x14, 0x54, 0x73, 0x97, 0x1a, 0x86, 0xbf, 0x58, 0x30, 0xfc, 0x45, + 0xf1, 0xe9, 0xba, 0x3d, 0x9e, 0xbf, 0xaa, 0x3a, 0x08, 0x2e, 0x4a, 0xc3, 0x32, 0xee, 0xc4, 0xfa, 0x31, 0x96, 0x59, + 0xd8, 0x5d, 0xc5, 0xc2, 0xee, 0x84, 0xb7, 0xdc, 0x95, 0xe7, 0xfd, 0x75, 0x7d, 0x2f, 0xab, 0x9c, 0xed, 0xaf, 0xf5, + 0xc6, 0xff, 0x6b, 0x70, 0x6f, 0x1b, 0x8b, 0xcb, 0xed, 0xf9, 0x7b, 0x32, 0x59, 0x45, 0x81, 0xfc, 0x0a, 0x92, 0x0e, + 0x04, 0x19, 0x58, 0x87, 0x0e, 0x6a, 0x39, 0x65, 0xf2, 0x80, 0xbc, 0x68, 0x56, 0x88, 0x7c, 0xa2, 0xfb, 0x2c, 0xf4, + 0x49, 0x23, 0xf9, 0x12, 0x5c, 0xd1, 0x32, 0xd6, 0x1e, 0x34, 0xcf, 0x72, 0xcd, 0x3f, 0xb1, 0x2c, 0x0e, 0x38, 0xd6, + 0x52, 0xa4, 0x08, 0xf2, 0x92, 0x98, 0x6c, 0xe3, 0xd5, 0x77, 0x78, 0xc4, 0x32, 0x56, 0x24, 0x94, 0x7b, 0x05, 0x9a, + 0x6f, 0x1a, 0xac, 0x80, 0x80, 0x8c, 0x1a, 0x0c, 0xff, 0xa9, 0x3e, 0xf5, 0xe7, 0x43, 0x6f, 0xe0, 0x07, 0x9a, 0x50, + 0x91, 0xe4, 0x31, 0xa4, 0xa5, 0xf8, 0x71, 0x75, 0xa8, 0x69, 0x67, 0x67, 0xcb, 0x73, 0xa5, 0x5b, 0x02, 0x0e, 0x80, + 0xdb, 0x6f, 0xd0, 0x70, 0x0e, 0xe7, 0x73, 0xea, 0xa1, 0x29, 0x9a, 0xd3, 0xe5, 0xa3, 0x2c, 0xc2, 0xff, 0x44, 0xef, + 0x70, 0x86, 0xca, 0x32, 0x50, 0x50, 0xbb, 0x23, 0x46, 0xd3, 0xd8, 0xc5, 0x9f, 0xe8, 0x5d, 0x50, 0x9d, 0x19, 0x97, + 0x47, 0x9c, 0xe5, 0x02, 0xba, 0xf9, 0x4d, 0xe6, 0xe2, 0x7a, 0x90, 0x60, 0x5e, 0xe2, 0x9c, 0xb3, 0x31, 0x10, 0xe7, + 0xb7, 0xf4, 0x2e, 0x50, 0xfd, 0x31, 0xeb, 0xbc, 0x1e, 0x9a, 0x1b, 0xd4, 0xfb, 0x56, 0xb1, 0xbd, 0x0c, 0xda, 0xa0, + 0x38, 0x93, 0x6d, 0xcf, 0x49, 0xa3, 0x5e, 0x6d, 0x1e, 0x22, 0x54, 0x3e, 0x74, 0x2a, 0xf8, 0x5b, 0x5b, 0xb4, 0x89, + 0x46, 0xe6, 0xeb, 0x52, 0x23, 0x0a, 0x0d, 0xea, 0x4c, 0x8f, 0x6d, 0x2f, 0x33, 0xbb, 0x4e, 0x1f, 0x42, 0xb0, 0x1c, + 0x61, 0xdf, 0x0a, 0xdd, 0x69, 0xf0, 0x27, 0x95, 0x10, 0x52, 0x47, 0x92, 0xbe, 0xa9, 0xdb, 0x39, 0xdb, 0x1e, 0xe0, + 0x1d, 0x12, 0x5a, 0x42, 0x79, 0x26, 0xb3, 0x34, 0xd9, 0xa2, 0x7f, 0x16, 0xc4, 0x9b, 0x9b, 0x29, 0x04, 0x99, 0x8d, + 0x45, 0x51, 0x02, 0x15, 0x6a, 0xfa, 0x52, 0x09, 0x80, 0x6c, 0xe4, 0xb1, 0x15, 0xa9, 0x99, 0x4b, 0xa9, 0xe9, 0x5b, + 0x18, 0xdf, 0x20, 0x25, 0xa9, 0x44, 0x86, 0x54, 0x22, 0xa5, 0xd0, 0xd3, 0x8b, 0xab, 0x49, 0xc8, 0x5e, 0xd0, 0xea, + 0x04, 0x9d, 0x5a, 0xf3, 0xbc, 0x01, 0x96, 0x27, 0xfb, 0x41, 0x65, 0x00, 0x53, 0xa2, 0xaa, 0x42, 0x59, 0x1d, 0xcd, + 0x36, 0xe9, 0xad, 0x9e, 0x3c, 0xeb, 0x24, 0xa7, 0x45, 0x0c, 0x4a, 0xbc, 0x08, 0xcd, 0x33, 0x2f, 0xc2, 0x39, 0xa4, + 0x23, 0x16, 0x65, 0x05, 0x3f, 0xb5, 0x57, 0xa3, 0x91, 0xac, 0xbc, 0xfe, 0x94, 0x1f, 0x28, 0xf3, 0x02, 0x52, 0x34, + 0x71, 0x66, 0x78, 0x4a, 0xe6, 0xc9, 0xe3, 0x76, 0xd6, 0xb2, 0xfd, 0x45, 0x27, 0xe8, 0x68, 0xc0, 0xfe, 0x2c, 0xbc, + 0xb9, 0x35, 0x0b, 0xfb, 0x44, 0xb7, 0x3e, 0xf5, 0xa7, 0x83, 0x7d, 0x75, 0x0e, 0xa9, 0xc7, 0xc9, 0x92, 0xc4, 0xb9, + 0x3f, 0xd5, 0xf2, 0xe7, 0x19, 0xe5, 0x77, 0xa7, 0x14, 0x52, 0x9d, 0x73, 0x38, 0xf0, 0x5b, 0x2f, 0x43, 0x9d, 0xa7, + 0x3e, 0xcc, 0xa5, 0xb2, 0x52, 0x36, 0xcf, 0x01, 0x2e, 0x9f, 0x12, 0x2c, 0x65, 0xb4, 0xd1, 0x72, 0xc4, 0xa8, 0xdd, + 0x42, 0x37, 0x9e, 0x9f, 0xa4, 0x7d, 0x06, 0xfe, 0xb5, 0x1a, 0xd3, 0x3a, 0x58, 0x80, 0x0b, 0xfb, 0x4c, 0xea, 0x19, + 0x3f, 0x5f, 0xf6, 0xca, 0x40, 0x11, 0x84, 0xef, 0xf2, 0xcd, 0x53, 0x5d, 0x97, 0x34, 0xbb, 0x79, 0xaa, 0x8d, 0xa0, + 0x9f, 0x4c, 0xf8, 0xc1, 0x7a, 0x9c, 0xea, 0x04, 0x33, 0x2b, 0x4b, 0x54, 0x02, 0x78, 0x7f, 0xec, 0x7b, 0xde, 0x1f, + 0x75, 0xca, 0xa0, 0x0f, 0xb1, 0xd8, 0xd3, 0x34, 0x37, 0x4c, 0xbc, 0x1e, 0xff, 0x8f, 0x2b, 0xe3, 0xff, 0xd1, 0x3a, + 0x75, 0x0a, 0xa6, 0xd1, 0x38, 0xa3, 0xb1, 0x61, 0x9d, 0x48, 0x11, 0xa0, 0xd4, 0xdb, 0x0a, 0x41, 0x3e, 0x5d, 0x06, + 0xa0, 0x71, 0xcd, 0x47, 0x79, 0x26, 0x5a, 0xa3, 0x70, 0xc2, 0xd2, 0xbb, 0x60, 0xc6, 0x5a, 0x93, 0x3c, 0xcb, 0x8b, + 0x69, 0x18, 0x51, 0x5c, 0xdc, 0x15, 0x82, 0x4e, 0x5a, 0x33, 0x86, 0x5f, 0xd2, 0xf4, 0x9a, 0x0a, 0x16, 0x85, 0xd8, + 0x3d, 0xe6, 0x2c, 0x4c, 0x9d, 0x37, 0x21, 0xe7, 0xf9, 0x8d, 0x8b, 0xdf, 0xe7, 0x57, 0xb9, 0xc8, 0xf1, 0xdb, 0xdb, + 0xbb, 0x31, 0xcd, 0xf0, 0xc7, 0xab, 0x59, 0x26, 0x66, 0xb8, 0x08, 0xb3, 0xa2, 0x55, 0x50, 0xce, 0x46, 0xfd, 0x28, + 0x4f, 0x73, 0xde, 0x82, 0x8c, 0xed, 0x09, 0x0d, 0x52, 0x36, 0x4e, 0x84, 0x13, 0x87, 0xfc, 0x53, 0xbf, 0xd5, 0x9a, + 0x72, 0x36, 0x09, 0xf9, 0x5d, 0x4b, 0xd6, 0x08, 0xbe, 0xea, 0xec, 0x85, 0x4f, 0x47, 0xfb, 0x7d, 0xc1, 0xc3, 0xac, + 0x60, 0xb0, 0x4c, 0x41, 0x98, 0xa6, 0xce, 0xde, 0x41, 0x67, 0x52, 0x6c, 0xa9, 0x40, 0x5e, 0x98, 0x89, 0xf2, 0x12, + 0x7f, 0x00, 0xb8, 0xfd, 0x2b, 0x91, 0xe1, 0xab, 0x99, 0x10, 0x79, 0x36, 0x8f, 0x66, 0xbc, 0xc8, 0x79, 0x30, 0xcd, + 0x59, 0x26, 0x28, 0xef, 0x5f, 0xe5, 0x3c, 0xa6, 0xbc, 0xc5, 0xc3, 0x98, 0xcd, 0x8a, 0x60, 0x7f, 0x7a, 0xdb, 0x07, + 0xcd, 0x62, 0xcc, 0xf3, 0x59, 0x16, 0xeb, 0xb1, 0x58, 0x96, 0x50, 0xce, 0x84, 0xfd, 0x42, 0x5e, 0x64, 0x12, 0xa4, + 0x2c, 0xa3, 0x21, 0x6f, 0x8d, 0xa1, 0x31, 0x98, 0x45, 0x9d, 0x98, 0x8e, 0x31, 0x1f, 0x5f, 0x85, 0x5e, 0xb7, 0xf7, + 0x04, 0x9b, 0xff, 0xfd, 0x03, 0xe4, 0x74, 0xd6, 0x17, 0x77, 0x3b, 0x9d, 0x7f, 0x42, 0xfd, 0xa5, 0x51, 0x24, 0x40, + 0x41, 0x77, 0x7a, 0xeb, 0x14, 0x39, 0x64, 0xb4, 0xad, 0x6b, 0xd9, 0x9f, 0x86, 0x31, 0xe4, 0x03, 0x07, 0xbd, 0xe9, + 0x6d, 0x09, 0xb3, 0x0b, 0x54, 0x8a, 0xa9, 0x9e, 0xa4, 0x7e, 0x9a, 0xff, 0x5a, 0x88, 0x0f, 0xd7, 0x43, 0xdc, 0x33, + 0x10, 0xd7, 0x58, 0x6f, 0xc5, 0x33, 0x2e, 0x63, 0xab, 0x41, 0xb7, 0x50, 0x80, 0x24, 0xf9, 0x35, 0xe5, 0x06, 0x0e, + 0xf9, 0xf0, 0xab, 0xc1, 0xe8, 0xad, 0x07, 0xe3, 0xf0, 0x73, 0x60, 0xf0, 0x2c, 0x9e, 0x37, 0xd7, 0xb5, 0xcb, 0xe9, + 0xa4, 0x9f, 0x50, 0xa0, 0xa7, 0xa0, 0x07, 0xbf, 0x6f, 0x58, 0x2c, 0x12, 0xf5, 0x53, 0x92, 0xf3, 0x8d, 0x7a, 0x77, + 0xd0, 0xe9, 0xa8, 0xe7, 0x82, 0xfd, 0x42, 0x83, 0xae, 0x0f, 0x15, 0xca, 0x4b, 0xfc, 0xd7, 0xea, 0x34, 0x6f, 0x93, + 0x7b, 0xe2, 0x3f, 0xda, 0xc7, 0x7c, 0xad, 0x14, 0xc5, 0xfa, 0x50, 0x34, 0xce, 0x8d, 0xac, 0x54, 0xc2, 0x07, 0xdc, + 0x76, 0x92, 0x3b, 0x12, 0x36, 0xa8, 0x8e, 0x71, 0xb2, 0xe1, 0x1f, 0x55, 0xde, 0x45, 0x00, 0x91, 0x0e, 0x2b, 0xd5, + 0xb0, 0xe8, 0xe7, 0x03, 0xd2, 0xe9, 0xe7, 0xad, 0x16, 0xf2, 0x0a, 0x92, 0x9d, 0xe5, 0x3a, 0x39, 0xcf, 0x63, 0xc3, + 0x42, 0x1a, 0xdb, 0x1c, 0x05, 0x05, 0x9c, 0x35, 0x5d, 0x2c, 0x78, 0x9d, 0x90, 0x21, 0x4f, 0x6b, 0xfc, 0x55, 0xe8, + 0x0a, 0x98, 0x5b, 0x9c, 0x3c, 0x34, 0xd7, 0xbb, 0x64, 0x86, 0x57, 0xa4, 0x79, 0x24, 0x31, 0xe7, 0x4f, 0x43, 0x91, + 0x80, 0x97, 0xa2, 0x12, 0x3f, 0x75, 0x0a, 0x93, 0xdb, 0x76, 0xd1, 0x30, 0xab, 0xf2, 0xdb, 0x20, 0x8f, 0x2f, 0x2b, + 0xa1, 0x97, 0x2b, 0x41, 0xa0, 0xc7, 0xba, 0xff, 0x8f, 0xc2, 0x92, 0xd4, 0x99, 0xcf, 0xb2, 0x28, 0x9d, 0xc5, 0xb4, + 0x90, 0x3d, 0xd4, 0xe2, 0x1c, 0xee, 0x86, 0xa8, 0x6a, 0xc9, 0x26, 0xd0, 0xbb, 0xcc, 0xe6, 0x81, 0x8a, 0x70, 0x8b, + 0x4a, 0xf5, 0xdc, 0x92, 0xcf, 0x75, 0xdb, 0x37, 0x75, 0xb2, 0x28, 0xb4, 0xf4, 0x67, 0x19, 0xfb, 0x79, 0x46, 0x2f, + 0x58, 0x6c, 0x9d, 0xdc, 0xa5, 0x59, 0x94, 0xc7, 0xf4, 0xe3, 0xfb, 0x6f, 0x20, 0xdb, 0x3d, 0xcf, 0x80, 0xc4, 0x32, + 0xe5, 0xef, 0xc2, 0x9c, 0x64, 0x7e, 0x4c, 0xaf, 0x59, 0x44, 0x87, 0x97, 0xdb, 0xf3, 0xb5, 0x15, 0xd5, 0x6b, 0x54, + 0xb6, 0x2f, 0xc1, 0x7f, 0xa7, 0xa0, 0xbc, 0xdc, 0x9e, 0x5f, 0x89, 0xb2, 0xbd, 0x3d, 0xcf, 0xfc, 0x38, 0x9f, 0x84, + 0x2c, 0x83, 0xdf, 0xbc, 0xdc, 0x9e, 0x33, 0xf8, 0x21, 0xca, 0xcb, 0xb2, 0x4e, 0x14, 0xad, 0x20, 0xb2, 0xa6, 0xa0, + 0x71, 0xd7, 0x45, 0xfe, 0x4f, 0x39, 0xcb, 0x64, 0xd1, 0x7d, 0x3d, 0x53, 0xd3, 0x2b, 0x20, 0xf9, 0x17, 0xa2, 0x0c, + 0x66, 0x63, 0x2e, 0x5f, 0x3c, 0xd4, 0x5c, 0xa6, 0x99, 0x60, 0x32, 0x2d, 0xde, 0x84, 0x73, 0x92, 0xb0, 0xb8, 0x88, + 0xd4, 0x49, 0xd4, 0xa2, 0x3e, 0x75, 0x11, 0x4a, 0xc4, 0x2a, 0x0b, 0x98, 0x72, 0x69, 0xec, 0xd3, 0xcd, 0x47, 0x25, + 0xb3, 0xfb, 0x8c, 0xbf, 0x8a, 0xaa, 0x8a, 0x7c, 0xc6, 0x23, 0x88, 0xf5, 0x6a, 0x95, 0x62, 0xd5, 0x2b, 0xe6, 0x4a, + 0xfd, 0xcd, 0xc5, 0xc2, 0x4a, 0xb2, 0x15, 0x70, 0xa6, 0xaf, 0xbe, 0xb6, 0x83, 0xca, 0x78, 0xa2, 0x3a, 0x0b, 0xa3, + 0xf5, 0x07, 0x33, 0x25, 0x50, 0x88, 0x62, 0x99, 0x2f, 0xea, 0xe5, 0x64, 0x90, 0xd7, 0x38, 0x27, 0x84, 0x30, 0x9f, + 0xc5, 0x32, 0x90, 0x07, 0x8a, 0x45, 0xab, 0x0b, 0x91, 0x21, 0x16, 0xd7, 0x1a, 0x1e, 0xd3, 0x78, 0x5e, 0x2c, 0xe0, + 0x6c, 0x8a, 0xac, 0xab, 0x9c, 0x2a, 0xa0, 0x83, 0x31, 0xac, 0x5e, 0x06, 0x39, 0xae, 0xba, 0x0c, 0xa0, 0x52, 0xd9, + 0x57, 0xe8, 0x53, 0xc8, 0x22, 0x06, 0x9d, 0xc7, 0x4a, 0x45, 0x28, 0x10, 0xb6, 0x5f, 0x57, 0x47, 0xf8, 0x1b, 0xf8, + 0xee, 0x2c, 0x2d, 0x8b, 0xb2, 0xa7, 0x96, 0x17, 0xcb, 0x2f, 0x72, 0x2e, 0x3c, 0x2f, 0xc2, 0x21, 0x22, 0x83, 0x48, + 0x52, 0xed, 0x51, 0x28, 0xff, 0x19, 0xb6, 0xba, 0x41, 0xb7, 0xf2, 0x84, 0x34, 0x4e, 0x56, 0xab, 0x3c, 0x33, 0x7d, + 0x3a, 0x17, 0xc0, 0xc5, 0xd5, 0x6f, 0x35, 0x9f, 0xfa, 0xb9, 0x9a, 0x16, 0xd6, 0x9c, 0x4b, 0x49, 0x7d, 0xaf, 0x01, + 0x84, 0x8c, 0xbb, 0x6d, 0x18, 0x0a, 0x95, 0xf5, 0xbc, 0xab, 0x5d, 0x7c, 0xa9, 0xb4, 0x9d, 0x0b, 0x8b, 0x8c, 0x2f, + 0x99, 0xf1, 0xd7, 0x35, 0x09, 0xac, 0xd4, 0x18, 0xb1, 0x58, 0xc0, 0xba, 0x6a, 0x0a, 0x96, 0x3b, 0x92, 0xad, 0xa5, + 0x52, 0x5f, 0x3d, 0x52, 0x45, 0x16, 0xeb, 0xab, 0xc8, 0xac, 0xc7, 0x75, 0x80, 0x81, 0x07, 0xa0, 0x10, 0x66, 0x0a, + 0xc0, 0x4c, 0x46, 0x14, 0x8e, 0x24, 0x69, 0xd6, 0x82, 0xe7, 0x4a, 0x8d, 0x0f, 0xdc, 0x77, 0x6f, 0x4f, 0x3f, 0xb8, + 0x18, 0xee, 0x34, 0xa3, 0xbc, 0x08, 0xe6, 0xae, 0x4e, 0x26, 0x6c, 0x41, 0x60, 0xda, 0x0d, 0xdc, 0x70, 0x0a, 0xa7, + 0xb3, 0x25, 0xf7, 0x6c, 0xdf, 0xb6, 0x6e, 0x6e, 0x6e, 0x5a, 0x70, 0x74, 0xac, 0x35, 0xe3, 0xa9, 0xe2, 0x2b, 0xb1, + 0x5b, 0x96, 0xc8, 0x17, 0x09, 0xcd, 0xaa, 0x5b, 0x8f, 0xf2, 0x94, 0xfa, 0x69, 0x3e, 0x56, 0x07, 0x5f, 0x97, 0xfd, + 0x10, 0xe9, 0xe5, 0x91, 0xbc, 0xcd, 0x6b, 0x70, 0x24, 0xd4, 0x3d, 0x6a, 0x82, 0xc3, 0xcf, 0x01, 0x44, 0xa9, 0x8e, + 0xda, 0x22, 0x91, 0x0f, 0xa7, 0xb0, 0x6d, 0xe4, 0xd3, 0xf6, 0x7c, 0x85, 0xc8, 0x86, 0xd0, 0x45, 0x32, 0x50, 0x53, + 0x2b, 0x64, 0xad, 0xcb, 0x20, 0xbd, 0xbc, 0x2c, 0x8f, 0xda, 0xd0, 0x57, 0xdb, 0xf4, 0x7b, 0x95, 0xc7, 0x77, 0xa6, + 0x7d, 0x45, 0x78, 0x70, 0xab, 0x53, 0x46, 0x06, 0xd0, 0x05, 0x8c, 0x1b, 0x0f, 0x24, 0xce, 0x34, 0xaf, 0x3c, 0xab, + 0x1f, 0xca, 0x73, 0x07, 0x38, 0x63, 0x09, 0x25, 0x40, 0x97, 0xd0, 0x79, 0x5c, 0x35, 0x90, 0xdb, 0x5a, 0x15, 0x6d, + 0x02, 0x50, 0x55, 0xac, 0xb7, 0x8b, 0xf2, 0x67, 0xd7, 0x64, 0x61, 0x20, 0x8e, 0x6d, 0xe0, 0x2f, 0x11, 0xfc, 0x2b, + 0x01, 0x3f, 0x6a, 0x2b, 0x34, 0x5d, 0xda, 0xf7, 0xcb, 0xa8, 0x9b, 0x1f, 0x2a, 0x64, 0x9e, 0x15, 0x02, 0x7f, 0x10, + 0xf8, 0xd3, 0xa5, 0xac, 0x6a, 0xd4, 0x01, 0xd0, 0x53, 0x41, 0x6d, 0xea, 0x18, 0xbd, 0x2f, 0xca, 0xd3, 0x34, 0x9c, + 0x16, 0x34, 0x30, 0x3f, 0xb4, 0x66, 0x00, 0x0a, 0xc6, 0xaa, 0x2a, 0xa6, 0x13, 0x9c, 0x4e, 0x40, 0x61, 0x5b, 0xd5, + 0x13, 0xaf, 0x43, 0xee, 0xb5, 0x5a, 0x51, 0xeb, 0x6a, 0x8c, 0x4a, 0x91, 0xcc, 0x6d, 0xbd, 0xe2, 0x71, 0xa7, 0xd3, + 0x87, 0x6c, 0xd4, 0x56, 0x98, 0xb2, 0x71, 0x16, 0xa4, 0x74, 0x24, 0x4a, 0x01, 0xc7, 0x04, 0xe7, 0x46, 0x91, 0xf3, + 0x7b, 0x07, 0x9c, 0x4e, 0x1c, 0x1f, 0xfe, 0xde, 0x3f, 0x70, 0x29, 0xe2, 0x20, 0x13, 0x49, 0x4b, 0x66, 0x3d, 0xc3, + 0x99, 0x0d, 0x91, 0x34, 0x9e, 0xe7, 0xd6, 0x40, 0x11, 0x05, 0x25, 0xb7, 0x14, 0xdc, 0x11, 0x09, 0x16, 0xdc, 0xae, + 0x97, 0xa1, 0xf9, 0xca, 0x0c, 0x56, 0x75, 0xad, 0x3d, 0x54, 0x16, 0xd2, 0x34, 0x59, 0xad, 0x6c, 0x14, 0xd6, 0xe6, + 0xd3, 0x0a, 0xfa, 0x2c, 0xd5, 0xba, 0x54, 0xae, 0xfd, 0xb9, 0x6a, 0xf1, 0x10, 0x64, 0x36, 0x94, 0x7e, 0x6c, 0xb7, + 0x40, 0x25, 0xcb, 0xa6, 0x33, 0x71, 0x26, 0xc3, 0x0a, 0x1c, 0x0e, 0xa8, 0x9c, 0x63, 0xab, 0x04, 0x70, 0x70, 0x3e, + 0x57, 0xc0, 0x44, 0x61, 0x1a, 0x79, 0x00, 0x91, 0xd3, 0x72, 0x0e, 0x39, 0x9d, 0xa0, 0xfe, 0x84, 0x65, 0x2d, 0xf5, + 0xee, 0xc0, 0x52, 0x0c, 0xfd, 0x27, 0xf0, 0x54, 0xfa, 0xb2, 0x37, 0x2c, 0xb3, 0x87, 0xd7, 0xe0, 0xf2, 0xf2, 0xbc, + 0x2c, 0xfb, 0xb9, 0xf0, 0xce, 0xbe, 0xf1, 0xd0, 0x39, 0xfe, 0xc5, 0xba, 0x21, 0xc7, 0x35, 0x3b, 0xc9, 0xc5, 0x3d, + 0xb4, 0xa1, 0x8a, 0xbd, 0x17, 0x64, 0xb5, 0x5f, 0x08, 0x54, 0x7c, 0xe5, 0xb9, 0xb4, 0x98, 0xb6, 0x14, 0xcb, 0x6b, + 0x49, 0x92, 0x75, 0xa1, 0x29, 0xd2, 0xbe, 0x72, 0x4a, 0xe7, 0x92, 0x9b, 0xe9, 0x43, 0x32, 0xca, 0x9d, 0x73, 0x5e, + 0x1d, 0xaa, 0xd2, 0xcf, 0xf6, 0x31, 0x2a, 0xd4, 0x60, 0x37, 0x97, 0xc7, 0x4d, 0xd6, 0x08, 0xca, 0x45, 0x75, 0x91, + 0x60, 0x98, 0xa6, 0x30, 0xe0, 0xa5, 0xd1, 0x48, 0xec, 0x7b, 0x57, 0xce, 0xc4, 0xb9, 0x87, 0x4a, 0xbd, 0x4f, 0x9f, + 0x49, 0xa5, 0xde, 0xba, 0xbd, 0x70, 0x4b, 0x98, 0x70, 0x9d, 0x12, 0xd1, 0x0c, 0x12, 0x0e, 0x1a, 0x89, 0xe9, 0xfd, + 0x9a, 0xb5, 0x29, 0x93, 0xc0, 0x91, 0x13, 0x22, 0x2e, 0xcf, 0x62, 0xd7, 0xf9, 0x43, 0x94, 0xb2, 0xe8, 0x13, 0x71, + 0xb7, 0xe7, 0x1e, 0x5a, 0x3d, 0x77, 0x2a, 0xb9, 0x82, 0xe1, 0xf3, 0xa8, 0x19, 0xca, 0xc8, 0x7d, 0x8b, 0x85, 0xab, + 0xab, 0x89, 0xdc, 0x01, 0xe8, 0x4d, 0x47, 0x6d, 0x35, 0xce, 0xe0, 0xb2, 0xbc, 0xa8, 0xaf, 0x1c, 0xab, 0xa1, 0x00, + 0x34, 0xab, 0x72, 0x47, 0x12, 0x15, 0x71, 0x3f, 0x4b, 0x69, 0xae, 0xa3, 0x98, 0x1a, 0xc0, 0x29, 0x34, 0x7f, 0x73, + 0x9d, 0x3f, 0x54, 0x65, 0xb4, 0xf2, 0x29, 0xc9, 0xa4, 0x18, 0xe2, 0xc2, 0x58, 0xe0, 0x48, 0xf0, 0x63, 0x2a, 0x42, + 0x96, 0xaa, 0x26, 0x7d, 0xe3, 0x02, 0x59, 0x9a, 0xd1, 0x62, 0xc1, 0x9b, 0x73, 0x61, 0x4d, 0x0c, 0xca, 0x99, 0x1d, + 0xb5, 0x6b, 0xb8, 0xe5, 0xcc, 0xe4, 0x9e, 0xb4, 0x83, 0xb3, 0xf5, 0x0c, 0xd5, 0x3b, 0xe7, 0x0f, 0x91, 0x3c, 0xb6, + 0x05, 0x00, 0x16, 0x1a, 0x40, 0x48, 0x1b, 0x50, 0xc7, 0x92, 0xbc, 0x90, 0x14, 0xbe, 0x08, 0xf9, 0x98, 0x8a, 0x25, + 0xc4, 0x86, 0x2a, 0x4b, 0xb8, 0x6f, 0x52, 0x04, 0x56, 0xa0, 0x4d, 0x9a, 0xd0, 0x82, 0x12, 0x5d, 0x0e, 0x41, 0x0f, + 0x26, 0x6b, 0xd5, 0xe9, 0x08, 0x81, 0xbc, 0x95, 0x8b, 0xc3, 0xa5, 0x84, 0x29, 0xa4, 0x84, 0x51, 0x9c, 0xc0, 0x91, + 0x63, 0x49, 0x10, 0x4b, 0xd7, 0x19, 0x2a, 0xc8, 0x69, 0xac, 0x60, 0x26, 0xb9, 0x6c, 0x55, 0x94, 0x47, 0x6d, 0x55, + 0x5b, 0x89, 0x00, 0x55, 0x09, 0x90, 0x20, 0xf7, 0x69, 0x8d, 0x03, 0xc8, 0x2c, 0xb7, 0xf1, 0x10, 0xb3, 0xeb, 0x8a, + 0xd8, 0xe4, 0x01, 0xb6, 0xc1, 0x51, 0x1a, 0x5e, 0xd1, 0x74, 0xb0, 0x3d, 0xcf, 0x17, 0x8b, 0x4e, 0x79, 0xd4, 0x56, + 0x8f, 0xce, 0x91, 0xe4, 0x1b, 0xea, 0xe2, 0x51, 0xb9, 0xc4, 0x70, 0x2a, 0x14, 0xf2, 0x6d, 0x4d, 0xa2, 0x59, 0xa0, + 0x3b, 0x28, 0x5d, 0x47, 0xa6, 0xb8, 0xc8, 0x4a, 0x95, 0x1e, 0x55, 0xba, 0x0e, 0x8b, 0x57, 0xcb, 0x0a, 0x41, 0xa7, + 0x50, 0x1a, 0x2d, 0x16, 0xdd, 0xd2, 0x75, 0x26, 0x2c, 0x83, 0xa7, 0x7c, 0xb1, 0x90, 0x07, 0x2e, 0x27, 0x2c, 0xf3, + 0x3a, 0x40, 0xb6, 0xae, 0x33, 0x09, 0x6f, 0xe5, 0x84, 0xcd, 0x9b, 0xf0, 0xd6, 0xeb, 0xea, 0x57, 0x7e, 0x85, 0x1f, + 0x0e, 0x14, 0x57, 0xaf, 0x68, 0xa8, 0x57, 0x34, 0xc6, 0x33, 0x75, 0x94, 0x8c, 0x78, 0x31, 0x09, 0xd7, 0xaf, 0x68, + 0x6c, 0x56, 0x74, 0xb6, 0x61, 0x45, 0x67, 0xf7, 0xac, 0x68, 0xa2, 0x57, 0xcf, 0xa9, 0x70, 0x57, 0x2c, 0x16, 0xdd, + 0x4e, 0x8d, 0xbd, 0xa3, 0x76, 0xcc, 0xae, 0x61, 0x35, 0x40, 0x3b, 0x14, 0x6c, 0x42, 0xd7, 0x13, 0x65, 0x13, 0xc5, + 0xf4, 0x8b, 0x30, 0x59, 0x63, 0x21, 0x6f, 0x62, 0xc1, 0xa6, 0xeb, 0x2a, 0xea, 0xf9, 0x5b, 0x52, 0x36, 0x03, 0x3c, + 0x70, 0xc0, 0x43, 0x64, 0x2e, 0x22, 0xf5, 0xdc, 0x0f, 0x2e, 0x76, 0x1d, 0xd7, 0x90, 0xf5, 0x65, 0x79, 0x01, 0x32, + 0x42, 0xce, 0xef, 0x41, 0xb4, 0x08, 0xb5, 0xdd, 0xc1, 0x66, 0x9a, 0x83, 0x04, 0x85, 0x9b, 0x9c, 0xc7, 0x6e, 0xa0, + 0xaa, 0x7e, 0x11, 0xaa, 0x26, 0x2c, 0xd3, 0xe9, 0x6e, 0x1b, 0x69, 0xad, 0x7e, 0x6f, 0x53, 0x5c, 0xef, 0xe0, 0x40, + 0xd5, 0x98, 0x86, 0x42, 0x50, 0x9e, 0x69, 0xca, 0x75, 0xdd, 0x7f, 0x17, 0x54, 0xb8, 0x86, 0xaf, 0x24, 0x66, 0x01, + 0x0c, 0x01, 0x6a, 0x3d, 0x5f, 0xf3, 0x7c, 0x25, 0x9e, 0xb6, 0x6a, 0x05, 0xf7, 0x0e, 0xd9, 0xb6, 0x86, 0x2a, 0x02, + 0xd3, 0x67, 0x36, 0xa1, 0xf1, 0x85, 0x64, 0xd0, 0xc3, 0xf4, 0x52, 0x2b, 0xac, 0x4b, 0xe2, 0xae, 0x6e, 0x80, 0xdd, + 0x1f, 0x67, 0xbd, 0x27, 0xfb, 0x27, 0x2e, 0x56, 0x3c, 0x3e, 0x1f, 0x8d, 0x5c, 0x54, 0x3a, 0x0f, 0x6b, 0xd6, 0xdd, + 0xff, 0x71, 0xf6, 0xf5, 0x8b, 0xce, 0xd7, 0x55, 0xe3, 0x0c, 0x88, 0x48, 0x67, 0x58, 0x18, 0x51, 0x65, 0xc1, 0x6b, + 0x66, 0x34, 0x0a, 0xb3, 0xcd, 0xd3, 0x39, 0xb3, 0xa7, 0x53, 0x4c, 0x29, 0x8d, 0x81, 0x38, 0xf1, 0x4a, 0xe9, 0x45, + 0x4a, 0xaf, 0xa9, 0xb9, 0xfe, 0x71, 0xcd, 0x60, 0x6b, 0x5a, 0x44, 0xf9, 0x2c, 0x13, 0x3a, 0xd5, 0x44, 0xb3, 0x5a, + 0x6b, 0x4a, 0x97, 0x72, 0x0e, 0xb6, 0x09, 0x71, 0xa7, 0xe4, 0x5c, 0x53, 0x7a, 0x95, 0x97, 0xd8, 0xb5, 0x00, 0xd8, + 0x08, 0xd9, 0x70, 0x43, 0x79, 0xd0, 0xc1, 0x9d, 0x4d, 0xb0, 0xe1, 0x2e, 0x0a, 0x5c, 0xf7, 0xdc, 0xe0, 0x49, 0x7a, + 0x8b, 0x1b, 0x37, 0x76, 0x6c, 0xc4, 0xd7, 0x67, 0x31, 0x70, 0xc5, 0xa1, 0xb3, 0x8c, 0x16, 0xc5, 0x46, 0x04, 0x54, + 0x8b, 0x88, 0xdd, 0xba, 0xb6, 0xbb, 0xa1, 0x17, 0xdc, 0xc1, 0xb0, 0xc3, 0x24, 0xc0, 0x55, 0xcc, 0x5a, 0xd7, 0xa2, + 0xa3, 0x11, 0x8d, 0x2a, 0x67, 0x3b, 0x44, 0x1f, 0x47, 0x2c, 0x15, 0x10, 0x84, 0x93, 0xd1, 0x31, 0xf7, 0x4d, 0x9e, + 0x51, 0x17, 0x99, 0x7c, 0x5a, 0x0d, 0xbf, 0x96, 0xff, 0xeb, 0xe1, 0x51, 0x3d, 0x36, 0x61, 0xd1, 0xa3, 0x2c, 0x16, + 0xc6, 0x17, 0xd4, 0x28, 0x6f, 0x22, 0x32, 0x97, 0xce, 0x9e, 0x4d, 0x1b, 0xe8, 0x61, 0xdb, 0x64, 0xde, 0xfd, 0xfa, + 0xa0, 0xdb, 0x29, 0x5d, 0xec, 0x42, 0x77, 0x0f, 0xdd, 0x25, 0xb2, 0xd5, 0x1e, 0xb4, 0x9a, 0x65, 0x5f, 0xd2, 0xae, + 0xd7, 0x7d, 0xda, 0x75, 0xb1, 0xba, 0xc8, 0x01, 0x95, 0x15, 0x33, 0x88, 0xc0, 0xfd, 0xfc, 0x77, 0x4f, 0xa5, 0xd9, + 0xf9, 0xc3, 0xe0, 0x79, 0xdc, 0xed, 0xb8, 0xd8, 0x2d, 0x44, 0x3e, 0xfd, 0x82, 0x29, 0xec, 0xb9, 0xd8, 0x8d, 0xd2, + 0xbc, 0xa0, 0xf6, 0x1c, 0x94, 0x3a, 0xfb, 0xf7, 0x4f, 0x42, 0x41, 0x34, 0xe5, 0xb4, 0x28, 0x1c, 0xbb, 0x7f, 0x4d, + 0x4a, 0x9f, 0x61, 0x98, 0x6b, 0x29, 0xae, 0xa0, 0x42, 0xe2, 0x45, 0xdd, 0xb1, 0x60, 0x53, 0x95, 0x2a, 0x5b, 0x21, + 0x36, 0x29, 0x02, 0x2a, 0xc6, 0xa6, 0xb4, 0xab, 0xcf, 0x8e, 0xbc, 0x66, 0xeb, 0xa9, 0x81, 0x55, 0x54, 0x7e, 0x75, + 0x80, 0x46, 0xc9, 0x84, 0x65, 0x17, 0x6b, 0x4a, 0xc3, 0xdb, 0x35, 0xa5, 0xa0, 0xb2, 0x55, 0xd0, 0xe9, 0xfb, 0x7f, + 0x3e, 0x8f, 0xf5, 0x5a, 0xf1, 0xb1, 0x41, 0x8c, 0xa5, 0x73, 0xf3, 0x33, 0x90, 0x5a, 0xcb, 0x20, 0x7b, 0xf8, 0xf5, + 0xc3, 0x41, 0xc9, 0x97, 0x0c, 0x57, 0xf5, 0xf2, 0xf7, 0xcd, 0x10, 0x4a, 0x5b, 0x10, 0x41, 0x48, 0xbf, 0x68, 0xae, + 0xf4, 0xf6, 0xf3, 0x04, 0x67, 0x69, 0x55, 0x7f, 0xc7, 0xd2, 0xeb, 0x7b, 0x04, 0x96, 0xd7, 0x7e, 0x4d, 0xb1, 0x56, + 0x7c, 0xaa, 0xf5, 0x8f, 0x52, 0x36, 0xa9, 0x49, 0x60, 0x15, 0x4c, 0xa9, 0xf1, 0x40, 0x3a, 0x99, 0xdd, 0x89, 0x52, + 0x7d, 0x2e, 0xe0, 0x90, 0x2c, 0xdc, 0x43, 0x32, 0xe3, 0xf4, 0x22, 0xcd, 0x6f, 0x96, 0x6f, 0x56, 0xdb, 0x5c, 0x39, + 0x61, 0xe3, 0xc4, 0x3a, 0xf9, 0x46, 0x49, 0xb5, 0x08, 0xf7, 0x0e, 0x50, 0xfe, 0xeb, 0xbf, 0xf8, 0xfe, 0xbf, 0xfe, + 0xcb, 0x67, 0xab, 0x42, 0xf7, 0xe5, 0x25, 0x16, 0x75, 0xb7, 0x9b, 0x77, 0xd7, 0xfa, 0x91, 0x9a, 0x38, 0x5f, 0x5f, + 0x67, 0x65, 0x11, 0xe0, 0xfd, 0xca, 0x12, 0xac, 0x14, 0xaa, 0xdd, 0xe7, 0xfc, 0x1a, 0xc0, 0x60, 0x5e, 0x9f, 0x85, + 0x0c, 0x2a, 0xfd, 0x5d, 0xa0, 0x5d, 0xa2, 0xe0, 0x41, 0x2b, 0xf2, 0xeb, 0x31, 0xfc, 0xb9, 0x39, 0xfc, 0x9d, 0xe0, + 0x6b, 0xff, 0x44, 0x7a, 0x79, 0x59, 0xa5, 0x38, 0xda, 0x4d, 0xe1, 0x02, 0x85, 0xe1, 0x4a, 0x89, 0x56, 0x3c, 0x82, + 0x0e, 0x1a, 0xc8, 0x03, 0x9a, 0x24, 0xbd, 0x7c, 0x0d, 0xb7, 0x26, 0x1d, 0x5d, 0x71, 0xe3, 0xe0, 0xbd, 0x47, 0x38, + 0x40, 0x17, 0xcd, 0x59, 0xc9, 0x4e, 0x57, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0xe2, 0xf4, 0x52, 0x5b, 0x9b, + 0x27, 0xca, 0x0d, 0x13, 0x2c, 0x93, 0xb6, 0x76, 0xcf, 0x34, 0x90, 0x8e, 0x9d, 0x0f, 0x12, 0x5f, 0xb2, 0x32, 0xad, + 0xad, 0x7b, 0xe9, 0xea, 0x02, 0x3b, 0xa2, 0x62, 0x3f, 0xd7, 0x61, 0x7a, 0xfd, 0x30, 0xc6, 0xb7, 0x59, 0xa0, 0x2e, + 0x9c, 0xc5, 0x3f, 0x5a, 0x25, 0x58, 0xb4, 0x16, 0xeb, 0xf4, 0x81, 0x9b, 0x50, 0x50, 0x7e, 0x91, 0x40, 0x96, 0x15, + 0xff, 0x0c, 0x73, 0x82, 0x95, 0xc6, 0x54, 0xfe, 0x65, 0x44, 0xdf, 0x52, 0xfd, 0x0f, 0xe2, 0x54, 0x0c, 0x52, 0x24, + 0x61, 0x28, 0x6b, 0x11, 0xfe, 0x3f, 0xdf, 0xfa, 0x77, 0xc3, 0xb7, 0xee, 0x1f, 0xa2, 0x71, 0x00, 0xfb, 0x8b, 0x17, + 0xf2, 0xdf, 0x37, 0xbb, 0xe3, 0x92, 0xdd, 0xfd, 0x0a, 0x46, 0xc7, 0xff, 0x31, 0x8c, 0x4e, 0xda, 0xc8, 0x86, 0xd3, + 0xe9, 0x8b, 0x77, 0xec, 0xf7, 0xe1, 0x4d, 0x78, 0x57, 0xef, 0xab, 0xf4, 0xf2, 0xf8, 0x26, 0xbc, 0xab, 0x17, 0x61, + 0x33, 0xbb, 0x58, 0xee, 0x63, 0xe8, 0xbe, 0x7d, 0xe3, 0x06, 0xee, 0xdb, 0xaf, 0xbf, 0x76, 0xf1, 0x65, 0x41, 0xc5, + 0x10, 0x0a, 0xc9, 0xf6, 0x7c, 0x6b, 0xb9, 0x22, 0xb8, 0x51, 0x60, 0x8a, 0x32, 0xd4, 0x86, 0x8b, 0x06, 0x30, 0xac, + 0xb8, 0xc8, 0x33, 0x1b, 0x9a, 0x77, 0x60, 0xd9, 0x7f, 0x29, 0x38, 0xb2, 0x97, 0x15, 0x78, 0x64, 0xe9, 0x32, 0x40, + 0xb2, 0xb0, 0x01, 0x51, 0x7d, 0x1f, 0xd1, 0xfd, 0xfc, 0xbf, 0xbe, 0x73, 0x41, 0x5d, 0x25, 0x12, 0x0d, 0xd3, 0xcb, + 0x2f, 0x11, 0x1f, 0x6a, 0xb0, 0xda, 0x63, 0x67, 0xdc, 0x9d, 0x61, 0xb9, 0x3d, 0x8f, 0x76, 0x76, 0xd8, 0xd0, 0xc5, + 0xf2, 0x12, 0xa8, 0x72, 0x9d, 0x70, 0xe1, 0xf0, 0x27, 0x87, 0x3f, 0x45, 0xcd, 0xa8, 0x59, 0x36, 0xe2, 0x21, 0xa7, + 0xf1, 0x66, 0x26, 0x5d, 0x5d, 0x9e, 0xa4, 0x49, 0x43, 0x65, 0x77, 0x17, 0x17, 0x32, 0xaf, 0x69, 0xc2, 0x40, 0x1f, + 0xdd, 0xb2, 0x3f, 0x11, 0xa4, 0x6f, 0x5b, 0xab, 0xbe, 0x30, 0x60, 0x23, 0x9c, 0x12, 0x5e, 0x25, 0x52, 0xc0, 0x95, + 0x9d, 0x3a, 0xf5, 0x04, 0xbb, 0x48, 0x7a, 0xdd, 0x63, 0x32, 0x90, 0x39, 0x15, 0xdf, 0x64, 0xc2, 0x8b, 0x7d, 0xc1, + 0xd9, 0xc4, 0x43, 0xb8, 0xdb, 0x41, 0xc8, 0x38, 0x1b, 0x62, 0x32, 0xd8, 0x62, 0xc5, 0x9b, 0xf0, 0x8d, 0x17, 0xcb, + 0x5b, 0xbe, 0xe4, 0x77, 0x81, 0xe0, 0x04, 0xe6, 0xb3, 0xd9, 0x68, 0x44, 0xb9, 0x67, 0x4e, 0x17, 0xfe, 0x7e, 0x1f, + 0x0e, 0x30, 0xc3, 0xdb, 0xe7, 0xa1, 0x08, 0xbf, 0x63, 0xf4, 0xc6, 0x2b, 0x50, 0x3f, 0xaf, 0x6f, 0x7e, 0x8c, 0xf1, + 0x4c, 0x26, 0x2e, 0x14, 0x54, 0x7c, 0x93, 0x89, 0xbd, 0x9e, 0x37, 0xfb, 0xfd, 0x3e, 0x8e, 0xe1, 0x3e, 0x0d, 0x93, + 0x32, 0xae, 0x2e, 0x42, 0xf9, 0xc8, 0x32, 0x71, 0xa8, 0xce, 0x78, 0x16, 0x48, 0xbb, 0x0f, 0xab, 0x74, 0x1b, 0x27, + 0xac, 0x3a, 0x8c, 0xc9, 0x20, 0xd9, 0x25, 0xea, 0xc4, 0xa7, 0xbc, 0xc2, 0xf7, 0x24, 0x09, 0xf9, 0x09, 0x9c, 0x26, + 0x07, 0x40, 0xaf, 0x44, 0x1e, 0x7a, 0x49, 0xf5, 0x99, 0x28, 0xaf, 0xfd, 0xe3, 0x6e, 0x7b, 0x8c, 0x65, 0xc6, 0x4d, + 0x5d, 0xd4, 0x86, 0xa2, 0x0b, 0xbb, 0x88, 0xec, 0x6e, 0xb7, 0x31, 0xec, 0xc1, 0xfe, 0x5a, 0x1f, 0xad, 0x59, 0xba, + 0xd6, 0x0d, 0x0f, 0xa7, 0x55, 0xdc, 0xe0, 0x24, 0xe4, 0x9c, 0x51, 0xee, 0x78, 0x2f, 0x7f, 0x41, 0xc1, 0xbf, 0xfe, + 0xcb, 0xfa, 0xf8, 0x81, 0x0e, 0x19, 0x38, 0x90, 0xb9, 0xd2, 0x92, 0xb9, 0xde, 0xc4, 0x8d, 0x54, 0x43, 0xd7, 0x84, + 0x3b, 0xf6, 0x0e, 0x3b, 0x9d, 0x8e, 0x0e, 0x09, 0x74, 0xd5, 0x4f, 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x90, 0x91, 0x6c, + 0xe2, 0xaa, 0x00, 0xe5, 0x61, 0x67, 0x7a, 0xeb, 0x0e, 0x60, 0x3b, 0x68, 0x28, 0xde, 0xd3, 0x29, 0x0d, 0xc5, 0x17, + 0x8d, 0xcf, 0x65, 0x93, 0x6a, 0xf8, 0xae, 0x19, 0xba, 0x1e, 0x77, 0x69, 0xd0, 0x83, 0xe5, 0x41, 0x3f, 0xb0, 0x89, + 0xbc, 0x17, 0x6a, 0xd3, 0xa8, 0xd2, 0x53, 0xdd, 0x18, 0x53, 0xa8, 0x16, 0xae, 0x23, 0x31, 0x9e, 0xe4, 0x69, 0x4c, + 0x39, 0x71, 0xa9, 0x3f, 0xf6, 0x9d, 0xa7, 0x9d, 0x4e, 0x07, 0xb7, 0xf6, 0x0f, 0x3a, 0x1d, 0x7c, 0xf0, 0xb8, 0x83, + 0x5b, 0xf0, 0xc7, 0xf7, 0xfd, 0x25, 0x18, 0xee, 0x8b, 0xda, 0x76, 0x3b, 0x9c, 0x4e, 0x34, 0x80, 0xf7, 0x86, 0x15, + 0xeb, 0x3d, 0x01, 0xb7, 0x57, 0xeb, 0x7d, 0xaf, 0x24, 0x9b, 0xbe, 0x3d, 0x41, 0xe7, 0xba, 0x4a, 0x7f, 0x61, 0x51, + 0x07, 0x4d, 0xa9, 0xba, 0x55, 0xf0, 0x1b, 0x4d, 0x08, 0x81, 0x73, 0x02, 0x57, 0xa3, 0xca, 0x78, 0x29, 0x64, 0x1e, + 0xc1, 0xd7, 0xd7, 0x44, 0xc8, 0x32, 0xf8, 0x30, 0x97, 0x89, 0x9a, 0x1a, 0x46, 0x55, 0x2c, 0x65, 0xf4, 0x3e, 0x52, + 0x61, 0xe9, 0x75, 0x04, 0x71, 0xfe, 0x08, 0xe1, 0xf0, 0x21, 0x0d, 0xf4, 0x0a, 0x42, 0xfd, 0xe4, 0x21, 0xf5, 0x0d, + 0xf6, 0xcf, 0x1f, 0xc9, 0x44, 0xa8, 0xad, 0x68, 0xb1, 0xd8, 0x0a, 0x17, 0x8b, 0xad, 0xe4, 0xe1, 0x33, 0x54, 0xcb, + 0x6b, 0x8e, 0x58, 0xc0, 0xb5, 0xa2, 0x0a, 0xe8, 0x6f, 0xa0, 0x3c, 0x88, 0xb0, 0x02, 0x49, 0x3d, 0x85, 0x58, 0x0f, + 0xa8, 0x1e, 0x93, 0x72, 0x09, 0x29, 0x31, 0x89, 0x94, 0x7d, 0xbe, 0x58, 0x68, 0xe2, 0xc7, 0x33, 0x12, 0x56, 0x45, + 0x5d, 0x17, 0x4f, 0x49, 0x52, 0x3d, 0xba, 0x12, 0xe4, 0xa9, 0xe6, 0x52, 0x35, 0xc4, 0x37, 0x21, 0xcf, 0x6c, 0x80, + 0xdf, 0xe4, 0x8e, 0x1e, 0xd6, 0x99, 0xf2, 0xfc, 0x9a, 0x41, 0xc2, 0xcd, 0xd2, 0xc0, 0x13, 0x02, 0xb7, 0x8a, 0xf5, + 0xed, 0x50, 0xb8, 0xd5, 0xc1, 0x07, 0xc3, 0x67, 0xe1, 0x0a, 0xcb, 0x6a, 0x82, 0x41, 0xac, 0xe7, 0x16, 0xcc, 0xcc, + 0xb4, 0xde, 0x87, 0x37, 0xc1, 0xd4, 0x3c, 0xbc, 0x50, 0xb9, 0x3d, 0xc1, 0xa4, 0x3a, 0xb6, 0xf3, 0x8e, 0xbc, 0x81, + 0xd8, 0x8f, 0x6b, 0xf8, 0x36, 0x5c, 0xe2, 0xa9, 0x78, 0xdc, 0xfb, 0x57, 0xa7, 0x34, 0xe4, 0x51, 0xf2, 0x2e, 0xe4, + 0xe1, 0xa4, 0xe8, 0x8f, 0xcc, 0x15, 0x61, 0x86, 0x02, 0x2e, 0x46, 0x32, 0xbb, 0x2a, 0x8b, 0xee, 0x5c, 0x1c, 0x23, + 0x5c, 0xbf, 0x57, 0x10, 0x28, 0x3f, 0xb7, 0x8b, 0x67, 0xf6, 0x2b, 0x58, 0x67, 0x17, 0x4f, 0x10, 0x56, 0x49, 0x4b, + 0xef, 0x7e, 0xcb, 0x74, 0x25, 0x0c, 0xf9, 0x35, 0xc1, 0xc8, 0xaf, 0x3f, 0xa1, 0x67, 0x12, 0x98, 0x3e, 0x2c, 0x25, + 0x30, 0xad, 0x41, 0xa3, 0xc3, 0x69, 0x31, 0xcd, 0xb3, 0x82, 0xba, 0xf8, 0x03, 0xb4, 0x53, 0xf7, 0x3c, 0xdb, 0x0d, + 0x57, 0x68, 0xae, 0x6a, 0x2a, 0xdf, 0xa8, 0x76, 0x10, 0xd4, 0xf9, 0xf0, 0x97, 0x2a, 0x8e, 0x6f, 0xe2, 0x3b, 0x32, + 0xcb, 0x9d, 0xd1, 0x0d, 0x89, 0xb8, 0x9c, 0x7e, 0x36, 0x11, 0x37, 0x7d, 0x50, 0x22, 0xae, 0xbc, 0x3e, 0xe5, 0x37, + 0x4d, 0xc4, 0x65, 0xd4, 0x4a, 0xc4, 0x05, 0x39, 0xf7, 0xf5, 0x83, 0xf2, 0x39, 0x4d, 0xf6, 0x5d, 0x7e, 0x53, 0x90, + 0xae, 0x8e, 0x81, 0xa4, 0xf9, 0x18, 0x92, 0x39, 0xff, 0xf1, 0xb9, 0x99, 0x69, 0x3e, 0xb6, 0x33, 0x33, 0xe1, 0xab, + 0x27, 0x40, 0x76, 0x38, 0x27, 0x73, 0xf7, 0xc7, 0xdb, 0xee, 0xb3, 0xb3, 0x6e, 0x7f, 0xaf, 0x3b, 0x71, 0x03, 0x17, + 0x9c, 0x8e, 0xb2, 0xa0, 0xd3, 0xdf, 0xdb, 0x83, 0x82, 0x1b, 0xab, 0xa0, 0x07, 0x05, 0xcc, 0x2a, 0x38, 0x80, 0x82, + 0xc8, 0x2a, 0x78, 0x0c, 0x05, 0xb1, 0x55, 0xf0, 0x04, 0x0a, 0xae, 0xdd, 0xf2, 0x8c, 0x55, 0xd9, 0xc6, 0x4f, 0x90, + 0xbc, 0x1e, 0x71, 0x2b, 0x6f, 0x1e, 0x0d, 0x8f, 0x88, 0xa9, 0xf2, 0xa4, 0xba, 0x56, 0xa2, 0xb5, 0x6f, 0x6e, 0x41, + 0xbc, 0xfc, 0xdd, 0x25, 0xb0, 0xd6, 0x08, 0xae, 0x47, 0x80, 0x98, 0xa4, 0xaa, 0xb9, 0x67, 0x5e, 0xbb, 0x41, 0x95, + 0x92, 0xdb, 0xc1, 0x3d, 0x93, 0x94, 0x1b, 0xb8, 0x48, 0xf2, 0x25, 0xf5, 0xe2, 0x60, 0x37, 0xd6, 0xdd, 0xc2, 0x05, + 0x83, 0xf5, 0xed, 0x9e, 0x7b, 0x08, 0x4f, 0x8c, 0x02, 0x44, 0x3d, 0xf8, 0xba, 0xc3, 0x07, 0x36, 0xa1, 0x66, 0xbf, + 0x98, 0x01, 0x1c, 0x99, 0xb6, 0xdc, 0x8f, 0x6a, 0xc5, 0xe8, 0x1d, 0x1e, 0xd5, 0x17, 0xca, 0x7e, 0x20, 0xea, 0x82, + 0xbe, 0x1c, 0xab, 0x30, 0xd7, 0x14, 0x8b, 0x70, 0x1c, 0x40, 0xda, 0x26, 0x64, 0x8c, 0x04, 0x23, 0x42, 0x48, 0x67, + 0x38, 0x0b, 0xde, 0xe1, 0x9b, 0x84, 0x66, 0xc1, 0xa4, 0xec, 0x57, 0xeb, 0xaf, 0xb2, 0x46, 0x3f, 0x54, 0xb7, 0x90, + 0x4b, 0x9a, 0xa8, 0xdf, 0x2a, 0x28, 0x5b, 0x15, 0xed, 0x6c, 0xc8, 0x33, 0xb4, 0x94, 0x9d, 0x51, 0x9a, 0xdf, 0xb4, + 0x40, 0xdc, 0xaf, 0xcd, 0x3d, 0x84, 0xb9, 0x55, 0xb9, 0x87, 0xaf, 0x00, 0xd6, 0xea, 0xe9, 0x43, 0x38, 0xae, 0x7e, + 0xbf, 0xa6, 0x45, 0x11, 0x8e, 0x75, 0xcd, 0xcd, 0xb9, 0x86, 0x12, 0x44, 0x3b, 0xcf, 0xd0, 0x00, 0x01, 0x09, 0x81, + 0x80, 0x10, 0x08, 0xe8, 0xea, 0xfc, 0x40, 0x98, 0x79, 0x33, 0xb5, 0x50, 0xa2, 0xaa, 0x59, 0x24, 0xc2, 0x71, 0x5d, + 0x70, 0x34, 0xe5, 0x54, 0x27, 0x2d, 0x02, 0x16, 0xcb, 0xa3, 0x36, 0x14, 0xa8, 0xd7, 0x1b, 0x52, 0x08, 0x0d, 0x77, + 0xd9, 0x9c, 0x48, 0xe8, 0x98, 0x14, 0x42, 0xfb, 0xd8, 0x4b, 0x75, 0xe6, 0x65, 0x35, 0x71, 0xed, 0xab, 0x6e, 0x04, + 0xff, 0xe9, 0xb4, 0xb8, 0xaf, 0x46, 0xa3, 0xd1, 0xbd, 0x29, 0x85, 0x5f, 0xc5, 0x23, 0xda, 0xa3, 0x07, 0x7d, 0x38, + 0x12, 0xd1, 0xd2, 0x89, 0x68, 0xdd, 0x52, 0xe2, 0x6e, 0xfe, 0xb0, 0xca, 0x90, 0xb3, 0x26, 0x92, 0xf9, 0xc3, 0xd3, + 0x0b, 0xcb, 0x29, 0xa7, 0xf3, 0x49, 0xc8, 0xc7, 0x2c, 0x0b, 0x3a, 0xa5, 0x7f, 0xad, 0xf3, 0xf1, 0xbe, 0x3a, 0x3c, + 0x3c, 0x2c, 0xfd, 0xd8, 0x3c, 0x75, 0xe2, 0xb8, 0xf4, 0xa3, 0x79, 0x35, 0x8d, 0x4e, 0x67, 0x34, 0x2a, 0x7d, 0x66, + 0x0a, 0xf6, 0x7a, 0x51, 0xbc, 0xd7, 0x2b, 0xfd, 0x1b, 0xab, 0x46, 0xe9, 0x53, 0xfd, 0xc4, 0x69, 0xdc, 0x38, 0x57, + 0xf1, 0xa4, 0xd3, 0x29, 0x7d, 0x45, 0x68, 0x73, 0x88, 0xc9, 0xa9, 0x9f, 0x41, 0x38, 0x13, 0x79, 0x79, 0x59, 0x96, + 0xfd, 0x54, 0x78, 0x67, 0xdb, 0xfa, 0xce, 0x4a, 0xf5, 0x91, 0xc7, 0x12, 0x9d, 0xe3, 0xaf, 0xed, 0xcc, 0x39, 0x20, + 0x66, 0x99, 0x31, 0x97, 0x9a, 0xc4, 0xba, 0xc6, 0x6b, 0xa0, 0x2c, 0xf9, 0xfa, 0x6b, 0x92, 0xd6, 0x09, 0x75, 0xc0, + 0xc7, 0xa0, 0xa6, 0xba, 0x5a, 0x3d, 0xdb, 0x24, 0x3d, 0x8a, 0xcf, 0x4b, 0x8f, 0xab, 0x87, 0x08, 0x8f, 0xe2, 0x37, + 0x17, 0x1e, 0x99, 0x2d, 0x3c, 0x14, 0xeb, 0xb8, 0x11, 0xc4, 0x8d, 0x12, 0x1a, 0x7d, 0xba, 0xca, 0x6f, 0x5b, 0xb0, + 0x25, 0xb8, 0x2b, 0xc5, 0xca, 0xf5, 0xaf, 0x3d, 0x26, 0x60, 0x3a, 0xb3, 0xbe, 0x10, 0x29, 0x75, 0xfc, 0xb7, 0x19, + 0x71, 0xdf, 0x9a, 0xc0, 0x9e, 0x2a, 0x19, 0x8d, 0x88, 0xfb, 0x76, 0x34, 0x72, 0xcd, 0xcd, 0x3b, 0xa1, 0xa0, 0xb2, + 0xd6, 0x9b, 0x46, 0x89, 0xac, 0x05, 0x86, 0x7e, 0x5d, 0x66, 0x17, 0xe8, 0xbc, 0x3b, 0x3b, 0xc7, 0x4e, 0xbf, 0x89, + 0x59, 0x01, 0x5b, 0x0d, 0x3e, 0x5c, 0xd9, 0xbc, 0xf9, 0x3f, 0x6b, 0x7c, 0xa6, 0xa9, 0x02, 0x78, 0xcd, 0xb7, 0xa5, + 0x96, 0xaf, 0x9d, 0x1b, 0x53, 0xa3, 0xe2, 0x3f, 0xbb, 0xfb, 0x26, 0xf6, 0x6e, 0x04, 0x2a, 0x59, 0xf1, 0x36, 0x5b, + 0xba, 0x52, 0x42, 0xc1, 0x48, 0x88, 0x3d, 0xad, 0x52, 0xe4, 0xe3, 0x71, 0x2a, 0x4f, 0xaa, 0x34, 0x0c, 0x6e, 0xd5, + 0x7c, 0xd8, 0x98, 0x6f, 0x60, 0x37, 0xd4, 0xdf, 0xee, 0x90, 0x1f, 0x33, 0x56, 0x47, 0x91, 0xaf, 0xf5, 0x57, 0x6d, + 0x65, 0x4c, 0x70, 0xae, 0x79, 0xfc, 0x5c, 0x1d, 0x60, 0x15, 0x98, 0xc5, 0xaa, 0x39, 0x8b, 0xcb, 0x52, 0x1f, 0xfd, + 0x8f, 0x59, 0x31, 0x05, 0xed, 0x49, 0xb5, 0xa4, 0x9f, 0x63, 0xe1, 0xc5, 0x8d, 0x95, 0xdc, 0xd6, 0x58, 0xae, 0xd2, + 0xd8, 0x69, 0x2a, 0x5b, 0xe8, 0x46, 0x94, 0xae, 0x36, 0xd9, 0x0c, 0x12, 0x5d, 0x47, 0xe1, 0x53, 0xa5, 0xdd, 0x59, + 0x33, 0x84, 0xcc, 0x9f, 0x6a, 0x41, 0xcc, 0x2b, 0x53, 0x50, 0xda, 0x56, 0x96, 0x7c, 0xa3, 0xb0, 0x25, 0x53, 0xc5, + 0x8a, 0x69, 0x98, 0x19, 0x63, 0x4e, 0xf1, 0x83, 0xed, 0x79, 0xbd, 0xf2, 0xa5, 0x6b, 0xc0, 0x56, 0xc4, 0x3b, 0x38, + 0x6a, 0x43, 0x83, 0x81, 0xd3, 0x00, 0x3d, 0x5b, 0xc9, 0x30, 0xbb, 0x3f, 0xd7, 0xfb, 0xd3, 0xa5, 0x5f, 0xdc, 0x60, + 0xbf, 0xb8, 0x71, 0x7e, 0x3f, 0x6f, 0xdd, 0xd0, 0xab, 0x4f, 0x4c, 0xb4, 0x44, 0x38, 0x6d, 0x81, 0xf7, 0x54, 0x66, + 0x86, 0x68, 0xf6, 0x2c, 0x75, 0x74, 0x65, 0xfa, 0xf5, 0x67, 0x05, 0xa4, 0x84, 0x4b, 0x33, 0x2a, 0xc8, 0xf2, 0x8c, + 0xf6, 0x9b, 0x67, 0x03, 0xed, 0x0c, 0x63, 0x83, 0xad, 0xf3, 0x79, 0x0e, 0x29, 0xe4, 0xe2, 0x2e, 0xe8, 0x68, 0xb6, + 0xde, 0x31, 0xe9, 0xc3, 0x9d, 0xb5, 0xf5, 0x03, 0x8d, 0xdc, 0x5d, 0x29, 0xbd, 0xf8, 0x6a, 0x1a, 0xf5, 0xa6, 0x34, + 0xe8, 0xcf, 0x9d, 0x94, 0x83, 0x7c, 0x12, 0xf3, 0xbf, 0x75, 0xc4, 0x70, 0xb9, 0x58, 0x9e, 0x94, 0x7b, 0x08, 0x64, + 0x41, 0x38, 0x12, 0x94, 0xe3, 0x87, 0xd4, 0xbc, 0x92, 0x97, 0x5a, 0xcc, 0x41, 0xcc, 0x04, 0xdd, 0xc3, 0xe9, 0xed, + 0xc3, 0xbb, 0xbf, 0x7f, 0xfa, 0xa5, 0xc6, 0x91, 0xb9, 0xe4, 0xd5, 0x75, 0xfb, 0xb0, 0x11, 0xd2, 0xf0, 0x2e, 0x60, + 0x99, 0x94, 0x79, 0x57, 0x90, 0x14, 0xd2, 0x9f, 0xe6, 0xfa, 0xc8, 0x27, 0xa7, 0xa9, 0xfc, 0xae, 0xbb, 0x5e, 0x8a, + 0xbd, 0xc7, 0xd3, 0x5b, 0xb3, 0x1a, 0xdd, 0xa5, 0xa3, 0x9c, 0xbf, 0xe9, 0x89, 0xcd, 0xcd, 0x47, 0x44, 0x9b, 0xa7, + 0x0e, 0x0f, 0xa6, 0xb7, 0x7d, 0x25, 0x68, 0x5b, 0x5c, 0x41, 0xd5, 0x99, 0xde, 0xda, 0x67, 0x56, 0xeb, 0x8e, 0x1c, + 0x7f, 0xaf, 0x70, 0x68, 0x58, 0xd0, 0x3e, 0x7c, 0xc6, 0x8a, 0x45, 0x61, 0xaa, 0x85, 0xf9, 0x84, 0xc5, 0x71, 0x4a, + 0xfb, 0x46, 0x5e, 0x3b, 0xdd, 0xc7, 0x70, 0xe4, 0xd3, 0x5e, 0xb2, 0xe6, 0xaa, 0x58, 0xc8, 0xab, 0xf0, 0x14, 0x5e, + 0x15, 0x79, 0x0a, 0x1f, 0x91, 0x5c, 0x8b, 0x4e, 0x7d, 0x16, 0xb2, 0x53, 0x23, 0x4f, 0xfe, 0x6e, 0xce, 0xe5, 0xa0, + 0xf3, 0x4f, 0x7d, 0xb9, 0xe0, 0x9d, 0xbe, 0xc8, 0xa7, 0x41, 0x6b, 0xaf, 0x39, 0x11, 0x78, 0x55, 0x4d, 0x01, 0xaf, + 0x99, 0x16, 0x06, 0x69, 0xa5, 0xf8, 0xb4, 0xe3, 0x77, 0x75, 0x99, 0xec, 0x00, 0x8c, 0xd0, 0xaa, 0xa8, 0x6c, 0x4e, + 0xe6, 0x1f, 0xb3, 0x5b, 0x9e, 0xae, 0xdf, 0x2d, 0x4f, 0xcd, 0x6e, 0xb9, 0x9f, 0x62, 0xbf, 0x1a, 0x75, 0xe1, 0xbf, + 0x7e, 0x3d, 0xa1, 0xa0, 0xe3, 0xec, 0x4d, 0x6f, 0x1d, 0xd0, 0xd3, 0x5a, 0xbd, 0xe9, 0xad, 0x3a, 0xb1, 0x0b, 0x89, + 0x6b, 0x1d, 0x38, 0xc3, 0x8a, 0x3b, 0x0e, 0x14, 0xc2, 0xff, 0x9d, 0xc6, 0xab, 0xee, 0x3e, 0xbc, 0x83, 0x56, 0x07, + 0xab, 0xef, 0x7a, 0xf7, 0x6f, 0xda, 0x20, 0xcb, 0x85, 0x17, 0x18, 0x6e, 0x8c, 0x7c, 0x11, 0x5e, 0x5d, 0xd1, 0x38, + 0x18, 0xe5, 0xd1, 0xac, 0xf8, 0x67, 0x0d, 0xbf, 0x46, 0xe2, 0xbd, 0x5b, 0x7a, 0xa9, 0x1f, 0xd3, 0x54, 0x9d, 0x1f, + 0x36, 0x3d, 0xcc, 0xab, 0x75, 0x0a, 0x8a, 0x28, 0x4c, 0xa9, 0xd7, 0xf3, 0xf7, 0xd7, 0x6c, 0x82, 0x7f, 0x93, 0xb5, + 0x59, 0x3b, 0x99, 0xbf, 0x17, 0x19, 0xf7, 0x22, 0xe1, 0x8b, 0x70, 0x60, 0xaf, 0x61, 0xe7, 0x70, 0x3d, 0xb8, 0x67, + 0x66, 0xa4, 0x73, 0x23, 0x14, 0xb4, 0xdc, 0x89, 0xe9, 0x28, 0x9c, 0xa5, 0xe2, 0xfe, 0x5e, 0x37, 0x51, 0xc6, 0x4a, + 0xaf, 0xf7, 0x30, 0xf4, 0xba, 0xee, 0x03, 0xb9, 0xf4, 0x57, 0x4f, 0xf7, 0xe1, 0x3f, 0x75, 0xf8, 0xe5, 0xaa, 0xd6, + 0xd5, 0x95, 0xd5, 0x0b, 0xba, 0xfa, 0x75, 0x43, 0x19, 0x57, 0x22, 0x5c, 0xea, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, + 0x83, 0xaa, 0x6b, 0x2d, 0xeb, 0x8b, 0x6a, 0x7f, 0x59, 0xe7, 0x0f, 0xac, 0x1b, 0x29, 0xcd, 0xb5, 0x59, 0x57, 0x7f, + 0xd7, 0x7e, 0xa5, 0xb2, 0xc1, 0xb8, 0xac, 0x7f, 0x4d, 0xae, 0x2a, 0x13, 0x45, 0xa5, 0xa2, 0x82, 0x95, 0x72, 0xad, + 0xac, 0x94, 0x9c, 0x92, 0xcb, 0xa3, 0xe1, 0xed, 0x24, 0x75, 0xae, 0xd5, 0xe5, 0x3b, 0xc4, 0xed, 0xfa, 0x1d, 0xd7, + 0x91, 0x4e, 0x3a, 0xf8, 0x06, 0x98, 0xfb, 0xf1, 0xc3, 0xd7, 0xad, 0x43, 0x77, 0x08, 0x9a, 0xd6, 0xf5, 0x58, 0x6a, + 0x76, 0xaf, 0xc2, 0x3b, 0xca, 0x2f, 0x7a, 0xda, 0x05, 0xaf, 0xf2, 0xc5, 0x65, 0x99, 0xd3, 0x73, 0x9d, 0xdb, 0x49, + 0x9a, 0x15, 0xc4, 0x4d, 0x84, 0x98, 0x06, 0xed, 0xf6, 0xcd, 0xcd, 0x8d, 0x7f, 0xb3, 0xe7, 0xe7, 0x7c, 0xdc, 0xee, + 0x75, 0x3a, 0x1d, 0xf8, 0x9c, 0x88, 0xeb, 0x5c, 0x33, 0x7a, 0xf3, 0x2c, 0xbf, 0x25, 0x6e, 0xc7, 0xe9, 0x38, 0xdd, + 0xde, 0xa1, 0xd3, 0xed, 0xed, 0xfb, 0x8f, 0x0f, 0xdd, 0xc1, 0xef, 0x1c, 0xe7, 0x28, 0xa6, 0xa3, 0x02, 0x7e, 0x38, + 0xce, 0x91, 0x54, 0xbc, 0xd4, 0x6f, 0xc7, 0xf1, 0xa3, 0xb4, 0x68, 0x75, 0x9d, 0xb9, 0x7e, 0x74, 0x1c, 0xb8, 0xa2, + 0x28, 0x70, 0xbe, 0x1a, 0xf5, 0x46, 0xfb, 0xa3, 0xa7, 0x7d, 0x5d, 0x5c, 0xfe, 0xae, 0x51, 0x1d, 0xab, 0x7f, 0x7b, + 0x56, 0xb3, 0x42, 0xf0, 0xfc, 0x13, 0xd5, 0xae, 0x7d, 0x07, 0x44, 0xcf, 0xda, 0xa6, 0xbd, 0xd5, 0x91, 0xba, 0x87, + 0x57, 0xd1, 0xa8, 0x57, 0x57, 0x97, 0x30, 0xb6, 0x2b, 0x20, 0x8f, 0xda, 0x06, 0xf4, 0x23, 0x1b, 0x4d, 0xdd, 0xd6, + 0x3a, 0x44, 0x75, 0x5d, 0x3d, 0xc7, 0xb1, 0x99, 0xdf, 0x11, 0x9c, 0x88, 0x37, 0xba, 0xaa, 0x84, 0xc0, 0x75, 0x62, + 0xe2, 0xbe, 0xee, 0xf6, 0x0e, 0x71, 0xb7, 0xfb, 0xd8, 0x7f, 0x7c, 0x18, 0x75, 0xf0, 0xbe, 0xbf, 0xdf, 0xda, 0xf3, + 0x1f, 0xe3, 0xc3, 0xd6, 0x21, 0x3e, 0x7c, 0x79, 0x18, 0xb5, 0xf6, 0xfd, 0x7d, 0xdc, 0x69, 0x1d, 0x42, 0x61, 0xeb, + 0xb0, 0x75, 0x78, 0xdd, 0xda, 0x3f, 0x8c, 0x3a, 0xb2, 0xb4, 0xe7, 0x1f, 0x1c, 0xb4, 0xba, 0x1d, 0xff, 0xe0, 0x00, + 0x1f, 0xf8, 0x8f, 0x1f, 0xb7, 0xba, 0x7b, 0xfe, 0xe3, 0xc7, 0xaf, 0x0e, 0x0e, 0xfd, 0x3d, 0x78, 0xb7, 0xb7, 0x17, + 0xed, 0xf9, 0xdd, 0x6e, 0x0b, 0xfe, 0xe0, 0x43, 0xbf, 0xa7, 0x7e, 0x74, 0xbb, 0xfe, 0x5e, 0x17, 0x77, 0xd2, 0x83, + 0x9e, 0xff, 0xf8, 0x29, 0x96, 0x7f, 0x65, 0x35, 0x2c, 0xff, 0x40, 0x37, 0xf8, 0xa9, 0xdf, 0x7b, 0xac, 0x7e, 0xc9, + 0x0e, 0xaf, 0xf7, 0x0f, 0x7f, 0x70, 0xdb, 0x1b, 0xe7, 0xd0, 0x55, 0x73, 0x38, 0x3c, 0xf0, 0xf7, 0xf6, 0xf0, 0x7e, + 0xd7, 0x3f, 0xdc, 0x4b, 0x5a, 0xfb, 0x3d, 0xff, 0xf1, 0x93, 0xa8, 0xd5, 0xf5, 0x9f, 0x3c, 0xc1, 0x9d, 0xd6, 0x9e, + 0xdf, 0xc3, 0x5d, 0x7f, 0x7f, 0x4f, 0xfe, 0xd8, 0xf3, 0x7b, 0xd7, 0x4f, 0x9e, 0xfa, 0x8f, 0x0f, 0x92, 0xc7, 0xfe, + 0xfe, 0x77, 0xfb, 0x87, 0x7e, 0x6f, 0x2f, 0xd9, 0x7b, 0xec, 0xf7, 0x9e, 0x5c, 0x3f, 0xf6, 0xf7, 0x93, 0x56, 0xef, + 0xf1, 0xbd, 0x2d, 0xbb, 0x3d, 0x1f, 0x70, 0x24, 0x5f, 0xc3, 0x0b, 0xac, 0x5f, 0xc0, 0xff, 0x89, 0x6c, 0xfb, 0x6f, + 0xd8, 0x4d, 0xb1, 0xda, 0xf4, 0xa9, 0x7f, 0xf8, 0x24, 0x52, 0xd5, 0xa1, 0xa0, 0x65, 0x6a, 0x40, 0x93, 0xeb, 0x96, + 0x1a, 0x56, 0x76, 0xd7, 0x32, 0x1d, 0x99, 0xff, 0xf5, 0x60, 0xd7, 0x2d, 0x18, 0x58, 0x8d, 0xfb, 0xff, 0xb4, 0x9f, + 0x6a, 0xc9, 0x8f, 0xda, 0x63, 0x45, 0xfa, 0xe3, 0xc1, 0xef, 0xd4, 0xb7, 0x82, 0x7e, 0x77, 0x89, 0xc3, 0x4d, 0x8e, + 0x8f, 0xf4, 0xf3, 0x8e, 0x8f, 0x84, 0x3e, 0xc4, 0xf3, 0x91, 0xfe, 0xe6, 0x9e, 0x8f, 0x70, 0xd9, 0x6d, 0x7e, 0x2b, + 0x56, 0x1c, 0x1c, 0xcb, 0x56, 0xf1, 0x37, 0xc2, 0x3b, 0xcb, 0xe1, 0xbb, 0xd4, 0x65, 0xff, 0x56, 0x90, 0x84, 0xda, + 0x7e, 0xa0, 0x1c, 0x58, 0xec, 0xad, 0x50, 0x3c, 0x36, 0xda, 0x84, 0x90, 0xf8, 0xf3, 0x08, 0xf9, 0xfe, 0x21, 0xf8, + 0x88, 0x7f, 0x73, 0x7c, 0x44, 0x36, 0x3e, 0x1a, 0x9e, 0x7c, 0xe9, 0x69, 0x90, 0x9e, 0x82, 0x53, 0xf9, 0xec, 0xc1, + 0x95, 0x1c, 0xbb, 0x6e, 0x9b, 0x5e, 0xcb, 0xc8, 0x9d, 0x0a, 0xae, 0xbf, 0xfc, 0x92, 0xa0, 0x83, 0xba, 0x7f, 0x87, + 0xb8, 0xda, 0x2d, 0x33, 0x95, 0x52, 0x47, 0x3f, 0x54, 0x42, 0xa9, 0xe7, 0x77, 0xfc, 0x4e, 0xe5, 0xd2, 0x81, 0x3b, + 0x97, 0xc8, 0x3c, 0x17, 0x61, 0xb0, 0xd5, 0xc5, 0x69, 0x3e, 0x86, 0x9b, 0x98, 0xe4, 0xb7, 0xe9, 0xe0, 0xc4, 0x43, + 0xa4, 0x3e, 0x0b, 0x08, 0xe9, 0x13, 0xda, 0xd1, 0x13, 0xf2, 0x4f, 0x7f, 0x86, 0x20, 0xa6, 0x89, 0x49, 0x4c, 0xc0, + 0xdb, 0xf1, 0x9a, 0xc6, 0x2c, 0xf4, 0x5c, 0x6f, 0xca, 0xe9, 0x88, 0xf2, 0xa2, 0xd5, 0xb8, 0x0c, 0x48, 0xde, 0x03, + 0x84, 0x5c, 0x0d, 0xe1, 0x88, 0xc3, 0xb7, 0x96, 0xc8, 0x99, 0xf6, 0x37, 0xba, 0xda, 0x00, 0x73, 0x4b, 0x6c, 0x4a, + 0x38, 0xc8, 0xda, 0x5a, 0x69, 0x73, 0x95, 0xd6, 0xd6, 0xf5, 0x7b, 0x07, 0xc8, 0x91, 0xc5, 0xf0, 0x15, 0x9b, 0xbf, + 0x7a, 0xad, 0xbd, 0xce, 0x3f, 0x21, 0xab, 0x59, 0xd5, 0xd1, 0xb9, 0x76, 0xb7, 0x65, 0xd5, 0xb7, 0x0e, 0x97, 0xc2, + 0xae, 0xae, 0xa2, 0x88, 0xaf, 0xd4, 0xdc, 0x5d, 0xd4, 0xcf, 0x74, 0xd2, 0x9c, 0xba, 0x6f, 0x70, 0xc4, 0xc6, 0x9e, + 0x75, 0x97, 0x45, 0xa6, 0xbe, 0x92, 0x03, 0x57, 0xe1, 0x23, 0x54, 0xd6, 0x55, 0x32, 0x34, 0x97, 0xd1, 0x16, 0x96, + 0x39, 0xd9, 0x62, 0xe1, 0x65, 0xe0, 0x22, 0x27, 0x16, 0x4e, 0xe1, 0x19, 0x35, 0x90, 0x9c, 0xe1, 0x0a, 0x20, 0x89, + 0x60, 0x92, 0xa9, 0x7f, 0xeb, 0x62, 0xf3, 0x43, 0x3b, 0xbe, 0xfc, 0x34, 0xcc, 0xc6, 0x40, 0x85, 0x61, 0x36, 0x5e, + 0x71, 0xab, 0xa9, 0x80, 0xd1, 0x52, 0x69, 0xdd, 0x55, 0xed, 0x3e, 0x2b, 0x9e, 0xdd, 0x7d, 0xd0, 0xd7, 0x69, 0xbb, + 0xe0, 0x9d, 0x96, 0xf1, 0x8d, 0xfa, 0xd3, 0x3f, 0xbb, 0xe4, 0xd1, 0xd1, 0x84, 0x8a, 0x50, 0x1d, 0x56, 0x03, 0x7d, + 0x02, 0x72, 0x59, 0x1c, 0x6d, 0x8d, 0xea, 0xa0, 0x3e, 0x51, 0x17, 0x08, 0x28, 0x51, 0x8f, 0x1d, 0x7d, 0x0f, 0x5d, + 0x4b, 0x2e, 0x0d, 0xe9, 0x62, 0xe5, 0x8f, 0x89, 0x42, 0x79, 0x1c, 0x99, 0x64, 0xb9, 0x3b, 0x78, 0x54, 0xe5, 0xba, + 0x6c, 0x5a, 0x84, 0x94, 0x65, 0x9f, 0xce, 0x38, 0x4d, 0xff, 0x99, 0x3c, 0x62, 0x51, 0x9e, 0x3d, 0x3a, 0x77, 0x51, + 0x5f, 0xf8, 0x09, 0xa7, 0x23, 0xf2, 0x08, 0x64, 0x7c, 0x20, 0xad, 0x0f, 0x60, 0x84, 0xbb, 0xb7, 0x93, 0x14, 0x4b, + 0x8d, 0xe9, 0x01, 0x0a, 0x91, 0x02, 0xd7, 0xed, 0x1d, 0xb8, 0x8e, 0xb2, 0x89, 0xe5, 0xef, 0x81, 0x12, 0xa7, 0x52, + 0x09, 0x70, 0xba, 0x3d, 0xff, 0x20, 0xe9, 0xf9, 0x4f, 0xaf, 0x9f, 0xf8, 0x87, 0x49, 0xf7, 0xc9, 0x75, 0x0b, 0xfe, + 0xed, 0xf9, 0x4f, 0xd3, 0x56, 0xcf, 0x7f, 0x0a, 0xff, 0x7f, 0xb7, 0xef, 0x1f, 0x24, 0xad, 0xae, 0x7f, 0x78, 0xbd, + 0xe7, 0xef, 0xbd, 0xea, 0xf6, 0xfc, 0x3d, 0xa7, 0xeb, 0xa8, 0x76, 0xc0, 0xae, 0x15, 0x77, 0x7e, 0xb4, 0xb4, 0x21, + 0xd6, 0x04, 0xe3, 0xd4, 0x81, 0x3b, 0x17, 0xcb, 0x33, 0xd2, 0xf6, 0xfe, 0xd4, 0xce, 0xba, 0xe7, 0x21, 0x87, 0xcf, + 0xa6, 0x36, 0xf7, 0x6e, 0xe3, 0x1d, 0x6e, 0xf0, 0x8b, 0x35, 0x43, 0x4c, 0x65, 0x04, 0xdc, 0xbe, 0xc8, 0x0d, 0x6e, + 0x41, 0x93, 0x5f, 0x99, 0x32, 0x97, 0xed, 0x6f, 0x26, 0x6d, 0x55, 0xd1, 0x5c, 0xe8, 0x2f, 0x99, 0x05, 0x93, 0xdf, + 0xf3, 0x93, 0x83, 0x7c, 0x13, 0x97, 0xcb, 0xe3, 0xc3, 0xb9, 0x3f, 0x9e, 0x5b, 0x77, 0xd9, 0xd1, 0x3a, 0xc8, 0x1f, + 0x33, 0xb8, 0x7d, 0xb0, 0x2c, 0x0d, 0xe8, 0x0d, 0x37, 0x6d, 0x8d, 0x25, 0xc9, 0x2f, 0x68, 0x31, 0x74, 0xa1, 0xc8, + 0x0d, 0x5c, 0xe9, 0xe2, 0x73, 0xab, 0x4f, 0xc7, 0x56, 0x84, 0x5d, 0x17, 0x60, 0x79, 0xe3, 0x04, 0xec, 0x5a, 0xc0, + 0x8f, 0x8b, 0x76, 0x76, 0x36, 0xee, 0x17, 0xa9, 0x40, 0xc2, 0x5c, 0xeb, 0x2f, 0x4e, 0xda, 0xac, 0xc8, 0xb5, 0x11, + 0x5d, 0xf5, 0x2b, 0x51, 0x88, 0x34, 0x9e, 0xae, 0x68, 0x28, 0xfc, 0x30, 0x53, 0x27, 0x08, 0x2c, 0x86, 0x85, 0xbb, + 0x74, 0x0f, 0x95, 0xb9, 0x08, 0x55, 0x52, 0x98, 0xbd, 0xcf, 0x73, 0x11, 0x9a, 0x9b, 0x99, 0x42, 0xd1, 0x38, 0x38, + 0x9f, 0xf4, 0x06, 0x6f, 0x3f, 0x1c, 0x3b, 0x6a, 0x7b, 0x1e, 0xb5, 0x93, 0xde, 0xe0, 0x48, 0xfa, 0x4c, 0x54, 0xd8, + 0x9f, 0xa8, 0xb0, 0xbf, 0xa3, 0x2f, 0xa6, 0x81, 0x48, 0x5a, 0xd9, 0x56, 0xd3, 0x96, 0x36, 0x83, 0xf2, 0xf6, 0x4e, + 0x66, 0xa9, 0x60, 0xf0, 0xc5, 0xa4, 0xb6, 0x8c, 0xf9, 0xcb, 0x1c, 0x02, 0x73, 0x08, 0x55, 0x6b, 0x87, 0x57, 0x22, + 0x33, 0xbe, 0xe1, 0x11, 0x4b, 0xa9, 0x39, 0x76, 0xaa, 0xbb, 0xaa, 0x12, 0x7e, 0x56, 0x6b, 0x17, 0xb3, 0x2b, 0x48, + 0x7a, 0x30, 0xe9, 0x45, 0x1f, 0x75, 0x83, 0x23, 0x39, 0x14, 0x44, 0xee, 0x95, 0x98, 0x36, 0xdf, 0x86, 0x6d, 0x2e, + 0xa9, 0x9e, 0xbd, 0x96, 0x10, 0x70, 0x3d, 0x48, 0xb2, 0x37, 0xa8, 0xdc, 0xc5, 0xf6, 0xbb, 0xf2, 0xa8, 0x9d, 0xec, + 0x0d, 0x2e, 0x83, 0xb1, 0xee, 0xef, 0x55, 0x3e, 0x5e, 0xdf, 0x57, 0x9a, 0x8f, 0x87, 0xf2, 0x1c, 0xbc, 0xba, 0x30, + 0xca, 0x28, 0xbf, 0x79, 0xea, 0x0e, 0x8e, 0xb4, 0x32, 0xe0, 0xc8, 0xb0, 0xba, 0x7b, 0xd0, 0x31, 0x47, 0xeb, 0xd3, + 0x7c, 0x0c, 0x1b, 0x52, 0x35, 0xb1, 0x06, 0x69, 0x78, 0xdc, 0x93, 0xee, 0xe0, 0x28, 0x74, 0x24, 0x6f, 0x91, 0xcc, + 0xa3, 0x08, 0xda, 0xd0, 0x38, 0xc9, 0x27, 0xd4, 0x67, 0x79, 0xfb, 0x86, 0x5e, 0xb5, 0xc2, 0x29, 0xab, 0xdd, 0xdb, + 0xa0, 0x74, 0x54, 0x43, 0xe6, 0x4b, 0x29, 0x56, 0xbd, 0xda, 0xdd, 0xb6, 0x0f, 0x36, 0x8f, 0x71, 0xcd, 0x49, 0x9f, + 0x9c, 0x05, 0x56, 0x3e, 0x38, 0x6a, 0x87, 0x4b, 0x18, 0x91, 0xfc, 0xbe, 0xd4, 0x8e, 0x76, 0x30, 0x6c, 0xae, 0x64, + 0x7e, 0x97, 0x12, 0x07, 0xc6, 0x21, 0xaf, 0x05, 0x75, 0xe9, 0x0e, 0xfe, 0xd7, 0x7f, 0xfb, 0x1f, 0xda, 0xc7, 0x7e, + 0xd4, 0x4e, 0xba, 0xa6, 0xaf, 0xa5, 0x55, 0x29, 0x8f, 0xe0, 0x72, 0x9c, 0x3a, 0x28, 0x4c, 0x6f, 0x5b, 0x63, 0xce, + 0xe2, 0x56, 0x12, 0xa6, 0x23, 0x77, 0xb0, 0x19, 0x9b, 0x2a, 0xff, 0xb0, 0x65, 0xc2, 0xa9, 0xab, 0x45, 0x40, 0xaf, + 0xbf, 0xea, 0xd6, 0x05, 0x93, 0xd2, 0x25, 0xb7, 0xb6, 0x7d, 0x07, 0x43, 0xbd, 0xfb, 0x1a, 0xf7, 0x30, 0x64, 0xfa, + 0x83, 0xd3, 0x9a, 0x03, 0x66, 0x8d, 0xeb, 0x17, 0x4a, 0xd7, 0xa9, 0x82, 0x5a, 0xff, 0xe7, 0xbf, 0xff, 0xa7, 0xff, + 0x62, 0x1e, 0x21, 0x56, 0xf5, 0xbf, 0xfe, 0xeb, 0x7f, 0xfc, 0xdf, 0xff, 0xf3, 0x3f, 0x43, 0xfe, 0x99, 0x8e, 0x67, + 0x49, 0xa6, 0xe2, 0xd4, 0xc1, 0x2c, 0xc5, 0x5d, 0x1c, 0x38, 0xd5, 0x36, 0x61, 0x85, 0x60, 0x51, 0xf3, 0x42, 0x86, + 0x53, 0x39, 0xa0, 0xdc, 0x99, 0x1a, 0x3a, 0xb9, 0xc3, 0xcb, 0x9a, 0xa0, 0x1a, 0x28, 0x97, 0x84, 0x5b, 0x1e, 0xb5, + 0x01, 0xdf, 0x0f, 0xbb, 0xc3, 0xc6, 0xaf, 0x96, 0x63, 0x6e, 0xc8, 0x04, 0x4a, 0xca, 0xba, 0xdc, 0x81, 0xd8, 0xca, + 0x1c, 0x1e, 0x83, 0x9e, 0x55, 0x2c, 0x57, 0xaf, 0xd1, 0xa6, 0xff, 0xd3, 0xac, 0x10, 0x6c, 0x04, 0x28, 0x57, 0x7e, + 0x62, 0x19, 0xc6, 0x6e, 0x81, 0xae, 0x98, 0xde, 0x95, 0xb2, 0x17, 0x45, 0xa0, 0xfb, 0x87, 0xff, 0x54, 0xfe, 0x61, + 0x02, 0x1a, 0x99, 0xe3, 0x4d, 0xc2, 0x5b, 0x6d, 0x9e, 0x3f, 0xee, 0x74, 0xa6, 0xb7, 0x68, 0x5e, 0x8f, 0x80, 0x37, + 0x0d, 0x26, 0xe9, 0xd8, 0xee, 0x50, 0xc6, 0xbf, 0x2b, 0x37, 0x76, 0xc7, 0x01, 0x5f, 0xb8, 0xd3, 0x29, 0xcb, 0xdf, + 0xcf, 0xa5, 0x27, 0x95, 0xfd, 0x02, 0x71, 0x6a, 0xed, 0x74, 0xbe, 0xca, 0xed, 0xc9, 0xcd, 0xad, 0x56, 0x3d, 0xd5, + 0x2a, 0xe9, 0xae, 0x5e, 0xcd, 0x62, 0xc7, 0xd9, 0xed, 0x08, 0xf9, 0x3e, 0xc4, 0xbc, 0x93, 0x2e, 0x4e, 0x7a, 0xf3, + 0xaa, 0x7b, 0x21, 0xf2, 0x89, 0x1d, 0x58, 0xa7, 0x21, 0x8d, 0xe8, 0xc8, 0x38, 0xeb, 0xf5, 0x7b, 0x15, 0x34, 0x2f, + 0x93, 0xbd, 0x35, 0x63, 0x69, 0x90, 0x64, 0x40, 0xdd, 0xe9, 0x94, 0x5f, 0xc1, 0x0e, 0x9c, 0x8f, 0xd2, 0x3c, 0x14, + 0x81, 0x24, 0xd8, 0xbe, 0x1d, 0x9e, 0x0f, 0x81, 0x27, 0xe5, 0x73, 0x0b, 0x9e, 0xbe, 0xaa, 0x0a, 0x6e, 0xf3, 0xe6, + 0x05, 0x3a, 0xa5, 0x2f, 0x9b, 0xdb, 0x5d, 0x29, 0xaf, 0xdb, 0xf7, 0x3a, 0xea, 0xfd, 0xb2, 0xe1, 0xae, 0xd2, 0x02, + 0xa9, 0x87, 0xd6, 0xbf, 0x57, 0x72, 0x5d, 0xbd, 0xfd, 0x8b, 0xf0, 0x5c, 0x09, 0xa6, 0xbb, 0x5c, 0x4b, 0x16, 0x42, + 0xad, 0x97, 0xe4, 0xfb, 0xca, 0x64, 0x0a, 0xa7, 0x53, 0x59, 0x11, 0xf5, 0x8f, 0xda, 0x4a, 0xd3, 0x05, 0xee, 0x21, + 0x53, 0x3a, 0x54, 0x06, 0x85, 0xae, 0xa4, 0xb7, 0x82, 0xfa, 0xa5, 0x73, 0x2b, 0xe0, 0x43, 0xe4, 0x83, 0xff, 0x0b, + 0x64, 0xce, 0x91, 0xa6, 0x21, 0x98, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0xc8, 0x90, 0x11, 0x55, 0xb5, 0x2b, 0x2a, 0x8a, 0xaa, 0x55, 0x0f, 0xd0, 0x7a, 0xc0, 0x36, 0x66, 0x21, 0xff, - 0x0b, 0x0b, 0xa3, 0x01, 0x85, 0xcd, 0xc9, 0x64, 0x39, 0xe4, 0x0c, 0x83, 0xa7, 0x5a, 0x3d, 0x8d, 0x21, 0xe6, 0xfa, - 0x1a, 0xa7, 0xef, 0x35, 0x45, 0xd8, 0xd0, 0xc6, 0x30, 0x0a, 0x7e, 0xe2, 0x70, 0x81, 0x7e, 0xd3, 0x30, 0x8a, 0xf7, - 0x08, 0x8d, 0x7d, 0x92, 0xbb, 0x98, 0x33, 0xdf, 0xfb, 0xfc, 0x16, 0x8f, 0x9c, 0x41, 0x68, 0x88, 0x3d, 0x00, 0xca, - 0xb9, 0x8e, 0x1a, 0xab, 0x60, 0xf5, 0x24, 0xe5, 0x28, 0x3b, 0xbf, 0xca, 0x5f, 0xd9, 0x7d, 0x2e, 0xa7, 0xea, 0x32, - 0x41, 0xe7, 0x1b, 0x9e, 0x44, 0xdb, 0xde, 0x6f, 0x16, 0xa9, 0xda, 0xef, 0xbf, 0xbd, 0x27, 0x46, 0x81, 0x70, 0x53, - 0x66, 0x14, 0x4b, 0xb4, 0x26, 0x10, 0xf3, 0x21, 0x4a, 0xe9, 0xc3, 0xed, 0xb0, 0xff, 0xab, 0x2d, 0xff, 0xfb, 0x34, - 0xd5, 0x70, 0xe3, 0xc3, 0xc8, 0x07, 0x19, 0x24, 0xc3, 0x64, 0x31, 0x73, 0x3d, 0x59, 0x96, 0x9d, 0xcc, 0xc3, 0xc2, - 0x08, 0xa3, 0xc4, 0xc8, 0x7e, 0xd2, 0x65, 0x49, 0x64, 0xf7, 0xcd, 0xab, 0xca, 0x5f, 0x54, 0xdf, 0x32, 0x4d, 0xad, - 0xda, 0xc8, 0xf9, 0x38, 0xb8, 0xd1, 0xa2, 0x3f, 0x6a, 0x2c, 0xa4, 0xa8, 0x53, 0x5e, 0x0e, 0x10, 0x01, 0xd2, 0x16, - 0xf3, 0x90, 0x7e, 0x26, 0xbf, 0xd6, 0x2f, 0xfd, 0xb1, 0xaa, 0x36, 0xe0, 0x19, 0x76, 0xdf, 0xac, 0xc4, 0x3e, 0xea, - 0xb5, 0xdc, 0x95, 0xb8, 0x04, 0x4e, 0xbe, 0x4e, 0xce, 0xe4, 0x7c, 0x20, 0x3a, 0x9d, 0x2e, 0xad, 0x20, 0x81, 0xd4, - 0x2a, 0xc0, 0x47, 0xd8, 0x60, 0x9b, 0x3b, 0x34, 0xb2, 0xff, 0xdf, 0x54, 0x3f, 0xdb, 0x01, 0x18, 0x36, 0xa5, 0xa2, - 0xb2, 0x73, 0x1b, 0x92, 0x3a, 0x88, 0x4b, 0x39, 0xe5, 0xa6, 0x70, 0x51, 0x72, 0xee, 0xbd, 0xef, 0xdd, 0xd5, 0x24, - 0x7c, 0x61, 0x06, 0xc4, 0x7e, 0x24, 0x7d, 0x01, 0x04, 0x69, 0xe6, 0x23, 0x26, 0x85, 0xf4, 0xde, 0x9b, 0x01, 0x38, - 0x03, 0x50, 0x5a, 0x80, 0x94, 0x56, 0x71, 0xcf, 0xa1, 0x48, 0xf9, 0x6f, 0x48, 0x49, 0x5e, 0x87, 0x94, 0xaa, 0x26, - 0xe4, 0xce, 0xa7, 0x8f, 0x55, 0xb9, 0xa9, 0x68, 0xdc, 0xb9, 0x74, 0x6b, 0xa7, 0x43, 0x13, 0xe7, 0xec, 0xce, 0x93, - 0x52, 0xd8, 0x63, 0xa8, 0xb5, 0x3a, 0x6f, 0xfe, 0xb7, 0xba, 0x71, 0x46, 0x11, 0x68, 0x7a, 0xdb, 0x50, 0xad, 0xbf, - 0x56, 0x7a, 0xd7, 0x60, 0x86, 0x10, 0x42, 0x13, 0x1c, 0x37, 0x5f, 0xd3, 0x1d, 0x77, 0x77, 0x16, 0xd9, 0xc4, 0x38, - 0xe3, 0x00, 0xf5, 0x14, 0xa4, 0xa1, 0x63, 0x36, 0xdd, 0xac, 0xc6, 0xb9, 0x8d, 0x3c, 0xdf, 0x08, 0x26, 0x6e, 0x0f, - 0x41, 0xb7, 0x86, 0x03, 0x27, 0xd0, 0xc8, 0xf3, 0x4c, 0xfe, 0xe8, 0x03, 0x9b, 0xe3, 0xd7, 0x37, 0x64, 0xd0, 0xcb, - 0x61, 0xad, 0x05, 0xdc, 0x42, 0xb4, 0xbd, 0x0a, 0xca, 0x46, 0x80, 0x9a, 0x55, 0x5f, 0x0f, 0xd9, 0xfb, 0xc6, 0xfb, - 0x6f, 0x77, 0x9f, 0x0d, 0xb1, 0xd2, 0xbf, 0xa7, 0x58, 0xfe, 0x6b, 0x78, 0x6d, 0xd6, 0x25, 0x6b, 0x1d, 0xac, 0x87, - 0x90, 0xf3, 0x30, 0xf1, 0x10, 0x05, 0x6f, 0x61, 0x8e, 0xe3, 0xc6, 0xe3, 0x99, 0x21, 0x63, 0xcb, 0x45, 0xad, 0x07, - 0x66, 0xce, 0xfe, 0xfd, 0xf8, 0x6c, 0x4b, 0x35, 0x38, 0xc7, 0xc5, 0x46, 0xb4, 0xe9, 0x72, 0x49, 0x39, 0xb5, 0xd9, - 0xe5, 0xc8, 0x52, 0xba, 0xfd, 0x77, 0xd7, 0xa6, 0x8a, 0xfb, 0xec, 0xad, 0x6b, 0x39, 0xfc, 0xbc, 0x93, 0x13, 0x25, - 0x10, 0x51, 0xf1, 0x81, 0x22, 0xe5, 0x4a, 0x1d, 0x95, 0xaf, 0x33, 0x95, 0xa5, 0x5f, 0x7e, 0x85, 0x03, 0x41, 0x3c, - 0x20, 0x7a, 0xe3, 0x76, 0xbd, 0x4e, 0x47, 0x66, 0xcc, 0x2b, 0x62, 0x7e, 0xfb, 0xf9, 0xf9, 0x72, 0x61, 0xc0, 0xd7, - 0x10, 0x77, 0x9a, 0xd6, 0x03, 0xd6, 0xed, 0x1b, 0xf7, 0x5f, 0xcb, 0xd9, 0xe5, 0x7e, 0xcb, 0xb6, 0xb6, 0xfc, 0xb9, - 0xe1, 0x31, 0xbd, 0x50, 0x9d, 0xf2, 0x75, 0x1e, 0x16, 0xdc, 0xb4, 0x5b, 0x83, 0xe4, 0xa1, 0x3d, 0x00, 0x9f, 0xab, - 0x66, 0xc4, 0xb7, 0x1b, 0x55, 0x3a, 0xcf, 0x0b, 0x05, 0x89, 0xdb, 0x39, 0x49, 0xeb, 0xf4, 0x0e, 0x55, 0x66, 0x22, - 0x1a, 0xe1, 0x1f, 0x81, 0xac, 0xdc, 0x38, 0xe2, 0x83, 0xa0, 0xd7, 0x43, 0x82, 0x75, 0x84, 0x6a, 0x6a, 0x1e, 0xa5, - 0x0f, 0xef, 0x8d, 0xf5, 0x73, 0xdd, 0x40, 0xfe, 0x9b, 0x19, 0xa2, 0x4c, 0xf8, 0x61, 0xc8, 0x54, 0xb5, 0xdb, 0x76, - 0x21, 0x01, 0x80, 0x2a, 0xd3, 0x11, 0xb3, 0x9e, 0x79, 0x02, 0x9e, 0x0e, 0xe7, 0x32, 0xda, 0x14, 0x78, 0xab, 0x8f, - 0x77, 0xaf, 0x2f, 0x12, 0x87, 0xcb, 0x41, 0xfc, 0x30, 0xac, 0xdd, 0x8a, 0xab, 0xeb, 0x54, 0xc0, 0x17, 0x3b, 0x05, - 0x59, 0x27, 0x05, 0xd2, 0xb2, 0x6b, 0x96, 0x23, 0xf7, 0x20, 0x6f, 0xd8, 0x20, 0xb3, 0xca, 0x7d, 0x2d, 0xdf, 0x7a, - 0xf3, 0x77, 0x2e, 0x0a, 0xa1, 0xc4, 0x5f, 0x1d, 0xb3, 0xad, 0xb1, 0x40, 0x64, 0x48, 0x7f, 0x0f, 0x14, 0x83, 0x13, - 0xb1, 0xc8, 0x2c, 0xcb, 0x14, 0x96, 0x57, 0xc8, 0xa4, 0x6d, 0x5c, 0xaf, 0xc9, 0xb1, 0x15, 0xbd, 0x6a, 0xf0, 0xf0, - 0xf8, 0x25, 0x99, 0x45, 0x0a, 0x19, 0x96, 0x8f, 0x85, 0x91, 0xf2, 0x24, 0xef, 0x43, 0x97, 0xd3, 0x18, 0x3e, 0xc2, - 0xe9, 0xd3, 0x05, 0xa1, 0x2c, 0xc2, 0x94, 0x23, 0x92, 0xbd, 0x8d, 0x8d, 0x66, 0xc7, 0xac, 0x21, 0x84, 0xc9, 0x9f, - 0xf5, 0xaf, 0x73, 0xfc, 0x2b, 0xa6, 0x34, 0x05, 0xb2, 0x04, 0x1f, 0x7e, 0xa9, 0x08, 0x87, 0x08, 0x36, 0xb6, 0x71, - 0x91, 0x3d, 0x43, 0xca, 0x35, 0x90, 0x00, 0x42, 0x15, 0x18, 0xe3, 0xd9, 0x72, 0xee, 0xf8, 0x8c, 0x97, 0xb7, 0x83, - 0xce, 0x36, 0x0a, 0xcb, 0x17, 0x32, 0x8a, 0xd9, 0xd4, 0x0a, 0x28, 0x2f, 0x73, 0xaa, 0xfb, 0x34, 0x9b, 0xb4, 0xbb, - 0x20, 0xeb, 0x0a, 0x21, 0xdf, 0x1b, 0xa1, 0x1a, 0xa3, 0xdd, 0xe1, 0x17, 0x82, 0x5d, 0x99, 0x69, 0x12, 0x35, 0x55, - 0xf8, 0xfd, 0x2f, 0x07, 0x50, 0xf4, 0x2a, 0x1e, 0x57, 0xfa, 0x07, 0xd9, 0x97, 0x32, 0x97, 0x1c, 0xd6, 0xc7, 0xe0, - 0xa5, 0x3a, 0xaf, 0xa6, 0x36, 0x02, 0x05, 0xc4, 0xa8, 0xad, 0x44, 0xf5, 0x37, 0x6b, 0x1a, 0xb0, 0xa3, 0x8c, 0xf5, - 0xd7, 0xe5, 0x08, 0x87, 0x33, 0xd8, 0xe2, 0xd9, 0x52, 0xfe, 0x5a, 0x6f, 0x24, 0x8c, 0x51, 0x9b, 0xa9, 0xf2, 0x82, - 0xf1, 0xed, 0x41, 0x10, 0xd3, 0x68, 0x77, 0x72, 0x06, 0xdf, 0xc8, 0x1d, 0xf5, 0x07, 0xf1, 0x2a, 0xd7, 0x50, 0x0a, - 0x1a, 0x5f, 0x25, 0x90, 0x5b, 0x1b, 0x24, 0x90, 0x06, 0x4b, 0x11, 0x1a, 0xc7, 0x36, 0xc2, 0x3f, 0x2c, 0x55, 0xc1, - 0xbf, 0x1a, 0xcd, 0xf2, 0xed, 0x47, 0xf1, 0xf9, 0xd2, 0x6f, 0x41, 0x8c, 0xcf, 0x2b, 0xf9, 0xc7, 0x56, 0x3a, 0x97, - 0x96, 0x25, 0x83, 0xda, 0x95, 0x25, 0x35, 0x91, 0x8d, 0xe9, 0xe8, 0x7d, 0xa9, 0xa2, 0x05, 0xc4, 0x5a, 0xff, 0xa2, - 0xfa, 0xde, 0xd0, 0x89, 0x26, 0xed, 0x02, 0x1e, 0x29, 0xe8, 0x0e, 0x1e, 0x4c, 0x4f, 0xaf, 0xd6, 0xe6, 0x2d, 0x51, - 0xd4, 0xfe, 0xde, 0x86, 0x3f, 0x4d, 0x53, 0x17, 0x15, 0xf1, 0x25, 0x7b, 0x7e, 0x60, 0x6d, 0xba, 0xdd, 0xd4, 0xa0, - 0xb8, 0xc9, 0x08, 0xb5, 0x1a, 0xae, 0xde, 0x47, 0xac, 0x56, 0x30, 0x5c, 0x12, 0x9e, 0xaa, 0xd9, 0x56, 0x12, 0xbb, - 0x54, 0x50, 0xd6, 0xc7, 0xcd, 0x5d, 0x62, 0xe1, 0xab, 0xc6, 0x64, 0x13, 0x62, 0xf2, 0x9e, 0x20, 0x77, 0x3b, 0x76, - 0x0c, 0x86, 0x05, 0x0f, 0x3c, 0x20, 0x1e, 0xa8, 0xa5, 0x04, 0x03, 0xe3, 0x72, 0xf2, 0x3f, 0xbc, 0xe1, 0xe9, 0xa1, - 0x37, 0x41, 0x22, 0x20, 0xde, 0xa4, 0x2f, 0xf7, 0x0a, 0x82, 0x15, 0x95, 0x15, 0x80, 0x13, 0x35, 0x90, 0xb0, 0x42, - 0x85, 0x81, 0x43, 0xbd, 0x0e, 0xe9, 0xfc, 0x4d, 0xf3, 0xce, 0x0d, 0x18, 0x64, 0x56, 0x2d, 0xa4, 0x5b, 0xd7, 0xe9, - 0x1d, 0xe0, 0x89, 0x82, 0xeb, 0x53, 0x2b, 0x4b, 0x04, 0xe7, 0xa6, 0x97, 0x71, 0x98, 0x22, 0xf7, 0x69, 0x76, 0x9c, - 0x1e, 0x51, 0xd9, 0xdd, 0xae, 0x89, 0x64, 0x98, 0xfc, 0x09, 0xfa, 0xae, 0xd4, 0xdf, 0xe4, 0x54, 0x1b, 0x28, 0x0d, - 0xab, 0xe3, 0xdf, 0xb2, 0x8e, 0x22, 0xc1, 0x1f, 0xc4, 0xdc, 0x40, 0xd8, 0x8b, 0xc1, 0xd4, 0xa5, 0x44, 0x98, 0xd6, - 0x77, 0x05, 0xf6, 0x65, 0x29, 0xc3, 0xc7, 0x86, 0x43, 0xd6, 0xd7, 0x55, 0x9b, 0x1a, 0xe1, 0xeb, 0x09, 0xf9, 0xbc, - 0x77, 0xb2, 0xbe, 0x6e, 0x03, 0x79, 0xac, 0x1c, 0xa6, 0x6f, 0xde, 0x3a, 0x99, 0x2a, 0x70, 0xeb, 0xce, 0x73, 0xd2, - 0xdc, 0x9e, 0xa5, 0xee, 0x3b, 0xb8, 0xc7, 0xcd, 0xa7, 0x95, 0xd3, 0x75, 0x27, 0xaa, 0xd8, 0x78, 0x20, 0x2f, 0x24, - 0xf0, 0x5b, 0x59, 0x4a, 0x6b, 0x41, 0x8d, 0xf8, 0x18, 0xb4, 0xa1, 0xf5, 0x90, 0xe7, 0xd7, 0x33, 0xd4, 0x0c, 0x73, - 0x5a, 0x9c, 0x43, 0x3f, 0x2a, 0x6a, 0x33, 0x20, 0x62, 0xa4, 0x36, 0xa3, 0x3c, 0xaf, 0x82, 0xfb, 0xa5, 0xf5, 0x8f, - 0x98, 0x1b, 0xbe, 0xbe, 0xaf, 0x1f, 0x1a, 0xf3, 0x16, 0xaa, 0x8b, 0xb2, 0x4e, 0x99, 0xf9, 0xc9, 0x21, 0x0b, 0x44, - 0x86, 0x3c, 0x2b, 0xea, 0xe3, 0x7b, 0x6d, 0x05, 0x09, 0xe0, 0x1a, 0x01, 0x3b, 0xee, 0x1e, 0xc4, 0xc6, 0x16, 0x21, - 0x82, 0x0a, 0xed, 0x4e, 0x01, 0x1c, 0x54, 0x90, 0x89, 0x1f, 0xc9, 0xb5, 0xd1, 0x20, 0xaf, 0x5f, 0xa2, 0x1f, 0x2e, - 0x5c, 0x0f, 0xc9, 0xfa, 0x70, 0xc8, 0x20, 0x28, 0xe3, 0x6d, 0xe2, 0x40, 0x82, 0x08, 0x4b, 0x00, 0x3a, 0x36, 0xfe, - 0x4a, 0x25, 0xac, 0x24, 0x3a, 0xe2, 0xae, 0xde, 0x2e, 0x4f, 0x6e, 0x3d, 0x1c, 0xfc, 0x61, 0x95, 0x02, 0xc6, 0xf1, - 0x9e, 0x7f, 0x7e, 0xbf, 0x42, 0x91, 0x82, 0x98, 0x15, 0xc2, 0x21, 0xa7, 0x74, 0x99, 0x88, 0x41, 0xd6, 0x3e, 0xae, - 0x51, 0x73, 0x58, 0xc2, 0x86, 0x88, 0x8a, 0x66, 0xbb, 0x50, 0x2d, 0xea, 0x23, 0xc4, 0xe0, 0x67, 0x33, 0x76, 0xe8, - 0x22, 0x51, 0x49, 0x2b, 0x55, 0x1a, 0xd6, 0xc1, 0x7a, 0x8f, 0x5c, 0x29, 0xf0, 0x41, 0x8d, 0xaf, 0xbe, 0x09, 0x44, - 0xb1, 0x7b, 0x44, 0x6d, 0x17, 0x92, 0xc1, 0xcb, 0x7b, 0xe8, 0x4e, 0xf4, 0xcb, 0x1e, 0x85, 0xac, 0x63, 0x0d, 0xed, - 0x29, 0x4f, 0x64, 0x1e, 0x7b, 0x42, 0x03, 0x25, 0x5a, 0xfe, 0xe8, 0x4c, 0xc9, 0x44, 0x38, 0xcf, 0x3c, 0x1f, 0xae, - 0x2e, 0xf3, 0xd1, 0x87, 0xc7, 0x3c, 0xa4, 0x94, 0x58, 0xf8, 0x84, 0x25, 0x07, 0x74, 0xdd, 0x05, 0x49, 0x01, 0xbc, - 0x6b, 0x8a, 0xa5, 0xfb, 0x51, 0x11, 0x0f, 0x27, 0xeb, 0x69, 0xe6, 0x71, 0xb1, 0x57, 0xaa, 0x38, 0x7a, 0x90, 0x5d, - 0xb8, 0x40, 0xdd, 0xdb, 0x40, 0xd0, 0xb1, 0xc0, 0x2c, 0x81, 0x44, 0x88, 0xf4, 0xde, 0x56, 0xe7, 0x42, 0xc8, 0xeb, - 0x24, 0x33, 0x12, 0x81, 0x5a, 0xe5, 0x6c, 0x02, 0x75, 0xe3, 0x91, 0x22, 0x74, 0x92, 0x92, 0x3c, 0xe1, 0x00, 0xd1, - 0xe3, 0x0a, 0xeb, 0x28, 0x38, 0xc4, 0x75, 0x25, 0x65, 0x4e, 0xfe, 0xcb, 0x94, 0x26, 0x26, 0xbb, 0x72, 0x38, 0x24, - 0x02, 0xa4, 0x74, 0x4b, 0xad, 0x06, 0x9f, 0x45, 0xc4, 0x47, 0x02, 0x30, 0x13, 0x91, 0x28, 0xfc, 0x4b, 0xf7, 0xd2, - 0x33, 0x2f, 0x21, 0xa2, 0x31, 0xd3, 0xa4, 0xb3, 0xe4, 0xed, 0x35, 0xe9, 0xf0, 0x71, 0xa3, 0x93, 0xa8, 0x66, 0xed, - 0x2f, 0xa5, 0x8f, 0x89, 0x2b, 0xf7, 0x8f, 0x02, 0x13, 0x31, 0x9a, 0x9c, 0x53, 0xe9, 0x67, 0x69, 0x71, 0x3e, 0x16, - 0x28, 0x35, 0xaa, 0x2d, 0xbe, 0xbe, 0xad, 0xcf, 0x36, 0x44, 0x9d, 0xb3, 0x4b, 0x1c, 0xf0, 0x74, 0xd5, 0x74, 0xca, - 0x6d, 0x81, 0x0f, 0x2d, 0x93, 0x03, 0x52, 0x74, 0xa7, 0x5d, 0xa2, 0xdb, 0xde, 0x87, 0xe4, 0x30, 0x98, 0xad, 0x80, - 0x03, 0x28, 0xa3, 0x6a, 0x31, 0xb2, 0x1c, 0xc8, 0x62, 0xa9, 0xe4, 0x72, 0x01, 0x40, 0x8b, 0xac, 0x2b, 0xa7, 0x0c, - 0x85, 0xca, 0x69, 0x64, 0x09, 0x07, 0xd5, 0xc6, 0x48, 0xe6, 0x5a, 0x7d, 0x65, 0x08, 0x69, 0xd4, 0x5c, 0x03, 0x73, - 0xa0, 0x50, 0xb3, 0x64, 0xdd, 0x45, 0xa9, 0x56, 0xe1, 0xb9, 0x30, 0x40, 0x9e, 0x3f, 0xae, 0x36, 0xeb, 0x2e, 0x3b, - 0x2f, 0x4e, 0xc5, 0x0b, 0x0a, 0x1b, 0x1e, 0x24, 0xbb, 0x12, 0x27, 0x25, 0x08, 0x9c, 0xa2, 0xa6, 0xb1, 0x57, 0xdc, - 0x7f, 0x25, 0x7f, 0x3f, 0xa4, 0x92, 0x74, 0x2a, 0xa3, 0x18, 0xf1, 0xf4, 0xab, 0x2a, 0xeb, 0x1a, 0x6d, 0x80, 0x94, - 0xbf, 0x77, 0xe9, 0xc8, 0x7a, 0xd3, 0x55, 0x46, 0xaf, 0x4c, 0x9d, 0x55, 0xf8, 0x71, 0x3e, 0x19, 0xd3, 0xe9, 0x8b, - 0xb8, 0xaa, 0x13, 0x47, 0x01, 0x45, 0x20, 0xec, 0xf1, 0xe3, 0x2b, 0xe5, 0xd1, 0x5e, 0x09, 0x58, 0xb2, 0x8d, 0xc1, - 0x9a, 0x54, 0x47, 0x4c, 0x48, 0x5a, 0xde, 0x7d, 0x04, 0xc6, 0x4a, 0x15, 0x45, 0x17, 0xe0, 0xc3, 0x07, 0x94, 0x1e, - 0x14, 0x1a, 0xc7, 0x3c, 0xe5, 0x36, 0x64, 0x98, 0x80, 0x81, 0x1e, 0x07, 0x79, 0x76, 0xfc, 0xc9, 0x55, 0x15, 0xea, - 0x40, 0x3f, 0x2c, 0xd9, 0xd9, 0xb2, 0xb0, 0xbc, 0xca, 0x8e, 0xfd, 0xa7, 0x28, 0xba, 0xae, 0x7b, 0x62, 0x09, 0x47, - 0x7a, 0xdf, 0x8a, 0xdc, 0xc4, 0x82, 0xf3, 0xd5, 0x4a, 0x88, 0xe5, 0x09, 0xc3, 0x00, 0x69, 0x39, 0x66, 0xca, 0x40, - 0x0e, 0x1d, 0x81, 0x91, 0x0c, 0x99, 0x56, 0x77, 0xf8, 0xf4, 0x2d, 0x7e, 0xc0, 0x21, 0x93, 0x94, 0x9c, 0x69, 0x72, - 0xdc, 0x8b, 0x62, 0xb0, 0x2b, 0x43, 0x54, 0x40, 0xe3, 0x6a, 0x3a, 0x85, 0x21, 0x59, 0xea, 0x7d, 0xa5, 0x5b, 0x6a, - 0x3d, 0x82, 0xbb, 0xf3, 0x44, 0x0a, 0x76, 0x40, 0xd5, 0xcb, 0xe8, 0x8c, 0x63, 0x01, 0x84, 0xf4, 0x24, 0xc9, 0x5d, - 0x52, 0x0c, 0xb2, 0x89, 0x14, 0x0a, 0xac, 0x2f, 0x3b, 0x8c, 0x69, 0x31, 0x7d, 0x3f, 0x08, 0x9c, 0x2c, 0x75, 0x49, - 0x04, 0xe9, 0xf3, 0x60, 0x77, 0x49, 0xf1, 0x08, 0x95, 0x8f, 0xbd, 0xfb, 0x59, 0x0a, 0x4a, 0x53, 0x9d, 0xe4, 0x09, - 0x82, 0xf6, 0x1c, 0x18, 0x1d, 0x13, 0x30, 0x1f, 0x48, 0x45, 0x7d, 0x38, 0xad, 0x1e, 0x0b, 0xbb, 0x0f, 0x29, 0xee, - 0xcb, 0xec, 0xe5, 0x2f, 0xe6, 0x73, 0xa4, 0x39, 0x33, 0x74, 0x52, 0xa7, 0x90, 0xcc, 0x66, 0xf9, 0xa5, 0x28, 0x91, - 0xe6, 0xbd, 0xb7, 0x87, 0x23, 0xfd, 0x80, 0xdf, 0x17, 0x82, 0x1b, 0xc0, 0x1c, 0x46, 0xf0, 0x55, 0x17, 0xc5, 0x6e, - 0x96, 0x6d, 0x48, 0xa1, 0xb5, 0xa3, 0x19, 0x2e, 0xd9, 0xee, 0x8d, 0x24, 0x66, 0xad, 0xc8, 0x84, 0x7a, 0xaf, 0x74, - 0x64, 0x6a, 0x3f, 0x2c, 0x61, 0x6b, 0xa5, 0x62, 0x7a, 0x1e, 0xc6, 0xb0, 0x0e, 0x32, 0xc8, 0x08, 0x2a, 0x2b, 0x5c, - 0x30, 0xd4, 0x50, 0x9c, 0x94, 0xf3, 0x06, 0x91, 0xec, 0x1c, 0x4c, 0x27, 0xa6, 0xa1, 0x14, 0x8b, 0x18, 0xd3, 0x43, - 0xb7, 0x79, 0x8f, 0x62, 0x12, 0xf4, 0xfb, 0xb2, 0x3b, 0x9e, 0x3c, 0xc0, 0xcc, 0x04, 0x4e, 0x2d, 0x0d, 0xb2, 0x94, - 0xe1, 0x5c, 0xdb, 0x5f, 0xf1, 0xc3, 0x75, 0x1f, 0x7a, 0x40, 0x74, 0xbf, 0x0f, 0xf2, 0xa1, 0x5e, 0xad, 0x31, 0x18, - 0xe4, 0xb0, 0x50, 0xfa, 0xde, 0x34, 0x84, 0x87, 0x1d, 0x18, 0xcd, 0xc1, 0x32, 0x4c, 0x67, 0x59, 0x4b, 0xae, 0x6c, - 0x55, 0x4d, 0xec, 0x82, 0x6e, 0xd4, 0xba, 0x74, 0xa4, 0x9f, 0x44, 0x2a, 0x76, 0x3d, 0xc7, 0xbd, 0x16, 0xb8, 0xdb, - 0xb6, 0xbc, 0x1c, 0x8b, 0x71, 0x32, 0x23, 0xd2, 0xa8, 0x7e, 0x5a, 0x40, 0x76, 0xac, 0x23, 0x0a, 0x9e, 0x26, 0x23, - 0x1c, 0x06, 0xff, 0x83, 0xcd, 0xad, 0x23, 0xbc, 0x78, 0x2d, 0x74, 0x08, 0xad, 0x6d, 0xb8, 0x6d, 0xe9, 0xee, 0x13, - 0x44, 0xff, 0x5d, 0x27, 0x20, 0x33, 0x81, 0x0a, 0x39, 0x51, 0x1d, 0xe5, 0x54, 0xc5, 0x70, 0xd0, 0xe9, 0xd6, 0x34, - 0x56, 0x69, 0x62, 0xdd, 0xc5, 0x87, 0xe8, 0xd3, 0x0e, 0x48, 0x51, 0x5d, 0x01, 0x93, 0x45, 0xf5, 0x9b, 0x10, 0x80, - 0x8a, 0x2d, 0x33, 0x30, 0x31, 0x2f, 0x67, 0x5a, 0xda, 0xff, 0x2a, 0x2e, 0x59, 0xc5, 0xf2, 0x2f, 0x49, 0xe1, 0xf1, - 0x31, 0x4a, 0x19, 0x58, 0x6b, 0x40, 0xd4, 0xb5, 0x5e, 0xee, 0xd5, 0x45, 0xce, 0xb8, 0xa6, 0xe0, 0xc1, 0xd7, 0xee, - 0x57, 0x75, 0xc3, 0x1f, 0x3f, 0x6a, 0x38, 0xf0, 0x05, 0xa9, 0x46, 0x63, 0x01, 0xe9, 0x7e, 0x17, 0xa3, 0xc2, 0x6c, - 0xbf, 0xac, 0x07, 0x49, 0x22, 0x2a, 0x4f, 0x00, 0x7f, 0x5f, 0xaf, 0x42, 0xb7, 0x06, 0x44, 0xdc, 0x42, 0x1e, 0xcf, - 0x7a, 0x9a, 0xe4, 0x8e, 0x30, 0x45, 0xe2, 0xeb, 0xf7, 0x11, 0xa2, 0x32, 0x99, 0xde, 0xfc, 0x33, 0x6b, 0xc4, 0x29, - 0x4b, 0x60, 0x72, 0x0b, 0x4a, 0xea, 0x1c, 0xf2, 0x28, 0x23, 0x7d, 0xaa, 0x5e, 0xf2, 0x9b, 0x34, 0x07, 0x32, 0x69, - 0x83, 0x4c, 0x11, 0x88, 0x4e, 0x0f, 0xd2, 0x28, 0xfa, 0x20, 0x00, 0xee, 0x20, 0x08, 0xb4, 0x04, 0x81, 0x00, 0x3e, - 0xd2, 0x3b, 0x09, 0x34, 0x21, 0x93, 0xfc, 0x1a, 0x96, 0xa7, 0x2a, 0x95, 0xdb, 0xd4, 0x6e, 0x9c, 0x2d, 0x11, 0x9d, - 0x0a, 0x3a, 0x28, 0x66, 0xa1, 0xdf, 0x1b, 0xbf, 0x25, 0x1d, 0x7a, 0x5f, 0xa2, 0xc2, 0xd8, 0xd3, 0x34, 0xf3, 0x2c, - 0x50, 0xb2, 0x50, 0xf7, 0x7b, 0xb8, 0xff, 0x58, 0x10, 0xde, 0x25, 0x14, 0x64, 0x78, 0xa8, 0x67, 0x8a, 0x14, 0xf7, - 0x70, 0x02, 0x27, 0xe5, 0xc7, 0x8a, 0xcc, 0xde, 0xd7, 0xfc, 0x9e, 0xfe, 0x4c, 0xa0, 0x36, 0xe6, 0x0f, 0x5e, 0x3a, - 0xe6, 0x7c, 0x19, 0x17, 0x18, 0x27, 0x11, 0x07, 0x9a, 0xa2, 0xc0, 0x0e, 0x27, 0x7a, 0xde, 0xf1, 0x62, 0x1d, 0xe2, - 0xae, 0xdc, 0x3c, 0xe8, 0xad, 0xa7, 0x3a, 0x64, 0x5c, 0xcf, 0x44, 0xd6, 0xb6, 0xa8, 0xdf, 0x7f, 0xbf, 0xfa, 0x9e, - 0x1e, 0x5f, 0x8e, 0xe7, 0xa4, 0x4e, 0x51, 0x81, 0x66, 0x5a, 0x78, 0x10, 0xfe, 0x31, 0x99, 0x99, 0xc7, 0xc0, 0x07, - 0x26, 0x63, 0x74, 0xcc, 0xc8, 0x83, 0xf5, 0xb7, 0x82, 0xbc, 0xd8, 0x41, 0x7e, 0xa7, 0x90, 0xfc, 0xe4, 0xc3, 0x0c, - 0x69, 0x44, 0x41, 0x50, 0xa5, 0x3e, 0xa0, 0x50, 0x26, 0x96, 0xfd, 0xf7, 0x96, 0xf6, 0x6d, 0x72, 0x60, 0x12, 0xcb, - 0xe3, 0x6c, 0x31, 0x1e, 0xb3, 0x38, 0xe7, 0x40, 0x7f, 0x2c, 0x59, 0x78, 0x2f, 0x3c, 0x1d, 0xf3, 0xb0, 0x36, 0xf3, - 0xce, 0xc6, 0x04, 0xf0, 0x36, 0xd6, 0x96, 0x7e, 0xc7, 0xcd, 0xfa, 0x71, 0xe8, 0xa0, 0x07, 0xad, 0x3d, 0x74, 0xc0, - 0xca, 0xd3, 0x13, 0x28, 0x8a, 0x6d, 0xc1, 0xd7, 0xdb, 0x3b, 0xac, 0x65, 0x14, 0x3b, 0x64, 0xab, 0xf9, 0xba, 0x2d, - 0xad, 0xc7, 0x28, 0xa9, 0xbf, 0x32, 0xeb, 0x83, 0xb1, 0x7b, 0xf8, 0x01, 0xbb, 0xfa, 0xf5, 0xd5, 0xea, 0x1a, 0x1f, - 0xcf, 0xbb, 0x3a, 0x28, 0x7d, 0xf0, 0x2e, 0x2e, 0x99, 0xcb, 0x4a, 0xcd, 0xe3, 0x2e, 0x45, 0xec, 0x0f, 0x82, 0x67, - 0x11, 0xdd, 0xda, 0x41, 0x1a, 0x7c, 0xbf, 0x14, 0xc1, 0x06, 0xab, 0x7a, 0xa5, 0x15, 0x70, 0xa4, 0xe2, 0xce, 0x3e, - 0x51, 0x88, 0x62, 0xb6, 0x37, 0x10, 0xf1, 0xfc, 0x53, 0xfd, 0xf9, 0x3e, 0xc3, 0x57, 0x05, 0x1f, 0x90, 0x41, 0x86, - 0xcd, 0x86, 0x4b, 0xb6, 0xe2, 0xf2, 0x69, 0x18, 0x90, 0x77, 0x03, 0xbf, 0xf5, 0xdc, 0x5f, 0xc3, 0x7d, 0x64, 0xa9, - 0xe5, 0x5f, 0x20, 0x12, 0x51, 0xf8, 0x8d, 0x62, 0x22, 0xb8, 0x27, 0x08, 0x78, 0x52, 0xc9, 0x10, 0x8b, 0x75, 0xa0, - 0x6b, 0x9c, 0x1e, 0x5e, 0x0f, 0xd3, 0x59, 0x5f, 0x78, 0x9c, 0xbb, 0x36, 0xab, 0xbc, 0xca, 0x75, 0xd7, 0xb6, 0xf6, - 0x6c, 0x89, 0xf8, 0x19, 0x49, 0xac, 0x5a, 0xce, 0xcf, 0x28, 0xb6, 0x0f, 0x98, 0xca, 0xbf, 0x0d, 0xba, 0xb8, 0x23, - 0x4d, 0xae, 0x87, 0xdd, 0xfe, 0xc2, 0x56, 0x55, 0x2c, 0x1e, 0x3f, 0x7a, 0xf3, 0x6e, 0xf3, 0xc5, 0xf5, 0x81, 0x6f, - 0x69, 0x72, 0x69, 0x7f, 0x66, 0x36, 0x49, 0x92, 0xee, 0xe7, 0x64, 0x71, 0xa1, 0x8e, 0x7f, 0x3f, 0xf1, 0x49, 0xc7, - 0xc2, 0x98, 0x97, 0x5d, 0x2d, 0x66, 0x4a, 0x2b, 0xf9, 0x3b, 0xdf, 0xdf, 0x7e, 0xff, 0xec, 0x51, 0x8c, 0x6d, 0xc5, - 0xb9, 0x6d, 0x92, 0x24, 0x79, 0x96, 0x6b, 0xe1, 0x7b, 0x34, 0xd4, 0x47, 0xda, 0xe3, 0xc6, 0xcb, 0x7c, 0x89, 0xc2, - 0x6a, 0xd6, 0x3c, 0x63, 0xb6, 0x7e, 0x5e, 0x7e, 0xf7, 0xd8, 0xd9, 0xe4, 0x7a, 0x13, 0xcb, 0x91, 0xf0, 0x2d, 0xbe, - 0x65, 0x0b, 0x66, 0xba, 0x80, 0xe4, 0x2f, 0xe5, 0xee, 0xf1, 0x5d, 0x71, 0xf9, 0xc3, 0xae, 0x17, 0x66, 0x96, 0x73, - 0x2c, 0x31, 0x96, 0x28, 0x1e, 0xb8, 0x39, 0xdf, 0x81, 0x35, 0x69, 0x72, 0xbe, 0xad, 0x78, 0x8d, 0x73, 0x90, 0xfb, - 0x7b, 0xfa, 0x1f, 0x3f, 0x39, 0xda, 0xdc, 0xc5, 0xc7, 0x11, 0x74, 0x41, 0x62, 0xb7, 0x0b, 0xd6, 0x6e, 0x8a, 0x57, - 0x13, 0xc3, 0x4d, 0x54, 0x95, 0x44, 0x3d, 0x31, 0x1b, 0x01, 0x96, 0x4b, 0x5f, 0x0f, 0x38, 0xd0, 0x4d, 0x27, 0xca, - 0x22, 0xff, 0x6b, 0xec, 0x22, 0x65, 0x40, 0xf8, 0x97, 0x52, 0x48, 0x70, 0xaa, 0xb7, 0x24, 0x25, 0xb8, 0xe6, 0x3b, - 0x56, 0xe5, 0xff, 0x0d, 0x64, 0xc2, 0x6c, 0x26, 0xc2, 0x8a, 0xec, 0x7e, 0xf5, 0xdb, 0x33, 0x82, 0xa9, 0xe7, 0x22, - 0x66, 0x6d, 0xf7, 0xec, 0xd3, 0xb0, 0x67, 0x93, 0x37, 0x22, 0x0b, 0x38, 0x67, 0x08, 0x9c, 0x3c, 0xe3, 0xca, 0xe2, - 0xe4, 0x96, 0xe5, 0x37, 0x77, 0xb9, 0x27, 0x7a, 0x21, 0x91, 0x48, 0x31, 0xab, 0x68, 0xe2, 0x58, 0x01, 0x48, 0x5a, - 0x7d, 0xf8, 0x71, 0xd4, 0xf7, 0x1f, 0x58, 0xaf, 0xd5, 0xdb, 0xb8, 0x4e, 0xc7, 0x88, 0xf8, 0x68, 0x38, 0x6e, 0x21, - 0x78, 0xb9, 0x4a, 0x4d, 0xf4, 0x19, 0xb7, 0xe4, 0x15, 0xa3, 0xde, 0x90, 0xee, 0xac, 0xce, 0x7b, 0x3a, 0xb7, 0xf3, - 0x65, 0x9b, 0x28, 0x54, 0x33, 0x34, 0x83, 0x41, 0x81, 0xf8, 0x38, 0x5f, 0xab, 0x91, 0x44, 0xdf, 0x11, 0xea, 0x84, - 0xbf, 0x5d, 0xb2, 0x48, 0x88, 0x69, 0x36, 0x3b, 0xf9, 0x75, 0xee, 0xa2, 0x9a, 0x48, 0xd2, 0x3b, 0xe7, 0x10, 0x64, - 0xfa, 0x39, 0x83, 0x44, 0x0a, 0x27, 0x18, 0x43, 0x19, 0xc5, 0xb5, 0x59, 0x2e, 0x6a, 0xa1, 0x8a, 0xcf, 0xeb, 0xd9, - 0xb0, 0x53, 0x22, 0xd9, 0x4a, 0x14, 0xeb, 0x7c, 0x6d, 0x4f, 0xae, 0xa9, 0xb7, 0x5c, 0x0f, 0x19, 0xc5, 0x75, 0xf2, - 0xfc, 0xaa, 0x56, 0xb1, 0x51, 0x13, 0xf0, 0xa7, 0x94, 0xe2, 0xc0, 0x86, 0xdb, 0xbc, 0x25, 0x52, 0x7a, 0x56, 0xd6, - 0xdf, 0x3a, 0x49, 0x88, 0xef, 0xce, 0x4d, 0x2b, 0x7b, 0x43, 0x84, 0x87, 0x24, 0x81, 0xdc, 0xa8, 0xb5, 0xa6, 0x72, - 0xd7, 0xed, 0x33, 0x5f, 0x15, 0x56, 0x75, 0xfb, 0xd7, 0x6b, 0x37, 0xe0, 0x10, 0xf8, 0x00, 0x02, 0x21, 0xee, 0x25, - 0xb3, 0xcb, 0x61, 0x73, 0x04, 0x09, 0xf4, 0x19, 0xf0, 0x07, 0x2f, 0x5a, 0xa1, 0xe0, 0xad, 0xed, 0xc0, 0x03, 0x00, - 0x40, 0x6e, 0x35, 0x56, 0x3c, 0xdb, 0xc5, 0x7c, 0x47, 0xfe, 0x30, 0x55, 0x6b, 0xbe, 0x6e, 0x75, 0xd7, 0x05, 0x38, - 0x2f, 0x30, 0x9b, 0x7f, 0x2c, 0x55, 0xdb, 0x75, 0xc4, 0x69, 0x1a, 0x14, 0x98, 0xa8, 0xd2, 0xab, 0x4c, 0x95, 0xa4, - 0x56, 0x95, 0xa2, 0xe5, 0x61, 0x4d, 0xbb, 0xfa, 0x3c, 0x3e, 0xe6, 0x83, 0xb5, 0x26, 0x10, 0x5a, 0x07, 0x2f, 0xdd, - 0xdb, 0x9b, 0x96, 0x74, 0x6e, 0xb4, 0x4a, 0x9e, 0x68, 0xf3, 0x55, 0xe9, 0x5d, 0x05, 0xb7, 0x4c, 0xf9, 0x22, 0x23, - 0x0e, 0x61, 0x8d, 0xf0, 0x5f, 0xf5, 0x61, 0x68, 0x5b, 0x28, 0xb2, 0x7f, 0x1e, 0x88, 0xe0, 0xa9, 0x92, 0xbd, 0xcc, - 0x6c, 0xf3, 0x88, 0x0c, 0x61, 0x78, 0xe7, 0x12, 0x17, 0xc4, 0xf2, 0x53, 0x5d, 0x79, 0x66, 0xed, 0xee, 0x4d, 0x64, - 0x8b, 0x6c, 0xbc, 0xe3, 0x41, 0xc7, 0x3c, 0xaf, 0x2b, 0xd8, 0x61, 0xa3, 0xbd, 0x49, 0xb3, 0xc7, 0x79, 0x9b, 0xb2, - 0x8c, 0xd5, 0xc1, 0x0b, 0x59, 0x27, 0xc4, 0x24, 0x2d, 0x2a, 0x45, 0xe0, 0x7c, 0x80, 0xd6, 0x1e, 0x4f, 0x77, 0x3f, - 0x25, 0x7e, 0x6d, 0x2e, 0x2c, 0x36, 0xe8, 0x4b, 0x07, 0xbb, 0x9f, 0x79, 0xc4, 0x86, 0x11, 0x5b, 0x90, 0x7f, 0xdb, - 0x06, 0x10, 0xbb, 0x47, 0x94, 0xb2, 0x1b, 0xd1, 0xa3, 0x54, 0x3f, 0xe1, 0x55, 0x3e, 0x50, 0x81, 0x34, 0x66, 0x48, - 0x69, 0xc5, 0x15, 0x27, 0x92, 0xa0, 0x77, 0xb0, 0x04, 0x49, 0x0e, 0xec, 0x7b, 0x82, 0x88, 0xe8, 0x87, 0x9c, 0x8a, - 0x5c, 0xc5, 0x53, 0xcf, 0xa6, 0xdb, 0x23, 0xa3, 0x24, 0x48, 0xee, 0xf1, 0xa3, 0xe0, 0xbb, 0xbd, 0x89, 0xe2, 0x6e, - 0xf3, 0x44, 0xf0, 0xe6, 0x09, 0x26, 0x82, 0xf3, 0x02, 0xf9, 0x98, 0x5d, 0x3c, 0x81, 0x44, 0x25, 0x42, 0xbf, 0xe4, - 0xec, 0xe8, 0xdf, 0x65, 0xa9, 0xb7, 0xda, 0xeb, 0x50, 0x18, 0xb4, 0x2d, 0xa7, 0xd6, 0x38, 0xee, 0xb0, 0x94, 0x5d, - 0x34, 0x77, 0x59, 0xb2, 0x2c, 0x6b, 0x2f, 0xa3, 0x11, 0x1a, 0xa9, 0x79, 0xf8, 0x5c, 0x6a, 0x59, 0xd1, 0xf1, 0xa2, - 0x16, 0xe1, 0xc0, 0x10, 0x4b, 0xa5, 0xb3, 0x9c, 0x62, 0xb5, 0x5d, 0x18, 0x59, 0x8e, 0x23, 0x97, 0x2b, 0x09, 0x28, - 0x9a, 0x43, 0x44, 0x99, 0x0c, 0x1c, 0x47, 0x0b, 0x53, 0x29, 0x30, 0x66, 0x16, 0x1e, 0xec, 0x7c, 0x9b, 0x91, 0xeb, - 0x68, 0x24, 0x5f, 0xf8, 0x86, 0x14, 0xe3, 0x83, 0xb4, 0xd7, 0xd9, 0x88, 0x64, 0xe4, 0x80, 0x3d, 0x97, 0xa9, 0x08, - 0xab, 0x38, 0xaa, 0x77, 0x73, 0x8d, 0xeb, 0x46, 0x65, 0xe4, 0x8a, 0xf6, 0x3a, 0xb2, 0x58, 0x68, 0xc1, 0x7a, 0x7e, - 0xc9, 0xbc, 0xfb, 0x1c, 0x60, 0x6b, 0xa3, 0xac, 0x76, 0xe9, 0x02, 0xcd, 0xf9, 0x58, 0x53, 0xf8, 0x3b, 0x19, 0x81, - 0xbf, 0x71, 0xc2, 0x4e, 0xb3, 0x9f, 0xf7, 0xae, 0x91, 0x59, 0xf6, 0x32, 0xde, 0x32, 0x8f, 0x4e, 0x1d, 0x27, 0xb7, - 0x4e, 0x13, 0xc3, 0x98, 0x61, 0xc9, 0xf7, 0x07, 0xb8, 0xc4, 0x7c, 0x47, 0x80, 0x9d, 0xdf, 0xf3, 0x5c, 0xd2, 0x4e, - 0xe9, 0x80, 0xb4, 0x64, 0xf3, 0xc4, 0x4d, 0xd6, 0x5b, 0x93, 0x9f, 0x53, 0x8a, 0x95, 0x0b, 0xfe, 0x5a, 0xbf, 0xb2, - 0x9e, 0x94, 0xef, 0xd3, 0xe1, 0xad, 0x37, 0x33, 0xf9, 0xc1, 0x56, 0x98, 0xb0, 0x77, 0x40, 0x07, 0x5f, 0xc7, 0x7a, - 0x0b, 0x1f, 0x1f, 0xd8, 0xd1, 0x92, 0x84, 0x4e, 0x15, 0x5a, 0xd5, 0x51, 0xc8, 0xf8, 0xe8, 0x3e, 0x77, 0x1a, 0x89, - 0x45, 0x52, 0x2c, 0xa0, 0xf3, 0xad, 0xda, 0xfb, 0x27, 0xd4, 0xfc, 0xa8, 0x35, 0x99, 0xa2, 0xe9, 0xcc, 0xa9, 0x73, - 0xf5, 0xd7, 0xd4, 0x97, 0xed, 0x58, 0x07, 0x33, 0x71, 0xfd, 0x2d, 0xba, 0x56, 0x5f, 0x73, 0x9f, 0xa5, 0x20, 0x35, - 0x65, 0xd9, 0xc5, 0x89, 0xea, 0xcc, 0xab, 0x51, 0xa4, 0x53, 0xf1, 0xf1, 0x36, 0x72, 0xc7, 0x8b, 0x91, 0xd8, 0xc2, - 0x3b, 0xf8, 0x0a, 0x4b, 0xa2, 0xde, 0x6f, 0x44, 0x7c, 0x4c, 0xa8, 0x19, 0xbe, 0x43, 0x15, 0x38, 0x6b, 0x81, 0x81, - 0x92, 0x9c, 0xa8, 0xdb, 0x4e, 0xc5, 0xd9, 0x19, 0xbc, 0x34, 0x62, 0x57, 0x24, 0xa1, 0x43, 0x3e, 0x43, 0x7d, 0x05, - 0x1f, 0xed, 0xb3, 0x82, 0x1b, 0x4c, 0x2d, 0xf8, 0xb5, 0x8c, 0x62, 0x66, 0xfa, 0xdc, 0x35, 0xc4, 0x20, 0xfa, 0x9e, - 0x96, 0x66, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, 0x9e, 0x83, 0xf7, 0x02, 0x23, 0x62, 0xba, 0x6c, 0x77, 0x36, 0xbf, - 0x6e, 0x23, 0xc8, 0x12, 0x5d, 0x75, 0x9b, 0xc8, 0x24, 0x06, 0xce, 0xb1, 0x26, 0xc4, 0x87, 0x30, 0x43, 0x90, 0x0b, - 0xdd, 0xeb, 0x64, 0xa4, 0xd2, 0x27, 0x5c, 0xa4, 0xa3, 0x8e, 0x1e, 0xee, 0x66, 0x59, 0xbb, 0x61, 0xd7, 0xac, 0xfe, - 0x77, 0xde, 0xb5, 0xc3, 0xeb, 0xd3, 0xa0, 0xc8, 0x13, 0x6a, 0xb0, 0x40, 0x7a, 0x84, 0xbf, 0xf9, 0xf1, 0x50, 0x22, - 0xd3, 0xaf, 0x8f, 0x53, 0x21, 0x33, 0xce, 0x81, 0x03, 0xc8, 0x74, 0x4a, 0xff, 0xce, 0xbe, 0xac, 0xac, 0x60, 0xa4, - 0x0d, 0x7c, 0x6b, 0x06, 0xdb, 0x39, 0x59, 0x88, 0x8e, 0xd3, 0x6e, 0x86, 0xe8, 0xa1, 0x2d, 0x3b, 0xfd, 0x08, 0xad, - 0x53, 0x92, 0x96, 0xfd, 0x10, 0xc1, 0xca, 0x6a, 0x9f, 0x24, 0xba, 0x97, 0x46, 0xc0, 0xae, 0x5f, 0x65, 0x49, 0x2c, - 0x48, 0xa3, 0xff, 0xcc, 0xbc, 0xd2, 0x8d, 0x08, 0x0f, 0x6b, 0xc8, 0x00, 0x36, 0xc4, 0xea, 0x1e, 0xbb, 0x29, 0x2c, - 0xbc, 0xb5, 0x29, 0xd0, 0x99, 0x66, 0x8e, 0x06, 0x01, 0xdb, 0xcb, 0x7d, 0x8c, 0x34, 0x94, 0x3f, 0x5b, 0x89, 0x2d, - 0x47, 0x9a, 0xe2, 0xa3, 0xff, 0x78, 0x6d, 0x9a, 0x62, 0x91, 0x3a, 0x5f, 0xac, 0x27, 0x99, 0xe0, 0xbf, 0xa9, 0x9e, - 0x13, 0xcf, 0x3e, 0x32, 0xba, 0xef, 0xbf, 0x5e, 0x47, 0x56, 0x9e, 0x4f, 0x1c, 0x5f, 0xb5, 0x32, 0x39, 0x5f, 0xb1, - 0xcd, 0x41, 0x05, 0x6c, 0x7e, 0xe0, 0xe7, 0xac, 0x70, 0x6c, 0xc8, 0x3f, 0x9a, 0xf9, 0x08, 0xe3, 0x6a, 0x85, 0xef, - 0xda, 0x8b, 0x87, 0xb6, 0x62, 0x52, 0x24, 0x2d, 0xa8, 0xa4, 0x81, 0x54, 0x23, 0x2b, 0x12, 0x64, 0x18, 0xb9, 0x40, - 0xaf, 0xf8, 0x14, 0x4f, 0xcc, 0x96, 0x24, 0x3c, 0x14, 0xdd, 0xe2, 0x19, 0xa1, 0x42, 0xf0, 0xdf, 0x07, 0x64, 0x22, - 0x90, 0x04, 0x98, 0xeb, 0x08, 0x75, 0x94, 0xc4, 0x13, 0x9e, 0x1e, 0x24, 0xe8, 0x24, 0xe8, 0xe5, 0x5b, 0x21, 0x22, - 0x2a, 0x5f, 0x7d, 0xdd, 0x24, 0x68, 0x56, 0x82, 0x10, 0xcb, 0x19, 0x4b, 0x22, 0xb8, 0xd6, 0x8c, 0xde, 0xfd, 0x88, - 0x52, 0xdd, 0x6d, 0x48, 0x63, 0xf9, 0x0f, 0x23, 0x52, 0xe5, 0x9b, 0x9f, 0x71, 0x75, 0x19, 0xed, 0x19, 0xb9, 0x0b, - 0x54, 0x68, 0xf6, 0x09, 0x19, 0xfa, 0x18, 0xab, 0x16, 0xd1, 0x07, 0xf3, 0xb6, 0xa1, 0xb8, 0xc5, 0x14, 0x9b, 0xbb, - 0xb5, 0x7e, 0xce, 0x7e, 0xcc, 0x1f, 0x90, 0x50, 0x9e, 0x0a, 0x38, 0xc4, 0xc4, 0x2f, 0xc2, 0x06, 0x7d, 0x38, 0xef, - 0xd5, 0x48, 0x75, 0x7f, 0xbf, 0xed, 0xc3, 0x3c, 0x16, 0xe5, 0x27, 0xd4, 0xf6, 0x0c, 0x28, 0xa8, 0x94, 0x51, 0xa0, - 0xd6, 0x80, 0xb1, 0x0b, 0x4e, 0xe4, 0xfc, 0x34, 0x2c, 0x00, 0xea, 0x2b, 0x56, 0x4d, 0x31, 0x18, 0x23, 0x18, 0xe9, - 0x36, 0xc0, 0x0e, 0xa9, 0xd3, 0xc2, 0xc1, 0xbc, 0xfe, 0xf3, 0xa5, 0x0b, 0x0b, 0x84, 0x82, 0x37, 0xc9, 0xd2, 0x9a, - 0x29, 0xf4, 0x13, 0x04, 0xa6, 0xe0, 0x53, 0x79, 0xd4, 0x93, 0x78, 0xdf, 0x3f, 0x5f, 0x57, 0x89, 0x14, 0xf8, 0xb9, - 0xf0, 0x86, 0x08, 0x2b, 0xa6, 0x88, 0x79, 0xc4, 0x67, 0xd6, 0x92, 0x7d, 0xe1, 0x7d, 0xeb, 0x81, 0x3a, 0x05, 0x3c, - 0x73, 0xdf, 0x27, 0xf7, 0x42, 0xe0, 0x0f, 0x57, 0x1f, 0x3e, 0x99, 0x1f, 0xcd, 0x80, 0x55, 0x3d, 0xb2, 0x98, 0x84, - 0xa9, 0x28, 0xb3, 0x84, 0x20, 0x6e, 0x2a, 0x81, 0x85, 0x61, 0x5c, 0x8d, 0x9b, 0x8f, 0x75, 0xeb, 0x29, 0x13, 0x00, - 0x6a, 0x49, 0x42, 0xf7, 0x0c, 0x65, 0xcc, 0xec, 0xa5, 0x15, 0xa0, 0xdc, 0x73, 0x75, 0xf2, 0x72, 0x68, 0x8f, 0x61, - 0xe0, 0x50, 0xb6, 0x36, 0x98, 0xc6, 0x89, 0xc8, 0x32, 0x10, 0x20, 0x0e, 0xe5, 0xd7, 0xb9, 0xd2, 0xba, 0xea, 0x46, - 0x4c, 0x5d, 0x87, 0x7a, 0x3b, 0x47, 0xc7, 0x42, 0xdc, 0xfb, 0x99, 0x1e, 0x01, 0xb6, 0xd3, 0xf7, 0xf2, 0x03, 0x27, - 0x15, 0x02, 0xaf, 0x84, 0xca, 0x03, 0x89, 0xec, 0x81, 0x76, 0x50, 0x36, 0x00, 0x92, 0xdc, 0x16, 0x57, 0x0a, 0xd2, - 0x16, 0x20, 0x66, 0x36, 0xfe, 0xa7, 0x1f, 0x34, 0x8a, 0x03, 0xf2, 0xbe, 0x0f, 0x92, 0x92, 0xc6, 0xb3, 0x50, 0x6d, - 0x9c, 0x48, 0x11, 0xcc, 0xe0, 0x61, 0x11, 0x34, 0x22, 0x53, 0xa1, 0x73, 0x2b, 0xd8, 0xc6, 0xef, 0x5e, 0x9b, 0x47, - 0xa2, 0xc2, 0xf4, 0x37, 0xff, 0x74, 0x65, 0xdd, 0xa2, 0x48, 0xcb, 0xef, 0x71, 0xdd, 0xc7, 0xf8, 0xff, 0x06, 0x45, - 0x49, 0x92, 0xcd, 0x5e, 0x2a, 0x99, 0xce, 0xd8, 0xf3, 0x2b, 0xad, 0x8f, 0x16, 0xed, 0x81, 0x7d, 0xc3, 0x7b, 0xd0, - 0xdc, 0x03, 0xe1, 0x87, 0x92, 0x56, 0x9b, 0xfa, 0x84, 0xaa, 0x0a, 0x32, 0x24, 0x1a, 0xe3, 0x22, 0xb5, 0xa6, 0x4c, - 0xb5, 0x5b, 0xec, 0x06, 0x90, 0x4c, 0x63, 0x54, 0xd1, 0xe4, 0xbe, 0x79, 0x66, 0xf3, 0xc2, 0x3d, 0x91, 0x46, 0xd3, - 0x05, 0xb9, 0xfc, 0x2c, 0x39, 0xca, 0x94, 0x92, 0x25, 0xb1, 0x0c, 0x87, 0xf3, 0x10, 0x61, 0xae, 0x35, 0x44, 0x54, - 0x2a, 0x8c, 0x37, 0x4c, 0x4a, 0x13, 0x2b, 0xf9, 0x2d, 0x4a, 0x84, 0x45, 0xb0, 0xfa, 0xb4, 0xad, 0x03, 0x5c, 0x9b, - 0x83, 0x72, 0x84, 0x7b, 0xcb, 0x13, 0x6c, 0x6a, 0x9d, 0x07, 0xe7, 0x51, 0xae, 0x8a, 0x43, 0xa1, 0x4e, 0xdb, 0x07, - 0x54, 0xde, 0x44, 0xe8, 0x0c, 0x99, 0xb0, 0x35, 0x1e, 0x63, 0x90, 0x1b, 0x8f, 0x37, 0xd1, 0x0d, 0xcd, 0x87, 0x89, - 0x8a, 0xfa, 0x44, 0x5e, 0x26, 0xa0, 0xaa, 0xde, 0xa4, 0xf7, 0x53, 0xf2, 0xd3, 0x28, 0xa2, 0xc8, 0x9d, 0xe4, 0x84, - 0xca, 0x5a, 0x12, 0x15, 0x05, 0xb6, 0xf0, 0x24, 0x09, 0x09, 0xa0, 0xb8, 0x1b, 0xe3, 0x50, 0x85, 0xfc, 0xae, 0xca, - 0xe1, 0x5d, 0x8f, 0xea, 0xd0, 0xd2, 0x25, 0x90, 0xe4, 0x67, 0x32, 0xe9, 0x8f, 0x79, 0xef, 0x3e, 0x93, 0x87, 0xf7, - 0x23, 0x85, 0xb9, 0x8f, 0xf1, 0x1a, 0x66, 0x21, 0x2e, 0xff, 0xf6, 0xf3, 0xa2, 0x17, 0x1f, 0x25, 0x9d, 0x20, 0x33, - 0x54, 0xae, 0x8d, 0xf7, 0x4d, 0x23, 0x52, 0x55, 0xd4, 0x42, 0x20, 0x9f, 0xdc, 0xfd, 0x7a, 0x06, 0xa5, 0x8c, 0xe6, - 0x72, 0xaa, 0x5e, 0x27, 0xe5, 0x36, 0x7e, 0x18, 0x1a, 0xa2, 0xd7, 0xe5, 0x68, 0x53, 0xc0, 0x12, 0x6d, 0xf3, 0xf0, - 0xcf, 0x07, 0xab, 0xc8, 0x97, 0xe3, 0xa6, 0xd8, 0xa7, 0x8a, 0xc5, 0x9c, 0x7b, 0x7f, 0xb7, 0xc6, 0x03, 0x61, 0x7f, - 0x4a, 0x22, 0x99, 0x08, 0x02, 0x92, 0xb2, 0x05, 0x9e, 0x81, 0x43, 0x29, 0x5d, 0x9a, 0xa8, 0x35, 0x38, 0x94, 0xd4, - 0x9c, 0x7d, 0x4f, 0x2a, 0x9f, 0x3e, 0x2f, 0x11, 0x7e, 0x65, 0x5e, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xc7, - 0x12, 0x2d, 0x80, 0x5a, 0xa8, 0x0b, 0x75, 0x53, 0x01, 0xc1, 0xf8, 0x5a, 0xef, 0x0f, 0x91, 0x51, 0x85, 0xe2, 0x29, - 0x4a, 0xe9, 0x68, 0x97, 0xaf, 0xb8, 0x7d, 0xe9, 0x84, 0x29, 0x7c, 0xc3, 0x11, 0x47, 0xe4, 0x99, 0xee, 0x9b, 0x76, - 0xb9, 0x69, 0x45, 0xff, 0x80, 0x08, 0xf1, 0x6e, 0xbe, 0xd4, 0xb9, 0x31, 0x39, 0x82, 0x2b, 0x82, 0x66, 0x8b, 0x83, - 0xa7, 0xf2, 0x0f, 0xd7, 0x65, 0x21, 0x5d, 0x13, 0xe5, 0x48, 0x22, 0x3f, 0x64, 0x06, 0x5a, 0x01, 0x89, 0x35, 0x61, - 0x44, 0x0e, 0x66, 0x0b, 0x00, 0xbd, 0x36, 0x47, 0xb7, 0xda, 0xa8, 0x2e, 0x5b, 0x00, 0x5b, 0xfa, 0x0a, 0x46, 0x86, - 0x42, 0xe8, 0x88, 0xe1, 0x40, 0x46, 0xd4, 0x27, 0x95, 0x81, 0x2c, 0x3a, 0xc7, 0x02, 0x94, 0x79, 0x9f, 0x82, 0xbc, - 0x71, 0x12, 0x25, 0x24, 0x8d, 0x33, 0xf3, 0x49, 0x9d, 0x9d, 0x94, 0x83, 0xac, 0xa5, 0x90, 0x9e, 0x54, 0x37, 0xa8, - 0x5c, 0x2b, 0x7a, 0x25, 0xf4, 0x50, 0x72, 0x27, 0x36, 0x83, 0xd7, 0x5c, 0x19, 0xc5, 0x2f, 0x2d, 0xff, 0x32, 0xa1, - 0x61, 0x51, 0x9d, 0x40, 0x07, 0x7a, 0x09, 0xad, 0x21, 0xe6, 0xff, 0x5d, 0xb9, 0x77, 0x1d, 0xa4, 0x5b, 0xc7, 0x40, - 0xcb, 0x79, 0xab, 0xd4, 0xb3, 0x50, 0xd1, 0xad, 0xed, 0x99, 0xd4, 0x56, 0x15, 0x07, 0xdb, 0x98, 0x16, 0x64, 0xde, - 0xc1, 0xe7, 0x94, 0x0e, 0xa9, 0x8f, 0xb6, 0x71, 0xcd, 0x15, 0xd9, 0x83, 0xa5, 0xaf, 0xb1, 0x32, 0xa7, 0x0f, 0xc3, - 0x81, 0x17, 0x93, 0xb9, 0xb1, 0xe3, 0x6f, 0x84, 0x55, 0x2b, 0xd5, 0x46, 0xc4, 0xec, 0x10, 0x60, 0xaa, 0x1a, 0x8d, - 0x35, 0xef, 0xc3, 0x64, 0xa1, 0x9f, 0x65, 0xae, 0x00, 0xe5, 0x88, 0x49, 0xbd, 0xb2, 0xec, 0x85, 0xd6, 0x83, 0xef, - 0x97, 0x57, 0x57, 0xb2, 0xec, 0x5a, 0xa7, 0x87, 0xc0, 0x09, 0xe0, 0x4d, 0x41, 0xd5, 0x1a, 0x2f, 0xee, 0xdb, 0x0b, - 0xaf, 0xad, 0x0b, 0x52, 0x12, 0xf0, 0x8e, 0x92, 0xc1, 0x57, 0x9e, 0x06, 0x82, 0xe6, 0x7b, 0xe5, 0x7e, 0x62, 0x46, - 0x24, 0x72, 0xc7, 0xed, 0x19, 0x1f, 0xcf, 0xc3, 0x95, 0xa1, 0xf8, 0x65, 0x6c, 0x4d, 0x6b, 0x81, 0xf9, 0x83, 0x04, - 0x96, 0x13, 0xb5, 0x5b, 0x9f, 0x8b, 0x79, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x23, 0x54, 0x0c, 0x27, 0x81, 0xa2, 0x91, - 0x16, 0x98, 0xc3, 0x58, 0xe7, 0x70, 0x0b, 0x08, 0xa9, 0x53, 0x20, 0xe8, 0x6f, 0x47, 0x02, 0x8c, 0xfc, 0x41, 0x91, - 0x13, 0x4f, 0x9a, 0x9b, 0x35, 0x08, 0xfc, 0x7d, 0x38, 0x54, 0xa7, 0xed, 0xe5, 0x27, 0xdc, 0x81, 0x9b, 0xd8, 0x33, - 0x8e, 0x9f, 0xc5, 0xfd, 0x26, 0x27, 0x91, 0x73, 0x28, 0xaa, 0xf2, 0x39, 0x87, 0xc4, 0x4c, 0x1c, 0xea, 0x70, 0xfb, - 0x20, 0x5d, 0x5b, 0xc0, 0x70, 0x71, 0x98, 0xc6, 0x5e, 0x1d, 0x25, 0x20, 0x95, 0x7c, 0x74, 0x37, 0x9f, 0x7e, 0xf6, - 0x51, 0x3d, 0x88, 0xf6, 0x21, 0xe2, 0x6f, 0x6d, 0x49, 0xa3, 0x50, 0x79, 0x38, 0xb7, 0xbe, 0xa4, 0x86, 0x8f, 0x10, - 0x87, 0x7f, 0x2f, 0x16, 0xc5, 0x40, 0xec, 0x36, 0xb9, 0xe6, 0x82, 0x41, 0xef, 0x24, 0x03, 0xa1, 0xf5, 0x66, 0x98, - 0xca, 0x55, 0xb3, 0x2d, 0xac, 0x4c, 0x3b, 0x83, 0x0f, 0x36, 0xb6, 0xc5, 0x09, 0x08, 0xa2, 0x95, 0x41, 0xb7, 0x84, - 0x09, 0x4b, 0x8c, 0x29, 0xf4, 0x2d, 0x31, 0xcc, 0x79, 0x16, 0x95, 0xc4, 0x02, 0x4c, 0x47, 0x6b, 0xb6, 0xf4, 0x2b, - 0xa6, 0x2b, 0x9d, 0x89, 0xde, 0xb4, 0x41, 0xa6, 0x92, 0x66, 0x16, 0xc0, 0xdf, 0x64, 0x67, 0xd9, 0xe0, 0x1f, 0xd0, - 0xda, 0x95, 0x22, 0x31, 0x21, 0xdd, 0x82, 0x17, 0x95, 0x95, 0x9a, 0x37, 0x2e, 0x94, 0xfb, 0x35, 0xdf, 0xb4, 0xad, - 0x15, 0x82, 0xc3, 0x3a, 0x24, 0x1f, 0x58, 0x80, 0xe5, 0x72, 0x29, 0x2e, 0x55, 0x3b, 0x82, 0xa1, 0xb4, 0x95, 0xe4, - 0xc3, 0x22, 0x43, 0xd2, 0xe3, 0x13, 0x0d, 0x91, 0x90, 0x33, 0x9e, 0xb3, 0x35, 0xe0, 0xe4, 0xee, 0xce, 0x6a, 0xa6, - 0xf5, 0xa7, 0xdd, 0x78, 0xcf, 0x4b, 0x10, 0x93, 0x66, 0x0a, 0xbc, 0x27, 0xbb, 0x81, 0xb4, 0xdb, 0x2c, 0x36, 0xfa, - 0x9b, 0x6e, 0x69, 0x80, 0xee, 0xb6, 0x83, 0x01, 0x0c, 0x8c, 0x30, 0x0b, 0x2e, 0xbc, 0xa0, 0x6b, 0xff, 0xe0, 0x18, - 0xf0, 0x48, 0x81, 0xb3, 0x62, 0x48, 0x19, 0xe2, 0x6e, 0x6c, 0xf3, 0x63, 0xb6, 0x58, 0xbc, 0xfe, 0xfa, 0x3d, 0x32, - 0xa0, 0x2e, 0x70, 0x04, 0x1f, 0x68, 0x19, 0xa9, 0x34, 0x70, 0x4a, 0x2a, 0x3f, 0xda, 0x3b, 0x93, 0x6c, 0x65, 0x6a, - 0x85, 0xb0, 0xaa, 0x06, 0x9b, 0x1a, 0xd0, 0x66, 0x96, 0x96, 0xb6, 0xa5, 0x16, 0x98, 0xdb, 0xde, 0x0b, 0x30, 0xf9, - 0x02, 0x7a, 0xc0, 0xf2, 0x9f, 0xa1, 0x7b, 0x18, 0x4d, 0x2c, 0xe3, 0x5e, 0x10, 0x17, 0x55, 0x10, 0x40, 0x7a, 0x5b, - 0x8f, 0x20, 0x69, 0x5a, 0x63, 0xa2, 0xc3, 0xa2, 0xbb, 0x11, 0xb0, 0x0a, 0x2d, 0x31, 0x02, 0x7b, 0xc8, 0x8d, 0xa9, - 0x58, 0x3a, 0xf2, 0xab, 0x05, 0x16, 0x3e, 0x0f, 0x62, 0x5f, 0x93, 0xae, 0x97, 0xa5, 0x06, 0x62, 0xf2, 0x68, 0xeb, - 0x8d, 0x7e, 0x48, 0x8f, 0x76, 0x5d, 0xe3, 0x7d, 0xd4, 0x44, 0x60, 0x65, 0x2a, 0xb7, 0x87, 0xd9, 0x76, 0xfd, 0xd5, - 0x92, 0x02, 0xd5, 0xcc, 0x59, 0x16, 0xfe, 0xf6, 0xfe, 0x69, 0x3f, 0x01, 0x2e, 0xdf, 0xf1, 0xae, 0xe7, 0x80, 0xb0, - 0x1c, 0x9d, 0x55, 0x72, 0xdd, 0x6e, 0x6b, 0xff, 0x33, 0x3e, 0x34, 0x86, 0x92, 0x61, 0xfb, 0x9f, 0xee, 0x4e, 0xd7, - 0x23, 0x15, 0x0e, 0xa3, 0xc0, 0x51, 0xf8, 0xde, 0x7b, 0xcf, 0xab, 0x95, 0x3a, 0xce, 0xb2, 0x5f, 0xfb, 0xd6, 0xd4, - 0xeb, 0x64, 0x1b, 0xd6, 0x28, 0xbe, 0x1d, 0x23, 0x1b, 0x7b, 0xc1, 0xc8, 0xda, 0x18, 0xab, 0x7b, 0x04, 0x6b, 0x8f, - 0x6b, 0x8a, 0xe1, 0x6e, 0x05, 0xdf, 0x6f, 0xf7, 0xb8, 0x96, 0xd3, 0x39, 0xdd, 0x99, 0x6f, 0xdb, 0x2f, 0x7f, 0x72, - 0x96, 0x16, 0x1e, 0x34, 0x6f, 0xca, 0x65, 0x96, 0x2e, 0xab, 0xe4, 0x5a, 0x20, 0x4f, 0x36, 0x9d, 0x8b, 0x7a, 0xfd, - 0x79, 0xaf, 0x11, 0x66, 0xb0, 0x77, 0x17, 0xf1, 0xf6, 0x3e, 0xba, 0x9b, 0xcb, 0xa9, 0xcf, 0xbb, 0x45, 0x43, 0x08, - 0xe5, 0xe6, 0x95, 0xd3, 0xd6, 0x1b, 0xc7, 0x1c, 0x0f, 0xf8, 0xb0, 0x78, 0xef, 0x90, 0x13, 0x42, 0x6d, 0xf0, 0xeb, - 0x09, 0xee, 0x3e, 0xc4, 0x93, 0x6d, 0x7f, 0x4e, 0xdc, 0xe6, 0x0c, 0x11, 0xb6, 0xc8, 0xc3, 0xd2, 0x94, 0x74, 0x5c, - 0x03, 0x1b, 0xee, 0xce, 0x0a, 0x99, 0xb9, 0xf8, 0x95, 0xfb, 0xc6, 0x2d, 0x1c, 0x7d, 0x4f, 0xc8, 0x21, 0xcb, 0x32, - 0x6d, 0xde, 0x82, 0xbe, 0xb0, 0x99, 0xe5, 0x69, 0x1a, 0x93, 0xe5, 0x0f, 0x23, 0xdc, 0x15, 0x72, 0xd7, 0x5c, 0x45, - 0xcb, 0x69, 0x96, 0x8a, 0xba, 0x67, 0x1c, 0xb7, 0x38, 0xe3, 0x20, 0xbe, 0x07, 0x33, 0xfd, 0x7e, 0x8d, 0x6c, 0x68, - 0x5e, 0xfb, 0x07, 0x9e, 0x65, 0xe0, 0xf4, 0x5f, 0x6d, 0x54, 0xa7, 0x72, 0x9e, 0x03, 0xa0, 0x64, 0x89, 0xfe, 0x74, - 0x1c, 0xd2, 0x86, 0x42, 0x18, 0x15, 0xee, 0xbe, 0xfc, 0x68, 0x6f, 0x79, 0x15, 0x13, 0xd1, 0x1e, 0x3d, 0xe9, 0xce, - 0x08, 0x57, 0xc4, 0x5b, 0x46, 0x03, 0x28, 0xc6, 0x82, 0x0e, 0x14, 0x52, 0x56, 0x7b, 0x34, 0x67, 0x43, 0x9c, 0x79, - 0x9e, 0x54, 0x91, 0x2e, 0x02, 0xd6, 0x77, 0xc5, 0xa1, 0x9e, 0xdc, 0xab, 0xc0, 0xcb, 0xbe, 0x60, 0x1d, 0xea, 0x01, - 0xdc, 0x6f, 0x8a, 0x14, 0x1f, 0x69, 0xeb, 0x97, 0x5c, 0x31, 0xba, 0xb6, 0x4a, 0xc6, 0xfa, 0x6e, 0x8c, 0x68, 0xc4, - 0xe4, 0xaa, 0x26, 0x2c, 0xa7, 0x31, 0x8a, 0x46, 0x81, 0xe4, 0x9c, 0x1a, 0xc7, 0x38, 0x1d, 0x58, 0x4f, 0x22, 0x29, - 0x5d, 0x40, 0xc8, 0x2c, 0xc9, 0xf4, 0xa0, 0x01, 0x96, 0x64, 0xa4, 0x0d, 0x2a, 0xef, 0xa1, 0xa3, 0x71, 0xcf, 0x32, - 0x68, 0xee, 0x50, 0x57, 0x15, 0xae, 0xdd, 0xf2, 0x20, 0x53, 0x31, 0xb7, 0x66, 0x53, 0xfd, 0xb8, 0x1c, 0x44, 0x76, - 0x4d, 0xbb, 0x76, 0xdb, 0x67, 0x03, 0x2a, 0xb8, 0x81, 0x0c, 0x07, 0x29, 0xfb, 0x90, 0xd1, 0x23, 0x72, 0x67, 0x49, - 0xf7, 0xf9, 0x81, 0x42, 0xbf, 0x53, 0x07, 0x04, 0x18, 0xf9, 0x4a, 0x68, 0x87, 0x0d, 0x77, 0xea, 0xd0, 0x79, 0xdb, - 0x63, 0x22, 0x47, 0xe1, 0xf0, 0x2a, 0x49, 0xdf, 0x13, 0x6d, 0x47, 0x37, 0xee, 0xfb, 0xe3, 0x80, 0x9f, 0x94, 0xa6, - 0x88, 0x5a, 0x93, 0xd4, 0xe9, 0x62, 0xb9, 0x25, 0x9a, 0x0c, 0xfd, 0x8d, 0xe2, 0xb3, 0xe0, 0xc2, 0xc3, 0x12, 0xb7, - 0x1b, 0x0a, 0x5c, 0x89, 0xab, 0x72, 0x1f, 0x5f, 0x09, 0x68, 0x5c, 0x27, 0xe8, 0xfa, 0x8c, 0xa3, 0x3a, 0x18, 0x43, - 0x25, 0x66, 0x6f, 0xb0, 0x82, 0xb2, 0xaa, 0x47, 0x1c, 0x63, 0xeb, 0x67, 0x34, 0x37, 0x1e, 0x63, 0xd2, 0xb8, 0x9c, - 0x71, 0x44, 0xfa, 0xc8, 0x8c, 0x54, 0x86, 0x29, 0xbc, 0x3d, 0x72, 0x74, 0xa7, 0x76, 0xd3, 0xe5, 0x82, 0x66, 0x8c, - 0xca, 0xa0, 0x5f, 0xbc, 0x84, 0xd9, 0xc2, 0x12, 0x3c, 0x88, 0xab, 0x8b, 0x73, 0x6b, 0x17, 0x1f, 0x1d, 0x2a, 0xcc, - 0xc7, 0x36, 0x9f, 0x2f, 0x53, 0x45, 0xae, 0x84, 0x61, 0xea, 0xa7, 0xe9, 0xc5, 0x75, 0xa7, 0x92, 0xf6, 0x8b, 0xb0, - 0xfa, 0x9a, 0x19, 0x0f, 0xd8, 0x77, 0xdb, 0x10, 0x6d, 0xbf, 0x2f, 0x59, 0xaf, 0x2b, 0x53, 0x69, 0x7f, 0x6c, 0xee, - 0xd6, 0x64, 0xb7, 0xdb, 0x69, 0xdf, 0xa1, 0x13, 0x65, 0x90, 0xff, 0xfe, 0xcd, 0x7e, 0xe5, 0x4b, 0x4b, 0xfd, 0xa9, - 0xd0, 0x58, 0x1e, 0xb9, 0xf9, 0xb5, 0x1b, 0x55, 0x1d, 0x36, 0x94, 0xbb, 0x4e, 0xc7, 0xc8, 0x9d, 0x7d, 0x35, 0xd1, - 0xc4, 0x37, 0x4f, 0xf7, 0x73, 0xb1, 0xdc, 0x5f, 0x7d, 0xb4, 0xb7, 0x8f, 0xa4, 0x5c, 0xa4, 0x7c, 0xc9, 0x5e, 0xf3, - 0x94, 0xed, 0x22, 0x95, 0x11, 0xa0, 0x8c, 0xde, 0x48, 0x6f, 0x12, 0x9a, 0x26, 0xa9, 0x46, 0xfe, 0xe4, 0xf7, 0xf0, - 0xad, 0xba, 0x7b, 0xfd, 0x93, 0xa5, 0xbd, 0x13, 0x22, 0x1e, 0x00, 0xfe, 0x5b, 0xbe, 0xfd, 0xa9, 0xd8, 0xcd, 0x5c, - 0x56, 0x5b, 0x3e, 0xf0, 0xad, 0xb0, 0xaf, 0x8c, 0x87, 0x7e, 0x25, 0x55, 0x94, 0x7e, 0x95, 0x70, 0x89, 0x91, 0xb1, - 0xc9, 0x47, 0x75, 0xd3, 0x7a, 0xdc, 0x7b, 0x7d, 0x47, 0x00, 0x45, 0xf8, 0xc7, 0xc2, 0x18, 0xef, 0x21, 0x51, 0x38, - 0x15, 0x62, 0x98, 0x96, 0x9a, 0xca, 0x01, 0xd8, 0x34, 0xfa, 0x35, 0x8a, 0x53, 0xa9, 0xc8, 0x8f, 0xdf, 0x1f, 0x59, - 0xf9, 0xcd, 0x6d, 0xfe, 0xff, 0xdb, 0xcf, 0xde, 0x23, 0x14, 0x5a, 0x40, 0xd2, 0x7d, 0x14, 0xc9, 0x27, 0x11, 0xa8, - 0xb4, 0x72, 0x58, 0x8d, 0xb5, 0x1d, 0x24, 0x5a, 0x35, 0xad, 0xea, 0xc3, 0x17, 0x8f, 0xa1, 0xa7, 0x68, 0xa6, 0x14, - 0x51, 0xa9, 0xf2, 0x06, 0x09, 0xa1, 0x9e, 0xc6, 0xa7, 0x89, 0x4a, 0x85, 0xfc, 0x72, 0xb3, 0xfe, 0xe9, 0x8e, 0x49, - 0x10, 0x96, 0x73, 0x60, 0x88, 0xf4, 0x90, 0x3c, 0xa0, 0xc2, 0xee, 0x7c, 0x4c, 0xa3, 0x3a, 0xa5, 0x4f, 0x47, 0xf0, - 0x76, 0xaa, 0x69, 0xbb, 0x56, 0x5e, 0xcb, 0x2e, 0x91, 0x50, 0x82, 0xfb, 0x48, 0x33, 0x87, 0x0e, 0x1a, 0xa5, 0xa3, - 0xfb, 0xde, 0x3f, 0x09, 0x19, 0xba, 0xc0, 0xd0, 0xfb, 0xed, 0x03, 0x3f, 0xb6, 0xd5, 0xa0, 0xc7, 0x70, 0xd1, 0xb6, - 0xe8, 0x55, 0x5f, 0x16, 0x5d, 0x26, 0xb7, 0x97, 0xa2, 0x01, 0x92, 0x64, 0x7a, 0x16, 0x44, 0xe6, 0x7e, 0x21, 0x67, - 0x1d, 0xcf, 0x4f, 0x71, 0x2f, 0x1e, 0x53, 0x25, 0xa3, 0x1b, 0xfe, 0xea, 0x34, 0xf2, 0xbd, 0x89, 0xc4, 0xc7, 0x24, - 0x16, 0x92, 0x6d, 0x8c, 0xa0, 0xd7, 0x62, 0x78, 0x6e, 0x2c, 0xfd, 0x8d, 0x28, 0x50, 0x1a, 0x04, 0x58, 0x3a, 0x8f, - 0x94, 0x81, 0x2b, 0x36, 0xca, 0xdf, 0x6d, 0x68, 0x98, 0x52, 0x9b, 0x07, 0x44, 0xde, 0x65, 0xbf, 0x28, 0x32, 0xde, - 0x40, 0x24, 0x08, 0x46, 0x2a, 0xb8, 0x09, 0x52, 0xd0, 0x98, 0x2e, 0x30, 0x5b, 0x40, 0xb6, 0x38, 0x6e, 0x80, 0xcb, - 0x57, 0x8a, 0xe9, 0x52, 0xf5, 0xce, 0xe6, 0xaa, 0xe2, 0xc7, 0xf0, 0xbe, 0x5b, 0xeb, 0x20, 0x3e, 0x38, 0x11, 0x74, - 0x45, 0x69, 0xd2, 0xd3, 0x47, 0x26, 0xc9, 0x5a, 0x94, 0x2d, 0x46, 0x0f, 0x1a, 0x06, 0x2a, 0x2a, 0xac, 0x36, 0xd6, - 0x28, 0xf6, 0x2b, 0xba, 0x20, 0x8c, 0xc2, 0x17, 0xed, 0xc6, 0xc8, 0x7b, 0x97, 0x66, 0x5e, 0xbb, 0x1b, 0x47, 0xad, - 0xc8, 0x8b, 0x63, 0x5e, 0x73, 0x14, 0xd9, 0x1d, 0x26, 0x79, 0xfc, 0x55, 0x11, 0x05, 0xc3, 0x64, 0x64, 0x7b, 0xec, - 0xdb, 0x22, 0x33, 0x11, 0x22, 0xb6, 0x7e, 0xeb, 0x9d, 0x7d, 0x1b, 0x85, 0xb8, 0xe7, 0x23, 0xe1, 0xfe, 0x92, 0xe4, - 0x2a, 0xe0, 0x65, 0x5e, 0x73, 0xe8, 0x37, 0xe6, 0xd4, 0x50, 0xa9, 0xd1, 0x10, 0xf0, 0x2b, 0x95, 0x78, 0x40, 0x26, - 0xa8, 0x9c, 0xd8, 0x75, 0x1f, 0x5c, 0x46, 0x40, 0x87, 0xcb, 0xda, 0x68, 0xe6, 0xd3, 0xf7, 0xc8, 0xb5, 0x9d, 0xd6, - 0x47, 0x1a, 0x51, 0xe0, 0xe5, 0x56, 0x65, 0x70, 0xa0, 0x4f, 0xa5, 0xac, 0xbc, 0x20, 0x8a, 0x4e, 0xb4, 0x15, 0x1c, - 0x16, 0xb7, 0xc1, 0xbf, 0x47, 0x58, 0x2c, 0xb9, 0xe7, 0xb8, 0x01, 0xc8, 0x39, 0x8b, 0xc8, 0x46, 0x05, 0xf1, 0xef, - 0x00, 0x3b, 0x32, 0xe6, 0x1a, 0xc9, 0xb2, 0x86, 0xa9, 0x88, 0xb6, 0xf7, 0x11, 0x91, 0x6e, 0x87, 0x0b, 0x73, 0x8a, - 0x5e, 0x8c, 0x6f, 0x9b, 0x55, 0xb4, 0xe0, 0x01, 0xaa, 0xe0, 0xf3, 0x59, 0x70, 0x88, 0x95, 0x5f, 0xe1, 0xbe, 0xd9, - 0x10, 0x4d, 0xe0, 0x3c, 0x99, 0x07, 0x9d, 0x8b, 0x76, 0x22, 0xd7, 0xcf, 0x15, 0xb9, 0x97, 0xe4, 0x1b, 0x58, 0xaf, - 0x2c, 0xdd, 0x37, 0x8b, 0x79, 0x1a, 0x58, 0x81, 0x7e, 0x58, 0x84, 0x34, 0x70, 0x56, 0x99, 0xce, 0x3a, 0x7a, 0xaa, - 0x79, 0x22, 0x10, 0x12, 0xc0, 0x02, 0x03, 0x29, 0xfd, 0x35, 0xec, 0xde, 0x47, 0xa0, 0x11, 0xec, 0x14, 0x98, 0x61, - 0xde, 0x4f, 0x24, 0x0d, 0x6d, 0x53, 0xf5, 0x23, 0x1d, 0xd8, 0xbd, 0xb2, 0x57, 0xd8, 0x40, 0x07, 0xcb, 0xdf, 0xe7, - 0xdc, 0xf0, 0xd2, 0xdd, 0x7c, 0xfb, 0x57, 0x89, 0xd4, 0x72, 0x6d, 0xb5, 0xc0, 0xbf, 0x13, 0xeb, 0x73, 0x21, 0xc8, - 0x3e, 0xef, 0xcb, 0x08, 0x2b, 0x6a, 0x1c, 0x35, 0x9f, 0xb5, 0x17, 0xb5, 0xfc, 0x59, 0x09, 0x08, 0xce, 0xbd, 0x25, - 0xf1, 0x6e, 0x08, 0x1e, 0x77, 0x2e, 0xc9, 0xde, 0xd0, 0xe3, 0x49, 0x1f, 0xb2, 0xf2, 0xb1, 0x83, 0xd9, 0x42, 0x26, - 0xf3, 0x1d, 0x2a, 0x8a, 0x03, 0xf1, 0x46, 0x29, 0x3c, 0xc7, 0xdf, 0xcd, 0xd2, 0x04, 0x29, 0x79, 0xa5, 0xbf, 0x15, - 0x6f, 0x8c, 0x30, 0x1f, 0x63, 0x03, 0x07, 0xa3, 0x00, 0x91, 0xbf, 0x45, 0x83, 0x2a, 0x94, 0x70, 0xb4, 0x10, 0xa7, - 0xa1, 0xea, 0x25, 0x62, 0xdf, 0x95, 0x0f, 0xd5, 0xec, 0xab, 0x7e, 0xa2, 0x4e, 0xd7, 0x99, 0xb5, 0x37, 0x08, 0x85, - 0x6e, 0xb3, 0x5b, 0x6f, 0x32, 0x86, 0x2c, 0xda, 0x86, 0xd3, 0xf1, 0xf8, 0xfb, 0x73, 0xb3, 0x7c, 0xac, 0xd3, 0xec, - 0x5f, 0x2e, 0x0f, 0x48, 0xb5, 0xea, 0x8e, 0x7d, 0x3f, 0x2b, 0xfb, 0xc9, 0x7f, 0x1f, 0x53, 0x5d, 0xc6, 0xd3, 0xbd, - 0x12, 0x80, 0x8f, 0x45, 0x94, 0xa7, 0x17, 0x11, 0x9a, 0xab, 0xf9, 0x4e, 0xfd, 0x95, 0x3c, 0xe2, 0xab, 0xd7, 0xee, - 0x1f, 0xf9, 0xa0, 0x96, 0xd3, 0x55, 0x01, 0x19, 0x32, 0xe2, 0x71, 0xff, 0x55, 0xc8, 0x68, 0xd5, 0x5c, 0x5f, 0xcc, - 0x51, 0xf4, 0xdc, 0xf9, 0x7b, 0xd3, 0x90, 0x4d, 0x2f, 0x45, 0x4f, 0x98, 0x0f, 0xd4, 0xc8, 0x6d, 0x20, 0xe8, 0x26, - 0xdc, 0xe0, 0x74, 0x47, 0xaa, 0x4e, 0x56, 0x8c, 0x2e, 0x17, 0xbf, 0x4f, 0xcf, 0x22, 0xa5, 0xbe, 0x4c, 0x2d, 0x14, - 0xaa, 0x7d, 0x1f, 0x6a, 0x47, 0xc7, 0x55, 0x21, 0x6f, 0x82, 0x07, 0xc5, 0xd9, 0x12, 0x16, 0x6d, 0x54, 0x4e, 0x14, - 0x48, 0x32, 0xac, 0x16, 0x19, 0x37, 0x9f, 0x94, 0xac, 0x21, 0x43, 0x9d, 0x99, 0x23, 0xd0, 0x1c, 0x62, 0xa7, 0x62, - 0x28, 0xe9, 0xfd, 0x65, 0x06, 0x0a, 0x33, 0x44, 0xfb, 0x81, 0x01, 0x7a, 0xe5, 0x3e, 0x9a, 0x5b, 0xe6, 0xe4, 0x62, - 0x5c, 0x76, 0x09, 0xc4, 0x33, 0x8c, 0xbd, 0x6f, 0x91, 0x08, 0xda, 0xc9, 0x3b, 0x2a, 0x0d, 0xbe, 0x98, 0xee, 0x98, - 0x40, 0x72, 0x42, 0xce, 0x99, 0x31, 0x7d, 0xc5, 0x7f, 0xcd, 0xf5, 0xe4, 0xe4, 0x4d, 0x52, 0x1e, 0x57, 0x8f, 0xf0, - 0xdb, 0xb5, 0xf6, 0x2d, 0x72, 0x1f, 0x8c, 0x34, 0x55, 0x4b, 0x7e, 0x5b, 0x2a, 0xc8, 0x12, 0x16, 0x6e, 0xac, 0x7e, - 0xea, 0xca, 0x2e, 0x64, 0xb7, 0xba, 0xf0, 0xdc, 0x36, 0x2f, 0x6b, 0xf4, 0xfb, 0x66, 0xef, 0xa1, 0xbd, 0x75, 0x05, - 0xea, 0x55, 0x6d, 0x40, 0xa5, 0xce, 0xfd, 0xd1, 0xfc, 0xf6, 0x12, 0xf4, 0x4a, 0x7d, 0xf9, 0x78, 0xf0, 0x2b, 0x6a, - 0x2c, 0x62, 0xfa, 0x5b, 0xf5, 0xb7, 0x70, 0xf2, 0x84, 0x7b, 0xab, 0x5d, 0x63, 0x5d, 0x45, 0x03, 0xa1, 0xb9, 0x7b, - 0xed, 0xf9, 0xf0, 0xbe, 0x57, 0x6d, 0x75, 0x0d, 0x50, 0xbd, 0xe3, 0x9f, 0xe1, 0x5b, 0x08, 0xa7, 0x51, 0xe8, 0xee, - 0xa7, 0x16, 0x50, 0xd0, 0xe1, 0x34, 0x55, 0x01, 0x0e, 0x51, 0x5f, 0x03, 0xb4, 0xe4, 0xa7, 0xfa, 0x45, 0x42, 0xf5, - 0xf4, 0xf0, 0xe6, 0xec, 0xd3, 0xb5, 0xec, 0x90, 0x66, 0xab, 0x6d, 0xf4, 0xd3, 0xef, 0x3b, 0x87, 0xa5, 0xec, 0xa3, - 0x4a, 0xe8, 0xad, 0x8b, 0x25, 0x9e, 0x39, 0x13, 0x07, 0xcf, 0x7f, 0xe9, 0x70, 0xed, 0x9e, 0xd8, 0x72, 0xba, 0x3e, - 0xa4, 0x3d, 0x97, 0x69, 0xe4, 0x04, 0xa6, 0x34, 0x3d, 0x49, 0x64, 0x05, 0x63, 0x6a, 0x79, 0x20, 0xa3, 0xa5, 0x65, - 0x3c, 0x6f, 0x5d, 0x1a, 0x4c, 0x79, 0xfd, 0xd0, 0x54, 0x7b, 0x6e, 0x93, 0x6d, 0x1d, 0xb0, 0x5e, 0x8e, 0x53, 0xf3, - 0x1f, 0x2e, 0xa1, 0x46, 0x13, 0x0b, 0x65, 0xc4, 0xda, 0x61, 0x5e, 0x58, 0x25, 0xd4, 0xb4, 0xa5, 0x54, 0x59, 0x54, - 0x39, 0xfb, 0x5c, 0xde, 0xaf, 0x1e, 0xa1, 0x83, 0xc1, 0x84, 0x04, 0xab, 0x53, 0x7d, 0xf1, 0x34, 0x28, 0x7a, 0x25, - 0x9e, 0xdf, 0x94, 0x2e, 0x37, 0x24, 0xf5, 0xb2, 0x4a, 0xe4, 0x2f, 0x55, 0xea, 0x85, 0xf5, 0x84, 0x60, 0x5e, 0x34, - 0xd3, 0x47, 0x98, 0x5b, 0xa7, 0x91, 0xd3, 0x53, 0xa9, 0x7a, 0xa3, 0xcd, 0x02, 0x21, 0x80, 0xc7, 0xa6, 0xeb, 0x76, - 0x8a, 0xe1, 0xd7, 0xfe, 0xb0, 0x3e, 0x66, 0x15, 0x6c, 0xba, 0xf6, 0x14, 0xc2, 0xc0, 0x75, 0xbd, 0x87, 0x37, 0x65, - 0xd3, 0x59, 0xad, 0xc6, 0x89, 0x38, 0x51, 0x29, 0x76, 0x7d, 0x27, 0x26, 0x33, 0x7a, 0xcf, 0xd0, 0x1f, 0x68, 0x8e, - 0x29, 0x21, 0x01, 0x50, 0x93, 0x1e, 0x3e, 0xff, 0x2d, 0xdd, 0xe5, 0xb6, 0x28, 0x86, 0x8a, 0x0d, 0xc2, 0xea, 0x6b, - 0x1d, 0x37, 0xc3, 0xbf, 0xe0, 0x97, 0x0f, 0xc1, 0x27, 0x24, 0x80, 0x2a, 0x0a, 0xfc, 0x83, 0xc1, 0x04, 0xda, 0x25, - 0xa7, 0x64, 0xed, 0x41, 0x73, 0x2b, 0xb1, 0xe2, 0x31, 0x10, 0x43, 0x7c, 0xfa, 0x20, 0x14, 0x31, 0x76, 0x43, 0xbb, - 0x3c, 0xec, 0xf8, 0x8a, 0xe5, 0x52, 0x99, 0x8f, 0xd5, 0x62, 0x49, 0xfa, 0x51, 0xf8, 0x45, 0xb1, 0x13, 0x02, 0x39, - 0x41, 0x35, 0x47, 0x7f, 0xde, 0x12, 0xc4, 0x9c, 0x9a, 0x5d, 0x7b, 0x6a, 0x02, 0xae, 0xe7, 0x30, 0x85, 0x1f, 0x65, - 0x6e, 0x7d, 0x88, 0xa7, 0x28, 0x9d, 0x4b, 0xc0, 0x3b, 0xb9, 0x2f, 0x3c, 0xd8, 0xba, 0xd4, 0x9d, 0x00, 0x1f, 0x12, - 0x88, 0x5a, 0x99, 0x3c, 0x99, 0xf8, 0x68, 0x51, 0x30, 0xe7, 0x33, 0x86, 0x9f, 0x34, 0x49, 0x29, 0xdc, 0x21, 0x3a, - 0x9b, 0x15, 0x4a, 0x3a, 0xa6, 0xd8, 0x0c, 0x90, 0x41, 0x00, 0x04, 0x96, 0x55, 0xfe, 0x40, 0xec, 0x72, 0x15, 0x16, - 0x1a, 0xb1, 0x52, 0x14, 0x84, 0x54, 0xdb, 0x81, 0x69, 0xd7, 0x75, 0xab, 0xc0, 0xb7, 0x4e, 0x38, 0x0d, 0xd7, 0x58, - 0x9e, 0x94, 0x94, 0xcc, 0xb0, 0x32, 0x14, 0x70, 0x6e, 0x25, 0xb2, 0x99, 0xaf, 0x8e, 0x04, 0x4e, 0xfe, 0x15, 0x0c, - 0x72, 0x5f, 0xca, 0xae, 0x1c, 0x80, 0xf3, 0xa9, 0x25, 0x2e, 0xed, 0xeb, 0xb9, 0x70, 0xeb, 0x24, 0x55, 0x9d, 0xad, - 0xf6, 0x60, 0x31, 0x2e, 0xba, 0xb4, 0xdb, 0x92, 0x14, 0x14, 0xe8, 0xbe, 0x78, 0x3a, 0x4d, 0x52, 0x67, 0x3a, 0x49, - 0x79, 0x2c, 0x66, 0x30, 0xb2, 0x44, 0x4b, 0xd5, 0x09, 0xf7, 0x9a, 0x86, 0x9d, 0xe5, 0x7f, 0x0a, 0x8d, 0xd4, 0x64, - 0x33, 0x9d, 0x6e, 0xba, 0x7b, 0xdf, 0xa7, 0x60, 0x31, 0xc0, 0xcf, 0xa2, 0x8a, 0x7c, 0x3a, 0x2b, 0xbb, 0x41, 0x00, - 0x52, 0x04, 0x7a, 0x88, 0xc7, 0xd3, 0xb8, 0x2b, 0x19, 0xd3, 0x04, 0xe6, 0x5b, 0x04, 0xd0, 0xd4, 0x21, 0x51, 0xc0, - 0xc6, 0xbc, 0x0d, 0x35, 0xde, 0x17, 0xd7, 0x77, 0x1e, 0xf3, 0x52, 0x0c, 0x72, 0x40, 0x6e, 0xfb, 0xce, 0x15, 0x40, - 0x38, 0x83, 0x0b, 0xc4, 0x1e, 0xda, 0x09, 0x8c, 0x63, 0xf7, 0xf9, 0x91, 0x48, 0x15, 0x27, 0xcc, 0x77, 0x8a, 0xcc, - 0x1e, 0x9e, 0x1a, 0xef, 0xd1, 0x27, 0xe5, 0x34, 0x1a, 0x3f, 0x48, 0x98, 0xdf, 0xd8, 0x8c, 0x9e, 0xeb, 0xea, 0x69, - 0xce, 0x47, 0x41, 0x74, 0x58, 0xe4, 0xde, 0xff, 0xe9, 0x00, 0x39, 0x31, 0xbe, 0x6e, 0x99, 0x28, 0x39, 0x13, 0x52, - 0x87, 0x5a, 0xd6, 0xfb, 0xd4, 0x44, 0xa5, 0x06, 0x9d, 0xdc, 0xf2, 0x1d, 0x29, 0xa2, 0x2a, 0x8b, 0x1d, 0x5f, 0xeb, - 0x1e, 0x2a, 0xe9, 0xc6, 0x55, 0x5d, 0x74, 0x5a, 0x0d, 0x4d, 0x9e, 0x6a, 0xe9, 0x29, 0x84, 0x9f, 0xfb, 0xb4, 0xa6, - 0x2d, 0x60, 0x3d, 0xff, 0xa1, 0xd0, 0x6c, 0x7e, 0x88, 0xf0, 0x60, 0xf5, 0x19, 0x4d, 0x68, 0xe1, 0xc9, 0x40, 0x76, - 0x1d, 0x70, 0x6c, 0x46, 0xf2, 0xb2, 0x2f, 0x11, 0x74, 0x2d, 0xcc, 0x32, 0x56, 0x8f, 0xb8, 0x51, 0xf6, 0x72, 0xd2, - 0x1e, 0xe9, 0x3c, 0x43, 0x06, 0xed, 0x4f, 0x1d, 0xf7, 0xf0, 0x04, 0x4e, 0x24, 0xf3, 0x30, 0xc6, 0x16, 0x91, 0xf3, - 0x1e, 0xcf, 0x58, 0x07, 0xea, 0xd1, 0x72, 0x8b, 0x78, 0x60, 0xec, 0xd9, 0x2e, 0x82, 0xd2, 0xd0, 0x82, 0x1d, 0xf6, - 0x81, 0x43, 0x20, 0x92, 0x85, 0x6e, 0x2f, 0x59, 0xef, 0x89, 0x54, 0x90, 0x7c, 0xef, 0xa4, 0x8c, 0x0a, 0x70, 0x0d, - 0x2b, 0x1c, 0x31, 0xe6, 0x99, 0xe3, 0x64, 0x30, 0xeb, 0x1e, 0x0a, 0xa5, 0xa1, 0x73, 0xf0, 0xc9, 0x5e, 0x8b, 0x9f, - 0x3f, 0x38, 0x21, 0x87, 0x08, 0x36, 0xf6, 0x12, 0x5d, 0xaa, 0x52, 0x50, 0x29, 0xc3, 0x40, 0xf3, 0xbc, 0xb5, 0x30, - 0x29, 0x48, 0x85, 0x07, 0x98, 0xf1, 0xf1, 0xe8, 0x0f, 0x6d, 0xce, 0xd5, 0x33, 0x64, 0x0e, 0xec, 0xb0, 0x64, 0x1f, - 0xe3, 0x82, 0x22, 0x48, 0xd4, 0x10, 0x26, 0xfa, 0x24, 0x57, 0x0f, 0x8a, 0xf4, 0x09, 0x45, 0xaf, 0x89, 0xd3, 0xd3, - 0x81, 0x09, 0x74, 0xce, 0x93, 0x16, 0xa2, 0x1e, 0x14, 0x95, 0xf3, 0x83, 0xdc, 0xbd, 0x50, 0x19, 0x77, 0x70, 0x92, - 0x4b, 0x4a, 0xd7, 0x36, 0xf3, 0xfe, 0x46, 0xdb, 0xdb, 0xf3, 0x96, 0x54, 0x07, 0x9d, 0x24, 0x31, 0x87, 0x0a, 0xbc, - 0x42, 0x40, 0x42, 0xeb, 0xbb, 0x19, 0x1d, 0xdd, 0x83, 0xde, 0x84, 0xe9, 0x55, 0x45, 0x05, 0xc8, 0xbf, 0xf7, 0x2a, - 0x1a, 0x39, 0x47, 0xea, 0xea, 0xda, 0x91, 0xba, 0xb4, 0xbb, 0xfc, 0x49, 0xa1, 0x42, 0x3e, 0x10, 0x9a, 0x1f, 0x94, - 0x9d, 0x92, 0xbe, 0x26, 0xcc, 0x75, 0x35, 0xaf, 0x09, 0x36, 0xe0, 0xb3, 0x21, 0xc7, 0x91, 0xba, 0xf1, 0x83, 0x9a, - 0x01, 0xae, 0xdc, 0xa8, 0x87, 0x95, 0xdc, 0x77, 0x2e, 0x7e, 0xb1, 0x1f, 0x34, 0x33, 0x1f, 0xe3, 0x89, 0xae, 0x7a, - 0xdc, 0xcc, 0xd8, 0x83, 0xce, 0x0f, 0xa6, 0x4e, 0xd0, 0x6d, 0x93, 0x21, 0xc4, 0x3e, 0x4d, 0xf7, 0x90, 0xe7, 0xce, - 0x8f, 0x1e, 0x4c, 0xd0, 0xb9, 0x29, 0x08, 0xad, 0x9a, 0x14, 0xe8, 0xca, 0x2e, 0x79, 0x09, 0x3f, 0xbd, 0x7a, 0x45, - 0x97, 0x76, 0xd3, 0x5b, 0xf9, 0xe3, 0x26, 0x2c, 0x03, 0x7a, 0x17, 0xdf, 0x3b, 0xd4, 0xa7, 0x4c, 0xc7, 0x3d, 0xab, - 0xdd, 0x4b, 0x7e, 0xaa, 0x39, 0x8d, 0x9f, 0xb1, 0x5a, 0xa2, 0xf3, 0xc3, 0x79, 0x40, 0x70, 0x85, 0x10, 0x57, 0xfd, - 0xc0, 0x9b, 0xbd, 0x88, 0x52, 0xa6, 0x6a, 0x8b, 0xee, 0x4f, 0xfa, 0xc0, 0x2e, 0xe1, 0xf0, 0xb2, 0x6e, 0x8e, 0x13, - 0xf1, 0xdd, 0x58, 0x00, 0x26, 0x0c, 0xea, 0xea, 0xb7, 0x10, 0x30, 0x21, 0xba, 0xf3, 0xe4, 0x67, 0xfc, 0xbf, 0x21, - 0xe6, 0x3b, 0x45, 0xf8, 0xea, 0x78, 0xc1, 0xc9, 0xe9, 0xe4, 0x25, 0x2c, 0x81, 0x6f, 0x77, 0x18, 0x19, 0x22, 0x63, - 0x42, 0xa0, 0x19, 0xf3, 0x17, 0x69, 0x98, 0x4b, 0xe0, 0x2d, 0x0e, 0x81, 0xa3, 0xb8, 0x25, 0xfe, 0x64, 0x83, 0xbb, - 0xf7, 0xf9, 0xa6, 0x0f, 0xb1, 0xa6, 0xca, 0x2e, 0x41, 0xb9, 0xab, 0x78, 0xec, 0x66, 0x14, 0x68, 0x8c, 0xc2, 0x7e, - 0x83, 0x62, 0xa0, 0x45, 0xb7, 0x0e, 0x44, 0x14, 0xfa, 0x67, 0x55, 0xd1, 0xf9, 0x68, 0xa9, 0x88, 0x1d, 0xb2, 0x03, - 0x38, 0x01, 0xb2, 0x8b, 0x38, 0x19, 0x53, 0x97, 0x3b, 0x8a, 0x42, 0x03, 0x01, 0xce, 0xf0, 0x17, 0x3b, 0x9c, 0xf1, - 0x1f, 0xac, 0x03, 0x9b, 0x1c, 0x10, 0xd4, 0x06, 0xeb, 0x62, 0x8b, 0x53, 0x3c, 0x91, 0xfa, 0xc6, 0xec, 0xed, 0x79, - 0x3d, 0x1d, 0xf0, 0x1e, 0xdf, 0x55, 0xa9, 0x68, 0x21, 0x05, 0x5b, 0xf8, 0xb6, 0x1b, 0x32, 0x56, 0x0a, 0xab, 0xa0, - 0x77, 0xe7, 0x41, 0xd5, 0x9f, 0x4a, 0xa3, 0xfa, 0xbf, 0xba, 0x3b, 0xeb, 0xba, 0x05, 0x0f, 0xed, 0x92, 0xee, 0x82, - 0x2c, 0x59, 0xaa, 0x87, 0xad, 0xbe, 0xd9, 0x4d, 0x05, 0x05, 0xa9, 0x1d, 0x72, 0x7d, 0xeb, 0xff, 0xac, 0xc1, 0x81, - 0xac, 0xad, 0xda, 0x88, 0x03, 0xe1, 0x1d, 0x27, 0xc4, 0x57, 0x8f, 0xea, 0xae, 0x2e, 0x12, 0x54, 0x4d, 0xf9, 0xb8, - 0xc4, 0xfc, 0x32, 0x5e, 0xe5, 0x8d, 0x49, 0xaf, 0x2b, 0xbb, 0xef, 0x75, 0x39, 0x91, 0xb7, 0x93, 0xf9, 0x53, 0x10, - 0xdf, 0xd1, 0xcc, 0x00, 0x27, 0x27, 0xa5, 0x6c, 0x3d, 0xfb, 0x58, 0xdc, 0xe7, 0x38, 0x21, 0x92, 0x56, 0x19, 0x46, - 0x77, 0x7e, 0xe9, 0x0c, 0x6f, 0xdf, 0x80, 0xc2, 0xdb, 0x27, 0x4f, 0x80, 0x85, 0xd7, 0x94, 0x35, 0x8e, 0xb4, 0x28, - 0x24, 0x86, 0x61, 0x28, 0x05, 0xa2, 0x89, 0xd3, 0x6d, 0xa3, 0xbc, 0x09, 0xd0, 0x5b, 0xa1, 0x3f, 0x34, 0xf6, 0x88, - 0x9c, 0xb3, 0x7a, 0x79, 0x24, 0x97, 0xcc, 0x9f, 0xa8, 0x63, 0xfc, 0xc4, 0x0f, 0xfd, 0x93, 0x07, 0xf7, 0xba, 0x69, - 0x03, 0x38, 0xa4, 0x82, 0x9c, 0xc8, 0xf3, 0xb6, 0xbd, 0xaa, 0x8b, 0x26, 0x84, 0x3c, 0xe4, 0x56, 0x80, 0x87, 0x3c, - 0x3f, 0x9f, 0xeb, 0xa3, 0x10, 0x86, 0x43, 0x73, 0x05, 0x9c, 0x10, 0xd4, 0xc0, 0xbe, 0x81, 0x71, 0xe4, 0x46, 0x9e, - 0xdb, 0xd4, 0x17, 0x3d, 0x4e, 0xde, 0xed, 0x20, 0xa0, 0x0d, 0xfd, 0xf0, 0xbc, 0x3e, 0x75, 0xf5, 0xa3, 0xed, 0xf5, - 0x89, 0xdf, 0xc7, 0x68, 0x04, 0xe5, 0xcd, 0x5f, 0x61, 0x9f, 0x48, 0x5c, 0x81, 0x2d, 0xcd, 0x71, 0x36, 0x29, 0x9f, - 0xd5, 0x69, 0x53, 0xa1, 0x9e, 0x7c, 0x91, 0x63, 0x92, 0xdc, 0x57, 0x37, 0xd5, 0xc9, 0x42, 0x44, 0x1c, 0xf9, 0x9d, - 0x71, 0x87, 0xc1, 0xfc, 0x3c, 0xc9, 0xcd, 0x85, 0x2e, 0xb9, 0x3e, 0x4d, 0x2a, 0x68, 0xa0, 0xa2, 0x25, 0x79, 0x2f, - 0x3c, 0xe6, 0xad, 0xd0, 0xe4, 0x73, 0x61, 0x99, 0x2f, 0x85, 0xeb, 0x7c, 0x5d, 0x3f, 0x80, 0xef, 0x11, 0x37, 0xaa, - 0x56, 0x63, 0x3f, 0xf6, 0xe4, 0xbb, 0x96, 0x98, 0xf3, 0xaf, 0x34, 0xd6, 0xbc, 0x4d, 0x77, 0x89, 0x15, 0xcc, 0x68, - 0x36, 0x6d, 0x2c, 0x6e, 0x0c, 0x31, 0x15, 0xae, 0x49, 0xef, 0x70, 0x8d, 0xca, 0xf4, 0xec, 0x34, 0x22, 0x10, 0xbd, - 0x20, 0x6b, 0x0a, 0xb2, 0xb3, 0x95, 0x55, 0xb8, 0xb7, 0xd0, 0xb8, 0x58, 0xb8, 0x74, 0x7a, 0x1d, 0xbc, 0x42, 0xf5, - 0xfd, 0x76, 0x3d, 0x72, 0x89, 0xf2, 0xda, 0x94, 0xb4, 0xe1, 0x23, 0x27, 0x98, 0x63, 0xb1, 0x27, 0x28, 0xa1, 0xc8, - 0x50, 0xda, 0x12, 0xf0, 0x5c, 0x38, 0xe0, 0x1b, 0x31, 0x54, 0xeb, 0x7b, 0x5e, 0xa1, 0x27, 0x14, 0x39, 0x3e, 0x2a, - 0x77, 0x55, 0xc5, 0x49, 0x55, 0xba, 0xe6, 0x13, 0x5c, 0xbf, 0x1f, 0xbd, 0x8f, 0x88, 0x62, 0xed, 0x2b, 0xfb, 0xc2, - 0xbf, 0xb7, 0xc5, 0xea, 0xb2, 0x4f, 0x99, 0x80, 0x90, 0x5c, 0xde, 0xf2, 0x13, 0xc5, 0x1e, 0x39, 0x83, 0xef, 0x89, - 0xb0, 0x16, 0x93, 0x1c, 0xa4, 0xe3, 0x45, 0xc4, 0x0f, 0xa0, 0x03, 0x5b, 0xbe, 0x33, 0xcd, 0x29, 0xe2, 0x71, 0x25, - 0xbe, 0xef, 0x27, 0x83, 0x12, 0x2b, 0xb1, 0xca, 0xd9, 0x4f, 0xaa, 0x3a, 0x09, 0xe6, 0x7e, 0xf4, 0x1d, 0x8f, 0x1b, - 0xc1, 0xc1, 0xd4, 0xf1, 0x22, 0x64, 0x40, 0xe0, 0x17, 0xa0, 0x52, 0xe9, 0x01, 0xf1, 0x01, 0xa2, 0x6f, 0x40, 0x85, - 0x40, 0x78, 0x19, 0x94, 0xef, 0x51, 0x55, 0x9d, 0xda, 0x97, 0x73, 0x57, 0xde, 0x11, 0x94, 0x60, 0x1a, 0xde, 0xd1, - 0x48, 0x12, 0x94, 0x07, 0x1a, 0xed, 0x4e, 0x8e, 0xf8, 0xe0, 0x87, 0x37, 0x1d, 0x4d, 0x97, 0x2f, 0x31, 0x13, 0xed, - 0xd5, 0x9b, 0xf2, 0xe2, 0x5f, 0x83, 0x4c, 0x7c, 0xc9, 0x51, 0x20, 0x3e, 0xca, 0x93, 0xf5, 0xa6, 0xa4, 0x57, 0x17, - 0x4b, 0xbc, 0xff, 0x42, 0x39, 0xc2, 0xef, 0x16, 0x54, 0x0b, 0x30, 0xc7, 0xfe, 0xfc, 0xd0, 0xb6, 0x12, 0x3a, 0xc4, - 0x9a, 0xb7, 0xae, 0x04, 0xfe, 0x91, 0x9d, 0xb1, 0xbd, 0x0e, 0xc1, 0x7d, 0xdd, 0x9d, 0xcf, 0x0c, 0x33, 0xd9, 0xbc, - 0x52, 0x5c, 0x5e, 0x5a, 0x5e, 0x46, 0xe5, 0xb9, 0x27, 0xb9, 0xbe, 0x7e, 0x27, 0xf1, 0x9b, 0x4d, 0xed, 0xe2, 0xf2, - 0x5b, 0x4b, 0xdf, 0x98, 0x9a, 0x59, 0x26, 0xe0, 0x7e, 0xa7, 0xd7, 0x78, 0xa0, 0xd6, 0xed, 0x68, 0x6c, 0x33, 0x9b, - 0x13, 0xc6, 0x10, 0xe9, 0x6e, 0x3b, 0x53, 0x7b, 0xaa, 0xe0, 0xb7, 0x25, 0x45, 0xb2, 0x98, 0xd1, 0xd8, 0x22, 0x8e, - 0x54, 0x6f, 0xe5, 0x71, 0xcf, 0x7f, 0x67, 0xfa, 0x21, 0x43, 0xe3, 0x0c, 0x7f, 0xa0, 0x10, 0x01, 0x74, 0x23, 0x90, - 0xbb, 0xf0, 0xf5, 0x9e, 0x7f, 0x51, 0x21, 0x00, 0x40, 0x6d, 0x06, 0xa6, 0xbd, 0x18, 0xe7, 0x3a, 0x51, 0x1b, 0x72, - 0x8a, 0xee, 0xa6, 0xff, 0x1c, 0xbe, 0xd7, 0xdd, 0x89, 0x85, 0x56, 0x54, 0x7f, 0xf3, 0x43, 0x1b, 0xf0, 0x27, 0x75, - 0x9a, 0x62, 0x11, 0xba, 0xd8, 0xb8, 0xbc, 0x41, 0x9e, 0xa2, 0x35, 0x4a, 0x07, 0x55, 0x7e, 0x56, 0xd8, 0x1c, 0xbf, - 0xb7, 0x7f, 0xc6, 0x15, 0x78, 0x6b, 0x27, 0x55, 0xcf, 0x8d, 0xae, 0x0d, 0x00, 0x7d, 0x53, 0xdf, 0x0b, 0x4d, 0x66, - 0xde, 0xa8, 0xd2, 0xeb, 0xf7, 0x7b, 0xf2, 0x44, 0xfb, 0x10, 0x78, 0x02, 0x1a, 0x4e, 0x80, 0xd0, 0x95, 0x7c, 0x32, - 0x1f, 0x60, 0x03, 0x49, 0xa9, 0x38, 0xb0, 0xd3, 0x10, 0x7a, 0xa0, 0x63, 0x39, 0x61, 0x98, 0xc8, 0xe4, 0xc4, 0x71, - 0xc3, 0xff, 0x08, 0x2b, 0x42, 0x3f, 0xfa, 0x7f, 0xc6, 0x22, 0xae, 0x86, 0x73, 0x04, 0x31, 0x6a, 0xde, 0xc8, 0x02, - 0x14, 0xfc, 0xd7, 0xa9, 0xa7, 0x93, 0x13, 0xd9, 0x1c, 0xe7, 0x8c, 0x5a, 0xc6, 0x14, 0x21, 0xf2, 0x20, 0xc4, 0xf8, - 0x15, 0x9b, 0x58, 0x46, 0xd0, 0xf4, 0x43, 0x45, 0xef, 0x06, 0xb5, 0x95, 0x8c, 0xb8, 0x59, 0x3b, 0xb1, 0x03, 0xd7, - 0xde, 0x23, 0x01, 0x03, 0x79, 0xd3, 0x92, 0xed, 0x9b, 0xd2, 0xd5, 0xf8, 0xb0, 0x3f, 0x4e, 0xc6, 0xeb, 0x49, 0x16, - 0xf8, 0x27, 0xcd, 0x6e, 0x76, 0x86, 0xe4, 0x30, 0x49, 0xaa, 0x3c, 0x10, 0x09, 0xbc, 0xeb, 0x16, 0x43, 0x6a, 0x2c, - 0x6d, 0xb5, 0x4c, 0x14, 0xd6, 0x66, 0xc5, 0xc0, 0x91, 0x4d, 0x58, 0x17, 0x21, 0x06, 0x75, 0xb8, 0x2e, 0x4e, 0x01, - 0xd5, 0x09, 0xc2, 0x1c, 0x2a, 0xcc, 0x3a, 0x04, 0x9d, 0x32, 0x70, 0xd0, 0x31, 0xde, 0xd5, 0x83, 0xdf, 0x37, 0xce, - 0x88, 0x27, 0xc7, 0x4d, 0x83, 0xcb, 0xb9, 0xb1, 0x1c, 0x39, 0x37, 0xc2, 0xcb, 0xc0, 0xe9, 0x76, 0xbd, 0x21, 0xd5, - 0x36, 0x9c, 0x55, 0x45, 0x15, 0xad, 0xf2, 0x59, 0x75, 0x12, 0xd3, 0x56, 0xaf, 0xd9, 0x04, 0x51, 0x77, 0xe7, 0xb9, - 0x61, 0x2d, 0x83, 0x86, 0x11, 0x25, 0x21, 0x56, 0xef, 0x03, 0xfd, 0x89, 0x3d, 0xf8, 0xa2, 0x6a, 0x0f, 0x04, 0xba, - 0xd3, 0x60, 0x61, 0xc7, 0xcf, 0x00, 0x1c, 0x6e, 0xc6, 0x31, 0x8e, 0x41, 0xfb, 0xd2, 0x8a, 0x42, 0xaf, 0x96, 0x44, - 0xe0, 0x0c, 0xb3, 0xfc, 0x1f, 0xdf, 0xe2, 0xb5, 0xe8, 0xb5, 0xeb, 0xd0, 0xb9, 0xfa, 0x24, 0x36, 0x75, 0x6d, 0x9a, - 0xf8, 0xe8, 0xba, 0x81, 0x4b, 0x2f, 0xf0, 0x00, 0xee, 0x89, 0x17, 0x5d, 0x81, 0xc0, 0xf3, 0x4f, 0x26, 0x4a, 0xf7, - 0x70, 0x80, 0x39, 0x53, 0xdc, 0x18, 0x4e, 0xb9, 0x94, 0x1c, 0x43, 0xd3, 0xc2, 0x12, 0x18, 0x39, 0x40, 0x7f, 0x31, - 0xae, 0x30, 0x49, 0xba, 0xa4, 0x45, 0x47, 0xd1, 0x43, 0x2e, 0xc9, 0x3a, 0xa7, 0x5f, 0x64, 0x7e, 0xac, 0xae, 0xb1, - 0x51, 0x1c, 0x6b, 0x85, 0xcc, 0x3f, 0x44, 0x34, 0xea, 0x37, 0xe7, 0x05, 0x4c, 0xec, 0x8b, 0x83, 0x39, 0xbf, 0xf7, - 0xb7, 0xd6, 0xf2, 0xfa, 0xe3, 0xc9, 0xa6, 0xa7, 0x8c, 0x06, 0xc0, 0x18, 0x7e, 0xc2, 0xf1, 0x20, 0xa5, 0xd7, 0x57, - 0xa4, 0x82, 0xf7, 0x4d, 0xf1, 0x69, 0x5f, 0xc8, 0x4c, 0x4a, 0xf4, 0x8f, 0x41, 0x2c, 0x7d, 0x36, 0xad, 0x26, 0xd3, - 0x1f, 0xd0, 0xe6, 0x68, 0x0c, 0xe2, 0x51, 0x73, 0x78, 0x8b, 0x45, 0x75, 0xf5, 0x0c, 0x3f, 0xa1, 0xcc, 0x2d, 0x99, - 0x0f, 0xd9, 0x3e, 0x42, 0x5f, 0x8c, 0x25, 0x66, 0x1a, 0x9f, 0x27, 0x3f, 0x77, 0x91, 0x6b, 0xab, 0x37, 0x37, 0xf2, - 0xdf, 0xd4, 0x52, 0xa4, 0x36, 0xaa, 0x08, 0xfe, 0xfa, 0x13, 0xfa, 0x6a, 0x67, 0xde, 0xa4, 0x00, 0x9d, 0x2f, 0x09, - 0xfa, 0xd9, 0x80, 0x2a, 0x52, 0x04, 0x0d, 0xf8, 0xce, 0x16, 0xda, 0xa5, 0x32, 0x1d, 0x73, 0xfa, 0x5a, 0xde, 0xdf, - 0x84, 0x15, 0xdc, 0x1d, 0x6a, 0x1b, 0x92, 0xac, 0x46, 0x7e, 0x3d, 0xc6, 0x8a, 0xad, 0xef, 0x5d, 0x65, 0x38, 0xed, - 0xff, 0x18, 0x07, 0x01, 0xc8, 0x5b, 0xc5, 0xdd, 0x92, 0xd6, 0x69, 0xbd, 0x93, 0x74, 0xa5, 0x18, 0xd2, 0xca, 0xd5, - 0xfd, 0xee, 0xfb, 0xff, 0x30, 0x45, 0x63, 0x4a, 0x9f, 0xd8, 0x08, 0xed, 0x2a, 0x40, 0x92, 0x03, 0xa2, 0x87, 0x07, - 0x2d, 0x1d, 0x7f, 0x08, 0x45, 0x0b, 0x16, 0xbe, 0x05, 0x7d, 0xc3, 0x20, 0xda, 0x1e, 0xc1, 0x01, 0xbc, 0x0b, 0x97, - 0x7f, 0xf8, 0xa5, 0x71, 0x0d, 0x91, 0xdc, 0x7c, 0x4f, 0x6a, 0xea, 0xea, 0xcd, 0xbb, 0xe9, 0x5f, 0x42, 0xd6, 0x4d, - 0xfd, 0xe9, 0xaf, 0xd3, 0xb6, 0x2f, 0xbc, 0x9e, 0x14, 0x89, 0x66, 0x1c, 0x7f, 0x7b, 0x62, 0xe3, 0x8d, 0x31, 0xba, - 0x3e, 0x8a, 0x9e, 0x56, 0xcf, 0xde, 0x7a, 0xe9, 0x41, 0x2f, 0x4e, 0x08, 0x1e, 0xe3, 0x8f, 0x60, 0xc2, 0x6b, 0xfe, - 0x94, 0x50, 0xc7, 0xdf, 0x7a, 0x84, 0x7f, 0x36, 0x53, 0x18, 0x09, 0x15, 0x7e, 0xc7, 0x23, 0x8b, 0xca, 0xc5, 0xa5, - 0x24, 0x03, 0x42, 0x5c, 0x03, 0x60, 0x78, 0x2f, 0x9f, 0x02, 0x44, 0x62, 0xe3, 0xef, 0xe4, 0xde, 0x56, 0x78, 0x38, - 0xf7, 0xee, 0x50, 0x8e, 0xc5, 0xf2, 0x21, 0x65, 0xa6, 0x8f, 0xf8, 0x6d, 0xa4, 0x6e, 0x05, 0x75, 0x97, 0xe3, 0x97, - 0x0d, 0xc4, 0x7c, 0x00, 0xee, 0xef, 0xe1, 0xcd, 0x94, 0x57, 0x3f, 0x88, 0x6b, 0x00, 0xe4, 0xcf, 0x9d, 0x28, 0x99, - 0xd6, 0x1f, 0xed, 0x37, 0x74, 0x32, 0x10, 0x41, 0x82, 0x5a, 0x0b, 0x6a, 0x09, 0xb6, 0xc9, 0xee, 0x4d, 0x08, 0xbb, - 0xb5, 0xde, 0xcc, 0x77, 0xec, 0xc0, 0xce, 0x17, 0x7c, 0xc2, 0xf9, 0xb2, 0xf6, 0xa2, 0x9e, 0x1b, 0x19, 0xfe, 0x1d, - 0xf1, 0x0c, 0xfb, 0x05, 0xf3, 0xda, 0xb3, 0x9b, 0x9b, 0xf4, 0x3a, 0x5d, 0x0f, 0x4b, 0x5a, 0xa3, 0x7e, 0xc3, 0x8a, - 0x47, 0xb7, 0xd3, 0xa9, 0xd5, 0x6d, 0xb3, 0xaf, 0xd3, 0xef, 0x22, 0x96, 0x09, 0x34, 0x3f, 0xf1, 0xd6, 0x07, 0xa4, - 0xbe, 0xfd, 0x34, 0xb2, 0x9d, 0x5f, 0xfc, 0xf0, 0x0d, 0x86, 0xd3, 0x9f, 0x1c, 0xe1, 0xae, 0x0c, 0x7e, 0x66, 0x07, - 0xaa, 0x03, 0x25, 0x9f, 0xdd, 0x32, 0xc2, 0x60, 0x1c, 0x3e, 0xf0, 0x0c, 0x2b, 0xf8, 0x64, 0x7f, 0x15, 0xde, 0xc1, - 0xea, 0x1f, 0x5e, 0xf0, 0x5a, 0x5a, 0x23, 0xd5, 0x02, 0xdb, 0x85, 0x50, 0x42, 0xd9, 0x21, 0x35, 0x6e, 0xd4, 0xf6, - 0xef, 0x5c, 0x30, 0xd9, 0x22, 0xe1, 0xa6, 0x91, 0xe3, 0x57, 0x76, 0x9e, 0xb9, 0x72, 0x3c, 0xdf, 0x70, 0x33, 0xab, - 0xa0, 0x6f, 0x41, 0x19, 0x16, 0x56, 0x5f, 0x3a, 0xbe, 0x68, 0x88, 0xfe, 0x65, 0xf1, 0x0b, 0xc7, 0x51, 0xfe, 0x98, - 0xa3, 0x06, 0xee, 0xfc, 0x32, 0xaa, 0x88, 0x92, 0x3c, 0x66, 0x83, 0x03, 0xbd, 0xa3, 0xd1, 0x3c, 0xa1, 0x53, 0x2b, - 0x34, 0x80, 0x72, 0x0f, 0x1d, 0xfd, 0x80, 0xf5, 0xd4, 0x7e, 0xc3, 0x36, 0x1e, 0xe3, 0xf2, 0xaf, 0xe3, 0x4e, 0x46, - 0x9c, 0x92, 0x62, 0x7e, 0xcb, 0x33, 0x83, 0xf5, 0x82, 0x25, 0x5e, 0x25, 0x61, 0x07, 0xa4, 0xa8, 0xdf, 0xb1, 0xe7, - 0x7f, 0xe7, 0x7b, 0x1d, 0x60, 0xbe, 0x2d, 0xe8, 0xc9, 0xac, 0x01, 0xbf, 0xf5, 0x02, 0x6a, 0x2f, 0xe8, 0x2d, 0xa7, - 0xc5, 0x76, 0x55, 0x0d, 0x70, 0x02, 0x23, 0xa8, 0x99, 0x27, 0xf1, 0xe5, 0xde, 0xda, 0xff, 0x52, 0x71, 0x6a, 0xc0, - 0xc7, 0xc7, 0xeb, 0x07, 0xcc, 0x43, 0x87, 0x1c, 0xe5, 0x19, 0xef, 0x80, 0xcf, 0x1e, 0x1f, 0xf3, 0x1c, 0xb0, 0x63, - 0xf2, 0x7f, 0xe1, 0x61, 0xa9, 0xb3, 0xe7, 0x78, 0xf8, 0x12, 0x76, 0x8b, 0x93, 0x3d, 0xdc, 0x4d, 0xf2, 0x30, 0xde, - 0x24, 0xde, 0x06, 0x4f, 0x74, 0x63, 0xe0, 0x6a, 0xf0, 0xe3, 0x14, 0xeb, 0x3b, 0xde, 0xea, 0xe3, 0xf7, 0x7a, 0x7d, - 0x62, 0x5f, 0x35, 0x78, 0xbe, 0xff, 0x8d, 0x8f, 0xc6, 0x2d, 0xe3, 0x7f, 0xd5, 0x9a, 0xe7, 0x17, 0xa4, 0xaf, 0x63, - 0xf7, 0x74, 0x24, 0xdb, 0xea, 0xb1, 0x20, 0x67, 0x3a, 0x46, 0x47, 0x3a, 0x4e, 0xcb, 0x9f, 0xe2, 0xfa, 0x94, 0x9f, - 0x7c, 0xaf, 0xaf, 0x4f, 0x3c, 0xa9, 0xd4, 0xc6, 0xf3, 0x69, 0xb4, 0x01, 0x47, 0x0b, 0xe8, 0x4f, 0xab, 0x69, 0x6b, - 0x43, 0x12, 0x6f, 0x60, 0xb2, 0x4b, 0x71, 0x68, 0x56, 0xec, 0x96, 0xed, 0x4c, 0x3d, 0xd0, 0x9f, 0x77, 0xad, 0x07, - 0xe7, 0x85, 0xb9, 0xb1, 0x67, 0x05, 0x6e, 0x98, 0xac, 0xd4, 0x0e, 0xd2, 0x20, 0x1a, 0x11, 0x4b, 0x16, 0x88, 0x8e, - 0xfc, 0xda, 0x6b, 0x8f, 0x4d, 0xc5, 0xd9, 0xfd, 0x1a, 0x43, 0x97, 0x92, 0x01, 0x70, 0xb9, 0x2c, 0xec, 0xd4, 0xeb, - 0xed, 0x00, 0x0d, 0x02, 0x14, 0x07, 0x55, 0xce, 0x4c, 0xa0, 0x6c, 0x16, 0xf8, 0x1c, 0xe8, 0x55, 0x80, 0x3d, 0xe8, - 0xc2, 0xd1, 0xb9, 0x21, 0x5e, 0xe0, 0x9c, 0xd9, 0x2b, 0x03, 0x42, 0x89, 0x92, 0x5f, 0x34, 0xbc, 0x2d, 0xc6, 0x1c, - 0x7d, 0xd8, 0x08, 0x6b, 0x46, 0xa7, 0xaa, 0xe3, 0xda, 0x5b, 0xa5, 0xe3, 0xe6, 0xc1, 0xf1, 0x3d, 0x48, 0x90, 0x63, - 0x90, 0xc6, 0xfa, 0x3d, 0x7f, 0xb7, 0x3c, 0x95, 0x19, 0x58, 0x65, 0xc7, 0xfc, 0x7e, 0xc8, 0xad, 0x18, 0x79, 0x33, - 0x99, 0x28, 0x4b, 0x78, 0x90, 0x2b, 0xbc, 0xaf, 0xe2, 0x3f, 0x17, 0x91, 0xec, 0x24, 0x3f, 0xd2, 0x47, 0x42, 0xf5, - 0x8c, 0xf0, 0xcb, 0x27, 0xaa, 0xfe, 0x28, 0x66, 0xc3, 0x50, 0xec, 0xc6, 0x6a, 0x36, 0x0e, 0x73, 0x2e, 0xe7, 0x8d, - 0x36, 0xc4, 0x5b, 0x27, 0xb5, 0x89, 0xb4, 0xc1, 0x15, 0x7e, 0xb3, 0x00, 0x74, 0xc5, 0xf2, 0x40, 0x21, 0x90, 0x23, - 0xb4, 0xb7, 0x15, 0x2d, 0xf1, 0x29, 0x07, 0xbf, 0x60, 0x07, 0x3b, 0x84, 0x66, 0xbf, 0xcc, 0x43, 0x6b, 0x34, 0x6d, - 0x64, 0xd2, 0x61, 0xe7, 0x12, 0xc8, 0xd4, 0x02, 0x23, 0xd4, 0x38, 0xcb, 0xa1, 0xb0, 0x2a, 0xb8, 0x6f, 0xb4, 0x72, - 0x2e, 0x5c, 0xb7, 0x94, 0x4f, 0x86, 0x05, 0x3e, 0xc1, 0x16, 0x3e, 0x63, 0xc2, 0xee, 0x0b, 0xba, 0x39, 0x24, 0x52, - 0x48, 0x15, 0x25, 0x8d, 0xc9, 0xa0, 0x42, 0xe9, 0xb8, 0x8a, 0x5a, 0xa7, 0x81, 0xee, 0x31, 0x21, 0xa6, 0xa7, 0x20, - 0x16, 0x47, 0x6e, 0x5f, 0xfd, 0x11, 0xcf, 0xcf, 0x9b, 0x1f, 0xfb, 0x18, 0x27, 0x1a, 0x8b, 0xc7, 0x91, 0x3a, 0x3f, - 0x42, 0x65, 0xb8, 0xbc, 0x39, 0xed, 0x2e, 0xec, 0x35, 0x75, 0xd9, 0x29, 0x92, 0x12, 0x21, 0xa6, 0xb2, 0x5c, 0xe0, - 0x70, 0xdf, 0xeb, 0x9a, 0x54, 0xec, 0x08, 0xbc, 0x2e, 0xc4, 0x2f, 0x85, 0x7b, 0x6b, 0xf8, 0xbd, 0x62, 0xb7, 0x5a, - 0x3b, 0xdf, 0xb6, 0xb9, 0x33, 0x8f, 0xfc, 0xc0, 0xe1, 0xcc, 0xc9, 0x4c, 0xf4, 0x8b, 0xb0, 0xc4, 0xba, 0x23, 0xc7, - 0xd2, 0x90, 0xe0, 0xc4, 0x33, 0x54, 0xd9, 0x54, 0x43, 0xf7, 0x3b, 0x2f, 0x14, 0x71, 0x53, 0x72, 0xb4, 0x9b, 0x80, - 0x5c, 0xae, 0xe9, 0x52, 0xcb, 0xa8, 0x1c, 0x92, 0x84, 0xe7, 0x39, 0x90, 0xe7, 0x84, 0x62, 0xf5, 0xb3, 0xac, 0x33, - 0xe2, 0xbc, 0x81, 0x52, 0x3e, 0x12, 0x49, 0x78, 0xa6, 0xa6, 0xe7, 0x66, 0xe2, 0x4f, 0xd4, 0x5f, 0x89, 0xb3, 0x37, - 0x19, 0x1e, 0x8e, 0xe3, 0x0a, 0xc3, 0x35, 0xfc, 0x87, 0xd0, 0xa3, 0x07, 0xfe, 0xb9, 0x19, 0xc3, 0x20, 0x24, 0x99, - 0x51, 0x28, 0xc2, 0xa4, 0xf4, 0xea, 0xba, 0x6b, 0x1a, 0xe3, 0x44, 0xc7, 0xbd, 0x07, 0x9f, 0xab, 0x77, 0x13, 0xa4, - 0x84, 0xc4, 0x31, 0xa5, 0x0c, 0xca, 0xb5, 0xa8, 0xf0, 0xe0, 0xa9, 0xf6, 0xf5, 0x8f, 0x99, 0x5b, 0x51, 0x74, 0xf9, - 0x0a, 0xd9, 0x48, 0x00, 0x46, 0x4f, 0x06, 0x58, 0x0f, 0xcb, 0x0c, 0x76, 0x22, 0x21, 0xbe, 0x0a, 0x87, 0x2c, 0xad, - 0x3a, 0xca, 0x00, 0xb0, 0xd9, 0x6d, 0x04, 0xa3, 0x0f, 0x58, 0x75, 0x86, 0x5a, 0xd1, 0xdf, 0xb2, 0xa8, 0x5a, 0x69, - 0xdd, 0x48, 0x79, 0x35, 0x8d, 0x3e, 0xd1, 0x91, 0x0b, 0x3e, 0x97, 0x75, 0xbb, 0x20, 0x29, 0x49, 0x8c, 0x36, 0xb4, - 0xd0, 0x6f, 0x6b, 0x48, 0x57, 0xff, 0xf9, 0xe9, 0x7e, 0x28, 0xa2, 0x28, 0xad, 0x8b, 0x41, 0x72, 0x14, 0x94, 0xfe, - 0x87, 0x50, 0x07, 0x70, 0x36, 0x2d, 0xea, 0x27, 0x51, 0xc7, 0xed, 0x06, 0x1a, 0xf1, 0xe5, 0x07, 0xd8, 0xd9, 0x3a, - 0xba, 0xdb, 0xd6, 0xba, 0xd3, 0x24, 0x9a, 0x5c, 0x34, 0xa3, 0xca, 0x59, 0x23, 0xc7, 0x87, 0x41, 0x76, 0x16, 0xb9, - 0x4c, 0x46, 0x38, 0x77, 0x7b, 0x5d, 0xb0, 0x61, 0x12, 0x65, 0xc5, 0xff, 0x7c, 0x15, 0xa2, 0xbb, 0x94, 0x8b, 0x7e, - 0x00, 0x5b, 0xf2, 0xb2, 0xe3, 0x64, 0xd5, 0x20, 0x20, 0x5a, 0x09, 0x58, 0xce, 0xfc, 0xa2, 0x30, 0x8d, 0xd3, 0x77, - 0x5d, 0xba, 0x98, 0xc6, 0x90, 0xb5, 0x6e, 0x3e, 0xf0, 0x6f, 0x54, 0xb9, 0xc7, 0xb5, 0x26, 0xb8, 0x25, 0xa4, 0x77, - 0xe1, 0x0e, 0xf0, 0x6a, 0x53, 0xc7, 0x6e, 0xd7, 0x21, 0x10, 0x12, 0x08, 0x95, 0x2e, 0x24, 0xa8, 0x42, 0xdd, 0xce, - 0x84, 0x35, 0xd5, 0x23, 0xbc, 0x70, 0x62, 0xec, 0x2f, 0x57, 0x25, 0x37, 0x02, 0x07, 0x50, 0x34, 0x9b, 0x2f, 0x84, - 0xcd, 0xe4, 0xa8, 0x57, 0x8d, 0x6a, 0x47, 0xf0, 0x15, 0x3b, 0x1e, 0xfc, 0xd9, 0x67, 0x12, 0x31, 0x66, 0xe8, 0xc2, - 0x86, 0xdc, 0xf2, 0x33, 0x5d, 0x30, 0x6f, 0x0e, 0xda, 0xe9, 0x69, 0xed, 0xa3, 0xa0, 0x42, 0x75, 0x7e, 0xaa, 0x17, - 0x66, 0x12, 0xf2, 0x1c, 0x8b, 0x17, 0x83, 0xe6, 0xb9, 0xb1, 0x7e, 0x1f, 0x1d, 0xf2, 0xff, 0xd7, 0x0a, 0x18, 0x39, - 0xbb, 0x95, 0xee, 0x99, 0x52, 0xa6, 0xe4, 0xbb, 0xc5, 0xfc, 0xca, 0xc4, 0x70, 0xb5, 0x9c, 0x1a, 0xc1, 0x71, 0x9c, - 0xe6, 0xf1, 0x11, 0x26, 0x83, 0xa8, 0xbe, 0xc6, 0x56, 0x7c, 0xe8, 0xca, 0x90, 0x85, 0x7b, 0xbf, 0x4a, 0x54, 0x7a, - 0x87, 0xa3, 0xa7, 0xda, 0x9a, 0x51, 0xb5, 0x04, 0xea, 0xeb, 0x46, 0xad, 0xa8, 0xd5, 0x82, 0x72, 0x2a, 0x98, 0x57, - 0x98, 0xf2, 0xc4, 0x56, 0xe7, 0xff, 0x2d, 0x2b, 0xe1, 0xcf, 0x0d, 0xff, 0x8b, 0xbf, 0x10, 0x4e, 0x58, 0xb1, 0xa4, - 0xc2, 0x8f, 0x57, 0x07, 0x03, 0xb0, 0xf0, 0xdf, 0x87, 0xdd, 0xe8, 0x6f, 0x63, 0xb9, 0x80, 0xd4, 0xfd, 0xe8, 0x29, - 0x96, 0x4e, 0x11, 0x42, 0x2c, 0xe5, 0x45, 0xcf, 0x54, 0x52, 0x8b, 0x33, 0x2f, 0x1a, 0x00, 0x98, 0xf7, 0x60, 0xcd, - 0x7d, 0x71, 0x9c, 0x24, 0x41, 0xcd, 0x2a, 0xa0, 0x9a, 0x72, 0x3d, 0x27, 0xcc, 0xaf, 0x38, 0xf5, 0xa7, 0xac, 0xe9, - 0x99, 0x53, 0x50, 0xb7, 0xe7, 0x27, 0x69, 0x8c, 0x82, 0x66, 0xac, 0x18, 0xa7, 0xb2, 0x9d, 0xa4, 0xbf, 0x58, 0xbb, - 0xdc, 0xdd, 0x25, 0xca, 0xa4, 0xcb, 0xb3, 0x36, 0xe3, 0xbf, 0x92, 0x4a, 0x69, 0xc5, 0xee, 0xd4, 0xa9, 0xd1, 0x71, - 0x6e, 0x09, 0x6a, 0x34, 0x84, 0xe0, 0xcb, 0x40, 0x7a, 0xc8, 0x79, 0x59, 0x3a, 0xca, 0x73, 0xe0, 0x3c, 0x94, 0xed, - 0xc9, 0x83, 0x19, 0x68, 0x8f, 0xfe, 0x36, 0x8c, 0xa6, 0x96, 0xcc, 0xdf, 0xb9, 0x6a, 0xc3, 0x0e, 0xd1, 0xd0, 0x22, - 0x98, 0xae, 0x36, 0xc7, 0xed, 0x80, 0xf7, 0x72, 0x29, 0xb9, 0x3a, 0xd7, 0xae, 0xcf, 0x92, 0xe7, 0x67, 0xef, 0xc3, - 0x56, 0xd2, 0x6d, 0xfa, 0x4f, 0xde, 0x4e, 0x6d, 0x72, 0x7d, 0x9b, 0x56, 0xba, 0x2c, 0x9b, 0x20, 0x4a, 0x33, 0x34, - 0x71, 0xfe, 0x30, 0xdf, 0x4e, 0xfd, 0x13, 0xc1, 0x72, 0xc6, 0xa6, 0xec, 0xc7, 0xf9, 0xaa, 0x14, 0x66, 0xaa, 0x90, - 0x40, 0xda, 0x14, 0x7d, 0x49, 0x8d, 0x0b, 0x73, 0x3a, 0xbc, 0xa7, 0x93, 0x5c, 0x40, 0xfa, 0x34, 0x42, 0xe8, 0x63, - 0x27, 0x34, 0xe7, 0x68, 0xe4, 0xcd, 0x7f, 0x32, 0xf3, 0x5d, 0xf8, 0x41, 0x34, 0x68, 0xf8, 0x1d, 0x6f, 0x86, 0xda, - 0x76, 0xfa, 0x6a, 0x6f, 0xd3, 0x3c, 0x04, 0xb5, 0x6f, 0x34, 0x09, 0x1a, 0xf8, 0x7a, 0xf6, 0x03, 0x3e, 0xd9, 0x6c, - 0xaa, 0xa9, 0xf6, 0xc3, 0xaf, 0x26, 0xec, 0x90, 0x2a, 0xcb, 0xd0, 0x0c, 0x12, 0x06, 0xed, 0x0a, 0xdf, 0xd3, 0x25, - 0x4c, 0x02}; + 0x1b, 0x20, 0x98, 0x51, 0xd4, 0x8d, 0x56, 0x4b, 0xe5, 0xa2, 0xa8, 0x56, 0xa5, 0x80, 0x56, 0x05, 0xd9, 0x90, 0x89, + 0x0d, 0xfb, 0x77, 0x53, 0xb6, 0xa6, 0x94, 0xb5, 0x35, 0x4d, 0x09, 0x86, 0xa5, 0xbd, 0xe9, 0xf6, 0x5f, 0xc7, 0xd8, + 0xa5, 0xc5, 0x13, 0x67, 0x4e, 0x5c, 0xc8, 0x0a, 0xc3, 0x73, 0x8e, 0xd0, 0xd8, 0x27, 0xb9, 0xf7, 0xbe, 0x4d, 0xff, + 0xbf, 0x7e, 0x63, 0x35, 0x27, 0x95, 0x6f, 0x03, 0x48, 0x26, 0x74, 0x17, 0xcd, 0xb2, 0x2d, 0xa7, 0x0f, 0x84, 0x3d, + 0xe0, 0x49, 0x6c, 0xc9, 0x1d, 0x8d, 0x59, 0x62, 0xf2, 0xff, 0xf3, 0xfc, 0xac, 0xa5, 0xdf, 0x7d, 0x2e, 0x27, 0x83, + 0xa2, 0x56, 0xbd, 0xe9, 0x4a, 0xfd, 0xe5, 0xd8, 0xf8, 0x85, 0x59, 0x77, 0xcf, 0x9c, 0x10, 0x52, 0x98, 0xd0, 0xb6, + 0xf3, 0x17, 0x88, 0xa0, 0xb2, 0xd3, 0xfe, 0xbf, 0xda, 0xfa, 0x8a, 0xbb, 0x92, 0xc8, 0xa5, 0xcf, 0x29, 0xfc, 0x3e, + 0x57, 0x36, 0x86, 0x9e, 0x5e, 0x9e, 0x90, 0xd5, 0xfb, 0x32, 0x3b, 0x78, 0xb0, 0x3f, 0xa8, 0xc0, 0xa7, 0x29, 0x9b, + 0x63, 0xab, 0x96, 0x3f, 0xf2, 0xeb, 0x24, 0x98, 0x30, 0x9c, 0x28, 0xec, 0x20, 0x99, 0x71, 0xca, 0x01, 0x6b, 0xf3, + 0xb6, 0x34, 0x69, 0x05, 0x17, 0xb8, 0x27, 0x2e, 0xd6, 0xc1, 0xcc, 0x73, 0xbe, 0x59, 0xba, 0xac, 0x5a, 0xff, 0x07, + 0x35, 0x91, 0x76, 0x74, 0xc7, 0x0e, 0x72, 0x8d, 0x9d, 0x71, 0xfc, 0x41, 0xf6, 0xdf, 0x9b, 0x6a, 0x95, 0x36, 0x40, + 0xb3, 0xbb, 0xe7, 0x7c, 0x6a, 0x5c, 0x6a, 0x9c, 0x32, 0x88, 0x2b, 0x9d, 0xf3, 0x49, 0x70, 0x41, 0xc8, 0x7e, 0xef, + 0xfd, 0xff, 0x86, 0xed, 0x30, 0x44, 0x77, 0x13, 0x3b, 0x70, 0x94, 0x08, 0x92, 0x58, 0xfa, 0x12, 0xad, 0xe4, 0xff, + 0xff, 0x0d, 0x80, 0xdd, 0x00, 0xa5, 0x05, 0x29, 0x69, 0x8b, 0xe2, 0x70, 0xab, 0x68, 0xd6, 0x19, 0xce, 0xac, 0x3d, + 0xe3, 0x75, 0x53, 0x75, 0xd6, 0x45, 0x36, 0x4a, 0x8c, 0xcf, 0xae, 0x72, 0x1b, 0x85, 0xc6, 0xa6, 0x97, 0x5d, 0x78, + 0xe9, 0x39, 0x15, 0x55, 0xca, 0xed, 0x59, 0x9b, 0x06, 0x63, 0xd8, 0x32, 0x74, 0xf8, 0xac, 0x3a, 0xeb, 0xd9, 0x94, + 0x1b, 0xc2, 0x2d, 0x27, 0xc4, 0xba, 0x6d, 0xa4, 0xda, 0xe1, 0x38, 0xe9, 0x72, 0xee, 0x62, 0xa6, 0x10, 0x42, 0x03, + 0xc1, 0xfb, 0xe3, 0xc6, 0xf4, 0xc2, 0xdd, 0x9c, 0x44, 0x30, 0x31, 0xb6, 0x38, 0x40, 0x3a, 0x05, 0x7e, 0xe8, 0x50, + 0xa7, 0x9b, 0x52, 0x9c, 0x27, 0xe8, 0xf4, 0x37, 0x82, 0x69, 0xb6, 0x87, 0xa0, 0x1c, 0xc3, 0x81, 0x0d, 0x68, 0x64, + 0x79, 0xe6, 0xea, 0xdd, 0x07, 0x36, 0x5e, 0xd7, 0x2f, 0xc8, 0xa0, 0xc7, 0xbb, 0xdd, 0x1c, 0x70, 0x93, 0x92, 0x73, + 0xd7, 0x28, 0x1b, 0x41, 0xd7, 0xac, 0x5a, 0x08, 0xf2, 0x77, 0xfd, 0xf3, 0xb7, 0x37, 0x07, 0x1a, 0x93, 0xe8, 0x1f, + 0x52, 0xd3, 0x52, 0xc2, 0xb3, 0xa0, 0x4b, 0xda, 0x5e, 0xc0, 0xe1, 0x8b, 0x90, 0x87, 0x9e, 0x87, 0x5d, 0xf0, 0x5a, + 0x6b, 0xdd, 0x4e, 0x73, 0x3c, 0x33, 0x66, 0x6c, 0xb9, 0x48, 0xf5, 0x40, 0xcd, 0xf4, 0xce, 0xe1, 0xa0, 0x4b, 0x55, + 0x38, 0xab, 0xce, 0x49, 0xb4, 0xe9, 0x76, 0x89, 0x91, 0x3b, 0x5d, 0x7e, 0x9c, 0x52, 0xba, 0xf9, 0xbb, 0xad, 0x9a, + 0x84, 0x7b, 0x7a, 0x8b, 0x5f, 0xe3, 0xe1, 0x4f, 0x3b, 0x2f, 0xc2, 0x0a, 0x8a, 0x88, 0x78, 0xa4, 0x48, 0xb9, 0x3c, + 0x58, 0x4d, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0xc1, 0x48, 0x01, 0x2b, 0x1a, 0xe7, 0x08, 0xe7, 0x65, 0x7e, 0x9c, + 0x8c, 0x79, 0x59, 0xc4, 0xa7, 0x87, 0xc3, 0x79, 0xe7, 0x0e, 0xd7, 0x9d, 0x9b, 0xbd, 0x59, 0x0f, 0xa6, 0x6e, 0x5f, + 0x7f, 0x17, 0xf2, 0x6e, 0x58, 0x4f, 0xc1, 0xd6, 0x96, 0x5f, 0xbb, 0x5e, 0xf1, 0x0b, 0x35, 0x97, 0xae, 0xeb, 0xf5, + 0x80, 0x9b, 0xa6, 0x09, 0x32, 0x16, 0xda, 0x03, 0xfa, 0x73, 0x55, 0xc9, 0xfa, 0xf3, 0x20, 0x13, 0xca, 0x29, 0xfb, + 0x2e, 0xb8, 0xed, 0xba, 0xc4, 0xb1, 0x78, 0x42, 0xa6, 0x9a, 0xc8, 0x37, 0xf8, 0x8f, 0x80, 0x5a, 0x1e, 0x6c, 0xf0, + 0x28, 0xe4, 0x21, 0x30, 0xae, 0x23, 0x8a, 0xaa, 0xe6, 0x91, 0x50, 0xfd, 0xd6, 0xef, 0xd6, 0x20, 0x83, 0xfc, 0x5b, + 0xa3, 0x31, 0xda, 0x60, 0x08, 0x92, 0x99, 0xbb, 0x4d, 0xb2, 0x0b, 0x80, 0xc0, 0x54, 0x1d, 0x49, 0x69, 0x99, 0x47, + 0xe4, 0xe9, 0x78, 0x8e, 0x91, 0xf9, 0xc0, 0x7b, 0x1c, 0x16, 0xd3, 0x8d, 0xb8, 0xe1, 0x76, 0x00, 0x43, 0xc8, 0xdd, + 0x82, 0xa9, 0x6b, 0xca, 0x20, 0x19, 0xec, 0x14, 0x94, 0x34, 0x29, 0x90, 0x9c, 0x5d, 0xd3, 0x1c, 0x15, 0x01, 0x79, + 0xdd, 0xb5, 0xd3, 0xb1, 0x6f, 0x6b, 0xbc, 0xc5, 0x9b, 0xbf, 0xb3, 0x8e, 0x46, 0xc4, 0xf8, 0xbb, 0x6b, 0xe7, 0x92, + 0x8b, 0xb5, 0x02, 0xa4, 0x93, 0x70, 0xd7, 0x6b, 0xbf, 0x51, 0x3a, 0x6d, 0x9b, 0x39, 0x6c, 0x3f, 0x62, 0x26, 0xed, + 0xdc, 0x7a, 0x8f, 0x73, 0x9d, 0xaa, 0x98, 0x6d, 0x0e, 0x8f, 0x9f, 0x53, 0x24, 0x2a, 0xa9, 0x87, 0xed, 0xb7, 0x51, + 0x02, 0xfb, 0x5e, 0x6e, 0x3a, 0x4f, 0x98, 0xe9, 0x13, 0x9c, 0xf2, 0x8c, 0x58, 0x16, 0x30, 0xe5, 0x02, 0xf1, 0xde, + 0xc6, 0x4a, 0xb3, 0x4d, 0xd0, 0x10, 0xcc, 0xe4, 0x4f, 0xa5, 0x6b, 0x1b, 0xff, 0xb2, 0x88, 0x21, 0xd6, 0x41, 0x82, + 0x0f, 0x3f, 0x57, 0x0d, 0xa1, 0x94, 0xb0, 0x70, 0x9d, 0x8f, 0xef, 0x2a, 0x40, 0xca, 0x29, 0x90, 0x40, 0x42, 0x05, + 0xd4, 0xb9, 0x73, 0x46, 0xb0, 0xed, 0x27, 0x3c, 0xbf, 0x0f, 0xf2, 0x76, 0xb2, 0xc8, 0xf2, 0x5a, 0x64, 0x2b, 0x87, + 0x3b, 0x01, 0xf6, 0x7d, 0x9b, 0xea, 0x01, 0xf3, 0xd1, 0xef, 0x76, 0xb4, 0x39, 0x81, 0x85, 0xdb, 0x7a, 0x30, 0xdb, + 0x78, 0x5e, 0xfa, 0x17, 0x82, 0x5e, 0xf9, 0x1e, 0x44, 0xd3, 0x96, 0xa8, 0xc2, 0x7f, 0x7f, 0xfd, 0x9a, 0x40, 0xdc, + 0xb5, 0xe2, 0xd6, 0xff, 0xf0, 0xee, 0x26, 0x37, 0x44, 0x61, 0x3d, 0x70, 0x5d, 0xaa, 0xd3, 0xa5, 0x5a, 0x5f, 0x83, + 0x00, 0x34, 0x6e, 0x25, 0xd8, 0xdf, 0x14, 0x01, 0xb1, 0xfb, 0xd5, 0xf1, 0xaf, 0xdb, 0x11, 0x42, 0x82, 0xd4, 0xd9, + 0xce, 0x19, 0xf6, 0xbb, 0xf4, 0x41, 0x9b, 0x2d, 0x6a, 0x0a, 0xb3, 0x3f, 0x30, 0xbe, 0x26, 0x50, 0x28, 0x33, 0x9e, + 0x17, 0x99, 0xc4, 0x9d, 0xdc, 0xe1, 0x7a, 0x70, 0x5d, 0xe5, 0x2a, 0x7c, 0x24, 0xd6, 0x2a, 0x91, 0x3c, 0x73, 0xed, + 0x02, 0x7d, 0xb0, 0xe8, 0xc0, 0xae, 0x91, 0x11, 0xfe, 0xf3, 0xa8, 0x0a, 0x5e, 0x39, 0x9a, 0x95, 0x35, 0x5f, 0x8d, + 0x17, 0xbd, 0x05, 0x57, 0x7c, 0xde, 0xa9, 0x87, 0xce, 0xcc, 0xdb, 0xd1, 0xcf, 0x25, 0x83, 0xe4, 0xca, 0x62, 0x12, + 0x0a, 0x75, 0xea, 0x88, 0x32, 0x8b, 0x16, 0x18, 0x9b, 0xf9, 0xcb, 0x17, 0xcf, 0x82, 0x4e, 0x88, 0xb4, 0x9d, 0xca, + 0xce, 0x86, 0x67, 0xfc, 0x60, 0x87, 0x7a, 0x91, 0x9d, 0x4f, 0x48, 0x04, 0x0a, 0xdf, 0xba, 0xed, 0xd9, 0x7f, 0xca, + 0x43, 0xcb, 0x17, 0x5d, 0xfb, 0x93, 0x27, 0xd9, 0xed, 0x36, 0x12, 0xc5, 0x6d, 0x92, 0x90, 0xd8, 0x70, 0xd3, 0x7d, + 0x5c, 0xd6, 0x0a, 0x89, 0x4b, 0x34, 0xd7, 0x4a, 0x3b, 0xa5, 0x63, 0xec, 0xd2, 0x48, 0x59, 0xbb, 0x3d, 0x3e, 0x8b, + 0x1b, 0x7d, 0x15, 0x57, 0x20, 0x43, 0x4c, 0xd5, 0x13, 0xea, 0x9e, 0xc4, 0x35, 0x60, 0x58, 0x70, 0x64, 0x45, 0x73, + 0x21, 0x51, 0x09, 0x09, 0x86, 0xe9, 0xb4, 0x1f, 0x78, 0x29, 0xea, 0x6d, 0x10, 0x07, 0x88, 0x37, 0xf0, 0xf2, 0xfc, + 0x0a, 0x84, 0x15, 0xb5, 0x15, 0x80, 0x13, 0x55, 0x90, 0xf0, 0x15, 0x0a, 0x0c, 0x0a, 0xd4, 0x6b, 0x50, 0x04, 0x7b, + 0x44, 0xef, 0x04, 0x60, 0x90, 0x5b, 0xcd, 0x18, 0xde, 0xb6, 0x46, 0x6f, 0x03, 0x8e, 0xd9, 0xd8, 0x36, 0xcd, 0xa4, + 0x48, 0x61, 0x70, 0x7a, 0x89, 0xc5, 0x14, 0x75, 0xa3, 0xe6, 0xca, 0x92, 0xd8, 0x55, 0xdd, 0xdd, 0x9a, 0x22, 0x8d, + 0x7c, 0x58, 0x0f, 0xd1, 0x77, 0x67, 0xda, 0xe3, 0x02, 0x70, 0x0a, 0xb5, 0x61, 0xe5, 0xf6, 0x25, 0x8f, 0xb5, 0x50, + 0xf0, 0xf7, 0xbc, 0x6e, 0x20, 0xee, 0x45, 0x77, 0xea, 0x72, 0x22, 0x8c, 0xe3, 0x27, 0x03, 0xfb, 0xa9, 0x31, 0xc2, + 0x3d, 0xe4, 0x91, 0xb5, 0xb3, 0xa1, 0x0a, 0x8d, 0x70, 0x3d, 0x24, 0x9f, 0xf7, 0x97, 0xb4, 0xaf, 0x31, 0xd2, 0x71, + 0x71, 0x3e, 0xbc, 0x78, 0x63, 0x30, 0x15, 0xe0, 0x16, 0xad, 0xe7, 0xa0, 0xd9, 0x5a, 0xc6, 0x32, 0x7b, 0x70, 0xc8, + 0x8e, 0xe3, 0xda, 0xe9, 0xda, 0x22, 0xac, 0xda, 0x78, 0x20, 0x31, 0x24, 0xf0, 0x9b, 0x25, 0x86, 0x94, 0xc0, 0x4a, + 0x7c, 0xf4, 0xda, 0x40, 0x08, 0x5c, 0xbf, 0xe6, 0x20, 0x25, 0x98, 0xe5, 0xcb, 0x5f, 0xd2, 0x90, 0x8a, 0x5c, 0x0d, + 0x08, 0x19, 0xa9, 0xcf, 0x28, 0xcf, 0xac, 0xe0, 0x41, 0x71, 0xfc, 0x23, 0x46, 0x87, 0xcf, 0x9f, 0xed, 0x87, 0xc6, + 0xbe, 0x85, 0xf2, 0xa2, 0xac, 0x54, 0x66, 0x8e, 0x72, 0x42, 0x82, 0x22, 0x4b, 0x9e, 0x22, 0xb6, 0xf1, 0x15, 0x2b, + 0x41, 0x05, 0xf0, 0x8d, 0x40, 0xc6, 0xbb, 0x53, 0xc1, 0xb1, 0x89, 0x14, 0x01, 0x86, 0x76, 0x3b, 0x81, 0x84, 0xc0, + 0x20, 0x13, 0x47, 0x92, 0xab, 0xa3, 0x41, 0x62, 0x7f, 0x32, 0x8f, 0x5d, 0x38, 0x23, 0x92, 0xb5, 0x10, 0x24, 0x18, + 0x69, 0xbc, 0x57, 0x46, 0x9a, 0x80, 0xb0, 0x36, 0x40, 0xc7, 0xca, 0x3f, 0x83, 0x15, 0x96, 0x23, 0x30, 0x37, 0x2b, + 0xb8, 0x4b, 0xf3, 0x12, 0x42, 0xf4, 0x87, 0x95, 0x0a, 0xe8, 0xc7, 0x43, 0x7f, 0xce, 0x26, 0x28, 0x52, 0x10, 0xb4, + 0x42, 0x3c, 0xe4, 0x98, 0x4e, 0x14, 0x31, 0x70, 0xfa, 0xc7, 0x3d, 0x2c, 0xf6, 0x03, 0xb1, 0x60, 0x45, 0x45, 0x63, + 0x92, 0xbd, 0x14, 0xf5, 0x31, 0x62, 0xf0, 0x87, 0x19, 0x3b, 0x74, 0x9a, 0xa8, 0xa4, 0x97, 0x2a, 0x15, 0xeb, 0x60, + 0x5d, 0xa8, 0xac, 0x04, 0xe9, 0xd4, 0xe4, 0xe2, 0x1b, 0xa0, 0x28, 0x78, 0x27, 0x5e, 0x75, 0x06, 0x29, 0xbc, 0xd4, + 0x41, 0x2f, 0x40, 0xbf, 0x6c, 0x51, 0xe8, 0x19, 0x57, 0xe7, 0xde, 0xa4, 0x89, 0x2c, 0x61, 0x4f, 0xe8, 0xa0, 0x44, + 0xcb, 0x3f, 0xb8, 0xb0, 0x7a, 0x45, 0x08, 0x8e, 0x3d, 0x1f, 0xfe, 0xff, 0x69, 0x40, 0xfa, 0xf0, 0xa8, 0x87, 0x14, + 0x92, 0x08, 0x9f, 0xb0, 0xe5, 0x80, 0xae, 0x3b, 0x20, 0x29, 0x80, 0x77, 0x95, 0x31, 0x2d, 0x8f, 0x0b, 0xe2, 0xee, + 0x64, 0x4d, 0xcd, 0xd8, 0x2f, 0x13, 0xd0, 0xa9, 0xe0, 0xb8, 0x7a, 0xd7, 0x84, 0x35, 0xef, 0x6d, 0xa4, 0xe8, 0x58, + 0x60, 0x96, 0x40, 0x22, 0x44, 0x7a, 0x7f, 0x16, 0xe7, 0x42, 0xcc, 0xeb, 0x24, 0xb3, 0xdf, 0x72, 0x6a, 0x15, 0xa3, + 0x09, 0x14, 0x8e, 0x63, 0x59, 0xde, 0x93, 0x94, 0xe4, 0x09, 0x8f, 0x11, 0x8e, 0x57, 0x58, 0x47, 0xc1, 0x34, 0xa9, + 0x29, 0x29, 0x71, 0xf8, 0x5f, 0xa6, 0x34, 0x31, 0xd8, 0x95, 0xe8, 0x50, 0x11, 0x20, 0xa5, 0x59, 0x6a, 0x31, 0xf8, + 0x3c, 0x22, 0x1e, 0x0b, 0x80, 0x44, 0x44, 0xa2, 0xf0, 0x2f, 0x5d, 0xc9, 0xcf, 0x3c, 0x85, 0x88, 0xca, 0x4c, 0x83, + 0xce, 0xa2, 0xf7, 0xd5, 0x51, 0x4f, 0xd2, 0x6f, 0x74, 0x18, 0xd5, 0x2c, 0xff, 0x52, 0xf8, 0x90, 0xb8, 0xe1, 0xfe, + 0x59, 0x40, 0xa4, 0x7a, 0x93, 0x53, 0x2a, 0xed, 0x2c, 0xbd, 0xfc, 0xed, 0x0b, 0x14, 0x1b, 0x15, 0xc3, 0xf5, 0x63, + 0x7d, 0xb4, 0x21, 0xea, 0x9c, 0x1b, 0xe2, 0x80, 0x27, 0xac, 0x66, 0x4e, 0xe7, 0x8a, 0xbe, 0xb8, 0x4c, 0x1e, 0x13, + 0x53, 0x73, 0x9a, 0xde, 0xea, 0xe9, 0xb3, 0x48, 0x0e, 0x53, 0x67, 0x2b, 0x30, 0x05, 0x94, 0x61, 0xc5, 0x18, 0x59, + 0x0e, 0x24, 0xb1, 0x58, 0x72, 0xb9, 0x00, 0xa0, 0x45, 0xd6, 0x95, 0x63, 0x86, 0x42, 0xe5, 0x34, 0x32, 0x87, 0x83, + 0x8a, 0x63, 0xa4, 0x5d, 0xa9, 0x3e, 0x33, 0x84, 0x34, 0xea, 0xae, 0x01, 0x46, 0x14, 0x72, 0x96, 0xed, 0xbb, 0x28, + 0xe6, 0x22, 0x3c, 0x11, 0x06, 0xc8, 0xf3, 0x87, 0xd9, 0x66, 0xdd, 0x41, 0xe3, 0xc5, 0xc1, 0x78, 0x41, 0x65, 0xc3, + 0x48, 0xb2, 0x2c, 0x71, 0x50, 0x82, 0xc0, 0x29, 0x02, 0x8d, 0x7d, 0xfa, 0xd6, 0xa9, 0xfc, 0xfd, 0x32, 0x13, 0x89, + 0x87, 0x32, 0x8a, 0x11, 0x8f, 0x2f, 0xaa, 0xac, 0xab, 0x5b, 0x0e, 0x31, 0x7f, 0x78, 0xdb, 0xd8, 0x7e, 0xd3, 0x95, + 0x46, 0xcf, 0x0f, 0x9d, 0x15, 0x92, 0x66, 0x1c, 0xcd, 0xe9, 0xf4, 0x27, 0x71, 0x55, 0x53, 0x6c, 0x04, 0x14, 0x81, + 0xb0, 0xc7, 0x9b, 0x77, 0x4a, 0xa3, 0xbd, 0x13, 0xb0, 0x64, 0x1d, 0x83, 0x3d, 0xa9, 0xf6, 0x98, 0x90, 0xb4, 0xbc, + 0xff, 0x08, 0xcc, 0x95, 0x0a, 0x92, 0x4f, 0xc1, 0x87, 0x23, 0x94, 0x16, 0x14, 0xa2, 0x83, 0x4f, 0xba, 0x0d, 0x99, + 0x26, 0x60, 0xa2, 0x27, 0x41, 0x9e, 0x6d, 0xde, 0xb8, 0xa8, 0x42, 0x08, 0xe0, 0x81, 0xc9, 0xa6, 0x6f, 0xb2, 0xa4, + 0x55, 0xf6, 0xec, 0x3f, 0x87, 0x51, 0x96, 0xe5, 0x12, 0x9a, 0x04, 0xe9, 0x3d, 0x23, 0x72, 0xdb, 0x16, 0x9c, 0x9f, + 0xc5, 0x0a, 0xc9, 0xac, 0x2d, 0x0d, 0x69, 0x39, 0x84, 0x31, 0x28, 0x87, 0x8e, 0x08, 0xbe, 0x0c, 0x19, 0x56, 0x13, + 0x92, 0xe1, 0x5b, 0xfc, 0x07, 0x87, 0x4c, 0x52, 0x72, 0xa4, 0xc9, 0x7e, 0x2f, 0x06, 0x93, 0x5d, 0xe9, 0xa2, 0x02, + 0x1e, 0x66, 0xd3, 0x41, 0x0c, 0xc9, 0x56, 0xef, 0x29, 0xcd, 0x52, 0xcb, 0x11, 0xdc, 0x9d, 0x07, 0x52, 0xb0, 0x0d, + 0xaa, 0x9e, 0x47, 0x67, 0x1c, 0x2d, 0x00, 0xca, 0x5c, 0x92, 0xdc, 0x27, 0xc5, 0x20, 0x9b, 0x48, 0xa1, 0x80, 0x3d, + 0x65, 0x34, 0x86, 0x25, 0xb4, 0xfd, 0x71, 0x84, 0xc1, 0xd2, 0x90, 0x48, 0x91, 0x3e, 0x75, 0x62, 0xa7, 0x14, 0x8f, + 0x50, 0xf9, 0xd8, 0xba, 0x77, 0x50, 0x90, 0x40, 0x75, 0x92, 0x27, 0x08, 0xda, 0x73, 0xa0, 0x77, 0x4c, 0xc0, 0x7c, + 0x24, 0x19, 0xf1, 0xe3, 0x78, 0xbb, 0x62, 0x61, 0xf7, 0x21, 0xc5, 0x9d, 0x99, 0xdd, 0xfc, 0xc5, 0x7c, 0x8e, 0x34, + 0x67, 0x86, 0x4e, 0xea, 0x14, 0x92, 0xd9, 0x38, 0x27, 0xfa, 0x0b, 0xd2, 0xbc, 0x77, 0x11, 0x1d, 0xf1, 0x18, 0x7e, + 0x9f, 0x08, 0xae, 0x8f, 0xe7, 0x30, 0x82, 0xaf, 0xba, 0x28, 0x76, 0xb3, 0xde, 0x8a, 0x14, 0x5a, 0x3b, 0x19, 0xe2, + 0x82, 0xed, 0x3e, 0x18, 0x28, 0xa5, 0x24, 0xa2, 0xe9, 0xf7, 0x4a, 0x43, 0xc6, 0xa6, 0x41, 0x32, 0x63, 0x2b, 0x05, + 0x7a, 0x56, 0x8b, 0x38, 0x95, 0xd8, 0x91, 0x12, 0x74, 0x56, 0x38, 0x67, 0xa8, 0x01, 0x18, 0xed, 0xbc, 0xce, 0x1a, + 0x2c, 0x1d, 0x0c, 0x27, 0xae, 0xa1, 0x64, 0x8b, 0x3c, 0xc6, 0x87, 0x6e, 0xf6, 0x9e, 0xe5, 0x35, 0x40, 0xc1, 0x8f, + 0x8b, 0x20, 0xca, 0x03, 0xd4, 0x8c, 0xe0, 0xd8, 0x34, 0xab, 0x9e, 0xa4, 0x0d, 0xe7, 0x26, 0xbd, 0x19, 0x41, 0x5c, + 0xf6, 0x89, 0x8a, 0xc6, 0xff, 0x7e, 0x1c, 0x99, 0x7e, 0xb5, 0xea, 0x81, 0x94, 0x73, 0x16, 0x4a, 0xe3, 0x1b, 0x34, + 0xe2, 0x91, 0x07, 0xf6, 0xbb, 0xc6, 0x36, 0x4c, 0xa7, 0xa4, 0xa5, 0xc2, 0x7c, 0x55, 0x0d, 0xec, 0x80, 0x70, 0xd4, + 0xb2, 0x74, 0xac, 0x5f, 0x1e, 0x54, 0xf4, 0x7a, 0x9e, 0x7f, 0xb5, 0x7c, 0x6f, 0xd3, 0x02, 0x64, 0x67, 0x0c, 0x07, + 0x33, 0x26, 0x8d, 0x0a, 0xa8, 0x05, 0x64, 0xca, 0x3a, 0xa4, 0xe2, 0x69, 0x52, 0xc2, 0x91, 0x0d, 0x38, 0x1a, 0xb7, + 0x8d, 0xf4, 0x92, 0xf5, 0xd0, 0x01, 0xca, 0xac, 0xc3, 0x17, 0xb7, 0xad, 0xc7, 0x48, 0x35, 0xe0, 0x35, 0x00, 0x9c, + 0x14, 0xa9, 0x90, 0x12, 0x15, 0x52, 0x0e, 0x55, 0x4c, 0x07, 0x9d, 0x72, 0x4d, 0x9d, 0x95, 0x66, 0xe6, 0x5d, 0xdc, + 0xc1, 0x9f, 0x1e, 0x21, 0x84, 0x75, 0x19, 0x08, 0x16, 0xc5, 0x6f, 0x40, 0x10, 0x31, 0x59, 0x33, 0x7d, 0x23, 0x03, + 0x73, 0xbc, 0xa4, 0xe9, 0x57, 0x71, 0xc0, 0x2c, 0x96, 0x5e, 0x25, 0x26, 0xf1, 0x91, 0x51, 0x48, 0xdf, 0x58, 0x02, + 0xa2, 0x6e, 0x66, 0x79, 0x7e, 0xb5, 0xde, 0x33, 0x2e, 0x29, 0xf8, 0x98, 0x6f, 0xf7, 0xa3, 0xc2, 0xe1, 0xdb, 0x23, + 0x87, 0x03, 0x67, 0x90, 0x8a, 0x34, 0x66, 0x90, 0x53, 0xf0, 0xa2, 0x57, 0x98, 0xf1, 0xc7, 0x5c, 0xc9, 0x12, 0x51, + 0x78, 0x1b, 0xf0, 0xf7, 0x2c, 0x45, 0xe8, 0xf6, 0x80, 0xf0, 0x5d, 0xc8, 0xf8, 0xac, 0x84, 0x49, 0xfe, 0x08, 0x63, + 0x24, 0xb9, 0x7c, 0x1f, 0x6e, 0x2a, 0x93, 0xf1, 0xcd, 0x6f, 0x59, 0x14, 0xa8, 0x2c, 0x83, 0x69, 0x6a, 0x50, 0x52, + 0xe7, 0x00, 0x21, 0x8f, 0x9c, 0x57, 0xf5, 0xcc, 0xd4, 0x49, 0x23, 0xd2, 0x46, 0x1f, 0x64, 0x8a, 0x40, 0x74, 0x7a, + 0x10, 0x46, 0x1e, 0x08, 0x01, 0xf0, 0x1c, 0x02, 0x40, 0x4b, 0xe0, 0x0c, 0xe0, 0x98, 0xee, 0xc9, 0xa0, 0x11, 0x1a, + 0xf5, 0x9f, 0xed, 0x49, 0x54, 0xa4, 0x72, 0x1b, 0xdb, 0x0f, 0x7b, 0x8b, 0x44, 0xa3, 0x82, 0x1a, 0x8a, 0x29, 0xe2, + 0x6b, 0xfd, 0x4d, 0xe2, 0xae, 0xf7, 0xc9, 0x33, 0x8c, 0x2d, 0x4d, 0x23, 0x4d, 0x0b, 0x54, 0x3c, 0x75, 0x5f, 0xb0, + 0xb5, 0x27, 0x08, 0x69, 0x12, 0x8a, 0x32, 0x8c, 0xea, 0x9a, 0x2a, 0xc5, 0x2d, 0x1c, 0xc1, 0x51, 0xfa, 0xee, 0x44, + 0xdc, 0xfb, 0xc8, 0xf1, 0xe9, 0xcf, 0x08, 0x6a, 0x7d, 0x7e, 0xf4, 0xb6, 0xc9, 0xe9, 0x97, 0x61, 0x85, 0xbe, 0x12, + 0x11, 0xd1, 0x10, 0x06, 0x76, 0x38, 0xd0, 0x93, 0x86, 0x17, 0x63, 0x17, 0x77, 0x34, 0xd1, 0x83, 0x33, 0xf6, 0x54, + 0x86, 0xf4, 0xed, 0x99, 0xc8, 0xda, 0x16, 0xf5, 0xfa, 0xef, 0xe2, 0x4b, 0x78, 0x72, 0x3e, 0x1e, 0x93, 0x3a, 0x45, + 0x05, 0x9c, 0xa8, 0x55, 0xbd, 0x95, 0xc7, 0x60, 0x66, 0x1e, 0x7d, 0x2b, 0x26, 0x63, 0x9c, 0x9a, 0x91, 0x91, 0xb5, + 0x0b, 0x41, 0x5e, 0xec, 0x20, 0xbf, 0x53, 0x48, 0x7e, 0x74, 0x27, 0x03, 0x1a, 0x51, 0x10, 0x54, 0x8e, 0x1f, 0x28, + 0x94, 0x81, 0xb1, 0x7c, 0x6e, 0x6b, 0x3f, 0x21, 0xf6, 0x8c, 0x62, 0x19, 0xcf, 0x36, 0xe3, 0x39, 0x2f, 0x7f, 0xb1, + 0xa7, 0x41, 0x96, 0xd8, 0x7c, 0x26, 0x9e, 0x8e, 0x78, 0x68, 0x9b, 0x79, 0x41, 0xed, 0x04, 0xf0, 0x5e, 0x6a, 0x97, + 0xe6, 0x7a, 0xaa, 0xf5, 0x87, 0x91, 0xf6, 0x3e, 0x08, 0x52, 0x3e, 0x4f, 0xc2, 0xca, 0x43, 0x14, 0x28, 0xaa, 0x6d, + 0xc1, 0xf3, 0x93, 0x3d, 0xa7, 0x3c, 0x8a, 0x25, 0xb2, 0x59, 0x14, 0xd9, 0xd7, 0xac, 0xab, 0x3c, 0xa5, 0xfe, 0xc9, + 0xa8, 0x0f, 0xfe, 0x4d, 0x11, 0x1f, 0x71, 0xc3, 0x7f, 0x17, 0xab, 0xaa, 0xdf, 0xb4, 0x37, 0x5a, 0x28, 0x7d, 0x01, + 0x2f, 0x2e, 0x8a, 0xcb, 0xad, 0x5f, 0x3e, 0xf6, 0x52, 0x84, 0x26, 0x12, 0xe6, 0x16, 0x71, 0x6a, 0x3b, 0x28, 0x26, + 0xdf, 0xcf, 0x05, 0x74, 0x8a, 0x59, 0x71, 0xeb, 0x17, 0x35, 0x16, 0x1c, 0xde, 0x39, 0xe0, 0xa2, 0xf1, 0x64, 0x36, + 0x17, 0x42, 0xd1, 0x73, 0x50, 0xf5, 0x7b, 0xfb, 0x41, 0x32, 0x1b, 0xae, 0xdf, 0x38, 0x85, 0x13, 0x8b, 0x85, 0x9e, + 0x39, 0x87, 0xbf, 0x57, 0x9b, 0x1b, 0x2f, 0x65, 0xbd, 0xbe, 0x35, 0x7b, 0x7f, 0x8f, 0x9e, 0x53, 0xc6, 0xb6, 0xff, + 0x31, 0x44, 0xc2, 0x13, 0xbf, 0x5e, 0x84, 0x22, 0x5c, 0x13, 0x02, 0x1e, 0x54, 0xd2, 0xcd, 0x62, 0x55, 0x74, 0x9e, + 0xd3, 0x83, 0x77, 0x6b, 0xe1, 0xac, 0x30, 0x9c, 0xc6, 0x8e, 0xd3, 0x2e, 0xaf, 0xe8, 0xa9, 0x97, 0xb6, 0xfa, 0xa9, + 0x8b, 0xc3, 0x5b, 0x24, 0xae, 0x68, 0x39, 0x3e, 0x23, 0xd7, 0x7d, 0xd1, 0x54, 0xfe, 0x49, 0xd0, 0xf3, 0x32, 0xf8, + 0xbc, 0xc4, 0x55, 0x64, 0x6f, 0xbf, 0x6f, 0x57, 0x66, 0xb8, 0x5d, 0x79, 0xe7, 0x66, 0x77, 0xbf, 0xa3, 0xaa, 0xc6, + 0x9d, 0xe9, 0x6c, 0xe4, 0x1f, 0x96, 0x91, 0xd6, 0xd3, 0x2e, 0xdf, 0xfe, 0xaf, 0xd1, 0xef, 0x1f, 0xb7, 0x9e, 0xff, + 0xd2, 0x94, 0x32, 0x9f, 0xea, 0xb6, 0xe3, 0xa9, 0xe5, 0x72, 0x37, 0x56, 0xaf, 0xaf, 0x3f, 0xf9, 0x8c, 0x28, 0x3f, + 0x61, 0x12, 0x6c, 0x47, 0xeb, 0x32, 0xca, 0x95, 0x70, 0x8d, 0x66, 0xf6, 0xab, 0xed, 0x71, 0xfd, 0xb0, 0x9c, 0x66, + 0xf1, 0xea, 0xa3, 0xe4, 0x71, 0xb3, 0xb5, 0xbb, 0x5d, 0xcd, 0x4b, 0x9b, 0x57, 0x0b, 0x4a, 0x63, 0xc2, 0xd7, 0xf6, + 0x23, 0x5b, 0x30, 0xde, 0x04, 0x24, 0x7f, 0x20, 0x6a, 0xbe, 0xab, 0x37, 0x7d, 0x5b, 0x4d, 0xa9, 0x98, 0xe6, 0x34, + 0x11, 0x4d, 0x33, 0xaa, 0x21, 0x4e, 0x8a, 0x30, 0x0e, 0xb6, 0x33, 0xcf, 0x4f, 0x18, 0xe0, 0x9c, 0xca, 0x5d, 0x4c, + 0xfc, 0xcb, 0x4f, 0x53, 0x6d, 0xee, 0x34, 0xcb, 0x11, 0x4c, 0x8e, 0x62, 0x77, 0x72, 0xd8, 0x6e, 0xa0, 0x59, 0xde, + 0xe2, 0x0d, 0x55, 0xa5, 0x94, 0xe7, 0x62, 0x26, 0x81, 0xa2, 0x52, 0x33, 0xe8, 0x70, 0xa0, 0x9b, 0xb9, 0xd9, 0x4f, + 0x87, 0xff, 0x1e, 0xbb, 0x88, 0xe1, 0x14, 0xfe, 0xb9, 0x18, 0x84, 0x50, 0xd8, 0xb7, 0x90, 0x6a, 0xc2, 0x91, 0xb2, + 0xe1, 0x3b, 0x56, 0xe2, 0xef, 0x38, 0x33, 0x61, 0x34, 0x13, 0x61, 0x45, 0xd3, 0x7c, 0x06, 0xdc, 0xe3, 0x82, 0xb1, + 0x27, 0xc2, 0x6f, 0x6d, 0xb7, 0xec, 0xd4, 0xf5, 0xd9, 0xd0, 0x39, 0xc9, 0x02, 0x8e, 0x1b, 0x02, 0x07, 0xd0, 0xb8, + 0x33, 0x2f, 0xb2, 0xb5, 0xae, 0x57, 0x1f, 0x62, 0x2e, 0xba, 0x15, 0x69, 0x32, 0x7e, 0xab, 0xe8, 0xd2, 0xdd, 0x05, + 0x20, 0x69, 0xf5, 0xee, 0xc7, 0x5e, 0x3f, 0x38, 0x72, 0xf3, 0x56, 0xef, 0x65, 0x18, 0x1e, 0x6b, 0xf2, 0x91, 0x86, + 0xed, 0xe4, 0x86, 0x97, 0x2b, 0xd5, 0x44, 0x9b, 0x71, 0x5b, 0x5e, 0xb1, 0xd6, 0x1b, 0xd2, 0x95, 0xdd, 0x79, 0xa8, + 0x72, 0x1b, 0x2f, 0x5b, 0x84, 0xc1, 0x5c, 0x9c, 0xcd, 0xe4, 0x17, 0x48, 0xf4, 0xf5, 0xcd, 0x5c, 0xbe, 0x03, 0xce, + 0x1e, 0xa1, 0x4e, 0xf8, 0xeb, 0x55, 0x4f, 0xa6, 0x31, 0x89, 0x13, 0x9b, 0xf0, 0x70, 0xba, 0x52, 0x2c, 0x14, 0x02, + 0xef, 0xa6, 0x87, 0x20, 0xd1, 0xcf, 0x98, 0x52, 0x99, 0x74, 0x0f, 0x4d, 0x1a, 0x63, 0x5c, 0x9a, 0x65, 0xa3, 0x2e, + 0x2d, 0xe2, 0xa7, 0xcd, 0x35, 0xd3, 0x9a, 0x2d, 0x8d, 0x8a, 0x2a, 0xdb, 0xdc, 0xaf, 0x6a, 0x6f, 0xab, 0x7a, 0xf7, + 0x10, 0x64, 0xb0, 0x73, 0xe5, 0xf9, 0x45, 0x59, 0x69, 0xc6, 0x60, 0xf0, 0x94, 0x6f, 0xc4, 0x02, 0x19, 0xb7, 0x79, + 0x77, 0x98, 0xf8, 0xca, 0xa4, 0xbf, 0x76, 0x0d, 0x34, 0xe6, 0xee, 0x4f, 0xd6, 0xe9, 0xca, 0x1a, 0x23, 0x6e, 0x5b, + 0x2d, 0xe1, 0x02, 0x27, 0x9e, 0x42, 0xb9, 0xe9, 0xf6, 0x9d, 0x2f, 0x0b, 0x93, 0x9a, 0xbc, 0xe0, 0xf5, 0x1b, 0x10, + 0x05, 0xb3, 0x00, 0x01, 0x11, 0xf7, 0xa2, 0xd8, 0x74, 0xc4, 0x22, 0x06, 0x09, 0xf4, 0x06, 0x42, 0xe0, 0x0c, 0x7f, + 0x50, 0xd0, 0xb5, 0x1d, 0x18, 0x01, 0x00, 0xe4, 0x66, 0x43, 0xea, 0xa5, 0x52, 0xb9, 0x27, 0xa2, 0x6a, 0xa8, 0x56, + 0x97, 0x74, 0xd7, 0x5c, 0x97, 0xc0, 0x79, 0x9d, 0xb5, 0xf9, 0x53, 0x09, 0xcb, 0xba, 0x21, 0xce, 0x65, 0x85, 0x02, + 0x13, 0x15, 0xcd, 0x99, 0xa7, 0x82, 0xc0, 0x5a, 0x95, 0xac, 0xf1, 0x2c, 0x85, 0xdd, 0xfd, 0x59, 0xcd, 0xdd, 0x80, + 0xd3, 0xd8, 0x41, 0x98, 0x19, 0xf0, 0xb6, 0x7d, 0xbc, 0x61, 0xec, 0xed, 0xca, 0x59, 0xf0, 0xc8, 0x24, 0x5f, 0x96, + 0xee, 0x7e, 0x82, 0x1b, 0x2b, 0xfd, 0x94, 0x3e, 0x87, 0xb0, 0x24, 0xfc, 0x77, 0x85, 0xe0, 0xba, 0x34, 0xbe, 0xab, + 0x9e, 0x0b, 0x22, 0x78, 0xba, 0x64, 0x6f, 0x13, 0x79, 0x5f, 0x91, 0x13, 0x49, 0xf7, 0xce, 0x1a, 0x1f, 0x89, 0xe5, + 0xe7, 0xda, 0xf8, 0xbb, 0xa7, 0xfa, 0xca, 0x2a, 0x27, 0x91, 0x8d, 0xcf, 0xe5, 0x80, 0x65, 0x9e, 0xf7, 0x29, 0xd4, + 0x58, 0xa0, 0xc7, 0x30, 0x7b, 0xdc, 0xb0, 0x88, 0x9f, 0xc1, 0x16, 0xee, 0x94, 0x9a, 0xc6, 0xb4, 0x92, 0xac, 0x52, + 0x04, 0xce, 0xa7, 0xe0, 0x72, 0xce, 0xd3, 0xed, 0x86, 0xc4, 0x2f, 0xed, 0xa3, 0xb8, 0x0e, 0xfa, 0x69, 0x29, 0x36, + 0x7f, 0xfa, 0x8a, 0x16, 0x92, 0xd8, 0x82, 0xce, 0xcb, 0x16, 0x22, 0x60, 0x2f, 0x3e, 0xa5, 0xec, 0xb6, 0xff, 0x28, + 0xd5, 0x0c, 0x78, 0x95, 0x0f, 0x94, 0xa1, 0x18, 0x33, 0xa4, 0xb4, 0xe2, 0xaa, 0x13, 0x49, 0xd0, 0xdb, 0x3c, 0x15, + 0x02, 0xa7, 0xb0, 0x0f, 0xa5, 0x64, 0xa2, 0x1f, 0xb0, 0xcc, 0x72, 0x97, 0xbe, 0xe4, 0x9a, 0xf5, 0x76, 0xd7, 0x28, + 0x09, 0xcc, 0x04, 0xf9, 0x59, 0xf0, 0x89, 0xdb, 0x9e, 0xdc, 0x2d, 0xb9, 0x22, 0x30, 0x7f, 0x92, 0x89, 0xe0, 0xd8, + 0x40, 0x3e, 0x93, 0x8b, 0x27, 0x91, 0xa8, 0xa4, 0xd0, 0x2e, 0x39, 0x3a, 0x7a, 0xd7, 0x49, 0x6a, 0x15, 0x6b, 0x1d, + 0x0a, 0x1d, 0xb7, 0x71, 0x53, 0x59, 0xc7, 0x73, 0x12, 0xa3, 0xf6, 0xe8, 0x2e, 0x49, 0xdb, 0xec, 0xee, 0x54, 0x1a, + 0xa1, 0x92, 0xea, 0x0a, 0x19, 0x4b, 0x33, 0x92, 0x38, 0x3f, 0xb1, 0x45, 0x88, 0x18, 0x90, 0x58, 0x3a, 0xcb, 0x21, + 0x56, 0xdd, 0xa7, 0x0d, 0xcb, 0x71, 0xe8, 0x94, 0x25, 0x01, 0x45, 0xb3, 0x34, 0x46, 0x07, 0x03, 0xc7, 0xd1, 0x1c, + 0x55, 0x0a, 0x8c, 0x99, 0x97, 0x39, 0xec, 0x7c, 0x95, 0xa1, 0x73, 0x69, 0xa4, 0xd9, 0xf0, 0x75, 0x31, 0xb5, 0x47, + 0xa9, 0xce, 0xb5, 0x11, 0xc9, 0xc8, 0x41, 0x7b, 0x2e, 0x53, 0x11, 0x56, 0x71, 0x51, 0xee, 0xc6, 0x92, 0x59, 0x17, + 0x62, 0x9c, 0x8c, 0xf6, 0x6a, 0xb2, 0x68, 0x55, 0x40, 0x39, 0xbe, 0x64, 0xda, 0x03, 0x2e, 0x59, 0xdb, 0x7e, 0x29, + 0x27, 0x75, 0x81, 0xe6, 0x7c, 0xac, 0x2b, 0xfc, 0x8d, 0x2c, 0x80, 0x31, 0x3b, 0xf2, 0xa5, 0xdd, 0x6e, 0xfe, 0x25, + 0x27, 0xdb, 0x5f, 0xc6, 0x39, 0xf3, 0x98, 0x2b, 0x61, 0xec, 0x5a, 0x4d, 0xf4, 0x64, 0x86, 0x1a, 0x9f, 0x13, 0x70, + 0xc9, 0xeb, 0x27, 0x03, 0xec, 0x8c, 0xc7, 0xb9, 0xa4, 0x9d, 0xd2, 0xa5, 0xd2, 0x52, 0x9c, 0xc6, 0xdc, 0x64, 0x2d, + 0xab, 0xdd, 0x3f, 0x0f, 0xb1, 0x5c, 0xc1, 0xbe, 0xf5, 0x91, 0x75, 0x1f, 0xdf, 0x97, 0x29, 0x6f, 0xbd, 0x9a, 0xd1, + 0xaf, 0xb6, 0xc2, 0x84, 0xbd, 0xa3, 0x6b, 0x0c, 0x93, 0x1d, 0x6b, 0x15, 0xa4, 0x3d, 0xb2, 0xa3, 0x45, 0x32, 0x1e, + 0x4e, 0x68, 0x55, 0x7b, 0x21, 0x43, 0x1e, 0x7e, 0x6e, 0x34, 0x12, 0x8b, 0xa4, 0x58, 0x40, 0xe7, 0x7b, 0x54, 0x57, + 0x4b, 0x8a, 0xe9, 0x49, 0x6b, 0x32, 0x78, 0xd4, 0x99, 0x53, 0xe7, 0xca, 0x2f, 0x2c, 0xf7, 0x55, 0x53, 0x06, 0x03, + 0x71, 0xfd, 0x09, 0xea, 0xae, 0xec, 0x71, 0x2e, 0x31, 0x81, 0x9a, 0xb2, 0x68, 0xe2, 0x48, 0x32, 0xf9, 0xe5, 0xcb, + 0x4c, 0x9b, 0xec, 0xc3, 0x55, 0x24, 0x82, 0x17, 0x23, 0xb1, 0x85, 0xdf, 0xe9, 0x02, 0xcb, 0xa2, 0x3e, 0x6c, 0x1a, + 0x73, 0xe3, 0x28, 0x19, 0xae, 0x50, 0x04, 0x8e, 0x5a, 0x60, 0xa0, 0x24, 0x27, 0x6a, 0xb2, 0x66, 0x76, 0x9e, 0x0e, + 0x5e, 0x5c, 0x68, 0x1d, 0xdf, 0x11, 0x3a, 0xa4, 0x33, 0x94, 0x57, 0xf0, 0xcd, 0xbe, 0xcb, 0x5c, 0x60, 0xaa, 0x25, + 0x7d, 0x8c, 0x5e, 0x33, 0x7d, 0xec, 0x1a, 0xbc, 0x10, 0x3d, 0xb7, 0x96, 0x67, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, + 0x1e, 0x87, 0x77, 0x07, 0x59, 0xb1, 0x88, 0x6c, 0x77, 0x2e, 0x2e, 0x5b, 0x14, 0xe8, 0x14, 0x27, 0xeb, 0x36, 0xa8, + 0xd7, 0xa0, 0x29, 0xe7, 0x58, 0xa5, 0x31, 0x3b, 0x30, 0x43, 0x90, 0x0b, 0x1d, 0xb6, 0x44, 0xa9, 0xf4, 0x23, 0x4e, + 0x04, 0x1b, 0xac, 0xee, 0xcc, 0x66, 0x59, 0xb3, 0xc3, 0x9e, 0x93, 0xfa, 0x9f, 0x78, 0xd7, 0xb6, 0x9c, 0xd7, 0xc2, + 0x48, 0x13, 0xb2, 0xb1, 0x40, 0x7a, 0x94, 0xbf, 0xf9, 0xdb, 0x87, 0x7c, 0x61, 0xfa, 0xf5, 0xb0, 0x2a, 0x64, 0xc6, + 0x4e, 0xe0, 0x00, 0x32, 0x41, 0x06, 0x1f, 0x29, 0x3d, 0x93, 0x82, 0x91, 0xd6, 0xf7, 0xc2, 0x0c, 0xb6, 0x63, 0xb2, + 0x10, 0x1d, 0xab, 0xdd, 0x0c, 0x20, 0x87, 0x36, 0xb6, 0x7c, 0x0d, 0xa5, 0x55, 0x92, 0x96, 0x72, 0x71, 0x40, 0x61, + 0xd5, 0x5b, 0x71, 0xd3, 0x4b, 0xfb, 0x08, 0x4d, 0xbf, 0x4b, 0x06, 0xca, 0x94, 0x80, 0xf6, 0x33, 0xf3, 0x4a, 0x07, + 0x11, 0x1e, 0xa6, 0x34, 0x01, 0xd8, 0x10, 0x2b, 0x5b, 0xec, 0xad, 0xc5, 0xc2, 0x7b, 0xd2, 0x02, 0xd6, 0x34, 0x73, + 0xd8, 0x09, 0x58, 0x5f, 0xee, 0x26, 0x62, 0x53, 0xfe, 0x6c, 0x25, 0xd6, 0x1c, 0x71, 0x11, 0x1f, 0xbd, 0x5f, 0xd7, + 0xa7, 0x29, 0x16, 0xa9, 0x73, 0x6f, 0x3d, 0xc9, 0x00, 0xff, 0xbc, 0x78, 0x0e, 0x9c, 0xde, 0x25, 0xdf, 0xf7, 0xcf, + 0xd6, 0x92, 0xc5, 0xd5, 0xc0, 0xf1, 0x55, 0x2b, 0x93, 0xd3, 0x15, 0x2d, 0x05, 0x65, 0xb0, 0xf9, 0xbe, 0x77, 0x49, + 0x21, 0x6e, 0xa0, 0x3c, 0x9a, 0xf9, 0x08, 0xe3, 0xca, 0x2b, 0x7c, 0x4a, 0x8d, 0x78, 0x68, 0x26, 0x2c, 0x10, 0x49, + 0xad, 0x44, 0xc5, 0x82, 0x54, 0x55, 0x4f, 0x5f, 0x90, 0xa1, 0xe7, 0x02, 0x3e, 0xeb, 0x53, 0x3c, 0x38, 0x5b, 0x3b, + 0x0e, 0xa2, 0x68, 0x2b, 0x7e, 0x56, 0xa8, 0x10, 0xfc, 0x57, 0x81, 0x1a, 0x29, 0x32, 0x02, 0xcc, 0xf5, 0x84, 0xba, + 0x3f, 0x90, 0x27, 0x3c, 0x3f, 0xa5, 0x82, 0xa5, 0x42, 0x4e, 0xea, 0x94, 0x88, 0x28, 0xff, 0xca, 0xcb, 0x26, 0x41, + 0xb3, 0x9c, 0xd2, 0x98, 0x7c, 0xc4, 0x92, 0x08, 0xae, 0x66, 0x4d, 0x3e, 0xfd, 0x88, 0x52, 0xdd, 0xcb, 0x0c, 0xd7, + 0xa6, 0x04, 0x0d, 0x85, 0x6f, 0x3c, 0xe0, 0xe8, 0xd3, 0xed, 0x74, 0x42, 0x6e, 0x4b, 0x19, 0x9c, 0x7c, 0x44, 0x87, + 0xb9, 0xf5, 0xd5, 0x4c, 0xd0, 0xdc, 0x98, 0xb7, 0x0d, 0xc5, 0x2d, 0x21, 0xdb, 0xec, 0xd7, 0xbb, 0x35, 0xf9, 0x3a, + 0xfd, 0xe0, 0x92, 0xa6, 0x4c, 0xe8, 0x62, 0xe2, 0x17, 0x61, 0x86, 0x36, 0xdc, 0xf0, 0xe5, 0x8b, 0xed, 0xe5, 0x70, + 0x1c, 0x20, 0x73, 0x2c, 0xca, 0xef, 0xa8, 0xed, 0x19, 0x50, 0x50, 0x8e, 0xd1, 0x55, 0x6b, 0xc0, 0xd8, 0x8e, 0xad, + 0x75, 0x5f, 0x9e, 0x64, 0x0d, 0x50, 0x4f, 0xb5, 0x72, 0x8a, 0xc1, 0xd8, 0x87, 0x96, 0x6e, 0x03, 0x6c, 0x90, 0x3a, + 0x2c, 0x1c, 0x4c, 0xeb, 0x1f, 0x2d, 0x5e, 0x68, 0x01, 0x22, 0x6f, 0x92, 0xa5, 0x35, 0xde, 0x13, 0x7f, 0x07, 0xd7, + 0x14, 0x7c, 0x8f, 0xe3, 0x07, 0x89, 0xf7, 0x3c, 0xbb, 0xac, 0x28, 0x2a, 0x61, 0x9e, 0x0b, 0x6f, 0x88, 0xb0, 0x62, + 0x82, 0x98, 0x63, 0x1e, 0x72, 0x42, 0xf6, 0x85, 0x5b, 0xd6, 0xb6, 0x3a, 0x04, 0x3c, 0xbc, 0xef, 0xfb, 0xe9, 0x85, + 0x80, 0xa2, 0x2b, 0x3b, 0x77, 0x9c, 0x47, 0x33, 0x60, 0x35, 0x43, 0xbe, 0xc5, 0x76, 0x98, 0x8a, 0x32, 0x4a, 0x08, + 0xe2, 0x06, 0x2b, 0xb0, 0x30, 0xf4, 0xac, 0x71, 0xf5, 0x89, 0xd3, 0x7a, 0xca, 0x00, 0x80, 0x52, 0xda, 0xa1, 0x7b, + 0x86, 0x32, 0x61, 0xf4, 0xd2, 0x2a, 0x50, 0x6e, 0xb9, 0x3a, 0x78, 0xd9, 0xb9, 0xc7, 0x30, 0xb0, 0x33, 0x5b, 0xeb, + 0x4c, 0xe3, 0x40, 0x64, 0x19, 0x08, 0x10, 0x87, 0xba, 0x48, 0x95, 0x86, 0xa2, 0xeb, 0x00, 0xaf, 0x45, 0x7d, 0x92, + 0x61, 0x61, 0x21, 0xee, 0x56, 0xa2, 0x63, 0xc0, 0x34, 0x5e, 0xe3, 0xed, 0x42, 0x2a, 0x04, 0x5e, 0x09, 0x91, 0x07, + 0x12, 0xd9, 0x03, 0xed, 0xa0, 0x6c, 0x00, 0x24, 0xb9, 0x13, 0x5c, 0x29, 0x48, 0x6b, 0x09, 0xe5, 0x64, 0xff, 0x4f, + 0x54, 0x1a, 0x65, 0x02, 0xf2, 0x99, 0x6b, 0x89, 0x49, 0xe3, 0x25, 0x30, 0x17, 0x0e, 0x24, 0x1f, 0x66, 0xb0, 0x93, + 0x05, 0x8d, 0xc8, 0x94, 0xe9, 0xdc, 0x0a, 0xb6, 0xf1, 0xea, 0x4d, 0xd2, 0x48, 0x54, 0x98, 0xfe, 0xe6, 0x57, 0x97, + 0x4f, 0x5d, 0x18, 0x61, 0xf9, 0x5b, 0x2e, 0xfb, 0x1c, 0xf9, 0x4d, 0x18, 0x25, 0xed, 0x6c, 0xf8, 0x52, 0xc9, 0x74, + 0xdc, 0x9e, 0x9f, 0x69, 0x6d, 0xb4, 0x78, 0x0f, 0xf2, 0x05, 0xef, 0x41, 0x75, 0x47, 0x92, 0xec, 0x73, 0x5a, 0x93, + 0xd4, 0x35, 0xaa, 0xca, 0x70, 0x90, 0x68, 0x8c, 0x8b, 0xd4, 0x9a, 0x98, 0x53, 0xb3, 0x78, 0x1a, 0x40, 0x32, 0x8d, + 0xfd, 0x8c, 0x2a, 0x0f, 0x2c, 0x27, 0x36, 0x2f, 0xa6, 0x27, 0xd2, 0x68, 0xba, 0x20, 0x97, 0x9f, 0x52, 0xef, 0x66, + 0x4a, 0xd1, 0xb2, 0x58, 0x86, 0xc3, 0xd9, 0x41, 0x98, 0x23, 0x5d, 0xbe, 0x9a, 0xeb, 0xa3, 0x2f, 0x19, 0x26, 0xa5, + 0x4b, 0x57, 0xf2, 0x67, 0x94, 0x2c, 0x5f, 0x08, 0xab, 0x0f, 0xdb, 0x26, 0x08, 0x64, 0xd4, 0xa0, 0x1c, 0xe1, 0xd6, + 0xf2, 0x00, 0x1b, 0x1b, 0xf2, 0xe0, 0xec, 0xa6, 0x2a, 0x7b, 0x64, 0x9a, 0xb3, 0xa9, 0xa0, 0xf2, 0x46, 0xa3, 0x85, + 0x66, 0x26, 0x9b, 0xaf, 0x2e, 0xbe, 0x4a, 0x90, 0x1b, 0xa7, 0x83, 0xd5, 0x52, 0x7d, 0x68, 0x42, 0x56, 0x1f, 0xc8, + 0xcb, 0xa4, 0xa8, 0xaa, 0x85, 0x22, 0xed, 0x94, 0xfc, 0x34, 0x9a, 0xba, 0xeb, 0x4e, 0x72, 0x42, 0x65, 0x35, 0x89, + 0x8a, 0x02, 0x5b, 0x78, 0x59, 0x08, 0x15, 0x40, 0x71, 0xb7, 0xfb, 0xa1, 0x02, 0xe5, 0xcf, 0x45, 0x0e, 0xee, 0x78, + 0xaf, 0x0e, 0x4c, 0xcb, 0x00, 0x92, 0xfc, 0x4c, 0x26, 0xbd, 0x69, 0xdc, 0xbb, 0x87, 0xf2, 0xf0, 0x59, 0x54, 0x62, + 0xee, 0x43, 0x7e, 0x15, 0x03, 0x8d, 0x59, 0x02, 0xee, 0xb7, 0xcb, 0x5e, 0x7c, 0x94, 0x74, 0x82, 0xcc, 0x50, 0xb9, + 0x36, 0xde, 0x37, 0xf5, 0x48, 0x85, 0x91, 0x4b, 0x81, 0x7c, 0x70, 0xf7, 0xfb, 0x3d, 0x40, 0x31, 0xfe, 0xa2, 0x7d, + 0xf1, 0x3a, 0x29, 0x37, 0x31, 0x04, 0x24, 0x7a, 0x5d, 0x8e, 0x36, 0x08, 0xc8, 0xd1, 0x24, 0x41, 0x7e, 0x3c, 0x9e, + 0x49, 0xbe, 0xec, 0x38, 0xc5, 0x36, 0x95, 0x25, 0xa6, 0xdc, 0xfb, 0xe5, 0x2a, 0x0f, 0x84, 0xfd, 0x39, 0x91, 0x46, + 0xa4, 0x00, 0x30, 0xcc, 0x16, 0x78, 0x04, 0x0e, 0x34, 0xf1, 0xe2, 0x44, 0xad, 0xc2, 0x81, 0x86, 0xcd, 0xd9, 0x8b, + 0x98, 0x54, 0x64, 0xcc, 0x3e, 0x7e, 0x65, 0x5c, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xe7, 0xb2, 0x4a, 0x00, + 0xb5, 0x10, 0x0a, 0xa1, 0xc1, 0x20, 0xc1, 0xf8, 0x46, 0xef, 0x4f, 0xa8, 0x47, 0x14, 0x8a, 0x57, 0xab, 0xc5, 0x44, + 0xbb, 0x7c, 0xc7, 0x2d, 0x4c, 0x97, 0x8c, 0x41, 0x75, 0xaf, 0xd8, 0x23, 0x2f, 0x5e, 0xad, 0xca, 0xed, 0xd8, 0xa9, + 0xea, 0xd6, 0x18, 0xa1, 0xee, 0xe6, 0xb5, 0xce, 0x8d, 0x69, 0x22, 0xb8, 0x2c, 0x68, 0xb6, 0x38, 0xf4, 0x74, 0xfe, + 0xe1, 0xca, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0x27, 0x89, 0x60, 0xa8, 0x51, 0x5e, 0x08, 0x23, 0x52, 0xff, + 0xce, 0x90, 0x7b, 0x96, 0xa2, 0x53, 0x6d, 0x54, 0x97, 0x2d, 0x80, 0x2d, 0x7d, 0x0d, 0x23, 0x43, 0x21, 0x74, 0xc4, + 0x30, 0xd2, 0x2e, 0xf5, 0x51, 0x66, 0x48, 0x16, 0x5d, 0x57, 0x45, 0x90, 0x79, 0xd7, 0x4e, 0xde, 0x24, 0x89, 0x12, + 0x6a, 0xe8, 0x67, 0xe6, 0x93, 0x3a, 0x3b, 0x89, 0x53, 0x5a, 0x4b, 0xa1, 0xe6, 0xa4, 0xba, 0x8e, 0xe9, 0x3b, 0x55, + 0x29, 0xa1, 0x27, 0x8c, 0xdd, 0x7b, 0x33, 0x78, 0xd5, 0xc6, 0x18, 0x9f, 0x6b, 0xfe, 0x79, 0xd2, 0x0e, 0xe3, 0xd0, + 0x03, 0xd4, 0x02, 0x39, 0x85, 0xd6, 0x80, 0xcc, 0xff, 0xdd, 0xd9, 0xd9, 0x9e, 0x10, 0xb6, 0x4d, 0x82, 0x96, 0xcb, + 0xad, 0x5c, 0x4f, 0x42, 0x59, 0x37, 0x4f, 0x5a, 0xe7, 0x24, 0xb1, 0x38, 0xd8, 0x22, 0x39, 0x52, 0xe6, 0x13, 0x7c, + 0xce, 0x79, 0x42, 0xea, 0x07, 0x5b, 0xf8, 0xce, 0xc6, 0x77, 0x15, 0x21, 0xf7, 0x3d, 0x36, 0x2f, 0x63, 0x08, 0x11, + 0x89, 0xc9, 0xdc, 0xab, 0x23, 0x1f, 0x44, 0x91, 0x0b, 0x55, 0x7b, 0xc4, 0x3c, 0x21, 0xc0, 0x54, 0xb5, 0x1f, 0x9c, + 0xf6, 0xe5, 0x42, 0xf6, 0xb7, 0x58, 0x19, 0xa0, 0x9c, 0x33, 0xa9, 0x97, 0xff, 0xf9, 0x52, 0xeb, 0xfe, 0xf7, 0x0b, + 0xac, 0xcb, 0x6d, 0x3b, 0xdf, 0xe9, 0x01, 0x60, 0x00, 0x78, 0x5d, 0x50, 0xb5, 0xca, 0x8b, 0x5d, 0x7d, 0x51, 0x6f, + 0x9b, 0x20, 0x24, 0x01, 0xef, 0x2a, 0xe9, 0xff, 0x3e, 0xd3, 0x40, 0xd0, 0x7c, 0x93, 0xec, 0x8f, 0x6c, 0x10, 0x89, + 0x3c, 0xf5, 0xa4, 0xc5, 0xc7, 0x3b, 0xe1, 0xdd, 0xc1, 0xf8, 0x65, 0x6c, 0x5d, 0xd1, 0x3d, 0xf3, 0x07, 0x09, 0x2c, + 0x07, 0x6a, 0xb7, 0x1e, 0xbd, 0x71, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x33, 0x98, 0x12, 0x07, 0x81, 0xa2, 0x91, 0x16, + 0xe0, 0x49, 0x4c, 0x13, 0x4c, 0x0b, 0x08, 0xa9, 0x53, 0x40, 0x62, 0xbe, 0x1d, 0x96, 0x23, 0x78, 0x95, 0x22, 0x27, + 0x9e, 0x38, 0x37, 0xab, 0x0a, 0xe8, 0x3e, 0x44, 0xd5, 0xfc, 0x74, 0xf3, 0x06, 0x77, 0xe0, 0x26, 0xf6, 0x8d, 0xe3, + 0x0f, 0x71, 0xbf, 0xa1, 0x81, 0xe4, 0x1c, 0x12, 0x8b, 0xbc, 0xe6, 0x61, 0x3c, 0x93, 0x84, 0x3a, 0xdc, 0x42, 0x48, + 0xe7, 0x17, 0x30, 0x98, 0x17, 0x4c, 0x63, 0xab, 0xce, 0x22, 0x20, 0xe4, 0x3c, 0xbe, 0x1d, 0xc7, 0xb7, 0x1e, 0xac, + 0x07, 0xd1, 0x5e, 0x44, 0xfc, 0xad, 0x2d, 0x6a, 0x14, 0x2a, 0x0f, 0xa7, 0xd6, 0xd7, 0xd4, 0x70, 0x0c, 0x71, 0xf8, + 0x57, 0x90, 0x48, 0x09, 0x64, 0xb7, 0xed, 0x6b, 0x2e, 0xe8, 0xf4, 0x6e, 0xa7, 0x23, 0xb4, 0xd6, 0x0c, 0x2a, 0x73, + 0xd5, 0xac, 0xc1, 0xca, 0xb4, 0xd3, 0xff, 0x61, 0x73, 0x5b, 0x92, 0x80, 0x20, 0x5a, 0xe9, 0xf7, 0x55, 0x98, 0xb0, + 0xc4, 0x18, 0x03, 0x1e, 0x09, 0x32, 0xe7, 0x29, 0x44, 0x12, 0x0b, 0x30, 0x1c, 0xad, 0xd5, 0xc5, 0x7f, 0x56, 0xdc, + 0xfa, 0xd1, 0xe8, 0x4d, 0x9b, 0x64, 0xca, 0xcd, 0xaa, 0x05, 0xf0, 0xc7, 0x59, 0x65, 0xd9, 0xd6, 0x33, 0x40, 0xca, + 0x93, 0x2c, 0x09, 0x2e, 0xdd, 0x82, 0x93, 0xf2, 0x49, 0x4a, 0x9b, 0xe4, 0xca, 0xfd, 0xc2, 0x55, 0xf6, 0x3d, 0x53, + 0x04, 0x87, 0xf5, 0x4c, 0x73, 0x60, 0x01, 0x16, 0xcc, 0xa5, 0x74, 0xb1, 0xda, 0x19, 0x12, 0x09, 0x56, 0x92, 0x0f, + 0xcb, 0x0c, 0x49, 0x8f, 0x6f, 0xab, 0x8b, 0x84, 0x9c, 0xf1, 0xbc, 0xad, 0x01, 0x07, 0x78, 0x77, 0x2e, 0x46, 0x5a, + 0xef, 0xb0, 0x23, 0xef, 0x9d, 0x92, 0x52, 0x52, 0x35, 0x05, 0xe4, 0xd1, 0x86, 0x20, 0xed, 0x36, 0xc5, 0xa0, 0xbf, + 0x19, 0x2c, 0x8d, 0x7b, 0xcf, 0x25, 0x46, 0x0a, 0xa4, 0xda, 0x99, 0x3e, 0x70, 0xe1, 0x2f, 0xc8, 0xa9, 0xf9, 0xe0, + 0x9d, 0x6d, 0xd8, 0x4f, 0x4b, 0x0e, 0x08, 0xc5, 0xc5, 0x5d, 0x7f, 0xd4, 0x27, 0xb6, 0x58, 0x1c, 0x5c, 0xbe, 0x51, + 0xf6, 0xa8, 0x09, 0xec, 0xc1, 0x07, 0x5a, 0x46, 0x2a, 0x0d, 0x0a, 0x25, 0xc5, 0xbb, 0x73, 0x63, 0xda, 0x5b, 0x9b, + 0x5a, 0x56, 0x58, 0x55, 0x83, 0x55, 0xf5, 0xb1, 0xc4, 0xd2, 0xd2, 0xb6, 0xd8, 0x02, 0x73, 0xdd, 0x7b, 0x01, 0x26, + 0x5f, 0xc7, 0x47, 0x4c, 0x4b, 0x89, 0xee, 0x41, 0xa2, 0x2f, 0xe3, 0x30, 0x80, 0x8b, 0x2a, 0x08, 0x20, 0xbd, 0xae, + 0xe3, 0x48, 0x6c, 0xd6, 0x98, 0xe8, 0xb0, 0x68, 0xd3, 0x08, 0x54, 0x84, 0x1a, 0x18, 0x01, 0x2d, 0xe4, 0xca, 0x54, + 0x2c, 0x9d, 0xf9, 0xec, 0x02, 0x4b, 0x9f, 0xfb, 0x69, 0x5b, 0xdb, 0x5d, 0x31, 0x4b, 0x15, 0x24, 0xa5, 0x51, 0xd7, + 0x1b, 0x7d, 0xbb, 0x76, 0x67, 0x5d, 0xe3, 0x3d, 0x6e, 0xa4, 0x68, 0x6d, 0x2a, 0xd7, 0x47, 0xc9, 0x76, 0xfb, 0xdd, + 0xd2, 0x02, 0xd5, 0xcc, 0x59, 0x5a, 0x3b, 0x45, 0xf6, 0x3b, 0x0a, 0x70, 0xf9, 0x8e, 0x37, 0x18, 0x03, 0x64, 0x39, + 0xd2, 0xc6, 0xdc, 0x9a, 0x7c, 0xe4, 0x1e, 0x68, 0xe7, 0xdf, 0xbf, 0x4a, 0x82, 0xad, 0x3f, 0x2d, 0xc6, 0x65, 0xf0, + 0xcc, 0x61, 0x14, 0x38, 0x0a, 0x1f, 0xbd, 0x47, 0x5e, 0xad, 0x94, 0x31, 0xad, 0xcd, 0xe9, 0x4b, 0x23, 0x0d, 0x3e, + 0xd8, 0x86, 0xb5, 0x48, 0xae, 0xc7, 0xc8, 0xc6, 0x5e, 0xb7, 0xb0, 0x16, 0xc6, 0xe2, 0x8e, 0x21, 0xe5, 0x53, 0x49, + 0x09, 0xdc, 0xad, 0xe0, 0xe9, 0xc9, 0x9f, 0x52, 0x3e, 0x95, 0xd3, 0x4d, 0xae, 0xb3, 0x2f, 0x7f, 0x77, 0x4e, 0x17, + 0x1e, 0x34, 0x02, 0xfb, 0x32, 0x4b, 0x97, 0x55, 0x72, 0x2d, 0x90, 0x97, 0x6e, 0x3c, 0x17, 0xe5, 0xfa, 0xeb, 0x6e, + 0x23, 0x4c, 0x60, 0x9f, 0x2e, 0xf9, 0xdb, 0x7b, 0xf0, 0x7e, 0x2e, 0xe7, 0xf5, 0xb9, 0xb7, 0xa8, 0x93, 0x42, 0xbe, + 0xf9, 0xe4, 0x8b, 0x5d, 0x71, 0x9c, 0x10, 0x1f, 0xe8, 0x43, 0xe3, 0xbd, 0x5f, 0x8b, 0x04, 0xc4, 0x0a, 0xbf, 0x24, + 0x40, 0x44, 0x06, 0x70, 0xbc, 0xf3, 0xcf, 0xb1, 0xdb, 0x2c, 0x8d, 0x11, 0xdb, 0xe4, 0x61, 0x69, 0x4a, 0xda, 0xce, + 0x83, 0x0d, 0xf7, 0x67, 0x85, 0x52, 0x9c, 0x00, 0xcb, 0x33, 0xed, 0xb4, 0x8b, 0xbd, 0x08, 0xae, 0x69, 0x9b, 0x79, + 0xf5, 0x16, 0xf4, 0x84, 0xed, 0x2c, 0xcf, 0x63, 0x7b, 0xcb, 0xcf, 0xea, 0x20, 0xc2, 0x90, 0xbb, 0xe2, 0x4c, 0x5a, + 0x26, 0x90, 0x2a, 0xa6, 0x7d, 0xe3, 0xb8, 0xcd, 0x19, 0x3b, 0xf1, 0x02, 0xd1, 0x3f, 0x4e, 0x35, 0x2a, 0x9a, 0x4f, + 0xcd, 0x07, 0x8e, 0x34, 0x30, 0xf1, 0xab, 0x8d, 0xca, 0x54, 0x8e, 0x75, 0x00, 0x94, 0x2c, 0xd1, 0x9f, 0xb6, 0x28, + 0xad, 0x2b, 0x84, 0x51, 0xe1, 0x76, 0xf9, 0xf7, 0xf7, 0x36, 0xad, 0x62, 0x22, 0xda, 0xa3, 0x2b, 0xcd, 0xd9, 0x87, + 0x13, 0xf1, 0x96, 0x61, 0x07, 0x8a, 0x31, 0xa3, 0x03, 0x99, 0x94, 0xd5, 0x1e, 0x8d, 0x55, 0xe9, 0x46, 0x9e, 0x27, + 0x45, 0xa4, 0xbd, 0x80, 0xf5, 0xbd, 0xe0, 0x90, 0x8f, 0xef, 0x95, 0x21, 0x79, 0x5f, 0x77, 0x04, 0xe5, 0x00, 0xee, + 0x37, 0x4c, 0x1a, 0x7c, 0xf0, 0xcd, 0x5f, 0x72, 0xc5, 0xe8, 0xea, 0x95, 0x53, 0x36, 0xcd, 0xd8, 0x97, 0x1c, 0x26, + 0x57, 0xb8, 0x90, 0xed, 0xd3, 0x18, 0x79, 0xa3, 0x40, 0x72, 0x8e, 0x8d, 0x43, 0x3e, 0x6d, 0x58, 0x6f, 0x47, 0x52, + 0xba, 0x80, 0x90, 0xa9, 0x40, 0xd3, 0x83, 0x3a, 0x58, 0x92, 0x91, 0xd6, 0xa9, 0xbc, 0x8b, 0x8e, 0xfa, 0x3d, 0xeb, + 0x41, 0x73, 0xa5, 0xac, 0x0a, 0x84, 0x9b, 0xe5, 0xe5, 0x44, 0xc5, 0xb2, 0x3d, 0x9b, 0xca, 0xc7, 0xe5, 0x20, 0xb2, + 0x69, 0xda, 0xf9, 0xdb, 0xbe, 0x94, 0x22, 0x82, 0x07, 0xd4, 0x43, 0x08, 0xa1, 0xb4, 0x21, 0x03, 0x3d, 0xf2, 0x74, + 0x0d, 0xef, 0xf4, 0x03, 0x85, 0x7e, 0x3b, 0x0b, 0x82, 0xe0, 0xf8, 0x4a, 0xe8, 0x64, 0xcb, 0x9d, 0xda, 0x75, 0xde, + 0x63, 0x9f, 0xc8, 0x5e, 0x38, 0x79, 0xe5, 0xd2, 0xb4, 0x44, 0xdb, 0xd5, 0x8d, 0x3b, 0xff, 0xd8, 0xe1, 0x27, 0xa5, + 0x29, 0xa2, 0xd6, 0x24, 0x75, 0x3a, 0x58, 0x6e, 0x89, 0xa2, 0x45, 0x83, 0x83, 0x08, 0x74, 0x9c, 0x9c, 0x17, 0x71, + 0xdb, 0x0d, 0x05, 0xbe, 0xe4, 0x93, 0x70, 0x8f, 0x32, 0x16, 0xd0, 0x38, 0x52, 0xd0, 0x95, 0x16, 0x47, 0xb5, 0x32, + 0x86, 0x62, 0xcc, 0xde, 0x60, 0x0c, 0x65, 0x05, 0x1a, 0xac, 0x63, 0xeb, 0x45, 0xba, 0x1b, 0xa7, 0xbc, 0x86, 0x66, + 0x40, 0xe3, 0x7e, 0xea, 0x6b, 0x66, 0x84, 0x30, 0x34, 0xe1, 0xed, 0xd1, 0x3b, 0x77, 0x6c, 0x7f, 0xa5, 0xbe, 0x20, + 0x0c, 0x85, 0x18, 0xb0, 0x8b, 0x47, 0x31, 0x5b, 0x58, 0x22, 0x01, 0x71, 0xe5, 0x3e, 0x38, 0x30, 0xcb, 0xf2, 0xe0, + 0x1d, 0xa2, 0x42, 0x7b, 0x6c, 0xe3, 0xa6, 0x78, 0x4a, 0xc8, 0x15, 0x18, 0xc6, 0xfe, 0x32, 0x7d, 0x34, 0xf2, 0x54, + 0xd2, 0x7f, 0x11, 0x5a, 0x3f, 0x7b, 0xa4, 0x5b, 0x2c, 0xbb, 0xad, 0x0b, 0x6e, 0xdf, 0xea, 0x9f, 0xa5, 0xae, 0x4c, + 0xa4, 0xff, 0xb1, 0xb1, 0x6e, 0x75, 0xd9, 0x77, 0xfd, 0xfe, 0x43, 0x27, 0xea, 0x20, 0xff, 0xf4, 0x75, 0xdd, 0xe2, + 0x10, 0x8a, 0x27, 0x1f, 0xda, 0x43, 0x03, 0xf1, 0x31, 0xcd, 0x9a, 0x4b, 0x72, 0xde, 0xd0, 0xd0, 0x3f, 0x2b, 0x5c, + 0xfb, 0x51, 0x1f, 0x7a, 0x5c, 0xcc, 0x7f, 0x4e, 0xbe, 0xc3, 0xdd, 0xe8, 0xa3, 0x0b, 0x8f, 0xe4, 0x5c, 0x24, 0x8f, + 0xc9, 0x9e, 0xfe, 0xd8, 0x76, 0x91, 0xd2, 0x08, 0x50, 0x47, 0xaf, 0x9b, 0x96, 0xa6, 0x6b, 0x92, 0xd2, 0x3c, 0x28, + 0x5f, 0xe0, 0xaa, 0x1f, 0xbd, 0x5f, 0xdb, 0x43, 0x21, 0x9f, 0xd8, 0x5e, 0x2e, 0x49, 0xb7, 0xa7, 0x0f, 0x6f, 0x33, + 0xad, 0xce, 0x48, 0x8d, 0x5b, 0xd8, 0x97, 0xdb, 0xa3, 0xd0, 0x81, 0x32, 0x4a, 0xaf, 0x48, 0xbc, 0xc4, 0x38, 0xb9, + 0xc9, 0x0f, 0x4a, 0xcd, 0xb1, 0x7d, 0x1c, 0x79, 0x83, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0xde, 0x83, 0xa1, 0x72, + 0x2a, 0x58, 0x31, 0x2d, 0xe9, 0x89, 0x01, 0xb0, 0x69, 0xf4, 0x4b, 0xa8, 0xb6, 0x3b, 0x81, 0x4e, 0x6f, 0x9a, 0x54, + 0xdb, 0xc4, 0xff, 0xbe, 0x6f, 0xf4, 0x28, 0x59, 0x4a, 0x01, 0x59, 0xf7, 0xfd, 0x64, 0x6c, 0x12, 0x40, 0xa5, 0x79, + 0x96, 0xd5, 0x44, 0xdd, 0x81, 0xa1, 0x57, 0x33, 0x93, 0x3c, 0x7f, 0x8b, 0x0b, 0x3d, 0xee, 0x66, 0x4a, 0x0e, 0x95, + 0x22, 0x6f, 0x91, 0x08, 0xf5, 0x15, 0x7c, 0x1f, 0x49, 0x54, 0xcc, 0x2f, 0xe9, 0xec, 0x71, 0x68, 0xbc, 0x20, 0xd4, + 0x6f, 0xc0, 0x10, 0xf9, 0x21, 0x3a, 0x08, 0x81, 0xdd, 0xb9, 0x5c, 0x41, 0x72, 0x55, 0xdf, 0xcf, 0xa0, 0xee, 0x18, + 0xfd, 0x76, 0x55, 0xbf, 0x76, 0x0f, 0x86, 0x8c, 0x12, 0xbc, 0x46, 0xba, 0x39, 0x74, 0xd0, 0xa8, 0x1d, 0x3d, 0xd3, + 0x53, 0xe5, 0xa3, 0x0b, 0x14, 0x7d, 0xd8, 0x52, 0xe3, 0x89, 0x37, 0x52, 0xd0, 0x73, 0x71, 0xc0, 0x1b, 0xc3, 0x5e, + 0xd5, 0x81, 0xd1, 0x31, 0x7c, 0x7e, 0x29, 0x32, 0x20, 0x49, 0xaa, 0xa7, 0x45, 0xc4, 0x72, 0x28, 0x67, 0x6d, 0xe6, + 0x0e, 0xfa, 0x5e, 0x9c, 0x62, 0x86, 0xef, 0x6e, 0xf8, 0x8b, 0xbf, 0x19, 0x5f, 0xda, 0xe5, 0xda, 0x93, 0x6e, 0x51, + 0x1a, 0xac, 0xdb, 0xfa, 0x0e, 0x7a, 0x33, 0x12, 0x5d, 0xd0, 0xf4, 0xc7, 0x02, 0x11, 0x87, 0x94, 0x88, 0xa6, 0x69, + 0xe8, 0x94, 0x81, 0x23, 0x36, 0xe2, 0x7f, 0xb0, 0xa2, 0x41, 0x50, 0x6a, 0x1e, 0x58, 0x12, 0x2f, 0x07, 0x39, 0x92, + 0xf2, 0x06, 0x42, 0x41, 0x50, 0x53, 0xc1, 0x59, 0x90, 0xd2, 0x8d, 0x69, 0x87, 0xc8, 0x15, 0xb9, 0xae, 0x8f, 0x1b, + 0xf4, 0xe5, 0x2b, 0x39, 0x31, 0xa9, 0x32, 0x72, 0x6b, 0xaa, 0x62, 0xc7, 0xe0, 0x1d, 0xe7, 0xd6, 0x81, 0x7b, 0x83, + 0x22, 0x68, 0x8a, 0x92, 0xa5, 0x97, 0x39, 0x2f, 0x42, 0x5b, 0xe4, 0xba, 0x1e, 0x3d, 0xa8, 0x18, 0x28, 0xa9, 0xb0, + 0xd8, 0x90, 0x56, 0xf4, 0xa7, 0xce, 0x3b, 0x8c, 0xc2, 0x95, 0x76, 0x65, 0xe4, 0xe1, 0x3d, 0x1e, 0x47, 0xef, 0x26, + 0x51, 0x2c, 0xf2, 0x5c, 0x9d, 0xd7, 0x2c, 0xc8, 0xba, 0x9d, 0x26, 0x79, 0xbe, 0x1b, 0xce, 0xa2, 0x62, 0x52, 0xb2, + 0x95, 0x24, 0xaf, 0x59, 0x28, 0x8c, 0xd8, 0xfa, 0xcd, 0xa3, 0x20, 0xf9, 0x2c, 0xba, 0xbd, 0x1f, 0x09, 0xaf, 0x17, + 0x49, 0x66, 0x11, 0xcf, 0xf3, 0x2c, 0xb5, 0x6c, 0xcc, 0xa9, 0x50, 0xa9, 0xce, 0x10, 0xf8, 0x2b, 0x69, 0x7a, 0x53, + 0x26, 0x28, 0xdc, 0xb6, 0xe9, 0x3e, 0x98, 0x8c, 0x88, 0x0e, 0xdf, 0xb9, 0xd1, 0xcc, 0xc7, 0x6f, 0x94, 0x81, 0x1d, + 0xd6, 0xda, 0xd0, 0x76, 0x81, 0x97, 0x5b, 0x95, 0xc1, 0x9e, 0x46, 0x95, 0x32, 0xf2, 0x82, 0xa8, 0x3a, 0xd1, 0x56, + 0x70, 0xe8, 0x87, 0x0d, 0xfe, 0x3d, 0xc2, 0x70, 0xc9, 0x3d, 0xbb, 0x0d, 0x40, 0x0e, 0x59, 0x44, 0x3a, 0x2a, 0xa0, + 0x47, 0x9f, 0xae, 0x66, 0xcc, 0x15, 0xdc, 0x65, 0x0d, 0x82, 0x3b, 0xda, 0x3e, 0xc3, 0x40, 0xd2, 0x1d, 0x2e, 0xb4, + 0x29, 0x7a, 0xd4, 0xdf, 0x36, 0x4b, 0x67, 0xc1, 0x9b, 0x54, 0xc1, 0xcf, 0xb4, 0xe0, 0x84, 0xb7, 0xfd, 0x1e, 0xef, + 0x1b, 0xad, 0xb1, 0x6d, 0x86, 0xc7, 0xc6, 0xbc, 0x3b, 0xc8, 0x1a, 0xab, 0x8b, 0xc5, 0x35, 0x41, 0x2e, 0x25, 0xf9, + 0x88, 0xeb, 0xe5, 0x69, 0x19, 0x7c, 0xaa, 0x9e, 0x2a, 0x56, 0xa0, 0x1c, 0x16, 0x21, 0x14, 0x4c, 0xb3, 0x87, 0xb1, + 0x0e, 0x1f, 0x23, 0x31, 0x28, 0x24, 0x84, 0x05, 0x16, 0xa5, 0xee, 0xc7, 0x42, 0xa7, 0xd2, 0x40, 0x50, 0x42, 0x85, + 0x02, 0x23, 0xce, 0x7b, 0x2d, 0xbd, 0x86, 0xb6, 0xa9, 0x8c, 0x1e, 0x06, 0xbb, 0x58, 0xf6, 0x0e, 0x99, 0xc2, 0x92, + 0x2d, 0x0f, 0x21, 0x37, 0xdc, 0xd8, 0xa7, 0xef, 0xdb, 0xb5, 0x8a, 0x55, 0x33, 0xba, 0x9a, 0xfa, 0xdf, 0x11, 0xa1, + 0x71, 0x00, 0xd9, 0xc7, 0x6b, 0xe9, 0x60, 0x45, 0x8c, 0x9d, 0xe6, 0x23, 0xf5, 0xa2, 0x9c, 0x3f, 0x9b, 0x02, 0x82, + 0x6d, 0x6f, 0xed, 0x58, 0x37, 0x40, 0xe2, 0x76, 0x8e, 0xc9, 0x5e, 0x5d, 0xe2, 0x49, 0xef, 0x83, 0xf2, 0xb9, 0x75, + 0xdb, 0x25, 0x81, 0xcc, 0x17, 0xac, 0x28, 0x06, 0x24, 0x2b, 0x25, 0x78, 0xce, 0x7f, 0x6b, 0x1d, 0x54, 0x90, 0x90, + 0xe7, 0x83, 0x46, 0xb2, 0x32, 0xea, 0xf9, 0x98, 0x08, 0x1c, 0xd4, 0x02, 0x44, 0x63, 0x70, 0x06, 0x25, 0x28, 0x5b, + 0xc6, 0x3e, 0x1c, 0xce, 0x69, 0xf2, 0x12, 0xa1, 0x29, 0xca, 0x87, 0x2c, 0xf6, 0x57, 0x3f, 0x51, 0xa8, 0x9b, 0x1b, + 0xb9, 0x11, 0x1d, 0x0a, 0x5d, 0xbd, 0x6b, 0x6f, 0x32, 0x82, 0x34, 0xda, 0xba, 0xb9, 0x9e, 0x3d, 0x3f, 0xeb, 0xe1, + 0x63, 0x73, 0xba, 0x1e, 0x2e, 0x6f, 0x4a, 0xb5, 0x22, 0x42, 0xfb, 0x7f, 0x56, 0x96, 0x93, 0xff, 0x2c, 0xfa, 0x8b, + 0xcf, 0x8a, 0xfe, 0x94, 0x02, 0x49, 0x5d, 0x44, 0x5c, 0x5c, 0xb3, 0xd1, 0x5c, 0x29, 0x37, 0x6c, 0xaf, 0x9c, 0x27, + 0xbe, 0x72, 0x2e, 0x7f, 0x08, 0x07, 0xd5, 0x4e, 0x38, 0x0b, 0xe0, 0xa4, 0x8c, 0xb8, 0x1c, 0x3c, 0x8b, 0x01, 0xad, + 0xe2, 0x8a, 0x5a, 0x1d, 0x39, 0xcf, 0x1d, 0x6f, 0x1b, 0x6a, 0x2e, 0xea, 0xa1, 0x10, 0xe7, 0x03, 0x31, 0x32, 0x1b, + 0x88, 0xba, 0x09, 0x33, 0xd8, 0xdf, 0x91, 0xb2, 0x93, 0xe5, 0xa2, 0x4b, 0x6d, 0xf7, 0xc4, 0x51, 0xa4, 0xa4, 0x97, + 0xa9, 0xad, 0x40, 0x45, 0xaa, 0x24, 0x75, 0x74, 0x44, 0x14, 0xc2, 0x26, 0x58, 0x50, 0x3c, 0x6a, 0xc2, 0xa8, 0x4d, + 0xc2, 0xed, 0x00, 0x49, 0x8a, 0xd5, 0x28, 0xe3, 0xba, 0xa3, 0x12, 0x34, 0x24, 0xd4, 0x99, 0xa3, 0x03, 0x1a, 0x35, + 0x09, 0x25, 0x43, 0x49, 0xf3, 0x2f, 0x53, 0xd3, 0x98, 0x21, 0xea, 0x0f, 0x8c, 0xd0, 0x3b, 0xb7, 0x21, 0xe0, 0x96, + 0xf9, 0xad, 0x56, 0x2e, 0x8b, 0x04, 0xe2, 0x53, 0xc6, 0x3e, 0x50, 0xad, 0x11, 0xb5, 0x93, 0x2f, 0x54, 0x3a, 0x7c, + 0x09, 0xc5, 0x31, 0xd1, 0xc9, 0x09, 0x67, 0xcf, 0x4c, 0x28, 0x2b, 0xfe, 0x4d, 0xa6, 0xcd, 0x90, 0xb6, 0xf4, 0x41, + 0x8f, 0x4e, 0x24, 0xe1, 0x1c, 0xcb, 0x16, 0xb9, 0xaf, 0x46, 0xba, 0xaa, 0x25, 0x09, 0x43, 0x05, 0x99, 0xcb, 0xc2, + 0xf5, 0x49, 0x78, 0xed, 0x1e, 0x92, 0xf6, 0xb3, 0x0e, 0x2c, 0xb7, 0xcd, 0x4b, 0xec, 0xc2, 0x59, 0xef, 0x41, 0xb4, + 0xf7, 0x4c, 0x08, 0x7c, 0x16, 0xeb, 0x13, 0x29, 0x74, 0xff, 0x60, 0x12, 0x86, 0x84, 0xcf, 0xe0, 0xe1, 0x72, 0xf4, + 0x23, 0x45, 0x57, 0x24, 0x94, 0xb7, 0x6a, 0x5d, 0x12, 0x12, 0x85, 0x7b, 0x8b, 0x45, 0x63, 0x5d, 0x44, 0x43, 0xa1, + 0xb9, 0x78, 0xed, 0x49, 0xf5, 0xbe, 0x17, 0x75, 0x75, 0x8c, 0x50, 0xbd, 0xe0, 0x9f, 0xc1, 0x4f, 0x48, 0x42, 0xa7, + 0xd0, 0xdd, 0x36, 0x2d, 0x20, 0xb3, 0xc3, 0x69, 0x88, 0x02, 0x1e, 0xa2, 0x2a, 0x02, 0xb4, 0x98, 0x36, 0x97, 0x43, + 0x0a, 0xd5, 0xf3, 0x13, 0x9d, 0x7c, 0x40, 0xdd, 0x03, 0x99, 0xb2, 0xed, 0xb4, 0x7c, 0xba, 0x57, 0x38, 0x2c, 0xb5, + 0xbf, 0x89, 0x84, 0x92, 0x99, 0x58, 0x42, 0xdb, 0x98, 0x24, 0x7c, 0xfe, 0x75, 0xeb, 0x4a, 0xc4, 0xf8, 0x90, 0xbe, + 0x1c, 0xc9, 0xb8, 0xc2, 0x3b, 0x95, 0x9c, 0x40, 0xc4, 0xa6, 0xb7, 0x47, 0x21, 0x21, 0x65, 0x6a, 0x7c, 0x20, 0xa5, + 0xa5, 0x77, 0x7b, 0xda, 0x7c, 0x2a, 0x85, 0x1f, 0xaf, 0x3a, 0xd9, 0x73, 0x75, 0xb0, 0x75, 0x94, 0xf6, 0x98, 0x4c, + 0xf6, 0x1f, 0xfa, 0x98, 0xa2, 0x89, 0x81, 0x32, 0x62, 0xec, 0x30, 0x0f, 0xac, 0x12, 0x62, 0xda, 0x50, 0xaa, 0x2c, + 0x25, 0x39, 0x07, 0x0c, 0x3f, 0x4e, 0x1e, 0xa1, 0x80, 0xc1, 0xc4, 0x04, 0x2b, 0xc3, 0xe5, 0x62, 0x69, 0x50, 0x97, + 0x4a, 0x3c, 0x79, 0x2a, 0x4d, 0xae, 0xa7, 0xb1, 0xc4, 0x55, 0x22, 0x81, 0x49, 0x0d, 0x3d, 0x02, 0x18, 0x8f, 0xd4, + 0x8b, 0x6c, 0xfa, 0x0c, 0x9c, 0x96, 0xbe, 0x73, 0x7a, 0xca, 0x24, 0x6f, 0xb4, 0x59, 0x20, 0x98, 0xf0, 0xd8, 0x30, + 0x74, 0x47, 0x95, 0x7c, 0xb4, 0x4f, 0xac, 0xcf, 0x99, 0x45, 0x19, 0x8f, 0x3d, 0x05, 0x18, 0x38, 0xad, 0xf7, 0xe8, + 0x47, 0xd9, 0x74, 0x56, 0x93, 0x71, 0x22, 0x4f, 0x54, 0x52, 0x65, 0xd9, 0x89, 0x49, 0x8d, 0x1e, 0xaa, 0x65, 0x4f, + 0x76, 0x4c, 0x81, 0x04, 0x50, 0x4d, 0x72, 0xf8, 0x19, 0xb8, 0x74, 0x16, 0xda, 0x22, 0x95, 0x24, 0x6c, 0x00, 0xab, + 0xcf, 0x69, 0xdc, 0x38, 0xff, 0xba, 0x8f, 0x02, 0xa8, 0x57, 0x42, 0x4c, 0x54, 0xd0, 0x0a, 0xfb, 0xa0, 0x32, 0x81, + 0x76, 0xcb, 0x29, 0x69, 0x3b, 0xca, 0x48, 0x72, 0x15, 0xd7, 0x81, 0x18, 0xdc, 0xd3, 0x03, 0xb1, 0x88, 0xae, 0x1b, + 0xd8, 0x74, 0x60, 0xc7, 0x6f, 0x8c, 0x97, 0x6a, 0x7b, 0xac, 0xea, 0x4a, 0x92, 0x8f, 0x92, 0x4d, 0xaa, 0x9d, 0x00, + 0xe4, 0x48, 0xa8, 0x5a, 0xe4, 0xa7, 0x4d, 0x29, 0xa5, 0xb5, 0x61, 0xf7, 0x9e, 0x9a, 0x90, 0xeb, 0x55, 0x3d, 0x85, + 0x8f, 0x63, 0x64, 0x0e, 0xf1, 0x18, 0x67, 0x67, 0x88, 0x78, 0xc7, 0x95, 0x85, 0xfb, 0xdb, 0x22, 0xf5, 0x5c, 0x4a, + 0x52, 0x7b, 0x90, 0x4b, 0xb9, 0x4c, 0x3e, 0x98, 0xe6, 0xd2, 0x22, 0x30, 0xe7, 0x45, 0x25, 0x8e, 0x2e, 0x29, 0xc1, + 0x1d, 0x9a, 0x5e, 0x67, 0x39, 0x08, 0x2d, 0x53, 0xcc, 0x06, 0x48, 0x21, 0x20, 0x02, 0xe3, 0x2a, 0x5f, 0xb0, 0x77, + 0xb9, 0x8a, 0x0b, 0x8d, 0x60, 0x29, 0x32, 0x43, 0xaa, 0xed, 0xc4, 0xb4, 0xfb, 0xca, 0x59, 0xf4, 0xd3, 0x72, 0x39, + 0xd2, 0x71, 0x4d, 0x9c, 0x97, 0x92, 0xbc, 0x19, 0x46, 0x86, 0xce, 0x5b, 0x53, 0x6c, 0x75, 0x36, 0xf3, 0xd9, 0x90, + 0x40, 0x48, 0xc0, 0x82, 0x42, 0x2e, 0x4b, 0xd9, 0x99, 0xc7, 0xb4, 0xc7, 0xe3, 0xcc, 0xe8, 0xfe, 0xfa, 0x7d, 0x3d, + 0x9d, 0x96, 0x05, 0x55, 0x79, 0xb8, 0xed, 0x0e, 0x96, 0xc7, 0x41, 0x97, 0x76, 0x59, 0x4c, 0x15, 0xbf, 0x92, 0xec, + 0x27, 0x0d, 0x2f, 0xa3, 0x61, 0xae, 0x79, 0x49, 0xf5, 0x52, 0xcc, 0x70, 0x64, 0x91, 0xe6, 0xab, 0x23, 0xf6, 0xb3, + 0x33, 0xad, 0xad, 0xfc, 0xfb, 0x91, 0x59, 0x3b, 0xda, 0x5e, 0x49, 0x7d, 0xa5, 0x8f, 0x7e, 0xee, 0x83, 0xc5, 0x04, + 0x7f, 0x56, 0x28, 0x17, 0x7a, 0x52, 0x58, 0xa1, 0xfe, 0xb3, 0xae, 0x65, 0x7f, 0x6c, 0x82, 0x0f, 0xed, 0x83, 0x0f, + 0x98, 0x26, 0x34, 0x3f, 0x32, 0xc0, 0xa6, 0x8a, 0x09, 0xcb, 0xb7, 0x15, 0xb6, 0x21, 0xc5, 0xfb, 0xe7, 0x75, 0xcb, + 0x63, 0x9e, 0x8a, 0x29, 0x2f, 0x90, 0x5b, 0xfe, 0x2c, 0x20, 0x12, 0x75, 0x06, 0xd7, 0x43, 0x3e, 0x81, 0x6e, 0xec, + 0x3c, 0x3c, 0x12, 0xb9, 0xe2, 0x36, 0xc3, 0x9d, 0xc2, 0xb7, 0x87, 0xc7, 0xca, 0xbb, 0xb4, 0x52, 0x48, 0xa3, 0xfa, + 0x83, 0x36, 0xc3, 0x1b, 0xab, 0xd1, 0x43, 0x5d, 0x2d, 0x09, 0x61, 0x11, 0x84, 0x87, 0x45, 0xe8, 0xfd, 0x9f, 0xae, + 0x54, 0x48, 0x4c, 0x4e, 0x5b, 0x46, 0x72, 0x0e, 0x84, 0x54, 0xa0, 0x96, 0xe9, 0x3e, 0x65, 0x51, 0xa9, 0xdb, 0x42, + 0x6e, 0xfc, 0x96, 0x7c, 0x44, 0x15, 0x16, 0x3b, 0xbf, 0xd6, 0xdd, 0x27, 0xd2, 0x75, 0x57, 0xd4, 0x85, 0x56, 0x53, + 0x96, 0xa7, 0x68, 0x7a, 0x0e, 0xc4, 0xee, 0x71, 0x95, 0xfc, 0x9e, 0x40, 0x3a, 0xff, 0xb1, 0xe0, 0xef, 0xef, 0x15, + 0x49, 0xa2, 0xf5, 0x45, 0xe3, 0x51, 0xeb, 0x8b, 0x3d, 0x75, 0x68, 0x80, 0xd3, 0x05, 0x24, 0x8f, 0xaf, 0x02, 0x74, + 0x0d, 0x66, 0xe9, 0xaa, 0x63, 0x8e, 0x9b, 0xee, 0x7c, 0xd9, 0x16, 0x69, 0x3d, 0x43, 0x00, 0xed, 0x0d, 0x19, 0x77, + 0xff, 0x21, 0x4e, 0xb4, 0x67, 0x61, 0x82, 0x2e, 0x22, 0xe9, 0x3d, 0xec, 0x28, 0xb9, 0xd5, 0x9c, 0xe5, 0x0e, 0xdd, + 0x81, 0xae, 0x67, 0xbd, 0x88, 0x4a, 0x43, 0x0e, 0x76, 0x52, 0x6a, 0x08, 0x20, 0xda, 0x83, 0x6e, 0x2f, 0x4e, 0xee, + 0xed, 0x62, 0xc5, 0x7a, 0xdb, 0x0e, 0x4d, 0x2c, 0x54, 0x85, 0x2b, 0xac, 0x31, 0xe6, 0x96, 0xe3, 0xf6, 0x70, 0xd6, + 0x39, 0x16, 0x4a, 0xa3, 0xc1, 0xc0, 0xb7, 0xaf, 0xf3, 0xe3, 0x78, 0x61, 0x8f, 0x1c, 0x80, 0xd0, 0xb1, 0x17, 0x65, + 0x52, 0x05, 0x8a, 0x63, 0x19, 0x02, 0x2d, 0xda, 0xad, 0x59, 0xa5, 0x20, 0x17, 0x1e, 0x50, 0x8b, 0x8f, 0x17, 0xfe, + 0xb3, 0xcd, 0xb9, 0xd0, 0x42, 0xe6, 0xa8, 0x9d, 0x96, 0xec, 0x53, 0xbd, 0xa0, 0x00, 0x89, 0x32, 0xc2, 0xb6, 0x56, + 0x32, 0xf5, 0x71, 0x0a, 0x36, 0x21, 0xfb, 0x35, 0x49, 0x72, 0x3a, 0x32, 0x81, 0xd6, 0x79, 0xbb, 0x91, 0xa8, 0x0b, + 0x51, 0xe5, 0xc6, 0xa8, 0x0f, 0x7b, 0x46, 0xc7, 0x13, 0x8c, 0xe4, 0x98, 0xd2, 0xb1, 0xce, 0xbc, 0x7b, 0xab, 0x3d, + 0x76, 0xa7, 0x4d, 0x2b, 0x53, 0x9a, 0x29, 0x88, 0x39, 0x94, 0x49, 0x12, 0x04, 0x24, 0xb6, 0xbe, 0xbb, 0xce, 0x51, + 0x2d, 0xe8, 0x0e, 0x4c, 0x9f, 0x19, 0x8d, 0x02, 0x09, 0xf8, 0x6e, 0x39, 0x23, 0xe7, 0x90, 0xc2, 0xba, 0xb6, 0x50, + 0x91, 0x76, 0x97, 0x57, 0x82, 0x0a, 0xe7, 0x82, 0xd0, 0xec, 0xa0, 0xe0, 0xd4, 0xee, 0x77, 0x9b, 0xa1, 0xae, 0x3a, + 0xfa, 0x80, 0x1b, 0xb0, 0xd9, 0x10, 0xe2, 0x48, 0xdc, 0x78, 0xa1, 0x6c, 0x80, 0x13, 0x37, 0x2a, 0x61, 0x75, 0x62, + 0x7b, 0x72, 0xf4, 0xa3, 0x0b, 0xb5, 0xcc, 0x27, 0x58, 0xa2, 0x8b, 0x9e, 0x57, 0xb6, 0xdd, 0x5e, 0xe6, 0xdb, 0x6a, + 0x5e, 0xa0, 0xd8, 0x26, 0x21, 0xc4, 0x32, 0x4d, 0xe7, 0x98, 0xe7, 0xc2, 0x8f, 0x0e, 0x26, 0xc8, 0x3c, 0x94, 0x82, + 0x56, 0xf5, 0x0a, 0x34, 0x65, 0x97, 0xac, 0x84, 0x7b, 0xb7, 0xbe, 0xc9, 0xa4, 0x5d, 0xb4, 0x56, 0xde, 0x5d, 0x3d, + 0x6d, 0x40, 0xf7, 0xdc, 0xfb, 0x94, 0xfe, 0x25, 0xd0, 0x71, 0xc9, 0x6a, 0xf7, 0xbc, 0x9f, 0x52, 0x4e, 0xe3, 0x9a, + 0x28, 0x25, 0x0a, 0x3f, 0x1c, 0x06, 0xc4, 0xcc, 0x10, 0xe2, 0x8f, 0x7e, 0xe0, 0xcd, 0x5e, 0xec, 0x52, 0xa6, 0x4a, + 0x8b, 0xe2, 0x4f, 0x7a, 0x3f, 0x65, 0xc2, 0xc9, 0x7d, 0xd1, 0x3f, 0x37, 0xc4, 0x77, 0xa2, 0x01, 0x26, 0x62, 0x50, + 0x47, 0xbf, 0x45, 0x60, 0x3d, 0xa2, 0x23, 0x4b, 0xde, 0x2c, 0xff, 0x5d, 0xd6, 0xde, 0x9f, 0x76, 0x16, 0xaf, 0x2d, + 0xa9, 0xc1, 0x46, 0xb7, 0x1b, 0xc3, 0xda, 0xb0, 0xed, 0x29, 0x15, 0x20, 0x32, 0x7a, 0x04, 0xaa, 0x31, 0x5f, 0xcd, + 0x12, 0x14, 0x03, 0x1f, 0x71, 0x02, 0x1c, 0xb9, 0xad, 0x93, 0x95, 0x14, 0xee, 0xde, 0xfa, 0xb6, 0xd7, 0xc4, 0xbe, + 0xb2, 0x4b, 0x58, 0xee, 0xc8, 0x1d, 0xbb, 0xe9, 0x04, 0xaa, 0xa3, 0xb0, 0x57, 0x30, 0xac, 0x68, 0xd1, 0xb5, 0x03, + 0x11, 0x85, 0xde, 0x4e, 0x54, 0x14, 0x3e, 0x66, 0x58, 0x51, 0xd9, 0xd9, 0x01, 0x8c, 0x00, 0xfe, 0x45, 0x1c, 0x9e, + 0xd8, 0xe5, 0xa9, 0x66, 0x31, 0x83, 0x00, 0x63, 0xf8, 0xca, 0x06, 0x67, 0xc6, 0x0b, 0xcb, 0xc0, 0x26, 0x07, 0x80, + 0x5a, 0x47, 0x51, 0x6f, 0x71, 0x8a, 0x0f, 0x53, 0xdf, 0x18, 0xbc, 0xbd, 0x54, 0x4e, 0x47, 0xbc, 0x87, 0xdd, 0x95, + 0x8a, 0x1a, 0x52, 0xb0, 0x85, 0x6f, 0xbb, 0x21, 0x60, 0xa5, 0x30, 0x09, 0xfa, 0x50, 0x4e, 0x9b, 0xcb, 0x93, 0xcf, + 0x54, 0xff, 0x57, 0x4f, 0xc9, 0x54, 0x2c, 0x78, 0xd9, 0x49, 0x4f, 0x67, 0x9c, 0x96, 0xa5, 0xb2, 0xcf, 0xfd, 0xd3, + 0x4e, 0x12, 0x28, 0xf0, 0xed, 0x10, 0xf0, 0xec, 0xff, 0x2c, 0xda, 0xa8, 0x48, 0xad, 0x9a, 0x68, 0xa3, 0xa5, 0x75, + 0xec, 0x11, 0xff, 0x7e, 0x94, 0x76, 0x75, 0xe0, 0xa1, 0xaa, 0xcf, 0x27, 0x79, 0xe6, 0xbf, 0xe2, 0x49, 0xde, 0x10, + 0x75, 0x3b, 0xb1, 0xfb, 0x26, 0xa7, 0x4b, 0x79, 0x3b, 0x99, 0x57, 0x41, 0x7c, 0x47, 0x53, 0x03, 0xb3, 0x39, 0x29, + 0x71, 0xeb, 0xa5, 0xa2, 0xde, 0xe2, 0xc8, 0x23, 0x3a, 0x48, 0x32, 0x8c, 0xe6, 0xfc, 0xdc, 0x4e, 0xfc, 0x78, 0x2e, + 0x58, 0xfc, 0xb8, 0xbf, 0x2f, 0x30, 0x1c, 0x7d, 0x70, 0x12, 0x67, 0xda, 0xd5, 0x18, 0x29, 0x86, 0xaa, 0x14, 0x70, + 0x26, 0x36, 0xb7, 0xed, 0x47, 0x00, 0xe8, 0x3d, 0x70, 0xdc, 0xfb, 0x6e, 0xc1, 0xd9, 0xb3, 0xba, 0xb9, 0x90, 0x49, + 0xe6, 0x15, 0x65, 0x8c, 0x2b, 0x5e, 0xf4, 0x95, 0x2b, 0xf7, 0x3a, 0xc9, 0x03, 0x18, 0x52, 0x41, 0x4e, 0xe4, 0x9d, + 0x96, 0xba, 0xa2, 0xce, 0x42, 0xc8, 0x42, 0xce, 0x05, 0xb8, 0xca, 0xf3, 0xa7, 0xb3, 0x32, 0x8b, 0xe9, 0xdd, 0x5a, + 0xeb, 0x04, 0x08, 0x41, 0xf5, 0x95, 0x0c, 0xc6, 0xa1, 0x27, 0x79, 0x9f, 0x0a, 0x89, 0xb5, 0xe1, 0x1d, 0xb3, 0x1e, + 0x73, 0xf0, 0xc7, 0x84, 0xda, 0x4e, 0xa9, 0x07, 0xf9, 0x46, 0x6a, 0xd3, 0x7b, 0xc6, 0xe3, 0xf6, 0x0d, 0xb7, 0xd3, + 0x04, 0x09, 0x8a, 0x6b, 0x02, 0x2d, 0x97, 0x71, 0x0b, 0x60, 0xa9, 0x33, 0x45, 0xc3, 0x5b, 0xea, 0x7e, 0x62, 0x01, + 0x6b, 0xde, 0xad, 0x8c, 0x27, 0x0e, 0x73, 0xb2, 0x3d, 0x58, 0xbf, 0x2d, 0x86, 0x56, 0xa2, 0x0a, 0x07, 0x2b, 0x7b, + 0xde, 0x6d, 0x3b, 0xfe, 0x60, 0xcf, 0x65, 0x46, 0x84, 0x61, 0x1f, 0x38, 0x0a, 0x53, 0xec, 0xf2, 0x2a, 0x5b, 0x23, + 0x47, 0x18, 0x4e, 0xbe, 0xde, 0xa8, 0x81, 0xe5, 0xc4, 0xce, 0x69, 0xf6, 0x6f, 0xe8, 0x89, 0x40, 0xc6, 0x53, 0x7f, + 0xfc, 0xcc, 0x0c, 0xf5, 0xe0, 0x21, 0xdb, 0xed, 0xd2, 0xd7, 0xd6, 0x76, 0xb9, 0xb6, 0xad, 0x71, 0x8b, 0x68, 0x39, + 0x94, 0xd8, 0xb5, 0x46, 0x2c, 0xdd, 0xa1, 0x0b, 0x1f, 0xd8, 0x02, 0x37, 0xaa, 0x42, 0xe4, 0x2e, 0x37, 0x53, 0x89, + 0x35, 0x14, 0x80, 0xab, 0x9d, 0x17, 0x66, 0xd4, 0x27, 0x92, 0xf1, 0x15, 0x7b, 0x64, 0xa9, 0xf9, 0xa9, 0xcf, 0x3c, + 0xb0, 0x17, 0x8d, 0x42, 0xdf, 0xa4, 0x39, 0xcd, 0x8b, 0xf6, 0x83, 0xec, 0x16, 0xf9, 0x09, 0x42, 0x2b, 0xe1, 0x7c, + 0x7e, 0xd9, 0x7e, 0xd1, 0x2e, 0x66, 0x39, 0xe2, 0x61, 0x7f, 0x53, 0x4f, 0x2b, 0xbd, 0x8f, 0x77, 0x04, 0x0b, 0xb7, + 0x1d, 0x08, 0x26, 0x92, 0x3e, 0x12, 0xf2, 0xf0, 0x9d, 0xf8, 0xff, 0x6b, 0x43, 0xa0, 0x0d, 0x5b, 0x31, 0x5b, 0x1c, + 0x7e, 0x6a, 0x0a, 0xde, 0x41, 0x33, 0x4f, 0xa3, 0xb6, 0xb2, 0xce, 0xaa, 0xda, 0x2c, 0xe0, 0x15, 0x2f, 0x3f, 0x65, + 0x78, 0x81, 0x93, 0x71, 0x8e, 0x64, 0x78, 0x3f, 0x0f, 0x10, 0x25, 0x04, 0x24, 0xc4, 0xe9, 0x75, 0xf7, 0x60, 0x70, + 0x07, 0x6d, 0x7c, 0x09, 0x0a, 0xeb, 0xf9, 0x6c, 0x3c, 0x8f, 0xd9, 0x9b, 0xfc, 0x33, 0xba, 0x9e, 0xe8, 0x34, 0xae, + 0x54, 0x5b, 0xad, 0x5f, 0xbd, 0xf0, 0xdb, 0x43, 0xcd, 0x37, 0xf7, 0x93, 0xfb, 0x6c, 0x92, 0xad, 0x7c, 0xa8, 0x54, + 0x59, 0xde, 0x0d, 0x68, 0x31, 0x44, 0x65, 0x39, 0x4c, 0xa3, 0xdd, 0x86, 0xa3, 0xc3, 0x96, 0xdb, 0x49, 0xad, 0x9d, + 0x80, 0xec, 0xa0, 0x69, 0x51, 0x89, 0x17, 0x56, 0x90, 0x71, 0x9f, 0x72, 0x37, 0xa2, 0xa0, 0x20, 0xba, 0xc9, 0x52, + 0x9d, 0x61, 0x6a, 0x6c, 0x38, 0xf5, 0x80, 0xb2, 0xa0, 0xff, 0x75, 0x60, 0x28, 0x32, 0xa3, 0xb6, 0x30, 0x3f, 0xa6, + 0xca, 0xc9, 0x1f, 0xb7, 0x9c, 0xca, 0xc4, 0xaa, 0x57, 0xe8, 0xd5, 0xeb, 0x7d, 0x6e, 0x9a, 0x4e, 0x0c, 0x14, 0x1f, + 0x70, 0x35, 0x27, 0x58, 0x4d, 0xe4, 0x8b, 0x78, 0xb9, 0xca, 0x9c, 0x7d, 0x00, 0x7e, 0xd1, 0x75, 0x0b, 0x87, 0x69, + 0x79, 0xdb, 0xec, 0x8f, 0xe8, 0xec, 0x4a, 0xf2, 0x62, 0xc9, 0x16, 0x7c, 0x8c, 0x06, 0x70, 0x64, 0x0f, 0xaa, 0xc6, + 0x29, 0xc0, 0x22, 0x91, 0xd8, 0xc2, 0x52, 0x5a, 0x0f, 0xca, 0x05, 0x31, 0xb5, 0x8c, 0xe9, 0x36, 0x7a, 0x3c, 0x2d, + 0x23, 0x40, 0x0b, 0xb5, 0xb5, 0xc2, 0x3b, 0x8a, 0x29, 0x2a, 0x9b, 0x0b, 0xb9, 0x0a, 0x6c, 0xff, 0x9a, 0x52, 0x29, + 0x17, 0xb1, 0xdb, 0xa4, 0xb4, 0x43, 0xfd, 0x87, 0x7e, 0xc5, 0x6a, 0xc9, 0x09, 0x89, 0xd1, 0x47, 0x2e, 0x2e, 0x09, + 0x69, 0x45, 0xa6, 0x39, 0x5c, 0x33, 0x24, 0xf8, 0x73, 0x5a, 0x6b, 0x2f, 0xc5, 0x91, 0x31, 0x67, 0xee, 0x9b, 0xe2, + 0xda, 0x69, 0xab, 0xbf, 0xd8, 0x19, 0x57, 0x02, 0x82, 0xe1, 0xfc, 0x32, 0x97, 0x43, 0x77, 0xee, 0xbd, 0xb4, 0xe7, + 0xbc, 0xcc, 0x10, 0xc1, 0x4c, 0x20, 0xe4, 0x49, 0xe9, 0x5c, 0x74, 0x7d, 0x3a, 0x75, 0x24, 0xb1, 0xb6, 0x3e, 0x65, + 0xc6, 0x64, 0xc2, 0x64, 0x28, 0x28, 0xee, 0x19, 0xbf, 0x3f, 0x81, 0x8c, 0xa0, 0x86, 0xa0, 0xa0, 0xba, 0xee, 0xf1, + 0xf4, 0x65, 0x35, 0xf8, 0xf5, 0xb2, 0x42, 0x49, 0xe8, 0xb8, 0xf4, 0xdf, 0xe6, 0xb2, 0xcb, 0x92, 0x83, 0xbd, 0xbd, + 0x37, 0x30, 0xce, 0xa6, 0xd1, 0x93, 0x9d, 0x98, 0x72, 0xb7, 0x9d, 0xa0, 0x52, 0xf2, 0x9a, 0x52, 0x51, 0xb8, 0xd5, + 0x4b, 0xb4, 0x9e, 0x79, 0xe5, 0x70, 0x97, 0x78, 0x43, 0x59, 0xbc, 0x63, 0xc3, 0x4e, 0xf9, 0xcf, 0x8f, 0x6d, 0xf9, + 0xb2, 0x8d, 0x07, 0x7b, 0xba, 0x3f, 0x09, 0xfa, 0xce, 0xb8, 0xdf, 0x31, 0xf2, 0x57, 0x5f, 0x7c, 0x57, 0x93, 0xbf, + 0xf4, 0x9b, 0xb5, 0x1e, 0xf3, 0xba, 0x87, 0xdf, 0xef, 0xd3, 0x29, 0x7b, 0xe0, 0x6d, 0xe8, 0x9f, 0x47, 0xab, 0x75, + 0x05, 0xe4, 0x43, 0x87, 0xce, 0x7f, 0xe6, 0xfd, 0x33, 0x9f, 0xb9, 0xf4, 0xa7, 0xa3, 0x85, 0xd8, 0x1d, 0xf3, 0x37, + 0x06, 0x6f, 0x1b, 0xb1, 0x7b, 0x29, 0x76, 0x5f, 0xf4, 0x9a, 0x33, 0x0f, 0x53, 0x16, 0x5e, 0x41, 0xd0, 0x52, 0x79, + 0x57, 0xf8, 0x9c, 0xb7, 0x85, 0x6d, 0x3e, 0x14, 0x1e, 0xf2, 0xb1, 0xf0, 0x98, 0x4f, 0x6b, 0x4f, 0x4a, 0xb6, 0xd8, + 0xe3, 0xb8, 0x9a, 0xa8, 0x4a, 0x14, 0x7a, 0xf4, 0xc3, 0xc3, 0xa7, 0x52, 0x2a, 0x6b, 0x7c, 0xe3, 0x99, 0x67, 0x05, + 0x1b, 0x94, 0x10, 0x2b, 0xc3, 0x9b, 0x3a, 0x79, 0x75, 0x52, 0x12, 0x09, 0xf5, 0xcc, 0x5a, 0xd5, 0x41, 0x57, 0x49, + 0x59, 0x70, 0xb7, 0xdc, 0x86, 0x62, 0x7b, 0xb2, 0xb8, 0x8c, 0x5a, 0x43, 0xbd, 0xb7, 0x92, 0x19, 0xbd, 0x46, 0xa8, + 0xac, 0xbd, 0xbd, 0x4f, 0x47, 0x28, 0x2d, 0x27, 0x54, 0x25, 0xee, 0x67, 0x68, 0x15, 0x71, 0x86, 0x2d, 0x41, 0xde, + 0x7f, 0x06, 0x4c, 0x5a, 0x38, 0x6a, 0x5d, 0xae, 0xf7, 0x84, 0xd5, 0xe8, 0xd6, 0x12, 0xe9, 0x8b, 0x3c, 0x9a, 0xba, + 0xee, 0xaa, 0xc0, 0xcd, 0x89, 0x33, 0xf4, 0x1a, 0xf9, 0xed, 0xf0, 0xd8, 0x1a, 0xbb, 0xdc, 0xaa, 0xf9, 0x72, 0xfd, + 0xeb, 0xec, 0x3b, 0x2e, 0xc5, 0x84, 0x01, 0xea, 0x39, 0x0a, 0x91, 0x45, 0x0d, 0x17, 0xfc, 0x4a, 0x40, 0x5a, 0x6c, + 0x85, 0x1f, 0xbd, 0xaf, 0x61, 0x72, 0x81, 0x07, 0xa6, 0xbb, 0x75, 0x74, 0x96, 0x9f, 0xdc, 0xff, 0xf0, 0x9b, 0xff, + 0x19, 0x91, 0x13, 0x34, 0x16, 0x99, 0xfe, 0xb3, 0x9d, 0x1c, 0xc5, 0xa4, 0xb9, 0x74, 0x4b, 0xee, 0x6f, 0xc8, 0x60, + 0xea, 0x7d, 0x0d, 0x25, 0x20, 0xf0, 0x00, 0xa4, 0x94, 0x45, 0x75, 0x26, 0x04, 0xd7, 0xe3, 0x85, 0x45, 0x11, 0x5d, + 0x86, 0xf5, 0x10, 0x37, 0xa7, 0x63, 0x73, 0x53, 0x0d, 0xfe, 0x81, 0x98, 0x04, 0xd5, 0xf0, 0x4b, 0x4a, 0xda, 0xe8, + 0x46, 0x48, 0x29, 0x4c, 0xfb, 0x9d, 0x09, 0xfd, 0xe4, 0x47, 0x1f, 0xfa, 0xc2, 0xe7, 0x3e, 0x66, 0x42, 0xdc, 0x52, + 0xd1, 0xfc, 0x6d, 0xe0, 0x35, 0xb3, 0xfd, 0x6e, 0x85, 0x3f, 0xc8, 0xa7, 0xe3, 0xbd, 0x5f, 0x75, 0xbd, 0xb5, 0x39, + 0x75, 0x43, 0x3d, 0xe2, 0xef, 0x11, 0x44, 0x0d, 0x1f, 0x4b, 0xaf, 0xdd, 0x83, 0x84, 0x73, 0xec, 0x62, 0xb8, 0x2a, + 0xd7, 0xc1, 0xc7, 0x79, 0x99, 0xe7, 0xc6, 0x6c, 0x1a, 0xc1, 0x7d, 0xe1, 0x83, 0xcf, 0x38, 0x33, 0x9a, 0x7d, 0xc6, + 0xb2, 0x6d, 0xad, 0x54, 0x3a, 0xe5, 0xda, 0x52, 0xfb, 0x7e, 0x8d, 0xe2, 0x57, 0x58, 0xdb, 0xa6, 0x5d, 0xdb, 0xf4, + 0x4c, 0xd5, 0x78, 0x1d, 0x81, 0x67, 0xc9, 0x1f, 0xc7, 0x56, 0x58, 0xdf, 0xa2, 0x31, 0x0b, 0x6c, 0x4e, 0x6c, 0x97, + 0xa3, 0x97, 0xbf, 0x18, 0xdb, 0xc7, 0xd0, 0x4b, 0x2d, 0x62, 0x8a, 0x90, 0xbe, 0xac, 0xd2, 0xad, 0xa4, 0x89, 0x1e, + 0xdf, 0x43, 0xa8, 0xc2, 0x7e, 0xef, 0x39, 0x08, 0xd0, 0xd8, 0x6b, 0x2e, 0x28, 0x3a, 0xd7, 0xe9, 0x4a, 0x20, 0x74, + 0xe1, 0xf7, 0xa1, 0x7d, 0x53, 0x74, 0xaa, 0x83, 0xb4, 0x0c, 0x54, 0x13, 0x79, 0xf5, 0x3d, 0xb9, 0x1c, 0xe4, 0x2a, + 0xc3, 0x43, 0x8f, 0x0e, 0xdf, 0xe4, 0xe1, 0xd2, 0xc2, 0x4e, 0x24, 0x7e, 0xf3, 0x33, 0xb7, 0x62, 0xde, 0x6f, 0x47, + 0x47, 0x8b, 0x70, 0x50, 0x59, 0xcb, 0x5b, 0x64, 0x3a, 0x54, 0x40, 0x1a, 0xa8, 0xce, 0x12, 0x89, 0xe5, 0xfc, 0x57, + 0xfa, 0xd1, 0x6d, 0x88, 0x1f, 0xdd, 0x54, 0xf4, 0xfa, 0xb8, 0xb7, 0x02, 0xd0, 0x8d, 0xea, 0x33, 0x50, 0x65, 0xe6, + 0x5c, 0x94, 0xbe, 0xbf, 0xc5, 0xfe, 0xbe, 0x76, 0x11, 0x7d, 0xef, 0xb4, 0x7e, 0x76, 0x42, 0x56, 0xce, 0x3f, 0x7d, + 0x84, 0x8d, 0x0a, 0xea, 0xff, 0x81, 0x6b, 0xda, 0xd7, 0x81, 0x4e, 0x9c, 0x5f, 0xca, 0x44, 0x7a, 0x2e, 0x89, 0xcb, + 0x8c, 0x4f, 0x30, 0x0b, 0x24, 0xed, 0xf8, 0xa3, 0x8b, 0xe2, 0x2a, 0x9c, 0xfb, 0x8c, 0x75, 0x9a, 0x37, 0x4e, 0xad, + 0x0d, 0xf6, 0xeb, 0x1b, 0xdd, 0x64, 0x44, 0xd6, 0xb9, 0x39, 0xc3, 0x9a, 0xd1, 0x47, 0x88, 0xe4, 0x16, 0x4d, 0xa8, + 0x8e, 0x19, 0x2c, 0x0f, 0x7a, 0xf0, 0x9b, 0x74, 0xde, 0x6d, 0xc4, 0x96, 0x99, 0x81, 0x47, 0x23, 0xb6, 0xe1, 0x51, + 0x84, 0x0c, 0x32, 0x70, 0xce, 0x77, 0xd2, 0xfd, 0x50, 0x90, 0x8c, 0x0f, 0x8e, 0xcf, 0x1d, 0xdc, 0x74, 0x2f, 0x0b, + 0x64, 0xa5, 0x1e, 0x43, 0x73, 0xb3, 0x20, 0x6a, 0xb3, 0x4d, 0x79, 0x83, 0x2f, 0xf8, 0xd2, 0xf5, 0x8a, 0x54, 0x57, + 0xda, 0x6a, 0xe9, 0x29, 0x2c, 0xcd, 0x82, 0x81, 0x6c, 0x69, 0xb1, 0x2c, 0x62, 0x0c, 0xd2, 0x70, 0x9d, 0x4d, 0x11, + 0x4a, 0x13, 0x84, 0x3a, 0x14, 0x98, 0x12, 0x05, 0x3a, 0x05, 0xe0, 0xa0, 0x9c, 0xd0, 0x5e, 0x07, 0xbf, 0xa7, 0xeb, + 0x65, 0xd6, 0x7e, 0x7f, 0x6f, 0x38, 0x5f, 0x6f, 0x87, 0x67, 0xec, 0xf5, 0xe4, 0xbf, 0x38, 0x83, 0xfc, 0x9a, 0xe6, + 0xe6, 0xaa, 0x67, 0x2c, 0x17, 0x49, 0xb4, 0x3a, 0x7f, 0xf9, 0x26, 0x53, 0x8f, 0x7e, 0xd0, 0xd5, 0x7a, 0xea, 0x6e, + 0xb2, 0x37, 0x8c, 0x0f, 0xd4, 0x7a, 0x19, 0x4b, 0x8c, 0xd5, 0xaa, 0xe8, 0xff, 0xeb, 0x5a, 0xf8, 0x2a, 0x69, 0x0f, + 0x54, 0x17, 0xe2, 0xfe, 0x4a, 0x8f, 0xcf, 0x08, 0x0e, 0x17, 0x6d, 0x17, 0x27, 0x74, 0xa5, 0xd6, 0xa2, 0x42, 0xb7, + 0x86, 0x19, 0x62, 0xaf, 0x2d, 0xf1, 0x2f, 0xfd, 0x24, 0x4b, 0xd1, 0x77, 0xc7, 0xd0, 0xb9, 0xfc, 0xe1, 0x70, 0x75, + 0xac, 0x9a, 0xe6, 0xa7, 0x77, 0xe3, 0xec, 0xf7, 0x30, 0xb7, 0x7e, 0x57, 0xac, 0xe8, 0x08, 0x05, 0x9e, 0xac, 0x4c, + 0xe8, 0xf5, 0xe5, 0x85, 0x32, 0x93, 0xcd, 0x27, 0xcc, 0x40, 0x4f, 0xde, 0x31, 0xd0, 0x8d, 0x53, 0xed, 0x23, 0x67, + 0xc5, 0xff, 0x2c, 0x47, 0x6d, 0xb6, 0x3b, 0x4c, 0x54, 0xef, 0xf6, 0x8e, 0xdc, 0x07, 0xe8, 0x33, 0xe8, 0x23, 0x53, + 0x01, 0xea, 0xb8, 0x55, 0xc5, 0xb0, 0x99, 0xa4, 0xdd, 0x7d, 0x63, 0x7d, 0xac, 0x97, 0x99, 0x63, 0x9f, 0xd8, 0x02, + 0x10, 0xc7, 0x1f, 0x94, 0x55, 0x81, 0xaf, 0xcf, 0xdf, 0xe2, 0x6d, 0xba, 0xcf, 0x68, 0x08, 0x4c, 0x98, 0xa7, 0x3f, + 0x19, 0xa5, 0xf4, 0xfd, 0xe9, 0x89, 0xd2, 0x6b, 0x83, 0x7b, 0x9a, 0x3d, 0x5d, 0x30, 0x9e, 0xfe, 0x43, 0x50, 0x6b, + 0xef, 0xfd, 0x95, 0x5b, 0xeb, 0x3b, 0x48, 0xb3, 0x33, 0xfa, 0xc1, 0x69, 0x0e, 0x72, 0x2c, 0x4a, 0xab, 0xc7, 0xf9, + 0x11, 0xcd, 0x5c, 0x08, 0xf0, 0x21, 0x2b, 0x0e, 0xfa, 0xe7, 0x18, 0x63, 0xae, 0xe0, 0xc7, 0xe8, 0x8f, 0x0e, 0x42, + 0x6d, 0xe5, 0xd3, 0x7d, 0xf1, 0x77, 0x6a, 0xcd, 0x51, 0xeb, 0x59, 0x15, 0xaa, 0xbe, 0x93, 0xb2, 0xda, 0x64, 0x6b, + 0x05, 0xd0, 0xf8, 0x92, 0xe2, 0xfb, 0x3a, 0x24, 0x04, 0x55, 0x48, 0xc0, 0x2d, 0xab, 0xa4, 0x4b, 0xda, 0x2f, 0x39, + 0xbc, 0x91, 0xde, 0x43, 0xd8, 0x88, 0xbb, 0x8d, 0x5d, 0x1f, 0xd2, 0x9f, 0x29, 0xf2, 0x9b, 0x28, 0x63, 0x6c, 0xbd, + 0x71, 0x99, 0x91, 0x03, 0xff, 0x77, 0x37, 0x08, 0x44, 0x3e, 0x2a, 0x98, 0x25, 0xb5, 0xd3, 0x18, 0x62, 0x69, 0x4a, + 0x31, 0xfa, 0x95, 0xcb, 0xfb, 0xb3, 0xf9, 0xff, 0x61, 0x02, 0x93, 0xf1, 0x9f, 0x44, 0x07, 0xed, 0x2a, 0x42, 0xda, + 0x47, 0x44, 0x17, 0x0f, 0x9a, 0x3f, 0x7e, 0x3b, 0x54, 0x0e, 0xb6, 0xb6, 0x05, 0x55, 0xc6, 0x20, 0xf2, 0x1e, 0xc1, + 0x59, 0x43, 0x07, 0x26, 0x7f, 0xc7, 0xb5, 0xe5, 0x14, 0xa2, 0x7d, 0xf5, 0x5d, 0x49, 0xa9, 0x2b, 0x9f, 0x3e, 0xf4, + 0x7f, 0xd3, 0x00, 0x98, 0xd4, 0xa8, 0xbc, 0x4e, 0x5b, 0xbe, 0xf0, 0x7d, 0xd9, 0x54, 0x64, 0xe3, 0xf8, 0xe8, 0x8a, + 0x8e, 0xb7, 0xc6, 0xb8, 0x5f, 0x44, 0x49, 0xab, 0x6b, 0x3f, 0xdd, 0xb4, 0xa0, 0x1b, 0x47, 0x44, 0x8f, 0xf1, 0x2e, + 0xe6, 0xb6, 0x37, 0xaf, 0x12, 0xeb, 0xf8, 0xa8, 0x4d, 0xed, 0x68, 0x33, 0x85, 0x07, 0x76, 0xc0, 0x63, 0x78, 0x6a, + 0xf9, 0x78, 0xb8, 0xe1, 0x10, 0x44, 0xb0, 0x41, 0x02, 0x8c, 0xa4, 0x24, 0x31, 0x65, 0x49, 0xec, 0x71, 0x38, 0xae, + 0xb4, 0x15, 0x3e, 0x9d, 0x4a, 0x77, 0xc8, 0x1f, 0x6a, 0xbc, 0x4f, 0xaa, 0xe1, 0xb1, 0xcf, 0x38, 0x89, 0x5b, 0x89, + 0xfa, 0x51, 0x1e, 0xc4, 0x56, 0xb0, 0xcf, 0x02, 0x5c, 0x55, 0x84, 0xb3, 0x35, 0x0f, 0x1c, 0xc0, 0x06, 0x09, 0x4c, + 0x29, 0xe2, 0x28, 0x8e, 0xef, 0x7e, 0xd2, 0x4f, 0xfc, 0xdc, 0x8a, 0x65, 0x31, 0x2b, 0x48, 0xf2, 0xfe, 0x73, 0x78, + 0x24, 0x4f, 0xcb, 0x9b, 0x24, 0xd9, 0x64, 0xfe, 0x7e, 0x7c, 0x61, 0x4f, 0x2c, 0x7c, 0xc1, 0x0a, 0xa7, 0x3b, 0xb2, + 0xf4, 0x32, 0x6a, 0x5d, 0xfc, 0x05, 0x4e, 0xb0, 0xbf, 0x4d, 0xef, 0x5d, 0x79, 0x75, 0xbf, 0xea, 0x7d, 0x5f, 0xae, + 0x49, 0xed, 0x97, 0x1b, 0x2d, 0x1e, 0x3f, 0x4f, 0x27, 0x5a, 0xb7, 0x8c, 0x3e, 0xf4, 0xbf, 0x79, 0x76, 0x87, 0x20, + 0xfb, 0x49, 0xd6, 0xde, 0x27, 0xb1, 0xed, 0x07, 0x28, 0x72, 0xdd, 0xdc, 0xaf, 0x10, 0x4e, 0xbf, 0xb3, 0xc0, 0x4b, + 0x09, 0x7e, 0x66, 0x83, 0xaa, 0xc7, 0x6a, 0x39, 0xb9, 0xda, 0xc1, 0xa0, 0x1c, 0x2e, 0x78, 0x02, 0xd6, 0x59, 0xcc, + 0x0c, 0x4a, 0xba, 0xa3, 0xd6, 0xdf, 0x3d, 0xc5, 0xf7, 0xda, 0x66, 0x36, 0x26, 0x22, 0xb9, 0x51, 0xf6, 0xb0, 0x74, + 0x11, 0xce, 0xf2, 0x9d, 0xf3, 0xf1, 0xf7, 0x46, 0xc8, 0x19, 0x56, 0xf9, 0x2e, 0x91, 0x93, 0xcf, 0xf8, 0x94, 0x0d, + 0x57, 0x97, 0x1b, 0x2d, 0x36, 0x88, 0x56, 0xf4, 0x95, 0x38, 0x20, 0x51, 0xb4, 0x5b, 0x3c, 0xef, 0x65, 0x48, 0xfe, + 0x36, 0xb9, 0xc6, 0x01, 0x46, 0x2e, 0xb3, 0x9c, 0xc1, 0x17, 0xd7, 0x8c, 0x81, 0xea, 0x57, 0xd3, 0xfb, 0x60, 0x91, + 0x92, 0x51, 0x69, 0x9e, 0xd1, 0xa8, 0x65, 0x2e, 0xc1, 0xf8, 0x0a, 0x0d, 0xfd, 0x88, 0x7d, 0xfa, 0x7c, 0x23, 0x72, + 0x77, 0x0c, 0xeb, 0x3f, 0x8a, 0xef, 0x01, 0x72, 0xec, 0x0d, 0xea, 0x06, 0xd9, 0xb0, 0x48, 0x6a, 0x44, 0xe3, 0x12, + 0xab, 0x74, 0x41, 0x36, 0xb0, 0x7b, 0x61, 0xef, 0x7f, 0xc7, 0x7f, 0xa6, 0x12, 0x09, 0x43, 0x84, 0x2f, 0x36, 0x32, + 0xe8, 0x06, 0x17, 0xc1, 0xf4, 0x19, 0xe1, 0x41, 0x92, 0xa8, 0xbb, 0x62, 0x2c, 0xf0, 0x04, 0x4a, 0x50, 0x32, 0xcf, + 0xe2, 0xea, 0x0e, 0xfa, 0xff, 0xa5, 0x18, 0xd5, 0xe7, 0xed, 0xf2, 0xa6, 0x12, 0xf5, 0xd0, 0x21, 0xc7, 0x79, 0xc1, + 0x17, 0x60, 0xb3, 0x27, 0x4b, 0x5e, 0x02, 0x31, 0x4c, 0xfe, 0x2b, 0x2c, 0x2c, 0x7d, 0x8a, 0xe5, 0x74, 0xf8, 0x97, + 0x6b, 0x16, 0x7b, 0x7b, 0xb8, 0xe9, 0x84, 0x61, 0x7c, 0x4a, 0xf3, 0x05, 0xbd, 0x5d, 0x37, 0x35, 0x6c, 0xe5, 0xc7, + 0x55, 0x16, 0x4f, 0x9d, 0xfb, 0xe5, 0x9b, 0xbc, 0xb8, 0xb4, 0x67, 0x53, 0x75, 0x7e, 0xf0, 0xdc, 0x17, 0xe3, 0x96, + 0xf1, 0xdf, 0xe8, 0x88, 0x97, 0x5f, 0xbc, 0xaf, 0x48, 0xc4, 0xcc, 0x83, 0xcd, 0x7d, 0x5d, 0x90, 0xd3, 0x2f, 0xd1, + 0x3c, 0x2c, 0x57, 0x94, 0x5e, 0x65, 0x76, 0xd5, 0x0f, 0xdf, 0xe4, 0xd9, 0xa5, 0x97, 0x1d, 0xb4, 0xda, 0x7c, 0xaa, + 0x6d, 0xc0, 0xda, 0x02, 0xfa, 0x2f, 0x4b, 0xb5, 0xd9, 0x86, 0x34, 0x5e, 0xa8, 0x7c, 0x57, 0x1d, 0x51, 0x03, 0xfb, + 0x23, 0x3b, 0x6c, 0x78, 0xa0, 0xff, 0x36, 0xbd, 0x9e, 0x3a, 0xb5, 0xaa, 0xb6, 0x3b, 0x09, 0x70, 0xc6, 0x64, 0xad, + 0x62, 0x8c, 0x04, 0xd1, 0x5d, 0x7a, 0xb3, 0x6d, 0x7c, 0x68, 0xda, 0x52, 0xc1, 0xf7, 0xfd, 0x89, 0x61, 0x8a, 0x7b, + 0xda, 0x70, 0xf1, 0x2c, 0x14, 0xf8, 0x9d, 0xb1, 0x43, 0x4f, 0xf4, 0x00, 0x5d, 0x1f, 0x64, 0xb3, 0x58, 0xb6, 0x4b, + 0x20, 0xcf, 0x33, 0xf8, 0xd9, 0x22, 0x96, 0x45, 0xfa, 0x66, 0x46, 0xf7, 0x8f, 0x9a, 0x20, 0x90, 0xb3, 0xa2, 0x2f, + 0x26, 0x05, 0x25, 0x72, 0x54, 0x53, 0x1f, 0xed, 0x4b, 0x9d, 0xa3, 0x2f, 0x36, 0xc2, 0x1a, 0x4a, 0x20, 0xea, 0x0c, + 0xf9, 0xad, 0x52, 0x70, 0xf3, 0xc4, 0x72, 0x81, 0x06, 0x03, 0x25, 0x5c, 0xce, 0x5f, 0xfc, 0x0f, 0xd9, 0x5a, 0xeb, + 0x02, 0x69, 0x65, 0xc3, 0xfc, 0xaa, 0xca, 0xad, 0xe8, 0xe6, 0x3b, 0x34, 0x35, 0xbd, 0x7a, 0x22, 0x54, 0x78, 0xaf, + 0xdc, 0x3f, 0xab, 0xc8, 0xb8, 0x8e, 0x73, 0x48, 0x73, 0x10, 0xc5, 0x33, 0x29, 0x1b, 0x1a, 0x34, 0x53, 0x0e, 0xb2, + 0xaf, 0x32, 0x40, 0xa2, 0xac, 0xea, 0x28, 0xb6, 0xb8, 0xdc, 0xd0, 0x76, 0x89, 0xdb, 0x96, 0x52, 0x9b, 0x48, 0x5b, + 0xbc, 0xc2, 0x23, 0x4b, 0x88, 0x2e, 0x3b, 0x00, 0x85, 0x48, 0x8e, 0xac, 0x7b, 0xae, 0x48, 0xd1, 0xca, 0xed, 0xdb, + 0xb0, 0xe3, 0x3a, 0x42, 0xeb, 0xae, 0xe6, 0xaa, 0x35, 0x6a, 0x34, 0x32, 0xc9, 0xb0, 0x71, 0x6d, 0xf0, 0xaa, 0x04, + 0x35, 0xd4, 0xd8, 0xc6, 0xa1, 0x4c, 0xff, 0xf3, 0xcc, 0x17, 0x33, 0x67, 0x5a, 0x5f, 0xf2, 0xfd, 0x24, 0xb6, 0x48, + 0x45, 0xc3, 0x7e, 0xc6, 0xbe, 0x89, 0x0c, 0x41, 0x8b, 0x8e, 0x58, 0xf5, 0xa9, 0x58, 0xcd, 0x75, 0x32, 0x28, 0x50, + 0x6a, 0xde, 0x38, 0x6d, 0xae, 0x57, 0xe5, 0xdc, 0x23, 0xae, 0x8c, 0x81, 0xdd, 0x9c, 0xdc, 0xb6, 0xf2, 0xbb, 0x99, + 0x9f, 0x36, 0xce, 0x2b, 0x45, 0x86, 0x33, 0xb6, 0x73, 0x52, 0x9f, 0x17, 0x48, 0x0c, 0x97, 0x16, 0xf3, 0x87, 0x0b, + 0x4a, 0x4d, 0x1d, 0x16, 0x8a, 0x24, 0xa7, 0xa5, 0xa9, 0xc0, 0x6f, 0x3f, 0xbc, 0xf6, 0xca, 0x2c, 0x15, 0x0b, 0x02, + 0x2f, 0x14, 0xf3, 0xe7, 0xc2, 0x0e, 0x16, 0xef, 0x33, 0xa1, 0x83, 0x49, 0x9f, 0xf2, 0xdc, 0xe6, 0x26, 0xef, 0xe5, + 0x85, 0xc3, 0xe4, 0xc5, 0x86, 0xe8, 0x67, 0x11, 0x8d, 0x7e, 0x3a, 0xe8, 0x5c, 0x5b, 0xa8, 0x70, 0xe2, 0x09, 0x92, + 0x6c, 0x4a, 0xa1, 0x7b, 0xcd, 0x23, 0x45, 0x52, 0x83, 0x1c, 0xed, 0x7e, 0x27, 0x17, 0xe3, 0xa4, 0xd5, 0x38, 0x2a, + 0xab, 0x24, 0xe1, 0xf3, 0x83, 0xe4, 0x36, 0xa1, 0x44, 0xf9, 0x2c, 0xd2, 0x8c, 0x24, 0x6b, 0xdc, 0x6b, 0x2b, 0xb8, + 0x46, 0xcc, 0xad, 0x0a, 0x06, 0x9b, 0xfd, 0x44, 0xfa, 0xd5, 0x76, 0xf0, 0x26, 0xc5, 0x83, 0x44, 0x09, 0x86, 0x8b, + 0x73, 0xfa, 0xa1, 0x45, 0x47, 0x7e, 0x9d, 0x8d, 0x30, 0x08, 0x0e, 0xa1, 0x14, 0x2a, 0x6b, 0x29, 0x68, 0xe8, 0xbf, + 0x27, 0x6b, 0x87, 0x14, 0x48, 0x04, 0x7c, 0x4e, 0xde, 0x4d, 0x98, 0x12, 0x9c, 0x3c, 0x95, 0x9c, 0x10, 0xae, 0x2a, + 0x16, 0x6f, 0x4a, 0xee, 0x40, 0x79, 0x0c, 0xdc, 0x8a, 0xa0, 0x0b, 0xaa, 0x13, 0x51, 0x2a, 0x70, 0xf4, 0xf6, 0x29, + 0xba, 0xbb, 0x8b, 0x33, 0x58, 0x88, 0x04, 0xf7, 0x2a, 0xb3, 0x4e, 0x6a, 0xc9, 0x51, 0x46, 0x21, 0x9b, 0xcd, 0x46, + 0x34, 0xfa, 0x84, 0x2b, 0x60, 0xe2, 0x49, 0xfc, 0x1f, 0x51, 0x55, 0x13, 0xad, 0xbb, 0xa1, 0xbb, 0x2e, 0x49, 0x1f, + 0x9a, 0x8e, 0x61, 0x5a, 0x5c, 0xb7, 0x13, 0x92, 0x3a, 0xd3, 0x7e, 0x1b, 0x06, 0xcf, 0x6f, 0xce, 0x57, 0x9b, 0x3f, + 0xde, 0x6e, 0xad, 0x44, 0x51, 0xe4, 0x82, 0xc9, 0xc0, 0x91, 0x11, 0x72, 0xd5, 0x45, 0xdd, 0xf1, 0xb0, 0x35, 0x2d, + 0x92, 0xdc, 0xe9, 0xb8, 0xdd, 0x40, 0x35, 0xbe, 0xfc, 0xc6, 0x75, 0x9b, 0xcd, 0x10, 0xf2, 0x76, 0x7f, 0xf0, 0x34, + 0x39, 0x10, 0x55, 0xe5, 0x5f, 0x4a, 0xd6, 0x0f, 0x03, 0x4f, 0x4a, 0x72, 0xe8, 0xa9, 0x30, 0xee, 0xc9, 0xca, 0x44, + 0x87, 0x89, 0x45, 0x24, 0xff, 0x2f, 0x7f, 0x04, 0x4b, 0x4c, 0x71, 0x2d, 0x15, 0xd8, 0x62, 0x7e, 0x58, 0xdd, 0x5b, + 0x19, 0x03, 0x22, 0x97, 0x00, 0x12, 0x21, 0x6f, 0xc8, 0xd7, 0x49, 0xf2, 0xae, 0x70, 0xed, 0x54, 0xaf, 0x79, 0x62, + 0xe6, 0x91, 0xdf, 0xf9, 0x89, 0x79, 0x9c, 0x6a, 0x82, 0x59, 0x82, 0x2b, 0x26, 0x2e, 0x00, 0xaf, 0xf4, 0x17, 0x55, + 0x6e, 0x0a, 0x04, 0x82, 0xb3, 0xaf, 0xd2, 0x9f, 0x14, 0x54, 0x21, 0x6e, 0x47, 0x42, 0x9b, 0x6a, 0x11, 0x9e, 0xd9, + 0x33, 0x0e, 0x2e, 0x36, 0x39, 0x22, 0x03, 0x03, 0x90, 0xe5, 0xa9, 0xd7, 0xc2, 0x3e, 0x9f, 0xf9, 0x37, 0xda, 0x5e, + 0x5b, 0x65, 0x2b, 0x16, 0x3c, 0x78, 0xed, 0xd5, 0x77, 0xb3, 0x4a, 0xd9, 0x2a, 0xb7, 0xfc, 0x86, 0xce, 0xf0, 0x3e, + 0x83, 0x36, 0xd1, 0xf7, 0x1e, 0x0d, 0x56, 0x28, 0xcd, 0x4f, 0x09, 0x93, 0xb0, 0x10, 0xe6, 0x98, 0x6d, 0x27, 0x54, + 0xcf, 0x99, 0xf5, 0xab, 0x14, 0x55, 0xfe, 0x91, 0x63, 0xdc, 0x75, 0xea, 0x5c, 0x98, 0x67, 0xf2, 0x99, 0x92, 0x6c, + 0x58, 0x03, 0xe3, 0x86, 0xe1, 0xdb, 0xfc, 0x8b, 0x9e, 0x0c, 0xed, 0x51, 0xbf, 0xef, 0xd0, 0xf6, 0x30, 0xaa, 0xd3, + 0xad, 0x10, 0x17, 0x5d, 0x18, 0x82, 0x70, 0xf7, 0x29, 0x2f, 0x48, 0xeb, 0xb0, 0xf6, 0x54, 0xa3, 0xc3, 0xa0, 0xc6, + 0x40, 0x9d, 0x16, 0x83, 0xe5, 0xb4, 0x54, 0x50, 0x36, 0x05, 0x33, 0xd5, 0x06, 0x6e, 0xd8, 0x9a, 0xfb, 0x7f, 0xf9, + 0x1f, 0x21, 0xbc, 0x3f, 0xf0, 0x87, 0xf1, 0xbf, 0x97, 0x48, 0x8e, 0x98, 0xb0, 0xa4, 0x92, 0xbb, 0x77, 0x01, 0xe3, + 0x4f, 0xa1, 0xbf, 0x86, 0xf6, 0xa1, 0x1d, 0x43, 0x7b, 0x20, 0xca, 0xe0, 0xfe, 0x6a, 0x29, 0xc6, 0x4e, 0x01, 0x21, + 0xc6, 0xf2, 0xa2, 0x04, 0x2a, 0x29, 0xc5, 0x81, 0x17, 0x15, 0x00, 0xce, 0xbb, 0x40, 0xc7, 0xa6, 0xd8, 0xf6, 0x92, + 0x20, 0x06, 0x15, 0x10, 0x4d, 0x89, 0x9c, 0x93, 0xb4, 0xaf, 0x38, 0xf1, 0x1e, 0x73, 0x72, 0x62, 0x1f, 0xd4, 0xf5, + 0xf9, 0x86, 0xcb, 0xb1, 0x40, 0xd7, 0x15, 0x63, 0x53, 0xb6, 0xa3, 0xcb, 0x8b, 0xd5, 0xcb, 0x5b, 0x31, 0x89, 0x02, + 0xe9, 0xd2, 0x46, 0x5e, 0x90, 0x8f, 0xb8, 0x3d, 0x5b, 0x96, 0x65, 0xf3, 0xa2, 0x65, 0x9c, 0xaf, 0x0c, 0x90, 0x0d, + 0x50, 0xb4, 0xa5, 0x2f, 0x2c, 0xe4, 0xb0, 0x2c, 0x0d, 0xe5, 0x36, 0x70, 0xae, 0xca, 0xf6, 0xe6, 0x4d, 0x82, 0x34, + 0x3f, 0xe4, 0x75, 0xac, 0x4d, 0x2d, 0xb5, 0xff, 0x6e, 0xab, 0x36, 0xec, 0x68, 0x14, 0xcd, 0x81, 0xe9, 0xa8, 0x73, + 0x98, 0x8f, 0x39, 0x17, 0xe4, 0x59, 0xd4, 0xb6, 0x76, 0xbd, 0x95, 0x3c, 0xbf, 0xf1, 0x2a, 0xce, 0x05, 0x0f, 0xab, + 0x3f, 0x3e, 0xb6, 0xd4, 0xc6, 0xf5, 0x2d, 0xbe, 0xf1, 0x07, 0x7f, 0x0f, 0xa2, 0x54, 0x43, 0x0d, 0xe7, 0x2f, 0x27, + 0xe7, 0xb5, 0x7d, 0x02, 0x2c, 0xa7, 0xad, 0xca, 0x7e, 0x9d, 0x57, 0xb1, 0x30, 0x13, 0x99, 0xef, 0xd2, 0x9a, 0xe8, + 0x4b, 0x4d, 0x16, 0x99, 0xd3, 0xf1, 0x37, 0x6d, 0xf8, 0xed, 0xd2, 0x9b, 0x11, 0x42, 0xc9, 0x8c, 0xd0, 0x8c, 0xa3, + 0x9a, 0x37, 0xff, 0xa1, 0xe5, 0xfb, 0xb2, 0x43, 0x0a, 0xee, 0x78, 0x4b, 0x56, 0x43, 0x79, 0x3b, 0x5d, 0x9b, 0x8f, + 0xbc, 0x2c, 0x40, 0xed, 0xa9, 0x54, 0x82, 0x04, 0x7e, 0x4f, 0x1f, 0x9a, 0x87, 0xcd, 0xa6, 0xaa, 0xbd, 0x5e, 0x1f, + 0x1a, 0x13, 0x61, 0x2a, 0x8f, 0x60, 0x71, 0xb9, 0x51, 0x68, 0x67, 0xf8, 0x95, 0xce, 0xb9, 0x19}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 7bf86f6e8b..b230f2a906 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -10,7608 +10,7677 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x69, 0x7b, 0x1b, 0x37, 0xb2, 0x30, 0xfa, - 0xf9, 0xde, 0x5f, 0x21, 0xf5, 0x71, 0x34, 0x0d, 0x11, 0x6c, 0x91, 0xd4, 0x62, 0xb9, 0x29, 0x88, 0xd7, 0xeb, 0xd8, - 0x59, 0x6c, 0xc7, 0xb2, 0x9d, 0x49, 0x18, 0x1e, 0x07, 0xec, 0x06, 0x49, 0xc4, 0x4d, 0x80, 0x69, 0x80, 0x96, 0x14, - 0x92, 0xff, 0xfd, 0x3e, 0x85, 0xa5, 0x1b, 0x4d, 0xd2, 0x9e, 0x39, 0xef, 0x5d, 0x9e, 0xf7, 0xe4, 0x8c, 0xc5, 0xc6, - 0x8e, 0x42, 0xa1, 0x50, 0x55, 0xa8, 0x2a, 0x5c, 0x1d, 0xe6, 0x32, 0xd3, 0xf7, 0x0b, 0x76, 0x30, 0xd3, 0xf3, 0xe2, - 0xfa, 0xca, 0xfd, 0xcb, 0x68, 0x7e, 0x7d, 0x55, 0x70, 0xf1, 0xf9, 0xa0, 0x64, 0x05, 0xe1, 0x99, 0x14, 0x07, 0xb3, - 0x92, 0x4d, 0x48, 0x4e, 0x35, 0x4d, 0xf9, 0x9c, 0x4e, 0xd9, 0xc1, 0xc9, 0xf5, 0xd5, 0x9c, 0x69, 0x7a, 0x90, 0xcd, - 0x68, 0xa9, 0x98, 0x26, 0x1f, 0xde, 0xbf, 0x68, 0x5f, 0x5e, 0x5f, 0xa9, 0xac, 0xe4, 0x0b, 0x7d, 0x00, 0x4d, 0x92, - 0xb9, 0xcc, 0x97, 0x05, 0xbb, 0x3e, 0x39, 0xb9, 0xbd, 0xbd, 0x4d, 0xfe, 0x54, 0xff, 0xe7, 0x17, 0x5a, 0x1e, 0xfc, - 0xb3, 0x24, 0x6f, 0xc6, 0x7f, 0xb2, 0x4c, 0x27, 0x39, 0x9b, 0x70, 0xc1, 0xde, 0x96, 0x72, 0xc1, 0x4a, 0x7d, 0xdf, - 0x87, 0xcc, 0x9f, 0x4b, 0x12, 0x73, 0xac, 0x31, 0x43, 0xe4, 0x5a, 0x1f, 0x70, 0x71, 0xc0, 0x07, 0xff, 0x2c, 0x4d, - 0xca, 0x8a, 0x89, 0xe5, 0x9c, 0x95, 0x74, 0x5c, 0xb0, 0xf4, 0xb0, 0x83, 0x33, 0x29, 0x26, 0x7c, 0xba, 0xac, 0xbe, - 0x6f, 0x4b, 0xae, 0xfd, 0xef, 0x2f, 0xb4, 0x58, 0xb2, 0x94, 0x6d, 0x50, 0xca, 0x87, 0x7a, 0x44, 0x98, 0x69, 0xf9, - 0x73, 0xdd, 0x70, 0xfc, 0xb3, 0x69, 0xf2, 0x7e, 0xc1, 0xe4, 0xe4, 0x40, 0x1f, 0x92, 0x48, 0xdd, 0xcf, 0xc7, 0xb2, - 0x88, 0x06, 0xba, 0x15, 0x45, 0x29, 0x94, 0xc1, 0x0c, 0xf5, 0x33, 0x29, 0x94, 0x3e, 0x10, 0x9c, 0xdc, 0x72, 0x91, - 0xcb, 0x5b, 0x7c, 0x2b, 0x88, 0xe0, 0xc9, 0xcd, 0x8c, 0xe6, 0xf2, 0xf6, 0x9d, 0x94, 0xfa, 0xe8, 0x28, 0x76, 0xdf, - 0xf7, 0x4f, 0x6f, 0x6e, 0x08, 0x21, 0x5f, 0x24, 0xcf, 0x0f, 0x3a, 0xeb, 0x75, 0x90, 0x9a, 0x08, 0xaa, 0xf9, 0x17, - 0x66, 0x2b, 0xa1, 0xa3, 0xa3, 0x88, 0xe6, 0x72, 0xa1, 0x59, 0x7e, 0xa3, 0xef, 0x0b, 0x76, 0x33, 0x63, 0x4c, 0xab, - 0x88, 0x8b, 0x83, 0x67, 0x32, 0x5b, 0xce, 0x99, 0xd0, 0xc9, 0xa2, 0x94, 0x5a, 0xc2, 0xc0, 0x8e, 0x8e, 0xa2, 0x92, - 0x2d, 0x0a, 0x9a, 0x31, 0xc8, 0x7f, 0x7a, 0x73, 0x53, 0xd7, 0xa8, 0x0b, 0xe1, 0xcf, 0x82, 0xdc, 0x98, 0xa1, 0xc7, - 0x08, 0xff, 0x22, 0x88, 0x60, 0xb7, 0x07, 0xbf, 0x30, 0xfa, 0xf9, 0x27, 0xba, 0xe8, 0x67, 0x05, 0x55, 0xea, 0xe0, - 0xb5, 0x5c, 0x99, 0x69, 0x94, 0xcb, 0x4c, 0xcb, 0x32, 0xd6, 0x98, 0x61, 0x81, 0x56, 0x7c, 0x12, 0xeb, 0x19, 0x57, - 0xc9, 0xa7, 0x07, 0x99, 0x52, 0xef, 0x98, 0x5a, 0x16, 0xfa, 0x01, 0x39, 0xec, 0x60, 0x71, 0x48, 0xc8, 0x67, 0x81, - 0xf4, 0xac, 0x94, 0xb7, 0x07, 0xcf, 0xcb, 0x52, 0x96, 0x71, 0xf4, 0xf4, 0xe6, 0xc6, 0x96, 0x38, 0xe0, 0xea, 0x40, - 0x48, 0x7d, 0x50, 0xb5, 0x07, 0xd0, 0x4e, 0x0e, 0x3e, 0x28, 0x76, 0xf0, 0xc7, 0x52, 0x28, 0x3a, 0x61, 0x4f, 0x6f, - 0x6e, 0xfe, 0x38, 0x90, 0xe5, 0xc1, 0x1f, 0x99, 0x52, 0x7f, 0x1c, 0x70, 0xa1, 0x34, 0xa3, 0x79, 0x12, 0xa1, 0xbe, - 0xe9, 0x2c, 0x53, 0xea, 0x3d, 0xbb, 0xd3, 0x44, 0x63, 0xf3, 0xa9, 0x09, 0xdb, 0x4c, 0x99, 0x3e, 0x50, 0xd5, 0xbc, - 0x62, 0xb4, 0x2a, 0x98, 0x3e, 0xd0, 0xc4, 0xe4, 0x4b, 0x07, 0x7f, 0x66, 0x3f, 0x75, 0x9f, 0x4f, 0xe2, 0x5b, 0x71, - 0x74, 0xa4, 0x2b, 0x40, 0xa3, 0x95, 0x5b, 0x21, 0xc2, 0x0e, 0x7d, 0xda, 0xd1, 0x11, 0x4b, 0x0a, 0x26, 0xa6, 0x7a, - 0x46, 0x08, 0xe9, 0xf6, 0xc5, 0xd1, 0x51, 0xac, 0xc9, 0x2f, 0x22, 0x99, 0x32, 0x1d, 0x33, 0x84, 0x70, 0x5d, 0xfb, - 0xe8, 0x28, 0xb6, 0x40, 0x90, 0x44, 0x1b, 0xc0, 0x35, 0x60, 0x8c, 0x12, 0x07, 0xfd, 0x9b, 0x7b, 0x91, 0xc5, 0xe1, - 0xf8, 0x11, 0x16, 0x47, 0x47, 0xbf, 0x88, 0x44, 0x41, 0x8b, 0x58, 0x23, 0xb4, 0x29, 0x99, 0x5e, 0x96, 0xe2, 0x40, - 0x6f, 0xb4, 0xbc, 0xd1, 0x25, 0x17, 0xd3, 0x18, 0xad, 0x7c, 0x5a, 0x50, 0x71, 0xb3, 0xb1, 0xc3, 0xfd, 0xad, 0x24, - 0x9c, 0x5c, 0x43, 0x8f, 0xaf, 0x65, 0xec, 0x70, 0x90, 0x13, 0x12, 0x29, 0x53, 0x37, 0x1a, 0xf0, 0x94, 0xb7, 0xa2, - 0x08, 0xdb, 0x51, 0xe2, 0xcf, 0x02, 0x61, 0xa1, 0x01, 0x75, 0x93, 0x24, 0xd1, 0x88, 0x5c, 0xaf, 0x3c, 0x58, 0x78, - 0x30, 0xd1, 0x01, 0x1f, 0x76, 0x46, 0xa9, 0x4e, 0x4a, 0x96, 0x2f, 0x33, 0x16, 0xc7, 0x02, 0x2b, 0x2c, 0x11, 0xb9, - 0x16, 0xad, 0xb8, 0x24, 0xd7, 0xb0, 0xde, 0x65, 0x73, 0xb1, 0x09, 0x39, 0xec, 0x20, 0x37, 0xc8, 0xd2, 0x8f, 0x10, - 0x40, 0xec, 0x06, 0x54, 0x12, 0x12, 0x89, 0xe5, 0x7c, 0xcc, 0xca, 0xa8, 0x2a, 0xd6, 0x6f, 0xe0, 0xc5, 0x52, 0xb1, - 0x83, 0x4c, 0xa9, 0x83, 0xc9, 0x52, 0x64, 0x9a, 0x4b, 0x71, 0x10, 0xb5, 0xca, 0x56, 0x64, 0xf1, 0xa1, 0x42, 0x87, - 0x08, 0x6d, 0x50, 0xac, 0x50, 0x8b, 0x0f, 0x65, 0xab, 0x3b, 0xc2, 0x30, 0x4a, 0xd4, 0x77, 0xed, 0x39, 0x08, 0x30, - 0xcc, 0x61, 0x92, 0x1b, 0xfc, 0xbd, 0xdd, 0xf9, 0x30, 0xc5, 0x5b, 0x31, 0xe0, 0xc9, 0xee, 0x4e, 0x21, 0x3a, 0x99, - 0xd3, 0x45, 0xcc, 0xc8, 0x35, 0x33, 0xd8, 0x45, 0x45, 0x06, 0x63, 0x6d, 0x2c, 0xdc, 0x80, 0xa5, 0x2c, 0xa9, 0x71, - 0x0a, 0xa5, 0x3a, 0x99, 0xc8, 0xf2, 0x39, 0xcd, 0x66, 0x50, 0xaf, 0xc2, 0x98, 0xdc, 0x6f, 0xb8, 0xac, 0x64, 0x54, - 0xb3, 0xe7, 0x05, 0x83, 0xaf, 0x38, 0x32, 0x35, 0x23, 0x84, 0x15, 0x6c, 0xf5, 0x82, 0xeb, 0xd7, 0x52, 0x64, 0xac, - 0xaf, 0x02, 0xfc, 0x32, 0x2b, 0xff, 0x58, 0xeb, 0x92, 0x8f, 0x97, 0x9a, 0xc5, 0x91, 0x80, 0x12, 0x11, 0x56, 0x08, - 0x8b, 0x44, 0xb3, 0x3b, 0xfd, 0x54, 0x0a, 0xcd, 0x84, 0x26, 0xcc, 0x43, 0x15, 0xf3, 0x84, 0x2e, 0x16, 0x4c, 0xe4, - 0x4f, 0x67, 0xbc, 0xc8, 0x63, 0x81, 0x36, 0x68, 0x83, 0x7f, 0x15, 0x04, 0x26, 0x49, 0xae, 0x79, 0x0a, 0xff, 0x7c, - 0x7d, 0x3a, 0xb1, 0x26, 0xd7, 0x66, 0x5b, 0x30, 0x12, 0x45, 0xfd, 0x89, 0x2c, 0x63, 0x37, 0x85, 0x03, 0x20, 0x5d, - 0xd0, 0xc7, 0xbb, 0x65, 0xc1, 0x14, 0x62, 0x2d, 0x22, 0xaa, 0x75, 0x74, 0x10, 0xfe, 0xad, 0x8c, 0x19, 0x2c, 0x00, - 0x47, 0x29, 0x37, 0x24, 0xf0, 0x47, 0xee, 0x36, 0x55, 0x5e, 0x11, 0xb5, 0xbf, 0x04, 0xc9, 0x79, 0xa2, 0xcb, 0xa5, - 0xd2, 0x2c, 0x7f, 0x7f, 0xbf, 0x60, 0x0a, 0x6b, 0x4a, 0xfe, 0x12, 0x83, 0xbf, 0x44, 0xc2, 0xe6, 0x0b, 0x7d, 0x7f, - 0x63, 0xa8, 0x79, 0x1a, 0x45, 0xf8, 0x5f, 0xa6, 0x68, 0xc9, 0x68, 0x06, 0x24, 0xcd, 0x81, 0xec, 0xad, 0x2c, 0xee, - 0x27, 0xbc, 0x28, 0x6e, 0x96, 0x8b, 0x85, 0x2c, 0x35, 0xd6, 0x82, 0xac, 0xb4, 0xac, 0xe1, 0x03, 0x2b, 0xba, 0x52, - 0xb7, 0x5c, 0x67, 0xb3, 0x58, 0xa3, 0x55, 0x46, 0x15, 0x3b, 0x78, 0x22, 0x65, 0xc1, 0xa8, 0x48, 0x39, 0xe1, 0x03, - 0x4d, 0x53, 0xb1, 0x2c, 0x8a, 0xfe, 0xb8, 0x64, 0xf4, 0x73, 0xdf, 0x64, 0xdb, 0xc3, 0x21, 0x35, 0xbf, 0x1f, 0x97, - 0x25, 0xbd, 0x87, 0x82, 0x84, 0x40, 0xb1, 0x01, 0x4f, 0xbf, 0xbf, 0x79, 0xf3, 0x3a, 0xb1, 0x7b, 0x85, 0x4f, 0xee, - 0x63, 0x5e, 0xed, 0x3f, 0xbe, 0xc1, 0x93, 0x52, 0xce, 0xb7, 0xba, 0xb6, 0xa0, 0xe3, 0xfd, 0xaf, 0x0c, 0x81, 0x11, - 0x7e, 0x68, 0x9b, 0x0e, 0x47, 0xf0, 0xda, 0x60, 0x3e, 0x64, 0x12, 0xd7, 0x2f, 0xfc, 0x93, 0xda, 0xe4, 0x98, 0xa3, - 0x6f, 0x8f, 0x56, 0x97, 0xf7, 0x2b, 0x46, 0xcc, 0x38, 0x17, 0x70, 0x30, 0xc2, 0x18, 0x33, 0xaa, 0xb3, 0xd9, 0x8a, - 0x99, 0xc6, 0x36, 0x7e, 0xc4, 0x6c, 0xb3, 0xc1, 0x7f, 0x4b, 0x8f, 0xf5, 0xfa, 0x90, 0x10, 0x6e, 0xe8, 0x15, 0xd1, - 0xeb, 0x35, 0x27, 0x84, 0x23, 0xfc, 0x8e, 0x93, 0x15, 0xf5, 0x13, 0x82, 0x93, 0x0d, 0xb6, 0x67, 0x6a, 0xa9, 0x0c, - 0x9c, 0x80, 0x5f, 0x58, 0xa9, 0x59, 0x99, 0x6a, 0x81, 0x4b, 0x36, 0x29, 0x60, 0x1c, 0x87, 0x5d, 0x3c, 0xa3, 0xea, - 0xe9, 0x8c, 0x8a, 0x29, 0xcb, 0xd3, 0xbf, 0xe5, 0x06, 0x33, 0x41, 0xa2, 0x09, 0x17, 0xb4, 0xe0, 0x7f, 0xb3, 0x3c, - 0x72, 0xe7, 0xc2, 0x47, 0x7d, 0xc0, 0xee, 0x34, 0x13, 0xb9, 0x3a, 0x78, 0xf9, 0xfe, 0xa7, 0x1f, 0xdd, 0x62, 0x36, - 0xce, 0x0a, 0xb4, 0x52, 0xcb, 0x05, 0x2b, 0x63, 0x84, 0xdd, 0x59, 0xf1, 0x9c, 0x1b, 0x3a, 0xf9, 0x13, 0x5d, 0xd8, - 0x14, 0xae, 0x3e, 0x2c, 0x72, 0xaa, 0xd9, 0x5b, 0x26, 0x72, 0x2e, 0xa6, 0xe4, 0xb0, 0x6b, 0xd3, 0x67, 0xd4, 0x65, - 0xe4, 0x55, 0xd2, 0xa7, 0x07, 0xcf, 0x0b, 0x33, 0xf7, 0xea, 0x73, 0x19, 0xa3, 0x8d, 0xd2, 0x54, 0xf3, 0xec, 0x80, - 0xe6, 0xf9, 0x2b, 0xc1, 0x35, 0x37, 0x23, 0x2c, 0x61, 0x89, 0x00, 0x57, 0x99, 0x3d, 0x35, 0xfc, 0xc8, 0x63, 0x84, - 0xe3, 0xd8, 0x9d, 0x05, 0x33, 0xe4, 0xd6, 0xec, 0xe8, 0xa8, 0xa6, 0xfc, 0x03, 0x96, 0xda, 0x4c, 0x32, 0x1c, 0xa1, - 0x64, 0xb1, 0x54, 0xb0, 0xd8, 0xbe, 0x0b, 0x38, 0x68, 0xe4, 0x58, 0xb1, 0xf2, 0x0b, 0xcb, 0x2b, 0x04, 0x51, 0x31, - 0x5a, 0x6d, 0xf5, 0xe1, 0xb6, 0x87, 0x26, 0xc3, 0x51, 0x3f, 0x24, 0xe1, 0xcc, 0x21, 0xbb, 0xe5, 0x54, 0x38, 0x53, - 0x15, 0x51, 0x89, 0xe1, 0x40, 0xad, 0x08, 0x8b, 0x22, 0x7e, 0x7e, 0x8b, 0x58, 0x00, 0x0f, 0x11, 0x52, 0x0e, 0x7f, - 0xe6, 0x3e, 0xff, 0x62, 0x0e, 0x0f, 0x85, 0x05, 0xc2, 0xda, 0x8e, 0x54, 0x21, 0xb4, 0x41, 0x58, 0xfb, 0xe1, 0x5a, - 0xa2, 0xe4, 0xf9, 0x22, 0x38, 0xb5, 0xc9, 0x3b, 0x6e, 0x8e, 0x6d, 0xa0, 0x6d, 0x54, 0xb3, 0xa3, 0xa3, 0x98, 0x25, - 0x15, 0x62, 0x90, 0xc3, 0xae, 0x5b, 0xa4, 0x00, 0x5a, 0x5f, 0x19, 0x37, 0xf4, 0x6c, 0x18, 0x9c, 0x43, 0x96, 0x08, - 0xf9, 0x38, 0xcb, 0x98, 0x52, 0xb2, 0x3c, 0x3a, 0x3a, 0x34, 0xe5, 0x2b, 0xce, 0x02, 0x16, 0xf1, 0xcd, 0xad, 0xa8, - 0x87, 0x80, 0xea, 0xd3, 0xd6, 0xf3, 0x4d, 0xa4, 0xe6, 0x9b, 0x3c, 0x13, 0x92, 0x46, 0x9f, 0x3e, 0x45, 0x2d, 0x8d, - 0x1d, 0x1c, 0xa6, 0xcc, 0x77, 0x7d, 0xff, 0x8c, 0x59, 0xb6, 0xd0, 0x30, 0x21, 0x3b, 0xa0, 0xd9, 0xcb, 0x0f, 0xc6, - 0xcd, 0x21, 0x61, 0x8d, 0x15, 0xda, 0x04, 0x2b, 0xba, 0xb7, 0x69, 0xc3, 0xdf, 0xd8, 0xa5, 0x5b, 0x4d, 0x0d, 0x4f, - 0x11, 0xac, 0xe3, 0x90, 0x8d, 0x36, 0xd8, 0xc0, 0xde, 0xcf, 0x46, 0x9a, 0x81, 0x0e, 0xf5, 0xa8, 0xef, 0xf2, 0x89, - 0xb2, 0x90, 0x2b, 0xd9, 0x5f, 0x4b, 0xa6, 0xb4, 0x45, 0xe4, 0x58, 0x63, 0x89, 0xe1, 0x8c, 0xda, 0x66, 0x3a, 0x1b, - 0x2c, 0xe9, 0xbe, 0xb1, 0xbd, 0x59, 0xc0, 0xd9, 0xa8, 0x00, 0xa9, 0xbf, 0x8d, 0x4f, 0x30, 0x56, 0x8d, 0xd6, 0xeb, - 0x77, 0xdc, 0xb7, 0x52, 0xaf, 0x65, 0xc5, 0xaf, 0x6d, 0x2d, 0x0a, 0x13, 0xc8, 0x1d, 0xce, 0x87, 0x5d, 0x37, 0x7e, - 0x31, 0x22, 0x87, 0x9d, 0x0a, 0x8b, 0x1d, 0x58, 0xed, 0x78, 0x2c, 0x14, 0xdf, 0xd8, 0xa6, 0x90, 0x39, 0xeb, 0x1b, - 0xf8, 0x92, 0xcc, 0x76, 0x70, 0x75, 0x46, 0x86, 0xc0, 0x75, 0x24, 0xb3, 0xd1, 0xd7, 0xf0, 0xc9, 0x53, 0x84, 0x58, - 0xef, 0xe6, 0xd5, 0x84, 0xe3, 0x4b, 0x93, 0x70, 0x6c, 0x4d, 0x23, 0x5a, 0x54, 0x55, 0xa2, 0x0a, 0xcd, 0xdc, 0x56, - 0xaf, 0xb3, 0xb0, 0x30, 0x83, 0xa9, 0xa7, 0x14, 0x34, 0xf1, 0x9a, 0xce, 0x99, 0x8a, 0x19, 0xc2, 0x5f, 0x2b, 0x60, - 0xf1, 0x13, 0x8a, 0x8c, 0x82, 0x33, 0x54, 0xc1, 0x19, 0x0a, 0xec, 0x2e, 0x30, 0x69, 0xcd, 0x2d, 0xa7, 0x30, 0x1b, - 0xaa, 0x51, 0xcd, 0xdb, 0x05, 0x93, 0x37, 0x87, 0xb3, 0x43, 0x70, 0x0f, 0x3f, 0x9b, 0x66, 0x81, 0x66, 0x58, 0x08, - 0x85, 0xf0, 0x61, 0x67, 0x7b, 0x25, 0x7d, 0xa9, 0x7a, 0x8e, 0xc3, 0x11, 0xac, 0x83, 0x39, 0x36, 0x12, 0xae, 0xcc, - 0xdf, 0xc6, 0x56, 0x03, 0xb0, 0xdd, 0x00, 0x66, 0x24, 0x93, 0x82, 0xea, 0xb8, 0x7b, 0xd2, 0x01, 0xc6, 0xf4, 0x0b, - 0x83, 0x53, 0x05, 0xa1, 0xdd, 0xa9, 0xb0, 0x64, 0x29, 0xd4, 0x8c, 0x4f, 0x74, 0xfc, 0xab, 0x30, 0x44, 0x85, 0x15, - 0x8a, 0x81, 0x84, 0x13, 0xb0, 0xc7, 0x86, 0xe0, 0xfc, 0x2a, 0xa0, 0x9f, 0x7e, 0x75, 0x10, 0xb9, 0x91, 0x1a, 0xc2, - 0x05, 0xe4, 0xa1, 0x66, 0xad, 0x6b, 0x32, 0x53, 0x31, 0x6e, 0xc0, 0x3d, 0x76, 0x07, 0xb6, 0xc5, 0xd4, 0x51, 0x03, - 0x11, 0x70, 0xb0, 0x22, 0x0d, 0x49, 0x84, 0x4b, 0xd4, 0x89, 0x96, 0x3f, 0xca, 0x5b, 0x56, 0x3e, 0xa5, 0x30, 0xf8, - 0xd4, 0x56, 0xdf, 0xd8, 0xa3, 0xc0, 0x50, 0x7c, 0xdd, 0xf7, 0xf8, 0xf2, 0xc9, 0x4c, 0xfc, 0x6d, 0x29, 0xe7, 0x5c, - 0x31, 0xe0, 0xdb, 0x2c, 0xfc, 0x05, 0x6c, 0x34, 0xb3, 0x23, 0xe1, 0xb8, 0x61, 0x15, 0x7e, 0x3d, 0xfe, 0xb1, 0x89, - 0x5f, 0x9f, 0x1e, 0x3c, 0x9f, 0x7a, 0x0a, 0xd8, 0xdc, 0xc7, 0x08, 0xc7, 0x4e, 0xbc, 0x08, 0x4e, 0xba, 0x64, 0x86, - 0xdc, 0x31, 0xbf, 0x5e, 0xeb, 0x40, 0x8c, 0x6b, 0x70, 0x8e, 0xcc, 0x6e, 0x1b, 0xb4, 0xa1, 0x79, 0x0e, 0x2c, 0x5e, - 0x29, 0x8b, 0x22, 0x38, 0xac, 0xb0, 0xe8, 0x57, 0xc7, 0xd3, 0xa7, 0x07, 0xcf, 0x6f, 0xbe, 0x75, 0x42, 0x41, 0x7e, - 0x78, 0x48, 0xf9, 0x81, 0x8a, 0x9c, 0x95, 0x20, 0x57, 0x06, 0xab, 0xe5, 0xce, 0xd9, 0xa7, 0x52, 0x08, 0x96, 0x69, - 0x96, 0x83, 0xd0, 0x22, 0x88, 0x4e, 0x66, 0x52, 0xe9, 0x2a, 0xb1, 0x1e, 0xbd, 0x08, 0x85, 0xd0, 0x24, 0xa3, 0x45, - 0x11, 0x5b, 0x01, 0x65, 0x2e, 0xbf, 0xb0, 0x3d, 0xa3, 0xee, 0x37, 0x86, 0x5c, 0x35, 0xc3, 0x82, 0x66, 0x58, 0xa2, - 0x16, 0x05, 0xcf, 0x58, 0x75, 0x78, 0xdd, 0x24, 0x5c, 0xe4, 0xec, 0x0e, 0xe8, 0x08, 0xba, 0xbe, 0xbe, 0xee, 0xe0, - 0x2e, 0xda, 0x58, 0x80, 0xaf, 0x76, 0x00, 0xfb, 0x8d, 0x63, 0xd3, 0x0a, 0xe2, 0xab, 0xbd, 0x64, 0x0d, 0x05, 0x67, - 0x25, 0xf7, 0x82, 0x96, 0x25, 0xcf, 0x08, 0xe7, 0xac, 0x60, 0x9a, 0x79, 0x72, 0x0e, 0xcc, 0xb4, 0xdd, 0xba, 0xef, - 0x2a, 0xf8, 0x55, 0xe8, 0xe4, 0x77, 0x99, 0x5f, 0x73, 0x55, 0x89, 0xee, 0xf5, 0xf2, 0xd4, 0xd0, 0x1e, 0x68, 0xbb, - 0x3c, 0x54, 0x6b, 0x9a, 0xcd, 0xac, 0xc4, 0x1e, 0xef, 0x4c, 0xa9, 0x6e, 0xc3, 0x91, 0xf6, 0x6a, 0x13, 0x7d, 0x5f, - 0xba, 0x61, 0xee, 0x03, 0xc1, 0x8d, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x4f, 0x69, 0x51, 0x8c, 0x69, 0xf6, - 0xb9, 0x89, 0xfd, 0x35, 0x1a, 0x90, 0x6d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, 0xd2, 0x8d, 0x8d, - 0x12, 0x1f, 0x76, 0x6a, 0xb4, 0x6f, 0x2e, 0xf4, 0x57, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, 0x40, 0x05, 0xfe, - 0x2d, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xcd, 0xd6, 0x40, 0x34, 0x5a, 0x6d, 0x72, 0xae, 0xbe, 0x0e, - 0x81, 0xff, 0x57, 0x46, 0xf9, 0x2c, 0xe8, 0xe1, 0x3f, 0x1d, 0x68, 0x45, 0xe3, 0x1c, 0xe3, 0x5c, 0x8d, 0xcc, 0x31, - 0x14, 0x9e, 0xd0, 0xfc, 0x00, 0xcc, 0x8b, 0xc1, 0xf7, 0x37, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, 0xd5, 0x0f, 0x19, - 0x8a, 0x06, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x1b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, 0xee, 0x68, 0x6e, - 0x49, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9e, 0x85, 0xda, 0x99, 0x85, 0x4a, 0x02, 0x69, 0x0b, 0xd5, - 0xc8, 0x1c, 0x54, 0x4f, 0xb5, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x22, 0xb8, 0x05, 0xd1, 0xb8, - 0x74, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x75, 0x15, 0x89, 0xec, 0xe6, 0x68, 0xc8, 0xbe, 0x12, 0x97, 0x68, 0x8b, - 0xbf, 0xdf, 0x6c, 0x1c, 0x94, 0x18, 0x72, 0xab, 0xd3, 0x60, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, 0x33, 0x6c, 0x59, - 0x9f, 0x6d, 0xe0, 0x54, 0xed, 0x1e, 0x12, 0x22, 0x6b, 0xd8, 0x34, 0x98, 0x4a, 0xcf, 0x5d, 0x49, 0x84, 0xa9, 0x67, - 0x4b, 0xcb, 0x7a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0x0d, 0x56, 0x0d, 0xe1, 0x30, 0x0d, 0x8a, 0x6d, 0x52, 0x20, - 0xaa, 0xe5, 0x3e, 0x78, 0xef, 0xc3, 0x9a, 0x46, 0x3b, 0x01, 0xc4, 0xcb, 0x06, 0xc4, 0x03, 0xd0, 0x4a, 0x4b, 0xbc, - 0xe4, 0x88, 0xd0, 0x66, 0xe5, 0x98, 0xe1, 0xd2, 0x2e, 0xc4, 0x0e, 0x14, 0xb7, 0xd9, 0x4f, 0x83, 0x85, 0x20, 0xcb, - 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xf5, 0x7a, 0x07, 0xed, 0xf6, 0x72, 0xa1, 0x28, 0xa9, 0xa5, - 0xc3, 0xf5, 0xfa, 0x6f, 0x89, 0x62, 0xc7, 0xff, 0x62, 0x86, 0x06, 0x9e, 0xe8, 0x3e, 0xfe, 0x11, 0x4a, 0x19, 0x76, - 0xb4, 0x4e, 0xa9, 0x04, 0x87, 0x26, 0xd6, 0x36, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xe9, 0x0e, 0x01, 0x33, 0x89, 0xee, - 0xa4, 0xae, 0xa7, 0xfc, 0xd4, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xe1, 0x3e, 0xf9, 0xf2, 0xe8, 0x48, - 0x05, 0x0d, 0x7d, 0xaa, 0x28, 0xc5, 0x9f, 0x31, 0x9c, 0xca, 0xea, 0x5e, 0x18, 0xf6, 0xe5, 0x4f, 0x7f, 0x0e, 0xed, - 0x48, 0xa7, 0x9d, 0x3e, 0x08, 0xe6, 0xf4, 0x96, 0x72, 0x7d, 0x50, 0xb5, 0x62, 0x05, 0xf3, 0x98, 0xa1, 0x95, 0xe3, - 0x36, 0x92, 0x92, 0x01, 0xff, 0x08, 0x64, 0xc1, 0x73, 0xd1, 0x16, 0xf1, 0xb3, 0x19, 0x03, 0x55, 0xb6, 0x67, 0x24, - 0x2a, 0xf1, 0xf0, 0xd0, 0x1d, 0x24, 0xae, 0xe1, 0xfd, 0x63, 0xdf, 0x6c, 0x57, 0x6f, 0x48, 0x03, 0x0b, 0x56, 0x4e, - 0x64, 0x39, 0xf7, 0x79, 0x9b, 0xad, 0x6f, 0x47, 0x1c, 0xf9, 0x24, 0xde, 0xdb, 0xb6, 0x13, 0x01, 0xfa, 0x5b, 0xb2, - 0x77, 0x2d, 0xb5, 0x37, 0x4e, 0xd3, 0xea, 0x00, 0xb6, 0x0a, 0x42, 0x8f, 0x99, 0x2a, 0x94, 0xf2, 0x9d, 0x7a, 0xb5, - 0x6f, 0x75, 0x27, 0x87, 0xdd, 0x7e, 0x25, 0xf9, 0x79, 0x6c, 0xe8, 0x5b, 0x1d, 0x87, 0x3b, 0x55, 0xe5, 0xb2, 0xc8, - 0xdd, 0x60, 0x05, 0xc2, 0xcc, 0xe1, 0xd1, 0x2d, 0x2f, 0x8a, 0x3a, 0xf5, 0x7f, 0x42, 0xda, 0x95, 0x23, 0xed, 0xd2, - 0x93, 0x76, 0x20, 0x15, 0x40, 0xda, 0x6d, 0x73, 0x75, 0x75, 0xb9, 0xb3, 0x3d, 0xa5, 0x25, 0xea, 0xca, 0x88, 0xd3, - 0xd0, 0xdf, 0xd2, 0x8f, 0x00, 0x55, 0xcc, 0xd7, 0xe7, 0xd8, 0xe9, 0x63, 0x40, 0x0c, 0xb4, 0x3a, 0x4d, 0x16, 0x6a, - 0x2a, 0x3e, 0xc7, 0x08, 0xab, 0x0d, 0xab, 0x30, 0xfb, 0xf1, 0x73, 0x50, 0xda, 0x05, 0xd3, 0x81, 0x73, 0xcc, 0x24, - 0xff, 0x8f, 0xf8, 0x28, 0x3f, 0x3b, 0xe1, 0x66, 0xa7, 0xfc, 0xec, 0x80, 0xd6, 0xd7, 0xb3, 0xcb, 0xbf, 0x4d, 0xed, - 0xcd, 0xf4, 0x44, 0x35, 0xbd, 0x7a, 0xbd, 0xd7, 0xeb, 0x78, 0x2b, 0x05, 0x34, 0xfa, 0x4e, 0x4a, 0x29, 0xab, 0xd6, - 0x81, 0x06, 0x84, 0x90, 0x81, 0x84, 0x8d, 0x9d, 0x74, 0x75, 0xca, 0xfd, 0xf8, 0xef, 0xf4, 0x3c, 0x46, 0x71, 0x6f, - 0xeb, 0x3f, 0x95, 0xf3, 0x05, 0x30, 0x64, 0x5b, 0x28, 0x3d, 0x65, 0xae, 0xc3, 0x3a, 0x7f, 0xb3, 0x27, 0xad, 0x51, - 0xc7, 0xec, 0xc7, 0x06, 0x36, 0x55, 0x52, 0xf3, 0x61, 0x67, 0xb3, 0xac, 0x92, 0x2a, 0xc2, 0xb1, 0x4f, 0xb7, 0xf2, - 0x74, 0x5b, 0x33, 0xe3, 0x33, 0xde, 0xc4, 0xc2, 0xd2, 0x61, 0x01, 0xb4, 0x2e, 0x20, 0x3f, 0x1e, 0xdd, 0xc3, 0xf5, - 0xdf, 0xd4, 0xc0, 0x59, 0x6d, 0xb6, 0xc0, 0xb7, 0xda, 0x6c, 0x3e, 0x6a, 0x27, 0x69, 0xe3, 0x8f, 0x7b, 0xe4, 0xde, - 0x0a, 0x7a, 0x75, 0xa6, 0x93, 0x19, 0x87, 0x23, 0x48, 0xdb, 0x61, 0x21, 0xc9, 0x6a, 0x2e, 0x73, 0x96, 0x46, 0x72, - 0xc1, 0x44, 0xb4, 0x01, 0x3d, 0xab, 0x43, 0x80, 0x7f, 0x89, 0x78, 0xf5, 0xae, 0xa9, 0x6f, 0x4d, 0x3f, 0xea, 0x0d, - 0xa8, 0xc2, 0x7e, 0xe4, 0x7b, 0x94, 0xb1, 0x1f, 0x59, 0xa9, 0x0c, 0x4f, 0x5a, 0xb1, 0xb7, 0x3f, 0xf2, 0xfa, 0x80, - 0xfa, 0x91, 0xa7, 0x5f, 0xaf, 0x52, 0x0b, 0x24, 0x51, 0x37, 0xb9, 0x48, 0x4e, 0x23, 0x64, 0x34, 0xc6, 0x2f, 0xbc, - 0xc6, 0x78, 0x59, 0x69, 0x8c, 0x5f, 0x6a, 0xb2, 0xdc, 0xd2, 0x18, 0xff, 0x20, 0xc8, 0x4b, 0x3d, 0x78, 0xe9, 0xb5, - 0xe9, 0x6f, 0x65, 0xc1, 0xb3, 0xfb, 0x38, 0x2a, 0xb8, 0x6e, 0xc3, 0x6d, 0x62, 0x84, 0x57, 0x36, 0x03, 0x54, 0x8d, - 0x46, 0xdf, 0xbd, 0xf1, 0xf2, 0x1f, 0x16, 0x82, 0x44, 0x0f, 0x0a, 0xae, 0x1f, 0x44, 0x78, 0xa6, 0xc9, 0x1f, 0xf0, - 0xeb, 0xc1, 0x2a, 0xfe, 0x89, 0xea, 0x59, 0x52, 0x52, 0x91, 0xcb, 0x79, 0x8c, 0x5a, 0x51, 0x84, 0x12, 0x65, 0x84, - 0x90, 0x47, 0x68, 0xf3, 0xe0, 0x0f, 0xfc, 0xa7, 0x24, 0xd1, 0x20, 0x6a, 0xcd, 0x34, 0x66, 0x94, 0xfc, 0x71, 0xf5, - 0x60, 0xf5, 0xa7, 0xdc, 0x5c, 0xff, 0x81, 0x9f, 0xeb, 0x4a, 0xad, 0x8f, 0xef, 0x18, 0x89, 0x11, 0xb9, 0x7e, 0xee, - 0x87, 0xf4, 0x54, 0xce, 0xad, 0x82, 0x3f, 0x42, 0xf8, 0x0b, 0xe8, 0x75, 0xaf, 0x79, 0x4d, 0x84, 0xdc, 0x1d, 0xcc, - 0x21, 0x89, 0xa4, 0x51, 0x1e, 0x44, 0x47, 0x47, 0x41, 0x5a, 0xc5, 0x42, 0xe0, 0x27, 0x92, 0x34, 0x44, 0x75, 0xcc, - 0x29, 0xb4, 0xf4, 0x44, 0xc6, 0x1c, 0xf9, 0x66, 0x62, 0xaf, 0xa9, 0x76, 0x3b, 0x96, 0x0f, 0xad, 0xee, 0x21, 0xe1, - 0x9a, 0x95, 0x54, 0xcb, 0x72, 0x84, 0x42, 0xb6, 0x04, 0xbf, 0xe6, 0xe4, 0x8f, 0xe1, 0xc1, 0xff, 0xf1, 0x7f, 0xfe, - 0x3e, 0xf9, 0xbd, 0x1c, 0xfd, 0x81, 0x05, 0x23, 0x27, 0x57, 0xf1, 0x20, 0x8d, 0x0f, 0xdb, 0xed, 0xf5, 0xef, 0x27, - 0xc3, 0xff, 0xa6, 0xed, 0xbf, 0x1f, 0xb7, 0x7f, 0x1b, 0xa1, 0x75, 0xfc, 0xfb, 0xc9, 0x60, 0xe8, 0xbe, 0x86, 0xff, - 0x7d, 0xfd, 0xbb, 0x1a, 0x1d, 0xdb, 0xc4, 0x07, 0x08, 0x9d, 0x4c, 0xf1, 0x3f, 0x05, 0x39, 0x69, 0xb7, 0xaf, 0x4f, - 0xa6, 0xf8, 0x67, 0x41, 0x4e, 0xe0, 0xef, 0xbd, 0x26, 0xef, 0xd8, 0xf4, 0xf9, 0xdd, 0x22, 0xfe, 0xe3, 0x7a, 0xfd, - 0x60, 0xf5, 0x9a, 0x6f, 0xa0, 0xdd, 0xe1, 0x7f, 0xff, 0xfe, 0xbb, 0x8a, 0xfe, 0x71, 0x4d, 0x4e, 0x46, 0x2d, 0x14, - 0x9b, 0xe4, 0x63, 0x62, 0xff, 0xc4, 0x83, 0x74, 0xf8, 0xdf, 0x6e, 0x28, 0xd1, 0x3f, 0x7e, 0xff, 0xe3, 0xea, 0x9a, - 0x8c, 0xd6, 0x71, 0xb4, 0xfe, 0x07, 0x5a, 0x23, 0xb4, 0x7e, 0x80, 0xfe, 0xc0, 0xd1, 0x34, 0x42, 0xf8, 0x37, 0x41, - 0x4e, 0xfe, 0x71, 0x32, 0xc5, 0xdf, 0x0b, 0x72, 0x12, 0x9d, 0x4c, 0xf1, 0x47, 0x49, 0x4e, 0xfe, 0x3b, 0x1e, 0xa4, - 0x56, 0x09, 0xb7, 0x36, 0xea, 0x8f, 0x35, 0xdc, 0x84, 0xd0, 0x92, 0xd1, 0xb5, 0xe6, 0xba, 0x60, 0xe8, 0xc1, 0x09, - 0xc7, 0x2f, 0x25, 0x00, 0x2b, 0xd6, 0xa0, 0xa4, 0x31, 0x97, 0xb0, 0xab, 0x4f, 0xb0, 0xf0, 0x80, 0x41, 0x0f, 0x52, - 0x8e, 0xad, 0x9e, 0x40, 0xa5, 0xda, 0xde, 0xde, 0x2a, 0xb8, 0xbe, 0xc5, 0x37, 0xe4, 0xa5, 0x8c, 0xbb, 0x08, 0x0b, - 0x0a, 0x3f, 0x7a, 0x08, 0x7f, 0xd0, 0xee, 0xc2, 0x13, 0xb6, 0xb9, 0xc5, 0x30, 0x21, 0x2d, 0x3f, 0x13, 0x21, 0xfc, - 0x7c, 0x4f, 0xa6, 0x9e, 0x81, 0xfa, 0x01, 0x61, 0xad, 0xc2, 0xeb, 0x51, 0xfc, 0x54, 0x93, 0x0a, 0x39, 0xde, 0x97, - 0x8c, 0xfd, 0x42, 0x8b, 0xcf, 0xac, 0x8c, 0x9f, 0x6b, 0xdc, 0xed, 0x3d, 0xc2, 0x46, 0x55, 0x7d, 0xd8, 0x45, 0xfd, - 0xea, 0x76, 0xeb, 0x83, 0xb4, 0xf7, 0x09, 0x70, 0x0a, 0x37, 0xf5, 0x35, 0xb0, 0xf6, 0x87, 0x7c, 0x47, 0xa9, 0x55, - 0xd2, 0xdb, 0x08, 0x35, 0xaf, 0x52, 0xb9, 0xf8, 0x42, 0x0b, 0x9e, 0x1f, 0x68, 0x36, 0x5f, 0x14, 0x54, 0xb3, 0x03, - 0x37, 0xe7, 0x03, 0x0a, 0x0d, 0x45, 0x15, 0x4f, 0xf1, 0x83, 0xa8, 0x37, 0xed, 0x0f, 0x22, 0xa9, 0xf7, 0x4e, 0x0c, - 0xf7, 0x59, 0x8e, 0x2f, 0x51, 0xb4, 0xba, 0x2e, 0xdb, 0xbe, 0x11, 0x6c, 0x77, 0x41, 0x59, 0x36, 0x32, 0xe7, 0xb7, - 0xc2, 0x70, 0xbf, 0x49, 0x48, 0x6f, 0x10, 0x5d, 0xa9, 0x2f, 0xd3, 0xeb, 0x08, 0x6e, 0x72, 0x4a, 0x22, 0x98, 0x51, - 0x1e, 0x41, 0x09, 0x4a, 0x3a, 0x7d, 0x7a, 0xc5, 0xfa, 0xb4, 0xd5, 0xf2, 0x6c, 0x76, 0x46, 0xf8, 0x90, 0xda, 0xfa, - 0x05, 0x9e, 0xe1, 0x9c, 0xb4, 0xbb, 0x78, 0x49, 0x3a, 0xa6, 0x4a, 0x7f, 0x79, 0x95, 0xb9, 0x7e, 0x8e, 0x8e, 0xe2, - 0x32, 0x29, 0xa8, 0xd2, 0xaf, 0x40, 0x23, 0x40, 0x96, 0x78, 0x46, 0xca, 0x84, 0xdd, 0xb1, 0x2c, 0xce, 0x10, 0x9e, - 0x39, 0x1a, 0x84, 0xfa, 0x68, 0x49, 0x82, 0x62, 0x20, 0x67, 0x10, 0xc1, 0x06, 0xb3, 0x61, 0x77, 0x44, 0x08, 0x89, - 0x0e, 0xdb, 0xed, 0x68, 0x50, 0x92, 0x7f, 0x8a, 0x14, 0x52, 0x02, 0x76, 0x9a, 0xfc, 0x0c, 0x49, 0xbd, 0x20, 0x29, - 0xfe, 0x28, 0x13, 0xcd, 0x94, 0x8e, 0x21, 0x19, 0x94, 0x04, 0xca, 0x63, 0x78, 0x74, 0x75, 0x12, 0xb5, 0x20, 0xd5, - 0xa0, 0x28, 0xc2, 0x25, 0xb9, 0xd7, 0x28, 0x9d, 0x0d, 0x4f, 0x47, 0xe1, 0x19, 0x61, 0x53, 0xa1, 0xff, 0x7b, 0x3d, - 0x98, 0x0d, 0x3b, 0xa6, 0xff, 0xeb, 0x68, 0x10, 0x97, 0x44, 0x59, 0x36, 0x6e, 0xa0, 0x52, 0xc1, 0xcc, 0x7c, 0x51, - 0xea, 0x06, 0xe8, 0xfa, 0xce, 0x49, 0xbb, 0x97, 0xc6, 0x79, 0x38, 0x93, 0x36, 0x74, 0xe8, 0x40, 0x81, 0x0b, 0x02, - 0xe5, 0x71, 0x49, 0xa0, 0xd3, 0xba, 0xda, 0xbd, 0x4e, 0x5d, 0xc2, 0x3f, 0xa2, 0x7f, 0x0c, 0xbe, 0x17, 0xe9, 0x6f, - 0xc2, 0x8e, 0xe0, 0x7b, 0xb1, 0x5e, 0xc3, 0xdf, 0xdf, 0xc4, 0x00, 0x86, 0x65, 0xd2, 0xfe, 0xe9, 0xd2, 0x7e, 0x86, - 0x34, 0xc1, 0x52, 0x33, 0x60, 0xac, 0x2a, 0x7e, 0xcc, 0x2e, 0xce, 0x84, 0xd8, 0x19, 0x1c, 0x1d, 0xf1, 0x21, 0x6d, - 0x75, 0x47, 0x70, 0x23, 0x50, 0x6a, 0xf5, 0x0b, 0xd7, 0xb3, 0x38, 0x3a, 0xb9, 0x8e, 0xd0, 0x20, 0x3a, 0x80, 0x55, - 0xee, 0xcb, 0x16, 0x71, 0xb0, 0xce, 0x5a, 0x8c, 0xa6, 0xf9, 0x35, 0xe9, 0x0c, 0x62, 0x61, 0x89, 0x7c, 0x81, 0x70, - 0xe6, 0x68, 0x6a, 0x07, 0xe7, 0xa8, 0x25, 0x44, 0xcb, 0x7f, 0xe7, 0xa8, 0x35, 0xd3, 0xad, 0x09, 0x4a, 0x33, 0xf8, - 0x1b, 0xe7, 0x84, 0x90, 0x76, 0xaf, 0xaa, 0xe8, 0x0f, 0x4b, 0x8a, 0xd2, 0x89, 0x57, 0x8f, 0x0e, 0xcd, 0xe6, 0x90, - 0xad, 0x98, 0x0f, 0xd9, 0x68, 0xbd, 0x8e, 0xae, 0x06, 0xd7, 0x11, 0x6a, 0xc5, 0x1e, 0xed, 0x4e, 0x3c, 0xde, 0x21, - 0x84, 0xc5, 0x68, 0xe3, 0x6e, 0xa0, 0x6e, 0x59, 0xe3, 0xb6, 0x69, 0x55, 0xef, 0xff, 0x80, 0x2c, 0xb0, 0x4d, 0x25, - 0xf7, 0x58, 0xfe, 0x76, 0x01, 0x53, 0xf5, 0xb8, 0x2d, 0x49, 0x07, 0x97, 0xc4, 0xab, 0xbb, 0x29, 0xd1, 0x35, 0xfe, - 0x67, 0xa4, 0x2e, 0x8e, 0x87, 0x05, 0x9e, 0x8d, 0x88, 0xa2, 0x46, 0x7e, 0xe9, 0x7b, 0x65, 0x3a, 0x2b, 0xc8, 0x2d, - 0xdb, 0xba, 0xff, 0x2d, 0xe0, 0x4e, 0xe6, 0xa9, 0x4e, 0xb2, 0x65, 0x59, 0x32, 0xa1, 0x5f, 0xcb, 0xdc, 0x31, 0x76, - 0xac, 0x00, 0xd9, 0x0a, 0x2e, 0x76, 0x31, 0x70, 0x75, 0x3d, 0xbf, 0x53, 0xf2, 0x9d, 0xec, 0x25, 0xc9, 0x2d, 0xc3, - 0x65, 0xae, 0x7b, 0xfb, 0x4b, 0x27, 0x4a, 0xc7, 0x08, 0xe7, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x99, 0x64, 0x90, - 0x0d, 0x1d, 0x28, 0xb4, 0x31, 0xfb, 0x2a, 0x56, 0xe4, 0xa9, 0x4e, 0x04, 0xbb, 0x33, 0xdd, 0xc6, 0xa8, 0x3e, 0xc4, - 0xfd, 0x7e, 0xbb, 0xa2, 0x7d, 0x43, 0x80, 0x54, 0x22, 0x64, 0xce, 0x00, 0x42, 0x70, 0xf7, 0xef, 0x92, 0x66, 0x54, - 0x85, 0x37, 0x5b, 0xf5, 0x00, 0x87, 0xa1, 0xca, 0x7b, 0x09, 0x7a, 0x62, 0xc3, 0x9e, 0x55, 0x85, 0xad, 0xf2, 0x1c, - 0x21, 0x3e, 0x89, 0x97, 0x09, 0xdc, 0x08, 0x1a, 0x4c, 0x12, 0x02, 0xad, 0xd7, 0xcb, 0x10, 0xb7, 0x66, 0xb5, 0x62, - 0x7a, 0x42, 0x66, 0xc3, 0xb2, 0xd5, 0x32, 0xca, 0xeb, 0xdc, 0xe2, 0xc5, 0x12, 0xe1, 0x49, 0xb5, 0xd7, 0x7c, 0xb9, - 0x05, 0x69, 0x76, 0x15, 0x4f, 0x9a, 0x4a, 0xe0, 0x96, 0x10, 0xc8, 0xe8, 0x17, 0x35, 0xb4, 0x8e, 0xa7, 0xe4, 0x24, - 0x1e, 0x26, 0x83, 0xff, 0x6b, 0x84, 0x06, 0x71, 0x72, 0x8c, 0x4e, 0x2c, 0x2d, 0x99, 0xa0, 0x7e, 0x66, 0xfb, 0x58, - 0x99, 0xdb, 0xcf, 0x2e, 0x36, 0x0a, 0xc8, 0x54, 0x62, 0x41, 0xe7, 0x2c, 0x9d, 0xc2, 0xae, 0xf7, 0xc8, 0xb3, 0xc0, - 0x80, 0x4c, 0xe9, 0xd4, 0xd1, 0x96, 0x24, 0x1a, 0x94, 0xb4, 0xfa, 0x1a, 0x44, 0x83, 0xac, 0xfe, 0xfa, 0xbf, 0xa2, - 0x41, 0x41, 0xd3, 0xa7, 0x7c, 0xe3, 0x94, 0xe4, 0x8d, 0x3e, 0x2e, 0x7c, 0x1f, 0x1b, 0xbb, 0x38, 0x01, 0xf0, 0x72, - 0xb4, 0xab, 0x1d, 0x59, 0xa2, 0x0d, 0x9f, 0x54, 0xd4, 0x49, 0x25, 0x9a, 0x4e, 0x01, 0xaa, 0xc1, 0x22, 0xa8, 0xd0, - 0x36, 0x20, 0x98, 0x32, 0x60, 0x8b, 0x47, 0x5a, 0x80, 0xe6, 0xf2, 0xba, 0x83, 0x56, 0x8d, 0xc2, 0x8e, 0xb3, 0x6a, - 0xde, 0xc5, 0x57, 0xc4, 0x7b, 0x02, 0x54, 0xf9, 0x6a, 0xd9, 0x9f, 0xb4, 0x5a, 0x48, 0x79, 0xfc, 0xca, 0x87, 0x93, - 0x11, 0xbe, 0x03, 0x14, 0xc2, 0x0d, 0x8c, 0xc2, 0x8d, 0x39, 0xf6, 0xdc, 0x1c, 0x5b, 0x2d, 0xb9, 0x41, 0xfd, 0xa0, - 0xf2, 0xd2, 0x55, 0xde, 0x6c, 0x2c, 0x64, 0xb6, 0x31, 0xee, 0x12, 0x99, 0x14, 0x30, 0x04, 0x23, 0x84, 0xfc, 0x29, - 0xd1, 0xde, 0x66, 0xa1, 0x51, 0xa8, 0x6e, 0x76, 0x2f, 0x50, 0x54, 0x7b, 0x7a, 0xc4, 0x00, 0x0b, 0xa8, 0x5a, 0xa9, - 0x91, 0x67, 0x1a, 0xe7, 0xad, 0xae, 0x41, 0xf7, 0x76, 0xb7, 0xdf, 0x6c, 0xec, 0x61, 0xdd, 0x18, 0xce, 0x5b, 0x64, - 0x56, 0xef, 0xf0, 0x8d, 0x6c, 0xb5, 0x36, 0xcd, 0xfb, 0x52, 0xbf, 0x89, 0x1b, 0xf7, 0x17, 0xcf, 0x77, 0x4c, 0x3c, - 0xfc, 0xe9, 0x5b, 0x9f, 0xb7, 0x22, 0xe1, 0x42, 0xb0, 0x12, 0x4e, 0x58, 0xa2, 0xb1, 0xd8, 0x6c, 0xaa, 0x53, 0xff, - 0x17, 0x6d, 0x6d, 0xc6, 0x08, 0x07, 0x3a, 0x64, 0xa4, 0x36, 0x2c, 0x71, 0x89, 0xa9, 0xa1, 0x22, 0x84, 0x90, 0x0f, - 0xda, 0x9b, 0xc7, 0x68, 0x43, 0x92, 0x32, 0x12, 0x9c, 0xdd, 0xb1, 0x22, 0x2c, 0xf9, 0xf4, 0xe0, 0xa9, 0xfc, 0xa6, - 0x48, 0x37, 0x14, 0xa3, 0xd4, 0x14, 0x2b, 0x1c, 0x21, 0x2b, 0xc8, 0x17, 0x90, 0x73, 0xaa, 0x0b, 0x96, 0xc4, 0x10, - 0xc4, 0x67, 0xbc, 0x64, 0x86, 0x71, 0x7f, 0xe0, 0xe5, 0xc6, 0xac, 0xc9, 0x69, 0x66, 0xa1, 0xf6, 0x07, 0xa0, 0x59, - 0x80, 0x72, 0x48, 0x92, 0x9d, 0x62, 0x9f, 0x1e, 0x3c, 0x7e, 0xb3, 0x4f, 0x86, 0x5e, 0xaf, 0x9d, 0xf4, 0x9c, 0x01, - 0xeb, 0x83, 0x8b, 0x7a, 0xa8, 0x99, 0xfb, 0x91, 0xc6, 0x99, 0x61, 0xa2, 0x8a, 0x98, 0x03, 0x32, 0x7d, 0x7a, 0xf0, - 0xf8, 0x7d, 0xcc, 0x8d, 0x6e, 0x0a, 0xe1, 0x70, 0xde, 0x71, 0x49, 0x62, 0x4a, 0x18, 0xb2, 0x93, 0xaf, 0xe8, 0x58, - 0x19, 0x9c, 0xee, 0x29, 0x35, 0x99, 0x20, 0x76, 0x0c, 0xc5, 0x88, 0x64, 0x0e, 0x04, 0x24, 0x43, 0x38, 0x6b, 0xc8, - 0x75, 0xc4, 0xac, 0x81, 0xe9, 0xec, 0x06, 0x16, 0x23, 0xb1, 0xec, 0x21, 0xc2, 0x99, 0xe9, 0x56, 0x6f, 0xec, 0x71, - 0x22, 0xe9, 0xb6, 0xa1, 0x5b, 0x2d, 0xcf, 0x7e, 0x04, 0xc1, 0xcb, 0x7f, 0xbc, 0x76, 0x6d, 0x57, 0x09, 0xcf, 0xbc, - 0x45, 0xda, 0xa7, 0x07, 0x8f, 0x7f, 0x72, 0x46, 0x69, 0x0b, 0xea, 0xc9, 0xff, 0x8e, 0x8c, 0xfa, 0xf8, 0xa7, 0xa4, - 0xce, 0x35, 0x85, 0x3f, 0x3d, 0x78, 0xfc, 0x61, 0x5f, 0x31, 0x48, 0xdf, 0x2c, 0x6b, 0x25, 0x81, 0x19, 0xdf, 0x8a, - 0x15, 0xe9, 0xca, 0x9d, 0x15, 0xa9, 0xd8, 0x60, 0x73, 0x42, 0xa5, 0x6a, 0x53, 0xe9, 0x56, 0x9e, 0x61, 0x49, 0xcc, - 0x55, 0x52, 0x73, 0xd9, 0x1c, 0x1a, 0x73, 0x29, 0x6e, 0x32, 0xb9, 0x60, 0x5f, 0xb9, 0x5f, 0x7a, 0xae, 0x51, 0xc2, - 0xe7, 0x60, 0x88, 0x63, 0xc6, 0x2e, 0xf0, 0x61, 0x07, 0xf5, 0xb7, 0xce, 0x33, 0x69, 0x10, 0xb5, 0x6c, 0x1e, 0x36, - 0x98, 0x92, 0x0e, 0xce, 0x48, 0x07, 0x17, 0x44, 0x0d, 0x3b, 0xf6, 0xc4, 0xe8, 0x17, 0x55, 0xd3, 0xf6, 0xdc, 0x81, - 0xed, 0x5e, 0xd8, 0x7d, 0x6b, 0x0f, 0xe5, 0x59, 0xbf, 0x30, 0xfa, 0x4b, 0x73, 0xd0, 0xcf, 0x0c, 0x6a, 0xbc, 0x62, - 0x71, 0x89, 0x4b, 0xd3, 0xf2, 0x0d, 0x1f, 0x17, 0x60, 0xa7, 0x02, 0x33, 0xc3, 0x1a, 0xa5, 0x55, 0xd9, 0xae, 0x2b, - 0x5b, 0x24, 0x66, 0xad, 0x4a, 0x5c, 0x24, 0x40, 0xca, 0x71, 0xe1, 0xec, 0x7a, 0xd4, 0x6e, 0x95, 0x8b, 0xa3, 0xa3, - 0xd8, 0x56, 0x9a, 0xd1, 0xb8, 0xf4, 0xf9, 0xf5, 0x0d, 0xe0, 0x47, 0x4b, 0x35, 0x66, 0xc8, 0x4c, 0xa0, 0xd5, 0xca, - 0x46, 0x1b, 0x7a, 0x48, 0x48, 0x5c, 0x34, 0xa1, 0xe8, 0x47, 0x6f, 0x98, 0xc1, 0x2d, 0x00, 0xb4, 0x5a, 0xd5, 0x75, - 0xef, 0x16, 0xc4, 0x9e, 0x6b, 0x2c, 0x37, 0x5f, 0xe2, 0xca, 0x9a, 0xa8, 0xb3, 0x63, 0x87, 0xe5, 0x47, 0x81, 0x44, - 0x88, 0xbb, 0xc2, 0xcf, 0x27, 0xd8, 0x1a, 0x02, 0xca, 0xbd, 0x72, 0x36, 0x10, 0xd8, 0x58, 0x6d, 0xb9, 0x42, 0x9e, - 0xb4, 0xf5, 0x50, 0xea, 0x0b, 0xc1, 0x05, 0x17, 0x14, 0x6a, 0x6d, 0x1c, 0x96, 0xbf, 0x62, 0xbb, 0xe6, 0x9c, 0x58, - 0x21, 0xa7, 0x2d, 0x33, 0xc3, 0x30, 0x00, 0xeb, 0x55, 0x80, 0x79, 0x49, 0x9e, 0x7f, 0x1d, 0xf5, 0x1f, 0x07, 0xa8, - 0xff, 0x84, 0xb0, 0x60, 0x1b, 0x58, 0x5d, 0x49, 0x22, 0x9d, 0x82, 0x42, 0xf9, 0xac, 0xa7, 0x0b, 0x02, 0xda, 0xb8, - 0x26, 0x54, 0x1b, 0x57, 0x94, 0x5f, 0xa1, 0x2c, 0xe1, 0x4e, 0x31, 0xfa, 0x4c, 0xec, 0xef, 0x93, 0xe3, 0xfa, 0x82, - 0x0e, 0xba, 0xde, 0xa7, 0x1c, 0x0c, 0x49, 0xe1, 0xe3, 0x0f, 0xdf, 0xbe, 0x5b, 0x7d, 0xba, 0xd8, 0xdd, 0xc1, 0x81, - 0x59, 0x29, 0xcc, 0x3a, 0xd8, 0xc0, 0x4d, 0x23, 0x53, 0xe8, 0xbf, 0xba, 0x13, 0x6f, 0x52, 0xa1, 0xad, 0xcd, 0xe8, - 0x8f, 0x43, 0x18, 0x6d, 0xb7, 0x6b, 0x4a, 0xb0, 0xa0, 0x59, 0xa0, 0x4b, 0xd6, 0xb8, 0x95, 0x96, 0x5f, 0x21, 0x23, - 0x8f, 0x4d, 0x01, 0x26, 0xf2, 0xfd, 0xd9, 0x4f, 0x36, 0x0e, 0x4f, 0xec, 0xd0, 0xd0, 0xca, 0x10, 0x42, 0x8b, 0xf7, - 0x80, 0x39, 0xf6, 0x88, 0x00, 0x10, 0x3d, 0x37, 0x90, 0xaa, 0x41, 0x16, 0x45, 0xb5, 0x22, 0xff, 0xe5, 0x21, 0x21, - 0xcf, 0x6b, 0x45, 0xe6, 0xbb, 0xda, 0x98, 0x0b, 0x10, 0x03, 0xa5, 0x70, 0x91, 0x50, 0x25, 0xd8, 0xcb, 0xd0, 0x0f, - 0xda, 0x97, 0x37, 0xd2, 0x66, 0x52, 0x73, 0xe3, 0xc1, 0x4d, 0xa9, 0x51, 0xf1, 0xd9, 0x7c, 0x0f, 0x89, 0xad, 0xdc, - 0x07, 0x90, 0xcb, 0xa9, 0x19, 0x24, 0x7c, 0xbf, 0x37, 0xa5, 0x7d, 0xbb, 0x9b, 0xcf, 0xdb, 0x16, 0x31, 0x5b, 0xeb, - 0x92, 0x70, 0xa1, 0x58, 0xa9, 0x9f, 0xb0, 0x89, 0x2c, 0xe1, 0xfe, 0xa3, 0x02, 0x0b, 0xda, 0x3c, 0x08, 0x74, 0x80, - 0x66, 0x82, 0xc1, 0xa5, 0xc3, 0xd6, 0x0c, 0xcd, 0xaf, 0xcf, 0xe6, 0x0e, 0xfc, 0xd3, 0x76, 0xad, 0xe7, 0x47, 0x47, - 0x5f, 0x58, 0x0d, 0x28, 0x37, 0x4c, 0x33, 0x8c, 0x80, 0x78, 0x59, 0x2e, 0xc7, 0xdd, 0x0c, 0x3f, 0x88, 0x6b, 0x95, - 0x81, 0x27, 0x1c, 0x21, 0x11, 0x7a, 0x49, 0xf4, 0x66, 0xba, 0x4d, 0xef, 0x9d, 0x36, 0x43, 0x84, 0x62, 0x0d, 0x90, - 0x7b, 0x90, 0xcb, 0xad, 0x92, 0x49, 0xd5, 0xb6, 0xb6, 0xd5, 0x20, 0x9e, 0x02, 0xb8, 0x62, 0x23, 0xa4, 0x04, 0x68, - 0xb8, 0x5f, 0x68, 0xf9, 0x20, 0x81, 0xfd, 0xc7, 0x2a, 0x01, 0x91, 0x16, 0x35, 0x36, 0x2e, 0x42, 0xd8, 0x9a, 0xfa, - 0x04, 0xc6, 0x09, 0x8f, 0x5f, 0xee, 0xd3, 0x50, 0x7b, 0xd4, 0x66, 0xe6, 0x0c, 0x82, 0x12, 0x12, 0x55, 0x15, 0x92, - 0x2f, 0xb1, 0x70, 0xdc, 0x9c, 0xbf, 0x87, 0x03, 0x52, 0x2c, 0x69, 0x6c, 0xef, 0xb6, 0xe0, 0xf8, 0x28, 0x93, 0x65, - 0xdc, 0xe8, 0xba, 0x5f, 0x9a, 0x6a, 0xd8, 0x81, 0x8e, 0x86, 0x70, 0x2a, 0xcd, 0x3d, 0xe1, 0xd3, 0x9a, 0xa4, 0x6a, - 0x67, 0x01, 0xe5, 0x89, 0x61, 0x6d, 0x9a, 0x12, 0xcc, 0x5f, 0x3b, 0xf3, 0xb5, 0xea, 0x98, 0x60, 0x66, 0x18, 0xb7, - 0x76, 0x15, 0xd8, 0x06, 0x70, 0x6c, 0xf5, 0x44, 0x06, 0x8b, 0xea, 0x95, 0xe2, 0xa6, 0xd3, 0x80, 0x09, 0x78, 0x07, - 0xd6, 0x33, 0xdb, 0x5b, 0xff, 0xa5, 0x39, 0x18, 0x05, 0x56, 0x0d, 0x02, 0x2f, 0x0d, 0x81, 0x47, 0xc0, 0xb8, 0x79, - 0xd3, 0xf2, 0x81, 0x33, 0xa2, 0x11, 0xfe, 0xc4, 0x73, 0x78, 0x66, 0x59, 0xee, 0x9d, 0x8f, 0xad, 0x15, 0x49, 0x05, - 0x01, 0xdb, 0x22, 0xec, 0x88, 0xbc, 0x44, 0x58, 0xb5, 0x5a, 0x7d, 0x75, 0xc5, 0x6a, 0xad, 0x4a, 0x3d, 0x4c, 0x01, - 0xb7, 0xc4, 0x80, 0xf7, 0x8d, 0x13, 0x15, 0x0c, 0x09, 0xbc, 0xf5, 0xb7, 0x02, 0xf5, 0xfd, 0xe3, 0x77, 0x71, 0x48, - 0xdf, 0xc2, 0xb2, 0xd5, 0x45, 0x2c, 0x4c, 0x29, 0xae, 0xef, 0x70, 0xde, 0x7e, 0xdb, 0x6c, 0x04, 0xc6, 0x7d, 0xd8, - 0xc5, 0x60, 0xe3, 0x86, 0xfa, 0xda, 0x92, 0x86, 0x6a, 0x13, 0xf6, 0x51, 0x6d, 0xef, 0x18, 0x76, 0xd6, 0xd7, 0xb5, - 0xb4, 0xab, 0x89, 0xda, 0x6c, 0x14, 0xab, 0x8d, 0x06, 0xb6, 0x0c, 0x3b, 0xcd, 0x31, 0xb3, 0xab, 0xc0, 0x7f, 0xba, - 0x20, 0x1a, 0x07, 0xc8, 0xfa, 0xf6, 0x6b, 0xd7, 0x29, 0xf5, 0x30, 0x61, 0x7b, 0xbb, 0xf3, 0xf1, 0x29, 0xdf, 0x77, - 0x3e, 0x62, 0xe9, 0xb6, 0xbe, 0x39, 0x1b, 0xbb, 0xff, 0xc1, 0xd9, 0xe8, 0xd4, 0xf6, 0xfe, 0x78, 0x04, 0xee, 0xa4, - 0x71, 0x3c, 0x36, 0xd7, 0x94, 0x48, 0x2c, 0xdc, 0x72, 0x5c, 0xf7, 0xd6, 0x6b, 0x31, 0xec, 0x80, 0xda, 0x29, 0x8a, - 0xe0, 0x67, 0xd7, 0xfe, 0x0c, 0x48, 0xb2, 0xd5, 0x21, 0xc7, 0xa2, 0x12, 0x65, 0x50, 0x02, 0x06, 0xd4, 0xb1, 0xb1, - 0xf5, 0x32, 0x88, 0xed, 0x70, 0xc8, 0x61, 0x39, 0x11, 0xd5, 0xd5, 0x15, 0x8c, 0xd8, 0x1c, 0x1b, 0x4e, 0xc0, 0x8c, - 0xf7, 0x5a, 0x15, 0x7a, 0xf1, 0xf3, 0xdf, 0x33, 0xa7, 0x8d, 0x23, 0xc6, 0x72, 0x12, 0x0d, 0x2b, 0x06, 0x37, 0x02, - 0xc7, 0x30, 0x1e, 0x1a, 0x09, 0xb5, 0x3e, 0xd5, 0x51, 0xe3, 0x48, 0xc2, 0x1d, 0x50, 0xbb, 0x1d, 0x9a, 0x73, 0x69, - 0xbd, 0xde, 0x7b, 0xb0, 0xe0, 0x32, 0xc0, 0xed, 0x97, 0x44, 0x37, 0x48, 0x0a, 0x25, 0x4e, 0x82, 0xc2, 0x85, 0x41, - 0x55, 0x4d, 0xe4, 0xb0, 0x33, 0x02, 0x9e, 0xb4, 0x9f, 0x5d, 0xc9, 0x5a, 0x48, 0xce, 0x5a, 0x2d, 0x54, 0x54, 0x1d, - 0xd3, 0xa1, 0x68, 0x65, 0x23, 0xcc, 0x70, 0x66, 0x05, 0x16, 0x38, 0xbd, 0xe2, 0xa2, 0xee, 0x7a, 0x98, 0x8d, 0x10, - 0x2e, 0xd7, 0xeb, 0xd8, 0x0e, 0xad, 0x40, 0xeb, 0x75, 0x11, 0x0e, 0xcd, 0xe4, 0x43, 0xc5, 0xe7, 0x03, 0x4d, 0x9e, - 0x9b, 0xf3, 0xf0, 0x39, 0x0c, 0xb2, 0x45, 0xe2, 0xc2, 0xa9, 0x04, 0x0b, 0xd0, 0x5c, 0xb5, 0xe4, 0x30, 0x6b, 0x75, - 0x47, 0x01, 0x0d, 0x1b, 0x66, 0x23, 0x52, 0x6c, 0xc0, 0x72, 0x56, 0xb9, 0x03, 0xf3, 0x4f, 0x38, 0xd8, 0xfe, 0x34, - 0xe7, 0x8c, 0x6d, 0x30, 0x5c, 0x93, 0x6d, 0x95, 0x41, 0x85, 0x57, 0x6e, 0x71, 0x7d, 0xb9, 0x86, 0x81, 0x45, 0x55, - 0x08, 0xbb, 0x6b, 0xe6, 0x01, 0x08, 0xff, 0x15, 0xb6, 0x97, 0xb4, 0x32, 0xe2, 0xde, 0x42, 0x7c, 0x6f, 0xbb, 0x9d, - 0x24, 0x09, 0x2d, 0xa7, 0xe6, 0x4a, 0xc4, 0xdf, 0xf0, 0x9a, 0x3d, 0x70, 0xea, 0xc6, 0x19, 0xf4, 0x3c, 0xac, 0x3a, - 0x1b, 0x11, 0x3b, 0x7e, 0xcf, 0xec, 0x78, 0xc7, 0x15, 0x4a, 0xf7, 0xeb, 0x22, 0xec, 0x60, 0xb2, 0xff, 0xe5, 0xc1, - 0x9c, 0xb9, 0xc1, 0x58, 0x34, 0xd9, 0x82, 0xdb, 0x57, 0xe0, 0x41, 0xe9, 0x16, 0xdc, 0xbe, 0x0e, 0x5f, 0x0f, 0xad, - 0xe2, 0xab, 0x03, 0x0c, 0xc8, 0x84, 0x1d, 0x69, 0x9d, 0x10, 0x0c, 0xf3, 0x7c, 0x9b, 0x23, 0xb3, 0x64, 0x15, 0x0e, - 0x57, 0x4d, 0x62, 0xb1, 0xb5, 0x17, 0x6a, 0x26, 0x35, 0x10, 0x8c, 0x45, 0xfa, 0x1c, 0x85, 0x4a, 0x83, 0xa6, 0x71, - 0x0c, 0x60, 0x95, 0xd3, 0xd6, 0x3f, 0x3f, 0x3a, 0x02, 0xa1, 0x01, 0x58, 0xbb, 0x24, 0xa3, 0x0b, 0xbd, 0x2c, 0x81, - 0xbf, 0x52, 0xfe, 0x37, 0x24, 0x83, 0xdb, 0x89, 0x49, 0x83, 0x1f, 0x90, 0xb0, 0xa0, 0x4a, 0xf1, 0x2f, 0x36, 0xcd, - 0xfd, 0xc6, 0x25, 0xf1, 0x18, 0xad, 0x2c, 0xa7, 0x28, 0x51, 0x5f, 0x3a, 0x74, 0x6d, 0x42, 0xee, 0xf9, 0x17, 0x26, - 0xf4, 0x8f, 0x5c, 0x69, 0x26, 0x00, 0x00, 0x35, 0xe2, 0xc1, 0x94, 0x14, 0x82, 0xad, 0xdb, 0xa8, 0x45, 0xf3, 0xfc, - 0x9b, 0x55, 0x74, 0x93, 0x2d, 0x9a, 0x51, 0x91, 0x17, 0xb6, 0x93, 0xd0, 0x66, 0xd2, 0xdb, 0x89, 0x56, 0x25, 0x43, - 0x8b, 0x9d, 0x9a, 0xfd, 0x30, 0xb4, 0x3e, 0x16, 0xc4, 0x9f, 0x0b, 0xfe, 0x2c, 0xfd, 0x26, 0x1f, 0x03, 0x57, 0xea, - 0x5f, 0x59, 0x85, 0x70, 0x26, 0x58, 0x07, 0xe4, 0x35, 0x69, 0x8e, 0xd3, 0xa3, 0xce, 0x6c, 0x47, 0xb9, 0x50, 0x19, - 0x85, 0x6d, 0x9d, 0x14, 0x06, 0x53, 0x2e, 0xbe, 0x2e, 0x71, 0xfd, 0xe4, 0x8f, 0x11, 0x7f, 0x74, 0x88, 0xff, 0x94, - 0x4a, 0xa3, 0x55, 0x85, 0x60, 0xc8, 0xef, 0x48, 0xa6, 0xe0, 0x2a, 0xb6, 0xe0, 0xfa, 0xa5, 0x9e, 0x17, 0x5b, 0x9e, - 0x38, 0x7d, 0xa6, 0x2a, 0xe8, 0xa8, 0xf8, 0x96, 0xe1, 0x57, 0x0c, 0xee, 0x8d, 0x5f, 0xf0, 0xa0, 0xca, 0xee, 0x7d, - 0xf1, 0x8b, 0xe0, 0xbe, 0xf8, 0x05, 0x4f, 0x77, 0x8b, 0x06, 0xf7, 0xc4, 0xbd, 0xe4, 0x32, 0xe9, 0x44, 0x9e, 0x8f, - 0xca, 0x69, 0xed, 0x5f, 0x69, 0xb7, 0x06, 0xae, 0x6d, 0xe2, 0xc0, 0x38, 0xaf, 0x29, 0x42, 0x31, 0x67, 0xce, 0x68, - 0x39, 0xfc, 0xaf, 0xad, 0x93, 0x3b, 0x79, 0xa4, 0x95, 0x42, 0xde, 0xd2, 0x52, 0x3f, 0x80, 0x0d, 0x57, 0xee, 0xf8, - 0x00, 0x52, 0x02, 0xca, 0xb6, 0xff, 0xac, 0x8b, 0x40, 0x1c, 0x57, 0xd6, 0xf9, 0x28, 0x6c, 0x9f, 0x94, 0x15, 0x57, - 0xd7, 0x14, 0x42, 0xee, 0x8c, 0x96, 0x00, 0x61, 0xea, 0x5d, 0xf3, 0x98, 0xa3, 0xc9, 0x2c, 0x5d, 0x6d, 0x2a, 0xd5, - 0x41, 0x69, 0xb9, 0x3a, 0x8e, 0x70, 0xb9, 0x31, 0x37, 0xe8, 0x7f, 0x73, 0xfc, 0x27, 0x77, 0x34, 0xf2, 0xfb, 0x8a, - 0x02, 0x7d, 0xdc, 0xef, 0x6b, 0xb3, 0x87, 0x44, 0xda, 0x39, 0x54, 0x96, 0x02, 0x80, 0xd5, 0x06, 0x5f, 0x37, 0x1e, - 0xa7, 0x9e, 0x49, 0x37, 0x9b, 0xaf, 0x1a, 0xc2, 0x62, 0x56, 0x59, 0xf0, 0x98, 0x6e, 0xf6, 0x58, 0x8e, 0x7a, 0x59, - 0x5c, 0x57, 0x7b, 0xac, 0xd1, 0x2f, 0xfa, 0x0a, 0x28, 0x6b, 0x43, 0xb4, 0xf5, 0x3a, 0x6e, 0xc2, 0x9b, 0x88, 0xe0, - 0x1a, 0x04, 0x61, 0x11, 0x18, 0x70, 0x34, 0x18, 0x6f, 0x5b, 0x27, 0x46, 0xdb, 0xf6, 0x4b, 0x9e, 0x75, 0x6f, 0x8c, - 0x23, 0x54, 0x34, 0xd8, 0xea, 0xa1, 0xe6, 0x01, 0xdb, 0xd9, 0x55, 0x1d, 0x05, 0x10, 0xca, 0xa9, 0x37, 0xce, 0xad, - 0xad, 0x68, 0xf7, 0xc0, 0x17, 0x7d, 0xc3, 0x3c, 0xd7, 0x81, 0x6e, 0x37, 0x3f, 0xb0, 0x6d, 0x7a, 0x26, 0xbf, 0x66, - 0xdb, 0xd4, 0xe0, 0x84, 0x0f, 0x3b, 0xe8, 0xdb, 0x86, 0xb0, 0xb6, 0xaf, 0xfd, 0x45, 0xfe, 0x17, 0xba, 0xeb, 0x02, - 0x7a, 0x5a, 0x30, 0x7b, 0x1a, 0xf3, 0x41, 0x6f, 0x36, 0xdf, 0x57, 0xfe, 0x0b, 0xc6, 0x56, 0xe8, 0x7b, 0xbb, 0x0b, - 0x9c, 0x58, 0x69, 0x1c, 0x82, 0xe3, 0xbf, 0x39, 0x99, 0x16, 0x72, 0x4c, 0x8b, 0xf7, 0xd0, 0x63, 0x9d, 0xfb, 0xf2, - 0x3e, 0x2f, 0xa9, 0x66, 0x8e, 0xd6, 0xd4, 0xa3, 0xf8, 0x9b, 0x07, 0xc3, 0xf8, 0x9b, 0x5b, 0xca, 0x5d, 0xb7, 0x80, - 0x57, 0x3f, 0x56, 0x4d, 0xa4, 0xdf, 0x6f, 0x3c, 0xed, 0xe0, 0x6a, 0x7f, 0x2f, 0xdb, 0x24, 0x8d, 0x57, 0x24, 0x8d, - 0xab, 0x78, 0xbb, 0xa9, 0x38, 0xfe, 0xf3, 0x2b, 0x83, 0xdd, 0x25, 0x73, 0x7f, 0x06, 0x64, 0xee, 0x4f, 0x9e, 0x7e, - 0xb3, 0x56, 0x40, 0xf1, 0x4e, 0x93, 0x53, 0x63, 0x19, 0x63, 0x47, 0xfd, 0x4e, 0x83, 0x41, 0x83, 0x26, 0xd7, 0x81, - 0xb7, 0x43, 0x7d, 0x7a, 0x79, 0xfb, 0xa3, 0x38, 0x5b, 0x2a, 0x2d, 0xe7, 0xae, 0x51, 0xe5, 0x7c, 0x9c, 0x4c, 0x26, - 0x28, 0xb0, 0xcd, 0x1d, 0x7e, 0xda, 0x74, 0x23, 0x5b, 0x7d, 0xe6, 0x22, 0x4f, 0x15, 0x76, 0x67, 0x8b, 0x4a, 0xe5, - 0x86, 0x78, 0x33, 0xe7, 0xdd, 0x3c, 0x3c, 0xe1, 0x82, 0xab, 0x19, 0x2b, 0xe3, 0x12, 0xad, 0xbe, 0xd6, 0x59, 0x09, - 0xb7, 0x39, 0xb6, 0x33, 0xbc, 0xac, 0x2c, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xce, 0xf4, 0x4c, 0xe6, 0x60, - 0xf8, 0x92, 0xe4, 0x95, 0x3b, 0xd5, 0xd1, 0xd1, 0x61, 0x1c, 0x19, 0xfd, 0x05, 0xf8, 0xa0, 0x87, 0x39, 0x68, 0xb0, - 0x02, 0xc7, 0xa0, 0xba, 0x6b, 0x86, 0x56, 0x6c, 0xdb, 0x87, 0x46, 0x27, 0x9f, 0xd9, 0x3d, 0xe6, 0x68, 0xb3, 0x49, - 0xed, 0xa8, 0xa3, 0x09, 0x67, 0x45, 0x1e, 0xe1, 0xcf, 0xec, 0x3e, 0xad, 0xdc, 0xd6, 0x8d, 0x97, 0xb5, 0x59, 0xc4, - 0x48, 0xde, 0x8a, 0x08, 0xd7, 0x9d, 0xa4, 0xab, 0x0d, 0x96, 0x25, 0x9f, 0x02, 0x8e, 0xfe, 0xc0, 0xee, 0x53, 0xd7, - 0x5e, 0xe0, 0x2a, 0x88, 0x56, 0x1e, 0xf4, 0x49, 0x90, 0x1c, 0x2e, 0x83, 0x13, 0x38, 0x86, 0xa6, 0xee, 0x88, 0x34, - 0xca, 0xd5, 0x22, 0x24, 0x42, 0x9b, 0xff, 0x74, 0x2a, 0x78, 0x12, 0x9e, 0x73, 0xba, 0x61, 0x71, 0xbb, 0x55, 0x89, - 0x41, 0x85, 0xda, 0x82, 0xe4, 0xd7, 0x98, 0xfb, 0xdd, 0xe7, 0xbc, 0x1f, 0x02, 0x9d, 0xd9, 0x84, 0xba, 0x46, 0xd3, - 0xa5, 0xf9, 0x85, 0xea, 0x3b, 0xa8, 0xb9, 0xae, 0x2b, 0x1e, 0xfc, 0x1a, 0x03, 0xe0, 0xc1, 0x5a, 0x86, 0x1a, 0x87, - 0xd0, 0x8d, 0x37, 0x53, 0x5d, 0x50, 0x12, 0xaf, 0xfc, 0x1c, 0x52, 0x1e, 0x82, 0x51, 0x6f, 0x00, 0x0d, 0x1d, 0x82, - 0x59, 0xcb, 0x43, 0x3e, 0x89, 0xc5, 0xce, 0x19, 0x2a, 0xcd, 0x19, 0x9a, 0x04, 0x20, 0xff, 0xca, 0x99, 0xc9, 0x0c, - 0x34, 0x0c, 0x6f, 0x69, 0x0e, 0x40, 0xb7, 0xba, 0x0e, 0x87, 0xc2, 0x15, 0xad, 0x9c, 0xf7, 0xec, 0xa2, 0xcb, 0xc6, - 0xb0, 0x62, 0xd3, 0x0e, 0xda, 0xa4, 0x30, 0x25, 0x66, 0x0b, 0x6c, 0xbc, 0xde, 0x87, 0x7b, 0xbb, 0xda, 0xb8, 0x4c, - 0xfc, 0xb4, 0x88, 0x87, 0x49, 0x4c, 0xd1, 0x8a, 0xc7, 0x14, 0x4b, 0xb0, 0x83, 0x2c, 0x37, 0xd5, 0xf8, 0x59, 0xb8, - 0x1c, 0x0d, 0x2b, 0xe9, 0xfd, 0x0e, 0x86, 0xc0, 0xe5, 0x6b, 0xb0, 0x0d, 0xc5, 0xbc, 0x22, 0x2c, 0xb1, 0xf1, 0xf4, - 0x0b, 0xd6, 0x6d, 0x6a, 0x17, 0xc4, 0xaf, 0xc0, 0x82, 0xc6, 0xab, 0x60, 0x16, 0xa1, 0x53, 0xb9, 0x73, 0x38, 0x74, - 0xd7, 0x84, 0xb5, 0xf1, 0x6a, 0xac, 0xc8, 0xd6, 0xd1, 0xf3, 0x6d, 0x1b, 0xcf, 0xbf, 0x96, 0xac, 0xbc, 0xbf, 0x61, - 0x60, 0x63, 0x2d, 0xc1, 0xdd, 0xb8, 0x5e, 0x86, 0xda, 0x40, 0x7e, 0x20, 0x0d, 0xeb, 0xb2, 0xc1, 0xdf, 0x8c, 0x8a, - 0xb1, 0x31, 0xf7, 0x94, 0x81, 0xb6, 0xc6, 0x6e, 0x17, 0xf6, 0x55, 0xd7, 0x4d, 0xd6, 0x37, 0xb1, 0x12, 0x6a, 0x48, - 0xbb, 0xbb, 0x05, 0x5c, 0x86, 0xfe, 0xb0, 0x43, 0x35, 0xda, 0x56, 0xdd, 0x40, 0x12, 0x5c, 0xfb, 0xc9, 0xaf, 0x4f, - 0x75, 0x9f, 0xb5, 0xee, 0xd7, 0xa7, 0xda, 0xb8, 0x2c, 0x34, 0x86, 0x44, 0xd8, 0xf5, 0x53, 0xf9, 0x4f, 0x8b, 0xcd, - 0x06, 0x6d, 0x60, 0x78, 0x4f, 0x78, 0x3f, 0x8e, 0x9f, 0x78, 0x0b, 0xc5, 0x04, 0x2e, 0x72, 0x6f, 0x0a, 0xe9, 0x09, - 0x79, 0x3d, 0x82, 0x27, 0x7c, 0x67, 0x08, 0x4f, 0x78, 0xe0, 0xf4, 0x0a, 0x52, 0xd3, 0x54, 0xb0, 0xdc, 0xd3, 0x4f, - 0x64, 0x91, 0xd0, 0xf0, 0x71, 0x6f, 0x38, 0x11, 0xfa, 0x8f, 0x14, 0xf8, 0x2f, 0x3c, 0x5e, 0x6a, 0x2d, 0x05, 0xe6, - 0x62, 0xb1, 0xd4, 0x58, 0x99, 0xd1, 0xaf, 0x26, 0x52, 0xe8, 0xf6, 0x84, 0xce, 0x79, 0x71, 0x9f, 0x2e, 0x79, 0x7b, - 0x2e, 0x85, 0x54, 0x0b, 0x9a, 0x31, 0xac, 0xee, 0x95, 0x66, 0xf3, 0xf6, 0x92, 0xe3, 0x97, 0xac, 0xf8, 0xc2, 0x34, - 0xcf, 0x28, 0x7e, 0x27, 0xc7, 0x52, 0x4b, 0xfc, 0xe6, 0xee, 0x7e, 0xca, 0x04, 0xfe, 0x30, 0x5e, 0x0a, 0xbd, 0xc4, - 0x8a, 0x0a, 0xd5, 0x56, 0xac, 0xe4, 0x93, 0x7e, 0xbb, 0xbd, 0x28, 0xf9, 0x9c, 0x96, 0xf7, 0xed, 0x4c, 0x16, 0xb2, - 0x4c, 0xff, 0xab, 0x73, 0x4a, 0x1f, 0x4d, 0xce, 0xfa, 0xba, 0xa4, 0x42, 0x71, 0x58, 0x98, 0x94, 0x16, 0xc5, 0xc1, - 0xe9, 0x79, 0x67, 0xae, 0x0e, 0xed, 0x85, 0x1f, 0x15, 0x7a, 0xf3, 0x07, 0xfe, 0x45, 0xc2, 0x28, 0x93, 0xb1, 0x16, - 0x6e, 0x90, 0xab, 0x6c, 0x59, 0x2a, 0x59, 0xa6, 0x0b, 0xc9, 0x85, 0x66, 0x65, 0x7f, 0x2c, 0xcb, 0x9c, 0x95, 0xed, - 0x92, 0xe6, 0x7c, 0xa9, 0xd2, 0xb3, 0xc5, 0x5d, 0xbf, 0xd9, 0x83, 0xcd, 0x4f, 0x85, 0x14, 0xac, 0x0f, 0xfc, 0xc6, - 0xb4, 0x94, 0x4b, 0x91, 0xbb, 0x61, 0x2c, 0x85, 0x62, 0xba, 0xbf, 0xa0, 0x39, 0xd8, 0x01, 0xa7, 0x97, 0x8b, 0xbb, - 0xbe, 0x99, 0xf5, 0x2d, 0xe3, 0xd3, 0x99, 0x4e, 0xcf, 0x3b, 0x1d, 0xfb, 0xad, 0xf8, 0xdf, 0x2c, 0xed, 0xf6, 0x92, - 0xde, 0xf9, 0xe2, 0x0e, 0x38, 0x78, 0xcd, 0xca, 0x36, 0xc0, 0x02, 0x2a, 0x75, 0x93, 0xce, 0xa3, 0xd3, 0x87, 0x90, - 0x01, 0x36, 0x0e, 0x6d, 0x33, 0x21, 0x30, 0x76, 0x4f, 0x97, 0x8b, 0x05, 0x2b, 0xc1, 0x8b, 0xbe, 0x3f, 0xa7, 0xe5, - 0x94, 0x8b, 0x76, 0x69, 0x1a, 0x6d, 0x5f, 0x2e, 0xee, 0x36, 0x30, 0x9f, 0xd4, 0x9a, 0xad, 0xba, 0x69, 0xb9, 0xaf, - 0x55, 0x30, 0x44, 0x13, 0x93, 0x26, 0x2d, 0xa7, 0x63, 0x1a, 0x77, 0x7b, 0x0f, 0xb1, 0xff, 0x5f, 0xd2, 0x43, 0x01, - 0xd8, 0xda, 0xf9, 0xb2, 0x34, 0xb7, 0xa8, 0x69, 0x57, 0xd9, 0x66, 0x67, 0xf2, 0x0b, 0x2b, 0x7d, 0xab, 0xe6, 0x63, - 0xb5, 0x33, 0xef, 0xff, 0x51, 0xa3, 0xd4, 0xb6, 0xf5, 0x4a, 0xdd, 0x00, 0x8d, 0xde, 0x6d, 0xec, 0xbf, 0x7a, 0x97, - 0xf4, 0xe1, 0xd9, 0xb9, 0x87, 0xfb, 0x64, 0x32, 0x69, 0x00, 0xdd, 0x43, 0xb7, 0xdb, 0x59, 0xdc, 0x1d, 0xf4, 0x3a, - 0x1e, 0xc6, 0x16, 0xa6, 0x17, 0x8b, 0xbb, 0x3d, 0x2b, 0x18, 0x60, 0xc5, 0x76, 0x6f, 0x07, 0xc9, 0xa9, 0x3a, 0x60, - 0x54, 0xb1, 0xcd, 0x1f, 0x78, 0x4e, 0x01, 0x37, 0x0c, 0xd2, 0x0e, 0x8d, 0x9c, 0x0a, 0x2b, 0x30, 0x5a, 0xdd, 0xf2, - 0x5c, 0xcf, 0xd2, 0x6e, 0xa7, 0xf3, 0x5d, 0x8d, 0x49, 0xfd, 0x99, 0x5d, 0xd2, 0x6e, 0xc9, 0xe6, 0x0d, 0xfc, 0x1a, - 0xd3, 0x6a, 0x17, 0xac, 0x16, 0xd2, 0x75, 0x5a, 0xb2, 0xc2, 0x44, 0xb9, 0xd9, 0xb8, 0xad, 0xb0, 0x33, 0x65, 0x2e, - 0x66, 0xac, 0xe4, 0xba, 0xdf, 0xfc, 0xaa, 0x3b, 0xde, 0x9d, 0xd3, 0xc6, 0xca, 0xc7, 0x2b, 0x5b, 0xc3, 0x5d, 0xc6, - 0x3e, 0x85, 0x8f, 0x5d, 0xac, 0xfc, 0x42, 0xcb, 0x78, 0x6b, 0xc3, 0xe0, 0xb0, 0x06, 0xda, 0x04, 0x73, 0x2e, 0xc1, - 0x54, 0x74, 0x84, 0xbf, 0x02, 0x85, 0x8c, 0x16, 0x59, 0x0c, 0x23, 0x3a, 0x68, 0x1f, 0x9c, 0x96, 0x6c, 0x8e, 0x3c, - 0x20, 0x92, 0x87, 0xe7, 0x25, 0x9b, 0x6f, 0x12, 0x53, 0x7d, 0x65, 0x50, 0x97, 0x16, 0x7c, 0x2a, 0xd2, 0x8c, 0xc1, - 0xb6, 0xda, 0x24, 0x4c, 0x68, 0xae, 0xef, 0xdb, 0xa5, 0xbc, 0x5d, 0xe5, 0x5c, 0x2d, 0x0a, 0x7a, 0x9f, 0x4e, 0x0a, - 0x76, 0xd7, 0x37, 0xa5, 0xda, 0x5c, 0xb3, 0xb9, 0x72, 0x65, 0xfb, 0x90, 0xde, 0xce, 0xad, 0x39, 0x07, 0x40, 0x4f, - 0xde, 0x6e, 0xef, 0x6b, 0xbf, 0x68, 0x6d, 0xb9, 0xd4, 0x07, 0x1d, 0xd5, 0x9f, 0x73, 0xd1, 0x76, 0x03, 0x39, 0x03, - 0x8c, 0xd8, 0x85, 0x7c, 0xd0, 0x7f, 0xc2, 0xee, 0x16, 0x54, 0xe4, 0x2c, 0x5f, 0x05, 0xd5, 0x7a, 0x50, 0x2f, 0x2c, - 0x95, 0x0a, 0x3d, 0x6b, 0x1b, 0x1b, 0xb4, 0xb8, 0x27, 0xd0, 0x57, 0x50, 0xfe, 0x51, 0x07, 0xdb, 0xff, 0x4f, 0xba, - 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xbe, 0x0d, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, 0x5a, 0x38, 0x88, - 0xcc, 0x79, 0x9e, 0x17, 0x8d, 0x11, 0x5d, 0x07, 0x9d, 0x75, 0xd1, 0x0a, 0xe6, 0x9f, 0x76, 0x0e, 0x3a, 0x07, 0x66, - 0x2e, 0x6e, 0x1b, 0x9c, 0x9d, 0x3d, 0x3c, 0x7d, 0xc4, 0xfa, 0x05, 0x17, 0xac, 0x31, 0xd5, 0x6f, 0x82, 0x3a, 0x6c, - 0xb8, 0xe7, 0x1a, 0xee, 0x1e, 0x74, 0x0f, 0xce, 0x3a, 0xdf, 0x79, 0x2a, 0x52, 0xb0, 0x89, 0xb6, 0xfb, 0xa6, 0x41, - 0x56, 0x2e, 0x7d, 0xd3, 0xb7, 0x25, 0x5d, 0xa4, 0x42, 0xc2, 0x9f, 0x3e, 0x6c, 0xfe, 0x49, 0x21, 0x6f, 0xd3, 0x19, - 0xcf, 0x73, 0x26, 0x6c, 0x81, 0x2a, 0x91, 0x15, 0x05, 0x5f, 0x28, 0x6e, 0x57, 0xc3, 0xe1, 0xee, 0xf9, 0x16, 0x54, - 0xc3, 0x01, 0x9d, 0x06, 0x03, 0x3a, 0xaf, 0x07, 0x54, 0xf7, 0x1f, 0x8e, 0xb0, 0xb7, 0x35, 0x57, 0x53, 0xaa, 0xdf, - 0xc0, 0xa4, 0x3f, 0x97, 0x4a, 0x03, 0xcc, 0xbd, 0xf1, 0x88, 0x39, 0x5d, 0xda, 0x63, 0xa6, 0x6f, 0x19, 0x13, 0x5f, - 0x1f, 0xc4, 0x75, 0x2a, 0x45, 0x71, 0x6f, 0x3f, 0x57, 0x61, 0x97, 0x74, 0xa9, 0xe5, 0x26, 0x19, 0x73, 0x41, 0xcb, - 0xfb, 0x4f, 0x8a, 0x09, 0x25, 0xcb, 0x4f, 0x72, 0x32, 0x59, 0x7d, 0x8d, 0xe4, 0x3d, 0x44, 0x9b, 0x44, 0x71, 0x31, - 0x2d, 0x98, 0x25, 0x70, 0x06, 0x11, 0xdc, 0x21, 0x63, 0xdb, 0x35, 0x4d, 0x36, 0x06, 0xbd, 0x49, 0xb2, 0x82, 0xcf, - 0xa9, 0x66, 0x06, 0xce, 0x01, 0xa9, 0x71, 0x93, 0xb7, 0x54, 0xae, 0x73, 0x60, 0xff, 0xd4, 0xa5, 0x61, 0x1b, 0x05, - 0x85, 0x7d, 0x93, 0x5c, 0x18, 0xfc, 0x30, 0xe0, 0x30, 0xbb, 0xc8, 0xac, 0x9e, 0x59, 0xbb, 0x00, 0x76, 0x30, 0xbb, - 0x46, 0x53, 0xd7, 0x8e, 0x2e, 0xd9, 0x16, 0xcf, 0x3b, 0xdf, 0x35, 0x73, 0x0b, 0x3a, 0x66, 0xc5, 0xca, 0x6e, 0x54, - 0x0f, 0x5c, 0xb7, 0x55, 0xc3, 0x65, 0x0e, 0x48, 0x86, 0x01, 0xd1, 0x28, 0x4d, 0xdb, 0xb7, 0x6c, 0xfc, 0x99, 0x6b, - 0xbb, 0x65, 0xda, 0xea, 0x16, 0x9c, 0x8a, 0xcc, 0x98, 0x16, 0xac, 0x5c, 0x79, 0x42, 0xde, 0x69, 0x10, 0xd0, 0x1b, - 0x61, 0x0e, 0x68, 0x4d, 0xc7, 0x6d, 0x08, 0xb1, 0xc6, 0xca, 0xd5, 0xbe, 0xc9, 0xcd, 0xe9, 0x9d, 0x43, 0xb1, 0x47, - 0x9d, 0xef, 0x1a, 0x87, 0xec, 0x59, 0xa7, 0xe3, 0x8f, 0x88, 0xb6, 0xad, 0x91, 0x76, 0x93, 0x73, 0x36, 0xaf, 0x12, - 0xb5, 0x5c, 0xa4, 0x8d, 0x84, 0xb1, 0xd4, 0x5a, 0xce, 0x6d, 0xda, 0x1e, 0x6a, 0xd4, 0x24, 0xbd, 0xdd, 0xde, 0xe2, - 0xee, 0xc0, 0xfc, 0xd3, 0x39, 0xe8, 0xec, 0x92, 0xda, 0x5d, 0xac, 0x38, 0x45, 0x1e, 0x8f, 0xa1, 0xe3, 0x2e, 0x9b, - 0xf7, 0x97, 0x0a, 0x8e, 0x7b, 0x03, 0x71, 0x73, 0xa2, 0x6d, 0xcc, 0x64, 0x01, 0xb0, 0x94, 0x0b, 0x38, 0x5d, 0xed, - 0x61, 0x07, 0x7d, 0x28, 0x09, 0xe6, 0xf0, 0x7b, 0x1b, 0x6d, 0x0e, 0xab, 0x73, 0x50, 0x0f, 0x0c, 0xfe, 0xd9, 0xfc, - 0x51, 0xf3, 0xe7, 0xcf, 0x58, 0x20, 0x1f, 0xf1, 0x56, 0x72, 0xbe, 0xee, 0x38, 0x99, 0x28, 0xd7, 0xb5, 0xa8, 0x66, - 0x3c, 0x4a, 0xe6, 0xf4, 0xce, 0xba, 0x96, 0xcc, 0xb9, 0x00, 0xc3, 0x35, 0x84, 0x75, 0x60, 0xe2, 0x3f, 0x0b, 0x1b, - 0xca, 0x75, 0x0c, 0x0d, 0x1f, 0xf7, 0x92, 0xf3, 0x73, 0x84, 0x3b, 0xb8, 0x77, 0x7e, 0x1e, 0xc8, 0x64, 0x13, 0xbd, - 0xaf, 0xe8, 0xbe, 0x92, 0x72, 0x4f, 0xc9, 0x13, 0xd3, 0xe8, 0x49, 0xb7, 0xd3, 0xc1, 0xc6, 0x7d, 0xbe, 0x2a, 0x2c, - 0xd4, 0x9e, 0x66, 0xbb, 0x9d, 0x0e, 0x34, 0x0b, 0x7f, 0xdc, 0xbc, 0x7e, 0x20, 0xab, 0x4e, 0xda, 0xc1, 0xdd, 0xb4, - 0x8b, 0x7b, 0x69, 0x0f, 0x9f, 0xa6, 0xa7, 0xf8, 0x2c, 0x3d, 0xc3, 0xe7, 0xe9, 0x39, 0xbe, 0x48, 0x2f, 0xf0, 0xc3, - 0xf4, 0x21, 0xbe, 0x4c, 0x2f, 0xf1, 0xa3, 0xf4, 0x11, 0x7e, 0x9c, 0x76, 0x3b, 0xf8, 0x49, 0xda, 0xed, 0xe2, 0xa7, - 0x69, 0xb7, 0x87, 0x9f, 0xa5, 0xdd, 0x53, 0xfc, 0x3c, 0xed, 0x9e, 0xe1, 0x17, 0x69, 0xf7, 0x1c, 0x53, 0xc8, 0x1d, - 0x43, 0x6e, 0x06, 0xb9, 0x39, 0xe4, 0x32, 0xc8, 0x9d, 0xa4, 0xdd, 0xf3, 0x0d, 0x56, 0x36, 0xe4, 0x46, 0xd4, 0xe9, - 0xf6, 0x4e, 0xcf, 0xce, 0x2f, 0x1e, 0x5e, 0x3e, 0x7a, 0xfc, 0xe4, 0xe9, 0xb3, 0xe7, 0x2f, 0xa2, 0x11, 0xfe, 0x64, - 0x3c, 0x5f, 0x94, 0x18, 0xf2, 0xa3, 0xee, 0xf9, 0x08, 0xdf, 0xfb, 0xcf, 0x98, 0x1f, 0xf5, 0xce, 0x3a, 0xe8, 0xfa, - 0xfa, 0x6c, 0xd4, 0xaa, 0x72, 0x9f, 0x18, 0x87, 0x9b, 0x3a, 0x8b, 0x10, 0x12, 0x43, 0x0e, 0xc2, 0x77, 0xd6, 0x81, - 0x86, 0xc5, 0x3c, 0x29, 0xd1, 0xd1, 0x91, 0xf9, 0x31, 0xf5, 0x3f, 0xc6, 0xfe, 0x07, 0x0d, 0x16, 0xe9, 0x0b, 0x8d, - 0x9d, 0xc7, 0xb5, 0xae, 0xfc, 0x1d, 0x2a, 0x53, 0xa2, 0x03, 0xee, 0x8c, 0xfa, 0xff, 0x2b, 0xb2, 0x46, 0x3b, 0xe4, - 0xcc, 0x2a, 0xc6, 0xce, 0x07, 0x8c, 0xac, 0xca, 0xb4, 0x77, 0x7e, 0x7e, 0xf4, 0xc3, 0x90, 0x0f, 0xbb, 0xa3, 0xd1, - 0x71, 0xf7, 0x21, 0x9e, 0x56, 0x09, 0x3d, 0x9b, 0x30, 0xae, 0x12, 0x4e, 0x6d, 0x02, 0x4d, 0x6d, 0x6d, 0x48, 0x3a, - 0x33, 0x49, 0x50, 0x62, 0x93, 0x9a, 0xb6, 0x1f, 0xda, 0xb6, 0x1f, 0x81, 0x35, 0x99, 0x69, 0xde, 0x35, 0x7d, 0x75, - 0x75, 0xb6, 0x76, 0x8d, 0xe2, 0x69, 0xea, 0x5a, 0xf3, 0x89, 0x67, 0xa3, 0x11, 0x1e, 0x9b, 0xc4, 0xf3, 0x3a, 0xf1, - 0x62, 0x34, 0x72, 0x5d, 0x3d, 0x32, 0x5d, 0x3d, 0xac, 0xb3, 0x2e, 0x47, 0x23, 0xd3, 0x25, 0x72, 0xb1, 0x03, 0x94, - 0x3e, 0xb8, 0xad, 0xf4, 0x37, 0xfc, 0xaa, 0x77, 0x7e, 0x3e, 0x00, 0x0c, 0x33, 0x36, 0xc1, 0x1e, 0x46, 0x9f, 0x03, - 0x18, 0xdd, 0xc1, 0xef, 0xc1, 0x27, 0x9a, 0xde, 0xd3, 0x0a, 0x48, 0x83, 0xe8, 0xbf, 0xa2, 0x96, 0x36, 0x30, 0x37, - 0x7f, 0xa6, 0xf6, 0xcf, 0x18, 0xb5, 0x6e, 0x29, 0x80, 0x1b, 0x34, 0x52, 0x5e, 0xa5, 0x6c, 0x7a, 0xbc, 0xa1, 0xe0, - 0xe2, 0x33, 0x53, 0x05, 0x1d, 0xac, 0x67, 0xb7, 0xe3, 0xf5, 0x4c, 0x7d, 0x41, 0xbf, 0xc7, 0xbf, 0xab, 0xe3, 0x78, - 0xd8, 0x6e, 0x25, 0xec, 0xf7, 0x1c, 0x7c, 0x89, 0x06, 0x69, 0xce, 0xa6, 0x68, 0x30, 0xfc, 0x5d, 0xe1, 0x51, 0x2b, - 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0xd0, 0x00, 0x0d, 0x7e, 0x57, 0xc7, 0xbf, 0xa3, - 0x07, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x87, 0x1f, 0x3a, 0xae, 0xb6, 0x30, 0xc3, 0xdd, 0x36, 0x83, 0x60, - 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe2, 0x27, 0xa7, 0x1d, 0xf4, 0x5d, 0xb7, 0x07, 0xca, 0x95, 0xb6, 0x38, 0xde, - 0xdd, 0xf4, 0x65, 0xfb, 0x14, 0x3f, 0x6a, 0x97, 0xb8, 0x8b, 0x70, 0xbb, 0xeb, 0xb5, 0xde, 0x43, 0x15, 0x77, 0x10, - 0x56, 0xf1, 0x25, 0xfc, 0x73, 0x86, 0x46, 0xf5, 0x86, 0xfc, 0x89, 0x6e, 0xf7, 0x0e, 0x7e, 0xb3, 0x24, 0x56, 0x2d, - 0x7e, 0x72, 0xd1, 0x41, 0xdf, 0x5d, 0x98, 0x8e, 0xd8, 0xb1, 0xde, 0xd3, 0x95, 0xc4, 0x67, 0x6d, 0x09, 0x1d, 0x75, - 0xaa, 0x7e, 0x44, 0x7c, 0x8e, 0xb0, 0x88, 0x4f, 0xe1, 0x9f, 0x6e, 0xd8, 0xcf, 0xd3, 0x9d, 0x7e, 0xcc, 0xbc, 0xbb, - 0x38, 0x39, 0xb7, 0x6e, 0xb8, 0xca, 0xde, 0x89, 0xb7, 0xd8, 0x75, 0xd7, 0x5c, 0xe6, 0x75, 0x4f, 0xe0, 0x03, 0x61, - 0x7d, 0x4c, 0x14, 0x66, 0xc7, 0xe0, 0xbf, 0x0b, 0x66, 0x2b, 0xea, 0xea, 0xb4, 0xaf, 0x5a, 0x2d, 0x24, 0x86, 0x6a, - 0x74, 0x4c, 0xba, 0x6d, 0xdd, 0x66, 0x18, 0x7e, 0xb7, 0x48, 0x15, 0x14, 0x4e, 0xd4, 0xbd, 0xbe, 0x71, 0xbd, 0xda, - 0x9b, 0x7f, 0x8f, 0x1d, 0x84, 0x10, 0x35, 0x88, 0x75, 0x9b, 0xa1, 0x13, 0xd1, 0x8a, 0xf5, 0x15, 0x1b, 0x5c, 0xa4, - 0x1d, 0x64, 0xb0, 0x53, 0x0d, 0x62, 0xd6, 0xe6, 0x90, 0xde, 0x4b, 0x63, 0xde, 0xd6, 0xf0, 0xeb, 0x2c, 0x80, 0x96, - 0x00, 0xbc, 0xab, 0xbd, 0x91, 0xca, 0x93, 0xde, 0xf9, 0x39, 0x16, 0x84, 0x27, 0x53, 0xf3, 0x4b, 0x11, 0x9e, 0x8c, - 0xcd, 0x2f, 0x49, 0x2a, 0x78, 0xd9, 0xde, 0x71, 0x49, 0x82, 0x55, 0x35, 0x29, 0x14, 0x16, 0xb4, 0x44, 0x27, 0x3d, - 0x6f, 0x16, 0x80, 0x67, 0x7e, 0x0e, 0xa0, 0x06, 0x29, 0x8d, 0x45, 0xa8, 0x6c, 0x97, 0xb8, 0x20, 0xf4, 0x3a, 0x39, - 0x1f, 0xcc, 0x4e, 0xe2, 0x5e, 0x5b, 0xb6, 0x4b, 0x94, 0xce, 0x4e, 0x4c, 0x4d, 0x9c, 0x91, 0x37, 0xd4, 0xb6, 0x86, - 0x67, 0x70, 0x97, 0x9b, 0x91, 0xec, 0xf8, 0xa2, 0xd3, 0x4a, 0xce, 0x11, 0x1e, 0x66, 0xeb, 0x0e, 0x2e, 0xd6, 0xeb, - 0x0e, 0xa6, 0xe1, 0x32, 0x08, 0x0f, 0x90, 0x4a, 0x53, 0xb7, 0x1d, 0x9b, 0x67, 0xc0, 0x63, 0x0d, 0x76, 0x09, 0x1a, - 0xbc, 0x7d, 0x34, 0xf8, 0x21, 0xa5, 0xdc, 0x5d, 0x08, 0x22, 0x13, 0x9d, 0x70, 0x12, 0xea, 0xee, 0xde, 0x08, 0xbf, - 0xae, 0xde, 0xb2, 0x54, 0xc4, 0xbf, 0x4a, 0x6c, 0xd3, 0xea, 0x62, 0x0f, 0xe8, 0x6e, 0xb1, 0xa7, 0x74, 0xa7, 0xd8, - 0xdb, 0x3d, 0xc5, 0x7e, 0xda, 0x2d, 0xf6, 0x97, 0x0c, 0x34, 0x8d, 0xfc, 0xbb, 0xd3, 0x8b, 0x4e, 0xeb, 0x14, 0x90, - 0xf5, 0xf4, 0xa2, 0x53, 0x17, 0x7a, 0x4c, 0xeb, 0xb5, 0xd2, 0xe4, 0x86, 0x5a, 0x5f, 0x0b, 0xee, 0x9d, 0xbe, 0xcd, - 0xc2, 0x59, 0x97, 0xf3, 0xca, 0xbf, 0x7c, 0x78, 0x0e, 0xb6, 0x2c, 0xc2, 0x50, 0x3b, 0x3d, 0xbc, 0x18, 0x0d, 0x66, - 0x2c, 0x6e, 0x41, 0x2a, 0x4a, 0x27, 0xda, 0xfd, 0x42, 0xd5, 0x95, 0xf6, 0x5f, 0x12, 0x92, 0x7a, 0x23, 0x84, 0x25, - 0x69, 0xe9, 0xe1, 0xe9, 0xc8, 0x9c, 0x77, 0x25, 0xfc, 0x3e, 0x33, 0xbf, 0x2b, 0x85, 0x92, 0x73, 0xc8, 0x98, 0xdd, - 0x8e, 0xa3, 0x81, 0x20, 0x0f, 0x68, 0x6c, 0x6c, 0xec, 0x51, 0x5a, 0x65, 0xa8, 0x2f, 0x90, 0xf1, 0xb6, 0xca, 0x10, - 0xe4, 0x8d, 0x70, 0xbf, 0xf1, 0xaa, 0x4c, 0xc1, 0xde, 0x06, 0x4f, 0x53, 0xb0, 0xb5, 0xc1, 0xe3, 0x54, 0x80, 0x3f, - 0x08, 0x4d, 0x59, 0x60, 0xc5, 0xff, 0xdc, 0x69, 0xf0, 0xcc, 0xad, 0x33, 0x31, 0x58, 0xda, 0x67, 0x70, 0x52, 0xfc, - 0x25, 0x63, 0xf8, 0xdb, 0xd2, 0x08, 0x33, 0x68, 0x93, 0x21, 0xcc, 0x93, 0x92, 0x40, 0x1a, 0xe6, 0xc9, 0x94, 0x30, - 0x68, 0x92, 0x27, 0x63, 0xc2, 0x86, 0xbd, 0x00, 0x4d, 0x5e, 0x19, 0xd8, 0x01, 0x70, 0x78, 0xf3, 0x22, 0x5f, 0xdb, - 0xc6, 0xc1, 0x42, 0x00, 0x9a, 0x10, 0x04, 0x62, 0x2e, 0x0c, 0xc1, 0x6c, 0x44, 0xd9, 0x9f, 0xbd, 0x3a, 0xfc, 0x25, - 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x00, 0x59, 0x8d, 0x1f, 0xac, 0xd8, 0x06, 0x1f, 0x3c, 0x58, 0x89, 0xcd, 0x77, 0xf0, - 0x47, 0xd9, 0x3f, 0xc0, 0x3c, 0x24, 0x14, 0x6d, 0xd0, 0x1f, 0x29, 0x14, 0xdb, 0x53, 0x0a, 0xfd, 0xe1, 0xdd, 0x01, - 0x15, 0x59, 0xdd, 0xa5, 0x51, 0x4e, 0xcb, 0xcf, 0x11, 0xfe, 0x2d, 0x8d, 0x0a, 0xe0, 0x16, 0x23, 0xfc, 0x6b, 0x1a, - 0x95, 0x2c, 0xc2, 0xff, 0x4a, 0xa3, 0x71, 0xb1, 0x8c, 0xf0, 0x2f, 0x69, 0x34, 0x2d, 0x23, 0xfc, 0x11, 0x94, 0xb5, - 0x39, 0x5f, 0xce, 0x23, 0xfc, 0x21, 0x8d, 0x94, 0xf1, 0x86, 0xc0, 0x8f, 0xd3, 0x88, 0xb1, 0x08, 0xbf, 0x4f, 0x23, - 0x59, 0x44, 0xf8, 0x26, 0x8d, 0x64, 0x19, 0xe1, 0x27, 0x69, 0x54, 0xd2, 0x08, 0x3f, 0x4d, 0x23, 0x28, 0x34, 0x8d, - 0xf0, 0xb3, 0x34, 0x82, 0x96, 0x55, 0x84, 0xdf, 0xa5, 0x11, 0x17, 0x11, 0xfe, 0x39, 0x8d, 0xf4, 0xb2, 0xfc, 0x6b, - 0x29, 0xb9, 0x8a, 0xf0, 0xf3, 0x34, 0x9a, 0xf1, 0x08, 0xbf, 0x4d, 0xa3, 0x52, 0x46, 0xf8, 0x4d, 0x1a, 0xd1, 0x22, - 0xc2, 0xaf, 0xd3, 0xa8, 0x60, 0x11, 0xfe, 0x29, 0x8d, 0x72, 0x16, 0xe1, 0x1f, 0xd3, 0xe8, 0x9e, 0x15, 0x85, 0x8c, - 0xf0, 0x8b, 0x34, 0x62, 0x22, 0xc2, 0x3f, 0xa4, 0x51, 0x36, 0x8b, 0xf0, 0x3f, 0xd3, 0x88, 0x96, 0x9f, 0x55, 0x84, - 0x5f, 0xa6, 0x11, 0xa3, 0x11, 0x7e, 0x65, 0x3b, 0x9a, 0x46, 0xf8, 0xfb, 0x34, 0xba, 0x9d, 0x45, 0x1b, 0x2c, 0x15, - 0x59, 0xbd, 0xe1, 0x19, 0xfb, 0x17, 0x4b, 0xa3, 0x49, 0x67, 0x72, 0x39, 0x99, 0x44, 0x98, 0x0a, 0xcd, 0xff, 0x5a, - 0xb2, 0xdb, 0xe7, 0x1a, 0x12, 0x29, 0x1b, 0xe7, 0x0f, 0x23, 0x4c, 0xff, 0x5a, 0xd2, 0x34, 0x9a, 0x4c, 0x4c, 0x81, - 0xbf, 0x96, 0x74, 0x4e, 0xcb, 0x77, 0x2c, 0x8d, 0x1e, 0x4e, 0x26, 0x93, 0xfc, 0x2c, 0xc2, 0xf4, 0xef, 0xe5, 0xaf, - 0xa6, 0x05, 0x53, 0x60, 0xcc, 0xf8, 0x14, 0xea, 0x9e, 0x4f, 0xce, 0xf3, 0x2c, 0xc2, 0x63, 0xae, 0xfe, 0x5a, 0xc2, - 0xf7, 0x84, 0x9d, 0x65, 0x67, 0x11, 0x1e, 0x17, 0x34, 0xfb, 0x9c, 0x46, 0x1d, 0xf3, 0x4b, 0xfc, 0xc0, 0xf2, 0x37, - 0x73, 0x69, 0xae, 0x32, 0x26, 0x6c, 0x9c, 0xe5, 0x11, 0x36, 0x83, 0x99, 0xc0, 0xdf, 0x2f, 0xfc, 0x3d, 0xd3, 0x69, - 0x74, 0x49, 0x7b, 0x63, 0xd6, 0x8b, 0xf0, 0xf8, 0xed, 0xad, 0x48, 0x23, 0x7a, 0xde, 0xa3, 0x3d, 0x1a, 0xe1, 0xf1, - 0xb2, 0x2c, 0xee, 0x6f, 0xa5, 0xcc, 0x01, 0x08, 0xe3, 0xcb, 0xcb, 0x87, 0x11, 0xce, 0xe8, 0x4f, 0x1a, 0x6a, 0x9f, - 0x4f, 0x1e, 0x31, 0xda, 0x89, 0xf0, 0x0f, 0xb4, 0xd4, 0xbf, 0x2e, 0x95, 0x1b, 0x68, 0x07, 0x52, 0x64, 0xf6, 0x1e, - 0xd4, 0xfc, 0x51, 0xde, 0xbb, 0x78, 0xd4, 0x65, 0x11, 0xce, 0x6e, 0xde, 0x40, 0x6f, 0x0f, 0x27, 0xe7, 0x1d, 0xf8, - 0x10, 0x20, 0x97, 0xb2, 0x12, 0x1a, 0xb9, 0x38, 0x7b, 0x74, 0xce, 0x72, 0x93, 0xa8, 0x78, 0xf1, 0xd9, 0xcc, 0xfe, - 0x12, 0xe6, 0x93, 0x95, 0x7c, 0xae, 0xa4, 0x48, 0xa3, 0x3c, 0xeb, 0x9e, 0x9d, 0x42, 0xc2, 0x3d, 0x15, 0x1e, 0x38, - 0x77, 0x50, 0xf5, 0x72, 0x1c, 0xe1, 0x3b, 0x9b, 0x7a, 0x39, 0x36, 0x1f, 0xd3, 0xf7, 0x3f, 0x89, 0xb7, 0x79, 0x1a, - 0x8d, 0x2f, 0x2f, 0x2f, 0x3a, 0x90, 0xf0, 0x0b, 0xbd, 0x4f, 0x23, 0xfa, 0x08, 0xfe, 0x83, 0xec, 0x5f, 0x5f, 0x40, - 0x87, 0x30, 0xc2, 0xbb, 0xe9, 0xaf, 0x61, 0xce, 0xe7, 0x19, 0xfd, 0xcc, 0xd3, 0x68, 0x9c, 0x8f, 0x1f, 0x5e, 0x40, - 0xbd, 0x39, 0x9d, 0xbe, 0xd0, 0x14, 0xda, 0xed, 0x74, 0x4c, 0xcb, 0xef, 0xf9, 0x17, 0x66, 0xaa, 0x9f, 0x9f, 0x5f, - 0x8c, 0x7b, 0x30, 0x82, 0x1b, 0x50, 0xa8, 0xc0, 0x78, 0x2e, 0x33, 0xd3, 0xe0, 0x4d, 0xf6, 0x3c, 0x4f, 0xa3, 0x47, - 0x8f, 0x4e, 0x7b, 0x59, 0x16, 0xe1, 0xbb, 0x5f, 0x73, 0x5b, 0xdb, 0xe4, 0x29, 0x80, 0x7d, 0x1a, 0xb1, 0x47, 0x8f, - 0x2e, 0x1e, 0x52, 0xf8, 0x7e, 0x69, 0xda, 0xba, 0x9c, 0x8c, 0xb3, 0x4b, 0x68, 0xeb, 0x03, 0x4c, 0xe7, 0xec, 0xf2, - 0x34, 0x37, 0x7d, 0x7d, 0x30, 0xa3, 0xee, 0x4d, 0xce, 0x26, 0x67, 0x26, 0xd3, 0x0c, 0xb5, 0xfa, 0xfc, 0x99, 0xa5, - 0x51, 0xc6, 0xf2, 0x6e, 0x84, 0xef, 0xdc, 0xc2, 0x3d, 0x3a, 0xeb, 0x74, 0xf2, 0xd3, 0x08, 0xe7, 0x8f, 0x17, 0x8b, - 0x77, 0x06, 0x82, 0xdd, 0xb3, 0x47, 0xf6, 0x5b, 0x7d, 0xbe, 0x87, 0xa6, 0xc7, 0x06, 0x68, 0x39, 0x9f, 0x9b, 0x96, - 0x2f, 0x1e, 0xc1, 0x7f, 0xe6, 0xdb, 0x34, 0x5d, 0x7d, 0xcb, 0x7c, 0x6a, 0x17, 0xa5, 0xcb, 0x1e, 0x75, 0xa0, 0xc6, - 0x84, 0xff, 0x3a, 0x2e, 0x39, 0xa0, 0xd1, 0xb8, 0x07, 0xff, 0x17, 0xe1, 0x49, 0x71, 0xf3, 0xc6, 0xe1, 0xec, 0x64, - 0x42, 0x27, 0x9d, 0x08, 0x4f, 0xe4, 0xaf, 0x4a, 0xff, 0xf2, 0x58, 0xa4, 0x51, 0xaf, 0x77, 0x39, 0x36, 0x65, 0x96, - 0x3f, 0x28, 0x6e, 0xf0, 0xb8, 0x63, 0x5a, 0x99, 0xd2, 0x77, 0x6a, 0x7c, 0x23, 0x61, 0x25, 0xe1, 0xbf, 0x08, 0x4f, - 0x41, 0x0b, 0xe7, 0x5a, 0xb9, 0xb4, 0xdb, 0x61, 0xfa, 0xde, 0xa0, 0x66, 0xfe, 0x10, 0xe0, 0xe5, 0x97, 0x31, 0xa7, - 0xf4, 0xbc, 0xd7, 0x89, 0xb0, 0x19, 0xf5, 0x65, 0x07, 0xfe, 0x8b, 0xb0, 0x85, 0x9c, 0x81, 0xeb, 0xf4, 0xd7, 0x17, - 0x3f, 0xde, 0xa6, 0x11, 0xcd, 0x27, 0x13, 0x58, 0x12, 0x33, 0x19, 0x5f, 0x6c, 0x26, 0x05, 0xbb, 0xff, 0xe9, 0xd6, - 0x6d, 0x17, 0x93, 0xa0, 0x1d, 0x74, 0x2e, 0x1e, 0x8d, 0xcf, 0x22, 0xfc, 0x2e, 0xe7, 0x54, 0xc0, 0x2a, 0x65, 0xf9, - 0x79, 0x76, 0x9e, 0x99, 0x84, 0xa9, 0x4c, 0xa3, 0x33, 0x58, 0xf2, 0x5e, 0x84, 0xf9, 0x97, 0x9b, 0x7b, 0x8b, 0x6e, - 0x50, 0xdb, 0x21, 0xc8, 0xa4, 0xc3, 0x2e, 0x2e, 0xb3, 0x08, 0x17, 0xf4, 0xcb, 0x8b, 0x9f, 0xca, 0x34, 0x62, 0x17, - 0xec, 0x62, 0x42, 0xfd, 0xf7, 0xbf, 0xd4, 0xcc, 0xd4, 0xe8, 0x4c, 0xce, 0x21, 0xe9, 0x56, 0x98, 0xb1, 0x3e, 0xcc, - 0x26, 0x06, 0x43, 0x5e, 0xcf, 0xa5, 0xc8, 0x9e, 0x4f, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, 0x1b, 0x40, 0x9b, - 0xe6, 0xf9, 0x25, 0xbb, 0x88, 0xf0, 0x6f, 0x76, 0x97, 0xb8, 0x09, 0xfc, 0x66, 0x31, 0x9b, 0xb9, 0xdd, 0xfe, 0x9b, - 0x05, 0x0a, 0xcc, 0x77, 0x42, 0x27, 0x34, 0xef, 0x45, 0xf8, 0x37, 0x03, 0x97, 0xfc, 0x14, 0xfe, 0x83, 0x02, 0xd0, - 0xd9, 0xa3, 0x0e, 0x63, 0x8f, 0x3a, 0xe6, 0x2b, 0xcc, 0x73, 0x33, 0x1f, 0x5f, 0x64, 0xdd, 0x08, 0xff, 0xe6, 0xd0, - 0x71, 0x32, 0xa1, 0x1d, 0x40, 0xc7, 0xdf, 0x1c, 0x3a, 0xf6, 0x3a, 0xe3, 0x1e, 0x35, 0xdf, 0x16, 0x6b, 0x2e, 0x1f, - 0x66, 0x0c, 0x26, 0xf7, 0x9b, 0x45, 0xc8, 0x87, 0x0f, 0x2f, 0x2f, 0x1f, 0x3d, 0x82, 0x4f, 0xd3, 0x76, 0xf5, 0xa9, - 0xf4, 0xe3, 0xc2, 0x20, 0x59, 0x27, 0x3b, 0x03, 0x3a, 0xf9, 0x9b, 0x19, 0xe3, 0x64, 0x32, 0x61, 0x9d, 0x08, 0x17, - 0x7c, 0xce, 0x2c, 0x26, 0xd8, 0xdf, 0xa6, 0xa3, 0xd3, 0x5e, 0x96, 0x9f, 0xf6, 0x22, 0x5c, 0xbc, 0x7b, 0x61, 0x66, - 0xd3, 0x81, 0xd9, 0xfb, 0x2d, 0xe7, 0xb1, 0x66, 0x4e, 0xdf, 0xc2, 0x20, 0x61, 0xa5, 0xa1, 0xf2, 0xc7, 0x80, 0x1e, - 0x5e, 0x5c, 0x64, 0x39, 0x0c, 0xf4, 0x23, 0x74, 0x0b, 0x60, 0xfc, 0x68, 0x37, 0xdf, 0x98, 0x9e, 0x9f, 0xc3, 0x74, - 0x3f, 0x2e, 0x96, 0xe5, 0xe2, 0x75, 0x1a, 0x3d, 0x3a, 0x7d, 0xd8, 0xc9, 0xc7, 0x11, 0xfe, 0xe8, 0x26, 0x78, 0x9a, - 0x8d, 0x4f, 0x1f, 0x76, 0x23, 0xfc, 0xd1, 0xec, 0xb7, 0x87, 0xe3, 0x8b, 0x4b, 0x38, 0x37, 0x3e, 0xaa, 0x45, 0xf9, - 0x6e, 0x6a, 0x0a, 0x4c, 0xe8, 0x23, 0x68, 0xf6, 0x67, 0xb3, 0x1b, 0xf3, 0x2e, 0x6c, 0xe4, 0x8f, 0x66, 0x93, 0x19, - 0x3c, 0x79, 0xd8, 0x3d, 0xbf, 0x3c, 0x8f, 0xf0, 0x9c, 0xe7, 0x02, 0x08, 0xbc, 0xd9, 0x28, 0x8f, 0xba, 0x8f, 0x1e, - 0x76, 0x22, 0x3c, 0x7f, 0xa7, 0xb3, 0x5f, 0xe9, 0xdc, 0x50, 0xe3, 0x09, 0xc0, 0x6c, 0xce, 0x95, 0xbe, 0x7f, 0xab, - 0x1c, 0x3d, 0x66, 0xdd, 0x08, 0xcf, 0x65, 0x96, 0x51, 0xf5, 0xce, 0x26, 0x8c, 0xcf, 0x23, 0x2c, 0xe8, 0x17, 0xfa, - 0xa7, 0xf4, 0x9b, 0x29, 0x67, 0x34, 0x37, 0x69, 0x06, 0x87, 0x23, 0xfc, 0x3e, 0x87, 0xcb, 0xc8, 0x34, 0x9a, 0xe4, - 0x93, 0x73, 0x00, 0x0f, 0x10, 0x20, 0x8b, 0xdd, 0x00, 0x0d, 0xf8, 0xca, 0x9f, 0x8c, 0xd3, 0xe8, 0x62, 0x7c, 0xc9, - 0x7a, 0xa7, 0x11, 0xae, 0xa8, 0x11, 0x3d, 0x87, 0x7c, 0xf3, 0xf9, 0xab, 0xd9, 0x52, 0x67, 0x36, 0xc1, 0x00, 0x28, - 0xa7, 0x0f, 0x3b, 0xf9, 0x45, 0x84, 0x17, 0x6f, 0x98, 0xdf, 0x63, 0x8c, 0xb1, 0x4b, 0x80, 0x25, 0x24, 0x19, 0x04, - 0xba, 0x9c, 0x8c, 0x1f, 0x5d, 0x9a, 0x6f, 0x00, 0x03, 0x9d, 0x30, 0x06, 0x40, 0x5a, 0xbc, 0x61, 0x15, 0x20, 0xf2, - 0xf1, 0xc3, 0x0e, 0xd0, 0x97, 0x05, 0x5d, 0xd0, 0x7b, 0x7a, 0xfb, 0x7c, 0x61, 0xe6, 0x34, 0xc9, 0xcf, 0x23, 0xbc, - 0x78, 0xf9, 0xc3, 0x62, 0x39, 0x99, 0x98, 0x09, 0xd1, 0xf1, 0xa3, 0x08, 0x2f, 0x58, 0xb9, 0x84, 0x35, 0xba, 0x3c, - 0x3f, 0x9d, 0x44, 0xd8, 0xa1, 0x61, 0xd6, 0xc9, 0xc6, 0x70, 0xdb, 0xba, 0x9c, 0xa7, 0x51, 0x9e, 0xd3, 0x4e, 0x0e, - 0x77, 0xaf, 0xf2, 0xf6, 0xa7, 0xd2, 0xa2, 0x11, 0x33, 0xf8, 0xe0, 0xd6, 0x10, 0xe6, 0x0b, 0xf0, 0xf8, 0x75, 0xcc, - 0xb2, 0x8c, 0xba, 0xc4, 0x8b, 0x8b, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0x6f, 0xd5, 0xfd, 0xb8, 0x94, - 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xf6, 0xfe, 0x8d, 0xa1, 0xab, 0xdd, 0x8b, 0x47, 0xb0, 0x00, 0x8a, 0xe6, - 0xf9, 0x6b, 0x7b, 0xb8, 0x5d, 0x8e, 0xcf, 0xce, 0xbb, 0xa7, 0x11, 0xf6, 0x1b, 0x81, 0x5e, 0x76, 0x1e, 0xf6, 0xa0, - 0x84, 0xc8, 0xef, 0x6d, 0x89, 0xc9, 0x19, 0x3d, 0xbb, 0xe8, 0x44, 0xd8, 0x6f, 0x0d, 0x76, 0x39, 0x3e, 0x7f, 0x08, - 0x9f, 0x6a, 0xc6, 0x8a, 0xc2, 0xe0, 0xf7, 0x39, 0xc0, 0x45, 0xf1, 0x17, 0x82, 0xa6, 0x11, 0xed, 0x9c, 0xf7, 0x7a, - 0x39, 0x7c, 0x16, 0x5f, 0x58, 0x99, 0x46, 0x59, 0x07, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, 0x38, 0xc2, 0x06, 0xef, - 0x2e, 0xe8, 0xb9, 0xd9, 0xfb, 0x6e, 0x57, 0x75, 0x2e, 0x3b, 0xb0, 0x61, 0xdd, 0xa6, 0x72, 0x5f, 0x4a, 0xc8, 0x5b, - 0x47, 0x62, 0x69, 0x84, 0x03, 0x04, 0x9d, 0x3c, 0x9c, 0x44, 0xd8, 0xef, 0xb8, 0xb3, 0x8b, 0xcb, 0x1e, 0x90, 0x32, - 0x0d, 0x84, 0x22, 0xef, 0x8d, 0xcf, 0x80, 0x34, 0x69, 0xf6, 0xc6, 0xe2, 0x49, 0x84, 0xf5, 0x73, 0xa5, 0x5f, 0xa7, - 0x51, 0x7e, 0x39, 0x9e, 0xe4, 0x97, 0x11, 0xd6, 0x72, 0x4e, 0xb5, 0x34, 0x14, 0xf0, 0xf4, 0xec, 0x61, 0x84, 0x0d, - 0x9a, 0x77, 0x58, 0x27, 0xef, 0x44, 0xd8, 0x1d, 0x25, 0x8c, 0x5d, 0xf6, 0x60, 0x5a, 0xdf, 0xbf, 0xd4, 0x80, 0xcb, - 0x39, 0x1b, 0x9f, 0x46, 0xb8, 0xa2, 0xf7, 0x86, 0x10, 0xc1, 0x97, 0x9a, 0xcb, 0xcf, 0x8e, 0xf5, 0x00, 0x52, 0xe7, - 0x37, 0x3c, 0x2c, 0xc3, 0x8f, 0xb7, 0x16, 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, 0x6d, 0xf4, 0x33, 0x1a, 0x7b, 0xb6, 0x9d, - 0x93, 0xd5, 0x06, 0x57, 0x41, 0x5e, 0x3f, 0xb3, 0x7b, 0x15, 0x4b, 0x65, 0x38, 0xd9, 0x20, 0x45, 0x29, 0xe4, 0xdd, - 0x1a, 0x9c, 0xe7, 0x2a, 0x08, 0x92, 0x82, 0x74, 0xfa, 0xe2, 0xca, 0x7b, 0xd3, 0xf6, 0x05, 0x84, 0x7e, 0x80, 0xf4, - 0x92, 0x50, 0xa2, 0x21, 0x42, 0x8e, 0x15, 0x26, 0xbd, 0x93, 0x81, 0x91, 0x29, 0xa5, 0x75, 0x5b, 0xa0, 0x84, 0xfa, - 0xd8, 0xf8, 0xb1, 0xc4, 0x0a, 0xa2, 0x47, 0xa1, 0xbe, 0x24, 0x26, 0xd2, 0xf5, 0x2b, 0xa1, 0x63, 0xa9, 0x86, 0xe5, - 0x08, 0x77, 0x2f, 0x10, 0x86, 0x18, 0x12, 0x64, 0x28, 0xaf, 0xaf, 0xbb, 0x17, 0x47, 0x46, 0xe8, 0xbb, 0xbe, 0xbe, - 0xb4, 0x3f, 0xe0, 0xdf, 0x51, 0x1d, 0xb7, 0x1b, 0xc6, 0xf7, 0x91, 0xd5, 0x73, 0x7c, 0x6f, 0xf8, 0xeb, 0x8f, 0x6c, - 0xbd, 0x8e, 0x3f, 0x32, 0x02, 0x33, 0xc6, 0x1f, 0x59, 0x62, 0xee, 0x48, 0xac, 0x87, 0x10, 0x19, 0x82, 0xe6, 0xac, - 0x83, 0x21, 0x9a, 0xbc, 0xe7, 0xbc, 0x3f, 0xb2, 0x21, 0x6f, 0x7a, 0x97, 0xd7, 0x21, 0x9c, 0x8f, 0x8e, 0x56, 0x65, - 0xaa, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xad, 0x98, 0xa0, 0xeb, 0x20, 0xfa, 0x67, 0x03, 0x90, 0x52, 0x8c, 0xb2, - 0xc5, 0xf1, 0xd4, 0x3f, 0x82, 0xda, 0x03, 0xb4, 0x93, 0x83, 0x5a, 0xd9, 0x51, 0xe9, 0x2a, 0xf6, 0x2a, 0x30, 0xf6, - 0x26, 0x3a, 0x6d, 0xc7, 0xc9, 0x7f, 0xa2, 0xee, 0x78, 0xd7, 0x10, 0xcb, 0x7e, 0xdc, 0x2b, 0x96, 0xc1, 0x4a, 0x1a, - 0xd1, 0xec, 0xd0, 0xc6, 0x23, 0xd1, 0xc3, 0x87, 0x46, 0x30, 0xab, 0x83, 0xe4, 0xb5, 0x20, 0xa9, 0x0f, 0x52, 0xc8, - 0xa5, 0x91, 0xd2, 0x4a, 0x94, 0xe6, 0x3a, 0x2e, 0x41, 0x43, 0xe9, 0x15, 0x94, 0x55, 0x2c, 0xd7, 0x96, 0x01, 0x88, - 0xb2, 0x32, 0x9a, 0x95, 0xd5, 0xce, 0x41, 0x74, 0x01, 0x4d, 0x98, 0x91, 0x58, 0xa0, 0x01, 0x61, 0x1a, 0x10, 0xae, - 0x32, 0x88, 0x33, 0x2e, 0xfb, 0xcc, 0x64, 0x2b, 0x93, 0xad, 0xaa, 0x6c, 0xe9, 0xb3, 0xad, 0x90, 0x28, 0x4d, 0xb6, - 0xac, 0xb2, 0x41, 0x66, 0xc3, 0xd3, 0x54, 0xe1, 0x71, 0x2a, 0xad, 0xa8, 0x56, 0xcb, 0x56, 0x2f, 0x68, 0xa8, 0xcd, - 0x3d, 0x3a, 0x8a, 0x2b, 0x39, 0xc9, 0xa8, 0x89, 0x1f, 0xac, 0x78, 0x52, 0x1a, 0x19, 0x88, 0x27, 0x53, 0xf7, 0x77, - 0xbc, 0xd9, 0x96, 0x95, 0xca, 0xe9, 0xf8, 0x2b, 0x25, 0xd1, 0x1f, 0x5e, 0x89, 0xfa, 0x91, 0x9b, 0x28, 0x40, 0x57, - 0x24, 0xe9, 0x74, 0x4e, 0xbb, 0xa7, 0x9d, 0xcb, 0x01, 0x3f, 0xee, 0xf6, 0x92, 0x47, 0xbd, 0xd4, 0x28, 0x22, 0x16, - 0xf2, 0x16, 0x14, 0x30, 0x27, 0xbd, 0xe4, 0x0c, 0x1d, 0x77, 0x93, 0xce, 0xf9, 0x79, 0x1b, 0xfe, 0xc1, 0x4f, 0x74, - 0x55, 0xed, 0xac, 0x73, 0x76, 0x3e, 0xe0, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x82, 0x82, 0xe8, 0xc4, 0x54, 0xc2, 0x50, - 0xbf, 0x5e, 0xde, 0xd7, 0x3b, 0x7a, 0x9e, 0x27, 0x3a, 0x96, 0x56, 0x15, 0x07, 0x50, 0xf5, 0x5f, 0x53, 0x03, 0x44, - 0xff, 0x35, 0xae, 0x22, 0xf5, 0xae, 0x4a, 0x10, 0xb5, 0x3f, 0xf2, 0x58, 0xb4, 0xd8, 0x71, 0x6c, 0xf3, 0x35, 0xd4, - 0x6d, 0x43, 0xf4, 0x3c, 0x3c, 0x75, 0xb9, 0x2a, 0xcc, 0x9d, 0x22, 0xd4, 0x56, 0x90, 0x3b, 0x76, 0xb9, 0x32, 0xcc, - 0x1d, 0x23, 0xd4, 0x96, 0x90, 0x4b, 0x53, 0x9e, 0x50, 0xc8, 0xd1, 0x09, 0x6d, 0x1b, 0x48, 0xd6, 0x8b, 0xf2, 0x92, - 0xf9, 0x61, 0xf3, 0x09, 0x2c, 0x8f, 0x21, 0x28, 0x4e, 0x90, 0x16, 0xf0, 0xc2, 0x4a, 0xa5, 0xcd, 0xe9, 0xe0, 0x4a, - 0x8d, 0x03, 0x19, 0x2d, 0xf8, 0xe7, 0x98, 0x99, 0x67, 0x37, 0x3a, 0x83, 0xd3, 0x8b, 0x4e, 0xda, 0x05, 0x57, 0x71, - 0x90, 0xb5, 0x85, 0x95, 0xb5, 0x85, 0x97, 0xb5, 0x85, 0x97, 0xb5, 0x41, 0x80, 0x0f, 0xfa, 0xfe, 0x97, 0x6c, 0x98, - 0xdf, 0xf0, 0xca, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, 0xaa, 0x51, 0xaa, 0x5a, - 0xfd, 0xb9, 0x2a, 0xd3, 0x0e, 0x9e, 0xa6, 0xa0, 0xe5, 0xee, 0x60, 0x6a, 0x36, 0xb7, 0xa7, 0x0a, 0xdb, 0x51, 0x7c, - 0x06, 0x5e, 0x9d, 0x7c, 0x4d, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa6, 0xdc, 0xd2, 0x0c, 0x6e, 0x69, 0x06, 0xb7, 0x34, - 0x03, 0x1a, 0xc1, 0x55, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x86, 0xa7, 0x23, 0x08, 0x62, 0x18, 0x6b, 0x62, - 0x46, 0xbd, 0xd5, 0x79, 0x17, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1a, 0xf3, 0xdf, 0x0d, 0xb4, - 0x4f, 0xe0, 0x45, 0x9d, 0xc7, 0x3a, 0xee, 0x80, 0xe9, 0x4a, 0x54, 0x46, 0x03, 0x43, 0x16, 0x52, 0xa3, 0xb3, 0x71, - 0x26, 0xe9, 0x9f, 0xb7, 0x3c, 0x81, 0x2d, 0x25, 0x08, 0xdf, 0x91, 0xf8, 0xcc, 0xea, 0xd0, 0x04, 0x95, 0xc5, 0xad, - 0x33, 0x97, 0xb3, 0x47, 0x42, 0x1f, 0xcc, 0xe6, 0x7d, 0xcc, 0xab, 0x81, 0x20, 0x25, 0xc4, 0x7c, 0x4c, 0x4d, 0xa2, - 0x8b, 0xda, 0x0c, 0x4e, 0xcc, 0xe4, 0x0b, 0x35, 0x2e, 0x3d, 0xef, 0xed, 0x9f, 0xbf, 0x69, 0xe0, 0xf3, 0x58, 0x4e, - 0xc7, 0xde, 0x55, 0xf8, 0x93, 0x89, 0x6d, 0x44, 0x0e, 0x0f, 0xad, 0x45, 0xbb, 0xf9, 0xda, 0x36, 0x69, 0x37, 0x89, - 0x26, 0x1b, 0x76, 0xa8, 0x5f, 0xa3, 0x7f, 0x79, 0x8f, 0xbd, 0x72, 0x3a, 0x46, 0x01, 0xcd, 0x36, 0x60, 0x95, 0x35, - 0xb0, 0x94, 0xab, 0x57, 0x39, 0x72, 0x42, 0xef, 0x66, 0xcc, 0x9b, 0x72, 0x3a, 0xde, 0xfb, 0xf4, 0x8a, 0xed, 0x71, - 0xf0, 0x82, 0x06, 0x3d, 0x78, 0xd5, 0xf6, 0x8c, 0xdd, 0x7d, 0xab, 0xce, 0xe7, 0xbd, 0x75, 0x54, 0xf1, 0xad, 0x3a, - 0xaf, 0xf6, 0xd5, 0x99, 0xf3, 0xbb, 0xd8, 0xef, 0x1d, 0x1d, 0xa8, 0xb1, 0x8d, 0x99, 0xd4, 0x74, 0x0c, 0xb1, 0xf2, - 0xe1, 0xaf, 0x8d, 0x68, 0xd3, 0xf7, 0x24, 0x1c, 0x56, 0x41, 0x0e, 0x92, 0xf3, 0x94, 0x61, 0x4a, 0x7a, 0xc7, 0xa5, - 0x89, 0x69, 0x23, 0x12, 0xda, 0x56, 0x09, 0xc5, 0x05, 0x89, 0x63, 0x7a, 0x9c, 0x41, 0x64, 0x9e, 0xee, 0x80, 0xa6, - 0x31, 0x6d, 0x65, 0xe8, 0x24, 0xee, 0xb6, 0xe8, 0x71, 0x86, 0x50, 0xab, 0x0b, 0x3a, 0x53, 0x49, 0xba, 0xed, 0x02, - 0x62, 0x75, 0x1a, 0x52, 0x5c, 0x1c, 0x8b, 0xa4, 0x6c, 0xc9, 0x63, 0x95, 0x94, 0xad, 0xe4, 0x1c, 0x8b, 0x64, 0x5a, - 0x25, 0x4f, 0x4d, 0xf2, 0xd4, 0x26, 0x8f, 0xab, 0xe4, 0xb1, 0x49, 0x1e, 0xdb, 0x64, 0x4a, 0xca, 0x63, 0x91, 0xd0, - 0x56, 0xdc, 0x6d, 0x97, 0xe8, 0x18, 0x46, 0xe0, 0x47, 0x4f, 0x44, 0x18, 0x22, 0x7d, 0x63, 0x6c, 0x8c, 0x16, 0xb2, - 0x70, 0x41, 0x4b, 0x6b, 0x20, 0x55, 0x8e, 0x5f, 0x50, 0xe7, 0x75, 0x00, 0x26, 0xac, 0xed, 0x1f, 0x1f, 0x92, 0x6f, - 0x93, 0x15, 0x52, 0x04, 0x8e, 0x6d, 0x60, 0x8b, 0xff, 0xd9, 0xb9, 0xf3, 0x00, 0x54, 0x37, 0xb4, 0x58, 0xcc, 0xe8, - 0x8e, 0xf7, 0x70, 0x39, 0x1d, 0xbb, 0x9d, 0x55, 0x35, 0xc3, 0x68, 0x69, 0x43, 0x5d, 0x37, 0xfd, 0x3c, 0x01, 0xd4, - 0xde, 0xb7, 0x34, 0xa1, 0x46, 0x49, 0x6e, 0x6b, 0x4c, 0x4b, 0x76, 0xaf, 0x32, 0x5a, 0xb0, 0xb8, 0x3e, 0x80, 0xeb, - 0x61, 0x32, 0xf2, 0x0c, 0x3c, 0x02, 0xca, 0xe3, 0xe4, 0xb4, 0xa5, 0x93, 0xe9, 0x71, 0x72, 0xfe, 0xa8, 0xa5, 0x93, - 0xf1, 0x71, 0xd2, 0xed, 0xd6, 0x38, 0x9b, 0x94, 0x44, 0x27, 0x53, 0xa2, 0x41, 0x63, 0x68, 0x1b, 0x95, 0x0b, 0x0a, - 0x26, 0x6e, 0xff, 0xc1, 0x30, 0x5a, 0x6e, 0x18, 0x82, 0x4d, 0x6d, 0xd4, 0xcf, 0x9d, 0x31, 0x84, 0xdd, 0xf4, 0xce, - 0xcf, 0xdb, 0x3a, 0x29, 0xb1, 0xb6, 0x2b, 0xd9, 0xd6, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x6d, 0x9d, 0x8c, 0x6d, 0x53, - 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0x97, 0x2c, 0x80, 0x7c, 0xcf, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, 0xf8, 0xad, 0x72, - 0x6d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xbb, 0x75, 0x93, 0xec, 0xdf, 0x97, 0xad, 0x9a, 0x2d, - 0xa5, 0x6e, 0x16, 0x7c, 0xde, 0xc0, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x7f, 0x52, 0x12, 0x43, 0x6c, 0x3f, 0x73, 0x0a, - 0x71, 0xe2, 0xf5, 0xc8, 0x90, 0xc4, 0x5b, 0xad, 0x0d, 0x8a, 0x83, 0xf3, 0xf6, 0x55, 0x48, 0x55, 0x77, 0x02, 0xfe, - 0x11, 0x12, 0x2d, 0x85, 0x35, 0x09, 0xcd, 0xa3, 0x9a, 0x16, 0xbf, 0x73, 0xda, 0xdd, 0xc6, 0x01, 0x71, 0x74, 0xb4, - 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xed, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, 0x98, 0x07, 0x88, - 0xe2, 0x43, 0x6f, 0x3d, 0x34, 0x14, 0x7e, 0x58, 0xc7, 0x1d, 0x74, 0x39, 0xed, 0x0b, 0x93, 0x61, 0xfa, 0x1a, 0x05, - 0x63, 0x7b, 0x10, 0x4e, 0xa8, 0xb2, 0x95, 0xfc, 0xb7, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, 0x46, 0xff, 0x0c, - 0x2d, 0x93, 0x6b, 0xd8, 0x38, 0x9f, 0xf4, 0xf5, 0xba, 0xf1, 0x3c, 0x91, 0x7d, 0x04, 0x07, 0x1d, 0x1d, 0x71, 0xf5, - 0x02, 0x8c, 0xa9, 0x59, 0xdc, 0x0a, 0x0f, 0xdf, 0xbf, 0x1a, 0xa7, 0xf5, 0x9f, 0xe6, 0x5c, 0x4d, 0x83, 0x83, 0xee, - 0x71, 0x23, 0x7f, 0xef, 0x4a, 0x0c, 0x74, 0xca, 0xdd, 0x5a, 0x3f, 0xa9, 0x4d, 0xd5, 0x77, 0x1e, 0xca, 0x3a, 0x3a, - 0xe2, 0x75, 0xb8, 0xaa, 0xe8, 0xbb, 0x08, 0x0d, 0x8c, 0x0c, 0xf2, 0xa2, 0x90, 0x14, 0x6e, 0x44, 0xe1, 0x8a, 0x21, - 0x6d, 0xf1, 0x13, 0x8d, 0x7f, 0x90, 0xff, 0x8f, 0x1a, 0x39, 0xd6, 0x69, 0x8b, 0x07, 0x02, 0x58, 0xc8, 0x0a, 0xd5, - 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1d, 0xe6, 0x74, 0xb1, 0x28, 0xee, 0xcd, 0x5b, 0x61, 0x01, 0x47, - 0x55, 0x5f, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x04, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xea, 0x72, 0x5b, 0x20, - 0x90, 0xcc, 0x14, 0x91, 0xed, 0x6e, 0x5f, 0x5d, 0x83, 0x5c, 0xd6, 0x6e, 0x23, 0xed, 0x82, 0x97, 0x63, 0x0e, 0x32, - 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, 0x0c, 0x68, 0x84, - 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xd2, 0x77, 0xfc, 0x95, 0x96, 0xca, 0xa1, 0x1a, 0x8d, 0x70, 0x69, - 0x9e, 0xc7, 0xa8, 0xe6, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, 0x33, 0x72, 0x6d, - 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbf, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x63, 0x2e, 0x0a, 0x9d, 0xbc, 0xc9, 0xae, 0x44, - 0xbf, 0xd5, 0x62, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, 0xc5, 0x6c, 0x04, - 0x3e, 0x08, 0x0d, 0xde, 0x48, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xaa, 0x9f, 0x2a, 0x94, - 0x6c, 0x6d, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x57, 0xef, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, 0x9b, 0x60, 0x00, - 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8a, 0x13, 0x60, 0x6f, 0x6e, - 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x82, 0x1c, 0x3d, 0x22, 0xd0, 0xb9, 0xfd, 0x59, 0xd3, 0x85, 0x5a, - 0x26, 0xae, 0xc6, 0xf8, 0xcf, 0xe0, 0x36, 0x6f, 0x18, 0x7d, 0xfa, 0x64, 0x36, 0xf9, 0xa7, 0x4f, 0x11, 0x0e, 0x8d, - 0xeb, 0xa3, 0x80, 0x17, 0x8c, 0x46, 0x55, 0x68, 0x2d, 0xb3, 0xf1, 0xdb, 0xdd, 0xba, 0xb1, 0x8f, 0xb4, 0xc6, 0x3b, - 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x90, 0x03, 0xbc, 0xd9, 0x90, 0x8f, 0xfa, 0x0f, 0x62, 0x85, 0x8e, 0x8e, - 0x1e, 0xc4, 0x12, 0x0d, 0x6e, 0x98, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x21, 0x37, 0xc3, 0x97, 0x01, 0x02, 0xdc, 0xb0, - 0x6d, 0xc9, 0xe6, 0x9d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0x3e, 0x08, 0xa1, - 0xdd, 0x67, 0x84, 0x01, 0x0b, 0x5f, 0xf9, 0x0a, 0xb2, 0x64, 0xce, 0xca, 0x29, 0x2b, 0xd7, 0xeb, 0x8f, 0xd4, 0xfa, - 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xfd, 0x56, 0x8b, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x47, 0xf8, 0xf0, 0x41, 0x5c, 0x22, - 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0xd6, 0x58, 0x97, 0x12, 0x55, 0x8d, 0x14, 0xa4, 0x83, 0x67, 0x24, - 0xab, 0xd6, 0xe8, 0x6a, 0xd6, 0x6f, 0xb5, 0x0a, 0x24, 0xe3, 0x6c, 0x58, 0x8c, 0x30, 0xc7, 0x25, 0x5c, 0xa6, 0xee, - 0xae, 0xc3, 0x82, 0x35, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x49, 0x37, 0xe1, 0xee, 0xa6, 0x01, 0x91, - 0xd8, 0x07, 0x64, 0x61, 0x81, 0xac, 0x3c, 0x90, 0x85, 0x01, 0xb2, 0x42, 0x83, 0x05, 0x04, 0x6d, 0x52, 0x28, 0xdd, - 0xa1, 0xe8, 0xcd, 0xf0, 0xa2, 0xce, 0x75, 0x05, 0x73, 0x13, 0xe1, 0xc2, 0x2d, 0x07, 0xb8, 0xb1, 0xb8, 0xb9, 0x2b, - 0xb2, 0x8a, 0x22, 0x13, 0x69, 0x17, 0xdf, 0x99, 0x3f, 0xc9, 0x1d, 0xbe, 0xb7, 0x3f, 0xee, 0x03, 0x65, 0xd2, 0x87, - 0x86, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xf9, 0xee, 0x9c, 0xb2, 0xe1, - 0x30, 0x44, 0x8b, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xfb, 0xef, 0x11, 0x1a, 0x08, 0x88, 0x66, 0xe4, 0x4e, 0xb6, 0x76, - 0x17, 0xb5, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0xd4, 0x51, 0xd6, 0x1a, - 0xc3, 0x30, 0x83, 0xaa, 0xc3, 0x7f, 0x5c, 0xaf, 0xb6, 0x83, 0x2d, 0x19, 0xa8, 0x0a, 0x13, 0xe9, 0x06, 0xd9, 0x87, - 0xd8, 0x18, 0x61, 0x47, 0x47, 0x6c, 0x28, 0x46, 0xc1, 0xcb, 0x6a, 0xb5, 0x05, 0x89, 0x0e, 0x17, 0x2e, 0xce, 0x20, - 0xda, 0xfd, 0x7a, 0x6d, 0xff, 0x92, 0x5f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0x67, 0xac, 0xd8, 0x2f, 0x8b, 0x25, - 0x5a, 0x7e, 0x00, 0xcb, 0x3e, 0x17, 0xbb, 0x90, 0xbb, 0xa9, 0x76, 0x2b, 0x17, 0x1c, 0xa3, 0x51, 0x08, 0x22, 0x07, - 0xd7, 0x47, 0x1a, 0x5e, 0xe8, 0x30, 0xaf, 0x11, 0x01, 0xb8, 0x50, 0x55, 0x20, 0x57, 0x38, 0x52, 0x12, 0xb0, 0xf4, - 0x36, 0x74, 0x12, 0x7e, 0x34, 0xa9, 0xa4, 0x63, 0x21, 0x01, 0x0a, 0x1c, 0x99, 0xcb, 0x79, 0x13, 0xa8, 0x9f, 0xa1, - 0x3d, 0x44, 0x2e, 0x30, 0xa1, 0x69, 0xca, 0x96, 0x2e, 0xa2, 0x56, 0x34, 0x97, 0x4b, 0xc5, 0x96, 0x0b, 0x38, 0xdf, - 0xab, 0xb4, 0xac, 0xe0, 0xd9, 0xe7, 0x66, 0x0a, 0x18, 0x44, 0xde, 0xe9, 0x39, 0x13, 0xcb, 0xc8, 0xcd, 0xf3, 0xb5, - 0x15, 0xf7, 0xdf, 0xbe, 0xc2, 0x1f, 0x49, 0xef, 0xf8, 0x35, 0xfe, 0x8b, 0x92, 0x8f, 0xad, 0xd7, 0x78, 0xca, 0x89, - 0xe5, 0x0d, 0x92, 0xb7, 0x6f, 0x6e, 0x5e, 0xbd, 0x7f, 0xf5, 0xf1, 0xf9, 0xa7, 0x57, 0xaf, 0x5f, 0xbc, 0x7a, 0xfd, - 0xea, 0xfd, 0xaf, 0xf8, 0x5f, 0x94, 0xbc, 0x3e, 0xe9, 0x5e, 0x76, 0xf0, 0x07, 0xf2, 0xfa, 0xa4, 0x87, 0xef, 0x34, - 0x79, 0x7d, 0x72, 0x86, 0x67, 0x8a, 0xbc, 0x3e, 0xee, 0x9d, 0x9c, 0xe2, 0xa5, 0xb6, 0x4d, 0x16, 0x72, 0xda, 0xed, - 0xe0, 0xbf, 0xdc, 0x17, 0x88, 0xf7, 0x81, 0x1b, 0x0e, 0xdb, 0x32, 0x7e, 0x30, 0x65, 0xe8, 0x58, 0x19, 0x43, 0x94, - 0xab, 0x00, 0x9d, 0x72, 0x15, 0xa2, 0x93, 0x0d, 0x25, 0x0d, 0x36, 0x8c, 0x80, 0x56, 0x9c, 0xb8, 0x76, 0xf8, 0x49, - 0x97, 0x9d, 0x02, 0x7d, 0xe2, 0x95, 0x70, 0x5c, 0xa9, 0x70, 0xba, 0x4e, 0x8b, 0x31, 0x29, 0xa4, 0x2c, 0xe3, 0x25, - 0x30, 0x02, 0x46, 0x6b, 0xc1, 0x4f, 0xaa, 0x98, 0x55, 0xe2, 0x8a, 0x74, 0x07, 0xdd, 0x54, 0x5c, 0x91, 0xde, 0xa0, - 0x07, 0x7f, 0xce, 0x07, 0xe7, 0x69, 0xb7, 0x83, 0x8e, 0x83, 0x71, 0xfc, 0xd0, 0x40, 0xeb, 0xe1, 0x08, 0xbb, 0x2e, - 0xd4, 0x5f, 0xa5, 0xf6, 0x2a, 0x3d, 0xe1, 0xd4, 0xb1, 0xdd, 0xbe, 0xb8, 0x62, 0x46, 0x0f, 0xcb, 0xbf, 0x03, 0xd4, - 0x36, 0x6e, 0x35, 0xd5, 0xc6, 0x71, 0xbf, 0xf8, 0x89, 0x40, 0x8d, 0xc0, 0x38, 0x31, 0x5b, 0x77, 0x10, 0x30, 0x8d, - 0x26, 0x1b, 0xcc, 0x81, 0x12, 0x25, 0x4b, 0xed, 0x83, 0xfb, 0xab, 0xb6, 0x44, 0xc9, 0x42, 0x2e, 0xe2, 0x86, 0xaa, - 0xe1, 0xa7, 0xc0, 0xcc, 0xf1, 0x90, 0xab, 0xd7, 0xf4, 0x75, 0xdc, 0xe0, 0x79, 0x42, 0xd6, 0x2e, 0xdc, 0x16, 0xff, - 0x74, 0x56, 0x14, 0x0d, 0x70, 0x55, 0x80, 0xf5, 0xa3, 0x6a, 0xeb, 0x2b, 0x78, 0xc5, 0x90, 0xb5, 0xf4, 0x35, 0x09, - 0xa8, 0xe7, 0xcf, 0x95, 0x19, 0x57, 0xa5, 0x8c, 0xf6, 0x8a, 0x68, 0x63, 0x16, 0xe4, 0x15, 0xd1, 0x57, 0xca, 0x00, - 0x41, 0x12, 0x3e, 0x14, 0x23, 0x38, 0xf0, 0xed, 0x00, 0xa5, 0xa1, 0x73, 0xa0, 0x56, 0xaa, 0xcd, 0x84, 0xcc, 0xa7, - 0x09, 0xd1, 0x00, 0x9a, 0xa7, 0x5a, 0x05, 0x65, 0x3e, 0xb1, 0x44, 0xc1, 0xd0, 0x7f, 0x0b, 0x37, 0xc0, 0x71, 0x6c, - 0x50, 0x31, 0xb4, 0xab, 0x11, 0xcd, 0xfc, 0xee, 0x65, 0xe7, 0xe4, 0x75, 0x90, 0xbf, 0x54, 0xde, 0xde, 0xe3, 0xcf, - 0x80, 0x92, 0xdb, 0xa0, 0x62, 0x5d, 0xec, 0xe3, 0xc1, 0xf5, 0x43, 0x80, 0x1c, 0x6b, 0x74, 0x62, 0x1e, 0x74, 0xec, - 0x23, 0x7d, 0x4c, 0xba, 0x1d, 0x08, 0xe2, 0xb6, 0x87, 0xf2, 0xfd, 0xbc, 0x05, 0x53, 0x9d, 0xdc, 0xb5, 0x81, 0x56, - 0xc3, 0x1b, 0x4f, 0xf7, 0x6d, 0x9e, 0xdc, 0x63, 0x15, 0xe0, 0x0c, 0x3b, 0x66, 0x2d, 0x71, 0x2c, 0x90, 0x0b, 0x7e, - 0x6b, 0x37, 0x80, 0xa6, 0xa2, 0x67, 0xdf, 0x1a, 0xf4, 0xc6, 0x51, 0x57, 0xed, 0xe4, 0xfc, 0xf8, 0xf5, 0xd1, 0x51, - 0x2c, 0x5b, 0xe4, 0x23, 0xc2, 0x2b, 0x0a, 0x36, 0xdb, 0xe0, 0x7b, 0xc7, 0x2d, 0x13, 0x9f, 0xaa, 0x80, 0x3a, 0x4e, - 0x54, 0xe3, 0x58, 0xab, 0x3b, 0xab, 0x76, 0x83, 0x1f, 0x53, 0x0f, 0xb5, 0x82, 0x34, 0x3b, 0xba, 0x5e, 0x03, 0xca, - 0x0d, 0x47, 0x39, 0xd8, 0x96, 0xad, 0xbf, 0x28, 0xfa, 0xee, 0x63, 0xfb, 0x75, 0x30, 0xe1, 0x86, 0x69, 0xd2, 0xc7, - 0xd6, 0x47, 0xf4, 0xdd, 0xc7, 0xc0, 0xd5, 0x91, 0xd7, 0xec, 0x89, 0xe7, 0x46, 0x7e, 0xb6, 0x5c, 0xe9, 0xcf, 0x20, - 0xd9, 0x97, 0xe4, 0x67, 0xc0, 0x72, 0x4a, 0x7e, 0x8e, 0x65, 0x1b, 0x42, 0x40, 0x92, 0x9f, 0xe3, 0x12, 0x7e, 0x14, - 0xe4, 0xe7, 0x18, 0xb0, 0x1d, 0xcf, 0xcc, 0x8f, 0xb2, 0x02, 0x06, 0xb8, 0xd7, 0x49, 0xeb, 0x65, 0x57, 0xae, 0xd7, - 0xe2, 0xe8, 0x48, 0xda, 0x5f, 0xf4, 0x3a, 0x3b, 0x3a, 0x2a, 0xae, 0x66, 0x75, 0xdf, 0x5c, 0xef, 0xa3, 0x2f, 0x06, - 0xa1, 0x70, 0x60, 0x9a, 0xc6, 0xc3, 0x19, 0x7f, 0xdf, 0xa0, 0xac, 0xd0, 0x40, 0xfb, 0xb4, 0xf7, 0xf0, 0xe2, 0x12, - 0xc3, 0xbf, 0x0f, 0x83, 0x82, 0x3a, 0xf3, 0x13, 0x23, 0x5d, 0xd6, 0xbe, 0xa8, 0xeb, 0x5c, 0x07, 0xf8, 0x8c, 0x19, - 0x6a, 0x8b, 0xa3, 0x23, 0x7e, 0x15, 0xe0, 0x32, 0x66, 0xa8, 0x15, 0x58, 0xec, 0x3d, 0xae, 0xec, 0xc9, 0x0c, 0xd7, - 0x04, 0x8f, 0xfb, 0xf2, 0x61, 0x39, 0xba, 0xd2, 0x8e, 0x9a, 0x84, 0x21, 0xc0, 0x15, 0xe9, 0xb8, 0x4d, 0xd6, 0x17, - 0x6d, 0x75, 0xdd, 0xed, 0x23, 0x49, 0x54, 0x4b, 0x5c, 0x5f, 0x77, 0x31, 0xa8, 0xe4, 0x07, 0x8a, 0xc8, 0x54, 0x10, - 0xef, 0xa6, 0xb8, 0x2a, 0x64, 0xaa, 0xf0, 0x8c, 0xa7, 0xc2, 0xcb, 0xd9, 0x6f, 0xbc, 0xf5, 0xb4, 0x71, 0x1c, 0x35, - 0x3d, 0x33, 0x2c, 0x06, 0xaa, 0x72, 0x78, 0x84, 0x4d, 0xaa, 0x46, 0xf0, 0x76, 0x62, 0x85, 0x79, 0xcc, 0x7a, 0xf9, - 0x31, 0x88, 0x4d, 0xad, 0x5a, 0x5d, 0xc8, 0x84, 0xcf, 0x4d, 0xaa, 0x60, 0xa0, 0xa6, 0xf0, 0x15, 0x84, 0x3d, 0xcc, - 0x6a, 0xc3, 0x6c, 0xdf, 0x30, 0x14, 0x10, 0x50, 0xe0, 0x9a, 0xb0, 0x40, 0x82, 0xe7, 0x59, 0x83, 0x70, 0x34, 0xc9, - 0x85, 0x9d, 0xdc, 0x95, 0x82, 0xee, 0xc4, 0xe8, 0x4a, 0xf7, 0x91, 0x68, 0xb5, 0x1c, 0xb7, 0x7d, 0x2d, 0xcc, 0x20, - 0xda, 0xdd, 0xd1, 0x35, 0xeb, 0x23, 0xd5, 0x6e, 0x57, 0x06, 0x90, 0xd7, 0x9d, 0xf5, 0x5a, 0x5d, 0xf9, 0x46, 0x06, - 0xfe, 0x1c, 0x37, 0x7c, 0x97, 0x17, 0x3c, 0x7f, 0x93, 0x64, 0x18, 0x01, 0x55, 0x05, 0x3e, 0x5b, 0x2e, 0x22, 0x1c, - 0x99, 0x67, 0xf5, 0xe0, 0xaf, 0x79, 0x0e, 0x2d, 0xc2, 0x91, 0x7b, 0x69, 0x2f, 0x1a, 0xd5, 0x83, 0x15, 0x59, 0x15, - 0x24, 0x9e, 0x27, 0x9f, 0x80, 0x71, 0xd0, 0x7f, 0x2a, 0xb4, 0xaa, 0x7f, 0x27, 0x85, 0x0b, 0x97, 0xa2, 0xfc, 0xe3, - 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, 0x8d, 0xd7, 0x27, 0xbb, 0xee, - 0xd1, 0xf3, 0x55, 0xd5, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0xbf, 0xc9, 0xbd, 0x2f, 0x20, 0x47, 0x9f, 0xa4, 0x78, - 0x46, 0x35, 0x8d, 0x5a, 0x0f, 0x8c, 0xe1, 0x9b, 0x95, 0xb3, 0xfa, 0x5f, 0x1b, 0x07, 0xfb, 0x8f, 0xba, 0x87, 0x00, - 0x16, 0x8d, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, 0x3c, 0xfc, 0x18, 0x29, 0xb8, - 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x86, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, 0xe3, 0xef, 0x06, 0x85, 0x5c, - 0xf7, 0x42, 0x35, 0x89, 0x69, 0xdd, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xea, 0xde, 0x8d, 0x84, 0x52, 0xbf, - 0x6b, 0x67, 0xde, 0x26, 0x6d, 0x77, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, 0xbc, 0x87, 0x55, 0xd0, 0xae, - 0x6b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xaf, 0xdc, 0xcb, 0x74, 0x7c, 0x28, 0x47, 0x9b, 0xea, 0x9d, 0xba, - 0x00, 0x0f, 0xea, 0x91, 0xaa, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x0d, 0xfd, 0x10, 0xff, 0x1b, 0x0e, 0xf8, 0x1a, - 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0x7e, 0x2f, 0x43, 0x47, 0xdd, 0xa6, 0x4e, 0xc5, - 0xfa, 0xc2, 0x36, 0x15, 0x2b, 0x55, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, 0x59, 0xf7, 0xe8, 0xd4, 0x63, - 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x17, 0x25, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x0c, 0x5f, 0x55, 0x1e, 0xc2, 0x3d, - 0x61, 0xc5, 0x73, 0x56, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, 0x3a, 0x16, 0x26, 0xb6, 0x84, - 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, 0xb0, 0xa2, 0xf0, 0xd2, 0x49, - 0x66, 0x41, 0x5f, 0xfb, 0xfa, 0x10, 0xf5, 0x94, 0x07, 0xb1, 0xd1, 0xf7, 0xbe, 0xe7, 0x73, 0x26, 0x97, 0xf0, 0x78, - 0x13, 0x66, 0x44, 0x31, 0xed, 0xbf, 0x81, 0x82, 0xc0, 0x0b, 0x40, 0x3c, 0xc4, 0x47, 0xe0, 0xab, 0x3c, 0xad, 0x2b, - 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0x83, 0x08, 0xbc, 0x88, 0x40, 0x84, 0x22, 0x24, 0x62, 0x22, 0x8f, - 0x06, 0x91, 0x71, 0xc9, 0x8a, 0xc0, 0x6a, 0x0c, 0x94, 0xdc, 0x11, 0x9e, 0xaa, 0x9a, 0x88, 0x85, 0x35, 0x75, 0x50, - 0x89, 0xa5, 0xc6, 0x4c, 0xfb, 0xa4, 0x57, 0x83, 0x90, 0x66, 0xdb, 0x82, 0xb2, 0xde, 0x52, 0x17, 0x60, 0x49, 0x8c, - 0xe9, 0x2d, 0x4f, 0x3e, 0x01, 0x37, 0xc7, 0x72, 0x57, 0x74, 0xc5, 0x6f, 0x40, 0x3d, 0x9d, 0x96, 0xf8, 0x93, 0x61, - 0xd8, 0xf2, 0x94, 0x6e, 0x08, 0xc7, 0x19, 0x29, 0x13, 0x7a, 0x07, 0xb1, 0x35, 0xe6, 0x5c, 0xa4, 0x05, 0x9e, 0xd3, - 0xbb, 0x74, 0x86, 0xe7, 0x5c, 0x3c, 0xb3, 0xcb, 0x9e, 0xe6, 0x90, 0xe4, 0x3f, 0x96, 0x1b, 0x62, 0x9e, 0x06, 0xfb, - 0xa0, 0x58, 0xf9, 0x04, 0x78, 0x15, 0x15, 0xa3, 0x7e, 0x6e, 0x6c, 0xca, 0xb9, 0xae, 0x8d, 0xd7, 0xdf, 0xe8, 0x98, - 0xe2, 0x0c, 0x17, 0x28, 0x29, 0x24, 0x66, 0x03, 0x91, 0xbe, 0x81, 0xb8, 0xda, 0x19, 0xb6, 0xcf, 0x8a, 0xf1, 0x3b, - 0x56, 0xbc, 0x90, 0xe5, 0x47, 0xb3, 0xe5, 0x0b, 0x04, 0x85, 0xc0, 0x45, 0x45, 0xb4, 0xe1, 0x76, 0x6f, 0x39, 0x90, - 0x75, 0x53, 0xf4, 0xce, 0x36, 0xe5, 0x86, 0x38, 0x83, 0x80, 0xc4, 0xc9, 0x8c, 0xb7, 0xba, 0x98, 0x0d, 0x3a, 0xdf, - 0x68, 0x74, 0x86, 0xaa, 0x92, 0x08, 0xc3, 0x5a, 0xb5, 0x55, 0x2a, 0x89, 0x68, 0x2b, 0x27, 0xe1, 0xad, 0x0c, 0xb0, - 0x53, 0x85, 0x33, 0xb9, 0x14, 0x3a, 0x95, 0x01, 0xde, 0x64, 0xf5, 0xe6, 0x5a, 0xdd, 0x59, 0x88, 0x69, 0x7c, 0x6f, - 0x7f, 0x30, 0xfc, 0xc9, 0xa8, 0xf8, 0xdf, 0x81, 0x61, 0x8f, 0x4a, 0x05, 0xc0, 0x0f, 0x0c, 0x67, 0x01, 0x72, 0x96, - 0x9f, 0xbc, 0x03, 0xf0, 0x59, 0x16, 0xf2, 0x1e, 0x52, 0x99, 0x49, 0xbd, 0x87, 0x54, 0x06, 0xa9, 0xc6, 0xa3, 0xfe, - 0x50, 0xd4, 0xca, 0xa2, 0xb0, 0x41, 0xa2, 0x70, 0xa5, 0x0e, 0x96, 0x44, 0x24, 0xd0, 0xae, 0x11, 0xe5, 0xe6, 0x5c, - 0x40, 0x68, 0x45, 0x68, 0xdc, 0x7e, 0xd3, 0x3b, 0xf8, 0xbe, 0xb7, 0xf9, 0xcc, 0xe7, 0xdf, 0xdb, 0x7c, 0xd3, 0x91, - 0xc7, 0xf8, 0xe6, 0x6d, 0xa7, 0xb1, 0x8c, 0x97, 0x0e, 0x6b, 0x3f, 0x54, 0x0f, 0xd9, 0x74, 0xcc, 0x83, 0xe1, 0xa4, - 0x8b, 0xe7, 0x01, 0x52, 0xb6, 0x6b, 0x1e, 0xae, 0x87, 0xbb, 0x9d, 0xe3, 0x98, 0xb7, 0x49, 0x17, 0xa1, 0x63, 0x27, - 0x5c, 0x89, 0xd8, 0x48, 0x4e, 0xc7, 0x1f, 0x4f, 0xe0, 0xee, 0x65, 0xac, 0xb6, 0x7c, 0xa5, 0x6c, 0xb5, 0x76, 0xb7, - 0x73, 0xcc, 0xf7, 0x56, 0x69, 0x75, 0xf1, 0x9c, 0x91, 0x15, 0x78, 0xa0, 0xd1, 0xd2, 0xaa, 0x1a, 0xc0, 0x65, 0xf5, - 0x95, 0xf8, 0x79, 0x49, 0x73, 0xf3, 0x7d, 0x6c, 0x53, 0xde, 0x2c, 0xb5, 0x4f, 0x6a, 0x73, 0x18, 0x44, 0x0f, 0xb9, - 0x92, 0x41, 0x4e, 0xcc, 0x4f, 0x48, 0x72, 0x8e, 0xae, 0xba, 0x83, 0xe4, 0xfc, 0x98, 0x1f, 0xf3, 0x14, 0x78, 0xd8, - 0xb8, 0xed, 0x2b, 0xb4, 0xbb, 0xbe, 0xce, 0xd3, 0xe5, 0x98, 0x67, 0xae, 0xf9, 0xba, 0x83, 0x2a, 0xd5, 0xce, 0x11, - 0xb2, 0x00, 0xc5, 0x7c, 0x2f, 0x41, 0x76, 0xb3, 0x9b, 0x63, 0x9e, 0x42, 0x3f, 0x50, 0xab, 0x67, 0x6b, 0x55, 0x83, - 0xfb, 0x79, 0x09, 0x08, 0xe6, 0x3b, 0x6a, 0xcc, 0xc5, 0xa6, 0xb7, 0xe3, 0xba, 0xb3, 0x63, 0x5e, 0x8f, 0x30, 0x2c, - 0xb3, 0xdb, 0x9f, 0x9f, 0x5a, 0xdd, 0xe5, 0x71, 0x00, 0x91, 0x9f, 0x97, 0x5c, 0x84, 0x9d, 0x86, 0xdd, 0xba, 0x9c, - 0xb0, 0xd3, 0xe6, 0x2c, 0x83, 0x22, 0xbb, 0xbd, 0xee, 0xcc, 0xb4, 0x39, 0xdb, 0x1b, 0x70, 0x24, 0x84, 0x49, 0x99, - 0x95, 0xce, 0xa4, 0x8a, 0xf9, 0xf1, 0x07, 0xe4, 0x5a, 0x7f, 0xb3, 0xd4, 0x3e, 0xbf, 0x42, 0x04, 0xc8, 0xae, 0xbb, - 0xae, 0xaa, 0x43, 0x1f, 0x55, 0x13, 0xaf, 0x8f, 0x79, 0xb0, 0x72, 0xcf, 0xef, 0x16, 0x32, 0xf5, 0xf8, 0x3a, 0xe8, - 0xa4, 0x3b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, 0xbb, 0xbd, 0x83, 0x92, 0xe1, 0xc4, 0x7d, 0xe9, - 0x0f, 0xcc, 0x5e, 0x37, 0xf0, 0xab, 0xe4, 0x1c, 0xa6, 0xbe, 0xdd, 0xc3, 0x71, 0x0f, 0xfa, 0x30, 0x70, 0xd8, 0x6e, - 0xd0, 0x67, 0xd6, 0x10, 0x79, 0xca, 0x4b, 0x8b, 0x67, 0xd7, 0xa4, 0x3b, 0xe0, 0xa9, 0xdb, 0x4c, 0x46, 0x34, 0xea, - 0xb6, 0x79, 0x30, 0x33, 0xc0, 0x2f, 0x57, 0x36, 0x2c, 0xe2, 0xd7, 0x29, 0x80, 0x92, 0x2f, 0x56, 0xaf, 0x4f, 0x0d, - 0xaf, 0x66, 0xc3, 0xe9, 0x76, 0xba, 0x5f, 0x37, 0xb8, 0xdd, 0xf5, 0xf0, 0x84, 0x87, 0x68, 0x2c, 0x5a, 0xfb, 0x89, - 0xcf, 0x81, 0x03, 0x4a, 0x3a, 0x0f, 0xcf, 0xc1, 0x85, 0xb2, 0x82, 0xe5, 0x6e, 0xb9, 0xf1, 0x4e, 0x39, 0x0b, 0x47, - 0x5b, 0x32, 0xe0, 0x0e, 0xb6, 0x21, 0x0a, 0x1d, 0x1c, 0xf7, 0x70, 0xd2, 0xed, 0xf6, 0xce, 0x71, 0x72, 0x76, 0x0e, - 0x03, 0x6d, 0x25, 0xe7, 0xc7, 0x63, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x4f, 0x20, 0x68, 0x55, 0x28, 0x5e, - 0xf3, 0xe3, 0x38, 0xee, 0x26, 0x0f, 0x3b, 0xdd, 0xf3, 0xcb, 0x16, 0x00, 0xa8, 0xed, 0x3e, 0x5c, 0x8d, 0x37, 0x4b, - 0xdd, 0xac, 0x52, 0x21, 0x7c, 0xb3, 0x5a, 0xcb, 0x57, 0x6b, 0x75, 0x37, 0xf5, 0x14, 0x7c, 0x55, 0x27, 0x9c, 0xdb, - 0x22, 0x5e, 0x69, 0x13, 0x6e, 0x8b, 0xd8, 0x0e, 0x24, 0x06, 0xe9, 0x3c, 0x39, 0xef, 0x9d, 0x23, 0x3b, 0x16, 0xed, - 0xf0, 0xa3, 0xda, 0x27, 0x3b, 0x45, 0x5a, 0x1a, 0x90, 0xa4, 0x9a, 0x9d, 0x5c, 0x82, 0x44, 0xcd, 0xc9, 0x75, 0xb7, - 0x3d, 0x67, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0xac, 0x56, 0xc1, 0x25, 0x05, 0x80, 0xb8, 0x02, 0xe3, 0xa2, 0x87, - 0xe7, 0x83, 0x87, 0xc9, 0xf9, 0x45, 0xcf, 0x12, 0x3d, 0x7e, 0xd5, 0x6b, 0xa4, 0x99, 0xa9, 0x27, 0xe7, 0x26, 0x0d, - 0xba, 0x4e, 0x1e, 0x9e, 0x43, 0x19, 0x97, 0x12, 0x96, 0x82, 0x60, 0x1b, 0x75, 0x31, 0x88, 0xb0, 0x91, 0x36, 0x72, - 0x2f, 0x1a, 0xd9, 0x97, 0x67, 0xa7, 0x0f, 0xcf, 0x43, 0xa8, 0x55, 0xb3, 0x30, 0x0b, 0xed, 0x26, 0xe2, 0x67, 0x07, - 0x4b, 0x8b, 0x8e, 0x93, 0xf3, 0x74, 0x67, 0x82, 0x76, 0xd3, 0x1c, 0x1b, 0x1c, 0x08, 0x14, 0x8e, 0xcf, 0x85, 0xd3, - 0x97, 0x04, 0xf7, 0x63, 0xb5, 0xa1, 0x49, 0xa8, 0x70, 0xf6, 0xf7, 0x94, 0xc1, 0x7b, 0x9a, 0xe1, 0x55, 0xe5, 0x53, - 0x2a, 0xbe, 0x50, 0xf5, 0x96, 0x42, 0x04, 0x11, 0x31, 0x8a, 0x5c, 0x7c, 0xf3, 0x66, 0xee, 0x3f, 0xc1, 0x45, 0x98, - 0x09, 0xb8, 0xd0, 0xf4, 0x4a, 0xd0, 0x9a, 0x17, 0xf8, 0x14, 0x3a, 0xd4, 0x9a, 0x61, 0x0d, 0x78, 0xea, 0x4c, 0x0a, - 0x42, 0xdd, 0xd6, 0x4b, 0xfe, 0xad, 0x72, 0x49, 0x75, 0x95, 0x9d, 0x9c, 0xa3, 0xc4, 0x5d, 0x96, 0x27, 0x5d, 0x94, - 0x04, 0x26, 0x24, 0xee, 0x48, 0x2e, 0x32, 0x32, 0x8c, 0xee, 0x22, 0x1c, 0xdd, 0x47, 0x38, 0xb2, 0x3e, 0xcc, 0xbf, - 0x80, 0x1f, 0x77, 0x84, 0x23, 0xeb, 0xca, 0x1c, 0xe1, 0x48, 0x33, 0x01, 0x81, 0xc5, 0xa2, 0x11, 0x9e, 0x41, 0x69, - 0xe3, 0x59, 0x5d, 0x95, 0x7e, 0xea, 0xbf, 0x2a, 0xd7, 0x6b, 0x9b, 0x12, 0x48, 0x99, 0xb9, 0xd9, 0xa1, 0xf6, 0x61, - 0xec, 0x88, 0x7a, 0x66, 0x3d, 0xc2, 0x20, 0x80, 0xd0, 0x7b, 0xff, 0xb0, 0x5e, 0x1d, 0x93, 0x84, 0x9d, 0xc2, 0x4a, - 0x83, 0x2b, 0x7a, 0x14, 0x9e, 0x61, 0x11, 0x9e, 0x08, 0x5f, 0x18, 0xc4, 0x0a, 0xff, 0xbb, 0x90, 0x72, 0xe1, 0x7f, - 0x6b, 0x59, 0xfd, 0x82, 0xe7, 0x58, 0x9c, 0x45, 0x0b, 0x58, 0x6e, 0xd9, 0x10, 0x48, 0x63, 0xd6, 0x1c, 0xc1, 0xa7, - 0x89, 0x0b, 0x53, 0x07, 0x12, 0xe1, 0x27, 0x23, 0x50, 0x79, 0xf9, 0xf0, 0x93, 0x0d, 0x99, 0x64, 0x3e, 0x21, 0x66, - 0x1a, 0x84, 0x45, 0x96, 0x70, 0xa1, 0x31, 0x2d, 0x99, 0x52, 0x91, 0x8d, 0x25, 0x18, 0x49, 0xe1, 0x1f, 0x87, 0xf4, - 0x29, 0x13, 0x11, 0x99, 0x0e, 0x9b, 0xb3, 0xb5, 0xe2, 0x70, 0x21, 0x4b, 0x95, 0xda, 0x97, 0x62, 0x3c, 0x18, 0x17, - 0xd5, 0x33, 0x8c, 0xe9, 0x2c, 0xdb, 0x60, 0x7b, 0x87, 0x5d, 0x15, 0x72, 0x57, 0xda, 0x61, 0xa9, 0x22, 0xdb, 0x7c, - 0x6d, 0x42, 0xaa, 0x31, 0xa3, 0x60, 0xa2, 0xf5, 0x80, 0xea, 0xc0, 0x1d, 0x50, 0xd8, 0x06, 0xa5, 0x49, 0x57, 0x55, - 0xc9, 0x74, 0x55, 0x2d, 0xc3, 0x59, 0xa7, 0xb3, 0xd9, 0xe0, 0x92, 0x99, 0x40, 0x2e, 0x7b, 0x4b, 0x40, 0xbe, 0x9a, - 0xc9, 0xdb, 0x20, 0x57, 0xa5, 0xd5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, 0x5f, 0xb8, 0xe2, 0x00, - 0x4f, 0x37, 0xbb, 0xb1, 0x94, 0x05, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x3c, 0x67, 0xfb, 0xdb, 0x04, - 0x33, 0xe6, 0xff, 0xac, 0x45, 0x8f, 0x40, 0x96, 0xdd, 0x33, 0xa8, 0x03, 0x8b, 0xb8, 0x86, 0x0e, 0x42, 0x19, 0x7c, - 0x19, 0xe2, 0x66, 0x41, 0xef, 0xe5, 0x52, 0x03, 0x5c, 0x96, 0x5a, 0xbe, 0x75, 0xe1, 0x10, 0x0e, 0x3b, 0xd8, 0x47, - 0x46, 0x58, 0x41, 0xc8, 0x80, 0x0e, 0xb6, 0x11, 0x31, 0x3a, 0xd8, 0x05, 0x2a, 0xe8, 0x60, 0x13, 0x9e, 0xa2, 0xb3, - 0xa9, 0x62, 0x9b, 0xdd, 0x57, 0x4f, 0x6a, 0xd6, 0x9b, 0x60, 0xe2, 0xa4, 0x43, 0x4d, 0x74, 0x70, 0x7b, 0xc8, 0x08, - 0x6f, 0x7d, 0x7f, 0xf3, 0xe6, 0xb5, 0x8b, 0x5c, 0xcd, 0x27, 0xe0, 0xb2, 0xe9, 0x54, 0x63, 0xf7, 0x36, 0xc4, 0x7c, - 0xad, 0x28, 0xb5, 0xc2, 0xa9, 0x09, 0xf6, 0x29, 0x74, 0x91, 0xd8, 0xcb, 0x8b, 0x17, 0xb2, 0x9c, 0x53, 0x7b, 0x63, - 0x84, 0xef, 0x95, 0x7b, 0x7c, 0xde, 0xbc, 0x6f, 0x53, 0x4f, 0xf2, 0xfd, 0xf6, 0x55, 0xc4, 0x24, 0x33, 0xf2, 0x2b, - 0x68, 0x03, 0x4c, 0x65, 0x3f, 0x70, 0x56, 0x12, 0x17, 0xff, 0x3f, 0x20, 0x2f, 0xef, 0x2c, 0x75, 0x89, 0xa2, 0x16, - 0x37, 0xf8, 0xc9, 0xca, 0x5a, 0xc7, 0xc5, 0xcd, 0xfb, 0x91, 0xa4, 0xe3, 0xc4, 0x8b, 0xa8, 0x13, 0x35, 0xdf, 0xde, - 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0x29, 0x24, 0x88, 0x1e, 0xd5, 0x33, 0x7f, 0x1c, 0x44, 0x13, 0x7f, 0xf7, 0x7c, - 0xdd, 0xf5, 0x74, 0xb6, 0xa8, 0xd5, 0x89, 0xd5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, 0x0e, 0x12, 0x59, - 0xa5, 0x3d, 0xf4, 0xb9, 0xa8, 0x1f, 0x17, 0x57, 0x5d, 0xd6, 0x3e, 0x5b, 0xaf, 0x8b, 0xeb, 0x2e, 0xeb, 0x9e, 0xdb, - 0x67, 0xf7, 0x22, 0x95, 0x01, 0xcd, 0xe5, 0x13, 0x9e, 0x45, 0xa0, 0x9d, 0x5d, 0x64, 0x26, 0x9c, 0x82, 0x97, 0xa6, - 0xc9, 0x52, 0xd7, 0x7d, 0x49, 0x30, 0x2e, 0x25, 0x56, 0x8f, 0x5f, 0xa2, 0x41, 0x37, 0xdd, 0x75, 0x95, 0x6e, 0x77, - 0x8f, 0x83, 0x0b, 0x97, 0x12, 0xe1, 0x1e, 0x84, 0x3c, 0x00, 0xfd, 0xee, 0x4a, 0x80, 0x69, 0x10, 0xa0, 0xb2, 0x02, - 0x91, 0x96, 0xcf, 0x97, 0xf3, 0x17, 0x25, 0x35, 0xcb, 0xf0, 0x8c, 0x4f, 0xb9, 0x56, 0x29, 0x05, 0xe9, 0x76, 0x5f, - 0xfa, 0x66, 0xbf, 0x04, 0x95, 0x35, 0xe2, 0xef, 0x26, 0x9a, 0x67, 0x9f, 0x95, 0x5b, 0x38, 0x84, 0xcd, 0xca, 0x0a, - 0x9c, 0xa1, 0x0d, 0x2e, 0xe4, 0x94, 0x96, 0x5c, 0xcf, 0xe6, 0xff, 0xd1, 0xea, 0xb0, 0xa1, 0x1e, 0x99, 0x0b, 0x2b, - 0x00, 0x09, 0x15, 0xf9, 0x7a, 0xcd, 0x4f, 0xbe, 0x7d, 0x9f, 0xe4, 0x7d, 0xc2, 0xbb, 0xb8, 0x87, 0x4f, 0xf1, 0x39, - 0xee, 0x76, 0x70, 0xf7, 0x1c, 0xae, 0xee, 0xb3, 0x62, 0x99, 0x33, 0x15, 0xc3, 0xfb, 0x6b, 0xfa, 0x3a, 0xb9, 0x3c, - 0xae, 0x5f, 0x1d, 0x28, 0x13, 0x87, 0x2e, 0x41, 0xf0, 0x7b, 0x17, 0x35, 0x30, 0x8a, 0xc2, 0x90, 0x75, 0x8b, 0x50, - 0x75, 0x52, 0xe9, 0x17, 0xae, 0x4f, 0x07, 0x60, 0xcf, 0x6d, 0x57, 0xb6, 0x0d, 0x66, 0xdf, 0xf6, 0x67, 0x5a, 0xff, - 0x6c, 0xeb, 0x0a, 0x31, 0x3c, 0xf4, 0x6a, 0xf4, 0x40, 0xd7, 0xa4, 0x7b, 0x74, 0x04, 0x56, 0x47, 0xc1, 0x6c, 0xb8, - 0x8d, 0x7e, 0xc0, 0xdb, 0x8d, 0x34, 0x08, 0x56, 0x00, 0xc6, 0x9d, 0x0f, 0x38, 0x59, 0x59, 0xd8, 0x6a, 0xa0, 0xc2, - 0xac, 0x0c, 0xe3, 0xea, 0x85, 0xa4, 0xc2, 0x08, 0xd1, 0x70, 0x84, 0xb9, 0x60, 0x28, 0x87, 0x1d, 0x2c, 0x27, 0x13, - 0xc5, 0x34, 0x1c, 0x1d, 0x25, 0xfb, 0xc2, 0x4a, 0x65, 0x4e, 0x91, 0x31, 0x9b, 0x72, 0xf1, 0x58, 0xff, 0xc6, 0x4a, - 0x69, 0x3e, 0x8d, 0x06, 0x23, 0x8d, 0xcc, 0x2a, 0x46, 0x38, 0x2b, 0xf8, 0x02, 0xaa, 0x4e, 0x4b, 0x70, 0xfa, 0x81, - 0xbf, 0x3c, 0x4f, 0xc3, 0x36, 0x81, 0x7c, 0xfd, 0x62, 0x63, 0xba, 0xe0, 0xbc, 0xa4, 0xb7, 0x6f, 0xc4, 0x53, 0xd8, - 0x51, 0x8f, 0x4b, 0x46, 0x21, 0x1b, 0x92, 0xde, 0x43, 0x53, 0xf0, 0x01, 0x6d, 0xfe, 0x68, 0x00, 0x97, 0x5e, 0x9a, - 0x0f, 0x5b, 0xd1, 0xc7, 0x6e, 0x4c, 0xaa, 0xb6, 0x4c, 0xa6, 0x39, 0xa5, 0xeb, 0x4c, 0x1b, 0x85, 0xaa, 0x9a, 0xc2, - 0x06, 0xbb, 0xa8, 0x27, 0xe1, 0x60, 0x72, 0xaa, 0x66, 0xe9, 0x70, 0x64, 0xfe, 0xbe, 0xb1, 0x25, 0x3b, 0xd8, 0x45, - 0x9c, 0xd9, 0x60, 0xf3, 0x70, 0x6a, 0x50, 0xbe, 0x8b, 0xe1, 0x1e, 0x16, 0x5e, 0xef, 0x6c, 0x90, 0xcf, 0x33, 0x4f, - 0x36, 0xcf, 0x36, 0x1b, 0x33, 0x10, 0x95, 0x82, 0x1e, 0xe8, 0x9d, 0xdf, 0x36, 0x1d, 0xd8, 0x1e, 0xd5, 0xd7, 0x79, - 0x07, 0xcf, 0x39, 0x3c, 0x46, 0xea, 0xdb, 0xbb, 0xd1, 0xa5, 0xfc, 0xec, 0x40, 0xd2, 0x09, 0x52, 0xec, 0x74, 0x82, - 0xce, 0x4e, 0x71, 0x30, 0x72, 0xa0, 0xe7, 0x37, 0x9f, 0x2d, 0xac, 0xfd, 0xef, 0xb7, 0x55, 0x41, 0x13, 0x4f, 0xa7, - 0x9a, 0x50, 0xe6, 0xcf, 0xcf, 0x07, 0x3c, 0xa9, 0x51, 0xc1, 0xbd, 0xe2, 0x05, 0x7b, 0xda, 0x06, 0xfa, 0x9c, 0xd3, - 0x3f, 0xed, 0x0f, 0x1b, 0xc3, 0xa7, 0xd2, 0xb2, 0x65, 0xa5, 0x54, 0xea, 0xb1, 0x4d, 0xb3, 0x47, 0x0f, 0x1c, 0x91, - 0x3f, 0x42, 0x17, 0xc0, 0xeb, 0xe7, 0xa5, 0x5c, 0x18, 0x44, 0x70, 0xbf, 0xdd, 0xb8, 0x8d, 0xaf, 0x00, 0x78, 0x3b, - 0x1c, 0xd4, 0xff, 0x74, 0x80, 0xfd, 0x8d, 0xaa, 0x92, 0x7e, 0xbc, 0x3d, 0x7b, 0xfc, 0x97, 0x12, 0xa2, 0xc6, 0x5b, - 0x3c, 0x4c, 0x1c, 0x3a, 0x55, 0xac, 0x59, 0xf5, 0x73, 0xa7, 0x24, 0x60, 0x58, 0xb3, 0x60, 0xc8, 0xc6, 0xed, 0x14, - 0xb7, 0x99, 0xff, 0x83, 0x0a, 0x06, 0x0b, 0xbe, 0x36, 0x92, 0x9a, 0x65, 0xf1, 0xdb, 0xa7, 0xc9, 0x7f, 0x35, 0x39, - 0xae, 0x43, 0xdd, 0x78, 0x29, 0x74, 0x6c, 0xa2, 0x34, 0x47, 0xe8, 0xe8, 0x68, 0x2b, 0x83, 0x4e, 0x00, 0xf0, 0xc8, - 0xb1, 0x5f, 0x7e, 0xf9, 0x3c, 0x3b, 0x66, 0x34, 0x8f, 0x65, 0x14, 0x32, 0x77, 0x9e, 0x9b, 0xb3, 0x13, 0x79, 0x46, - 0xd5, 0xcc, 0x17, 0x06, 0x38, 0x3e, 0xd9, 0x49, 0x05, 0x7c, 0x8f, 0x36, 0x7b, 0x26, 0xb0, 0xc5, 0x6f, 0xd9, 0x49, - 0xed, 0x2b, 0xe8, 0x17, 0x68, 0xb5, 0x8f, 0xa9, 0xdc, 0x5a, 0xe0, 0x68, 0x7b, 0x22, 0x7b, 0x87, 0xbe, 0x55, 0xa7, - 0x62, 0x3d, 0x5e, 0xed, 0x37, 0xfa, 0x92, 0x62, 0x5f, 0x72, 0x4d, 0xdb, 0xc6, 0xac, 0x7e, 0x2d, 0x58, 0xd7, 0xa6, - 0x4e, 0xf5, 0x35, 0x6f, 0x6d, 0x69, 0x53, 0xd9, 0x25, 0xd9, 0xbb, 0x2d, 0x16, 0x5e, 0x85, 0xb7, 0x5a, 0xd5, 0x45, - 0x28, 0xd8, 0x63, 0x89, 0x51, 0x9f, 0x13, 0xb8, 0x5e, 0x58, 0xaf, 0x63, 0xf8, 0xb3, 0x6f, 0x0c, 0xfb, 0x4c, 0x97, - 0x3e, 0xf0, 0x2d, 0x7e, 0x25, 0x08, 0x58, 0xec, 0xec, 0x20, 0xc1, 0xba, 0xcb, 0x0d, 0x1a, 0x8e, 0x13, 0xff, 0x05, - 0xcf, 0x65, 0x6b, 0xef, 0x72, 0x30, 0xcf, 0xbe, 0xf2, 0xc4, 0x5e, 0xc5, 0x5a, 0x36, 0xa2, 0xdd, 0x6f, 0x49, 0x30, - 0xc4, 0x6e, 0x4a, 0xe7, 0xb8, 0x95, 0x74, 0x51, 0xe4, 0x8a, 0xd5, 0xe8, 0xff, 0xb5, 0x22, 0x99, 0xcd, 0xfc, 0xaf, - 0x8b, 0x8b, 0x0b, 0x97, 0xe2, 0x6c, 0xfe, 0x94, 0xf1, 0x80, 0x33, 0x09, 0xec, 0x0b, 0xcf, 0x98, 0xd1, 0x21, 0xbf, - 0x83, 0xa1, 0x10, 0x41, 0xae, 0x85, 0x63, 0x97, 0xe0, 0xb5, 0x47, 0xa0, 0x3c, 0xc0, 0xfe, 0x3d, 0xdb, 0x2a, 0xe7, - 0x9f, 0x8b, 0xf2, 0xe1, 0x94, 0xab, 0x06, 0xd9, 0x17, 0xf3, 0x39, 0xb4, 0x66, 0x32, 0xf0, 0x42, 0x42, 0x84, 0xed, - 0x6f, 0xc3, 0xd2, 0x3a, 0x4b, 0x19, 0x1c, 0x69, 0xb9, 0xcc, 0x66, 0x56, 0xf3, 0xef, 0x3e, 0x4c, 0x59, 0xf7, 0xd4, - 0x10, 0x44, 0xee, 0x22, 0x2b, 0x17, 0x15, 0x34, 0xfa, 0x47, 0x15, 0x00, 0xf4, 0xe0, 0x35, 0x5b, 0xb2, 0x7f, 0xe0, - 0x83, 0x3a, 0x05, 0x3e, 0x1e, 0x97, 0x9c, 0x16, 0xff, 0xc0, 0x07, 0x75, 0x20, 0x50, 0x70, 0x85, 0x34, 0xb1, 0x34, - 0xb1, 0x79, 0x56, 0x3b, 0x8d, 0x04, 0x50, 0xd0, 0x22, 0x32, 0x07, 0xd9, 0x4b, 0x17, 0xa3, 0x31, 0xe9, 0x61, 0x17, - 0x1c, 0xcc, 0x46, 0x84, 0xb5, 0x81, 0xd4, 0x21, 0x6e, 0x5d, 0x35, 0x1b, 0xf3, 0xf5, 0x64, 0x6b, 0x41, 0x8c, 0x32, - 0x99, 0x5c, 0xbf, 0xe4, 0xf1, 0xce, 0x62, 0xa1, 0xb0, 0x5a, 0xb0, 0x40, 0x8d, 0x2a, 0x75, 0x7a, 0x58, 0x7c, 0xb7, - 0x60, 0x16, 0x14, 0x31, 0x5b, 0xef, 0xf1, 0x1d, 0x57, 0x04, 0xa4, 0x64, 0x97, 0x04, 0x2f, 0xa3, 0x1b, 0x4c, 0x25, - 0xab, 0xb9, 0xcc, 0x99, 0x25, 0xf4, 0x4c, 0xe9, 0x08, 0x9b, 0x3c, 0x05, 0x91, 0xc4, 0x0e, 0x3b, 0xd8, 0xb1, 0x46, - 0xaf, 0x84, 0x17, 0x52, 0xe0, 0x5c, 0x35, 0x4d, 0xcc, 0x29, 0x37, 0xd1, 0xc5, 0x1e, 0xab, 0x05, 0xcb, 0xb4, 0x45, - 0x80, 0x43, 0x87, 0x86, 0x52, 0xbc, 0x34, 0xa0, 0x30, 0x4f, 0x7a, 0xbb, 0x94, 0xa7, 0xb0, 0x78, 0x41, 0x0a, 0x10, - 0x35, 0x2e, 0xa6, 0x55, 0x9d, 0x45, 0xb1, 0x9c, 0x72, 0x51, 0x23, 0x43, 0xc9, 0xd4, 0x42, 0x0a, 0x78, 0x51, 0xa3, - 0x2a, 0x62, 0xe8, 0x50, 0x03, 0xdf, 0x2d, 0x09, 0xab, 0xea, 0x98, 0x63, 0x8a, 0x8b, 0xba, 0x06, 0x30, 0x17, 0x8f, - 0x8d, 0x80, 0xe8, 0xc3, 0xcb, 0xbe, 0x11, 0xef, 0xe5, 0xa2, 0xce, 0xf7, 0x34, 0xce, 0x07, 0xae, 0x77, 0x76, 0xc3, - 0x68, 0x63, 0x1e, 0xbd, 0x0a, 0xb6, 0xef, 0x07, 0x5e, 0x3f, 0x04, 0xb7, 0x31, 0xcf, 0x66, 0x55, 0x59, 0x63, 0x56, - 0xbd, 0x11, 0x51, 0xb7, 0xd7, 0xac, 0x2a, 0x85, 0xad, 0x08, 0x50, 0x29, 0x79, 0xbe, 0x93, 0xff, 0x4a, 0xdb, 0x7c, - 0x7b, 0x0e, 0x55, 0xe1, 0x81, 0x3c, 0x19, 0xaa, 0x7b, 0xc0, 0x65, 0xf5, 0x21, 0x80, 0xc5, 0x8f, 0x4c, 0xfc, 0xe0, - 0x7d, 0x17, 0xc8, 0x9c, 0xa9, 0x58, 0xe2, 0xd5, 0x90, 0x8e, 0x52, 0x2b, 0x0f, 0xa5, 0x12, 0x6c, 0x7b, 0x6e, 0x4b, - 0xae, 0x7d, 0xa0, 0x62, 0x3c, 0x64, 0xa3, 0x74, 0xd5, 0x0c, 0x66, 0x6c, 0xc3, 0x29, 0x7b, 0x73, 0x4e, 0x13, 0xfd, - 0x97, 0x8e, 0x70, 0x41, 0xc0, 0xf6, 0xd8, 0xb3, 0xa7, 0x0f, 0xe2, 0x0c, 0x0d, 0x9a, 0x1c, 0xfe, 0x6a, 0x83, 0x0b, - 0x9c, 0xa1, 0xf4, 0x71, 0x0c, 0x17, 0x58, 0x1b, 0x0c, 0xe0, 0xcb, 0x2c, 0xa9, 0x02, 0x8f, 0xd4, 0xcc, 0x48, 0xac, - 0xee, 0x22, 0x10, 0xad, 0x74, 0x78, 0x3b, 0xce, 0x7c, 0x38, 0x70, 0xc3, 0xbd, 0xbe, 0x30, 0xc2, 0xe1, 0x3c, 0x8b, - 0x1b, 0xe7, 0x0c, 0x27, 0xd7, 0x87, 0xbc, 0x71, 0x62, 0x82, 0xb5, 0x77, 0x78, 0xaa, 0x80, 0x1e, 0x0d, 0x4e, 0x15, - 0x4b, 0x43, 0x20, 0x66, 0x02, 0x78, 0x33, 0x87, 0x47, 0x5b, 0x80, 0xf3, 0xd1, 0x06, 0x07, 0x5f, 0x69, 0xa3, 0xab, - 0x6d, 0x25, 0xca, 0x66, 0x83, 0x87, 0x79, 0x86, 0x97, 0x19, 0x9e, 0x66, 0xa3, 0xf0, 0xb8, 0xc9, 0x42, 0x93, 0xae, - 0xf5, 0xfa, 0x95, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0x68, 0x00, 0x08, 0x9f, 0x42, 0x16, 0xd0, 0x92, 0x81, - 0xfb, 0xdb, 0xb2, 0xaf, 0x85, 0xa3, 0x56, 0xcc, 0x13, 0x4b, 0x46, 0x06, 0xfe, 0x47, 0x95, 0x65, 0x5b, 0x6b, 0x45, - 0x8b, 0xbb, 0x83, 0xa8, 0xe5, 0xdb, 0xab, 0xcf, 0x97, 0x71, 0x65, 0xb6, 0x03, 0x88, 0x62, 0x8d, 0x93, 0x74, 0xb0, - 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcd, 0x03, 0x7a, 0xb1, 0x42, 0x89, 0xe1, - 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x86, 0xc8, 0xfd, 0x29, 0xab, 0x2d, - 0x83, 0x04, 0x11, 0x46, 0xe4, 0xb7, 0xd7, 0xa5, 0xc2, 0x3e, 0xd1, 0x67, 0xff, 0x18, 0x5f, 0x40, 0xb8, 0x79, 0x9b, - 0xd2, 0x72, 0x4c, 0xa7, 0xc0, 0xc6, 0x42, 0x1c, 0xc2, 0x9d, 0x84, 0xf5, 0x7a, 0x38, 0xea, 0x0b, 0x43, 0x9e, 0xdd, - 0x03, 0x82, 0x55, 0x43, 0xfb, 0x1b, 0x80, 0xab, 0x6e, 0x4b, 0xcd, 0xb5, 0xd1, 0xfd, 0x50, 0xf3, 0xc6, 0x19, 0x77, - 0x49, 0xee, 0x99, 0x92, 0xfa, 0x25, 0xf2, 0x86, 0x05, 0xb8, 0x09, 0x5d, 0x85, 0x73, 0xbc, 0xb4, 0x36, 0x9c, 0xe6, - 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x66, 0x23, 0x9c, 0xfb, 0x70, 0xe7, 0x87, 0xef, 0xe2, - 0x1c, 0xa1, 0x92, 0x18, 0x98, 0x5a, 0x97, 0xed, 0xbc, 0xb6, 0xdb, 0x37, 0x99, 0x86, 0x61, 0x30, 0x46, 0xcc, 0x79, - 0x68, 0xc4, 0x5c, 0xb4, 0x5a, 0x68, 0x49, 0x72, 0x30, 0x62, 0x5e, 0x06, 0xad, 0x2d, 0xed, 0x63, 0xa7, 0x41, 0x7b, - 0x4b, 0x84, 0xfa, 0x1c, 0x68, 0x9a, 0x86, 0x67, 0x4d, 0xea, 0x67, 0xe5, 0xfd, 0x23, 0x5b, 0x27, 0x3d, 0x50, 0x24, - 0x4c, 0xae, 0xfd, 0x24, 0xac, 0x6b, 0xb8, 0x1d, 0xf7, 0xc4, 0x8c, 0xdb, 0xd9, 0x36, 0xa8, 0xa1, 0x1c, 0x66, 0xa3, - 0x51, 0x5f, 0x7a, 0x2b, 0x89, 0x0e, 0x9e, 0xd4, 0x0f, 0xa1, 0xd4, 0x8b, 0xf7, 0x45, 0x6f, 0x5f, 0x79, 0x73, 0xff, - 0xbe, 0xea, 0xf6, 0x79, 0x0c, 0x1c, 0xd0, 0x21, 0xdc, 0x0f, 0xd5, 0xf1, 0xc1, 0x4e, 0x7a, 0x10, 0x05, 0x2d, 0xed, - 0x34, 0x04, 0x52, 0x6b, 0x66, 0x17, 0xeb, 0xb6, 0x42, 0xc7, 0x02, 0xc2, 0x90, 0xa9, 0xba, 0xbb, 0x3b, 0x15, 0xa8, - 0x86, 0x38, 0x9c, 0xfa, 0x4f, 0xad, 0x11, 0x6b, 0x1c, 0xf5, 0xf2, 0xc8, 0x18, 0x49, 0xda, 0xe5, 0x83, 0xb7, 0x8f, - 0xc0, 0x4a, 0xc0, 0xc7, 0xa0, 0x36, 0x49, 0xc6, 0x90, 0xe0, 0x1d, 0xcb, 0xb4, 0xe1, 0x43, 0xb8, 0x43, 0x50, 0x9e, - 0xd8, 0xa0, 0xb4, 0xae, 0x92, 0x85, 0x5c, 0xdd, 0xe5, 0x7d, 0x80, 0x9e, 0x77, 0xd5, 0x6f, 0x6c, 0x38, 0xb2, 0x60, - 0x60, 0xd9, 0xce, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x23, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0x78, 0xdd, 0x37, 0xb0, 0x41, - 0xf1, 0x02, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, 0x49, 0xbc, 0x58, 0xaf, - 0x3b, 0xe8, 0xf8, 0x5f, 0xe6, 0x49, 0xea, 0x49, 0xa5, 0x70, 0x9f, 0xd4, 0x0a, 0x77, 0xb0, 0x04, 0x24, 0x93, 0x40, - 0xd7, 0x8e, 0x65, 0xa8, 0x46, 0x87, 0x68, 0xe9, 0xaf, 0x20, 0x76, 0xb6, 0x3b, 0x96, 0x40, 0xcf, 0xbe, 0x53, 0xc0, - 0xea, 0xda, 0xab, 0x12, 0xc8, 0x08, 0xee, 0x7e, 0x13, 0x18, 0x15, 0xa2, 0xf1, 0xf9, 0x33, 0xaf, 0x5a, 0xf0, 0xc4, - 0xf9, 0x73, 0xcd, 0x0d, 0xeb, 0x5e, 0xd2, 0x5b, 0xd3, 0x7c, 0x3c, 0xc1, 0xed, 0x89, 0x05, 0xe7, 0x49, 0x0f, 0x7e, - 0x5a, 0x88, 0x9e, 0xf4, 0xb0, 0x4b, 0xc5, 0x93, 0x0a, 0xc8, 0x21, 0x7a, 0x3a, 0x03, 0x29, 0x60, 0xa5, 0x63, 0xab, - 0x45, 0x9a, 0xa2, 0xf5, 0x7a, 0x7a, 0x45, 0x3a, 0x08, 0xad, 0xd4, 0x2d, 0xd7, 0xd9, 0x0c, 0x7c, 0xa4, 0x41, 0x31, - 0xf0, 0x96, 0xea, 0x59, 0x8c, 0xf0, 0x04, 0xad, 0x72, 0x36, 0xa1, 0xcb, 0x42, 0xa7, 0x6a, 0xc0, 0x13, 0x1b, 0xb8, - 0x97, 0xd9, 0x48, 0x70, 0x27, 0x3d, 0x3c, 0x35, 0xfc, 0xe5, 0x47, 0x63, 0x0e, 0x52, 0x66, 0x26, 0x79, 0x6a, 0x12, - 0x30, 0x4f, 0xb2, 0x42, 0x2a, 0x66, 0x9b, 0xe9, 0x5b, 0xdb, 0x72, 0x08, 0x49, 0x1e, 0xe9, 0x92, 0x1b, 0x2b, 0xca, - 0x28, 0x9d, 0x11, 0x35, 0x50, 0x27, 0xbd, 0x74, 0x8a, 0x79, 0x02, 0x9c, 0xde, 0x7b, 0x19, 0xb3, 0x56, 0x75, 0x2b, - 0x3a, 0x47, 0xc7, 0x33, 0x2c, 0xea, 0x4b, 0xd4, 0x39, 0x3a, 0x9e, 0x22, 0x3c, 0x6f, 0x91, 0x99, 0x02, 0x8f, 0x61, - 0x2e, 0xfe, 0x3f, 0x29, 0xff, 0xd5, 0x61, 0x43, 0x88, 0xe9, 0x77, 0xb0, 0x53, 0x58, 0x1e, 0xa5, 0x05, 0x01, 0xaf, - 0xc5, 0xee, 0x05, 0xce, 0xc8, 0xb4, 0x5d, 0xf8, 0x80, 0x7b, 0xa6, 0x95, 0xd6, 0x9d, 0x46, 0xc7, 0x19, 0xce, 0xb7, - 0x93, 0x62, 0x33, 0xd7, 0x76, 0x91, 0x66, 0x70, 0xbe, 0xd7, 0xa3, 0x70, 0xe5, 0x97, 0xdb, 0x49, 0x61, 0x79, 0x07, - 0xdc, 0x76, 0x8e, 0x45, 0x9b, 0xe2, 0x02, 0xcf, 0xdb, 0xaf, 0xf1, 0xbc, 0xfd, 0xa1, 0xca, 0x68, 0x2d, 0xb1, 0x80, - 0xe0, 0x7d, 0x90, 0x88, 0xe7, 0x75, 0x72, 0x8e, 0x45, 0xcb, 0x94, 0xc7, 0xf3, 0x56, 0x5d, 0xba, 0xbd, 0xc4, 0xa2, - 0x65, 0x4a, 0xb7, 0x3e, 0xe0, 0x79, 0xeb, 0xf5, 0xbf, 0x99, 0x74, 0x94, 0x02, 0xba, 0x2c, 0xd0, 0x2a, 0xb3, 0x43, - 0xbc, 0xf9, 0xf9, 0xdd, 0xfb, 0xee, 0xa7, 0xde, 0xf1, 0x14, 0xfb, 0xf5, 0xcb, 0x0c, 0x8e, 0x65, 0x3a, 0x66, 0x6d, - 0x80, 0x68, 0x86, 0x7b, 0xc7, 0x33, 0xdc, 0x3b, 0xce, 0x5c, 0x53, 0x9b, 0x79, 0x8b, 0xdc, 0xe9, 0x10, 0x8a, 0x3a, - 0x4a, 0x43, 0xf8, 0xf8, 0xc9, 0xa6, 0x53, 0xd4, 0x00, 0x25, 0x3a, 0x9e, 0x36, 0x40, 0x05, 0xdf, 0xcb, 0xc6, 0x77, - 0x5d, 0xaf, 0xc6, 0x20, 0x0b, 0x25, 0x14, 0xae, 0xb9, 0x01, 0x4f, 0x23, 0xc5, 0x40, 0x26, 0x4c, 0xb1, 0x40, 0xf9, - 0x06, 0x28, 0x8c, 0xf2, 0xc4, 0x0c, 0x3d, 0x98, 0x8e, 0x49, 0xfc, 0xff, 0x79, 0x32, 0xd5, 0xd0, 0xab, 0x2d, 0xb3, - 0x33, 0x3d, 0x37, 0x99, 0x70, 0xf8, 0xc0, 0x63, 0xfd, 0x6f, 0x3b, 0x50, 0x6c, 0x40, 0x8a, 0xff, 0x37, 0x1d, 0x5d, - 0x08, 0x46, 0xc8, 0x8a, 0xd2, 0xd2, 0x21, 0xfe, 0xb7, 0x87, 0x15, 0x74, 0x5f, 0xee, 0x74, 0x5f, 0x9a, 0xee, 0xc3, - 0xa6, 0x8d, 0x2a, 0x27, 0xad, 0x2b, 0x59, 0xf2, 0xdf, 0xa4, 0x5b, 0x3b, 0xa0, 0x11, 0x0d, 0x7a, 0x36, 0x0d, 0x1b, - 0x3c, 0xec, 0xa6, 0x7b, 0x90, 0x79, 0xc3, 0xed, 0x0b, 0xa9, 0x70, 0xf8, 0x06, 0x77, 0xaa, 0xd7, 0x1d, 0xf0, 0xde, - 0x54, 0x46, 0x5f, 0x19, 0x87, 0x96, 0x83, 0x74, 0xdb, 0x94, 0xdb, 0x18, 0x4b, 0x27, 0xe7, 0xd8, 0xb8, 0x22, 0x42, - 0xa5, 0xbb, 0x6b, 0x50, 0x8a, 0x4f, 0x74, 0x9b, 0x99, 0xaf, 0x2b, 0x9d, 0x98, 0x4b, 0xa8, 0x96, 0xf9, 0xbc, 0xbf, - 0xd6, 0x89, 0x96, 0x0b, 0x9b, 0x77, 0x7f, 0x05, 0x7d, 0x82, 0x86, 0xb5, 0x15, 0xd8, 0xed, 0x73, 0x67, 0x07, 0x19, - 0x1c, 0x82, 0xe1, 0x01, 0xe4, 0x48, 0x8b, 0xed, 0x03, 0x9b, 0xd6, 0xb0, 0xeb, 0xa2, 0x5d, 0x25, 0xda, 0x56, 0xdb, - 0x26, 0xd7, 0xee, 0x61, 0xbe, 0x08, 0x79, 0x0a, 0x51, 0x5a, 0xfd, 0xf8, 0x1e, 0x76, 0xe3, 0x4b, 0x83, 0x91, 0x68, - 0x2a, 0x99, 0x2a, 0xe8, 0x27, 0x77, 0x98, 0x25, 0xf7, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, 0x13, 0x97, 0x3f, 0xaa, - 0x25, 0x39, 0xb0, 0xec, 0x6f, 0xb1, 0xe4, 0x0e, 0xcc, 0x13, 0xab, 0x6a, 0x12, 0xeb, 0xe4, 0x3e, 0x58, 0x44, 0x69, - 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0x61, 0x50, 0x95, 0xd2, 0xae, 0xb3, 0xb4, - 0xd1, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9e, 0xc6, 0x6d, 0xc0, 0x35, 0xfd, 0xbb, 0x49, 0x24, 0x63, 0xf6, 0x37, - 0x67, 0xe5, 0xd3, 0x65, 0x69, 0x30, 0x4d, 0x0c, 0x74, 0x92, 0x2d, 0xba, 0x60, 0xaa, 0x97, 0x2d, 0x7a, 0x77, 0xd8, - 0x7d, 0xdf, 0xdb, 0xef, 0x7b, 0x2c, 0x06, 0xcc, 0x64, 0xa4, 0xcc, 0x14, 0xf3, 0xdf, 0xf7, 0xf6, 0xfb, 0x1e, 0xef, - 0x0e, 0xe6, 0xb3, 0xbf, 0x50, 0xac, 0xd8, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x1a, 0x59, 0x26, 0x08, 0x6c, - 0x23, 0x01, 0xe2, 0x7c, 0xbe, 0x8a, 0x6b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xeb, 0x54, 0xe0, 0x31, 0x41, - 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd2, 0x93, 0x24, 0xc0, 0xab, 0x1a, 0x95, 0xb7, - 0x29, 0x52, 0x7d, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x42, 0x15, 0x03, 0x58, 0x55, 0x25, 0x7d, 0x02, 0x69, 0xe6, 0x87, - 0x9e, 0x9a, 0xdb, 0xc8, 0x63, 0xdf, 0xf9, 0xfd, 0xcc, 0xf4, 0xac, 0x94, 0xcb, 0xe9, 0x0c, 0x7c, 0x68, 0x81, 0x65, - 0x28, 0x4d, 0xbd, 0xda, 0xd6, 0xbf, 0x21, 0xb9, 0x09, 0xa0, 0x70, 0xba, 0x2d, 0x13, 0x9a, 0xe9, 0x25, 0x2d, 0x8c, - 0x25, 0x29, 0x17, 0xd3, 0x27, 0xf2, 0xee, 0x47, 0xc0, 0x6e, 0x4a, 0x74, 0x6b, 0x4f, 0xde, 0x3b, 0xd8, 0x01, 0x38, - 0x23, 0x6c, 0x5f, 0xc5, 0xc7, 0x0a, 0x74, 0xfe, 0xb8, 0x20, 0x6c, 0x5f, 0xd5, 0x67, 0xcc, 0x66, 0xcf, 0xc8, 0xd6, - 0x70, 0x07, 0x71, 0xd6, 0x2a, 0xd0, 0x49, 0x2f, 0x2d, 0xfa, 0x9e, 0x18, 0x58, 0x80, 0x06, 0xc0, 0xdd, 0xd9, 0x9e, - 0xd5, 0xdd, 0x0d, 0x01, 0xbd, 0x4b, 0x26, 0xed, 0x75, 0xb9, 0x49, 0x59, 0xaf, 0x7b, 0x35, 0x15, 0x2c, 0xf1, 0x2c, - 0xd8, 0x0b, 0xd4, 0x7e, 0xed, 0xa1, 0x38, 0x3f, 0x65, 0xdb, 0xa6, 0xe7, 0x55, 0xdf, 0xfd, 0x3d, 0x8b, 0x8c, 0x6d, - 0xda, 0xbb, 0x3d, 0x44, 0xc2, 0x72, 0xc2, 0x3a, 0xe0, 0x84, 0xeb, 0xda, 0x01, 0x01, 0xfa, 0x14, 0x88, 0xdc, 0x58, - 0x92, 0xd5, 0xa6, 0x36, 0xba, 0x0f, 0xfc, 0x6e, 0x29, 0x91, 0x6e, 0xb4, 0x15, 0xc1, 0xf4, 0x09, 0x46, 0x4d, 0x67, - 0x9e, 0xa6, 0x6e, 0xbc, 0xba, 0xbc, 0x2d, 0xda, 0xfa, 0x37, 0xa0, 0xb1, 0xd9, 0x1e, 0x26, 0x86, 0x32, 0x88, 0x81, - 0xde, 0x47, 0xbc, 0xdf, 0x6a, 0x65, 0x08, 0x14, 0x32, 0xd9, 0x08, 0xcb, 0xc4, 0x6b, 0xd1, 0x8f, 0x8e, 0x0c, 0x3c, - 0xea, 0x04, 0x84, 0x29, 0x08, 0x21, 0x61, 0xd7, 0x06, 0x61, 0xc3, 0xe5, 0x6a, 0xe4, 0xc2, 0x46, 0x6a, 0x0c, 0x1d, - 0xfc, 0xbf, 0xc2, 0x65, 0x6b, 0x66, 0x56, 0x8b, 0x62, 0x70, 0xb3, 0x30, 0x60, 0x91, 0x20, 0x3d, 0xda, 0x6c, 0x0f, - 0xc5, 0xfd, 0xb9, 0xd8, 0x6c, 0x08, 0x48, 0x2c, 0x60, 0x82, 0xa2, 0xe5, 0xdc, 0x18, 0x63, 0x95, 0xd4, 0x5a, 0xd6, - 0x86, 0xc4, 0x1c, 0x04, 0x8c, 0x0e, 0xd7, 0x7d, 0x75, 0x97, 0x32, 0x7c, 0x9f, 0x0a, 0x7c, 0x0b, 0x9e, 0x34, 0xa9, - 0xc4, 0xee, 0xf1, 0x82, 0x72, 0x43, 0x74, 0xdf, 0xb3, 0xb7, 0x25, 0xac, 0xb3, 0xd9, 0x23, 0x22, 0xf8, 0x5d, 0xff, - 0xea, 0x82, 0xef, 0x16, 0x7e, 0x0d, 0xd6, 0xcf, 0xc1, 0x49, 0x8a, 0x45, 0x4b, 0xb6, 0x4b, 0x77, 0x64, 0x40, 0xb9, - 0x9a, 0x5f, 0x0e, 0x53, 0x77, 0x8a, 0xe1, 0xc6, 0xc7, 0x6b, 0xfc, 0x61, 0xab, 0xdd, 0x96, 0xaa, 0x8a, 0xdb, 0xbd, - 0x29, 0x5a, 0xb2, 0x6e, 0x7a, 0x4f, 0xe6, 0x56, 0x4a, 0xf3, 0xeb, 0x03, 0xee, 0xec, 0xb4, 0xef, 0xa7, 0xf9, 0xce, - 0xa3, 0x73, 0xdd, 0xb4, 0x4f, 0x6d, 0x14, 0xc1, 0xc1, 0xcf, 0x0e, 0x6e, 0xef, 0x0c, 0x38, 0x80, 0x9f, 0xbf, 0xa3, - 0x79, 0x93, 0x41, 0x74, 0x7a, 0xab, 0x19, 0x5f, 0xc7, 0xbf, 0xe7, 0xad, 0x78, 0x90, 0xfe, 0x9e, 0xfc, 0x9e, 0xb7, - 0xd0, 0x00, 0xc5, 0x8b, 0xbb, 0x35, 0x9b, 0xaf, 0x21, 0xd8, 0xda, 0x83, 0x13, 0xfc, 0x20, 0x2c, 0xc9, 0x35, 0x2d, - 0x78, 0xb6, 0x76, 0x0f, 0x02, 0xae, 0xdd, 0xab, 0x44, 0x6b, 0xf3, 0xc6, 0xd5, 0x3a, 0x96, 0xe3, 0x02, 0x02, 0x0b, - 0xc7, 0x07, 0xed, 0xc1, 0xb0, 0xd3, 0x7e, 0x34, 0xb2, 0xff, 0x9a, 0x08, 0xf7, 0xa8, 0x11, 0xb1, 0xed, 0xed, 0xd6, - 0xd6, 0x8f, 0xc1, 0xb0, 0x03, 0x42, 0x81, 0x83, 0x5c, 0xfa, 0x26, 0x43, 0xd6, 0xf7, 0x64, 0xbd, 0x66, 0x2e, 0x9a, - 0xb5, 0xd3, 0xe0, 0x57, 0xb1, 0x99, 0x8e, 0xbb, 0x49, 0xaf, 0xef, 0xc5, 0x58, 0xd2, 0x82, 0x48, 0xd3, 0x98, 0x41, - 0x20, 0xa9, 0x95, 0xe1, 0xb0, 0x16, 0x77, 0x51, 0x5a, 0xdf, 0x1f, 0x41, 0xca, 0x77, 0x51, 0xca, 0x4f, 0x08, 0x04, - 0xd0, 0xb6, 0xcc, 0x51, 0xd5, 0x90, 0xf7, 0x5d, 0x7a, 0x6c, 0x9c, 0x19, 0x5a, 0x7c, 0xbd, 0xee, 0xd4, 0xc3, 0x54, - 0x65, 0x73, 0x98, 0xab, 0x0d, 0x16, 0xe4, 0x01, 0xe8, 0x9a, 0x15, 0x11, 0x83, 0xd0, 0x55, 0x1e, 0xde, 0x43, 0xc6, - 0x92, 0x80, 0x93, 0xfe, 0x40, 0x0c, 0x4a, 0x72, 0xfd, 0x38, 0x06, 0x1f, 0x33, 0xcc, 0x87, 0x7a, 0x58, 0x8e, 0x46, - 0x28, 0x75, 0x4e, 0x67, 0xa9, 0x89, 0xb8, 0x12, 0xf8, 0x25, 0x97, 0xe0, 0x97, 0xac, 0x10, 0x1b, 0x96, 0x23, 0xf2, - 0x38, 0x8b, 0x25, 0x38, 0xe5, 0xef, 0xf1, 0x79, 0x7c, 0x1e, 0x1a, 0x98, 0x9a, 0x61, 0x99, 0x8b, 0x6c, 0xb0, 0x98, - 0xb3, 0x96, 0x40, 0x70, 0x33, 0xe0, 0x2e, 0xb5, 0x21, 0xd1, 0x58, 0x03, 0x45, 0x77, 0x51, 0x68, 0x66, 0xf4, 0x6a, - 0xa7, 0x8d, 0x61, 0xe4, 0xf0, 0xc2, 0x5c, 0xc3, 0x58, 0x04, 0x32, 0x97, 0xab, 0x1e, 0xfb, 0xab, 0x0f, 0x9b, 0x15, - 0x06, 0xaf, 0xc8, 0x74, 0xe8, 0x8e, 0x63, 0xc6, 0x57, 0x7b, 0xe2, 0x18, 0x82, 0x4c, 0x2c, 0x95, 0x6e, 0x39, 0x26, - 0xae, 0xa2, 0xcf, 0xc4, 0x90, 0xed, 0x96, 0x67, 0xe6, 0x42, 0x37, 0xdb, 0x7f, 0x39, 0xb7, 0x73, 0x4e, 0xb8, 0xd1, - 0x4a, 0x1a, 0x6d, 0xd4, 0x0b, 0x43, 0x55, 0x5d, 0x30, 0xbf, 0xc7, 0x4e, 0x4b, 0x8b, 0x9d, 0xab, 0x77, 0x3f, 0x7c, - 0x9d, 0xaf, 0x8a, 0xbf, 0xc5, 0xea, 0xd0, 0x8a, 0x0c, 0x77, 0x3b, 0xc8, 0x9b, 0x33, 0x3d, 0xf6, 0x8a, 0x5c, 0xa8, - 0x0e, 0x7f, 0x51, 0x5f, 0x98, 0x07, 0x3b, 0xa3, 0x96, 0xf0, 0xe8, 0xf7, 0x20, 0x03, 0xe5, 0x1f, 0x4c, 0x4c, 0x16, - 0x2c, 0xb9, 0xa5, 0xa5, 0x88, 0xff, 0xf1, 0x4a, 0x98, 0x58, 0x55, 0x07, 0x30, 0x90, 0x03, 0x53, 0xf1, 0x00, 0x6e, - 0x4d, 0xf8, 0x84, 0xb3, 0x3c, 0x3d, 0x88, 0xfe, 0xd1, 0x12, 0xad, 0x7f, 0x44, 0xff, 0x00, 0x77, 0x67, 0xf7, 0x3a, - 0x64, 0x15, 0x17, 0xc2, 0xdf, 0x63, 0x3d, 0xae, 0x54, 0xca, 0x58, 0x7b, 0xdd, 0x72, 0x78, 0x21, 0xf5, 0x36, 0x8b, - 0x1f, 0x3b, 0x62, 0x6d, 0x53, 0xb0, 0x0e, 0x29, 0x29, 0x3c, 0xbb, 0x62, 0x6e, 0xb5, 0x98, 0xbb, 0xd4, 0x12, 0xfe, - 0xfa, 0xea, 0x71, 0xa5, 0x82, 0x86, 0x83, 0xd0, 0x95, 0xb6, 0x90, 0x00, 0x03, 0x97, 0xca, 0xa7, 0xd3, 0x9d, 0x49, - 0x64, 0x9c, 0xc5, 0xf0, 0xee, 0x41, 0x10, 0x48, 0x80, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, 0x3a, 0xea, 0xa5, 0x24, - 0x10, 0x80, 0xbe, 0xf2, 0x1e, 0x94, 0x57, 0x65, 0xbf, 0xd5, 0x92, 0xa0, 0x85, 0xa5, 0xe6, 0x5a, 0x15, 0xd3, 0xc3, - 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, 0x10, 0xac, 0xb2, 0x83, - 0xf2, 0xef, 0x62, 0x8a, 0x6c, 0xfe, 0x90, 0x7d, 0x47, 0x5d, 0x87, 0x23, 0x57, 0xb0, 0xee, 0xa5, 0x8a, 0x82, 0x01, - 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0xf5, 0xdc, 0x9e, 0x35, 0xfd, 0x86, - 0x8c, 0xb3, 0x8f, 0x30, 0xce, 0x3e, 0x0a, 0xbc, 0x58, 0x24, 0xf9, 0x41, 0xc6, 0x1a, 0xc7, 0xaa, 0x2d, 0xd0, 0x49, - 0x0f, 0xb8, 0x33, 0x70, 0xe0, 0x01, 0x5b, 0x94, 0xa3, 0x23, 0xea, 0x2c, 0xee, 0x69, 0x2b, 0xf3, 0xde, 0x9e, 0x50, - 0xbb, 0x8c, 0x05, 0x6e, 0x37, 0xcc, 0xb4, 0xa0, 0xb5, 0xd2, 0x38, 0x8f, 0x87, 0x11, 0x19, 0x1b, 0xf1, 0x13, 0xb6, - 0xac, 0xa9, 0x9a, 0x37, 0xd0, 0x1c, 0x35, 0x82, 0xdc, 0xbc, 0x32, 0xde, 0xaa, 0x64, 0x18, 0x45, 0x23, 0xcb, 0xa9, - 0x10, 0x43, 0x32, 0x86, 0x9d, 0x51, 0x70, 0xab, 0xbd, 0x5e, 0x73, 0x8f, 0xf8, 0xa2, 0xe1, 0xad, 0x66, 0x6e, 0x01, - 0xb2, 0x32, 0x8e, 0xaa, 0x7b, 0x93, 0x08, 0xbc, 0x6f, 0xab, 0x08, 0x69, 0xab, 0xa1, 0x7d, 0xba, 0xb2, 0x52, 0x6c, - 0xbe, 0xa7, 0xd3, 0x51, 0x1a, 0xd9, 0x11, 0x45, 0xf8, 0x53, 0x05, 0x49, 0xb8, 0x4a, 0xfa, 0xa4, 0x32, 0xb9, 0x60, - 0x2a, 0xe5, 0xf8, 0x53, 0x29, 0xa5, 0xbe, 0xb1, 0x5f, 0x12, 0xd7, 0x77, 0x32, 0x02, 0x7f, 0x9a, 0x32, 0xfd, 0x9e, - 0x96, 0x53, 0x06, 0x7e, 0x45, 0xfe, 0x76, 0x2c, 0xa5, 0xe4, 0xfa, 0x95, 0x88, 0x87, 0x14, 0xc3, 0xbb, 0xab, 0x23, - 0xac, 0x4d, 0x08, 0x94, 0x0a, 0x17, 0xe1, 0x82, 0xe8, 0x6d, 0x29, 0xef, 0xee, 0xe3, 0x12, 0x3b, 0x07, 0xc0, 0xca, - 0x69, 0x12, 0xe0, 0x5f, 0x3d, 0xe6, 0x63, 0x35, 0xe6, 0xd4, 0xe8, 0xfa, 0xdd, 0xef, 0xe4, 0x13, 0xd0, 0xdb, 0xca, - 0x51, 0x70, 0xd8, 0x19, 0x41, 0x2e, 0xdc, 0x85, 0xc1, 0xc5, 0x57, 0x58, 0xbb, 0x2c, 0x8d, 0x37, 0x16, 0x40, 0xef, - 0x49, 0x06, 0x16, 0x6c, 0x98, 0x63, 0x0a, 0x8f, 0xd6, 0x4e, 0x99, 0x0e, 0xa2, 0x82, 0x3c, 0xab, 0x9e, 0x25, 0x6d, - 0xd4, 0x7e, 0xc7, 0x26, 0x70, 0x87, 0x91, 0x7c, 0xbd, 0x70, 0xe2, 0xc0, 0x03, 0x32, 0x4d, 0x66, 0x9b, 0x7d, 0xeb, - 0x23, 0x8f, 0xbc, 0x99, 0xc4, 0xfb, 0x5a, 0x0a, 0xf3, 0xcd, 0x8a, 0x6e, 0x30, 0x84, 0xa2, 0x08, 0xfb, 0xbd, 0x55, - 0x31, 0x45, 0xb5, 0x41, 0x1b, 0x34, 0x2c, 0x6f, 0xc5, 0x0f, 0x70, 0xc6, 0xd0, 0x66, 0x21, 0x7b, 0x47, 0x67, 0x1d, - 0xce, 0x1c, 0x66, 0xcc, 0x08, 0x8c, 0x4a, 0xcb, 0x92, 0x4e, 0xc1, 0xd1, 0xb9, 0xfe, 0x20, 0x2a, 0xae, 0x8f, 0x15, - 0x80, 0x27, 0x99, 0xc1, 0x3f, 0xc5, 0x36, 0x58, 0x0f, 0x3b, 0x0d, 0xc3, 0xd4, 0x1f, 0xf4, 0xae, 0x6b, 0xf9, 0x2a, - 0xc4, 0x91, 0x2e, 0x86, 0xd0, 0x3a, 0x77, 0xf7, 0x80, 0x22, 0x2e, 0xe8, 0x45, 0xaa, 0xf1, 0x27, 0xb5, 0x1c, 0x9b, - 0xf5, 0x35, 0xae, 0x63, 0xda, 0x20, 0x8a, 0x75, 0xd7, 0xc4, 0x9f, 0xea, 0x57, 0x60, 0x55, 0x0a, 0xac, 0x33, 0x28, - 0x3f, 0x54, 0x75, 0xd9, 0x90, 0x4a, 0x72, 0x6d, 0x3a, 0x95, 0xa6, 0xd3, 0x1a, 0xa1, 0x5c, 0x7a, 0x52, 0xdd, 0xbf, - 0x42, 0x08, 0x03, 0x53, 0x66, 0x0f, 0x56, 0xa9, 0x1d, 0xac, 0x82, 0x57, 0x2f, 0xb6, 0xb0, 0x4a, 0xc2, 0xf1, 0x5c, - 0xa1, 0x51, 0x59, 0xe3, 0x90, 0x21, 0x7d, 0x21, 0x16, 0x41, 0x02, 0x60, 0xd1, 0x8f, 0x99, 0xcb, 0xfb, 0x16, 0x0e, - 0x85, 0x3d, 0xc9, 0x24, 0x9c, 0x6e, 0x42, 0x0b, 0x78, 0x1e, 0x58, 0x0d, 0x3c, 0x42, 0xcc, 0x4c, 0xfc, 0x27, 0x78, - 0x16, 0xfa, 0xdb, 0xcf, 0xd1, 0x3a, 0x0b, 0xf2, 0xf4, 0xdf, 0xa2, 0x24, 0x34, 0xf6, 0x3f, 0xc7, 0x43, 0x87, 0x84, - 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe3, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0x36, 0xa1, 0x07, 0x80, 0x25, 0x14, - 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x54, 0xf7, 0xb7, 0x1d, 0x2f, - 0xa5, 0x35, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf5, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, 0xfb, 0xc2, 0x9f, 0x1c, - 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xca, 0xc5, 0x61, 0xdb, 0x41, 0xf7, 0x02, 0x73, - 0x75, 0x53, 0x67, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0xaa, 0x0a, 0x2e, 0x40, 0xbc, - 0x1f, 0x08, 0x93, 0x53, 0x45, 0x03, 0x78, 0x9f, 0x55, 0x8f, 0x4e, 0x0d, 0x38, 0xb8, 0x8c, 0x1b, 0x36, 0xf1, 0x99, - 0xf0, 0xa9, 0xc0, 0x4a, 0x5a, 0xe3, 0xd0, 0x88, 0xe6, 0x74, 0x01, 0x66, 0x1b, 0x40, 0xc1, 0xdd, 0xf9, 0xb0, 0xb5, - 0x50, 0xc1, 0x93, 0xbc, 0x8d, 0x17, 0xb4, 0x09, 0x71, 0x26, 0x4d, 0xc1, 0xdd, 0x76, 0x59, 0x06, 0xe6, 0xb7, 0xff, - 0x51, 0x58, 0x24, 0x18, 0x50, 0xa5, 0x49, 0x82, 0xf0, 0x04, 0x95, 0x91, 0x6e, 0xed, 0x66, 0x02, 0xe9, 0x44, 0x84, - 0x37, 0xcc, 0x3f, 0x6e, 0x9d, 0xaf, 0x8e, 0x1a, 0x88, 0x9a, 0x1a, 0xa8, 0x80, 0x1a, 0xc8, 0xe6, 0xf6, 0x2f, 0x61, - 0x21, 0x6c, 0x84, 0x2a, 0x11, 0x04, 0x44, 0x58, 0x68, 0xc3, 0x07, 0x94, 0x49, 0x08, 0x79, 0x03, 0xa8, 0x98, 0x92, - 0x77, 0x60, 0x34, 0x0e, 0xaf, 0xf7, 0x80, 0xfb, 0xa5, 0x65, 0x18, 0x3c, 0xa7, 0x60, 0xf2, 0x5f, 0xf8, 0x7c, 0xa8, - 0x5e, 0xad, 0x0e, 0x42, 0xf8, 0x19, 0xc4, 0x8a, 0x70, 0xfc, 0xc5, 0x0f, 0x40, 0x36, 0x15, 0x96, 0x47, 0x47, 0x12, - 0x04, 0x7e, 0x88, 0x22, 0x1c, 0xf0, 0x0c, 0xef, 0xb2, 0x2d, 0xa2, 0xe7, 0x67, 0xa5, 0xea, 0x59, 0xc9, 0x60, 0x56, - 0xa5, 0xa7, 0x71, 0x74, 0x43, 0x18, 0x08, 0x2e, 0xd4, 0xee, 0x1b, 0x84, 0x40, 0xd9, 0x72, 0x6b, 0xe8, 0xd2, 0x73, - 0x30, 0x1f, 0x8d, 0xa3, 0x77, 0x0c, 0x1e, 0x16, 0x36, 0xee, 0x28, 0x4c, 0xb3, 0x4c, 0x1b, 0xe6, 0xb1, 0x15, 0x38, - 0xa9, 0x53, 0x94, 0xfc, 0x29, 0xb9, 0x88, 0xa3, 0xf6, 0x75, 0x84, 0x5a, 0xf0, 0x6f, 0x8b, 0xa3, 0x3e, 0x4d, 0x68, - 0x9e, 0xfb, 0xe0, 0x37, 0x19, 0x31, 0x9b, 0x6c, 0xbd, 0x16, 0x35, 0x41, 0x4f, 0xec, 0x06, 0x03, 0x56, 0xe2, 0x19, - 0xb0, 0x0f, 0x96, 0x83, 0x25, 0xef, 0x45, 0xac, 0xfc, 0x29, 0x85, 0xc1, 0xea, 0x39, 0x43, 0x08, 0x67, 0x01, 0x93, - 0xf2, 0x3f, 0x9f, 0x69, 0xb8, 0x7e, 0x7e, 0xbe, 0x8e, 0x11, 0x91, 0x3e, 0x88, 0x5c, 0x83, 0x1d, 0x11, 0x41, 0xd8, - 0x32, 0x3d, 0x74, 0x65, 0xbe, 0xf3, 0xd6, 0xd5, 0x23, 0x1b, 0x2e, 0x0e, 0x0c, 0xa8, 0x51, 0x60, 0xb4, 0x82, 0x0b, - 0x52, 0x0d, 0x1c, 0x94, 0x10, 0x9a, 0x95, 0xf1, 0x8c, 0x5c, 0x43, 0x24, 0xbc, 0x0c, 0xf5, 0xc1, 0xb0, 0x20, 0x90, - 0xa0, 0x66, 0x20, 0x41, 0x65, 0xbe, 0x76, 0x0e, 0xb3, 0x2e, 0xcc, 0x6c, 0x67, 0xa8, 0xef, 0x82, 0xfc, 0xfc, 0xa0, - 0xe3, 0x1c, 0x58, 0xda, 0xa3, 0xa3, 0x12, 0x22, 0x88, 0x01, 0x05, 0xaf, 0x24, 0xc0, 0x40, 0x03, 0x5e, 0x6e, 0x69, - 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x2a, 0xc8, 0xc5, 0xeb, 0x7a, 0x4f, 0x13, 0x42, 0x0e, 0x3b, 0x03, - 0x9d, 0xee, 0x46, 0x48, 0x1c, 0xfc, 0xaa, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xeb, 0x8d, 0xf9, 0x77, 0x43, 0x8f, 0x58, - 0x4f, 0x42, 0xba, 0x20, 0x5d, 0x9e, 0x4f, 0x7b, 0x0d, 0x57, 0xac, 0xd2, 0xc8, 0xc1, 0x25, 0xe8, 0xb3, 0x01, 0x01, - 0x4a, 0x54, 0x99, 0x4a, 0xd0, 0x32, 0x2e, 0x93, 0x8a, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, 0xd6, 0x2b, 0x41, 0xb7, 0xd6, - 0x00, 0x78, 0x67, 0x66, 0xff, 0x54, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, 0x1c, 0x76, 0x2b, 0x76, 0x5d, - 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0x5e, 0xec, 0xf2, 0x09, 0x10, 0xa2, 0xb6, 0x62, - 0x1a, 0xb1, 0x84, 0x21, 0xeb, 0xc6, 0x90, 0x8d, 0x36, 0x14, 0x9e, 0x4a, 0xe4, 0xc0, 0x25, 0x9a, 0x20, 0xf9, 0x8e, - 0x4b, 0x70, 0x08, 0x2f, 0x3c, 0xc2, 0x7f, 0x01, 0x16, 0xa9, 0xc4, 0x0c, 0xcb, 0xf5, 0x1a, 0xea, 0x79, 0xbc, 0xcf, - 0xb6, 0x83, 0x93, 0xca, 0xad, 0xb1, 0x4b, 0x3b, 0xf1, 0xb8, 0x6a, 0x42, 0xe2, 0x0c, 0xfa, 0xf5, 0x15, 0xd1, 0xe0, - 0xb0, 0x9b, 0xbe, 0xf2, 0xef, 0x95, 0xb9, 0x1d, 0x88, 0x0d, 0xeb, 0x0d, 0x56, 0x1f, 0x40, 0xcb, 0xff, 0xcc, 0xfc, - 0x43, 0x65, 0xc1, 0x4d, 0x82, 0xda, 0x5e, 0xc4, 0x3e, 0xeb, 0x23, 0x46, 0x1a, 0x8b, 0xbb, 0x47, 0x88, 0xff, 0x73, - 0x27, 0x8a, 0x01, 0x4f, 0x6a, 0xfe, 0x39, 0x46, 0x7d, 0x08, 0x45, 0x6d, 0x3d, 0x6c, 0x80, 0xd2, 0xae, 0x36, 0xb5, - 0x18, 0x19, 0x12, 0xc8, 0x77, 0x2e, 0xbc, 0xa0, 0x39, 0x89, 0x14, 0xc8, 0xc9, 0x75, 0x17, 0x4f, 0xb2, 0x2d, 0x61, - 0xae, 0xbf, 0x83, 0x63, 0xe6, 0x6a, 0x23, 0x2b, 0xe3, 0xf7, 0xc0, 0xce, 0x70, 0x23, 0x59, 0x3a, 0xf0, 0xa9, 0x06, - 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0xd0, 0xe0, 0xbd, 0x7d, 0x64, 0x0e, 0x7e, 0xa7, 0x81, 0xf8, 0x98, 0x39, 0x1d, - 0xc9, 0x56, 0xa8, 0x35, 0x67, 0xc7, 0xcb, 0xb6, 0x23, 0x0c, 0x0a, 0x1b, 0xbd, 0xaf, 0x46, 0x56, 0xb1, 0xb7, 0x53, - 0x11, 0xcc, 0xe9, 0x56, 0xd5, 0xce, 0xa9, 0xdc, 0x32, 0xaa, 0x95, 0xa6, 0x01, 0x22, 0x5c, 0xf9, 0x44, 0xf2, 0x31, - 0x33, 0xe1, 0x1f, 0x0c, 0xc6, 0x35, 0x23, 0x85, 0x7f, 0xdc, 0x17, 0x3b, 0x64, 0x37, 0x3a, 0xdc, 0x56, 0xd0, 0xbc, - 0x50, 0xc1, 0x03, 0x8e, 0x4a, 0x96, 0x10, 0x29, 0x72, 0x7d, 0xa8, 0x1a, 0xa6, 0x6c, 0x9f, 0x22, 0x84, 0x90, 0xf6, - 0x38, 0xeb, 0x86, 0xd6, 0x0c, 0x3d, 0x52, 0x3b, 0x4d, 0xee, 0xd0, 0x5c, 0x17, 0xa0, 0xc2, 0x08, 0xa4, 0xab, 0xcf, - 0xec, 0x3e, 0x95, 0x10, 0xbd, 0x7c, 0xe3, 0x42, 0x18, 0x3b, 0x2b, 0x4b, 0x5c, 0x9a, 0x51, 0xdb, 0x30, 0xba, 0x6e, - 0x63, 0x38, 0x1b, 0x18, 0x33, 0x0d, 0x4a, 0x3a, 0x10, 0xea, 0xba, 0x4f, 0xaf, 0x32, 0x13, 0xe8, 0xb1, 0x20, 0xb4, - 0xc5, 0xf0, 0x8c, 0x68, 0xb0, 0x6c, 0x2a, 0xc1, 0x82, 0x6f, 0x55, 0xa6, 0xd6, 0x66, 0x93, 0xc5, 0xbf, 0xea, 0xd8, - 0x3c, 0xed, 0x57, 0xd4, 0xcc, 0x73, 0xe9, 0xa3, 0x23, 0x64, 0x3e, 0x1e, 0xdd, 0xf3, 0xb7, 0x37, 0xaf, 0x7e, 0x7c, - 0xf3, 0x7a, 0xbd, 0xee, 0xb2, 0x76, 0xf7, 0x0c, 0xff, 0x53, 0x57, 0xf1, 0x60, 0xab, 0x28, 0x40, 0x47, 0x47, 0x87, - 0xdc, 0xb8, 0xf0, 0x7c, 0xe6, 0x0b, 0x88, 0x1b, 0xa4, 0x47, 0xb8, 0x28, 0xab, 0x98, 0x20, 0x77, 0xd1, 0x20, 0xba, - 0x8f, 0x40, 0x09, 0x55, 0x93, 0xbf, 0x5f, 0xb6, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, - 0xa5, 0xb8, 0x24, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, 0x44, 0xc5, 0x25, 0x90, 0x44, - 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0x17, 0xce, 0x5d, 0xaa, 0x40, 0x83, 0x4e, - 0x5a, 0xe0, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xef, 0x4f, 0x07, 0x71, 0x5c, 0xe0, 0x25, 0x11, 0xc7, 0xfe, 0x59, - 0xc4, 0xd5, 0xa2, 0x64, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x97, 0xca, 0xe4, 0xae, 0x9d, 0x1f, 0xc7, 0x65, 0x72, - 0xd7, 0x56, 0xc9, 0x1d, 0xc2, 0xf7, 0xa9, 0x4c, 0xee, 0x6d, 0xca, 0x7d, 0x5b, 0xc1, 0xcd, 0x17, 0x16, 0x70, 0x28, - 0xda, 0xa2, 0xad, 0xe5, 0x76, 0x51, 0x9b, 0xe2, 0x8a, 0x86, 0xd1, 0x14, 0xf7, 0x6c, 0xfc, 0x30, 0x7c, 0x09, 0xae, - 0x4c, 0x9a, 0xc8, 0x3f, 0x41, 0xfa, 0xe9, 0xd4, 0x06, 0xee, 0x33, 0xd2, 0xe9, 0xcf, 0xae, 0x44, 0xbb, 0xdb, 0x6f, - 0xb5, 0x66, 0xb0, 0x77, 0x33, 0x52, 0xf8, 0x62, 0xb3, 0x96, 0x89, 0xaf, 0x73, 0x98, 0xad, 0xd7, 0x87, 0x05, 0x32, - 0x1b, 0x6e, 0xca, 0x62, 0x3d, 0x9c, 0x8d, 0x70, 0x07, 0x7f, 0xc8, 0x10, 0x5a, 0xb1, 0xe1, 0x6c, 0x44, 0xd8, 0x70, - 0xd6, 0xea, 0x8e, 0xac, 0xa1, 0x9d, 0xd9, 0x8a, 0x1b, 0x08, 0xa1, 0x39, 0x1b, 0x9d, 0x98, 0x92, 0xd2, 0xe5, 0xdb, - 0x2f, 0x5a, 0x07, 0xf4, 0x53, 0x8d, 0xe0, 0x65, 0x12, 0xf7, 0xa0, 0x2f, 0x7a, 0x65, 0x9f, 0x6e, 0x2d, 0xc9, 0xe9, - 0x49, 0xed, 0x6a, 0x4f, 0x11, 0x36, 0x3d, 0xa9, 0xe3, 0xf2, 0xd8, 0x34, 0xe3, 0xba, 0x94, 0xee, 0x3b, 0xd4, 0x8c, - 0xfc, 0xe5, 0x60, 0x01, 0x08, 0x52, 0xc3, 0xa3, 0x28, 0x5d, 0x38, 0xa5, 0x10, 0x2e, 0x0e, 0x2a, 0x3b, 0x30, 0x29, - 0x48, 0xa7, 0x5f, 0x18, 0x4b, 0xff, 0xc2, 0x45, 0x34, 0xa5, 0x98, 0x92, 0xcc, 0x97, 0x2c, 0x0c, 0x58, 0xe8, 0x36, - 0xe5, 0x99, 0x81, 0x5e, 0x69, 0x84, 0x73, 0x02, 0xf1, 0x90, 0xfa, 0xa5, 0x31, 0xf0, 0x8a, 0x67, 0xed, 0x72, 0xc8, - 0x46, 0xe8, 0xe4, 0x14, 0xd3, 0xe1, 0x1f, 0xd9, 0xa2, 0x0b, 0x8f, 0x05, 0xfe, 0x31, 0x22, 0xb3, 0xb6, 0xac, 0x12, - 0x04, 0x24, 0xe4, 0x6d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x86, 0x6c, 0xd4, 0x9e, 0x55, 0x15, 0x7b, - 0xbe, 0x62, 0x4b, 0x56, 0x09, 0xb6, 0x62, 0xcb, 0x55, 0x0c, 0x5f, 0x67, 0x30, 0x20, 0x08, 0x01, 0xc0, 0x00, 0x00, - 0x1a, 0x05, 0xd1, 0x7c, 0xb1, 0x22, 0x7e, 0xb3, 0xdb, 0x7b, 0xfc, 0x0e, 0x58, 0xa0, 0x35, 0xf6, 0xff, 0x3e, 0x94, - 0x01, 0x7b, 0xca, 0xd2, 0xc4, 0xcc, 0x2d, 0xad, 0x8a, 0x0e, 0xa0, 0x52, 0x21, 0x4c, 0x69, 0x20, 0x73, 0x98, 0x19, - 0xa8, 0x05, 0x5a, 0x83, 0x62, 0xa8, 0x47, 0xed, 0x0c, 0x8e, 0x18, 0x78, 0x87, 0x86, 0xcc, 0x8c, 0x31, 0x61, 0x5c, - 0xc0, 0x14, 0x33, 0x03, 0x9e, 0x59, 0xda, 0xd9, 0x48, 0x23, 0xcb, 0x0d, 0x8a, 0xc1, 0x5f, 0x3a, 0x56, 0xc3, 0xb2, - 0xdd, 0x1d, 0xa1, 0x43, 0x42, 0xec, 0xc7, 0x08, 0x36, 0x99, 0x4b, 0x6d, 0x99, 0xef, 0x93, 0x5e, 0x6a, 0x3f, 0xe1, - 0xcf, 0x68, 0x63, 0x76, 0x00, 0xe8, 0xc8, 0xb0, 0x59, 0x7f, 0xd9, 0x50, 0x79, 0xfd, 0xba, 0x37, 0x4a, 0xe5, 0xbe, - 0x77, 0xa7, 0x03, 0xd5, 0x44, 0xe8, 0xad, 0x87, 0xab, 0x87, 0x7a, 0x08, 0x98, 0x31, 0x98, 0x5b, 0x66, 0xf4, 0xad, - 0x10, 0xc9, 0x25, 0x91, 0xc0, 0x92, 0x60, 0x4a, 0x18, 0xec, 0xad, 0xa3, 0x23, 0x53, 0x8d, 0xb5, 0xe0, 0x79, 0x52, - 0x04, 0x82, 0x81, 0x8f, 0xa0, 0x0c, 0x68, 0xa2, 0xcc, 0x6d, 0x38, 0xf9, 0x95, 0xb9, 0x5f, 0xb8, 0xba, 0x7d, 0x2c, - 0x9d, 0xb6, 0xd5, 0x5c, 0x8f, 0x57, 0x05, 0xee, 0xab, 0x7b, 0x49, 0xab, 0xe0, 0x46, 0xf6, 0x26, 0x4f, 0x99, 0xbb, - 0x75, 0x5f, 0xaa, 0xb7, 0xbf, 0x99, 0x5e, 0xd5, 0x4c, 0x6f, 0xb7, 0x99, 0x30, 0xae, 0xe4, 0xd7, 0xac, 0x22, 0xcd, - 0xc9, 0x9a, 0xa8, 0x05, 0x15, 0xff, 0xa4, 0x0b, 0xd0, 0x8e, 0x72, 0x7b, 0xaf, 0x0a, 0x27, 0x57, 0x41, 0xae, 0x0f, - 0x0b, 0x43, 0x5c, 0x91, 0xb9, 0x50, 0x87, 0x00, 0x2f, 0xaf, 0xaa, 0xc7, 0x07, 0xb8, 0x14, 0x3f, 0xc9, 0xdc, 0x45, - 0x39, 0x15, 0x52, 0x4b, 0xc1, 0x22, 0x64, 0x50, 0xd5, 0xc5, 0xc0, 0x5e, 0xd9, 0xbd, 0x27, 0x06, 0x7c, 0x58, 0x47, - 0xcc, 0x1b, 0x99, 0xe7, 0x3e, 0xbe, 0xa5, 0x29, 0x76, 0x6a, 0xe2, 0x8c, 0xfc, 0x92, 0xc5, 0x05, 0xc8, 0x66, 0xc3, - 0xfa, 0xb5, 0xdf, 0x56, 0x17, 0x97, 0xed, 0x58, 0x0c, 0xcc, 0x13, 0x27, 0xdf, 0x95, 0xc6, 0x38, 0xc0, 0x3a, 0xfa, - 0x23, 0x4c, 0x2d, 0xd8, 0xb3, 0xc4, 0x53, 0xe8, 0xe4, 0xce, 0xa6, 0xdd, 0x87, 0x69, 0xf7, 0x26, 0xad, 0x07, 0xe5, - 0x80, 0x34, 0xbb, 0x32, 0xbd, 0x7b, 0xff, 0x7d, 0x0f, 0x2f, 0xdd, 0x6e, 0x20, 0x12, 0xf7, 0xe2, 0x89, 0x31, 0x86, - 0x78, 0x0b, 0x36, 0xa2, 0xea, 0xe8, 0xe8, 0x07, 0xe7, 0x7d, 0x5b, 0xcb, 0xb2, 0x5f, 0x0b, 0x07, 0xb6, 0xc5, 0x54, - 0xba, 0xbc, 0x5c, 0x66, 0x4b, 0xb0, 0xeb, 0x3c, 0xfc, 0x4a, 0x3c, 0x7c, 0x11, 0x32, 0x2d, 0xd6, 0x55, 0xfc, 0xb5, - 0xcc, 0x2b, 0x0f, 0x51, 0x0d, 0x11, 0x48, 0x6b, 0xeb, 0xd2, 0xd0, 0x74, 0xf4, 0x66, 0x46, 0x73, 0x79, 0xfb, 0x4e, - 0x4a, 0x3d, 0xb2, 0x2f, 0x72, 0xeb, 0x04, 0x1e, 0x2d, 0x6c, 0x30, 0x34, 0xf7, 0x95, 0x77, 0x92, 0x0d, 0x88, 0xda, - 0x1c, 0x77, 0x28, 0x89, 0xc4, 0xa2, 0xbe, 0x0b, 0xe1, 0x70, 0x17, 0x82, 0x79, 0x15, 0xb4, 0x0d, 0x62, 0xb7, 0xbb, - 0xa0, 0x6d, 0xe0, 0xd4, 0x6d, 0x03, 0xb7, 0x07, 0x83, 0x85, 0xbd, 0x0f, 0x2f, 0xc7, 0x72, 0x2c, 0x1c, 0x7f, 0xf0, - 0xd6, 0x3e, 0x00, 0x04, 0x6a, 0x1f, 0x56, 0x3e, 0x73, 0x20, 0x48, 0x9c, 0xe1, 0xe8, 0x47, 0xce, 0x6e, 0xad, 0xe5, - 0xf0, 0x7c, 0xb1, 0xd4, 0x2c, 0x37, 0x77, 0xd4, 0xa0, 0xe2, 0x6b, 0xfa, 0x79, 0xfd, 0x9c, 0x35, 0x74, 0xe3, 0x6f, - 0x21, 0x8c, 0x84, 0x53, 0x76, 0x18, 0x85, 0x84, 0x0d, 0x66, 0x55, 0xc5, 0x6b, 0xfb, 0x0d, 0xe2, 0x3d, 0x68, 0x13, - 0x4e, 0xb0, 0x6c, 0x5c, 0x50, 0x45, 0xd8, 0xc6, 0x1b, 0x0b, 0xa2, 0x3c, 0x3c, 0xd8, 0x31, 0x9a, 0x5e, 0x6d, 0x20, - 0xd0, 0xf1, 0x20, 0x6a, 0x47, 0x2d, 0x96, 0xba, 0xa0, 0xcc, 0x3e, 0xc2, 0xb8, 0xba, 0x3a, 0x33, 0x71, 0xda, 0x2b, - 0xbd, 0xfa, 0x6f, 0x19, 0x18, 0xe0, 0x0b, 0xf0, 0x12, 0x0b, 0xa3, 0xbb, 0x0e, 0x75, 0x0b, 0xea, 0xcb, 0x16, 0x1b, - 0xa1, 0xf5, 0xba, 0x53, 0x3d, 0x03, 0xe5, 0xae, 0xb9, 0x84, 0xbd, 0xe6, 0x12, 0xee, 0x9a, 0x4b, 0xf8, 0x6b, 0x2e, - 0x61, 0xae, 0xb9, 0x84, 0xbf, 0xe6, 0xf2, 0x20, 0xfc, 0x3e, 0x88, 0xe3, 0x18, 0x73, 0x88, 0xab, 0xa8, 0x6d, 0x64, - 0x3c, 0xb8, 0xf0, 0x3c, 0x64, 0x89, 0xaa, 0x96, 0x3f, 0x8c, 0x21, 0x57, 0x6c, 0xdb, 0x4a, 0x18, 0xb7, 0x29, 0xa6, - 0x20, 0x72, 0xfa, 0xd1, 0x51, 0xed, 0xee, 0x3c, 0xec, 0x8c, 0x52, 0x8e, 0x57, 0xd6, 0x89, 0xf6, 0x5f, 0xa0, 0x93, - 0x37, 0xbf, 0x7e, 0x4d, 0xe5, 0x86, 0x08, 0x67, 0x72, 0x7f, 0xd8, 0xf5, 0x94, 0xe2, 0xfb, 0xcc, 0x84, 0x27, 0xe7, - 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0x7f, 0xb3, 0xf7, 0xae, 0xcb, 0x6d, 0x23, 0x59, 0xba, 0xe8, 0xab, - 0x48, 0x0c, 0x9b, 0x05, 0x98, 0x49, 0x8a, 0xf2, 0xde, 0x33, 0x11, 0x07, 0x54, 0x9a, 0x61, 0xcb, 0xe5, 0x2e, 0x77, - 0xf9, 0xd6, 0xb6, 0xab, 0xba, 0xaa, 0x19, 0x3c, 0x2a, 0x08, 0x48, 0x12, 0x70, 0x81, 0x00, 0x0b, 0x00, 0x25, 0xd2, - 0x24, 0xde, 0x7d, 0xc7, 0x5a, 0x2b, 0xaf, 0x20, 0x28, 0xbb, 0x67, 0xf6, 0xfc, 0x3a, 0xe7, 0x8f, 0x2d, 0x26, 0x12, - 0x89, 0xbc, 0xe7, 0xca, 0x75, 0xf9, 0xbe, 0x88, 0x17, 0xb4, 0xde, 0x55, 0x28, 0x3c, 0xaa, 0xa2, 0x94, 0x5b, 0xc9, - 0x75, 0x06, 0x41, 0xec, 0xe8, 0x85, 0xe1, 0x4f, 0x20, 0x84, 0x20, 0xc2, 0x84, 0xdf, 0x86, 0x19, 0x6d, 0x67, 0x91, - 0x4e, 0xfa, 0x7d, 0x98, 0xe1, 0x06, 0x56, 0xf2, 0x73, 0xd5, 0x67, 0xfb, 0x6d, 0x10, 0xb2, 0x5d, 0x10, 0xb1, 0xdb, - 0x62, 0x1b, 0x94, 0xd6, 0x91, 0xf8, 0x49, 0x19, 0xfe, 0x16, 0x5e, 0x2f, 0x0f, 0x21, 0xde, 0xa7, 0x97, 0xe6, 0x67, - 0x69, 0x2b, 0x0a, 0x70, 0x1f, 0xa1, 0x47, 0x75, 0x20, 0xd8, 0x09, 0x4f, 0x78, 0x00, 0x27, 0xab, 0x59, 0xc5, 0x3f, - 0xa4, 0x20, 0x4e, 0x14, 0x1c, 0x02, 0xae, 0xb6, 0x9f, 0xd2, 0xaf, 0x60, 0xf8, 0xd2, 0xc1, 0x96, 0xc3, 0xdb, 0x62, - 0xdb, 0x63, 0x25, 0x7f, 0x04, 0xec, 0x5b, 0x3d, 0x19, 0xab, 0xdb, 0x03, 0x67, 0x5d, 0x4a, 0xd1, 0xf1, 0xa6, 0x38, - 0xbc, 0x3d, 0x9f, 0xed, 0xb7, 0x41, 0xc4, 0x76, 0x41, 0x86, 0xb5, 0x4e, 0x1a, 0x8e, 0x83, 0x21, 0x7c, 0x16, 0x23, - 0xec, 0xff, 0xa2, 0x1e, 0x78, 0x09, 0xa9, 0xa1, 0xc0, 0xc5, 0x60, 0xc3, 0xd1, 0xda, 0x2e, 0xd3, 0xc0, 0x4d, 0x0d, - 0x7a, 0x7d, 0x4f, 0x21, 0xca, 0x0b, 0x46, 0x73, 0x23, 0x58, 0x37, 0x86, 0x5c, 0x1c, 0x8e, 0x9b, 0xc5, 0x90, 0x97, - 0x34, 0x9d, 0x06, 0xa1, 0x74, 0x67, 0x59, 0x43, 0x12, 0x65, 0x1f, 0x84, 0xda, 0xb5, 0x65, 0xbf, 0x0d, 0x6c, 0x5f, - 0xfe, 0x68, 0x18, 0xfb, 0x17, 0x8b, 0x27, 0x42, 0xba, 0x88, 0xe7, 0x20, 0x88, 0xda, 0xcf, 0xb3, 0xe1, 0xc6, 0xbf, - 0x58, 0x3f, 0x11, 0xca, 0x6f, 0x3c, 0xb7, 0xe5, 0x10, 0x91, 0xb5, 0xf0, 0x85, 0xf1, 0xf0, 0xe0, 0xca, 0xd0, 0x76, - 0x38, 0x08, 0xfd, 0xb7, 0x59, 0x23, 0xb8, 0xb1, 0xa1, 0x7d, 0xbe, 0xf0, 0x61, 0x6b, 0xa3, 0xb1, 0xa6, 0x98, 0x6e, - 0xa1, 0x7f, 0x93, 0xd9, 0xd2, 0x9e, 0x46, 0x25, 0x2f, 0x4e, 0x4d, 0x23, 0x16, 0xc2, 0x80, 0xa1, 0x9f, 0xcc, 0x23, - 0x50, 0xcd, 0x1d, 0x8f, 0x40, 0x26, 0x1f, 0xe8, 0xc1, 0x9a, 0xd4, 0xaa, 0xbf, 0x86, 0x99, 0xfc, 0x3f, 0x52, 0x61, - 0x31, 0xba, 0xdb, 0x86, 0x99, 0xfa, 0x23, 0x92, 0x7f, 0xb0, 0x9c, 0xef, 0x52, 0x2f, 0xd4, 0x7e, 0x2c, 0xac, 0xc0, - 0xa0, 0x44, 0xd5, 0x80, 0x1e, 0x88, 0xa0, 0x2a, 0x83, 0x34, 0xc3, 0xea, 0x1c, 0xf4, 0xbb, 0xa7, 0x55, 0x47, 0x72, - 0x48, 0x6b, 0x35, 0xa4, 0x82, 0xa9, 0x52, 0x83, 0xfc, 0x70, 0x58, 0xa6, 0x4c, 0x97, 0x01, 0x97, 0xf4, 0x65, 0xaa, - 0x94, 0xc2, 0x7f, 0x21, 0x00, 0x9d, 0x83, 0x7b, 0x7c, 0x39, 0x06, 0xd2, 0x0c, 0x0b, 0xbf, 0x35, 0x3b, 0xbe, 0x26, - 0xe1, 0x36, 0x09, 0x2e, 0x06, 0x38, 0x47, 0x57, 0x61, 0xb9, 0x4c, 0x21, 0x82, 0xaa, 0x84, 0xfa, 0x56, 0xa6, 0x41, - 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, 0x11, 0xd7, 0x33, 0xc2, 0x9a, - 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, 0x8d, 0xab, 0x4a, 0x55, 0x77, - 0x73, 0x6a, 0x29, 0x2d, 0xda, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, 0xe4, 0x08, 0x26, 0x90, 0x24, - 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, - 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0xff, 0x25, 0x8c, 0x34, 0x99, 0xb1, 0x92, 0x45, - 0xb6, 0xab, 0x53, 0xe2, 0x3c, 0x4e, 0x60, 0x7b, 0x34, 0xbd, 0xe5, 0xfb, 0x0c, 0xa2, 0x82, 0x40, 0xc1, 0x8c, 0xf9, - 0xb2, 0x8b, 0xa7, 0xbe, 0xcf, 0x2c, 0x53, 0xf7, 0xe1, 0x60, 0xcc, 0xd8, 0x7e, 0xbf, 0x9f, 0xf7, 0xfb, 0x6a, 0xbe, - 0xf5, 0xfb, 0xc9, 0x33, 0xf3, 0xb7, 0x07, 0x0c, 0x0a, 0x72, 0x22, 0x9a, 0x0a, 0x11, 0xfc, 0x43, 0xf2, 0x04, 0xc9, - 0xe8, 0x8e, 0xfb, 0xdc, 0x72, 0xb6, 0xac, 0x8e, 0x40, 0x30, 0x0f, 0x87, 0x4b, 0x05, 0x76, 0x2d, 0x51, 0x24, 0x64, - 0xf9, 0x4f, 0xc0, 0x78, 0xe6, 0x3e, 0xc0, 0x92, 0x01, 0x08, 0x5b, 0xe5, 0xe9, 0x7a, 0xcf, 0x57, 0xc1, 0x3b, 0x1d, - 0xef, 0x1a, 0x2b, 0x32, 0x10, 0xb7, 0xc0, 0x46, 0xac, 0xb5, 0x07, 0xe4, 0x4c, 0x01, 0x8e, 0x17, 0x87, 0xc3, 0xb9, - 0xfc, 0xa5, 0x9b, 0xad, 0x13, 0xa8, 0x14, 0xb8, 0x3d, 0x3a, 0x39, 0xf8, 0x1f, 0x40, 0x33, 0x28, 0x87, 0x79, 0xbd, - 0xfd, 0x83, 0x39, 0xf9, 0xe9, 0x29, 0xfe, 0x09, 0x0f, 0xd1, 0xe9, 0xb7, 0x7b, 0xf3, 0x07, 0x45, 0xe5, 0xe1, 0xa0, - 0x16, 0xff, 0x39, 0xe7, 0x15, 0xfc, 0xc2, 0x37, 0x81, 0xd9, 0x64, 0xea, 0x9d, 0x7c, 0x93, 0xe7, 0x4c, 0xbd, 0xc6, - 0x2b, 0x26, 0xdf, 0xe1, 0x70, 0x2e, 0x46, 0xf5, 0x76, 0xe4, 0x44, 0x3b, 0xe5, 0x18, 0x07, 0x83, 0xff, 0x22, 0xda, - 0x26, 0x04, 0x18, 0xca, 0xe1, 0xc8, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, - 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, 0x88, 0x53, 0x9c, 0x80, 0x08, - 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x08, 0xc1, 0x90, 0x6f, 0x24, 0xe0, 0xae, 0xd7, 0xab, 0x31, 0xbe, - 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, 0x81, 0x67, 0xcb, 0xde, 0x44, - 0xb9, 0xdb, 0xf0, 0xb4, 0x9f, 0x5a, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, - 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, 0xf0, 0xe3, 0x55, 0x40, 0x57, - 0xc6, 0xbf, 0xd3, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0x27, 0x0a, 0x1f, 0x1d, 0x8e, 0xab, 0x74, 0xb4, - 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x2a, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, 0x7b, 0x2a, 0x00, 0x8b, 0x2d, - 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, 0xb3, 0xf1, 0x14, 0xfe, 0x07, - 0x62, 0x0f, 0xcb, 0x14, 0xd9, 0xb1, 0xeb, 0xe2, 0x07, 0xf1, 0xb6, 0xb6, 0xa3, 0x3f, 0x76, 0x10, 0xe9, 0xb8, 0x27, - 0x17, 0xea, 0x4b, 0x48, 0x25, 0x17, 0xea, 0x06, 0x62, 0x17, 0x6a, 0xbc, 0xe3, 0x22, 0xd6, 0xfa, 0xdb, 0x1a, 0x05, - 0x2b, 0x01, 0x67, 0xda, 0x5b, 0x30, 0xd8, 0xc0, 0xba, 0x65, 0x19, 0xfc, 0x0d, 0xd7, 0x34, 0x81, 0x1b, 0x16, 0x59, - 0xef, 0x0d, 0xb6, 0xd2, 0x5b, 0x70, 0xb4, 0x4c, 0x9c, 0x4b, 0x49, 0x52, 0xb6, 0xc8, 0xb8, 0x7a, 0x14, 0x52, 0x35, - 0xdd, 0xdf, 0x8a, 0xfa, 0x5e, 0x88, 0x3c, 0x58, 0xa5, 0x2c, 0x2a, 0x56, 0x20, 0xb3, 0x07, 0xff, 0x0a, 0x19, 0x39, - 0xca, 0x81, 0xa3, 0xd0, 0x3f, 0x9a, 0x40, 0xe7, 0xa9, 0x23, 0x9d, 0x47, 0x82, 0xad, 0xd4, 0x43, 0x61, 0xe5, 0x05, - 0x44, 0x07, 0xdb, 0x31, 0xb7, 0xf2, 0x24, 0x54, 0x6c, 0xca, 0x44, 0x1e, 0x07, 0xb5, 0x04, 0x8c, 0x15, 0x04, 0x73, - 0x96, 0x4b, 0x17, 0xa4, 0xaa, 0xd1, 0xc3, 0x22, 0x73, 0x3f, 0x16, 0x94, 0xff, 0xb1, 0xca, 0x09, 0xd7, 0x97, 0x21, - 0xc0, 0xd1, 0x3e, 0x06, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x78, 0x27, 0x33, 0x67, 0x53, 0xdb, 0x4b, 0x90, 0xb1, 0x1d, - 0x7e, 0x85, 0xd0, 0x6a, 0xa1, 0xc8, 0xa2, 0xe1, 0x82, 0xe9, 0xf6, 0x94, 0x56, 0xdd, 0xc3, 0x86, 0x27, 0xa5, 0x87, - 0x4a, 0x7d, 0x1b, 0x13, 0x58, 0x56, 0x29, 0xc3, 0xb7, 0x13, 0xaa, 0x4e, 0x0c, 0x2a, 0xd6, 0x0d, 0x5b, 0xc0, 0x21, - 0x16, 0x93, 0xc6, 0x3a, 0x1b, 0xf0, 0x88, 0x25, 0xf0, 0xcf, 0x86, 0x8f, 0xd9, 0x82, 0x47, 0x93, 0xcd, 0xd5, 0xa2, - 0xdf, 0x2f, 0xbd, 0xd0, 0xab, 0x67, 0xd9, 0xe3, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, - 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x31, 0xbc, 0xf6, 0x98, 0x47, 0x6a, 0x49, 0x25, 0x57, 0x19, 0xec, - 0xef, 0x03, 0x1e, 0xf9, 0xac, 0xf3, 0xd3, 0xb2, 0xe9, 0xd2, 0xfd, 0xcc, 0x8e, 0xbb, 0xd0, 0x1d, 0x60, 0xe3, 0x6d, - 0x83, 0x8e, 0xfc, 0xdb, 0x1d, 0x52, 0xea, 0x26, 0x03, 0xb0, 0x1b, 0x0d, 0x70, 0xc8, 0x54, 0x2f, 0x45, 0x56, 0x2f, - 0x65, 0xaa, 0x97, 0x64, 0xe5, 0x12, 0x2c, 0x24, 0xa6, 0xca, 0x6d, 0x64, 0xe5, 0x16, 0x0d, 0xd7, 0xc3, 0xc1, 0xd6, - 0x8a, 0xcb, 0x66, 0x09, 0xf7, 0x85, 0x15, 0x05, 0xfe, 0xdf, 0xb2, 0x1b, 0x76, 0x27, 0x8f, 0x81, 0x6b, 0x74, 0x4c, - 0x82, 0x0b, 0xc4, 0x1d, 0xbb, 0x05, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, - 0xad, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x96, 0x87, 0xc3, 0xb5, 0xe7, 0xb3, 0x7b, 0xfc, - 0x71, 0xbe, 0x3c, 0x1c, 0x76, 0x9e, 0x51, 0xef, 0xbd, 0xe5, 0x09, 0x7b, 0xcf, 0x93, 0xc9, 0xdb, 0x2b, 0x1e, 0x4f, - 0x06, 0x83, 0xb7, 0xfe, 0x0d, 0xaf, 0x67, 0x6f, 0x41, 0x3b, 0x70, 0x7e, 0x23, 0x75, 0xcd, 0xde, 0x2d, 0xcf, 0xbc, - 0x1b, 0x1c, 0x9b, 0x5b, 0x38, 0x7a, 0xfb, 0x7d, 0x6f, 0xc9, 0x23, 0xef, 0x96, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, - 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0xb7, 0xc1, 0x7b, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, - 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x5b, 0xd5, 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, - 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x9e, 0xbf, 0x65, 0x77, 0xdc, 0xb0, 0xcd, 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, - 0x50, 0xea, 0xda, 0x32, 0xac, 0xb4, 0xae, 0x7c, 0x08, 0x1c, 0x0e, 0xc8, 0x4f, 0x4b, 0xc4, 0x41, 0x68, 0xdd, 0x64, - 0x35, 0x57, 0x94, 0x73, 0xa1, 0x0d, 0x33, 0x2f, 0x07, 0x16, 0xb3, 0x94, 0x42, 0x63, 0x01, 0x80, 0x60, 0x52, 0x68, - 0xed, 0xbd, 0x0c, 0x20, 0x27, 0x68, 0xf8, 0x63, 0x73, 0x55, 0x96, 0xb5, 0x6c, 0x49, 0x88, 0xb2, 0x5d, 0x0f, 0x2f, - 0x11, 0x32, 0xad, 0xdf, 0x3f, 0x27, 0x92, 0xb5, 0x49, 0x75, 0x55, 0xa3, 0x25, 0xa0, 0x22, 0x4b, 0xc0, 0xc4, 0xaf, - 0x34, 0x9f, 0x00, 0x3c, 0xe9, 0x78, 0x50, 0x3d, 0xe6, 0x35, 0x13, 0x44, 0xb6, 0x51, 0xf9, 0x93, 0xe2, 0x19, 0x92, - 0x11, 0x14, 0x8f, 0x6b, 0x95, 0xb1, 0x30, 0xcc, 0x03, 0x05, 0xe4, 0xdd, 0xbb, 0x53, 0xdf, 0xda, 0x1f, 0x3b, 0xf6, - 0x6c, 0xad, 0x42, 0x2d, 0xd4, 0x14, 0x2e, 0x39, 0x44, 0x57, 0xa0, 0x81, 0x22, 0x92, 0xf1, 0xe4, 0xf5, 0xe0, 0x72, - 0x12, 0x5d, 0x71, 0x81, 0xce, 0xf8, 0xfa, 0xa6, 0x9b, 0xce, 0xa2, 0xc7, 0xd5, 0x7c, 0x42, 0x4a, 0xb2, 0xc3, 0x21, - 0x1b, 0x55, 0x75, 0xb1, 0x9e, 0x86, 0xf2, 0xa7, 0x87, 0xe0, 0xeb, 0x05, 0xf5, 0x9a, 0xac, 0x52, 0xfd, 0x98, 0x2a, - 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x71, 0x25, 0xf7, 0x3d, 0x20, 0xad, 0xe5, 0x25, 0x97, 0xef, 0x47, 0x88, 0x31, 0xe2, - 0x07, 0x5e, 0xc9, 0x23, 0x16, 0xaa, 0x29, 0x5c, 0xf3, 0x08, 0x41, 0xde, 0x32, 0x1d, 0xfc, 0xad, 0x27, 0x4e, 0xf7, - 0x27, 0x4a, 0xbb, 0xf8, 0xc2, 0xa2, 0xee, 0x39, 0xd2, 0x0d, 0xc8, 0xc1, 0x86, 0xe9, 0xa2, 0x20, 0xdb, 0x94, 0x46, - 0xd0, 0x46, 0xcb, 0x81, 0x0d, 0xa7, 0x52, 0x1b, 0xce, 0x5c, 0x43, 0x70, 0x9f, 0x9f, 0xa7, 0xa3, 0x1b, 0xf8, 0x90, - 0xea, 0xf6, 0x12, 0x3f, 0x1f, 0x36, 0x1c, 0xc9, 0xec, 0x88, 0xcf, 0x6c, 0x22, 0xe9, 0xa4, 0xce, 0x15, 0xb0, 0xdb, - 0xd9, 0x35, 0xc8, 0x11, 0x33, 0xf7, 0x15, 0xaa, 0x6f, 0xd1, 0x80, 0x2b, 0x63, 0xed, 0x6b, 0x92, 0xb1, 0xf0, 0xaa, - 0x9c, 0x86, 0x03, 0x80, 0xa1, 0xcb, 0xe8, 0x6b, 0x8b, 0x4d, 0x96, 0xbd, 0x29, 0x20, 0x08, 0xa2, 0x24, 0x1e, 0x1f, - 0xf0, 0xbe, 0xac, 0x86, 0x1a, 0x25, 0x1f, 0xcb, 0x4e, 0xe0, 0xeb, 0x25, 0xfa, 0xbb, 0x31, 0x97, 0x18, 0xf0, 0xba, - 0x6a, 0x0b, 0x0a, 0xe7, 0xf9, 0xe1, 0x70, 0x9e, 0x8f, 0x8c, 0x67, 0x19, 0xa8, 0x56, 0xa6, 0x75, 0xb0, 0x31, 0xf3, - 0xc5, 0xc2, 0x5f, 0xec, 0x9c, 0x44, 0x44, 0x41, 0x60, 0x47, 0xc2, 0x83, 0x48, 0xfd, 0xbe, 0xf2, 0x74, 0xa7, 0xfa, - 0x6c, 0x7f, 0x63, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, - 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, 0x9d, 0xc6, 0x36, 0x3c, 0xb6, 0xb0, 0x1a, 0xbd, - 0x35, 0x5b, 0xb2, 0x15, 0xbb, 0x55, 0x75, 0xba, 0xe1, 0xe1, 0x74, 0x78, 0x19, 0xe0, 0xea, 0x5b, 0x9f, 0x73, 0xbe, - 0xa4, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, 0xd6, 0x8f, 0x23, 0xb5, 0x78, 0xd6, 0x43, 0x7e, 0x43, 0xeb, 0x4f, - 0xcc, 0x96, 0x26, 0x79, 0x39, 0xe0, 0x37, 0x93, 0xf5, 0xe3, 0x08, 0x5e, 0x7d, 0x0c, 0x56, 0x8c, 0xcc, 0x99, 0x65, - 0xeb, 0xc7, 0x11, 0x8e, 0xd9, 0xf2, 0x71, 0x44, 0xa3, 0xb6, 0x92, 0xfb, 0xd2, 0x6d, 0x03, 0xc2, 0xca, 0x2d, 0x8b, - 0xe1, 0x35, 0x10, 0xcf, 0xb4, 0x91, 0x74, 0x2d, 0x0d, 0xbd, 0x31, 0x0f, 0xa7, 0x71, 0xb0, 0xa6, 0x56, 0xc8, 0x33, - 0x43, 0xcc, 0xe2, 0xc7, 0xd1, 0x9c, 0xad, 0xb0, 0x22, 0x1b, 0x1e, 0x0f, 0x2e, 0x27, 0x9b, 0x2b, 0xbe, 0x06, 0xf2, - 0xb3, 0xc9, 0xc6, 0x6c, 0x51, 0xb7, 0x5c, 0xcc, 0x36, 0x8f, 0xa3, 0xf9, 0x64, 0x05, 0x3d, 0x6b, 0x0f, 0x98, 0xf7, - 0x0a, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x25, 0x5b, 0x5f, 0x06, 0xb7, 0x6c, 0x3d, - 0x06, 0x22, 0x0e, 0xea, 0x77, 0x6f, 0x03, 0x8b, 0x2f, 0x62, 0xeb, 0x4b, 0x93, 0xb6, 0x79, 0x1c, 0x31, 0x77, 0x70, - 0x1a, 0xb8, 0x60, 0x2d, 0x32, 0x6f, 0xc5, 0xe0, 0x12, 0xb2, 0xf0, 0x62, 0xb6, 0x19, 0x5e, 0xb2, 0xf5, 0x08, 0xa7, - 0x7a, 0xe2, 0xb3, 0x25, 0xbf, 0x65, 0x09, 0x5f, 0x35, 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, - 0xcc, 0x9c, 0xf7, 0x16, 0x46, 0xe5, 0xbe, 0x05, 0x07, 0x14, 0xa4, 0x6d, 0x80, 0x20, 0x89, 0x67, 0x77, 0x1d, 0xae, - 0x3f, 0x49, 0x61, 0xc0, 0x4d, 0x60, 0x06, 0x0c, 0x4c, 0x3f, 0x83, 0x1f, 0x56, 0xba, 0x44, 0x88, 0xb3, 0x9f, 0x52, - 0x92, 0xcc, 0xf3, 0xf7, 0x22, 0xcd, 0xdd, 0xc2, 0x75, 0x0a, 0xb3, 0xa2, 0x40, 0xf5, 0x53, 0x52, 0x1a, 0x58, 0xa8, - 0x44, 0xa6, 0x52, 0xf0, 0xcb, 0xe6, 0x3c, 0xca, 0x8e, 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, - 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, - 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, - 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xad, 0x33, 0x07, 0x69, 0x4b, 0xf3, 0x5d, 0x13, 0x3f, 0x87, 0x05, 0x5c, 0x44, 0x0b, - 0x5b, 0xc3, 0xa3, 0x2a, 0x56, 0xee, 0x4d, 0x9e, 0x23, 0x9c, 0xd1, 0xa5, 0x4c, 0x00, 0x5c, 0xef, 0x97, 0x61, 0xad, - 0xf0, 0x8a, 0x9a, 0x9b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, - 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, - 0x0b, 0x40, 0x4d, 0x3f, 0xd5, 0x62, 0x5d, 0x05, 0xa5, 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, - 0x26, 0x4a, 0xe4, 0xfc, 0xb8, 0x29, 0xc5, 0xa2, 0x14, 0x55, 0xd2, 0x6e, 0x28, 0x78, 0x44, 0xb8, 0x0d, 0x1a, 0x33, - 0xb7, 0x27, 0xba, 0x68, 0x45, 0x28, 0xc7, 0x66, 0x1d, 0x23, 0x8d, 0x32, 0x3b, 0xd9, 0x75, 0xb2, 0xd0, 0x7e, 0x5f, - 0xe5, 0x90, 0x75, 0xc0, 0x1a, 0xc9, 0xd7, 0x6b, 0x0e, 0xdd, 0x36, 0xca, 0x8b, 0x7b, 0xcf, 0x57, 0x70, 0x9a, 0xe3, - 0x89, 0xdd, 0xf5, 0xba, 0x53, 0x24, 0xe2, 0x15, 0x4e, 0xaa, 0x7c, 0x24, 0x0b, 0xc7, 0x9d, 0x3b, 0xad, 0xc5, 0xaa, - 0x72, 0x59, 0x4f, 0x2d, 0x8e, 0x08, 0x7c, 0x2a, 0x8f, 0xf6, 0x42, 0xdb, 0xa2, 0x58, 0x08, 0xa3, 0x47, 0x27, 0xfc, - 0xa4, 0x04, 0xd6, 0xd7, 0xe1, 0xb0, 0xf4, 0x23, 0x8e, 0x7e, 0xa7, 0xd1, 0xe8, 0x86, 0x90, 0x86, 0xa7, 0x5e, 0x34, - 0xba, 0xa9, 0x8b, 0x3a, 0xcc, 0x9e, 0xe5, 0x7a, 0xa0, 0x30, 0x8c, 0x40, 0xfd, 0xe0, 0x2a, 0x83, 0xcf, 0x22, 0x44, - 0xcd, 0x03, 0xd3, 0x6c, 0x08, 0x47, 0x5d, 0xe0, 0xa1, 0x15, 0xb4, 0x98, 0x99, 0x8f, 0x42, 0x0c, 0x1f, 0xd2, 0xc5, - 0xf9, 0x13, 0xb2, 0xf2, 0x01, 0x76, 0x87, 0xee, 0x42, 0x39, 0x67, 0x2a, 0x06, 0xf8, 0x51, 0x40, 0x3e, 0x4a, 0xc0, - 0xcd, 0x00, 0xd9, 0x23, 0x4b, 0x00, 0xb1, 0x62, 0x74, 0x34, 0xf9, 0xdc, 0xf7, 0x22, 0x05, 0xef, 0xec, 0xb3, 0x5c, - 0x4d, 0x18, 0x0a, 0x9f, 0x18, 0xe8, 0xe6, 0x37, 0x7e, 0x7b, 0xde, 0x82, 0x91, 0x5d, 0x92, 0xe2, 0xb5, 0x66, 0xb8, - 0xdf, 0x80, 0xdb, 0x11, 0x50, 0xd6, 0x54, 0xc7, 0x24, 0xdb, 0x34, 0x44, 0x32, 0x60, 0x46, 0x8c, 0x08, 0x2a, 0xcb, - 0x85, 0xff, 0xdd, 0xcb, 0xa2, 0xc0, 0x01, 0x5c, 0xcd, 0x64, 0xf0, 0xda, 0x85, 0x51, 0x01, 0x70, 0x4e, 0x43, 0xa7, - 0xb4, 0x57, 0x55, 0x87, 0x64, 0xd5, 0xfc, 0x60, 0x36, 0x6f, 0x1a, 0x26, 0x46, 0x04, 0xd1, 0x45, 0x38, 0xc1, 0xf4, - 0x8a, 0xf4, 0xb5, 0x92, 0xd3, 0xd1, 0xaa, 0xa3, 0xb5, 0xc4, 0xc4, 0x5c, 0x51, 0xfc, 0x35, 0xe0, 0x71, 0x83, 0x57, - 0x27, 0x69, 0x3a, 0x51, 0x3d, 0x7a, 0xfc, 0x3a, 0x4d, 0x27, 0x25, 0xee, 0x0a, 0xbf, 0x01, 0x17, 0xcd, 0x36, 0x1f, - 0xfa, 0xf1, 0x0b, 0x8a, 0xb8, 0xa8, 0xc1, 0x95, 0x77, 0xaa, 0xaf, 0x54, 0x1f, 0x41, 0x2d, 0x3c, 0x31, 0xb2, 0x16, - 0x9e, 0x5c, 0xb2, 0xd6, 0x82, 0x60, 0x66, 0x73, 0xe0, 0x42, 0x7e, 0xa5, 0x14, 0xf1, 0x26, 0x12, 0x6a, 0x31, 0x68, - 0x3d, 0x66, 0xce, 0xaa, 0xd1, 0x8d, 0xca, 0x8c, 0xd0, 0xbe, 0xad, 0x45, 0xe7, 0x37, 0xf2, 0x53, 0x9e, 0xda, 0x97, - 0xed, 0x71, 0x3e, 0xde, 0xa3, 0xbb, 0xea, 0x2c, 0x33, 0x29, 0xe3, 0x93, 0x59, 0x82, 0xc2, 0x5d, 0x82, 0x0d, 0x48, - 0xb2, 0xdf, 0xea, 0x00, 0x19, 0xb5, 0xd7, 0x7e, 0xd7, 0x59, 0xbe, 0xba, 0xd9, 0x1a, 0x8a, 0x4a, 0xad, 0x24, 0xc5, - 0x41, 0x86, 0xeb, 0xb6, 0xf2, 0xe1, 0xe2, 0x02, 0x7a, 0xc6, 0x48, 0x64, 0x9e, 0x3f, 0x91, 0x2f, 0xc1, 0x39, 0xe3, - 0xac, 0x10, 0x98, 0x30, 0x56, 0xef, 0x5a, 0x4b, 0xa5, 0x21, 0xc5, 0xd8, 0xd1, 0x28, 0xcb, 0x2a, 0x4b, 0x97, 0xd9, - 0x5a, 0xc2, 0x96, 0x55, 0xe4, 0x16, 0xb6, 0xce, 0x64, 0x35, 0x1f, 0x55, 0xdc, 0x41, 0xf9, 0x66, 0xcb, 0x8c, 0xef, - 0x25, 0xb2, 0x77, 0x1b, 0x28, 0xe1, 0xd9, 0xe8, 0x3f, 0x90, 0x7e, 0x9b, 0x61, 0x9c, 0x72, 0x5b, 0x49, 0x0b, 0x70, - 0xfa, 0x87, 0xc3, 0xa3, 0x0a, 0x83, 0x06, 0x47, 0x18, 0x47, 0xd6, 0xef, 0xdf, 0x54, 0x5e, 0x8d, 0x89, 0x3a, 0x3e, - 0xab, 0xdf, 0xaf, 0xe8, 0xe1, 0xb4, 0x1a, 0xad, 0xd2, 0x2d, 0xb2, 0x13, 0xda, 0x58, 0xf9, 0x41, 0xad, 0x80, 0xd9, - 0x5b, 0x9f, 0x4f, 0x07, 0xa0, 0x63, 0x01, 0x12, 0xcd, 0x66, 0x22, 0x31, 0x27, 0xdd, 0x93, 0xf0, 0xf8, 0xc0, 0x02, - 0x07, 0x98, 0x8a, 0xff, 0x53, 0x78, 0x33, 0xb0, 0x41, 0xa3, 0x44, 0x5f, 0xa3, 0xab, 0xda, 0xdc, 0xe8, 0x78, 0xe9, - 0x29, 0x24, 0xb2, 0x82, 0x55, 0x73, 0x5f, 0x6e, 0xe0, 0xb4, 0x87, 0x9a, 0x43, 0x65, 0x01, 0xfe, 0xf6, 0x0b, 0x30, - 0x78, 0x64, 0x50, 0xd8, 0x6e, 0x2d, 0xb4, 0x37, 0x66, 0xa9, 0x86, 0x8a, 0x70, 0xd0, 0xf9, 0x4a, 0xcc, 0xea, 0x11, - 0xfd, 0x3d, 0x3f, 0x1c, 0x56, 0x04, 0x06, 0x1c, 0x96, 0x32, 0x13, 0x2d, 0x14, 0x4b, 0xeb, 0x6c, 0x46, 0x75, 0xe0, - 0x81, 0x89, 0x39, 0x0b, 0x77, 0x00, 0xda, 0xa4, 0x56, 0x81, 0x5e, 0x45, 0xf4, 0x13, 0xf7, 0x6b, 0xfb, 0xf5, 0x7a, - 0x64, 0x96, 0x8e, 0xdc, 0x18, 0x0b, 0x00, 0x0e, 0x3c, 0xaf, 0x49, 0x9e, 0x93, 0xaf, 0xa1, 0xdd, 0x93, 0x0b, 0xf9, - 0x13, 0x94, 0x2d, 0x3c, 0x57, 0x4d, 0x2b, 0x8b, 0x15, 0x57, 0xd5, 0xab, 0x0b, 0x5e, 0x99, 0x4c, 0xab, 0xb4, 0x12, - 0x95, 0x12, 0x0c, 0xa8, 0x4b, 0xbc, 0xd6, 0x34, 0xa3, 0xd4, 0x46, 0x9d, 0x89, 0x1a, 0xb0, 0xc1, 0x7e, 0xaa, 0x36, - 0x3a, 0x39, 0x97, 0xcf, 0x2f, 0x8d, 0xc3, 0xa7, 0x5d, 0xbd, 0x99, 0xa9, 0x1c, 0xf8, 0x6b, 0xe5, 0x43, 0xab, 0xc7, - 0x40, 0x07, 0xe4, 0xf4, 0xc7, 0xb0, 0x98, 0xd8, 0x1d, 0x9a, 0xb7, 0xbb, 0xcb, 0xea, 0x22, 0xbd, 0xd3, 0x94, 0xcc, - 0xea, 0x2d, 0x9f, 0x59, 0x3d, 0x3a, 0xe0, 0xc5, 0x43, 0xbd, 0x57, 0x98, 0x49, 0x04, 0x17, 0x43, 0x35, 0x89, 0xec, - 0x0e, 0xb4, 0xe6, 0x51, 0xc5, 0x04, 0xf8, 0x41, 0xa9, 0x35, 0xbd, 0xb7, 0xbb, 0x42, 0x9d, 0x52, 0x78, 0xdc, 0x5a, - 0xf2, 0x03, 0x73, 0xa7, 0x5d, 0xeb, 0x7c, 0x3c, 0xbf, 0xf4, 0xfd, 0x46, 0x9e, 0xd0, 0x66, 0x67, 0x72, 0xfa, 0x27, - 0x6f, 0xf5, 0x0f, 0x53, 0x7d, 0x0b, 0xdd, 0x09, 0xfa, 0x0c, 0x5d, 0x55, 0xdd, 0x95, 0xd8, 0xc2, 0x50, 0x4f, 0x2c, - 0xf2, 0x42, 0x9e, 0xb4, 0xc6, 0x8e, 0x83, 0xbd, 0x01, 0x4e, 0xfc, 0xf2, 0x70, 0x10, 0x57, 0xb9, 0xcf, 0xce, 0xbb, - 0x46, 0x56, 0x0e, 0x60, 0x05, 0x51, 0x30, 0x6e, 0xcd, 0xc7, 0x36, 0x48, 0x97, 0xb8, 0x1a, 0x1f, 0xbf, 0xa1, 0x58, - 0x26, 0x9b, 0x88, 0x8b, 0x8b, 0xfc, 0xf1, 0x53, 0x20, 0x2d, 0xeb, 0xf7, 0xa3, 0x67, 0x97, 0xd3, 0xa7, 0xc3, 0x28, - 0x00, 0xc7, 0x2e, 0x7b, 0x79, 0x19, 0xf3, 0xd5, 0x25, 0xb3, 0x4c, 0x61, 0x91, 0x6f, 0x06, 0x54, 0x97, 0xac, 0x96, - 0xae, 0x57, 0x80, 0xa5, 0xcb, 0x6f, 0xee, 0xc3, 0xd4, 0x80, 0x46, 0xd6, 0xdc, 0x9d, 0xe6, 0x5a, 0xa0, 0xd4, 0xf3, - 0x7e, 0x66, 0xc8, 0xd7, 0x65, 0xd0, 0x15, 0xa4, 0x7b, 0x1e, 0x91, 0x5e, 0xee, 0xa5, 0xd3, 0xfd, 0xbe, 0x14, 0x60, - 0xa9, 0x2f, 0xc5, 0x17, 0x50, 0x58, 0x34, 0xbe, 0x11, 0xa0, 0xad, 0xa1, 0x9a, 0xf6, 0x4a, 0x51, 0xf5, 0x82, 0x5e, - 0x29, 0xbe, 0xf4, 0xf4, 0x50, 0x99, 0x2f, 0x4b, 0x47, 0xff, 0x13, 0x6a, 0x2e, 0x38, 0x21, 0x66, 0x62, 0x0e, 0xa0, - 0x12, 0xb4, 0xf1, 0xdd, 0x1e, 0x6d, 0x7c, 0xaa, 0x57, 0x71, 0xd3, 0xe7, 0xb5, 0xb5, 0xcc, 0x09, 0x61, 0xd3, 0xbd, - 0x04, 0xa8, 0xc8, 0x2b, 0xe1, 0x11, 0x2c, 0xbf, 0xfc, 0x21, 0x4f, 0x57, 0x88, 0xd6, 0x71, 0xcf, 0x32, 0x97, 0xc6, - 0xfe, 0x95, 0xc1, 0xf4, 0xf5, 0xed, 0xb6, 0xc8, 0x4f, 0x4d, 0x4c, 0x58, 0x8f, 0x15, 0x7d, 0xf3, 0x2e, 0x5c, 0x09, - 0x14, 0x38, 0x94, 0x48, 0x6c, 0x53, 0x85, 0x22, 0x1e, 0x24, 0x7d, 0xba, 0x68, 0x7d, 0x1a, 0x60, 0x6a, 0x2d, 0x07, - 0xe6, 0x10, 0xae, 0xe2, 0xc2, 0x47, 0x4f, 0xdf, 0x62, 0x16, 0xce, 0x27, 0xde, 0x47, 0xaf, 0x18, 0x99, 0x8f, 0xfb, - 0xa8, 0x54, 0xd2, 0x3f, 0x0f, 0x87, 0x59, 0x35, 0xf7, 0x1d, 0xfa, 0x48, 0x0f, 0x55, 0x2e, 0x28, 0x7b, 0x63, 0x4c, - 0x22, 0x50, 0x1a, 0xe3, 0x7d, 0x1c, 0x1c, 0xe7, 0x7d, 0x1a, 0x40, 0x6a, 0x9f, 0x78, 0x4f, 0x4a, 0x0e, 0xcf, 0x39, - 0xe6, 0x84, 0xd2, 0x8a, 0x80, 0x09, 0x3d, 0x43, 0xb9, 0xee, 0x94, 0x82, 0x49, 0x0e, 0x09, 0x86, 0xbf, 0x6a, 0xde, - 0xc4, 0x0a, 0x84, 0x5d, 0x33, 0xaf, 0x46, 0x8f, 0xaa, 0x24, 0x2c, 0x05, 0x1c, 0x95, 0x99, 0x67, 0xd8, 0x1b, 0x1e, - 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, - 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, - 0xfd, 0x06, 0xc7, 0x7c, 0x56, 0x72, 0xd7, 0x3b, 0x9c, 0x85, 0x96, 0x90, 0x27, 0x77, 0x0c, 0xd2, 0x34, 0x96, 0x46, - 0xc0, 0x89, 0x48, 0xb6, 0xb1, 0x14, 0x8e, 0x00, 0x02, 0x02, 0xdd, 0x94, 0x19, 0xc6, 0x74, 0x30, 0xf2, 0x3c, 0xea, - 0x19, 0xef, 0x55, 0x78, 0x0a, 0x69, 0xb2, 0x7d, 0x3d, 0x7f, 0x6f, 0x04, 0x59, 0xb9, 0xe5, 0x1c, 0x0f, 0x8b, 0x6f, - 0x9c, 0x7d, 0x95, 0x93, 0xa7, 0x98, 0x65, 0xa4, 0x77, 0x8a, 0x79, 0x01, 0x7f, 0x2a, 0x4b, 0x7d, 0x8e, 0xd2, 0x5b, - 0xe6, 0x93, 0x55, 0x24, 0x5d, 0x78, 0x9b, 0x7e, 0x3f, 0x1e, 0xa9, 0x43, 0xcd, 0xdf, 0xc7, 0x23, 0x79, 0x86, 0x6d, - 0x58, 0xc2, 0x42, 0xab, 0x60, 0x0c, 0x20, 0x89, 0x8d, 0x88, 0x06, 0xa3, 0xbd, 0x39, 0x1c, 0xce, 0x37, 0xe6, 0x2c, - 0xd9, 0x83, 0xeb, 0x2b, 0x4f, 0xcc, 0x3b, 0xf0, 0x65, 0x1e, 0x13, 0x44, 0x6c, 0xe6, 0x6d, 0x58, 0x0d, 0x1e, 0xec, - 0xe0, 0xfa, 0x88, 0x2d, 0x8a, 0xb5, 0x8e, 0xa5, 0xb2, 0x0e, 0x4e, 0xeb, 0xd8, 0x34, 0x23, 0xa5, 0xc8, 0x3e, 0xc7, - 0xfe, 0xde, 0x0d, 0xae, 0xae, 0x8d, 0x41, 0xad, 0x71, 0x87, 0xb9, 0x73, 0x2a, 0xa0, 0x1e, 0xd3, 0x15, 0x54, 0xcf, - 0x2a, 0xf2, 0xe5, 0xb7, 0x76, 0x0e, 0x08, 0x1a, 0x81, 0xc0, 0x45, 0x03, 0x25, 0xd3, 0xa5, 0x9c, 0x77, 0x01, 0x21, - 0xbe, 0x4b, 0x41, 0x9f, 0xce, 0x60, 0x13, 0x9b, 0x4f, 0x20, 0x16, 0x4d, 0xf7, 0xb9, 0xd6, 0xcc, 0x17, 0x23, 0xda, - 0x99, 0x75, 0xb7, 0xc8, 0xad, 0x16, 0x22, 0x19, 0x3d, 0xdb, 0x4c, 0xb8, 0xeb, 0x50, 0xce, 0x48, 0xc0, 0x04, 0xad, - 0xad, 0x94, 0x7c, 0xae, 0x7b, 0x9d, 0xa0, 0x3d, 0x90, 0xb4, 0xee, 0xdf, 0x2c, 0x3a, 0xa3, 0xe4, 0xe4, 0x7a, 0x93, - 0x33, 0x48, 0xc1, 0x82, 0xed, 0x65, 0x4e, 0xb8, 0x01, 0x3e, 0xb2, 0x59, 0x72, 0x9a, 0x06, 0x79, 0x2c, 0x0c, 0xd2, - 0x47, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, - 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, - 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, 0x98, 0x07, 0xb6, 0xb6, 0x71, 0x4d, 0x60, 0xa0, 0x53, 0xfb, 0x5a, 0x94, 0x73, - 0xac, 0x22, 0x7a, 0x9f, 0x7f, 0xa8, 0xec, 0xe9, 0x83, 0x08, 0x1b, 0x15, 0x68, 0x2c, 0x25, 0xc6, 0x46, 0x8e, 0x7f, - 0x4b, 0x94, 0x0d, 0x19, 0x02, 0x42, 0x48, 0x1b, 0x39, 0xfd, 0xb0, 0xbe, 0x7c, 0x97, 0x69, 0xff, 0x4f, 0x12, 0xbf, - 0x0d, 0xf6, 0x72, 0xea, 0x4f, 0x3d, 0xe2, 0xf1, 0x5a, 0xa3, 0xc7, 0x94, 0x74, 0x1b, 0xe4, 0xa9, 0xf2, 0x14, 0x24, - 0x13, 0xc6, 0x02, 0x82, 0x45, 0xb9, 0xe0, 0x39, 0xaf, 0xb8, 0x84, 0xfb, 0xa8, 0x65, 0x45, 0x84, 0xaa, 0x44, 0x4e, - 0x9f, 0xaf, 0x80, 0x67, 0x02, 0x02, 0x1d, 0x63, 0xa4, 0x51, 0x05, 0x5f, 0x02, 0x63, 0x1d, 0x28, 0x3b, 0xcd, 0x48, - 0x70, 0xd9, 0xfd, 0x84, 0x44, 0xa9, 0x2f, 0x49, 0x49, 0xfa, 0x56, 0xd4, 0x78, 0x25, 0x56, 0x11, 0x09, 0x64, 0xa8, - 0x21, 0x62, 0x55, 0x3d, 0x75, 0xaf, 0x8a, 0xc9, 0x60, 0x50, 0xf9, 0x72, 0x7a, 0xe2, 0x0d, 0x0d, 0x95, 0x77, 0x5d, - 0xd1, 0x4e, 0xcf, 0xb5, 0x52, 0xde, 0x42, 0x5a, 0x82, 0xa6, 0x61, 0xa4, 0x39, 0x94, 0xba, 0x92, 0xee, 0xc6, 0x20, - 0xbe, 0x64, 0xa2, 0x67, 0x3b, 0xb5, 0xa3, 0xb4, 0x25, 0xed, 0x21, 0xa4, 0xe7, 0x2e, 0xf9, 0x98, 0x85, 0x5c, 0xdd, - 0x29, 0x27, 0xe5, 0x55, 0x88, 0x4e, 0xee, 0x7b, 0x0c, 0x89, 0x40, 0x9f, 0x73, 0x0c, 0xeb, 0xa2, 0xa1, 0xce, 0x61, - 0x85, 0x98, 0x2d, 0x94, 0x30, 0x5f, 0x32, 0x9e, 0x4a, 0x06, 0x0d, 0x80, 0x0c, 0xf8, 0xe2, 0x65, 0x60, 0xf9, 0x2b, - 0x88, 0x1f, 0x6d, 0x7c, 0x38, 0xfc, 0x55, 0x53, 0x88, 0xed, 0x5f, 0xb0, 0x19, 0xc2, 0xa3, 0x7a, 0xc0, 0x33, 0xdf, - 0xc4, 0x09, 0x5a, 0x01, 0x49, 0x99, 0x1d, 0x4d, 0x64, 0xaf, 0x7a, 0x08, 0xa7, 0xb2, 0x02, 0x75, 0x94, 0x75, 0x56, - 0xc2, 0x8f, 0x30, 0xd5, 0xad, 0xc4, 0x5a, 0xa0, 0xcd, 0xd5, 0x8a, 0xb5, 0x00, 0x0e, 0xfc, 0x1c, 0x82, 0x27, 0xf2, - 0x39, 0xb8, 0x18, 0x14, 0xe0, 0x73, 0x00, 0xbc, 0xc8, 0x5d, 0x78, 0x30, 0x0f, 0x2c, 0xab, 0x11, 0x86, 0xa3, 0x8a, - 0x58, 0xbf, 0x66, 0x3b, 0xf2, 0x81, 0xdb, 0x31, 0x3e, 0xd7, 0x1e, 0x4b, 0x96, 0x83, 0x51, 0xe6, 0x5e, 0x2d, 0xd1, - 0xf3, 0x26, 0x8d, 0x9b, 0xd1, 0xa3, 0x7d, 0x2d, 0xff, 0x17, 0xf4, 0x32, 0xe8, 0x6f, 0xe1, 0x96, 0xd7, 0xfc, 0x61, - 0xb9, 0x70, 0x9a, 0x5e, 0x41, 0xa4, 0x8c, 0x1a, 0x91, 0x31, 0x84, 0x4d, 0xaa, 0x9b, 0xdb, 0xa4, 0xba, 0x10, 0xf0, - 0x74, 0x44, 0xaa, 0x6b, 0x21, 0x6d, 0xe4, 0xd3, 0x3a, 0x90, 0xb1, 0x48, 0xef, 0x7e, 0xfc, 0xdb, 0xf3, 0xcf, 0xaf, - 0x7f, 0xfd, 0xf1, 0xe6, 0xf5, 0xbb, 0x57, 0xaf, 0xdf, 0xbd, 0xfe, 0xfc, 0x3b, 0x41, 0x78, 0x4c, 0x85, 0xca, 0xf0, - 0xe1, 0xfd, 0xa7, 0xd7, 0x4e, 0x06, 0xdb, 0x9b, 0x21, 0x6b, 0xdf, 0xc8, 0xc1, 0x10, 0x88, 0x6c, 0x10, 0x32, 0xc8, - 0x4e, 0xc9, 0x1c, 0x33, 0x31, 0xc7, 0xd8, 0x3b, 0x81, 0xc9, 0x16, 0x24, 0x87, 0x65, 0x5e, 0x32, 0x22, 0x57, 0x85, - 0xd6, 0x0f, 0x68, 0xc1, 0x5b, 0x70, 0x91, 0x49, 0xf3, 0xe5, 0xaf, 0x04, 0xb1, 0x4f, 0x2b, 0x29, 0xf7, 0xd5, 0xb6, - 0xe6, 0xf9, 0xf6, 0x7e, 0x2f, 0xe1, 0xfc, 0xe7, 0xd2, 0x88, 0x5a, 0x80, 0x03, 0xf0, 0x39, 0xfc, 0x71, 0xa5, 0x2d, - 0x69, 0x32, 0x8b, 0xf6, 0x33, 0x86, 0xa0, 0x4b, 0x03, 0x69, 0x62, 0x8f, 0xbc, 0xd4, 0x27, 0x0b, 0x09, 0xdc, 0x11, - 0xc3, 0xa7, 0x15, 0x41, 0xaf, 0x18, 0x51, 0x5c, 0x72, 0x85, 0x4a, 0x29, 0xf9, 0x37, 0xca, 0x2e, 0x2a, 0xe4, 0xac, - 0x60, 0x77, 0x8a, 0x1c, 0x19, 0x3f, 0x08, 0x26, 0xbe, 0x1c, 0xdc, 0x7f, 0x89, 0x77, 0x38, 0x53, 0x1c, 0xc9, 0x09, - 0xff, 0x33, 0xc3, 0xc0, 0xfe, 0x1c, 0x7c, 0x5e, 0x1d, 0xe6, 0xe5, 0x8d, 0x3e, 0xe5, 0x16, 0x7c, 0x3c, 0x59, 0x5c, - 0x81, 0xc1, 0x7e, 0xa1, 0x9a, 0xbb, 0xe6, 0xf5, 0x6c, 0x31, 0x67, 0xfb, 0x59, 0x34, 0x0f, 0x96, 0x6c, 0x96, 0xcd, - 0x83, 0x55, 0xc3, 0xd7, 0xec, 0x96, 0xaf, 0xad, 0xaa, 0xad, 0xed, 0xaa, 0x4d, 0x36, 0xfc, 0x16, 0x24, 0x84, 0xb7, - 0x99, 0x07, 0xbc, 0xc7, 0x4b, 0x9f, 0x6d, 0x40, 0xa2, 0x5d, 0xb1, 0x0d, 0x5c, 0xc4, 0xd6, 0xfc, 0x75, 0xe5, 0x6d, - 0x58, 0xc9, 0xce, 0xc7, 0x2c, 0xc7, 0xf9, 0xe7, 0xc3, 0x03, 0xda, 0x0b, 0xf5, 0xb3, 0x4b, 0xf5, 0x6c, 0xa2, 0xec, - 0x66, 0x9b, 0xd1, 0xcd, 0x5d, 0x5a, 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x0d, 0x7e, - 0xc9, 0x9a, 0x38, 0xff, 0x4c, 0xdb, 0x76, 0x55, 0x62, 0x2b, 0x68, 0x51, 0x64, 0xb5, 0xc2, 0x03, 0x73, 0xfe, 0x0c, - 0x16, 0x30, 0xf6, 0x1c, 0xe7, 0xbc, 0xf6, 0x47, 0xc8, 0x78, 0xef, 0x00, 0xa0, 0x65, 0x8e, 0x03, 0x3c, 0x62, 0xc5, - 0x28, 0x1a, 0xbc, 0xf3, 0x4b, 0x65, 0xb5, 0xd2, 0x9c, 0x84, 0xb6, 0x11, 0xab, 0x96, 0x23, 0x55, 0x33, 0x22, 0x7d, - 0x90, 0x9e, 0xf7, 0x3d, 0xa2, 0x1a, 0xec, 0xc9, 0xbc, 0x0e, 0xec, 0xd3, 0xfb, 0xd6, 0xaa, 0xee, 0xfc, 0x9e, 0x2a, - 0x5d, 0x72, 0x64, 0xcb, 0x4f, 0x97, 0xe1, 0xbd, 0xfa, 0x53, 0x72, 0x7d, 0x28, 0x70, 0x84, 0x87, 0x2a, 0xe0, 0x7c, - 0xbd, 0x12, 0xed, 0x4e, 0x84, 0x5d, 0xb9, 0x04, 0x84, 0xf8, 0x92, 0xa6, 0x39, 0x1e, 0x47, 0x34, 0x11, 0x61, 0x13, - 0xa3, 0xbf, 0xb0, 0xfb, 0x50, 0x62, 0x39, 0xcf, 0x35, 0x28, 0xb9, 0x64, 0xf0, 0x9e, 0xb4, 0xd7, 0xa0, 0x59, 0x5e, - 0x95, 0x9a, 0x4c, 0xe4, 0xa0, 0x7c, 0x38, 0x14, 0xb0, 0x97, 0x1a, 0x3f, 0x4d, 0xf8, 0x09, 0xcb, 0x5b, 0x7b, 0x6b, - 0x4a, 0x51, 0x49, 0x03, 0x54, 0xe0, 0x63, 0x06, 0xff, 0xbb, 0x33, 0xc4, 0x82, 0x29, 0x3a, 0x7e, 0x38, 0x13, 0x73, - 0xeb, 0xb9, 0x55, 0xd6, 0x51, 0xb6, 0x46, 0x39, 0x01, 0xff, 0x9e, 0xea, 0x38, 0x49, 0x84, 0x53, 0xef, 0x11, 0x17, - 0x75, 0x2f, 0x87, 0xa8, 0x1b, 0xf6, 0xb9, 0xd2, 0xc1, 0x96, 0xd3, 0x34, 0x38, 0x12, 0xbf, 0x52, 0x9f, 0x3d, 0xca, - 0x2c, 0x1e, 0x75, 0x64, 0x23, 0x4a, 0xd2, 0x38, 0x16, 0x39, 0x6c, 0xef, 0x37, 0x72, 0xff, 0xef, 0xf7, 0x21, 0x9c, - 0xb4, 0x0a, 0xe2, 0xd2, 0x13, 0x88, 0x08, 0x47, 0x87, 0x1f, 0x11, 0x9e, 0x48, 0x55, 0xe1, 0x87, 0xfa, 0xc4, 0x8d, - 0xd9, 0xbd, 0x30, 0x47, 0xf5, 0x16, 0x60, 0x18, 0xeb, 0xad, 0x45, 0x48, 0xa2, 0x95, 0x66, 0xb4, 0xf5, 0x80, 0x18, - 0xf1, 0x7e, 0x6d, 0x91, 0xc1, 0x58, 0x5b, 0x12, 0x09, 0xe0, 0x4b, 0x12, 0x32, 0xb4, 0x6d, 0x04, 0x66, 0x0c, 0x6f, - 0x67, 0xc5, 0xa5, 0xeb, 0xb0, 0xcd, 0x39, 0x7c, 0x21, 0x37, 0x9a, 0x75, 0x44, 0x69, 0x82, 0x90, 0x7f, 0xc0, 0xc9, - 0x42, 0x61, 0x34, 0x2f, 0x8f, 0xd2, 0x49, 0x62, 0x7d, 0xdf, 0x55, 0x2a, 0xd8, 0x6c, 0x3e, 0xa1, 0xbe, 0xec, 0x28, - 0xf9, 0x1a, 0x9c, 0x74, 0x9c, 0x64, 0x91, 0x83, 0xa8, 0x45, 0xe5, 0x7c, 0x4a, 0xc2, 0xd2, 0xae, 0x4e, 0xb5, 0x59, - 0xaf, 0x8b, 0xb2, 0xae, 0x5e, 0x8a, 0x48, 0xd1, 0xfb, 0xa8, 0x47, 0x8f, 0x24, 0xa4, 0x42, 0xab, 0x52, 0xbb, 0x3c, - 0x02, 0xb7, 0x4d, 0xad, 0xd8, 0x96, 0x4b, 0x58, 0xa2, 0xc6, 0x7f, 0x86, 0x3e, 0xca, 0xc5, 0xbd, 0x0c, 0xd0, 0xe8, - 0x78, 0x6a, 0xde, 0x7a, 0xe0, 0x95, 0xa3, 0xfc, 0xd2, 0x6a, 0x93, 0x7e, 0x05, 0x64, 0x46, 0xfb, 0x47, 0x4b, 0x09, - 0x64, 0x06, 0x66, 0xd2, 0xd2, 0x90, 0xc8, 0x51, 0xcc, 0xd2, 0xfc, 0x4f, 0x5c, 0xb1, 0x15, 0x22, 0x0d, 0xab, 0xb9, - 0xc7, 0x7f, 0xac, 0xbc, 0x5a, 0xae, 0x65, 0xa6, 0xb9, 0x59, 0xe2, 0x58, 0xb1, 0xb8, 0xa8, 0xd7, 0x95, 0xc8, 0x02, - 0x21, 0x8e, 0x30, 0x8d, 0xf5, 0xd4, 0x1b, 0xa5, 0xd5, 0x07, 0x24, 0x94, 0xf9, 0x11, 0x7b, 0x3b, 0xf6, 0x7a, 0x90, - 0x85, 0x38, 0xb6, 0x1c, 0x6c, 0xb6, 0xde, 0xe7, 0x32, 0x15, 0xf1, 0x59, 0x5d, 0x9c, 0x6d, 0x2a, 0x71, 0x56, 0x27, - 0xe2, 0xec, 0x07, 0xc8, 0xf9, 0xc3, 0x19, 0x15, 0x7d, 0x76, 0x9f, 0xd6, 0x49, 0xb1, 0xa9, 0xe9, 0xc9, 0x2b, 0x2c, - 0xe3, 0x87, 0x33, 0xe2, 0xaa, 0x39, 0xa3, 0x91, 0x8c, 0x47, 0x67, 0x1f, 0x32, 0x20, 0x79, 0x3d, 0x4b, 0x57, 0x30, - 0x78, 0x67, 0x61, 0x1e, 0x9f, 0x95, 0x62, 0x09, 0x16, 0xa7, 0xb2, 0xf3, 0x3d, 0xc8, 0xb0, 0x0a, 0xff, 0x14, 0x67, - 0x00, 0xed, 0x7a, 0x96, 0xd6, 0x67, 0x69, 0x75, 0x96, 0x17, 0xf5, 0x99, 0x92, 0xc2, 0x21, 0x8c, 0x1f, 0xde, 0xd3, - 0x57, 0x76, 0x79, 0x9b, 0xc5, 0x5d, 0x16, 0xf9, 0x53, 0xf4, 0x2a, 0x22, 0x26, 0x8d, 0x4a, 0x78, 0xed, 0xfe, 0xb6, - 0xb9, 0x7f, 0x78, 0xdd, 0xd8, 0xfd, 0xec, 0x8e, 0x11, 0x5d, 0x50, 0x8f, 0x57, 0x92, 0x52, 0x41, 0x01, 0x81, 0x13, - 0xcd, 0x1a, 0x0f, 0xee, 0x38, 0xe0, 0xd5, 0xc0, 0x16, 0x6c, 0xed, 0xf3, 0x67, 0xb1, 0x0c, 0xd3, 0xde, 0x04, 0xf8, - 0x57, 0xd9, 0x9b, 0xae, 0x83, 0x05, 0xde, 0xb7, 0x90, 0x6d, 0xe8, 0xf5, 0x4b, 0xfe, 0xdc, 0xcb, 0xd5, 0xdf, 0xec, - 0x9f, 0x00, 0x84, 0x01, 0x31, 0xab, 0x3e, 0x9a, 0xb8, 0x77, 0x56, 0x96, 0x9d, 0x93, 0x65, 0xd7, 0x43, 0xbf, 0x26, - 0x31, 0x2a, 0xad, 0x2c, 0xa5, 0x93, 0xa5, 0x84, 0x2c, 0xe0, 0x13, 0xa3, 0xa9, 0x8d, 0x00, 0xc2, 0x76, 0x94, 0xca, - 0x17, 0x2a, 0x2f, 0xa2, 0x70, 0x4e, 0xf0, 0x3c, 0x11, 0xa3, 0x3b, 0x2b, 0x19, 0x30, 0x1c, 0x42, 0x30, 0x07, 0x6d, - 0xb1, 0x37, 0x74, 0x13, 0xf1, 0xd7, 0xab, 0xa2, 0x7c, 0x1d, 0x93, 0x4f, 0xc1, 0xee, 0xe4, 0xe3, 0x12, 0x1e, 0x97, - 0x27, 0x1f, 0x87, 0xe8, 0x91, 0x70, 0xf2, 0x31, 0xf8, 0x1e, 0xc9, 0x79, 0xdd, 0xf5, 0x38, 0x41, 0x6e, 0x21, 0xdd, - 0xdf, 0x8e, 0x49, 0x80, 0xe6, 0x35, 0x2c, 0x47, 0x4d, 0xc5, 0x35, 0x33, 0x63, 0x3c, 0x6f, 0xf4, 0xfe, 0xd8, 0xf1, - 0x96, 0x29, 0x14, 0xb3, 0x98, 0xd7, 0xf0, 0x7b, 0x56, 0x05, 0xea, 0xae, 0xb7, 0x49, 0x6e, 0x99, 0xd5, 0x73, 0xb4, - 0xfb, 0xbe, 0xaf, 0x13, 0x41, 0xed, 0xef, 0xb0, 0xe7, 0x99, 0xf5, 0xae, 0x8a, 0x81, 0x4b, 0x95, 0xec, 0x90, 0xa9, - 0x6a, 0x7a, 0xa0, 0x52, 0x1a, 0x3c, 0xbd, 0xb4, 0x2e, 0x5f, 0x2a, 0x6d, 0xe4, 0x99, 0xe6, 0x37, 0x80, 0x17, 0x53, - 0x97, 0xc5, 0xee, 0x9b, 0xfb, 0x0a, 0x6e, 0xe3, 0xfd, 0xfe, 0xba, 0xf2, 0xcc, 0x4f, 0x5c, 0x00, 0xf6, 0xa6, 0x42, - 0xeb, 0x04, 0x4a, 0x0d, 0xeb, 0xf0, 0x3a, 0x11, 0xd1, 0x9f, 0xed, 0x72, 0x9d, 0xb9, 0x0e, 0x18, 0x51, 0xc4, 0x6f, - 0xe3, 0xd1, 0x1f, 0xa0, 0xb8, 0x36, 0xf6, 0x80, 0xb0, 0x0e, 0x09, 0x7d, 0x46, 0x00, 0x52, 0x8f, 0x3e, 0x4a, 0xee, - 0x41, 0xb3, 0xa2, 0xb9, 0x63, 0xf2, 0x73, 0x7d, 0xa5, 0xf4, 0xf7, 0xeb, 0xca, 0x23, 0x73, 0x4a, 0xdb, 0x4c, 0x63, - 0xb5, 0xa6, 0x12, 0x08, 0xaf, 0xa8, 0x64, 0x15, 0x3e, 0x9b, 0x37, 0xa2, 0xdf, 0x97, 0x47, 0x78, 0x5a, 0xfd, 0xb8, - 0xc5, 0xf8, 0x56, 0x40, 0x34, 0x12, 0xa0, 0x60, 0x05, 0x98, 0x17, 0xd9, 0xcc, 0xee, 0xe3, 0x80, 0x2a, 0x25, 0x9a, - 0xc6, 0xd9, 0x3c, 0xbf, 0xa7, 0x37, 0x65, 0x07, 0x9d, 0x3a, 0x55, 0xe0, 0x82, 0xab, 0x92, 0xf1, 0xca, 0x7a, 0x22, - 0x9f, 0xdf, 0xdc, 0x6e, 0xd2, 0x2c, 0x7e, 0x5f, 0xfe, 0x82, 0x63, 0xab, 0xeb, 0xf0, 0xc0, 0xd4, 0xe9, 0xda, 0x79, - 0xa4, 0xb5, 0x17, 0x02, 0x22, 0xda, 0x35, 0xd4, 0x7a, 0x61, 0xa1, 0x47, 0x7a, 0x22, 0x9c, 0x93, 0x44, 0x4d, 0x3b, - 0xd0, 0xd2, 0x08, 0x7d, 0x7d, 0xcd, 0xe9, 0x2f, 0x0c, 0xd6, 0x3e, 0x1f, 0x33, 0x20, 0x2b, 0xd1, 0x8f, 0xd5, 0x43, - 0x63, 0x33, 0x87, 0x9e, 0xb5, 0x2a, 0xcf, 0xbc, 0xea, 0x70, 0x40, 0x7c, 0x18, 0xfd, 0x25, 0xbf, 0xdf, 0x7f, 0x49, - 0xf3, 0x8f, 0x09, 0x35, 0x7e, 0xb6, 0x19, 0xa0, 0x6b, 0xdf, 0x95, 0x07, 0xa2, 0x9e, 0x6b, 0x95, 0x20, 0xc4, 0x1b, - 0xc4, 0x44, 0x33, 0x62, 0x0e, 0x4e, 0x3b, 0xd4, 0xfc, 0x93, 0xd4, 0x80, 0x10, 0x25, 0x5e, 0xc7, 0x94, 0x05, 0x39, - 0x6d, 0xe2, 0x48, 0x3f, 0x0a, 0x27, 0xf2, 0xa3, 0xa8, 0x8a, 0xec, 0x0e, 0x2e, 0x18, 0x4c, 0xbd, 0xa7, 0xfd, 0x12, - 0xfd, 0x96, 0x70, 0xe4, 0x1c, 0xad, 0x0a, 0x41, 0xe4, 0x84, 0xb0, 0xd6, 0x10, 0x26, 0x88, 0x0d, 0xe2, 0x65, 0xdf, - 0x25, 0x19, 0x8e, 0x14, 0x5c, 0xd6, 0xb1, 0x63, 0xcc, 0xd5, 0x51, 0xf5, 0x1a, 0xc0, 0x78, 0xe5, 0x08, 0x9a, 0x8d, - 0x22, 0xbb, 0x84, 0xa8, 0x22, 0xc7, 0x13, 0x50, 0x3b, 0x28, 0x8d, 0xcd, 0xf4, 0x7c, 0x1c, 0xe4, 0xa3, 0x9b, 0x0a, - 0x75, 0x4e, 0x2c, 0xe3, 0x35, 0x00, 0x6b, 0xe7, 0xaa, 0x9f, 0x67, 0x35, 0x78, 0xd2, 0x10, 0x9f, 0x8f, 0xd1, 0xf6, - 0xca, 0xe6, 0xa0, 0xda, 0x4e, 0x67, 0xe5, 0x15, 0xd3, 0xe5, 0xc0, 0xb8, 0x6f, 0x78, 0x45, 0x71, 0x86, 0x1f, 0x3d, - 0xd8, 0xe2, 0xfc, 0xe9, 0x86, 0xda, 0x8f, 0xb9, 0x51, 0x0f, 0x03, 0xad, 0x05, 0x6f, 0x0a, 0x62, 0xfd, 0x7d, 0xd4, - 0x91, 0xed, 0xbd, 0x16, 0x19, 0x4d, 0x3e, 0xfb, 0xf9, 0x87, 0x32, 0x5d, 0xa5, 0x70, 0x5f, 0x72, 0xb2, 0x68, 0xe6, - 0x21, 0xb0, 0x37, 0xc4, 0x70, 0x7d, 0x54, 0x78, 0x44, 0x59, 0xbf, 0x0f, 0xbf, 0xaf, 0x32, 0x30, 0xc5, 0xc0, 0x75, - 0x85, 0x60, 0x3c, 0x04, 0x82, 0x78, 0x98, 0x46, 0x27, 0x83, 0x1a, 0xb4, 0xe1, 0x1b, 0x80, 0xcc, 0x00, 0x8f, 0xcc, - 0x85, 0x47, 0xc0, 0x5d, 0xe0, 0xda, 0x93, 0xf1, 0xd8, 0x9f, 0x98, 0x86, 0x46, 0x4d, 0x69, 0xa6, 0xe7, 0xc6, 0x6f, - 0x3a, 0xaa, 0xe5, 0xda, 0xf9, 0x8f, 0x2f, 0xf9, 0x0d, 0x7a, 0x41, 0xcb, 0xcb, 0x7d, 0xa4, 0x2e, 0xf7, 0x19, 0xc5, - 0x65, 0x22, 0x39, 0x2c, 0x88, 0x65, 0x09, 0x07, 0x1e, 0xa3, 0x92, 0xc5, 0x96, 0x1e, 0xab, 0xa2, 0xe5, 0x8b, 0x72, - 0x83, 0x74, 0xe8, 0x84, 0x60, 0x89, 0x0a, 0x82, 0x25, 0x30, 0x2e, 0x62, 0xcd, 0x37, 0x83, 0x9c, 0xc5, 0xb3, 0xcd, - 0x9c, 0x23, 0x61, 0x5d, 0x72, 0x38, 0x14, 0x12, 0x6c, 0x26, 0x9b, 0xad, 0xe7, 0x6c, 0xed, 0x33, 0x50, 0x02, 0x94, - 0x32, 0x4d, 0x50, 0x9a, 0x56, 0x6c, 0xc5, 0x4d, 0x6b, 0xb0, 0x5a, 0x4d, 0xd9, 0xaa, 0xa6, 0xec, 0x9c, 0xa6, 0x1c, - 0x55, 0x50, 0x72, 0x42, 0x29, 0xca, 0x30, 0x80, 0x11, 0x9b, 0x44, 0x57, 0x19, 0xfa, 0x78, 0x27, 0x3c, 0x82, 0x2a, - 0x22, 0xf2, 0x09, 0x43, 0x08, 0x4c, 0x44, 0x71, 0xa1, 0x0a, 0xc5, 0x00, 0x19, 0x91, 0x40, 0x30, 0x51, 0xa9, 0x53, - 0x60, 0x3e, 0x9a, 0x2a, 0x86, 0x4d, 0x7b, 0xa2, 0x7c, 0x4f, 0x1d, 0xf7, 0x28, 0xdb, 0xfc, 0x2c, 0x76, 0x41, 0x88, - 0xdc, 0x8d, 0x3b, 0xf5, 0x33, 0xe2, 0xbd, 0xdd, 0x11, 0xc6, 0x4f, 0x76, 0xdc, 0x22, 0x5c, 0x11, 0x6c, 0xa1, 0xe6, - 0x10, 0x8b, 0x79, 0x35, 0x49, 0x50, 0xcb, 0x92, 0xf8, 0x1b, 0x9e, 0x0c, 0x72, 0xb6, 0x00, 0x0f, 0xda, 0x39, 0xcb, - 0x00, 0x7f, 0xc5, 0x6a, 0xd1, 0xef, 0xb5, 0xb7, 0x00, 0xf9, 0x69, 0x63, 0x37, 0x0a, 0x13, 0x23, 0x48, 0xd4, 0xed, - 0xca, 0x40, 0x7e, 0xf8, 0x80, 0xd3, 0xf1, 0xd8, 0x53, 0xc6, 0xdc, 0xca, 0xf4, 0x32, 0x9d, 0x2b, 0xf9, 0x46, 0xee, - 0xa5, 0x0f, 0xbd, 0x04, 0x3b, 0x07, 0xbc, 0x81, 0xb4, 0x81, 0x9f, 0x60, 0xbb, 0xf0, 0xda, 0x20, 0x61, 0x46, 0x80, - 0x2d, 0x8e, 0x8f, 0x91, 0x12, 0x18, 0xc2, 0x71, 0x96, 0x02, 0x30, 0x8d, 0xbe, 0xcc, 0x56, 0xf6, 0x65, 0x56, 0x6b, - 0xb6, 0x54, 0x4e, 0xf7, 0xce, 0xad, 0xdb, 0xf9, 0x5c, 0x02, 0x80, 0x49, 0x9d, 0x03, 0x71, 0x66, 0x82, 0x5d, 0x9a, - 0x44, 0x96, 0x8f, 0x61, 0xbe, 0x14, 0xaf, 0xca, 0x62, 0xa5, 0xba, 0xa2, 0xed, 0x33, 0x93, 0xcf, 0x48, 0x27, 0xa1, - 0x02, 0x0a, 0x0a, 0xb9, 0xd6, 0xa7, 0xef, 0xc2, 0x77, 0x41, 0xa1, 0x81, 0xd9, 0x2a, 0xdc, 0xd3, 0x64, 0x8d, 0xd4, - 0x1b, 0x55, 0xbf, 0x4f, 0xae, 0x81, 0x54, 0x67, 0x0e, 0x2d, 0x7b, 0x5e, 0x61, 0x80, 0xd8, 0x51, 0x9f, 0x91, 0x50, - 0x07, 0x52, 0x0f, 0x18, 0x42, 0xb4, 0x4d, 0x1f, 0x7f, 0x32, 0x24, 0xba, 0x00, 0x5b, 0x88, 0x36, 0xf0, 0xe3, 0x4f, - 0xb0, 0xcf, 0x82, 0xf0, 0x98, 0xe6, 0x6f, 0x21, 0xe9, 0xd8, 0xc0, 0x69, 0xf5, 0x29, 0xf8, 0x20, 0xc9, 0xc1, 0x44, - 0x1d, 0xbc, 0xdc, 0x5f, 0xfa, 0x7d, 0xd8, 0xb2, 0x73, 0x29, 0xd5, 0xb1, 0x52, 0x6f, 0xdb, 0xda, 0x0f, 0xa2, 0x2d, - 0x38, 0x42, 0xb0, 0x76, 0x86, 0x88, 0x60, 0x66, 0x10, 0x61, 0xd7, 0x42, 0xdd, 0xed, 0x29, 0xb5, 0x2c, 0xea, 0x6d, - 0x4f, 0x29, 0x75, 0x1b, 0x86, 0xef, 0x26, 0x98, 0x29, 0x6e, 0xf8, 0xa7, 0xcc, 0x0b, 0xf5, 0xc6, 0x63, 0xf1, 0xb4, - 0x7b, 0xfe, 0x7e, 0xc1, 0xab, 0xd9, 0x46, 0x99, 0x30, 0x97, 0x7c, 0x31, 0x0b, 0x65, 0x57, 0x4b, 0xe3, 0xce, 0x17, - 0x6f, 0xa1, 0xe6, 0x83, 0x7f, 0x38, 0x24, 0x10, 0x6f, 0x14, 0x5f, 0x2d, 0x1b, 0xb9, 0x75, 0x4d, 0x36, 0x57, 0x25, - 0xa0, 0x7e, 0x9f, 0xaf, 0x71, 0xbf, 0xc5, 0xfa, 0x77, 0x4f, 0x83, 0x8c, 0xd5, 0x0c, 0x57, 0x4c, 0xe1, 0x53, 0x00, - 0x18, 0x1c, 0x4e, 0x05, 0x69, 0x81, 0x37, 0xbc, 0x1c, 0x5e, 0x4e, 0x36, 0x64, 0xd2, 0xdd, 0xf8, 0xc8, 0x9d, 0x05, - 0xaa, 0xde, 0xef, 0x28, 0x4e, 0x1a, 0x24, 0x1a, 0x7b, 0x0d, 0x3e, 0xcf, 0x32, 0xca, 0x45, 0x13, 0xf7, 0x21, 0xf9, - 0x4a, 0x0f, 0x60, 0xae, 0x42, 0x09, 0x10, 0xfd, 0xc6, 0xb2, 0xd8, 0x88, 0xb6, 0xc5, 0x06, 0x96, 0x52, 0x35, 0xd7, - 0xab, 0xe9, 0x8b, 0x57, 0xa2, 0x79, 0x1f, 0xcd, 0x38, 0xa5, 0xd1, 0x80, 0xe3, 0x34, 0x0a, 0xb7, 0xef, 0xef, 0x44, - 0xb9, 0xc8, 0xc0, 0x92, 0xad, 0xc2, 0x29, 0x2e, 0x1b, 0x75, 0x46, 0x3c, 0xcf, 0x63, 0x05, 0xd0, 0xf1, 0x90, 0x00, - 0xa8, 0x2e, 0x08, 0xa8, 0x88, 0x96, 0xd2, 0x5b, 0xa1, 0xc5, 0x42, 0xbd, 0xe1, 0x28, 0x85, 0x3f, 0xd2, 0x9f, 0x07, - 0xf9, 0x14, 0x80, 0xd8, 0xf5, 0x71, 0xf4, 0xaa, 0x28, 0xe9, 0x53, 0xc5, 0x2c, 0x97, 0x83, 0x09, 0xec, 0xea, 0x44, - 0x86, 0x5a, 0x41, 0xde, 0xaa, 0x2b, 0x6f, 0x65, 0xf2, 0x36, 0xc6, 0x29, 0xf9, 0x81, 0x9b, 0x8e, 0x35, 0x62, 0xe0, - 0x95, 0xa7, 0x75, 0x9a, 0x20, 0x4d, 0xde, 0x00, 0xc3, 0x10, 0xbf, 0xcb, 0xbc, 0xe7, 0x9e, 0x23, 0x55, 0x41, 0x32, - 0xdb, 0x66, 0x9e, 0xba, 0x88, 0xea, 0x2b, 0xa7, 0x96, 0xce, 0x9c, 0x7e, 0x04, 0xf0, 0x1e, 0x53, 0x93, 0x86, 0x7c, - 0x84, 0xdb, 0x52, 0x7c, 0xbd, 0x55, 0xd7, 0x78, 0x69, 0x74, 0xee, 0x5e, 0xbe, 0x74, 0xa7, 0x41, 0x3f, 0x05, 0x41, - 0x39, 0x9f, 0x97, 0x02, 0xf6, 0x94, 0xd9, 0x5c, 0xaf, 0x56, 0xad, 0xd0, 0x3a, 0x1c, 0xc6, 0xda, 0x51, 0x48, 0xab, - 0xb3, 0x80, 0xad, 0x46, 0x3a, 0x25, 0x40, 0x08, 0x8e, 0xd3, 0xb0, 0x13, 0x8c, 0xbb, 0x74, 0x1a, 0x91, 0xf5, 0x4a, - 0x49, 0xba, 0x30, 0x83, 0xe4, 0x9f, 0xe4, 0xf5, 0x0c, 0x68, 0x09, 0xe0, 0x50, 0xc4, 0x12, 0x1e, 0x4e, 0x92, 0x2b, - 0x80, 0x4e, 0x87, 0x83, 0x4a, 0x43, 0x73, 0x56, 0xb3, 0x64, 0x3e, 0x89, 0xa5, 0xaa, 0xf2, 0x70, 0xf0, 0x94, 0x9b, - 0x41, 0xbf, 0x9f, 0x4d, 0x4b, 0xe5, 0x02, 0x10, 0xc4, 0xba, 0x30, 0x40, 0x3c, 0xd2, 0xc2, 0x93, 0x45, 0x9f, 0x92, - 0xf8, 0xe5, 0x2c, 0x99, 0x9b, 0x6c, 0x78, 0x07, 0x46, 0xb0, 0x19, 0xd7, 0x25, 0x65, 0xda, 0xa3, 0xf2, 0x7b, 0x46, - 0x4f, 0x6d, 0x5f, 0x6b, 0xb5, 0x45, 0xac, 0xeb, 0xe0, 0xaa, 0x44, 0x3d, 0xc5, 0x07, 0x25, 0x09, 0xde, 0x2f, 0x9d, - 0x9b, 0x91, 0xf2, 0xb5, 0xc8, 0xfd, 0xa0, 0x9d, 0xa9, 0x95, 0x03, 0x47, 0x20, 0xc7, 0x2a, 0x2a, 0x79, 0xbd, 0xeb, - 0x10, 0x3c, 0xba, 0x2b, 0x15, 0x28, 0x07, 0x3f, 0x03, 0x31, 0xba, 0xbe, 0xea, 0xac, 0xa1, 0x66, 0x1a, 0x55, 0x1e, - 0x41, 0xa7, 0x0e, 0xe0, 0x49, 0xc1, 0x4b, 0xad, 0x7e, 0x3c, 0x1c, 0x3c, 0xf3, 0x83, 0xbf, 0xcf, 0xf4, 0x2d, 0xc4, - 0x44, 0x39, 0xd5, 0x08, 0x89, 0x2b, 0x25, 0x89, 0xf8, 0x78, 0xd1, 0xb2, 0x62, 0x54, 0x86, 0xf7, 0xbc, 0x52, 0xe5, - 0xab, 0x53, 0x95, 0x17, 0x23, 0x6d, 0x4b, 0xe0, 0x35, 0xf9, 0x87, 0xc8, 0x35, 0x6f, 0x7d, 0xdd, 0x55, 0x86, 0x5e, - 0xcb, 0x0a, 0x74, 0x04, 0x5b, 0x59, 0x4a, 0x0e, 0xf8, 0xa4, 0xba, 0xab, 0x56, 0xad, 0xcf, 0x29, 0xdb, 0x08, 0x37, - 0xf9, 0x75, 0xec, 0xe0, 0x48, 0xf9, 0x0d, 0x9e, 0x0b, 0x60, 0xaf, 0x01, 0x7b, 0x73, 0xce, 0x8a, 0xe6, 0xc1, 0x21, - 0x6d, 0x0b, 0x34, 0x32, 0x73, 0x3b, 0x57, 0xf7, 0x6d, 0x79, 0x94, 0xc6, 0x10, 0x99, 0xf6, 0xc0, 0x74, 0xb0, 0x19, - 0xe5, 0xbf, 0xa7, 0xfc, 0x56, 0xe1, 0x18, 0xf8, 0x76, 0xea, 0x1d, 0x40, 0xd5, 0xd3, 0x06, 0x19, 0x6b, 0x86, 0xa1, - 0x95, 0x5d, 0x2e, 0x85, 0x96, 0xa0, 0xa5, 0x6e, 0x82, 0xe0, 0xfc, 0x88, 0x28, 0x47, 0x00, 0xba, 0x48, 0x01, 0x13, - 0xfc, 0x94, 0xb6, 0xbb, 0xdf, 0x5f, 0xa7, 0x1e, 0xb9, 0x77, 0x85, 0xca, 0x66, 0xf9, 0x99, 0x60, 0xec, 0x27, 0x1a, - 0x33, 0xe8, 0xe8, 0x8a, 0x9c, 0xf0, 0xac, 0xd5, 0x61, 0x5d, 0x37, 0x65, 0x50, 0x16, 0xc7, 0xbc, 0x9a, 0xce, 0xfe, - 0x78, 0xb4, 0xaf, 0x1b, 0x64, 0x21, 0xff, 0x83, 0xf5, 0x90, 0x0c, 0xba, 0x07, 0xa1, 0x10, 0xbd, 0x79, 0x30, 0xc3, - 0xff, 0xd8, 0x86, 0x67, 0xdf, 0x71, 0xa3, 0x4e, 0x00, 0x73, 0xc4, 0xf5, 0xd2, 0x53, 0xb4, 0xf5, 0x70, 0x0b, 0x64, - 0x6b, 0xbc, 0xbc, 0xb5, 0xd7, 0x40, 0x4e, 0x71, 0xfc, 0x4b, 0x9e, 0xa9, 0x95, 0x0d, 0x7e, 0x7a, 0xca, 0x76, 0xe0, - 0xe1, 0x45, 0x08, 0x28, 0x86, 0x65, 0xe3, 0x97, 0x96, 0xe3, 0x8c, 0xfe, 0x9b, 0x47, 0x0c, 0x83, 0x45, 0xe4, 0xc7, - 0x17, 0xa5, 0x10, 0x5f, 0x85, 0xf7, 0xb9, 0xf2, 0x96, 0xe4, 0x94, 0xb9, 0xd4, 0xc3, 0xe8, 0xba, 0x24, 0x7d, 0x97, - 0x7c, 0x6c, 0x0d, 0xdb, 0x1f, 0xda, 0xfd, 0x66, 0x88, 0x20, 0x84, 0x72, 0xfc, 0x9c, 0xd1, 0x09, 0x8d, 0x0f, 0xab, - 0xd9, 0xe9, 0xf5, 0x7b, 0xe7, 0x78, 0xc1, 0xd6, 0x68, 0x80, 0xc7, 0x43, 0x17, 0xf3, 0x44, 0x0d, 0x9d, 0xae, 0x6b, - 0xe7, 0xe0, 0x81, 0x41, 0x96, 0x27, 0xdf, 0x31, 0x2c, 0xb1, 0x3f, 0x89, 0x78, 0xd2, 0x56, 0x6d, 0x6c, 0x8e, 0x54, - 0x1b, 0x35, 0x03, 0x3f, 0x78, 0x05, 0x05, 0x46, 0x17, 0xa4, 0x5b, 0x30, 0x0e, 0x47, 0x00, 0xb2, 0x62, 0x1c, 0x8f, - 0x0c, 0x26, 0x30, 0xa4, 0x1b, 0x8a, 0x02, 0xf0, 0xf0, 0x38, 0x1e, 0x84, 0x0c, 0x20, 0x5d, 0xf0, 0xd0, 0xb0, 0x4d, - 0x42, 0xca, 0xcf, 0xf3, 0xbc, 0x56, 0x43, 0xe8, 0x3b, 0x0b, 0xd5, 0xb1, 0x1f, 0x69, 0xaf, 0x58, 0xd7, 0xaa, 0x74, - 0x64, 0xab, 0x03, 0xf4, 0x0d, 0x19, 0xf8, 0xd6, 0xb1, 0x05, 0x40, 0xb4, 0xc4, 0xef, 0xa9, 0x57, 0xfb, 0x32, 0x66, - 0x85, 0x7a, 0xfd, 0xc6, 0xb4, 0xeb, 0xa5, 0xb4, 0x28, 0xa0, 0xe2, 0xb6, 0x55, 0xdb, 0x23, 0x39, 0xff, 0xe1, 0x5d, - 0x47, 0x3b, 0x3e, 0x3b, 0x35, 0xb6, 0x84, 0x32, 0xb7, 0x78, 0x22, 0xab, 0xa3, 0x2d, 0xd5, 0xa9, 0x3e, 0xe0, 0x52, - 0x93, 0xea, 0xcc, 0xc0, 0xf0, 0x1a, 0x01, 0xca, 0x2d, 0x44, 0xd2, 0x38, 0xec, 0x9d, 0x4f, 0x06, 0x05, 0x73, 0x8b, - 0x04, 0x24, 0xb0, 0x8d, 0xad, 0x5d, 0x34, 0xd7, 0xaf, 0xdf, 0x53, 0xaf, 0x6a, 0x53, 0xd5, 0x83, 0x37, 0x5e, 0xe0, - 0xec, 0x9d, 0xd6, 0x02, 0x02, 0x28, 0x6c, 0x2d, 0xcb, 0xc1, 0xb9, 0xdb, 0x55, 0x2d, 0x15, 0x65, 0xd4, 0xef, 0x9f, - 0xff, 0x9e, 0xa2, 0x22, 0xf6, 0x54, 0x71, 0xca, 0xfa, 0xed, 0x96, 0x79, 0x53, 0x59, 0xf2, 0x06, 0x55, 0xb4, 0x56, - 0x47, 0x4d, 0xe5, 0xba, 0xb9, 0x6a, 0xc9, 0x04, 0x31, 0xba, 0x4f, 0xd7, 0x3a, 0x77, 0xea, 0xbd, 0x57, 0x71, 0xc4, - 0x40, 0x70, 0xd3, 0x3d, 0x3e, 0x38, 0x08, 0x8d, 0x8a, 0x72, 0xc1, 0x8d, 0xd2, 0xaa, 0x92, 0x52, 0xc8, 0x5b, 0x15, - 0xcd, 0x99, 0x3e, 0x02, 0x20, 0x02, 0xac, 0x12, 0xf5, 0xbf, 0xf9, 0xd2, 0x18, 0x0f, 0x1e, 0xf8, 0x9a, 0x5c, 0xc7, - 0xd6, 0xfb, 0xa7, 0x35, 0xd2, 0x6a, 0xe3, 0x98, 0xd4, 0xaa, 0x97, 0xad, 0xe2, 0x65, 0xf7, 0x3a, 0x15, 0x83, 0xe7, - 0xff, 0x73, 0x1f, 0xa0, 0x46, 0xb4, 0x94, 0xc1, 0xad, 0xab, 0x01, 0x1a, 0x1f, 0x8e, 0x85, 0x6f, 0xfc, 0x90, 0x71, - 0x3e, 0x98, 0xa1, 0xa3, 0xda, 0x1c, 0x1c, 0x10, 0x1c, 0xd5, 0x3d, 0x1a, 0x13, 0x66, 0xe1, 0xdc, 0x83, 0x40, 0xf5, - 0x89, 0xfb, 0x8c, 0x6b, 0x2f, 0x68, 0x13, 0xf8, 0x64, 0x5d, 0xd7, 0x14, 0x01, 0x2e, 0x62, 0x63, 0x22, 0x86, 0xb8, - 0x6c, 0x12, 0xa9, 0x6f, 0xc6, 0xa0, 0x00, 0x28, 0x9e, 0x55, 0x24, 0x97, 0xde, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, - 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, - 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, - 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, 0x19, 0x7f, 0x46, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, - 0x9e, 0xc3, 0x67, 0xbc, 0x9c, 0x84, 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, - 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, - 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, - 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, - 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, - 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, - 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, - 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x9b, 0x22, 0x87, 0xc5, 0xf8, 0x61, 0x83, - 0x91, 0xc6, 0x6a, 0x0d, 0x86, 0xe5, 0x12, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, - 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, - 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x22, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, - 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, - 0x9d, 0xe4, 0xed, 0x12, 0x8e, 0xba, 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, - 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, 0xf7, 0xa1, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, - 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, - 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, - 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, - 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0x67, 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, - 0xf3, 0x9a, 0x5d, 0x3f, 0x11, 0x6c, 0xc7, 0x76, 0x4f, 0x10, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, - 0x2f, 0x2c, 0xf9, 0x02, 0xc0, 0x03, 0x59, 0x0c, 0x28, 0x3e, 0x0b, 0xef, 0x17, 0x96, 0x80, 0x9a, 0xfc, 0x96, 0xaf, - 0xbd, 0x77, 0x94, 0x7a, 0x03, 0x7f, 0x0e, 0x28, 0x7d, 0x92, 0x73, 0x6f, 0x39, 0xbc, 0xf5, 0x2f, 0x9e, 0x82, 0xf3, - 0xc4, 0x6a, 0x78, 0x03, 0x7f, 0x15, 0x7c, 0xe8, 0x2d, 0x07, 0x98, 0x58, 0xf2, 0xa1, 0xb7, 0x1a, 0x40, 0xaa, 0xc2, - 0x85, 0xc4, 0xd8, 0x87, 0xdf, 0x82, 0x9c, 0xe1, 0x1f, 0xbf, 0x6b, 0x0c, 0xd6, 0xdf, 0x82, 0x42, 0xa3, 0xb1, 0x96, - 0x2a, 0x64, 0x29, 0x16, 0x67, 0x02, 0x6c, 0xc2, 0x71, 0xb7, 0x2f, 0x56, 0xb5, 0x59, 0x0b, 0xfa, 0xf3, 0x01, 0xdf, - 0xa3, 0xb1, 0xba, 0x2a, 0xe7, 0xa2, 0xfc, 0x88, 0xf4, 0xa9, 0x8e, 0x8f, 0x51, 0xb1, 0xa9, 0xbb, 0xd3, 0xa9, 0x56, - 0x1d, 0x69, 0xbf, 0x2b, 0xd7, 0x60, 0xc7, 0xeb, 0xe4, 0xc8, 0x52, 0x78, 0xd6, 0x61, 0xe7, 0xa5, 0x53, 0xa2, 0xc3, - 0x30, 0xde, 0x6d, 0xd5, 0x33, 0x86, 0xf2, 0xdc, 0x60, 0x4c, 0x17, 0x3c, 0xe2, 0xcf, 0x06, 0xb9, 0x0c, 0x8d, 0x79, - 0x84, 0x6c, 0x18, 0xca, 0x87, 0x16, 0x19, 0x12, 0x22, 0xde, 0x43, 0x25, 0x60, 0xdb, 0x82, 0x32, 0x29, 0xe0, 0x2c, - 0x1a, 0xfc, 0x5e, 0x7b, 0x39, 0xf0, 0x1e, 0x44, 0x7e, 0x23, 0x5d, 0xca, 0x25, 0x36, 0x3a, 0x71, 0x2c, 0x0b, 0xed, - 0x3c, 0xae, 0xbf, 0x8e, 0x41, 0xfd, 0x5e, 0xe9, 0x37, 0x28, 0x67, 0x7f, 0x94, 0xac, 0xd3, 0xc6, 0x13, 0xe3, 0x5f, - 0xae, 0xf2, 0x4f, 0xd1, 0x52, 0x0f, 0xff, 0x9f, 0x31, 0x85, 0xd2, 0x5f, 0xa7, 0x65, 0xb4, 0x59, 0x2d, 0x44, 0x29, - 0xf2, 0x48, 0x9c, 0x7c, 0x2d, 0xb2, 0x73, 0xf9, 0xce, 0xa7, 0xd0, 0x2f, 0x00, 0x2d, 0xfb, 0x04, 0x19, 0xfd, 0x2b, - 0x13, 0x7c, 0xf8, 0xab, 0x76, 0xae, 0xcd, 0xf9, 0x78, 0x92, 0x5f, 0x59, 0x7b, 0xb7, 0xe3, 0x45, 0x62, 0x14, 0x63, - 0xb9, 0xaf, 0xba, 0x59, 0x39, 0x51, 0xc9, 0x81, 0x91, 0xae, 0xc9, 0x5e, 0xae, 0x64, 0xdd, 0x4e, 0xb7, 0x12, 0x88, - 0xa8, 0x02, 0xef, 0x31, 0xae, 0x62, 0x1f, 0xc1, 0x74, 0xdd, 0x71, 0x19, 0xed, 0x78, 0xcf, 0x78, 0x75, 0xa2, 0xac, - 0xe0, 0x76, 0x23, 0xda, 0x13, 0x3a, 0xfa, 0x69, 0x52, 0x5b, 0x16, 0x0e, 0x40, 0xee, 0x12, 0xc6, 0xb2, 0x21, 0x58, - 0x31, 0x28, 0x7d, 0xbd, 0xa6, 0x64, 0x59, 0x80, 0x45, 0x67, 0x97, 0x11, 0x88, 0x61, 0xdd, 0x34, 0x27, 0x74, 0xbc, - 0x74, 0x71, 0xde, 0x6b, 0x15, 0x29, 0x78, 0x46, 0x8b, 0x8e, 0xb9, 0xe9, 0x48, 0x37, 0x46, 0x7b, 0xfb, 0xc2, 0x20, - 0xa4, 0x78, 0xfe, 0xc0, 0x56, 0xeb, 0xe2, 0x22, 0xf1, 0x0a, 0x99, 0x68, 0x41, 0x2c, 0x45, 0x60, 0xc6, 0x0b, 0x4d, - 0x23, 0x4c, 0x50, 0xa6, 0x04, 0x8b, 0xd6, 0xe8, 0xd0, 0xfe, 0xb0, 0x84, 0xdd, 0x63, 0x8c, 0x00, 0x81, 0x2a, 0xd3, - 0x8b, 0xb0, 0x35, 0x61, 0x36, 0x75, 0xb1, 0x01, 0xda, 0x2a, 0x86, 0x06, 0x61, 0x6d, 0x88, 0xf9, 0x98, 0xe6, 0xcb, - 0x7f, 0x62, 0x31, 0xb6, 0x27, 0x10, 0xdb, 0xbb, 0x5d, 0x93, 0x30, 0xdd, 0x6b, 0x71, 0x63, 0xbd, 0xdc, 0x9e, 0x72, - 0x4c, 0xed, 0x58, 0x1b, 0xb5, 0x63, 0x2d, 0xf4, 0x8e, 0xb5, 0xd6, 0x3b, 0xd6, 0xb2, 0xe1, 0x1f, 0x32, 0x2f, 0x66, - 0x09, 0xe8, 0x77, 0x57, 0x5c, 0x35, 0x08, 0x9a, 0xb1, 0x61, 0xb7, 0xf0, 0x5b, 0x62, 0xed, 0x96, 0xfe, 0xc5, 0x82, - 0xdd, 0x98, 0x3e, 0xd0, 0xad, 0x03, 0x2c, 0x23, 0x6a, 0xf2, 0x1d, 0xf2, 0x6e, 0x3a, 0x2b, 0x0a, 0xb7, 0x27, 0x76, - 0xe3, 0xb3, 0x6b, 0xf3, 0xe6, 0xdd, 0x93, 0x08, 0x72, 0xef, 0xb8, 0x77, 0x37, 0xbc, 0xf6, 0x2f, 0x74, 0x0b, 0xe4, - 0x64, 0x96, 0x33, 0x90, 0x3a, 0xe2, 0x33, 0x44, 0x2b, 0x7b, 0xca, 0x77, 0x42, 0xee, 0x6c, 0xeb, 0x27, 0x77, 0xee, - 0xb6, 0xb6, 0x7c, 0x72, 0xc7, 0xaa, 0x11, 0xc5, 0x8a, 0xd3, 0x14, 0x09, 0xb3, 0x68, 0x03, 0x3c, 0xf5, 0xf2, 0xfd, - 0x8e, 0x1d, 0x73, 0xb8, 0x7b, 0xd2, 0xd1, 0xf1, 0x72, 0x0e, 0xd8, 0xdd, 0x7f, 0xb4, 0x09, 0x1b, 0x2b, 0x5d, 0xab, - 0xd0, 0xe1, 0xee, 0x49, 0xa6, 0xf1, 0x1c, 0x8e, 0xe4, 0xd3, 0xb1, 0xc6, 0x06, 0x41, 0x5d, 0x9f, 0x33, 0xa8, 0x1d, - 0xbb, 0xaf, 0x09, 0xbb, 0xec, 0x98, 0xd7, 0xba, 0xe6, 0xed, 0x95, 0xa7, 0x62, 0x43, 0x40, 0x87, 0xaf, 0xd5, 0x0d, - 0xf2, 0x2f, 0x81, 0x53, 0x04, 0x80, 0x1c, 0x8e, 0x97, 0x3c, 0xf6, 0x7d, 0x9a, 0xa5, 0xf5, 0x0e, 0xb5, 0x16, 0x95, - 0x65, 0x19, 0xd6, 0xde, 0x0f, 0x5a, 0x31, 0x2c, 0x35, 0xfd, 0xd3, 0x71, 0xe0, 0x76, 0xb6, 0x5b, 0x19, 0xbb, 0x8c, - 0x27, 0xc5, 0xc5, 0xaf, 0xa7, 0x85, 0x72, 0xed, 0xe6, 0x6d, 0xfc, 0xa6, 0xd5, 0x92, 0xa5, 0xb5, 0x1e, 0xf2, 0xd2, - 0xb2, 0x88, 0x40, 0x00, 0xc3, 0x91, 0xb2, 0x8b, 0x25, 0xdc, 0x23, 0xac, 0xee, 0x41, 0x28, 0x99, 0x17, 0x2e, 0x9e, - 0xb2, 0x18, 0x12, 0x01, 0xb6, 0x3b, 0x54, 0x6c, 0x0b, 0x17, 0x4f, 0xd9, 0x86, 0x17, 0xfd, 0x7e, 0xa6, 0x3a, 0x85, - 0xac, 0x3b, 0x0b, 0xbe, 0x51, 0xcd, 0xb1, 0x86, 0x9a, 0xad, 0x4d, 0xb2, 0x35, 0xce, 0x6d, 0xc5, 0xc7, 0xb2, 0xad, - 0xf8, 0x58, 0x59, 0xeb, 0xd2, 0xbd, 0xde, 0xa3, 0xba, 0x00, 0xb6, 0xfe, 0xdb, 0xe3, 0x95, 0xeb, 0xf9, 0x8c, 0x00, - 0xbe, 0x6e, 0xf8, 0x78, 0x72, 0x83, 0x5e, 0x25, 0x37, 0xfe, 0xed, 0x40, 0x8d, 0xbf, 0xd3, 0xb9, 0x37, 0x00, 0x5d, - 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x37, 0x73, - 0xb6, 0x03, 0xa7, 0x82, 0x64, 0x60, 0x2f, 0x2b, 0xb6, 0x0b, 0x62, 0x3b, 0xe1, 0x77, 0x02, 0xa6, 0x7c, 0x0e, 0x41, - 0x5c, 0xc1, 0x2d, 0xc4, 0xe1, 0xc9, 0x3f, 0x07, 0x77, 0xad, 0xcd, 0xfa, 0x8e, 0x59, 0x9d, 0x13, 0xac, 0x99, 0xd5, - 0x83, 0xc1, 0xa2, 0x99, 0xac, 0xfa, 0x7d, 0x6f, 0xa7, 0x1d, 0x9f, 0x96, 0x52, 0x27, 0x76, 0x5a, 0xab, 0x75, 0xc3, - 0xae, 0xa5, 0xd6, 0xc5, 0x18, 0x7a, 0x80, 0xf8, 0xe9, 0x76, 0xc0, 0xef, 0x3a, 0xd6, 0x96, 0x77, 0xcd, 0x6e, 0xd8, - 0x0e, 0x2e, 0x41, 0x4d, 0x7b, 0xd9, 0x9f, 0x54, 0x2e, 0x68, 0xc7, 0x2e, 0x89, 0x87, 0x33, 0x66, 0x95, 0x32, 0xb3, - 0x4e, 0xaa, 0x2b, 0xd1, 0x19, 0xd3, 0x59, 0xeb, 0xf9, 0x5c, 0xcd, 0x27, 0x85, 0x06, 0xf5, 0x3b, 0x27, 0x3e, 0xa2, - 0xa2, 0xf3, 0x04, 0xb6, 0x96, 0x15, 0xc4, 0x6a, 0x9f, 0x83, 0xb5, 0x56, 0xbb, 0xf4, 0x7b, 0xf9, 0x80, 0xdb, 0x94, - 0xc3, 0x3a, 0x30, 0xa8, 0x39, 0xb1, 0xa2, 0x1e, 0xb2, 0x1d, 0xe3, 0xe6, 0xa7, 0x97, 0x3f, 0x38, 0x61, 0xc9, 0x8a, - 0xd5, 0xfe, 0xf4, 0xd7, 0x27, 0x9e, 0xfe, 0x4e, 0xed, 0x5f, 0x08, 0x3f, 0x18, 0xff, 0xbb, 0x76, 0x5f, 0x6b, 0x31, - 0x2a, 0x5b, 0xe5, 0x08, 0x8d, 0xbb, 0x95, 0x34, 0x59, 0x7e, 0x16, 0x9e, 0xb0, 0x16, 0x3c, 0xcb, 0xf5, 0x12, 0xcd, - 0x0a, 0x58, 0x61, 0x2d, 0x93, 0x70, 0x85, 0xb1, 0x5a, 0xda, 0xea, 0x5b, 0x34, 0xcd, 0xf1, 0xe1, 0x5c, 0x1b, 0x94, - 0x29, 0x67, 0x67, 0xc4, 0x6a, 0xb8, 0x0c, 0x4b, 0x13, 0x8a, 0x90, 0xdd, 0xdb, 0xc1, 0x8d, 0x9d, 0xb2, 0x94, 0x32, - 0x9c, 0x63, 0x30, 0xe1, 0x91, 0x18, 0x55, 0xf9, 0xfe, 0xbe, 0xa4, 0xc8, 0x69, 0x5b, 0x0e, 0xaa, 0x10, 0xf6, 0x91, - 0x44, 0x09, 0xdc, 0x8a, 0xb4, 0x50, 0xa4, 0x2c, 0xfe, 0x76, 0x80, 0x2e, 0xf0, 0x02, 0xea, 0x6a, 0xd4, 0xed, 0x0f, - 0x47, 0x3c, 0x7c, 0x60, 0xea, 0x03, 0x23, 0x96, 0x04, 0x6a, 0x7b, 0x9e, 0xa5, 0x4b, 0x50, 0xe1, 0xf7, 0x70, 0x35, - 0x11, 0xfb, 0xb9, 0x25, 0x45, 0x45, 0x36, 0xd2, 0x1b, 0x5a, 0x83, 0x47, 0x68, 0x4d, 0x79, 0xe1, 0xa4, 0xda, 0xa4, - 0xf3, 0x8e, 0x90, 0x63, 0xf5, 0xad, 0x25, 0x8c, 0x76, 0x45, 0x2f, 0xee, 0x1d, 0xbd, 0xe7, 0xe9, 0xaa, 0xe7, 0xfe, - 0xc4, 0x15, 0xf3, 0xe4, 0x36, 0x02, 0x75, 0x2b, 0xa8, 0x6e, 0xef, 0x55, 0x82, 0x05, 0x4b, 0xda, 0x7d, 0xfc, 0x76, - 0xd6, 0x0e, 0x44, 0x65, 0xac, 0xd2, 0xb7, 0x24, 0x61, 0x4f, 0x0c, 0x3a, 0x85, 0xaa, 0xdc, 0xee, 0x8e, 0xb6, 0xc0, - 0x75, 0xcc, 0x52, 0xf4, 0xdc, 0x16, 0xb9, 0x5b, 0xfe, 0xdd, 0x73, 0x45, 0xce, 0x7e, 0x09, 0x08, 0x4e, 0xcd, 0x37, - 0xc4, 0x97, 0x23, 0x3c, 0xaa, 0x6e, 0x81, 0xe3, 0xf4, 0x1d, 0xc0, 0x3f, 0x1c, 0x2e, 0x41, 0x13, 0x10, 0x0b, 0xd6, - 0x4b, 0xe3, 0x1e, 0xeb, 0xc5, 0xc5, 0x66, 0x99, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, - 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, - 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, - 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, - 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, - 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0xff, 0x31, 0x7e, 0xdc, 0x33, - 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, 0xaf, 0xff, 0x84, 0x00, 0x38, 0x3c, 0x9b, 0x7a, 0x97, 0x63, 0xc8, 0x2a, 0xcb, - 0x08, 0x24, 0x3f, 0x31, 0xf8, 0xf2, 0x05, 0x40, 0xd5, 0x67, 0xba, 0x56, 0x93, 0xa3, 0xf6, 0x98, 0x43, 0x57, 0x0c, - 0x00, 0xdb, 0xb0, 0x44, 0x55, 0x2d, 0x6c, 0xc2, 0xe2, 0xf6, 0x33, 0x8c, 0xe6, 0xb2, 0xe9, 0x05, 0x0d, 0xd4, 0x23, - 0x04, 0xbf, 0xb4, 0x1e, 0x5a, 0x6b, 0x99, 0x72, 0xe8, 0xda, 0x28, 0xaa, 0x6c, 0xa8, 0x4b, 0x58, 0xad, 0x45, 0x54, - 0x13, 0x45, 0xca, 0x25, 0xa3, 0x28, 0x96, 0x2a, 0xd8, 0x67, 0x62, 0x09, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0x7e, - 0x09, 0x08, 0x6b, 0x61, 0x2d, 0xa4, 0x33, 0xa8, 0xbd, 0xd3, 0x8f, 0x94, 0xbf, 0xbc, 0x90, 0xdb, 0xb9, 0x85, 0x22, - 0xdc, 0x9e, 0x83, 0xf2, 0xa6, 0xae, 0x4a, 0x45, 0x34, 0x5a, 0x02, 0xa5, 0xcc, 0x09, 0x22, 0x0b, 0x10, 0xc0, 0x71, - 0x03, 0x81, 0xcf, 0x6b, 0x7c, 0x02, 0x8d, 0x42, 0x20, 0x3f, 0xb0, 0x0a, 0xd7, 0x1e, 0xd2, 0x52, 0x6b, 0x44, 0x94, - 0x88, 0x1f, 0x5d, 0x3d, 0xc7, 0xf6, 0xd5, 0xd3, 0x58, 0x5b, 0x4a, 0x13, 0xc4, 0x4f, 0x2c, 0xb6, 0x10, 0x13, 0x44, - 0x75, 0x88, 0x8e, 0x60, 0x39, 0x21, 0x44, 0xe1, 0x4f, 0xa1, 0x9f, 0x1a, 0xf8, 0x4b, 0xb6, 0x28, 0xf2, 0x9a, 0x60, - 0x31, 0x2b, 0x06, 0x68, 0x55, 0x04, 0x9e, 0xe9, 0x6c, 0xa9, 0xcc, 0x69, 0x1e, 0x1d, 0xd9, 0xc1, 0x79, 0xd7, 0xc1, - 0x5e, 0xfa, 0x32, 0x76, 0xb2, 0x6c, 0x1a, 0xb5, 0xb1, 0x21, 0x12, 0x5e, 0x91, 0x5f, 0x67, 0xa9, 0x71, 0x8e, 0xcc, - 0xe5, 0xfa, 0xae, 0x8b, 0xe5, 0x92, 0xb6, 0x09, 0xab, 0x10, 0xa1, 0x6e, 0x1b, 0x2a, 0x97, 0xc2, 0x6c, 0x6c, 0x9a, - 0x06, 0xf8, 0x42, 0x51, 0xa9, 0x54, 0xa5, 0xb6, 0x52, 0xc9, 0x09, 0xef, 0xfa, 0xa6, 0x16, 0xa9, 0x2b, 0x82, 0x6d, - 0xcc, 0x50, 0x0f, 0xe5, 0x46, 0x8d, 0x7d, 0xdb, 0xb1, 0x4a, 0xef, 0x30, 0x41, 0xce, 0xc8, 0x8b, 0x1c, 0x5c, 0x94, - 0x14, 0x64, 0xae, 0x86, 0x30, 0x7f, 0xd0, 0xf0, 0x69, 0x61, 0xb9, 0x87, 0x12, 0x30, 0x3b, 0x6a, 0x78, 0x18, 0x21, - 0x10, 0x71, 0xa9, 0xec, 0x2b, 0x26, 0x7e, 0x4f, 0xc1, 0x2c, 0x99, 0xd0, 0xbd, 0x88, 0x45, 0x11, 0xda, 0xf8, 0x24, - 0x49, 0xa6, 0x9e, 0xa6, 0xe0, 0x46, 0x2e, 0xc3, 0x1c, 0x8d, 0xd0, 0x92, 0x8f, 0x1c, 0x48, 0x5f, 0xcb, 0xa9, 0x04, - 0x1f, 0x51, 0xa7, 0x80, 0xe3, 0xf9, 0x79, 0x61, 0xfd, 0x64, 0xb9, 0xc4, 0x5c, 0xd6, 0xe6, 0xbf, 0xec, 0xe8, 0x18, - 0xec, 0xf2, 0x34, 0x71, 0x5c, 0xfd, 0x47, 0x55, 0x52, 0xdc, 0xbf, 0x49, 0x73, 0x40, 0x11, 0xcc, 0xec, 0x29, 0xc6, - 0xc7, 0x3e, 0xcb, 0x14, 0xf0, 0xb7, 0xeb, 0xad, 0x25, 0x13, 0xbb, 0xa4, 0xdd, 0x5c, 0x19, 0xbf, 0xd4, 0x86, 0x1d, - 0x07, 0xe7, 0x06, 0xa0, 0x38, 0x6b, 0x74, 0x58, 0x5e, 0xeb, 0xb6, 0x55, 0xa1, 0x02, 0xb5, 0xfe, 0xf7, 0x6e, 0x61, - 0xca, 0xdb, 0xbc, 0x54, 0xde, 0xe6, 0xa1, 0x09, 0x10, 0x88, 0xcc, 0x90, 0x67, 0x4d, 0xc7, 0x24, 0x71, 0xef, 0x48, - 0x49, 0xfb, 0x8e, 0x14, 0x3f, 0x78, 0x47, 0x42, 0xbe, 0x25, 0x74, 0x64, 0x5f, 0x70, 0x72, 0x02, 0x65, 0x06, 0x7b, - 0x79, 0xcd, 0x64, 0xff, 0x80, 0xf6, 0xc2, 0xb9, 0x2c, 0xaf, 0xf8, 0x5b, 0xe1, 0xad, 0xfd, 0xe9, 0xfa, 0xb4, 0xab, - 0xea, 0xed, 0x37, 0x66, 0xe6, 0xe1, 0x50, 0x1c, 0x0e, 0x95, 0x09, 0xda, 0xbd, 0xe1, 0x62, 0x90, 0xb3, 0x3b, 0x37, - 0x3e, 0xfe, 0x9a, 0xa3, 0x88, 0xad, 0x94, 0x47, 0xd2, 0x85, 0x4a, 0x0c, 0x2f, 0x0d, 0x3c, 0xcc, 0x8e, 0x8f, 0x27, - 0xbb, 0xab, 0xbb, 0xc9, 0x60, 0xb0, 0x53, 0x7d, 0xbb, 0xe5, 0xf5, 0x6c, 0x37, 0x67, 0xf7, 0xfc, 0x76, 0xba, 0x0d, - 0xf6, 0x0d, 0x6c, 0xbb, 0xbb, 0x2b, 0x71, 0x38, 0xec, 0x9e, 0xf1, 0x1b, 0x7f, 0x7f, 0x8f, 0x80, 0xce, 0xfc, 0x7c, - 0xdc, 0xc6, 0xf8, 0x79, 0xdb, 0x76, 0xd5, 0xda, 0x01, 0x3c, 0xfd, 0x6b, 0xef, 0xed, 0x6c, 0x31, 0xf7, 0xd9, 0x07, - 0x7e, 0x0f, 0xfe, 0xf9, 0xb8, 0x49, 0x22, 0xf5, 0x89, 0x76, 0x99, 0x7c, 0x0b, 0x0e, 0xe4, 0x3b, 0x9f, 0x7d, 0xe6, - 0xf7, 0xb3, 0xc5, 0x9c, 0x17, 0x87, 0xc3, 0xfb, 0x69, 0x88, 0x64, 0x4d, 0x61, 0x45, 0x2c, 0x29, 0x9e, 0x1f, 0x84, - 0xc7, 0xef, 0x45, 0x64, 0x88, 0xb4, 0xdc, 0xbb, 0x43, 0xf6, 0x96, 0x45, 0x7e, 0x00, 0x1f, 0x64, 0x3b, 0x7f, 0x22, - 0x6b, 0x4a, 0xf7, 0x8b, 0x0f, 0xfe, 0xe1, 0x40, 0x7f, 0x7d, 0xf6, 0x0f, 0x87, 0xf7, 0xec, 0x1e, 0xc1, 0xd1, 0xf9, - 0x0e, 0xfa, 0x47, 0xdf, 0x3a, 0xa0, 0x2a, 0xc3, 0xeb, 0xd9, 0x66, 0xee, 0x3f, 0x5b, 0xb1, 0x25, 0x70, 0xa1, 0x28, - 0x2f, 0xb4, 0xb7, 0xec, 0x1e, 0xbd, 0xce, 0xc8, 0x89, 0x68, 0xb6, 0x9b, 0xfb, 0x2c, 0xc6, 0xe7, 0xea, 0xbe, 0x98, - 0x7c, 0xf3, 0xbe, 0xb8, 0x63, 0xdb, 0xee, 0xfb, 0xa2, 0x7c, 0xd3, 0x5d, 0x3f, 0x5b, 0xb6, 0x63, 0xf7, 0x30, 0xc3, - 0xae, 0xf9, 0xdb, 0xe6, 0xd8, 0x31, 0xf6, 0x9b, 0x37, 0x46, 0x00, 0x65, 0xb6, 0x60, 0xb1, 0xe0, 0xa0, 0x54, 0xab, - 0xb6, 0x25, 0x91, 0x57, 0x3a, 0x50, 0x6d, 0x46, 0x70, 0x5f, 0x2d, 0xe4, 0xcc, 0x33, 0x03, 0x7d, 0x5b, 0x21, 0x5a, - 0x38, 0x6c, 0xc0, 0xdf, 0x68, 0xeb, 0x18, 0xc3, 0x34, 0xab, 0x99, 0xb6, 0x45, 0x5d, 0x7e, 0xdf, 0x7b, 0x26, 0xbf, - 0x91, 0x81, 0x2d, 0x44, 0x52, 0x38, 0x8e, 0x2f, 0x9e, 0x9e, 0xf0, 0x5f, 0xb5, 0x3c, 0x6a, 0xb5, 0x5f, 0x28, 0xf5, - 0xe9, 0x35, 0x1d, 0xd1, 0xc4, 0xbd, 0x68, 0xcb, 0xb0, 0x46, 0x59, 0x53, 0x4b, 0x87, 0x61, 0x5c, 0xc3, 0xbe, 0x3c, - 0x70, 0xe8, 0x3b, 0x20, 0xd0, 0x56, 0xa9, 0x14, 0x68, 0xe1, 0x18, 0x46, 0x61, 0x16, 0x52, 0x1e, 0x16, 0x66, 0x29, - 0xef, 0xb1, 0x40, 0x8b, 0x5b, 0x75, 0x8f, 0xa9, 0xed, 0x16, 0x44, 0x58, 0xbd, 0x65, 0x9c, 0x5f, 0x36, 0xaa, 0x70, - 0x5b, 0x80, 0xa2, 0x08, 0xca, 0x60, 0x4f, 0x72, 0xdb, 0x8d, 0x92, 0x66, 0xa3, 0xb0, 0x16, 0xcb, 0xa2, 0xdc, 0xf5, - 0x1a, 0x76, 0x83, 0x17, 0x54, 0xfd, 0x84, 0xb0, 0x2d, 0x7b, 0xd6, 0xa1, 0x5c, 0xa4, 0xff, 0x96, 0xa5, 0xe7, 0xfb, - 0xad, 0x39, 0xff, 0xd3, 0x57, 0xf4, 0x51, 0xf9, 0xef, 0x5f, 0xd2, 0x4f, 0x06, 0xcb, 0xc8, 0x29, 0xf5, 0x53, 0x34, - 0xba, 0x4d, 0x73, 0xc2, 0xd8, 0xf2, 0xf5, 0xd3, 0xef, 0x90, 0x29, 0x48, 0x0e, 0xa5, 0x54, 0xe5, 0x64, 0x0f, 0x7d, - 0xe1, 0x75, 0x1f, 0x66, 0x82, 0x01, 0x08, 0xaf, 0xd1, 0xa6, 0x9a, 0x30, 0x89, 0x07, 0x57, 0xf0, 0x7f, 0x23, 0x88, - 0x41, 0xfb, 0x44, 0x51, 0xc7, 0xb6, 0x91, 0xae, 0xdb, 0xce, 0x41, 0x72, 0xa7, 0xae, 0xfc, 0x51, 0x39, 0xf9, 0x77, - 0x34, 0x44, 0x5e, 0x71, 0x85, 0x58, 0x59, 0x70, 0x89, 0xc5, 0x50, 0x91, 0x02, 0x5c, 0x43, 0x10, 0x29, 0x8b, 0x92, - 0xc2, 0x2d, 0x07, 0x55, 0x11, 0x80, 0x71, 0xb5, 0x3a, 0xea, 0x44, 0xf8, 0xb8, 0xb5, 0x16, 0x21, 0x58, 0xd1, 0xa8, - 0x95, 0xb5, 0x02, 0x5f, 0x90, 0xbe, 0x74, 0x28, 0x88, 0xe9, 0x51, 0x48, 0x55, 0xe9, 0x50, 0x20, 0xcd, 0xa1, 0xe2, - 0x1b, 0x83, 0x8d, 0xa2, 0x22, 0x3d, 0x7f, 0x69, 0x52, 0x72, 0x69, 0xcc, 0xf8, 0x20, 0xca, 0x48, 0xe4, 0x75, 0xb8, - 0x14, 0xd3, 0x02, 0xf9, 0x46, 0x8f, 0x1f, 0x04, 0x97, 0xf0, 0x6e, 0xc8, 0xbd, 0x02, 0x6c, 0x09, 0xd8, 0x01, 0xee, - 0x95, 0x19, 0xe5, 0x3a, 0xad, 0xeb, 0xb7, 0xd6, 0x43, 0x31, 0x0c, 0x9f, 0x58, 0x02, 0xdb, 0xd1, 0x3a, 0x3a, 0xd2, - 0xc3, 0x87, 0xff, 0x75, 0x55, 0x73, 0xd4, 0xa9, 0x5c, 0xce, 0x8e, 0x27, 0x2c, 0x45, 0xcc, 0xa0, 0xfb, 0xeb, 0xf6, - 0x5a, 0x00, 0xdd, 0x2e, 0x8b, 0x79, 0x36, 0xda, 0xc9, 0xbf, 0xa5, 0x1b, 0x2b, 0x4a, 0x9b, 0x78, 0x97, 0xf5, 0xc6, - 0xfe, 0x70, 0xf4, 0x1f, 0x4f, 0xde, 0x4d, 0x08, 0x55, 0x67, 0xc3, 0xd6, 0x3a, 0xce, 0xe5, 0x7f, 0xfd, 0xe7, 0x98, - 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, - 0x5f, 0x68, 0x9d, 0x30, 0x31, 0xb2, 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0xa5, 0xca, 0x2c, 0x20, 0xf3, 0x20, 0x9f, 0xac, - 0x8d, 0x06, 0x73, 0xc5, 0xeb, 0xd9, 0x7a, 0x2e, 0x95, 0xcf, 0x60, 0xca, 0x59, 0x0c, 0x4e, 0x96, 0xc2, 0xee, 0x48, - 0xa0, 0x68, 0xcd, 0xd0, 0xb5, 0x3f, 0xc5, 0x56, 0xbd, 0x4c, 0xab, 0x1a, 0xe0, 0x01, 0x21, 0x06, 0x86, 0xda, 0xab, - 0x85, 0x87, 0xd6, 0x02, 0x58, 0xfb, 0xa3, 0xd2, 0x0f, 0xc6, 0x93, 0x05, 0xbf, 0x41, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, - 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x1b, 0xbe, 0xf1, 0x95, 0x0f, 0xc6, 0x35, - 0x6a, 0xab, 0x41, 0x41, 0xed, 0xe8, 0x96, 0xc7, 0x8e, 0xde, 0xf9, 0xee, 0x84, 0xbe, 0xfa, 0x46, 0x0b, 0xc7, 0xdf, - 0x38, 0x23, 0xd7, 0x6c, 0xd5, 0x21, 0x47, 0x34, 0x93, 0x0e, 0x21, 0x62, 0xc5, 0xd6, 0xec, 0x9a, 0x54, 0xce, 0x9d, - 0x43, 0x76, 0xfa, 0x08, 0x55, 0x7a, 0xad, 0x87, 0xb7, 0x13, 0xa5, 0xbb, 0x3d, 0xde, 0x4d, 0xbe, 0x67, 0x13, 0x11, - 0x83, 0x01, 0x6d, 0x10, 0xce, 0xc8, 0x3a, 0x44, 0x2a, 0x1d, 0x20, 0x04, 0x8e, 0x09, 0x68, 0xfa, 0xaf, 0x6f, 0x49, - 0x14, 0x70, 0xa4, 0x8d, 0x90, 0xb5, 0xec, 0x70, 0xc8, 0x41, 0xa3, 0xdc, 0xfc, 0xe9, 0x15, 0xea, 0x34, 0x07, 0xe6, - 0xe9, 0x12, 0xf6, 0x1c, 0x3c, 0xd2, 0x8b, 0xe3, 0x23, 0xfd, 0xbf, 0xa3, 0x89, 0x1a, 0xff, 0xfb, 0x9a, 0x28, 0xa5, - 0x45, 0x72, 0x54, 0x4b, 0xdf, 0xa5, 0x8e, 0x82, 0x8b, 0xbc, 0xa3, 0x16, 0xb2, 0x67, 0xd9, 0xb8, 0x51, 0xcd, 0xfb, - 0xff, 0xb5, 0x32, 0xff, 0x5f, 0xd3, 0xca, 0x30, 0x25, 0x3b, 0x96, 0x6a, 0xe6, 0x81, 0x56, 0x31, 0xcc, 0xde, 0x90, - 0x84, 0xc8, 0x70, 0x69, 0xc0, 0x8f, 0x2a, 0xd8, 0xc7, 0x69, 0xb5, 0xce, 0xc2, 0x1d, 0x2a, 0x51, 0x6f, 0xc5, 0x32, - 0xcd, 0x9f, 0xd7, 0xff, 0x12, 0x65, 0x01, 0x53, 0x7b, 0x59, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, - 0x63, 0x1b, 0xdf, 0xc8, 0xf1, 0xb4, 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0xba, 0x90, 0x9c, 0xcb, 0xca, 0xe2, - 0x1e, 0xa1, 0x9b, 0x7f, 0x2c, 0xcb, 0xa2, 0xf4, 0x7a, 0x9f, 0x93, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, - 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, - 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, - 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, 0x2a, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, - 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xab, 0x1c, - 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, - 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x58, 0xb4, 0x92, - 0xb0, 0x6f, 0xdf, 0xb7, 0x53, 0x45, 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0xf3, 0x8c, 0x23, 0x49, 0x94, 0x08, 0x5e, - 0xe5, 0x8d, 0x19, 0x87, 0x1f, 0xdb, 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, - 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, - 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x37, 0x12, 0x97, - 0x10, 0x2f, 0xf3, 0xd5, 0x54, 0x44, 0xc1, 0xfb, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, - 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, - 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, - 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, - 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0x37, 0x42, 0x75, 0xb0, 0x2d, - 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, - 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, - 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, 0xf8, 0x8f, 0x99, 0x87, 0x69, 0x35, 0x2b, 0xc1, 0x9c, 0x6f, 0xa0, 0x12, 0xe3, - 0xc9, 0xe2, 0x8a, 0x6f, 0x5c, 0xac, 0xc4, 0x64, 0xb6, 0x98, 0x4f, 0xd6, 0x92, 0x6a, 0x2e, 0xf7, 0xd6, 0x2c, 0x63, - 0x0b, 0xd8, 0x3f, 0x0c, 0x0c, 0xa5, 0x03, 0x3b, 0x9a, 0x6a, 0xda, 0x24, 0xc0, 0x64, 0x3a, 0xe7, 0x7c, 0x78, 0x89, - 0x68, 0xb2, 0x3a, 0x75, 0x27, 0x53, 0xd5, 0x0e, 0xae, 0xc9, 0x99, 0x9c, 0x1e, 0xa9, 0xa7, 0x5a, 0xf7, 0x92, 0x8f, - 0xb6, 0xc3, 0x6a, 0xb4, 0xf5, 0x03, 0x70, 0xeb, 0x14, 0x76, 0xfa, 0x6e, 0x58, 0x8d, 0x76, 0xbe, 0x86, 0xdd, 0x25, - 0x85, 0x40, 0xf5, 0x57, 0x59, 0x93, 0xb9, 0x78, 0x5d, 0xdc, 0x7b, 0x05, 0x7b, 0xea, 0x0f, 0xf4, 0xaf, 0x92, 0x3d, - 0xf5, 0x6d, 0x26, 0xd7, 0xbf, 0xd2, 0xae, 0xd1, 0x98, 0xe9, 0x78, 0xed, 0x0a, 0xac, 0xd0, 0x00, 0xf9, 0x05, 0x3b, - 0xda, 0xeb, 0x1c, 0x04, 0x02, 0x74, 0x2f, 0xc1, 0x51, 0x14, 0x10, 0x35, 0xad, 0x2a, 0x8f, 0x4e, 0xf7, 0xfe, 0x1e, - 0xdf, 0x08, 0x01, 0x9b, 0x3c, 0xb5, 0xee, 0x2d, 0x63, 0xff, 0x70, 0x80, 0x10, 0x7a, 0x39, 0xfd, 0x46, 0x5b, 0x56, - 0x8f, 0x76, 0x2c, 0xf7, 0x0d, 0xa3, 0x9e, 0x82, 0x31, 0x0c, 0x5d, 0x58, 0xc5, 0x48, 0x9e, 0x01, 0x59, 0xe3, 0x37, - 0x88, 0x2e, 0x60, 0xd1, 0xeb, 0xbd, 0x3c, 0xa2, 0x41, 0x04, 0x54, 0x7a, 0x4d, 0x1a, 0x8b, 0x7c, 0xae, 0x0a, 0xd1, - 0x7b, 0x6f, 0xed, 0xbc, 0x99, 0x91, 0x2c, 0x93, 0x46, 0xaa, 0xdd, 0xca, 0x62, 0x5d, 0x79, 0xb3, 0x13, 0xd2, 0xc5, - 0x1c, 0x43, 0x65, 0xf0, 0x38, 0x00, 0xa5, 0xe7, 0x3f, 0x42, 0xaf, 0x64, 0xc8, 0x34, 0x4b, 0x34, 0xb3, 0xbb, 0xc6, - 0x9f, 0xac, 0x52, 0x2f, 0x46, 0xc4, 0x6c, 0x60, 0x0b, 0x71, 0x5b, 0x54, 0xba, 0x2d, 0x0a, 0x65, 0x8b, 0x22, 0x7d, - 0xa8, 0x9d, 0xe9, 0xce, 0x2c, 0x7c, 0x56, 0x99, 0xf6, 0x7d, 0xce, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, - 0x40, 0x85, 0x90, 0xbf, 0x46, 0x44, 0x24, 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, - 0x46, 0x79, 0xc1, 0x93, 0xa3, 0x01, 0xa9, 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xb8, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, - 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, - 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, - 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, - 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, 0xe9, 0xd9, 0xdf, 0x52, 0xb7, 0x67, 0xe5, 0x64, 0x2f, 0x3a, 0x27, 0xfb, - 0x74, 0x36, 0x0f, 0x04, 0x97, 0x3b, 0xf7, 0x79, 0x3e, 0xd5, 0xd3, 0xae, 0xf2, 0x83, 0xd6, 0x10, 0x59, 0xbb, 0x5c, - 0xd5, 0xbd, 0xae, 0x60, 0x01, 0x4b, 0x70, 0xb7, 0x5e, 0x9a, 0xff, 0x86, 0xdd, 0xdf, 0x0b, 0x7a, 0x69, 0xfe, 0x3b, - 0xfd, 0x49, 0x01, 0x1c, 0x80, 0xc6, 0xd4, 0x6e, 0x81, 0x87, 0x18, 0x2a, 0x28, 0xdc, 0xcd, 0xca, 0xb9, 0x57, 0x03, - 0x1c, 0x26, 0xe9, 0x1b, 0x5a, 0xbd, 0xd2, 0x62, 0xd7, 0xcb, 0x64, 0xaf, 0x00, 0x0f, 0x55, 0xc8, 0xc3, 0xc3, 0x21, - 0xea, 0x18, 0x76, 0x50, 0x47, 0xc0, 0xb0, 0x87, 0xd0, 0xd8, 0x02, 0xcf, 0xc7, 0x37, 0x19, 0xdf, 0x0b, 0x50, 0x1b, - 0x21, 0x3c, 0x5e, 0x2d, 0xca, 0x10, 0x5b, 0xf6, 0x1a, 0xa9, 0xa4, 0xde, 0x08, 0x44, 0x19, 0xad, 0x02, 0xda, 0x6a, - 0x8f, 0x59, 0x1a, 0x3f, 0x41, 0xa8, 0x58, 0xea, 0x63, 0x08, 0x0d, 0x1c, 0x7e, 0x87, 0x03, 0x48, 0xf0, 0x25, 0xd7, - 0x64, 0x73, 0xaf, 0xf3, 0x3b, 0xda, 0xe7, 0x0f, 0x87, 0xf3, 0x4b, 0x04, 0xa5, 0x4b, 0xe1, 0x23, 0x95, 0x88, 0xea, - 0x29, 0x6e, 0x4a, 0xc8, 0x66, 0xc9, 0x4a, 0x3f, 0xf8, 0x4d, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, - 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, - 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, - 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, - 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, - 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, - 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, - 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, - 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, - 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, - 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, - 0xe0, 0xcf, 0xc4, 0x68, 0x5d, 0x10, 0x20, 0xb2, 0xd9, 0xbe, 0x3e, 0x56, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, - 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0x48, 0xbc, 0xfd, 0x69, 0x90, 0x9d, - 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, - 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, - 0x47, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, - 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, - 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, - 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, - 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, 0x46, 0x69, 0xf5, 0x93, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, - 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xe5, 0x34, 0xd8, 0x61, 0xa2, - 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, - 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, - 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, - 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x5d, 0x8b, - 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0x2f, 0x8a, 0xed, 0xdb, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x27, - 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, - 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, 0x1c, 0xc7, 0x9f, 0xa0, 0x82, 0xe0, 0xbf, 0x00, 0xb3, 0x18, 0x20, 0x4f, - 0x67, 0x21, 0xe1, 0x14, 0xc2, 0xc5, 0x2a, 0xeb, 0xf7, 0xe5, 0x2f, 0xea, 0xa2, 0x8b, 0x4c, 0xd6, 0x7d, 0x12, 0x8e, - 0xcc, 0x58, 0x4e, 0xbd, 0x90, 0x3c, 0xef, 0x79, 0x32, 0x4d, 0x9e, 0xe4, 0x41, 0x04, 0x90, 0xcf, 0xe1, 0x5d, 0x98, - 0x66, 0x60, 0x95, 0x26, 0xe5, 0x47, 0x28, 0x7d, 0xf1, 0x79, 0xe5, 0x07, 0x3a, 0x7b, 0x6e, 0x92, 0xe1, 0xcd, 0xaa, - 0xf5, 0x26, 0xb5, 0xae, 0x8b, 0x07, 0xfc, 0xab, 0x33, 0xd8, 0x38, 0xd7, 0x99, 0xe0, 0xc0, 0x8b, 0xa4, 0xd6, 0x6b, - 0xc6, 0x9f, 0x65, 0xb8, 0x2e, 0x55, 0x1b, 0x7d, 0x14, 0xa2, 0x73, 0xc8, 0x54, 0x80, 0x42, 0x91, 0xf6, 0x0f, 0x4a, - 0xad, 0x4c, 0x2a, 0x6d, 0x24, 0x80, 0xee, 0x61, 0xd2, 0x60, 0x8b, 0xa1, 0x8c, 0xa5, 0x49, 0x94, 0x3b, 0x0d, 0xe2, - 0xca, 0x7e, 0xac, 0x24, 0x0e, 0x2d, 0x8b, 0xe4, 0xdf, 0xbb, 0x9e, 0xbe, 0x42, 0xea, 0x4e, 0x16, 0xc8, 0x8c, 0xf1, - 0x3c, 0x8f, 0x3f, 0x03, 0x61, 0x36, 0x68, 0xa3, 0xa2, 0x10, 0x42, 0x36, 0x88, 0x41, 0xe3, 0x79, 0x1e, 0xbf, 0x50, - 0x34, 0x1e, 0xf2, 0x51, 0xe4, 0xab, 0xbf, 0x4a, 0xfd, 0x57, 0xe8, 0x33, 0x13, 0x3c, 0x42, 0x35, 0xd1, 0xbf, 0x7b, - 0x3e, 0xbb, 0x03, 0xb5, 0x61, 0x14, 0x66, 0xa6, 0xfc, 0xca, 0x37, 0xc5, 0xd9, 0xeb, 0xaf, 0xe8, 0x2a, 0xdb, 0xba, - 0x1f, 0xbd, 0x3a, 0x22, 0xb0, 0x36, 0x46, 0x57, 0xdc, 0x18, 0x40, 0x0e, 0x93, 0xf7, 0x2b, 0x4a, 0xcb, 0x21, 0x0d, - 0x42, 0x07, 0x0d, 0x41, 0xaf, 0x24, 0xfa, 0x40, 0x62, 0x11, 0x63, 0x78, 0x21, 0x9e, 0x91, 0x9a, 0x4c, 0x34, 0xc4, - 0x2b, 0x62, 0x3f, 0x44, 0x4b, 0x4e, 0x4d, 0x74, 0x23, 0x4c, 0x31, 0x90, 0xd8, 0x19, 0x24, 0x27, 0x49, 0xad, 0xfc, - 0xe2, 0x99, 0x24, 0x2c, 0xb1, 0xf3, 0x10, 0x83, 0x49, 0x2d, 0xdd, 0xe9, 0x4d, 0x95, 0xbe, 0x1c, 0x69, 0x39, 0x68, - 0x1f, 0x80, 0x5d, 0x4a, 0x7a, 0xff, 0xa4, 0x50, 0xc4, 0x87, 0x30, 0x8e, 0x21, 0x7c, 0x8b, 0xa8, 0xae, 0xc0, 0xb9, - 0x56, 0xa0, 0xb1, 0x1a, 0x78, 0x68, 0x66, 0xd5, 0x7c, 0xc8, 0xe9, 0xa7, 0xd2, 0xf2, 0xc7, 0x88, 0xc6, 0x46, 0xeb, - 0xe6, 0x70, 0xd8, 0xd3, 0xaa, 0x97, 0xce, 0x41, 0x97, 0xcd, 0x24, 0x26, 0x6e, 0x20, 0x5d, 0x3f, 0xfa, 0xcd, 0x84, - 0xbd, 0x88, 0x0a, 0xb9, 0x14, 0x82, 0x82, 0x56, 0x07, 0x02, 0x87, 0xc2, 0x5b, 0x94, 0xf9, 0x22, 0xa6, 0x0d, 0x84, - 0xc1, 0xe7, 0x07, 0xf2, 0xf3, 0x4d, 0x41, 0x2a, 0x76, 0xac, 0x6b, 0xbf, 0xbf, 0x28, 0x3d, 0xc0, 0x93, 0x33, 0x49, - 0x9e, 0x36, 0x43, 0x58, 0x11, 0x40, 0x63, 0x56, 0x93, 0xc5, 0x09, 0x57, 0xe6, 0xf0, 0x55, 0xe5, 0x95, 0x2c, 0x65, - 0xea, 0x3c, 0xd5, 0x0b, 0x20, 0xea, 0x78, 0x83, 0x56, 0xa4, 0x7e, 0x85, 0xce, 0x5e, 0xb3, 0x12, 0x32, 0x1e, 0x9e, - 0x73, 0x9e, 0x8e, 0xee, 0x59, 0xc2, 0x23, 0xfc, 0x2b, 0x99, 0xe8, 0xc3, 0xef, 0x9e, 0xc3, 0xcd, 0x38, 0xe1, 0x91, - 0xdb, 0xec, 0x7d, 0x15, 0xae, 0xe0, 0x66, 0x5a, 0x00, 0x92, 0x5b, 0x90, 0x34, 0x01, 0x25, 0x24, 0x32, 0x21, 0xb3, - 0xa6, 0xe4, 0x8b, 0x96, 0xb6, 0xc1, 0x1a, 0x26, 0x9d, 0x07, 0xbc, 0x68, 0xf5, 0xd1, 0x6a, 0xa2, 0x5d, 0x66, 0xf9, - 0x7c, 0x88, 0x33, 0x54, 0x73, 0xdc, 0x9d, 0xc1, 0xcf, 0x01, 0xaf, 0x58, 0xd5, 0xa4, 0xa3, 0xdd, 0x80, 0x0b, 0x4f, - 0xae, 0xf3, 0x74, 0xb4, 0xc5, 0x5f, 0x72, 0x7f, 0x00, 0xe8, 0x60, 0xea, 0x12, 0xf8, 0x53, 0xb5, 0xd5, 0x54, 0xea, - 0xd7, 0xd6, 0x7e, 0x5d, 0x77, 0x56, 0x2b, 0xf7, 0xac, 0xcb, 0xd0, 0x1e, 0x19, 0x72, 0xc6, 0x0c, 0xf8, 0x73, 0xc6, - 0x92, 0x3f, 0x67, 0xac, 0xf8, 0x73, 0xc6, 0x8d, 0x91, 0x01, 0x94, 0xe0, 0x5e, 0xf2, 0x67, 0x7b, 0xc4, 0x0c, 0xb1, - 0x1a, 0x54, 0x02, 0x2b, 0x4b, 0x39, 0xf7, 0x91, 0x53, 0x4c, 0x39, 0x65, 0x78, 0xe9, 0x74, 0xe6, 0x0e, 0xe4, 0x3c, - 0x98, 0xb9, 0xc3, 0x64, 0xaf, 0xcf, 0x8d, 0x38, 0x96, 0xc6, 0xa4, 0xa8, 0x20, 0x9d, 0xd3, 0xe1, 0xe6, 0xd5, 0x71, - 0x9e, 0xb0, 0x8c, 0x8f, 0xdb, 0x67, 0x0a, 0x84, 0xd8, 0xe2, 0x19, 0x12, 0x29, 0x55, 0xb3, 0xdc, 0xe6, 0x0f, 0x87, - 0x7a, 0x74, 0xaf, 0x77, 0x7a, 0xf8, 0x95, 0xb0, 0x5f, 0x33, 0xcf, 0x3e, 0x41, 0x00, 0x93, 0x44, 0x9e, 0x49, 0x38, - 0xfa, 0xb1, 0x1c, 0xfd, 0x4d, 0xc3, 0xbf, 0x64, 0xa8, 0xee, 0x0e, 0x81, 0x89, 0x2d, 0x3b, 0x70, 0x08, 0x4e, 0x57, - 0x95, 0x48, 0xc0, 0xc1, 0x66, 0xc3, 0x22, 0xbd, 0xc7, 0x43, 0x9c, 0x0f, 0x0a, 0x1f, 0xa1, 0x61, 0x46, 0xef, 0xf7, - 0x37, 0xc2, 0xab, 0x64, 0x2b, 0x0f, 0x87, 0xc4, 0xba, 0x0b, 0x3b, 0xfa, 0x38, 0xda, 0xa3, 0x84, 0xda, 0x8f, 0x6a, - 0xbd, 0xa9, 0xd4, 0x83, 0xdc, 0xec, 0x42, 0x62, 0x50, 0xb1, 0x54, 0x9f, 0x5e, 0xa9, 0x3e, 0xd4, 0xac, 0xf3, 0xbb, - 0x3a, 0xee, 0x53, 0x31, 0x5a, 0xcb, 0x09, 0x01, 0xae, 0x83, 0x44, 0xa3, 0x03, 0x60, 0x9c, 0x6d, 0xb6, 0xbc, 0xd4, - 0xd6, 0x89, 0xd2, 0x71, 0x9c, 0xeb, 0xe3, 0xf8, 0x70, 0x90, 0x62, 0xc6, 0xe5, 0x91, 0x98, 0x71, 0xd9, 0x00, 0xbc, - 0x59, 0xe7, 0x41, 0x7d, 0x38, 0x5c, 0xd2, 0xa5, 0xc8, 0x74, 0xb6, 0x51, 0x7e, 0xd6, 0xa3, 0xfb, 0x27, 0x09, 0x9a, - 0x7b, 0x2b, 0xec, 0xbd, 0x48, 0xb6, 0x67, 0xb2, 0x4e, 0xbd, 0x8c, 0x7c, 0x7a, 0xe1, 0x9e, 0x5d, 0x72, 0xf5, 0xc3, - 0xea, 0xeb, 0xe9, 0x6f, 0xc2, 0x8b, 0x58, 0x45, 0xbb, 0x75, 0xc9, 0x84, 0xbd, 0xa5, 0x54, 0xd2, 0x2a, 0x2f, 0x9f, - 0x6e, 0xfc, 0x00, 0x33, 0xd3, 0x9e, 0x3e, 0xc8, 0x46, 0x54, 0x7f, 0x56, 0xa2, 0x56, 0x86, 0xc9, 0xc2, 0x79, 0xc9, - 0xd4, 0x93, 0x01, 0x8f, 0x59, 0xc9, 0x23, 0xd9, 0xe9, 0x8d, 0x41, 0x10, 0xc0, 0x3a, 0x27, 0xad, 0x3a, 0xe3, 0x68, - 0xb4, 0xaa, 0x5c, 0x9c, 0xae, 0x72, 0x81, 0xe1, 0x76, 0x6b, 0xb6, 0x51, 0x75, 0x96, 0x9b, 0x5a, 0xa5, 0x7c, 0x07, - 0xf0, 0xb1, 0xac, 0x72, 0x41, 0xc7, 0x94, 0xa9, 0xf3, 0x06, 0x82, 0xb1, 0x55, 0x8d, 0x0b, 0xa7, 0xc6, 0x05, 0x8f, - 0xa8, 0xdd, 0x4d, 0x53, 0x8f, 0xb6, 0xc0, 0x52, 0x3a, 0xda, 0xf1, 0x12, 0x55, 0x0a, 0x3f, 0x0b, 0xbe, 0x0f, 0xe3, - 0xf8, 0x45, 0xb1, 0x55, 0x07, 0xe2, 0x6d, 0xb1, 0x45, 0xda, 0x17, 0xf9, 0x17, 0xe2, 0x80, 0xd7, 0xba, 0xa6, 0xbc, - 0xb6, 0xe6, 0x34, 0xb0, 0x35, 0x8c, 0x94, 0x14, 0xce, 0xcd, 0x9f, 0x87, 0x03, 0xad, 0xec, 0x5a, 0xdd, 0x15, 0x6a, - 0x3d, 0xe6, 0xb0, 0x61, 0xdf, 0x64, 0xe1, 0x4e, 0x94, 0xe0, 0xc8, 0x25, 0xff, 0x3a, 0x1c, 0xb4, 0xca, 0x52, 0x1d, - 0xe9, 0xb3, 0xfd, 0xd7, 0x60, 0xcc, 0xd0, 0xa5, 0x09, 0x58, 0x36, 0x46, 0xf2, 0xaf, 0xa6, 0x99, 0x37, 0x4c, 0xd6, - 0x4c, 0xe1, 0x38, 0x34, 0x8c, 0x90, 0x06, 0x74, 0x1b, 0xd4, 0x86, 0x27, 0xf3, 0x4d, 0x55, 0x7e, 0x75, 0x47, 0xaa, - 0xfd, 0x60, 0x78, 0x39, 0x11, 0xe7, 0x74, 0x49, 0x52, 0x4f, 0x25, 0x94, 0x84, 0x60, 0x97, 0x3e, 0x90, 0x13, 0x2b, - 0x20, 0x6b, 0x19, 0xcb, 0x6f, 0xf5, 0x80, 0xd0, 0x7f, 0xda, 0xad, 0x17, 0xfa, 0x4f, 0xd3, 0x6c, 0xa1, 0xae, 0x3f, - 0x4c, 0xee, 0x3b, 0x7a, 0xfd, 0xc1, 0xe1, 0x9d, 0xba, 0xaa, 0xb8, 0x8a, 0x47, 0xb5, 0x61, 0x92, 0x1b, 0x65, 0xe1, - 0xae, 0xd8, 0xd4, 0x6a, 0x79, 0x3a, 0x0e, 0x23, 0x30, 0x23, 0x28, 0x40, 0xd6, 0x75, 0x1b, 0x11, 0xc3, 0x4a, 0x2e, - 0x13, 0xf2, 0x09, 0x01, 0x59, 0x94, 0x1a, 0xe7, 0xe3, 0x16, 0xa8, 0x44, 0x30, 0x38, 0x0d, 0xad, 0x55, 0x37, 0xf9, - 0x49, 0x65, 0x63, 0x4b, 0x20, 0x87, 0x24, 0x93, 0xc5, 0x72, 0x74, 0x2b, 0x16, 0x45, 0x29, 0xde, 0x60, 0x3d, 0x5c, - 0xb3, 0x85, 0xfb, 0x0c, 0x08, 0xed, 0x27, 0x4a, 0x7b, 0x13, 0x69, 0x82, 0xee, 0x25, 0x5b, 0x01, 0xc8, 0x00, 0x8a, - 0xba, 0xda, 0xad, 0xcf, 0xf9, 0x39, 0x92, 0x66, 0x38, 0x8c, 0x6e, 0x9f, 0x2e, 0x83, 0xe5, 0xe0, 0x12, 0xb5, 0xd2, - 0x97, 0x2c, 0x6e, 0x61, 0x50, 0xed, 0xcd, 0x12, 0x0e, 0x6a, 0x66, 0xad, 0x8d, 0x40, 0x30, 0xd9, 0x43, 0x41, 0xc5, - 0x5c, 0xc1, 0x3e, 0x28, 0x58, 0x4b, 0x5e, 0x07, 0x87, 0x5b, 0xfb, 0xb2, 0x52, 0x5c, 0x3c, 0xbd, 0x48, 0x5a, 0x17, - 0x96, 0xf2, 0xe2, 0x69, 0x03, 0x06, 0x97, 0x23, 0x6c, 0x2a, 0x30, 0x49, 0x00, 0xe8, 0x56, 0x44, 0x11, 0x2f, 0x4a, - 0x61, 0xdb, 0xca, 0x67, 0x4e, 0xd8, 0x60, 0xc3, 0xee, 0xe1, 0x5e, 0x19, 0x94, 0x0c, 0x2e, 0xc4, 0xb8, 0xdd, 0xec, - 0x02, 0x5c, 0xc1, 0x50, 0x18, 0x5b, 0xf3, 0x77, 0x99, 0x17, 0x29, 0x01, 0x37, 0x43, 0x94, 0xaf, 0x0d, 0x9c, 0x4c, - 0x7a, 0x72, 0x2d, 0x58, 0x0c, 0x58, 0xd0, 0xe0, 0x3b, 0x6a, 0xfd, 0x9d, 0xc9, 0xbf, 0xf1, 0xf4, 0xd0, 0x0f, 0x5e, - 0x64, 0xde, 0xc2, 0x67, 0xef, 0x2a, 0x19, 0xad, 0x49, 0xa2, 0xbc, 0x7a, 0xb8, 0x00, 0xb9, 0x61, 0x31, 0xba, 0x67, - 0x0b, 0x10, 0x27, 0x16, 0xa3, 0x84, 0x32, 0xba, 0xc2, 0xbd, 0xca, 0x6c, 0x99, 0x08, 0xa4, 0x38, 0xb0, 0x90, 0x72, - 0x6f, 0xb1, 0x0e, 0x16, 0xb8, 0x3f, 0x91, 0x5c, 0x40, 0xc9, 0x03, 0x28, 0x57, 0x0a, 0x08, 0xf8, 0x74, 0x00, 0xe5, - 0x4b, 0x79, 0x11, 0xfe, 0xc4, 0x89, 0x1a, 0x2c, 0x46, 0xf7, 0x0d, 0xfb, 0xc9, 0x0b, 0x2d, 0xfb, 0xc3, 0x52, 0x6b, - 0x1a, 0x56, 0x7c, 0x09, 0xd3, 0x62, 0xe2, 0xf6, 0xe5, 0xca, 0xae, 0x8a, 0xcf, 0x56, 0xea, 0xec, 0xa6, 0x86, 0x24, - 0xec, 0x1b, 0xb2, 0x0a, 0x70, 0xb0, 0x2a, 0xe2, 0x9e, 0x75, 0xb9, 0x0f, 0xa3, 0xbf, 0x36, 0x69, 0x29, 0x2c, 0x54, - 0x49, 0x7f, 0xdf, 0x94, 0x02, 0xa9, 0x4c, 0x74, 0xa2, 0x85, 0xe0, 0x0a, 0x0c, 0x02, 0x77, 0x22, 0xaf, 0x01, 0x30, - 0x06, 0x5c, 0x0a, 0x94, 0x65, 0x5b, 0x42, 0x48, 0x75, 0x3f, 0x03, 0xb5, 0x9d, 0xb8, 0x4b, 0x23, 0xb2, 0x16, 0xa2, - 0xaf, 0x82, 0x31, 0x73, 0x5e, 0x4a, 0xb7, 0xd8, 0x74, 0xb5, 0x59, 0x7d, 0x42, 0xe7, 0xd2, 0x96, 0x9b, 0x9f, 0xb0, - 0xc5, 0x5a, 0x81, 0xb2, 0x09, 0x49, 0xdb, 0x39, 0xcf, 0x51, 0x36, 0xa1, 0xa5, 0xbd, 0xa7, 0x1e, 0x15, 0xaa, 0x93, - 0xad, 0x97, 0xaa, 0xa9, 0x45, 0x58, 0x2d, 0x2e, 0x2a, 0x3f, 0x00, 0xdd, 0x54, 0x5a, 0x3d, 0xaf, 0x6b, 0x34, 0x85, - 0x5a, 0x2d, 0x1c, 0x37, 0xda, 0xd9, 0x74, 0x91, 0x2e, 0x11, 0x67, 0x55, 0xda, 0xa1, 0x7f, 0xca, 0xb4, 0xeb, 0x65, - 0x47, 0xbf, 0x19, 0x57, 0x17, 0xb8, 0x10, 0x1b, 0xf0, 0x39, 0xf7, 0x97, 0xd7, 0x7b, 0x1a, 0xf7, 0xfc, 0xc3, 0x01, - 0xd9, 0x93, 0xda, 0x1f, 0xaa, 0x8f, 0x5d, 0xc1, 0x90, 0x85, 0x51, 0xea, 0x2f, 0x52, 0xde, 0x7b, 0x84, 0xe3, 0xfe, - 0xa5, 0xea, 0xb1, 0x5f, 0x32, 0xbe, 0xaf, 0x8b, 0x4d, 0x94, 0x50, 0x54, 0x43, 0x6f, 0x55, 0x6c, 0x2a, 0x11, 0x17, - 0xf7, 0x79, 0x8f, 0x61, 0x32, 0x8c, 0x85, 0x4c, 0x85, 0x3f, 0x65, 0x2a, 0x78, 0x84, 0x50, 0xe2, 0x66, 0xdd, 0x23, - 0xed, 0x26, 0xc4, 0x29, 0xd5, 0xa2, 0x94, 0xc9, 0xf8, 0xb7, 0x7e, 0x02, 0xe5, 0x39, 0x45, 0xcb, 0xf4, 0xa3, 0xc2, - 0x65, 0xfa, 0x66, 0x7d, 0x5c, 0x7a, 0x26, 0x42, 0x9d, 0xb9, 0xd8, 0xd4, 0x3a, 0x1d, 0x63, 0xa7, 0x74, 0x6a, 0xc3, - 0xbe, 0x56, 0x8a, 0xcb, 0x8a, 0xc2, 0xbf, 0x91, 0xc8, 0xaa, 0x67, 0xc4, 0xf1, 0x7f, 0x66, 0xed, 0x33, 0xac, 0x02, - 0xbf, 0x0c, 0xe4, 0xfd, 0x02, 0xe0, 0xe3, 0xba, 0x2e, 0xd3, 0xdb, 0x0d, 0xd0, 0x86, 0xd0, 0xf0, 0xf7, 0x7c, 0x64, - 0xc0, 0x74, 0x1f, 0xe1, 0x0c, 0xe9, 0xa1, 0xce, 0x39, 0x9d, 0x95, 0xe9, 0x9c, 0xab, 0xb0, 0x96, 0x60, 0x2f, 0x27, - 0x4d, 0x2e, 0xd7, 0x25, 0xa8, 0x99, 0xc0, 0xed, 0x43, 0x7b, 0x44, 0x08, 0xb5, 0x29, 0xab, 0xe9, 0x25, 0xd4, 0xbc, - 0x93, 0xd3, 0x8e, 0x26, 0x25, 0xb8, 0x6a, 0xe8, 0xac, 0x5c, 0xff, 0x75, 0x38, 0xf4, 0x6e, 0xb3, 0x22, 0xfa, 0xb3, - 0x87, 0xfe, 0x8e, 0xdb, 0x4f, 0xe9, 0x57, 0x88, 0x96, 0xb1, 0xfe, 0x86, 0x0c, 0xe8, 0x78, 0x32, 0xbc, 0x2d, 0xb6, - 0x3d, 0xf6, 0x15, 0x35, 0x58, 0xfa, 0xfa, 0xf1, 0x09, 0x24, 0x54, 0x5d, 0xfb, 0xc2, 0xe2, 0x09, 0xf3, 0x94, 0x68, - 0x5b, 0xf8, 0x10, 0x16, 0xfa, 0x15, 0x22, 0x23, 0x21, 0xdc, 0x54, 0x76, 0x8f, 0x92, 0x76, 0xa1, 0x2f, 0x7d, 0x2d, - 0xfb, 0xca, 0x77, 0x2e, 0x00, 0x56, 0xf6, 0xa9, 0x0d, 0xf7, 0xa4, 0x3f, 0xa5, 0xfa, 0xb0, 0xfd, 0x2d, 0x59, 0x40, - 0xa1, 0x85, 0xf5, 0x54, 0xce, 0xce, 0x65, 0xc9, 0xf3, 0x6c, 0xba, 0x5f, 0xc3, 0x1e, 0x75, 0x87, 0x5e, 0x53, 0xc1, - 0xf9, 0xa5, 0x19, 0xbd, 0xdf, 0x0d, 0x85, 0xea, 0xa8, 0x73, 0x07, 0x59, 0x96, 0xd6, 0x25, 0xe7, 0x2f, 0x2b, 0x77, - 0x14, 0xe6, 0x77, 0x21, 0x78, 0x86, 0x75, 0xef, 0x2e, 0xce, 0x7b, 0xbf, 0xb5, 0xe6, 0xc8, 0x2f, 0xd9, 0x2c, 0x45, - 0x2c, 0x92, 0x39, 0x58, 0xfd, 0xd0, 0xcf, 0x63, 0xbf, 0x0d, 0x72, 0x38, 0x6e, 0x1a, 0xd0, 0x61, 0x43, 0x66, 0xed, - 0x4b, 0x04, 0x4e, 0x35, 0x82, 0x34, 0x35, 0x41, 0xcd, 0xf2, 0x10, 0x89, 0xed, 0x52, 0xb6, 0x0d, 0x72, 0xdd, 0x05, - 0xd3, 0x1c, 0x69, 0xcf, 0xe0, 0x7d, 0x93, 0x26, 0xa9, 0xd0, 0x2c, 0xba, 0x58, 0xc9, 0xf8, 0x77, 0xa4, 0xcd, 0x94, - 0xec, 0xb1, 0x35, 0xf0, 0x5e, 0x82, 0x72, 0x32, 0x4c, 0x31, 0x7c, 0xc7, 0xd7, 0x3b, 0x8f, 0x2e, 0xe2, 0xe7, 0x63, - 0xb6, 0x49, 0xd9, 0x11, 0x4c, 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xfd, 0x6d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, - 0x33, 0x69, 0x73, 0x85, 0x6e, 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, - 0xe2, 0x77, 0x60, 0x0e, 0x63, 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, - 0x02, 0x8c, 0xbe, 0xda, 0x16, 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, - 0xd0, 0xf9, 0x7d, 0x73, 0x5b, 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xed, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, - 0xad, 0x71, 0x9a, 0xf9, 0xdf, 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x5f, 0x20, 0x7a, 0x5f, - 0xb7, 0x72, 0x55, 0x6a, 0x37, 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, - 0x39, 0xff, 0x52, 0xf5, 0xfb, 0xde, 0x17, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, - 0x6d, 0x4a, 0xd8, 0x90, 0xdb, 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x0f, 0x39, 0xdf, - 0xaf, 0x85, 0xbc, 0x59, 0xc9, 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, - 0x57, 0x5a, 0xfa, 0xac, 0xa2, 0xfe, 0x85, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, - 0x5a, 0x82, 0x76, 0xc1, 0xa6, 0xb0, 0xbf, 0x3f, 0x38, 0xe4, 0xfd, 0xfe, 0xc7, 0xdc, 0x6b, 0xf1, 0xba, 0x1b, 0xb8, - 0xcb, 0xd2, 0x43, 0x08, 0x60, 0x2d, 0x03, 0x65, 0x1c, 0x61, 0xd2, 0x45, 0x5e, 0xa3, 0x6c, 0x3a, 0x11, 0xf8, 0x98, - 0x65, 0x57, 0x4e, 0x32, 0x0d, 0x30, 0xa3, 0x9a, 0xc2, 0x4c, 0x80, 0x91, 0xfa, 0x88, 0x75, 0xd3, 0xd3, 0x2a, 0xb4, - 0x7c, 0x0d, 0xc1, 0xba, 0xc8, 0x32, 0x8e, 0x62, 0x26, 0x00, 0xd8, 0x7c, 0x04, 0xf9, 0x8a, 0xae, 0x0e, 0x49, 0x2b, - 0x55, 0xde, 0xaf, 0x33, 0x22, 0xa3, 0x49, 0x88, 0xe6, 0xb7, 0xf0, 0xc0, 0xbe, 0x6d, 0x66, 0x54, 0xa9, 0x67, 0x54, - 0xe5, 0x33, 0x1c, 0x96, 0xc2, 0x31, 0xe2, 0xff, 0x9c, 0xaa, 0x1e, 0x11, 0xe8, 0x55, 0x99, 0x56, 0x51, 0x91, 0xe7, - 0x22, 0x42, 0x84, 0x6a, 0xe9, 0x1c, 0x0e, 0xfd, 0xd8, 0xef, 0xe3, 0x40, 0x98, 0x17, 0xeb, 0xe4, 0x81, 0xae, 0xac, - 0x69, 0xad, 0xa4, 0xc0, 0xa9, 0xa8, 0x11, 0x22, 0x84, 0xf7, 0x1b, 0xf0, 0xac, 0xa6, 0xbe, 0xdf, 0x58, 0x26, 0xba, - 0xdf, 0x33, 0xa0, 0xfc, 0x01, 0xf9, 0xba, 0x92, 0xe2, 0x8c, 0x48, 0x1e, 0x12, 0x67, 0x1c, 0x80, 0x98, 0x6f, 0x4b, - 0x34, 0x1a, 0xfb, 0x1f, 0x90, 0x60, 0xa8, 0x7e, 0xb0, 0xd3, 0x4d, 0xbd, 0x7f, 0x66, 0x12, 0x47, 0xd1, 0xa7, 0x6d, - 0xf2, 0x58, 0xb2, 0x34, 0x5a, 0x38, 0x7a, 0x8f, 0x18, 0xc6, 0xe1, 0x74, 0x3e, 0x26, 0xd9, 0xc6, 0x64, 0x15, 0x40, - 0x3a, 0x99, 0xa9, 0x63, 0x4a, 0x1d, 0x8d, 0x73, 0xbd, 0xa0, 0x0a, 0x3d, 0xd6, 0x25, 0xcf, 0xc1, 0x7a, 0xf2, 0xda, - 0x2b, 0xfd, 0xa9, 0x90, 0x73, 0xd8, 0x48, 0x04, 0x85, 0x1f, 0xe0, 0x6a, 0xb0, 0x52, 0xc0, 0x60, 0xea, 0x5b, 0xf8, - 0x9a, 0x78, 0x8e, 0x82, 0x47, 0x61, 0x17, 0x63, 0x6b, 0xe5, 0x3b, 0x9f, 0x14, 0x94, 0x7b, 0x56, 0xcc, 0x79, 0x05, - 0x9c, 0xcb, 0xa0, 0x10, 0xa6, 0xe3, 0x59, 0xfe, 0xcf, 0x24, 0xaf, 0x27, 0x36, 0x04, 0xc8, 0xe0, 0x4f, 0x89, 0xd3, - 0xd2, 0x1d, 0xba, 0xf3, 0xd0, 0xb3, 0x88, 0xc3, 0x46, 0x8f, 0xd6, 0x65, 0xb1, 0x4d, 0x51, 0x2f, 0x61, 0x7e, 0x20, - 0x3f, 0x6f, 0xc9, 0xf7, 0x21, 0x8a, 0xb7, 0xc1, 0xcf, 0x19, 0x8b, 0x05, 0xfe, 0xf5, 0xb7, 0x8c, 0xd1, 0x44, 0x0b, - 0xfe, 0x9e, 0x35, 0x48, 0x54, 0x0c, 0x58, 0x11, 0xc0, 0x65, 0xaa, 0x3e, 0x7c, 0x4a, 0x8c, 0xb7, 0x66, 0xc3, 0x03, - 0xdf, 0xac, 0x40, 0xa7, 0x3e, 0x77, 0x57, 0xb6, 0xa7, 0xab, 0x91, 0xaa, 0x6a, 0xfc, 0x9c, 0xaa, 0x6a, 0xfc, 0x9c, - 0x52, 0x35, 0xfe, 0xca, 0x28, 0x7e, 0xa7, 0xf2, 0x19, 0x32, 0x27, 0x9b, 0x98, 0xa4, 0xd3, 0xf7, 0x86, 0x13, 0xbb, - 0xec, 0xb7, 0x6e, 0x13, 0x69, 0x66, 0x22, 0x85, 0xdc, 0x1b, 0x80, 0x9a, 0x89, 0x1f, 0x73, 0xc3, 0x29, 0x71, 0x7e, - 0xee, 0xe1, 0x8a, 0x4d, 0xab, 0x6b, 0x5a, 0xb0, 0xc0, 0xe6, 0x65, 0x96, 0x67, 0x9a, 0xc0, 0xb6, 0x29, 0xb3, 0xbe, - 0xc9, 0x3d, 0x80, 0x60, 0x26, 0x35, 0x01, 0x20, 0x2d, 0x44, 0xa5, 0x10, 0xf9, 0x35, 0xce, 0xea, 0x73, 0xde, 0xdb, - 0xe4, 0x31, 0x91, 0x56, 0xf7, 0xfa, 0xfd, 0xf4, 0x2c, 0xcd, 0x29, 0xa8, 0xe1, 0x38, 0xeb, 0xf4, 0xa7, 0x2c, 0x10, - 0x89, 0x5c, 0xa5, 0xff, 0x70, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, 0x0b, - 0x04, 0x77, 0x72, 0xec, 0x27, 0xab, 0x52, 0x1e, 0x19, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, 0xfa, - 0x83, 0xd4, 0xd3, 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, 0x87, - 0xfb, 0xdc, 0x92, 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, 0xfb, - 0x7d, 0xf5, 0xf7, 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, 0xb9, - 0x8d, 0xa3, 0xad, 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, 0x2b, - 0x23, 0x2d, 0x3c, 0x7f, 0x8a, 0xbf, 0x6e, 0xea, 0x02, 0xc3, 0x33, 0x68, 0x8d, 0x56, 0x10, 0x4c, 0xf0, 0x8f, 0x0e, - 0xd4, 0x4b, 0x2b, 0xed, 0x23, 0xe8, 0x56, 0xa0, 0x07, 0x8d, 0x7d, 0x20, 0x69, 0x5f, 0x48, 0xd4, 0xed, 0xad, 0x4e, - 0xa3, 0x3f, 0x2b, 0x96, 0xf3, 0x0a, 0x26, 0x87, 0x1b, 0xfa, 0xb4, 0x0a, 0xb7, 0x9f, 0xe1, 0xe9, 0x1b, 0xa0, 0xdc, - 0x3a, 0x1c, 0x72, 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x29, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x4b, 0xd0, 0xde, - 0x05, 0xe8, 0x80, 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, 0x9e, - 0xe5, 0xb3, 0x4a, 0xe3, 0xb3, 0x27, 0x5e, 0xcd, 0x32, 0x70, 0x16, 0xb8, 0xa8, 0x7c, 0x96, 0x69, 0xd5, 0x53, 0x91, - 0xa0, 0xcf, 0x2b, 0x39, 0xc1, 0x95, 0xe0, 0x64, 0x03, 0xf2, 0x0b, 0x90, 0xa4, 0x29, 0x65, 0x4d, 0xf9, 0xec, 0x92, - 0x6e, 0xc8, 0xe8, 0x39, 0xef, 0x79, 0xd1, 0x30, 0xf4, 0x2f, 0xbc, 0x12, 0xc2, 0x37, 0x71, 0xdb, 0x46, 0x29, 0xec, - 0x6f, 0x02, 0x8b, 0x4f, 0xd8, 0x6b, 0x6f, 0xe1, 0x4f, 0xc7, 0x41, 0x38, 0x44, 0x6e, 0xa8, 0x98, 0x03, 0x7b, 0x1a, - 0xb0, 0xd8, 0xc4, 0x57, 0x9b, 0x49, 0x3c, 0x18, 0xf8, 0x3a, 0x63, 0x31, 0x8b, 0x81, 0x06, 0x39, 0x1e, 0x5c, 0xce, - 0xf5, 0x09, 0xa1, 0x1f, 0x46, 0x54, 0x8e, 0x0a, 0x74, 0x0e, 0xa2, 0xc1, 0x02, 0xf0, 0xd4, 0x5b, 0xd9, 0x20, 0xc9, - 0xd0, 0x40, 0x27, 0xae, 0x35, 0x49, 0x75, 0x38, 0xa1, 0x75, 0xa0, 0xe3, 0xea, 0x0d, 0x74, 0x3e, 0xae, 0x7b, 0x1f, - 0xaf, 0x86, 0x37, 0x54, 0xfa, 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0xf0, 0x66, 0x15, 0x6e, 0xdf, - 0xc8, 0x07, 0x8e, 0x3b, 0x2a, 0x69, 0x08, 0x0c, 0xde, 0x1e, 0xba, 0x9b, 0x19, 0xc7, 0x94, 0xa3, 0xc3, 0x38, 0x92, - 0x43, 0xac, 0x5a, 0x71, 0x21, 0xbd, 0x11, 0x7c, 0xbb, 0x50, 0x8c, 0x65, 0x63, 0x97, 0x86, 0xa2, 0xf0, 0x67, 0x00, - 0x3b, 0xd4, 0xfe, 0x4a, 0x25, 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, - 0x89, 0x3f, 0x32, 0x63, 0x1d, 0x35, 0x5d, 0x5f, 0xb0, 0x1c, 0x59, 0x92, 0x6e, 0x67, 0x12, 0xcb, 0x89, 0x24, 0xb5, - 0xdd, 0x47, 0xc4, 0x60, 0xe0, 0x83, 0x8d, 0x98, 0x66, 0x22, 0x1c, 0xf1, 0xa8, 0x44, 0x16, 0x5d, 0x7e, 0x1b, 0x61, - 0xd2, 0xf6, 0x65, 0x45, 0xb6, 0x20, 0x98, 0x9e, 0x44, 0x1f, 0x24, 0x29, 0xa7, 0x22, 0x91, 0x66, 0x84, 0x00, 0x3f, - 0x9e, 0x94, 0x57, 0xfa, 0x73, 0xd0, 0xb4, 0x12, 0xbc, 0x64, 0x90, 0x3c, 0x12, 0x3f, 0x93, 0x82, 0x59, 0x8c, 0x55, - 0x83, 0x01, 0x96, 0x53, 0x3d, 0x71, 0x4c, 0xd2, 0x7f, 0xeb, 0x74, 0xc2, 0x7e, 0xee, 0xe5, 0xb6, 0x96, 0x37, 0xcd, - 0xbd, 0xe7, 0x5e, 0xc5, 0x52, 0x0d, 0xcb, 0xa0, 0xff, 0x9a, 0x68, 0x17, 0x6c, 0x6d, 0x19, 0x13, 0x56, 0xfd, 0x00, - 0xd2, 0x1e, 0xe9, 0xf2, 0xaa, 0x61, 0xce, 0x04, 0x8f, 0x2e, 0xac, 0x79, 0x10, 0x5d, 0x08, 0x1f, 0xb9, 0xec, 0x26, - 0xc9, 0xd5, 0x78, 0xe2, 0x87, 0x83, 0x81, 0x02, 0xa0, 0xa5, 0x75, 0x52, 0x0c, 0xc2, 0x27, 0x42, 0x0e, 0xa4, 0xd1, - 0x51, 0x15, 0x60, 0xb1, 0xcc, 0xae, 0xca, 0x49, 0x36, 0x18, 0xf8, 0x20, 0x36, 0x26, 0x76, 0x43, 0xb3, 0xb9, 0xcf, - 0x4e, 0x14, 0x64, 0xb5, 0x39, 0x6a, 0xcd, 0x74, 0x0b, 0x0c, 0x00, 0x06, 0x11, 0xc1, 0x72, 0x9f, 0x1a, 0xf9, 0x88, - 0x3a, 0x3d, 0x85, 0x11, 0x10, 0xfc, 0x72, 0x22, 0x10, 0xb9, 0x48, 0xa0, 0x1e, 0x60, 0x26, 0xc0, 0x8c, 0x2a, 0x86, - 0x97, 0xc0, 0x2e, 0x9e, 0x9b, 0x57, 0x0c, 0xfa, 0x17, 0x89, 0xd9, 0x89, 0xa6, 0x12, 0x47, 0x63, 0xe4, 0x54, 0x1a, - 0x23, 0x03, 0x62, 0x17, 0xc7, 0xbf, 0xa7, 0xf4, 0x28, 0x48, 0xd9, 0x8b, 0xca, 0x10, 0x87, 0xa3, 0xf8, 0x0a, 0x56, - 0x8d, 0xc3, 0xa1, 0x36, 0xaf, 0xa7, 0xb3, 0x7a, 0x3e, 0x10, 0x01, 0xfc, 0x37, 0x14, 0xec, 0x57, 0x4d, 0x45, 0x6e, - 0x90, 0x3a, 0x0f, 0x87, 0x14, 0xe4, 0x53, 0xdd, 0xe4, 0x9f, 0x2a, 0x77, 0x3f, 0x9d, 0xcd, 0xad, 0x39, 0x7a, 0x51, - 0xe3, 0xba, 0xb5, 0xba, 0xa1, 0x90, 0x68, 0x4d, 0x93, 0xe2, 0xaa, 0x9a, 0x14, 0x03, 0x9e, 0xfb, 0x42, 0x75, 0xb1, - 0x35, 0x82, 0x85, 0x3f, 0xb7, 0x40, 0x98, 0xf4, 0xb7, 0x92, 0x0e, 0xa9, 0x1a, 0x77, 0x6d, 0xb5, 0xdb, 0x56, 0x36, - 0xa4, 0x68, 0x3e, 0xbc, 0x84, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0x7a, 0x23, 0xf2, 0x98, - 0x7e, 0x85, 0xfc, 0x52, 0x0c, 0xff, 0x53, 0xba, 0x37, 0xa7, 0x36, 0xc8, 0x01, 0x6c, 0xf7, 0x1e, 0x6e, 0xc7, 0xe8, - 0x81, 0x0c, 0xde, 0x08, 0x39, 0xe7, 0xfc, 0x72, 0x6a, 0xcd, 0x98, 0x68, 0x58, 0xb0, 0x72, 0x18, 0xf9, 0x01, 0x32, - 0x5e, 0x4e, 0x81, 0x95, 0xfd, 0xa8, 0x88, 0x4b, 0x7f, 0x18, 0xf9, 0x17, 0x4f, 0x83, 0x8c, 0x7b, 0xd1, 0xb0, 0xe3, - 0x0b, 0xb0, 0x57, 0x5f, 0x3c, 0x65, 0xd1, 0x80, 0x57, 0x57, 0xf5, 0x34, 0x0b, 0x86, 0x19, 0x8b, 0xae, 0x8a, 0x21, - 0xf8, 0xd0, 0x3e, 0x2b, 0x07, 0xa1, 0xef, 0x9b, 0x9d, 0x43, 0x77, 0x43, 0x2c, 0x8f, 0xb0, 0x9f, 0xc0, 0x6d, 0x57, - 0x4b, 0xcc, 0x60, 0xb2, 0x59, 0x46, 0xcc, 0x60, 0xcb, 0x5f, 0x3c, 0x35, 0x5c, 0x42, 0xd5, 0x33, 0xa9, 0xd9, 0x28, - 0xd0, 0x9c, 0x5c, 0xa1, 0x39, 0x59, 0x09, 0xb5, 0xe4, 0x93, 0x0a, 0x27, 0xec, 0x7c, 0x92, 0x2b, 0xbb, 0xd1, 0x18, - 0x03, 0x17, 0xad, 0xb9, 0x1d, 0x0a, 0x23, 0x33, 0x9d, 0xa5, 0x68, 0xc0, 0xc2, 0x33, 0x71, 0x4a, 0x63, 0x40, 0xfb, - 0x72, 0x60, 0x69, 0x43, 0x7e, 0x91, 0x33, 0x03, 0x6d, 0x43, 0x4a, 0xa3, 0x66, 0xe0, 0xcf, 0xd4, 0x84, 0xf9, 0x0d, - 0xac, 0x44, 0x10, 0xd5, 0x05, 0x98, 0x24, 0x39, 0x19, 0x8d, 0x94, 0x95, 0x48, 0xce, 0x01, 0xef, 0x23, 0x78, 0xb2, - 0x88, 0x6d, 0xed, 0x4f, 0xe9, 0x7f, 0x75, 0xf8, 0x5c, 0xfa, 0x4f, 0x04, 0xb0, 0x90, 0x4b, 0x83, 0xc8, 0x40, 0xe1, - 0x90, 0x5a, 0x86, 0xf7, 0xc4, 0xf1, 0x0c, 0x7c, 0x05, 0x17, 0x68, 0x0a, 0xe8, 0x0f, 0x6a, 0x46, 0x11, 0x59, 0xf8, - 0xab, 0x67, 0x37, 0x75, 0xa1, 0xe7, 0x99, 0xf3, 0x1a, 0x34, 0x33, 0x10, 0xd2, 0xe3, 0x54, 0xbd, 0x0d, 0x89, 0xce, - 0xcb, 0x6b, 0xfd, 0x32, 0x21, 0x92, 0x95, 0x91, 0xa7, 0xef, 0x73, 0x30, 0x8f, 0x28, 0x42, 0x07, 0x57, 0xe6, 0xe1, - 0x70, 0x2e, 0x28, 0x7c, 0x47, 0x79, 0x3e, 0xe0, 0x34, 0xcb, 0x12, 0xd0, 0x06, 0xb2, 0xdc, 0x94, 0xb9, 0x4c, 0x5a, - 0xa6, 0xee, 0x3d, 0x58, 0x09, 0x2a, 0x74, 0x73, 0x0a, 0x0a, 0x65, 0x24, 0x28, 0xa5, 0xd5, 0x20, 0x94, 0xea, 0xb0, - 0x08, 0x22, 0x87, 0x2c, 0x04, 0xdc, 0x4c, 0x45, 0xa3, 0x25, 0x0d, 0x8f, 0x70, 0x6e, 0xa0, 0x10, 0x80, 0xc4, 0x9e, - 0x2a, 0xca, 0xb8, 0x1c, 0x02, 0x3e, 0x4a, 0x38, 0xc4, 0x59, 0x93, 0xb6, 0x3c, 0x07, 0x71, 0x2c, 0x17, 0x7c, 0x59, - 0x21, 0x18, 0x44, 0xe8, 0x33, 0xe4, 0x4f, 0x96, 0xf3, 0xef, 0xd6, 0x61, 0xda, 0x11, 0x3e, 0xec, 0x6a, 0x37, 0x5c, - 0xcc, 0x6e, 0xe7, 0x13, 0x88, 0x6f, 0xb9, 0x9d, 0x1f, 0x63, 0x88, 0xdc, 0xf8, 0x83, 0xe5, 0x50, 0x72, 0x45, 0xa1, - 0xcb, 0x7a, 0x44, 0x8a, 0xec, 0xe9, 0x9a, 0x23, 0x08, 0x0e, 0xb4, 0x6a, 0x90, 0xa1, 0x91, 0xf8, 0xe2, 0x29, 0x64, - 0x0d, 0xd6, 0xfc, 0x45, 0x45, 0xce, 0xea, 0xfe, 0x64, 0x03, 0xd5, 0x24, 0x93, 0xb5, 0xa2, 0x72, 0xfe, 0x76, 0x55, - 0x16, 0x27, 0xab, 0x32, 0x5c, 0x0d, 0xba, 0xaa, 0xb2, 0xe0, 0x48, 0x6d, 0x80, 0xd6, 0x74, 0x85, 0x18, 0x0a, 0x59, - 0x83, 0x85, 0x55, 0x95, 0x35, 0xf5, 0x09, 0x04, 0xfa, 0x00, 0xcb, 0xa8, 0xd9, 0x4f, 0x87, 0xbf, 0x04, 0xbf, 0xa8, - 0x90, 0xa5, 0x3a, 0xad, 0x33, 0xf1, 0x5b, 0xb0, 0x60, 0xf8, 0xc7, 0xef, 0xc1, 0x1a, 0xb0, 0x04, 0xc8, 0x72, 0xb7, - 0xb1, 0xd1, 0x7a, 0xe5, 0x15, 0xe2, 0x5d, 0xad, 0x2f, 0xfa, 0xad, 0xdb, 0x44, 0xad, 0x00, 0x23, 0x14, 0x5a, 0x04, - 0xd8, 0xea, 0x81, 0x7b, 0x0a, 0x7e, 0x20, 0x86, 0x73, 0x4d, 0x5a, 0x53, 0x27, 0xbc, 0xce, 0xc6, 0x91, 0x88, 0xea, - 0x2d, 0x5c, 0xdc, 0xeb, 0xad, 0xc5, 0xdf, 0xa8, 0x40, 0x00, 0x64, 0x31, 0xc5, 0xda, 0x79, 0x43, 0x7a, 0x65, 0xd8, - 0x49, 0xe8, 0xbd, 0x61, 0x27, 0x90, 0x17, 0x87, 0x9d, 0x42, 0x97, 0x68, 0x3b, 0x45, 0x6a, 0xa2, 0xed, 0xa4, 0x9b, - 0x55, 0x58, 0x42, 0xf0, 0xab, 0xf6, 0xd6, 0x51, 0xb6, 0x2f, 0xb2, 0x84, 0x69, 0x0b, 0x18, 0xe5, 0x56, 0x7d, 0xe6, - 0x14, 0xb1, 0x52, 0xf6, 0x4e, 0x27, 0x55, 0xee, 0x22, 0x9f, 0x5b, 0x4d, 0x91, 0xc9, 0x2f, 0x8e, 0x5b, 0x24, 0x9f, - 0xbc, 0x69, 0x37, 0x4c, 0xa6, 0x7f, 0x3c, 0xfa, 0x02, 0xba, 0x22, 0x3b, 0x7d, 0x02, 0x01, 0x99, 0x0a, 0xaa, 0xd5, - 0xad, 0x62, 0x9a, 0xb7, 0xab, 0xec, 0xf6, 0x42, 0x89, 0xe1, 0x74, 0x76, 0x12, 0x1e, 0x6d, 0x86, 0x0c, 0x1c, 0x82, - 0x40, 0x21, 0x54, 0x14, 0xc3, 0x23, 0x50, 0x6b, 0x24, 0x1f, 0xe0, 0x47, 0xbb, 0x53, 0x41, 0xa4, 0x76, 0x53, 0x71, - 0xe3, 0xe4, 0xa6, 0xeb, 0xa5, 0x40, 0xad, 0x53, 0xb2, 0x02, 0x28, 0x21, 0xea, 0xcf, 0x62, 0x5b, 0x5f, 0xc3, 0x15, - 0x9b, 0xef, 0x1b, 0x45, 0x4f, 0xae, 0x4f, 0x51, 0xb7, 0xe2, 0xea, 0x34, 0x6d, 0x35, 0xc7, 0x8e, 0x33, 0xe4, 0xe0, - 0x59, 0x41, 0xb0, 0x1d, 0x95, 0x28, 0xdf, 0xb6, 0x9b, 0x8e, 0x89, 0xad, 0xfe, 0xb9, 0xa9, 0x36, 0x4b, 0xa8, 0x88, - 0x88, 0x8f, 0xb2, 0x9b, 0x27, 0xed, 0x77, 0xb0, 0xc7, 0x5a, 0x0d, 0x22, 0xfb, 0x0c, 0xae, 0x72, 0x9d, 0x16, 0xb9, - 0x2d, 0x83, 0xf3, 0x0f, 0xaf, 0x76, 0x15, 0x36, 0x39, 0xd6, 0xd5, 0xd5, 0x4c, 0x75, 0x52, 0xb1, 0x81, 0xb1, 0xa6, - 0xb5, 0x54, 0xf3, 0x18, 0x92, 0xee, 0xca, 0xe2, 0xac, 0x4a, 0xba, 0xe9, 0xb9, 0x71, 0xa6, 0x10, 0x03, 0x67, 0xab, - 0xd1, 0x72, 0x86, 0x21, 0xba, 0x3e, 0xcc, 0x12, 0xbf, 0xd5, 0x53, 0xee, 0xf3, 0x70, 0xeb, 0x77, 0xf5, 0x82, 0x93, - 0xc9, 0x7e, 0x72, 0x9c, 0xbb, 0x5d, 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0x62, 0x29, 0xea, 0x5f, 0x2a, - 0x00, 0x1a, 0xdc, 0xe4, 0xb1, 0x44, 0xa9, 0xdf, 0xab, 0xea, 0x07, 0x35, 0x53, 0x35, 0x0d, 0x04, 0x73, 0x2a, 0x05, - 0xfc, 0xe1, 0x76, 0xe1, 0x8a, 0x47, 0xdc, 0xb0, 0x30, 0xfe, 0xe5, 0xd5, 0xec, 0x54, 0x50, 0x19, 0xb8, 0x19, 0xff, - 0xe5, 0x09, 0x76, 0x0a, 0x6b, 0x05, 0x64, 0x85, 0xbf, 0xbc, 0xfc, 0x81, 0xf7, 0x2b, 0xfe, 0x97, 0x57, 0x3d, 0xf0, - 0x3e, 0xe2, 0xbc, 0xfc, 0x85, 0xa4, 0x4e, 0x88, 0xea, 0xf2, 0x17, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x25, 0x29, 0x7c, - 0x82, 0x2f, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, - 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, - 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, 0xb7, 0x61, 0x1d, 0x25, 0x69, 0xbe, 0x94, 0xd1, 0x47, 0x32, - 0xec, 0x48, 0x5f, 0x49, 0x89, 0xf6, 0x5a, 0x85, 0xe5, 0x68, 0xf6, 0xeb, 0x92, 0x03, 0xe5, 0x75, 0x2b, 0x28, 0x5f, - 0x35, 0x01, 0xf4, 0x4a, 0xb5, 0xcf, 0x40, 0x2b, 0x28, 0x2c, 0x95, 0x07, 0x2b, 0x71, 0x2e, 0xfa, 0xac, 0x38, 0x1c, - 0xd4, 0xc5, 0x90, 0x50, 0xa0, 0x4a, 0x9c, 0x84, 0x46, 0x3c, 0x87, 0x0b, 0xa1, 0x78, 0x96, 0x63, 0x6c, 0x45, 0x0e, - 0x1c, 0xc8, 0xf0, 0x03, 0x02, 0xef, 0x65, 0xff, 0x0a, 0x06, 0xc3, 0x04, 0x37, 0x32, 0xea, 0xe4, 0x9c, 0xfd, 0x85, - 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, - 0x9d, 0xf4, 0xcf, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, - 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, - 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, - 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, - 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, - 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, 0x28, 0x07, 0xfb, 0x97, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, - 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, 0x71, 0x50, 0xb1, 0x65, 0x19, 0x46, 0xc0, 0xa0, 0x8e, 0xfd, - 0x8f, 0x3e, 0x9b, 0x36, 0x64, 0x1f, 0x00, 0x2a, 0x57, 0x21, 0x60, 0x0f, 0xc0, 0x89, 0x46, 0xb8, 0x01, 0x6e, 0x35, - 0x5a, 0xd2, 0x41, 0xdd, 0x16, 0x0c, 0x44, 0x4b, 0xd8, 0xc8, 0xdb, 0xae, 0x4e, 0xdf, 0x10, 0x3e, 0xd4, 0x4e, 0x4a, - 0x87, 0xf2, 0x37, 0xcf, 0xd9, 0x7f, 0xef, 0xb0, 0xa6, 0xa6, 0x7c, 0x02, 0xcc, 0x9c, 0x95, 0xc8, 0x2b, 0x84, 0x4e, - 0x91, 0xdf, 0xab, 0xba, 0x12, 0xc3, 0x45, 0x2d, 0xca, 0xce, 0xec, 0xd6, 0x89, 0xde, 0x39, 0x05, 0xb5, 0x54, 0x36, - 0xc8, 0x49, 0xaa, 0xcd, 0x47, 0xd6, 0x0a, 0x4a, 0xd4, 0x35, 0x0a, 0x1c, 0x9f, 0x72, 0xed, 0xfe, 0xdf, 0x39, 0x13, - 0xd4, 0x6c, 0xa3, 0xba, 0xbf, 0xd4, 0x4f, 0x55, 0x4d, 0x62, 0x01, 0x2e, 0x27, 0x69, 0xde, 0xf1, 0x08, 0xab, 0x7f, - 0x9c, 0x2c, 0x45, 0xa0, 0x97, 0x11, 0xed, 0x4a, 0x40, 0x82, 0x76, 0x72, 0x16, 0x2a, 0x02, 0x05, 0xfa, 0xfa, 0x8b, - 0x4d, 0x9a, 0xc5, 0x72, 0x35, 0xdb, 0xc3, 0x44, 0x59, 0xac, 0x87, 0x08, 0x72, 0x66, 0xea, 0x60, 0xbf, 0xa7, 0x19, - 0xcd, 0xc2, 0x2b, 0x53, 0x82, 0x4b, 0x71, 0x15, 0x15, 0x39, 0xf8, 0x1c, 0xe2, 0x0b, 0x9f, 0x0b, 0xb9, 0x41, 0x44, - 0xd3, 0x9f, 0x24, 0xaa, 0x1d, 0x29, 0x90, 0x43, 0xc9, 0x4f, 0x88, 0xbf, 0x64, 0x6d, 0x8c, 0xfb, 0xa5, 0x53, 0xed, - 0x6b, 0x85, 0xe0, 0xfe, 0xc6, 0x16, 0x1b, 0x55, 0x9e, 0xe8, 0xc1, 0xa7, 0x58, 0xff, 0x93, 0x05, 0x94, 0xea, 0xbe, - 0x0d, 0x4e, 0xc5, 0xa3, 0x70, 0x53, 0x17, 0x9f, 0x10, 0x5a, 0xa0, 0x1c, 0x55, 0xc5, 0xa6, 0x8c, 0x88, 0x13, 0x76, - 0x53, 0x17, 0x3d, 0xcd, 0x81, 0x2e, 0xe7, 0x75, 0x22, 0x4f, 0x84, 0x76, 0x0b, 0xba, 0xa7, 0x39, 0x56, 0xe2, 0xb9, - 0x2c, 0x1d, 0x64, 0x9d, 0x48, 0x13, 0x2a, 0x77, 0x75, 0xd5, 0x51, 0xa9, 0xd4, 0x0d, 0xaf, 0x52, 0xcd, 0xf8, 0xbb, - 0x30, 0x7f, 0x62, 0xd9, 0xaf, 0x5a, 0xbf, 0xd5, 0x6a, 0x6f, 0xac, 0x1e, 0x95, 0xac, 0x39, 0xce, 0x26, 0x24, 0xa5, - 0x4f, 0xd8, 0x6e, 0x26, 0x5d, 0xeb, 0xc0, 0x93, 0xe0, 0x72, 0xe8, 0x09, 0xa8, 0x18, 0x34, 0xf1, 0x76, 0x17, 0xa8, - 0x47, 0xe0, 0x19, 0x28, 0x9f, 0xa8, 0x75, 0xc0, 0xcf, 0x6b, 0x2d, 0x4f, 0x19, 0x61, 0x58, 0xed, 0x2c, 0x5a, 0x0e, - 0xce, 0x3b, 0x45, 0xe0, 0xda, 0x95, 0xc0, 0xf3, 0xa1, 0x7a, 0x2f, 0x04, 0x0c, 0xf7, 0xcf, 0x85, 0xca, 0x66, 0x37, - 0xc3, 0x79, 0xd4, 0x38, 0x3d, 0xd0, 0xde, 0x76, 0xad, 0x87, 0x7a, 0xd7, 0xed, 0xdc, 0x56, 0xba, 0xf7, 0x6b, 0x27, - 0x93, 0x2e, 0xa0, 0xb5, 0xf9, 0xec, 0x3b, 0xbb, 0xd2, 0xba, 0xe9, 0x39, 0x7b, 0xb0, 0x75, 0x4b, 0x74, 0x2e, 0x88, - 0x26, 0xbf, 0x1f, 0x78, 0xd6, 0xb6, 0xa3, 0xdf, 0xa6, 0x1d, 0xdb, 0xdc, 0x43, 0xdd, 0x2b, 0xa8, 0xf5, 0x86, 0xe6, - 0xfd, 0x33, 0xd7, 0xb6, 0xe3, 0xab, 0x5f, 0xd7, 0x1d, 0xae, 0xf3, 0x26, 0x38, 0x6e, 0xba, 0xb6, 0xd5, 0xce, 0x7e, - 0xee, 0xee, 0xad, 0x9b, 0x28, 0xcc, 0xb2, 0x9f, 0x8a, 0xe2, 0xcf, 0x4a, 0xdf, 0x11, 0xe8, 0xe8, 0xce, 0x8b, 0x3a, - 0x5d, 0xec, 0x3e, 0x10, 0xc6, 0x93, 0x57, 0x1f, 0x11, 0xdd, 0xfa, 0x3e, 0x73, 0xbf, 0x02, 0xdc, 0x08, 0xee, 0x20, - 0xda, 0xbb, 0xa5, 0x3e, 0xa9, 0xd5, 0xd7, 0x7a, 0xed, 0x3c, 0x3d, 0xbf, 0xe9, 0xdc, 0x7e, 0xf7, 0xcd, 0xd1, 0xd6, - 0x7b, 0x5c, 0x58, 0x2b, 0x4b, 0x4f, 0x55, 0xc1, 0xde, 0x2c, 0x4f, 0x55, 0xc1, 0xe4, 0x81, 0xd7, 0xec, 0x17, 0x34, - 0xb8, 0xd2, 0xd1, 0xc6, 0x7b, 0xa2, 0x06, 0x6e, 0x51, 0x58, 0x3a, 0xfc, 0x92, 0x9b, 0xc9, 0x35, 0xee, 0x2f, 0x15, - 0xb9, 0xd8, 0x77, 0xce, 0xe8, 0xce, 0xcc, 0xba, 0x57, 0x15, 0xae, 0x16, 0xe4, 0xea, 0xc0, 0xd6, 0xb2, 0x8b, 0xc3, - 0x0d, 0x8b, 0x28, 0x40, 0x20, 0xa6, 0x57, 0x6a, 0xed, 0x8f, 0x68, 0x10, 0xf2, 0xc1, 0xc0, 0x2f, 0x30, 0x58, 0x15, - 0x28, 0x7c, 0xa0, 0x48, 0xfe, 0xd2, 0x13, 0xb0, 0x8b, 0x67, 0x80, 0x6e, 0xc5, 0x66, 0xc5, 0x08, 0x11, 0x32, 0x59, - 0xce, 0x6a, 0x3a, 0x83, 0x7c, 0xea, 0x8b, 0xef, 0x6c, 0xd5, 0xe9, 0xbc, 0xad, 0xa9, 0x72, 0xea, 0x50, 0xe8, 0xee, - 0xa6, 0xee, 0xdc, 0xba, 0xc8, 0x53, 0x87, 0x90, 0x2b, 0x15, 0x2b, 0x31, 0x0d, 0x35, 0x4f, 0xd2, 0x8c, 0xfa, 0xab, - 0xbd, 0xdf, 0x6b, 0x14, 0x4e, 0xf9, 0xd3, 0x31, 0xa8, 0xc2, 0x55, 0x0d, 0x71, 0x2c, 0x55, 0xf1, 0xc8, 0x06, 0x81, - 0xe6, 0xd5, 0xad, 0x4a, 0x9a, 0x90, 0xc9, 0x8d, 0xf0, 0xa9, 0x49, 0x29, 0x4f, 0xd3, 0x26, 0xad, 0x14, 0xa9, 0x83, - 0x0f, 0xea, 0x54, 0xe3, 0xb9, 0x59, 0x3d, 0x03, 0x30, 0xe3, 0xfc, 0x8a, 0x5f, 0x2a, 0x2e, 0xa3, 0xb6, 0x32, 0x93, - 0xf6, 0x27, 0x47, 0x63, 0xa3, 0x2e, 0xa7, 0x8d, 0x32, 0xc2, 0x4a, 0x69, 0x4e, 0x8a, 0xe5, 0x78, 0xfe, 0x01, 0x83, - 0x35, 0x4f, 0x60, 0x07, 0x13, 0x95, 0xf2, 0x3e, 0x02, 0xe2, 0xeb, 0x24, 0x5d, 0x26, 0x90, 0x22, 0xfd, 0x4b, 0x17, - 0x3c, 0x75, 0x18, 0x1b, 0x88, 0x31, 0x2b, 0x66, 0x46, 0xff, 0x83, 0xbb, 0xa4, 0x3f, 0x09, 0x01, 0x70, 0x13, 0x4d, - 0xa1, 0x53, 0xe7, 0xc9, 0x45, 0x1e, 0x2c, 0x2e, 0x3c, 0xb4, 0x62, 0xc4, 0x83, 0xff, 0x7c, 0x16, 0x22, 0x88, 0x39, - 0xa6, 0x78, 0xfa, 0x85, 0xd1, 0x7f, 0x04, 0x97, 0x18, 0x41, 0xe8, 0xee, 0x9d, 0xc3, 0x10, 0x6e, 0xf6, 0x20, 0x83, - 0xfa, 0x43, 0x1d, 0x12, 0x35, 0xfc, 0xa5, 0xf2, 0xa0, 0xff, 0xeb, 0x4c, 0x58, 0x6a, 0x3f, 0x3d, 0x1d, 0x40, 0x05, - 0xef, 0x2b, 0xde, 0x46, 0xc4, 0xf7, 0x89, 0x9f, 0xc4, 0x83, 0xcd, 0x93, 0x0d, 0x58, 0xeb, 0x3e, 0xe4, 0xc6, 0xba, - 0x4a, 0xd8, 0x40, 0xc0, 0xd7, 0x98, 0xd6, 0x9e, 0xd7, 0x6e, 0xf7, 0xe0, 0x3f, 0xfd, 0x8b, 0x90, 0x01, 0x13, 0xa7, - 0xef, 0x33, 0x27, 0x6b, 0x74, 0x91, 0xc9, 0xf4, 0xa1, 0x93, 0xbe, 0xd1, 0xe9, 0xbe, 0x13, 0xfe, 0x51, 0x31, 0x8b, - 0x0f, 0xb7, 0xf4, 0x95, 0x26, 0xc5, 0x1d, 0xb0, 0xb2, 0x79, 0x50, 0x10, 0xea, 0x5c, 0x44, 0xdf, 0x98, 0xf2, 0x2d, - 0xa1, 0x66, 0xdf, 0x58, 0x52, 0x4a, 0xf7, 0x1a, 0x7a, 0x95, 0xd6, 0xfa, 0x6d, 0x94, 0x60, 0x4c, 0x74, 0x3c, 0x79, - 0x19, 0x8f, 0x95, 0xf7, 0xf1, 0xb8, 0x91, 0x0a, 0x79, 0x00, 0x22, 0x50, 0x31, 0xfe, 0x74, 0xe5, 0xc9, 0x49, 0x2f, - 0x8c, 0x57, 0xa1, 0x14, 0x14, 0x06, 0x74, 0x05, 0x52, 0xc0, 0xa3, 0xf6, 0x44, 0x67, 0x61, 0x97, 0x70, 0x8f, 0x6e, - 0x02, 0xc6, 0xfa, 0xfc, 0x0b, 0xa0, 0xb9, 0x0b, 0x77, 0x78, 0x31, 0x40, 0x6d, 0xea, 0xd5, 0xdd, 0xc7, 0xb5, 0x3a, - 0x87, 0x43, 0x70, 0xb0, 0x1a, 0x44, 0x70, 0x3a, 0x9f, 0x3a, 0x9a, 0x65, 0x01, 0x2a, 0x27, 0xcb, 0x8d, 0xbc, 0x79, - 0xb4, 0xe8, 0xd5, 0x7d, 0x6f, 0x91, 0x96, 0x55, 0x1d, 0x64, 0x2c, 0x0b, 0x2b, 0xc0, 0xd5, 0xa1, 0xf5, 0x83, 0x70, - 0x59, 0x38, 0x7f, 0x20, 0x04, 0xb1, 0x7b, 0xb5, 0x2d, 0x78, 0xae, 0xe6, 0xf0, 0x93, 0xa7, 0x6c, 0xcd, 0x25, 0xea, - 0xa4, 0x33, 0x11, 0x80, 0xd8, 0x53, 0xb3, 0x8a, 0xae, 0x81, 0xa4, 0x4e, 0xb3, 0x8a, 0xae, 0xa9, 0xd9, 0xc6, 0x38, - 0x90, 0x8f, 0x56, 0x29, 0x60, 0xdf, 0x4d, 0xc7, 0xc1, 0xea, 0x49, 0x2c, 0xaf, 0x43, 0xcb, 0x27, 0x1b, 0xe5, 0x33, - 0xa8, 0x5b, 0x6d, 0x8c, 0x89, 0xed, 0xe6, 0xcb, 0xb9, 0x7e, 0x3b, 0x58, 0xf8, 0x76, 0xd0, 0x9c, 0x53, 0xf6, 0x52, - 0x97, 0xbd, 0xb2, 0xcb, 0xa6, 0x9e, 0x3b, 0x2a, 0x5a, 0x8d, 0x01, 0xbd, 0x81, 0x05, 0xeb, 0x73, 0x91, 0x66, 0xab, - 0x52, 0x95, 0x80, 0x17, 0xc6, 0x8a, 0x2d, 0xfd, 0x46, 0x66, 0x48, 0xc2, 0x3c, 0xce, 0xc4, 0x5b, 0xba, 0xd7, 0xc2, - 0xe4, 0x38, 0x16, 0xc9, 0x94, 0xd0, 0x29, 0xdd, 0xd9, 0x86, 0xce, 0x55, 0x18, 0x45, 0xb4, 0x56, 0x52, 0x69, 0x24, - 0x30, 0x35, 0x03, 0x94, 0xcc, 0x15, 0x38, 0xa5, 0xcb, 0xfd, 0xef, 0x48, 0x8c, 0x33, 0x5f, 0x94, 0xcc, 0x80, 0x6e, - 0xf9, 0x75, 0xb1, 0x6e, 0xa5, 0xc8, 0x08, 0xf3, 0xe6, 0xb8, 0xbd, 0xae, 0x0f, 0x81, 0x5c, 0x2d, 0x7b, 0x14, 0x8d, - 0x83, 0x42, 0x87, 0x4b, 0x95, 0x00, 0xfb, 0x22, 0xf1, 0x33, 0xc2, 0x96, 0xf6, 0x40, 0x6e, 0x8f, 0xce, 0x84, 0x39, - 0xe7, 0xa4, 0x2c, 0x3b, 0x97, 0x66, 0x70, 0x39, 0x71, 0x25, 0xb8, 0x48, 0x6f, 0xdb, 0xd3, 0xa4, 0xa5, 0xed, 0x63, - 0xc3, 0x39, 0x1a, 0xda, 0x06, 0xdd, 0xb1, 0x3f, 0x34, 0x17, 0x8b, 0xd8, 0xba, 0x58, 0x0c, 0x3b, 0xb3, 0x1f, 0x2d, - 0x16, 0x20, 0x07, 0x80, 0xa3, 0x6e, 0xc3, 0xc7, 0x6c, 0x01, 0x9c, 0x56, 0xd3, 0x6c, 0xea, 0x6d, 0x78, 0xf5, 0x44, - 0xf5, 0xf4, 0x82, 0xe7, 0x4f, 0x84, 0x19, 0x8b, 0x0d, 0xcf, 0x9f, 0x58, 0x47, 0x4e, 0xf5, 0x44, 0x28, 0xd1, 0xba, - 0x80, 0x66, 0xe0, 0x35, 0x05, 0x8c, 0x58, 0x32, 0x99, 0x52, 0x45, 0x1e, 0xf7, 0xa6, 0x1b, 0x35, 0x78, 0x41, 0xe1, - 0x10, 0x48, 0xe9, 0xf4, 0x8b, 0xa7, 0x4c, 0xbf, 0x77, 0xf1, 0xb4, 0x43, 0xd6, 0x36, 0x4c, 0x97, 0x9b, 0x61, 0x32, - 0x28, 0xfd, 0x27, 0x66, 0x62, 0x5c, 0x58, 0x93, 0x04, 0x10, 0xff, 0xc6, 0x7e, 0x87, 0x14, 0x6e, 0xde, 0x5f, 0x0c, - 0xe3, 0x07, 0xde, 0x8f, 0x91, 0x3d, 0x49, 0x33, 0xc4, 0x9a, 0x49, 0x85, 0xdc, 0x7d, 0xb5, 0xfe, 0x31, 0xb1, 0x9b, - 0xec, 0x81, 0x05, 0x20, 0xb6, 0xa6, 0xad, 0x6e, 0x79, 0xbf, 0xef, 0x99, 0x22, 0xc0, 0x0f, 0xca, 0x3f, 0xba, 0x33, - 0x24, 0x83, 0xb2, 0xeb, 0x86, 0x10, 0x0f, 0xca, 0xa6, 0x69, 0xaf, 0xb7, 0xbd, 0x33, 0x8f, 0xd5, 0x75, 0xda, 0x59, - 0x5c, 0x2d, 0x32, 0x48, 0xab, 0x0f, 0xd9, 0x71, 0x66, 0x9f, 0x1d, 0x2d, 0x95, 0xee, 0xf7, 0x21, 0x22, 0xee, 0x28, - 0x6b, 0xfb, 0xed, 0x16, 0x5c, 0xc3, 0xd1, 0x20, 0x74, 0x65, 0x6f, 0x97, 0xd1, 0xc6, 0x85, 0x38, 0xee, 0x99, 0xce, - 0x17, 0x7c, 0x79, 0x94, 0x76, 0x1e, 0x9c, 0xea, 0x89, 0x3e, 0x37, 0xdd, 0x55, 0x26, 0xd7, 0x3a, 0xac, 0xc6, 0xa0, - 0x36, 0x0b, 0x5b, 0xb8, 0x0b, 0xdb, 0xe8, 0xa0, 0xb5, 0x2f, 0x0b, 0xfe, 0x29, 0x03, 0xf0, 0xa5, 0x67, 0xcb, 0xb6, - 0xd7, 0xa4, 0xd5, 0x2b, 0x19, 0x85, 0xd8, 0xd2, 0xf6, 0xea, 0xd3, 0x51, 0x3e, 0x6e, 0x4e, 0x28, 0x2e, 0xe4, 0x28, - 0x3f, 0x78, 0x0d, 0x51, 0xd7, 0xba, 0x8e, 0x8b, 0x45, 0x87, 0x1b, 0x57, 0xdd, 0x76, 0xe3, 0x7a, 0x8d, 0x78, 0x6b, - 0xb4, 0x49, 0xa1, 0x56, 0xc6, 0x8e, 0xe0, 0x65, 0xf9, 0x70, 0xc8, 0xc4, 0x70, 0x28, 0x21, 0x53, 0x1f, 0xba, 0x37, - 0x34, 0xed, 0xf3, 0xd3, 0xd6, 0x8f, 0x58, 0x6a, 0x1c, 0xc5, 0x86, 0x77, 0xfa, 0xce, 0x63, 0x6b, 0x5c, 0xc9, 0x97, - 0xc1, 0x6c, 0x57, 0x50, 0x6d, 0x8d, 0x37, 0xec, 0xe5, 0xfc, 0xa7, 0x4a, 0x2a, 0xf9, 0xdb, 0x9f, 0xe1, 0x1a, 0xde, - 0xda, 0xd2, 0x41, 0x53, 0xcd, 0x72, 0x96, 0xeb, 0x7b, 0xc1, 0xf1, 0xc7, 0xdd, 0x2b, 0x82, 0xc1, 0xef, 0xe9, 0x28, - 0xc8, 0xc5, 0x52, 0xad, 0x01, 0x05, 0xe9, 0xc8, 0x8e, 0xa9, 0x2c, 0x30, 0x0c, 0xe0, 0x0d, 0x19, 0x20, 0x8f, 0x29, - 0xdc, 0x0d, 0x15, 0x5e, 0xf8, 0x6b, 0x45, 0x76, 0x09, 0x6c, 0x6b, 0xc6, 0xc7, 0x0c, 0x77, 0x10, 0xf2, 0x8f, 0x60, - 0x4b, 0xb6, 0x62, 0xb7, 0xec, 0x86, 0x21, 0xd9, 0x38, 0x0e, 0x63, 0xcc, 0xc7, 0x93, 0xf8, 0x4a, 0x4c, 0xe2, 0x01, - 0x8f, 0xd0, 0x31, 0x62, 0xcd, 0xeb, 0x59, 0x2c, 0x07, 0x90, 0x2d, 0xb9, 0xd2, 0x01, 0x21, 0x34, 0x36, 0xb4, 0xe4, - 0x55, 0x61, 0x70, 0xb1, 0x63, 0x9f, 0x91, 0x48, 0xc6, 0x21, 0x58, 0xb4, 0xaa, 0x81, 0x85, 0x89, 0xdd, 0xf2, 0x62, - 0xb6, 0x9a, 0xe3, 0x3f, 0x87, 0x03, 0x02, 0x60, 0x07, 0xfb, 0x86, 0x2d, 0x23, 0x44, 0x7a, 0xbb, 0xe1, 0x4b, 0xcb, - 0xd3, 0x85, 0xdd, 0xf1, 0x6b, 0x3e, 0x66, 0xe7, 0xaf, 0x3d, 0x88, 0x9c, 0x3d, 0xff, 0x08, 0x68, 0x88, 0x77, 0xfc, - 0x36, 0xf5, 0x2a, 0x76, 0x4b, 0x14, 0x84, 0xb7, 0xe0, 0x0c, 0x74, 0x07, 0x11, 0xb0, 0xd7, 0xfc, 0x06, 0x63, 0xc5, - 0xce, 0xd2, 0x85, 0x87, 0x19, 0xa1, 0xf6, 0x74, 0xbe, 0xac, 0xd5, 0x24, 0xdc, 0x5c, 0x2d, 0x26, 0x83, 0xc1, 0xc6, - 0xdf, 0xf1, 0x35, 0xf0, 0xc1, 0x9c, 0xbf, 0xf6, 0x76, 0x54, 0x2e, 0xfc, 0xe7, 0x75, 0x96, 0xbc, 0xf3, 0xd9, 0xf5, - 0x80, 0xdf, 0x00, 0xde, 0x12, 0x3a, 0x70, 0xdd, 0xf9, 0x4c, 0xe2, 0xb5, 0x5d, 0xeb, 0x6b, 0x04, 0x12, 0xf9, 0x02, - 0x30, 0x62, 0x62, 0x7e, 0x5f, 0x43, 0x04, 0x46, 0x0c, 0xbe, 0xad, 0xda, 0x23, 0x7e, 0xcb, 0x0d, 0xe0, 0x57, 0xe6, - 0xb3, 0x7b, 0x1e, 0xea, 0x9f, 0x89, 0xcf, 0xde, 0xf2, 0xf7, 0xfc, 0x99, 0x27, 0x25, 0xe9, 0x72, 0xf6, 0x7e, 0x0e, - 0xd7, 0x43, 0x29, 0x4f, 0x87, 0xf4, 0xb3, 0x31, 0x18, 0x40, 0x28, 0x64, 0xbe, 0xf5, 0x80, 0x35, 0x29, 0xc4, 0xbf, - 0x80, 0x6f, 0x47, 0x09, 0x9b, 0x6f, 0xbd, 0xad, 0xaf, 0xe5, 0xcd, 0xb7, 0xde, 0xbd, 0x4f, 0x51, 0x80, 0x55, 0x50, - 0xca, 0x02, 0xab, 0x20, 0x6c, 0xb4, 0x11, 0xc6, 0xc0, 0xd5, 0xbb, 0xc6, 0x50, 0xd7, 0x73, 0xc4, 0xb6, 0x95, 0xbe, - 0x0b, 0xdf, 0x41, 0x06, 0x7c, 0xf0, 0xaa, 0x28, 0x89, 0x3e, 0xa7, 0xa6, 0x48, 0x5a, 0xf7, 0xdc, 0x6f, 0xad, 0x3b, - 0x5a, 0x53, 0xea, 0x23, 0x57, 0xe3, 0xc3, 0xa1, 0x7e, 0x26, 0xb4, 0x48, 0x30, 0x05, 0x8d, 0x6b, 0xd0, 0x16, 0x20, - 0xe8, 0xf3, 0x00, 0x59, 0x4b, 0x8a, 0x05, 0xdf, 0xfe, 0x0a, 0x31, 0x78, 0x65, 0x7a, 0xe7, 0x72, 0x95, 0x91, 0xb0, - 0xbd, 0xf0, 0xcb, 0x61, 0xed, 0x4f, 0x9c, 0x5a, 0x58, 0x5a, 0xcd, 0x41, 0xfd, 0xc4, 0x96, 0xe3, 0x54, 0xd5, 0xfe, - 0x2e, 0x49, 0xaa, 0x5d, 0xa5, 0xe5, 0xf4, 0xce, 0xbe, 0xe9, 0x32, 0xc1, 0xc6, 0x7e, 0x40, 0xd5, 0x91, 0xd5, 0xb0, - 0xfb, 0x42, 0x7d, 0xd1, 0x53, 0x32, 0xa1, 0xf9, 0xa8, 0xa2, 0x79, 0x76, 0xbf, 0xd9, 0x51, 0xff, 0xe9, 0xe5, 0x50, - 0x04, 0x48, 0x56, 0x69, 0xb1, 0x14, 0x39, 0x1b, 0xfb, 0xf1, 0x30, 0xc9, 0x54, 0x78, 0x41, 0x3a, 0xba, 0xfb, 0x8d, - 0xfb, 0x5b, 0x6e, 0x20, 0x2b, 0xb4, 0x6a, 0x83, 0xb1, 0x52, 0xb4, 0x0c, 0xd6, 0x57, 0xe3, 0x7e, 0x5f, 0x5c, 0x8d, - 0xa7, 0x22, 0xa8, 0x81, 0xb8, 0x48, 0x3c, 0x1b, 0x4f, 0x6b, 0x62, 0x49, 0xed, 0x0a, 0x8c, 0xd1, 0xe3, 0xaa, 0xa8, - 0x7d, 0xea, 0x67, 0x10, 0x8a, 0x54, 0x6b, 0xe6, 0x58, 0xe3, 0xc6, 0x88, 0xb8, 0xc3, 0xca, 0xb5, 0x53, 0x7b, 0x1d, - 0x80, 0xe5, 0xd5, 0xb8, 0x20, 0x2c, 0x92, 0x63, 0xe7, 0x02, 0x56, 0xa3, 0x21, 0xd5, 0x6e, 0xb8, 0xf5, 0xb2, 0xf3, - 0x9b, 0x6f, 0x12, 0x5b, 0x1b, 0xe1, 0x96, 0x02, 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, - 0x23, 0x4e, 0x5c, 0xc0, 0x72, 0xc3, 0x53, 0xab, 0x6f, 0x62, 0x70, 0x22, 0x54, 0xad, 0x74, 0xb8, 0x93, 0x09, 0xc4, - 0xfd, 0xea, 0xbe, 0xee, 0x95, 0xe0, 0x27, 0x21, 0xaf, 0xdf, 0xf2, 0x0e, 0x00, 0x2b, 0x3e, 0xe4, 0xc5, 0xb4, 0x70, - 0xb4, 0x2e, 0x83, 0x32, 0x40, 0x84, 0x66, 0x00, 0x74, 0x72, 0x75, 0x10, 0xa5, 0x81, 0x2b, 0xee, 0x10, 0xe1, 0xa7, - 0xd1, 0x93, 0xfc, 0x59, 0xf8, 0xa4, 0x9a, 0x86, 0x17, 0x79, 0x10, 0x5d, 0x54, 0x41, 0xf4, 0xa4, 0xba, 0x0a, 0x9f, - 0xe4, 0xd3, 0xe8, 0x22, 0x0f, 0xc2, 0x8b, 0xaa, 0xb1, 0xef, 0xda, 0xdd, 0x3d, 0x21, 0x6f, 0xbb, 0xfa, 0x23, 0xe7, - 0xca, 0x9e, 0x32, 0x3d, 0x3f, 0xaf, 0xf5, 0x4a, 0xed, 0x36, 0xd7, 0x6b, 0xd4, 0x4c, 0x7d, 0x94, 0xfd, 0xcd, 0x36, - 0x16, 0x1e, 0xcd, 0x21, 0xf4, 0x19, 0x69, 0x31, 0xf7, 0x38, 0xd7, 0x9b, 0x3d, 0x29, 0x0c, 0x8c, 0x98, 0x54, 0x32, - 0x72, 0x7a, 0x81, 0x8b, 0x50, 0x85, 0x18, 0xd6, 0xd2, 0xd5, 0x3e, 0xeb, 0xd2, 0x1b, 0xa8, 0x6b, 0x8a, 0x7d, 0x0d, - 0x19, 0x78, 0xd1, 0xf4, 0x32, 0x18, 0x03, 0x72, 0x04, 0xde, 0xf1, 0xd9, 0x02, 0x0e, 0xcc, 0x35, 0x40, 0xdf, 0x3c, - 0xe8, 0xeb, 0xb2, 0xe4, 0x6b, 0xd5, 0x37, 0xd3, 0xf5, 0x48, 0x29, 0x3f, 0x56, 0x7c, 0x79, 0xf1, 0x94, 0xdd, 0x72, - 0x8d, 0x8a, 0xf2, 0x42, 0x2f, 0xd6, 0x3b, 0xe0, 0xaa, 0x7b, 0x01, 0xb7, 0x59, 0x3c, 0x76, 0xe5, 0x01, 0xcb, 0xb6, - 0xec, 0x9e, 0xbd, 0x65, 0xef, 0xd9, 0x07, 0xf6, 0x99, 0x7d, 0x65, 0x35, 0x42, 0x94, 0x97, 0x4a, 0xca, 0xf3, 0x6f, - 0xf8, 0xad, 0xb4, 0x3d, 0x4a, 0x58, 0xb2, 0x7b, 0xdb, 0x4e, 0x33, 0xdc, 0xb0, 0xf7, 0xfc, 0x66, 0xb8, 0x62, 0x9f, - 0x21, 0x1b, 0x0a, 0xc5, 0x83, 0x15, 0xab, 0xe1, 0x0a, 0x4b, 0x19, 0xf4, 0x69, 0x58, 0x5a, 0xc2, 0xa2, 0x29, 0x14, - 0xa5, 0xe8, 0xcf, 0xbc, 0x26, 0xec, 0xb4, 0x1a, 0x0b, 0x91, 0x1f, 0x1a, 0xae, 0xd8, 0x3d, 0xbf, 0x19, 0xac, 0xd8, - 0x7b, 0x6d, 0x23, 0x1a, 0x6c, 0xdc, 0xe2, 0x08, 0xcc, 0x4a, 0x17, 0x26, 0x05, 0xea, 0xad, 0x7d, 0x13, 0xdc, 0xb0, - 0xb7, 0x58, 0xbf, 0x0f, 0x58, 0x34, 0xca, 0xfc, 0x83, 0x15, 0xfb, 0xca, 0x25, 0x86, 0x9a, 0x5b, 0x9e, 0x74, 0x0c, - 0xd5, 0x05, 0xd2, 0x15, 0xe1, 0x03, 0xa7, 0x17, 0xd9, 0x57, 0x2c, 0x83, 0xbe, 0x32, 0x5c, 0xb1, 0x2d, 0xd6, 0xee, - 0xad, 0x31, 0x6e, 0x59, 0xd5, 0x93, 0xa0, 0xc0, 0x28, 0xab, 0x94, 0x96, 0x8b, 0x23, 0x96, 0x4d, 0x1d, 0x35, 0xa8, - 0x0d, 0x03, 0xfa, 0x60, 0xf4, 0x1f, 0xbe, 0x7e, 0xf7, 0x91, 0x57, 0xea, 0x9b, 0xef, 0x0b, 0xc7, 0xbb, 0xb2, 0x44, - 0xef, 0xca, 0xdf, 0x78, 0x39, 0x7b, 0x31, 0x9f, 0xe8, 0x5a, 0xd2, 0x26, 0x43, 0xee, 0xa6, 0xb3, 0x17, 0x1d, 0xfe, - 0x96, 0xbf, 0xf9, 0x7e, 0x63, 0xf5, 0xb1, 0xfa, 0xae, 0xee, 0xde, 0xfb, 0xc1, 0xa6, 0x71, 0x2a, 0xbe, 0x3b, 0x5d, - 0x71, 0x6c, 0x67, 0xad, 0xbd, 0x33, 0xff, 0x87, 0x6b, 0xbd, 0xc5, 0xb1, 0x7b, 0xcb, 0xb7, 0xc3, 0x8d, 0x3d, 0x0c, - 0xf2, 0xfb, 0xca, 0x2f, 0xbf, 0xe6, 0xcf, 0xbd, 0x4e, 0x49, 0x16, 0x50, 0x8d, 0xde, 0x18, 0x69, 0xe8, 0x92, 0x99, - 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, - 0x8d, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, 0xd8, 0x4b, 0xf2, 0x85, 0xcf, 0xde, 0x09, 0x77, 0x95, - 0xbe, 0xf0, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, - 0x11, 0xfc, 0x1d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0xbf, 0xd4, 0xea, 0xe7, 0x7b, 0x19, 0x9b, 0x03, 0x6f, 0x42, - 0x2b, 0xe8, 0xcd, 0xdb, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0x4d, 0x7d, 0x94, - 0x4e, 0xe5, 0x4d, 0xae, 0x79, 0x22, 0x2d, 0xcc, 0x77, 0x10, 0x0e, 0x7c, 0x6d, 0xc3, 0x14, 0xec, 0x38, 0x6e, 0x06, - 0xd7, 0x0c, 0x20, 0x24, 0xb3, 0xe9, 0x96, 0xbf, 0xe5, 0x1f, 0xf8, 0x57, 0xbe, 0x0b, 0xee, 0xf9, 0x7b, 0xfe, 0x99, - 0xd7, 0x35, 0xdf, 0xb1, 0x85, 0x84, 0x3c, 0xad, 0xb7, 0x97, 0xc1, 0x96, 0xd5, 0xbb, 0xcb, 0xe0, 0x9e, 0xd5, 0xdb, - 0xa7, 0xc1, 0x5b, 0x56, 0xef, 0x9e, 0x06, 0xef, 0xd9, 0xf6, 0x32, 0xf8, 0xc0, 0x76, 0x97, 0xc1, 0x67, 0xb6, 0x7d, - 0x1a, 0x7c, 0x65, 0xbb, 0xa7, 0x41, 0xad, 0x90, 0x1e, 0xbe, 0x0a, 0xc9, 0x74, 0xf2, 0xb5, 0x66, 0x86, 0x55, 0x37, - 0xf8, 0x22, 0xac, 0x5f, 0x54, 0xcb, 0xe0, 0x4b, 0xcd, 0x74, 0x9b, 0x03, 0x21, 0x98, 0x6e, 0x71, 0x70, 0x4b, 0x4f, - 0x4c, 0xbb, 0x82, 0x54, 0xb0, 0xae, 0x96, 0x06, 0x37, 0x75, 0xd3, 0x3a, 0x99, 0x1d, 0xef, 0xc4, 0xb8, 0xc3, 0x3b, - 0xf1, 0x86, 0x2d, 0x9a, 0x4e, 0x57, 0x9d, 0xd3, 0xe7, 0x81, 0x3e, 0x02, 0xf4, 0xde, 0x5f, 0x49, 0x0f, 0x9a, 0xa2, - 0xe1, 0xb9, 0xd2, 0x1d, 0xb7, 0xf6, 0xfb, 0xd0, 0xda, 0xef, 0x99, 0x54, 0xa4, 0x45, 0x2c, 0x2a, 0x8b, 0xaa, 0x42, - 0x3e, 0xf1, 0x20, 0xd3, 0x5a, 0xb5, 0x84, 0x91, 0x3a, 0x13, 0x30, 0xe9, 0x0b, 0x3a, 0x0c, 0x72, 0xb2, 0x2b, 0xb0, - 0x05, 0xdf, 0x0c, 0x12, 0xb6, 0xe6, 0xf1, 0x74, 0x98, 0x04, 0x0b, 0xb6, 0xe4, 0xc3, 0x6e, 0xb1, 0x60, 0xa5, 0xc2, - 0x98, 0xf4, 0xf5, 0xe9, 0x68, 0x77, 0xe7, 0xbd, 0x55, 0x1a, 0xc7, 0x99, 0x40, 0x9d, 0x5b, 0xa5, 0xb7, 0xf9, 0xad, - 0xb3, 0xab, 0xaf, 0xd5, 0x2e, 0x0f, 0x02, 0xc3, 0x6f, 0x40, 0xb4, 0x43, 0xbc, 0x77, 0x50, 0x63, 0xa4, 0x5b, 0x32, - 0xeb, 0xbe, 0xb2, 0xf7, 0xf5, 0xad, 0xd9, 0xaa, 0xff, 0xdd, 0x22, 0x68, 0x2f, 0x97, 0xbd, 0xff, 0xc6, 0xbc, 0xfa, - 0x7b, 0xc7, 0xab, 0x1b, 0x7f, 0x72, 0xcf, 0xdf, 0x60, 0x74, 0x02, 0x26, 0xb2, 0x1d, 0x7f, 0x33, 0xda, 0x36, 0x4e, - 0x79, 0x72, 0x2f, 0xff, 0xbf, 0x52, 0xa0, 0xbd, 0x9b, 0x57, 0xf6, 0xa6, 0xb8, 0xe5, 0x1d, 0x7b, 0xf9, 0xc2, 0xda, - 0x13, 0x0d, 0x42, 0xc9, 0x1b, 0xee, 0x06, 0x45, 0xc3, 0x9e, 0xf8, 0x82, 0x57, 0xb3, 0x37, 0xf3, 0xc9, 0x96, 0x1f, - 0xef, 0x88, 0x6f, 0x3a, 0x76, 0xc4, 0x17, 0xfe, 0x60, 0xd1, 0x7c, 0xab, 0x57, 0x3b, 0x77, 0x72, 0xa7, 0xd2, 0x3b, - 0x7e, 0xbc, 0x8f, 0x0f, 0xff, 0xed, 0x4a, 0xef, 0xbe, 0xbb, 0xd2, 0x76, 0x95, 0xbb, 0x3b, 0xdf, 0x74, 0x7c, 0x23, - 0x6b, 0x8d, 0xe1, 0x66, 0x46, 0xc1, 0x08, 0xd3, 0x16, 0xa6, 0x69, 0x10, 0x59, 0x8a, 0x45, 0x48, 0xd4, 0x28, 0x9d, - 0x13, 0x7d, 0x16, 0x74, 0x0a, 0xba, 0xb8, 0xd1, 0xdf, 0xf2, 0x31, 0xbb, 0x31, 0x2e, 0x9b, 0xb7, 0x57, 0x37, 0x93, - 0xc1, 0xe0, 0xd6, 0xdf, 0xdf, 0xf1, 0x70, 0x76, 0x3b, 0x67, 0xd7, 0xfc, 0x8e, 0xd6, 0xd3, 0x44, 0x35, 0xbe, 0x78, - 0x48, 0x02, 0xbb, 0xf5, 0xfd, 0x89, 0x45, 0x04, 0x6b, 0xdf, 0x38, 0x6f, 0xfd, 0x81, 0x34, 0x4b, 0xcb, 0xad, 0xfd, - 0xfd, 0xc3, 0x1a, 0x8a, 0x5b, 0x10, 0x32, 0xde, 0xdb, 0x2a, 0x87, 0xcf, 0xfc, 0xa3, 0x77, 0xed, 0x4f, 0xaf, 0x75, - 0xf0, 0xcd, 0x44, 0x9d, 0x4b, 0x9f, 0x2f, 0x9e, 0xb2, 0xdf, 0xf8, 0x1b, 0x79, 0xa6, 0xbc, 0x13, 0x72, 0xda, 0x7e, - 0x42, 0x12, 0x27, 0x3a, 0x2a, 0xbe, 0xba, 0x89, 0x04, 0x0a, 0x01, 0xbb, 0xc2, 0xd7, 0x9a, 0xdf, 0x4f, 0xca, 0xa9, - 0xb7, 0x03, 0x92, 0x57, 0x6e, 0x2b, 0xa2, 0x6f, 0x39, 0xe7, 0x37, 0xc3, 0xcb, 0xe9, 0xd7, 0x6e, 0xdf, 0x1e, 0x15, - 0xd6, 0xa6, 0x22, 0xde, 0x6e, 0x31, 0x08, 0xeb, 0x64, 0x66, 0x99, 0x4b, 0xbe, 0xf4, 0xb5, 0x36, 0x73, 0x8f, 0xe9, - 0x1d, 0x67, 0x9a, 0x21, 0xa3, 0x2f, 0x30, 0x33, 0x1d, 0x0e, 0xcb, 0x73, 0x2c, 0x8f, 0x0f, 0x3f, 0x3f, 0xf9, 0x30, - 0xf8, 0x80, 0x21, 0x5c, 0x56, 0x58, 0xc8, 0x57, 0x3e, 0xcc, 0xea, 0xd6, 0xb5, 0xe3, 0xe2, 0xe9, 0xf0, 0x05, 0xe4, - 0x0d, 0xba, 0x1e, 0x9a, 0x22, 0x5a, 0xe5, 0x77, 0x14, 0x7d, 0xa2, 0xe4, 0xa0, 0xe3, 0x09, 0xd4, 0x0e, 0xb9, 0x70, - 0xbf, 0x3e, 0xe1, 0xa0, 0xe8, 0xc0, 0x52, 0xfb, 0xfd, 0xf3, 0x37, 0x44, 0x28, 0x0d, 0xe3, 0xfd, 0x22, 0x8c, 0xfe, - 0x8c, 0xcb, 0x62, 0x0d, 0x47, 0xec, 0x00, 0x3e, 0xf7, 0x44, 0x5f, 0xc3, 0x96, 0xbe, 0xef, 0x07, 0xde, 0x96, 0xbf, - 0x65, 0x5f, 0xb9, 0x77, 0x39, 0xfc, 0xec, 0x3f, 0xf9, 0x00, 0xf2, 0x13, 0xe2, 0xa4, 0x60, 0x48, 0x6c, 0x47, 0x31, - 0x6a, 0x1d, 0x7e, 0xa9, 0x21, 0x56, 0xeb, 0x0d, 0x52, 0x77, 0x41, 0xfa, 0x07, 0x85, 0xec, 0x27, 0x04, 0x56, 0x93, - 0xf4, 0x29, 0x30, 0x89, 0x6f, 0x6b, 0x48, 0x20, 0x4d, 0x0b, 0xc4, 0xe0, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x87, 0x5f, - 0x48, 0xfe, 0xbb, 0xa9, 0xf9, 0x18, 0xfe, 0x86, 0xa1, 0x99, 0x54, 0xf7, 0x69, 0x1d, 0x25, 0x5e, 0x0d, 0xa7, 0x5e, - 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, 0x4e, 0x6e, 0x4b, 0x11, 0xfe, 0x39, 0xc1, 0x67, - 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, 0x65, 0xaf, 0x06, 0x37, 0xf5, 0x90, 0xdf, 0xd6, - 0xee, 0xfb, 0x72, 0x4e, 0xd0, 0x23, 0xfb, 0x01, 0xcd, 0xc1, 0x40, 0xcd, 0x40, 0xca, 0x10, 0xdc, 0xc2, 0xa5, 0xdf, - 0x53, 0x05, 0xf9, 0xf2, 0x7b, 0x5f, 0x84, 0x0c, 0x5c, 0xb9, 0x21, 0x4c, 0xb9, 0x54, 0x48, 0x81, 0xe3, 0xb6, 0x1e, - 0x7c, 0xd1, 0xe8, 0x24, 0x12, 0x7c, 0x4a, 0x40, 0x92, 0xb4, 0x3c, 0x90, 0x34, 0x62, 0x3a, 0x10, 0x17, 0x4a, 0xd3, - 0xac, 0xa4, 0x88, 0x43, 0xec, 0xaa, 0xd7, 0x48, 0x78, 0x16, 0xbc, 0x67, 0xb0, 0x76, 0xa4, 0x68, 0xf1, 0xd5, 0x98, - 0x8e, 0x75, 0xd8, 0xd0, 0x52, 0x16, 0xf7, 0x9b, 0xa4, 0x4e, 0x23, 0x71, 0xe5, 0x9d, 0x90, 0x3f, 0xff, 0xa9, 0x44, - 0x20, 0xbd, 0xab, 0x81, 0x18, 0x04, 0x3f, 0x40, 0xff, 0x01, 0x8b, 0x1c, 0x04, 0xa5, 0xba, 0x0c, 0xf3, 0x2a, 0xa3, - 0x02, 0x67, 0x3b, 0xb6, 0x9d, 0x33, 0x55, 0xb7, 0xe0, 0x8b, 0x30, 0x0c, 0x69, 0x67, 0xab, 0xe6, 0xe4, 0x56, 0x6f, - 0xa0, 0x9e, 0x49, 0x1c, 0xa9, 0xa5, 0x38, 0xd2, 0xd6, 0xdc, 0xa7, 0x0b, 0xaf, 0x5b, 0x5e, 0xd0, 0x70, 0x01, 0x7a, - 0x51, 0xba, 0xeb, 0x7c, 0x42, 0xa1, 0xcb, 0x6a, 0x5c, 0x0d, 0x45, 0x1d, 0xca, 0x31, 0xd6, 0xfe, 0x5c, 0xc9, 0xf3, - 0x3b, 0xb0, 0x1e, 0xa1, 0xe1, 0xab, 0x52, 0x07, 0xb1, 0xfd, 0x44, 0xef, 0x3a, 0x95, 0xfa, 0x1b, 0x00, 0x06, 0x4e, - 0x1d, 0x0f, 0xf5, 0x51, 0x3b, 0x85, 0x6c, 0xe7, 0xde, 0x12, 0xa3, 0x72, 0x25, 0x3c, 0x55, 0x5a, 0x9e, 0x52, 0x56, - 0x7d, 0x2d, 0xb8, 0x95, 0xdd, 0x67, 0x03, 0xc8, 0x68, 0x83, 0x02, 0x79, 0x46, 0x6d, 0x8d, 0x07, 0xa9, 0xa6, 0x59, - 0xe2, 0x18, 0x3e, 0x28, 0xd2, 0xac, 0x02, 0x8b, 0x97, 0xb9, 0x64, 0x0e, 0x0a, 0x96, 0xeb, 0xcd, 0x66, 0x9a, 0xa9, - 0xbe, 0xc8, 0xed, 0x8d, 0xc6, 0xcb, 0xf4, 0xdf, 0x2c, 0x19, 0xf0, 0xe8, 0xe2, 0xa9, 0x1f, 0x40, 0x9a, 0xa4, 0x78, - 0x80, 0x24, 0xd8, 0x1e, 0xec, 0x62, 0x87, 0x61, 0xab, 0x58, 0xd9, 0x93, 0xa7, 0xcb, 0x1d, 0x9a, 0x72, 0x09, 0x2e, - 0x39, 0x31, 0x97, 0x53, 0xdf, 0x97, 0xac, 0x37, 0x14, 0xa7, 0x6c, 0x9a, 0x80, 0x92, 0x40, 0xbb, 0x05, 0xff, 0x85, - 0x4f, 0x0d, 0x9d, 0x16, 0x60, 0xa9, 0xed, 0x06, 0xfc, 0x17, 0xfa, 0xc5, 0x76, 0x17, 0xf5, 0x03, 0xf3, 0x60, 0x6f, - 0x16, 0x57, 0xc6, 0x80, 0x93, 0xc4, 0x95, 0xe6, 0x91, 0xeb, 0x07, 0x45, 0x9f, 0x2e, 0x6b, 0x07, 0xce, 0x14, 0x17, - 0x56, 0xa9, 0x4d, 0xd2, 0x6b, 0xbf, 0xa5, 0x26, 0xde, 0x44, 0x49, 0x55, 0xd8, 0x0e, 0x69, 0xff, 0x92, 0x72, 0xa6, - 0x8a, 0x3b, 0x44, 0x4f, 0x76, 0x13, 0x57, 0x81, 0x17, 0x56, 0x15, 0x1b, 0xa1, 0x36, 0x23, 0xcb, 0x09, 0x9c, 0xee, - 0xb1, 0xba, 0xe0, 0x63, 0xbb, 0x9a, 0x5d, 0xb0, 0x92, 0xad, 0x99, 0x74, 0x9f, 0xb7, 0x63, 0x2e, 0xe4, 0x95, 0x5e, - 0x16, 0xad, 0x80, 0xf6, 0x20, 0x70, 0xf8, 0x85, 0xa6, 0x7b, 0xf4, 0x6c, 0xb3, 0x4d, 0x6d, 0x36, 0xb6, 0x16, 0x21, - 0x64, 0x20, 0x1a, 0xfa, 0x42, 0xce, 0x28, 0xf2, 0x55, 0x5a, 0xae, 0xd5, 0xc6, 0x2a, 0xe3, 0x05, 0x26, 0x82, 0x0c, - 0x67, 0xe1, 0x1d, 0x7a, 0x5a, 0x8f, 0x34, 0xc5, 0x24, 0x38, 0xe9, 0xe2, 0x2f, 0xc0, 0x86, 0xf2, 0x24, 0x37, 0x07, - 0xe4, 0x00, 0x2a, 0x97, 0xa2, 0x54, 0xca, 0xe0, 0x37, 0xea, 0x8e, 0x6c, 0xab, 0xfe, 0x3b, 0x0d, 0x64, 0x70, 0x07, - 0xfa, 0xb6, 0x17, 0x5a, 0x3b, 0xda, 0xb9, 0xb2, 0x35, 0x6d, 0x8b, 0x34, 0x8f, 0x91, 0xc5, 0x06, 0x90, 0x4f, 0xa4, - 0x73, 0x20, 0xf2, 0x9a, 0x68, 0xbc, 0xb3, 0x67, 0x7c, 0x3c, 0x15, 0x0f, 0xc9, 0x7b, 0x95, 0xef, 0x9b, 0x7b, 0x7d, - 0x30, 0xc6, 0xbe, 0x05, 0x65, 0xe2, 0x83, 0xd5, 0xd6, 0xba, 0xc4, 0x7a, 0xab, 0x34, 0x89, 0x6e, 0xb8, 0x82, 0x8e, - 0x23, 0x71, 0x83, 0x18, 0x1c, 0x33, 0x5e, 0x5b, 0x65, 0xe9, 0x2b, 0x2c, 0x73, 0x1d, 0xb3, 0x64, 0xc8, 0xa4, 0xce, - 0x13, 0x05, 0x4f, 0x7e, 0x9e, 0x90, 0x8c, 0x88, 0x9a, 0x6d, 0x39, 0x4a, 0xb9, 0x69, 0x01, 0x97, 0x19, 0x19, 0xc0, - 0x37, 0x69, 0x02, 0x50, 0x2e, 0x5f, 0x82, 0x54, 0x1a, 0x22, 0xb8, 0x66, 0x7b, 0xc9, 0xe8, 0xd6, 0xd1, 0x3a, 0xa8, - 0x92, 0xcc, 0x1d, 0x9c, 0xdb, 0x59, 0xa4, 0xd4, 0x9b, 0x8f, 0x30, 0xec, 0xe4, 0x43, 0x58, 0x27, 0xf8, 0x6d, 0x40, - 0x4d, 0xfa, 0x5c, 0x78, 0xd1, 0x08, 0xd0, 0xd4, 0x77, 0xaa, 0x8c, 0xcf, 0x85, 0x97, 0x8d, 0xb6, 0x2c, 0xa3, 0x14, - 0xaa, 0x0b, 0x66, 0xb7, 0xa6, 0x0b, 0x31, 0xaf, 0xaa, 0x81, 0x36, 0xc8, 0xed, 0x3a, 0x66, 0x40, 0xa3, 0xb6, 0x2b, - 0x8f, 0x2c, 0xc0, 0xad, 0x99, 0x08, 0x8c, 0x9c, 0x7f, 0x9f, 0x5f, 0xab, 0x70, 0x9e, 0x7e, 0x3f, 0xf4, 0xf6, 0xdb, - 0x20, 0x1a, 0x6d, 0x2f, 0xd9, 0x2e, 0x88, 0x46, 0xbb, 0xcb, 0x86, 0xd1, 0xef, 0xa7, 0xf4, 0xfb, 0x69, 0x03, 0xaa, - 0x12, 0x61, 0x22, 0xee, 0xf5, 0x1b, 0xb5, 0x7c, 0xa5, 0xd6, 0xef, 0xd4, 0xf2, 0xa5, 0x1a, 0xde, 0xda, 0x93, 0x48, - 0x10, 0x59, 0x1a, 0x9b, 0x7b, 0xc9, 0x96, 0x6a, 0xa9, 0x74, 0x8c, 0x2a, 0x23, 0x6a, 0xe9, 0x6c, 0x8e, 0x15, 0x23, - 0xed, 0x1c, 0x94, 0x0c, 0xc8, 0xb4, 0xb8, 0xaa, 0x31, 0xdd, 0xac, 0x68, 0x89, 0xc9, 0x08, 0x2b, 0xdb, 0xf2, 0x76, - 0x93, 0xaa, 0xe9, 0x9c, 0xdc, 0xdc, 0x2a, 0xe5, 0xe6, 0x56, 0xf0, 0xfc, 0x1b, 0xba, 0xe5, 0x92, 0x6b, 0x2f, 0xb3, - 0x69, 0xa1, 0x74, 0xcb, 0xb8, 0x06, 0x5b, 0xfb, 0x26, 0x90, 0x65, 0x3e, 0x50, 0xd4, 0xd8, 0x5e, 0x34, 0xca, 0x37, - 0xc8, 0x56, 0xc4, 0xa8, 0x53, 0x16, 0x8c, 0xbf, 0xdd, 0xd1, 0x03, 0x19, 0xa8, 0xaa, 0x6a, 0xe3, 0xe0, 0xce, 0x4a, - 0x7f, 0x58, 0x5e, 0x3c, 0x65, 0x89, 0x95, 0x4e, 0x2e, 0x54, 0xa1, 0x3f, 0x08, 0xd1, 0x4d, 0x65, 0xc3, 0xc1, 0xa1, - 0x2e, 0xb6, 0x32, 0x20, 0xf4, 0x30, 0xbd, 0xb7, 0xb1, 0x92, 0xe5, 0xae, 0x29, 0x5f, 0xcc, 0x78, 0xc2, 0x71, 0xf4, - 0xe5, 0x6a, 0x11, 0xd6, 0x6a, 0x91, 0x9d, 0x00, 0x0f, 0xad, 0xd5, 0x52, 0xc8, 0xd5, 0x22, 0x9c, 0x99, 0x2e, 0xd4, - 0x4c, 0xcf, 0x40, 0x01, 0x29, 0xd4, 0x2c, 0x4f, 0x00, 0x16, 0x5e, 0x98, 0x19, 0x2e, 0xcc, 0x0c, 0xc7, 0x21, 0x35, - 0xfe, 0x0f, 0x7a, 0xaf, 0x73, 0xcf, 0x2d, 0x77, 0xa3, 0xd3, 0x88, 0x6f, 0x47, 0x1b, 0xcc, 0xf1, 0x41, 0x38, 0xa9, - 0xfa, 0xfd, 0xb4, 0x44, 0xac, 0x1e, 0x03, 0x23, 0x28, 0x87, 0xca, 0xd1, 0x7e, 0x59, 0x58, 0x92, 0x25, 0x61, 0x49, - 0xee, 0xd5, 0x38, 0x97, 0x96, 0x8b, 0x57, 0x49, 0x20, 0x12, 0x19, 0x2f, 0xa5, 0x09, 0x3e, 0xe1, 0xe5, 0xc8, 0x48, - 0xcd, 0x93, 0x9b, 0xd4, 0xcb, 0x59, 0xc6, 0xc6, 0x88, 0x61, 0x14, 0xfa, 0x4d, 0xd5, 0xef, 0xe7, 0xa5, 0x97, 0x53, - 0x3b, 0x3f, 0x83, 0xeb, 0xe5, 0xa9, 0xb3, 0xc8, 0x11, 0xf2, 0x6a, 0x24, 0x15, 0x96, 0xd7, 0x4a, 0x3d, 0x7d, 0x09, - 0x3e, 0xa8, 0xbb, 0x37, 0x0a, 0x80, 0xb8, 0xc8, 0xa5, 0x7f, 0x6d, 0x09, 0x97, 0xa6, 0xdc, 0xc0, 0xa0, 0x87, 0x3c, - 0x27, 0x21, 0x54, 0x82, 0x90, 0x14, 0xd6, 0x8d, 0xfb, 0xe2, 0xe9, 0xc4, 0x75, 0x67, 0xb1, 0x81, 0x09, 0x0e, 0x07, - 0x40, 0x3c, 0x98, 0x7a, 0xd1, 0x80, 0x97, 0x6a, 0xce, 0x7c, 0xf4, 0x72, 0x82, 0xc9, 0x00, 0x55, 0xc5, 0xc0, 0x29, - 0xeb, 0x89, 0x7c, 0x64, 0xdc, 0xcc, 0x7c, 0x3f, 0xc0, 0x77, 0xeb, 0x42, 0xa2, 0x3f, 0x28, 0x80, 0x82, 0x4c, 0x01, - 0x14, 0x24, 0x06, 0xa0, 0x20, 0x36, 0x00, 0x05, 0x9b, 0x86, 0x2f, 0xa5, 0x0e, 0x37, 0x02, 0xba, 0x08, 0x1f, 0x7a, - 0x16, 0x36, 0x56, 0x28, 0x9e, 0x8d, 0xd9, 0x98, 0x15, 0x6a, 0xe7, 0xc9, 0xe5, 0x54, 0xec, 0x2c, 0xc6, 0xba, 0x8a, - 0xac, 0x13, 0x2f, 0x24, 0x14, 0x39, 0xe7, 0x46, 0xa2, 0xee, 0x7e, 0xee, 0xbd, 0x24, 0x63, 0xc9, 0xbc, 0xa1, 0x51, - 0x83, 0x79, 0xd9, 0x75, 0x00, 0xd3, 0x92, 0x6f, 0x0b, 0x1a, 0x4c, 0xa7, 0xca, 0x23, 0xd2, 0x24, 0xa8, 0x9d, 0xcb, - 0xa4, 0xc8, 0x09, 0x61, 0x12, 0xf4, 0x4a, 0xf0, 0x1b, 0x89, 0xf2, 0xff, 0x4d, 0x27, 0x78, 0x80, 0x63, 0xa2, 0x55, - 0xf2, 0x15, 0x0c, 0x98, 0x39, 0x7f, 0x2e, 0x9d, 0xb2, 0x11, 0x8a, 0xb1, 0x4c, 0xe3, 0xd1, 0x57, 0x36, 0x44, 0x68, - 0xab, 0xe7, 0x68, 0x62, 0x82, 0x3a, 0xc0, 0x23, 0xfa, 0x6b, 0xf4, 0xd5, 0x50, 0xa8, 0x74, 0x35, 0x52, 0xd7, 0xec, - 0x9c, 0xf3, 0x77, 0xb5, 0xe1, 0x44, 0xc6, 0xb4, 0x29, 0xf0, 0x0d, 0x08, 0xe4, 0x1b, 0x08, 0x00, 0x57, 0x4d, 0x67, - 0xf6, 0x0a, 0xe0, 0x1c, 0x08, 0xe0, 0x71, 0xde, 0xf1, 0xf8, 0x81, 0xfe, 0x2a, 0x8e, 0x7b, 0xa7, 0x69, 0xd8, 0xfe, - 0x2b, 0x30, 0x16, 0x43, 0x39, 0x9e, 0xef, 0x14, 0x24, 0x7b, 0x94, 0xb2, 0x74, 0xd5, 0x44, 0x76, 0x28, 0xd6, 0xa7, - 0x39, 0x65, 0x2c, 0x6d, 0xcb, 0x31, 0xda, 0x78, 0xfd, 0x10, 0x8f, 0x6f, 0x6e, 0xf4, 0xe4, 0x83, 0x1e, 0xdc, 0xde, - 0x5e, 0xbf, 0xec, 0x31, 0x9b, 0x6f, 0xc5, 0xe2, 0x59, 0x11, 0x27, 0x4e, 0xeb, 0x90, 0x03, 0x1c, 0xe4, 0x24, 0x04, - 0xd2, 0x31, 0x2e, 0xb5, 0xe8, 0xa0, 0x66, 0x39, 0xaf, 0x81, 0x65, 0x16, 0x41, 0x36, 0x40, 0x54, 0xd3, 0x54, 0xac, - 0x86, 0x07, 0xa5, 0x6a, 0x4e, 0xa9, 0xd4, 0xbe, 0xe1, 0x6c, 0x75, 0xfa, 0xc4, 0xaa, 0x4d, 0xb8, 0xf5, 0x6f, 0xb5, - 0x27, 0x68, 0x2b, 0x69, 0x20, 0xd4, 0xf3, 0x65, 0xba, 0xa4, 0x28, 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, - 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, - 0xc9, 0x3f, 0x84, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, - 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, - 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, 0x9a, 0xa7, 0xd5, 0x07, 0xf5, 0xf7, 0xfb, 0x05, - 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, 0x68, 0x09, 0xe0, 0x98, 0xa5, 0x3d, 0x14, 0xb2, - 0x60, 0x82, 0x35, 0x54, 0xe5, 0x29, 0x9f, 0xbd, 0x7c, 0x72, 0x03, 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, - 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, - 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, - 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, - 0xb6, 0x02, 0xc4, 0xc0, 0x52, 0x87, 0x24, 0xab, 0x8e, 0xed, 0xf7, 0x5f, 0x8d, 0x0c, 0x6f, 0x3a, 0x22, 0xc2, 0xe8, - 0xdf, 0x15, 0x08, 0x50, 0xb0, 0xcc, 0x6c, 0x67, 0x26, 0x5d, 0xed, 0x59, 0x3d, 0x6f, 0x36, 0x79, 0x57, 0xef, 0x58, - 0x4d, 0xcb, 0xa9, 0x69, 0x95, 0xd5, 0xb4, 0x49, 0x0e, 0x35, 0x13, 0xfd, 0xbe, 0xc6, 0x47, 0xcd, 0xe7, 0x80, 0xcb, - 0x86, 0xc9, 0xaf, 0x66, 0xd5, 0xbc, 0xdf, 0xf7, 0xe4, 0x23, 0xf8, 0x85, 0xc4, 0x65, 0x6e, 0x8d, 0xe5, 0xd3, 0xd7, - 0xc4, 0x67, 0x66, 0x10, 0x8f, 0x56, 0x47, 0x50, 0x5f, 0x9f, 0x84, 0xd7, 0x31, 0x57, 0xd8, 0x4c, 0x4c, 0x5f, 0xc1, - 0xe0, 0x79, 0xc2, 0x07, 0x6f, 0x39, 0xfa, 0x1b, 0xe9, 0xcc, 0x14, 0x2c, 0xe4, 0xdc, 0x9f, 0xbc, 0x42, 0xe8, 0x64, - 0x44, 0x7a, 0xd0, 0xe9, 0x04, 0x0d, 0xd9, 0xef, 0xdf, 0x42, 0x67, 0xb6, 0x52, 0x29, 0x5b, 0x15, 0x95, 0xe9, 0xba, - 0x2e, 0xca, 0x0a, 0x3a, 0x96, 0x7e, 0xde, 0x0a, 0x99, 0x59, 0x3f, 0xb3, 0x90, 0x9f, 0x6e, 0x25, 0xd6, 0x94, 0x6d, - 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, - 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, 0xf4, 0xa5, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, - 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, 0x39, 0x79, 0x05, 0xe0, 0x74, 0x88, 0x88, 0x5b, - 0x91, 0xa0, 0x63, 0xd5, 0xf0, 0xc6, 0xc2, 0x3d, 0xed, 0xa5, 0x71, 0x2f, 0xcd, 0xcf, 0xd2, 0x7e, 0xdf, 0x00, 0x68, - 0xa6, 0x88, 0x0c, 0x8f, 0x33, 0x72, 0x97, 0xb4, 0x10, 0x4c, 0x69, 0xff, 0xd5, 0x18, 0x12, 0x04, 0x02, 0xfe, 0x0f, - 0xe1, 0x7d, 0x00, 0xb4, 0x4d, 0xda, 0x80, 0xab, 0x1e, 0xd3, 0x81, 0xd9, 0x92, 0xb3, 0x55, 0x67, 0x03, 0x50, 0x4e, - 0x95, 0xd6, 0x53, 0x1e, 0xd7, 0x14, 0x11, 0xa9, 0xb2, 0x50, 0xbf, 0xb1, 0x9e, 0x4c, 0x56, 0xb9, 0xc8, 0x90, 0xa3, - 0x32, 0xbd, 0xab, 0x19, 0x21, 0x76, 0xe9, 0xe7, 0x37, 0xb0, 0x64, 0xe3, 0x8f, 0x38, 0x79, 0x4b, 0x80, 0xb4, 0x9d, - 0xb5, 0xab, 0x6a, 0x97, 0xe3, 0xd6, 0x6e, 0x0e, 0x48, 0xbe, 0xde, 0x68, 0x34, 0xd2, 0x7e, 0x72, 0x02, 0x86, 0xaa, - 0xa7, 0x96, 0x42, 0x8f, 0xd5, 0x0a, 0x5b, 0xb7, 0x23, 0x97, 0x59, 0x32, 0x98, 0x2f, 0x8c, 0xe3, 0x6b, 0xf3, 0xd1, - 0x87, 0x4b, 0x65, 0xed, 0x3a, 0xe2, 0xeb, 0x3f, 0xca, 0x6a, 0x7d, 0xcf, 0xbb, 0xaa, 0x09, 0xf8, 0xa2, 0x8a, 0x2d, - 0xfd, 0x8e, 0xf7, 0x64, 0xef, 0xe2, 0x6b, 0x9f, 0xb0, 0x4b, 0xbe, 0xe7, 0x2d, 0xea, 0x3c, 0x5f, 0xf9, 0xba, 0x51, - 0xa5, 0xdb, 0x7b, 0xc9, 0x0d, 0xae, 0xbd, 0xa3, 0xa6, 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7a, - 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, 0x1a, 0xfa, 0xd0, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, - 0x87, 0xde, 0x92, 0x93, 0x43, 0x82, 0xc1, 0xa9, 0x31, 0x7f, 0x78, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x89, 0xc9, - 0x7c, 0x7a, 0x4c, 0x3b, 0x0a, 0x30, 0xa3, 0x4a, 0x6f, 0x9f, 0x1e, 0xd8, 0x8e, 0x97, 0xf5, 0xd0, 0xd2, 0xbb, 0x27, - 0x47, 0xb7, 0xe3, 0x55, 0x35, 0xbe, 0x94, 0x43, 0x9e, 0xe7, 0xb3, 0xd1, 0x68, 0x24, 0x0c, 0x3a, 0x77, 0xa5, 0x37, - 0xb0, 0x02, 0x19, 0x5c, 0x54, 0x1f, 0xca, 0xa5, 0xb7, 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, - 0x63, 0x1c, 0x70, 0x4e, 0x0a, 0x25, 0x47, 0xc9, 0x5a, 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, - 0x1a, 0x21, 0x1f, 0x82, 0x9f, 0x3c, 0x50, 0x8b, 0x3f, 0xd3, 0x82, 0xd8, 0x43, 0x9f, 0x2a, 0xa5, 0x43, 0xbc, 0x2a, - 0x20, 0x44, 0x18, 0xf0, 0x06, 0xda, 0x41, 0x09, 0x0e, 0x3b, 0xdc, 0x23, 0x44, 0x88, 0x7e, 0xe9, 0xe5, 0x33, 0x19, - 0xae, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x88, 0x95, 0x3e, 0x03, 0x17, 0x4c, 0x40, 0x3d, 0xc5, 0xa7, 0xe8, 0x5f, 0x6f, - 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x80, 0x8a, 0xe8, 0xd9, 0xcf, 0xc7, 0x00, 0xde, 0xd9, 0xb5, 0x19, 0x69, 0x2f, 0x7f, - 0x03, 0x0c, 0x2b, 0x25, 0x89, 0x76, 0x4e, 0x89, 0xc0, 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x93, - 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, 0x01, 0x8f, 0x0e, 0x40, 0xe5, 0x4a, 0x41, 0xee, 0x35, 0x47, 0x72, 0xc7, - 0x0f, 0xbd, 0x1f, 0x06, 0xf5, 0xe0, 0x87, 0xde, 0x59, 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0x7e, - 0x18, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, 0x8b, 0xdc, 0x6a, 0xa2, 0xc6, 0x4d, 0x78, 0x97, 0x48, 0x1a, 0xa2, 0x6d, - 0xe7, 0x11, 0x71, 0x03, 0x20, 0x59, 0x7c, 0x36, 0x6f, 0x28, 0xea, 0xdd, 0x84, 0x6f, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, - 0x75, 0x9e, 0xd6, 0x3d, 0x1d, 0x2a, 0x83, 0x2f, 0x48, 0x35, 0x01, 0x1e, 0xed, 0x2f, 0xcd, 0xf1, 0xea, 0xd5, 0xe6, - 0x48, 0xb9, 0x51, 0x25, 0xea, 0xb7, 0x58, 0xcd, 0x7a, 0x88, 0xc8, 0x9d, 0x65, 0xc6, 0xde, 0x5e, 0xf0, 0x4a, 0xce, - 0xaa, 0xd8, 0x2e, 0xc7, 0x57, 0x84, 0xb5, 0x95, 0x04, 0xe8, 0x68, 0x3d, 0xd6, 0xa6, 0x18, 0xf9, 0x95, 0x42, 0x02, - 0x2e, 0x3a, 0xb6, 0x16, 0x8a, 0x8d, 0x17, 0xa0, 0x2f, 0xd9, 0x99, 0x06, 0x58, 0x6f, 0xf4, 0x2a, 0xe2, 0xb6, 0x7c, - 0xa0, 0xc2, 0x9b, 0xdc, 0x54, 0x99, 0x95, 0xcd, 0x4d, 0xbb, 0x9f, 0x2a, 0x5e, 0x21, 0x6e, 0xbd, 0x51, 0x7b, 0x14, - 0xa0, 0xf6, 0xd0, 0x42, 0x19, 0xa0, 0x4b, 0xd3, 0x0c, 0x00, 0x19, 0x00, 0x64, 0xaa, 0x88, 0xcf, 0x04, 0xa8, 0xb4, - 0xd5, 0x8d, 0x02, 0x27, 0xd2, 0x4b, 0x60, 0x5c, 0x60, 0xa5, 0x8f, 0x6c, 0x64, 0xb0, 0xd8, 0x22, 0xc0, 0x2d, 0x47, - 0xfa, 0x30, 0x0d, 0x27, 0xdb, 0x68, 0x0e, 0x93, 0x34, 0xbf, 0x0b, 0xb3, 0x54, 0x42, 0x4b, 0xbc, 0x96, 0x35, 0x46, - 0x2c, 0x20, 0x7d, 0x9f, 0xbe, 0x29, 0xb2, 0x98, 0x20, 0xe1, 0xac, 0xa7, 0x0e, 0xa0, 0x9a, 0x9c, 0x6b, 0x4d, 0xab, - 0x67, 0xb5, 0xc9, 0x43, 0x16, 0xe8, 0xec, 0xc1, 0x98, 0xd4, 0x72, 0x43, 0x8f, 0xec, 0xaf, 0x1c, 0xcf, 0x08, 0xdf, - 0xf5, 0x0c, 0xa7, 0xfe, 0xfb, 0x54, 0x03, 0x29, 0x53, 0x02, 0x08, 0x32, 0x38, 0x9a, 0x10, 0xca, 0xd3, 0x31, 0x99, - 0xda, 0xfc, 0x08, 0x84, 0x23, 0x82, 0x57, 0xf0, 0xdc, 0xd0, 0xba, 0xe5, 0xc6, 0xce, 0x22, 0x4f, 0x13, 0x40, 0x16, - 0x2f, 0xf8, 0x1d, 0x20, 0x73, 0xea, 0x55, 0x21, 0x7b, 0xf6, 0x5c, 0x4c, 0x67, 0xf3, 0xe0, 0xcf, 0x84, 0xf6, 0x2f, - 0x26, 0xfc, 0xa6, 0xbb, 0x4a, 0xae, 0x4c, 0xad, 0x7b, 0x13, 0x3d, 0xe6, 0x72, 0xa7, 0x4f, 0x2b, 0x8e, 0x11, 0xcf, - 0x60, 0x15, 0x90, 0x73, 0x36, 0xe4, 0xcf, 0xce, 0x01, 0xbb, 0x65, 0x25, 0xbc, 0x88, 0x3f, 0x0b, 0x65, 0xb5, 0x00, - 0xf9, 0x91, 0xf3, 0xc8, 0xfc, 0xf2, 0xd5, 0x76, 0x28, 0xe7, 0x14, 0x45, 0xb4, 0x9c, 0x9a, 0x96, 0x14, 0xb2, 0x43, - 0x4f, 0xc1, 0x64, 0x6a, 0xcb, 0xdf, 0x77, 0x89, 0x4b, 0xf2, 0xcd, 0x24, 0xb2, 0xaf, 0x03, 0xac, 0x59, 0xab, 0xee, - 0xa1, 0x1b, 0x82, 0x01, 0x22, 0x23, 0x94, 0xd9, 0x5c, 0xdf, 0xad, 0x07, 0x03, 0x05, 0xf3, 0x2b, 0xe8, 0xa6, 0x45, - 0xa7, 0x38, 0x40, 0xce, 0x5a, 0xd7, 0xa8, 0x54, 0x15, 0x87, 0x0e, 0xf3, 0x6e, 0x59, 0x95, 0x5d, 0x96, 0x5e, 0x08, - 0x52, 0xa3, 0xae, 0x82, 0x45, 0x4a, 0x45, 0x14, 0xef, 0xc9, 0xaf, 0x81, 0x89, 0x67, 0x56, 0x8e, 0xd2, 0x78, 0x0e, - 0x88, 0x41, 0x0a, 0x88, 0x53, 0x7e, 0x05, 0x68, 0xa2, 0x8b, 0x28, 0xcc, 0x5e, 0xc7, 0x55, 0x50, 0x5b, 0x4d, 0xbf, - 0x77, 0x20, 0x63, 0xcf, 0xeb, 0x7e, 0x3f, 0x25, 0x46, 0x3f, 0x8c, 0xc2, 0xc0, 0xbf, 0xc7, 0xd3, 0x7d, 0x13, 0xa4, - 0xe6, 0x95, 0x3f, 0xe1, 0x15, 0x5d, 0x6e, 0x6d, 0xca, 0x15, 0x8d, 0x0b, 0x7f, 0x8d, 0xe0, 0xf0, 0xa9, 0xa3, 0xd8, - 0x6e, 0x53, 0xe5, 0xd4, 0xc6, 0x60, 0x10, 0xc2, 0x7d, 0x2b, 0xe3, 0xf7, 0x89, 0x97, 0xcf, 0xa2, 0x39, 0x28, 0x4a, - 0x33, 0xcd, 0x17, 0x52, 0x48, 0x37, 0x01, 0xfa, 0x68, 0x10, 0x6a, 0x75, 0xe5, 0xa7, 0xc4, 0x4b, 0xd5, 0xb4, 0x36, - 0x4f, 0xb1, 0x46, 0x81, 0x98, 0x45, 0xf3, 0x86, 0x65, 0x74, 0x48, 0xaa, 0xcb, 0xa5, 0x69, 0xc6, 0x27, 0xab, 0x19, - 0xaa, 0x15, 0x47, 0x4d, 0x50, 0xa3, 0xf4, 0x09, 0x2e, 0x80, 0x3f, 0xd3, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, - 0x04, 0x31, 0x62, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, 0x5d, 0x33, 0xfa, 0x7d, 0x19, 0x32, 0x64, 0x92, 0x90, 0xa7, 0x0f, - 0x97, 0xeb, 0x47, 0x52, 0x5d, 0x00, 0xbf, 0x72, 0xc5, 0x66, 0xbd, 0xde, 0x1c, 0xe0, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, - 0x15, 0x9c, 0x5f, 0x12, 0xfc, 0xae, 0xfa, 0x11, 0x66, 0x19, 0x54, 0x01, 0x19, 0x7f, 0x2c, 0x14, 0xf5, 0xbc, 0xc5, - 0xec, 0x3e, 0x52, 0x17, 0x94, 0x59, 0x3a, 0xb7, 0x38, 0x41, 0xc0, 0x79, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, - 0x69, 0x46, 0x81, 0xea, 0x08, 0xf0, 0xd9, 0xac, 0x1f, 0xc2, 0xfe, 0x01, 0x91, 0x85, 0xfa, 0x9b, 0x6f, 0xe5, 0xac, - 0x21, 0x79, 0x20, 0xd5, 0xdc, 0xc7, 0x70, 0x6a, 0xdc, 0xe0, 0x4b, 0x37, 0xbd, 0xa9, 0xe0, 0x35, 0x21, 0x73, 0xdf, - 0xa0, 0xb5, 0xef, 0x06, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, - 0x5f, 0xbb, 0xf8, 0xc5, 0x29, 0xd2, 0xb3, 0xe8, 0x02, 0x03, 0x5d, 0x90, 0x79, 0xe3, 0x9f, 0x15, 0xac, 0x5c, 0x40, - 0xef, 0xa5, 0x62, 0x25, 0x27, 0xdb, 0x4e, 0xfd, 0x51, 0x2a, 0xfb, 0xed, 0x99, 0x35, 0x81, 0xdf, 0x27, 0xf6, 0x4b, - 0x64, 0xf2, 0x4d, 0x8f, 0x4d, 0xbe, 0x32, 0x2c, 0x3a, 0xb5, 0x0c, 0xce, 0xe9, 0x91, 0xc1, 0xb9, 0xb7, 0xb3, 0x6a, - 0x13, 0xc2, 0x50, 0x90, 0x04, 0x9a, 0x2e, 0x3c, 0xac, 0x9b, 0xfe, 0xfc, 0xa4, 0x45, 0xb5, 0x55, 0xfb, 0xd6, 0xfd, - 0x38, 0xc4, 0x2e, 0x7e, 0x9f, 0x78, 0x86, 0x88, 0xd4, 0x07, 0x3a, 0x30, 0x19, 0x3c, 0x71, 0xd9, 0xef, 0x43, 0x61, - 0xb3, 0xf1, 0x7c, 0x54, 0x17, 0x6f, 0x8a, 0x7b, 0x40, 0x75, 0xa8, 0xc0, 0x2e, 0x87, 0x32, 0x94, 0x11, 0x9b, 0xda, - 0x72, 0xcf, 0x1f, 0xd7, 0x61, 0x0e, 0xf2, 0x8e, 0x86, 0xc7, 0x39, 0x03, 0x31, 0x0c, 0xbe, 0xfe, 0xc3, 0xa3, 0x7d, - 0xda, 0xfc, 0x70, 0x06, 0xdf, 0x1d, 0x9d, 0x7d, 0x40, 0xba, 0x9b, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x38, 0xfb, - 0x01, 0x52, 0x7f, 0x38, 0x2b, 0xca, 0xb3, 0x1f, 0x54, 0x65, 0x7e, 0x38, 0xa3, 0x05, 0x37, 0xfa, 0xc3, 0x9a, 0x78, - 0xbf, 0x57, 0x9a, 0x01, 0x6d, 0x01, 0x91, 0x59, 0x5a, 0xfd, 0x08, 0x4a, 0x44, 0xc5, 0x8f, 0x2a, 0xa3, 0x5a, 0xad, - 0x1d, 0xe7, 0x51, 0xa2, 0x91, 0xb2, 0x69, 0x42, 0xe2, 0x6a, 0x09, 0xeb, 0x50, 0xcf, 0x4e, 0x9b, 0x6f, 0xc7, 0x79, - 0xa0, 0x0e, 0x88, 0x9c, 0x3f, 0xcb, 0x47, 0x5b, 0xfa, 0x1a, 0x7c, 0xeb, 0x70, 0xc8, 0x47, 0x3b, 0xf3, 0xd3, 0x27, - 0x6b, 0xa5, 0x8c, 0x3b, 0x52, 0xe4, 0x42, 0xc8, 0x19, 0xb7, 0xed, 0x31, 0xe0, 0x00, 0xf0, 0x0f, 0x07, 0xfa, 0xbd, - 0x93, 0xbf, 0xd5, 0x6e, 0x69, 0xd5, 0xf3, 0x43, 0x8b, 0x3b, 0xe3, 0x75, 0x6d, 0x88, 0xda, 0xf6, 0x12, 0x5b, 0x7a, - 0xdf, 0x34, 0xa8, 0x29, 0xa2, 0x9f, 0xb0, 0x9a, 0x58, 0xc5, 0x61, 0x41, 0x4a, 0x48, 0x62, 0x38, 0x46, 0x3b, 0xf4, - 0x38, 0x5d, 0x2c, 0x3d, 0xb9, 0xef, 0xf0, 0x72, 0xeb, 0xfb, 0x80, 0xa4, 0x55, 0x38, 0x7f, 0xe4, 0x85, 0x06, 0x1e, - 0xbd, 0xc8, 0xab, 0x22, 0x13, 0x23, 0x41, 0xa3, 0xfc, 0x9a, 0xc4, 0x99, 0x33, 0xac, 0xc5, 0x99, 0x02, 0x0b, 0x0b, - 0x09, 0xdd, 0xbb, 0x28, 0x29, 0x3d, 0x38, 0x7b, 0xb4, 0x2f, 0x9b, 0x3f, 0x08, 0x1e, 0x62, 0x74, 0x03, 0x8c, 0x38, - 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0x5e, 0xe6, 0x05, 0x84, 0x68, 0x9e, 0x49, 0xc5, 0x6a, 0x79, - 0x06, 0x8c, 0x79, 0x22, 0x3e, 0x0b, 0x2b, 0x39, 0x0d, 0xaa, 0x8e, 0x62, 0xf5, 0x36, 0x9e, 0x7b, 0x40, 0xf1, 0xfd, - 0x28, 0x01, 0x2e, 0x77, 0x9f, 0xbd, 0x52, 0xae, 0xa9, 0xa4, 0x47, 0x9e, 0x43, 0xb4, 0xe4, 0x75, 0x02, 0x14, 0xcf, - 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, - 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, - 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0xad, 0xcc, 0xbd, 0x10, 0x86, 0x2a, 0xe1, 0xde, 0xeb, 0x7a, 0x16, 0xca, 0x4d, 0xd1, - 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, 0xdf, 0x26, 0x5e, 0x0c, 0x86, 0xeb, 0x05, 0x2f, - 0x67, 0x1b, 0xb3, 0x10, 0x0e, 0x87, 0xcd, 0xa4, 0x98, 0x2d, 0x20, 0xcc, 0x75, 0x31, 0x3f, 0x1c, 0xba, 0x5a, 0xb6, - 0x16, 0x1e, 0x3c, 0x54, 0x2d, 0xdc, 0x34, 0x2c, 0x87, 0x9f, 0xc9, 0x2c, 0xc6, 0xf6, 0x35, 0x3e, 0xb3, 0x3f, 0x5f, - 0x74, 0xcf, 0x12, 0x24, 0xdf, 0x58, 0x03, 0xed, 0xd8, 0xac, 0xdd, 0xe1, 0x6a, 0x04, 0x24, 0xa5, 0xbb, 0xd1, 0xdf, - 0x95, 0x9d, 0x3c, 0x25, 0xc8, 0x1d, 0xad, 0xc0, 0x7e, 0xf7, 0x8d, 0x3f, 0xd1, 0x62, 0x0f, 0xda, 0x6d, 0x6c, 0x09, - 0x51, 0x4d, 0x7b, 0x2e, 0x57, 0x8a, 0xa5, 0x79, 0x2b, 0x6d, 0xf4, 0x7c, 0x58, 0x9f, 0xfb, 0x46, 0x0e, 0x14, 0x8c, - 0x11, 0x4f, 0xad, 0x83, 0x68, 0x36, 0x07, 0x1a, 0x0c, 0x34, 0x8f, 0xf0, 0xd4, 0x42, 0x07, 0x65, 0xd6, 0x86, 0xfd, - 0x3c, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, 0x31, 0xc5, 0xf6, 0xf8, 0x57, 0xa5, 0xa8, 0xf0, - 0xd8, 0x8e, 0xb8, 0xd6, 0x3e, 0x89, 0xda, 0x50, 0x39, 0xfc, 0x4b, 0xd8, 0x47, 0xd8, 0x5f, 0x68, 0x82, 0x30, 0xd8, - 0xf5, 0x67, 0x02, 0x21, 0x62, 0x21, 0x5e, 0xf0, 0xaf, 0x4a, 0x52, 0xd1, 0x09, 0x9f, 0xed, 0x4a, 0xe0, 0xad, 0xc3, - 0x80, 0x3e, 0x21, 0x3f, 0x13, 0x09, 0x43, 0x33, 0xa1, 0x77, 0xf4, 0xdf, 0x89, 0x9d, 0x6c, 0x92, 0x5b, 0x21, 0x1f, - 0x48, 0x2a, 0x09, 0x26, 0x58, 0x79, 0xa1, 0xfc, 0xd1, 0xbd, 0x50, 0x6a, 0xad, 0x05, 0xad, 0x5f, 0xfe, 0x3c, 0xf1, - 0x0c, 0xfe, 0x1e, 0xc8, 0x18, 0x74, 0x1b, 0x51, 0x4d, 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x67, 0xeb, - 0x2c, 0xac, 0x17, 0x45, 0xb9, 0x6a, 0x45, 0x8a, 0xca, 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x22, 0x1f, - 0x3c, 0x02, 0x60, 0x3c, 0xca, 0xd3, 0xaa, 0xa3, 0xb4, 0x7e, 0x60, 0x19, 0x30, 0x02, 0x27, 0xca, 0x80, 0x47, 0x58, - 0x06, 0xe6, 0x69, 0x97, 0xa1, 0x06, 0xb1, 0x46, 0xd5, 0x95, 0xda, 0x60, 0x4e, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, - 0x31, 0x34, 0x75, 0xe5, 0x91, 0xf5, 0x92, 0x13, 0xf6, 0x64, 0x37, 0x90, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0x5d, 0xcb, - 0x12, 0xe5, 0xa2, 0x5b, 0x46, 0x94, 0x89, 0x90, 0xfa, 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0xb4, 0x6f, 0x8f, - 0x14, 0xbd, 0x60, 0xd0, 0x3e, 0xed, 0x91, 0x52, 0xcf, 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0x5f, 0xa0, - 0x7c, 0x07, 0x33, 0xe3, 0x6c, 0xf6, 0x87, 0xde, 0xdc, 0x1e, 0xed, 0xeb, 0xe6, 0x0f, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, - 0x13, 0x9f, 0x2b, 0x16, 0x2a, 0xab, 0x10, 0x2b, 0x48, 0xfb, 0x5f, 0xc2, 0xfb, 0x03, 0xde, 0x1a, 0xa1, 0x59, 0x19, - 0x0f, 0xf3, 0xd1, 0xa3, 0xbd, 0x68, 0xfe, 0xe8, 0x2c, 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0x7f, 0x1c, 0x25, 0xcd, 0xd9, - 0xc3, 0x35, 0x92, 0x3a, 0xc0, 0x87, 0xeb, 0x33, 0x7c, 0xa0, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0x1f, - 0xad, 0xe7, 0xf4, 0xf1, 0x63, 0x39, 0xdd, 0x92, 0x22, 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xbc, 0x19, - 0xd2, 0xbb, 0x6e, 0x95, 0xd4, 0x65, 0x8f, 0x12, 0x41, 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, - 0x9b, 0xd5, 0x9c, 0x00, 0x11, 0x01, 0xad, 0x55, 0xde, 0x07, 0x8e, 0xf9, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x73, - 0xa5, 0xbd, 0x92, 0x02, 0xfa, 0x39, 0xc8, 0xdc, 0x3e, 0xba, 0xe5, 0xaa, 0x65, 0x9e, 0x4b, 0x5b, 0x0e, 0x58, 0xb4, - 0x10, 0xa8, 0xd9, 0xb9, 0x74, 0x38, 0x50, 0x10, 0xea, 0x4a, 0x54, 0x11, 0x57, 0x47, 0xd1, 0x42, 0xd4, 0x6a, 0xd5, - 0x2e, 0x27, 0x9b, 0x0a, 0xd9, 0x92, 0x08, 0x32, 0x4a, 0x31, 0x74, 0xe9, 0xa3, 0x5c, 0xed, 0x99, 0x86, 0x03, 0x34, - 0x01, 0x9b, 0x36, 0xf8, 0x5b, 0xe0, 0x5e, 0x06, 0x67, 0xa6, 0x7d, 0x1a, 0x46, 0xc0, 0x69, 0x0e, 0x31, 0x7f, 0x7e, - 0xd7, 0x83, 0x0a, 0x1e, 0x74, 0xa4, 0xbf, 0xae, 0x67, 0x05, 0x9e, 0xb9, 0x27, 0x9e, 0xbf, 0x3a, 0x91, 0x5e, 0xe4, - 0xf0, 0x40, 0xd3, 0x20, 0x66, 0xfc, 0x79, 0x59, 0x86, 0xbb, 0xd1, 0xa2, 0x2c, 0x56, 0x5e, 0xa4, 0xf7, 0xf1, 0x4c, - 0x8a, 0x81, 0xc4, 0x8c, 0x99, 0xd1, 0x55, 0xac, 0xe3, 0x1c, 0xc6, 0xbd, 0x3d, 0x09, 0x2b, 0xb4, 0x7f, 0x96, 0xd8, - 0xeb, 0x02, 0xb0, 0x1c, 0xb2, 0x06, 0xad, 0xf0, 0x4e, 0xb7, 0xb7, 0x7b, 0x5c, 0xb2, 0xa3, 0xb8, 0x01, 0xf4, 0xb3, - 0x1a, 0x5a, 0x26, 0xa8, 0x65, 0xd6, 0x9d, 0x4c, 0xa6, 0x48, 0x2e, 0xdf, 0x86, 0xbd, 0x62, 0x45, 0x3e, 0x6f, 0xe4, - 0xf6, 0xf0, 0x2e, 0x5c, 0x89, 0x58, 0x5b, 0xd0, 0x49, 0x47, 0xc6, 0xe1, 0x5e, 0x68, 0x6e, 0xa4, 0xfb, 0x47, 0x55, - 0x12, 0x96, 0x22, 0x86, 0x5b, 0x20, 0xdb, 0xab, 0x6d, 0x25, 0x28, 0x81, 0x0f, 0xf6, 0x43, 0x29, 0x16, 0xe9, 0x56, - 0x00, 0xae, 0x03, 0xff, 0x4d, 0x22, 0x12, 0xba, 0x3b, 0x0f, 0x51, 0xac, 0x91, 0xf7, 0x0d, 0xa2, 0xb1, 0xbf, 0x04, - 0x39, 0x0d, 0xc8, 0x44, 0x8a, 0x91, 0x2c, 0x18, 0xf8, 0x00, 0x72, 0xbe, 0x06, 0x93, 0xdc, 0x34, 0xf7, 0xfc, 0x20, - 0xd7, 0x1d, 0x4c, 0xfb, 0xa0, 0x7b, 0x71, 0xad, 0x59, 0x0e, 0x5e, 0x31, 0x11, 0xff, 0xb9, 0xf6, 0x4a, 0x96, 0xb3, - 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, - 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, - 0x41, 0xe8, 0xe7, 0x1a, 0x90, 0x36, 0x98, 0xa4, 0x49, 0xa8, 0x7c, 0x70, 0x41, 0x37, 0xcc, 0xcb, 0x95, 0xcb, 0x55, - 0x93, 0xaa, 0xe5, 0x97, 0x23, 0xea, 0xbb, 0x5a, 0x72, 0xa9, 0x36, 0x9f, 0x1a, 0x65, 0x8d, 0x20, 0x93, 0xa3, 0xf4, - 0xfb, 0x94, 0x0b, 0xb7, 0x32, 0x26, 0xeb, 0xc3, 0xc1, 0x2b, 0xb8, 0xa9, 0xf1, 0xeb, 0x9c, 0x08, 0x45, 0xed, 0x21, - 0x11, 0xb6, 0x76, 0x2b, 0x74, 0xef, 0x71, 0xa3, 0x34, 0x8f, 0xb2, 0x4d, 0x2c, 0x2a, 0xaf, 0x97, 0x80, 0xb5, 0xb8, - 0x07, 0xbc, 0xa8, 0xb4, 0xf4, 0x2b, 0x56, 0x00, 0x7a, 0x80, 0x14, 0x36, 0x5e, 0x23, 0x03, 0xd6, 0x23, 0x2f, 0xf5, - 0xfb, 0x7d, 0x63, 0xca, 0x7f, 0x7f, 0x9f, 0x03, 0x49, 0xa1, 0x28, 0xeb, 0x1d, 0x4c, 0x20, 0xb8, 0x76, 0x92, 0xf6, - 0xac, 0xe6, 0xcf, 0xd6, 0xb5, 0x07, 0xfc, 0x56, 0xbe, 0x45, 0x62, 0xf5, 0xd2, 0xbe, 0xd8, 0xec, 0xd3, 0xea, 0x93, - 0xd1, 0x38, 0x08, 0x96, 0x56, 0xaf, 0xb5, 0xca, 0x21, 0x6f, 0x78, 0x01, 0x22, 0x95, 0x75, 0x75, 0xad, 0x9c, 0xab, - 0x6b, 0xc1, 0x91, 0x4b, 0xb6, 0xe4, 0x39, 0xfc, 0x17, 0x72, 0xaf, 0x3c, 0x1c, 0x0a, 0xbf, 0xdf, 0x4f, 0x67, 0xa4, - 0x95, 0x05, 0xf6, 0xb4, 0x75, 0xed, 0x85, 0xfe, 0xe1, 0xf0, 0x1a, 0xbc, 0x46, 0xfc, 0xc3, 0xa1, 0xec, 0xf7, 0x3f, - 0x9a, 0x9b, 0xcc, 0xf9, 0x58, 0x29, 0x65, 0x2f, 0x51, 0xe9, 0xfe, 0x39, 0xe1, 0xbd, 0xff, 0x3d, 0xfa, 0xdf, 0xa3, - 0xcb, 0x9e, 0x0a, 0x01, 0x4b, 0xf8, 0x0c, 0x6f, 0xe8, 0x4c, 0x5d, 0xce, 0x99, 0x74, 0x77, 0x57, 0x7e, 0xe8, 0x3d, - 0x0d, 0x15, 0xdf, 0x9b, 0x9b, 0x36, 0xfe, 0x5c, 0x1d, 0x69, 0x12, 0x3a, 0x2e, 0xfa, 0x87, 0xc3, 0x9b, 0x44, 0xeb, - 0xd3, 0x52, 0xa5, 0x4f, 0x53, 0x38, 0x4a, 0x86, 0xdc, 0xcd, 0x2d, 0x4c, 0x07, 0xf6, 0xe3, 0xe6, 0xab, 0xe4, 0xc5, - 0x59, 0x0a, 0xd7, 0xde, 0x7c, 0x96, 0xce, 0xa7, 0x60, 0x5d, 0x19, 0xe6, 0xb3, 0x7a, 0x1e, 0x40, 0xea, 0x10, 0xd2, - 0xac, 0x69, 0xf8, 0x8f, 0xca, 0x15, 0xbc, 0xb5, 0xc7, 0xbb, 0x81, 0x8b, 0x52, 0x47, 0xfa, 0xa4, 0x8d, 0xa6, 0x4b, - 0x2a, 0xf9, 0x8f, 0x22, 0x8f, 0x31, 0x66, 0xe3, 0x25, 0xf1, 0x7e, 0x16, 0xf9, 0x75, 0x01, 0xd8, 0x45, 0x00, 0x86, - 0x9c, 0xce, 0x1d, 0x49, 0xfc, 0x63, 0xf2, 0xfd, 0x1f, 0xd3, 0xa5, 0x7d, 0x28, 0x8b, 0x65, 0x29, 0xaa, 0xea, 0xa8, - 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, - 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0x17, 0xbb, 0xd7, 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, - 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, - 0xaf, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, - 0xfe, 0x4c, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, 0xb2, 0xbc, 0x3a, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, - 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x33, 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, - 0x9b, 0x79, 0xe2, 0x19, 0xd0, 0x31, 0x3f, 0x43, 0x57, 0xc5, 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, - 0xf1, 0xce, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, - 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, - 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xab, 0xb3, 0x07, 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, - 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, - 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, - 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, - 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, - 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xa1, 0xb6, 0x2c, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, - 0x17, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, - 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xeb, 0x97, 0x67, 0x3f, 0xf4, - 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xce, 0x56, 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, - 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, - 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, - 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x69, 0x02, 0xa1, 0x16, 0xcc, - 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, - 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, - 0xfd, 0x48, 0x05, 0xe5, 0x24, 0xf4, 0x8b, 0x42, 0xbf, 0x34, 0x1c, 0x65, 0xcc, 0xbf, 0x84, 0x9a, 0x23, 0xa0, 0xde, - 0xf2, 0x50, 0xd1, 0x05, 0xe0, 0x72, 0x8e, 0x98, 0x71, 0xde, 0xe3, 0x2e, 0x30, 0xe7, 0xff, 0xe1, 0xed, 0x4b, 0xbc, - 0xdb, 0xb6, 0xb1, 0x7e, 0xff, 0x15, 0x8b, 0x2f, 0x55, 0x89, 0x08, 0x92, 0x25, 0x27, 0xe9, 0x4c, 0x29, 0xc3, 0xfa, - 0xdc, 0x2c, 0x6d, 0x3a, 0xcd, 0xd2, 0x24, 0x5d, 0x66, 0xf4, 0xf4, 0xb9, 0x34, 0x09, 0x5b, 0x6c, 0x68, 0x40, 0x25, - 0x29, 0x2f, 0x91, 0xf8, 0xbf, 0xbf, 0x73, 0x2f, 0x56, 0x52, 0x94, 0x93, 0x99, 0xf7, 0xbd, 0x77, 0x72, 0x4e, 0x2c, - 0x82, 0x20, 0x76, 0x5c, 0x5c, 0xdc, 0xe5, 0x77, 0x4d, 0x08, 0x0a, 0x73, 0x1d, 0x2c, 0x0c, 0x00, 0xbd, 0x6b, 0x8f, - 0xb6, 0x9c, 0x74, 0x09, 0x16, 0xcf, 0x0d, 0x2c, 0x5e, 0x5d, 0x2c, 0xaa, 0x2b, 0xae, 0xe5, 0x16, 0x36, 0xa5, 0xac, - 0x62, 0x08, 0x20, 0xd0, 0x8c, 0x19, 0x76, 0xcb, 0x5d, 0x8e, 0x64, 0x5d, 0x14, 0x5c, 0xec, 0x04, 0x86, 0x6e, 0xc6, - 0x25, 0x33, 0x07, 0x57, 0x33, 0xac, 0x93, 0x8a, 0x02, 0xec, 0xea, 0x02, 0x64, 0x2f, 0x0c, 0x75, 0xdd, 0xcc, 0x96, - 0xeb, 0xc0, 0xd7, 0xa5, 0x0b, 0x5f, 0x52, 0xf0, 0x72, 0x25, 0x45, 0x99, 0x5d, 0xf3, 0x9f, 0xec, 0xcb, 0x66, 0x2c, - 0x29, 0xb4, 0x23, 0x7d, 0xd5, 0xee, 0x8e, 0x16, 0xe3, 0xd8, 0x72, 0x7c, 0x4b, 0xa5, 0x5b, 0x3d, 0xaa, 0x5e, 0x08, - 0x6d, 0x9d, 0x6b, 0x99, 0xa5, 0x29, 0x17, 0x2f, 0x45, 0x9a, 0x25, 0x5e, 0x72, 0xac, 0x63, 0x55, 0xbb, 0x20, 0x58, - 0x2e, 0x4c, 0xf2, 0xb3, 0xac, 0xc4, 0xd8, 0xc1, 0x8d, 0x46, 0xb5, 0xa2, 0x4e, 0x99, 0x18, 0x18, 0xf2, 0x1d, 0x06, - 0xdf, 0x66, 0x32, 0x01, 0x86, 0x1f, 0x13, 0xf5, 0x25, 0x3d, 0x85, 0x80, 0x0f, 0x2a, 0x34, 0xf7, 0x33, 0x8e, 0xe0, - 0xd7, 0x56, 0x65, 0x0e, 0x4c, 0xb6, 0x56, 0x41, 0x22, 0xee, 0x5d, 0x36, 0xd7, 0x8b, 0x68, 0xa1, 0xee, 0x42, 0xbd, - 0x78, 0xbb, 0xed, 0x25, 0x8a, 0x0e, 0x38, 0xf9, 0x69, 0xf0, 0x22, 0xce, 0x72, 0x9e, 0x1e, 0x54, 0xf2, 0x40, 0x6d, - 0xa8, 0x03, 0xe5, 0xcc, 0x01, 0x3b, 0xef, 0xeb, 0xea, 0x40, 0xaf, 0xe9, 0x03, 0xdd, 0xce, 0x03, 0xb8, 0x60, 0xe0, - 0xce, 0xbd, 0xcc, 0xae, 0xb9, 0x38, 0x00, 0x65, 0xa0, 0x35, 0x1e, 0xa8, 0xcb, 0x6a, 0xa4, 0x26, 0x46, 0xc7, 0xb0, - 0x4e, 0xf4, 0xc1, 0x1c, 0xd0, 0x9f, 0x21, 0xac, 0x7d, 0xeb, 0xed, 0x4a, 0x1f, 0xb4, 0x01, 0x7d, 0xb7, 0x34, 0x7d, - 0xd0, 0x81, 0xe3, 0x55, 0x74, 0xe0, 0xc6, 0x90, 0x6a, 0xd0, 0x56, 0x23, 0xab, 0x40, 0xf1, 0x86, 0xb7, 0x78, 0x77, - 0xae, 0x25, 0x1b, 0xef, 0x25, 0x62, 0x7c, 0x65, 0xa2, 0x8a, 0x33, 0x71, 0xea, 0xa5, 0xf2, 0x5a, 0x3b, 0xc9, 0x08, - 0xe3, 0x5b, 0x56, 0x52, 0x7f, 0x87, 0x98, 0x5b, 0xa4, 0x39, 0x0c, 0x5e, 0x86, 0x15, 0x99, 0xf1, 0x7e, 0x5f, 0xce, - 0x64, 0x54, 0xce, 0xc4, 0x61, 0x19, 0x29, 0xb0, 0xb6, 0x7d, 0x22, 0xa0, 0x7b, 0x25, 0x40, 0xbe, 0x00, 0xa8, 0xba, - 0x4f, 0xf8, 0x73, 0x9f, 0xd4, 0xa7, 0x53, 0xe8, 0x53, 0x68, 0xeb, 0x15, 0x57, 0x10, 0xaf, 0xea, 0xc6, 0xc8, 0x36, - 0x2a, 0x68, 0xf1, 0x58, 0x9e, 0xd5, 0x86, 0xb1, 0x39, 0xb5, 0xfe, 0xf5, 0x66, 0x83, 0x29, 0x9b, 0x0b, 0xb5, 0x0a, - 0x43, 0x12, 0x7d, 0x2c, 0xbd, 0x48, 0x22, 0x16, 0x36, 0xab, 0xb5, 0xf9, 0x4d, 0x18, 0x90, 0x4c, 0xa4, 0xb8, 0x9f, - 0x2d, 0x71, 0xee, 0xe2, 0xf1, 0xbc, 0xea, 0x6b, 0x2d, 0x2d, 0x32, 0x6d, 0xbe, 0xd5, 0x97, 0x21, 0x4d, 0x45, 0x0d, - 0x69, 0xd4, 0x99, 0x41, 0xf7, 0xed, 0xf2, 0x96, 0xd5, 0x08, 0x13, 0xe0, 0x95, 0xce, 0xa0, 0x1b, 0x8d, 0x07, 0x62, - 0x59, 0x8d, 0x8a, 0xb5, 0x10, 0x08, 0x3c, 0x0c, 0x39, 0x66, 0x96, 0x90, 0x64, 0x9f, 0xf8, 0x77, 0x2a, 0xce, 0x42, - 0x11, 0xdf, 0x18, 0x64, 0xef, 0xca, 0xba, 0x76, 0xd7, 0x91, 0x9f, 0x13, 0x0b, 0xab, 0xfd, 0x87, 0xe6, 0x51, 0x6b, - 0x9c, 0x05, 0xb4, 0x35, 0xad, 0x6e, 0x38, 0xdc, 0xa3, 0x3a, 0x16, 0xa5, 0xc1, 0x26, 0xf6, 0xc8, 0x72, 0xd1, 0x3a, - 0x66, 0xd0, 0x80, 0xfe, 0x36, 0xbb, 0x5a, 0x5f, 0x21, 0x80, 0x5b, 0x89, 0xac, 0x93, 0x54, 0xfe, 0x25, 0xed, 0x51, - 0xd7, 0xf6, 0x54, 0xfe, 0xb7, 0x6d, 0xaa, 0x1c, 0x5a, 0x4c, 0x79, 0xec, 0xe6, 0x2c, 0x50, 0x1d, 0x09, 0xa2, 0x40, - 0x6d, 0xbd, 0x60, 0xea, 0x9d, 0x32, 0x45, 0x07, 0x08, 0x74, 0x61, 0xce, 0xb0, 0x2f, 0x38, 0x62, 0xcc, 0x52, 0x89, - 0xc1, 0xd4, 0xc7, 0x18, 0xd5, 0xb4, 0x56, 0x80, 0xae, 0x9f, 0x6e, 0xe0, 0x4f, 0x54, 0xd4, 0x68, 0xa8, 0x35, 0x92, - 0x42, 0xd1, 0x44, 0x85, 0x22, 0x4b, 0x0b, 0x1d, 0x57, 0xa1, 0x93, 0x48, 0x58, 0x02, 0x1a, 0x26, 0x44, 0x27, 0x15, - 0x78, 0x6b, 0x00, 0x67, 0x3e, 0x2e, 0xca, 0x75, 0xa1, 0x0d, 0xe6, 0x7e, 0x88, 0xaf, 0xf9, 0xcb, 0x67, 0xce, 0xa8, - 0xbe, 0x65, 0xad, 0xef, 0x69, 0x41, 0x7e, 0x08, 0x39, 0x45, 0x07, 0x26, 0x76, 0xb2, 0x41, 0x63, 0x8c, 0xb2, 0xd6, - 0x51, 0x2f, 0xde, 0xe8, 0x50, 0x2c, 0xda, 0x04, 0xef, 0x1e, 0x4f, 0x11, 0x6d, 0x78, 0x28, 0x8c, 0x55, 0x35, 0x3e, - 0x95, 0xac, 0xa5, 0x07, 0x2b, 0x78, 0xba, 0x4e, 0x78, 0x08, 0x7a, 0x24, 0xc2, 0x4e, 0xc2, 0x62, 0x1e, 0x2f, 0xe0, - 0x38, 0x29, 0x08, 0xa8, 0x1d, 0xf4, 0x15, 0x7c, 0xbe, 0x40, 0xf7, 0x57, 0x89, 0x1e, 0x60, 0x68, 0x41, 0xdc, 0x8c, - 0x82, 0x3a, 0xba, 0x8a, 0x57, 0x0d, 0x15, 0x09, 0x9f, 0x17, 0x60, 0x3b, 0xa4, 0xd4, 0x53, 0xa0, 0x85, 0x4a, 0x94, - 0x7e, 0x18, 0xf8, 0x0e, 0x8d, 0x81, 0xad, 0x75, 0x80, 0x86, 0x7e, 0xc6, 0x34, 0xb5, 0xce, 0x50, 0xf9, 0xcc, 0xbb, - 0x67, 0x46, 0xcb, 0x99, 0x45, 0x63, 0xd0, 0xb7, 0xd1, 0x14, 0xc5, 0x39, 0xf9, 0x2c, 0x28, 0xe2, 0x34, 0x8b, 0x73, - 0xf0, 0xdb, 0x8c, 0x0b, 0xcc, 0x98, 0xc4, 0x15, 0xbf, 0x94, 0x05, 0x68, 0xbb, 0x73, 0x95, 0x5a, 0xd7, 0x20, 0x20, - 0xfb, 0x01, 0xac, 0x5e, 0x1a, 0x3a, 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x62, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, - 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x76, 0xfb, - 0x8f, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, 0x31, 0xf6, 0x8f, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, - 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, - 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, - 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, 0x58, 0x87, 0x9b, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, - 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, - 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, 0x14, 0x36, 0xc5, 0x76, 0xab, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, - 0x51, 0xfc, 0x07, 0xf7, 0xc2, 0x4e, 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x0f, 0x0e, 0x17, 0x89, 0xef, 0xa4, - 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x8e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, - 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, - 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, - 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, - 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, 0x71, 0xac, 0x89, 0x6a, 0xc1, 0xf7, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, - 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, - 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, - 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, - 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, - 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0xfb, 0x87, 0x84, 0xaa, 0xb8, 0x37, 0xbc, - 0x1d, 0xf7, 0xc6, 0x09, 0xbf, 0xe6, 0x62, 0xa1, 0x43, 0xb5, 0x98, 0x4b, 0x96, 0xdf, 0x5a, 0xef, 0x96, 0x24, 0xb5, - 0x02, 0xda, 0x67, 0x59, 0x50, 0x13, 0x01, 0x20, 0x7f, 0xf8, 0x0b, 0x84, 0xce, 0xf0, 0xb7, 0xc7, 0xe0, 0x8a, 0x14, - 0xee, 0x1d, 0x02, 0x61, 0x4d, 0x37, 0x77, 0x6a, 0x03, 0xbe, 0x18, 0xf7, 0x67, 0x4c, 0x3d, 0xfd, 0x36, 0x93, 0xbb, - 0xba, 0x6e, 0x8f, 0x2c, 0xc3, 0x47, 0xb8, 0x52, 0x00, 0x37, 0x13, 0xfe, 0x62, 0x98, 0x49, 0xf5, 0x09, 0x60, 0xaa, - 0xe9, 0xe0, 0x3e, 0x41, 0x60, 0x00, 0x95, 0x68, 0x31, 0xba, 0x56, 0x8e, 0x68, 0x06, 0x6e, 0x4d, 0xb7, 0xc2, 0x78, - 0xeb, 0x41, 0x0b, 0x3d, 0xd3, 0x70, 0xe2, 0x3f, 0x68, 0xe6, 0x55, 0x01, 0x01, 0xb4, 0x32, 0x82, 0xb7, 0xd6, 0x47, - 0x73, 0x84, 0xf8, 0x84, 0x25, 0xd1, 0x84, 0xc5, 0x33, 0xc5, 0x8f, 0x09, 0xdd, 0x34, 0xb5, 0x4d, 0x1f, 0x90, 0xfe, - 0xe2, 0x9a, 0xf5, 0x53, 0x96, 0xb5, 0x6f, 0x0f, 0x15, 0x2f, 0xa6, 0xcd, 0x38, 0x88, 0x89, 0x2a, 0xc6, 0xff, 0x82, - 0xfb, 0x52, 0x2b, 0x40, 0x64, 0xee, 0xaa, 0xa7, 0xdf, 0x6f, 0x66, 0xcb, 0x81, 0x50, 0xf9, 0x9d, 0x41, 0xd2, 0xa7, - 0x43, 0xfb, 0x81, 0x4d, 0xa2, 0xb6, 0xd0, 0xf3, 0xc7, 0xa5, 0x6e, 0xe2, 0xe5, 0xb5, 0xa9, 0x11, 0xad, 0x90, 0xa1, - 0xb2, 0x75, 0xc0, 0xfa, 0xfe, 0x21, 0xdc, 0x5d, 0xd4, 0x34, 0xd4, 0xba, 0xe7, 0xae, 0x45, 0xc1, 0x89, 0x3f, 0xc0, - 0x58, 0x5c, 0x48, 0x6a, 0x1d, 0x8f, 0x49, 0x3f, 0x5a, 0xc8, 0xe4, 0x46, 0x5d, 0x9d, 0x9c, 0x29, 0xe6, 0x09, 0x5c, - 0x80, 0xcb, 0xb6, 0xbf, 0xa2, 0x52, 0x97, 0x72, 0x7b, 0x45, 0x69, 0x7a, 0x48, 0xdb, 0xab, 0x38, 0x6f, 0x0b, 0x2e, - 0xf8, 0x17, 0x0a, 0x2e, 0xac, 0x83, 0x75, 0xc7, 0x9d, 0xb2, 0x27, 0x3c, 0x51, 0xa6, 0xb5, 0xc1, 0x5d, 0x37, 0x18, - 0x13, 0x63, 0xbf, 0xbb, 0xe4, 0xc9, 0x47, 0x64, 0xc1, 0xbf, 0xcb, 0x04, 0x78, 0x26, 0xbb, 0x57, 0x2a, 0xff, 0x0f, - 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xb9, 0x92, - 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0xbd, 0x04, - 0x6e, 0xba, 0xbf, 0x36, 0x33, 0x73, 0xba, 0x56, 0xa2, 0xe9, 0xd2, 0xd8, 0x5a, 0x96, 0x2a, 0x8c, 0xf7, 0xbd, 0x27, - 0xd9, 0x34, 0x3f, 0x5e, 0x4e, 0x73, 0x4b, 0xdd, 0x36, 0x6e, 0xd9, 0x00, 0x1a, 0x62, 0xd7, 0xda, 0xca, 0x01, 0x2f, - 0xb7, 0x07, 0xd1, 0x7c, 0xad, 0x08, 0x3d, 0x55, 0x22, 0xf4, 0x69, 0xda, 0xec, 0x83, 0x5d, 0x55, 0xeb, 0x46, 0xc8, - 0xa3, 0x41, 0xaa, 0x19, 0xf9, 0x37, 0xd7, 0xbc, 0xb8, 0xc8, 0xe5, 0x0d, 0xc0, 0x21, 0x93, 0xda, 0x28, 0x2c, 0xaf, - 0xc0, 0x9d, 0x1f, 0x1d, 0xc7, 0x99, 0x18, 0xe5, 0x18, 0xb7, 0x15, 0x91, 0x92, 0x75, 0xe2, 0x0c, 0xf0, 0x90, 0xfd, - 0x49, 0xd3, 0xa1, 0x5d, 0x0b, 0x0c, 0xef, 0x0b, 0xdc, 0x55, 0xce, 0x4e, 0x36, 0xb9, 0x5d, 0xf4, 0xcd, 0x19, 0xd6, - 0x1d, 0x29, 0xad, 0x8d, 0x45, 0xd7, 0x1d, 0xac, 0x35, 0x83, 0xb6, 0x08, 0x25, 0x1f, 0x72, 0x27, 0xed, 0xa7, 0x80, - 0x06, 0x67, 0x59, 0x7a, 0x6b, 0xad, 0xf2, 0x37, 0x5a, 0x88, 0x13, 0xc5, 0xd4, 0x89, 0x6f, 0xa2, 0x44, 0x9f, 0x9f, - 0x89, 0x71, 0x03, 0x81, 0xd4, 0x1f, 0x30, 0xbe, 0x46, 0x11, 0x26, 0x70, 0x1d, 0x88, 0x62, 0x7b, 0xa2, 0x36, 0x96, - 0x23, 0xe8, 0x84, 0x10, 0xef, 0xa0, 0x0c, 0x63, 0x75, 0x71, 0xa0, 0x0d, 0x96, 0xbe, 0x6e, 0xad, 0x73, 0x43, 0x28, - 0x8c, 0x13, 0x98, 0x62, 0x90, 0xd4, 0x59, 0x67, 0x99, 0xa0, 0xca, 0x8e, 0x49, 0xe7, 0x7d, 0x80, 0xee, 0xae, 0x45, - 0x53, 0x7c, 0xdd, 0xb9, 0x83, 0xf6, 0x71, 0xfd, 0x5a, 0x8b, 0xdc, 0xe0, 0xcf, 0x5b, 0x22, 0x2c, 0x02, 0x67, 0xad, - 0xc9, 0x57, 0x8d, 0x70, 0x60, 0x4a, 0x32, 0x0d, 0x7b, 0xb9, 0xb2, 0xe9, 0xde, 0x6e, 0x7b, 0xbd, 0xbd, 0x22, 0xae, - 0x1e, 0x63, 0x95, 0x77, 0x33, 0xb7, 0x77, 0xaa, 0xb5, 0xd8, 0xbd, 0x69, 0xfb, 0x29, 0x76, 0xd4, 0x5a, 0xbb, 0xdd, - 0x70, 0x42, 0x0d, 0xf9, 0x56, 0x54, 0x69, 0x75, 0xba, 0x31, 0x68, 0x87, 0xd0, 0xd6, 0x22, 0x83, 0x1b, 0xe5, 0x33, - 0x27, 0x74, 0x52, 0x21, 0x57, 0x9d, 0xba, 0x60, 0x73, 0xc5, 0xab, 0xa5, 0x4c, 0x23, 0x41, 0xd1, 0xe6, 0x3c, 0x2a, - 0x69, 0x22, 0xd7, 0xa2, 0x8a, 0x64, 0x8d, 0x7a, 0x51, 0xab, 0x31, 0x40, 0x40, 0xa6, 0xb3, 0xa6, 0x07, 0x55, 0x30, - 0x1b, 0xca, 0x48, 0x4e, 0x5f, 0x80, 0xa5, 0x3d, 0x72, 0xac, 0xf5, 0xbe, 0x3a, 0x5b, 0x7c, 0xab, 0x27, 0x04, 0x53, - 0x98, 0x3d, 0x10, 0x11, 0xae, 0x69, 0x0c, 0x39, 0xed, 0x12, 0x97, 0x35, 0xdd, 0x12, 0xf6, 0x70, 0xbb, 0x92, 0x9d, - 0xb8, 0x79, 0xd2, 0xdc, 0x5c, 0xc1, 0x4e, 0x8a, 0xf9, 0x18, 0xb4, 0x5f, 0x52, 0x5d, 0xbb, 0x34, 0xb7, 0x1e, 0x0f, - 0x02, 0x1a, 0x0c, 0x0a, 0xc3, 0xbf, 0x4e, 0x8c, 0x87, 0x27, 0x0d, 0x08, 0x92, 0x72, 0x11, 0x8e, 0x7d, 0x23, 0xfa, - 0xc9, 0x54, 0x1e, 0x73, 0xb4, 0x78, 0x87, 0x56, 0xe7, 0x10, 0xd0, 0x4b, 0x84, 0x92, 0x18, 0x55, 0xa1, 0x11, 0x41, - 0x79, 0x5a, 0xfe, 0x52, 0x55, 0x87, 0x80, 0x42, 0xda, 0x57, 0x14, 0xca, 0x36, 0x89, 0xa1, 0x19, 0x7e, 0x39, 0x9f, - 0x2c, 0xf4, 0x0c, 0x0c, 0xe4, 0xfc, 0x68, 0xa1, 0x67, 0x61, 0x20, 0xe7, 0x8f, 0x16, 0xb5, 0x5b, 0x07, 0x9a, 0x80, - 0x78, 0x2e, 0x1c, 0x9d, 0x94, 0x56, 0x65, 0x0b, 0xe8, 0xe6, 0x3e, 0x82, 0xfe, 0x0f, 0x7b, 0x08, 0x3a, 0xb9, 0xd0, - 0x8e, 0xdc, 0x80, 0xb6, 0x43, 0x12, 0xd8, 0x2b, 0x26, 0x15, 0x26, 0x16, 0xd1, 0x31, 0x1b, 0x83, 0x21, 0xb6, 0xfa, - 0xe0, 0x98, 0x8d, 0xa7, 0x3e, 0x09, 0x02, 0x46, 0xf7, 0x07, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, 0x93, 0x8d, 0x40, - 0x37, 0x7d, 0x77, 0x37, 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, 0xd5, 0x6b, 0x88, - 0x1b, 0xf2, 0x2b, 0xa3, 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, 0xea, 0xd6, 0xb3, - 0x01, 0x19, 0x66, 0x7a, 0xcb, 0x64, 0x7d, 0x0f, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, 0xf7, 0x0f, 0xbe, - 0xc9, 0xf8, 0x99, 0xc3, 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, - 0xc9, 0xe7, 0x59, 0x28, 0x6f, 0xbc, 0xa6, 0xff, 0x51, 0xe9, 0xcd, 0x0e, 0x87, 0x9c, 0xae, 0x60, 0xc5, 0xcd, 0xaa, - 0xd0, 0xf0, 0xb3, 0xc8, 0x1b, 0x47, 0xbc, 0x26, 0x51, 0xd5, 0x7d, 0xde, 0xdb, 0x88, 0xa5, 0x1d, 0xe3, 0x00, 0xe0, - 0x44, 0xad, 0x1a, 0x76, 0xa5, 0x71, 0xad, 0x0e, 0x62, 0x44, 0x4a, 0xd8, 0x2a, 0x71, 0x24, 0x94, 0xbf, 0x01, 0x08, - 0x8b, 0xa1, 0x38, 0xde, 0x1a, 0xd6, 0x7b, 0xd8, 0x0f, 0x5d, 0xa0, 0x69, 0x4e, 0xa9, 0x66, 0x00, 0x90, 0x04, 0xfc, - 0xd1, 0xd3, 0x4d, 0x43, 0x65, 0x9b, 0xe7, 0xa1, 0x65, 0x75, 0x05, 0xf7, 0xf4, 0xd4, 0x95, 0x0c, 0x8c, 0xab, 0x3a, - 0xf6, 0x36, 0xfb, 0xdb, 0xa3, 0x55, 0xe4, 0x3b, 0x9b, 0xd4, 0x34, 0x0b, 0x20, 0x45, 0xe3, 0xd2, 0x17, 0x7a, 0x3a, - 0x01, 0x5a, 0xaf, 0x2d, 0x15, 0xed, 0xf7, 0x51, 0x8c, 0x1a, 0x17, 0x0a, 0xac, 0xc2, 0x04, 0x85, 0x43, 0x84, 0x11, - 0x42, 0x7f, 0x2e, 0xc3, 0x8d, 0x2f, 0xc8, 0x20, 0x1a, 0xae, 0x45, 0x87, 0x22, 0x72, 0xbc, 0x68, 0x5b, 0xaa, 0x6a, - 0x4e, 0x9a, 0xb6, 0x04, 0xde, 0x44, 0x06, 0x6c, 0xe7, 0x9f, 0x36, 0x44, 0xae, 0xc2, 0x05, 0x0c, 0xdf, 0x11, 0xd7, - 0x82, 0xe8, 0xa6, 0x36, 0xf5, 0x36, 0xec, 0x10, 0x1d, 0x4d, 0xf1, 0xe8, 0x90, 0x7b, 0xee, 0x9e, 0xdb, 0x22, 0xbe, - 0xf9, 0x0c, 0xb9, 0x6b, 0x3a, 0x7b, 0x29, 0xc2, 0xa0, 0x6e, 0xd9, 0x40, 0xb1, 0x8e, 0x9d, 0xa0, 0x00, 0x03, 0xb8, - 0x7c, 0x02, 0x3a, 0x36, 0x18, 0x54, 0x04, 0x9f, 0x14, 0xb6, 0x4d, 0x83, 0xfc, 0x11, 0xef, 0x86, 0x0e, 0xaf, 0x2d, - 0x79, 0x20, 0x5e, 0x61, 0x9f, 0x29, 0x61, 0xff, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, - 0xd9, 0xf1, 0x5c, 0x6b, 0x4a, 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, - 0x51, 0xe5, 0xb1, 0x44, 0x91, 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, - 0xb4, 0xcb, 0x96, 0xb9, 0x04, 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x1d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, - 0x31, 0x5e, 0x5f, 0x46, 0x4d, 0xbf, 0x78, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, - 0x94, 0x9f, 0xb0, 0xf1, 0x74, 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x02, 0x5a, 0x67, 0x26, 0xae, - 0xf1, 0x69, 0xfb, 0x0a, 0x5a, 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, - 0xa9, 0x64, 0x9f, 0x96, 0xd6, 0x61, 0xdf, 0x2e, 0x14, 0x5a, 0x68, 0xe2, 0x57, 0x19, 0xe2, 0xa7, 0xae, 0x33, 0xff, - 0x36, 0xed, 0x53, 0x83, 0x58, 0x38, 0x12, 0x83, 0x88, 0x5f, 0x9c, 0x2a, 0xdb, 0x09, 0xa1, 0x62, 0xe3, 0xa1, 0x6b, - 0xdd, 0x38, 0x92, 0x2a, 0x0c, 0xa5, 0xd0, 0x78, 0x6a, 0xb8, 0xef, 0x85, 0x0e, 0x5f, 0x87, 0x59, 0xdc, 0x66, 0x8d, - 0xa4, 0xc6, 0x38, 0x15, 0x26, 0x4e, 0xa5, 0x5c, 0x45, 0x02, 0x03, 0xe5, 0xd9, 0xc2, 0x20, 0xc0, 0x24, 0x26, 0x19, - 0x5b, 0x0b, 0x61, 0xc2, 0xd8, 0xb9, 0xc2, 0x34, 0x75, 0x91, 0xfa, 0xcd, 0xc0, 0x64, 0x41, 0x43, 0x7e, 0x8f, 0x46, - 0x6b, 0xaa, 0xa6, 0x00, 0xc3, 0x38, 0x4a, 0x35, 0xfe, 0x2d, 0x42, 0x6d, 0x86, 0x01, 0x80, 0x6d, 0xde, 0xca, 0x4c, - 0x54, 0x2f, 0x05, 0x42, 0xa0, 0x39, 0xfb, 0xa9, 0xb8, 0xda, 0x99, 0x05, 0xa3, 0x68, 0xb7, 0x57, 0x3e, 0x1f, 0x38, - 0xa1, 0x3c, 0x55, 0x17, 0xa8, 0x17, 0xb2, 0x78, 0x25, 0x53, 0xde, 0x0a, 0x91, 0x79, 0x20, 0xd9, 0x4f, 0xf9, 0x08, - 0xce, 0x2b, 0x74, 0x2a, 0x37, 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, - 0xf0, 0x6b, 0x88, 0x33, 0xb6, 0x73, 0x12, 0x6e, 0xf6, 0xf3, 0xc0, 0x10, 0xa5, 0x5c, 0xb4, 0x44, 0xc3, 0xd6, 0x8e, - 0xd7, 0x93, 0x6b, 0xc2, 0x7d, 0xd8, 0x88, 0x35, 0x19, 0x63, 0x5c, 0x9b, 0x1b, 0x59, 0x3f, 0x5a, 0xe0, 0xc1, 0x98, - 0xb2, 0xfe, 0x04, 0x32, 0xad, 0xa4, 0xac, 0xf3, 0x85, 0x11, 0x33, 0xa9, 0x44, 0xef, 0xf6, 0x8d, 0xcf, 0xea, 0x2e, - 0xa2, 0x7e, 0x6b, 0xbf, 0x27, 0xf5, 0x70, 0xe7, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, - 0x37, 0x4d, 0x8a, 0x38, 0x3d, 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, - 0x24, 0x49, 0xd6, 0xd2, 0xd8, 0x8a, 0x5d, 0x1a, 0xa4, 0x67, 0x6f, 0xc4, 0xa5, 0x17, 0x15, 0x1a, 0xd2, 0x52, 0xef, - 0x2c, 0x54, 0x32, 0x7f, 0xc5, 0x7f, 0x06, 0xb5, 0x02, 0x1d, 0x6d, 0x52, 0x8c, 0xa7, 0xc0, 0x88, 0xef, 0x06, 0xb3, - 0xba, 0x87, 0xb8, 0x68, 0x82, 0x52, 0xef, 0x88, 0x1d, 0x3f, 0x37, 0x79, 0x78, 0x17, 0x72, 0xce, 0xe0, 0xd3, 0xfb, - 0x59, 0xa2, 0xd6, 0x3a, 0x12, 0x23, 0x35, 0x03, 0x68, 0x3a, 0x28, 0x73, 0x1e, 0x8b, 0x60, 0xd6, 0x33, 0x89, 0x51, - 0x8f, 0xeb, 0x5f, 0xa0, 0xa1, 0xf6, 0x9b, 0x95, 0xe5, 0x59, 0x75, 0xf7, 0x25, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, - 0x75, 0x25, 0x2f, 0x2f, 0x55, 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, - 0x37, 0x8b, 0xbb, 0x59, 0x46, 0x03, 0x61, 0x6d, 0xe7, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, - 0x00, 0x10, 0xe9, 0x41, 0x14, 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xee, 0xe3, 0x28, 0x0b, 0xa5, 0x97, 0xb3, 0x8c, 0x9f, - 0x36, 0x8d, 0xb5, 0xce, 0x0a, 0x65, 0x68, 0x6d, 0x74, 0xa7, 0xab, 0x0c, 0xb1, 0xfd, 0x24, 0xce, 0x16, 0xe0, 0xfe, - 0x98, 0xa1, 0xd0, 0xd0, 0x59, 0x46, 0x9a, 0x68, 0xf8, 0xae, 0x3d, 0x83, 0x8c, 0xe2, 0x64, 0x9d, 0x57, 0xd2, 0x8d, - 0x3e, 0x6b, 0x23, 0x61, 0xee, 0x21, 0xfa, 0x55, 0x0c, 0x1e, 0xe5, 0x3e, 0xaf, 0x8d, 0x4e, 0xa6, 0x65, 0xa4, 0xdd, - 0xf9, 0x49, 0xbd, 0xcc, 0x52, 0xad, 0xc3, 0xf6, 0x19, 0xf6, 0xd6, 0x98, 0xf4, 0x26, 0xa4, 0x86, 0x91, 0xf8, 0x7c, - 0x46, 0x8d, 0x10, 0xd0, 0x96, 0xe3, 0xef, 0xf0, 0x19, 0x86, 0xa6, 0xc0, 0x52, 0xc5, 0x2d, 0xec, 0x86, 0xaf, 0xf9, - 0x64, 0xd5, 0x02, 0x10, 0xcc, 0xca, 0xd7, 0xbb, 0x78, 0x25, 0xd4, 0x67, 0xda, 0x0c, 0x00, 0x59, 0x50, 0xca, 0x1d, - 0x3f, 0xa5, 0xd2, 0xc1, 0x12, 0x45, 0xdb, 0xcb, 0xe9, 0x1b, 0x1d, 0x1b, 0xdf, 0xa7, 0xe7, 0x02, 0xb6, 0x0b, 0xf9, - 0xad, 0xbd, 0x7a, 0x89, 0x8a, 0xd4, 0xb6, 0x59, 0xf7, 0xf0, 0xe5, 0x06, 0x4d, 0xc2, 0x08, 0xca, 0x94, 0x29, 0x80, - 0xc1, 0x4d, 0x35, 0x0a, 0x26, 0xad, 0x46, 0xc2, 0x96, 0x7a, 0x92, 0xe5, 0xa6, 0x0f, 0x4e, 0xb5, 0x47, 0xd0, 0x73, - 0xab, 0x9c, 0x2f, 0x5a, 0xf6, 0x6b, 0x05, 0x47, 0x27, 0x57, 0x43, 0xd4, 0xcc, 0x7b, 0x6d, 0x47, 0x86, 0x94, 0xcb, - 0x30, 0x10, 0x4c, 0x39, 0xe6, 0xe9, 0xb1, 0xf5, 0x8c, 0x88, 0xee, 0x39, 0xfb, 0x4c, 0xb7, 0xea, 0x4a, 0x02, 0xa2, - 0xe3, 0x37, 0x8f, 0x5f, 0x5e, 0xc5, 0x97, 0x06, 0x45, 0xa9, 0x61, 0x11, 0xa3, 0x4c, 0xfb, 0x2a, 0x09, 0x83, 0xf7, - 0xcb, 0xbb, 0x9f, 0x54, 0x96, 0xda, 0xef, 0xc1, 0xc6, 0x8a, 0xaa, 0x7e, 0x29, 0x79, 0xd1, 0x14, 0x60, 0xed, 0xb3, - 0x44, 0x81, 0xdc, 0xef, 0x6c, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, 0x6d, 0xc9, 0x8e, - 0xac, 0x44, 0xce, 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x0d, 0xaa, 0x52, 0xf1, 0x7b, 0x23, 0x82, 0x53, - 0xc7, 0xaa, 0xc2, 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, 0xfd, 0xce, 0x0a, - 0x6a, 0x7e, 0xff, 0xd3, 0x18, 0xf2, 0x35, 0xa5, 0xa0, 0x92, 0x80, 0x9d, 0x41, 0xa3, 0xa7, 0x4a, 0x18, 0x48, 0x41, - 0xf0, 0x04, 0x28, 0x5f, 0x44, 0x8d, 0xd5, 0x6e, 0x5f, 0x9d, 0x1a, 0xa3, 0x2d, 0x20, 0xb4, 0x90, 0x1e, 0x5d, 0xf6, - 0x71, 0x1b, 0xeb, 0x40, 0xe2, 0xc1, 0x09, 0xb6, 0x73, 0x75, 0x8d, 0x46, 0x42, 0xf3, 0xfb, 0x46, 0x03, 0x5e, 0xd3, - 0x0a, 0x14, 0xea, 0x39, 0x8e, 0x86, 0xce, 0x0e, 0x29, 0x88, 0xd8, 0xa0, 0x85, 0x7d, 0x7b, 0x3e, 0x34, 0xfb, 0x7a, - 0x9e, 0x2c, 0x48, 0x4d, 0xa5, 0xfb, 0xdc, 0x2d, 0x21, 0x6b, 0xd5, 0xa1, 0xac, 0x3c, 0xc0, 0xf1, 0x42, 0xc9, 0xfc, - 0x1d, 0x26, 0x35, 0x4a, 0x63, 0x42, 0x63, 0xc4, 0x02, 0x96, 0x04, 0xed, 0xf5, 0x40, 0xfd, 0x32, 0x08, 0x15, 0xce, - 0xf4, 0x44, 0xe2, 0x53, 0xca, 0xd5, 0xa7, 0x05, 0xa9, 0xa7, 0x05, 0x73, 0xa0, 0x97, 0xbe, 0x95, 0x5f, 0xd9, 0xf8, - 0x68, 0x77, 0xef, 0x9a, 0x0b, 0xeb, 0x18, 0xe2, 0x62, 0x0b, 0xbf, 0x39, 0x35, 0x05, 0x60, 0xc3, 0x53, 0x5d, 0x96, - 0x6f, 0xd4, 0x44, 0x66, 0x71, 0x48, 0x22, 0x90, 0x6c, 0x37, 0x37, 0xb7, 0x11, 0x6c, 0x7b, 0x0b, 0xb5, 0xa1, 0xfe, - 0xf2, 0xb6, 0xfb, 0x9e, 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xc3, 0xfe, 0x55, 0xf2, 0x7f, 0x55, 0xc9, - 0x7e, 0xab, 0xcc, 0xba, 0x2d, 0xde, 0xef, 0x3a, 0x6e, 0x39, 0x46, 0x83, 0xc0, 0x9a, 0x02, 0x03, 0xe9, 0x49, 0x63, - 0x9a, 0xe8, 0xe8, 0xca, 0x8c, 0x19, 0x3c, 0xba, 0x00, 0xcd, 0x61, 0x3a, 0xcf, 0x63, 0x00, 0x0e, 0xf0, 0x8f, 0x3c, - 0x42, 0xfd, 0xd3, 0x79, 0x1e, 0x9c, 0x05, 0x83, 0x72, 0x10, 0xe8, 0x4f, 0x5c, 0x73, 0x82, 0x05, 0xe8, 0xdc, 0x62, - 0x06, 0x71, 0x27, 0xad, 0x99, 0x43, 0x7c, 0x9c, 0x4c, 0x07, 0x83, 0x98, 0x6c, 0x00, 0xa4, 0x2f, 0x5e, 0x58, 0xe7, - 0xa0, 0x42, 0x2f, 0xc8, 0x56, 0xdd, 0x45, 0xb3, 0x62, 0xaf, 0xda, 0x69, 0xde, 0xef, 0xe7, 0xf3, 0x72, 0x10, 0x34, - 0x2a, 0x2c, 0x8c, 0xf7, 0x1f, 0x6d, 0x7e, 0x69, 0x74, 0xd2, 0x04, 0x23, 0xd6, 0x9e, 0xa2, 0x7a, 0xc5, 0xd3, 0x8c, - 0x36, 0x6e, 0xc7, 0x4a, 0xf9, 0x02, 0xa2, 0x78, 0x60, 0xc8, 0x5a, 0x79, 0x77, 0x0e, 0x5e, 0x97, 0x1b, 0x6f, 0x8e, - 0x28, 0xc0, 0x6e, 0x0a, 0xe3, 0xa4, 0xe6, 0xa2, 0x8b, 0x9a, 0x78, 0x06, 0x3b, 0x5d, 0xbd, 0x95, 0x68, 0x35, 0xde, - 0x8b, 0x77, 0xcd, 0xc6, 0x5f, 0xcb, 0x03, 0x5d, 0xe6, 0xc1, 0x05, 0x20, 0xce, 0x1e, 0xc4, 0xd5, 0x01, 0x96, 0x7a, - 0x10, 0x0c, 0x2c, 0x72, 0x48, 0xbb, 0x5a, 0x3d, 0x14, 0x91, 0x3a, 0x8f, 0xc1, 0x80, 0xc9, 0x34, 0xa4, 0x26, 0xd3, - 0x5e, 0xac, 0x20, 0x6d, 0xac, 0xb5, 0x80, 0x36, 0x1c, 0x16, 0x3b, 0x76, 0xc3, 0xee, 0x74, 0xeb, 0x50, 0x28, 0x61, - 0x20, 0xeb, 0xba, 0x79, 0xa8, 0x35, 0x3c, 0x11, 0xf4, 0xa0, 0x1a, 0xed, 0xa7, 0x87, 0xf2, 0xa4, 0x3d, 0x16, 0xe0, - 0xa2, 0x87, 0x2f, 0x9f, 0x0b, 0xbc, 0x68, 0xef, 0x20, 0xcf, 0x99, 0x4f, 0x95, 0x0f, 0x62, 0xc3, 0x2d, 0xc3, 0x87, - 0xf6, 0xf1, 0xad, 0x40, 0x26, 0x75, 0x47, 0x53, 0x5b, 0xbb, 0xa3, 0x71, 0x4c, 0xa0, 0xdf, 0x94, 0xa3, 0x94, 0x89, - 0xa9, 0x65, 0xc9, 0x4e, 0x7a, 0xb9, 0xf2, 0x86, 0x4a, 0xd9, 0xc9, 0xb2, 0xcd, 0xf9, 0xa5, 0x8d, 0x84, 0x7e, 0x5f, - 0xbb, 0x03, 0xe1, 0x1b, 0xb5, 0xde, 0x90, 0x97, 0x0d, 0x11, 0xcb, 0x21, 0x66, 0xe0, 0x78, 0x21, 0x95, 0x6b, 0x77, - 0xd1, 0x54, 0xd5, 0xed, 0x6c, 0xe5, 0x82, 0x96, 0x78, 0x2b, 0x05, 0x56, 0x91, 0x3a, 0xbd, 0x9e, 0x4a, 0xdc, 0xf7, - 0x51, 0x6c, 0x3f, 0x02, 0xb6, 0xb1, 0x71, 0x34, 0x36, 0x6e, 0x11, 0x1b, 0x7c, 0x15, 0x55, 0xb4, 0xe0, 0x00, 0xc1, - 0xdd, 0x96, 0xd4, 0xd2, 0xcc, 0x21, 0xee, 0x2b, 0x1e, 0xa0, 0x7d, 0x17, 0x47, 0x9c, 0x0a, 0xb0, 0xad, 0x6b, 0x9d, - 0xb3, 0x5a, 0x0e, 0xd8, 0x4c, 0xf4, 0xfc, 0xd3, 0xaa, 0x91, 0x88, 0x61, 0x95, 0x8d, 0x94, 0x15, 0xda, 0xbd, 0xd2, - 0x25, 0x5c, 0x7c, 0x01, 0x5e, 0xb6, 0xf7, 0x2b, 0xbb, 0xcf, 0x96, 0xd8, 0x3f, 0xcc, 0xab, 0x26, 0x78, 0xe4, 0x35, - 0xde, 0xde, 0xc3, 0xc4, 0x97, 0x4a, 0x21, 0xbc, 0x4a, 0x69, 0x28, 0x01, 0x18, 0x24, 0x41, 0x0d, 0x57, 0xda, 0x36, - 0x83, 0x54, 0xc6, 0xb0, 0xbb, 0xd5, 0x5b, 0xfd, 0x9f, 0x56, 0xe1, 0xa2, 0x92, 0xc5, 0x98, 0x04, 0x3a, 0xa7, 0x5a, - 0x6e, 0x02, 0x0b, 0x9e, 0xed, 0x92, 0x23, 0x50, 0xd8, 0x09, 0xe0, 0x86, 0x12, 0xf6, 0x4f, 0xbc, 0x0d, 0xe5, 0xec, - 0xb5, 0x95, 0x3c, 0xb9, 0x7d, 0x49, 0x05, 0x4d, 0xc8, 0x54, 0xd8, 0xfd, 0xdb, 0xda, 0xb0, 0xcf, 0x42, 0x39, 0x92, - 0x02, 0x17, 0x07, 0x9d, 0x03, 0xd8, 0x1f, 0xe4, 0x32, 0x36, 0x9f, 0x49, 0xbf, 0xaf, 0xde, 0x3f, 0xcd, 0xb3, 0xe4, - 0xe3, 0xce, 0x7b, 0xc3, 0xd3, 0x2c, 0x19, 0x50, 0x89, 0x98, 0x5a, 0x57, 0xc5, 0x70, 0xa9, 0x5d, 0x8c, 0x1b, 0x24, - 0x23, 0xde, 0x4b, 0x1d, 0x62, 0xc4, 0xf8, 0x22, 0x3b, 0x24, 0x25, 0xa7, 0xcb, 0xba, 0xb3, 0xe7, 0x5a, 0x34, 0x83, - 0xc6, 0x70, 0x3b, 0xde, 0x4b, 0x7a, 0x05, 0xa8, 0x00, 0xd1, 0x3d, 0x0b, 0x5c, 0xc3, 0x9b, 0x4b, 0xa2, 0xb1, 0xa5, - 0xa7, 0x2d, 0xd1, 0xc0, 0x5e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x18, 0x16, 0x00, 0xd4, 0x6a, - 0x90, 0x5e, 0xe9, 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, - 0x03, 0xfa, 0xb2, 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x87, 0xa5, - 0x49, 0x02, 0x41, 0x09, 0xca, 0x37, 0xe8, 0xbf, 0x4a, 0xcf, 0xc7, 0xf2, 0x47, 0xef, 0x50, 0xfa, 0x21, 0x2c, 0x40, - 0xa6, 0xa8, 0x2b, 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, - 0x59, 0x86, 0x38, 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, - 0x4a, 0x20, 0xca, 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, - 0xa4, 0x99, 0x5d, 0x87, 0x11, 0xa9, 0x76, 0x92, 0xcc, 0x97, 0x3f, 0xca, 0x4c, 0x78, 0xdf, 0xc0, 0x63, 0xb3, 0x59, - 0x36, 0xc5, 0x7c, 0xa1, 0x82, 0x39, 0xb8, 0x4f, 0x54, 0x5c, 0x8a, 0xca, 0x7f, 0xc2, 0x2e, 0x78, 0x31, 0x1e, 0xbc, - 0x5e, 0x23, 0xc0, 0x7e, 0xe5, 0x3f, 0x79, 0x63, 0xf6, 0xa7, 0x75, 0xe3, 0xcb, 0x4c, 0xc4, 0x07, 0x3e, 0xba, 0xa5, - 0x7c, 0x74, 0xe7, 0x65, 0xfa, 0xae, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x9d, 0x44, 0xd9, - 0xa8, 0xe2, 0x02, 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x84, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, - 0x61, 0x99, 0xa9, 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x37, 0x49, 0xf4, 0xe7, 0xd2, 0x43, 0x52, 0x33, 0x53, - 0xb6, 0xa9, 0x1d, 0xa1, 0x36, 0xbe, 0x8e, 0x74, 0xa3, 0x2d, 0x00, 0xe0, 0x9e, 0x2d, 0xd2, 0x48, 0x32, 0x31, 0x9c, - 0xd4, 0x8c, 0x9b, 0xf4, 0x02, 0x53, 0xe3, 0x9a, 0x55, 0x34, 0x71, 0x16, 0x32, 0xa0, 0xf7, 0xa7, 0xb9, 0x7e, 0xce, - 0xe0, 0xfe, 0x83, 0xd6, 0xc0, 0xe5, 0x71, 0xd1, 0xef, 0xcb, 0xe3, 0x62, 0xbb, 0x2d, 0x4f, 0xe2, 0x7e, 0x5f, 0x9e, - 0xc4, 0x86, 0x7f, 0x50, 0x8a, 0x6d, 0x63, 0x6e, 0x90, 0xd0, 0x5c, 0x42, 0xd4, 0xa2, 0x11, 0xfc, 0xa1, 0x59, 0xce, - 0x45, 0x94, 0x1f, 0x27, 0xfd, 0x7e, 0x6f, 0x39, 0x13, 0x83, 0x7c, 0x98, 0x44, 0xf9, 0x30, 0xf1, 0x9c, 0x10, 0x7f, - 0xf5, 0x9c, 0x10, 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, - 0xab, 0x5a, 0x12, 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0x7d, 0xb7, 0x04, 0x9e, 0x28, 0xe7, - 0xd5, 0x06, 0x18, 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x4d, 0x4d, 0x2f, 0xe8, 0x8a, - 0x5e, 0x22, 0x3f, 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, - 0xc2, 0xf5, 0x2c, 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x55, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x66, 0x10, 0xde, - 0x2f, 0x9d, 0x85, 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, - 0x97, 0x74, 0x45, 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, - 0x55, 0xe1, 0x5d, 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x68, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, - 0x66, 0x64, 0x24, 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, - 0xdc, 0xfd, 0x92, 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, - 0x38, 0xb0, 0x07, 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x25, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, - 0xc4, 0x2b, 0x70, 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, - 0x2b, 0x95, 0x7e, 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, - 0x17, 0xa3, 0x3b, 0x02, 0x16, 0x5e, 0xe3, 0xe9, 0xfa, 0x98, 0xc5, 0xd3, 0xc1, 0x60, 0x8d, 0x54, 0x5d, 0xe5, 0x5e, - 0x93, 0x05, 0xbd, 0xc0, 0x89, 0x20, 0xc0, 0xd0, 0x67, 0x62, 0x6d, 0x68, 0xf8, 0x53, 0x06, 0x1f, 0xdf, 0xb1, 0x8b, - 0xd1, 0x1d, 0xbd, 0x65, 0x4f, 0xb7, 0xe3, 0x29, 0x30, 0x53, 0xab, 0x59, 0x78, 0x77, 0x7c, 0x39, 0xbb, 0x64, 0x77, - 0xd1, 0xdd, 0x09, 0x34, 0xf4, 0x8a, 0xdd, 0x21, 0xe0, 0x52, 0xfa, 0x70, 0x39, 0x78, 0x4a, 0x0e, 0x07, 0x83, 0x94, - 0x44, 0xe1, 0x75, 0xe8, 0xb5, 0xf2, 0x29, 0xbd, 0x23, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, - 0xee, 0xea, 0xeb, 0xd0, 0xdb, 0xcd, 0x89, 0xe8, 0x04, 0x31, 0x42, 0x5f, 0x03, 0x47, 0xb3, 0x5c, 0x98, 0x09, 0x78, - 0x32, 0x17, 0x19, 0x2d, 0x0a, 0xcd, 0x40, 0x9c, 0x95, 0x80, 0x58, 0x12, 0x75, 0xbf, 0xd9, 0xe8, 0x0c, 0x96, 0x73, - 0xbf, 0xdf, 0xab, 0x0c, 0x3d, 0x40, 0xe4, 0xcc, 0x4e, 0x7a, 0xd0, 0xf3, 0xe9, 0x01, 0x7e, 0xa2, 0x57, 0x0d, 0xe2, - 0x64, 0xfe, 0xb0, 0x8c, 0x7e, 0xf5, 0xe8, 0xc3, 0x2f, 0xdd, 0x94, 0xa7, 0xcc, 0xff, 0x7d, 0xca, 0x23, 0xf3, 0xe8, - 0x55, 0xe5, 0x81, 0xe0, 0x79, 0x6b, 0x52, 0x69, 0x24, 0xaa, 0xd1, 0xd9, 0x2a, 0x06, 0x6d, 0x24, 0x6a, 0x1b, 0xf4, - 0x13, 0x5a, 0x58, 0x41, 0x84, 0x9c, 0xa3, 0x67, 0x60, 0x90, 0x0a, 0xa1, 0x72, 0xd4, 0xa2, 0x44, 0x43, 0x90, 0x5c, - 0x96, 0x5c, 0x85, 0xcf, 0x21, 0x54, 0x9d, 0x3e, 0xce, 0x44, 0xd8, 0xd0, 0xe3, 0xd0, 0x07, 0x80, 0xff, 0xe7, 0x0e, - 0xb9, 0x28, 0xf9, 0x25, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb0, 0x44, 0x34, 0x43, 0xdb, 0x20, 0xf6, 0x63, 0x49, 0xb0, - 0x1e, 0x49, 0xe3, 0x51, 0x69, 0x8e, 0x08, 0x3f, 0x8a, 0x8f, 0xa2, 0xa7, 0xb1, 0x21, 0x91, 0x1c, 0x49, 0x24, 0x1f, - 0x00, 0xe1, 0x24, 0xe8, 0x2f, 0xee, 0x9a, 0xec, 0x5a, 0x48, 0x0c, 0xfa, 0xd3, 0x92, 0x69, 0xd9, 0xbd, 0xea, 0xb1, - 0xaf, 0x08, 0x72, 0xc7, 0xf4, 0xef, 0x5e, 0x1f, 0xfe, 0x5a, 0xe2, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0x99, 0x37, - 0xb8, 0x91, 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, 0xf1, - 0x9c, 0xca, 0xf5, 0xca, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, 0x57, - 0xd2, 0x72, 0xf4, 0x94, 0x72, 0xd5, 0x4c, 0xb9, 0x58, 0xe7, 0xf9, 0x4f, 0x3b, 0xa9, 0x38, 0xc5, 0xcd, 0x14, 0xa4, - 0x4a, 0x2d, 0x17, 0x50, 0x3d, 0x47, 0x2d, 0x77, 0x4b, 0xb3, 0x03, 0x9c, 0xdb, 0xa6, 0xfa, 0x58, 0x99, 0x5d, 0x78, - 0xc9, 0x8d, 0xfb, 0x93, 0x29, 0xc3, 0x82, 0x51, 0x68, 0xb3, 0xea, 0x4a, 0xdb, 0x17, 0x5a, 0xa7, 0x61, 0xb8, 0xf2, - 0xe3, 0x05, 0xa4, 0x0b, 0x18, 0xc7, 0x8b, 0x92, 0x89, 0x71, 0x7b, 0xf4, 0x56, 0x10, 0x5f, 0xb2, 0x15, 0x48, 0xbf, - 0xdf, 0x13, 0xde, 0xae, 0xeb, 0x68, 0xbb, 0x27, 0x4e, 0x19, 0x95, 0xab, 0x58, 0x7c, 0x1f, 0xaf, 0x0c, 0x64, 0xb2, - 0x3a, 0x1e, 0x1b, 0x63, 0x3a, 0xfd, 0x3e, 0x09, 0xfd, 0x42, 0x28, 0xf8, 0xac, 0x97, 0x56, 0x9e, 0xdc, 0x1e, 0x96, - 0x71, 0x8d, 0x5e, 0x89, 0x2b, 0xdd, 0x37, 0x23, 0x85, 0xd4, 0x23, 0x5f, 0x35, 0x05, 0xf4, 0x66, 0xec, 0x9b, 0xa9, - 0x30, 0x6f, 0x7b, 0xc6, 0x5c, 0x21, 0x58, 0xa9, 0xb2, 0xdb, 0x77, 0x6a, 0x4c, 0xc5, 0x0c, 0xa6, 0xd8, 0x76, 0x16, - 0x93, 0x6e, 0xe5, 0x9f, 0x76, 0xee, 0xd3, 0xbc, 0xc3, 0x5d, 0x51, 0xbf, 0x05, 0x2e, 0x34, 0x2b, 0xca, 0xaa, 0x2d, - 0x1b, 0xb6, 0x8d, 0x37, 0xb2, 0x50, 0x6c, 0x80, 0x65, 0xcf, 0x7d, 0x0b, 0x0f, 0x10, 0x37, 0xe1, 0x9e, 0x5d, 0xd4, - 0x70, 0x63, 0xf8, 0xb2, 0x92, 0x7c, 0x57, 0x1a, 0x73, 0xe9, 0x53, 0xa5, 0x89, 0xe1, 0x64, 0x31, 0xe2, 0x22, 0x5d, - 0xd4, 0x99, 0x5d, 0x0b, 0x9f, 0xf1, 0x32, 0x9c, 0xf3, 0x85, 0xd1, 0x4d, 0xe9, 0xd2, 0x0b, 0x96, 0xe8, 0x4e, 0x6f, - 0x56, 0x1a, 0x2b, 0x25, 0xe2, 0xd6, 0x2c, 0x13, 0x28, 0x4b, 0x59, 0x2b, 0xe1, 0x4d, 0xd1, 0xb2, 0x95, 0x34, 0xf2, - 0x9e, 0x39, 0xb8, 0x8f, 0xfd, 0x82, 0x98, 0xc8, 0x26, 0x30, 0x29, 0x1a, 0x3a, 0xa0, 0x5d, 0x75, 0xe1, 0x9b, 0x51, - 0x0f, 0x06, 0xb9, 0x25, 0x89, 0x58, 0x41, 0x8a, 0x15, 0xac, 0x6b, 0x56, 0xcc, 0xf3, 0x05, 0xbd, 0x60, 0x72, 0x9e, - 0x2e, 0xe8, 0x8a, 0xc9, 0xf9, 0x1a, 0x6f, 0x42, 0x17, 0x70, 0x42, 0x92, 0x4d, 0xac, 0x14, 0xb0, 0x17, 0x78, 0x79, - 0xc3, 0x33, 0x55, 0xd3, 0xb2, 0x4b, 0xc5, 0x01, 0xc6, 0xe7, 0x65, 0x18, 0x96, 0xc3, 0x0b, 0xb0, 0x96, 0x38, 0x0c, - 0x57, 0x73, 0xbe, 0x50, 0xbf, 0x21, 0xea, 0x7c, 0x12, 0x2a, 0x76, 0xc1, 0xee, 0x05, 0x32, 0xbd, 0x9a, 0xf3, 0x85, - 0x1a, 0x09, 0x5d, 0xf0, 0x95, 0x35, 0x36, 0x89, 0x3d, 0x41, 0xcb, 0x2c, 0x9e, 0x8f, 0x17, 0x51, 0x5c, 0xc3, 0x32, - 0x7c, 0xaf, 0x66, 0xa6, 0x25, 0xff, 0x49, 0xd4, 0x86, 0x26, 0xfa, 0x06, 0xab, 0xc8, 0x1f, 0x1e, 0x1f, 0x5d, 0x02, - 0x19, 0x3b, 0xbb, 0x92, 0x99, 0x0f, 0x7d, 0x1f, 0x19, 0xdc, 0x73, 0x53, 0xce, 0xb8, 0x0a, 0x12, 0x65, 0xe0, 0xee, - 0xd5, 0x2c, 0x19, 0x6b, 0x11, 0xbe, 0x7b, 0x54, 0x14, 0x7d, 0x26, 0x4d, 0x03, 0xba, 0x8f, 0x04, 0x73, 0xa0, 0xf7, - 0x0a, 0x1d, 0x2e, 0xab, 0x6d, 0x26, 0xe0, 0x2f, 0x12, 0xe4, 0xb7, 0x42, 0xaf, 0x6a, 0x0c, 0xaa, 0x68, 0x17, 0xb1, - 0xf4, 0xef, 0x23, 0x7e, 0x94, 0xcd, 0xdf, 0xcd, 0x3d, 0x5e, 0x49, 0x18, 0xfc, 0x90, 0x9a, 0x4d, 0x32, 0x6f, 0xaf, - 0xd8, 0x7b, 0xe8, 0xa8, 0x47, 0xad, 0xf1, 0xbe, 0x7a, 0xc1, 0x29, 0xc4, 0x28, 0xa1, 0xe8, 0x24, 0x18, 0xc0, 0xed, - 0x12, 0x52, 0xdc, 0x0d, 0x76, 0xd3, 0xbc, 0xe6, 0x45, 0xc1, 0xf9, 0xba, 0xaa, 0x02, 0x3f, 0xa0, 0xe1, 0x7c, 0xb1, - 0x1b, 0xc2, 0x70, 0x4c, 0x5b, 0xd7, 0x30, 0x08, 0x33, 0x86, 0x91, 0x10, 0xbc, 0xfe, 0x45, 0x8f, 0x68, 0x12, 0xaf, - 0xbe, 0xe3, 0x9f, 0x32, 0x5e, 0x28, 0x22, 0x0d, 0x22, 0xa4, 0x6e, 0xe2, 0x1b, 0x99, 0x26, 0x05, 0x14, 0x02, 0x8c, - 0x02, 0x2a, 0xb1, 0xa1, 0xa9, 0xf8, 0x5b, 0x2d, 0x3e, 0xf8, 0xa9, 0xe9, 0x78, 0x34, 0xae, 0x5b, 0x9d, 0x51, 0x41, - 0x67, 0xa0, 0x47, 0xad, 0xa8, 0xa7, 0x41, 0x2b, 0xc1, 0x34, 0xd2, 0xbc, 0x75, 0x0f, 0x81, 0x57, 0xa6, 0xc5, 0x3b, - 0x0f, 0xe8, 0xe6, 0xcc, 0x07, 0x4f, 0x1e, 0xd3, 0x33, 0x87, 0x9e, 0x5c, 0xb1, 0x93, 0xaa, 0x87, 0xda, 0x7b, 0x33, - 0x42, 0x41, 0xbf, 0x8f, 0x29, 0xd0, 0x8d, 0xa0, 0xf6, 0xae, 0xee, 0x95, 0xdc, 0xe5, 0xf0, 0x1d, 0x67, 0xb9, 0x01, - 0x2c, 0x15, 0x59, 0x2b, 0xf0, 0x28, 0x40, 0x5d, 0x2a, 0x43, 0xd8, 0x62, 0x0e, 0x87, 0xca, 0x6e, 0xd5, 0x6a, 0x28, - 0xc9, 0x71, 0x39, 0x02, 0x87, 0xd0, 0x75, 0x39, 0x28, 0x47, 0xcb, 0xac, 0x7a, 0x87, 0xbf, 0x35, 0xeb, 0x90, 0x64, - 0xfb, 0x58, 0x07, 0x6e, 0x59, 0x87, 0xe9, 0x47, 0x83, 0x14, 0x80, 0x26, 0x1b, 0x81, 0x4b, 0x00, 0xde, 0xdb, 0x7f, - 0x44, 0xa8, 0x95, 0xe9, 0x5e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, - 0x91, 0xce, 0x49, 0x9d, 0x89, 0x77, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x77, 0x78, 0x9b, - 0xd5, 0x52, 0x1b, 0x3d, 0x50, 0x00, 0xbf, 0x1b, 0xdc, 0x21, 0xc8, 0x57, 0x63, 0xb8, 0x56, 0xf2, 0x26, 0xe4, 0xc3, - 0x82, 0x1e, 0x91, 0x81, 0x7d, 0x16, 0xc3, 0x98, 0x1e, 0x91, 0x63, 0xfb, 0x2c, 0xdd, 0x00, 0x0e, 0xa4, 0x1e, 0x55, - 0x7a, 0x04, 0x0d, 0xfa, 0xdd, 0xb6, 0xc8, 0x1d, 0x80, 0xd2, 0x28, 0x62, 0xa0, 0x4a, 0x10, 0x51, 0x8b, 0x7f, 0xde, - 0x9b, 0xeb, 0x0e, 0x73, 0x81, 0x30, 0x07, 0x03, 0x0e, 0xe2, 0x36, 0x08, 0xcd, 0x01, 0xb3, 0xb9, 0x8d, 0x04, 0xbd, - 0xb3, 0x86, 0x99, 0x1d, 0xfd, 0xe1, 0x56, 0x82, 0x6f, 0xb2, 0xd6, 0xa8, 0xf3, 0xe2, 0x10, 0x08, 0x82, 0x37, 0x85, - 0xaa, 0xf6, 0xaa, 0x07, 0x36, 0xde, 0xaa, 0x1f, 0xdb, 0xed, 0x78, 0x2a, 0xdc, 0xb5, 0x5f, 0x50, 0x38, 0xf9, 0x94, - 0xfc, 0xeb, 0x9d, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, - 0x3c, 0x52, 0xf4, 0x6f, 0xaf, 0xac, 0x7c, 0x6a, 0xa7, 0x7f, 0xbb, 0x35, 0xeb, 0xf3, 0x78, 0x34, 0xd9, 0x6e, 0x7b, - 0x71, 0xa5, 0x3d, 0xd6, 0xf4, 0x82, 0x40, 0xe7, 0x7a, 0x72, 0x78, 0x04, 0x51, 0x11, 0x9a, 0x71, 0x37, 0xcb, 0x86, - 0x44, 0xc6, 0x8f, 0xd3, 0x59, 0x36, 0x04, 0x3b, 0xdc, 0x8b, 0x4a, 0x5c, 0x8e, 0x5a, 0x1b, 0x9c, 0xde, 0x25, 0x21, - 0x84, 0x72, 0xc0, 0xca, 0x6e, 0xd5, 0x9f, 0x3b, 0x65, 0x26, 0xa4, 0x26, 0xab, 0xdb, 0x29, 0xdd, 0xc3, 0x34, 0x3f, - 0x30, 0x23, 0x38, 0xe0, 0xde, 0xfe, 0xaa, 0x3f, 0x86, 0x49, 0xa6, 0xc9, 0x29, 0x92, 0x5f, 0xa4, 0xa7, 0x90, 0xb4, - 0x43, 0x4f, 0x15, 0x01, 0x9c, 0x50, 0xfb, 0x31, 0xfc, 0x86, 0x71, 0xff, 0xae, 0xf9, 0xda, 0x4d, 0x45, 0xf4, 0x98, - 0x62, 0x99, 0x9a, 0x9c, 0x26, 0x59, 0x91, 0x40, 0xd4, 0x46, 0xd5, 0x8c, 0xe8, 0x91, 0x8b, 0xf9, 0xa8, 0x08, 0x9f, - 0x57, 0xeb, 0xff, 0x0c, 0xe1, 0x33, 0x0a, 0x37, 0x80, 0xcb, 0x2b, 0x2e, 0xcf, 0xc3, 0x27, 0x8f, 0xe9, 0xc1, 0xe4, - 0x9b, 0x23, 0x7a, 0x70, 0xf4, 0xe8, 0x09, 0x01, 0x58, 0xb4, 0xcb, 0xf3, 0xf0, 0xe8, 0xc9, 0x13, 0x7a, 0xf0, 0xed, - 0xb7, 0xf4, 0x60, 0xf2, 0xe8, 0xa8, 0x91, 0x36, 0x79, 0xf2, 0x2d, 0x3d, 0xf8, 0xe6, 0x71, 0x23, 0xed, 0x68, 0xfc, - 0x84, 0x1e, 0xfc, 0xfd, 0x1b, 0x93, 0xf6, 0x37, 0xc8, 0xf6, 0xed, 0x11, 0xfe, 0x67, 0xd2, 0x26, 0x4f, 0x1e, 0xd1, - 0x83, 0xc9, 0x18, 0x2a, 0x79, 0xe2, 0x2a, 0x19, 0x4f, 0xe0, 0xe3, 0x47, 0xf0, 0xdf, 0xdf, 0x08, 0x6c, 0x02, 0xc9, - 0x72, 0x81, 0xfa, 0x33, 0x14, 0x71, 0xa2, 0x6a, 0x22, 0xe1, 0x21, 0x66, 0x56, 0xdf, 0xc4, 0x61, 0x40, 0x5c, 0x3a, - 0x14, 0x44, 0x0f, 0xc6, 0xa3, 0x27, 0x24, 0xf0, 0xe1, 0xe9, 0x3e, 0xfa, 0x20, 0x63, 0xb9, 0x98, 0x67, 0x5f, 0xe5, - 0x26, 0xb6, 0x82, 0x07, 0x60, 0xf5, 0xde, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x8a, 0xcb, 0xdd, 0x5c, 0xff, 0x68, 0x01, - 0xca, 0xfb, 0xab, 0x96, 0x7d, 0x2c, 0x54, 0xe8, 0xb4, 0xd6, 0xe8, 0xb3, 0xf7, 0x98, 0x3e, 0x18, 0x78, 0x37, 0xec, - 0xef, 0x77, 0xca, 0x69, 0x7d, 0xa3, 0x51, 0xa8, 0x51, 0x79, 0x48, 0xd8, 0x09, 0x14, 0x3d, 0x18, 0x00, 0x4f, 0xe0, - 0xe1, 0xbe, 0xfd, 0x9b, 0x65, 0xbc, 0xef, 0x28, 0xe3, 0x5f, 0x28, 0x43, 0x40, 0xa3, 0x1e, 0x66, 0x37, 0x3d, 0x6c, - 0x74, 0xab, 0x97, 0x2c, 0xd5, 0xc9, 0xd4, 0xf4, 0x0c, 0xf6, 0xb5, 0xae, 0xe5, 0x81, 0x11, 0x45, 0xcb, 0x8b, 0x83, - 0x94, 0xcf, 0x2a, 0xf6, 0xfd, 0x12, 0xd5, 0x5b, 0x51, 0xe3, 0x8d, 0xcc, 0x66, 0x15, 0xfb, 0xd9, 0xbc, 0x01, 0x6e, - 0x86, 0xfd, 0x43, 0x3d, 0xf9, 0x81, 0x33, 0x32, 0x69, 0xdb, 0xa3, 0x4c, 0x8c, 0x00, 0x2b, 0x20, 0x03, 0x07, 0x1e, - 0x00, 0x1d, 0xf4, 0x47, 0x7b, 0xbb, 0x55, 0x29, 0xcd, 0x3e, 0x5b, 0x18, 0x40, 0xc3, 0xbc, 0x4d, 0x3c, 0x54, 0xb3, - 0x86, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0x76, 0x0a, 0x43, 0x08, 0xc1, 0x2a, 0x65, 0x00, 0x38, 0x10, 0x60, 0x30, - 0xd6, 0x32, 0xa0, 0x66, 0xcb, 0x47, 0x1b, 0xae, 0xd4, 0x93, 0xc0, 0x19, 0x5c, 0xc8, 0x22, 0xe1, 0x6f, 0xb4, 0xd8, - 0x1f, 0xad, 0x1f, 0x7d, 0xdf, 0x1e, 0x0f, 0xd6, 0xbe, 0xc7, 0x47, 0xfa, 0xb3, 0xc6, 0x75, 0x60, 0xd3, 0xf2, 0x8d, - 0x17, 0xb5, 0x95, 0x78, 0x94, 0xc0, 0x1b, 0x98, 0x88, 0x14, 0x06, 0xa9, 0x16, 0x38, 0x06, 0xe5, 0x8d, 0x85, 0x58, - 0xaa, 0xae, 0x6e, 0xe8, 0x96, 0x0c, 0xc1, 0xc3, 0xed, 0xc7, 0xa5, 0x0a, 0x1c, 0xd5, 0xef, 0x67, 0xd2, 0x77, 0x7b, - 0x32, 0x76, 0xe4, 0x38, 0xf5, 0x53, 0xe1, 0xe0, 0xbf, 0x49, 0x5d, 0x1b, 0xbb, 0xfb, 0x94, 0x59, 0x96, 0x85, 0x9d, - 0x84, 0x5a, 0xee, 0x51, 0x79, 0x90, 0x7c, 0x21, 0x87, 0x48, 0x16, 0x18, 0x85, 0x82, 0x0c, 0x27, 0x54, 0x8c, 0xd6, - 0xa2, 0x5c, 0x66, 0x17, 0x55, 0xb8, 0x51, 0x0a, 0x65, 0x4e, 0xd1, 0xb7, 0x1b, 0x1c, 0x48, 0x48, 0x94, 0x95, 0xaf, - 0xe3, 0xd7, 0x21, 0x82, 0xd5, 0x71, 0x6d, 0x0b, 0xc5, 0xbd, 0xfd, 0x99, 0xa5, 0x5d, 0xfc, 0x91, 0x71, 0x01, 0x75, - 0xb1, 0x98, 0x86, 0x13, 0xab, 0xdf, 0x71, 0x5f, 0x58, 0x4d, 0x0f, 0x40, 0x7d, 0x97, 0x4a, 0x8c, 0xa0, 0xbe, 0x32, - 0xf6, 0xb1, 0x3d, 0xc6, 0xe4, 0x0c, 0x62, 0x0d, 0xeb, 0xbb, 0x9d, 0xea, 0x1b, 0x61, 0x27, 0x00, 0xdc, 0x08, 0xad, - 0xd1, 0x91, 0x49, 0xaa, 0x10, 0xcf, 0x4b, 0x15, 0xbe, 0x35, 0x23, 0x74, 0x0c, 0xde, 0x54, 0xb6, 0x91, 0x42, 0xfa, - 0x82, 0x41, 0x73, 0x6c, 0xeb, 0x28, 0xac, 0xb6, 0xb2, 0xec, 0x04, 0xe0, 0x06, 0xb2, 0x63, 0x73, 0xf1, 0x9c, 0x55, - 0xf3, 0x6c, 0x11, 0x99, 0xa0, 0x80, 0x4b, 0x61, 0x19, 0xb4, 0xd7, 0x7b, 0x64, 0x3b, 0x0e, 0xa1, 0x1b, 0xee, 0x23, - 0x18, 0x4f, 0xbb, 0x29, 0x58, 0x41, 0x34, 0x42, 0x3c, 0xcc, 0x98, 0xc5, 0xf7, 0x4a, 0x53, 0x9e, 0xaa, 0x96, 0x40, - 0xe0, 0x28, 0x84, 0xba, 0xd8, 0x35, 0x4a, 0x70, 0x99, 0x1a, 0xc1, 0x0c, 0x76, 0xec, 0x48, 0x6d, 0x97, 0x9c, 0xd3, - 0xa1, 0x9a, 0xd2, 0x52, 0x4f, 0xa9, 0xf6, 0x35, 0x14, 0xf3, 0x12, 0x3d, 0xf4, 0xc0, 0xf5, 0x40, 0x3b, 0xe4, 0x95, - 0x74, 0x62, 0x22, 0xe8, 0xb4, 0xda, 0x84, 0x9d, 0x1b, 0xe9, 0x96, 0xd5, 0xc8, 0x3b, 0x86, 0x66, 0x47, 0xbc, 0xf4, - 0x03, 0x75, 0x01, 0x44, 0xc8, 0xde, 0x16, 0x99, 0xd9, 0x67, 0x59, 0xf9, 0x02, 0xca, 0xe2, 0x88, 0xad, 0x2b, 0xe0, - 0x5a, 0x0a, 0x26, 0x97, 0x3c, 0xca, 0x52, 0x44, 0x04, 0x3c, 0x55, 0xda, 0xf5, 0x9d, 0x96, 0x10, 0x2a, 0x52, 0x20, - 0x6e, 0x2e, 0x8a, 0x73, 0x6d, 0x03, 0x59, 0x00, 0x7d, 0xfb, 0x29, 0xbb, 0xf2, 0xc2, 0xc1, 0x6e, 0xae, 0x32, 0xf1, - 0x8c, 0x5f, 0x64, 0x82, 0xa7, 0x08, 0x76, 0x75, 0x6b, 0x1e, 0xb8, 0x63, 0xdb, 0xc0, 0xf2, 0xed, 0x3b, 0x58, 0x30, - 0x65, 0xa8, 0x95, 0x12, 0x99, 0x88, 0x04, 0x64, 0xf6, 0x99, 0xbb, 0x57, 0x99, 0x78, 0x15, 0xdf, 0x82, 0x37, 0x45, - 0x83, 0x9f, 0x1e, 0x9d, 0xe3, 0x97, 0x88, 0x24, 0x0a, 0x31, 0x6c, 0x31, 0x22, 0x16, 0x22, 0xc7, 0x8e, 0x09, 0xe5, - 0x4a, 0xd0, 0xda, 0x1a, 0x02, 0x2f, 0xfe, 0xb4, 0xea, 0xde, 0x55, 0x26, 0x8c, 0x7d, 0xc6, 0x55, 0x7c, 0xcb, 0x4a, - 0x05, 0x66, 0x81, 0x71, 0xee, 0xdb, 0x52, 0x92, 0xab, 0x4c, 0x18, 0x01, 0xc9, 0x55, 0x7c, 0x4b, 0x9b, 0x32, 0x0e, - 0x6d, 0x45, 0xe7, 0xc5, 0xf9, 0xdd, 0x1d, 0x7e, 0x89, 0xa1, 0x56, 0xc6, 0xfd, 0x3e, 0x48, 0xcc, 0xa4, 0x6d, 0xca, - 0x4c, 0x46, 0x52, 0xa3, 0x85, 0x54, 0x94, 0x0f, 0x26, 0x64, 0x77, 0xa5, 0x5a, 0x46, 0xd4, 0x7e, 0x15, 0x8a, 0xd9, - 0x38, 0x9a, 0x10, 0x3a, 0xe9, 0x58, 0xef, 0xa6, 0xb5, 0x90, 0x69, 0xf4, 0x24, 0xf2, 0x7c, 0x3a, 0x0b, 0x56, 0x4d, - 0x8b, 0x63, 0xc6, 0xa7, 0xc5, 0x60, 0x40, 0xb4, 0x4b, 0xe1, 0x06, 0xeb, 0x01, 0x53, 0x1a, 0x17, 0x6f, 0xcd, 0xb4, - 0xfa, 0x85, 0x54, 0x21, 0xe9, 0x3d, 0x03, 0x12, 0x21, 0x5d, 0xb0, 0x5b, 0x90, 0x28, 0x7a, 0xfe, 0x77, 0x6a, 0x0b, - 0xee, 0x7a, 0x30, 0x36, 0xa3, 0xfb, 0x7a, 0xc6, 0x7f, 0xa8, 0x6d, 0x41, 0xd4, 0xa7, 0x92, 0xf5, 0x3a, 0x12, 0x55, - 0xc8, 0x45, 0xf8, 0xd9, 0xd1, 0x10, 0x43, 0x54, 0x7b, 0x2c, 0x10, 0xeb, 0xab, 0x73, 0x5e, 0xe0, 0xf4, 0x33, 0x77, - 0xb9, 0x82, 0x6d, 0x41, 0x2b, 0x43, 0xa3, 0x5e, 0xc7, 0xaf, 0x23, 0x7b, 0x59, 0xd0, 0x45, 0x3e, 0x43, 0x21, 0x6b, - 0x1e, 0x86, 0xd5, 0xb0, 0x3d, 0x88, 0xe4, 0xb0, 0x3d, 0x09, 0x8d, 0xc6, 0xc0, 0x02, 0xd9, 0xa1, 0x11, 0xb8, 0x08, - 0xad, 0xfc, 0xed, 0x18, 0x5c, 0xb8, 0x2c, 0x22, 0xcb, 0x50, 0xc7, 0x6f, 0x6a, 0x37, 0x41, 0xf5, 0x0a, 0x9d, 0xa6, - 0xb0, 0x2a, 0x65, 0x92, 0x0f, 0xbf, 0x5e, 0xc8, 0x02, 0x33, 0x79, 0x5d, 0xf6, 0xe8, 0x6b, 0xbb, 0xbd, 0x03, 0x53, - 0xb0, 0xee, 0x93, 0xf7, 0xf5, 0xc3, 0xce, 0x9e, 0x80, 0x51, 0xac, 0xca, 0xd1, 0x14, 0x52, 0x6a, 0x1f, 0x94, 0xfa, - 0x63, 0xb8, 0x14, 0x9a, 0x63, 0xb7, 0x80, 0x49, 0xc0, 0x3e, 0x43, 0xaa, 0xc7, 0xb4, 0x63, 0x9f, 0xa3, 0x0d, 0x2c, - 0x09, 0x38, 0xfc, 0x23, 0x21, 0x6b, 0xff, 0xea, 0x5e, 0xa6, 0xcd, 0x90, 0x2d, 0xf3, 0x05, 0xf0, 0xf9, 0xb0, 0x6b, - 0xa3, 0x12, 0x65, 0x13, 0x91, 0xa4, 0xb0, 0xe5, 0x31, 0x48, 0x7b, 0x14, 0xd3, 0x55, 0xc1, 0x93, 0x0c, 0xa5, 0x14, - 0x89, 0xf6, 0x09, 0xce, 0xe1, 0x0d, 0xee, 0x47, 0x15, 0x10, 0x5e, 0x85, 0x9c, 0x8e, 0x52, 0xaa, 0x2d, 0x60, 0x14, - 0xf5, 0x00, 0x51, 0x5e, 0x06, 0x72, 0xbc, 0xed, 0x76, 0x42, 0x57, 0x6c, 0x39, 0x9c, 0x50, 0x24, 0x25, 0x97, 0x58, - 0xee, 0x15, 0xe8, 0x3c, 0xce, 0x59, 0xef, 0x25, 0x60, 0x11, 0x9c, 0xc1, 0xdf, 0x98, 0xd0, 0x6b, 0xf8, 0x9b, 0x13, - 0xfa, 0x94, 0x85, 0x57, 0xc3, 0x4b, 0x72, 0x18, 0xa6, 0x83, 0x89, 0x12, 0x8c, 0xdd, 0xb1, 0xb4, 0x0c, 0x55, 0xe2, - 0xea, 0xf0, 0x82, 0x3c, 0xbc, 0xa0, 0xb7, 0xf4, 0x86, 0xbe, 0xa2, 0x6f, 0x80, 0xf0, 0xdf, 0x1d, 0x4f, 0xf8, 0x70, - 0xf2, 0xb8, 0xdf, 0xef, 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, - 0x7a, 0x31, 0x7d, 0xa3, 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xbc, 0x23, 0x43, 0x7c, 0xbc, 0xc8, 0xa5, 0x2c, - 0xc2, 0xcb, 0xc3, 0x3b, 0x42, 0xdf, 0x9c, 0x80, 0xde, 0x14, 0xeb, 0x7b, 0xf3, 0xf0, 0x4e, 0xd7, 0x46, 0xe8, 0xcb, - 0x30, 0x81, 0x6d, 0x72, 0xcb, 0xec, 0x5d, 0x7b, 0x32, 0x86, 0x58, 0x26, 0x77, 0x5e, 0x79, 0x77, 0x0f, 0x6f, 0xc9, - 0xe1, 0x2d, 0x78, 0x8a, 0x5a, 0xf2, 0x37, 0x0b, 0x6f, 0x58, 0xab, 0x86, 0x87, 0x77, 0xf4, 0x55, 0xab, 0x11, 0x0f, - 0xef, 0x48, 0x14, 0xde, 0xb0, 0x4b, 0xfa, 0x8a, 0x5d, 0x11, 0x7a, 0xde, 0xef, 0x9f, 0xf5, 0xfb, 0xb2, 0xdf, 0xff, - 0x3e, 0x0e, 0xc3, 0x78, 0x58, 0x90, 0x43, 0x49, 0xef, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, - 0x59, 0x95, 0xb7, 0xca, 0x75, 0x47, 0xc1, 0x5a, 0xe1, 0x8e, 0xa9, 0xa7, 0x37, 0xf4, 0x86, 0x15, 0xf4, 0x15, 0x8b, - 0x49, 0x74, 0x0d, 0xad, 0x38, 0x9f, 0x15, 0xd1, 0x0d, 0x7d, 0xc5, 0xce, 0x66, 0x71, 0xf4, 0x8a, 0xbe, 0x61, 0xf9, - 0x70, 0x02, 0x79, 0x5f, 0x0d, 0x6f, 0xc8, 0xe1, 0x1b, 0x12, 0x85, 0x6f, 0xf4, 0xef, 0x3b, 0x7a, 0xc9, 0xc3, 0x37, - 0xd4, 0xab, 0xe6, 0x0d, 0x31, 0xd5, 0x37, 0x6a, 0x7f, 0x43, 0x22, 0x7f, 0x30, 0xdf, 0x58, 0x7b, 0x9a, 0xb7, 0x8e, - 0x36, 0xae, 0xcb, 0xf0, 0x8e, 0xd0, 0x75, 0x19, 0xde, 0x10, 0x32, 0x6d, 0x8e, 0x1d, 0x0c, 0xe8, 0xec, 0x6d, 0x94, - 0x10, 0x7a, 0xe3, 0x97, 0x7a, 0x83, 0x63, 0x68, 0x46, 0x48, 0xf7, 0x13, 0xd3, 0x70, 0x1d, 0x7c, 0xd0, 0x60, 0x1d, - 0xe7, 0xfd, 0x7e, 0xb8, 0xee, 0xf7, 0x21, 0xd2, 0x7d, 0x31, 0x33, 0xb1, 0xdd, 0x1c, 0xd9, 0xa4, 0x37, 0xa0, 0xfd, - 0xff, 0x30, 0x18, 0x40, 0x67, 0xbc, 0x92, 0xc2, 0x9b, 0xc1, 0x87, 0x87, 0x77, 0x44, 0xd5, 0x51, 0xd0, 0x52, 0x86, - 0x05, 0x7d, 0x4a, 0x33, 0x00, 0xfc, 0xfa, 0x30, 0x18, 0x90, 0xc8, 0x7c, 0x46, 0xa6, 0x1f, 0x8e, 0xdf, 0x4c, 0x07, - 0x83, 0x0f, 0x66, 0x9b, 0x7c, 0x62, 0x7b, 0x4a, 0x81, 0xf5, 0x77, 0xd6, 0xef, 0x7f, 0x3a, 0x89, 0xc9, 0x79, 0xc1, - 0xe3, 0x8f, 0xd3, 0x66, 0x5b, 0x3e, 0xb9, 0xa8, 0x6a, 0x67, 0xfd, 0xfe, 0xba, 0xdf, 0x7f, 0x05, 0xd8, 0x45, 0x33, - 0xe7, 0xeb, 0x09, 0xd2, 0x96, 0xb9, 0xa3, 0x48, 0x9a, 0xe4, 0xd0, 0x18, 0xda, 0x16, 0xab, 0xb6, 0xcd, 0x3a, 0x32, - 0xb0, 0x38, 0x6a, 0x56, 0x14, 0xd7, 0x24, 0x0a, 0x7b, 0x67, 0xdb, 0xed, 0x2b, 0xc6, 0x58, 0x4c, 0x40, 0xfa, 0xe1, - 0xbf, 0x7e, 0x55, 0x37, 0x62, 0x88, 0x95, 0x4a, 0x7c, 0xb7, 0x59, 0xda, 0x43, 0x20, 0xe2, 0xb0, 0xe9, 0xdf, 0x99, - 0x7b, 0xb9, 0xa8, 0x1d, 0xdf, 0xfa, 0x2f, 0x00, 0x21, 0x92, 0x2c, 0xe4, 0x33, 0x1c, 0x83, 0x32, 0x03, 0x20, 0xf3, - 0x48, 0xcd, 0xbc, 0x04, 0x10, 0x60, 0xb2, 0xdd, 0x8e, 0xc6, 0xe3, 0x09, 0x2d, 0xd8, 0xe8, 0x6f, 0x4f, 0x1e, 0x56, - 0x0f, 0xc3, 0x20, 0x18, 0x64, 0xa4, 0xa5, 0xa7, 0xb0, 0x8b, 0xb5, 0x3a, 0x04, 0x23, 0x78, 0xcd, 0x3e, 0x5e, 0x67, - 0x5f, 0xcc, 0x3e, 0x22, 0x61, 0x6d, 0x30, 0x8e, 0x5c, 0xa4, 0x2d, 0xbd, 0xdd, 0x1e, 0x06, 0x93, 0x8b, 0xf4, 0x33, - 0x6c, 0xa7, 0xcf, 0xbf, 0x79, 0x30, 0x9e, 0x70, 0x30, 0xba, 0x8b, 0x82, 0x3e, 0xd3, 0xb6, 0xdb, 0xca, 0xbf, 0x04, - 0xbe, 0xc6, 0x54, 0xd0, 0xb1, 0x59, 0x16, 0x6e, 0x50, 0x11, 0x75, 0xb4, 0x0c, 0xaa, 0x5a, 0xd9, 0xce, 0x01, 0xb5, - 0xc4, 0xaa, 0x4c, 0xdc, 0x02, 0xc3, 0x90, 0xa1, 0x2e, 0xf7, 0xb4, 0xfa, 0x17, 0x2f, 0xa4, 0x81, 0xcf, 0x70, 0x22, - 0x42, 0x8f, 0x5b, 0xe3, 0x3e, 0xb7, 0x26, 0x3e, 0xc3, 0xad, 0x95, 0x48, 0x62, 0x0d, 0x2c, 0xa9, 0xb9, 0x1c, 0x25, - 0xec, 0xa4, 0x64, 0x7c, 0x56, 0x46, 0x09, 0x8d, 0xe1, 0x41, 0x32, 0x31, 0x93, 0x51, 0x82, 0xf6, 0x89, 0x2e, 0xc2, - 0xe0, 0x5f, 0x80, 0xd9, 0x4f, 0x73, 0xf8, 0x2b, 0xc9, 0x34, 0x39, 0x86, 0x80, 0x10, 0xc7, 0xe3, 0x59, 0x1c, 0x8e, - 0x49, 0x94, 0x9c, 0xc0, 0x13, 0xfc, 0x57, 0x84, 0x63, 0x52, 0xeb, 0x3b, 0x8c, 0x54, 0x97, 0xdb, 0x84, 0x01, 0x5c, - 0xd9, 0x78, 0x36, 0x89, 0xac, 0x74, 0x57, 0x3e, 0x1c, 0x8d, 0x9f, 0x90, 0x69, 0x1c, 0xca, 0x41, 0x42, 0x28, 0x78, - 0xf7, 0x86, 0xe5, 0x30, 0xd1, 0xf0, 0x6c, 0xc0, 0xe6, 0x95, 0x8e, 0xcd, 0x93, 0x70, 0x02, 0xc2, 0x30, 0x21, 0xc7, - 0xba, 0x07, 0x29, 0x45, 0x9f, 0xe7, 0xd8, 0x4f, 0x7d, 0x04, 0x61, 0x76, 0xd4, 0x52, 0xf1, 0x15, 0x00, 0x5d, 0xe2, - 0xe0, 0x50, 0x7b, 0xe6, 0x8b, 0x59, 0x58, 0x7a, 0x54, 0xca, 0x54, 0x77, 0x28, 0x1a, 0x94, 0xdf, 0x34, 0xe8, 0x50, - 0x90, 0xc1, 0x84, 0x96, 0x27, 0x13, 0xfe, 0x08, 0x02, 0x78, 0x34, 0x22, 0x7e, 0x29, 0x9c, 0x18, 0x08, 0xaf, 0x82, - 0x0c, 0x54, 0x5a, 0xab, 0xc6, 0x8c, 0x6c, 0xc5, 0x07, 0x10, 0x26, 0xe5, 0xe0, 0x46, 0xae, 0xf3, 0x14, 0xa2, 0x82, - 0xad, 0xf3, 0xea, 0xe0, 0x12, 0x2c, 0xd9, 0xe3, 0x0a, 0xe2, 0x84, 0xad, 0x57, 0x80, 0x9d, 0xfb, 0x60, 0x53, 0xd6, - 0x07, 0xea, 0xbb, 0x03, 0x6c, 0x39, 0xbc, 0xaa, 0xe4, 0xc1, 0x64, 0x3c, 0x1e, 0x8f, 0xfe, 0x80, 0xa3, 0x03, 0x08, - 0x2d, 0x89, 0x0c, 0x9f, 0x0c, 0xd0, 0xb8, 0xeb, 0x8a, 0x7b, 0xe3, 0x42, 0x51, 0x56, 0x3a, 0x99, 0x10, 0x10, 0x3f, - 0x9b, 0xbe, 0xc1, 0xbe, 0xe2, 0x3a, 0xfe, 0xc9, 0xee, 0x27, 0x66, 0x45, 0xab, 0x95, 0x3a, 0x7a, 0xfb, 0xe6, 0xfd, - 0xcb, 0x0f, 0x2f, 0x7f, 0x7d, 0x7e, 0xf6, 0xf2, 0xf5, 0x8b, 0x97, 0xaf, 0x5f, 0x7e, 0xf8, 0xe7, 0x3d, 0x0c, 0xb6, - 0x6f, 0x2b, 0x62, 0xc7, 0xde, 0xbb, 0xc7, 0x78, 0xb5, 0xf8, 0xc2, 0xd9, 0x23, 0x77, 0x8b, 0x05, 0xd8, 0x04, 0xc3, - 0x2d, 0x08, 0xaa, 0x19, 0x8d, 0x4a, 0xdf, 0x13, 0x90, 0xd1, 0xa8, 0x90, 0x8d, 0x87, 0x15, 0x5b, 0x21, 0x17, 0xef, - 0x18, 0x0e, 0x3e, 0xb2, 0xbf, 0x15, 0x67, 0xc2, 0xed, 0x68, 0x6b, 0x56, 0x04, 0x7c, 0xbe, 0xd6, 0xa2, 0xf2, 0xb8, - 0x10, 0xb5, 0xb7, 0xed, 0x73, 0x48, 0xa8, 0x47, 0xe4, 0x3a, 0x78, 0xdf, 0x06, 0xd9, 0xe3, 0x23, 0xef, 0x49, 0x79, - 0x86, 0xfa, 0x1c, 0x0d, 0x1f, 0x35, 0x9e, 0xd1, 0x89, 0xb9, 0x36, 0x3a, 0xd4, 0xb3, 0x02, 0xf6, 0xb7, 0x12, 0x63, - 0xd3, 0x82, 0x95, 0x29, 0x62, 0x7d, 0x38, 0xdd, 0xef, 0xee, 0xcd, 0xe8, 0x67, 0x38, 0x7e, 0x94, 0x6a, 0x02, 0x69, - 0x51, 0xa0, 0x74, 0x65, 0xc8, 0x6d, 0xcf, 0xc2, 0xc2, 0xfc, 0x0c, 0x1b, 0x04, 0xd0, 0x5e, 0x76, 0x2c, 0x09, 0x34, - 0x8b, 0xd7, 0xba, 0xfe, 0x79, 0xf9, 0x32, 0xd1, 0xce, 0x17, 0xdf, 0x42, 0x88, 0x61, 0xff, 0x8a, 0xd0, 0x98, 0x70, - 0x37, 0xc9, 0xee, 0xd2, 0x62, 0xee, 0x55, 0x57, 0x31, 0x1e, 0x77, 0x7b, 0xae, 0x14, 0xcd, 0x5b, 0x17, 0xd8, 0x03, - 0x35, 0xaf, 0xe3, 0x25, 0x0b, 0x01, 0x9b, 0xf1, 0xd0, 0x2e, 0x12, 0xe7, 0xf7, 0x4e, 0x27, 0xe4, 0xf0, 0x68, 0xca, - 0x87, 0xac, 0xa4, 0x62, 0xc0, 0xca, 0x7a, 0x87, 0x9a, 0xf3, 0x36, 0x21, 0x17, 0xbb, 0x34, 0x5c, 0x0c, 0xf9, 0x7d, - 0x97, 0xa4, 0x0f, 0xbc, 0xe1, 0x50, 0x6d, 0x9b, 0x8b, 0x21, 0x4d, 0x39, 0xdd, 0xa5, 0x32, 0x20, 0x44, 0xba, 0x8a, - 0x2b, 0x52, 0xeb, 0xa3, 0x2a, 0x75, 0x92, 0x8e, 0xeb, 0x6c, 0xf3, 0x99, 0x4b, 0xb6, 0xba, 0x5d, 0xfb, 0xd7, 0xea, - 0xf6, 0x85, 0x19, 0xc8, 0xdf, 0x9f, 0x88, 0x6a, 0x62, 0x20, 0xba, 0x80, 0x0a, 0xfe, 0x09, 0x5e, 0x9e, 0x3c, 0xd2, - 0x0a, 0xd0, 0x7d, 0x67, 0x47, 0xd7, 0x1e, 0x6f, 0xcc, 0x62, 0x6b, 0x89, 0x73, 0x56, 0xf9, 0xce, 0xf2, 0xaa, 0x6c, - 0x85, 0xae, 0x23, 0xd8, 0xbf, 0xc2, 0x8e, 0xbe, 0x7b, 0xdb, 0x00, 0x88, 0x52, 0x58, 0xb9, 0xb3, 0x5f, 0x78, 0x67, - 0xbf, 0xb0, 0x67, 0xbf, 0xdd, 0x04, 0xca, 0x87, 0x15, 0x5a, 0xf6, 0x42, 0x8a, 0xca, 0x34, 0x79, 0xdc, 0xd4, 0x65, - 0x21, 0x2d, 0xe6, 0x87, 0x96, 0x76, 0x3d, 0x1e, 0x53, 0x89, 0xea, 0x91, 0x1f, 0xb0, 0x55, 0x87, 0x25, 0xb9, 0xff, - 0x9e, 0xf9, 0x3f, 0x7b, 0x83, 0xdc, 0x77, 0xb7, 0xfb, 0xbf, 0xb9, 0xd0, 0xc1, 0x6d, 0x2d, 0x15, 0x9e, 0xba, 0x3a, - 0x2e, 0xf0, 0xae, 0x96, 0xde, 0x7f, 0x57, 0x7b, 0x90, 0xe9, 0x65, 0x57, 0x01, 0x6a, 0x90, 0x58, 0x5f, 0xf1, 0x22, - 0x4b, 0x6a, 0xab, 0xd0, 0x78, 0xc3, 0x21, 0xb4, 0x87, 0x77, 0x70, 0x81, 0x1c, 0x96, 0x10, 0xfa, 0xb1, 0x32, 0x02, - 0x40, 0x9f, 0xc5, 0x7e, 0xc3, 0xc3, 0x8c, 0x0c, 0x7c, 0x89, 0x9f, 0x94, 0xbe, 0xb8, 0xf8, 0x70, 0x27, 0x33, 0x41, - 0xaf, 0x12, 0x17, 0x35, 0x57, 0xb6, 0x63, 0x7e, 0xf8, 0x5f, 0x60, 0x34, 0x08, 0xaf, 0x2d, 0xd9, 0xa1, 0xe8, 0x98, - 0xe5, 0x0a, 0x8e, 0xda, 0xd2, 0x95, 0x29, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x0d, 0xc8, 0xbe, 0x90, - 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0x77, - 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0xf5, 0x01, 0xea, 0x6b, 0x6c, 0x49, 0xb2, 0xa9, 0xd8, 0x5f, 0x60, 0x16, 0x0b, 0xc4, - 0xd1, 0xc1, 0x2f, 0xce, 0x17, 0x00, 0xb2, 0x0c, 0xcb, 0x4c, 0x0b, 0x8b, 0x64, 0xaa, 0x7c, 0x64, 0x0b, 0x26, 0x8f, - 0xc7, 0x33, 0xbf, 0xe7, 0x8e, 0xc1, 0x21, 0x24, 0x9a, 0x58, 0xe3, 0x17, 0x3f, 0x0b, 0xc6, 0x71, 0x28, 0x4f, 0x64, - 0xe3, 0xbb, 0x92, 0x44, 0x63, 0x63, 0xaa, 0xac, 0xaf, 0x12, 0xd5, 0x30, 0x21, 0x0f, 0x0b, 0x72, 0x58, 0xd0, 0xa5, - 0x3f, 0x96, 0x98, 0x7e, 0x18, 0x1f, 0x4e, 0xc6, 0xe4, 0x61, 0xfc, 0x70, 0x62, 0xe0, 0x86, 0xfd, 0x1c, 0xf9, 0x70, - 0x49, 0x0e, 0x9b, 0x55, 0x82, 0x29, 0xaa, 0xe9, 0x99, 0x5f, 0x49, 0x32, 0x58, 0x0e, 0xd2, 0x87, 0xad, 0xbc, 0x58, - 0xab, 0x1e, 0xef, 0xf5, 0x31, 0x9f, 0x12, 0xd1, 0xb8, 0x31, 0xac, 0xe9, 0x55, 0xfc, 0xa7, 0x2c, 0x22, 0x29, 0x01, - 0x91, 0x10, 0xd4, 0xdb, 0xd9, 0x45, 0x96, 0xc4, 0x22, 0x8d, 0xd2, 0x9a, 0xd0, 0xf4, 0x84, 0x4d, 0xc6, 0xb3, 0x94, - 0xa5, 0xc7, 0x93, 0x27, 0xb3, 0xc9, 0x93, 0xe8, 0x68, 0x1c, 0xa5, 0x83, 0x01, 0x24, 0x1f, 0x8d, 0xc1, 0xc5, 0x0e, - 0x7e, 0xb3, 0x23, 0x18, 0xba, 0x13, 0x64, 0x09, 0x0b, 0x68, 0xda, 0x97, 0x35, 0x49, 0x0f, 0xe7, 0x85, 0xea, 0x49, - 0x7c, 0x4b, 0xd7, 0x9e, 0x83, 0x8b, 0xdf, 0xc2, 0x0b, 0xd7, 0xc2, 0x8b, 0xdd, 0x16, 0x0a, 0x4d, 0xb6, 0x63, 0xf9, - 0xff, 0xe3, 0x86, 0xb1, 0xef, 0x2e, 0x61, 0x16, 0xd7, 0x75, 0x36, 0x5a, 0x15, 0xb2, 0x92, 0x70, 0x9b, 0x50, 0xa2, - 0xb0, 0x51, 0xbc, 0x5a, 0xe5, 0xda, 0x45, 0x6c, 0x5e, 0x51, 0x00, 0x77, 0x81, 0x38, 0xc5, 0xc0, 0x42, 0x1b, 0x03, - 0xb9, 0x4f, 0xbc, 0x90, 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0xcf, 0x10, 0x8c, 0x51, 0xc5, 0xc9, 0x78, 0xa6, 0xb0, - 0x2e, 0x3e, 0x27, 0xef, 0xfd, 0x37, 0x8e, 0x22, 0x7b, 0x34, 0x83, 0x9e, 0x20, 0x72, 0x1e, 0x71, 0xf6, 0x64, 0xf2, - 0x32, 0x70, 0x3f, 0x83, 0x95, 0xfe, 0xba, 0xdb, 0x8c, 0xb5, 0xed, 0xd1, 0xbd, 0x30, 0x42, 0xd1, 0x4f, 0xf8, 0xce, - 0xd4, 0x0b, 0xb8, 0x84, 0x6a, 0x60, 0xd7, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, 0xf4, 0xfb, 0xbd, 0x3f, 0x0d, - 0x34, 0x69, 0xc9, 0x8b, 0x57, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x1f, 0x2b, 0xfb, 0x4c, 0xc7, 0x64, - 0xe6, 0x3f, 0x0e, 0x27, 0x24, 0x6a, 0xbe, 0x26, 0x9f, 0x39, 0x4d, 0x3f, 0x73, 0x45, 0xfb, 0x0f, 0x64, 0xe6, 0x86, - 0x43, 0x86, 0xfa, 0x4b, 0xc7, 0x3c, 0x19, 0xbd, 0x4e, 0xcc, 0x4e, 0x04, 0xab, 0x66, 0x10, 0x85, 0xbd, 0x80, 0x07, - 0x75, 0x2d, 0x8b, 0xa7, 0x30, 0xfb, 0xa0, 0x46, 0x14, 0xc7, 0x6c, 0x3c, 0x0b, 0x65, 0x38, 0x01, 0xfb, 0xde, 0xc9, - 0x18, 0xee, 0x03, 0x32, 0xfc, 0x58, 0x85, 0xd8, 0x39, 0x48, 0xfb, 0x58, 0xa1, 0x62, 0x02, 0x20, 0x02, 0x21, 0x6f, - 0xbf, 0x2f, 0x55, 0x12, 0xbe, 0x2e, 0x31, 0xa5, 0x50, 0x1f, 0xfc, 0x27, 0x52, 0x75, 0xc7, 0xf4, 0xab, 0xf5, 0xe3, - 0xcf, 0x84, 0xe2, 0xd3, 0x5d, 0x4a, 0x7c, 0x0b, 0xc1, 0x9d, 0x0b, 0xd0, 0x41, 0x54, 0x68, 0xc6, 0x76, 0x3f, 0xbf, - 0x2b, 0xf6, 0xf3, 0xbb, 0xe2, 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, - 0xf4, 0x9f, 0xf3, 0x89, 0x7b, 0x79, 0xea, 0xab, 0x4c, 0x4c, 0xf7, 0x30, 0xcd, 0x3e, 0x41, 0x41, 0x58, 0xc5, 0x5d, - 0x7a, 0xb2, 0xae, 0xec, 0xad, 0x95, 0x0c, 0x31, 0xcf, 0x3d, 0xac, 0x51, 0x58, 0x79, 0x40, 0xf7, 0xa8, 0xda, 0x20, - 0x4e, 0x04, 0x0f, 0x63, 0x66, 0xa5, 0xef, 0xdb, 0xad, 0x51, 0x61, 0xde, 0xcb, 0x45, 0x41, 0x76, 0xf3, 0xf1, 0x6c, - 0x1c, 0x85, 0xd8, 0x80, 0xff, 0x98, 0xb1, 0x6a, 0xc8, 0xe6, 0x3b, 0x19, 0xa9, 0x1d, 0x93, 0xa7, 0xc9, 0x2e, 0xe9, - 0x1d, 0xf0, 0x0e, 0xf9, 0x79, 0xfd, 0x31, 0x8c, 0xa5, 0xe1, 0xb7, 0xe4, 0x65, 0x5c, 0x64, 0xd5, 0xf2, 0x2a, 0x4b, - 0x90, 0xe9, 0x82, 0x17, 0x5f, 0xcc, 0x74, 0x79, 0x1f, 0xeb, 0x03, 0xc6, 0x53, 0x8a, 0xd7, 0x0d, 0x51, 0xfa, 0xba, - 0xe5, 0x59, 0xa1, 0x2e, 0x4f, 0x2a, 0x66, 0x7b, 0x56, 0x82, 0xd3, 0x29, 0x98, 0xe0, 0xeb, 0x9f, 0xae, 0xf7, 0x09, - 0xe0, 0x82, 0x42, 0xcd, 0x69, 0x21, 0x57, 0x06, 0xcb, 0xc9, 0x42, 0x77, 0x02, 0x66, 0xa8, 0x14, 0x78, 0x81, 0x82, - 0xbf, 0x68, 0x60, 0x44, 0x5f, 0xb8, 0xdf, 0x64, 0x60, 0x90, 0x2e, 0xcd, 0x89, 0x30, 0x76, 0xdc, 0x4e, 0x9c, 0xb6, - 0xa2, 0x9c, 0x71, 0xf6, 0x4e, 0x5d, 0x29, 0xc0, 0x00, 0x6f, 0x73, 0x13, 0x9d, 0x25, 0xe8, 0xb5, 0xa0, 0x74, 0xde, - 0xc0, 0xdd, 0x2c, 0x23, 0x23, 0x5c, 0x7c, 0x58, 0x79, 0x2c, 0xb8, 0x67, 0xbf, 0x90, 0x58, 0x5b, 0x3f, 0x30, 0x66, - 0xf3, 0x82, 0x05, 0x0a, 0x15, 0x28, 0xb0, 0x9c, 0x69, 0x4b, 0xd3, 0x6a, 0xc8, 0x0f, 0x8f, 0xd0, 0xda, 0xb4, 0x1a, - 0xf0, 0xc3, 0xa3, 0x3a, 0xca, 0x8e, 0x21, 0xcb, 0x89, 0x9f, 0x41, 0xbd, 0xae, 0x23, 0x93, 0x62, 0xb2, 0xfb, 0xf5, - 0xa5, 0xfe, 0xa8, 0x6e, 0xc0, 0xf5, 0x03, 0x10, 0xc0, 0x06, 0xe0, 0x10, 0xa8, 0x06, 0x4b, 0x23, 0x82, 0x45, 0x99, - 0x42, 0xfb, 0x1a, 0x7a, 0x6f, 0x34, 0xfc, 0x17, 0xb8, 0x8b, 0xc8, 0x95, 0xff, 0x09, 0x02, 0x7f, 0x45, 0x99, 0x56, - 0xa6, 0xf8, 0x9f, 0x68, 0xf5, 0x0a, 0xe5, 0xac, 0x69, 0xcd, 0x07, 0xd1, 0x9a, 0x08, 0xd5, 0x8c, 0x21, 0xf8, 0xb7, - 0xb2, 0x4c, 0x5b, 0xaa, 0x2a, 0xf5, 0xa1, 0xf1, 0x5a, 0x2b, 0x9c, 0xe5, 0xe3, 0xc8, 0x7b, 0x8d, 0xa1, 0x63, 0x13, - 0x67, 0x29, 0xa7, 0x52, 0x67, 0xaf, 0x0f, 0x65, 0xe4, 0x00, 0xa7, 0x13, 0x36, 0x9e, 0x26, 0xc7, 0x72, 0x9a, 0x38, - 0xc8, 0xfc, 0x9c, 0x61, 0x64, 0x55, 0x03, 0xc2, 0xa2, 0x6c, 0x28, 0x6d, 0x01, 0x26, 0x39, 0x21, 0x64, 0x8a, 0xa1, - 0x28, 0xf2, 0x91, 0xee, 0x87, 0xf5, 0x66, 0x75, 0x5f, 0xbc, 0xd5, 0x00, 0xa7, 0x61, 0x02, 0x81, 0xc0, 0x8b, 0xf8, - 0x26, 0x13, 0x97, 0xe0, 0x31, 0x3c, 0x80, 0x2f, 0xc1, 0x4d, 0x2e, 0x65, 0xbf, 0x57, 0x61, 0x8e, 0x6b, 0x0b, 0x18, - 0x34, 0x58, 0x3d, 0x88, 0x0e, 0x97, 0xd2, 0x66, 0x57, 0x01, 0x62, 0x63, 0x0a, 0xb1, 0x2c, 0xd8, 0xda, 0xb2, 0x67, - 0x3f, 0xab, 0xa6, 0xa1, 0x75, 0xc2, 0xa9, 0xb8, 0xcc, 0x21, 0x8a, 0xca, 0x20, 0x06, 0x77, 0x24, 0x8f, 0xcf, 0x7b, - 0x2b, 0xc2, 0x0b, 0x02, 0x6e, 0x65, 0x89, 0x0c, 0x57, 0x74, 0x39, 0xba, 0xa5, 0xeb, 0xd1, 0x0d, 0x1d, 0xd3, 0xc9, - 0xdf, 0xc7, 0x68, 0x91, 0xad, 0x52, 0xef, 0xe8, 0x7a, 0xb4, 0xa4, 0xdf, 0x8e, 0xe9, 0xd1, 0xdf, 0xc6, 0x64, 0x9a, - 0xe3, 0x61, 0x42, 0x2f, 0xc0, 0xb1, 0x8b, 0xd4, 0xe8, 0xa9, 0xe9, 0x1b, 0x1c, 0x56, 0xa3, 0x7c, 0xc8, 0x47, 0x39, - 0xe5, 0xa3, 0x62, 0x58, 0x8d, 0xc0, 0xd3, 0xb1, 0x1a, 0xf2, 0x51, 0x45, 0xf9, 0xe8, 0x7c, 0x58, 0x8d, 0xce, 0x49, - 0xb3, 0xe9, 0x2f, 0x2b, 0x7e, 0x55, 0xb2, 0x35, 0x6c, 0x0b, 0x58, 0xbe, 0x6e, 0x95, 0xe5, 0xa9, 0xbf, 0xaa, 0xcd, - 0xc9, 0x6c, 0x39, 0x7b, 0x7b, 0xdd, 0xe5, 0xc4, 0xe2, 0x71, 0xdb, 0x74, 0xb8, 0xfa, 0x72, 0xa2, 0x4e, 0x7a, 0x85, - 0xfc, 0x30, 0x9e, 0x0a, 0x75, 0x0e, 0x81, 0x99, 0xc4, 0x2c, 0x8c, 0x19, 0x36, 0x53, 0xa7, 0x81, 0x02, 0x27, 0x1b, - 0x79, 0x2e, 0x8a, 0xd9, 0x28, 0xa7, 0xf0, 0x3e, 0x26, 0x24, 0x12, 0x70, 0x56, 0x9d, 0x54, 0xa3, 0x02, 0x62, 0x8e, - 0xb0, 0x10, 0x1f, 0xa1, 0x5f, 0xea, 0x23, 0x0f, 0x09, 0x3c, 0xc3, 0xbe, 0x16, 0x83, 0x18, 0x8e, 0x78, 0x5b, 0x59, - 0x35, 0x0b, 0x13, 0xa8, 0xac, 0x1a, 0x96, 0xa6, 0xb2, 0x82, 0x66, 0xa3, 0xca, 0xaf, 0xac, 0xc2, 0x31, 0x4a, 0x08, - 0x89, 0x4a, 0x5d, 0x19, 0xa8, 0x4f, 0x12, 0x16, 0x96, 0xba, 0xb2, 0x73, 0xf5, 0xd1, 0xb9, 0x5f, 0xd9, 0x39, 0xb8, - 0x90, 0x0e, 0x12, 0xff, 0x2a, 0xb5, 0x4c, 0xdb, 0xd7, 0xc1, 0xc6, 0xaa, 0xa2, 0x1b, 0x7e, 0x5b, 0x15, 0x71, 0x54, - 0x52, 0x17, 0x03, 0x1a, 0x17, 0x46, 0x24, 0xa9, 0x5e, 0xa3, 0xe0, 0x0f, 0x09, 0xa2, 0xd2, 0x18, 0xbc, 0x3a, 0x93, - 0xae, 0x95, 0x5a, 0x51, 0x31, 0x28, 0x07, 0x05, 0xdc, 0x9f, 0xf2, 0xd6, 0x42, 0xfa, 0x19, 0x22, 0x2a, 0x43, 0x79, - 0x83, 0x5f, 0x30, 0x78, 0x32, 0xbb, 0x4c, 0xc3, 0x64, 0x74, 0x47, 0xe3, 0xd1, 0x12, 0xe1, 0x60, 0xd8, 0x45, 0xaa, - 0xf0, 0xd6, 0x57, 0x90, 0x7e, 0x4b, 0xe3, 0xd1, 0x0d, 0x4d, 0xad, 0xcd, 0xa9, 0x81, 0xba, 0xea, 0x8d, 0xe9, 0x6d, - 0x04, 0xaf, 0xef, 0xa2, 0x25, 0x85, 0xad, 0x74, 0x9a, 0x67, 0x97, 0x22, 0x4a, 0x29, 0x22, 0x10, 0xae, 0x11, 0x39, - 0x70, 0xa9, 0xd1, 0x06, 0xd7, 0x03, 0x28, 0x43, 0xc3, 0x05, 0x2e, 0x07, 0xf1, 0x68, 0xe9, 0x91, 0xa9, 0x54, 0x5f, - 0x64, 0x11, 0x3e, 0xda, 0xd9, 0x68, 0x29, 0x9e, 0x11, 0x0b, 0xe3, 0x0a, 0x86, 0x50, 0x17, 0x56, 0x9a, 0x82, 0xa4, - 0x0b, 0x1c, 0xd9, 0x0b, 0xe3, 0x2a, 0xdc, 0x80, 0x69, 0xd1, 0x1d, 0x98, 0x47, 0x81, 0xc2, 0xc1, 0x25, 0x48, 0x3f, - 0xa1, 0x6c, 0xe7, 0x28, 0x4d, 0x0e, 0x6f, 0x82, 0xd6, 0x3b, 0x13, 0x84, 0xb4, 0xab, 0x9b, 0x6c, 0x49, 0xdf, 0x60, - 0x7b, 0x87, 0x4e, 0x45, 0x05, 0xd5, 0xe7, 0x16, 0x4c, 0x96, 0x6c, 0x10, 0xb6, 0x84, 0xe9, 0x99, 0x5e, 0x03, 0xf6, - 0xf4, 0xe1, 0xd1, 0xce, 0x7c, 0x17, 0xb3, 0xd7, 0x87, 0x65, 0x34, 0x56, 0x16, 0xbc, 0xb9, 0x25, 0x76, 0x4b, 0x36, - 0x9e, 0x2e, 0x8f, 0xcb, 0xe9, 0x12, 0x89, 0x9d, 0xa1, 0x5b, 0x8c, 0xcf, 0x97, 0x0b, 0x9a, 0xe0, 0xd9, 0xc6, 0xaa, - 0xf9, 0xd2, 0xa0, 0xa5, 0xa4, 0x0c, 0xd7, 0xdb, 0x12, 0xfd, 0xff, 0xd5, 0xc5, 0x2f, 0x05, 0x78, 0x09, 0xc6, 0x02, - 0x40, 0xb8, 0x07, 0xd3, 0x82, 0xd4, 0x46, 0xd9, 0x48, 0xd3, 0x30, 0xc5, 0x45, 0x60, 0x52, 0xfa, 0xfd, 0x30, 0x67, - 0x29, 0xf1, 0xa0, 0x43, 0xed, 0x28, 0x5d, 0xa4, 0xbe, 0x10, 0x04, 0x78, 0x24, 0x75, 0x8e, 0x4d, 0xfe, 0x3e, 0x9e, - 0x05, 0x6a, 0x20, 0x82, 0x28, 0x3b, 0xc6, 0x47, 0x0c, 0x5c, 0x14, 0xe9, 0xb8, 0x9d, 0xae, 0x88, 0xd5, 0xee, 0x31, - 0x0b, 0x71, 0x92, 0x30, 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, - 0x04, 0x91, 0x5a, 0x6d, 0x19, 0x97, 0x5d, 0x65, 0x7c, 0x0b, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, - 0x9b, 0x28, 0xe4, 0x27, 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0x6f, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0x57, 0xcd, 0x59, - 0xd7, 0x50, 0x9a, 0xb8, 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, - 0x82, 0x09, 0x3a, 0x9a, 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x5e, 0x26, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, - 0x0f, 0xaa, 0x93, 0x75, 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, - 0xc7, 0x03, 0x78, 0xcd, 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, - 0x6d, 0xc6, 0xa6, 0x4d, 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, - 0x29, 0x70, 0x32, 0x9b, 0xdb, 0x68, 0x49, 0xef, 0xa2, 0x94, 0xde, 0x44, 0x6b, 0xba, 0x8c, 0x2e, 0x8c, 0x89, 0x71, - 0x52, 0xc3, 0x39, 0x00, 0xad, 0x02, 0x48, 0x3c, 0xf5, 0xeb, 0x1d, 0x4f, 0xaa, 0x70, 0x49, 0x53, 0x70, 0x1b, 0xf6, - 0xed, 0x33, 0xcf, 0x7d, 0x89, 0xd4, 0x06, 0x31, 0xd6, 0xac, 0xa1, 0xe2, 0xc6, 0x5b, 0xf7, 0x91, 0xa8, 0x61, 0xe7, - 0xba, 0xd8, 0x44, 0xd5, 0x70, 0x32, 0x2d, 0x01, 0xb1, 0xb5, 0x1c, 0x0e, 0xdd, 0x11, 0xb2, 0x7b, 0xfc, 0xe8, 0x40, - 0xcf, 0x3d, 0x69, 0xb1, 0x6d, 0x5b, 0xfe, 0xc0, 0x10, 0xa6, 0xf4, 0xf3, 0x47, 0x3e, 0x20, 0x56, 0x5c, 0xc1, 0xd9, - 0x08, 0xd4, 0xd1, 0x0a, 0x9d, 0x7e, 0xaf, 0xc2, 0x42, 0x1f, 0xe0, 0x9b, 0xdb, 0x28, 0xa1, 0x77, 0x51, 0xee, 0x91, - 0xb5, 0x65, 0xcd, 0xe4, 0xf4, 0x2c, 0x0b, 0x79, 0xfb, 0x40, 0x2f, 0x17, 0x00, 0xa2, 0x35, 0x88, 0x7d, 0xa9, 0xeb, - 0x11, 0x38, 0x0d, 0xa1, 0x49, 0x68, 0x04, 0x57, 0x15, 0x84, 0x11, 0x70, 0x25, 0xe1, 0x6f, 0x30, 0x51, 0x81, 0x2f, - 0xc0, 0x45, 0x26, 0x4d, 0x73, 0x1e, 0xd4, 0xfe, 0x48, 0xbe, 0x2a, 0xda, 0xde, 0xae, 0x30, 0x9a, 0x60, 0xec, 0x89, - 0xf6, 0x79, 0xa4, 0x1c, 0xc5, 0x45, 0x12, 0x66, 0xa3, 0x5b, 0x75, 0x9e, 0xd3, 0x6c, 0x74, 0xa7, 0x7f, 0x55, 0x74, - 0x4c, 0x7f, 0xd5, 0x01, 0x6d, 0x94, 0xf4, 0xad, 0xe3, 0x6c, 0x40, 0xeb, 0xc5, 0xd2, 0xf8, 0x5f, 0xcb, 0xd1, 0x2d, - 0x95, 0xa3, 0x3b, 0xdf, 0x92, 0x6a, 0x32, 0x2d, 0x8e, 0x05, 0x1a, 0x52, 0x75, 0x7e, 0x5f, 0x00, 0x3f, 0x57, 0x1a, - 0xdf, 0x69, 0xf3, 0xbd, 0xd7, 0xfe, 0xb3, 0x4e, 0x9e, 0x40, 0xb1, 0x44, 0x05, 0xab, 0x46, 0x60, 0xc7, 0xbe, 0xce, - 0xe3, 0xc2, 0x8c, 0x52, 0x4c, 0xad, 0x49, 0x3f, 0x06, 0xae, 0x98, 0xf6, 0x0a, 0x70, 0xb5, 0x04, 0x27, 0x01, 0x88, - 0xa1, 0x09, 0x7b, 0x76, 0x0c, 0x51, 0xcf, 0x8d, 0x63, 0x94, 0x6c, 0xb8, 0x07, 0xc4, 0x5a, 0xe6, 0xad, 0x5c, 0x02, - 0x12, 0x78, 0xeb, 0x61, 0x52, 0x00, 0xc6, 0x60, 0xb9, 0x24, 0x3a, 0x8f, 0x87, 0x3e, 0xa1, 0x5e, 0x68, 0xd4, 0x09, - 0xd9, 0xd8, 0x12, 0x38, 0xfe, 0xb0, 0x3e, 0x04, 0x82, 0x57, 0x79, 0xae, 0xbf, 0xd2, 0xba, 0xfe, 0x52, 0xe9, 0xb9, - 0x63, 0xb9, 0xae, 0xdf, 0xb5, 0xa9, 0xd1, 0x0b, 0xb0, 0xf0, 0xdd, 0x28, 0xf3, 0x48, 0x6e, 0x11, 0x52, 0x15, 0x58, - 0xa9, 0x5b, 0x48, 0x30, 0xff, 0x4a, 0xce, 0x56, 0x65, 0xbe, 0x7a, 0xe4, 0x5e, 0x39, 0x9b, 0x9e, 0xfe, 0x86, 0x04, - 0xed, 0xae, 0x23, 0xcd, 0xe3, 0x2d, 0x3a, 0x7c, 0x76, 0xad, 0x25, 0xe6, 0x4e, 0xa2, 0xe2, 0xf9, 0x14, 0xb0, 0xd5, - 0xb3, 0xec, 0x4a, 0xf9, 0x58, 0xed, 0xe2, 0xf8, 0x99, 0xf3, 0x27, 0xa9, 0xc2, 0xb5, 0x68, 0x28, 0x41, 0xc0, 0x9b, - 0xc3, 0xd8, 0x15, 0xaa, 0x80, 0x86, 0xe6, 0x06, 0x8e, 0x73, 0x35, 0xac, 0x34, 0x01, 0xd3, 0x52, 0x1e, 0x1d, 0xe0, - 0xd0, 0xe4, 0x51, 0xbb, 0x69, 0x58, 0x19, 0xba, 0xd6, 0xe8, 0x73, 0x5b, 0xe9, 0x8c, 0x37, 0x1b, 0x7e, 0x78, 0x34, - 0xa8, 0xf0, 0x27, 0x69, 0x8e, 0x46, 0x3b, 0x37, 0xdc, 0x69, 0x04, 0x66, 0xae, 0xe4, 0x8a, 0xec, 0x8e, 0x92, 0x97, - 0xdf, 0xd3, 0x0b, 0x0b, 0xe8, 0xcf, 0x7f, 0x2e, 0x26, 0x9c, 0xb4, 0xc4, 0x84, 0x68, 0xe9, 0xa0, 0x45, 0x07, 0x3b, - 0xca, 0x2b, 0xfb, 0x12, 0x2f, 0x9d, 0xe3, 0x7f, 0x5f, 0x8f, 0xb5, 0xab, 0x40, 0x68, 0x75, 0xf2, 0xb0, 0x3d, 0x59, - 0x20, 0x6a, 0x40, 0x35, 0xbb, 0x2a, 0x47, 0x99, 0x76, 0x56, 0x64, 0xd3, 0x90, 0xb9, 0xee, 0x66, 0x69, 0xd8, 0x4c, - 0x76, 0x2c, 0x2c, 0x33, 0x0c, 0xd6, 0x4e, 0x15, 0x7d, 0x0e, 0x5a, 0x7e, 0x04, 0xcf, 0x9a, 0xca, 0x33, 0x9f, 0xcd, - 0x32, 0xe2, 0x05, 0x3a, 0xe7, 0x54, 0x2c, 0x9a, 0xd2, 0xb1, 0x72, 0xbb, 0x2d, 0xd1, 0x58, 0xa2, 0x8c, 0x82, 0xa0, - 0xb6, 0x41, 0xd8, 0x75, 0xe9, 0x9e, 0xf4, 0x69, 0x17, 0x9f, 0x56, 0xa0, 0xef, 0xf1, 0x3e, 0x03, 0x89, 0xa9, 0x27, - 0x79, 0xa8, 0x1a, 0xcd, 0xd1, 0xc9, 0xb3, 0x24, 0xd5, 0xf8, 0xfc, 0x4a, 0x76, 0xd6, 0xbc, 0x5b, 0x8d, 0x29, 0xfe, - 0x23, 0x75, 0xfb, 0xce, 0x65, 0x68, 0xa2, 0xbf, 0x96, 0x07, 0x2d, 0x85, 0x05, 0xc7, 0x6d, 0xe3, 0xaf, 0xdf, 0x66, - 0x0e, 0x31, 0x2c, 0x5d, 0x0e, 0x6f, 0x42, 0x87, 0xee, 0xae, 0xb2, 0x33, 0xd7, 0x47, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, - 0x50, 0xb2, 0xe4, 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0xaf, 0x87, 0xe1, 0xce, 0x3c, 0x6a, 0x76, 0x77, 0xbb, 0x9d, 0x90, - 0xb6, 0x7d, 0x30, 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0x76, 0xf0, 0x73, 0x58, 0x3d, 0xe4, 0x83, 0x7f, 0xe1, 0x38, - 0xc3, 0xe8, 0x67, 0xca, 0xd0, 0xe7, 0x45, 0x21, 0xaf, 0x54, 0xa7, 0x7c, 0xa1, 0x5b, 0xcb, 0xd4, 0xfb, 0x75, 0xfc, - 0xba, 0x15, 0x20, 0xc6, 0xeb, 0x8a, 0x95, 0xe2, 0x0d, 0xad, 0x30, 0xae, 0x81, 0xdb, 0xe4, 0x50, 0x4b, 0xb5, 0x40, - 0xd4, 0xe5, 0x27, 0x0f, 0x79, 0x64, 0xd4, 0x99, 0xf0, 0xdd, 0x43, 0xee, 0x4b, 0xd7, 0x76, 0x9b, 0xf8, 0xb9, 0xa6, - 0x1d, 0xee, 0x0e, 0x74, 0x47, 0xeb, 0xee, 0x6f, 0x9e, 0xcd, 0xcf, 0x23, 0xf3, 0xc5, 0x00, 0x9b, 0xb5, 0xcb, 0xb8, - 0xec, 0x18, 0xee, 0x7b, 0xd3, 0x83, 0xb1, 0x80, 0x40, 0x62, 0x86, 0x5e, 0x06, 0x2e, 0x70, 0x81, 0xbb, 0xc2, 0x80, - 0x21, 0xae, 0x69, 0xc9, 0x9d, 0xb6, 0xb2, 0xf5, 0x91, 0xb7, 0x51, 0x21, 0x58, 0xd7, 0x1d, 0x37, 0x49, 0x0e, 0xc1, - 0x09, 0x5b, 0xee, 0x7d, 0xed, 0xb5, 0x33, 0xfc, 0x65, 0x20, 0x9c, 0x5b, 0xa2, 0x67, 0xd4, 0xf6, 0x50, 0xab, 0x7b, - 0x0d, 0xaf, 0x72, 0x17, 0x79, 0xd6, 0x6f, 0xe6, 0xa5, 0x61, 0x5f, 0xf0, 0x5a, 0x0a, 0x0e, 0x8d, 0xed, 0x56, 0xb8, - 0xc5, 0xe2, 0x1d, 0xad, 0x56, 0xd6, 0xda, 0x6a, 0xaf, 0x95, 0x8a, 0xee, 0x5f, 0x73, 0x9c, 0x38, 0x4b, 0x61, 0xfb, - 0xe1, 0xfd, 0x05, 0xbb, 0x26, 0x80, 0x41, 0x8b, 0xc9, 0x02, 0x25, 0xa8, 0x64, 0xad, 0x6a, 0xb7, 0x53, 0xe2, 0x97, - 0xfb, 0x45, 0x97, 0xd9, 0xce, 0xe3, 0xd7, 0x4d, 0xda, 0x67, 0x3e, 0x47, 0x3f, 0xcc, 0xef, 0xac, 0x93, 0x92, 0x33, - 0x8c, 0x6b, 0xf9, 0xff, 0x55, 0xf4, 0xb2, 0xc8, 0xd2, 0x68, 0x63, 0x78, 0x30, 0x1b, 0x6a, 0xd3, 0x87, 0xc6, 0xa8, - 0xdc, 0xb2, 0x51, 0x44, 0xb4, 0xba, 0x05, 0xc1, 0x8c, 0xe2, 0xbe, 0x44, 0x9b, 0x57, 0xaa, 0x2c, 0xbc, 0xc3, 0x67, - 0x36, 0x7a, 0xc3, 0xf6, 0x84, 0x50, 0xbe, 0x7b, 0x5a, 0x98, 0x55, 0x4b, 0x45, 0x83, 0xed, 0x12, 0xde, 0xc5, 0xa8, - 0xd2, 0x4f, 0x98, 0x6c, 0x59, 0x30, 0xd5, 0xff, 0xef, 0x8b, 0x2c, 0x6d, 0x53, 0x74, 0x60, 0x3a, 0x9b, 0x3e, 0x9d, - 0x74, 0x83, 0xeb, 0x0c, 0x58, 0x44, 0xb0, 0xa5, 0xc2, 0xf1, 0x28, 0xb5, 0x1b, 0x24, 0x4c, 0x04, 0x37, 0x51, 0x2f, - 0x3b, 0x5a, 0xa6, 0x64, 0x55, 0xc0, 0xf3, 0x2b, 0x57, 0x99, 0x8e, 0xa3, 0xa1, 0xdf, 0x3f, 0x4f, 0x4d, 0xe8, 0x57, - 0xea, 0xa5, 0x2a, 0xce, 0xc3, 0xa8, 0x3a, 0x54, 0x18, 0xa3, 0x25, 0x4d, 0xe1, 0x18, 0xcc, 0x2e, 0xc2, 0x14, 0x2f, - 0x67, 0x9b, 0x84, 0x7d, 0xc1, 0x40, 0x2e, 0xb5, 0x41, 0xbd, 0xa6, 0x44, 0x6b, 0xd6, 0xde, 0xcc, 0x29, 0xa1, 0x17, - 0xac, 0xf4, 0xef, 0x42, 0x6b, 0x10, 0x28, 0xca, 0x66, 0xca, 0xf4, 0x4c, 0xb7, 0xf3, 0x82, 0x26, 0xb4, 0xa0, 0x2b, - 0x52, 0x83, 0xbe, 0xd7, 0xc9, 0xd9, 0xd1, 0xc9, 0xce, 0xcc, 0x7a, 0xcc, 0x8a, 0xe1, 0x64, 0x1a, 0xc3, 0x35, 0x2d, - 0x76, 0xd7, 0xb4, 0x65, 0xf3, 0xc6, 0xd5, 0xd8, 0x38, 0x0d, 0xda, 0x05, 0xd2, 0x36, 0xcd, 0xed, 0xa7, 0x1e, 0xb7, - 0xbf, 0xae, 0xd9, 0x72, 0xda, 0x5b, 0x6f, 0xb7, 0xbd, 0x14, 0x6c, 0x44, 0x3d, 0x3e, 0x7e, 0xad, 0xa4, 0xeb, 0x96, - 0xcb, 0x4f, 0xe1, 0xd9, 0xe3, 0xeb, 0x97, 0x3e, 0xb8, 0x1c, 0xad, 0xda, 0xdc, 0xfd, 0x72, 0x17, 0x59, 0xee, 0x8b, - 0x86, 0x96, 0xeb, 0x19, 0x6a, 0x92, 0x67, 0xa3, 0xbd, 0x43, 0x2d, 0x58, 0xce, 0xba, 0x09, 0x4f, 0x0c, 0x76, 0xec, - 0x55, 0x63, 0x73, 0x54, 0xe6, 0x92, 0xd5, 0x20, 0x81, 0x3e, 0xc9, 0x33, 0x4d, 0xff, 0x20, 0xc3, 0x7c, 0x74, 0x4b, - 0x73, 0xc0, 0x15, 0xab, 0xec, 0x25, 0x83, 0xd4, 0x55, 0x7b, 0x89, 0x2b, 0x5f, 0xe1, 0x90, 0x6c, 0xf0, 0xc9, 0x30, - 0x55, 0x9f, 0x5d, 0xf2, 0xe0, 0xff, 0x6d, 0xd5, 0x2a, 0x3d, 0x37, 0xc9, 0x0d, 0xc7, 0xbf, 0x4e, 0xda, 0x3e, 0x26, - 0x06, 0x09, 0x78, 0x6a, 0x17, 0x43, 0x35, 0xaa, 0x8a, 0x58, 0x94, 0xb9, 0x89, 0x39, 0xb6, 0xb7, 0x6b, 0xe8, 0xa0, - 0x0c, 0x7e, 0xdd, 0xf0, 0x89, 0xb9, 0x03, 0x5b, 0x81, 0x8e, 0x4e, 0x34, 0x97, 0x61, 0x66, 0x2e, 0xc3, 0xb4, 0x6b, - 0xab, 0xc0, 0xf0, 0xaa, 0xad, 0x92, 0x28, 0x57, 0xa3, 0x1e, 0x37, 0xb3, 0xd4, 0xec, 0x45, 0xde, 0xbd, 0x26, 0x3d, - 0x89, 0x3f, 0x5d, 0x7a, 0xf2, 0x7a, 0x18, 0x10, 0xf9, 0x25, 0x4b, 0xc3, 0x35, 0x0a, 0x82, 0x53, 0xab, 0x1d, 0x48, - 0xf3, 0x11, 0x20, 0xf3, 0xe3, 0x34, 0x7c, 0xa7, 0xc5, 0x39, 0x64, 0xa3, 0x34, 0x4e, 0x6c, 0x69, 0xd4, 0x43, 0x70, - 0xe7, 0xbd, 0xe2, 0x31, 0x04, 0x3e, 0xfc, 0x80, 0x9b, 0x41, 0x45, 0xb7, 0x25, 0x26, 0x4a, 0x9b, 0x47, 0xdd, 0xf2, - 0x51, 0x43, 0xa8, 0x64, 0x65, 0x78, 0x09, 0xb4, 0x77, 0x47, 0x60, 0x54, 0x39, 0x81, 0xcc, 0xb0, 0x38, 0x3c, 0x1a, - 0xa6, 0x4a, 0x50, 0x34, 0x94, 0xc3, 0x25, 0xca, 0x01, 0x31, 0x09, 0x04, 0x46, 0xc5, 0x20, 0xd5, 0x95, 0xa9, 0x17, - 0x83, 0x54, 0xdf, 0xaa, 0x48, 0x7d, 0x96, 0x85, 0x15, 0xd5, 0x2d, 0xa2, 0x63, 0x3a, 0x94, 0x74, 0x69, 0x76, 0x6a, - 0xae, 0xa5, 0x17, 0x6a, 0x39, 0x3e, 0xd5, 0x69, 0x30, 0x8a, 0xef, 0x5d, 0x8a, 0x7e, 0xab, 0xf6, 0xb3, 0xff, 0x16, - 0x53, 0x6a, 0xc4, 0xa6, 0xf6, 0x16, 0x31, 0xac, 0xda, 0x0f, 0x59, 0x95, 0x83, 0x76, 0x17, 0x94, 0x8d, 0x95, 0x71, - 0x9e, 0x6f, 0x04, 0x33, 0x07, 0x6d, 0x63, 0xd5, 0xf4, 0xa1, 0x37, 0x62, 0xd4, 0xde, 0x98, 0x6a, 0xdc, 0x13, 0xf8, - 0x69, 0x83, 0xa6, 0x7b, 0x91, 0xe7, 0xa8, 0x47, 0xde, 0xfd, 0xcf, 0x1c, 0xd9, 0x99, 0x7c, 0x16, 0xcb, 0xa4, 0x6e, - 0x1f, 0x93, 0x60, 0xa1, 0xea, 0x18, 0x5d, 0xb8, 0x91, 0x29, 0xed, 0xe7, 0xce, 0xf4, 0x23, 0x9e, 0xc9, 0xfd, 0x76, - 0x68, 0xd4, 0x97, 0x86, 0xb5, 0xa4, 0x88, 0xfa, 0x82, 0xde, 0x9a, 0xea, 0xe8, 0x88, 0x7a, 0x1d, 0x81, 0xd5, 0x15, - 0x6d, 0x50, 0x03, 0x30, 0x19, 0xd7, 0xb6, 0x36, 0x9f, 0x83, 0xa9, 0xad, 0xaa, 0xe0, 0x09, 0xdd, 0x15, 0x4a, 0xf7, - 0x26, 0x75, 0xdd, 0x1a, 0x62, 0x0b, 0x18, 0x10, 0xb8, 0xd1, 0x53, 0xd3, 0x1f, 0x34, 0x51, 0x01, 0x68, 0xd0, 0xb8, - 0x9d, 0xe9, 0x1c, 0x89, 0x7e, 0xa7, 0x36, 0x6d, 0x33, 0xd5, 0xab, 0xca, 0x07, 0x50, 0xf1, 0x67, 0xe9, 0xec, 0xc2, - 0x8c, 0x58, 0x00, 0xe3, 0x1e, 0x38, 0x53, 0xbd, 0xd3, 0x0c, 0xac, 0x27, 0xf2, 0x3c, 0x2b, 0x79, 0x22, 0x05, 0xcc, - 0x88, 0xbc, 0xba, 0x92, 0x02, 0x86, 0x41, 0x0d, 0x00, 0x5a, 0x34, 0x97, 0xd1, 0x84, 0x3f, 0xaa, 0xe9, 0xbe, 0x3c, - 0xfc, 0x91, 0xce, 0xf5, 0xcd, 0xb8, 0x06, 0x43, 0xe5, 0x75, 0xc5, 0x77, 0x32, 0x7d, 0xc3, 0x1f, 0x7b, 0x99, 0x96, - 0x72, 0x5d, 0xec, 0x64, 0x79, 0xf4, 0x0d, 0x7f, 0xa2, 0xf3, 0x1c, 0x3d, 0xae, 0x69, 0x1a, 0xdf, 0xed, 0x64, 0xf9, - 0xfb, 0x37, 0x8f, 0x6d, 0x9e, 0x47, 0xe3, 0x9a, 0xde, 0x70, 0xfe, 0xd1, 0x65, 0x9a, 0xe8, 0xaa, 0xc6, 0x8f, 0xff, - 0x6e, 0x73, 0x3d, 0xae, 0xe9, 0x95, 0x14, 0xd5, 0x72, 0xa7, 0xa8, 0xa3, 0x6f, 0x8e, 0xfe, 0xce, 0xbf, 0x31, 0xdd, - 0x3b, 0xaa, 0xe9, 0x5f, 0xeb, 0xb8, 0xa8, 0x78, 0xb1, 0x53, 0xdc, 0xdf, 0xfe, 0xfe, 0xf7, 0xc7, 0x36, 0xe3, 0xe3, - 0x9a, 0xde, 0xf1, 0xb8, 0xa3, 0xed, 0x93, 0x27, 0x8f, 0xf9, 0xdf, 0xea, 0x9a, 0xfe, 0xc6, 0xfc, 0xe0, 0xa8, 0xa7, - 0x99, 0xa7, 0x87, 0xcf, 0x65, 0x13, 0x35, 0x60, 0xe8, 0xa1, 0x01, 0x2c, 0xa5, 0x55, 0xd3, 0xec, 0xf1, 0xca, 0x05, - 0xb7, 0xef, 0xb3, 0x38, 0x8d, 0x57, 0x70, 0x10, 0x6c, 0xd0, 0x38, 0xab, 0x00, 0x4e, 0x15, 0x78, 0xcf, 0xa8, 0xa4, - 0x59, 0x29, 0x7f, 0xe3, 0xfc, 0x23, 0x0c, 0x1a, 0x42, 0xda, 0xa8, 0xc8, 0x40, 0x6f, 0x56, 0x3a, 0xb2, 0x11, 0xfa, - 0x6f, 0x36, 0xe3, 0xe0, 0xf8, 0x30, 0x7a, 0xfd, 0x7e, 0x58, 0x30, 0x11, 0x16, 0x84, 0xd0, 0x3f, 0xc3, 0x02, 0x1c, - 0x4a, 0x0a, 0xe6, 0xe5, 0x33, 0xbe, 0xe7, 0xda, 0x28, 0x2c, 0x04, 0xd1, 0x5d, 0x64, 0x1f, 0x50, 0xf5, 0xe8, 0x3b, - 0x74, 0x43, 0xbc, 0xac, 0xb0, 0x60, 0x68, 0x55, 0x03, 0x33, 0x04, 0xc5, 0xbf, 0xe2, 0xa1, 0x04, 0x9f, 0x78, 0x80, - 0x8f, 0x1e, 0x93, 0x19, 0x57, 0xd7, 0xda, 0x37, 0x17, 0x61, 0x41, 0x03, 0xdd, 0x76, 0x08, 0x3a, 0x10, 0xf9, 0x2f, - 0xc0, 0x53, 0x60, 0xe0, 0xc3, 0xc2, 0xae, 0x3b, 0xf0, 0x7c, 0x7e, 0x33, 0xac, 0xa3, 0x0b, 0x3f, 0xfa, 0x9b, 0x75, - 0x61, 0xcf, 0xc8, 0x54, 0x1e, 0x97, 0xc3, 0xc9, 0x74, 0x30, 0x90, 0x2e, 0x8e, 0xdb, 0x69, 0x36, 0xff, 0x6d, 0x2e, - 0x17, 0x0b, 0xd4, 0x7d, 0xe3, 0xbc, 0xce, 0xf4, 0xdf, 0x48, 0x3b, 0x1f, 0xbc, 0x3a, 0xfd, 0xfd, 0xec, 0xfd, 0xe9, - 0x0b, 0x70, 0x3e, 0xf8, 0xf0, 0xfc, 0xfb, 0xe7, 0xef, 0x54, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, 0x93, 0xfa, 0x84, - 0x7c, 0x58, 0x91, 0xc3, 0x30, 0x7e, 0x58, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, 0x51, 0xdb, 0xdf, - 0xe5, 0x70, 0xe2, 0x81, 0x59, 0xdc, 0x36, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x79, 0xe2, 0xf5, 0x83, 0x93, - 0xa9, 0x74, 0x6c, 0x61, 0xc1, 0xa0, 0x6c, 0x68, 0xd3, 0x69, 0x36, 0x2f, 0x16, 0xb6, 0x5d, 0x6e, 0x81, 0x8c, 0xd2, - 0xec, 0xe2, 0x22, 0x54, 0xd0, 0xd5, 0x27, 0xa0, 0x01, 0x30, 0x8d, 0x2a, 0x5c, 0x8b, 0xf8, 0xcc, 0x2f, 0x3f, 0x1a, - 0x7b, 0xcd, 0xbb, 0x46, 0xdd, 0x93, 0x69, 0x56, 0xd5, 0x18, 0xd0, 0xc1, 0x84, 0x72, 0x37, 0xe8, 0x26, 0x98, 0x8c, - 0x6a, 0xcb, 0x6f, 0xf3, 0x6a, 0x61, 0x9a, 0xe3, 0x86, 0xa1, 0xf2, 0x4a, 0xbe, 0x90, 0x0d, 0x44, 0x06, 0x92, 0x61, - 0xd8, 0xa3, 0x31, 0x8a, 0xd4, 0x0f, 0x76, 0xbd, 0xe3, 0x37, 0xb9, 0x84, 0x68, 0x8a, 0x19, 0x48, 0xe7, 0x4f, 0x85, - 0x72, 0x2e, 0x97, 0x8c, 0xcf, 0xc5, 0xe2, 0x04, 0xdc, 0xce, 0xe7, 0x62, 0x11, 0x61, 0x50, 0xbe, 0x0c, 0x62, 0x95, - 0x80, 0xdd, 0x8b, 0x83, 0xf0, 0xed, 0x84, 0x36, 0xb0, 0x1b, 0x48, 0xb2, 0x41, 0x69, 0x57, 0x1a, 0xa2, 0xdc, 0x29, - 0x8f, 0x36, 0x88, 0x3c, 0xc4, 0xaa, 0x79, 0xd5, 0xf6, 0x64, 0x33, 0x17, 0x13, 0x5c, 0x65, 0x31, 0x93, 0xd3, 0xf8, - 0x98, 0x15, 0xd3, 0x18, 0x4a, 0x89, 0xd3, 0x34, 0x8c, 0xe9, 0x84, 0x0a, 0x42, 0x12, 0xc6, 0xe7, 0xf1, 0x82, 0x26, - 0x28, 0x25, 0x08, 0x21, 0xe4, 0xc7, 0x08, 0x6d, 0x73, 0x60, 0xc9, 0xdb, 0xed, 0xe7, 0xe9, 0xe7, 0x76, 0x0c, 0x97, - 0x51, 0x11, 0xba, 0x41, 0x67, 0x0d, 0xff, 0x46, 0x54, 0xd0, 0x18, 0x2b, 0x86, 0x20, 0xe0, 0x05, 0x46, 0x25, 0x2c, - 0x48, 0xcc, 0x2a, 0x88, 0x22, 0x50, 0xce, 0xe3, 0x05, 0x2b, 0x68, 0xd3, 0xe6, 0x34, 0xd6, 0x26, 0x41, 0x3d, 0x87, - 0xa5, 0x76, 0x20, 0x95, 0x0a, 0xb1, 0xc7, 0x67, 0x22, 0xba, 0xd1, 0x86, 0x06, 0x80, 0x02, 0xa5, 0xe4, 0xe2, 0x37, - 0x5f, 0xee, 0xe1, 0xa6, 0xa0, 0xff, 0xd9, 0xc6, 0x44, 0x3b, 0xcb, 0xd5, 0xa1, 0x37, 0x5f, 0xd0, 0x38, 0xcf, 0x21, - 0x14, 0x9b, 0x41, 0x20, 0x17, 0x59, 0x05, 0x11, 0x2d, 0xee, 0x02, 0x13, 0x12, 0x0e, 0xda, 0xf4, 0x0b, 0xa4, 0x36, - 0xc4, 0xe4, 0xca, 0x13, 0x03, 0xbb, 0xad, 0x12, 0x04, 0x1c, 0xe9, 0x79, 0xf6, 0xa9, 0x89, 0xb1, 0xa6, 0xa9, 0x99, - 0x89, 0xb7, 0xa1, 0x10, 0x0d, 0x5a, 0x10, 0xcd, 0xe0, 0xfd, 0x73, 0xc5, 0xf1, 0xaa, 0x03, 0x3f, 0xe0, 0x9d, 0x8b, - 0x33, 0xaf, 0x66, 0x1e, 0x91, 0x53, 0x4f, 0x73, 0x44, 0xbf, 0xe4, 0x61, 0x35, 0xd2, 0xc9, 0x18, 0x2b, 0x89, 0x83, - 0xde, 0x06, 0x0b, 0xe6, 0x84, 0xae, 0x78, 0x68, 0xf9, 0xf8, 0x17, 0xc8, 0x64, 0x94, 0xd4, 0x58, 0xd1, 0x95, 0x16, - 0x23, 0xce, 0x6b, 0x98, 0xa5, 0xc9, 0x8a, 0x2e, 0x16, 0x9a, 0x34, 0x0b, 0x65, 0x1a, 0xe0, 0x13, 0x68, 0x31, 0x72, - 0x0f, 0x35, 0x6d, 0x20, 0x34, 0xec, 0x0e, 0x01, 0x1f, 0xb9, 0x87, 0x0e, 0xff, 0x3f, 0xcf, 0x2e, 0x10, 0x69, 0xef, - 0xd2, 0x44, 0xc6, 0x23, 0x75, 0x03, 0x07, 0xc5, 0xf8, 0xd8, 0x37, 0x13, 0xbf, 0x70, 0x46, 0xef, 0x93, 0xca, 0x77, - 0xf8, 0x60, 0xf9, 0xe3, 0x4d, 0xcd, 0xac, 0x8c, 0x60, 0x3d, 0x6c, 0xb7, 0xb8, 0x20, 0xda, 0x2e, 0x80, 0xd4, 0x33, - 0x5e, 0x2d, 0x7c, 0xe3, 0xd5, 0x78, 0x8f, 0xf1, 0xaa, 0xb3, 0xc2, 0x0a, 0x73, 0xb2, 0x41, 0x7d, 0x96, 0x92, 0xe7, - 0xe7, 0x28, 0x13, 0x6c, 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, - 0x0e, 0x23, 0x81, 0xaa, 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, - 0x03, 0xa1, 0xa1, 0xb1, 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xed, 0xb6, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, - 0xac, 0x46, 0x13, 0xe0, 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, - 0x49, 0x66, 0x65, 0x34, 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, - 0xba, 0xcc, 0x92, 0xcc, 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, - 0x90, 0x1f, 0x40, 0x19, 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, - 0x64, 0x57, 0xbc, 0xac, 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0x6c, 0x9f, 0xdb, 0x1e, 0x15, 0xe6, 0xd5, 0xeb, 0xe7, - 0xdf, 0x9f, 0x36, 0x5e, 0xed, 0x22, 0x8e, 0x86, 0x60, 0x5b, 0x31, 0xc6, 0xe8, 0x2d, 0x3e, 0x0d, 0x26, 0xca, 0x35, - 0x02, 0xbd, 0x4b, 0x41, 0xbf, 0xfd, 0xa5, 0x9e, 0x80, 0x57, 0x5c, 0x2f, 0xbf, 0xe4, 0x23, 0x60, 0x89, 0x0a, 0x3d, - 0x2b, 0xcc, 0xcd, 0xca, 0x6c, 0x6f, 0xb7, 0x22, 0x33, 0xed, 0x4a, 0x23, 0x03, 0xf1, 0x6a, 0x3b, 0x8c, 0x85, 0x4b, - 0xd7, 0x74, 0x3b, 0xd8, 0xd5, 0xd2, 0xb3, 0x44, 0xde, 0x6e, 0x4b, 0xe8, 0x90, 0x1d, 0x70, 0xef, 0x65, 0x7c, 0x0b, - 0x2f, 0x4b, 0xaf, 0x9b, 0xcd, 0xe0, 0x09, 0x60, 0x26, 0x5c, 0x38, 0xcb, 0xe2, 0x98, 0x65, 0x49, 0xa8, 0x62, 0x73, - 0x35, 0x44, 0xde, 0x8a, 0xd0, 0x9a, 0xfd, 0x15, 0x8a, 0x11, 0xd8, 0x9d, 0xbc, 0xff, 0x98, 0xad, 0x66, 0x6b, 0x40, - 0xcd, 0xbf, 0xca, 0x04, 0xd0, 0x5c, 0xbb, 0x16, 0x6c, 0x53, 0x68, 0x73, 0x5d, 0x3f, 0x8d, 0x57, 0x71, 0x02, 0xaa, - 0x1b, 0xf0, 0x16, 0xb9, 0xd5, 0xa2, 0x2b, 0x83, 0x2e, 0x4a, 0xef, 0x29, 0xc7, 0x92, 0x42, 0x47, 0xdf, 0x7b, 0x42, - 0x9d, 0x7b, 0x06, 0x70, 0x49, 0xa3, 0xe6, 0xa9, 0x96, 0x32, 0x16, 0x00, 0x0b, 0x1d, 0xcc, 0x14, 0xd9, 0x8a, 0xae, - 0x0d, 0x26, 0x05, 0xbc, 0x35, 0xc0, 0x1f, 0x22, 0xab, 0xd4, 0x5d, 0xb1, 0x0c, 0x4b, 0xcf, 0xfe, 0xba, 0xdf, 0x8f, - 0x3d, 0xfb, 0xeb, 0x95, 0xa6, 0x75, 0x71, 0xbb, 0x01, 0xa4, 0xc6, 0x00, 0x22, 0xa7, 0x7a, 0x20, 0x4c, 0x44, 0xb1, - 0xa6, 0xef, 0xdf, 0xa9, 0xc9, 0xa2, 0x40, 0xe8, 0x77, 0xea, 0xf5, 0xa4, 0x24, 0xa0, 0x53, 0xab, 0xd8, 0xc9, 0x40, - 0x9b, 0x7d, 0x40, 0x40, 0x54, 0x3f, 0x23, 0x9b, 0x2f, 0x94, 0x73, 0xb1, 0x0a, 0x1f, 0x3e, 0xa6, 0x10, 0x50, 0xb8, - 0xa3, 0x46, 0xe7, 0x6d, 0x88, 0x04, 0xca, 0x0a, 0x45, 0xac, 0x79, 0xb1, 0x96, 0x84, 0xcc, 0xc7, 0x0b, 0x14, 0x5c, - 0x39, 0x60, 0x57, 0xce, 0x26, 0xc3, 0x32, 0xe2, 0x2c, 0xdc, 0xff, 0xcd, 0x64, 0x41, 0x50, 0x73, 0xe5, 0x07, 0x72, - 0xdc, 0xc9, 0xd4, 0xd8, 0x53, 0x8d, 0x1a, 0x04, 0x93, 0x11, 0x04, 0x86, 0x1b, 0x7e, 0xc1, 0xc7, 0x47, 0x0b, 0x02, - 0x2a, 0x32, 0x6b, 0x16, 0x62, 0x5e, 0x1c, 0x3f, 0x02, 0xd4, 0x98, 0xd1, 0xd1, 0x93, 0x29, 0x67, 0x70, 0x88, 0xd2, - 0x31, 0xc8, 0x68, 0x05, 0xfc, 0x16, 0xea, 0x77, 0xeb, 0xc4, 0xf7, 0xa1, 0x5f, 0x05, 0xbd, 0x88, 0x81, 0xe1, 0x88, - 0x26, 0x87, 0x21, 0x1f, 0x4c, 0x06, 0xa0, 0x2d, 0xf1, 0x76, 0x5f, 0x4b, 0x2b, 0x6e, 0x4e, 0x97, 0x4e, 0xf7, 0x4f, - 0xda, 0x04, 0x49, 0xa4, 0x92, 0x95, 0x8a, 0x18, 0x40, 0x28, 0x4b, 0xb5, 0x4d, 0xd6, 0x60, 0x59, 0x61, 0x96, 0x34, - 0x37, 0x28, 0x89, 0xbb, 0x9b, 0x81, 0x63, 0xd4, 0xac, 0xd3, 0xb0, 0x6c, 0xb9, 0x51, 0x03, 0x7c, 0x4e, 0xc2, 0x0a, - 0x7b, 0xc3, 0x99, 0x49, 0xef, 0x4c, 0x87, 0xab, 0x63, 0xce, 0x5e, 0x71, 0x04, 0xe3, 0x48, 0xf0, 0xc6, 0x43, 0x97, - 0x4c, 0x43, 0x45, 0xa6, 0x8c, 0x83, 0x69, 0x0f, 0x70, 0xef, 0x39, 0x18, 0x87, 0xb1, 0x41, 0x65, 0x49, 0x7d, 0xea, - 0xdd, 0x85, 0x40, 0x90, 0xd6, 0x7a, 0x99, 0xcf, 0xf0, 0xf4, 0x8c, 0x50, 0xf6, 0x87, 0x1c, 0xbe, 0x00, 0x3b, 0x0a, - 0x72, 0x32, 0xe1, 0x4f, 0x1e, 0xee, 0x06, 0xaa, 0xe2, 0x83, 0xe0, 0x20, 0x16, 0xe9, 0x41, 0x30, 0x10, 0xf0, 0xab, - 0xe0, 0x07, 0x95, 0x94, 0x07, 0x17, 0x71, 0x71, 0x10, 0xaf, 0xe2, 0xa2, 0x3a, 0xb8, 0xc9, 0xaa, 0xe5, 0x81, 0xe9, - 0x10, 0x40, 0xf3, 0x06, 0x83, 0x78, 0x10, 0x1c, 0x04, 0x83, 0xc2, 0x4c, 0xed, 0x8a, 0x95, 0x8d, 0xe3, 0xcc, 0x84, - 0x28, 0x0b, 0x9a, 0x01, 0xc2, 0x1a, 0xa7, 0x01, 0xf0, 0xa9, 0x6b, 0x96, 0xd2, 0x0b, 0x0c, 0x37, 0x20, 0xa6, 0x6b, - 0xe8, 0x03, 0xf0, 0xc8, 0x6b, 0x1a, 0xc3, 0x12, 0xb8, 0x18, 0x0c, 0xc8, 0x05, 0x44, 0x2e, 0x58, 0x53, 0x1b, 0xc4, - 0x21, 0x5c, 0x2b, 0x3b, 0xed, 0x5d, 0x60, 0xa6, 0xed, 0x16, 0x10, 0x95, 0x27, 0xa4, 0xdf, 0xb7, 0xdf, 0x50, 0xff, - 0x82, 0xbd, 0x04, 0xfb, 0xab, 0xa2, 0x0a, 0x73, 0xa9, 0x34, 0xdf, 0x97, 0xec, 0x64, 0xa0, 0x22, 0x0e, 0xef, 0x38, - 0x52, 0xb4, 0x51, 0xb9, 0x2c, 0x7b, 0xb2, 0x6c, 0xf8, 0x4a, 0x5c, 0x71, 0xe7, 0xc7, 0x55, 0x49, 0x99, 0x57, 0xd9, - 0x4a, 0xb1, 0x7f, 0x33, 0xae, 0xb9, 0x3f, 0xb0, 0xfe, 0x6c, 0xbe, 0x82, 0x6b, 0xab, 0xf7, 0xae, 0xc9, 0x35, 0x22, - 0x67, 0x09, 0xe5, 0x92, 0xda, 0xe6, 0xe1, 0x2d, 0x7d, 0x9f, 0x5f, 0x7d, 0x9b, 0xe9, 0x34, 0x3e, 0xab, 0xb0, 0x70, - 0x21, 0x5a, 0x11, 0x1c, 0x1a, 0x72, 0xd1, 0x3c, 0x02, 0xcc, 0xb5, 0xcf, 0x56, 0x50, 0x90, 0xfa, 0xac, 0x42, 0xef, - 0x56, 0x48, 0x78, 0xa1, 0xd9, 0xa5, 0xfb, 0x81, 0x94, 0x71, 0x7b, 0x68, 0x09, 0x93, 0x96, 0x17, 0xe1, 0xbd, 0xd7, - 0xdc, 0xe4, 0x9e, 0x85, 0x18, 0xbd, 0xc8, 0xb3, 0x13, 0x30, 0xd6, 0x5d, 0xb2, 0xb3, 0xe1, 0x89, 0xdf, 0xf0, 0x9c, - 0xb5, 0x68, 0x34, 0x5d, 0xb2, 0xa4, 0xdf, 0x8f, 0xc1, 0xc4, 0x3b, 0x65, 0x39, 0xfc, 0xca, 0x17, 0x74, 0xcd, 0x00, - 0x53, 0x8c, 0x5e, 0x40, 0x42, 0x8a, 0x48, 0x24, 0x6b, 0x75, 0x92, 0x7c, 0xa6, 0xbb, 0x00, 0x8c, 0x7e, 0x31, 0x4b, - 0xa3, 0xe5, 0x5e, 0x33, 0x0b, 0x24, 0xcf, 0xd0, 0x77, 0x1d, 0x6c, 0x6f, 0xec, 0x83, 0x94, 0xf3, 0x63, 0x31, 0x1d, - 0x0c, 0x38, 0xd1, 0x70, 0xe3, 0xa5, 0x12, 0xd7, 0xea, 0x16, 0x77, 0x0c, 0x63, 0xa9, 0x6f, 0x8b, 0x18, 0x1c, 0xb0, - 0x8b, 0x56, 0x76, 0xfb, 0x00, 0xfb, 0xca, 0xf1, 0x2e, 0x55, 0x76, 0xa7, 0xc7, 0x4c, 0x73, 0xd9, 0x6a, 0xd2, 0x49, - 0xc5, 0x7e, 0x22, 0xdf, 0xe4, 0x0e, 0xba, 0x5c, 0x8e, 0x35, 0x6f, 0x39, 0x00, 0x15, 0xfd, 0x48, 0x51, 0xdd, 0x2f, - 0x70, 0x84, 0xb9, 0xb7, 0x6e, 0xf3, 0xc9, 0xa1, 0x29, 0x70, 0x88, 0x3c, 0x69, 0xa3, 0x29, 0xa0, 0x7b, 0x17, 0x0f, - 0xbb, 0xfa, 0x6d, 0xe9, 0x2e, 0x50, 0xa2, 0x9d, 0x8a, 0x1b, 0x7e, 0x4c, 0xd4, 0xe9, 0x4c, 0x1b, 0x42, 0xff, 0xca, - 0x88, 0xfb, 0x4b, 0xe3, 0x2a, 0xde, 0xf4, 0x2e, 0x9f, 0x71, 0xa8, 0xb3, 0x1b, 0x42, 0x01, 0xb8, 0x6a, 0x4f, 0xa7, - 0x6e, 0x0c, 0xe9, 0x95, 0x12, 0xdd, 0x06, 0x07, 0xdb, 0xeb, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, - 0x43, 0x39, 0x88, 0x1f, 0x16, 0x74, 0x19, 0x89, 0x87, 0xc5, 0x20, 0x7e, 0x28, 0xeb, 0x7a, 0xf7, 0x5c, 0xd9, 0xdf, - 0x47, 0xe4, 0x59, 0x77, 0xf6, 0x52, 0x09, 0x1b, 0x03, 0xcf, 0xae, 0x05, 0x84, 0x53, 0xf0, 0x44, 0xb6, 0x96, 0x3e, - 0x74, 0x6e, 0xf7, 0xb1, 0x65, 0x92, 0x20, 0xe8, 0x79, 0x9b, 0x4d, 0xa2, 0xd8, 0xd9, 0xe6, 0xd1, 0x87, 0x53, 0x20, - 0xa1, 0xdb, 0x6d, 0xb3, 0xae, 0xd6, 0x80, 0x62, 0x1a, 0x8e, 0xf9, 0x61, 0x31, 0xba, 0xf1, 0xdd, 0xf5, 0x0f, 0x8b, - 0xd1, 0x92, 0x0c, 0x27, 0x66, 0xf2, 0xe3, 0x93, 0xf1, 0x2c, 0x8e, 0x26, 0x75, 0xc7, 0x69, 0xa1, 0xf1, 0x4f, 0xbd, - 0x5b, 0x28, 0x02, 0xa7, 0x62, 0x04, 0x47, 0x4e, 0x85, 0x72, 0x52, 0x6a, 0x60, 0xf8, 0x1f, 0x54, 0x3b, 0xda, 0xb4, - 0x57, 0x71, 0x95, 0x2c, 0x33, 0x71, 0xa9, 0xc3, 0x87, 0xeb, 0xe8, 0xe2, 0x36, 0xa0, 0x9d, 0x77, 0x99, 0x76, 0xfc, - 0x3a, 0x69, 0xd0, 0x13, 0x57, 0x33, 0x03, 0x6e, 0xdd, 0x8f, 0xd0, 0x0c, 0x81, 0xd1, 0xf2, 0xfc, 0x2d, 0x62, 0x6e, - 0xff, 0xaa, 0x6c, 0x7e, 0x15, 0xed, 0x73, 0x64, 0xa4, 0x6c, 0x93, 0x91, 0x0a, 0x8c, 0x30, 0xa5, 0x48, 0xe2, 0x2a, - 0x84, 0x40, 0xf6, 0x5f, 0x52, 0x5c, 0x8b, 0xa5, 0xf7, 0x1a, 0x84, 0x09, 0xb6, 0x0b, 0xda, 0xaf, 0x6e, 0xe7, 0xb6, - 0xd2, 0x62, 0x8f, 0xd4, 0xf7, 0xb9, 0xb3, 0x5d, 0xd1, 0xe4, 0xef, 0xcb, 0x06, 0xb4, 0x01, 0x44, 0xb9, 0xaf, 0x8f, - 0x4a, 0xe0, 0x64, 0xc4, 0x0d, 0x25, 0x46, 0x2f, 0xe8, 0xea, 0x44, 0xee, 0xd9, 0xa9, 0x79, 0x53, 0x31, 0x53, 0x71, - 0xe5, 0x9b, 0x3d, 0xf3, 0x1f, 0x0c, 0x05, 0x2d, 0xc1, 0xc0, 0xdb, 0x9c, 0xf1, 0xe8, 0x40, 0x77, 0x63, 0x74, 0x5a, - 0xb0, 0x59, 0x50, 0x97, 0x75, 0xd3, 0xc6, 0x83, 0x46, 0x1c, 0x14, 0xc5, 0xaa, 0x50, 0x23, 0xe1, 0x89, 0x40, 0xc0, - 0x94, 0x5d, 0xf1, 0xc8, 0x08, 0x6a, 0x7a, 0x13, 0x0a, 0x1b, 0x0a, 0xfe, 0x2a, 0x51, 0x4d, 0x6f, 0x42, 0x9b, 0x4c, - 0x9c, 0x66, 0x10, 0xc1, 0x8c, 0xd8, 0xee, 0xb7, 0x80, 0x36, 0xb7, 0x66, 0xb4, 0xa9, 0x6b, 0xab, 0xad, 0x42, 0x2e, - 0x29, 0x52, 0x96, 0xff, 0x4e, 0x4d, 0x05, 0x25, 0xb5, 0x5c, 0xf4, 0x26, 0x4d, 0x17, 0x3d, 0x9e, 0x19, 0x49, 0xa0, - 0x72, 0xcb, 0x1d, 0xa3, 0x3f, 0x84, 0x05, 0x1e, 0x31, 0x71, 0x62, 0xc1, 0xdc, 0xea, 0x84, 0x65, 0x73, 0xb1, 0x18, - 0xad, 0x24, 0x84, 0x0d, 0x3e, 0x66, 0xd9, 0xbc, 0xd4, 0x0f, 0xa1, 0x2f, 0x2c, 0x7d, 0x03, 0x76, 0xb1, 0xc1, 0x4a, - 0x96, 0x01, 0xf8, 0x5e, 0xd0, 0xcd, 0x4a, 0x96, 0x91, 0x54, 0xdd, 0x8f, 0x6b, 0x2c, 0x41, 0xa5, 0x15, 0x2a, 0x2d, - 0xa9, 0xb1, 0x20, 0xf0, 0x55, 0xd5, 0xe5, 0x43, 0xb2, 0xab, 0x40, 0x3d, 0x75, 0xd4, 0x80, 0x53, 0xa0, 0xaa, 0xc0, - 0x82, 0x24, 0xa8, 0x0c, 0x5d, 0x15, 0x98, 0x56, 0x60, 0x9a, 0xa9, 0xc2, 0x45, 0x99, 0x1d, 0x4a, 0xb3, 0x5e, 0xf2, - 0x59, 0x3c, 0x08, 0x93, 0x61, 0x4c, 0x1e, 0x22, 0xd4, 0xfe, 0x61, 0x1e, 0xc5, 0x5a, 0x2e, 0x79, 0xe9, 0xfc, 0xe2, - 0x6f, 0x3e, 0x63, 0xaf, 0x7b, 0x86, 0xc1, 0x02, 0x9c, 0xa5, 0xed, 0x55, 0x26, 0xde, 0xca, 0x56, 0x70, 0x1c, 0xcc, - 0xa2, 0x1c, 0x56, 0x3d, 0x39, 0xa2, 0xb9, 0xc8, 0xb5, 0x77, 0x11, 0x22, 0x07, 0x99, 0x3d, 0x06, 0xd8, 0x8d, 0xf0, - 0x75, 0x68, 0x6d, 0x6e, 0x75, 0x85, 0xf8, 0x1b, 0x25, 0x12, 0x3f, 0x49, 0xf9, 0x71, 0xbd, 0x52, 0xb9, 0x2a, 0x83, - 0xc7, 0xaa, 0x9b, 0xc1, 0x33, 0xed, 0x7b, 0xac, 0xfd, 0x5b, 0xdb, 0xcd, 0xf1, 0xde, 0x83, 0x07, 0xad, 0xff, 0xad, - 0x27, 0x21, 0xb4, 0x57, 0x4e, 0x52, 0x77, 0xd4, 0xe8, 0x99, 0xc9, 0x1a, 0x51, 0x09, 0x53, 0xbb, 0x53, 0x39, 0x06, - 0x6a, 0x3a, 0x80, 0x6b, 0x89, 0x9a, 0xa0, 0x27, 0x05, 0x1b, 0xc3, 0x11, 0x67, 0x71, 0xd0, 0x8e, 0x63, 0x14, 0x2f, - 0xe7, 0x4a, 0xbc, 0x9c, 0x9f, 0x30, 0x0e, 0xd0, 0x5a, 0x80, 0x54, 0xaf, 0x61, 0x3f, 0x73, 0x05, 0x0b, 0x6c, 0xee, - 0x7c, 0x47, 0x16, 0xc8, 0x10, 0x27, 0x9b, 0xe3, 0x64, 0x8f, 0x6b, 0x3d, 0xf7, 0x02, 0x1f, 0x27, 0xf5, 0xc2, 0xab, - 0xab, 0x6c, 0xd7, 0xb5, 0x64, 0xe5, 0xbc, 0x18, 0x4c, 0x20, 0x28, 0x4b, 0x39, 0x2f, 0x86, 0x93, 0x05, 0xcd, 0xe1, - 0xc7, 0xa2, 0x81, 0x0e, 0xb1, 0x1c, 0x24, 0x70, 0xe9, 0xec, 0x31, 0xe0, 0x0d, 0xa5, 0x16, 0x77, 0x63, 0x1d, 0x39, - 0xd6, 0x51, 0x1c, 0x86, 0x31, 0xe0, 0xca, 0x3a, 0x81, 0xf7, 0xfe, 0xeb, 0x63, 0x13, 0x90, 0x55, 0xbb, 0xc2, 0xab, - 0x51, 0xee, 0xba, 0xd2, 0xe8, 0x4b, 0x4a, 0x4f, 0x78, 0xc1, 0x53, 0xc9, 0x76, 0xdb, 0x33, 0x70, 0xb6, 0xc4, 0x43, - 0xe2, 0x1d, 0x23, 0x7a, 0x31, 0x6d, 0x64, 0xe6, 0x04, 0xce, 0x6c, 0x77, 0xd9, 0xc6, 0xfc, 0xd8, 0x01, 0x0e, 0x16, - 0x41, 0x48, 0xdc, 0x10, 0x86, 0x89, 0x9d, 0x94, 0x43, 0x2d, 0x84, 0xeb, 0x5a, 0x78, 0x1d, 0xa7, 0x65, 0x0c, 0x2e, - 0xd2, 0xda, 0x36, 0x71, 0x0f, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, - 0x0c, 0x40, 0xd3, 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, - 0xfe, 0x9d, 0xe6, 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, - 0x13, 0xb7, 0xdb, 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, - 0x18, 0x30, 0x97, 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, - 0xcc, 0x03, 0x99, 0x02, 0xe2, 0xf9, 0xc7, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd5, 0xf1, 0x8d, 0xe8, 0x7b, - 0xfb, 0xe2, 0x92, 0x57, 0x6f, 0x6e, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, - 0x1d, 0x14, 0x59, 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xaf, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, - 0x09, 0x53, 0x80, 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, - 0x31, 0x80, 0xc2, 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa6, 0x3a, 0x03, 0x2d, 0xeb, - 0x69, 0x01, 0xa2, 0x3a, 0x88, 0xb6, 0x0a, 0x84, 0x39, 0xa5, 0x65, 0x46, 0x97, 0x82, 0xa6, 0x82, 0x26, 0x19, 0xbd, - 0xe0, 0x4a, 0x54, 0x7c, 0x21, 0x98, 0xa2, 0xed, 0x86, 0xb0, 0xff, 0xd8, 0xa0, 0xeb, 0xad, 0x58, 0x6b, 0x68, 0x77, - 0x82, 0x8c, 0xd0, 0x7c, 0xa1, 0x83, 0x90, 0xa1, 0x72, 0x12, 0xf1, 0xe1, 0x35, 0x5e, 0x81, 0x4b, 0xa6, 0xd9, 0x68, - 0x19, 0x97, 0x61, 0x60, 0xbf, 0x0a, 0x2c, 0x26, 0x07, 0x26, 0xbd, 0x5f, 0x9f, 0x3f, 0x95, 0x57, 0x2b, 0x29, 0xb8, - 0xa8, 0x14, 0x44, 0xbf, 0xc1, 0x7d, 0x37, 0x71, 0xd5, 0x59, 0xb3, 0x56, 0x7a, 0xdf, 0xb7, 0x3e, 0x6b, 0xe3, 0xbe, - 0x30, 0x38, 0x06, 0x3b, 0x1f, 0x11, 0x03, 0x69, 0x50, 0xe9, 0x16, 0x87, 0x26, 0x40, 0x97, 0x0e, 0x29, 0x64, 0xc9, - 0x54, 0xa6, 0x4a, 0x50, 0xf1, 0x8d, 0xdf, 0x49, 0x59, 0x8d, 0xfe, 0x5a, 0xf3, 0xe2, 0xee, 0x3d, 0xcf, 0x39, 0x8e, - 0x51, 0x90, 0xc4, 0xe2, 0x3a, 0x2e, 0x03, 0xe2, 0x5b, 0x5e, 0x05, 0x47, 0xa9, 0x09, 0x1b, 0xb3, 0x53, 0x35, 0x6a, - 0xbd, 0x0a, 0xf4, 0x95, 0x51, 0xbe, 0x31, 0x18, 0x9a, 0x88, 0x2a, 0xe8, 0x7b, 0xad, 0xee, 0x69, 0x75, 0xc3, 0x02, - 0xe2, 0xcf, 0x95, 0x5e, 0xa8, 0xf5, 0xba, 0x19, 0x73, 0xc3, 0x44, 0x08, 0x1a, 0x3d, 0xaa, 0x17, 0x0e, 0x3f, 0x7f, - 0xa3, 0x2c, 0x89, 0xe0, 0xc5, 0x26, 0x5d, 0x17, 0x26, 0x96, 0x06, 0xd5, 0x01, 0x73, 0xa3, 0x4d, 0xce, 0x2f, 0x41, - 0xf4, 0xe7, 0xac, 0x88, 0x26, 0x75, 0x4d, 0x15, 0x82, 0x61, 0xb4, 0xb9, 0x6d, 0xa4, 0xd3, 0x3b, 0xf0, 0x72, 0x33, - 0xd6, 0x48, 0xda, 0xd3, 0xb1, 0xa6, 0x05, 0x2f, 0x57, 0x52, 0x94, 0x10, 0xdd, 0xb9, 0x37, 0xa6, 0x57, 0x71, 0x26, - 0xaa, 0x38, 0x13, 0xa7, 0xe5, 0x8a, 0x27, 0xd5, 0x3b, 0xa8, 0x50, 0x1b, 0xe3, 0x60, 0xeb, 0xd5, 0xa8, 0xab, 0x70, - 0xc8, 0x2f, 0x2f, 0x9e, 0xdf, 0xae, 0x62, 0x91, 0xc2, 0xa8, 0xd7, 0xfb, 0x5e, 0x34, 0xa7, 0x63, 0x15, 0x17, 0x5c, - 0x98, 0xa8, 0xc5, 0xb4, 0x62, 0x01, 0xd7, 0x19, 0x03, 0xca, 0x55, 0xec, 0xce, 0x4c, 0xc5, 0x32, 0x8c, 0xcb, 0xf2, - 0xa7, 0xac, 0xc4, 0x3b, 0x00, 0xb4, 0x06, 0x4e, 0x8b, 0x99, 0x01, 0x01, 0xb9, 0xcb, 0x0d, 0x2e, 0x02, 0x0b, 0x8e, - 0x1e, 0x8f, 0x57, 0xb7, 0x01, 0xf5, 0xde, 0x48, 0x75, 0x3d, 0x64, 0xc1, 0x78, 0xf4, 0x24, 0x70, 0xc8, 0x21, 0xfe, - 0x47, 0x8f, 0x8f, 0xf6, 0x7f, 0x33, 0x09, 0x48, 0x3d, 0x05, 0x55, 0x85, 0x51, 0x88, 0xc2, 0xb4, 0xbf, 0x5a, 0xab, - 0x5b, 0xee, 0x9b, 0xf3, 0x92, 0x17, 0xd7, 0x10, 0xad, 0x9d, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, - 0xab, 0xaa, 0xc8, 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, - 0x58, 0xd4, 0xa4, 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, - 0x4a, 0x8c, 0x35, 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, - 0xb7, 0x53, 0xd5, 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xea, 0x60, - 0x78, 0x00, 0xc9, 0x64, 0xfa, 0x69, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, - 0x3d, 0xef, 0xff, 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, - 0xcf, 0x50, 0xad, 0xef, 0xd3, 0xa2, 0x88, 0xef, 0x6a, 0x88, 0x6c, 0x2a, 0x9c, 0x77, 0x0d, 0xf5, 0xc8, 0x02, 0x3d, - 0x22, 0xd3, 0x0b, 0xc1, 0xe0, 0x9b, 0x77, 0x55, 0x18, 0xf0, 0x72, 0x35, 0xe4, 0xa2, 0xca, 0xaa, 0xbb, 0x21, 0xe6, - 0x09, 0xf0, 0x53, 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x89, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, - 0xe2, 0x63, 0xaa, 0xba, 0x31, 0xf9, 0x86, 0xea, 0xbe, 0x4d, 0xbe, 0x01, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, - 0x8c, 0xc6, 0xf4, 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf1, 0x76, 0xf6, 0xd1, - 0x68, 0xf4, 0xa6, 0xa0, 0xa3, 0xd1, 0xe8, 0x63, 0x56, 0x13, 0xba, 0x12, 0x1d, 0xef, 0xdf, 0x71, 0x7a, 0x2e, 0xd3, - 0xbb, 0x28, 0x08, 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0xaf, 0xd2, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, - 0x6d, 0x44, 0x48, 0x26, 0x42, 0x1f, 0xec, 0xf4, 0x6c, 0x34, 0x1a, 0xbd, 0x4a, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x14, - 0xcd, 0x29, 0x9c, 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x3d, 0x9c, 0xcd, 0xc7, 0xc3, 0x6f, 0x47, - 0x8b, 0x87, 0x87, 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, - 0xb1, 0xf5, 0x2d, 0xfa, 0xea, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x14, 0x80, - 0x17, 0x67, 0x23, 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, - 0xc7, 0xd3, 0xf2, 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x15, 0x44, 0x25, 0x3b, 0x7a, 0x32, - 0x55, 0x70, 0xc7, 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x76, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, - 0x72, 0x19, 0x83, 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, - 0x4c, 0x1e, 0x96, 0x54, 0x7e, 0x35, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0x7a, 0xf9, - 0xa4, 0xec, 0x70, 0xfe, 0xbf, 0x4b, 0xba, 0x18, 0x1c, 0xba, 0xa1, 0x79, 0xa0, 0xdd, 0x79, 0x2b, 0x64, 0x1c, 0xab, - 0xf0, 0x4d, 0x4a, 0xac, 0x31, 0x2e, 0x67, 0x27, 0x1b, 0xd3, 0x9d, 0x51, 0x55, 0x64, 0x57, 0x21, 0xd1, 0xbd, 0x72, - 0x20, 0xa1, 0x41, 0x94, 0x8d, 0x70, 0xfd, 0x80, 0xf5, 0x8c, 0xd7, 0xc9, 0x6b, 0x5e, 0x54, 0x59, 0xa2, 0xde, 0x5f, - 0x37, 0xde, 0xd7, 0xb5, 0x09, 0xa8, 0xfa, 0xb6, 0x60, 0x30, 0xcf, 0x0f, 0x0a, 0x00, 0x31, 0x45, 0x1a, 0xe0, 0x13, - 0xcc, 0x20, 0xa8, 0x5d, 0x33, 0xaf, 0x1a, 0xc1, 0x37, 0xe0, 0xab, 0xb7, 0x05, 0x60, 0x90, 0x84, 0x20, 0x45, 0x86, - 0xd0, 0x40, 0x20, 0xd0, 0x30, 0xe4, 0x02, 0x83, 0x9f, 0x78, 0x71, 0x24, 0x95, 0x53, 0x22, 0x0f, 0x03, 0xfc, 0x11, - 0x50, 0x15, 0x80, 0xc4, 0x78, 0x1c, 0xc2, 0x0b, 0xf5, 0xcb, 0xbd, 0x51, 0x7b, 0x84, 0x3d, 0x4d, 0x43, 0x08, 0x36, - 0x84, 0x0f, 0x01, 0x2c, 0x29, 0x42, 0x1f, 0x20, 0x97, 0x11, 0x06, 0x17, 0x79, 0xb6, 0xd2, 0x49, 0xd5, 0xa8, 0xa3, - 0xf9, 0x50, 0x6a, 0x47, 0x72, 0x40, 0xbd, 0xf4, 0x18, 0xd3, 0x0b, 0x95, 0xae, 0x8a, 0x72, 0x46, 0x39, 0x6f, 0xf5, - 0xc4, 0xb8, 0xb0, 0x85, 0x1c, 0x22, 0xe1, 0xbc, 0x2d, 0x54, 0x28, 0x1c, 0xbe, 0x00, 0x30, 0x30, 0x90, 0x76, 0xec, - 0xc6, 0xbb, 0x51, 0xd9, 0xcf, 0x38, 0x3b, 0xfc, 0xef, 0x79, 0x3c, 0xfc, 0x34, 0x1e, 0x7e, 0xbb, 0x18, 0x84, 0x43, - 0xfb, 0x93, 0x3c, 0x7c, 0x70, 0x48, 0x5f, 0x70, 0xcb, 0xa5, 0xc1, 0xc2, 0x6f, 0x04, 0xfb, 0x51, 0x2b, 0x21, 0x88, - 0x02, 0xbc, 0x61, 0xb9, 0xd5, 0x38, 0x01, 0xc0, 0xc3, 0xe0, 0xbf, 0x02, 0x34, 0x9a, 0x72, 0x17, 0x2f, 0xd0, 0x97, - 0xa8, 0xdf, 0x27, 0x8f, 0x1a, 0x06, 0x83, 0x20, 0xae, 0x51, 0x31, 0x61, 0x88, 0x2e, 0x63, 0xa2, 0x60, 0x90, 0x6d, - 0xf6, 0xed, 0xb6, 0xd7, 0x96, 0x84, 0xe1, 0x97, 0x7e, 0xa6, 0x89, 0x99, 0x77, 0xb8, 0xb1, 0xad, 0xe4, 0x2a, 0x44, - 0xac, 0x40, 0xfd, 0x2b, 0x67, 0x10, 0x7b, 0xf3, 0x3a, 0x03, 0x9f, 0x0e, 0xfb, 0xc5, 0x78, 0x06, 0x6c, 0x14, 0xdc, - 0xf9, 0x0a, 0x7e, 0x91, 0x81, 0x9b, 0xb7, 0x88, 0x51, 0xe0, 0x60, 0x97, 0x44, 0xbf, 0xdf, 0xcb, 0xb3, 0x30, 0xd7, - 0xb8, 0xd3, 0x79, 0x6d, 0xd4, 0x10, 0xa8, 0x23, 0x07, 0xf5, 0x83, 0x1e, 0x82, 0xa1, 0x1a, 0x82, 0xa2, 0xa3, 0x2d, - 0xae, 0x5e, 0x5b, 0x4f, 0x61, 0x7a, 0xab, 0xea, 0x2b, 0x46, 0x7f, 0xca, 0x4c, 0x60, 0x21, 0xed, 0x9a, 0x63, 0x5d, - 0x73, 0x8c, 0xb4, 0xa7, 0xdf, 0x17, 0x0d, 0xf2, 0xd3, 0x59, 0x78, 0x10, 0xa8, 0x52, 0xe5, 0x4e, 0x59, 0x94, 0xdb, - 0xd2, 0xbc, 0x31, 0xac, 0x69, 0x9e, 0xd9, 0x38, 0x37, 0xb3, 0x5e, 0x2f, 0x0c, 0xd1, 0xc1, 0x13, 0x4b, 0xc5, 0xda, - 0x20, 0xdc, 0x91, 0x49, 0x18, 0x5d, 0x81, 0xec, 0x32, 0x3c, 0xe3, 0x04, 0xf9, 0x54, 0x60, 0x1f, 0x54, 0xb5, 0x5e, - 0x4e, 0x78, 0x6c, 0xe4, 0xcb, 0x46, 0xd0, 0x20, 0x2f, 0x29, 0xea, 0x4d, 0xdc, 0x8e, 0x3d, 0x6d, 0x21, 0x57, 0x6e, - 0xea, 0x69, 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, - 0xcc, 0x70, 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, - 0x13, 0xf9, 0xea, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, - 0xf5, 0xa2, 0x84, 0x0a, 0xd8, 0x6e, 0x2b, 0x41, 0xf0, 0xef, 0xc7, 0x6c, 0x86, 0x7f, 0xb3, 0x7e, 0xbf, 0x17, 0xe2, - 0x2f, 0x8e, 0xc1, 0x8c, 0xe6, 0x62, 0xc1, 0x3e, 0x82, 0x8c, 0x89, 0x44, 0x98, 0xaa, 0x8c, 0x01, 0x59, 0x05, 0x16, - 0x81, 0xe6, 0x03, 0x95, 0x0b, 0x33, 0xd9, 0xcb, 0x9c, 0x6b, 0xc8, 0xf3, 0xd6, 0x38, 0x65, 0xa3, 0x2c, 0x51, 0xae, - 0x1c, 0xd9, 0x28, 0xce, 0xb3, 0xb8, 0xe4, 0xe5, 0x76, 0xab, 0x0f, 0xc7, 0xa4, 0xe0, 0xc0, 0xae, 0x2b, 0x2a, 0x55, - 0xb2, 0x8e, 0x54, 0x0f, 0xbc, 0x34, 0x2c, 0x70, 0x9f, 0xf2, 0x79, 0x61, 0x68, 0xc4, 0x01, 0x08, 0x33, 0x98, 0xba, - 0xa5, 0xf7, 0xc2, 0x02, 0x9a, 0x57, 0x12, 0xb2, 0xc1, 0x54, 0xcf, 0xc2, 0x37, 0x66, 0x62, 0x5e, 0x2c, 0x20, 0xac, - 0x4e, 0xb1, 0xd0, 0xcc, 0x26, 0x4d, 0x58, 0x0c, 0xb0, 0x79, 0x31, 0x99, 0x42, 0x7c, 0x77, 0x55, 0x4e, 0xbc, 0x30, - 0xf7, 0xed, 0xc4, 0x21, 0x87, 0xc0, 0xab, 0xda, 0xa0, 0xab, 0xd9, 0x86, 0xa3, 0x8e, 0x94, 0x13, 0x93, 0xdf, 0x4f, - 0x15, 0x84, 0xb8, 0x13, 0x47, 0xc2, 0xe5, 0xcd, 0x76, 0xe1, 0x65, 0x07, 0x82, 0x8e, 0x1a, 0x9c, 0xf2, 0x33, 0x83, - 0xa3, 0x31, 0x49, 0x37, 0xde, 0x09, 0x52, 0x84, 0x31, 0xd9, 0x48, 0x76, 0x2e, 0x43, 0x31, 0x8f, 0x17, 0xa0, 0xbc, - 0x8c, 0x17, 0x60, 0x69, 0x64, 0x0c, 0x52, 0x41, 0x7e, 0xc7, 0xbd, 0x50, 0x58, 0x14, 0x57, 0x88, 0xf4, 0xac, 0x7e, - 0x4f, 0x8b, 0x76, 0x28, 0x10, 0x14, 0x77, 0x28, 0xf3, 0xe4, 0xac, 0xc7, 0x02, 0x89, 0x0d, 0x01, 0xe3, 0x2b, 0x9d, - 0xa6, 0x5a, 0xeb, 0xde, 0xd8, 0xe8, 0x55, 0xd3, 0x6c, 0x24, 0x64, 0x75, 0x76, 0x01, 0x22, 0x25, 0x1f, 0x1d, 0x1f, - 0xf9, 0x45, 0xdc, 0x59, 0xe6, 0xad, 0x6d, 0x51, 0xc9, 0x4e, 0x36, 0x00, 0x5a, 0xa8, 0xa3, 0x67, 0x29, 0xb9, 0x4d, - 0x49, 0x6a, 0xb7, 0x29, 0x60, 0x25, 0xf9, 0x0b, 0x18, 0x82, 0xaf, 0x1d, 0x08, 0xa7, 0x63, 0x85, 0x78, 0x4d, 0x53, - 0x44, 0x9a, 0x0c, 0x4b, 0x8a, 0x63, 0x5b, 0x22, 0x0a, 0xaa, 0x2d, 0xcb, 0x0e, 0x86, 0x89, 0x12, 0xfc, 0x2c, 0xf5, - 0x28, 0x51, 0x10, 0x50, 0x3d, 0xe4, 0x20, 0xc1, 0xb6, 0x0d, 0x84, 0x07, 0xe4, 0x11, 0xbd, 0xb1, 0xfe, 0x3e, 0xeb, - 0x3c, 0xbb, 0xd0, 0x3c, 0x97, 0xeb, 0x5d, 0x61, 0xc6, 0x08, 0x4f, 0x32, 0x13, 0x36, 0xc0, 0x3b, 0xcf, 0x8c, 0xda, - 0xa6, 0xe7, 0xe1, 0xb5, 0x3d, 0xc7, 0x08, 0x7d, 0x7b, 0x06, 0xdd, 0x04, 0xf3, 0xea, 0xb0, 0x59, 0xaf, 0x14, 0xa4, - 0x86, 0xa9, 0x45, 0x13, 0xb3, 0x9e, 0x35, 0x28, 0xdf, 0x6e, 0x7b, 0x7a, 0xae, 0xf6, 0xcf, 0xdd, 0x76, 0xdb, 0xc3, - 0x6e, 0x3d, 0x4b, 0xbb, 0xad, 0xe2, 0x2b, 0xf5, 0x41, 0x7b, 0xfc, 0xb9, 0x1b, 0x7f, 0x6e, 0x90, 0x4d, 0x4a, 0x47, - 0x33, 0x6d, 0x7d, 0x10, 0x1e, 0x38, 0xbd, 0x6b, 0x34, 0xe9, 0xfb, 0x2c, 0x94, 0x74, 0x25, 0x1a, 0xd5, 0x99, 0x10, - 0x66, 0xac, 0xba, 0x7f, 0xfd, 0xdf, 0xbf, 0x0a, 0xf0, 0x88, 0x53, 0x3b, 0x7b, 0x6f, 0x83, 0x8a, 0x46, 0x5b, 0x38, - 0x52, 0x84, 0x1e, 0x90, 0x84, 0x7d, 0x2d, 0x6b, 0x71, 0x9b, 0xef, 0xb3, 0xfb, 0xe9, 0xd3, 0x87, 0xd4, 0xf7, 0x42, - 0x70, 0xcb, 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, - 0xbd, 0xf2, 0x3d, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0x7d, 0x9f, 0xcd, 0xb3, 0xc5, 0x76, 0x1b, 0xe2, 0xdf, - 0xae, 0x16, 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0x7f, 0x2d, 0x1a, 0x4e, - 0x13, 0xcf, 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, - 0xc0, 0x15, 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x4f, 0x96, 0xb6, 0x55, 0xc5, - 0x9d, 0xb7, 0xa4, 0x39, 0xae, 0x03, 0xe7, 0xeb, 0x60, 0x86, 0xd8, 0x94, 0x5d, 0x2d, 0x90, 0xfb, 0xe5, 0x35, 0xed, - 0x8d, 0xeb, 0x04, 0x66, 0x6d, 0x53, 0x5b, 0xc6, 0xcf, 0x96, 0xfe, 0x4e, 0x0f, 0xae, 0x32, 0x06, 0x9b, 0x1b, 0x2b, - 0x0d, 0xbb, 0x6f, 0x3c, 0x5f, 0x0a, 0x08, 0x4f, 0xe7, 0xd3, 0xe3, 0xf7, 0x99, 0x47, 0x8f, 0x81, 0xe8, 0x98, 0x8f, - 0x4a, 0xf7, 0x91, 0xdd, 0xbd, 0x7e, 0x40, 0xc0, 0x79, 0xd5, 0x2e, 0x68, 0x5e, 0x2e, 0x20, 0xb0, 0xaa, 0x57, 0x5e, - 0x61, 0xf9, 0xcc, 0x98, 0x5d, 0x02, 0x19, 0x2a, 0x08, 0x04, 0xee, 0xee, 0x3a, 0x17, 0x62, 0xd5, 0x61, 0x65, 0x4e, - 0x93, 0xb0, 0x93, 0x10, 0xcd, 0x5b, 0x83, 0x59, 0xf0, 0x5f, 0xc1, 0xa0, 0x1c, 0x04, 0x51, 0x10, 0x05, 0x01, 0x19, - 0x14, 0xf0, 0x0b, 0x71, 0xd7, 0x08, 0xc6, 0x6c, 0x81, 0x0e, 0x3f, 0xe0, 0xcc, 0x67, 0x44, 0x5e, 0xfa, 0x61, 0x3d, - 0xbd, 0x01, 0x38, 0x97, 0x32, 0xe7, 0x31, 0xfa, 0x9c, 0x3c, 0xe0, 0x2c, 0x23, 0xf4, 0x81, 0x77, 0x2a, 0xbf, 0xe5, - 0x8d, 0x60, 0x7f, 0xbb, 0xc3, 0xf6, 0x02, 0xe4, 0x15, 0xbd, 0x31, 0x7d, 0xc0, 0x49, 0x94, 0x35, 0x9c, 0xa9, 0x39, - 0xf4, 0xac, 0xb2, 0xac, 0x15, 0x35, 0xe4, 0x06, 0xc5, 0xdc, 0xc8, 0x32, 0x39, 0x99, 0xb6, 0x9a, 0x53, 0x81, 0xeb, - 0xce, 0xae, 0x17, 0x90, 0x1c, 0x0a, 0xcd, 0xd2, 0xd9, 0x70, 0xde, 0xb6, 0x65, 0xcf, 0x5a, 0xa7, 0x90, 0xd7, 0x10, - 0x15, 0x0d, 0xd2, 0x11, 0x50, 0x43, 0x2b, 0x2e, 0x2b, 0x70, 0x61, 0x36, 0xed, 0xe1, 0xa6, 0x3d, 0xa6, 0x19, 0x3f, - 0x41, 0xcc, 0x3c, 0x8e, 0x2d, 0x03, 0x3b, 0x12, 0x87, 0xef, 0xe3, 0x7c, 0x81, 0x76, 0xe9, 0xad, 0xab, 0xc5, 0x23, - 0xac, 0x3d, 0x6f, 0x85, 0x84, 0x00, 0xf1, 0x69, 0x2a, 0xdd, 0x6e, 0x83, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, - 0x6a, 0xd8, 0x49, 0x73, 0x6b, 0xb6, 0xc4, 0x5e, 0x51, 0x78, 0x0c, 0xcc, 0xa9, 0xf9, 0xcf, 0x20, 0xa0, 0x78, 0xee, - 0x86, 0x60, 0x6f, 0xca, 0x4e, 0x36, 0x45, 0xbf, 0xff, 0xac, 0xc0, 0x07, 0x94, 0x0b, 0x83, 0x98, 0x5b, 0xc7, 0xf1, - 0x30, 0xec, 0x93, 0xfa, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x47, 0x58, 0x2a, 0x43, 0x58, 0xb8, 0x62, 0xa4, 0x83, 0x38, - 0xa8, 0x49, 0xe7, 0x60, 0x55, 0x2e, 0xf8, 0x72, 0xaf, 0xf7, 0x1a, 0x60, 0xd2, 0x33, 0x6f, 0x58, 0x5e, 0x78, 0x80, - 0x68, 0xbd, 0x1e, 0x2e, 0x14, 0x8f, 0x4c, 0x34, 0xd0, 0x38, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, 0x56, 0x32, 0x1a, - 0x8d, 0xaa, 0x5a, 0x49, 0x3e, 0xec, 0x77, 0x9f, 0x5a, 0x28, 0x9e, 0x32, 0x4e, 0x79, 0x0a, 0x96, 0xef, 0x86, 0xd2, - 0xcd, 0x17, 0x74, 0xc5, 0x45, 0xaa, 0x7e, 0x7a, 0xe8, 0x9b, 0x0d, 0xe2, 0x9a, 0x35, 0x75, 0x38, 0x76, 0xf8, 0x21, - 0x00, 0xa6, 0x7d, 0x98, 0xb9, 0x74, 0x0d, 0xd3, 0x0b, 0xe2, 0xd9, 0xb8, 0xe0, 0xa1, 0xcb, 0x03, 0xd8, 0x87, 0xe6, - 0x90, 0xc4, 0x4f, 0xe1, 0xe7, 0xcc, 0xa4, 0x75, 0x7c, 0x86, 0xb3, 0x19, 0x95, 0xea, 0x46, 0xd0, 0x7e, 0x0d, 0x89, - 0xc4, 0x20, 0x3d, 0x37, 0x18, 0x8a, 0xd6, 0xdd, 0x06, 0xae, 0xfc, 0x96, 0xde, 0xf9, 0x34, 0x08, 0xb0, 0xbe, 0xb1, - 0x18, 0x00, 0x50, 0xc5, 0x1f, 0xa8, 0xba, 0x32, 0x57, 0x14, 0xd3, 0x30, 0x95, 0x68, 0xef, 0x38, 0xae, 0xa3, 0xc6, - 0x75, 0x58, 0xb0, 0xd2, 0xda, 0x36, 0xbb, 0xb7, 0x10, 0x7f, 0x44, 0x97, 0x80, 0x6a, 0x41, 0xdc, 0x09, 0xe0, 0x43, - 0x23, 0xd5, 0x81, 0x20, 0xbb, 0x0f, 0x0e, 0x00, 0x78, 0xc3, 0xf3, 0x30, 0x84, 0x3f, 0xb0, 0x70, 0x60, 0x59, 0xaa, - 0x7e, 0x2e, 0xa7, 0x31, 0x9c, 0xbb, 0xb9, 0xda, 0xe1, 0xb3, 0x25, 0x28, 0x36, 0xd5, 0x9c, 0x9a, 0xcb, 0x57, 0xde, - 0xd8, 0xef, 0x31, 0xc1, 0x3c, 0x66, 0xb6, 0xe1, 0xb7, 0x9e, 0x6e, 0xeb, 0x1b, 0xec, 0x06, 0x4e, 0xda, 0x0b, 0xa7, - 0xbd, 0xd8, 0x2e, 0x0d, 0xe4, 0x5f, 0xdd, 0x10, 0x22, 0x7c, 0xd0, 0xc4, 0x22, 0x6b, 0xc8, 0x74, 0x2c, 0x56, 0x88, - 0x6a, 0x53, 0xf1, 0x54, 0x1b, 0x08, 0x94, 0x53, 0x75, 0x61, 0x6a, 0xa5, 0x32, 0x61, 0x10, 0x77, 0x4a, 0x58, 0x54, - 0x19, 0x60, 0x18, 0x54, 0x48, 0x71, 0x6d, 0x3d, 0x7f, 0xe2, 0xf2, 0xcd, 0x4c, 0x9b, 0xed, 0xa7, 0x2f, 0xf2, 0xf8, - 0x72, 0xbb, 0x0d, 0xbb, 0x5f, 0x80, 0x39, 0x6a, 0xa9, 0x34, 0x8c, 0xe0, 0x04, 0xa2, 0x24, 0xd7, 0x7b, 0x72, 0x4e, - 0x1c, 0x27, 0xd7, 0x6e, 0xde, 0x6c, 0x27, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0x49, 0x6a, 0x4f, - 0x01, 0x6f, 0xd3, 0x3b, 0x4a, 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, - 0x83, 0x80, 0xd3, 0x9e, 0x6e, 0xac, 0x55, 0x24, 0x9b, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0xb5, 0xbb, 0x6d, - 0x55, 0xb6, 0x50, 0x30, 0x0f, 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x17, 0xa4, 0xd0, 0x2b, - 0x47, 0xab, 0x9a, 0x77, 0x25, 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xfb, 0x5a, 0xd6, 0x58, 0x5c, 0x39, 0x21, - 0x85, 0x4d, 0xf8, 0xd2, 0x52, 0x2c, 0xcc, 0x62, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x8c, 0x36, - 0x58, 0x37, 0xdb, 0xed, 0x87, 0x22, 0x9c, 0x67, 0x0b, 0x2a, 0x47, 0x59, 0x8a, 0x90, 0x6a, 0xc6, 0x63, 0xd9, 0x76, - 0xc1, 0x4c, 0x0c, 0x75, 0xed, 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, - 0x1e, 0xee, 0xdf, 0xa5, 0x10, 0xd3, 0xce, 0xac, 0xbb, 0x5f, 0x77, 0x6e, 0x88, 0xdf, 0x41, 0x60, 0x85, 0x92, 0x7d, - 0x28, 0x46, 0xe7, 0x99, 0x48, 0x71, 0xa7, 0xaa, 0x28, 0xc1, 0x6a, 0x1d, 0x34, 0x5b, 0x6e, 0xef, 0xc5, 0x96, 0x28, - 0x40, 0x9c, 0x67, 0xa1, 0x19, 0xcf, 0xca, 0x59, 0xce, 0x64, 0x14, 0x1b, 0x12, 0x95, 0x5e, 0x94, 0x78, 0x9f, 0xa7, - 0x31, 0x3d, 0x74, 0x6b, 0x10, 0x5c, 0x57, 0x77, 0x36, 0xd2, 0x7c, 0x41, 0x88, 0x9a, 0x00, 0x09, 0x1b, 0xd5, 0x9c, - 0x5a, 0x97, 0xe2, 0x7e, 0x56, 0xf9, 0x4e, 0x1f, 0xc4, 0x97, 0x02, 0x78, 0x58, 0x6f, 0x7b, 0x5f, 0x09, 0x8f, 0xb5, - 0xc1, 0xb7, 0xdb, 0xed, 0xa5, 0x98, 0x07, 0x81, 0xc7, 0x68, 0xfe, 0xa0, 0x24, 0xe6, 0xbd, 0x31, 0x85, 0x15, 0xef, - 0xbb, 0xf8, 0x75, 0x93, 0x5a, 0x6b, 0x91, 0xbb, 0xc3, 0xf5, 0x01, 0xcf, 0x53, 0xe2, 0x68, 0x47, 0xe5, 0x54, 0x5a, - 0xdb, 0x01, 0xec, 0x8a, 0xc0, 0x40, 0xd9, 0xbf, 0xa4, 0x6c, 0x03, 0xe6, 0x89, 0x60, 0x7d, 0x84, 0x7e, 0x5b, 0x4a, - 0x7f, 0x32, 0x46, 0xe3, 0x1e, 0xb9, 0xae, 0xa2, 0x23, 0xae, 0xa3, 0xd9, 0xf3, 0xe8, 0x6f, 0x4f, 0xc6, 0xb4, 0x88, - 0x45, 0x2a, 0xaf, 0x40, 0x05, 0x01, 0xca, 0x10, 0x74, 0x84, 0xd0, 0xd4, 0x00, 0x34, 0x08, 0x6e, 0x00, 0x7e, 0xeb, - 0x74, 0xa2, 0xb4, 0x35, 0xf9, 0x18, 0xad, 0xaa, 0xc8, 0x59, 0x1b, 0xda, 0x4d, 0x25, 0x87, 0xe4, 0x61, 0x09, 0xf8, - 0x96, 0xd8, 0x2c, 0x65, 0x83, 0xa2, 0x36, 0x9b, 0x7a, 0xad, 0xd8, 0x91, 0xdb, 0x46, 0xd1, 0x66, 0x2d, 0x6a, 0xbb, - 0x91, 0xf9, 0x62, 0x7a, 0x6b, 0x85, 0x81, 0x53, 0xd3, 0x9a, 0x9b, 0x1d, 0x28, 0x39, 0x5b, 0x9f, 0xc9, 0x4d, 0x80, - 0x38, 0xc0, 0x70, 0xdd, 0xce, 0x6f, 0x16, 0x84, 0xde, 0xb2, 0x5b, 0x2b, 0x56, 0xbd, 0xb1, 0x72, 0x11, 0x93, 0x76, - 0x33, 0x98, 0xc0, 0x65, 0x9c, 0x15, 0xf6, 0x85, 0x56, 0x37, 0x14, 0x1d, 0x6d, 0x93, 0xf6, 0xf3, 0x8e, 0x76, 0xc3, - 0x05, 0xdf, 0x8a, 0x75, 0x9c, 0x5b, 0xd6, 0x54, 0xa1, 0x69, 0x07, 0x7a, 0x3b, 0x04, 0x34, 0x67, 0x63, 0xba, 0xa4, - 0x29, 0x5e, 0xa0, 0xe9, 0x1a, 0xcc, 0x74, 0x2e, 0xa0, 0xaf, 0xdd, 0x3e, 0xda, 0x17, 0xaa, 0x27, 0xc2, 0x5b, 0xa2, - 0xe0, 0xdb, 0x92, 0x82, 0x97, 0x5a, 0xce, 0x63, 0x33, 0x87, 0x80, 0x4f, 0xa3, 0x4a, 0xf4, 0x4e, 0x8a, 0x4b, 0xd0, - 0x66, 0xc2, 0x11, 0x68, 0xaa, 0x46, 0x6c, 0xe5, 0x00, 0xb7, 0x17, 0x4f, 0x03, 0x42, 0x41, 0xaa, 0xbb, 0xb6, 0x2b, - 0xf2, 0x96, 0x9d, 0x6c, 0x6e, 0xc1, 0x4c, 0xb8, 0x5a, 0x97, 0xad, 0xaf, 0x6c, 0xb2, 0xfb, 0xb8, 0x26, 0xd8, 0x76, - 0x6f, 0x83, 0x84, 0xb7, 0xf4, 0x86, 0x6c, 0x6e, 0xfa, 0xfd, 0x10, 0xfa, 0x43, 0xa8, 0xee, 0xd0, 0x6d, 0x67, 0x87, - 0x6e, 0xbd, 0x76, 0x9e, 0x5b, 0x3d, 0x9f, 0xf2, 0x0e, 0xf9, 0x80, 0x26, 0x6b, 0x74, 0x15, 0xdf, 0xc1, 0xa6, 0x8e, - 0x2a, 0xaa, 0x2a, 0x8f, 0x12, 0x0a, 0x2a, 0xf1, 0x8c, 0x97, 0xef, 0x39, 0xc6, 0x7a, 0xd5, 0x4f, 0x6f, 0x35, 0xaf, - 0xb6, 0x36, 0x6b, 0xb3, 0x5c, 0x9f, 0x83, 0x85, 0xc4, 0x39, 0x8f, 0xae, 0x34, 0x2d, 0xb9, 0xf4, 0xa1, 0x34, 0x71, - 0x54, 0x82, 0x8b, 0x38, 0xcb, 0x41, 0x8d, 0x7b, 0xd1, 0xec, 0x7f, 0xa8, 0x6d, 0xc7, 0x96, 0x8d, 0x33, 0xf7, 0x3a, - 0x24, 0x9b, 0xff, 0xb1, 0x81, 0x7a, 0x1a, 0x62, 0x84, 0x58, 0xb3, 0xa0, 0xdf, 0x30, 0x88, 0x15, 0x1a, 0x94, 0xeb, - 0x24, 0xe1, 0x65, 0x19, 0x18, 0xa5, 0xd6, 0x9a, 0xad, 0xcd, 0x79, 0xf6, 0x96, 0x9d, 0xbc, 0xed, 0x31, 0x76, 0x4b, - 0x68, 0xa2, 0x75, 0x42, 0xa6, 0xc6, 0xc8, 0xd3, 0x02, 0xe9, 0x0e, 0x45, 0xd9, 0x45, 0xf8, 0x06, 0x85, 0x2c, 0xed, - 0x7d, 0x6e, 0x4e, 0x64, 0xf5, 0x8d, 0x36, 0x42, 0x89, 0x54, 0x22, 0xc8, 0xc6, 0x6f, 0x10, 0xc0, 0x18, 0x9a, 0x1d, - 0x90, 0xcd, 0x92, 0xbd, 0xa2, 0x67, 0xd6, 0x24, 0x08, 0x5e, 0xbf, 0x51, 0x89, 0x66, 0x94, 0x15, 0xd1, 0x55, 0x46, - 0x3f, 0x77, 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, - 0x6a, 0x6c, 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, - 0xbc, 0xa5, 0xe0, 0x2f, 0xf6, 0x96, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb2, 0x93, - 0xcd, 0xdb, 0xf0, 0x55, 0x63, 0xe6, 0xee, 0x42, 0xbc, 0x54, 0x25, 0x3d, 0x6f, 0x9e, 0xcc, 0x40, 0xac, 0xac, 0xd6, - 0xfc, 0x96, 0x59, 0x7d, 0x02, 0x10, 0xa9, 0x5b, 0xeb, 0x60, 0x8b, 0x1f, 0x9b, 0x2e, 0x93, 0x4d, 0xca, 0xda, 0x4c, - 0x94, 0x52, 0x91, 0x34, 0x17, 0x01, 0xf4, 0x1b, 0x86, 0xa3, 0x06, 0xb8, 0x73, 0x3d, 0xf6, 0x66, 0x68, 0xbc, 0x31, - 0x35, 0xf4, 0x6c, 0xa3, 0x97, 0xb7, 0xa3, 0x10, 0x66, 0x2c, 0xa2, 0x5b, 0x77, 0x2c, 0x86, 0xaf, 0xe8, 0x1b, 0xa8, - 0xf0, 0x69, 0x88, 0xd1, 0x85, 0x49, 0x5d, 0x4f, 0xd7, 0x6a, 0x2b, 0xdd, 0x10, 0x9a, 0x63, 0x54, 0x23, 0xaf, 0x6d, - 0x77, 0xd4, 0x08, 0xed, 0x09, 0xe5, 0xe1, 0x2d, 0xad, 0xe8, 0x8d, 0x65, 0x11, 0x9c, 0xfc, 0xd8, 0xcb, 0x4f, 0xe8, - 0xb9, 0x27, 0x30, 0x29, 0xda, 0x1a, 0xc0, 0x5f, 0x50, 0x3f, 0x9c, 0xd5, 0x53, 0x2b, 0xe5, 0xf0, 0x14, 0xbe, 0x64, - 0x03, 0x72, 0x05, 0xbd, 0x58, 0x63, 0x76, 0x12, 0x83, 0x0e, 0x6a, 0x67, 0x77, 0x78, 0x93, 0x52, 0x86, 0x68, 0x8d, - 0xe8, 0x20, 0xaf, 0x7e, 0x03, 0x4d, 0x1f, 0xa4, 0x85, 0x29, 0x5d, 0xa3, 0x80, 0x07, 0xf4, 0x4d, 0xfd, 0x7e, 0x8e, - 0xcf, 0xb5, 0x67, 0x99, 0xa6, 0x2c, 0x90, 0x09, 0x5d, 0x7a, 0x71, 0xbb, 0x40, 0xda, 0xec, 0x58, 0x05, 0x60, 0x45, - 0x12, 0x68, 0x44, 0x02, 0x96, 0x4b, 0x9e, 0xb8, 0x6c, 0x83, 0x06, 0x35, 0x51, 0x49, 0x21, 0x4b, 0x24, 0x81, 0x1f, - 0x46, 0x50, 0xa6, 0x28, 0x06, 0x71, 0xaf, 0x5e, 0x5e, 0x71, 0x4d, 0x0d, 0x58, 0x53, 0x04, 0x13, 0xac, 0xd3, 0x29, - 0x10, 0x5b, 0xb1, 0x5e, 0x81, 0x27, 0xaa, 0xbb, 0x48, 0x22, 0x4b, 0x80, 0x06, 0x7a, 0xbe, 0x74, 0xda, 0x2d, 0x6f, - 0x4f, 0xb4, 0x54, 0xb1, 0xb9, 0xf7, 0x62, 0x61, 0xb9, 0xc7, 0xca, 0xdf, 0x0e, 0xb4, 0x17, 0x56, 0x3b, 0x22, 0x6a, - 0xb0, 0x3a, 0x6c, 0xdb, 0xf9, 0xa1, 0x34, 0x54, 0xf7, 0xca, 0x31, 0x01, 0x15, 0x5d, 0xc5, 0xd5, 0x32, 0xca, 0x46, - 0xf0, 0x67, 0xbb, 0x0d, 0x0e, 0x03, 0xb0, 0x08, 0xfd, 0xe5, 0xdd, 0x4f, 0x11, 0x86, 0xab, 0xfa, 0xe5, 0xdd, 0x4f, - 0xdb, 0xed, 0x93, 0xf1, 0xd8, 0x70, 0x05, 0x4e, 0xad, 0x03, 0xfc, 0x81, 0x61, 0x1b, 0xec, 0x92, 0xdd, 0x6e, 0x9f, - 0x00, 0x07, 0xa1, 0xd8, 0x06, 0xb3, 0x8b, 0x95, 0x63, 0x9b, 0x62, 0x35, 0xf4, 0x8e, 0x04, 0xec, 0xbe, 0x1d, 0x96, - 0x62, 0x97, 0xfa, 0xa8, 0x90, 0x94, 0x7a, 0xd1, 0x3f, 0xef, 0x14, 0x58, 0x52, 0x30, 0xe5, 0x0d, 0x96, 0x55, 0xb5, - 0x2a, 0xa3, 0xc3, 0xc3, 0x78, 0x95, 0x8d, 0xca, 0x0c, 0xb6, 0x79, 0x79, 0x7d, 0x09, 0x00, 0x13, 0x01, 0x6d, 0xbc, - 0x5b, 0x8b, 0xcc, 0xbc, 0x58, 0xd0, 0x65, 0x86, 0x6b, 0x12, 0xcc, 0x0e, 0x72, 0x6e, 0x75, 0x93, 0x53, 0x62, 0x1f, - 0xc0, 0x06, 0x73, 0xbb, 0x6d, 0xf0, 0x0b, 0x27, 0xa3, 0x27, 0xb3, 0x65, 0xa6, 0x0d, 0x5c, 0xb9, 0xd9, 0xff, 0x24, - 0xf2, 0xd2, 0x50, 0xf1, 0x49, 0xa6, 0xcf, 0x33, 0xe0, 0xf3, 0xd8, 0x27, 0x11, 0xfa, 0x2c, 0x57, 0xa3, 0x35, 0xc0, - 0xc6, 0x66, 0x17, 0x77, 0xa3, 0x94, 0x43, 0x84, 0x8e, 0xc0, 0xaa, 0x6b, 0x96, 0x19, 0xf1, 0x6d, 0x2a, 0x6e, 0x5b, - 0xaa, 0xb0, 0x4f, 0xc2, 0x73, 0xde, 0xe1, 0xc6, 0x71, 0xa8, 0x37, 0x89, 0xc2, 0xe7, 0x28, 0x44, 0xe5, 0x68, 0x5c, - 0xe8, 0xe4, 0x6b, 0x99, 0xc7, 0x84, 0x62, 0x0e, 0xf7, 0xee, 0x9f, 0xa9, 0x33, 0x97, 0xf1, 0x85, 0x7b, 0xcf, 0x7d, - 0x99, 0xc9, 0xb5, 0x04, 0x90, 0x28, 0x55, 0xfb, 0xcf, 0x9f, 0x91, 0x1a, 0xff, 0x95, 0x6a, 0x0d, 0x40, 0xef, 0x67, - 0xa8, 0xc9, 0x11, 0x04, 0x6c, 0xc5, 0xd4, 0x8f, 0x2e, 0x60, 0x25, 0xf3, 0x3f, 0xa1, 0x6e, 0x47, 0xb0, 0x8d, 0x8a, - 0x27, 0x14, 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0xee, 0x22, 0x5e, 0x4f, 0xb1, 0x24, 0x66, 0x23, 0x86, - 0xfd, 0xdc, 0xec, 0xc2, 0xbb, 0xa2, 0x61, 0x12, 0x4f, 0x4b, 0x7f, 0x5b, 0x79, 0x9b, 0xc9, 0x32, 0xce, 0xc8, 0x94, - 0x2b, 0x04, 0x73, 0xab, 0xef, 0x31, 0x27, 0xf8, 0xe3, 0xa3, 0xc7, 0x84, 0x5e, 0xcb, 0x69, 0x89, 0x20, 0x7d, 0x22, - 0xb5, 0xae, 0xab, 0xd8, 0xaf, 0x29, 0x44, 0xb5, 0x10, 0x0c, 0x42, 0x99, 0x9a, 0xf6, 0x29, 0xbe, 0xcf, 0x96, 0xfd, - 0xc9, 0x94, 0x2d, 0xc9, 0x46, 0x40, 0xc7, 0xa4, 0xf3, 0x7e, 0xf5, 0xf6, 0xec, 0xcc, 0xfb, 0x0d, 0x9a, 0x70, 0x50, - 0xdd, 0x40, 0xbb, 0x0a, 0x32, 0x8d, 0x51, 0x6c, 0x16, 0x63, 0xed, 0xd6, 0x44, 0x04, 0x41, 0xb8, 0xcb, 0x59, 0xd8, - 0x6e, 0x27, 0xc4, 0xdb, 0x40, 0x02, 0x05, 0xae, 0x6d, 0x94, 0x93, 0x90, 0xa8, 0x0b, 0x99, 0x39, 0x26, 0x24, 0x0b, - 0xf4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0xb7, 0x4f, 0x01, 0x7d, 0x51, 0xb0, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x6f, 0x36, - 0xa0, 0x1f, 0xa5, 0x7a, 0x04, 0x8f, 0x69, 0x60, 0xb9, 0xe8, 0xeb, 0x82, 0x21, 0xcc, 0xd2, 0xef, 0x29, 0x9b, 0x7c, - 0xf3, 0x77, 0x37, 0xbf, 0xe7, 0x5a, 0xcc, 0x0e, 0x42, 0x71, 0x7b, 0x3d, 0x01, 0xe2, 0x57, 0xf1, 0x2b, 0xb0, 0x36, - 0xd7, 0x12, 0x6f, 0x4f, 0xf2, 0x20, 0x7c, 0x39, 0xba, 0xfd, 0xa4, 0x34, 0x9f, 0x40, 0xd0, 0x1e, 0x27, 0x29, 0x77, - 0xdf, 0xbd, 0x97, 0xae, 0x22, 0x18, 0x2d, 0x40, 0xf0, 0xdb, 0x5b, 0xc9, 0x59, 0x53, 0xf8, 0x8f, 0x75, 0xbe, 0xc0, - 0x58, 0x2a, 0xf2, 0x3d, 0x4e, 0x7f, 0x13, 0x1c, 0xdc, 0xbf, 0x95, 0x59, 0x43, 0xa2, 0x73, 0xf5, 0x11, 0xd0, 0xff, - 0xb1, 0x1e, 0xbf, 0x53, 0x94, 0xf4, 0x25, 0x71, 0x8e, 0xf0, 0x4d, 0xbc, 0x44, 0xd3, 0xc5, 0xde, 0xb8, 0xa6, 0x9f, - 0x0a, 0xf3, 0x42, 0x2b, 0x38, 0xec, 0x5b, 0xa3, 0xf0, 0xc0, 0x33, 0xef, 0x3b, 0xd1, 0x10, 0x74, 0xff, 0x03, 0xf7, - 0xc6, 0x77, 0x82, 0x65, 0x78, 0x53, 0xce, 0x32, 0x73, 0x87, 0xbb, 0xc9, 0x44, 0x2a, 0x6f, 0x18, 0x0b, 0xd6, 0x42, - 0x99, 0xf3, 0xa6, 0xc1, 0x6c, 0x53, 0x47, 0x2a, 0xd9, 0x7d, 0xff, 0x67, 0xe3, 0x84, 0xcd, 0x06, 0xc1, 0xfb, 0x4a, - 0x16, 0xf1, 0x25, 0x0f, 0xa6, 0x5a, 0x45, 0x91, 0x81, 0x5d, 0x21, 0x20, 0xe5, 0x38, 0xed, 0x1d, 0x3c, 0x59, 0x6a, - 0x66, 0x42, 0x7e, 0x5b, 0x9d, 0x05, 0xbc, 0x35, 0xa3, 0x79, 0x5a, 0xc1, 0x2e, 0xf3, 0x95, 0x14, 0xdf, 0xb5, 0x24, - 0xd9, 0x58, 0x7f, 0x43, 0x86, 0x6d, 0xe5, 0x33, 0xe7, 0x80, 0xb9, 0xf3, 0x51, 0xaa, 0xa0, 0x7f, 0x3d, 0xc6, 0x6e, - 0x24, 0x12, 0x01, 0xe1, 0x2c, 0x26, 0xee, 0x84, 0x09, 0x87, 0xe9, 0x02, 0x05, 0xc5, 0x18, 0x28, 0xe8, 0xbd, 0x0c, - 0x39, 0x3d, 0xe5, 0x83, 0xa4, 0x31, 0x5b, 0x7f, 0xaa, 0x12, 0xe9, 0x8d, 0x24, 0xf4, 0x0c, 0x7e, 0x8f, 0x5b, 0x3c, - 0x50, 0x23, 0x58, 0xa7, 0xbb, 0x39, 0x1d, 0xbe, 0x2e, 0xc8, 0xf0, 0x77, 0xf0, 0x76, 0x8b, 0xed, 0x65, 0x39, 0x81, - 0xc5, 0x1d, 0x7b, 0xc5, 0xd3, 0x5c, 0xb5, 0x38, 0x21, 0x1e, 0xb1, 0xc8, 0x7d, 0x62, 0x01, 0x23, 0x6a, 0x18, 0x8d, - 0x1f, 0xdf, 0xbf, 0x79, 0xad, 0x31, 0xac, 0x72, 0xff, 0x03, 0x18, 0x51, 0x2d, 0x6d, 0xb7, 0x03, 0xbe, 0x1c, 0xa1, - 0x01, 0x7b, 0xea, 0x06, 0xbb, 0xdf, 0x37, 0x69, 0x27, 0xa5, 0x97, 0xcd, 0x89, 0x41, 0x77, 0x94, 0x36, 0x4b, 0x65, - 0x60, 0xdc, 0x55, 0x38, 0x9a, 0x13, 0x1b, 0xb1, 0xaa, 0xf7, 0x61, 0xb8, 0xa4, 0xb1, 0x95, 0x95, 0xdb, 0xdd, 0x84, - 0x23, 0x9b, 0x00, 0xd7, 0xa7, 0xa0, 0xbd, 0x9a, 0x73, 0xd0, 0x82, 0x12, 0x05, 0x8e, 0x68, 0xbb, 0x0d, 0x21, 0x22, - 0x49, 0x31, 0x9c, 0xcc, 0xc2, 0x62, 0x38, 0x54, 0x03, 0x5f, 0x10, 0x12, 0x7d, 0x2a, 0xe6, 0xd9, 0x42, 0x21, 0x18, - 0xf9, 0x3b, 0xe9, 0xd7, 0x42, 0x71, 0xca, 0xbd, 0xef, 0x04, 0xd9, 0xfc, 0x23, 0xc5, 0x18, 0x8c, 0x4e, 0xb3, 0x99, - 0x81, 0x84, 0xf5, 0xb4, 0x22, 0x6a, 0x1d, 0xd9, 0xd9, 0x00, 0x55, 0x2c, 0x9a, 0x06, 0x83, 0xba, 0xc5, 0x13, 0xeb, - 0x19, 0xbd, 0x07, 0x95, 0x20, 0xaa, 0x05, 0xbb, 0x31, 0x5c, 0x6b, 0xaf, 0x45, 0x28, 0x29, 0x27, 0x4d, 0x66, 0xc6, - 0x8a, 0x06, 0x0b, 0x10, 0x92, 0xc6, 0x65, 0xf5, 0x4a, 0xa6, 0xd9, 0x45, 0x06, 0x08, 0x12, 0xce, 0x9f, 0x50, 0x36, - 0xde, 0x3c, 0x55, 0xf3, 0xd2, 0x95, 0x38, 0xb3, 0xb0, 0x27, 0x5d, 0x6f, 0x69, 0x41, 0xa2, 0x02, 0x68, 0x94, 0xaf, - 0xe5, 0xf9, 0x7e, 0xc7, 0x2a, 0x64, 0xf7, 0xc3, 0xa9, 0xb2, 0x1d, 0xe2, 0x27, 0xac, 0x22, 0xde, 0x69, 0x5d, 0x29, - 0x91, 0x46, 0x47, 0xdb, 0x80, 0x18, 0xb6, 0xec, 0x5b, 0xd4, 0xf0, 0x41, 0xd8, 0x45, 0x27, 0xf9, 0x41, 0x4f, 0xf1, - 0xd8, 0x1a, 0x48, 0xfa, 0x5a, 0x04, 0x5f, 0xa3, 0x23, 0x9d, 0x28, 0xd3, 0x48, 0x4c, 0x21, 0xd1, 0xaf, 0x17, 0x5a, - 0x63, 0x19, 0x65, 0x5f, 0x91, 0xff, 0xb3, 0xee, 0xde, 0x77, 0x62, 0xbb, 0x85, 0x49, 0xf6, 0x3c, 0xd0, 0x60, 0x53, - 0xa3, 0x56, 0x08, 0x67, 0xe7, 0xb4, 0x42, 0xed, 0x58, 0x2f, 0x2c, 0x81, 0x3c, 0x80, 0xad, 0x48, 0x83, 0x32, 0x48, - 0xf6, 0xa9, 0x98, 0x8b, 0x85, 0x13, 0xe5, 0x48, 0x85, 0x7f, 0x26, 0x47, 0x29, 0x87, 0xab, 0x58, 0x58, 0x30, 0xe4, - 0x57, 0x47, 0x17, 0x85, 0xbc, 0x02, 0x49, 0x89, 0x61, 0xa8, 0x2c, 0xaf, 0x8b, 0xab, 0xb6, 0x24, 0xb4, 0x77, 0x06, - 0xa0, 0x34, 0x05, 0x08, 0x5e, 0x1a, 0x35, 0xc4, 0x6c, 0xa3, 0x76, 0x57, 0xb4, 0x97, 0x1c, 0x50, 0xa7, 0xbb, 0x76, - 0xeb, 0x4d, 0xd9, 0xaa, 0x5b, 0x71, 0xe1, 0x9f, 0x50, 0xfa, 0x29, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, - 0x59, 0x76, 0x71, 0x87, 0x4b, 0xbf, 0x6a, 0x8c, 0x5f, 0xbf, 0xdf, 0x53, 0x0b, 0xa1, 0x91, 0x0a, 0xcc, 0xb7, 0xcf, - 0x4c, 0x55, 0x46, 0x53, 0x6a, 0x2f, 0xc1, 0x95, 0xb3, 0x1f, 0x41, 0x45, 0x5c, 0x57, 0xa4, 0x36, 0x35, 0x40, 0x07, - 0x5e, 0x56, 0xb8, 0x95, 0x05, 0x78, 0xec, 0x04, 0x64, 0xbb, 0xe5, 0x61, 0xa0, 0x0f, 0x9d, 0xc0, 0xdf, 0x92, 0xaf, - 0x90, 0x59, 0xb3, 0x8f, 0xff, 0xd2, 0x82, 0x7f, 0x6c, 0xc1, 0x4f, 0x28, 0xee, 0xb4, 0x32, 0xff, 0x56, 0x5a, 0xb7, - 0xb8, 0x7f, 0x27, 0xd3, 0x84, 0xa2, 0x32, 0xa1, 0xf6, 0x2b, 0xfd, 0xd1, 0x04, 0x8f, 0x52, 0xd9, 0x3f, 0x48, 0xf8, - 0x60, 0xd6, 0x78, 0x62, 0x8d, 0x27, 0xc3, 0xe9, 0x56, 0x1a, 0x96, 0x01, 0x85, 0x7e, 0x5e, 0xe6, 0x8a, 0xea, 0xe7, - 0x9f, 0xd7, 0x7c, 0xcd, 0x9b, 0x2d, 0xb6, 0x49, 0xf7, 0x34, 0xd8, 0xcb, 0xa3, 0x29, 0x85, 0x93, 0xa8, 0x73, 0x23, - 0x51, 0x17, 0x35, 0xcb, 0x50, 0x9d, 0xe0, 0xd5, 0x3c, 0xd5, 0xc3, 0xde, 0x4c, 0x44, 0x6b, 0x25, 0x65, 0x89, 0x01, - 0x6b, 0x1d, 0x79, 0x48, 0xee, 0xd6, 0x3a, 0xee, 0x34, 0xd4, 0xa5, 0x29, 0xd4, 0x04, 0x2b, 0x5c, 0x80, 0x23, 0xe8, - 0x5d, 0x11, 0x72, 0xb8, 0xa6, 0x2a, 0xfd, 0x82, 0xa6, 0xe4, 0x89, 0xa7, 0xa8, 0xd5, 0x8a, 0x74, 0xfb, 0x51, 0x8e, - 0xdd, 0xf0, 0x8d, 0x13, 0x72, 0x62, 0x84, 0xfe, 0xee, 0x58, 0xca, 0x19, 0x5a, 0x3c, 0xa8, 0x13, 0xac, 0x97, 0xb7, - 0x14, 0x28, 0xe6, 0xe8, 0xb2, 0xea, 0x9a, 0x97, 0x68, 0xfb, 0xb2, 0xec, 0xf7, 0x73, 0x5b, 0x4f, 0xca, 0x4e, 0x36, - 0x4b, 0xb3, 0x0f, 0x51, 0x31, 0x85, 0xbb, 0x3e, 0xd1, 0xfc, 0x55, 0xa8, 0xaf, 0xda, 0x32, 0xe7, 0x23, 0x8e, 0x38, - 0x21, 0x39, 0xa9, 0xff, 0xa5, 0xa6, 0x5e, 0x89, 0xfb, 0x55, 0x25, 0xbf, 0x0a, 0x63, 0xc5, 0x68, 0x89, 0x21, 0x8a, - 0xb4, 0x7b, 0x63, 0xfa, 0xb2, 0x00, 0xf8, 0x2b, 0xc1, 0x3e, 0xa5, 0xa1, 0x56, 0x7e, 0x8b, 0xb6, 0x80, 0x7f, 0xa3, - 0xb8, 0x01, 0xab, 0xc0, 0x00, 0xa3, 0xc9, 0xf6, 0x9c, 0x26, 0x70, 0xc0, 0x09, 0xad, 0xa2, 0xa0, 0xc2, 0x0c, 0x0d, - 0xb5, 0x85, 0xd1, 0x57, 0x28, 0xe3, 0x56, 0x99, 0xbd, 0x1b, 0x63, 0xa7, 0x05, 0x5e, 0xc3, 0xbf, 0xd1, 0x0b, 0xc5, - 0x6c, 0xd4, 0x41, 0x7a, 0x74, 0x12, 0xd3, 0x1f, 0xb7, 0x70, 0x72, 0xb3, 0x70, 0x96, 0x35, 0x4b, 0xa0, 0x3b, 0x70, - 0x41, 0x8c, 0xfb, 0xfd, 0x1c, 0x8e, 0x4c, 0x33, 0xf2, 0x05, 0xcb, 0x69, 0xcc, 0x96, 0x54, 0x7b, 0x1e, 0x5e, 0x56, - 0x61, 0x4e, 0x97, 0x56, 0xc6, 0x9b, 0x32, 0x50, 0x19, 0x6d, 0xb7, 0x21, 0xfc, 0xe9, 0xb6, 0x76, 0x49, 0xe7, 0x4b, - 0xc8, 0x00, 0x7f, 0x40, 0x22, 0x8a, 0x58, 0xe0, 0xff, 0x56, 0xe3, 0x94, 0x9e, 0x28, 0xad, 0x59, 0x42, 0xd7, 0x4c, - 0xd7, 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0xb6, 0xdb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, - 0x02, 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0x2f, - 0x1f, 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xfc, 0x31, 0x0d, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0xbf, 0x82, 0x2c, 0x47, - 0x00, 0xae, 0xe7, 0x2b, 0x88, 0x02, 0xb7, 0x86, 0xb8, 0xf0, 0xd0, 0xa0, 0xb7, 0x85, 0xbc, 0xca, 0x4a, 0x1e, 0xe2, - 0x3d, 0xc1, 0xd3, 0x8c, 0xee, 0x37, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0x36, 0x9e, 0x72, 0xbf, 0xfe, 0x55, 0x84, - 0x73, 0x88, 0xde, 0xb9, 0xa0, 0x5a, 0x5d, 0xed, 0x00, 0xb9, 0x3c, 0xdb, 0xab, 0xb7, 0x70, 0xba, 0xe9, 0xeb, 0x5b, - 0x15, 0x3a, 0x73, 0x00, 0x69, 0x0f, 0xc9, 0xba, 0xe6, 0x7a, 0x07, 0x78, 0x47, 0xe2, 0x1a, 0x68, 0xac, 0xdb, 0x9a, - 0x9d, 0xf6, 0x28, 0x1e, 0x13, 0x99, 0x19, 0x8b, 0x14, 0x63, 0xee, 0xd6, 0x69, 0x51, 0xb4, 0x41, 0x33, 0x84, 0xdd, - 0xbb, 0x4e, 0xb6, 0x6e, 0x45, 0x9c, 0xdf, 0x6f, 0xfb, 0x02, 0xa3, 0x61, 0xcc, 0xb5, 0x7b, 0xbe, 0xa1, 0xdb, 0xda, - 0x8d, 0x8c, 0x46, 0x82, 0xcc, 0xd4, 0x81, 0x28, 0x6b, 0x6b, 0xc0, 0xf6, 0x96, 0xeb, 0x4d, 0x0b, 0xfc, 0xbc, 0x89, - 0xc1, 0xdb, 0xb3, 0xc6, 0x29, 0xad, 0xaf, 0x71, 0xcd, 0x71, 0x55, 0x88, 0xa8, 0x2d, 0x52, 0x00, 0x0c, 0x3b, 0x5f, - 0xe0, 0xce, 0xac, 0x30, 0x98, 0x13, 0x96, 0x4a, 0x76, 0x2a, 0xd7, 0x9f, 0xc3, 0x16, 0x07, 0xa9, 0x7c, 0xe9, 0xf5, - 0xf7, 0x5f, 0xbe, 0xf8, 0x02, 0xdd, 0xf6, 0x9c, 0x1f, 0x41, 0x90, 0x09, 0x74, 0x50, 0x53, 0xaa, 0xc7, 0x1f, 0x0a, - 0xa0, 0xf6, 0x30, 0x0f, 0x3f, 0x14, 0x4c, 0xc4, 0xd7, 0xd9, 0x65, 0x5c, 0xc9, 0x62, 0x74, 0xcd, 0x45, 0x2a, 0x0b, - 0x2b, 0x35, 0x0e, 0x4e, 0x57, 0xab, 0x9c, 0x07, 0x60, 0x2a, 0x6f, 0x19, 0x65, 0x27, 0x97, 0xd4, 0x83, 0xab, 0xe5, - 0xe9, 0x95, 0x16, 0x9d, 0x97, 0xd7, 0x97, 0x41, 0x84, 0xbf, 0xce, 0xcd, 0x8f, 0xab, 0xb8, 0xfc, 0x18, 0x44, 0xd6, - 0xa6, 0xce, 0xfc, 0x40, 0xa9, 0x3c, 0xf8, 0x3b, 0x81, 0x4c, 0xf7, 0x87, 0x02, 0x2c, 0xb3, 0x6d, 0xc5, 0xc7, 0x31, - 0xd6, 0x3a, 0x9c, 0x90, 0x99, 0x2a, 0xd1, 0x7b, 0x97, 0xac, 0x0b, 0xb0, 0xf6, 0x53, 0xd8, 0xce, 0x2a, 0xd7, 0x0c, - 0x2b, 0x53, 0x15, 0x19, 0x82, 0xb6, 0x66, 0x87, 0xa1, 0x75, 0xa2, 0x99, 0xa3, 0xb7, 0x80, 0x7e, 0x20, 0x87, 0x97, - 0x54, 0xae, 0x99, 0xe7, 0x63, 0xd3, 0x78, 0xfd, 0xe0, 0xf0, 0xd2, 0x13, 0x28, 0xd9, 0x3b, 0x39, 0x0a, 0x13, 0xc1, - 0xd3, 0xd8, 0x8c, 0x2f, 0xf2, 0xac, 0x80, 0x1d, 0x34, 0x19, 0x8f, 0xa9, 0xb7, 0xb4, 0x5a, 0x37, 0x47, 0x87, 0x6c, - 0x9b, 0x3d, 0xac, 0x1e, 0x72, 0x72, 0xc8, 0x5b, 0xa6, 0xb6, 0x6d, 0xeb, 0x38, 0x4f, 0x93, 0xaf, 0x4c, 0xf7, 0xcb, - 0xb5, 0x8d, 0x10, 0xaf, 0x9c, 0x1d, 0x9d, 0x97, 0x74, 0xeb, 0x9b, 0xd2, 0xd0, 0x6b, 0x09, 0xc0, 0x7c, 0xda, 0x80, - 0xbf, 0x60, 0x72, 0x3d, 0xaa, 0x78, 0x59, 0x81, 0x84, 0x05, 0x45, 0x78, 0x53, 0xec, 0x4d, 0xe1, 0x6e, 0x9c, 0x9e, - 0xc3, 0x0e, 0x5c, 0x4c, 0xd1, 0x1d, 0x27, 0x26, 0xb3, 0xd2, 0x68, 0x45, 0x23, 0xfd, 0xcb, 0xf5, 0x25, 0xd6, 0x7d, - 0xd1, 0xca, 0x3c, 0x9b, 0x53, 0x61, 0xd3, 0xbb, 0xca, 0xa5, 0x13, 0xf5, 0x5b, 0x26, 0x5c, 0xb9, 0x12, 0x04, 0x64, - 0x5a, 0xb0, 0x5e, 0x61, 0x76, 0x51, 0x81, 0x84, 0x0c, 0x0c, 0x5f, 0x83, 0xb5, 0x28, 0xb9, 0xb1, 0x82, 0xf5, 0xee, - 0xf9, 0x3a, 0x41, 0x48, 0xc1, 0x03, 0x37, 0x41, 0xbf, 0xb4, 0x6e, 0xde, 0x8e, 0x12, 0x65, 0x10, 0x9f, 0x5c, 0x3b, - 0xe5, 0x20, 0x81, 0x00, 0x1c, 0x58, 0x15, 0x92, 0x44, 0x81, 0xce, 0x83, 0xab, 0x19, 0x47, 0xb0, 0x79, 0xe5, 0xcc, - 0xc5, 0x0d, 0xe0, 0xbc, 0xf2, 0xe7, 0xb2, 0xc1, 0x96, 0xf5, 0x88, 0x2a, 0x73, 0xc6, 0x29, 0x06, 0x75, 0xb2, 0x04, - 0x7d, 0x65, 0x29, 0xed, 0x25, 0x68, 0x1a, 0xaf, 0xd8, 0x4a, 0xf9, 0x00, 0xd0, 0x73, 0xb6, 0x52, 0xc6, 0xfe, 0xf8, - 0xf5, 0x19, 0x5b, 0x69, 0x69, 0xf0, 0xf4, 0x6a, 0x76, 0x3e, 0x3b, 0x1b, 0xb0, 0xa3, 0x28, 0xd4, 0x06, 0x0c, 0x81, - 0x8b, 0x4c, 0x10, 0x0c, 0x42, 0x8d, 0xff, 0x32, 0x50, 0x01, 0xc2, 0x88, 0xc7, 0x63, 0x23, 0x8e, 0x58, 0x38, 0x1e, - 0x62, 0x30, 0xb0, 0xe6, 0x0b, 0x12, 0x10, 0x6a, 0x4a, 0x43, 0x5f, 0xcf, 0x70, 0x38, 0x39, 0x98, 0x40, 0x2a, 0x66, - 0x66, 0xaa, 0x30, 0x36, 0x26, 0x11, 0xc4, 0x7f, 0xed, 0xac, 0x17, 0xca, 0xed, 0xae, 0xd1, 0x40, 0xd0, 0x0c, 0xbe, - 0xa8, 0xe2, 0xc9, 0xc1, 0xb0, 0xab, 0x62, 0x1c, 0x85, 0x6b, 0xa3, 0x7c, 0x3b, 0x3b, 0x06, 0x30, 0xdf, 0xb3, 0xa1, - 0x2f, 0x97, 0x38, 0x3b, 0x7c, 0x4c, 0x1e, 0x3e, 0x26, 0xf4, 0x8c, 0x9d, 0x7d, 0xf5, 0x98, 0x9e, 0x29, 0x72, 0x72, - 0x30, 0x89, 0xae, 0x99, 0xc5, 0xc0, 0x39, 0x52, 0x4d, 0xa0, 0x97, 0xa3, 0xb5, 0x50, 0x0b, 0x4c, 0x3b, 0x34, 0x85, - 0xdf, 0x8e, 0x0f, 0x82, 0xc1, 0x75, 0xbb, 0xe9, 0xd7, 0xed, 0xb6, 0x7a, 0x5e, 0x5d, 0x07, 0x47, 0xd1, 0x6e, 0x31, - 0x93, 0xbf, 0x8f, 0x0f, 0xdc, 0x1c, 0x60, 0x7d, 0xf7, 0x8f, 0x89, 0x69, 0xd2, 0xce, 0xa8, 0xf8, 0x35, 0x3d, 0xc2, - 0x3e, 0x34, 0x8b, 0xec, 0xe8, 0xc3, 0xf0, 0xdf, 0xea, 0x44, 0x7d, 0xf6, 0xd5, 0x11, 0x90, 0x23, 0x90, 0x81, 0x62, - 0x89, 0x60, 0x86, 0x03, 0x4d, 0x01, 0x05, 0x99, 0x1e, 0x77, 0xaa, 0x87, 0x5f, 0x8d, 0x9a, 0x9a, 0x91, 0x6b, 0x98, - 0x1a, 0x6c, 0x0b, 0x7e, 0xa0, 0xba, 0xa1, 0xbf, 0xd1, 0x68, 0x4f, 0xda, 0xc9, 0xcc, 0xbc, 0xa4, 0x36, 0xce, 0xdd, - 0x35, 0x04, 0x74, 0x76, 0x70, 0x8b, 0x92, 0x7d, 0x7d, 0x7c, 0x79, 0x80, 0xab, 0x08, 0x50, 0xc3, 0x58, 0xf0, 0xf5, - 0xe0, 0x52, 0x6f, 0xee, 0x83, 0x80, 0x0c, 0xbe, 0x0e, 0x4e, 0xbe, 0x1e, 0xc8, 0x41, 0x70, 0x7c, 0x78, 0x79, 0x12, - 0x38, 0xe3, 0x7e, 0x08, 0x79, 0xa9, 0x2a, 0x8a, 0x99, 0x30, 0x55, 0x24, 0xb6, 0xf6, 0xdc, 0xd6, 0xab, 0x8c, 0xcf, - 0x68, 0x3a, 0xb5, 0x48, 0xe8, 0x61, 0xca, 0x62, 0xf3, 0x3b, 0x98, 0xf0, 0xab, 0x20, 0x72, 0x41, 0x61, 0x67, 0x79, - 0x14, 0xd3, 0x25, 0xbb, 0x15, 0x61, 0x4a, 0x93, 0xc3, 0x9c, 0x90, 0x28, 0x5c, 0x2a, 0x30, 0x41, 0xf5, 0x3a, 0x81, - 0xb8, 0xb6, 0xee, 0xf3, 0x5b, 0x11, 0x2e, 0x69, 0x7e, 0x98, 0x90, 0x56, 0x11, 0x2e, 0x42, 0xcd, 0xa6, 0xa6, 0x17, - 0x2c, 0x5c, 0xd1, 0x4b, 0x34, 0xd5, 0x5c, 0x87, 0x97, 0xc0, 0xe5, 0xad, 0xe7, 0xab, 0x05, 0xbb, 0x6c, 0x48, 0xdf, - 0x0c, 0x5f, 0x7c, 0x61, 0x7d, 0xf2, 0x80, 0x87, 0x74, 0x7e, 0x78, 0x29, 0xd8, 0x00, 0x5c, 0x67, 0xfc, 0xe6, 0x3b, - 0x79, 0xab, 0xe7, 0xa5, 0x3d, 0xc5, 0x38, 0x33, 0xed, 0xc4, 0xa4, 0x9d, 0x90, 0xfb, 0xf7, 0x6d, 0xdf, 0xbd, 0x78, - 0xad, 0x5c, 0x56, 0x2d, 0x43, 0x12, 0xaf, 0x95, 0xeb, 0x34, 0x4a, 0x4e, 0xad, 0xc0, 0x93, 0x5d, 0xf0, 0x2a, 0x59, - 0xfa, 0x07, 0x95, 0xb5, 0x1a, 0xb0, 0xc7, 0x88, 0x65, 0xa1, 0x70, 0xec, 0x5f, 0x65, 0x2c, 0x5e, 0x37, 0x90, 0x81, - 0x91, 0x7b, 0x7b, 0x95, 0x31, 0x2f, 0x06, 0x6d, 0xbe, 0xf6, 0x42, 0xf7, 0x79, 0xe9, 0xcb, 0x16, 0xef, 0xe5, 0x94, - 0x1a, 0x46, 0x22, 0x7a, 0x30, 0x56, 0x66, 0x94, 0x2a, 0x51, 0x6b, 0xd0, 0x88, 0x60, 0x63, 0x17, 0x0c, 0x14, 0x9c, - 0x50, 0xb9, 0xa7, 0xce, 0xf6, 0xed, 0x94, 0x4a, 0x0f, 0x68, 0x97, 0x1a, 0x55, 0xb9, 0x5b, 0x66, 0x92, 0x55, 0x83, - 0x60, 0xf4, 0x67, 0x29, 0xc5, 0x0c, 0xef, 0x8c, 0x2c, 0x98, 0x82, 0x95, 0xa0, 0xaa, 0x65, 0x58, 0x0e, 0x39, 0x6a, - 0xf1, 0x8c, 0x4f, 0xaa, 0xd4, 0x3f, 0x3a, 0x82, 0x06, 0xa7, 0xeb, 0x56, 0xd0, 0xe0, 0xc7, 0xe3, 0xc7, 0x7a, 0xa0, - 0xd7, 0x6b, 0xed, 0x78, 0xe8, 0xf3, 0xdb, 0x88, 0x37, 0xae, 0x7b, 0x4f, 0xb5, 0x56, 0xa1, 0x0c, 0xb4, 0x58, 0x51, - 0xb9, 0x52, 0x4b, 0xba, 0xdf, 0x45, 0x00, 0x2c, 0x62, 0x63, 0x36, 0xde, 0xb5, 0xcd, 0x0a, 0x41, 0xa3, 0xcb, 0x4e, - 0x36, 0xf1, 0x80, 0x25, 0xba, 0xb5, 0x83, 0x09, 0x8d, 0x4f, 0x58, 0xd9, 0xef, 0xe7, 0x27, 0x40, 0x4f, 0xb5, 0x11, - 0x53, 0x01, 0x47, 0xfe, 0x97, 0x56, 0x64, 0x8a, 0x02, 0x9b, 0x35, 0x75, 0xb7, 0xc6, 0x32, 0x12, 0x7d, 0x99, 0xd2, - 0xe5, 0x09, 0xcf, 0x80, 0xe9, 0x62, 0xdd, 0x72, 0x5c, 0xd9, 0x55, 0x1c, 0x79, 0x2a, 0x2c, 0x2b, 0xce, 0xab, 0x70, - 0xbc, 0xf5, 0xf8, 0x06, 0x87, 0x86, 0x4d, 0x5b, 0xf9, 0x43, 0x08, 0x0b, 0xe1, 0x55, 0x06, 0xb7, 0x11, 0x6d, 0x27, - 0x81, 0xca, 0x1b, 0x73, 0x9d, 0x50, 0x36, 0xb7, 0x17, 0x6b, 0xcf, 0x20, 0x9d, 0x98, 0x03, 0xa5, 0x1a, 0x41, 0x6b, - 0x34, 0x0b, 0xaa, 0x46, 0x3c, 0x72, 0xe6, 0x5f, 0xce, 0x20, 0x56, 0xcb, 0x97, 0x34, 0x95, 0xa2, 0x01, 0x18, 0x17, - 0xc0, 0xe5, 0xe9, 0x97, 0x77, 0x3f, 0xbd, 0xe7, 0x71, 0x91, 0x2c, 0xdf, 0xc6, 0x45, 0x7c, 0x55, 0x86, 0x1b, 0x35, - 0x46, 0x71, 0x4d, 0xa6, 0x62, 0xc0, 0xa4, 0x59, 0x49, 0xcd, 0x5d, 0xa9, 0x09, 0x31, 0xd6, 0x99, 0xac, 0xcb, 0x4a, - 0x5e, 0x35, 0x2a, 0x5d, 0x17, 0x19, 0x7e, 0xdc, 0xf2, 0x39, 0x3d, 0x04, 0x60, 0x53, 0xe3, 0x42, 0x1a, 0x49, 0x5d, - 0x88, 0x31, 0x17, 0xf1, 0xba, 0x3e, 0x1e, 0x37, 0xba, 0x5e, 0xb2, 0x27, 0xe3, 0x47, 0xd3, 0x57, 0x59, 0x98, 0x0d, - 0x04, 0x19, 0x55, 0x4b, 0x2e, 0x5a, 0xa6, 0x9c, 0xca, 0x24, 0x00, 0x7d, 0x3c, 0x7b, 0x8c, 0x1d, 0x8d, 0xc7, 0x64, - 0xd3, 0x16, 0x0f, 0xf0, 0x30, 0x5d, 0x87, 0x05, 0x99, 0xe9, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, 0x2a, 0x00, 0x64, 0x4b, - 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0x93, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, 0x37, 0xf3, 0xd2, 0xf7, - 0x28, 0x92, 0xc6, 0x65, 0x69, 0xa7, 0x52, 0xa9, 0xf6, 0xcc, 0xcc, 0x75, 0x0d, 0x62, 0x52, 0x84, 0xba, 0xee, 0xd2, - 0xab, 0x7b, 0xb7, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, 0xba, 0x22, 0x6a, 0x7a, - 0xb9, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0xeb, 0x35, 0x05, 0xa5, 0x60, 0xb4, 0x5a, 0x7b, 0x0b, 0xf7, 0xa9, 0x6c, - 0x5c, 0x58, 0x32, 0xbd, 0x5a, 0x94, 0x94, 0x50, 0xdd, 0x54, 0x8c, 0x94, 0x30, 0x52, 0x1a, 0x9e, 0xca, 0xf7, 0x02, - 0x8f, 0xf3, 0x3c, 0x88, 0x5a, 0x5e, 0x60, 0xa7, 0x15, 0x39, 0x05, 0x47, 0x2f, 0x93, 0xd3, 0x50, 0xe0, 0x1f, 0x33, - 0x05, 0xea, 0x3a, 0x54, 0xf7, 0x1b, 0xdc, 0xfc, 0xbf, 0x15, 0x2c, 0xf0, 0xf8, 0xd6, 0x2b, 0xdc, 0x46, 0xbf, 0x15, - 0x3e, 0x2d, 0x7d, 0x23, 0x7d, 0x57, 0x17, 0x4f, 0xda, 0x9b, 0x8d, 0x92, 0x65, 0x96, 0xa7, 0xaf, 0x65, 0xca, 0x41, - 0x64, 0x86, 0xd6, 0xa0, 0xec, 0x44, 0x34, 0x6e, 0x78, 0x60, 0xc4, 0xd8, 0xb8, 0xf1, 0xfd, 0x98, 0x81, 0x6c, 0x18, - 0xac, 0xbe, 0x59, 0x2a, 0x93, 0x35, 0x20, 0x6c, 0x68, 0xf9, 0x89, 0xc6, 0xdb, 0x08, 0xf5, 0xf5, 0x0b, 0xdc, 0xe6, - 0x4a, 0xdf, 0xe7, 0xfc, 0xc7, 0x8c, 0xfe, 0x88, 0xc0, 0x2f, 0xf1, 0x0a, 0xe4, 0x1e, 0x4f, 0xa1, 0x6e, 0x84, 0xed, - 0xe5, 0x18, 0x2c, 0x09, 0xd1, 0x51, 0x44, 0xc5, 0x02, 0x05, 0x4d, 0x61, 0x10, 0x45, 0xd4, 0x05, 0x73, 0x78, 0x9e, - 0xcb, 0xe4, 0xe3, 0xd4, 0xf8, 0xcc, 0x0f, 0x63, 0x8c, 0x21, 0x1d, 0x0c, 0xc2, 0x6a, 0x16, 0x0c, 0xc7, 0xa3, 0xc9, - 0xd1, 0x13, 0x38, 0xb7, 0x83, 0x71, 0x40, 0x06, 0x41, 0x5d, 0xae, 0x62, 0x41, 0xcb, 0xeb, 0x4b, 0x5b, 0x06, 0x7e, - 0x5c, 0x07, 0x83, 0xdf, 0x0a, 0x4f, 0xf1, 0x0e, 0x9a, 0x93, 0x3b, 0x19, 0x06, 0x01, 0xbd, 0x5c, 0x13, 0x90, 0x94, - 0xf5, 0x34, 0x3f, 0xa9, 0x0f, 0x37, 0xa6, 0xb4, 0x7f, 0xe6, 0xf0, 0x82, 0xc3, 0x0e, 0x09, 0x14, 0x48, 0xe3, 0x69, - 0x36, 0x7a, 0xa9, 0x14, 0xb9, 0x6f, 0x0b, 0x0e, 0x77, 0xe6, 0x9e, 0x33, 0x3d, 0x72, 0x0a, 0x89, 0x66, 0x16, 0x70, - 0x23, 0x7f, 0x29, 0xae, 0xe3, 0x3c, 0x4b, 0x0f, 0x9a, 0x6f, 0x0e, 0xca, 0x3b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, 0x58, - 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xc7, 0xcc, 0x64, 0xc6, 0x23, 0xf0, 0x08, - 0x6c, 0xfa, 0x40, 0x16, 0x77, 0xce, 0x25, 0xc9, 0xdf, 0x4c, 0xa5, 0xbd, 0xea, 0x95, 0x3b, 0x05, 0x59, 0xaf, 0xb6, - 0x72, 0xd7, 0xad, 0xcf, 0xbe, 0xe9, 0xf0, 0x0a, 0x3c, 0x93, 0xe0, 0x16, 0xd9, 0xef, 0x37, 0x05, 0x95, 0xc2, 0xa8, - 0x88, 0x77, 0x92, 0x6b, 0xf4, 0x6f, 0xf7, 0xc6, 0x46, 0x91, 0xdc, 0xf2, 0xfe, 0x01, 0xd4, 0x99, 0xbc, 0x2b, 0x6e, - 0xe7, 0x10, 0xb5, 0x75, 0x37, 0x1e, 0x78, 0x6f, 0xd0, 0x2e, 0x6b, 0x8e, 0x60, 0xcb, 0x8b, 0x83, 0x0c, 0xc6, 0x02, - 0x67, 0x65, 0xa4, 0xd4, 0xb8, 0x56, 0x46, 0x03, 0x6a, 0x93, 0x3d, 0x64, 0xa9, 0x27, 0x41, 0x91, 0xe3, 0x59, 0x0c, - 0x99, 0xc6, 0xdb, 0x40, 0xec, 0xb7, 0x32, 0x04, 0x69, 0xda, 0x76, 0xdb, 0x1c, 0x81, 0xb2, 0x7b, 0x60, 0x4a, 0x52, - 0xd7, 0xc6, 0xd4, 0x40, 0x43, 0x0f, 0xa2, 0x46, 0x2a, 0xe2, 0xec, 0xe4, 0x29, 0xe8, 0x10, 0xc1, 0xf7, 0x3b, 0xcd, - 0xca, 0x8e, 0x17, 0x13, 0x82, 0x27, 0xef, 0xf3, 0xdb, 0xac, 0xac, 0xca, 0xe8, 0x45, 0x8a, 0x86, 0x50, 0x89, 0x14, - 0xd1, 0x6b, 0x88, 0x2f, 0x58, 0xe2, 0xef, 0x32, 0x7a, 0x97, 0xd2, 0x38, 0x4d, 0x31, 0xfd, 0x59, 0x01, 0x3f, 0x9f, - 0x02, 0xca, 0x25, 0xee, 0x84, 0xe8, 0x4c, 0x82, 0xbd, 0x1a, 0x44, 0xf7, 0xaa, 0x38, 0x60, 0x8a, 0x46, 0xb7, 0x82, - 0x22, 0x66, 0x1d, 0x66, 0xff, 0xa5, 0x40, 0xa1, 0x90, 0x2a, 0xe6, 0x57, 0x61, 0x1f, 0xa2, 0x6a, 0x0d, 0xe5, 0x9c, - 0xbe, 0x7d, 0x69, 0x86, 0x34, 0xba, 0x95, 0x54, 0x6f, 0x6d, 0x3c, 0xb6, 0x10, 0xa5, 0x27, 0xba, 0x5a, 0xd3, 0xb3, - 0x78, 0x95, 0x45, 0x1b, 0xc0, 0x9f, 0x78, 0xfb, 0xf2, 0xa9, 0xb2, 0x30, 0x79, 0x99, 0x81, 0xe2, 0xe0, 0xf4, 0xed, - 0xcb, 0x57, 0x32, 0x5d, 0xe7, 0x3c, 0xba, 0x93, 0x48, 0x5a, 0x4f, 0xdf, 0xbe, 0xfc, 0x19, 0xcd, 0xbd, 0xde, 0x15, - 0xf0, 0xfe, 0x05, 0xf0, 0x96, 0x51, 0xb2, 0x86, 0x3e, 0xa9, 0xdf, 0xf9, 0x1a, 0x3b, 0xe5, 0xd5, 0x5a, 0x46, 0xff, - 0x4c, 0x6b, 0x4f, 0x5a, 0xf5, 0x57, 0xe1, 0x53, 0x3b, 0x4f, 0xc0, 0x73, 0x9b, 0x67, 0xe2, 0x63, 0x64, 0x45, 0x3b, - 0x41, 0xf4, 0xf5, 0xc1, 0xed, 0x55, 0x2e, 0xca, 0x08, 0x5f, 0x30, 0xb4, 0x0b, 0x8a, 0x0e, 0x0f, 0x6f, 0x6e, 0x6e, - 0x46, 0x37, 0x8f, 0x46, 0xb2, 0xb8, 0x3c, 0x9c, 0x7c, 0xfb, 0xed, 0xb7, 0x87, 0xf8, 0x36, 0xf8, 0xba, 0xed, 0xf6, - 0x5e, 0x11, 0x3e, 0x60, 0x01, 0x22, 0x76, 0x7f, 0x0d, 0x57, 0x14, 0xd0, 0xc2, 0x0d, 0xbe, 0x0e, 0xbe, 0xd6, 0x87, - 0xce, 0xd7, 0xc7, 0xe5, 0xf5, 0xa5, 0x2a, 0xbf, 0xab, 0xe4, 0xa3, 0xf1, 0x78, 0x7c, 0x08, 0x12, 0xa8, 0xaf, 0x07, - 0x7c, 0x10, 0x9c, 0x04, 0x83, 0x0c, 0x2e, 0x34, 0xe5, 0xf5, 0xe5, 0x49, 0xe0, 0x19, 0xd8, 0x36, 0x58, 0x44, 0x07, - 0xe2, 0x12, 0x1c, 0x5e, 0xd2, 0xe0, 0xeb, 0x80, 0xb8, 0x94, 0xaf, 0x20, 0xe5, 0xab, 0xa3, 0x27, 0x7e, 0xda, 0xff, - 0x52, 0x69, 0x8f, 0xfc, 0xb4, 0x63, 0x4c, 0x7b, 0xf4, 0xd4, 0x4f, 0x3b, 0x51, 0x69, 0xcf, 0xfd, 0xb4, 0xff, 0x5d, - 0x0e, 0x20, 0xf5, 0xc0, 0xb7, 0xfe, 0x3b, 0xf3, 0x5a, 0x83, 0xa7, 0x50, 0x94, 0x5d, 0xc5, 0x97, 0x1c, 0x1a, 0x3d, - 0xb8, 0xbd, 0xca, 0x69, 0x30, 0xc0, 0xf6, 0x7a, 0x46, 0x1e, 0xde, 0x07, 0x5f, 0xaf, 0x8b, 0x3c, 0x0c, 0xbe, 0x1e, - 0x60, 0x21, 0x83, 0xaf, 0x03, 0xf2, 0xb5, 0x3e, 0xd2, 0xae, 0x05, 0xdb, 0x04, 0x2e, 0x34, 0xeb, 0xd0, 0x06, 0x4c, - 0xf3, 0xa5, 0x71, 0x35, 0xfd, 0xbd, 0xe8, 0xce, 0x86, 0xb7, 0x44, 0xe5, 0xa6, 0x1b, 0xd4, 0xf4, 0x01, 0x78, 0x27, - 0x40, 0xa3, 0xa2, 0xe0, 0x3a, 0x2e, 0xc2, 0xe1, 0xb0, 0xbc, 0xbe, 0x24, 0x60, 0x97, 0xb9, 0xe2, 0x71, 0x15, 0x05, - 0x42, 0x0e, 0xd5, 0xcf, 0x40, 0x45, 0x02, 0x0b, 0x10, 0xca, 0x08, 0xfe, 0x0b, 0x6a, 0xfa, 0x56, 0xb2, 0x4d, 0x30, - 0xbc, 0xe1, 0xe7, 0x1f, 0xb3, 0x6a, 0xa8, 0x44, 0x8b, 0xd7, 0x82, 0xc2, 0x0f, 0xf8, 0xeb, 0xaa, 0x8e, 0x7e, 0x07, - 0x37, 0xee, 0xa6, 0x86, 0xfd, 0xad, 0xf4, 0x1c, 0xda, 0xe4, 0x3c, 0x5b, 0x4c, 0x5b, 0x07, 0xfa, 0x03, 0x49, 0xaa, - 0x79, 0x36, 0x08, 0x86, 0xc1, 0x80, 0x2f, 0xd8, 0x03, 0x39, 0xe7, 0x9e, 0xf9, 0xd4, 0xa9, 0xf4, 0xa7, 0x79, 0x96, - 0x0d, 0xc0, 0x37, 0x05, 0xf9, 0x91, 0xc3, 0xff, 0x9e, 0x0f, 0x51, 0x78, 0x38, 0x78, 0x70, 0x48, 0x66, 0xc1, 0xea, - 0x16, 0x3d, 0x3a, 0xa3, 0x20, 0x13, 0x4b, 0x5e, 0x64, 0x95, 0xb7, 0x54, 0x6e, 0xd7, 0x6d, 0x2f, 0x8f, 0xbd, 0x67, - 0xf3, 0x2a, 0x16, 0x81, 0x3a, 0xe7, 0x40, 0xf1, 0x86, 0xb2, 0xa7, 0xb2, 0x29, 0x21, 0xd5, 0x86, 0xbc, 0x61, 0x39, - 0x60, 0xc1, 0x71, 0x6f, 0x38, 0x3c, 0x08, 0x06, 0x4e, 0x9d, 0x3b, 0x08, 0x0e, 0x86, 0xc3, 0x93, 0xc0, 0xdd, 0x87, - 0xb2, 0x91, 0xbb, 0x33, 0xd2, 0x82, 0xfd, 0x55, 0x84, 0x25, 0x05, 0xf1, 0x98, 0xd4, 0xe2, 0x2f, 0x0d, 0x2e, 0x33, - 0x00, 0xe8, 0x23, 0x25, 0x01, 0x33, 0xb0, 0x32, 0x03, 0x08, 0x55, 0x4e, 0x63, 0x76, 0x07, 0xcc, 0x23, 0x70, 0xcc, - 0x0a, 0x26, 0x0b, 0x10, 0x4b, 0x02, 0x9c, 0xbb, 0x20, 0x8a, 0x75, 0x21, 0xa7, 0x10, 0x04, 0x00, 0x7f, 0x12, 0x53, - 0x0a, 0x26, 0xe9, 0xd8, 0x8d, 0x20, 0x88, 0xe3, 0xb3, 0x6b, 0xd1, 0x9a, 0x9c, 0x25, 0x3a, 0x98, 0x91, 0x04, 0xd8, - 0x10, 0x03, 0xc3, 0x07, 0xf7, 0x73, 0x50, 0x7a, 0x58, 0xbd, 0x13, 0x72, 0xc1, 0x77, 0xdc, 0xb1, 0x50, 0xd7, 0x70, - 0xf5, 0x84, 0x83, 0xe0, 0x8e, 0x6b, 0x16, 0x60, 0x54, 0x15, 0xeb, 0xb2, 0xe2, 0xe9, 0x87, 0xbb, 0x15, 0xc4, 0x02, - 0xc4, 0x01, 0x7d, 0x2b, 0xf3, 0x2c, 0xb9, 0x0b, 0x9d, 0x3d, 0xd7, 0x46, 0xa5, 0xff, 0xf0, 0xe1, 0xd5, 0x4f, 0x11, - 0x88, 0x1c, 0x6b, 0x43, 0xe9, 0xef, 0x38, 0x9e, 0x4d, 0x7e, 0xc4, 0x2b, 0x7f, 0x63, 0xdf, 0x71, 0x7b, 0x7a, 0xf4, - 0xfb, 0x50, 0x37, 0xbd, 0xe3, 0xb3, 0x3b, 0x3e, 0x72, 0xc5, 0xa1, 0xba, 0xc2, 0x7d, 0xfd, 0x71, 0xed, 0x1b, 0x21, - 0xdd, 0x3f, 0xcf, 0x94, 0x37, 0xe6, 0x47, 0x3b, 0x18, 0x06, 0xc1, 0x54, 0x0b, 0x25, 0x21, 0x0a, 0x09, 0x53, 0x02, - 0x86, 0xe8, 0x40, 0x2f, 0xab, 0x29, 0x72, 0x6e, 0x6a, 0x64, 0xe1, 0xfd, 0x80, 0x69, 0xa1, 0x43, 0x23, 0x87, 0xf2, - 0x83, 0xc3, 0x09, 0x63, 0x16, 0x7e, 0xab, 0x84, 0xe9, 0x57, 0x8b, 0xca, 0x39, 0x88, 0x1e, 0x80, 0x31, 0xae, 0xe0, - 0x05, 0x74, 0x85, 0xdd, 0xac, 0x55, 0x94, 0x10, 0x04, 0xd3, 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, 0xaa, - 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, 0x06, 0x7e, 0xc9, 0x7e, 0x29, 0xd0, 0xb3, 0x7c, 0x2a, - 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0xb8, 0x7e, 0x3c, - 0x7d, 0x25, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, 0xc5, 0x44, 0xc1, 0x3e, 0x42, 0xbf, 0xda, 0x36, 0xfa, - 0xec, 0x76, 0xad, 0x37, 0x83, 0x12, 0x1d, 0xf3, 0x1a, 0x05, 0xd7, 0x4a, 0xa1, 0x60, 0xb4, 0xb7, 0xf1, 0x67, 0x38, - 0x72, 0xab, 0xdb, 0x43, 0xef, 0xb7, 0x2a, 0xbe, 0x7c, 0x8d, 0xbe, 0x9d, 0xf6, 0xe7, 0xa8, 0x92, 0xbf, 0xac, 0x56, - 0xe0, 0x43, 0x05, 0x91, 0x56, 0x2c, 0x4e, 0x2f, 0xd4, 0xf3, 0xfe, 0xed, 0xe9, 0x6b, 0xf0, 0xa3, 0xc4, 0xdf, 0xbf, - 0x7e, 0x1f, 0xd4, 0x64, 0x1a, 0xcf, 0x0a, 0xf3, 0xa1, 0xcd, 0x01, 0xa1, 0x5a, 0x5c, 0x9a, 0x7d, 0x3f, 0x8b, 0x9b, - 0xec, 0xbb, 0x66, 0xeb, 0x69, 0xd1, 0x44, 0x92, 0x32, 0xdc, 0x3e, 0x18, 0x10, 0xe8, 0x03, 0x44, 0x71, 0xf6, 0x05, - 0x8d, 0x21, 0xcd, 0x67, 0xf6, 0xfd, 0x08, 0x81, 0x2f, 0x77, 0x42, 0xaa, 0x71, 0x85, 0x45, 0xa3, 0x87, 0x7c, 0xc6, - 0x23, 0x65, 0x58, 0xf4, 0x0e, 0x13, 0x88, 0x33, 0x9c, 0x56, 0xef, 0x11, 0x03, 0x1a, 0xef, 0x06, 0x5a, 0xf6, 0x10, - 0x65, 0xd4, 0x65, 0x6f, 0x58, 0x7c, 0xbf, 0x5f, 0x87, 0x99, 0xb5, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x1b, 0x80, 0x53, - 0x8e, 0x2c, 0x5f, 0x65, 0x36, 0xba, 0x5a, 0x62, 0x7a, 0x13, 0x41, 0x6c, 0x22, 0x9d, 0x0e, 0x6b, 0x57, 0xa7, 0xea, - 0x5d, 0xed, 0x7c, 0x26, 0x7a, 0x15, 0x68, 0xe5, 0xda, 0xf6, 0x78, 0x08, 0xff, 0xa9, 0xa5, 0x15, 0x36, 0xc2, 0x9e, - 0x8b, 0x2f, 0x3c, 0xc7, 0xe6, 0x04, 0x34, 0xb8, 0x92, 0x29, 0x00, 0x67, 0x69, 0x35, 0x1a, 0x35, 0xc2, 0x3e, 0x2b, - 0xe7, 0x73, 0xd8, 0x5a, 0x88, 0xa7, 0x05, 0xe0, 0xc0, 0x4d, 0x4c, 0x4e, 0xde, 0x8d, 0xc9, 0x39, 0xfd, 0xa8, 0xe0, - 0xbe, 0x83, 0xb3, 0x72, 0x19, 0xa7, 0xf2, 0x06, 0xb0, 0x29, 0x03, 0x3f, 0x15, 0x4b, 0xf5, 0x12, 0x92, 0x25, 0x4f, - 0x3e, 0xa2, 0xd5, 0x46, 0x1a, 0x00, 0x57, 0x39, 0x35, 0x96, 0x7b, 0x0a, 0x34, 0xd5, 0x95, 0xa2, 0x12, 0xe2, 0xaa, - 0x8a, 0x93, 0xe5, 0x7b, 0x4c, 0x0d, 0x37, 0xd0, 0x8b, 0x28, 0x90, 0x2b, 0x2e, 0x80, 0xa4, 0xe7, 0xec, 0x5f, 0x99, - 0xc6, 0x5e, 0x7f, 0x23, 0x51, 0xc0, 0xa4, 0x51, 0x94, 0xb1, 0x52, 0xf6, 0x52, 0x9a, 0xe8, 0x77, 0x41, 0x50, 0xbb, - 0x97, 0x7f, 0x41, 0xdd, 0x4f, 0xa1, 0x15, 0x61, 0x03, 0xbc, 0x50, 0x83, 0x1f, 0xa6, 0x76, 0xc9, 0x79, 0x40, 0x86, - 0xce, 0xfb, 0xac, 0xb6, 0x5b, 0xfd, 0xe9, 0x12, 0xb0, 0x5e, 0x53, 0xe3, 0x53, 0x18, 0x26, 0xc4, 0xc4, 0x4a, 0xb6, - 0xca, 0x4a, 0xbb, 0xa1, 0x4c, 0x3b, 0xe9, 0x92, 0x79, 0x2d, 0x9c, 0xe6, 0x3d, 0xc6, 0x96, 0x23, 0x95, 0xbb, 0xdf, - 0x0f, 0xcd, 0x4f, 0x96, 0xd3, 0x37, 0x3a, 0x84, 0xb5, 0x37, 0x1e, 0x34, 0x27, 0x5a, 0x5d, 0xd5, 0xd1, 0x0f, 0xe8, - 0x00, 0xcc, 0xb4, 0x45, 0xa8, 0x74, 0xc1, 0xb7, 0x7d, 0x25, 0x2a, 0x2e, 0x49, 0x58, 0x2a, 0x09, 0xec, 0xec, 0xa6, - 0x64, 0x67, 0x13, 0x10, 0xcf, 0x70, 0xd7, 0xd3, 0x62, 0x27, 0xa4, 0x09, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, 0x55, - 0x97, 0x90, 0x8d, 0x31, 0x74, 0xf1, 0x2f, 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x09, 0x0a, 0x55, 0xee, 0xb6, - 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, 0x37, 0xea, 0x66, 0xd4, 0x54, 0x75, 0xea, 0x25, 0xf8, 0x38, 0xcd, 0xba, - 0x0a, 0x32, 0x0b, 0xbb, 0x2a, 0xd6, 0x3c, 0xd0, 0xb1, 0xba, 0x94, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x23, 0x63, - 0x6c, 0x61, 0x0d, 0x47, 0xda, 0x1e, 0x37, 0x3d, 0x41, 0xe8, 0x27, 0x6c, 0x28, 0x81, 0x9b, 0xce, 0xf6, 0xd4, 0x34, - 0xf3, 0x01, 0x11, 0x87, 0x01, 0x05, 0x92, 0x8d, 0x43, 0x9a, 0x23, 0x7d, 0x41, 0xd2, 0x84, 0x81, 0xb2, 0x15, 0xcf, - 0x09, 0xb2, 0xa2, 0xd0, 0xb3, 0x75, 0x55, 0x43, 0xfc, 0x5c, 0x86, 0x39, 0x5a, 0x72, 0x2a, 0x3c, 0x4d, 0x90, 0x89, - 0xed, 0x69, 0x9b, 0x99, 0x0c, 0x47, 0xc9, 0x02, 0xf3, 0x2b, 0x88, 0x12, 0x77, 0xa6, 0x59, 0x95, 0x83, 0x71, 0x01, - 0x0b, 0xb4, 0xf2, 0x3d, 0xa8, 0x1b, 0x6b, 0x68, 0xa3, 0x61, 0x99, 0xdd, 0xfe, 0x04, 0xfb, 0xb5, 0x76, 0x5a, 0x97, - 0x29, 0x96, 0x97, 0x29, 0x44, 0x7b, 0x21, 0xf3, 0x1b, 0x45, 0xa2, 0x3b, 0x45, 0x18, 0x12, 0xd6, 0x51, 0xf6, 0xa4, - 0x4d, 0x0d, 0xa0, 0xa7, 0x5e, 0x00, 0xf8, 0xce, 0xb5, 0x0c, 0xbb, 0x48, 0xf7, 0x57, 0x05, 0xe3, 0xd2, 0x0d, 0x82, - 0x14, 0xbd, 0x49, 0xc1, 0x9c, 0xd7, 0xa3, 0xa4, 0xde, 0x9c, 0xb6, 0xcc, 0xa8, 0x3a, 0x2a, 0x42, 0xca, 0x09, 0xfe, - 0x93, 0x57, 0x52, 0x13, 0x9b, 0x30, 0xc1, 0x03, 0x1f, 0xe6, 0x19, 0x36, 0xf0, 0x76, 0xfb, 0x36, 0x0d, 0x93, 0x36, - 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0x09, 0x81, 0xca, 0x5e, 0xe2, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, 0x1b, - 0x0d, 0x4c, 0xdc, 0xea, 0xca, 0xd6, 0x61, 0x42, 0xc3, 0x25, 0xd5, 0xce, 0x4e, 0x2a, 0xf9, 0xa2, 0xbd, 0x2e, 0x2f, - 0x6c, 0x1f, 0x74, 0x2c, 0xb5, 0xae, 0xe1, 0x81, 0xe6, 0x35, 0xbb, 0xb8, 0x62, 0x9a, 0x26, 0x1a, 0xeb, 0x21, 0x65, - 0xc9, 0xb1, 0xae, 0xa7, 0x2b, 0x5c, 0x2d, 0x33, 0x0d, 0x74, 0x2f, 0xf1, 0x42, 0x0f, 0xf8, 0xe0, 0xe1, 0x8a, 0x44, - 0x17, 0xd8, 0x6c, 0xb6, 0xaa, 0xc9, 0x34, 0xdf, 0x97, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, - 0x69, 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, - 0xe8, 0xde, 0xf9, 0x22, 0x75, 0xf3, 0x0b, 0xb0, 0x8d, 0xda, 0x18, 0xd3, 0x2c, 0xb1, 0x0e, 0x13, 0x65, 0x61, 0x8d, - 0x2c, 0xe4, 0x12, 0x7c, 0x30, 0x77, 0x9b, 0x3a, 0x7d, 0xde, 0x41, 0x84, 0xfd, 0x2e, 0x7a, 0x3c, 0xc2, 0x58, 0xb1, - 0x06, 0x89, 0x61, 0x15, 0xd6, 0xb4, 0xb9, 0x1c, 0xa2, 0x9c, 0x9a, 0x25, 0x13, 0x2d, 0xa9, 0x4f, 0x29, 0xa2, 0x14, - 0xcc, 0x8d, 0xa7, 0x65, 0xc3, 0x94, 0x10, 0x21, 0x2b, 0xa4, 0x03, 0xaa, 0xb5, 0xd0, 0x52, 0x4d, 0x10, 0xf0, 0xd0, - 0xcb, 0x42, 0x63, 0x0a, 0xa2, 0x8f, 0xc8, 0x70, 0x23, 0x8e, 0x8c, 0xee, 0x8e, 0x51, 0x4c, 0x20, 0x74, 0xb7, 0x97, - 0x17, 0x56, 0x9f, 0x96, 0x6d, 0x75, 0x10, 0xd7, 0x98, 0x26, 0x7b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, - 0x67, 0x11, 0xfa, 0x76, 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0x48, 0xeb, 0x35, 0x15, 0x03, 0xd4, 0xce, 0x63, 0x17, - 0xb1, 0x4a, 0x77, 0x0b, 0x51, 0xde, 0xa8, 0xac, 0xdf, 0xaf, 0x43, 0xb2, 0xdd, 0x62, 0x59, 0xe0, 0xcb, 0xfe, 0x6a, - 0xbd, 0x07, 0x02, 0xfd, 0xe9, 0xfa, 0xb3, 0x10, 0xe8, 0xcf, 0xb2, 0x2f, 0x81, 0x40, 0x7f, 0xba, 0xfe, 0x9f, 0x86, - 0x40, 0x7f, 0xb5, 0xf6, 0x20, 0xd0, 0xd5, 0x60, 0xfc, 0xa3, 0x60, 0xc1, 0x9b, 0xd7, 0x01, 0x7d, 0x26, 0x59, 0xf0, - 0xe6, 0xc5, 0x0b, 0x4f, 0x98, 0xfe, 0x83, 0xd0, 0x48, 0xfe, 0x46, 0x16, 0x8c, 0xb8, 0x2d, 0xf0, 0x0a, 0xb5, 0x4e, - 0x3e, 0x50, 0x51, 0x06, 0x40, 0xf4, 0xe5, 0x6f, 0x59, 0xb5, 0x0c, 0x83, 0xc3, 0x80, 0xcc, 0x1c, 0x24, 0xe8, 0x70, - 0xd2, 0xb8, 0xbd, 0xfd, 0x22, 0x1a, 0x42, 0x1d, 0x1b, 0x79, 0x00, 0xbe, 0xf2, 0x44, 0xf6, 0xfe, 0x0d, 0x11, 0x3f, - 0x99, 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x0f, 0xd6, 0x9e, - 0x6d, 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, - 0xe5, 0xbf, 0xbc, 0x7b, 0x69, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, - 0xfe, 0x78, 0xb0, 0xe9, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x93, - 0xd5, 0x87, 0x0f, 0x36, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x53, 0xc2, 0x0f, 0x5e, 0xff, - 0xe1, 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, - 0xa8, 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, - 0x9d, 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, - 0x2e, 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xbb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, - 0x79, 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0x7c, 0xff, 0x45, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, - 0x2e, 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, - 0x95, 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0xc9, 0x84, - 0x5d, 0x5e, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc6, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, - 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x0a, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x41, 0x9d, 0x95, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x7b, 0x7f, 0x1a, 0xb9, 0xb2, 0x28, 0xfa, + 0xf7, 0x3d, 0x9f, 0xc2, 0xee, 0x9d, 0xf1, 0xb4, 0x8c, 0x68, 0x03, 0x36, 0x8e, 0xd3, 0x58, 0xe6, 0xe4, 0x39, 0xc9, + 0x3c, 0x92, 0x4c, 0x9c, 0x64, 0x26, 0xc3, 0xb0, 0x33, 0xa2, 0x11, 0xa0, 0xa4, 0x91, 0x98, 0x96, 0x88, 0xed, 0x01, + 0xbe, 0xfb, 0xfd, 0x95, 0x1e, 0xdd, 0x6a, 0x20, 0x59, 0x6b, 0x9d, 0x7b, 0xce, 0xfd, 0x9d, 0x3d, 0x7b, 0xc5, 0xb4, + 0xde, 0x2a, 0x95, 0x4a, 0x55, 0xa5, 0xaa, 0xd2, 0xe5, 0xe1, 0x58, 0x66, 0xfa, 0x6e, 0xc1, 0x0e, 0x66, 0x7a, 0x9e, + 0x5f, 0x5d, 0xba, 0x7f, 0x19, 0x1d, 0x5f, 0x5d, 0xe6, 0x5c, 0x7c, 0x3e, 0x28, 0x58, 0x4e, 0x78, 0x26, 0xc5, 0xc1, + 0xac, 0x60, 0x13, 0x32, 0xa6, 0x9a, 0xa6, 0x7c, 0x4e, 0xa7, 0xec, 0xe0, 0xe4, 0xea, 0x72, 0xce, 0x34, 0x3d, 0xc8, + 0x66, 0xb4, 0x50, 0x4c, 0x93, 0x77, 0x6f, 0x9f, 0x35, 0x2f, 0xae, 0x2e, 0x55, 0x56, 0xf0, 0x85, 0x3e, 0x80, 0x26, + 0xc9, 0x5c, 0x8e, 0x97, 0x39, 0xbb, 0x3a, 0x39, 0xb9, 0xb9, 0xb9, 0x49, 0x3e, 0xa9, 0xff, 0xf1, 0x85, 0x16, 0x07, + 0xbf, 0x16, 0xe4, 0xd5, 0xe8, 0x13, 0xcb, 0x74, 0x32, 0x66, 0x13, 0x2e, 0xd8, 0xeb, 0x42, 0x2e, 0x58, 0xa1, 0xef, + 0x7a, 0x90, 0xf9, 0x47, 0x41, 0x62, 0x8e, 0x35, 0x66, 0x88, 0x5c, 0xe9, 0x03, 0x2e, 0x0e, 0x78, 0xff, 0xd7, 0xc2, + 0xa4, 0xac, 0x98, 0x58, 0xce, 0x59, 0x41, 0x47, 0x39, 0x4b, 0x0f, 0x5b, 0x38, 0x93, 0x62, 0xc2, 0xa7, 0xcb, 0xf2, + 0xfb, 0xa6, 0xe0, 0xda, 0xff, 0xfe, 0x42, 0xf3, 0x25, 0x4b, 0xd9, 0x06, 0xa5, 0x7c, 0xa0, 0x87, 0x84, 0x99, 0x96, + 0x3f, 0x57, 0x0d, 0xc7, 0x7f, 0x98, 0x26, 0xef, 0x16, 0x4c, 0x4e, 0x0e, 0xf4, 0x21, 0x89, 0xd4, 0xdd, 0x7c, 0x24, + 0xf3, 0xa8, 0xaf, 0x1b, 0x51, 0x94, 0x42, 0x19, 0xcc, 0x50, 0x2f, 0x93, 0x42, 0xe9, 0x03, 0xc1, 0xc9, 0x0d, 0x17, + 0x63, 0x79, 0x83, 0x3f, 0x0b, 0x22, 0x78, 0x72, 0x3d, 0xa3, 0x63, 0x79, 0xf3, 0x46, 0x4a, 0x7d, 0x74, 0x14, 0xbb, + 0xef, 0xbb, 0xc7, 0xd7, 0xd7, 0x84, 0x90, 0x2f, 0x92, 0x8f, 0x0f, 0x5a, 0xeb, 0x75, 0x90, 0x9a, 0x08, 0xaa, 0xf9, + 0x17, 0x66, 0x2b, 0xa1, 0xa3, 0xa3, 0x88, 0x8e, 0xe5, 0x42, 0xb3, 0xf1, 0xb5, 0xbe, 0xcb, 0xd9, 0xf5, 0x8c, 0x31, + 0xad, 0x22, 0x2e, 0x0e, 0x9e, 0xc8, 0x6c, 0x39, 0x67, 0x42, 0x27, 0x8b, 0x42, 0x6a, 0x09, 0x03, 0x3b, 0x3a, 0x8a, + 0x0a, 0xb6, 0xc8, 0x69, 0xc6, 0x20, 0xff, 0xf1, 0xf5, 0x75, 0x55, 0xa3, 0x2a, 0x84, 0xaf, 0x05, 0xb9, 0x36, 0x43, + 0x8f, 0x11, 0xfe, 0x4d, 0x10, 0xc1, 0x6e, 0x0e, 0x7e, 0x63, 0xf4, 0xf3, 0x2f, 0x74, 0xd1, 0xcb, 0x72, 0xaa, 0xd4, + 0xc1, 0x4b, 0xb9, 0x32, 0xd3, 0x28, 0x96, 0x99, 0x96, 0x45, 0xac, 0x31, 0xc3, 0x02, 0xad, 0xf8, 0x24, 0xd6, 0x33, + 0xae, 0x92, 0x8f, 0xf7, 0x32, 0xa5, 0xde, 0x30, 0xb5, 0xcc, 0xf5, 0x3d, 0x72, 0xd8, 0xc2, 0xe2, 0x90, 0x90, 0x6b, + 0x81, 0xf4, 0xac, 0x90, 0x37, 0x07, 0x4f, 0x8b, 0x42, 0x16, 0x71, 0xf4, 0xf8, 0xfa, 0xda, 0x96, 0x38, 0xe0, 0xea, + 0x40, 0x48, 0x7d, 0x50, 0xb6, 0x07, 0xd0, 0x4e, 0x0e, 0xde, 0x29, 0x76, 0xf0, 0xd7, 0x52, 0x28, 0x3a, 0x61, 0x8f, + 0xaf, 0xaf, 0xff, 0x3a, 0x90, 0xc5, 0xc1, 0x5f, 0x99, 0x52, 0x7f, 0x1d, 0x70, 0xa1, 0x34, 0xa3, 0xe3, 0x24, 0x42, + 0x3d, 0xd3, 0x59, 0xa6, 0xd4, 0x5b, 0x76, 0xab, 0x89, 0xc6, 0xe6, 0x53, 0x13, 0xb6, 0x99, 0x32, 0x7d, 0xa0, 0xca, + 0x79, 0xc5, 0x68, 0x95, 0x33, 0x7d, 0xa0, 0x89, 0xc9, 0x97, 0x0e, 0xfe, 0xcc, 0x7e, 0xea, 0x1e, 0x9f, 0xc4, 0x9f, + 0xc5, 0xd1, 0x91, 0x2e, 0x01, 0x8d, 0x56, 0x6e, 0x85, 0x08, 0x3b, 0xf4, 0x69, 0x47, 0x47, 0x2c, 0xc9, 0x99, 0x98, + 0xea, 0x19, 0x21, 0xa4, 0xdd, 0x13, 0x47, 0x47, 0xb1, 0x26, 0xbf, 0x89, 0x64, 0xca, 0x74, 0xcc, 0x10, 0xc2, 0x55, + 0xed, 0xa3, 0xa3, 0xd8, 0x02, 0x41, 0x12, 0x6d, 0x00, 0x57, 0x83, 0x31, 0x4a, 0x1c, 0xf4, 0xaf, 0xef, 0x44, 0x16, + 0x87, 0xe3, 0x47, 0x58, 0x1c, 0x1d, 0xfd, 0x26, 0x12, 0x05, 0x2d, 0x62, 0x8d, 0xd0, 0xa6, 0x60, 0x7a, 0x59, 0x88, + 0x03, 0xbd, 0xd1, 0xf2, 0x5a, 0x17, 0x5c, 0x4c, 0x63, 0xb4, 0xf2, 0x69, 0x41, 0xc5, 0xcd, 0xc6, 0x0e, 0xf7, 0xc7, + 0x82, 0x70, 0x72, 0x05, 0x3d, 0xbe, 0x94, 0xb1, 0xc3, 0x41, 0x4e, 0x48, 0xa4, 0x4c, 0xdd, 0xa8, 0xcf, 0x53, 0xde, + 0x88, 0x22, 0x6c, 0x47, 0x89, 0xaf, 0x05, 0xc2, 0x42, 0x03, 0xea, 0x26, 0x49, 0xa2, 0x11, 0xb9, 0x5a, 0x79, 0xb0, + 0xf0, 0x60, 0xa2, 0x7d, 0x3e, 0x68, 0x0d, 0x53, 0x9d, 0x14, 0x6c, 0xbc, 0xcc, 0x58, 0x1c, 0x0b, 0xac, 0xb0, 0x44, + 0xe4, 0x4a, 0x34, 0xe2, 0x82, 0x5c, 0xc1, 0x7a, 0x17, 0xf5, 0xc5, 0x26, 0xe4, 0xb0, 0x85, 0xdc, 0x20, 0x0b, 0x3f, + 0x42, 0x00, 0xb1, 0x1b, 0x50, 0x41, 0x48, 0x24, 0x96, 0xf3, 0x11, 0x2b, 0xa2, 0xb2, 0x58, 0xaf, 0x86, 0x17, 0x4b, + 0xc5, 0x0e, 0x32, 0xa5, 0x0e, 0x26, 0x4b, 0x91, 0x69, 0x2e, 0xc5, 0x41, 0xd4, 0x28, 0x1a, 0x91, 0xc5, 0x87, 0x12, + 0x1d, 0x22, 0xb4, 0x41, 0xb1, 0x42, 0x0d, 0x3e, 0x90, 0x8d, 0xf6, 0x10, 0xc3, 0x28, 0x51, 0xcf, 0xb5, 0xe7, 0x20, + 0xc0, 0x30, 0x87, 0x49, 0x6e, 0xb0, 0xa6, 0x66, 0x83, 0xc2, 0x14, 0x3f, 0x8b, 0x3e, 0x4f, 0x76, 0x77, 0x0a, 0xd1, + 0xc9, 0x9c, 0x2e, 0x62, 0x46, 0xae, 0x98, 0xc1, 0x2e, 0x2a, 0x32, 0x18, 0x6b, 0x6d, 0xe1, 0xfa, 0x2c, 0x65, 0x49, + 0x85, 0x53, 0x28, 0xd5, 0xc9, 0x44, 0x16, 0x4f, 0x69, 0x36, 0x83, 0x7a, 0x25, 0xc6, 0x8c, 0xfd, 0x86, 0xcb, 0x0a, + 0x46, 0x35, 0x7b, 0x9a, 0x33, 0xf8, 0x8a, 0x23, 0x53, 0x33, 0x42, 0x58, 0xc1, 0x56, 0xcf, 0xb9, 0x7e, 0x29, 0x45, + 0xc6, 0x7a, 0x2a, 0xc0, 0x2f, 0xb3, 0xf2, 0x0f, 0xb5, 0x2e, 0xf8, 0x68, 0xa9, 0x59, 0x1c, 0x09, 0x28, 0x11, 0x61, + 0x85, 0xb0, 0x48, 0x34, 0xbb, 0xd5, 0x8f, 0xa5, 0xd0, 0x4c, 0x68, 0xc2, 0x3c, 0x54, 0x31, 0x4f, 0xe8, 0x62, 0xc1, + 0xc4, 0xf8, 0xf1, 0x8c, 0xe7, 0xe3, 0x58, 0xa0, 0x0d, 0xda, 0xe0, 0x0f, 0x82, 0xc0, 0x24, 0xc9, 0x15, 0x4f, 0xe1, + 0x9f, 0xaf, 0x4f, 0x27, 0xd6, 0xe4, 0xca, 0x6c, 0x0b, 0x46, 0xa2, 0xa8, 0x37, 0x91, 0x45, 0xec, 0xa6, 0x70, 0x00, + 0xa4, 0x0b, 0xfa, 0x78, 0xb3, 0xcc, 0x99, 0x42, 0xac, 0x41, 0x44, 0xb9, 0x8e, 0x0e, 0xc2, 0x3f, 0x16, 0x31, 0x83, + 0x05, 0xe0, 0x28, 0xe5, 0x86, 0x04, 0xbe, 0xe1, 0x6e, 0x53, 0x8d, 0x4b, 0xa2, 0xf6, 0xb7, 0x20, 0x63, 0x9e, 0xe8, + 0x62, 0xa9, 0x34, 0x1b, 0xbf, 0xbd, 0x5b, 0x30, 0x85, 0x19, 0x25, 0x7f, 0x8b, 0xfe, 0xdf, 0x22, 0x61, 0xf3, 0x85, + 0xbe, 0xbb, 0x36, 0xd4, 0x3c, 0x8d, 0x22, 0xfc, 0xbb, 0x29, 0x5a, 0x30, 0x9a, 0x01, 0x49, 0x73, 0x20, 0x7b, 0x2d, + 0xf3, 0xbb, 0x09, 0xcf, 0xf3, 0xeb, 0xe5, 0x62, 0x21, 0x0b, 0x8d, 0x99, 0x20, 0x2b, 0x2d, 0x2b, 0xf8, 0xc0, 0x8a, + 0xae, 0xd4, 0x0d, 0xd7, 0xd9, 0x2c, 0xd6, 0x68, 0x95, 0x51, 0xc5, 0x0e, 0x1e, 0x49, 0x99, 0x33, 0x2a, 0x52, 0x4e, + 0x78, 0x9f, 0xd1, 0x54, 0x2c, 0xf3, 0xbc, 0x37, 0x2a, 0x18, 0xfd, 0xdc, 0x33, 0xd9, 0xf6, 0x70, 0x48, 0xcd, 0xef, + 0x87, 0x45, 0x41, 0xef, 0xa0, 0x20, 0x21, 0x50, 0xac, 0xcf, 0xd3, 0x1f, 0xaf, 0x5f, 0xbd, 0x4c, 0xec, 0x5e, 0xe1, + 0x93, 0xbb, 0x98, 0x97, 0xfb, 0x8f, 0x6f, 0xf0, 0xa4, 0x90, 0xf3, 0xad, 0xae, 0x2d, 0xe8, 0x78, 0xef, 0x2b, 0x43, + 0x60, 0x84, 0x1f, 0xda, 0xa6, 0xc3, 0x11, 0xbc, 0x34, 0x98, 0x0f, 0x99, 0xc4, 0xf5, 0x0b, 0xff, 0xa4, 0x36, 0x39, + 0xe6, 0xe8, 0xdb, 0xa3, 0xd5, 0xc5, 0xdd, 0x8a, 0x11, 0x33, 0xce, 0x05, 0x1c, 0x8c, 0x30, 0xc6, 0x8c, 0xea, 0x6c, + 0xb6, 0x62, 0xa6, 0xb1, 0x8d, 0x1f, 0x31, 0xdb, 0x6c, 0xf0, 0x3f, 0xd2, 0x63, 0xbd, 0x3e, 0x24, 0x84, 0x1b, 0x7a, + 0x45, 0xf4, 0x7a, 0xcd, 0x09, 0xe1, 0x08, 0x3f, 0xe3, 0x64, 0x45, 0xfd, 0x84, 0xe0, 0x64, 0x83, 0xed, 0x99, 0x5a, + 0x2a, 0x03, 0x27, 0xe0, 0x17, 0x56, 0x68, 0x18, 0xa8, 0xc0, 0x05, 0x9b, 0xe4, 0x30, 0x8e, 0xc3, 0x36, 0x9e, 0x51, + 0xf5, 0x78, 0x46, 0xc5, 0x94, 0x8d, 0xd3, 0x7f, 0xe4, 0x06, 0x0b, 0x41, 0xa2, 0x09, 0x17, 0x34, 0xe7, 0xff, 0xb0, + 0x71, 0xe4, 0xce, 0x85, 0xf7, 0xfa, 0x80, 0xdd, 0x6a, 0x26, 0xc6, 0xea, 0xe0, 0xf9, 0xdb, 0x5f, 0x7e, 0x76, 0x8b, + 0x59, 0x3b, 0x2b, 0xd0, 0x4a, 0x2d, 0x17, 0xac, 0x88, 0x11, 0x76, 0x67, 0xc5, 0x53, 0x6e, 0xe8, 0xe4, 0x2f, 0x74, + 0x61, 0x53, 0xb8, 0x7a, 0xb7, 0x18, 0x53, 0xcd, 0x5e, 0x33, 0x31, 0xe6, 0x62, 0x4a, 0x0e, 0xdb, 0x36, 0x7d, 0x46, + 0x5d, 0xc6, 0xb8, 0x4c, 0xfa, 0x78, 0xef, 0x69, 0x6e, 0xe6, 0x5e, 0x7e, 0x2e, 0x63, 0xb4, 0x51, 0x9a, 0x6a, 0x9e, + 0x1d, 0xd0, 0xf1, 0xf8, 0x85, 0xe0, 0x9a, 0x9b, 0x11, 0x16, 0xb0, 0x44, 0x80, 0xab, 0xcc, 0x9e, 0x1a, 0x7e, 0xe4, + 0x31, 0xc2, 0x71, 0xec, 0xce, 0x82, 0x19, 0x72, 0x6b, 0x76, 0x74, 0x54, 0x51, 0xfe, 0x3e, 0x4b, 0x6d, 0x26, 0x19, + 0x0c, 0x51, 0xb2, 0x58, 0x2a, 0x58, 0x6c, 0xdf, 0x05, 0x1c, 0x34, 0x72, 0xa4, 0x58, 0xf1, 0x85, 0x8d, 0x4b, 0x04, + 0x51, 0x31, 0x5a, 0x6d, 0xf5, 0xe1, 0xb6, 0x87, 0x26, 0x83, 0x61, 0x2f, 0x24, 0xe1, 0xcc, 0x21, 0xbb, 0xe5, 0x54, + 0x38, 0x53, 0x25, 0x51, 0x89, 0xe1, 0x40, 0x2d, 0x09, 0x8b, 0x22, 0x7e, 0x7e, 0x8b, 0x58, 0x00, 0x0f, 0x11, 0x52, + 0x0e, 0x7f, 0xe6, 0x3e, 0xfd, 0x62, 0x0e, 0x0f, 0x85, 0x05, 0xc2, 0xda, 0x8e, 0x54, 0x21, 0xb4, 0x41, 0x58, 0xfb, + 0xe1, 0x5a, 0xa2, 0xe4, 0xf9, 0x22, 0x38, 0xb5, 0xc9, 0x33, 0x6e, 0x8e, 0x6d, 0xa0, 0x6d, 0x54, 0xb3, 0xa3, 0xa3, + 0x98, 0x25, 0x25, 0x62, 0x90, 0xc3, 0xb6, 0x5b, 0xa4, 0x00, 0x5a, 0x5f, 0x19, 0x37, 0xf4, 0x6c, 0x18, 0x9c, 0x43, + 0x96, 0x08, 0xf9, 0x30, 0xcb, 0x98, 0x52, 0xb2, 0x38, 0x3a, 0x3a, 0x34, 0xe5, 0x4b, 0xce, 0x02, 0x16, 0xf1, 0xd5, + 0x8d, 0xa8, 0x86, 0x80, 0xaa, 0xd3, 0xd6, 0xf3, 0x4d, 0xa4, 0xe2, 0x9b, 0x3c, 0x13, 0x92, 0x46, 0x1f, 0x3f, 0x46, + 0x0d, 0x8d, 0x1d, 0x1c, 0xa6, 0xcc, 0x77, 0x7d, 0xf7, 0x84, 0x59, 0xb6, 0xd0, 0x30, 0x21, 0x3b, 0xa0, 0xd9, 0xcb, + 0x0f, 0xc6, 0xf5, 0x21, 0x61, 0x8d, 0x15, 0xda, 0x04, 0x2b, 0xba, 0xb7, 0x69, 0xc3, 0xdf, 0xd8, 0xa5, 0x5b, 0x4d, + 0x0d, 0x4f, 0x11, 0xac, 0xe3, 0x80, 0x0d, 0x37, 0xd8, 0xc0, 0xde, 0xcf, 0x46, 0x9a, 0x81, 0x0e, 0xf4, 0xb0, 0xe7, + 0xf2, 0x89, 0xb2, 0x90, 0x2b, 0xd8, 0xdf, 0x4b, 0xa6, 0xb4, 0x45, 0xe4, 0x58, 0x63, 0x89, 0xe1, 0x8c, 0xda, 0x66, + 0x3a, 0x6b, 0x2c, 0xe9, 0xbe, 0xb1, 0xbd, 0x5a, 0xc0, 0xd9, 0xa8, 0x00, 0xa9, 0xbf, 0x8d, 0x4f, 0x30, 0x56, 0x8d, + 0xd6, 0xeb, 0x67, 0xdc, 0xb7, 0x52, 0xad, 0x65, 0xc9, 0xaf, 0x6d, 0x2d, 0x8a, 0x10, 0xc8, 0x1d, 0xce, 0x87, 0x6d, + 0x3b, 0x7e, 0x21, 0x86, 0xe4, 0xb0, 0x55, 0x62, 0xb1, 0x03, 0xab, 0x1d, 0x8f, 0x85, 0xe2, 0x2b, 0xdb, 0x14, 0x32, + 0x67, 0x7d, 0x0d, 0x5f, 0x92, 0xd9, 0x0e, 0xae, 0xce, 0xc8, 0x00, 0xb8, 0x8e, 0x64, 0x36, 0xfc, 0x1a, 0x3e, 0x79, + 0x8a, 0x10, 0xeb, 0xdd, 0xbc, 0x8a, 0x70, 0x7c, 0xa9, 0x13, 0x8e, 0xad, 0x69, 0x44, 0x8b, 0xb2, 0x4a, 0x54, 0xa2, + 0x99, 0xdb, 0xea, 0x55, 0x16, 0x16, 0x66, 0x30, 0xd5, 0x94, 0x82, 0x26, 0x5e, 0xd2, 0x39, 0x53, 0x31, 0x43, 0xf8, + 0x6b, 0x05, 0x2c, 0x7e, 0x42, 0x91, 0x61, 0x70, 0x86, 0x2a, 0x38, 0x43, 0x81, 0xdd, 0x05, 0x26, 0xad, 0xbe, 0xe5, + 0x14, 0x66, 0x03, 0x35, 0xac, 0x78, 0xbb, 0x60, 0xf2, 0xe6, 0x70, 0x76, 0x08, 0xee, 0xe1, 0x67, 0xd3, 0x2c, 0xd0, + 0x0c, 0x0b, 0xa1, 0x10, 0x3e, 0x6c, 0x6d, 0xaf, 0xa4, 0x2f, 0x55, 0xcd, 0x71, 0x30, 0x84, 0x75, 0x30, 0xc7, 0x46, + 0xc2, 0x95, 0xf9, 0x5b, 0xdb, 0x6a, 0x00, 0xb6, 0x6b, 0xc0, 0x8c, 0x64, 0x92, 0x53, 0x1d, 0xb7, 0x4f, 0x5a, 0xc0, + 0x98, 0x7e, 0x61, 0x70, 0xaa, 0x20, 0xb4, 0x3b, 0x15, 0x96, 0x2c, 0x85, 0x9a, 0xf1, 0x89, 0x8e, 0x3f, 0x08, 0x43, + 0x54, 0x58, 0xae, 0x18, 0x48, 0x38, 0x01, 0x7b, 0x6c, 0x08, 0xce, 0x07, 0x01, 0xfd, 0xf4, 0xca, 0x83, 0xc8, 0x8d, + 0xd4, 0x10, 0x2e, 0x20, 0x0f, 0x15, 0x6b, 0x5d, 0x91, 0x99, 0x92, 0x71, 0x03, 0xee, 0xb1, 0xdd, 0xb7, 0x2d, 0xa6, + 0x8e, 0x1a, 0x88, 0x80, 0x83, 0x15, 0x69, 0x48, 0x22, 0x5c, 0xa2, 0x4e, 0xb4, 0xfc, 0x59, 0xde, 0xb0, 0xe2, 0x31, + 0x85, 0xc1, 0xa7, 0xb6, 0xfa, 0xc6, 0x1e, 0x05, 0x86, 0xe2, 0xeb, 0x9e, 0xc7, 0x97, 0x8f, 0x66, 0xe2, 0xaf, 0x0b, + 0x39, 0xe7, 0x8a, 0x01, 0xdf, 0x66, 0xe1, 0x2f, 0x60, 0xa3, 0x99, 0x1d, 0x09, 0xc7, 0x0d, 0x2b, 0xf1, 0xeb, 0xe1, + 0xcf, 0x75, 0xfc, 0xfa, 0x78, 0xef, 0xe9, 0xd4, 0x53, 0xc0, 0xfa, 0x3e, 0x46, 0x38, 0x76, 0xe2, 0x45, 0x70, 0xd2, + 0x25, 0x33, 0xe4, 0x8e, 0xf9, 0xf5, 0x5a, 0x07, 0x62, 0x5c, 0x8d, 0x73, 0x64, 0x76, 0xdb, 0xa0, 0x0d, 0x1d, 0x8f, + 0x81, 0xc5, 0x2b, 0x64, 0x9e, 0x07, 0x87, 0x15, 0x16, 0xbd, 0xf2, 0x78, 0xfa, 0x78, 0xef, 0xe9, 0xf5, 0xb7, 0x4e, + 0x28, 0xc8, 0x0f, 0x0f, 0x29, 0x3f, 0x50, 0x31, 0x66, 0x05, 0xc8, 0x95, 0xc1, 0x6a, 0xb9, 0x73, 0xf6, 0xb1, 0x14, + 0x82, 0x65, 0x9a, 0x8d, 0x41, 0x68, 0x11, 0x44, 0x27, 0x33, 0xa9, 0x74, 0x99, 0x58, 0x8d, 0x5e, 0x84, 0x42, 0x68, + 0x92, 0xd1, 0x3c, 0x8f, 0xad, 0x80, 0x32, 0x97, 0x5f, 0xd8, 0x9e, 0x51, 0xf7, 0x6a, 0x43, 0x2e, 0x9b, 0x61, 0x41, + 0x33, 0x2c, 0x51, 0x8b, 0x9c, 0x67, 0xac, 0x3c, 0xbc, 0xae, 0x13, 0x2e, 0xc6, 0xec, 0x16, 0xe8, 0x08, 0xba, 0xba, + 0xba, 0x6a, 0xe1, 0x36, 0xda, 0x58, 0x80, 0xaf, 0x76, 0x00, 0xfb, 0x8d, 0x63, 0xd3, 0x0a, 0xe2, 0xab, 0x7d, 0xf4, + 0x80, 0xa1, 0xe0, 0xac, 0xe4, 0x5e, 0xd0, 0xb2, 0xe4, 0x19, 0xe1, 0x31, 0xcb, 0x99, 0x66, 0x9e, 0x9c, 0x03, 0x33, + 0x6d, 0xb7, 0xee, 0x9b, 0x12, 0x7e, 0x25, 0x3a, 0xf9, 0x5d, 0xe6, 0xd7, 0x5c, 0x95, 0xa2, 0x7b, 0xb5, 0x3c, 0x15, + 0xb4, 0xfb, 0xda, 0x2e, 0x0f, 0xd5, 0x9a, 0x66, 0x33, 0x2b, 0xb1, 0xc7, 0x3b, 0x53, 0xaa, 0xda, 0x70, 0xa4, 0xbd, + 0xdc, 0x44, 0x9a, 0xba, 0x61, 0xee, 0x03, 0xc1, 0xb5, 0x23, 0x0a, 0x0c, 0x84, 0x40, 0xbb, 0x6c, 0x8f, 0x69, 0x9e, + 0x8f, 0x68, 0xf6, 0xb9, 0x8e, 0xfd, 0x15, 0x1a, 0x90, 0x6d, 0x6a, 0x1c, 0x64, 0x05, 0x24, 0x2b, 0x9c, 0xb7, 0xa7, + 0xd2, 0xb5, 0x8d, 0x12, 0x1f, 0xb6, 0x2a, 0xb4, 0xaf, 0x2f, 0xf4, 0x57, 0xb1, 0xdd, 0x8c, 0x48, 0xb8, 0x99, 0xc5, + 0x40, 0x05, 0xfe, 0x25, 0xc6, 0x79, 0x7a, 0xe0, 0xf0, 0x0e, 0x04, 0x8f, 0xcd, 0xd6, 0x40, 0x34, 0x5a, 0x6d, 0xc6, + 0x5c, 0x7d, 0x1d, 0x02, 0xff, 0x5b, 0x46, 0xf9, 0x24, 0xe8, 0xe1, 0xdf, 0x1d, 0x68, 0x49, 0xe3, 0x1c, 0xe3, 0x5c, + 0x8e, 0xcc, 0x31, 0x14, 0x9e, 0xd0, 0xfc, 0x04, 0xcc, 0x8b, 0xc1, 0xf7, 0x57, 0x36, 0xcb, 0xf0, 0x65, 0x30, 0x0c, + 0xd5, 0x0b, 0x19, 0x8a, 0x1a, 0x0a, 0x38, 0xa2, 0x2a, 0xcc, 0x99, 0x2b, 0x6b, 0xa2, 0xa4, 0xe3, 0xda, 0xad, 0x38, + 0xee, 0x68, 0x6e, 0x41, 0xe2, 0x38, 0x56, 0x20, 0xcd, 0x79, 0xfe, 0xbe, 0x9a, 0x85, 0xda, 0x99, 0x85, 0x4a, 0x02, + 0x69, 0x0b, 0x55, 0xc8, 0x1c, 0x54, 0x4f, 0x99, 0x40, 0x61, 0x29, 0x60, 0x59, 0x13, 0xa0, 0xd0, 0xa8, 0x24, 0xb8, + 0x39, 0xd1, 0xb8, 0x70, 0xa2, 0x8e, 0xc3, 0x35, 0x20, 0x19, 0x55, 0x15, 0x89, 0xec, 0xe6, 0xa8, 0xc9, 0xbe, 0x12, + 0x17, 0x68, 0x8b, 0xbf, 0xdf, 0x6c, 0x1c, 0x94, 0x18, 0x72, 0xab, 0x53, 0x63, 0x8c, 0x03, 0xb0, 0x60, 0x49, 0x1c, + 0x33, 0x6c, 0x59, 0x9f, 0x6d, 0xe0, 0x94, 0xed, 0x1e, 0x12, 0x22, 0x2b, 0xd8, 0xd4, 0x98, 0x4a, 0xcf, 0x5d, 0x49, + 0x84, 0xa9, 0x67, 0x4b, 0x8b, 0x6a, 0xe2, 0x84, 0x44, 0x5e, 0x3b, 0x11, 0xf5, 0x57, 0x35, 0xe1, 0x30, 0x0d, 0x8a, + 0x6d, 0x52, 0x20, 0xaa, 0xc5, 0x3e, 0x78, 0xef, 0xc3, 0x9a, 0x5a, 0x3b, 0x01, 0xc4, 0x8b, 0x1a, 0xc4, 0x03, 0xd0, + 0x4a, 0x4b, 0xbc, 0xe4, 0x90, 0xd0, 0x7a, 0xe5, 0x98, 0xe1, 0xc2, 0x2e, 0xc4, 0x0e, 0x14, 0xb7, 0xd9, 0x4f, 0x83, + 0x85, 0x20, 0xcb, 0x2a, 0xe0, 0xef, 0xc2, 0x23, 0x22, 0x86, 0xc1, 0x8b, 0xf5, 0x7a, 0x07, 0xed, 0xf6, 0x72, 0xa1, + 0x28, 0xa9, 0xa4, 0xc3, 0xf5, 0xfa, 0x1f, 0x89, 0x62, 0xc7, 0xff, 0x62, 0x86, 0xfa, 0x9e, 0xe8, 0x3e, 0xfc, 0x19, + 0x4a, 0x19, 0x76, 0xb4, 0x4a, 0x29, 0x05, 0x87, 0x3a, 0xd6, 0xd6, 0x17, 0x4a, 0x07, 0x94, 0xfb, 0xf1, 0x0e, 0x01, + 0x33, 0x89, 0xee, 0xa4, 0xae, 0xa6, 0xfc, 0xd8, 0x35, 0x2d, 0x10, 0x42, 0xa9, 0x32, 0xb2, 0xcc, 0xe1, 0x3e, 0xf9, + 0xf2, 0xe8, 0x48, 0x05, 0x0d, 0x7d, 0x2c, 0x29, 0xc5, 0xa7, 0x18, 0x4e, 0x65, 0x75, 0x27, 0x0c, 0xfb, 0xf2, 0xc9, + 0x9f, 0x43, 0x3b, 0xd2, 0x69, 0xab, 0x07, 0x82, 0x39, 0xbd, 0xa1, 0x5c, 0x1f, 0x94, 0xad, 0x58, 0xc1, 0x3c, 0x66, + 0x68, 0xe5, 0xb8, 0x8d, 0xa4, 0x60, 0xc0, 0x3f, 0x02, 0x59, 0xf0, 0x5c, 0xb4, 0x45, 0xfc, 0x6c, 0xc6, 0x40, 0x95, + 0xed, 0x19, 0x89, 0x92, 0xea, 0x1f, 0xba, 0x83, 0xc4, 0x35, 0xbc, 0x7f, 0xec, 0x9b, 0xed, 0xea, 0x35, 0x69, 0x60, + 0xc1, 0x8a, 0x89, 0x2c, 0xe6, 0x3e, 0x6f, 0xb3, 0xf5, 0xed, 0x88, 0x23, 0x9f, 0xc4, 0x7b, 0xdb, 0x76, 0x22, 0x40, + 0x6f, 0x4b, 0xf6, 0xae, 0xa4, 0xf6, 0xda, 0x69, 0x5a, 0x1e, 0xc0, 0x56, 0x41, 0xe8, 0x31, 0x53, 0x85, 0x52, 0xbe, + 0x53, 0xaf, 0xf6, 0xac, 0xee, 0xe4, 0xb0, 0xdd, 0x2b, 0x25, 0x3f, 0x8f, 0x0d, 0x3d, 0xab, 0xe3, 0x70, 0xa7, 0xaa, + 0x5c, 0xe6, 0x63, 0x37, 0x58, 0x81, 0x30, 0x73, 0x78, 0x74, 0xc3, 0xf3, 0xbc, 0x4a, 0xfd, 0x4f, 0x48, 0xbb, 0x72, + 0xa4, 0x5d, 0x7a, 0xd2, 0x0e, 0xa4, 0x02, 0x48, 0xbb, 0x6d, 0xae, 0xaa, 0x2e, 0x77, 0xb6, 0xa7, 0xb4, 0x44, 0x5d, + 0x19, 0x71, 0x1a, 0xfa, 0x5b, 0xfa, 0x11, 0xa0, 0x92, 0xf9, 0xfa, 0x1c, 0x3b, 0x7d, 0x0c, 0x88, 0x81, 0x56, 0xa7, + 0xc9, 0x42, 0x4d, 0xc5, 0xe7, 0x18, 0x61, 0xb5, 0x61, 0x25, 0x66, 0x3f, 0x7c, 0x0a, 0x4a, 0xbb, 0x60, 0x3a, 0x70, + 0x8e, 0x99, 0xe4, 0xff, 0x88, 0x8f, 0xf2, 0xb3, 0x13, 0x6e, 0x76, 0xca, 0xcf, 0x0e, 0x68, 0x7d, 0x35, 0xbb, 0xf1, + 0xb7, 0xa9, 0xbd, 0x99, 0x9e, 0x28, 0xa7, 0x57, 0xad, 0xf7, 0x7a, 0x1d, 0x6f, 0xa5, 0x80, 0x46, 0xdf, 0x49, 0x29, + 0x45, 0xd9, 0x3a, 0xd0, 0x80, 0x10, 0x32, 0x90, 0xb0, 0xb1, 0x93, 0x2e, 0x4f, 0xb9, 0x9f, 0xff, 0x95, 0x9e, 0xc7, + 0x28, 0xee, 0x6d, 0xfd, 0xc7, 0x72, 0xbe, 0x00, 0x86, 0x6c, 0x0b, 0xa5, 0xa7, 0xcc, 0x75, 0x58, 0xe5, 0x6f, 0xf6, + 0xa4, 0xd5, 0xea, 0x98, 0xfd, 0x58, 0xc3, 0xa6, 0x52, 0x6a, 0x3e, 0x6c, 0x6d, 0x96, 0x65, 0x52, 0x49, 0x38, 0xf6, + 0xe9, 0x56, 0x1e, 0x6f, 0x6b, 0x66, 0x7c, 0xc6, 0xab, 0x58, 0x58, 0x3a, 0x2c, 0x80, 0xd6, 0x05, 0xe4, 0xc7, 0xa3, + 0x7b, 0xb8, 0xfe, 0x9b, 0x0a, 0x38, 0xab, 0xcd, 0x16, 0xf8, 0x56, 0x9b, 0xcd, 0x7b, 0xed, 0x24, 0x6d, 0xfc, 0x7e, + 0x8f, 0xdc, 0x5b, 0x42, 0xaf, 0xca, 0x74, 0x32, 0xe3, 0x60, 0x08, 0x69, 0x3b, 0x2c, 0x24, 0x59, 0xcd, 0xe5, 0x98, + 0xa5, 0x91, 0x5c, 0x30, 0x11, 0x6d, 0x40, 0xcf, 0xea, 0x10, 0xe0, 0x77, 0x11, 0xaf, 0xde, 0xd4, 0xf5, 0xad, 0xe9, + 0x7b, 0xbd, 0x01, 0x55, 0xd8, 0x1b, 0xbe, 0x47, 0x19, 0xfb, 0x9e, 0x15, 0xca, 0xf0, 0xa4, 0x25, 0x7b, 0xfb, 0x86, + 0x57, 0x07, 0xd4, 0x1b, 0x9e, 0x7e, 0xbd, 0x4a, 0x25, 0x90, 0x44, 0xed, 0xe4, 0x3c, 0x39, 0x8d, 0x90, 0xd1, 0x18, + 0xbf, 0xf4, 0x1a, 0xe3, 0x65, 0xa9, 0x31, 0x7e, 0xae, 0xc9, 0x72, 0x4b, 0x63, 0xfc, 0x93, 0x20, 0xcf, 0x75, 0xff, + 0xb9, 0xd7, 0xa6, 0xbf, 0x96, 0x39, 0xcf, 0xee, 0xe2, 0x28, 0xe7, 0xba, 0x09, 0xb7, 0x89, 0x11, 0x5e, 0xd9, 0x0c, + 0x50, 0x35, 0x1a, 0x7d, 0xf7, 0xc6, 0xcb, 0x7f, 0x58, 0x09, 0x12, 0xdd, 0xcb, 0xb9, 0xbe, 0x17, 0xe1, 0x99, 0x26, + 0x7f, 0xc1, 0xaf, 0x7b, 0xab, 0xf8, 0x17, 0xaa, 0x67, 0x49, 0x41, 0xc5, 0x58, 0xce, 0x63, 0xd4, 0x88, 0x22, 0x94, + 0x28, 0x23, 0x84, 0x3c, 0x40, 0x9b, 0x7b, 0x7f, 0xe1, 0x4f, 0x92, 0x44, 0xfd, 0xa8, 0x31, 0xd3, 0x98, 0x53, 0xf2, + 0xd7, 0xe5, 0xbd, 0xd5, 0x27, 0xb9, 0xb9, 0xfa, 0x0b, 0x3f, 0xd5, 0xa5, 0x5a, 0x1f, 0xdf, 0x32, 0x12, 0x23, 0x72, + 0xf5, 0xd4, 0x0f, 0xe9, 0xb1, 0x9c, 0x5b, 0x05, 0x7f, 0x84, 0xf0, 0x17, 0xd0, 0xeb, 0x5e, 0xf1, 0x8a, 0x08, 0xb9, + 0x3b, 0x98, 0x43, 0x12, 0x49, 0xa3, 0x3c, 0x88, 0x8e, 0x8e, 0x82, 0xb4, 0x92, 0x85, 0xc0, 0x8f, 0x24, 0xa9, 0x89, + 0xea, 0x58, 0x50, 0x68, 0xe9, 0x91, 0x8c, 0x39, 0xf2, 0xcd, 0xc4, 0x5e, 0x53, 0xed, 0x76, 0x2c, 0x1f, 0x58, 0xdd, + 0x43, 0xc2, 0x35, 0x2b, 0xa8, 0x96, 0xc5, 0x10, 0x85, 0x6c, 0x09, 0xfe, 0x87, 0x93, 0xbf, 0x06, 0x07, 0xff, 0xcf, + 0xff, 0xf8, 0x73, 0xf2, 0x67, 0x31, 0xfc, 0x0b, 0x0b, 0x46, 0x4e, 0x2e, 0xe3, 0x7e, 0x1a, 0x1f, 0x36, 0x9b, 0xeb, + 0x3f, 0x4f, 0x06, 0xff, 0x4d, 0x9b, 0xff, 0x3c, 0x6c, 0xfe, 0x31, 0x44, 0xeb, 0xf8, 0xcf, 0x93, 0xfe, 0xc0, 0x7d, + 0x0d, 0xfe, 0xfb, 0xea, 0x4f, 0x35, 0x3c, 0xb6, 0x89, 0xf7, 0x10, 0x3a, 0x99, 0xe2, 0x1f, 0x04, 0x39, 0x69, 0x36, + 0xaf, 0x4e, 0xa6, 0xf8, 0x57, 0x41, 0x4e, 0xe0, 0xef, 0x9d, 0x26, 0x6f, 0xd8, 0xf4, 0xe9, 0xed, 0x22, 0xfe, 0xeb, + 0x6a, 0x7d, 0x6f, 0xf5, 0x0f, 0xdf, 0x40, 0xbb, 0x83, 0xff, 0xfe, 0xf3, 0x4f, 0x15, 0x7d, 0x7f, 0x45, 0x4e, 0x86, + 0x0d, 0x14, 0x9b, 0xe4, 0x63, 0x62, 0xff, 0xc4, 0xfd, 0x74, 0xf0, 0xdf, 0x6e, 0x28, 0xd1, 0xf7, 0x7f, 0xfe, 0x75, + 0x79, 0x45, 0x86, 0xeb, 0x38, 0x5a, 0x7f, 0x8f, 0xd6, 0x08, 0xad, 0xef, 0xa1, 0xbf, 0x70, 0x34, 0x8d, 0x10, 0xfe, + 0x43, 0x90, 0x93, 0xef, 0x4f, 0xa6, 0xf8, 0x47, 0x41, 0x4e, 0xa2, 0x93, 0x29, 0x7e, 0x2f, 0xc9, 0xc9, 0x7f, 0xc7, + 0xfd, 0xd4, 0x2a, 0xe1, 0xd6, 0x46, 0xfd, 0xb1, 0x86, 0x9b, 0x10, 0x5a, 0x30, 0xba, 0xd6, 0x5c, 0xe7, 0x0c, 0xdd, + 0x3b, 0xe1, 0xf8, 0xb9, 0x04, 0x60, 0xc5, 0x1a, 0x94, 0x34, 0xe6, 0x12, 0x76, 0xf5, 0x11, 0x16, 0x1e, 0x30, 0xe8, + 0x5e, 0xca, 0xb1, 0xd5, 0x13, 0xa8, 0x54, 0xdb, 0xdb, 0x5b, 0x05, 0xd7, 0xb7, 0xf8, 0x9a, 0x3c, 0x97, 0x71, 0x1b, + 0x61, 0x45, 0xe1, 0x47, 0x07, 0xe1, 0x77, 0xda, 0x5d, 0x78, 0xc2, 0x36, 0xb7, 0x18, 0x26, 0xa4, 0xe5, 0x67, 0x22, + 0x84, 0x9f, 0xee, 0xc9, 0xd4, 0x33, 0x50, 0x3f, 0x20, 0xac, 0x55, 0x78, 0x3d, 0x8a, 0x1f, 0x6b, 0x52, 0x22, 0xc7, + 0xdb, 0x82, 0xb1, 0xdf, 0x68, 0xfe, 0x99, 0x15, 0xf1, 0x53, 0x8d, 0xdb, 0x9d, 0x07, 0xd8, 0xa8, 0xaa, 0x0f, 0xdb, + 0xa8, 0x57, 0xde, 0x6e, 0xbd, 0x93, 0xf6, 0x3e, 0x01, 0x4e, 0xe1, 0xba, 0xbe, 0x06, 0xd6, 0xfe, 0x90, 0xef, 0x28, + 0xb5, 0x0a, 0x7a, 0x13, 0xa1, 0xfa, 0x55, 0x2a, 0x17, 0x5f, 0x68, 0xce, 0xc7, 0x07, 0x9a, 0xcd, 0x17, 0x39, 0xd5, + 0xec, 0xc0, 0xcd, 0xf9, 0x80, 0x42, 0x43, 0x51, 0xc9, 0x53, 0xfc, 0x24, 0xaa, 0x4d, 0xfb, 0x93, 0x48, 0xaa, 0xbd, + 0x13, 0xc3, 0x7d, 0x96, 0xe3, 0x4b, 0x64, 0x75, 0x5d, 0xb6, 0x7d, 0x23, 0xd8, 0x6c, 0x83, 0xb2, 0x6c, 0x68, 0xce, + 0x6f, 0x85, 0xe1, 0x7e, 0x93, 0x90, 0x4e, 0x3f, 0xba, 0x54, 0x5f, 0xa6, 0x57, 0x11, 0xdc, 0xe4, 0x14, 0x44, 0x30, + 0xa3, 0x3c, 0x82, 0x12, 0x94, 0xb4, 0x7a, 0xf4, 0x92, 0xf5, 0x68, 0xa3, 0xe1, 0xd9, 0xec, 0x8c, 0xf0, 0x01, 0xb5, + 0xf5, 0x73, 0x3c, 0xc3, 0x63, 0xd2, 0x6c, 0xe3, 0x25, 0x69, 0x99, 0x2a, 0xbd, 0xe5, 0x65, 0xe6, 0xfa, 0x39, 0x3a, + 0x8a, 0x8b, 0x24, 0xa7, 0x4a, 0xbf, 0x00, 0x8d, 0x00, 0x59, 0xe2, 0x19, 0x29, 0x12, 0x76, 0xcb, 0xb2, 0x38, 0x43, + 0x78, 0xe6, 0x68, 0x10, 0xea, 0xa1, 0x25, 0x09, 0x8a, 0x81, 0x9c, 0x41, 0x04, 0xeb, 0xcf, 0x06, 0xed, 0x21, 0x21, + 0x24, 0x3a, 0x6c, 0x36, 0xa3, 0x7e, 0x41, 0x7e, 0x10, 0x29, 0xa4, 0x04, 0xec, 0x34, 0xf9, 0x15, 0x92, 0x3a, 0x41, + 0x52, 0xfc, 0x5e, 0x26, 0x9a, 0x29, 0x1d, 0x43, 0x32, 0x28, 0x09, 0x94, 0xc7, 0xf0, 0xe8, 0xf2, 0x24, 0x6a, 0x40, + 0xaa, 0x41, 0x51, 0x84, 0x0b, 0x72, 0xa7, 0x51, 0x3a, 0x1b, 0x9c, 0x0e, 0xc3, 0x33, 0xc2, 0xa6, 0x42, 0xff, 0x77, + 0xba, 0x3f, 0x1b, 0xb4, 0x4c, 0xff, 0x57, 0x51, 0x3f, 0x2e, 0x88, 0xb2, 0x6c, 0x5c, 0x5f, 0xa5, 0x82, 0x99, 0xf9, + 0xa2, 0xd4, 0x0d, 0xd0, 0xf5, 0x3d, 0x26, 0xcd, 0x4e, 0x1a, 0x8f, 0xc3, 0x99, 0x34, 0xa1, 0x43, 0x07, 0x0a, 0x9c, + 0x13, 0x28, 0x8f, 0x0b, 0x02, 0x9d, 0x56, 0xd5, 0xee, 0x74, 0xea, 0x12, 0xbe, 0x8f, 0xbe, 0xef, 0xff, 0x28, 0xd2, + 0x3f, 0x84, 0x1d, 0xc1, 0x8f, 0x62, 0xbd, 0x86, 0xbf, 0x7f, 0x88, 0x3e, 0x0c, 0xcb, 0xa4, 0xfd, 0xe0, 0xd2, 0x7e, + 0x85, 0x34, 0xc1, 0x52, 0x33, 0x60, 0xac, 0x4a, 0x7e, 0xcc, 0x2e, 0xce, 0x84, 0xd8, 0x19, 0x1c, 0x1d, 0xf1, 0x01, + 0x6d, 0xb4, 0x87, 0x70, 0x23, 0x50, 0x68, 0xf5, 0x1b, 0xd7, 0xb3, 0x38, 0x3a, 0xb9, 0x8a, 0x50, 0x3f, 0x3a, 0x80, + 0x55, 0xee, 0xc9, 0x06, 0x71, 0xb0, 0xce, 0x1a, 0x9c, 0xa6, 0xe3, 0x2b, 0xd2, 0xea, 0xc7, 0xc2, 0x12, 0xf9, 0x1c, + 0xe1, 0xcc, 0xd1, 0xd4, 0x16, 0x1e, 0xa3, 0x86, 0x12, 0x0d, 0xff, 0x3d, 0x46, 0x8d, 0x99, 0x6e, 0x4c, 0x50, 0x9a, + 0xc1, 0xdf, 0x78, 0x4c, 0x08, 0x69, 0x76, 0xca, 0x8a, 0xfe, 0xb0, 0xa4, 0x28, 0x9d, 0x78, 0xf5, 0xe8, 0xc0, 0x6c, + 0x0e, 0xd9, 0x88, 0xf9, 0x80, 0x0d, 0xd7, 0xeb, 0xe8, 0xb2, 0x7f, 0x15, 0xa1, 0x46, 0xec, 0xd1, 0xee, 0xc4, 0xe3, + 0x1d, 0x42, 0x58, 0x0c, 0x37, 0xee, 0x06, 0xea, 0x86, 0xd5, 0x6e, 0x9b, 0x56, 0xd5, 0xfe, 0x0f, 0xc8, 0x02, 0xdb, + 0x94, 0x72, 0x8f, 0xe5, 0x6f, 0x17, 0x30, 0x55, 0x8f, 0xdb, 0x92, 0xb4, 0x70, 0x41, 0xbc, 0xba, 0x9b, 0x12, 0x5d, + 0xe1, 0x7f, 0x46, 0xaa, 0xe2, 0x78, 0x90, 0xe3, 0xd9, 0x90, 0x48, 0x6a, 0xe4, 0x97, 0x9e, 0x57, 0xa6, 0xb3, 0x9c, + 0xdc, 0xb0, 0xad, 0xfb, 0xdf, 0x1c, 0xee, 0x64, 0x1e, 0xeb, 0x24, 0x5b, 0x16, 0x05, 0x13, 0xfa, 0xa5, 0x1c, 0x3b, + 0xc6, 0x8e, 0xe5, 0x20, 0x5b, 0xc1, 0xc5, 0x2e, 0x06, 0xae, 0xae, 0xe3, 0x77, 0xca, 0x78, 0x27, 0x7b, 0x49, 0xc6, + 0x96, 0xe1, 0x32, 0xd7, 0xbd, 0xbd, 0xa5, 0x13, 0xa5, 0x63, 0x84, 0xc7, 0xee, 0x1e, 0x38, 0x4e, 0x92, 0x64, 0x99, + 0x64, 0x90, 0x0d, 0x1d, 0x28, 0xb4, 0x31, 0xfb, 0x2a, 0x56, 0xe4, 0xb1, 0x4e, 0x04, 0xbb, 0x35, 0xdd, 0xc6, 0xa8, + 0x3a, 0xc4, 0xfd, 0x7e, 0xbb, 0xa4, 0x3d, 0x43, 0x80, 0x54, 0x22, 0xe4, 0x98, 0x01, 0x84, 0xe0, 0xee, 0xdf, 0x25, + 0xcd, 0xa8, 0x0a, 0x6f, 0xb6, 0xaa, 0x01, 0x0e, 0x42, 0x95, 0xf7, 0x12, 0xf4, 0xc4, 0x86, 0x3d, 0x2b, 0x0b, 0x5b, + 0xe5, 0x39, 0x42, 0x7c, 0x12, 0x2f, 0x13, 0xb8, 0x11, 0x34, 0x98, 0xa4, 0x04, 0x5a, 0xaf, 0x97, 0x21, 0x6e, 0xcd, + 0x2a, 0xc5, 0xf4, 0x84, 0xcc, 0x06, 0x45, 0xa3, 0x61, 0x94, 0xd7, 0x63, 0x8b, 0x17, 0x4b, 0x84, 0x27, 0xe5, 0x5e, + 0xf3, 0xe5, 0x16, 0xa4, 0xde, 0x55, 0x3c, 0xa9, 0x2b, 0x81, 0x1b, 0x4a, 0x20, 0xa3, 0x5f, 0xd4, 0xd0, 0x3a, 0x9e, + 0x92, 0x93, 0x78, 0x90, 0xf4, 0xff, 0xe7, 0x10, 0xf5, 0xe3, 0xe4, 0x18, 0x9d, 0x58, 0x5a, 0x32, 0x41, 0xbd, 0xcc, + 0xf6, 0xb1, 0x32, 0xb7, 0x9f, 0x6d, 0x6c, 0x14, 0x90, 0xa9, 0xc4, 0x82, 0xce, 0x59, 0x3a, 0x85, 0x5d, 0xef, 0x91, + 0x67, 0x81, 0x01, 0x99, 0xd2, 0xa9, 0xa3, 0x2d, 0x49, 0xd4, 0xa7, 0xb4, 0xfc, 0xea, 0x47, 0xfd, 0xbc, 0xfa, 0xfa, + 0x9f, 0x51, 0x7f, 0x46, 0xd3, 0xc7, 0x7c, 0xe3, 0x94, 0xe4, 0xb5, 0x3e, 0xce, 0x7d, 0x1f, 0x1b, 0xbb, 0x38, 0x01, + 0xf0, 0xc6, 0x68, 0x57, 0x3b, 0xb2, 0x44, 0x1b, 0x3e, 0x29, 0xa9, 0x93, 0x4a, 0x34, 0x9d, 0x02, 0x54, 0x83, 0x45, + 0x50, 0xa1, 0x6d, 0x40, 0x30, 0x65, 0xc0, 0x16, 0x8f, 0xb4, 0x00, 0xcd, 0xe5, 0x55, 0x0b, 0xad, 0x6a, 0x85, 0x1d, + 0x67, 0x55, 0xbf, 0x8b, 0x2f, 0x89, 0xf7, 0x04, 0xa8, 0xf2, 0xe5, 0xb2, 0x37, 0x69, 0x34, 0x90, 0xf2, 0xf8, 0x35, + 0x1e, 0x4c, 0x86, 0xf8, 0x16, 0x50, 0x08, 0xd7, 0x30, 0x0a, 0xd7, 0xe6, 0xd8, 0x71, 0x73, 0x6c, 0x34, 0xe4, 0x06, + 0xf5, 0x82, 0xca, 0x4b, 0x57, 0x79, 0xb3, 0xb1, 0x90, 0xd9, 0xc6, 0xb8, 0x0b, 0x64, 0x52, 0xc0, 0x10, 0x8c, 0x10, + 0xf2, 0x49, 0xa2, 0xbd, 0xcd, 0x42, 0xa3, 0x50, 0xdd, 0xec, 0x5e, 0xa0, 0xa8, 0xf6, 0xf4, 0x88, 0x01, 0x16, 0x50, + 0xb5, 0x54, 0x23, 0xcf, 0x34, 0x1e, 0x37, 0xda, 0x06, 0xdd, 0x9b, 0xed, 0x5e, 0xbd, 0xb1, 0xfb, 0x55, 0x63, 0x78, + 0xdc, 0x20, 0xb3, 0x6a, 0x87, 0x6f, 0x64, 0xa3, 0xb1, 0xa9, 0xdf, 0x97, 0xfa, 0x4d, 0x5c, 0xbb, 0xbf, 0x78, 0xba, + 0x63, 0xe2, 0xe1, 0x4f, 0xdf, 0xea, 0xbc, 0x15, 0x09, 0x17, 0x82, 0x15, 0x70, 0xc2, 0x12, 0x8d, 0xc5, 0x66, 0x53, + 0x9e, 0xfa, 0xbf, 0x69, 0x6b, 0x33, 0x46, 0x38, 0xd0, 0x21, 0x23, 0xb5, 0x61, 0x89, 0x0b, 0x4c, 0x0d, 0x15, 0x21, + 0x84, 0xbc, 0xd3, 0xde, 0x3c, 0x46, 0x1b, 0x92, 0x94, 0x91, 0xe0, 0xec, 0x8e, 0x15, 0x61, 0xc9, 0xc7, 0x7b, 0x8f, + 0xe5, 0x37, 0x45, 0xba, 0x81, 0x18, 0xa6, 0xa6, 0x58, 0xee, 0x08, 0x59, 0x4e, 0xbe, 0x80, 0x9c, 0x53, 0x5e, 0xb0, + 0x24, 0x86, 0x20, 0x3e, 0xe1, 0x05, 0x33, 0x8c, 0xfb, 0x3d, 0x2f, 0x37, 0x66, 0x75, 0x4e, 0x33, 0x0b, 0xb5, 0x3f, + 0x00, 0xcd, 0x1c, 0x94, 0x43, 0x92, 0xec, 0x14, 0xfb, 0x78, 0xef, 0xe1, 0xab, 0x7d, 0x32, 0xf4, 0x7a, 0xed, 0xa4, + 0xe7, 0x0c, 0x58, 0x1f, 0x9c, 0x57, 0x43, 0xcd, 0xdc, 0x8f, 0x34, 0xce, 0x0c, 0x13, 0x95, 0xc7, 0x1c, 0x90, 0xe9, + 0xe3, 0xbd, 0x87, 0x6f, 0x63, 0x6e, 0x74, 0x53, 0x08, 0x87, 0xf3, 0x8e, 0x0b, 0x12, 0x53, 0xc2, 0x90, 0x9d, 0x7c, + 0x49, 0xc7, 0x8a, 0xe0, 0x74, 0x4f, 0xa9, 0xc9, 0x04, 0xb1, 0x63, 0x20, 0x86, 0x24, 0x73, 0x20, 0x20, 0x19, 0xc2, + 0x59, 0x4d, 0xae, 0x23, 0x66, 0x0d, 0x4c, 0x67, 0xd7, 0xb0, 0x18, 0x89, 0x65, 0x0f, 0x11, 0xce, 0x4c, 0xb7, 0x7a, + 0x63, 0x8f, 0x93, 0x82, 0x6e, 0x1b, 0xba, 0x55, 0xf2, 0xec, 0x7b, 0x10, 0xbc, 0xfc, 0xc7, 0x4b, 0xd7, 0x76, 0x99, + 0xf0, 0xc4, 0x5b, 0xa4, 0x7d, 0xbc, 0xf7, 0xf0, 0x17, 0x67, 0x94, 0xb6, 0xa0, 0x9e, 0xfc, 0xef, 0xc8, 0xa8, 0x0f, + 0x7f, 0x49, 0xaa, 0x5c, 0x53, 0xf8, 0xe3, 0xbd, 0x87, 0xef, 0xf6, 0x15, 0x83, 0xf4, 0xcd, 0xb2, 0x52, 0x12, 0x98, + 0xf1, 0xad, 0x58, 0x9e, 0xae, 0xdc, 0x59, 0x91, 0x8a, 0x0d, 0x36, 0x27, 0x54, 0xaa, 0x36, 0xa5, 0x6e, 0xe5, 0x09, + 0x96, 0xc4, 0x5c, 0x25, 0xd5, 0x97, 0xcd, 0xa1, 0x31, 0x97, 0xe2, 0x3a, 0x93, 0x0b, 0xf6, 0x95, 0xfb, 0xa5, 0xa7, + 0x1a, 0x25, 0x7c, 0x0e, 0x86, 0x38, 0x66, 0xec, 0x02, 0x1f, 0xb6, 0x50, 0x6f, 0xeb, 0x3c, 0x93, 0x06, 0x51, 0x8b, + 0xfa, 0x61, 0x83, 0x29, 0x69, 0xe1, 0x8c, 0xb4, 0x70, 0x4e, 0xd4, 0xa0, 0x65, 0x4f, 0x8c, 0x5e, 0x5e, 0x36, 0x6d, + 0xcf, 0x1d, 0xd8, 0xee, 0xb9, 0xdd, 0xb7, 0xf6, 0x50, 0x9e, 0xf5, 0x72, 0xa3, 0xbf, 0x34, 0x07, 0xfd, 0xcc, 0xa0, + 0xc6, 0x0b, 0x16, 0x17, 0xb8, 0x30, 0x2d, 0x5f, 0xf3, 0x51, 0x0e, 0x76, 0x2a, 0x30, 0x33, 0xac, 0x51, 0x5a, 0x96, + 0x6d, 0xbb, 0xb2, 0x79, 0x62, 0xd6, 0xaa, 0xc0, 0x79, 0x02, 0xa4, 0x1c, 0xe7, 0xce, 0xae, 0x47, 0xed, 0x56, 0x39, + 0x3f, 0x3a, 0x8a, 0x6d, 0xa5, 0x31, 0x8d, 0x0b, 0x9f, 0x5f, 0xdd, 0x00, 0xbe, 0xb7, 0x54, 0x63, 0x86, 0xcc, 0x04, + 0x1a, 0x8d, 0x6c, 0xb8, 0xa1, 0x87, 0x84, 0xc4, 0x79, 0x1d, 0x8a, 0x7e, 0xf4, 0x86, 0x19, 0xdc, 0x02, 0x40, 0xa3, + 0x51, 0x5e, 0xf7, 0x6e, 0x41, 0xec, 0xa9, 0xc6, 0x72, 0xf3, 0x25, 0x2e, 0xad, 0x89, 0x5a, 0x3b, 0x76, 0x58, 0x7e, + 0x14, 0x48, 0x84, 0xb8, 0x2b, 0xfc, 0x7c, 0x82, 0xad, 0x21, 0xa0, 0xdc, 0x0b, 0x67, 0x03, 0x81, 0x8d, 0xd5, 0x96, + 0x2b, 0xe4, 0x49, 0x5b, 0x07, 0xa5, 0xbe, 0x10, 0x5c, 0x70, 0x41, 0xa1, 0xc6, 0xc6, 0x61, 0xf9, 0x0b, 0xb6, 0x6b, + 0xce, 0x89, 0x15, 0x72, 0xda, 0x32, 0x33, 0x0c, 0x03, 0xb0, 0x4e, 0x09, 0x98, 0xe7, 0xe4, 0xe9, 0xd7, 0x51, 0xff, + 0x61, 0x80, 0xfa, 0x8f, 0x08, 0x0b, 0xb6, 0x81, 0xd5, 0x95, 0x24, 0xd2, 0x29, 0x28, 0x94, 0xcf, 0x7a, 0xbc, 0x20, + 0xa0, 0x8d, 0xab, 0x43, 0xb5, 0x76, 0x45, 0xf9, 0x15, 0xca, 0x12, 0xee, 0x14, 0xa3, 0xcf, 0xc4, 0xfe, 0x3e, 0x39, + 0xae, 0x2e, 0xe8, 0xa0, 0xeb, 0x7d, 0xca, 0xc1, 0x90, 0x14, 0x3e, 0x7c, 0xf7, 0xed, 0xbb, 0xd5, 0xc7, 0x8b, 0xdd, + 0x1d, 0x1c, 0x98, 0x95, 0xc2, 0xac, 0x83, 0x0d, 0x5c, 0x37, 0x32, 0x85, 0xfe, 0xcb, 0x3b, 0xf1, 0x3a, 0x15, 0xda, + 0xda, 0x8c, 0xfe, 0x38, 0x84, 0xd1, 0xb6, 0xdb, 0xa6, 0x04, 0x0b, 0x9a, 0x05, 0xba, 0x64, 0x8d, 0x5b, 0x69, 0xf1, + 0x15, 0x32, 0xf2, 0xd0, 0x14, 0x60, 0x62, 0xbc, 0x3f, 0xfb, 0xd1, 0xc6, 0xe1, 0x89, 0x1d, 0x1a, 0x5a, 0x19, 0x42, + 0x68, 0xf1, 0x1e, 0x30, 0xc7, 0x1e, 0x11, 0x00, 0xa2, 0xa7, 0x06, 0x52, 0x15, 0xc8, 0xa2, 0xa8, 0x52, 0xe4, 0x3f, + 0x3f, 0x24, 0xe4, 0x69, 0xa5, 0xc8, 0x7c, 0x53, 0x19, 0x73, 0x01, 0x62, 0xa0, 0x14, 0x2e, 0x12, 0xca, 0x04, 0x7b, + 0x19, 0xfa, 0x4e, 0xfb, 0xf2, 0x46, 0xda, 0x4c, 0x2a, 0x6e, 0x3c, 0xb8, 0x29, 0x35, 0x2a, 0x3e, 0x9b, 0xef, 0x21, + 0xb1, 0x95, 0x7b, 0x0f, 0x72, 0x05, 0x35, 0x83, 0x84, 0xef, 0xb7, 0xa6, 0xb4, 0x6f, 0x77, 0xf3, 0x79, 0xdb, 0x22, + 0x66, 0x6b, 0x5d, 0x12, 0x2e, 0x14, 0x2b, 0xf4, 0x23, 0x36, 0x91, 0x05, 0xdc, 0x7f, 0x94, 0x60, 0x41, 0x9b, 0x7b, + 0x81, 0x0e, 0xd0, 0x4c, 0x30, 0xb8, 0x74, 0xd8, 0x9a, 0xa1, 0xf9, 0xf5, 0xd9, 0xdc, 0x81, 0x7f, 0xdc, 0xae, 0xf5, + 0xf4, 0xe8, 0xe8, 0x0b, 0xab, 0x00, 0xe5, 0x86, 0x69, 0x86, 0x11, 0x10, 0x2f, 0xcb, 0xe5, 0xb8, 0x9b, 0xe1, 0x7b, + 0x71, 0xa5, 0x32, 0xf0, 0x84, 0x23, 0x24, 0x42, 0xcf, 0x89, 0xde, 0x4c, 0xb7, 0xe9, 0xbd, 0xd3, 0x66, 0x88, 0x50, + 0xac, 0x01, 0x72, 0x0f, 0x72, 0xb9, 0x55, 0x32, 0xa9, 0xca, 0xd6, 0xb6, 0x1c, 0xc4, 0x63, 0x00, 0x57, 0x6c, 0x84, + 0x94, 0x00, 0x0d, 0xf7, 0x0b, 0x2d, 0xef, 0x24, 0xb0, 0xff, 0x58, 0x25, 0x20, 0xd2, 0xa2, 0xda, 0xc6, 0x45, 0x08, + 0x5b, 0x53, 0x9f, 0xc0, 0x38, 0xe1, 0xe1, 0xf3, 0x7d, 0x1a, 0x6a, 0x8f, 0xda, 0xcc, 0x9c, 0x41, 0x50, 0x42, 0xa2, + 0xb2, 0x42, 0xf2, 0x25, 0x16, 0x8e, 0x9b, 0xf3, 0xf7, 0x70, 0x40, 0x8a, 0x0b, 0x1a, 0xdb, 0xbb, 0x2d, 0x38, 0x3e, + 0x8a, 0x64, 0x19, 0xd7, 0xba, 0xee, 0x15, 0xa6, 0x1a, 0x76, 0xa0, 0xa3, 0x21, 0x9c, 0x0a, 0x73, 0x4f, 0xf8, 0xb8, + 0x22, 0xa9, 0xda, 0x59, 0x40, 0x79, 0x62, 0x58, 0x99, 0xa6, 0x04, 0xf3, 0xd7, 0xce, 0x7c, 0xad, 0x3c, 0x26, 0x98, + 0x19, 0xc6, 0x8d, 0x5d, 0x05, 0xb6, 0x01, 0x1c, 0x5b, 0x3d, 0x92, 0xc1, 0xa2, 0x7a, 0xa5, 0xb8, 0xe9, 0x34, 0x60, + 0x02, 0xde, 0x80, 0xf5, 0xcc, 0xf6, 0xd6, 0x7f, 0x6e, 0x0e, 0x46, 0x81, 0x55, 0x8d, 0xc0, 0x4b, 0x43, 0xe0, 0x11, + 0x30, 0x6e, 0xde, 0xb4, 0xbc, 0xef, 0x8c, 0x68, 0x84, 0x3f, 0xf1, 0x1c, 0x9e, 0x59, 0x96, 0x7b, 0xe7, 0x63, 0x6b, + 0x45, 0x52, 0x41, 0xc0, 0xb6, 0x08, 0x3b, 0x22, 0x2f, 0x11, 0x56, 0x8d, 0x46, 0x4f, 0x5d, 0xb2, 0x4a, 0xab, 0x52, + 0x0d, 0x53, 0xc0, 0x2d, 0x31, 0xe0, 0x7d, 0xed, 0x44, 0x05, 0x43, 0x02, 0x6f, 0xfd, 0xad, 0x40, 0x7d, 0xff, 0xf0, + 0x4d, 0x1c, 0xd2, 0xb7, 0xb0, 0x6c, 0x79, 0x11, 0x0b, 0x53, 0x8a, 0xab, 0x3b, 0x9c, 0xd7, 0xdf, 0x36, 0x1b, 0x81, + 0x71, 0x1f, 0xb6, 0x31, 0xd8, 0xb8, 0xa1, 0x9e, 0xb6, 0xa4, 0xa1, 0xdc, 0x84, 0x3d, 0x54, 0xd9, 0x3b, 0x86, 0x9d, + 0xf5, 0x74, 0x25, 0xed, 0x6a, 0xa2, 0x36, 0x1b, 0xc5, 0x2a, 0xa3, 0x81, 0x2d, 0xc3, 0x4e, 0x73, 0xcc, 0xec, 0x2a, + 0xf0, 0x1f, 0x2f, 0x88, 0xc6, 0x01, 0xb2, 0xbe, 0xfe, 0xda, 0x75, 0x4a, 0x35, 0x4c, 0xd8, 0xde, 0xee, 0x7c, 0x7c, + 0xcc, 0xf7, 0x9d, 0x8f, 0x58, 0xba, 0xad, 0x6f, 0xce, 0xc6, 0xf6, 0xbf, 0x71, 0x36, 0x3a, 0xb5, 0xbd, 0x3f, 0x1e, + 0x81, 0x3b, 0xa9, 0x1d, 0x8f, 0xf5, 0x35, 0x25, 0x12, 0x0b, 0xb7, 0x1c, 0x57, 0x9d, 0xf5, 0x5a, 0x0c, 0x5a, 0xa0, + 0x76, 0x8a, 0x22, 0xf8, 0xd9, 0xb6, 0x3f, 0x03, 0x92, 0x6c, 0x75, 0xc8, 0xb1, 0x28, 0x45, 0x19, 0x94, 0x80, 0x01, + 0x75, 0x6c, 0x6c, 0xbd, 0x0c, 0x62, 0x3b, 0x1c, 0x72, 0x58, 0x4e, 0x44, 0x79, 0x75, 0x05, 0x23, 0x36, 0xc7, 0x86, + 0x13, 0x30, 0xe3, 0xbd, 0x56, 0x85, 0x5e, 0xfc, 0xfc, 0xd7, 0xcc, 0x69, 0xed, 0x88, 0xb1, 0x9c, 0x44, 0xcd, 0x8a, + 0xc1, 0x8d, 0xc0, 0x31, 0x8c, 0x87, 0x46, 0x42, 0xad, 0x4e, 0x75, 0x54, 0x3b, 0x92, 0x70, 0x0b, 0xd4, 0x6e, 0x87, + 0xe6, 0x5c, 0x5a, 0xaf, 0xf7, 0x1e, 0x2c, 0xb8, 0x08, 0x70, 0xfb, 0x39, 0xd1, 0x35, 0x92, 0x42, 0x89, 0x93, 0xa0, + 0x70, 0x6e, 0x50, 0x55, 0x13, 0x39, 0x68, 0x0d, 0x81, 0x27, 0xed, 0x65, 0x97, 0xb2, 0x12, 0x92, 0xb3, 0x46, 0x03, + 0xe5, 0x65, 0xc7, 0x74, 0x20, 0x1a, 0xd9, 0x10, 0x33, 0x9c, 0x59, 0x81, 0x05, 0x4e, 0xaf, 0x38, 0xaf, 0xba, 0x1e, + 0x64, 0x43, 0x84, 0x8b, 0xf5, 0x3a, 0xb6, 0x43, 0xcb, 0xd1, 0x7a, 0x9d, 0x87, 0x43, 0x33, 0xf9, 0x50, 0xf1, 0x69, + 0x5f, 0x93, 0xa7, 0xe6, 0x3c, 0x7c, 0x0a, 0x83, 0x6c, 0x90, 0x38, 0x77, 0x2a, 0xc1, 0x1c, 0x34, 0x57, 0x0d, 0x39, + 0xc8, 0x1a, 0xed, 0x61, 0x40, 0xc3, 0x06, 0xd9, 0x90, 0xe4, 0x1b, 0xb0, 0x9c, 0x55, 0xee, 0xc0, 0xfc, 0x04, 0x07, + 0xdb, 0x27, 0x73, 0xce, 0xd8, 0x06, 0xc3, 0x35, 0xd9, 0x56, 0x19, 0x94, 0x78, 0xe5, 0x16, 0xd7, 0x97, 0xab, 0x19, + 0x58, 0x94, 0x85, 0xb0, 0xbb, 0x66, 0xee, 0x83, 0xf0, 0x5f, 0x62, 0x3b, 0xa5, 0xa5, 0x11, 0xf7, 0x16, 0xe2, 0x7b, + 0xdb, 0xed, 0x24, 0x49, 0x68, 0x31, 0x35, 0x57, 0x22, 0xfe, 0x86, 0xd7, 0xec, 0x81, 0x53, 0x37, 0xce, 0xa0, 0xe7, + 0x41, 0xd9, 0xd9, 0x90, 0xd8, 0xf1, 0x7b, 0x66, 0xc7, 0x3b, 0xae, 0x64, 0x74, 0xbf, 0x2e, 0xc2, 0x0e, 0x26, 0xff, + 0x5f, 0x1e, 0xcc, 0x99, 0x1b, 0x8c, 0x45, 0x93, 0x2d, 0xb8, 0x7d, 0x05, 0x1e, 0x19, 0xdd, 0x82, 0xdb, 0xd7, 0xe1, + 0xeb, 0xa1, 0x35, 0xfb, 0xea, 0x00, 0x03, 0x32, 0x61, 0x47, 0x5a, 0x25, 0x04, 0xc3, 0xec, 0x6e, 0x73, 0x64, 0x96, + 0xac, 0xc2, 0xe1, 0xaa, 0x49, 0x2c, 0xb6, 0xf6, 0x42, 0xc5, 0xa4, 0x06, 0x82, 0xb1, 0x48, 0x9f, 0xa2, 0x50, 0x69, + 0x50, 0x37, 0x8e, 0x01, 0xac, 0x72, 0xda, 0xfa, 0xa7, 0x47, 0x47, 0x20, 0x34, 0x00, 0x6b, 0x97, 0x64, 0x74, 0xa1, + 0x97, 0x05, 0xf0, 0x57, 0xca, 0xff, 0x86, 0x64, 0x70, 0x3b, 0x31, 0x69, 0xf0, 0x03, 0x12, 0x16, 0x54, 0x29, 0xfe, + 0xc5, 0xa6, 0xb9, 0xdf, 0xb8, 0x20, 0x1e, 0xa3, 0x95, 0xe5, 0x14, 0x25, 0xea, 0x49, 0x87, 0xae, 0x75, 0xc8, 0x3d, + 0xfd, 0xc2, 0x84, 0xfe, 0x99, 0x2b, 0xcd, 0x04, 0x00, 0xa0, 0x42, 0x3c, 0x98, 0x92, 0x42, 0xb0, 0x75, 0x6b, 0xb5, + 0xe8, 0x78, 0xfc, 0xcd, 0x2a, 0xba, 0xce, 0x16, 0xcd, 0xa8, 0x18, 0xe7, 0xb6, 0x93, 0xd0, 0x66, 0xd2, 0xdb, 0x89, + 0x96, 0x25, 0x43, 0x8b, 0x9d, 0x8a, 0xfd, 0x30, 0xb4, 0x3e, 0x16, 0xc4, 0x9f, 0x0b, 0xfe, 0x2c, 0xfd, 0x26, 0x1f, + 0x03, 0x57, 0xea, 0x5f, 0x59, 0x85, 0x70, 0x26, 0x58, 0x07, 0xe4, 0x35, 0xa9, 0x8f, 0xd3, 0xa3, 0xce, 0x78, 0x47, + 0xb9, 0x50, 0x1a, 0x85, 0x6d, 0x9d, 0x14, 0x06, 0x53, 0xce, 0xbf, 0x2e, 0x71, 0xfd, 0xe2, 0x8f, 0x11, 0x7f, 0x74, + 0x88, 0x7f, 0x97, 0x4a, 0xa3, 0x55, 0x89, 0x60, 0xc8, 0xef, 0x48, 0xa6, 0xe0, 0x2a, 0x36, 0xe7, 0xfa, 0xb9, 0x9e, + 0xe7, 0x5b, 0x9e, 0x38, 0x3d, 0xa6, 0x4a, 0xe8, 0xa8, 0xf8, 0x86, 0xe1, 0x17, 0x0c, 0xee, 0x8d, 0x5f, 0xf2, 0xa0, + 0xca, 0xee, 0x7d, 0xf1, 0xcb, 0xe0, 0xbe, 0xf8, 0x25, 0x4f, 0x77, 0x8b, 0x06, 0xf7, 0xc4, 0x9d, 0xe4, 0x22, 0x69, + 0x45, 0x9e, 0x8f, 0x5a, 0xd2, 0xca, 0xbf, 0xd2, 0x6e, 0x0d, 0x5c, 0xd9, 0xc4, 0x81, 0x71, 0x5e, 0x5d, 0x84, 0x62, + 0xce, 0x9c, 0xd1, 0x72, 0xf8, 0x5f, 0x5b, 0x27, 0x77, 0xf2, 0x48, 0x2b, 0x85, 0xbc, 0xa6, 0x85, 0xbe, 0x07, 0x1b, + 0xae, 0xd8, 0xf1, 0x01, 0xa4, 0x04, 0x94, 0x6d, 0xff, 0x5e, 0x17, 0x81, 0x38, 0xae, 0xac, 0xf3, 0x51, 0xd8, 0x3e, + 0x29, 0x4a, 0xae, 0xae, 0x2e, 0x84, 0xdc, 0x1a, 0x2d, 0x01, 0xc2, 0xd4, 0xbb, 0xe6, 0x31, 0x47, 0x93, 0x59, 0xba, + 0xda, 0x94, 0xaa, 0x83, 0xc2, 0x72, 0x75, 0x1c, 0xe1, 0x62, 0x63, 0x6e, 0xd0, 0x3f, 0x71, 0xfc, 0x88, 0x3b, 0x1a, + 0xf9, 0x63, 0x49, 0x81, 0xde, 0xef, 0xf7, 0xb5, 0xd9, 0x43, 0x22, 0xed, 0x1c, 0x4a, 0x4b, 0x01, 0xc0, 0x6a, 0x83, + 0xaf, 0x1b, 0x8f, 0x53, 0x4f, 0xa4, 0x9b, 0xcd, 0x57, 0x0d, 0x61, 0x31, 0x2b, 0x2d, 0x78, 0x4c, 0x37, 0x7b, 0x2c, + 0x47, 0xbd, 0x2c, 0xae, 0xcb, 0x3d, 0x56, 0xeb, 0x17, 0x7d, 0x05, 0x94, 0x95, 0x21, 0xda, 0x7a, 0x1d, 0xd7, 0xe1, + 0x4d, 0x44, 0x70, 0x0d, 0x82, 0xb0, 0x08, 0x0c, 0x38, 0x6a, 0x8c, 0xb7, 0xad, 0x13, 0xa3, 0x6d, 0xfb, 0x25, 0xcf, + 0xba, 0xd7, 0xc6, 0x11, 0x2a, 0x1a, 0x6c, 0xf5, 0x50, 0xf3, 0x80, 0xed, 0xec, 0xca, 0x8e, 0x02, 0x08, 0x2d, 0x4b, + 0xe3, 0xdc, 0xca, 0x8a, 0x76, 0x0f, 0x7c, 0xd1, 0x37, 0xcc, 0x73, 0x1d, 0xe8, 0x76, 0xf3, 0x03, 0xdb, 0xa6, 0x27, + 0xf2, 0x6b, 0xb6, 0x4d, 0x35, 0x4e, 0xf8, 0xb0, 0x85, 0xbe, 0x6d, 0x08, 0x6b, 0xfb, 0xda, 0x5f, 0xe4, 0x7f, 0xa1, + 0xbb, 0x36, 0xa0, 0xa7, 0x05, 0xb3, 0xa7, 0x31, 0xef, 0xf4, 0x66, 0xf3, 0x63, 0xe9, 0xbf, 0x60, 0x6c, 0x85, 0x7e, + 0xb4, 0xbb, 0xc0, 0x89, 0x95, 0xc6, 0x21, 0x38, 0xfe, 0xc4, 0xc9, 0x34, 0x97, 0x23, 0x9a, 0xbf, 0x85, 0x1e, 0xab, + 0xdc, 0xe7, 0x77, 0xe3, 0x82, 0x6a, 0xe6, 0x68, 0x4d, 0x35, 0x8a, 0x4f, 0x3c, 0x18, 0xc6, 0x27, 0x6e, 0x29, 0x77, + 0xd5, 0x02, 0x5e, 0xfd, 0x5c, 0x36, 0x91, 0xfe, 0xb8, 0xf1, 0xb4, 0x83, 0xab, 0xfd, 0xbd, 0x6c, 0x93, 0x34, 0x5e, + 0x92, 0x34, 0xae, 0xe2, 0xed, 0xa6, 0xe2, 0xf8, 0xd1, 0x57, 0x06, 0xbb, 0x4b, 0xe6, 0x1e, 0x05, 0x64, 0xee, 0x11, + 0x4f, 0xbf, 0x59, 0x2b, 0xa0, 0x78, 0xa7, 0xc9, 0xa9, 0xb1, 0x8c, 0xb1, 0xa3, 0x7e, 0xa3, 0xc1, 0xa0, 0x41, 0x93, + 0xab, 0xc0, 0xdb, 0xa1, 0x3a, 0xbd, 0xbc, 0xfd, 0x51, 0x9c, 0x2d, 0x95, 0x96, 0x73, 0xd7, 0xa8, 0x72, 0x3e, 0x4e, + 0x26, 0x13, 0x14, 0xd8, 0xe6, 0x0e, 0x3f, 0xad, 0xbb, 0x91, 0xad, 0x3e, 0x73, 0x31, 0x4e, 0x15, 0x76, 0x67, 0x8b, + 0x4a, 0xe5, 0x86, 0x78, 0x33, 0xe7, 0xdd, 0x3c, 0x3c, 0xe1, 0x82, 0xab, 0x19, 0x2b, 0xe2, 0x02, 0xad, 0xbe, 0xd6, + 0x59, 0x01, 0xb7, 0x39, 0xb6, 0x33, 0x3c, 0x29, 0x2d, 0x07, 0x74, 0x02, 0xad, 0x81, 0xce, 0x68, 0xce, 0xf4, 0x4c, + 0x8e, 0xc1, 0xf0, 0x25, 0x19, 0x97, 0xee, 0x54, 0x47, 0x47, 0x87, 0x71, 0x64, 0xf4, 0x17, 0xe0, 0x83, 0x1e, 0xe6, + 0xa0, 0xfe, 0x0a, 0x1c, 0x83, 0xaa, 0xae, 0x19, 0x5a, 0xb1, 0x6d, 0x1f, 0x1a, 0x9d, 0x7c, 0x66, 0x77, 0x98, 0xa3, + 0xcd, 0x26, 0xb5, 0xa3, 0x8e, 0x26, 0x9c, 0xe5, 0xe3, 0x08, 0x7f, 0x66, 0x77, 0x69, 0xe9, 0xb6, 0x6e, 0xbc, 0xac, + 0xcd, 0x22, 0x46, 0xf2, 0x46, 0x44, 0xb8, 0xea, 0x24, 0x5d, 0x6d, 0xb0, 0x2c, 0xf8, 0x14, 0x70, 0xf4, 0x27, 0x76, + 0x97, 0xba, 0xf6, 0x02, 0x57, 0x41, 0xb4, 0xf2, 0xa0, 0x4f, 0x82, 0xe4, 0x70, 0x19, 0x9c, 0xc0, 0x31, 0x30, 0x75, + 0x87, 0xa4, 0x56, 0xae, 0x12, 0x21, 0x11, 0xda, 0xfc, 0xbb, 0x53, 0xc1, 0x8b, 0xf0, 0x9c, 0xd3, 0x35, 0x8b, 0xdb, + 0xad, 0x4a, 0x0c, 0x2a, 0x54, 0x16, 0x24, 0x1f, 0x62, 0xee, 0x77, 0x9f, 0xf3, 0x7e, 0x08, 0x74, 0x66, 0x0b, 0xea, + 0x1a, 0x4d, 0x27, 0xe6, 0x17, 0xaa, 0xee, 0xa0, 0xe6, 0xba, 0xaa, 0x78, 0xf0, 0x21, 0x06, 0xc0, 0x83, 0xb5, 0x0c, + 0x35, 0x0e, 0xa1, 0x1b, 0x6f, 0xa6, 0x3a, 0xa5, 0x24, 0x5e, 0xf9, 0x39, 0xa4, 0x3c, 0x04, 0xa3, 0xde, 0x00, 0x1a, + 0x3a, 0x04, 0xb3, 0x96, 0x87, 0x7c, 0x12, 0x8b, 0x9d, 0x33, 0x54, 0x9a, 0x33, 0x34, 0x09, 0x40, 0xfe, 0x95, 0x33, + 0x93, 0x19, 0x68, 0x18, 0xde, 0xd2, 0x1c, 0x80, 0x6e, 0x75, 0x1d, 0x0e, 0x85, 0x2b, 0x5a, 0x3a, 0xef, 0xd9, 0x45, + 0x97, 0xb5, 0x61, 0xc5, 0xa6, 0x1d, 0xb4, 0x49, 0x61, 0x4a, 0xcc, 0x16, 0xd8, 0x78, 0xbd, 0x0f, 0xf7, 0x76, 0xb5, + 0x71, 0x91, 0xf8, 0x69, 0x11, 0x0f, 0x93, 0x98, 0xa2, 0x15, 0x8f, 0x29, 0x96, 0x60, 0x07, 0x59, 0x6c, 0xca, 0xf1, + 0xb3, 0x70, 0x39, 0x6a, 0x56, 0xd2, 0xfb, 0x1d, 0x0c, 0x81, 0xcb, 0xd7, 0x60, 0x1b, 0x8a, 0x79, 0x49, 0x58, 0x62, + 0xe3, 0xe9, 0x17, 0xac, 0xdb, 0xdc, 0x2e, 0x88, 0x5f, 0x81, 0x29, 0x8d, 0x57, 0xc1, 0x2c, 0x42, 0xa7, 0x72, 0xe7, + 0x70, 0xe8, 0xae, 0x09, 0x2b, 0xe3, 0xd5, 0x58, 0x91, 0xad, 0xa3, 0xe7, 0xdb, 0x36, 0x9e, 0x7f, 0x2f, 0x59, 0x71, + 0x77, 0xcd, 0xc0, 0xc6, 0x5a, 0x82, 0xbb, 0x71, 0xb5, 0x0c, 0x95, 0x81, 0x7c, 0x5f, 0x1a, 0xd6, 0x65, 0x83, 0xbf, + 0x19, 0x15, 0x63, 0x63, 0xee, 0x29, 0x03, 0x6d, 0x8d, 0xdd, 0x2e, 0xec, 0xab, 0xae, 0x9b, 0xac, 0x67, 0x62, 0x25, + 0x54, 0x90, 0x76, 0x77, 0x0b, 0xb8, 0x08, 0xfd, 0x61, 0x07, 0x6a, 0xb8, 0xad, 0xba, 0x81, 0x24, 0xb8, 0xf6, 0x93, + 0x5f, 0x9f, 0xea, 0x3e, 0x6b, 0xdd, 0xaf, 0x4f, 0xb5, 0x76, 0x59, 0x68, 0x0c, 0x89, 0xb0, 0xeb, 0xa7, 0xf4, 0x9f, + 0x16, 0x9b, 0x0d, 0xda, 0xc0, 0xf0, 0xde, 0xf3, 0x5e, 0x1c, 0xbf, 0xf7, 0x16, 0x8a, 0x09, 0x5c, 0xe4, 0x5e, 0xe7, + 0xd2, 0x13, 0xf2, 0x6a, 0x04, 0xef, 0xf9, 0xce, 0x10, 0xde, 0xf3, 0xc0, 0xe9, 0x15, 0xa4, 0xa6, 0xa9, 0x60, 0x63, + 0x4f, 0x3f, 0x91, 0x45, 0x42, 0xc3, 0xc7, 0xdd, 0xe3, 0x44, 0xe8, 0xbf, 0x52, 0xe0, 0xbf, 0xf0, 0x68, 0xa9, 0xb5, + 0x14, 0x98, 0x8b, 0xc5, 0x52, 0x63, 0x65, 0x46, 0xbf, 0x9a, 0x48, 0xa1, 0x9b, 0x13, 0x3a, 0xe7, 0xf9, 0x5d, 0xba, + 0xe4, 0xcd, 0xb9, 0x14, 0x52, 0x2d, 0x68, 0xc6, 0xb0, 0xba, 0x53, 0x9a, 0xcd, 0x9b, 0x4b, 0x8e, 0x9f, 0xb3, 0xfc, + 0x0b, 0xd3, 0x3c, 0xa3, 0xf8, 0x8d, 0x1c, 0x49, 0x2d, 0xf1, 0xab, 0xdb, 0xbb, 0x29, 0x13, 0xf8, 0xdd, 0x68, 0x29, + 0xf4, 0x12, 0x2b, 0x2a, 0x54, 0x53, 0xb1, 0x82, 0x4f, 0x7a, 0xcd, 0xe6, 0xa2, 0xe0, 0x73, 0x5a, 0xdc, 0x35, 0x33, + 0x99, 0xcb, 0x22, 0xfd, 0xaf, 0xd6, 0x29, 0x7d, 0x30, 0x39, 0xeb, 0xe9, 0x82, 0x0a, 0xc5, 0x61, 0x61, 0x52, 0x9a, + 0xe7, 0x07, 0xa7, 0xdd, 0xd6, 0x5c, 0x1d, 0xda, 0x0b, 0x3f, 0x2a, 0xf4, 0xe6, 0x2f, 0xfc, 0x9b, 0x84, 0x51, 0x26, + 0x23, 0x2d, 0xdc, 0x20, 0x57, 0xd9, 0xb2, 0x50, 0xb2, 0x48, 0x17, 0x92, 0x0b, 0xcd, 0x8a, 0xde, 0x48, 0x16, 0x63, + 0x56, 0x34, 0x0b, 0x3a, 0xe6, 0x4b, 0x95, 0x9e, 0x2d, 0x6e, 0x7b, 0xf5, 0x1e, 0x6c, 0x7e, 0x2a, 0xa4, 0x60, 0x3d, + 0xe0, 0x37, 0xa6, 0x85, 0x5c, 0x8a, 0xb1, 0x1b, 0xc6, 0x52, 0x28, 0xa6, 0x7b, 0x0b, 0x3a, 0x06, 0x3b, 0xe0, 0xf4, + 0x62, 0x71, 0xdb, 0x33, 0xb3, 0xbe, 0x61, 0x7c, 0x3a, 0xd3, 0x69, 0xb7, 0xd5, 0xb2, 0xdf, 0x8a, 0xff, 0xc3, 0xd2, + 0x76, 0x27, 0xe9, 0x74, 0x17, 0xb7, 0xc0, 0xc1, 0x6b, 0x56, 0x34, 0x01, 0x16, 0x50, 0xa9, 0x9d, 0xb4, 0x1e, 0x9c, + 0xde, 0x87, 0x0c, 0xb0, 0x71, 0x68, 0x9a, 0x09, 0x81, 0xb1, 0x7b, 0xba, 0x5c, 0x2c, 0x58, 0x01, 0x5e, 0xf4, 0xbd, + 0x39, 0x2d, 0xa6, 0x5c, 0x34, 0x0b, 0xd3, 0x68, 0xf3, 0x62, 0x71, 0xbb, 0x81, 0xf9, 0xa4, 0xd6, 0x6c, 0xd5, 0x4d, + 0xcb, 0x7d, 0xad, 0x82, 0x21, 0x9a, 0x98, 0x34, 0x69, 0x31, 0x1d, 0xd1, 0xb8, 0xdd, 0xb9, 0x8f, 0xfd, 0xff, 0x92, + 0x0e, 0x0a, 0xc0, 0xd6, 0x1c, 0x2f, 0x0b, 0x73, 0x8b, 0x9a, 0xb6, 0x95, 0x6d, 0x76, 0x26, 0xbf, 0xb0, 0xc2, 0xb7, + 0x6a, 0x3e, 0x56, 0x3b, 0xf3, 0xfe, 0x8f, 0x1a, 0xa5, 0xb6, 0xad, 0x17, 0xea, 0x1a, 0x68, 0xf4, 0x6e, 0x63, 0xff, + 0xd5, 0xb9, 0xa0, 0xf7, 0xcf, 0xba, 0x1e, 0xee, 0x93, 0xc9, 0xa4, 0x06, 0x74, 0x0f, 0xdd, 0x76, 0x6b, 0x71, 0x7b, + 0xd0, 0x69, 0x79, 0x18, 0x5b, 0x98, 0x9e, 0x2f, 0x6e, 0xf7, 0xac, 0x60, 0x80, 0x15, 0xdb, 0xbd, 0x1d, 0x24, 0xa7, + 0xea, 0x80, 0x51, 0xc5, 0x36, 0x7f, 0xe1, 0x11, 0x05, 0xdc, 0x30, 0x48, 0x3b, 0x30, 0x72, 0x2a, 0xac, 0xc0, 0x70, + 0x75, 0xc3, 0xc7, 0x7a, 0x96, 0xb6, 0x5b, 0xad, 0xef, 0x2a, 0x4c, 0xea, 0xcd, 0xec, 0x92, 0xb6, 0x0b, 0x36, 0xaf, + 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0x76, + 0xa6, 0xcc, 0xc5, 0x8c, 0x15, 0x5c, 0xf7, 0xea, 0x5f, 0x55, 0xc7, 0xbb, 0x73, 0xda, 0x58, 0xf9, 0x78, 0x65, 0x6b, + 0xb8, 0xcb, 0xd8, 0xc7, 0xf0, 0xb1, 0x8b, 0x95, 0x5f, 0x68, 0x11, 0x6f, 0x6d, 0x18, 0x1c, 0xd6, 0x40, 0x9b, 0x60, + 0xce, 0x05, 0x98, 0x8a, 0x0e, 0xf1, 0x57, 0xa0, 0x90, 0xd1, 0x3c, 0x8b, 0x61, 0x44, 0x07, 0xcd, 0x83, 0xd3, 0x82, + 0xcd, 0x91, 0x07, 0x44, 0x72, 0xbf, 0x5b, 0xb0, 0xf9, 0x26, 0x31, 0xd5, 0x57, 0x06, 0x75, 0x69, 0xce, 0xa7, 0x22, + 0xcd, 0x18, 0x6c, 0xab, 0x4d, 0xc2, 0x84, 0xe6, 0xfa, 0xae, 0x59, 0xc8, 0x9b, 0xd5, 0x98, 0xab, 0x45, 0x4e, 0xef, + 0xd2, 0x49, 0xce, 0x6e, 0x7b, 0xa6, 0x54, 0x93, 0x6b, 0x36, 0x57, 0xae, 0x6c, 0x0f, 0xd2, 0x9b, 0x63, 0x6b, 0xce, + 0x01, 0xd0, 0x93, 0x37, 0xdb, 0xfb, 0xda, 0x2f, 0x5a, 0x53, 0x2e, 0xf5, 0x41, 0x4b, 0xf5, 0xe6, 0x5c, 0x34, 0xdd, + 0x40, 0xce, 0x00, 0x23, 0x76, 0x21, 0x1f, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, 0x36, 0x5e, 0x05, 0xd5, 0x3a, + 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x1b, 0xb4, 0xb8, 0x23, 0xd0, 0x57, 0x50, 0xfe, 0x41, 0x0b, 0xdb, + 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xae, 0x09, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, + 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, 0x2b, 0x98, 0x7f, 0xda, 0x3a, + 0x68, 0x1d, 0x98, 0xb9, 0xb8, 0x6d, 0x70, 0x76, 0x76, 0xff, 0xf4, 0x01, 0xeb, 0xe5, 0x5c, 0xb0, 0xda, 0x54, 0xbf, + 0x09, 0xea, 0xb0, 0xe1, 0x8e, 0x6b, 0xb8, 0x7d, 0xd0, 0x3e, 0x38, 0x6b, 0x7d, 0xe7, 0xa9, 0x48, 0xce, 0x26, 0xda, + 0xee, 0x9b, 0x1a, 0x59, 0xb9, 0xf0, 0x4d, 0xdf, 0x14, 0x74, 0x91, 0x0a, 0x09, 0x7f, 0x7a, 0xb0, 0xf9, 0x27, 0xb9, + 0xbc, 0x49, 0x67, 0x7c, 0x3c, 0x06, 0x17, 0x2e, 0x28, 0x50, 0x26, 0xb2, 0x3c, 0xe7, 0x0b, 0xc5, 0xed, 0x6a, 0x38, + 0xdc, 0xed, 0x6e, 0x41, 0x35, 0x1c, 0xd0, 0x69, 0x30, 0xa0, 0x6e, 0x35, 0xa0, 0xaa, 0xff, 0x70, 0x84, 0x9d, 0xad, + 0xb9, 0x9a, 0x52, 0xbd, 0x1a, 0x26, 0x7d, 0x5a, 0x2a, 0x0d, 0x30, 0xf7, 0xc6, 0x23, 0xe6, 0x74, 0x69, 0x8e, 0x98, + 0xbe, 0x61, 0x4c, 0x7c, 0x7d, 0x10, 0x57, 0xa9, 0x14, 0xf9, 0x9d, 0xfd, 0x5c, 0x85, 0x5d, 0xd2, 0xa5, 0x96, 0x9b, + 0x64, 0xc4, 0x05, 0x2d, 0xee, 0x3e, 0x2a, 0x26, 0x94, 0x2c, 0x3e, 0xca, 0xc9, 0x64, 0xf5, 0x35, 0x92, 0x77, 0x1f, + 0x6d, 0x12, 0xc5, 0xc5, 0x34, 0x67, 0x96, 0xc0, 0x19, 0x44, 0x70, 0x87, 0x8c, 0x6d, 0xd7, 0x34, 0x59, 0x1b, 0xf4, + 0x26, 0xc9, 0x72, 0x3e, 0xa7, 0x9a, 0x19, 0x38, 0x07, 0xa4, 0xc6, 0x4d, 0xde, 0x52, 0xb9, 0xd6, 0x81, 0xfd, 0x53, + 0x95, 0x86, 0x6d, 0x14, 0x14, 0xf6, 0x4d, 0x72, 0x61, 0xf0, 0xc3, 0x80, 0xc3, 0xec, 0x22, 0xb3, 0x7a, 0x66, 0xed, + 0x02, 0xd8, 0xc1, 0xec, 0x6a, 0x4d, 0x5d, 0x39, 0xba, 0x64, 0x5b, 0xec, 0xb6, 0xbe, 0xab, 0xe7, 0xe6, 0x74, 0xc4, + 0xf2, 0x95, 0xdd, 0xa8, 0x1e, 0xb8, 0x6e, 0xab, 0x86, 0xcb, 0x1c, 0x90, 0x0c, 0x03, 0xa2, 0x61, 0x9a, 0x36, 0x6f, + 0xd8, 0xe8, 0x33, 0xd7, 0x76, 0xcb, 0x34, 0xd5, 0x0d, 0x38, 0x15, 0x99, 0x31, 0x2d, 0x58, 0xb1, 0xf2, 0x84, 0xbc, + 0x55, 0x23, 0xa0, 0xbf, 0x08, 0x73, 0x40, 0x6b, 0x3a, 0x6a, 0x42, 0x88, 0x35, 0x56, 0xac, 0xf6, 0x4d, 0x6e, 0x4e, + 0x6f, 0x1d, 0x8a, 0x3d, 0x68, 0x7d, 0x57, 0x3b, 0x64, 0xcf, 0x5a, 0x2d, 0x7f, 0x44, 0x34, 0x6d, 0x8d, 0xb4, 0x9d, + 0x74, 0xd9, 0xbc, 0x4c, 0xd4, 0x72, 0x91, 0xd6, 0x12, 0x46, 0x52, 0x6b, 0x39, 0xb7, 0x69, 0x7b, 0xa8, 0x51, 0x9d, + 0xf4, 0xb6, 0x3b, 0x8b, 0xdb, 0x03, 0xf3, 0x4f, 0xeb, 0xa0, 0xb5, 0x4b, 0x6a, 0x77, 0xb1, 0xe2, 0x14, 0x79, 0x3c, + 0x86, 0x8e, 0xdb, 0x6c, 0xde, 0x5b, 0x2a, 0x38, 0xee, 0x0d, 0xc4, 0xcd, 0x89, 0xb6, 0x31, 0x93, 0x05, 0xc0, 0x52, + 0x2e, 0xe0, 0x74, 0xb5, 0x87, 0x1d, 0xf4, 0xa1, 0x24, 0x98, 0xc3, 0xef, 0x6d, 0xb4, 0x3e, 0xac, 0xd6, 0x41, 0x35, + 0x30, 0xf8, 0x67, 0xf3, 0x57, 0xc5, 0x9f, 0x3f, 0x61, 0x81, 0x7c, 0xc4, 0x1b, 0x49, 0x77, 0xdd, 0x72, 0x32, 0xd1, + 0x58, 0x57, 0xa2, 0x9a, 0xf1, 0x28, 0x99, 0xd3, 0x5b, 0xeb, 0x5a, 0x32, 0xe7, 0x02, 0x0c, 0xd7, 0x10, 0xd6, 0x81, + 0x89, 0xff, 0x2c, 0x6c, 0x68, 0xac, 0x63, 0x68, 0xf8, 0xb8, 0x93, 0x74, 0xbb, 0x08, 0xb7, 0x70, 0xa7, 0xdb, 0x0d, + 0x64, 0xb2, 0x89, 0xde, 0x57, 0x74, 0x5f, 0x49, 0xb9, 0xa7, 0xe4, 0x89, 0x69, 0xf4, 0xa4, 0xdd, 0x6a, 0x61, 0xe3, + 0x3e, 0x5f, 0x16, 0x16, 0x6a, 0x4f, 0xb3, 0xed, 0x56, 0x0b, 0x9a, 0x85, 0x3f, 0x6e, 0x5e, 0x3f, 0x91, 0x55, 0x2b, + 0x6d, 0xe1, 0x76, 0xda, 0xc6, 0x9d, 0xb4, 0x83, 0x4f, 0xd3, 0x53, 0x7c, 0x96, 0x9e, 0xe1, 0x6e, 0xda, 0xc5, 0xe7, + 0xe9, 0x39, 0xbe, 0x9f, 0xde, 0xc7, 0x17, 0xe9, 0x05, 0x7e, 0x90, 0x3e, 0xc0, 0x0f, 0xd3, 0x76, 0x0b, 0x3f, 0x4a, + 0xdb, 0x6d, 0xfc, 0x38, 0x6d, 0x77, 0xf0, 0x93, 0xb4, 0x7d, 0x8a, 0x9f, 0xa6, 0xed, 0x33, 0xfc, 0x2c, 0x6d, 0x77, + 0x31, 0x85, 0xdc, 0x11, 0xe4, 0x66, 0x90, 0x3b, 0x86, 0x5c, 0x06, 0xb9, 0x93, 0xb4, 0xdd, 0xdd, 0x60, 0x69, 0x43, + 0x6e, 0x44, 0xad, 0x76, 0xe7, 0xf4, 0xac, 0x7b, 0x7e, 0xff, 0xe2, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x7d, 0x16, + 0x0d, 0xf1, 0x9d, 0xf1, 0x7c, 0x91, 0x62, 0xc0, 0x8f, 0xda, 0xdd, 0x21, 0xbe, 0xf5, 0x9f, 0x31, 0x3f, 0xea, 0x9c, + 0xb5, 0xd0, 0xd5, 0xd5, 0xd9, 0xb0, 0x51, 0xe6, 0x3e, 0x32, 0x0e, 0x37, 0x55, 0x16, 0x21, 0x24, 0x86, 0x1c, 0x84, + 0xbf, 0x58, 0x07, 0x1a, 0x16, 0xf3, 0xa4, 0x40, 0x47, 0x47, 0xe6, 0xc7, 0xd4, 0xff, 0x18, 0xf9, 0x1f, 0x34, 0x58, + 0xa4, 0x1b, 0x1a, 0x3b, 0x8f, 0x6b, 0x5d, 0xfa, 0x3b, 0x94, 0xa6, 0x44, 0x07, 0xdc, 0x19, 0xf5, 0xff, 0x57, 0x64, + 0x8d, 0x76, 0xc8, 0x99, 0x55, 0x8c, 0x75, 0xfb, 0x8c, 0xac, 0x8a, 0xb4, 0xd3, 0xed, 0x1e, 0xfd, 0x34, 0xe0, 0x83, + 0xf6, 0x70, 0x78, 0xdc, 0xbe, 0x8f, 0xa7, 0x65, 0x42, 0xc7, 0x26, 0x8c, 0xca, 0x84, 0x53, 0x9b, 0x40, 0x53, 0x5b, + 0x1b, 0x92, 0xce, 0x4c, 0x12, 0x94, 0xd8, 0xa4, 0xa6, 0xed, 0xfb, 0xb6, 0xed, 0x07, 0x60, 0x4d, 0x66, 0x9a, 0x77, + 0x4d, 0x5f, 0x5e, 0x9e, 0xad, 0x5d, 0xa3, 0x78, 0x9a, 0xba, 0xd6, 0x7c, 0xe2, 0xd9, 0x70, 0x88, 0x47, 0x26, 0xb1, + 0x5b, 0x25, 0x9e, 0x0f, 0x87, 0xae, 0xab, 0x07, 0xa6, 0xab, 0xfb, 0x55, 0xd6, 0xc5, 0x70, 0x68, 0xba, 0x44, 0x2e, + 0x76, 0x80, 0xd2, 0x07, 0x9f, 0x4b, 0xfd, 0x0d, 0xbf, 0xec, 0x74, 0xbb, 0x7d, 0xc0, 0x30, 0x63, 0x13, 0xec, 0x61, + 0x74, 0x1d, 0xc0, 0xe8, 0x0b, 0xfc, 0xee, 0xdf, 0xd1, 0xf4, 0x96, 0x96, 0x40, 0xea, 0x47, 0xff, 0x15, 0x35, 0xb4, + 0x81, 0xb9, 0xf9, 0x33, 0xb5, 0x7f, 0x46, 0xa8, 0xf1, 0x99, 0x02, 0xb8, 0x41, 0x23, 0xe5, 0x55, 0xca, 0xa6, 0xc7, + 0x5f, 0x28, 0xb8, 0xf8, 0xcc, 0x54, 0x4e, 0xfb, 0xeb, 0xd9, 0xcd, 0x68, 0x3d, 0x53, 0x5f, 0xd0, 0x9f, 0xf1, 0x9f, + 0xea, 0x38, 0x1e, 0x34, 0x1b, 0x09, 0xfb, 0x73, 0x0c, 0xbe, 0x44, 0xfd, 0x74, 0xcc, 0xa6, 0xa8, 0x3f, 0xf8, 0x53, + 0xe1, 0x61, 0x23, 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0x50, 0x1f, 0xf5, 0xff, 0x54, + 0xc7, 0x7f, 0xa2, 0x7b, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x85, 0x1f, 0x3a, 0x2e, 0xb7, 0x30, 0xc3, 0xed, + 0x26, 0x83, 0x60, 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe0, 0x27, 0xa7, 0x2d, 0xf4, 0x5d, 0xbb, 0x03, 0xca, 0x95, + 0xa6, 0x38, 0xde, 0xdd, 0xf4, 0x45, 0xf3, 0x14, 0x3f, 0x68, 0x16, 0xb8, 0x8d, 0x70, 0xb3, 0xed, 0xb5, 0xde, 0x03, + 0x15, 0xb7, 0x10, 0x56, 0xf1, 0x05, 0xfc, 0x73, 0x86, 0x86, 0xd5, 0x86, 0x7c, 0x4c, 0xb7, 0x7b, 0x07, 0xbf, 0x59, + 0x12, 0xab, 0x06, 0x3f, 0x39, 0x6f, 0xa1, 0xef, 0xce, 0x4d, 0x47, 0xec, 0x58, 0xef, 0xe9, 0x4a, 0xe2, 0xb3, 0xa6, + 0x84, 0x8e, 0x5a, 0x65, 0x3f, 0x22, 0xee, 0x22, 0x2c, 0xe2, 0x53, 0xf8, 0xa7, 0x1d, 0xf6, 0x73, 0x6f, 0xa7, 0x1f, + 0x33, 0xef, 0x36, 0x4e, 0xba, 0xd6, 0x0d, 0x57, 0xd9, 0x3b, 0xf1, 0x06, 0xbb, 0x6a, 0x9b, 0xcb, 0xbc, 0xf6, 0x09, + 0x7c, 0x20, 0xac, 0x8f, 0x89, 0xc2, 0xec, 0x18, 0xfc, 0x77, 0xc1, 0x6c, 0x45, 0x5d, 0x9e, 0xf6, 0x54, 0xa3, 0x81, + 0xc4, 0x40, 0x0d, 0x8f, 0x49, 0xbb, 0xa9, 0x9b, 0x0c, 0xc3, 0xef, 0x06, 0x29, 0x83, 0xc2, 0x89, 0xaa, 0xd7, 0x57, + 0xae, 0x57, 0x7b, 0xf3, 0xef, 0xb1, 0x83, 0x10, 0xa2, 0xfa, 0xb1, 0x6e, 0x32, 0x74, 0x22, 0x1a, 0xb1, 0xbe, 0x64, + 0xfd, 0xf3, 0xb4, 0x85, 0x0c, 0x76, 0xaa, 0x7e, 0xcc, 0x9a, 0x1c, 0xd2, 0x3b, 0x69, 0xcc, 0x9b, 0x1a, 0x7e, 0x9d, + 0x05, 0xd0, 0x12, 0x80, 0x77, 0x95, 0x37, 0x52, 0x71, 0xd2, 0xe9, 0x76, 0xb1, 0x20, 0x3c, 0x99, 0x9a, 0x5f, 0x8a, + 0xf0, 0x64, 0x64, 0x7e, 0x49, 0x52, 0xc2, 0xcb, 0xf6, 0x8e, 0x0b, 0x12, 0xac, 0xaa, 0x49, 0xa1, 0xb0, 0xa0, 0x05, + 0x3a, 0xe9, 0x78, 0xb3, 0x00, 0x3c, 0xf3, 0x73, 0x00, 0x35, 0x48, 0x61, 0x2c, 0x42, 0x65, 0xb3, 0xc0, 0x39, 0xa1, + 0x57, 0x49, 0xb7, 0x3f, 0x3b, 0x89, 0x3b, 0x4d, 0xd9, 0x2c, 0x50, 0x3a, 0x3b, 0x31, 0x35, 0x71, 0x46, 0x5e, 0x51, + 0xdb, 0x1a, 0x9e, 0xc1, 0x5d, 0x6e, 0x46, 0xb2, 0xe3, 0xf3, 0x56, 0x23, 0xe9, 0x22, 0x3c, 0xc8, 0xd6, 0x2d, 0x9c, + 0xaf, 0xd7, 0x2d, 0x4c, 0xc3, 0x65, 0x10, 0x1e, 0x20, 0xa5, 0xa6, 0x6e, 0x3b, 0x36, 0x4f, 0x9f, 0xc7, 0x1a, 0xec, + 0x12, 0x34, 0x78, 0xfb, 0x68, 0xf0, 0x43, 0x4a, 0xb9, 0xbb, 0x10, 0x44, 0x26, 0x3a, 0xe1, 0x24, 0xd4, 0xdd, 0xbd, + 0x12, 0x7e, 0x5d, 0xdd, 0xc8, 0xef, 0x89, 0xf8, 0x83, 0xc4, 0x36, 0xad, 0x2a, 0xf6, 0x9a, 0xee, 0x16, 0xbb, 0x47, + 0x77, 0x8a, 0x3d, 0xdc, 0x53, 0xec, 0xf1, 0x6e, 0xb1, 0xbf, 0x65, 0xa0, 0x69, 0xe4, 0xdf, 0x9d, 0x9e, 0xb7, 0x1a, + 0xa7, 0x80, 0xac, 0xa7, 0xe7, 0xad, 0xaa, 0xd0, 0x53, 0x5a, 0xad, 0x95, 0x26, 0xbf, 0x50, 0xeb, 0x6b, 0xc1, 0xbd, + 0xd3, 0xb7, 0x59, 0x38, 0xeb, 0x72, 0x5e, 0xfa, 0x97, 0x0f, 0xba, 0x60, 0xcb, 0x22, 0x0c, 0xb5, 0xd3, 0x83, 0xf3, + 0x61, 0x7f, 0xc6, 0xe2, 0x06, 0xa4, 0xa2, 0x74, 0xa2, 0xdd, 0x2f, 0x54, 0x5e, 0x69, 0xff, 0x2d, 0x21, 0xa9, 0x33, + 0x44, 0x58, 0x92, 0x86, 0x1e, 0x9c, 0x0e, 0xcd, 0x79, 0x57, 0xc0, 0xef, 0x33, 0xf3, 0xbb, 0x54, 0x28, 0x39, 0x87, + 0x8c, 0xd9, 0xcd, 0x28, 0xea, 0x0b, 0xf2, 0x9a, 0xc6, 0xc6, 0xc6, 0x1e, 0xa5, 0x65, 0x86, 0xfa, 0x02, 0x19, 0x0f, + 0xcb, 0x0c, 0x41, 0x5e, 0x09, 0xf7, 0x1b, 0xaf, 0x8a, 0x14, 0xec, 0x6d, 0xf0, 0x34, 0x05, 0x5b, 0x1b, 0x3c, 0x4a, + 0x05, 0xf8, 0x83, 0xd0, 0x94, 0x05, 0x56, 0xfc, 0x2f, 0x9c, 0x06, 0xcf, 0xdc, 0x3a, 0x13, 0x83, 0xa5, 0x3d, 0x06, + 0x27, 0xc5, 0xdf, 0x32, 0x86, 0xbf, 0x0d, 0x8d, 0x30, 0x83, 0x36, 0x19, 0xc2, 0x3c, 0x29, 0x08, 0xa4, 0x61, 0x9e, + 0x4c, 0x09, 0x83, 0x26, 0x79, 0x32, 0x22, 0x6c, 0xd0, 0x09, 0xd0, 0xe4, 0x89, 0x81, 0x1d, 0x00, 0x87, 0xd7, 0x2f, + 0xf2, 0xb5, 0x6d, 0x1c, 0x2c, 0x04, 0xa0, 0x09, 0x41, 0x20, 0xe6, 0xc2, 0x00, 0xcc, 0x46, 0x94, 0xfd, 0xd9, 0xa9, + 0xc2, 0x5f, 0xf2, 0x84, 0x1a, 0xea, 0xfd, 0x17, 0x90, 0xd5, 0xf8, 0xde, 0x8a, 0x6d, 0xf0, 0xc1, 0xbd, 0x95, 0xd8, + 0x7c, 0x07, 0x7f, 0x94, 0xfd, 0x03, 0xcc, 0x43, 0x42, 0xd1, 0x06, 0xfd, 0x95, 0x42, 0xb1, 0x3d, 0xa5, 0xd0, 0x5f, + 0x8e, 0x44, 0x2b, 0x45, 0x56, 0xb7, 0x69, 0x34, 0xa6, 0xc5, 0xe7, 0x08, 0xff, 0x91, 0x46, 0x39, 0x70, 0x8b, 0x11, + 0xfe, 0x90, 0x46, 0x05, 0x8b, 0xf0, 0xef, 0x69, 0x34, 0xca, 0x97, 0x11, 0xfe, 0x2d, 0x8d, 0xa6, 0x45, 0x84, 0xdf, + 0x83, 0xb2, 0x76, 0xcc, 0x97, 0xf3, 0x08, 0xbf, 0x4b, 0x23, 0x65, 0xbc, 0x21, 0xf0, 0xc3, 0x34, 0x62, 0x2c, 0xc2, + 0x6f, 0xd3, 0x48, 0xe6, 0x11, 0xbe, 0x4e, 0x23, 0x59, 0x44, 0xf8, 0x51, 0x1a, 0x15, 0x34, 0xc2, 0x8f, 0xd3, 0x08, + 0x0a, 0x4d, 0x23, 0xfc, 0x24, 0x8d, 0xa0, 0x65, 0x15, 0xe1, 0x37, 0x69, 0xc4, 0x45, 0x84, 0x7f, 0x4d, 0x23, 0xbd, + 0x2c, 0xfe, 0x5e, 0x4a, 0xae, 0x22, 0xfc, 0x34, 0x8d, 0x66, 0x3c, 0xc2, 0xaf, 0xd3, 0xa8, 0x90, 0x11, 0x7e, 0x95, + 0x46, 0x34, 0x8f, 0xf0, 0xcb, 0x34, 0xca, 0x59, 0x84, 0x7f, 0x49, 0xa3, 0x31, 0x8b, 0xf0, 0xcf, 0x69, 0x74, 0xc7, + 0xf2, 0x5c, 0x46, 0xf8, 0x59, 0x1a, 0x31, 0x11, 0xe1, 0x9f, 0xd2, 0x28, 0x9b, 0x45, 0xf8, 0x87, 0x34, 0xa2, 0xc5, + 0x67, 0x15, 0xe1, 0xe7, 0x69, 0xc4, 0x68, 0x84, 0x5f, 0xd8, 0x8e, 0xa6, 0x11, 0xfe, 0x31, 0x8d, 0x6e, 0x66, 0xd1, + 0x06, 0x4b, 0x45, 0x56, 0xaf, 0x78, 0xc6, 0x7e, 0x67, 0x69, 0x34, 0x69, 0x4d, 0x2e, 0x26, 0x93, 0x08, 0x53, 0xa1, + 0xf9, 0xdf, 0x4b, 0x76, 0xf3, 0x54, 0x43, 0x22, 0x65, 0xa3, 0xf1, 0xfd, 0x08, 0xd3, 0xbf, 0x97, 0x34, 0x8d, 0x26, + 0x13, 0x53, 0xe0, 0xef, 0x25, 0x9d, 0xd3, 0xe2, 0x0d, 0x4b, 0xa3, 0xfb, 0x93, 0xc9, 0x64, 0x7c, 0x16, 0x61, 0xfa, + 0xcf, 0xf2, 0x83, 0x69, 0xc1, 0x14, 0x18, 0x31, 0x3e, 0x85, 0xba, 0xdd, 0x49, 0x77, 0x9c, 0x45, 0x78, 0xc4, 0xd5, + 0xdf, 0x4b, 0xf8, 0x9e, 0xb0, 0xb3, 0xec, 0x2c, 0xc2, 0xa3, 0x9c, 0x66, 0x9f, 0xd3, 0xa8, 0x65, 0x7e, 0x89, 0x9f, + 0xd8, 0xf8, 0xd5, 0x5c, 0x9a, 0xab, 0x8c, 0x09, 0x1b, 0x65, 0xe3, 0x08, 0x9b, 0xc1, 0x4c, 0xe0, 0xef, 0x17, 0xfe, + 0x96, 0xe9, 0x34, 0xba, 0xa0, 0x9d, 0x11, 0xeb, 0x44, 0x78, 0xf4, 0xfa, 0x46, 0xa4, 0x11, 0xed, 0x76, 0x68, 0x87, + 0x46, 0x78, 0xb4, 0x2c, 0xf2, 0xbb, 0x1b, 0x29, 0xc7, 0x00, 0x84, 0xd1, 0xc5, 0xc5, 0xfd, 0x08, 0x67, 0xf4, 0x17, + 0x0d, 0xb5, 0xbb, 0x93, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x13, 0x2d, 0xf4, 0x87, 0xa5, 0x72, 0x03, 0x6d, 0x41, 0x8a, + 0xcc, 0xde, 0x82, 0x9a, 0x3f, 0x1a, 0x77, 0xce, 0x1f, 0xb4, 0x59, 0x84, 0xb3, 0xeb, 0x57, 0xd0, 0xdb, 0xfd, 0x49, + 0xb7, 0x05, 0x1f, 0x02, 0xe4, 0x52, 0x56, 0x40, 0x23, 0xe7, 0x67, 0x0f, 0xba, 0x6c, 0x6c, 0x12, 0x15, 0xcf, 0x3f, + 0x9b, 0xd9, 0x5f, 0xc0, 0x7c, 0xb2, 0x82, 0xcf, 0x95, 0x14, 0x69, 0x34, 0xce, 0xda, 0x67, 0xa7, 0x90, 0x70, 0x47, + 0x85, 0x07, 0xce, 0x2d, 0x54, 0xbd, 0x18, 0x45, 0xf8, 0xd6, 0xa6, 0x5e, 0x8c, 0xcc, 0xc7, 0xf4, 0xed, 0x2f, 0xe2, + 0xf5, 0x38, 0x8d, 0x46, 0x17, 0x17, 0xe7, 0x2d, 0x48, 0xf8, 0x8d, 0xde, 0xa5, 0x11, 0x7d, 0x00, 0xff, 0x41, 0xf6, + 0x87, 0x67, 0xd0, 0x21, 0x8c, 0xf0, 0x76, 0xfa, 0x21, 0xcc, 0xf9, 0x3c, 0xa3, 0x9f, 0x79, 0x1a, 0x8d, 0xc6, 0xa3, + 0xfb, 0xe7, 0x50, 0x6f, 0x4e, 0xa7, 0xcf, 0x34, 0x85, 0x76, 0x5b, 0x2d, 0xd3, 0xf2, 0x5b, 0xfe, 0x85, 0x99, 0xea, + 0xdd, 0xee, 0xf9, 0xa8, 0x03, 0x23, 0xb8, 0x06, 0x85, 0x0a, 0x8c, 0xe7, 0x22, 0x33, 0x0d, 0x5e, 0x67, 0x4f, 0xc7, + 0x69, 0xf4, 0xe0, 0xc1, 0x69, 0x27, 0xcb, 0x22, 0x7c, 0xfb, 0x61, 0x6c, 0x6b, 0x9b, 0x3c, 0x05, 0xb0, 0x4f, 0x23, + 0xf6, 0xe0, 0xc1, 0xf9, 0x7d, 0x0a, 0xdf, 0xcf, 0x4d, 0x5b, 0x17, 0x93, 0x51, 0x76, 0x01, 0x6d, 0xbd, 0x83, 0xe9, + 0x9c, 0x5d, 0x9c, 0x8e, 0x4d, 0x5f, 0xef, 0xcc, 0xa8, 0x3b, 0x93, 0xb3, 0xc9, 0x99, 0xc9, 0x34, 0x43, 0x2d, 0x3f, + 0x7f, 0x65, 0x69, 0x94, 0xb1, 0x71, 0x3b, 0xc2, 0xb7, 0x6e, 0xe1, 0x1e, 0x9c, 0xb5, 0x5a, 0xe3, 0xd3, 0x08, 0x8f, + 0x1f, 0x2e, 0x16, 0x6f, 0x0c, 0x04, 0xdb, 0x67, 0x0f, 0xec, 0xb7, 0xfa, 0x7c, 0x07, 0x4d, 0x8f, 0x0c, 0xd0, 0xc6, + 0x7c, 0x6e, 0x5a, 0x3e, 0x7f, 0x00, 0xff, 0x99, 0x6f, 0xd3, 0x74, 0xf9, 0x2d, 0xc7, 0x53, 0xbb, 0x28, 0x6d, 0xf6, + 0xa0, 0x05, 0x35, 0x26, 0xfc, 0xc3, 0xa8, 0xe0, 0x80, 0x46, 0xa3, 0x0e, 0xfc, 0x5f, 0x84, 0x27, 0xf9, 0xf5, 0x2b, + 0x87, 0xb3, 0x93, 0x09, 0x9d, 0xb4, 0x22, 0x3c, 0x91, 0x1f, 0x94, 0xfe, 0xed, 0xa1, 0x48, 0xa3, 0x4e, 0xe7, 0x62, + 0x64, 0xca, 0x2c, 0x7f, 0x52, 0xdc, 0xe0, 0x71, 0xcb, 0xb4, 0x32, 0xa5, 0x6f, 0xd4, 0xe8, 0x5a, 0xc2, 0x4a, 0xc2, + 0x7f, 0x11, 0x9e, 0x82, 0x16, 0xce, 0xb5, 0x72, 0x61, 0xb7, 0xc3, 0xf4, 0xad, 0x41, 0xcd, 0xf1, 0x7d, 0x80, 0x97, + 0x5f, 0xc6, 0x31, 0xa5, 0xdd, 0x4e, 0x2b, 0xc2, 0x66, 0xd4, 0x17, 0x2d, 0xf8, 0x2f, 0xc2, 0x16, 0x72, 0x06, 0xae, + 0xd3, 0x0f, 0xcf, 0x7e, 0xbe, 0x49, 0x23, 0x3a, 0x9e, 0x4c, 0x60, 0x49, 0xcc, 0x64, 0x7c, 0xb1, 0x99, 0x14, 0xec, + 0xee, 0x97, 0x1b, 0xb7, 0x5d, 0x4c, 0x82, 0x76, 0xd0, 0x39, 0x7f, 0x30, 0x3a, 0x8b, 0xf0, 0x9b, 0x31, 0xa7, 0x02, + 0x56, 0x29, 0x1b, 0x77, 0xb3, 0x6e, 0x66, 0x12, 0xa6, 0x32, 0x8d, 0xce, 0x60, 0xc9, 0x3b, 0x11, 0xe6, 0x5f, 0xae, + 0xef, 0x2c, 0xba, 0x41, 0x6d, 0x87, 0x20, 0x93, 0x16, 0x3b, 0xbf, 0xc8, 0x22, 0x9c, 0xd3, 0x2f, 0xcf, 0x7e, 0x29, + 0xd2, 0x88, 0x9d, 0xb3, 0xf3, 0x09, 0xf5, 0xdf, 0xbf, 0xab, 0x99, 0xa9, 0xd1, 0x9a, 0x74, 0x21, 0xe9, 0x46, 0x98, + 0xb1, 0xde, 0xcf, 0x26, 0x06, 0x43, 0x5e, 0xce, 0xa5, 0xc8, 0x9e, 0x4e, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, + 0x07, 0x40, 0x9b, 0x8e, 0xc7, 0x17, 0xec, 0x3c, 0xc2, 0x7f, 0xd8, 0x5d, 0xe2, 0x26, 0xf0, 0x87, 0xc5, 0x6c, 0xe6, + 0x76, 0xfb, 0x1f, 0x16, 0x28, 0x30, 0xdf, 0x09, 0x9d, 0xd0, 0x71, 0x27, 0xc2, 0x7f, 0x18, 0xb8, 0x8c, 0x4f, 0xe1, + 0x3f, 0x28, 0x00, 0x9d, 0x3d, 0x68, 0x31, 0xf6, 0xa0, 0x65, 0xbe, 0xc2, 0x3c, 0x37, 0xf3, 0xd1, 0x79, 0xd6, 0x8e, + 0xf0, 0x1f, 0x0e, 0x1d, 0x27, 0x13, 0xda, 0x02, 0x74, 0xfc, 0xc3, 0xa1, 0x63, 0xa7, 0x35, 0xea, 0x50, 0xf3, 0x6d, + 0xb1, 0xe6, 0xe2, 0x7e, 0xc6, 0x60, 0x72, 0x7f, 0x58, 0x84, 0xbc, 0x7f, 0xff, 0xe2, 0xe2, 0xc1, 0x03, 0xf8, 0x34, + 0x6d, 0x97, 0x9f, 0x4a, 0x3f, 0xcc, 0x0d, 0x92, 0xb5, 0xb2, 0x33, 0xa0, 0x93, 0x7f, 0x98, 0x31, 0x4e, 0x26, 0x13, + 0xd6, 0x8a, 0x70, 0xce, 0xe7, 0xcc, 0x62, 0x82, 0xfd, 0x6d, 0x3a, 0x3a, 0xed, 0x64, 0xe3, 0xd3, 0x4e, 0x84, 0xf3, + 0x37, 0xcf, 0xcc, 0x6c, 0x5a, 0x30, 0x7b, 0xbf, 0xe5, 0x3c, 0xd6, 0xcc, 0xe9, 0x6b, 0x18, 0x24, 0xac, 0x34, 0x54, + 0x7e, 0x1f, 0xd0, 0xc3, 0xf3, 0xf3, 0x6c, 0x0c, 0x03, 0x7d, 0x0f, 0xdd, 0x02, 0x18, 0xdf, 0xdb, 0xcd, 0x37, 0xa2, + 0xdd, 0x2e, 0x4c, 0xf7, 0xfd, 0x62, 0x59, 0x2c, 0x5e, 0xa6, 0xd1, 0x83, 0xd3, 0xfb, 0xad, 0xf1, 0x28, 0xc2, 0xef, + 0xdd, 0x04, 0x4f, 0xb3, 0xd1, 0xe9, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, 0x7f, 0x74, 0x7e, 0x01, 0xe7, 0xc6, + 0x7b, 0xb5, 0x28, 0xde, 0x4c, 0x4d, 0x81, 0x09, 0x7d, 0x00, 0xcd, 0xfe, 0x6a, 0x76, 0xe3, 0xb8, 0x0d, 0x1b, 0xf9, + 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0xbb, 0x17, 0xdd, 0x08, 0xcf, 0xf9, 0x58, 0x00, 0x81, 0x37, 0x1b, 0xe5, + 0x41, 0xfb, 0xc1, 0xfd, 0x56, 0x84, 0xe7, 0x6f, 0x74, 0xf6, 0x81, 0xce, 0x0d, 0x35, 0x9e, 0x00, 0xcc, 0xe6, 0x5c, + 0xe9, 0xbb, 0xd7, 0xca, 0xd1, 0x63, 0xd6, 0x8e, 0xf0, 0x5c, 0x66, 0x19, 0x55, 0x6f, 0x6c, 0xc2, 0xa8, 0x1b, 0x61, + 0x41, 0xbf, 0xd0, 0x4f, 0xd2, 0x6f, 0xa6, 0x31, 0xa3, 0x63, 0x93, 0x66, 0x70, 0x38, 0xc2, 0x6f, 0xc7, 0x70, 0x19, + 0x99, 0x46, 0x93, 0xf1, 0xa4, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb1, 0x1b, 0xa0, 0x01, 0x5f, 0xe3, 0x47, 0xa3, 0x34, + 0x3a, 0x1f, 0x5d, 0xb0, 0xce, 0x69, 0x84, 0x4b, 0x6a, 0x44, 0xbb, 0x90, 0x6f, 0x3e, 0x3f, 0x98, 0x2d, 0x75, 0x66, + 0x13, 0x0c, 0x80, 0xc6, 0xf4, 0x7e, 0x6b, 0x7c, 0x1e, 0xe1, 0xc5, 0x2b, 0xe6, 0xf7, 0x18, 0x63, 0xec, 0x02, 0x60, + 0x09, 0x49, 0x06, 0x81, 0x2e, 0x26, 0xa3, 0x07, 0x17, 0xe6, 0x1b, 0xc0, 0x40, 0x27, 0x8c, 0x01, 0x90, 0x16, 0xaf, + 0x58, 0x09, 0x88, 0xf1, 0xe8, 0x7e, 0x0b, 0xe8, 0xcb, 0x82, 0x2e, 0xe8, 0x1d, 0xbd, 0x79, 0xba, 0x30, 0x73, 0x9a, + 0x8c, 0xbb, 0x11, 0x5e, 0x3c, 0xff, 0x69, 0xb1, 0x9c, 0x4c, 0xcc, 0x84, 0xe8, 0xe8, 0x41, 0x84, 0x17, 0xac, 0x58, + 0xc2, 0x1a, 0x5d, 0x74, 0x4f, 0x27, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, 0x11, 0xdc, 0xb6, 0x2e, 0xe7, 0x69, 0x34, + 0x1e, 0xd3, 0xd6, 0x18, 0xee, 0x5e, 0xe5, 0xcd, 0x2f, 0x85, 0x45, 0x23, 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, + 0xe0, 0xf1, 0x61, 0xc4, 0xb2, 0x8c, 0xba, 0xc4, 0xf3, 0xf3, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0xaf, + 0xd5, 0xdd, 0xa8, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xfa, 0xee, 0x95, 0xa1, 0xab, 0xed, 0xf3, 0x07, + 0xb0, 0x00, 0x8a, 0x8e, 0xc7, 0x2f, 0xed, 0xe1, 0x76, 0x31, 0x3a, 0xeb, 0xb6, 0x4f, 0x23, 0xec, 0x37, 0x02, 0xbd, + 0x68, 0xdd, 0xef, 0x40, 0x09, 0x31, 0xbe, 0xb3, 0x25, 0x26, 0x67, 0xf4, 0xec, 0xbc, 0x15, 0x61, 0xbf, 0x35, 0xd8, + 0xc5, 0xa8, 0x7b, 0x1f, 0x3e, 0xd5, 0x8c, 0xe5, 0xb9, 0xc1, 0xef, 0x2e, 0xc0, 0x45, 0xf1, 0x67, 0x82, 0xa6, 0x11, + 0x6d, 0x75, 0x3b, 0x9d, 0x31, 0x7c, 0xe6, 0x5f, 0x58, 0x91, 0x46, 0x59, 0x0b, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, + 0x28, 0xc2, 0x06, 0xef, 0xce, 0x69, 0xd7, 0xec, 0x7d, 0xb7, 0xab, 0x5a, 0x17, 0x2d, 0xd8, 0xb0, 0x6e, 0x53, 0xb9, + 0x2f, 0x25, 0xe4, 0x8d, 0x23, 0xb1, 0x34, 0xc2, 0x01, 0x82, 0x4e, 0xee, 0x4f, 0x22, 0xec, 0x77, 0xdc, 0xd9, 0xf9, + 0x45, 0x07, 0x48, 0x99, 0x06, 0x42, 0x31, 0xee, 0x8c, 0xce, 0x80, 0x34, 0x69, 0xf6, 0xca, 0xe2, 0x49, 0x84, 0xf5, + 0x53, 0xa5, 0x5f, 0xa6, 0xd1, 0xf8, 0x62, 0x34, 0x19, 0x5f, 0x44, 0x58, 0xcb, 0x39, 0xd5, 0xd2, 0x50, 0xc0, 0xd3, + 0xb3, 0xfb, 0x11, 0x36, 0x68, 0xde, 0x62, 0xad, 0x71, 0x2b, 0xc2, 0xee, 0x28, 0x61, 0xec, 0xa2, 0x03, 0xd3, 0xfa, + 0xf1, 0xb9, 0x06, 0x5c, 0x1e, 0xb3, 0xd1, 0x69, 0x84, 0x4b, 0x7a, 0x6f, 0x08, 0x11, 0x7c, 0xa9, 0xb9, 0xfc, 0xec, + 0x58, 0x0f, 0x20, 0x75, 0x7e, 0xc3, 0xc3, 0x32, 0xfc, 0x7c, 0x63, 0xd1, 0x88, 0x9a, 0x2d, 0x1e, 0xdc, 0x46, 0xbf, + 0xa5, 0xb1, 0x67, 0xdb, 0x39, 0x59, 0x6d, 0x70, 0x19, 0xe4, 0xf5, 0x33, 0xbb, 0x53, 0xb1, 0x54, 0x86, 0x93, 0x0d, + 0x52, 0x94, 0x42, 0xde, 0xad, 0xc1, 0x79, 0xae, 0x82, 0x20, 0x29, 0x48, 0xab, 0x27, 0x2e, 0xbd, 0x37, 0x6d, 0x4f, + 0x40, 0xe8, 0x07, 0x48, 0x2f, 0x08, 0x25, 0x1a, 0x22, 0xe4, 0x58, 0x61, 0xd2, 0x3b, 0x19, 0x18, 0x99, 0x52, 0x5a, + 0xb7, 0x05, 0x4a, 0xa8, 0x8f, 0x8d, 0x1f, 0x4b, 0xac, 0x20, 0x7a, 0x14, 0xea, 0x49, 0x62, 0x22, 0x5d, 0xbf, 0x10, + 0x3a, 0x96, 0x6a, 0x50, 0x0c, 0x71, 0xfb, 0x1c, 0x61, 0x88, 0x21, 0x41, 0x06, 0xf2, 0xea, 0xaa, 0x7d, 0x7e, 0x64, + 0x84, 0xbe, 0xab, 0xab, 0x0b, 0xfb, 0x03, 0xfe, 0x1d, 0x56, 0x71, 0xbb, 0x61, 0x7c, 0xef, 0x59, 0x35, 0xc7, 0x9f, + 0x0d, 0x7f, 0xfd, 0x9e, 0xad, 0xd7, 0xf1, 0x7b, 0x46, 0x60, 0xc6, 0xf8, 0x3d, 0x4b, 0xcc, 0x1d, 0x89, 0xf5, 0x10, + 0x22, 0x03, 0xd0, 0x9c, 0xb5, 0x30, 0x44, 0x93, 0xf7, 0x9c, 0xf7, 0x7b, 0x36, 0xe0, 0x75, 0xef, 0xf2, 0x2a, 0x84, + 0xf3, 0xd1, 0xd1, 0xaa, 0x48, 0xb5, 0x15, 0x13, 0xb4, 0x15, 0x13, 0xb4, 0x15, 0x13, 0x74, 0x15, 0x44, 0xff, 0xac, + 0x0f, 0x52, 0x8a, 0x51, 0xb6, 0x38, 0x9e, 0xfa, 0x0d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, + 0x62, 0xaf, 0x02, 0x63, 0x6f, 0xa2, 0xd3, 0x76, 0x9c, 0xfc, 0x3b, 0xea, 0x8e, 0x67, 0x35, 0xb1, 0xec, 0xcd, 0x5e, + 0xb1, 0x0c, 0x56, 0xd2, 0x88, 0x66, 0x87, 0x36, 0x1e, 0x89, 0x1e, 0xdc, 0x37, 0x82, 0x59, 0x15, 0x24, 0xaf, 0x01, + 0x49, 0x3d, 0x90, 0x42, 0x2e, 0x8c, 0x94, 0x56, 0xa0, 0x74, 0xac, 0xe3, 0x02, 0x34, 0x94, 0x5e, 0x41, 0x59, 0xc6, + 0x72, 0x6d, 0x18, 0x80, 0x28, 0x2b, 0xa3, 0x59, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0x8c, 0xc4, 0x02, 0x0d, + 0x08, 0xd3, 0x80, 0x70, 0x95, 0x41, 0x9c, 0x71, 0xd9, 0x67, 0x26, 0x5b, 0x99, 0x6c, 0x55, 0x66, 0x4b, 0x9f, 0x6d, + 0x85, 0x44, 0x69, 0xb2, 0x65, 0x99, 0x0d, 0x32, 0x1b, 0x9e, 0xa6, 0x0a, 0x8f, 0x52, 0x69, 0x45, 0xb5, 0x4a, 0xb6, + 0x7a, 0x49, 0x43, 0x6d, 0xee, 0xd1, 0x51, 0x5c, 0xca, 0x49, 0x46, 0x4d, 0x7c, 0x6f, 0xc5, 0x93, 0xc2, 0xc8, 0x40, + 0x3c, 0x99, 0xba, 0xbf, 0xa3, 0xcd, 0xb6, 0xac, 0x54, 0x4c, 0x47, 0x5f, 0x29, 0x89, 0xfe, 0xf2, 0x4a, 0xd4, 0xe7, + 0xdc, 0x44, 0x01, 0xba, 0x24, 0x49, 0xab, 0x75, 0xda, 0x3e, 0x6d, 0x5d, 0xf4, 0xf9, 0x71, 0xbb, 0x93, 0x3c, 0xe8, + 0xa4, 0x46, 0x11, 0xb1, 0x90, 0x37, 0xa0, 0x80, 0x39, 0xe9, 0x24, 0x67, 0xe8, 0xb8, 0x9d, 0xb4, 0xba, 0xdd, 0x26, + 0xfc, 0x83, 0x1f, 0xe9, 0xb2, 0xda, 0x59, 0xeb, 0xac, 0xdb, 0xe7, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x80, 0x82, 0xe8, + 0xc4, 0x54, 0xc2, 0x50, 0xbf, 0x5a, 0xde, 0x7f, 0x76, 0xf4, 0x3c, 0x8f, 0x74, 0x2c, 0xad, 0x2a, 0x0e, 0xa0, 0xea, + 0xbf, 0xa6, 0x06, 0x88, 0xfe, 0x6b, 0x54, 0x46, 0xea, 0x5d, 0x15, 0x20, 0x6a, 0x3f, 0xe7, 0xb1, 0x68, 0xb0, 0xe3, + 0xd8, 0xe6, 0x6b, 0xa8, 0xdb, 0x84, 0xe8, 0x79, 0x78, 0xea, 0x72, 0x55, 0x98, 0x3b, 0x45, 0xa8, 0xa9, 0x20, 0x77, + 0xe4, 0x72, 0x65, 0x98, 0x3b, 0x42, 0xa8, 0x29, 0x21, 0x97, 0xa6, 0x3c, 0xa1, 0x90, 0xa3, 0x13, 0xda, 0x34, 0x90, + 0xac, 0x16, 0xe5, 0x39, 0xf3, 0xc3, 0xe6, 0x13, 0x58, 0x1e, 0x43, 0x50, 0x9c, 0x20, 0x2d, 0xe0, 0x85, 0x95, 0x52, + 0x9b, 0xd3, 0xc2, 0xa5, 0x1a, 0x07, 0x32, 0x1a, 0xf0, 0xcf, 0x31, 0x33, 0xcf, 0x6e, 0xb4, 0xfa, 0xa7, 0xe7, 0xad, + 0xb4, 0x0d, 0xae, 0xe2, 0x20, 0x6b, 0x0b, 0x2b, 0x6b, 0x0b, 0x2f, 0x6b, 0x0b, 0x2f, 0x6b, 0x83, 0x00, 0x1f, 0xf4, + 0xfd, 0xbb, 0xac, 0x99, 0xdf, 0xf0, 0xd2, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, + 0xac, 0x51, 0xa8, 0x4a, 0xfd, 0xb9, 0x2a, 0xd2, 0x16, 0x9e, 0xa6, 0xa0, 0xe5, 0x6e, 0x61, 0x6a, 0x36, 0xb7, 0xa7, + 0x0a, 0xdb, 0x51, 0x7c, 0xfa, 0x5e, 0x9d, 0x7c, 0x45, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa4, 0xdc, 0xd2, 0x0c, 0x6e, + 0x69, 0x06, 0xb7, 0x34, 0x03, 0x1a, 0xc1, 0x65, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x06, 0xa7, 0x43, 0x08, + 0x62, 0x18, 0x6b, 0x62, 0x46, 0xbd, 0xd5, 0x79, 0x1b, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1c, + 0xf3, 0xa7, 0x1a, 0xda, 0x27, 0xf0, 0xa2, 0xce, 0x43, 0x1d, 0xb7, 0xc0, 0x74, 0x25, 0x2a, 0xa2, 0xbe, 0x21, 0x0b, + 0xa9, 0xd1, 0xd9, 0x38, 0x93, 0xf4, 0xcf, 0x5b, 0x9e, 0xc0, 0x96, 0x12, 0x84, 0xef, 0x48, 0x7c, 0x66, 0x55, 0x68, + 0x82, 0xd2, 0xe2, 0xd6, 0x99, 0xcb, 0xd9, 0x23, 0xa1, 0x07, 0x66, 0xf3, 0x3e, 0xe6, 0x55, 0x5f, 0x90, 0x02, 0x62, + 0x3e, 0xa6, 0x26, 0xd1, 0x45, 0x6d, 0x06, 0x27, 0x66, 0x72, 0x43, 0x8d, 0x4b, 0xcf, 0xcf, 0xf6, 0xcf, 0x27, 0x1a, + 0xf8, 0x3c, 0x16, 0xd3, 0x91, 0x77, 0x15, 0xfe, 0x68, 0x62, 0x1b, 0x91, 0xc3, 0x43, 0x6b, 0xd1, 0x6e, 0xbe, 0xb6, + 0x4d, 0xda, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x77, 0xef, 0xb1, 0x57, 0x4c, 0x47, 0x28, 0xa0, 0xd9, + 0x06, 0xac, 0xb2, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x47, 0x4e, 0xe8, 0xdd, 0x8c, 0x79, 0x53, 0x4c, 0x47, 0x7b, 0x9f, + 0x5e, 0xb1, 0x3d, 0xf6, 0x5f, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb1, 0xdb, 0x6f, 0xd5, 0xb9, 0xde, 0x5b, 0x47, + 0xe5, 0xdf, 0xaa, 0xf3, 0x64, 0x5f, 0x9d, 0x39, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, 0x81, 0x1a, 0xdb, 0x98, 0x49, 0x4d, + 0x47, 0x10, 0x2b, 0x1f, 0xfe, 0xda, 0x88, 0x36, 0x3d, 0x4f, 0xc2, 0x61, 0x15, 0x64, 0x3f, 0xe9, 0xa6, 0x0c, 0x53, + 0xd2, 0x39, 0x2e, 0x4c, 0x4c, 0x1b, 0x91, 0xd0, 0xa6, 0x4a, 0x28, 0xce, 0x49, 0x1c, 0xd3, 0xe3, 0x0c, 0x22, 0xf3, + 0xb4, 0xfb, 0x34, 0x8d, 0x69, 0x23, 0x43, 0x27, 0x71, 0xbb, 0x41, 0x8f, 0x33, 0x84, 0x1a, 0x6d, 0xd0, 0x99, 0x4a, + 0xd2, 0x6e, 0xe6, 0x10, 0xab, 0xd3, 0x90, 0xe2, 0xfc, 0x58, 0x24, 0x45, 0x43, 0x1e, 0xab, 0xa4, 0x68, 0x24, 0x5d, + 0x2c, 0x92, 0x69, 0x99, 0x3c, 0x35, 0xc9, 0x53, 0x9b, 0x3c, 0x2a, 0x93, 0x47, 0x26, 0x79, 0x64, 0x93, 0x29, 0x29, + 0x8e, 0x45, 0x42, 0x1b, 0x71, 0xbb, 0x59, 0xa0, 0x63, 0x18, 0x81, 0x1f, 0x3d, 0x11, 0x61, 0x88, 0xf4, 0x8d, 0xb1, + 0x31, 0x5a, 0xc8, 0xdc, 0x05, 0x2d, 0xad, 0x80, 0x54, 0x3a, 0x7e, 0x41, 0x9d, 0x7f, 0x02, 0x30, 0x61, 0x6d, 0xff, + 0xf8, 0x90, 0x7c, 0x9b, 0x2c, 0x97, 0x22, 0x70, 0x6c, 0x03, 0x5b, 0xfc, 0xcf, 0xce, 0x9d, 0x07, 0xa0, 0xba, 0xa1, + 0xf9, 0x62, 0x46, 0x77, 0xbc, 0x87, 0x8b, 0xe9, 0xc8, 0xed, 0xac, 0xb2, 0x19, 0x46, 0x0b, 0x1b, 0xea, 0xba, 0xee, + 0xe7, 0x09, 0xa0, 0xf6, 0xbe, 0xa5, 0x09, 0x35, 0x4a, 0x72, 0x5b, 0x63, 0x5a, 0xb0, 0x3b, 0x95, 0xd1, 0x9c, 0xc5, + 0xd5, 0x01, 0x5c, 0x0d, 0x93, 0x91, 0x27, 0xe0, 0x11, 0x50, 0x1c, 0x27, 0xa7, 0x0d, 0x9d, 0x4c, 0x8f, 0x93, 0xee, + 0x83, 0x86, 0x4e, 0x46, 0xc7, 0x49, 0xbb, 0x5d, 0xe1, 0x6c, 0x52, 0x10, 0x9d, 0x4c, 0x89, 0x06, 0x8d, 0xa1, 0x6d, + 0x54, 0x2e, 0x28, 0x98, 0xb8, 0xfd, 0x1b, 0xc3, 0x68, 0xb8, 0x61, 0x08, 0x36, 0xb5, 0x51, 0x3f, 0x77, 0xc6, 0x10, + 0x76, 0xd3, 0xe9, 0x76, 0x9b, 0x3a, 0x29, 0xb0, 0xb6, 0x2b, 0xd9, 0xd4, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x4d, 0x9d, + 0x8c, 0x6c, 0x53, 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0xe7, 0x2c, 0x80, 0x7c, 0xc7, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, + 0xf8, 0xad, 0x72, 0x4d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xdb, 0x55, 0x93, 0xec, 0x5f, 0x97, + 0x2d, 0x9b, 0x2d, 0xa4, 0xae, 0x17, 0x7c, 0x51, 0xc3, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x8f, 0x28, 0x89, 0x21, 0xb6, + 0x9f, 0x39, 0x85, 0x38, 0xf1, 0x7a, 0x64, 0x48, 0xe2, 0x8d, 0xc6, 0x06, 0xc5, 0xc1, 0x79, 0xfb, 0x22, 0xa4, 0xaa, + 0x3b, 0x01, 0xff, 0x08, 0x89, 0x96, 0xc2, 0x9a, 0x84, 0x8e, 0xa3, 0x8a, 0x16, 0xbf, 0x71, 0xda, 0xdd, 0xda, 0x01, + 0x71, 0x74, 0xb4, 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xec, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, + 0x98, 0x07, 0x88, 0xe2, 0x43, 0x6f, 0xdd, 0x37, 0x14, 0x7e, 0x50, 0xc5, 0x1d, 0x74, 0x39, 0xcd, 0x73, 0x93, 0x61, + 0xfa, 0x1a, 0x06, 0x63, 0x7b, 0x15, 0x4e, 0xa8, 0xb4, 0x95, 0xfc, 0x97, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, + 0x46, 0x3f, 0x85, 0x96, 0xc9, 0x15, 0x6c, 0x9c, 0x4f, 0xfa, 0x7a, 0x5d, 0x7b, 0x9e, 0xc8, 0x3e, 0x82, 0x83, 0x8e, + 0x8e, 0xb8, 0x7a, 0x06, 0xc6, 0xd4, 0x2c, 0x6e, 0x84, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x93, 0x39, 0x57, 0xd3, + 0xe0, 0xa0, 0x7b, 0x58, 0xcb, 0xdf, 0xbb, 0x12, 0x7d, 0x9d, 0x72, 0xb7, 0xd6, 0xef, 0x2b, 0x53, 0xf5, 0x9d, 0x87, + 0xb2, 0x8e, 0x8e, 0x78, 0x15, 0xae, 0x2a, 0xfa, 0x2e, 0x42, 0x7d, 0x23, 0x83, 0x3c, 0xcb, 0x25, 0x85, 0x1b, 0x51, + 0xb8, 0x62, 0x48, 0x1b, 0xfc, 0x44, 0xe3, 0x9f, 0xe4, 0xff, 0xa7, 0x46, 0x8e, 0x75, 0xda, 0xe0, 0x81, 0xb9, 0x41, + 0xc8, 0x0a, 0x55, 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1e, 0xe6, 0x74, 0xb1, 0xc8, 0xef, 0xcc, 0x5b, + 0x61, 0x01, 0x47, 0x55, 0x5d, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x00, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xf2, + 0x72, 0x5b, 0x20, 0x90, 0xcc, 0x14, 0x91, 0xcd, 0x76, 0x4f, 0x5d, 0x81, 0x5c, 0xd6, 0x6c, 0x22, 0xed, 0x82, 0x97, + 0x63, 0x0e, 0x32, 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, + 0x0c, 0x68, 0x84, 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xc2, 0x77, 0xfc, 0x95, 0x96, 0x8a, 0x81, 0x1a, + 0x0e, 0x71, 0x61, 0x9e, 0xc7, 0x28, 0xe7, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, + 0x33, 0x72, 0x6d, 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbd, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x65, 0x2e, 0x0a, 0x9d, 0xbc, + 0xc9, 0x2e, 0x45, 0xaf, 0xd1, 0x60, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, + 0xc5, 0x6c, 0x04, 0x3e, 0x08, 0x0d, 0x5e, 0x4b, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xb2, + 0x9f, 0x32, 0x94, 0x6c, 0x65, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x53, 0xed, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, + 0x9b, 0x60, 0x00, 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8c, 0x13, + 0x60, 0x6f, 0x6e, 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x80, 0x1c, 0x3d, 0x24, 0xd0, 0xb9, 0xfd, 0x59, + 0xd1, 0x85, 0x4a, 0x26, 0x2e, 0xc7, 0xf8, 0x43, 0x70, 0x9b, 0x37, 0x88, 0x3e, 0x7e, 0x34, 0x9b, 0xfc, 0xe3, 0xc7, + 0x08, 0x87, 0xc6, 0xf5, 0x51, 0xc0, 0x0b, 0x46, 0xc3, 0x32, 0xb4, 0x96, 0xd9, 0xf8, 0xcd, 0x76, 0x80, 0x76, 0xb4, + 0xc2, 0x3b, 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x80, 0x03, 0xbc, 0xd9, 0x80, 0x0f, 0x7b, 0xaf, 0x62, 0x85, + 0x8e, 0x8e, 0x5e, 0xc5, 0x12, 0xf5, 0xaf, 0x99, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x01, 0x37, 0xc3, 0x97, 0x01, 0x02, + 0x5c, 0xb3, 0x6d, 0xc9, 0xe6, 0x8d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0xbe, + 0x0a, 0xa1, 0xdd, 0x63, 0x84, 0x01, 0x0b, 0x5f, 0xfa, 0x0a, 0xb2, 0x64, 0xce, 0x8a, 0x29, 0x2b, 0xd6, 0xeb, 0xe7, + 0xd4, 0xfa, 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xbd, 0x46, 0x83, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x87, 0xf8, 0xf0, 0x55, + 0x5c, 0x20, 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0x56, 0x5b, 0x97, 0x02, 0x95, 0x8d, 0xe4, 0xa4, 0x85, + 0x67, 0x24, 0x2b, 0xd7, 0xe8, 0x72, 0xd6, 0x6b, 0x34, 0x72, 0x24, 0xe3, 0x6c, 0x90, 0x0f, 0x31, 0xc7, 0x05, 0x5c, + 0xa6, 0xee, 0xae, 0xc3, 0x82, 0xd5, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x47, 0x37, 0x01, 0x30, 0xde, + 0xd1, 0x80, 0x48, 0xec, 0x03, 0xb2, 0xb0, 0x40, 0x56, 0x1e, 0xc8, 0xc2, 0x00, 0x59, 0xa1, 0xfe, 0x02, 0x82, 0x36, + 0x29, 0x94, 0xee, 0x50, 0xf4, 0x7a, 0x78, 0x51, 0xe7, 0xba, 0x82, 0xb9, 0x89, 0x70, 0xe1, 0x96, 0x03, 0xdc, 0x58, + 0xdc, 0xdc, 0x15, 0x59, 0x45, 0x91, 0x89, 0xb4, 0x8b, 0x6f, 0xcd, 0x9f, 0xe4, 0x16, 0xdf, 0xd9, 0x1f, 0x77, 0x81, + 0x32, 0xe9, 0xb7, 0x9a, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xfe, 0xee, + 0x9c, 0xb2, 0xe1, 0x30, 0x44, 0x83, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xe7, 0x9f, 0x11, 0xea, 0x0b, 0x88, 0x66, 0xe4, + 0x4e, 0xb6, 0x66, 0x1b, 0x35, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0x54, + 0x36, 0x1e, 0xb5, 0x61, 0x98, 0x41, 0x55, 0xe1, 0x3f, 0xae, 0x56, 0xdb, 0xc1, 0x96, 0x0c, 0x54, 0x85, 0x89, 0x74, + 0x83, 0xec, 0x43, 0x6c, 0x8c, 0xb0, 0xa3, 0x23, 0x36, 0x10, 0xc3, 0xe0, 0x65, 0xb5, 0xaa, 0x75, 0x1d, 0x2e, 0x5c, + 0x9c, 0x41, 0xb4, 0xfb, 0xf5, 0xda, 0xfe, 0x25, 0x1f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0xb7, 0xf1, 0x62, 0xbf, + 0x2c, 0x96, 0x68, 0xf9, 0x0e, 0x2c, 0xfb, 0x5c, 0xec, 0x42, 0xee, 0xa6, 0xda, 0xf6, 0x50, 0x5f, 0x18, 0x8d, 0x42, + 0x10, 0x39, 0xb8, 0x3a, 0xd2, 0xf0, 0x42, 0x87, 0x79, 0xb5, 0x08, 0xc0, 0xb9, 0x2a, 0x03, 0xb9, 0xc2, 0x91, 0x92, + 0x80, 0xa5, 0xb7, 0xa1, 0x93, 0xf0, 0xa3, 0x4e, 0x25, 0x1d, 0x0b, 0x09, 0x50, 0xe0, 0xc8, 0x5c, 0xce, 0x9b, 0x40, + 0xfd, 0x0c, 0xed, 0x21, 0x72, 0xd5, 0x2a, 0xff, 0x5d, 0x97, 0x2d, 0x5d, 0x44, 0xad, 0x68, 0x2e, 0x97, 0x8a, 0x2d, + 0x17, 0x70, 0xbe, 0x97, 0x69, 0x59, 0xce, 0xb3, 0xcf, 0xf5, 0x14, 0x30, 0x88, 0xbc, 0xd5, 0x73, 0x26, 0x96, 0x91, + 0x9b, 0xe7, 0x4b, 0x2b, 0xee, 0xbf, 0x7e, 0x81, 0xdf, 0x93, 0xce, 0xf1, 0x4b, 0xfc, 0x3b, 0x25, 0xef, 0x1b, 0x2f, + 0xf1, 0x94, 0x13, 0xcb, 0x1b, 0x24, 0xaf, 0x5f, 0x5d, 0xbf, 0x78, 0xfb, 0xe2, 0xfd, 0xd3, 0x8f, 0x2f, 0x5e, 0x3e, + 0x7b, 0xf1, 0xf2, 0xc5, 0xdb, 0x0f, 0xf8, 0x27, 0x4a, 0x5e, 0x9e, 0xb4, 0x2f, 0x5a, 0xf8, 0x1d, 0x79, 0x79, 0xd2, + 0xc1, 0xb7, 0x9a, 0xbc, 0x3c, 0x39, 0xc3, 0x33, 0x45, 0x5e, 0x1e, 0x77, 0x4e, 0x4e, 0xf1, 0x52, 0xdb, 0x26, 0x73, + 0x39, 0x6d, 0xb7, 0xf0, 0xdf, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x53, 0xb6, 0x65, 0xfc, 0x60, 0xca, 0xd0, 0x91, + 0x32, 0x86, 0x28, 0x97, 0x01, 0x3a, 0x8d, 0x55, 0xdd, 0xb4, 0x01, 0x42, 0x49, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, + 0xae, 0x1d, 0x7e, 0xd2, 0x66, 0xa7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd3, 0x62, 0x4c, 0x72, + 0x29, 0x8b, 0x78, 0x09, 0x8c, 0x80, 0xd1, 0x5a, 0xf0, 0x93, 0x32, 0x66, 0x95, 0xb8, 0x24, 0xed, 0x7e, 0x3b, 0x15, + 0x97, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x9b, 0xb6, 0x5b, 0xe8, 0x38, 0x18, 0xc7, 0x0f, 0x35, 0xb4, 0x1e, + 0x0c, 0xb1, 0xeb, 0x42, 0xfd, 0x5d, 0x68, 0xaf, 0xd2, 0x13, 0x4e, 0x1d, 0xdb, 0xee, 0x89, 0x4b, 0x66, 0xf4, 0xb0, + 0xfc, 0x3b, 0x40, 0x6d, 0xe3, 0x56, 0x53, 0x6e, 0x1c, 0xf7, 0x8b, 0x9f, 0x08, 0x54, 0x0b, 0x8c, 0x13, 0xb3, 0x75, + 0x0b, 0x01, 0xd3, 0x68, 0xb2, 0xc1, 0x1c, 0x28, 0x51, 0xb2, 0xd0, 0x3e, 0xb8, 0xbf, 0x6a, 0x4a, 0x94, 0x2c, 0xe4, + 0x22, 0xae, 0xa9, 0x1a, 0x7e, 0x09, 0xcc, 0x1c, 0x0f, 0xb9, 0x7a, 0x49, 0x5f, 0xc6, 0x35, 0x9e, 0x27, 0x64, 0xed, + 0xc2, 0x6d, 0xf1, 0xab, 0xb3, 0xa2, 0xa8, 0x81, 0xab, 0x04, 0xac, 0x1f, 0x55, 0x53, 0x5f, 0xc2, 0x2b, 0x86, 0xac, + 0xa1, 0xaf, 0x48, 0x40, 0x3d, 0x7f, 0x2d, 0xcd, 0xb8, 0x4a, 0x65, 0xb4, 0x57, 0x44, 0x1b, 0xb3, 0x20, 0xaf, 0x88, + 0xbe, 0x54, 0x06, 0x08, 0x92, 0xf0, 0x81, 0x18, 0xc2, 0x81, 0x6f, 0x07, 0x28, 0x0d, 0x9d, 0x03, 0xb5, 0x52, 0x65, + 0x26, 0x64, 0x3e, 0x4d, 0x88, 0x06, 0xd0, 0x3c, 0x55, 0x2a, 0x28, 0xf3, 0x89, 0x25, 0x0a, 0x86, 0xfe, 0x47, 0xb8, + 0x01, 0x8e, 0x63, 0x83, 0x8a, 0xa1, 0x5d, 0x8d, 0xa8, 0xe7, 0xb7, 0x2f, 0x5a, 0x27, 0x2f, 0x83, 0xfc, 0xa5, 0xf2, + 0xf6, 0x1e, 0x9f, 0x02, 0x4a, 0x6e, 0x83, 0x8a, 0xb5, 0xb1, 0x8f, 0x07, 0xd7, 0x0b, 0x01, 0x72, 0xac, 0xd1, 0x89, + 0x79, 0xd0, 0xb1, 0x87, 0xf4, 0x31, 0x69, 0xb7, 0x20, 0x88, 0xdb, 0x1e, 0xca, 0xf7, 0xc7, 0x16, 0x4c, 0x75, 0x72, + 0xdb, 0x04, 0x5a, 0x0d, 0x6f, 0x3c, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, 0x33, 0xec, 0x98, 0x35, 0xc4, 0xb1, + 0x40, 0x2e, 0xf8, 0xad, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0x6b, 0xd0, 0x1b, 0x47, 0x5d, 0x36, 0x93, 0xee, 0xf1, + 0xcb, 0xa3, 0xa3, 0x58, 0x36, 0xc8, 0x7b, 0x84, 0x57, 0x14, 0x6c, 0xb6, 0xc1, 0xf7, 0x8e, 0x5b, 0x26, 0x3e, 0x55, + 0x01, 0x75, 0x9c, 0xa8, 0xda, 0xb1, 0x56, 0x75, 0x56, 0xee, 0x06, 0x3f, 0xa6, 0x0e, 0x6a, 0x04, 0x69, 0x76, 0x74, + 0x9d, 0x10, 0xca, 0x3f, 0xd6, 0x1c, 0xe5, 0x60, 0x5b, 0x36, 0x7e, 0xa7, 0xe8, 0xbb, 0xf7, 0xcd, 0x97, 0x01, 0x1e, + 0xd4, 0x4c, 0x93, 0xde, 0x37, 0xde, 0xa3, 0xef, 0xde, 0x07, 0xae, 0x8e, 0xbc, 0x62, 0x4f, 0x3c, 0x37, 0xf2, 0xab, + 0xe5, 0x4a, 0x7f, 0x05, 0xc9, 0xbe, 0x20, 0xbf, 0x02, 0x96, 0x53, 0xf2, 0x6b, 0x2c, 0x9b, 0x10, 0x02, 0x92, 0xfc, + 0x1a, 0x17, 0xf0, 0x23, 0x27, 0xbf, 0xc6, 0x80, 0xed, 0x78, 0x66, 0x7e, 0x14, 0x25, 0x30, 0xc0, 0xbd, 0x4e, 0x5a, + 0x2f, 0xbb, 0x62, 0xbd, 0x16, 0x47, 0x47, 0xd2, 0xfe, 0xa2, 0x57, 0xd9, 0xd1, 0x51, 0x7e, 0x39, 0xab, 0xfa, 0xe6, + 0x7a, 0x1f, 0x7d, 0x31, 0x08, 0x85, 0x03, 0xd3, 0x34, 0x1e, 0xce, 0x58, 0x67, 0x21, 0xe2, 0x40, 0x03, 0xcd, 0xd3, + 0xce, 0xfd, 0xf3, 0x0b, 0x0c, 0xff, 0xde, 0x0f, 0x0a, 0x82, 0x0e, 0xdf, 0x4e, 0x8c, 0xb4, 0x59, 0xf3, 0xbc, 0xaa, + 0x73, 0x15, 0xe0, 0x33, 0x66, 0xa8, 0x29, 0x8e, 0x8e, 0xf8, 0x65, 0x80, 0xcb, 0x98, 0xa1, 0x46, 0x60, 0xb1, 0xf7, + 0xb4, 0xb4, 0x27, 0x33, 0x5c, 0x13, 0x3c, 0xee, 0xcb, 0x07, 0xc5, 0xf0, 0x52, 0x3b, 0x6a, 0x12, 0x86, 0x00, 0x57, + 0xa4, 0xe5, 0x36, 0x59, 0x4f, 0x34, 0xd5, 0x55, 0xbb, 0x87, 0x24, 0x51, 0x0d, 0x71, 0x75, 0xd5, 0xc6, 0xa0, 0x92, + 0xef, 0x2b, 0x22, 0x53, 0x41, 0xbc, 0x9b, 0xe2, 0x2a, 0x97, 0xa9, 0xc2, 0x33, 0x9e, 0x0a, 0x2f, 0x67, 0xdf, 0xf3, + 0xd6, 0xd3, 0xc6, 0x71, 0xd4, 0xf4, 0xcc, 0xb0, 0xe8, 0xab, 0xd2, 0xe1, 0x11, 0x36, 0xa9, 0x1a, 0xc2, 0xdb, 0x89, + 0x25, 0xe6, 0x31, 0xeb, 0xe5, 0xc7, 0x20, 0x36, 0xb5, 0x6a, 0xb4, 0x21, 0x13, 0x3e, 0x37, 0xa9, 0x82, 0x81, 0x9a, + 0xc2, 0x97, 0x60, 0x64, 0x95, 0x55, 0x86, 0xd9, 0xbe, 0x61, 0x28, 0x20, 0xa0, 0xc0, 0x15, 0x61, 0x81, 0x04, 0x2f, + 0xb2, 0x1a, 0xe1, 0xa8, 0x93, 0x0b, 0x3b, 0xb9, 0x4b, 0x05, 0xdd, 0x89, 0xe1, 0xa5, 0xee, 0x21, 0xd1, 0x68, 0x38, + 0x6e, 0xfb, 0x4a, 0x98, 0x41, 0x34, 0xdb, 0xc3, 0x2b, 0xd6, 0x43, 0xaa, 0xd9, 0x2c, 0x0d, 0x20, 0xaf, 0x5a, 0xeb, + 0xb5, 0xba, 0xf4, 0x8d, 0xf4, 0xfd, 0x39, 0x6e, 0xf8, 0x2e, 0x2f, 0x78, 0xfe, 0x21, 0xc9, 0x20, 0x02, 0xaa, 0x0a, + 0x7c, 0xb6, 0x5c, 0x44, 0x38, 0x32, 0xcf, 0xea, 0xc1, 0x5f, 0xf3, 0x1c, 0x5a, 0x84, 0x23, 0xf7, 0xd2, 0x5e, 0x34, + 0xac, 0x06, 0xab, 0xb2, 0x32, 0x48, 0x3c, 0x4f, 0x3e, 0x02, 0xe3, 0xa0, 0x3f, 0x29, 0xb4, 0xaa, 0x7e, 0x27, 0xb9, + 0x0b, 0x97, 0xa2, 0xfc, 0xe3, 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, + 0x8d, 0xd7, 0x27, 0xdb, 0xee, 0xd1, 0xf3, 0x55, 0xd9, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0x7f, 0xc8, 0xbd, 0x2f, + 0x20, 0x47, 0x1f, 0xa5, 0x78, 0x42, 0x35, 0x8d, 0x1a, 0xaf, 0x8d, 0xe1, 0x9b, 0x95, 0xb3, 0x7a, 0x5f, 0x1b, 0x07, + 0xfb, 0xb7, 0xba, 0x87, 0x00, 0x16, 0xb5, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, + 0x3c, 0xfc, 0x18, 0x29, 0xb8, 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x9a, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, + 0xe3, 0xef, 0x06, 0x85, 0x5c, 0xf7, 0x42, 0xd5, 0x89, 0x69, 0xd5, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xaa, + 0xde, 0x8d, 0x84, 0x52, 0xbd, 0x6b, 0x67, 0xde, 0x26, 0x6d, 0xb6, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, + 0xbc, 0x87, 0x65, 0xd0, 0xae, 0x2b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xad, 0xdc, 0xcb, 0x74, 0x7c, 0x20, + 0x87, 0x9b, 0xf2, 0x9d, 0xba, 0x00, 0x0f, 0x02, 0xa7, 0x80, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x35, 0xfd, 0x10, + 0xff, 0x07, 0x0e, 0xf8, 0x0a, 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0xfe, 0x28, 0x43, + 0x47, 0xdd, 0xba, 0x4e, 0xc5, 0xfa, 0xc2, 0xd6, 0x15, 0x2b, 0x65, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, + 0x59, 0xf7, 0xe8, 0xd4, 0x43, 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x67, 0x05, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x08, + 0x5f, 0x55, 0x1e, 0xc0, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, + 0x3a, 0x16, 0x26, 0xb6, 0x84, 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, + 0xb0, 0xa2, 0xf0, 0xd2, 0xa9, 0xc8, 0x82, 0xbe, 0xf6, 0xf5, 0x21, 0xaa, 0x29, 0xf7, 0x63, 0xa3, 0xef, 0x7d, 0xcb, + 0xe7, 0x4c, 0x2e, 0xe1, 0xf1, 0x26, 0xcc, 0x88, 0x62, 0xda, 0x7f, 0x03, 0x05, 0x81, 0x17, 0x80, 0x78, 0x88, 0x8f, + 0xc0, 0x57, 0x79, 0x5a, 0x47, 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0xfd, 0x08, 0xbc, 0x88, 0x40, 0x84, + 0x22, 0x24, 0x62, 0x62, 0x1c, 0xf5, 0x23, 0xe3, 0x92, 0x15, 0x81, 0xd5, 0x18, 0x28, 0xb9, 0x23, 0x3c, 0x55, 0x15, + 0x11, 0x0b, 0x6b, 0xea, 0xa0, 0x12, 0x4b, 0x8d, 0x99, 0xf6, 0x49, 0xa7, 0x02, 0x61, 0x96, 0x6d, 0x0b, 0xca, 0x7a, + 0x4b, 0x5d, 0x80, 0x25, 0x31, 0xa6, 0xb7, 0x3c, 0xf9, 0x08, 0xdc, 0x1c, 0x1b, 0xbb, 0xa2, 0x2b, 0x7e, 0x0d, 0xea, + 0xe9, 0xb4, 0xc0, 0x1f, 0x0d, 0xc3, 0x36, 0x4e, 0xe9, 0x86, 0x70, 0x9c, 0x91, 0x22, 0xa1, 0xb7, 0x10, 0x5b, 0x63, + 0xce, 0x45, 0x9a, 0xe3, 0x39, 0xbd, 0x4d, 0x67, 0x78, 0xce, 0xc5, 0x13, 0xbb, 0xec, 0xe9, 0x18, 0x92, 0xfc, 0xc7, + 0x72, 0x43, 0xcc, 0xd3, 0x60, 0xef, 0x14, 0x2b, 0x1e, 0x01, 0xaf, 0xa2, 0x62, 0xd4, 0x1b, 0x1b, 0x9b, 0x72, 0xae, + 0x2b, 0xe3, 0xf5, 0x7b, 0x3a, 0xa6, 0x38, 0xc3, 0x39, 0x4a, 0x72, 0x89, 0x59, 0x5f, 0xa4, 0xf7, 0x20, 0xae, 0x76, + 0x86, 0xed, 0xb3, 0x62, 0xfc, 0x96, 0xe5, 0xcf, 0x64, 0xf1, 0xde, 0x6c, 0xf9, 0x1c, 0x41, 0x21, 0x70, 0x51, 0x11, + 0x4d, 0xb8, 0xdd, 0x5b, 0xf6, 0x65, 0xd5, 0x14, 0xbd, 0xb5, 0x4d, 0xb9, 0x21, 0xce, 0x20, 0x20, 0x71, 0x32, 0xe3, + 0x8d, 0x36, 0x66, 0xfd, 0xd6, 0x37, 0x1a, 0x9d, 0xa1, 0xb2, 0x24, 0xc2, 0xb0, 0x56, 0x4d, 0x95, 0x4a, 0x22, 0x9a, + 0xca, 0x49, 0x78, 0x2b, 0x03, 0xec, 0x54, 0xe1, 0x4c, 0x2e, 0x85, 0x4e, 0x65, 0x80, 0x37, 0x79, 0xb5, 0xb9, 0x56, + 0xb7, 0x16, 0x62, 0x1a, 0xdf, 0xd9, 0x1f, 0x0c, 0x7f, 0x34, 0x2a, 0xfe, 0x37, 0x60, 0xd8, 0xa3, 0x52, 0x01, 0xf0, + 0x03, 0xc3, 0x59, 0x80, 0x9c, 0xe5, 0x27, 0x6f, 0x01, 0x7c, 0x96, 0x85, 0xbc, 0x83, 0x54, 0x66, 0x52, 0xef, 0x20, + 0x95, 0x41, 0xaa, 0xf1, 0xa8, 0x3f, 0x14, 0x95, 0xb2, 0x28, 0x6c, 0x90, 0x28, 0x5c, 0xaa, 0x83, 0x25, 0x11, 0x09, + 0xb4, 0x6b, 0x44, 0xb9, 0x39, 0x17, 0x10, 0x5a, 0x11, 0x1a, 0xb7, 0xdf, 0xf4, 0x16, 0xbe, 0xef, 0x6c, 0x3e, 0xf3, + 0xf9, 0x77, 0x36, 0xdf, 0x74, 0xe4, 0x31, 0xbe, 0x7e, 0xdb, 0x69, 0x2c, 0xe3, 0xa5, 0xc3, 0xda, 0x77, 0xe5, 0x43, + 0x36, 0x2d, 0xf3, 0x60, 0x38, 0x69, 0xe3, 0x79, 0x80, 0x94, 0xcd, 0x8a, 0x87, 0xeb, 0xe0, 0x76, 0xeb, 0x38, 0xe6, + 0x4d, 0xd2, 0x46, 0xe8, 0xd8, 0x09, 0x57, 0x22, 0x36, 0x92, 0xd3, 0xf1, 0xfb, 0x13, 0xb8, 0x7b, 0x19, 0xa9, 0x2d, + 0x5f, 0x29, 0x5b, 0xad, 0xd9, 0x6e, 0x1d, 0xf3, 0xbd, 0x55, 0x1a, 0x6d, 0x3c, 0x67, 0x64, 0x05, 0x1e, 0x68, 0xb4, + 0xb0, 0xaa, 0x06, 0x70, 0x59, 0x7d, 0x21, 0x7e, 0x5d, 0xd2, 0xb1, 0xf9, 0x3e, 0xb6, 0x29, 0xaf, 0x96, 0xda, 0x27, + 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x5c, 0xc9, 0x20, 0x27, 0xe6, 0x27, 0x24, 0xe9, 0xa2, 0xcb, 0x76, 0x3f, 0xe9, 0x1e, + 0xf3, 0x63, 0x9e, 0x02, 0x0f, 0x1b, 0x37, 0x7d, 0x85, 0x66, 0xdb, 0xd7, 0x79, 0xbc, 0x1c, 0xf1, 0xcc, 0x35, 0x5f, + 0x75, 0x50, 0xa6, 0xda, 0x39, 0x42, 0x16, 0xa0, 0x98, 0xef, 0x25, 0xc8, 0xae, 0x77, 0x73, 0xcc, 0x53, 0xe8, 0x07, + 0x6a, 0x75, 0x6c, 0xad, 0x72, 0x70, 0xbf, 0x2e, 0x01, 0xc1, 0x7c, 0x47, 0xb5, 0xb9, 0xd8, 0xf4, 0x66, 0x5c, 0x75, + 0x76, 0xcc, 0xab, 0x11, 0x86, 0x65, 0x76, 0xfb, 0xf3, 0x53, 0xab, 0xba, 0x3c, 0x0e, 0x20, 0xf2, 0xeb, 0x92, 0x8b, + 0xb0, 0xd3, 0xb0, 0x5b, 0x97, 0x13, 0x76, 0x5a, 0x9f, 0x65, 0x50, 0x64, 0xb7, 0xd7, 0x9d, 0x99, 0xd6, 0x67, 0x7b, + 0x0d, 0x8e, 0x84, 0x30, 0x29, 0xb3, 0xd2, 0x99, 0x54, 0x31, 0x3f, 0x7e, 0x87, 0x5c, 0xeb, 0xaf, 0x96, 0xda, 0xe7, + 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xe5, 0x31, 0x0f, 0x56, 0xee, 0xe9, 0xed, + 0x42, 0xa6, 0x1e, 0x5f, 0xfb, 0xad, 0x74, 0x07, 0x39, 0x81, 0x78, 0xb8, 0xee, 0xc2, 0xb2, 0x20, 0x67, 0x37, 0x77, + 0x50, 0x32, 0x9c, 0xb8, 0x2f, 0xfd, 0x8e, 0xd9, 0xeb, 0x06, 0x7e, 0x99, 0x74, 0x61, 0xea, 0xdb, 0x3d, 0x1c, 0x77, + 0xa0, 0x0f, 0x03, 0x87, 0xed, 0x06, 0x7d, 0x66, 0x05, 0x91, 0xc7, 0xbc, 0xb0, 0x78, 0x76, 0x45, 0xda, 0x7d, 0x9e, + 0xba, 0xcd, 0x64, 0x44, 0xa3, 0x76, 0x93, 0x07, 0x33, 0x03, 0xfc, 0x72, 0x65, 0xc3, 0x22, 0x7e, 0x9d, 0x02, 0x28, + 0xf9, 0x62, 0xd5, 0xfa, 0x54, 0xf0, 0xaa, 0x37, 0x9c, 0x6e, 0xa7, 0xfb, 0x75, 0x83, 0xdb, 0x5d, 0x0f, 0x4f, 0x78, + 0x88, 0xc6, 0xa2, 0xb5, 0x9f, 0xf8, 0x1c, 0x38, 0xa0, 0xa4, 0x75, 0xbf, 0x0b, 0x2e, 0x94, 0x25, 0x2c, 0x77, 0xcb, + 0x8d, 0x76, 0xca, 0x59, 0x38, 0xda, 0x92, 0x01, 0x77, 0xb0, 0x0d, 0x51, 0xe8, 0xe0, 0xb8, 0x83, 0x93, 0x76, 0xbb, + 0xd3, 0xc5, 0xc9, 0x59, 0x17, 0x06, 0xda, 0x48, 0xba, 0xc7, 0x23, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x8f, + 0x20, 0x68, 0x55, 0x28, 0x5e, 0xf3, 0xe3, 0x38, 0x6e, 0x27, 0xf7, 0x5b, 0xed, 0xee, 0x45, 0x03, 0x00, 0xd4, 0x74, + 0x1f, 0xae, 0xc6, 0xab, 0xa5, 0xae, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xab, 0x35, 0xda, 0x9b, 0x6a, 0x0a, + 0xbe, 0xaa, 0x13, 0xce, 0x6d, 0x11, 0xaf, 0xb4, 0x09, 0xb7, 0x45, 0x6c, 0x07, 0x12, 0x83, 0x74, 0x9e, 0x74, 0x3b, + 0x5d, 0x64, 0xc7, 0xa2, 0x1d, 0x7e, 0x94, 0xfb, 0x64, 0xa7, 0x48, 0x43, 0x03, 0x92, 0x94, 0xb3, 0x93, 0x4b, 0x90, + 0xa8, 0x39, 0xb9, 0x6a, 0x37, 0xe7, 0x2c, 0xf1, 0x13, 0x30, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xb8, 0xa4, 0x00, 0x10, + 0x97, 0x60, 0x5c, 0x74, 0xbf, 0xdb, 0xbf, 0x9f, 0x74, 0xcf, 0x3b, 0x96, 0xe8, 0xf1, 0xcb, 0x4e, 0x2d, 0xcd, 0x4c, + 0x3d, 0xe9, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0xdf, 0x85, 0x32, 0x2e, 0x25, 0x2c, 0x05, 0xc1, 0x36, 0xaa, 0x62, 0x10, + 0x61, 0x23, 0xad, 0xe5, 0x9e, 0xd7, 0xb2, 0x2f, 0xce, 0x4e, 0xef, 0x77, 0x43, 0xa8, 0x95, 0xb3, 0x30, 0x0b, 0xed, + 0x26, 0xe2, 0x67, 0x07, 0x4b, 0x8b, 0x8e, 0x93, 0x6e, 0xba, 0x33, 0x41, 0xbb, 0x69, 0x8e, 0x0d, 0x0e, 0x04, 0x0a, + 0xc7, 0x17, 0xc2, 0xe9, 0x4b, 0x82, 0xfb, 0xb1, 0xca, 0xd0, 0x24, 0x54, 0x38, 0xfb, 0x7b, 0xca, 0xe0, 0x3d, 0xcd, + 0xf0, 0xaa, 0xf2, 0x31, 0x15, 0x5f, 0xa8, 0x7a, 0x4d, 0x21, 0x82, 0x88, 0x18, 0x46, 0x2e, 0xbe, 0x79, 0x3d, 0xf7, + 0x07, 0x70, 0x11, 0x66, 0x02, 0x2e, 0x34, 0xbd, 0x12, 0xb4, 0xe2, 0x05, 0x3e, 0x86, 0x0e, 0xb5, 0x66, 0x58, 0x7d, + 0x9e, 0x3a, 0x93, 0x82, 0x50, 0xb7, 0xf5, 0x8e, 0x7f, 0xab, 0x5c, 0x52, 0x5e, 0x65, 0x27, 0x5d, 0x94, 0xb8, 0xcb, + 0xf2, 0xa4, 0x8d, 0x92, 0xc0, 0x84, 0xc4, 0x1d, 0xc9, 0xb3, 0x8c, 0x0c, 0xa2, 0xdb, 0x08, 0x47, 0x77, 0x11, 0x8e, + 0xac, 0x0f, 0xf3, 0x6f, 0xe0, 0xc7, 0x1d, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, 0xd2, 0x4c, 0x40, 0x60, 0xb1, 0x68, + 0x88, 0xc7, 0x50, 0xda, 0x78, 0x56, 0x97, 0xa5, 0x1f, 0xfb, 0xaf, 0xd2, 0xf5, 0xda, 0xa6, 0x04, 0x52, 0xe6, 0xd2, + 0xec, 0x50, 0xfb, 0x30, 0x76, 0x44, 0x3d, 0xb3, 0x1e, 0x61, 0x10, 0x40, 0xe8, 0x9d, 0x7f, 0x58, 0xaf, 0x8a, 0x49, + 0xc2, 0x4e, 0x61, 0xa5, 0xc1, 0x15, 0x3d, 0x0a, 0xcf, 0xb0, 0x08, 0x4f, 0x84, 0x2f, 0x0c, 0x62, 0x85, 0xff, 0x9d, + 0x4b, 0xb9, 0xf0, 0xbf, 0xb5, 0x2c, 0x7f, 0xc1, 0x73, 0x2c, 0xce, 0xa2, 0x05, 0x2c, 0xb7, 0x6c, 0x08, 0xa4, 0x11, + 0xab, 0x8f, 0xe0, 0xe3, 0xc4, 0x85, 0xa9, 0x03, 0x89, 0xf0, 0xa3, 0x11, 0xa8, 0xbc, 0x7c, 0xf8, 0xd1, 0x86, 0x4c, + 0x32, 0x9f, 0x10, 0x33, 0x0d, 0xc2, 0x22, 0x4b, 0xb8, 0xd0, 0x98, 0x16, 0x4c, 0xa9, 0xc8, 0xc6, 0x12, 0x8c, 0xa4, + 0xf0, 0x8f, 0x43, 0xfa, 0x94, 0x89, 0x88, 0x4c, 0x87, 0xf5, 0xd9, 0x5a, 0x71, 0x38, 0x97, 0x85, 0x4a, 0xed, 0x4b, + 0x31, 0x1e, 0x8c, 0x8b, 0xf2, 0x19, 0xc6, 0x74, 0x9c, 0x6d, 0xb0, 0xbd, 0xc3, 0x2e, 0x0b, 0xb9, 0x2b, 0xed, 0xb0, + 0xd4, 0x2c, 0xdb, 0x7c, 0x6d, 0x42, 0xaa, 0x36, 0xa3, 0x60, 0xa2, 0xd5, 0x80, 0xaa, 0xc0, 0x1d, 0x50, 0xd8, 0x06, + 0xa5, 0x49, 0x57, 0x65, 0xc9, 0x74, 0x55, 0x2e, 0xc3, 0x59, 0xab, 0xb5, 0xd9, 0xe0, 0x82, 0x99, 0x40, 0x2e, 0x7b, + 0x4b, 0x40, 0xbe, 0x9a, 0xc9, 0x9b, 0x20, 0x57, 0xa5, 0xe5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, + 0x5f, 0xb8, 0xe2, 0x00, 0x4f, 0x37, 0xbb, 0x91, 0x94, 0x39, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x7c, + 0xcc, 0xf6, 0xb7, 0x09, 0x66, 0xcc, 0xff, 0x5e, 0x8b, 0x1e, 0x81, 0x2c, 0xbb, 0x67, 0x50, 0x07, 0x16, 0x71, 0x0d, + 0x1d, 0x84, 0x32, 0xf8, 0x24, 0xc4, 0xcd, 0x9c, 0xde, 0xc9, 0xa5, 0x06, 0xb8, 0x2c, 0xb5, 0x7c, 0xed, 0xc2, 0x21, + 0x1c, 0xb6, 0xb0, 0x8f, 0x8c, 0xb0, 0x82, 0x90, 0x01, 0x2d, 0x6c, 0x23, 0x62, 0xb4, 0xb0, 0x0b, 0x54, 0xd0, 0xc2, + 0x26, 0x3c, 0x45, 0x6b, 0x53, 0xc6, 0x36, 0xbb, 0x2b, 0x9f, 0xd4, 0xac, 0x36, 0xc1, 0xc2, 0x49, 0x87, 0x9a, 0xe8, + 0xe0, 0xf6, 0x90, 0x11, 0xde, 0xf8, 0xf1, 0xfa, 0xd5, 0x4b, 0x17, 0xb9, 0x9a, 0x4f, 0xc0, 0x65, 0xd3, 0xa9, 0xc6, + 0xee, 0x6c, 0x88, 0xf9, 0x4a, 0x51, 0x6a, 0x85, 0x53, 0x13, 0xec, 0x53, 0xe8, 0x3c, 0xb1, 0x97, 0x17, 0xcf, 0x64, + 0x31, 0xa7, 0xf6, 0xc6, 0x08, 0xdf, 0x29, 0xf7, 0xf8, 0xbc, 0x79, 0xdf, 0xa6, 0x9a, 0xe4, 0xdb, 0xed, 0xab, 0x88, + 0x45, 0x66, 0xe4, 0x57, 0xd0, 0x06, 0x98, 0xca, 0x7e, 0xe0, 0xac, 0x20, 0x2e, 0xfe, 0x7f, 0x40, 0x5e, 0xde, 0x58, + 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, + 0xd5, 0xdf, 0xde, 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0xc9, 0x25, 0x88, 0x1e, 0xe5, 0x33, 0x7f, 0x1c, 0x44, 0x13, + 0x7f, 0xf7, 0x7c, 0xd5, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, + 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x17, 0xe7, 0x97, 0x6d, 0xd6, 0x3c, 0x5b, 0xaf, 0xf3, 0xab, 0x36, + 0x6b, 0x77, 0xed, 0xb3, 0x7b, 0x91, 0xca, 0x80, 0xe6, 0xf2, 0x09, 0xcf, 0x22, 0xd0, 0xce, 0x4e, 0x33, 0x13, 0x4e, + 0x61, 0xe3, 0x15, 0x3f, 0x4b, 0x5d, 0xf5, 0x25, 0xc1, 0xb8, 0x94, 0x58, 0x3d, 0x7e, 0x81, 0xfa, 0xed, 0x74, 0xd7, + 0x55, 0xba, 0xd9, 0x3e, 0x0e, 0x2e, 0x5c, 0x0a, 0x84, 0x3b, 0x10, 0xf2, 0x00, 0xf4, 0xbb, 0x2b, 0x01, 0xa6, 0x41, + 0x80, 0xca, 0x0a, 0x44, 0x5a, 0x3e, 0x5f, 0xce, 0x9f, 0x15, 0xd4, 0x2c, 0xc3, 0x13, 0x3e, 0xe5, 0x5a, 0xa5, 0x14, + 0xa4, 0xdb, 0x7d, 0xe9, 0x9b, 0xfd, 0x12, 0x54, 0x56, 0x8b, 0xbf, 0x9b, 0x68, 0x9e, 0x7d, 0x56, 0x6e, 0xe1, 0x10, + 0x36, 0x2b, 0x2b, 0x70, 0x86, 0x36, 0x38, 0x97, 0x53, 0x5a, 0x70, 0x3d, 0x9b, 0xff, 0x5b, 0xab, 0xc3, 0x06, 0x7a, + 0x68, 0x2e, 0xac, 0x00, 0x24, 0x54, 0x8c, 0xd7, 0x6b, 0x7e, 0xf2, 0xed, 0xfb, 0x24, 0xef, 0x13, 0xde, 0xc6, 0x1d, + 0x7c, 0x8a, 0xbb, 0xb8, 0xdd, 0xc2, 0xed, 0x2e, 0x5c, 0xdd, 0x67, 0xf9, 0x72, 0xcc, 0x54, 0x0c, 0xef, 0xaf, 0xe9, + 0xab, 0xe4, 0xe2, 0xb8, 0x7a, 0x75, 0xa0, 0x48, 0x1c, 0xba, 0x04, 0xc1, 0xef, 0x5d, 0xd4, 0xc0, 0x28, 0x0a, 0x43, + 0xd6, 0x4d, 0x43, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x3a, 0xed, 0x83, 0x3d, 0xb7, 0x5d, 0xd9, 0x26, 0x98, 0x7d, 0xdb, + 0x9f, 0x69, 0xf5, 0xb3, 0xa9, 0x4b, 0xc4, 0xf0, 0xd0, 0xab, 0xd0, 0x03, 0x5d, 0x91, 0xf6, 0xd1, 0x11, 0x58, 0x1d, + 0x05, 0xb3, 0xe1, 0x36, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, 0x18, 0x77, 0xbe, 0xe2, 0x64, 0x65, 0x61, + 0xab, 0x81, 0x0a, 0xb3, 0x22, 0x8c, 0xab, 0x17, 0x92, 0x0a, 0x23, 0x44, 0xc3, 0x11, 0xe6, 0x82, 0xa1, 0x1c, 0xb6, + 0xb0, 0x9c, 0x4c, 0x14, 0xd3, 0x70, 0x74, 0x14, 0xec, 0x0b, 0x2b, 0x94, 0x39, 0x45, 0x46, 0x6c, 0xca, 0xc5, 0x43, + 0xfd, 0x07, 0x2b, 0xa4, 0xf9, 0x34, 0x1a, 0x8c, 0x34, 0x32, 0xab, 0x18, 0xe1, 0x2c, 0xe7, 0x0b, 0xa8, 0x3a, 0x2d, + 0xc0, 0xe9, 0x07, 0xfe, 0xf2, 0x71, 0x1a, 0xb6, 0x09, 0xe4, 0xeb, 0x37, 0x1b, 0xd3, 0x05, 0x8f, 0x0b, 0x7a, 0xf3, + 0x4a, 0x3c, 0x86, 0x1d, 0xf5, 0xb0, 0x60, 0x14, 0xb2, 0x21, 0xe9, 0x2d, 0x34, 0x05, 0x1f, 0xd0, 0xe6, 0xcf, 0x06, + 0x70, 0xe9, 0x85, 0xf9, 0xb0, 0x15, 0x7d, 0xec, 0xc6, 0xa4, 0x6c, 0xcb, 0x64, 0x9a, 0x53, 0xba, 0xca, 0xb4, 0x51, + 0xa8, 0xca, 0x29, 0x6c, 0xb0, 0x8b, 0x7a, 0x12, 0x0e, 0x66, 0x4c, 0xd5, 0x2c, 0x1d, 0x0c, 0xcd, 0xdf, 0x57, 0xb6, + 0x64, 0x0b, 0xbb, 0x88, 0x33, 0x1b, 0x6c, 0x1e, 0x4e, 0x0d, 0xca, 0xb7, 0x31, 0xdc, 0xc3, 0xc2, 0xeb, 0x9d, 0x35, + 0xf2, 0x79, 0xe6, 0xc9, 0xe6, 0xd9, 0x66, 0x63, 0x06, 0xa2, 0x52, 0xd0, 0x03, 0xbd, 0xf1, 0xdb, 0xa6, 0x05, 0xdb, + 0xa3, 0xfc, 0xea, 0xb6, 0xf0, 0x9c, 0xc3, 0x63, 0xa4, 0xbe, 0xbd, 0x6b, 0x5d, 0xc8, 0xcf, 0x0e, 0x24, 0xad, 0x20, + 0xc5, 0x4e, 0x27, 0xe8, 0xec, 0x14, 0x07, 0x23, 0x07, 0x7a, 0x7e, 0xfd, 0xd9, 0xc2, 0xda, 0xff, 0x7e, 0x5d, 0x16, + 0x34, 0xf1, 0x74, 0xca, 0x09, 0x65, 0xfe, 0xfc, 0x7c, 0xc5, 0x93, 0x0a, 0x15, 0xdc, 0x2b, 0x5e, 0xb0, 0xa7, 0x6d, + 0xa0, 0xcf, 0x39, 0xfd, 0x64, 0x7f, 0xd8, 0x18, 0x3e, 0xa5, 0x96, 0x2d, 0x2b, 0xa4, 0x52, 0x0f, 0x6d, 0x9a, 0x3d, + 0x7a, 0xe0, 0x88, 0xfc, 0x19, 0xba, 0x00, 0x5e, 0x7f, 0x5c, 0xc8, 0x85, 0x41, 0x04, 0xf7, 0xdb, 0x8d, 0xdb, 0xf8, + 0x0a, 0x80, 0xb7, 0xc3, 0x41, 0xf5, 0x4f, 0x0b, 0xd8, 0xdf, 0xa8, 0x2c, 0xe9, 0xc7, 0xdb, 0xb1, 0xc7, 0x7f, 0x21, + 0x21, 0x6a, 0xbc, 0xc5, 0xc3, 0xc4, 0xa1, 0x53, 0xc9, 0x9a, 0x95, 0x3f, 0x77, 0x4a, 0x02, 0x86, 0xd5, 0x0b, 0x86, + 0x6c, 0xdc, 0x4e, 0x71, 0x9b, 0xf9, 0x1f, 0x54, 0x30, 0x58, 0xf0, 0xb5, 0x91, 0x54, 0x2c, 0x8b, 0xdf, 0x3e, 0x75, + 0xfe, 0xab, 0xce, 0x71, 0x1d, 0xea, 0xda, 0x4b, 0xa1, 0x23, 0x13, 0xa5, 0x39, 0x42, 0x47, 0x47, 0x5b, 0x19, 0x74, + 0x02, 0x80, 0x47, 0x8e, 0xfd, 0xf2, 0xcb, 0xe7, 0xd9, 0x31, 0xa3, 0x79, 0x2c, 0xa2, 0x90, 0xb9, 0xf3, 0xdc, 0x9c, + 0x9d, 0xc8, 0x13, 0xaa, 0x66, 0xbe, 0x30, 0xc0, 0xf1, 0xd1, 0x4e, 0x2a, 0xe0, 0x7b, 0xb4, 0xd9, 0x33, 0x81, 0x2d, + 0x7e, 0xcb, 0x4e, 0x6a, 0x5f, 0x41, 0xbf, 0x40, 0xab, 0x7d, 0x4c, 0xe5, 0xd6, 0x02, 0x47, 0xdb, 0x13, 0xd9, 0x3b, + 0xf4, 0xad, 0x3a, 0x25, 0xeb, 0xf1, 0x62, 0xbf, 0xd1, 0x57, 0x21, 0xf6, 0x25, 0x57, 0xb4, 0x6d, 0xc4, 0xaa, 0xd7, + 0x82, 0x75, 0x65, 0xea, 0x54, 0x5d, 0xf3, 0x56, 0x96, 0x36, 0xa5, 0x5d, 0x92, 0xbd, 0xdb, 0x62, 0xe1, 0x55, 0x78, + 0xa3, 0x51, 0x5e, 0x84, 0x82, 0x3d, 0x96, 0x18, 0xf6, 0x38, 0x81, 0xeb, 0x85, 0xf5, 0x3a, 0x86, 0x3f, 0xfb, 0xc6, + 0xb0, 0xcf, 0x74, 0xe9, 0x37, 0xbe, 0xc5, 0xaf, 0x04, 0x01, 0x8b, 0x9d, 0x1d, 0x24, 0x58, 0x77, 0xb9, 0x41, 0xc3, + 0x71, 0xe2, 0xbf, 0xe0, 0xb9, 0x6c, 0xed, 0x5d, 0x0e, 0x46, 0xd9, 0x57, 0x9e, 0xd8, 0x2b, 0x59, 0xcb, 0x5a, 0xb4, + 0xfb, 0x2d, 0x09, 0x86, 0xd8, 0x4d, 0xe9, 0x1c, 0xb7, 0x92, 0x36, 0x8a, 0x5c, 0xb1, 0x0a, 0xfd, 0xbf, 0x56, 0x24, + 0xb3, 0x99, 0xff, 0x75, 0x7e, 0x7e, 0xee, 0x52, 0x9c, 0xcd, 0x9f, 0x32, 0x1e, 0x70, 0x26, 0x81, 0x7d, 0xe1, 0x19, + 0x33, 0x3a, 0xe4, 0x37, 0x30, 0x14, 0x22, 0xc8, 0x95, 0x70, 0xec, 0x12, 0xbc, 0xf6, 0x08, 0x94, 0x07, 0xd8, 0xbf, + 0x27, 0x5b, 0xe5, 0xfc, 0x73, 0x51, 0x3e, 0x9c, 0x72, 0xd9, 0x20, 0xfb, 0x62, 0x3e, 0x07, 0xd6, 0x4c, 0x06, 0x5e, + 0x48, 0x88, 0xb0, 0xfd, 0x6d, 0x58, 0x5a, 0x67, 0x29, 0x83, 0x23, 0x2d, 0x97, 0xd9, 0xcc, 0x6a, 0xfe, 0xdd, 0x87, + 0x29, 0xeb, 0x9e, 0x1a, 0x82, 0xc8, 0x5d, 0x64, 0xe5, 0xa2, 0x82, 0x46, 0xdf, 0x97, 0x01, 0x40, 0x0f, 0x5e, 0xb2, + 0x25, 0xfb, 0x1e, 0x1f, 0x54, 0x29, 0xf0, 0xf1, 0xb0, 0xe0, 0x34, 0xff, 0x1e, 0x1f, 0x54, 0x81, 0x40, 0xc1, 0x15, + 0xd2, 0xc4, 0xd2, 0xc4, 0xe6, 0x59, 0xed, 0x34, 0x12, 0x40, 0x41, 0xf3, 0xc8, 0x1c, 0x64, 0xcf, 0x5d, 0x8c, 0xc6, + 0xa4, 0x83, 0x5d, 0x70, 0x30, 0x1b, 0x11, 0xd6, 0x06, 0x52, 0x87, 0xb8, 0x75, 0xe5, 0x6c, 0xcc, 0xd7, 0xa3, 0xad, + 0x05, 0x31, 0xca, 0x64, 0x72, 0xf5, 0x8e, 0xc7, 0x3b, 0x8b, 0x85, 0xc2, 0x6a, 0xc1, 0x02, 0xd5, 0xaa, 0x54, 0xe9, + 0x61, 0xf1, 0xdd, 0x82, 0x59, 0x50, 0xc4, 0x6c, 0xbd, 0x87, 0xb7, 0x5c, 0x11, 0x90, 0x92, 0x5d, 0x12, 0xbc, 0x8c, + 0x6e, 0x30, 0x95, 0xac, 0xe6, 0x72, 0xcc, 0x2c, 0xa1, 0x67, 0x4a, 0x47, 0xd8, 0xe4, 0x29, 0x88, 0x24, 0x76, 0xd8, + 0xc2, 0x8e, 0x35, 0x7a, 0x21, 0xbc, 0x90, 0x02, 0xe7, 0xaa, 0x69, 0x62, 0x4e, 0xb9, 0x89, 0x2e, 0xf6, 0x50, 0x2d, + 0x58, 0xa6, 0x2d, 0x02, 0x1c, 0x3a, 0x34, 0x94, 0xe2, 0xb9, 0x01, 0x85, 0x79, 0xd2, 0xdb, 0xa5, 0x3c, 0x86, 0xc5, + 0x0b, 0x52, 0x80, 0xa8, 0x71, 0x31, 0x2d, 0xeb, 0x2c, 0xf2, 0xe5, 0x94, 0x8b, 0x0a, 0x19, 0x0a, 0xa6, 0x16, 0x52, + 0xc0, 0x8b, 0x1a, 0x65, 0x11, 0x43, 0x87, 0x6a, 0xf8, 0x6e, 0x49, 0x58, 0x59, 0xc7, 0x1c, 0x53, 0x5c, 0x54, 0x35, + 0x80, 0xb9, 0x78, 0x68, 0x04, 0x44, 0x1f, 0x5e, 0xf6, 0x95, 0x78, 0x2b, 0x17, 0x55, 0xbe, 0xa7, 0x71, 0x3e, 0x70, + 0xbd, 0xb3, 0x1b, 0x46, 0x1b, 0xf3, 0xe8, 0x55, 0xb0, 0x7d, 0x7f, 0xe3, 0xd5, 0x43, 0x70, 0x1b, 0xf3, 0x6c, 0x56, + 0x99, 0x35, 0x62, 0xe5, 0x1b, 0x11, 0x55, 0x7b, 0xf5, 0xaa, 0x85, 0xb0, 0x15, 0x01, 0x2a, 0x05, 0x1f, 0xef, 0xe4, + 0xbf, 0xd0, 0x36, 0xdf, 0x9e, 0x43, 0x65, 0x78, 0x20, 0x4f, 0x86, 0xaa, 0x1e, 0x70, 0x51, 0x7e, 0x08, 0x60, 0xf1, + 0x23, 0x13, 0x3f, 0x78, 0xdf, 0x05, 0x32, 0x67, 0x2a, 0x96, 0x78, 0x35, 0xa0, 0xc3, 0xd4, 0xca, 0x43, 0xa9, 0x04, + 0xdb, 0x9e, 0x9b, 0x82, 0x6b, 0x1f, 0xa8, 0x18, 0x0f, 0xd8, 0x30, 0x5d, 0xd5, 0x83, 0x19, 0xdb, 0x70, 0xca, 0xde, + 0x9c, 0xd3, 0x44, 0xff, 0xa5, 0x43, 0x9c, 0x13, 0xb0, 0x3d, 0x2e, 0x99, 0xfb, 0x38, 0x43, 0xfd, 0x3a, 0x87, 0xbf, + 0xda, 0xe0, 0x1c, 0x67, 0x28, 0x7d, 0x18, 0xc3, 0x05, 0xd6, 0x06, 0x03, 0xf8, 0x32, 0x4b, 0xaa, 0xc0, 0x23, 0x35, + 0x33, 0x12, 0xab, 0xbb, 0x08, 0x44, 0x2b, 0x1d, 0xde, 0x8e, 0x33, 0x1f, 0x0e, 0xdc, 0x70, 0xaf, 0xcf, 0x8c, 0x70, + 0x38, 0xca, 0xe2, 0xda, 0x39, 0xc3, 0xc9, 0xd5, 0x21, 0xaf, 0x9d, 0x98, 0x60, 0xed, 0x1d, 0x9e, 0x2a, 0xa0, 0x47, + 0x83, 0x53, 0xc5, 0xd2, 0x10, 0x88, 0x99, 0x00, 0xde, 0xcc, 0xe1, 0xd1, 0x16, 0xe0, 0x7c, 0xb4, 0xc1, 0xc1, 0x57, + 0x5a, 0xeb, 0x6a, 0x5b, 0x89, 0xb2, 0xd9, 0xe0, 0xc1, 0x32, 0xc3, 0x93, 0x0c, 0xcf, 0xb3, 0x61, 0x70, 0xdc, 0x7c, + 0xcc, 0x42, 0x93, 0xae, 0xf5, 0xfa, 0x85, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0xa8, 0x0f, 0x08, 0x9f, 0x42, + 0x16, 0xd0, 0x92, 0xbe, 0xfb, 0xdb, 0xb0, 0xaf, 0x85, 0xa3, 0x46, 0xcc, 0x13, 0x4b, 0x46, 0xfa, 0xfe, 0x47, 0x99, + 0x65, 0x5b, 0x6b, 0x44, 0x8b, 0xdb, 0x83, 0xa8, 0xe1, 0xdb, 0xab, 0xce, 0x97, 0x51, 0x69, 0xb6, 0x03, 0x88, 0x62, + 0x8d, 0x93, 0x74, 0xb0, 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcc, 0x03, 0x7a, + 0xb1, 0x42, 0x89, 0xe1, 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x9a, 0xc8, + 0x7d, 0x97, 0x55, 0x96, 0x41, 0x82, 0x08, 0x23, 0xf2, 0xdb, 0xeb, 0x52, 0x61, 0x9f, 0xe8, 0xb3, 0x7f, 0x8c, 0x2f, + 0x20, 0xdc, 0xbc, 0x4d, 0x69, 0x31, 0xa2, 0x53, 0x60, 0x63, 0x21, 0x0e, 0xe1, 0x4e, 0xc2, 0x7a, 0x3d, 0x18, 0xf6, + 0x84, 0x21, 0xcf, 0xee, 0x01, 0xc1, 0xb2, 0xa1, 0xfd, 0x0d, 0xc0, 0x55, 0xb7, 0xa5, 0xe6, 0xda, 0xe8, 0x7e, 0xa8, + 0x79, 0xe3, 0x8c, 0xbb, 0x24, 0xf7, 0x4c, 0x49, 0xf5, 0x12, 0x79, 0xcd, 0x02, 0xdc, 0x84, 0xae, 0xc2, 0x63, 0xbc, + 0xb4, 0x36, 0x9c, 0xe6, 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x64, 0x43, 0x3c, 0xf6, 0xe1, + 0xce, 0x0f, 0xdf, 0xc4, 0x63, 0x84, 0x0a, 0x62, 0x60, 0x6a, 0x5d, 0xb6, 0xc7, 0x95, 0xdd, 0xbe, 0xc9, 0x34, 0x0c, + 0x83, 0x31, 0x62, 0x1e, 0x87, 0x46, 0xcc, 0x79, 0xa3, 0x81, 0x96, 0x64, 0x0c, 0x46, 0xcc, 0xcb, 0xa0, 0xb5, 0xa5, + 0x7d, 0xec, 0x34, 0x68, 0x6f, 0x89, 0x50, 0x8f, 0x03, 0x4d, 0xd3, 0xf0, 0xac, 0x49, 0xf5, 0xac, 0xbc, 0x7f, 0x64, + 0xeb, 0xa4, 0x03, 0x8a, 0x84, 0xc9, 0x95, 0x9f, 0x84, 0x75, 0x0d, 0xb7, 0xe3, 0x9e, 0x98, 0x71, 0x3b, 0xdb, 0x06, + 0x35, 0x90, 0x83, 0x6c, 0x38, 0xec, 0x49, 0x6f, 0x25, 0xd1, 0xc2, 0x93, 0xea, 0x21, 0x94, 0x6a, 0xf1, 0xbe, 0xe8, + 0xed, 0x2b, 0x6f, 0xee, 0xdf, 0x57, 0xdd, 0x3e, 0x8f, 0x81, 0x03, 0x3a, 0x84, 0xfb, 0xa1, 0x2a, 0x3e, 0xd8, 0x49, + 0x07, 0xa2, 0xa0, 0xa5, 0xad, 0x9a, 0x40, 0x6a, 0xcd, 0xec, 0x62, 0xdd, 0x54, 0xe8, 0x58, 0x40, 0x18, 0x32, 0x55, + 0x75, 0x77, 0xab, 0x02, 0xd5, 0x10, 0x87, 0x53, 0xff, 0xb1, 0x35, 0x62, 0x8d, 0xa3, 0xce, 0x38, 0x32, 0x46, 0x92, + 0x76, 0xf9, 0xe0, 0xed, 0x23, 0xb0, 0x12, 0xf0, 0x31, 0xa8, 0x4d, 0x92, 0x31, 0x24, 0x78, 0xc3, 0x32, 0x6d, 0xf8, + 0x10, 0xee, 0x10, 0x94, 0x27, 0x36, 0x28, 0xad, 0xab, 0x64, 0x21, 0x17, 0x74, 0x19, 0xa0, 0xe7, 0x97, 0xf2, 0x37, + 0x36, 0x1c, 0x59, 0x00, 0x87, 0x6c, 0x67, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2f, 0x85, 0x4e, 0x4c, 0xbc, + 0xee, 0x6b, 0xd8, 0xa0, 0x78, 0x01, 0x0e, 0x82, 0x4e, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x35, 0xc9, 0x06, 0xb7, 0xe6, + 0x24, 0x5e, 0xac, 0xd7, 0x2d, 0x74, 0xfc, 0x93, 0x79, 0x92, 0x7a, 0x52, 0x2a, 0xdc, 0x27, 0x95, 0xc2, 0x1d, 0x2c, + 0x01, 0xc9, 0x24, 0xd0, 0xb5, 0x63, 0x19, 0xaa, 0xd1, 0x21, 0x5a, 0xfa, 0x0b, 0x88, 0x9d, 0xed, 0x8e, 0x25, 0xd0, + 0xb3, 0xef, 0x14, 0xb0, 0xba, 0xf6, 0xb2, 0x04, 0x32, 0x82, 0xbb, 0xdf, 0x04, 0x46, 0x85, 0x68, 0x7c, 0xfe, 0xcc, + 0xab, 0x16, 0x3c, 0x71, 0xfe, 0x5c, 0x73, 0xc3, 0xba, 0x17, 0xf4, 0xc6, 0x34, 0x1f, 0x4f, 0x70, 0x73, 0x62, 0xc1, + 0x79, 0xd2, 0x81, 0x9f, 0x16, 0xa2, 0x27, 0x1d, 0xec, 0x52, 0xf1, 0xa4, 0x04, 0x72, 0x88, 0x9e, 0xce, 0x40, 0x0a, + 0x58, 0xe9, 0xd8, 0x6a, 0x91, 0xa6, 0x68, 0xbd, 0x9e, 0x5e, 0x92, 0x16, 0x42, 0x2b, 0x75, 0xc3, 0x75, 0x36, 0x03, + 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa6, 0x7a, 0x16, 0x23, 0x3c, 0x41, 0xab, 0x31, 0x9b, 0xd0, 0x65, 0xae, 0x53, 0xd5, + 0xe7, 0x89, 0x0d, 0xdc, 0xcb, 0x6c, 0x24, 0xb8, 0x93, 0x0e, 0x9e, 0x1a, 0xfe, 0xf2, 0xbd, 0x31, 0x07, 0x29, 0x32, + 0x93, 0x3c, 0x35, 0x09, 0x98, 0x27, 0x59, 0x2e, 0x15, 0xb3, 0xcd, 0xf4, 0xac, 0x6d, 0x39, 0x84, 0x24, 0x8f, 0x74, + 0xc1, 0x8d, 0x15, 0x65, 0x94, 0xce, 0x88, 0xea, 0xab, 0x93, 0x4e, 0x3a, 0xc5, 0x3c, 0x01, 0x4e, 0xef, 0xad, 0x8c, + 0x59, 0xa3, 0xbc, 0x15, 0x9d, 0xa3, 0xe3, 0x19, 0x16, 0xd5, 0x25, 0xea, 0x1c, 0x1d, 0x4f, 0x11, 0x9e, 0x37, 0xc8, + 0x4c, 0x81, 0xc7, 0x30, 0x17, 0xff, 0x47, 0xca, 0x7f, 0x75, 0xd8, 0x10, 0x62, 0xfa, 0x0d, 0xec, 0x14, 0x36, 0x8e, + 0xd2, 0x9c, 0x80, 0xd7, 0x62, 0xfb, 0x1c, 0x67, 0x64, 0xda, 0xcc, 0x7d, 0xc0, 0x3d, 0xd3, 0x4a, 0xe3, 0x56, 0xa3, + 0xe3, 0x0c, 0x8f, 0xb7, 0x93, 0x62, 0x33, 0xd7, 0x66, 0x9e, 0x66, 0x70, 0xbe, 0x57, 0xa3, 0x70, 0xe5, 0x97, 0xdb, + 0x49, 0x61, 0x79, 0x07, 0xdc, 0xe6, 0x18, 0x8b, 0x26, 0xc5, 0x39, 0x9e, 0x37, 0x5f, 0xe2, 0x79, 0xf3, 0x5d, 0x99, + 0xd1, 0x58, 0x62, 0x01, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xab, 0xe4, 0x31, 0x16, 0x0d, 0x53, 0x1e, 0xcf, 0x1b, 0x55, + 0xe9, 0xe6, 0x12, 0x8b, 0x86, 0x29, 0xdd, 0x78, 0x87, 0xe7, 0x8d, 0x97, 0xff, 0x62, 0xd2, 0x51, 0x0a, 0xe8, 0xb2, + 0x40, 0xab, 0xcc, 0x0e, 0xf1, 0xfa, 0xd7, 0x37, 0x6f, 0xdb, 0x1f, 0x3b, 0xc7, 0x53, 0xec, 0xd7, 0x2f, 0x33, 0x38, + 0x96, 0xe9, 0x98, 0x35, 0x01, 0xa2, 0x19, 0xee, 0x1c, 0xcf, 0x70, 0xe7, 0x38, 0x73, 0x4d, 0x6d, 0xe6, 0x0d, 0x72, + 0xab, 0x43, 0x28, 0xea, 0x28, 0x0d, 0xe1, 0xe3, 0x27, 0x9b, 0x4e, 0x51, 0x0d, 0x94, 0xe8, 0x78, 0x5a, 0x03, 0x15, + 0x7c, 0x2f, 0x6b, 0xdf, 0x55, 0xbd, 0x0a, 0x83, 0x2c, 0x94, 0x50, 0xb8, 0xe6, 0x06, 0x3c, 0xb5, 0x14, 0x03, 0x99, + 0x30, 0xc5, 0x02, 0xe5, 0x1b, 0xa0, 0x30, 0xca, 0x13, 0x33, 0xf4, 0x60, 0x3a, 0x26, 0xf1, 0xff, 0xe7, 0xc9, 0x94, + 0x43, 0x2f, 0xb7, 0xcc, 0xce, 0xf4, 0xdc, 0x64, 0xc2, 0xe1, 0x03, 0x8f, 0xf5, 0x7f, 0xed, 0x40, 0xb1, 0x01, 0x29, + 0xfe, 0xbf, 0x74, 0x74, 0x21, 0x18, 0x21, 0x2b, 0x4a, 0x0b, 0x87, 0xf8, 0xdf, 0x1e, 0x56, 0xd0, 0x7d, 0xb1, 0xd3, + 0x7d, 0x61, 0xba, 0x0f, 0x9b, 0x36, 0xaa, 0x9c, 0xb4, 0xaa, 0x64, 0xc9, 0x7f, 0x9d, 0x6e, 0xed, 0x80, 0x46, 0xd4, + 0xe8, 0xd9, 0x34, 0x6c, 0xf0, 0xb0, 0x9d, 0xee, 0x41, 0xe6, 0x0d, 0xb7, 0x2f, 0xa4, 0xc2, 0xe1, 0x1b, 0xdc, 0xa9, + 0x5e, 0xb5, 0xc0, 0x7b, 0x53, 0x19, 0x7d, 0x65, 0x1c, 0x5a, 0x0e, 0xd2, 0x6d, 0x53, 0x6e, 0x63, 0x2c, 0x9d, 0x74, + 0xb1, 0x71, 0x45, 0x84, 0x4a, 0xb7, 0x57, 0xa0, 0x14, 0x9f, 0xe8, 0x26, 0x33, 0x5f, 0x97, 0x3a, 0x31, 0x97, 0x50, + 0x0d, 0xf3, 0x79, 0x77, 0xa5, 0x13, 0x2d, 0x17, 0x36, 0xef, 0xee, 0x12, 0xfa, 0x04, 0x0d, 0x6b, 0x23, 0xb0, 0xdb, + 0xe7, 0xce, 0x0e, 0x32, 0x38, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, + 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x11, 0xf2, 0x14, 0xa2, 0xb0, 0xfa, 0xf1, 0x3d, 0xec, 0xc6, + 0x4d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, + 0x13, 0x97, 0x3f, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, + 0x2e, 0x58, 0x44, 0x69, 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0xa1, 0x5f, 0x96, + 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9a, 0xc6, 0xe7, 0x80, 0x6b, 0xfa, 0x57, 0x93, + 0x48, 0x46, 0xec, 0x1f, 0xce, 0x8a, 0xc7, 0xcb, 0xc2, 0x60, 0x9a, 0xe8, 0xeb, 0x24, 0x5b, 0xb4, 0xc1, 0x54, 0x2f, + 0x5b, 0x74, 0x6e, 0xb1, 0xfb, 0xbe, 0xb3, 0xdf, 0x77, 0x58, 0xf4, 0x99, 0xc9, 0x48, 0x99, 0x29, 0xe6, 0xbf, 0xef, + 0xec, 0xf7, 0x1d, 0xde, 0x1d, 0xcc, 0xb5, 0xbf, 0x50, 0x2c, 0xd9, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x6a, + 0x59, 0x26, 0x08, 0x6c, 0x2d, 0x01, 0xe2, 0x7c, 0xbe, 0x88, 0x2b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xab, + 0x54, 0xe0, 0x31, 0x41, 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd4, 0x93, 0x24, 0xc0, + 0xab, 0x1a, 0x95, 0xb7, 0x29, 0x52, 0x7e, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x44, 0x15, 0x03, 0x58, 0x95, 0x25, 0x7d, + 0x02, 0xa9, 0xe7, 0x07, 0x13, 0xfd, 0x65, 0x1b, 0x79, 0xec, 0x3b, 0xbf, 0x9f, 0x99, 0x9e, 0x15, 0x72, 0x39, 0x9d, + 0x81, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, + 0x33, 0xbd, 0xa4, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xfa, 0x48, 0xde, 0xfe, 0x0c, 0xd8, 0x4d, 0x89, 0x6e, 0xec, 0xc9, + 0x7b, 0x03, 0x3b, 0x00, 0x67, 0x84, 0xed, 0xab, 0xf8, 0x50, 0x81, 0xce, 0x1f, 0xe7, 0x84, 0xed, 0xab, 0xfa, 0x84, + 0xd9, 0xec, 0x19, 0xd9, 0x1a, 0x6e, 0x3f, 0xce, 0x1a, 0x39, 0x3a, 0xe9, 0xa4, 0x79, 0xcf, 0x13, 0x03, 0x0b, 0xd0, + 0x00, 0xb8, 0x3b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0xa0, 0x77, 0xc9, 0xa4, 0xbd, 0x2e, 0x37, 0x29, 0xeb, 0x75, 0xa7, + 0xa2, 0x82, 0x05, 0x9e, 0x05, 0x7b, 0x81, 0xda, 0xaf, 0x3d, 0x14, 0xe7, 0x71, 0xb6, 0x6d, 0x7a, 0x5e, 0xf6, 0xdd, + 0xdb, 0xb3, 0xc8, 0xd8, 0xa6, 0xbd, 0xd9, 0x43, 0x24, 0x2c, 0x27, 0xac, 0x03, 0x4e, 0xb8, 0xaa, 0x1d, 0x10, 0xa0, + 0x8f, 0x81, 0xc8, 0x8d, 0x25, 0x59, 0x6d, 0x2a, 0xa3, 0xfb, 0xc0, 0xef, 0x96, 0x12, 0xe9, 0x46, 0x5b, 0x12, 0x4c, + 0x9f, 0x60, 0xd4, 0x74, 0xe6, 0x69, 0xea, 0xda, 0xab, 0xcb, 0xdb, 0xa2, 0xad, 0x7f, 0x03, 0x1a, 0x9b, 0xed, 0x61, + 0x62, 0x28, 0x83, 0x18, 0xe8, 0x7d, 0xc4, 0x7b, 0x8d, 0x46, 0x86, 0x40, 0x21, 0x93, 0x0d, 0xb1, 0x4c, 0xbc, 0x16, + 0xfd, 0xe8, 0xc8, 0xc0, 0xa3, 0x4a, 0x40, 0x98, 0x82, 0x10, 0x12, 0x76, 0x6d, 0x10, 0x36, 0x5c, 0xae, 0x5a, 0x2e, + 0x6c, 0xa4, 0xda, 0xd0, 0xc1, 0xff, 0x2b, 0x5c, 0xb6, 0x7a, 0x66, 0xb9, 0x28, 0x06, 0x37, 0x73, 0x03, 0x16, 0x09, + 0xd2, 0xa3, 0xcd, 0xf6, 0x50, 0xdc, 0x9f, 0x8b, 0xcd, 0x86, 0x80, 0xc4, 0x1c, 0x26, 0x28, 0x1a, 0xce, 0x8d, 0x31, + 0x56, 0x49, 0xa5, 0x65, 0xad, 0x49, 0xcc, 0x41, 0xc0, 0xe8, 0x70, 0xdd, 0x57, 0xb7, 0x29, 0xc3, 0x77, 0xa9, 0xc0, + 0x37, 0xe0, 0x49, 0x93, 0x4a, 0xec, 0x1e, 0x2f, 0x28, 0x36, 0x44, 0xf7, 0x3c, 0x7b, 0x5b, 0xc0, 0x3a, 0x9b, 0x3d, + 0x22, 0x82, 0xdf, 0xd5, 0xaf, 0x36, 0xf8, 0x6e, 0xe1, 0x97, 0x60, 0xfd, 0x1c, 0x9c, 0xa4, 0x58, 0x34, 0x64, 0xb3, + 0x70, 0x47, 0x06, 0x94, 0xab, 0xf8, 0xe5, 0x30, 0x75, 0xa7, 0x18, 0xae, 0x7d, 0xbc, 0xc4, 0xef, 0xb6, 0xda, 0x6d, + 0xa8, 0xb2, 0xb8, 0xdd, 0x9b, 0xa2, 0x21, 0xab, 0xa6, 0xf7, 0x64, 0x6e, 0xa5, 0xd4, 0xbf, 0xde, 0xe1, 0xd6, 0x4e, + 0xfb, 0x7e, 0x9a, 0x6f, 0x3c, 0x3a, 0x57, 0x4d, 0xfb, 0xd4, 0x5a, 0x11, 0x1c, 0xfc, 0x6c, 0xe1, 0xe6, 0xce, 0x80, + 0x03, 0xf8, 0xf9, 0x3b, 0x9a, 0x57, 0x19, 0x44, 0xa7, 0xb7, 0x9a, 0xf1, 0x75, 0xfc, 0xe7, 0xb8, 0x11, 0xf7, 0xd3, + 0x3f, 0x93, 0x3f, 0xc7, 0x0d, 0xd4, 0x47, 0xf1, 0xe2, 0x76, 0xcd, 0xe6, 0x6b, 0x08, 0xb6, 0x76, 0xef, 0x04, 0xbf, + 0x0e, 0x4b, 0x72, 0x4d, 0x73, 0x9e, 0xad, 0xdd, 0x83, 0x80, 0x6b, 0xf7, 0x2a, 0xd1, 0xda, 0xbc, 0x71, 0xb5, 0x8e, + 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, 0x3d, 0xaa, + 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, 0xf5, 0x3d, + 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, 0x96, 0x34, + 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, 0xf2, 0x5d, + 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, 0x06, 0x5f, + 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, 0x87, 0xae, + 0xf2, 0xf0, 0x1e, 0x32, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, 0x61, 0x3e, + 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, 0x64, 0x85, + 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, 0x0c, 0xcb, + 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, 0xba, 0x8d, + 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, 0xf5, 0xd8, + 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, 0x64, 0x62, + 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, 0xee, 0xdc, + 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, 0x2d, 0x76, + 0xae, 0xde, 0xbd, 0xf0, 0x75, 0xbe, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, 0xce, 0xf4, + 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xec, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, 0x0c, 0x94, + 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, 0x20, 0x07, + 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, 0xdf, 0x83, + 0xbb, 0xb3, 0x7b, 0x1d, 0xb2, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, 0x39, 0xbc, + 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, 0x5a, 0xcc, + 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, 0x4b, 0xe9, + 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, + 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, 0xa5, 0xe6, + 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, + 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, 0xb0, 0xea, + 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0x81, 0xd1, + 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, 0x71, 0xac, + 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, 0x36, 0x32, + 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, 0xdb, 0x3c, + 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, 0x92, 0x41, + 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, 0x8b, 0x9a, + 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, 0x06, 0xf6, + 0xe9, 0xca, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, 0x2a, 0xe9, + 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, 0x08, 0xfc, + 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, 0x1e, 0x50, + 0x0c, 0xef, 0xae, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, 0x8b, 0x0b, + 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, 0xbf, 0x93, + 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, 0xa2, 0x30, + 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x5a, 0x3b, 0x65, 0x3a, 0x88, 0x0a, 0xf2, + 0xa4, 0x7c, 0x96, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, 0xc8, 0x34, + 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, 0x10, 0x8a, + 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, 0xeb, 0x85, + 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, 0xea, 0x83, + 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, 0x7f, 0xd2, + 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, 0xa9, 0xc6, + 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, 0x81, 0x55, + 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, 0x84, 0x72, + 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, 0xd8, 0xc2, + 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, 0x6f, 0x32, + 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x3c, 0xb0, 0xea, 0x7b, 0x84, 0x98, + 0x99, 0xf8, 0x4f, 0xf0, 0x2c, 0xf4, 0xb7, 0x9f, 0xa3, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, 0xec, 0x3f, + 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0xd6, 0xa1, + 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x94, + 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, + 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, 0x61, 0xdb, + 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0x28, + 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, 0x70, 0x19, + 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, 0x00, 0x05, + 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0x4f, 0xf2, 0xd6, 0x5e, 0xd0, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, 0xdb, 0x45, + 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, 0x95, 0x9b, + 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, 0x35, 0x90, + 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, 0x10, 0xf2, + 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, 0xc1, 0xe4, + 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, 0x6c, 0x2a, + 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, 0x4a, 0x55, + 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, 0xb2, 0xe5, + 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0x2c, 0x6c, 0xc2, 0xed, 0x30, 0xcd, 0x32, 0x6d, + 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, 0xdf, 0x06, + 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, 0x62, 0x37, + 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, + 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, + 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, 0x03, 0x6a, + 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, 0x2f, 0x43, + 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, 0x33, 0xd4, + 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, + 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, 0xd5, 0x9e, + 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xab, 0x8d, + 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, 0xc8, 0xc1, + 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, + 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, + 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, 0xd8, 0xe5, + 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, 0xc8, 0x81, + 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xeb, + 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, + 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, + 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, 0x6a, 0x8b, + 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, + 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0xaa, + 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, 0x70, 0x23, + 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, 0xfc, 0x4e, + 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, 0x7a, 0x5f, + 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, 0x03, 0x44, + 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, 0xc8, 0x6e, + 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, 0x4c, 0xd9, + 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, 0x2e, 0x40, + 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, 0xb8, 0x30, + 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, 0x5e, 0x66, + 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, 0xad, 0xcd, + 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, 0x47, 0xf7, + 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, 0x1e, 0x6c, + 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, 0x45, 0x19, + 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, + 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, + 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0xe5, 0xce, + 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, 0x9c, 0xe3, + 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, 0xe4, 0xb6, + 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, 0xa6, 0x82, + 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, 0xef, 0x3d, + 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, 0x5a, 0xbd, + 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, 0x75, 0x0e, + 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, 0x84, 0x56, + 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, 0xce, 0x86, + 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, 0x8b, 0x5e, + 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, 0xcd, 0xb8, + 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, 0x29, 0x84, + 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, 0x24, 0xf3, + 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, 0xc2, 0x18, + 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, 0x02, 0xff, + 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x06, + 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, 0xf0, 0x93, + 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, + 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, + 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, 0xc0, 0x3b, + 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, 0xae, 0x9f, + 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, + 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, + 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, 0x87, 0x80, + 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, 0x3a, 0x3a, + 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, 0x93, 0x0f, + 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, 0x5a, 0x05, + 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, 0xcd, 0x84, + 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, 0xed, 0xbd, + 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, 0x1f, 0x1f, + 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, 0xf6, 0xca, + 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, 0x67, 0xe4, + 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, 0x9c, 0x7c, + 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, 0x76, 0x17, + 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, 0xbb, 0x81, + 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, 0x25, 0xcb, + 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, 0xf8, 0xcf, + 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, 0x86, 0xa6, + 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, 0x1a, 0x43, + 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, 0x77, 0x21, + 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, 0xd8, 0xfb, + 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, 0x82, 0xc4, + 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, 0x7c, 0x75, + 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, 0xac, 0xaa, + 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, 0xe5, 0xe1, + 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, 0x11, 0xc6, + 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, 0xdd, 0x75, + 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, 0x35, 0x97, + 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, 0xa0, 0x51, + 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, 0xb1, 0x7c, + 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, 0x72, 0xbc, + 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, 0x5d, 0x52, + 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0xff, 0xb2, 0xf7, 0xae, 0xcb, 0x6d, + 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, 0xa8, 0x32, + 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, 0xe0, 0x06, + 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, 0xfd, 0x3a, + 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0x2f, 0xe2, 0x05, 0xad, 0x77, 0x15, 0x0a, 0x8f, + 0xaa, 0x28, 0xe5, 0x56, 0x72, 0x9d, 0x41, 0x10, 0x3b, 0x7a, 0x61, 0xf8, 0x13, 0x08, 0x21, 0x88, 0x30, 0xe1, 0xb7, + 0x61, 0x46, 0xdb, 0x59, 0xa4, 0x93, 0x7e, 0x1f, 0x66, 0xb8, 0x81, 0x95, 0xfc, 0x5c, 0xf5, 0xd9, 0x7e, 0x1b, 0x84, + 0x6c, 0x17, 0x44, 0xec, 0xa6, 0xd8, 0x06, 0xa5, 0x75, 0x24, 0x7e, 0x54, 0x86, 0xbf, 0xa5, 0xd7, 0xcb, 0x43, 0x88, + 0xf7, 0xe9, 0xa5, 0xf9, 0x59, 0xda, 0x8a, 0x02, 0xdc, 0x47, 0xe8, 0x51, 0x1d, 0x08, 0x76, 0xc2, 0x13, 0x1e, 0xc0, + 0xc9, 0x6a, 0x56, 0xf1, 0xf7, 0x29, 0x88, 0x13, 0x05, 0x87, 0x80, 0xab, 0xed, 0xc7, 0xf4, 0x2b, 0x18, 0xbe, 0x74, + 0xb0, 0xe5, 0xf0, 0xa6, 0xd8, 0xf6, 0x58, 0xc9, 0xdf, 0x01, 0xfb, 0x56, 0x4f, 0xc6, 0xea, 0xf6, 0xc0, 0x59, 0x97, + 0x52, 0x74, 0xbc, 0x29, 0x0e, 0x6f, 0xcf, 0x67, 0xfb, 0x6d, 0x10, 0xb1, 0x5d, 0x90, 0x61, 0xad, 0x93, 0x86, 0xe3, + 0x60, 0x08, 0x9f, 0xc5, 0x08, 0xfb, 0xbf, 0xac, 0x07, 0x5e, 0x42, 0x6a, 0x28, 0x70, 0x31, 0xd8, 0x70, 0xb4, 0xb6, + 0xcb, 0x34, 0x70, 0x53, 0x83, 0x5e, 0xdf, 0x53, 0x88, 0xf2, 0x92, 0xd1, 0xdc, 0x08, 0xd6, 0x8d, 0x21, 0x17, 0x87, + 0xe3, 0x66, 0x39, 0xe4, 0x25, 0x4d, 0xa7, 0x41, 0x28, 0xdd, 0x59, 0xd6, 0x90, 0x44, 0xd9, 0x07, 0xa1, 0x76, 0x6d, + 0xd9, 0x6f, 0x03, 0xdb, 0x97, 0x3f, 0x1a, 0xc6, 0xfe, 0xc5, 0xf2, 0xb1, 0x90, 0x2e, 0xe2, 0x39, 0x08, 0xa2, 0xf6, + 0xf3, 0x6c, 0xb8, 0xf1, 0x2f, 0xd6, 0x8f, 0x85, 0xf2, 0x1b, 0xcf, 0x6d, 0x39, 0x24, 0xcd, 0x5a, 0xf8, 0xc2, 0x38, + 0x25, 0xb8, 0x32, 0xb4, 0x1d, 0x0e, 0x42, 0xff, 0x6d, 0xd6, 0x08, 0x6e, 0x6c, 0x68, 0x9f, 0x2f, 0x7c, 0xd8, 0xda, + 0x68, 0xac, 0x29, 0xa6, 0x5b, 0xe8, 0xdf, 0x64, 0xb6, 0xb4, 0xa7, 0x51, 0xc9, 0x8b, 0x53, 0xd3, 0x88, 0x85, 0x30, + 0x60, 0xe8, 0x27, 0xf3, 0x0e, 0x54, 0x73, 0xc7, 0x23, 0x90, 0xc9, 0x07, 0x7a, 0xb0, 0x26, 0xb5, 0xea, 0xaf, 0x61, + 0x26, 0xff, 0x8f, 0x54, 0x58, 0x8c, 0xee, 0xb6, 0x61, 0xa6, 0xfe, 0x88, 0xe4, 0x1f, 0x2c, 0xe7, 0xbb, 0xd4, 0x0b, + 0xb5, 0x1f, 0x0b, 0x2b, 0x30, 0x28, 0x51, 0x35, 0xa0, 0x07, 0x22, 0xa8, 0xca, 0x20, 0xcd, 0xb0, 0x3a, 0x07, 0xfd, + 0xee, 0x69, 0xd5, 0x91, 0x1c, 0xd2, 0x5a, 0x0d, 0xa9, 0x60, 0xaa, 0xd4, 0x20, 0x3f, 0x1c, 0x6e, 0x53, 0xa6, 0xcb, + 0x80, 0x4b, 0xfa, 0x6d, 0xaa, 0x94, 0xc2, 0x5f, 0x10, 0x80, 0xce, 0xc1, 0x3d, 0xbe, 0x1c, 0x03, 0x69, 0x86, 0x85, + 0xdf, 0x9a, 0x1d, 0x5f, 0x93, 0x70, 0x9b, 0x04, 0x17, 0x03, 0x9c, 0xa3, 0xab, 0xb0, 0xbc, 0x4d, 0x21, 0x82, 0xaa, + 0x84, 0xfa, 0x56, 0xa6, 0x41, 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, + 0x11, 0xd7, 0x33, 0xc2, 0x9a, 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, + 0x8d, 0xab, 0x4a, 0x55, 0x77, 0x73, 0x6a, 0x29, 0x2d, 0xdb, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, + 0xe4, 0x08, 0x26, 0x90, 0x24, 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, + 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0x7f, 0x11, 0x46, + 0x9a, 0xcc, 0x58, 0xc9, 0x22, 0xdb, 0xd5, 0x29, 0x71, 0x1e, 0x27, 0xb0, 0x3d, 0x9a, 0xde, 0xf2, 0x7d, 0x06, 0x51, + 0x41, 0xa0, 0x60, 0xc6, 0x7c, 0xd9, 0xc5, 0x13, 0xdf, 0x67, 0x96, 0xa9, 0xfb, 0x70, 0x30, 0x66, 0x6c, 0xbf, 0xdf, + 0xcf, 0xfb, 0x7d, 0x35, 0xdf, 0xfa, 0xfd, 0xe4, 0xa9, 0xf9, 0xdb, 0x03, 0x06, 0x05, 0x39, 0x11, 0x4d, 0x85, 0x08, + 0xfe, 0x21, 0x79, 0x8c, 0x64, 0x74, 0xc7, 0x7d, 0x6e, 0x79, 0x7e, 0x56, 0x47, 0x20, 0x98, 0x87, 0xc3, 0xa5, 0x02, + 0xbb, 0x96, 0x28, 0x12, 0xb2, 0xfc, 0xc7, 0x60, 0x3c, 0x73, 0x1f, 0x60, 0xc9, 0x00, 0x84, 0xad, 0xf2, 0x74, 0xbd, + 0xe7, 0xab, 0xe0, 0x9d, 0x8e, 0x77, 0x8d, 0x15, 0x19, 0x88, 0x5b, 0x60, 0x23, 0xd6, 0xda, 0x03, 0x72, 0xa6, 0x00, + 0xc7, 0x8b, 0xc3, 0xe1, 0x5c, 0xfe, 0xd2, 0xcd, 0xd6, 0x09, 0x54, 0x0a, 0xdc, 0x1e, 0x9d, 0x1c, 0xfc, 0x0f, 0xa0, + 0x19, 0x94, 0xc3, 0xbc, 0xde, 0xfe, 0xc1, 0x9c, 0xfc, 0xf4, 0x14, 0xff, 0x84, 0x87, 0xe8, 0xf4, 0xdb, 0xbd, 0xf9, + 0x83, 0xa2, 0xf2, 0x70, 0x50, 0x8b, 0xff, 0x9c, 0xf3, 0x0a, 0x7e, 0xe1, 0x9b, 0xc0, 0x6c, 0x32, 0xf5, 0x4e, 0xbe, + 0xc9, 0x73, 0xa6, 0x5e, 0xe3, 0x15, 0x93, 0xef, 0x70, 0x38, 0x17, 0xa3, 0x7a, 0x3b, 0x72, 0xa2, 0x9d, 0x72, 0x8c, + 0x83, 0xc1, 0x7f, 0x11, 0x6d, 0x13, 0x02, 0x0c, 0xe5, 0x12, 0xcd, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, + 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, + 0x88, 0x53, 0x9c, 0x80, 0x08, 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x04, 0xc1, 0x90, 0xaf, 0x25, 0xe0, + 0xae, 0xd7, 0xab, 0x31, 0xbe, 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, + 0x81, 0x67, 0xcb, 0xde, 0x44, 0xb9, 0xdb, 0xf0, 0xb4, 0x1f, 0x5b, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, + 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, + 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0x67, 0xd6, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0xc7, 0x0a, 0x1f, + 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x22, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, + 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, + 0xd3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0x0b, 0x3b, 0xb7, 0x63, 0xd7, 0xc5, 0x0f, 0xe2, 0x6d, 0x6d, 0x47, 0x7f, + 0xec, 0x20, 0xd2, 0x71, 0x4f, 0x2e, 0xd4, 0x97, 0x90, 0x4a, 0x2e, 0xd4, 0x0d, 0xc4, 0x2e, 0xd4, 0x78, 0xc7, 0x45, + 0xac, 0xf5, 0x37, 0x35, 0x0a, 0x56, 0x02, 0xce, 0xb4, 0x37, 0x60, 0xb0, 0x81, 0x75, 0xcb, 0x32, 0xf8, 0x1b, 0xae, + 0x69, 0x02, 0x37, 0x2c, 0xb2, 0xde, 0x1b, 0x6c, 0xa5, 0x37, 0xe0, 0x68, 0x99, 0x38, 0x97, 0x92, 0xa4, 0x6c, 0x91, + 0x71, 0xf5, 0x28, 0xa4, 0x6a, 0xba, 0xbf, 0x11, 0xf5, 0xbd, 0x10, 0x79, 0xb0, 0x4a, 0x59, 0x54, 0xac, 0x40, 0x66, + 0x0f, 0xfe, 0x1e, 0x32, 0x72, 0x94, 0x03, 0x47, 0xa1, 0x7f, 0x36, 0x81, 0xce, 0x23, 0x22, 0x9d, 0x47, 0x82, 0xad, + 0xd4, 0x43, 0x61, 0xe5, 0x05, 0x44, 0x07, 0xab, 0x23, 0xde, 0x54, 0x9e, 0x84, 0x8a, 0x4d, 0x99, 0xc8, 0xe3, 0xa0, + 0x96, 0x80, 0xb1, 0x82, 0x60, 0xce, 0x72, 0xe9, 0x82, 0x54, 0x35, 0x7a, 0x58, 0x64, 0xee, 0x1f, 0x04, 0xe5, 0xff, + 0x41, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x7f, 0x00, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x8c, 0x2e, 0x99, 0xb3, + 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, 0xc1, 0x74, 0x7b, 0x4a, 0xab, + 0xee, 0x61, 0xc3, 0x93, 0xd2, 0x43, 0xa5, 0xbe, 0x8d, 0x09, 0x2c, 0xab, 0x94, 0xe1, 0xdb, 0x09, 0x55, 0x27, 0x06, + 0x15, 0xeb, 0x86, 0x2d, 0xe1, 0x10, 0x8b, 0x49, 0x63, 0x9d, 0x0d, 0x78, 0xc4, 0x12, 0xf8, 0x67, 0xc3, 0xc7, 0x6c, + 0xc9, 0xa3, 0xc9, 0xe6, 0x6a, 0xd9, 0xef, 0x97, 0x5e, 0xe8, 0xd5, 0xb3, 0xec, 0x87, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, + 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x07, 0x78, 0xed, 0x07, 0x1e, + 0xa9, 0x25, 0x95, 0x5c, 0x65, 0xb0, 0xbf, 0x0f, 0x78, 0xe4, 0xb3, 0xce, 0x4f, 0xcb, 0xa6, 0x4b, 0xf7, 0x33, 0xab, + 0x03, 0x22, 0xdd, 0x01, 0x36, 0xde, 0x36, 0xe8, 0xc8, 0xbf, 0xdd, 0x21, 0xa5, 0x6e, 0x32, 0x00, 0xbb, 0xd1, 0x00, + 0x87, 0x4c, 0xf5, 0x52, 0x64, 0xf5, 0x52, 0xa6, 0x7a, 0x49, 0x56, 0x2e, 0xc1, 0x42, 0x62, 0xaa, 0xdc, 0x46, 0x56, + 0x6e, 0xd9, 0x70, 0x3d, 0x1c, 0x6c, 0xad, 0xb8, 0x6c, 0x6e, 0xe1, 0xbe, 0xb0, 0xa2, 0xc0, 0xff, 0x1b, 0xb6, 0x60, + 0x77, 0xf2, 0x18, 0xb8, 0x46, 0xc7, 0xa4, 0xc8, 0xab, 0xd8, 0x1d, 0xbb, 0x01, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, + 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, 0x8d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x6e, + 0x0f, 0x87, 0x6b, 0xcf, 0x67, 0xf7, 0xf8, 0xe3, 0xfc, 0xf6, 0x70, 0xd8, 0x79, 0x46, 0xbd, 0xf7, 0x86, 0x27, 0xec, + 0x11, 0x4f, 0x26, 0x6f, 0xae, 0x78, 0x3c, 0x19, 0x0c, 0xde, 0xf8, 0x0b, 0x5e, 0xcf, 0xde, 0x80, 0x76, 0xe0, 0x7c, + 0x21, 0x75, 0xcd, 0xde, 0x0d, 0xcf, 0xbc, 0x05, 0x8e, 0xcd, 0x0d, 0x1c, 0xbd, 0xfd, 0xbe, 0x77, 0xcb, 0x23, 0xef, + 0x86, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0x37, 0xc1, + 0x23, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x1b, 0xd5, + 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x88, 0xbf, 0x61, 0x77, 0xdc, 0xb0, 0xcd, + 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x50, 0xea, 0xda, 0x82, 0x64, 0x6e, 0x5d, 0xf9, 0x10, 0x38, 0x1c, 0x90, + 0x9f, 0x6e, 0x11, 0x07, 0xa1, 0x75, 0x93, 0xd5, 0x5c, 0x51, 0xce, 0x85, 0x36, 0xca, 0xbc, 0x1c, 0x58, 0xcc, 0x52, + 0x0a, 0x8d, 0x05, 0x00, 0x82, 0x49, 0xa1, 0xb5, 0xf7, 0x32, 0x80, 0x9c, 0xa0, 0xe1, 0x8f, 0xcd, 0x55, 0x49, 0xd6, + 0xb2, 0x25, 0x21, 0xca, 0x76, 0x3d, 0xbc, 0x44, 0xc8, 0xb4, 0x7e, 0xff, 0x9c, 0x48, 0xd6, 0x26, 0xd5, 0x55, 0x8d, + 0x96, 0x80, 0x8a, 0x2c, 0x01, 0x13, 0xbf, 0xd2, 0x7c, 0x02, 0xf0, 0xa4, 0xe3, 0x41, 0xf5, 0x03, 0xaf, 0x99, 0x20, + 0xb2, 0x8d, 0xca, 0x9f, 0x14, 0x4f, 0x91, 0x8c, 0xa0, 0xf8, 0xa1, 0x56, 0x19, 0x0b, 0xc3, 0x3c, 0x50, 0x40, 0xde, + 0xbd, 0x3b, 0xf5, 0x2d, 0xda, 0x9a, 0x8e, 0x3d, 0x5b, 0xab, 0x50, 0x0b, 0x35, 0x85, 0x4b, 0x0e, 0xd1, 0x15, 0x68, + 0xa0, 0x88, 0x64, 0x3c, 0x79, 0x3d, 0xb8, 0x9c, 0x44, 0x57, 0x5c, 0xa0, 0x33, 0xbe, 0xbe, 0xe9, 0xa6, 0xb3, 0xe8, + 0x87, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, 0xf0, 0xf5, + 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0xfe, 0x81, 0x2a, 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x87, 0x4a, 0xee, 0x7b, 0x40, 0x5a, + 0xcb, 0x4b, 0x2e, 0xdf, 0x8f, 0x10, 0x63, 0xc4, 0x0f, 0xbc, 0x92, 0x47, 0x2c, 0x54, 0x53, 0xb8, 0xe6, 0x11, 0x82, + 0xbc, 0x65, 0x3a, 0xf8, 0x5b, 0x4f, 0x9c, 0xee, 0x4f, 0x94, 0x76, 0xf1, 0x85, 0xc5, 0xb4, 0x72, 0xa4, 0x1b, 0x90, + 0x83, 0x0d, 0xd3, 0x45, 0x41, 0xb6, 0x29, 0x8d, 0xa0, 0x8d, 0x96, 0x03, 0x1b, 0x4e, 0xa5, 0x36, 0x9c, 0xb9, 0x86, + 0xe0, 0x3e, 0x3f, 0x4f, 0x47, 0x0b, 0xf8, 0x90, 0xea, 0xf6, 0x12, 0x3f, 0x0f, 0x1b, 0x2d, 0x90, 0xd9, 0x11, 0x9f, + 0xd9, 0x44, 0xd2, 0x49, 0x9d, 0x2b, 0x60, 0xb7, 0xb3, 0x6b, 0x90, 0x23, 0x66, 0xee, 0x2b, 0x54, 0xdf, 0xa2, 0x01, + 0x57, 0xc6, 0xda, 0xd7, 0x24, 0x63, 0xe1, 0x55, 0x39, 0x0d, 0x07, 0x00, 0x43, 0x97, 0xd1, 0xd7, 0x96, 0x9b, 0x2c, + 0x7b, 0x5d, 0x40, 0x10, 0x44, 0x49, 0x3c, 0x3e, 0xe0, 0x7d, 0x59, 0x0d, 0x35, 0x4a, 0x3e, 0x96, 0x1d, 0xc3, 0xd7, + 0x4b, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, 0x1f, 0x19, 0xcf, + 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x60, 0x69, 0xe6, 0x8b, 0x85, 0xbf, 0xd8, 0x39, 0x89, 0x88, 0x82, 0xc0, 0x8e, 0x84, + 0x07, 0x91, 0xfa, 0x51, 0xe5, 0xe9, 0x4e, 0xf5, 0xd9, 0x7e, 0x61, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, + 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, + 0x9d, 0xc6, 0x36, 0x3c, 0x36, 0x62, 0xd9, 0xd2, 0x5b, 0xb3, 0x5b, 0xb6, 0x62, 0x37, 0xaa, 0x4e, 0x0b, 0x1e, 0x4e, + 0x87, 0x97, 0x01, 0xae, 0xbe, 0xf5, 0x39, 0xe7, 0xb7, 0x74, 0x82, 0xad, 0x07, 0x3c, 0x9a, 0x88, 0xd9, 0xfa, 0x87, + 0x48, 0x2d, 0x9e, 0xf5, 0x90, 0x2f, 0x68, 0xfd, 0x89, 0xd9, 0xad, 0x49, 0xbe, 0x1d, 0xf0, 0xc5, 0x64, 0xfd, 0x43, + 0x04, 0xaf, 0xfe, 0x00, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0x1f, 0x22, 0x1c, 0xb3, 0xdb, 0x1f, 0x22, 0x1a, 0xb5, + 0x95, 0xdc, 0x97, 0x6e, 0x1a, 0x10, 0x56, 0x6e, 0x58, 0x0c, 0xaf, 0x81, 0x78, 0xa6, 0x8d, 0xa4, 0x6b, 0x69, 0xe8, + 0x8d, 0x79, 0x38, 0x8d, 0x83, 0x35, 0xb5, 0x42, 0x9e, 0x19, 0x62, 0x16, 0xff, 0x10, 0xcd, 0xd9, 0x0a, 0x2b, 0xb2, + 0xe1, 0xf1, 0xe0, 0x72, 0xb2, 0xb9, 0xe2, 0x6b, 0x20, 0x3f, 0x9b, 0x6c, 0xcc, 0x16, 0x75, 0xc3, 0xc5, 0x6c, 0xf3, + 0x43, 0x34, 0x9f, 0xac, 0xa0, 0x67, 0xed, 0x01, 0xf3, 0x5e, 0x82, 0x08, 0x25, 0x21, 0x35, 0xe5, 0xa6, 0xd7, 0x63, + 0xeb, 0x71, 0x70, 0xcb, 0xd6, 0x97, 0xc1, 0x0d, 0x5b, 0x8f, 0x81, 0x88, 0x83, 0xfa, 0xdd, 0xdb, 0xc0, 0xe2, 0x8b, + 0xd8, 0xfa, 0xd2, 0xa4, 0x6d, 0x7e, 0x88, 0x98, 0x3b, 0x38, 0x0d, 0x5c, 0xb0, 0xd6, 0x99, 0xb7, 0x62, 0x70, 0x09, + 0x59, 0x7a, 0x31, 0xdb, 0x0c, 0x2f, 0xd9, 0x7a, 0x84, 0x53, 0x3d, 0xf1, 0xd9, 0x2d, 0xbf, 0x61, 0x09, 0x5f, 0x35, + 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, 0x0a, 0x65, 0xb1, 0x30, 0x2a, 0xf7, 0x2d, 0x38, 0xa0, + 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0xeb, 0x70, 0xfd, 0x51, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, 0x60, 0xfa, + 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0xbf, 0x17, 0x69, 0xee, 0x16, 0xae, 0x53, + 0x98, 0x15, 0x05, 0xaa, 0x9f, 0x92, 0xd2, 0xc0, 0x42, 0x25, 0x32, 0x95, 0x82, 0x5f, 0xd6, 0x4e, 0xbb, 0xce, 0x8e, + 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, + 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, + 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xdd, 0x66, 0x0e, 0xd2, + 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0xb6, 0x86, 0x47, 0x55, 0xac, 0xdc, 0x9b, 0x3c, 0x47, + 0x38, 0xa3, 0x4b, 0x99, 0x00, 0xb8, 0xde, 0x2f, 0xc2, 0x5a, 0xe1, 0x15, 0x35, 0x8b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, + 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, + 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, 0x0b, 0x40, 0x4d, 0x3f, 0xd6, 0x62, 0x5d, 0x05, 0xa5, + 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, 0x26, 0x4a, 0xe4, 0xfc, 0x58, 0x94, 0x62, 0x59, 0x8a, + 0x2a, 0x69, 0x37, 0x14, 0x3c, 0x22, 0xdc, 0x06, 0x8d, 0x99, 0xdb, 0x13, 0x5d, 0xb4, 0x22, 0x94, 0x63, 0xb3, 0x8e, + 0x91, 0x46, 0x99, 0x9d, 0xec, 0x3a, 0x59, 0x68, 0xbf, 0xaf, 0x72, 0xc8, 0x3a, 0x60, 0x8d, 0xe4, 0xeb, 0x35, 0x87, + 0x6e, 0x1b, 0xe5, 0xc5, 0xbd, 0xe7, 0x2b, 0x38, 0xcd, 0xf1, 0xc4, 0xee, 0x7a, 0xdd, 0x29, 0x12, 0xf1, 0x0a, 0x27, + 0x55, 0x3e, 0x92, 0x85, 0xe3, 0xce, 0x9d, 0xd6, 0x62, 0x55, 0xb9, 0xac, 0xa7, 0x16, 0x47, 0x04, 0x3e, 0x95, 0x47, + 0x7b, 0xa1, 0x6d, 0x51, 0x2c, 0x84, 0xd1, 0xa3, 0x13, 0x7e, 0x52, 0x02, 0xeb, 0xeb, 0x70, 0x58, 0xfa, 0x11, 0x47, + 0xbf, 0xd3, 0x68, 0xb4, 0x20, 0xa4, 0xe1, 0xa9, 0x17, 0x8d, 0x16, 0x75, 0x51, 0x87, 0xd9, 0xd3, 0x5c, 0x0f, 0x14, + 0x86, 0x11, 0xa8, 0x1f, 0x5c, 0x65, 0xf0, 0x59, 0x84, 0xa8, 0x79, 0x60, 0x9a, 0x0d, 0xe1, 0xa8, 0x0b, 0x3c, 0xb4, + 0x82, 0x16, 0x33, 0xf3, 0x51, 0x88, 0xe1, 0x43, 0xba, 0x38, 0x7f, 0x42, 0x56, 0x3e, 0xc0, 0xee, 0xd0, 0x5d, 0x28, + 0xe7, 0x4c, 0xc5, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, 0x8c, 0x8e, + 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x96, 0xab, 0x09, 0x43, 0xe1, 0x13, 0x03, 0xdd, 0xfc, 0xc6, 0x6f, + 0xcf, 0x5b, 0x30, 0xb2, 0x4b, 0x52, 0xbc, 0xd6, 0x0c, 0xf7, 0x1b, 0x70, 0x3b, 0x02, 0xca, 0x9a, 0xea, 0x98, 0x64, + 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x7b, 0x59, 0x14, 0x38, 0x80, 0xab, 0x99, + 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0xf6, 0xaa, 0xea, 0x90, 0xac, 0x9a, 0x1f, 0xcc, 0xe6, + 0x4d, 0xc3, 0xc4, 0x88, 0x20, 0xba, 0x08, 0x27, 0x98, 0x5e, 0x91, 0xbe, 0x56, 0x72, 0x3a, 0x5a, 0x75, 0xb4, 0x96, + 0x98, 0x98, 0x2b, 0x8a, 0xbf, 0x06, 0x3c, 0x6e, 0xf0, 0xea, 0x24, 0x4d, 0x27, 0xaa, 0x47, 0x8f, 0x5f, 0xa7, 0xe9, + 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7e, 0x41, 0x11, 0x17, 0x35, 0xb8, 0xf2, 0x4e, + 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, 0x0e, 0x5c, + 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x44, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xcc, 0x59, 0x35, 0x5a, 0xa8, 0xcc, 0x08, 0xed, + 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xe3, 0x3d, 0xba, 0xab, 0xce, 0x32, 0x93, + 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xad, 0x0e, 0x90, 0x51, 0x7b, 0xed, 0x77, 0x9d, + 0xe5, 0xab, 0x9b, 0xad, 0xa1, 0xa8, 0xd4, 0x4a, 0x52, 0x1c, 0x64, 0xb8, 0x6e, 0x2b, 0x1f, 0x2e, 0x2e, 0xa0, 0x67, + 0x8c, 0x44, 0xe6, 0xf9, 0x13, 0xf9, 0x12, 0x9c, 0x33, 0xce, 0x0a, 0x81, 0x09, 0x63, 0xf5, 0xae, 0xb5, 0x54, 0x1a, + 0x52, 0x8c, 0x1d, 0x8d, 0xb2, 0xac, 0xb2, 0x74, 0x99, 0xad, 0x25, 0x6c, 0x59, 0x45, 0x6e, 0x61, 0xb7, 0x99, 0xac, + 0xe6, 0xbb, 0x8a, 0x3b, 0x28, 0xdf, 0x6c, 0x95, 0xf1, 0xbd, 0x44, 0xf6, 0x6e, 0x03, 0x25, 0x3c, 0x1d, 0xfd, 0x05, + 0xe9, 0xb7, 0x19, 0xc6, 0x29, 0xb7, 0x95, 0xb4, 0x00, 0xa7, 0x7f, 0x38, 0xbc, 0xab, 0x30, 0x68, 0x70, 0x84, 0x71, + 0x64, 0xfd, 0xfe, 0xa2, 0xf2, 0x6a, 0x4c, 0xd4, 0xf1, 0x59, 0xfd, 0x7e, 0x45, 0x0f, 0xa7, 0xd5, 0x68, 0x95, 0x6e, + 0x91, 0x9d, 0xd0, 0xc6, 0xca, 0x0f, 0x6a, 0x05, 0xcc, 0xde, 0xfa, 0x7c, 0x3a, 0x00, 0x1d, 0x0b, 0x90, 0x68, 0x36, + 0x13, 0x89, 0x39, 0xe9, 0x9e, 0x84, 0xc7, 0x07, 0x16, 0x38, 0xc0, 0x54, 0xfc, 0x5f, 0xc2, 0x9b, 0x81, 0x0d, 0x1a, + 0x25, 0xfa, 0x1a, 0x5d, 0xd5, 0xe6, 0x46, 0xc7, 0x4b, 0x4f, 0x21, 0x91, 0x15, 0xac, 0x9a, 0xfb, 0x72, 0x03, 0xa7, + 0x3d, 0xd4, 0x1c, 0x2a, 0x4b, 0xf0, 0xb7, 0x5f, 0xe6, 0x87, 0xc3, 0x2a, 0x83, 0xc2, 0x76, 0x6b, 0xa1, 0xbd, 0x31, + 0x4b, 0x35, 0x54, 0x84, 0x83, 0xce, 0x57, 0x62, 0x56, 0x8f, 0xe8, 0xef, 0xf9, 0xe1, 0xb0, 0x22, 0x30, 0xe0, 0xb0, + 0x94, 0x99, 0x68, 0xa1, 0x58, 0x5a, 0x67, 0x33, 0xaa, 0x03, 0x0f, 0x4c, 0xcc, 0x59, 0xb8, 0x03, 0xd0, 0x26, 0xb5, + 0x0a, 0xf4, 0x2a, 0xa2, 0x9f, 0xb8, 0x5f, 0xdb, 0xaf, 0xd7, 0x23, 0xb3, 0x74, 0xe4, 0xc6, 0x58, 0x00, 0x70, 0xe0, + 0x79, 0x4d, 0xf2, 0x9c, 0x7c, 0x0d, 0xed, 0x9e, 0x5c, 0xc8, 0x9f, 0xa0, 0x6c, 0xe1, 0xb9, 0x6a, 0x5a, 0x59, 0xac, + 0xb8, 0xaa, 0x5e, 0x5d, 0xf0, 0xca, 0x64, 0x5a, 0xa5, 0x95, 0xa8, 0x94, 0x60, 0x40, 0x5d, 0xe2, 0xb5, 0xa6, 0x19, + 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x7e, 0x69, 0x1c, 0x3e, 0xed, + 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0x2b, 0x1f, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, 0xc5, 0xc4, 0xee, + 0xd0, 0xbc, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, 0x01, 0x2f, 0x1e, + 0xea, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x2a, 0x26, 0xc0, 0x0f, 0x4a, + 0xad, 0xe9, 0xbd, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, 0xe7, 0xe3, 0xf9, + 0xa5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x79, 0xab, 0x7f, 0x98, 0xea, 0x5b, 0xe8, 0x4e, 0xd0, + 0x67, 0xe8, 0xaa, 0xea, 0xae, 0xc4, 0x16, 0x86, 0x7a, 0x62, 0x91, 0x17, 0xf2, 0xa4, 0x35, 0x76, 0x1c, 0xec, 0x0d, + 0x70, 0xe2, 0x97, 0x87, 0x83, 0xb8, 0xca, 0x7d, 0x76, 0xde, 0x35, 0xb2, 0x72, 0x00, 0x2b, 0x88, 0x82, 0x71, 0x6b, + 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xd5, 0xf8, 0xf8, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0xe4, 0x3f, 0x3c, 0x01, + 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7a, 0x39, 0x7d, 0x32, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, 0x31, 0x5f, 0x5d, + 0x32, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, 0xe6, 0x3e, 0x4c, + 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, 0x5d, 0x41, 0xba, + 0xe7, 0x11, 0xe9, 0xe5, 0x5e, 0x3a, 0xdd, 0xef, 0x4b, 0x01, 0x96, 0xfa, 0x52, 0x7c, 0x06, 0x85, 0x45, 0xe3, 0x1b, + 0x01, 0xda, 0x1a, 0xaa, 0x69, 0xaf, 0x14, 0x55, 0x2f, 0xe8, 0x95, 0xe2, 0x73, 0x4f, 0x0f, 0x95, 0xf9, 0xb2, 0x74, + 0xf4, 0x3f, 0xa1, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xe2, 0x68, 0xe3, 0x53, 0xbd, + 0x8a, 0x9b, 0x3e, 0xaf, 0xad, 0x65, 0x4e, 0x08, 0x9b, 0xee, 0x25, 0x40, 0x45, 0x5e, 0x09, 0x8f, 0x60, 0xf9, 0xe5, + 0x0f, 0x79, 0xba, 0x42, 0xb4, 0x8e, 0x7b, 0x96, 0xb9, 0x34, 0xf6, 0x2f, 0x0d, 0xa6, 0xaf, 0x6f, 0xb7, 0x45, 0x7e, + 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0xb7, 0xe1, 0x4a, 0xa0, 0xc0, 0xa1, 0x44, 0x62, 0x9b, 0x2a, 0x14, 0xf1, + 0x20, 0xe9, 0xd3, 0x45, 0xeb, 0xd3, 0x00, 0x53, 0x6b, 0x39, 0x30, 0x87, 0x70, 0x15, 0x17, 0x3e, 0x7a, 0xfa, 0x16, + 0xb3, 0x70, 0x3e, 0xf1, 0x3e, 0x78, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x38, 0xcc, 0xaa, 0xb9, + 0xef, 0xd0, 0x47, 0x7a, 0xa8, 0x72, 0x41, 0xd9, 0x1b, 0x63, 0x12, 0x81, 0xd2, 0x18, 0xef, 0xe3, 0xe0, 0x38, 0xef, + 0xd3, 0x00, 0x52, 0xfb, 0xc4, 0x3b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0x55, 0x7c, 0x9b, 0xa1, + 0x5c, 0x77, 0x4a, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x99, 0x57, 0xa3, 0x47, + 0x55, 0x12, 0x96, 0x22, 0xee, 0xf7, 0x77, 0x99, 0x67, 0xd8, 0x1b, 0x1e, 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, + 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, + 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, 0xfd, 0x06, 0xc7, 0x7c, 0x70, 0x1f, 0x71, + 0xbc, 0xc3, 0x59, 0x68, 0x09, 0x79, 0x72, 0xc7, 0x20, 0x4d, 0x63, 0x69, 0x04, 0x9c, 0x88, 0x64, 0x1b, 0x4b, 0xe1, + 0x08, 0x20, 0x20, 0xd0, 0x4d, 0x99, 0x61, 0x4c, 0x07, 0x23, 0xcf, 0xa3, 0x9e, 0xf1, 0x5e, 0x85, 0xa7, 0x90, 0x26, + 0xdb, 0xd7, 0xf3, 0xf7, 0x46, 0x90, 0x95, 0x5b, 0xce, 0xf1, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, 0x79, 0x8a, 0x59, + 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0xe7, 0x28, 0xbd, 0x65, 0x3e, 0x59, 0x45, 0xd2, 0xa5, 0xb7, + 0xe9, 0xf7, 0xe3, 0x91, 0x3a, 0xd4, 0xfc, 0x7d, 0x3c, 0x92, 0x67, 0xd8, 0x86, 0x25, 0x2c, 0xb4, 0x0a, 0xc6, 0x00, + 0x92, 0xd8, 0x88, 0x68, 0x30, 0xda, 0x9b, 0xc3, 0xe1, 0x7c, 0x63, 0xce, 0x92, 0x3d, 0xb8, 0xbe, 0xf2, 0xc4, 0xbc, + 0x03, 0x5f, 0xe6, 0x31, 0x41, 0xc4, 0x66, 0xde, 0x86, 0xd5, 0xe0, 0xc1, 0x0e, 0xae, 0x8f, 0xd8, 0xa2, 0x58, 0xeb, + 0x58, 0x2a, 0xeb, 0xe0, 0xb4, 0x8e, 0x4d, 0x33, 0x52, 0x8a, 0xec, 0x73, 0xec, 0xef, 0xdd, 0xe0, 0xea, 0xda, 0x18, + 0xd4, 0x1a, 0x77, 0x98, 0x3b, 0xa7, 0x02, 0xea, 0x31, 0x5d, 0x41, 0xf5, 0xac, 0x22, 0x5f, 0x7e, 0x6b, 0xe7, 0x80, + 0xa0, 0x11, 0x08, 0x5c, 0x34, 0xfe, 0x77, 0x5d, 0xca, 0x79, 0x17, 0x10, 0xe2, 0xbb, 0x14, 0xf4, 0xe9, 0x0c, 0x36, + 0xb1, 0xf9, 0x04, 0x62, 0xd1, 0x74, 0x9f, 0x6b, 0xcd, 0x7c, 0x31, 0xa2, 0x9d, 0x59, 0x77, 0x8b, 0xdc, 0x6a, 0x21, + 0x92, 0xd1, 0xb3, 0xcd, 0x84, 0xdb, 0x0e, 0xe5, 0x8c, 0x04, 0x4c, 0xd0, 0xda, 0x4a, 0xc9, 0xe7, 0xba, 0xd7, 0x09, + 0xda, 0x03, 0x49, 0xeb, 0xfe, 0xcd, 0xa2, 0x33, 0x4a, 0x4e, 0xae, 0x37, 0x39, 0x83, 0x14, 0x2c, 0xd8, 0x5e, 0xe6, + 0x84, 0x1b, 0xe0, 0x23, 0x9b, 0x25, 0xa7, 0x69, 0x90, 0xc7, 0x42, 0xd7, 0xec, 0x7d, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, + 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, + 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, + 0x98, 0x07, 0xee, 0x6c, 0xe3, 0x9a, 0xc0, 0x40, 0xa7, 0xf6, 0xb5, 0x28, 0xe7, 0x58, 0x45, 0xf4, 0x3e, 0x7f, 0x5f, + 0xd9, 0xd3, 0x07, 0x11, 0x36, 0x2a, 0xd0, 0x58, 0x4a, 0x8c, 0x8d, 0x1c, 0xff, 0x96, 0x28, 0x1b, 0x32, 0x04, 0x84, + 0x90, 0x36, 0x72, 0xfa, 0x61, 0x07, 0xad, 0x64, 0xda, 0xff, 0x93, 0xc4, 0x6f, 0x83, 0xbd, 0x9c, 0xfa, 0x53, 0x8f, + 0x78, 0xbc, 0xd6, 0xe8, 0x31, 0x25, 0xdd, 0x06, 0x79, 0xaa, 0x3c, 0x05, 0xc9, 0x84, 0xb1, 0x84, 0x60, 0x51, 0x2e, + 0x78, 0xce, 0x2b, 0x2e, 0xe1, 0x3e, 0x6a, 0x59, 0x11, 0xa1, 0x2a, 0x91, 0xd3, 0xe7, 0x2b, 0xe0, 0x99, 0x80, 0x40, + 0xc7, 0x18, 0x69, 0x54, 0xc1, 0x97, 0xc0, 0x58, 0x48, 0xca, 0x4e, 0x33, 0x12, 0x5c, 0x76, 0x3f, 0x22, 0x51, 0xea, + 0x0b, 0x52, 0x92, 0xbe, 0x11, 0x35, 0x5e, 0x89, 0x55, 0x44, 0x02, 0x19, 0x6a, 0x88, 0x58, 0x55, 0x4f, 0xdd, 0xab, + 0x62, 0x32, 0x18, 0x54, 0xbe, 0x9c, 0x9e, 0x78, 0x43, 0x43, 0xe5, 0x5d, 0x57, 0xb4, 0xd3, 0x33, 0xad, 0x94, 0xb7, + 0x90, 0x96, 0xa0, 0x69, 0x18, 0x69, 0x0e, 0xa5, 0xae, 0xa4, 0xbb, 0x31, 0x88, 0x2f, 0x99, 0xe8, 0xd9, 0x4e, 0xed, + 0x28, 0x6d, 0x49, 0x7b, 0x08, 0xe9, 0xb9, 0x4b, 0x3e, 0x66, 0x21, 0x57, 0x77, 0xca, 0x49, 0x79, 0x15, 0xa2, 0x93, + 0xfb, 0x1e, 0x43, 0x22, 0xd0, 0xe7, 0x1c, 0xc3, 0xba, 0x68, 0xa8, 0x73, 0x58, 0x21, 0x66, 0x0b, 0x25, 0xcc, 0x97, + 0x8c, 0xa7, 0x92, 0x41, 0x03, 0x20, 0x03, 0x3e, 0x7b, 0x19, 0x58, 0xfe, 0x0a, 0xe2, 0x47, 0x1b, 0x1f, 0x0e, 0x5f, + 0x6a, 0x0a, 0xb1, 0xfd, 0x02, 0x9b, 0x21, 0x3c, 0xaa, 0x07, 0x3c, 0xf3, 0x4d, 0x9c, 0xa0, 0xe5, 0x88, 0x93, 0xd9, + 0xd1, 0x44, 0xf6, 0xaa, 0x87, 0x70, 0x2a, 0x2b, 0x50, 0x47, 0x59, 0x67, 0x25, 0xfc, 0x08, 0x53, 0xdd, 0x4a, 0xac, + 0x05, 0xda, 0x5c, 0xad, 0x58, 0x0b, 0xe0, 0xc0, 0xcf, 0x21, 0x78, 0x22, 0x9f, 0x83, 0x8b, 0x41, 0x01, 0x3e, 0x07, + 0xc0, 0x8b, 0xdc, 0xd1, 0xb9, 0x3f, 0x3d, 0xb0, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, + 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x4e, 0x98, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x8f, + 0xf6, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0x87, 0xe5, 0x35, 0x60, 0x7a, 0x05, 0x91, + 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x6e, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x11, 0xa9, 0xae, 0x85, 0xb4, + 0x91, 0x4f, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfd, 0xe9, 0x6f, 0xcf, 0x3e, 0xbd, 0xfa, 0xf5, 0xa7, 0xc5, 0xab, 0xb7, + 0x2f, 0x5f, 0xbd, 0x7d, 0xf5, 0xe9, 0x77, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xfd, 0xbb, 0x8f, 0xaf, 0x9c, 0x0c, + 0x36, 0xcc, 0x58, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0x92, 0x39, 0x66, 0x62, 0x8e, + 0xb1, 0x77, 0x02, 0x93, 0x2d, 0xf0, 0x1d, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x37, 0xe0, + 0x22, 0x93, 0xe6, 0xb7, 0xbf, 0x12, 0xc4, 0x3e, 0xad, 0xa4, 0xdc, 0x57, 0xdb, 0x9a, 0xe7, 0xdb, 0xfb, 0xbd, 0x84, + 0xf3, 0x9f, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0xe7, 0xf0, 0xc7, 0x95, 0xb6, 0xa4, 0xc9, 0x2c, 0xda, 0xcf, 0x18, + 0x82, 0x2e, 0x0d, 0x3e, 0x88, 0x3d, 0xf2, 0x52, 0x9f, 0x2c, 0x24, 0x70, 0x47, 0x0c, 0x9f, 0x56, 0x04, 0xbd, 0x62, + 0x44, 0x71, 0xc9, 0x15, 0x2a, 0xa5, 0xe4, 0xdf, 0x28, 0xbb, 0xa8, 0x90, 0xb3, 0x82, 0xdd, 0x29, 0x72, 0x64, 0xfc, + 0x20, 0x98, 0xf8, 0x72, 0x70, 0xff, 0x25, 0xde, 0xe1, 0x4c, 0x71, 0x24, 0x27, 0xfc, 0x63, 0x86, 0x81, 0xfd, 0x39, + 0xf8, 0xbc, 0x3a, 0xcc, 0xcb, 0x1b, 0x7d, 0xca, 0x2d, 0xf9, 0x78, 0xb2, 0xbc, 0x02, 0x83, 0xfd, 0x52, 0x35, 0x77, + 0xcd, 0xeb, 0xd9, 0x72, 0xce, 0xf6, 0xb3, 0x68, 0x1e, 0xdc, 0xb2, 0x59, 0x36, 0x0f, 0x56, 0x0d, 0x5f, 0xb3, 0x1b, + 0xbe, 0xb6, 0xaa, 0xb6, 0xb6, 0xab, 0x36, 0xd9, 0xf0, 0x1b, 0x90, 0x10, 0xae, 0xc1, 0x2f, 0x39, 0x61, 0xb7, 0x3e, + 0xdb, 0x80, 0x44, 0xbb, 0x62, 0x1b, 0xb8, 0x88, 0xad, 0xf9, 0xab, 0xca, 0xdb, 0xb0, 0x92, 0x9d, 0x8f, 0x59, 0x8e, + 0xf3, 0xcf, 0x87, 0x07, 0xb4, 0x17, 0xea, 0x67, 0x97, 0xea, 0xd9, 0x44, 0xd9, 0xcd, 0x36, 0xa3, 0xc5, 0x5d, 0x5a, + 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x4d, 0x9c, 0xdf, 0xd3, 0xb6, + 0x5d, 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x9c, 0x3f, 0x85, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, + 0xfd, 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xfc, 0x52, 0x59, + 0xad, 0x34, 0x27, 0xa1, 0x6d, 0xc4, 0xaa, 0xe5, 0x48, 0xd5, 0x8c, 0x48, 0x1f, 0xa4, 0xe7, 0x7d, 0x8f, 0xa8, 0x06, + 0x7b, 0x32, 0xaf, 0x03, 0xfb, 0xf4, 0xae, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, + 0x78, 0xaf, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xa1, 0x0a, 0x38, 0x5f, 0xaf, 0x44, 0xbb, 0x13, 0x61, 0x57, + 0x2e, 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, + 0xce, 0x73, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xa5, 0x26, 0x13, 0x39, 0x28, 0x1f, + 0x0e, 0x05, 0xec, 0xa5, 0xc6, 0x4f, 0x13, 0x7e, 0xc2, 0xf2, 0xd6, 0xde, 0x9a, 0x52, 0x54, 0xd2, 0x00, 0x15, 0xf8, + 0x98, 0xc1, 0xff, 0xee, 0x0c, 0xb1, 0x60, 0x8a, 0x8e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x94, 0xad, + 0xd1, 0x4e, 0xc0, 0xa9, 0x8e, 0x93, 0x44, 0x38, 0xf5, 0x1e, 0x71, 0x51, 0xf7, 0x72, 0x88, 0xba, 0x61, 0x9f, 0x2a, + 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, 0x7b, 0x2b, 0x88, 0x20, 0x45, 0x36, 0xa2, 0x24, 0x8d, + 0x63, 0x91, 0xc3, 0xf6, 0xbe, 0x90, 0xfb, 0x7f, 0xbf, 0x0f, 0xe1, 0xa4, 0x55, 0x10, 0x97, 0x9e, 0x40, 0x44, 0x38, + 0x3a, 0xfc, 0x88, 0xf0, 0x44, 0xaa, 0x0a, 0xdf, 0xd7, 0x27, 0x6e, 0xcc, 0xee, 0x85, 0x39, 0xaa, 0xb7, 0x00, 0xc3, + 0x58, 0x6f, 0x2d, 0x42, 0x12, 0xad, 0x34, 0xa3, 0xad, 0x07, 0xc4, 0x88, 0x77, 0x6b, 0x8b, 0x0c, 0xc6, 0xda, 0x92, + 0x48, 0x00, 0xbf, 0x25, 0x21, 0x43, 0xdb, 0x46, 0x60, 0xc6, 0xf0, 0x76, 0x56, 0x5c, 0xba, 0x0e, 0xdb, 0x9c, 0xc3, + 0x17, 0xb2, 0xd0, 0xac, 0x23, 0x4a, 0x13, 0x84, 0xfc, 0x03, 0x4e, 0x16, 0x0a, 0xa3, 0x79, 0x71, 0x94, 0x4e, 0x12, + 0xeb, 0xbb, 0xae, 0x52, 0xc1, 0x66, 0xf3, 0x11, 0xf5, 0x65, 0x47, 0xc9, 0xd7, 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, + 0x44, 0x2d, 0x2a, 0xe7, 0x63, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xcd, 0x7a, 0x5d, 0x94, 0x75, 0xf5, 0x42, 0x44, 0x8a, + 0xde, 0x47, 0x3d, 0x7a, 0x24, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe5, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, + 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0xee, 0x65, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x03, 0xaf, 0x1c, 0xe5, + 0x97, 0x56, 0x9b, 0xf4, 0x2b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, + 0x62, 0x96, 0xe6, 0x7f, 0xe2, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x53, 0xe5, 0xd5, 0x72, 0x2d, 0x33, + 0xcd, 0xcd, 0x12, 0xc7, 0x8a, 0xc5, 0x45, 0xbd, 0xae, 0x44, 0x16, 0x08, 0x71, 0x84, 0x69, 0xac, 0xa7, 0xde, 0x28, + 0xad, 0xde, 0x23, 0xa1, 0xcc, 0x4f, 0xd8, 0xdb, 0xb1, 0xd7, 0x83, 0x2c, 0xc4, 0xb1, 0xe5, 0x60, 0xb3, 0xf5, 0x3e, + 0x95, 0xa9, 0x88, 0xcf, 0xea, 0xe2, 0x6c, 0x53, 0x89, 0xb3, 0x3a, 0x11, 0x67, 0x3f, 0x42, 0xce, 0x1f, 0xcf, 0xa8, + 0xe8, 0xb3, 0xfb, 0xb4, 0x4e, 0x8a, 0x4d, 0x4d, 0x4f, 0x5e, 0x62, 0x19, 0x3f, 0x9e, 0x11, 0x57, 0xcd, 0x19, 0x8d, + 0x64, 0x3c, 0x3a, 0x7b, 0x9f, 0x01, 0xc9, 0xeb, 0x59, 0xba, 0x82, 0xc1, 0x3b, 0x0b, 0xf3, 0xf8, 0xac, 0x14, 0xb7, + 0x60, 0x71, 0x2a, 0x3b, 0xdf, 0x83, 0x0c, 0xab, 0xf0, 0x4f, 0x71, 0x06, 0xd0, 0xae, 0x67, 0x69, 0x7d, 0x96, 0x56, + 0x67, 0x79, 0x51, 0x9f, 0x29, 0x29, 0x1c, 0xc2, 0xf8, 0xe1, 0x3d, 0x7d, 0x65, 0x97, 0xb7, 0x59, 0xdc, 0x65, 0x91, + 0x3f, 0x45, 0xaf, 0x22, 0x62, 0xd2, 0xa8, 0x84, 0xd7, 0xee, 0x6f, 0x9b, 0xfb, 0x87, 0xd7, 0x8d, 0xdd, 0xcf, 0xee, + 0x18, 0xd1, 0x05, 0xf5, 0x78, 0x25, 0x29, 0x15, 0x14, 0x10, 0x38, 0xd1, 0xac, 0xf1, 0xe0, 0x8e, 0x03, 0x5e, 0x0d, + 0x6c, 0xc9, 0xd6, 0x3e, 0x7f, 0x1a, 0xcb, 0x30, 0xed, 0x4d, 0x80, 0x7f, 0x95, 0xbd, 0xe9, 0x3a, 0x58, 0xe2, 0x7d, + 0x0b, 0xd9, 0x86, 0x5e, 0xbd, 0xe0, 0xcf, 0xbc, 0x5c, 0xfd, 0xcd, 0x7e, 0x07, 0x20, 0x0c, 0x88, 0x59, 0xf5, 0xd1, + 0xc4, 0xbd, 0xb3, 0xb2, 0xec, 0x9c, 0x2c, 0xbb, 0x1e, 0xfa, 0x35, 0x89, 0x51, 0x69, 0x65, 0x29, 0x9d, 0x2c, 0x25, + 0x64, 0x01, 0x9f, 0x18, 0x4d, 0x6d, 0x04, 0x10, 0xb6, 0xa3, 0x54, 0xbe, 0x50, 0x79, 0x11, 0x85, 0x73, 0x82, 0xe7, + 0x89, 0x18, 0xdd, 0x59, 0xc9, 0x80, 0xe1, 0x10, 0x82, 0x39, 0x68, 0x8b, 0xbd, 0xa1, 0x9b, 0x88, 0xbf, 0x5e, 0x16, + 0xe5, 0xab, 0x98, 0x7c, 0x0a, 0x76, 0x27, 0x1f, 0x97, 0xf0, 0xb8, 0x3c, 0xf9, 0x38, 0x44, 0x8f, 0x84, 0x93, 0x8f, + 0xc1, 0xf7, 0x48, 0xce, 0xeb, 0xae, 0xc7, 0x09, 0x72, 0x0b, 0xe9, 0xfe, 0x76, 0x4c, 0x02, 0x34, 0xaf, 0x61, 0x39, + 0x6a, 0x2a, 0xae, 0x99, 0x19, 0xe3, 0x79, 0xa3, 0xf7, 0xc7, 0x8e, 0xb7, 0x4c, 0xa1, 0x98, 0xc5, 0xbc, 0x86, 0xdf, + 0xb3, 0x2a, 0x50, 0x77, 0xbd, 0x4d, 0x72, 0xcb, 0xac, 0x9e, 0xa3, 0xdd, 0xf7, 0x5d, 0x9d, 0x08, 0x6a, 0x7f, 0x87, + 0x3d, 0xcf, 0xac, 0x77, 0x55, 0x0c, 0x5c, 0xaa, 0x64, 0x87, 0x4c, 0x55, 0xd3, 0x03, 0x95, 0xd2, 0xe0, 0xe9, 0xa5, + 0x75, 0xf9, 0x52, 0x69, 0x23, 0xcf, 0x34, 0xbf, 0x01, 0xbc, 0x98, 0xba, 0x2c, 0x76, 0xdf, 0xdc, 0x57, 0x70, 0x1b, + 0xef, 0xf7, 0xd7, 0x95, 0x67, 0x7e, 0xe2, 0x02, 0xb0, 0x37, 0x15, 0x5a, 0x27, 0x50, 0x6a, 0x58, 0x87, 0xd7, 0x89, + 0x88, 0xfe, 0x6c, 0x97, 0xeb, 0xcc, 0x75, 0xc0, 0x88, 0x22, 0x7e, 0x1b, 0x8f, 0xfe, 0x00, 0xc5, 0xb5, 0xb1, 0x07, + 0x84, 0x75, 0x48, 0xe8, 0x33, 0x02, 0x90, 0x7a, 0xf4, 0x51, 0xf2, 0x27, 0x68, 0x56, 0x34, 0x77, 0x4c, 0x7e, 0xae, + 0xaf, 0x94, 0xfe, 0x7e, 0x5d, 0x79, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0x54, 0x02, 0xe1, 0x15, 0x95, 0xac, + 0xc2, 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x9f, 0xb6, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0xc2, 0xef, + 0xf7, 0x2b, 0x80, 0x79, 0x91, 0xcd, 0xec, 0x3e, 0x0e, 0xa8, 0x52, 0xa2, 0x69, 0x9c, 0xcd, 0xf3, 0x7b, 0x7a, 0x53, + 0x76, 0xd0, 0xa9, 0x53, 0x05, 0x2e, 0xb8, 0x2a, 0x19, 0xaf, 0xac, 0x27, 0xf2, 0xf9, 0xcd, 0xcd, 0x26, 0xcd, 0xe2, + 0x77, 0xe5, 0x2f, 0x38, 0xb6, 0xba, 0x0e, 0x0f, 0x4c, 0x9d, 0xae, 0x9d, 0x47, 0x5a, 0x7b, 0x21, 0x20, 0xa2, 0x5d, + 0x43, 0xad, 0x17, 0x16, 0x7a, 0xa4, 0x27, 0xc2, 0x39, 0x49, 0xd4, 0xb4, 0x03, 0x2d, 0x8d, 0xd0, 0xd7, 0xd7, 0x9c, + 0xfe, 0xc2, 0x60, 0xed, 0xf3, 0x31, 0x03, 0xb2, 0x12, 0xfd, 0x58, 0x3d, 0x34, 0x36, 0x73, 0xe8, 0x59, 0xab, 0xf2, + 0xcc, 0xab, 0x0e, 0x07, 0xc4, 0x87, 0xd1, 0x5f, 0xf2, 0xfb, 0xfd, 0x17, 0x34, 0xff, 0x98, 0x50, 0xe3, 0x67, 0x9b, + 0x01, 0xba, 0xf6, 0x5d, 0x79, 0x20, 0xea, 0xb9, 0x56, 0x09, 0x42, 0xbc, 0x41, 0x4c, 0x34, 0x23, 0xe6, 0xe0, 0xb4, + 0x43, 0xcd, 0x3f, 0x49, 0x0d, 0x08, 0x51, 0xe2, 0x75, 0x4c, 0x59, 0x90, 0xd3, 0x26, 0x8e, 0xf4, 0xa3, 0x70, 0x22, + 0x3f, 0x88, 0xaa, 0xc8, 0xee, 0xe0, 0x82, 0xc1, 0xd4, 0x7b, 0xda, 0x2f, 0xd1, 0x6f, 0x09, 0x47, 0xce, 0xd1, 0xaa, + 0x10, 0x44, 0x4e, 0x08, 0x6b, 0x0d, 0x61, 0x82, 0xd8, 0x20, 0x5e, 0xf6, 0x5d, 0x92, 0xe1, 0x48, 0xc1, 0x65, 0x1d, + 0x3b, 0xc6, 0x5c, 0x1d, 0x55, 0xaf, 0x01, 0x8c, 0x57, 0x8e, 0xa0, 0xd9, 0x28, 0xb2, 0x4b, 0x88, 0x2a, 0x72, 0x3c, + 0x01, 0xb5, 0x83, 0xd2, 0xd8, 0x4c, 0xcf, 0xc7, 0x41, 0x3e, 0x5a, 0x54, 0xa8, 0x73, 0x62, 0x19, 0xaf, 0x01, 0x58, + 0x3b, 0x57, 0xfd, 0x3c, 0xab, 0xc1, 0x93, 0x86, 0xf8, 0x7c, 0x8c, 0xb6, 0x57, 0x36, 0x07, 0xd5, 0x76, 0x3a, 0x2b, + 0xaf, 0x98, 0x2e, 0x07, 0xc6, 0x7d, 0xc3, 0x2b, 0x8a, 0x33, 0xfc, 0xe0, 0xc1, 0x16, 0xe7, 0x4f, 0x37, 0xd4, 0x7e, + 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0xbb, 0x8e, 0x6c, 0xef, 0xb4, 0xc8, 0x68, 0xf2, + 0xd9, 0xcf, 0xdf, 0x97, 0xe9, 0x2a, 0x85, 0xfb, 0x92, 0x93, 0x45, 0x33, 0x0f, 0x81, 0xbd, 0x21, 0x86, 0xeb, 0xa3, + 0xc2, 0x23, 0xca, 0xfa, 0x7d, 0xf8, 0x7d, 0x95, 0x81, 0x29, 0x06, 0xae, 0x2b, 0x04, 0xe3, 0x21, 0x10, 0xc4, 0xc3, + 0x34, 0x3a, 0x19, 0xd4, 0xa0, 0x0d, 0xdf, 0x00, 0x64, 0x06, 0x78, 0x64, 0x2e, 0x3d, 0x02, 0xee, 0x02, 0xd7, 0x9e, + 0x8c, 0xc7, 0xfe, 0xc4, 0x34, 0x34, 0x6a, 0x4a, 0x33, 0x3d, 0x37, 0x7e, 0xd3, 0x51, 0x2d, 0xd7, 0xce, 0x7f, 0x7c, + 0xc9, 0x6f, 0xd0, 0x0b, 0x5a, 0x5e, 0xee, 0x23, 0x75, 0xb9, 0xcf, 0x28, 0x2e, 0x13, 0xc9, 0x61, 0x41, 0x2c, 0x4b, + 0x38, 0xf0, 0x18, 0x95, 0x2c, 0xb6, 0xf4, 0x58, 0x15, 0x2d, 0x5f, 0x94, 0x1b, 0xa4, 0x43, 0x27, 0x04, 0x4b, 0x54, + 0x10, 0x2c, 0x81, 0x71, 0x11, 0x6b, 0xbe, 0x19, 0xe4, 0x2c, 0x9e, 0x6d, 0xe6, 0x1c, 0x09, 0xeb, 0x92, 0xc3, 0xa1, + 0x90, 0x60, 0x33, 0xd9, 0x6c, 0x3d, 0x67, 0x6b, 0x9f, 0x81, 0x12, 0xa0, 0x94, 0x69, 0x82, 0xd2, 0xb4, 0x62, 0x2b, + 0x6e, 0x5a, 0x83, 0xd5, 0x6a, 0xca, 0x56, 0x35, 0x65, 0xe7, 0x34, 0xe5, 0xa8, 0x82, 0x92, 0x13, 0x4a, 0x51, 0x86, + 0x01, 0x8c, 0xd8, 0x24, 0xba, 0xca, 0xd0, 0xc7, 0x3b, 0xe1, 0x11, 0x54, 0x11, 0x91, 0x4f, 0x18, 0x42, 0x60, 0x22, + 0x8a, 0x0b, 0x55, 0x28, 0x06, 0xc8, 0x88, 0x04, 0x82, 0x89, 0x4a, 0x9d, 0x02, 0xf3, 0xd1, 0x54, 0x31, 0x6c, 0xda, + 0x13, 0xe5, 0x7b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0x1f, 0x62, 0x17, 0x84, 0xc8, 0xdd, 0xb8, 0x53, 0x3f, 0x23, 0xde, + 0xdb, 0x1d, 0x61, 0xfc, 0x64, 0xc7, 0x2d, 0xc2, 0x15, 0xc1, 0x96, 0x6a, 0x0e, 0xb1, 0x98, 0x57, 0x93, 0x04, 0xb5, + 0x2c, 0x89, 0xbf, 0xe1, 0xc9, 0x20, 0x67, 0x4b, 0xf0, 0xa0, 0x9d, 0xb3, 0x0c, 0xf0, 0x57, 0xac, 0x16, 0xfd, 0x5e, + 0x7b, 0x4b, 0x90, 0x9f, 0x36, 0x76, 0xa3, 0x30, 0x31, 0x82, 0x44, 0xdd, 0xae, 0x0c, 0xe4, 0x87, 0xf7, 0x38, 0x1d, + 0x8f, 0x3d, 0x65, 0xcc, 0xad, 0x4c, 0x2f, 0xd3, 0xb9, 0x92, 0x6f, 0xe4, 0x5e, 0xfa, 0xd0, 0x4b, 0xb0, 0x73, 0xc0, + 0x1b, 0x48, 0x1b, 0xf8, 0x11, 0xb6, 0x0b, 0xaf, 0x0d, 0x12, 0x66, 0x04, 0xd8, 0xe2, 0xf8, 0x18, 0x29, 0x81, 0x21, + 0x1c, 0x67, 0x29, 0x00, 0xd3, 0xe8, 0xcb, 0x6c, 0x65, 0x5f, 0x66, 0xb5, 0x66, 0x4b, 0xe5, 0x74, 0xef, 0xdc, 0xba, + 0x9d, 0xcf, 0x24, 0x00, 0x98, 0xd4, 0x39, 0x10, 0x67, 0x26, 0xd8, 0xa5, 0x49, 0x64, 0xf9, 0x10, 0xe6, 0xb7, 0xe2, + 0x65, 0x59, 0xac, 0x54, 0x57, 0xb4, 0x7d, 0x66, 0xf2, 0x19, 0xe9, 0x24, 0x54, 0x40, 0x41, 0x21, 0xd7, 0xfa, 0xf4, + 0x6d, 0xf8, 0x36, 0x28, 0x34, 0x30, 0x5b, 0x85, 0x7b, 0x9a, 0xac, 0x91, 0x7a, 0xa3, 0xea, 0xf7, 0xc9, 0x35, 0x90, + 0xea, 0xcc, 0xa1, 0x65, 0xcf, 0x2a, 0x0c, 0x10, 0x3b, 0xea, 0x33, 0x12, 0xea, 0x40, 0xea, 0x01, 0x43, 0x88, 0xb6, + 0xe9, 0xe3, 0x4f, 0x86, 0x44, 0x17, 0x60, 0x0b, 0xd1, 0x06, 0x7e, 0xfc, 0x09, 0xf6, 0x59, 0x10, 0x1e, 0xd3, 0xfc, + 0x0d, 0x24, 0x1d, 0x1b, 0x38, 0xad, 0x3e, 0x05, 0x1f, 0x24, 0x39, 0x98, 0xa8, 0x83, 0x97, 0xfb, 0x4b, 0xbf, 0x0f, + 0x5b, 0x76, 0x2e, 0xa5, 0x3a, 0x56, 0xea, 0x6d, 0x5b, 0xfb, 0x41, 0xb4, 0x05, 0x47, 0x16, 0xf1, 0xf7, 0x19, 0x22, + 0x82, 0x99, 0x41, 0x84, 0x5d, 0x0b, 0x75, 0xb7, 0xa7, 0xd4, 0xb2, 0xa8, 0xb7, 0x3d, 0xa5, 0xd4, 0x6d, 0x18, 0xbe, + 0x9b, 0x60, 0xa6, 0xb8, 0xe1, 0x6f, 0x32, 0x2f, 0xd4, 0x1b, 0x8f, 0x71, 0x8c, 0x5f, 0x7b, 0xfe, 0x7e, 0xc9, 0xab, + 0xd9, 0x46, 0x99, 0x30, 0x6f, 0xf9, 0x72, 0x16, 0xca, 0xae, 0x96, 0xc6, 0x9d, 0xcf, 0xde, 0x52, 0xcd, 0x07, 0xff, + 0x70, 0x48, 0x20, 0xde, 0x28, 0xbe, 0xba, 0x6d, 0xe4, 0xd6, 0x35, 0xd9, 0x5c, 0x95, 0x80, 0xfa, 0x7d, 0xbe, 0xc6, + 0xfd, 0x16, 0xeb, 0xdf, 0x3d, 0x0d, 0x32, 0x56, 0x33, 0x5c, 0x31, 0x85, 0x4f, 0x01, 0x60, 0x70, 0x38, 0x15, 0xa4, + 0x05, 0xde, 0xf0, 0x72, 0x78, 0x39, 0xd9, 0x90, 0x49, 0x77, 0xe3, 0x23, 0x77, 0x16, 0xa8, 0x7a, 0xbf, 0xa3, 0x38, + 0x69, 0x90, 0x68, 0xec, 0x35, 0xf8, 0x2c, 0xcb, 0x28, 0x17, 0x4d, 0xdc, 0x87, 0xe4, 0x2b, 0x3d, 0x80, 0xb9, 0x0a, + 0x25, 0x40, 0xf4, 0x1b, 0xcb, 0x62, 0x23, 0xda, 0x16, 0x1b, 0x58, 0x4a, 0xd5, 0x5c, 0xaf, 0xa6, 0xcf, 0x5e, 0x89, + 0xe6, 0x7d, 0x34, 0xe3, 0x94, 0x46, 0x03, 0x8e, 0xd3, 0x28, 0xdc, 0xbe, 0xbb, 0x13, 0xe5, 0x32, 0x03, 0x4b, 0xb6, + 0x0a, 0xa7, 0xb8, 0x6c, 0xd4, 0x19, 0xf1, 0x2c, 0x8f, 0x15, 0x40, 0xc7, 0x43, 0x02, 0xa0, 0xba, 0x20, 0xa0, 0x22, + 0x5a, 0x4a, 0x6f, 0x85, 0x16, 0x0b, 0xf5, 0x86, 0xa3, 0x14, 0xfe, 0x48, 0x7f, 0x1e, 0xe4, 0x53, 0x00, 0x62, 0xd7, + 0xc7, 0xd1, 0xcb, 0xa2, 0xa4, 0x4f, 0x15, 0xb3, 0x5c, 0x0e, 0x26, 0xb0, 0xab, 0x13, 0x19, 0x6a, 0x05, 0x79, 0xab, + 0xae, 0xbc, 0x95, 0xc9, 0xdb, 0x18, 0xa7, 0xe4, 0x07, 0x6e, 0x3a, 0xd6, 0x88, 0x81, 0x57, 0x9e, 0xd6, 0x69, 0x82, + 0x34, 0xb9, 0x00, 0x86, 0x21, 0x7e, 0x9f, 0x79, 0xcf, 0x3c, 0x47, 0xaa, 0x82, 0x64, 0x76, 0x97, 0x79, 0xea, 0x22, + 0xaa, 0xaf, 0x9c, 0x5a, 0x3a, 0x73, 0xfa, 0x11, 0xc0, 0x7b, 0x4c, 0x4d, 0x1a, 0xf2, 0x11, 0x6e, 0x4b, 0xf1, 0xf5, + 0x56, 0x5d, 0xe3, 0xa5, 0xd1, 0xb9, 0x7b, 0xf9, 0xd2, 0x9d, 0x06, 0xfd, 0x14, 0x04, 0xe5, 0x7c, 0x56, 0x0a, 0xd8, + 0x53, 0x66, 0x73, 0xbd, 0x5a, 0xb5, 0x42, 0xeb, 0x70, 0x18, 0x6b, 0x47, 0x21, 0xad, 0xce, 0x02, 0xb6, 0x1a, 0xe9, + 0x94, 0x00, 0x21, 0x38, 0x4e, 0xc3, 0x4e, 0x30, 0xee, 0xd2, 0x69, 0x44, 0xd6, 0x2b, 0x25, 0xe9, 0xc2, 0x0c, 0x92, + 0x7f, 0x92, 0xd7, 0x33, 0xa0, 0x25, 0x80, 0x43, 0x11, 0x4b, 0x78, 0x38, 0x49, 0xae, 0x00, 0x3a, 0x1d, 0x0e, 0x2a, + 0x0d, 0xcd, 0x59, 0xcd, 0x92, 0xf9, 0x24, 0x96, 0xaa, 0xca, 0xc3, 0xc1, 0x53, 0x6e, 0x06, 0xfd, 0x7e, 0x36, 0x2d, + 0x95, 0x0b, 0x40, 0x10, 0xeb, 0xc2, 0x00, 0xf1, 0x48, 0x0b, 0x4f, 0x16, 0x7d, 0x4a, 0xe2, 0x97, 0xb3, 0x64, 0x6e, + 0xb2, 0xe1, 0x1d, 0x18, 0xc1, 0x66, 0x5c, 0x97, 0x94, 0x69, 0x8f, 0xca, 0xef, 0x19, 0x3d, 0xb5, 0x7d, 0xad, 0xd5, + 0x16, 0xb1, 0xae, 0x83, 0xab, 0x12, 0xf5, 0x14, 0x1f, 0x94, 0x24, 0x78, 0xbf, 0x70, 0x6e, 0x46, 0xca, 0xd7, 0x22, + 0xf7, 0x83, 0x76, 0xa6, 0x56, 0x0e, 0x1c, 0x81, 0x1c, 0xab, 0xa8, 0xe4, 0xf5, 0xae, 0x43, 0xf0, 0xe8, 0xae, 0x54, + 0xa0, 0x1c, 0xfc, 0x14, 0xc4, 0xe8, 0xfa, 0xaa, 0xb3, 0x86, 0x9a, 0x69, 0x54, 0x79, 0x04, 0x9d, 0x3a, 0x80, 0x27, + 0x05, 0x2f, 0xb5, 0xfa, 0xf1, 0x70, 0xf0, 0xcc, 0x0f, 0xfe, 0x2e, 0xd3, 0xb7, 0x10, 0x13, 0xe5, 0x54, 0x23, 0x24, + 0xae, 0x94, 0x24, 0xe2, 0xe3, 0x45, 0xcb, 0x8a, 0x51, 0x19, 0xde, 0xf3, 0x4a, 0x95, 0xaf, 0x4e, 0x55, 0x5e, 0x8c, + 0xb4, 0x2d, 0x81, 0xd7, 0xe4, 0x1f, 0x22, 0xd7, 0xbc, 0xf5, 0x75, 0x57, 0x19, 0xfa, 0x48, 0x56, 0xa0, 0x23, 0xd8, + 0xca, 0x52, 0x72, 0xc0, 0x27, 0xd5, 0x5d, 0xb5, 0x6a, 0x7d, 0x4e, 0xd9, 0x46, 0xb8, 0xc9, 0xaf, 0x63, 0x07, 0x47, + 0xca, 0x6f, 0xf0, 0x5c, 0x00, 0x7b, 0x0d, 0xd8, 0x9b, 0x73, 0x56, 0x34, 0x0f, 0x0e, 0x69, 0x5b, 0xa0, 0x91, 0x99, + 0xdb, 0xb9, 0xba, 0x6f, 0xcb, 0xa3, 0x34, 0x86, 0xc8, 0xb4, 0x07, 0xa6, 0x83, 0xcd, 0x28, 0xff, 0x3d, 0xe5, 0xb7, + 0x0a, 0xc7, 0xc0, 0xb7, 0x53, 0xef, 0x00, 0xaa, 0x9e, 0x36, 0xc8, 0x58, 0x33, 0x0c, 0xad, 0xec, 0x72, 0x29, 0xb4, + 0x04, 0x2d, 0x75, 0x13, 0x04, 0xe7, 0x47, 0x44, 0x39, 0x02, 0xd0, 0x45, 0x0a, 0x98, 0xe0, 0xa7, 0xb4, 0xdd, 0xfd, + 0xfe, 0x3a, 0xf5, 0xc8, 0xbd, 0x2b, 0xd4, 0x28, 0xa1, 0x04, 0x63, 0x3f, 0xd1, 0x98, 0x41, 0x47, 0x57, 0xe4, 0x84, + 0x67, 0xad, 0x0e, 0xeb, 0xba, 0x29, 0x83, 0xb2, 0x38, 0xe6, 0xd5, 0x74, 0xf6, 0xc7, 0xa3, 0x7d, 0xdd, 0x20, 0x0b, + 0xf9, 0x1f, 0xac, 0x87, 0x64, 0xd0, 0x3d, 0x08, 0x85, 0xe8, 0xcd, 0x83, 0x19, 0xfe, 0xc7, 0x36, 0x3c, 0xfb, 0x8e, + 0x1b, 0x75, 0x82, 0x98, 0x23, 0x8e, 0x97, 0x9e, 0xa2, 0xad, 0x87, 0x5b, 0x20, 0x5b, 0xe3, 0xe5, 0xad, 0xbd, 0x06, + 0x72, 0x8a, 0xe3, 0xbf, 0xe5, 0x99, 0x5a, 0xd9, 0xe0, 0xa7, 0xa7, 0x6c, 0x07, 0x1e, 0x5e, 0x84, 0x80, 0x62, 0x58, + 0x36, 0xfe, 0xd6, 0x72, 0x9c, 0xd1, 0x7f, 0xf3, 0x88, 0x61, 0xb0, 0x88, 0xfc, 0xf8, 0xb2, 0x14, 0xe2, 0xab, 0xf0, + 0x3e, 0x55, 0xde, 0x2d, 0x39, 0x65, 0xde, 0xea, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x4b, 0x3e, 0xb6, 0x86, 0xed, 0x0f, + 0xed, 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0xd5, 0xec, 0xf4, 0xfa, 0xbd, 0x73, + 0xbc, 0x60, 0x6b, 0x34, 0xc0, 0xe3, 0xa1, 0x8b, 0x79, 0xa2, 0x86, 0x4e, 0xd7, 0xb5, 0x73, 0xf0, 0xc0, 0x20, 0xcb, + 0x93, 0xef, 0x18, 0x96, 0xd8, 0x9f, 0x44, 0x3c, 0x69, 0xab, 0x36, 0x36, 0x47, 0xaa, 0x8d, 0x9a, 0x81, 0x1f, 0xbc, + 0x82, 0x02, 0xa3, 0x0b, 0xd2, 0x02, 0x8c, 0xc3, 0x11, 0x80, 0xac, 0x18, 0xc7, 0x23, 0x83, 0x09, 0x0c, 0xe9, 0x86, + 0xa2, 0x00, 0x3c, 0x3c, 0x8e, 0x07, 0x21, 0x03, 0x48, 0x17, 0x3c, 0x34, 0x6c, 0x93, 0x90, 0xf2, 0xf3, 0x3c, 0xaf, + 0xd5, 0x10, 0xfa, 0xce, 0x42, 0x75, 0xec, 0x47, 0xda, 0x2b, 0xd6, 0xb5, 0x2a, 0x1d, 0xd9, 0xea, 0x00, 0x7d, 0x43, + 0x06, 0xbe, 0x75, 0x6c, 0x01, 0x10, 0x2d, 0xf1, 0x25, 0xf5, 0x6a, 0x5f, 0xc6, 0xac, 0x50, 0xaf, 0x2f, 0x4c, 0xbb, + 0x5e, 0x48, 0x8b, 0x02, 0x2a, 0x6e, 0x5b, 0xb5, 0x3d, 0x92, 0xf3, 0x1f, 0xde, 0x75, 0xb4, 0xe3, 0xb3, 0x53, 0x63, + 0x4b, 0x28, 0x73, 0x8b, 0x27, 0xb2, 0x3a, 0xda, 0x52, 0x9d, 0xea, 0x03, 0x2e, 0x35, 0xa9, 0xce, 0x0c, 0x0c, 0xaf, + 0x11, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xde, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xd8, 0xda, + 0x45, 0x73, 0xfd, 0xfa, 0x92, 0x7a, 0x55, 0x9b, 0xaa, 0x1e, 0xbc, 0xf1, 0x02, 0x67, 0xef, 0xb4, 0x16, 0x10, 0x40, + 0x61, 0x6b, 0x59, 0x0e, 0xce, 0xdd, 0xae, 0x6a, 0xa9, 0x28, 0xa3, 0x7e, 0xff, 0xfc, 0x4b, 0x8a, 0x8a, 0xd8, 0x53, + 0xc5, 0x29, 0xeb, 0xb7, 0x5b, 0xe6, 0xa2, 0xb2, 0xe4, 0x0d, 0xaa, 0x68, 0xad, 0x8e, 0x9a, 0xca, 0x75, 0x73, 0xd5, + 0x92, 0x09, 0x62, 0x74, 0x9f, 0xae, 0x75, 0xee, 0xd4, 0x7b, 0xaf, 0xe2, 0x88, 0x81, 0xe0, 0xa6, 0x7b, 0x7c, 0x70, + 0x10, 0x1a, 0x15, 0xe5, 0x82, 0x1b, 0xa5, 0x55, 0x25, 0xa5, 0x90, 0xb7, 0x2a, 0x9a, 0x33, 0x7d, 0x04, 0x40, 0x04, + 0x58, 0x25, 0xea, 0xff, 0xf0, 0xa5, 0x31, 0x1e, 0x3c, 0xf0, 0x35, 0xb9, 0x8e, 0xad, 0xf7, 0x4f, 0x6b, 0xa4, 0xd5, + 0xc6, 0x31, 0xa9, 0x55, 0x2f, 0x5b, 0xc5, 0xcb, 0xee, 0x75, 0x2a, 0x06, 0xcf, 0xff, 0xe7, 0x3e, 0x40, 0x8d, 0x68, + 0x29, 0x83, 0x5b, 0x57, 0x03, 0x34, 0x3e, 0x1c, 0x0b, 0xdf, 0xf8, 0x21, 0xe3, 0x7c, 0x30, 0x43, 0x47, 0xb5, 0x39, + 0x38, 0x20, 0x38, 0xaa, 0x7b, 0x34, 0x26, 0xcc, 0xc2, 0xb9, 0x07, 0x81, 0xea, 0x13, 0xf7, 0x19, 0xd7, 0x5e, 0xd0, + 0x26, 0xf0, 0xc9, 0xba, 0xae, 0x29, 0x02, 0x5c, 0xc4, 0xc6, 0x44, 0x0c, 0x71, 0xd9, 0x24, 0x52, 0xdf, 0x8c, 0x41, + 0x01, 0x50, 0x3c, 0xad, 0x48, 0x2e, 0x5d, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, + 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, + 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, + 0x19, 0x7f, 0x4a, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, 0x9e, 0xc3, 0xa7, 0xbc, 0x9c, 0x84, + 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, + 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, + 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, + 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, + 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, + 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, + 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, + 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0x7c, 0xbf, 0xc1, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0xf2, + 0x16, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, + 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, + 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x24, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, + 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, 0x99, 0xe4, 0xed, 0x12, 0x8e, 0xba, + 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, + 0xf7, 0xbe, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, + 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, + 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, + 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0xa7, + 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, 0xf3, 0x9a, 0x5d, 0x3f, 0x16, 0x6c, + 0xc7, 0x76, 0x8f, 0x11, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, 0x2f, 0xdc, 0xf2, 0x25, 0x80, 0x07, + 0xb2, 0x18, 0x50, 0x7c, 0x96, 0xde, 0x2f, 0x2c, 0x01, 0x35, 0xf9, 0x0d, 0x5f, 0x7b, 0x6f, 0x29, 0x75, 0x01, 0x7f, + 0x0e, 0x28, 0x7d, 0x92, 0x73, 0xef, 0x76, 0x78, 0xe3, 0x5f, 0x3c, 0x01, 0xe7, 0x89, 0xd5, 0x70, 0x01, 0x7f, 0x15, + 0x7c, 0xe8, 0xdd, 0x0e, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x35, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x05, + 0x39, 0xc3, 0x3f, 0x7e, 0xd7, 0x18, 0xac, 0xbf, 0x05, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0xce, 0x04, + 0xd8, 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xb3, 0x16, 0xf4, 0xe7, 0x03, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, + 0xf9, 0x01, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x53, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x57, 0xae, 0xc1, + 0x8e, 0xd7, 0xc9, 0x91, 0xa5, 0xf0, 0xac, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, + 0xe5, 0xb9, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0e, 0x72, 0x19, 0x1a, 0xf3, 0x0e, 0xd9, 0x30, 0x94, 0x0f, 0x2d, + 0x32, 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xbd, 0xf6, 0x72, 0xe0, + 0x3d, 0x88, 0xfc, 0x46, 0xba, 0x94, 0x4b, 0x6c, 0x74, 0xe2, 0x58, 0x16, 0xda, 0x79, 0x5c, 0x7f, 0x1d, 0x83, 0xfa, + 0xbd, 0xd2, 0x6f, 0x50, 0xce, 0xfe, 0x20, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xbf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, + 0xfe, 0x3f, 0x63, 0x0a, 0xa5, 0xbf, 0x4e, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, + 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x57, 0x26, 0xf8, 0xf0, 0x57, 0xed, 0x5c, + 0x9b, 0xf3, 0xf1, 0x24, 0xbf, 0xb2, 0xf6, 0x6e, 0xc7, 0x8b, 0xc4, 0x28, 0xc6, 0x72, 0x5f, 0x75, 0xb3, 0x72, 0xa2, + 0x92, 0x03, 0x23, 0x5d, 0x93, 0xbd, 0x5c, 0xc9, 0xba, 0x9d, 0x6e, 0x25, 0x10, 0x51, 0x05, 0xde, 0x63, 0x5c, 0xc5, + 0x3e, 0x82, 0xe9, 0xba, 0xe3, 0x32, 0xda, 0xf1, 0x9e, 0xf1, 0xea, 0x44, 0x59, 0xc1, 0xed, 0x46, 0xb4, 0x27, 0x74, + 0xf4, 0xd3, 0xa4, 0xb6, 0x2c, 0x1c, 0x80, 0xdc, 0x25, 0x8c, 0x65, 0x43, 0xb0, 0x62, 0x50, 0xfa, 0x7a, 0x4d, 0xc9, + 0xb2, 0x00, 0x8b, 0xce, 0x2e, 0x23, 0x10, 0xc3, 0xba, 0x69, 0x4e, 0xe8, 0x78, 0xe9, 0xe2, 0xbc, 0xd7, 0x2a, 0x52, + 0xf0, 0x8c, 0x16, 0x1d, 0x73, 0xd3, 0x91, 0x6e, 0x8c, 0xf6, 0xf6, 0xb9, 0x41, 0x48, 0xf1, 0xfc, 0x81, 0xad, 0xd6, + 0xc5, 0x45, 0xe2, 0x15, 0x32, 0xd1, 0x82, 0x58, 0x8a, 0xc0, 0x8c, 0x17, 0x9a, 0x46, 0x98, 0xa0, 0x4c, 0x09, 0x16, + 0xad, 0xd1, 0xa1, 0xfd, 0x61, 0x09, 0xbb, 0xc7, 0x18, 0x01, 0x02, 0x55, 0xa6, 0x5f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, + 0xc5, 0x06, 0x68, 0xab, 0x18, 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x43, 0x9a, 0xdf, 0xfe, 0x0b, 0x8b, 0xb1, 0x3d, 0x81, + 0xd8, 0xde, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xa8, 0x1d, + 0x6b, 0xa9, 0x77, 0xac, 0xb5, 0xde, 0xb1, 0x6e, 0x1b, 0xfe, 0x2c, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, + 0x83, 0xa0, 0x19, 0x1b, 0x76, 0x03, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, + 0x60, 0x19, 0x51, 0x93, 0xef, 0x90, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0x77, + 0x8f, 0x23, 0xc8, 0xbd, 0xe3, 0xde, 0xdd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, + 0x4f, 0x10, 0xad, 0xec, 0x29, 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x1f, 0xdf, 0xb9, 0xdb, 0xda, 0xed, 0xe3, 0x3b, 0x56, + 0x8d, 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xe3, + 0x8e, 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0x8f, 0x33, 0x8d, + 0xe7, 0x70, 0x24, 0x9f, 0x8e, 0x35, 0x36, 0x08, 0xea, 0xfa, 0x9c, 0x41, 0xed, 0xd8, 0x7d, 0x4d, 0xd8, 0x65, 0xc7, + 0xbc, 0xd6, 0x35, 0x6f, 0xaf, 0x3c, 0x15, 0x1b, 0x02, 0x3a, 0x7c, 0xad, 0x6e, 0x90, 0x7f, 0x09, 0x9c, 0x22, 0x00, + 0xe4, 0x70, 0xbc, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0x77, 0xa8, 0xb5, 0xa8, 0x2c, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, + 0x8a, 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2e, 0x2e, 0x7e, 0x3d, 0x2d, + 0x94, 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x8e, + 0x94, 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf1, 0x84, 0xc5, 0x90, 0x08, 0xb0, 0xdd, + 0xa1, 0x62, 0x5b, 0xb8, 0x78, 0xc2, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, + 0x8e, 0x35, 0xd4, 0x6c, 0x6d, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x6e, 0xdb, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, + 0xeb, 0x3d, 0xaa, 0x0b, 0x60, 0xeb, 0xbf, 0x39, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, + 0x7a, 0x95, 0x2c, 0xfc, 0x9b, 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, + 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, + 0x97, 0x15, 0xdb, 0x05, 0xb1, 0x9d, 0xf0, 0x3b, 0x01, 0x53, 0x3e, 0x83, 0x20, 0xae, 0xe0, 0x06, 0xe2, 0xf0, 0xe4, + 0x9f, 0x83, 0xbb, 0xd6, 0x66, 0x7d, 0xc7, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, + 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, 0xb7, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, + 0x40, 0xfc, 0x74, 0x33, 0xe0, 0x77, 0x1d, 0x6b, 0xcb, 0xbb, 0x66, 0x0b, 0xb6, 0x83, 0x4b, 0x50, 0xd3, 0x5e, 0xf6, + 0x27, 0x95, 0x0b, 0xda, 0xb1, 0x4b, 0xe2, 0xe1, 0x8c, 0x59, 0xa5, 0xcc, 0xac, 0x93, 0xea, 0x4a, 0x74, 0xc6, 0x74, + 0xd6, 0x7a, 0x3e, 0x57, 0xf3, 0x49, 0xa1, 0x41, 0xfd, 0xce, 0x89, 0x8f, 0xa8, 0xe8, 0x3c, 0x81, 0xad, 0x65, 0x05, + 0xb1, 0xda, 0xe7, 0x60, 0xad, 0xd5, 0x2e, 0xfd, 0x5e, 0x3e, 0xe0, 0x36, 0xe5, 0xb0, 0x0e, 0x0c, 0x6a, 0x4e, 0xac, + 0xa8, 0x87, 0x6c, 0xc7, 0xb8, 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xf5, 0xb1, 0xa7, + 0xbf, 0x53, 0xfb, 0x17, 0xc2, 0x0f, 0xc6, 0xff, 0xa9, 0xdd, 0xd7, 0x5a, 0x8c, 0xca, 0x56, 0x39, 0x42, 0xe3, 0x6e, + 0x25, 0x4d, 0x96, 0x9f, 0x84, 0x27, 0xac, 0x05, 0xcf, 0x72, 0xbd, 0x44, 0xb3, 0x02, 0x56, 0x58, 0xcb, 0x24, 0x5c, + 0x61, 0xac, 0x96, 0xb6, 0xfa, 0x16, 0x4d, 0x73, 0x7c, 0x38, 0xd7, 0x06, 0x65, 0xca, 0xd9, 0x19, 0xb1, 0x1a, 0x2e, + 0xc3, 0xd2, 0x84, 0x22, 0x64, 0xf7, 0x76, 0x70, 0x63, 0xa7, 0x2c, 0xa5, 0x0c, 0xe7, 0x18, 0x4c, 0x78, 0x24, 0x46, + 0x55, 0xbe, 0xbf, 0x2f, 0x29, 0x72, 0xda, 0x96, 0x83, 0x2a, 0x84, 0x7d, 0x24, 0x51, 0x02, 0xb7, 0x22, 0x2d, 0x14, + 0x29, 0x8b, 0xbf, 0x1d, 0xa0, 0x0b, 0xbc, 0x80, 0xba, 0x1a, 0x75, 0xfb, 0xc3, 0x11, 0x0f, 0x1f, 0x98, 0xfa, 0xc0, + 0x88, 0x25, 0x81, 0xda, 0x9e, 0x65, 0xe9, 0x2d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, + 0x1b, 0xe9, 0x0d, 0xad, 0xc1, 0x23, 0xb4, 0xa6, 0x3c, 0x77, 0x52, 0x6d, 0xd2, 0x79, 0x47, 0xc8, 0xb1, 0xfa, 0xd6, + 0x12, 0x46, 0xbb, 0xa2, 0x17, 0xf7, 0x8e, 0xde, 0xf3, 0x74, 0xd5, 0x73, 0x7f, 0xe2, 0x8a, 0x79, 0x72, 0x1b, 0x81, + 0xba, 0x15, 0x54, 0xb7, 0x77, 0x2a, 0xc1, 0x82, 0x25, 0xed, 0x3e, 0x7e, 0x3b, 0x6b, 0x07, 0xa2, 0x32, 0x56, 0xe9, + 0x5b, 0x92, 0xb0, 0x27, 0x06, 0x9d, 0x42, 0x55, 0x6e, 0x77, 0x47, 0x5b, 0xe0, 0x3a, 0x66, 0x29, 0x7a, 0x66, 0x8b, + 0xdc, 0x2d, 0xff, 0xee, 0xb9, 0x22, 0x67, 0xbf, 0x04, 0x04, 0xa7, 0xe6, 0x1b, 0xe2, 0xcb, 0x11, 0x1e, 0x55, 0xb7, + 0xc0, 0x71, 0xfa, 0x0e, 0xe0, 0x1f, 0x0e, 0x97, 0xa0, 0x09, 0x88, 0x05, 0xeb, 0xa5, 0x71, 0x8f, 0xf5, 0xe2, 0x62, + 0x73, 0x9b, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, + 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, + 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, + 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, + 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, + 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0x7f, 0x19, 0xff, 0xd0, 0x33, 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, + 0xaf, 0xbf, 0x42, 0x00, 0x1c, 0x9e, 0x4d, 0xbd, 0xcb, 0x31, 0x64, 0x95, 0x65, 0x04, 0x92, 0x9f, 0x18, 0x7c, 0xf9, + 0x02, 0xa0, 0xea, 0x33, 0x5d, 0xab, 0xc9, 0x51, 0x7b, 0xcc, 0xa1, 0x2b, 0x06, 0x80, 0x6d, 0x58, 0xa2, 0xaa, 0x16, + 0x36, 0x61, 0x71, 0xfb, 0x19, 0x46, 0x73, 0xd9, 0xf4, 0x82, 0x06, 0xea, 0x11, 0x82, 0x5f, 0x5a, 0x0f, 0xad, 0xb5, + 0x4c, 0x39, 0x74, 0x6d, 0x14, 0x55, 0x36, 0xd4, 0x25, 0xac, 0xd6, 0x22, 0xaa, 0x89, 0x22, 0xe5, 0x92, 0x51, 0x14, + 0x4b, 0x15, 0xec, 0x33, 0x71, 0x0b, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x16, 0x10, 0xd6, 0xc2, 0x5a, 0x48, + 0x67, 0x50, 0x7b, 0xa7, 0x1f, 0x29, 0x7f, 0x79, 0x21, 0xb7, 0x73, 0x0b, 0x45, 0xb8, 0x3d, 0x07, 0xe5, 0x4d, 0x5d, + 0x95, 0x8a, 0x68, 0xb4, 0x04, 0x4a, 0x99, 0x13, 0x44, 0x16, 0x20, 0x80, 0xe3, 0x06, 0x02, 0x9f, 0xd7, 0xf8, 0x04, + 0x1a, 0x85, 0x40, 0x7e, 0x60, 0x15, 0xae, 0x3d, 0xa4, 0xa5, 0xd6, 0x88, 0x28, 0x11, 0x3f, 0xba, 0x7a, 0x8e, 0xed, + 0xab, 0xa7, 0xb1, 0xb6, 0x94, 0x26, 0x88, 0x9f, 0x58, 0x6c, 0x21, 0x26, 0x88, 0xea, 0x10, 0x1d, 0xc1, 0x72, 0x42, + 0x88, 0xc2, 0x9f, 0x42, 0x3f, 0x35, 0xf0, 0x97, 0x6c, 0x59, 0xe4, 0x35, 0xc1, 0x62, 0x56, 0x0c, 0xd0, 0xaa, 0x08, + 0x3c, 0xd3, 0xd9, 0x52, 0x99, 0xd3, 0x3c, 0x3a, 0xb2, 0x83, 0xf3, 0xae, 0x83, 0xbd, 0xf4, 0x65, 0xec, 0x64, 0xd9, + 0x34, 0x6a, 0x63, 0x43, 0x24, 0xbc, 0x22, 0xbf, 0xce, 0x52, 0xe3, 0x1c, 0x99, 0xcb, 0xf5, 0x5d, 0x17, 0xb7, 0xb7, + 0xb4, 0x4d, 0x58, 0x85, 0x08, 0x75, 0xdb, 0x50, 0xb9, 0x14, 0x66, 0x63, 0xd3, 0x34, 0xc0, 0x17, 0x8a, 0x4a, 0xa5, + 0x2a, 0xb5, 0x95, 0x4a, 0x4e, 0x78, 0xd7, 0x37, 0xb5, 0x48, 0x5d, 0x11, 0x6c, 0x63, 0x86, 0x7a, 0x28, 0x37, 0x6a, + 0xec, 0xdb, 0x8e, 0x55, 0x7a, 0x87, 0x09, 0x72, 0x46, 0x5e, 0xe4, 0xe0, 0xa2, 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, + 0x83, 0x86, 0x4f, 0x0b, 0xcb, 0x3d, 0x94, 0x80, 0xd9, 0x51, 0xc3, 0xa3, 0x08, 0x81, 0x88, 0x4b, 0x65, 0x5f, 0x31, + 0xf1, 0x7b, 0x0a, 0x66, 0xc9, 0x84, 0xee, 0x45, 0x2c, 0x8b, 0xd0, 0xc6, 0x27, 0x49, 0x32, 0xf5, 0x34, 0x05, 0x37, + 0x72, 0x19, 0xe6, 0x68, 0x84, 0x96, 0x7c, 0xe4, 0x40, 0xfa, 0x5a, 0x4e, 0x25, 0xf8, 0x88, 0x3a, 0x05, 0x1c, 0xcf, + 0xcf, 0x0b, 0xeb, 0x27, 0xcb, 0x25, 0xe6, 0xb2, 0x36, 0xff, 0x65, 0x47, 0xc7, 0x60, 0x97, 0xa7, 0x89, 0xe3, 0xea, + 0x3f, 0xaa, 0x92, 0xe2, 0xfe, 0x75, 0x9a, 0x03, 0x8a, 0x60, 0x66, 0x4f, 0x31, 0x3e, 0xf6, 0x59, 0xa6, 0x80, 0xbf, + 0x5d, 0x6f, 0x2d, 0x99, 0xd8, 0x25, 0xed, 0xe6, 0xca, 0xf8, 0xa5, 0x36, 0xec, 0x38, 0x38, 0x37, 0x00, 0xc5, 0x59, + 0xa3, 0xc3, 0xf2, 0x5a, 0xb7, 0xad, 0x0a, 0x15, 0xa8, 0xf5, 0x7f, 0x76, 0x0b, 0x53, 0xde, 0xe6, 0xa5, 0xf2, 0x36, + 0x0f, 0x4d, 0x80, 0x40, 0x64, 0x86, 0x3c, 0x6b, 0x3a, 0x26, 0x89, 0x7b, 0x47, 0x4a, 0xda, 0x77, 0xa4, 0xf8, 0xc1, + 0x3b, 0x12, 0xf2, 0x2d, 0xa1, 0x23, 0xfb, 0x92, 0x93, 0x13, 0x28, 0x33, 0xd8, 0xcb, 0x6b, 0x26, 0xfb, 0x07, 0xb4, + 0x17, 0xce, 0x65, 0x79, 0xc5, 0xdf, 0x08, 0x6f, 0xed, 0x4f, 0xd7, 0xa7, 0x5d, 0x55, 0x6f, 0xbe, 0x31, 0x33, 0x0f, + 0x87, 0xe2, 0x70, 0xa8, 0x4c, 0xd0, 0xee, 0x82, 0x8b, 0x41, 0xce, 0xee, 0xdc, 0xf8, 0xf8, 0x6b, 0x8e, 0x22, 0xb6, + 0x52, 0x1e, 0x49, 0x17, 0x2a, 0x31, 0xbc, 0x34, 0xf0, 0x30, 0x3b, 0x3e, 0x9e, 0xec, 0xae, 0xee, 0x26, 0x83, 0xc1, + 0x4e, 0xf5, 0xed, 0x96, 0xd7, 0xb3, 0xdd, 0x9c, 0xdd, 0xf3, 0x9b, 0xe9, 0x36, 0xd8, 0x37, 0xb0, 0xed, 0xee, 0xae, + 0xc4, 0xe1, 0xb0, 0x7b, 0xca, 0x17, 0xfe, 0xfe, 0x1e, 0x01, 0x9d, 0xf9, 0xf9, 0xb8, 0x8d, 0xf1, 0xf3, 0xa6, 0xed, + 0xaa, 0xb5, 0x03, 0x78, 0xfa, 0x57, 0xde, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0xf7, 0xfc, 0x1e, 0xfc, 0xf3, 0x71, 0x93, + 0x44, 0xea, 0x13, 0xed, 0x32, 0xf9, 0x06, 0x1c, 0xc8, 0x77, 0x3e, 0xfb, 0xc4, 0xef, 0x67, 0xcb, 0x39, 0x2f, 0x0e, + 0x87, 0x47, 0xd3, 0x10, 0xc9, 0x9a, 0xc2, 0x8a, 0x58, 0x52, 0x3c, 0x3f, 0x08, 0x8f, 0xdf, 0x8b, 0xc8, 0x10, 0x69, + 0xb9, 0x77, 0x87, 0xec, 0x0d, 0x8b, 0xfc, 0x00, 0x3e, 0xc8, 0x76, 0xfe, 0x44, 0xd6, 0x94, 0xee, 0x17, 0xef, 0xfd, + 0xc3, 0x81, 0xfe, 0xfa, 0xe4, 0x1f, 0x0e, 0x8f, 0xd8, 0x3d, 0x82, 0xa3, 0xf3, 0x1d, 0xf4, 0x8f, 0xbe, 0x75, 0x40, + 0x55, 0x86, 0xd7, 0xb3, 0xcd, 0xdc, 0x7f, 0xba, 0x62, 0xb7, 0xc0, 0x85, 0xa2, 0xbc, 0xd0, 0xde, 0xb0, 0x7b, 0xf4, + 0x3a, 0x23, 0x27, 0xa2, 0xd9, 0x6e, 0xee, 0xb3, 0x18, 0x9f, 0xab, 0xfb, 0x62, 0xf2, 0xcd, 0xfb, 0xe2, 0x8e, 0x6d, + 0xbb, 0xef, 0x8b, 0xf2, 0x4d, 0x77, 0xfd, 0x6c, 0xd9, 0x8e, 0xdd, 0xc3, 0x0c, 0xbb, 0xe6, 0x6f, 0x9a, 0x63, 0xc7, + 0xd8, 0x6f, 0xde, 0x18, 0x01, 0x94, 0xd9, 0x82, 0xc5, 0x82, 0x83, 0x52, 0xad, 0xda, 0x96, 0x44, 0x5e, 0xe9, 0x40, + 0xb5, 0x19, 0xc1, 0x7d, 0xb5, 0x90, 0x33, 0xcf, 0x0c, 0xf4, 0x6d, 0x85, 0x68, 0xe1, 0xb0, 0x01, 0x7f, 0xa3, 0xad, + 0x63, 0x0c, 0xd3, 0xac, 0x66, 0xda, 0x16, 0x75, 0xf9, 0x7d, 0xef, 0x99, 0xfc, 0x46, 0x06, 0xb6, 0x10, 0x49, 0xe1, + 0x38, 0xbe, 0x78, 0x72, 0xc2, 0x7f, 0xd5, 0xf2, 0xa8, 0xd5, 0x7e, 0xa1, 0xd4, 0xa7, 0xd7, 0x74, 0x44, 0x13, 0xf7, + 0xa2, 0x2d, 0xc3, 0x1a, 0x65, 0x4d, 0x2d, 0x1d, 0x86, 0x71, 0x0d, 0xfb, 0xf2, 0xc0, 0xa1, 0xef, 0x80, 0x40, 0x5b, + 0xa5, 0x52, 0xa0, 0x85, 0x63, 0x18, 0x85, 0x59, 0x48, 0x79, 0x58, 0x98, 0xa5, 0xbc, 0xc7, 0x02, 0x2d, 0x6e, 0xd5, + 0x3d, 0xa6, 0xb6, 0x5b, 0x10, 0x61, 0xf5, 0x96, 0x71, 0x7e, 0xd9, 0xa8, 0xc2, 0x6d, 0x01, 0x8a, 0x22, 0x28, 0x83, + 0x3d, 0xc9, 0x6d, 0x0b, 0x25, 0xcd, 0x46, 0x61, 0x2d, 0x6e, 0x8b, 0x72, 0xd7, 0x6b, 0xd8, 0x02, 0x2f, 0xa8, 0xfa, + 0x09, 0x61, 0x5b, 0xf6, 0xac, 0x43, 0xb9, 0x48, 0xff, 0x23, 0x4b, 0xcf, 0xf7, 0x5b, 0x73, 0xfe, 0xa7, 0xaf, 0xe8, + 0xa3, 0xf2, 0x3f, 0xbf, 0xa4, 0x9f, 0x0c, 0x96, 0x91, 0x53, 0xea, 0x97, 0x68, 0x74, 0x93, 0xe6, 0x84, 0xb1, 0xe5, + 0xeb, 0xa7, 0xdf, 0x21, 0x53, 0x90, 0x1c, 0x4a, 0xa9, 0xca, 0xc9, 0x1e, 0xfa, 0xc2, 0xeb, 0x3e, 0xcc, 0x04, 0x03, + 0x10, 0x5e, 0xa3, 0x4d, 0x35, 0x61, 0x12, 0x0f, 0xae, 0xe0, 0xff, 0x46, 0x10, 0x83, 0xf6, 0x89, 0xa2, 0x8e, 0x6d, + 0x23, 0x5d, 0xb7, 0x9d, 0x83, 0xe4, 0x4e, 0x5d, 0xf9, 0xa3, 0x72, 0xf2, 0x9f, 0x68, 0x88, 0xbc, 0xe2, 0x0a, 0xb1, + 0xb2, 0xe0, 0x12, 0x8b, 0xa1, 0x22, 0x05, 0xb8, 0x86, 0x20, 0x52, 0x16, 0x25, 0x85, 0x5b, 0x0e, 0xaa, 0x22, 0x00, + 0xe3, 0x6a, 0x75, 0xd4, 0x89, 0xf0, 0x71, 0x6b, 0x2d, 0x42, 0xb0, 0xa2, 0x51, 0x2b, 0x6b, 0x05, 0xbe, 0x20, 0x7d, + 0xe9, 0x50, 0x10, 0xd3, 0xa3, 0x90, 0xaa, 0xd2, 0xa1, 0x40, 0x9a, 0x43, 0xc5, 0x37, 0x06, 0x1b, 0x45, 0x45, 0x7a, + 0xfe, 0xd2, 0xa4, 0xe4, 0xd2, 0x98, 0xf1, 0x5e, 0x94, 0x91, 0xc8, 0xeb, 0xf0, 0x56, 0x4c, 0x0b, 0xe4, 0x1b, 0x3d, + 0x7e, 0x10, 0x5c, 0xc2, 0xbb, 0x21, 0xf7, 0x0a, 0xb0, 0x25, 0x60, 0x07, 0xb8, 0x57, 0x66, 0x94, 0xeb, 0xb4, 0xae, + 0xdf, 0x5a, 0x0f, 0xc5, 0x30, 0x7c, 0x6c, 0x09, 0x6c, 0x47, 0xeb, 0xe8, 0x48, 0x0f, 0x1f, 0xfe, 0xd7, 0x55, 0xcd, + 0x51, 0xa7, 0x72, 0x39, 0x3b, 0x9e, 0xb0, 0x14, 0x31, 0x83, 0xee, 0xaf, 0xdb, 0x6b, 0x01, 0x74, 0xbb, 0x2c, 0xe6, + 0xd9, 0x68, 0x27, 0xff, 0x96, 0x6e, 0xac, 0x28, 0x6d, 0xe2, 0x5d, 0xd6, 0x1b, 0xfb, 0xc3, 0xd1, 0x5f, 0x1e, 0xbf, + 0x9d, 0x10, 0xaa, 0xce, 0x86, 0xad, 0x75, 0x9c, 0xcb, 0xff, 0xfa, 0xeb, 0x98, 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, + 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, 0x5f, 0x6a, 0x9d, 0x30, 0x31, 0xb2, + 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0x5b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x3e, 0x59, 0x1b, 0x0d, 0xe6, 0x8a, 0xd7, 0xb3, + 0xf5, 0x5c, 0x2a, 0x9f, 0xc1, 0x94, 0xb3, 0x1c, 0x9c, 0x2c, 0x85, 0xdd, 0x91, 0x40, 0xd1, 0x9a, 0xa1, 0x6b, 0x7f, + 0x8a, 0xad, 0x7a, 0x91, 0x56, 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf6, + 0x47, 0xa5, 0x1f, 0x8c, 0x27, 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, + 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x05, 0xdf, 0xf8, 0xca, 0x07, 0xe3, 0x1a, 0xb5, 0xd5, 0xa0, 0xa0, 0x76, 0x74, + 0xcb, 0x63, 0x47, 0xef, 0x7c, 0x77, 0x42, 0x5f, 0xbd, 0xd0, 0xc2, 0xf1, 0x37, 0xce, 0xc8, 0x35, 0x5b, 0x75, 0xc8, + 0x11, 0xcd, 0xa4, 0x43, 0x88, 0x58, 0xb1, 0x35, 0xbb, 0x26, 0x95, 0x73, 0xe7, 0x90, 0x9d, 0x3e, 0x42, 0x95, 0x5e, + 0xeb, 0xe1, 0xed, 0x44, 0xe9, 0x6e, 0x8f, 0x77, 0x93, 0xef, 0xd9, 0x44, 0xc4, 0x60, 0x40, 0x1b, 0x84, 0x33, 0xb2, + 0x0e, 0x91, 0x4a, 0x07, 0x08, 0x81, 0x63, 0x02, 0x9a, 0xfe, 0xfb, 0x5b, 0x12, 0x05, 0x1c, 0x69, 0x23, 0x64, 0x2d, + 0x3b, 0x1c, 0x72, 0xd0, 0x28, 0x37, 0x7f, 0x7a, 0x85, 0x3a, 0xcd, 0x81, 0x79, 0xba, 0x84, 0x3d, 0x07, 0x8f, 0xf4, + 0xe2, 0xf8, 0x48, 0xff, 0xef, 0x68, 0xa2, 0xc6, 0xff, 0xb9, 0x26, 0x4a, 0x69, 0x91, 0x1c, 0xd5, 0xd2, 0x77, 0xa9, + 0xa3, 0xe0, 0x22, 0xef, 0xa8, 0x85, 0xec, 0x59, 0x36, 0x6e, 0x54, 0xf3, 0xfe, 0x7f, 0xad, 0xcc, 0xff, 0xd7, 0xb4, + 0x32, 0x4c, 0xc9, 0x8e, 0xa5, 0x9a, 0x79, 0xa0, 0x55, 0x0c, 0xb3, 0xd7, 0x24, 0x21, 0x32, 0x5c, 0x1a, 0xf0, 0xa3, + 0x0a, 0xf6, 0x71, 0x5a, 0xad, 0xb3, 0x70, 0x87, 0x4a, 0xd4, 0x1b, 0x71, 0x9b, 0xe6, 0xcf, 0xea, 0x7f, 0x8b, 0xb2, + 0x80, 0xa9, 0x7d, 0x5b, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, 0x63, 0x1b, 0x5f, 0xcb, 0xf1, 0xb4, + 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0x96, 0x92, 0x9c, 0xcb, 0xca, 0xe2, 0x1e, 0xa1, 0x9b, 0x7f, 0x2a, 0xcb, + 0xa2, 0xf4, 0x7a, 0x9f, 0x92, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, + 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, + 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, + 0x36, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, + 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xdb, 0x1c, 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, + 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, + 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x5c, 0xb6, 0x92, 0xb0, 0x6f, 0xdf, 0xb5, 0x53, 0x45, + 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0x4f, 0x19, 0x47, 0x92, 0x28, 0x11, 0xbc, 0xcd, 0x1b, 0x33, 0x0e, 0xaf, 0xda, + 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, + 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, + 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x0b, 0x89, 0x4b, 0x88, 0x97, 0xf9, 0x6a, 0x9a, 0x46, + 0xc1, 0xa3, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, + 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, + 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, + 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, + 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0xd7, 0x42, 0x75, 0xb0, 0x2d, 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, + 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, + 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, + 0xf8, 0xab, 0xcc, 0xc3, 0xb4, 0x9a, 0x95, 0x60, 0xce, 0x37, 0x50, 0x89, 0xf1, 0x64, 0x79, 0xc5, 0x37, 0x2e, 0x56, + 0x62, 0x32, 0x5b, 0xce, 0x27, 0x6b, 0x49, 0x35, 0x97, 0x7b, 0x6b, 0x96, 0xb1, 0x25, 0xec, 0x1f, 0x06, 0xf9, 0xd1, + 0x81, 0x1d, 0x4d, 0x35, 0x6d, 0x12, 0x60, 0x32, 0x9d, 0x73, 0x3e, 0xbc, 0x44, 0x34, 0x59, 0x9d, 0xba, 0x93, 0xa9, + 0x6a, 0x07, 0xd7, 0xe4, 0x4c, 0x4e, 0x8f, 0xd4, 0x53, 0xad, 0x7b, 0xc9, 0x47, 0xdb, 0x61, 0x35, 0xda, 0xfa, 0x01, + 0xb8, 0x75, 0x0a, 0x3b, 0x7d, 0x37, 0xac, 0x46, 0x3b, 0x5f, 0xc3, 0xee, 0x92, 0x42, 0xa0, 0xfa, 0x52, 0xd6, 0x64, + 0x2e, 0x5e, 0x17, 0xf7, 0x5e, 0xc1, 0x9e, 0xf8, 0x03, 0xfd, 0xab, 0x64, 0x4f, 0x7c, 0x9b, 0xc9, 0xf5, 0xb7, 0xb4, + 0x6b, 0x34, 0x66, 0x3a, 0x5e, 0xbb, 0x02, 0x2b, 0x34, 0x40, 0x7e, 0xc1, 0x8e, 0xf6, 0x2a, 0x07, 0x81, 0x00, 0xdd, + 0x4b, 0x70, 0x14, 0x05, 0x44, 0x4d, 0xab, 0xca, 0xa3, 0xd3, 0xbd, 0xbf, 0xc7, 0x37, 0x42, 0xc0, 0x26, 0x4f, 0xad, + 0x7b, 0xcb, 0xd8, 0x3f, 0x1c, 0x20, 0x84, 0x5e, 0x4e, 0xbf, 0xd1, 0x96, 0xd5, 0xa3, 0x1d, 0xcb, 0x7d, 0xc3, 0xa8, + 0xa7, 0x60, 0x0c, 0x43, 0x17, 0x56, 0x31, 0x92, 0x67, 0x40, 0xd6, 0xf8, 0x0d, 0xa2, 0x0b, 0x58, 0xf4, 0x7a, 0x9f, + 0x8e, 0x68, 0x10, 0x01, 0x95, 0x5e, 0x73, 0xd4, 0x22, 0x9f, 0xab, 0x42, 0xf4, 0xde, 0x5b, 0x3b, 0x6f, 0x66, 0x24, + 0xcb, 0xa4, 0x91, 0x6a, 0xb7, 0xb2, 0x58, 0x57, 0xde, 0xec, 0x84, 0x74, 0x31, 0xc7, 0x50, 0x19, 0x3c, 0x0e, 0x40, + 0xe9, 0xf9, 0xef, 0xd0, 0x2b, 0x19, 0x32, 0xcd, 0x12, 0xcd, 0xec, 0xae, 0xf1, 0x27, 0xab, 0xd4, 0x8b, 0x11, 0x31, + 0x1b, 0xd8, 0x42, 0xdc, 0x16, 0x95, 0x6e, 0x8b, 0x42, 0xd9, 0xa2, 0x48, 0x1f, 0x6a, 0x67, 0xba, 0x33, 0x0b, 0x9f, + 0x55, 0xd6, 0x4a, 0xc9, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, 0x40, 0x85, 0x90, 0xbf, 0x40, 0x44, 0x24, + 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, 0x46, 0x79, 0xc9, 0x93, 0xa3, 0x01, 0xa9, + 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xba, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, + 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, + 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, + 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, + 0xe9, 0xd9, 0x7f, 0xa4, 0x6e, 0xcf, 0xca, 0xc9, 0x5e, 0x74, 0x4e, 0xf6, 0xe9, 0x6c, 0x1e, 0x08, 0x2e, 0x77, 0xee, + 0xf3, 0x7c, 0xaa, 0xa7, 0x5d, 0xe5, 0x07, 0xad, 0x21, 0xb2, 0xc6, 0xae, 0xea, 0x5e, 0x57, 0xb0, 0x80, 0x25, 0xb8, + 0x5b, 0x2f, 0xcd, 0x7f, 0xc3, 0xee, 0xef, 0x05, 0xbd, 0x34, 0xff, 0x9d, 0xfe, 0xa4, 0x00, 0x0e, 0x40, 0x63, 0x6a, + 0xb7, 0xc0, 0x43, 0x0c, 0x15, 0x14, 0xee, 0x66, 0xe5, 0xdc, 0xab, 0x01, 0x0e, 0x93, 0xf4, 0x0d, 0xad, 0x5e, 0x69, + 0xb1, 0xeb, 0x65, 0xb2, 0x57, 0x80, 0x87, 0x2a, 0xe4, 0xe1, 0xe1, 0x10, 0x75, 0x0c, 0x3b, 0xa8, 0x23, 0x60, 0xd8, + 0x43, 0x68, 0x6c, 0x81, 0xe7, 0xe3, 0x87, 0x8c, 0xef, 0x05, 0xa8, 0x8d, 0x10, 0x1e, 0xaf, 0x16, 0x65, 0x88, 0x2d, + 0x7b, 0x85, 0x54, 0x52, 0xaf, 0x05, 0xa2, 0x8c, 0x56, 0x01, 0x6d, 0xb5, 0xc7, 0x2c, 0x8d, 0x1f, 0x21, 0x54, 0x2c, + 0xf5, 0x31, 0x84, 0x06, 0x0e, 0xbf, 0xc3, 0x01, 0x24, 0xf8, 0x92, 0x6b, 0xb2, 0xb9, 0x57, 0xf9, 0x1d, 0xed, 0xf3, + 0x87, 0xc3, 0xf9, 0x25, 0x82, 0xd2, 0xa5, 0xf0, 0x91, 0x4a, 0x44, 0xf5, 0x14, 0x37, 0x25, 0x64, 0xb3, 0x64, 0xa5, + 0x1f, 0xfc, 0x43, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, + 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, + 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, + 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, + 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, + 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, + 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, + 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, + 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, + 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, + 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, 0xe0, 0x4f, 0xc5, 0x68, 0x5d, 0x10, 0x20, + 0xb2, 0xd9, 0xbe, 0x3e, 0x54, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, + 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0xbd, 0xbd, 0xfd, 0x69, 0x90, 0x9d, 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, + 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, + 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0x4b, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, + 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, + 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, + 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, + 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, + 0x46, 0x69, 0xf5, 0xb3, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, + 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xeb, 0x34, 0xd8, 0x61, 0xa2, 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, + 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, + 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, + 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, + 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x6b, 0x8b, 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0xcf, + 0x8b, 0xed, 0x9b, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x67, 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, + 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, + 0x1c, 0xc7, 0x1f, 0xa1, 0x82, 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, + 0x59, 0xbf, 0x2f, 0x7f, 0x51, 0x17, 0x5d, 0x64, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, + 0xcf, 0x93, 0x69, 0xf2, 0x38, 0x0f, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc2, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, + 0xe9, 0x8b, 0xcf, 0x2b, 0x3f, 0xd0, 0xd9, 0x73, 0x93, 0x0c, 0x6f, 0x56, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, + 0x9f, 0x9d, 0xc1, 0xc6, 0xb9, 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x34, 0xc3, 0x75, 0xa9, 0xda, + 0xe8, 0xa3, 0x10, 0x9d, 0x43, 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x65, 0x52, 0x69, 0x23, 0x01, 0x74, + 0x0f, 0x93, 0x06, 0x5b, 0x0c, 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0x43, 0x25, 0x71, 0x68, 0x59, + 0x24, 0xff, 0xde, 0xf5, 0xf4, 0x15, 0x52, 0x77, 0xb2, 0x40, 0x66, 0x8c, 0x67, 0x79, 0xfc, 0x09, 0x08, 0xb3, 0x41, + 0x1b, 0x15, 0x85, 0x10, 0xb2, 0x41, 0x0c, 0x1a, 0xcf, 0xf2, 0xf8, 0xb9, 0xa2, 0xf1, 0x90, 0x8f, 0x22, 0x5f, 0xfd, + 0x55, 0xea, 0xbf, 0x42, 0x9f, 0x99, 0xe0, 0x11, 0xaa, 0x89, 0xfe, 0xdd, 0xf3, 0xd9, 0x1d, 0xa8, 0x0d, 0xa3, 0x30, + 0x33, 0xe5, 0x57, 0xbe, 0x29, 0xce, 0x5e, 0x7f, 0x45, 0x57, 0xd9, 0xd6, 0xfd, 0xe8, 0xe5, 0x11, 0x81, 0xb5, 0x31, + 0xba, 0xe2, 0xc6, 0x00, 0x72, 0x98, 0xbc, 0x5f, 0x51, 0x5a, 0x0e, 0x69, 0x10, 0x3a, 0x68, 0x08, 0xa3, 0x25, 0xd1, + 0x07, 0x12, 0x8b, 0x18, 0xc3, 0x0b, 0xf1, 0x8c, 0xd4, 0x64, 0xa2, 0x21, 0x5e, 0x11, 0xfb, 0x21, 0x5a, 0x72, 0x6a, + 0xa2, 0x1b, 0x61, 0x8a, 0x81, 0xc4, 0xce, 0x20, 0x39, 0x49, 0x6a, 0xe5, 0x17, 0xcf, 0x24, 0x61, 0x89, 0x9d, 0x87, + 0x18, 0x4c, 0x6a, 0xe9, 0x4e, 0x6f, 0xaa, 0xf4, 0xfc, 0x48, 0xcb, 0x41, 0xfb, 0x00, 0xec, 0x52, 0xd2, 0xfb, 0x27, + 0x85, 0x22, 0xde, 0x87, 0x71, 0x0c, 0xe1, 0x5b, 0x44, 0x75, 0x05, 0xce, 0xb5, 0x02, 0x8d, 0xd5, 0xc0, 0x43, 0x33, + 0xab, 0xe6, 0x43, 0x4e, 0x3f, 0x95, 0x96, 0x3f, 0x46, 0x34, 0x36, 0x5a, 0x37, 0x87, 0xc3, 0x9e, 0x56, 0xbd, 0x74, + 0x0e, 0xba, 0x6c, 0x26, 0x31, 0x71, 0x03, 0xe9, 0xfa, 0xd1, 0x6f, 0x26, 0xec, 0x45, 0x54, 0xc8, 0xa5, 0x10, 0x14, + 0xb4, 0x3a, 0x10, 0x38, 0x14, 0xde, 0xa2, 0xcc, 0x17, 0x31, 0x6d, 0x20, 0x0c, 0x3e, 0x3f, 0x90, 0x9f, 0x6f, 0x0a, + 0x52, 0xb1, 0x63, 0x5d, 0xfb, 0xfd, 0x65, 0xe9, 0x01, 0x9e, 0x9c, 0x49, 0xf2, 0xb4, 0x19, 0xc2, 0x8a, 0x00, 0x1a, + 0xb3, 0x9a, 0x2c, 0x4e, 0xb8, 0x32, 0x87, 0x2f, 0x2b, 0xaf, 0x64, 0x29, 0x53, 0xe7, 0xa9, 0x5e, 0x00, 0x51, 0xc7, + 0x1b, 0xb4, 0x22, 0xf5, 0x2b, 0x74, 0xf6, 0x9a, 0x95, 0x90, 0xf1, 0xf0, 0x9c, 0xf3, 0x74, 0x74, 0xcf, 0x12, 0x1e, + 0xe1, 0x5f, 0xc9, 0x44, 0x1f, 0x7e, 0xf7, 0x1c, 0x6e, 0xc6, 0x09, 0x8f, 0xdc, 0x66, 0xef, 0xab, 0x70, 0x05, 0x37, + 0xd3, 0x02, 0x90, 0xdc, 0x82, 0xa4, 0x09, 0x28, 0x21, 0x91, 0x09, 0x99, 0x35, 0x25, 0x7f, 0x6d, 0x69, 0x1b, 0xac, + 0x61, 0xd2, 0x79, 0xc0, 0x8b, 0x56, 0x1f, 0xad, 0x26, 0xda, 0x65, 0x96, 0xcf, 0x87, 0x38, 0x43, 0x35, 0xc7, 0xdd, + 0x19, 0xfc, 0x1c, 0xf0, 0x8a, 0x55, 0x4d, 0x3a, 0xda, 0x0d, 0xb8, 0xf0, 0xe4, 0x3a, 0x4f, 0x47, 0x5b, 0xfc, 0x25, + 0xf7, 0x07, 0x80, 0x0e, 0xa6, 0x2e, 0x81, 0x3f, 0x55, 0x5b, 0x4d, 0xa5, 0x7e, 0x6e, 0xed, 0xd7, 0x75, 0x67, 0xb5, + 0x72, 0xcf, 0xba, 0x0c, 0xed, 0x91, 0x21, 0x67, 0xcc, 0x80, 0x3f, 0x67, 0x2c, 0xf9, 0x73, 0xc6, 0x8a, 0x3f, 0x67, + 0xdc, 0x18, 0x19, 0x40, 0x09, 0xee, 0x25, 0x7f, 0xba, 0x47, 0xcc, 0x10, 0xab, 0x41, 0x25, 0xb0, 0xb2, 0x94, 0x73, + 0x1f, 0x39, 0xc5, 0x94, 0x53, 0x86, 0x97, 0x4e, 0x67, 0xee, 0x40, 0xce, 0x83, 0x99, 0x3b, 0x4c, 0xf6, 0xfa, 0xdc, + 0x88, 0x63, 0x69, 0x4c, 0x8a, 0x0a, 0xd2, 0x39, 0x1d, 0x6e, 0x5e, 0x1d, 0xe7, 0x09, 0xcb, 0xf8, 0xb8, 0x7d, 0xa6, + 0x40, 0x88, 0x2d, 0x9e, 0x21, 0x91, 0x52, 0x35, 0xcb, 0x6d, 0xfe, 0x70, 0xa8, 0x47, 0xf7, 0x7a, 0xa7, 0x87, 0x5f, + 0x09, 0xfb, 0x39, 0xf3, 0xec, 0x13, 0x04, 0x30, 0x49, 0xe4, 0x99, 0x84, 0xa3, 0x1f, 0xcb, 0xd1, 0xdf, 0x34, 0xfc, + 0x79, 0x86, 0xea, 0xee, 0x10, 0x98, 0xd8, 0xb2, 0x03, 0x87, 0xe0, 0x74, 0x55, 0x89, 0x04, 0x1c, 0x6c, 0x36, 0x2c, + 0xd2, 0x7b, 0x3c, 0xc4, 0xf9, 0xa0, 0xf0, 0x11, 0x1a, 0x66, 0xf4, 0x7e, 0x7f, 0x23, 0xbc, 0x4a, 0xb6, 0xf2, 0x70, + 0x48, 0x2c, 0x0d, 0x90, 0xa3, 0x8f, 0xa3, 0x3d, 0x4a, 0xa8, 0xfd, 0xa8, 0xd6, 0x9b, 0x4a, 0x3d, 0xc8, 0xcd, 0x2e, + 0x24, 0x06, 0x15, 0x4b, 0xf5, 0xe9, 0x95, 0xea, 0x43, 0xcd, 0x92, 0x43, 0xaa, 0xe3, 0x3e, 0x15, 0xa3, 0xb5, 0x9c, + 0x10, 0xe0, 0x3a, 0x48, 0x34, 0x3a, 0x00, 0xc6, 0xd9, 0x66, 0xcb, 0x4b, 0x6d, 0x9d, 0x28, 0x1d, 0xc7, 0xb9, 0x3e, + 0x8e, 0x0f, 0x07, 0x29, 0x66, 0x5c, 0x1e, 0x89, 0x19, 0x97, 0x0d, 0xc0, 0x9b, 0x75, 0x1e, 0xd4, 0x87, 0xc3, 0x25, + 0x5d, 0x8a, 0x4c, 0x67, 0x1b, 0xe5, 0x67, 0x3d, 0xba, 0x7f, 0x9c, 0xa0, 0xb9, 0xb7, 0xc2, 0xde, 0x8b, 0x64, 0x7b, + 0x26, 0xeb, 0xd4, 0xcb, 0xc8, 0xa7, 0x17, 0xee, 0xd9, 0x25, 0x57, 0x3f, 0xac, 0xbe, 0x9e, 0xfe, 0x26, 0xbc, 0x88, + 0x55, 0xb4, 0x5b, 0x97, 0x4c, 0xd8, 0x5b, 0x4a, 0x25, 0xad, 0xf2, 0xf2, 0xe9, 0xc6, 0x0f, 0x30, 0x33, 0xed, 0xe9, + 0x83, 0x6c, 0x44, 0xf5, 0x67, 0x25, 0x6a, 0x65, 0x98, 0x2c, 0x9c, 0x97, 0x4c, 0x3d, 0x19, 0xf0, 0x98, 0x95, 0x3c, + 0x92, 0x9d, 0xde, 0x18, 0x04, 0x01, 0xac, 0x73, 0xd2, 0xaa, 0x33, 0x8e, 0x46, 0xab, 0xca, 0xc5, 0xe9, 0x2a, 0x17, + 0x18, 0x6e, 0xb7, 0x66, 0x1b, 0x55, 0x67, 0xb9, 0xa9, 0x55, 0xca, 0x77, 0x00, 0x1f, 0xcb, 0x2a, 0x17, 0x74, 0x4c, + 0x99, 0x3a, 0x6f, 0x20, 0x18, 0x5b, 0xd5, 0xb8, 0x70, 0x6a, 0x5c, 0xf0, 0x88, 0xda, 0xdd, 0x34, 0xf5, 0x68, 0x0b, + 0x2c, 0xa5, 0xa3, 0x1d, 0x2f, 0x51, 0xa5, 0xf0, 0x0f, 0xc1, 0xf7, 0x61, 0x1c, 0x3f, 0x2f, 0xb6, 0xea, 0x40, 0xbc, + 0x29, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, + 0x92, 0xc2, 0xb9, 0xf9, 0xf3, 0x70, 0xa0, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, + 0xee, 0x44, 0x09, 0x8e, 0x5c, 0xf2, 0xaf, 0xc3, 0x41, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0xdb, 0x7f, 0x0d, 0xc6, 0x0c, + 0x5d, 0x9a, 0x80, 0x65, 0x63, 0x24, 0xff, 0x6a, 0x9a, 0x79, 0xc3, 0x64, 0xcd, 0x14, 0x8e, 0x43, 0xc3, 0x08, 0x69, + 0x40, 0xb7, 0x41, 0x6d, 0x78, 0x32, 0xdf, 0x54, 0xe5, 0x57, 0x77, 0xa4, 0xda, 0x0f, 0x86, 0x97, 0x13, 0x71, 0x4e, + 0x97, 0x24, 0xf5, 0x54, 0x42, 0x49, 0x08, 0x76, 0xe9, 0x03, 0x39, 0xb1, 0x02, 0xb2, 0x96, 0xb1, 0xfc, 0x56, 0x0f, + 0x08, 0xfd, 0xa7, 0xdd, 0x7a, 0xa1, 0xff, 0x34, 0xcd, 0x16, 0xea, 0xfa, 0xc3, 0xe4, 0xbe, 0xa3, 0xd7, 0x1f, 0x1c, + 0xde, 0xa9, 0xab, 0x8a, 0xab, 0x78, 0x54, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8a, 0x4d, 0xad, 0x96, 0xa7, 0xe3, + 0x30, 0x02, 0x33, 0x82, 0x02, 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xac, 0xe4, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, + 0x71, 0x3e, 0x6e, 0x81, 0x4a, 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0x9f, 0x55, 0x36, 0x76, 0x0b, 0xe4, 0x90, + 0x64, 0xb2, 0xb8, 0x1d, 0xdd, 0x88, 0x65, 0x51, 0x8a, 0xd7, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, + 0x89, 0xd2, 0xde, 0x44, 0x9a, 0xa0, 0xfb, 0x96, 0xad, 0x00, 0x64, 0x00, 0x45, 0x5d, 0xed, 0xd6, 0xe7, 0xfc, 0x1c, + 0x49, 0x33, 0x1c, 0x46, 0xb7, 0x4f, 0x6f, 0x83, 0xdb, 0xc1, 0x25, 0x6a, 0xa5, 0x2f, 0x59, 0xdc, 0xc2, 0xa0, 0xda, + 0x9b, 0x25, 0x1c, 0xd4, 0xcc, 0x5a, 0x1b, 0x81, 0x60, 0xb2, 0x87, 0x82, 0x8a, 0xb9, 0x82, 0x7d, 0x50, 0xb0, 0x96, + 0xbc, 0x0e, 0x0e, 0xb7, 0xf6, 0x65, 0xa5, 0xb8, 0x78, 0x72, 0x91, 0xb4, 0x2e, 0x2c, 0xe5, 0xc5, 0x93, 0x06, 0x0c, + 0x2e, 0x47, 0xd8, 0x54, 0x60, 0x92, 0x00, 0xd0, 0xad, 0x88, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, + 0xc1, 0x86, 0xdd, 0xc3, 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, + 0xe6, 0x5f, 0x33, 0x2f, 0x52, 0x02, 0x6e, 0x86, 0x28, 0x5f, 0x1b, 0x38, 0x99, 0xf4, 0xe4, 0x5a, 0xb2, 0x18, 0xb0, + 0xa0, 0xc1, 0x77, 0xd4, 0xfa, 0x3b, 0x93, 0x7f, 0xe3, 0xe9, 0xa1, 0x1f, 0xfc, 0x9a, 0x79, 0x4b, 0x9f, 0xbd, 0xad, + 0x64, 0xb4, 0x26, 0x89, 0xf2, 0xea, 0xe1, 0x12, 0xe4, 0x86, 0xe5, 0xe8, 0x9e, 0x2d, 0x41, 0x9c, 0x58, 0x8e, 0x12, + 0xca, 0xe8, 0x0a, 0xf7, 0x2a, 0xb3, 0x65, 0x22, 0x90, 0xe2, 0xc0, 0x52, 0xca, 0xbd, 0xc5, 0x3a, 0x58, 0xe2, 0xfe, + 0x44, 0x72, 0x01, 0x25, 0x0f, 0xa0, 0x5c, 0x29, 0x20, 0xe0, 0xd3, 0x01, 0x94, 0x2f, 0xe5, 0x45, 0xf8, 0x13, 0x27, + 0x6a, 0xb0, 0x1c, 0xdd, 0x37, 0xec, 0x67, 0x2f, 0xb4, 0xec, 0x0f, 0xb7, 0x5a, 0xd3, 0xb0, 0xe2, 0xb7, 0x30, 0x2d, + 0x26, 0x6e, 0x5f, 0xae, 0xec, 0xaa, 0xf8, 0x6c, 0xa5, 0xce, 0x6e, 0x6a, 0x48, 0xc2, 0xbe, 0x21, 0xab, 0x00, 0x07, + 0xab, 0x22, 0xee, 0x59, 0x97, 0xfb, 0x30, 0xfa, 0xb2, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, + 0x65, 0xa2, 0x13, 0x2d, 0x04, 0x57, 0x60, 0x10, 0xb8, 0x13, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, + 0x12, 0x42, 0xaa, 0xfb, 0x19, 0xa8, 0xed, 0xc4, 0x5d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, + 0xba, 0xc5, 0xa6, 0xab, 0xcd, 0xea, 0x23, 0x3a, 0x97, 0xb6, 0xdc, 0xfc, 0x84, 0x2d, 0xd6, 0x0a, 0x94, 0x4d, 0x48, + 0xda, 0xce, 0x79, 0x8e, 0xb2, 0x09, 0x2d, 0xed, 0x3d, 0xf5, 0xa8, 0x50, 0x9d, 0x6c, 0xbd, 0x54, 0x4d, 0x2d, 0xc2, + 0x6a, 0x71, 0x51, 0xf9, 0x01, 0xe8, 0xa6, 0xd2, 0xea, 0x59, 0x5d, 0xa3, 0x29, 0xd4, 0x6a, 0xe1, 0xb8, 0xd1, 0xce, + 0xa6, 0xcb, 0xf4, 0x16, 0x71, 0x56, 0xa5, 0x1d, 0xfa, 0x97, 0x4c, 0xbb, 0x5e, 0x76, 0xf4, 0x9b, 0x71, 0x75, 0x81, + 0x0b, 0xb1, 0x01, 0x9f, 0x73, 0x7f, 0x79, 0xbd, 0x27, 0x71, 0xcf, 0x3f, 0x1c, 0x90, 0x3d, 0xa9, 0xfd, 0xa1, 0xfa, + 0xd8, 0x15, 0x0c, 0x59, 0x18, 0xa5, 0xfe, 0x22, 0xe5, 0xbd, 0x47, 0x38, 0xee, 0x9f, 0xab, 0x1e, 0xfb, 0x57, 0xc6, + 0xf7, 0x75, 0xb1, 0x89, 0x12, 0x8a, 0x6a, 0xe8, 0xad, 0x8a, 0x4d, 0x25, 0xe2, 0xe2, 0x3e, 0xef, 0x31, 0x4c, 0x86, + 0xb1, 0x90, 0xa9, 0xf0, 0xa7, 0x4c, 0x05, 0x8f, 0x10, 0x4a, 0xdc, 0xac, 0x7b, 0xa4, 0xdd, 0x84, 0x38, 0xa5, 0x5a, + 0x94, 0x32, 0x19, 0xff, 0xd6, 0x4f, 0xa0, 0x3c, 0xa7, 0x68, 0x99, 0x7e, 0x54, 0xb8, 0x4c, 0xdf, 0xac, 0x8f, 0x4b, + 0xcf, 0x44, 0xa8, 0x33, 0x17, 0x9b, 0x5a, 0xa7, 0x63, 0xec, 0x94, 0x4e, 0x6d, 0xd8, 0xd7, 0x4a, 0x71, 0x59, 0x51, + 0xf8, 0x37, 0x12, 0x59, 0xf5, 0x8c, 0x38, 0xfe, 0x7b, 0xd6, 0x3e, 0xc3, 0x2a, 0xf0, 0xcb, 0x40, 0xde, 0x2f, 0x00, + 0x3e, 0xae, 0xeb, 0x32, 0xbd, 0xd9, 0x00, 0x6d, 0x08, 0x0d, 0x7f, 0xcf, 0x47, 0x06, 0x4c, 0xf7, 0x11, 0xce, 0x90, + 0x1e, 0xea, 0x9c, 0xd3, 0x59, 0x99, 0xce, 0xb9, 0x0a, 0x6b, 0x09, 0xf6, 0x72, 0xd2, 0xe4, 0x72, 0x5d, 0x82, 0x9a, + 0x09, 0xdc, 0x3e, 0xb4, 0x47, 0x84, 0x50, 0x9b, 0xb2, 0x9a, 0x5e, 0x42, 0xcd, 0x3b, 0x39, 0xed, 0x68, 0x52, 0x82, + 0xab, 0x86, 0xce, 0xca, 0xf5, 0x5f, 0x87, 0x43, 0xef, 0x26, 0x2b, 0xa2, 0x3f, 0x7b, 0xe8, 0xef, 0xb8, 0xfd, 0x98, + 0x7e, 0x85, 0x68, 0x19, 0xeb, 0x6f, 0xc8, 0x80, 0x8e, 0x27, 0xc3, 0x9b, 0x62, 0xdb, 0x63, 0x5f, 0x51, 0x83, 0xa5, + 0xaf, 0x1f, 0x1f, 0x41, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0x5f, + 0x21, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, 0xd7, 0xb2, 0xaf, 0x7c, 0xe7, 0x02, 0x60, + 0x65, 0x9f, 0xd8, 0x70, 0x4f, 0xfa, 0x53, 0xaa, 0x0f, 0xdb, 0xdf, 0x92, 0x05, 0x14, 0x5a, 0x58, 0x4f, 0xe5, 0xec, + 0xbc, 0x2d, 0x79, 0x95, 0x4d, 0xf7, 0x6b, 0xd8, 0xa3, 0xee, 0xd0, 0x6b, 0x2a, 0x38, 0xbf, 0x34, 0xa3, 0xf7, 0xc5, + 0x50, 0xa8, 0x8e, 0x3a, 0x77, 0x90, 0xdb, 0xd2, 0xba, 0xe4, 0xfc, 0x66, 0xe5, 0x8e, 0xc2, 0xfc, 0x2e, 0x04, 0xcf, + 0xb0, 0xee, 0xdd, 0xc5, 0x79, 0xef, 0x1f, 0xad, 0x39, 0xf2, 0xaf, 0x6c, 0x96, 0x22, 0x16, 0xc9, 0x1c, 0xac, 0x7e, + 0xe8, 0xe7, 0xb1, 0xdf, 0x06, 0x39, 0x1c, 0x37, 0x0d, 0xe8, 0xb0, 0x21, 0xb3, 0xf6, 0x25, 0x02, 0xa7, 0x1a, 0x41, + 0x9a, 0x9a, 0xa0, 0x66, 0x79, 0x88, 0xc4, 0x76, 0x29, 0xdb, 0x06, 0xb9, 0xee, 0x82, 0x69, 0x8e, 0xb4, 0x67, 0xf0, + 0xbe, 0x49, 0x93, 0x54, 0x68, 0x16, 0x8d, 0xae, 0x64, 0xfc, 0x3b, 0xd2, 0x66, 0x4a, 0xf6, 0xd8, 0x1a, 0x78, 0x2f, + 0x41, 0x39, 0x19, 0xa6, 0x18, 0xbe, 0xe3, 0xeb, 0x9d, 0x47, 0x17, 0xf1, 0xb7, 0x63, 0xb6, 0x49, 0xd9, 0x11, 0x4c, + 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xdd, 0x4d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, 0x53, 0x69, 0x73, 0x85, 0x6e, + 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, 0xe2, 0xb7, 0x60, 0x0e, 0x63, + 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, 0x02, 0x8c, 0xbe, 0xda, 0x16, + 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, 0xd0, 0xf9, 0x7d, 0x73, 0x53, + 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xf3, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, 0xad, 0x71, 0x9a, 0xf9, 0xdf, + 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x9f, 0x21, 0x7a, 0x5f, 0xb7, 0x72, 0x55, 0x6a, 0x37, + 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, 0x39, 0xff, 0x5c, 0xf5, 0xfb, + 0xde, 0x67, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, 0x6d, 0x4a, 0xd8, 0x90, 0xdb, + 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x6f, 0x39, 0xdf, 0xaf, 0x85, 0xbc, 0x59, 0xc9, + 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, + 0xfe, 0x8e, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, 0x5a, 0x82, 0x76, 0xc1, 0xa6, + 0xb0, 0x3a, 0x79, 0x68, 0xc8, 0xfb, 0xfd, 0x97, 0xb9, 0xd7, 0xe2, 0x75, 0x37, 0x70, 0x97, 0xa5, 0x87, 0x10, 0xc0, + 0x5a, 0x06, 0xca, 0x38, 0xc2, 0xa4, 0x8b, 0xbc, 0x46, 0xd9, 0x74, 0x22, 0xf0, 0x31, 0xcb, 0xae, 0x9c, 0x64, 0x1a, + 0x60, 0x46, 0x35, 0x85, 0x99, 0x00, 0x23, 0xf5, 0x01, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, + 0x65, 0x1c, 0xc5, 0x4c, 0x00, 0xb0, 0xf9, 0x00, 0xf2, 0x15, 0x5d, 0x1d, 0x92, 0x56, 0xaa, 0xbc, 0x5f, 0x67, 0x44, + 0x46, 0x93, 0x10, 0xcd, 0x6f, 0xe1, 0x81, 0x7d, 0xdb, 0xcc, 0xa8, 0x52, 0xcf, 0xa8, 0xca, 0x67, 0x38, 0x2c, 0x85, + 0x63, 0xc4, 0xff, 0x5b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, + 0x73, 0x38, 0xf4, 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0x14, 0x0f, 0x75, 0x65, 0x4d, 0x6b, 0x25, 0x05, 0x4e, 0x45, + 0x8d, 0x10, 0x21, 0xbc, 0x7f, 0x00, 0xcf, 0x6a, 0xea, 0xfb, 0x8d, 0x65, 0xa2, 0xfb, 0x92, 0x01, 0xe5, 0x0f, 0xc8, + 0xd7, 0x95, 0x14, 0x67, 0xd2, 0xe4, 0x21, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xb6, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, + 0x86, 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x3d, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xc7, 0x92, 0xa5, 0xd1, 0xc2, + 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x31, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, 0xea, + 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x0e, 0xd6, 0x93, 0x57, 0x5e, 0xe9, 0x4f, 0x85, 0x9c, 0xc3, + 0x46, 0x22, 0x28, 0xfc, 0x00, 0x57, 0x83, 0x95, 0x02, 0x06, 0x53, 0xdf, 0xc2, 0xd7, 0xc4, 0x73, 0x14, 0x3c, 0x0a, + 0xbb, 0x18, 0x5b, 0x2b, 0xdf, 0xf9, 0xa4, 0xa0, 0xdc, 0xb3, 0x62, 0xce, 0x2b, 0xe0, 0x5c, 0x06, 0x85, 0x30, 0x1d, + 0xcf, 0xf2, 0x7f, 0x26, 0x79, 0x3d, 0xb1, 0x21, 0x40, 0x06, 0x7f, 0x4a, 0x9c, 0x96, 0xee, 0xd0, 0x9d, 0x87, 0x9e, + 0x45, 0x1c, 0x36, 0x7a, 0xb4, 0x2e, 0x8b, 0x6d, 0x8a, 0x7a, 0x09, 0xf3, 0x03, 0xf9, 0x79, 0x4b, 0xbe, 0x0f, 0x51, + 0xbc, 0x0d, 0xfe, 0x96, 0xb1, 0x58, 0xe0, 0x5f, 0xff, 0xcc, 0x18, 0x4d, 0xb4, 0xa0, 0x4e, 0x1a, 0x24, 0x2a, 0x16, + 0xc9, 0x04, 0x60, 0x1d, 0xb9, 0xfa, 0xf0, 0x29, 0x31, 0xde, 0x9a, 0x0d, 0x0f, 0x7c, 0xb3, 0x02, 0x9d, 0xfa, 0xdc, + 0x5d, 0xd9, 0x9e, 0xae, 0x46, 0xaa, 0xaa, 0xf1, 0xb7, 0x54, 0x55, 0xe3, 0x6f, 0x29, 0x55, 0xe3, 0xb7, 0x8c, 0xe2, + 0x77, 0x2a, 0x9f, 0x21, 0x73, 0xb2, 0x89, 0x49, 0x3a, 0x7d, 0x6f, 0x38, 0xb1, 0xcb, 0x7e, 0xeb, 0x36, 0x91, 0x67, + 0x26, 0x52, 0xc8, 0xbd, 0x01, 0xa8, 0x99, 0xf8, 0x32, 0x37, 0x9c, 0x12, 0xe7, 0xe7, 0x1e, 0xae, 0xd8, 0xb4, 0xba, + 0xa6, 0x05, 0x0b, 0x6c, 0x5e, 0x66, 0x79, 0xe6, 0x09, 0x6c, 0x9b, 0x32, 0xeb, 0x87, 0xdc, 0x03, 0x08, 0x66, 0x52, + 0x13, 0x00, 0xd2, 0x42, 0x54, 0x0a, 0x91, 0x5f, 0xe3, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, + 0xdf, 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0x7f, 0xc9, 0x82, 0x34, 0x91, 0xab, 0xf4, 0x9f, 0x6e, + 0x90, 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, + 0x55, 0xca, 0x23, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0xbf, 0x97, 0x7a, 0x1a, 0xdd, 0x17, + 0x7b, 0x30, 0x06, 0xef, 0x00, 0xf0, 0x4c, 0x87, 0x06, 0x48, 0xdf, 0x33, 0xf2, 0x70, 0x9f, 0x5b, 0xf2, 0x93, 0xca, + 0xda, 0x24, 0x61, 0x45, 0xb1, 0x19, 0xc6, 0x08, 0x25, 0xe3, 0x34, 0xb6, 0x7e, 0xbf, 0xaf, 0xfe, 0xde, 0x61, 0x14, + 0x15, 0x15, 0x77, 0x8c, 0x46, 0x65, 0x55, 0x8f, 0xb6, 0x83, 0xc3, 0xe1, 0x3c, 0xb7, 0x71, 0xb4, 0xf5, 0x0a, 0xd8, + 0x5b, 0xa1, 0x52, 0xf6, 0x4a, 0x84, 0xe5, 0x87, 0x2b, 0xbf, 0xdf, 0x87, 0x7f, 0x65, 0xa4, 0x85, 0xe7, 0x4f, 0xf1, + 0xd7, 0xa2, 0x2e, 0x30, 0x3c, 0x83, 0xd6, 0x68, 0x05, 0xc1, 0x04, 0xff, 0xec, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x80, + 0x6e, 0x05, 0x7a, 0xd0, 0x70, 0x12, 0x27, 0xed, 0x0b, 0x89, 0xba, 0xbd, 0xd5, 0x69, 0xf4, 0x67, 0xc5, 0x72, 0x5e, + 0xc0, 0xe4, 0x70, 0x43, 0x9f, 0x56, 0xe1, 0xf6, 0x13, 0x3c, 0x7d, 0x0d, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, + 0xb8, 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x08, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, + 0x57, 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xaa, 0x56, 0xda, 0x59, + 0x94, 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x65, 0x82, 0x3e, 0xaf, 0xe4, 0x04, + 0x57, 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0xd3, 0x4b, 0xba, 0x21, 0xa3, 0xe7, 0xbc, + 0xe7, 0x45, 0xc3, 0xd0, 0xbf, 0xf0, 0x4a, 0x08, 0xdf, 0xc4, 0x6d, 0x1b, 0xa5, 0xb0, 0xbf, 0x09, 0x2c, 0x3e, 0x61, + 0xaf, 0xbc, 0xa5, 0x3f, 0x1d, 0x07, 0xe1, 0x10, 0xb9, 0xa1, 0x62, 0x0e, 0xec, 0x69, 0xc0, 0x62, 0x13, 0x5f, 0x6d, + 0x26, 0xf1, 0x60, 0xe0, 0xeb, 0x8c, 0xc5, 0x2c, 0x06, 0x1a, 0xe4, 0x78, 0x70, 0x39, 0xd7, 0x27, 0x84, 0x7e, 0x18, + 0x51, 0x39, 0x2a, 0xd0, 0x39, 0x88, 0x06, 0x4b, 0xc0, 0x53, 0x6f, 0x65, 0x83, 0x24, 0xe3, 0x18, 0x92, 0xb8, 0xd6, + 0x24, 0xd5, 0xe1, 0x84, 0xd6, 0x81, 0x8e, 0xab, 0x0b, 0xe8, 0x7c, 0x5c, 0xf7, 0x3e, 0x5e, 0x0d, 0x17, 0x54, 0xfa, + 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0x70, 0xb1, 0x0a, 0xb7, 0xaf, 0xe5, 0x03, 0xc7, 0x1d, 0x95, + 0x34, 0x04, 0x06, 0x6f, 0x0f, 0xdd, 0xcd, 0x8c, 0x77, 0xc8, 0xd1, 0x61, 0x9c, 0xc9, 0x21, 0x56, 0xad, 0xb8, 0x90, + 0xde, 0x08, 0xbe, 0x5d, 0x28, 0xc6, 0xb2, 0xb1, 0x4b, 0x43, 0x51, 0xf8, 0x37, 0x00, 0x3b, 0xd4, 0xfe, 0x4a, 0x25, + 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, 0x89, 0x3f, 0xb2, 0xc6, 0xba, + 0xe9, 0xfa, 0x82, 0xa9, 0x6a, 0x98, 0x74, 0x3b, 0x93, 0x58, 0x4e, 0x24, 0xa9, 0xed, 0x3e, 0x22, 0x06, 0x03, 0x1f, + 0x6c, 0xc4, 0x34, 0x13, 0xe1, 0x88, 0x47, 0x25, 0xb2, 0xe8, 0xf2, 0xdb, 0x88, 0x92, 0xb6, 0x2f, 0x2b, 0xb2, 0x05, + 0xc1, 0xf4, 0x24, 0xfa, 0x20, 0x49, 0x39, 0x15, 0x89, 0x34, 0x23, 0x04, 0xf8, 0xf1, 0xa4, 0xbc, 0xd2, 0x9f, 0x83, + 0xa6, 0x95, 0xe0, 0x25, 0x83, 0xe4, 0x91, 0xf8, 0x99, 0x14, 0xcc, 0x62, 0xac, 0x1a, 0x0c, 0xb0, 0x9c, 0xea, 0xb1, + 0x63, 0x92, 0xfe, 0x5b, 0xa7, 0x13, 0xf6, 0x33, 0x2f, 0xb7, 0xb5, 0xbc, 0x69, 0xee, 0x3d, 0xf3, 0x2a, 0x96, 0x6a, + 0x58, 0x06, 0xfd, 0xd7, 0x44, 0xbb, 0x60, 0x6b, 0xcb, 0x98, 0xb0, 0xea, 0x07, 0x90, 0xf6, 0x48, 0x97, 0x57, 0x0d, + 0x73, 0x26, 0x78, 0x74, 0x61, 0xcd, 0x83, 0xe8, 0x42, 0xf8, 0xc8, 0x65, 0x37, 0x49, 0xae, 0xc6, 0x13, 0x3f, 0x1c, + 0x0c, 0x14, 0x00, 0x2d, 0xad, 0x93, 0x62, 0x10, 0x3e, 0x16, 0x72, 0x20, 0x8d, 0x8e, 0xaa, 0x00, 0x8b, 0x65, 0x76, + 0x55, 0x4e, 0xb2, 0xc1, 0xc0, 0x07, 0xb1, 0x31, 0xb1, 0x1b, 0x9a, 0xcd, 0x7d, 0x76, 0xa2, 0x20, 0xab, 0xcd, 0x59, + 0x6b, 0xa6, 0x5b, 0x60, 0x00, 0x30, 0x88, 0x08, 0x96, 0xfb, 0xc4, 0xc8, 0x47, 0xd4, 0xe9, 0x29, 0x8c, 0x80, 0xe0, + 0x97, 0x13, 0x81, 0xc8, 0x45, 0x02, 0xf5, 0x00, 0x33, 0x01, 0x66, 0x54, 0x31, 0xbc, 0x04, 0x76, 0xf1, 0xdc, 0xbc, + 0x62, 0xd0, 0xbf, 0x68, 0x97, 0x48, 0x34, 0x95, 0x38, 0x1a, 0x23, 0xa7, 0xd2, 0x18, 0x19, 0x10, 0xbb, 0x38, 0xfe, + 0x3d, 0xa5, 0x47, 0x41, 0xca, 0x9e, 0x57, 0x86, 0x38, 0x1c, 0xc5, 0x57, 0xb0, 0x6a, 0x1c, 0x0e, 0xb5, 0x79, 0x3d, + 0x9d, 0xd5, 0xf3, 0x81, 0x08, 0xe0, 0xbf, 0xa1, 0x60, 0xbf, 0x6a, 0x2a, 0x72, 0x83, 0xd4, 0x79, 0x38, 0xa4, 0x20, + 0x9f, 0x1a, 0xab, 0x6c, 0xe5, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0x2f, 0x6a, 0x5c, 0xb7, 0x56, 0x37, 0x14, 0x12, + 0xad, 0x69, 0x52, 0x5c, 0x55, 0x93, 0x62, 0xc0, 0x73, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, 0xe7, 0x16, 0x08, + 0x93, 0xfe, 0x56, 0xdc, 0x21, 0x55, 0xe3, 0xae, 0xad, 0x76, 0xdb, 0xca, 0x86, 0x14, 0xcd, 0x87, 0x97, 0xb0, 0x4b, + 0xa7, 0x88, 0xb6, 0x5d, 0x12, 0x7c, 0x01, 0x5a, 0x56, 0x17, 0x22, 0x8f, 0xe9, 0x57, 0xc8, 0x2f, 0xc5, 0xf0, 0xaf, + 0xd2, 0xbd, 0x39, 0xb5, 0x41, 0x0e, 0x60, 0xbb, 0xf7, 0x70, 0x3b, 0x46, 0x0f, 0x64, 0xf0, 0x46, 0xc8, 0x39, 0xe7, + 0x97, 0x53, 0x6b, 0xc6, 0x44, 0xc3, 0x82, 0x95, 0xc3, 0xc8, 0x0f, 0x90, 0xf1, 0x72, 0x0a, 0xac, 0xec, 0x47, 0x45, + 0x5c, 0xfa, 0xc3, 0xc8, 0xbf, 0x78, 0x12, 0x64, 0xdc, 0x8b, 0x86, 0x1d, 0x5f, 0x80, 0xbd, 0xfa, 0xe2, 0x09, 0x8b, + 0x06, 0xbc, 0xba, 0xaa, 0xa7, 0x59, 0x30, 0xcc, 0x58, 0x74, 0x55, 0x0c, 0xc1, 0x87, 0xf6, 0x69, 0x39, 0x08, 0x7d, + 0xdf, 0xec, 0x1c, 0xc6, 0x98, 0x2c, 0x8f, 0xb0, 0x9f, 0xc1, 0x6d, 0x57, 0x4b, 0xcc, 0x60, 0xb2, 0xb9, 0x8d, 0x98, + 0xc1, 0x96, 0xbf, 0x78, 0x62, 0xb8, 0x84, 0xaa, 0xa7, 0x52, 0xb3, 0x51, 0xa0, 0x39, 0xb9, 0x42, 0x73, 0xb2, 0x12, + 0x6a, 0xc9, 0x27, 0x15, 0x4e, 0xd8, 0xf9, 0x24, 0x57, 0x76, 0xa3, 0x31, 0x06, 0x2e, 0xda, 0x5b, 0x93, 0x30, 0x32, + 0xd3, 0x59, 0x8a, 0x06, 0x2c, 0x3c, 0x13, 0xa7, 0x34, 0x06, 0xb4, 0x2f, 0x07, 0x96, 0x36, 0xe4, 0x17, 0x39, 0x33, + 0xd0, 0x36, 0xa4, 0x34, 0x6a, 0x06, 0xfe, 0x4c, 0x4d, 0x98, 0xdf, 0xc0, 0x4a, 0x04, 0x51, 0x5d, 0x80, 0x49, 0x92, + 0x93, 0xd1, 0x48, 0x59, 0x89, 0xe4, 0x1c, 0xf0, 0x3e, 0x80, 0x27, 0x8b, 0xd8, 0xd6, 0xfe, 0x94, 0xfe, 0x57, 0x87, + 0xcf, 0xa5, 0xff, 0x58, 0x00, 0x0b, 0xb9, 0x34, 0x88, 0x0c, 0x14, 0x0e, 0xa9, 0xe5, 0x18, 0x93, 0x38, 0x9e, 0x81, + 0x2f, 0xe1, 0x02, 0x4d, 0x01, 0xfd, 0x41, 0xcd, 0x28, 0x22, 0x0b, 0x7f, 0xf5, 0xec, 0xa6, 0xae, 0xf5, 0x3c, 0x73, + 0x5e, 0x83, 0x66, 0x06, 0x42, 0x7a, 0x9c, 0xaa, 0xb7, 0x21, 0xd1, 0x79, 0xf9, 0x56, 0xbf, 0x4c, 0x88, 0x64, 0x61, + 0xe4, 0xe9, 0xfb, 0x1c, 0xcc, 0x23, 0x8a, 0xd0, 0xc1, 0x95, 0x79, 0x38, 0x9c, 0x0b, 0x0a, 0xdf, 0x51, 0x9e, 0x0f, + 0x38, 0xcd, 0x92, 0x04, 0xb4, 0x81, 0x2c, 0x37, 0x65, 0xae, 0x92, 0x96, 0xa9, 0x7b, 0x0f, 0x56, 0x82, 0x0a, 0xdd, + 0x9c, 0x82, 0x42, 0x19, 0x09, 0x4a, 0x69, 0x35, 0x08, 0xa5, 0x3a, 0x2c, 0x82, 0xc8, 0x21, 0x0b, 0x01, 0x37, 0x53, + 0xd1, 0x68, 0x49, 0xc3, 0x23, 0x9c, 0x1b, 0x28, 0x04, 0x20, 0xb1, 0xa7, 0x8a, 0x32, 0x2e, 0x87, 0x80, 0x8f, 0x12, + 0x0e, 0x71, 0xd6, 0xa4, 0x2d, 0xcf, 0x41, 0x1c, 0xcb, 0x25, 0xbf, 0xad, 0x10, 0x0c, 0x22, 0xf4, 0x19, 0xf2, 0x27, + 0xcb, 0xf9, 0x77, 0xe3, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0x9b, 0xf9, 0x04, 0xe2, 0x5b, 0x6e, + 0xe6, 0xc7, 0x18, 0x22, 0x0b, 0x7f, 0x70, 0x3b, 0x94, 0x5c, 0x51, 0xe8, 0xb2, 0x1e, 0x91, 0x22, 0x7b, 0xba, 0xe6, + 0x08, 0x82, 0x03, 0xad, 0x1a, 0x64, 0x68, 0x24, 0xbe, 0x78, 0x02, 0x59, 0x83, 0x35, 0x7f, 0x5e, 0x91, 0xb3, 0xba, + 0x3f, 0xd9, 0x40, 0x35, 0xc9, 0x64, 0xad, 0xa8, 0x9c, 0xbf, 0x5d, 0x95, 0xe5, 0xc9, 0xaa, 0x0c, 0x57, 0x83, 0xae, + 0xaa, 0x2c, 0x39, 0x52, 0x1b, 0xa0, 0x35, 0x5d, 0x21, 0x86, 0x42, 0xd6, 0x60, 0x69, 0x55, 0x65, 0x4d, 0x7d, 0x02, + 0x81, 0x3e, 0xc0, 0x32, 0x6a, 0xf6, 0xd3, 0xe1, 0x2f, 0xc1, 0x2f, 0x2a, 0x64, 0xa9, 0x4e, 0xeb, 0x4c, 0xfc, 0x16, + 0x2c, 0x19, 0xfe, 0xf1, 0x7b, 0xb0, 0x06, 0x2c, 0x01, 0xb2, 0xdc, 0x6d, 0x6c, 0xb4, 0x5e, 0x15, 0x3f, 0x57, 0xeb, + 0x8b, 0x7e, 0xeb, 0x36, 0x51, 0x2b, 0xc0, 0x08, 0x85, 0x16, 0x01, 0xb6, 0x7a, 0xe0, 0x9e, 0x82, 0x1f, 0x88, 0xe1, + 0x5c, 0x93, 0xd6, 0xd4, 0x09, 0xaf, 0xb3, 0x71, 0x24, 0xa2, 0x7a, 0x0b, 0x17, 0xf7, 0x7a, 0x6b, 0xf1, 0x37, 0x2a, + 0x10, 0x00, 0x59, 0x4c, 0xb1, 0x76, 0xde, 0x90, 0x5e, 0x19, 0x76, 0x12, 0x7a, 0x6f, 0xd8, 0x09, 0xe4, 0xc5, 0x61, + 0xa7, 0xd0, 0x25, 0xda, 0x4e, 0x91, 0x9a, 0x68, 0x3b, 0x69, 0xb1, 0x0a, 0x4b, 0x08, 0x7e, 0xd5, 0xde, 0x3a, 0xca, + 0xf6, 0x45, 0x96, 0x30, 0x6d, 0x01, 0xa3, 0xdc, 0xaa, 0xcf, 0x9c, 0x22, 0x56, 0xca, 0xde, 0xe9, 0xa4, 0xca, 0x5d, + 0xe4, 0x53, 0xab, 0x29, 0x32, 0xf9, 0xf9, 0x71, 0x8b, 0xe4, 0x93, 0xd7, 0xed, 0x86, 0xc9, 0xf4, 0x0f, 0x47, 0x5f, + 0x40, 0x57, 0x64, 0xa7, 0x4f, 0x20, 0x20, 0x53, 0x41, 0xb5, 0xba, 0x55, 0x4c, 0xf3, 0x76, 0x95, 0xdd, 0x5e, 0x28, + 0x31, 0x9c, 0xce, 0x4e, 0xc2, 0xa3, 0xcd, 0x90, 0x81, 0x43, 0x10, 0x28, 0x84, 0x8a, 0x62, 0x78, 0x04, 0x6a, 0x8d, + 0xe4, 0x03, 0xfc, 0x68, 0x77, 0x2a, 0x88, 0xd4, 0x6e, 0x2a, 0x6e, 0x9c, 0xdc, 0x74, 0xbd, 0x14, 0xa8, 0x75, 0x4a, + 0x56, 0x00, 0x25, 0x44, 0xfd, 0x49, 0x6c, 0xeb, 0x6b, 0xb8, 0x62, 0xf3, 0x7d, 0xa3, 0xe8, 0xc9, 0xf5, 0x29, 0xea, + 0x56, 0x5c, 0x9d, 0xa6, 0xad, 0xe6, 0xd8, 0x71, 0x86, 0x1c, 0x3c, 0x2b, 0x08, 0xb6, 0xa3, 0x12, 0xe5, 0x9b, 0x76, + 0xd3, 0x31, 0xb1, 0xd5, 0x3f, 0x8b, 0x6a, 0x73, 0x0b, 0x15, 0x11, 0xf1, 0x51, 0x76, 0xf3, 0xa4, 0xfd, 0x0e, 0xf6, + 0x58, 0xab, 0x41, 0x64, 0x9f, 0xc1, 0x55, 0xae, 0xd3, 0x22, 0xb7, 0x65, 0x70, 0xfe, 0xe1, 0xd5, 0xae, 0xc2, 0x26, + 0xc7, 0xba, 0xba, 0x9a, 0xa9, 0x4e, 0x2a, 0x36, 0x30, 0xd6, 0xb4, 0x96, 0x6a, 0x1e, 0x43, 0xd2, 0x5d, 0x59, 0x9c, + 0x55, 0x49, 0x37, 0x3d, 0x37, 0xce, 0x14, 0x62, 0xe0, 0x6c, 0x35, 0x5a, 0xce, 0x30, 0x44, 0xd7, 0x87, 0x59, 0xe2, + 0xb7, 0x7a, 0xca, 0x7d, 0x1e, 0x6e, 0xfd, 0xae, 0x5e, 0x70, 0x32, 0xd9, 0x4f, 0x8e, 0x73, 0xb7, 0x8b, 0xb4, 0x9f, + 0xf8, 0x36, 0xcc, 0xbf, 0xbe, 0x41, 0xdc, 0x8a, 0xfa, 0x97, 0x0a, 0x80, 0x06, 0x37, 0x79, 0x2c, 0x51, 0xea, 0xf7, + 0xaa, 0xfa, 0x41, 0xcd, 0x54, 0x4d, 0x03, 0xc1, 0x9c, 0x4a, 0x01, 0x7f, 0xb8, 0x5d, 0xb8, 0xe2, 0x11, 0x37, 0x2c, + 0x8c, 0x5f, 0xbc, 0x9a, 0x9d, 0x0a, 0x2a, 0x03, 0x37, 0xe3, 0x2f, 0x9e, 0x60, 0xa7, 0xb0, 0x56, 0x40, 0x56, 0xf8, + 0xe2, 0xe5, 0x0f, 0xbc, 0x5f, 0xf1, 0x2f, 0x5e, 0xf5, 0xc0, 0xfb, 0x88, 0xf3, 0xf2, 0x05, 0x49, 0x9d, 0x10, 0xd5, + 0xe5, 0x0b, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x05, 0x29, 0x7c, 0x82, 0xcf, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, + 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, + 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, + 0x37, 0x61, 0x1d, 0x25, 0x69, 0x7e, 0x2b, 0xa3, 0x8f, 0x64, 0xd8, 0x91, 0xbe, 0x92, 0x12, 0xed, 0xb5, 0x0a, 0xcb, + 0xd1, 0xec, 0xd7, 0x25, 0x07, 0xca, 0xeb, 0x56, 0x50, 0xbe, 0x6a, 0x02, 0xe8, 0x95, 0x6a, 0x9f, 0x81, 0x56, 0x50, + 0x58, 0x2a, 0x0f, 0x56, 0xe2, 0x5c, 0xf4, 0x59, 0x71, 0x38, 0xa8, 0x8b, 0x21, 0xa1, 0x40, 0x95, 0x38, 0x09, 0x8d, + 0x78, 0x0e, 0x17, 0x42, 0xf1, 0x34, 0xc7, 0xd8, 0x8a, 0x1c, 0x38, 0x90, 0xe1, 0x07, 0x04, 0xde, 0xcb, 0xfe, 0x15, + 0x0c, 0x86, 0x09, 0x6e, 0x64, 0xd4, 0xc9, 0x39, 0xfb, 0x82, 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, + 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, 0x9d, 0xf4, 0x4f, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, + 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, + 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, + 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, + 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, + 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, + 0x28, 0x07, 0xfb, 0x17, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, + 0x71, 0x50, 0xb1, 0xdb, 0x32, 0x8c, 0x80, 0x41, 0x1d, 0xfb, 0x1f, 0x7d, 0x36, 0x6d, 0xc8, 0x3e, 0x00, 0x54, 0xae, + 0x42, 0xc0, 0x1e, 0x80, 0x13, 0x8d, 0x70, 0x03, 0xdc, 0x6a, 0xb4, 0xa4, 0x83, 0xba, 0x2d, 0x18, 0x88, 0x96, 0xb0, + 0x91, 0xb7, 0x5d, 0x9d, 0xbe, 0x21, 0x7c, 0xa8, 0x9d, 0x94, 0x0e, 0xe5, 0x6f, 0x9e, 0xb3, 0xff, 0xd9, 0x61, 0x4d, + 0x4d, 0xf9, 0x08, 0x98, 0x39, 0x2b, 0x91, 0x57, 0x08, 0x9d, 0x22, 0xbf, 0x57, 0x75, 0x25, 0x86, 0xcb, 0x5a, 0x94, + 0x9d, 0xd9, 0xad, 0x13, 0xbd, 0x73, 0x0a, 0x6a, 0xa9, 0x6c, 0x90, 0x93, 0x54, 0x9b, 0x8f, 0xac, 0x15, 0x94, 0xa8, + 0x6b, 0x14, 0x38, 0x3e, 0xe5, 0xda, 0xfd, 0xbf, 0x73, 0x26, 0xa8, 0xd9, 0x46, 0x75, 0x7f, 0xa1, 0x9f, 0xaa, 0x9a, + 0xc4, 0x02, 0x5c, 0x4e, 0xd2, 0xbc, 0xe3, 0x11, 0x56, 0xff, 0x38, 0x59, 0x8a, 0x40, 0x9f, 0x22, 0xda, 0x95, 0x80, + 0x04, 0xed, 0xe4, 0x2c, 0x54, 0x04, 0x0a, 0xf4, 0xf5, 0xe7, 0x9b, 0x34, 0x8b, 0xe5, 0x6a, 0xb6, 0x87, 0x89, 0xb2, + 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x57, 0xa6, 0x04, 0x97, 0xe2, 0x2a, 0x2a, + 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0x4b, 0x54, 0x3b, 0x52, 0x20, 0x87, 0x92, + 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0xd7, 0x0a, 0xc1, 0xfd, 0xb5, 0x2d, 0x36, 0xaa, 0x3c, + 0xd1, 0x83, 0x4f, 0xb1, 0xfe, 0x27, 0x0b, 0x28, 0xd5, 0x7d, 0x1b, 0x9c, 0x8a, 0x47, 0xe1, 0xa6, 0x2e, 0x3e, 0x22, + 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, 0x9d, 0x3a, 0x0c, 0x1c, + 0x50, 0x13, 0x25, 0xa2, 0xd8, 0x2d, 0xe8, 0x9e, 0xe6, 0x58, 0x89, 0x67, 0xb2, 0x74, 0x90, 0x75, 0x22, 0x4d, 0xa8, + 0xdc, 0xd5, 0x55, 0x47, 0xa5, 0x52, 0x37, 0xbc, 0x4c, 0x35, 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x6c, 0xfd, + 0x56, 0xab, 0xbd, 0xb1, 0x7a, 0x54, 0xb2, 0xe6, 0x38, 0x9b, 0x90, 0x94, 0x3e, 0x61, 0xbb, 0x99, 0x74, 0xad, 0x03, + 0x4f, 0x82, 0xcb, 0xa1, 0x27, 0xa0, 0x62, 0xd0, 0xc4, 0xdb, 0x5d, 0xa0, 0x1e, 0x81, 0x67, 0xa0, 0x7c, 0xa2, 0xd6, + 0x01, 0x3f, 0xaf, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x38, 0xef, 0x14, 0x81, 0x6b, 0x57, 0x02, + 0xcf, 0x87, 0xea, 0xbd, 0x10, 0x30, 0xdc, 0x3f, 0x15, 0x2a, 0x9b, 0xdd, 0x0c, 0xe7, 0x51, 0xe3, 0xf4, 0x40, 0x7b, + 0xdb, 0xb5, 0x1e, 0xea, 0x5d, 0xb7, 0x73, 0x5b, 0xe9, 0xde, 0xaf, 0x9d, 0x4c, 0xba, 0x80, 0xd6, 0xe6, 0xb3, 0xef, + 0xec, 0x4a, 0xeb, 0xa6, 0xe7, 0xec, 0xc1, 0xd6, 0x2d, 0xd1, 0xb9, 0x20, 0x9a, 0xfc, 0x7e, 0xe0, 0x59, 0xdb, 0x8e, + 0x7e, 0x9b, 0x76, 0x6c, 0x73, 0x0f, 0x75, 0xaf, 0xa0, 0xd6, 0x1b, 0x9a, 0xf7, 0xcf, 0x5c, 0xdb, 0x8e, 0xaf, 0x7e, + 0x5d, 0x77, 0xb8, 0xce, 0x9b, 0xe0, 0xb8, 0xe9, 0xda, 0x56, 0x3b, 0xfb, 0xb9, 0xbb, 0xb7, 0x16, 0x51, 0x98, 0x65, + 0x3f, 0x17, 0xc5, 0x9f, 0x95, 0xbe, 0x23, 0xd0, 0xd1, 0x9d, 0x17, 0x75, 0xba, 0xdc, 0xbd, 0x27, 0x8c, 0x27, 0xaf, + 0x3e, 0x22, 0xba, 0xf5, 0x7d, 0xe6, 0x7e, 0x05, 0xb8, 0x11, 0xdc, 0x41, 0xb4, 0x77, 0x4b, 0x7d, 0x52, 0xab, 0xaf, + 0xf5, 0xda, 0x79, 0x7a, 0x7e, 0xd3, 0xb9, 0xfd, 0xee, 0x9b, 0xa3, 0xad, 0xf7, 0xb8, 0xb0, 0x56, 0x96, 0x9e, 0xaa, + 0x82, 0xbd, 0x59, 0x9e, 0xaa, 0x82, 0xc9, 0x03, 0xaf, 0xd9, 0x2f, 0x68, 0x70, 0xa5, 0xa3, 0x8d, 0xf7, 0x44, 0x0d, + 0xdc, 0xa2, 0xb0, 0x74, 0xf8, 0x25, 0x37, 0x93, 0x6b, 0xdc, 0x5f, 0x2a, 0x72, 0xb1, 0xef, 0x9c, 0xd1, 0x9d, 0x99, + 0x75, 0xaf, 0x2a, 0x5c, 0x2d, 0xc8, 0xd5, 0x81, 0xad, 0x65, 0x17, 0x87, 0x1b, 0x16, 0x51, 0x80, 0x40, 0x4c, 0xaf, + 0xd4, 0xda, 0x1f, 0xd1, 0x20, 0xe4, 0x83, 0x81, 0x5f, 0x60, 0xb0, 0x2a, 0x50, 0xf8, 0x40, 0x91, 0xfc, 0x85, 0x27, + 0x60, 0x17, 0xcf, 0x00, 0xdd, 0x8a, 0xcd, 0x8a, 0x11, 0x22, 0x64, 0xb2, 0x9c, 0xd5, 0x74, 0x06, 0xf9, 0xd4, 0x17, + 0xdf, 0xd9, 0xaa, 0xd3, 0x79, 0x5b, 0x53, 0xe5, 0xd4, 0xa1, 0xd0, 0xdd, 0x4d, 0xdd, 0xb9, 0x75, 0x91, 0xa7, 0x0e, + 0x21, 0x57, 0x2a, 0x56, 0x62, 0x1a, 0x6a, 0x9e, 0xa4, 0x19, 0xf5, 0x57, 0x7b, 0xbf, 0xd7, 0x28, 0x9c, 0xf2, 0xa7, + 0x63, 0x50, 0x85, 0xab, 0x1a, 0xe2, 0x58, 0xaa, 0xe2, 0x91, 0x0d, 0x02, 0xcd, 0xab, 0x5b, 0x95, 0x34, 0x21, 0x93, + 0x1b, 0xe1, 0x53, 0x93, 0x52, 0x9e, 0xa6, 0x4d, 0x5a, 0x29, 0x52, 0x07, 0x1f, 0xd4, 0xa9, 0xc6, 0x73, 0xb3, 0x7a, + 0x0a, 0x60, 0xc6, 0xf9, 0x15, 0xbf, 0x54, 0x5c, 0x46, 0x6d, 0x65, 0x26, 0xed, 0x4f, 0x8e, 0xc6, 0x46, 0x5d, 0x4e, + 0x95, 0x79, 0xc5, 0xa0, 0x4f, 0xbf, 0xd6, 0xe7, 0x1f, 0x30, 0x58, 0xf3, 0x04, 0x76, 0x30, 0x51, 0x29, 0xef, 0x23, + 0x20, 0xbe, 0x4e, 0xd2, 0xdb, 0x04, 0x52, 0xa4, 0x7f, 0xe9, 0x92, 0xa7, 0x0e, 0x63, 0x03, 0x31, 0x66, 0xc5, 0xcc, + 0xe8, 0x7f, 0x70, 0x97, 0xf4, 0x27, 0x21, 0x00, 0x6e, 0xa2, 0x29, 0x74, 0xea, 0x3c, 0xb9, 0xc8, 0x83, 0xe5, 0x85, + 0x87, 0x56, 0x8c, 0x78, 0xf0, 0xd7, 0xa7, 0x21, 0x82, 0x98, 0x63, 0x8a, 0xa7, 0x5f, 0x18, 0xfd, 0x25, 0xb8, 0xc4, + 0x08, 0x42, 0x77, 0xef, 0x1c, 0x86, 0x70, 0xb3, 0x07, 0x19, 0xd4, 0x1f, 0xea, 0x90, 0xa8, 0xe1, 0x2f, 0x95, 0x07, + 0xfd, 0x5f, 0x67, 0xc2, 0x52, 0xfb, 0xe9, 0xe9, 0x00, 0x2a, 0x78, 0x5f, 0xf1, 0x36, 0x22, 0xbe, 0x4f, 0xfc, 0x38, + 0x1e, 0x6c, 0x1e, 0x6f, 0xc0, 0x5a, 0xf7, 0x2c, 0x37, 0xd6, 0x55, 0xc2, 0x06, 0x02, 0xbe, 0xc6, 0xb4, 0xf6, 0xbc, + 0x76, 0xbb, 0x07, 0x7f, 0xf5, 0x2f, 0x42, 0x06, 0x4c, 0x9c, 0xbe, 0xcf, 0x9c, 0xac, 0xd1, 0x45, 0x26, 0xd3, 0x87, + 0x4e, 0xfa, 0x46, 0xa7, 0xfb, 0x4e, 0xf8, 0x47, 0xc5, 0x2c, 0x3e, 0xdc, 0xd2, 0x57, 0x9a, 0x14, 0x77, 0xc0, 0xca, + 0xe6, 0x41, 0x41, 0xa8, 0x73, 0x11, 0x7d, 0x63, 0xca, 0xb7, 0x84, 0x9a, 0x7d, 0x63, 0x49, 0x29, 0xdd, 0x6b, 0xe8, + 0x65, 0x5a, 0xeb, 0xb7, 0x51, 0x82, 0x31, 0xd1, 0xf1, 0xe4, 0x65, 0x3c, 0x56, 0xde, 0xc7, 0xe3, 0x46, 0x2a, 0xe4, + 0x01, 0x88, 0x40, 0xc5, 0xf8, 0xd3, 0x95, 0x27, 0x27, 0xbd, 0x30, 0x5e, 0x85, 0x52, 0x50, 0x18, 0xd0, 0x15, 0x48, + 0x01, 0x8f, 0xda, 0x13, 0x9d, 0x85, 0x5d, 0xc2, 0x3d, 0xba, 0x09, 0x18, 0xeb, 0xf3, 0x2f, 0x80, 0xe6, 0x2e, 0xdc, + 0xe1, 0xc5, 0x00, 0xb5, 0xa9, 0x57, 0x77, 0x1f, 0xd7, 0xea, 0x1c, 0x0e, 0xc1, 0xc1, 0x6a, 0x10, 0xc1, 0xe9, 0x7c, + 0xea, 0x68, 0x96, 0x05, 0xa8, 0x9c, 0x2c, 0x37, 0xf2, 0xe6, 0xd1, 0xa2, 0x57, 0xf7, 0xbd, 0x65, 0x5a, 0x56, 0x75, + 0x90, 0xb1, 0x2c, 0xac, 0x00, 0x57, 0x87, 0xd6, 0x0f, 0xc2, 0x65, 0xe1, 0xfc, 0x81, 0x10, 0xc4, 0xee, 0xd5, 0xb6, + 0xe4, 0xb9, 0x9a, 0xc3, 0x8f, 0x9f, 0xb0, 0x35, 0x97, 0xa8, 0x93, 0xce, 0x44, 0x00, 0x62, 0x4f, 0xcd, 0x2a, 0xba, + 0x06, 0x92, 0x3a, 0xcd, 0x2a, 0xba, 0xa6, 0x66, 0x1b, 0xe3, 0x40, 0x3e, 0x5a, 0xa5, 0x80, 0x7d, 0x37, 0x1d, 0x07, + 0xab, 0xc7, 0xb1, 0xbc, 0x0e, 0xdd, 0x3e, 0xde, 0x28, 0x9f, 0x41, 0xdd, 0x6a, 0x63, 0x4c, 0x6c, 0x37, 0x5f, 0xce, + 0xf5, 0x9b, 0xc1, 0xd2, 0xb7, 0x83, 0xe6, 0x9c, 0xb2, 0x6f, 0x75, 0xd9, 0x2b, 0xbb, 0x6c, 0xea, 0xb9, 0xa3, 0xa2, + 0xd5, 0x18, 0xd0, 0x1b, 0x58, 0xb0, 0x3e, 0x17, 0x69, 0xb6, 0x2a, 0x55, 0x09, 0x78, 0x61, 0xac, 0xd8, 0xad, 0xdf, + 0xc8, 0x0c, 0x49, 0x98, 0xc7, 0x99, 0x78, 0x43, 0xf7, 0x5a, 0x98, 0x1c, 0xc7, 0x22, 0x99, 0x12, 0x3a, 0xa5, 0x3b, + 0xdb, 0xd0, 0xb9, 0x0a, 0xa3, 0x88, 0xd6, 0x4a, 0x2a, 0x8d, 0x04, 0xa6, 0x66, 0x80, 0x92, 0xb9, 0x02, 0xa7, 0x74, + 0xb9, 0xff, 0x1d, 0x89, 0x71, 0xe6, 0x8b, 0x92, 0x19, 0xd0, 0x2d, 0xbf, 0x2e, 0xd6, 0xad, 0x14, 0x19, 0x61, 0xde, + 0x1c, 0xb7, 0xd7, 0xf5, 0x21, 0x90, 0xab, 0x65, 0x8f, 0xa2, 0x71, 0x50, 0xe8, 0x70, 0xa9, 0x12, 0x60, 0x5f, 0x24, + 0x7e, 0x46, 0xd8, 0xd2, 0x1e, 0xc8, 0xed, 0xd1, 0x99, 0x30, 0xe7, 0x9c, 0x94, 0x65, 0xe7, 0xd2, 0x0c, 0x2e, 0x27, + 0xae, 0x04, 0x17, 0xe9, 0x6d, 0x7b, 0x9a, 0xb4, 0xb4, 0x7d, 0x6c, 0x38, 0x47, 0x43, 0xdb, 0xa0, 0x3b, 0xf6, 0x87, + 0xe6, 0x62, 0x11, 0x5b, 0x17, 0x8b, 0x61, 0x67, 0xf6, 0xa3, 0xc5, 0x02, 0xe4, 0x00, 0x70, 0xd4, 0x6d, 0xf8, 0x98, + 0x2d, 0x81, 0xd3, 0x6a, 0x9a, 0x4d, 0xbd, 0x0d, 0xaf, 0x1e, 0xab, 0x9e, 0x5e, 0xf2, 0xfc, 0xb1, 0x30, 0x63, 0xb1, + 0xe1, 0xf9, 0x63, 0xeb, 0xc8, 0xa9, 0x1e, 0x0b, 0x25, 0x5a, 0x17, 0xd0, 0x0c, 0xbc, 0xa6, 0x80, 0x11, 0x4b, 0x26, + 0x53, 0xaa, 0xc8, 0xe3, 0xde, 0x74, 0xa3, 0x06, 0x2f, 0x28, 0x1c, 0x02, 0x29, 0x9d, 0x7e, 0xf1, 0x84, 0xe9, 0xf7, + 0x2e, 0x9e, 0x74, 0xc8, 0xda, 0x86, 0xe9, 0x72, 0x33, 0x4c, 0x06, 0xa5, 0xff, 0xd8, 0x4c, 0x8c, 0x0b, 0x6b, 0x92, + 0x00, 0xe2, 0xdf, 0xd8, 0xef, 0x90, 0xc2, 0xcd, 0xfb, 0xcb, 0x61, 0xfc, 0xc0, 0xfb, 0x31, 0xb2, 0x27, 0x69, 0x86, + 0x58, 0x33, 0xa9, 0x90, 0xbb, 0xaf, 0xd6, 0x3f, 0x26, 0x76, 0x93, 0x3d, 0xb0, 0x00, 0xc4, 0xd6, 0xb4, 0xd5, 0x2d, + 0xef, 0xf7, 0x3d, 0x53, 0x04, 0xf8, 0x41, 0xf9, 0x47, 0x77, 0x86, 0x64, 0x50, 0x76, 0xdd, 0x10, 0xe2, 0x41, 0xd9, + 0x34, 0xed, 0xf5, 0xb6, 0x77, 0xe6, 0xb1, 0xba, 0x4e, 0x3b, 0x8b, 0xab, 0x45, 0x06, 0x69, 0xf5, 0x21, 0x3b, 0xce, + 0xec, 0xb3, 0xa3, 0xa5, 0xd2, 0xfd, 0x3e, 0x44, 0xc4, 0x1d, 0x65, 0x6d, 0xbf, 0xdd, 0x82, 0x6b, 0x38, 0x1a, 0x84, + 0xae, 0xec, 0xed, 0x32, 0xda, 0xb8, 0x10, 0xc7, 0x3d, 0xd3, 0xf9, 0x82, 0x2f, 0x8f, 0xd2, 0xce, 0x83, 0x53, 0x3d, + 0xd1, 0xe7, 0xa6, 0xbb, 0xca, 0xe4, 0x5a, 0x87, 0xd5, 0x18, 0xd4, 0x66, 0x61, 0x0b, 0x77, 0x61, 0x1b, 0x1d, 0xb4, + 0xf6, 0x65, 0xc1, 0x3f, 0x65, 0x00, 0xbe, 0xf4, 0x6c, 0xd9, 0xf6, 0x9a, 0xb4, 0x7a, 0x29, 0xa3, 0x10, 0x5b, 0xda, + 0x5e, 0x7d, 0x3a, 0xca, 0xc7, 0xcd, 0x09, 0xc5, 0x85, 0x1c, 0xe5, 0x07, 0xaf, 0x21, 0xea, 0x5a, 0xd7, 0x71, 0xb1, + 0xe8, 0x70, 0xe3, 0xaa, 0xdb, 0x6e, 0x5c, 0xaf, 0x10, 0x6f, 0x8d, 0x36, 0x29, 0xd4, 0xca, 0xd8, 0x11, 0xbc, 0x2c, + 0x1f, 0x0e, 0x99, 0x18, 0x0e, 0x25, 0x64, 0xea, 0x43, 0xf7, 0x86, 0xa6, 0x7d, 0x7e, 0xda, 0xfa, 0x11, 0x4b, 0x8d, + 0xa3, 0xd8, 0xf0, 0x4e, 0xdf, 0x79, 0x6c, 0x8d, 0x2b, 0xf9, 0x32, 0x98, 0xed, 0x0a, 0xaa, 0xad, 0xf1, 0x86, 0xbd, + 0x9c, 0xff, 0x5c, 0x49, 0x25, 0x7f, 0xfb, 0x33, 0x5c, 0xc3, 0x5b, 0x5b, 0x3a, 0x68, 0xaa, 0x59, 0xce, 0x72, 0x7d, + 0x2f, 0x38, 0xfe, 0xb8, 0x7b, 0x45, 0x30, 0xf8, 0x3d, 0x1d, 0x05, 0xb9, 0x58, 0xaa, 0x35, 0xa0, 0x20, 0x1d, 0xd9, + 0x31, 0x95, 0x05, 0x86, 0x01, 0xbc, 0x21, 0x03, 0xe4, 0x31, 0x85, 0xbb, 0xa1, 0xc2, 0x0b, 0x7f, 0xad, 0xc8, 0x2e, + 0x81, 0x6d, 0xcd, 0xf8, 0x98, 0xe1, 0x0e, 0x42, 0xfe, 0x11, 0xec, 0x96, 0xad, 0xd8, 0x0d, 0x5b, 0x30, 0x24, 0x1b, + 0xc7, 0x61, 0x8c, 0xf9, 0x78, 0x12, 0x5f, 0x89, 0x49, 0x3c, 0xe0, 0x11, 0x3a, 0x46, 0xac, 0x79, 0x3d, 0x8b, 0xe5, + 0x00, 0xb2, 0x5b, 0xae, 0x74, 0x40, 0x08, 0x8d, 0x0d, 0x2d, 0x79, 0x59, 0x18, 0x5c, 0xec, 0xd8, 0x67, 0x24, 0x92, + 0x71, 0x08, 0x16, 0xad, 0x6a, 0x60, 0x61, 0x62, 0x37, 0xbc, 0x98, 0xad, 0xe6, 0xf8, 0xcf, 0xe1, 0x80, 0x00, 0xd8, + 0xc1, 0xbe, 0x61, 0xb7, 0x11, 0x22, 0xbd, 0x2d, 0xf8, 0xad, 0xe5, 0xe9, 0xc2, 0xee, 0xf8, 0x35, 0x1f, 0xb3, 0xf3, + 0x57, 0x1e, 0x44, 0xce, 0x9e, 0x7f, 0x00, 0x34, 0xc4, 0x3b, 0x7e, 0x93, 0x7a, 0x15, 0xbb, 0x21, 0x0a, 0xc2, 0x1b, + 0x70, 0x06, 0xba, 0x83, 0x08, 0xd8, 0x6b, 0xbe, 0xc0, 0x58, 0xb1, 0xb3, 0x74, 0xe9, 0x61, 0x46, 0xa8, 0x3d, 0x9d, + 0x2f, 0x6b, 0x35, 0x09, 0x37, 0x57, 0xcb, 0xc9, 0x60, 0xb0, 0xf1, 0x77, 0x7c, 0x0d, 0x7c, 0x30, 0xe7, 0xaf, 0xbc, + 0x1d, 0x95, 0x0b, 0xff, 0x79, 0x9d, 0x25, 0xef, 0x7c, 0x76, 0x3d, 0xe0, 0x0b, 0xc0, 0x5b, 0x42, 0x07, 0xae, 0x3b, + 0x9f, 0x49, 0xbc, 0xb6, 0x6b, 0x7d, 0x8d, 0x40, 0x22, 0x5f, 0x00, 0x46, 0x4c, 0xcc, 0xef, 0x6b, 0x88, 0xc0, 0xd8, + 0x80, 0x6f, 0xab, 0xf6, 0x88, 0xdf, 0x72, 0x03, 0xf8, 0x95, 0xf9, 0xec, 0x9e, 0x87, 0xfa, 0x67, 0xe2, 0xb3, 0x37, + 0xfc, 0x11, 0x7f, 0xea, 0x49, 0x49, 0xba, 0x9c, 0x3d, 0x9a, 0xc3, 0xf5, 0x50, 0xca, 0xd3, 0x21, 0xfd, 0x6c, 0x0c, + 0x06, 0x10, 0x0a, 0x99, 0x6f, 0x3c, 0x60, 0x4d, 0x0a, 0xf1, 0x2f, 0xe0, 0xdb, 0x51, 0xc2, 0xe6, 0x1b, 0x6f, 0xeb, + 0x6b, 0x79, 0xf3, 0x8d, 0x77, 0xef, 0x53, 0x14, 0x60, 0x15, 0x94, 0xb2, 0xc0, 0x2a, 0x08, 0x1b, 0x6d, 0x84, 0x31, + 0x70, 0xf5, 0xae, 0x31, 0xd4, 0xf5, 0x1c, 0xb1, 0x6d, 0xa5, 0x6f, 0xc3, 0xb7, 0x90, 0x01, 0x1f, 0xbc, 0x2c, 0x4a, + 0xa2, 0xcf, 0xa9, 0x29, 0x92, 0xd6, 0x3d, 0xf7, 0x5b, 0xeb, 0x8e, 0xd6, 0x94, 0xfa, 0xc8, 0xd5, 0xf8, 0x70, 0xa8, + 0x9f, 0x0a, 0x2d, 0x12, 0x4c, 0x41, 0xe3, 0x1a, 0xb4, 0x05, 0x08, 0xfa, 0x3c, 0x40, 0xd6, 0x92, 0x62, 0xc1, 0xb7, + 0xbf, 0x42, 0x0c, 0x5e, 0x99, 0xde, 0xb9, 0x5c, 0x65, 0x24, 0x6c, 0x2f, 0xfc, 0x72, 0x58, 0xfb, 0x13, 0xa7, 0x16, + 0x96, 0x56, 0x73, 0x50, 0x3f, 0xb6, 0xe5, 0x38, 0x5d, 0xb5, 0xc8, 0xeb, 0x50, 0x5a, 0x4e, 0xef, 0xec, 0x9b, 0x2e, + 0x13, 0x6c, 0xec, 0x07, 0x54, 0x1d, 0x59, 0x0d, 0xbb, 0x2f, 0xd4, 0x17, 0x3d, 0x25, 0x13, 0x9a, 0x8f, 0x2a, 0x9a, + 0xe7, 0xd6, 0x37, 0x8f, 0xeb, 0x3f, 0xbd, 0x1c, 0x8a, 0x00, 0xc9, 0x2a, 0x2d, 0x96, 0x22, 0x67, 0x63, 0x3f, 0x1e, + 0x26, 0x99, 0x0a, 0x2f, 0x48, 0x47, 0x77, 0xbf, 0x71, 0x7f, 0xcb, 0x0d, 0x64, 0x85, 0x56, 0x6d, 0x30, 0x56, 0x8a, + 0x96, 0xc1, 0xfa, 0x6a, 0xdc, 0xef, 0x8b, 0xab, 0xf1, 0x54, 0x04, 0x35, 0x10, 0x17, 0x89, 0xa7, 0xe3, 0x69, 0x4d, + 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x14, 0x42, 0x91, 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, + 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, 0x75, 0x72, 0xec, 0x5c, 0xc0, + 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x65, 0x62, 0x6b, 0x23, 0xdc, 0x52, 0x40, 0x19, 0xe5, + 0x37, 0x96, 0x13, 0x76, 0xa7, 0x7a, 0x47, 0xaa, 0x76, 0xc4, 0x89, 0x0b, 0x58, 0x6e, 0x78, 0x6a, 0xf5, 0x4d, 0x0c, + 0x4e, 0x84, 0xaa, 0x95, 0x0e, 0x77, 0x32, 0x81, 0xb8, 0x5f, 0xdd, 0xd7, 0xbd, 0x12, 0xfc, 0x24, 0xe4, 0xf5, 0x5b, + 0xde, 0x01, 0x60, 0xc5, 0x87, 0xbc, 0x98, 0x16, 0x8e, 0xd6, 0x65, 0x50, 0x06, 0x88, 0xd0, 0x0c, 0x80, 0x4e, 0xae, + 0x0e, 0xa2, 0x34, 0x70, 0xc5, 0x1d, 0x22, 0xfc, 0x34, 0x7a, 0x9c, 0x3f, 0x0d, 0x1f, 0x57, 0xd3, 0xf0, 0x22, 0x0f, + 0xa2, 0x8b, 0x2a, 0x88, 0x1e, 0x57, 0x57, 0xe1, 0xe3, 0x7c, 0x1a, 0x5d, 0xe4, 0x41, 0x78, 0x51, 0x35, 0xf6, 0x5d, + 0xbb, 0xbb, 0x27, 0xe4, 0x6d, 0x57, 0x7f, 0xe4, 0x5c, 0xd9, 0x53, 0xa6, 0xe7, 0xe7, 0xb5, 0x5e, 0xa9, 0xdd, 0xe6, + 0x7a, 0x8d, 0x9a, 0xa9, 0x8f, 0xb2, 0xbf, 0xd9, 0xc6, 0xc2, 0xa3, 0x39, 0x84, 0x3e, 0x23, 0x2d, 0xe6, 0x1e, 0xe7, + 0x7a, 0xb3, 0x27, 0x85, 0x81, 0x11, 0x93, 0x4a, 0x46, 0x4e, 0x2f, 0x70, 0x11, 0xaa, 0x10, 0xc3, 0x5a, 0xba, 0xda, + 0x67, 0x5d, 0x7a, 0x03, 0x75, 0x4d, 0xb1, 0xaf, 0x21, 0x03, 0x2f, 0x9a, 0x5e, 0x06, 0x63, 0x40, 0x8e, 0xc0, 0x3b, + 0x3e, 0x5b, 0xc2, 0x81, 0xb9, 0x06, 0xe8, 0x9b, 0x07, 0x7d, 0x5d, 0x6e, 0xf9, 0x5a, 0xf5, 0xcd, 0x74, 0x3d, 0x52, + 0xca, 0x8f, 0x15, 0xbf, 0xbd, 0x78, 0xc2, 0x6e, 0xb8, 0x46, 0x45, 0x79, 0xae, 0x17, 0xeb, 0x1d, 0x70, 0xd5, 0x3d, + 0x87, 0xdb, 0x2c, 0x1e, 0xbb, 0xf2, 0x80, 0x65, 0x5b, 0x76, 0xcf, 0xde, 0xb0, 0x47, 0xec, 0x3d, 0xfb, 0xc4, 0xbe, + 0xb2, 0x1a, 0x21, 0xca, 0x4b, 0x25, 0xe5, 0xf9, 0x0b, 0x7e, 0x23, 0x6d, 0x8f, 0x12, 0x96, 0xec, 0xde, 0xb6, 0xd3, + 0x0c, 0x37, 0xec, 0x11, 0x5f, 0x0c, 0x57, 0xec, 0x13, 0x64, 0x43, 0xa1, 0x78, 0xb0, 0x62, 0x35, 0x5c, 0x61, 0x29, + 0x83, 0x3e, 0x0d, 0x4b, 0x4b, 0x58, 0x34, 0x85, 0xa2, 0x14, 0xfd, 0x89, 0xd7, 0x84, 0x9d, 0x56, 0x63, 0x21, 0xf2, + 0x43, 0xc3, 0x15, 0xbb, 0xe7, 0x8b, 0xc1, 0x8a, 0x3d, 0xd2, 0x36, 0xa2, 0xc1, 0xc6, 0x2d, 0x8e, 0xc0, 0xac, 0x74, + 0x61, 0x52, 0xa0, 0xde, 0xda, 0x37, 0xc1, 0x0d, 0x7b, 0x83, 0xf5, 0x7b, 0x8f, 0x45, 0xa3, 0xcc, 0x3f, 0x58, 0xb1, + 0xaf, 0x5c, 0x62, 0xa8, 0xb9, 0xe5, 0x49, 0xc7, 0x50, 0x5d, 0x20, 0x5d, 0x11, 0xde, 0x73, 0x7a, 0x91, 0x7d, 0xc5, + 0x32, 0xe8, 0x2b, 0xc3, 0x15, 0xdb, 0x62, 0xed, 0xde, 0x18, 0xe3, 0x96, 0x55, 0x3d, 0x09, 0x0a, 0x8c, 0xb2, 0x4a, + 0x69, 0xb9, 0x38, 0x62, 0xd9, 0xd4, 0x51, 0x83, 0xda, 0x30, 0xa0, 0x0f, 0x46, 0x7f, 0xf1, 0xf5, 0xbb, 0xef, 0xbc, + 0x52, 0xdf, 0x7c, 0x9f, 0x3b, 0xde, 0x95, 0x25, 0x7a, 0x57, 0xfe, 0xc6, 0xcb, 0xd9, 0xf3, 0xf9, 0x44, 0xd7, 0x92, + 0x36, 0x19, 0x72, 0x37, 0x9d, 0x3d, 0xef, 0xf0, 0xb7, 0xfc, 0xcd, 0xf7, 0x1b, 0xab, 0x8f, 0xd5, 0x77, 0x75, 0xf7, + 0xde, 0x0f, 0x36, 0x8d, 0x53, 0xf1, 0xdd, 0xe9, 0x8a, 0x63, 0x3b, 0x6b, 0xed, 0x9d, 0xf9, 0x3f, 0x5c, 0xeb, 0x2d, + 0x8e, 0xdd, 0x1b, 0xbe, 0x1d, 0x6e, 0xec, 0x61, 0x90, 0xdf, 0x97, 0x8a, 0xe3, 0xac, 0xe6, 0xcf, 0xbc, 0x4e, 0x49, + 0x16, 0x50, 0x8d, 0x5e, 0x1b, 0x69, 0xe8, 0x92, 0x99, 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, + 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, 0xb5, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, + 0xd8, 0x4b, 0xf2, 0xb9, 0xcf, 0xde, 0x0a, 0x77, 0x95, 0x3e, 0xf7, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, + 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, 0x16, 0xfc, 0x2d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0x3f, + 0xd7, 0xea, 0xe7, 0x3b, 0x19, 0x9b, 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0x9b, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, + 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0xd7, 0x3c, 0x96, 0x16, 0xe6, 0x3b, 0x08, + 0x07, 0xbe, 0xb6, 0x61, 0x0a, 0x76, 0x1c, 0x37, 0x83, 0x6b, 0x06, 0x10, 0x92, 0xd9, 0x74, 0xcb, 0xdf, 0xf0, 0xf7, + 0xfc, 0x2b, 0xdf, 0x05, 0xf7, 0xfc, 0x11, 0xff, 0xc4, 0xeb, 0x9a, 0xef, 0xd8, 0x52, 0x42, 0x9e, 0xd6, 0xdb, 0xcb, + 0x60, 0xcb, 0xea, 0xdd, 0x65, 0x70, 0xcf, 0xea, 0xed, 0x93, 0xe0, 0x0d, 0xab, 0x77, 0x4f, 0x82, 0x47, 0x6c, 0x7b, + 0x19, 0xbc, 0x67, 0xbb, 0xcb, 0xe0, 0x13, 0xdb, 0x3e, 0x09, 0xbe, 0xb2, 0xdd, 0x93, 0xa0, 0x56, 0x48, 0x0f, 0x5f, + 0x85, 0x64, 0x3a, 0xf9, 0x5a, 0x33, 0xc3, 0xaa, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, 0x65, 0xf0, 0xb9, 0x66, 0xba, + 0xcd, 0x81, 0x10, 0x4c, 0xb7, 0x38, 0xb8, 0xa1, 0x27, 0xa6, 0x5d, 0x41, 0x2a, 0x58, 0x57, 0x4b, 0x83, 0x45, 0xdd, + 0xb4, 0x4e, 0x66, 0xc7, 0x3b, 0x31, 0xee, 0xf0, 0x4e, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, 0xaa, 0x73, 0xfa, 0x3c, 0xd0, + 0x47, 0x80, 0xde, 0xfb, 0x2b, 0xe9, 0x41, 0x53, 0x34, 0x3c, 0x57, 0xba, 0xe3, 0xd6, 0x7e, 0x1f, 0x5a, 0xfb, 0x3d, + 0x93, 0x8a, 0xb4, 0x88, 0x45, 0x65, 0x51, 0x55, 0xc8, 0x27, 0x1e, 0x64, 0x5a, 0xab, 0x96, 0x30, 0x52, 0x67, 0x02, + 0x26, 0x7d, 0x41, 0x87, 0x41, 0x4e, 0x76, 0x05, 0xb6, 0xe4, 0x9b, 0x41, 0xc2, 0xd6, 0x3c, 0x9e, 0x0e, 0x93, 0x60, + 0xc9, 0x6e, 0xf9, 0xb0, 0x5b, 0x2c, 0x58, 0xa9, 0x30, 0x26, 0x7d, 0x7d, 0x3a, 0xda, 0xdd, 0x79, 0x6f, 0x95, 0xc6, + 0x71, 0x26, 0x50, 0xe7, 0x56, 0xe9, 0x6d, 0x7e, 0xeb, 0xec, 0xea, 0x6b, 0xb5, 0xcb, 0x83, 0xc0, 0xf0, 0x1b, 0x10, + 0xed, 0x10, 0xef, 0x1d, 0xd4, 0x18, 0xe9, 0x96, 0xcc, 0xba, 0xaf, 0xec, 0x7d, 0x7d, 0x6b, 0xb6, 0xea, 0xff, 0xb4, + 0x08, 0xda, 0xcb, 0x65, 0xef, 0xbf, 0x36, 0xaf, 0xfe, 0xde, 0xf1, 0xea, 0xc6, 0x9f, 0xdc, 0xf3, 0xd7, 0x18, 0x9d, + 0x80, 0x89, 0x6c, 0xc7, 0x5f, 0x8f, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xcb, 0xff, 0xaf, 0x14, 0x68, 0xef, 0xe6, 0x95, + 0xbd, 0x29, 0x6e, 0x79, 0xc7, 0x5e, 0xbe, 0xb4, 0xf6, 0x44, 0x83, 0x50, 0xf2, 0x9a, 0xbb, 0x41, 0xd1, 0xb0, 0x27, + 0x3e, 0xe7, 0xd5, 0xec, 0xf5, 0x7c, 0xb2, 0xe5, 0xc7, 0x3b, 0xe2, 0xeb, 0x8e, 0x1d, 0xf1, 0xb9, 0x3f, 0x58, 0x36, + 0xdf, 0xea, 0xd5, 0xce, 0x9d, 0xdc, 0xa9, 0xf4, 0x8e, 0x1f, 0xef, 0xe3, 0xc3, 0xff, 0xb8, 0xd2, 0xbb, 0xef, 0xae, + 0xb4, 0x5d, 0xe5, 0xee, 0xce, 0x37, 0x1d, 0xdf, 0xc8, 0x5a, 0x63, 0xb8, 0x99, 0x51, 0x30, 0xc2, 0xb4, 0x85, 0x69, + 0x1a, 0x44, 0x96, 0x62, 0x11, 0x12, 0x35, 0x4a, 0xe7, 0x44, 0x9f, 0x05, 0x9d, 0x82, 0x2e, 0x6e, 0xf4, 0x37, 0x7c, + 0xcc, 0x16, 0xc6, 0x65, 0xf3, 0xe6, 0x6a, 0x31, 0x19, 0x0c, 0x6e, 0xfc, 0xfd, 0x1d, 0x0f, 0x67, 0x37, 0x73, 0x76, + 0xcd, 0xef, 0x68, 0x3d, 0x4d, 0x54, 0xe3, 0x8b, 0x87, 0x24, 0xb0, 0x1b, 0xdf, 0x9f, 0x58, 0x44, 0xb0, 0xf6, 0x8d, + 0xf3, 0xc6, 0x1f, 0x48, 0xb3, 0xb4, 0xdc, 0xda, 0x1f, 0x3d, 0xac, 0xa1, 0xb8, 0x01, 0x21, 0xe3, 0x91, 0xad, 0x72, + 0xf8, 0xc4, 0x3f, 0x78, 0xd7, 0xfe, 0xf4, 0x5a, 0x07, 0xdf, 0x4c, 0xd4, 0xb9, 0xf4, 0xe9, 0xe2, 0x09, 0xfb, 0x8d, + 0xbf, 0x96, 0x67, 0xca, 0x5b, 0x21, 0xa7, 0xed, 0x47, 0x24, 0x71, 0xa2, 0xa3, 0xe2, 0xab, 0x9b, 0x48, 0xa0, 0x10, + 0xb0, 0x2b, 0x7c, 0xad, 0xf9, 0xfd, 0xa4, 0x9c, 0x7a, 0x3b, 0x20, 0x79, 0xe5, 0xb6, 0x22, 0xfa, 0x86, 0x73, 0xbe, + 0x18, 0x5e, 0x4e, 0xbf, 0x76, 0xfb, 0xf6, 0xa8, 0xb0, 0x36, 0x15, 0xf1, 0x76, 0x83, 0x41, 0x58, 0x27, 0x33, 0xcb, + 0x5c, 0xf2, 0xa5, 0xaf, 0xb5, 0x99, 0x7b, 0x4c, 0xef, 0x38, 0xd3, 0x0c, 0x19, 0x7d, 0x81, 0x99, 0xe9, 0x70, 0xb8, + 0x3d, 0xc7, 0xf2, 0xf8, 0xf0, 0xd3, 0xe3, 0xf7, 0x83, 0xf7, 0x18, 0xc2, 0x65, 0x85, 0x85, 0x7c, 0xe5, 0xc3, 0xac, + 0x6e, 0x5d, 0x3b, 0x2e, 0x9e, 0x0c, 0x9f, 0x43, 0xde, 0xa0, 0xeb, 0xa1, 0x29, 0xa2, 0x55, 0x7e, 0x47, 0xd1, 0x27, + 0x4a, 0x0e, 0x3a, 0x9e, 0x40, 0xed, 0x90, 0x0b, 0xf7, 0xeb, 0x63, 0x0e, 0x8a, 0x0e, 0x2c, 0xb5, 0xdf, 0x3f, 0x7f, + 0x4d, 0x84, 0xd2, 0x30, 0xde, 0xcf, 0xc3, 0xe8, 0xcf, 0xb8, 0x2c, 0xd6, 0x70, 0xc4, 0x0e, 0xe0, 0x73, 0x8f, 0xf5, + 0x35, 0xec, 0xd6, 0xf7, 0xfd, 0xc0, 0xdb, 0xf2, 0x37, 0xec, 0x2b, 0xf7, 0x2e, 0x87, 0x9f, 0xfc, 0xc7, 0xef, 0x41, + 0x7e, 0x42, 0x9c, 0x14, 0x0c, 0x89, 0xed, 0x28, 0x46, 0xad, 0xc3, 0xcf, 0x35, 0xc4, 0x6a, 0xbd, 0x46, 0xea, 0x2e, + 0x48, 0x7f, 0xaf, 0x90, 0xfd, 0x84, 0xc0, 0x6a, 0x92, 0x3e, 0x05, 0x26, 0xf1, 0x4d, 0x0d, 0x09, 0xa4, 0x69, 0x81, + 0x18, 0x1c, 0x28, 0x3e, 0x15, 0xfc, 0xeb, 0xf0, 0x33, 0xc9, 0x7f, 0x8b, 0x9a, 0x8f, 0xe1, 0x6f, 0x18, 0x9a, 0x49, + 0x75, 0x9f, 0xd6, 0x10, 0x11, 0x0d, 0xa7, 0x5e, 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, + 0x4c, 0x6e, 0x4a, 0x11, 0xfe, 0x39, 0xc1, 0x67, 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, + 0x65, 0xaf, 0x06, 0x8b, 0x7a, 0xc8, 0x6f, 0x6a, 0xf7, 0x7d, 0x39, 0x27, 0xe8, 0x91, 0xfd, 0x80, 0xe6, 0x60, 0xa0, + 0x66, 0x20, 0x65, 0x08, 0x6e, 0xe0, 0xd2, 0xef, 0xa9, 0x82, 0x7c, 0xf9, 0xbd, 0xcf, 0x42, 0x06, 0xae, 0x2c, 0x08, + 0x53, 0x2e, 0x15, 0x52, 0xe0, 0xb8, 0xa9, 0x07, 0x9f, 0x35, 0x3a, 0x89, 0x04, 0x9f, 0x12, 0x90, 0x24, 0x2d, 0x0f, + 0x24, 0x8d, 0x98, 0x0e, 0xc4, 0x85, 0xd2, 0x34, 0x2b, 0x29, 0xe2, 0x10, 0xbb, 0xea, 0x35, 0x12, 0x9e, 0x05, 0x8f, + 0x18, 0xac, 0x1d, 0x29, 0x5a, 0x7c, 0x35, 0xa6, 0x63, 0x1d, 0x36, 0x74, 0x2b, 0x8b, 0xfb, 0x4d, 0x52, 0xa7, 0x91, + 0xb8, 0xf2, 0x56, 0xc8, 0x9f, 0xff, 0x52, 0x22, 0x90, 0xde, 0xd5, 0x40, 0x0c, 0x82, 0x1f, 0xa0, 0xff, 0x80, 0x45, + 0x0e, 0x82, 0x52, 0x5d, 0x86, 0x79, 0x95, 0x51, 0x81, 0xb3, 0x1d, 0xdb, 0xce, 0x99, 0xaa, 0x5b, 0xf0, 0x59, 0x18, + 0x86, 0xb4, 0xb3, 0x55, 0x73, 0x72, 0xab, 0x37, 0x50, 0xcf, 0x24, 0x8e, 0xd4, 0x52, 0x1c, 0x69, 0x6b, 0xee, 0xd3, + 0xa5, 0xd7, 0x2d, 0x2f, 0x68, 0xb8, 0x00, 0xbd, 0x28, 0xdd, 0x75, 0x3e, 0xa1, 0xd0, 0x65, 0x35, 0xae, 0x86, 0xa2, + 0x0e, 0xe5, 0x18, 0x6b, 0x7f, 0xae, 0xe4, 0xf9, 0x1d, 0x58, 0x8f, 0xd0, 0xf0, 0x55, 0xa9, 0x83, 0xd8, 0x7e, 0xa2, + 0x77, 0x9d, 0x4a, 0xfd, 0x0d, 0x00, 0x03, 0xa7, 0x8e, 0x87, 0xfa, 0xa8, 0x9d, 0x42, 0xb6, 0x73, 0x6f, 0x89, 0x51, + 0xb9, 0x12, 0x9e, 0x2a, 0x2d, 0x4f, 0x29, 0xab, 0xbe, 0x16, 0xdc, 0xca, 0xee, 0xb3, 0x01, 0x64, 0xb4, 0x41, 0x81, + 0x3c, 0xa3, 0xb6, 0xc6, 0x83, 0x54, 0xd3, 0x2c, 0x71, 0x0c, 0x1f, 0x14, 0x69, 0x56, 0x81, 0xc5, 0xcb, 0x5c, 0x32, + 0x07, 0x05, 0xcb, 0xf5, 0x66, 0x33, 0xcd, 0x54, 0x5f, 0xe4, 0xf6, 0x46, 0xe3, 0x65, 0xfa, 0x6f, 0x96, 0x0c, 0x78, + 0x74, 0xf1, 0xc4, 0x0f, 0x20, 0x4d, 0x52, 0x3c, 0x40, 0x12, 0x6c, 0x0f, 0x76, 0xb1, 0xc3, 0xb0, 0x55, 0xac, 0xec, + 0xc9, 0xd3, 0xe5, 0x0e, 0x4d, 0xb9, 0x04, 0x97, 0x9c, 0x98, 0xcb, 0xa9, 0xef, 0x4b, 0xd6, 0x1b, 0x8a, 0x53, 0x36, + 0x4d, 0x40, 0x49, 0xa0, 0xdd, 0x82, 0xff, 0xc2, 0xa7, 0x86, 0x4e, 0x0b, 0xb0, 0xd4, 0x76, 0x03, 0xfe, 0x0b, 0xfd, + 0x62, 0xbb, 0x8b, 0xfa, 0x81, 0x79, 0xb0, 0x37, 0x8b, 0x2b, 0x63, 0xc0, 0x49, 0xe2, 0x4a, 0xf3, 0xc8, 0xf5, 0x83, + 0xa2, 0x4f, 0x97, 0xb5, 0x03, 0x67, 0x8a, 0x0b, 0xab, 0xd4, 0x26, 0xe9, 0xb5, 0xdf, 0x52, 0x13, 0x6f, 0xa2, 0xa4, + 0x2a, 0x6c, 0x87, 0xb4, 0x7f, 0x49, 0x39, 0x53, 0xc5, 0x1d, 0xa2, 0x27, 0xbb, 0x89, 0xab, 0xc0, 0x0b, 0xab, 0x8a, + 0x8d, 0x50, 0x9b, 0x91, 0xe5, 0x04, 0x4e, 0xf7, 0x58, 0x5d, 0xf0, 0xb1, 0x5d, 0xcd, 0x2e, 0x58, 0xc9, 0xd6, 0x4c, + 0xba, 0xcf, 0xdb, 0x31, 0x17, 0xf2, 0x4a, 0x2f, 0x8b, 0x56, 0x40, 0x7b, 0x10, 0x38, 0xfc, 0x5c, 0xd3, 0x3d, 0x7a, + 0xb6, 0xd9, 0xa6, 0x36, 0x1b, 0x5b, 0x8b, 0x10, 0x32, 0x10, 0x0d, 0x7d, 0x21, 0x67, 0x14, 0xf9, 0x2a, 0x2d, 0xd7, + 0x6a, 0x63, 0x95, 0xf1, 0x02, 0x13, 0x41, 0x86, 0xb3, 0xf0, 0x0e, 0x3d, 0xad, 0x47, 0x9a, 0x62, 0x12, 0x9c, 0x74, + 0xf1, 0x17, 0x60, 0x43, 0x79, 0x92, 0x9b, 0x03, 0x72, 0x00, 0x95, 0x4b, 0x51, 0x2a, 0x65, 0xf0, 0x6b, 0x75, 0x47, + 0xb6, 0x55, 0xff, 0x9d, 0x06, 0x32, 0xb8, 0x03, 0x7d, 0xdb, 0x0b, 0xad, 0x1d, 0xed, 0x5c, 0xd9, 0x9a, 0xb6, 0x65, + 0x9a, 0xc7, 0xc8, 0x62, 0x03, 0xc8, 0x27, 0xd2, 0x39, 0x10, 0x79, 0x4d, 0x34, 0xde, 0xd9, 0x53, 0x3e, 0x9e, 0x8a, + 0x87, 0xe4, 0xbd, 0xca, 0xf7, 0xcd, 0xbd, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x32, 0xf1, 0xc1, 0x6a, 0x6b, 0x5d, 0x62, + 0xbd, 0x55, 0x9a, 0x44, 0x37, 0x5c, 0x41, 0xc7, 0x91, 0xb8, 0x41, 0x0c, 0x8e, 0x19, 0xaf, 0xad, 0xb2, 0xf4, 0x15, + 0x96, 0xb9, 0x8e, 0x59, 0x32, 0x64, 0x52, 0xe7, 0x89, 0x82, 0x27, 0x3f, 0x4f, 0x48, 0x46, 0x44, 0xcd, 0xb6, 0x1c, + 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0xe0, 0x9b, 0x34, 0x01, 0x28, 0x97, 0x2f, 0x41, 0x2a, 0x0d, 0x11, 0x5c, + 0xb3, 0xbd, 0x64, 0x74, 0xe3, 0x68, 0x1d, 0x54, 0x49, 0xe6, 0x0e, 0xce, 0xed, 0x2c, 0x52, 0xea, 0xcd, 0x47, 0x18, + 0x76, 0xf2, 0x3e, 0xac, 0x13, 0xfc, 0x36, 0xa0, 0x26, 0x7d, 0x2a, 0xbc, 0x68, 0x04, 0x68, 0xea, 0x3b, 0x55, 0xc6, + 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, 0x98, 0x57, 0xd5, 0x40, 0x1b, + 0xe4, 0x76, 0x1d, 0x33, 0xa0, 0x51, 0xdb, 0x95, 0x47, 0x16, 0xe0, 0xd6, 0x4c, 0x04, 0x46, 0xce, 0xbf, 0xcb, 0xaf, + 0x55, 0x38, 0x4f, 0xbf, 0x1f, 0x7a, 0xfb, 0x6d, 0x10, 0x8d, 0xb6, 0x97, 0x6c, 0x17, 0x44, 0xa3, 0xdd, 0x65, 0xc3, + 0xe8, 0xf7, 0x13, 0xfa, 0xfd, 0xa4, 0x01, 0x55, 0x89, 0x30, 0x11, 0xf7, 0xfa, 0x8d, 0x5a, 0xbe, 0x52, 0xeb, 0x77, + 0x6a, 0xf9, 0x52, 0x0d, 0x6f, 0xed, 0x49, 0x24, 0x88, 0x2c, 0x8d, 0xcd, 0xbd, 0x64, 0x4b, 0xb5, 0x54, 0x3a, 0x46, + 0x95, 0x11, 0xb5, 0x74, 0x36, 0xc7, 0x8a, 0x91, 0x76, 0x0e, 0x4a, 0x06, 0x64, 0x5a, 0x5c, 0xd5, 0x98, 0x6e, 0x56, + 0xb4, 0xc4, 0x64, 0x84, 0x95, 0x6d, 0x79, 0xbb, 0x49, 0xd5, 0x74, 0x4e, 0x6e, 0x6e, 0x95, 0x72, 0x73, 0x2b, 0x78, + 0xfe, 0x0d, 0xdd, 0x72, 0xc9, 0xb5, 0x97, 0xd9, 0xb4, 0x50, 0xba, 0x65, 0x5c, 0x83, 0xad, 0x7d, 0x13, 0xc8, 0x32, + 0x1f, 0x28, 0x6a, 0x6c, 0x2f, 0x1a, 0xe5, 0x1b, 0x64, 0x2b, 0x62, 0xd4, 0x29, 0x0b, 0xc6, 0xdf, 0xee, 0xe8, 0x81, + 0x0c, 0x54, 0x55, 0xb5, 0x71, 0x70, 0x67, 0xa5, 0x3f, 0x2c, 0x2f, 0x9e, 0xb0, 0xc4, 0x4a, 0x27, 0x17, 0xaa, 0xd0, + 0x1f, 0x84, 0xe8, 0xa6, 0xb2, 0xe1, 0xe0, 0x50, 0x17, 0x5b, 0x19, 0x10, 0x7a, 0x98, 0xde, 0xdb, 0x58, 0xc9, 0x72, + 0xd7, 0x94, 0x2f, 0x66, 0x3c, 0xe1, 0x38, 0xfa, 0x72, 0xb5, 0x08, 0x6b, 0xb5, 0xc8, 0x4e, 0x80, 0x87, 0xd6, 0x6a, + 0x29, 0xe4, 0x6a, 0x11, 0xce, 0x4c, 0x17, 0x6a, 0xa6, 0x67, 0xa0, 0x80, 0x14, 0x6a, 0x96, 0x27, 0x00, 0x0b, 0x2f, + 0xcc, 0x0c, 0x17, 0x66, 0x86, 0xe3, 0x90, 0x1a, 0xff, 0x07, 0xbd, 0xd7, 0xb9, 0xe7, 0x96, 0xbb, 0xd1, 0x69, 0xc4, + 0xb7, 0xa3, 0x0d, 0xe6, 0xf8, 0x20, 0x9c, 0x54, 0xfd, 0x7e, 0x5a, 0x22, 0x56, 0x8f, 0x81, 0x11, 0x94, 0x43, 0xe5, + 0x68, 0xbf, 0x2c, 0x2c, 0xc9, 0x92, 0xb0, 0x24, 0xf7, 0x6a, 0x9c, 0x4b, 0xcb, 0xc5, 0xab, 0x24, 0x10, 0x89, 0x8c, + 0x97, 0xd2, 0x04, 0x9f, 0xf0, 0x72, 0x64, 0xa4, 0xe6, 0xc9, 0x22, 0xf5, 0x72, 0x96, 0xb1, 0x31, 0x62, 0x18, 0x85, + 0x7e, 0x53, 0xf5, 0xfb, 0x79, 0xe9, 0xe5, 0xd4, 0xce, 0x4f, 0xe0, 0x7a, 0x79, 0xea, 0x2c, 0x72, 0x84, 0xbc, 0x1a, + 0x49, 0x85, 0xe5, 0xb5, 0x52, 0x4f, 0x5f, 0x82, 0x0f, 0xea, 0xee, 0x8d, 0x02, 0x20, 0x2e, 0x72, 0xe9, 0x5f, 0x5b, + 0xc2, 0xa5, 0x29, 0x37, 0x30, 0xe8, 0x21, 0xcf, 0x49, 0x08, 0x95, 0x20, 0x24, 0x85, 0x75, 0xe3, 0xbe, 0x78, 0x32, + 0x71, 0xdd, 0x59, 0x6c, 0x60, 0x82, 0xc3, 0x01, 0x10, 0x0f, 0xa6, 0x5e, 0x34, 0xe0, 0xa5, 0x9a, 0x33, 0x1f, 0xbc, + 0x9c, 0x60, 0x32, 0x40, 0x55, 0x31, 0x70, 0xca, 0x7a, 0x2c, 0x1f, 0x19, 0x37, 0x33, 0xdf, 0x0f, 0xf0, 0xdd, 0xba, + 0x90, 0xe8, 0x0f, 0x0a, 0xa0, 0x20, 0x53, 0x00, 0x05, 0x89, 0x01, 0x28, 0x88, 0x0d, 0x40, 0xc1, 0xa6, 0xe1, 0x2b, + 0xa9, 0xc3, 0x8d, 0x80, 0x2e, 0xc2, 0x87, 0x9e, 0x85, 0x8d, 0x15, 0x8a, 0x67, 0x63, 0x36, 0x66, 0x85, 0xda, 0x79, + 0x72, 0x39, 0x15, 0x3b, 0x8b, 0xb1, 0xae, 0x22, 0xb7, 0x89, 0x17, 0x12, 0x8a, 0x9c, 0x73, 0x23, 0x51, 0x77, 0x3f, + 0xf7, 0x5e, 0x92, 0xb1, 0x64, 0xde, 0xd0, 0xa8, 0xc1, 0xbc, 0xec, 0x3a, 0x80, 0x69, 0xc9, 0xb7, 0x05, 0x0d, 0xa6, + 0x53, 0xe5, 0x11, 0x69, 0x12, 0xd4, 0xce, 0x65, 0x52, 0xe4, 0x84, 0x30, 0x09, 0x7a, 0x25, 0xf8, 0x8d, 0x44, 0xf9, + 0xff, 0xa6, 0x13, 0x3c, 0xc0, 0x31, 0xd1, 0x2a, 0xf9, 0x0a, 0x06, 0xcc, 0x9c, 0x3f, 0x93, 0x4e, 0xd9, 0x08, 0xc5, + 0x58, 0xa6, 0xf1, 0xe8, 0x2b, 0x1b, 0x22, 0xb4, 0xd5, 0x33, 0x34, 0x31, 0x41, 0x1d, 0xe0, 0x11, 0xfd, 0x35, 0xfa, + 0x6a, 0x28, 0x54, 0xba, 0x1a, 0xa9, 0x6b, 0x76, 0xce, 0xf9, 0xdb, 0xda, 0x70, 0x22, 0x63, 0xda, 0x14, 0xf8, 0x06, + 0x04, 0xf2, 0x0d, 0x04, 0x80, 0xab, 0xa6, 0x33, 0x7b, 0x05, 0x70, 0x0e, 0x04, 0xf0, 0x38, 0xef, 0x78, 0xfc, 0x40, + 0x7f, 0x15, 0xc7, 0xbd, 0xd3, 0x34, 0x6c, 0xff, 0x15, 0x18, 0x8b, 0xa1, 0x1c, 0xcf, 0x77, 0x0a, 0x92, 0x3d, 0x4a, + 0x59, 0xba, 0x6a, 0x22, 0x3b, 0x14, 0xeb, 0xd3, 0x9c, 0x32, 0x96, 0xb6, 0xe5, 0x18, 0x6d, 0xbc, 0x7e, 0x88, 0xc7, + 0x37, 0x37, 0x7a, 0xf2, 0x41, 0x0f, 0x6e, 0x6f, 0xaf, 0x5e, 0xf4, 0x98, 0xcd, 0xb7, 0x62, 0xf1, 0xac, 0x88, 0x13, + 0xa7, 0x75, 0xc8, 0x01, 0x0e, 0x72, 0x12, 0x02, 0xe9, 0x18, 0x97, 0x5a, 0x74, 0x50, 0xb3, 0x9c, 0xd7, 0xc0, 0x32, + 0x8b, 0x20, 0x1b, 0x20, 0xaa, 0x69, 0x2a, 0x56, 0xc3, 0x83, 0x52, 0x35, 0xa7, 0x54, 0x6a, 0xdf, 0x70, 0xb6, 0x3a, + 0x7d, 0x62, 0xd5, 0x26, 0xdc, 0xfa, 0xb7, 0xda, 0x13, 0xb4, 0x95, 0x34, 0x10, 0xea, 0xf9, 0x22, 0xbd, 0xa5, 0x28, + 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, + 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, 0xc9, 0x3f, 0x85, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, + 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, + 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, + 0x9a, 0xa7, 0xd5, 0x7b, 0xf5, 0xf7, 0xbb, 0x25, 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, + 0xe8, 0x16, 0xc0, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x04, 0x6b, 0xa8, 0xca, 0x53, 0x3e, 0x7b, 0xf9, 0x64, 0x07, + 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, + 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, + 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, + 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, 0x76, 0x03, 0x88, 0x81, 0xa5, 0x0e, 0x49, 0x56, 0x1d, 0xdb, 0xef, + 0xbf, 0x1c, 0x19, 0xde, 0x74, 0x44, 0x84, 0xd1, 0xbf, 0x2b, 0x10, 0xa0, 0x60, 0x99, 0xd9, 0xce, 0x4c, 0xba, 0xda, + 0xb3, 0x7a, 0xde, 0x6c, 0xf2, 0xae, 0xde, 0xb1, 0x9a, 0x96, 0x53, 0xd3, 0x2a, 0xab, 0x69, 0x93, 0x1c, 0x6a, 0x26, + 0xfa, 0x7d, 0x8d, 0x8f, 0x9a, 0xcf, 0x01, 0x97, 0x0d, 0x93, 0x5f, 0xce, 0xaa, 0x79, 0xbf, 0xef, 0xc9, 0x47, 0xf0, + 0x0b, 0x89, 0xcb, 0xdc, 0x1a, 0xcb, 0xa7, 0xaf, 0x88, 0xcf, 0xcc, 0x20, 0x1e, 0xdd, 0x1c, 0x41, 0x7d, 0x7d, 0x14, + 0x5e, 0xc7, 0x5c, 0x61, 0x33, 0x31, 0x7d, 0x09, 0x83, 0xe7, 0x09, 0x1f, 0xbc, 0xe5, 0xe8, 0x6f, 0xa4, 0x33, 0x53, + 0xb0, 0x90, 0x73, 0x7f, 0xf2, 0x12, 0xa1, 0x93, 0x11, 0xe9, 0x41, 0xa7, 0x13, 0x34, 0x64, 0xbf, 0xbf, 0x80, 0xce, + 0x6c, 0xa5, 0x52, 0xb6, 0x2a, 0x2a, 0xd3, 0x75, 0x5d, 0x94, 0x15, 0x74, 0x2c, 0xfd, 0xbc, 0x11, 0x32, 0xb3, 0x7e, + 0x66, 0x21, 0x3f, 0x2d, 0x24, 0xd6, 0x94, 0x6d, 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, + 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, + 0xf4, 0xb9, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, + 0x39, 0x79, 0x09, 0xe0, 0x74, 0x88, 0x88, 0x5b, 0x91, 0xa0, 0x63, 0xd5, 0x70, 0x67, 0xe1, 0x9e, 0xf6, 0xd2, 0xb8, + 0x97, 0xe6, 0x67, 0x69, 0xbf, 0x6f, 0x00, 0x34, 0x53, 0x44, 0x86, 0xc7, 0x19, 0xb9, 0x4d, 0x5a, 0x08, 0xa6, 0xb4, + 0xff, 0x6a, 0x0c, 0x09, 0x02, 0x01, 0xff, 0xa7, 0xf0, 0xde, 0x03, 0xda, 0x26, 0x6d, 0xc0, 0x55, 0x8f, 0xe9, 0xc0, + 0x6c, 0xc9, 0xd9, 0xaa, 0xb3, 0x01, 0x28, 0xa7, 0x4a, 0xeb, 0x29, 0x8f, 0x6b, 0x8a, 0x88, 0x54, 0x59, 0xa8, 0xdf, + 0x58, 0x4f, 0x26, 0xab, 0x5c, 0x64, 0xc8, 0x51, 0x99, 0xde, 0xd6, 0x8c, 0x10, 0xbb, 0xf4, 0xf3, 0x05, 0x2c, 0xd9, + 0xf8, 0x03, 0x4e, 0xde, 0x12, 0x20, 0x6d, 0x67, 0xed, 0xaa, 0xda, 0xe5, 0xb8, 0xb5, 0x9b, 0x03, 0x92, 0xaf, 0x37, + 0x1a, 0x8d, 0xb4, 0x9f, 0x9c, 0x80, 0xa1, 0xea, 0xa9, 0xa5, 0xd0, 0x63, 0xb5, 0xc2, 0xd6, 0xed, 0xc8, 0x65, 0x96, + 0x0c, 0xe6, 0x0b, 0xe3, 0xf8, 0xda, 0x7c, 0xf4, 0xe1, 0x52, 0x59, 0xbb, 0x8e, 0xf8, 0xfa, 0x4f, 0xb2, 0x5a, 0xdf, + 0xf3, 0xae, 0x6a, 0x02, 0xbe, 0xa8, 0x62, 0x4b, 0xbf, 0xe3, 0x3d, 0xd9, 0xbb, 0xf8, 0xda, 0x47, 0xec, 0x92, 0xef, + 0x79, 0x8b, 0x3a, 0xcf, 0x57, 0xbe, 0x6e, 0x54, 0xe9, 0xf6, 0x5e, 0xb2, 0xc0, 0xb5, 0x77, 0xd4, 0x34, 0xd6, 0x33, + 0x3f, 0x7a, 0x58, 0x84, 0x6c, 0xe7, 0x43, 0xef, 0xab, 0xe6, 0xe9, 0x59, 0x43, 0x6f, 0x52, 0x43, 0x1f, 0x7a, 0x51, + 0xb6, 0x4f, 0x4d, 0x23, 0x7a, 0x0d, 0x1b, 0xfa, 0xd0, 0x5b, 0x72, 0x72, 0x48, 0x30, 0x38, 0x35, 0xe6, 0x0f, 0x0f, + 0xa7, 0x33, 0xfc, 0x1d, 0x03, 0x2a, 0x31, 0x99, 0x4f, 0x8f, 0x69, 0x47, 0x01, 0x66, 0x54, 0xe9, 0xed, 0xd3, 0x03, + 0xdb, 0xf1, 0xb2, 0x1e, 0x5a, 0x7a, 0xf7, 0xe4, 0xe8, 0x76, 0xbc, 0xaa, 0xc6, 0x97, 0x72, 0xc8, 0xf3, 0x7c, 0x36, + 0x1a, 0x8d, 0x84, 0x41, 0xe7, 0xae, 0xf4, 0x06, 0x56, 0x20, 0x83, 0x8b, 0xea, 0x43, 0xb9, 0xf4, 0x76, 0xea, 0xd0, + 0xae, 0xfc, 0x49, 0x7e, 0x38, 0x14, 0x23, 0x73, 0x8c, 0x03, 0xce, 0x49, 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, + 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x15, 0x91, 0x57, 0x23, 0xe4, 0x43, 0xf0, 0xb3, 0x07, 0x6a, 0xf1, 0xa7, 0x5a, 0x10, + 0x7b, 0xe8, 0x53, 0xa5, 0x74, 0x88, 0x57, 0x05, 0x84, 0x08, 0x03, 0xde, 0x40, 0x3b, 0x28, 0xc1, 0x61, 0x87, 0x7b, + 0x8f, 0x08, 0xd1, 0x2f, 0xbc, 0x7c, 0x26, 0xc3, 0x95, 0x7b, 0x83, 0x6a, 0xce, 0x00, 0xb1, 0xd2, 0x67, 0xe0, 0x82, + 0x09, 0xa8, 0xa7, 0xf8, 0x14, 0xfd, 0xeb, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, 0x50, 0x11, 0x3d, 0xfb, 0xf9, 0x18, + 0xc0, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xe5, 0x6f, 0x80, 0x61, 0xa5, 0x24, 0xd1, 0xce, 0x29, 0x11, 0xb8, 0xf3, 0x91, + 0x2d, 0xfd, 0x28, 0x05, 0x62, 0xee, 0x78, 0x92, 0xc8, 0x1e, 0x6c, 0xe4, 0x04, 0x6e, 0x31, 0xe0, 0xd1, 0x01, 0xa8, + 0x5c, 0x29, 0xc8, 0xbd, 0xe6, 0x48, 0xee, 0xf8, 0xb1, 0xf7, 0xe3, 0xa0, 0x1e, 0xfc, 0xd8, 0x3b, 0x4b, 0x49, 0xee, + 0x08, 0xcf, 0xd4, 0x94, 0x10, 0xf1, 0xd9, 0x8f, 0x83, 0x7c, 0x80, 0x67, 0x89, 0x16, 0x69, 0x91, 0x5b, 0x4d, 0xd4, + 0xb8, 0x09, 0x6f, 0x13, 0x49, 0x43, 0x74, 0xd7, 0x79, 0x44, 0x2c, 0x00, 0x24, 0x8b, 0xcf, 0xe6, 0x0d, 0x45, 0xbd, + 0x9b, 0xf0, 0x2d, 0xba, 0xcb, 0x62, 0xbf, 0xbf, 0xca, 0xd3, 0xba, 0xa7, 0x43, 0x65, 0xf0, 0x05, 0xa9, 0x26, 0xc0, + 0xa3, 0xfd, 0x85, 0x39, 0x5e, 0xbd, 0xda, 0x1c, 0x29, 0x0b, 0x55, 0xa2, 0x7e, 0x8b, 0xd5, 0xac, 0x87, 0x88, 0xdc, + 0x59, 0x66, 0xec, 0xed, 0x05, 0xaf, 0xe4, 0xac, 0x8a, 0xed, 0x72, 0x7c, 0x45, 0x58, 0x5b, 0x49, 0x80, 0x8e, 0xd6, + 0x63, 0x6d, 0x8a, 0x91, 0x5f, 0x29, 0x24, 0xe0, 0xa2, 0x63, 0x6b, 0xa1, 0xd8, 0x78, 0x01, 0xfa, 0x92, 0x9d, 0x69, + 0x80, 0xf5, 0x46, 0xaf, 0x22, 0x6e, 0xcb, 0x07, 0x2a, 0xbc, 0xc9, 0x4d, 0x95, 0x59, 0xd9, 0x2c, 0xda, 0xfd, 0x54, + 0xf1, 0x0a, 0x71, 0xeb, 0x8d, 0xda, 0xa3, 0x00, 0xb5, 0x87, 0x16, 0xca, 0x00, 0x5d, 0x9a, 0x66, 0x00, 0xc8, 0x00, + 0x20, 0x53, 0x45, 0x7c, 0x26, 0x40, 0xa5, 0xad, 0x6e, 0x14, 0x38, 0x91, 0x5e, 0x00, 0xe3, 0x02, 0x2b, 0x7d, 0x64, + 0x23, 0x83, 0xc5, 0x16, 0x01, 0x6e, 0x39, 0xd2, 0x87, 0x69, 0x38, 0xd9, 0x46, 0x73, 0x98, 0xa4, 0xf9, 0x5d, 0x98, + 0xa5, 0x12, 0x5a, 0xe2, 0x95, 0xac, 0x31, 0x62, 0x01, 0xe9, 0xfb, 0xf4, 0xa2, 0xc8, 0x62, 0x82, 0x84, 0xb3, 0x9e, + 0x3a, 0x80, 0x6a, 0x72, 0xae, 0x35, 0xad, 0x9e, 0xd5, 0x26, 0x0f, 0x59, 0xa0, 0xb3, 0x07, 0x63, 0x52, 0xcb, 0x0d, + 0x3d, 0xb2, 0xbf, 0x72, 0x3c, 0x23, 0x7c, 0xd7, 0x33, 0x9c, 0xfa, 0xef, 0x63, 0x0d, 0xa4, 0x4c, 0x09, 0x20, 0xc8, + 0xe0, 0x68, 0x42, 0x28, 0x4f, 0xc7, 0x64, 0x6a, 0xf3, 0x23, 0x10, 0x8e, 0x08, 0x5e, 0xc1, 0x73, 0x43, 0xeb, 0x96, + 0x1b, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x59, 0xbc, 0xe0, 0xf7, 0x80, 0xcc, 0xa9, 0x57, 0x85, 0xec, 0xd9, 0x73, 0x31, + 0x9d, 0xcd, 0x83, 0x8f, 0x09, 0xed, 0x5f, 0x4c, 0xf8, 0x4d, 0x77, 0x95, 0x5c, 0x99, 0x5a, 0xf7, 0x26, 0x7a, 0xcc, + 0xe5, 0x4e, 0x9f, 0x56, 0x1c, 0x23, 0x9e, 0xc1, 0x2a, 0x20, 0xe7, 0x6c, 0xc8, 0x9f, 0x9e, 0x03, 0x76, 0xcb, 0x4a, + 0x78, 0x11, 0x7f, 0x1a, 0xca, 0x6a, 0x01, 0xf2, 0x23, 0xe7, 0x91, 0xf9, 0xe5, 0xab, 0xed, 0x50, 0xce, 0x29, 0x8a, + 0x68, 0x39, 0x35, 0x2d, 0x29, 0x64, 0x87, 0x9e, 0x82, 0xc9, 0xd4, 0x96, 0xbf, 0xef, 0x13, 0x97, 0xe4, 0x9b, 0x49, + 0x64, 0x5f, 0x07, 0x58, 0xb3, 0x56, 0xdd, 0x43, 0x37, 0x04, 0x03, 0x44, 0x46, 0x28, 0xb3, 0xb9, 0xbe, 0x5b, 0x0f, + 0x06, 0x0a, 0xe6, 0x57, 0xd0, 0x4d, 0x8b, 0x4e, 0x71, 0x80, 0x9c, 0xb5, 0xae, 0x51, 0xa9, 0x2a, 0x0e, 0x1d, 0xe6, + 0xdd, 0xb2, 0x2a, 0xbb, 0x2c, 0xbd, 0x10, 0xa4, 0x46, 0x5d, 0x05, 0x8b, 0x94, 0x8a, 0x28, 0xde, 0x93, 0x5f, 0x03, + 0x13, 0xcf, 0xac, 0x1c, 0xa5, 0xf1, 0x1c, 0x10, 0x83, 0x14, 0x10, 0xa7, 0xfc, 0x0a, 0xd0, 0x44, 0x17, 0x51, 0x98, + 0xbd, 0x8a, 0xab, 0xa0, 0xb6, 0x9a, 0xfe, 0xa7, 0x03, 0x19, 0x7b, 0x5e, 0xf7, 0xfb, 0x29, 0x31, 0xfa, 0x61, 0x14, + 0x06, 0xfe, 0x3d, 0x9e, 0xee, 0x9b, 0x20, 0x35, 0xaf, 0x7c, 0x84, 0x57, 0x74, 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, + 0xfc, 0x35, 0x82, 0xc3, 0xa7, 0x8e, 0x62, 0xbb, 0x4d, 0x95, 0x53, 0x1b, 0x83, 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xff, + 0x99, 0x78, 0xf9, 0x2c, 0x9a, 0x83, 0xa2, 0x34, 0xd3, 0x7c, 0x21, 0x85, 0x74, 0x13, 0xa0, 0x8f, 0x06, 0xa1, 0x56, + 0x57, 0xbe, 0x49, 0xbc, 0x54, 0x4d, 0x6b, 0xf3, 0x14, 0x6b, 0x14, 0x88, 0x59, 0x34, 0x6f, 0x58, 0x46, 0x87, 0xa4, + 0xba, 0x5c, 0x9a, 0x66, 0xbc, 0xb1, 0x9a, 0xa1, 0x5a, 0x71, 0xd4, 0x04, 0x35, 0x4a, 0x1f, 0xe1, 0x02, 0xf8, 0x0f, + 0xba, 0xe3, 0xa8, 0x46, 0x91, 0xa2, 0x01, 0x9f, 0x20, 0x46, 0xac, 0xd9, 0x3c, 0x61, 0xad, 0xa9, 0x6b, 0x46, 0xbf, + 0x2f, 0x43, 0x86, 0x4c, 0x12, 0xf2, 0xf4, 0xe1, 0x72, 0xfd, 0x40, 0xaa, 0x0b, 0xe0, 0x57, 0xae, 0xd8, 0xac, 0xd7, + 0x9b, 0x03, 0x5c, 0x2f, 0xac, 0x5f, 0xd8, 0xb8, 0x82, 0xf3, 0x4b, 0x82, 0xdf, 0x55, 0x3f, 0xc2, 0x2c, 0x83, 0x2a, + 0x20, 0xe3, 0x8f, 0x05, 0x55, 0x9c, 0xbb, 0x98, 0xd4, 0x2f, 0x47, 0xea, 0x82, 0x32, 0x4b, 0xe7, 0x16, 0x27, 0x08, + 0x38, 0x0f, 0xab, 0x27, 0x90, 0xec, 0xcb, 0xc7, 0x3e, 0xcd, 0x28, 0x50, 0x1d, 0x01, 0x3e, 0x9b, 0xf5, 0x43, 0xd8, + 0x3f, 0x20, 0xb2, 0x50, 0x7f, 0xf3, 0x5a, 0xce, 0x1a, 0x92, 0x07, 0x52, 0xcd, 0x7d, 0x0c, 0xa7, 0xc6, 0x02, 0x5f, + 0x5a, 0xf4, 0xa6, 0x82, 0xd7, 0x84, 0xcc, 0xbd, 0x40, 0x6b, 0xdf, 0x02, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, + 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, 0x3f, 0x72, 0xf1, 0x8b, 0x53, 0xa4, 0x67, 0xd1, 0x05, 0x06, 0xba, + 0x20, 0xf3, 0xc6, 0xbf, 0x2a, 0x58, 0xb9, 0x80, 0xde, 0x4b, 0xc5, 0x4a, 0x4e, 0xb6, 0x9d, 0xfa, 0xa3, 0x54, 0xf6, + 0xdb, 0x33, 0x6b, 0x02, 0xbf, 0x4b, 0xec, 0x97, 0xc8, 0xe4, 0x9b, 0x1e, 0x9b, 0x7c, 0x65, 0x58, 0x74, 0x6a, 0x19, + 0x9c, 0xd3, 0x23, 0x83, 0x73, 0x6f, 0x67, 0xd5, 0x26, 0x82, 0xa1, 0x20, 0x09, 0x34, 0x5d, 0x7a, 0x58, 0x37, 0xfd, + 0xf9, 0x49, 0x8b, 0x6a, 0xab, 0xf6, 0xad, 0xfb, 0x71, 0x88, 0x5d, 0xfc, 0x2e, 0xf1, 0x0c, 0x11, 0xa9, 0x0f, 0x74, + 0x60, 0x32, 0x78, 0xe2, 0xb2, 0xdf, 0x87, 0xc2, 0x66, 0xe3, 0xf9, 0xa8, 0x2e, 0x5e, 0x17, 0xf7, 0x80, 0xea, 0x50, + 0x81, 0x5d, 0x0e, 0x65, 0x28, 0x23, 0x36, 0xb5, 0xe5, 0x9e, 0x3f, 0xae, 0xc3, 0x1c, 0xe4, 0x1d, 0x0d, 0x8f, 0x73, + 0x06, 0x62, 0x18, 0x7c, 0xfd, 0xc7, 0x47, 0xfb, 0xb4, 0xf9, 0xf1, 0x0c, 0xbe, 0x3b, 0x3a, 0x7b, 0x8f, 0x74, 0x37, + 0x67, 0xeb, 0xb2, 0xb8, 0x4b, 0x63, 0x71, 0xf6, 0x23, 0xa4, 0xfe, 0x78, 0x56, 0x94, 0x67, 0x3f, 0xaa, 0xca, 0xfc, + 0x78, 0x46, 0x0b, 0x6e, 0xf4, 0x87, 0x35, 0xf1, 0x7e, 0xaf, 0x34, 0x03, 0xda, 0x12, 0x22, 0xb3, 0xb4, 0xfa, 0x11, + 0x94, 0x88, 0x8a, 0x1f, 0x55, 0x46, 0xb5, 0x5a, 0x3b, 0xce, 0xfb, 0x44, 0x23, 0x65, 0xd3, 0x84, 0xc4, 0xd5, 0x12, + 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xdf, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x39, 0x7f, 0x9a, 0x8f, 0xb6, 0xf4, 0x35, 0xf8, + 0xd6, 0xe1, 0x90, 0x8f, 0x76, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x77, 0x24, 0x7b, 0x07, 0x6b, 0x0b, 0x9c, 0x20, + 0xc0, 0x01, 0xe0, 0x1f, 0x0e, 0xf4, 0x7b, 0x27, 0x7f, 0xab, 0xdd, 0xd2, 0xaa, 0xe7, 0xb3, 0x16, 0x77, 0xc6, 0xab, + 0xda, 0x10, 0xb5, 0xed, 0x25, 0xb6, 0xf4, 0xbe, 0x69, 0x50, 0x53, 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x8a, 0xc3, 0x82, + 0x94, 0x90, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0x58, 0x7a, 0x72, 0xdf, 0xe1, 0xe5, 0xd6, 0xf7, 0x01, 0x49, + 0xab, 0x70, 0xfe, 0xce, 0x0b, 0x0d, 0x3c, 0x7a, 0x91, 0x57, 0x45, 0x26, 0x46, 0x82, 0x46, 0xf9, 0x15, 0x89, 0x33, + 0x67, 0x58, 0x8b, 0x33, 0x05, 0x16, 0x16, 0x12, 0x24, 0x78, 0x51, 0x52, 0x7a, 0x70, 0xf6, 0x68, 0x5f, 0x36, 0x7f, + 0x10, 0x3c, 0xc4, 0x68, 0x01, 0x8c, 0x38, 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0xba, 0xcd, 0x0b, + 0x08, 0xd1, 0x3c, 0x93, 0x8a, 0xd5, 0xf2, 0x0c, 0x18, 0xf3, 0x44, 0x7c, 0x16, 0x56, 0x72, 0x1a, 0x54, 0x1d, 0xc5, + 0xaa, 0x6d, 0x3c, 0xca, 0x3d, 0xa0, 0xf8, 0x7e, 0x9f, 0x00, 0x97, 0xbb, 0xcf, 0x5e, 0x2a, 0xd7, 0x54, 0xd2, 0x23, + 0xcf, 0x21, 0x5a, 0xf2, 0x51, 0x02, 0x14, 0xcf, 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, + 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, + 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0x2d, 0xcc, 0xbd, 0x10, 0x86, 0x2a, + 0xe1, 0xde, 0xab, 0x7a, 0x16, 0xca, 0x4d, 0xd1, 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, + 0xaf, 0x13, 0x2f, 0x06, 0xc3, 0xf5, 0x92, 0x97, 0xb3, 0x8d, 0x59, 0x08, 0x87, 0xc3, 0x66, 0x52, 0xcc, 0x96, 0x10, + 0xe6, 0xba, 0x9c, 0x1f, 0x0e, 0x5d, 0x2d, 0x5b, 0x0b, 0x0f, 0x1e, 0xaa, 0x16, 0x6e, 0x1a, 0x96, 0xc3, 0xcf, 0x64, + 0x16, 0x63, 0xfb, 0x1a, 0x9f, 0xd9, 0x9f, 0x2f, 0xba, 0x67, 0x09, 0x92, 0x6f, 0xac, 0x81, 0x76, 0x6c, 0xd6, 0xee, + 0x70, 0x35, 0x02, 0x92, 0xd2, 0xdd, 0xe8, 0x1c, 0xcb, 0x4e, 0x9e, 0x12, 0xe4, 0x8e, 0x56, 0x60, 0xbf, 0xfb, 0xc6, + 0x9f, 0x68, 0xb1, 0x07, 0xed, 0x36, 0xb6, 0x84, 0xa8, 0xa6, 0x3d, 0x97, 0x2b, 0xc5, 0xd2, 0x0d, 0x96, 0x36, 0x7a, + 0x3e, 0xac, 0xcf, 0x7d, 0x23, 0x07, 0x0a, 0xc6, 0x88, 0xa7, 0xd6, 0x41, 0x34, 0x9b, 0x03, 0x0d, 0x06, 0x9a, 0x47, + 0x78, 0x6a, 0xa1, 0x83, 0x32, 0x6b, 0xc3, 0xfe, 0x29, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, + 0x31, 0xc5, 0xf6, 0xf8, 0xa5, 0x52, 0x54, 0x78, 0x6c, 0x47, 0x5c, 0x6b, 0x1f, 0x45, 0x6d, 0xa8, 0x1c, 0xfe, 0x2d, + 0xec, 0x23, 0xec, 0x0b, 0x9a, 0x20, 0x0c, 0x76, 0xfd, 0x99, 0x40, 0x88, 0x58, 0x88, 0x17, 0xfc, 0x52, 0x49, 0x2a, + 0x3a, 0xe1, 0xb3, 0x5d, 0x09, 0xbc, 0x75, 0x18, 0xd0, 0x27, 0xe4, 0x67, 0x22, 0x61, 0x68, 0x26, 0xf4, 0x8e, 0xfe, + 0x3b, 0xb1, 0x93, 0x4d, 0x72, 0x2b, 0xe4, 0x03, 0x49, 0x25, 0xc1, 0x04, 0x2b, 0x2f, 0x94, 0xaf, 0xdc, 0x0b, 0xa5, + 0xd6, 0x5a, 0xd0, 0xfa, 0xe5, 0x3f, 0x25, 0x9e, 0xc1, 0xdf, 0x03, 0x19, 0x83, 0x6e, 0x23, 0xaa, 0x49, 0x8e, 0xe9, + 0xa3, 0x74, 0x9e, 0x81, 0x0a, 0xe8, 0x6c, 0x9d, 0x85, 0xf5, 0xb2, 0x28, 0x57, 0xad, 0x48, 0x51, 0x59, 0xfa, 0x48, + 0x3d, 0xc6, 0xbc, 0x30, 0x4f, 0x4e, 0xe4, 0x83, 0x47, 0x00, 0x8c, 0x47, 0x79, 0x5a, 0x75, 0x94, 0xd6, 0x0f, 0x2c, + 0x03, 0x46, 0xe0, 0x44, 0x19, 0xf0, 0x08, 0xcb, 0xc0, 0x3c, 0xed, 0x32, 0xd4, 0x20, 0xd6, 0xa8, 0xba, 0x52, 0x1b, + 0xcc, 0x89, 0xa2, 0xe4, 0x53, 0x2c, 0xad, 0x30, 0x86, 0xa6, 0xae, 0x3c, 0xb2, 0x5e, 0x72, 0xc2, 0x9e, 0xec, 0x06, + 0xd2, 0x2d, 0x6c, 0x14, 0xce, 0xa0, 0x6b, 0x59, 0xa2, 0x5c, 0x74, 0xcb, 0x88, 0x32, 0x11, 0x52, 0x3f, 0x7b, 0x38, + 0xd3, 0x6a, 0xbf, 0xb1, 0x93, 0xf6, 0xed, 0x91, 0xa2, 0x17, 0x0c, 0xda, 0xa7, 0x3d, 0x52, 0xea, 0x59, 0x23, 0x97, + 0x81, 0x2d, 0x5d, 0xaa, 0x7a, 0xfe, 0x1b, 0x94, 0xef, 0x60, 0x66, 0x9c, 0xcd, 0xfe, 0xd0, 0x9b, 0xdb, 0xa3, 0x7d, + 0xdd, 0xfc, 0xc1, 0x7a, 0x3d, 0xd8, 0x1a, 0x64, 0xe2, 0x33, 0xc5, 0x42, 0x65, 0x15, 0x62, 0x05, 0x69, 0xff, 0x5b, + 0x78, 0x7f, 0xc0, 0x5b, 0x23, 0x34, 0x2b, 0xe3, 0x61, 0x3e, 0x7a, 0xb4, 0x17, 0xcd, 0x1f, 0x9d, 0x65, 0x5b, 0xb9, + 0x2a, 0x99, 0xed, 0x8f, 0xa3, 0xa4, 0x39, 0x7b, 0xb8, 0x46, 0x52, 0x07, 0xf8, 0x70, 0x7d, 0x86, 0x0f, 0x54, 0x42, + 0xa9, 0x05, 0x55, 0x0d, 0x5a, 0x1f, 0xfb, 0xa3, 0xf5, 0x9c, 0x3e, 0x7e, 0x2c, 0xa7, 0x5b, 0x52, 0x84, 0xf1, 0x03, + 0x83, 0x29, 0x3b, 0x71, 0xea, 0x92, 0x37, 0x43, 0x7a, 0xd7, 0xad, 0x92, 0xba, 0xec, 0x51, 0x22, 0x08, 0x75, 0xb0, + 0x7e, 0xb1, 0x1f, 0xc2, 0xcc, 0x16, 0xfd, 0x61, 0xb3, 0x9a, 0x13, 0x20, 0x22, 0xa0, 0xb5, 0xca, 0xfb, 0xc0, 0x31, + 0x5f, 0x98, 0x35, 0x37, 0xa4, 0x5b, 0x6f, 0xae, 0xb4, 0x57, 0x52, 0x40, 0x3f, 0x07, 0x99, 0xdb, 0x47, 0xb7, 0x5c, + 0xb5, 0xcc, 0x73, 0x69, 0xcb, 0x01, 0x8b, 0x16, 0x02, 0x35, 0x3b, 0x97, 0x0e, 0x07, 0x0a, 0x42, 0x5d, 0x89, 0x2a, + 0xe2, 0xea, 0x28, 0x5a, 0x88, 0x5a, 0xad, 0xda, 0xe5, 0x64, 0x53, 0x21, 0x5b, 0x12, 0x41, 0x46, 0xc9, 0x5e, 0x09, + 0xf5, 0x51, 0xae, 0xf6, 0x4c, 0xc3, 0x01, 0x9a, 0x80, 0x4d, 0x1b, 0xfc, 0x2d, 0x70, 0x2f, 0x83, 0x33, 0xd3, 0x3e, + 0x0d, 0x23, 0xe0, 0x34, 0x87, 0x98, 0x3f, 0xbf, 0xeb, 0x41, 0x05, 0x0f, 0x3a, 0xd2, 0x5f, 0xd5, 0xb3, 0x02, 0xcf, + 0xdc, 0x13, 0xcf, 0x5f, 0x9e, 0x48, 0x2f, 0x73, 0x78, 0xa0, 0x69, 0x10, 0x33, 0xfe, 0xac, 0x2c, 0xc3, 0xdd, 0x68, + 0x59, 0x16, 0x2b, 0x2f, 0xd2, 0xfb, 0x78, 0x26, 0xc5, 0x40, 0x62, 0xc6, 0xcc, 0xe8, 0x2a, 0xd6, 0x71, 0x0e, 0xe3, + 0xde, 0x9e, 0x84, 0x15, 0xda, 0x3f, 0x4b, 0xec, 0x75, 0x01, 0x58, 0x0e, 0x59, 0x83, 0x56, 0x78, 0xa7, 0xdb, 0xdb, + 0x3d, 0x2e, 0xd9, 0x51, 0xdc, 0x00, 0xfa, 0x59, 0x0d, 0x2d, 0x13, 0xd4, 0x32, 0xeb, 0x4e, 0x26, 0x53, 0x24, 0x97, + 0x6f, 0xc3, 0x5e, 0xb2, 0x32, 0x9f, 0x37, 0x72, 0x7b, 0x78, 0x1b, 0xae, 0x44, 0xac, 0x2d, 0xe8, 0xa4, 0x23, 0xe3, + 0x70, 0x2f, 0x34, 0x37, 0xd2, 0xfd, 0xa3, 0x2a, 0x09, 0x4b, 0x11, 0xc3, 0x2d, 0x90, 0xed, 0xd5, 0xb6, 0x12, 0x94, + 0xc0, 0x07, 0xfb, 0xbe, 0x14, 0xcb, 0x74, 0x2b, 0x00, 0xd7, 0x81, 0xff, 0x26, 0x11, 0x09, 0xdd, 0x9d, 0x87, 0x28, + 0xd6, 0xc8, 0xfb, 0x06, 0xd1, 0xd8, 0x3f, 0x81, 0x9c, 0x06, 0x64, 0x22, 0xc5, 0x48, 0x16, 0x0c, 0x7c, 0x00, 0x39, + 0x5f, 0x83, 0x49, 0x6e, 0x9a, 0x7b, 0x7e, 0x90, 0xeb, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, 0xb8, 0xd6, 0x2c, 0x07, 0xaf, + 0x98, 0x88, 0xff, 0xa3, 0xf6, 0x4a, 0x96, 0xb3, 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, + 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, + 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, 0x41, 0xe8, 0x1f, 0x35, 0x20, 0x6d, 0x30, 0x49, 0x93, 0x50, 0xf9, + 0xe0, 0x82, 0x6e, 0x18, 0x9b, 0x2b, 0x97, 0xab, 0x26, 0x55, 0xcb, 0x2f, 0x47, 0xd4, 0x77, 0xb5, 0xe4, 0x52, 0x6d, + 0x3e, 0x35, 0xca, 0x1a, 0x41, 0x26, 0x47, 0xe9, 0xf7, 0x29, 0x17, 0x6e, 0x65, 0x4c, 0xd6, 0x87, 0x83, 0x57, 0x70, + 0x53, 0xe3, 0x17, 0x39, 0x11, 0x8a, 0xda, 0x43, 0x22, 0x6c, 0xed, 0x56, 0xe8, 0xde, 0xe3, 0x46, 0x69, 0x1e, 0x65, + 0x9b, 0x58, 0x54, 0x5e, 0x2f, 0x01, 0x6b, 0x71, 0x0f, 0x78, 0x51, 0x69, 0xe9, 0x57, 0xac, 0x00, 0xf4, 0x00, 0x29, + 0x6c, 0xbc, 0x40, 0x06, 0xac, 0x77, 0x5e, 0xea, 0xf7, 0xfb, 0xc6, 0x94, 0xff, 0xee, 0x3e, 0x07, 0x92, 0x42, 0x51, + 0xd6, 0x3b, 0x98, 0x40, 0x70, 0xed, 0x24, 0xed, 0x59, 0xcd, 0x9f, 0xae, 0x6b, 0x0f, 0xf8, 0xad, 0x7c, 0x8b, 0xc4, + 0xea, 0x93, 0x7d, 0xb1, 0xd9, 0xa7, 0xd5, 0x47, 0xa3, 0x71, 0x10, 0x2c, 0xad, 0x5e, 0x69, 0x95, 0x43, 0xde, 0xf0, + 0x02, 0x44, 0x2a, 0xeb, 0xea, 0x5a, 0x39, 0x57, 0xd7, 0x82, 0x23, 0x97, 0x6c, 0xc9, 0x73, 0xf8, 0x2f, 0xe4, 0x5e, + 0x79, 0x38, 0x14, 0x7e, 0xbf, 0x9f, 0xce, 0x48, 0x2b, 0x0b, 0xec, 0x69, 0xeb, 0xda, 0x0b, 0xfd, 0xc3, 0xe1, 0x05, + 0x78, 0x8d, 0xf8, 0x87, 0x43, 0xd9, 0xef, 0x7f, 0x30, 0x37, 0x99, 0xf3, 0xb1, 0x52, 0xca, 0x5e, 0xa2, 0xd2, 0xfd, + 0x75, 0xc2, 0x7b, 0xff, 0x7b, 0xf4, 0xbf, 0x47, 0x97, 0x3d, 0xd9, 0xf5, 0x1f, 0x12, 0x3e, 0xc3, 0x1b, 0x3a, 0x53, + 0x97, 0x73, 0x26, 0xdd, 0xdd, 0x95, 0x1f, 0x7a, 0x4f, 0x43, 0xc5, 0xf7, 0xe6, 0xa6, 0x8d, 0xff, 0xa8, 0x8e, 0x34, + 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x43, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0x1c, 0x25, 0x43, 0xee, 0xe6, + 0x16, 0xa6, 0x03, 0xfb, 0x71, 0xf3, 0x55, 0xf2, 0xe2, 0x2c, 0x85, 0x6b, 0x6f, 0x3e, 0x4b, 0xe7, 0x53, 0xb0, 0xae, + 0x0c, 0xf3, 0x59, 0x3d, 0x0f, 0x20, 0x75, 0x08, 0x69, 0xd6, 0x34, 0xfc, 0x67, 0xe5, 0x0a, 0xde, 0xda, 0xe3, 0xdd, + 0xc0, 0x45, 0xa9, 0x23, 0x7d, 0xd2, 0x46, 0xd3, 0x25, 0x95, 0xfc, 0x07, 0x91, 0xc7, 0x18, 0xb3, 0xf1, 0x82, 0x78, + 0x3f, 0x8b, 0xfc, 0xba, 0x00, 0xec, 0x22, 0x00, 0x43, 0x4e, 0xe7, 0x8e, 0x24, 0xfe, 0x32, 0xf9, 0xfe, 0x8f, 0xe9, + 0xd2, 0xde, 0x97, 0xc5, 0x6d, 0x29, 0xaa, 0xea, 0xa8, 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, + 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0xe7, 0xbb, 0x57, + 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, + 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, 0xef, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, + 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, 0xfe, 0x54, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, + 0xb2, 0xbc, 0x3d, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x53, + 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, 0x9b, 0x79, 0xe2, 0x29, 0xd0, 0x31, 0x3f, 0x45, 0x57, 0xc5, + 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, 0xf1, 0xd5, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, + 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, + 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xb3, 0xb3, 0x07, + 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, + 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, + 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, + 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, + 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xc1, 0xb6, + 0xff, 0x2a, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, 0x37, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, + 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, + 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xab, 0x17, 0x67, 0x3f, 0xf6, 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xcf, 0x56, + 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, + 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, + 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, + 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x79, 0x02, 0xa1, 0x16, 0xcc, 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, + 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, + 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, 0xfd, 0x48, 0x05, 0xe5, 0xfc, 0x1f, 0xde, 0xde, 0x85, + 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, + 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, + 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, + 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0xec, 0xa5, 0x7a, 0x52, 0xae, 0x5f, 0x16, 0x8e, 0x32, + 0x65, 0x3f, 0xc4, 0x36, 0x46, 0x40, 0x75, 0xcb, 0x62, 0x13, 0x2e, 0x00, 0xb7, 0x73, 0x42, 0x9d, 0xf1, 0x1e, 0x6b, + 0x02, 0x73, 0x9a, 0x10, 0x14, 0xe6, 0x3a, 0x58, 0x18, 0x00, 0x7a, 0xd7, 0x1e, 0x6d, 0x39, 0xe9, 0x12, 0x2c, 0x9e, + 0x1b, 0x58, 0xbc, 0xba, 0x58, 0x54, 0x57, 0x5c, 0xcb, 0x2d, 0x6c, 0x4a, 0x59, 0xc5, 0x10, 0x40, 0xa0, 0x19, 0x33, + 0xec, 0x96, 0xbb, 0x1c, 0xc9, 0xba, 0x28, 0xb8, 0xd8, 0x0b, 0x0c, 0xdd, 0x8c, 0x4b, 0x66, 0x0e, 0xae, 0x66, 0x58, + 0x27, 0x15, 0x05, 0xd8, 0xd5, 0x05, 0xc8, 0x5e, 0x18, 0xea, 0xba, 0x99, 0x2d, 0xd7, 0x81, 0xaf, 0x4b, 0x17, 0xbe, + 0xa4, 0xe0, 0xe5, 0x4a, 0x8a, 0x32, 0xbb, 0xe6, 0x3f, 0xd9, 0x97, 0xcd, 0x58, 0x52, 0x68, 0x47, 0xfa, 0xba, 0xdd, + 0x1d, 0x2d, 0xc6, 0xb1, 0xe5, 0xf8, 0x96, 0x4a, 0xd7, 0x7a, 0x54, 0xbd, 0x10, 0xda, 0x3a, 0xd7, 0x32, 0x4b, 0x53, + 0x2e, 0x5e, 0x89, 0x34, 0x4b, 0xbc, 0xe4, 0x58, 0xc7, 0xaa, 0x76, 0x41, 0xb0, 0x5c, 0x98, 0xe4, 0x67, 0x59, 0x89, + 0xb1, 0x83, 0x1b, 0x8d, 0x6a, 0x45, 0x9d, 0x32, 0x31, 0x30, 0xe4, 0x7b, 0x0c, 0xbe, 0xcd, 0x8a, 0x04, 0x18, 0x7e, + 0x4c, 0xd4, 0x97, 0xf4, 0x14, 0x02, 0x3e, 0xa8, 0xd0, 0xdc, 0xcf, 0x38, 0x82, 0x5f, 0x5b, 0x95, 0x39, 0x30, 0xd9, + 0x5a, 0x05, 0x89, 0xb8, 0x77, 0xd9, 0x5c, 0x2f, 0xa2, 0x85, 0xba, 0x0b, 0xf5, 0xe2, 0xdd, 0xae, 0x97, 0x28, 0x3a, + 0xe0, 0xe4, 0xa7, 0xc1, 0x8b, 0x38, 0xcb, 0x79, 0x7a, 0x50, 0xc9, 0x03, 0xb5, 0xa1, 0x0e, 0x94, 0x33, 0x07, 0xec, + 0xbc, 0x6f, 0xab, 0x03, 0xbd, 0xa6, 0x0f, 0x74, 0x3b, 0x0f, 0xe0, 0x82, 0x81, 0x3b, 0xf7, 0x32, 0xbb, 0xe6, 0xe2, + 0x00, 0x94, 0x81, 0xd6, 0x78, 0xa0, 0x2e, 0xab, 0x91, 0x9a, 0x18, 0x1d, 0xc3, 0x3a, 0xd1, 0x07, 0x73, 0x40, 0x7f, + 0x86, 0xb0, 0xf6, 0xad, 0xb7, 0x2b, 0x7d, 0xd0, 0x06, 0xf4, 0xc5, 0xd2, 0xf4, 0x41, 0x07, 0x8e, 0x57, 0xd1, 0x81, + 0x1b, 0x43, 0xaa, 0x41, 0x5b, 0x8d, 0xac, 0x02, 0xc5, 0x1b, 0xde, 0xe2, 0xdd, 0xbb, 0x96, 0x6c, 0xbd, 0x97, 0x88, + 0xf1, 0x95, 0x89, 0x2a, 0xce, 0xc4, 0xa9, 0x97, 0xca, 0x6b, 0xed, 0x24, 0x23, 0x8c, 0x6f, 0x59, 0x49, 0xfd, 0x1d, + 0x62, 0x6e, 0x91, 0xe6, 0x30, 0x78, 0x15, 0x56, 0x64, 0xc6, 0xfb, 0x7d, 0x39, 0x93, 0x51, 0x39, 0x13, 0x87, 0x65, + 0xa4, 0xc0, 0xda, 0xee, 0x12, 0x01, 0xdd, 0x2b, 0x01, 0xf2, 0x05, 0x40, 0xd5, 0x7d, 0xc2, 0x9f, 0xfb, 0xa4, 0x3e, + 0x9d, 0x42, 0x9f, 0x42, 0x5b, 0xaf, 0xb8, 0x82, 0x78, 0x55, 0x37, 0x46, 0xb6, 0x51, 0x41, 0x8b, 0xc7, 0xf2, 0xac, + 0x36, 0x8c, 0xcd, 0xa9, 0xf5, 0xaf, 0x37, 0x1b, 0x4c, 0xd9, 0x5c, 0xa8, 0x55, 0x18, 0x92, 0xe8, 0x53, 0xe9, 0x45, + 0x12, 0xb1, 0xb0, 0x59, 0xad, 0xcd, 0x6f, 0xc2, 0x80, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, + 0x55, 0x5f, 0x6b, 0x69, 0x91, 0x69, 0xf3, 0xad, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, + 0x97, 0xb7, 0xac, 0x46, 0x98, 0x00, 0xaf, 0x74, 0x06, 0xdd, 0x68, 0x3c, 0x10, 0xcb, 0x6a, 0x54, 0xac, 0x85, 0x40, + 0xe0, 0x61, 0xc8, 0x31, 0xb3, 0x84, 0x24, 0xfb, 0xcc, 0x7f, 0x50, 0x71, 0x16, 0x8a, 0xf8, 0xc6, 0x20, 0x7b, 0x57, + 0xd6, 0xb5, 0xbb, 0x8e, 0xfc, 0x9c, 0x58, 0x58, 0xed, 0x3f, 0x34, 0x8f, 0x5a, 0xe3, 0x2c, 0xa0, 0xad, 0x69, 0x75, + 0xc3, 0xe1, 0x1e, 0xd5, 0xb1, 0x28, 0x0d, 0x36, 0xb1, 0x47, 0x96, 0x8b, 0xd6, 0x31, 0x83, 0x06, 0xf4, 0xb7, 0xd9, + 0xd5, 0xfa, 0x0a, 0x01, 0xdc, 0x4a, 0x64, 0x9d, 0xa4, 0xf2, 0x2f, 0x69, 0x8f, 0xba, 0xb6, 0xa7, 0xf2, 0xbf, 0x6d, + 0x53, 0xe5, 0xd0, 0x62, 0xca, 0x63, 0x37, 0x67, 0x81, 0xea, 0x48, 0x10, 0x05, 0x6a, 0xeb, 0x05, 0x53, 0xef, 0x94, + 0x29, 0x3a, 0x40, 0xa0, 0x0b, 0x73, 0x86, 0x7d, 0xc5, 0x11, 0x63, 0x96, 0x4a, 0x0c, 0xa6, 0x3e, 0xc6, 0xa8, 0xa6, + 0xb5, 0x02, 0x74, 0xfd, 0x74, 0x0b, 0x7f, 0xa2, 0xa2, 0x46, 0x43, 0xad, 0x91, 0x14, 0x8a, 0x26, 0x2a, 0x14, 0x59, + 0x5a, 0xe8, 0xb8, 0x0a, 0x9d, 0x44, 0xc2, 0x12, 0xd0, 0x30, 0x21, 0x3a, 0xa9, 0xc0, 0x5b, 0x03, 0x38, 0xf3, 0x71, + 0x51, 0xae, 0x0b, 0x6d, 0x30, 0xf7, 0x32, 0xbe, 0xe6, 0xaf, 0x9e, 0x39, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa7, 0x05, + 0x79, 0x19, 0x72, 0x8a, 0x0e, 0x4c, 0xec, 0x64, 0x8b, 0xc6, 0x18, 0x65, 0xad, 0xa3, 0x5e, 0xbc, 0xd5, 0xa1, 0x58, + 0xb4, 0x09, 0xde, 0x3d, 0x9e, 0x22, 0xda, 0xf0, 0x50, 0x18, 0xab, 0x6a, 0x7c, 0x2a, 0x59, 0x4b, 0x0f, 0x56, 0xf0, + 0x74, 0x9d, 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xc5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, + 0x2b, 0xf8, 0x7c, 0x81, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, 0xb8, 0x19, 0x05, 0x75, 0x74, 0x15, 0xaf, 0x1a, + 0x2a, 0x12, 0x3e, 0x2f, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, 0x95, 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0x03, + 0x5b, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, 0x99, 0x77, 0xcf, 0x8c, 0x96, 0x33, 0x8b, 0xc6, + 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x59, 0x50, 0xc4, 0x69, 0x16, 0xe7, 0xe0, 0xb7, 0x19, 0x17, 0x98, 0x31, + 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0xd0, 0x76, 0xe7, 0x2a, 0xb5, 0xae, 0x41, 0x40, 0xf6, 0x12, 0xac, 0x5e, 0x1a, 0x3a, + 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x12, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, + 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x6e, 0xf7, 0xcf, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, + 0x31, 0xf6, 0xcf, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, + 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, + 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, + 0x58, 0x87, 0xdb, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, + 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, + 0x14, 0xb6, 0xc5, 0x6e, 0xa7, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, 0x51, 0xfc, 0x27, 0xf7, 0xc2, 0x4e, + 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x4f, 0x0e, 0x17, 0x89, 0x1f, 0xa4, 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, + 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x9e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, + 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, + 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, + 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, + 0x71, 0xac, 0x89, 0x6a, 0xc1, 0x8f, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, + 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, + 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, + 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, + 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, + 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0x77, 0x0f, 0x09, 0x55, 0x71, 0x6f, 0x78, 0x3b, 0xee, 0x8d, 0x13, 0x7e, 0xcd, + 0xc5, 0x42, 0x87, 0x6a, 0x31, 0x97, 0x2c, 0xbf, 0xb5, 0xde, 0x2d, 0x49, 0x6a, 0x05, 0xb4, 0xcf, 0xb2, 0xa0, 0x26, + 0x02, 0x40, 0xfe, 0xf0, 0x17, 0x08, 0x9d, 0xe1, 0x6f, 0x8f, 0xc1, 0x15, 0x29, 0xbc, 0x73, 0x08, 0x84, 0x35, 0xdd, + 0xdc, 0xab, 0x0d, 0xf8, 0x62, 0xdc, 0x9f, 0x31, 0xf5, 0xf4, 0xdb, 0x4c, 0xee, 0xeb, 0xba, 0x3d, 0xb2, 0x0c, 0x1f, + 0xe1, 0x4a, 0x01, 0xdc, 0x4c, 0xf8, 0x8b, 0x61, 0x26, 0xd5, 0x27, 0x80, 0xa9, 0xa6, 0x83, 0xfb, 0x04, 0x81, 0x01, + 0x54, 0xa2, 0xc5, 0xe8, 0x5a, 0x39, 0xa2, 0x19, 0xb8, 0x35, 0xdd, 0x0a, 0xe3, 0xad, 0x07, 0x2d, 0xf4, 0x4c, 0xc3, + 0x89, 0xff, 0xa0, 0x99, 0x57, 0x05, 0x04, 0xd0, 0xca, 0x08, 0xde, 0x5a, 0x9f, 0xcc, 0x11, 0xe2, 0x13, 0x96, 0x44, + 0x13, 0x16, 0xcf, 0x14, 0x3f, 0x26, 0x74, 0xdb, 0xd4, 0x36, 0x7d, 0x44, 0xfa, 0x8b, 0x6b, 0xd6, 0x4f, 0x59, 0xd6, + 0xbe, 0x3d, 0x54, 0xbc, 0x98, 0x36, 0xe3, 0x20, 0x26, 0xaa, 0x18, 0xff, 0x0b, 0xee, 0x4b, 0xad, 0x00, 0x91, 0xb9, + 0xab, 0x9e, 0x7e, 0xbf, 0x99, 0x2d, 0x07, 0x42, 0xe5, 0x77, 0x06, 0x49, 0x9f, 0x0e, 0xed, 0x07, 0x36, 0x89, 0xda, + 0x42, 0xcf, 0x1f, 0x97, 0xba, 0x89, 0x97, 0xd7, 0xa6, 0x46, 0xb4, 0x42, 0x86, 0xca, 0xd6, 0x01, 0xeb, 0xfb, 0x65, + 0xb8, 0xbf, 0xa8, 0x69, 0xa8, 0x75, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x7f, 0x80, 0xb1, 0xb8, 0x90, 0xd4, 0x3a, 0x1e, + 0x93, 0x7e, 0xb4, 0x90, 0xc9, 0x8d, 0xba, 0x3a, 0x39, 0x53, 0xcc, 0x13, 0xb8, 0x00, 0x97, 0x6d, 0x7f, 0x45, 0xa5, + 0x2e, 0xe5, 0xf6, 0x8a, 0xd2, 0xf4, 0x90, 0xb6, 0x57, 0x71, 0xde, 0x16, 0x5c, 0xf0, 0xaf, 0x14, 0x5c, 0x58, 0x07, + 0xeb, 0x8e, 0x3b, 0x65, 0x4f, 0x78, 0xa2, 0x4c, 0x6b, 0x83, 0xbb, 0x6e, 0x30, 0x26, 0xc6, 0x7e, 0x77, 0xc9, 0x93, + 0x4f, 0xc8, 0x82, 0xff, 0x90, 0x09, 0xf0, 0x4c, 0x76, 0xaf, 0x54, 0xfe, 0x97, 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, + 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xbd, 0x92, 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, + 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0x3b, 0x09, 0xdc, 0xf4, 0xee, 0xda, 0xcc, 0xcc, + 0xe9, 0x5a, 0x89, 0xa6, 0x4b, 0x63, 0x6b, 0x59, 0xaa, 0x30, 0xde, 0xef, 0x3c, 0xc9, 0xa6, 0xf9, 0xf1, 0x72, 0x9a, + 0x5b, 0xea, 0xb6, 0x75, 0xcb, 0x06, 0xd0, 0x10, 0xbb, 0xd6, 0x56, 0x0e, 0x78, 0xb9, 0x3d, 0x88, 0xe6, 0x6b, 0x45, + 0xe8, 0xa9, 0x12, 0xa1, 0x4f, 0xd3, 0x66, 0x1f, 0xec, 0xaa, 0x5a, 0x37, 0x42, 0x1e, 0x0d, 0x52, 0xcd, 0xc8, 0xbf, + 0xbd, 0xe6, 0xc5, 0x45, 0x2e, 0x6f, 0x00, 0x0e, 0x99, 0xd4, 0x46, 0x61, 0x79, 0x05, 0xee, 0xfc, 0xe8, 0x38, 0xce, + 0xc4, 0x28, 0xc7, 0xb8, 0xad, 0x88, 0x94, 0xac, 0x13, 0x67, 0x80, 0x87, 0xec, 0x4f, 0x9a, 0x0e, 0xed, 0x5a, 0x60, + 0x78, 0x5f, 0xe0, 0xae, 0x72, 0x76, 0xb2, 0xcd, 0xed, 0xa2, 0x6f, 0xce, 0xb0, 0xee, 0x48, 0x69, 0x6d, 0x2c, 0xba, + 0xee, 0x60, 0xad, 0x19, 0xb4, 0x45, 0x28, 0xf9, 0x90, 0x3b, 0x69, 0x3f, 0x07, 0x34, 0x38, 0xcb, 0xd2, 0x5b, 0x6b, + 0x95, 0xbf, 0xd5, 0x42, 0x9c, 0x28, 0xa6, 0x4e, 0x7c, 0x13, 0x25, 0xfa, 0xfc, 0x4c, 0x8c, 0x1b, 0x08, 0xa4, 0xbe, + 0xc4, 0xf8, 0x1a, 0x45, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xed, 0x89, 0xda, 0x58, 0x8e, 0xa0, 0x13, 0x42, 0xbc, 0x83, + 0x32, 0x8c, 0xd5, 0xc5, 0x81, 0x36, 0x58, 0xfa, 0xba, 0xb5, 0xce, 0x0d, 0xa1, 0x30, 0x4e, 0x60, 0x8a, 0x41, 0x52, + 0x67, 0x9d, 0x65, 0x82, 0x2a, 0x3b, 0x26, 0x9d, 0xf7, 0x01, 0xba, 0xbf, 0x16, 0x4d, 0xf1, 0x75, 0xe7, 0x0e, 0xba, + 0x8b, 0xeb, 0xd7, 0x5a, 0xe4, 0x06, 0x7f, 0xde, 0x12, 0x61, 0x11, 0x38, 0x6b, 0x4d, 0xbe, 0x6a, 0x84, 0x03, 0x53, + 0x92, 0x69, 0xd8, 0xcb, 0x95, 0x4d, 0xf7, 0x6e, 0xd7, 0xeb, 0xdd, 0x29, 0xe2, 0xea, 0x31, 0x56, 0x79, 0x37, 0x73, + 0x7b, 0xa7, 0x5a, 0x8b, 0xfd, 0x9b, 0xb6, 0x9f, 0x62, 0x47, 0xad, 0xb5, 0xdb, 0x0d, 0x27, 0xd4, 0x90, 0x6f, 0x45, + 0x95, 0x56, 0xa7, 0x1b, 0x83, 0x76, 0x08, 0x6d, 0x2d, 0x32, 0xb8, 0x51, 0x3e, 0x73, 0x42, 0x27, 0x15, 0x72, 0xd5, + 0xa9, 0x0b, 0xb6, 0x57, 0xbc, 0x5a, 0xca, 0x34, 0x12, 0x14, 0x6d, 0xce, 0xa3, 0x92, 0x26, 0x72, 0x2d, 0xaa, 0x48, + 0xd6, 0xa8, 0x17, 0xb5, 0x1a, 0x03, 0x04, 0x64, 0x3a, 0x6b, 0x7a, 0x50, 0x05, 0xb3, 0xa1, 0x8c, 0xe4, 0xf4, 0x0d, + 0x58, 0xda, 0x23, 0xc7, 0x5a, 0xdf, 0x55, 0x67, 0x8b, 0x6f, 0xf5, 0x84, 0x60, 0x0a, 0xb3, 0x07, 0x22, 0xc2, 0x35, + 0x8d, 0x21, 0xa7, 0x5d, 0xe2, 0xb2, 0xa6, 0x5b, 0xc2, 0x1d, 0xdc, 0xae, 0x64, 0x27, 0x6e, 0x9e, 0x34, 0x37, 0x57, + 0xb0, 0x93, 0x62, 0x3e, 0x06, 0xed, 0x97, 0x54, 0xd7, 0x2e, 0xcd, 0xad, 0xc7, 0x83, 0x80, 0x06, 0x83, 0xc2, 0xf0, + 0xaf, 0x13, 0xe3, 0xe1, 0x49, 0x03, 0x82, 0xa4, 0x5c, 0x84, 0x63, 0xdf, 0x88, 0x7e, 0x32, 0x95, 0xc7, 0x1c, 0x2d, + 0xde, 0xa1, 0xd5, 0x39, 0x04, 0xf4, 0x12, 0xa1, 0x24, 0x46, 0x55, 0x68, 0x44, 0x50, 0x9e, 0x96, 0xbf, 0x54, 0xd5, + 0x21, 0xa0, 0x90, 0xf6, 0x15, 0x85, 0xb2, 0x4d, 0x62, 0x68, 0x86, 0x5f, 0xce, 0x27, 0x0b, 0x3d, 0x03, 0x03, 0x39, + 0x3f, 0x5a, 0xe8, 0x59, 0x18, 0xc8, 0xf9, 0xa3, 0x45, 0xed, 0xd6, 0x81, 0x26, 0x20, 0x9e, 0x0b, 0x47, 0x27, 0xa5, + 0x55, 0xd9, 0x02, 0xba, 0xbd, 0x8f, 0xa0, 0xff, 0xd3, 0x1e, 0x82, 0x4e, 0x2e, 0xb4, 0x27, 0x37, 0xa0, 0xed, 0x90, + 0x04, 0xf6, 0x8a, 0x49, 0x85, 0x89, 0x45, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0xad, 0x3e, 0x38, 0x66, 0xe3, 0xa9, 0x4f, + 0x82, 0x80, 0xd1, 0x7d, 0x69, 0xc0, 0xc1, 0x6f, 0xf1, 0x2a, 0x7d, 0xb2, 0x15, 0xe8, 0xa6, 0xef, 0xee, 0x86, 0xde, + 0xc5, 0x15, 0x9c, 0xaa, 0xdd, 0x3d, 0x09, 0xdd, 0x64, 0xda, 0xb1, 0x7a, 0x0d, 0x71, 0x43, 0x7e, 0x65, 0x34, 0x1a, + 0xd9, 0x94, 0x90, 0x10, 0xc3, 0x39, 0x34, 0x73, 0x5a, 0x2e, 0x5f, 0xdd, 0x7a, 0xb6, 0x20, 0xc3, 0x4c, 0x6f, 0x99, + 0xac, 0xef, 0xa1, 0xac, 0x7a, 0x0c, 0xed, 0xd0, 0x7b, 0xe4, 0xf8, 0xfe, 0xc1, 0x37, 0x19, 0xbf, 0x70, 0xb8, 0xf6, + 0x70, 0x2e, 0x7c, 0x97, 0x35, 0x23, 0x73, 0xe8, 0x3c, 0xfb, 0x38, 0xde, 0xc3, 0x38, 0xf9, 0x32, 0x0b, 0xe5, 0x8d, + 0xd7, 0xf4, 0xbf, 0x55, 0x7a, 0xb3, 0xc3, 0x21, 0xa7, 0x2b, 0x58, 0x71, 0xb3, 0x2a, 0x34, 0xfc, 0x2c, 0xf2, 0xc6, + 0x11, 0xaf, 0x49, 0x54, 0x75, 0x9f, 0xf7, 0x36, 0x62, 0x69, 0xc7, 0x38, 0x00, 0x38, 0x51, 0xab, 0x86, 0x7d, 0x69, + 0x5c, 0xab, 0x83, 0x18, 0x91, 0x12, 0xb6, 0x4a, 0x1c, 0x09, 0xe5, 0x6f, 0x00, 0xc2, 0x62, 0x28, 0x8e, 0xb7, 0x86, + 0xf5, 0x1e, 0xf6, 0x43, 0x17, 0x68, 0x9a, 0x53, 0xaa, 0x19, 0x00, 0x24, 0x01, 0x7f, 0xf4, 0x74, 0xd3, 0x50, 0xd9, + 0xe6, 0x79, 0x68, 0x59, 0x5d, 0xc1, 0x3d, 0x3d, 0x75, 0x25, 0x03, 0xe3, 0xaa, 0x8e, 0xbd, 0xed, 0xdd, 0xed, 0xd1, + 0x2a, 0xf2, 0xbd, 0x4d, 0x6a, 0x9a, 0x05, 0x90, 0xa2, 0x71, 0xe9, 0x0b, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, + 0xf6, 0xfb, 0x28, 0x46, 0x8d, 0x0b, 0x05, 0x56, 0x61, 0x82, 0xc2, 0x21, 0xc2, 0x08, 0xa1, 0x3f, 0x97, 0xe1, 0xd6, + 0x17, 0x64, 0x10, 0x0d, 0xd7, 0xa2, 0x43, 0x11, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, + 0x22, 0x03, 0xb6, 0xf3, 0x4f, 0x1b, 0x22, 0x57, 0xe1, 0x02, 0x86, 0xef, 0x89, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, + 0x1b, 0x76, 0x88, 0x8e, 0xa6, 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x81, 0xdc, 0x35, 0x9d, + 0xbd, 0x14, 0x61, 0x50, 0xb7, 0x6c, 0xa0, 0x58, 0xc7, 0x4e, 0x50, 0x80, 0x01, 0x5c, 0x3e, 0x03, 0x1d, 0x1b, 0x0c, + 0x2a, 0x82, 0x4f, 0x0a, 0xdb, 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0x2f, + 0x94, 0x70, 0xf7, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf3, 0x5c, 0x6b, 0x4a, + 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, 0x51, 0xe5, 0xb1, 0x44, 0x91, + 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, 0xb4, 0xcb, 0x96, 0xb9, 0x04, + 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x3d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x47, 0x4d, + 0xbf, 0x7a, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x9f, 0xb0, 0xf1, 0x74, + 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x0a, 0x5a, 0x67, 0x26, 0xae, 0xf1, 0x69, 0xfb, 0x0a, 0x5a, + 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, 0xa9, 0x64, 0x7f, 0x2e, 0xad, + 0xc3, 0xbe, 0x5d, 0x28, 0xb4, 0xd0, 0xc4, 0xaf, 0x32, 0xc4, 0x4f, 0x5d, 0x67, 0xfe, 0x63, 0xda, 0xa7, 0x06, 0xb1, + 0x70, 0x24, 0x06, 0x11, 0xbf, 0x38, 0x55, 0xb6, 0x13, 0x42, 0xc5, 0xc6, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0x18, + 0x4a, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, 0x0b, 0x1d, 0xbe, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, + 0x9c, 0x4a, 0xb9, 0x8a, 0x04, 0x06, 0xca, 0xb3, 0x85, 0x41, 0x80, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0x84, 0xb1, + 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, + 0x71, 0x94, 0x6a, 0xfc, 0x47, 0x84, 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x09, 0x84, 0x40, + 0x73, 0xf6, 0x53, 0x71, 0xb5, 0x37, 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xaa, 0x2e, 0x50, + 0x2f, 0x64, 0xf1, 0x5a, 0xa6, 0xbc, 0x15, 0x22, 0xf3, 0x40, 0xb2, 0xf7, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, + 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x88, 0x33, 0xb6, + 0x77, 0x12, 0x6e, 0xef, 0xe6, 0x81, 0x21, 0x4a, 0xb9, 0x68, 0x89, 0x86, 0xad, 0x1d, 0xaf, 0x27, 0xd7, 0x84, 0xfb, + 0xb0, 0x11, 0x6b, 0x32, 0xc6, 0xb8, 0x36, 0x37, 0xb2, 0x7e, 0xb4, 0xc0, 0x83, 0x31, 0x65, 0xfd, 0x09, 0x64, 0x5a, + 0x49, 0x59, 0xe7, 0x0b, 0x23, 0x66, 0x52, 0x89, 0xde, 0xed, 0x1b, 0x9f, 0xd5, 0x5d, 0x44, 0xfd, 0xd6, 0x7e, 0x4f, + 0xea, 0x61, 0xe3, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, 0x37, 0x4d, 0x8a, 0x38, 0x3d, + 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, 0x24, 0x49, 0xd6, 0xd2, 0xd8, + 0x8a, 0x5d, 0x1a, 0xa4, 0xe7, 0xce, 0x88, 0x4b, 0x2f, 0x2a, 0x34, 0xa4, 0xa5, 0xde, 0x59, 0xa8, 0x64, 0xfe, 0x8a, + 0xff, 0x0c, 0x6a, 0x05, 0x3a, 0xda, 0xa4, 0x18, 0x4f, 0x81, 0x11, 0xdf, 0x0f, 0x66, 0x75, 0x0f, 0x71, 0xd1, 0x04, + 0xa5, 0xde, 0x13, 0x3b, 0x7e, 0x69, 0xf2, 0xf0, 0x2e, 0xe4, 0x9c, 0xc1, 0xa7, 0xf7, 0xb3, 0x44, 0xad, 0x75, 0x24, + 0x46, 0x6a, 0x06, 0xd0, 0x74, 0x50, 0xe6, 0x3c, 0x16, 0xc1, 0xac, 0x67, 0x12, 0xa3, 0x1e, 0xd7, 0xbf, 0x40, 0x43, + 0xed, 0x37, 0x2b, 0xcb, 0xb3, 0x6a, 0xf3, 0x35, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, 0x75, 0x25, 0x2f, 0x2f, 0x55, + 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, 0x37, 0x8b, 0xbb, 0x59, 0x46, + 0x03, 0x61, 0x6d, 0xef, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, 0x00, 0x10, 0xe9, 0x41, 0x14, + 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xde, 0xc5, 0x51, 0x16, 0x4a, 0x2f, 0x67, 0x19, 0x3f, 0x6d, 0x1a, 0x6b, 0x9d, 0x15, + 0xca, 0xd0, 0xda, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, 0x49, 0x9c, 0x2d, 0xc0, 0xfd, 0x31, 0x43, 0xa1, 0xa1, 0xb3, + 0x8c, 0x34, 0xd1, 0xf0, 0x5d, 0x77, 0x0c, 0x32, 0x8a, 0x93, 0x75, 0x5e, 0x49, 0xb7, 0xfa, 0xac, 0x8d, 0x84, 0xb9, + 0x87, 0xe8, 0x57, 0x31, 0x78, 0x94, 0xfb, 0xbc, 0x36, 0x3a, 0x99, 0x96, 0x91, 0x76, 0xe7, 0x27, 0xf5, 0x32, 0x4b, + 0xb5, 0x0e, 0xdb, 0x67, 0xd8, 0x5b, 0x63, 0xd2, 0x9b, 0x90, 0x1a, 0x46, 0xe2, 0xcb, 0x19, 0x35, 0x42, 0x40, 0x5b, + 0x8e, 0xbf, 0xc7, 0x67, 0x18, 0x9a, 0x02, 0x4b, 0x15, 0xb7, 0xb0, 0x1b, 0xbe, 0xe6, 0x93, 0x55, 0x0b, 0x40, 0x30, + 0x2b, 0x5f, 0xef, 0xe2, 0x95, 0x50, 0x9f, 0x69, 0x33, 0x00, 0x64, 0x41, 0x29, 0x77, 0xfc, 0x94, 0x4a, 0x07, 0x4b, + 0x14, 0x6d, 0x2f, 0xa7, 0x6f, 0x74, 0x6c, 0x7c, 0x9f, 0x9e, 0x0b, 0xd8, 0x2e, 0xe4, 0xb7, 0xee, 0xd4, 0x4b, 0x54, + 0xa4, 0xb6, 0xcd, 0xba, 0x87, 0x2f, 0x37, 0x68, 0x12, 0x46, 0x50, 0xa6, 0x4c, 0x01, 0x0c, 0x6e, 0xaa, 0x51, 0x30, + 0x69, 0x35, 0x12, 0xb6, 0xd4, 0x93, 0x2c, 0x37, 0x7d, 0x70, 0xaa, 0x3b, 0x04, 0x3d, 0xb7, 0xca, 0xf9, 0xa2, 0x65, + 0xbf, 0x56, 0x70, 0x74, 0x72, 0x35, 0x44, 0xcd, 0xbc, 0xd7, 0x76, 0x64, 0x48, 0xb9, 0x0c, 0x03, 0xc1, 0x94, 0x63, + 0x9e, 0x1e, 0x5b, 0xcf, 0x88, 0xe8, 0x9e, 0xb3, 0xcf, 0x74, 0xab, 0xae, 0x24, 0x20, 0x3a, 0x7e, 0xf7, 0xf8, 0xd5, + 0x55, 0x7c, 0x69, 0x50, 0x94, 0x1a, 0x16, 0x31, 0xca, 0xb4, 0xaf, 0x92, 0x30, 0x78, 0xbf, 0xbc, 0xff, 0x49, 0x65, + 0xa9, 0xfd, 0x1e, 0x6c, 0xad, 0xa8, 0xea, 0x97, 0x92, 0x17, 0x4d, 0x01, 0xd6, 0x5d, 0x96, 0x28, 0x90, 0xfb, 0xbd, + 0x4d, 0x33, 0xdf, 0x44, 0x8d, 0x9b, 0x0d, 0xeb, 0x8d, 0xeb, 0x76, 0xa9, 0x2d, 0xd9, 0x91, 0x95, 0xc8, 0x99, 0xc5, + 0x60, 0xc6, 0x8f, 0x0a, 0x83, 0xd2, 0xb0, 0x45, 0x55, 0x2a, 0x7e, 0x6f, 0x44, 0x70, 0xea, 0x58, 0x55, 0x18, 0xd3, + 0x80, 0xd9, 0x56, 0xd4, 0x1a, 0xd4, 0x41, 0x29, 0x6d, 0x4d, 0x40, 0xb6, 0x7f, 0xb1, 0x82, 0x9a, 0xdf, 0xff, 0x36, + 0x86, 0x7c, 0x4d, 0x29, 0xa8, 0x24, 0x60, 0x67, 0xd0, 0xe8, 0xa9, 0x12, 0x06, 0x52, 0x10, 0x3c, 0x01, 0xca, 0x17, + 0x51, 0x63, 0xb5, 0xdf, 0x57, 0xa7, 0xc6, 0x68, 0x0b, 0x08, 0x2d, 0xa4, 0x47, 0x97, 0x7d, 0xdc, 0xd6, 0x3a, 0x90, + 0x78, 0x70, 0x82, 0xed, 0x5c, 0x5d, 0xa3, 0x91, 0xd0, 0xfc, 0xbe, 0xd1, 0x80, 0xd7, 0xb4, 0x02, 0x85, 0x7a, 0x8e, + 0xa3, 0xa1, 0xb3, 0x43, 0x0a, 0x22, 0x36, 0x68, 0x61, 0xdf, 0x1d, 0x1f, 0x9a, 0x7d, 0x3d, 0x4f, 0x16, 0xa4, 0xa6, + 0xd2, 0x7d, 0xee, 0x96, 0x90, 0xb5, 0xea, 0x50, 0x56, 0x1e, 0xe0, 0x78, 0xa1, 0x64, 0xfe, 0x0e, 0x93, 0x1a, 0xa5, + 0x31, 0xa1, 0x31, 0x62, 0x01, 0x4b, 0x82, 0xf6, 0x7a, 0xa0, 0x7e, 0x19, 0x84, 0x0a, 0x67, 0x7a, 0x22, 0xf1, 0x29, + 0xe5, 0xea, 0xd3, 0x82, 0xd4, 0xd3, 0x82, 0x39, 0xd0, 0x4b, 0xdf, 0xca, 0xaf, 0x6c, 0x7c, 0xb4, 0xbf, 0x77, 0xcd, + 0x85, 0x75, 0x0c, 0x71, 0xb1, 0x85, 0xdf, 0x9c, 0x9a, 0x02, 0xb0, 0xe1, 0xa9, 0x2e, 0xcb, 0x37, 0x6a, 0x22, 0xb3, + 0x38, 0x24, 0x11, 0x48, 0xb6, 0x9b, 0x9b, 0xdb, 0x08, 0xb6, 0xbd, 0x85, 0xda, 0x50, 0x7f, 0x79, 0xdb, 0xfd, 0x8e, + 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xf2, 0xee, 0x55, 0xf2, 0x7f, 0x55, 0xc9, 0xdd, 0x56, 0x99, 0x75, + 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, 0x35, 0x05, 0x06, 0xd2, 0x93, 0xc6, 0x34, 0xd1, 0xd1, 0x95, + 0x19, 0x33, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, 0xc7, 0x00, 0x1c, 0xe0, 0x1f, 0x79, 0x84, 0xfa, 0xa7, 0xf3, + 0x3c, 0x38, 0x0b, 0x06, 0xe5, 0x20, 0xd0, 0x9f, 0xb8, 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0xe2, 0x4e, 0x5a, + 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, 0x02, 0x48, 0x5f, 0xbc, 0xb0, 0xce, 0x41, 0x85, 0x5e, 0x90, + 0xad, 0xba, 0x8b, 0x66, 0xc5, 0x5e, 0xb5, 0xd3, 0xbc, 0xdf, 0xcf, 0xe7, 0xe5, 0x20, 0x68, 0x54, 0x58, 0x18, 0xef, + 0x3f, 0xda, 0xfc, 0xd2, 0xe8, 0xa4, 0x09, 0x46, 0xac, 0x3d, 0x45, 0xf5, 0x8a, 0xa7, 0x19, 0x6d, 0xdc, 0x8e, 0x95, + 0xf2, 0x05, 0x44, 0xf1, 0xc0, 0x90, 0xb5, 0xf2, 0xee, 0x1d, 0xbc, 0x2e, 0x37, 0xde, 0x1c, 0x51, 0x80, 0xdd, 0x14, + 0xc6, 0x49, 0xcd, 0x45, 0x17, 0x35, 0xf1, 0x0c, 0x76, 0xba, 0x7a, 0x2b, 0xd1, 0x6a, 0xbc, 0x17, 0xef, 0x9b, 0x8d, + 0xbf, 0x91, 0x07, 0xba, 0xcc, 0x83, 0x0b, 0x40, 0x9c, 0x3d, 0x88, 0xab, 0x03, 0x2c, 0xf5, 0x20, 0x18, 0x58, 0xe4, + 0x90, 0x76, 0xb5, 0x7a, 0x28, 0x22, 0x75, 0x1e, 0x83, 0x01, 0x93, 0x69, 0x48, 0x4d, 0xa6, 0xbd, 0x58, 0x41, 0xda, + 0x58, 0x6b, 0x01, 0x6d, 0x38, 0x2c, 0xf6, 0xec, 0x86, 0xdd, 0xe9, 0xd6, 0xa1, 0x50, 0xc2, 0x40, 0xd6, 0x75, 0xf3, + 0x50, 0x6b, 0x78, 0x22, 0xe8, 0x41, 0x35, 0xda, 0x4f, 0x0f, 0xe5, 0x49, 0x7b, 0x2c, 0xc0, 0x45, 0x0f, 0x5f, 0x3e, + 0x17, 0x78, 0xd1, 0xde, 0x43, 0x9e, 0x33, 0x9f, 0x2a, 0x1f, 0xc4, 0x86, 0x5b, 0x86, 0x0f, 0xed, 0xe3, 0x5b, 0x81, + 0x4c, 0xea, 0x8e, 0xa6, 0xb6, 0x76, 0x47, 0xe3, 0x98, 0x40, 0xbf, 0x29, 0x47, 0x29, 0x13, 0x53, 0xcb, 0x92, 0x9d, + 0xf4, 0x72, 0xe5, 0x0d, 0x95, 0xb2, 0x93, 0x65, 0x9b, 0xf3, 0x4b, 0x1b, 0x09, 0xfd, 0xbe, 0x76, 0x07, 0xc2, 0x37, + 0x6a, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, 0xf1, 0x42, 0x2a, 0xd7, 0xee, 0xa2, 0xa9, 0xaa, 0xdb, + 0xdb, 0xca, 0x05, 0x2d, 0xf1, 0x56, 0x0a, 0xac, 0x22, 0x75, 0x7a, 0x3d, 0x95, 0x78, 0xd7, 0x47, 0xb1, 0xfd, 0x08, + 0xd8, 0xc6, 0xc6, 0xd1, 0xd8, 0xb8, 0x45, 0x6c, 0xf1, 0x55, 0x54, 0xd1, 0x82, 0x03, 0x04, 0x77, 0x5b, 0x52, 0x4b, + 0x33, 0x87, 0xb8, 0xaf, 0x78, 0x80, 0xf6, 0x5d, 0x1c, 0xce, 0xa4, 0x02, 0x6c, 0xeb, 0x5a, 0xe7, 0xac, 0x96, 0x03, + 0x36, 0x13, 0x3d, 0xff, 0xb4, 0x6a, 0x24, 0x62, 0x58, 0x65, 0x23, 0x65, 0x85, 0x76, 0xaf, 0x74, 0x09, 0x17, 0x5f, + 0x80, 0x97, 0xed, 0xbb, 0x95, 0xdd, 0x67, 0x4b, 0xec, 0x1f, 0xe6, 0x55, 0x13, 0x3c, 0xf2, 0x1a, 0x6f, 0xef, 0x61, + 0xe2, 0x6b, 0xa5, 0x10, 0x5e, 0xa5, 0x34, 0x94, 0x00, 0x0c, 0x92, 0xa0, 0x86, 0x2b, 0x6d, 0x9b, 0x41, 0x2a, 0x63, + 0xd8, 0xfd, 0xea, 0xad, 0xfe, 0x4f, 0xab, 0x70, 0x51, 0xc9, 0x62, 0x4c, 0x02, 0x9d, 0x53, 0x2d, 0x37, 0x81, 0x05, + 0xcf, 0xf6, 0xc9, 0x11, 0x28, 0xec, 0x04, 0x70, 0x43, 0x09, 0xfb, 0x0b, 0x6f, 0x43, 0x39, 0xfb, 0x6c, 0x25, 0x4f, + 0x6e, 0x5f, 0x52, 0x41, 0x13, 0x32, 0x15, 0x76, 0xff, 0xb6, 0x36, 0xec, 0xb3, 0x50, 0x8e, 0xa4, 0xc0, 0xc5, 0x41, + 0xe7, 0x00, 0xf6, 0x07, 0xb9, 0x8c, 0xcd, 0x67, 0xd2, 0xef, 0xab, 0xf7, 0x4f, 0xf3, 0x2c, 0xf9, 0xb4, 0xf7, 0xde, + 0xf0, 0x34, 0x4b, 0x06, 0x54, 0x22, 0xa6, 0xd6, 0x55, 0x31, 0x5c, 0x6a, 0x17, 0xe3, 0x06, 0xc9, 0x88, 0xef, 0xa4, + 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x3d, 0x92, 0x92, 0xd3, 0x65, 0xdd, 0xd9, 0x73, 0x2d, 0x9a, 0x41, 0x63, 0xb8, 0x3d, + 0xef, 0x25, 0xbd, 0x02, 0x54, 0x80, 0xe8, 0x9e, 0x05, 0xae, 0xe1, 0xcd, 0x25, 0xd1, 0xd8, 0xd2, 0xd3, 0x96, 0x68, + 0xe0, 0x4e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x14, 0x16, 0x00, 0xd4, 0x6a, 0x90, 0x5e, 0xe9, + 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, 0x03, 0xfa, 0xaa, + 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x4f, 0x4b, 0x93, 0x04, 0x82, + 0x12, 0x94, 0x6f, 0xd0, 0xdf, 0x4b, 0xcf, 0xc7, 0xf2, 0x1f, 0xde, 0xa1, 0xf4, 0x32, 0x2c, 0x40, 0xa6, 0xa8, 0x2b, + 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, 0x59, 0x86, 0x38, + 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, 0x4a, 0x20, 0xca, + 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, 0xa4, 0x99, 0x5d, + 0x87, 0x11, 0xa9, 0xf6, 0x92, 0xcc, 0x97, 0xff, 0x90, 0x99, 0xf0, 0xbe, 0x81, 0xc7, 0x66, 0xb3, 0x6c, 0x8a, 0xf9, + 0x42, 0x05, 0x73, 0x70, 0x9f, 0xa8, 0xb8, 0x14, 0x95, 0xff, 0x84, 0x5d, 0xf0, 0x62, 0x3c, 0x78, 0xbd, 0x46, 0x80, + 0xfd, 0xca, 0x7f, 0xf2, 0xc6, 0xec, 0x07, 0xeb, 0xc6, 0x97, 0x99, 0x88, 0x0f, 0x7c, 0x74, 0x4b, 0xf9, 0x68, 0xe3, + 0x65, 0xfa, 0xb5, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x93, 0x44, 0xd9, 0xa8, 0xe2, 0x02, + 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x82, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, 0x61, 0x99, 0xa9, + 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x9f, 0x92, 0xe8, 0x87, 0xa5, 0x07, 0x22, 0x67, 0xa6, 0x6c, 0x5b, 0x3b, + 0x42, 0x6d, 0x7c, 0x1d, 0xe9, 0x56, 0x5b, 0x00, 0xc0, 0x3d, 0x5b, 0xa4, 0x91, 0x64, 0x62, 0x38, 0xa9, 0x19, 0x37, + 0xe9, 0x05, 0xa6, 0xc6, 0x35, 0xab, 0x68, 0xe2, 0x2c, 0x64, 0x40, 0xef, 0x4f, 0x73, 0xfd, 0x9c, 0xc1, 0xfd, 0x07, + 0xad, 0x81, 0xcb, 0xe3, 0xa2, 0xdf, 0x97, 0xc7, 0xc5, 0x6e, 0x57, 0x9e, 0xc4, 0xfd, 0xbe, 0x3c, 0x89, 0x0d, 0xff, + 0xa0, 0x14, 0xdb, 0xc6, 0xdc, 0x20, 0xa1, 0xb9, 0x84, 0xa8, 0x45, 0x23, 0xf8, 0x43, 0xb3, 0x9c, 0x8b, 0x28, 0x3f, + 0x4e, 0xfa, 0xfd, 0xde, 0x72, 0x26, 0x06, 0xf9, 0x30, 0x89, 0xf2, 0x61, 0xe2, 0x39, 0x21, 0xbe, 0xf4, 0x9c, 0x10, + 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, 0xab, 0x5a, 0x12, + 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0xfd, 0xba, 0x04, 0x9e, 0x28, 0xe7, 0xd5, 0x16, 0x18, + 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x6d, 0x4d, 0x2f, 0xe8, 0x8a, 0x5e, 0x22, 0x3f, + 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, 0xc2, 0xf5, 0x2c, + 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x53, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x65, 0x10, 0xde, 0x2f, 0x9d, 0x85, + 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, 0x97, 0x74, 0x45, + 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, 0x55, 0xe1, 0x5d, + 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x69, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, 0x66, 0x64, 0x24, + 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, 0xdc, 0xfd, 0x92, + 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, 0x38, 0xb0, 0x07, + 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x23, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, 0xc4, 0x2b, 0x70, + 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, 0x2b, 0x95, 0x7e, + 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, 0x17, 0xa3, 0x0d, + 0x01, 0x0b, 0xaf, 0xf1, 0x74, 0x7d, 0xcc, 0xe2, 0xe9, 0x60, 0xb0, 0x46, 0xaa, 0xae, 0x72, 0xaf, 0xc9, 0x82, 0x5e, + 0xe0, 0x44, 0x10, 0x60, 0xe8, 0x33, 0xb1, 0x36, 0x34, 0xfc, 0x29, 0x83, 0x8f, 0x37, 0xec, 0x62, 0xb4, 0xa1, 0xb7, + 0xec, 0xe9, 0x6e, 0x3c, 0x05, 0x66, 0x6a, 0x35, 0x0b, 0x37, 0xc7, 0x97, 0xb3, 0x4b, 0xb6, 0x89, 0x36, 0x27, 0xd0, + 0xd0, 0x2b, 0xb6, 0x41, 0xc0, 0xa5, 0xf4, 0xe1, 0x72, 0xf0, 0x94, 0x1c, 0x0e, 0x06, 0x29, 0x89, 0xc2, 0xeb, 0xd0, + 0x6b, 0xe5, 0x53, 0xba, 0x21, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, 0x36, 0xf5, 0x75, 0xe8, + 0xed, 0xe6, 0x5c, 0x74, 0x82, 0x18, 0xa1, 0xaf, 0x81, 0xa3, 0x59, 0x2e, 0xcc, 0x04, 0x3c, 0x99, 0x8b, 0x8c, 0x16, + 0x85, 0x66, 0x20, 0xce, 0x4a, 0x40, 0x2c, 0x89, 0xba, 0xdf, 0x6c, 0x74, 0x06, 0xcb, 0xb9, 0xdf, 0xef, 0x55, 0x86, + 0x1e, 0x20, 0x72, 0x66, 0x27, 0x3d, 0xe8, 0xf9, 0xf4, 0x00, 0x3f, 0xd1, 0xab, 0x06, 0x71, 0x32, 0x7f, 0x59, 0x46, + 0x2f, 0x3d, 0xfa, 0xf0, 0x5b, 0x37, 0xe5, 0x91, 0xf9, 0x7f, 0x4e, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x79, 0x40, 0x6c, + 0xde, 0x9a, 0x54, 0x1a, 0x89, 0x6a, 0x74, 0xb6, 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xfd, 0x84, 0x16, 0x56, 0x10, + 0x21, 0xe7, 0xe8, 0x19, 0x18, 0xa4, 0x42, 0xa8, 0x1c, 0xb5, 0x28, 0xd1, 0x10, 0x24, 0x97, 0x25, 0x57, 0xe1, 0x73, + 0x08, 0x55, 0xa7, 0x8f, 0x33, 0x11, 0x36, 0xf4, 0x38, 0xf4, 0x01, 0xe0, 0xff, 0xda, 0x23, 0x17, 0x25, 0xbf, 0xc4, + 0xb3, 0xb9, 0x4d, 0x30, 0x0a, 0x96, 0x8b, 0x66, 0x68, 0x1b, 0xc4, 0x7e, 0x2c, 0x09, 0xd6, 0x23, 0x69, 0x3c, 0x2a, + 0xcd, 0x11, 0xe1, 0x47, 0xf1, 0x51, 0xf4, 0x34, 0x36, 0x24, 0x92, 0x23, 0x89, 0xe4, 0x03, 0x20, 0x9c, 0x04, 0xfd, + 0xc5, 0x5d, 0x93, 0x5d, 0x0b, 0xb5, 0xd7, 0xef, 0xc1, 0xbf, 0x96, 0x4c, 0xcb, 0xee, 0x55, 0x8f, 0x7d, 0x45, 0x90, + 0x07, 0x13, 0xe0, 0xf5, 0xe1, 0x5f, 0x4b, 0x9c, 0x41, 0xeb, 0xf9, 0xa2, 0x3a, 0x33, 0xf3, 0x06, 0x37, 0xf2, 0xba, + 0xac, 0x5d, 0x97, 0x2f, 0xf8, 0x01, 0xbf, 0xad, 0xb8, 0x48, 0xcb, 0x83, 0x9f, 0xab, 0x36, 0x9e, 0x53, 0xb9, 0x5e, + 0xb9, 0x38, 0x2b, 0xca, 0x38, 0xd5, 0x93, 0xba, 0x18, 0x6b, 0xd8, 0x86, 0xdf, 0x23, 0xea, 0x4a, 0x5a, 0x8e, 0x9e, + 0x52, 0xae, 0x9a, 0x29, 0x17, 0xeb, 0x3c, 0xff, 0x69, 0x2f, 0x15, 0xa7, 0xb8, 0x99, 0x82, 0x54, 0xa9, 0xe5, 0x02, + 0xaa, 0xe7, 0xa8, 0xe5, 0x6e, 0x69, 0x76, 0x80, 0x73, 0xdb, 0x54, 0x1f, 0x2b, 0xb3, 0x0b, 0x2f, 0xb9, 0x71, 0x7f, + 0x32, 0x65, 0x58, 0x30, 0x0a, 0x6d, 0x56, 0x5d, 0x69, 0xfb, 0x42, 0xeb, 0x34, 0x0c, 0x57, 0x7e, 0xbc, 0x80, 0x74, + 0x01, 0xe3, 0x78, 0x51, 0x32, 0x31, 0x6e, 0x8f, 0xde, 0x0a, 0xe2, 0x6b, 0xb6, 0x02, 0xe9, 0xf7, 0x7b, 0xc2, 0xdb, + 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, 0x72, 0x15, 0x8b, 0x1f, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, + 0x4c, 0xa7, 0x3f, 0x27, 0xa1, 0x5f, 0x08, 0x05, 0x9f, 0xf5, 0xd2, 0xca, 0x93, 0xdb, 0xc3, 0x32, 0xae, 0xd1, 0x2b, + 0x71, 0xa5, 0xfb, 0x66, 0xa4, 0x90, 0x7a, 0xe4, 0xab, 0xa6, 0x80, 0xde, 0x8c, 0x7d, 0x33, 0x15, 0xe6, 0xed, 0x8e, + 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, + 0xa7, 0x9d, 0xfb, 0x75, 0xde, 0xe1, 0xae, 0xa8, 0xdf, 0x02, 0x17, 0x9a, 0x15, 0x65, 0xd5, 0x96, 0x0d, 0xdb, 0xc6, + 0x1b, 0x59, 0x28, 0x36, 0xc0, 0xb2, 0xe7, 0xbe, 0x85, 0x07, 0x88, 0x9b, 0x70, 0xcf, 0x2e, 0x6a, 0xb8, 0x31, 0x7c, + 0x5d, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, + 0x85, 0x2f, 0x78, 0x19, 0xce, 0xf9, 0xc2, 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0xd3, 0x21, 0x53, 0xe8, 0x76, 0xa5, 0xb1, + 0x52, 0x22, 0x6e, 0xcd, 0x32, 0x81, 0xb2, 0x94, 0xb5, 0x12, 0xde, 0x14, 0x2d, 0x5b, 0x49, 0x23, 0xef, 0x99, 0x83, + 0xfb, 0xd8, 0x6f, 0x88, 0x89, 0x6c, 0x02, 0x93, 0xa2, 0xa1, 0x03, 0xda, 0x55, 0x17, 0xbe, 0x19, 0xf5, 0x60, 0x90, + 0x5b, 0x92, 0x88, 0x15, 0xa4, 0x58, 0xc1, 0xba, 0x66, 0xc5, 0x3c, 0x5f, 0xd0, 0x0b, 0x26, 0xe7, 0xe9, 0x82, 0xae, + 0x98, 0x9c, 0xaf, 0xf1, 0x26, 0x74, 0x01, 0x27, 0x24, 0xd9, 0xc6, 0x4a, 0x01, 0x7b, 0x81, 0x97, 0x37, 0x3c, 0x53, + 0x35, 0x2d, 0xbb, 0x54, 0x1c, 0x60, 0x7c, 0x5e, 0x86, 0x61, 0x39, 0xbc, 0x00, 0x6b, 0x89, 0xc3, 0x70, 0x35, 0xe7, + 0x0b, 0xf5, 0x1b, 0xa2, 0xce, 0x27, 0xa1, 0x62, 0x17, 0xec, 0x5e, 0x20, 0xd3, 0xab, 0x39, 0x5f, 0xa8, 0x91, 0xd0, + 0x05, 0x5f, 0x59, 0x63, 0x93, 0xd8, 0x13, 0xb4, 0xcc, 0xe2, 0xf9, 0x78, 0x11, 0xc5, 0x35, 0x2c, 0xc3, 0x0f, 0x6a, + 0x66, 0x5a, 0xf2, 0x9f, 0x5c, 0x6d, 0x68, 0xa2, 0x6f, 0xb0, 0x8a, 0xfc, 0xe1, 0xf1, 0xd1, 0x25, 0x90, 0xb1, 0xb3, + 0x2b, 0x99, 0xf9, 0xd0, 0xf7, 0x91, 0xc1, 0x3d, 0x37, 0xe5, 0x8c, 0xab, 0x20, 0x51, 0x06, 0xee, 0x5e, 0xcd, 0x92, + 0xb1, 0x16, 0xe1, 0xfb, 0x47, 0x45, 0xd1, 0x67, 0xd2, 0x34, 0xa0, 0xfb, 0x48, 0x30, 0x07, 0x7a, 0xaf, 0xd0, 0xe1, + 0xb2, 0xda, 0x66, 0x02, 0xfe, 0x22, 0x41, 0x7e, 0x2b, 0xf4, 0xaa, 0xc6, 0xa0, 0x8a, 0x76, 0x11, 0x4b, 0xff, 0x3e, + 0xe2, 0x47, 0xd9, 0xfc, 0xa7, 0xb9, 0xc7, 0x2b, 0x09, 0x83, 0x1f, 0x52, 0xb3, 0x49, 0xe6, 0xed, 0x15, 0xfb, 0x0e, + 0x3a, 0xea, 0x51, 0x6b, 0xbc, 0xaf, 0x5e, 0x70, 0x0a, 0x31, 0x4a, 0x28, 0x3a, 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, + 0x77, 0x83, 0xdd, 0x36, 0xaf, 0x79, 0x51, 0x70, 0xbe, 0xae, 0xaa, 0xc0, 0x0f, 0x68, 0x38, 0x5f, 0xec, 0x87, 0x30, + 0x1c, 0xd3, 0xd6, 0x35, 0x0c, 0xc2, 0x8c, 0x61, 0x24, 0x04, 0xaf, 0x7f, 0xd1, 0x23, 0x9a, 0xc4, 0xab, 0x1f, 0xf8, + 0xe7, 0x8c, 0x17, 0x8a, 0x48, 0x83, 0x08, 0xa9, 0x9b, 0xf8, 0x46, 0xa6, 0x49, 0x01, 0x85, 0x00, 0xa3, 0x80, 0x4a, + 0x6c, 0x68, 0x2a, 0xfe, 0x56, 0x8b, 0x0f, 0x7e, 0x6a, 0x3a, 0x1e, 0x8d, 0xeb, 0x56, 0x67, 0x54, 0xd0, 0x19, 0xe8, + 0x51, 0x2b, 0xea, 0x69, 0xd0, 0x4a, 0x30, 0x8d, 0x34, 0x6f, 0xdd, 0x43, 0xe0, 0x95, 0x69, 0xf1, 0xce, 0x03, 0xba, + 0x3d, 0xf3, 0xc1, 0x93, 0xc7, 0xf4, 0xcc, 0xa1, 0x27, 0x57, 0xec, 0xa4, 0xea, 0xa1, 0xf6, 0xde, 0x8c, 0x50, 0xd0, + 0xef, 0x63, 0x0a, 0x74, 0x23, 0xa8, 0xbd, 0xab, 0x7b, 0x25, 0xf7, 0x39, 0x7c, 0xc7, 0x59, 0x6e, 0x01, 0x4b, 0x45, + 0xd6, 0x0a, 0x3c, 0x0a, 0x50, 0x97, 0xca, 0x10, 0xb6, 0x98, 0xc3, 0xa1, 0xb2, 0x5b, 0xb5, 0x1a, 0x4a, 0x72, 0x5c, + 0x8e, 0xc0, 0x21, 0x74, 0x5d, 0x0e, 0xca, 0xd1, 0x32, 0xab, 0xde, 0xe3, 0x6f, 0xcd, 0x3a, 0x24, 0xd9, 0x5d, 0xac, + 0x03, 0xb7, 0xac, 0xc3, 0xf4, 0x93, 0x41, 0x0a, 0x40, 0x93, 0x8d, 0xc0, 0x25, 0x00, 0xef, 0xed, 0x3f, 0x22, 0xd4, + 0xca, 0xf4, 0x4e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, 0x91, 0xce, + 0x49, 0x9d, 0x89, 0xf7, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x1b, 0xbc, 0xcd, 0x6a, 0xa9, + 0x8d, 0x1e, 0x28, 0x80, 0xdf, 0x0d, 0x36, 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x47, + 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x47, 0xe4, 0xd8, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x41, + 0x83, 0xfe, 0x65, 0x5b, 0xe4, 0x0e, 0x40, 0x69, 0x14, 0x31, 0x50, 0x25, 0x88, 0xa8, 0xc5, 0xbf, 0xef, 0xcd, 0xb5, + 0xc1, 0x5c, 0x20, 0xcc, 0xc1, 0x80, 0x83, 0xb8, 0x0d, 0x42, 0x73, 0xc0, 0x6c, 0x6f, 0x23, 0x41, 0x37, 0xd6, 0x30, + 0xb3, 0xa3, 0x3f, 0xdc, 0x4a, 0xf0, 0x4d, 0xd6, 0x1a, 0x75, 0x5e, 0x1c, 0x02, 0x41, 0xf0, 0xa6, 0x50, 0xd5, 0x5e, + 0xf5, 0xc0, 0xc6, 0x5b, 0xf5, 0x63, 0xb7, 0x1b, 0x4f, 0x85, 0xbb, 0xf6, 0x0b, 0x0a, 0x27, 0x9f, 0x92, 0x7f, 0xbd, + 0x37, 0x19, 0x1c, 0x18, 0x19, 0xbe, 0xf4, 0xf6, 0x2f, 0x7c, 0xad, 0xa5, 0x7b, 0x62, 0x50, 0x92, 0x87, 0x47, 0x8a, + 0xfe, 0xdd, 0x29, 0x2b, 0x9f, 0xda, 0xe9, 0xdf, 0xed, 0xcc, 0xfa, 0x3c, 0x1e, 0x4d, 0x76, 0xbb, 0x5e, 0x5c, 0x69, + 0x8f, 0x35, 0xbd, 0x20, 0xd0, 0xb9, 0x9e, 0x1c, 0x1e, 0x41, 0x54, 0x84, 0x66, 0xdc, 0xcd, 0xb2, 0x21, 0x91, 0xf1, + 0xe3, 0x74, 0x96, 0x0d, 0xc1, 0x0e, 0xf7, 0xa2, 0x12, 0x97, 0xa3, 0xd6, 0x06, 0xa7, 0xb7, 0x49, 0x08, 0xa1, 0x1c, + 0xb0, 0xb2, 0x5b, 0xf5, 0x67, 0xa3, 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x07, 0x66, 0x04, + 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xa7, 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0xf6, 0xe8, 0xa9, + 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, 0xdf, 0x30, 0xee, 0x3f, 0x34, 0x5f, 0xbb, 0xa9, 0x88, 0x1e, 0x53, 0x2c, 0x53, + 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x72, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, + 0x9f, 0x21, 0x7c, 0x46, 0xb2, 0x0b, 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xe4, 0x31, 0x3d, 0x98, 0x7c, 0x77, 0x44, + 0x0f, 0x8e, 0x1e, 0x3d, 0x21, 0x00, 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3d, 0x79, 0x42, 0x0f, 0xbe, 0xff, 0x9e, 0x1e, + 0x4c, 0x1e, 0x1d, 0x35, 0xd2, 0x26, 0x4f, 0xbe, 0xa7, 0x07, 0xdf, 0x3d, 0x6e, 0xa4, 0x1d, 0x8d, 0x9f, 0xd0, 0x83, + 0xbf, 0x7f, 0x67, 0xd2, 0xfe, 0x06, 0xd9, 0xbe, 0x3f, 0xc2, 0xff, 0x4c, 0xda, 0xe4, 0xc9, 0x23, 0x7a, 0x30, 0x19, + 0x43, 0x25, 0x4f, 0x5c, 0x25, 0xe3, 0x09, 0x7c, 0xfc, 0x08, 0xfe, 0xfb, 0x1b, 0x81, 0x4d, 0x20, 0xd9, 0x52, 0xa0, + 0xfe, 0x0c, 0x45, 0x9c, 0xa8, 0x9a, 0x48, 0x78, 0x88, 0x99, 0xd5, 0x37, 0x71, 0x18, 0x10, 0x97, 0x0e, 0x05, 0xd1, + 0x83, 0xf1, 0xe8, 0x09, 0x09, 0x7c, 0x78, 0xba, 0x4f, 0x3e, 0xc8, 0xd8, 0x52, 0xcc, 0xb3, 0x6f, 0x96, 0x26, 0xb6, + 0x82, 0x07, 0x60, 0xf5, 0xc1, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x86, 0xcb, 0xfd, 0x5c, 0x3f, 0xb6, 0x00, 0xe5, 0xfd, + 0x55, 0xcb, 0x3e, 0x15, 0x2a, 0x74, 0x5a, 0x6b, 0xf4, 0xd9, 0x07, 0x4c, 0x1f, 0x0c, 0xbc, 0x1b, 0xf6, 0xcf, 0x7b, + 0xe5, 0xb4, 0xbe, 0xd1, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x65, 0xfc, + 0xfe, 0x1f, 0x96, 0xf1, 0xa1, 0xa3, 0x8c, 0x7f, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, + 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x07, 0x46, 0x14, 0x2d, 0x2f, 0x0e, 0x52, 0x3e, + 0xab, 0xd8, 0xcf, 0x4b, 0x54, 0x6f, 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x77, 0xf3, 0x06, 0xb8, 0x19, 0xf6, + 0xa3, 0x7a, 0xf2, 0x03, 0x67, 0x64, 0xd2, 0xb6, 0x47, 0x99, 0x18, 0x01, 0x56, 0x40, 0x06, 0x0e, 0x3c, 0x00, 0x3a, + 0xe8, 0x8f, 0xf6, 0x6e, 0xa7, 0x52, 0x9a, 0x7d, 0xb6, 0x30, 0x80, 0x86, 0x79, 0x9b, 0xb8, 0xb2, 0xab, 0xd4, 0x97, + 0x97, 0xa0, 0x70, 0xab, 0x59, 0xde, 0x5e, 0x61, 0x2a, 0x6e, 0x4f, 0xca, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, + 0x40, 0xcd, 0x96, 0x8f, 0xb6, 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0xdf, 0x6a, 0xb1, 0x3f, 0x5a, + 0x3f, 0xfa, 0xbe, 0x3d, 0x1e, 0xac, 0x7d, 0x8f, 0x8f, 0xf4, 0x67, 0x8d, 0xeb, 0xc0, 0xb6, 0xe5, 0x1b, 0x2f, 0x6a, + 0x2b, 0xf1, 0x28, 0x81, 0x37, 0x30, 0x11, 0x29, 0x0c, 0x52, 0x2d, 0x70, 0x0c, 0xca, 0x1b, 0x0b, 0xb1, 0x54, 0x5d, + 0xdd, 0xd0, 0x2d, 0x19, 0x82, 0x87, 0x5b, 0x95, 0xaa, 0xc0, 0x51, 0xfd, 0x7e, 0x26, 0x7d, 0xb7, 0x27, 0x63, 0x47, + 0x8e, 0x53, 0x3f, 0x15, 0x0e, 0xfe, 0x9b, 0xd4, 0xb5, 0x7e, 0x99, 0xa5, 0xcc, 0xb2, 0x2c, 0xec, 0x24, 0xd4, 0x72, + 0x8f, 0xca, 0x83, 0xe4, 0x0b, 0x39, 0x44, 0xb2, 0xc0, 0x28, 0x14, 0x64, 0x38, 0xa1, 0x62, 0xb4, 0x16, 0xe5, 0x32, + 0xbb, 0xa8, 0xc2, 0xad, 0x52, 0x28, 0x73, 0x8a, 0xbe, 0xdd, 0xe0, 0x40, 0x42, 0xa2, 0xac, 0x7c, 0x13, 0xbf, 0x09, + 0x11, 0xac, 0x8e, 0x6b, 0x5b, 0x28, 0xee, 0xed, 0x4f, 0x91, 0x76, 0xf1, 0x47, 0xc6, 0x05, 0xd4, 0xc5, 0x62, 0x1a, + 0x4e, 0x6c, 0xec, 0x03, 0xf7, 0x85, 0xd5, 0xf4, 0x00, 0xd4, 0x77, 0xa9, 0xc4, 0x08, 0xea, 0x2b, 0x63, 0x1f, 0xdb, + 0x63, 0x4c, 0xce, 0x20, 0xd6, 0xb0, 0x2e, 0x5b, 0xf5, 0x8d, 0xb0, 0x13, 0x00, 0x6e, 0x84, 0xd6, 0xe8, 0xc8, 0x24, + 0x55, 0x88, 0xe7, 0xa5, 0x0a, 0xdf, 0x9a, 0x11, 0x3a, 0x06, 0x6f, 0x2a, 0xd7, 0x48, 0xe9, 0x0b, 0x06, 0xcd, 0xb1, + 0xad, 0xa3, 0xb0, 0xda, 0xca, 0xb2, 0x13, 0x80, 0x1b, 0xc8, 0x8e, 0xcd, 0xc5, 0x73, 0x56, 0xcd, 0xb3, 0x45, 0x64, + 0x82, 0x02, 0xa6, 0xc2, 0x32, 0x68, 0x6f, 0xee, 0x90, 0xed, 0x38, 0x84, 0x6e, 0xb8, 0x8f, 0x60, 0x3c, 0xed, 0xa6, + 0x60, 0x05, 0xd1, 0x08, 0xf1, 0x30, 0x63, 0x16, 0xdf, 0x2b, 0x4d, 0x79, 0xaa, 0x5a, 0x02, 0x81, 0xa3, 0x10, 0xea, + 0x62, 0xdf, 0x28, 0xc1, 0x65, 0x6a, 0x04, 0x33, 0xd8, 0xb3, 0x23, 0xb5, 0x5d, 0x72, 0x4e, 0x87, 0x6a, 0x4a, 0x4b, + 0x3d, 0xa5, 0xda, 0xd7, 0x50, 0xcc, 0x4b, 0xf4, 0xd0, 0x03, 0xd7, 0x03, 0xed, 0x90, 0x57, 0xd2, 0x89, 0x89, 0xa0, + 0xd3, 0x6a, 0x13, 0x76, 0x6e, 0xa4, 0x5b, 0x56, 0x23, 0xef, 0x18, 0x9a, 0x1d, 0xf1, 0xca, 0x0f, 0xd4, 0x05, 0x10, + 0x21, 0x77, 0xb6, 0xc8, 0x10, 0x67, 0x96, 0x95, 0x2f, 0xa0, 0x2c, 0x8e, 0xd8, 0xba, 0x02, 0xae, 0xa5, 0x60, 0x72, + 0xc9, 0x23, 0x91, 0x22, 0x22, 0xe0, 0xa9, 0xd2, 0xae, 0xef, 0xb5, 0x84, 0xd0, 0x32, 0x05, 0xe2, 0xe6, 0xa2, 0x38, + 0xd7, 0x36, 0x90, 0x05, 0xd0, 0xb7, 0x9f, 0xb2, 0x2b, 0x2f, 0x1c, 0xec, 0xf6, 0x2a, 0x13, 0xcf, 0xf8, 0x45, 0x26, + 0x78, 0x8a, 0x60, 0x57, 0xb7, 0xe6, 0x81, 0x3b, 0xb6, 0x0d, 0x2c, 0xdf, 0x7e, 0x80, 0x05, 0x53, 0x86, 0x5a, 0x29, + 0x91, 0x89, 0x48, 0x40, 0x66, 0x9f, 0xb9, 0x7b, 0x9d, 0x89, 0xd7, 0xf1, 0x2d, 0x78, 0x53, 0x34, 0xf8, 0xe9, 0xd1, + 0x39, 0x7e, 0x89, 0x48, 0xa2, 0x10, 0xc3, 0x16, 0x23, 0x62, 0x21, 0x72, 0xec, 0x98, 0x50, 0xae, 0x04, 0xad, 0xad, + 0x21, 0xf0, 0xe2, 0x4f, 0xab, 0xee, 0x5d, 0x65, 0xc2, 0xd8, 0x67, 0x5c, 0xc5, 0xb7, 0xac, 0x54, 0x60, 0x16, 0x18, + 0xe7, 0xbe, 0x2d, 0x25, 0xb9, 0xca, 0x84, 0x11, 0x90, 0x5c, 0xc5, 0xb7, 0xb4, 0x29, 0xe3, 0xd0, 0x56, 0x74, 0x5e, + 0x9c, 0xdf, 0xfd, 0xe1, 0x97, 0x18, 0x6a, 0x65, 0xdc, 0xef, 0x83, 0xc4, 0x4c, 0xda, 0xa6, 0xcc, 0x64, 0x24, 0x35, + 0x5a, 0x48, 0x45, 0xf9, 0x60, 0x42, 0xf6, 0x57, 0xaa, 0x65, 0x44, 0xed, 0x57, 0xa1, 0x98, 0x8d, 0xa3, 0x09, 0xa1, + 0x93, 0x8e, 0xf5, 0x6e, 0x5a, 0x0b, 0x99, 0x46, 0x4f, 0x22, 0xcf, 0xa7, 0xb3, 0x60, 0xd5, 0xb4, 0x38, 0x66, 0x7c, + 0x5a, 0x0c, 0x06, 0x44, 0xbb, 0x14, 0x6e, 0xb1, 0x1e, 0x30, 0xa5, 0x71, 0xf1, 0xd6, 0x4c, 0xab, 0x5f, 0x48, 0x15, + 0x92, 0xde, 0x33, 0x20, 0x11, 0xd2, 0x05, 0xbb, 0x05, 0x89, 0xa2, 0xe7, 0x7f, 0xa7, 0xb6, 0xe0, 0xbe, 0x07, 0x63, + 0x33, 0xba, 0xaf, 0x67, 0xfc, 0x87, 0xda, 0x16, 0x44, 0x7d, 0x2a, 0x59, 0xaf, 0x23, 0x51, 0x85, 0x5c, 0x84, 0x9f, + 0x1d, 0x0d, 0x31, 0x44, 0xb5, 0xc7, 0x02, 0xb1, 0xbe, 0x3a, 0xe7, 0x05, 0x4e, 0x3f, 0x73, 0x97, 0x2b, 0xd8, 0x16, + 0xb4, 0x32, 0x34, 0xea, 0x4d, 0xfc, 0x26, 0xb2, 0x97, 0x05, 0x5d, 0xe4, 0x33, 0x14, 0xb2, 0xe6, 0x61, 0x58, 0x0d, + 0xdb, 0x83, 0x48, 0x0e, 0xdb, 0x93, 0xd0, 0x68, 0x0c, 0x2c, 0x90, 0x3d, 0x1a, 0x81, 0x8b, 0xd0, 0xca, 0xdf, 0x8e, + 0xc1, 0x85, 0xcb, 0x22, 0xb2, 0x0c, 0x75, 0xfc, 0xa6, 0x76, 0x13, 0x54, 0xaf, 0xd0, 0x69, 0x0a, 0xab, 0x52, 0x26, + 0xf9, 0xf0, 0xeb, 0x85, 0x2c, 0x30, 0x93, 0xd7, 0x65, 0x8f, 0xbe, 0xb6, 0xdb, 0x3b, 0x30, 0x05, 0xeb, 0x3e, 0x79, + 0x5f, 0x3f, 0xec, 0xec, 0x09, 0x18, 0xc5, 0xaa, 0x1c, 0x4d, 0x21, 0xa5, 0xf6, 0x41, 0xa9, 0x3f, 0x85, 0xa9, 0xd0, + 0x1c, 0xbb, 0x05, 0x4c, 0x02, 0xf6, 0x19, 0x52, 0x3d, 0xa6, 0x1d, 0xfb, 0x1c, 0x6d, 0x61, 0x49, 0xc0, 0xe1, 0x1f, + 0x09, 0x59, 0xfb, 0x57, 0x77, 0x99, 0x36, 0x43, 0xb6, 0xcc, 0x17, 0xc0, 0xe7, 0xc3, 0xae, 0x8d, 0x4a, 0x94, 0x4d, + 0x44, 0x92, 0xc2, 0x96, 0xc7, 0x20, 0xed, 0x51, 0x4c, 0x57, 0x05, 0x4f, 0x32, 0x94, 0x52, 0x24, 0xda, 0x27, 0x38, + 0x87, 0x37, 0xb8, 0x1f, 0x55, 0x40, 0x78, 0x15, 0x72, 0x3a, 0x4a, 0xa9, 0xb6, 0x80, 0x51, 0xd4, 0x03, 0x44, 0x79, + 0x19, 0xc8, 0xf1, 0x76, 0xbb, 0x09, 0x5d, 0xb1, 0xe5, 0x70, 0x42, 0x91, 0x94, 0x5c, 0x62, 0xb9, 0x57, 0xa0, 0xf3, + 0x38, 0x67, 0xbd, 0x57, 0x80, 0x45, 0x70, 0x06, 0x7f, 0x63, 0x42, 0xaf, 0xe1, 0x6f, 0x4e, 0xe8, 0x53, 0x16, 0x5e, + 0x0d, 0x2f, 0xc9, 0x61, 0x98, 0x0e, 0x26, 0x4a, 0x30, 0xb6, 0x61, 0x69, 0x19, 0xaa, 0xc4, 0xd5, 0xe1, 0x05, 0x79, + 0x78, 0x41, 0x6f, 0xe9, 0x0d, 0x7d, 0x4d, 0x1f, 0x00, 0xe1, 0xdf, 0x1c, 0x4f, 0xf8, 0x70, 0xf2, 0xb8, 0xdf, 0xef, + 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, 0x7a, 0x31, 0x7d, 0xa0, + 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xdc, 0x90, 0x21, 0x3e, 0x5e, 0xe4, 0x52, 0x16, 0xe1, 0xe5, 0xe1, 0x86, + 0xd0, 0x07, 0x27, 0xa0, 0x37, 0xc5, 0xfa, 0x1e, 0x3c, 0xdc, 0xe8, 0xda, 0x08, 0x7d, 0x15, 0x26, 0xb0, 0x4d, 0x6e, + 0x99, 0xbd, 0x6b, 0x4f, 0xc6, 0x10, 0xcb, 0x64, 0xe3, 0x95, 0xb7, 0x79, 0x78, 0x4b, 0x0e, 0x6f, 0xc1, 0x53, 0xd4, + 0x92, 0xbf, 0x59, 0x78, 0xc3, 0x5a, 0x35, 0x3c, 0xdc, 0xd0, 0xd7, 0xad, 0x46, 0x3c, 0xdc, 0x90, 0x28, 0xbc, 0x61, + 0x97, 0xf4, 0x35, 0xbb, 0x22, 0xf4, 0xbc, 0xdf, 0x3f, 0xeb, 0xf7, 0x65, 0xbf, 0xff, 0x73, 0x1c, 0x86, 0xf1, 0xb0, + 0x20, 0x87, 0x92, 0x6e, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, 0x59, 0x95, 0xb7, 0xca, 0xb5, + 0xa1, 0x60, 0xad, 0xb0, 0x61, 0xea, 0xe9, 0x01, 0xbd, 0x61, 0x05, 0x7d, 0xcd, 0x62, 0x12, 0x5d, 0x43, 0x2b, 0xce, + 0x67, 0x45, 0x74, 0x43, 0x5f, 0xb3, 0xb3, 0x59, 0x1c, 0xbd, 0xa6, 0x0f, 0x58, 0x3e, 0x9c, 0x40, 0xde, 0xd7, 0xc3, + 0x1b, 0x72, 0xf8, 0x80, 0x44, 0xe1, 0x03, 0xfd, 0x7b, 0x43, 0x2f, 0x79, 0xf8, 0x80, 0x7a, 0xd5, 0x3c, 0x20, 0xa6, + 0xfa, 0x46, 0xed, 0x0f, 0x48, 0xe4, 0x0f, 0xe6, 0x03, 0x6b, 0x4f, 0xf3, 0xce, 0xd1, 0xc6, 0x75, 0x19, 0x6e, 0x08, + 0x5d, 0x97, 0xe1, 0x0d, 0x21, 0xd3, 0xe6, 0xd8, 0xc1, 0x80, 0xce, 0xde, 0x45, 0x09, 0xa1, 0x37, 0x7e, 0xa9, 0x37, + 0x38, 0x86, 0x66, 0x84, 0x74, 0x3f, 0x31, 0x0d, 0xd7, 0xc1, 0x47, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, + 0x1f, 0x22, 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0x8f, 0x83, 0x01, 0x74, 0xc6, + 0x2b, 0x29, 0xbc, 0x19, 0x7c, 0x7c, 0xb8, 0x21, 0xaa, 0x8e, 0x82, 0x96, 0x32, 0x2c, 0xe8, 0x53, 0x9a, 0x01, 0xe0, + 0xd7, 0xc7, 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0xfd, 0x78, 0xfc, 0x60, 0x3a, 0x18, 0x7c, 0x34, 0xdb, 0xe4, 0x33, + 0xbb, 0xa3, 0x14, 0x58, 0x7f, 0x67, 0xfd, 0xfe, 0xe7, 0x93, 0x98, 0x9c, 0x17, 0x3c, 0xfe, 0x34, 0x6d, 0xb6, 0xe5, + 0xb3, 0x8b, 0xaa, 0x76, 0xd6, 0xef, 0xaf, 0xfb, 0xfd, 0xd7, 0x80, 0x5d, 0x34, 0x73, 0xbe, 0x9e, 0x20, 0x6d, 0x99, + 0x3b, 0x8a, 0xa4, 0x49, 0x0e, 0x8d, 0xa1, 0x6d, 0xb1, 0x6a, 0xdb, 0xac, 0x23, 0x03, 0x8b, 0xa3, 0x66, 0x45, 0x71, + 0x4d, 0xa2, 0xb0, 0x77, 0xb6, 0xdb, 0xbd, 0x66, 0x8c, 0xc5, 0x04, 0xa4, 0x1f, 0xfe, 0xeb, 0xd7, 0x75, 0x23, 0x86, + 0x58, 0xa9, 0xc4, 0x77, 0xdb, 0xa5, 0x3d, 0x04, 0x22, 0x0e, 0x9b, 0xfe, 0xbd, 0xb9, 0x97, 0x8b, 0xda, 0xf1, 0xad, + 0xbf, 0x03, 0x08, 0x91, 0x64, 0x21, 0x9f, 0xe1, 0x18, 0x94, 0x19, 0x00, 0x99, 0x47, 0x6a, 0xe6, 0x25, 0x80, 0x00, + 0x93, 0xdd, 0x6e, 0x34, 0x1e, 0x4f, 0x68, 0xc1, 0x46, 0x7f, 0x7b, 0xf2, 0xb0, 0x7a, 0x18, 0x06, 0xc1, 0x20, 0x23, + 0x2d, 0x3d, 0x85, 0x5d, 0xac, 0xd5, 0x21, 0x18, 0xc1, 0x6b, 0xf6, 0xf1, 0x3a, 0xfb, 0x6a, 0xf6, 0x11, 0x09, 0x6b, + 0x83, 0x71, 0xe4, 0x22, 0x6d, 0xe9, 0xed, 0xee, 0x60, 0x30, 0xb9, 0x48, 0xbf, 0xc0, 0x76, 0xfa, 0xfc, 0x9b, 0x07, + 0xe3, 0x09, 0x07, 0xa3, 0xbb, 0x28, 0xe8, 0x33, 0x6d, 0xb7, 0xab, 0xfc, 0x4b, 0xe0, 0x1b, 0x4c, 0x05, 0x1d, 0x9b, + 0x65, 0xe1, 0x06, 0x15, 0x51, 0x47, 0xcb, 0xa0, 0xaa, 0x95, 0xed, 0x1c, 0x50, 0x4b, 0xac, 0xca, 0xc4, 0x2d, 0x30, + 0x0c, 0x19, 0xea, 0x72, 0x4f, 0xab, 0xdf, 0x79, 0x21, 0x0d, 0x7c, 0x86, 0x13, 0x11, 0x7a, 0xdc, 0x1a, 0xf7, 0xb9, + 0x35, 0xf1, 0x05, 0x6e, 0xad, 0x44, 0x12, 0x6b, 0x60, 0x49, 0xcd, 0xe5, 0x28, 0x61, 0x27, 0x25, 0xe3, 0xb3, 0x32, + 0x4a, 0x68, 0x0c, 0x0f, 0x92, 0x89, 0x99, 0x8c, 0x12, 0xb4, 0x4f, 0x74, 0x11, 0x06, 0xff, 0x02, 0xcc, 0x7e, 0x9a, + 0xc3, 0x5f, 0x49, 0xa6, 0xc9, 0x31, 0x04, 0x84, 0x38, 0x1e, 0xcf, 0xe2, 0x70, 0x4c, 0xa2, 0xe4, 0x04, 0x9e, 0xe0, + 0xbf, 0x22, 0x1c, 0x93, 0x5a, 0xdf, 0x61, 0xa4, 0xba, 0xdc, 0x26, 0x0c, 0xe0, 0xca, 0xc6, 0xb3, 0x49, 0x64, 0xa5, + 0xbb, 0xf2, 0xe1, 0x68, 0xfc, 0x84, 0x4c, 0xe3, 0x50, 0x0e, 0x12, 0x42, 0xc1, 0xbb, 0x37, 0x2c, 0x87, 0x89, 0x86, + 0x67, 0x03, 0x36, 0xaf, 0x74, 0x6c, 0x9e, 0x84, 0x13, 0x10, 0x86, 0x09, 0x39, 0xd6, 0x3b, 0x90, 0x52, 0xf4, 0x79, + 0x8e, 0xfd, 0xd4, 0x47, 0x10, 0x66, 0x47, 0x2d, 0x15, 0x5f, 0x01, 0xd0, 0x25, 0x0e, 0x0e, 0xb5, 0x67, 0xbe, 0x98, + 0x85, 0xa5, 0x47, 0xa5, 0x4c, 0x75, 0x87, 0xa2, 0x41, 0xf9, 0x4d, 0x83, 0x0e, 0x05, 0x19, 0x4c, 0x68, 0x79, 0x32, + 0xe1, 0x8f, 0x20, 0x80, 0x47, 0x23, 0xe2, 0x97, 0xc2, 0x89, 0x81, 0xf0, 0x2a, 0xc8, 0x40, 0xa5, 0xb5, 0x6a, 0xcc, + 0xc8, 0x56, 0x7c, 0x00, 0x61, 0x52, 0x0e, 0x6e, 0xe4, 0x3a, 0x4f, 0x21, 0x2a, 0xd8, 0x3a, 0xaf, 0x0e, 0x2e, 0xc1, + 0x92, 0x3d, 0xae, 0x20, 0x4e, 0xd8, 0x7a, 0x05, 0xd8, 0xb9, 0x0f, 0xb6, 0x65, 0x7d, 0xa0, 0xbe, 0x3b, 0xc0, 0x96, + 0xc3, 0xab, 0x4a, 0x1e, 0x4c, 0xc6, 0xe3, 0xf1, 0xe8, 0x0f, 0x38, 0x3a, 0x80, 0xd0, 0x92, 0xc8, 0xf0, 0xc9, 0x00, + 0x8d, 0xbb, 0xae, 0xb8, 0x37, 0x2e, 0x14, 0x65, 0xa5, 0x93, 0x09, 0x01, 0xf1, 0xb3, 0xe9, 0x1b, 0xec, 0x2b, 0xae, + 0xe3, 0x9f, 0xec, 0x7f, 0x62, 0x56, 0xb4, 0x5a, 0xa9, 0xa3, 0x77, 0x6f, 0x3f, 0xbc, 0xfa, 0xf8, 0xea, 0xd7, 0xe7, + 0x67, 0xaf, 0xde, 0xbc, 0x78, 0xf5, 0xe6, 0xd5, 0xc7, 0x7f, 0xdf, 0xc3, 0x60, 0xfb, 0xb6, 0x22, 0x76, 0xec, 0xbd, + 0x7b, 0x8c, 0x57, 0x8b, 0x2f, 0x9c, 0x3d, 0x72, 0xb7, 0x58, 0x80, 0x4d, 0x30, 0xdc, 0x82, 0xa0, 0x9a, 0xd1, 0xa8, + 0xf4, 0x3d, 0x01, 0x19, 0x8d, 0x0a, 0xd9, 0x78, 0x58, 0xb1, 0x15, 0x72, 0xf1, 0x8e, 0xe1, 0xe0, 0x23, 0xfb, 0x5b, + 0x71, 0x26, 0xdc, 0x8e, 0xb6, 0x66, 0x45, 0xc0, 0xe7, 0x6b, 0x2d, 0x2a, 0x8f, 0x0b, 0x51, 0x7b, 0xdb, 0x3e, 0x87, + 0x84, 0x7a, 0x44, 0xae, 0x83, 0xf7, 0x6d, 0x90, 0x3d, 0x3e, 0xf2, 0x9e, 0x94, 0x67, 0xa8, 0xcf, 0xd1, 0xf0, 0x51, + 0xe3, 0x19, 0x9d, 0x98, 0x6b, 0xa3, 0x43, 0x3d, 0x2b, 0x60, 0x7f, 0x2b, 0x31, 0x36, 0x98, 0x43, 0xa7, 0x88, 0xf5, + 0xe1, 0x74, 0xbf, 0xfb, 0x37, 0xa3, 0x9f, 0xe1, 0xf8, 0x51, 0xaa, 0x09, 0xa4, 0x45, 0x81, 0xd2, 0x95, 0x21, 0xb7, + 0x3d, 0x0b, 0x0b, 0xf3, 0x33, 0x6c, 0x10, 0x40, 0x7b, 0xd9, 0xb1, 0x24, 0xd0, 0x2c, 0x5e, 0xeb, 0xfa, 0xe7, 0xe5, + 0xcb, 0x44, 0x3b, 0x5f, 0x7c, 0x0b, 0x21, 0x86, 0xfd, 0x2b, 0x42, 0x63, 0xc2, 0xdd, 0x24, 0xbb, 0x4b, 0x8b, 0xb9, + 0x57, 0x5d, 0xc5, 0x78, 0xdc, 0xdd, 0x71, 0xa5, 0x68, 0xde, 0xba, 0xc0, 0x1e, 0xa8, 0x79, 0x1d, 0x2f, 0x59, 0x08, + 0xd8, 0x8c, 0x87, 0x76, 0x91, 0x38, 0xbf, 0x77, 0x3a, 0x21, 0x87, 0x47, 0x53, 0x3e, 0x64, 0x25, 0x15, 0x03, 0x56, + 0xd6, 0x7b, 0xd4, 0x9c, 0xb7, 0x09, 0xb9, 0xd8, 0xa7, 0xe1, 0x62, 0xc8, 0xef, 0xbb, 0x24, 0x7d, 0xe4, 0x0d, 0x87, + 0x6a, 0xdb, 0x5c, 0x0c, 0x69, 0xca, 0xe9, 0x3e, 0x95, 0x01, 0x21, 0xd2, 0x55, 0x5c, 0x91, 0x5a, 0x1f, 0x55, 0x6b, + 0x27, 0xe9, 0xb8, 0xce, 0xb6, 0x5f, 0xb8, 0x64, 0xab, 0xdb, 0xb5, 0x7f, 0xad, 0x6e, 0x5f, 0x98, 0x81, 0xfc, 0xfd, + 0x89, 0xa8, 0x26, 0x06, 0xa2, 0x0b, 0xa8, 0xe0, 0x9f, 0xe0, 0xe5, 0xc9, 0x23, 0xad, 0x00, 0xbd, 0xeb, 0xec, 0xe8, + 0xda, 0xe3, 0x8d, 0x59, 0x6c, 0x2d, 0x71, 0xce, 0x2a, 0xdf, 0x59, 0x5e, 0x95, 0xad, 0xd0, 0x75, 0x04, 0xfb, 0x3d, + 0xec, 0xe8, 0xbb, 0xb7, 0x0d, 0x80, 0x28, 0x85, 0x95, 0x3b, 0xfb, 0x85, 0x77, 0xf6, 0x0b, 0x7b, 0xf6, 0xdb, 0x4d, + 0xa0, 0x7c, 0x58, 0xa1, 0x65, 0x2f, 0xa4, 0xa8, 0x4c, 0x93, 0xc7, 0x4d, 0x5d, 0x16, 0xd2, 0x62, 0x7e, 0x68, 0x69, + 0xd7, 0xe3, 0x31, 0x95, 0xa8, 0x1e, 0x79, 0x89, 0xad, 0x3a, 0x2c, 0xc9, 0xfd, 0xf7, 0xcc, 0xff, 0xd9, 0x1b, 0xe4, + 0x5d, 0x77, 0xbb, 0xff, 0x9b, 0x0b, 0x1d, 0xdc, 0xd6, 0xd6, 0xc2, 0x53, 0x57, 0xc7, 0x05, 0xde, 0xd5, 0xd6, 0xf7, + 0xdf, 0xd5, 0xde, 0x66, 0x7a, 0xd9, 0x55, 0x80, 0x1a, 0x24, 0xd6, 0x57, 0xbc, 0xc8, 0x92, 0xda, 0x2a, 0x34, 0x1e, + 0x70, 0x08, 0xed, 0xe1, 0x1d, 0x5c, 0x20, 0x87, 0x25, 0x84, 0x7e, 0xaa, 0x8c, 0x00, 0xd0, 0x67, 0xb1, 0x1f, 0xf0, + 0x30, 0x23, 0x03, 0x5f, 0xe2, 0x27, 0xa5, 0x2f, 0x2e, 0x3e, 0xdc, 0xcb, 0x4c, 0xd0, 0xab, 0xc4, 0x66, 0x2f, 0x64, + 0x3b, 0xe6, 0x87, 0xff, 0x05, 0x46, 0x83, 0xf0, 0xda, 0x92, 0x1d, 0x8a, 0x8e, 0x59, 0xae, 0xe0, 0xa8, 0x2d, 0xbd, + 0x32, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x01, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, + 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0xf7, 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0x45, + 0xfe, 0x85, 0xfa, 0x1a, 0x5b, 0x92, 0x6c, 0x2b, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, + 0x2d, 0xa1, 0x0d, 0x95, 0x41, 0x4f, 0x2e, 0x52, 0xe5, 0x23, 0x5b, 0x30, 0x79, 0x3c, 0x9e, 0xf9, 0x3d, 0x77, 0x0c, + 0x0e, 0x21, 0xd1, 0xc4, 0x1a, 0xbf, 0xf8, 0x59, 0x30, 0x8e, 0x43, 0x79, 0x22, 0x1b, 0xdf, 0x95, 0x24, 0x1a, 0x1b, + 0x53, 0x65, 0x7d, 0x95, 0xa8, 0x86, 0x09, 0x79, 0x58, 0x90, 0xc3, 0x82, 0x2e, 0xfd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, + 0x70, 0x32, 0x26, 0x0f, 0xe3, 0x87, 0x13, 0x03, 0x37, 0xec, 0xe7, 0xc8, 0x87, 0x4b, 0x72, 0xd8, 0xac, 0x12, 0x4c, + 0x51, 0x4d, 0xcf, 0xfc, 0x4a, 0x92, 0xc1, 0x72, 0x90, 0x3e, 0x6c, 0xe5, 0xc5, 0x5a, 0xf5, 0x78, 0xaf, 0x8f, 0xf9, + 0x94, 0x88, 0xc6, 0x8d, 0x61, 0x4d, 0xaf, 0xe2, 0x3f, 0x65, 0x11, 0x49, 0x09, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, + 0xb2, 0x24, 0x16, 0x69, 0x94, 0xd6, 0x84, 0xa6, 0x27, 0x6c, 0x32, 0x9e, 0xa5, 0x2c, 0x3d, 0x9e, 0x3c, 0x99, 0x4d, + 0x9e, 0x44, 0x47, 0xe3, 0x28, 0x1d, 0x0c, 0x20, 0xf9, 0x68, 0x0c, 0x2e, 0x76, 0xf0, 0x9b, 0x1d, 0xc1, 0xd0, 0x9d, + 0x20, 0x4b, 0x58, 0x40, 0xd3, 0xbe, 0xae, 0x49, 0x7a, 0x38, 0x2f, 0x54, 0x4f, 0xe2, 0x5b, 0xba, 0xf6, 0x1c, 0x5c, + 0xfc, 0x16, 0x5e, 0xb8, 0x16, 0x5e, 0xec, 0xb7, 0x50, 0x68, 0xb2, 0x1d, 0xcb, 0xff, 0x3f, 0x6e, 0x18, 0x77, 0xdd, + 0x25, 0xcc, 0xe2, 0xba, 0xce, 0x46, 0xab, 0x42, 0x56, 0x12, 0x6e, 0x13, 0x4a, 0x14, 0x36, 0x8a, 0x57, 0xab, 0x5c, + 0xbb, 0x88, 0xcd, 0x2b, 0x0a, 0xe0, 0x2e, 0x10, 0xa7, 0x18, 0x58, 0x68, 0x63, 0x20, 0xf7, 0x99, 0x17, 0x92, 0x59, + 0xb5, 0x8f, 0xb9, 0x47, 0xfe, 0x19, 0x82, 0x31, 0xaa, 0x38, 0x19, 0xcf, 0x14, 0xd6, 0xc5, 0x97, 0xe4, 0xbd, 0xff, + 0xc1, 0x51, 0x64, 0x8f, 0x66, 0xd0, 0x13, 0x44, 0xce, 0x23, 0xce, 0x9e, 0x4c, 0x5e, 0x06, 0xee, 0x67, 0xb0, 0xd2, + 0x5f, 0x77, 0x9b, 0xb1, 0xb6, 0x3d, 0xba, 0x17, 0x46, 0x28, 0xfa, 0x19, 0xdf, 0x99, 0x7a, 0x01, 0x97, 0x50, 0x0d, + 0xec, 0xfa, 0xf2, 0x92, 0x97, 0x00, 0x22, 0x94, 0x89, 0x7e, 0xbf, 0xf7, 0xa7, 0x81, 0x26, 0x2d, 0x79, 0xf1, 0x3a, + 0x13, 0xd6, 0x19, 0x07, 0x9a, 0x0a, 0xd4, 0xff, 0x53, 0x65, 0x9f, 0xe9, 0x98, 0xcc, 0xfc, 0xc7, 0xe1, 0x84, 0x44, + 0xcd, 0xd7, 0xe4, 0x0b, 0xa7, 0xe9, 0x17, 0xae, 0x68, 0xff, 0x0d, 0x99, 0xb9, 0xe1, 0x90, 0xa1, 0xfe, 0xd2, 0x31, + 0x4f, 0x46, 0xaf, 0x13, 0xb3, 0x13, 0xc1, 0xaa, 0x19, 0x44, 0x61, 0x2f, 0xe0, 0x41, 0x5d, 0xcb, 0xe2, 0x29, 0xcc, + 0x3e, 0xa8, 0x11, 0xc5, 0x31, 0x1b, 0xcf, 0x42, 0x19, 0x4e, 0xc0, 0xbe, 0x77, 0x32, 0x86, 0xfb, 0x80, 0x0c, 0x3f, + 0x55, 0x21, 0x76, 0x0e, 0xd2, 0x3e, 0x55, 0xa8, 0x98, 0x00, 0x88, 0x40, 0xc8, 0xdb, 0xef, 0x4b, 0x95, 0x84, 0xaf, + 0x4b, 0x4c, 0x29, 0xd4, 0x07, 0xff, 0x1d, 0xa9, 0xba, 0x63, 0xfa, 0xd5, 0xfa, 0xf1, 0x67, 0x42, 0xf1, 0xe9, 0x2e, + 0x25, 0xbe, 0x85, 0xe0, 0xce, 0x31, 0xe8, 0x20, 0x2a, 0x34, 0x63, 0xbb, 0x9f, 0xdf, 0x15, 0x77, 0xf3, 0xbb, 0xe2, + 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, 0xf4, 0xdf, 0xe7, 0x13, 0xef, + 0xe4, 0xa9, 0xaf, 0x32, 0x31, 0xbd, 0x83, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd3, 0x93, 0x75, 0x65, 0x6f, + 0xad, 0x64, 0x88, 0x79, 0xee, 0x61, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, + 0x2b, 0x7d, 0xdf, 0xed, 0x8c, 0x0a, 0xf3, 0x5e, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, + 0xb7, 0x19, 0xab, 0x86, 0x6c, 0xbe, 0x93, 0x91, 0xda, 0x33, 0x79, 0x9a, 0xec, 0x93, 0xde, 0x01, 0xef, 0x90, 0x9f, + 0xd7, 0x9f, 0xc2, 0x58, 0x1a, 0x7e, 0x4b, 0x5e, 0xc6, 0x45, 0x56, 0x2d, 0xaf, 0xb2, 0x04, 0x99, 0x2e, 0x78, 0xf1, + 0xd5, 0x4c, 0x97, 0xf7, 0xb1, 0x3e, 0x60, 0x3c, 0xa5, 0x78, 0xdd, 0x10, 0xa5, 0x5f, 0xb4, 0x3c, 0x2b, 0xd4, 0xe5, + 0x49, 0xc5, 0x6c, 0xcf, 0x4a, 0x70, 0x3a, 0x05, 0x13, 0x7c, 0xfd, 0xd3, 0xf5, 0x3e, 0x01, 0x5c, 0x50, 0xa8, 0x39, + 0x2d, 0xe4, 0xca, 0x60, 0x39, 0x59, 0xe8, 0x4e, 0xc0, 0x0c, 0x95, 0x02, 0x2f, 0x50, 0xf0, 0x17, 0x0d, 0x8c, 0xe8, + 0x0b, 0xf7, 0x9b, 0x0c, 0x0c, 0xd2, 0xa5, 0x39, 0x11, 0xc6, 0x8e, 0xdb, 0x49, 0xd2, 0x56, 0x94, 0x33, 0xce, 0xde, + 0xab, 0x2b, 0x05, 0x18, 0xe0, 0x6d, 0x6f, 0xa2, 0x4d, 0x82, 0x5e, 0x0b, 0x4a, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0x32, + 0xc2, 0xc5, 0x87, 0x95, 0xc7, 0x82, 0x7b, 0xf6, 0x0b, 0x89, 0xb5, 0xf5, 0x03, 0x63, 0x36, 0x2f, 0x58, 0xa0, 0x50, + 0x81, 0x02, 0xcb, 0x99, 0xb6, 0x34, 0xad, 0x86, 0xfc, 0xf0, 0x08, 0xad, 0x4d, 0xab, 0x01, 0x3f, 0x3c, 0xaa, 0xa3, + 0xec, 0x18, 0xb2, 0x9c, 0xf8, 0x19, 0xd4, 0xeb, 0x3a, 0x32, 0x29, 0x26, 0xbb, 0x57, 0x5f, 0x9e, 0xfa, 0xa3, 0xba, + 0x05, 0xd7, 0x0f, 0x40, 0x00, 0x1b, 0x80, 0x43, 0xa0, 0x1a, 0x2c, 0x8d, 0x08, 0x16, 0x65, 0x0a, 0xed, 0x6b, 0xe8, + 0xbd, 0xd1, 0xf0, 0x5f, 0xe0, 0x2e, 0x22, 0x57, 0xfe, 0x27, 0x08, 0xfc, 0x15, 0x65, 0x5a, 0x99, 0xe2, 0x7f, 0xa2, + 0xd5, 0x2b, 0x94, 0xb3, 0xa6, 0x35, 0x1f, 0x44, 0x6b, 0x22, 0x54, 0x33, 0x86, 0xe0, 0xdf, 0xca, 0x32, 0x6d, 0xa9, + 0xaa, 0xd4, 0x87, 0xc6, 0x6b, 0xad, 0x70, 0x96, 0x8f, 0x23, 0xef, 0x35, 0x86, 0x8e, 0x4d, 0x9c, 0xa5, 0x9c, 0x4a, + 0x9d, 0xbd, 0x39, 0x94, 0x91, 0x03, 0x9c, 0x4e, 0xd8, 0x78, 0x9a, 0x1c, 0xcb, 0x69, 0xe2, 0x20, 0xf3, 0x73, 0x86, + 0x91, 0x55, 0x0d, 0x08, 0x8b, 0xb2, 0xa1, 0xb4, 0x05, 0x98, 0xe4, 0x84, 0x90, 0x29, 0x86, 0xa2, 0xc8, 0x47, 0xba, + 0x1f, 0xd6, 0x9b, 0xd5, 0x7d, 0xf1, 0x4e, 0x03, 0x9c, 0x86, 0x09, 0x04, 0x02, 0x2f, 0xe2, 0x9b, 0x4c, 0x5c, 0x82, + 0xc7, 0xf0, 0x00, 0xbe, 0x04, 0x37, 0xb9, 0x94, 0xfd, 0xab, 0x0a, 0x73, 0x5c, 0x5b, 0xc0, 0xa0, 0xc1, 0xea, 0x41, + 0x74, 0xb8, 0x94, 0x36, 0xbb, 0x0a, 0x10, 0x1b, 0x53, 0x88, 0x65, 0xc1, 0xd6, 0x96, 0x3d, 0xfb, 0x59, 0x35, 0x0d, + 0xad, 0x13, 0x4e, 0xc5, 0x65, 0x0e, 0x51, 0x54, 0x06, 0x31, 0xb8, 0x23, 0x79, 0x7c, 0xde, 0xa9, 0x08, 0x2f, 0x08, + 0xb8, 0x95, 0x25, 0x32, 0x5c, 0xd1, 0xe5, 0xe8, 0x96, 0xae, 0x47, 0x37, 0x74, 0x4c, 0x27, 0x7f, 0x1f, 0xa3, 0x45, + 0xb6, 0x4a, 0xdd, 0xd0, 0xf5, 0x68, 0x49, 0xbf, 0x1f, 0xd3, 0xa3, 0xbf, 0x8d, 0xc9, 0x74, 0x89, 0x87, 0x09, 0xbd, + 0x00, 0xc7, 0x2e, 0x52, 0xa3, 0xa7, 0xa6, 0x6f, 0x70, 0x58, 0x8d, 0xf2, 0x21, 0x1f, 0xe5, 0x94, 0x8f, 0x8a, 0x61, + 0x35, 0x02, 0x4f, 0xc7, 0x6a, 0xc8, 0x47, 0x15, 0xe5, 0xa3, 0xf3, 0x61, 0x35, 0x3a, 0x27, 0xcd, 0xa6, 0xbf, 0xaa, + 0xf8, 0x55, 0xc9, 0x2e, 0x60, 0x5b, 0xc0, 0xf2, 0x75, 0xab, 0x6c, 0x99, 0xfa, 0xab, 0xda, 0x9c, 0xcc, 0x96, 0xb3, + 0xb7, 0xd7, 0x5d, 0x4e, 0x2c, 0x1e, 0xb7, 0x4d, 0x87, 0xab, 0x2f, 0x27, 0xea, 0xa4, 0x57, 0xc8, 0x0f, 0xe3, 0xa9, + 0x50, 0xe7, 0x10, 0x98, 0x49, 0xcc, 0xc2, 0x98, 0x61, 0x33, 0x75, 0x1a, 0x28, 0x70, 0xb2, 0x91, 0xe7, 0xa2, 0x98, + 0x8d, 0x72, 0x0a, 0xef, 0x63, 0x42, 0x22, 0x01, 0x67, 0xd5, 0x49, 0x35, 0x2a, 0x20, 0xe6, 0x08, 0x0b, 0xf1, 0x11, + 0xfa, 0xa5, 0x3e, 0xf2, 0x90, 0xc0, 0x33, 0xec, 0x6b, 0x31, 0x88, 0xe1, 0x88, 0xb7, 0x95, 0x55, 0xb3, 0x30, 0x81, + 0xca, 0xaa, 0x61, 0x69, 0x2a, 0x2b, 0x68, 0x36, 0xaa, 0xfc, 0xca, 0x2a, 0x1c, 0xa3, 0x84, 0x90, 0xa8, 0xd4, 0x95, + 0x81, 0xfa, 0x24, 0x61, 0x61, 0xa9, 0x2b, 0x3b, 0x57, 0x1f, 0x9d, 0xfb, 0x95, 0x9d, 0x83, 0x0b, 0xe9, 0x20, 0xf1, + 0xaf, 0x52, 0x69, 0xda, 0xbe, 0x0e, 0x36, 0x56, 0x15, 0xdd, 0xf2, 0xdb, 0xaa, 0x88, 0xa3, 0x92, 0xba, 0x18, 0xd0, + 0xb8, 0x30, 0x22, 0x49, 0xf5, 0x1a, 0x05, 0x7f, 0x48, 0x10, 0x95, 0xc6, 0xe0, 0xd5, 0x99, 0x74, 0xad, 0xd4, 0x8a, + 0x8a, 0x41, 0x39, 0x28, 0xe0, 0xfe, 0x94, 0xb7, 0x16, 0xd2, 0xcf, 0x10, 0x51, 0x19, 0xca, 0x1b, 0xfc, 0x82, 0xc1, + 0x93, 0xd9, 0x55, 0x1a, 0x26, 0xa3, 0x0d, 0x8d, 0x47, 0x4b, 0x84, 0x83, 0x61, 0xab, 0x54, 0xe1, 0xad, 0x5f, 0x42, + 0xfa, 0x2d, 0x8d, 0x47, 0x37, 0x34, 0xb5, 0x36, 0xa7, 0x06, 0xea, 0xaa, 0x37, 0xa6, 0xb7, 0x11, 0xbc, 0xde, 0x44, + 0x4b, 0x0a, 0x5b, 0xe9, 0x34, 0xcf, 0x2e, 0x45, 0x94, 0x52, 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa3, 0x0d, + 0xae, 0x07, 0x50, 0x86, 0x86, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, 0xd2, 0x23, 0x53, 0x6b, 0x7d, 0x91, 0x45, 0xf8, 0x68, + 0x67, 0xa3, 0xa5, 0x78, 0x46, 0x2c, 0x8c, 0x2b, 0x18, 0x42, 0x5d, 0x58, 0x69, 0x0a, 0x92, 0x2e, 0x70, 0x64, 0x2f, + 0x8c, 0xab, 0x70, 0x0b, 0xa6, 0x45, 0x1b, 0x30, 0x8f, 0x02, 0x85, 0x83, 0x4b, 0x90, 0x7e, 0x42, 0xd9, 0xce, 0x51, + 0x9a, 0x1c, 0xde, 0x04, 0x5d, 0xec, 0x4d, 0x10, 0xd2, 0xae, 0x6e, 0xb2, 0x25, 0x7d, 0x83, 0xed, 0x3d, 0x3a, 0x15, + 0x15, 0x54, 0x9f, 0x5b, 0x30, 0x59, 0xb2, 0x41, 0xd8, 0x12, 0xa6, 0x67, 0xfa, 0x02, 0xb0, 0xa7, 0x0f, 0x8f, 0xf6, + 0xe6, 0xbb, 0x98, 0xbd, 0x39, 0x2c, 0xa3, 0xb1, 0xb2, 0xe0, 0xcd, 0x2d, 0xb1, 0x5b, 0xb2, 0xf1, 0x74, 0x79, 0x5c, + 0x4e, 0x97, 0x48, 0xec, 0x0c, 0xdd, 0x62, 0x7c, 0xbe, 0x5c, 0xd0, 0x04, 0xcf, 0x36, 0x56, 0xcd, 0x97, 0x06, 0x2d, + 0x25, 0x65, 0xb8, 0xde, 0x96, 0xe8, 0xff, 0xaf, 0x2e, 0x7e, 0x29, 0xc0, 0x4b, 0x30, 0x16, 0x00, 0xc2, 0x3d, 0x98, + 0x16, 0xa4, 0x36, 0xca, 0xc6, 0x3a, 0x0d, 0x53, 0x5c, 0x04, 0x26, 0xa5, 0xdf, 0x0f, 0x73, 0x96, 0x12, 0x0f, 0x3a, + 0xd4, 0x8e, 0xd2, 0xaa, 0x61, 0x33, 0x07, 0x3c, 0x92, 0x3a, 0xc7, 0x26, 0x7f, 0x1f, 0xcf, 0x02, 0x35, 0x10, 0x41, + 0x94, 0x1d, 0xe3, 0x23, 0x06, 0x2e, 0x8a, 0x74, 0xdc, 0x4e, 0x57, 0xc4, 0xe5, 0xfe, 0x31, 0x0b, 0x71, 0x92, 0x30, + 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, 0x04, 0x91, 0x5a, 0x6d, + 0x19, 0x57, 0x5d, 0x65, 0x7c, 0x0f, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, 0x9b, 0x28, 0xe4, 0x27, + 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0xef, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0xe7, 0xcd, 0x59, 0xd7, 0x50, 0x9a, 0xb8, + 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, 0x82, 0x09, 0x3a, 0x9a, + 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x9e, 0x25, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, 0x0f, 0xaa, 0x93, 0x75, + 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xcd, + 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, + 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, 0x01, 0x70, 0x32, 0xdb, + 0xdb, 0x68, 0x49, 0x37, 0x51, 0x4a, 0x6f, 0xa2, 0x35, 0x5d, 0x46, 0x17, 0xc6, 0xc4, 0x38, 0xa9, 0xe1, 0x1c, 0x80, + 0x56, 0x01, 0x24, 0x9e, 0xfa, 0xf5, 0x9e, 0x27, 0x55, 0xb8, 0xa4, 0x29, 0xb8, 0x0d, 0xfb, 0xf6, 0x99, 0x67, 0xbe, + 0x44, 0x6a, 0x8b, 0x18, 0x6b, 0xd6, 0x50, 0x71, 0xeb, 0xad, 0xfb, 0x48, 0xd4, 0xb0, 0x73, 0x5d, 0x6c, 0xa2, 0x6a, + 0x38, 0x99, 0x96, 0x80, 0xd8, 0x5a, 0x0e, 0x87, 0xee, 0x08, 0xd9, 0x3f, 0x7e, 0x74, 0xa0, 0xe7, 0x9e, 0xb4, 0xd8, + 0xb6, 0x2d, 0x7f, 0x60, 0x08, 0x53, 0xfa, 0xe5, 0x23, 0x1f, 0x10, 0x2b, 0xce, 0xe1, 0x6c, 0x04, 0xea, 0x68, 0x85, + 0x4e, 0xff, 0xaa, 0xc2, 0x42, 0x1f, 0xe0, 0xdb, 0xdb, 0x28, 0xa1, 0x9b, 0x28, 0xf7, 0xc8, 0xda, 0xb2, 0x66, 0x72, + 0x7a, 0x96, 0x85, 0xbc, 0x7d, 0xa0, 0x97, 0x0b, 0x00, 0xd1, 0x1a, 0xc4, 0xbe, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, + 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xb8, 0x92, 0xf0, 0x37, 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, + 0x39, 0x0f, 0x6a, 0x7f, 0x24, 0x5f, 0x17, 0x6d, 0x6f, 0x57, 0x18, 0x4d, 0x30, 0xf6, 0x44, 0xfb, 0x3c, 0x52, 0x8e, + 0xe2, 0x22, 0x09, 0xb3, 0xd1, 0xad, 0x3a, 0xcf, 0x69, 0x36, 0xda, 0xe8, 0x5f, 0x15, 0x1d, 0xd3, 0x5f, 0x75, 0x40, + 0x1b, 0x25, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0x34, 0xfe, 0xd7, 0x72, 0x74, 0x4b, 0xe5, 0x68, 0xe3, 0x5b, + 0x52, 0x4d, 0xa6, 0xc5, 0xb1, 0x40, 0x43, 0xaa, 0xce, 0xef, 0x0b, 0xe0, 0xe7, 0x4a, 0xe3, 0x3b, 0x6d, 0xbe, 0xf7, + 0xda, 0xbf, 0xe9, 0xe4, 0x09, 0x14, 0x4b, 0x54, 0xb0, 0x6a, 0x04, 0x76, 0xec, 0xeb, 0x3c, 0x2e, 0xcc, 0x28, 0xc5, + 0xd4, 0x9a, 0xf4, 0x63, 0xe0, 0x8a, 0x69, 0xaf, 0x00, 0x57, 0x4b, 0x70, 0x12, 0x80, 0x18, 0x9a, 0xb0, 0x67, 0xc7, + 0x10, 0xf5, 0xdc, 0x38, 0x46, 0xc9, 0x86, 0x7b, 0x40, 0xac, 0x65, 0xde, 0xca, 0x25, 0x20, 0x81, 0xb7, 0x1e, 0x26, + 0x05, 0x60, 0x0c, 0x96, 0x4b, 0xa2, 0xf3, 0x78, 0xe8, 0x13, 0xea, 0x85, 0x46, 0x9d, 0x90, 0x8d, 0x2d, 0x81, 0xe3, + 0x0f, 0xeb, 0x43, 0x20, 0x78, 0x95, 0xe7, 0xfa, 0x2b, 0xad, 0xeb, 0x2f, 0x95, 0x9e, 0x3b, 0x96, 0x17, 0xb5, 0xba, + 0x4d, 0x8d, 0x5e, 0x80, 0x85, 0xef, 0x56, 0x99, 0x47, 0x72, 0x8b, 0x90, 0xaa, 0xc0, 0x4a, 0xdd, 0x42, 0x82, 0xf9, + 0x57, 0x72, 0xb6, 0x2a, 0xf3, 0xd5, 0x23, 0xf7, 0xca, 0xd9, 0xf4, 0xf4, 0x37, 0x24, 0x68, 0x9b, 0x8e, 0x34, 0x8f, + 0xb7, 0xe8, 0xf0, 0xd9, 0xb5, 0x96, 0x98, 0x7b, 0x89, 0x8a, 0xe7, 0x53, 0xc0, 0x56, 0xcf, 0xb2, 0x2b, 0xe5, 0x63, + 0xb5, 0x8f, 0xe3, 0x67, 0xce, 0x9f, 0xa4, 0x0a, 0x2f, 0x44, 0x43, 0x09, 0x02, 0xde, 0x1c, 0xc6, 0xae, 0x50, 0x05, + 0x34, 0x34, 0x37, 0x70, 0x9c, 0xab, 0x61, 0xa5, 0x09, 0x98, 0x96, 0xf2, 0xe8, 0x00, 0x87, 0x26, 0x8f, 0xda, 0x4d, + 0xc3, 0xca, 0xd0, 0xb5, 0x46, 0x9f, 0xdb, 0x4a, 0x67, 0xbc, 0xd9, 0xf0, 0xc3, 0xa3, 0x41, 0x85, 0x3f, 0x49, 0x73, + 0x34, 0xda, 0xb9, 0xe1, 0x4e, 0x23, 0x30, 0x73, 0x25, 0x57, 0x64, 0x7f, 0x94, 0xbc, 0xfc, 0x9e, 0x5e, 0x58, 0x40, + 0x7f, 0xfe, 0xfb, 0x62, 0xc2, 0x49, 0x4b, 0x4c, 0x88, 0x96, 0x0e, 0x5a, 0x74, 0xb0, 0xa7, 0xbc, 0xb2, 0x2f, 0xf1, + 0xd2, 0x39, 0xfe, 0xcf, 0xf5, 0x58, 0xfb, 0x0a, 0x84, 0x56, 0x27, 0x0f, 0xdb, 0x93, 0x05, 0xa2, 0x06, 0x54, 0xb3, + 0xab, 0x72, 0x94, 0x69, 0x67, 0x45, 0xb6, 0x0d, 0x99, 0xeb, 0x7e, 0x96, 0x86, 0xcd, 0x64, 0xc7, 0xc2, 0x32, 0xc3, + 0x60, 0xed, 0x54, 0xd1, 0xe7, 0xa0, 0xe5, 0x47, 0xf0, 0xac, 0xa9, 0x3c, 0xf3, 0xd9, 0x2c, 0x23, 0x5e, 0xa0, 0x73, + 0x4e, 0xc5, 0xa2, 0x29, 0x1d, 0x2b, 0x77, 0xbb, 0x12, 0x8d, 0x25, 0xca, 0x28, 0x08, 0x6a, 0x1b, 0x84, 0x5d, 0x97, + 0xee, 0x49, 0x9f, 0xf6, 0xf1, 0x69, 0x05, 0xfa, 0x1e, 0xdf, 0x65, 0x20, 0x31, 0xf5, 0x24, 0x0f, 0x55, 0xa3, 0x39, + 0x3a, 0x79, 0x96, 0xa7, 0x1a, 0x9f, 0x5f, 0xc9, 0xce, 0x9a, 0x77, 0xab, 0x31, 0xc5, 0x7f, 0xa4, 0x6e, 0xdf, 0xb9, + 0x0c, 0x4d, 0xf4, 0xd7, 0xf2, 0xa0, 0xa5, 0xb0, 0xe0, 0xb8, 0x6d, 0xfc, 0xf5, 0xdb, 0xcc, 0x21, 0x86, 0xa5, 0xcb, + 0xe1, 0x4d, 0xe8, 0xd0, 0xdd, 0x55, 0xf6, 0xe6, 0xfa, 0x88, 0x3a, 0x75, 0xb1, 0x6e, 0x03, 0x4a, 0x96, 0xbc, 0x5b, + 0xa7, 0x27, 0x56, 0xfa, 0xf5, 0x30, 0xdc, 0x9b, 0x47, 0xcd, 0xee, 0xee, 0x76, 0x13, 0xd2, 0xb6, 0x0f, 0xc6, 0xfb, + 0x12, 0x16, 0xe2, 0xbc, 0xc3, 0x0e, 0x7e, 0x0e, 0xab, 0x87, 0x7c, 0xf0, 0x3b, 0x8e, 0x33, 0x8c, 0x7e, 0xa6, 0x0c, + 0x7d, 0x5e, 0x14, 0xf2, 0x4a, 0x75, 0xca, 0x17, 0xba, 0xb5, 0x4c, 0xbd, 0xdf, 0xc4, 0x6f, 0x5a, 0x01, 0x62, 0xbc, + 0xae, 0x58, 0x29, 0xde, 0xd0, 0x0a, 0xe3, 0x1a, 0xb8, 0x4d, 0x0e, 0xb5, 0x54, 0x0b, 0x44, 0x5d, 0x7e, 0xf2, 0x90, + 0x47, 0x46, 0x9d, 0x09, 0xdf, 0x3d, 0xe4, 0xbe, 0x74, 0x6d, 0xbf, 0x89, 0x5f, 0x6a, 0xda, 0xe1, 0xfe, 0x40, 0x77, + 0xb4, 0xee, 0xfe, 0xe6, 0xd9, 0xfc, 0x3c, 0x32, 0x5f, 0x0c, 0xb0, 0x59, 0xfb, 0x8c, 0xcb, 0x9e, 0xe1, 0xbe, 0x37, + 0x3d, 0x18, 0x0b, 0x08, 0x24, 0x66, 0xe8, 0x65, 0xe0, 0x02, 0x17, 0xb8, 0x2b, 0x0c, 0x18, 0xe2, 0x9a, 0x96, 0xdc, + 0x6a, 0x2b, 0x5b, 0x1f, 0x79, 0x1b, 0x15, 0x82, 0x75, 0xdd, 0x71, 0x93, 0xe4, 0x10, 0x9c, 0xb0, 0xe5, 0xde, 0xd7, + 0x5e, 0x3b, 0xc3, 0x5f, 0x06, 0xc2, 0xb9, 0x25, 0x7a, 0x46, 0x6d, 0x0f, 0xb5, 0xba, 0xd7, 0xf0, 0x2a, 0x9b, 0xc8, + 0xb3, 0x7e, 0x33, 0x2f, 0x0d, 0xfb, 0x82, 0xd7, 0x52, 0x70, 0x68, 0x6c, 0xb7, 0xc2, 0x2d, 0x16, 0xef, 0x68, 0xb5, + 0xb2, 0xd6, 0x56, 0x7b, 0xad, 0x54, 0xf4, 0xee, 0x35, 0xc7, 0x89, 0xb3, 0x14, 0xb6, 0x1f, 0xde, 0x5f, 0xb0, 0x6b, + 0x02, 0x18, 0xb4, 0x98, 0x2c, 0x50, 0x82, 0x4a, 0xd6, 0xaa, 0x76, 0x3b, 0x25, 0x7e, 0xb9, 0x5f, 0x75, 0x99, 0xed, + 0x3c, 0x7e, 0xdd, 0xa4, 0x7d, 0xe1, 0x73, 0xf4, 0xc3, 0xfc, 0xc1, 0x3a, 0x29, 0x39, 0xc3, 0xb8, 0x96, 0xff, 0x5f, + 0x45, 0x2f, 0x8b, 0x2c, 0x8d, 0xb6, 0x86, 0x07, 0xb3, 0xa1, 0x36, 0x7d, 0x68, 0x8c, 0xca, 0x2d, 0x1b, 0x45, 0x44, + 0xab, 0x5b, 0x10, 0xcc, 0x28, 0xee, 0x4b, 0xb4, 0x79, 0xa5, 0xca, 0xc2, 0x3b, 0x7c, 0x61, 0xa3, 0x37, 0x6c, 0x4f, + 0x08, 0xe5, 0xfb, 0xa7, 0x85, 0x59, 0xb5, 0x54, 0x34, 0xd8, 0x2e, 0xe1, 0x5d, 0x8c, 0x2a, 0xfd, 0x84, 0xc9, 0x96, + 0x05, 0x53, 0xfd, 0xff, 0xb1, 0xc8, 0xd2, 0x36, 0x45, 0x07, 0xa6, 0xb3, 0xe9, 0xd3, 0x49, 0xb7, 0xb8, 0xce, 0x80, + 0x45, 0x04, 0x5b, 0x2a, 0x1c, 0x8f, 0x52, 0xbb, 0x41, 0xc2, 0x44, 0x70, 0x13, 0xf5, 0xb2, 0xa3, 0x65, 0x4a, 0x56, + 0x05, 0x3c, 0xbf, 0x72, 0x95, 0xe9, 0x38, 0x1a, 0xfa, 0xfd, 0xb3, 0xd4, 0x84, 0x7e, 0xa5, 0x5e, 0xaa, 0xe2, 0x3c, + 0x8c, 0xaa, 0x43, 0x85, 0x31, 0x5a, 0xd2, 0x14, 0x8e, 0xc1, 0xec, 0x22, 0x4c, 0xf1, 0x72, 0xb6, 0x4d, 0xd8, 0x57, + 0x0c, 0xe4, 0x52, 0x1b, 0xd4, 0x6b, 0x4a, 0xb4, 0x66, 0xed, 0xcd, 0x9c, 0x12, 0x7a, 0xc1, 0x4a, 0xff, 0x2e, 0xb4, + 0x06, 0x81, 0xa2, 0x6c, 0xa6, 0x4c, 0x37, 0xba, 0x9d, 0x17, 0x34, 0xa1, 0x05, 0x5d, 0x91, 0x1a, 0xf4, 0xbd, 0x4e, + 0xce, 0x8e, 0x4e, 0x76, 0x66, 0xd6, 0x63, 0x56, 0x0c, 0x27, 0xd3, 0x18, 0xae, 0x69, 0xb1, 0xbb, 0xa6, 0x2d, 0x9b, + 0x37, 0xae, 0xc6, 0xc6, 0x69, 0xd0, 0x2e, 0x90, 0xb6, 0x69, 0x6e, 0x3f, 0xf5, 0xb8, 0xfd, 0x75, 0xcd, 0x96, 0xd3, + 0xde, 0x7a, 0xb7, 0xeb, 0xa5, 0x60, 0x23, 0xea, 0xf1, 0xf1, 0x6b, 0x25, 0x5d, 0xb7, 0x5c, 0x7e, 0x0a, 0xcf, 0x1e, + 0x5f, 0xbf, 0xf4, 0xc1, 0xe5, 0x68, 0xd5, 0xe6, 0xee, 0x97, 0xfb, 0xc8, 0x72, 0x5f, 0x35, 0xb4, 0x5c, 0xcf, 0x50, + 0x93, 0x3c, 0x1b, 0xed, 0x1d, 0x6a, 0xc1, 0x72, 0xd6, 0x4d, 0x78, 0x62, 0xb0, 0x63, 0xaf, 0x1a, 0x9b, 0xa3, 0x32, + 0x97, 0xac, 0x06, 0x09, 0xf4, 0x49, 0x9e, 0x69, 0xfa, 0x47, 0x19, 0xe6, 0xa3, 0x5b, 0x9a, 0x03, 0xae, 0x58, 0x65, + 0x2f, 0x19, 0xa4, 0xae, 0xda, 0x4b, 0x5c, 0xf9, 0x0a, 0x87, 0x64, 0x8b, 0x4f, 0x86, 0xa9, 0xfa, 0xe2, 0x92, 0x07, + 0xff, 0x6f, 0xab, 0x56, 0xe9, 0xb9, 0x49, 0x6e, 0x38, 0xfe, 0x75, 0xd2, 0xf6, 0x31, 0x31, 0x48, 0xc0, 0x53, 0xbb, + 0x18, 0xaa, 0x51, 0x55, 0xc4, 0xa2, 0xcc, 0x4d, 0xcc, 0xb1, 0x3b, 0xbb, 0x86, 0x0e, 0xca, 0xe0, 0xd7, 0x0d, 0x9f, + 0x98, 0x3b, 0xb0, 0x15, 0xe8, 0xe8, 0x44, 0x73, 0x19, 0x66, 0xe6, 0x32, 0x4c, 0xbb, 0xb6, 0x0a, 0x0c, 0xaf, 0xda, + 0x2a, 0x89, 0x72, 0x35, 0xea, 0x71, 0x33, 0x4b, 0xcd, 0x5e, 0xe4, 0xdd, 0x6b, 0xd2, 0x93, 0xf8, 0xd3, 0xa5, 0x27, + 0xaf, 0x87, 0x01, 0x91, 0x5f, 0xb3, 0x34, 0x5c, 0xa3, 0x20, 0x38, 0xb5, 0xda, 0x81, 0x34, 0x1f, 0x01, 0x32, 0x3f, + 0x4e, 0xc3, 0x0f, 0x5a, 0x9c, 0x43, 0xb6, 0x4a, 0xe3, 0xc4, 0x96, 0x46, 0x3d, 0x04, 0x77, 0xde, 0x2b, 0x1e, 0x43, + 0xe0, 0xc3, 0x8f, 0xb8, 0x19, 0x54, 0x74, 0x5b, 0x62, 0xa2, 0xb4, 0x79, 0xd4, 0x2d, 0x1f, 0x35, 0x84, 0x4a, 0x56, + 0x86, 0x97, 0x40, 0x7b, 0xf7, 0x04, 0x46, 0x95, 0x13, 0xc8, 0x0c, 0x8b, 0xc3, 0xa3, 0x61, 0xaa, 0x04, 0x45, 0x43, + 0x39, 0x5c, 0xa2, 0x1c, 0x10, 0x93, 0x40, 0x60, 0x54, 0x0c, 0x52, 0x5d, 0x99, 0x7a, 0x31, 0x48, 0xf5, 0xad, 0x8a, + 0xd4, 0x67, 0x59, 0x58, 0x51, 0xdd, 0x22, 0x3a, 0xa6, 0x43, 0x49, 0x97, 0x66, 0xa7, 0xe6, 0x5a, 0x7a, 0xa1, 0x96, + 0xe3, 0x53, 0x9d, 0x06, 0xa3, 0xf8, 0xc1, 0xa5, 0xe8, 0xb7, 0x6a, 0x3f, 0xfb, 0x6f, 0x31, 0xa5, 0x46, 0x6c, 0x6a, + 0x6f, 0x11, 0xc3, 0xaa, 0xfd, 0x98, 0x55, 0x39, 0x68, 0x77, 0x41, 0xd9, 0x58, 0x19, 0xe7, 0xf9, 0x46, 0x30, 0x73, + 0xd0, 0x36, 0x56, 0x4d, 0x1f, 0x7a, 0x23, 0x46, 0xed, 0x8d, 0xa9, 0xc6, 0x3d, 0x81, 0x9f, 0x36, 0x68, 0xba, 0x17, + 0x79, 0x8e, 0x7a, 0xe4, 0xdd, 0xff, 0xcc, 0x91, 0x9d, 0xc9, 0x17, 0xb1, 0x4c, 0xea, 0xf6, 0x31, 0x09, 0x16, 0xaa, + 0x8e, 0xd1, 0x85, 0x1b, 0x99, 0xd2, 0x7e, 0xee, 0x4d, 0x3f, 0xe2, 0x99, 0xdc, 0x6f, 0x87, 0x46, 0x7d, 0x69, 0x58, + 0x4b, 0x8a, 0xa8, 0x2f, 0xe8, 0xad, 0xa9, 0x8e, 0x8e, 0xa8, 0xd7, 0x11, 0x58, 0x5d, 0xd1, 0x16, 0x35, 0x00, 0x93, + 0x71, 0x6d, 0x6b, 0xf3, 0x39, 0x98, 0xda, 0xaa, 0x0a, 0x9e, 0xd0, 0x7d, 0xa1, 0x74, 0x6f, 0x52, 0xd7, 0xad, 0x21, + 0xb6, 0x80, 0x01, 0x81, 0x1b, 0x3d, 0x35, 0xfd, 0x41, 0x13, 0x15, 0x80, 0x06, 0x8d, 0xdb, 0x99, 0xce, 0x91, 0xe8, + 0x77, 0x6a, 0xd3, 0x36, 0x53, 0xbd, 0xaa, 0x7c, 0x00, 0x15, 0x7f, 0x96, 0xce, 0x2e, 0xcc, 0x88, 0x05, 0x30, 0xee, + 0x81, 0x33, 0xd5, 0x3b, 0xcd, 0xc0, 0x7a, 0x22, 0xcf, 0xb3, 0x92, 0x27, 0x52, 0xc0, 0x8c, 0xc8, 0xab, 0x2b, 0x29, + 0x60, 0x18, 0xd4, 0x00, 0xa0, 0x45, 0x73, 0x19, 0x4d, 0xf8, 0xa3, 0x9a, 0xde, 0x95, 0x87, 0x3f, 0xd2, 0xb9, 0xbe, + 0x1b, 0xd7, 0x60, 0xa8, 0xbc, 0xae, 0xf8, 0x5e, 0xa6, 0xef, 0xf8, 0x63, 0x2f, 0xd3, 0x52, 0xae, 0x8b, 0xbd, 0x2c, + 0x8f, 0xbe, 0xe3, 0x4f, 0x74, 0x9e, 0xa3, 0xc7, 0x35, 0x4d, 0xe3, 0xcd, 0x5e, 0x96, 0xbf, 0x7f, 0xf7, 0xd8, 0xe6, + 0x79, 0x34, 0xae, 0xe9, 0x0d, 0xe7, 0x9f, 0x5c, 0xa6, 0x89, 0xae, 0x6a, 0xfc, 0xf8, 0xef, 0x36, 0xd7, 0xe3, 0x9a, + 0x5e, 0x49, 0x51, 0x2d, 0xf7, 0x8a, 0x3a, 0xfa, 0xee, 0xe8, 0xef, 0xfc, 0x3b, 0xd3, 0xbd, 0xa3, 0x9a, 0xfe, 0xb5, + 0x8e, 0x8b, 0x8a, 0x17, 0x7b, 0xc5, 0xfd, 0xed, 0xef, 0x7f, 0x7f, 0x6c, 0x33, 0x3e, 0xae, 0xe9, 0x86, 0xc7, 0x1d, + 0x6d, 0x9f, 0x3c, 0x79, 0xcc, 0xff, 0x56, 0xd7, 0xf4, 0x37, 0xe6, 0x07, 0x47, 0x3d, 0xcd, 0x3c, 0x3d, 0x7c, 0x2e, + 0x9b, 0xa8, 0x01, 0x43, 0x0f, 0x0d, 0x60, 0x29, 0xad, 0x9a, 0xe6, 0x0e, 0xaf, 0x5c, 0x70, 0xfb, 0x3e, 0x8b, 0xd3, + 0x78, 0x05, 0x07, 0xc1, 0x16, 0x8d, 0xb3, 0x0a, 0xe0, 0x54, 0x81, 0xf7, 0x8c, 0x4a, 0x9a, 0x95, 0xf2, 0x37, 0xce, + 0x3f, 0xc1, 0xa0, 0x21, 0xa4, 0x8d, 0x8a, 0x0c, 0xf4, 0x76, 0xa5, 0x23, 0x1b, 0xa1, 0xff, 0x66, 0x33, 0x0e, 0x8e, + 0x0f, 0xa3, 0xd7, 0xef, 0x87, 0x05, 0x13, 0x61, 0x41, 0x08, 0xfd, 0x33, 0x2c, 0xc0, 0xa1, 0xa4, 0x60, 0x5e, 0x3e, + 0xe3, 0x7b, 0xae, 0x8d, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xf6, 0x01, 0x55, 0x8f, 0xbe, 0x43, 0x37, 0xc4, 0xcb, 0x0a, + 0x0b, 0x86, 0x56, 0x35, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x4a, 0xf0, 0x89, 0x07, 0xf8, 0xe8, 0x31, 0x99, 0x71, + 0x75, 0xad, 0x7d, 0x7b, 0x11, 0x16, 0x34, 0xd0, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xff, 0x02, 0x3c, 0x05, 0x06, 0x3e, + 0x2c, 0xec, 0xba, 0x03, 0xcf, 0xe7, 0x37, 0xc3, 0x3a, 0xba, 0xf0, 0xa3, 0xbf, 0x59, 0x17, 0xf6, 0x8c, 0x4c, 0xe5, + 0x71, 0x39, 0x9c, 0x4c, 0x07, 0x03, 0xe9, 0xe2, 0xb8, 0x9d, 0x66, 0xf3, 0xdf, 0xe6, 0x72, 0xb1, 0x40, 0xdd, 0x37, + 0xce, 0xeb, 0x4c, 0xff, 0x8d, 0xb4, 0xf3, 0xc1, 0xeb, 0xd3, 0x7f, 0x9d, 0x7d, 0x38, 0x7d, 0x01, 0xce, 0x07, 0x1f, + 0x9f, 0xff, 0xf8, 0xfc, 0xbd, 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0x72, 0x18, + 0xc6, 0x0f, 0x0b, 0x65, 0xf4, 0x40, 0x8e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, + 0x8b, 0xeb, 0x86, 0x08, 0xd7, 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x4f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, + 0x18, 0x94, 0x0d, 0x6d, 0x3a, 0xcd, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, + 0xba, 0xfa, 0x04, 0x34, 0x00, 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0x37, 0xa8, + 0x7b, 0x32, 0xcd, 0xaa, 0x1a, 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x6d, 0x5e, + 0x2d, 0x4c, 0x73, 0xdc, 0x30, 0x54, 0x5e, 0xc9, 0x17, 0xb2, 0x81, 0xc8, 0x40, 0x32, 0x0c, 0x7b, 0x34, 0x46, 0x91, + 0xfa, 0xc1, 0xbe, 0x77, 0xfc, 0x36, 0x97, 0x10, 0x4d, 0x31, 0x03, 0xe9, 0xfc, 0x73, 0xa1, 0x9c, 0xcb, 0x25, 0xe3, + 0x73, 0xb1, 0x38, 0x01, 0xb7, 0xf3, 0xb9, 0x58, 0x44, 0x18, 0x94, 0x2f, 0x83, 0x58, 0x25, 0x60, 0xf7, 0xe2, 0xa0, + 0x47, 0x3a, 0xa1, 0x0d, 0xec, 0x06, 0x92, 0x6c, 0x50, 0xda, 0x95, 0x86, 0x28, 0x77, 0xca, 0xa3, 0x0d, 0x22, 0x0f, + 0xb1, 0x6a, 0x5e, 0xb5, 0x3d, 0xd9, 0xcc, 0xc5, 0x04, 0x57, 0x59, 0xcc, 0xe4, 0x34, 0x3e, 0x66, 0xc5, 0x34, 0x86, + 0x52, 0xe2, 0x34, 0x0d, 0x63, 0x3a, 0xa1, 0x82, 0x90, 0x84, 0xf1, 0x79, 0xbc, 0xa0, 0x09, 0x4a, 0x09, 0x42, 0x08, + 0xf9, 0x31, 0x42, 0xdb, 0x1c, 0x58, 0xf2, 0x76, 0xfb, 0x79, 0x2a, 0xbe, 0x3d, 0xc3, 0x65, 0x54, 0x84, 0x6e, 0xd1, + 0x59, 0xc3, 0xbf, 0x11, 0x15, 0x34, 0xc6, 0x8a, 0x21, 0x08, 0x78, 0x81, 0x51, 0x09, 0x0b, 0x12, 0xb3, 0x0a, 0xa2, + 0x08, 0x94, 0xf3, 0x78, 0xc1, 0x0a, 0xda, 0xb4, 0x39, 0x8d, 0xb5, 0x49, 0x50, 0xcf, 0x61, 0xa9, 0x1d, 0x48, 0xa5, + 0x42, 0xec, 0xf1, 0x99, 0x88, 0x3e, 0x69, 0x43, 0x03, 0x40, 0x81, 0x52, 0x72, 0xf1, 0x9b, 0xaf, 0xf7, 0x70, 0x53, + 0xd0, 0xff, 0x6c, 0x6b, 0xa2, 0x9d, 0xe5, 0xea, 0xd0, 0x9b, 0x2f, 0x68, 0x9c, 0xe7, 0x10, 0x8a, 0xcd, 0x20, 0x90, + 0x8b, 0xac, 0x82, 0x88, 0x16, 0x9b, 0xc0, 0x84, 0x84, 0x83, 0x36, 0xfd, 0x02, 0xa9, 0x0d, 0x31, 0xb9, 0xf2, 0xc4, + 0xc0, 0x6e, 0xab, 0x04, 0x01, 0x47, 0x7a, 0x9e, 0x7d, 0x6e, 0x62, 0xac, 0x69, 0x6a, 0x66, 0xe2, 0x6d, 0x28, 0x44, + 0x83, 0x16, 0x44, 0x33, 0x78, 0xff, 0x5c, 0x71, 0xbc, 0xea, 0xc0, 0x0f, 0x78, 0xe7, 0xe2, 0xcc, 0xab, 0x99, 0x47, + 0xe4, 0xd4, 0xe7, 0x39, 0xa2, 0x5f, 0xf2, 0xb0, 0x1a, 0xe9, 0x64, 0x8c, 0x95, 0xc4, 0x41, 0x6f, 0x83, 0x05, 0x73, + 0x42, 0x57, 0x3c, 0xb4, 0x7c, 0xfc, 0x0b, 0x64, 0x32, 0x4a, 0x6a, 0xac, 0xe8, 0x4a, 0x8b, 0x11, 0xe7, 0x35, 0xcc, + 0xd2, 0x64, 0x45, 0x17, 0x0b, 0x4d, 0x9a, 0x85, 0x32, 0x0d, 0xf0, 0x09, 0xb4, 0x18, 0xb9, 0x87, 0x9a, 0x36, 0x10, + 0x1a, 0xf6, 0x87, 0x80, 0x8f, 0xdc, 0x43, 0x87, 0xff, 0x9f, 0x67, 0x17, 0x88, 0xb4, 0x77, 0x69, 0x22, 0xe3, 0x91, + 0xba, 0x81, 0x83, 0x62, 0x7c, 0xec, 0x9b, 0x89, 0x5f, 0x39, 0xa3, 0xf7, 0x49, 0xe5, 0x3b, 0x7c, 0xb0, 0xfc, 0xf1, + 0xa6, 0x66, 0x56, 0x46, 0xb0, 0x1e, 0x76, 0x3b, 0x5c, 0x10, 0x6d, 0x17, 0x40, 0xea, 0x19, 0xaf, 0x16, 0xbe, 0xf1, + 0x6a, 0x7c, 0x87, 0xf1, 0xaa, 0xb3, 0xfa, 0x0a, 0x73, 0xb2, 0x45, 0x7d, 0x96, 0x92, 0xe7, 0xe7, 0x28, 0x13, 0x6c, + 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, 0x0e, 0x23, 0x81, 0xaa, + 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, 0x03, 0xa1, 0xa1, 0xb1, + 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xdd, 0xae, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, 0xac, 0x46, 0x13, 0xe0, + 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, 0x49, 0x66, 0x65, 0x34, + 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, 0xba, 0xcc, 0x92, 0xcc, + 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, 0x90, 0x1f, 0x40, 0x19, + 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, 0x66, 0x57, 0xbc, 0xac, + 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0xec, 0x2e, 0xb7, 0x3d, 0x2a, 0xcc, 0xab, 0x37, 0xcf, 0x7f, 0x3c, 0x6d, 0xbc, + 0xda, 0x47, 0x1c, 0x0d, 0xc1, 0xb6, 0x62, 0x8c, 0xd1, 0x5b, 0x7c, 0x1a, 0x4c, 0x94, 0x6b, 0x04, 0x7a, 0x97, 0x82, + 0x7e, 0xfb, 0x6b, 0x3d, 0x01, 0xaf, 0xb8, 0x5e, 0x7e, 0xc9, 0x27, 0xc0, 0x12, 0x15, 0x7a, 0x56, 0x98, 0x9b, 0x95, + 0xd9, 0x9d, 0xdd, 0x8a, 0xcc, 0xb4, 0x2b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, 0x16, 0x2e, 0x5d, 0xd3, 0xed, 0x60, + 0x57, 0x4b, 0xcf, 0x12, 0x79, 0xb7, 0x2b, 0xa1, 0x43, 0x76, 0xc0, 0xbd, 0x97, 0xf1, 0x2d, 0xbc, 0x2c, 0xbd, 0x6e, + 0x36, 0x83, 0x27, 0x80, 0x99, 0x70, 0xe1, 0x2c, 0x8b, 0x63, 0x26, 0x92, 0x50, 0xc5, 0xe6, 0x6a, 0x88, 0xbc, 0x15, + 0xa1, 0x35, 0xfb, 0x2b, 0x14, 0x23, 0xb0, 0x3b, 0xf9, 0xf0, 0x29, 0x5b, 0xcd, 0xd6, 0x80, 0x9a, 0x7f, 0x95, 0x09, + 0xa0, 0xb9, 0x76, 0x2d, 0xd8, 0xa6, 0xd0, 0xe6, 0xba, 0x7e, 0x1a, 0xaf, 0xe2, 0x04, 0x54, 0x37, 0xe0, 0x2d, 0x72, + 0xad, 0x45, 0x57, 0x06, 0x5d, 0x94, 0xde, 0x53, 0x8e, 0x25, 0x85, 0x8e, 0xbe, 0xf7, 0x84, 0x3a, 0xf7, 0x0c, 0xe0, + 0x92, 0x46, 0xcd, 0x53, 0x2d, 0x65, 0x2c, 0x00, 0x16, 0x3a, 0x98, 0x29, 0xb2, 0x15, 0xdd, 0x18, 0x4c, 0x0a, 0x78, + 0x6b, 0x80, 0x3f, 0x44, 0x56, 0xa9, 0xbb, 0x62, 0x19, 0x96, 0x9e, 0xfd, 0x75, 0xbf, 0x1f, 0x7b, 0xf6, 0xd7, 0x2b, + 0x4d, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x8d, 0x01, 0x44, 0x4e, 0xf5, 0x40, 0x98, 0x88, 0x62, 0x4d, 0xdf, 0xbf, 0x53, + 0x93, 0x45, 0x81, 0xd0, 0xef, 0xd5, 0xeb, 0x49, 0x49, 0x40, 0xa7, 0x56, 0xb1, 0x93, 0x81, 0x36, 0xfb, 0x80, 0x80, + 0xa8, 0x7e, 0x46, 0x36, 0x5f, 0x28, 0xe7, 0x62, 0x15, 0x3e, 0x7c, 0x4c, 0x21, 0xa0, 0x70, 0x47, 0x8d, 0xce, 0xdb, + 0x10, 0x09, 0x94, 0x15, 0x8a, 0x58, 0xf3, 0x62, 0x2d, 0x09, 0x99, 0x8f, 0x17, 0x28, 0xb8, 0x72, 0xc0, 0xae, 0x9c, + 0x4d, 0x86, 0x65, 0xc4, 0x59, 0x78, 0xf7, 0x37, 0x93, 0x05, 0x41, 0xcd, 0x95, 0x1f, 0xc8, 0x71, 0x2f, 0x53, 0x63, + 0x4f, 0x35, 0x6a, 0x10, 0x4c, 0x46, 0x10, 0x18, 0x6e, 0xf8, 0x15, 0x1f, 0x1f, 0x2d, 0x08, 0xa8, 0xc8, 0xac, 0x59, + 0x88, 0x79, 0x71, 0xfc, 0x08, 0x50, 0x63, 0x46, 0x47, 0x4f, 0xa6, 0x9c, 0xc1, 0x21, 0x4a, 0xc7, 0x20, 0xa3, 0x15, + 0xf0, 0x5b, 0xa8, 0xdf, 0xad, 0x13, 0xdf, 0x87, 0x7e, 0x15, 0xf4, 0x22, 0x06, 0x86, 0x23, 0x9a, 0x1c, 0x86, 0x7c, + 0x30, 0x19, 0x80, 0xb6, 0xc4, 0xdb, 0x7d, 0x2d, 0xad, 0xb8, 0x39, 0x5d, 0x3a, 0xdd, 0x3f, 0x69, 0x13, 0x24, 0x91, + 0x4a, 0x56, 0x2a, 0x62, 0x00, 0xa1, 0x2c, 0xd5, 0x36, 0x59, 0x83, 0x65, 0x85, 0x59, 0xd2, 0xdc, 0xa0, 0x24, 0xee, + 0x6f, 0x06, 0x8e, 0x51, 0xb3, 0x4e, 0xc3, 0xb2, 0xe5, 0x46, 0x0d, 0xf0, 0x39, 0x09, 0x2b, 0xec, 0x0d, 0x67, 0x26, + 0xbd, 0x33, 0x1d, 0xae, 0x8e, 0x39, 0x7b, 0xcd, 0x11, 0x8c, 0x23, 0xc1, 0x1b, 0x0f, 0x5d, 0x32, 0x0d, 0x15, 0x99, + 0x32, 0x0e, 0xa6, 0x3d, 0xc0, 0xbd, 0xe7, 0x60, 0x1c, 0xc6, 0x06, 0x95, 0x25, 0xf5, 0xa9, 0x77, 0x17, 0x02, 0x41, + 0x5a, 0xeb, 0x65, 0x3e, 0xc3, 0xd3, 0x33, 0x42, 0xd9, 0x1f, 0x72, 0xf8, 0x02, 0xec, 0x28, 0xc8, 0xc9, 0x84, 0x3f, + 0x79, 0xb8, 0x1f, 0xa8, 0x8a, 0x0f, 0x82, 0x83, 0x58, 0xa4, 0x07, 0xc1, 0x40, 0xc0, 0xaf, 0x82, 0x1f, 0x54, 0x52, + 0x1e, 0x5c, 0xc4, 0xc5, 0x41, 0xbc, 0x8a, 0x8b, 0xea, 0xe0, 0x26, 0xab, 0x96, 0x07, 0xa6, 0x43, 0x00, 0xcd, 0x1b, + 0x0c, 0xe2, 0x41, 0x70, 0x10, 0x0c, 0x0a, 0x33, 0xb5, 0x2b, 0x56, 0x36, 0x8e, 0x33, 0x13, 0xa2, 0x2c, 0x68, 0x06, + 0x08, 0x6b, 0x9c, 0x06, 0xc0, 0xa7, 0xae, 0x59, 0x4a, 0x2f, 0x30, 0xdc, 0x80, 0x98, 0xae, 0xa1, 0x0f, 0xc0, 0x23, + 0xaf, 0x69, 0x0c, 0x4b, 0xe0, 0x62, 0x30, 0x20, 0x17, 0x10, 0xb9, 0x60, 0x4d, 0x6d, 0x10, 0x87, 0x70, 0xad, 0xec, + 0xb4, 0xf7, 0x81, 0x99, 0x76, 0x3b, 0x40, 0x54, 0x9e, 0x90, 0x7e, 0xdf, 0x7e, 0x43, 0xfd, 0x0b, 0xf6, 0x12, 0xec, + 0xaf, 0x8a, 0x2a, 0xcc, 0xa5, 0xd2, 0x7c, 0x5f, 0xb2, 0x93, 0x81, 0x8a, 0x38, 0xbc, 0xe7, 0x48, 0xd1, 0x46, 0xe5, + 0xb2, 0xec, 0xc9, 0xb2, 0xe1, 0x2b, 0x71, 0xc5, 0x9d, 0x1f, 0x57, 0x25, 0x65, 0x5e, 0x65, 0x2b, 0xc5, 0xfe, 0xcd, + 0xb8, 0xe6, 0xfe, 0xc0, 0xfa, 0xb3, 0xf9, 0x0a, 0xae, 0xad, 0xde, 0xbb, 0x26, 0xd7, 0x88, 0x9c, 0x25, 0x94, 0x4b, + 0x6a, 0x9b, 0x87, 0xb7, 0xf4, 0x7d, 0x7e, 0xf5, 0x6d, 0xa6, 0xd3, 0xf8, 0xac, 0xc2, 0xc2, 0x85, 0x68, 0x45, 0x70, + 0x68, 0xc8, 0x45, 0xf3, 0x08, 0x30, 0xd7, 0x3e, 0x5b, 0x41, 0x41, 0xea, 0xb3, 0x0a, 0xbd, 0x5b, 0x21, 0xe1, 0x85, + 0x66, 0x97, 0xee, 0x07, 0x52, 0xc6, 0xed, 0xa1, 0x25, 0x4c, 0x5a, 0x5e, 0x84, 0xf7, 0x5e, 0x73, 0x93, 0x7b, 0x16, + 0x62, 0xf4, 0x22, 0xcf, 0x4e, 0xc0, 0x58, 0x77, 0xc9, 0xce, 0x86, 0x27, 0x7e, 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, + 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x01, + 0x09, 0x29, 0x22, 0x91, 0xac, 0xd5, 0x49, 0xf2, 0x85, 0xee, 0x02, 0x30, 0xfa, 0xc5, 0x2c, 0x8d, 0x96, 0x77, 0x9a, + 0x59, 0x20, 0x79, 0x86, 0xbe, 0xeb, 0x60, 0x7b, 0x63, 0x1f, 0xa4, 0x9c, 0x1f, 0x8b, 0xe9, 0x60, 0xc0, 0x89, 0x86, + 0x1b, 0x2f, 0x95, 0xb8, 0x56, 0xb7, 0xb8, 0x63, 0x18, 0x4b, 0x7d, 0x5b, 0xc4, 0xe0, 0x80, 0x5d, 0xb4, 0xb2, 0xdb, + 0x07, 0xd8, 0x57, 0x8e, 0x77, 0xa9, 0xb2, 0x3b, 0x3d, 0x66, 0x9a, 0xcb, 0x56, 0x93, 0x4e, 0x2a, 0xee, 0x26, 0xf2, + 0x4d, 0xee, 0xa0, 0xcb, 0xe5, 0x58, 0xf3, 0x96, 0x03, 0x50, 0xd1, 0x8f, 0x14, 0xd5, 0xfd, 0x0a, 0x47, 0x98, 0x7b, + 0xeb, 0x36, 0x9f, 0x1c, 0x9a, 0x02, 0x87, 0xc8, 0x93, 0x36, 0x9a, 0x02, 0xba, 0x77, 0xf1, 0xb0, 0xab, 0xdf, 0x96, + 0xee, 0x02, 0x25, 0xda, 0xab, 0xb8, 0xe1, 0xc7, 0x44, 0x9d, 0xce, 0xb4, 0x21, 0xf4, 0xaf, 0x8c, 0xb8, 0xbf, 0x34, + 0xae, 0xe2, 0x4d, 0xef, 0xf2, 0x19, 0x87, 0x3a, 0xbb, 0x21, 0x14, 0x80, 0xab, 0xf6, 0x74, 0xea, 0xc6, 0x90, 0x5e, + 0x29, 0xd1, 0x6d, 0x70, 0xb0, 0x3b, 0x7d, 0xc6, 0x51, 0xf4, 0x63, 0xd4, 0xc8, 0x37, 0x91, 0x78, 0x28, 0x07, 0xf1, + 0xc3, 0x82, 0x2e, 0x23, 0xf1, 0xb0, 0x18, 0xc4, 0x0f, 0x65, 0x5d, 0xef, 0x9f, 0x2b, 0x77, 0xf7, 0x11, 0x79, 0xd6, + 0xbd, 0xbd, 0x54, 0xc2, 0xc6, 0xc0, 0xb3, 0x6b, 0x01, 0xe1, 0x14, 0x3c, 0x91, 0xad, 0xa5, 0x0f, 0x9d, 0xdb, 0x7d, + 0x6c, 0x99, 0x24, 0x08, 0x7a, 0xde, 0x66, 0x93, 0x28, 0x76, 0xb6, 0x79, 0xf4, 0xe1, 0x14, 0x48, 0xe8, 0x76, 0xdb, + 0xac, 0xab, 0x35, 0xa0, 0x98, 0x86, 0x63, 0x7e, 0x58, 0x8c, 0x6e, 0x7c, 0x77, 0xfd, 0xc3, 0x62, 0xb4, 0x24, 0xc3, + 0x89, 0x99, 0xfc, 0xf8, 0x64, 0x3c, 0x8b, 0xa3, 0x49, 0xdd, 0x71, 0x5a, 0x68, 0xfc, 0x53, 0xef, 0x16, 0x8a, 0xc0, + 0xa9, 0x18, 0xc1, 0x91, 0x53, 0xa1, 0x9c, 0x94, 0x1a, 0x18, 0xfe, 0x07, 0xd5, 0x9e, 0x36, 0xed, 0x75, 0x5c, 0x25, + 0xcb, 0x4c, 0x5c, 0xea, 0xf0, 0xe1, 0x3a, 0xba, 0xb8, 0x0d, 0x68, 0xe7, 0x5d, 0xa6, 0x1d, 0xbf, 0x4e, 0x1a, 0xf4, + 0xc4, 0xd5, 0xcc, 0x80, 0x5b, 0xf7, 0x23, 0x34, 0x43, 0x60, 0xb4, 0x3c, 0x7f, 0x87, 0x98, 0xdb, 0xbf, 0x2a, 0x9b, + 0x5f, 0x45, 0xfb, 0x1c, 0x19, 0x29, 0xdb, 0x64, 0xa4, 0x02, 0x23, 0x4c, 0x29, 0x92, 0xb8, 0x0a, 0x21, 0x90, 0xfd, + 0xd7, 0x14, 0xd7, 0x62, 0xe9, 0xbd, 0x06, 0x61, 0x82, 0xed, 0x82, 0xf6, 0xab, 0xdb, 0xbb, 0xad, 0xb4, 0xd8, 0x23, + 0xf5, 0x7d, 0xee, 0x6c, 0x57, 0x34, 0xf9, 0xfb, 0xba, 0x01, 0x6d, 0x00, 0x51, 0xde, 0xd5, 0x47, 0x25, 0x70, 0x32, + 0xe2, 0x86, 0x12, 0xa3, 0x17, 0x74, 0x75, 0x22, 0xf7, 0xec, 0xd4, 0xbc, 0xa9, 0x98, 0xa9, 0xb8, 0xf2, 0xcd, 0x9e, + 0xf9, 0x0f, 0x86, 0x82, 0x4a, 0x30, 0xf0, 0x36, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, 0x18, 0x9d, 0x16, 0x6c, 0x16, 0xd4, + 0x65, 0xdd, 0xb4, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb1, 0x2a, 0xd4, 0x48, 0x78, 0x22, 0x10, 0x30, 0x65, 0x57, 0x3c, + 0x32, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x4a, 0x54, 0xd3, 0x9b, 0xd0, 0x26, 0x13, 0xa7, 0x19, 0x44, + 0x30, 0x23, 0xb6, 0xfb, 0x2d, 0xa0, 0xcd, 0xad, 0x19, 0x6d, 0xeb, 0xda, 0x6a, 0xab, 0x90, 0x4b, 0x8a, 0x94, 0xe5, + 0xbf, 0x53, 0x53, 0x41, 0x49, 0x2d, 0x17, 0xbd, 0x49, 0xd3, 0x45, 0x8f, 0x67, 0x46, 0x12, 0xa8, 0xdc, 0x72, 0xc7, + 0xe8, 0x0f, 0x61, 0x81, 0x47, 0x4c, 0x9c, 0x58, 0x30, 0xb7, 0x3a, 0x61, 0xd9, 0x5c, 0x2c, 0x46, 0x2b, 0x09, 0x61, + 0x83, 0x8f, 0x59, 0x36, 0x2f, 0xf5, 0x43, 0xe8, 0x0b, 0x4b, 0x1f, 0x80, 0x5d, 0x6c, 0xb0, 0x92, 0x65, 0x00, 0xbe, + 0x17, 0x74, 0xbb, 0x92, 0x65, 0x24, 0x55, 0xf7, 0xe3, 0x1a, 0x4b, 0x50, 0x69, 0x85, 0x4a, 0x4b, 0x6a, 0x2c, 0x08, + 0x7c, 0x55, 0x75, 0xf9, 0x90, 0xec, 0x2a, 0x50, 0x4f, 0x1d, 0x35, 0xe0, 0x14, 0xa8, 0x2a, 0xb0, 0x20, 0x09, 0x2a, + 0x43, 0x57, 0x05, 0xa6, 0x15, 0x98, 0x66, 0xaa, 0x70, 0x51, 0x66, 0x87, 0xd2, 0xac, 0x97, 0x7c, 0x16, 0x0f, 0xc2, + 0x64, 0x18, 0x93, 0x87, 0x08, 0xb5, 0x7f, 0x98, 0x47, 0xb1, 0x96, 0x4b, 0x5e, 0x3a, 0xbf, 0xf8, 0x9b, 0x2f, 0xd8, + 0xeb, 0x9e, 0x61, 0xb0, 0x00, 0x67, 0x69, 0x7b, 0x95, 0x89, 0x77, 0xb2, 0x15, 0x1c, 0x07, 0xb3, 0x28, 0x87, 0x55, + 0x4f, 0x8e, 0x68, 0x2e, 0x72, 0xed, 0x5d, 0x84, 0xc8, 0x41, 0x66, 0x8f, 0x01, 0x76, 0x23, 0x7c, 0x1d, 0x5a, 0x9b, + 0x5b, 0x5d, 0x21, 0xfe, 0x46, 0x89, 0xc4, 0x4f, 0x52, 0x7e, 0x5a, 0xaf, 0x54, 0xae, 0xca, 0xe0, 0xb1, 0xea, 0x66, + 0xf0, 0x4c, 0xfb, 0x1e, 0x6b, 0xff, 0xd6, 0x76, 0x73, 0xbc, 0xf7, 0xe0, 0x41, 0xeb, 0x7f, 0xeb, 0x49, 0x08, 0xed, + 0x95, 0x93, 0xd4, 0x1d, 0x35, 0x7a, 0x66, 0xb2, 0x46, 0x54, 0xc2, 0xd4, 0xee, 0x54, 0x8e, 0x81, 0x9a, 0x0e, 0xe0, + 0x5a, 0xa2, 0x26, 0xe8, 0x49, 0xc1, 0xc6, 0x70, 0xc4, 0x59, 0x1c, 0xb4, 0xe3, 0x18, 0xc5, 0xcb, 0xb9, 0x12, 0x2f, + 0xe7, 0x27, 0x8c, 0x03, 0xb4, 0x16, 0x20, 0xd5, 0x6b, 0xd8, 0xcf, 0x5c, 0xc1, 0x02, 0x9b, 0x3b, 0xdf, 0x91, 0x05, + 0x32, 0xc4, 0xc9, 0xe6, 0x38, 0xd9, 0xe3, 0x5a, 0xcf, 0xbd, 0xc0, 0xc7, 0x49, 0xbd, 0xf0, 0xea, 0x2a, 0xdb, 0x75, + 0x2d, 0x59, 0x39, 0x2f, 0x06, 0x13, 0x08, 0xca, 0x52, 0xce, 0x8b, 0xe1, 0x64, 0x41, 0x73, 0xf8, 0xb1, 0x68, 0xa0, + 0x43, 0x2c, 0x07, 0x09, 0x5c, 0x3a, 0x7b, 0x0c, 0x78, 0x43, 0xa9, 0xc5, 0xdd, 0x58, 0x47, 0x8e, 0x75, 0x14, 0x87, + 0x61, 0x0c, 0xb8, 0xb2, 0x4e, 0xe0, 0x7d, 0xf7, 0xf5, 0xb1, 0x09, 0xc8, 0xaa, 0x5d, 0xe1, 0xd5, 0x28, 0x77, 0x5d, + 0x69, 0xf4, 0x25, 0xa5, 0x27, 0xbc, 0xe0, 0xa9, 0x64, 0xb7, 0xeb, 0x19, 0x38, 0x5b, 0xe2, 0x21, 0xf1, 0x8e, 0x11, + 0xbd, 0x98, 0x36, 0x32, 0x73, 0x02, 0x67, 0xb6, 0xbb, 0x6c, 0x63, 0x7e, 0xec, 0x00, 0x07, 0x8b, 0x20, 0x24, 0x6e, + 0x08, 0xc3, 0xc4, 0x4e, 0xca, 0xa1, 0x16, 0xc2, 0x75, 0x2d, 0xbc, 0x8e, 0xd3, 0x32, 0x06, 0x17, 0x69, 0x6d, 0x9b, + 0x78, 0x07, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, 0x0c, 0x40, 0xd3, + 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, 0xfe, 0xbd, 0xe6, + 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, 0x13, 0xb7, 0xdb, + 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, 0x18, 0x30, 0x97, + 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, 0xcc, 0x03, 0x99, + 0x02, 0xe2, 0xf9, 0x87, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd3, 0xf1, 0x8d, 0xe8, 0x6b, 0xfb, 0xe2, 0x92, + 0x57, 0x6f, 0x6f, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, 0x1d, 0x14, 0x59, + 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xad, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, 0x09, 0x53, 0x80, + 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, 0x31, 0x80, 0xc2, + 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa4, 0x3a, 0x03, 0x2d, 0xeb, 0x69, 0x01, 0xa2, + 0x3a, 0x88, 0xb6, 0x0a, 0x51, 0xa1, 0x53, 0x5a, 0x66, 0x34, 0x15, 0x74, 0x2d, 0x68, 0x92, 0xd1, 0x0b, 0xae, 0x44, + 0xc5, 0x2b, 0xc1, 0x14, 0x6d, 0x37, 0x84, 0xfd, 0x1f, 0x0d, 0xba, 0xde, 0x8a, 0xb5, 0x86, 0x76, 0x27, 0xc8, 0x08, + 0xcd, 0x17, 0x3a, 0x08, 0x19, 0x2a, 0x27, 0xa1, 0x6b, 0x95, 0xc6, 0x2b, 0x70, 0xc9, 0x34, 0x1b, 0x2d, 0xe3, 0x32, + 0x0c, 0xec, 0x57, 0x81, 0xc5, 0xe4, 0xc0, 0xa4, 0x0f, 0xeb, 0xf3, 0xa7, 0xf2, 0x6a, 0x25, 0x05, 0x17, 0x95, 0x82, + 0xe8, 0x37, 0xb8, 0xef, 0x26, 0xae, 0x3a, 0x6b, 0xd6, 0x4a, 0xef, 0xfb, 0xd6, 0x67, 0x6d, 0xdc, 0x17, 0x06, 0xc7, + 0x60, 0xef, 0x23, 0x62, 0x20, 0x0d, 0x2a, 0xdd, 0xe2, 0xd0, 0x04, 0xe8, 0xd2, 0x21, 0x85, 0x2c, 0x99, 0xca, 0x54, + 0x09, 0x2a, 0xbe, 0xf1, 0x7b, 0x29, 0xab, 0xd1, 0x5f, 0x6b, 0x5e, 0x6c, 0x3e, 0xf0, 0x9c, 0xe3, 0x18, 0x05, 0x49, + 0x2c, 0xae, 0xe3, 0x32, 0x20, 0xbe, 0xe5, 0x55, 0x70, 0x94, 0x9a, 0xb0, 0x31, 0x7b, 0x55, 0xa3, 0xd6, 0xab, 0x40, + 0x5f, 0x19, 0xe5, 0x1b, 0x83, 0xa1, 0x89, 0xa8, 0x82, 0xbe, 0xd7, 0xea, 0x9e, 0x56, 0x37, 0x2c, 0x20, 0xfe, 0x5c, + 0xe9, 0x85, 0x5a, 0xaf, 0x9b, 0x31, 0x37, 0x4c, 0x84, 0xa0, 0xd1, 0xa3, 0x7a, 0xe1, 0xf0, 0xf3, 0xb7, 0xca, 0x92, + 0x08, 0x5e, 0x6c, 0xd3, 0x75, 0x61, 0x62, 0x69, 0x50, 0x1d, 0x30, 0x37, 0xda, 0xe6, 0xfc, 0x12, 0x44, 0x7f, 0xce, + 0x8a, 0x68, 0x52, 0xd7, 0x54, 0x21, 0x18, 0x46, 0xdb, 0xdb, 0x46, 0x3a, 0xdd, 0x80, 0x97, 0x9b, 0xb1, 0x46, 0xd2, + 0x9e, 0x8e, 0x35, 0x2d, 0x78, 0xb9, 0x92, 0xa2, 0x84, 0xe8, 0xce, 0xbd, 0x31, 0xbd, 0x8a, 0x33, 0x51, 0xc5, 0x99, + 0x38, 0x2d, 0x57, 0x3c, 0xa9, 0xde, 0x43, 0x85, 0xda, 0x18, 0x07, 0x5b, 0xaf, 0x46, 0x5d, 0x85, 0x43, 0x7e, 0x75, + 0xf1, 0xfc, 0x76, 0x15, 0x8b, 0x14, 0x46, 0xbd, 0xbe, 0xeb, 0x45, 0x73, 0x3a, 0x56, 0x71, 0xc1, 0x85, 0x89, 0x5a, + 0x4c, 0x2b, 0x16, 0x70, 0x9d, 0x31, 0xa0, 0x5c, 0xc5, 0xee, 0xcc, 0x54, 0x2c, 0xc3, 0xb8, 0x2c, 0x7f, 0xca, 0x4a, + 0xbc, 0x03, 0x40, 0x6b, 0xe0, 0xb4, 0x98, 0x19, 0x10, 0x90, 0x4d, 0x6e, 0x70, 0x11, 0x58, 0x70, 0xf4, 0x78, 0xbc, + 0xba, 0x0d, 0xa8, 0xf7, 0x46, 0xaa, 0xeb, 0x21, 0x0b, 0xc6, 0xa3, 0x27, 0x81, 0x43, 0x0e, 0xf1, 0x3f, 0x7a, 0x7c, + 0x74, 0xf7, 0x37, 0x93, 0x80, 0xd4, 0x53, 0x50, 0x55, 0x18, 0x85, 0x28, 0x4c, 0xfb, 0xeb, 0xb5, 0xba, 0xe5, 0xbe, + 0x3d, 0x2f, 0x79, 0x71, 0x0d, 0xfb, 0x92, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, 0xab, 0xaa, 0xc8, + 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, 0x58, 0xd4, 0xa4, + 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, 0x4a, 0x8c, 0x35, + 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, 0xb7, 0x53, 0xd5, + 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xe6, 0x60, 0x78, 0x00, 0xc9, + 0x64, 0xfa, 0x79, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, 0x3d, 0x1f, 0xfe, + 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, 0xef, 0x50, 0xad, + 0xef, 0xd3, 0xa2, 0x88, 0x37, 0x35, 0x59, 0xd0, 0x95, 0x70, 0xde, 0x35, 0xd4, 0x23, 0x0b, 0xf4, 0x88, 0x4c, 0x57, + 0x82, 0xc1, 0x37, 0xef, 0xab, 0x30, 0xe0, 0xe5, 0x6a, 0xc8, 0x45, 0x95, 0x55, 0x9b, 0x21, 0xe6, 0x09, 0xf0, 0x53, + 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x99, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, 0xe2, 0x63, 0xaa, + 0xba, 0x31, 0xf9, 0x8e, 0xea, 0xbe, 0x4d, 0xbe, 0x03, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, 0x8c, 0xc6, 0xf4, + 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf3, 0x76, 0xf6, 0xd1, 0x68, 0xf4, 0xa0, + 0xa0, 0xa3, 0xd1, 0xe8, 0x53, 0x56, 0x13, 0x7a, 0x29, 0x3a, 0xde, 0xbf, 0xe7, 0xf4, 0x5c, 0xa6, 0x9b, 0x28, 0x08, + 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0x4f, 0xd3, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, 0x6d, 0x44, 0x48, + 0x26, 0x42, 0xdf, 0xee, 0xf5, 0x6c, 0x34, 0x1a, 0x3d, 0x4d, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x00, 0xcd, 0x29, 0x9c, + 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x35, 0x9c, 0xcd, 0xc7, 0xc3, 0xef, 0x47, 0x8b, 0x87, 0x87, + 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, 0xb1, 0xf5, 0x2d, + 0xfa, 0xe6, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x12, 0x80, 0x17, 0x67, 0x23, + 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, 0xc7, 0xd3, 0xf2, + 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x13, 0x44, 0x25, 0x3b, 0x7a, 0x32, 0x55, 0x70, 0xc7, + 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x7e, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, 0x72, 0x19, 0x83, + 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, 0x4c, 0x1e, 0x96, + 0x54, 0x7e, 0x33, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0xaa, 0x57, 0x6f, 0x53, 0x76, + 0x38, 0xff, 0x3f, 0x25, 0x5d, 0x0c, 0x0e, 0xdd, 0xd0, 0xbc, 0xd3, 0xee, 0xbc, 0x15, 0x32, 0x8e, 0x55, 0xf8, 0x36, + 0x25, 0xd6, 0x18, 0x97, 0xb3, 0x93, 0xad, 0xe9, 0xce, 0xa8, 0x2a, 0xb2, 0xab, 0x90, 0xe8, 0x5e, 0x39, 0x90, 0xd0, + 0x20, 0xca, 0x46, 0xb8, 0x7e, 0xc0, 0x7a, 0xc6, 0xeb, 0xe4, 0x35, 0x2f, 0xaa, 0x2c, 0x51, 0xef, 0xaf, 0x1b, 0xef, + 0xeb, 0xda, 0x04, 0x54, 0x7d, 0x57, 0x30, 0x98, 0xe7, 0xb7, 0x05, 0x80, 0x98, 0x22, 0x0d, 0xf0, 0x09, 0x66, 0x10, + 0xd4, 0xae, 0x99, 0x57, 0x8d, 0xe0, 0x1b, 0xf0, 0xd5, 0xbb, 0x02, 0x30, 0x48, 0x42, 0x90, 0x22, 0x43, 0x68, 0x20, + 0x10, 0x68, 0x18, 0x72, 0x81, 0xc1, 0x4f, 0xbc, 0x38, 0x92, 0xca, 0x29, 0x91, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0a, + 0x40, 0x62, 0x3c, 0x0e, 0xe1, 0x85, 0xfa, 0xe5, 0xde, 0xa8, 0x3d, 0xc2, 0x1e, 0xa4, 0x21, 0x04, 0x1b, 0xc2, 0x87, + 0x00, 0x96, 0x14, 0xa1, 0xef, 0x90, 0xcb, 0x08, 0x83, 0x8b, 0x3c, 0x5b, 0xe9, 0xa4, 0x6a, 0xd4, 0xd1, 0x7c, 0x28, + 0xb5, 0x23, 0x39, 0xa0, 0x5e, 0x7a, 0x8c, 0xe9, 0x85, 0x4a, 0x57, 0x45, 0x39, 0xa3, 0x9c, 0x53, 0x3d, 0x31, 0x2e, + 0x6c, 0x21, 0x87, 0x48, 0x38, 0xef, 0x0a, 0x15, 0x0a, 0x87, 0x2f, 0x00, 0x0c, 0x0c, 0xa4, 0x1d, 0xfb, 0xf1, 0x6e, + 0x54, 0xf6, 0x33, 0xce, 0x0e, 0xff, 0x6b, 0x1e, 0x0f, 0x3f, 0x8f, 0x87, 0xdf, 0x2f, 0x06, 0xe1, 0xd0, 0xfe, 0x24, + 0x0f, 0x1f, 0x1c, 0xd2, 0x17, 0xdc, 0x72, 0x69, 0xb0, 0xf0, 0x1b, 0xc1, 0x7e, 0xd4, 0x4a, 0x08, 0xa2, 0x00, 0x6f, + 0x58, 0x6e, 0x35, 0x4e, 0x00, 0xf0, 0x30, 0xf8, 0xdf, 0x01, 0x1a, 0x4d, 0xb9, 0x8b, 0x17, 0xe8, 0x4b, 0xd4, 0xef, + 0x93, 0x47, 0x0d, 0x83, 0x41, 0x10, 0xd7, 0xa8, 0x98, 0x30, 0x44, 0x97, 0x31, 0x51, 0x30, 0xc8, 0x36, 0xfb, 0x6e, + 0xd7, 0x6b, 0x4b, 0xc2, 0xf0, 0x4b, 0x3f, 0xd3, 0xc4, 0xcc, 0x3b, 0xdc, 0xd8, 0x56, 0x72, 0x15, 0x22, 0x56, 0xa0, + 0xfe, 0x95, 0x33, 0x88, 0xbd, 0x79, 0x9d, 0x81, 0x4f, 0x87, 0xfd, 0x62, 0x3c, 0x03, 0x36, 0x0a, 0xee, 0x7c, 0x05, + 0xbf, 0xc8, 0xc0, 0xcd, 0x5b, 0xc4, 0x28, 0x70, 0xb0, 0x4b, 0xa2, 0xdf, 0xef, 0xe5, 0x59, 0x98, 0x6b, 0xdc, 0xe9, + 0xbc, 0x36, 0x6a, 0x08, 0xd4, 0x91, 0x83, 0xfa, 0x41, 0x0f, 0xc1, 0x50, 0x0d, 0x41, 0xd1, 0xd1, 0x16, 0x57, 0xaf, + 0xad, 0xa7, 0x30, 0xbd, 0x55, 0xf5, 0x15, 0xa3, 0x3f, 0x65, 0x26, 0xb0, 0x90, 0x76, 0xcd, 0xb1, 0xae, 0x39, 0x46, + 0xda, 0xd3, 0xef, 0x8b, 0x06, 0xf9, 0xe9, 0x2c, 0x3c, 0x08, 0x54, 0xa9, 0x72, 0xaf, 0x2c, 0xca, 0x6d, 0x69, 0xde, + 0x18, 0xd6, 0x34, 0xcf, 0x6c, 0x9c, 0x9b, 0x59, 0xaf, 0x17, 0x86, 0xe8, 0xe0, 0x89, 0xa5, 0x62, 0x6d, 0x10, 0xee, + 0xc8, 0x24, 0x8c, 0xae, 0x40, 0x76, 0x19, 0x9e, 0x71, 0x82, 0x7c, 0x2a, 0xb0, 0x0f, 0xaa, 0x5a, 0x2f, 0x27, 0x3c, + 0x36, 0xf2, 0x65, 0x23, 0x68, 0x90, 0x97, 0x14, 0xf5, 0x26, 0x6e, 0xc7, 0x3e, 0x6f, 0x21, 0x57, 0x6e, 0xeb, 0x69, + 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, 0xcc, 0x70, + 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, 0x13, 0xf9, + 0xe6, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, 0xf5, 0xa2, + 0x84, 0x0a, 0xd8, 0x6e, 0x97, 0x82, 0xe0, 0xdf, 0x4f, 0xd9, 0x0c, 0xff, 0x66, 0xfd, 0x7e, 0x2f, 0xc4, 0x5f, 0x1c, + 0x83, 0x19, 0xcd, 0xc5, 0x82, 0x7d, 0x02, 0x19, 0x13, 0x89, 0x30, 0x55, 0x19, 0x03, 0xb2, 0x0a, 0x2c, 0x02, 0xcd, + 0x07, 0x2a, 0x17, 0x66, 0xb2, 0x97, 0x39, 0xd7, 0x90, 0x57, 0xad, 0x71, 0xca, 0x46, 0x59, 0xa2, 0x5c, 0x39, 0xb2, + 0x51, 0x9c, 0x67, 0x71, 0xc9, 0xcb, 0xdd, 0x4e, 0x1f, 0x8e, 0x49, 0xc1, 0x81, 0x5d, 0x57, 0x54, 0xaa, 0x64, 0x1d, + 0xa9, 0x1e, 0x78, 0x69, 0x58, 0xe0, 0x3e, 0xe5, 0xf3, 0xc2, 0xd0, 0x88, 0x03, 0x10, 0x66, 0x30, 0x75, 0x4b, 0xef, + 0x85, 0x05, 0x34, 0xaf, 0x24, 0x64, 0x8b, 0xa9, 0x9e, 0x85, 0x6f, 0xcc, 0xc4, 0xbc, 0x58, 0x40, 0x58, 0x9d, 0x62, + 0xa1, 0x99, 0x4d, 0x9a, 0xb0, 0x18, 0x60, 0xf3, 0x62, 0x32, 0x85, 0xf8, 0xee, 0xaa, 0x9c, 0x78, 0x61, 0xee, 0xdb, + 0x89, 0x43, 0x0e, 0x81, 0x57, 0xb5, 0x41, 0x57, 0xb3, 0x0d, 0x47, 0x1d, 0x29, 0x27, 0x26, 0xbf, 0x9f, 0x2a, 0x08, + 0x71, 0x27, 0x8e, 0x84, 0xcb, 0x9b, 0xed, 0xc2, 0xb3, 0x0e, 0x04, 0x1d, 0x35, 0x38, 0xe5, 0x17, 0x06, 0x47, 0x63, + 0x92, 0x6e, 0xbd, 0x13, 0xa4, 0x08, 0x63, 0xb2, 0x95, 0xec, 0x5c, 0x86, 0x62, 0x1e, 0x2f, 0x40, 0x79, 0x19, 0x2f, + 0xc0, 0xd2, 0xc8, 0x18, 0xa4, 0x82, 0xfc, 0x8e, 0x7b, 0xa1, 0xb0, 0x28, 0xae, 0x10, 0xe9, 0x59, 0xfd, 0x9e, 0x16, + 0xed, 0x50, 0x20, 0x28, 0xee, 0x50, 0xe6, 0xc9, 0x59, 0x8f, 0x05, 0x12, 0x1b, 0x02, 0xc6, 0x57, 0x3a, 0x4d, 0xb5, + 0xd6, 0xbd, 0x31, 0xf3, 0xc0, 0xa7, 0xd9, 0x48, 0xc8, 0xea, 0xec, 0x02, 0x44, 0x4a, 0x3e, 0x3a, 0x3e, 0xf2, 0x8b, + 0xb8, 0xb3, 0xcc, 0x5b, 0xdb, 0xa2, 0x92, 0x9d, 0x6c, 0x01, 0xb4, 0x50, 0x47, 0xcf, 0x52, 0x72, 0x9b, 0x92, 0xd4, + 0x6e, 0x53, 0xc0, 0x4a, 0xf2, 0x17, 0x30, 0x04, 0x5f, 0x3b, 0x10, 0x4e, 0xc7, 0x0a, 0xf1, 0x9a, 0xa6, 0x88, 0x34, + 0x19, 0x96, 0x14, 0xc7, 0xb6, 0x44, 0x14, 0x54, 0x5b, 0x96, 0x1d, 0x0c, 0x13, 0x25, 0xf8, 0x63, 0xea, 0x51, 0xa2, + 0x20, 0xa0, 0x7a, 0xc8, 0x41, 0x82, 0x6d, 0x1b, 0x08, 0x0f, 0xc8, 0x23, 0x7a, 0x63, 0xfd, 0x73, 0xd6, 0x79, 0x76, + 0xa1, 0x79, 0x2e, 0xd7, 0xbb, 0xc2, 0x8c, 0x11, 0x9e, 0x64, 0x26, 0x6c, 0x80, 0x77, 0x9e, 0x19, 0xb5, 0x4d, 0xcf, + 0xc3, 0x6b, 0x7b, 0x8e, 0x11, 0xfa, 0xee, 0x18, 0x74, 0x13, 0xcc, 0xab, 0xc3, 0x66, 0xbd, 0x52, 0x90, 0x1a, 0xa6, + 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0xa0, 0x7c, 0xb7, 0xeb, 0xe9, 0xb9, 0xba, 0x7b, 0xee, 0x76, 0xbb, 0x1e, 0x76, 0xeb, + 0x63, 0xda, 0x6d, 0x15, 0x5f, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, 0x6c, 0x52, 0x3a, 0x9a, 0x69, + 0xeb, 0x83, 0xf0, 0xc0, 0xe9, 0xa6, 0xd1, 0xa4, 0x9f, 0xb3, 0x50, 0xd2, 0x4b, 0xd1, 0xa8, 0xae, 0x76, 0x26, 0xa6, + 0xf7, 0xae, 0xff, 0xfb, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xd9, 0xa0, 0xa2, 0xd1, 0x16, 0x8e, 0x14, 0xa1, + 0x07, 0x24, 0xe1, 0xae, 0x96, 0xb5, 0xb8, 0xcd, 0x0f, 0xd9, 0xfd, 0xf4, 0xe9, 0xa7, 0xd4, 0xf7, 0x42, 0x70, 0xcb, + 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, 0xbd, 0xf2, + 0x03, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0xfd, 0x90, 0xcd, 0xb3, 0xc5, 0x6e, 0x17, 0xe2, 0xdf, 0xae, 0x16, + 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0xff, 0x2c, 0x1a, 0x4e, 0x13, 0xcf, + 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, 0xc0, 0x15, + 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x7b, 0x4b, 0xdb, 0xaa, 0x62, 0xe3, 0x2d, + 0x69, 0x8e, 0xeb, 0xc0, 0xf9, 0x3a, 0xd8, 0x80, 0x77, 0xba, 0xec, 0x6a, 0x81, 0xdc, 0x2f, 0xaf, 0x69, 0x6f, 0x5c, + 0x27, 0x30, 0x6b, 0xdb, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x17, 0x7a, 0x70, 0x95, 0x31, 0xd8, 0xdc, 0x58, 0x69, 0xd8, + 0x7d, 0xe3, 0xf9, 0x52, 0x40, 0x78, 0x3a, 0x9f, 0x1e, 0x7f, 0xc8, 0x3c, 0x7a, 0x0c, 0x44, 0xc7, 0x7c, 0x54, 0xba, + 0x8f, 0xec, 0xee, 0xf5, 0x03, 0x02, 0xce, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x55, 0xbd, 0xf2, 0x0a, 0xcb, + 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0x20, 0x70, 0x77, 0xd7, 0xb9, 0x10, 0xab, 0x0e, 0x2b, 0x73, 0x9a, 0x84, + 0x9d, 0x84, 0x68, 0xde, 0x1a, 0xcc, 0x82, 0xff, 0x1d, 0x0c, 0xca, 0x41, 0x10, 0x05, 0x51, 0x10, 0x90, 0x41, 0x01, + 0xbf, 0x10, 0x77, 0x8d, 0x60, 0xcc, 0x16, 0xe8, 0xf0, 0x5b, 0xce, 0x7c, 0x46, 0xe4, 0x95, 0x1f, 0xd6, 0xd3, 0x1b, + 0x80, 0x73, 0x29, 0x73, 0x1e, 0xa3, 0xcf, 0xc9, 0x5b, 0xce, 0x32, 0x42, 0xdf, 0x7a, 0xa7, 0xf2, 0x3b, 0xde, 0x08, + 0xf6, 0xb7, 0x3f, 0x6c, 0x2f, 0x40, 0x5e, 0xd1, 0x1b, 0xd3, 0xb7, 0x9c, 0x44, 0x59, 0xc3, 0x99, 0x9a, 0x43, 0xcf, + 0x2a, 0xcb, 0x5a, 0x51, 0x43, 0x6e, 0x50, 0xcc, 0x8d, 0x2c, 0x93, 0x93, 0x69, 0xab, 0x39, 0x15, 0xb8, 0xee, 0xec, + 0x7a, 0x01, 0xc9, 0xa1, 0xd0, 0x2c, 0x9d, 0x0d, 0xe7, 0xed, 0x0e, 0xc5, 0xd6, 0x29, 0xe4, 0x35, 0x44, 0x45, 0x83, + 0x74, 0x04, 0xd4, 0xd0, 0x8a, 0xcb, 0x0a, 0x5c, 0x98, 0x4d, 0x7b, 0xb8, 0x69, 0x8f, 0x69, 0xc6, 0x7b, 0x88, 0x99, + 0xc7, 0xb1, 0x65, 0x60, 0x47, 0xe2, 0x90, 0x9e, 0x9c, 0x2f, 0xd0, 0x3e, 0xbd, 0x75, 0xb5, 0x78, 0x84, 0xb5, 0xe7, + 0xad, 0x90, 0x10, 0x20, 0x3e, 0x4d, 0xa5, 0xbb, 0x5d, 0x10, 0xc0, 0x00, 0xf7, 0xfb, 0x3d, 0xe0, 0x5a, 0x0d, 0x3b, + 0x69, 0x6e, 0xcd, 0x96, 0xd8, 0x2b, 0x0a, 0x8f, 0x81, 0x39, 0x35, 0xff, 0x19, 0x04, 0x14, 0xcf, 0xdd, 0x10, 0xec, + 0x4d, 0xd9, 0xc9, 0xb6, 0xe8, 0xf7, 0x9f, 0x15, 0xf8, 0x80, 0x72, 0x61, 0x10, 0x73, 0xeb, 0x38, 0x1e, 0x86, 0x7d, + 0x52, 0x1f, 0xe2, 0x58, 0xe4, 0x59, 0xe8, 0x08, 0x4b, 0x65, 0x08, 0x0b, 0x57, 0x8c, 0x74, 0x10, 0x07, 0x35, 0xe9, + 0x1c, 0xac, 0xca, 0x05, 0x5f, 0xee, 0xf5, 0x3e, 0x03, 0x4c, 0x7a, 0xe6, 0x0d, 0xcb, 0x1b, 0x0f, 0x10, 0xad, 0xd7, + 0xc3, 0x85, 0xe2, 0x91, 0x89, 0x06, 0x1a, 0x27, 0xbe, 0xb4, 0xec, 0xfa, 0x4c, 0xcb, 0x4a, 0x46, 0xa3, 0x51, 0x55, + 0x2b, 0xc9, 0x87, 0xfd, 0xee, 0xcf, 0x16, 0x8a, 0xa7, 0x8c, 0x53, 0x9e, 0x82, 0xe5, 0xbb, 0xa1, 0x74, 0xf3, 0x05, + 0x5d, 0x71, 0x91, 0xaa, 0x9f, 0x1e, 0xfa, 0x66, 0x83, 0xb8, 0x66, 0x4d, 0x1d, 0x8e, 0x1d, 0x7e, 0x08, 0x80, 0x69, + 0x1f, 0x66, 0x2e, 0x5d, 0xc3, 0xf4, 0x82, 0x78, 0x36, 0x2e, 0x78, 0xe8, 0xf2, 0x00, 0xf6, 0xa1, 0x39, 0x24, 0xf1, + 0x53, 0xf8, 0x39, 0x33, 0x69, 0x1d, 0x9f, 0xe1, 0x6c, 0x46, 0xa5, 0xba, 0x11, 0xb4, 0x5f, 0x43, 0x22, 0x31, 0x48, + 0xcf, 0x0d, 0x86, 0xa2, 0x75, 0xb7, 0x81, 0x2b, 0xbf, 0xa5, 0x77, 0x3e, 0x0d, 0x02, 0xac, 0x6f, 0x2c, 0x06, 0x00, + 0x54, 0xf1, 0x07, 0xaa, 0xae, 0xcc, 0x15, 0xc5, 0x34, 0x4c, 0x25, 0xda, 0x3b, 0x8e, 0xeb, 0xa8, 0x71, 0x1d, 0x16, + 0xac, 0xb4, 0xb6, 0xcd, 0xee, 0x2d, 0x2d, 0x6c, 0x09, 0xa8, 0x16, 0xc4, 0x9d, 0x00, 0x3e, 0x34, 0x52, 0x1d, 0x08, + 0xb2, 0xfb, 0xe0, 0x00, 0x80, 0x37, 0x3c, 0x0f, 0x43, 0xf8, 0x03, 0x0b, 0x07, 0x96, 0xa5, 0xea, 0xe7, 0x72, 0x1a, + 0xc3, 0xb9, 0x9b, 0xab, 0x1d, 0x3e, 0x5b, 0x82, 0x62, 0x53, 0xcd, 0xa9, 0xb9, 0x7c, 0xe5, 0x8d, 0xfd, 0x1e, 0x13, + 0xcc, 0x63, 0x66, 0x1b, 0x7e, 0xeb, 0xe9, 0xb6, 0xbe, 0xc1, 0x6e, 0xe0, 0xa4, 0xbd, 0x70, 0xda, 0x8b, 0xed, 0xd2, + 0x40, 0xfe, 0xd5, 0x0d, 0x21, 0xc2, 0x47, 0x4d, 0x2c, 0xb2, 0x86, 0x4c, 0xc7, 0x62, 0x85, 0xa8, 0x36, 0x15, 0x4f, + 0xb5, 0x81, 0x40, 0x39, 0x55, 0x17, 0xa6, 0x56, 0x2a, 0x13, 0x06, 0x71, 0xa7, 0x84, 0x45, 0x95, 0x01, 0x86, 0x41, + 0x85, 0x14, 0xd7, 0xd6, 0xf3, 0x03, 0x2e, 0xdf, 0xcc, 0xb4, 0xd9, 0x7e, 0xfa, 0x22, 0x8f, 0x2f, 0x77, 0xbb, 0xb0, + 0xfb, 0x05, 0x98, 0xa3, 0x96, 0x4a, 0xc3, 0x08, 0x4e, 0x20, 0x4a, 0x72, 0x7d, 0x47, 0xce, 0x89, 0xe3, 0xe4, 0xda, + 0xcd, 0x9b, 0xed, 0xa5, 0x18, 0x81, 0x05, 0x9c, 0xb8, 0x48, 0x07, 0x5a, 0x2a, 0x49, 0xed, 0x29, 0xe0, 0x6d, 0x7a, + 0x47, 0xa9, 0xf0, 0x6a, 0xa1, 0x49, 0x48, 0xe5, 0xee, 0x25, 0x76, 0xd4, 0x80, 0x73, 0x52, 0x77, 0x10, 0x70, 0xda, + 0xd3, 0x8d, 0xb5, 0x8a, 0x64, 0x93, 0xe0, 0xbd, 0xd2, 0x43, 0x97, 0x68, 0xa7, 0x76, 0xb7, 0xad, 0xca, 0x16, 0x0a, + 0xe6, 0x41, 0xce, 0x12, 0x75, 0x3c, 0xa0, 0xd0, 0x45, 0x1d, 0x0d, 0xf9, 0x82, 0x14, 0x7a, 0xe5, 0x68, 0x55, 0xf3, + 0xbe, 0x64, 0xa0, 0x54, 0xab, 0x20, 0xaf, 0x89, 0x75, 0x5f, 0xcb, 0x1a, 0x8b, 0x2b, 0x27, 0xa4, 0xb0, 0x09, 0x5f, + 0x5b, 0x8a, 0x85, 0x59, 0xec, 0x8d, 0xa9, 0x2f, 0x5c, 0x22, 0xb4, 0xdd, 0x6d, 0x88, 0xd1, 0x06, 0xeb, 0x66, 0xb7, + 0xfb, 0x58, 0x84, 0xf3, 0x6c, 0x41, 0xe5, 0x28, 0x4b, 0x11, 0x52, 0xcd, 0x78, 0x2c, 0xdb, 0x2e, 0x98, 0x89, 0xa1, + 0xae, 0x3d, 0x5e, 0x92, 0x29, 0xd6, 0x26, 0xc9, 0x51, 0x7c, 0x2e, 0x0b, 0xb5, 0xd6, 0x08, 0xc1, 0xc3, 0xfd, 0xd7, + 0x14, 0x62, 0xda, 0x99, 0x75, 0xf7, 0x72, 0xef, 0x86, 0xf8, 0x2b, 0x04, 0x56, 0x28, 0xd9, 0xc7, 0x62, 0x74, 0x9e, + 0x41, 0x30, 0x58, 0x90, 0x35, 0x63, 0x94, 0x60, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, 0x4b, 0x14, 0x20, 0xce, + 0xb3, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x67, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x4a, 0xbc, 0xcf, 0xd3, 0x98, 0x1e, + 0xba, 0x35, 0x08, 0xae, 0xab, 0x7b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, 0x6a, 0x4e, 0xad, 0x2b, + 0x71, 0x3f, 0xab, 0xbc, 0xd1, 0x07, 0xf1, 0x95, 0x00, 0x1e, 0xd6, 0xdb, 0xde, 0xe7, 0xc2, 0x63, 0x6d, 0xf0, 0xed, + 0x6e, 0x77, 0x25, 0xe6, 0x41, 0xe0, 0x31, 0x9a, 0xbf, 0x28, 0x89, 0x79, 0x6f, 0x4c, 0x61, 0xc5, 0xfb, 0x2e, 0x7e, + 0xdd, 0xa4, 0xd6, 0x5a, 0xe4, 0xee, 0x71, 0x7d, 0xc0, 0xf3, 0x94, 0x38, 0xda, 0x51, 0x39, 0x95, 0xd6, 0x76, 0x00, + 0xbb, 0x22, 0x30, 0x50, 0xf6, 0x6f, 0x29, 0xdb, 0x82, 0x79, 0x22, 0x58, 0x1f, 0xa1, 0xdf, 0x96, 0xd2, 0x9f, 0x8c, + 0xd1, 0xb8, 0x47, 0xae, 0xab, 0xe8, 0x88, 0xeb, 0x68, 0xf6, 0x3c, 0xfa, 0xdb, 0x93, 0x31, 0x2d, 0x62, 0x91, 0xca, + 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x1d, 0x21, 0x34, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, 0x7f, 0x77, 0x3a, 0x51, + 0xda, 0x9a, 0x7c, 0x8c, 0x56, 0x55, 0xe4, 0xac, 0x0d, 0xed, 0xa6, 0x92, 0x43, 0xf2, 0xb0, 0x04, 0x7c, 0x4b, 0x6c, + 0x96, 0xb2, 0x41, 0x51, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, 0xb5, 0xdd, 0xc8, 0x7c, + 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x1e, 0x94, 0x9c, 0xad, 0xcf, 0xe4, 0x26, 0x40, 0x1c, 0x60, + 0xb8, 0x6e, 0xe7, 0x37, 0x0b, 0x42, 0x6f, 0xd9, 0xad, 0x15, 0xab, 0xde, 0x58, 0xb9, 0x88, 0x49, 0xbb, 0x19, 0x4c, + 0xe0, 0x32, 0xce, 0x0a, 0xfb, 0x42, 0xab, 0x1b, 0x8a, 0x8e, 0xb6, 0x49, 0xfb, 0x79, 0x47, 0xbb, 0xe1, 0x82, 0x6f, + 0xc5, 0x3a, 0xce, 0x2d, 0x6b, 0xaa, 0xd0, 0xb4, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, 0x5d, 0xd2, 0x14, 0x2f, + 0xd0, 0x74, 0x0d, 0x66, 0x3a, 0x17, 0xd0, 0xd7, 0x6e, 0x1f, 0xed, 0x0b, 0xd5, 0x13, 0xe1, 0x2d, 0x51, 0xf0, 0x6d, + 0x49, 0xc1, 0x4b, 0x2d, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0xa7, 0x51, 0x25, 0x7a, 0x27, 0xc5, 0x25, 0x68, 0x33, 0xe1, + 0x08, 0x34, 0x55, 0x23, 0xb6, 0x72, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, 0xdb, 0x15, 0x79, 0xcb, + 0x4e, 0xb6, 0xb7, 0x60, 0x26, 0x5c, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, 0x6c, 0xbb, 0x87, 0x1a, + 0x1b, 0xde, 0xd2, 0x1b, 0xb2, 0xbd, 0xe9, 0xf7, 0x43, 0xe8, 0x0f, 0xa1, 0xba, 0x43, 0xb7, 0x9d, 0x1d, 0xba, 0xf5, + 0xda, 0x79, 0x6e, 0xf5, 0x7c, 0xca, 0x3b, 0xe4, 0x23, 0x9a, 0xac, 0xd1, 0x55, 0xbc, 0x81, 0x4d, 0x1d, 0x55, 0x54, + 0x55, 0x1e, 0x25, 0x14, 0x54, 0xe2, 0x19, 0x2f, 0x3f, 0x70, 0x8c, 0xf5, 0xaa, 0x9f, 0xde, 0x69, 0x5e, 0x6d, 0x6d, + 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x0b, 0x89, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x83, 0xaa, 0xe2, 0xa8, 0x04, + 0x17, 0x71, 0x96, 0x83, 0x1a, 0xf7, 0xa2, 0xd9, 0xff, 0x50, 0xdb, 0x8e, 0x2d, 0x1b, 0x67, 0xee, 0x75, 0x48, 0xb6, + 0xff, 0x63, 0x03, 0xf5, 0x34, 0xc4, 0x08, 0xb1, 0x66, 0x41, 0x3f, 0x60, 0x10, 0x2b, 0x34, 0x28, 0xd7, 0x49, 0xc2, + 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x1d, 0x3b, 0x79, 0xd7, 0x63, 0xec, 0x96, 0xd0, 0x44, + 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x01, 0x0a, 0x59, 0xda, 0xfb, 0xdc, + 0x9c, 0xc8, 0xea, 0x1b, 0x6d, 0x84, 0x12, 0xa9, 0x44, 0x90, 0x8d, 0xdf, 0x20, 0x80, 0x31, 0x34, 0x3b, 0x20, 0xdb, + 0x25, 0x7b, 0x4d, 0xcf, 0xac, 0x49, 0x10, 0xbc, 0x7e, 0xa0, 0x12, 0xcd, 0x28, 0x2b, 0xa2, 0xab, 0x8c, 0x7e, 0x36, + 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, 0x6a, 0x6c, + 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, 0xbc, 0xa5, + 0xe0, 0x2f, 0xf6, 0x8e, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb1, 0x93, 0xed, 0xbb, + 0xf0, 0x75, 0x63, 0xe6, 0x36, 0x21, 0x5e, 0xaa, 0x92, 0x9e, 0x37, 0x4f, 0x66, 0x20, 0x56, 0x56, 0x6b, 0x7e, 0xcb, + 0xac, 0x3e, 0x01, 0x88, 0xd4, 0xad, 0x75, 0xb0, 0xc5, 0x8f, 0x4d, 0x97, 0xc9, 0x36, 0x65, 0x6d, 0x26, 0x4a, 0xa9, + 0x48, 0x9a, 0x8b, 0x00, 0xfa, 0x0d, 0xc3, 0x51, 0x03, 0xdc, 0xb9, 0x1e, 0x7b, 0x33, 0x34, 0xde, 0x98, 0x1a, 0x7a, + 0xb6, 0xd5, 0xcb, 0xdb, 0x51, 0x08, 0x33, 0x16, 0xd1, 0xad, 0x3b, 0x16, 0xc3, 0xd7, 0xf4, 0x01, 0x54, 0xf8, 0x34, + 0xc4, 0xe8, 0xc2, 0xa4, 0xae, 0xa7, 0x6b, 0xb5, 0x95, 0x6e, 0x08, 0xcd, 0x31, 0xaa, 0x91, 0xd7, 0xb6, 0x0d, 0x35, + 0x42, 0x7b, 0x42, 0x79, 0x78, 0x4b, 0x2b, 0x7a, 0x63, 0x59, 0x04, 0x27, 0x3f, 0xf6, 0xf2, 0x13, 0x7a, 0xee, 0x06, + 0xed, 0xa7, 0xa2, 0xad, 0x01, 0xfc, 0x0d, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, 0xe1, 0x4b, 0xb6, 0x20, + 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0xf6, 0x76, 0x87, 0x37, 0x29, 0x65, 0x88, 0xd6, 0x88, 0x0e, + 0xf2, 0xea, 0xdf, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, 0xdf, 0xcf, 0xf1, 0xb9, + 0xf6, 0x2c, 0xd3, 0x94, 0x05, 0x32, 0xa1, 0x4b, 0x57, 0x1a, 0x88, 0xca, 0xb7, 0x8e, 0x55, 0x00, 0x56, 0x24, 0x81, + 0x46, 0x24, 0x60, 0xb9, 0xe4, 0x89, 0xcb, 0xb6, 0x68, 0x50, 0x13, 0x95, 0x14, 0xb2, 0x44, 0x12, 0xf8, 0x61, 0x04, + 0x65, 0x8a, 0x62, 0x10, 0xf7, 0xea, 0xe5, 0x15, 0xd7, 0xd4, 0x80, 0x35, 0x45, 0x30, 0xc1, 0x3a, 0x9d, 0x02, 0xb1, + 0x15, 0xeb, 0x15, 0x78, 0xa2, 0xba, 0x8b, 0x24, 0xb2, 0x04, 0x68, 0xa0, 0xe7, 0x4b, 0xa7, 0xdd, 0xf2, 0xf6, 0x44, + 0x4b, 0x15, 0x9b, 0x7b, 0x2f, 0x16, 0x96, 0x7b, 0xac, 0xfc, 0xed, 0x40, 0x7b, 0x61, 0xb5, 0x27, 0xa2, 0x06, 0xab, + 0xc3, 0xb6, 0x9d, 0x1f, 0x4a, 0x43, 0x75, 0xaf, 0x1c, 0x13, 0x50, 0xd1, 0x55, 0x5c, 0x2d, 0xa3, 0x6c, 0x04, 0x7f, + 0x76, 0xbb, 0xe0, 0x30, 0x00, 0x8b, 0xd0, 0x5f, 0xde, 0xff, 0x14, 0x61, 0xb8, 0xaa, 0x5f, 0xde, 0xff, 0xb4, 0xdb, + 0x3d, 0x19, 0x8f, 0x0d, 0x57, 0xe0, 0xd4, 0x3a, 0xc0, 0x1f, 0x18, 0xb6, 0xc1, 0x2e, 0xd9, 0xdd, 0xee, 0x09, 0x70, + 0x10, 0x8a, 0x6d, 0x30, 0xbb, 0x58, 0x39, 0xb6, 0x29, 0x56, 0x43, 0xef, 0x48, 0xc0, 0xee, 0xdb, 0x63, 0x29, 0xf6, + 0xa9, 0x8f, 0x0a, 0x49, 0xa9, 0x17, 0xfd, 0xf3, 0x4e, 0x81, 0x25, 0x05, 0x53, 0xde, 0x60, 0x59, 0x55, 0xab, 0x32, + 0x3a, 0x3c, 0x8c, 0x57, 0xd9, 0xa8, 0xcc, 0x60, 0x9b, 0x97, 0xd7, 0x97, 0x00, 0x30, 0x11, 0xd0, 0xc6, 0xbb, 0xb5, + 0xc8, 0xcc, 0x8b, 0x05, 0x5d, 0x66, 0xb8, 0x26, 0xc1, 0xec, 0x20, 0xe7, 0x56, 0x37, 0x39, 0x25, 0xf6, 0x01, 0x6c, + 0x30, 0x77, 0xbb, 0x06, 0xbf, 0x70, 0x32, 0x7a, 0x32, 0x5b, 0x66, 0xda, 0xc0, 0x95, 0x9b, 0xfd, 0x4f, 0x22, 0x2f, + 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x3c, 0x03, 0x3e, 0x8f, 0xfd, 0x29, 0x42, 0x9f, 0xe5, 0x6a, 0xb4, 0x06, 0xd8, 0xd8, + 0xec, 0x62, 0x33, 0x4a, 0x39, 0x44, 0xe8, 0x08, 0xac, 0xba, 0x66, 0x99, 0x11, 0xdf, 0xa6, 0xe2, 0xb6, 0xa5, 0x0a, + 0xfb, 0x53, 0x78, 0xce, 0x3b, 0xdc, 0x38, 0x0e, 0xf5, 0x26, 0x51, 0xf8, 0x1c, 0x85, 0xa8, 0x1c, 0x8d, 0x0b, 0x9d, + 0x7c, 0x2d, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x95, 0x3a, 0x73, 0x19, 0x5f, 0xb8, 0xf7, 0xdc, 0x97, 0x99, + 0x5c, 0x4b, 0x00, 0x89, 0x52, 0xb5, 0xff, 0xfe, 0x05, 0xa9, 0xf1, 0xbf, 0x52, 0xad, 0x01, 0xe8, 0xfd, 0x0e, 0x35, + 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0xd1, 0x05, 0xac, 0x64, 0xfe, 0x27, 0xd4, 0xed, 0x08, 0xb6, 0x55, 0xf1, 0x84, + 0xa2, 0x8a, 0x16, 0x3c, 0x5d, 0x8b, 0x34, 0x16, 0xc9, 0x26, 0xe2, 0xf5, 0x14, 0x4b, 0x62, 0x36, 0x62, 0xd8, 0xef, + 0xcd, 0x2e, 0xbc, 0x2f, 0x1a, 0x26, 0xf1, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, 0x8c, 0x4c, 0xb9, 0x42, + 0x30, 0xb7, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3e, 0x7a, 0x4c, 0xe8, 0xb5, 0x9c, 0x96, 0x08, 0xd2, 0x27, 0x52, 0xeb, + 0xba, 0x8a, 0xfd, 0x9a, 0x42, 0x54, 0x0b, 0xc1, 0x20, 0x94, 0xa9, 0x69, 0x9f, 0xe2, 0xfb, 0x6c, 0xd9, 0x7f, 0x9a, + 0xb2, 0x25, 0xd9, 0x0a, 0xe8, 0x98, 0x74, 0xde, 0xaf, 0xde, 0x9e, 0x9d, 0x79, 0xbf, 0x41, 0x13, 0x0e, 0xaa, 0x1b, + 0x68, 0x57, 0x41, 0xa6, 0x31, 0x8a, 0xcd, 0x62, 0xac, 0xdd, 0x9a, 0x88, 0x20, 0x08, 0x77, 0x39, 0x0b, 0xdb, 0xed, + 0x84, 0x78, 0x1b, 0x48, 0xa0, 0xc0, 0xb5, 0x8d, 0x72, 0x12, 0x12, 0x75, 0x21, 0x33, 0xc7, 0x84, 0x64, 0x81, 0x5e, + 0x63, 0x47, 0x01, 0x3d, 0xe5, 0xf6, 0x29, 0xa0, 0x2f, 0x0a, 0x76, 0xca, 0x07, 0xc1, 0x10, 0xe3, 0xcd, 0x06, 0xf4, + 0x93, 0x54, 0x8f, 0xe0, 0x31, 0x0d, 0x2c, 0x17, 0x7d, 0x53, 0x30, 0x84, 0x59, 0xfa, 0x67, 0xca, 0x26, 0xdf, 0xfd, + 0xdd, 0xcd, 0xef, 0x99, 0x16, 0xb3, 0x83, 0x50, 0xdc, 0x5e, 0x4f, 0x80, 0xf8, 0x55, 0xfc, 0x0a, 0xac, 0xcd, 0xb5, + 0xc4, 0xdb, 0x93, 0x3c, 0x08, 0x5f, 0x8e, 0x6e, 0x3f, 0x29, 0xcd, 0x27, 0x10, 0xb4, 0xc7, 0x49, 0xca, 0xdd, 0x77, + 0x1f, 0xa4, 0xab, 0x08, 0x46, 0x0b, 0x10, 0xfc, 0xee, 0xac, 0x64, 0xd3, 0x14, 0xfe, 0x63, 0x9d, 0x2f, 0x30, 0x96, + 0x8a, 0xfc, 0x80, 0xd3, 0xdf, 0x04, 0x07, 0xf7, 0x6f, 0x65, 0xd6, 0x90, 0xe8, 0x4c, 0x7d, 0x04, 0xf4, 0x7f, 0xac, + 0xc7, 0xef, 0x14, 0x25, 0x7d, 0x49, 0x9c, 0x23, 0x7c, 0x13, 0x2f, 0xd1, 0x74, 0xb1, 0x37, 0xae, 0xe9, 0xe7, 0xc2, + 0xbc, 0xd0, 0x0a, 0x0e, 0xfb, 0xd6, 0x28, 0x3c, 0xf0, 0xcc, 0xfb, 0x55, 0x34, 0x04, 0xdd, 0x3f, 0xe2, 0xde, 0xf8, + 0x55, 0xb0, 0x0c, 0x6f, 0xca, 0x59, 0x66, 0xee, 0x70, 0x37, 0x99, 0x48, 0xe5, 0x0d, 0x63, 0xc1, 0x5a, 0x28, 0x73, + 0xde, 0x34, 0x98, 0x6d, 0xeb, 0x48, 0x25, 0xbb, 0xef, 0xff, 0x6c, 0x9c, 0xb0, 0xd9, 0x20, 0xf8, 0x50, 0xc9, 0x22, + 0xbe, 0xe4, 0xc1, 0x54, 0xab, 0x28, 0x32, 0xb0, 0x2b, 0x04, 0xa4, 0x1c, 0xa7, 0xbd, 0x83, 0x27, 0x4b, 0xcd, 0x4c, + 0xc8, 0x6f, 0xab, 0xb3, 0x80, 0xb7, 0x66, 0x34, 0x4f, 0x2b, 0xd8, 0x65, 0xbe, 0x92, 0xe2, 0x87, 0x96, 0x24, 0x1b, + 0xeb, 0x6f, 0xc8, 0xb0, 0xad, 0x7c, 0xe6, 0x0c, 0x30, 0x77, 0x3e, 0x49, 0x15, 0xf4, 0xaf, 0xc7, 0xd8, 0x8d, 0x44, + 0x22, 0x20, 0x9c, 0xc5, 0xc4, 0xad, 0x30, 0xe1, 0x30, 0x5d, 0xa0, 0xa0, 0x18, 0x03, 0x05, 0x7d, 0x90, 0x21, 0xa7, + 0xa7, 0x7c, 0x90, 0x34, 0x66, 0xeb, 0x07, 0x55, 0x22, 0xbd, 0x91, 0x84, 0x6e, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, + 0x82, 0x75, 0xba, 0x9b, 0xd3, 0xe1, 0x9b, 0x82, 0x0c, 0xff, 0x09, 0xde, 0x6e, 0xb1, 0xbd, 0x2c, 0x27, 0xb0, 0xb8, + 0x63, 0xaf, 0x78, 0x9a, 0xab, 0x16, 0x27, 0xc4, 0x23, 0x16, 0xb9, 0x4f, 0x2c, 0x60, 0x44, 0x0d, 0xa3, 0xf1, 0x8f, + 0x0f, 0x6f, 0xdf, 0x68, 0x0c, 0xab, 0xdc, 0xff, 0x00, 0x46, 0x54, 0x4b, 0xdb, 0xed, 0x80, 0x2f, 0x47, 0x68, 0xc0, + 0x9e, 0xba, 0xc1, 0xee, 0xf7, 0x4d, 0xda, 0x49, 0xe9, 0x65, 0x73, 0x62, 0xd0, 0x3d, 0xa5, 0xcd, 0x52, 0x19, 0x18, + 0x77, 0x15, 0x8e, 0xe6, 0xc4, 0x46, 0xac, 0xea, 0x7d, 0x18, 0x2e, 0x69, 0x6c, 0x65, 0xe5, 0x76, 0x37, 0xe1, 0xc8, + 0x26, 0xc0, 0xf5, 0x29, 0x68, 0xaf, 0xe6, 0x1c, 0xb4, 0xa0, 0x44, 0x81, 0x23, 0xda, 0xed, 0x42, 0x88, 0x48, 0x52, + 0x0c, 0x27, 0xb3, 0xb0, 0x18, 0x0e, 0xd5, 0xc0, 0x17, 0x84, 0x44, 0x9f, 0x8b, 0x79, 0xb6, 0x50, 0x08, 0x46, 0xfe, + 0x4e, 0xfa, 0xb5, 0x50, 0x9c, 0x72, 0xef, 0x57, 0x41, 0xb6, 0x3f, 0xa6, 0x18, 0x83, 0xd1, 0x69, 0x36, 0x33, 0x90, + 0xb0, 0x9e, 0x56, 0x44, 0xad, 0x23, 0x3b, 0x1b, 0xa0, 0x8a, 0x45, 0xd3, 0x60, 0x50, 0xb7, 0x78, 0x62, 0x3d, 0xa3, + 0xf7, 0xa0, 0x12, 0x44, 0xb5, 0x60, 0x37, 0x86, 0x6b, 0xed, 0xb3, 0x08, 0x25, 0xe5, 0xa4, 0xc9, 0xcc, 0x58, 0xd1, + 0x60, 0x01, 0x42, 0xd2, 0xb8, 0xac, 0x5e, 0xcb, 0x34, 0xbb, 0xc8, 0x00, 0x41, 0xc2, 0xf9, 0x13, 0xca, 0xc6, 0x9b, + 0xa7, 0x6a, 0x5e, 0xba, 0x12, 0x67, 0x16, 0xf6, 0xa4, 0xeb, 0x2d, 0x2d, 0x48, 0x54, 0x00, 0x8d, 0xf2, 0xb5, 0x3c, + 0x3f, 0xef, 0x59, 0x85, 0xec, 0x7f, 0x38, 0x55, 0xb6, 0x43, 0xfc, 0x84, 0x55, 0xc4, 0x3b, 0xad, 0x2b, 0x25, 0xd2, + 0xe8, 0x68, 0x1b, 0x10, 0xc3, 0x96, 0x7d, 0x8b, 0x1a, 0x3e, 0x08, 0xbb, 0xe8, 0x24, 0x3f, 0xe8, 0x29, 0x1e, 0x5b, + 0x03, 0x49, 0x5f, 0x8b, 0xe0, 0x6b, 0x74, 0xa4, 0x13, 0x65, 0x1a, 0x89, 0x29, 0x24, 0xfa, 0xf5, 0x42, 0x6b, 0x2c, + 0xa3, 0xec, 0x2b, 0xf2, 0x7f, 0xd7, 0xdd, 0xfb, 0x55, 0xec, 0x76, 0x30, 0xc9, 0x9e, 0x07, 0x1a, 0x6c, 0x6a, 0xd4, + 0x0a, 0xe1, 0xec, 0x9c, 0x56, 0xa8, 0x1d, 0xeb, 0x85, 0x25, 0x90, 0x07, 0xb0, 0x15, 0x69, 0x50, 0x06, 0xc9, 0x3e, + 0x17, 0x73, 0xb1, 0x70, 0xa2, 0x1c, 0xa9, 0xf0, 0xcf, 0xe4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x0b, 0x86, 0xfc, 0xea, + 0xe8, 0xa2, 0x90, 0x57, 0x20, 0x29, 0x31, 0x0c, 0x95, 0xe5, 0x75, 0x71, 0xd5, 0x96, 0x84, 0xf6, 0x36, 0x00, 0x4a, + 0x53, 0x80, 0xe0, 0xa5, 0x51, 0x43, 0xcc, 0xb6, 0x6a, 0x77, 0x45, 0x77, 0x92, 0x03, 0xea, 0x74, 0xd7, 0x6e, 0xbd, + 0x29, 0x5b, 0x75, 0x2b, 0x2e, 0xfc, 0x01, 0x4a, 0x3f, 0xe5, 0x83, 0xc2, 0xa7, 0x12, 0xb8, 0xf1, 0xd5, 0x26, 0xcb, + 0x2e, 0x36, 0xb8, 0xf4, 0xab, 0xc6, 0xf8, 0xf5, 0xfb, 0x3d, 0xb5, 0x10, 0x1a, 0xa9, 0xc0, 0x7c, 0xfb, 0xcc, 0x54, + 0x65, 0x34, 0xa5, 0xf6, 0x12, 0x5c, 0x39, 0xfb, 0x11, 0x54, 0xc4, 0x75, 0x45, 0x6a, 0x53, 0x03, 0x74, 0xe0, 0x65, + 0x85, 0x5b, 0x59, 0x80, 0xc7, 0x4e, 0x40, 0x76, 0x3b, 0x1e, 0x06, 0xfa, 0xd0, 0x09, 0xfc, 0x2d, 0xf9, 0x1a, 0x99, + 0x35, 0xfb, 0xf8, 0x0f, 0x2d, 0xf8, 0xc7, 0x16, 0xfc, 0x84, 0xe2, 0x4e, 0x2b, 0xf3, 0x6f, 0xa5, 0x75, 0x8b, 0xfb, + 0xf7, 0x32, 0x4d, 0x28, 0x2a, 0x13, 0x6a, 0xbf, 0xd2, 0x6a, 0x6d, 0xd4, 0x18, 0x98, 0xfd, 0xa3, 0x84, 0x0f, 0x66, + 0x8d, 0x27, 0xd6, 0x78, 0x32, 0x9c, 0x6e, 0xa5, 0x61, 0x19, 0x50, 0xe8, 0xe7, 0x65, 0xae, 0xa8, 0x7e, 0xfe, 0x79, + 0xcd, 0xd7, 0xbc, 0xd9, 0x62, 0x9b, 0x74, 0x4f, 0x83, 0xbd, 0x3c, 0x9a, 0x52, 0x38, 0x89, 0x3a, 0x37, 0x12, 0x75, + 0x51, 0xb3, 0x0c, 0xd5, 0x09, 0x5e, 0xcd, 0x53, 0x3d, 0xec, 0xcd, 0x44, 0xb4, 0x56, 0x52, 0x96, 0x18, 0xb0, 0xd6, + 0x91, 0x87, 0xe4, 0x6e, 0xad, 0xe3, 0x4e, 0x43, 0x5d, 0x9a, 0x42, 0x4d, 0xb0, 0xc2, 0x05, 0x38, 0x82, 0xde, 0x17, + 0x21, 0x87, 0x6b, 0xaa, 0xd2, 0x2f, 0x68, 0x4a, 0x9e, 0x78, 0x8a, 0x5a, 0xad, 0x48, 0xb7, 0x1f, 0xe5, 0xd8, 0x0d, + 0xdf, 0x38, 0x21, 0x27, 0x46, 0xe8, 0xef, 0x8e, 0xa5, 0x9c, 0xa1, 0xc5, 0x83, 0x3a, 0xc1, 0x7a, 0x79, 0x4b, 0x81, + 0x62, 0x8e, 0x2e, 0xab, 0xae, 0x79, 0x85, 0xb6, 0x2f, 0xcb, 0x7e, 0x3f, 0xb7, 0xf5, 0xa4, 0xec, 0x64, 0xbb, 0x34, + 0xfb, 0x10, 0x15, 0x53, 0xb8, 0xeb, 0x13, 0xcd, 0x5f, 0x85, 0xfa, 0xaa, 0x2d, 0x73, 0x3e, 0xe2, 0x88, 0x13, 0x92, + 0x93, 0xfa, 0x1f, 0x6a, 0xea, 0x95, 0xb8, 0x5f, 0x55, 0xf2, 0x52, 0x18, 0x2b, 0x46, 0x4b, 0x0c, 0x51, 0xa4, 0xdd, + 0x1b, 0xd3, 0x57, 0x05, 0xc0, 0x5f, 0x09, 0xf6, 0x67, 0x1a, 0x6a, 0xe5, 0xb7, 0x68, 0x0b, 0xf8, 0xb7, 0x8a, 0x1b, + 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, 0x2a, 0xcc, 0xd0, 0x50, 0x5b, + 0x18, 0x7d, 0x8d, 0x32, 0x6e, 0x95, 0xd9, 0xbb, 0x31, 0x76, 0x5a, 0xe0, 0x35, 0xfc, 0x1b, 0xbd, 0x50, 0xcc, 0x46, + 0x1d, 0xa4, 0x47, 0x27, 0x31, 0xfd, 0x71, 0x0b, 0x27, 0x37, 0x0b, 0x67, 0x59, 0xb3, 0x04, 0xba, 0x03, 0x17, 0xc4, + 0xb8, 0xdf, 0xcf, 0xe1, 0xc8, 0x34, 0x23, 0x5f, 0xb0, 0x9c, 0xc6, 0x6c, 0x49, 0xb5, 0xe7, 0xe1, 0x65, 0x15, 0xe6, + 0x74, 0x69, 0x65, 0xbc, 0x29, 0x03, 0x95, 0xd1, 0x6e, 0x17, 0xc2, 0x9f, 0x6e, 0x6b, 0x97, 0x74, 0xbe, 0x84, 0x0c, + 0xf0, 0x07, 0x24, 0xa2, 0x88, 0x05, 0xfe, 0x1f, 0x35, 0x4e, 0xe9, 0x89, 0xd2, 0x9a, 0x25, 0x10, 0x3c, 0x4e, 0xd5, + 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0x76, 0xbb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, 0x02, + 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0xaf, 0x1f, + 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xac, 0xd6, 0x61, 0x62, 0x8a, 0x44, 0x85, 0xe8, 0xec, 0x25, 0xc8, 0x72, 0x04, 0xe0, + 0x7a, 0xbe, 0x96, 0x35, 0xe5, 0x6b, 0x88, 0x0b, 0x0f, 0x0d, 0x7a, 0x57, 0xc8, 0xab, 0xac, 0xe4, 0x21, 0xde, 0x13, + 0x3c, 0xcd, 0xe8, 0xdd, 0x06, 0x1f, 0xda, 0xda, 0xa3, 0x27, 0xc8, 0xd6, 0x53, 0xee, 0xd7, 0x2f, 0x45, 0x38, 0x87, + 0xe8, 0x9d, 0x0b, 0xaa, 0xd5, 0xd5, 0x0e, 0x90, 0xcb, 0xb3, 0xbd, 0x7a, 0x07, 0xa7, 0x9b, 0xbe, 0xbe, 0x55, 0xa1, + 0x33, 0x07, 0x90, 0xf6, 0x90, 0xac, 0x6b, 0xae, 0x77, 0x80, 0x3b, 0x12, 0xb3, 0x35, 0xd0, 0x58, 0xb7, 0x35, 0x3b, + 0xed, 0x51, 0x3c, 0x26, 0x32, 0x33, 0x16, 0x29, 0xc6, 0xdc, 0xad, 0xd3, 0xa2, 0x68, 0x8b, 0x66, 0x08, 0xfb, 0x77, + 0x1d, 0xb1, 0x6e, 0x45, 0x9c, 0xbf, 0xdb, 0xf6, 0x05, 0x46, 0xc3, 0x98, 0x6b, 0xf7, 0x3c, 0x43, 0x37, 0x6c, 0xb0, + 0x8d, 0x24, 0x88, 0x48, 0x90, 0x99, 0x3a, 0x10, 0x65, 0x6d, 0x0d, 0xd8, 0xde, 0x71, 0xbd, 0x69, 0x81, 0x9f, 0x37, + 0x31, 0x78, 0x7b, 0xd6, 0x38, 0xa5, 0xf5, 0x35, 0xae, 0x39, 0xae, 0x0a, 0x11, 0xb5, 0x45, 0x0a, 0x80, 0x61, 0xe7, + 0x0b, 0xdc, 0x99, 0x15, 0x06, 0x73, 0xc2, 0x52, 0xc9, 0x5e, 0xe5, 0xfa, 0x73, 0xd8, 0xe2, 0x20, 0x95, 0x2f, 0xbd, + 0xfe, 0xfe, 0xc3, 0x17, 0x5f, 0xa0, 0xdb, 0x9e, 0xf3, 0x23, 0x08, 0x32, 0x81, 0x0e, 0x6a, 0x4a, 0xf5, 0xf8, 0xb2, + 0x00, 0x6a, 0x0f, 0xf3, 0xf0, 0xb2, 0x60, 0x22, 0xbe, 0xce, 0x2e, 0xe3, 0x4a, 0x16, 0xa3, 0x6b, 0x2e, 0x52, 0x59, + 0x58, 0xa9, 0x71, 0x70, 0xba, 0x5a, 0xe5, 0x3c, 0x00, 0x53, 0x79, 0xcb, 0x28, 0x3b, 0x21, 0xa3, 0x1e, 0x5c, 0x2d, + 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, 0x5c, 0xc5, 0xe5, 0xa7, 0x20, 0xb2, + 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0xdf, 0x09, 0x64, 0xba, 0x2f, 0x0b, 0xb0, 0xcc, 0xb6, 0x15, 0x1f, 0xc7, + 0x58, 0xeb, 0x70, 0x42, 0x66, 0xaa, 0x44, 0xef, 0x5d, 0xb2, 0x2e, 0xc0, 0xda, 0x4f, 0x61, 0x3b, 0xab, 0x5c, 0x33, + 0xac, 0x4c, 0x55, 0x64, 0x0c, 0xe0, 0xd7, 0xec, 0x30, 0xb4, 0x4e, 0x34, 0x73, 0xf4, 0x16, 0xd0, 0x0f, 0xe4, 0xf0, + 0x92, 0x16, 0x6b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0x38, 0xbc, 0x74, 0x0b, 0xf6, 0xda, 0xde, 0xc9, 0x51, 0x98, + 0x08, 0x9e, 0xc6, 0x66, 0x7c, 0x91, 0x67, 0x05, 0xec, 0xa0, 0xc9, 0x78, 0x4c, 0xbd, 0xa5, 0xd5, 0xba, 0x39, 0x3a, + 0x64, 0xdb, 0xec, 0x61, 0xf5, 0x90, 0x93, 0x43, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, 0xba, + 0x2f, 0xd7, 0x36, 0x42, 0xbc, 0x72, 0x76, 0x74, 0x5e, 0xd2, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xf3, 0x69, + 0x03, 0xfe, 0x82, 0x15, 0xeb, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, 0xe3, + 0xf4, 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x95, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, 0xb1, + 0xee, 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x9b, 0xde, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, 0x20, + 0x20, 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0x62, 0x24, 0x64, 0x60, 0xf8, 0x1a, 0xac, 0x45, 0xc9, 0x8d, 0x15, 0xac, + 0x77, 0xcf, 0xd7, 0x09, 0x42, 0x0a, 0x1e, 0xb8, 0x09, 0xfa, 0xa5, 0x75, 0xf3, 0x76, 0x94, 0x28, 0x83, 0xf8, 0xe4, + 0xda, 0x29, 0x07, 0x09, 0x04, 0xe0, 0xc0, 0xaa, 0x90, 0x24, 0x0a, 0x74, 0x1e, 0x5c, 0xcd, 0x38, 0x82, 0xcd, 0x2b, + 0x67, 0x2e, 0x6e, 0x00, 0xe7, 0x95, 0x3f, 0x97, 0x0d, 0xb6, 0xac, 0x47, 0x54, 0x99, 0x33, 0x4e, 0x31, 0xa8, 0x93, + 0x25, 0xe8, 0x2b, 0x4b, 0x69, 0x2f, 0x41, 0xd3, 0x78, 0xc5, 0x56, 0xca, 0x07, 0x80, 0x9e, 0xb3, 0x95, 0x32, 0xf6, + 0xc7, 0xaf, 0xcf, 0xd8, 0x4a, 0x4b, 0x83, 0xa7, 0x57, 0xb3, 0xf3, 0xd9, 0xd9, 0x80, 0x1d, 0x45, 0xa1, 0x36, 0x60, + 0x08, 0x5c, 0x64, 0x82, 0x60, 0x10, 0x6a, 0xfc, 0x97, 0x81, 0x0a, 0x10, 0x46, 0x3c, 0x1e, 0x1b, 0x71, 0xc4, 0xc2, + 0xf1, 0x10, 0x83, 0x81, 0x35, 0x5f, 0x90, 0x80, 0x50, 0x53, 0x1a, 0xfa, 0x7a, 0x86, 0xc3, 0xc9, 0xc1, 0x04, 0x52, + 0x31, 0x33, 0x53, 0x85, 0xb1, 0x31, 0x89, 0x20, 0xfe, 0x6b, 0x67, 0xbd, 0x50, 0x6e, 0x77, 0x8d, 0x06, 0x82, 0x66, + 0xf0, 0x55, 0x15, 0x4f, 0x0e, 0x86, 0x5d, 0x15, 0xe3, 0x28, 0x5c, 0x1b, 0xe5, 0xdb, 0xd9, 0x31, 0x80, 0xf9, 0x9e, + 0x0d, 0x7d, 0xb9, 0xc4, 0xd9, 0xe1, 0x63, 0xf2, 0xf0, 0x31, 0xa1, 0x67, 0xec, 0xec, 0x9b, 0xc7, 0xf4, 0x4c, 0x91, + 0x93, 0x83, 0x49, 0x74, 0xcd, 0x2c, 0x06, 0xce, 0x91, 0x6a, 0x02, 0xbd, 0x1c, 0xad, 0x85, 0x5a, 0x60, 0xda, 0xa1, + 0x29, 0xfc, 0x7e, 0x7c, 0x10, 0x0c, 0xae, 0xdb, 0x4d, 0xbf, 0x6e, 0xb7, 0xd5, 0xf3, 0xea, 0x3a, 0x38, 0x8a, 0xf6, + 0x8b, 0x99, 0xfc, 0x7d, 0x7c, 0xe0, 0xe6, 0x00, 0xeb, 0xbb, 0x7f, 0x4c, 0x4c, 0x93, 0xf6, 0x46, 0xc5, 0xaf, 0xe9, + 0x11, 0xf6, 0xa1, 0x59, 0x64, 0x47, 0x1f, 0x86, 0xff, 0x51, 0x27, 0xea, 0xb3, 0x6f, 0x8e, 0x80, 0x1c, 0x81, 0x0c, + 0x14, 0x4b, 0x04, 0x33, 0x1c, 0x68, 0x0a, 0x28, 0xc8, 0xf4, 0xb8, 0x53, 0x3d, 0xfc, 0x6a, 0xd4, 0xd4, 0x8c, 0x5c, + 0xc3, 0xd4, 0x60, 0x5b, 0xf0, 0x03, 0xd5, 0x0d, 0xfd, 0x8d, 0x46, 0x7b, 0xd2, 0x4e, 0x66, 0xe6, 0x25, 0xb5, 0x71, + 0xee, 0xae, 0x21, 0xa0, 0xb3, 0x83, 0x5b, 0x94, 0xec, 0xdb, 0xe3, 0xcb, 0x03, 0x5c, 0x45, 0x80, 0x1a, 0xc6, 0x82, + 0x6f, 0x07, 0x97, 0x7a, 0x73, 0x1f, 0x04, 0x64, 0xf0, 0x6d, 0x70, 0xf2, 0xed, 0x40, 0x0e, 0x82, 0xe3, 0xc3, 0xcb, + 0x93, 0xc0, 0x19, 0xf7, 0x43, 0xc8, 0x4b, 0x55, 0x51, 0xcc, 0x84, 0xa9, 0x22, 0xb1, 0xb5, 0xe7, 0xb6, 0x5e, 0x65, + 0x7c, 0x46, 0xd3, 0xa9, 0x45, 0x42, 0x0f, 0x53, 0x16, 0x9b, 0xdf, 0xc1, 0x84, 0x5f, 0x05, 0x91, 0x0b, 0x0a, 0x3b, + 0xcb, 0xa3, 0x98, 0x2e, 0xd9, 0xb5, 0x08, 0x53, 0x9a, 0x1c, 0xe6, 0x84, 0x44, 0xe1, 0x52, 0x81, 0x09, 0xaa, 0xd7, + 0x09, 0xc4, 0xb5, 0x75, 0x9f, 0x5f, 0x8b, 0x70, 0x49, 0xf3, 0xc3, 0x84, 0xb4, 0x8a, 0x70, 0x11, 0x6a, 0xb6, 0x35, + 0xbd, 0x60, 0xe1, 0x8a, 0x5e, 0x02, 0x33, 0x15, 0xaf, 0xc3, 0x4b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, 0x36, + 0xa4, 0x6f, 0x86, 0x2f, 0xbe, 0xb0, 0x3e, 0x79, 0xc0, 0x43, 0x3a, 0x3f, 0xbc, 0x14, 0x6c, 0x00, 0xae, 0x33, 0x7e, + 0xf3, 0x83, 0xbc, 0xd5, 0xf3, 0xd2, 0x9e, 0x62, 0x9c, 0x99, 0x76, 0x62, 0xd2, 0x4e, 0xc8, 0xfd, 0xfb, 0xb6, 0xef, + 0x5e, 0xbc, 0x56, 0x2e, 0xab, 0x96, 0x21, 0x49, 0xd6, 0xca, 0x75, 0x1a, 0x25, 0xa7, 0x56, 0xe0, 0xc9, 0x2e, 0x78, + 0x95, 0x2c, 0xfd, 0x83, 0xca, 0x5a, 0x0d, 0xd8, 0x63, 0xc4, 0xb2, 0x50, 0x38, 0xf6, 0xaf, 0x33, 0x96, 0xac, 0x7d, + 0x81, 0x46, 0x8e, 0xdc, 0xdb, 0xeb, 0x8c, 0x79, 0x31, 0x68, 0x97, 0x6b, 0x2f, 0x74, 0x9f, 0x97, 0x9e, 0xb6, 0x78, + 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0x83, 0xb1, 0x32, 0xa3, 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0x60, + 0xa0, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, 0x7a, 0x40, 0xbb, 0xd4, 0xa8, 0xca, 0xdd, 0x32, 0x93, + 0xac, 0x1a, 0x04, 0xa3, 0x3f, 0x4b, 0x29, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, 0x55, 0x2d, 0xc3, 0x72, + 0xc8, 0x51, 0x8b, 0x67, 0x7c, 0x52, 0xa5, 0xfe, 0xd1, 0x11, 0x34, 0x78, 0xbd, 0x6e, 0x05, 0x0d, 0x7e, 0x3c, 0x7e, + 0xac, 0x07, 0xfa, 0x62, 0xad, 0x1d, 0x0f, 0x7d, 0x7e, 0x1b, 0xf1, 0xc6, 0x75, 0xef, 0xa9, 0xd6, 0x2a, 0x94, 0x81, + 0x16, 0x2b, 0x2a, 0x57, 0x6a, 0x49, 0xef, 0x76, 0x11, 0x00, 0x8b, 0xd8, 0x98, 0x8d, 0xf7, 0x6d, 0xb3, 0x42, 0xd0, + 0xe8, 0xc2, 0x52, 0x1c, 0xb0, 0x44, 0xb7, 0x76, 0x30, 0xa1, 0xf1, 0x09, 0x2b, 0xfb, 0xfd, 0xfc, 0x04, 0xe8, 0xa9, + 0x36, 0x62, 0x2a, 0xe0, 0xc8, 0xff, 0xda, 0x8a, 0x4c, 0x51, 0x60, 0xb3, 0xa6, 0xee, 0xd6, 0x58, 0x46, 0xa2, 0x2f, + 0x53, 0xba, 0x3c, 0xe1, 0x19, 0x30, 0xad, 0xd6, 0x2d, 0xc7, 0x95, 0x7d, 0xc5, 0x91, 0xa7, 0xc2, 0xb2, 0xe2, 0xbc, + 0x0a, 0xc7, 0x5b, 0x8f, 0x6f, 0x70, 0x68, 0xd8, 0xb4, 0x4b, 0x7f, 0x08, 0x61, 0x21, 0xbc, 0xce, 0xe0, 0x36, 0xa2, + 0xed, 0x24, 0x50, 0x79, 0x63, 0xae, 0x13, 0xca, 0xe6, 0x76, 0xb5, 0xf6, 0x0c, 0xd2, 0x89, 0x39, 0x50, 0xaa, 0x11, + 0xb4, 0x46, 0xb3, 0xa0, 0x6a, 0xc4, 0x23, 0x67, 0xfe, 0xe5, 0x0c, 0x62, 0xb5, 0x7c, 0x49, 0x53, 0x29, 0x1a, 0x80, + 0x71, 0x01, 0x5c, 0x9e, 0x7e, 0x79, 0xff, 0xd3, 0x07, 0x1e, 0x17, 0xc9, 0xf2, 0x5d, 0x5c, 0xc4, 0x57, 0x65, 0xb8, + 0x55, 0x63, 0x14, 0xd7, 0x64, 0x2a, 0x06, 0x4c, 0x9a, 0x95, 0xd4, 0xdc, 0x95, 0x9a, 0x10, 0x63, 0x9d, 0xc9, 0xba, + 0xac, 0xe4, 0x55, 0xa3, 0xd2, 0x75, 0x91, 0xe1, 0xc7, 0x2d, 0x9f, 0xd3, 0x43, 0x00, 0x36, 0x35, 0x2e, 0xa4, 0x91, + 0xd4, 0x85, 0x18, 0x73, 0x11, 0xaf, 0xeb, 0xe3, 0x71, 0xa3, 0xeb, 0x25, 0x7b, 0x32, 0x7e, 0x34, 0x7d, 0x9d, 0x85, + 0xd9, 0x40, 0x90, 0x51, 0xb5, 0xe4, 0xa2, 0x65, 0xca, 0xa9, 0x4c, 0x02, 0xd0, 0xc7, 0xb3, 0xc7, 0xd8, 0xd1, 0x78, + 0x4c, 0xb6, 0x6d, 0xf1, 0x00, 0x0f, 0xd7, 0xeb, 0xb0, 0x20, 0x33, 0x5d, 0x47, 0x14, 0x08, 0x7e, 0x5b, 0x05, 0x80, + 0x6c, 0x69, 0xab, 0x32, 0x5c, 0x1a, 0x7b, 0x32, 0x9e, 0x50, 0x89, 0xdd, 0x0e, 0x49, 0xed, 0x55, 0xe8, 0x66, 0x5e, + 0xfa, 0x1e, 0x45, 0xd2, 0xb8, 0x2c, 0xed, 0x55, 0x2a, 0xd5, 0x9e, 0x99, 0xb9, 0xae, 0x41, 0x4c, 0x8a, 0x50, 0xd7, + 0x5d, 0x7a, 0x75, 0xef, 0x37, 0xd7, 0x9a, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xc9, 0x5b, 0xcc, 0x5b, 0x57, 0x44, + 0x4d, 0xaf, 0xd6, 0x60, 0x56, 0x8c, 0xb2, 0xa5, 0xe8, 0x62, 0x4d, 0x41, 0x29, 0x18, 0x5d, 0xae, 0xbd, 0x85, 0xfb, + 0x54, 0x36, 0x2e, 0x2c, 0x99, 0x5e, 0x2d, 0x4a, 0x4a, 0xa8, 0x6e, 0x2a, 0x46, 0x4a, 0x18, 0x29, 0x0d, 0x4f, 0xe5, + 0x7b, 0x81, 0xc7, 0x79, 0x1e, 0x44, 0x2d, 0x2f, 0xb0, 0xd3, 0x8a, 0x9c, 0x82, 0xa3, 0x97, 0xc9, 0x69, 0x28, 0x70, + 0x25, 0x14, 0xa8, 0xeb, 0x50, 0xdd, 0x6f, 0x70, 0xf3, 0xff, 0x56, 0xb0, 0xc0, 0xe3, 0x5b, 0xcf, 0x71, 0x1b, 0xfd, + 0x56, 0xf8, 0xb4, 0xf4, 0x81, 0xf4, 0x5d, 0x5d, 0x3c, 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x91, 0x29, + 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x13, 0xd1, 0xb8, 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0x57, 0x41, 0x20, 0x47, + 0x40, 0xee, 0xe7, 0x2c, 0x95, 0xc9, 0x1a, 0x10, 0x36, 0xb4, 0xfc, 0x44, 0xe3, 0x6d, 0x84, 0xfa, 0xfa, 0x05, 0x6e, + 0x73, 0xa5, 0xef, 0x73, 0x5e, 0x09, 0x5a, 0x09, 0x00, 0x7e, 0x89, 0x57, 0x20, 0xf7, 0x78, 0x0a, 0x75, 0x23, 0x6c, + 0x2f, 0xc7, 0x60, 0x49, 0x88, 0x8e, 0x22, 0x2a, 0x16, 0x28, 0x68, 0x0a, 0x83, 0x28, 0xa2, 0x2e, 0x98, 0xc3, 0xf3, + 0x5c, 0x26, 0x9f, 0xa6, 0xc6, 0x67, 0x7e, 0x18, 0x63, 0x0c, 0xe9, 0x60, 0x10, 0x56, 0xb3, 0x60, 0x38, 0x1e, 0x4d, + 0x8e, 0x9e, 0xc0, 0xb9, 0x1d, 0x8c, 0x03, 0x32, 0x08, 0xea, 0x72, 0x15, 0x0b, 0x5a, 0x5e, 0x5f, 0xda, 0x32, 0xf0, + 0xe3, 0x3a, 0x18, 0xfc, 0x56, 0xb8, 0x51, 0xf9, 0x37, 0x68, 0x4e, 0x36, 0x32, 0x0c, 0x02, 0x7a, 0xb5, 0x26, 0x20, + 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, + 0xd3, 0x6c, 0xf4, 0x4a, 0x29, 0x72, 0xdf, 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, + 0xe0, 0x46, 0xfe, 0x4a, 0x5c, 0xc7, 0x79, 0x96, 0x1e, 0x34, 0xdf, 0x1c, 0x94, 0x1b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, + 0x58, 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xcf, 0xcc, 0x64, 0xc6, 0x23, 0xf0, + 0x08, 0x6c, 0xfa, 0x40, 0x16, 0x1b, 0xe7, 0x92, 0xe4, 0x6f, 0xa6, 0xd2, 0x5e, 0xf5, 0xca, 0xbd, 0x82, 0xac, 0x57, + 0x5b, 0xb9, 0xef, 0xd6, 0x67, 0xdf, 0x74, 0x78, 0x05, 0x9e, 0x49, 0x70, 0x8b, 0xec, 0xf7, 0x9b, 0x82, 0x4a, 0x61, + 0x54, 0xc4, 0x7b, 0xc9, 0x35, 0xfa, 0xb7, 0x7b, 0x63, 0xa3, 0x48, 0x6e, 0x79, 0xff, 0x00, 0xea, 0x4c, 0xde, 0x15, + 0xb7, 0x73, 0x88, 0xda, 0xba, 0x1b, 0x0f, 0xbc, 0x37, 0x68, 0x97, 0x35, 0x47, 0xb0, 0xe5, 0xc5, 0x41, 0x06, 0x63, + 0x81, 0xb3, 0x32, 0x52, 0x6a, 0x5c, 0x43, 0x6a, 0xc1, 0x27, 0x79, 0x7a, 0x07, 0x59, 0xea, 0x49, 0x50, 0xe4, 0x78, + 0x16, 0x43, 0xa6, 0xf1, 0x36, 0x10, 0xfb, 0xad, 0x0c, 0x41, 0x9a, 0xb6, 0xdb, 0x35, 0x47, 0xa0, 0xec, 0x1e, 0x98, + 0x92, 0xd4, 0xb5, 0x31, 0x35, 0xd0, 0xd0, 0x83, 0xa8, 0x91, 0x8a, 0x38, 0x3b, 0x79, 0x0a, 0x3a, 0x44, 0xf0, 0xfd, + 0x4e, 0xb3, 0xb2, 0xe3, 0xc5, 0x84, 0xe0, 0xc9, 0xfb, 0xfc, 0x36, 0x2b, 0xab, 0x32, 0x7a, 0x93, 0xa2, 0x21, 0x54, + 0x22, 0x45, 0xf4, 0x19, 0xe2, 0x0b, 0x96, 0xf8, 0xbb, 0x8c, 0x5e, 0xa4, 0x34, 0x4e, 0x53, 0x4c, 0x7f, 0x56, 0xc0, + 0xcf, 0xa7, 0x80, 0x72, 0x89, 0x3b, 0x21, 0x3a, 0x93, 0x60, 0xaf, 0x06, 0xd1, 0xbd, 0x2a, 0x0e, 0x98, 0xa2, 0xd1, + 0xb5, 0xa0, 0x88, 0x59, 0x87, 0xd9, 0x7f, 0x29, 0x50, 0x28, 0xa4, 0x8a, 0x79, 0x29, 0xec, 0x43, 0xc4, 0xd7, 0x50, + 0xce, 0xe9, 0xbb, 0x57, 0x66, 0x48, 0xa3, 0x5b, 0x49, 0xf5, 0xd6, 0xc6, 0x63, 0x0b, 0x51, 0x7a, 0xa2, 0xf3, 0x35, + 0x3d, 0x8b, 0x57, 0x59, 0xb4, 0x05, 0xfc, 0x89, 0x77, 0xaf, 0x9e, 0x2a, 0x0b, 0x93, 0x57, 0x19, 0x28, 0x0e, 0x4e, + 0xdf, 0xbd, 0x7a, 0x2d, 0xd3, 0x75, 0xce, 0xa3, 0x8d, 0x44, 0xd2, 0x7a, 0xfa, 0xee, 0xd5, 0xcf, 0x68, 0xee, 0xf5, + 0xbe, 0x80, 0xf7, 0x2f, 0x80, 0xb7, 0x8c, 0xf2, 0x35, 0xf4, 0x49, 0xfd, 0x5e, 0xae, 0xb1, 0x53, 0x5e, 0xad, 0x65, + 0xf4, 0x57, 0x5a, 0x7b, 0xd2, 0xaa, 0xbf, 0x0a, 0x9f, 0xda, 0x79, 0x02, 0x9e, 0xdb, 0x3c, 0x13, 0x9f, 0x22, 0x2b, + 0xda, 0x09, 0xa2, 0x6f, 0x0f, 0x6e, 0xaf, 0x72, 0x51, 0x46, 0xf8, 0x82, 0xa1, 0x5d, 0x50, 0x74, 0x78, 0x78, 0x73, + 0x73, 0x33, 0xba, 0x79, 0x34, 0x92, 0xc5, 0xe5, 0xe1, 0xe4, 0xfb, 0xef, 0xbf, 0x3f, 0xc4, 0xb7, 0xc1, 0xb7, 0x6d, + 0xb7, 0xf7, 0x8a, 0xf0, 0x01, 0x0b, 0x10, 0xb1, 0xfb, 0x5b, 0xb8, 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x6d, 0xf0, 0xad, + 0x3e, 0x74, 0xbe, 0x3d, 0x2e, 0xaf, 0x2f, 0x55, 0xf9, 0x5d, 0x25, 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, + 0x3b, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0x29, 0xaf, 0x2f, 0x4f, 0x02, 0xcf, 0xe4, 0xb5, 0xc1, 0x22, + 0x3a, 0x10, 0x97, 0xe0, 0xf0, 0x92, 0x06, 0xdf, 0x06, 0xc4, 0xa5, 0x7c, 0x03, 0x29, 0xdf, 0x1c, 0x3d, 0xf1, 0xd3, + 0xfe, 0x97, 0x4a, 0x7b, 0xe4, 0xa7, 0x1d, 0x63, 0xda, 0xa3, 0xa7, 0x7e, 0xda, 0x89, 0x4a, 0x7b, 0xee, 0xa7, 0xfd, + 0x9f, 0x72, 0x00, 0xa9, 0x07, 0xbe, 0xf5, 0xdf, 0xc6, 0x6b, 0x0d, 0x9e, 0x42, 0x51, 0x76, 0x15, 0x5f, 0x72, 0x68, + 0xf4, 0xe0, 0xf6, 0x2a, 0xa7, 0xc1, 0x00, 0xdb, 0xeb, 0x19, 0x79, 0x78, 0x1f, 0x7c, 0xbb, 0x2e, 0xf2, 0x30, 0xf8, + 0x76, 0x80, 0x85, 0x0c, 0xbe, 0x0d, 0xc8, 0xb7, 0xc6, 0x40, 0x46, 0xb0, 0x6d, 0xe0, 0x42, 0xb3, 0x0e, 0x6d, 0xc0, + 0x34, 0x5f, 0x1a, 0x57, 0xd3, 0x7f, 0x15, 0xdd, 0xd9, 0xf0, 0x96, 0xa8, 0xdc, 0x74, 0x83, 0x9a, 0xbe, 0x05, 0xef, + 0x04, 0x68, 0x54, 0x14, 0x5c, 0xc7, 0x45, 0x38, 0x1c, 0x96, 0xd7, 0x97, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa2, + 0x40, 0xc8, 0xa1, 0xfa, 0x19, 0xa8, 0x48, 0x60, 0x01, 0x42, 0x19, 0xc1, 0x7f, 0x41, 0x4d, 0xdf, 0x49, 0xb6, 0x0d, + 0x86, 0x37, 0xfc, 0xfc, 0x53, 0x56, 0x0d, 0x95, 0x68, 0xf1, 0x46, 0x50, 0xf8, 0x01, 0x7f, 0x5d, 0xd5, 0xd1, 0xbf, + 0xc0, 0x8d, 0xbb, 0xa9, 0x61, 0x7f, 0x27, 0x3d, 0x87, 0x36, 0x39, 0xcf, 0x16, 0xd3, 0xd6, 0x81, 0xfe, 0x56, 0x92, + 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, 0xe0, 0x0b, 0xf6, 0x56, 0xce, 0xb9, 0x67, 0x3e, 0x75, 0x2a, 0xfd, 0x69, 0x9e, + 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, 0xe4, 0xf0, 0xbf, 0xe6, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0x1c, 0x92, 0x59, 0xb0, + 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xeb, 0x75, 0xdb, 0xcb, 0xe3, 0xce, + 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, + 0x1c, 0xb0, 0xe0, 0xb8, 0x37, 0x1c, 0x1e, 0x04, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x07, 0xc3, 0xe1, 0x49, 0xe0, 0xee, + 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, 0xc1, 0xfe, 0x2a, 0xc2, 0x92, 0x82, 0x78, 0x4c, 0x6a, 0xf1, 0x97, 0x06, 0x97, + 0x19, 0x00, 0xf4, 0x91, 0x92, 0x80, 0x19, 0x58, 0x99, 0x01, 0x84, 0x2a, 0xa7, 0x31, 0xbb, 0x05, 0xe6, 0x11, 0x38, + 0x66, 0x05, 0x93, 0x05, 0x88, 0x25, 0x01, 0xce, 0x5d, 0x10, 0xc5, 0xba, 0x90, 0x53, 0x08, 0x02, 0x80, 0x3f, 0x89, + 0x29, 0x05, 0x93, 0x74, 0xec, 0x46, 0x10, 0xc4, 0xf1, 0xd9, 0x8d, 0x68, 0x4d, 0xce, 0x12, 0x1d, 0xcc, 0x48, 0x02, + 0x6c, 0x88, 0x81, 0xe1, 0x83, 0xfb, 0x39, 0x28, 0x3d, 0xac, 0xde, 0x09, 0xb9, 0xe0, 0x0d, 0x77, 0x2c, 0xd4, 0x0d, + 0x5c, 0x3d, 0xe1, 0x20, 0xd8, 0x70, 0xcd, 0x02, 0x8c, 0xaa, 0x62, 0x5d, 0x56, 0x3c, 0xfd, 0xb8, 0x59, 0x41, 0x2c, + 0x40, 0x1c, 0xd0, 0x77, 0x32, 0xcf, 0x92, 0x4d, 0xe8, 0xec, 0xb9, 0xb6, 0x2a, 0xfd, 0xe5, 0xc7, 0xd7, 0x3f, 0x45, + 0x20, 0x72, 0xac, 0x0d, 0xa5, 0xdf, 0x70, 0x3c, 0x9b, 0xfc, 0x88, 0x57, 0xfe, 0xc6, 0xde, 0x70, 0x7b, 0x7a, 0xf4, + 0xfb, 0x50, 0x37, 0xdd, 0xf0, 0xd9, 0x86, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0xf0, 0xec, 0xb2, 0xd6, 0xbe, 0x11, 0xd2, + 0xfd, 0xf3, 0x4c, 0x79, 0x63, 0x7e, 0xb4, 0x83, 0x61, 0x10, 0x4c, 0xb5, 0x50, 0x12, 0xa2, 0x90, 0x30, 0x25, 0x60, + 0x88, 0x0e, 0xf4, 0xb2, 0x9a, 0x22, 0xe7, 0xa6, 0x46, 0x16, 0xde, 0x0f, 0x98, 0x16, 0x3a, 0x34, 0x72, 0x28, 0x3f, + 0x38, 0x9c, 0x30, 0x66, 0xe1, 0xb7, 0x4a, 0x98, 0x7e, 0xb5, 0xa8, 0x9c, 0x83, 0xe8, 0x01, 0x18, 0xe3, 0x0a, 0x5e, + 0x40, 0x57, 0xd8, 0xa7, 0xb5, 0x8a, 0x12, 0x82, 0x60, 0x7a, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, + 0xab, 0x72, 0x96, 0x2a, 0xea, 0x32, 0x94, 0x95, 0xb1, 0xc2, 0xc0, 0x2f, 0xd9, 0x2f, 0x05, 0x7a, 0x96, 0x4f, 0x45, + 0x17, 0xbc, 0x10, 0x4a, 0xb0, 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xd7, 0x8f, 0xa7, + 0xaf, 0x65, 0xca, 0xb5, 0x09, 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x07, 0xe8, 0x57, 0xdb, 0x46, 0x9f, + 0x5d, 0xaf, 0xf5, 0x66, 0x50, 0xa2, 0x63, 0x5e, 0xa3, 0xe0, 0x5a, 0x29, 0x14, 0x8c, 0xf6, 0x36, 0xfe, 0x02, 0x47, + 0x6e, 0x75, 0x7b, 0xe8, 0xfd, 0x56, 0xc5, 0x97, 0x6f, 0xd0, 0xb7, 0xd3, 0xfe, 0x1c, 0x55, 0xf2, 0x97, 0xd5, 0x0a, + 0x7c, 0xa8, 0x20, 0xd2, 0x8a, 0xc5, 0xe9, 0x85, 0x7a, 0x3e, 0xbc, 0x3b, 0x7d, 0x03, 0x7e, 0x94, 0xf8, 0xfb, 0xd7, + 0x1f, 0x83, 0x9a, 0x4c, 0xe3, 0x59, 0x61, 0x3e, 0xb4, 0x39, 0x20, 0x54, 0x8b, 0x4b, 0xb3, 0xef, 0x67, 0x71, 0x93, + 0x7d, 0xd7, 0x6c, 0x3d, 0x2d, 0x9a, 0x48, 0x52, 0x86, 0xdb, 0x07, 0x03, 0x02, 0x7d, 0x80, 0x28, 0xce, 0xbe, 0xa0, + 0x31, 0xa4, 0xf9, 0xcc, 0xbe, 0x1f, 0x21, 0xf0, 0xd5, 0x5e, 0x48, 0x35, 0xae, 0xb0, 0x68, 0xf4, 0x90, 0xcf, 0x78, + 0xa4, 0x0c, 0x8b, 0xde, 0x63, 0x02, 0x71, 0x86, 0xd3, 0xea, 0x3d, 0x62, 0x40, 0xe3, 0xdd, 0x40, 0xcb, 0x1e, 0xa2, + 0x8c, 0xba, 0xec, 0x0d, 0x8b, 0xef, 0xd7, 0xeb, 0x30, 0xb3, 0x96, 0x97, 0x43, 0xf8, 0x1b, 0x68, 0x03, 0x70, 0xca, + 0x91, 0xe5, 0xab, 0xcc, 0x46, 0x57, 0x4b, 0x4c, 0x6f, 0x22, 0x88, 0x4d, 0xa4, 0xd3, 0x61, 0xed, 0xea, 0x54, 0xbd, + 0xab, 0x9d, 0xcf, 0x44, 0xaf, 0x02, 0xad, 0x5c, 0xdb, 0x1e, 0x0f, 0xe1, 0x3f, 0xb5, 0xb4, 0xc2, 0x46, 0xd8, 0x73, + 0xf1, 0x85, 0xe7, 0xd8, 0x9c, 0x80, 0x06, 0x57, 0x32, 0x05, 0xe0, 0x2c, 0xad, 0x46, 0xa3, 0x46, 0xd8, 0x67, 0xe5, + 0x7c, 0x0e, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x1c, 0xb8, 0x89, 0xc9, 0xc9, 0xbb, 0x31, 0x39, 0xa7, 0x9f, 0x14, 0xdc, + 0x77, 0x70, 0x56, 0x2e, 0xe3, 0x54, 0xde, 0x00, 0x36, 0x65, 0xe0, 0xa7, 0x62, 0xa9, 0x5e, 0x42, 0xb2, 0xe4, 0xc9, + 0x27, 0xb4, 0xda, 0x48, 0x03, 0xe0, 0x2a, 0xa7, 0xc6, 0x72, 0x4f, 0x81, 0xa6, 0xba, 0x52, 0x54, 0x42, 0x5c, 0x55, + 0x71, 0xb2, 0xfc, 0x80, 0xa9, 0xe1, 0x16, 0x7a, 0x11, 0x05, 0x72, 0xc5, 0x05, 0x90, 0xf4, 0x9c, 0xfd, 0x23, 0xd3, + 0xd8, 0xeb, 0x0f, 0x24, 0x0a, 0x98, 0x34, 0x8a, 0x32, 0x56, 0xca, 0x5e, 0x49, 0x13, 0xfd, 0x2e, 0x08, 0x6a, 0xf7, + 0xf2, 0x2f, 0xa8, 0xfb, 0x29, 0xb4, 0x22, 0x6c, 0x80, 0x17, 0x6a, 0xf0, 0xc3, 0xd4, 0x2e, 0x39, 0x0f, 0xc8, 0xd0, + 0x79, 0x9f, 0xd5, 0x76, 0xab, 0x3f, 0x5d, 0x02, 0xd6, 0x6b, 0x6a, 0x7c, 0x0a, 0xc3, 0x84, 0x98, 0x58, 0xc9, 0x56, + 0x59, 0x69, 0x37, 0x94, 0x69, 0x27, 0x5d, 0x32, 0xaf, 0x85, 0xd3, 0xbc, 0xc7, 0xd8, 0x72, 0xa4, 0x72, 0xf7, 0xfb, + 0xa1, 0xf9, 0xc9, 0x72, 0xfa, 0x40, 0x87, 0xb0, 0xf6, 0xc6, 0x83, 0xe6, 0x44, 0xab, 0xab, 0x3a, 0xfa, 0x01, 0x1d, + 0x80, 0x99, 0xb6, 0x08, 0x95, 0x2e, 0xf8, 0xb6, 0xaf, 0x44, 0xc5, 0x25, 0x09, 0x4b, 0x25, 0x81, 0x9d, 0xdd, 0x94, + 0xec, 0x6c, 0x03, 0xe2, 0x19, 0xee, 0x7a, 0x5a, 0xec, 0x84, 0x34, 0xe1, 0x2d, 0x0e, 0x12, 0x10, 0x75, 0xa8, 0xea, + 0x12, 0xb2, 0x35, 0x86, 0x2e, 0xfe, 0x45, 0x29, 0x4c, 0x58, 0xcb, 0xa4, 0x2a, 0x31, 0x41, 0xa1, 0xca, 0xfd, 0x16, + 0x81, 0x25, 0x0a, 0x76, 0x00, 0x7b, 0xef, 0x46, 0xdd, 0x8c, 0x9a, 0xaa, 0x4e, 0xbd, 0x04, 0x1f, 0xa7, 0x59, 0x57, + 0x41, 0x66, 0x61, 0x57, 0xc5, 0x9a, 0x07, 0x3a, 0x56, 0x97, 0x32, 0x26, 0xee, 0xd2, 0x22, 0x43, 0x7c, 0x64, 0x8c, + 0x2d, 0xac, 0xe1, 0x48, 0xdb, 0xe3, 0xa6, 0x27, 0x08, 0xfd, 0x84, 0x0d, 0x25, 0x70, 0xd3, 0xd9, 0x9e, 0x9a, 0x66, + 0x3e, 0x20, 0xe2, 0x30, 0xa0, 0x40, 0xb2, 0x71, 0x48, 0x73, 0xa4, 0x2f, 0x48, 0x9a, 0x30, 0x50, 0xb6, 0xe2, 0x39, + 0x41, 0x56, 0x14, 0x7a, 0xb6, 0xae, 0x6a, 0x88, 0x9f, 0xcb, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xa7, 0x09, 0x32, 0xb1, + 0x3b, 0xda, 0x66, 0x26, 0xc3, 0x51, 0xb2, 0xc0, 0xfc, 0x0a, 0xa2, 0xc4, 0x9d, 0x69, 0x56, 0xe5, 0x60, 0x5c, 0xc0, + 0x02, 0xad, 0x7c, 0x0f, 0xea, 0xc6, 0x1a, 0xda, 0x6a, 0x58, 0x66, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, + 0x8a, 0xe5, 0x65, 0x0a, 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x5e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, + 0x53, 0x03, 0xe8, 0xa9, 0x17, 0x00, 0xbe, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xb8, 0x74, 0x83, 0x20, + 0x45, 0x6f, 0x52, 0x30, 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, + 0xe4, 0x95, 0xd4, 0xc4, 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdb, 0x9d, 0xa6, 0x61, 0xd2, 0x66, + 0x1b, 0x52, 0x90, 0x56, 0x98, 0x38, 0x21, 0x50, 0xd9, 0x2b, 0xdc, 0x2f, 0xd8, 0x4e, 0x9a, 0x82, 0x07, 0x61, 0xa3, + 0x81, 0x89, 0x5b, 0x5d, 0x02, 0x8c, 0x66, 0xc2, 0x25, 0xd5, 0xce, 0x4e, 0x5a, 0x58, 0xdf, 0x5e, 0x97, 0x17, 0xb6, + 0x0f, 0x3a, 0x96, 0x5a, 0xd7, 0xf0, 0x40, 0xf3, 0x9a, 0x5d, 0x5c, 0x31, 0x4d, 0x13, 0x8d, 0xf5, 0x90, 0xb2, 0xe4, + 0x58, 0xd7, 0xd3, 0x15, 0xae, 0x96, 0x99, 0x06, 0xba, 0x97, 0x78, 0xa1, 0x07, 0x7c, 0xf0, 0x70, 0x45, 0xa2, 0x0b, + 0x6c, 0x36, 0x5b, 0xd5, 0x64, 0x9a, 0xdf, 0x95, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, 0x69, + 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, 0xe8, + 0x9d, 0xf3, 0x45, 0xea, 0xe6, 0x17, 0x60, 0x1b, 0xb5, 0xb5, 0xa6, 0x59, 0xeb, 0x30, 0x51, 0x16, 0xd6, 0xc8, 0x42, + 0x2e, 0xc1, 0x07, 0x73, 0xbf, 0xa9, 0xd3, 0xe7, 0x1d, 0x44, 0xd8, 0xef, 0xa2, 0xc7, 0x23, 0x8c, 0x15, 0x6b, 0x90, + 0x18, 0x56, 0x61, 0x4d, 0x9b, 0xcb, 0x21, 0xca, 0xa9, 0x59, 0x32, 0xd1, 0x92, 0xfa, 0x94, 0x22, 0x4a, 0xc1, 0xdc, + 0x78, 0x5a, 0x36, 0x4c, 0x09, 0x11, 0xb2, 0x42, 0x3a, 0xa0, 0x5a, 0x0b, 0x2d, 0xd5, 0x04, 0x01, 0x0f, 0xbd, 0x2c, + 0x34, 0xa6, 0x20, 0xfa, 0x88, 0x0c, 0x37, 0xe2, 0xc8, 0xe8, 0xfe, 0x18, 0xc5, 0x04, 0x42, 0x77, 0x7b, 0x79, 0x61, + 0xf5, 0x69, 0xd9, 0x56, 0x07, 0x71, 0x8d, 0x69, 0x72, 0x07, 0x41, 0x8d, 0x51, 0xd0, 0xe6, 0x74, 0xa3, 0xff, 0x2e, + 0x42, 0xdf, 0x2e, 0x1c, 0xbb, 0x51, 0x10, 0x09, 0x11, 0x69, 0xbd, 0xa6, 0x62, 0x80, 0xda, 0x79, 0xec, 0x22, 0x56, + 0xe9, 0x6e, 0x21, 0xca, 0x1b, 0x95, 0xf5, 0xeb, 0x75, 0x48, 0x76, 0x3b, 0x2c, 0x0b, 0x7c, 0xd9, 0x9f, 0xae, 0xef, + 0x80, 0x40, 0x7f, 0xb0, 0xfe, 0x22, 0x04, 0xfa, 0xb3, 0xec, 0x6b, 0x20, 0xd0, 0x1f, 0xac, 0xff, 0xa7, 0x21, 0xd0, + 0x9f, 0xae, 0x3d, 0x08, 0x74, 0x35, 0x18, 0xff, 0x2c, 0x58, 0xf0, 0xf6, 0x4d, 0x40, 0x9f, 0x49, 0x16, 0xbc, 0x7d, + 0xf1, 0xc2, 0x13, 0xa6, 0x7f, 0xcc, 0x34, 0x92, 0xbf, 0x91, 0x05, 0x23, 0x6e, 0x0b, 0xbc, 0x42, 0xad, 0x93, 0x0f, + 0x54, 0x94, 0x01, 0x10, 0x7d, 0xf9, 0x5b, 0x56, 0x2d, 0xc3, 0xe0, 0x30, 0x20, 0x33, 0x07, 0x09, 0x3a, 0x9c, 0x34, + 0x6e, 0x6f, 0xbf, 0x88, 0x86, 0x50, 0xc7, 0x46, 0x1e, 0x80, 0xaf, 0x5c, 0xae, 0xb7, 0xfe, 0x0d, 0x11, 0x3f, 0x99, + 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x3f, 0x16, 0x9e, 0x6d, + 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, 0xe5, + 0xbf, 0xbc, 0x7f, 0x65, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, 0xfe, + 0x78, 0xb0, 0xed, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x9b, 0xd5, + 0x87, 0x0f, 0xb6, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x5b, 0xc2, 0x0f, 0x5e, 0xff, 0xe1, + 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, 0xa8, + 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, 0x9d, + 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, 0x2e, + 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xfb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, 0x79, + 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0xfc, 0xf8, 0x55, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, 0x2e, + 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, 0x95, + 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0x49, 0x87, 0x5d, + 0x3e, 0x5d, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc5, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, + 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x09, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x45, 0x9d, 0x95, 0xe0, 0x49, 0xe5, 0x71, 0xe2, 0x2a, 0x16, 0x40, 0x46, 0x4d, 0x34, 0x80, 0x8e, 0x1c, 0x34, 0xb4, 0x7b, 0x4d, 0x3b, 0x96, 0x1b, 0x95, 0x45, 0x06, 0x96, 0xb0, 0xcf, 0xa1, 0x74, 0x40, 0x6c, 0x87, 0x70, 0x21, 0x70, 0xf5, 0xc4, 0xab, 0x51, 0x03, 0xb1, 0x87, 0x96, 0xbe, 0xbb, 0x90, 0x62, 0xb5, 0x0c, 0xda, 0x65, 0x63, 0x98, 0xf0, 0x7a, 0x8d, 0x2e, 0xc3, 0xa0, 0xf8, 0x2f, 0xdc, 0xa2, 0x44, 0x5c, 0xa4, 0x2c, 0x55, 0x46, 0x67, 0x3d, 0x94, 0x85, 0xe1, 0xb3, 0xa7, - 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0x8d, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, - 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0xdd, 0xc2, 0xc0, 0x5d, 0xe8, 0xb2, - 0x5a, 0x93, 0xb8, 0xf7, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, + 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0xad, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, + 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0x66, 0x61, 0xe0, 0x2e, 0x74, 0x59, + 0xad, 0x49, 0xbc, 0xf3, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, 0x6a, 0x7f, 0xab, 0x7d, 0xe2, 0x9e, 0x6d, 0xd7, 0x68, 0xd3, 0xcf, 0xa1, 0x5d, 0x23, 0x35, 0x4b, 0xa9, 0xe0, 0x7f, - 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0xd4, 0x87, 0x91, 0x26, 0xd1, 0x0a, 0x09, 0x4a, 0x51, 0xdf, - 0xd6, 0x0b, 0xd5, 0x06, 0x42, 0xd4, 0x6d, 0x31, 0x4d, 0x9f, 0x23, 0x68, 0x3b, 0x48, 0x49, 0x70, 0x6f, 0xd9, 0x98, - 0x5f, 0x5d, 0xcb, 0x67, 0x0e, 0xdd, 0x59, 0xcc, 0x3e, 0x97, 0x61, 0x30, 0x88, 0x3e, 0x97, 0x85, 0x4d, 0xee, 0x59, - 0xa5, 0x2a, 0xcb, 0xb1, 0xb1, 0xbd, 0x9c, 0xa2, 0x29, 0x4b, 0xf8, 0x76, 0x1d, 0x36, 0xd7, 0x3e, 0xc5, 0xd9, 0xa7, - 0x9b, 0x2b, 0x5e, 0x2d, 0x65, 0x1a, 0x05, 0xdf, 0x3f, 0xff, 0x10, 0x18, 0xd5, 0x75, 0xa1, 0x41, 0x8b, 0xb4, 0x36, - 0x27, 0x97, 0x97, 0x20, 0xcb, 0xec, 0x15, 0x23, 0xf9, 0x71, 0x27, 0xca, 0xe7, 0x1f, 0x3f, 0x7c, 0xf8, 0xf0, 0xf6, - 0x00, 0x15, 0x3e, 0xbd, 0x83, 0xf7, 0x0a, 0x3d, 0xe0, 0xe0, 0xc1, 0xa6, 0xd0, 0x2a, 0xf6, 0xfa, 0x0f, 0x7b, 0x56, - 0x15, 0x2d, 0x05, 0xb9, 0x01, 0x05, 0xf4, 0xaa, 0x68, 0x0d, 0x6b, 0xe1, 0xb4, 0xd8, 0x7e, 0x66, 0xa5, 0x5d, 0x0a, - 0x50, 0x77, 0xa2, 0x6a, 0x8e, 0x94, 0x5e, 0x1e, 0x22, 0x2d, 0x84, 0xd5, 0x9e, 0xad, 0x56, 0x75, 0x6d, 0x35, 0x59, - 0x54, 0x99, 0xb8, 0x3c, 0xc3, 0xdd, 0xff, 0x45, 0x5b, 0xce, 0xcc, 0xb0, 0xa2, 0x17, 0xed, 0xdd, 0xd6, 0x80, 0x2a, - 0xd3, 0x46, 0xb9, 0x7a, 0x0f, 0x81, 0xc0, 0xac, 0xac, 0xa7, 0xfe, 0xc7, 0xc6, 0x62, 0xc4, 0x4f, 0x53, 0x40, 0x6e, - 0xc0, 0x03, 0xb1, 0x93, 0x78, 0x64, 0xda, 0x77, 0x83, 0x72, 0x93, 0xe3, 0xa4, 0x95, 0x30, 0x1b, 0x4e, 0xa2, 0x09, - 0xb1, 0xf1, 0x25, 0x34, 0x0d, 0xfb, 0x7e, 0xf4, 0xfc, 0xf5, 0x87, 0x97, 0x1f, 0xfe, 0x79, 0xf6, 0xf4, 0xf4, 0xc3, - 0xf3, 0xef, 0xdf, 0xbc, 0x7b, 0xf9, 0xfc, 0x3d, 0x9e, 0x10, 0x1a, 0xb0, 0x32, 0xdc, 0x68, 0xab, 0xe8, 0x66, 0x59, - 0x91, 0xa8, 0x49, 0xb3, 0x29, 0x0a, 0x31, 0x0a, 0x33, 0xdb, 0x22, 0x7f, 0x79, 0xfd, 0xec, 0xf9, 0x8b, 0x97, 0xaf, - 0x9f, 0x3f, 0x6b, 0x7f, 0x3d, 0x9c, 0xd4, 0xa4, 0x76, 0x33, 0xa7, 0x23, 0xa4, 0x70, 0x3b, 0x5e, 0x1d, 0xf4, 0x09, - 0xb5, 0xf2, 0x3e, 0x7d, 0xca, 0x60, 0x45, 0x32, 0x25, 0xa7, 0xc7, 0xdf, 0x1e, 0xfe, 0xaf, 0xda, 0x78, 0xdb, 0x2d, - 0xf0, 0x10, 0x48, 0xc6, 0x94, 0xac, 0x1f, 0x46, 0x35, 0xa3, 0xea, 0x65, 0x24, 0xa8, 0x2d, 0x0d, 0x6c, 0xa0, 0x53, - 0xaa, 0x42, 0x2a, 0x9c, 0x25, 0x71, 0xc5, 0x2f, 0x65, 0x71, 0x17, 0x65, 0xa3, 0x56, 0x0a, 0x6d, 0x2c, 0x80, 0x28, - 0x04, 0xc1, 0x72, 0x23, 0x89, 0xf4, 0x14, 0x01, 0xf0, 0x86, 0xc0, 0x8d, 0xea, 0xdc, 0x45, 0x0b, 0x68, 0x17, 0x4c, - 0x16, 0xdb, 0x6d, 0xc7, 0xa0, 0x75, 0xd2, 0xbe, 0x68, 0x9e, 0x29, 0xa2, 0xb8, 0x00, 0xc6, 0x1c, 0x8e, 0x37, 0x75, - 0x76, 0x31, 0x73, 0xdc, 0x9d, 0xea, 0xa8, 0x9f, 0x60, 0x8d, 0xe8, 0x5e, 0x9b, 0xc0, 0x32, 0xcd, 0xf3, 0x70, 0xdc, - 0xa2, 0xb8, 0x06, 0xe3, 0xb7, 0x95, 0xaa, 0x96, 0x99, 0xc6, 0x56, 0x84, 0x99, 0x82, 0x70, 0x5c, 0x46, 0x74, 0x1b, - 0xe6, 0x60, 0x21, 0xd3, 0x98, 0x5f, 0x33, 0x0e, 0x79, 0x24, 0x0d, 0x4c, 0x1e, 0x98, 0x0c, 0xee, 0xc9, 0xb5, 0x8c, - 0x8a, 0x06, 0xe0, 0xa5, 0x6c, 0x0e, 0xea, 0xf1, 0xff, 0x69, 0xef, 0x69, 0xb7, 0xdb, 0xb6, 0x91, 0xfd, 0xdf, 0xa7, - 0x60, 0x98, 0x6c, 0x4a, 0x26, 0x24, 0x4d, 0x4a, 0x96, 0xad, 0x48, 0x96, 0xdc, 0xe6, 0x6b, 0x9b, 0xd6, 0x6d, 0x7a, - 0x62, 0x37, 0x7b, 0x77, 0x5d, 0x1f, 0x8b, 0x92, 0x20, 0x89, 0x1b, 0x8a, 0xd4, 0x25, 0x29, 0x4b, 0xae, 0xc2, 0x7d, - 0x96, 0x7d, 0x84, 0xfb, 0x0c, 0x7d, 0xb2, 0x7b, 0x66, 0x06, 0x20, 0xc1, 0x0f, 0xc9, 0x72, 0x93, 0xb6, 0x7b, 0xcf, - 0xb9, 0xa7, 0x4d, 0x22, 0x82, 0x00, 0x08, 0x0c, 0x80, 0x99, 0xc1, 0x7c, 0x46, 0xc5, 0x67, 0xd8, 0xc6, 0xa5, 0x2a, - 0x28, 0xb2, 0x2d, 0x56, 0x02, 0xd1, 0xc2, 0xe8, 0x94, 0x3e, 0x6f, 0x25, 0xe1, 0x59, 0xb8, 0x12, 0xe2, 0xe1, 0x93, - 0xa8, 0xa6, 0x10, 0xcf, 0x46, 0xc7, 0x3d, 0x19, 0xd1, 0x0f, 0x27, 0xdd, 0x42, 0x04, 0xd2, 0x1c, 0xc0, 0x19, 0x73, - 0x3a, 0xa0, 0x2b, 0xd3, 0xf5, 0xa3, 0x8d, 0xd8, 0x78, 0xe9, 0xc0, 0xcb, 0x92, 0xbf, 0x16, 0x18, 0x8b, 0x94, 0x83, - 0x5e, 0x8e, 0x35, 0x5a, 0x53, 0x8d, 0xef, 0x8f, 0x9e, 0x57, 0xcb, 0x9d, 0x58, 0xf4, 0xc8, 0x28, 0x17, 0x66, 0x7d, - 0x15, 0xb6, 0x66, 0x23, 0xad, 0x6e, 0x60, 0x24, 0x5e, 0x12, 0x53, 0xc0, 0xf0, 0xcb, 0x88, 0xf1, 0x1f, 0x55, 0x30, - 0x3e, 0x5a, 0xd9, 0x65, 0x08, 0xff, 0xc7, 0xb7, 0xe7, 0x17, 0xa0, 0xbd, 0x72, 0x51, 0xdd, 0xbc, 0x51, 0xb9, 0xa5, - 0x8a, 0x09, 0xfa, 0x20, 0xb5, 0xa3, 0xba, 0x0b, 0xa0, 0xc7, 0x78, 0x2f, 0x38, 0x58, 0x9b, 0xab, 0xd5, 0xca, 0x04, - 0xbb, 0x55, 0x73, 0x19, 0xf9, 0xc4, 0x03, 0x8e, 0xd5, 0x54, 0x20, 0x72, 0x56, 0x42, 0xe4, 0x10, 0xf4, 0x96, 0x67, - 0x4d, 0x39, 0x9f, 0x85, 0xab, 0xaf, 0x7d, 0x5f, 0x16, 0xce, 0x08, 0x56, 0x8d, 0xcb, 0x2b, 0x0a, 0x88, 0x41, 0x03, - 0x1d, 0x93, 0xe5, 0xc5, 0xd7, 0xdc, 0x2a, 0x60, 0x7c, 0x3d, 0xbc, 0xbd, 0xe6, 0x9a, 0x87, 0x2c, 0xea, 0xf0, 0xf9, - 0xe0, 0x64, 0xec, 0xdd, 0x28, 0xc8, 0x4f, 0xf6, 0x54, 0x70, 0xd9, 0xf2, 0xd9, 0x70, 0x99, 0x24, 0x61, 0x60, 0x46, - 0xe1, 0x4a, 0xed, 0x9f, 0xd0, 0x83, 0xa8, 0xe0, 0xd2, 0xa3, 0xaa, 0x7c, 0x35, 0xf2, 0xbd, 0xd1, 0x87, 0x9e, 0xfa, - 0x68, 0xe3, 0xf5, 0xfa, 0x25, 0xae, 0xd1, 0x4e, 0xd5, 0x3e, 0x8c, 0x55, 0xf9, 0xda, 0xf7, 0x4f, 0x0e, 0xa8, 0x45, - 0xff, 0xe4, 0x60, 0xec, 0xdd, 0xf4, 0xa5, 0x04, 0x30, 0x5c, 0x3b, 0xda, 0xe3, 0x81, 0x36, 0x33, 0x7b, 0xb2, 0x18, - 0x23, 0x37, 0x8c, 0x98, 0x96, 0x5f, 0x71, 0x21, 0xa2, 0x0c, 0x8d, 0x57, 0x1b, 0xa1, 0xd0, 0xdc, 0x87, 0x0b, 0xdd, - 0xc7, 0x8f, 0x5a, 0x66, 0x6d, 0x3a, 0x93, 0x42, 0xb1, 0xa1, 0x32, 0x0f, 0xab, 0x18, 0x18, 0x4f, 0x46, 0xd7, 0x44, - 0xc0, 0x38, 0x5f, 0x37, 0x46, 0xa9, 0x81, 0x79, 0x74, 0xdc, 0x05, 0xe8, 0x15, 0xf9, 0x4f, 0xe9, 0xde, 0x3b, 0x82, - 0xdc, 0xd9, 0x12, 0xe2, 0xd6, 0x25, 0xcd, 0x0a, 0x9d, 0x42, 0x1e, 0x0d, 0x10, 0x54, 0x22, 0xf8, 0x1d, 0xd2, 0x76, - 0x68, 0xbe, 0x0e, 0xb9, 0xdb, 0xb2, 0x10, 0x3c, 0x6e, 0x2a, 0xb2, 0xa5, 0x09, 0xb8, 0x9c, 0x16, 0x56, 0xa8, 0x53, - 0x5e, 0x2f, 0x11, 0x1b, 0xf2, 0x41, 0xbc, 0x6d, 0xc9, 0x40, 0x53, 0xa7, 0x25, 0x46, 0x89, 0xce, 0x82, 0xef, 0x9e, - 0xa4, 0x1e, 0x62, 0x86, 0x76, 0x19, 0x1b, 0xe1, 0x55, 0x4e, 0x9b, 0x62, 0x42, 0x94, 0x9d, 0x30, 0xcd, 0xc3, 0x34, - 0xd3, 0xaa, 0xf7, 0x1f, 0x6d, 0x02, 0x24, 0x66, 0x71, 0xaf, 0x5f, 0xdc, 0x07, 0x89, 0x3b, 0x34, 0x69, 0x33, 0xab, - 0xca, 0x57, 0xe3, 0xa1, 0x9f, 0x2d, 0x36, 0x1d, 0x82, 0x99, 0x1b, 0x8c, 0x7d, 0x76, 0xe1, 0x0e, 0xbf, 0xc1, 0x3a, - 0x2f, 0x87, 0xfe, 0x0b, 0xa8, 0x90, 0xaa, 0xfd, 0x47, 0x1b, 0x22, 0xd7, 0x75, 0x08, 0x3b, 0xa5, 0x2d, 0x50, 0xfe, - 0x0e, 0x4f, 0xac, 0xc4, 0x22, 0x6a, 0x8d, 0x83, 0x25, 0x12, 0x4b, 0x18, 0xb5, 0x38, 0x32, 0x9e, 0xd8, 0x07, 0xf6, - 0xa6, 0xc2, 0x4f, 0x2d, 0x8c, 0x2b, 0x14, 0x27, 0x58, 0xde, 0x99, 0xf2, 0x60, 0x89, 0x94, 0xbe, 0x0b, 0x57, 0x62, - 0xa4, 0x1c, 0x00, 0x14, 0x88, 0xf2, 0xf4, 0x7c, 0x70, 0x22, 0x2b, 0x7f, 0x50, 0x42, 0x4e, 0xfd, 0xc2, 0xaf, 0x54, - 0x55, 0xf2, 0x34, 0x4f, 0x8b, 0xb5, 0xda, 0x3f, 0x39, 0x90, 0x6b, 0xf7, 0x07, 0x9d, 0x57, 0xd2, 0xe4, 0xb0, 0x57, - 0x71, 0x3b, 0xbe, 0xcc, 0x1f, 0xd2, 0x2b, 0x05, 0xee, 0xc2, 0x29, 0x94, 0x00, 0x8c, 0x8a, 0x4d, 0x2a, 0xe4, 0x07, - 0x12, 0x23, 0xe6, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0xa1, 0xde, 0xc9, 0x96, 0x90, 0xec, 0x2f, 0x45, 0x6f, 0x03, - 0xfe, 0x6f, 0x0e, 0x12, 0x94, 0x67, 0xb3, 0x20, 0x0e, 0x23, 0x15, 0xa6, 0x59, 0xce, 0x8e, 0xa4, 0x48, 0x59, 0xd9, - 0x70, 0xc2, 0xb5, 0x64, 0x15, 0x00, 0x76, 0x50, 0x6e, 0x2a, 0xcd, 0x7b, 0xa0, 0xe7, 0x3f, 0x14, 0x3e, 0x99, 0x12, - 0xd2, 0xca, 0x06, 0xb8, 0x3d, 0xeb, 0xd4, 0xe5, 0x5b, 0xcf, 0xf8, 0x5b, 0x68, 0xcc, 0x5d, 0x63, 0xe8, 0x1a, 0xe7, - 0xc1, 0x55, 0x5a, 0xbb, 0x78, 0x59, 0xc6, 0x38, 0x83, 0x75, 0x35, 0x88, 0xb3, 0x54, 0xbc, 0x57, 0x78, 0x16, 0xb7, - 0x0c, 0xb9, 0x70, 0xa3, 0x29, 0x13, 0x89, 0xda, 0xc4, 0x5b, 0x21, 0x21, 0xd0, 0x25, 0xb0, 0x40, 0x10, 0xb2, 0x07, - 0xdc, 0x80, 0xce, 0xb3, 0x46, 0x49, 0xe4, 0x7f, 0xc7, 0x6e, 0xe1, 0x3a, 0x19, 0x27, 0xe1, 0x02, 0x24, 0x53, 0xee, - 0x94, 0x6b, 0x1a, 0x0c, 0x60, 0x6a, 0xf6, 0xf9, 0xdc, 0xc7, 0x8f, 0x4c, 0xca, 0x1d, 0x96, 0x84, 0xd3, 0xa9, 0xcf, - 0x34, 0x29, 0xc7, 0x58, 0xf6, 0x99, 0xd3, 0x07, 0xb6, 0x88, 0x4f, 0xad, 0xa7, 0xdb, 0x0e, 0x56, 0xce, 0x01, 0x0a, - 0x9d, 0x3e, 0x20, 0x2e, 0x32, 0xa1, 0x42, 0x26, 0x5c, 0x13, 0xe7, 0x22, 0x3f, 0xb8, 0xe6, 0x38, 0x5c, 0x0e, 0x7d, - 0x66, 0xe2, 0x69, 0x80, 0x4f, 0x6e, 0x86, 0xcb, 0xe1, 0xd0, 0xa7, 0xa4, 0x60, 0x10, 0x65, 0x2d, 0x8c, 0x51, 0xfa, - 0x99, 0xea, 0x5d, 0xe4, 0xd4, 0x92, 0xf2, 0xf0, 0xc1, 0x32, 0x12, 0x6e, 0x0b, 0xf4, 0x81, 0x04, 0x24, 0x9d, 0xd5, - 0x33, 0xdd, 0x53, 0xe1, 0x96, 0xc2, 0x62, 0xb5, 0x5b, 0xc3, 0xd2, 0xf5, 0x2e, 0xd5, 0x73, 0x84, 0xb0, 0xe2, 0x06, - 0x63, 0xe5, 0x05, 0xed, 0x5d, 0xd5, 0x50, 0xc9, 0xc0, 0x8b, 0xe7, 0x90, 0x53, 0x0d, 0xf5, 0xa5, 0xe7, 0x4e, 0x83, - 0x30, 0x4e, 0xbc, 0x91, 0x7a, 0xd5, 0x7d, 0xe9, 0x69, 0x97, 0xf3, 0x44, 0xd3, 0xaf, 0x8c, 0xbf, 0xca, 0xd9, 0xbe, - 0x04, 0xa6, 0xc4, 0x64, 0x5f, 0x5b, 0xea, 0xc8, 0xa7, 0x67, 0x57, 0x3d, 0x81, 0x91, 0xb1, 0xce, 0x5f, 0x7b, 0x50, - 0xab, 0x94, 0x37, 0x0c, 0x13, 0x42, 0x42, 0xde, 0xb0, 0xbf, 0xea, 0x5d, 0x12, 0xb5, 0x7c, 0xbd, 0xdc, 0x20, 0xd3, - 0x90, 0xe4, 0xc4, 0x17, 0x43, 0xdd, 0x0b, 0xff, 0x50, 0x7a, 0x7e, 0x20, 0xfb, 0x36, 0x14, 0xc8, 0xf8, 0xe0, 0xeb, - 0x22, 0x07, 0xf2, 0x68, 0x93, 0xa4, 0x60, 0x58, 0x18, 0x84, 0x89, 0x02, 0xf1, 0xdb, 0xe0, 0x83, 0x83, 0xb2, 0x2d, - 0x34, 0xef, 0x55, 0xd3, 0x53, 0x8e, 0x05, 0x9e, 0x23, 0x2d, 0x45, 0xf9, 0x24, 0x84, 0x9b, 0x80, 0x50, 0xa4, 0x85, - 0x68, 0x4d, 0xdc, 0x03, 0x0f, 0x96, 0xaf, 0xc0, 0xbf, 0x49, 0x78, 0xbf, 0x48, 0xcf, 0x1f, 0x6d, 0xe2, 0x53, 0x41, - 0xd4, 0xdf, 0xc4, 0xb8, 0x96, 0xc0, 0xae, 0x70, 0x2a, 0x9f, 0xaa, 0xca, 0xa9, 0xa0, 0x44, 0x58, 0xb7, 0x80, 0x5e, - 0x35, 0xc1, 0xee, 0x46, 0x22, 0x32, 0x3e, 0x4f, 0x3f, 0x2e, 0x18, 0xb0, 0xd2, 0xd1, 0x83, 0x90, 0x4c, 0x19, 0x6f, - 0x95, 0x80, 0x5d, 0x35, 0x12, 0x0c, 0xc0, 0x5c, 0x9c, 0x47, 0x18, 0xa4, 0xd7, 0xc0, 0x48, 0x42, 0x9c, 0x32, 0x31, - 0x47, 0x23, 0x94, 0x53, 0xc5, 0x79, 0xc1, 0x62, 0x99, 0x60, 0xfc, 0x79, 0x18, 0x00, 0x4b, 0x55, 0x05, 0x2f, 0x89, - 0x80, 0xeb, 0xf3, 0xcb, 0x4f, 0xaa, 0x2a, 0xde, 0xb8, 0x5a, 0xc6, 0xe5, 0x31, 0x80, 0xe3, 0x70, 0x1a, 0xa8, 0xbd, - 0x81, 0xc7, 0x88, 0x4f, 0x63, 0x64, 0xe4, 0xc9, 0x5b, 0xb4, 0x11, 0x5a, 0x39, 0xd4, 0x20, 0x90, 0x11, 0xf5, 0xd3, - 0xd5, 0xfc, 0xda, 0xc9, 0x42, 0x4c, 0xea, 0xc2, 0x34, 0x07, 0x20, 0x89, 0x3c, 0x05, 0xd8, 0xf5, 0x1e, 0x6d, 0xdc, - 0xcc, 0x80, 0x4e, 0xbd, 0x50, 0xc9, 0x7a, 0x6e, 0x80, 0x60, 0x18, 0xa4, 0xd7, 0xb9, 0x3b, 0x6b, 0x3e, 0x5f, 0xd8, - 0x92, 0x54, 0xae, 0xa0, 0x3d, 0x5b, 0x8f, 0x5b, 0xad, 0x2d, 0x22, 0x6f, 0xee, 0x46, 0xb7, 0x64, 0xe4, 0x66, 0xc8, - 0x96, 0x70, 0xba, 0xaa, 0x10, 0x3d, 0x20, 0x00, 0x10, 0x69, 0x50, 0x95, 0xaf, 0xb2, 0x32, 0xc6, 0x67, 0x9b, 0x59, - 0xfa, 0xc0, 0xb7, 0xae, 0xd5, 0xa7, 0xcc, 0x22, 0x29, 0x23, 0x35, 0xe9, 0x6a, 0xf1, 0x96, 0xe9, 0xc5, 0xc5, 0xe9, - 0x05, 0xc5, 0x8d, 0x86, 0x93, 0x21, 0x4a, 0x41, 0xe3, 0xc6, 0x99, 0x61, 0xaa, 0xcb, 0xfa, 0x15, 0xa5, 0x77, 0x7f, - 0xe8, 0x72, 0x30, 0x58, 0x8e, 0x00, 0x96, 0xa3, 0x46, 0x00, 0xeb, 0x8a, 0x15, 0x01, 0x5e, 0x04, 0xb8, 0x90, 0x08, - 0x39, 0x10, 0xca, 0x82, 0xa9, 0x64, 0x5b, 0x28, 0x82, 0xa3, 0x41, 0x63, 0xa7, 0xa3, 0x11, 0xf5, 0x7a, 0x21, 0xb6, - 0x8a, 0xd2, 0x93, 0x03, 0xaa, 0x4d, 0x44, 0x91, 0x2a, 0x01, 0x18, 0x22, 0x98, 0x61, 0x0e, 0x05, 0x48, 0x03, 0xde, - 0x73, 0xf2, 0x8b, 0x8e, 0x35, 0x47, 0xe5, 0xb3, 0x73, 0x5a, 0x64, 0x78, 0xb0, 0x95, 0xda, 0x3f, 0xc1, 0xc4, 0x9e, - 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xc9, 0x01, 0x3d, 0x2a, 0xa5, 0x13, 0x91, 0x77, 0x22, 0xa4, 0x8e, 0x1d, 0xde, 0xc1, - 0xbd, 0x8e, 0x4a, 0x9c, 0xb0, 0x05, 0x94, 0xba, 0xa9, 0xaa, 0xcc, 0x39, 0x83, 0xc5, 0x63, 0xec, 0x41, 0x00, 0x1e, - 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xee, 0xae, 0x71, 0xe6, 0xe2, 0x8d, 0xbb, 0xd6, 0x1c, 0xfe, 0x2a, 0x3f, 0x6b, 0x71, - 0xf1, 0xac, 0x8d, 0xf8, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x19, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, 0x4c, 0x2c, - 0xee, 0x78, 0xcb, 0xe2, 0x8e, 0x77, 0x2c, 0xae, 0xcf, 0x17, 0x52, 0xc9, 0x40, 0x17, 0xa1, 0xc7, 0x74, 0x06, 0x3c, - 0xce, 0x8f, 0x74, 0xf8, 0x39, 0x43, 0x38, 0x99, 0xb1, 0x0f, 0x16, 0xc3, 0x5b, 0x60, 0x55, 0x07, 0x17, 0x09, 0x10, - 0xd5, 0x89, 0x67, 0xa7, 0x6e, 0x24, 0x49, 0x06, 0x34, 0xbf, 0x3c, 0x5f, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x5b, - 0x66, 0x3a, 0xdb, 0x31, 0xd3, 0x51, 0xe1, 0xe8, 0xf2, 0x69, 0xd3, 0x21, 0x94, 0x27, 0x05, 0x7b, 0x10, 0xbc, 0x28, - 0x70, 0xcb, 0x14, 0xf7, 0xe1, 0x76, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x1b, 0xc7, 0xab, 0x30, 0x02, 0x33, 0x04, 0xe8, - 0xe6, 0x7e, 0x5b, 0x6a, 0xee, 0x05, 0x3c, 0xc2, 0xd9, 0xd6, 0xcd, 0x94, 0xbf, 0x97, 0xb7, 0x54, 0xa3, 0xd5, 0xa2, - 0x1a, 0x0b, 0x37, 0x49, 0x58, 0x84, 0x40, 0x77, 0x21, 0x15, 0xc6, 0x7f, 0xc8, 0x36, 0xab, 0xc1, 0x21, 0xbe, 0x84, - 0xd5, 0x11, 0x43, 0x2f, 0x80, 0x05, 0x23, 0xbd, 0x63, 0xa0, 0x6f, 0xa4, 0x68, 0xa9, 0x51, 0x06, 0xf8, 0x1f, 0xf0, - 0xb8, 0x6a, 0x91, 0xe4, 0xcf, 0xeb, 0x1c, 0xe9, 0xd6, 0xc2, 0x1d, 0x9f, 0x83, 0xb5, 0x8b, 0xd6, 0x30, 0xc0, 0x73, - 0x45, 0x8e, 0x8d, 0x1a, 0x11, 0x4f, 0x38, 0xca, 0x91, 0x24, 0x62, 0x49, 0x6e, 0x17, 0x0c, 0x21, 0x05, 0x5c, 0x73, - 0x72, 0xb5, 0x69, 0xa4, 0x07, 0x53, 0x4f, 0xaf, 0x60, 0x4d, 0x40, 0x6d, 0x7e, 0xaf, 0x9f, 0x09, 0xdd, 0x7c, 0xc3, - 0x39, 0xd2, 0x41, 0x1d, 0x7a, 0x09, 0x49, 0xcf, 0x6d, 0x71, 0x99, 0x1e, 0x44, 0x40, 0xb5, 0x40, 0x79, 0xf8, 0x78, - 0x8a, 0xbf, 0x9c, 0xab, 0xf4, 0xf1, 0x10, 0x7f, 0x35, 0xae, 0x32, 0x55, 0x55, 0x49, 0x8a, 0x20, 0xcd, 0x59, 0xed, - 0x17, 0xf6, 0x13, 0x19, 0x65, 0xdf, 0x63, 0xdb, 0xf0, 0x05, 0x7e, 0xf8, 0x68, 0x13, 0x43, 0x18, 0x02, 0x79, 0x0e, - 0x81, 0x15, 0xe9, 0x69, 0x6d, 0xf9, 0x74, 0x4b, 0xf9, 0x50, 0xff, 0x83, 0x09, 0x3f, 0xee, 0x92, 0x30, 0xa7, 0x29, - 0x45, 0x19, 0xc8, 0xf5, 0xd0, 0x0b, 0xdc, 0xe8, 0xf6, 0x9a, 0x6e, 0x21, 0x9a, 0x24, 0xe4, 0x7d, 0x90, 0x0b, 0x07, - 0x6e, 0x8b, 0x36, 0x20, 0x89, 0xa4, 0xa0, 0xba, 0xe5, 0x84, 0xbe, 0xf7, 0x5d, 0x24, 0xf1, 0x77, 0x85, 0x6b, 0x2c, - 0x5f, 0x90, 0xc2, 0x87, 0xae, 0x1f, 0x6d, 0x34, 0x56, 0xed, 0xa6, 0x34, 0xdb, 0x12, 0x03, 0x09, 0xcb, 0x83, 0x57, - 0xe2, 0xf9, 0xd8, 0xeb, 0xa0, 0x91, 0xc7, 0x30, 0x5c, 0x9b, 0x8f, 0x36, 0xc9, 0xa9, 0x3a, 0x77, 0xa3, 0x0f, 0x6c, - 0x6c, 0x8e, 0xbc, 0x68, 0xe4, 0x03, 0xf3, 0x38, 0xf4, 0xdd, 0xe0, 0x03, 0x7f, 0x34, 0xc3, 0x65, 0x82, 0x66, 0x5b, - 0x77, 0xde, 0xa0, 0x05, 0x4c, 0x48, 0x90, 0x88, 0x5c, 0x6d, 0x0d, 0x14, 0x94, 0xf3, 0x81, 0xb8, 0xd6, 0xe7, 0x8c, - 0x62, 0x5e, 0xcb, 0x00, 0xaf, 0x03, 0xb0, 0x24, 0x83, 0x30, 0x0e, 0x86, 0x8a, 0xeb, 0xa5, 0x1a, 0xf2, 0x54, 0x49, - 0x8f, 0x96, 0xe5, 0x21, 0xbe, 0xc6, 0x1e, 0x7e, 0xfb, 0xe7, 0xa0, 0xe4, 0x3e, 0x9f, 0xcb, 0x7a, 0xf9, 0xb4, 0x19, - 0x42, 0xa9, 0x49, 0xee, 0x83, 0xf7, 0xf8, 0x38, 0x67, 0x30, 0xb7, 0x7f, 0x5a, 0x6e, 0xec, 0xc6, 0xf1, 0x72, 0xce, - 0xc6, 0xa4, 0x0c, 0x3b, 0xcd, 0x07, 0x55, 0xbc, 0x87, 0xc8, 0x03, 0xfb, 0x79, 0xd9, 0x38, 0x3e, 0x7c, 0x01, 0x66, - 0x7c, 0xc0, 0x50, 0x86, 0x93, 0x89, 0x9a, 0x8b, 0x02, 0xee, 0x68, 0xe6, 0x1c, 0xfe, 0xbc, 0x7c, 0xfd, 0xca, 0x7e, - 0x9d, 0x35, 0x0e, 0x80, 0x31, 0x16, 0x36, 0x49, 0x9c, 0x2f, 0x96, 0xc6, 0x2b, 0x66, 0x34, 0x71, 0x83, 0xed, 0xd3, - 0xb9, 0x2c, 0x6c, 0xf1, 0x05, 0x63, 0x63, 0x60, 0xb8, 0x8d, 0x4a, 0xe9, 0xb5, 0xcf, 0x6e, 0x58, 0x66, 0xef, 0x54, - 0xfd, 0x58, 0x4d, 0x0b, 0x0c, 0xc8, 0xca, 0x75, 0x8f, 0x9c, 0xab, 0x93, 0xa6, 0x34, 0xc0, 0x39, 0xf0, 0x99, 0xcb, - 0x47, 0xac, 0x74, 0xa4, 0x06, 0x86, 0x2a, 0x0d, 0x60, 0xeb, 0xc8, 0x4e, 0xb7, 0x94, 0x77, 0x00, 0x51, 0x6f, 0x19, - 0x9b, 0xe1, 0xe8, 0x1d, 0x48, 0x60, 0xc1, 0xe1, 0xe4, 0xc3, 0xc9, 0xd3, 0x72, 0xa9, 0xc9, 0x36, 0x88, 0xd5, 0x89, - 0xda, 0x54, 0x12, 0xd2, 0x08, 0x17, 0x00, 0xf4, 0x85, 0x11, 0xe2, 0xaa, 0xda, 0xb5, 0x51, 0x8a, 0x33, 0x1f, 0x62, - 0x7a, 0xf7, 0x80, 0xc5, 0xf1, 0x56, 0x80, 0x65, 0x8b, 0x6e, 0xa8, 0x79, 0xed, 0x22, 0x3c, 0xf2, 0x72, 0xc3, 0x36, - 0x80, 0x25, 0xc0, 0x09, 0x96, 0xbf, 0x85, 0xe4, 0xe5, 0x7a, 0xce, 0x8d, 0x38, 0xa3, 0xe9, 0x50, 0xe5, 0x06, 0x76, - 0xdb, 0xde, 0xaf, 0x54, 0x3e, 0xa8, 0x02, 0x99, 0xae, 0x1d, 0x9a, 0x56, 0x40, 0xbd, 0x15, 0xa9, 0x12, 0x76, 0x20, - 0xc6, 0x54, 0xc2, 0xaf, 0x6c, 0x32, 0x61, 0xa3, 0x24, 0xd6, 0x85, 0x8c, 0x29, 0x0b, 0xa9, 0x0e, 0x4a, 0xbb, 0x07, - 0x3d, 0xf5, 0x07, 0x08, 0x2c, 0x23, 0x22, 0x0f, 0xf2, 0x01, 0x89, 0x3b, 0x53, 0x3d, 0x98, 0xa8, 0xc7, 0x22, 0x88, - 0xf8, 0x57, 0x40, 0x0a, 0x5d, 0x53, 0x8e, 0x43, 0xe3, 0xf4, 0x27, 0xdf, 0x17, 0x61, 0x66, 0xea, 0xb9, 0x1b, 0x15, - 0xed, 0x3a, 0xbe, 0x1b, 0xe7, 0x75, 0xcb, 0xb1, 0x53, 0xd5, 0x00, 0x87, 0xe6, 0x0f, 0xa5, 0x6d, 0x4c, 0x04, 0xaa, - 0xa7, 0x9e, 0xbd, 0x7d, 0xf1, 0xdd, 0xab, 0x97, 0xfb, 0x62, 0x04, 0xec, 0xb2, 0x09, 0x5d, 0x2e, 0x83, 0x1d, 0x9d, - 0xfe, 0xf4, 0xc3, 0xfd, 0xba, 0x6d, 0x38, 0xcf, 0x1c, 0xd5, 0x20, 0x1b, 0x74, 0x09, 0x2f, 0x8e, 0xc2, 0x1b, 0x16, - 0x7d, 0x32, 0x18, 0xe4, 0xce, 0xeb, 0x87, 0xfb, 0xf6, 0xc7, 0x57, 0x3f, 0xec, 0x3d, 0xd4, 0x23, 0xc7, 0x06, 0xdc, - 0x9e, 0x84, 0x8b, 0x7b, 0xcc, 0xae, 0xa9, 0x1a, 0xea, 0xc8, 0x0f, 0x63, 0xb6, 0x65, 0x04, 0x2f, 0xce, 0xde, 0x9e, - 0x23, 0xb8, 0x72, 0x16, 0x84, 0xba, 0xfa, 0xb4, 0xc9, 0xff, 0xf8, 0xee, 0xd5, 0xf9, 0xb9, 0x6a, 0x60, 0x4a, 0xee, - 0x58, 0xee, 0x9d, 0x6f, 0xe2, 0x3b, 0x28, 0x4e, 0xed, 0x5e, 0x27, 0xaa, 0x46, 0x17, 0xe9, 0xe2, 0x6c, 0xa8, 0xac, - 0xb2, 0xcd, 0x39, 0xb5, 0xe3, 0x5f, 0xa6, 0xdb, 0xef, 0x5e, 0xf3, 0xaa, 0xc1, 0x47, 0xbb, 0x49, 0x6a, 0xa1, 0x64, - 0xee, 0x05, 0xd7, 0x35, 0xa5, 0xee, 0xba, 0xa6, 0x14, 0xae, 0x8f, 0x15, 0xfc, 0xb8, 0x0c, 0xe7, 0x12, 0x3b, 0xc2, - 0xd6, 0x77, 0x83, 0x4b, 0xba, 0xc3, 0x7d, 0xc2, 0xa0, 0x79, 0x4a, 0x95, 0xf2, 0xa8, 0x6b, 0x8a, 0xf9, 0xc5, 0x2b, - 0x83, 0xed, 0xc8, 0x07, 0xcb, 0x7b, 0x26, 0xab, 0x21, 0x8b, 0xac, 0x2a, 0xf7, 0x9b, 0xe9, 0x95, 0x6e, 0x05, 0xd4, - 0x8c, 0x54, 0x37, 0x9c, 0xa6, 0x2c, 0xdc, 0x31, 0x98, 0xb3, 0x9b, 0xc3, 0x30, 0x49, 0xc2, 0x79, 0xc7, 0xb1, 0x17, - 0x6b, 0x55, 0xe9, 0x0a, 0x61, 0x07, 0xb7, 0xb6, 0xef, 0xfc, 0xfa, 0xef, 0x12, 0x9a, 0xa7, 0xf2, 0xeb, 0x84, 0xcd, - 0x17, 0x2c, 0x72, 0x93, 0x65, 0xc4, 0x52, 0xe5, 0xd7, 0xff, 0x79, 0x51, 0xba, 0xd8, 0x77, 0xe5, 0x36, 0xc4, 0xd2, - 0xcb, 0x4d, 0xae, 0xfd, 0x70, 0xf5, 0x20, 0xf7, 0xab, 0xbb, 0xa3, 0xf2, 0xcc, 0x9b, 0xce, 0xb2, 0xda, 0xa7, 0xc9, - 0x8e, 0xb9, 0x89, 0xd1, 0x93, 0x3e, 0x40, 0x39, 0x0b, 0x57, 0x9d, 0x5f, 0xff, 0x9d, 0x09, 0x6c, 0xee, 0xdc, 0x75, - 0xf5, 0x03, 0x2d, 0xae, 0x68, 0x7d, 0x9d, 0xca, 0x12, 0xc3, 0xfb, 0xca, 0x02, 0x57, 0x0a, 0x69, 0x57, 0x56, 0x75, - 0x73, 0x3b, 0xe6, 0xf4, 0x8d, 0x37, 0x9d, 0x7d, 0xea, 0xa4, 0x00, 0xa0, 0x77, 0xce, 0x0a, 0x2a, 0x7d, 0x86, 0x69, - 0x0d, 0x3a, 0xfb, 0x2f, 0xd8, 0x27, 0xce, 0xeb, 0xae, 0x29, 0x7d, 0x8e, 0xd9, 0x70, 0xc9, 0xed, 0xf9, 0x60, 0x90, - 0xa5, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0x69, 0xa5, 0x84, 0xb3, 0x17, 0x1d, 0x5b, 0xa7, 0x90, 0x3d, 0x7b, 0x00, - 0x04, 0x6d, 0xdc, 0x6b, 0xc0, 0xb1, 0x1d, 0x5f, 0x93, 0xab, 0x5a, 0xe5, 0xdb, 0x15, 0x64, 0x0d, 0xa5, 0x98, 0xce, - 0x34, 0xd3, 0x1a, 0x1a, 0xf5, 0xc3, 0x59, 0x45, 0xee, 0x82, 0x94, 0x04, 0x0a, 0x6a, 0x4c, 0x40, 0xe8, 0x52, 0xba, - 0x45, 0xdf, 0xb8, 0xfe, 0xcd, 0x7e, 0x17, 0xaa, 0xed, 0x14, 0x0c, 0x49, 0xf3, 0x9f, 0x47, 0xbc, 0x91, 0x2e, 0xdf, - 0x9b, 0x76, 0xaf, 0xdc, 0x84, 0x45, 0xd7, 0x33, 0xf0, 0xe9, 0x15, 0xd2, 0x03, 0x88, 0x96, 0xbb, 0x0b, 0x29, 0x17, - 0xd8, 0xd2, 0x1a, 0x34, 0x9a, 0x63, 0xb8, 0xdf, 0x86, 0xbb, 0x3f, 0x13, 0xe6, 0xee, 0xbc, 0x02, 0xaf, 0xcb, 0xdf, - 0x0d, 0x7b, 0xef, 0xa2, 0x4c, 0xff, 0x8f, 0xbd, 0xff, 0x13, 0xb1, 0xf7, 0xce, 0xef, 0xfc, 0x96, 0x85, 0xfd, 0x3f, - 0x80, 0xe5, 0x3b, 0xac, 0xf7, 0x8a, 0x63, 0x7a, 0x4d, 0x73, 0x7b, 0x42, 0xb9, 0x2a, 0xe3, 0xd5, 0x8a, 0x82, 0x95, - 0x87, 0x54, 0xe3, 0x96, 0x83, 0x2e, 0x22, 0xfb, 0x1d, 0x47, 0xf9, 0xf7, 0x47, 0xf4, 0x31, 0xe5, 0xa1, 0x92, 0x30, - 0x7d, 0xe7, 0x95, 0x11, 0x17, 0x66, 0xe2, 0xae, 0xdc, 0xdb, 0x7d, 0xf0, 0x8e, 0x18, 0xec, 0xd7, 0x2b, 0xf7, 0xb6, - 0x6e, 0xb0, 0x5b, 0xd1, 0x6b, 0xf9, 0x63, 0xa7, 0xe0, 0xcb, 0xd3, 0x41, 0x47, 0x1e, 0x63, 0x10, 0xb3, 0xe4, 0x14, - 0x0a, 0x7b, 0x8f, 0x36, 0x0f, 0xca, 0x15, 0xd3, 0x01, 0x78, 0x39, 0x4b, 0x03, 0x0f, 0x0b, 0x03, 0xf7, 0xe2, 0xeb, - 0x30, 0xb8, 0xcf, 0xc8, 0x7f, 0x04, 0xe1, 0xcf, 0x6f, 0x1e, 0x3a, 0x7e, 0xae, 0x32, 0x76, 0x2c, 0x2d, 0x0f, 0x1e, - 0x0b, 0xcb, 0xa3, 0xef, 0xd6, 0xcb, 0xea, 0x4b, 0x84, 0x16, 0x69, 0x2c, 0x23, 0x42, 0xab, 0x80, 0x5e, 0x45, 0x01, - 0x1d, 0x97, 0x20, 0xb9, 0x98, 0xa0, 0xf4, 0xd5, 0x36, 0xa7, 0xae, 0x37, 0x77, 0x3b, 0x75, 0x5d, 0xec, 0xe5, 0xd4, - 0xf5, 0xe6, 0xb3, 0x3b, 0x75, 0xbd, 0x92, 0x9d, 0xba, 0xe0, 0x50, 0xbd, 0x62, 0x7b, 0xf9, 0xd0, 0x08, 0x3b, 0xd7, - 0x70, 0x15, 0xf7, 0x1c, 0x2e, 0x6e, 0x8b, 0x47, 0x33, 0x06, 0xfa, 0x0b, 0xbe, 0xff, 0xfd, 0x70, 0x0a, 0xae, 0x2e, - 0xdb, 0x9d, 0x59, 0x3e, 0x97, 0x2b, 0x8b, 0x1f, 0x4e, 0x55, 0x29, 0x45, 0x4b, 0x20, 0x52, 0xb4, 0x40, 0x58, 0x9a, - 0x9f, 0xd7, 0xce, 0xf3, 0x4b, 0xa7, 0xdb, 0x74, 0x20, 0xc4, 0x19, 0x88, 0xa4, 0xb1, 0xc0, 0xee, 0x36, 0x9b, 0x50, - 0xb0, 0x92, 0x0a, 0x1a, 0x50, 0xe0, 0x49, 0x05, 0x2d, 0x28, 0x18, 0x49, 0x05, 0x47, 0x50, 0x30, 0x96, 0x0a, 0x8e, - 0xa1, 0xe0, 0x46, 0x4d, 0x2f, 0x83, 0xcc, 0x65, 0xed, 0x58, 0xbf, 0x2a, 0x64, 0xe7, 0xca, 0xf4, 0x27, 0xa2, 0xca, - 0xb1, 0x21, 0x42, 0x45, 0x9b, 0x87, 0x3a, 0x77, 0x8e, 0x1a, 0x7c, 0x31, 0x80, 0x20, 0x2e, 0xa0, 0x4e, 0x32, 0x40, - 0x19, 0x47, 0x35, 0x9b, 0xe2, 0xb5, 0xda, 0xc9, 0x5c, 0xbc, 0x6c, 0xa3, 0x21, 0x5c, 0xa6, 0x3a, 0xe8, 0xc0, 0x2b, - 0x2a, 0xb7, 0x9e, 0xce, 0xb2, 0xb8, 0x91, 0xcb, 0x5e, 0xee, 0x07, 0xdf, 0x84, 0xe8, 0xf9, 0x60, 0x14, 0xf5, 0x12, - 0x6f, 0xa6, 0x56, 0x12, 0x82, 0x9b, 0xb3, 0x88, 0x97, 0x28, 0x3e, 0xa0, 0xa0, 0x1f, 0x5c, 0xd7, 0xcd, 0x43, 0x5b, - 0xf2, 0x28, 0xab, 0x34, 0xfa, 0x79, 0x16, 0xbc, 0x92, 0x04, 0xac, 0x4b, 0x23, 0x71, 0xa7, 0x9d, 0x99, 0x41, 0xda, - 0xd5, 0xce, 0x14, 0xa2, 0x91, 0x9f, 0x8e, 0x3b, 0x0b, 0x63, 0x35, 0x63, 0x41, 0x67, 0xc2, 0xfd, 0x0f, 0x60, 0xfd, - 0xc9, 0xbc, 0x74, 0xae, 0x0b, 0xbb, 0x68, 0xdc, 0x13, 0xf9, 0x5b, 0x1a, 0xa5, 0x99, 0x6d, 0xa5, 0xdc, 0xa4, 0x57, - 0x93, 0x35, 0xaf, 0x9f, 0xc3, 0x00, 0xf3, 0x25, 0x1b, 0x2e, 0xa7, 0xca, 0x59, 0x38, 0xbd, 0xd3, 0xd8, 0x52, 0x7e, - 0x05, 0xa3, 0x54, 0xc9, 0xc4, 0xc4, 0x14, 0xdb, 0x9b, 0x7f, 0x8b, 0x1e, 0xd3, 0x62, 0xfd, 0x04, 0xc6, 0xa6, 0x24, - 0x84, 0xdc, 0xe0, 0x3b, 0x00, 0x6d, 0xc9, 0x9c, 0xf1, 0x0c, 0xe0, 0x27, 0x3d, 0x5f, 0xb8, 0xd2, 0x78, 0xfa, 0xdf, - 0xb3, 0x38, 0x76, 0xa7, 0xa2, 0x7e, 0x75, 0x9c, 0xe0, 0xd9, 0x9b, 0xc9, 0x98, 0x11, 0x80, 0xa0, 0xad, 0xf4, 0x2a, - 0x46, 0xaa, 0xe0, 0x3b, 0x03, 0xc6, 0xdb, 0xb0, 0x68, 0xb9, 0x45, 0xa7, 0x67, 0xc1, 0xf2, 0x14, 0x8d, 0x2b, 0x01, - 0x89, 0xdc, 0x30, 0xbf, 0x5c, 0x98, 0xb8, 0xd3, 0x72, 0x11, 0xad, 0x75, 0x2a, 0x8f, 0x2d, 0xb3, 0x6d, 0x2c, 0x14, - 0x7e, 0x8a, 0xb1, 0x9e, 0x1f, 0x4e, 0x7f, 0x57, 0x4b, 0xbd, 0x1d, 0x16, 0x96, 0xe7, 0x81, 0x11, 0x24, 0x03, 0x0b, - 0x61, 0xac, 0x58, 0x00, 0xc2, 0x4e, 0x90, 0xcc, 0x4c, 0x8c, 0x29, 0xa3, 0x35, 0x02, 0xdd, 0xb0, 0x70, 0x6d, 0x37, - 0xe5, 0x48, 0x5a, 0x9d, 0x68, 0x3a, 0x74, 0x35, 0xa7, 0x71, 0x6c, 0x88, 0x3f, 0x96, 0xdd, 0xd2, 0x53, 0xec, 0x41, - 0x19, 0x7b, 0x37, 0x9b, 0x49, 0x18, 0x24, 0xe6, 0xc4, 0x9d, 0x7b, 0xfe, 0x6d, 0x67, 0x1e, 0x06, 0x61, 0xbc, 0x70, - 0x47, 0xac, 0x9b, 0x2b, 0x0d, 0xba, 0x18, 0xa3, 0x91, 0x87, 0x09, 0x72, 0xac, 0x46, 0xc4, 0xe6, 0xd4, 0x3a, 0x0b, - 0xc1, 0x38, 0xf1, 0xd9, 0x3a, 0xe5, 0x9f, 0x2f, 0x54, 0xa6, 0xaa, 0xb8, 0xe5, 0xa8, 0x05, 0x48, 0xc0, 0x78, 0x7c, - 0x47, 0x88, 0x6a, 0xdc, 0xe5, 0x57, 0x91, 0x8e, 0xd5, 0x68, 0x45, 0x6c, 0xae, 0x58, 0xad, 0xad, 0x9d, 0x47, 0xe1, - 0xaa, 0x0f, 0xa3, 0xc5, 0xc6, 0x66, 0xcc, 0xfc, 0x09, 0xbe, 0x31, 0x31, 0xa4, 0x84, 0xe8, 0xc7, 0x44, 0x65, 0x03, - 0xf4, 0xc6, 0xe6, 0x5d, 0x78, 0xdd, 0x69, 0x28, 0x76, 0x77, 0xee, 0x05, 0x26, 0x4d, 0xe7, 0xd8, 0x5e, 0x48, 0x7d, - 0xc9, 0xf0, 0xd3, 0x37, 0x58, 0xdd, 0x51, 0xec, 0x2e, 0x08, 0x95, 0x27, 0x7e, 0xb8, 0xea, 0xcc, 0xbc, 0xf1, 0x98, - 0x05, 0x5d, 0x1c, 0x73, 0x56, 0xc8, 0x7c, 0xdf, 0x5b, 0xc4, 0x5e, 0xdc, 0x9d, 0xbb, 0x6b, 0xde, 0xeb, 0xe1, 0xb6, - 0x5e, 0x9b, 0xbc, 0xd7, 0xe6, 0xde, 0xbd, 0x4a, 0xdd, 0x40, 0xf8, 0x0a, 0xea, 0x87, 0x0f, 0xad, 0xa5, 0xd8, 0xa5, - 0x79, 0xee, 0xdd, 0xeb, 0x22, 0x62, 0x9b, 0xb9, 0x1b, 0x4d, 0xbd, 0xa0, 0x63, 0xa7, 0xd6, 0xcd, 0x86, 0x36, 0xc6, - 0xc3, 0x76, 0xbb, 0x9d, 0x5a, 0x63, 0xf1, 0x64, 0x8f, 0xc7, 0xa9, 0x35, 0x12, 0x4f, 0x93, 0x89, 0x6d, 0x4f, 0x26, - 0xa9, 0xe5, 0x89, 0x82, 0x66, 0x63, 0x34, 0x6e, 0x36, 0x52, 0x6b, 0x25, 0xd5, 0x48, 0x2d, 0xc6, 0x9f, 0x22, 0x36, - 0xee, 0xe2, 0x46, 0xe2, 0x8e, 0x50, 0xc7, 0xb6, 0x9d, 0x22, 0x06, 0xb8, 0x2c, 0xe0, 0x26, 0xd4, 0x67, 0x5d, 0x6d, - 0xf6, 0xae, 0xa9, 0xe4, 0x9f, 0x1b, 0x8d, 0x6a, 0xeb, 0x8d, 0xdd, 0xe8, 0xc3, 0x95, 0x22, 0xcd, 0xc2, 0x75, 0xa9, - 0xda, 0x46, 0x80, 0xc1, 0x5c, 0x77, 0x20, 0x56, 0x77, 0x77, 0x18, 0x46, 0x70, 0x66, 0x23, 0x77, 0xec, 0x2d, 0xe3, - 0x8e, 0xd3, 0x58, 0xac, 0x45, 0x11, 0xdf, 0xeb, 0x79, 0x01, 0x9e, 0xbd, 0x4e, 0x1c, 0xfa, 0xde, 0x58, 0x14, 0x6d, - 0x3b, 0x4b, 0x4e, 0x43, 0xef, 0x62, 0xa4, 0x3a, 0x0f, 0xe3, 0x2d, 0xba, 0xbe, 0xaf, 0x58, 0xcd, 0x58, 0x61, 0x6e, - 0x8c, 0x3a, 0x74, 0xc5, 0x8e, 0x09, 0x2e, 0x18, 0x95, 0xce, 0x39, 0x5c, 0xac, 0xb3, 0x3d, 0xef, 0x1c, 0x2d, 0xd6, - 0xe9, 0x57, 0x73, 0x36, 0xf6, 0x5c, 0x45, 0xcb, 0x77, 0x93, 0x63, 0x83, 0x9e, 0x5d, 0xdf, 0x6c, 0xd9, 0xa6, 0xe2, - 0x58, 0x40, 0x4e, 0x83, 0x07, 0xde, 0x7c, 0x11, 0x46, 0x89, 0x1b, 0x24, 0x69, 0x3a, 0xb8, 0x4a, 0xd3, 0xee, 0x85, - 0xa7, 0x5d, 0xfe, 0x5d, 0x23, 0x5a, 0x48, 0x76, 0x29, 0xa9, 0x7e, 0x65, 0xbc, 0x62, 0xb2, 0x0d, 0x2d, 0x90, 0x31, - 0xb4, 0x9f, 0x95, 0x2b, 0x13, 0xbd, 0xad, 0x56, 0x26, 0x20, 0x67, 0xd5, 0xc9, 0x24, 0xb7, 0x58, 0x05, 0x29, 0x10, - 0x54, 0x78, 0xc5, 0x7a, 0x17, 0x92, 0x41, 0x2e, 0x30, 0x3d, 0x58, 0x99, 0x02, 0x0a, 0xbc, 0xdc, 0xc6, 0x7b, 0x5e, - 0xdc, 0xcd, 0x7b, 0xfe, 0x23, 0xd9, 0x87, 0xf7, 0xbc, 0xf8, 0xec, 0xbc, 0xe7, 0xcb, 0x6a, 0x40, 0x81, 0x8b, 0xb0, - 0xa7, 0x66, 0x56, 0x14, 0x40, 0x9a, 0x22, 0x0a, 0xd5, 0xfb, 0x32, 0xf9, 0xad, 0x9e, 0xdd, 0xa2, 0x37, 0x4a, 0x3e, - 0x4f, 0x94, 0x1b, 0xee, 0x5e, 0x6f, 0x83, 0xde, 0x77, 0x91, 0xfc, 0x3c, 0x99, 0xf4, 0x5e, 0x86, 0x52, 0x41, 0xf6, - 0xc4, 0x0d, 0x4c, 0x0b, 0x61, 0x15, 0xe9, 0x4d, 0x66, 0x02, 0x0c, 0x89, 0x27, 0x21, 0x2a, 0x1b, 0xf9, 0x7b, 0x8d, - 0x33, 0x43, 0xfc, 0x6e, 0x71, 0x08, 0x5a, 0xe6, 0xf9, 0x22, 0x62, 0x6f, 0x54, 0xd4, 0xa5, 0x53, 0x96, 0xf0, 0x60, - 0x59, 0xcf, 0x6f, 0xdf, 0x8c, 0xb5, 0x8b, 0x50, 0x4f, 0xbd, 0xf8, 0x6d, 0x39, 0xf2, 0x85, 0x10, 0x7e, 0xc9, 0xd3, - 0x49, 0xb9, 0x31, 0xbd, 0x14, 0xe0, 0x0e, 0x5f, 0x53, 0xf3, 0xd3, 0xc2, 0x4c, 0x3b, 0x72, 0x43, 0x9e, 0xe1, 0xba, - 0x42, 0x8c, 0xb9, 0x87, 0xf8, 0x86, 0x73, 0x79, 0x98, 0xb4, 0x1b, 0x03, 0x86, 0x8d, 0xa9, 0xb9, 0x37, 0x4e, 0x53, - 0xbd, 0x2b, 0x00, 0x21, 0x11, 0x5a, 0x76, 0x17, 0x13, 0x17, 0xe7, 0x57, 0x3f, 0x6e, 0x05, 0x45, 0x26, 0x4e, 0x17, - 0x60, 0x34, 0xc8, 0x0d, 0xa2, 0x38, 0xcc, 0x54, 0x85, 0xc0, 0x47, 0xc6, 0xa4, 0xd2, 0x84, 0xc0, 0xca, 0x4d, 0x36, - 0xc1, 0x2e, 0x2c, 0x48, 0xd5, 0xdb, 0x85, 0x80, 0x83, 0x56, 0x8f, 0x10, 0xde, 0x4f, 0xc8, 0xea, 0x08, 0xed, 0xf0, - 0x3a, 0xf8, 0x90, 0xaa, 0x19, 0xef, 0x87, 0xdb, 0xaf, 0x7f, 0x72, 0x00, 0x0d, 0xfa, 0x25, 0x49, 0xdc, 0x1d, 0xce, - 0x1a, 0xc0, 0x4a, 0xc4, 0x2b, 0xc3, 0x8a, 0x57, 0xca, 0x93, 0x8d, 0x08, 0x8d, 0x99, 0xb8, 0x0b, 0x13, 0x44, 0x3f, - 0x88, 0x7b, 0x39, 0xc6, 0x93, 0xa2, 0x70, 0x76, 0x97, 0x31, 0xe0, 0x46, 0x14, 0x2d, 0x20, 0xfe, 0xe9, 0x8e, 0x96, - 0x51, 0x1c, 0x46, 0x9d, 0x45, 0xe8, 0x05, 0x09, 0x8b, 0x52, 0x04, 0xd5, 0x25, 0xc2, 0x47, 0x80, 0xe7, 0x6a, 0x13, - 0x2e, 0xdc, 0x91, 0x97, 0xdc, 0x76, 0x6c, 0xce, 0x52, 0xd8, 0x5d, 0xce, 0x1d, 0xd8, 0xb5, 0xf5, 0x3b, 0x1c, 0x9a, - 0x4f, 0x91, 0xf1, 0x8b, 0xaa, 0xec, 0x8c, 0xbc, 0xcd, 0xbb, 0xd2, 0x5b, 0x0a, 0x0e, 0x0a, 0xec, 0x87, 0x1b, 0x99, - 0x53, 0xc0, 0xf2, 0xb0, 0xd4, 0xf6, 0x98, 0x4d, 0x0d, 0xc4, 0xda, 0x60, 0x7b, 0x20, 0xfe, 0x58, 0x2d, 0x5d, 0xb1, - 0xeb, 0x8b, 0x81, 0xe3, 0xd1, 0xf7, 0x19, 0x59, 0xc7, 0x85, 0x54, 0xda, 0xc6, 0x3e, 0x35, 0x87, 0x6c, 0x12, 0x46, - 0x8c, 0x12, 0xc9, 0x38, 0xed, 0xc5, 0x7a, 0xff, 0xee, 0x77, 0x4f, 0xbf, 0xbe, 0x9f, 0x20, 0x4c, 0x34, 0xd1, 0x99, - 0x7e, 0x47, 0x6f, 0x55, 0x7a, 0x06, 0xac, 0x21, 0x41, 0x7e, 0x44, 0x9e, 0x90, 0x10, 0x04, 0xa4, 0x36, 0x5e, 0xf7, - 0x22, 0xe4, 0x34, 0x2f, 0x62, 0xbe, 0x9b, 0x78, 0x37, 0x82, 0x67, 0x6c, 0x1e, 0x2d, 0xd6, 0x62, 0x8d, 0x91, 0xe0, - 0xdd, 0x63, 0x91, 0x4a, 0x43, 0x11, 0x8b, 0x54, 0x2e, 0xc6, 0x45, 0xea, 0x56, 0x66, 0x23, 0x42, 0x58, 0x96, 0x28, - 0x7d, 0x6b, 0xb1, 0x96, 0x49, 0x74, 0xde, 0x2c, 0xa3, 0xd4, 0xe5, 0xd8, 0xe3, 0x73, 0x6f, 0x3c, 0xf6, 0x59, 0x5a, - 0x58, 0xe8, 0xe2, 0x5a, 0x4a, 0xc0, 0xc9, 0xe0, 0xe0, 0x0e, 0xe3, 0xd0, 0x5f, 0x26, 0xac, 0x1e, 0x5c, 0x04, 0x9c, - 0x86, 0x9d, 0x03, 0x07, 0x7f, 0x17, 0xc7, 0xda, 0x02, 0x76, 0x1b, 0xb6, 0x89, 0xdd, 0x85, 0x54, 0x43, 0x66, 0xb3, - 0x38, 0x74, 0x78, 0x95, 0x0d, 0xda, 0xa8, 0x99, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0x4b, - 0xb7, 0x92, 0x15, 0xa5, 0xc5, 0xc9, 0xfc, 0x3e, 0x67, 0xec, 0x59, 0xfd, 0x19, 0x7b, 0x26, 0xce, 0xd8, 0xee, 0x9d, - 0xf9, 0x70, 0xe2, 0xc0, 0x7f, 0xdd, 0x7c, 0x42, 0x1d, 0x5b, 0x69, 0x2e, 0xd6, 0x8a, 0xb3, 0x58, 0x2b, 0x66, 0x63, - 0xb1, 0x56, 0xb0, 0x6b, 0xb4, 0x79, 0x35, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf0, 0xca, 0x39, - 0x84, 0x77, 0xd0, 0xaa, 0x55, 0x7d, 0xd7, 0xd8, 0x7d, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0x89, 0x3b, 0x1c, - 0xb2, 0x71, 0x67, 0x12, 0x8e, 0x96, 0xf1, 0xbf, 0xf8, 0xf8, 0x39, 0x10, 0x77, 0x22, 0x82, 0x52, 0x3f, 0xa2, 0x29, - 0x48, 0x0f, 0x6f, 0x98, 0xe8, 0x61, 0x93, 0xad, 0x53, 0x87, 0xf2, 0x22, 0x35, 0xac, 0xc3, 0x9a, 0x4d, 0x5e, 0x0f, - 0xe8, 0xdf, 0x6d, 0x95, 0xb6, 0xa3, 0x98, 0x4f, 0x00, 0xcb, 0x4e, 0x70, 0xdc, 0x1f, 0x1a, 0x7c, 0x35, 0xed, 0x76, - 0xfd, 0x70, 0x2f, 0xc5, 0x97, 0xae, 0x04, 0x51, 0xe1, 0x74, 0x8b, 0xfb, 0xe7, 0xee, 0xee, 0x75, 0xdb, 0x1e, 0xa9, - 0xf4, 0xba, 0x83, 0x20, 0xe4, 0x75, 0xf7, 0xc4, 0xf2, 0x0f, 0x9f, 0x1d, 0xc2, 0x7f, 0xc4, 0xd5, 0xff, 0x23, 0xa9, - 0x63, 0xd4, 0x5f, 0x26, 0x05, 0x46, 0x9d, 0x58, 0x25, 0x64, 0xc4, 0xf7, 0xaf, 0x3f, 0x99, 0xdc, 0xaf, 0xc1, 0xde, - 0xb5, 0xc9, 0x5c, 0xbc, 0x5c, 0xfb, 0x79, 0x18, 0xfa, 0xcc, 0x0d, 0xaa, 0xd5, 0x05, 0x78, 0xc8, 0xf7, 0x2f, 0xe9, - 0x41, 0x23, 0x71, 0x8f, 0x20, 0x4b, 0x45, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x6c, 0xdb, 0x55, 0xe2, 0xdd, 0xdd, 0x57, - 0x89, 0x6f, 0xf7, 0xba, 0x4a, 0xbc, 0xfb, 0xec, 0x57, 0x89, 0xb3, 0xea, 0x55, 0xe2, 0x2c, 0x14, 0x3e, 0x42, 0xc6, - 0xeb, 0x25, 0xff, 0xf9, 0x9e, 0x8c, 0x80, 0xde, 0x85, 0xbd, 0x96, 0x4d, 0xb9, 0x8e, 0x2e, 0x7e, 0xf3, 0xc5, 0x02, - 0x37, 0xe2, 0x3b, 0x34, 0x99, 0xcf, 0xaf, 0x16, 0x1c, 0xb3, 0xe3, 0x77, 0xa4, 0x62, 0x3f, 0x0c, 0xa6, 0x3f, 0x82, - 0x11, 0x18, 0x88, 0x03, 0x23, 0xe9, 0x85, 0x17, 0xff, 0x18, 0x2e, 0x96, 0x8b, 0x37, 0xd0, 0xd7, 0x7b, 0x2f, 0xf6, - 0x86, 0x3e, 0xcb, 0x82, 0x4b, 0x91, 0x89, 0x3f, 0x97, 0xad, 0x83, 0x57, 0x8d, 0xf8, 0xe9, 0xae, 0xc5, 0x4f, 0xf4, - 0xbb, 0xe1, 0xbf, 0xc9, 0x77, 0x40, 0xad, 0xbf, 0x88, 0x08, 0xb5, 0xb1, 0x34, 0xe8, 0xfb, 0x5f, 0x46, 0xce, 0x42, - 0xbd, 0x66, 0x96, 0xc2, 0xa6, 0x73, 0x6b, 0x3f, 0xac, 0xdc, 0xcf, 0xeb, 0xa5, 0x6e, 0x64, 0xb1, 0xb7, 0xab, 0xe2, - 0xfc, 0x79, 0xb8, 0x8c, 0xd9, 0x38, 0x5c, 0x05, 0xaa, 0x11, 0x70, 0x47, 0x04, 0x4a, 0x5f, 0x9c, 0xb5, 0xf9, 0x6f, - 0xc8, 0x73, 0x70, 0x8e, 0x8c, 0x32, 0x84, 0xe8, 0xb1, 0x16, 0x00, 0x43, 0x93, 0x4c, 0xdb, 0x4c, 0x9c, 0xa2, 0x9a, - 0xa5, 0x37, 0x7e, 0xa0, 0x69, 0x61, 0xef, 0x7e, 0x2d, 0x85, 0x39, 0x6a, 0x68, 0x71, 0xa9, 0x70, 0xac, 0x05, 0x42, - 0xb8, 0x28, 0x02, 0x60, 0xd6, 0x2c, 0x1c, 0x7f, 0x43, 0x91, 0xa3, 0xf2, 0xb7, 0x10, 0x8a, 0x28, 0x5d, 0xf2, 0xf5, - 0xe0, 0xe1, 0x20, 0xe9, 0xf1, 0x85, 0x04, 0xc6, 0xb7, 0x37, 0x2c, 0xf2, 0xdd, 0x5b, 0x4d, 0x4f, 0xc3, 0xe0, 0x7b, - 0x00, 0xc0, 0xcb, 0x70, 0x15, 0xc8, 0x15, 0x30, 0x4b, 0x6b, 0xcd, 0x5e, 0xaa, 0x0d, 0x5c, 0x0a, 0x8e, 0xbc, 0xd2, - 0x08, 0x3c, 0x6b, 0xe1, 0x4e, 0xd9, 0x7f, 0x19, 0xf4, 0xef, 0xdf, 0xf5, 0xd4, 0x78, 0x17, 0x66, 0x1f, 0xfa, 0x69, - 0xb1, 0xc7, 0x67, 0x1e, 0x3f, 0x7e, 0xb0, 0x7d, 0xda, 0xda, 0xc8, 0x67, 0x6e, 0x24, 0x46, 0x51, 0xd3, 0x5a, 0xdf, - 0x7a, 0x0a, 0x60, 0x14, 0x17, 0xe1, 0x72, 0x34, 0x43, 0x67, 0x9e, 0xcf, 0x37, 0xdf, 0x04, 0xfa, 0x64, 0xf1, 0xa5, - 0x7d, 0x95, 0x4d, 0xbd, 0x54, 0x94, 0x43, 0x01, 0xbf, 0xff, 0x0a, 0x32, 0x6f, 0xfc, 0x89, 0x60, 0xa8, 0xee, 0x9a, - 0x2c, 0x0e, 0xc8, 0xbd, 0x36, 0x6f, 0xd7, 0x03, 0x57, 0x7d, 0x8a, 0x69, 0x29, 0x94, 0x74, 0xf5, 0x48, 0x26, 0x2d, - 0x03, 0x4d, 0x8e, 0x1f, 0xbf, 0x2d, 0x34, 0xbe, 0xf8, 0x0a, 0xb3, 0xe8, 0x9a, 0xce, 0x9d, 0x29, 0x0d, 0xc6, 0xb1, - 0x55, 0x09, 0xc9, 0x70, 0x13, 0x4b, 0x86, 0xe8, 0xab, 0xfc, 0x6e, 0xee, 0x05, 0x06, 0xa6, 0x7f, 0xab, 0xbe, 0x71, - 0xd7, 0x90, 0x00, 0x09, 0x90, 0x5b, 0xf9, 0x15, 0x14, 0x1a, 0x72, 0x08, 0x01, 0xc8, 0xf1, 0xac, 0xd6, 0x42, 0x42, - 0x68, 0x03, 0x07, 0x5f, 0x28, 0x8a, 0xa2, 0x64, 0xd7, 0x08, 0x25, 0xbb, 0x47, 0x60, 0x39, 0x5e, 0x07, 0x40, 0x5b, - 0x92, 0x2e, 0xd6, 0x54, 0x02, 0x37, 0x03, 0x34, 0xaa, 0x12, 0x05, 0x3c, 0xc6, 0x7f, 0xcb, 0x16, 0x05, 0xe2, 0x42, - 0x0f, 0xf1, 0xd9, 0xdd, 0x08, 0x52, 0x01, 0x75, 0x14, 0xbc, 0xb0, 0xe3, 0x5b, 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, - 0x74, 0x59, 0x7d, 0x30, 0xf8, 0x40, 0xc2, 0x82, 0xa0, 0x75, 0x28, 0xe5, 0x76, 0x32, 0x58, 0x0d, 0x6e, 0xc4, 0x7b, - 0xd1, 0x3a, 0x99, 0xb3, 0x60, 0xa9, 0x62, 0x32, 0x68, 0x0c, 0xce, 0x0f, 0x75, 0x5e, 0x12, 0xb3, 0x05, 0xd8, 0xa6, - 0xbe, 0xe5, 0x8c, 0x68, 0x61, 0xcc, 0x51, 0xaa, 0x6b, 0x8c, 0xb8, 0x57, 0x7c, 0xcc, 0x71, 0x5b, 0x99, 0x42, 0xf0, - 0x25, 0x0d, 0x8b, 0xd8, 0x9c, 0xc7, 0xc1, 0x40, 0x4e, 0x81, 0x02, 0x1e, 0x72, 0x71, 0x91, 0x00, 0xbb, 0xe6, 0x96, - 0x17, 0x2d, 0xd3, 0xc8, 0xb8, 0x25, 0x41, 0x51, 0xa4, 0x57, 0xbb, 0xe1, 0xe3, 0x84, 0x88, 0xc4, 0x5b, 0xfb, 0x19, - 0x55, 0xfa, 0xd9, 0x32, 0xe9, 0x0f, 0xec, 0x96, 0x08, 0x09, 0x81, 0xea, 0x03, 0xbb, 0x05, 0x8b, 0xb1, 0x57, 0x20, - 0x4d, 0x51, 0x77, 0xa0, 0x6b, 0x03, 0x72, 0xfc, 0x8d, 0x20, 0x4a, 0xf5, 0x8e, 0x03, 0x64, 0xa7, 0x3b, 0xb0, 0x38, - 0x82, 0x38, 0x30, 0xe2, 0xae, 0x38, 0xc4, 0xdc, 0x8d, 0x51, 0xab, 0x85, 0xb1, 0x59, 0x73, 0x34, 0xf4, 0x27, 0x8e, - 0x6d, 0x1f, 0x54, 0xea, 0x83, 0x20, 0xbb, 0xae, 0xb6, 0x6e, 0x24, 0x3d, 0xc7, 0x36, 0xbd, 0x27, 0x56, 0xa3, 0x5b, - 0xa1, 0xd1, 0x52, 0x12, 0x89, 0x01, 0x8a, 0xbf, 0xfa, 0x8f, 0x36, 0x5a, 0xe5, 0x40, 0xea, 0x65, 0xb7, 0x40, 0x1c, - 0x5b, 0xca, 0xe5, 0x5f, 0x83, 0x2a, 0xe9, 0xa7, 0x14, 0x16, 0x94, 0xd0, 0x74, 0x00, 0x69, 0x90, 0x34, 0x38, 0x46, - 0x7f, 0x51, 0x9e, 0x2a, 0x1a, 0x1d, 0x1f, 0x5d, 0x1f, 0x74, 0x05, 0x46, 0x11, 0x7e, 0xf3, 0x72, 0x07, 0xa5, 0x2f, - 0xc6, 0x65, 0x0c, 0xc7, 0x13, 0xae, 0xb0, 0x5c, 0xa3, 0xb7, 0x93, 0x5b, 0xc0, 0xfe, 0xb7, 0x90, 0x4f, 0x6b, 0x08, - 0x81, 0x9f, 0xa0, 0x06, 0x24, 0x4d, 0xbb, 0xb3, 0x43, 0x88, 0xd3, 0x27, 0x77, 0x57, 0x24, 0x92, 0xfb, 0x77, 0x86, - 0x44, 0x07, 0x75, 0x68, 0x59, 0x7f, 0xf5, 0xe4, 0xee, 0x9e, 0x5d, 0xb2, 0x60, 0x5c, 0xec, 0xb0, 0x44, 0xbf, 0xf6, - 0xef, 0xae, 0x80, 0x51, 0x20, 0x9b, 0x60, 0x58, 0x83, 0x51, 0xd2, 0x30, 0xc0, 0xcd, 0x4f, 0xc7, 0xcd, 0xdb, 0x8b, - 0x8b, 0xc1, 0x06, 0x14, 0x0a, 0x3c, 0x6b, 0x26, 0x09, 0xc5, 0x21, 0x65, 0x15, 0x86, 0xd5, 0xd0, 0x04, 0x23, 0xba, - 0x75, 0x27, 0x26, 0xc2, 0x87, 0x21, 0x6f, 0xe3, 0xf1, 0x24, 0x14, 0xfb, 0x4a, 0xad, 0xbd, 0xbb, 0xa5, 0xd6, 0xc9, - 0x5d, 0x52, 0x6b, 0x72, 0x19, 0x27, 0x7b, 0xa0, 0xcc, 0x75, 0x5e, 0x30, 0xe7, 0x72, 0xf0, 0x81, 0x82, 0xa8, 0x1b, - 0x3d, 0xcc, 0x45, 0xab, 0x4a, 0x6f, 0xe4, 0x95, 0x80, 0xe2, 0x6f, 0xe9, 0x82, 0x22, 0x14, 0xea, 0xb2, 0x6c, 0xfc, - 0x2c, 0x97, 0x8d, 0xd3, 0xad, 0x26, 0x77, 0x16, 0x16, 0xdc, 0xbf, 0xe4, 0x88, 0x9f, 0xdd, 0x0e, 0x72, 0x87, 0xfc, - 0x7c, 0xa4, 0x92, 0x8b, 0x79, 0x7e, 0xd1, 0x90, 0x02, 0x17, 0x88, 0x5b, 0x46, 0x31, 0x7e, 0x41, 0xb1, 0x6a, 0xee, - 0x61, 0x9e, 0x97, 0x83, 0xd4, 0x1d, 0x87, 0x9c, 0x15, 0xcb, 0xdb, 0xa6, 0xe8, 0x62, 0x2c, 0xbf, 0x96, 0x36, 0x49, - 0xe6, 0x0b, 0x4c, 0x00, 0x16, 0x62, 0xfa, 0x92, 0x5e, 0x3b, 0xb3, 0x81, 0xc0, 0x41, 0xd6, 0x84, 0x2e, 0xb8, 0x5b, - 0x3a, 0x4f, 0x89, 0x12, 0x73, 0xd5, 0xb5, 0x83, 0xd4, 0x9d, 0x34, 0xc1, 0xb2, 0x3c, 0x02, 0x61, 0x7d, 0x25, 0x49, - 0x10, 0x3a, 0xb6, 0x62, 0x77, 0x6b, 0x18, 0x00, 0xa4, 0xff, 0xe5, 0x67, 0xce, 0x0a, 0x80, 0x24, 0x52, 0xb1, 0x65, - 0x9d, 0x3f, 0x1e, 0x62, 0x93, 0xcc, 0xdb, 0xb0, 0x6a, 0xf5, 0x9b, 0x24, 0xef, 0xd9, 0x70, 0x47, 0xe1, 0xa2, 0x38, - 0x9f, 0xd7, 0xe8, 0x88, 0x71, 0xf0, 0x5d, 0x16, 0x2d, 0x03, 0xcc, 0x7f, 0x67, 0x26, 0x91, 0x3b, 0xfa, 0xb0, 0x91, - 0xbe, 0xc7, 0x45, 0xa2, 0x20, 0x2e, 0x2e, 0x2a, 0x15, 0xba, 0x2e, 0xa6, 0x8b, 0x60, 0x1d, 0xab, 0x11, 0x4b, 0x82, - 0x9a, 0xce, 0x43, 0xbb, 0xe9, 0x3e, 0x9b, 0x1c, 0x96, 0xe4, 0xa7, 0x8d, 0x56, 0x51, 0xba, 0x9e, 0x8d, 0x63, 0x1e, - 0xfe, 0xc2, 0x43, 0x2a, 0xfc, 0xf1, 0x9f, 0x8e, 0xf9, 0x37, 0x4b, 0x6b, 0xf4, 0x29, 0x43, 0x80, 0xf6, 0x05, 0xc5, - 0xb4, 0xac, 0xa6, 0xa9, 0x94, 0x6c, 0x1b, 0xd6, 0xc4, 0xf3, 0x7d, 0xd3, 0x07, 0xdb, 0xc6, 0xcd, 0x27, 0x4d, 0x0f, - 0xfb, 0x59, 0x42, 0xa2, 0xa2, 0x4f, 0xe8, 0xa7, 0xb8, 0x53, 0x92, 0xd9, 0x72, 0x3e, 0xdc, 0xc8, 0x82, 0x72, 0x49, - 0x7e, 0x5e, 0x95, 0x99, 0xcb, 0x9f, 0x9d, 0x4c, 0x26, 0x45, 0xa9, 0xb1, 0xad, 0x1c, 0xa2, 0xe4, 0xf7, 0xa1, 0x6d, - 0xdb, 0x65, 0xf8, 0x6e, 0x3b, 0x28, 0x74, 0x30, 0x4c, 0x14, 0xc2, 0xb7, 0xef, 0xde, 0x53, 0x7f, 0xd0, 0x68, 0xa9, - 0xab, 0x6d, 0xe7, 0x91, 0xb6, 0xda, 0x7f, 0xc4, 0x50, 0x10, 0x35, 0xdc, 0x75, 0xfc, 0xab, 0x7b, 0x65, 0x47, 0x4f, - 0xe5, 0x03, 0x7c, 0xbf, 0xc6, 0x77, 0xec, 0xf5, 0x3d, 0x9a, 0x6e, 0xdb, 0xde, 0xa9, 0x95, 0x93, 0xdd, 0x82, 0xcd, - 0x52, 0x97, 0x2c, 0x95, 0xbc, 0x84, 0xcd, 0xe3, 0xce, 0x88, 0xa1, 0x82, 0xd4, 0x92, 0xa8, 0x2d, 0x5a, 0xf5, 0x98, - 0x53, 0xb0, 0xe3, 0x72, 0x04, 0x1e, 0xb6, 0x15, 0x54, 0x56, 0x55, 0x34, 0x6b, 0xe2, 0x23, 0x48, 0xc5, 0x36, 0x55, - 0x85, 0x13, 0x6e, 0xd3, 0x96, 0xfd, 0x97, 0x42, 0x3d, 0x05, 0xb8, 0xd3, 0x8d, 0xb0, 0x36, 0x21, 0xe5, 0x09, 0xfe, - 0x9d, 0x29, 0xe7, 0x9e, 0x2d, 0xd6, 0x45, 0xe3, 0xae, 0x36, 0xa8, 0x9b, 0x72, 0x52, 0x46, 0xa3, 0xae, 0x43, 0x7d, - 0x99, 0x09, 0xd0, 0x44, 0xb6, 0x6e, 0x01, 0x0b, 0x9a, 0x42, 0x5a, 0xde, 0x1a, 0xdd, 0x18, 0x5e, 0x67, 0x61, 0xe7, - 0xe5, 0xf2, 0x7d, 0xfc, 0x05, 0x09, 0x4a, 0x21, 0xea, 0xf9, 0x5f, 0x8c, 0xa7, 0x6d, 0x54, 0xee, 0x15, 0xb6, 0x2a, - 0x9a, 0xca, 0xe0, 0x1e, 0x10, 0x37, 0x52, 0x65, 0x19, 0xf9, 0x26, 0xe5, 0xac, 0xd5, 0xf4, 0x4d, 0x75, 0xde, 0xdb, - 0xbb, 0x77, 0x5a, 0xa0, 0xd7, 0xa8, 0x82, 0x6a, 0x2f, 0xd5, 0x5e, 0x59, 0x87, 0x2d, 0xc6, 0x09, 0x2b, 0x00, 0x8e, - 0x34, 0x0a, 0x1a, 0x0d, 0x29, 0x25, 0xdc, 0x47, 0x93, 0xce, 0xde, 0xca, 0xc8, 0x5a, 0xcc, 0x13, 0xbb, 0xab, 0xaf, - 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xc0, 0x8e, 0x63, 0x27, 0x7c, 0x36, 0x61, 0xc7, 0xc8, 0xe8, 0xca, 0xc1, 0x1d, 0x84, - 0xa7, 0xd4, 0xa4, 0x58, 0xe8, 0x74, 0x4a, 0x51, 0x97, 0xf0, 0x6d, 0xad, 0xf0, 0xfe, 0xa2, 0x20, 0x8d, 0xe7, 0x9e, - 0xa8, 0x0d, 0x7d, 0xaf, 0xda, 0x73, 0x2f, 0xd8, 0xbf, 0xae, 0xbb, 0xde, 0xbb, 0x2e, 0x30, 0x87, 0x7b, 0x57, 0x06, - 0xee, 0x92, 0xac, 0x94, 0x92, 0xde, 0xb7, 0x92, 0xf2, 0x40, 0x8e, 0xa2, 0xa4, 0x62, 0x2b, 0xba, 0xd1, 0xff, 0xb0, - 0xec, 0x0d, 0x4e, 0x4e, 0xd7, 0x73, 0x5f, 0xb9, 0x61, 0x11, 0xe4, 0xef, 0xee, 0xa9, 0x8e, 0x65, 0xab, 0x0a, 0xc6, - 0x04, 0xf2, 0x82, 0x69, 0x4f, 0xfd, 0xe9, 0xe2, 0xb5, 0xd9, 0x56, 0x4f, 0xc1, 0x1c, 0xe3, 0x66, 0x8a, 0x2c, 0xee, - 0x99, 0x7b, 0xcb, 0xa2, 0xeb, 0x86, 0xaa, 0x60, 0x9a, 0x6e, 0x62, 0x6e, 0xb1, 0x4c, 0x69, 0xa8, 0x7b, 0x64, 0x83, - 0x55, 0x6e, 0x3c, 0xb6, 0x7a, 0x1e, 0xae, 0x7b, 0x2a, 0x20, 0x56, 0xa7, 0xd1, 0x56, 0x9c, 0xc6, 0xa1, 0x75, 0xd4, - 0x56, 0xfb, 0x5f, 0x28, 0xca, 0xc9, 0x98, 0x4d, 0xe2, 0x3e, 0x8a, 0x63, 0x4e, 0x90, 0x1f, 0xa4, 0xdf, 0x8a, 0x62, - 0x8d, 0xfc, 0xd8, 0x74, 0x94, 0x0d, 0x7f, 0x54, 0x14, 0x40, 0x46, 0x1d, 0xe5, 0xe1, 0xa4, 0x31, 0x39, 0x9c, 0x3c, - 0xeb, 0xf2, 0xe2, 0xf4, 0x8b, 0x42, 0x75, 0x83, 0xfe, 0x6d, 0x48, 0xcd, 0xe2, 0x24, 0x0a, 0x3f, 0x30, 0xce, 0x4b, - 0x2a, 0x99, 0xa0, 0xa8, 0xdc, 0xb4, 0x51, 0xfd, 0x92, 0xd3, 0x1e, 0x8e, 0x26, 0x8d, 0xbc, 0x3a, 0x8e, 0xf1, 0x20, - 0x1b, 0xe4, 0xc9, 0x81, 0x18, 0xfa, 0x89, 0x0c, 0x26, 0xc7, 0xac, 0x03, 0x94, 0xa3, 0xf2, 0x39, 0x4e, 0xc5, 0xfc, - 0x4e, 0x20, 0xd9, 0x4a, 0xee, 0xd2, 0x10, 0x63, 0xb3, 0x9e, 0xfa, 0xbd, 0xd3, 0x68, 0x1b, 0x8e, 0x73, 0x64, 0x1d, - 0xb5, 0x47, 0xb6, 0x71, 0x68, 0x1d, 0x9a, 0x4d, 0xeb, 0xc8, 0x68, 0x9b, 0x6d, 0xa3, 0xfd, 0x4d, 0x7b, 0x64, 0x1e, - 0x5a, 0x87, 0x86, 0x6d, 0xb6, 0xa1, 0xd0, 0x6c, 0x9b, 0xed, 0x1b, 0xf3, 0xb0, 0x3d, 0xb2, 0xb1, 0xb4, 0x61, 0xb5, - 0x5a, 0xa6, 0x63, 0x5b, 0xad, 0x96, 0xd1, 0xb2, 0x8e, 0x8e, 0x4c, 0xa7, 0x69, 0x1d, 0x1d, 0x9d, 0xb5, 0xda, 0x56, - 0x13, 0xde, 0x35, 0x9b, 0xa3, 0xa6, 0xe5, 0x38, 0x26, 0xfc, 0x65, 0xb4, 0xad, 0x06, 0xfd, 0x70, 0x1c, 0xab, 0xe9, - 0x18, 0xb6, 0xdf, 0x6a, 0x58, 0x47, 0xcf, 0x0c, 0xfc, 0x1b, 0xab, 0x19, 0xf8, 0x17, 0x74, 0x63, 0x3c, 0xb3, 0x1a, - 0x47, 0xf4, 0x0b, 0x3b, 0xbc, 0x39, 0x6c, 0xff, 0x43, 0x3d, 0xd8, 0x3a, 0x07, 0x87, 0xe6, 0xd0, 0x6e, 0x59, 0xcd, - 0xa6, 0x71, 0xe8, 0x58, 0xed, 0xe6, 0xcc, 0x3c, 0x6c, 0x58, 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, - 0x6c, 0x5a, 0x0d, 0xc3, 0xb1, 0x0e, 0x9b, 0xf8, 0xa3, 0x69, 0x35, 0x6e, 0x8e, 0x9f, 0x59, 0x47, 0xad, 0xd9, 0x91, - 0x75, 0xf8, 0xfe, 0xb0, 0x6d, 0x35, 0x9a, 0xb3, 0xe6, 0x91, 0xd5, 0x38, 0xbe, 0x39, 0xb2, 0x0e, 0x67, 0x66, 0xe3, - 0x68, 0x67, 0x4b, 0xa7, 0x61, 0x01, 0x8c, 0xf0, 0x35, 0xbc, 0x30, 0xf8, 0x0b, 0xf8, 0x33, 0xc3, 0xb6, 0x7f, 0x60, - 0x37, 0x71, 0xb5, 0xe9, 0x33, 0xab, 0x7d, 0x3c, 0xa2, 0xea, 0x50, 0x60, 0x8a, 0x1a, 0xd0, 0xe4, 0xc6, 0xa4, 0xcf, - 0x62, 0x77, 0xa6, 0xe8, 0x48, 0xfc, 0xe1, 0x1f, 0xbb, 0x31, 0xe1, 0xc3, 0xf4, 0xdd, 0x3f, 0xb5, 0x9f, 0x6c, 0xc9, - 0x4f, 0x0e, 0xa6, 0xb4, 0xf5, 0xa7, 0xfd, 0x2f, 0x28, 0xb3, 0xf3, 0xc0, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x9f, 0x77, - 0x2b, 0x25, 0x9f, 0x2f, 0xf7, 0x51, 0x4a, 0xfe, 0xf3, 0xb3, 0x2b, 0x25, 0x7f, 0x29, 0xfb, 0xd6, 0xbc, 0x2e, 0x27, - 0xa0, 0xfc, 0x76, 0x53, 0x16, 0x39, 0x04, 0xae, 0x76, 0xf9, 0xc3, 0xf2, 0x0a, 0x82, 0xca, 0xbe, 0x0e, 0x7b, 0xcf, - 0x97, 0x05, 0x83, 0xcf, 0x10, 0x70, 0xec, 0xeb, 0x90, 0x70, 0xec, 0xfb, 0x65, 0x0f, 0xac, 0xcc, 0x38, 0x9b, 0xe3, - 0x8d, 0xcd, 0x99, 0xeb, 0x4f, 0x32, 0x16, 0x09, 0x4a, 0xba, 0x58, 0x0c, 0xce, 0x74, 0x40, 0x9e, 0xe1, 0x26, 0xb3, - 0x9c, 0x07, 0x31, 0x58, 0x04, 0x83, 0x25, 0xc7, 0x24, 0x4a, 0x4b, 0x8d, 0x2d, 0x11, 0x86, 0xf7, 0x9a, 0x7b, 0x59, - 0x6d, 0x7d, 0x8f, 0x06, 0xc0, 0xf5, 0xbd, 0x3b, 0xd5, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, - 0xbd, 0x2f, 0x9a, 0xe1, 0x96, 0x0c, 0xaf, 0xb7, 0x8f, 0x14, 0x46, 0x52, 0x6e, 0xef, 0x14, 0xcd, 0x78, 0xef, 0x9a, - 0x66, 0xcd, 0xe7, 0x0b, 0xcd, 0x77, 0xd8, 0x10, 0x67, 0x1d, 0x97, 0x41, 0xb5, 0x29, 0xf0, 0x69, 0xf5, 0x00, 0xc9, - 0x2f, 0xa8, 0xb9, 0xa1, 0x71, 0xce, 0xa9, 0xda, 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd0, 0xa7, 0x6c, 0x9c, 0xfc, - 0x64, 0x83, 0xf7, 0x0a, 0xef, 0x17, 0xe0, 0x44, 0x39, 0xc7, 0x33, 0x0c, 0x65, 0x38, 0x6f, 0xa4, 0x7e, 0x49, 0x1a, - 0x91, 0xce, 0x9c, 0x4d, 0x95, 0x17, 0xdd, 0xea, 0x96, 0xe0, 0xb0, 0xb9, 0xe0, 0x82, 0xf0, 0xf3, 0xe4, 0x04, 0x90, - 0x92, 0xa3, 0x06, 0xfa, 0x39, 0xec, 0xea, 0x4c, 0xd4, 0x7b, 0x08, 0x9b, 0x98, 0x67, 0x03, 0x50, 0xe4, 0x38, 0x67, - 0x9b, 0x89, 0x1f, 0xba, 0x49, 0x07, 0xd9, 0x34, 0x89, 0xe5, 0x6d, 0xa0, 0xc7, 0x42, 0x77, 0x87, 0x31, 0x9d, 0xdc, - 0x31, 0xef, 0x04, 0x3d, 0x1f, 0x76, 0xd9, 0xdf, 0x65, 0x0e, 0x67, 0x9b, 0x82, 0x39, 0x8a, 0xd3, 0x3a, 0x36, 0x9c, - 0x23, 0xc3, 0x3a, 0x6e, 0xe9, 0xa9, 0x38, 0x70, 0x72, 0x97, 0x05, 0x80, 0x80, 0x03, 0x44, 0x36, 0x4c, 0x2f, 0xf0, - 0x12, 0xcf, 0xf5, 0x53, 0xe0, 0x87, 0x8b, 0x97, 0x94, 0x7f, 0x2e, 0xe3, 0x04, 0xe6, 0x28, 0x98, 0x5e, 0x74, 0xfe, - 0x30, 0x87, 0x2c, 0x59, 0x31, 0x16, 0x6c, 0x31, 0x8c, 0x29, 0xfb, 0x92, 0xfc, 0x7e, 0x96, 0xf5, 0x29, 0x59, 0xad, - 0x0d, 0x93, 0x80, 0xef, 0x0f, 0xe1, 0xf8, 0x90, 0x0e, 0x8c, 0x6f, 0xb6, 0x21, 0xdc, 0x9f, 0xee, 0x46, 0xb8, 0x09, - 0xdb, 0x07, 0xe1, 0xfe, 0xf4, 0xd9, 0x11, 0xee, 0x37, 0x32, 0xc2, 0x2d, 0xf8, 0x0f, 0xe6, 0x1a, 0xa6, 0x73, 0x7c, - 0xd6, 0x20, 0x27, 0xd7, 0x53, 0xf5, 0x80, 0x18, 0x78, 0x55, 0xcf, 0x13, 0xd7, 0xfd, 0xad, 0x90, 0x22, 0x1c, 0x05, - 0xa0, 0x98, 0xef, 0x89, 0xd2, 0x11, 0x7b, 0xe0, 0xea, 0x96, 0xa5, 0x24, 0x66, 0x2b, 0xe5, 0x4d, 0x90, 0xf8, 0xd6, - 0x3b, 0x7e, 0x8f, 0x04, 0x85, 0xee, 0xeb, 0x30, 0x9a, 0xbb, 0x18, 0x77, 0x5c, 0xd5, 0xc1, 0x9d, 0x0e, 0x1e, 0x6c, - 0xf0, 0x0e, 0x1e, 0x85, 0xc1, 0x38, 0xd3, 0x4a, 0xb2, 0xde, 0x25, 0x71, 0xdc, 0xea, 0x2d, 0x73, 0x23, 0xd5, 0xa0, - 0xd7, 0xb0, 0xb8, 0x4f, 0x9a, 0xf6, 0x93, 0xc6, 0xe1, 0x93, 0x23, 0x1b, 0xfe, 0x77, 0x58, 0x33, 0x35, 0x78, 0xc5, - 0x79, 0x18, 0x40, 0x76, 0x63, 0x51, 0x73, 0x5b, 0xb5, 0x15, 0x63, 0x1f, 0xf2, 0x5a, 0xc7, 0xf5, 0x95, 0xc6, 0xee, - 0x6d, 0x5e, 0xa7, 0xb6, 0xc6, 0x2c, 0x5c, 0x4a, 0xc3, 0xaa, 0x19, 0x8d, 0x17, 0x2c, 0x41, 0xce, 0x2e, 0xd5, 0x90, - 0x5f, 0xf3, 0xe9, 0xe6, 0xf3, 0x62, 0xcd, 0xf4, 0x2a, 0x4f, 0xa1, 0x2e, 0x32, 0xe9, 0xdd, 0x09, 0x41, 0xae, 0xa2, - 0xb4, 0x31, 0x11, 0x05, 0xa6, 0x38, 0x82, 0x34, 0x14, 0x59, 0xe2, 0x6b, 0x97, 0x16, 0x28, 0x89, 0x96, 0xc1, 0x48, - 0xc3, 0x9f, 0xee, 0x30, 0xd6, 0xbc, 0x83, 0xc8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xdc, 0xbe, 0x9d, 0xe7, 0x9b, 0x8d, - 0xc5, 0xaa, 0xb8, 0x4f, 0x12, 0x23, 0x42, 0x3d, 0x36, 0x2d, 0xad, 0xd9, 0x73, 0x9f, 0x64, 0x0d, 0x9f, 0x24, 0x46, - 0xf0, 0x14, 0x74, 0x9f, 0x3d, 0xfb, 0xf1, 0x63, 0xaa, 0xf5, 0xa0, 0x27, 0xa6, 0x75, 0x3a, 0xca, 0xc3, 0x55, 0x2b, - 0xee, 0x34, 0xa4, 0x88, 0xd5, 0x9d, 0x91, 0x11, 0x3e, 0x7d, 0xda, 0xef, 0x39, 0x3a, 0xe6, 0x32, 0x4f, 0x45, 0x0c, - 0xd0, 0x00, 0x53, 0xd3, 0x9d, 0xed, 0x67, 0x68, 0xa4, 0xd7, 0xba, 0xd2, 0x2e, 0xe0, 0xce, 0x64, 0x0b, 0x77, 0x04, - 0x8e, 0xbd, 0x20, 0x6d, 0x2d, 0x19, 0x14, 0xb8, 0xc2, 0xe0, 0x47, 0xd4, 0xc9, 0x6e, 0x5d, 0x4d, 0xcb, 0xb6, 0x6c, - 0x35, 0x6b, 0x38, 0xf1, 0xa6, 0xbd, 0x4d, 0x98, 0xb8, 0x90, 0x00, 0xdc, 0x0f, 0xa7, 0xe0, 0x47, 0x97, 0x78, 0x89, - 0x0f, 0xd9, 0xa4, 0xc1, 0xa1, 0x6e, 0x4e, 0xf7, 0xf2, 0x94, 0x7b, 0x37, 0xb8, 0x11, 0x64, 0x2c, 0x8d, 0x6e, 0x85, - 0x2b, 0x2e, 0x46, 0x50, 0xfd, 0x1e, 0x88, 0xa1, 0xa6, 0x6a, 0x20, 0x1b, 0x60, 0x51, 0x6c, 0xca, 0xde, 0x42, 0x1d, - 0x05, 0xda, 0xe8, 0x2a, 0x9f, 0xc4, 0x24, 0x72, 0xe7, 0x90, 0x52, 0x6f, 0x93, 0x1a, 0x1c, 0xd3, 0xaa, 0x1c, 0xd5, - 0x2a, 0xce, 0xb3, 0x23, 0x43, 0x69, 0x38, 0x86, 0x62, 0x03, 0xba, 0x55, 0x53, 0x63, 0x93, 0x5e, 0x75, 0xef, 0x32, - 0x78, 0x20, 0xfc, 0xf2, 0x90, 0xe6, 0x41, 0xa6, 0x0e, 0x5c, 0x95, 0x94, 0x50, 0xe4, 0x7c, 0x4d, 0x4a, 0xa5, 0xe5, - 0x91, 0xd2, 0xf3, 0x82, 0xad, 0x13, 0x1d, 0xb3, 0x2d, 0xf3, 0x2a, 0x9e, 0xbe, 0x41, 0x87, 0x61, 0x2f, 0x50, 0xbc, - 0x8f, 0x1f, 0x35, 0x0f, 0x9c, 0x99, 0x7a, 0x12, 0x7c, 0xe0, 0x59, 0x2f, 0x00, 0xcc, 0xcb, 0xd5, 0xf4, 0x08, 0x2c, - 0xf0, 0x34, 0x84, 0x7f, 0xf3, 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0xbe, 0x1b, 0x4c, 0x01, 0xa5, 0xb9, 0xc1, 0xb4, - 0x62, 0x8e, 0x45, 0x3e, 0xcf, 0xa5, 0xd2, 0xbc, 0xab, 0xdc, 0x54, 0x2a, 0x7e, 0x7e, 0x7b, 0x41, 0xd9, 0xe4, 0x35, - 0x15, 0xa8, 0x1c, 0xba, 0xe8, 0xe6, 0x9a, 0xdc, 0xa7, 0xbd, 0x2f, 0x4f, 0xe6, 0x2c, 0x71, 0x49, 0x0d, 0x04, 0x97, - 0x5f, 0x60, 0x07, 0x14, 0x4e, 0x68, 0x78, 0x54, 0xc2, 0x1e, 0x25, 0xd8, 0x20, 0x3a, 0x61, 0x28, 0x9c, 0x4e, 0x99, - 0x68, 0xf1, 0xd9, 0x73, 0x0c, 0x72, 0x38, 0x18, 0xb9, 0x18, 0x64, 0xbf, 0x17, 0x84, 0x6a, 0xff, 0xcb, 0xcc, 0x37, - 0x73, 0xdb, 0x22, 0xf8, 0x5e, 0xf0, 0xe1, 0x32, 0x62, 0xfe, 0xbf, 0x7a, 0x5f, 0x02, 0xe1, 0xfe, 0xf2, 0x4a, 0xd5, - 0xbb, 0x89, 0x35, 0x8b, 0xd8, 0xa4, 0xf7, 0x25, 0xa6, 0xdd, 0x45, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xae, 0xe7, 0xbe, - 0x81, 0xd7, 0x7b, 0x1a, 0x8b, 0xda, 0x6c, 0xe4, 0xc1, 0x4e, 0x9b, 0x7b, 0x5d, 0xea, 0xfb, 0xfc, 0xb6, 0x0e, 0x37, - 0xc0, 0x4d, 0xe1, 0x8e, 0xed, 0x74, 0xf1, 0xfe, 0x3c, 0xf4, 0xdd, 0xd1, 0x87, 0x2e, 0xbd, 0x29, 0x3c, 0x98, 0x40, - 0xad, 0x47, 0xee, 0xa2, 0x83, 0xe4, 0x55, 0x2e, 0x04, 0xef, 0x69, 0x2a, 0xcd, 0x38, 0xbb, 0xda, 0xbd, 0x8c, 0x5b, - 0x79, 0x83, 0x5f, 0xc6, 0x4f, 0xad, 0x66, 0x5e, 0xc2, 0xc4, 0xa7, 0xf0, 0x21, 0x4d, 0xc5, 0x45, 0x9d, 0xae, 0xa8, - 0x78, 0xb1, 0xb6, 0x9a, 0x8a, 0xd3, 0xfe, 0xa6, 0x75, 0xe3, 0xd8, 0xb3, 0x86, 0x63, 0xb5, 0xdf, 0x3b, 0xed, 0x59, - 0xd3, 0x3a, 0xf6, 0xcd, 0xa6, 0x75, 0x0c, 0x7f, 0xde, 0x1f, 0x5b, 0xed, 0x99, 0xd9, 0xb0, 0x0e, 0xdf, 0x3b, 0x0d, - 0xdf, 0x6c, 0x5b, 0xc7, 0xf0, 0xe7, 0x8c, 0x5a, 0xc1, 0x05, 0x88, 0xee, 0x3b, 0x5f, 0x16, 0xb0, 0x80, 0xf4, 0x3b, - 0xd3, 0xc9, 0x1a, 0x05, 0xf2, 0x56, 0xa3, 0xd7, 0x05, 0x94, 0x41, 0xb9, 0xe6, 0xd0, 0x14, 0xa1, 0xab, 0x05, 0x3d, - 0x46, 0xd9, 0xe5, 0x84, 0x79, 0x9b, 0xf0, 0x43, 0x17, 0x29, 0xbe, 0x6a, 0x8f, 0x11, 0x6f, 0x53, 0x9f, 0xd6, 0x4a, - 0xa4, 0x9f, 0x27, 0x45, 0xf0, 0x4f, 0x0b, 0x0c, 0xca, 0x2a, 0xb2, 0x31, 0x4a, 0x58, 0x09, 0x7c, 0xcf, 0xad, 0x20, - 0x5c, 0xa1, 0x6d, 0xc5, 0x5d, 0x03, 0x47, 0x6f, 0x7e, 0x96, 0xa5, 0xe0, 0xfe, 0xac, 0x7d, 0x4b, 0x49, 0x2f, 0x3f, - 0xa9, 0x1f, 0x4c, 0x07, 0x98, 0x67, 0xf2, 0x83, 0x5c, 0x16, 0x63, 0x2f, 0xca, 0x86, 0x27, 0xa1, 0x68, 0xa7, 0x3e, - 0x1f, 0x98, 0x0e, 0xb9, 0x8a, 0xdf, 0x00, 0x97, 0x7c, 0xe3, 0xfa, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x41, 0x86, 0xf9, - 0x1f, 0x3f, 0xce, 0x07, 0x67, 0x96, 0xc6, 0x7d, 0xe2, 0xb4, 0x80, 0xec, 0xb6, 0x58, 0x73, 0xa7, 0x4d, 0x25, 0xdd, - 0x74, 0x76, 0xf9, 0x56, 0xe7, 0xe9, 0x0f, 0x84, 0xdd, 0x94, 0xb0, 0xd8, 0xd8, 0x6a, 0xd8, 0x59, 0xb1, 0xd7, 0x80, - 0xfc, 0x31, 0xa5, 0xab, 0x8e, 0xaa, 0x77, 0x03, 0x61, 0x7e, 0x10, 0xec, 0xc8, 0xfc, 0xc2, 0xef, 0x62, 0x2a, 0x80, - 0x66, 0xc7, 0x3c, 0xee, 0x70, 0x10, 0xff, 0xb3, 0x27, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x3a, 0xad, 0x05, 0xe7, - 0xbd, 0x8c, 0xae, 0x12, 0x41, 0x65, 0xf1, 0xa9, 0x0a, 0x45, 0x90, 0xc4, 0x1e, 0x70, 0xa3, 0x9a, 0x19, 0x8b, 0x66, - 0xd4, 0x22, 0x2f, 0x30, 0x3c, 0xcc, 0xb2, 0x25, 0x1c, 0x47, 0xf5, 0xc7, 0x8f, 0xb7, 0x12, 0x21, 0x32, 0xce, 0x89, - 0x59, 0x92, 0x65, 0xd6, 0x56, 0x65, 0xfc, 0xa6, 0xca, 0x28, 0x26, 0xeb, 0x17, 0xb1, 0x86, 0xb0, 0x71, 0xa5, 0xbd, - 0x87, 0x3f, 0x87, 0xcc, 0x4d, 0x2c, 0xae, 0x2c, 0xd5, 0x24, 0xe2, 0x6e, 0x38, 0xac, 0x09, 0xd6, 0xad, 0x3c, 0x76, - 0x73, 0x96, 0xa0, 0xf7, 0x6f, 0x4b, 0x1e, 0xd5, 0x01, 0xfa, 0xf8, 0x68, 0xe7, 0xc1, 0xb9, 0xde, 0x26, 0x2e, 0x85, - 0x24, 0x93, 0x49, 0x6e, 0x98, 0xb8, 0x22, 0x59, 0x34, 0xf0, 0xe5, 0xf5, 0x01, 0x59, 0xa4, 0xc8, 0x0f, 0xfd, 0xb7, - 0x17, 0x5f, 0x2b, 0x7c, 0xff, 0x93, 0xb5, 0x00, 0x5e, 0x64, 0x28, 0xe7, 0x5c, 0x8f, 0x72, 0xce, 0x29, 0x3c, 0xbd, - 0xa1, 0x8a, 0xd9, 0x82, 0x09, 0x82, 0x28, 0x80, 0x26, 0x1b, 0x8a, 0xf9, 0xd2, 0x4f, 0xbc, 0x85, 0x1b, 0x25, 0x07, - 0x98, 0x70, 0x0e, 0x90, 0x9c, 0xba, 0x2d, 0x1e, 0x04, 0x99, 0x61, 0x88, 0x90, 0xe1, 0x49, 0x20, 0xec, 0x30, 0x26, - 0x9e, 0x9f, 0x99, 0x61, 0x88, 0x0f, 0xb8, 0xa3, 0x11, 0x5b, 0x24, 0xbd, 0x42, 0x62, 0xbb, 0x70, 0x94, 0xb0, 0xc4, - 0x8c, 0x93, 0x88, 0xb9, 0x73, 0x35, 0x4b, 0x4d, 0x51, 0xed, 0x2f, 0x5e, 0x0e, 0xe7, 0x5e, 0x92, 0xc5, 0x76, 0xa7, - 0x09, 0x82, 0x41, 0x04, 0x0c, 0x11, 0x82, 0xcc, 0x10, 0x08, 0xcf, 0xc2, 0x69, 0x69, 0x47, 0xe5, 0x9c, 0xcb, 0x29, - 0x66, 0x0e, 0xa1, 0x9b, 0x0c, 0x48, 0x8b, 0x47, 0xa1, 0x7f, 0xcd, 0x63, 0x58, 0x64, 0x21, 0xe8, 0xd5, 0xfe, 0x09, - 0xbf, 0xde, 0x2a, 0x18, 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x1b, 0x65, 0x5b, 0x74, 0x8b, 0x03, 0x5e, 0x19, 0x48, 0x13, - 0xf5, 0x8c, 0xe9, 0xad, 0x68, 0x2c, 0x17, 0xc0, 0x08, 0x15, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x73, 0xa7, 0xc4, 0x51, - 0x21, 0xaf, 0xf4, 0xf1, 0xe3, 0xf9, 0xe0, 0xd7, 0x7f, 0x43, 0x0e, 0xae, 0x99, 0x23, 0x62, 0x4a, 0x5c, 0xca, 0xb5, - 0x38, 0xf7, 0x69, 0x0c, 0xd0, 0x58, 0x8a, 0x8d, 0x45, 0x08, 0x20, 0xb1, 0xb5, 0xd2, 0xc1, 0x95, 0x08, 0x0e, 0x0c, - 0xd9, 0xfb, 0x74, 0x11, 0xf9, 0x02, 0x93, 0x41, 0x0f, 0x44, 0x4c, 0x14, 0xe5, 0xe7, 0xf5, 0xf3, 0x63, 0x25, 0x8f, - 0xa9, 0x54, 0x67, 0xd1, 0x43, 0x7b, 0xa8, 0x7f, 0xe2, 0x2a, 0xc8, 0xb4, 0x20, 0xfb, 0x11, 0x77, 0x0e, 0x60, 0x9a, - 0xb3, 0x70, 0xce, 0x2c, 0x2f, 0x3c, 0x58, 0xb1, 0xa1, 0xe9, 0x2e, 0x3c, 0xb2, 0xcb, 0x41, 0xb9, 0x9b, 0x42, 0x9c, - 0x5f, 0x66, 0xee, 0x42, 0xfc, 0x75, 0x9a, 0x83, 0x32, 0x2c, 0x46, 0x83, 0x6e, 0x35, 0x72, 0x3d, 0xe0, 0x21, 0x05, - 0x80, 0x13, 0x70, 0x0c, 0xfb, 0x27, 0x07, 0x6e, 0xbf, 0x18, 0x8e, 0xde, 0x12, 0x69, 0xd5, 0x8a, 0x44, 0xe0, 0x94, - 0xa2, 0xca, 0x8b, 0x00, 0xf2, 0xf9, 0x83, 0x19, 0x4e, 0x26, 0x72, 0x08, 0x79, 0xab, 0x38, 0xbc, 0x0c, 0x68, 0xf9, - 0x96, 0x0e, 0x17, 0xf4, 0xa5, 0xea, 0x27, 0xb2, 0x9f, 0x6a, 0x07, 0x73, 0x47, 0xc0, 0x9c, 0xe1, 0xb8, 0x57, 0x42, - 0xd1, 0x67, 0x10, 0x7b, 0x48, 0x95, 0x38, 0x1e, 0x29, 0x27, 0x3e, 0xda, 0xc2, 0xb9, 0x3c, 0xe8, 0xf5, 0x08, 0xcd, - 0x95, 0xb1, 0x1d, 0x00, 0xb1, 0x26, 0xc5, 0x1c, 0x4c, 0x36, 0x81, 0x86, 0x26, 0xb9, 0xcb, 0x62, 0xa3, 0xf2, 0x74, - 0xaa, 0x63, 0x3c, 0x70, 0xc5, 0xf6, 0x2b, 0x6c, 0x50, 0xd8, 0x78, 0x7c, 0xdd, 0x01, 0xbf, 0x8b, 0x7e, 0x4a, 0x68, - 0x5e, 0xf9, 0x8a, 0x30, 0xba, 0xe9, 0xbb, 0xb7, 0xa1, 0x64, 0xc6, 0xc4, 0x23, 0x9a, 0x9c, 0x61, 0xe9, 0x85, 0xf0, - 0x24, 0xae, 0x1c, 0x34, 0x24, 0x61, 0x90, 0x8a, 0xab, 0x7a, 0xd8, 0x72, 0xfa, 0xeb, 0xb3, 0xbb, 0xce, 0x9a, 0x5c, - 0xb7, 0x38, 0x19, 0x44, 0x9e, 0x69, 0x7e, 0x0e, 0x0b, 0x2f, 0x11, 0x2d, 0xa4, 0x27, 0x07, 0x30, 0x3f, 0x88, 0xc2, - 0x52, 0x60, 0x9c, 0x3c, 0x1d, 0x42, 0xbd, 0xb8, 0x31, 0x99, 0x62, 0xbd, 0x19, 0x0b, 0x9e, 0x0f, 0x2f, 0x96, 0x52, - 0x82, 0x59, 0xa9, 0x4a, 0x95, 0x97, 0xb1, 0xeb, 0x99, 0xc0, 0xbb, 0xf3, 0xd6, 0xbd, 0x5f, 0x62, 0xd2, 0xba, 0xb4, - 0x9b, 0x30, 0x11, 0xe4, 0xe0, 0x2c, 0xd9, 0x12, 0x07, 0x61, 0x5b, 0x15, 0xe2, 0x67, 0x77, 0x54, 0xc8, 0xf7, 0xf1, - 0xae, 0x5a, 0x39, 0xe7, 0x94, 0x55, 0x9b, 0xba, 0x9a, 0xfa, 0x10, 0x77, 0x7c, 0xa5, 0x36, 0x96, 0x42, 0xbd, 0xb3, - 0xa4, 0x07, 0x55, 0x85, 0x2c, 0xde, 0x5d, 0x2c, 0xa8, 0xb2, 0xde, 0x3d, 0x39, 0xa0, 0x6b, 0x69, 0x9f, 0x76, 0x58, - 0xff, 0x04, 0x4c, 0xb9, 0x69, 0xd1, 0xdd, 0xc5, 0x82, 0x2f, 0x29, 0xfd, 0xa2, 0x37, 0x07, 0xb3, 0x64, 0xee, 0xf7, - 0xff, 0x17, 0x99, 0x05, 0x40, 0xf2, 0xa6, 0x72, 0x03, 0x00}; + 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0x34, 0x86, 0x2e, 0x8a, 0x44, 0x2b, 0x24, 0x28, 0x45, 0x7d, + 0x5b, 0x2f, 0x54, 0x1b, 0x08, 0x51, 0xb7, 0xc5, 0x34, 0x7d, 0x8e, 0xa0, 0xed, 0x20, 0x25, 0xc1, 0xbd, 0x65, 0x63, + 0x7e, 0x75, 0x2d, 0x9f, 0x39, 0x74, 0x67, 0x31, 0xfb, 0x52, 0x86, 0xc1, 0x20, 0xfa, 0x52, 0x16, 0x36, 0xb9, 0x67, + 0x95, 0xaa, 0x2c, 0xc7, 0xc6, 0xf6, 0x72, 0x8a, 0xa6, 0x2c, 0xe1, 0xbb, 0x75, 0xd8, 0x5c, 0xfb, 0x14, 0x67, 0x9f, + 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x54, 0xd7, 0x85, 0x06, 0x2d, 0xd2, 0xda, + 0x9c, 0x5c, 0x5e, 0x82, 0x2c, 0xb3, 0x57, 0x8c, 0xe4, 0xa7, 0xbd, 0x28, 0x9f, 0x7f, 0xbc, 0xfc, 0xf8, 0xf1, 0xdd, + 0x01, 0x2a, 0x7c, 0x7a, 0x07, 0x1f, 0x14, 0x7a, 0xc0, 0xc1, 0x83, 0x6d, 0xa1, 0x55, 0xec, 0xf5, 0x1f, 0xf6, 0xac, + 0x2a, 0x5a, 0x0a, 0x72, 0x03, 0x0a, 0xe8, 0x55, 0xd1, 0x1a, 0xd6, 0xc2, 0x69, 0xb1, 0xfd, 0xcc, 0x4a, 0xbb, 0x14, + 0xa0, 0xee, 0x44, 0xd5, 0x1c, 0x29, 0xbd, 0x3c, 0x44, 0x5a, 0x08, 0xab, 0x3b, 0xb6, 0x5a, 0xd5, 0xb5, 0xd5, 0x64, + 0x51, 0x65, 0xe2, 0xf2, 0x0c, 0x77, 0xff, 0x57, 0x6d, 0x39, 0x33, 0xc3, 0x8a, 0x5e, 0xb4, 0x77, 0x5b, 0x03, 0xaa, + 0x4c, 0x1b, 0xe5, 0xea, 0x3d, 0x04, 0x02, 0xb3, 0xb2, 0x9e, 0xfa, 0x1f, 0x1b, 0x8b, 0x11, 0x3f, 0x4d, 0x01, 0xb9, + 0x01, 0x0f, 0xc4, 0x4e, 0xe2, 0x91, 0x69, 0xdf, 0x0d, 0xca, 0x4d, 0x8e, 0x93, 0x56, 0xc2, 0x6c, 0x38, 0x89, 0x26, + 0xc4, 0xc6, 0x97, 0xd0, 0x34, 0xec, 0xc7, 0xd1, 0xf3, 0x37, 0x1f, 0x5f, 0x7d, 0xfc, 0xf7, 0xd9, 0xd3, 0xd3, 0x8f, + 0xcf, 0x7f, 0x7c, 0xfb, 0xfe, 0xd5, 0xf3, 0x0f, 0x78, 0x42, 0x68, 0xc0, 0xca, 0x70, 0xab, 0xad, 0xa2, 0x9b, 0x65, + 0x45, 0xa2, 0x26, 0xcd, 0xa6, 0x28, 0xc4, 0x28, 0xcc, 0x6c, 0x8b, 0xfc, 0xe5, 0xcd, 0xb3, 0xe7, 0x2f, 0x5e, 0xbd, + 0x79, 0xfe, 0xac, 0xfd, 0xf5, 0x70, 0x52, 0x93, 0xda, 0xcd, 0x9c, 0x8e, 0x90, 0xc2, 0xed, 0x78, 0x75, 0xd0, 0x27, + 0xd4, 0xca, 0xfb, 0xf4, 0x29, 0x83, 0x15, 0xc9, 0x94, 0x9c, 0x1e, 0x7f, 0x7b, 0xf8, 0xbf, 0x6a, 0xe3, 0xed, 0x76, + 0xc0, 0x43, 0x20, 0x19, 0x53, 0xb2, 0x7e, 0x18, 0xd5, 0x8c, 0xaa, 0x97, 0x11, 0x44, 0x7a, 0xd1, 0xa5, 0x81, 0x0d, + 0x74, 0x4a, 0x55, 0x48, 0x85, 0xb3, 0x24, 0xae, 0xf8, 0xa5, 0x2c, 0x36, 0x51, 0x36, 0x6a, 0xa5, 0xd0, 0xc6, 0x02, + 0x88, 0x42, 0x10, 0x2c, 0x37, 0x92, 0x48, 0x4f, 0x11, 0x00, 0x6f, 0x08, 0xdc, 0xa8, 0xce, 0x5d, 0xb4, 0x80, 0x76, + 0xc1, 0x64, 0xb1, 0xdb, 0x75, 0x0c, 0x5a, 0x27, 0xed, 0x8b, 0xe6, 0x99, 0x22, 0x8a, 0x0b, 0x60, 0xcc, 0xe1, 0x78, + 0x53, 0x67, 0x17, 0x33, 0xc7, 0xdd, 0xa9, 0x8e, 0xfa, 0x09, 0xd6, 0x88, 0xee, 0xb5, 0x09, 0x2c, 0xd3, 0x3c, 0x0f, + 0xff, 0xbf, 0xf6, 0x9e, 0x36, 0xb9, 0x6d, 0x23, 0xd9, 0xff, 0x39, 0x05, 0x04, 0x7b, 0x6d, 0xc0, 0x06, 0x20, 0x80, + 0x14, 0x25, 0x9a, 0x14, 0xa8, 0xc4, 0xb6, 0x9c, 0x64, 0x57, 0x89, 0x53, 0xb6, 0xe2, 0xfd, 0xd0, 0xaa, 0x44, 0x90, + 0x1c, 0x92, 0x58, 0x83, 0x00, 0x0b, 0x00, 0x45, 0x2a, 0x34, 0xf6, 0x2c, 0x7b, 0x84, 0x77, 0x86, 0x3d, 0xd9, 0xab, + 0xee, 0x9e, 0x01, 0x06, 0x20, 0x48, 0x51, 0xb1, 0x93, 0xdd, 0x57, 0xf5, 0x2a, 0xb1, 0x4d, 0x0c, 0x66, 0x06, 0x3d, + 0x5f, 0xdd, 0x3d, 0xfd, 0x69, 0x57, 0x30, 0xae, 0x88, 0xf1, 0x5b, 0x29, 0xa5, 0x6d, 0xc6, 0x63, 0x2b, 0xc2, 0x4a, + 0x41, 0x3a, 0x2e, 0x21, 0xba, 0xd5, 0x02, 0xb0, 0x90, 0x29, 0xad, 0xaf, 0x98, 0x87, 0xa0, 0x13, 0x89, 0x30, 0x79, + 0x60, 0x32, 0xb8, 0xa5, 0xd6, 0xb4, 0x13, 0x97, 0x02, 0x5e, 0x46, 0xe5, 0x49, 0x3d, 0x8d, 0xcb, 0xcf, 0xb0, 0x8d, + 0x2b, 0x55, 0x50, 0x64, 0x5b, 0xae, 0x04, 0xa2, 0x85, 0xe1, 0x19, 0x7d, 0xde, 0x4a, 0xa3, 0x8b, 0x68, 0x29, 0xc4, + 0xc3, 0xa7, 0x71, 0x4d, 0x21, 0x9e, 0x8d, 0x8e, 0x77, 0x3a, 0xa4, 0x1f, 0x4e, 0xb6, 0x85, 0x08, 0x64, 0xc5, 0x04, + 0xe7, 0xcc, 0x69, 0x9f, 0xae, 0x4c, 0x37, 0x8f, 0xd7, 0x62, 0xe3, 0x65, 0x7d, 0x3f, 0x4f, 0xfe, 0x5a, 0x62, 0x2c, + 0x32, 0x3e, 0xf5, 0x72, 0xac, 0xd1, 0x9a, 0x6a, 0x7c, 0x7f, 0xb8, 0x7e, 0x2d, 0x77, 0x62, 0xd1, 0x23, 0xa3, 0x5c, + 0x98, 0xf5, 0x55, 0xd8, 0x8a, 0x0d, 0xb5, 0x3a, 0xc0, 0x48, 0xbc, 0x24, 0x86, 0x80, 0xe1, 0x97, 0x11, 0xe3, 0x7f, + 0x1b, 0x57, 0x31, 0x3e, 0x5a, 0xd9, 0xe5, 0x08, 0xff, 0xa7, 0xb7, 0xef, 0x2f, 0x41, 0x7b, 0xe5, 0xa1, 0xba, 0x79, + 0xad, 0x72, 0x4b, 0x15, 0x13, 0xf4, 0x41, 0x6a, 0x47, 0xf5, 0xe6, 0x40, 0x8f, 0xf1, 0x5e, 0x70, 0xb8, 0x32, 0x97, + 0xcb, 0xa5, 0x09, 0x76, 0xab, 0xe6, 0x22, 0x0e, 0x88, 0x07, 0x1c, 0xa9, 0x99, 0x40, 0xe4, 0xac, 0x82, 0xc8, 0x21, + 0xe8, 0x2d, 0xcf, 0x9a, 0xf2, 0x7e, 0x1a, 0x2d, 0xbf, 0x09, 0x02, 0x59, 0x38, 0x23, 0x58, 0x35, 0x2e, 0xaf, 0x28, + 0x21, 0x06, 0x0d, 0x74, 0x4c, 0x96, 0x9f, 0xdc, 0x70, 0xab, 0x80, 0xd1, 0xcd, 0xe0, 0xee, 0x86, 0x6b, 0x1e, 0xf2, + 0xa8, 0xc3, 0xef, 0xfb, 0xa7, 0x23, 0xff, 0x56, 0x41, 0x7e, 0xd2, 0x55, 0xc1, 0x65, 0x2b, 0x60, 0x83, 0x45, 0x9a, + 0x46, 0xa1, 0x19, 0x47, 0x4b, 0xb5, 0x77, 0x4a, 0x0f, 0xa2, 0x82, 0x47, 0x8f, 0xaa, 0xf2, 0xf5, 0x30, 0xf0, 0x87, + 0x1f, 0x5d, 0xf5, 0xf1, 0xda, 0x77, 0x7b, 0x15, 0xae, 0xd1, 0xce, 0xd4, 0x1e, 0xc0, 0xaa, 0x7c, 0x13, 0x04, 0xa7, + 0x87, 0xd4, 0xa2, 0x77, 0x7a, 0x38, 0xf2, 0x6f, 0x7b, 0x52, 0x02, 0x18, 0xae, 0x1d, 0x75, 0x79, 0xa0, 0xcd, 0xdc, + 0x9e, 0x2c, 0xc1, 0xc8, 0x0d, 0x43, 0xa6, 0x15, 0x57, 0x5c, 0x88, 0x28, 0x43, 0xf0, 0x6a, 0x43, 0x14, 0x9a, 0x07, + 0x70, 0xa1, 0xfb, 0xf4, 0x49, 0xcb, 0xad, 0x4d, 0xa7, 0x52, 0x28, 0x36, 0x54, 0xe6, 0x61, 0x15, 0x03, 0xe3, 0xc9, + 0xe8, 0x9a, 0x08, 0x18, 0x17, 0xe8, 0xc6, 0x30, 0x33, 0x30, 0x8f, 0x8e, 0x37, 0x07, 0xbd, 0x22, 0xff, 0x29, 0xdd, + 0x7b, 0x87, 0x90, 0x3b, 0x5b, 0x42, 0xdc, 0xba, 0xa4, 0x59, 0xa1, 0x53, 0xc8, 0xa3, 0x01, 0x82, 0x4a, 0x04, 0xbf, + 0x43, 0xda, 0x0e, 0x2d, 0xd0, 0x21, 0x77, 0x5b, 0x1e, 0x82, 0xc7, 0xcb, 0x44, 0xb6, 0x34, 0x31, 0x2f, 0x67, 0xa5, + 0x15, 0xea, 0x54, 0xd7, 0x4b, 0xc4, 0x86, 0x3c, 0x48, 0xb6, 0x2d, 0x19, 0x68, 0xea, 0xb4, 0xd4, 0xa8, 0xd0, 0x59, + 0xf0, 0xdd, 0x93, 0xd4, 0x43, 0xcc, 0xd0, 0xae, 0x12, 0x23, 0xba, 0x2e, 0x68, 0x53, 0x42, 0x88, 0xb2, 0x13, 0x65, + 0x45, 0x98, 0x66, 0x5a, 0xf5, 0xde, 0xe3, 0x75, 0x88, 0xc4, 0x2c, 0x71, 0x7b, 0xe5, 0x7d, 0x90, 0x7a, 0x03, 0x93, + 0x36, 0xb3, 0xaa, 0x7c, 0x3d, 0x1a, 0x04, 0xf9, 0x62, 0xd3, 0x21, 0x98, 0x7a, 0xe1, 0x28, 0x60, 0x97, 0xde, 0xe0, + 0x3b, 0xac, 0xf3, 0x7a, 0x10, 0xbc, 0x82, 0x0a, 0x99, 0xda, 0x7b, 0xbc, 0x26, 0x72, 0x5d, 0x87, 0xb0, 0x33, 0xda, + 0x02, 0xd5, 0xef, 0xf0, 0xc4, 0x4a, 0x2c, 0xa6, 0xd6, 0x08, 0x2c, 0x91, 0x58, 0xc2, 0xa8, 0x65, 0xc8, 0x78, 0x62, + 0x1f, 0xd8, 0x9b, 0x0a, 0x3f, 0xb5, 0x00, 0x57, 0x24, 0x4e, 0xb0, 0xbc, 0x33, 0x65, 0x60, 0x89, 0x94, 0xbe, 0x8b, + 0x96, 0x02, 0x52, 0x3e, 0x01, 0x14, 0x88, 0xf2, 0xec, 0x7d, 0xff, 0x54, 0x56, 0xfe, 0xa0, 0x84, 0x9c, 0xfa, 0x85, + 0x5f, 0x99, 0xaa, 0x14, 0x69, 0x9e, 0xe6, 0x2b, 0xb5, 0x77, 0x7a, 0x28, 0xd7, 0xee, 0xf5, 0x3b, 0xe7, 0xd2, 0xe0, + 0xb0, 0x57, 0x71, 0x3b, 0xbe, 0x2a, 0x1e, 0xb2, 0x6b, 0x05, 0xee, 0xc2, 0x19, 0x94, 0xc0, 0x1c, 0x95, 0x9b, 0x6c, + 0x90, 0x1f, 0x48, 0x8c, 0x58, 0x10, 0x28, 0xda, 0x3d, 0x02, 0x3f, 0x46, 0x7a, 0x27, 0x5f, 0x42, 0xb2, 0xbf, 0x14, + 0xbd, 0xf5, 0xf9, 0xbf, 0xc5, 0x94, 0xa0, 0x3c, 0x9b, 0x85, 0x49, 0x14, 0xab, 0x30, 0xcc, 0x6a, 0x76, 0x24, 0x45, + 0xca, 0xca, 0x86, 0x03, 0xae, 0x25, 0xab, 0x30, 0x61, 0x87, 0xd5, 0xa6, 0xd2, 0xb8, 0xfb, 0x7a, 0xf1, 0x43, 0xe1, + 0x83, 0xa9, 0x20, 0xad, 0x1c, 0xc0, 0xed, 0x59, 0xa7, 0xae, 0x1e, 0xfb, 0xc6, 0x9f, 0x23, 0x63, 0xe0, 0x19, 0x37, + 0x9e, 0xf1, 0x43, 0x78, 0x9d, 0xd5, 0x2e, 0x5e, 0x9e, 0x31, 0xce, 0x60, 0x5d, 0x0d, 0xe2, 0x2c, 0x95, 0xef, 0x15, + 0xbe, 0xc5, 0x2d, 0x43, 0x2e, 0xbd, 0x78, 0xc2, 0x44, 0xa2, 0x36, 0xf1, 0x56, 0x48, 0x08, 0x74, 0x69, 0x5a, 0x20, + 0x08, 0xd9, 0x01, 0x37, 0xa0, 0xf3, 0xad, 0x61, 0x1a, 0x07, 0x7f, 0x62, 0x77, 0x70, 0x9d, 0x4c, 0xd2, 0x68, 0x0e, + 0x92, 0x29, 0x6f, 0xc2, 0x35, 0x0d, 0x06, 0x30, 0x35, 0xfb, 0x7c, 0xee, 0xd3, 0x27, 0x26, 0xe5, 0x0e, 0x4b, 0xa3, + 0xc9, 0x24, 0x60, 0x9a, 0x94, 0x63, 0x2c, 0xff, 0xcc, 0xd9, 0x81, 0x2d, 0xe2, 0x53, 0xeb, 0xd9, 0xb6, 0x83, 0x55, + 0x70, 0x80, 0x42, 0xa7, 0x0f, 0x88, 0x8b, 0x4c, 0xa8, 0x90, 0x09, 0xd7, 0xc4, 0xb9, 0x28, 0x0e, 0xae, 0x39, 0x8a, + 0x16, 0x83, 0x80, 0x99, 0x78, 0x1a, 0xe0, 0x93, 0xeb, 0xc1, 0x62, 0x30, 0x08, 0x28, 0x29, 0x18, 0x44, 0x59, 0x8b, + 0x12, 0x94, 0x7e, 0x66, 0x7a, 0x17, 0x39, 0xb5, 0xb4, 0x0a, 0x3e, 0x58, 0x46, 0xc2, 0x6d, 0x81, 0x3e, 0x90, 0x82, + 0xa4, 0x73, 0xf3, 0x4c, 0xbb, 0x2a, 0xdc, 0x52, 0x58, 0xa2, 0x76, 0x6b, 0x58, 0x3a, 0xf7, 0x4a, 0x7d, 0x8f, 0x33, + 0xac, 0x78, 0xe1, 0x48, 0x79, 0x45, 0x7b, 0x57, 0x35, 0x54, 0x32, 0xf0, 0xe2, 0x39, 0xe4, 0x54, 0x43, 0x7d, 0xed, + 0x7b, 0x93, 0x30, 0x4a, 0x52, 0x7f, 0xa8, 0x5e, 0x77, 0x5f, 0xfb, 0xda, 0xd5, 0x2c, 0xd5, 0xf4, 0x6b, 0xe3, 0x5b, + 0x39, 0xdb, 0x97, 0xc0, 0x94, 0x98, 0xec, 0x6b, 0x4b, 0x1d, 0xf9, 0xf4, 0xec, 0xaa, 0x27, 0x30, 0x32, 0xd6, 0xf9, + 0xd6, 0x85, 0x5a, 0x95, 0xbc, 0x61, 0x98, 0x10, 0x12, 0xf2, 0x86, 0x7d, 0xab, 0x77, 0x49, 0xd4, 0xf2, 0xcd, 0x62, + 0x8d, 0x4c, 0x43, 0x5a, 0x10, 0x5f, 0x0c, 0x75, 0x2f, 0xfc, 0x43, 0xe9, 0xf9, 0x40, 0xf6, 0x6d, 0x28, 0x91, 0xf1, + 0xfe, 0x37, 0x65, 0x0e, 0xe4, 0xf1, 0x3a, 0xcd, 0xc0, 0xb0, 0x30, 0x8c, 0x52, 0x05, 0xe2, 0xb7, 0xc1, 0x07, 0xfb, + 0x55, 0x5b, 0x68, 0xde, 0xab, 0xa6, 0x67, 0x1c, 0x0b, 0xbc, 0x44, 0x5a, 0x8a, 0xf2, 0x49, 0x08, 0x37, 0x01, 0xa1, + 0x48, 0x4b, 0xd1, 0x9a, 0xb8, 0x07, 0x1e, 0x2c, 0x5f, 0x89, 0x7f, 0x93, 0xf0, 0x7e, 0x99, 0x9e, 0x3f, 0x5e, 0x27, + 0x67, 0x82, 0xa8, 0x7f, 0x9f, 0xe0, 0x5a, 0x02, 0xbb, 0xc2, 0xa9, 0x7c, 0xa6, 0x2a, 0x67, 0x82, 0x12, 0x61, 0xdd, + 0x12, 0x7a, 0xd5, 0x04, 0xbb, 0x1b, 0x8b, 0xc8, 0xf8, 0x3c, 0xfd, 0xb8, 0x60, 0xc0, 0x2a, 0x47, 0x0f, 0x42, 0x32, + 0xe5, 0xbc, 0x55, 0x0a, 0x76, 0xd5, 0x48, 0x30, 0x00, 0x73, 0x71, 0x1e, 0xa1, 0x9f, 0xdd, 0x00, 0x23, 0x09, 0x71, + 0xca, 0xc4, 0x18, 0x8d, 0x48, 0x4e, 0x15, 0xe7, 0x87, 0xf3, 0x45, 0x8a, 0xf1, 0xe7, 0x01, 0x00, 0x96, 0xa9, 0x0a, + 0x5e, 0x12, 0x01, 0xd7, 0x17, 0x97, 0x9f, 0x4c, 0x55, 0xfc, 0xd1, 0x66, 0x19, 0x97, 0xc7, 0x00, 0x8e, 0xc3, 0x61, + 0xa0, 0xf6, 0x06, 0x1e, 0x63, 0x3e, 0x8c, 0xa1, 0x51, 0x24, 0x6f, 0xd1, 0x86, 0x68, 0xe5, 0x50, 0x83, 0x40, 0x86, + 0xd4, 0x4f, 0x57, 0x0b, 0x6a, 0x07, 0x0b, 0x31, 0xa9, 0x4b, 0xc3, 0xec, 0x83, 0x24, 0xf2, 0x0c, 0xe6, 0xce, 0x7d, + 0xbc, 0xf6, 0x72, 0x03, 0x3a, 0xf5, 0x52, 0x25, 0xeb, 0xb9, 0x3e, 0x4e, 0x43, 0x3f, 0xbb, 0x29, 0xdc, 0x59, 0x8b, + 0xf1, 0xc2, 0x96, 0xa4, 0x72, 0x05, 0xed, 0xd9, 0x5c, 0x6e, 0xb5, 0x36, 0x8f, 0xfd, 0x99, 0x17, 0xdf, 0x91, 0x91, + 0x9b, 0x21, 0x5b, 0xc2, 0xe9, 0xaa, 0x42, 0xf4, 0x80, 0x26, 0x80, 0x48, 0x83, 0xaa, 0x7c, 0x9d, 0x97, 0x31, 0x3e, + 0xda, 0xdc, 0xd2, 0x07, 0xbe, 0x75, 0xa3, 0x3e, 0x67, 0x16, 0x49, 0x19, 0xa9, 0x49, 0x57, 0x4b, 0xb6, 0x0c, 0x2f, + 0x29, 0x0f, 0x2f, 0x2c, 0x6f, 0x34, 0x1c, 0x0c, 0x51, 0x0a, 0x82, 0x1b, 0x47, 0x86, 0xa9, 0x2e, 0xeb, 0x57, 0x94, + 0xde, 0xfd, 0xae, 0xcb, 0xc1, 0x60, 0x39, 0x42, 0x58, 0x8e, 0x1a, 0x01, 0xac, 0x27, 0x56, 0x04, 0x78, 0x11, 0xe0, + 0x42, 0x62, 0xe4, 0x40, 0x28, 0x0b, 0xa6, 0x92, 0x6f, 0xa1, 0x18, 0x8e, 0x06, 0xc1, 0x4e, 0x47, 0x23, 0x76, 0xdd, + 0x08, 0x5b, 0xc5, 0xd9, 0xe9, 0x21, 0xd5, 0x26, 0xa2, 0x48, 0x95, 0x60, 0x1a, 0x62, 0x18, 0x61, 0x31, 0x0b, 0x90, + 0x06, 0xdc, 0x75, 0x8a, 0x8b, 0x8e, 0x35, 0x43, 0xe5, 0xb3, 0x73, 0x56, 0x66, 0x78, 0xb0, 0x95, 0xda, 0x3b, 0xc5, + 0xc4, 0x9e, 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xe9, 0x21, 0x3d, 0x2a, 0x95, 0x13, 0x51, 0x74, 0x22, 0xa4, 0x8e, 0x1d, + 0xde, 0xc1, 0x83, 0x8e, 0x4a, 0x92, 0xb2, 0x39, 0x94, 0x7a, 0x99, 0xaa, 0xcc, 0x38, 0x83, 0xc5, 0x63, 0xec, 0x41, + 0x00, 0x1e, 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xe6, 0xad, 0x70, 0xe4, 0xe2, 0x8d, 0xb7, 0xd2, 0x1c, 0xfe, 0xaa, 0x38, + 0x6b, 0x49, 0xf9, 0xac, 0x0d, 0xf9, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x29, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, + 0x54, 0x2c, 0xee, 0x68, 0xcb, 0xe2, 0x8e, 0x76, 0x2c, 0x6e, 0xc0, 0x17, 0x52, 0xc9, 0xa7, 0x2e, 0x46, 0x8f, 0xe9, + 0x7c, 0xf2, 0x38, 0x3f, 0xd2, 0xe1, 0xe7, 0x0c, 0xe7, 0xc9, 0x4c, 0x02, 0xb0, 0x18, 0xde, 0x32, 0x57, 0x75, 0xf3, + 0x22, 0x4d, 0xc4, 0xe6, 0xc0, 0xf3, 0x53, 0x37, 0x94, 0x24, 0x03, 0x5a, 0x50, 0x1d, 0x2f, 0xec, 0x52, 0x6c, 0x68, + 0x68, 0xd3, 0x2d, 0x23, 0x9d, 0xee, 0x18, 0xe9, 0xb0, 0x74, 0x74, 0xf9, 0xb0, 0xe9, 0x10, 0xca, 0x83, 0x82, 0x3d, + 0x08, 0x5e, 0x14, 0xb8, 0x65, 0xca, 0xfb, 0x70, 0x3b, 0x8e, 0x95, 0x76, 0xd4, 0xdc, 0x4b, 0x92, 0x65, 0x14, 0x83, + 0x19, 0x02, 0x74, 0xf3, 0xb0, 0x2d, 0x35, 0xf3, 0x43, 0x1e, 0xe1, 0x6c, 0xeb, 0x66, 0x2a, 0xde, 0xcb, 0x5b, 0xaa, + 0xd1, 0x6a, 0x51, 0x8d, 0xb9, 0x97, 0xa6, 0x2c, 0xc6, 0x49, 0xf7, 0x20, 0x15, 0xc6, 0x7f, 0xc9, 0x36, 0xab, 0xc1, + 0x21, 0x81, 0x84, 0xd5, 0x11, 0x43, 0xcf, 0x81, 0x05, 0x23, 0xbd, 0x63, 0xa8, 0xaf, 0xa5, 0x68, 0xa9, 0x71, 0x3e, + 0xf1, 0x3f, 0xe2, 0x71, 0xd5, 0x62, 0xc9, 0x9f, 0xd7, 0x39, 0xd6, 0xad, 0xb9, 0x37, 0x7a, 0x0f, 0xd6, 0x2e, 0x5a, + 0xc3, 0x00, 0xcf, 0x15, 0x39, 0x36, 0x6a, 0x4c, 0x3c, 0xe1, 0xb0, 0x40, 0x92, 0x88, 0x25, 0xb9, 0x5d, 0x30, 0x84, + 0x14, 0xf0, 0xcc, 0xf1, 0xf5, 0xba, 0x91, 0x1d, 0x4e, 0x7c, 0x7d, 0x03, 0x6b, 0x02, 0x6a, 0x0b, 0xdc, 0x5e, 0x2e, + 0x74, 0x0b, 0x0c, 0xe7, 0x58, 0x07, 0x75, 0xe8, 0x15, 0x24, 0x3d, 0xb7, 0xc5, 0x65, 0xba, 0x1f, 0x03, 0xd5, 0x02, + 0xe5, 0xe1, 0x93, 0x09, 0xfe, 0x72, 0xae, 0xb3, 0x27, 0x03, 0xfc, 0xd5, 0xb8, 0xce, 0x55, 0x55, 0x15, 0x29, 0x82, + 0x34, 0x66, 0xb5, 0x57, 0xda, 0x4f, 0x64, 0x94, 0xfd, 0x80, 0x6d, 0xc3, 0x17, 0xf8, 0xd1, 0xe3, 0x75, 0x02, 0x61, + 0x08, 0xe4, 0x31, 0x84, 0x56, 0xac, 0x67, 0xb5, 0xe5, 0x93, 0x2d, 0xe5, 0x03, 0xfd, 0x77, 0x26, 0xfc, 0xb8, 0x4b, + 0xa2, 0x82, 0xa6, 0x94, 0x65, 0x20, 0x37, 0x03, 0x3f, 0xf4, 0xe2, 0xbb, 0x1b, 0xba, 0x85, 0x68, 0x92, 0x90, 0xf7, + 0xa0, 0x10, 0x0e, 0xdc, 0x95, 0x6d, 0x40, 0x52, 0x49, 0x41, 0x75, 0xc7, 0x09, 0xbd, 0xfb, 0xa7, 0x58, 0xe2, 0xef, + 0x4a, 0xd7, 0x58, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3c, 0x5e, 0x6b, 0x6c, 0xb3, 0x9b, 0xca, 0x68, 0x2b, 0x0c, 0x24, + 0x2c, 0x0f, 0x5e, 0x89, 0x67, 0x23, 0xbf, 0x83, 0x46, 0x1e, 0x83, 0x68, 0x65, 0x3e, 0x5e, 0xa7, 0x67, 0xea, 0xcc, + 0x8b, 0x3f, 0xb2, 0x91, 0x39, 0xf4, 0xe3, 0x61, 0x00, 0xcc, 0xe3, 0x20, 0xf0, 0xc2, 0x8f, 0xfc, 0xd1, 0x8c, 0x16, + 0x29, 0x9a, 0x6d, 0xdd, 0x7b, 0x83, 0x16, 0x73, 0x42, 0x82, 0x44, 0xe4, 0x6a, 0x6b, 0x66, 0x41, 0x79, 0xdf, 0x17, + 0xd7, 0xfa, 0x82, 0x51, 0x2c, 0x6a, 0x19, 0xe0, 0x75, 0x00, 0x96, 0x64, 0x10, 0xc6, 0xc1, 0x50, 0x71, 0xbd, 0x54, + 0x43, 0x1e, 0x2a, 0xe9, 0xd1, 0xf2, 0x3c, 0xc4, 0x37, 0xd8, 0xc3, 0xaf, 0xff, 0x1c, 0x94, 0x3c, 0xe4, 0x73, 0x79, + 0x2f, 0x9f, 0x37, 0x42, 0x28, 0x35, 0xc9, 0x7d, 0xf0, 0x01, 0x1f, 0xe7, 0x0c, 0xe6, 0xf6, 0x4f, 0xcb, 0x8d, 0xbd, + 0x24, 0x59, 0xcc, 0xd8, 0x88, 0x94, 0x61, 0x67, 0x05, 0x50, 0xe5, 0x7b, 0x88, 0x0c, 0xd8, 0xdf, 0x17, 0x8d, 0x93, + 0xa3, 0x57, 0x60, 0xc6, 0x07, 0x0c, 0x65, 0x34, 0x1e, 0xab, 0x85, 0x28, 0xe0, 0x9e, 0x66, 0xce, 0xd1, 0xdf, 0x17, + 0x6f, 0xce, 0xed, 0x37, 0x79, 0xe3, 0x10, 0x18, 0x63, 0x61, 0x93, 0xc4, 0xf9, 0x62, 0x09, 0x5e, 0x31, 0xa2, 0xb1, + 0x17, 0x6e, 0x1f, 0xce, 0x55, 0x69, 0x8b, 0xcf, 0x19, 0x1b, 0x01, 0xc3, 0x6d, 0x6c, 0x94, 0xde, 0x04, 0xec, 0x96, + 0xe5, 0xf6, 0x4e, 0x9b, 0x1f, 0xab, 0x69, 0x81, 0x01, 0x59, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0xfa, 0x38, + 0x06, 0x3e, 0x72, 0xf9, 0x88, 0x55, 0x8e, 0x54, 0xdf, 0x50, 0x25, 0x00, 0xb6, 0x42, 0x76, 0xb6, 0xa5, 0xbc, 0x03, + 0x88, 0x7a, 0x0b, 0x6c, 0x86, 0xa3, 0x77, 0x20, 0x81, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0xb6, + 0xcd, 0x58, 0x9d, 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x01, 0x40, 0x5f, 0x18, 0x21, 0xae, 0xaa, 0x5d, 0x1b, 0xa5, + 0x3c, 0xf2, 0x01, 0xa6, 0x77, 0x0f, 0x59, 0x92, 0x6c, 0x9d, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, + 0xa2, 0xdc, 0xb0, 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x99, 0x71, 0x23, 0xce, 0x78, 0x32, + 0x50, 0xb9, 0x81, 0xdd, 0xb6, 0xf7, 0x4b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0xb5, 0xa0, 0x69, 0x25, 0xd4, 0xbb, 0x21, + 0x55, 0xc2, 0x0e, 0x04, 0x4c, 0x15, 0xfc, 0xca, 0xc6, 0x63, 0x36, 0x4c, 0x13, 0x5d, 0xc8, 0x98, 0xf2, 0x90, 0xea, + 0xa0, 0xb4, 0x3b, 0x70, 0xd5, 0x1f, 0x21, 0xb0, 0x8c, 0x88, 0x3c, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xfa, 0x69, 0xa2, + 0x1e, 0xcb, 0x53, 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x9a, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0xa9, + 0xe7, 0x6e, 0x54, 0xb4, 0xeb, 0xf8, 0xae, 0x9d, 0x37, 0x2d, 0xc7, 0xce, 0x54, 0x03, 0x1c, 0x9a, 0x3f, 0x56, 0xb6, + 0x31, 0x11, 0x28, 0x57, 0xbd, 0x78, 0xfb, 0xea, 0x4f, 0xe7, 0xaf, 0xf7, 0xc5, 0x08, 0xd8, 0x65, 0x13, 0xba, 0x5c, + 0x84, 0x3b, 0x3a, 0xfd, 0xf9, 0xc7, 0x87, 0x75, 0xdb, 0x70, 0x5e, 0x38, 0xaa, 0x41, 0x36, 0xe8, 0x12, 0x5e, 0x1c, + 0x46, 0xb7, 0x2c, 0xfe, 0xec, 0x69, 0x90, 0x3b, 0xaf, 0x07, 0xf7, 0xed, 0x4f, 0xe7, 0x3f, 0xee, 0x0d, 0xea, 0xb1, + 0x63, 0x03, 0x6e, 0x4f, 0xa3, 0xf9, 0x03, 0x46, 0xd7, 0x54, 0x0d, 0x75, 0x18, 0x44, 0x09, 0xdb, 0x02, 0xc1, 0xab, + 0x8b, 0xb7, 0xef, 0x71, 0xba, 0x0a, 0x16, 0x84, 0xba, 0xfa, 0xbc, 0xc1, 0xff, 0xf4, 0xee, 0xfc, 0xfd, 0x7b, 0xd5, + 0xc0, 0x94, 0xdc, 0x89, 0xdc, 0x3b, 0xdf, 0xc4, 0xf7, 0x50, 0x9c, 0xda, 0xbd, 0x4e, 0x54, 0x8d, 0x2e, 0xd2, 0xe5, + 0xd1, 0x50, 0xd9, 0xc6, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x7b, 0x8d, 0xab, 0x06, 0x1f, 0xed, 0x26, + 0xa9, 0xa5, 0x92, 0x99, 0x1f, 0xde, 0xd4, 0x94, 0x7a, 0xab, 0x9a, 0x52, 0xb8, 0x3e, 0x6e, 0xe0, 0xc7, 0x45, 0x34, + 0x93, 0xd8, 0x11, 0xb6, 0xba, 0x7f, 0xba, 0xa4, 0x3b, 0xdc, 0x67, 0x00, 0xcd, 0x53, 0xaa, 0x54, 0xa1, 0xae, 0x29, + 0xe6, 0x17, 0xaf, 0x7c, 0x6e, 0x87, 0x01, 0x58, 0xde, 0x33, 0x59, 0x0d, 0x59, 0x66, 0x55, 0xb9, 0xdf, 0x8c, 0x5b, + 0xb9, 0x15, 0x50, 0x33, 0x52, 0xdd, 0x70, 0x9a, 0x32, 0xf7, 0x46, 0x60, 0xce, 0x6e, 0x0e, 0xa2, 0x34, 0x8d, 0x66, + 0x1d, 0xc7, 0x9e, 0xaf, 0x54, 0xa5, 0x2b, 0x84, 0x1d, 0xdc, 0xda, 0xbe, 0xf3, 0xef, 0x7f, 0x55, 0xd0, 0x3c, 0x95, + 0xdf, 0xa4, 0x6c, 0x36, 0x67, 0xb1, 0x97, 0x2e, 0x62, 0x96, 0x29, 0xff, 0xfe, 0x9f, 0x57, 0x95, 0x8b, 0x7d, 0x57, + 0x6e, 0x43, 0x2c, 0xbd, 0xdc, 0xe4, 0x26, 0x88, 0x96, 0x07, 0x85, 0x5f, 0xdd, 0x3d, 0x95, 0xa7, 0xfe, 0x64, 0x9a, + 0xd7, 0x3e, 0x4b, 0x77, 0x8c, 0x4d, 0x40, 0x4f, 0xfa, 0x00, 0xe5, 0x22, 0x5a, 0x76, 0xfe, 0xfd, 0xaf, 0x5c, 0x60, + 0x73, 0xef, 0xae, 0xab, 0x07, 0xb4, 0xbc, 0xa2, 0xf5, 0x75, 0x36, 0x96, 0x18, 0xde, 0x6f, 0x2c, 0xf0, 0x46, 0x21, + 0xed, 0xca, 0x4d, 0xdd, 0xdc, 0x8e, 0x31, 0x7d, 0xe7, 0x4f, 0xa6, 0x9f, 0x3b, 0x28, 0x98, 0xd0, 0x7b, 0x47, 0x05, + 0x95, 0xbe, 0xc0, 0xb0, 0xfa, 0x9d, 0xfd, 0x17, 0xec, 0x33, 0xc7, 0x75, 0xdf, 0x90, 0xbe, 0xc4, 0x68, 0xb8, 0xe4, + 0xf6, 0x7d, 0xbf, 0x9f, 0xa7, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0xd9, 0x46, 0x09, 0x67, 0x2f, 0x3a, 0xb6, 0x4e, + 0x21, 0x7b, 0xf6, 0x98, 0x10, 0xb4, 0x71, 0xaf, 0x99, 0x8e, 0xed, 0xf8, 0x9a, 0x5c, 0xd5, 0x36, 0xbe, 0xbd, 0x81, + 0xac, 0xa1, 0x14, 0xd3, 0x99, 0xe6, 0x5a, 0x43, 0xa3, 0x1e, 0x9c, 0x65, 0xec, 0xcd, 0x49, 0x49, 0xa0, 0xa0, 0xc6, + 0x04, 0x84, 0x2e, 0x95, 0x5b, 0xf4, 0xad, 0x17, 0xdc, 0xee, 0x77, 0xa1, 0xda, 0x4e, 0xc1, 0x90, 0x34, 0xff, 0xe7, + 0x88, 0x37, 0xd2, 0xe5, 0x07, 0xd3, 0xee, 0xa5, 0x97, 0xb2, 0xf8, 0x66, 0x0a, 0x3e, 0xbd, 0x42, 0x7a, 0x00, 0xd1, + 0x72, 0x77, 0x21, 0xe5, 0x12, 0x5b, 0x5a, 0x83, 0x46, 0x0b, 0x0c, 0xf7, 0xeb, 0x70, 0xf7, 0x17, 0xc2, 0xdc, 0x9d, + 0x73, 0xf0, 0xba, 0xfc, 0xcd, 0xb0, 0xf7, 0x2e, 0xca, 0xf4, 0xff, 0xd8, 0xfb, 0xbf, 0x11, 0x7b, 0xef, 0xfc, 0xce, + 0xaf, 0x59, 0xd8, 0xff, 0x03, 0x58, 0xbe, 0xc3, 0xdc, 0x73, 0x8e, 0xe9, 0x35, 0xcd, 0x73, 0x85, 0x72, 0x55, 0xc6, + 0xab, 0x1b, 0x0a, 0x56, 0x1e, 0x52, 0x8d, 0x5b, 0x0e, 0x7a, 0x88, 0xec, 0x77, 0x1c, 0xe5, 0xdf, 0x1e, 0xd1, 0x27, + 0x94, 0x87, 0x4a, 0xc2, 0xf4, 0x9d, 0x73, 0x23, 0x29, 0x8d, 0xc4, 0x5b, 0x7a, 0x77, 0xfb, 0xe0, 0x1d, 0x01, 0xec, + 0x37, 0x4b, 0xef, 0xae, 0x0e, 0xd8, 0xad, 0xe8, 0xb5, 0xfa, 0xb1, 0x33, 0xf0, 0xe5, 0xe9, 0xa0, 0x23, 0x8f, 0xd1, + 0x4f, 0x58, 0x7a, 0x06, 0x85, 0xee, 0xe3, 0xf5, 0x41, 0xb5, 0x62, 0xd6, 0x07, 0x2f, 0x67, 0x09, 0xf0, 0xa8, 0x04, + 0xb8, 0x9f, 0xdc, 0x44, 0xe1, 0x43, 0x20, 0xff, 0x09, 0x84, 0x3f, 0xbf, 0x1a, 0x74, 0xfc, 0xdc, 0x06, 0xec, 0x58, + 0x5a, 0x05, 0x1e, 0x0b, 0xab, 0xd0, 0x77, 0xeb, 0x65, 0xf5, 0x15, 0x42, 0x8b, 0x34, 0x96, 0x11, 0xa1, 0x55, 0x40, + 0xaf, 0xa2, 0x80, 0x8e, 0xab, 0x42, 0x72, 0xfd, 0x70, 0x1c, 0x7b, 0x31, 0x1b, 0x6d, 0xbf, 0x02, 0x94, 0x2c, 0x95, + 0xef, 0xac, 0x64, 0x31, 0x9f, 0x47, 0x71, 0x9a, 0xdc, 0x60, 0x34, 0x96, 0x99, 0x0f, 0x17, 0x0a, 0xc8, 0x1b, 0x96, + 0xc7, 0xe6, 0x3d, 0xaf, 0x93, 0x6f, 0x1b, 0xcc, 0x2d, 0xa7, 0xd4, 0xe0, 0x3e, 0x36, 0x06, 0xf7, 0xd2, 0x99, 0x4a, + 0xfa, 0x8b, 0xa9, 0x95, 0xc6, 0xfe, 0x4c, 0xd3, 0x0d, 0xc7, 0xd6, 0x75, 0x21, 0x5f, 0x99, 0xba, 0xbd, 0x03, 0x8a, + 0x29, 0x3c, 0xd5, 0x21, 0x36, 0x21, 0xfa, 0xad, 0x80, 0xad, 0xdc, 0xcb, 0xc5, 0x78, 0xcc, 0x62, 0x4d, 0x04, 0x5f, + 0x84, 0xe8, 0xaf, 0x64, 0x0c, 0x08, 0xde, 0x8c, 0x1f, 0x7c, 0xb6, 0x84, 0x2c, 0x4f, 0x45, 0xf0, 0x74, 0xf0, 0xe8, + 0x24, 0x13, 0x72, 0xc8, 0x20, 0x97, 0x36, 0x1b, 0xda, 0xe8, 0xd9, 0x91, 0x31, 0x85, 0x90, 0x4b, 0x85, 0x13, 0x3c, + 0x46, 0xf3, 0xf3, 0xc3, 0xb4, 0x8d, 0x5f, 0x80, 0x0e, 0xe0, 0xf0, 0x06, 0x6e, 0xee, 0xfd, 0xa4, 0x0c, 0xf3, 0x0e, + 0xa7, 0x6e, 0x2f, 0x78, 0xee, 0x92, 0x9e, 0x07, 0xed, 0xf6, 0x5e, 0x4d, 0xbd, 0xf8, 0x55, 0x34, 0x62, 0x08, 0xe8, + 0x20, 0x8d, 0xc0, 0x27, 0x53, 0x0a, 0xb6, 0x83, 0xb1, 0x76, 0xcc, 0x52, 0xfc, 0x9d, 0x43, 0x28, 0xba, 0x91, 0x8b, + 0xdc, 0xe7, 0x8f, 0x0f, 0x0d, 0x38, 0x69, 0xf5, 0x2b, 0x2d, 0x16, 0x8d, 0x2f, 0x75, 0xed, 0x2b, 0x79, 0xb7, 0xbe, + 0xf2, 0xe2, 0xd8, 0x67, 0xb1, 0xa2, 0x7d, 0xf7, 0x8b, 0x2e, 0x6f, 0xda, 0x92, 0x42, 0x87, 0x6b, 0x99, 0x15, 0x8c, + 0x39, 0x37, 0xf6, 0x59, 0x30, 0x72, 0xd5, 0x21, 0x35, 0xcc, 0x95, 0x37, 0xcd, 0xb6, 0x6d, 0xdb, 0x5c, 0x61, 0xea, + 0xd0, 0x4f, 0x50, 0x98, 0xc2, 0x4f, 0x78, 0x28, 0x89, 0x17, 0xdb, 0xc4, 0x45, 0x6c, 0x90, 0xb3, 0x5a, 0x08, 0xdf, + 0x51, 0xd4, 0x9e, 0x87, 0xc0, 0xc6, 0xa3, 0xfb, 0x08, 0xd0, 0x1c, 0x01, 0x56, 0x01, 0x53, 0x05, 0xa0, 0xd6, 0x43, + 0x00, 0xba, 0xf4, 0x67, 0x7e, 0x38, 0x49, 0xb6, 0x42, 0x84, 0x6a, 0xd3, 0x12, 0x3c, 0x29, 0xb5, 0x50, 0x15, 0x5c, + 0xc3, 0x69, 0x14, 0x40, 0xb6, 0x21, 0x95, 0x59, 0x13, 0x4b, 0x79, 0x61, 0xdb, 0xb6, 0x61, 0x1e, 0x41, 0x5e, 0xbf, + 0xd6, 0xb1, 0x6d, 0x98, 0xf0, 0x97, 0x65, 0x59, 0x35, 0xf2, 0xd8, 0xee, 0xcc, 0x0f, 0x4d, 0x7a, 0x6c, 0xd8, 0xfb, + 0xc1, 0x7b, 0xaf, 0x55, 0x6f, 0xc2, 0x75, 0x63, 0x83, 0xdc, 0x41, 0x54, 0x1b, 0xb8, 0x49, 0xd9, 0xd6, 0xcd, 0xa2, + 0xb0, 0x4a, 0x3c, 0xea, 0x45, 0x85, 0x18, 0x0d, 0xca, 0x6f, 0x91, 0x2d, 0x8d, 0xab, 0xd9, 0x2a, 0xd4, 0xef, 0x39, + 0x58, 0x1d, 0xe5, 0x55, 0xb4, 0x08, 0x46, 0x68, 0x0e, 0x05, 0xb6, 0xcb, 0x4a, 0x61, 0x15, 0x5a, 0x49, 0x29, 0x05, + 0x19, 0xc3, 0x31, 0x9d, 0xda, 0x7b, 0x24, 0x4e, 0x51, 0xac, 0x3d, 0xc5, 0x29, 0xbe, 0xaa, 0xdb, 0x82, 0xd7, 0x4f, + 0x21, 0x6a, 0xd0, 0x1e, 0x0d, 0xf8, 0xbe, 0x80, 0xfa, 0xc1, 0x3e, 0xf5, 0xc5, 0xba, 0x5d, 0x3f, 0xa5, 0xd0, 0xb2, + 0xde, 0xa7, 0x4f, 0x07, 0xc3, 0x4f, 0x9f, 0x0e, 0x36, 0xf2, 0x71, 0x6c, 0x1f, 0x21, 0x6d, 0x0c, 0xc6, 0x03, 0x89, + 0x40, 0x74, 0x20, 0x02, 0xfa, 0x7b, 0x28, 0xef, 0x78, 0x3c, 0x26, 0x15, 0x3d, 0x0d, 0x0d, 0xfe, 0x41, 0x7a, 0x0c, + 0xb2, 0xca, 0xa4, 0x4c, 0x5d, 0x8f, 0xc4, 0x3c, 0x9f, 0x3e, 0xf1, 0xe3, 0x66, 0x8c, 0xdc, 0x61, 0x5e, 0xe4, 0xa8, + 0xc6, 0xc2, 0x0d, 0xf2, 0x47, 0x15, 0x41, 0x5e, 0x70, 0x8c, 0x59, 0x40, 0xbc, 0xf4, 0xe2, 0x50, 0x06, 0xf8, 0xc7, + 0x48, 0xe1, 0x9f, 0x55, 0x78, 0xdc, 0xd3, 0x51, 0x75, 0x35, 0xc6, 0x2e, 0xd3, 0x16, 0x84, 0x03, 0x85, 0xa5, 0x9b, + 0xd4, 0xc1, 0xa5, 0xc0, 0xf6, 0x98, 0xfc, 0x54, 0x0c, 0x10, 0xbd, 0xa8, 0xf1, 0xe4, 0x8e, 0xc4, 0xb0, 0xde, 0x79, + 0xcb, 0xce, 0x42, 0x3c, 0x9c, 0x93, 0x49, 0x7c, 0x67, 0x9c, 0x7b, 0x27, 0xcf, 0xc9, 0xb7, 0x70, 0xe2, 0x7e, 0x1b, + 0x6b, 0x73, 0x23, 0x35, 0x54, 0x41, 0x46, 0x54, 0xdd, 0x98, 0xd5, 0x85, 0x51, 0xed, 0xce, 0x78, 0x50, 0x19, 0x4d, + 0x6c, 0x85, 0x9b, 0x31, 0xfa, 0x2a, 0x84, 0xc3, 0x3b, 0x0c, 0x93, 0x5c, 0xbc, 0x27, 0x50, 0x6e, 0x78, 0x8e, 0xbd, + 0x91, 0xfc, 0x0a, 0x16, 0x5c, 0x35, 0xc6, 0xba, 0x41, 0x3e, 0x00, 0x93, 0x2f, 0x69, 0xee, 0x4f, 0x91, 0x93, 0x67, + 0x52, 0x50, 0x57, 0xe1, 0x00, 0x70, 0x53, 0x71, 0x00, 0xa8, 0x99, 0x4f, 0x25, 0x66, 0xc9, 0x3c, 0x0a, 0xe1, 0xae, + 0x78, 0x53, 0x78, 0x75, 0xdd, 0x6c, 0x7a, 0x75, 0xd5, 0x34, 0xc5, 0x37, 0xd4, 0x0e, 0x54, 0xd2, 0x97, 0x7f, 0xa9, + 0x58, 0xe8, 0x0b, 0x52, 0x8f, 0xb9, 0xc8, 0xcf, 0xb7, 0xf9, 0x6f, 0x7f, 0x7f, 0xbf, 0xff, 0xf6, 0xc5, 0x5e, 0xfe, + 0xdb, 0xdf, 0x7f, 0x71, 0xff, 0xed, 0x73, 0xd9, 0x7f, 0x1b, 0x48, 0xf0, 0x39, 0xdb, 0xcb, 0x5d, 0x56, 0xb8, 0xb4, + 0x44, 0xcb, 0xc4, 0x75, 0xb8, 0x66, 0x2d, 0x19, 0x4e, 0x19, 0x98, 0x2a, 0x70, 0x56, 0x37, 0x88, 0x26, 0xe0, 0xd5, + 0xba, 0xdd, 0x6f, 0xf5, 0x4b, 0x79, 0xad, 0x06, 0xd1, 0x44, 0x95, 0xb2, 0xb1, 0x85, 0x22, 0x1b, 0x1b, 0x44, 0xa0, + 0xfb, 0xfb, 0xca, 0x79, 0x79, 0xe5, 0x74, 0x9b, 0x0e, 0x44, 0x33, 0x05, 0xed, 0x33, 0x16, 0xd8, 0xdd, 0x66, 0x13, + 0x0a, 0x96, 0x52, 0x41, 0x03, 0x0a, 0x7c, 0xa9, 0xa0, 0x05, 0x05, 0x43, 0xa9, 0xe0, 0x18, 0x0a, 0x46, 0x52, 0xc1, + 0x09, 0x14, 0xdc, 0xaa, 0xd9, 0x55, 0x98, 0x7b, 0xa7, 0x9f, 0xe8, 0xd7, 0xa5, 0x44, 0x9c, 0xb9, 0xa9, 0x84, 0xa8, + 0x72, 0x62, 0x88, 0xac, 0x10, 0xe6, 0x91, 0xce, 0x79, 0xb4, 0xfe, 0x57, 0x7d, 0xc0, 0xbc, 0x60, 0x39, 0x62, 0x80, + 0xdd, 0x0d, 0xd5, 0x6c, 0x8a, 0xd7, 0x6a, 0x27, 0xf7, 0xe6, 0xb6, 0x8d, 0x86, 0xf0, 0x8e, 0xee, 0x60, 0xac, 0x0e, + 0x51, 0xb9, 0xf5, 0x7c, 0x9a, 0x87, 0x88, 0x5e, 0xb8, 0x45, 0xc8, 0x9b, 0x26, 0x24, 0xca, 0xe1, 0xbc, 0x1a, 0xd3, + 0xc0, 0x5e, 0x06, 0x22, 0x9a, 0x88, 0x53, 0x24, 0x3e, 0xa0, 0xa0, 0xcb, 0x7b, 0xd7, 0x2b, 0x78, 0x38, 0x1e, 0x50, + 0x9d, 0xa0, 0x9f, 0xe5, 0x71, 0xaa, 0x49, 0x97, 0xba, 0x30, 0x52, 0x6f, 0xd2, 0x99, 0x1a, 0x64, 0x48, 0xd5, 0x99, + 0x40, 0xe2, 0x91, 0xb3, 0x51, 0x67, 0x6e, 0x2c, 0xa7, 0x2c, 0xec, 0x8c, 0xb9, 0xab, 0x21, 0xac, 0x3f, 0x79, 0x92, + 0xcc, 0x74, 0xe1, 0x02, 0x85, 0x7b, 0xa2, 0x78, 0x4b, 0x50, 0x9a, 0xf9, 0x56, 0x2a, 0xbc, 0x77, 0x34, 0xd9, 0xc8, + 0xea, 0x4b, 0xf8, 0x5a, 0xbc, 0x66, 0x83, 0xc5, 0x44, 0xb9, 0x88, 0x26, 0xf7, 0xfa, 0x55, 0xc8, 0xaf, 0x00, 0x4a, + 0x95, 0xac, 0x49, 0x4d, 0xb1, 0xbd, 0xf9, 0xb7, 0xe8, 0x31, 0x2b, 0xd7, 0x4f, 0x01, 0x36, 0x25, 0x25, 0xb6, 0x01, + 0xbe, 0x03, 0xb3, 0x2d, 0x79, 0x2e, 0x5c, 0xc0, 0xfc, 0x49, 0xcf, 0x97, 0x9e, 0x04, 0x4f, 0xef, 0x07, 0x96, 0x24, + 0xde, 0x84, 0xc9, 0xa8, 0xa5, 0xd4, 0x39, 0x60, 0xc1, 0x5c, 0x9d, 0x8c, 0x13, 0x08, 0x8c, 0xbd, 0xbf, 0xe1, 0x8f, + 0x02, 0x6e, 0xb2, 0xe0, 0xa7, 0x05, 0x8b, 0x56, 0x38, 0x6f, 0xf8, 0x16, 0x2c, 0x4f, 0xd9, 0x8f, 0x02, 0x90, 0xc8, + 0x2d, 0x0b, 0xaa, 0x85, 0xa9, 0x37, 0xa9, 0x16, 0xd1, 0x5a, 0x67, 0x25, 0xb4, 0xa7, 0x97, 0x1e, 0x05, 0x2e, 0xfc, + 0x0c, 0xbb, 0xfc, 0x20, 0x9a, 0xfc, 0xa6, 0x46, 0xf9, 0x3b, 0x9c, 0x29, 0x7e, 0x08, 0x8d, 0x30, 0xed, 0x5b, 0x38, + 0xc7, 0x8a, 0x05, 0x53, 0xd8, 0x09, 0xd3, 0xa9, 0x89, 0xe1, 0xe3, 0xb4, 0x46, 0xa8, 0x1b, 0x16, 0xae, 0xed, 0xba, + 0x1a, 0x34, 0xb3, 0x13, 0x4f, 0x06, 0x9e, 0xe6, 0x34, 0x4e, 0x0c, 0xf1, 0xc7, 0xb2, 0x5b, 0x7a, 0x86, 0x3d, 0x28, + 0x23, 0xff, 0x76, 0x3d, 0x8e, 0xc2, 0xd4, 0x1c, 0x7b, 0x33, 0x3f, 0xb8, 0xeb, 0xcc, 0xa2, 0x30, 0x4a, 0xe6, 0xde, + 0x90, 0x75, 0x25, 0x7e, 0x14, 0xc3, 0x31, 0xf3, 0x88, 0x80, 0x8e, 0xd5, 0x88, 0xd9, 0x8c, 0x5a, 0xe7, 0xd1, 0x96, + 0xc7, 0x01, 0x5b, 0x65, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, 0x96, 0x99, 0x87, 0x72, 0x86, + 0x04, 0x06, 0x5d, 0x2e, 0x75, 0xec, 0x58, 0x8d, 0x56, 0xcc, 0x66, 0x8a, 0xd5, 0xda, 0xda, 0x79, 0x1c, 0x2d, 0x7b, + 0x00, 0x2d, 0x36, 0x36, 0x13, 0x16, 0x8c, 0xf1, 0x8d, 0x89, 0xd1, 0xa3, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, + 0x6c, 0xd6, 0x85, 0xd7, 0x9d, 0x86, 0x62, 0x4b, 0xfc, 0xf4, 0x89, 0x3d, 0x97, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, + 0x75, 0x47, 0xb1, 0xbb, 0xa0, 0x3f, 0x1e, 0x07, 0xd1, 0xb2, 0x33, 0xf5, 0x47, 0x23, 0x16, 0x76, 0x11, 0xe6, 0xbc, + 0x90, 0x05, 0x81, 0x3f, 0x4f, 0xfc, 0xa4, 0x3b, 0xf3, 0x56, 0xbc, 0xd7, 0xa3, 0x6d, 0xbd, 0x36, 0x79, 0xaf, 0xcd, + 0xbd, 0x7b, 0x95, 0xba, 0x81, 0x48, 0x55, 0xd4, 0x0f, 0x07, 0xad, 0xa5, 0xd8, 0x95, 0x71, 0xee, 0xdd, 0xeb, 0x3c, + 0x66, 0xeb, 0x99, 0x17, 0x4f, 0xfc, 0xb0, 0x63, 0x67, 0xd6, 0xed, 0x9a, 0x36, 0xc6, 0xa3, 0x76, 0xbb, 0x9d, 0x59, + 0x23, 0xf1, 0x64, 0x8f, 0x46, 0x99, 0x35, 0x14, 0x4f, 0xe3, 0xb1, 0x6d, 0x8f, 0xc7, 0x99, 0xe5, 0x8b, 0x82, 0x66, + 0x63, 0x38, 0x6a, 0x36, 0x32, 0x6b, 0x29, 0xd5, 0xc8, 0x2c, 0xc6, 0x9f, 0x62, 0x36, 0xea, 0xe2, 0x46, 0xe2, 0x3e, + 0xcf, 0x27, 0xb6, 0x9d, 0x21, 0x06, 0xb8, 0x2a, 0xe1, 0x26, 0x34, 0x5d, 0xb9, 0x5e, 0xef, 0x5d, 0x53, 0x29, 0x3e, + 0x37, 0x1c, 0xd6, 0xd6, 0x1b, 0x79, 0xf1, 0xc7, 0x6b, 0x45, 0x1a, 0x85, 0xe7, 0x51, 0xb5, 0xb5, 0x98, 0x06, 0x73, + 0xd5, 0x81, 0xb4, 0x1c, 0xdd, 0x41, 0x14, 0xc3, 0x99, 0x8d, 0xbd, 0x91, 0xbf, 0x48, 0x3a, 0x4e, 0x63, 0xbe, 0x12, + 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0x3a, 0x49, 0x14, 0xf8, 0x23, 0x51, 0xb4, 0xed, 0x2c, 0x39, 0x0d, 0xbd, + 0x8b, 0xfc, 0xab, 0x8f, 0xa1, 0x95, 0xbd, 0x20, 0x50, 0xac, 0x66, 0xa2, 0x30, 0x2f, 0x41, 0x73, 0x39, 0xc5, 0x4e, + 0x68, 0x5e, 0x30, 0x00, 0xad, 0x73, 0x34, 0x5f, 0xe5, 0x7b, 0xde, 0x39, 0x9e, 0xaf, 0xb2, 0xaf, 0x67, 0x6c, 0xe4, + 0x7b, 0x8a, 0x56, 0xec, 0x26, 0xc7, 0x06, 0x93, 0x3a, 0x7d, 0xbd, 0x65, 0x9b, 0x8a, 0x63, 0x01, 0xe9, 0x8b, 0x0e, + 0xfc, 0x19, 0xc8, 0x61, 0xbc, 0x30, 0xcd, 0xb2, 0xfe, 0x75, 0x96, 0x75, 0x2f, 0x7c, 0xed, 0xea, 0xaf, 0x1a, 0xd1, + 0x42, 0x32, 0x41, 0xcd, 0xf4, 0x6b, 0xe3, 0x9c, 0xc9, 0xee, 0x32, 0x40, 0xc6, 0xd0, 0x55, 0x46, 0xae, 0x4c, 0xf4, + 0x76, 0xb3, 0x32, 0x4d, 0x72, 0x5e, 0x9d, 0xbc, 0x6f, 0xca, 0x55, 0x90, 0x02, 0x41, 0x85, 0x73, 0xe6, 0x5e, 0x48, + 0xbe, 0x37, 0xc0, 0xf4, 0x60, 0x65, 0x8a, 0x1d, 0xf4, 0x7a, 0x1b, 0xef, 0x79, 0x79, 0x3f, 0xef, 0xf9, 0xb7, 0x74, + 0x1f, 0xde, 0xf3, 0xf2, 0x8b, 0xf3, 0x9e, 0xaf, 0x37, 0x63, 0x07, 0x5d, 0x46, 0xae, 0x9a, 0x1b, 0x4c, 0x02, 0x69, + 0x8a, 0x29, 0x2a, 0xff, 0xeb, 0xf4, 0xd7, 0x06, 0x71, 0x11, 0xbd, 0x21, 0x51, 0xe0, 0x7c, 0x2a, 0x88, 0x59, 0xdf, + 0x86, 0xee, 0x9f, 0x62, 0xf9, 0x79, 0x3c, 0x76, 0x5f, 0x47, 0x52, 0x41, 0xfe, 0xc4, 0x7d, 0x49, 0x4a, 0x11, 0x94, + 0xe9, 0x4d, 0xee, 0xed, 0x03, 0x39, 0xa6, 0x21, 0x00, 0x2b, 0xb9, 0x76, 0x8f, 0x72, 0x9f, 0xbb, 0x6e, 0x19, 0x04, + 0x2d, 0x77, 0x72, 0x15, 0x61, 0xb6, 0x36, 0x2c, 0xa3, 0x26, 0x4c, 0xc8, 0x00, 0x5e, 0xde, 0x7d, 0x3f, 0xd2, 0x2e, + 0x23, 0x3d, 0xf3, 0x93, 0xb7, 0xd5, 0x20, 0x57, 0x42, 0xcf, 0x25, 0x0f, 0x27, 0xe3, 0x7e, 0x73, 0x52, 0x2c, 0x5b, + 0x7c, 0x4d, 0xcd, 0xcf, 0x4a, 0x23, 0xed, 0xc8, 0x0d, 0xbb, 0x14, 0xd9, 0x7b, 0x83, 0x18, 0xf3, 0x60, 0x30, 0x6b, + 0xce, 0xe5, 0xad, 0xf1, 0x19, 0x62, 0x83, 0x8e, 0xa8, 0xb9, 0x3f, 0xca, 0x32, 0xbd, 0x2b, 0x26, 0x42, 0x22, 0xb4, + 0xec, 0x3e, 0x26, 0x2e, 0x29, 0x84, 0x40, 0x5c, 0xe2, 0x43, 0xd6, 0xcc, 0x97, 0xe0, 0x1f, 0xc0, 0x6d, 0x9f, 0xf9, + 0x9c, 0xa9, 0x0a, 0x4d, 0x1f, 0xf9, 0x8d, 0x48, 0x03, 0x02, 0x83, 0x76, 0xd9, 0xdb, 0xaa, 0xb4, 0x20, 0x9b, 0x8e, + 0xad, 0x34, 0x39, 0xe8, 0xe0, 0x00, 0x91, 0x7c, 0x85, 0x58, 0x88, 0xd0, 0x0e, 0xaf, 0x83, 0x0f, 0x99, 0x9a, 0xf3, + 0x7e, 0xb8, 0xfd, 0x7a, 0xa7, 0x87, 0xd0, 0xa0, 0x57, 0x51, 0xba, 0xdd, 0xe3, 0x97, 0x09, 0xac, 0x44, 0xb2, 0x34, + 0xac, 0x64, 0xa9, 0x3c, 0x5b, 0x8b, 0x28, 0xd8, 0xa9, 0x37, 0x37, 0x41, 0xcb, 0x83, 0xb8, 0x97, 0x63, 0x3c, 0x29, + 0xe0, 0x76, 0x77, 0x91, 0x00, 0x6e, 0x44, 0x39, 0x0a, 0xe2, 0x9f, 0xee, 0x70, 0x11, 0x27, 0x51, 0xdc, 0x99, 0x47, + 0x7e, 0x98, 0xb2, 0x38, 0x23, 0xc1, 0x0a, 0xce, 0x8f, 0x98, 0x9e, 0xeb, 0x75, 0x34, 0xf7, 0x86, 0x7e, 0x7a, 0xd7, + 0xb1, 0x39, 0x4b, 0x61, 0x77, 0x39, 0x77, 0x60, 0xd7, 0xd6, 0xef, 0xf0, 0xd9, 0x7c, 0x8e, 0x8c, 0x5f, 0xbc, 0xc9, + 0xce, 0xc8, 0xdb, 0xbc, 0x2b, 0xbd, 0xa5, 0x38, 0xe0, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x01, 0x2c, 0x0f, 0x4b, 0x6d, + 0x8f, 0xd8, 0xc4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0xd5, 0xd2, 0x15, 0xbb, 0xbe, 0x18, 0x38, 0x1e, 0x7d, + 0x1f, 0xc8, 0x3a, 0xde, 0x38, 0x65, 0xb1, 0xb1, 0x4f, 0xcd, 0x01, 0x1b, 0x47, 0x31, 0xa3, 0x9c, 0x71, 0x4e, 0x7b, + 0xbe, 0xda, 0xbf, 0xfb, 0xdd, 0xc3, 0xaf, 0xef, 0x27, 0x8c, 0x52, 0x4d, 0x74, 0xa6, 0xdf, 0xd3, 0xdb, 0x26, 0x3d, + 0x03, 0xd6, 0x90, 0x66, 0x7e, 0x48, 0x52, 0x10, 0x88, 0xf7, 0x55, 0x9b, 0x9a, 0x63, 0x1e, 0x71, 0x9a, 0x17, 0xb3, + 0xc0, 0x4b, 0xfd, 0x5b, 0xc1, 0x33, 0x36, 0x8f, 0xe7, 0x2b, 0xb1, 0xc6, 0x48, 0xf0, 0x1e, 0xb0, 0x48, 0x15, 0x50, + 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xba, 0x1b, 0xa3, 0x11, 0xd1, 0xaa, 0x2b, 0x94, 0xbe, 0x35, 0x5f, 0xc9, 0x24, + 0xba, 0x68, 0x96, 0x53, 0xea, 0x6a, 0x9a, 0x91, 0x99, 0x3f, 0x1a, 0x05, 0x2c, 0x2b, 0x2d, 0x74, 0x79, 0x2d, 0xa5, + 0xc9, 0xc9, 0xe7, 0xc1, 0x1b, 0x24, 0x51, 0xb0, 0x48, 0x59, 0xfd, 0x74, 0x09, 0x89, 0x6e, 0x31, 0x39, 0xf8, 0xbb, + 0x0c, 0x6b, 0x0b, 0xd8, 0x6d, 0xd8, 0x26, 0x76, 0x17, 0xb2, 0x0a, 0x9a, 0xcd, 0x32, 0xe8, 0xf0, 0x2a, 0x07, 0xda, + 0xa8, 0x19, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0xcf, 0xac, 0x96, 0x17, 0x65, 0xe5, 0xc1, + 0xfc, 0x36, 0x67, 0xec, 0x45, 0xfd, 0x19, 0x7b, 0x21, 0xce, 0xd8, 0xee, 0x9d, 0xf9, 0x68, 0xec, 0xc0, 0x7f, 0xdd, + 0x62, 0x40, 0x1d, 0x5b, 0x69, 0xce, 0x57, 0x8a, 0x33, 0x5f, 0x29, 0x66, 0x63, 0xbe, 0x52, 0xb0, 0x6b, 0x74, 0x6f, + 0x31, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf4, 0xca, 0x39, 0x82, 0x77, 0xd0, 0xaa, 0xb5, 0xf9, + 0xae, 0xb1, 0xfb, 0xa8, 0xd3, 0x59, 0x12, 0x48, 0x5b, 0xb7, 0x52, 0x6f, 0x30, 0x00, 0x51, 0x66, 0x34, 0x5c, 0x24, + 0xff, 0xe4, 0xf0, 0xf3, 0x49, 0xdc, 0x89, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0x28, 0xbc, 0x65, 0xa2, 0x87, 0x75, + 0xbe, 0x4e, 0x1d, 0x4a, 0x81, 0xd8, 0xb0, 0x8e, 0x6a, 0x36, 0x79, 0xfd, 0x44, 0xff, 0x66, 0xab, 0xb4, 0x1d, 0xc5, + 0x7c, 0xc6, 0xb4, 0xec, 0x9c, 0x8e, 0x87, 0xcf, 0x06, 0x5f, 0x4d, 0xbb, 0x5d, 0x0f, 0xee, 0x95, 0xf8, 0xd2, 0xb5, + 0x20, 0x2a, 0x9c, 0x6e, 0xf1, 0x50, 0x1c, 0xbb, 0x7b, 0xdd, 0xb6, 0x47, 0x36, 0x7a, 0xdd, 0x41, 0x10, 0x8a, 0xba, + 0x7b, 0x62, 0xf9, 0x47, 0x2f, 0x8e, 0xe0, 0x3f, 0xe2, 0xea, 0xff, 0x96, 0xd6, 0x31, 0xea, 0xaf, 0xd3, 0x12, 0xa3, + 0x4e, 0xac, 0x12, 0x32, 0xe2, 0xfb, 0xd7, 0x1f, 0x8f, 0x1f, 0xd6, 0x60, 0xef, 0xda, 0xe4, 0x19, 0x56, 0xad, 0xfd, + 0x32, 0x8a, 0x02, 0xe6, 0x85, 0x9b, 0xd5, 0xc5, 0xf4, 0x90, 0x9b, 0x7f, 0xea, 0x42, 0x23, 0x71, 0x8f, 0x20, 0xa7, + 0x04, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x62, 0xdb, 0x55, 0xe2, 0xdd, 0xfd, 0x57, 0x89, 0x3f, 0xee, 0x75, 0x95, 0x78, + 0xf7, 0xc5, 0xaf, 0x12, 0x17, 0x9b, 0x57, 0x89, 0x8b, 0x48, 0xb8, 0x03, 0x1b, 0x6f, 0x16, 0xfc, 0xe7, 0x07, 0xb2, + 0xf7, 0x7d, 0x17, 0xb9, 0x2d, 0x9b, 0xd2, 0x1a, 0x5e, 0xfe, 0xea, 0x8b, 0x05, 0x6e, 0xc4, 0x77, 0xe8, 0x1d, 0x57, + 0x5c, 0x2d, 0x38, 0x66, 0xc7, 0xef, 0x48, 0xc5, 0x41, 0x14, 0x4e, 0x7e, 0x02, 0x7b, 0x6f, 0x10, 0x07, 0xc6, 0xd2, + 0x0b, 0x3f, 0xf9, 0x29, 0x9a, 0x2f, 0xe6, 0xa8, 0xa8, 0xfa, 0xe0, 0x27, 0xfe, 0x20, 0x60, 0x79, 0x1c, 0x49, 0xd2, + 0xba, 0x72, 0xd9, 0x3a, 0x28, 0x5e, 0xc5, 0x4f, 0x6f, 0x25, 0x7e, 0xa2, 0x8b, 0x2d, 0xff, 0x4d, 0x6e, 0x82, 0x6a, + 0xfd, 0x45, 0x44, 0x58, 0x88, 0x49, 0x40, 0x3f, 0xfc, 0x32, 0x72, 0x11, 0xe9, 0x35, 0xa3, 0x14, 0xee, 0x1b, 0x5b, + 0xfb, 0x61, 0xd5, 0x7e, 0xde, 0x2c, 0x74, 0x23, 0x4f, 0xb3, 0xb1, 0x29, 0xce, 0x9f, 0x45, 0x8b, 0x84, 0x8d, 0xa2, + 0x65, 0xa8, 0x1a, 0x21, 0xd7, 0xab, 0x46, 0x28, 0x53, 0xcf, 0xdb, 0x94, 0x15, 0x8e, 0xaa, 0x35, 0x87, 0x39, 0x34, + 0x49, 0x83, 0x6d, 0xe2, 0x10, 0x55, 0x11, 0xb2, 0xa9, 0x7b, 0xa0, 0x69, 0x91, 0xfb, 0xb0, 0x96, 0xc2, 0xf3, 0x24, + 0xb2, 0xb8, 0x54, 0x38, 0xd1, 0x42, 0x21, 0x5c, 0x14, 0xb1, 0xae, 0x6b, 0x16, 0x8e, 0xbf, 0xa1, 0x20, 0x91, 0xc5, + 0x5b, 0xd0, 0x55, 0x65, 0x0b, 0xbe, 0x1e, 0x3c, 0xf2, 0x33, 0x3d, 0xbe, 0x92, 0xa6, 0xf1, 0xed, 0x2d, 0x8b, 0x03, + 0xef, 0x4e, 0xd3, 0xb3, 0x28, 0xfc, 0x01, 0x26, 0xe0, 0x75, 0xb4, 0x0c, 0xe5, 0x0a, 0x98, 0x90, 0xbd, 0x66, 0x2f, + 0xd5, 0xc6, 0x28, 0x87, 0x98, 0x1d, 0x12, 0x04, 0xbe, 0x35, 0xf7, 0x26, 0xec, 0x2f, 0x06, 0xfd, 0xfb, 0x57, 0x3d, + 0x33, 0xde, 0x45, 0xf9, 0x87, 0x7e, 0x9e, 0xef, 0xf1, 0x99, 0x27, 0x4f, 0x0e, 0xb6, 0x0f, 0x5b, 0x1b, 0x06, 0xcc, + 0x8b, 0x05, 0x14, 0x35, 0xad, 0xf5, 0xad, 0xa7, 0x00, 0xa0, 0xb8, 0x8c, 0x16, 0xc3, 0x29, 0xfa, 0xed, 0x7e, 0xb9, + 0xf1, 0xa6, 0xd0, 0x27, 0x4b, 0xae, 0xec, 0xeb, 0x7c, 0xe8, 0x95, 0xa2, 0x62, 0x16, 0xf0, 0xfb, 0xe7, 0x90, 0x64, + 0xeb, 0x3f, 0x38, 0x0d, 0x9b, 0xbb, 0x26, 0x0f, 0xf9, 0xf5, 0xa0, 0xcd, 0xdb, 0xf5, 0x21, 0x2a, 0x0f, 0x85, 0xaf, + 0x16, 0x4a, 0xba, 0x7a, 0x24, 0x93, 0x55, 0x27, 0x4d, 0x4e, 0x15, 0xb3, 0x2d, 0x0b, 0x8e, 0xf8, 0x0a, 0xb3, 0x4a, + 0x56, 0x23, 0x06, 0xe3, 0xd8, 0xaa, 0x82, 0x64, 0xb8, 0x37, 0x05, 0x43, 0xf4, 0x55, 0x7d, 0x37, 0xf3, 0x43, 0x03, + 0x33, 0xbd, 0x6e, 0xbe, 0xf1, 0x56, 0x90, 0xeb, 0x10, 0x90, 0x5b, 0xf5, 0x15, 0x14, 0x1a, 0x72, 0xb4, 0x20, 0x6f, + 0x34, 0xd2, 0xd4, 0xda, 0x99, 0x10, 0xda, 0xc0, 0xfe, 0x57, 0x8a, 0xa2, 0x28, 0xf9, 0x35, 0x42, 0xc9, 0xef, 0x11, + 0x58, 0x8e, 0xd7, 0x01, 0xd0, 0x96, 0x64, 0xf3, 0x15, 0x95, 0xc0, 0xcd, 0x00, 0xed, 0xa7, 0x45, 0x01, 0x4f, 0xe7, + 0x03, 0xc6, 0x2d, 0x54, 0x20, 0x2e, 0xf4, 0xa0, 0xfa, 0xf6, 0x62, 0xc8, 0xfa, 0xd7, 0x51, 0xf0, 0xc2, 0x8e, 0x6f, + 0xb9, 0x24, 0x58, 0xb1, 0xe9, 0xb1, 0xdf, 0x65, 0xf5, 0x79, 0x5f, 0x42, 0x09, 0x0b, 0x82, 0xd6, 0xa1, 0x92, 0xc6, + 0xd1, 0x60, 0x35, 0xb8, 0x11, 0xef, 0x45, 0xab, 0x74, 0xc6, 0xc2, 0x85, 0x6a, 0x80, 0xd5, 0x09, 0xe6, 0xe1, 0x81, + 0x3a, 0xaf, 0x89, 0xd9, 0x02, 0x6c, 0x53, 0xdf, 0x72, 0x4a, 0xb4, 0x50, 0x98, 0xaa, 0x78, 0xc6, 0x90, 0x07, 0xc0, + 0x49, 0x38, 0x6e, 0xab, 0x52, 0x08, 0xbe, 0xa4, 0x51, 0x19, 0x9b, 0xf3, 0x90, 0x57, 0xc8, 0x29, 0x90, 0x8d, 0x18, + 0x17, 0x17, 0x89, 0x69, 0xd7, 0xbc, 0xea, 0xa2, 0xe5, 0x1a, 0x19, 0xaf, 0x22, 0x28, 0x8a, 0xf5, 0xcd, 0x6e, 0x38, + 0x9c, 0x90, 0x7c, 0x60, 0x6b, 0x3f, 0xc3, 0x8d, 0x7e, 0xb6, 0x0c, 0xfa, 0x23, 0xbb, 0x23, 0x42, 0x42, 0x53, 0xf5, + 0x91, 0xdd, 0x81, 0x71, 0xf8, 0x39, 0x48, 0x53, 0xd4, 0x1d, 0xe8, 0xda, 0x80, 0x74, 0xbe, 0x43, 0x48, 0x48, 0xb1, + 0xe3, 0x00, 0xd9, 0xd9, 0x0e, 0x2c, 0x8e, 0x53, 0x1c, 0x1a, 0x49, 0x57, 0x1c, 0x62, 0x1e, 0xb1, 0x40, 0xab, 0x9d, + 0x63, 0xb3, 0xe6, 0x68, 0xe8, 0xcf, 0x1c, 0xdb, 0x3e, 0xdc, 0xa8, 0x0f, 0x82, 0xec, 0xba, 0xda, 0xba, 0x91, 0xba, + 0x8e, 0x6d, 0xfa, 0xcf, 0xac, 0x46, 0x77, 0x83, 0x46, 0x4b, 0xf9, 0xa2, 0xfa, 0x28, 0xfe, 0xea, 0x3d, 0x5e, 0x6b, + 0x1b, 0x07, 0x52, 0xaf, 0x46, 0x00, 0x40, 0xd8, 0x32, 0x2e, 0xff, 0xea, 0x6f, 0x92, 0x7e, 0xca, 0x56, 0x45, 0xb9, + 0xcb, 0xfb, 0x90, 0xf1, 0x50, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x7e, 0x57, 0x60, + 0x14, 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0x6e, 0x35, 0x56, 0x68, 0xf4, 0x76, 0x72, + 0x0b, 0xd8, 0xff, 0x16, 0xf2, 0x69, 0x0d, 0x20, 0xc6, 0x23, 0xd4, 0x80, 0xfc, 0xa8, 0xf7, 0x76, 0x08, 0x21, 0x79, + 0xe5, 0xee, 0xca, 0x44, 0x72, 0xff, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x9e, 0xdc, 0x3d, 0xb0, 0x4b, + 0x16, 0x8e, 0xca, 0x1d, 0x56, 0xe8, 0xd7, 0xfe, 0xdd, 0x95, 0x30, 0x0a, 0x24, 0x0e, 0x8e, 0x6a, 0x30, 0x4a, 0x16, + 0x85, 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x7b, 0x71, 0x31, 0xd8, 0x80, 0xb2, 0x7e, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0x64, + 0xa7, 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0xb7, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x6f, 0x6a, + 0x5f, 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, + 0x98, 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x6a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, + 0xb7, 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x51, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, + 0xbf, 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, + 0x24, 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, + 0x6f, 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, + 0xe7, 0x36, 0x10, 0x08, 0x64, 0x4d, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x13, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, + 0x49, 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x25, 0x09, 0x42, 0xc7, 0x56, 0xec, 0x6e, 0x0d, 0x03, 0x80, 0xf4, + 0xbf, 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xdd, + 0xfc, 0x26, 0xc9, 0x7b, 0xd6, 0x3c, 0x26, 0x48, 0x59, 0x9c, 0xcf, 0x6b, 0x74, 0x04, 0x1c, 0x7c, 0x97, 0xc5, 0x8b, + 0x10, 0x53, 0xdd, 0x9a, 0x69, 0xec, 0x0d, 0x3f, 0xae, 0xa5, 0xef, 0x71, 0x91, 0x28, 0x88, 0x8b, 0xcb, 0x4a, 0x85, + 0xae, 0x87, 0x99, 0xa1, 0x58, 0xc7, 0x6a, 0x24, 0x92, 0xa0, 0xa6, 0xf3, 0xc8, 0x6e, 0x7a, 0x2f, 0xc6, 0x47, 0x15, + 0xf9, 0x69, 0xa3, 0x55, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa2, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, + 0x66, 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x8d, 0x92, 0x6d, 0x60, 0x8d, 0xfd, + 0x20, 0x30, 0x03, 0x70, 0x63, 0x58, 0x7f, 0xd6, 0xf0, 0xb0, 0x9f, 0x05, 0xe4, 0x24, 0xfc, 0x8c, 0x7e, 0xca, 0x3b, + 0x25, 0x9d, 0x2e, 0x66, 0x83, 0xb5, 0x2c, 0x28, 0x97, 0xe4, 0xe7, 0x9b, 0x32, 0x73, 0xf9, 0xb3, 0xe3, 0xf1, 0xb8, + 0x2c, 0x35, 0xb6, 0x95, 0x23, 0x94, 0xfc, 0x3e, 0xb2, 0x6d, 0xbb, 0x3a, 0xbf, 0xdb, 0x0e, 0x0a, 0x1d, 0x0c, 0x13, + 0x85, 0xf0, 0xed, 0xfb, 0xf7, 0xd4, 0xef, 0x04, 0x2d, 0x75, 0xb5, 0xed, 0x3c, 0xd2, 0x56, 0xfb, 0xaf, 0x00, 0x05, + 0x51, 0xc3, 0x7d, 0xc7, 0x7f, 0x73, 0xaf, 0xec, 0xe8, 0xa9, 0x7a, 0x80, 0x1f, 0xd6, 0xf8, 0x9e, 0xbd, 0xbe, 0x47, + 0xd3, 0x6d, 0xdb, 0x3b, 0xb3, 0x0a, 0xb2, 0x5b, 0xb2, 0x59, 0xea, 0x92, 0xa5, 0x92, 0x9f, 0xb2, 0x59, 0xd2, 0x19, + 0x32, 0x54, 0x90, 0x5a, 0x12, 0xb5, 0x45, 0xab, 0x1e, 0x73, 0x02, 0x76, 0x5c, 0x8e, 0xc0, 0xc3, 0xb6, 0x82, 0xca, + 0xaa, 0x0d, 0xcd, 0x9a, 0xf8, 0x08, 0x52, 0xb1, 0xf5, 0xa6, 0xc2, 0x09, 0xb7, 0x69, 0xcb, 0xfe, 0x43, 0xa9, 0x9e, + 0x02, 0xdc, 0xe9, 0x5a, 0x58, 0x9b, 0x90, 0xf2, 0x04, 0xff, 0xce, 0x95, 0x73, 0x2f, 0xe6, 0xab, 0xb2, 0x71, 0x57, + 0x1b, 0xd4, 0x4d, 0x05, 0x29, 0x23, 0xa8, 0xeb, 0x50, 0x5f, 0x6e, 0x02, 0x34, 0x96, 0xad, 0x5b, 0xc0, 0x82, 0x46, + 0x4c, 0x41, 0x45, 0x47, 0x98, 0x83, 0x8a, 0xd7, 0x59, 0xd8, 0x79, 0x85, 0x7c, 0x1f, 0x7f, 0x41, 0x2e, 0x72, 0x48, + 0x70, 0xf2, 0x07, 0xe3, 0x79, 0x1b, 0x95, 0x7b, 0xa5, 0xad, 0x8a, 0xa6, 0x32, 0xb8, 0x07, 0xc4, 0x8d, 0x54, 0x59, + 0xc4, 0x81, 0x49, 0xe9, 0xe9, 0x35, 0x7d, 0xbd, 0x39, 0xee, 0xed, 0xdd, 0x3b, 0x2d, 0xd0, 0x6b, 0x6c, 0x4e, 0xd5, + 0x5e, 0xaa, 0xbd, 0xaa, 0x0e, 0x5b, 0xc0, 0x09, 0x2b, 0x00, 0x3e, 0xb3, 0x0a, 0x1a, 0x0d, 0x29, 0x15, 0xdc, 0x47, + 0x83, 0xce, 0xdf, 0xca, 0xc8, 0x5a, 0x8c, 0x13, 0xbb, 0xab, 0xaf, 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xcc, 0x1d, 0xc7, + 0x4e, 0xf8, 0x6c, 0xc2, 0x8e, 0x91, 0xd1, 0x95, 0x83, 0x3b, 0x08, 0x4f, 0xa9, 0x49, 0x69, 0x4f, 0xe8, 0x94, 0xa2, + 0x2e, 0xe1, 0x8f, 0xb5, 0xc2, 0xfb, 0xcb, 0x92, 0x34, 0x9e, 0x07, 0x9d, 0x68, 0xe8, 0x7b, 0xd5, 0x9e, 0xf9, 0xe1, + 0xfe, 0x75, 0xbd, 0xd5, 0xde, 0x75, 0x81, 0x39, 0xdc, 0xbb, 0x32, 0x70, 0x97, 0x58, 0xf9, 0x32, 0x75, 0xff, 0x28, + 0x29, 0x0f, 0xe4, 0x80, 0x89, 0x2a, 0xb6, 0xa2, 0x1b, 0xfd, 0x8f, 0x0b, 0xb7, 0x7f, 0x7a, 0xb6, 0x9a, 0x05, 0xca, + 0x2d, 0x8b, 0x13, 0x48, 0x28, 0xa1, 0x3a, 0x96, 0xad, 0x2a, 0x68, 0xd0, 0xef, 0x87, 0x13, 0x57, 0xfd, 0xf9, 0xf2, + 0x8d, 0xd9, 0x56, 0xcf, 0xc0, 0x1c, 0xe3, 0x76, 0x82, 0x2c, 0xee, 0x85, 0x77, 0xc7, 0xe2, 0x9b, 0x06, 0xf7, 0xf8, + 0x21, 0xe6, 0x16, 0xcb, 0x94, 0x86, 0xba, 0x47, 0xe2, 0x77, 0xe5, 0xd6, 0x67, 0xcb, 0x97, 0xd1, 0xca, 0x55, 0x01, + 0xb1, 0x3a, 0x8d, 0xb6, 0xe2, 0x34, 0x8e, 0xac, 0xe3, 0xb6, 0xda, 0xfb, 0x4a, 0x51, 0x4e, 0x47, 0x6c, 0x9c, 0xf4, + 0x50, 0x1c, 0x73, 0x8a, 0xfc, 0x20, 0xfd, 0x56, 0x14, 0x6b, 0x18, 0x24, 0xa6, 0xa3, 0xac, 0xf9, 0xa3, 0xa2, 0x00, + 0x32, 0xea, 0x28, 0x8f, 0xc6, 0x8d, 0xf1, 0xd1, 0xf8, 0x45, 0x97, 0x17, 0x67, 0x5f, 0x95, 0xaa, 0x1b, 0xf4, 0x6f, + 0x43, 0x6a, 0x96, 0xa4, 0x71, 0xf4, 0x91, 0x71, 0x5e, 0x52, 0xc9, 0x05, 0x45, 0xd5, 0xa6, 0x8d, 0xcd, 0x2f, 0x39, + 0xed, 0xc1, 0x70, 0xdc, 0x28, 0xaa, 0x23, 0x8c, 0x87, 0x39, 0x90, 0xa7, 0x87, 0x02, 0xf4, 0x53, 0x79, 0x9a, 0x1c, + 0xb3, 0x6e, 0xa2, 0x1c, 0x95, 0x8f, 0x71, 0x22, 0xc6, 0x77, 0x0a, 0x79, 0xd5, 0x0a, 0xef, 0xc5, 0x04, 0x9b, 0xb9, + 0xea, 0x0f, 0x4e, 0xa3, 0x6d, 0x38, 0xce, 0xb1, 0x75, 0xdc, 0x1e, 0xda, 0xc6, 0x91, 0x75, 0x64, 0x36, 0xad, 0x63, + 0xa3, 0x6d, 0xb6, 0x8d, 0xf6, 0x77, 0xed, 0xa1, 0x79, 0x64, 0x1d, 0x19, 0xb6, 0xd9, 0x86, 0x42, 0xb3, 0x6d, 0xb6, + 0x6f, 0xcd, 0xa3, 0xf6, 0xd0, 0xc6, 0xd2, 0x86, 0xd5, 0x6a, 0x99, 0x8e, 0x6d, 0xb5, 0x5a, 0x46, 0xcb, 0x3a, 0x3e, + 0x36, 0x9d, 0xa6, 0x75, 0x7c, 0x7c, 0xd1, 0x6a, 0x5b, 0x4d, 0x78, 0xd7, 0x6c, 0x0e, 0x9b, 0x96, 0xe3, 0x98, 0xf0, + 0x97, 0xd1, 0xb6, 0x1a, 0xf4, 0xc3, 0x71, 0xac, 0xa6, 0x63, 0xd8, 0x41, 0xab, 0x61, 0x1d, 0xbf, 0x30, 0xf0, 0x6f, + 0xac, 0x66, 0xe0, 0x5f, 0xd0, 0x8d, 0xf1, 0xc2, 0x6a, 0x1c, 0xd3, 0x2f, 0xec, 0xf0, 0xf6, 0xa8, 0xfd, 0x37, 0xf5, + 0x70, 0xeb, 0x18, 0x1c, 0x1a, 0x43, 0xbb, 0x65, 0x35, 0x9b, 0xc6, 0x91, 0x63, 0xb5, 0x9b, 0x53, 0xf3, 0xa8, 0x61, + 0x1d, 0x9f, 0x0c, 0x4d, 0xc7, 0x3a, 0x39, 0x31, 0x6c, 0xb3, 0x69, 0x35, 0x0c, 0xc7, 0x3a, 0x6a, 0xe2, 0x8f, 0xa6, + 0xd5, 0xb8, 0x3d, 0x79, 0x61, 0x1d, 0xb7, 0xa6, 0xc7, 0xd6, 0xd1, 0x87, 0xa3, 0xb6, 0xd5, 0x68, 0x4e, 0x9b, 0xc7, + 0x56, 0xe3, 0xe4, 0xf6, 0xd8, 0x3a, 0x9a, 0x9a, 0x8d, 0xe3, 0x9d, 0x2d, 0x9d, 0x86, 0x05, 0x73, 0x84, 0xaf, 0xe1, + 0x85, 0xc1, 0x5f, 0xc0, 0x9f, 0x29, 0xb6, 0xfd, 0x1d, 0xbb, 0x49, 0x36, 0x9b, 0xbe, 0xb0, 0xda, 0x27, 0x43, 0xaa, + 0x0e, 0x05, 0xa6, 0xa8, 0x01, 0x4d, 0x6e, 0x4d, 0xfa, 0x2c, 0x76, 0x67, 0x8a, 0x8e, 0xc4, 0x1f, 0xfe, 0xb1, 0x5b, + 0x13, 0x3e, 0x4c, 0xdf, 0xfd, 0x8f, 0xf6, 0x93, 0x2f, 0xf9, 0xe9, 0xe1, 0x84, 0xb6, 0xfe, 0xa4, 0xf7, 0xd5, 0x29, + 0x1c, 0xee, 0x5e, 0xdf, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x1f, 0xf7, 0x2b, 0x25, 0x5f, 0x2e, 0xf6, 0x51, 0x4a, 0xfe, + 0xe3, 0x8b, 0x2b, 0x25, 0x7f, 0xa9, 0xfa, 0xd6, 0xbc, 0xa9, 0xe6, 0x9a, 0xfe, 0xe3, 0xba, 0x2a, 0x72, 0x48, 0x3c, + 0xed, 0xea, 0xc7, 0xc5, 0x35, 0xc4, 0x8f, 0x7f, 0x13, 0xb9, 0x2f, 0x17, 0x25, 0x83, 0xcf, 0x08, 0x70, 0xec, 0x9b, + 0x88, 0x70, 0xec, 0x87, 0x85, 0x0b, 0x56, 0x66, 0x9c, 0xcd, 0xf1, 0x47, 0xe6, 0xd4, 0x0b, 0xc6, 0x39, 0x8b, 0x04, + 0x25, 0x5d, 0x2c, 0x06, 0xbf, 0x79, 0x20, 0xcf, 0x70, 0x93, 0x59, 0xcc, 0xc2, 0x04, 0x2c, 0x82, 0xc1, 0x92, 0x63, + 0x1c, 0x67, 0x95, 0xc6, 0x96, 0x88, 0xb8, 0x7f, 0xc3, 0x3d, 0x8a, 0xb7, 0xbe, 0x47, 0x03, 0xe0, 0xfa, 0xde, 0x9d, + 0xcd, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, 0xbd, 0x2f, 0x9b, 0xe1, 0x56, 0x0c, 0xaf, 0xb7, + 0x43, 0x0a, 0x90, 0x54, 0xdb, 0x3b, 0x65, 0x33, 0xde, 0xfb, 0x86, 0x59, 0xf3, 0xf9, 0x52, 0xf3, 0x1d, 0x36, 0xc4, + 0x79, 0xc7, 0xd5, 0xa9, 0x5a, 0x97, 0xf8, 0xb4, 0xfa, 0x09, 0x29, 0x2e, 0xa8, 0x85, 0xa1, 0x71, 0xc1, 0xa9, 0xda, + 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd4, 0xa7, 0x6c, 0x9c, 0xfc, 0x6c, 0x8d, 0xf7, 0x0a, 0xff, 0x17, 0xe0, 0x44, + 0x39, 0xc7, 0x33, 0x88, 0xe4, 0x79, 0x5e, 0x4b, 0xfd, 0x92, 0x34, 0x22, 0x9b, 0x3a, 0xeb, 0x4d, 0x5e, 0x74, 0xab, + 0x5b, 0x82, 0xc3, 0x66, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x13, 0x40, 0x46, 0x8e, 0x1a, 0xe8, 0xe7, 0xb0, 0xab, 0x33, + 0x51, 0xef, 0x11, 0x6c, 0x62, 0xee, 0x09, 0xa8, 0xc8, 0x21, 0x4d, 0xd7, 0xe3, 0x20, 0xf2, 0xd2, 0x0e, 0xb2, 0x69, + 0x12, 0xcb, 0xdb, 0x40, 0x8f, 0x85, 0xee, 0x0e, 0x63, 0x3a, 0xb9, 0x63, 0xde, 0x09, 0x7a, 0x3e, 0xec, 0xb2, 0xbf, + 0xcb, 0x1d, 0xce, 0xd6, 0x25, 0x73, 0x14, 0xa7, 0x75, 0x62, 0x38, 0xc7, 0x86, 0x75, 0xd2, 0xd2, 0x33, 0x71, 0xe0, + 0xe4, 0x2e, 0x4b, 0x13, 0x02, 0x0e, 0x10, 0x39, 0x98, 0x7e, 0xe8, 0xa7, 0xbe, 0x17, 0x64, 0xc0, 0x0f, 0x97, 0x2f, + 0x29, 0xff, 0x58, 0x24, 0x29, 0x8c, 0x51, 0x30, 0xbd, 0xe8, 0xfc, 0x61, 0x0e, 0x58, 0xba, 0x64, 0x2c, 0xdc, 0x62, + 0x18, 0x53, 0xf5, 0x25, 0xf9, 0xed, 0x2c, 0xeb, 0x33, 0xb2, 0x5a, 0x1b, 0xa4, 0x21, 0xdf, 0x1f, 0xc2, 0xf1, 0x21, + 0xeb, 0x1b, 0xdf, 0x6d, 0x43, 0xb8, 0x3f, 0xdf, 0x8f, 0x70, 0x53, 0xb6, 0x0f, 0xc2, 0xfd, 0xf9, 0x8b, 0x23, 0xdc, + 0xef, 0x64, 0x84, 0x5b, 0xf2, 0x1f, 0x2c, 0x34, 0x4c, 0xef, 0xf1, 0x59, 0x03, 0x17, 0xd9, 0xe7, 0xea, 0x21, 0x31, + 0xf0, 0xaa, 0x5e, 0xe4, 0xa8, 0xfd, 0xf3, 0x42, 0xb6, 0xa0, 0x46, 0x01, 0x28, 0xa6, 0x76, 0xf4, 0xd1, 0x75, 0xd9, + 0x07, 0x57, 0x37, 0x11, 0x86, 0x01, 0xfa, 0xfc, 0x3e, 0x4c, 0x03, 0xeb, 0x1d, 0xbf, 0x47, 0x82, 0x42, 0xf7, 0x4d, + 0x14, 0xcf, 0x3c, 0x4c, 0x31, 0xa2, 0xea, 0xe0, 0x4e, 0x07, 0x0f, 0x36, 0x04, 0x02, 0x19, 0x46, 0xe1, 0x28, 0xd7, + 0x4a, 0x32, 0xf7, 0x8a, 0x38, 0x6e, 0xf5, 0x8e, 0x79, 0xb1, 0x6a, 0xd0, 0x6b, 0x58, 0xdc, 0x67, 0x4d, 0xfb, 0x59, + 0xe3, 0xe8, 0xd9, 0xb1, 0x0d, 0xff, 0x3b, 0xac, 0x99, 0x19, 0xbc, 0xe2, 0x2c, 0x0a, 0xd3, 0x69, 0x51, 0x73, 0x5b, + 0xb5, 0x25, 0x63, 0x1f, 0x8b, 0x5a, 0x27, 0xf5, 0x95, 0x46, 0xde, 0x5d, 0x51, 0xa7, 0xb6, 0xc6, 0x34, 0x5a, 0x48, + 0x60, 0xd5, 0x40, 0xe3, 0x87, 0x0b, 0x90, 0xb3, 0x4b, 0x35, 0xe4, 0xd7, 0x7c, 0xb8, 0xc5, 0xb8, 0x58, 0x33, 0xbb, + 0x16, 0x39, 0x14, 0xd4, 0xae, 0x48, 0x9a, 0x7b, 0xef, 0x0c, 0x72, 0x15, 0xa5, 0x8d, 0x39, 0xa7, 0x30, 0x9b, 0x21, + 0x64, 0x9c, 0x62, 0x62, 0x81, 0x3c, 0x5a, 0xa0, 0x34, 0x5e, 0x84, 0x43, 0x0d, 0x7f, 0x7a, 0x83, 0x44, 0xf3, 0x0f, + 0x63, 0x8b, 0x7f, 0x58, 0xc7, 0x55, 0xf3, 0x7a, 0x76, 0x91, 0x5a, 0x3e, 0x11, 0xab, 0xe2, 0x3d, 0x4b, 0x8d, 0x18, + 0xf5, 0xd8, 0xb4, 0xb4, 0xa6, 0xeb, 0x3d, 0xcb, 0x1b, 0x3e, 0x4b, 0x8d, 0xf0, 0x39, 0xe8, 0x3e, 0x5d, 0xfb, 0xc9, + 0x13, 0xaa, 0x75, 0xe0, 0x8a, 0x61, 0x9d, 0x0d, 0x8b, 0xcc, 0x14, 0x8a, 0x37, 0x89, 0x28, 0x39, 0x45, 0x67, 0x68, + 0x44, 0xcf, 0x9f, 0xf7, 0x5c, 0x47, 0x1f, 0xc4, 0xcc, 0xfb, 0x98, 0x89, 0x70, 0xdf, 0x21, 0x66, 0xa1, 0xbd, 0xd8, + 0xcf, 0xd0, 0x48, 0xaf, 0x75, 0xa5, 0x9d, 0xc3, 0x9d, 0xc9, 0x16, 0xee, 0x08, 0x1c, 0x7b, 0x41, 0x86, 0x7a, 0x32, + 0x28, 0xf0, 0x84, 0xc1, 0x8f, 0xa8, 0x93, 0xdf, 0xba, 0x9a, 0x96, 0x6d, 0xd9, 0x6a, 0xde, 0x70, 0xec, 0x4f, 0xdc, + 0x75, 0x94, 0x7a, 0x9d, 0x03, 0xc7, 0x08, 0xa2, 0x09, 0xf8, 0xd1, 0xa5, 0x7e, 0x1a, 0xb0, 0x8e, 0xaa, 0x82, 0x43, + 0xdd, 0x8c, 0xee, 0xe5, 0x19, 0xf7, 0x6e, 0xf0, 0x62, 0x48, 0x4e, 0x1e, 0xdf, 0x09, 0x57, 0x5c, 0x0c, 0x96, 0xfe, + 0x03, 0x10, 0x43, 0x4d, 0xd5, 0x40, 0x36, 0xc0, 0xe2, 0xc4, 0x94, 0xbd, 0x85, 0x3a, 0x0a, 0xb4, 0xd1, 0x55, 0x3e, + 0x88, 0x71, 0xec, 0xcd, 0x20, 0x7b, 0xee, 0x3a, 0x33, 0x38, 0xa6, 0x55, 0x39, 0xaa, 0x55, 0x9c, 0x17, 0xc7, 0x86, + 0xd2, 0x70, 0x0c, 0xc5, 0x06, 0x74, 0xab, 0x66, 0xc6, 0x3a, 0xbb, 0xee, 0xde, 0x67, 0xf0, 0x40, 0xf8, 0xe5, 0x11, + 0x8d, 0x83, 0x4c, 0x1d, 0xb8, 0x2a, 0x29, 0xa5, 0x24, 0x39, 0x9a, 0x94, 0x35, 0xd3, 0x27, 0xa5, 0xe7, 0x25, 0x5b, + 0xa5, 0x3a, 0x68, 0x8e, 0x44, 0x15, 0x5f, 0x5f, 0xa3, 0xc3, 0xb0, 0x1f, 0x2a, 0xfe, 0xa7, 0x4f, 0x9a, 0x0f, 0xce, + 0x4c, 0xae, 0x34, 0x3f, 0xf0, 0xac, 0x97, 0x26, 0xcc, 0x2f, 0xd4, 0xf4, 0x38, 0x59, 0xe0, 0x69, 0x08, 0xff, 0x16, + 0xc5, 0xe2, 0x07, 0x37, 0x93, 0xb0, 0x02, 0x2f, 0x9c, 0x00, 0x4a, 0xf3, 0xc2, 0xc9, 0x86, 0x39, 0x16, 0xf9, 0x3c, + 0x57, 0x4a, 0x8b, 0xae, 0x0a, 0x53, 0xa9, 0xe4, 0xe5, 0xdd, 0xa5, 0x37, 0xf9, 0xd1, 0x9b, 0x31, 0x4d, 0x05, 0x2a, + 0x87, 0x2e, 0xba, 0x85, 0x26, 0xf7, 0xb9, 0xfb, 0xf4, 0x74, 0xc6, 0x52, 0x8f, 0xd4, 0x40, 0x70, 0xf9, 0x05, 0x76, + 0x40, 0xe1, 0x84, 0x86, 0x07, 0xbc, 0x70, 0x29, 0x97, 0x16, 0xd1, 0x09, 0x43, 0xe1, 0x74, 0xca, 0x44, 0x8b, 0x4f, + 0xd7, 0x31, 0xc8, 0xe1, 0x60, 0xe8, 0x61, 0x3e, 0x1d, 0x37, 0x8c, 0xd4, 0xde, 0xd3, 0xdc, 0x37, 0x73, 0xdb, 0x22, + 0x04, 0x7e, 0xf8, 0xf1, 0x2a, 0x66, 0xc1, 0x3f, 0xdd, 0xa7, 0x40, 0xb8, 0x9f, 0x5e, 0xab, 0x7a, 0x37, 0xb5, 0xa6, + 0x31, 0x1b, 0xbb, 0x4f, 0xe1, 0x42, 0xda, 0x41, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xaf, 0x66, 0x81, 0x81, 0xd7, 0x7b, + 0x82, 0x45, 0x6d, 0x36, 0x8a, 0xb8, 0xe6, 0xcd, 0xbd, 0x2e, 0xf5, 0x3d, 0x7e, 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, + 0xc7, 0x76, 0xba, 0x78, 0x7f, 0x1e, 0x04, 0xde, 0xf0, 0x63, 0x97, 0xde, 0x94, 0x1e, 0x4c, 0xa0, 0xd6, 0x43, 0x6f, + 0xde, 0x41, 0xf2, 0x2a, 0x17, 0x82, 0xf7, 0x34, 0x95, 0xe6, 0x9c, 0x5d, 0xed, 0x5e, 0xc6, 0xad, 0xbc, 0xc6, 0x2f, + 0xe3, 0xa7, 0x96, 0x53, 0x3f, 0x65, 0xe2, 0x53, 0xf8, 0x90, 0x65, 0xe2, 0xa2, 0x4e, 0x57, 0x54, 0xbc, 0x58, 0x5b, + 0x4d, 0xc5, 0x69, 0x7f, 0xd7, 0xba, 0x75, 0xec, 0x69, 0xc3, 0xb1, 0xda, 0x1f, 0x9c, 0xf6, 0xb4, 0x69, 0x9d, 0x04, + 0x66, 0xd3, 0x3a, 0x81, 0x3f, 0x1f, 0x4e, 0xac, 0xf6, 0xd4, 0x6c, 0x58, 0x47, 0x1f, 0x9c, 0x46, 0x60, 0xb6, 0xad, + 0x13, 0xf8, 0x73, 0x41, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, + 0x89, 0xbc, 0xd5, 0xe8, 0x75, 0xe7, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0xbb, 0x5a, 0xe8, 0x32, 0x4a, 0x24, 0x2b, + 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0x59, 0x7b, 0x8c, 0x78, 0x9b, 0xfa, 0x0c, 0x96, 0xba, 0xc8, 0x05, 0x8c, + 0xcf, 0x3f, 0xcf, 0x31, 0xfe, 0xba, 0x48, 0xbc, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x89, 0xb6, 0x15, + 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xfc, 0xd6, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, + 0x21, 0x67, 0x9f, 0x1c, 0xf9, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xfa, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, + 0x7c, 0xeb, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x20, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, + 0x9d, 0x16, 0x90, 0xdd, 0x16, 0x6b, 0xee, 0xb4, 0xa9, 0xa4, 0x9b, 0xce, 0x2e, 0xdf, 0xea, 0x22, 0xd3, 0x91, 0xb0, + 0x9b, 0x12, 0x16, 0x1b, 0x5b, 0x0d, 0x3b, 0x37, 0xec, 0x35, 0x20, 0x55, 0x5c, 0xe5, 0xaa, 0xa3, 0xea, 0xdd, 0x50, + 0x98, 0x1f, 0x84, 0x3b, 0x92, 0xbc, 0xf1, 0xbb, 0x98, 0x0a, 0x53, 0xb3, 0x63, 0x1c, 0xf7, 0x38, 0x88, 0xff, 0xa7, + 0x07, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x39, 0xad, 0x25, 0xe7, 0xbd, 0x9c, 0xae, 0x12, 0x41, 0x65, 0xc9, 0x99, + 0x0a, 0x45, 0x6a, 0x47, 0x45, 0xc7, 0x30, 0x35, 0x37, 0x16, 0xcd, 0xa9, 0x45, 0x51, 0x60, 0xf8, 0x98, 0x50, 0x53, + 0x38, 0x8e, 0xea, 0x4f, 0x9e, 0x6c, 0x25, 0x42, 0x64, 0x9c, 0x93, 0xb0, 0x54, 0x30, 0xe8, 0x9a, 0x2a, 0xe3, 0x37, + 0x55, 0x46, 0x31, 0x79, 0xbf, 0x88, 0x35, 0x84, 0x8d, 0x2b, 0xed, 0x3d, 0xfc, 0x39, 0x60, 0x5e, 0x6a, 0x71, 0x65, + 0xa9, 0x26, 0x11, 0x77, 0xc3, 0x61, 0x4d, 0xb0, 0x6e, 0xe5, 0x69, 0x1a, 0x78, 0x1a, 0x94, 0xc7, 0xeb, 0x3f, 0x2f, + 0x78, 0x54, 0x07, 0xe8, 0xe3, 0x93, 0x5d, 0xc4, 0xe1, 0x7c, 0x9b, 0x7a, 0x14, 0x07, 0x4d, 0x26, 0xb9, 0x51, 0xea, + 0x91, 0x3d, 0x87, 0x8f, 0xa1, 0x6b, 0xea, 0x23, 0x72, 0x49, 0x91, 0x1f, 0x7a, 0x6f, 0x2f, 0xbf, 0x51, 0xf8, 0xfe, + 0x27, 0x6b, 0x01, 0xbc, 0xc8, 0x50, 0xbc, 0x19, 0x97, 0xe2, 0xcd, 0x28, 0x3c, 0x93, 0x31, 0xe4, 0x5c, 0xcd, 0x0e, + 0x69, 0x06, 0x51, 0x00, 0x4d, 0x36, 0x14, 0xb3, 0x45, 0x90, 0xfa, 0x73, 0x2f, 0x4e, 0x0f, 0x31, 0xd8, 0x0c, 0x06, + 0xaf, 0xd9, 0x16, 0x0f, 0x82, 0xcc, 0x30, 0x44, 0x76, 0x90, 0x34, 0x14, 0x76, 0x18, 0x63, 0x3f, 0xc8, 0xcd, 0x30, + 0xc4, 0x07, 0xbc, 0xe1, 0x90, 0xcd, 0x53, 0xb7, 0x14, 0xd4, 0x26, 0x1a, 0xa6, 0x2c, 0x35, 0x93, 0x34, 0x66, 0xde, + 0x4c, 0xcd, 0x83, 0x5c, 0x6d, 0xf6, 0x97, 0x2c, 0x06, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, + 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0x2f, 0xa2, 0x49, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x19, 0x26, 0x09, 0xa3, 0x9b, + 0x0c, 0x48, 0x8b, 0x87, 0x51, 0x70, 0xc3, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xde, 0x29, 0xbf, 0xde, 0x2a, 0x18, + 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x06, 0x6d, 0x5b, 0x74, 0x8b, 0x43, 0x5e, 0x19, 0x48, 0x13, 0xf5, 0x8c, 0x99, 0x2c, + 0x09, 0x96, 0x4b, 0x60, 0x84, 0x4a, 0x06, 0x33, 0x53, 0xa7, 0x97, 0xbb, 0x53, 0x22, 0x54, 0xc8, 0x2b, 0x7d, 0xfa, + 0xf4, 0xbe, 0xff, 0xef, 0x7f, 0x41, 0xba, 0xcd, 0xa9, 0x23, 0x62, 0x4a, 0x5c, 0xc9, 0xb5, 0x38, 0xf7, 0x69, 0xf4, + 0xd1, 0x58, 0x8a, 0x8d, 0x44, 0xb4, 0x3f, 0xb1, 0xb5, 0xb2, 0xfe, 0xb5, 0x88, 0x53, 0x07, 0x89, 0x7a, 0x75, 0x11, + 0xf9, 0xa2, 0x0f, 0xcb, 0xdb, 0x17, 0x31, 0x51, 0x94, 0xbf, 0xaf, 0x5e, 0x9e, 0x28, 0x45, 0xf8, 0xc4, 0x3a, 0x8b, + 0x1e, 0xda, 0x43, 0xbd, 0x53, 0x4f, 0x41, 0xa6, 0x05, 0xd9, 0x8f, 0xa4, 0x73, 0x08, 0xc3, 0x9c, 0x46, 0x33, 0x66, + 0xf9, 0xd1, 0xe1, 0x92, 0x0d, 0x4c, 0x6f, 0xee, 0x93, 0x5d, 0x0e, 0xca, 0xdd, 0x14, 0xe2, 0xfc, 0x72, 0x73, 0x17, + 0xe2, 0xaf, 0xb3, 0x62, 0x2a, 0xa3, 0x4a, 0x20, 0xb4, 0x46, 0xa1, 0x07, 0x3c, 0xe2, 0x41, 0xc6, 0x44, 0xcd, 0xde, + 0xe9, 0xa1, 0xd7, 0x2b, 0x67, 0x9e, 0xb1, 0x44, 0x06, 0xd5, 0x32, 0x11, 0x38, 0xa3, 0x04, 0x32, 0x22, 0x57, 0x4c, + 0xf1, 0x60, 0x46, 0xe3, 0xb1, 0x9c, 0x2d, 0xc6, 0x2a, 0x83, 0x97, 0x4f, 0x5a, 0xb1, 0xa5, 0xa3, 0x39, 0x7d, 0x69, + 0xf3, 0x13, 0xf9, 0x4f, 0xb5, 0x83, 0x69, 0xa2, 0x60, 0xcc, 0x70, 0xdc, 0x37, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, + 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x85, 0x73, 0x39, 0x70, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0x58, + 0x93, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x9b, 0x30, 0x1e, 0x7a, 0x62, + 0xfb, 0x95, 0x36, 0x28, 0x6c, 0x3c, 0xbe, 0xee, 0x80, 0xdf, 0x45, 0x3f, 0x15, 0x34, 0xaf, 0x7c, 0x4d, 0x18, 0xdd, + 0x0c, 0xbc, 0xbb, 0x48, 0x32, 0x63, 0xe2, 0x11, 0x4d, 0x2e, 0xb0, 0xf4, 0x52, 0x78, 0x12, 0x6f, 0x1c, 0x34, 0x24, + 0x61, 0x90, 0x75, 0x73, 0xf3, 0xb0, 0x15, 0xf4, 0x37, 0x60, 0xf7, 0x9d, 0x35, 0xb9, 0x6e, 0x79, 0x30, 0x88, 0x3c, + 0xb3, 0xe2, 0x1c, 0x96, 0x5e, 0x22, 0x5a, 0xc8, 0x4e, 0x0f, 0x61, 0x7c, 0x10, 0x85, 0xa5, 0xc4, 0x38, 0xf9, 0x3a, + 0x84, 0x7a, 0xf1, 0x12, 0x32, 0xc5, 0xfa, 0x7e, 0x24, 0x78, 0x3e, 0xbc, 0x58, 0x4a, 0xb9, 0xe4, 0xa5, 0x2a, 0x9b, + 0xbc, 0x8c, 0x5d, 0xcf, 0x04, 0xde, 0x9f, 0xa2, 0xf6, 0xc3, 0x02, 0xf3, 0xd3, 0x66, 0xdd, 0x94, 0x89, 0x20, 0x07, + 0x17, 0xe9, 0x96, 0x38, 0x08, 0xdb, 0xaa, 0x10, 0x3f, 0xbb, 0xa3, 0x42, 0xb1, 0x8f, 0x77, 0xd5, 0x2a, 0x38, 0xa7, + 0xa2, 0x9a, 0xa7, 0xa9, 0x8f, 0x70, 0xc7, 0x6f, 0xd4, 0xc6, 0x52, 0x8c, 0xce, 0x90, 0xba, 0x50, 0x55, 0xc8, 0xe2, + 0xbd, 0xf9, 0x9c, 0x2a, 0xeb, 0xdd, 0xd3, 0x43, 0xba, 0x96, 0xf6, 0x68, 0x87, 0xf5, 0x4e, 0xc1, 0x94, 0x9b, 0x16, + 0xdd, 0x9b, 0xcf, 0xf9, 0x92, 0xd2, 0x2f, 0x7a, 0x73, 0x38, 0x4d, 0x67, 0x41, 0xef, 0x7f, 0x01, 0xb9, 0x4b, 0x40, + 0x75, 0x91, 0x7a, 0x03, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0xa5, 0x72, 0x53, 0x82, 0x27, 0x1b, 0xbc, 0x80, 0x75, 0x03, 0x48, 0xa5, 0xee, 0x7f, 0x2b, 0x0f, 0x47, 0x11, - 0x6c, 0x9c, 0x30, 0x00, 0xbc, 0x78, 0xe3, 0x55, 0x06, 0x02, 0xe7, 0x01, 0x48, 0x39, 0xae, 0xfd, 0x5e, 0x40, 0x55, - 0x4d, 0x39, 0x3a, 0x86, 0x68, 0xb0, 0x4b, 0x00, 0x54, 0x6c, 0xdf, 0xed, 0x57, 0x28, 0x4a, 0x70, 0x44, 0x0e, 0x0a, - 0x69, 0x65, 0x69, 0xd3, 0x0b, 0x32, 0x81, 0x19, 0x99, 0x45, 0x41, 0x5c, 0x10, 0x08, 0x62, 0xa3, 0x51, 0x83, 0xcd, - 0x39, 0x4f, 0x9c, 0xe3, 0x34, 0x65, 0x23, 0x09, 0xb7, 0x1c, 0x9c, 0x0d, 0xdd, 0x8c, 0x40, 0x15, 0x18, 0xc2, 0xe1, - 0x0d, 0x6d, 0x41, 0xba, 0xf2, 0xe0, 0xce, 0x7b, 0x72, 0x4e, 0x34, 0xfe, 0x50, 0x23, 0x59, 0xda, 0x96, 0x63, 0x22, - 0x70, 0xf0, 0x6a, 0xb7, 0x8c, 0x88, 0x6e, 0x48, 0x1a, 0xf6, 0x45, 0xf5, 0xa0, 0xf6, 0x37, 0xf1, 0x4b, 0x22, 0x1c, - 0x2f, 0x73, 0x23, 0x8a, 0x31, 0x70, 0x24, 0x71, 0x67, 0x77, 0x29, 0xa1, 0x7d, 0xad, 0xb1, 0x07, 0x6b, 0x81, 0x56, - 0x9e, 0x58, 0x49, 0x4c, 0x4f, 0x54, 0x3f, 0x88, 0x99, 0x48, 0x93, 0x67, 0x63, 0xed, 0x72, 0xc1, 0x0d, 0x75, 0x3e, - 0x51, 0xff, 0x97, 0xe7, 0x7b, 0xc9, 0x07, 0xd3, 0x4d, 0xf1, 0x33, 0xbf, 0xf5, 0x5a, 0xc7, 0x8d, 0x5a, 0x44, 0x59, - 0xb7, 0xb4, 0xf1, 0x5d, 0x70, 0x1b, 0xcf, 0xdd, 0x66, 0xb5, 0xe0, 0x04, 0x41, 0x10, 0xcb, 0x00, 0xc7, 0x98, 0xa8, - 0x1f, 0x22, 0x6d, 0x84, 0x78, 0xf1, 0x7e, 0x44, 0xdf, 0xfe, 0x4b, 0xb5, 0xff, 0xfa, 0x0d, 0x7b, 0xb6, 0x6e, 0xaf, - 0x4d, 0xcf, 0xbc, 0x4d, 0x53, 0x8c, 0xb3, 0xd8, 0x7b, 0x56, 0xdb, 0x59, 0x59, 0x2a, 0x19, 0xc6, 0x3d, 0xe4, 0x45, - 0x0c, 0x01, 0x1c, 0x00, 0x1d, 0x49, 0xee, 0xa7, 0x7d, 0x9b, 0xf6, 0x9d, 0xee, 0xf3, 0xd8, 0xd6, 0x6f, 0xdb, 0x09, - 0xa9, 0x7d, 0xca, 0xc5, 0xdf, 0x31, 0x02, 0x2b, 0x31, 0x12, 0x63, 0x89, 0x96, 0xfb, 0x2a, 0x67, 0xfd, 0x79, 0x2e, - 0x37, 0x57, 0x8c, 0x46, 0x4e, 0x9e, 0x5a, 0x22, 0xb3, 0x00, 0xef, 0xa9, 0xfe, 0x18, 0x84, 0x77, 0xd9, 0xac, 0xb6, - 0xa9, 0xf6, 0x87, 0xa4, 0x14, 0x52, 0x85, 0x5d, 0x44, 0xc8, 0x19, 0x21, 0xb6, 0x92, 0xef, 0x97, 0xf6, 0x7b, 0x7f, - 0xe6, 0xfb, 0xf5, 0x0d, 0xc7, 0xb9, 0x19, 0x8e, 0x76, 0x1d, 0x86, 0x94, 0x3a, 0x29, 0xb5, 0x39, 0xb2, 0x18, 0x16, - 0x5e, 0x64, 0x69, 0x9f, 0x24, 0x5c, 0xc7, 0xff, 0x7a, 0x5f, 0x57, 0x5f, 0xbf, 0x76, 0x17, 0x2b, 0xce, 0x1d, 0x1d, - 0x29, 0x4b, 0xd8, 0xe7, 0x15, 0x37, 0x3d, 0x19, 0xc2, 0x23, 0xbc, 0x42, 0x91, 0xcc, 0x23, 0xa5, 0x72, 0x19, 0xc7, - 0xea, 0x18, 0xed, 0x1a, 0xd9, 0xa5, 0x56, 0x88, 0x8c, 0xd5, 0xf0, 0xff, 0xf5, 0x35, 0xad, 0xaf, 0x5f, 0x89, 0xb0, - 0xca, 0x5c, 0xea, 0x40, 0xa1, 0x99, 0xfd, 0x3d, 0x92, 0x9c, 0x65, 0xd9, 0x3d, 0x15, 0x82, 0x96, 0x69, 0x1b, 0x2f, - 0xe0, 0x00, 0x7a, 0xcd, 0xba, 0xf7, 0xbe, 0xaa, 0xfe, 0xfb, 0xe7, 0x0b, 0xa1, 0x3b, 0x44, 0x1b, 0xb8, 0xdc, 0x1d, - 0x26, 0x4b, 0x33, 0x6b, 0xaa, 0xe9, 0xce, 0xd8, 0x14, 0x05, 0x4a, 0x4c, 0x25, 0xca, 0x8f, 0x80, 0x95, 0x49, 0x4b, - 0x5d, 0x55, 0x94, 0xce, 0x7e, 0x48, 0x05, 0x65, 0x53, 0x36, 0x34, 0xc3, 0xb6, 0x75, 0xea, 0xfb, 0x93, 0xcc, 0xf7, - 0x13, 0x5e, 0x90, 0x8d, 0x0d, 0xcd, 0xb7, 0x2f, 0x4f, 0xd7, 0x71, 0x23, 0x2d, 0xb0, 0xc4, 0x22, 0xbd, 0x6f, 0x90, - 0x13, 0xa5, 0x12, 0xf3, 0x3f, 0xdc, 0x72, 0xe2, 0x12, 0x88, 0xd6, 0x66, 0x6f, 0x0b, 0xf1, 0x8a, 0x2f, 0x12, 0x3d, - 0x1f, 0x44, 0x3c, 0x4d, 0x2d, 0x5f, 0x6f, 0xfb, 0x25, 0x5f, 0xa5, 0x73, 0x29, 0x2f, 0xa5, 0x58, 0x49, 0x37, 0x57, - 0xba, 0xc0, 0xbb, 0xb7, 0xa9, 0x44, 0x69, 0x3a, 0xb0, 0x81, 0x1c, 0x8a, 0xa4, 0x8c, 0x2d, 0x50, 0xd8, 0x7b, 0x7f, - 0x3f, 0xfb, 0xaf, 0x5f, 0x9d, 0x5a, 0x9c, 0x39, 0x0c, 0x22, 0xde, 0x77, 0x34, 0xb0, 0x8f, 0xc7, 0x5b, 0xad, 0x1b, - 0x35, 0xc6, 0xec, 0xd2, 0xe0, 0x25, 0x51, 0xdb, 0xd3, 0x70, 0xcc, 0x65, 0x55, 0x7d, 0x8a, 0x0a, 0x8d, 0x18, 0x42, - 0x97, 0x67, 0xbf, 0xcf, 0x64, 0x1f, 0xd3, 0x0d, 0xcc, 0x60, 0xd8, 0xc8, 0x73, 0x82, 0x71, 0xbd, 0x10, 0xd1, 0xd6, - 0x60, 0xa9, 0xda, 0x8a, 0x21, 0x49, 0x97, 0xed, 0x91, 0x5d, 0x78, 0x51, 0xf6, 0x07, 0x7f, 0xeb, 0x3c, 0x3c, 0x12, - 0x95, 0x0f, 0x0f, 0xc9, 0x07, 0xd4, 0xea, 0x1b, 0x7e, 0xdf, 0xd7, 0xa6, 0x7b, 0x97, 0xc9, 0x61, 0x2b, 0xf1, 0x2f, - 0x8d, 0x52, 0x01, 0x68, 0x0b, 0xe0, 0x51, 0x80, 0x2e, 0x45, 0x3d, 0x35, 0x58, 0xfe, 0xff, 0xde, 0x4a, 0xcb, 0xed, - 0x8f, 0xb4, 0x20, 0xda, 0x01, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xca, 0x02, 0x5b, 0x0d, 0x90, 0xec, 0x71, - 0x66, 0x25, 0xad, 0xb5, 0xd8, 0x54, 0x5c, 0xf3, 0x2e, 0xf3, 0xbb, 0xe8, 0x8c, 0x1f, 0x86, 0x15, 0x26, 0xb3, 0x91, - 0xae, 0x9a, 0x65, 0x1b, 0x59, 0x4e, 0x03, 0x80, 0xe0, 0x7d, 0xef, 0xff, 0x28, 0xfc, 0xff, 0x23, 0x8b, 0xf3, 0x23, - 0xb2, 0x40, 0x45, 0x66, 0x15, 0xe7, 0x64, 0x15, 0x30, 0xa3, 0x2a, 0x90, 0x33, 0x2a, 0x80, 0x7d, 0x74, 0x40, 0x8e, - 0x13, 0xbd, 0xa6, 0xe9, 0x8e, 0x86, 0x94, 0xf7, 0x3b, 0x2d, 0x56, 0x6c, 0xca, 0xfb, 0xdd, 0x0e, 0x94, 0x35, 0x4b, - 0x69, 0xa5, 0xa3, 0xff, 0xd5, 0x99, 0xeb, 0x3f, 0xd6, 0x5d, 0x11, 0x26, 0x5f, 0x27, 0xdd, 0x30, 0x6c, 0xf1, 0xff, - 0x92, 0x41, 0x72, 0x1a, 0x60, 0x39, 0x28, 0x17, 0xe5, 0x94, 0xec, 0x32, 0x8d, 0x1d, 0xbb, 0xad, 0xc4, 0xc3, 0xc6, - 0x63, 0x5f, 0xd5, 0x1f, 0xc3, 0xef, 0xe1, 0x68, 0x41, 0x98, 0x3a, 0xd3, 0x34, 0xfd, 0x77, 0xfb, 0x63, 0xd9, 0xf7, - 0x3a, 0x3d, 0xe7, 0xe8, 0xef, 0xac, 0x42, 0x08, 0x24, 0x04, 0x14, 0x84, 0x60, 0xdd, 0xd9, 0x46, 0xb5, 0x2a, 0x5d, - 0x6d, 0xdd, 0x71, 0xd5, 0xaa, 0x69, 0xbe, 0x86, 0x3f, 0x04, 0x08, 0x81, 0x99, 0xbb, 0xc7, 0x70, 0x76, 0x39, 0x03, - 0x11, 0x09, 0xd1, 0x7f, 0x8f, 0x53, 0xca, 0x99, 0xd2, 0x83, 0xb4, 0x05, 0x42, 0xa4, 0xc6, 0x6b, 0x7b, 0xfd, 0xfd, - 0xf3, 0x78, 0xb9, 0x45, 0x74, 0x52, 0xdf, 0x2b, 0xd0, 0x1e, 0xa1, 0xed, 0x1f, 0x89, 0xa7, 0x3c, 0xe4, 0x11, 0xaf, - 0x04, 0x8b, 0x4d, 0xd2, 0xd5, 0x70, 0x9f, 0x00, 0x57, 0xf8, 0x16, 0x97, 0xb6, 0x76, 0x97, 0x9b, 0xac, 0xc5, 0x35, - 0x13, 0x6c, 0xee, 0x2c, 0x26, 0xce, 0x2d, 0x0e, 0x10, 0x4e, 0xc7, 0x88, 0xb6, 0xe0, 0x32, 0xd0, 0x1c, 0xe7, 0x0e, - 0x7e, 0xf9, 0xbc, 0x10, 0x4c, 0xa3, 0x3d, 0x94, 0x6c, 0xc7, 0x28, 0xc4, 0x14, 0x44, 0x9e, 0x17, 0xce, 0xde, 0x7d, - 0x60, 0x72, 0x3f, 0xa5, 0x62, 0x30, 0x0b, 0xa3, 0x27, 0x2c, 0x19, 0x68, 0x5a, 0x2f, 0xf9, 0x15, 0x80, 0x77, 0xf8, - 0x2e, 0x9c, 0xb0, 0x08, 0x94, 0xf1, 0xed, 0x17, 0xdc, 0x67, 0x18, 0x3f, 0x0b, 0xd3, 0xce, 0x0a, 0x75, 0xf0, 0x40, - 0xe0, 0xfd, 0xba, 0xf1, 0x8c, 0x5f, 0x28, 0x37, 0xec, 0x96, 0x61, 0xe6, 0x91, 0xce, 0x2f, 0xa7, 0xe8, 0x0a, 0x49, - 0x95, 0x0b, 0x62, 0xcf, 0x3d, 0x2e, 0xcd, 0xf9, 0x8f, 0x68, 0x79, 0x19, 0xb8, 0xa3, 0x37, 0x81, 0x98, 0xfa, 0x7b, - 0xeb, 0xaa, 0xd9, 0xde, 0x69, 0x11, 0x00, 0x48, 0xae, 0x5d, 0x1c, 0x66, 0xb4, 0x2d, 0xae, 0xaf, 0xe5, 0xd5, 0x6e, - 0xbc, 0x95, 0x7a, 0x98, 0xa0, 0x21, 0xd9, 0x30, 0x83, 0x33, 0xdb, 0x7f, 0x78, 0xf9, 0xf6, 0xda, 0x62, 0x5c, 0x46, - 0xcd, 0xfe, 0x3a, 0xad, 0x6d, 0xe8, 0x48, 0x1b, 0x90, 0xc3, 0x5d, 0xe9, 0xfa, 0x90, 0x52, 0x50, 0xd8, 0xb0, 0xc9, - 0xe0, 0xb9, 0xe8, 0x8e, 0xfb, 0x98, 0xd4, 0x12, 0x93, 0x75, 0x39, 0xe7, 0xd2, 0x00, 0xb3, 0x99, 0xbd, 0xbd, 0x76, - 0xa5, 0x01, 0x77, 0xf8, 0x71, 0xb7, 0x3f, 0x32, 0xb9, 0x17, 0x4d, 0xfc, 0x62, 0xc6, 0xe5, 0x71, 0x08, 0xec, 0xed, - 0x8f, 0xb4, 0xaf, 0x16, 0x34, 0x9b, 0x5b, 0x3f, 0xe6, 0x1b, 0x5f, 0x76, 0xd7, 0xa3, 0x08, 0x1a, 0x9a, 0x7c, 0x69, - 0xd0, 0xbc, 0x68, 0x7a, 0xf5, 0x19, 0xb5, 0x42, 0x7d, 0xe3, 0x27, 0x52, 0x78, 0xec, 0x26, 0xf1, 0xd7, 0x2e, 0xb7, - 0xef, 0x7e, 0xf7, 0x38, 0x78, 0xf4, 0x45, 0x0c, 0x2f, 0xdf, 0x5e, 0x3f, 0x6e, 0x9e, 0xe1, 0x39, 0xa3, 0x3a, 0x6c, - 0x86, 0x84, 0xa1, 0xe6, 0xf7, 0x5f, 0x32, 0xcc, 0xbe, 0x2c, 0x7b, 0x32, 0xab, 0xcb, 0x7f, 0xee, 0xeb, 0x23, 0x3e, - 0xa8, 0x5d, 0x3e, 0xe3, 0xd7, 0x3f, 0x10, 0x9e, 0xfe, 0x8b, 0xa4, 0x87, 0x75, 0x87, 0xf6, 0x67, 0x7d, 0x33, 0x7e, - 0xec, 0xaa, 0xb0, 0xef, 0xc3, 0x7c, 0x43, 0x68, 0x7b, 0x1e, 0x53, 0xd3, 0x2b, 0x51, 0xc1, 0x44, 0x1c, 0x07, 0x21, - 0x18, 0xb5, 0x75, 0x7a, 0x6b, 0x06, 0xe7, 0xf6, 0x0c, 0xc6, 0xec, 0xb6, 0x5a, 0x2c, 0x6d, 0x08, 0x6f, 0xe6, 0xc3, - 0xae, 0x8f, 0x0b, 0xf4, 0x17, 0x58, 0x8c, 0x21, 0xed, 0xfa, 0xfe, 0x4a, 0x5f, 0xad, 0x2c, 0xcb, 0x00, 0x40, 0x60, - 0xa8, 0x67, 0xc3, 0xd1, 0xb3, 0x44, 0xc6, 0x3c, 0x9b, 0xcf, 0x0d, 0xe9, 0x32, 0xf4, 0xc8, 0xf5, 0x4d, 0xb7, 0x06, - 0x0d, 0x2f, 0x16, 0x6c, 0xc0, 0x57, 0x2b, 0x05, 0xeb, 0x15, 0x16, 0xe4, 0xce, 0x59, 0x71, 0x7f, 0x0f, 0xa5, 0x66, - 0x4d, 0xc4, 0x72, 0xdc, 0x4a, 0x0e, 0xf2, 0xbe, 0x8f, 0x30, 0xd2, 0xd8, 0xd7, 0xf6, 0xd6, 0x8b, 0xeb, 0x3b, 0xa8, - 0x08, 0x7b, 0x28, 0xf7, 0xb2, 0x4a, 0x41, 0x6c, 0xef, 0x18, 0xd2, 0xb3, 0x7c, 0xdc, 0xd7, 0xd7, 0x6e, 0xe6, 0x84, - 0x0f, 0x46, 0x23, 0x43, 0x19, 0x37, 0xd6, 0xe4, 0x89, 0xd8, 0x8f, 0xab, 0x94, 0xe6, 0x31, 0xca, 0x0f, 0x3a, 0xf2, - 0x42, 0x8c, 0xc6, 0xa4, 0x17, 0xec, 0x3b, 0x59, 0x0a, 0x8d, 0xe3, 0xbc, 0x24, 0x1e, 0x6b, 0x71, 0x44, 0x0a, 0x68, - 0x14, 0x1f, 0xc8, 0x66, 0x46, 0x24, 0x40, 0xd5, 0x22, 0xed, 0x2c, 0x9c, 0x44, 0x2d, 0x4e, 0xb4, 0xc1, 0x7b, 0xbf, - 0xdf, 0x71, 0xe7, 0xa4, 0x84, 0x8b, 0x2f, 0x2e, 0xdb, 0x9e, 0x26, 0xe4, 0xe1, 0x97, 0x72, 0xb2, 0xe6, 0x89, 0x9e, - 0x92, 0x5b, 0x1e, 0xb1, 0xa9, 0xb0, 0x4c, 0xc6, 0x42, 0x0f, 0x14, 0x87, 0x6e, 0x99, 0x57, 0xf1, 0x8e, 0x2f, 0x9f, - 0xe1, 0x6a, 0xf7, 0x9b, 0xef, 0x2d, 0x5f, 0xcb, 0xcc, 0x57, 0xeb, 0x1e, 0xd0, 0xf8, 0xe0, 0x04, 0x9e, 0xb2, 0xbb, - 0x6f, 0xbc, 0x9b, 0xbc, 0x06, 0x78, 0xf9, 0xdc, 0x2f, 0x51, 0xbe, 0xa8, 0xfd, 0x86, 0xe8, 0x35, 0x80, 0xc0, 0x03, - 0x91, 0x6c, 0xc5, 0xd4, 0x5b, 0x4e, 0x64, 0x72, 0xff, 0x3e, 0xc3, 0x36, 0x7c, 0xf2, 0x6e, 0x1d, 0xaa, 0xa4, 0xb1, - 0x12, 0x9e, 0x49, 0xeb, 0x77, 0xaa, 0xf6, 0x39, 0x12, 0x18, 0x7b, 0x15, 0xcc, 0xb0, 0x3b, 0x86, 0x98, 0x9d, 0xa4, - 0x70, 0xdc, 0x17, 0x1b, 0x2c, 0xf3, 0x9b, 0x99, 0x43, 0xb7, 0x34, 0x3e, 0x86, 0x3b, 0x19, 0xab, 0xb4, 0x4d, 0xa5, - 0x71, 0xd7, 0xf8, 0x1b, 0x82, 0xc0, 0x55, 0x87, 0xda, 0xa3, 0x49, 0xbf, 0x64, 0x5f, 0x70, 0x1d, 0x9c, 0x09, 0x7a, - 0x59, 0x0e, 0x56, 0xb8, 0x54, 0x83, 0xe5, 0xad, 0x8f, 0x00, 0x02, 0x61, 0x5b, 0x10, 0xc2, 0x06, 0xdb, 0x6b, 0xe9, - 0x58, 0x8d, 0x9c, 0xb1, 0x79, 0xff, 0xf1, 0x66, 0x89, 0x1e, 0xca, 0x16, 0x4e, 0x53, 0x7d, 0x29, 0x6b, 0xb5, 0xdf, - 0xbb, 0x7f, 0xbe, 0xef, 0x00, 0x07, 0x09, 0xc3, 0x0b, 0x3a, 0x38, 0xfe, 0x1a, 0xbd, 0x15, 0x8b, 0x60, 0x61, 0xb4, - 0x6d, 0x7d, 0xf6, 0xed, 0xa1, 0x78, 0x66, 0x41, 0x7c, 0x33, 0x6b, 0xb7, 0xae, 0x2a, 0x8e, 0xb0, 0x55, 0xc3, 0x26, - 0x84, 0xd6, 0x10, 0x01, 0x98, 0xfa, 0x4b, 0x8d, 0x7c, 0xb7, 0x0d, 0xab, 0x4e, 0x45, 0x14, 0xdb, 0xaa, 0x10, 0x47, - 0x50, 0xc9, 0xc1, 0xa0, 0x8a, 0x42, 0x17, 0x76, 0x0f, 0x7e, 0xe2, 0x64, 0x5c, 0x50, 0xdc, 0x54, 0x3c, 0x7a, 0x7e, - 0x0b, 0x94, 0x81, 0xa9, 0xbf, 0x5c, 0x69, 0xef, 0x0f, 0x90, 0x3e, 0xd8, 0xc3, 0x4e, 0xc9, 0xe7, 0x2a, 0x9e, 0xd0, - 0x77, 0x27, 0x34, 0x81, 0xe1, 0xe1, 0xd8, 0x9b, 0xc4, 0x07, 0x12, 0xf0, 0xa0, 0x60, 0x41, 0xbe, 0xbf, 0x13, 0xea, - 0xa6, 0x4f, 0x03, 0x02, 0x88, 0xaf, 0xaa, 0xe3, 0x70, 0x84, 0x60, 0x45, 0x1d, 0x0b, 0xec, 0x89, 0x8a, 0x53, 0x72, - 0x44, 0x86, 0x71, 0x82, 0xfa, 0x06, 0xe8, 0xe6, 0x53, 0xa5, 0xfc, 0x0b, 0xb7, 0x9b, 0x44, 0xe2, 0x59, 0xdf, 0x2a, - 0xda, 0x65, 0xa4, 0x48, 0xe0, 0x8d, 0x58, 0x47, 0x95, 0x42, 0xe9, 0x06, 0xcb, 0x94, 0x22, 0x4e, 0xd3, 0xe0, 0xfa, - 0xd2, 0x4b, 0xbd, 0xd6, 0x4e, 0x2d, 0xfd, 0x7a, 0xdd, 0x04, 0xfa, 0x1a, 0x0f, 0x59, 0xf0, 0xa5, 0xfa, 0xa9, 0x26, - 0xb0, 0x1b, 0x68, 0x3b, 0x97, 0xda, 0x9f, 0xa1, 0x71, 0xb2, 0xa1, 0x7d, 0x2d, 0x6f, 0x21, 0x80, 0x29, 0xdc, 0xa0, - 0xb6, 0xbc, 0x48, 0xa6, 0x76, 0x22, 0x66, 0x7f, 0x6c, 0x22, 0x99, 0x20, 0xaf, 0x1c, 0x6c, 0x68, 0x1f, 0xda, 0xc2, - 0xf3, 0xa0, 0x04, 0xc3, 0xcf, 0x5a, 0xca, 0xc0, 0x8a, 0xb0, 0xad, 0xed, 0xd7, 0xc7, 0xb0, 0x09, 0xa6, 0x0c, 0x82, - 0x50, 0x7f, 0x09, 0xda, 0x69, 0x30, 0x79, 0xd4, 0x63, 0xc6, 0x3e, 0x9b, 0x39, 0xdf, 0x83, 0x1e, 0xa5, 0x92, 0x85, - 0x20, 0x39, 0x0c, 0xf4, 0xd7, 0x62, 0x62, 0x1c, 0xa1, 0x42, 0x22, 0xb4, 0x5b, 0x25, 0x03, 0xf7, 0x1f, 0x54, 0x0c, - 0x11, 0x76, 0x54, 0x9d, 0x4b, 0xb3, 0x6b, 0x54, 0x31, 0x50, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x23, 0x84, 0xd3, 0xa6, - 0xf6, 0xce, 0x5d, 0x24, 0xd2, 0x53, 0x29, 0x62, 0xb1, 0x71, 0x56, 0xba, 0xd4, 0x0c, 0x6b, 0x61, 0x2c, 0x27, 0x46, - 0xd0, 0x38, 0x73, 0x47, 0x54, 0xc7, 0xb7, 0xac, 0x61, 0x04, 0xb8, 0x47, 0xec, 0xb6, 0x07, 0xad, 0x00, 0xb9, 0x26, - 0x69, 0xa0, 0xa0, 0xbd, 0x31, 0x21, 0x8b, 0x02, 0x19, 0x19, 0x93, 0xe8, 0x46, 0x50, 0x72, 0xf7, 0x75, 0x24, 0x8f, - 0x01, 0x76, 0xe5, 0x64, 0x3d, 0x43, 0x24, 0xc4, 0xf1, 0xa6, 0x56, 0x04, 0x81, 0xb1, 0x0c, 0xb0, 0x63, 0xe9, 0xa8, - 0xe4, 0x5c, 0xdc, 0xa0, 0xa7, 0xaa, 0x99, 0x5f, 0xd8, 0xf5, 0x19, 0x8a, 0x34, 0xa2, 0x5d, 0x40, 0x40, 0xce, 0x5c, - 0x75, 0x1d, 0x18, 0x39, 0x48, 0x5c, 0xa3, 0x3b, 0xad, 0x90, 0x51, 0x44, 0x3e, 0x2e, 0x86, 0xe5, 0x05, 0xe4, 0x46, - 0x5c, 0x6c, 0x94, 0x65, 0xc8, 0x45, 0x1f, 0xb9, 0x0d, 0xde, 0xb9, 0xd1, 0x93, 0xae, 0x13, 0x96, 0x00, 0xac, 0xc7, - 0xb2, 0x98, 0x70, 0xab, 0xa6, 0x67, 0xbf, 0x01, 0x9a, 0x04, 0x5e, 0x3b, 0xea, 0x1c, 0xe2, 0xf8, 0x42, 0x8d, 0x6c, - 0xf0, 0x6f, 0x6a, 0x94, 0xb0, 0xb6, 0x0d, 0x2b, 0x67, 0x9c, 0x56, 0x51, 0xec, 0xb1, 0xf2, 0x4c, 0xc4, 0xfc, 0x05, - 0xa3, 0xe8, 0x34, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x85, 0x88, 0x3d, 0x02, 0x4d, 0x81, 0x7d, - 0x6f, 0x28, 0x4c, 0xeb, 0x23, 0xc9, 0x49, 0xda, 0x53, 0x74, 0x36, 0x67, 0xc3, 0x0c, 0xb1, 0x8b, 0x80, 0x6e, 0xcf, - 0xb9, 0x0e, 0x57, 0xf6, 0x45, 0x29, 0x3c, 0x25, 0x33, 0x6a, 0x09, 0x26, 0xc2, 0x64, 0x78, 0x95, 0x5d, 0x20, 0xf2, - 0xde, 0xa6, 0x99, 0x49, 0xef, 0xe9, 0x95, 0xfb, 0x13, 0x40, 0x1e, 0xf7, 0xe4, 0x7d, 0xa6, 0x29, 0xc3, 0x15, 0x0e, - 0x41, 0x6d, 0x57, 0xcc, 0x63, 0xb9, 0x4d, 0xad, 0x4a, 0x6e, 0x38, 0xe0, 0x62, 0x21, 0x35, 0xee, 0xee, 0x6a, 0x73, - 0x42, 0x03, 0x48, 0x55, 0x4b, 0x67, 0x83, 0xe7, 0x80, 0xe2, 0x3d, 0x01, 0x44, 0x22, 0x1a, 0x85, 0xef, 0xfc, 0x28, - 0x47, 0xe7, 0x24, 0x21, 0x14, 0xe6, 0xea, 0x76, 0x5e, 0x7e, 0xa6, 0x94, 0x59, 0x6e, 0x38, 0x3a, 0x00, 0xd8, 0xa2, - 0x7d, 0x51, 0xf8, 0x3c, 0x02, 0xf9, 0xff, 0xa4, 0xb0, 0xf1, 0xad, 0x69, 0xc7, 0x54, 0xf5, 0x6c, 0x56, 0xe7, 0x61, - 0x81, 0xe7, 0x38, 0x65, 0x82, 0xe7, 0xdf, 0x56, 0x77, 0x43, 0xd4, 0xf9, 0xa7, 0xd8, 0x01, 0x5b, 0x6d, 0xb3, 0xbb, - 0x1d, 0xbc, 0xae, 0x16, 0x27, 0x87, 0x4c, 0xaa, 0xce, 0xf6, 0xc1, 0x37, 0xfb, 0xe9, 0x5f, 0x4e, 0x7e, 0x33, 0xc6, - 0x02, 0xc8, 0xab, 0x82, 0xaa, 0xc8, 0xc8, 0x74, 0x40, 0x89, 0x57, 0x86, 0xcf, 0xc5, 0x00, 0x2d, 0x32, 0xaf, 0x5a, - 0x09, 0x14, 0x9a, 0xd5, 0x88, 0xf2, 0x06, 0x10, 0x64, 0x2b, 0xd4, 0x5c, 0xa3, 0xe0, 0x08, 0x79, 0xd2, 0x62, 0x63, - 0xde, 0xb0, 0x52, 0x8b, 0x66, 0x99, 0xb6, 0xa6, 0xc8, 0x22, 0xb0, 0x38, 0x20, 0xae, 0xbf, 0xa0, 0x75, 0x36, 0x30, - 0x95, 0xe7, 0x83, 0x11, 0x06, 0xd8, 0x0d, 0x37, 0x92, 0x4d, 0x8c, 0xbd, 0x12, 0x8a, 0x9c, 0x06, 0xd2, 0xd8, 0x8f, - 0xef, 0xae, 0xe5, 0xed, 0xae, 0x25, 0xa6, 0xbe, 0x3c, 0x9c, 0x18, 0x4d, 0x0c, 0x2d, 0xed, 0x86, 0xa5, 0x87, 0xa8, - 0x9f, 0x9d, 0xcc, 0x4c, 0x39, 0x5b, 0x7b, 0x0c, 0x0f, 0x5d, 0xe7, 0x92, 0xbc, 0x7f, 0x36, 0x03, 0x01, 0xf9, 0xad, - 0xc0, 0x1a, 0xd0, 0x26, 0x11, 0x45, 0x20, 0x1c, 0xe4, 0xf4, 0x2d, 0x71, 0xf4, 0x37, 0x03, 0x4b, 0x76, 0x3d, 0xd4, - 0x2d, 0x75, 0x8b, 0xb1, 0xac, 0x95, 0x95, 0x53, 0x50, 0x71, 0xe9, 0x99, 0x8c, 0x79, 0x20, 0xd9, 0xa0, 0x6a, 0xb0, - 0x92, 0x7d, 0xde, 0x2e, 0x1c, 0xa8, 0xa4, 0x90, 0xbd, 0x9f, 0x06, 0x79, 0x71, 0x7a, 0x91, 0xac, 0x56, 0x62, 0x8c, - 0x47, 0xa9, 0xb6, 0xb9, 0x0e, 0x88, 0xab, 0x0e, 0x6d, 0xe0, 0xc5, 0x85, 0xed, 0x76, 0xbb, 0x66, 0xab, 0x80, 0xac, - 0x95, 0x4e, 0xe4, 0x66, 0x16, 0x9d, 0xef, 0x2d, 0x22, 0x9d, 0xb5, 0xe5, 0x21, 0x2f, 0xe7, 0xb1, 0x0d, 0xb2, 0xe8, - 0x96, 0xf0, 0xc2, 0x98, 0xb0, 0x81, 0xe5, 0xee, 0xdb, 0xf8, 0x82, 0x43, 0x21, 0x29, 0xd3, 0xd3, 0x4c, 0xbb, 0x37, - 0xc4, 0x7c, 0x57, 0x4d, 0xb4, 0xc2, 0x16, 0xcc, 0x75, 0xf0, 0x8b, 0x64, 0xb5, 0x97, 0xa2, 0x5a, 0x3a, 0x1f, 0x66, - 0xef, 0xd2, 0x91, 0xda, 0xcb, 0x00, 0xd5, 0x4e, 0x63, 0x33, 0x8e, 0x73, 0x02, 0xfa, 0x28, 0x98, 0x59, 0xe1, 0x25, - 0x20, 0xbb, 0x48, 0x61, 0x85, 0x95, 0xba, 0xcd, 0x18, 0x96, 0x52, 0xf7, 0xc3, 0x44, 0x67, 0x19, 0x62, 0xe3, 0x49, - 0x5f, 0x1a, 0x7b, 0x34, 0x8a, 0x47, 0xa8, 0x22, 0xaa, 0xdd, 0x1f, 0x21, 0x4c, 0x48, 0x75, 0x86, 0x27, 0x30, 0xed, - 0xf9, 0x08, 0x1d, 0x17, 0x30, 0xbf, 0x98, 0x85, 0x76, 0xfb, 0x7a, 0x8b, 0x58, 0x78, 0xf5, 0x21, 0xc5, 0x35, 0xa5, - 0xb7, 0xf2, 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x58, 0xa1, 0x68, 0x34, 0x1f, - 0xee, 0x36, 0x03, 0x6c, 0x86, 0xa0, 0x44, 0x42, 0x71, 0x63, 0x98, 0xc5, 0x30, 0x63, 0x0d, 0x4c, 0xee, 0x16, 0xdd, - 0x9c, 0x64, 0xcd, 0x9d, 0x4c, 0x72, 0xe6, 0xbb, 0x9f, 0x18, 0xe5, 0xc6, 0x31, 0xc5, 0x5e, 0xc7, 0x57, 0x35, 0x59, - 0x5d, 0xab, 0xe9, 0x2d, 0xae, 0x9c, 0x10, 0xb4, 0xce, 0xe2, 0x3e, 0xad, 0x5d, 0x62, 0x02, 0xd8, 0x0a, 0xec, 0x4e, - 0x55, 0x24, 0x15, 0xf4, 0xa1, 0x31, 0xcc, 0x1d, 0x0c, 0x27, 0xb6, 0xa1, 0x92, 0xb5, 0x1c, 0x1d, 0xc4, 0xb6, 0x7f, - 0x1f, 0xe4, 0x0c, 0xe8, 0xf8, 0xed, 0x64, 0x4c, 0x85, 0x40, 0xcd, 0x22, 0xad, 0x2e, 0x43, 0xba, 0x14, 0xe2, 0x5a, - 0x59, 0x5e, 0x08, 0x92, 0xbc, 0x4f, 0xcc, 0x25, 0xca, 0xdb, 0x61, 0xea, 0x35, 0xac, 0xcb, 0x0e, 0x48, 0xa3, 0x17, - 0xaa, 0xf2, 0x1b, 0x16, 0xe1, 0x48, 0x13, 0x26, 0x6b, 0x67, 0x20, 0xe6, 0x35, 0x6a, 0x33, 0x45, 0xc6, 0xaa, 0x03, - 0x47, 0xa0, 0x1c, 0x9d, 0x97, 0x8d, 0xf5, 0x53, 0xb3, 0x46, 0x6f, 0x28, 0x0c, 0x6c, 0xcf, 0x73, 0x49, 0x19, 0x48, - 0x63, 0x2c, 0x84, 0x1b, 0x93, 0x4e, 0x15, 0xd4, 0x03, 0xd9, 0xb3, 0xbe, 0xc0, 0x78, 0x96, 0x98, 0xf0, 0x9d, 0x03, - 0x8e, 0xe7, 0xcb, 0x48, 0x2f, 0x5d, 0x13, 0xad, 0x68, 0x65, 0x21, 0xfe, 0xec, 0x64, 0xd6, 0x96, 0xb9, 0x0e, 0x7c, - 0x05, 0xa0, 0x3a, 0x99, 0x0a, 0x2a, 0x51, 0x25, 0x95, 0x50, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x6a, 0xac, 0xbc, 0x71, - 0xef, 0x46, 0x86, 0x3f, 0x7b, 0x03, 0x4b, 0xeb, 0xae, 0xf0, 0xc1, 0xd9, 0x5f, 0x65, 0x90, 0x22, 0xed, 0x99, 0xb1, - 0x1b, 0x1b, 0xf3, 0xcc, 0x91, 0xd7, 0xd7, 0x8e, 0x89, 0xff, 0x5d, 0xb8, 0x63, 0x92, 0xdd, 0x7b, 0x14, 0x32, 0xb6, - 0xe5, 0x80, 0xa8, 0xdb, 0x3a, 0x0e, 0x47, 0x6a, 0xf8, 0x93, 0x9c, 0xe2, 0x3f, 0xae, 0x82, 0xa8, 0x5d, 0x69, 0x21, - 0xf9, 0x48, 0xcf, 0x21, 0x6b, 0x30, 0x9a, 0x34, 0x26, 0x30, 0xde, 0x03, 0xa3, 0x4c, 0x88, 0x89, 0x18, 0xdd, 0x84, - 0x09, 0x67, 0x9e, 0x01, 0xfe, 0xd2, 0x94, 0x85, 0x6d, 0x11, 0xb0, 0xdb, 0xc5, 0x6c, 0x2f, 0x3a, 0x4c, 0x18, 0xe4, - 0xdd, 0xe5, 0x0b, 0xf9, 0x47, 0xe2, 0x61, 0x73, 0xd9, 0xdf, 0xf2, 0x52, 0x44, 0x89, 0x2a, 0x42, 0x98, 0x06, 0x09, - 0x0d, 0x75, 0x56, 0x14, 0x69, 0xcc, 0x10, 0x6b, 0x98, 0xe3, 0x27, 0x1b, 0x45, 0x48, 0x85, 0x50, 0x28, 0x02, 0xd1, - 0x19, 0x22, 0x8c, 0x9c, 0x27, 0x0c, 0xf0, 0xae, 0x01, 0xd0, 0x12, 0xb4, 0x63, 0xc8, 0x96, 0x5b, 0x27, 0x84, 0x16, - 0x73, 0x89, 0xdf, 0xe7, 0x52, 0xca, 0x52, 0x7d, 0xad, 0x2e, 0x0b, 0xee, 0x25, 0x57, 0x2a, 0x6e, 0xa0, 0xe8, 0x28, - 0x9e, 0x86, 0x0f, 0x4c, 0x4d, 0x1f, 0xa5, 0x53, 0x1b, 0x6b, 0x9a, 0x27, 0xce, 0x39, 0xb2, 0x1f, 0xa8, 0xbb, 0xb9, - 0x3b, 0x41, 0xdc, 0xa9, 0x2a, 0xa1, 0x2c, 0xc3, 0x4d, 0xb7, 0x4c, 0x97, 0x92, 0x1a, 0x2e, 0xda, 0x92, 0xfc, 0xb6, - 0x29, 0x3e, 0x78, 0xc3, 0xf1, 0xe9, 0x7d, 0xc1, 0xec, 0x36, 0x3f, 0x7e, 0x32, 0x37, 0x02, 0xb3, 0xe0, 0xd1, 0xcd, - 0xc3, 0x1b, 0x36, 0x50, 0xc0, 0x8e, 0x04, 0x86, 0xae, 0x78, 0xa3, 0x35, 0xf1, 0x48, 0x63, 0x3d, 0x38, 0x78, 0x4f, - 0x79, 0x18, 0xb7, 0xa4, 0x8b, 0xac, 0xeb, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0x87, 0xa7, 0xa7, 0x93, 0x3e, 0x69, 0x53, - 0x54, 0x5c, 0x91, 0xce, 0xcd, 0x47, 0x7f, 0x11, 0x2c, 0xcc, 0x63, 0xec, 0x9c, 0xc9, 0x38, 0x47, 0x67, 0xcc, 0xc6, - 0xc1, 0x0e, 0xc6, 0x8b, 0x7d, 0xcb, 0xef, 0x14, 0xc9, 0x2f, 0x65, 0x05, 0x68, 0x44, 0x21, 0xa8, 0xd3, 0x6e, 0x51, - 0x28, 0x81, 0x43, 0xff, 0xab, 0xac, 0xed, 0x7b, 0xe4, 0xe7, 0xb2, 0x8b, 0x25, 0x82, 0xd8, 0x8d, 0xcd, 0xea, 0x5c, - 0xdc, 0xad, 0x46, 0x36, 0xad, 0x5b, 0x48, 0xa8, 0x3f, 0xcc, 0xcc, 0xb3, 0x67, 0x7e, 0x35, 0x22, 0x78, 0x93, 0x6f, - 0x86, 0xf5, 0xcd, 0x98, 0xeb, 0xbf, 0x4a, 0xfa, 0x73, 0x25, 0x31, 0x8e, 0xdf, 0xc8, 0x80, 0xac, 0x39, 0x90, 0x05, - 0xa5, 0xe2, 0x56, 0x3e, 0xca, 0xe3, 0x3d, 0x7e, 0x14, 0x28, 0xa2, 0xc9, 0x94, 0x51, 0x72, 0x2d, 0x14, 0xf9, 0xc8, - 0xdb, 0xb3, 0xbb, 0x37, 0x9e, 0x8e, 0x1a, 0x2f, 0x37, 0x7f, 0xa0, 0xb7, 0x65, 0xab, 0x1b, 0x3f, 0x98, 0xbd, 0x2d, - 0xff, 0xf9, 0x88, 0x3a, 0x5d, 0x17, 0x19, 0xcf, 0x43, 0xbd, 0x85, 0x6c, 0x1a, 0xa9, 0x16, 0xdd, 0x46, 0x40, 0x37, - 0xe2, 0x98, 0x77, 0xdc, 0x6d, 0xc0, 0x17, 0xc0, 0xbb, 0x84, 0x81, 0x78, 0xff, 0xa0, 0xe7, 0xa6, 0xc9, 0xcb, 0xb3, - 0x29, 0x17, 0x77, 0x5e, 0xd9, 0xed, 0x1e, 0x80, 0xce, 0x4f, 0xab, 0x7f, 0xbc, 0xcf, 0xe1, 0x17, 0x3f, 0xf9, 0x67, - 0x95, 0x50, 0x41, 0xba, 0x6f, 0x8c, 0xab, 0xbc, 0x9c, 0xf5, 0xee, 0x7e, 0xd6, 0x6e, 0xbb, 0xe3, 0x49, 0x0d, 0xed, - 0xbf, 0x92, 0xef, 0x8a, 0x74, 0x1b, 0x65, 0xfc, 0x4b, 0xb0, 0xf8, 0x92, 0x85, 0xde, 0x0f, 0x40, 0xdc, 0x14, 0x69, - 0x0f, 0xe9, 0x6a, 0xc6, 0x0f, 0xe3, 0xdd, 0x68, 0xc7, 0xad, 0xab, 0x5d, 0x12, 0x2e, 0x6a, 0xc4, 0xfd, 0xbc, 0x76, - 0x33, 0xd7, 0x7b, 0x4c, 0xab, 0x69, 0x97, 0x7f, 0xe6, 0x20, 0xbc, 0xb4, 0x90, 0xb2, 0x36, 0xbd, 0xb6, 0x45, 0xe9, - 0x5a, 0x60, 0xf9, 0xcb, 0x59, 0x9b, 0x6e, 0x55, 0x68, 0xda, 0xa5, 0xca, 0xd7, 0xf8, 0x37, 0x4e, 0xc5, 0x2e, 0xe7, - 0x8f, 0xfe, 0x73, 0xf2, 0xf6, 0xf0, 0xd7, 0x92, 0x77, 0xcc, 0x45, 0x6e, 0xce, 0xdc, 0xdf, 0xc2, 0x15, 0x59, 0x16, - 0x17, 0xf9, 0xfc, 0xff, 0x95, 0x7b, 0xfc, 0xd7, 0xe1, 0xf9, 0xb9, 0x26, 0x64, 0x76, 0x54, 0xf3, 0x4a, 0x6a, 0x5e, - 0xfe, 0xdf, 0xe7, 0xc5, 0xd3, 0xab, 0x07, 0xa4, 0xc1, 0xf0, 0x8d, 0xd9, 0x66, 0x96, 0x95, 0xd1, 0xc2, 0x21, 0x1e, - 0xc3, 0xfb, 0x26, 0xaf, 0x41, 0x90, 0x37, 0x5d, 0x96, 0xd3, 0xe0, 0x6e, 0x2a, 0xc9, 0xec, 0x4a, 0x39, 0x2c, 0x6e, - 0xfd, 0x78, 0x59, 0x96, 0xcd, 0x65, 0x4f, 0xf3, 0x4d, 0xed, 0x85, 0xfc, 0xd3, 0x97, 0x54, 0xba, 0x04, 0xe7, 0x8f, - 0x7c, 0xbc, 0x5c, 0xfc, 0x9c, 0x8d, 0xcb, 0x8f, 0x09, 0x21, 0x0e, 0x69, 0x22, 0x4d, 0x03, 0xda, 0x31, 0x98, 0x0f, - 0x71, 0x6e, 0xb6, 0x39, 0xcc, 0x0d, 0xdf, 0xe3, 0x05, 0x60, 0x67, 0x1e, 0x5f, 0xd5, 0x8b, 0x81, 0x38, 0x1d, 0x87, - 0x40, 0x8e, 0x47, 0xff, 0xb7, 0x8e, 0x7e, 0xe8, 0x22, 0xbd, 0xc8, 0x2d, 0xdf, 0xba, 0x87, 0x95, 0xe6, 0xc6, 0xd1, - 0x68, 0xe4, 0x88, 0x6d, 0x76, 0x17, 0x81, 0x8f, 0xb1, 0xe8, 0xe4, 0xe0, 0x2d, 0xe2, 0xa5, 0x7e, 0x97, 0x98, 0x07, - 0x57, 0xf9, 0x77, 0x62, 0xf1, 0xa5, 0x38, 0xde, 0xdd, 0x3b, 0x02, 0xe0, 0xf5, 0xc4, 0x2b, 0x07, 0xa7, 0x65, 0x38, - 0x85, 0xa4, 0x4e, 0x54, 0xd6, 0x4a, 0x75, 0xcf, 0xbe, 0x8f, 0x17, 0x93, 0x08, 0xbc, 0x3f, 0xde, 0xf7, 0x09, 0x3b, - 0x5d, 0xa4, 0xe7, 0x78, 0xaf, 0x8c, 0x40, 0x80, 0x22, 0x0a, 0x90, 0x06, 0xf9, 0xa8, 0x6e, 0x91, 0xbf, 0xc0, 0x50, - 0xdf, 0x39, 0x5c, 0x7d, 0xae, 0x28, 0x90, 0x1e, 0xae, 0xd6, 0xc5, 0x7d, 0x0a, 0x50, 0x12, 0xdb, 0x84, 0x80, 0xed, - 0x3f, 0xbd, 0x6f, 0x07, 0xb6, 0xde, 0xa4, 0x5d, 0xcf, 0x20, 0x77, 0x6a, 0x62, 0xf7, 0x19, 0x46, 0xc6, 0x0b, 0xcf, - 0x0b, 0x9d, 0xf0, 0x28, 0xc7, 0x44, 0xaf, 0xa8, 0xac, 0xac, 0xe3, 0xce, 0x7c, 0xb0, 0xb2, 0xff, 0x5c, 0x42, 0x21, - 0x4c, 0x37, 0xe9, 0xcb, 0x2a, 0xa1, 0x4a, 0xf3, 0x0a, 0x6e, 0x65, 0x4c, 0x46, 0x2f, 0xa1, 0xce, 0xf8, 0x5d, 0x53, - 0x64, 0x8a, 0xb1, 0x0c, 0x98, 0xe9, 0x6f, 0xa6, 0x9c, 0x09, 0x00, 0xce, 0xe2, 0x32, 0x80, 0x04, 0xaa, 0xbe, 0xaa, - 0x95, 0x6f, 0x69, 0xc6, 0x29, 0x59, 0x47, 0xd9, 0x79, 0xae, 0x95, 0x52, 0x1e, 0x5f, 0x36, 0xb0, 0xe1, 0x4c, 0xc3, - 0x82, 0x2b, 0xf9, 0x64, 0xbb, 0x2f, 0x57, 0x73, 0x5d, 0xd6, 0xc3, 0x09, 0x30, 0xfb, 0xfd, 0x00, 0xfa, 0x96, 0x72, - 0xc5, 0x46, 0xd9, 0xcb, 0x3f, 0xf4, 0x06, 0x6b, 0xd0, 0xf0, 0xa1, 0x87, 0x29, 0x37, 0xbe, 0x50, 0xd4, 0x7f, 0x08, - 0x9c, 0x15, 0x23, 0x97, 0x6a, 0x4d, 0xa1, 0x97, 0x18, 0xa1, 0x9f, 0x65, 0x50, 0xb5, 0x7a, 0x63, 0x2a, 0x2a, 0x95, - 0xaf, 0xef, 0xb9, 0xc3, 0x95, 0xe5, 0xc0, 0x9d, 0xf9, 0xe4, 0x14, 0x90, 0x02, 0x44, 0x41, 0xac, 0x54, 0x7e, 0x1e, - 0x66, 0x9b, 0x90, 0xca, 0x20, 0x99, 0xbe, 0x50, 0x64, 0xdd, 0x37, 0xfa, 0x0b, 0x2b, 0xb6, 0xea, 0x25, 0x74, 0x0f, - 0x76, 0x78, 0xcf, 0x7d, 0x9b, 0xf7, 0x67, 0xcb, 0x59, 0xf5, 0xb4, 0xf4, 0xd6, 0x73, 0xb7, 0x6b, 0xe0, 0x52, 0xe7, - 0x00, 0x20, 0x2d, 0x97, 0x3a, 0x7f, 0xdf, 0xc4, 0xdd, 0xac, 0x36, 0x7e, 0x76, 0x51, 0x46, 0x47, 0x8f, 0x5b, 0xe9, - 0xe9, 0x91, 0x75, 0x61, 0x95, 0x74, 0x78, 0xdf, 0x44, 0xe0, 0xcb, 0x1f, 0xc3, 0xb0, 0x7a, 0x61, 0x7a, 0x6e, 0x50, - 0x9c, 0x09, 0x9b, 0x93, 0x7d, 0xf6, 0xce, 0xcd, 0x5b, 0x0d, 0x1f, 0xa2, 0x37, 0xe1, 0x73, 0x87, 0x7d, 0x2e, 0x02, - 0xe8, 0x36, 0x6b, 0x7e, 0xc6, 0x41, 0xd1, 0x2a, 0x54, 0x8b, 0x97, 0x25, 0xb0, 0x29, 0x59, 0xee, 0xe7, 0x78, 0x11, - 0x6c, 0x0a, 0xed, 0x8b, 0x20, 0x2f, 0x67, 0x54, 0xa1, 0x17, 0xd2, 0xbb, 0x0a, 0x5c, 0xb9, 0x15, 0x7c, 0x7f, 0xc5, - 0x60, 0x75, 0xd5, 0xb6, 0x14, 0x1f, 0xce, 0x18, 0xfd, 0xae, 0x02, 0xe6, 0xab, 0xaf, 0x98, 0xd9, 0xd0, 0xa7, 0x3d, - 0x0f, 0xab, 0xfb, 0xfe, 0xb5, 0xe5, 0x0b, 0x82, 0xef, 0xdf, 0x4c, 0x4d, 0xbb, 0x38, 0x9c, 0x12, 0x1b, 0x81, 0xb9, - 0x47, 0x88, 0xc3, 0x10, 0x69, 0x50, 0x77, 0x90, 0x6f, 0xef, 0x96, 0x24, 0x21, 0x4f, 0xd6, 0xbf, 0x78, 0xfc, 0xee, - 0x4c, 0x7a, 0x22, 0xbd, 0xf8, 0xe1, 0xe3, 0x75, 0x22, 0x2c, 0xdb, 0x0b, 0x35, 0xd9, 0xc1, 0xe3, 0x94, 0x5b, 0x79, - 0x80, 0x66, 0x0d, 0x5d, 0x74, 0xdb, 0x87, 0x74, 0x5c, 0x9c, 0x5f, 0x63, 0xe8, 0xfb, 0x06, 0xde, 0xcd, 0x0c, 0x0d, - 0x79, 0xcf, 0xd8, 0x5d, 0xf5, 0x81, 0x0a, 0x2b, 0xc9, 0x4b, 0xb9, 0x57, 0xf6, 0x5c, 0x74, 0xb5, 0x61, 0xe2, 0x1c, - 0x50, 0x7f, 0xb3, 0xcf, 0xcb, 0xae, 0x8a, 0x0f, 0xf8, 0x7a, 0xa5, 0x81, 0xaf, 0xeb, 0x0c, 0x35, 0x02, 0x3a, 0x48, - 0x91, 0x25, 0xe0, 0x33, 0xcc, 0xa8, 0x49, 0x38, 0xcd, 0xf4, 0x96, 0xf2, 0x3c, 0xca, 0x60, 0x51, 0x53, 0xba, 0xd0, - 0xe5, 0xdb, 0xae, 0x16, 0x73, 0x7a, 0x17, 0x13, 0xed, 0x52, 0xf3, 0xde, 0x7e, 0x00, 0x70, 0xb5, 0xdb, 0x90, 0x70, - 0x91, 0x7e, 0x14, 0xf7, 0xad, 0xf3, 0x63, 0xea, 0xeb, 0xe2, 0xe2, 0x11, 0x64, 0x2a, 0x98, 0x04, 0xb9, 0xe9, 0x73, - 0xfd, 0x17, 0x34, 0x31, 0x21, 0x3f, 0xf9, 0xb3, 0x04, 0x5f, 0xda, 0xb5, 0x5d, 0x0c, 0xc1, 0x47, 0x6a, 0x8d, 0xde, - 0x2d, 0x05, 0x64, 0x61, 0x3f, 0xec, 0x3d, 0xd7, 0x14, 0x64, 0xc7, 0x21, 0x69, 0x00, 0x7d, 0xdf, 0xa4, 0xe3, 0x17, - 0x16, 0xc6, 0x22, 0x91, 0x9a, 0xde, 0xc2, 0x76, 0x99, 0x6c, 0xa7, 0xaf, 0x6e, 0x6f, 0x19, 0x5f, 0x5d, 0xec, 0x7a, - 0x0a, 0xeb, 0x06, 0xb0, 0xc3, 0x46, 0x1b, 0x6f, 0xba, 0x80, 0xc3, 0x6d, 0x76, 0xc6, 0x94, 0x7a, 0x57, 0xdc, 0x24, - 0x0e, 0x03, 0xc1, 0x10, 0xf5, 0x22, 0x99, 0x45, 0xf9, 0x3d, 0xf5, 0x26, 0x1c, 0xf5, 0x90, 0xf6, 0x0f, 0x6e, 0xbe, - 0xff, 0x8f, 0x2a, 0x3d, 0x38, 0x1b, 0x06, 0x7e, 0xb2, 0x7b, 0x40, 0xf2, 0xd4, 0x54, 0xf4, 0x80, 0x26, 0x5b, 0x9e, - 0x04, 0xe2, 0xa6, 0x73, 0xed, 0xc3, 0xfe, 0x31, 0xe5, 0x1b, 0x02, 0x6a, 0x9e, 0x18, 0xa1, 0xda, 0x7a, 0xe4, 0x2f, - 0x6b, 0xa5, 0x37, 0xd6, 0x10, 0xcf, 0xaf, 0x08, 0xde, 0xaf, 0x5e, 0x1c, 0x7e, 0x2d, 0x69, 0xa0, 0xdc, 0x2e, 0x67, - 0xe9, 0xbf, 0xeb, 0x0a, 0x17, 0x02, 0x0f, 0xc9, 0xa7, 0x11, 0x92, 0x2b, 0x0b, 0x7c, 0xfc, 0xe2, 0x50, 0xe7, 0xd3, - 0xf7, 0xba, 0xf1, 0x59, 0xdd, 0x10, 0x85, 0x9c, 0x1f, 0xa0, 0xaa, 0x0d, 0x31, 0x46, 0x08, 0x17, 0x7c, 0xf4, 0xd1, - 0x65, 0x59, 0xa3, 0x25, 0x20, 0xed, 0xca, 0xe5, 0x8f, 0x17, 0x06, 0x5e, 0x2b, 0x7e, 0xcb, 0x61, 0x5e, 0xa6, 0x43, - 0x7c, 0xa5, 0xb1, 0x7d, 0x2d, 0x1d, 0x32, 0xd7, 0xd1, 0xa8, 0x08, 0x55, 0x15, 0xa9, 0xe7, 0xe2, 0xa3, 0xf5, 0xbb, - 0x6e, 0xe4, 0x33, 0x83, 0xc5, 0xa5, 0x65, 0x63, 0xc7, 0x49, 0x75, 0xc9, 0x33, 0x3c, 0x40, 0x67, 0xb0, 0xcf, 0xd9, - 0x76, 0xf1, 0x67, 0x95, 0xac, 0xe1, 0x00, 0x23, 0xb0, 0x07, 0x43, 0xae, 0x4a, 0x12, 0x64, 0x30, 0x36, 0x25, 0x97, - 0xa1, 0xe4, 0x7d, 0xbd, 0xb1, 0x59, 0x8e, 0xf2, 0xa0, 0xd0, 0x91, 0xe1, 0x8a, 0xff, 0xa9, 0xb7, 0x8a, 0x34, 0xbd, - 0xfc, 0xdc, 0x38, 0x5b, 0xe7, 0x74, 0xb3, 0x3b, 0xb2, 0xc3, 0x87, 0x51, 0x6e, 0x21, 0x4e, 0xa6, 0x79, 0x18, 0x09, - 0xac, 0x64, 0x6e, 0x9e, 0x0e, 0x80, 0xf8, 0x26, 0x33, 0x5a, 0xb7, 0xe4, 0x7f, 0xf2, 0xb5, 0xae, 0x23, 0x44, 0xb4, - 0xb1, 0xbe, 0xab, 0xe8, 0x0c, 0x12, 0x27, 0xb9, 0x41, 0x31, 0x9e, 0xaa, 0x98, 0x31, 0xc8, 0x96, 0xaa, 0x4e, 0xf2, - 0xfb, 0x4f, 0xbe, 0x4b, 0xa1, 0x37, 0xbd, 0x3d, 0x37, 0xeb, 0xb6, 0x93, 0xe5, 0x88, 0x1a, 0x29, 0x33, 0xbb, 0x31, - 0xe8, 0xa6, 0xa0, 0x10, 0x29, 0x29, 0xcf, 0x14, 0xe9, 0x18, 0x0e, 0xf7, 0xda, 0x1f, 0xe1, 0x89, 0xed, 0x58, 0xc2, - 0xda, 0x66, 0x81, 0x47, 0x80, 0xc0, 0x47, 0xfd, 0x16, 0x41, 0x34, 0xd5, 0x15, 0x15, 0x6a, 0x79, 0x63, 0x77, 0x76, - 0x74, 0x7b, 0x5a, 0x5b, 0xd0, 0x3e, 0x83, 0x3f, 0x15, 0x14, 0xdc, 0x76, 0xad, 0xe7, 0x64, 0x64, 0x45, 0xea, 0x42, - 0x30, 0x02, 0x32, 0xeb, 0x9f, 0x21, 0xe3, 0x53, 0x13, 0xa2, 0xee, 0x2f, 0x1b, 0x43, 0x8e, 0x84, 0x40, 0x80, 0xf0, - 0xb2, 0x7c, 0x96, 0xf0, 0x49, 0xa0, 0x08, 0x50, 0xf5, 0xb8, 0xf4, 0xca, 0x72, 0xa9, 0xd1, 0xf0, 0xa8, 0xd5, 0x80, - 0x6d, 0xbb, 0x40, 0xed, 0x80, 0x05, 0xd6, 0x4e, 0x61, 0x9d, 0x13, 0x52, 0x75, 0x29, 0x16, 0xdd, 0xaa, 0x2e, 0x52, - 0x9e, 0xcd, 0xeb, 0x4c, 0x11, 0x36, 0xad, 0x7f, 0xad, 0x7c, 0x99, 0x80, 0x68, 0x9b, 0xbf, 0x04, 0x6e, 0x8e, 0xcd, - 0xfe, 0x8f, 0x36, 0x13, 0xd3, 0x3a, 0xf5, 0x2a, 0x02, 0x94, 0x9d, 0x2a, 0xf1, 0x1a, 0x65, 0x0c, 0x4a, 0x50, 0xe7, - 0xc7, 0x5e, 0xa2, 0x82, 0x5c, 0x25, 0x7d, 0x31, 0x50, 0x80, 0x30, 0x5e, 0x3a, 0xe2, 0xa5, 0xab, 0xbc, 0xd8, 0x56, - 0xeb, 0x9c, 0x60, 0xec, 0xcd, 0xec, 0x05, 0xa4, 0x3e, 0x5d, 0xee, 0x24, 0x47, 0xd3, 0xc5, 0xb5, 0xcb, 0xab, 0x78, - 0xc8, 0x74, 0x59, 0x7c, 0x4c, 0x83, 0xa7, 0x2a, 0xe7, 0x89, 0x15, 0xc2, 0xff, 0xb6, 0x8c, 0x1b, 0xaf, 0x94, 0x69, - 0x81, 0x10, 0x6b, 0x49, 0x14, 0x38, 0xdf, 0x0c, 0x92, 0x87, 0xe5, 0x51, 0x69, 0x9a, 0xc7, 0xfe, 0xda, 0xd0, 0xec, - 0x49, 0xf6, 0x40, 0x92, 0x0f, 0xdb, 0xbe, 0x4b, 0x82, 0xb9, 0xef, 0x27, 0x1d, 0xc3, 0x44, 0x61, 0x1f, 0x34, 0xe4, - 0x71, 0xd5, 0x02, 0x08, 0x46, 0xee, 0x57, 0x5f, 0xcb, 0xdd, 0xb6, 0xed, 0x36, 0x08, 0x3e, 0xc7, 0x42, 0xc4, 0x5f, - 0x0c, 0x49, 0xf0, 0xed, 0xd5, 0x0b, 0x2a, 0x17, 0xab, 0x75, 0xc8, 0xbc, 0x3c, 0x25, 0xd9, 0xce, 0x93, 0xae, 0xef, - 0x9e, 0xf7, 0xfc, 0x8a, 0x88, 0xd3, 0x15, 0xcd, 0x4c, 0x9c, 0x23, 0xe9, 0xa8, 0xc4, 0x0b, 0xee, 0x0e, 0xea, 0xec, - 0xfd, 0x9c, 0xe2, 0x14, 0x93, 0xe6, 0x16, 0x15, 0x42, 0x17, 0x12, 0xba, 0xd6, 0xb9, 0x7c, 0x5d, 0x58, 0xbb, 0x79, - 0xa2, 0xf4, 0xfe, 0xa5, 0x99, 0x51, 0x54, 0xea, 0xe7, 0x62, 0x09, 0x24, 0x13, 0x72, 0xa2, 0xdf, 0xd8, 0xea, 0xa4, - 0xbb, 0x87, 0x6f, 0x6a, 0xa3, 0xc5, 0x3c, 0x88, 0x73, 0xc0, 0xca, 0x97, 0x61, 0x6f, 0x1b, 0x93, 0xe2, 0xf6, 0xd7, - 0x25, 0x64, 0xb5, 0xdd, 0x1f, 0x4a, 0x7f, 0xce, 0x05, 0x2e, 0xd1, 0x98, 0x18, 0x31, 0xc3, 0x2f, 0x44, 0x5a, 0xa3, - 0x44, 0xce, 0x3d, 0xce, 0x6d, 0x42, 0xfe, 0x2b, 0x53, 0x6f, 0xa4, 0xbb, 0x42, 0xc8, 0xff, 0xf3, 0x3c, 0xe2, 0x8e, - 0xe9, 0xe6, 0xde, 0xde, 0xc9, 0x30, 0x72, 0x0e, 0xcc, 0xda, 0x6e, 0xca, 0x2c, 0xdc, 0x45, 0x7a, 0x8b, 0x19, 0xd3, - 0xec, 0x10, 0xbc, 0x0c, 0x9d, 0x74, 0x52, 0x7c, 0xea, 0x00, 0xa1, 0xea, 0x08, 0x60, 0x4a, 0x16, 0xfa, 0x17, 0x28, - 0x5d, 0xbd, 0x58, 0xa6, 0x96, 0x4a, 0xcd, 0x75, 0x27, 0x16, 0x3f, 0xa1, 0xc0, 0x20, 0x7e, 0x71, 0xab, 0x35, 0x9d, - 0x1d, 0x52, 0x44, 0xa2, 0x27, 0xfd, 0x18, 0x1e, 0x63, 0xe5, 0x31, 0xeb, 0xa1, 0x50, 0x13, 0x5c, 0xef, 0x64, 0xd5, - 0xb3, 0x92, 0x20, 0x8d, 0x74, 0x0f, 0xb0, 0x37, 0x4f, 0xed, 0x51, 0xa2, 0x15, 0x02, 0x2f, 0x91, 0xc6, 0x0c, 0x89, - 0xf6, 0x21, 0xf6, 0x90, 0x98, 0x00, 0x6f, 0x0a, 0x26, 0xd8, 0x52, 0x68, 0x3b, 0x07, 0xce, 0x3b, 0x0a, 0x58, 0x9b, - 0x6b, 0xd4, 0x60, 0xe6, 0x91, 0x23, 0x26, 0xe2, 0x38, 0xfb, 0x5d, 0xd4, 0x21, 0x81, 0xe4, 0x10, 0xed, 0x9c, 0x6a, - 0x1a, 0xb4, 0x38, 0x73, 0x5e, 0x23, 0x57, 0x08, 0xc7, 0xa7, 0xa0, 0x8c, 0x23, 0xd8, 0x70, 0x7d, 0xcc, 0x25, 0xeb, - 0xb2, 0x22, 0x0a, 0x9b, 0x3b, 0x4b, 0xde, 0xaf, 0xe3, 0xf7, 0xa6, 0xb0, 0x92, 0x65, 0xe1, 0x9b, 0xa6, 0xd4, 0x33, - 0xe5, 0x73, 0x2f, 0xac, 0x4a, 0x7a, 0x76, 0x00, 0xf7, 0x88, 0xff, 0xc1, 0xe5, 0x66, 0xe4, 0xa7, 0x94, 0x82, 0x1a, - 0xf0, 0x47, 0x13, 0xda, 0x95, 0x0a, 0x8a, 0xc5, 0xc0, 0x48, 0xd3, 0x69, 0x5b, 0xa8, 0x97, 0x1a, 0x36, 0x30, 0xcc, - 0x63, 0xb2, 0x50, 0xe8, 0xd4, 0xfe, 0x86, 0xe7, 0xf3, 0x88, 0x46, 0xde, 0x4c, 0x1b, 0x64, 0xf9, 0x1d, 0xba, 0xd7, - 0x2a, 0x27, 0xf3, 0x6d, 0x05, 0x10, 0x3f, 0xf3, 0xb2, 0x60, 0x34, 0x54, 0x34, 0x29, 0x66, 0x30, 0x5c, 0x9a, 0x3f, - 0x71, 0x15, 0xa0, 0xc7, 0xf4, 0xd5, 0xda, 0xa2, 0x3a, 0xef, 0x40, 0xc4, 0x74, 0x1f, 0x94, 0x2a, 0x52, 0x5f, 0xe9, - 0x66, 0xab, 0xe3, 0x1c, 0xfc, 0xb1, 0xaa, 0xae, 0x20, 0xd1, 0x6e, 0x79, 0x34, 0xa6, 0xd1, 0xb1, 0x2f, 0x0e, 0xd9, - 0xb1, 0xc7, 0xf3, 0x0e, 0x45, 0xc8, 0xfd, 0xd9, 0x37, 0xa6, 0xf8, 0x24, 0x23, 0x69, 0x04, 0xfa, 0x0a, 0x84, 0xab, - 0x7e, 0xee, 0xae, 0xa8, 0xb0, 0xd5, 0xc8, 0x66, 0x41, 0x19, 0x86, 0xa8, 0xa6, 0xa7, 0x68, 0x1c, 0x78, 0x56, 0x90, - 0x88, 0x09, 0x01, 0x4a, 0xd8, 0xb5, 0x44, 0x0f, 0xfd, 0x1f, 0x66, 0x56, 0xbf, 0xf2, 0x86, 0xad, 0x4c, 0xeb, 0x00, - 0x52, 0x04, 0x84, 0x54, 0xca, 0xd5, 0xfd, 0x83, 0xb9, 0x70, 0x3c, 0x4a, 0x4c, 0x26, 0x3f, 0xcf, 0x3e, 0x80, 0x37, - 0x33, 0xbd, 0x3c, 0xf2, 0x13, 0x69, 0x62, 0x93, 0x7a, 0x4c, 0x6b, 0xa4, 0x76, 0xbb, 0x03, 0x5c, 0xad, 0xd2, 0x0b, - 0x53, 0xff, 0xa2, 0x08, 0x46, 0xff, 0x4a, 0x07, 0x69, 0xdd, 0xcb, 0x9c, 0x4b, 0xb0, 0x29, 0x7a, 0xdb, 0x06, 0x30, - 0xed, 0xdb, 0x52, 0x75, 0x23, 0x41, 0x8a, 0x6d, 0x53, 0xf8, 0xee, 0xf0, 0x12, 0x11, 0x8b, 0x33, 0x16, 0xab, 0xd5, - 0x1d, 0x2d, 0xe6, 0xc1, 0xf7, 0x53, 0x47, 0x10, 0xf6, 0xaf, 0xb0, 0x09, 0x6c, 0x3c, 0x40, 0x16, 0x7b, 0x90, 0x8e, - 0x58, 0xa9, 0xa6, 0x39, 0x8f, 0x56, 0x81, 0x95, 0xaa, 0x2c, 0xde, 0xc7, 0x95, 0xb4, 0xfb, 0x5a, 0x26, 0x0e, 0xa8, - 0xce, 0x21, 0xfc, 0xd6, 0xa2, 0x6f, 0x25, 0x64, 0x5e, 0xd7, 0x38, 0x02, 0xd4, 0x95, 0xb8, 0x12, 0x37, 0x0a, 0x92, - 0x91, 0x1f, 0x34, 0x93, 0x13, 0x74, 0x34, 0xf9, 0xf8, 0x81, 0x06, 0x1e, 0xba, 0xe7, 0x6f, 0xd4, 0x50, 0xec, 0xdb, - 0x55, 0x74, 0x28, 0xb4, 0x26, 0xd9, 0x7f, 0xf6, 0x9d, 0x69, 0xcd, 0x69, 0x46, 0x3d, 0x35, 0xc1, 0x9d, 0x7a, 0x5b, - 0x17, 0x5b, 0xa6, 0x71, 0xe4, 0x2e, 0xcc, 0x9c, 0xf1, 0xb5, 0xbd, 0x81, 0x38, 0xdf, 0x0b, 0x89, 0x9b, 0xe9, 0x88, - 0x29, 0xfd, 0xa4, 0x31, 0x02, 0x6a, 0x14, 0x1d, 0x6c, 0x64, 0xda, 0xb7, 0x02, 0x39, 0x9b, 0xa0, 0xa3, 0x2a, 0xa8, - 0xb6, 0x98, 0x99, 0xa5, 0x71, 0x6a, 0xa4, 0x05, 0x05, 0x2b, 0x8d, 0x41, 0x61, 0xa5, 0x2a, 0xc9, 0x5e, 0x94, 0x58, - 0x7a, 0x9e, 0xb3, 0xd0, 0xa1, 0x6c, 0x3a, 0x7c, 0x5a, 0x0b, 0x97, 0x84, 0xd1, 0xd6, 0xc2, 0x30, 0x6d, 0xb6, 0xd2, - 0xb6, 0xb2, 0xa2, 0x12, 0x2a, 0xb9, 0xbe, 0xa8, 0x24, 0x69, 0x1e, 0x61, 0x1c, 0x4f, 0x65, 0x76, 0x43, 0xf9, 0x0a, - 0x5b, 0xb7, 0xf1, 0xa1, 0xf0, 0x6f, 0x42, 0xc9, 0x6c, 0xc8, 0x80, 0x0c, 0x54, 0x12, 0xac, 0xe2, 0xf4, 0xf3, 0xe5, - 0x35, 0x67, 0x11, 0x97, 0x39, 0xf0, 0x6a, 0xea, 0xb5, 0x76, 0x1c, 0x4a, 0x7c, 0xed, 0xe4, 0x3f, 0xd3, 0xe4, 0xcf, - 0x12, 0x0e, 0xd7, 0xb9, 0xb2, 0xe2, 0x74, 0x58, 0xd0, 0x8f, 0xd8, 0xab, 0xcf, 0xd7, 0x4b, 0x62, 0xcb, 0xa3, 0x48, - 0xdd, 0x2b, 0x6d, 0xef, 0x3d, 0x1b, 0xa9, 0xd0, 0xac, 0xdd, 0x7d, 0xdf, 0x49, 0x5a, 0x65, 0x6a, 0xb5, 0x8b, 0x7b, - 0xd8, 0x40, 0x68, 0x6b, 0x52, 0x22, 0xee, 0xdd, 0xa4, 0x0c, 0x2f, 0x6d, 0x16, 0x40, 0xb5, 0x26, 0x14, 0xdf, 0x8d, - 0xeb, 0x44, 0xee, 0xc3, 0x33, 0x99, 0xbf, 0xdd, 0x7d, 0x30, 0xda, 0x0d, 0xec, 0x8a, 0xd0, 0x0f, 0xa2, 0x2d, 0x58, - 0x75, 0xe9, 0x8d, 0xba, 0xc0, 0x64, 0x51, 0xea, 0x60, 0xa4, 0x82, 0x2c, 0x5e, 0xb9, 0x03, 0xbb, 0x8e, 0x47, 0x10, - 0x40, 0x7f, 0xe3, 0xb8, 0xc5, 0x6d, 0x22, 0x15, 0xc1, 0x5d, 0x76, 0x9c, 0x54, 0x69, 0xbd, 0xcd, 0x8e, 0x63, 0xc1, - 0xd8, 0x52, 0xc8, 0xcc, 0x2a, 0x08, 0x5a, 0x09, 0xb4, 0xbe, 0x4a, 0x76, 0xba, 0x0c, 0xb3, 0x56, 0x14, 0xb0, 0x0f, - 0x2a, 0x39, 0xeb, 0x0f, 0x4a, 0x51, 0x5d, 0xc1, 0xf7, 0x71, 0x78, 0xfa, 0xdd, 0xc0, 0x01, 0x8b, 0xa1, 0x15, 0x82, - 0x23, 0xf6, 0x48, 0x87, 0x2d, 0xbd, 0xa9, 0x77, 0x7c, 0xae, 0xc2, 0x79, 0xf3, 0x58, 0xff, 0x07, 0xa9, 0x3e, 0xef, - 0xeb, 0x17, 0x38, 0xc1, 0x2f, 0x5e, 0x54, 0x8f, 0x77, 0xfc, 0xff, 0x06, 0x43, 0x54, 0x1d, 0xa6, 0xb6, 0xf8, 0x73, - 0x82, 0x74, 0x26, 0x0d, 0x7b, 0xb8, 0xbe, 0x92, 0x76, 0xbe, 0xa0, 0x1a, 0x7a, 0x64, 0x63, 0xb5, 0x1e, 0x94, 0x20, - 0x52, 0xde, 0xbb, 0x7d, 0x36, 0x2f, 0x25, 0xa5, 0x1a, 0xd1, 0x42, 0x4d, 0x7c, 0xb3, 0xe6, 0x4d, 0xb2, 0x16, 0x24, - 0xb1, 0xed, 0x59, 0x3b, 0xb2, 0x85, 0xf8, 0xfd, 0x5b, 0x8c, 0x26, 0x07, 0xf1, 0xde, 0xec, 0xba, 0x0c, 0xba, 0xd5, - 0xb3, 0xb4, 0x84, 0x55, 0x1b, 0xa8, 0x6a, 0xaa, 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0xf5, 0xeb, 0x4a, 0x3a, 0xa7, - 0xb4, 0x10, 0x6a, 0x19, 0xf7, 0x44, 0xb2, 0x88, 0xf8, 0x58, 0x05, 0x3f, 0x29, 0xcc, 0xa9, 0xbb, 0x68, 0x44, 0x16, - 0xa3, 0x57, 0x6e, 0xc3, 0x69, 0xab, 0xa5, 0x4a, 0x40, 0xac, 0xdf, 0xb5, 0x1a, 0x67, 0xb3, 0xc2, 0x89, 0xa1, 0xef, - 0xff, 0xc4, 0x55, 0xe1, 0x4b, 0x10, 0xc6, 0xf1, 0x99, 0x24, 0x4b, 0xf1, 0x19, 0xaf, 0x3c, 0xf0, 0x0e, 0xac, 0xe8, - 0x6e, 0x5f, 0xf1, 0xfb, 0x4f, 0x57, 0x61, 0x85, 0x66, 0x59, 0x51, 0x6e, 0x5d, 0x63, 0x49, 0xdd, 0x23, 0xc7, 0x79, - 0x71, 0x0f, 0x70, 0x26, 0x34, 0xa3, 0x22, 0x4c, 0x69, 0x24, 0x2d, 0x3f, 0x53, 0x5b, 0xb1, 0xf4, 0x09, 0xc5, 0x12, - 0x01, 0x32, 0xf8, 0xfe, 0x93, 0x44, 0x57, 0x1e, 0xeb, 0x00, 0xff, 0xa8, 0x58, 0xb9, 0x2c, 0x66, 0x85, 0x86, 0xba, - 0x00, 0xc9, 0xfa, 0xea, 0x4a, 0xd6, 0xec, 0x6c, 0x43, 0x04, 0x95, 0xba, 0xeb, 0x20, 0x40, 0x6c, 0xd7, 0x08, 0x7c, - 0xf9, 0xd7, 0x68, 0x58, 0x6f, 0x65, 0x41, 0x1d, 0x36, 0xd9, 0x05, 0x01, 0xd1, 0xbd, 0xe8, 0x97, 0x9e, 0x1b, 0xff, - 0xd8, 0xf8, 0x64, 0x63, 0xf9, 0xf0, 0x33, 0x72, 0x2d, 0xaa, 0x87, 0xcc, 0x16, 0x80, 0x98, 0x8d, 0x34, 0x1b, 0x27, - 0xba, 0x6a, 0xef, 0x7b, 0x8d, 0xb2, 0x4d, 0x86, 0xed, 0x12, 0xb3, 0x78, 0xb0, 0xa8, 0x31, 0x65, 0x64, 0x63, 0x8f, - 0x7b, 0xe5, 0xc1, 0x5d, 0xf6, 0x41, 0x04, 0x9d, 0xcb, 0x76, 0xcc, 0xb4, 0x76, 0x38, 0xaf, 0x1a, 0xbb, 0x42, 0x66, - 0x05, 0x9b, 0xc4, 0x41, 0x00, 0xd9, 0x65, 0xdd, 0x05, 0x53, 0xce, 0x69, 0x71, 0xc3, 0x62, 0x0f, 0x36, 0x50, 0x16, - 0x3a, 0xb0, 0x25, 0xd4, 0x50, 0x0a, 0xd3, 0x58, 0x7a, 0xe0, 0x6c, 0x05, 0xe6, 0x5a, 0x8f, 0x63, 0x5d, 0xb3, 0x4e, - 0xd1, 0xa5, 0x02, 0xd2, 0xe2, 0xe8, 0xf9, 0x4d, 0x1f, 0xd2, 0xbe, 0xdb, 0xda, 0xf0, 0xbd, 0x6e, 0xbc, 0x26, 0xc3, - 0x4a, 0x79, 0x12, 0xed, 0x55, 0xfd, 0xf6, 0x02, 0xa3, 0x5a, 0xf8, 0xcc, 0xe5, 0x4b, 0x25, 0xff, 0x6e, 0x0d, 0x03, - 0xcd, 0x17, 0x0a, 0x5f, 0xf5, 0x04, 0x32, 0x2d, 0x69, 0x51, 0xf0, 0xce, 0xf8, 0x69, 0xb3, 0x05, 0xe3, 0xfe, 0xcd, - 0x4d, 0xc5, 0xb8, 0xfe, 0xed, 0x4d, 0xd3, 0xaf, 0x86, 0xc0, 0x6f, 0x14, 0x24, 0xdd, 0x87, 0xed, 0x11, 0x04, 0x88, - 0x7b, 0xab, 0x5c, 0x36, 0xb9, 0x7e, 0xf3, 0xb8, 0xa1, 0xaf, 0x6e, 0xf9, 0xc7, 0x1d, 0xe0, 0x59, 0x92, 0x93, 0xad, - 0x2d, 0x8b, 0x47, 0xce, 0xec, 0xee, 0x65, 0x1c, 0xff, 0x00, 0x38, 0x85, 0xd5, 0xad, 0xfc, 0xe9, 0xfd, 0xcc, 0x9e, - 0x52, 0x73, 0xbd, 0xf5, 0xe7, 0xab, 0x5f, 0xb9, 0x6d, 0x1e, 0xab, 0x53, 0xc3, 0xc6, 0x4d, 0x63, 0x49, 0x66, 0x4b, - 0x30, 0x33, 0x07, 0x29, 0x9c, 0xaf, 0xd5, 0xe7, 0x8c, 0xa3, 0xb8, 0xce, 0x09, 0x23, 0x6c, 0x63, 0x90, 0x1f, 0xbf, - 0x24, 0x96, 0x92, 0xf9, 0xc7, 0xed, 0xca, 0x18, 0x26, 0x91, 0x6e, 0x4f, 0xbd, 0x97, 0xa9, 0xce, 0x29, 0xdb, 0x63, - 0x1e, 0x9b, 0xe0, 0x67, 0xd5, 0x23, 0xd0, 0x0a, 0xfc, 0x0b, 0x02, 0xb6, 0xbb, 0x2c, 0xb3, 0x07, 0x9a, 0x37, 0xff, - 0x03, 0x78, 0x23, 0x3a, 0x65, 0x61, 0x27, 0xbb, 0xbe, 0xf9, 0x5d, 0x87, 0xc3, 0x95, 0x61, 0x89, 0x1b, 0xc6, 0x30, - 0x60, 0x1c, 0xba, 0xb5, 0xb5, 0x27, 0xb5, 0x1b, 0x1c, 0xa4, 0x8a, 0xf7, 0x50, 0x8a, 0x75, 0x34, 0x2f, 0x2c, 0xff, - 0x28, 0x07, 0xca, 0x0a, 0x03, 0xf2, 0x60, 0xd8, 0xf9, 0x98, 0x35, 0x52, 0x0d, 0x5d, 0xba, 0x8e, 0x2b, 0xad, 0xb1, - 0x21, 0x1f, 0x33, 0xec, 0x7e, 0xef, 0x1c, 0x05, 0xed, 0xe9, 0x7a, 0xcb, 0x81, 0x33, 0xac, 0xbd, 0x2f, 0xe3, 0x3c, - 0xf5, 0x72, 0xc1, 0xce, 0xd4, 0xd0, 0x9f, 0xf7, 0x9b, 0xac, 0xa6, 0x60, 0xa3, 0x23, 0xa8, 0xd3, 0x4f, 0x2e, 0x4a, - 0x5c, 0x65, 0x46, 0xd6, 0xfd, 0x96, 0x54, 0x67, 0x82, 0x83, 0xac, 0x2b, 0x94, 0xdf, 0xc5, 0x99, 0xd0, 0x87, 0x26, - 0x35, 0x8b, 0x64, 0xe3, 0x7d, 0x94, 0x1e, 0x18, 0x22, 0x0b, 0x3d, 0x6e, 0xd6, 0x9e, 0xaf, 0x19, 0x27, 0xb1, 0xfc, - 0xd7, 0x85, 0xd3, 0x76, 0xab, 0xf6, 0x08, 0x06, 0x81, 0xe7, 0x5f, 0x45, 0xcc, 0xb6, 0x1a, 0xd6, 0x9d, 0x99, 0xa9, - 0xaa, 0x97, 0xeb, 0xd5, 0xdc, 0x5a, 0x8f, 0x09, 0x15, 0x54, 0x5e, 0xaa, 0xae, 0x32, 0x26, 0x32, 0xf2, 0x63, 0x41, - 0x39, 0xba, 0xba, 0xcd, 0x73, 0xde, 0xa3, 0x3d, 0x8b, 0xdc, 0x0c, 0x80, 0x91, 0x4e, 0xc8, 0x30, 0xe1, 0x16, 0x66, - 0x3a, 0xb2, 0x5a, 0x55, 0x16, 0xf0, 0x51, 0xc3, 0x17, 0x1d, 0xb4, 0xc0, 0xe4, 0xd5, 0x13, 0x87, 0xb3, 0x42, 0x8c, - 0x14, 0xf7, 0xb1, 0x9f, 0x10, 0xf3, 0xc7, 0x69, 0x26, 0xa6, 0x6a, 0xd6, 0x3e, 0xef, 0x7e, 0x07, 0x42, 0x13, 0x43, - 0x74, 0x58, 0x44, 0xaf, 0x43, 0x01, 0x9b, 0xe4, 0xb5, 0x55, 0xb5, 0xc8, 0xf0, 0xeb, 0x81, 0xc6, 0x32, 0x06, 0x21, - 0xcc, 0x25, 0x30, 0xab, 0xfd, 0x74, 0xdb, 0x05, 0x65, 0xa3, 0x48, 0x2b, 0x9c, 0xac, 0x57, 0xac, 0x35, 0xb1, 0x16, - 0x96, 0xe3, 0xa2, 0x43, 0x71, 0x15, 0x1a, 0xb1, 0x8a, 0xa8, 0x75, 0x89, 0x9f, 0xec, 0x14, 0x8d, 0x82, 0xb8, 0x6c, - 0x09, 0x22, 0x6a, 0x72, 0x72, 0xd7, 0x43, 0xea, 0x13, 0x2b, 0xa4, 0x29, 0x41, 0xf8, 0xce, 0x13, 0x94, 0x31, 0x02, - 0xb7, 0x55, 0x6a, 0x8c, 0x0d, 0x25, 0x99, 0x83, 0xc1, 0xf0, 0xcd, 0x04, 0x27, 0x7a, 0x09, 0x65, 0x46, 0xab, 0xe4, - 0x3e, 0x66, 0x4c, 0x63, 0x29, 0x27, 0x33, 0xa3, 0x6f, 0x58, 0xf8, 0xb3, 0x74, 0x21, 0xe7, 0xce, 0x5d, 0x5d, 0x9e, - 0xa9, 0xaf, 0xc8, 0xf3, 0xb9, 0x2d, 0x5c, 0x4b, 0xc6, 0x50, 0x7b, 0xd4, 0x94, 0xad, 0x78, 0xc3, 0x48, 0xaa, 0x71, - 0xfc, 0xaa, 0x97, 0x22, 0xac, 0xbb, 0x62, 0x78, 0xbd, 0xdd, 0x65, 0xe6, 0xda, 0x16, 0xd3, 0x5f, 0xcb, 0xfb, 0x19, - 0x5a, 0x0f, 0x7c, 0x35, 0x74, 0x73, 0x58, 0xf3, 0xfb, 0xa2, 0xdc, 0x23, 0x2c, 0xb7, 0x7f, 0x27, 0xc6, 0xed, 0xeb, - 0x5b, 0x30, 0x58, 0xc8, 0xe7, 0x66, 0x29, 0x6e, 0xb0, 0x7a, 0x90, 0x2e, 0x28, 0x1c, 0x89, 0xa9, 0x5c, 0xbd, 0x6c, - 0xc5, 0x4d, 0xed, 0x76, 0x9b, 0xb1, 0x4e, 0xa4, 0x56, 0xbe, 0x41, 0xb1, 0x6f, 0x7c, 0x81, 0xed, 0x8f, 0x30, 0xb4, - 0xeb, 0x15, 0xe7, 0xb6, 0xfa, 0xb7, 0xbc, 0xe3, 0xf7, 0xfd, 0x61, 0x13, 0x3a, 0xfe, 0x74, 0x7b, 0xe8, 0x86, 0x07, - 0xd2, 0x77, 0x69, 0x5f, 0x76, 0xa5, 0xa8, 0xbf, 0xe4, 0xc0, 0xa9, 0xf3, 0x63, 0x74, 0x5b, 0xf5, 0xa6, 0xde, 0xc7, - 0x11, 0x5e, 0x2a, 0xff, 0xc3, 0xda, 0xe2, 0x3e, 0xcd, 0x47, 0x7b, 0xde, 0x7a, 0xf2, 0xab, 0xdb, 0x74, 0x17, 0x56, - 0x35, 0x7f, 0x2b, 0x53, 0x1a, 0x2f, 0xce, 0x39, 0x60, 0xf6, 0x4f, 0xd4, 0x64, 0x0f, 0x91, 0xa9, 0xe4, 0x38, 0xae, - 0x62, 0x51, 0xeb, 0x49, 0xa1, 0x11, 0x79, 0xc3, 0xd5, 0x9e, 0x47, 0x83, 0x90, 0xd8, 0x01, 0x22, 0x3f, 0x16, 0x85, - 0xa1, 0x23, 0x16, 0x91, 0x76, 0x8d, 0xcf, 0x8b, 0xfa, 0x08, 0x85, 0x58, 0x4d, 0x84, 0x87, 0x05, 0x79, 0x1f, 0x01, - 0x54, 0xda, 0x4b, 0x5a, 0x5b, 0xe9, 0x20, 0xdb, 0x57, 0x82, 0x64, 0x72, 0x60, 0x24, 0xbd, 0x83, 0xd8, 0xce, 0x79, - 0x15, 0x2e, 0xbf, 0x98, 0x9b, 0x42, 0xee, 0xba, 0xca, 0x97, 0x3e, 0x69, 0x6c, 0x72, 0x80, 0xa3, 0xc2, 0xda, 0x57, - 0x4e, 0xc7, 0x41, 0x1f, 0xc4, 0x5e, 0xfe, 0x77, 0x16, 0xb8, 0x64, 0xdd, 0x05, 0xac, 0x97, 0xbe, 0xcf, 0xc3, 0x84, - 0x12, 0x6a, 0xd2, 0xb2, 0x44, 0x17, 0x36, 0x28, 0x55, 0xda, 0x6f, 0x21, 0xe2, 0xb0, 0xc5, 0x97, 0xdc, 0xa6, 0x51, - 0xb7, 0x52, 0xae, 0x6f, 0xe7, 0x94, 0x43, 0xeb, 0x8d, 0x1d, 0xc3, 0xd6, 0x62, 0xbc, 0x70, 0x18, 0x14, 0xa2, 0xa1, - 0xc6, 0x25, 0xcd, 0x57, 0x50, 0x6b, 0xe4, 0x8e, 0x45, 0x4b, 0x32, 0x9c, 0x3e, 0x6e, 0x39, 0x58, 0xa6, 0x81, 0x18, - 0xce, 0xa7, 0x9e, 0xbc, 0x26, 0xf9, 0x40, 0xc1, 0x0d, 0x9a, 0x65, 0x55, 0xd8, 0x1d, 0xd0, 0xbc, 0x0e, 0x1a, 0xad, - 0xa4, 0xc9, 0xa8, 0x4a, 0xba, 0x9f, 0xa6, 0xf8, 0x5d, 0xc6, 0xba, 0x57, 0x94, 0x12, 0xc6, 0xa8, 0xfe, 0xd0, 0x28, - 0x25, 0x07, 0x37, 0xd9, 0xb2, 0x27, 0xd4, 0x25, 0x62, 0xa2, 0x3c, 0x4f, 0xa1, 0x2b, 0xb4, 0x32, 0x72, 0xa8, 0xae, - 0x78, 0x83, 0x2c, 0x0e, 0x76, 0x96, 0x22, 0x99, 0x0f, 0x3a, 0x52, 0xef, 0x13, 0x4d, 0x21, 0x9c, 0xab, 0x64, 0x74, - 0xe3, 0xee, 0x94, 0x1e, 0x24, 0x70, 0xe2, 0x42, 0x47, 0xdb, 0xa1, 0xd7, 0x02, 0x76, 0xa3, 0x12, 0x7a, 0x8a, 0xdf, - 0xe9, 0xf3, 0x2c, 0x78, 0x3b, 0x12, 0xdb, 0x46, 0x31, 0xe6, 0xa8, 0x3a, 0xf5, 0x07, 0x6b, 0xdb, 0x71, 0xdf, 0x64, - 0xc3, 0x2f, 0x26, 0x7f, 0xd4, 0x41, 0x70, 0xcc, 0x3b, 0x59, 0x0e, 0x04, 0x32, 0x80, 0x4a, 0x27, 0x86, 0xf7, 0xc5, - 0x2e, 0x07, 0x85, 0x5f, 0xf5, 0x32, 0x57, 0xda, 0x96, 0x88, 0x8b, 0x8a, 0x83, 0x6f, 0x70, 0x3d, 0xa6, 0x7a, 0x2f, - 0x1d, 0x02, 0xe3, 0x1b, 0xa9, 0x70, 0x73, 0xdf, 0x0a, 0x03, 0x1d, 0x08, 0xca, 0xd9, 0xa8, 0x51, 0xa7, 0x3e, 0x5f, - 0x2d, 0xc8, 0x0b, 0x3c, 0x56, 0x8a, 0x63, 0xd7, 0x75, 0x2f, 0x3c, 0x96, 0x62, 0x3f, 0xa8, 0x50, 0xfe, 0xe7, 0x08, - 0x50, 0x89, 0x00, 0x46, 0xad, 0xd8, 0xca, 0xee, 0x7f, 0x31, 0x5d, 0xa6, 0xba, 0xa4, 0x48, 0xfd, 0x95, 0xe5, 0x24, - 0x7f, 0xe4, 0x61, 0x8f, 0xca, 0xc6, 0x83, 0x2d, 0x46, 0x81, 0x03, 0x78, 0x98, 0xa4, 0xf0, 0x56, 0xc6, 0x78, 0x5d, - 0xc5, 0x5a, 0x23, 0x15, 0x82, 0x64, 0x66, 0xb7, 0x8d, 0x7c, 0x91, 0x9f, 0x26, 0x41, 0x13, 0x3f, 0xa7, 0xde, 0x2b, - 0x4c, 0x3b, 0x76, 0xd6, 0x12, 0x05, 0xf4, 0xf2, 0x0e, 0xa1, 0x43, 0x56, 0xf1, 0xe5, 0xd4, 0x9a, 0x45, 0x40, 0x62, - 0x71, 0x6d, 0x7c, 0x4d, 0xb3, 0x7d, 0x9e, 0xc5, 0x08, 0xcb, 0x2f, 0xa8, 0x82, 0xcb, 0x14, 0xa8, 0x95, 0xda, 0xb3, - 0xee, 0x30, 0xd8, 0xa1, 0x2c, 0x63, 0x7a, 0x11, 0xb2, 0x28, 0xd2, 0xc4, 0x5a, 0xed, 0x62, 0x34, 0x20, 0xc1, 0x25, - 0x4c, 0x54, 0x28, 0x23, 0xcb, 0x18, 0x90, 0xe6, 0x96, 0xb5, 0x7d, 0x91, 0x51, 0x41, 0xbd, 0xfd, 0xcf, 0xac, 0xf6, - 0x3d, 0x2c, 0xd2, 0xf6, 0x4a, 0xba, 0x7e, 0xff, 0xdb, 0x4d, 0xe8, 0xf2, 0x45, 0xdf, 0x3d, 0x7c, 0xc5, 0x9a, 0xed, - 0x0d, 0x7c, 0xe9, 0xc3, 0xa0, 0x49, 0x99, 0x1c, 0x0a, 0x03, 0xcd, 0x32, 0x6e, 0x44, 0x6b, 0x07, 0x3c, 0xb2, 0xc3, - 0xb2, 0x89, 0xbc, 0xce, 0x6b, 0xaa, 0x67, 0x57, 0xa4, 0x61, 0x96, 0x26, 0xc5, 0x05, 0xa0, 0xb7, 0xbe, 0xd2, 0x35, - 0x55, 0x23, 0x4b, 0x60, 0x82, 0x62, 0x10, 0x6f, 0x4e, 0x65, 0x97, 0x36, 0xba, 0xf0, 0x28, 0x6f, 0x62, 0xac, 0x1f, - 0xb1, 0xdd, 0x01, 0x81, 0x4a, 0xd5, 0x02, 0x75, 0x2f, 0x0c, 0xe6, 0xe4, 0xaa, 0xa3, 0xda, 0xca, 0x48, 0x90, 0x4d, - 0xc3, 0x36, 0xbf, 0xd0, 0x70, 0x47, 0xc9, 0x26, 0x41, 0x52, 0xc8, 0x26, 0x63, 0xce, 0x8b, 0xda, 0xbd, 0x22, 0x66, - 0xa2, 0x4f, 0x1e, 0xdb, 0x39, 0xc8, 0x74, 0xb7, 0xcf, 0xe9, 0x63, 0x95, 0xc0, 0xe1, 0x9e, 0x46, 0x31, 0x3b, 0x5a, - 0xe1, 0xcf, 0x0b, 0xda, 0x9a, 0x61, 0xec, 0x21, 0x5c, 0xbd, 0x95, 0x12, 0x48, 0xdc, 0x8b, 0x2a, 0x38, 0xdb, 0x90, - 0xf4, 0xdb, 0xd1, 0x67, 0x4a, 0x8e, 0xe4, 0xca, 0x7e, 0x41, 0x5b, 0x27, 0x4e, 0x7c, 0x04, 0xe7, 0xed, 0xd6, 0x0b, - 0x43, 0x4f, 0x5b, 0xba, 0x0b, 0x5f, 0x16, 0xf7, 0x72, 0x75, 0x46, 0x3d, 0xb8, 0x8e, 0x4b, 0xb5, 0x20, 0x11, 0x2c, - 0x5a, 0xe7, 0x22, 0x5d, 0xe0, 0xe5, 0x78, 0xe4, 0xfc, 0x54, 0xc4, 0xae, 0xa0, 0x85, 0xf8, 0x90, 0x89, 0x8a, 0xf5, - 0xd6, 0xd1, 0x9f, 0xb8, 0x27, 0xd2, 0x20, 0xb7, 0xeb, 0xd1, 0x8e, 0xec, 0xe1, 0x47, 0xb5, 0xe4, 0x8a, 0xc2, 0x5e, - 0x25, 0x3b, 0xdf, 0xf5, 0x1a, 0x33, 0xeb, 0x9b, 0x65, 0x1f, 0x42, 0xb0, 0x80, 0xec, 0x14, 0xdf, 0xcb, 0x0b, 0xc8, - 0xbf, 0xc8, 0x58, 0x66, 0x31, 0x30, 0x93, 0x61, 0xc3, 0xe0, 0x1f, 0xb4, 0xa8, 0xd4, 0xcb, 0xe9, 0x38, 0xb8, 0x23, - 0x8e, 0x86, 0x43, 0x32, 0x55, 0x25, 0xdd, 0x3f, 0x18, 0x65, 0x5d, 0x0a, 0x27, 0x98, 0x64, 0xda, 0xfe, 0x15, 0xb4, - 0xda, 0x35, 0xef, 0x48, 0x72, 0x22, 0x3b, 0x53, 0xbb, 0xa6, 0x71, 0x43, 0xeb, 0x96, 0xce, 0x1d, 0xbd, 0x7b, 0x06, - 0x0f, 0xac, 0xbc, 0xe2, 0x6d, 0x49, 0xe2, 0x9d, 0x40, 0x85, 0x77, 0x03, 0x55, 0xde, 0x0b, 0xb4, 0xf1, 0xbe, 0xa4, - 0x9d, 0x0f, 0x02, 0x19, 0x5b, 0x88, 0xb9, 0xd5, 0x5c, 0x37, 0xb7, 0x9e, 0x8b, 0xb5, 0x7e, 0x30, 0x48, 0xb5, 0x1b, - 0xff, 0x9c, 0x3c, 0xfb, 0x52, 0xb7, 0xdd, 0x8e, 0xfb, 0xf9, 0xfe, 0x69, 0xb4, 0xb7, 0x3f, 0x99, 0x42, 0xe7, 0x45, - 0x12, 0x69, 0x7c, 0xee, 0xf5, 0x30, 0x04, 0xeb, 0xdc, 0x18, 0x7d, 0xdd, 0x05, 0x0d, 0xe5, 0x2e, 0x6c, 0x97, 0x7f, - 0xee, 0xfd, 0xc7, 0x93, 0x5f, 0x15, 0xf5, 0xd8, 0xfa, 0x50, 0x9a, 0xc5, 0x65, 0x00, 0xae, 0x3b, 0xd1, 0x78, 0xe5, - 0x82, 0x37, 0x86, 0xfe, 0xcc, 0x92, 0x96, 0x98, 0x47, 0x44, 0x3d, 0xd1, 0x12, 0xd7, 0x94, 0x49, 0x9f, 0x87, 0x2e, - 0xb1, 0xe4, 0xc8, 0x0d, 0xfb, 0x5b, 0xff, 0x85, 0x86, 0x3b, 0xad, 0xc6, 0x54, 0x8e, 0xfd, 0xfd, 0xb5, 0x81, 0xea, - 0x72, 0x28, 0xcd, 0xa6, 0x0f, 0x09, 0x13, 0xf5, 0x71, 0x0c, 0x77, 0x6e, 0x0c, 0x17, 0x78, 0x79, 0xb5, 0xa0, 0x5b, - 0x6d, 0xc0, 0x00, 0xcf, 0x79, 0x03, 0x50, 0xc9, 0x08, 0xfc, 0x0b, 0xde, 0xaf, 0x5a, 0x94, 0xe1, 0x8b, 0xd1, 0xef, - 0xce, 0xaf, 0xb6, 0x1f, 0x88, 0x13, 0x1e, 0x2d, 0x56, 0xe8, 0x9a, 0x99, 0xff, 0xb0, 0xc2, 0x7a, 0x8e, 0xbd, 0x9b, - 0xaf, 0x72, 0xde, 0xda, 0x0b, 0xe8, 0xed, 0xae, 0x40, 0x88, 0x40, 0xa3, 0xab, 0xc3, 0x59, 0xdf, 0xe6, 0x8f, 0x1f, - 0x52, 0x36, 0x13, 0x06, 0xe0, 0xd3, 0xca, 0x87, 0x7f, 0x37, 0x7f, 0x53, 0xbc, 0x48, 0xe1, 0x7e, 0xfd, 0xbe, 0x2a, - 0xc2, 0x7f, 0x61, 0x60, 0x7c, 0xc7, 0xc9, 0x05, 0x79, 0x6c, 0xde, 0xae, 0x2c, 0xef, 0xd0, 0xba, 0x68, 0xb1, 0xaf, - 0xcd, 0x13, 0x75, 0xf3, 0xf9, 0x27, 0xaa, 0x39, 0xb7, 0xab, 0xc7, 0xeb, 0xe6, 0xf7, 0xbb, 0xa9, 0x39, 0x7f, 0xc8, - 0x5f, 0xdd, 0x3f, 0x3a, 0xba, 0x6a, 0x38, 0x18, 0x5d, 0x7f, 0x9d, 0x65, 0xbb, 0x61, 0xfe, 0x7e, 0xd1, 0xca, 0x51, - 0x62, 0x95, 0x9a, 0xe5, 0x0f, 0x7b, 0x1f, 0xf3, 0x69, 0x5a, 0xd7, 0xbb, 0x5f, 0xbf, 0xc0, 0xfc, 0x0f, 0x71, 0x23, - 0xda, 0xc3, 0xe3, 0x3f, 0x1b, 0xff, 0xb4, 0x59, 0x73, 0x12, 0x7a, 0x32, 0xd6, 0x2a, 0x88, 0x1a, 0xe3, 0xe9, 0xf9, - 0xc8, 0x90, 0xc6, 0x7f, 0x7a, 0x52, 0x4e, 0x98, 0xe5, 0xc4, 0xd2, 0x7d, 0x4b, 0x78, 0x28, 0x15, 0xe5, 0x46, 0x71, - 0x3c, 0x26, 0xfc, 0xaf, 0x3d, 0xb9, 0x2d, 0x56, 0x29, 0x33, 0x80, 0xfb, 0xa1, 0xe6, 0xfb, 0xc5, 0x75, 0x32, 0x08, - 0xd2, 0x84, 0x89, 0x19, 0x83, 0x31, 0x51, 0x4e, 0xdd, 0x50, 0x08, 0xbe, 0x91, 0x53, 0x8a, 0x9c, 0x5a, 0xba, 0x3f, - 0x11, 0x1e, 0x0e, 0xcf, 0xee, 0x86, 0xa3, 0xdd, 0xcf, 0x1f, 0xb8, 0x9d, 0xe4, 0xd4, 0x98, 0x2f, 0x4f, 0x8d, 0xc6, - 0x9e, 0x01, 0x73, 0xba, 0x40, 0xa7, 0xd5, 0x33, 0xa4, 0xfd, 0x62, 0x20, 0x18, 0xba, 0xf2, 0xd0, 0x76, 0xf1, 0x6d, - 0x8b, 0xcb, 0x8f, 0x0d, 0x7a, 0xcd, 0xb0, 0x1a, 0xfc, 0x53, 0x03, 0xd6, 0x18, 0x13, 0x71, 0x8c, 0x09, 0x4c, 0xf9, - 0x96, 0x66, 0xdd, 0x92, 0x1d, 0x6c, 0xec, 0x29, 0xe5, 0x31, 0x52, 0x32, 0x87, 0xbc, 0x6c, 0xda, 0x98, 0x1b, 0x3c, - 0x2b, 0x9f, 0xe7, 0x76, 0xd2, 0x8e, 0xd0, 0x48, 0xc8, 0xf7, 0xac, 0xd8, 0xa4, 0xe8, 0xcc, 0x21, 0xee, 0x6c, 0x9d, - 0xcd, 0x31, 0x3e, 0x71, 0x44, 0x94, 0xdd, 0x7b, 0xd1, 0xd1, 0xbe, 0xd2, 0x17, 0xe4, 0x6c, 0x2e, 0xbf, 0xcd, 0x31, - 0xcf, 0xf2, 0xe8, 0x91, 0xf4, 0x42, 0xdf, 0x4b, 0x33, 0x8e, 0xc7, 0xbc, 0x6a, 0x69, 0x9e, 0xdd, 0x83, 0x78, 0x46, - 0x21, 0x68, 0x33, 0x4c, 0x7f, 0x7c, 0x33, 0x9f, 0x22, 0x75, 0x2f, 0xe3, 0x5e, 0x36, 0x0d, 0xe8, 0xb0, 0xa1, 0x03, - 0xaa, 0x42, 0x82, 0xa9, 0x55, 0xe8, 0x77, 0x2b, 0x2e, 0xb3, 0x55, 0x5a, 0xbc, 0x45, 0x73, 0x77, 0x65, 0x12, 0x97, - 0x11, 0xfa, 0xdd, 0xf5, 0x45, 0xb2, 0x3e, 0x03, 0xc6, 0x2d, 0x36, 0x14, 0xb3, 0xff, 0x58, 0xea, 0xf1, 0x89, 0x96, - 0x91, 0x81, 0x7d, 0x7d, 0x79, 0xee, 0xae, 0xb5, 0x67, 0x1b, 0x15, 0xb1, 0x31, 0xc5, 0xdc, 0xdc, 0xfa, 0x79, 0xb6, - 0x22, 0x99, 0xdc, 0x36, 0xe1, 0x0c, 0x98, 0xa3, 0x6b, 0xb8, 0x2b, 0x88, 0x71, 0x16, 0x40, 0x43, 0xe1, 0x6c, 0xdf, - 0x84, 0xcb, 0x0b, 0x49, 0x6c, 0x8c, 0x12, 0x7d, 0xe9, 0x7f, 0x77, 0x7e, 0x6a, 0xd0, 0x0f, 0x92, 0xd0, 0x73, 0xef, - 0xd1, 0xe9, 0xf6, 0xa7, 0xf9, 0x54, 0xfd, 0xac, 0xb5, 0x8d, 0x2f, 0xa0, 0x4f, 0x7d, 0x68, 0x79, 0xfb, 0x98, 0x51, - 0x80, 0x95, 0x94, 0xe2, 0x6b, 0x47, 0x75, 0x4c, 0xfd, 0x2d, 0x62, 0xea, 0xf8, 0x8d, 0x91, 0x47, 0xdd, 0xce, 0xa5, - 0x8f, 0x79, 0x33, 0xed, 0xb4, 0x67, 0x09, 0x38, 0xc7, 0x7b, 0xb1, 0xa5, 0x27, 0xbd, 0xee, 0x0b, 0x0e, 0x6c, 0x76, - 0x15, 0xf3, 0x36, 0xd7, 0xd0, 0x66, 0xed, 0xe6, 0xef, 0x6a, 0xec, 0x95, 0xf5, 0x56, 0x0f, 0x92, 0xad, 0xbe, 0xcc, - 0xf3, 0xf3, 0x6b, 0x7e, 0x5b, 0x2a, 0x95, 0xb8, 0x53, 0xc6, 0x77, 0xde, 0xff, 0xbe, 0x86, 0xea, 0xd4, 0x53, 0x46, - 0x29, 0xcc, 0x08, 0xcb, 0x27, 0xcf, 0xd3, 0xf2, 0x97, 0x5d, 0xd6, 0x67, 0x3b, 0x6f, 0xc1, 0xd1, 0xe5, 0xc0, 0x71, - 0x62, 0x16, 0x81, 0xef, 0xf1, 0x15, 0x84, 0xf2, 0xe5, 0x14, 0xb0, 0x25, 0xff, 0xc6, 0x84, 0xe4, 0x96, 0x67, 0x2d, - 0x49, 0x6d, 0x24, 0x16, 0x62, 0x38, 0x71, 0xda, 0xf5, 0x01, 0x20, 0xde, 0x22, 0x02, 0xf2, 0x49, 0xe6, 0x7e, 0xb0, - 0xa0, 0x17, 0xc3, 0x02, 0x7b, 0xbe, 0x14, 0x15, 0xbd, 0xe0, 0x1f, 0x32, 0x68, 0xd5, 0x4a, 0x66, 0x0a, 0x0f, 0x52, - 0x50, 0x72, 0xe2, 0xb1, 0xf8, 0x44, 0x08, 0x6d, 0x74, 0x16, 0xca, 0x30, 0x27, 0x6e, 0x79, 0x9a, 0x83, 0xab, 0xcb, - 0xac, 0xf5, 0x62, 0xec, 0xdd, 0x61, 0xe7, 0x11, 0x32, 0xdc, 0x1f, 0xae, 0xcb, 0xda, 0x92, 0xb6, 0x04, 0xb4, 0xd6, - 0x4e, 0x80, 0x3e, 0xea, 0xd2, 0x2d, 0x77, 0x5d, 0x02, 0x0b, 0xa7, 0xec, 0xee, 0x02, 0xec, 0x82, 0x64, 0xc6, 0xf9, - 0x19, 0xec, 0xdc, 0xe3, 0x0f, 0xf0, 0xfd, 0x0c, 0xda, 0x02, 0x7c, 0x3b, 0x83, 0xf5, 0xeb, 0x08, 0x7c, 0x3d, 0x03, - 0x73, 0x00, 0x67, 0x67, 0xf0, 0x57, 0xf1, 0x7b, 0xe9, 0xe9, 0x19, 0xf8, 0x97, 0x0a, 0x5f, 0xd8, 0x8d, 0x35, 0x84, - 0x13, 0xd6, 0xbc, 0x16, 0x8e, 0xe1, 0x80, 0xd7, 0xac, 0x5d, 0x61, 0x0f, 0xbf, 0x23, 0x63, 0xb0, 0x8f, 0xd8, 0x23, - 0x6f, 0x70, 0xc4, 0xec, 0x0e, 0x87, 0x97, 0x86, 0x77, 0xfb, 0xff, 0xb1, 0xb1, 0x3c, 0x4c, 0xd8, 0x7e, 0x8b, 0xbf, - 0x54, 0x42, 0x85, 0xcf, 0xff, 0x53, 0xbd, 0x80, 0xe9, 0x19, 0xd4, 0x05, 0xf8, 0x74, 0x06, 0xdb, 0x02, 0x7c, 0x3c, - 0x83, 0xdb, 0x52, 0xd7, 0x0d, 0x70, 0x70, 0x06, 0x7a, 0x07, 0x3e, 0x9c, 0xc1, 0xe6, 0x1b, 0x78, 0x73, 0x06, 0xea, - 0xf8, 0xed, 0x81, 0xb7, 0x67, 0xa0, 0x57, 0xe0, 0x9d, 0x67, 0x60, 0xe0, 0xfd, 0xdf, 0x38, 0x7f, 0x83, 0x91, 0x53, - 0x76, 0x9f, 0xe5, 0x2b, 0x46, 0xd3, 0x0f, 0xc9, 0x63, 0x27, 0xce, 0x2c, 0xc0, 0x67, 0xfb, 0x6f, 0xa4, 0xe9, 0x26, - 0x5b, 0x6c, 0x02, 0x29, 0x5c, 0x55, 0x66, 0x0c, 0x8c, 0xff, 0x23, 0x7e, 0x66, 0x0e, 0x86, 0x46, 0x12, 0x1b, 0xd9, - 0xc0, 0xaa, 0xed, 0xf9, 0x3f, 0xb6, 0x09, 0xbb, 0x5b, 0x45, 0xb6, 0x73, 0xef, 0xf1, 0xe3, 0xa3, 0xfb, 0xca, 0xa6, - 0xb1, 0x48, 0x03, 0xaa, 0xba, 0x80, 0x8e, 0x94, 0x52, 0x0b, 0xe6, 0x6e, 0xf5, 0x4f, 0x84, 0x6f, 0x2e, 0x78, 0x84, - 0xd9, 0xad, 0x34, 0x52, 0x80, 0x94, 0x99, 0xfe, 0x27, 0x57, 0x7b, 0xa4, 0x2c, 0x3d, 0xcb, 0xa2, 0xf2, 0xa9, 0xf7, - 0xc9, 0xcb, 0xe4, 0x98, 0x65, 0x2e, 0xd4, 0x38, 0xf4, 0xf3, 0x14, 0x02, 0xca, 0x21, 0x25, 0xdc, 0x9e, 0x86, 0x97, - 0x8c, 0xe1, 0x5b, 0x72, 0xeb, 0x05, 0xf6, 0x9e, 0x60, 0xc8, 0xed, 0x98, 0x02, 0xab, 0x98, 0xa9, 0x0d, 0xfa, 0x08, - 0xc4, 0x71, 0x53, 0x6a, 0xfc, 0x35, 0xfa, 0xf0, 0x76, 0xb1, 0xab, 0xe3, 0x60, 0x50, 0xf5, 0x3b, 0x0d, 0x8f, 0x88, - 0x4a, 0xca, 0x21, 0x8b, 0x16, 0x59, 0xb2, 0xfd, 0x85, 0x03, 0x4a, 0xd0, 0x44, 0xbb, 0xd2, 0xf2, 0x9a, 0x14, 0xbc, - 0x1c, 0x5d, 0x30, 0x19, 0x8e, 0x67, 0xf0, 0x0c, 0x52, 0x7f, 0xce, 0x1b, 0x5e, 0x01, 0xda, 0xe0, 0x93, 0xee, 0xd7, - 0x75, 0xc7, 0x17, 0x7a, 0x47, 0x69, 0xc6, 0x15, 0x3e, 0x8b, 0xdf, 0x30, 0xcb, 0x5c, 0xff, 0x46, 0x90, 0x66, 0x7b, - 0xeb, 0x69, 0x0b, 0x60, 0xfe, 0x01, 0xdb, 0xb3, 0x97, 0x33, 0x5c, 0x6c, 0xed, 0x51, 0x54, 0x2b, 0x2d, 0x38, 0xe8, - 0x6e, 0x33, 0xe0, 0x6e, 0x31, 0xb8, 0x67, 0x47, 0x7b, 0x25, 0x14, 0x4e, 0x44, 0xab, 0x0c, 0x45, 0x76, 0x00, 0xdf, - 0xb1, 0xb1, 0x25, 0x1a, 0xe9, 0xf4, 0xa0, 0x6f, 0xd0, 0xb6, 0x44, 0x10, 0xb6, 0x6e, 0xb7, 0x88, 0x81, 0xec, 0x55, - 0xe2, 0x7f, 0x5f, 0xee, 0x65, 0xd4, 0xd2, 0x4c, 0xdf, 0xe3, 0x3b, 0xe6, 0xa7, 0xb4, 0x50, 0x9f, 0x24, 0x65, 0xec, - 0x34, 0xfe, 0xe9, 0xcf, 0x90, 0xe7, 0x78, 0xd5, 0x55, 0x00, 0x14, 0xdc, 0xd0, 0x28, 0xfe, 0x90, 0xcf, 0x9a, 0xb0, - 0x70, 0x19, 0x79, 0x5c, 0x30, 0xc0, 0x2c, 0x73, 0xdc, 0xc4, 0xd8, 0x70, 0x71, 0x58, 0x70, 0x98, 0x99, 0x74, 0x99, - 0xd1, 0xeb, 0x62, 0x5c, 0x8a, 0xd6, 0x7d, 0x35, 0x35, 0x7e, 0x93, 0x19, 0xa1, 0x0f, 0x4f, 0xc3, 0x80, 0x5d, 0xc4, - 0xd8, 0xbf, 0x6b, 0x70, 0x55, 0x30, 0xb6, 0x55, 0x83, 0x15, 0xa5, 0x66, 0x95, 0xbf, 0x7c, 0x76, 0xd4, 0x1f, 0xde, - 0xe4, 0xd6, 0x33, 0x06, 0x0c, 0xfb, 0x82, 0x09, 0x6d, 0xca, 0xdf, 0x1b, 0x93, 0x88, 0x5e, 0x70, 0x6e, 0x7c, 0x4a, - 0x16, 0x6e, 0x9a, 0x61, 0x2a, 0x76, 0xd0, 0x24, 0x75, 0x08, 0xb1, 0x89, 0xbf, 0x7d, 0xf2, 0xe4, 0x39, 0xa4, 0x7c, - 0x4e, 0x44, 0x92, 0x68, 0x75, 0x47, 0xf1, 0x6c, 0xe2, 0x8a, 0x67, 0x41, 0x54, 0x72, 0x03, 0xc0, 0x11, 0xe8, 0xd2, - 0x74, 0xf8, 0xdd, 0x7e, 0xdc, 0x6b, 0x03, 0xcc, 0x36, 0xd6, 0xdd, 0xc7, 0xa1, 0x31, 0xe5, 0x19, 0xdd, 0x0f, 0x7a, - 0xe5, 0x39, 0x78, 0x9a, 0x5f, 0xa6, 0x24, 0x43, 0x86, 0xd5, 0xcc, 0xa1, 0xc3, 0x75, 0x54, 0xe5, 0x1a, 0xb4, 0xe0, - 0x63, 0xaa, 0xd4, 0xc8, 0x9b, 0xf7, 0x87, 0xeb, 0x82, 0xe4, 0x68, 0x07, 0xb4, 0xf6, 0x7a, 0x98, 0x5d, 0x08, 0x0c, - 0x52, 0x48, 0xb8, 0x63, 0x5b, 0x7b, 0x7f, 0xa7, 0x87, 0xeb, 0xed, 0x4b, 0x94, 0x5b, 0x6f, 0x7d, 0x60, 0x96, 0xfe, - 0xa4, 0xb3, 0x2b, 0xc3, 0x8e, 0xbf, 0x5a, 0x93, 0x0f, 0x6f, 0x6a, 0x6d, 0xa4, 0x64, 0xfa, 0xea, 0x82, 0x1f, 0x27, - 0x8c, 0x09, 0x9e, 0x81, 0x98, 0x10, 0xd5, 0xe9, 0x7a, 0x49, 0x22, 0x8a, 0xad, 0x09, 0x91, 0x52, 0x24, 0x11, 0xc9, - 0x49, 0xba, 0xab, 0x9b, 0xe2, 0x93, 0xd3, 0x13, 0x69, 0xe6, 0x0e, 0x0c, 0x60, 0xa9, 0x4f, 0xcf, 0xe6, 0x2c, 0x7f, - 0x23, 0x10, 0x7e, 0x94, 0x02, 0x96, 0xd6, 0x60, 0xf2, 0x80, 0xbd, 0xa4, 0x7e, 0xa6, 0xea, 0x2e, 0x9a, 0x14, 0xc9, - 0xa3, 0x67, 0x80, 0xad, 0x9c, 0x72, 0x84, 0x2a, 0xd3, 0x4c, 0x48, 0x8e, 0x73, 0x6b, 0x32, 0x27, 0x21, 0x94, 0x9c, - 0x99, 0x7b, 0xc4, 0xf2, 0x29, 0xfc, 0xb2, 0x29, 0x6f, 0x7a, 0x27, 0x5b, 0x8a, 0x75, 0x35, 0x84, 0xe1, 0xc4, 0x80, - 0xdf, 0x42, 0xec, 0xf5, 0xd6, 0x91, 0x34, 0xc8, 0x79, 0xf2, 0x8c, 0x23, 0x6c, 0x5c, 0x62, 0xa3, 0x6f, 0x36, 0x4a, - 0x12, 0x72, 0x40, 0x26, 0xbb, 0x50, 0x72, 0x72, 0x07, 0xef, 0xc1, 0xc7, 0x36, 0xdd, 0x9f, 0xff, 0xca, 0x13, 0xad, - 0x6a, 0x63, 0x60, 0xd5, 0xd7, 0x03, 0x59, 0x99, 0x7c, 0x25, 0x40, 0x5b, 0xc0, 0x85, 0xe4, 0x6f, 0x7f, 0xc5, 0x71, - 0x88, 0xaf, 0x32, 0xc8, 0x60, 0xd4, 0xe2, 0x8b, 0xc8, 0x3e, 0xb5, 0x62, 0xe3, 0xef, 0x94, 0xe6, 0x0a, 0x56, 0xb5, - 0x2f, 0x41, 0x64, 0x71, 0x68, 0xba, 0x4f, 0x73, 0xb0, 0x46, 0xad, 0x3f, 0x52, 0xe4, 0x6c, 0x8a, 0xd6, 0x1f, 0x4a, - 0x68, 0x24, 0x2b, 0xde, 0xea, 0x8b, 0x4b, 0xea, 0x2c, 0xaa, 0xa7, 0xa7, 0xc4, 0xa2, 0x62, 0x37, 0x6f, 0x6f, 0x71, - 0x4d, 0xd6, 0x2d, 0xb8, 0x1c, 0x59, 0x19, 0xbe, 0x5d, 0xe9, 0x6c, 0xca, 0xf3, 0x7b, 0x7a, 0x36, 0xb6, 0x60, 0x1f, - 0x7c, 0x6b, 0x53, 0x49, 0x73, 0x61, 0xc5, 0xaf, 0xf2, 0x70, 0x85, 0xdf, 0x90, 0xa0, 0x50, 0x85, 0x3f, 0xbd, 0x48, - 0x8e, 0x8b, 0xef, 0x88, 0x3d, 0x68, 0x5b, 0x83, 0x86, 0xb3, 0x08, 0x33, 0x21, 0x21, 0xe1, 0x00, 0x64, 0xf2, 0x61, - 0xdc, 0x2a, 0xa9, 0x25, 0xb6, 0xa4, 0x97, 0x23, 0x31, 0xe0, 0xf2, 0x5b, 0xb7, 0xc9, 0x4a, 0x57, 0x4f, 0xc1, 0x24, - 0x6e, 0x60, 0x05, 0x53, 0x8f, 0xe3, 0x1b, 0xa5, 0xb3, 0xd2, 0x12, 0x89, 0x04, 0x63, 0x21, 0x44, 0x7d, 0x3f, 0xf5, - 0x26, 0x33, 0x64, 0x45, 0x23, 0x8d, 0x48, 0xd3, 0x4d, 0x30, 0x03, 0x31, 0x81, 0xc2, 0x3c, 0xe6, 0xd6, 0x08, 0x11, - 0x66, 0x98, 0x6e, 0x22, 0x5d, 0xeb, 0x06, 0xcb, 0xf1, 0xfe, 0xa9, 0x1e, 0x8d, 0x79, 0xec, 0x06, 0xb5, 0xb6, 0x91, - 0x86, 0x31, 0x9e, 0xae, 0x10, 0x42, 0xb7, 0x10, 0xc5, 0xc3, 0x9a, 0xb5, 0x9a, 0xc6, 0x7e, 0x74, 0x6d, 0xf7, 0x20, - 0x00, 0xce, 0x63, 0x98, 0x5e, 0x06, 0x51, 0xd2, 0x2b, 0x13, 0x32, 0x1e, 0x91, 0x66, 0xe4, 0xc9, 0x15, 0xad, 0x22, - 0xad, 0xc1, 0xc2, 0xaa, 0x12, 0xc9, 0x9f, 0xa0, 0x52, 0x08, 0x49, 0xfa, 0x9e, 0xe6, 0xc3, 0xa3, 0xa5, 0x32, 0x56, - 0xbc, 0xa7, 0xef, 0xf3, 0xdb, 0xd5, 0x7c, 0x8d, 0x48, 0x98, 0x27, 0x40, 0x7c, 0x5d, 0xc0, 0x71, 0x5e, 0x95, 0x7c, - 0x0a, 0x12, 0x03, 0x03, 0xa1, 0x10, 0x6a, 0xbf, 0xc7, 0x99, 0xbb, 0x2a, 0x2b, 0x85, 0x20, 0x79, 0xb8, 0x15, 0xc5, - 0xcd, 0x48, 0xa5, 0xb1, 0x22, 0x48, 0xc6, 0x77, 0xf3, 0xa5, 0xaf, 0x25, 0x7b, 0xeb, 0x41, 0x26, 0x13, 0xc4, 0x59, - 0xfc, 0x7f, 0x96, 0x37, 0xcd, 0x7e, 0xbf, 0xf8, 0x52, 0x13, 0x23, 0x45, 0xb2, 0x97, 0x6a, 0xf2, 0xf4, 0x2f, 0x53, - 0x96, 0x01, 0x87, 0x44, 0x4b, 0x5f, 0xa1, 0x09, 0x0e, 0xb4, 0x21, 0xb3, 0x59, 0x80, 0x50, 0x48, 0x69, 0x31, 0xda, - 0x5d, 0xa4, 0x3a, 0xcb, 0xea, 0x98, 0x9d, 0x35, 0x33, 0x2c, 0x2a, 0xfd, 0x10, 0xb3, 0xa7, 0x61, 0xa6, 0x37, 0x59, - 0xf1, 0x8f, 0xd9, 0x4d, 0xca, 0xaf, 0xd9, 0x4d, 0x51, 0x06, 0x45, 0x1e, 0x1c, 0xe4, 0x90, 0x0b, 0xee, 0x26, 0x36, - 0x12, 0x75, 0x0f, 0x96, 0x0d, 0x93, 0x8b, 0x13, 0xbb, 0x24, 0x90, 0xb4, 0xc1, 0xe3, 0xbd, 0xde, 0x47, 0xf8, 0x90, - 0x0a, 0xf3, 0x7c, 0xfc, 0x21, 0x93, 0x93, 0xc9, 0x85, 0xcb, 0xea, 0x07, 0x66, 0x77, 0x41, 0xa2, 0x07, 0xe6, 0xc7, - 0xee, 0xd8, 0x49, 0x94, 0x82, 0x4c, 0xe6, 0x7a, 0x8b, 0xb4, 0xc7, 0xf4, 0xb1, 0x59, 0x75, 0xbf, 0x8c, 0xea, 0xfe, - 0xa0, 0xe8, 0x15, 0x8e, 0xb0, 0xf7, 0xa3, 0x72, 0x12, 0x68, 0xea, 0x29, 0x77, 0x6d, 0xe0, 0xde, 0xab, 0x58, 0x98, - 0xbc, 0x99, 0xe5, 0x1b, 0xcf, 0xb6, 0x2f, 0x52, 0xe7, 0xd9, 0x3a, 0x6a, 0x76, 0x1f, 0x97, 0x95, 0x64, 0x89, 0x73, - 0x81, 0x32, 0x46, 0xa0, 0x9a, 0x86, 0xe7, 0xae, 0x0b, 0x9b, 0x49, 0x69, 0x38, 0x8d, 0x9e, 0x50, 0x35, 0x48, 0x9d, - 0x53, 0x8a, 0x46, 0xb3, 0xf8, 0x2e, 0xe5, 0x9c, 0xe7, 0x4c, 0x38, 0x00, 0xa5, 0x94, 0x4b, 0x25, 0xcb, 0xf6, 0xf1, - 0x98, 0x0a, 0x7e, 0x67, 0xa2, 0xf0, 0x47, 0x17, 0x78, 0xe4, 0xba, 0xee, 0x6e, 0x08, 0x63, 0xe5, 0x0a, 0x3a, 0x83, - 0xf3, 0x3a, 0xf6, 0x8b, 0xce, 0x30, 0x19, 0x9e, 0xc1, 0xa8, 0x9e, 0xe5, 0x0c, 0xef, 0x57, 0x71, 0x5b, 0x56, 0x9e, - 0xbf, 0x73, 0x5d, 0x6b, 0xf3, 0x03, 0xce, 0x50, 0x53, 0x0f, 0x73, 0xa5, 0xc6, 0xf9, 0x9a, 0x01, 0x77, 0xaf, 0xe5, - 0x39, 0x58, 0x51, 0x61, 0xc1, 0x16, 0xcc, 0xb0, 0x01, 0xaa, 0x8b, 0xfc, 0x28, 0xa9, 0x60, 0x85, 0x0b, 0xaf, 0x57, - 0xfb, 0xeb, 0xaa, 0x0f, 0xa8, 0xa1, 0xcc, 0x3d, 0xae, 0xf0, 0x90, 0xfa, 0x0a, 0xbb, 0x12, 0x23, 0xbb, 0x05, 0xd7, - 0x78, 0xdc, 0xf6, 0xe6, 0xb5, 0x78, 0x2c, 0x9a, 0x9d, 0xf6, 0x23, 0xc6, 0x26, 0x16, 0xcf, 0xc2, 0x42, 0x27, 0xc9, - 0x99, 0xef, 0xbc, 0x57, 0x8a, 0xf2, 0xfc, 0x81, 0xb1, 0x9f, 0x25, 0x91, 0x20, 0x94, 0xd4, 0xf6, 0x4f, 0x08, 0xad, - 0x61, 0xaa, 0xa5, 0x34, 0x17, 0xd1, 0xe7, 0x1a, 0x0c, 0x98, 0x12, 0x66, 0x39, 0x8d, 0xca, 0x6b, 0x5b, 0xb6, 0x63, - 0xde, 0xf9, 0x53, 0xa9, 0x05, 0x91, 0xcc, 0x8f, 0xd1, 0x88, 0x60, 0x43, 0x4c, 0x90, 0x79, 0x33, 0x9f, 0x96, 0xd3, - 0x92, 0xcf, 0xbb, 0xf9, 0xc3, 0xe2, 0x81, 0xca, 0x6d, 0xf5, 0xb9, 0xa6, 0x33, 0x94, 0x87, 0xba, 0x7a, 0x53, 0x5d, - 0xa3, 0xbb, 0x39, 0xf4, 0x5d, 0x59, 0xe9, 0xbd, 0xf9, 0xef, 0x77, 0x67, 0xc9, 0x7b, 0xc0, 0xf4, 0xa2, 0x6a, 0xb4, - 0x9f, 0x00, 0x9e, 0xe5, 0xd2, 0xc1, 0xff, 0x54, 0xa4, 0x26, 0x57, 0xd1, 0x04, 0xf4, 0xdd, 0xcc, 0x0d, 0x48, 0x5b, - 0xd9, 0x74, 0x06, 0x8d, 0xa1, 0xe6, 0xa8, 0x5e, 0x19, 0xf1, 0xe7, 0xf2, 0xaf, 0x57, 0x18, 0x18, 0xd6, 0x32, 0x33, - 0x16, 0x21, 0x83, 0x59, 0x9a, 0xd8, 0xe4, 0x9d, 0xe6, 0xf4, 0xe7, 0x76, 0xed, 0xe6, 0xab, 0xdd, 0x7b, 0x0b, 0xb2, - 0xc0, 0x09, 0x86, 0x93, 0x4f, 0x1c, 0x2a, 0x8a, 0xcb, 0xb7, 0x75, 0x3d, 0xfd, 0xd7, 0xed, 0xdb, 0xd0, 0xfb, 0xe6, - 0xac, 0x98, 0xd4, 0xb4, 0xec, 0x1e, 0x4d, 0x0b, 0x30, 0x7f, 0x2a, 0x6e, 0xbf, 0xec, 0xf9, 0x36, 0x8e, 0x16, 0x47, - 0x07, 0xe3, 0x67, 0xf7, 0xd7, 0x3b, 0x06, 0xc0, 0xe3, 0xcf, 0x29, 0xa9, 0xa6, 0x39, 0x5d, 0xfc, 0x70, 0xca, 0xa1, - 0xc6, 0x39, 0x39, 0x4f, 0x81, 0x3c, 0x6c, 0xb7, 0xcd, 0xc3, 0x71, 0x53, 0x45, 0x4c, 0x67, 0x8e, 0xa0, 0x37, 0xe9, - 0x2b, 0x8a, 0x30, 0x53, 0xe1, 0xc2, 0xf4, 0x53, 0x96, 0xb2, 0xd4, 0xe8, 0x74, 0x91, 0x55, 0x39, 0x60, 0xe9, 0xdb, - 0x89, 0x6f, 0x3c, 0x22, 0x4d, 0xb1, 0xc1, 0xd8, 0x3a, 0xe4, 0x04, 0xb1, 0x0c, 0x1f, 0x8e, 0xe5, 0xed, 0x25, 0x5e, - 0xe2, 0x39, 0x56, 0xd7, 0xc9, 0x37, 0x6f, 0x82, 0x13, 0x63, 0x7b, 0x1e, 0x6e, 0xb0, 0xd1, 0x46, 0x3e, 0xe4, 0x46, - 0x33, 0x14, 0xb8, 0xaa, 0xc4, 0xac, 0x02, 0x7d, 0x41, 0x97, 0x83, 0xe7, 0xe6, 0x5d, 0x5b, 0x05, 0x6d, 0x02, 0x37, - 0x39, 0x83, 0xa3, 0x76, 0xa7, 0x36, 0x98, 0x7e, 0x3c, 0x17, 0xa4, 0xa7, 0xbe, 0x73, 0x1f, 0x52, 0xbe, 0xb1, 0x40, - 0x35, 0x62, 0x44, 0x0d, 0x1c, 0xe0, 0x65, 0x9f, 0x87, 0xe6, 0x0d, 0x95, 0xbd, 0x57, 0x0b, 0x08, 0xa3, 0x29, 0xe4, - 0xae, 0x00, 0xec, 0x84, 0x21, 0x42, 0x83, 0xa3, 0x13, 0x00, 0x2b, 0xdc, 0xc5, 0xa7, 0xe8, 0x7f, 0x63, 0xbf, 0xbe, - 0x57, 0x71, 0xae, 0xdf, 0x22, 0x4a, 0xd3, 0x14, 0xf9, 0xa3, 0x66, 0x0d, 0x41, 0xa8, 0xb7, 0xe1, 0x66, 0xe9, 0xcf, - 0x7e, 0x80, 0x73, 0x03, 0x6b, 0x2c, 0x89, 0xe1, 0x03, 0x13, 0x4e, 0xd1, 0x86, 0x2b, 0xea, 0xdb, 0x69, 0xb1, 0x70, - 0xee, 0xdf, 0xa8, 0xa8, 0xf7, 0xea, 0xfb, 0xa9, 0xac, 0x7c, 0x22, 0x23, 0x40, 0x9a, 0x9b, 0xa1, 0x23, 0x73, 0x5f, - 0x37, 0x6b, 0xb7, 0x9e, 0xf0, 0x64, 0xb2, 0xf6, 0x20, 0xfd, 0x1e, 0x2f, 0xe5, 0xbf, 0xdf, 0x19, 0xcf, 0xa3, 0x7e, - 0xa3, 0x81, 0x15, 0x45, 0xab, 0x76, 0x34, 0xb1, 0xbe, 0x05, 0x0c, 0x41, 0x20, 0x95, 0x52, 0x3c, 0x21, 0xbf, 0x04, - 0xa3, 0xd2, 0xad, 0xc8, 0xac, 0xcd, 0x09, 0xc3, 0xc2, 0xd3, 0x2d, 0xd0, 0x2b, 0x6e, 0x28, 0xdc, 0x6b, 0x3d, 0xa2, - 0xee, 0x53, 0xe9, 0xbe, 0xce, 0xf8, 0x83, 0xd5, 0x17, 0xa9, 0xde, 0xbe, 0xe7, 0xb7, 0xe5, 0xda, 0xdd, 0xe9, 0x7f, - 0x7d, 0xc8, 0xe7, 0xf6, 0xb4, 0xef, 0xf6, 0x3e, 0x6e, 0xd7, 0x48, 0x3f, 0x5e, 0xb6, 0xf5, 0x29, 0xd6, 0xb5, 0x5b, - 0x54, 0xd9, 0x34, 0x69, 0xb5, 0x89, 0xa7, 0x6c, 0xfc, 0x1b, 0xa2, 0x62, 0x73, 0x88, 0x23, 0xf3, 0xc8, 0xa4, 0x72, - 0xce, 0xcf, 0x7f, 0x59, 0xd8, 0xc3, 0xa9, 0x07, 0x5b, 0x39, 0x97, 0xc6, 0x5a, 0xb1, 0x51, 0x21, 0x52, 0x70, 0xc9, - 0xd6, 0xb8, 0xbb, 0xb0, 0xa4, 0xb1, 0x06, 0x6c, 0xc0, 0x50, 0xb6, 0x83, 0x42, 0x6a, 0xc9, 0xde, 0xd9, 0xf1, 0x7a, - 0x3b, 0x46, 0x7f, 0xb0, 0x95, 0x51, 0xbd, 0xed, 0xc8, 0x52, 0xcb, 0x9a, 0xd7, 0x82, 0x96, 0x39, 0xcf, 0x05, 0x9e, - 0x85, 0x32, 0xfd, 0x42, 0x58, 0x17, 0x52, 0x46, 0xeb, 0x80, 0x14, 0xcc, 0x1a, 0x77, 0x5e, 0x94, 0xa5, 0xfd, 0x55, - 0xbd, 0xb8, 0xd3, 0x55, 0x05, 0xba, 0xad, 0x18, 0x95, 0x78, 0xcb, 0x4f, 0x59, 0x95, 0xd0, 0x26, 0x45, 0x2d, 0xdf, - 0x55, 0xe9, 0xf1, 0xda, 0x59, 0x60, 0xb1, 0x8c, 0x14, 0xb3, 0xf1, 0xc0, 0xe8, 0x67, 0x22, 0xfd, 0x40, 0x7f, 0xaa, - 0x4c, 0x41, 0xb0, 0x71, 0xea, 0x92, 0x7f, 0x8f, 0x04, 0x8a, 0x10, 0x4d, 0xce, 0x05, 0x5a, 0xfa, 0x97, 0x26, 0x1e, - 0x15, 0xe5, 0xe4, 0x0a, 0x46, 0x2b, 0xc3, 0xa3, 0xfc, 0x69, 0xae, 0x2b, 0xf4, 0x3c, 0x51, 0xfb, 0x25, 0xbb, 0xfd, - 0x62, 0xe3, 0x68, 0x5b, 0xcc, 0x6b, 0x1c, 0xd9, 0x3b, 0xf6, 0x58, 0x29, 0x45, 0x6e, 0x9f, 0x7a, 0x60, 0xad, 0x4b, - 0x39, 0xee, 0xea, 0xe1, 0x25, 0xdc, 0x9b, 0xbe, 0x91, 0x83, 0xb2, 0xb8, 0x98, 0xb7, 0xfa, 0x91, 0xfe, 0x10, 0xaf, - 0x28, 0x62, 0xd7, 0x12, 0xf6, 0xe9, 0x25, 0xcd, 0xd7, 0xb4, 0xc8, 0x90, 0xe8, 0xf8, 0x4d, 0x1b, 0xe5, 0x8d, 0x61, - 0xd5, 0x39, 0xb8, 0xdf, 0x29, 0x79, 0x82, 0x9a, 0xc3, 0xcc, 0xb0, 0xb1, 0xba, 0x9a, 0xb7, 0x71, 0x72, 0x4f, 0xab, - 0x0a, 0xf7, 0x5c, 0x40, 0x7b, 0x9b, 0xe5, 0x5b, 0x50, 0x1f, 0x73, 0xd4, 0xba, 0xfd, 0xb4, 0x49, 0xca, 0x99, 0x17, - 0xde, 0xd7, 0xa1, 0xa1, 0xfb, 0x2a, 0x9d, 0xdb, 0x18, 0x19, 0xa7, 0x83, 0xaa, 0x4b, 0x06, 0xe3, 0xfe, 0xd1, 0xba, - 0x61, 0xf1, 0x54, 0x6d, 0xad, 0x95, 0xb3, 0xba, 0x95, 0xfe, 0x79, 0x52, 0xc3, 0xda, 0xe5, 0xbc, 0x1e, 0x06, 0x17, - 0xa7, 0x6a, 0xfe, 0xa9, 0x09, 0x96, 0x19, 0x9c, 0xc3, 0xa6, 0x0c, 0xb9, 0x10, 0xc7, 0x87, 0x79, 0x4f, 0xbd, 0xd4, - 0xda, 0x38, 0x47, 0xc2, 0x22, 0xea, 0xb7, 0x82, 0xa7, 0xb9, 0x7c, 0x63, 0xae, 0x7b, 0xd0, 0xd8, 0x26, 0xc3, 0xbf, - 0x2f, 0xe8, 0x5f, 0x7e, 0x19, 0xbe, 0x42, 0x42, 0x94, 0xb4, 0x97, 0x1c, 0xcd, 0x73, 0xed, 0x51, 0xd8, 0x73, 0x60, - 0x21, 0x5e, 0x71, 0x6f, 0x20, 0x7f, 0xa4, 0x5f, 0xfa, 0xe4, 0x14, 0x87, 0x28, 0xa2, 0x81, 0x70, 0xfe, 0x6d, 0x50, - 0x97, 0xd8, 0xf3, 0x89, 0x74, 0x36, 0x68, 0x1c, 0xd8, 0x0d, 0x10, 0x7a, 0x89, 0x4d, 0xd8, 0x4f, 0x54, 0x1b, 0x0c, - 0xe6, 0xd4, 0x34, 0x3d, 0x36, 0x76, 0x6b, 0x08, 0x14, 0xdf, 0x8d, 0xd1, 0xe6, 0x4e, 0x81, 0xd6, 0xcb, 0xa7, 0x9c, - 0x55, 0x59, 0x75, 0x01, 0x2e, 0x0b, 0xaa, 0xe5, 0x90, 0xab, 0x9f, 0xe8, 0x4e, 0x05, 0xa4, 0x4d, 0xec, 0x7f, 0xc6, - 0xf9, 0xc0, 0xde, 0x1b, 0x3f, 0x38, 0xa2, 0xf5, 0xd9, 0x86, 0x2e, 0x84, 0x59, 0xab, 0x43, 0x4a, 0x59, 0x24, 0x72, - 0xdb, 0x6a, 0x7d, 0x1e, 0x2b, 0xa6, 0xf0, 0xe0, 0xdf, 0x9f, 0x44, 0x1a, 0xd6, 0xaa, 0xe8, 0x22, 0x1a, 0xce, 0xb6, - 0x28, 0xcc, 0xeb, 0xf5, 0x20, 0x7f, 0x35, 0xe5, 0x64, 0x03, 0x77, 0x93, 0x51, 0x3a, 0x7b, 0x91, 0x4a, 0x1c, 0x37, - 0x5d, 0x6e, 0x3b, 0xee, 0x48, 0xb7, 0xd8, 0xed, 0x21, 0xa9, 0x5c, 0x16, 0x6a, 0x6f, 0xda, 0xa0, 0x07, 0x8c, 0xa5, - 0xb7, 0x40, 0x8a, 0x6d, 0x19, 0x20, 0x7b, 0xf8, 0x85, 0xa2, 0x84, 0xa8, 0x8b, 0xb9, 0xc0, 0x78, 0x03, 0x01, 0x51, - 0xf6, 0x3c, 0x0b, 0xb6, 0xb5, 0x3c, 0x9a, 0x23, 0x53, 0x9a, 0xa6, 0xaa, 0x3d, 0x87, 0x5c, 0xd2, 0xc5, 0x94, 0x1b, - 0xed, 0x65, 0xfd, 0x70, 0x19, 0x41, 0xd0, 0xfd, 0x96, 0x67, 0xd5, 0xe8, 0x25, 0x10, 0x96, 0x2b, 0x28, 0x4f, 0xa6, - 0xfb, 0x45, 0x53, 0x9c, 0x79, 0x1a, 0xa4, 0x9a, 0x1b, 0x9e, 0x36, 0x13, 0x16, 0x4e, 0x7c, 0x9b, 0x24, 0xfd, 0x51, - 0x2d, 0xaf, 0xb5, 0xf0, 0x81, 0x7a, 0x70, 0xdb, 0xf0, 0x72, 0x34, 0xef, 0x57, 0x5b, 0x9a, 0x53, 0x7e, 0x99, 0x34, - 0xab, 0x9b, 0x72, 0xcc, 0x6d, 0xcc, 0x7a, 0x89, 0x34, 0xda, 0x94, 0xb7, 0xb1, 0x51, 0x32, 0xab, 0xa4, 0x25, 0x72, - 0xfa, 0x1b, 0x4b, 0xa4, 0x86, 0xc9, 0xa5, 0xc8, 0xc5, 0x5f, 0xc9, 0x42, 0xda, 0x7a, 0x6b, 0x74, 0x27, 0x06, 0x4a, - 0xd7, 0x79, 0x8f, 0x5b, 0xc2, 0xb3, 0x5f, 0x02, 0x40, 0xb3, 0x2a, 0x6f, 0x90, 0x72, 0xb1, 0x0a, 0x67, 0x7e, 0xb6, - 0x45, 0x6f, 0x7b, 0x0e, 0xab, 0x55, 0x42, 0xbf, 0x6f, 0x75, 0x05, 0xdc, 0xc0, 0x3e, 0x0f, 0xeb, 0x83, 0x5d, 0x18, - 0xd5, 0x6b, 0x25, 0x84, 0xd5, 0x04, 0x85, 0xb0, 0x72, 0x25, 0xd9, 0x83, 0x28, 0x42, 0x0f, 0xdc, 0x1d, 0x52, 0x9b, - 0x89, 0x78, 0xbe, 0x86, 0xf0, 0xcf, 0x31, 0x7b, 0xa8, 0xe8, 0x92, 0x01, 0x0a, 0xea, 0x47, 0x40, 0x29, 0x64, 0x04, - 0x10, 0x90, 0x90, 0x17, 0x21, 0x98, 0x7a, 0x42, 0xe9, 0x26, 0x38, 0xd2, 0xff, 0xd1, 0x0b, 0x95, 0x95, 0x30, 0x23, - 0x3e, 0xa3, 0x60, 0x14, 0x06, 0x1c, 0xdf, 0x9d, 0x50, 0x78, 0xd4, 0x3c, 0x55, 0x43, 0x7e, 0x7d, 0x78, 0x4f, 0x2f, - 0xb6, 0xd1, 0xbe, 0x50, 0x1f, 0x40, 0x97, 0xba, 0xca, 0x0b, 0x3a, 0x0d, 0x52, 0x45, 0x03, 0x14, 0x21, 0xbc, 0x74, - 0x43, 0x31, 0xc0, 0x0c, 0x8d, 0xcd, 0xc9, 0xc8, 0x8a, 0x2e, 0x6e, 0xba, 0x19, 0x88, 0xbc, 0x70, 0x8e, 0x8d, 0xea, - 0x78, 0xfa, 0x4f, 0xd5, 0xdc, 0x4c, 0x83, 0xb4, 0xc6, 0xd9, 0xd4, 0xa9, 0xcd, 0x10, 0x33, 0x11, 0x71, 0x51, 0xad, - 0x4b, 0xee, 0x25, 0x34, 0x87, 0x5d, 0x78, 0xef, 0x13, 0x6f, 0x29, 0xa5, 0x70, 0x66, 0x75, 0xb6, 0xdb, 0x02, 0x2d, - 0xe9, 0x3c, 0x7b, 0xea, 0x1d, 0x2e, 0x32, 0x15, 0x11, 0xfe, 0x6c, 0x63, 0x32, 0x51, 0x8a, 0xf4, 0x0c, 0xb5, 0x5c, - 0x70, 0x94, 0xec, 0x2a, 0x64, 0xfa, 0x2f, 0x9c, 0xb2, 0x03, 0xd0, 0xb6, 0x9b, 0xf0, 0x6e, 0x72, 0xc7, 0x37, 0xde, - 0xdf, 0xab, 0xbd, 0x2b, 0x36, 0xb5, 0x6b, 0x1c, 0x62, 0x7a, 0xf7, 0x14, 0x7b, 0x40, 0xa0, 0xa2, 0xc5, 0x12, 0x1a, - 0x7b, 0x6e, 0x5e, 0x1e, 0x8f, 0x93, 0x15, 0x25, 0x67, 0x9f, 0xeb, 0x8b, 0x85, 0x6d, 0x3a, 0xf1, 0xd2, 0xed, 0x95, - 0xc3, 0x02, 0x3d, 0x8c, 0x40, 0x38, 0x85, 0x19, 0x4d, 0x80, 0x4e, 0x8f, 0x3b, 0x23, 0x41, 0x39, 0xf5, 0x15, 0x03, - 0x26, 0x90, 0xc7, 0x6a, 0xdc, 0x14, 0x2e, 0x21, 0x67, 0x7b, 0xac, 0x88, 0x91, 0x06, 0x63, 0xfb, 0x3a, 0x28, 0x1c, - 0xa0, 0x13, 0x67, 0x7b, 0xa0, 0xae, 0x13, 0xef, 0x15, 0x79, 0x4d, 0xac, 0x35, 0xde, 0xb7, 0xa6, 0x38, 0x9d, 0x94, - 0xaf, 0x25, 0x9a, 0x23, 0x9a, 0xd3, 0x16, 0xf9, 0x03, 0x58, 0x79, 0xac, 0xbf, 0xb2, 0xba, 0x2f, 0x67, 0xac, 0xbf, - 0x30, 0xb2, 0xe4, 0x36, 0x42, 0x37, 0x1c, 0xac, 0x55, 0x10, 0xed, 0xc1, 0xd6, 0x62, 0xed, 0x08, 0xcb, 0x66, 0x6f, - 0x6b, 0x01, 0xee, 0xb4, 0xe7, 0x22, 0x0a, 0x17, 0x2b, 0xf0, 0x9e, 0xae, 0x21, 0xaf, 0xc4, 0x19, 0xfd, 0x23, 0x9c, - 0x98, 0x83, 0x04, 0xb1, 0x81, 0x1e, 0x95, 0xf5, 0x1f, 0x86, 0xc8, 0xe8, 0x74, 0x33, 0x1a, 0xbb, 0x7c, 0x69, 0xb4, - 0x6a, 0x05, 0x30, 0xa8, 0x6f, 0xf3, 0x78, 0x58, 0xc6, 0x8b, 0x39, 0x0e, 0x6d, 0x6b, 0xdf, 0x78, 0x94, 0x59, 0x78, - 0xff, 0x09, 0x4c, 0x6b, 0xb8, 0x2d, 0xf2, 0x7f, 0x2f, 0xcb, 0x4b, 0x79, 0xb6, 0x2b, 0xe7, 0xe9, 0xbd, 0xdf, 0xab, - 0x3c, 0xbb, 0x3b, 0xbd, 0xb7, 0xd8, 0xe4, 0x81, 0x71, 0x31, 0x47, 0xc0, 0x69, 0xeb, 0xc3, 0xbb, 0xef, 0x5e, 0x1f, - 0xbc, 0xa7, 0x2f, 0x7a, 0xcb, 0x6f, 0x64, 0xd3, 0x87, 0xe1, 0x14, 0x4f, 0xf1, 0xf3, 0x25, 0xef, 0x5a, 0xff, 0x35, - 0xdb, 0x6c, 0xce, 0x6b, 0xef, 0x94, 0xeb, 0x16, 0x57, 0x0d, 0xed, 0xcf, 0xdb, 0x6a, 0x0a, 0x9c, 0x6c, 0x02, 0x45, - 0x7c, 0xdd, 0x15, 0xa7, 0xac, 0x34, 0x80, 0x40, 0xb8, 0x3e, 0xfd, 0x9b, 0x6f, 0x8c, 0x52, 0xd9, 0xe0, 0xed, 0xa7, - 0xe5, 0x27, 0xa3, 0xc3, 0x23, 0x82, 0x0b, 0xd9, 0x7a, 0xa4, 0x7f, 0xe7, 0xe9, 0xce, 0xd7, 0xf3, 0x3c, 0xaa, 0x41, - 0x05, 0x64, 0xa9, 0xc6, 0x99, 0x0d, 0xe2, 0x98, 0xbb, 0xcd, 0x55, 0x4b, 0xc2, 0x37, 0x0b, 0x16, 0xdd, 0x75, 0xc0, - 0x91, 0x17, 0xcc, 0x31, 0x44, 0x70, 0xf8, 0xde, 0x32, 0xca, 0x77, 0xdc, 0x89, 0x1d, 0x0f, 0xc2, 0x22, 0x2c, 0xcf, - 0x5a, 0xd1, 0xb0, 0xfa, 0x81, 0x37, 0x7b, 0xf9, 0xff, 0xda, 0x50, 0xad, 0x17, 0x51, 0x95, 0x6c, 0x2d, 0x04, 0x58, - 0x17, 0xdb, 0x3c, 0x7e, 0x8a, 0x37, 0x76, 0xad, 0x91, 0xc4, 0xc3, 0x73, 0xf7, 0xd3, 0x3d, 0x41, 0x39, 0xce, 0xcf, - 0x3b, 0xbc, 0x46, 0x74, 0x06, 0xf1, 0x11, 0x78, 0x2f, 0xd7, 0x36, 0x28, 0xf8, 0xff, 0xfc, 0x57, 0x97, 0xb1, 0x5a, - 0xd6, 0x03, 0x56, 0x37, 0xfc, 0xb4, 0x0d, 0xde, 0xba, 0xbf, 0x9d, 0x6f, 0xe8, 0xd3, 0xb8, 0xde, 0x63, 0xad, 0xde, - 0x59, 0x97, 0xd6, 0x8c, 0x4e, 0xc2, 0x32, 0x8b, 0xb9, 0x12, 0xb2, 0x9e, 0x6b, 0xf3, 0x48, 0x86, 0x0f, 0x6b, 0xdb, - 0x96, 0x92, 0x83, 0x36, 0x0e, 0x4d, 0xb9, 0xa4, 0x42, 0xda, 0x54, 0x46, 0xff, 0x66, 0xaa, 0x28, 0x99, 0xf5, 0x74, - 0xf6, 0x2c, 0xba, 0x61, 0xa1, 0x4f, 0x81, 0x0c, 0x3c, 0xaf, 0x83, 0xaa, 0x25, 0x69, 0x2a, 0x44, 0x46, 0xa8, 0xa6, - 0x01, 0x6a, 0x9f, 0x54, 0x35, 0x14, 0x9e, 0xeb, 0x39, 0x1d, 0xfc, 0xc2, 0x47, 0x22, 0x48, 0x46, 0x12, 0x47, 0x0d, - 0x32, 0x65, 0x6f, 0xd7, 0xba, 0x57, 0xd7, 0xe9, 0xa9, 0xd3, 0x9c, 0x6d, 0x3e, 0xf2, 0xbf, 0x72, 0x73, 0x52, 0x2c, - 0xb6, 0x11, 0x88, 0x0b, 0x79, 0x8b, 0x29, 0xdb, 0x63, 0xc3, 0x30, 0xa8, 0xe3, 0xd7, 0x9b, 0x36, 0x6e, 0xa3, 0x04, - 0x11, 0xad, 0xe3, 0x93, 0x66, 0x8d, 0x8b, 0xaf, 0x5b, 0xe6, 0x9b, 0xcb, 0xaf, 0xd7, 0x38, 0xaa, 0xf5, 0xd9, 0x4e, - 0x95, 0x9b, 0x6b, 0x71, 0x54, 0x9b, 0xc6, 0x24, 0x3d, 0x21, 0x5b, 0x5e, 0xa0, 0x4d, 0xb9, 0xc9, 0x78, 0x83, 0xd2, - 0x40, 0xea, 0x05, 0xf3, 0x70, 0xb4, 0x33, 0x4f, 0xc7, 0xb7, 0x13, 0x2b, 0x67, 0x13, 0x5d, 0xda, 0x4d, 0xad, 0x85, - 0xf0, 0x78, 0x31, 0xe6, 0x35, 0x87, 0x7c, 0x56, 0x71, 0xe6, 0x7a, 0x1e, 0x4a, 0x8a, 0x30, 0xe1, 0xda, 0x2c, 0xd1, - 0x9b, 0x9b, 0x10, 0x16, 0x4b, 0x4e, 0x17, 0x08, 0x1d, 0x24, 0xcd, 0x77, 0xb4, 0xcf, 0x57, 0x7a, 0x78, 0x7e, 0x7f, - 0x4a, 0xb4, 0xdd, 0x3c, 0xe9, 0xec, 0xf3, 0xbb, 0x67, 0x1a, 0x75, 0xab, 0x54, 0xdb, 0x2a, 0x8a, 0x59, 0x23, 0x01, - 0x57, 0xeb, 0x08, 0xf4, 0xaa, 0x96, 0x3d, 0xd4, 0xd2, 0x47, 0xdd, 0xd5, 0x51, 0xab, 0xe7, 0xa2, 0xd6, 0x3e, 0x95, - 0x2e, 0xcf, 0x37, 0x8d, 0xc2, 0x90, 0x8b, 0xa2, 0x18, 0xa5, 0xa7, 0xdd, 0xb5, 0xf9, 0x32, 0x37, 0xa0, 0x99, 0x7b, - 0x07, 0xb5, 0x3c, 0x0f, 0xa8, 0xe7, 0xc6, 0xff, 0xa9, 0xd8, 0xf2, 0x18, 0x11, 0xaa, 0x3c, 0x9b, 0xa7, 0x15, 0x88, - 0xea, 0xda, 0x92, 0x6f, 0x8c, 0x64, 0xff, 0xf0, 0x8f, 0x7a, 0x3f, 0x4e, 0x4e, 0xe5, 0xef, 0xc0, 0x1d, 0x7d, 0x10, - 0xf7, 0x90, 0xc2, 0x55, 0xbc, 0xe6, 0x2e, 0xb7, 0xc8, 0x34, 0xf8, 0xff, 0xf8, 0xa5, 0x1b, 0x60, 0xe7, 0x78, 0x39, - 0x89, 0xe8, 0x5d, 0x09, 0x4a, 0xda, 0x94, 0xe1, 0x9a, 0x13, 0x0c, 0xf0, 0x7b, 0xdd, 0x31, 0xe5, 0xbc, 0xb1, 0x1c, - 0xc5, 0x52, 0x03, 0x3e, 0x54, 0xf9, 0x84, 0xf6, 0x8f, 0xed, 0x25, 0xbb, 0xba, 0x3c, 0xb6, 0x8d, 0xb3, 0xd4, 0xa6, - 0x65, 0xfb, 0x48, 0x34, 0x82, 0xea, 0x25, 0x81, 0x25, 0xb5, 0xcb, 0xaf, 0x6c, 0xab, 0x50, 0x36, 0x9b, 0xe0, 0xb2, - 0xf6, 0xe6, 0xae, 0x2c, 0x46, 0x9a, 0x65, 0xec, 0x3b, 0xcc, 0x76, 0x63, 0xed, 0xf4, 0x08, 0x09, 0xd5, 0xd3, 0x8a, - 0x65, 0xe9, 0x0b, 0xb1, 0xa7, 0x9f, 0x8f, 0xfa, 0xa9, 0x3d, 0x05, 0x00, 0x30, 0x5a, 0xef, 0x51, 0xc9, 0x0e, 0xae, - 0xdb, 0x20, 0xc0, 0x07, 0x7a, 0x7d, 0x03, 0xa0, 0x39, 0x9e, 0xdd, 0x16, 0x2c, 0xc5, 0x4f, 0xe2, 0x23, 0xf3, 0xb0, - 0xb3, 0x0c, 0x26, 0x70, 0x6b, 0xd6, 0x01, 0xa7, 0x6b, 0x37, 0x36, 0x6d, 0x9c, 0xac, 0xb3, 0xe9, 0xeb, 0x72, 0x0a, - 0x88, 0xe7, 0x6e, 0xdc, 0x1e, 0xa6, 0x8d, 0xab, 0x3b, 0x86, 0xf4, 0x29, 0x5a, 0xd6, 0x1d, 0x3f, 0x23, 0x0a, 0xab, - 0x22, 0xcb, 0x72, 0x86, 0xbd, 0x62, 0x9a, 0xa8, 0x79, 0xcb, 0xad, 0x82, 0x9c, 0x15, 0x60, 0xed, 0xf5, 0x7a, 0x40, - 0x38, 0xb5, 0x1e, 0x7c, 0xfb, 0x3f, 0x75, 0xd4, 0x77, 0xeb, 0xb8, 0x0b, 0xe7, 0x46, 0x0b, 0xcf, 0x53, 0x88, 0xb2, - 0x3c, 0x20, 0xb3, 0xe5, 0xaf, 0xff, 0xf2, 0x94, 0x7c, 0xd2, 0xee, 0xf6, 0x6f, 0xe8, 0xd6, 0x4f, 0x00, 0xc7, 0x36, - 0x3b, 0x40, 0x37, 0x48, 0x75, 0x83, 0x08, 0xda, 0xef, 0x19, 0xe8, 0x66, 0xa0, 0x8c, 0x8a, 0x89, 0xcf, 0x1b, 0xdd, - 0x55, 0x00, 0xfa, 0xfe, 0x9c, 0x6d, 0x71, 0xee, 0xb3, 0x20, 0x6f, 0xc1, 0xaa, 0xd9, 0x1f, 0x05, 0x86, 0x6b, 0xfb, - 0x81, 0x33, 0x08, 0xea, 0x5a, 0x07, 0x4a, 0xbb, 0xdc, 0x3e, 0x5a, 0x01, 0x88, 0x58, 0x58, 0x13, 0x36, 0x51, 0xfd, - 0x97, 0x48, 0x97, 0x34, 0x24, 0x61, 0xa6, 0xfa, 0x89, 0xd8, 0xb3, 0x96, 0x18, 0x56, 0x7a, 0x80, 0x4d, 0x9c, 0x07, - 0x74, 0x83, 0x28, 0x5e, 0x87, 0x06, 0xff, 0x4e, 0x58, 0x90, 0xf7, 0x94, 0xfa, 0xcc, 0x50, 0xd5, 0xa5, 0xb0, 0xe6, - 0x51, 0xaa, 0xc1, 0xf0, 0x1c, 0xda, 0x00, 0x6b, 0x29, 0x6a, 0x6e, 0xbb, 0x24, 0x95, 0x20, 0xf1, 0xc6, 0xd4, 0x77, - 0x33, 0xe0, 0xdd, 0xac, 0x0c, 0xa0, 0x40, 0x52, 0x5f, 0x50, 0xf4, 0xe6, 0xd1, 0x77, 0x6b, 0xc2, 0xb3, 0xd3, 0xdd, - 0x88, 0x49, 0xb2, 0xae, 0xb6, 0x10, 0x11, 0x8b, 0x68, 0xdb, 0x56, 0x85, 0xa1, 0x03, 0x99, 0xe8, 0x51, 0x95, 0xa4, - 0x04, 0xff, 0xcd, 0xd8, 0x2e, 0x46, 0xd4, 0x30, 0xa0, 0xa0, 0x60, 0x6f, 0x8f, 0xdb, 0x85, 0x2f, 0x6f, 0x69, 0xcc, - 0x2d, 0x05, 0x5e, 0x85, 0xc6, 0xc3, 0x3a, 0x90, 0x2b, 0xa2, 0x41, 0xe7, 0x5c, 0x3b, 0xe3, 0xe4, 0xb8, 0x99, 0xf9, - 0x12, 0xcf, 0x9f, 0x5b, 0xfb, 0x7d, 0xa5, 0x14, 0xf9, 0x37, 0x28, 0x24, 0x9c, 0x5a, 0x55, 0xa3, 0xaa, 0x0f, 0x60, - 0x4d, 0xd7, 0x04, 0x77, 0xc6, 0xb3, 0x4f, 0x08, 0x24, 0x3f, 0xe5, 0x52, 0x67, 0x93, 0x36, 0x02, 0xa3, 0x2f, 0xc1, - 0xe4, 0x85, 0xe9, 0x6a, 0x01, 0x71, 0x78, 0xa0, 0x3f, 0x26, 0x8a, 0xe4, 0xa9, 0x22, 0x0a, 0x6a, 0x78, 0xaa, 0x32, - 0x5f, 0x2f, 0xf5, 0x3a, 0xb9, 0xd1, 0xd9, 0x13, 0x8f, 0x69, 0x9b, 0x9a, 0x21, 0x9b, 0xc9, 0x8b, 0xfb, 0xe1, 0xba, - 0x7b, 0x75, 0x1f, 0x14, 0x12, 0x27, 0x37, 0x0d, 0x90, 0xb7, 0xea, 0x44, 0x9e, 0x16, 0x24, 0x80, 0xe5, 0xd2, 0x34, - 0x6b, 0xbf, 0x3c, 0x9a, 0x20, 0x84, 0xcf, 0x86, 0xbd, 0x71, 0x5c, 0x34, 0x4d, 0x27, 0x06, 0x0e, 0x97, 0x37, 0x39, - 0x9e, 0x19, 0x99, 0xad, 0x3b, 0xdf, 0x34, 0x26, 0x1a, 0xba, 0x6a, 0x57, 0x86, 0xc9, 0x1b, 0xa7, 0x5b, 0xee, 0xd4, - 0xee, 0x42, 0x19, 0x5c, 0xa4, 0xcb, 0xa6, 0x6c, 0x04, 0x20, 0xba, 0x76, 0x68, 0x94, 0x27, 0x47, 0x61, 0x42, 0x73, - 0x5b, 0x83, 0x17, 0x40, 0xdb, 0x3f, 0xea, 0x46, 0xa9, 0x17, 0x22, 0x2b, 0x3c, 0xfe, 0x68, 0x23, 0xd7, 0xcb, 0xad, - 0x53, 0xe5, 0xe5, 0x3a, 0x6a, 0xe7, 0xe5, 0xd6, 0xad, 0x66, 0xa5, 0xa9, 0x4d, 0xd8, 0x08, 0x6c, 0x2f, 0xbd, 0xe4, - 0x19, 0x7a, 0xfa, 0x19, 0x7a, 0xc6, 0x36, 0x2f, 0x44, 0x4c, 0xd9, 0xfa, 0x95, 0x57, 0xa4, 0x75, 0x60, 0xff, 0xb3, - 0x7f, 0xdf, 0x40, 0x64, 0x2a, 0x56, 0xbb, 0x4a, 0xc4, 0x14, 0xc8, 0x5a, 0xa1, 0x7e, 0x64, 0x1f, 0xb4, 0xff, 0xda, - 0xfb, 0xed, 0x7d, 0x6e, 0x2a, 0x9a, 0x0c, 0xf8, 0xfd, 0x09, 0x33, 0xcd, 0x31, 0xc4, 0x12, 0x33, 0xba, 0x1f, 0x5d, - 0x47, 0x0e, 0xa6, 0xdf, 0x95, 0x12, 0xff, 0xc9, 0x5d, 0x6d, 0xb7, 0x9c, 0x89, 0x38, 0x22, 0xee, 0x76, 0x40, 0x37, - 0x41, 0x7c, 0x7d, 0xfc, 0xb2, 0x06, 0x97, 0xb9, 0xda, 0x17, 0x59, 0xc8, 0xf0, 0xfa, 0x83, 0x87, 0xec, 0x33, 0xef, - 0xb2, 0x53, 0x73, 0x86, 0x6b, 0x0b, 0xd7, 0x83, 0xe2, 0xcd, 0xcc, 0xaf, 0x03, 0x2f, 0x2a, 0xee, 0x54, 0x67, 0x2f, - 0xaa, 0xf1, 0x10, 0x1a, 0xcf, 0x02, 0xf7, 0x68, 0x9d, 0xd2, 0xbf, 0x66, 0x21, 0x3e, 0x9b, 0xbc, 0xb1, 0x99, 0xc7, - 0xdc, 0xcd, 0x1c, 0x82, 0x94, 0x9f, 0xe4, 0x52, 0x85, 0x91, 0x85, 0x74, 0xd3, 0x92, 0x55, 0xc2, 0x5b, 0xbc, 0x33, - 0x8f, 0xbb, 0x3f, 0x97, 0x78, 0x07, 0xf5, 0x8a, 0xf0, 0x22, 0xb3, 0x27, 0xd7, 0x31, 0x0c, 0xcc, 0x12, 0x2e, 0x64, - 0x0e, 0x8d, 0xd4, 0xdb, 0x5b, 0x3c, 0x71, 0x41, 0xf5, 0x63, 0x78, 0xe7, 0x5d, 0x76, 0x59, 0xc9, 0xed, 0xe1, 0x63, - 0x3d, 0x39, 0x4b, 0xdc, 0x0b, 0x66, 0xce, 0xad, 0xc7, 0x7d, 0x75, 0x26, 0x69, 0x76, 0xe4, 0x22, 0x41, 0x63, 0x01, - 0x2b, 0x31, 0x94, 0x9e, 0xde, 0x71, 0x3c, 0xbb, 0x23, 0xc0, 0x0f, 0x8e, 0xf5, 0x6d, 0x4d, 0xd9, 0x78, 0x72, 0x76, - 0xbd, 0x0d, 0xdc, 0x97, 0x5d, 0xf7, 0x2e, 0x46, 0xa9, 0xba, 0xa1, 0x89, 0x6b, 0x33, 0x10, 0xd8, 0xdd, 0x54, 0x3c, - 0x85, 0xa3, 0xe9, 0xc6, 0xf7, 0x4d, 0x5d, 0x9b, 0x8e, 0x02, 0xd2, 0x2e, 0x01, 0xad, 0x6d, 0xbf, 0xb8, 0xa1, 0x7b, - 0x04, 0xc3, 0x26, 0xc4, 0xc8, 0xe6, 0x6a, 0x3f, 0xac, 0xc7, 0x76, 0xdc, 0xd0, 0x51, 0x67, 0x19, 0x3e, 0x73, 0xd9, - 0x01, 0x7d, 0x26, 0x2f, 0xf4, 0x5d, 0x6c, 0x88, 0x4e, 0xb0, 0xee, 0xd8, 0xe0, 0x93, 0x80, 0x38, 0xbf, 0xf1, 0x0e, - 0x17, 0x70, 0xb9, 0xc0, 0x12, 0xc0, 0xfa, 0xec, 0xc4, 0xe0, 0x99, 0xbe, 0x8b, 0x5d, 0xc7, 0xb9, 0x27, 0xdc, 0x55, - 0x28, 0x05, 0x2e, 0xcd, 0x4f, 0x21, 0x4f, 0x5e, 0xe8, 0x5e, 0x3f, 0x9f, 0x25, 0xa6, 0xee, 0x62, 0x6b, 0x7d, 0xd8, - 0x94, 0x0a, 0x98, 0xfb, 0x94, 0x4e, 0xad, 0x83, 0xe2, 0xed, 0x13, 0x5a, 0x20, 0x0c, 0x63, 0x7b, 0xff, 0xaa, 0x89, - 0x61, 0x3c, 0x8d, 0x67, 0x0e, 0x82, 0x81, 0x11, 0x61, 0x80, 0x2f, 0xf1, 0x5e, 0x4e, 0x48, 0x9e, 0xa0, 0x99, 0x7d, - 0x36, 0x52, 0xec, 0x5d, 0x9e, 0xf4, 0xf5, 0xee, 0x4c, 0x66, 0x8f, 0x0f, 0xef, 0x02, 0x5a, 0xef, 0xc6, 0x4b, 0x0d, - 0x8f, 0x65, 0xed, 0x72, 0x25, 0x96, 0x42, 0xbc, 0x76, 0xd1, 0xfa, 0x6f, 0xda, 0xe4, 0xb0, 0x45, 0x33, 0x18, 0xf9, - 0x4e, 0x5f, 0x9a, 0x63, 0x79, 0x47, 0x5e, 0xd8, 0x48, 0x35, 0x80, 0xe2, 0xca, 0x20, 0xc3, 0x90, 0xb5, 0x77, 0x58, - 0x44, 0x41, 0x61, 0xe8, 0x8a, 0x47, 0x7d, 0x4a, 0x44, 0x9d, 0x04, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xae, 0x0c, 0x4e, - 0x01, 0xb5, 0xe2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x1a, 0x76, 0x26, 0xee, 0x2a, 0xb0, 0x3c, 0xe5, 0x83, 0x5d, 0x5c, - 0x60, 0xe2, 0xbf, 0xee, 0xf5, 0x89, 0x81, 0x23, 0xdd, 0x8d, 0xb0, 0x05, 0x30, 0x0d, 0x76, 0xe5, 0x95, 0xbc, 0xe4, - 0xa9, 0xd7, 0x10, 0x9c, 0x5c, 0x6d, 0x5e, 0x9f, 0xcc, 0xfa, 0x12, 0x84, 0x52, 0xaa, 0x11, 0x76, 0x0b, 0xec, 0xda, - 0x72, 0xb6, 0xae, 0x4e, 0x26, 0x6a, 0xdb, 0xc8, 0xb8, 0x61, 0x3f, 0x63, 0xed, 0x22, 0x76, 0x7d, 0xbc, 0xd8, 0x85, - 0x6c, 0x2a, 0x76, 0x2e, 0x4c, 0x8a, 0x9c, 0x41, 0x07, 0x0e, 0xb5, 0xc3, 0x19, 0x31, 0xd3, 0xed, 0x74, 0xc9, 0x76, - 0xfa, 0xe0, 0x9d, 0x76, 0x4e, 0x05, 0x74, 0x06, 0xe3, 0xec, 0xd4, 0x4e, 0x1a, 0xa1, 0x0b, 0x8c, 0xef, 0x4a, 0xe8, - 0x17, 0xb3, 0x54, 0xc3, 0x6b, 0xd6, 0x80, 0xb4, 0x92, 0x0a, 0xe6, 0xd9, 0x8a, 0x2d, 0x29, 0xdc, 0xe6, 0xc5, 0xd6, - 0xe2, 0x7f, 0xe9, 0x47, 0xba, 0x2e, 0x0f, 0x88, 0x20, 0x1b, 0x88, 0xd2, 0x49, 0xf0, 0x9f, 0xc5, 0x0c, 0x7f, 0x6e, - 0x60, 0xf4, 0x32, 0xb3, 0x78, 0x9a, 0xe5, 0xa8, 0x19, 0xdf, 0x19, 0xfe, 0x54, 0x46, 0xf2, 0x93, 0x2c, 0x27, 0xf0, - 0xbe, 0x0e, 0x01, 0x8e, 0x4c, 0xed, 0xe7, 0x2c, 0x67, 0xbc, 0x82, 0x96, 0x8d, 0xa2, 0x43, 0x14, 0xf5, 0xba, 0x7e, - 0xee, 0xc3, 0xe2, 0x9c, 0x50, 0x82, 0x91, 0x4d, 0x2f, 0xa1, 0x10, 0xa2, 0xf7, 0xcd, 0xb1, 0x18, 0x99, 0xbf, 0x28, - 0xe1, 0x04, 0x0b, 0x39, 0xd0, 0xbd, 0x2a, 0x20, 0x1d, 0x9f, 0x08, 0x0d, 0x13, 0x73, 0xb6, 0x91, 0xa9, 0xce, 0x26, - 0x16, 0xd2, 0x59, 0x71, 0xcd, 0xb1, 0x94, 0x56, 0x73, 0xe5, 0x75, 0x19, 0x75, 0x27, 0xe5, 0x97, 0xd0, 0xf4, 0x7a, - 0xcb, 0x59, 0x8c, 0x2a, 0xfc, 0xa7, 0xc3, 0x84, 0x6f, 0xd0, 0x2e, 0x2c, 0x67, 0x1d, 0x22, 0x54, 0xc1, 0x03, 0x5d, - 0x93, 0xbe, 0x8e, 0x56, 0xc3, 0x08, 0xcd, 0xdd, 0x0a, 0x0a, 0x84, 0xb4, 0x3f, 0xb0, 0xa8, 0x6d, 0xac, 0x9a, 0xb3, - 0x77, 0x47, 0x3b, 0x58, 0x35, 0x98, 0x9f, 0x1c, 0x05, 0xac, 0xba, 0x91, 0x70, 0xb1, 0xfc, 0x95, 0xc3, 0x43, 0x56, - 0x70, 0xf3, 0x01, 0xdc, 0x7e, 0x00, 0xe3, 0x98, 0xf1, 0x91, 0x3d, 0x69, 0x01, 0xc3, 0x99, 0xeb, 0x01, 0xef, 0x8d, - 0x53, 0x6f, 0xa4, 0xd1, 0x81, 0xa3, 0xab, 0xe5, 0x25, 0x7e, 0x28, 0x22, 0xc3, 0xaf, 0x49, 0x54, 0xd7, 0x34, 0x83, - 0x3c, 0x95, 0xd2, 0xe4, 0xd8, 0x1d, 0x50, 0x00, 0x7b, 0x1f, 0xe8, 0x98, 0xb6, 0x31, 0x93, 0xeb, 0x29, 0xba, 0x24, - 0xcd, 0xeb, 0x79, 0x68, 0x3f, 0x62, 0x9d, 0x11, 0x50, 0x8e, 0xed, 0x01, 0xf3, 0x5d, 0x03, 0x54, 0x2d, 0xcc, 0xf9, - 0x6f, 0x6a, 0x6b, 0x73, 0xe8, 0x58, 0x3d, 0x20, 0x2c, 0xf9, 0xf5, 0x51, 0x0b, 0xf2, 0xfb, 0x58, 0xe1, 0xb0, 0x45, - 0xfb, 0x62, 0x47, 0xaa, 0x0e, 0x6a, 0x85, 0xc1, 0x45, 0xa5, 0xca, 0xd4, 0x11, 0xc3, 0x0b, 0xb2, 0x49, 0x28, 0x14, - 0x1a, 0xc7, 0x13, 0x1b, 0xd0, 0xec, 0x8f, 0x58, 0x4a, 0xbb, 0x4b, 0x7e, 0xcd, 0x04, 0x91, 0xe6, 0xa5, 0xbf, 0xdb, - 0xe1, 0xa2, 0x0e, 0x17, 0xaf, 0x79, 0xa3, 0xe7, 0xb4, 0x09, 0xcd, 0x16, 0x63, 0xbc, 0x52, 0x6d, 0x82, 0xec, 0x4e, - 0xf3, 0xe8, 0x68, 0xc7, 0x16, 0x85, 0x24, 0x64, 0x7f, 0x79, 0x6d, 0x26, 0x47, 0x15, 0xfd, 0xbb, 0xc8, 0x59, 0x96, - 0x12, 0xe2, 0x1d, 0xf8, 0x45, 0x4f, 0xb9, 0x92, 0x46, 0xa7, 0xba, 0x23, 0xba, 0xa0, 0xa8, 0x7f, 0x76, 0x34, 0x0c, - 0xb3, 0x3c, 0x19, 0x54, 0xc1, 0x01, 0x8c, 0xd9, 0xe8, 0xa3, 0xeb, 0x85, 0x4b, 0x31, 0x98, 0xf2, 0xb0, 0x6a, 0xb3, - 0xb6, 0x61, 0xea, 0xc6, 0xb8, 0x30, 0x5c, 0x33, 0xb6, 0x31, 0x01, 0x18, 0xdb, 0x34, 0xdb, 0x4c, 0x9b, 0xfe, 0xfe, - 0xa9, 0xb0, 0x7a, 0x48, 0x24, 0x22, 0x90, 0x0f, 0xa2, 0x0f, 0x06, 0xa4, 0x7f, 0x5d, 0xa4, 0x60, 0x74, 0xa9, 0x15, - 0x3f, 0x89, 0x15, 0x1d, 0xf0, 0x9b, 0x8d, 0x77, 0x68, 0x18, 0x73, 0xde, 0x29, 0xc6, 0x5c, 0x9e, 0x82, 0x1d, 0x76, - 0x0e, 0xc2, 0x93, 0x2a, 0x46, 0xdb, 0x93, 0x58, 0x41, 0xd3, 0xf3, 0x05, 0xac, 0x6f, 0x12, 0x56, 0x63, 0x98, 0x56, - 0x33, 0x37, 0xc5, 0x5d, 0x2e, 0x3c, 0x66, 0x4d, 0xd6, 0x82, 0xf8, 0x20, 0x10, 0x59, 0x26, 0x41, 0x04, 0x3d, 0x16, - 0xde, 0x93, 0x99, 0x57, 0xc8, 0xd2, 0x0d, 0xba, 0x8c, 0x8c, 0xfb, 0xc0, 0x86, 0xfa, 0x41, 0xfd, 0xa0, 0x85, 0x74, - 0xa1, 0xf9, 0x6b, 0x54, 0xd5, 0x32, 0xcf, 0x71, 0xa3, 0x1c, 0x5a, 0x72, 0x6e, 0x8e, 0x40, 0x0b, 0x81, 0x50, 0x7b, - 0x35, 0x37, 0xc0, 0x58, 0x7e, 0x08, 0x87, 0x9c, 0x03, 0x40, 0x67, 0x31, 0xe1, 0xf1, 0x6d, 0x1b, 0x20, 0xb5, 0x71, - 0xf4, 0xa4, 0x6e, 0xed, 0xa6, 0xc9, 0x10, 0x41, 0x24, 0xbe, 0x1d, 0x03, 0xeb, 0xe7, 0xf9, 0x77, 0x11, 0x9d, 0x60, - 0xe8, 0xc7, 0xe2, 0x2e, 0x7f, 0x34, 0xf4, 0x54, 0x7f, 0x3e, 0x55, 0x4f, 0x62, 0xc4, 0x52, 0xc4, 0x8f, 0x79, 0x6d, - 0x2e, 0xa0, 0x14, 0xa5, 0xd9, 0x04, 0x46, 0x39, 0xd2, 0xe3, 0x4a, 0x92, 0x47, 0xa2, 0x81, 0x18, 0x44, 0xa3, 0xe2, - 0x9b, 0x2b, 0x5d, 0x3b, 0x87, 0xab, 0x78, 0xe5, 0xb1, 0xae, 0x97, 0xc7, 0xeb, 0x99, 0x9d, 0x7a, 0x2f, 0x07, 0xeb, - 0xd4, 0x3b, 0x2f, 0x44, 0x4b, 0x57, 0xc4, 0xe8, 0xf4, 0x13, 0x51, 0xab, 0x76, 0xbd, 0x6b, 0x04, 0x22, 0x09, 0x97, - 0xff, 0x19, 0x02, 0xb5, 0xf0, 0xe1, 0xd2, 0xb3, 0xc3, 0x62, 0x6e, 0x74, 0xf9, 0xa6, 0x19, 0x94, 0x02, 0x1e, 0xd4, - 0xea, 0xb8, 0x86, 0xe8, 0xdc, 0x56, 0xf2, 0x82, 0xd4, 0x7f, 0x12, 0xab, 0xa0, 0xe0, 0xbd, 0x95, 0xee, 0x79, 0x91, - 0x6a, 0xb8, 0xa9, 0x72, 0x07, 0xe8, 0xb5, 0xa8, 0x62, 0x4d, 0x83, 0x17, 0x76, 0xa6, 0x24, 0xf2, 0x81, 0x97, 0x10, - 0xa1, 0xfb, 0x4e, 0xcc, 0x1a, 0xa6, 0xad, 0x66, 0x67, 0xec, 0x46, 0x0f, 0xa1, 0x47, 0x31, 0x59, 0x5e, 0x2d, 0x21, - 0xe0, 0xb3, 0xdf, 0x46, 0xb3, 0xf7, 0x36, 0x25, 0x19, 0x17, 0xfe, 0x6d, 0x02, 0x4b, 0x6e, 0x71, 0x87, 0x41, 0x0c, - 0xd6, 0x1f, 0x09, 0x1e, 0x98, 0x83, 0xed, 0xa1, 0xb0, 0xac, 0x9e, 0xcd, 0x33, 0x0f, 0xb4, 0x8f, 0x51, 0x94, 0xd1, - 0x04, 0xf0, 0xc9, 0x7a, 0x47, 0x02, 0x80, 0x6c, 0x5d, 0xa1, 0x46, 0x9f, 0x74, 0x65, 0xdd, 0x55, 0x77, 0xc3, 0x52, - 0x19, 0xba, 0x1b, 0x59, 0x4b, 0x01, 0x1d, 0x8a, 0x53, 0x96, 0x59, 0xf4, 0xc6, 0x07, 0x55, 0x14, 0xf9, 0x3e, 0xb1, - 0x2d, 0x61, 0xea, 0xdb, 0x9b, 0x44, 0x17, 0x85, 0x44, 0x01, 0x61, 0x92, 0x9c, 0x78, 0x5f, 0x20, 0x71, 0xb6, 0x5e, - 0x22, 0x6a, 0xc2, 0xe5, 0x67, 0xf7, 0xca, 0x04, 0x1e, 0xb4, 0xf5, 0xac, 0xec, 0x02, 0x97, 0xd7, 0x17, 0x43, 0x10, - 0x05, 0x72, 0x0a, 0x62, 0x72, 0x09, 0x8a, 0x0f, 0xe6, 0x7a, 0x02, 0x4e, 0x91, 0xef, 0xa5, 0xe6, 0x7d, 0xe3, 0x00, - 0x1c, 0x85, 0x10, 0x8b, 0x91, 0x08, 0x08, 0xc9, 0x26, 0xc0, 0xa5, 0x15, 0x68, 0xf7, 0x17, 0x7b, 0xed, 0x0b, 0xf7, - 0x8f, 0xd8, 0xad, 0x30, 0x17, 0xb2, 0x30, 0x5a, 0x11, 0xdd, 0x4b, 0x02, 0x67, 0x87, 0x3a, 0xbf, 0x65, 0x96, 0xc6, - 0xb7, 0xee, 0xe7, 0xa0, 0x94, 0x80, 0xb0, 0xff, 0xc9, 0x38, 0x10, 0x00, 0x73, 0x69, 0x25, 0x6d, 0x89, 0x78, 0xf6, - 0x42, 0x9a, 0x0d, 0xfd, 0xc6, 0x86, 0x37, 0x0f, 0x15, 0x60, 0x49, 0xad, 0x5e, 0x30, 0x97, 0x55, 0xce, 0x68, 0x0d, - 0x4a, 0x78, 0xdb, 0x42, 0x57, 0xcf, 0x56, 0xbf, 0x17, 0xd5, 0x8f, 0xfb, 0xe1, 0x5b, 0xd5, 0x6d, 0x4f, 0xaa, 0x33, - 0xc9, 0x60, 0xf2, 0x54, 0xad, 0xa7, 0x59, 0x70, 0xf7, 0x7e, 0xa7, 0x00, 0x64, 0xa1, 0xf1, 0x76, 0xd6, 0xd9, 0xdc, - 0x1e, 0xfa, 0xc0, 0xfe, 0x80, 0x0b, 0x8a, 0x3f, 0x24, 0x1d, 0xdf, 0x27, 0x11, 0x11, 0x59, 0xdb, 0xb1, 0xcb, 0x5b, - 0xdb, 0x36, 0xad, 0x99, 0x97, 0x3e, 0x56, 0xdf, 0xfc, 0xf6, 0x96, 0xbc, 0x17, 0x25, 0x27, 0xe9, 0x0b, 0x56, 0xb7, - 0x68, 0x7b, 0xc8, 0xd3, 0x81, 0x09, 0x74, 0xeb, 0xbc, 0xf1, 0x4e, 0x31, 0xd2, 0xd4, 0x11, 0x47, 0x99, 0x8d, 0x0c, - 0x9e, 0xe9, 0x59, 0x1f, 0x1d, 0x28, 0x9e, 0x61, 0xba, 0x26, 0x62, 0x9f, 0xb8, 0xec, 0x0a, 0x3c, 0x21, 0x3a, 0x3e, - 0x82, 0x69, 0x43, 0xde, 0xaf, 0xc2, 0xfb, 0xe2, 0x58, 0xfc, 0x60, 0x31, 0x89, 0x7c, 0x90, 0x03, 0xbc, 0x0f, 0x6c, - 0x59, 0x61, 0x64, 0xe0, 0x73, 0xb6, 0x3b, 0x8e, 0x17, 0x80, 0x11, 0x0f, 0xb9, 0x47, 0x77, 0x7c, 0x0f, 0x02, 0xc7, - 0x33, 0xd5, 0x62, 0xe7, 0xb0, 0x04, 0x01, 0x90, 0x19, 0x2c, 0x8e, 0x8b, 0xd1, 0x28, 0x4a, 0x09, 0x78, 0x26, 0xa7, - 0x6e, 0xd5, 0x10, 0xcb, 0xec, 0x9b, 0x80, 0x72, 0xe9, 0x5a, 0x48, 0xc1, 0xad, 0xfa, 0xc6, 0x98, 0x90, 0x6e, 0x1b, - 0x0d, 0xb6, 0xf0, 0xaf, 0x05, 0xb1, 0xa4, 0x41, 0x5d, 0x93, 0xf7, 0x61, 0xb6, 0x50, 0xda, 0x9b, 0xae, 0xe3, 0xd4, - 0x25, 0x92, 0xb8, 0xb6, 0xc4, 0x48, 0x20, 0x98, 0x59, 0x87, 0x22, 0x8b, 0x21, 0xf6, 0xb1, 0xda, 0x02, 0x80, 0x27, - 0x10, 0x1d, 0x39, 0x66, 0xef, 0x11, 0xc5, 0xfd, 0x0b, 0xf8, 0x65, 0xf9, 0x03, 0x19, 0x7f, 0x7b, 0x3e, 0xce, 0x8e, - 0x28, 0xfa, 0x77, 0x12, 0x4f, 0x55, 0x2c, 0x81, 0x34, 0xb6, 0x03, 0x2c, 0x5d, 0x81, 0x5c, 0x06, 0x8e, 0x11, 0xeb, - 0x67, 0xd6, 0x27, 0xe0, 0xc7, 0x01, 0x16, 0x1d, 0xbf, 0x0e, 0x95, 0x5d, 0x4a, 0xe5, 0x6f, 0x95, 0x5b, 0x99, 0x31, - 0x38, 0x17, 0xba, 0x3b, 0x49, 0x53, 0xaf, 0xee, 0x6d, 0x43, 0x7d, 0x93, 0xa4, 0x7d, 0x6b, 0x09, 0x03, 0xee, 0xeb, - 0x24, 0x8d, 0xa1, 0xd0, 0x27, 0xcb, 0xe3, 0x26, 0xa9, 0x89, 0xa1, 0x37, 0x45, 0xbc, 0x9b, 0x6a, 0x8f, 0xd4, 0xee, - 0x4b, 0xd3, 0x2e, 0x02, 0xb3, 0xa4, 0xb1, 0x68, 0x32, 0xfc, 0x08, 0x58, 0x1c, 0x8a, 0x14, 0x23, 0x72, 0x19, 0x80, - 0xb0, 0x61, 0x07, 0x77, 0x52, 0x3d, 0xa6, 0xd9, 0x13, 0xf0, 0xd2, 0xa6, 0x78, 0xef, 0xaa, 0xc5, 0x84, 0x32, 0x61, - 0xf2, 0xe0, 0xad, 0xdd, 0x5c, 0x30, 0x53, 0x2a, 0x49, 0x20, 0x9b, 0xb2, 0x90, 0x2b, 0xf8, 0xd9, 0x8b, 0xbf, 0x7f, - 0x50, 0x54, 0x3a, 0x02, 0xee, 0x78, 0xd9, 0xfd, 0xb9, 0x11, 0xff, 0x64, 0x88, 0x47, 0x46, 0x66, 0xf8, 0x2f, 0x49, - 0xd6, 0xf8, 0x04, 0x32, 0x09, 0x2f, 0x69, 0x0f, 0xd2, 0x25, 0x3c, 0x52, 0xeb, 0x60, 0x96, 0x47, 0x1b, 0x9a, 0xc8, - 0xdf, 0x84, 0xc2, 0xaa, 0xab, 0x0c, 0x2c, 0xce, 0x32, 0xe4, 0xe7, 0x52, 0x73, 0x0c, 0xc0, 0x6f, 0x02, 0xf0, 0x86, - 0x86, 0x49, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x34, 0xe9, 0x3a, 0x55, 0x5d, 0x90, 0x1d, 0x65, 0xd0, 0x2e, 0x0c, 0x89, - 0x80, 0x9e, 0xef, 0x6d, 0xf1, 0xa0, 0x79, 0x7a, 0x93, 0x1f, 0x10, 0xf8, 0xd8, 0x4f, 0xa3, 0x55, 0x75, 0xa0, 0xd6, - 0xe8, 0x19, 0x41, 0x4f, 0x33, 0xe0, 0x36, 0x2e, 0x87, 0xb0, 0x8d, 0x63, 0x58, 0x98, 0xf1, 0x62, 0x18, 0x2f, 0x86, - 0x5c, 0x79, 0x7b, 0x0a, 0xb1, 0x80, 0xdd, 0x80, 0xd4, 0x2c, 0x27, 0x64, 0x27, 0x52, 0xf6, 0x20, 0x50, 0x10, 0xa1, - 0xfc, 0xe6, 0x65, 0xfc, 0x1b, 0x21, 0x28, 0x08, 0xb0, 0x82, 0x68, 0xd5, 0x81, 0x64, 0x6b, 0x13, 0x39, 0xad, 0x25, - 0x55, 0x71, 0x7e, 0x29, 0xc3, 0xe4, 0x77, 0xfd, 0xf9, 0x75, 0x1b, 0x6d, 0x18, 0xc3, 0x53, 0x73, 0xcd, 0x46, 0x93, - 0xe1, 0x53, 0x66, 0x7f, 0x21, 0xc4, 0xc1, 0x21, 0xbf, 0x15, 0xc3, 0x7a, 0x28, 0x6d, 0x18, 0x3c, 0xea, 0x5c, 0x5a, - 0x45, 0xa5, 0xbd, 0x61, 0x27, 0x1a, 0xc6, 0xde, 0xf2, 0xe7, 0x3b, 0x81, 0x8f, 0x81, 0x2b, 0x0c, 0x10, 0xf4, 0x7f, - 0xfb, 0x5b, 0xef, 0x00, 0xff, 0x31, 0xa2, 0xc8, 0x81, 0xdb, 0x0a, 0x83, 0x8c, 0x6d, 0xb3, 0xed, 0x36, 0xfa, 0x98, - 0x6b, 0x3d, 0xf1, 0x42, 0x27, 0x0b, 0xe3, 0xdd, 0x1f, 0x41, 0x19, 0xe6, 0x45, 0x12, 0xe7, 0x45, 0x54, 0xe9, 0xc3, - 0xa2, 0xaa, 0x22, 0xdd, 0x3f, 0x00, 0x30, 0x0a, 0xe7, 0xd3, 0xef, 0xdf, 0x10, 0xaf, 0xec, 0xc6, 0xf7, 0x6a, 0x24, - 0x9f, 0x13, 0xe2, 0xf5, 0xdc, 0x77, 0xb8, 0x03, 0xb3, 0x5f, 0x21, 0x98, 0xb9, 0x9c, 0x4c, 0x06, 0xd7, 0xf4, 0x1b, - 0x05, 0x72, 0xfc, 0xd8, 0x0d, 0x1d, 0xd8, 0x4c, 0xa7, 0xf6, 0x96, 0xef, 0x07, 0xf8, 0xcc, 0x19, 0xcd, 0xea, 0xcd, - 0x8f, 0xbe, 0x6c, 0x50, 0x16, 0xe1, 0x8f, 0x63, 0x72, 0x20, 0x75, 0x95, 0x2e, 0x21, 0xe0, 0x59, 0x9f, 0x34, 0xd0, - 0x10, 0x4e, 0x6d, 0x44, 0x7e, 0x7f, 0x1b, 0x22, 0x7c, 0x67, 0x4f, 0x39, 0xea, 0x44, 0x8f, 0xa8, 0x27, 0x64, 0xb6, - 0xdd, 0xd6, 0x07, 0x64, 0x59, 0xb0, 0xf9, 0x06, 0xce, 0x53, 0xd3, 0x92, 0xc3, 0x4f, 0xfd, 0xb9, 0x09, 0x55, 0xa4, - 0xec, 0x77, 0xf0, 0x26, 0xc9, 0xc8, 0xa8, 0x50, 0xfe, 0x37, 0x59, 0x6f, 0x51, 0x32, 0xe2, 0x4b, 0x62, 0x2a, 0x98, - 0x3e, 0xf2, 0x98, 0xcd, 0x48, 0x4a, 0x5d, 0x6b, 0x25, 0x0f, 0xbe, 0x87, 0x42, 0xe3, 0xf4, 0x06, 0x21, 0xd8, 0x60, - 0x5a, 0x41, 0x3c, 0x5a, 0x31, 0xca, 0x1a, 0x4f, 0x26, 0xef, 0xb7, 0x52, 0x13, 0x7a, 0x7c, 0x5b, 0x25, 0x8b, 0x27, - 0x73, 0x47, 0xca, 0x47, 0x12, 0x47, 0xda, 0x28, 0x68, 0xf1, 0xa6, 0xe3, 0xfd, 0xac, 0x33, 0x22, 0x05, 0xbd, 0x9c, - 0x1b, 0x91, 0xf2, 0xcb, 0x1b, 0x66, 0xdf, 0x1e, 0x5c, 0x1e, 0x3c, 0x3e, 0x16, 0x45, 0x4e, 0x81, 0xbb, 0x75, 0x0d, - 0x2f, 0xfb, 0xa2, 0x2b, 0x61, 0x28, 0xa7, 0x94, 0x07, 0x85, 0xc2, 0xc8, 0x16, 0x48, 0x43, 0x7e, 0x12, 0xf9, 0xfb, - 0x61, 0x3e, 0x63, 0xf8, 0xba, 0xf4, 0x49, 0xca, 0x4a, 0x62, 0x7f, 0x22, 0xd2, 0x64, 0xe2, 0x8d, 0x79, 0xbf, 0xff, - 0x63, 0xf6, 0x62, 0x3f, 0x54, 0x19, 0x33, 0x77, 0x93, 0xc8, 0x42, 0x1d, 0x94, 0xf2, 0x15, 0x4e, 0x3b, 0xfc, 0xff, - 0x46, 0xa2, 0xed, 0x42, 0x0f, 0x6f, 0x0f, 0x3c, 0x14, 0xad, 0x49, 0x62, 0xdb, 0x7b, 0xba, 0x04, 0x2b, 0x54, 0xdb, - 0xf8, 0x72, 0x1a, 0x79, 0x56, 0xf4, 0x6a, 0x77, 0xc5, 0x70, 0xef, 0xa0, 0xbe, 0xc9, 0xaa, 0xfd, 0xd4, 0x64, 0x1a, - 0x58, 0x81, 0xc0, 0x77, 0x41, 0x6e, 0x1d, 0x27, 0xae, 0xd7, 0xda, 0xdf, 0xad, 0x36, 0x61, 0xb5, 0xa1, 0x6e, 0x41, - 0x64, 0x5e, 0x30, 0xb0, 0x2c, 0x9a, 0x27, 0x11, 0x14, 0xc3, 0x32, 0x18, 0x72, 0xa6, 0x64, 0x81, 0xf3, 0x56, 0x40, - 0x1e, 0xdd, 0x2b, 0x38, 0x21, 0x61, 0xb4, 0x8e, 0x35, 0x1b, 0xf9, 0x22, 0x14, 0xf9, 0xaa, 0x6d, 0x36, 0x2e, 0xc5, - 0x3d, 0x4d, 0x6a, 0x15, 0xd0, 0x5c, 0x56, 0x30, 0x85, 0xf6, 0x8d, 0x42, 0xe2, 0x4c, 0x23, 0x79, 0xfe, 0x92, 0xee, - 0xc7, 0xb1, 0x41, 0x17, 0xf9, 0x2b, 0x0d, 0xdb, 0xce, 0xb5, 0xbe, 0xfb, 0xa0, 0x00, 0x5f, 0xa8, 0x23, 0xf3, 0x29, - 0xed, 0x2f, 0xab, 0xd6, 0x0d, 0x5f, 0xa8, 0xe5, 0x17, 0x13, 0xfd, 0xa5, 0x92, 0x66, 0x7f, 0x5f, 0x5a, 0xa0, 0x94, - 0xa7, 0x59, 0xae, 0x9a, 0x5a, 0x3e, 0xf2, 0x3f, 0xcd, 0x93, 0x09, 0x99, 0xd0, 0x39, 0x2c, 0x1f, 0x15, 0x69, 0x76, - 0x9f, 0x3f, 0x70, 0xff, 0x86, 0x57, 0xca, 0xde, 0x13, 0xe7, 0x31, 0xbd, 0xa7, 0xc4, 0xe6, 0xcc, 0x03, 0x0c, 0xb2, - 0x22, 0x4e, 0x6d, 0xab, 0xd9, 0x3b, 0x92, 0x39, 0x56, 0xdd, 0x65, 0x72, 0xc2, 0x64, 0xe8, 0xae, 0xe2, 0x83, 0x46, - 0xd8, 0xcd, 0xf7, 0x89, 0x0f, 0x2c, 0x82, 0x66, 0x94, 0xee, 0x6a, 0xb7, 0x7f, 0x2c, 0x57, 0xb1, 0x48, 0xa4, 0xc8, - 0x56, 0xd4, 0x6a, 0x9f, 0xe8, 0x21, 0x7f, 0x2b, 0xf9, 0xf9, 0x3f, 0x95, 0x88, 0x1b, 0x87, 0xd3, 0x7f, 0x4e, 0x54, - 0x10, 0x06, 0xb5, 0x43, 0x46, 0xb2, 0x84, 0x0a, 0x14, 0xc6, 0xce, 0x04, 0xdb, 0x5f, 0xb0, 0x1e, 0x60, 0x91, 0x48, - 0x22, 0x69, 0x28, 0x8f, 0x2c, 0x11, 0xa8, 0x12, 0xdf, 0x53, 0x97, 0xcd, 0x0f, 0x51, 0xb4, 0x71, 0x7d, 0x1e, 0x10, - 0x2a, 0xd3, 0x96, 0x2b, 0xe7, 0xb4, 0x72, 0xe5, 0x5e, 0x90, 0x18, 0x49, 0x24, 0x38, 0x82, 0xda, 0xa8, 0x21, 0x7c, - 0x48, 0x4a, 0x2f, 0x9d, 0x54, 0xde, 0xb5, 0xb8, 0x26, 0x8f, 0x02, 0x88, 0x4d, 0xc6, 0xf8, 0xf5, 0xe5, 0xaa, 0xdd, - 0x78, 0xba, 0x6c, 0xc4, 0xe2, 0x77, 0x0a, 0x38, 0x41, 0xba, 0xaf, 0x28, 0xa0, 0x37, 0x60, 0x55, 0x07, 0x7c, 0xfb, - 0x04, 0x8e, 0x4a, 0x07, 0x8a, 0xe9, 0xc8, 0xa1, 0x22, 0xbf, 0x03, 0xae, 0xdd, 0xad, 0x88, 0xf0, 0xed, 0xf2, 0x35, - 0x2b, 0x6a, 0x09, 0x41, 0xad, 0x35, 0x89, 0x66, 0xb6, 0x08, 0xc5, 0xc6, 0xbd, 0x80, 0xcb, 0x73, 0x28, 0xfa, 0xf0, - 0x12, 0x17, 0x71, 0xe0, 0xfd, 0xc5, 0x4b, 0x9b, 0x27, 0xd3, 0x29, 0xfd, 0xd6, 0x77, 0x74, 0xf0, 0xe8, 0xe5, 0xc3, - 0xb2, 0x48, 0x27, 0x29, 0x78, 0xc4, 0x20, 0x08, 0x93, 0xf4, 0x89, 0x47, 0x4c, 0x76, 0x9a, 0x77, 0x1e, 0xdc, 0xc5, - 0x05, 0xb2, 0x1f, 0x46, 0xf0, 0x10, 0xd9, 0x5e, 0x9a, 0x38, 0xa0, 0x3d, 0xb7, 0x75, 0x76, 0x32, 0x6e, 0x9e, 0x78, - 0x2f, 0x5a, 0xf0, 0x2a, 0xe6, 0x7d, 0xe2, 0x11, 0xc6, 0x0c, 0x7e, 0xee, 0x12, 0x92, 0x1c, 0x6b, 0xa9, 0xe0, 0x28, - 0xe8, 0x81, 0x7c, 0x31, 0x92, 0x51, 0x9a, 0xd1, 0xb7, 0x3f, 0x9b, 0xbb, 0x1d, 0xed, 0xaa, 0xdb, 0x6c, 0x83, 0x8b, - 0xae, 0x8c, 0x5f, 0xcf, 0x7d, 0xd9, 0xb1, 0xa3, 0x2b, 0x37, 0x0e, 0xd8, 0x96, 0xd1, 0x9b, 0x2e, 0xb1, 0x58, 0x69, - 0x0d, 0xa9, 0x20, 0xf6, 0x65, 0x4e, 0xe0, 0xd2, 0x4a, 0x73, 0x52, 0xb0, 0x06, 0xef, 0x32, 0x3d, 0x59, 0xad, 0xbe, - 0x7b, 0x29, 0xeb, 0xe1, 0x19, 0x7f, 0xdb, 0x0b, 0xd5, 0xc8, 0xc5, 0xef, 0xa7, 0x1c, 0x64, 0x1d, 0x5d, 0x64, 0xc8, - 0xa4, 0x2f, 0xd0, 0xde, 0x37, 0x59, 0x04, 0x36, 0xe1, 0x80, 0xdc, 0xbb, 0x95, 0xda, 0xc0, 0x65, 0xbc, 0xb1, 0x89, - 0xe8, 0x69, 0x2c, 0xc2, 0x69, 0x2f, 0xec, 0xc1, 0xdf, 0xd1, 0xcd, 0x34, 0xe7, 0xa9, 0xbc, 0x74, 0xdf, 0xde, 0xbb, - 0x74, 0xbf, 0x48, 0xbe, 0xc7, 0xee, 0xf3, 0xc5, 0xfb, 0x45, 0x1d, 0xde, 0x1c, 0xd8, 0x3f, 0x33, 0xbc, 0xb4, 0x47, - 0xcd, 0xcd, 0xdb, 0x9a, 0x7d, 0x2d, 0xf6, 0x5b, 0x87, 0x37, 0x5d, 0x44, 0x99, 0x9d, 0x33, 0x1a, 0x5b, 0xf3, 0x6b, - 0xbc, 0x7e, 0xfc, 0xf1, 0x67, 0xfe, 0x59, 0xce, 0x0b, 0x86, 0x61, 0x8d, 0x9f, 0x77, 0x59, 0x0f, 0xab, 0xb6, 0x7e, - 0x2c, 0xf0, 0xd1, 0xdc, 0xbc, 0xa3, 0xda, 0xb8, 0xb7, 0x48, 0x1f, 0xad, 0xdc, 0x35, 0x9f, 0x3c, 0x32, 0xb8, 0xf0, - 0x23, 0xf3, 0xf9, 0xa8, 0x1f, 0x41, 0xc8, 0xe5, 0x4f, 0xde, 0x45, 0x62, 0xfa, 0xc7, 0xd6, 0x2b, 0xb1, 0x88, 0x7d, - 0xaa, 0x81, 0x70, 0x37, 0x5e, 0xa4, 0x45, 0xd9, 0x77, 0xf4, 0x0b, 0x7b, 0x4c, 0x56, 0xef, 0x40, 0x04, 0x0a, 0x5a, - 0x9f, 0x9d, 0x24, 0x12, 0x3f, 0x44, 0xff, 0xe4, 0x8f, 0xa8, 0xd3, 0x4e, 0xb4, 0xff, 0xd8, 0x4e, 0xf8, 0xff, 0xa7, - 0x6b, 0x5b, 0xf5, 0x96, 0x0d, 0xf0, 0xd6, 0xff, 0x05, 0xa2, 0x0d, 0x6d, 0xaf, 0x04, 0xe9, 0xa1, 0x8b, 0x88, 0xfc, - 0xd9, 0xad, 0x66, 0x59, 0x61, 0xf5, 0x32, 0x57, 0x2c, 0xe3, 0x09, 0x9d, 0x93, 0x0b, 0x8d, 0x93, 0x34, 0x4d, 0x19, - 0xbc, 0x67, 0xd2, 0xec, 0x75, 0x2d, 0x43, 0xef, 0x36, 0x67, 0x8f, 0xd0, 0x49, 0x3a, 0xce, 0x92, 0x8a, 0x45, 0xb4, - 0x6e, 0x57, 0x6d, 0x9e, 0xad, 0x47, 0x70, 0x06, 0x07, 0x67, 0x59, 0x40, 0xef, 0xc1, 0x52, 0xdb, 0x9d, 0x1b, 0x3b, - 0x4c, 0xf7, 0x2f, 0x2d, 0x87, 0x23, 0x82, 0xc6, 0xde, 0x2c, 0xb7, 0xed, 0x8f, 0x4a, 0x0a, 0x15, 0xf1, 0xe6, 0xc0, - 0x40, 0x2f, 0x7e, 0x3d, 0x91, 0x65, 0xd0, 0x75, 0x2f, 0x5f, 0x0b, 0x61, 0x59, 0xab, 0xb9, 0x76, 0x18, 0x9f, 0x0b, - 0xab, 0x20, 0xb4, 0x0b, 0x21, 0xce, 0x5e, 0xe8, 0x3a, 0x01, 0x4d, 0x8c, 0x78, 0x8b, 0x0b, 0x09, 0x36, 0x39, 0x28, - 0x54, 0x50, 0x3a, 0x3e, 0xd2, 0xee, 0x41, 0x10, 0x7a, 0x2e, 0xc6, 0x0a, 0xc8, 0xb1, 0xdc, 0x4e, 0x65, 0x22, 0x9a, - 0x24, 0x04, 0xae, 0xf2, 0x43, 0xf8, 0x8c, 0x64, 0xbc, 0x9c, 0xda, 0x45, 0x58, 0x77, 0x9b, 0xaa, 0xcd, 0x41, 0xef, - 0xfe, 0x27, 0xac, 0x42, 0x17, 0x45, 0xd1, 0x7a, 0xd6, 0x59, 0x9e, 0x47, 0xcc, 0x03, 0xb3, 0x49, 0x81, 0x46, 0x11, - 0x8a, 0xd0, 0xbf, 0x27, 0xf6, 0xd0, 0x88, 0x2a, 0xa3, 0xba, 0x60, 0x31, 0xac, 0x30, 0x57, 0x4e, 0x4b, 0x69, 0xa7, - 0x2c, 0x77, 0xa3, 0x1d, 0xe0, 0xc7, 0x57, 0xff, 0x6c, 0x43, 0xff, 0x72, 0xe9, 0x63, 0xdb, 0x8b, 0x2d, 0x36, 0xbf, - 0x7e, 0x3e, 0x4b, 0xef, 0x0e, 0x4f, 0xa3, 0xd8, 0x82, 0x9a, 0x40, 0x25, 0x13, 0x85, 0x52, 0xf3, 0xba, 0xe0, 0x10, - 0xb4, 0x50, 0xfc, 0x68, 0x54, 0xd4, 0xfb, 0x79, 0x35, 0x01, 0x05, 0x09, 0x20, 0x1c, 0x4b, 0x1a, 0x69, 0x97, 0xd8, - 0x82, 0x48, 0xeb, 0xb3, 0xf2, 0x6e, 0x84, 0xd7, 0x36, 0x68, 0x8a, 0xe0, 0x90, 0x25, 0xd3, 0xc2, 0xb0, 0x22, 0x83, - 0x04, 0x18, 0xb7, 0x11, 0xd2, 0x8b, 0xe4, 0x1f, 0x50, 0x02, 0xf0, 0x2a, 0xa2, 0xbd, 0x51, 0x99, 0x88, 0xe4, 0xa5, - 0xac, 0x51, 0x0a, 0x4b, 0x00, 0x02, 0xff, 0x32, 0xbf, 0x22, 0x58, 0x22, 0xd5, 0x58, 0xa3, 0x35, 0x9d, 0x11, 0xa8, - 0xad, 0x7e, 0x07, 0x44, 0x98, 0xd7, 0xd8, 0xcd, 0x68, 0x7e, 0x43, 0xb3, 0x24, 0xc6, 0xb8, 0x6a, 0x6f, 0x3e, 0xe7, - 0x72, 0xbb, 0xe6, 0xb2, 0xdf, 0x5a, 0x0f, 0xec, 0x4d, 0xba, 0xcf, 0x3a, 0xf3, 0xc0, 0xc7, 0xa7, 0x15, 0xce, 0xeb, - 0x25, 0x99, 0x95, 0xc7, 0x47, 0x5f, 0xf7, 0xae, 0xb5, 0x50, 0x73, 0xf3, 0xbe, 0x3e, 0xdc, 0xbc, 0x77, 0x6d, 0x85, - 0x1f, 0xfc, 0x5f, 0xc6, 0xf1, 0xb4, 0x46, 0x56, 0xfe, 0x5a, 0x15, 0xd5, 0x36, 0x62, 0x98, 0x78, 0x3b, 0x65, 0x08, - 0xe4, 0xa9, 0xda, 0x83, 0xdd, 0x49, 0x54, 0xda, 0x6f, 0x2a, 0x52, 0xb7, 0x9d, 0x0b, 0x45, 0x67, 0xa2, 0x4d, 0x72, - 0xc2, 0x33, 0x9e, 0x6f, 0x8e, 0x30, 0x89, 0xa4, 0xe5, 0x3a, 0x53, 0x37, 0xdc, 0xfd, 0x5c, 0xae, 0x3f, 0x6e, 0x1a, - 0xd0, 0x21, 0x8b, 0x8f, 0xfb, 0x90, 0x51, 0x10, 0x34, 0xbc, 0x6c, 0x96, 0x09, 0x79, 0xac, 0x13, 0xeb, 0x6a, 0xf7, - 0x65, 0x8a, 0xba, 0x3f, 0xd7, 0x2f, 0xc4, 0xb1, 0xb7, 0xc3, 0x24, 0xb1, 0xb1, 0x64, 0x9a, 0xb5, 0x46, 0x1a, 0x79, - 0x70, 0x7a, 0x6a, 0x7b, 0xe6, 0x65, 0x67, 0xf5, 0xd6, 0xcc, 0x03, 0x1d, 0x70, 0x12, 0x69, 0x0b, 0xe6, 0x64, 0x5e, - 0xcc, 0xcf, 0x4f, 0x07, 0xe9, 0xc6, 0xfd, 0x5c, 0x8d, 0xed, 0x88, 0xc7, 0xa4, 0x27, 0x09, 0xfc, 0x44, 0x09, 0xbe, - 0x25, 0x91, 0x06, 0xe0, 0xe5, 0xeb, 0xcb, 0x11, 0x64, 0xb6, 0x0a, 0x48, 0x4c, 0xb6, 0xf5, 0xeb, 0x4f, 0x01, 0x83, - 0xce, 0x56, 0x20, 0x01, 0x43, 0xf1, 0x33, 0x68, 0xbd, 0xc6, 0x97, 0x1a, 0x24, 0x29, 0x31, 0x3e, 0x99, 0xe1, 0xe6, - 0x93, 0x28, 0xf0, 0xf0, 0x5b, 0x47, 0xb6, 0xd9, 0x0e, 0x65, 0x9c, 0x41, 0xf5, 0x98, 0xd6, 0xc3, 0x29, 0x33, 0xe3, - 0xf9, 0x4c, 0x7a, 0x1c, 0x7f, 0xab, 0x80, 0xbc, 0x0f, 0xcc, 0xdb, 0xa0, 0x6c, 0x82, 0x70, 0x02, 0x83, 0xcb, 0xb9, - 0x17, 0x9b, 0x40, 0x5c, 0xbf, 0x84, 0x35, 0xa6, 0x93, 0x3c, 0x9f, 0xab, 0xc3, 0x0f, 0xe3, 0xb7, 0x1e, 0xb9, 0x37, - 0xbd, 0x57, 0x8c, 0x4b, 0xd3, 0x7a, 0xc1, 0x30, 0xbb, 0x52, 0x6c, 0x80, 0x5a, 0x05, 0x33, 0x5b, 0x32, 0x6e, 0xa5, - 0x45, 0x16, 0x38, 0x6e, 0x7a, 0xef, 0xd4, 0xec, 0xae, 0xad, 0x07, 0xa4, 0x4f, 0x34, 0x44, 0x8c, 0x4f, 0x55, 0xe0, - 0x12, 0x75, 0xfc, 0x1e, 0x7f, 0x7a, 0xcf, 0x5f, 0xc3, 0x38, 0x15, 0x6f, 0xb6, 0xf1, 0x22, 0x63, 0x2b, 0xcb, 0xf3, - 0xf7, 0xf1, 0x9e, 0x43, 0x4b, 0x6b, 0x3f, 0x8c, 0x31, 0x58, 0xc9, 0x67, 0x0a, 0xf5, 0x84, 0x1d, 0xff, 0x22, 0x91, - 0xfe, 0xd9, 0x5a, 0xfa, 0x5b, 0xfc, 0x33, 0xc2, 0xff, 0x31, 0x0c, 0x95, 0xe6, 0xcb, 0x3f, 0xa2, 0xfe, 0x23, 0xbe, - 0x50, 0x56, 0x7a, 0x91, 0x73, 0x4f, 0xb5, 0xd9, 0x98, 0x8f, 0xf6, 0x26, 0x4e, 0x0a, 0x18, 0xc5, 0x99, 0x89, 0x82, - 0x38, 0xcf, 0xd5, 0xf9, 0x48, 0xf2, 0xb7, 0x9a, 0xb8, 0xf0, 0xcb, 0xf1, 0xd1, 0xf0, 0xf1, 0xdc, 0xa7, 0xe7, 0xfd, - 0x1e, 0x52, 0xb9, 0x2f, 0x12, 0xd5, 0xb6, 0xb2, 0x7d, 0xf2, 0xf7, 0x5d, 0xe7, 0x8e, 0x08, 0xac, 0x3f, 0x0f, 0x3e, - 0xb3, 0x8c, 0x3f, 0x19, 0x5e, 0xa6, 0x29, 0x5a, 0x33, 0x16, 0x5f, 0xe8, 0x33, 0xad, 0x8d, 0xdf, 0xb8, 0x55, 0x65, - 0x9b, 0x1a, 0x50, 0x9b, 0x6e, 0x82, 0xc4, 0xa4, 0x82, 0x06, 0x65, 0x9d, 0xfb, 0xf4, 0x07, 0x44, 0x1b, 0x12, 0x8a, - 0x7e, 0xfc, 0x43, 0x21, 0xe8, 0x2e, 0x41, 0x02, 0x90, 0xc4, 0x30, 0x33, 0x7e, 0x29, 0x48, 0x07, 0x34, 0x3c, 0xd4, - 0xdb, 0xcb, 0xc6, 0x56, 0x7d, 0x0e, 0x39, 0xfe, 0x6d, 0x74, 0x7f, 0x60, 0xf5, 0xd0, 0x80, 0x8a, 0xe3, 0x70, 0xf9, - 0x7f, 0xf4, 0x86, 0x30, 0x8a, 0x7a, 0x48, 0xa8, 0x2e, 0x16, 0x8d, 0x7f, 0x3a, 0x4a, 0xca, 0x19, 0x4a, 0x96, 0x72, - 0x1e, 0x15, 0x03, 0xcf, 0x82, 0xa0, 0xba, 0xa2, 0xc7, 0x26, 0xcf, 0xc5, 0xb3, 0x82, 0x43, 0xfe, 0x4f, 0xb0, 0xec, - 0x32, 0xc4, 0x64, 0x8c, 0xf8, 0xce, 0x4f, 0x10, 0x96, 0x64, 0x35, 0x6c, 0xcc, 0x1e, 0xc2, 0xed, 0x47, 0x6f, 0xa0, - 0x21, 0xdc, 0x7c, 0x7c, 0x80, 0x04, 0x7c, 0xe3, 0xcd, 0xea, 0x6a, 0x54, 0xbe, 0x30, 0xa7, 0x5d, 0x41, 0xdc, 0x18, - 0x02, 0x10, 0x89, 0xe0, 0x54, 0x52, 0x80, 0xfa, 0x26, 0x69, 0x8b, 0x80, 0xc5, 0x84, 0x6b, 0x43, 0x72, 0xd0, 0x8e, - 0x8b, 0xc9, 0x99, 0x72, 0x28, 0x73, 0xea, 0x28, 0x05, 0xe4, 0x24, 0x8f, 0x0e, 0x64, 0xd6, 0xed, 0xa5, 0x64, 0x7c, - 0x95, 0x8d, 0x76, 0xd9, 0x42, 0xf5, 0x49, 0x84, 0x99, 0x44, 0x8c, 0x54, 0xf0, 0x24, 0x67, 0x65, 0x82, 0x7e, 0xd1, - 0x2e, 0xa6, 0x36, 0xe2, 0xe1, 0xde, 0x66, 0x46, 0xec, 0x22, 0xd0, 0xe0, 0xca, 0x21, 0x79, 0xc5, 0xab, 0x90, 0x41, - 0x90, 0x09, 0x0b, 0x84, 0x05, 0x5c, 0x68, 0xf7, 0x7d, 0xe2, 0x78, 0xd8, 0xef, 0x47, 0xc1, 0x25, 0xe7, 0xf5, 0x86, - 0x5d, 0x82, 0x3b, 0xaf, 0x7a, 0x7d, 0x5d, 0x5b, 0x87, 0x8f, 0x9f, 0x33, 0x22, 0x05, 0x96, 0x41, 0xde, 0xe0, 0xe5, - 0x41, 0x18, 0xf8, 0x81, 0x3d, 0x82, 0x97, 0xa9, 0xb3, 0x2f, 0xc2, 0x90, 0x60, 0xd6, 0x93, 0x1a, 0xd2, 0x96, 0x05, - 0x57, 0xa7, 0xd3, 0x36, 0xdb, 0x51, 0xa0, 0x46, 0xa9, 0xde, 0x17, 0x86, 0x32, 0x25, 0x5a, 0x65, 0x13, 0xd8, 0x21, - 0x10, 0x2d, 0x5b, 0x11, 0xbe, 0xc5, 0xdc, 0x84, 0x05, 0x3a, 0xe9, 0xb4, 0xcd, 0x76, 0xb4, 0x08, 0xdf, 0x80, 0x4e, - 0x2e, 0x26, 0x5c, 0x4c, 0xb9, 0xf4, 0x84, 0xbc, 0x3a, 0xa9, 0x40, 0x89, 0x09, 0x78, 0x28, 0x23, 0xc3, 0x7c, 0x9a, - 0xf2, 0xa5, 0x27, 0xbf, 0x89, 0x59, 0xb4, 0x5f, 0xe6, 0x3c, 0x0d, 0xd2, 0x06, 0x13, 0x1b, 0xa4, 0xa6, 0xd5, 0x49, - 0x12, 0xdf, 0x1f, 0x5a, 0xc0, 0x0c, 0x4a, 0x73, 0x7c, 0x6e, 0x63, 0x52, 0x4a, 0x45, 0xc8, 0xb8, 0x5e, 0x1e, 0xf5, - 0xec, 0x7c, 0x18, 0x09, 0x6a, 0x76, 0x13, 0x7e, 0xb6, 0x17, 0x8d, 0x96, 0x8a, 0x97, 0x93, 0x50, 0xc2, 0x08, 0x89, - 0x95, 0x80, 0x04, 0x79, 0x93, 0xd9, 0x00, 0xe5, 0x4f, 0xca, 0x95, 0xfb, 0x4a, 0xc6, 0x63, 0x87, 0x70, 0xc0, 0xcf, - 0x1c, 0x03, 0x47, 0x19, 0x35, 0xfa, 0x47, 0xf3, 0xc1, 0x61, 0x74, 0xea, 0x12, 0x86, 0x09, 0xc8, 0x72, 0x89, 0x35, - 0xca, 0xf8, 0x30, 0x40, 0xf5, 0xba, 0x1f, 0x26, 0x1b, 0xfc, 0x11, 0x4d, 0x78, 0x24, 0x1b, 0xe6, 0xb0, 0xab, 0x16, - 0x9a, 0x18, 0xe4, 0x01, 0xe4, 0x16, 0x55, 0x46, 0x8e, 0xcc, 0xe9, 0x3d, 0xaa, 0x1c, 0xad, 0xd0, 0xf7, 0x11, 0xb0, - 0x94, 0xea, 0xd9, 0xb5, 0x34, 0x55, 0x00, 0x4b, 0x68, 0x25, 0x50, 0xb6, 0x31, 0x9b, 0x7c, 0x6f, 0xd9, 0xde, 0xb8, - 0xcc, 0x46, 0xfe, 0x22, 0x8d, 0x58, 0xc3, 0x96, 0x80, 0x73, 0xf5, 0x81, 0xd0, 0x76, 0xb2, 0x07, 0x10, 0xa2, 0xa4, - 0x17, 0x99, 0xbb, 0x32, 0x41, 0x6e, 0x5e, 0xf3, 0x89, 0x36, 0xcb, 0x00, 0x5b, 0x0d, 0xc1, 0x9d, 0xe7, 0xc2, 0x37, - 0xa9, 0x39, 0x29, 0xb8, 0xe0, 0xe7, 0xfb, 0x2b, 0x44, 0x15, 0x5e, 0xe4, 0xba, 0x1b, 0xae, 0x45, 0x3c, 0x37, 0xe6, - 0x5f, 0xab, 0xc6, 0x8b, 0x45, 0x19, 0x96, 0xca, 0xbf, 0xa1, 0xc9, 0x16, 0xb2, 0x6f, 0xa9, 0xa4, 0xf1, 0x6f, 0x09, - 0x7b, 0xe2, 0x83, 0xd1, 0x88, 0x32, 0xdc, 0xc0, 0x9a, 0xf8, 0xc8, 0xbc, 0x8a, 0x5e, 0x1c, 0x0f, 0x08, 0x0e, 0x02, - 0x94, 0x81, 0x93, 0x10, 0x06, 0xe2, 0x73, 0x8c, 0x35, 0x5f, 0xb3, 0x1e, 0x73, 0xde, 0xf4, 0x26, 0xcf, 0x35, 0xbf, - 0xe0, 0x35, 0xa0, 0x02, 0xda, 0xc3, 0x8e, 0x1e, 0xcb, 0x60, 0x42, 0x33, 0x1e, 0x42, 0x3e, 0x7d, 0xf0, 0xdb, 0xfc, - 0x8c, 0xc1, 0x2c, 0x0a, 0x09, 0x32, 0x9c, 0xae, 0xba, 0x99, 0xa1, 0xd5, 0x26, 0xf0, 0x7f, 0xbf, 0xbb, 0x19, 0x35, - 0x44, 0xde, 0x8b, 0x90, 0xe9, 0x06, 0x32, 0xda, 0x62, 0x1a, 0x36, 0xcd, 0x34, 0x5b, 0x0d, 0x86, 0xea, 0xa3, 0xa6, - 0xaf, 0xf1, 0xda, 0x6b, 0x1d, 0x95, 0x43, 0xa7, 0x36, 0x30, 0xbc, 0xe7, 0xbf, 0x77, 0x0f, 0x05, 0x79, 0x91, 0x14, - 0x72, 0x3b, 0x1d, 0x22, 0xc3, 0x4d, 0xec, 0x58, 0xf7, 0xfa, 0x9f, 0x31, 0xe3, 0xe4, 0x33, 0x93, 0x39, 0x81, 0x4d, - 0x53, 0x53, 0xb4, 0xa0, 0x9f, 0x36, 0x4b, 0x73, 0xa7, 0xac, 0xf5, 0x5a, 0xf0, 0x4b, 0xab, 0xd4, 0x38, 0x64, 0x55, - 0xc3, 0xcb, 0x0b, 0x5d, 0x3c, 0xf1, 0x82, 0xbf, 0x0c, 0x4c, 0xb8, 0xf1, 0x53, 0x2b, 0xea, 0xea, 0xe2, 0x85, 0xbe, - 0xef, 0x3e, 0x4b, 0x79, 0x48, 0xb4, 0x45, 0x16, 0x1a, 0xb2, 0xb9, 0xc9, 0x8b, 0x99, 0x2f, 0x36, 0xa3, 0x82, 0xcf, - 0x57, 0x68, 0x20, 0x1b, 0x1c, 0xb6, 0xd5, 0x35, 0xbe, 0xf0, 0xbc, 0x4b, 0xa4, 0x32, 0x72, 0xb1, 0x17, 0x1c, 0xc2, - 0x61, 0xb9, 0xb4, 0x98, 0xb5, 0x7a, 0xfe, 0x0e, 0x9d, 0xf1, 0x14, 0xa7, 0x90, 0xa8, 0x94, 0x8b, 0x4f, 0xcc, 0xfe, - 0xac, 0xef, 0xf7, 0x39, 0xc3, 0xfb, 0x03, 0xc9, 0x67, 0xfd, 0x63, 0x5f, 0x6d, 0x82, 0xbd, 0x93, 0xb7, 0x4a, 0xfb, - 0xda, 0x86, 0x65, 0xec, 0x23, 0x05, 0x04, 0x7f, 0x53, 0x38, 0x35, 0xf4, 0x08, 0x53, 0xd2, 0x72, 0x2f, 0xf2, 0xdb, - 0x8a, 0x68, 0x89, 0x06, 0xde, 0xe2, 0xb8, 0x48, 0x9f, 0xb6, 0xe5, 0x5d, 0xb6, 0xd4, 0xf1, 0xd0, 0xad, 0x8c, 0x25, - 0xd1, 0xa8, 0xd2, 0xf4, 0x41, 0xf4, 0xdc, 0xd9, 0x92, 0xe8, 0xed, 0xce, 0x68, 0xf6, 0x24, 0x1f, 0x13, 0xea, 0x1a, - 0x71, 0xab, 0x9e, 0xb7, 0xd8, 0xd7, 0xd4, 0xec, 0x86, 0x5e, 0xa8, 0x19, 0x2a, 0x21, 0xab, 0xd1, 0x17, 0x6a, 0xfd, - 0x28, 0x42, 0x92, 0xec, 0xf1, 0xeb, 0x9a, 0x5f, 0x3e, 0xdf, 0x48, 0x85, 0x72, 0x75, 0x51, 0x51, 0xa0, 0xf9, 0x79, - 0x9a, 0x78, 0x82, 0x72, 0x5e, 0x4b, 0x5f, 0x7d, 0x6a, 0x00, 0x2a, 0x42, 0x72, 0x6b, 0x87, 0x86, 0x34, 0xb4, 0xcc, - 0xcd, 0xb3, 0x79, 0x16, 0x8a, 0x00, 0xdd, 0x33, 0x4f, 0x3c, 0x75, 0x31, 0x6e, 0xf6, 0x82, 0x41, 0xc5, 0xce, 0x13, - 0x93, 0x01, 0x70, 0x92, 0x3a, 0x88, 0x46, 0xb0, 0xb7, 0x3b, 0xcd, 0x3e, 0xe6, 0xe2, 0x19, 0xb8, 0x10, 0xd6, 0xd3, - 0xf2, 0xda, 0xb3, 0x68, 0xd7, 0x33, 0xa4, 0x49, 0xb7, 0x6f, 0x57, 0xe3, 0xd1, 0x05, 0x77, 0x64, 0xd2, 0x48, 0x68, - 0xa9, 0x86, 0x42, 0xae, 0x52, 0xb9, 0xa3, 0xee, 0xac, 0x99, 0x52, 0x6e, 0xa2, 0x70, 0x2b, 0x73, 0xd9, 0xba, 0x8c, - 0xe5, 0x1c, 0x61, 0x85, 0xad, 0xcc, 0x12, 0xcf, 0x02, 0xfc, 0x08, 0x0c, 0xa2, 0x52, 0x95, 0x67, 0xa2, 0x08, 0x49, - 0xdd, 0x60, 0x81, 0x89, 0xec, 0x7d, 0xbf, 0x85, 0x02, 0x0f, 0xbe, 0xf2, 0x11, 0xa3, 0x48, 0x14, 0x02, 0x02, 0x68, - 0x30, 0xd0, 0x02, 0xaa, 0x59, 0x3a, 0xa8, 0x86, 0x0f, 0xa1, 0xf3, 0x22, 0x9e, 0x98, 0x24, 0x19, 0xf4, 0x6f, 0xff, - 0x43, 0x81, 0x98, 0xf4, 0x01, 0x92, 0x2a, 0x13, 0x80, 0x1b, 0x16, 0x8f, 0xd3, 0x68, 0x2e, 0x5b, 0x91, 0x2b, 0x3d, - 0x8e, 0x7c, 0x6e, 0x8b, 0x7a, 0xc1, 0xca, 0x4b, 0x48, 0x69, 0xc7, 0xf0, 0xb2, 0xd7, 0xa5, 0xc2, 0xcf, 0x5e, 0xf3, - 0x0b, 0x26, 0x17, 0xc6, 0x21, 0x29, 0x17, 0xca, 0x10, 0xd6, 0x03, 0x00, 0x99, 0x77, 0x03, 0xd5, 0x9b, 0x84, 0x87, - 0xad, 0xb2, 0x39, 0x14, 0x0c, 0xc1, 0xc1, 0xbd, 0xf3, 0x39, 0x21, 0x89, 0x79, 0x0c, 0x43, 0x00, 0x27, 0x71, 0x4a, - 0x68, 0x33, 0x97, 0x71, 0xa6, 0x4e, 0x4f, 0xb2, 0xeb, 0x40, 0xdc, 0xda, 0x12, 0x42, 0xb1, 0x97, 0x75, 0x62, 0xc8, - 0x92, 0xaa, 0xc7, 0xa4, 0xdc, 0x8c, 0x60, 0xd7, 0xfe, 0x14, 0x4f, 0x75, 0x18, 0x8a, 0x9b, 0x19, 0x18, 0x89, 0x99, - 0x90, 0x9c, 0x0d, 0x92, 0xe4, 0x99, 0x74, 0x59, 0x5b, 0x93, 0xba, 0xce, 0xdf, 0x32, 0x84, 0x47, 0x24, 0xe3, 0xfc, - 0x2a, 0x0f, 0x75, 0xc7, 0x95, 0x4d, 0xaa, 0x2c, 0x4f, 0x4f, 0xbe, 0xeb, 0x5e, 0xd7, 0x98, 0x1a, 0xde, 0x03, 0x6a, - 0x64, 0x71, 0xe8, 0x36, 0xe7, 0x63, 0x67, 0x82, 0x9f, 0xbb, 0x3c, 0x50, 0x17, 0x0f, 0x3b, 0x92, 0xd0, 0xcf, 0x37, - 0x78, 0x5d, 0x68, 0x74, 0xc6, 0x80, 0x9c, 0x24, 0xe7, 0xe2, 0x52, 0x0b, 0xd4, 0x58, 0xf0, 0xd5, 0x8e, 0xa4, 0x6e, - 0x23, 0x0f, 0x7c, 0x23, 0x2e, 0x84, 0x2e, 0x72, 0xdb, 0x74, 0x8d, 0xfc, 0x9c, 0xde, 0xad, 0x5a, 0xe0, 0x49, 0x7e, - 0xfd, 0x7b, 0x55, 0x7a, 0x42, 0xaf, 0x2a, 0x71, 0x16, 0x9f, 0xb8, 0x44, 0x37, 0xd3, 0x3c, 0x82, 0x93, 0xba, 0x6a, - 0xca, 0x00, 0xbd, 0x2e, 0xbc, 0x1d, 0x68, 0x12, 0x09, 0xbc, 0x30, 0xdd, 0x25, 0xae, 0xa4, 0x03, 0xe1, 0x41, 0xb1, - 0x87, 0x09, 0x26, 0x42, 0xa3, 0xcc, 0x86, 0x03, 0xc0, 0xcf, 0x21, 0xde, 0x8d, 0xf9, 0xab, 0x61, 0x59, 0x55, 0x0b, - 0x82, 0x3b, 0x65, 0x01, 0xd9, 0xcb, 0xc8, 0x80, 0x02, 0xea, 0x84, 0x2c, 0x28, 0x6d, 0xd4, 0xd8, 0x21, 0x67, 0x83, - 0x15, 0xaa, 0xe6, 0x01, 0xc7, 0x26, 0xdd, 0xda, 0xa7, 0x16, 0x62, 0x44, 0x83, 0x6a, 0x72, 0xfe, 0x3a, 0x40, 0x42, - 0xf9, 0x0c, 0x29, 0x70, 0xa4, 0x5f, 0x32, 0xff, 0x06, 0x4c, 0x7a, 0xa7, 0x20, 0xe8, 0x97, 0x21, 0xe3, 0x7e, 0xa9, - 0x23, 0x50, 0x5a, 0xc6, 0xf6, 0x0f, 0xc5, 0xf1, 0x0d, 0x67, 0x4c, 0xcf, 0xc9, 0xd7, 0x36, 0x9a, 0x3f, 0xaf, 0xd4, - 0x22, 0xc4, 0x4b, 0x42, 0x2a, 0x0c, 0x00, 0xbf, 0xb7, 0x92, 0xce, 0x63, 0xf0, 0xee, 0x01, 0xc7, 0x59, 0xad, 0x09, - 0xa5, 0x67, 0x40, 0xbe, 0xc5, 0xbf, 0x31, 0x4d, 0x07, 0x05, 0x70, 0x6a, 0x45, 0xde, 0xbb, 0xbb, 0xbb, 0x75, 0x28, - 0x18, 0xfa, 0x3a, 0x4c, 0x59, 0xbf, 0xe0, 0x28, 0x1b, 0xc8, 0x6d, 0xbb, 0xdd, 0x6d, 0x55, 0xd2, 0xce, 0x24, 0xc3, - 0x23, 0x89, 0x41, 0x2a, 0x8d, 0xfc, 0xac, 0x2b, 0xab, 0xcb, 0x2c, 0x8e, 0x14, 0x17, 0x80, 0xee, 0x78, 0x86, 0xcd, - 0x1b, 0x5b, 0xf5, 0x81, 0x77, 0x20, 0xcd, 0x75, 0x02, 0x00, 0xbc, 0xf0, 0x54, 0x31, 0xe1, 0x8e, 0xb9, 0xca, 0x4e, - 0xa2, 0x9e, 0x4c, 0x34, 0x07, 0xe7, 0xf9, 0xa8, 0x42, 0x3e, 0xe9, 0x0e, 0x2b, 0x3e, 0x2f, 0x02, 0xe2, 0x71, 0x9c, - 0x54, 0x06, 0x43, 0xa2, 0xe0, 0xa7, 0x22, 0xec, 0x78, 0xba, 0x70, 0x9e, 0xdc, 0x55, 0xe9, 0xce, 0x01, 0xaa, 0x21, - 0x01, 0xab, 0x82, 0x6d, 0xd8, 0xbc, 0xcc, 0x49, 0x5c, 0xb6, 0x33, 0x86, 0x64, 0x1d, 0x0e, 0x6a, 0xe1, 0x63, 0xaf, - 0xf4, 0x43, 0x52, 0x28, 0xc4, 0xb9, 0x08, 0xe7, 0x59, 0x48, 0x9e, 0x0e, 0x90, 0x19, 0x79, 0x39, 0x79, 0xaf, 0xdd, - 0xd9, 0xae, 0x5b, 0x82, 0x48, 0xb7, 0x78, 0x6b, 0xac, 0xa7, 0xe3, 0x95, 0x4d, 0xc7, 0x54, 0x05, 0x92, 0x4d, 0xa4, - 0x82, 0x2a, 0xa5, 0xc1, 0xca, 0xd3, 0x01, 0x50, 0x30, 0x37, 0xfc, 0xad, 0x71, 0x4f, 0xcb, 0x84, 0x61, 0x73, 0x34, - 0xd8, 0x24, 0x0e, 0xee, 0x07, 0x83, 0x4e, 0x21, 0x6e, 0xd4, 0x2e, 0x70, 0x0d, 0x36, 0xd1, 0xcc, 0xc4, 0x1e, 0xff, - 0x5e, 0x7e, 0x10, 0x59, 0x65, 0x57, 0x25, 0xcd, 0x44, 0xa2, 0x5c, 0xba, 0x08, 0xc9, 0x5e, 0xfd, 0x3b, 0xfd, 0x56, - 0xe8, 0x74, 0xa0, 0x00, 0x74, 0x1c, 0x29, 0x24, 0xc4, 0x4c, 0x93, 0xee, 0x89, 0xe7, 0xf7, 0x5f, 0x7f, 0xfd, 0xdd, - 0xd6, 0xd6, 0x7c, 0x15, 0xbc, 0xf3, 0x79, 0xd1, 0x84, 0xed, 0xce, 0x52, 0xea, 0xfa, 0x1d, 0x58, 0x00, 0x3b, 0xdb, - 0x78, 0x26, 0x86, 0xb7, 0x4d, 0xf4, 0xa0, 0x0b, 0xf2, 0xc2, 0xf1, 0xa3, 0xf6, 0x87, 0x8f, 0xb8, 0x55, 0x16, 0xe8, - 0xbd, 0xba, 0x33, 0x8b, 0x40, 0xcc, 0x00, 0x2a, 0x20, 0xaf, 0xa0, 0xab, 0x18, 0x82, 0xe0, 0x97, 0x06, 0x49, 0x87, - 0x13, 0xce, 0x04, 0x7c, 0x36, 0x08, 0xba, 0xf3, 0xb7, 0xc3, 0x8e, 0xee, 0x44, 0xbc, 0x77, 0xe8, 0xe2, 0xd7, 0x76, - 0xea, 0x90, 0x29, 0x4f, 0x2f, 0x8d, 0xae, 0xec, 0x42, 0x73, 0xbd, 0xd3, 0xa7, 0x12, 0xe2, 0x63, 0x36, 0x46, 0x2e, - 0x28, 0x5e, 0xc1, 0x40, 0xf3, 0x60, 0x93, 0x7c, 0xb1, 0xf5, 0x3a, 0xb8, 0x1f, 0x37, 0x8f, 0x14, 0xfb, 0x05, 0xd5, - 0x0f, 0xb8, 0x61, 0x17, 0x52, 0xcb, 0xc7, 0x05, 0xc6, 0xca, 0x38, 0x28, 0x7f, 0x4e, 0xbb, 0xd3, 0x0b, 0xbf, 0x58, - 0x14, 0x15, 0x53, 0x12, 0xbf, 0x4d, 0xc2, 0xa4, 0x71, 0xaf, 0x5b, 0xd3, 0xe3, 0xf4, 0xbc, 0x20, 0x9c, 0x3b, 0xb9, - 0x7b, 0xfe, 0x4b, 0xb4, 0x3e, 0x9b, 0xe3, 0x76, 0xd7, 0xad, 0xe9, 0x77, 0x83, 0xa5, 0x4a, 0x93, 0x6e, 0x69, 0xec, - 0x5c, 0xbd, 0x09, 0x97, 0x75, 0x11, 0x89, 0xee, 0xcf, 0x7a, 0x2c, 0xa8, 0xd4, 0x33, 0x33, 0x7f, 0x0a, 0xa2, 0x86, - 0xb8, 0xde, 0xea, 0xe2, 0xbd, 0x5e, 0x7c, 0x4b, 0x8e, 0xbd, 0x74, 0x95, 0x64, 0x30, 0xa8, 0x0e, 0x5d, 0x0d, 0x8b, - 0xe4, 0x88, 0xa8, 0x5f, 0x31, 0x09, 0x98, 0xf5, 0x9c, 0x8f, 0xae, 0xd7, 0xa2, 0x79, 0xfa, 0xd6, 0x13, 0xa1, 0x7f, - 0xae, 0xc3, 0xed, 0xfb, 0x04, 0xae, 0xb6, 0xad, 0x63, 0x19, 0x8d, 0xe2, 0xcb, 0x46, 0x22, 0x66, 0x61, 0x47, 0xa2, - 0x4f, 0xff, 0x80, 0x48, 0xa2, 0xfc, 0xa4, 0xa5, 0x07, 0x49, 0x25, 0xdb, 0x6f, 0xf8, 0x70, 0x1f, 0xb5, 0x10, 0x68, - 0x6f, 0xff, 0x28, 0x52, 0x35, 0xbd, 0x4c, 0x24, 0xb1, 0xea, 0x40, 0xbd, 0xa6, 0xd4, 0xe7, 0x3e, 0xff, 0x7c, 0xfb, - 0x1d, 0x25, 0x64, 0x9a, 0x28, 0x59, 0xce, 0x18, 0x40, 0xae, 0xb1, 0xbb, 0x92, 0x90, 0x35, 0xbc, 0x4c, 0x4a, 0xef, - 0xc3, 0xcf, 0x67, 0xeb, 0xd0, 0x77, 0xff, 0x94, 0xc6, 0x65, 0xc1, 0x39, 0xf3, 0x66, 0xfe, 0x98, 0x9e, 0x06, 0x82, - 0x35, 0xaf, 0xb1, 0x77, 0x97, 0xeb, 0xcb, 0xd2, 0xe9, 0xa2, 0x5d, 0x3a, 0x5d, 0xb4, 0xda, 0x1b, 0xe6, 0xdf, 0xac, - 0x63, 0x0e, 0xbc, 0x5a, 0xb6, 0x0d, 0xa6, 0x12, 0x3c, 0xb5, 0xe5, 0x3f, 0x3a, 0x03, 0x57, 0x1e, 0x90, 0x1a, 0x6d, - 0xa0, 0x4f, 0x65, 0x10, 0x74, 0x73, 0xc3, 0x82, 0xa6, 0xab, 0x32, 0x23, 0xcd, 0x7c, 0x24, 0x5d, 0xf0, 0x39, 0x8d, - 0x39, 0xd8, 0xa7, 0xa9, 0xf2, 0x32, 0x14, 0x33, 0x7e, 0x56, 0xda, 0x82, 0xa6, 0x43, 0xe1, 0x47, 0x5c, 0xa6, 0x06, - 0xf4, 0xa2, 0xf3, 0x6b, 0x98, 0xc7, 0x59, 0xfa, 0x9b, 0xa7, 0x18, 0xe3, 0xf3, 0x86, 0x4c, 0xe1, 0xb8, 0xeb, 0x5e, - 0xa2, 0x80, 0x9f, 0x13, 0x1a, 0xcb, 0xf8, 0xbd, 0x18, 0xb4, 0x2f, 0xd2, 0x6d, 0x2e, 0x02, 0xa7, 0x02, 0xe4, 0x0f, - 0x09, 0xe3, 0x40, 0xd1, 0xd1, 0x5e, 0x63, 0xdf, 0x29, 0x55, 0xa6, 0xcf, 0x3d, 0xad, 0xd1, 0x13, 0xa5, 0x4c, 0x3f, - 0x19, 0x63, 0xcc, 0xba, 0xc8, 0xb1, 0xa5, 0xf9, 0xc0, 0x20, 0x93, 0x7c, 0xe1, 0x22, 0xa7, 0xc7, 0x9c, 0x3a, 0x0b, - 0x74, 0xab, 0x50, 0x6b, 0x0f, 0x96, 0x3f, 0xa0, 0x72, 0x60, 0xa8, 0x28, 0xfb, 0x71, 0x8a, 0x2d, 0xe2, 0x43, 0xfb, - 0x0d, 0xb7, 0x90, 0xb8, 0xed, 0x45, 0x26, 0x82, 0x54, 0x83, 0xa2, 0x58, 0xdb, 0x24, 0x23, 0xb9, 0xa1, 0x8a, 0xc1, - 0x46, 0x2d, 0x9f, 0x3e, 0x83, 0xd3, 0xe5, 0xd3, 0xd3, 0x9c, 0x5a, 0xb4, 0x25, 0x33, 0xf5, 0x8c, 0xc4, 0xd2, 0x15, - 0x76, 0xf1, 0xf2, 0x6b, 0xbc, 0xa1, 0x7d, 0xcc, 0x40, 0x22, 0x29, 0xbd, 0x6a, 0x1a, 0xc4, 0x0c, 0x36, 0x90, 0x46, - 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x4e, 0x40, 0x00, 0x46, 0x0f, 0x3f, 0x7a, 0x43, 0xe9, 0xb4, 0xd9, 0xed, 0x76, 0x56, - 0x26, 0x50, 0x74, 0xcd, 0x27, 0x63, 0x92, 0x37, 0x84, 0x9d, 0xc5, 0x2d, 0x79, 0x2a, 0x84, 0x31, 0x78, 0x79, 0x66, - 0x6c, 0x31, 0x7f, 0x7e, 0x3d, 0xd6, 0x2f, 0x0c, 0x25, 0x51, 0x52, 0xc8, 0xbe, 0xd4, 0x2d, 0x33, 0x1c, 0x59, 0x9c, - 0xe6, 0xe4, 0xd2, 0x83, 0x33, 0xf5, 0x18, 0x78, 0x0e, 0x04, 0xf2, 0xfa, 0x0e, 0xfb, 0xed, 0xc0, 0x09, 0x47, 0xfc, - 0x14, 0xf3, 0xf1, 0x4f, 0xd5, 0x42, 0xf6, 0xcc, 0xea, 0xbc, 0x53, 0x16, 0xbb, 0x2a, 0x54, 0x51, 0x67, 0x0a, 0x2a, - 0xf8, 0xad, 0x43, 0x04, 0x6d, 0xfb, 0x49, 0x92, 0x21, 0x12, 0x55, 0x81, 0xfa, 0x6c, 0x26, 0x92, 0x60, 0x2e, 0xc0, - 0x92, 0xe5, 0x0d, 0xe7, 0xbc, 0xf6, 0xb7, 0xae, 0x49, 0xe6, 0x0d, 0x70, 0xd1, 0x7c, 0xda, 0xe9, 0xe9, 0x3a, 0xf2, - 0xad, 0x87, 0xa9, 0x75, 0xa8, 0x05, 0xb3, 0x84, 0x8b, 0x59, 0xb9, 0x89, 0x7d, 0x79, 0x1b, 0xa8, 0x99, 0x1c, 0x84, - 0xca, 0x9f, 0x98, 0x9c, 0x52, 0x1b, 0xa9, 0x90, 0xb5, 0x87, 0xcc, 0x49, 0x07, 0x21, 0xdc, 0x86, 0xf4, 0xdb, 0xf9, - 0x65, 0x87, 0x4c, 0xf6, 0xa3, 0x2d, 0x0c, 0xe9, 0xff, 0x7a, 0x85, 0x49, 0x68, 0x30, 0x42, 0xb8, 0x9f, 0x04, 0x08, - 0xf7, 0xa2, 0x53, 0x16, 0xe1, 0xc2, 0x9d, 0x47, 0x61, 0xbf, 0x77, 0x36, 0x54, 0x86, 0x05, 0xe7, 0x07, 0xcd, 0xcf, - 0x71, 0x10, 0x8e, 0xf5, 0x9a, 0x3c, 0x30, 0x7e, 0xfc, 0x91, 0xbd, 0x40, 0xc0, 0x7c, 0x37, 0x11, 0xb4, 0xea, 0x14, - 0x28, 0x0b, 0xd6, 0x38, 0x18, 0x48, 0x0a, 0x16, 0xfb, 0x46, 0xaa, 0x7a, 0x9b, 0xb2, 0x2d, 0x9f, 0xe5, 0x49, 0xc7, - 0xe9, 0x5f, 0xd6, 0x7a, 0x9b, 0x10, 0x62, 0x5f, 0xf4, 0xb9, 0xf2, 0x01, 0x4a, 0xb4, 0xda, 0xe7, 0xff, 0x25, 0xb8, - 0xf5, 0xf5, 0xdf, 0x79, 0x35, 0xd3, 0x46, 0x8a, 0x59, 0x14, 0x5e, 0x7b, 0xa9, 0xac, 0x19, 0x9f, 0x90, 0xad, 0x66, - 0x4d, 0x36, 0x4e, 0x05, 0xc5, 0x4d, 0x5d, 0x0b, 0xb6, 0x98, 0x96, 0x6c, 0xde, 0x16, 0x93, 0x78, 0x63, 0x7e, 0x49, - 0xcb, 0xb1, 0x39, 0x17, 0xda, 0x8a, 0x41, 0xa3, 0x8e, 0x87, 0x8d, 0x9e, 0x13, 0x9d, 0x32, 0x5d, 0xaf, 0x1c, 0x37, - 0x55, 0xb5, 0xbf, 0x04, 0x0e, 0x9d, 0xda, 0x0a, 0x91, 0x56, 0xcb, 0x51, 0x43, 0x9e, 0x61, 0x59, 0x2b, 0x03, 0xe1, - 0x3a, 0x90, 0x76, 0xe7, 0xaf, 0xb3, 0xe4, 0x59, 0x70, 0xcb, 0x12, 0x8f, 0xf0, 0xa5, 0x66, 0x72, 0x8b, 0xe4, 0x15, - 0x93, 0x28, 0x0f, 0xe5, 0xc1, 0xee, 0xfc, 0x7c, 0xa2, 0xbd, 0x92, 0x2c, 0xe7, 0x33, 0xcd, 0x0b, 0x10, 0x42, 0xa6, - 0x6b, 0x09, 0x6d, 0xd9, 0x0b, 0xf6, 0xc4, 0xb8, 0x7a, 0x4a, 0x92, 0xf9, 0x25, 0x38, 0xf8, 0xeb, 0x7e, 0x9b, 0xa5, - 0x35, 0xf8, 0xdb, 0xbb, 0xc5, 0x4c, 0x6c, 0x2f, 0xb4, 0x19, 0xa9, 0x90, 0x7d, 0xff, 0xd7, 0x81, 0x78, 0x13, 0x98, - 0x1f, 0xea, 0xa8, 0x71, 0x74, 0x4f, 0x35, 0xfe, 0x2f, 0x1c, 0x36, 0x5a, 0x7a, 0xed, 0x68, 0xae, 0x91, 0x80, 0xc9, - 0x91, 0x7b, 0x55, 0xdf, 0x8b, 0x82, 0xbd, 0xe1, 0x81, 0x40, 0x59, 0xcd, 0xfe, 0x7e, 0xfd, 0x20, 0x00, 0x70, 0xa5, - 0x67, 0x1d, 0xaf, 0xe5, 0x67, 0xdb, 0x6d, 0x6c, 0xc0, 0xe5, 0x5a, 0xc1, 0x7f, 0x15, 0x47, 0xe8, 0xaf, 0xcd, 0x24, - 0x87, 0xed, 0xba, 0x1e, 0x0a, 0x3a, 0x64, 0xcc, 0x29, 0x06, 0x71, 0x3d, 0xf9, 0x92, 0xf5, 0x3a, 0x30, 0x6f, 0x82, - 0xda, 0xfc, 0x62, 0xef, 0xc5, 0x5e, 0x65, 0xd2, 0xa0, 0x29, 0x82, 0xff, 0x02, 0xf5, 0x01, 0xfe, 0xf4, 0x82, 0xb0, - 0x28, 0x7e, 0x50, 0x1c, 0xce, 0xb0, 0xc0, 0x66, 0x56, 0x1a, 0x5a, 0x07, 0xc6, 0x8f, 0x19, 0x3d, 0xf5, 0x09, 0xc6, - 0xa1, 0xc8, 0xd9, 0x39, 0x38, 0xc9, 0x51, 0xaa, 0x95, 0xfb, 0xfb, 0x4d, 0x9e, 0x84, 0x49, 0x4b, 0x3b, 0xf7, 0x27, - 0x68, 0x1f, 0xab, 0x3f, 0xff, 0xc7, 0xb1, 0x9b, 0x31, 0x2c, 0xa3, 0x76, 0x13, 0xbf, 0x3f, 0x81, 0x1b, 0x35, 0x4f, - 0xa9, 0xdb, 0xbd, 0x33, 0x7f, 0xd7, 0xb7, 0xf6, 0xf8, 0x69, 0xa0, 0x34, 0x86, 0xb1, 0x00, 0xb1, 0x98, 0xc6, 0x4b, - 0x63, 0x79, 0x07, 0x33, 0x37, 0x6c, 0xa3, 0x6f, 0x66, 0x7c, 0xeb, 0xe7, 0x0c, 0x41, 0x03, 0x62, 0xd4, 0x74, 0x69, - 0x45, 0xa5, 0xdf, 0xa5, 0xb8, 0xf3, 0x26, 0x14, 0x68, 0x9e, 0xfb, 0x1c, 0x0a, 0xa7, 0xa3, 0x48, 0x25, 0x25, 0xc0, - 0x3a, 0x59, 0x7e, 0xd6, 0x2e, 0xe2, 0xfd, 0x85, 0xd0, 0x25, 0xbc, 0xae, 0x53, 0xc4, 0xaf, 0xc5, 0x70, 0x33, 0x4d, - 0x37, 0x1b, 0xa8, 0x2f, 0xcb, 0x2e, 0x9d, 0x83, 0x23, 0xf8, 0x6a, 0x8d, 0x54, 0x44, 0xce, 0x50, 0x5f, 0x24, 0xd6, - 0x70, 0xe8, 0x23, 0x0e, 0xd6, 0xa5, 0xea, 0x80, 0x26, 0xdf, 0xac, 0x76, 0xd9, 0x69, 0xa3, 0x39, 0x4d, 0x4d, 0x31, - 0x83, 0x18, 0x0e, 0x3e, 0x89, 0xd0, 0xd9, 0xb4, 0x8f, 0x9b, 0xac, 0x89, 0x33, 0x34, 0x0d, 0xd7, 0x31, 0x5a, 0x55, - 0xc2, 0xac, 0xb2, 0x8d, 0xc7, 0x53, 0xda, 0x55, 0xeb, 0x9e, 0x08, 0x3b, 0xe7, 0xd2, 0x51, 0xab, 0x09, 0xda, 0x26, - 0x22, 0x85, 0xe2, 0xb0, 0xd5, 0x84, 0xbe, 0x3b, 0xac, 0x58, 0x61, 0xc5, 0xdb, 0x25, 0xf5, 0x3a, 0x66, 0x1c, 0xae, - 0x84, 0xc5, 0x1c, 0x60, 0xe0, 0x97, 0xb1, 0xf2, 0x81, 0x9a, 0xe4, 0x54, 0x7a, 0x48, 0x79, 0x97, 0x52, 0x9d, 0xcc, - 0x63, 0xff, 0xe2, 0xee, 0xf5, 0xa5, 0xf9, 0xe2, 0x6e, 0x32, 0xde, 0x42, 0x98, 0x3a, 0x6d, 0xa0, 0x2e, 0x6b, 0x3b, - 0x22, 0x74, 0xb9, 0x4f, 0xb4, 0x18, 0xef, 0x29, 0x74, 0x97, 0x93, 0xce, 0x09, 0xd5, 0x7f, 0x0a, 0x44, 0xf9, 0x88, - 0x32, 0xc8, 0xdd, 0x9d, 0x8a, 0x5d, 0xc9, 0xd3, 0x9d, 0x24, 0x3e, 0x56, 0xdf, 0x30, 0x32, 0x68, 0x6d, 0x9d, 0xa8, - 0xf6, 0x9d, 0xf5, 0x3e, 0x41, 0x8c, 0x75, 0x4b, 0x2c, 0xcb, 0xb7, 0xcb, 0x1d, 0xd2, 0x80, 0x38, 0xb7, 0x97, 0x61, - 0x5d, 0xce, 0xd1, 0x08, 0xf3, 0x65, 0x2c, 0x25, 0x24, 0x20, 0x92, 0x3e, 0x4e, 0x48, 0x97, 0xe2, 0xef, 0xba, 0xc3, - 0x65, 0x79, 0x12, 0xc2, 0x7c, 0xf4, 0x32, 0x66, 0x52, 0x97, 0xe0, 0x6b, 0xbc, 0xc9, 0x2f, 0x09, 0xb8, 0x24, 0x9a, - 0x5e, 0x5f, 0x71, 0xaa, 0x4b, 0xd5, 0xdb, 0x16, 0x14, 0xa7, 0xe9, 0x57, 0x2d, 0xc9, 0x2d, 0xf1, 0x99, 0xb1, 0x60, - 0x10, 0xa8, 0x43, 0x45, 0x2f, 0x03, 0x15, 0x63, 0x2c, 0x22, 0x4e, 0x97, 0x5f, 0x32, 0xa9, 0xae, 0x74, 0xa8, 0xda, - 0xb3, 0xf7, 0x17, 0x4f, 0x76, 0x78, 0x34, 0x7d, 0xfa, 0xe3, 0xeb, 0x41, 0x0f, 0xaa, 0xa0, 0x53, 0xb8, 0xdd, 0xd9, - 0xc0, 0x50, 0x28, 0x40, 0x56, 0x76, 0x2e, 0xcb, 0x00, 0xea, 0x4c, 0x4d, 0x49, 0x77, 0x7d, 0xdd, 0x9b, 0x44, 0x7a, - 0xd9, 0x30, 0xe3, 0xe7, 0xd0, 0x92, 0x9f, 0x4d, 0xf3, 0xcb, 0x1d, 0x6d, 0x63, 0x39, 0xe2, 0x29, 0xb0, 0xb1, 0x30, - 0x78, 0x0f, 0x29, 0x6e, 0xc2, 0x20, 0x43, 0x0e, 0x92, 0xbc, 0xd2, 0x96, 0xe5, 0xb9, 0x96, 0x92, 0x0d, 0x33, 0x7e, - 0x4f, 0x8a, 0x02, 0xe5, 0x77, 0x89, 0xb7, 0x71, 0x43, 0x00, 0x4e, 0x50, 0xda, 0x1c, 0x39, 0x56, 0x71, 0x2b, 0xbf, - 0x31, 0x78, 0x11, 0x81, 0x9e, 0x29, 0x1c, 0xe3, 0xf9, 0xc3, 0x7e, 0x1c, 0x21, 0x48, 0x05, 0x3f, 0xac, 0xd4, 0x66, - 0x47, 0x2f, 0xfd, 0xd7, 0xac, 0xa6, 0x47, 0x46, 0xba, 0xdb, 0x24, 0x6a, 0xcb, 0x4e, 0x54, 0x80, 0x19, 0x44, 0x63, - 0xe0, 0x82, 0x3b, 0xc6, 0x34, 0x1f, 0xfe, 0xdb, 0x4f, 0xac, 0x3d, 0xcc, 0xdf, 0xce, 0x78, 0xe5, 0xc9, 0x4b, 0x64, - 0x81, 0x9a, 0x8f, 0x5d, 0x5f, 0x5e, 0xc6, 0x77, 0xeb, 0x3e, 0x9e, 0xba, 0x05, 0x59, 0x40, 0x80, 0x81, 0xf8, 0x99, - 0x33, 0xd1, 0x1b, 0xc2, 0x9d, 0xd4, 0xc4, 0xd3, 0x5a, 0xcd, 0x6f, 0xf2, 0xf6, 0xda, 0x45, 0x0d, 0xc9, 0x5b, 0x67, - 0xed, 0x66, 0x55, 0x7a, 0x6c, 0x4d, 0xf2, 0xfd, 0x9a, 0x49, 0x96, 0xfa, 0x5f, 0xc3, 0xad, 0xb1, 0x7d, 0xbb, 0x0a, - 0xcb, 0x3a, 0xcc, 0x5f, 0x5e, 0x5f, 0x72, 0x1c, 0xe7, 0xbc, 0xf8, 0x8d, 0x35, 0xb6, 0xf0, 0xe6, 0x64, 0x4b, 0xc2, - 0x65, 0x6a, 0x35, 0xf7, 0xac, 0x56, 0xb5, 0x67, 0x49, 0xc8, 0xcd, 0x5e, 0xf6, 0x00, 0x9d, 0xbf, 0x37, 0xe9, 0x73, - 0xfc, 0x5e, 0x67, 0xcd, 0xe9, 0x7b, 0x83, 0x34, 0xd7, 0x9f, 0x22, 0xb2, 0x78, 0x66, 0x9d, 0x3c, 0xaa, 0xec, 0x15, - 0x93, 0x69, 0x3e, 0x26, 0xe4, 0x0a, 0x61, 0x58, 0x55, 0xbb, 0x3e, 0x3d, 0xa1, 0xe2, 0x86, 0x03, 0xc8, 0x6d, 0x7c, - 0x3e, 0xc8, 0x0d, 0xfe, 0x5e, 0xd9, 0x59, 0x0e, 0x3a, 0x0b, 0x6d, 0x7e, 0xec, 0xa1, 0xee, 0xc7, 0xe1, 0x61, 0x08, - 0xae, 0xcc, 0xde, 0x9c, 0xaa, 0x5f, 0x03, 0xd2, 0xea, 0x9c, 0xdb, 0xae, 0x20, 0x17, 0x7b, 0xfd, 0x4a, 0xb9, 0x37, - 0x0a, 0x44, 0x63, 0x43, 0x49, 0xea, 0x2c, 0xf2, 0xdd, 0x90, 0x3a, 0xb9, 0xdb, 0xce, 0xe8, 0x68, 0x7d, 0xe2, 0x23, - 0xfe, 0x54, 0x0d, 0x55, 0x98, 0xaf, 0xe7, 0x36, 0xcb, 0x7a, 0x80, 0xc6, 0x11, 0x69, 0x56, 0xd7, 0x9b, 0x92, 0x5e, - 0xad, 0x88, 0x4c, 0x68, 0x0c, 0xbe, 0xc9, 0xe0, 0x20, 0x1f, 0x57, 0x42, 0x2f, 0x92, 0x6e, 0xca, 0x27, 0xfb, 0x5f, - 0x45, 0x7b, 0x31, 0x07, 0x10, 0xfb, 0x16, 0x5d, 0x60, 0xb6, 0x56, 0x60, 0x8f, 0xd0, 0x1c, 0x2f, 0x11, 0xbd, 0xac, - 0x2c, 0x54, 0x5c, 0x58, 0x13, 0xd6, 0x7a, 0x9f, 0xb5, 0xc2, 0x69, 0xee, 0xfc, 0x53, 0x5d, 0x84, 0x50, 0xe2, 0x53, - 0x99, 0xd5, 0x80, 0x62, 0xa8, 0x81, 0x64, 0x3f, 0x39, 0xbf, 0xf2, 0x59, 0x64, 0x06, 0xe4, 0x6b, 0xb7, 0xe3, 0x83, - 0x3b, 0x1e, 0x8c, 0x3b, 0xbe, 0x6d, 0x3f, 0xb5, 0xd6, 0x9b, 0x49, 0x56, 0x4d, 0x33, 0x73, 0xde, 0x05, 0x86, 0x1d, - 0x0e, 0x2e, 0xcf, 0xce, 0xe7, 0x2e, 0x68, 0xda, 0x13, 0x96, 0xa9, 0x45, 0x73, 0x1b, 0xf0, 0xe4, 0x23, 0x7a, 0x4a, - 0x23, 0x39, 0xbb, 0xc3, 0x7b, 0x20, 0x77, 0x28, 0x7d, 0x6a, 0x25, 0x5f, 0xb0, 0x62, 0xc1, 0x79, 0xb3, 0x20, 0x16, - 0xcb, 0xa6, 0xea, 0x25, 0x48, 0x3a, 0xc4, 0xf9, 0x6c, 0x70, 0x9d, 0x4a, 0xa1, 0x1b, 0xfc, 0x7f, 0x89, 0x91, 0x1c, - 0xb6, 0xa2, 0x20, 0x98, 0x3a, 0x27, 0x41, 0x25, 0x62, 0xff, 0x46, 0x86, 0x0e, 0xfe, 0x0c, 0xaa, 0x94, 0x7d, 0x44, - 0x97, 0x3e, 0xbb, 0x37, 0xc1, 0x89, 0xd8, 0xee, 0x19, 0xe9, 0x7c, 0x48, 0x68, 0x7f, 0x7e, 0xfe, 0xcd, 0x65, 0x1f, - 0x19, 0x62, 0xbe, 0xae, 0xdd, 0x9b, 0xf7, 0x20, 0xd5, 0xb3, 0x3f, 0x47, 0x2c, 0x86, 0xb3, 0xcc, 0x84, 0xe7, 0x51, - 0x4c, 0xaf, 0xdd, 0x37, 0x78, 0x12, 0x48, 0x18, 0x43, 0xd0, 0x3e, 0x5c, 0xe1, 0x9b, 0xaf, 0x22, 0x26, 0x6b, 0x48, - 0xf8, 0xf8, 0xac, 0xf8, 0xad, 0xb3, 0x17, 0xb5, 0xb8, 0x61, 0x68, 0xa6, 0x8e, 0xd3, 0x3c, 0x6f, 0xc1, 0x7d, 0x9e, - 0xda, 0x73, 0xa2, 0xd2, 0x68, 0x9d, 0xe7, 0xeb, 0x37, 0x61, 0x56, 0x2d, 0xdd, 0xe6, 0xef, 0xc2, 0xd8, 0x56, 0xa8, - 0x22, 0xff, 0xbc, 0x8b, 0xb0, 0x1f, 0x71, 0x1a, 0x68, 0x24, 0xbf, 0x6a, 0x4b, 0xbe, 0xf2, 0x4e, 0xc2, 0x2c, 0xcc, - 0x4d, 0xac, 0x8b, 0x8d, 0x32, 0x3f, 0x8b, 0xc9, 0xcf, 0x54, 0xe4, 0x63, 0xe3, 0x8a, 0xae, 0xf6, 0x09, 0xf1, 0xf0, - 0x68, 0x7d, 0x18, 0x77, 0xcb, 0x62, 0x6d, 0x56, 0xe6, 0x8b, 0xb2, 0x2b, 0xb5, 0xcf, 0xd3, 0x17, 0xfc, 0x68, 0xb1, - 0x3e, 0xd8, 0xb9, 0x97, 0x08, 0xc8, 0xa0, 0x5a, 0x96, 0xb6, 0x43, 0xe4, 0xe1, 0xe5, 0x26, 0x2f, 0x79, 0x9b, 0x27, - 0x2a, 0x4a, 0xdb, 0x21, 0xf0, 0xdd, 0x7d, 0x9d, 0x1c, 0xd0, 0x25, 0xcc, 0xd3, 0x15, 0x40, 0x6b, 0xc0, 0x42, 0x6e, - 0x56, 0x27, 0xf6, 0x5c, 0x95, 0x6c, 0xda, 0xdb, 0x35, 0xf9, 0x73, 0x07, 0x94, 0x13, 0x6e, 0xec, 0xcb, 0xc8, 0xb0, - 0x5c, 0x95, 0x6e, 0x84, 0xcf, 0xfa, 0xc8, 0x9d, 0x67, 0x1f, 0xf0, 0xc3, 0x6f, 0xc9, 0x3d, 0xfa, 0xeb, 0x3c, 0x32, - 0x2d, 0xdf, 0x16, 0x34, 0x6a, 0x1c, 0xa2, 0xf1, 0x56, 0x12, 0x10, 0x15, 0x55, 0x03, 0x1e, 0x53, 0x7e, 0x16, 0x2c, - 0x8f, 0x64, 0x94, 0x1d, 0xf2, 0xa5, 0xb6, 0xfb, 0xb1, 0x35, 0xf1, 0xcf, 0xac, 0x43, 0xab, 0xac, 0x4f, 0x86, 0x2f, - 0xb5, 0xdd, 0xde, 0x7b, 0xa1, 0x80, 0x08, 0xb0, 0x87, 0xc1, 0xe7, 0xd8, 0x5a, 0x2d, 0xf8, 0xfc, 0xf8, 0xf9, 0x81, - 0x3b, 0x56, 0xcc, 0x79, 0xdf, 0xf5, 0x5d, 0x80, 0x92, 0xcc, 0x08, 0x03, 0x3b, 0x66, 0x37, 0xc6, 0x90, 0xc4, 0x49, - 0xa3, 0x71, 0x1f, 0xc4, 0x09, 0xbd, 0x35, 0xec, 0x00, 0x70, 0x89, 0x3c, 0x19, 0x2e, 0x53, 0x48, 0x97, 0xc8, 0x87, - 0xe9, 0x7b, 0x5c, 0x91, 0x45, 0x02, 0x7c, 0xc3, 0x6b, 0x25, 0xdb, 0x26, 0x58, 0x41, 0x8b, 0x62, 0x0e, 0x64, 0x3a, - 0x4b, 0x15, 0xdf, 0x30, 0xe2, 0x9c, 0x3f, 0x74, 0x9b, 0x37, 0x17, 0x33, 0x5e, 0x3f, 0x9f, 0xfa, 0xb4, 0x97, 0x09, - 0xed, 0x68, 0x4e, 0x33, 0x30, 0xa0, 0xe8, 0x57, 0xc5, 0xe6, 0x4f, 0xb0, 0x44, 0xc9, 0x3f, 0xda, 0xc8, 0xce, 0x9f, - 0x10, 0xfa, 0x88, 0x24, 0x60, 0xa2, 0xb1, 0xfd, 0x74, 0x4e, 0xd1, 0xdb, 0xaa, 0x86, 0xae, 0x08, 0x0b, 0xef, 0x83, - 0x1d, 0x5b, 0xb8, 0x36, 0x43, 0xd1, 0x38, 0xa2, 0x1e, 0x98, 0xf7, 0x65, 0xc7, 0x69, 0xbe, 0x6f, 0x6c, 0x10, 0xa4, - 0x3e, 0x6f, 0x45, 0x26, 0x07, 0x24, 0x25, 0x36, 0xb0, 0xf0, 0xb8, 0x79, 0xba, 0xac, 0x4b, 0xbe, 0x77, 0x59, 0x9d, - 0xba, 0xa2, 0xb1, 0x85, 0x12, 0x67, 0x2c, 0x1a, 0x8c, 0x29, 0x11, 0x49, 0xe6, 0x42, 0xb0, 0x46, 0xc3, 0xdf, 0x7c, - 0x22, 0x68, 0x3e, 0xe1, 0xb1, 0xf7, 0x09, 0x77, 0x32, 0x99, 0xde, 0x50, 0x13, 0x65, 0x3b, 0x7a, 0xf7, 0xf3, 0x81, - 0xd2, 0x4e, 0x73, 0x3e, 0x96, 0x31, 0x73, 0xc9, 0x02, 0x94, 0x99, 0x08, 0x11, 0x90, 0x43, 0x8f, 0x3b, 0xc9, 0x22, - 0x41, 0xaf, 0xf1, 0x15, 0x26, 0x52, 0xd3, 0x91, 0xd9, 0xeb, 0x6a, 0x22, 0x1a, 0x8f, 0x1c, 0x29, 0xf0, 0x62, 0xbc, - 0xc9, 0xa8, 0x4b, 0xb1, 0x5a, 0xbc, 0x61, 0x92, 0x29, 0x7e, 0xf2, 0xd7, 0xf6, 0x27, 0x27, 0xe4, 0xbd, 0x9e, 0x5a, - 0xa1, 0xdf, 0xf3, 0xc6, 0xd6, 0xa5, 0xa0, 0xdd, 0xff, 0x6c, 0xc9, 0x28, 0xda, 0x98, 0x56, 0xcf, 0xe2, 0x4b, 0xfd, - 0xa2, 0x97, 0xc8, 0xe5, 0x4d, 0x1e, 0xdb, 0x87, 0x11, 0xa3, 0xd0, 0x5a, 0x85, 0xd9, 0x7b, 0x8f, 0x62, 0x63, 0xef, - 0xb5, 0x42, 0x34, 0xce, 0x21, 0xba, 0x84, 0xcb, 0x8d, 0x97, 0xc8, 0x24, 0x3e, 0x39, 0xe3, 0x2c, 0xf3, 0x6f, 0xa9, - 0x48, 0x58, 0xce, 0x32, 0x8f, 0xd1, 0xc3, 0xde, 0x54, 0x25, 0x9b, 0x02, 0x4e, 0x51, 0xd6, 0x8a, 0xb8, 0x99, 0xce, - 0x77, 0xad, 0x40, 0x6b, 0xe2, 0x67, 0x30, 0x8a, 0xc9, 0x6a, 0xf2, 0xe6, 0xd5, 0x7f, 0x73, 0xe2, 0x5f, 0x54, 0x33, - 0xfe, 0x50, 0xc6, 0xf8, 0x97, 0x8b, 0x75, 0x58, 0xf9, 0x7d, 0x73, 0x28, 0x09, 0x70, 0x8d, 0x93, 0x4a, 0x7c, 0xad, - 0x70, 0x8e, 0x00, 0xfa, 0xae, 0xbb, 0x24, 0xd4, 0x0b, 0x8e, 0x06, 0x1d, 0x16, 0x23, 0x58, 0x1c, 0x13, 0x7d, 0x74, - 0xff, 0x77, 0xc5, 0x00, 0x2d, 0x46, 0x23, 0xd7, 0x5f, 0xcf, 0xc5, 0xb1, 0x22, 0xc9, 0x26, 0x57, 0x58, 0x88, 0x11, - 0x02, 0x08, 0xb9, 0x48, 0x02, 0x1d, 0xe7, 0x07, 0x9f, 0x8a, 0x17, 0x8d, 0x48, 0x01, 0x68, 0x48, 0xfb, 0x6b, 0x80, - 0xc0, 0x21, 0x98, 0x23, 0x41, 0x30, 0x92, 0x67, 0x01, 0x91, 0x13, 0xb2, 0x77, 0xa2, 0x42, 0x84, 0x59, 0x1d, 0xec, - 0x7a, 0x83, 0xba, 0x80, 0x2d, 0x9a, 0xe7, 0x48, 0x50, 0x54, 0x21, 0x22, 0x2c, 0x2b, 0x36, 0x57, 0xaf, 0xd6, 0xbc, - 0x47, 0x85, 0x17, 0x85, 0x2e, 0x99, 0x3e, 0xcd, 0x2e, 0xa1, 0xcc, 0x2f, 0xc0, 0xbf, 0x16, 0x75, 0x60, 0xcf, 0xbb, - 0x0e, 0x1d, 0x5b, 0x71, 0x72, 0x2a, 0x2e, 0x7f, 0xce, 0x39, 0x00, 0x4a, 0x7a, 0xd6, 0x21, 0x86, 0x06, 0x9d, 0xeb, - 0x96, 0x6b, 0xd2, 0x00, 0x0c, 0x97, 0x8c, 0x57, 0x86, 0xda, 0xd6, 0xb3, 0xeb, 0x17, 0x7f, 0x46, 0x66, 0x8e, 0x0e, - 0x4d, 0xbc, 0x88, 0x12, 0x77, 0x59, 0x5c, 0x02, 0x15, 0xaf, 0xf3, 0x51, 0xad, 0x6b, 0xe5, 0x95, 0xed, 0x1a, 0x87, - 0x0b, 0x1a, 0x82, 0x2d, 0xbc, 0x6a, 0xc0, 0x75, 0xb8, 0xac, 0x8b, 0xc0, 0x8f, 0x9e, 0x16, 0x05, 0xca, 0xdb, 0xb5, - 0x20, 0x0d, 0x3d, 0xd9, 0x89, 0xca, 0xa7, 0x69, 0xe9, 0xef, 0xcd, 0x7a, 0xf9, 0x8e, 0x16, 0x53, 0x8e, 0x43, 0x85, - 0x3f, 0x03, 0xc2, 0xa6, 0xb8, 0x1b, 0x14, 0x0d, 0xe5, 0xc5, 0x0d, 0x84, 0x72, 0x3a, 0x3b, 0x7c, 0xdb, 0x69, 0x56, - 0x11, 0xc4, 0xbc, 0x1f, 0xfd, 0xa7, 0x5c, 0x56, 0x60, 0xe9, 0x74, 0xec, 0x71, 0x93, 0x39, 0x47, 0x79, 0xde, 0xf6, - 0x8d, 0xd4, 0xa9, 0x45, 0x48, 0x55, 0xbc, 0x5a, 0xf4, 0x55, 0xba, 0xf7, 0x69, 0x83, 0x99, 0xb7, 0x59, 0xb1, 0x07, - 0xd9, 0x8a, 0x8d, 0x68, 0x96, 0xbc, 0xee, 0x31, 0x25, 0xd5, 0x47, 0x4c, 0x1c, 0xa0, 0x5b, 0xde, 0x2f, 0x1e, 0xc3, - 0x54, 0xaf, 0x30, 0x62, 0xb5, 0xd9, 0x5f, 0x00, 0x73, 0x6f, 0xdc, 0xcf, 0x35, 0x7b, 0xe6, 0x53, 0x29, 0xa4, 0x58, - 0x85, 0xf0, 0xba, 0x2a, 0x33, 0x38, 0xf9, 0x14, 0x82, 0x21, 0x7f, 0xf9, 0x31, 0xf3, 0xeb, 0x55, 0xf7, 0x87, 0x19, - 0xcf, 0xea, 0x7b, 0x3a, 0x60, 0x6f, 0xa8, 0x0d, 0xaf, 0x7b, 0x0a, 0x71, 0x45, 0x98, 0xdd, 0xb3, 0x53, 0x60, 0xcd, - 0x64, 0x70, 0xdf, 0xb1, 0x29, 0xea, 0x09, 0xfc, 0x28, 0x9c, 0x37, 0x0b, 0xe6, 0x6f, 0x79, 0xc5, 0x68, 0xde, 0x4c, - 0x91, 0x74, 0xe1, 0xc1, 0x88, 0x4f, 0x19, 0x97, 0x28, 0x5b, 0xfa, 0x90, 0x7e, 0x87, 0x78, 0x23, 0xc7, 0x9b, 0xb5, - 0xf4, 0x8d, 0xe2, 0xb0, 0xd5, 0x64, 0x1b, 0x12, 0xa6, 0x00, 0x68, 0x91, 0xf3, 0x11, 0x30, 0x5d, 0xaf, 0xd9, 0x8a, - 0xb2, 0x0d, 0x61, 0x91, 0x86, 0x86, 0x50, 0x34, 0xac, 0x17, 0x4c, 0x4d, 0x8a, 0xbb, 0x43, 0x23, 0x26, 0xc6, 0x73, - 0xc6, 0xf2, 0x0b, 0xf2, 0xd3, 0xa2, 0x4c, 0x5b, 0x63, 0x2f, 0xae, 0xcc, 0x0a, 0x26, 0x1e, 0x34, 0x13, 0x20, 0x09, - 0xe0, 0xd5, 0x2a, 0xea, 0x8c, 0xf3, 0x54, 0x62, 0x73, 0x7f, 0xe3, 0x09, 0x19, 0x20, 0xd0, 0x29, 0x69, 0xa2, 0xa3, - 0xab, 0xf5, 0x41, 0x8a, 0xbd, 0x00, 0x94, 0x9d, 0xb0, 0xc1, 0x32, 0x86, 0x06, 0x58, 0xd7, 0x66, 0x73, 0x8a, 0x6b, - 0xd9, 0x53, 0x27, 0xb3, 0x36, 0xf2, 0x34, 0x7f, 0xb8, 0xb4, 0x30, 0x22, 0xc6, 0x45, 0xcd, 0x27, 0xe2, 0xab, 0x29, - 0x46, 0xa0, 0xf5, 0x04, 0xe4, 0xf5, 0x70, 0xca, 0xdb, 0x75, 0x8d, 0x71, 0xe9, 0x9a, 0x64, 0xf2, 0xa2, 0xc0, 0xa9, - 0x2f, 0x93, 0x7f, 0x19, 0x7f, 0x02, 0x9b, 0x78, 0x4e, 0x27, 0x3e, 0x4e, 0xb6, 0x3a, 0x51, 0x54, 0x40, 0x54, 0x8b, - 0xf0, 0x4a, 0x7a, 0x11, 0x92, 0x9a, 0xf1, 0x32, 0x10, 0xea, 0x78, 0xa3, 0x01, 0xc9, 0xfb, 0xba, 0x12, 0x5e, 0x5b, - 0xbe, 0x5c, 0x84, 0xbc, 0xd9, 0x0e, 0x6b, 0x77, 0x3e, 0x9d, 0x6e, 0x6f, 0x56, 0xc8, 0x0d, 0x50, 0x3a, 0x19, 0xae, - 0x82, 0xbe, 0xa1, 0xd9, 0x91, 0x3c, 0xa1, 0x23, 0x5f, 0x66, 0x65, 0x4c, 0xc2, 0xe2, 0x74, 0x43, 0x8e, 0x4a, 0x5e, - 0x29, 0xed, 0x2e, 0x64, 0x4f, 0x71, 0xaa, 0x3b, 0x58, 0x0f, 0x44, 0xe5, 0x10, 0x53, 0x6a, 0x14, 0x9e, 0xc4, 0xad, - 0x1c, 0x59, 0xfb, 0xb0, 0x4e, 0x2e, 0xbc, 0x8a, 0x33, 0x1d, 0xd2, 0xb6, 0xb5, 0xb9, 0xdb, 0x6c, 0x54, 0xa4, 0xcb, - 0x12, 0x69, 0xef, 0xed, 0xfa, 0x65, 0xd5, 0xa3, 0x49, 0x8a, 0xd2, 0xf7, 0x25, 0x8e, 0x2f, 0xeb, 0xa8, 0x7b, 0x3b, - 0x89, 0x25, 0x7c, 0x64, 0x99, 0x38, 0x05, 0x77, 0xc0, 0x58, 0x65, 0x27, 0xa2, 0x16, 0x48, 0xea, 0xbf, 0xf4, 0xb2, - 0x9e, 0x82, 0x14, 0xef, 0x96, 0xf5, 0x7a, 0x86, 0xc4, 0x7c, 0xc9, 0x18, 0xad, 0xc1, 0x00, 0x55, 0xd0, 0xf3, 0xd5, - 0x73, 0x40, 0xe0, 0x99, 0x4d, 0x2f, 0xbf, 0x13, 0x45, 0x9c, 0xdd, 0x65, 0x85, 0x26, 0x5a, 0x3c, 0xcb, 0x1e, 0x16, - 0xd8, 0x57, 0x0a, 0xf2, 0xec, 0xea, 0x25, 0x85, 0x96, 0x4d, 0x18, 0xf3, 0x1b, 0xa6, 0xbe, 0x02, 0xfb, 0xf2, 0x5a, - 0x99, 0x74, 0x56, 0x77, 0xb5, 0xc6, 0x02, 0xcf, 0x8b, 0x2a, 0x48, 0xa2, 0xde, 0x86, 0x99, 0x95, 0x89, 0x53, 0x3e, - 0xaa, 0x0a, 0x96, 0xb3, 0xf3, 0xdd, 0x94, 0xd0, 0xe8, 0xd1, 0x7f, 0xd5, 0x35, 0x09, 0xaa, 0xf4, 0xc8, 0x8c, 0x63, - 0x70, 0x11, 0x2d, 0xf4, 0xb3, 0x76, 0x5d, 0x54, 0x74, 0x7e, 0xcd, 0x62, 0x5a, 0x5f, 0x97, 0x92, 0x36, 0x3a, 0x2b, - 0xa4, 0xc4, 0xa2, 0x31, 0xcf, 0x2a, 0x64, 0xfb, 0xbd, 0xab, 0xad, 0xd5, 0x06, 0xc2, 0x4d, 0x26, 0x25, 0x48, 0x4a, - 0xc2, 0x3f, 0x94, 0x67, 0x5b, 0x46, 0x34, 0x2a, 0xad, 0x91, 0x2e, 0xaa, 0xd6, 0x9c, 0xb7, 0xa2, 0x30, 0x7f, 0xc2, - 0xe2, 0xbc, 0x46, 0xde, 0x08, 0x85, 0x00, 0xe1, 0x22, 0xfc, 0x39, 0x80, 0xfb, 0x3b, 0x96, 0x15, 0x0f, 0xab, 0xe9, - 0x29, 0xaf, 0xd4, 0x36, 0x8e, 0xc0, 0x01, 0x79, 0x8b, 0x93, 0xc1, 0x05, 0x92, 0x11, 0x26, 0x7e, 0x85, 0x68, 0x83, - 0xa5, 0x62, 0x52, 0x5a, 0x7c, 0xae, 0x6c, 0x42, 0xa7, 0x4f, 0xcb, 0x8a, 0xb9, 0xfa, 0x80, 0x3e, 0x5b, 0x55, 0x76, - 0xbe, 0x76, 0x0c, 0x43, 0x7e, 0x32, 0x5b, 0xe4, 0x49, 0xc9, 0xef, 0xc0, 0x98, 0x96, 0x37, 0x49, 0x6e, 0x53, 0x0d, - 0xfa, 0x58, 0x55, 0xf8, 0xea, 0x3d, 0xe7, 0x22, 0x3e, 0x98, 0xab, 0x11, 0xe9, 0x57, 0x83, 0xa9, 0x7f, 0xad, 0xdf, - 0xa7, 0x92, 0xe8, 0xd8, 0xe9, 0xba, 0xd0, 0xbc, 0x83, 0x4b, 0x2a, 0x2a, 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0x94, - 0x91, 0xda, 0xd7, 0x12, 0x59, 0x9b, 0x95, 0x3b, 0xd9, 0x7e, 0xb4, 0x9a, 0xcd, 0x30, 0xe5, 0xa5, 0xf5, 0xae, 0xac, - 0x2b, 0x3f, 0xe8, 0xca, 0x0e, 0xe9, 0x83, 0x7a, 0x22, 0x97, 0x4d, 0xe1, 0xe7, 0x5b, 0x9b, 0x03, 0x94, 0xfa, 0x5f, - 0x68, 0x5c, 0x86, 0xb3, 0x81, 0x4d, 0xe8, 0xea, 0x40, 0x7c, 0x50, 0xe6, 0x92, 0x6c, 0x5f, 0xf0, 0x84, 0xba, 0xee, - 0x82, 0x79, 0xd6, 0x15, 0x8b, 0xa2, 0xff, 0xf8, 0x9e, 0x85, 0xf7, 0xf4, 0xc9, 0xb0, 0xf2, 0x80, 0x7a, 0x79, 0xac, - 0xe5, 0xb2, 0x0e, 0x4c, 0x56, 0x12, 0x53, 0x4d, 0x58, 0xd5, 0x2d, 0xcd, 0x61, 0xeb, 0x8c, 0xe6, 0x34, 0xdd, 0x24, - 0xdf, 0x1f, 0x28, 0x9c, 0x44, 0x86, 0xbf, 0x5a, 0xdb, 0x81, 0x81, 0x06, 0x89, 0xea, 0x02, 0x54, 0x4a, 0xdc, 0x2f, - 0x54, 0x6b, 0x52, 0x95, 0x65, 0x07, 0x0a, 0x4b, 0xbe, 0x51, 0xd5, 0x2d, 0xbf, 0x5d, 0x94, 0xa8, 0x60, 0x94, 0xff, - 0xa9, 0x75, 0x59, 0x40, 0xb4, 0x1d, 0x5c, 0xeb, 0xb1, 0x57, 0x3e, 0xed, 0x62, 0x38, 0xde, 0x61, 0x57, 0xbf, 0xd3, - 0xea, 0x1c, 0xd5, 0x85, 0xa5, 0xc4, 0xb9, 0x57, 0xc8, 0x73, 0xb6, 0xb3, 0x9f, 0xf3, 0xf6, 0xa2, 0x83, 0x32, 0x7e, - 0xb9, 0x35, 0xcc, 0x6c, 0x16, 0xae, 0x8a, 0x80, 0x19, 0x7d, 0x75, 0x25, 0x00, 0xb0, 0x80, 0x29, 0x61, 0x61, 0xc4, - 0x8e, 0xa3, 0x3c, 0x73, 0x4c, 0x65, 0x9f, 0x7b, 0x46, 0xd7, 0x37, 0x27, 0xee, 0x91, 0xcb, 0x1d, 0xb4, 0x5a, 0x89, - 0xe3, 0x64, 0x61, 0x2d, 0x5f, 0x74, 0x05, 0xa6, 0x09, 0x49, 0x97, 0x5f, 0xcd, 0x81, 0x54, 0xad, 0xee, 0xc4, 0x3c, - 0x67, 0x13, 0x40, 0x6f, 0xdf, 0x35, 0x01, 0x8f, 0xc9, 0xf1, 0xcd, 0xe8, 0xde, 0x02, 0x33, 0xd2, 0xf5, 0x85, 0xd0, - 0x77, 0x2b, 0x99, 0xaf, 0x5b, 0xa3, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xe3, 0x12, 0xdb, 0xd0, 0xd2, 0x5d, 0x2f, - 0x82, 0x18, 0x08, 0x44, 0x72, 0x63, 0x14, 0x78, 0x7f, 0x76, 0xae, 0x7b, 0x31, 0x64, 0x29, 0x68, 0x46, 0x0f, 0x5e, - 0xb0, 0x5d, 0x26, 0x24, 0x13, 0xf9, 0x0e, 0x0d, 0x81, 0x95, 0xb9, 0x13, 0xfd, 0x08, 0xf0, 0xaa, 0xb8, 0xb5, 0xdf, - 0x27, 0xfa, 0xbd, 0xea, 0x43, 0x71, 0xe9, 0xb5, 0x82, 0xca, 0x6a, 0x24, 0xde, 0x0c, 0x3a, 0xe0, 0xd1, 0xe5, 0xa7, - 0x4a, 0x8c, 0x66, 0x10, 0x3c, 0x40, 0x14, 0x11, 0x65, 0xf6, 0x95, 0xdc, 0x16, 0x77, 0x87, 0x53, 0x40, 0x20, 0x63, - 0xd6, 0x65, 0x17, 0xc3, 0x44, 0x60, 0x89, 0xf9, 0x66, 0x7c, 0x31, 0x82, 0x1f, 0xdb, 0x7d, 0x54, 0xce, 0x45, 0xb9, - 0x06, 0x63, 0x1b, 0xf3, 0x99, 0x15, 0x7b, 0x82, 0x6f, 0x34, 0xd2, 0xd1, 0xcb, 0x18, 0xca, 0x25, 0xca, 0xc1, 0x4a, - 0xf7, 0x09, 0xf4, 0x60, 0x45, 0x15, 0x20, 0xce, 0x6e, 0x9c, 0x71, 0x6a, 0xc0, 0x2c, 0xb9, 0x21, 0x2d, 0x68, 0x72, - 0xea, 0xf0, 0x6b, 0x3a, 0x7a, 0x0e, 0x30, 0x29, 0xee, 0xc9, 0xcb, 0xe1, 0xd4, 0xb4, 0xd6, 0xd3, 0x5a, 0x7f, 0x03, - 0x0d, 0xb1, 0xa0, 0x2d, 0x6a, 0x67, 0x6f, 0xc0, 0xcc, 0x17, 0x6c, 0x1b, 0x6a, 0x8d, 0x3f, 0xec, 0x87, 0x16, 0x76, - 0x92, 0xe1, 0x34, 0x88, 0x24, 0xce, 0xc1, 0x34, 0x0a, 0xf1, 0x87, 0x56, 0x97, 0x15, 0xab, 0xf2, 0xc4, 0x6f, 0xdd, - 0x5f, 0x2b, 0xa5, 0xd1, 0xe7, 0x9f, 0xc5, 0xc2, 0x19, 0x99, 0xd8, 0xaf, 0xf6, 0xc2, 0xc2, 0xa2, 0xb2, 0x03, 0x57, - 0x35, 0x1a, 0x9e, 0x25, 0x2f, 0x85, 0xa7, 0x1c, 0x56, 0x68, 0x99, 0x09, 0x3f, 0x8f, 0xf3, 0x6a, 0xec, 0xcd, 0xa8, - 0x46, 0xb5, 0x62, 0x0a, 0xea, 0xf4, 0xe8, 0x40, 0xb8, 0x4c, 0x01, 0x56, 0xd9, 0x02, 0xd4, 0x9f, 0x5f, 0xe7, 0x1e, - 0x7d, 0x1a, 0x06, 0x2f, 0xca, 0x31, 0xd6, 0x20, 0xe8, 0x1d, 0x44, 0x21, 0x46, 0x47, 0xd2, 0x37, 0x29, 0xbd, 0xf9, - 0x23, 0x8f, 0xf1, 0x0d, 0xf1, 0x77, 0xc1, 0xce, 0xb7, 0xdc, 0xe7, 0xce, 0xe2, 0x35, 0x66, 0xcd, 0x75, 0xb4, 0x0e, - 0x43, 0xdd, 0x25, 0x30, 0x0d, 0x41, 0xc3, 0x44, 0x13, 0x04, 0x63, 0xc9, 0x73, 0xba, 0x36, 0x9a, 0xa0, 0xf4, 0x42, - 0x12, 0xfc, 0xbf, 0x4a, 0x78, 0x39, 0xa7, 0x72, 0x3a, 0x8a, 0x5a, 0xf0, 0x10, 0x5c, 0x55, 0x43, 0x2d, 0x50, 0x27, - 0x0f, 0x4f, 0xa1, 0x25, 0x63, 0x05, 0x9e, 0x63, 0x9f, 0x9b, 0x34, 0xc0, 0x78, 0x24, 0xf3, 0xb0, 0x61, 0xc2, 0x15, - 0x7a, 0xb6, 0x98, 0x33, 0x3b, 0xe6, 0x6d, 0x85, 0x91, 0xbd, 0x19, 0x97, 0x78, 0xf6, 0x3a, 0x16, 0xb3, 0xed, 0x71, - 0x68, 0x31, 0x37, 0x0f, 0x1c, 0xb5, 0x58, 0x9b, 0x08, 0x0a, 0x7d, 0x03, 0x5b, 0x80, 0xc1, 0x4e, 0xce, 0xaa, 0x51, - 0x42, 0xb2, 0xe6, 0x16, 0x40, 0x9e, 0xe9, 0x28, 0x84, 0x54, 0x36, 0xfc, 0xc4, 0x5a, 0xf2, 0x77, 0x60, 0xe7, 0xfc, - 0xcd, 0xc3, 0x40, 0x88, 0xda, 0x46, 0x68, 0x02, 0xfa, 0xea, 0xb5, 0x96, 0x10, 0x20, 0x0c, 0x82, 0x2b, 0xfa, 0xcb, - 0x9e, 0x84, 0x6e, 0x2e, 0xaf, 0xcb, 0x7b, 0x42, 0xd4, 0x75, 0xb0, 0x1e, 0x91, 0xf1, 0xdc, 0x15, 0xfe, 0xab, 0xde, - 0x0f, 0x12, 0x25, 0x14, 0x4b, 0x45, 0xf2, 0x23, 0xaa, 0x23, 0xc6, 0x11, 0xda, 0xd1, 0x49, 0x3e, 0x76, 0x85, 0x81, - 0x38, 0x54, 0x5b, 0x66, 0x7a, 0x7e, 0xc4, 0x56, 0x33, 0xf6, 0x28, 0xb8, 0x9e, 0x2c, 0x35, 0xbc, 0x40, 0x94, 0xae, - 0x7f, 0x04, 0x34, 0x93, 0xff, 0x98, 0xd9, 0xe6, 0xa9, 0xd9, 0x47, 0x45, 0xdf, 0x64, 0x76, 0x8e, 0x2c, 0x38, 0x8a, - 0xc2, 0x2b, 0x21, 0xf0, 0x52, 0x47, 0x3c, 0x35, 0x52, 0xc4, 0x3c, 0x64, 0x9a, 0x82, 0x5c, 0x0f, 0xe8, 0x0b, 0x4d, - 0x8e, 0xaa, 0x2e, 0xc7, 0xf4, 0x40, 0x81, 0x58, 0x1d, 0xdb, 0x11, 0xe2, 0xe2, 0x36, 0x11, 0xc3, 0x69, 0xd5, 0x65, - 0x0f, 0x49, 0xad, 0xf3, 0x74, 0xcc, 0x14, 0xe4, 0xc0, 0x4d, 0x58, 0xfd, 0xce, 0x71, 0x68, 0x17, 0x05, 0xb7, 0x6f, - 0xa9, 0x44, 0xb2, 0x51, 0xa6, 0xfb, 0x32, 0xfc, 0x20, 0x9a, 0x45, 0x03, 0xc8, 0x06, 0x7c, 0xa5, 0x3f, 0x8c, 0xa2, - 0xeb, 0x3b, 0xbf, 0xcc, 0x9a, 0x29, 0x5b, 0xbf, 0xdb, 0x30, 0xdb, 0x3a, 0x1e, 0x28, 0xb4, 0xa6, 0x85, 0x46, 0x9b, - 0xfa, 0xac, 0xf0, 0xad, 0x75, 0x02, 0x31, 0x39, 0xb9, 0xd9, 0xc8, 0x63, 0xb0, 0x8e, 0xb0, 0xee, 0x31, 0x36, 0x27, - 0xf1, 0x2f, 0xb5, 0x99, 0x0b, 0xc2, 0x33, 0x2b, 0x59, 0xf0, 0x0f, 0xba, 0x19, 0x6c, 0x39, 0x6f, 0xc2, 0xbf, 0xb1, - 0xa6, 0x09, 0x93, 0x35, 0x69, 0x05, 0xe5, 0x90, 0xd4, 0x6e, 0x68, 0xb4, 0x4e, 0x5e, 0xb6, 0x28, 0x10, 0x52, 0x13, - 0xcf, 0x45, 0x75, 0x27, 0xa3, 0xa5, 0x17, 0xe9, 0xc6, 0xde, 0x37, 0x3f, 0x87, 0xcf, 0xb4, 0xc2, 0x8b, 0x15, 0xc2, - 0x80, 0xfe, 0x64, 0x58, 0xdf, 0xab, 0xa4, 0xdd, 0x57, 0xed, 0x64, 0xd1, 0xda, 0x98, 0xaf, 0x02, 0x26, 0xd6, 0x3d, - 0xc5, 0xbc, 0x5c, 0x9d, 0xf4, 0xf7, 0xae, 0xc5, 0x16, 0xc6, 0x23, 0x99, 0x47, 0x72, 0x4a, 0xf8, 0x63, 0x40, 0xe3, - 0xdf, 0x50, 0x46, 0x0d, 0x0c, 0x34, 0x58, 0x3d, 0x1a, 0xca, 0x75, 0x00, 0x0e, 0x31, 0x34, 0x11, 0xc9, 0x40, 0x3b, - 0x81, 0x3b, 0x9a, 0x09, 0x52, 0x4f, 0x5b, 0x82, 0x4d, 0x3c, 0x47, 0x37, 0x31, 0x39, 0x19, 0xbb, 0x00, 0x57, 0xe0, - 0x96, 0xf5, 0x0c, 0xdb, 0x6e, 0xb3, 0x5d, 0x84, 0x94, 0x9a, 0x0a, 0xb6, 0xf0, 0x58, 0x6b, 0x02, 0x78, 0x4a, 0x35, - 0xd1, 0xa2, 0x21, 0xd5, 0x97, 0x4e, 0xc0, 0x7e, 0x71, 0xd2, 0x98, 0x5b, 0xd3, 0x58, 0x59, 0x3e, 0x0d, 0xbc, 0xd4, - 0x64, 0x4d, 0xac, 0xd0, 0x67, 0x9c, 0x72, 0x04, 0xe2, 0x1d, 0x7e, 0x73, 0x79, 0x33, 0x49, 0x6f, 0x0b, 0xfd, 0xd8, - 0x64, 0x80, 0x61, 0xe4, 0x1c, 0xe1, 0x17, 0x33, 0xec, 0x6c, 0xc3, 0xf9, 0xe7, 0x04, 0xc9, 0x78, 0x51, 0xf8, 0x57, - 0xe3, 0x05, 0xe9, 0xa8, 0x26, 0x21, 0xfe, 0x81, 0xe8, 0xd7, 0x0b, 0xce, 0xa0, 0x81, 0x36, 0xfb, 0x72, 0x59, 0xb3, - 0xb0, 0x2a, 0x68, 0xb4, 0xcf, 0xcd, 0x57, 0xb3, 0xe5, 0xdb, 0xeb, 0x7f, 0x94, 0xeb, 0x9e, 0x73, 0x1c, 0xb9, 0xd7, - 0x1c, 0x97, 0xbd, 0x2c, 0xf9, 0x41, 0x4b, 0xeb, 0x9d, 0x72, 0xda, 0xca, 0x45, 0x57, 0x50, 0xc2, 0x3f, 0xf6, 0x4f, - 0x8a, 0x64, 0xe7, 0x11, 0x2c, 0x89, 0x72, 0xb9, 0xe6, 0xe2, 0x8d, 0xd5, 0xbd, 0xbd, 0x13, 0x2c, 0x0c, 0x6e, 0xfc, - 0x82, 0x3c, 0x41, 0x92, 0xf2, 0x43, 0xf9, 0x5d, 0x0a, 0x71, 0xb6, 0x9d, 0xd5, 0x75, 0xb4, 0x8a, 0x78, 0xec, 0x5d, - 0x0e, 0x17, 0x76, 0x88, 0xd2, 0xe5, 0x83, 0x8b, 0xab, 0x59, 0x6b, 0x99, 0x2a, 0x93, 0x74, 0xc6, 0x33, 0x16, 0x70, - 0x9c, 0xc9, 0x32, 0x44, 0xd0, 0x33, 0x48, 0xc4, 0xe8, 0x7b, 0x17, 0x2c, 0x46, 0xc3, 0xd6, 0xea, 0xdb, 0x44, 0xd0, - 0x16, 0x14, 0xcd, 0x22, 0x7a, 0x31, 0x32, 0x15, 0x5e, 0x67, 0x13, 0x5a, 0xae, 0x64, 0x5e, 0x42, 0xab, 0x21, 0x6b, - 0x58, 0x94, 0xfb, 0x34, 0xf1, 0x83, 0x79, 0x3e, 0xb7, 0x50, 0x5b, 0x19, 0xab, 0x9f, 0x70, 0x66, 0xa9, 0x73, 0x41, - 0xb3, 0x5f, 0xd3, 0x5c, 0x81, 0xe7, 0xc9, 0xe6, 0xcb, 0x6f, 0xc4, 0xfa, 0x78, 0xca, 0xcf, 0xa0, 0xca, 0xdb, 0x84, - 0x25, 0xec, 0xcf, 0xa9, 0x52, 0x3c, 0xb2, 0xe1, 0x96, 0x55, 0x4b, 0x51, 0x1d, 0x8b, 0x24, 0x8a, 0x8c, 0x9d, 0x0c, - 0x67, 0xe8, 0x85, 0xc4, 0xb3, 0x59, 0x83, 0x09, 0x93, 0xf3, 0x2c, 0xde, 0x29, 0xcc, 0x95, 0x48, 0x12, 0x8b, 0x34, - 0x42, 0x91, 0xf6, 0x2d, 0xb9, 0x4c, 0xf2, 0x53, 0x93, 0xdb, 0x91, 0x50, 0xe5, 0x15, 0xfe, 0x1a, 0x70, 0x49, 0x88, - 0x54, 0xa0, 0x12, 0x9f, 0xfb, 0x8e, 0x58, 0xa2, 0x49, 0x15, 0xa5, 0x28, 0xa8, 0x97, 0xe9, 0x5f, 0x31, 0x2f, 0x4d, - 0x69, 0xec, 0x8e, 0xc0, 0xdd, 0x77, 0x19, 0x2b, 0x89, 0x3b, 0x8e, 0x99, 0x4c, 0x6b, 0x01, 0xd8, 0xa3, 0xcb, 0x4d, - 0xde, 0xe5, 0x80, 0xcb, 0xe3, 0xe3, 0x16, 0x40, 0xb0, 0x87, 0x05, 0xfc, 0xb5, 0x9d, 0x4b, 0x1d, 0x67, 0x24, 0x22, - 0x16, 0x9c, 0x21, 0x8b, 0x27, 0x6f, 0x00, 0x48, 0xce, 0xef, 0xe2, 0xe7, 0x05, 0x6d, 0x07, 0x40, 0x15, 0x8e, 0x0a, - 0x40, 0xec, 0x90, 0x60, 0xd0, 0x85, 0x77, 0xb2, 0xaf, 0x5a, 0xb3, 0xe3, 0xed, 0x05, 0x75, 0x1b, 0xcd, 0x3c, 0xd2, - 0x93, 0x92, 0x08, 0xe2, 0x0c, 0xb3, 0x1f, 0x04, 0x25, 0xaa, 0x57, 0xf5, 0x84, 0x30, 0x3a, 0x5b, 0x92, 0xc5, 0x4d, - 0x83, 0x80, 0xb4, 0x8f, 0x10, 0x33, 0xd9, 0x2e, 0xe5, 0x98, 0x7c, 0xed, 0x19, 0xe7, 0xac, 0x39, 0x43, 0x28, 0x1a, - 0xd8, 0xad, 0x25, 0x10, 0xeb, 0x1c, 0xca, 0x68, 0x28, 0x4d, 0xf9, 0x85, 0x1c, 0x41, 0xad, 0x63, 0xaf, 0x4c, 0x86, - 0x76, 0x1b, 0xdc, 0xfd, 0x80, 0x14, 0x29, 0xdc, 0xa3, 0x81, 0x65, 0x93, 0xd5, 0xe2, 0x92, 0x59, 0xbc, 0xe5, 0x91, - 0x62, 0x25, 0xb3, 0x1f, 0x04, 0xc3, 0x0b, 0xac, 0xe1, 0x62, 0x91, 0x8e, 0x12, 0xb2, 0x0a, 0x2e, 0x8b, 0xf5, 0xfe, - 0xec, 0xd6, 0x5d, 0x37, 0x05, 0xb9, 0xcd, 0xc9, 0x98, 0x29, 0xc7, 0xe3, 0x0a, 0xd2, 0x86, 0x5c, 0x1e, 0x07, 0x69, - 0xa4, 0xa9, 0x50, 0x3a, 0xb3, 0x7e, 0xba, 0x3f, 0xd5, 0xe3, 0xc5, 0x5c, 0x9d, 0x2c, 0x20, 0xa0, 0x8d, 0x3b, 0x70, - 0xca, 0x2a, 0x2c, 0x09, 0x87, 0x24, 0x6c, 0x78, 0x00, 0xa6, 0x5a, 0x3f, 0x8a, 0x4a, 0xfc, 0xbb, 0x64, 0x13, 0x41, - 0xa5, 0xe7, 0x06, 0xe7, 0x67, 0x69, 0x3c, 0x19, 0x85, 0x9f, 0xc4, 0x14, 0xce, 0x38, 0xcc, 0x11, 0xa2, 0xb2, 0x44, - 0xbf, 0x41, 0x89, 0xe7, 0x7e, 0x5a, 0xf2, 0x7f, 0xb6, 0x71, 0xfe, 0xa0, 0x8c, 0xe6, 0xd9, 0xb2, 0xe9, 0xb3, 0x05, - 0xc3, 0xde, 0x96, 0xb4, 0xb5, 0xee, 0x2c, 0x8a, 0xff, 0x8d, 0xea, 0xf0, 0xe9, 0x0e, 0x93, 0x58, 0x0f, 0x5c, 0x49, - 0xf0, 0xa9, 0x39, 0xe1, 0xd3, 0x9d, 0x3a, 0xe1, 0x87, 0x84, 0x88, 0x77, 0x8c, 0x8c, 0xb6, 0xc6, 0xd4, 0x6c, 0x05, - 0x8b, 0x4b, 0x2f, 0x2a, 0x82, 0x9d, 0x64, 0xd8, 0x94, 0x77, 0xbf, 0xe3, 0x95, 0x66, 0x07, 0x09, 0xe1, 0x45, 0xaa, - 0xed, 0x5c, 0xa3, 0xc5, 0x9c, 0x16, 0x50, 0x4a, 0x2a, 0x25, 0xd1, 0x6c, 0x1a, 0xc7, 0x6a, 0x81, 0x9f, 0x17, 0x24, - 0xb9, 0x55, 0xac, 0xfb, 0xb5, 0x33, 0x9c, 0xa8, 0x92, 0x9a, 0x92, 0x9a, 0xba, 0xb4, 0xa4, 0xc7, 0x60, 0xfe, 0xb7, - 0xc6, 0x44, 0xca, 0x35, 0x2e, 0x3c, 0xf0, 0x84, 0x32, 0x7e, 0x3d, 0x54, 0x3b, 0x59, 0x85, 0x33, 0xaf, 0xef, 0x2f, - 0xc3, 0xa1, 0xce, 0x85, 0x33, 0x0e, 0xdd, 0x70, 0x39, 0xb6, 0xdd, 0x6f, 0xed, 0xfc, 0x05, 0xfc, 0x45, 0x50, 0x2c, - 0x49, 0xa4, 0x66, 0xee, 0xfc, 0xa0, 0xec, 0xd4, 0x61, 0xee, 0x50, 0xa3, 0x95, 0xf1, 0xd4, 0x38, 0xd7, 0xd7, 0x58, - 0xa6, 0x37, 0x6a, 0x52, 0x45, 0x58, 0xd3, 0x40, 0x0d, 0x0f, 0xe9, 0x3c, 0x0b, 0x7a, 0x6a, 0x65, 0xfb, 0x74, 0xd0, - 0x07, 0x09, 0xcf, 0xa9, 0x80, 0x38, 0x13, 0x45, 0x2e, 0xbe, 0xf6, 0xfe, 0x32, 0xef, 0x57, 0x70, 0xb0, 0x41, 0xc9, - 0x5c, 0x3c, 0xb3, 0x38, 0x47, 0xcf, 0x0c, 0xe7, 0xf4, 0x99, 0xb5, 0xb3, 0x1d, 0xf6, 0x73, 0x29, 0x76, 0x25, 0xb0, - 0x28, 0x49, 0xca, 0x74, 0x5c, 0xb9, 0x3a, 0x9c, 0x3b, 0x0b, 0xe7, 0x91, 0xa9, 0x3a, 0xc5, 0x60, 0x52, 0xa6, 0xb4, - 0x7a, 0x62, 0x5b, 0x62, 0x6c, 0x99, 0x40, 0xb0, 0x4b, 0xbf, 0xae, 0xdc, 0xf6, 0x8b, 0xbb, 0x24, 0x85, 0xda, 0xd2, - 0xda, 0xf4, 0x24, 0x0a, 0x59, 0xf3, 0x4b, 0x1b, 0x4f, 0x89, 0xbd, 0xf3, 0x63, 0x15, 0x1d, 0xa4, 0x4b, 0x71, 0xac, - 0xdd, 0x89, 0x80, 0xcb, 0xb5, 0xa1, 0xfc, 0xb4, 0x35, 0x10, 0xd9, 0xf3, 0x16, 0xc9, 0xca, 0x1f, 0xca, 0xb0, 0x3c, - 0x21, 0x84, 0x89, 0xc0, 0xca, 0x58, 0x28, 0xad, 0x24, 0xb0, 0x0a, 0x7c, 0x94, 0xaa, 0xc5, 0xec, 0xb4, 0xf8, 0x3e, - 0x84, 0x6c, 0x8e, 0x9b, 0xd0, 0x9d, 0x00, 0xf2, 0x7a, 0x06, 0xd3, 0x55, 0x88, 0x02, 0xcd, 0x0c, 0x20, 0xe1, 0x87, - 0xec, 0xf6, 0x05, 0xcc, 0x1f, 0xd3, 0xb5, 0x5b, 0xb5, 0x72, 0x17, 0xed, 0x74, 0x2e, 0x89, 0x55, 0x9a, 0x6a, 0x52, - 0x5c, 0x94, 0x64, 0x21, 0xb1, 0x68, 0xe0, 0x95, 0x2b, 0x56, 0x9d, 0xfb, 0xc0, 0x6f, 0xd8, 0x36, 0x9e, 0xaf, 0xfa, - 0x31, 0xae, 0x40, 0xd5, 0xa8, 0x86, 0x1d, 0x7e, 0x00, 0xa6, 0xa6, 0x17, 0x09, 0x62, 0xb1, 0x59, 0xec, 0xce, 0x40, - 0x47, 0xf6, 0x51, 0xf1, 0xa4, 0x4c, 0x25, 0x0b, 0x54, 0x72, 0x8d, 0x14, 0x56, 0x5b, 0xb3, 0xa8, 0x4d, 0xc4, 0x7b, - 0xee, 0xd0, 0xba, 0x8a, 0xcb, 0x4c, 0x11, 0x7b, 0xa8, 0xe8, 0x33, 0x7a, 0xee, 0xc3, 0x2d, 0xbe, 0x87, 0x14, 0xc1, - 0x96, 0x8a, 0x91, 0x29, 0x09, 0xed, 0xc9, 0x0a, 0xa5, 0xc9, 0x12, 0x3c, 0x34, 0x50, 0x85, 0x0d, 0xf9, 0x0c, 0x07, - 0x6c, 0x3f, 0xa6, 0xf0, 0x64, 0x81, 0x12, 0x73, 0xa8, 0x76, 0x73, 0xf0, 0x5d, 0xed, 0x80, 0x77, 0x64, 0xcc, 0xcb, - 0xe4, 0x26, 0x17, 0xde, 0x91, 0xae, 0xbf, 0x1f, 0x07, 0x3b, 0x44, 0x18, 0xea, 0xa6, 0x80, 0xf4, 0xbc, 0x97, 0x0b, - 0x45, 0x89, 0x6f, 0xad, 0x18, 0xa8, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd4, 0x03, 0x3f, 0x21, 0xc8, 0x01, - 0x95, 0xd1, 0xa7, 0x2b, 0xda, 0xe2, 0xfa, 0xf3, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, 0x1d, 0x30, 0x8d, 0xfa, 0x68, - 0x68, 0xf7, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x17, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, 0xec, 0xd8, 0x3c, 0xba, 0xe1, - 0xdb, 0xf5, 0xc9, 0x80, 0xa1, 0x65, 0xd6, 0xdb, 0xa7, 0xab, 0x8f, 0xc6, 0xe7, 0x9a, 0x1a, 0x15, 0xc7, 0x45, 0x32, - 0x64, 0xaa, 0xa8, 0xf3, 0xc9, 0x26, 0x2a, 0x62, 0x6d, 0x2e, 0xfb, 0xce, 0x87, 0x31, 0xe8, 0xb1, 0x45, 0x95, 0x11, - 0xd7, 0x8e, 0xd9, 0xaf, 0x2f, 0xd6, 0xe5, 0x78, 0x9c, 0xd3, 0x07, 0x12, 0xa6, 0xed, 0x24, 0x42, 0xdd, 0x89, 0xf2, - 0x4d, 0x53, 0x9a, 0x05, 0x61, 0x3f, 0x58, 0xa4, 0x63, 0x0d, 0x9b, 0x6f, 0xc6, 0x6c, 0x6e, 0xa0, 0xba, 0xf2, 0x03, - 0xd4, 0x81, 0xb8, 0x18, 0x70, 0xf1, 0x0e, 0x8c, 0x39, 0xf3, 0xef, 0xb8, 0xbf, 0x2a, 0xa5, 0x34, 0xea, 0xf8, 0xb2, - 0xd4, 0xc8, 0xf6, 0x7e, 0xd9, 0x7f, 0x65, 0xf6, 0x21, 0xdf, 0x15, 0xa8, 0x50, 0x85, 0x34, 0x34, 0x89, 0x7a, 0xed, - 0x00, 0xb1, 0x9d, 0x8d, 0x26, 0x6a, 0xc5, 0x22, 0x52, 0x1e, 0x01, 0x0e, 0xe5, 0xf0, 0x5e, 0xb7, 0x0d, 0x23, 0xbe, - 0xbd, 0x4a, 0x3d, 0xd3, 0x96, 0x68, 0x1d, 0x0c, 0xf1, 0x2e, 0x5a, 0x4d, 0xe2, 0xcc, 0x0c, 0xe9, 0xd8, 0x99, 0xba, - 0x5f, 0xa2, 0xe8, 0x5d, 0x16, 0xd8, 0x6a, 0xae, 0xb6, 0x7e, 0x67, 0x45, 0x1f, 0xc2, 0x6a, 0xd9, 0xea, 0x7b, 0x31, - 0xd3, 0xd8, 0x4c, 0x9c, 0x20, 0x16, 0x40, 0xb3, 0x77, 0xee, 0x12, 0xc5, 0x98, 0xd9, 0x70, 0x59, 0xcc, 0x12, 0x29, - 0xc2, 0x0e, 0xe8, 0x24, 0x1a, 0x30, 0x31, 0xa7, 0x38, 0x36, 0x62, 0xdf, 0x27, 0xad, 0x6c, 0xe2, 0x4a, 0x28, 0x83, - 0x32, 0x69, 0xdd, 0x4e, 0xbf, 0x4c, 0x7c, 0xef, 0x5b, 0x40, 0xd3, 0x29, 0x73, 0x02, 0x7b, 0xce, 0x11, 0xe2, 0x0b, - 0x10, 0xe4, 0x56, 0x25, 0xef, 0x01, 0x96, 0xea, 0x9c, 0xa5, 0xeb, 0x53, 0x6f, 0x6c, 0x4b, 0xea, 0x89, 0xc3, 0xcc, - 0xf1, 0x3c, 0x2a, 0xbd, 0x02, 0xed, 0xe7, 0xbd, 0xef, 0xad, 0x6a, 0x9b, 0xf8, 0xeb, 0xf5, 0x01, 0x25, 0x46, 0xb3, - 0xb1, 0xa5, 0x9e, 0x6a, 0x69, 0xbe, 0xa9, 0x83, 0x9b, 0x10, 0xa2, 0x73, 0x5b, 0xb1, 0x66, 0xcd, 0xda, 0x91, 0x65, - 0xf4, 0xaf, 0x60, 0x85, 0x6f, 0x60, 0x2d, 0x2e, 0x01, 0xcd, 0xdf, 0x18, 0xdf, 0x08, 0x79, 0x5c, 0x7e, 0xa0, 0xf3, - 0x33, 0x46, 0x5d, 0x85, 0xa9, 0x22, 0xe1, 0xe1, 0xa5, 0xd6, 0x6b, 0x2d, 0xe8, 0x98, 0x96, 0x8f, 0x35, 0xf8, 0x42, - 0x4d, 0xab, 0x1d, 0xbc, 0xe5, 0x57, 0x6a, 0xea, 0x42, 0xe7, 0xe7, 0xa9, 0x03, 0x29, 0x5e, 0x7e, 0x45, 0x62, 0x8e, - 0xe5, 0xb7, 0x19, 0xfa, 0xe8, 0x7b, 0xf8, 0x75, 0xc3, 0x0f, 0x3a, 0x2f, 0x50, 0x49, 0x35, 0xce, 0x30, 0x0e, 0xe7, - 0xa7, 0x59, 0x35, 0x62, 0xa6, 0x08, 0x3f, 0x38, 0x75, 0x60, 0xf5, 0xba, 0x96, 0x87, 0x2e, 0x45, 0xa8, 0x02, 0x62, - 0x4f, 0xe3, 0xe7, 0x43, 0x98, 0x2a, 0xa6, 0x22, 0x81, 0x30, 0xa9, 0xd0, 0x9e, 0x92, 0x82, 0xdd, 0x62, 0xd5, 0xae, - 0x7a, 0xb7, 0x62, 0x5e, 0x93, 0x89, 0x80, 0x31, 0xde, 0x81, 0xe6, 0xcd, 0x6c, 0x5b, 0x87, 0xce, 0x89, 0x1d, 0x15, - 0xd8, 0x03, 0x32, 0xf6, 0x0e, 0x77, 0xbf, 0x99, 0x01, 0x27, 0x5c, 0xc3, 0xf4, 0x3c, 0x34, 0x1b, 0xdd, 0x70, 0xe5, - 0x5b, 0xfa, 0x74, 0xe6, 0xc4, 0xd9, 0x02, 0xcd, 0xd7, 0xc8, 0x56, 0xa2, 0xab, 0x9e, 0xa0, 0xee, 0x81, 0x64, 0x6f, - 0xdf, 0x5c, 0xf7, 0x76, 0x77, 0x05, 0x49, 0xa7, 0xbb, 0x19, 0xb0, 0x3b, 0x5c, 0xf0, 0x6e, 0xf5, 0x4c, 0x22, 0x09, - 0x00, 0x90, 0x3d, 0xe9, 0x3e, 0x0a, 0x5b, 0xe8, 0x4e, 0xb7, 0xbf, 0x76, 0x53, 0x59, 0xd0, 0x26, 0x5d, 0x79, 0x0c, - 0x6d, 0x13, 0x46, 0xc4, 0x90, 0x5d, 0x97, 0x91, 0x75, 0x4b, 0x5f, 0x08, 0x17, 0xf0, 0x88, 0x03, 0xb6, 0xc3, 0x76, - 0x41, 0x30, 0x12, 0x90, 0x90, 0x73, 0x21, 0xfe, 0x36, 0x0d, 0x35, 0x2b, 0xb8, 0xdb, 0x6c, 0x88, 0xdd, 0x24, 0xa1, - 0x3f, 0xe8, 0x0a, 0x6f, 0x6e, 0xbd, 0x1c, 0x2b, 0x28, 0xf3, 0xd1, 0x73, 0xb5, 0x9f, 0x35, 0x53, 0x7b, 0x3a, 0x69, - 0x69, 0xc6, 0xbc, 0x54, 0x6a, 0x9e, 0xc8, 0xbb, 0xb9, 0x81, 0x67, 0xe3, 0x99, 0x39, 0xc4, 0x89, 0x2d, 0x4d, 0xeb, - 0x66, 0xcc, 0xd1, 0xee, 0x6c, 0x3e, 0xf6, 0xec, 0xab, 0x9f, 0xcb, 0xbc, 0x54, 0x9f, 0xcd, 0xcd, 0xd2, 0xac, 0x9c, - 0x3f, 0x43, 0x54, 0xd8, 0x56, 0x16, 0x53, 0x4d, 0xe2, 0x18, 0x04, 0x46, 0x8b, 0x6e, 0x6f, 0xa1, 0x19, 0x76, 0x31, - 0x3b, 0xce, 0xa5, 0x59, 0x77, 0x7b, 0x85, 0xe3, 0x97, 0x99, 0xaf, 0x55, 0xed, 0x8d, 0x1b, 0x25, 0x0a, 0x4e, 0x87, - 0x83, 0xf3, 0xb0, 0xfd, 0x4b, 0x91, 0x37, 0x33, 0x8c, 0x25, 0x81, 0x68, 0x2d, 0x5a, 0xb8, 0xca, 0x68, 0xb5, 0x59, - 0x15, 0x21, 0x39, 0xb5, 0x33, 0xff, 0x85, 0x06, 0x90, 0x5a, 0xf0, 0x0a, 0x75, 0x73, 0x81, 0x05, 0xc7, 0xa8, 0xd4, - 0xa1, 0xf1, 0x29, 0xa7, 0x24, 0x43, 0x2a, 0x3a, 0xec, 0x72, 0xa2, 0x75, 0x4e, 0xb6, 0x1c, 0x01, 0x08, 0x94, 0x6a, - 0xc3, 0x06, 0x53, 0x1f, 0x26, 0x99, 0x5b, 0x99, 0x8e, 0x30, 0x53, 0x05, 0xc6, 0xdf, 0xac, 0x16, 0x7b, 0x97, 0x73, - 0x91, 0x24, 0xcc, 0xed, 0x0c, 0x3d, 0x59, 0x80, 0x0e, 0x63, 0x70, 0x7c, 0x3b, 0xf9, 0xa9, 0xfe, 0xb4, 0xba, 0x22, - 0xe3, 0xd4, 0x31, 0x39, 0x7b, 0x6d, 0x07, 0x05, 0x8d, 0xda, 0xee, 0x65, 0x78, 0xcd, 0xb3, 0x02, 0xed, 0xf3, 0xbf, - 0xda, 0xbd, 0xdd, 0xbc, 0xf0, 0xe5, 0xb7, 0x90, 0x15, 0x48, 0x3d, 0xc1, 0x6b, 0x53, 0x19, 0x95, 0x6a, 0xe7, 0x12, - 0x6d, 0xbf, 0x3c, 0x21, 0xc9, 0xb6, 0xf1, 0x6f, 0x91, 0x4b, 0x29, 0x90, 0xfc, 0x7d, 0x6d, 0x24, 0xb2, 0xc5, 0x2c, - 0x49, 0x98, 0xea, 0x35, 0x49, 0x75, 0x1e, 0xd6, 0xb1, 0x9b, 0x8e, 0xff, 0x2c, 0x43, 0xf4, 0x34, 0x12, 0x52, 0xeb, - 0x6d, 0x4d, 0xe6, 0x61, 0x1d, 0xdd, 0xc9, 0x16, 0xcf, 0x79, 0xc4, 0x53, 0x41, 0xc6, 0x6c, 0xb3, 0xee, 0x52, 0x89, - 0x44, 0x2d, 0x58, 0x06, 0xda, 0xed, 0x66, 0x38, 0x45, 0xad, 0x03, 0x14, 0x3b, 0x15, 0x7d, 0x19, 0xba, 0xd2, 0xd4, - 0x67, 0xb2, 0xa1, 0xb0, 0x52, 0x8b, 0xba, 0xbd, 0x94, 0x7a, 0xce, 0x86, 0xae, 0xbc, 0x3c, 0x99, 0x6b, 0xbe, 0x03, - 0xd8, 0x46, 0x1b, 0x4b, 0x37, 0x80, 0x6e, 0x34, 0x03, 0x37, 0x21, 0x03, 0x50, 0xd6, 0x14, 0x2a, 0x37, 0x35, 0xb8, - 0xa4, 0x9e, 0x95, 0x62, 0x0e, 0x48, 0x04, 0x67, 0xec, 0xdb, 0x00, 0x63, 0x7f, 0x8d, 0x9c, 0xc3, 0x55, 0xeb, 0xaa, - 0xad, 0x60, 0x6d, 0x9d, 0x3e, 0x6d, 0x1c, 0xc6, 0x2b, 0xfb, 0x27, 0xe0, 0xbb, 0x78, 0x51, 0x3b, 0x32, 0xfd, 0x2d, - 0x8e, 0x35, 0x84, 0x42, 0xd7, 0x27, 0x86, 0xc2, 0x8c, 0xc1, 0x30, 0xbb, 0xbb, 0x20, 0x4c, 0xaf, 0x2f, 0x05, 0x0c, - 0x0b, 0x37, 0x97, 0x62, 0xc7, 0xf1, 0xf3, 0x07, 0xfb, 0x89, 0x22, 0x1c, 0x9a, 0xa9, 0x10, 0x3e, 0x97, 0xae, 0x8c, - 0x82, 0x9c, 0x99, 0xcc, 0x09, 0x3c, 0xd8, 0x3e, 0x07, 0xd4, 0x28, 0x12, 0x8a, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x4d, - 0xc2, 0x05, 0xe9, 0xcb, 0x71, 0x7d, 0x34, 0xbd, 0x86, 0x29, 0x59, 0x99, 0xb7, 0x48, 0xfc, 0x6c, 0x99, 0xf5, 0x11, - 0xe1, 0x74, 0xaf, 0x6d, 0x60, 0x8b, 0xb5, 0x6d, 0xef, 0xd7, 0x3d, 0xe0, 0xca, 0xc2, 0x81, 0xa1, 0x8d, 0x4c, 0x7d, - 0xb5, 0xa1, 0x97, 0x14, 0x71, 0xfe, 0x15, 0x3d, 0x32, 0x7e, 0x30, 0xf6, 0x7d, 0x07, 0x77, 0x0a, 0xa4, 0xb7, 0x39, - 0xbf, 0x61, 0xa6, 0xf7, 0x60, 0x75, 0x03, 0x35, 0xac, 0xc1, 0xa5, 0x32, 0x4b, 0x8d, 0xf9, 0x17, 0xb7, 0xc4, 0x27, - 0x0b, 0x8e, 0x12, 0x9f, 0x42, 0xe2, 0x1a, 0xae, 0x4f, 0x1f, 0x1f, 0x99, 0xf4, 0x6d, 0x12, 0x8a, 0xec, 0x56, 0x2c, - 0xdb, 0x43, 0xc5, 0x98, 0x1c, 0xee, 0x8a, 0xab, 0x36, 0x38, 0x60, 0x88, 0xd2, 0xd1, 0x10, 0x49, 0x83, 0x26, 0x0e, - 0x24, 0x8c, 0xf7, 0xc5, 0x0c, 0xcb, 0x0d, 0x5d, 0xbc, 0x22, 0x7a, 0x6b, 0xcd, 0xce, 0xa4, 0xec, 0x65, 0x45, 0xbe, - 0x29, 0xd5, 0xe4, 0x63, 0xba, 0x5a, 0x4f, 0x4b, 0xaf, 0x2d, 0xf7, 0x58, 0x00, 0x74, 0xaf, 0x8e, 0x7f, 0xbd, 0xef, - 0x75, 0xd5, 0x67, 0x22, 0xdf, 0xfa, 0x7a, 0x18, 0xbe, 0xdd, 0x7f, 0xa9, 0xa3, 0x38, 0xb8, 0x45, 0xec, 0xdf, 0xfe, - 0x48, 0x59, 0xd4, 0xd6, 0xaa, 0x1f, 0xd4, 0xc1, 0xa1, 0xa7, 0x1e, 0x37, 0x67, 0x61, 0x4d, 0x30, 0xe1, 0x54, 0x81, - 0x73, 0xa6, 0x83, 0xd0, 0xc6, 0xf2, 0x6f, 0x1c, 0xd5, 0xa6, 0x6e, 0xdc, 0xa0, 0x3c, 0xe3, 0xd9, 0x58, 0x19, 0xea, - 0xb2, 0x95, 0x9d, 0xf9, 0xb2, 0xf3, 0x8c, 0x9c, 0xf7, 0xac, 0xa6, 0x5f, 0x1a, 0x0b, 0x7c, 0xa5, 0xe2, 0x08, 0xe1, - 0x67, 0xc0, 0xbb, 0xc4, 0xb1, 0x63, 0x66, 0x7c, 0x0c, 0x4a, 0xbb, 0x5b, 0xd2, 0xe8, 0x30, 0xb2, 0x1d, 0x74, 0x9d, - 0xcb, 0x64, 0x44, 0x50, 0x10, 0x22, 0xe4, 0x30, 0xb4, 0x43, 0x28, 0x67, 0xfb, 0xb1, 0xaa, 0xdc, 0x5e, 0xf4, 0x06, - 0xf3, 0x4a, 0xb6, 0x50, 0x04, 0x4c, 0x09, 0xbe, 0x5f, 0xd5, 0xd4, 0x88, 0x7d, 0xd3, 0xbf, 0x3d, 0x7c, 0x9a, 0x8b, - 0x9a, 0xa0, 0x01, 0xff, 0x3b, 0x96, 0xd5, 0xa0, 0x37, 0x56, 0x5f, 0x68, 0xd9, 0xb7, 0x86, 0x1c, 0x18, 0x55, 0x92, - 0xb6, 0x6e, 0x2f, 0x64, 0x95, 0x39, 0x57, 0xbb, 0x42, 0xf5, 0xa5, 0x47, 0x39, 0x99, 0xa6, 0x00, 0x30, 0x5d, 0x69, - 0x01, 0x71, 0x41, 0x21, 0xb4, 0xe0, 0xb0, 0x9a, 0x85, 0x4c, 0x5f, 0xcf, 0x4e, 0x61, 0xc1, 0x68, 0xbc, 0x30, 0xad, - 0x0d, 0x89, 0x32, 0x33, 0xa7, 0x4c, 0x4a, 0x77, 0xa9, 0xdd, 0x82, 0x3c, 0xf8, 0x2d, 0x2d, 0x1b, 0x80, 0x11, 0x13, - 0xc9, 0x77, 0x61, 0x13, 0x59, 0xfb, 0x7c, 0xce, 0xb8, 0xcd, 0xec, 0x49, 0xdf, 0xd4, 0xf4, 0x64, 0xe3, 0x34, 0x58, - 0x7f, 0x84, 0x9c, 0xe7, 0x6e, 0xa4, 0x6c, 0x6d, 0xe2, 0x96, 0xfb, 0x12, 0x1d, 0x43, 0x9f, 0x68, 0x97, 0x13, 0x76, - 0x40, 0x07, 0xfa, 0x4c, 0x5a, 0xc3, 0x35, 0x10, 0xe5, 0x30, 0x88, 0xa7, 0x72, 0x28, 0xae, 0x97, 0x3d, 0x46, 0x9d, - 0xc6, 0x02, 0x35, 0xb0, 0xc2, 0x17, 0x18, 0x46, 0x55, 0x05, 0x7b, 0xe0, 0x6f, 0x82, 0x9c, 0xae, 0xbe, 0x53, 0x2c, - 0x79, 0xd3, 0x12, 0xd1, 0x2e, 0x98, 0xb0, 0x0e, 0x2a, 0x1e, 0x63, 0xab, 0x49, 0x4a, 0x83, 0xa1, 0xeb, 0xc9, 0x77, - 0x41, 0xc6, 0x66, 0x32, 0xd2, 0xb4, 0x80, 0x3b, 0xcc, 0xed, 0x3c, 0x29, 0xcc, 0x21, 0x96, 0x8d, 0xab, 0xb8, 0x71, - 0xed, 0x6b, 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcd, 0x8b, 0xf6, 0x11, 0xaf, 0x63, 0x89, 0x65, 0xad, 0x9c, - 0xee, 0x30, 0xc2, 0x80, 0x88, 0xfb, 0x48, 0x17, 0xcc, 0x2c, 0xb5, 0xb5, 0xb8, 0x2a, 0x62, 0x59, 0xb6, 0x6b, 0x2c, - 0x06, 0x60, 0x14, 0xd8, 0x1f, 0xce, 0x6b, 0x19, 0x34, 0x7a, 0x3e, 0x7c, 0xba, 0x22, 0xa7, 0x65, 0x6d, 0x86, 0x0d, - 0xcf, 0xa6, 0x03, 0x54, 0xb8, 0x26, 0x56, 0xe7, 0x25, 0xd8, 0x8b, 0xb5, 0xe5, 0xe8, 0xdf, 0xbb, 0xf4, 0x22, 0x9e, - 0x17, 0x84, 0x70, 0x2a, 0x36, 0x5b, 0x1a, 0x20, 0x0e, 0x60, 0x17, 0x53, 0x1d, 0x10, 0x82, 0xba, 0xb3, 0xda, 0x03, - 0xf2, 0xf9, 0x6b, 0x86, 0xbe, 0x8f, 0x84, 0x6f, 0x02, 0x64, 0xa6, 0xa0, 0x3c, 0x51, 0xfb, 0x14, 0x45, 0xf4, 0xe0, - 0x27, 0x5d, 0x65, 0xb3, 0x16, 0x75, 0x12, 0x38, 0x1d, 0x71, 0x72, 0x16, 0xa3, 0x70, 0x5e, 0x3e, 0x13, 0xc0, 0x97, - 0x6b, 0x34, 0x98, 0x16, 0xdb, 0x28, 0x4e, 0xd9, 0x4e, 0xba, 0x5b, 0x03, 0x74, 0xc7, 0xe7, 0x88, 0xc3, 0x41, 0x26, - 0xca, 0xde, 0xae, 0x33, 0x5d, 0x86, 0x75, 0x53, 0x47, 0xbd, 0x9f, 0x28, 0x7c, 0x4a, 0xdd, 0xe3, 0x7d, 0x2e, 0x45, - 0x50, 0x21, 0x54, 0x12, 0xd4, 0x32, 0xa4, 0x3f, 0x6a, 0x79, 0x4e, 0x8d, 0xd4, 0x29, 0x8f, 0xcb, 0x05, 0x49, 0x6a, - 0xfb, 0x3e, 0x7b, 0xb4, 0x2f, 0x4f, 0xe4, 0x8e, 0x1b, 0x38, 0xd1, 0xb5, 0x02, 0x86, 0x4e, 0x73, 0x0f, 0x76, 0xde, - 0x8a, 0x8a, 0x64, 0x22, 0x8a, 0xa1, 0xbd, 0x84, 0xb3, 0x2a, 0xbb, 0x49, 0x42, 0x7f, 0x16, 0x2b, 0x9c, 0xd9, 0xb9, - 0x0c, 0xb5, 0x69, 0x6c, 0x61, 0x90, 0x51, 0x21, 0xb4, 0xdb, 0x98, 0x47, 0x98, 0xdc, 0x45, 0x6e, 0xf0, 0x2b, 0xad, - 0x54, 0x2e, 0x15, 0x92, 0xa6, 0x4b, 0x6f, 0xfd, 0x2f, 0x3b, 0x6a, 0xc5, 0x8d, 0xb7, 0x36, 0xca, 0x35, 0xca, 0xc5, - 0xcc, 0xf9, 0x8f, 0xd8, 0xe3, 0x12, 0x6b, 0xd8, 0x82, 0xcb, 0x86, 0xae, 0x50, 0x59, 0x4a, 0x03, 0x47, 0x1e, 0x88, - 0xa4, 0xee, 0x6b, 0x38, 0xe2, 0x16, 0xd5, 0x9f, 0xec, 0xf5, 0xc1, 0x06, 0xb5, 0x63, 0x36, 0x72, 0xb1, 0x8d, 0x5a, - 0xa1, 0x0b, 0x59, 0x45, 0x0d, 0x5c, 0x92, 0xb7, 0x60, 0x9a, 0x0c, 0xd1, 0x4d, 0x92, 0xb8, 0x7b, 0x3a, 0xc3, 0x2c, - 0x33, 0xbd, 0xe8, 0x7f, 0x56, 0xa2, 0xd2, 0xa1, 0xac, 0xb9, 0x92, 0xc3, 0x59, 0x47, 0xf5, 0xe3, 0xb0, 0x1f, 0xe2, - 0xd8, 0x74, 0x87, 0xe5, 0x80, 0x01, 0xac, 0x3a, 0xcc, 0x91, 0xa2, 0xf1, 0x62, 0xeb, 0xbb, 0x7d, 0xb7, 0x8d, 0x94, - 0xd0, 0xd0, 0x2f, 0x76, 0x08, 0xd8, 0xb7, 0xdf, 0x86, 0x39, 0xe3, 0xb6, 0x36, 0x8e, 0xf6, 0x51, 0x44, 0xda, 0x54, - 0x10, 0xfc, 0x91, 0x34, 0x39, 0xc0, 0x36, 0x5d, 0xca, 0x61, 0x73, 0xe5, 0xde, 0x67, 0x86, 0xc5, 0x94, 0x11, 0x31, - 0xab, 0xf7, 0x54, 0xe8, 0xaf, 0x7f, 0xf7, 0xdf, 0x2d, 0x5a, 0x5a, 0x34, 0xca, 0x8b, 0xf3, 0x72, 0x30, 0xb6, 0xea, - 0xd2, 0x7b, 0xb3, 0x34, 0xd6, 0x01, 0x40, 0xe5, 0xee, 0xfd, 0x45, 0x88, 0xbb, 0xeb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, - 0x93, 0xf2, 0xa9, 0xa7, 0x6c, 0x2c, 0x89, 0x3c, 0x65, 0xd6, 0xce, 0xed, 0x33, 0xbb, 0x09, 0x80, 0xf1, 0xbf, 0x32, - 0x3f, 0x2d, 0x2c, 0xf4, 0x9d, 0x56, 0x72, 0x51, 0xdb, 0x68, 0x67, 0xf4, 0x3e, 0x47, 0x81, 0x39, 0x40, 0x24, 0x27, - 0xe4, 0x3d, 0xbe, 0xa2, 0x78, 0xfc, 0x3f, 0x66, 0xa5, 0x61, 0xe3, 0xc4, 0x8e, 0xf2, 0xed, 0xc7, 0x0d, 0x1b, 0x29, - 0x39, 0x0f, 0x23, 0x23, 0x4c, 0xff, 0x1e, 0x99, 0x38, 0x8d, 0xca, 0xce, 0x3e, 0x2a, 0x88, 0x7a, 0xe2, 0xe3, 0xfb, - 0x73, 0x6c, 0xdd, 0x3f, 0x12, 0x2d, 0x65, 0x10, 0x96, 0x02, 0x38, 0x29, 0xf3, 0x48, 0xc3, 0x02, 0x98, 0xa2, 0x79, - 0x90, 0xf1, 0xc9, 0x69, 0x68, 0xbf, 0x7f, 0xe9, 0xf4, 0x1a, 0xb4, 0xbb, 0xc6, 0x30, 0x91, 0x35, 0x38, 0x77, 0x75, - 0xfb, 0x68, 0xd0, 0xdb, 0x7b, 0xde, 0x7e, 0x34, 0xe9, 0xad, 0xcd, 0x59, 0x43, 0x1b, 0x12, 0xc7, 0x3f, 0x6c, 0xff, - 0xa5, 0x9e, 0x27, 0x7b, 0xb7, 0x9a, 0x49, 0x91, 0x75, 0x39, 0xc4, 0x69, 0xd8, 0x52, 0x24, 0x1e, 0x80, 0xb8, 0xd4, - 0xfe, 0x58, 0xb2, 0xbc, 0xda, 0x83, 0xa2, 0xff, 0xd1, 0xfc, 0x48, 0x6b, 0xb2, 0x0f, 0xbe, 0x4c, 0xa1, 0x6a, 0xf7, - 0x33, 0xba, 0x3b, 0xbf, 0x07, 0x39, 0xb6, 0x59, 0x9a, 0xf8, 0xe2, 0xad, 0xa3, 0xe7, 0x89, 0xb4, 0x16, 0x5a, 0x99, - 0x61, 0x7a, 0xea, 0x1e, 0xc3, 0x52, 0x24, 0x4b, 0xcb, 0xde, 0xf2, 0x35, 0xe7, 0xe9, 0x4c, 0x7f, 0x7c, 0x10, 0xd7, - 0xb7, 0x7d, 0x4a, 0x7c, 0x8a, 0x98, 0x5f, 0xed, 0x13, 0xe0, 0x2c, 0x09, 0x1e, 0x47, 0x44, 0xa0, 0xb3, 0x15, 0xe5, - 0x23, 0x55, 0x75, 0xcd, 0xae, 0xff, 0xd1, 0xca, 0x02, 0x3b, 0x33, 0x1b, 0x77, 0x2b, 0x67, 0xfa, 0xe8, 0x34, 0xcf, - 0x72, 0x43, 0x3b, 0x90, 0x8b, 0x0d, 0x70, 0x60, 0xff, 0xb6, 0x49, 0x30, 0xac, 0x6d, 0xb8, 0x3f, 0x52, 0xbd, 0x31, - 0x4a, 0xfe, 0x46, 0x00, 0x46, 0x51, 0xd1, 0x56, 0xf1, 0xe6, 0x1a, 0xba, 0x90, 0x51, 0xbd, 0x3f, 0x79, 0x0f, 0xdf, - 0xef, 0x43, 0x1f, 0xba, 0x75, 0xd0, 0x5a, 0x70, 0x2a, 0x8b, 0x72, 0x39, 0xda, 0x3c, 0xef, 0x46, 0x5c, 0x7a, 0xf9, - 0x4d, 0x4f, 0x94, 0x7a, 0xfb, 0x6b, 0x07, 0x5b, 0x5a, 0x7e, 0x44, 0xa6, 0x9e, 0x24, 0x0a, 0x39, 0xd6, 0x4e, 0xf0, - 0x6a, 0xe9, 0x48, 0xc5, 0x81, 0xc3, 0xdd, 0x93, 0x91, 0x6f, 0xe6, 0x8c, 0x5d, 0x4b, 0x3a, 0x1e, 0x6c, 0x0c, 0xeb, - 0xe6, 0x6b, 0x29, 0xcd, 0x32, 0xeb, 0xd5, 0x3d, 0x3b, 0x11, 0x5e, 0x70, 0x78, 0x25, 0xb6, 0x29, 0xa4, 0xf9, 0xd5, - 0x44, 0x02, 0x37, 0xaf, 0xf7, 0x05, 0x20, 0x97, 0xb9, 0x74, 0x2e, 0xd8, 0x82, 0x74, 0xc5, 0x7f, 0x8e, 0x2a, 0xd0, - 0x27, 0x3f, 0xb3, 0x4a, 0xd7, 0xfa, 0x4a, 0x59, 0xa5, 0xf2, 0x1c, 0xdf, 0xd1, 0xa4, 0xd8, 0x3b, 0xda, 0x93, 0xd9, - 0x21, 0x1c, 0x8d, 0xc1, 0xcd, 0xfd, 0x46, 0x25, 0x65, 0x16, 0xa7, 0x5e, 0x92, 0xfe, 0x4b, 0xc2, 0x0c, 0x83, 0x84, - 0x04, 0x31, 0xff, 0x47, 0xdc, 0x98, 0xa3, 0x0e, 0x69, 0x0c, 0x4e, 0x64, 0x82, 0xd1, 0x42, 0x21, 0xba, 0x29, 0xcb, - 0x95, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xda, 0x65, 0x8d, 0x34, 0x2f, 0x7d, 0x0f, 0xbb, 0x87, 0x81, 0x14, 0x34, - 0x0a, 0x4b, 0x63, 0x0c, 0xec, 0xec, 0x26, 0x6d, 0x63, 0xb8, 0xd5, 0x1b, 0x68, 0x0a, 0x77, 0xef, 0xe9, 0x1a, 0xfa, - 0x5c, 0x24, 0x12, 0x4b, 0x7a, 0xb4, 0x8b, 0xc9, 0xb5, 0x96, 0xca, 0xb2, 0x5a, 0x8e, 0xdf, 0x4e, 0xf7, 0xb2, 0xbc, - 0x20, 0x68, 0xc8, 0x81, 0x93, 0xa3, 0xc0, 0x29, 0x97, 0x77, 0x32, 0x0d, 0x8e, 0x83, 0xb7, 0x99, 0x85, 0xc4, 0x1f, - 0xe4, 0x6d, 0xe8, 0xc8, 0x9c, 0xfd, 0xa0, 0x4d, 0x7f, 0xd4, 0x54, 0x85, 0x59, 0xd4, 0x43, 0x24, 0x03, 0x93, 0xee, - 0xde, 0x36, 0x06, 0x1d, 0x1f, 0xd7, 0x35, 0x6c, 0xee, 0x23, 0x0c, 0xae, 0x90, 0x08, 0xcd, 0xb1, 0x90, 0x3c, 0x03, - 0x9f, 0xe2, 0x61, 0x93, 0xa7, 0xcc, 0xdd, 0x8e, 0x89, 0xe3, 0xed, 0xe7, 0x9a, 0x26, 0x7b, 0xd9, 0xab, 0x7a, 0xf2, - 0x14, 0xb5, 0x5f, 0xb5, 0x6c, 0x46, 0x5a, 0xae, 0x79, 0x37, 0xf7, 0x30, 0x7a, 0x3e, 0xc5, 0x03, 0x3b, 0x08, 0xdc, - 0x19, 0xb1, 0x38, 0xc6, 0xf9, 0xbd, 0x55, 0x3c, 0x8c, 0xd1, 0x75, 0x19, 0x60, 0xd4, 0x06, 0xa2, 0x0f, 0x82, 0xf8, - 0x3e, 0x3b, 0x60, 0xdd, 0x39, 0xb0, 0x78, 0x63, 0x7a, 0xdc, 0x26, 0xe1, 0xb4, 0xd4, 0x27, 0xe3, 0x43, 0x36, 0x07, - 0x24, 0x54, 0x8a, 0x39, 0x0b, 0x42, 0x34, 0x01, 0x62, 0x0e, 0x29, 0xc9, 0x5e, 0xed, 0x03, 0x28, 0x62, 0x2e, 0x54, - 0x2e, 0x9a, 0x83, 0x1e, 0x10, 0x82, 0x1c, 0x66, 0x6c, 0xff, 0x31, 0x7e, 0x0c, 0x0f, 0x77, 0x58, 0xc8, 0x32, 0xe7, - 0x0d, 0x2e, 0xf2, 0xfd, 0x57, 0xc0, 0x5c, 0xba, 0x7a, 0xab, 0xbe, 0xd3, 0x13, 0xa4, 0xf4, 0x3e, 0x4b, 0x95, 0x5a, - 0x45, 0xee, 0x62, 0x95, 0x10, 0x5e, 0x17, 0x69, 0x34, 0x50, 0xd2, 0xdd, 0xa1, 0x1f, 0x7e, 0x05, 0x11, 0xd3, 0x17, - 0x12, 0xf0, 0x27, 0xf2, 0x03, 0xb1, 0xe0, 0xf5, 0x86, 0xa2, 0x30, 0x20, 0x7a, 0x0c, 0xb5, 0xf0, 0x0c, 0x95, 0x8a, - 0x93, 0xac, 0xe0, 0xee, 0x30, 0x4a, 0xd9, 0x3f, 0x4e, 0xe4, 0xc7, 0xaa, 0x3a, 0x76, 0x69, 0xd3, 0x5d, 0xc5, 0x6f, - 0x4b, 0xf6, 0x02, 0x88, 0x99, 0x2a, 0x3b, 0x53, 0x25, 0x22, 0x5f, 0x17, 0x88, 0xa0, 0x24, 0x3d, 0x4b, 0x76, 0xaf, - 0x86, 0xcf, 0xac, 0x62, 0x47, 0x9c, 0xd9, 0x25, 0x87, 0x80, 0xdf, 0x39, 0x99, 0xd8, 0xf4, 0xc1, 0xde, 0x79, 0xa0, - 0x4d, 0x1f, 0xa4, 0xc5, 0x5f, 0x16, 0x24, 0xf2, 0x0f, 0x5d, 0xf7, 0x16, 0x8c, 0x4d, 0x5a, 0x7f, 0x33, 0xf6, 0x20, - 0x6c, 0x8f, 0xb9, 0x79, 0x3b, 0x72, 0xcd, 0x7c, 0x89, 0x51, 0xee, 0xcd, 0xe9, 0x34, 0x7b, 0x9b, 0x61, 0x57, 0x37, - 0x7a, 0xd0, 0xac, 0x46, 0xfa, 0xe2, 0x27, 0xaa, 0xea, 0xe9, 0x06, 0x50, 0xef, 0xfc, 0xf4, 0xe9, 0xe8, 0xcb, 0x30, - 0x5b, 0x43, 0x72, 0x98, 0x30, 0x2f, 0xaa, 0xb1, 0xe7, 0xfa, 0x0c, 0xc1, 0xac, 0xa4, 0x7d, 0x07, 0x66, 0xe9, 0xb7, - 0x4c, 0x24, 0x87, 0x3e, 0xc5, 0xbe, 0x65, 0x45, 0x30, 0x48, 0xe7, 0xae, 0x46, 0xc5, 0x71, 0x16, 0xfa, 0x68, 0xda, - 0x72, 0x5f, 0xd4, 0xc8, 0x6d, 0x89, 0xd3, 0xe7, 0x72, 0xce, 0x40, 0xd8, 0x2f, 0xee, 0x38, 0xb3, 0xbe, 0xf3, 0x0e, - 0x49, 0x6b, 0x3d, 0x43, 0xbf, 0xa6, 0xf5, 0xd2, 0xad, 0xff, 0x3e, 0xf2, 0x56, 0xa6, 0x1d, 0x56, 0xcb, 0x39, 0x4d, - 0x4f, 0x55, 0xd9, 0x1b, 0x3c, 0x29, 0x03, 0x94, 0x2c, 0xa0, 0xbb, 0xac, 0x2d, 0x77, 0x13, 0xa0, 0xfe, 0x3a, 0xd2, - 0xb5, 0xfe, 0xce, 0x0a, 0x18, 0x14, 0x81, 0xda, 0x7e, 0x95, 0xf3, 0xa4, 0xbd, 0x12, 0x1f, 0x7f, 0xaf, 0x28, 0x36, - 0x5b, 0x9e, 0xbc, 0x15, 0xc8, 0x44, 0x3f, 0x0d, 0xcf, 0x9d, 0x9f, 0xab, 0x59, 0x98, 0x98, 0x4f, 0x97, 0x96, 0xdf, - 0xe3, 0x43, 0x77, 0x01, 0xad, 0xf7, 0x19, 0x21, 0x8d, 0xf9, 0x3f, 0xc7, 0x2c, 0x4b, 0xbc, 0x42, 0xb3, 0x7c, 0x1b, - 0xe0, 0x98, 0x0e, 0x4f, 0x49, 0xe3, 0x39, 0x0e, 0x28, 0x74, 0x83, 0x52, 0x6f, 0x37, 0x43, 0x2d, 0xc9, 0xc3, 0x42, - 0x41, 0x26, 0xfd, 0x88, 0xe6, 0x51, 0x76, 0x24, 0x80, 0x91, 0x69, 0xf5, 0xb7, 0xb9, 0xb6, 0xc8, 0xa3, 0x56, 0xfb, - 0x55, 0xe1, 0x5e, 0x9f, 0x45, 0xa3, 0xff, 0x6e, 0x06, 0x9c, 0x58, 0x1b, 0xb2, 0x37, 0x01, 0xd3, 0x88, 0x62, 0x8a, - 0x82, 0x1f, 0x0b, 0x92, 0x42, 0xa5, 0xe2, 0x5d, 0xd8, 0x22, 0x2c, 0x5c, 0x6a, 0x69, 0x19, 0x6b, 0xe2, 0x79, 0x0b, - 0xd0, 0xd1, 0xfe, 0xeb, 0xe2, 0xbb, 0xec, 0x99, 0xc1, 0x28, 0x29, 0xf7, 0x18, 0x8f, 0x04, 0xf5, 0x38, 0x2b, 0x01, - 0xfb, 0x2d, 0x84, 0xf8, 0x4a, 0x50, 0x93, 0x26, 0x75, 0x17, 0xc1, 0xe9, 0x36, 0x14, 0x70, 0x19, 0xad, 0x35, 0x12, - 0x34, 0x7c, 0x77, 0x92, 0x16, 0xb0, 0x2a, 0x78, 0x2f, 0x71, 0xc9, 0x8f, 0x81, 0x99, 0x8a, 0xee, 0xf0, 0x07, 0xd3, - 0xc7, 0x3b, 0xca, 0xf3, 0xb2, 0xd3, 0xba, 0xf6, 0x6e, 0xc3, 0x20, 0x8c, 0x18, 0x9f, 0x19, 0xe8, 0xc8, 0x5e, 0x0f, - 0xd8, 0x92, 0xc9, 0x18, 0x1b, 0xf0, 0x84, 0x28, 0xc8, 0x68, 0x9d, 0x8f, 0x2c, 0x5f, 0xec, 0xeb, 0x1e, 0x06, 0x27, - 0x64, 0x6c, 0x1c, 0x81, 0x1b, 0x35, 0x20, 0x43, 0xc2, 0x2c, 0xe1, 0xc7, 0x1e, 0xe1, 0x58, 0x3b, 0xf8, 0xaf, 0xb4, - 0x01, 0x05, 0xe4, 0x68, 0x4f, 0x0a, 0x49, 0xe6, 0x31, 0xcc, 0x1a, 0x14, 0x3e, 0x22, 0x43, 0x99, 0x93, 0xff, 0x1c, - 0x4b, 0x8a, 0x0d, 0xc7, 0xb1, 0x18, 0x99, 0x75, 0x1c, 0x7f, 0xea, 0xcc, 0x6f, 0x1b, 0xde, 0x83, 0x2a, 0x7a, 0xba, - 0x0e, 0x1e, 0x42, 0x29, 0x42, 0xb9, 0x99, 0x09, 0xe5, 0x47, 0x58, 0x74, 0x67, 0xb4, 0x01, 0xad, 0x1f, 0xa3, 0x47, - 0xbe, 0x7e, 0x83, 0x93, 0xcb, 0x50, 0x81, 0x75, 0xf1, 0xc3, 0x0f, 0xc4, 0xf4, 0xd9, 0x3b, 0x16, 0x6b, 0xe5, 0x6c, - 0x4e, 0x7d, 0xc9, 0xd0, 0x05, 0x5f, 0xa7, 0xeb, 0x13, 0xef, 0x95, 0x09, 0x52, 0xb3, 0xb0, 0x5a, 0x27, 0x36, 0x91, - 0x49, 0x8b, 0xd3, 0xe4, 0xdd, 0xfc, 0xe5, 0x69, 0x36, 0xf1, 0xca, 0xa5, 0xc0, 0xa4, 0x67, 0x51, 0x25, 0x36, 0x32, - 0xd3, 0x65, 0xc3, 0xbf, 0x1c, 0xe5, 0xf3, 0x6c, 0xa8, 0x67, 0x9e, 0x5f, 0xd0, 0x8d, 0xfb, 0xc3, 0x2c, 0x12, 0x6a, - 0x76, 0x5b, 0xe7, 0xcc, 0x4e, 0xb5, 0xcd, 0x7f, 0xb0, 0x73, 0xfb, 0xd8, 0xf7, 0x99, 0x8f, 0x64, 0x96, 0xae, 0x28, - 0x09, 0xbb, 0xe3, 0x21, 0xe9, 0x14, 0x93, 0x15, 0x67, 0x4e, 0x03, 0xf5, 0x5c, 0x16, 0xe7, 0x35, 0xb9, 0xbb, 0x80, - 0xb7, 0x82, 0x29, 0x03, 0x24, 0xd5, 0xf1, 0x45, 0x70, 0x55, 0x11, 0x38, 0x35, 0xb5, 0x50, 0x45, 0xf1, 0xb8, 0x33, - 0xdb, 0x2d, 0xa0, 0xea, 0xa7, 0x6a, 0x71, 0x69, 0xa4, 0xa2, 0x84, 0x67, 0xb2, 0x15, 0xa6, 0x40, 0xa6, 0x2b, 0x27, - 0xcd, 0x49, 0xac, 0x70, 0xd0, 0xcf, 0x22, 0x27, 0xd9, 0x8b, 0xaa, 0x76, 0xc3, 0x4b, 0x5b, 0x6b, 0x56, 0x18, 0xed, - 0x6c, 0xb5, 0x48, 0x27, 0x52, 0xb1, 0x7d, 0xa8, 0x1e, 0x0a, 0xf7, 0xdd, 0x04, 0x56, 0x6a, 0xa4, 0xb2, 0xfc, 0x75, - 0xa4, 0x86, 0x47, 0xfc, 0xb5, 0x49, 0x07, 0x49, 0xc3, 0x86, 0x1d, 0x6d, 0x6e, 0x9b, 0xcb, 0xa0, 0x58, 0xd6, 0x38, - 0x8c, 0x4a, 0x43, 0xb7, 0x11, 0xf9, 0x0a, 0xe5, 0x91, 0x7d, 0x13, 0x79, 0x43, 0x2c, 0xd9, 0x43, 0xbc, 0x46, 0xc2, - 0x24, 0xa5, 0x8f, 0x62, 0x8b, 0xc6, 0x85, 0xa2, 0x5b, 0xa6, 0xdd, 0xa6, 0x3b, 0x57, 0x49, 0x2e, 0xd3, 0x53, 0xcf, - 0xb3, 0x40, 0x29, 0xac, 0x44, 0x44, 0x42, 0xc8, 0x98, 0x67, 0x6f, 0xfc, 0xd4, 0xf4, 0xdc, 0x23, 0x4a, 0x34, 0xfb, - 0x02, 0xef, 0x85, 0x3e, 0x88, 0x11, 0x1f, 0x9b, 0x90, 0x63, 0xf8, 0xca, 0xe9, 0xf0, 0xbd, 0x6d, 0x4e, 0xfe, 0x68, - 0xe7, 0xe3, 0x89, 0x32, 0x25, 0xaa, 0x76, 0xf1, 0xb4, 0x81, 0xc4, 0x1a, 0x20, 0x9e, 0xa5, 0x63, 0x09, 0x4a, 0xa3, - 0xc7, 0x60, 0xe7, 0xf3, 0x6a, 0x97, 0x85, 0xda, 0xf4, 0x74, 0x97, 0xa5, 0x09, 0x70, 0xc1, 0x8e, 0xd2, 0xdb, 0xc4, - 0xee, 0xee, 0x2f, 0x1c, 0xd0, 0xdd, 0x37, 0x19, 0xd9, 0x68, 0x76, 0xd9, 0x90, 0xb0, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, - 0x25, 0x52, 0x21, 0xde, 0xd8, 0x37, 0x80, 0x99, 0x4c, 0x7b, 0xa6, 0xd1, 0x03, 0x91, 0xe2, 0x37, 0x60, 0x3b, 0x50, - 0x09, 0x0d, 0x32, 0x12, 0xf5, 0x93, 0x08, 0x35, 0x31, 0xee, 0x71, 0xfe, 0xe3, 0x9a, 0x72, 0x74, 0x90, 0x40, 0x8e, - 0x07, 0xbb, 0x67, 0x9d, 0x11, 0xc5, 0x59, 0x4f, 0x5a, 0xd5, 0x3c, 0x73, 0xd1, 0xa1, 0x74, 0x66, 0x1f, 0x28, 0xd1, - 0x13, 0x45, 0x7f, 0xb9, 0x1d, 0xe9, 0x47, 0x80, 0xc1, 0xb0, 0x2b, 0xcc, 0x7f, 0x32, 0x9d, 0x70, 0x41, 0x44, 0x3d, - 0x77, 0x57, 0xbd, 0x1d, 0x16, 0x3b, 0x93, 0xc9, 0xf8, 0xe4, 0x97, 0x81, 0xbb, 0x6f, 0x87, 0x88, 0xb4, 0x89, 0xdb, - 0x18, 0xf9, 0x64, 0x12, 0x30, 0xdb, 0xd5, 0x8d, 0x6a, 0x46, 0x3a, 0x26, 0x11, 0x53, 0xeb, 0x37, 0xf6, 0x79, 0x9b, - 0x5e, 0xbb, 0x07, 0xff, 0xfd, 0x06, 0x4d, 0x90, 0x7a, 0xa6, 0x8a, 0xc5, 0xfb, 0x70, 0xe7, 0xa0, 0xfb, 0xcb, 0xf6, - 0x59, 0x5e, 0xf6, 0xb0, 0x14, 0x32, 0xb4, 0x4a, 0xd4, 0xf9, 0x58, 0x3b, 0x8c, 0x74, 0x7e, 0xa6, 0x61, 0xb9, 0xd6, - 0x7f, 0xaa, 0x3a, 0x98, 0xf5, 0x9b, 0xc1, 0x49, 0x65, 0xb1, 0xa8, 0xa6, 0x92, 0x0b, 0xef, 0xe0, 0x6b, 0x38, 0xb7, - 0x86, 0x7e, 0xed, 0xa6, 0xf2, 0xd4, 0x55, 0xe1, 0xb2, 0xef, 0xa2, 0x9f, 0xb0, 0xa9, 0xbf, 0x8a, 0x41, 0xf9, 0xeb, - 0xe0, 0x14, 0x54, 0x6f, 0xc8, 0x1b, 0x23, 0x75, 0x17, 0xef, 0x17, 0x52, 0x62, 0x72, 0xc4, 0x3f, 0x0a, 0x86, 0x46, - 0x69, 0x5b, 0xaa, 0x63, 0xec, 0x2c, 0x98, 0xec, 0xac, 0x76, 0x5b, 0xff, 0x8e, 0x82, 0x27, 0xda, 0xce, 0xef, 0x7e, - 0x24, 0x35, 0x0f, 0xb0, 0xce, 0xfa, 0xf2, 0x23, 0x70, 0x5e, 0xdb, 0x8f, 0xd4, 0xf3, 0xa1, 0x98, 0x9e, 0x68, 0x7d, - 0xcc, 0xda, 0xf3, 0x6c, 0xc1, 0x9e, 0xef, 0x59, 0x08, 0x35, 0x52, 0x67, 0xfc, 0xc0, 0xcc, 0xef, 0x42, 0x67, 0x3b, - 0xec, 0xb2, 0x63, 0xad, 0x79, 0xbf, 0x32, 0x63, 0xa5, 0xca, 0x7a, 0xe7, 0xd8, 0x91, 0x6b, 0x8d, 0x27, 0x63, 0x18, - 0x48, 0x1a, 0xab, 0x9b, 0xe1, 0xd4, 0x09, 0x95, 0x6f, 0x66, 0x41, 0xc7, 0x4e, 0xa2, 0x9b, 0xe5, 0x22, 0x4a, 0xa4, - 0xc8, 0xdf, 0x06, 0x99, 0x62, 0x38, 0x64, 0xc2, 0xa3, 0xb8, 0x37, 0x41, 0xc2, 0xbc, 0x56, 0x52, 0x26, 0x56, 0x3b, - 0xba, 0x5e, 0xa5, 0x47, 0xc1, 0xc1, 0x9a, 0x2a, 0x69, 0x33, 0x10, 0x75, 0xa9, 0xfb, 0xb0, 0xa6, 0xfb, 0x43, 0xa3, - 0x3a, 0xd8, 0x5f, 0x79, 0x2b, 0xb5, 0x68, 0xfe, 0x45, 0x0d, 0xc7, 0x6a, 0x84, 0xcd, 0x0c, 0x78, 0x1c, 0xfd, 0x1f, - 0x49, 0xa1, 0x43, 0xd7, 0x02, 0xa0, 0xf6, 0xc7, 0xf2, 0x06, 0x45, 0x31, 0x02, 0xb4, 0x1f, 0x56, 0xde, 0x48, 0x7d, - 0xca, 0x1f, 0xcc, 0xae, 0xdb, 0x8e, 0x2c, 0x17, 0xc1, 0x58, 0x93, 0x6d, 0x00, 0x08, 0xcb, 0x17, 0xb0, 0x81, 0x28, - 0x1a, 0x45, 0xd9, 0xd2, 0x3b, 0xec, 0x16, 0x2f, 0x21, 0x5a, 0xf3, 0x98, 0x50, 0xf4, 0x0d, 0xa9, 0xa4, 0xb2, 0xac, - 0xf0, 0xfd, 0xab, 0x0b, 0xe6, 0x5a, 0x18, 0xbd, 0xb5, 0xe7, 0x56, 0xb6, 0xe8, 0xbc, 0xbb, 0xab, 0xe9, 0x9f, 0xda, - 0xd5, 0xf0, 0x91, 0x6d, 0xc0, 0x8c, 0x2c, 0x6c, 0xc9, 0x0f, 0x4f, 0xeb, 0x26, 0x1c, 0xff, 0x28, 0x2a, 0x46, 0x85, - 0x2b, 0x08, 0x16, 0xb5, 0x46, 0x9c, 0x92, 0x7f, 0x1c, 0x00, 0x05, 0xda, 0xc3, 0x92, 0x08, 0x89, 0x51, 0x95, 0xa1, - 0x12, 0xd9, 0x53, 0xf1, 0xab, 0x36, 0x90, 0xc1, 0x24, 0x1c, 0x4a, 0x06, 0x6e, 0x6a, 0xd7, 0x9c, 0x98, 0x9d, 0xb9, - 0xf5, 0x1f, 0xb7, 0x8c, 0xd5, 0x30, 0x61, 0x89, 0xfa, 0x14, 0x66, 0x7a, 0x59, 0xf5, 0x08, 0x8f, 0xa6, 0x85, 0xee, - 0x21, 0x48, 0x2d, 0x8b, 0x84, 0xdf, 0xb3, 0x8e, 0x50, 0x23, 0x98, 0x90, 0xdd, 0xb3, 0x32, 0x0e, 0x21, 0xd7, 0xe9, - 0x71, 0xc6, 0x0b, 0x50, 0xcb, 0x7a, 0x9d, 0xb1, 0xcc, 0x91, 0xd7, 0x82, 0x2e, 0xc9, 0x05, 0xd5, 0x6b, 0x94, 0x0d, - 0x33, 0xae, 0x3f, 0x97, 0x44, 0x23, 0xdf, 0xa0, 0xa1, 0x76, 0xe4, 0x39, 0xf1, 0x79, 0xce, 0xd1, 0x14, 0xc9, 0x1d, - 0x3d, 0x83, 0x56, 0x33, 0x5b, 0x73, 0xd3, 0x9b, 0xaf, 0x36, 0x23, 0x6c, 0x77, 0x3c, 0x4e, 0x99, 0x26, 0x4e, 0x06, - 0xe7, 0x47, 0xa0, 0xcd, 0x9d, 0x96, 0xdc, 0xb8, 0xf8, 0x3f, 0x44, 0x1e, 0xdd, 0x3c, 0x9e, 0x23, 0x98, 0xcb, 0x6d, - 0x8c, 0xe2, 0xe1, 0xe6, 0xd8, 0x05, 0x36, 0xec, 0xff, 0x13, 0x17, 0x5d, 0x13, 0xf1, 0xe2, 0x50, 0x2b, 0x51, 0x09, - 0x71, 0x62, 0x7d, 0xb6, 0x0f, 0xa4, 0xf5, 0x88, 0x84, 0x13, 0x65, 0x9d, 0xcd, 0xc2, 0x38, 0xd6, 0x65, 0xf0, 0xe1, - 0x07, 0x6a, 0x09, 0x41, 0x60, 0x98, 0xbf, 0xc4, 0xfe, 0x04, 0x56, 0x5c, 0x88, 0x42, 0x19, 0xf1, 0xc2, 0xbf, 0xfa, - 0x8c, 0xcf, 0x69, 0x56, 0x56, 0xba, 0xc6, 0xe5, 0xc8, 0x4c, 0xad, 0x61, 0x4e, 0x9e, 0xb0, 0x69, 0x8a, 0x58, 0x4c, - 0xcf, 0x0d, 0x53, 0xcc, 0x08, 0x68, 0x68, 0xce, 0xb9, 0x23, 0x65, 0x4d, 0x82, 0x97, 0x31, 0x29, 0x96, 0x02, 0x74, - 0x85, 0x2e, 0x33, 0xbb, 0xed, 0x0c, 0xe3, 0x60, 0xc8, 0xcd, 0x02, 0x40, 0xb8, 0x12, 0x41, 0x2d, 0x02, 0xcf, 0x8a, - 0x7d, 0x25, 0x32, 0x07, 0x73, 0x91, 0xa3, 0xde, 0xeb, 0xa4, 0xbf, 0x41, 0xc2, 0x25, 0xbc, 0x95, 0x02, 0x27, 0x03, - 0xba, 0x4c, 0xa4, 0x40, 0xf3, 0x12, 0x21, 0xc6, 0x1a, 0x90, 0xd4, 0x36, 0x7e, 0xb9, 0x88, 0x70, 0xcf, 0x07, 0xd9, - 0x70, 0xd6, 0x0d, 0x02, 0x20, 0x8f, 0xf2, 0xfa, 0x3b, 0x8b, 0x74, 0x87, 0x39, 0x01, 0x89, 0x0b, 0x8e, 0x91, 0x13, - 0xda, 0x39, 0x35, 0xd8, 0x32, 0x17, 0xa3, 0x8c, 0xdb, 0x1a, 0x25, 0x4b, 0xe1, 0x6c, 0x23, 0xed, 0x36, 0x72, 0x46, - 0x32, 0x50, 0xeb, 0x32, 0x09, 0x3b, 0x74, 0xed, 0xc9, 0x54, 0x6e, 0x07, 0x78, 0x67, 0xcd, 0x40, 0x9f, 0x6e, 0x3d, - 0x1f, 0xfb, 0x9f, 0x36, 0x57, 0xc9, 0xf4, 0x7d, 0x93, 0x31, 0x62, 0x2e, 0xd1, 0x97, 0x1c, 0x66, 0x9f, 0xf6, 0xfb, - 0x7c, 0x07, 0x8b, 0xf5, 0x55, 0xfc, 0x55, 0xc5, 0x46, 0xfd, 0xd4, 0x7a, 0xc1, 0x24, 0x49, 0x2c, 0xb9, 0x35, 0x28, - 0x29, 0xa8, 0xcc, 0xdb, 0xa8, 0x21, 0x2b, 0xa6, 0xb5, 0x66, 0x3b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, - 0x71, 0xc4, 0x3e, 0x79, 0xc4, 0xc6, 0xdb, 0xdb, 0x0f, 0x9c, 0xa1, 0x63, 0xf2, 0x00, 0x81, 0x42, 0x64, 0x5e, 0xba, - 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xca, 0x7f, 0x66, 0xd7, 0xfa, 0xd0, 0xd8, 0x27, 0xc2, 0xd7, 0xd9, 0xda, - 0xed, 0xd8, 0x87, 0x50, 0xa8, 0x22, 0x5f, 0x48, 0x1d, 0xcc, 0x5c, 0xbc, 0xa9, 0x0c, 0x6e, 0x7a, 0xfb, 0x28, 0x09, - 0x30, 0x39, 0x1b, 0xfd, 0x44, 0xad, 0x08, 0x3e, 0x7b, 0x44, 0xf8, 0x62, 0xbb, 0x2d, 0xa2, 0xe0, 0xca, 0x68, 0xc6, - 0xbb, 0x8c, 0x7e, 0x72, 0xa3, 0xc5, 0x2f, 0xd3, 0xb2, 0x3c, 0x7b, 0x6a, 0x3b, 0x85, 0xf6, 0x71, 0x10, 0xbb, 0x22, - 0x68, 0x6b, 0x63, 0x41, 0x90, 0x35, 0x75, 0xd9, 0xa4, 0x22, 0xc5, 0x6f, 0xad, 0x93, 0xce, 0xeb, 0xc4, 0x33, 0xdb, - 0xe5, 0x3e, 0x24, 0x62, 0x04, 0x6e, 0x8b, 0x6e, 0xb7, 0x41, 0x54, 0x70, 0xe9, 0xe8, 0x64, 0x82, 0x47, 0x5d, 0xe2, - 0xa4, 0xda, 0xf5, 0x76, 0xdc, 0xfe, 0xd9, 0x1c, 0xf6, 0x03, 0x50, 0xe9, 0x3a, 0xd0, 0x7f, 0x4b, 0xaf, 0x64, 0x8e, - 0x3d, 0xec, 0xcd, 0x41, 0x73, 0x0b, 0xf4, 0x53, 0xb5, 0x89, 0xa2, 0xee, 0x0b, 0xfa, 0xcc, 0x38, 0xfe, 0x2f, 0x55, - 0x56, 0x30, 0x14, 0x26, 0x33, 0xd1, 0xac, 0xb6, 0x20, 0x9d, 0x85, 0x41, 0xed, 0x87, 0xb7, 0x1a, 0x39, 0x60, 0x8b, - 0x79, 0xc4, 0xa1, 0x1e, 0x34, 0x82, 0x97, 0x50, 0x20, 0xcc, 0xbd, 0x33, 0x34, 0x06, 0x3d, 0x28, 0x0f, 0x90, 0x81, - 0x62, 0xd0, 0xb2, 0x14, 0x1a, 0xda, 0x84, 0x54, 0xbb, 0xdf, 0x1f, 0xbd, 0x3e, 0xf4, 0x7b, 0x35, 0x8a, 0x68, 0xd4, - 0x3b, 0x07, 0x09, 0x28, 0x7a, 0xc5, 0x81, 0x0c, 0x94, 0x37, 0x4b, 0x62, 0xc4, 0x32, 0x1e, 0x07, 0xb9, 0x3a, 0x78, - 0xbc, 0x52, 0x72, 0x3c, 0x2b, 0x84, 0x1e, 0x03, 0x18, 0xd6, 0x3d, 0x70, 0x2f, 0xbb, 0x15, 0x2c, 0x02, 0x9e, 0xd5, - 0x2b, 0xea, 0xd9, 0x6a, 0x3e, 0xd4, 0xbf, 0x97, 0x17, 0xef, 0xb7, 0xb4, 0x9f, 0x4a, 0xec, 0xb1, 0xac, 0xa9, 0x02, - 0x1f, 0xfe, 0xfc, 0x29, 0xf3, 0xb1, 0x58, 0xa4, 0x4f, 0x9f, 0x5c, 0xc3, 0x09, 0xd1, 0x75, 0xc9, 0xbf, 0x70, 0x71, - 0x6c, 0x53, 0x40, 0x0d, 0xa7, 0x61, 0xe7, 0x8a, 0xf0, 0x38, 0x61, 0x0d, 0x17, 0x45, 0x38, 0xec, 0xe0, 0x60, 0x23, - 0x8c, 0x6e, 0xa8, 0x21, 0x96, 0xf4, 0x4e, 0x7c, 0x3b, 0xc0, 0x25, 0xf8, 0x79, 0xa1, 0x97, 0x49, 0x80, 0xf8, 0x63, - 0x8b, 0xc1, 0x04, 0xb9, 0xc4, 0xda, 0x6c, 0xca, 0x6e, 0xf5, 0x5e, 0x6b, 0xda, 0x79, 0x9a, 0x6e, 0xee, 0xad, 0xd9, - 0x9c, 0xa8, 0x3c, 0x70, 0x92, 0x51, 0x5c, 0x90, 0x1e, 0xd5, 0x33, 0xf9, 0x2f, 0x8e, 0x13, 0x40, 0x66, 0xf1, 0xe0, - 0x5e, 0x09, 0x8c, 0xed, 0x2b, 0x5d, 0x8b, 0xf8, 0x97, 0xc8, 0xf8, 0xd9, 0x68, 0xc6, 0xec, 0x15, 0x96, 0x5c, 0x6d, - 0xa8, 0x0d, 0x07, 0xcc, 0x45, 0x2f, 0x15, 0x9d, 0x63, 0x8c, 0x5a, 0xd8, 0x8c, 0x5f, 0x8c, 0xdd, 0x42, 0xa4, 0x51, - 0x8d, 0xd9, 0xf6, 0x6b, 0x4b, 0x74, 0xdf, 0xe3, 0x89, 0x24, 0x68, 0x5e, 0x12, 0x50, 0x80, 0x5d, 0x4c, 0x30, 0x24, - 0xd7, 0x30, 0x8c, 0x69, 0x86, 0xe7, 0x29, 0xd4, 0xb5, 0x9e, 0x1a, 0x95, 0x97, 0xba, 0xcb, 0xda, 0x5c, 0xb6, 0x9b, - 0x3c, 0xee, 0x51, 0x90, 0x38, 0x6a, 0x9c, 0xa1, 0x61, 0x56, 0x3d, 0x43, 0xca, 0xb0, 0x84, 0x48, 0x2b, 0x2e, 0xf2, - 0xb6, 0x76, 0x99, 0xc2, 0x40, 0xde, 0x89, 0x6e, 0x3a, 0xa7, 0x42, 0x04, 0xbb, 0x8b, 0x8a, 0x84, 0x4d, 0xdb, 0xb2, - 0x89, 0x16, 0x3a, 0xf7, 0x6d, 0x28, 0x74, 0x09, 0xf1, 0x43, 0xb6, 0x17, 0xee, 0x5e, 0x22, 0xf6, 0x10, 0xc6, 0xe6, - 0x88, 0x2d, 0x3e, 0xea, 0x25, 0xad, 0x97, 0x43, 0x42, 0x70, 0xb6, 0x59, 0xfa, 0xfc, 0x77, 0x6c, 0xe8, 0xca, 0xcb, - 0x0d, 0x8d, 0xca, 0x8e, 0xae, 0xaf, 0xae, 0x5a, 0x25, 0x16, 0xa9, 0xc6, 0x1c, 0x72, 0xe2, 0xa1, 0x45, 0xe7, 0x01, - 0x6d, 0xe2, 0xac, 0x9c, 0x11, 0x92, 0x3b, 0x6b, 0x51, 0xe8, 0x1a, 0xec, 0xbd, 0x0b, 0x00, 0x3b, 0x36, 0x99, 0xea, - 0xc5, 0xca, 0x53, 0x92, 0x60, 0xe8, 0x56, 0xe8, 0x9d, 0xaf, 0x72, 0x07, 0x0a, 0x31, 0xac, 0x03, 0x2c, 0x9c, 0x95, - 0xcc, 0x09, 0xdb, 0x87, 0xf5, 0xf8, 0x31, 0xaa, 0x2d, 0x60, 0x7c, 0x08, 0xa1, 0xbe, 0xb7, 0x71, 0x1b, 0x8a, 0x8e, - 0xce, 0x68, 0x72, 0x97, 0x13, 0x64, 0xd0, 0x77, 0xae, 0x94, 0x4c, 0xf1, 0x84, 0xbc, 0x9c, 0x39, 0x52, 0xa8, 0xf2, - 0xa6, 0x55, 0xfa, 0x62, 0xfb, 0xf6, 0x4b, 0x1f, 0x61, 0x5d, 0x23, 0x2e, 0x15, 0x63, 0x3d, 0x20, 0xfb, 0xee, 0x28, - 0x5a, 0xd3, 0x5e, 0x3c, 0x5d, 0x11, 0xcf, 0xf1, 0x26, 0x1c, 0xe1, 0x4f, 0x9f, 0xaf, 0xab, 0xd5, 0x79, 0x40, 0xb9, - 0xf7, 0x66, 0xc1, 0x31, 0xea, 0x1d, 0x97, 0x88, 0x60, 0xd2, 0x39, 0xdd, 0x69, 0x33, 0xa8, 0x26, 0x22, 0x33, 0x7c, - 0xb8, 0xf4, 0xdb, 0xfd, 0xaf, 0x20, 0x58, 0x77, 0x11, 0x2e, 0xdc, 0xd2, 0x20, 0x0e, 0x59, 0x8a, 0x90, 0x76, 0x45, - 0x30, 0xd2, 0x51, 0x41, 0x6c, 0xc5, 0x4e, 0x8a, 0x3c, 0x5f, 0x43, 0x20, 0xe2, 0x1c, 0x5c, 0x3e, 0xb3, 0x0a, 0x2f, - 0xaa, 0xd7, 0x3f, 0x37, 0x48, 0xe9, 0xb2, 0x3a, 0xe8, 0x7f, 0x9d, 0x2c, 0xfc, 0xe4, 0xe0, 0xc0, 0xcb, 0xc8, 0xda, - 0xda, 0xec, 0xb4, 0xa9, 0xde, 0x0a, 0x76, 0xdc, 0xce, 0xf5, 0xbe, 0x7e, 0x03, 0x4a, 0xa3, 0xad, 0xa8, 0xd9, 0x6d, - 0xca, 0x4c, 0x8d, 0xe1, 0x31, 0xab, 0x45, 0x03, 0x5c, 0xb8, 0xc3, 0xfe, 0x64, 0xc0, 0xde, 0xc1, 0x54, 0xf4, 0xbc, - 0x6f, 0xff, 0xec, 0x64, 0x86, 0x84, 0xe9, 0x84, 0x43, 0xee, 0xc0, 0x67, 0x4c, 0x4f, 0x27, 0x7d, 0x2f, 0x10, 0xbf, - 0x8a, 0x24, 0x9b, 0xf0, 0xb7, 0x0a, 0xef, 0x69, 0x64, 0x6c, 0x09, 0x19, 0xdd, 0x16, 0x95, 0x22, 0x52, 0x4b, 0x83, - 0x81, 0x31, 0x8a, 0xf9, 0x94, 0x68, 0x26, 0x96, 0xdd, 0x61, 0x43, 0x62, 0x9f, 0xed, 0x39, 0x7b, 0xbb, 0x98, 0x4d, - 0x09, 0x5a, 0x56, 0x7b, 0xf1, 0x6a, 0x6d, 0xde, 0x2b, 0x8f, 0xae, 0x8f, 0x1b, 0x18, 0xb1, 0x3f, 0xb7, 0xda, 0x5b, - 0xe0, 0x41, 0x07, 0xfc, 0xf3, 0x9d, 0xe2, 0xc5, 0xad, 0xf2, 0x25, 0x04, 0x3f, 0x64, 0x9a, 0x2c, 0x81, 0x32, 0xc8, - 0xc5, 0x96, 0x0b, 0x1e, 0x48, 0x15, 0xb5, 0xdd, 0x7a, 0x8c, 0xd8, 0x3c, 0x9f, 0x7c, 0xda, 0xc1, 0xf0, 0x4c, 0x41, - 0x07, 0xfb, 0x97, 0xed, 0xfd, 0x06, 0x68, 0xdd, 0x64, 0xc8, 0xbf, 0x6b, 0xdd, 0x04, 0x19, 0xc1, 0xc7, 0xaf, 0xb6, - 0xbf, 0xb0, 0xe6, 0xd3, 0xd4, 0x76, 0x8c, 0x96, 0x41, 0xb7, 0xfc, 0x5d, 0x72, 0x0a, 0x71, 0x5d, 0xed, 0x01, 0x7c, - 0xba, 0x8c, 0x01, 0x5f, 0xa2, 0x6f, 0x90, 0x1a, 0x40, 0xe4, 0xb7, 0x1f, 0xf5, 0xe3, 0xa7, 0xe6, 0x66, 0xf5, 0x43, - 0xc7, 0x86, 0x12, 0x31, 0x38, 0xac, 0x42, 0xb6, 0xe3, 0x00, 0xa0, 0xe2, 0x61, 0xe5, 0x88, 0x0e, 0x9a, 0x0f, 0x05, - 0xfb, 0x14, 0x0f, 0x3b, 0x07, 0x5f, 0xd7, 0x45, 0x91, 0x35, 0xa2, 0x24, 0x07, 0x4b, 0x25, 0xdd, 0x2f, 0x8e, 0xd2, - 0x0c, 0xaa, 0xf6, 0x04, 0x71, 0x15, 0x01, 0xc4, 0x63, 0x30, 0xba, 0xaf, 0x4b, 0xbf, 0xe7, 0x8a, 0x05, 0xe0, 0xe7, - 0x14, 0x6e, 0x63, 0x9e, 0x8f, 0x29, 0x80, 0xa0, 0xcf, 0x86, 0x06, 0x73, 0x88, 0x48, 0xc6, 0xe9, 0xec, 0x5a, 0x8c, - 0xf2, 0x32, 0xf2, 0xed, 0x88, 0xad, 0x22, 0x7f, 0xc7, 0x2a, 0x2f, 0x2e, 0xee, 0x85, 0x64, 0x17, 0xab, 0x74, 0x06, - 0x91, 0xda, 0x85, 0x99, 0x8c, 0x46, 0x47, 0xa6, 0xe9, 0x04, 0xd1, 0x5e, 0x2a, 0xa4, 0x64, 0x18, 0xe5, 0x18, 0xc5, - 0x22, 0x8e, 0x9c, 0x83, 0x93, 0x25, 0x0c, 0xc3, 0x92, 0xe0, 0xbf, 0x69, 0x40, 0xd0, 0x2b, 0x95, 0x14, 0xec, 0xa2, - 0x84, 0xb7, 0x43, 0x06, 0x0d, 0x80, 0xa5, 0xc6, 0x3b, 0x24, 0x4f, 0x35, 0xaa, 0x93, 0x73, 0xad, 0xc8, 0x70, 0x2a, - 0x75, 0x21, 0x3b, 0xc6, 0x13, 0x02, 0x89, 0x71, 0xde, 0xf9, 0x3c, 0x0f, 0x1a, 0x20, 0xf6, 0x64, 0x6a, 0x8d, 0xf4, - 0xbc, 0x62, 0x0f, 0x66, 0x5b, 0xda, 0x86, 0x46, 0x33, 0x07, 0x46, 0x02, 0x9b, 0x3f, 0x30, 0x53, 0x15, 0x53, 0xf3, - 0xc8, 0x31, 0x08, 0x43, 0x68, 0xbd, 0x95, 0xd5, 0x01, 0x21, 0xb4, 0x3c, 0x29, 0x93, 0x0c, 0xe2, 0xda, 0xf8, 0x30, - 0xea, 0x1a, 0x1f, 0x34, 0x12, 0xa0, 0x35, 0x73, 0xb5, 0xc5, 0xc7, 0xb3, 0x85, 0xc2, 0x19, 0x4b, 0x46, 0x7f, 0xb6, - 0x35, 0xb5, 0x92, 0xee, 0xe6, 0xee, 0xaf, 0xb0, 0xe5, 0xeb, 0xe4, 0x22, 0xdd, 0x2e, 0x65, 0x5b, 0x50, 0x1e, 0x68, - 0xb7, 0x9b, 0x59, 0xff, 0xfc, 0x37, 0x1f, 0x3f, 0x22, 0x74, 0x91, 0xb0, 0x0b, 0xc9, 0x2d, 0xea, 0xf8, 0x8b, 0x8f, - 0x86, 0x27, 0x63, 0xd8, 0xee, 0x0c, 0xcc, 0x1d, 0xe6, 0x39, 0x86, 0xbd, 0xc7, 0xc7, 0x31, 0x0c, 0x10, 0x93, 0xaf, - 0xa6, 0x0a, 0x13, 0x79, 0x87, 0x81, 0xca, 0x55, 0xaf, 0x1d, 0x20, 0x22, 0xce, 0xd4, 0x3e, 0x89, 0xe6, 0x9f, 0xa9, - 0xc8, 0xfb, 0x67, 0xdb, 0x13, 0x92, 0x20, 0x5f, 0xcf, 0x9a, 0xb8, 0x8e, 0x29, 0xf0, 0x00, 0xdb, 0x97, 0x58, 0x34, - 0x76, 0x97, 0x84, 0xd0, 0x42, 0x17, 0xa1, 0xa4, 0xc1, 0x87, 0x50, 0xf5, 0x6a, 0x95, 0x6c, 0x98, 0x0a, 0x0b, 0xbc, - 0xf8, 0xf4, 0x70, 0x0c, 0xef, 0x8f, 0x07, 0xca, 0x05, 0x85, 0x5c, 0x4e, 0xf0, 0x21, 0x6e, 0x1a, 0x7b, 0x06, 0x52, - 0x90, 0xf6, 0x4d, 0xe1, 0x9a, 0x9f, 0x8c, 0xac, 0x0b, 0x1d, 0x59, 0x4e, 0x4e, 0x4c, 0xf6, 0x24, 0xfc, 0x8b, 0x92, - 0x19, 0x92, 0xbc, 0x1c, 0x9c, 0xda, 0xc0, 0xd7, 0x2e, 0xe9, 0x28, 0xd7, 0xa2, 0x6d, 0xc3, 0xaf, 0x15, 0x27, 0xe8, - 0x94, 0x43, 0x37, 0xc1, 0xcb, 0x5e, 0x7d, 0x4e, 0xcd, 0x8d, 0xef, 0x95, 0xb7, 0x8b, 0xfb, 0xd7, 0xab, 0x01, 0x0e, - 0xbe, 0x40, 0x8e, 0xf7, 0xcc, 0x28, 0xce, 0xbf, 0x1d, 0xc6, 0xab, 0xe5, 0x98, 0x21, 0x30, 0x81, 0x84, 0x4c, 0x23, - 0x62, 0x1b, 0x4e, 0xf0, 0xf1, 0x43, 0x9d, 0xa3, 0x92, 0xd0, 0xd2, 0x8a, 0x83, 0xe3, 0x5c, 0x7f, 0x1b, 0x65, 0x48, - 0x29, 0xcb, 0xa5, 0x8c, 0x30, 0xc4, 0xc4, 0x01, 0x39, 0xdb, 0x95, 0xef, 0xc5, 0xe7, 0xcc, 0x33, 0x0d, 0xa4, 0x77, - 0xf1, 0x80, 0x16, 0x19, 0xf5, 0x07, 0x85, 0x1a, 0x44, 0x9a, 0x18, 0x7c, 0x46, 0x49, 0x20, 0x31, 0xc6, 0x46, 0x08, - 0x94, 0x90, 0x63, 0xeb, 0x07, 0x8b, 0x2a, 0x4c, 0x84, 0x22, 0x80, 0x96, 0x68, 0x79, 0x24, 0x28, 0xc8, 0x0c, 0x69, - 0xa4, 0xc7, 0xdc, 0x2d, 0x1d, 0x98, 0x16, 0x60, 0x4a, 0xc5, 0x23, 0x80, 0x7c, 0x32, 0x86, 0xa9, 0x88, 0x60, 0x70, - 0x57, 0x5e, 0x26, 0x0d, 0x1d, 0xd6, 0x30, 0x17, 0xcd, 0xc5, 0x94, 0x79, 0x19, 0x85, 0x72, 0x82, 0xc9, 0x55, 0x3b, - 0x21, 0xee, 0x0c, 0xa6, 0x75, 0x17, 0xf3, 0x79, 0x80, 0xd0, 0xf6, 0xd6, 0xd9, 0x14, 0x28, 0x33, 0x92, 0xd8, 0x04, - 0x11, 0x91, 0x0c, 0x76, 0x20, 0x0d, 0x45, 0x22, 0x24, 0x84, 0x4a, 0x52, 0xd0, 0x3a, 0x99, 0x13, 0x11, 0x9f, 0x56, - 0x58, 0xec, 0x83, 0xb4, 0x58, 0x22, 0x9b, 0xf7, 0xad, 0x32, 0xcc, 0x0f, 0x04, 0x85, 0x15, 0x8b, 0xac, 0x0a, 0x16, - 0x21, 0x91, 0xb0, 0x7a, 0x9d, 0x30, 0x76, 0x5e, 0x5f, 0x7c, 0x9a, 0x08, 0x4a, 0x9c, 0xd0, 0x91, 0x60, 0x1c, 0xab, - 0xa2, 0x58, 0xc9, 0x9f, 0x14, 0x39, 0xac, 0xd8, 0xf0, 0xe5, 0x55, 0xe9, 0x26, 0x91, 0x7c, 0xc7, 0xae, 0xfa, 0x95, - 0xb0, 0xfb, 0xa1, 0x9e, 0x38, 0xab, 0x44, 0x72, 0x8a, 0x6a, 0xab, 0xfb, 0x4f, 0xcf, 0x57, 0x95, 0x44, 0x79, 0xa1, - 0xa4, 0x0c, 0x7a, 0x8f, 0xdb, 0x62, 0x2f, 0x28, 0x36, 0x69, 0x76, 0xcc, 0xb7, 0xbd, 0x4a, 0xe4, 0x55, 0xc1, 0x94, - 0x2e, 0xc4, 0x12, 0x10, 0x37, 0x83, 0x65, 0x28, 0x6d, 0xcc, 0xf9, 0x07, 0x08, 0x7d, 0xf5, 0x3e, 0x2a, 0xb3, 0x1f, - 0xfd, 0x60, 0x05, 0x4d, 0x5c, 0x3f, 0xb3, 0xe6, 0x7a, 0x93, 0x46, 0x24, 0x30, 0xce, 0x42, 0x2f, 0xc5, 0xbe, 0x1a, - 0x97, 0x33, 0x57, 0x9a, 0x3d, 0xde, 0x8c, 0x56, 0x20, 0x76, 0x95, 0x86, 0x1d, 0x71, 0x3c, 0x07, 0x80, 0x74, 0x1e, - 0x85, 0x23, 0xa9, 0x14, 0xde, 0x6b, 0x81, 0xeb, 0x86, 0x68, 0x4b, 0x3d, 0x1f, 0x19, 0x80, 0x73, 0xb2, 0xc8, 0x4a, - 0xde, 0x84, 0x8c, 0xc4, 0xbf, 0x3c, 0xf3, 0x98, 0x31, 0xf6, 0x5e, 0x55, 0x18, 0x21, 0xcd, 0xaf, 0x5e, 0xa8, 0xb8, - 0x60, 0x63, 0x35, 0x9f, 0x96, 0xa7, 0x3c, 0x90, 0x2a, 0x9f, 0xaf, 0xb4, 0xa9, 0x1f, 0x39, 0x1f, 0x89, 0xb9, 0xb9, - 0x99, 0x93, 0x7a, 0x60, 0x10, 0xb1, 0x71, 0x9f, 0x20, 0xf2, 0x48, 0xf1, 0x67, 0x45, 0x2e, 0xd2, 0x61, 0x05, 0x56, - 0x0a, 0x01, 0x0b, 0x0d, 0x90, 0x56, 0xde, 0x4f, 0xb0, 0xe5, 0xd7, 0x24, 0x1a, 0x52, 0x2f, 0x99, 0x0d, 0xa8, 0x06, - 0xf1, 0x7b, 0x27, 0x9b, 0xcd, 0x9d, 0x9c, 0xce, 0xb7, 0x27, 0x6b, 0x86, 0xc8, 0x11, 0x74, 0xf4, 0xeb, 0xfe, 0x8e, - 0xbd, 0x20, 0x6d, 0x3a, 0x3b, 0xd9, 0x5a, 0x1f, 0x5e, 0x01, 0x93, 0x4e, 0xc5, 0x48, 0x93, 0x1a, 0x95, 0xb0, 0xcc, - 0x94, 0x4d, 0x29, 0xd1, 0x15, 0xd8, 0x4a, 0xc9, 0xc1, 0x96, 0x24, 0x9f, 0x79, 0xf8, 0x98, 0x74, 0xd7, 0x08, 0x17, - 0xe0, 0x18, 0x78, 0x2f, 0x83, 0xd2, 0x79, 0x60, 0xf4, 0x62, 0x10, 0xf3, 0x24, 0x84, 0x37, 0x5c, 0x96, 0xbc, 0x6c, - 0xed, 0xc9, 0x8a, 0x1a, 0xab, 0x6f, 0xdf, 0x7c, 0x3b, 0xe8, 0xca, 0xac, 0xd9, 0xc9, 0xef, 0xe7, 0x26, 0x5f, 0x77, - 0xcd, 0xf7, 0xbc, 0x6d, 0x7f, 0xc7, 0xb5, 0xcb, 0x37, 0x38, 0x2e, 0x18, 0x05, 0x3b, 0x5d, 0xac, 0x4e, 0x1b, 0x74, - 0x5c, 0x2f, 0x61, 0x57, 0x66, 0x04, 0xb4, 0x7b, 0x5f, 0xeb, 0x7f, 0x07, 0x98, 0x99, 0x62, 0x1f, 0x09, 0x22, 0x59, - 0x89, 0x6a, 0xcf, 0xfc, 0x42, 0xed, 0x2f, 0x08, 0x05, 0xf3, 0x35, 0xc8, 0xa3, 0xb7, 0x43, 0xc2, 0x68, 0x99, 0x89, - 0x38, 0xc1, 0x86, 0x05, 0x8f, 0xae, 0xe7, 0x72, 0xb6, 0xc5, 0x0e, 0x8f, 0xad, 0xae, 0xda, 0xdc, 0xab, 0x14, 0xf9, - 0x88, 0xeb, 0xe3, 0x19, 0x7a, 0xdf, 0x99, 0x79, 0xd0, 0xd1, 0x85, 0x48, 0xd8, 0xe2, 0x3a, 0x7e, 0x60, 0xbe, 0x46, - 0xa1, 0x60, 0xae, 0x94, 0xb9, 0xbd, 0x45, 0xdd, 0x4f, 0x75, 0xcf, 0xc9, 0xee, 0xfb, 0x92, 0x6f, 0x7e, 0xa4, 0xbd, - 0x1f, 0x45, 0xb3, 0xc2, 0x13, 0x2b, 0x5c, 0x47, 0xcf, 0xe6, 0x37, 0x1f, 0x33, 0x45, 0x08, 0x61, 0x04, 0xfd, 0xc2, - 0xaf, 0x70, 0x2d, 0xf0, 0x46, 0x99, 0xb6, 0x61, 0x2f, 0xa9, 0xa5, 0x20, 0xae, 0x1d, 0x1e, 0xce, 0xd9, 0xad, 0x35, - 0x59, 0xec, 0x8e, 0xab, 0xbe, 0xd0, 0x28, 0x7f, 0x87, 0x4c, 0x3b, 0x7c, 0xf3, 0x0d, 0xb9, 0x61, 0xaf, 0xa6, 0x4f, - 0x46, 0x68, 0xe2, 0x4e, 0xbd, 0x7e, 0x0a, 0x24, 0xf3, 0x34, 0x01, 0xa2, 0x31, 0xfc, 0xdf, 0x25, 0x7b, 0x34, 0xa6, - 0x13, 0x36, 0xcc, 0x86, 0xac, 0x36, 0x60, 0xec, 0x21, 0x89, 0x1e, 0x7f, 0x45, 0xfe, 0xdf, 0x9a, 0x04, 0xc7, 0x4b, - 0x71, 0x9f, 0x1b, 0xfe, 0xb2, 0x0c, 0xb3, 0x9c, 0xc4, 0x2c, 0xb8, 0x65, 0xc5, 0xab, 0x20, 0x5c, 0xa6, 0x5d, 0x61, - 0x19, 0x96, 0x0b, 0x2c, 0x43, 0x59, 0x7d, 0x11, 0x49, 0x22, 0xed, 0x91, 0x98, 0x9d, 0xce, 0xde, 0x8b, 0x13, 0xb2, - 0xe3, 0x06, 0x4d, 0x8e, 0x2e, 0xb2, 0x31, 0x13, 0x45, 0xed, 0x41, 0x23, 0x83, 0x72, 0x35, 0x78, 0xb9, 0x86, 0x8e, - 0x0c, 0xe1, 0x6a, 0x54, 0xa1, 0x71, 0x21, 0x9d, 0x4f, 0x2f, 0x8f, 0x0c, 0x24, 0x19, 0x34, 0xc5, 0xb0, 0x23, 0x54, - 0xc5, 0xbc, 0x4e, 0xf5, 0x42, 0x6a, 0x85, 0x47, 0xf2, 0x28, 0xc3, 0xf2, 0xd2, 0x22, 0xa3, 0xdd, 0xbe, 0x72, 0x74, - 0x5d, 0x38, 0x8e, 0x9f, 0xc3, 0x64, 0xa1, 0x0e, 0xd7, 0x60, 0x20, 0xdd, 0x4f, 0x1f, 0x79, 0xe9, 0x7f, 0x34, 0x5d, - 0x0d, 0xed, 0xb3, 0x85, 0xf8, 0xea, 0x21, 0x23, 0x8e, 0xaf, 0x5e, 0x58, 0x84, 0xa3, 0xe5, 0x96, 0xe9, 0xe3, 0x98, - 0x6d, 0x1d, 0xaa, 0xdc, 0x1a, 0x8d, 0x67, 0xb5, 0x18, 0x3f, 0xba, 0x0a, 0x1a, 0x82, 0xa6, 0x24, 0x0b, 0xf7, 0x15, - 0x75, 0x41, 0x56, 0x30, 0x19, 0xac, 0xb0, 0xbc, 0x99, 0xdf, 0xa7, 0xb5, 0xa9, 0xb4, 0x7c, 0x24, 0xf8, 0x07, 0x0f, - 0xb1, 0xac, 0x4f, 0x85, 0xdd, 0x12, 0x17, 0x0f, 0x2c, 0xe4, 0x59, 0x2f, 0xdc, 0x68, 0xeb, 0x94, 0xab, 0x72, 0xd9, - 0x2d, 0x5d, 0x78, 0x55, 0xb7, 0xbc, 0x14, 0x82, 0xd7, 0x21, 0xc9, 0x49, 0x6e, 0x42, 0x2c, 0x06, 0x03, 0x6f, 0xe4, - 0xa4, 0xef, 0x14, 0x5c, 0xc8, 0x0d, 0x74, 0xa5, 0xaf, 0x13, 0x4b, 0x01, 0x05, 0xb0, 0x17, 0x1e, 0xd8, 0x78, 0x02, - 0x89, 0x3c, 0xbf, 0x5e, 0xd4, 0x89, 0x0e, 0x07, 0xbf, 0x9f, 0xaf, 0x14, 0x07, 0xf0, 0x5d, 0x82, 0x7c, 0x71, 0xde, - 0x48, 0xf0, 0x0f, 0xb0, 0xc3, 0xd9, 0xb9, 0xbf, 0xc1, 0x5c, 0xc2, 0x92, 0xec, 0x28, 0xe0, 0xb3, 0x02, 0xab, 0x9b, - 0x80, 0x8b, 0x04, 0xc1, 0x41, 0x5b, 0x2c, 0x17, 0x04, 0x87, 0x34, 0x0a, 0x15, 0xf3, 0x21, 0x3f, 0x37, 0x9b, 0x92, - 0x28, 0x92, 0xe1, 0xe7, 0xd7, 0xe0, 0x32, 0x23, 0x9c, 0xe2, 0x63, 0x4d, 0x95, 0x0f, 0x75, 0x5e, 0x8c, 0x74, 0x02, - 0x0c, 0x6f, 0xa6, 0x21, 0xda, 0x3f, 0x46, 0x8d, 0x92, 0xca, 0x3d, 0x0b, 0x97, 0xc6, 0xd9, 0x10, 0x2e, 0xf3, 0x6f, - 0xb2, 0xcc, 0x6b, 0x29, 0x96, 0x57, 0x36, 0x65, 0xc1, 0xf9, 0x1e, 0xd6, 0x71, 0xe4, 0xee, 0xb3, 0x5e, 0x59, 0x72, - 0x88, 0x76, 0xcb, 0x47, 0x67, 0x39, 0xa0, 0x57, 0x71, 0x75, 0xe3, 0x14, 0xc4, 0x91, 0x97, 0x97, 0x91, 0xca, 0x70, - 0x3c, 0x95, 0x04, 0x1c, 0xa9, 0xa7, 0xf8, 0xbf, 0x29, 0xe1, 0x1d, 0x04, 0x83, 0x30, 0x76, 0x0f, 0xf5, 0x2b, 0x40, - 0xd1, 0x16, 0x66, 0x07, 0x37, 0x25, 0x6e, 0xe2, 0xc0, 0x28, 0x47, 0x6f, 0x83, 0xf9, 0xd2, 0x12, 0xb4, 0xc2, 0x6a, - 0x46, 0xa0, 0xd5, 0xe7, 0x71, 0xaf, 0x08, 0xfc, 0xd4, 0x85, 0xe3, 0x79, 0x5e, 0x43, 0x77, 0x68, 0x1a, 0xcb, 0x33, - 0x69, 0x4b, 0xc2, 0x40, 0xd2, 0x2c, 0xb4, 0xf1, 0xe3, 0x73, 0x4d, 0x75, 0x3b, 0x8b, 0xe8, 0x7a, 0xbd, 0x0c, 0xa5, - 0x88, 0x58, 0xb4, 0x70, 0x34, 0x27, 0x1b, 0xd0, 0xe9, 0x3e, 0xd9, 0x98, 0x1a, 0x0e, 0x86, 0x90, 0x18, 0xb9, 0x0d, - 0xe3, 0x9c, 0xd8, 0xf0, 0x84, 0x2a, 0xd5, 0x13, 0x3f, 0x45, 0x5b, 0x89, 0xe0, 0x09, 0x95, 0x46, 0x1e, 0x78, 0x54, - 0xd1, 0x1a, 0x90, 0xc3, 0xc3, 0x47, 0xe0, 0x94, 0x6f, 0x30, 0x56, 0x47, 0x28, 0x50, 0x8e, 0x60, 0x4e, 0x91, 0x1f, - 0xee, 0xf0, 0x21, 0x7c, 0x2d, 0x4f, 0x30, 0x53, 0x6b, 0x2f, 0xc7, 0x5c, 0x0f, 0xb9, 0x1d, 0xf2, 0xb0, 0xff, 0xc4, - 0xcb, 0xc8, 0x46, 0x68, 0xf8, 0x91, 0x5f, 0xf5, 0x58, 0x7f, 0x3d, 0xc0, 0x7c, 0x3a, 0xd9, 0x83, 0x09, 0x67, 0x05, - 0x40, 0xfc, 0xd1, 0x55, 0x70, 0x37, 0x68, 0x58, 0x1f, 0x63, 0x12, 0x66, 0x27, 0x0e, 0x87, 0x6f, 0xa5, 0x02, 0x50, - 0x9e, 0x87, 0x19, 0x89, 0x2c, 0x24, 0xf3, 0xf3, 0x72, 0x8a, 0x6d, 0x51, 0xa6, 0xb6, 0xb4, 0x75, 0x0d, 0x38, 0x91, - 0xc5, 0xcd, 0x24, 0x79, 0x0a, 0x35, 0x2a, 0x22, 0x46, 0xc2, 0x2c, 0xd8, 0x7a, 0x99, 0xb0, 0xc7, 0x6f, 0x8c, 0x61, - 0xd4, 0xa6, 0x8d, 0xf4, 0x86, 0xbd, 0xea, 0x4f, 0xd6, 0xef, 0x11, 0x5b, 0x15, 0xe0, 0xbe, 0xa5, 0x1f, 0xa0, 0x48, - 0xe3, 0x96, 0x76, 0xf2, 0xd3, 0x89, 0x04, 0xfa, 0x87, 0x18, 0x36, 0x89, 0x0d, 0x0a, 0x8e, 0x2f, 0xb5, 0x29, 0xde, - 0x06, 0xce, 0x0c, 0xc5, 0x7a, 0xad, 0x67, 0xe0, 0x44, 0x1b, 0x41, 0x2a, 0x74, 0xcf, 0x58, 0x1e, 0x91, 0xa9, 0xf3, - 0x4f, 0x48, 0xcb, 0x16, 0xa6, 0x25, 0x9f, 0xe4, 0x74, 0x24, 0xd9, 0xf9, 0x29, 0x9a, 0xe4, 0x9d, 0xde, 0x25, 0x52, - 0x7c, 0x7d, 0x19, 0x66, 0x2f, 0xff, 0x84, 0x9a, 0x14, 0x22, 0x1d, 0x5c, 0xdd, 0x30, 0x31, 0xd4, 0x0a, 0x8c, 0xea, - 0x78, 0x9f, 0x8a, 0x4c, 0x1c, 0x0f, 0x6a, 0xe6, 0x45, 0x85, 0xc1, 0x13, 0x4b, 0x70, 0x94, 0xca, 0xae, 0xb6, 0xec, - 0x2d, 0x9c, 0x0c, 0x7e, 0x8a, 0x35, 0x49, 0xd5, 0xf1, 0x82, 0xb6, 0x6a, 0x68, 0x0e, 0x5d, 0x33, 0x6f, 0x66, 0xc7, - 0x63, 0xff, 0x2a, 0x61, 0xd1, 0xc0, 0x9a, 0x0e, 0x88, 0x5e, 0x07, 0xfd, 0x9c, 0x16, 0xdc, 0x2f, 0xbc, 0x0e, 0xbc, - 0x11, 0x83, 0x08, 0x0a, 0x66, 0x28, 0xf1, 0x79, 0xb5, 0x40, 0xc6, 0x86, 0x62, 0x92, 0x54, 0xd2, 0xb1, 0x71, 0x65, - 0x94, 0x8d, 0xcb, 0xf4, 0x72, 0xca, 0xdb, 0x2c, 0xe8, 0x21, 0x6f, 0xe5, 0x2b, 0x88, 0x93, 0xc6, 0x31, 0x22, 0x02, - 0x1c, 0x0f, 0x97, 0x39, 0x87, 0xbc, 0x59, 0x6c, 0x41, 0x4f, 0x09, 0xad, 0xc1, 0xcd, 0xce, 0x59, 0x4f, 0xf9, 0x52, - 0x3c, 0x5d, 0x14, 0x97, 0xdd, 0x6f, 0xa0, 0x00, 0x08, 0x03, 0xff, 0x23, 0x09, 0x7d, 0x56, 0x20, 0x63, 0x8e, 0x07, - 0xc9, 0x91, 0xe5, 0xb1, 0x96, 0x47, 0xa0, 0x85, 0x18, 0xa9, 0xde, 0x86, 0xbf, 0xf3, 0x29, 0x5e, 0x68, 0x07, 0x2b, - 0x77, 0x83, 0x20, 0x48, 0x70, 0x00, 0xfc, 0x85, 0xf7, 0xdd, 0xd0, 0x07, 0xef, 0xb7, 0x7b, 0x87, 0xff, 0xa7, 0x39, - 0xb3, 0x8f, 0x18, 0xdb, 0x7e, 0x88, 0x55, 0xdf, 0x25, 0xff, 0xf1, 0xd0, 0xd0, 0x06, 0xe8, 0xe1, 0x03, 0x1b, 0xce, - 0xde, 0xd3, 0x10, 0x6e, 0xdb, 0xa8, 0x02, 0x96, 0x14, 0x86, 0x48, 0x39, 0xa9, 0xa3, 0xfa, 0x22, 0x95, 0xdc, 0x24, - 0xfe, 0x3c, 0x33, 0x50, 0xfd, 0x83, 0x85, 0x5f, 0x83, 0x2f, 0xbb, 0x07, 0x05, 0x66, 0x62, 0x7d, 0x1a, 0x50, 0xaa, - 0xd4, 0x61, 0x7e, 0xf1, 0xd0, 0xfe, 0x1a, 0xb5, 0xab, 0x6c, 0x78, 0x7f, 0xd1, 0x95, 0x82, 0xb0, 0xc5, 0xe5, 0x21, - 0xd7, 0xe6, 0xde, 0x3e, 0xad, 0x5d, 0xed, 0x03, 0xef, 0x0a, 0x11, 0x60, 0xa7, 0xce, 0xe4, 0xe4, 0x19, 0x9f, 0x9a, - 0x40, 0xe7, 0xec, 0xde, 0xfe, 0x66, 0x03, 0x7e, 0x34, 0xc0, 0x76, 0x57, 0xf7, 0xf6, 0x01, 0x0c, 0xca, 0x65, 0xd4, - 0x50, 0x21, 0x31, 0xc4, 0x4b, 0x2a, 0x48, 0x39, 0x8a, 0xce, 0x87, 0xc8, 0x93, 0x43, 0x4c, 0x1b, 0x09, 0xae, 0xab, - 0xb4, 0x3d, 0x72, 0x12, 0xb4, 0x3c, 0xb2, 0x7b, 0x18, 0xb7, 0x51, 0x71, 0x5c, 0x64, 0x34, 0xf2, 0x0c, 0xee, 0x70, - 0xae, 0x23, 0xf4, 0x68, 0x55, 0x0a, 0x90, 0x26, 0x5c, 0x41, 0xfd, 0x3e, 0x9c, 0x8d, 0xb2, 0x87, 0xaa, 0xe5, 0xd8, - 0x4f, 0xe0, 0x35, 0x45, 0xef, 0xc8, 0x9f, 0x5b, 0x99, 0x15, 0xe1, 0xf2, 0xca, 0x62, 0xb2, 0x10, 0xcc, 0xd1, 0x36, - 0x6e, 0x99, 0x74, 0xf0, 0x0c, 0xf5, 0xfc, 0x50, 0xb5, 0x87, 0x15, 0x5f, 0x10, 0xc9, 0x34, 0xc5, 0x9d, 0xc3, 0xaf, - 0x63, 0x7e, 0x55, 0x38, 0x05, 0x72, 0x37, 0x1d, 0x26, 0xc2, 0x35, 0xdb, 0x4d, 0x90, 0x45, 0x9a, 0x0f, 0x15, 0xba, - 0x7d, 0xd6, 0x51, 0x9f, 0xb9, 0xc4, 0xa8, 0x3d, 0x4a, 0x66, 0x7c, 0xc2, 0x76, 0xbb, 0x91, 0x7e, 0xd1, 0xb5, 0x14, - 0x43, 0x24, 0x95, 0x29, 0xa5, 0x4b, 0x69, 0x89, 0x23, 0xb5, 0x0c, 0x65, 0x1c, 0x4a, 0xe8, 0x14, 0x40, 0xdb, 0x78, - 0xc8, 0x4c, 0x22, 0xed, 0x54, 0xfb, 0xac, 0xca, 0x64, 0x8f, 0xc5, 0x91, 0x30, 0x64, 0xe1, 0x99, 0x60, 0x7d, 0x7f, - 0xae, 0xf9, 0x92, 0x02, 0x55, 0x19, 0xac, 0x3b, 0x06, 0x7f, 0x2c, 0xb4, 0x79, 0x29, 0x2f, 0x85, 0x5e, 0x85, 0xa9, - 0x50, 0x5b, 0xbd, 0xb4, 0x4e, 0x1b, 0x42, 0x05, 0xb2, 0x76, 0x96, 0xe8, 0x51, 0x36, 0x38, 0xc8, 0xf1, 0xbf, 0x0d, - 0x22, 0xdb, 0x1e, 0x04, 0xdb, 0x7b, 0xa6, 0x22, 0xf5, 0xbd, 0xd5, 0x77, 0x9b, 0xf1, 0x89, 0x09, 0x81, 0xcb, 0x80, - 0xab, 0xce, 0xc7, 0x6e, 0x6c, 0xc3, 0x1f, 0x11, 0xe0, 0xef, 0x70, 0xe5, 0xa9, 0xf0, 0x55, 0xfa, 0x5a, 0xd9, 0xca, - 0x2b, 0xef, 0x39, 0x05, 0xb6, 0x6d, 0x7d, 0xa5, 0x09, 0x58, 0x31, 0xd0, 0x8b, 0x80, 0x6f, 0x73, 0xf2, 0x03, 0xf9, - 0xbc, 0x0b, 0xed, 0x99, 0x13, 0xb0, 0x19, 0xec, 0xc1, 0x8e, 0xdd, 0x8d, 0xd1, 0x28, 0x35, 0xe1, 0x57, 0xe6, 0xf6, - 0xa3, 0xaf, 0xa5, 0xff, 0xfc, 0x25, 0x86, 0xe8, 0x25, 0x30, 0x85, 0xf3, 0xd7, 0x11, 0xea, 0x0e, 0x59, 0x52, 0xda, - 0x91, 0x6a, 0x14, 0x5d, 0x54, 0x61, 0x5d, 0x0b, 0xb0, 0x42, 0x63, 0xf5, 0x8d, 0xe1, 0xb5, 0x92, 0x74, 0x14, 0x6b, - 0x2d, 0x86, 0xb7, 0xe9, 0xfc, 0xbe, 0x8a, 0x9d, 0x04, 0x2c, 0x60, 0xbe, 0x4e, 0x70, 0x17, 0x19, 0xec, 0x0e, 0xf7, - 0x6c, 0x3f, 0x27, 0x1a, 0x8e, 0x5c, 0x28, 0x80, 0x0a, 0x6f, 0x17, 0xd2, 0xa4, 0x5f, 0xe7, 0x3f, 0x57, 0xc5, 0x77, - 0x4c, 0x2d, 0x39, 0x4c, 0xf4, 0x52, 0xe3, 0x5f, 0xf7, 0xc6, 0x0f, 0xe5, 0xeb, 0xe5, 0x83, 0xbd, 0x10, 0x6e, 0x79, - 0x8e, 0x95, 0x15, 0x51, 0x0d, 0x71, 0x7f, 0xe8, 0x64, 0x46, 0xb9, 0x9b, 0x6b, 0x92, 0xd5, 0x49, 0x5a, 0x05, 0x4f, - 0x7d, 0x95, 0xf1, 0x67, 0x66, 0x94, 0x7b, 0x6e, 0x2c, 0x43, 0x89, 0x74, 0xe0, 0x8b, 0x86, 0xe6, 0x67, 0xa8, 0x8e, - 0x28, 0x9e, 0xab, 0x01, 0x1b, 0x40, 0x69, 0x5e, 0x0f, 0x03, 0x6b, 0x99, 0xba, 0x30, 0xaa, 0x36, 0xa2, 0xa0, 0x04, - 0x53, 0x48, 0x6b, 0x69, 0x4b, 0x2c, 0x50, 0x51, 0xb3, 0xa8, 0xb1, 0xd1, 0xcf, 0x74, 0x58, 0xe3, 0x66, 0x87, 0x7b, - 0x82, 0x19, 0x41, 0x50, 0x45, 0xb6, 0x3e, 0xb4, 0xaa, 0x46, 0x51, 0x3c, 0xf5, 0x73, 0x40, 0x41, 0xf9, 0x8f, 0x2b, - 0x5f, 0xda, 0xe2, 0xb8, 0x63, 0x35, 0xe0, 0x8b, 0xe2, 0xfd, 0x1e, 0xb9, 0x2a, 0x25, 0x36, 0x71, 0x93, 0x5b, 0x34, - 0x65, 0x04, 0xb1, 0xa7, 0x3f, 0x41, 0x95, 0x14, 0x29, 0x5d, 0xc4, 0x0d, 0xad, 0xb9, 0x38, 0x59, 0xa2, 0x0d, 0xf5, - 0xc0, 0xad, 0x6f, 0x64, 0x68, 0xa2, 0x57, 0xfb, 0xf2, 0x8d, 0x42, 0x0c, 0xc2, 0x92, 0x85, 0xbc, 0x62, 0x62, 0xcc, - 0x60, 0xe0, 0x48, 0xd1, 0xb6, 0x51, 0x2e, 0x46, 0x6f, 0xc4, 0x72, 0x75, 0x9c, 0xef, 0x64, 0x3b, 0x8a, 0x4a, 0x67, - 0xdc, 0x2b, 0xd0, 0xe6, 0xa7, 0x6d, 0xff, 0x86, 0xa7, 0xff, 0xa4, 0x26, 0x5c, 0x8f, 0xd0, 0xb3, 0x08, 0x9f, 0x7a, - 0x40, 0x2c, 0x8f, 0x81, 0x14, 0xa6, 0xe7, 0x2f, 0x52, 0x38, 0x46, 0xd2, 0x8d, 0x25, 0xb1, 0xe4, 0x39, 0x4e, 0xf1, - 0x3d, 0x75, 0xbe, 0xa4, 0x03, 0xea, 0xe8, 0xe4, 0x16, 0x12, 0x68, 0x9a, 0x09, 0xc9, 0xe6, 0x13, 0xda, 0xbc, 0x4c, - 0xcd, 0xba, 0x41, 0xf2, 0x96, 0xa7, 0x96, 0xef, 0x54, 0x2c, 0xe3, 0xfb, 0x21, 0x12, 0x42, 0xd6, 0x2b, 0x6a, 0x96, - 0xfc, 0x82, 0x94, 0xed, 0x02, 0xb4, 0x4b, 0x05, 0x61, 0x71, 0xf6, 0x9a, 0x98, 0xfb, 0x4a, 0xa5, 0x1f, 0xca, 0x6b, - 0xa4, 0x3d, 0x1c, 0x02, 0x00, 0xe3, 0x7e, 0x6f, 0xc2, 0xc4, 0xe8, 0x0c, 0x17, 0x4e, 0xd4, 0x52, 0x21, 0x09, 0xdb, - 0x24, 0x65, 0x76, 0x6f, 0xd6, 0xf1, 0xc3, 0x5f, 0x63, 0x38, 0x37, 0x5a, 0x2b, 0xe1, 0x36, 0xd0, 0x55, 0x67, 0xc8, - 0xab, 0x73, 0xc4, 0xde, 0xdc, 0x29, 0x7f, 0x2e, 0x07, 0xa1, 0xd2, 0x6a, 0x3e, 0x5b, 0x85, 0x5b, 0x30, 0x85, 0x27, - 0x5e, 0x13, 0x6c, 0x30, 0x2f, 0xe1, 0x25, 0xa0, 0xc6, 0x20, 0xe3, 0x23, 0x1f, 0x6c, 0x81, 0x95, 0xd5, 0xf8, 0x73, - 0xec, 0xdf, 0x87, 0xb9, 0xdb, 0xb3, 0x68, 0xe3, 0x7a, 0x31, 0x7d, 0x40, 0x49, 0x26, 0x9c, 0x76, 0xb7, 0x60, 0xdd, - 0xd0, 0x4e, 0x4c, 0xa1, 0x51, 0x31, 0x37, 0x20, 0x75, 0xec, 0xc6, 0xa1, 0xb6, 0xa3, 0xf5, 0xe6, 0x23, 0x8a, 0x06, - 0x71, 0x8e, 0xc8, 0xd6, 0x66, 0xbd, 0xb6, 0xb4, 0x5b, 0x18, 0x40, 0x29, 0x58, 0x4e, 0x09, 0xce, 0xbb, 0x72, 0xd1, - 0x2e, 0x0a, 0xb3, 0x05, 0x90, 0xd2, 0x0d, 0x64, 0xc8, 0x23, 0xea, 0x35, 0x99, 0x63, 0xb7, 0xf4, 0xf8, 0xd9, 0x40, - 0xec, 0x47, 0xbf, 0x24, 0xe3, 0xcc, 0xc0, 0xa4, 0xbd, 0x2f, 0x29, 0x79, 0xa2, 0x9c, 0xbc, 0x6a, 0xe4, 0x30, 0x6c, - 0xe9, 0x1d, 0xcb, 0xc3, 0x8c, 0x1e, 0x82, 0x04, 0x99, 0xf7, 0x8e, 0xe9, 0x12, 0x21, 0xbe, 0x87, 0x85, 0x80, 0x69, - 0xb4, 0xfe, 0xb7, 0xda, 0xe5, 0x53, 0x9f, 0xe7, 0x36, 0xed, 0xad, 0x3b, 0x74, 0xc5, 0x95, 0x4b, 0x6e, 0xfd, 0xa8, - 0x9e, 0xa9, 0xda, 0xa9, 0x7c, 0x6f, 0xb5, 0xec, 0xeb, 0x1c, 0xa4, 0xa1, 0x3d, 0xf2, 0x41, 0xbb, 0xd8, 0x58, 0xb6, - 0xa6, 0x59, 0x34, 0xb3, 0x68, 0xe3, 0x58, 0xd9, 0xc5, 0xb7, 0xc4, 0x23, 0x71, 0xc1, 0xdc, 0xc6, 0xa3, 0x32, 0x12, - 0x3b, 0x3c, 0xa2, 0x2d, 0x7c, 0x23, 0xb4, 0x6d, 0x98, 0x8b, 0x8f, 0x13, 0x70, 0xac, 0x2d, 0x9f, 0x96, 0x63, 0x66, - 0xb5, 0x88, 0x32, 0x59, 0x01, 0x8c, 0x8b, 0xda, 0x71, 0x6f, 0x82, 0xa1, 0x0e, 0xc9, 0xc5, 0x1a, 0x84, 0x30, 0xbd, - 0x16, 0xea, 0xcc, 0xab, 0xfc, 0x8a, 0x6c, 0x6d, 0x2c, 0xc2, 0x42, 0xcb, 0xc6, 0xcc, 0x64, 0x4d, 0x0b, 0x60, 0x8d, - 0xa0, 0xd7, 0x6b, 0xb8, 0x7b, 0x6e, 0xa9, 0xfc, 0x19, 0x1c, 0xb9, 0xf8, 0x18, 0xcc, 0xc7, 0x5e, 0xa5, 0xa4, 0xa9, - 0x87, 0xcf, 0x13, 0xcd, 0x08, 0x8e, 0x5b, 0xe5, 0x0d, 0xb5, 0x67, 0xc3, 0xff, 0x81, 0xaf, 0xe1, 0x73, 0x4e, 0x6e, - 0x85, 0x71, 0x70, 0x66, 0xed, 0x8b, 0x77, 0x75, 0x8c, 0x98, 0x45, 0x8c, 0xf1, 0x25, 0x6b, 0x4a, 0xb9, 0xf9, 0x2c, - 0xd6, 0x47, 0x50, 0x04, 0x96, 0xaf, 0x31, 0x19, 0x21, 0x1c, 0x2c, 0x6e, 0x34, 0x19, 0x62, 0x03, 0xdd, 0x9b, 0x7b, - 0x40, 0x0c, 0x06, 0xe0, 0x21, 0xce, 0x05, 0x59, 0xe8, 0x00, 0xb2, 0xfc, 0x01, 0x12, 0x08, 0x49, 0x60, 0x81, 0x22, - 0x21, 0x23, 0xaf, 0x5a, 0x87, 0x9a, 0x97, 0xb3, 0xcb, 0x0c, 0x17, 0x10, 0x0c, 0x5b, 0xb9, 0x4b, 0xab, 0x51, 0x9b, - 0xed, 0x2d, 0x96, 0x81, 0xde, 0x9e, 0x35, 0x95, 0xa4, 0x48, 0xf9, 0xb5, 0xe9, 0x18, 0xff, 0x78, 0xc8, 0x56, 0x74, - 0xae, 0x18, 0xc3, 0xfd, 0x48, 0x9e, 0xdd, 0xf9, 0xcb, 0xc2, 0x72, 0xb1, 0x1e, 0x4a, 0x3d, 0x34, 0x66, 0x17, 0x0b, - 0x1d, 0xb6, 0x45, 0xc3, 0x22, 0x52, 0xff, 0x24, 0xbc, 0x1e, 0xdc, 0xa3, 0xa8, 0x9c, 0x4c, 0xf0, 0x84, 0xda, 0xb9, - 0xb4, 0x6e, 0x04, 0xde, 0xa5, 0x3c, 0x9f, 0xa6, 0x60, 0x4b, 0xe3, 0x52, 0xa1, 0x94, 0x9d, 0x19, 0xd3, 0xa8, 0x93, - 0xf3, 0xd2, 0x1a, 0xeb, 0x36, 0x69, 0xc1, 0x18, 0x07, 0xa1, 0xfe, 0x74, 0xd6, 0x6f, 0xfe, 0x2d, 0x3f, 0x13, 0x52, - 0x39, 0x97, 0xdc, 0x3f, 0x64, 0x5a, 0xd5, 0xd4, 0x12, 0x68, 0x26, 0xd0, 0x0c, 0x7e, 0x2d, 0x90, 0xcf, 0x43, 0xb8, - 0x67, 0xfa, 0x2c, 0xc4, 0xfd, 0x20, 0x26, 0x1c, 0xb4, 0xf1, 0x86, 0x5e, 0xa3, 0x44, 0xea, 0xbf, 0x25, 0x03, 0x3a, - 0xb9, 0xc5, 0x42, 0xa9, 0x25, 0x89, 0xf3, 0xb5, 0x48, 0x75, 0xe7, 0xfb, 0xb8, 0x8e, 0x72, 0x41, 0x94, 0x74, 0xae, - 0x03, 0xdc, 0x27, 0x94, 0x73, 0x5a, 0x23, 0x6a, 0x24, 0xac, 0xd9, 0x4a, 0xe1, 0xd7, 0xe0, 0x41, 0x20, 0x3a, 0x80, - 0x84, 0xfd, 0xe1, 0xd5, 0xf6, 0x9a, 0xd9, 0xf9, 0xa0, 0x90, 0x05, 0xe2, 0x52, 0xb7, 0xdd, 0x62, 0x27, 0x21, 0x00, - 0xd1, 0x6d, 0x12, 0x0c, 0x14, 0xd4, 0x8e, 0xd3, 0x6f, 0xd0, 0xd0, 0x3b, 0xad, 0xec, 0xdd, 0xdd, 0x84, 0xa2, 0x08, - 0x21, 0x01, 0x12, 0x7b, 0xa0, 0xd2, 0x50, 0x10, 0x45, 0xcb, 0x41, 0x44, 0x28, 0xb1, 0xfb, 0xb8, 0x17, 0xa2, 0x82, - 0x1b, 0xe9, 0x88, 0x34, 0x62, 0xe8, 0x15, 0x6c, 0x88, 0x80, 0x40, 0x95, 0x87, 0x91, 0xc6, 0x2f, 0x09, 0x57, 0xb7, - 0x82, 0x4e, 0xd4, 0xc5, 0x9c, 0xb2, 0xb5, 0xf7, 0x20, 0x86, 0xe7, 0xb6, 0x92, 0x3e, 0x09, 0x42, 0xf4, 0x29, 0x98, - 0x43, 0x99, 0x7f, 0xca, 0x18, 0x63, 0x34, 0x90, 0xb3, 0x7d, 0x11, 0x22, 0x32, 0xb1, 0x9c, 0x51, 0x06, 0xa6, 0xd0, - 0x11, 0xb9, 0x44, 0x86, 0xfe, 0xe4, 0xe6, 0x8b, 0xda, 0x93, 0x1a, 0xc7, 0x75, 0xac, 0x5e, 0xaa, 0x67, 0x0d, 0xb6, - 0xa1, 0xf8, 0x47, 0xf2, 0xd8, 0x1c, 0x26, 0xe5, 0x17, 0x43, 0xd4, 0xe5, 0xec, 0xb0, 0xde, 0x43, 0x16, 0xab, 0xa2, - 0x01, 0x60, 0xb5, 0x5b, 0x61, 0x9d, 0x67, 0xa6, 0x7e, 0xa7, 0xcb, 0x1b, 0x5b, 0x5b, 0xb8, 0x45, 0x5d, 0xa8, 0x86, - 0x82, 0xf2, 0x6a, 0x50, 0x7f, 0xc2, 0xe8, 0x2f, 0x4f, 0x25, 0xe6, 0x19, 0x21, 0x99, 0xa7, 0xee, 0x1d, 0x7f, 0x09, - 0x8f, 0xc3, 0x96, 0x70, 0x75, 0xaa, 0xdb, 0x7f, 0xa9, 0xe2, 0xc9, 0xcc, 0xad, 0x46, 0xbe, 0x71, 0x0b, 0x85, 0x62, - 0x2f, 0x57, 0x23, 0xba, 0x0f, 0xad, 0xb2, 0x5f, 0xf6, 0x91, 0x6c, 0x84, 0x39, 0xcc, 0xe7, 0x63, 0x9f, 0x06, 0x1e, - 0x9f, 0x7b, 0xea, 0x78, 0x3b, 0xc0, 0x4d, 0x81, 0xcd, 0xd6, 0x81, 0xf0, 0x7c, 0x40, 0xf7, 0xd9, 0xa8, 0xc9, 0xba, - 0xd7, 0x45, 0x01, 0x62, 0x0b, 0x83, 0x2b, 0xad, 0x7f, 0xe4, 0x45, 0xd6, 0x17, 0x55, 0xa0, 0xed, 0x97, 0xe9, 0xbe, - 0x28, 0x0c, 0x0d, 0x4f, 0xbb, 0x8d, 0xd8, 0x63, 0x07, 0xcd, 0x92, 0xd6, 0x30, 0x79, 0x25, 0x1d, 0xe4, 0x6f, 0x62, - 0xb2, 0x48, 0x94, 0xbf, 0xfd, 0x35, 0x39, 0xc9, 0x5d, 0x6f, 0x76, 0x7b, 0x29, 0x6a, 0x2a, 0x4c, 0xfd, 0x5d, 0xfb, - 0xb0, 0x52, 0xff, 0x95, 0x7e, 0xb9, 0x0a, 0x75, 0x47, 0xd6, 0x82, 0x44, 0x4e, 0xc3, 0x90, 0x6b, 0x75, 0x58, 0x73, - 0xaa, 0xf3, 0x6c, 0x9d, 0xb5, 0x1d, 0x3e, 0x81, 0x9b, 0x25, 0x67, 0x09, 0x53, 0xf1, 0xa6, 0x26, 0x04, 0x87, 0x81, - 0xa0, 0x30, 0x5c, 0x14, 0x87, 0x48, 0x58, 0xbc, 0xd9, 0xe1, 0x85, 0xd3, 0x65, 0xb0, 0xf1, 0xd5, 0x7e, 0xa1, 0xcc, - 0x33, 0xb6, 0x0b, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x18, 0x35, 0xc0, 0xea, 0x9f, 0xf0, 0xf1, 0x7b, 0x12, 0xb6, 0x1e, - 0x74, 0x49, 0x6a, 0xd9, 0x54, 0x4a, 0x54, 0x5b, 0xc6, 0x35, 0xd6, 0x50, 0x71, 0xed, 0xf0, 0xc8, 0xea, 0x0c, 0xfd, - 0x47, 0xe7, 0x8b, 0xc4, 0x73, 0x48, 0x27, 0x8f, 0x56, 0x82, 0x68, 0x71, 0xcb, 0xba, 0xf5, 0xa1, 0xaf, 0xb9, 0x1c, - 0x85, 0x6d, 0x34, 0x94, 0xd2, 0x45, 0xbc, 0xa4, 0x76, 0x1d, 0x94, 0x81, 0xf4, 0x70, 0x65, 0xa2, 0xb3, 0x0f, 0xd4, - 0xb0, 0xee, 0x40, 0xe3, 0x4d, 0x8f, 0x29, 0xb4, 0xb1, 0xab, 0x16, 0xf3, 0x8a, 0xa9, 0x53, 0x74, 0x4b, 0x6c, 0x09, - 0xec, 0xae, 0xcb, 0xe1, 0xd6, 0xf4, 0x25, 0x10, 0x53, 0x4a, 0xc4, 0xb7, 0x5c, 0x6a, 0xee, 0xba, 0x8e, 0xe2, 0x13, - 0xb6, 0x42, 0x4b, 0xd6, 0xad, 0xc3, 0x6d, 0xac, 0xf5, 0x5a, 0x10, 0x52, 0xff, 0x52, 0x8b, 0x70, 0xf0, 0xea, 0x82, - 0x65, 0x5b, 0x7c, 0x74, 0xc2, 0x86, 0x16, 0x6d, 0x7b, 0x54, 0x41, 0x8b, 0x1d, 0x55, 0xe3, 0xa5, 0xcd, 0x5c, 0xe2, - 0x6a, 0x26, 0xc6, 0x37, 0xf4, 0xdb, 0x14, 0x07, 0x96, 0x9d, 0x15, 0xa0, 0xf1, 0xe0, 0xa4, 0xb7, 0x22, 0x2f, 0x35, - 0x3b, 0xa8, 0x99, 0x51, 0xcb, 0x67, 0x9a, 0x48, 0xeb, 0x05, 0xac, 0x11, 0xda, 0x5a, 0x7e, 0xe0, 0x8a, 0x13, 0x09, - 0xb6, 0x65, 0xfa, 0x7f, 0x98, 0x92, 0x56, 0x62, 0x47, 0x00, 0xcf, 0xb8, 0x8b, 0xfe, 0x81, 0x66, 0x05, 0x30, 0xa6, - 0x60, 0x26, 0x14, 0xf2, 0xb3, 0xe1, 0x08, 0x19, 0xdb, 0x3f, 0x69, 0x1f, 0x5b, 0x76, 0x73, 0x80, 0x00, 0x47, 0x96, - 0x81, 0x71, 0xef, 0x55, 0x2a, 0xda, 0xd3, 0x19, 0x8e, 0x51, 0xd5, 0xd2, 0x9a, 0xfb, 0x95, 0xaa, 0x24, 0x33, 0x60, - 0x37, 0x2f, 0x9a, 0xf6, 0xda, 0x22, 0x97, 0x28, 0xce, 0x90, 0xd5, 0xa9, 0x22, 0xb3, 0x30, 0xd6, 0xae, 0x92, 0x05, - 0x11, 0x1f, 0xfb, 0xc2, 0x19, 0xff, 0xd3, 0x94, 0xa0, 0xfc, 0xb8, 0xaf, 0xe9, 0xa4, 0x42, 0xa5, 0xb0, 0x8f, 0xcb, - 0x69, 0x7c, 0xc5, 0xc0, 0xa4, 0x02, 0x1b, 0x1a, 0xcc, 0x8f, 0x9b, 0x60, 0x50, 0x75, 0x00, 0x8f, 0x6e, 0x1a, 0xc5, - 0x5b, 0x06, 0xdf, 0x94, 0x2e, 0xb4, 0x1c, 0xe5, 0xa8, 0x1c, 0x70, 0xe6, 0xc8, 0xad, 0xc9, 0x4a, 0x04, 0x57, 0xd6, - 0x0e, 0x52, 0x54, 0x60, 0xb8, 0xb3, 0x6a, 0x90, 0xe6, 0xd2, 0x23, 0x25, 0xe3, 0xaf, 0x0b, 0xd0, 0x02, 0x08, 0xc3, - 0xca, 0xbf, 0xdc, 0x2c, 0xe3, 0x15, 0xca, 0x4a, 0xe9, 0x54, 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x7a, 0x3a, 0xe1, - 0x8d, 0xe7, 0x88, 0x73, 0x41, 0x50, 0x3b, 0xd5, 0x7c, 0x6f, 0x30, 0x0c, 0xea, 0xa4, 0x33, 0x40, 0x3e, 0x6a, 0x1a, - 0x4c, 0x78, 0x6d, 0xc9, 0xd1, 0x8b, 0xb8, 0xae, 0xc0, 0x72, 0x62, 0x67, 0x57, 0x09, 0x20, 0x97, 0xd6, 0xc2, 0x0e, - 0x32, 0x30, 0x96, 0xf1, 0xc7, 0x40, 0xee, 0xf8, 0xf4, 0x49, 0x69, 0xd9, 0x23, 0xeb, 0x95, 0x0d, 0x17, 0x9f, 0x7c, - 0x32, 0x7a, 0x83, 0xa5, 0xa2, 0xc9, 0xfd, 0x67, 0x63, 0x41, 0xdf, 0xc9, 0x06, 0x63, 0x2d, 0x3a, 0x07, 0x51, 0xae, - 0x42, 0x3b, 0xf2, 0x55, 0x59, 0x97, 0x05, 0xd9, 0xbe, 0x01, 0x29, 0x3f, 0xa7, 0x15, 0xa1, 0x54, 0x0b, 0x2a, 0x79, - 0x87, 0x55, 0x5c, 0x10, 0x42, 0xa9, 0x01, 0x07, 0x65, 0x08, 0x70, 0x94, 0x71, 0x77, 0xa7, 0x91, 0x00, 0x90, 0x8a, - 0xa1, 0x60, 0xce, 0x5c, 0xd6, 0xde, 0xe2, 0x02, 0x5b, 0x9c, 0x33, 0x73, 0x8d, 0xe1, 0x79, 0x2d, 0xcc, 0xd7, 0x1c, - 0x2b, 0x12, 0xc8, 0xda, 0x72, 0xba, 0x16, 0x5d, 0xaa, 0xa7, 0x47, 0x43, 0x81, 0xcc, 0x4a, 0x72, 0xee, 0xe5, 0xf3, - 0x0a, 0xa1, 0x95, 0xe4, 0xbf, 0x59, 0x62, 0x03, 0xc6, 0x38, 0xb1, 0x7f, 0x7c, 0xa1, 0x42, 0x7e, 0xe4, 0x71, 0xe3, - 0x90, 0x1f, 0x87, 0x13, 0x9c, 0x52, 0x02, 0x06, 0xb5, 0xf6, 0x39, 0x67, 0x7a, 0x63, 0xce, 0x44, 0x4c, 0x9c, 0xf0, - 0xf2, 0x3d, 0x7c, 0x64, 0xc0, 0x28, 0x45, 0xdb, 0x41, 0x45, 0xca, 0xb4, 0x02, 0x48, 0x68, 0xda, 0x1e, 0x5a, 0xaf, - 0xc5, 0xa4, 0xac, 0x98, 0xe2, 0x9a, 0xe6, 0x8a, 0xb7, 0xac, 0x1d, 0x35, 0xb5, 0x6f, 0x3c, 0x93, 0x78, 0x88, 0xe3, - 0xe7, 0x89, 0xaf, 0x13, 0x24, 0x84, 0x48, 0xa9, 0xf0, 0x17, 0x67, 0x5b, 0x3d, 0x7e, 0x49, 0xc5, 0xbd, 0xf0, 0x01, - 0x74, 0x8c, 0xa1, 0x31, 0x9b, 0x0a, 0x71, 0x43, 0x36, 0x43, 0xe2, 0xa8, 0x73, 0x23, 0xd3, 0xdd, 0x66, 0xd5, 0xe1, - 0xc3, 0xc9, 0xf2, 0xd3, 0xec, 0xb1, 0x17, 0x23, 0xc8, 0x60, 0xad, 0xd3, 0x8a, 0xdb, 0xe1, 0xb7, 0xff, 0x5b, 0xae, - 0x48, 0x8f, 0xea, 0xda, 0x22, 0xd1, 0xf9, 0x15, 0x12, 0x4c, 0x8b, 0xa4, 0xc8, 0xea, 0x5d, 0xca, 0x64, 0xdb, 0x2b, - 0x36, 0x5e, 0xcb, 0xe0, 0xb2, 0xb0, 0x38, 0x15, 0xf3, 0xcb, 0x5e, 0x8b, 0xc9, 0xae, 0xaf, 0x8b, 0xaf, 0xca, 0xcc, - 0x39, 0x56, 0x9e, 0x21, 0x8c, 0x85, 0xbd, 0x2e, 0x68, 0x53, 0x5a, 0xd8, 0x74, 0x50, 0x3d, 0x86, 0x29, 0xe3, 0xd1, - 0x6b, 0x47, 0x42, 0x7a, 0xa8, 0x75, 0xff, 0x26, 0xaf, 0xaf, 0xa3, 0xc2, 0x00, 0x10, 0x97, 0x22, 0x2c, 0x3c, 0x9e, - 0xc1, 0xe0, 0x12, 0x83, 0xc2, 0x3b, 0xec, 0xf4, 0xe2, 0x1a, 0xce, 0x3b, 0x37, 0xae, 0xd4, 0x72, 0x8a, 0x2d, 0x1d, - 0x27, 0x5f, 0x48, 0xcf, 0x7a, 0x45, 0x81, 0xbe, 0xa5, 0x66, 0x2d, 0x6e, 0xcd, 0x69, 0x0a, 0xc5, 0x90, 0xb2, 0xab, - 0xf6, 0x74, 0xef, 0xd4, 0xb5, 0x3d, 0x3b, 0x1f, 0xd6, 0x35, 0x45, 0xbb, 0x92, 0xa8, 0xf4, 0x1c, 0x91, 0x18, 0x2b, - 0x86, 0x76, 0xae, 0xad, 0xeb, 0xa2, 0x8e, 0x6a, 0xa8, 0xd6, 0x35, 0x46, 0xaa, 0x6e, 0x29, 0xd5, 0xbf, 0xd4, 0x7a, - 0x5c, 0x7a, 0x6d, 0x30, 0xf4, 0x9e, 0x3c, 0x8a, 0x97, 0x89, 0xba, 0x94, 0xdb, 0x4b, 0x9f, 0xea, 0x75, 0xbb, 0x7d, - 0xeb, 0xbb, 0xff, 0x53, 0xd0, 0xd6, 0xc5, 0x37, 0xf1, 0x3f, 0xc8, 0xff, 0x67, 0x0f, 0x18, 0x5b, 0x7c, 0x7c, 0x38, - 0xae, 0xb4, 0x59, 0x57, 0x36, 0x39, 0x25, 0x8f, 0x9d, 0x6f, 0xfa, 0x8a, 0xa5, 0x83, 0xba, 0xbb, 0x3b, 0x39, 0x0b, - 0x0e, 0x9b, 0x33, 0x47, 0x30, 0x50, 0x94, 0xc9, 0xcd, 0x95, 0xd1, 0xa6, 0xeb, 0x74, 0xa9, 0xc3, 0x2f, 0x4b, 0x93, - 0x90, 0xbd, 0xc6, 0x4b, 0x8c, 0x60, 0x9e, 0x4b, 0x99, 0xd8, 0x02, 0x5e, 0x39, 0x43, 0x51, 0x0f, 0x1d, 0x5b, 0x4a, - 0x30, 0x65, 0xd5, 0x20, 0x3e, 0xcb, 0x14, 0xcf, 0x51, 0x65, 0x1a, 0xd5, 0x73, 0xf7, 0xa6, 0x07, 0x8c, 0xc8, 0xc8, - 0xd9, 0xaf, 0x32, 0xeb, 0x42, 0x07, 0xeb, 0xf6, 0x6c, 0x7f, 0xc4, 0xb3, 0x52, 0x62, 0xc0, 0xbd, 0xb3, 0x01, 0xb1, - 0x43, 0x63, 0x95, 0x43, 0xa1, 0xf8, 0xc7, 0xad, 0x70, 0x99, 0xa8, 0xcf, 0x78, 0xcb, 0x5e, 0xb2, 0xb8, 0x0d, 0xcd, - 0xac, 0x43, 0xbe, 0x33, 0x15, 0x44, 0xec, 0x5d, 0xa7, 0xea, 0x39, 0x42, 0xd6, 0x94, 0x7a, 0xfc, 0x59, 0xa2, 0x2c, - 0x8d, 0xa8, 0xc4, 0xd1, 0xa8, 0x1a, 0x0b, 0xff, 0x77, 0xe6, 0x12, 0xdd, 0xc9, 0xfe, 0x19, 0x61, 0xe6, 0xbe, 0x22, - 0x56, 0x2e, 0xe1, 0x84, 0xe9, 0xd5, 0x36, 0x9d, 0x15, 0x22, 0x28, 0xe0, 0xf3, 0x45, 0xef, 0xcd, 0xa6, 0x2e, 0x04, - 0x8d, 0x77, 0x79, 0xde, 0x85, 0xf9, 0x8c, 0xdc, 0x08, 0xcd, 0x34, 0xac, 0x4d, 0x89, 0x72, 0x10, 0xb8, 0xe8, 0x09, - 0x34, 0xe7, 0x32, 0x30, 0xc1, 0x34, 0x2f, 0xb6, 0x7e, 0xd2, 0xd6, 0x99, 0x1e, 0x48, 0x43, 0x8c, 0x5a, 0x64, 0x9e, - 0xde, 0x95, 0xa6, 0x8f, 0xe9, 0xac, 0xd2, 0x3a, 0x6b, 0x03, 0x2b, 0x7e, 0x40, 0x31, 0x13, 0x41, 0xab, 0x97, 0x24, - 0xa9, 0xa0, 0x39, 0xb4, 0xe8, 0x65, 0xaf, 0x3a, 0x49, 0x41, 0xdd, 0xa9, 0x25, 0xe3, 0x82, 0xb0, 0xaf, 0x6d, 0xf7, - 0x84, 0xcc, 0x51, 0xb4, 0x41, 0x9a, 0x92, 0x4b, 0xbe, 0x47, 0x5c, 0x65, 0x3c, 0xff, 0xbc, 0x50, 0xf8, 0x02, 0x58, - 0x6e, 0x7f, 0x57, 0x96, 0xc3, 0xa2, 0x2e, 0x16, 0xbf, 0x9c, 0x80, 0x35, 0xf2, 0x8f, 0xe1, 0xfe, 0x28, 0x20, 0x1a, - 0x7e, 0x56, 0xb0, 0x3b, 0x68, 0xb3, 0x5f, 0x8c, 0xb3, 0xdd, 0xc7, 0xbd, 0xc5, 0x6e, 0xb8, 0xec, 0xf8, 0xcb, 0x27, - 0xeb, 0xf6, 0xb4, 0x07, 0xae, 0x0d, 0x83, 0xdb, 0x5f, 0x9c, 0xbf, 0xa6, 0xc1, 0xf3, 0x2d, 0x63, 0x37, 0x5b, 0xf9, - 0x90, 0xdf, 0xa3, 0xdc, 0xa9, 0xcb, 0xe5, 0x52, 0xd4, 0x10, 0x90, 0x6a, 0xe6, 0x9c, 0xb8, 0x7e, 0x52, 0x90, 0x16, - 0x68, 0x61, 0x4a, 0x47, 0xb7, 0x24, 0xde, 0x8b, 0x86, 0xac, 0x37, 0x17, 0x60, 0xd3, 0x6d, 0x2f, 0x90, 0x4a, 0x8a, - 0x99, 0x22, 0x2d, 0x26, 0x14, 0x3f, 0xe7, 0xa8, 0x93, 0x3b, 0xb8, 0x2f, 0xa1, 0x4d, 0x64, 0x58, 0x77, 0x93, 0x71, - 0xfe, 0x54, 0xed, 0x09, 0x3d, 0x6e, 0x18, 0xab, 0x43, 0x7e, 0x8b, 0x34, 0xa0, 0xf7, 0xe3, 0x99, 0x14, 0xd9, 0x0f, - 0x83, 0x02, 0xf8, 0xd4, 0x55, 0x40, 0xb5, 0x40, 0xbf, 0xe5, 0xe3, 0x89, 0x4c, 0x19, 0xc4, 0xa8, 0xec, 0x0d, 0xd0, - 0x48, 0x50, 0x64, 0x9b, 0xb2, 0x78, 0x3f, 0x2d, 0x08, 0xe8, 0x43, 0x09, 0x9d, 0xe9, 0x93, 0x0c, 0x11, 0xd5, 0x15, - 0x3c, 0xcc, 0xe9, 0x4e, 0xf8, 0xa6, 0xce, 0x87, 0xcf, 0x9d, 0xb1, 0xe7, 0x2d, 0xed, 0x0a, 0x5b, 0x86, 0x69, 0x68, - 0xa8, 0x82, 0x71, 0xe8, 0x5e, 0xb4, 0xf4, 0x14, 0xb7, 0xa1, 0xe4, 0xe3, 0xf1, 0xe7, 0xf2, 0xcb, 0x44, 0xd4, 0xdf, - 0x26, 0x32, 0xcc, 0x08, 0x7a, 0x66, 0x51, 0x2f, 0xae, 0x70, 0x61, 0x74, 0xba, 0x6a, 0x20, 0x68, 0x79, 0xbf, 0xad, - 0x07, 0xd7, 0xf9, 0x31, 0xdc, 0x38, 0x57, 0x89, 0x36, 0x4e, 0xe3, 0xde, 0x6f, 0x50, 0x5c, 0x2e, 0x71, 0xd0, 0xe5, - 0x05, 0x12, 0xdf, 0x07, 0xd7, 0x76, 0x59, 0xed, 0x6d, 0xaa, 0xf9, 0xcb, 0x7a, 0xe5, 0x0d, 0x09, 0x3b, 0x6f, 0x12, - 0x0e, 0xa4, 0x84, 0x0c, 0x27, 0x1f, 0x91, 0x5c, 0xd8, 0xa0, 0x4b, 0x3e, 0xde, 0xd2, 0xd0, 0x51, 0xc3, 0x8a, 0x68, - 0x17, 0x7e, 0xc3, 0x8f, 0x75, 0x5b, 0x88, 0x20, 0x6e, 0xb0, 0x4c, 0x00, 0xcf, 0x48, 0xe6, 0x44, 0x56, 0x75, 0x98, - 0xc0, 0x34, 0x97, 0x30, 0x0d, 0xec, 0xb6, 0x01, 0x34, 0x3e, 0x99, 0x94, 0xb8, 0x02, 0xdd, 0x2c, 0xd5, 0xce, 0xab, - 0x92, 0x8c, 0xfd, 0x85, 0xa0, 0x9d, 0xeb, 0x0f, 0x8f, 0x32, 0x2f, 0xb7, 0x9b, 0x5d, 0xa4, 0x79, 0x39, 0xc5, 0xd0, - 0x0e, 0x64, 0x76, 0x35, 0x0c, 0x99, 0xba, 0x4b, 0xea, 0x3c, 0x38, 0xa9, 0x2e, 0x0c, 0xc2, 0x21, 0x5c, 0x91, 0xa6, - 0x35, 0x17, 0x84, 0x59, 0x74, 0x6b, 0x0a, 0xef, 0x76, 0xc0, 0xd5, 0x12, 0x01, 0x25, 0x88, 0x38, 0xe9, 0x45, 0x87, - 0x55, 0x3c, 0xb8, 0x1b, 0x75, 0x67, 0x90, 0x96, 0x95, 0x8b, 0x95, 0x62, 0x7c, 0xa1, 0xc5, 0x9d, 0x60, 0x5a, 0x05, - 0xf7, 0x7e, 0x20, 0x46, 0x7b, 0xbe, 0x16, 0x4a, 0x1e, 0x63, 0xa4, 0xa2, 0x3c, 0xfa, 0xf6, 0x43, 0x4a, 0x7e, 0xd4, - 0xf0, 0x58, 0x2b, 0x94, 0x2a, 0x76, 0xea, 0xda, 0x05, 0x9d, 0x95, 0x08, 0xbb, 0x2c, 0x13, 0x2f, 0xa1, 0xdf, 0xd5, - 0xb0, 0xdb, 0x32, 0x1b, 0xbb, 0x40, 0xdc, 0x9e, 0x44, 0x4a, 0xe4, 0x60, 0xad, 0xe1, 0x1d, 0xc9, 0xf3, 0x34, 0x78, - 0x5b, 0x72, 0xeb, 0x97, 0x0c, 0xc5, 0xad, 0xb6, 0x60, 0xf1, 0x43, 0x7a, 0x74, 0x44, 0x01, 0xaa, 0x7f, 0xd3, 0x91, - 0x20, 0x71, 0xcb, 0x8c, 0xdf, 0x55, 0xe5, 0xe6, 0xb9, 0xb9, 0xe1, 0x59, 0x62, 0x55, 0xc4, 0xc2, 0xf9, 0xfb, 0x1a, - 0x20, 0x50, 0x48, 0x67, 0x33, 0xd7, 0x3c, 0x12, 0x75, 0xc5, 0xf5, 0xe0, 0x4e, 0x65, 0x4c, 0xdd, 0xa7, 0x23, 0xd5, - 0x1b, 0xee, 0x6a, 0x6c, 0xa9, 0x25, 0xbc, 0xa9, 0xb0, 0xa5, 0x3b, 0xcd, 0x15, 0x5b, 0x5c, 0xe6, 0x2a, 0xb5, 0x9d, - 0xc0, 0xb4, 0x6b, 0x9d, 0xfe, 0x38, 0x86, 0x1a, 0xca, 0x44, 0xdc, 0x26, 0xea, 0xe0, 0xb2, 0x6c, 0x8a, 0x72, 0x97, - 0x09, 0x4e, 0x92, 0x0d, 0xee, 0x80, 0x48, 0xd5, 0xe2, 0x32, 0xc7, 0x4d, 0x1b, 0x22, 0xc5, 0x77, 0xd2, 0x35, 0x45, - 0x52, 0x9c, 0xa6, 0x17, 0x9e, 0x46, 0x56, 0x6e, 0x76, 0x4a, 0x33, 0xe9, 0x1d, 0x52, 0x64, 0x45, 0x21, 0x71, 0xaf, - 0x22, 0x05, 0x0f, 0xad, 0xfa, 0xb3, 0xcc, 0x29, 0xd9, 0xc1, 0xf4, 0x6e, 0xb9, 0xee, 0xef, 0xc3, 0xc7, 0xf3, 0xf5, - 0x48, 0x44, 0x17, 0xc6, 0x57, 0x4a, 0x48, 0x56, 0x72, 0x90, 0x84, 0xbc, 0xe0, 0x90, 0xce, 0x5e, 0x15, 0x09, 0x38, - 0xd2, 0x2b, 0x17, 0x69, 0x5d, 0xb9, 0x56, 0x05, 0xda, 0xc1, 0x72, 0xca, 0xa8, 0x10, 0x33, 0x63, 0x8d, 0xe2, 0xfd, - 0x38, 0xbc, 0x3b, 0x1e, 0xa4, 0x3b, 0x92, 0x4d, 0xcd, 0x5c, 0x77, 0x28, 0x71, 0x19, 0x2a, 0x38, 0x12, 0x27, 0x2a, - 0x87, 0xe0, 0xe8, 0xcc, 0xf5, 0x1e, 0x0b, 0xeb, 0x0a, 0xe6, 0xcc, 0x79, 0x96, 0x07, 0xab, 0xab, 0xf5, 0x17, 0xee, - 0x7a, 0xfd, 0x7a, 0x22, 0xfa, 0x9d, 0x97, 0x9a, 0x6a, 0x80, 0x87, 0x16, 0xdb, 0x75, 0x3c, 0x8d, 0x29, 0xd0, 0x02, - 0xe9, 0xd5, 0x04, 0x45, 0xc3, 0x27, 0xcd, 0x30, 0x07, 0x3d, 0xd5, 0x37, 0x6f, 0xa3, 0x66, 0xb6, 0x65, 0x9a, 0x56, - 0x18, 0x66, 0x97, 0x06, 0xee, 0x4c, 0x72, 0x0d, 0x31, 0x6c, 0xfd, 0x7a, 0xb6, 0x4d, 0xe4, 0x72, 0xdf, 0xb3, 0x5a, - 0x08, 0xa6, 0xe9, 0x98, 0x23, 0xff, 0x3e, 0xc9, 0x61, 0xc2, 0x71, 0x0c, 0x4a, 0x4f, 0xbc, 0x2c, 0xc5, 0x2c, 0x27, - 0x61, 0x65, 0x5d, 0x5d, 0xc0, 0xf5, 0x64, 0x24, 0x02, 0xf1, 0x28, 0xb5, 0x58, 0x7e, 0x00, 0xd7, 0x54, 0x5e, 0xef, - 0x68, 0x63, 0x0f, 0x04, 0x00, 0xcb, 0xf6, 0xcc, 0x49, 0xaf, 0x1a, 0xf9, 0x2a, 0xa6, 0x90, 0x5c, 0xbe, 0x93, 0x4c, - 0x46, 0x04, 0xfb, 0x2a, 0xbd, 0xbf, 0xa0, 0x1f, 0xd4, 0xde, 0x8e, 0x10, 0xd1, 0x8b, 0x84, 0xfd, 0x72, 0x9b, 0x26, - 0x21, 0x0e, 0x5f, 0x98, 0x88, 0x8d, 0x0b, 0xd8, 0x8a, 0xd0, 0x97, 0xc7, 0x56, 0x26, 0xf3, 0xba, 0xeb, 0xf0, 0xfb, - 0x2d, 0x1f, 0xdc, 0x18, 0xc1, 0x24, 0xb2, 0x25, 0x02, 0x0b, 0x91, 0xca, 0x98, 0x28, 0xbe, 0x08, 0x3f, 0x57, 0xfb, - 0xbe, 0x51, 0x4c, 0x25, 0x9b, 0x3d, 0xdf, 0xf1, 0xee, 0x78, 0xfa, 0xae, 0xf5, 0xeb, 0xac, 0x90, 0x21, 0xd3, 0x5e, - 0xf7, 0x0f, 0x00, 0x3d, 0xf3, 0xa6, 0xbc, 0x9d, 0xcc, 0x77, 0x92, 0x76, 0x95, 0x36, 0xef, 0x34, 0xd1, 0xc0, 0xaf, - 0xbf, 0x11, 0x7a, 0xc5, 0x57, 0x9a, 0x88, 0x7e, 0xd5, 0x0b, 0x36, 0xab, 0xa8, 0x90, 0x67, 0xae, 0xc3, 0x9a, 0xf5, - 0xed, 0x1c, 0x9a, 0xbe, 0x29, 0xa5, 0x39, 0x4f, 0x06, 0x53, 0x87, 0xf4, 0x55, 0x46, 0x75, 0x30, 0xa0, 0xb9, 0x83, - 0x0d, 0xd2, 0xdf, 0x00, 0xcf, 0xb9, 0x83, 0x00, 0x27, 0x8a, 0x24, 0x0d, 0xbf, 0x74, 0xf3, 0x2a, 0x9a, 0x3c, 0x8c, - 0x9a, 0x0c, 0xc5, 0x65, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x43, 0x83, 0xa8, 0xb3, 0xf7, 0x88, 0xdd, 0x5e, 0xda, 0x7b, - 0xf0, 0x9f, 0x3e, 0x50, 0xb2, 0x2e, 0x42, 0xc5, 0x60, 0x42, 0xf9, 0x4b, 0xd9, 0x2f, 0x69, 0xcf, 0x4a, 0x57, 0xe6, - 0x42, 0xc1, 0xbc, 0x36, 0xa8, 0xc6, 0x01, 0x2c, 0xa0, 0xbd, 0x48, 0x40, 0xc5, 0x6e, 0x2b, 0x6c, 0xc8, 0x04, 0xdb, - 0x4f, 0x62, 0x5d, 0x89, 0x1f, 0x0a, 0x70, 0xf8, 0x9b, 0x86, 0x90, 0x84, 0x2c, 0xe6, 0x7e, 0x9d, 0x97, 0x6d, 0x5b, - 0xc7, 0x6d, 0xcc, 0xe6, 0x91, 0xbc, 0x8d, 0xb0, 0x9c, 0xf0, 0xe6, 0x7f, 0x98, 0x07, 0xe2, 0xb2, 0xea, 0x6f, 0x6b, - 0xbb, 0xb4, 0xa3, 0xd7, 0x61, 0x58, 0x89, 0xad, 0x62, 0xf9, 0x87, 0xb9, 0xea, 0xb1, 0x03, 0xb8, 0xbf, 0x87, 0xca, - 0xf0, 0x96, 0xe6, 0x86, 0xb7, 0xe3, 0x79, 0xa9, 0x41, 0xf6, 0x99, 0x8a, 0x24, 0x9c, 0xd2, 0xfd, 0x8a, 0x64, 0x48, - 0x13, 0x89, 0x1e, 0x3d, 0xc9, 0x47, 0x1a, 0x0f, 0xab, 0x94, 0x6d, 0xe8, 0xb0, 0xd9, 0xee, 0xa0, 0xf3, 0xf6, 0xb9, - 0xfb, 0xcb, 0xa9, 0xb7, 0x40, 0xb5, 0x4e, 0x61, 0xf3, 0xd2, 0xc3, 0x16, 0x5b, 0xf7, 0x2c, 0xa6, 0x7e, 0x0a, 0xb2, - 0x72, 0x24, 0x1b, 0x62, 0x22, 0xdd, 0x3b, 0x2d, 0x9e, 0x79, 0x94, 0xc0, 0xdd, 0x4d, 0x7d, 0x73, 0xec, 0xe3, 0x79, - 0xc9, 0x1f, 0xb3, 0x33, 0xdc, 0xf3, 0xa1, 0x97, 0xef, 0x59, 0x91, 0x3b, 0x62, 0xa7, 0xa3, 0x78, 0xc8, 0x45, 0x77, - 0x42, 0x59, 0x09, 0xcb, 0xf9, 0xb9, 0x6a, 0xa5, 0x36, 0x06, 0xa5, 0x42, 0x59, 0x96, 0x7b, 0x9f, 0x6c, 0xdd, 0x41, - 0x42, 0x95, 0xef, 0x41, 0x49, 0xe0, 0xf7, 0x49, 0x04, 0x52, 0xfd, 0xa3, 0x54, 0x21, 0x66, 0xcc, 0x4b, 0x33, 0x2f, - 0xd4, 0x9f, 0x50, 0xca, 0x81, 0x87, 0x80, 0x6f, 0x09, 0xb8, 0x34, 0xb4, 0xf5, 0xdf, 0x6d, 0x18, 0xd3, 0xb2, 0x1f, - 0x6b, 0xf4, 0xf7, 0x14, 0xf8, 0xbd, 0x06, 0xee, 0x89, 0x3a, 0x3f, 0x9d, 0x62, 0xf0, 0x68, 0xa1, 0xd7, 0xb7, 0xd3, - 0x7d, 0xc3, 0xd4, 0x78, 0xe5, 0x42, 0xf1, 0xad, 0x4d, 0xe5, 0x8f, 0xa1, 0x76, 0x5d, 0x0b, 0x4d, 0xf6, 0x42, 0x39, - 0x53, 0x8a, 0xb3, 0xc2, 0x9b, 0x06, 0x43, 0x2b, 0x1e, 0x49, 0xb5, 0xc4, 0x39, 0x7b, 0x8f, 0x5d, 0xc5, 0x09, 0xef, - 0x48, 0x03, 0x05, 0x2a, 0x99, 0x05, 0x47, 0x0c, 0x94, 0xf6, 0x65, 0x7d, 0x99, 0xee, 0xf6, 0x63, 0x2d, 0xee, 0xe0, - 0x78, 0x84, 0xaa, 0x22, 0x5f, 0x21, 0x27, 0x1e, 0x39, 0x90, 0x28, 0xf5, 0xfc, 0x26, 0xaa, 0xd0, 0xfc, 0x74, 0xa2, - 0x68, 0x7f, 0x97, 0x0d, 0xad, 0xe8, 0x3f, 0x1b, 0xfe, 0xec, 0x11, 0x20, 0x8f, 0x73, 0xd2, 0xf7, 0x09, 0xb6, 0x4c, - 0x88, 0xc6, 0xe5, 0xd8, 0xb7, 0x35, 0x78, 0x5e, 0x6a, 0xb4, 0x58, 0xf4, 0x72, 0x21, 0xfb, 0x8d, 0xd9, 0x58, 0x89, - 0x39, 0x73, 0xe1, 0x8d, 0x3b, 0xa1, 0xe1, 0x37, 0x0c, 0xa4, 0xf7, 0xb0, 0x9e, 0x84, 0x99, 0x66, 0x01, 0x28, 0x35, - 0xb4, 0xd0, 0x47, 0x8b, 0x9d, 0xeb, 0x3c, 0x39, 0xde, 0xf0, 0xa6, 0x14, 0x01, 0xe3, 0xeb, 0xfb, 0x1b, 0x42, 0x33, - 0x50, 0x24, 0x25, 0x62, 0x3e, 0x01, 0x8c, 0x62, 0x30, 0x6a, 0xaa, 0xd7, 0xe3, 0x01, 0x9f, 0x60, 0x10, 0x5f, 0x6c, - 0x7d, 0x79, 0x33, 0x6e, 0x20, 0xee, 0x86, 0xb3, 0x94, 0x4f, 0xc9, 0x77, 0x23, 0x01, 0x8c, 0x97, 0x7f, 0x02, 0x54, - 0x17, 0x5a, 0x6d, 0xb0, 0xbf, 0x13, 0xdb, 0x71, 0x7e, 0x01, 0x4d, 0xf0, 0x35, 0xd8, 0x05, 0x3f, 0x8e, 0x7f, 0x28, - 0xac, 0x6e, 0xa4, 0xa5, 0x5e, 0x4e, 0x47, 0x7d, 0xb6, 0x99, 0xf9, 0x00, 0x1b, 0xce, 0x37, 0x0f, 0x1b, 0xe5, 0xfa, - 0x8b, 0x09, 0x03, 0xf3, 0xca, 0x09, 0xa5, 0x9b, 0x23, 0x99, 0x5f, 0x32, 0xac, 0xcd, 0x1a, 0xfa, 0x5c, 0x4e, 0x5c, - 0xf2, 0x2d, 0x90, 0x6b, 0xa4, 0xda, 0x6f, 0xf1, 0xf2, 0x1b, 0xa4, 0x1e, 0x96, 0xef, 0x7f, 0x56, 0x4a, 0x17, 0xb1, - 0xa9, 0xcd, 0x7e, 0xe4, 0xb8, 0x4b, 0x9f, 0xcb, 0x93, 0xcf, 0x90, 0xfd, 0xd9, 0x1c, 0xf2, 0x79, 0x7f, 0xb5, 0x7b, - 0xb7, 0xfc, 0x33, 0x9b, 0xed, 0xc5, 0x66, 0xd7, 0xdb, 0xbb, 0xf9, 0x33, 0xf8, 0x3a, 0xfc, 0x1e, 0xc1, 0x6a, 0x6e, - 0x0f, 0x0a, 0x3e, 0x4c, 0xdf, 0xfc, 0xd7, 0x6f, 0xf6, 0x83, 0x81, 0x66, 0x1f, 0xa2, 0x00, 0x57, 0x88, 0xa8, 0x72, - 0x66, 0x5c, 0xc3, 0xae, 0xb8, 0xc7, 0xf6, 0x38, 0xe5, 0x7c, 0x5f, 0x9b, 0x50, 0x6e, 0xb3, 0x98, 0x36, 0x2b, 0x57, - 0x57, 0x38, 0x13, 0xdd, 0xfa, 0x86, 0x5d, 0x08, 0xc9, 0xf2, 0xed, 0x5d, 0xc0, 0x43, 0x31, 0x2a, 0xec, 0xed, 0xb9, - 0xe7, 0xe5, 0xc0, 0x9f, 0xa1, 0xbc, 0xc6, 0x4b, 0xab, 0xdf, 0xfa, 0x5c, 0xec, 0xa1, 0x0f, 0x78, 0x33, 0x7e, 0x2b, - 0xa8, 0xce, 0x7c, 0x16, 0x9a, 0x2c, 0x2e, 0xc4, 0x97, 0xba, 0xc1, 0x25, 0xf4, 0x32, 0xc7, 0x64, 0x03, 0x5f, 0x3a, - 0x5c, 0x55, 0xc8, 0x3c, 0xb4, 0x64, 0x94, 0x47, 0x6c, 0x39, 0x31, 0x73, 0xb7, 0x9a, 0x64, 0x5a, 0x99, 0x1f, 0xdd, - 0xc8, 0xc1, 0x83, 0x12, 0x92, 0x74, 0x65, 0x08, 0xff, 0x18, 0x27, 0xee, 0x45, 0xb0, 0xf1, 0x5e, 0x58, 0x8b, 0x76, - 0xf5, 0x50, 0x35, 0xeb, 0x26, 0x68, 0xd6, 0xa9, 0x1e, 0xef, 0x84, 0xbf, 0xa7, 0x7f, 0x3c, 0xd3, 0x46, 0xf8, 0xf3, - 0x99, 0x56, 0xc2, 0x1f, 0xa7, 0x8a, 0x09, 0x7f, 0x9e, 0xea, 0xcc, 0xd4, 0xfa, 0xc2, 0xbe, 0x7e, 0x63, 0x5f, 0xdf, - 0xd9, 0x63, 0xa0, 0xf6, 0xd0, 0xde, 0xcb, 0x1c, 0xb4, 0x13, 0x7b, 0x5b, 0x6f, 0xc9, 0x21, 0x9f, 0xcb, 0x2a, 0x4b, - 0x36, 0x3f, 0x37, 0xba, 0xfb, 0x9c, 0xca, 0xc2, 0xe3, 0x01, 0xca, 0x1a, 0x8f, 0xa3, 0xba, 0x16, 0x51, 0x31, 0x67, - 0x96, 0xb4, 0x5e, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x4e, 0x1c, 0x43, 0x0e, 0xaa, 0x86, 0x33, 0x52, 0x99, 0x20, 0x7f, - 0x34, 0xfd, 0xd8, 0x28, 0xf7, 0xa2, 0xf1, 0xc2, 0xdd, 0x3d, 0x53, 0x9e, 0xbf, 0x92, 0x46, 0x44, 0xa6, 0x15, 0xf8, - 0xde, 0xc1, 0x34, 0x2c, 0x66, 0x2d, 0x36, 0x3b, 0x20, 0xb3, 0x23, 0x7a, 0x09, 0x05, 0x42, 0xe8, 0xdb, 0x16, 0xfe, - 0xb3, 0x00, 0xa5, 0x62, 0x57, 0x46, 0x89, 0x78, 0x5c, 0x83, 0xa2, 0xd6, 0x5b, 0xd0, 0x20, 0x76, 0x43, 0x99, 0xee, - 0x88, 0x31, 0x87, 0x97, 0x55, 0x5c, 0x41, 0x56, 0xbf, 0x9c, 0x8b, 0x5f, 0xe7, 0xec, 0xe1, 0xf9, 0x46, 0x40, 0x83, - 0xff, 0xd7, 0x64, 0x3b, 0xe8, 0x4f, 0x68, 0x6b, 0x9c, 0x72, 0x49, 0xa5, 0xfd, 0x42, 0xce, 0xdb, 0x73, 0x5f, 0x67, - 0xd7, 0xb7, 0xce, 0x18, 0xc9, 0xcf, 0x39, 0x04, 0x72, 0x57, 0xed, 0xa7, 0xbb, 0x7d, 0x4c, 0x41, 0x56, 0x5d, 0xf7, - 0x9c, 0x60, 0x9d, 0x9d, 0xa9, 0xd4, 0xcd, 0x94, 0xfc, 0xfc, 0xd5, 0xff, 0xb2, 0xbf, 0x4f, 0xc9, 0x87, 0x7d, 0xad, - 0xd7, 0xfc, 0x72, 0x2c, 0xe7, 0x53, 0xaf, 0xf3, 0xf9, 0xfd, 0x17, 0xe5, 0x74, 0x3d, 0xa4, 0xe9, 0x38, 0xdd, 0xf5, - 0x8f, 0xe9, 0x82, 0x7e, 0xe9, 0x3e, 0x9b, 0xfe, 0x7a, 0x4a, 0x3e, 0xe4, 0x1b, 0xbd, 0x7e, 0x72, 0x97, 0x16, 0xff, - 0xa9, 0xe9, 0x72, 0x64, 0x0b, 0x00, 0xe5, 0xf9, 0x51, 0xb2, 0x39, 0x0e, 0x39, 0xd3, 0x3b, 0xd7, 0x15, 0xb6, 0xa8, - 0x5a, 0x0d, 0x8e, 0x5c, 0xac, 0x40, 0x8b, 0x7c, 0xc2, 0x13, 0xd9, 0xf8, 0x06, 0xec, 0x52, 0x66, 0xef, 0xb1, 0x0a, - 0xa4, 0xdb, 0xe6, 0xd3, 0x6c, 0x26, 0xcf, 0x5f, 0xa3, 0x6d, 0x76, 0x0d, 0xcb, 0x4c, 0xda, 0xd2, 0x54, 0x5c, 0x79, - 0xc0, 0x81, 0x03, 0x14, 0x06, 0xab, 0x91, 0x3a, 0x00, 0x46, 0x4e, 0xef, 0x30, 0xf4, 0xd9, 0x38, 0xce, 0xde, 0x6f, - 0x63, 0xc6, 0x52, 0x78, 0xec, 0xc8, 0xa2, 0x19, 0xed, 0xf0, 0x09, 0x37, 0xfd, 0x69, 0x26, 0xd4, 0x8f, 0x06, 0xe0, - 0xc4, 0x59, 0x36, 0x5d, 0x7f, 0xbb, 0x4f, 0x3c, 0xeb, 0x5a, 0xae, 0xac, 0x3f, 0x94, 0xd0, 0xb5, 0x39, 0x3a, 0x93, - 0xdc, 0x25, 0xa8, 0x30, 0xc2, 0x9c, 0xe1, 0xc5, 0x7b, 0xb3, 0x3a, 0xa5, 0x48, 0x7d, 0xa2, 0xd7, 0x82, 0x90, 0xd1, - 0x7f, 0x32, 0x98, 0xc6, 0x91, 0x1c, 0xb9, 0x3e, 0xf6, 0xef, 0x31, 0x43, 0xdb, 0xcc, 0xa8, 0xb7, 0x1a, 0x3b, 0x20, - 0xd2, 0xc0, 0x2a, 0x59, 0x63, 0x7d, 0x4b, 0xfc, 0x6b, 0x90, 0xeb, 0x34, 0x6b, 0x3c, 0xc3, 0xd9, 0x99, 0xb6, 0x27, - 0x3b, 0xdd, 0xcc, 0xdc, 0xaf, 0xb7, 0x3f, 0x8f, 0xdf, 0xdb, 0xef, 0x87, 0x71, 0xe9, 0x48, 0x0b, 0x72, 0xd3, 0x62, - 0xab, 0x7a, 0x6c, 0x9d, 0x4c, 0xcb, 0x0f, 0xd5, 0x8f, 0x0d, 0x0a, 0xc4, 0x18, 0xe7, 0x35, 0xd2, 0x8c, 0xcf, 0xf2, - 0x36, 0x2e, 0xc8, 0x82, 0x0d, 0x71, 0x3e, 0xdc, 0xde, 0x3e, 0x0a, 0xb2, 0x03, 0x4d, 0x7e, 0xf3, 0x0e, 0xdd, 0xd7, - 0x7e, 0xe7, 0x77, 0xa0, 0x98, 0xf5, 0xed, 0x25, 0xd5, 0x06, 0x75, 0x05, 0x7a, 0x03, 0x2e, 0xbf, 0x68, 0x13, 0xe6, - 0xae, 0xe1, 0xbc, 0xfc, 0x19, 0x0b, 0x49, 0x28, 0x5a, 0x29, 0x38, 0x2c, 0x36, 0xcd, 0x28, 0x4a, 0x8b, 0x75, 0xd1, - 0xaf, 0x6d, 0xc6, 0x9b, 0x6b, 0x37, 0x70, 0x6e, 0x10, 0x64, 0x31, 0x6b, 0x45, 0x3f, 0x46, 0xe4, 0x5d, 0xd6, 0xcc, - 0x56, 0xdb, 0x40, 0x0c, 0x2f, 0x71, 0xcd, 0x5a, 0x6c, 0x77, 0xcf, 0x60, 0x40, 0x8f, 0xf8, 0xe8, 0x1c, 0x82, 0x47, - 0x1e, 0x7a, 0x2c, 0x7e, 0x37, 0xa5, 0xc3, 0x3b, 0xc7, 0x5a, 0x0a, 0x91, 0xe5, 0x64, 0xfa, 0xc7, 0xa9, 0xcd, 0xc8, - 0xd3, 0x11, 0x25, 0x43, 0xa2, 0xfa, 0xc6, 0x3e, 0xfb, 0xd1, 0x20, 0xad, 0x3d, 0x9b, 0x35, 0x8e, 0x17, 0x2c, 0xad, - 0x0f, 0x8e, 0x87, 0x71, 0x1c, 0xa4, 0xa8, 0xa9, 0xac, 0xe2, 0x1f, 0x93, 0x61, 0x91, 0xae, 0xd9, 0x7e, 0x57, 0x06, - 0xaf, 0x84, 0x84, 0xae, 0x5c, 0x7b, 0x2d, 0x40, 0xc7, 0x2e, 0x6b, 0xf9, 0x33, 0xa7, 0x0b, 0x01, 0x2a, 0xbf, 0x08, - 0x93, 0x00, 0x43, 0x24, 0xca, 0x13, 0x79, 0xe1, 0x45, 0xd1, 0x47, 0x30, 0x87, 0x66, 0x58, 0x0d, 0xa6, 0xa9, 0xe8, - 0xaf, 0xd7, 0x99, 0x50, 0xc6, 0x01, 0xbc, 0xc8, 0xed, 0xcd, 0xc7, 0x32, 0x74, 0x28, 0xd2, 0x46, 0xce, 0x3c, 0x33, - 0xa7, 0xbc, 0xa1, 0x3e, 0x14, 0xa1, 0xf8, 0x4f, 0x30, 0x48, 0x72, 0x36, 0x00, 0x85, 0xac, 0x3d, 0x8f, 0x00, 0x60, - 0x49, 0x3f, 0x31, 0x03, 0x6f, 0xf8, 0xa7, 0xb3, 0xf1, 0x65, 0x91, 0xb1, 0x5f, 0xfd, 0x9b, 0x4b, 0xd3, 0x2c, 0xdc, - 0x59, 0xd5, 0xb3, 0x7b, 0x8a, 0x20, 0x0a, 0x24, 0x59, 0x28, 0x27, 0xf6, 0x1e, 0xe2, 0x57, 0x06, 0x98, 0x41, 0x48, - 0x06, 0x48, 0xc2, 0x74, 0xa4, 0x75, 0xe6, 0x27, 0xd7, 0x84, 0xad, 0xde, 0x16, 0x4a, 0xb0, 0x88, 0xce, 0xa3, 0xdb, - 0x2a, 0xcd, 0x5a, 0xba, 0x1f, 0xf6, 0xe6, 0x20, 0xe3, 0xe4, 0xcb, 0xca, 0x79, 0xe2, 0x3c, 0x7f, 0x43, 0x22, 0x7b, - 0x11, 0x51, 0x5e, 0x6e, 0x5d, 0x44, 0x7e, 0x05, 0xa5, 0x62, 0x03, 0xa0, 0x1a, 0x09, 0x53, 0x4d, 0xf1, 0xee, 0x17, - 0x77, 0xc0, 0x28, 0x1f, 0x68, 0x4f, 0x28, 0xee, 0x27, 0x2b, 0x63, 0x3d, 0xcc, 0x83, 0xcc, 0x22, 0x2e, 0x57, 0xa3, - 0xcd, 0x4e, 0x68, 0xa4, 0x5e, 0xd1, 0x04, 0x03, 0x1a, 0x96, 0xe1, 0x74, 0x6a, 0xeb, 0x1f, 0x05, 0xcb, 0x6c, 0xba, - 0x4e, 0xcf, 0x71, 0x29, 0x74, 0x5b, 0xf7, 0x49, 0x21, 0x8e, 0x86, 0xd0, 0xed, 0x28, 0x14, 0x46, 0x3f, 0xab, 0xf0, - 0xa2, 0x3e, 0xeb, 0xd7, 0xa2, 0x33, 0xd6, 0x98, 0xa1, 0xab, 0x2e, 0xbb, 0xa1, 0x00, 0x6c, 0xc4, 0xce, 0x10, 0x05, - 0x72, 0x7b, 0xd5, 0x2e, 0xd7, 0x70, 0x2f, 0x62, 0xf2, 0x1f, 0x5a, 0xef, 0x37, 0xda, 0x4f, 0xe0, 0x8f, 0x92, 0xcc, - 0xad, 0x09, 0xac, 0xa9, 0x9c, 0x97, 0xc4, 0x01, 0xd1, 0xe3, 0x7c, 0x3f, 0x08, 0xfe, 0xa4, 0xb5, 0x78, 0x50, 0x6c, - 0x11, 0xd2, 0x4a, 0xa9, 0x13, 0xf5, 0xda, 0x3a, 0x4d, 0xe4, 0x83, 0xc4, 0xa4, 0x62, 0x42, 0x75, 0x5a, 0xfb, 0x69, - 0x5e, 0xab, 0x59, 0xe0, 0x6d, 0xa2, 0x12, 0xaf, 0x30, 0x9d, 0xdb, 0x25, 0x43, 0xd2, 0x1d, 0xc1, 0xa9, 0x2e, 0x2b, - 0x86, 0xbb, 0xdb, 0xd6, 0xec, 0x17, 0x03, 0x5f, 0xd3, 0x35, 0x1c, 0xe3, 0x2e, 0xe8, 0xdc, 0x18, 0x6f, 0x88, 0xed, - 0xc1, 0xe0, 0x61, 0xf5, 0xe4, 0xec, 0xb4, 0x9a, 0x6e, 0x1a, 0x95, 0xb9, 0xb9, 0xd7, 0xd4, 0xd5, 0x42, 0xbf, 0x4a, - 0x60, 0xf9, 0x6c, 0x94, 0x6f, 0xb1, 0x67, 0xae, 0x51, 0x60, 0x6b, 0x89, 0xbb, 0x65, 0xd9, 0xb1, 0x18, 0xbd, 0x1b, - 0x18, 0x15, 0xd6, 0x2e, 0x62, 0xf0, 0xfc, 0x1c, 0xf6, 0xf6, 0xc4, 0x04, 0x42, 0xfd, 0x9b, 0x7a, 0xb2, 0x80, 0x8b, - 0x59, 0x1a, 0xc9, 0xb0, 0x1e, 0x94, 0xbd, 0x27, 0x5a, 0xfa, 0x88, 0xe7, 0x82, 0x60, 0xdb, 0x76, 0x8a, 0xad, 0x6b, - 0x18, 0x03, 0x1f, 0xba, 0xc6, 0x1d, 0x04, 0xd7, 0xec, 0x56, 0x34, 0xcf, 0xe0, 0x31, 0x88, 0x39, 0x30, 0xc2, 0x7c, - 0x5e, 0xaa, 0xba, 0x7d, 0xa2, 0xb3, 0xff, 0x02, 0x42, 0x31, 0xbb, 0xd5, 0xe5, 0xd6, 0x69, 0xe3, 0x21, 0x43, 0x16, - 0x64, 0x2c, 0x49, 0x8a, 0x8c, 0xfc, 0xa6, 0xa3, 0x2d, 0x63, 0xd1, 0x33, 0x97, 0x71, 0x4b, 0x6a, 0x42, 0xa9, 0xce, - 0xa6, 0x21, 0x51, 0x5e, 0x8f, 0xb0, 0xa8, 0x42, 0xec, 0x36, 0x87, 0x54, 0xce, 0x5c, 0x11, 0x99, 0xe2, 0x49, 0xda, - 0x66, 0x67, 0xb0, 0x46, 0x90, 0xa1, 0x60, 0x82, 0xaa, 0xf6, 0xfd, 0xe8, 0xfe, 0x86, 0x79, 0x30, 0xa6, 0xa9, 0x7a, - 0x78, 0xc3, 0x94, 0x89, 0xf0, 0x24, 0x6d, 0x6f, 0x3b, 0x62, 0xdb, 0xba, 0x8e, 0xf3, 0xec, 0x7b, 0xf2, 0x56, 0x8e, - 0x2c, 0xd9, 0x9a, 0xb2, 0x35, 0x15, 0xfb, 0xa0, 0x16, 0x15, 0x65, 0x28, 0x91, 0x48, 0x60, 0x2b, 0xea, 0xed, 0xa5, - 0x3a, 0x1b, 0x88, 0xf4, 0xca, 0x7a, 0xbf, 0x26, 0xcf, 0xe9, 0xda, 0x4a, 0x29, 0x58, 0x40, 0x21, 0x2c, 0x34, 0xf6, - 0xac, 0xef, 0x7f, 0x9c, 0xd7, 0xb0, 0x1f, 0x7e, 0xcc, 0x88, 0x2d, 0xfc, 0xea, 0xfd, 0x7a, 0x82, 0x01, 0x46, 0xdd, - 0x8b, 0xae, 0x48, 0xdf, 0x1b, 0xfa, 0x1e, 0xe9, 0xbb, 0xaf, 0xef, 0x66, 0x3f, 0xd0, 0x35, 0xd6, 0x86, 0x37, 0xee, - 0xdc, 0x42, 0xeb, 0x88, 0x2f, 0xb1, 0xd4, 0x41, 0x7f, 0x5b, 0x7e, 0x9a, 0xa8, 0xb2, 0x5f, 0x5b, 0x49, 0x29, 0x9b, - 0xbe, 0x24, 0x55, 0x1b, 0xba, 0x8c, 0x90, 0xba, 0x57, 0x82, 0xb7, 0x6f, 0x9d, 0xba, 0xba, 0x2d, 0xe5, 0xa7, 0xe3, - 0x62, 0xfc, 0xf2, 0xaf, 0x0e, 0xf1, 0x52, 0xc6, 0x74, 0xe8, 0xca, 0x3b, 0xef, 0xd9, 0x4a, 0x8d, 0x2b, 0xcc, 0x09, - 0xe7, 0x78, 0xb2, 0x90, 0x31, 0xea, 0xa1, 0xdc, 0xb9, 0x03, 0x2e, 0x23, 0x08, 0x7c, 0x45, 0x57, 0x55, 0x8a, 0x59, - 0xea, 0x3b, 0x06, 0x96, 0xf9, 0x3e, 0xd1, 0xe5, 0xf0, 0xf7, 0x02, 0x09, 0x7d, 0xea, 0xaa, 0x72, 0xed, 0x4a, 0x35, - 0x62, 0x6c, 0x8a, 0x24, 0xe7, 0x64, 0xbd, 0xcb, 0x8b, 0xbc, 0xf0, 0xd7, 0xd3, 0xaa, 0xa6, 0x03, 0x52, 0xcc, 0x4a, - 0x2c, 0xca, 0xa9, 0x58, 0x94, 0x22, 0x62, 0xfb, 0x12, 0x86, 0xca, 0x66, 0x12, 0x88, 0xbc, 0xb7, 0x73, 0x91, 0x58, - 0xbe, 0x02, 0x18, 0xac, 0xaa, 0x0f, 0x84, 0xe4, 0x77, 0x76, 0xd9, 0x25, 0x3f, 0xf6, 0x57, 0x4a, 0x26, 0x93, 0x56, - 0x18, 0x02, 0x77, 0xc4, 0x6f, 0x9f, 0x0e, 0x18, 0x13, 0x9c, 0x33, 0xda, 0x18, 0x30, 0xe7, 0xa6, 0x69, 0x48, 0xaa, - 0x9a, 0xb5, 0xca, 0xdd, 0xbc, 0xc2, 0x4c, 0x48, 0x62, 0xa8, 0xca, 0xcd, 0xf0, 0x6b, 0x3d, 0x52, 0x90, 0xf3, 0xf7, - 0x5c, 0x5d, 0x90, 0x31, 0x2a, 0x67, 0x3a, 0x99, 0x04, 0x5f, 0x07, 0xf0, 0x01, 0x73, 0x2b, 0x3e, 0xf8, 0xc7, 0x59, - 0xca, 0x23, 0x1b, 0xd0, 0x03, 0xb5, 0x43, 0x35, 0x56, 0x2d, 0x25, 0x0a, 0x13, 0x09, 0xa1, 0x0c, 0x3e, 0xe2, 0x33, - 0x99, 0x8b, 0x39, 0xab, 0xfb, 0x5c, 0x2c, 0xdb, 0x0e, 0x24, 0x06, 0x44, 0x99, 0x10, 0x49, 0x4e, 0x6a, 0xdd, 0x50, - 0x61, 0x71, 0x74, 0x69, 0xb1, 0x88, 0x13, 0x24, 0xd3, 0x7a, 0x21, 0xf8, 0x97, 0x1d, 0x5b, 0xc9, 0xf1, 0xa6, 0xff, - 0x66, 0x34, 0x57, 0x23, 0x33, 0xd9, 0x45, 0x6b, 0x5e, 0xf4, 0x8b, 0xb4, 0xe6, 0xf2, 0x21, 0x51, 0xe8, 0x1f, 0x68, - 0xdd, 0x5b, 0xd6, 0x10, 0x29, 0x58, 0xd2, 0x15, 0x7d, 0x45, 0xdb, 0x5d, 0x7a, 0x59, 0xe0, 0x71, 0xf7, 0x31, 0x41, - 0x82, 0xef, 0xb6, 0x8a, 0x97, 0xc0, 0x45, 0xb2, 0xc6, 0x9e, 0xfb, 0x44, 0x16, 0x1d, 0xd3, 0x8d, 0xd2, 0xd5, 0x91, - 0x9d, 0xd3, 0x37, 0x88, 0x92, 0x9c, 0x5d, 0x2b, 0x31, 0xf5, 0x3f, 0x47, 0xdd, 0xe4, 0xa2, 0xb2, 0x67, 0x87, 0x1c, - 0xc4, 0xcd, 0xd4, 0x42, 0x98, 0x92, 0xbd, 0x13, 0xd8, 0x08, 0x91, 0x91, 0x62, 0x52, 0x04, 0x25, 0xf7, 0x92, 0x2f, - 0x89, 0x14, 0xf2, 0x47, 0xa5, 0x86, 0xb6, 0x4c, 0xe9, 0x7f, 0xb4, 0x8e, 0xf0, 0xed, 0x0c, 0x27, 0x49, 0xf9, 0xe4, - 0x05, 0xb7, 0xad, 0xdd, 0x8e, 0xd9, 0x20, 0x09, 0xf7, 0xcf, 0x2c, 0x9f, 0xf5, 0xf6, 0x20, 0xff, 0x50, 0x26, 0x04, - 0x78, 0xeb, 0x9b, 0x5e, 0xd5, 0x2f, 0x01, 0xa3, 0x92, 0x6a, 0x51, 0x79, 0x3b, 0x39, 0x97, 0x38, 0xe5, 0xf2, 0x02, - 0x7e, 0xf9, 0x7e, 0xce, 0x81, 0x79, 0xf8, 0x4a, 0x5b, 0x4d, 0x14, 0xec, 0x87, 0xc3, 0x1e, 0x43, 0xc9, 0x0a, 0x1b, - 0xd9, 0xcd, 0xc6, 0xb8, 0x0b, 0x5d, 0x6b, 0xb3, 0x7e, 0x0a, 0xa9, 0x57, 0x77, 0x9c, 0xde, 0xc5, 0x55, 0x8d, 0x34, - 0xb7, 0x69, 0xc4, 0x51, 0xc9, 0x4c, 0x07, 0x72, 0x87, 0x69, 0x3a, 0x66, 0x6f, 0x23, 0xc1, 0xf2, 0xcd, 0x59, 0x5b, - 0x79, 0x2b, 0xef, 0x49, 0x08, 0x98, 0x70, 0xc0, 0x5c, 0xd1, 0xb0, 0x56, 0x0e, 0x82, 0x39, 0xf6, 0x7b, 0xad, 0x90, - 0x98, 0xaa, 0x48, 0x7a, 0x36, 0xf1, 0xb9, 0x56, 0x6b, 0xcf, 0x1a, 0x09, 0x59, 0x3a, 0x05, 0x8e, 0x35, 0x4f, 0x14, - 0x0c, 0x65, 0x6a, 0x56, 0xcb, 0x3c, 0xe0, 0x2a, 0x7b, 0xae, 0xe5, 0x95, 0x40, 0x0c, 0x1c, 0x14, 0x90, 0x9c, 0xf8, - 0x1e, 0xee, 0x49, 0xec, 0x3b, 0x73, 0x86, 0xc6, 0x4c, 0x86, 0xa8, 0xce, 0x4a, 0x15, 0x58, 0xd7, 0xdb, 0xc0, 0x54, - 0x51, 0x6b, 0x6e, 0xe8, 0x9e, 0x0c, 0xd6, 0xd7, 0x38, 0x3c, 0x10, 0xf6, 0xf8, 0x82, 0xdc, 0x87, 0xbf, 0xcf, 0xca, - 0x63, 0x67, 0x0b, 0x68, 0xc0, 0x7a, 0xf3, 0x1c, 0x39, 0xa2, 0xeb, 0x2d, 0x95, 0x2b, 0x5b, 0xd0, 0x65, 0xaf, 0xe9, - 0xfd, 0xd3, 0x41, 0x75, 0xb9, 0xdc, 0xcc, 0x8c, 0xa8, 0xe2, 0xc9, 0x24, 0x09, 0xfa, 0x10, 0x33, 0x28, 0xa9, 0x79, - 0x2a, 0xeb, 0x88, 0x89, 0x7b, 0xb0, 0xbc, 0x23, 0x13, 0xd3, 0x25, 0x98, 0xe3, 0x9c, 0xad, 0x8b, 0x06, 0x87, 0x1c, - 0x0e, 0x58, 0xa2, 0x4b, 0x1e, 0xdc, 0xfb, 0x56, 0x56, 0x6a, 0xd1, 0x97, 0x63, 0xa9, 0x84, 0xdc, 0x00, 0x36, 0x76, - 0xb4, 0x93, 0x0b, 0xe5, 0xd4, 0x4e, 0x10, 0xec, 0xe4, 0xa6, 0xf6, 0x0e, 0x49, 0x06, 0xc8, 0x1e, 0x08, 0x55, 0x19, - 0xf0, 0x79, 0x5d, 0x11, 0x00, 0x9a, 0xe3, 0x12, 0x89, 0x3f, 0x08, 0xe3, 0xe5, 0x37, 0x8a, 0x41, 0x83, 0xe3, 0x6e, - 0x66, 0x38, 0x78, 0x1d, 0xc0, 0x28, 0x8d, 0x12, 0xf3, 0x23, 0x10, 0xe5, 0x62, 0x7f, 0x95, 0x18, 0x1d, 0x29, 0x44, - 0x38, 0xf4, 0x8b, 0xdd, 0x85, 0xb4, 0xf5, 0x16, 0x6c, 0x65, 0x36, 0x2b, 0xb3, 0x5d, 0x03, 0x68, 0x1f, 0xa9, 0x01, - 0xd0, 0x66, 0xc3, 0x43, 0x3f, 0x37, 0xdd, 0x67, 0x3e, 0x43, 0xf7, 0x8e, 0x22, 0xf0, 0xeb, 0x32, 0x35, 0xdf, 0xc2, - 0x05, 0x4c, 0x33, 0xf5, 0x5e, 0x5e, 0x2d, 0xf7, 0x75, 0xb7, 0x63, 0x20, 0xbc, 0x5c, 0x62, 0x8f, 0xf8, 0x29, 0xab, - 0xe2, 0xa0, 0xc7, 0x1c, 0xbd, 0x46, 0x90, 0x66, 0x66, 0x69, 0xc8, 0x73, 0x0b, 0xe5, 0x33, 0x92, 0x03, 0xf9, 0x98, - 0x2c, 0x0f, 0xd9, 0xcb, 0x70, 0xe5, 0xa1, 0xae, 0x23, 0x24, 0x55, 0x90, 0x7a, 0x02, 0xcf, 0xd5, 0x0c, 0xc2, 0xb2, - 0x8f, 0xe7, 0xc4, 0xdc, 0xf3, 0xb7, 0x29, 0x68, 0xe4, 0x40, 0xa5, 0xf3, 0x93, 0xb2, 0x80, 0xdc, 0x43, 0x1d, 0xa6, - 0x98, 0xf1, 0xa0, 0x97, 0x5d, 0x95, 0x64, 0x38, 0x1a, 0xa1, 0xf1, 0x84, 0x82, 0xe4, 0x05, 0xc1, 0xd1, 0x57, 0x4b, - 0xe5, 0xaf, 0x24, 0xe5, 0x4d, 0x56, 0x96, 0x0d, 0xee, 0x25, 0x5e, 0x64, 0x0d, 0x9c, 0x59, 0xd8, 0xd1, 0xa6, 0xac, - 0x19, 0x13, 0x04, 0x80, 0x0f, 0x87, 0xe0, 0xc8, 0x22, 0x62, 0x59, 0x44, 0x13, 0xc5, 0x38, 0x96, 0x3f, 0x7b, 0xf8, - 0xa6, 0x08, 0xae, 0xd7, 0x91, 0xa0, 0x85, 0xc0, 0x27, 0x0e, 0xc0, 0x33, 0x33, 0x88, 0x78, 0xb6, 0xda, 0x3c, 0x02, - 0x13, 0xa9, 0xb5, 0x1f, 0x8d, 0xf8, 0x84, 0x13, 0xe7, 0xb8, 0x44, 0x1a, 0xb9, 0x5d, 0x8b, 0xc3, 0x21, 0x91, 0x89, - 0x9d, 0x39, 0xf2, 0xb1, 0xf1, 0x5d, 0x91, 0xff, 0x65, 0x16, 0x3d, 0x29, 0x51, 0x73, 0x39, 0x52, 0xbc, 0x69, 0x1b, - 0xa2, 0x55, 0xc6, 0xb5, 0xf4, 0x72, 0x98, 0x30, 0x58, 0xc0, 0xfe, 0xdf, 0x7c, 0x30, 0x1a, 0x8d, 0x95, 0xf3, 0x31, - 0xb8, 0xe2, 0x21, 0x3a, 0x6c, 0x38, 0x6a, 0x7d, 0xdd, 0x34, 0x99, 0x93, 0x0f, 0xfb, 0x6f, 0x7b, 0xb3, 0xeb, 0x6e, - 0x23, 0xea, 0x5c, 0x4a, 0x73, 0xe6, 0x85, 0xd0, 0x87, 0x91, 0xd5, 0x8b, 0x35, 0xe6, 0x84, 0xe6, 0x97, 0x8e, 0xa8, - 0x56, 0x1c, 0x9e, 0x3e, 0x08, 0xc5, 0xcb, 0xd1, 0x3e, 0xc4, 0x01, 0xb1, 0xa1, 0x44, 0xd9, 0x33, 0x95, 0x90, 0xc6, - 0x31, 0xb0, 0x5e, 0x85, 0x83, 0x40, 0xe0, 0xb4, 0x61, 0xbb, 0x66, 0xfd, 0x16, 0x2b, 0x4a, 0xc8, 0x21, 0xd5, 0x64, - 0xd9, 0x8c, 0x1f, 0x62, 0x47, 0x13, 0x94, 0x48, 0x29, 0x5a, 0x36, 0xfd, 0xc3, 0xb6, 0x23, 0x07, 0x2f, 0xa1, 0x21, - 0x71, 0x04, 0x2f, 0xbd, 0xf3, 0x87, 0xfd, 0x37, 0xeb, 0x23, 0xcf, 0x51, 0xbf, 0xe5, 0x21, 0xdf, 0xf2, 0x1c, 0xed, - 0x43, 0x1e, 0xf2, 0x21, 0xcf, 0x11, 0x3f, 0xe4, 0x41, 0xb2, 0x38, 0x4f, 0x5f, 0xdb, 0x7f, 0x0e, 0xc7, 0x4c, 0xa1, - 0x5c, 0x9e, 0x89, 0xad, 0xe4, 0xe8, 0x17, 0x1f, 0x32, 0xee, 0xb3, 0x89, 0x94, 0x3c, 0x21, 0x5e, 0x89, 0x12, 0x97, - 0xac, 0x2c, 0x93, 0x02, 0xf8, 0x34, 0xc4, 0xa7, 0x37, 0xdb, 0x77, 0xfc, 0x23, 0xac, 0x51, 0x74, 0x26, 0xe2, 0xc5, - 0x98, 0x8c, 0xd3, 0x3d, 0x73, 0xeb, 0x85, 0xad, 0x89, 0x90, 0x2c, 0x67, 0x04, 0x6d, 0x08, 0x71, 0xc8, 0x88, 0x91, - 0xcb, 0xf9, 0x64, 0xb4, 0xc4, 0xd0, 0xb7, 0xef, 0xa2, 0xd7, 0xcc, 0xfe, 0x1c, 0x03, 0x48, 0x95, 0xe7, 0x06, 0x64, - 0xe0, 0x18, 0x7b, 0xf5, 0x31, 0xd6, 0xa7, 0xe7, 0x45, 0x15, 0x0d, 0xba, 0x26, 0x87, 0x63, 0x4e, 0x90, 0x64, 0xa4, - 0x7f, 0xc5, 0xba, 0xec, 0x2c, 0x5d, 0x36, 0xaf, 0xc2, 0x3d, 0x61, 0xbe, 0x04, 0xb4, 0x28, 0x21, 0xd5, 0xcc, 0x72, - 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xa4, 0xc9, 0x52, 0x6d, 0x97, 0x85, 0xbb, 0xec, 0xf1, 0x0b, 0xfe, 0xe1, 0x9e, - 0xe6, 0x66, 0x91, 0x41, 0xfb, 0x22, 0x67, 0xf7, 0xde, 0x15, 0xb6, 0xb5, 0x06, 0xf3, 0x13, 0x29, 0xd6, 0x22, 0x7c, - 0x35, 0xa6, 0x17, 0xa4, 0x3d, 0x7c, 0x83, 0x22, 0x1a, 0xdf, 0x67, 0x13, 0x5b, 0x86, 0xf6, 0x96, 0x7c, 0x6d, 0xa9, - 0xc9, 0x66, 0xc5, 0x1a, 0x2c, 0xb9, 0xfd, 0xf6, 0x25, 0xb5, 0x43, 0x97, 0xb9, 0x28, 0xb2, 0x49, 0x75, 0x53, 0xac, - 0x4d, 0x81, 0x2f, 0xc9, 0x56, 0x84, 0x8e, 0x40, 0x51, 0xb9, 0xcb, 0xe2, 0x70, 0xb9, 0xaa, 0xe5, 0xd4, 0x94, 0x10, - 0x69, 0xc8, 0x2a, 0xcc, 0xf4, 0x52, 0x7c, 0xbc, 0x38, 0x14, 0x21, 0xe5, 0x28, 0xa1, 0x33, 0xb5, 0x9c, 0xae, 0x6b, - 0xf5, 0xb7, 0x50, 0xe0, 0xe0, 0x4b, 0x5e, 0x43, 0x2c, 0x61, 0xa9, 0x6a, 0x0e, 0x11, 0x67, 0x9e, 0xdd, 0xd0, 0x95, - 0x87, 0xfd, 0xf7, 0x21, 0x04, 0x79, 0xb1, 0xfd, 0x94, 0xae, 0x5d, 0x9f, 0x91, 0x49, 0x20, 0x91, 0x84, 0x02, 0x80, - 0x03, 0x00, 0xae, 0x7a, 0x05, 0xab, 0x02, 0x93, 0x5e, 0xab, 0xc0, 0xc0, 0x14, 0x3c, 0x41, 0x99, 0xa1, 0x1d, 0xe0, - 0xf2, 0x47, 0xa4, 0xf4, 0xda, 0x21, 0x5b, 0x4c, 0x04, 0x34, 0x94, 0xc0, 0x31, 0xa1, 0xdd, 0x16, 0xe3, 0xe5, 0x25, - 0x0a, 0x2f, 0x89, 0xd2, 0x51, 0xdb, 0x02, 0x34, 0x90, 0x57, 0xb3, 0x2c, 0x9c, 0x96, 0x91, 0xe7, 0x6b, 0x13, 0xde, - 0xf2, 0x76, 0x5d, 0x6e, 0x3f, 0xb2, 0x35, 0x4d, 0x21, 0x1b, 0x82, 0x7d, 0xcf, 0xd6, 0x3d, 0x63, 0xa8, 0x10, 0x6f, - 0xb1, 0x1c, 0x7a, 0xe3, 0xba, 0x56, 0x1b, 0xd2, 0x87, 0x3e, 0x7a, 0x28, 0xba, 0x72, 0x37, 0x8c, 0x04, 0x5a, 0x4b, - 0x04, 0xab, 0xe1, 0x39, 0x03, 0xed, 0x26, 0x2f, 0x25, 0x47, 0x41, 0xaa, 0x02, 0x1f, 0xd2, 0xcd, 0x37, 0x2c, 0x66, - 0xb0, 0xeb, 0x36, 0x0b, 0xe4, 0x6a, 0xa0, 0xf5, 0xf1, 0x3b, 0x0d, 0x7b, 0x7d, 0x02, 0x36, 0x96, 0x2e, 0x57, 0xdb, - 0x2e, 0x8a, 0xa3, 0xe6, 0x8a, 0xe6, 0xae, 0xed, 0x14, 0xfa, 0x73, 0xf1, 0x39, 0xdc, 0x9e, 0x27, 0x8d, 0xef, 0xf3, - 0x13, 0xe1, 0x7b, 0x97, 0x35, 0xde, 0x1b, 0x0d, 0xa8, 0x3f, 0xce, 0xc4, 0x58, 0x8b, 0x1c, 0x15, 0x65, 0xe0, 0xa3, - 0x59, 0x2d, 0xee, 0xa0, 0x29, 0x32, 0xde, 0x6b, 0x04, 0x77, 0x9b, 0x5a, 0x65, 0x70, 0xaf, 0xb5, 0x01, 0x7d, 0x8f, - 0x83, 0xd4, 0xbd, 0x36, 0xda, 0xd9, 0xb9, 0x96, 0xa0, 0x16, 0x23, 0xa3, 0x95, 0x66, 0x63, 0xbb, 0x0d, 0xdd, 0xba, - 0xa5, 0x7e, 0x41, 0x9f, 0xca, 0xc9, 0x81, 0xec, 0xac, 0xae, 0x4a, 0xc5, 0xa4, 0x25, 0x78, 0x8b, 0xeb, 0x7b, 0x65, - 0x4a, 0x64, 0xe0, 0x56, 0x75, 0x99, 0x30, 0x12, 0x07, 0xb0, 0xf8, 0xc8, 0x9d, 0xf1, 0xeb, 0x07, 0xa8, 0x14, 0x1e, - 0x9f, 0x8b, 0x52, 0x78, 0xfc, 0x41, 0xf8, 0x4c, 0x7d, 0x05, 0x91, 0x9a, 0xba, 0xff, 0x32, 0x8f, 0x4a, 0xe5, 0x9b, - 0xbd, 0x6c, 0xec, 0x85, 0x79, 0x1b, 0x40, 0xbe, 0x4d, 0x33, 0x31, 0x98, 0xf9, 0x27, 0x27, 0xba, 0xdb, 0x10, 0x65, - 0x73, 0x0f, 0xd1, 0x7b, 0x45, 0x1d, 0x86, 0x8e, 0xa1, 0x43, 0x91, 0x1a, 0xb7, 0x75, 0x5c, 0x5f, 0xb2, 0x02, 0x9e, - 0xf4, 0xdf, 0x79, 0x7c, 0x52, 0x75, 0xfb, 0x0d, 0x4b, 0x9c, 0x49, 0xa4, 0x92, 0x8a, 0x4d, 0x27, 0xee, 0x2a, 0x35, - 0x59, 0xee, 0xbd, 0xed, 0x90, 0xa0, 0x2d, 0x32, 0xc8, 0x54, 0xef, 0x57, 0x24, 0xce, 0xa1, 0x66, 0x94, 0xa6, 0x82, - 0xa9, 0xac, 0xb2, 0xf2, 0x64, 0xde, 0x9c, 0x7f, 0xc4, 0xa7, 0x34, 0x1e, 0xf0, 0x31, 0x2c, 0x66, 0x23, 0xff, 0x7e, - 0xc4, 0xe8, 0xe8, 0xa6, 0x36, 0xac, 0x52, 0x26, 0x98, 0x56, 0x28, 0xe1, 0x63, 0x05, 0xc1, 0x09, 0x7e, 0x10, 0x4c, - 0x8e, 0x9c, 0x94, 0xac, 0x3c, 0x7e, 0xb3, 0xde, 0x62, 0xf8, 0x38, 0x33, 0xb1, 0xf1, 0x55, 0x9d, 0x69, 0x71, 0x87, - 0xee, 0xae, 0xf0, 0x72, 0xac, 0x4a, 0x86, 0x0b, 0xb2, 0x89, 0xb1, 0x8e, 0xc2, 0x67, 0x24, 0x29, 0x39, 0x91, 0xa7, - 0x74, 0x64, 0x32, 0x13, 0x38, 0x05, 0x67, 0x61, 0xfc, 0xa0, 0x36, 0xae, 0xa4, 0x6f, 0xa1, 0xa7, 0x45, 0xba, 0x3d, - 0x23, 0x0f, 0x76, 0x55, 0xef, 0x51, 0x16, 0x44, 0x19, 0x69, 0x30, 0x42, 0xda, 0xb2, 0xc4, 0xb8, 0x26, 0x62, 0x93, - 0x51, 0x18, 0x65, 0x5a, 0x6b, 0x2d, 0xbb, 0x16, 0x7f, 0x37, 0x54, 0x33, 0x4d, 0xbd, 0x5a, 0x9c, 0xfc, 0xc4, 0x24, - 0xad, 0x19, 0x2e, 0x5b, 0x7c, 0x78, 0xa1, 0xf6, 0xa8, 0x54, 0x07, 0x62, 0x6f, 0x67, 0x14, 0x4a, 0xb7, 0xef, 0x69, - 0x88, 0xa7, 0x46, 0xe7, 0xa5, 0xd3, 0x79, 0x75, 0xaa, 0xba, 0x6f, 0x4c, 0xd4, 0xb6, 0xfb, 0x66, 0x9c, 0xe2, 0x19, - 0xd0, 0x7c, 0x62, 0x04, 0x1d, 0xfa, 0x4f, 0x85, 0x06, 0x61, 0xd1, 0x30, 0xf3, 0xd9, 0x03, 0x18, 0xe9, 0xa6, 0x4c, - 0x6b, 0x46, 0x82, 0x7b, 0x8f, 0x60, 0xe0, 0x31, 0x69, 0x1e, 0xd9, 0x98, 0x4e, 0x18, 0x86, 0xa8, 0xa2, 0x93, 0xb3, - 0xec, 0x73, 0xf3, 0xfb, 0x3d, 0xea, 0xba, 0xdd, 0xb0, 0xa9, 0xe5, 0xbc, 0x87, 0xd3, 0xfb, 0xbf, 0xb9, 0xe8, 0xa4, - 0xbf, 0x9c, 0x5d, 0x5b, 0xe8, 0xc2, 0xe2, 0x7d, 0x1d, 0xf6, 0xbf, 0x91, 0xf9, 0xc8, 0x53, 0xa5, 0x77, 0x18, 0x03, - 0x19, 0x3a, 0xb3, 0x26, 0xca, 0x2f, 0x0c, 0xed, 0x28, 0x24, 0xd9, 0x89, 0xdd, 0x54, 0x4d, 0x90, 0x80, 0x48, 0x8c, - 0xa9, 0xef, 0x1c, 0x0c, 0xb4, 0x53, 0x9d, 0xc5, 0xa4, 0x2d, 0x5f, 0x81, 0x72, 0x5a, 0x06, 0x2c, 0x2f, 0x55, 0x78, - 0x76, 0x1d, 0xd4, 0xd4, 0xc7, 0x09, 0xc5, 0x56, 0x70, 0x3d, 0x64, 0x90, 0xaa, 0x12, 0x42, 0xa7, 0x29, 0x02, 0xbb, - 0x38, 0x36, 0xf1, 0xc7, 0x86, 0xf1, 0x03, 0xac, 0x81, 0xa6, 0xb5, 0xd8, 0xc2, 0x41, 0x52, 0xcc, 0xfc, 0x2d, 0x4d, - 0x8f, 0xab, 0xf4, 0xca, 0x3b, 0x05, 0xd6, 0x26, 0x98, 0xb2, 0x25, 0xb7, 0x6e, 0x2d, 0x42, 0x21, 0x8c, 0x59, 0xd7, - 0x90, 0xca, 0x3b, 0x24, 0x7f, 0x46, 0x16, 0xf0, 0x76, 0xbf, 0x54, 0x48, 0x3d, 0x2b, 0xcc, 0xae, 0x13, 0x74, 0x52, - 0x10, 0x47, 0xba, 0x44, 0xfc, 0xff, 0xca, 0x84, 0x10, 0x7c, 0xda, 0xf0, 0x6d, 0x09, 0x4d, 0x52, 0x9c, 0x5d, 0xb9, - 0x0b, 0x78, 0xec, 0x7a, 0xfd, 0x2c, 0x59, 0xa3, 0xef, 0xf0, 0xd9, 0x20, 0x16, 0xd8, 0x88, 0x9e, 0x9a, 0xd4, 0xb0, - 0xfa, 0xea, 0x95, 0xdd, 0xee, 0x11, 0xf5, 0x8d, 0x62, 0x0a, 0x15, 0xce, 0x7e, 0xf6, 0x94, 0x38, 0xed, 0x4d, 0xd3, - 0x5a, 0x92, 0xf2, 0xbf, 0xe4, 0x8e, 0x20, 0xf1, 0xaf, 0x37, 0x04, 0x05, 0x3c, 0x1b, 0x9e, 0x1a, 0x92, 0xfb, 0xfd, - 0x5b, 0x15, 0xaa, 0xbd, 0x0e, 0x66, 0x82, 0x2e, 0xbc, 0x07, 0x09, 0x8e, 0xfc, 0x20, 0xcb, 0xc6, 0x2f, 0x0a, 0x4b, - 0xdf, 0x98, 0x3b, 0xc4, 0x9e, 0x38, 0xd3, 0x93, 0xe6, 0x51, 0x7e, 0x58, 0xc1, 0x24, 0xdd, 0x21, 0x83, 0x7c, 0x7e, - 0x81, 0xb1, 0x77, 0x84, 0x95, 0x53, 0xb7, 0x7d, 0x79, 0x07, 0xb1, 0xac, 0x74, 0xc9, 0xbd, 0xd4, 0x9a, 0x12, 0x46, - 0x6d, 0x38, 0xcb, 0xab, 0x56, 0xf4, 0xe5, 0x76, 0xb6, 0xd1, 0x27, 0x2a, 0x20, 0x56, 0xdf, 0x33, 0x39, 0x2d, 0x91, - 0x61, 0xff, 0xb4, 0x5e, 0x4d, 0x9e, 0x0e, 0x43, 0x5d, 0x6b, 0x87, 0x54, 0xdb, 0xf5, 0x4e, 0x05, 0x0a, 0x8c, 0x2d, - 0xbd, 0xa5, 0x67, 0xe9, 0x70, 0xcc, 0x35, 0x78, 0xb1, 0x8c, 0xe0, 0x79, 0xea, 0x07, 0x78, 0x5f, 0x2d, 0x8f, 0x25, - 0xee, 0x1d, 0xdd, 0xf8, 0x02, 0x3a, 0x98, 0xce, 0x02, 0x0f, 0xbf, 0x1d, 0xb0, 0x4a, 0x36, 0x26, 0x73, 0xaf, 0x89, - 0x60, 0x40, 0x29, 0xfa, 0x60, 0xdf, 0x8d, 0x55, 0x4a, 0x34, 0x41, 0x3f, 0xb2, 0xd8, 0xa2, 0x5b, 0xdf, 0x56, 0x44, - 0x3c, 0xe3, 0x72, 0x54, 0x43, 0xfc, 0x29, 0x67, 0x2f, 0xb1, 0x4c, 0x18, 0xc9, 0xc2, 0xa0, 0x91, 0xbd, 0xe0, 0x23, - 0x4a, 0xcf, 0x0f, 0x2d, 0xed, 0xbe, 0x5d, 0x0f, 0x3f, 0x12, 0xc1, 0x5a, 0x1d, 0x84, 0x03, 0x15, 0x8a, 0xec, 0xd9, - 0xca, 0xcd, 0xc1, 0x0d, 0x19, 0x01, 0x28, 0x57, 0x40, 0x36, 0x16, 0xfc, 0xee, 0x86, 0xb0, 0xb8, 0x95, 0x8c, 0xcb, - 0xc4, 0x3e, 0x6f, 0x66, 0x22, 0x3d, 0x27, 0x57, 0x11, 0xe0, 0xe6, 0xa0, 0x99, 0x34, 0x8f, 0x2d, 0xb7, 0xa8, 0xb8, - 0x02, 0x6a, 0x42, 0x6d, 0xd1, 0x44, 0x54, 0x08, 0xd0, 0xeb, 0x69, 0x1f, 0x11, 0xb1, 0x4e, 0xc6, 0xc0, 0xb6, 0x2d, - 0x99, 0x54, 0x2a, 0xe3, 0x7a, 0xa7, 0x38, 0xdc, 0xb5, 0xdd, 0xfd, 0xdf, 0x64, 0x66, 0xcf, 0x60, 0x19, 0x5a, 0xac, - 0x65, 0x77, 0x7f, 0x14, 0xfb, 0xe3, 0x80, 0x06, 0x32, 0x3f, 0xd4, 0x41, 0xf2, 0xd7, 0x3a, 0x43, 0x5c, 0x4a, 0x41, - 0xf9, 0x10, 0x57, 0xb2, 0xc8, 0x05, 0xe9, 0x4e, 0xba, 0xca, 0x73, 0x99, 0x93, 0x7b, 0x40, 0x50, 0x1f, 0x08, 0x85, - 0x2c, 0x37, 0x90, 0xc6, 0x1b, 0x9c, 0x38, 0x6f, 0xe2, 0x91, 0x84, 0xb6, 0x9e, 0x49, 0x64, 0xb2, 0x68, 0xc7, 0x32, - 0xf0, 0xc9, 0xaf, 0xdd, 0x4f, 0x3e, 0xc6, 0x66, 0xe3, 0x40, 0x9b, 0xe5, 0xc9, 0x32, 0xcc, 0xaa, 0xad, 0x2a, 0x4e, - 0x58, 0x32, 0x99, 0x26, 0xbc, 0xfe, 0x2b, 0xac, 0xdc, 0x1a, 0xbe, 0x82, 0x0f, 0x66, 0xb6, 0x84, 0x4b, 0x9b, 0x6f, - 0x91, 0xa2, 0xc3, 0x30, 0xdd, 0xe4, 0xf8, 0x18, 0x13, 0xd3, 0xc5, 0x66, 0xc5, 0x30, 0x1a, 0x14, 0x89, 0xb7, 0x9b, - 0xaf, 0xf6, 0xef, 0x13, 0x38, 0x58, 0x2d, 0xc8, 0xd6, 0xee, 0xaf, 0xc1, 0x65, 0x0f, 0x59, 0x49, 0xd5, 0x98, 0x20, - 0xb4, 0x42, 0x1a, 0x43, 0xd4, 0x25, 0xfe, 0x55, 0x5f, 0x1e, 0xd2, 0xf5, 0xd7, 0x32, 0xa3, 0xf8, 0x5e, 0xfe, 0x5e, - 0xf8, 0x8e, 0x7f, 0x60, 0x2a, 0x69, 0xf3, 0x1c, 0xe1, 0xeb, 0xa0, 0x4b, 0x83, 0x84, 0xa8, 0x89, 0x7c, 0x5b, 0x32, - 0x40, 0xcc, 0x7a, 0x88, 0x01, 0xdc, 0x65, 0x75, 0xab, 0x24, 0x21, 0x63, 0xc1, 0x30, 0xd8, 0x16, 0x2b, 0xf3, 0x78, - 0x46, 0xea, 0x1d, 0xc6, 0x22, 0x71, 0x3e, 0x0f, 0x16, 0xec, 0xd4, 0x75, 0x26, 0xa6, 0x8b, 0xff, 0x98, 0x60, 0x81, - 0x25, 0x18, 0x6b, 0x2d, 0xfc, 0x74, 0x55, 0xc0, 0x9d, 0xe1, 0x43, 0x88, 0x02, 0xb7, 0xc9, 0x13, 0x3f, 0xd3, 0x3d, - 0xc5, 0x2e, 0x38, 0x95, 0x7a, 0x45, 0xd6, 0x9f, 0x03, 0xad, 0x5a, 0x73, 0xa9, 0xce, 0xee, 0x5c, 0x0e, 0xc2, 0x54, - 0x8b, 0xc2, 0x84, 0xd7, 0x51, 0xe2, 0xab, 0x6a, 0x39, 0x4d, 0x18, 0x5a, 0xbf, 0x0a, 0xf5, 0x27, 0xb9, 0xa8, 0x28, - 0xe1, 0xc4, 0x4d, 0xd2, 0x4d, 0x05, 0x07, 0xd4, 0xef, 0xed, 0xda, 0x84, 0xb7, 0x5e, 0xf0, 0x1c, 0x58, 0x50, 0xe8, - 0x39, 0x62, 0xf0, 0x8c, 0x91, 0xc1, 0xeb, 0xb2, 0x41, 0x07, 0xbd, 0x4c, 0x7f, 0xdb, 0x7e, 0xa9, 0xb5, 0xe7, 0xbb, - 0x59, 0xe4, 0x1c, 0xe4, 0xd9, 0xaf, 0xa6, 0xef, 0xef, 0x39, 0x13, 0xe3, 0xa2, 0x79, 0xd1, 0xd3, 0xe0, 0xb4, 0xdc, - 0xa0, 0xd9, 0x43, 0xd0, 0x31, 0xc3, 0xf6, 0x33, 0x2d, 0x2f, 0xc6, 0xf4, 0x9d, 0x38, 0xa6, 0x3d, 0xec, 0xfa, 0x99, - 0xb9, 0xa7, 0x17, 0x14, 0x68, 0xef, 0x89, 0xb7, 0x9d, 0xde, 0xe9, 0xea, 0xf3, 0xe5, 0x9a, 0x44, 0xdf, 0xac, 0xcb, - 0x75, 0x0b, 0xd0, 0xf5, 0x32, 0x16, 0x8d, 0x56, 0x65, 0x9f, 0x2b, 0xcf, 0xee, 0xf9, 0xbe, 0x30, 0xfd, 0x2d, 0xdc, - 0x4e, 0x86, 0x4c, 0xd2, 0x52, 0xb5, 0x52, 0x45, 0x93, 0x2e, 0x90, 0x58, 0x33, 0x49, 0xcb, 0x35, 0x1a, 0xcc, 0xf7, - 0xdd, 0xe5, 0xca, 0xf2, 0x27, 0x16, 0xa2, 0x52, 0x2f, 0xdf, 0x12, 0xa9, 0xcf, 0x06, 0x8b, 0x54, 0x84, 0x25, 0xca, - 0x8d, 0x67, 0x00, 0xab, 0x5d, 0x01, 0xd4, 0x9c, 0xa2, 0x97, 0x4b, 0x45, 0xc0, 0xc4, 0xe9, 0xa7, 0xfb, 0xcd, 0x14, - 0x86, 0xeb, 0xab, 0xb3, 0xf2, 0xda, 0x2f, 0x1a, 0xb9, 0xc4, 0x9f, 0x4f, 0x1f, 0x0a, 0x41, 0xa3, 0xee, 0x8a, 0xdf, - 0x5c, 0x48, 0x00, 0xe4, 0x10, 0xaf, 0xd5, 0x40, 0xba, 0x79, 0x4b, 0xba, 0x4e, 0x64, 0x5d, 0xbc, 0x4b, 0x05, 0x5c, - 0x59, 0xef, 0x80, 0x6e, 0x21, 0xdd, 0x6a, 0x89, 0x83, 0x84, 0x6e, 0xf8, 0x50, 0x70, 0x02, 0x25, 0xd8, 0xc9, 0x04, - 0x99, 0xbc, 0x53, 0xde, 0x12, 0x5e, 0x4d, 0x4c, 0x51, 0x10, 0xc9, 0xbd, 0x97, 0x68, 0xb7, 0x28, 0x79, 0x6b, 0xb0, - 0x09, 0xb1, 0xdb, 0x91, 0xc7, 0x7e, 0x72, 0xe4, 0xf5, 0xd2, 0xe6, 0x62, 0xa3, 0x32, 0x75, 0xf2, 0x92, 0xd2, 0x00, - 0xdb, 0x5b, 0x0a, 0x68, 0xe1, 0x2a, 0xa6, 0xba, 0x9c, 0xe6, 0x84, 0x16, 0xd3, 0x80, 0x33, 0x94, 0x1c, 0xfd, 0x4f, - 0x24, 0x1d, 0x6c, 0x1d, 0x7e, 0x72, 0xd1, 0x83, 0x17, 0xac, 0x35, 0xcd, 0x4a, 0x68, 0xb5, 0x27, 0xd8, 0x82, 0xe6, - 0x55, 0xf2, 0xa9, 0x51, 0x00, 0x9b, 0x17, 0x20, 0xab, 0x9f, 0x3e, 0xee, 0xc5, 0x23, 0xe7, 0xa7, 0x1c, 0xdc, 0x9e, - 0xea, 0x5b, 0x2f, 0x2c, 0x3b, 0xcd, 0x4a, 0x8a, 0x28, 0xc2, 0x93, 0xed, 0x85, 0xf8, 0xee, 0xcb, 0x48, 0x2e, 0x2e, - 0x13, 0x30, 0x43, 0x02, 0x22, 0xd8, 0xf7, 0xe4, 0x03, 0xdc, 0xa9, 0x81, 0x30, 0xad, 0xdf, 0x79, 0x10, 0x34, 0xad, - 0x33, 0x07, 0xc4, 0x4c, 0xc3, 0xec, 0xd2, 0x18, 0x70, 0xc3, 0xfb, 0xd7, 0x38, 0x77, 0x83, 0x7f, 0xac, 0xcc, 0x8a, - 0x66, 0xd3, 0xc0, 0xa6, 0x75, 0x43, 0x36, 0xc4, 0x85, 0x55, 0x8a, 0xc6, 0x55, 0xc6, 0x42, 0xd1, 0xe8, 0xd9, 0xab, - 0xcc, 0x52, 0xd9, 0x3f, 0x37, 0xad, 0x3f, 0xf6, 0x36, 0xb5, 0x25, 0x31, 0x6b, 0x29, 0x89, 0x86, 0xab, 0xcc, 0xcc, - 0xb1, 0x02, 0x10, 0x99, 0xe9, 0x43, 0x12, 0xd4, 0xe0, 0xeb, 0xf0, 0x85, 0x15, 0x53, 0xe5, 0x25, 0xbb, 0x1f, 0x32, - 0xfe, 0xf2, 0xd0, 0x41, 0xd1, 0x3b, 0x58, 0x85, 0x6f, 0x19, 0xf5, 0x9e, 0x06, 0x5d, 0xbf, 0xb4, 0x5a, 0x51, 0x97, - 0x9a, 0xe5, 0xe9, 0x67, 0xfc, 0x7e, 0x20, 0x9e, 0xc0, 0xfe, 0x54, 0x9c, 0xb1, 0x7d, 0x94, 0x7b, 0xc9, 0xe0, 0x9e, - 0xf4, 0x49, 0xea, 0x27, 0x34, 0x3a, 0x0a, 0xe7, 0x6d, 0xdd, 0xb7, 0x42, 0x5f, 0xb6, 0x27, 0x36, 0x8e, 0xa4, 0xee, - 0x52, 0xf2, 0x81, 0xb4, 0x75, 0xd0, 0x7d, 0x41, 0x90, 0xf0, 0x2b, 0xcb, 0x29, 0x05, 0x02, 0x13, 0x2e, 0x11, 0x47, - 0x08, 0xbc, 0x2e, 0xdd, 0x58, 0x40, 0x95, 0xe8, 0x03, 0xbb, 0xa5, 0x0d, 0xc1, 0xef, 0x40, 0xf8, 0xc5, 0x4e, 0x68, - 0x26, 0x57, 0x85, 0x9a, 0x99, 0x2a, 0x7b, 0x84, 0x36, 0x41, 0xcb, 0x89, 0xf4, 0xa4, 0x27, 0x0d, 0x26, 0xd0, 0x68, - 0xea, 0x95, 0x4f, 0x87, 0x60, 0xe8, 0x6a, 0x57, 0x5a, 0x1c, 0x58, 0x41, 0xc9, 0x40, 0xc3, 0x7a, 0x75, 0x29, 0x9d, - 0x16, 0x18, 0x03, 0x84, 0xe7, 0x5e, 0x5e, 0x36, 0x47, 0x2c, 0x7f, 0x77, 0x4b, 0x96, 0x1b, 0x1c, 0xf8, 0xd6, 0xc9, - 0xad, 0xe6, 0x92, 0x91, 0x9e, 0x9b, 0xbe, 0xed, 0xac, 0x9d, 0x28, 0x28, 0xab, 0xcd, 0x05, 0x0f, 0x01, 0x6a, 0x9a, - 0x7d, 0xd8, 0x62, 0x0b, 0x02, 0xce, 0x7a, 0x11, 0x12, 0xe4, 0x6d, 0x02, 0xbe, 0x7c, 0x3f, 0xc7, 0xde, 0x13, 0x51, - 0xb9, 0xac, 0xec, 0xc9, 0xe7, 0xb7, 0x8b, 0xaa, 0xbb, 0x25, 0x78, 0x56, 0x20, 0xdc, 0xf9, 0xc3, 0x38, 0xef, 0xeb, - 0xba, 0x57, 0x00, 0x58, 0x91, 0xf0, 0x49, 0x21, 0x07, 0x04, 0xa3, 0x99, 0x5e, 0xd5, 0xfd, 0x6d, 0xce, 0xa8, 0x29, - 0x9e, 0x22, 0x9c, 0x1c, 0x10, 0x7c, 0x67, 0x3a, 0x51, 0x9b, 0x95, 0xd6, 0x6a, 0x47, 0x64, 0x08, 0xa5, 0x6b, 0x8e, - 0xbb, 0x72, 0x03, 0x94, 0xbb, 0x48, 0x60, 0x86, 0x57, 0xb9, 0x2f, 0xc4, 0x87, 0x34, 0xbb, 0x6c, 0x19, 0xbc, 0x20, - 0x4f, 0xbb, 0x8a, 0xe5, 0x2e, 0x93, 0x71, 0x5d, 0x0b, 0x5b, 0xcc, 0x90, 0x43, 0xe6, 0x7e, 0xc6, 0x29, 0x6c, 0xb6, - 0x69, 0x9f, 0x27, 0x46, 0x6e, 0x69, 0xc3, 0x98, 0x08, 0x06, 0x2e, 0xb4, 0x26, 0xf2, 0x45, 0xbb, 0xb6, 0xdd, 0x9c, - 0xa1, 0xbc, 0xfa, 0xc9, 0xe0, 0xc1, 0x37, 0xff, 0xea, 0x8b, 0x27, 0xb3, 0xc7, 0x7d, 0x2e, 0x1e, 0x9f, 0x79, 0xff, - 0x74, 0x3f, 0xef, 0x65, 0xbb, 0xc0, 0xf5, 0x4e, 0x5e, 0x53, 0xe0, 0x74, 0x28, 0x25, 0x71, 0xd2, 0x01, 0x14, 0xc1, - 0x6d, 0x3b, 0x96, 0x87, 0x88, 0x75, 0xa2, 0xa0, 0x0b, 0x55, 0xce, 0x34, 0x33, 0x8e, 0xf3, 0xe5, 0x95, 0xb4, 0x35, - 0xb8, 0xfd, 0x3c, 0xa4, 0x1a, 0x08, 0xbe, 0xd0, 0x85, 0x09, 0x0d, 0x26, 0x23, 0x6e, 0x6b, 0xda, 0x12, 0x8b, 0x25, - 0x2e, 0x10, 0x39, 0x43, 0x01, 0xc8, 0x21, 0xd3, 0x05, 0xa5, 0xfb, 0x64, 0x32, 0x3c, 0x52, 0xde, 0x88, 0xcc, 0xc8, - 0x70, 0x40, 0xb2, 0x63, 0x7d, 0xe7, 0x6a, 0x26, 0xc2, 0x24, 0xec, 0x22, 0x3c, 0xfd, 0x4b, 0x96, 0xa4, 0x7c, 0xcc, - 0xd3, 0x7e, 0xae, 0x98, 0x80, 0x79, 0x45, 0xe9, 0x25, 0x45, 0xe9, 0x42, 0x0d, 0x7d, 0xcb, 0xb1, 0x38, 0xa7, 0x01, - 0x43, 0x61, 0xaa, 0x84, 0x51, 0x16, 0xd3, 0x66, 0x22, 0x0b, 0x68, 0xc1, 0x39, 0x0a, 0x96, 0x2b, 0x02, 0x8f, 0x2a, - 0xb9, 0x2e, 0xe5, 0x37, 0x11, 0x15, 0x5a, 0x8e, 0x1d, 0x70, 0xc3, 0xba, 0x63, 0x90, 0x95, 0x09, 0x4c, 0xbe, 0xad, - 0x4a, 0x32, 0x2f, 0x39, 0x62, 0x11, 0xde, 0x2f, 0xe7, 0xdb, 0x6e, 0xd7, 0x38, 0x80, 0xbb, 0x76, 0x48, 0x15, 0x56, - 0x31, 0x28, 0x10, 0x26, 0x8a, 0x17, 0xa5, 0xf1, 0x07, 0x09, 0xb6, 0x3a, 0x46, 0xb4, 0xb1, 0xf4, 0xa3, 0x95, 0xb8, - 0x29, 0x47, 0xf4, 0xb2, 0x46, 0x2b, 0x45, 0xbd, 0xcb, 0x0a, 0x18, 0x6d, 0x91, 0x49, 0x48, 0x80, 0xf3, 0xd5, 0xb9, - 0x9a, 0x5f, 0x1f, 0x3a, 0x6a, 0xdb, 0x00, 0x59, 0x2a, 0x15, 0xa7, 0x68, 0x31, 0x58, 0x46, 0x82, 0x71, 0x5b, 0xb3, - 0x0a, 0x1c, 0xbf, 0x67, 0xf2, 0x00, 0xfa, 0x2d, 0xda, 0xe5, 0xae, 0x6a, 0x20, 0x7c, 0x94, 0x11, 0x5d, 0xb0, 0xcb, - 0x40, 0xde, 0x84, 0xd4, 0x1b, 0xb4, 0x60, 0x9b, 0xb6, 0x5b, 0xeb, 0xb9, 0xa8, 0x0f, 0x7d, 0x01, 0x9b, 0x74, 0x59, - 0x51, 0xa3, 0xb5, 0xa1, 0x86, 0xc3, 0xd5, 0x86, 0x23, 0xbb, 0x41, 0x4f, 0x13, 0x3a, 0x20, 0xf5, 0xb5, 0x9f, 0xde, - 0xae, 0x2c, 0x00, 0xfe, 0x81, 0xba, 0x48, 0xf4, 0xfb, 0x32, 0xbe, 0x81, 0x06, 0x41, 0x19, 0x40, 0xb0, 0x93, 0xae, - 0xad, 0xf4, 0x1c, 0x0c, 0xc2, 0x9a, 0x51, 0x0b, 0x6f, 0xca, 0x8f, 0x29, 0xc8, 0x10, 0x4e, 0x49, 0x6c, 0xf0, 0xa6, - 0xdb, 0xc3, 0xc2, 0x3e, 0xdc, 0xe1, 0xac, 0x36, 0xa5, 0x3f, 0x21, 0x9a, 0x4c, 0x74, 0x00, 0x76, 0x57, 0x4d, 0x6c, - 0x7c, 0xd8, 0x0f, 0x2b, 0x72, 0x42, 0x75, 0xa8, 0xe8, 0x13, 0x65, 0x62, 0x9b, 0x5f, 0x76, 0x24, 0x79, 0xa1, 0xb4, - 0xc4, 0x17, 0x06, 0xfb, 0xa6, 0x8b, 0xb1, 0x50, 0x71, 0x80, 0xc4, 0x1c, 0x32, 0xa6, 0x3b, 0x6e, 0x11, 0x07, 0xd3, - 0x66, 0xa0, 0xec, 0x6f, 0xd6, 0xdb, 0x81, 0xad, 0x01, 0x28, 0x73, 0xcb, 0x4f, 0xfa, 0x5b, 0x14, 0x47, 0xb0, 0xa8, - 0x5f, 0x47, 0xa0, 0x25, 0xd7, 0xb5, 0x4f, 0xe2, 0x2c, 0x67, 0xe9, 0x91, 0x1b, 0x2e, 0xfa, 0x7d, 0x55, 0x24, 0x13, - 0xa2, 0xe9, 0x50, 0xc7, 0x56, 0x7c, 0xac, 0xa3, 0xd8, 0x2a, 0xdc, 0x80, 0xdf, 0x49, 0x43, 0xc4, 0x08, 0x19, 0xe3, - 0xb4, 0x24, 0xd0, 0xa9, 0xe5, 0x3c, 0x6d, 0x04, 0x6a, 0x6b, 0x52, 0xe6, 0x9e, 0xed, 0x4f, 0xa4, 0x83, 0x92, 0x3c, - 0xb2, 0x02, 0x68, 0xff, 0x56, 0x1f, 0x7d, 0x69, 0xa5, 0x20, 0x48, 0xb3, 0x24, 0x32, 0x38, 0xa3, 0xe3, 0x1c, 0x37, - 0x5e, 0x48, 0x90, 0x2c, 0x1e, 0x4e, 0x42, 0x9f, 0xb4, 0x59, 0x6b, 0xf0, 0xa4, 0xbc, 0x28, 0x37, 0x2e, 0x00, 0x75, - 0x7a, 0xc8, 0x16, 0x0d, 0x73, 0x16, 0xc8, 0x4e, 0xbc, 0x87, 0x18, 0x1e, 0xea, 0x52, 0x69, 0x01, 0x73, 0x7a, 0x86, - 0xa4, 0xb9, 0x2c, 0xb2, 0x1a, 0x17, 0x04, 0xfd, 0x66, 0xf2, 0x23, 0xf4, 0x39, 0x26, 0x4e, 0x97, 0xa7, 0x31, 0x55, - 0x23, 0x71, 0x7a, 0x36, 0xcf, 0xc0, 0x3a, 0x62, 0x8f, 0xec, 0x42, 0x2b, 0x86, 0xe8, 0x57, 0x71, 0x29, 0xe1, 0x30, - 0xcb, 0x0b, 0x41, 0x47, 0xf9, 0xc5, 0xc8, 0xd9, 0x8c, 0x09, 0x2e, 0x7d, 0xe2, 0x86, 0x1f, 0x4a, 0xa9, 0xa1, 0x80, - 0xcd, 0x10, 0x82, 0xf4, 0x57, 0x12, 0x7d, 0xb0, 0xd6, 0xc0, 0xf3, 0x9e, 0x2e, 0x26, 0xdc, 0x6b, 0xc2, 0x8c, 0x87, - 0x48, 0x4d, 0x28, 0x74, 0x22, 0x3a, 0x00, 0x43, 0x58, 0x76, 0xd3, 0xad, 0x25, 0xef, 0xc5, 0x3a, 0x0d, 0x9a, 0x83, - 0xa7, 0x0c, 0xc6, 0x1b, 0xb9, 0x1c, 0x47, 0x8c, 0xd8, 0xd7, 0x3d, 0x21, 0x7b, 0x2f, 0x46, 0x10, 0x21, 0x5f, 0x1c, - 0x90, 0x31, 0x45, 0x3b, 0xd5, 0xb4, 0xa4, 0x6b, 0xf6, 0xd9, 0x22, 0xf4, 0xcd, 0xed, 0x71, 0x46, 0x64, 0x4a, 0xaa, - 0x2f, 0x4c, 0x10, 0x11, 0x7a, 0x3a, 0x48, 0xc1, 0x9c, 0xdd, 0x07, 0xaf, 0x28, 0x02, 0x01, 0xd6, 0xdb, 0x6a, 0x78, - 0x52, 0x9d, 0x4f, 0x81, 0xed, 0xba, 0x90, 0x4e, 0xb3, 0x34, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x37, 0x49, 0x0d, 0x63, - 0xba, 0xa8, 0x7c, 0xc0, 0x1f, 0xd4, 0x47, 0xdc, 0xa2, 0xbf, 0x8a, 0xc7, 0x19, 0xf6, 0x92, 0x86, 0x6e, 0x12, 0xdb, - 0x84, 0xa8, 0xaa, 0xc6, 0xba, 0xe6, 0x66, 0xf4, 0xb8, 0x22, 0x03, 0xd7, 0x48, 0xfd, 0x06, 0xad, 0x83, 0x4a, 0x0b, - 0xeb, 0x59, 0x7c, 0x0a, 0xf2, 0xdc, 0x1a, 0x5b, 0xee, 0x4f, 0x90, 0xc4, 0x8b, 0xd1, 0x69, 0x46, 0x7b, 0x86, 0x97, - 0x19, 0x0e, 0x01, 0xf6, 0x9d, 0xe3, 0xdd, 0xae, 0xdd, 0x6f, 0x49, 0xc6, 0x4e, 0xc2, 0x9f, 0x6d, 0x5d, 0x92, 0x34, - 0x06, 0xd4, 0x94, 0x7f, 0x57, 0x3f, 0xe4, 0xb1, 0x17, 0x50, 0x71, 0x1f, 0x23, 0x5d, 0x2f, 0x34, 0x9f, 0xbe, 0x44, - 0x3b, 0xad, 0xdc, 0x3a, 0xbc, 0x45, 0x26, 0xee, 0x3e, 0xc2, 0x00, 0x73, 0x21, 0x77, 0x47, 0xa0, 0xee, 0xad, 0x5f, - 0x10, 0x6f, 0x8a, 0xba, 0xc2, 0x54, 0x4a, 0xb6, 0x1a, 0xbc, 0x96, 0x98, 0x85, 0x9a, 0xcb, 0x95, 0x46, 0xd8, 0xca, - 0x11, 0xa8, 0x83, 0x8e, 0xa4, 0xad, 0xf5, 0xda, 0xc6, 0xac, 0xf2, 0x54, 0x6e, 0x26, 0x0b, 0xfa, 0x1c, 0x49, 0x99, - 0x33, 0x87, 0xce, 0x8a, 0x42, 0x57, 0x25, 0x61, 0xa9, 0xe5, 0xd6, 0xeb, 0xb3, 0x8e, 0x5f, 0xbc, 0xb7, 0x03, 0x88, - 0x05, 0x7b, 0x56, 0x3b, 0x19, 0x1c, 0x76, 0x5b, 0x5c, 0x56, 0xb9, 0xda, 0xa6, 0x44, 0x59, 0x42, 0x60, 0x2e, 0x59, - 0x7d, 0x0d, 0xd0, 0x53, 0x14, 0x45, 0x1a, 0x74, 0xd5, 0x75, 0x41, 0x42, 0xb8, 0x52, 0xf1, 0x77, 0x17, 0x66, 0xe4, - 0x08, 0x97, 0x88, 0xdc, 0x41, 0x57, 0x4a, 0x7e, 0x3c, 0x21, 0x3d, 0x9d, 0x10, 0x09, 0xbd, 0xbc, 0x31, 0x78, 0x97, - 0x83, 0xc7, 0xfe, 0x2e, 0xe4, 0x0a, 0x1f, 0x12, 0x6c, 0x39, 0x0c, 0xa5, 0xdc, 0x14, 0xe1, 0xbe, 0x2f, 0xd0, 0x49, - 0xb9, 0x8a, 0xe0, 0x20, 0xb5, 0x23, 0x9f, 0xab, 0x23, 0x7f, 0x66, 0x73, 0x0a, 0x97, 0xe6, 0x64, 0xd7, 0x28, 0x42, - 0x99, 0x62, 0xef, 0x79, 0x62, 0x60, 0x4a, 0x12, 0x3e, 0xbb, 0x4e, 0x64, 0xad, 0x75, 0x7f, 0xa7, 0x3d, 0x88, 0x17, - 0x4d, 0xa4, 0xfc, 0x20, 0x36, 0x1f, 0x68, 0x71, 0x5d, 0x5e, 0x63, 0xeb, 0x8e, 0x62, 0x06, 0xa0, 0xb9, 0xc9, 0xba, - 0xad, 0x32, 0xb9, 0xc1, 0x2a, 0x20, 0x4f, 0x67, 0xa1, 0xf1, 0x2c, 0xcd, 0x60, 0x9e, 0x9f, 0x38, 0x2b, 0x46, 0x2a, - 0x04, 0x8a, 0xd2, 0x52, 0x9b, 0xd5, 0x49, 0x5c, 0xc9, 0x8e, 0x3d, 0x6e, 0xd9, 0x42, 0x27, 0x20, 0xd5, 0xe3, 0x04, - 0xb4, 0x0d, 0xde, 0x51, 0x4a, 0x76, 0x67, 0x19, 0x07, 0xdb, 0x85, 0x7f, 0x07, 0x66, 0x1d, 0xea, 0xab, 0x08, 0x2a, - 0xd2, 0x26, 0xb6, 0x6a, 0x4a, 0x91, 0x74, 0x42, 0xeb, 0x62, 0x0b, 0x8a, 0xe2, 0x6a, 0x8f, 0xf8, 0xaa, 0x95, 0xe1, - 0xce, 0xec, 0xb6, 0xc8, 0xe6, 0x0c, 0xf7, 0x64, 0xe0, 0x8c, 0x2d, 0xa1, 0xcd, 0xac, 0x25, 0xf6, 0x71, 0x4f, 0x37, - 0xe9, 0xef, 0xb6, 0x92, 0x66, 0xd0, 0x88, 0xa1, 0xa5, 0x65, 0xf2, 0xef, 0x8d, 0xc9, 0xbc, 0x16, 0x43, 0x63, 0x4e, - 0x31, 0xdd, 0x30, 0x70, 0x8b, 0x2a, 0xb5, 0x19, 0xd7, 0x8a, 0x3e, 0xfd, 0x4e, 0x23, 0x39, 0xa4, 0x00, 0x4d, 0x28, - 0x05, 0x11, 0xc8, 0x97, 0x14, 0x82, 0x3b, 0x25, 0xdb, 0x44, 0x96, 0x5b, 0x89, 0xcb, 0xa2, 0xd3, 0xc3, 0xf1, 0x0f, - 0x27, 0xa0, 0x42, 0x5f, 0xae, 0x58, 0xd0, 0x4f, 0xf4, 0x3e, 0x26, 0xea, 0x58, 0xca, 0xc9, 0xf1, 0xe9, 0xd2, 0x55, - 0x55, 0x01, 0x2d, 0x57, 0xaf, 0x8b, 0x0e, 0xce, 0x35, 0x65, 0x80, 0xd4, 0x63, 0x14, 0xb6, 0x10, 0x26, 0x7f, 0x04, - 0xde, 0x4f, 0xef, 0xe5, 0xb8, 0xed, 0x36, 0x45, 0x8f, 0x74, 0x76, 0xa7, 0x48, 0x4d, 0x2a, 0xd1, 0xca, 0xc9, 0x31, - 0x9e, 0x1e, 0xf2, 0x62, 0x0c, 0xd8, 0x31, 0x71, 0xb3, 0x49, 0x0d, 0x18, 0x13, 0x80, 0x23, 0x33, 0x15, 0xdb, 0x54, - 0x5b, 0x2b, 0x13, 0xa2, 0xb6, 0xe5, 0x7c, 0x59, 0x4b, 0xa7, 0x28, 0xef, 0x60, 0x0e, 0x81, 0x79, 0xee, 0x32, 0x6d, - 0xa0, 0x9a, 0x22, 0xb3, 0xa4, 0x1d, 0xd5, 0xf1, 0x52, 0x6c, 0xbc, 0xf8, 0xa9, 0xc0, 0xbd, 0x91, 0xaa, 0x57, 0x56, - 0x0b, 0x6e, 0xce, 0x94, 0x71, 0xb8, 0xc5, 0x55, 0xe1, 0x24, 0xe2, 0x01, 0x8c, 0x3e, 0x63, 0x31, 0x9c, 0x2f, 0xf6, - 0x23, 0x3e, 0x2c, 0x6a, 0x0a, 0x6f, 0xab, 0xb7, 0x72, 0x5c, 0x86, 0x80, 0xea, 0x11, 0xc4, 0xe9, 0x4e, 0x65, 0xc1, - 0xeb, 0x8c, 0x1c, 0x11, 0xbe, 0x95, 0xe2, 0xa8, 0x64, 0x1c, 0xc4, 0x67, 0xb1, 0xe9, 0xc1, 0x31, 0x2d, 0x3c, 0x63, - 0x22, 0x77, 0xc0, 0x3c, 0xa3, 0xf1, 0x3d, 0x3e, 0x73, 0x43, 0x7c, 0xe7, 0xb5, 0xf7, 0xb6, 0x22, 0x3d, 0x37, 0xb3, - 0xf9, 0xc4, 0x9b, 0x86, 0xa8, 0xf3, 0xe1, 0xad, 0x27, 0x3a, 0xe7, 0x15, 0x2c, 0xe2, 0x50, 0xb8, 0x21, 0xcd, 0xe8, - 0x0b, 0xed, 0x1e, 0xb2, 0x79, 0x6a, 0xba, 0x8b, 0x0b, 0xd8, 0xa3, 0xe9, 0x77, 0x67, 0x04, 0xc4, 0x3e, 0x41, 0xc4, - 0x97, 0x3c, 0xb8, 0xbd, 0x75, 0x2b, 0x6d, 0x75, 0x8c, 0x91, 0x6a, 0xd3, 0xdc, 0x02, 0xbf, 0xdf, 0x97, 0x30, 0x7b, - 0x1c, 0x83, 0x77, 0x0d, 0x02, 0xc4, 0x2f, 0x40, 0x58, 0x35, 0x6d, 0x68, 0xc0, 0x77, 0xf8, 0x32, 0x5b, 0xe6, 0x5e, - 0x23, 0xaa, 0x1e, 0xe6, 0xf2, 0xc5, 0xc9, 0xae, 0x36, 0x22, 0x95, 0xdb, 0x7e, 0xe2, 0xcf, 0x0f, 0x86, 0x25, 0x3d, - 0x47, 0x87, 0x71, 0x20, 0x37, 0xe4, 0xcc, 0x28, 0xb1, 0x09, 0xa7, 0xad, 0x9c, 0x87, 0xc6, 0x3c, 0x15, 0x04, 0x64, - 0xf8, 0xff, 0x7a, 0x38, 0x48, 0xcc, 0x5b, 0x37, 0x28, 0x57, 0xd5, 0x06, 0xd6, 0x64, 0x2f, 0x0e, 0x22, 0xa8, 0xf2, - 0x50, 0xa4, 0x58, 0x5f, 0x74, 0x58, 0x97, 0xc4, 0x42, 0x26, 0x82, 0x51, 0x21, 0x49, 0x90, 0xad, 0xa3, 0x5b, 0xa3, - 0xdc, 0x25, 0xbd, 0x4e, 0x40, 0xcf, 0xf4, 0x32, 0xfe, 0x18, 0xc7, 0xa2, 0xac, 0x25, 0x7f, 0xee, 0x49, 0xb6, 0xcb, - 0xe8, 0xae, 0x66, 0xac, 0x23, 0x22, 0x36, 0xb4, 0x1c, 0x1d, 0xe7, 0x65, 0x51, 0x72, 0xdc, 0xb4, 0x27, 0x70, 0x2c, - 0xbc, 0xb3, 0xa2, 0x68, 0xe6, 0x42, 0xae, 0xe9, 0xab, 0x63, 0x8a, 0xd6, 0xe1, 0x31, 0x7b, 0x6d, 0xdb, 0x12, 0x3d, - 0x5c, 0x8e, 0xf1, 0x52, 0x1a, 0x2a, 0x34, 0x87, 0xda, 0x5a, 0x5d, 0xea, 0x39, 0x2c, 0x63, 0xc5, 0x17, 0x85, 0x52, - 0xee, 0xa2, 0xe1, 0xa9, 0x8b, 0x69, 0x40, 0x37, 0x69, 0x44, 0x3f, 0x91, 0x99, 0x53, 0x8d, 0x3c, 0xe9, 0xc7, 0xbe, - 0x51, 0x85, 0x01, 0xd0, 0xf1, 0x8a, 0x91, 0xec, 0xbe, 0x2f, 0x57, 0x87, 0x12, 0x7c, 0x7a, 0xd6, 0x51, 0x2c, 0xb5, - 0x8e, 0xf7, 0x79, 0x2d, 0xc7, 0x77, 0x37, 0x84, 0xd1, 0xba, 0x3d, 0x30, 0x2b, 0x9c, 0x8b, 0x49, 0x31, 0x6e, 0xd9, - 0x0a, 0x13, 0xe6, 0x11, 0x4a, 0xbc, 0x9b, 0xa2, 0xb1, 0x5f, 0x99, 0x12, 0x9d, 0x17, 0xe1, 0x65, 0x73, 0xc5, 0x42, - 0xa9, 0x7a, 0x71, 0x89, 0xfd, 0xc6, 0xbd, 0xed, 0x39, 0xe4, 0xb9, 0x0c, 0x1b, 0x6f, 0x67, 0x79, 0x7a, 0xc4, 0xe4, - 0xfc, 0x08, 0x9b, 0x79, 0x20, 0x7d, 0x2d, 0x04, 0x18, 0xf5, 0x9e, 0x1c, 0xbf, 0x7c, 0xdf, 0xcb, 0xae, 0x71, 0xbc, - 0x30, 0xd2, 0x38, 0xce, 0x17, 0xe4, 0x29, 0xb1, 0x44, 0x69, 0xe6, 0x8b, 0x7a, 0x94, 0x03, 0xf1, 0xdc, 0x0b, 0x76, - 0x3d, 0x6d, 0xc7, 0xbf, 0x17, 0xee, 0x4a, 0x7a, 0x34, 0xfa, 0x04, 0xbe, 0x1e, 0xfe, 0x73, 0x74, 0x58, 0x90, 0x44, - 0x44, 0x4f, 0xe3, 0x48, 0x4f, 0x6d, 0x59, 0xea, 0x3d, 0x3b, 0xd6, 0x44, 0xbd, 0xf1, 0x3a, 0x23, 0x94, 0xb6, 0xa1, - 0x94, 0xb6, 0x83, 0x32, 0x82, 0x25, 0xb0, 0x69, 0x53, 0x08, 0x51, 0x8d, 0xff, 0x82, 0x9b, 0xa7, 0x08, 0x3f, 0xeb, - 0x44, 0x69, 0x36, 0x53, 0x53, 0x74, 0x67, 0x34, 0x00, 0x6b, 0x79, 0x9f, 0x0d, 0xd0, 0xfa, 0xa1, 0xae, 0xbc, 0xc2, - 0xc0, 0x6a, 0x55, 0x57, 0x02, 0xb5, 0x22, 0x50, 0x82, 0x04, 0x4e, 0x78, 0x2f, 0x22, 0xa2, 0x1b, 0x98, 0x54, 0x7a, - 0xb0, 0x65, 0x3b, 0xb7, 0x0d, 0xbb, 0xd7, 0xd2, 0xe7, 0x87, 0xf7, 0x6a, 0xd2, 0x53, 0x57, 0x76, 0xc7, 0x43, 0xe4, - 0x24, 0x39, 0xbb, 0x07, 0x88, 0xe4, 0x51, 0x32, 0xd8, 0xb9, 0x7b, 0x7b, 0xda, 0xda, 0x1d, 0x62, 0x61, 0x5b, 0xf0, - 0xd3, 0x1d, 0xb1, 0x18, 0xa5, 0xdd, 0xec, 0x93, 0x9f, 0x67, 0x70, 0x58, 0x7a, 0x0b, 0xe0, 0x29, 0xd6, 0xdd, 0x5f, - 0xcd, 0xac, 0xe8, 0x1e, 0xff, 0xe2, 0xa1, 0x2b, 0x0a, 0xe9, 0x88, 0x59, 0xdc, 0xe2, 0xb8, 0x2e, 0x3b, 0xab, 0xbb, - 0x45, 0xce, 0x6d, 0x49, 0x84, 0x4a, 0x09, 0xc9, 0xe5, 0x98, 0x95, 0x1a, 0xdb, 0x23, 0xca, 0xe0, 0xb4, 0xb7, 0x97, - 0x7e, 0x63, 0xde, 0xc2, 0xf4, 0x05, 0xa0, 0x26, 0x60, 0xb9, 0x20, 0x1b, 0xef, 0x3e, 0x00, 0xcc, 0xd2, 0xaa, 0xab, - 0x33, 0x06, 0x17, 0xb7, 0xee, 0x7a, 0xc3, 0x22, 0x33, 0x9a, 0x89, 0xba, 0xc9, 0xdd, 0x11, 0x55, 0x8c, 0x16, 0x26, - 0xdb, 0x2f, 0xa5, 0xe1, 0xd3, 0x6a, 0x44, 0x2b, 0x2d, 0x5a, 0x46, 0x87, 0x5d, 0x5f, 0xc9, 0x51, 0x22, 0xb1, 0x5c, - 0x2c, 0xbb, 0xf2, 0x56, 0x98, 0xf8, 0x31, 0xb1, 0x36, 0x66, 0x44, 0x5a, 0xb2, 0x85, 0xc1, 0x11, 0x49, 0x79, 0xd4, - 0xdd, 0xb2, 0x6a, 0x72, 0x1b, 0x67, 0x2b, 0x3c, 0xdd, 0x52, 0xd4, 0x14, 0xaa, 0x43, 0xb4, 0xdd, 0x07, 0x19, 0x24, - 0xd3, 0x46, 0x91, 0xf3, 0xb9, 0xed, 0xb1, 0x88, 0x3a, 0x5d, 0xd1, 0x69, 0x91, 0x88, 0xb9, 0xdd, 0x53, 0xb4, 0x1d, - 0x25, 0xc9, 0x93, 0x94, 0x4c, 0x27, 0x0e, 0x54, 0xd3, 0x86, 0x5c, 0x4b, 0xef, 0x5f, 0x2b, 0x02, 0x71, 0xf1, 0x1f, - 0xf2, 0xb2, 0xed, 0xbb, 0x03, 0x83, 0x08, 0x3a, 0x98, 0x23, 0x09, 0xcc, 0x4b, 0x2d, 0x1d, 0x94, 0x48, 0x12, 0x91, - 0x9f, 0x34, 0xcc, 0xae, 0x4b, 0xd6, 0xe8, 0x83, 0x56, 0xba, 0x33, 0x99, 0x35, 0x24, 0x52, 0xaf, 0x49, 0x6d, 0x6d, - 0xb1, 0x89, 0x11, 0xcf, 0x7c, 0x67, 0x9d, 0x88, 0x22, 0xf1, 0x20, 0x73, 0x62, 0xa9, 0x3c, 0x5b, 0x44, 0x89, 0xaf, - 0x70, 0xf6, 0xb5, 0x5e, 0xec, 0x4e, 0x8b, 0x2c, 0xe6, 0x87, 0x91, 0x5f, 0x0e, 0x37, 0xbb, 0x15, 0x29, 0xea, 0xad, - 0xf1, 0xe5, 0x05, 0xcd, 0x6c, 0x5c, 0x3b, 0x71, 0xcc, 0x19, 0xd2, 0x48, 0x21, 0x48, 0x48, 0x9f, 0x8e, 0xf0, 0x5a, - 0x04, 0x07, 0x36, 0x6a, 0x7a, 0xc7, 0x9e, 0x67, 0x2b, 0x77, 0x57, 0x43, 0xc3, 0xb6, 0x43, 0x22, 0x48, 0xd0, 0x78, - 0x93, 0x59, 0x33, 0x34, 0x3f, 0xec, 0x3a, 0x6f, 0xcf, 0xf5, 0xf0, 0x8d, 0x62, 0x60, 0x69, 0x13, 0x09, 0xe0, 0x52, - 0x51, 0x95, 0xe6, 0xd6, 0x7e, 0x90, 0x43, 0x36, 0xe2, 0x8b, 0x56, 0xfd, 0x8a, 0x80, 0xee, 0x24, 0x21, 0x21, 0x40, - 0xd3, 0xeb, 0xfa, 0x3e, 0x5c, 0x24, 0x2c, 0x0e, 0x08, 0xdf, 0x55, 0xf0, 0xdf, 0x24, 0x4d, 0xaf, 0x4b, 0x13, 0xfa, - 0xb1, 0x28, 0x97, 0x83, 0x83, 0x2c, 0x10, 0x6f, 0x01, 0xd1, 0x10, 0x04, 0x82, 0x42, 0x58, 0x38, 0xa6, 0x12, 0xfa, - 0x17, 0x5a, 0x43, 0xc1, 0x04, 0x98, 0x8e, 0xc6, 0xb9, 0x34, 0x28, 0xaa, 0xad, 0x74, 0x9a, 0x53, 0x36, 0x5c, 0x34, - 0x0c, 0x32, 0xeb, 0x9f, 0xc2, 0x10, 0xa7, 0x98, 0x26, 0xe3, 0xfe, 0x2e, 0xc1, 0x78, 0xba, 0x6d, 0x3e, 0x51, 0xca, - 0x6a, 0x9f, 0xb5, 0x78, 0x42, 0x2b, 0x9e, 0x57, 0xa2, 0x3e, 0xa7, 0xd7, 0xde, 0x7f, 0xf4, 0x86, 0xef, 0xe0, 0xc9, - 0x47, 0x25, 0x7a, 0x1b, 0x27, 0x96, 0x3b, 0x58, 0x04, 0x58, 0xe4, 0x7d, 0xd7, 0x8c, 0xa4, 0x40, 0x86, 0x3a, 0xc0, - 0x5c, 0x63, 0x6e, 0xfb, 0x48, 0x0d, 0x6d, 0x0f, 0xe5, 0xde, 0xe4, 0xda, 0x34, 0xac, 0x7a, 0x58, 0x60, 0x79, 0x75, - 0xdd, 0xe6, 0xe6, 0x00, 0x79, 0xec, 0x5a, 0x8c, 0x08, 0x72, 0x44, 0x86, 0xe3, 0xc1, 0x6d, 0x42, 0x41, 0x80, 0x02, - 0xaa, 0xa6, 0x9a, 0xd6, 0xe1, 0xfe, 0x9c, 0x0f, 0xe2, 0x50, 0xd7, 0x84, 0xd8, 0xa8, 0x3c, 0x42, 0xaf, 0xb9, 0xef, - 0x13, 0xfd, 0x3e, 0xe5, 0x86, 0xc6, 0x1b, 0x24, 0x40, 0x2e, 0xae, 0xce, 0x93, 0x44, 0xdd, 0x18, 0xab, 0xa3, 0x38, - 0x22, 0x0c, 0x50, 0x98, 0x63, 0x38, 0xdc, 0x4e, 0x05, 0x47, 0x4b, 0x02, 0x6d, 0x2c, 0x55, 0x2f, 0xb7, 0xdf, 0x66, - 0x5d, 0xea, 0x1f, 0x14, 0x0c, 0xa2, 0xd3, 0x43, 0x5e, 0x38, 0x10, 0x32, 0xd6, 0xf7, 0xe1, 0xf2, 0x1e, 0x67, 0xb4, - 0x2e, 0xa3, 0x46, 0x30, 0x06, 0x0f, 0x50, 0xce, 0xaa, 0xc7, 0xd1, 0x2e, 0x20, 0x96, 0x87, 0xf4, 0xa1, 0xc9, 0x8c, - 0x90, 0x2d, 0x72, 0xf9, 0xa5, 0x16, 0xf9, 0xab, 0xd0, 0xb5, 0x78, 0xee, 0x01, 0x9d, 0x5a, 0x70, 0x0c, 0x75, 0x83, - 0xaf, 0xba, 0xe9, 0xaa, 0x96, 0xda, 0x36, 0xc7, 0xc8, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x6c, 0xdf, 0x7b, 0x07, - 0x80, 0x98, 0x02, 0x7a, 0x01, 0xb0, 0x1d, 0x5e, 0x0a, 0x3e, 0xf1, 0xe0, 0xb6, 0x3a, 0xec, 0xd8, 0x99, 0xa4, 0x71, - 0x1e, 0x4d, 0xbd, 0x39, 0xc7, 0x5c, 0xe8, 0x71, 0xec, 0xe7, 0x06, 0xd7, 0x9f, 0xac, 0x18, 0xbe, 0x6d, 0x4d, 0x70, - 0x78, 0xae, 0x72, 0x36, 0x24, 0x11, 0x4b, 0xd6, 0x3d, 0x47, 0x5f, 0x48, 0xe4, 0x69, 0x1b, 0xdf, 0x2f, 0xf4, 0xd5, - 0x39, 0x75, 0x91, 0x9d, 0x63, 0x92, 0x09, 0xf4, 0x60, 0xf2, 0x5e, 0x59, 0x1c, 0x1a, 0xab, 0x94, 0x59, 0xfc, 0xd0, - 0xb9, 0xa6, 0xb7, 0xf7, 0xab, 0x75, 0x29, 0xe5, 0x53, 0xad, 0x72, 0x2b, 0xbf, 0x8d, 0x1d, 0x4d, 0x3b, 0x35, 0xa0, - 0xdd, 0xd6, 0x37, 0x74, 0x1a, 0x45, 0x24, 0xe9, 0xee, 0x82, 0x5b, 0x78, 0x06, 0xd3, 0x18, 0x51, 0xb0, 0xe7, 0x53, - 0xeb, 0xf2, 0xb5, 0x97, 0x95, 0x78, 0x45, 0xbc, 0x2b, 0x06, 0x63, 0xe5, 0x84, 0x0e, 0x16, 0x69, 0x1a, 0x68, 0xe0, - 0x24, 0x49, 0xdc, 0xaa, 0x24, 0x7e, 0x6a, 0xf9, 0x17, 0xd4, 0xdc, 0xa8, 0x3c, 0x15, 0xf1, 0x75, 0x49, 0x98, 0x39, - 0x2e, 0xd5, 0xbd, 0x51, 0x79, 0x50, 0x8e, 0x79, 0xba, 0x66, 0x2c, 0x5a, 0xba, 0x9d, 0x22, 0xf3, 0x64, 0xcf, 0x9b, - 0x9b, 0x11, 0x25, 0x4a, 0x84, 0xea, 0x42, 0xaf, 0x72, 0x6d, 0x16, 0x3a, 0xd2, 0x88, 0x4d, 0x6b, 0x35, 0x9b, 0xd8, - 0xfd, 0x70, 0x0e, 0x52, 0x95, 0x3d, 0xc1, 0x35, 0xf4, 0xbc, 0x13, 0x86, 0xcd, 0xb5, 0xae, 0x43, 0x23, 0x86, 0xcc, - 0x80, 0x99, 0x66, 0x01, 0xa6, 0x40, 0x16, 0x71, 0x5f, 0x0d, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0xf5, 0x7c, 0xab, - 0xad, 0x3a, 0x26, 0xff, 0x32, 0x78, 0x0d, 0x67, 0x00, 0x45, 0x89, 0xe1, 0x44, 0xd3, 0x5e, 0xa9, 0xd5, 0x00, 0x61, - 0x9e, 0x10, 0xa3, 0xb0, 0x82, 0x6d, 0xd1, 0x68, 0xd5, 0x55, 0x30, 0x80, 0x1a, 0xe6, 0xc9, 0x08, 0x8d, 0x22, 0x32, - 0x1a, 0x5f, 0xd8, 0x8d, 0xbc, 0xb2, 0x00, 0xcb, 0x9a, 0xf4, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x8e, 0x12, - 0x72, 0xc3, 0x0d, 0x9a, 0x36, 0xa9, 0x37, 0x1e, 0x07, 0x7c, 0x6b, 0xc6, 0x99, 0x86, 0x76, 0xdb, 0x5a, 0xb9, 0x0f, - 0xec, 0xc0, 0x0d, 0xb7, 0x0d, 0xdf, 0xa9, 0x6a, 0x27, 0xf3, 0xf5, 0xeb, 0xdd, 0xee, 0x12, 0x6b, 0x42, 0x9b, 0x8e, - 0xb2, 0x06, 0xb6, 0x6d, 0x51, 0xcc, 0xc5, 0x48, 0xd7, 0x78, 0xb7, 0xd8, 0x77, 0x20, 0xdb, 0xf7, 0x60, 0xad, 0x92, - 0x90, 0x93, 0xab, 0x74, 0x7e, 0x8d, 0x7e, 0xd2, 0xe9, 0x2a, 0x91, 0x99, 0x5d, 0xe4, 0x77, 0x99, 0xa9, 0xef, 0x65, - 0xaa, 0xc7, 0xb5, 0x56, 0xa4, 0xc0, 0x56, 0xa8, 0x0a, 0xcf, 0x21, 0x30, 0x5d, 0xb2, 0xf2, 0x7f, 0x20, 0xe2, 0x9c, - 0x8c, 0x2b, 0xa1, 0xbd, 0x51, 0x35, 0x03, 0x18, 0x12, 0x8a, 0xa1, 0x89, 0xe5, 0xf4, 0xb8, 0xd4, 0x20, 0xaa, 0x93, - 0x06, 0x90, 0xe5, 0x81, 0x10, 0xf0, 0x13, 0x05, 0xd4, 0x99, 0x99, 0x30, 0xf0, 0x93, 0xc0, 0x59, 0x5a, 0x4d, 0x91, - 0x7e, 0x31, 0xe0, 0x0c, 0x45, 0xdd, 0x90, 0x7e, 0xc5, 0x94, 0xe8, 0x0e, 0xbf, 0x52, 0x68, 0x7d, 0x6a, 0x66, 0x2e, - 0x98, 0x91, 0x4e, 0x1a, 0xf8, 0x15, 0x2e, 0x6a, 0x0b, 0xfe, 0x32, 0xa5, 0x26, 0x33, 0x45, 0x98, 0xc9, 0x01, 0x5c, - 0x2a, 0xb7, 0xc5, 0xb3, 0xaa, 0x26, 0x30, 0xfb, 0x22, 0x65, 0x74, 0xe2, 0x18, 0x75, 0xdf, 0x6e, 0x38, 0x4a, 0x52, - 0xde, 0xfe, 0x7a, 0x95, 0x35, 0xca, 0x0e, 0x99, 0x59, 0xea, 0x2a, 0xfe, 0xd4, 0x24, 0x77, 0xbd, 0x0c, 0x9d, 0x74, - 0x2b, 0xb8, 0x65, 0x94, 0xf3, 0x0c, 0xcb, 0xdd, 0x18, 0xd1, 0x61, 0x73, 0x2f, 0x5d, 0xdf, 0xa5, 0xc9, 0xce, 0xad, - 0x4a, 0x4c, 0x08, 0x29, 0xb4, 0x5f, 0x9f, 0x9d, 0xfb, 0xe3, 0xd5, 0xf6, 0xdb, 0x51, 0xdf, 0x73, 0xe3, 0x7c, 0x3a, - 0xfe, 0xed, 0x72, 0xdb, 0x1d, 0x4c, 0x33, 0x54, 0x61, 0x5a, 0x3a, 0x08, 0xdd, 0x35, 0x0f, 0xd0, 0xbf, 0x24, 0x3e, - 0xf5, 0xfb, 0x0b, 0x2a, 0x1d, 0xd0, 0x26, 0xb3, 0x35, 0x15, 0xb2, 0x38, 0x28, 0xa1, 0x6c, 0xd3, 0x2e, 0x4d, 0x8b, - 0x29, 0x72, 0xa0, 0x6e, 0x21, 0x03, 0x52, 0xb2, 0x70, 0x99, 0x41, 0xe5, 0x57, 0xf1, 0x3a, 0xf1, 0x75, 0x7e, 0xb5, - 0x31, 0x32, 0xa2, 0x70, 0x55, 0xc8, 0x35, 0x7c, 0x47, 0x8b, 0x79, 0x01, 0xed, 0xa4, 0xda, 0x38, 0xf4, 0x55, 0xa3, - 0x8e, 0x49, 0xa0, 0xe3, 0xc3, 0x4f, 0x3e, 0x53, 0x37, 0x98, 0xdd, 0xad, 0x09, 0xf8, 0xb1, 0x39, 0x7b, 0x71, 0xa3, - 0x87, 0x38, 0xb5, 0x96, 0x7d, 0xbc, 0x50, 0xf6, 0xa8, 0x1a, 0x79, 0x6b, 0x8d, 0x83, 0xdc, 0xa4, 0x61, 0x6d, 0x38, - 0x29, 0x14, 0xe0, 0xe1, 0x52, 0x7e, 0x48, 0x0a, 0x97, 0xde, 0xa8, 0x44, 0x98, 0x07, 0xb0, 0x13, 0xb6, 0xd4, 0xbd, - 0x51, 0x49, 0x0b, 0xa8, 0x1e, 0xe9, 0xc9, 0xa0, 0x98, 0xce, 0x89, 0xc4, 0x98, 0xf1, 0x25, 0xdd, 0xf4, 0x43, 0xb4, - 0xba, 0x66, 0xd8, 0xc3, 0xfb, 0x58, 0x90, 0x20, 0x87, 0x04, 0x1b, 0xd7, 0x19, 0x42, 0xec, 0xa4, 0xc2, 0xf7, 0x7c, - 0x55, 0x6c, 0x99, 0x7f, 0x46, 0xa8, 0x6d, 0xeb, 0xbe, 0xed, 0x11, 0xe5, 0xb5, 0xd2, 0xb7, 0xb9, 0xbf, 0xe2, 0x8c, - 0xf1, 0x72, 0x86, 0xc6, 0x23, 0x2f, 0xfb, 0x39, 0xcc, 0xcf, 0x7e, 0x75, 0x03, 0x16, 0x20, 0x71, 0x6c, 0xc1, 0xb1, - 0xa7, 0xe4, 0x68, 0xae, 0x73, 0x3e, 0xb6, 0x11, 0xcc, 0x92, 0x69, 0x40, 0x64, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, - 0x71, 0x91, 0x28, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7c, 0x6f, 0x22, 0xf7, 0x05, 0x2d, 0x46, 0x59, 0xfc, 0xb1, 0xab, - 0xb6, 0xb6, 0x8a, 0x1c, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0xe3, 0x58, 0x15, 0x50, 0xbe, 0xce, 0x95, 0xd6, 0x52, - 0x5d, 0xa0, 0x8b, 0x43, 0xf7, 0x51, 0x8b, 0x8a, 0x6a, 0x35, 0x18, 0xf7, 0x40, 0xd9, 0x6b, 0x98, 0xd0, 0x03, 0x7e, - 0xb6, 0x0e, 0x63, 0x36, 0x78, 0xe7, 0xcd, 0xb1, 0x1a, 0xd3, 0x45, 0xce, 0x7b, 0x0b, 0xa8, 0x75, 0xbb, 0xde, 0x92, - 0x9a, 0x08, 0xad, 0x71, 0x93, 0x71, 0x58, 0x24, 0x7c, 0x17, 0x75, 0x38, 0x41, 0x21, 0x09, 0x20, 0x36, 0xc5, 0x08, - 0x53, 0xd0, 0x9a, 0x71, 0xb1, 0xa1, 0x85, 0xdd, 0x44, 0x77, 0xac, 0xcd, 0x23, 0xca, 0x38, 0xdc, 0xd1, 0x4c, 0x87, - 0xb9, 0xb9, 0x96, 0xe0, 0x7b, 0x89, 0xe8, 0x6d, 0xaa, 0xa6, 0x1d, 0x15, 0x36, 0xb7, 0x69, 0x64, 0xcc, 0x4c, 0x8f, - 0x77, 0x81, 0x76, 0xe3, 0xc9, 0xe8, 0x27, 0x54, 0xf0, 0xe7, 0x73, 0x5f, 0x24, 0x03, 0xf7, 0xd9, 0xe7, 0x01, 0x62, - 0x68, 0x4f, 0x9d, 0xee, 0x37, 0xb5, 0xac, 0x73, 0xc0, 0x14, 0x9b, 0xc4, 0xec, 0x67, 0x1c, 0xf5, 0x87, 0x1d, 0x6d, - 0x1c, 0x24, 0xc5, 0x10, 0x28, 0x1d, 0x7e, 0xdc, 0xd1, 0xca, 0xeb, 0xb6, 0xec, 0xdd, 0xf6, 0x1a, 0x77, 0xe4, 0x63, - 0xaa, 0x07, 0x93, 0x20, 0x49, 0xcb, 0xb1, 0x08, 0xcd, 0x18, 0xbc, 0x45, 0x5a, 0xb0, 0xb6, 0x47, 0x40, 0xcb, 0x5c, - 0x2f, 0x14, 0x7a, 0xe0, 0xe9, 0x3b, 0x73, 0x27, 0x85, 0xc5, 0x58, 0x2e, 0xe9, 0xe0, 0xd9, 0x04, 0xb3, 0x59, 0xd5, - 0x6a, 0x7d, 0x77, 0x68, 0x7b, 0xea, 0x2d, 0x10, 0x76, 0x5e, 0xea, 0x9b, 0x81, 0x23, 0x3f, 0xb3, 0x96, 0xc1, 0x94, - 0x73, 0xbb, 0xc1, 0xbb, 0xfe, 0xe8, 0x6f, 0xca, 0xe0, 0x63, 0x7f, 0x8d, 0xe3, 0xf7, 0x54, 0xdd, 0xb2, 0x74, 0xc2, - 0x74, 0x65, 0x3e, 0x46, 0x2b, 0x35, 0xf7, 0x39, 0x8c, 0xc9, 0x74, 0x80, 0x12, 0x1b, 0xf9, 0xba, 0x0b, 0x07, 0xd4, - 0x2d, 0xa3, 0xf8, 0x8a, 0x5f, 0xd6, 0x6f, 0xf7, 0x25, 0xed, 0x6d, 0xf7, 0x5b, 0x30, 0x53, 0xaf, 0xac, 0x04, 0x8f, - 0x0a, 0x02, 0x3c, 0x04, 0x95, 0xc9, 0xa3, 0xca, 0x12, 0xf0, 0x45, 0xbd, 0x0b, 0x90, 0x88, 0x3c, 0xad, 0x47, 0x79, - 0x09, 0x1b, 0xd5, 0xb0, 0xed, 0x7a, 0x5a, 0x1d, 0x08, 0x89, 0xd1, 0x1c, 0x4f, 0x9b, 0xb5, 0xe6, 0x5a, 0x19, 0x7e, - 0x89, 0x12, 0x17, 0xcf, 0xc6, 0x51, 0xb5, 0x51, 0x20, 0xe4, 0xaa, 0x16, 0x4a, 0xc4, 0xa2, 0xc3, 0x42, 0xa6, 0xf2, - 0x65, 0x65, 0x2c, 0x7b, 0x71, 0xb4, 0x9c, 0xc8, 0xd7, 0xf6, 0xd2, 0xc2, 0x7e, 0x1f, 0x1a, 0x7f, 0xfb, 0x50, 0x61, - 0xca, 0xea, 0xa7, 0x3d, 0x19, 0x71, 0x8d, 0xf5, 0xb1, 0xf5, 0xf6, 0xa1, 0x7f, 0x7c, 0xaf, 0xa6, 0x66, 0xbc, 0xed, - 0x90, 0xee, 0x96, 0x03, 0xb6, 0xc2, 0xdb, 0xc3, 0x96, 0xfc, 0xef, 0xb7, 0x2f, 0x76, 0xec, 0x82, 0xcc, 0x27, 0x2c, - 0x18, 0x91, 0x14, 0x8f, 0x4d, 0x06, 0x50, 0x6e, 0x19, 0xd0, 0x88, 0x60, 0x5f, 0x37, 0x76, 0xe4, 0x6b, 0xcb, 0x1c, - 0x97, 0xe9, 0xb2, 0x1f, 0x20, 0xcb, 0xbe, 0x0c, 0x81, 0x9d, 0xdb, 0x32, 0xe4, 0x80, 0x59, 0x1c, 0xc8, 0xcc, 0x4c, - 0xfb, 0x8f, 0x5a, 0x5e, 0xa1, 0x53, 0x4a, 0xb6, 0x33, 0x1f, 0xd0, 0xad, 0x31, 0xd9, 0xe8, 0x42, 0xb0, 0x2e, 0x74, - 0xb2, 0x23, 0xdc, 0xb8, 0x37, 0xd2, 0x0f, 0x8e, 0x6e, 0x31, 0xa7, 0x81, 0x11, 0xcf, 0xb4, 0x98, 0x16, 0x68, 0xc4, - 0x4f, 0x72, 0x55, 0x2f, 0xf5, 0x40, 0xd6, 0xe9, 0x5a, 0x8c, 0x2e, 0xdf, 0x08, 0x6c, 0xf6, 0x44, 0x9c, 0xcc, 0xa1, - 0xde, 0x21, 0x20, 0x25, 0x5a, 0xa5, 0xef, 0xd6, 0x01, 0xa1, 0x9d, 0x80, 0x65, 0x5a, 0x62, 0xaf, 0x53, 0x32, 0xda, - 0xf7, 0x6f, 0xfc, 0x49, 0x39, 0x0d, 0xd4, 0x52, 0x89, 0xd1, 0x2d, 0x41, 0x41, 0xcc, 0x71, 0x5c, 0x3a, 0x6f, 0x8a, - 0x48, 0xcc, 0x58, 0x7f, 0x71, 0xf4, 0x3d, 0xa3, 0x1f, 0x40, 0xad, 0xa4, 0xa9, 0x70, 0xcc, 0x8d, 0x9a, 0x91, 0x85, - 0xc1, 0x97, 0x11, 0x62, 0xb7, 0xc5, 0x3f, 0x89, 0x3c, 0x9d, 0xa2, 0x15, 0xd0, 0x3d, 0x55, 0x2d, 0xb2, 0x92, 0x56, - 0x39, 0xd4, 0x29, 0xbf, 0x0a, 0x96, 0xc3, 0xe4, 0x58, 0xc6, 0x75, 0x16, 0x43, 0x98, 0x9c, 0xe5, 0x14, 0x4a, 0x6e, - 0x71, 0x0a, 0x5f, 0xb4, 0xcc, 0x2e, 0xc3, 0x1a, 0x2a, 0x20, 0x64, 0x1c, 0x84, 0xc3, 0x4f, 0xfe, 0x54, 0x68, 0x7f, - 0x33, 0x4b, 0x36, 0x7a, 0xf7, 0x51, 0x98, 0xa0, 0x07, 0xe7, 0x56, 0x31, 0x83, 0xc9, 0x10, 0x3d, 0x57, 0xa1, 0x15, - 0xdc, 0x89, 0xe7, 0xb4, 0xc8, 0xa9, 0x7a, 0xc8, 0xa0, 0x55, 0x37, 0xeb, 0x75, 0x5f, 0x47, 0x29, 0x27, 0x42, 0x48, - 0x23, 0x4e, 0x5a, 0x53, 0x35, 0xd5, 0x12, 0x7c, 0x44, 0x49, 0x46, 0x8a, 0x33, 0x03, 0xe4, 0xec, 0xa4, 0xa2, 0x56, - 0x02, 0xe5, 0x19, 0x4e, 0x2a, 0x66, 0x9a, 0x93, 0x18, 0xb0, 0xde, 0x35, 0xde, 0xcf, 0xa6, 0xe9, 0x02, 0x80, 0xea, - 0x4b, 0xc7, 0x48, 0x7d, 0xd6, 0xf1, 0xa4, 0x1e, 0xfa, 0x62, 0xd9, 0xff, 0xa8, 0x9d, 0x3a, 0x30, 0x1a, 0xc4, 0xb8, - 0xda, 0x8f, 0x30, 0x38, 0x37, 0x23, 0x86, 0xcd, 0xfc, 0x81, 0xad, 0x0e, 0xd8, 0x26, 0xaa, 0xb9, 0x48, 0xa2, 0xa5, - 0xe8, 0x79, 0xa6, 0xde, 0x85, 0x1a, 0x0d, 0xd5, 0x53, 0x77, 0x3d, 0xf2, 0xc8, 0x4a, 0xb7, 0x26, 0x32, 0x88, 0x14, - 0x4b, 0xa4, 0x0b, 0xaa, 0xf3, 0x8d, 0xc0, 0xd9, 0x4e, 0x06, 0xa6, 0x30, 0xd6, 0xa3, 0xb8, 0xa5, 0x09, 0xbf, 0x2b, - 0x19, 0xda, 0x29, 0x73, 0x54, 0xc6, 0x21, 0x07, 0xd7, 0xca, 0x3c, 0xf9, 0xf9, 0xb7, 0x3e, 0xa5, 0x11, 0x07, 0x78, - 0x4c, 0x7d, 0x7e, 0x86, 0xeb, 0xeb, 0x6f, 0x92, 0x5f, 0x8a, 0x5b, 0xe9, 0x27, 0x7c, 0x67, 0x89, 0x38, 0xef, 0xc1, - 0xf0, 0xad, 0xea, 0x71, 0x60, 0x11, 0xba, 0x72, 0x2e, 0xea, 0xc1, 0xf9, 0xd3, 0x0b, 0x82, 0x17, 0xe5, 0x80, 0x09, - 0x90, 0xa9, 0xe6, 0xac, 0x7e, 0x4b, 0xe4, 0x40, 0xc6, 0x45, 0x55, 0x9a, 0x3c, 0x81, 0xbc, 0x04, 0x9c, 0x3b, 0xc9, - 0x60, 0x32, 0x64, 0xdd, 0x8f, 0xb7, 0x9d, 0xc4, 0x77, 0xc0, 0xfa, 0x8f, 0x49, 0xc6, 0xb9, 0x06, 0x81, 0x14, 0x2b, - 0x69, 0x27, 0xab, 0xf4, 0x41, 0x81, 0x07, 0x26, 0x99, 0x9c, 0x97, 0x4d, 0x69, 0x33, 0x4f, 0xa0, 0x33, 0xa0, 0x8d, - 0xad, 0x4d, 0x19, 0x9f, 0x56, 0x80, 0x12, 0x12, 0xde, 0xc8, 0xd6, 0x56, 0x67, 0x90, 0xca, 0xaa, 0xf3, 0xcf, 0xf6, - 0x38, 0x53, 0x85, 0xbe, 0xe8, 0xa2, 0x39, 0x37, 0xef, 0x1d, 0x38, 0x1f, 0xd6, 0xe6, 0xe9, 0xcb, 0x9f, 0x12, 0x55, - 0x70, 0xd7, 0xa4, 0x01, 0xaa, 0xba, 0xe5, 0x25, 0x9d, 0xf1, 0x4f, 0xd8, 0x5f, 0x62, 0x09, 0x53, 0x90, 0xb4, 0x3f, - 0x84, 0x8f, 0x90, 0xf6, 0x11, 0xf2, 0x66, 0xfb, 0x3f, 0x4a, 0x99, 0x1c, 0x0f, 0xb6, 0x9a, 0xfd, 0xb0, 0x29, 0xfe, - 0x2d, 0xb2, 0x06, 0xee, 0xab, 0xf5, 0xc3, 0xaa, 0x32, 0x89, 0x3e, 0xae, 0x8d, 0x17, 0x94, 0x31, 0x86, 0xe9, 0x64, - 0xb1, 0xea, 0xba, 0x8c, 0x1b, 0x52, 0x66, 0x65, 0xf0, 0xd1, 0xe1, 0x03, 0x4d, 0x48, 0x2a, 0x74, 0x3e, 0xc5, 0xbc, - 0x34, 0xf3, 0xeb, 0x26, 0x15, 0xe1, 0x0f, 0x65, 0xce, 0x3b, 0x6f, 0x89, 0xba, 0xeb, 0x7d, 0xd5, 0x2f, 0x0f, 0x68, - 0xb4, 0x4d, 0x4f, 0x28, 0x07, 0x67, 0x70, 0x9a, 0x64, 0xf4, 0xcc, 0x44, 0x3c, 0x22, 0x1f, 0xe2, 0xfa, 0x45, 0x68, - 0xa4, 0x97, 0x87, 0x1c, 0x11, 0xbf, 0xcb, 0xe2, 0xee, 0x15, 0xbf, 0xd1, 0x5f, 0x92, 0x0f, 0x4b, 0x3a, 0x4a, 0x62, - 0xad, 0xdd, 0x0f, 0x73, 0x4c, 0xda, 0x40, 0xc5, 0xff, 0x0f, 0x13, 0xaf, 0x29, 0x8b, 0x2c, 0xa3, 0x25, 0xba, 0xaa, - 0x1d, 0x1c, 0xed, 0xc3, 0x22, 0x45, 0xbe, 0xc8, 0x10, 0x52, 0x44, 0xb7, 0x46, 0x79, 0x08, 0xaf, 0x27, 0xff, 0xa8, - 0x2c, 0xfc, 0x61, 0xd5, 0x4d, 0x4f, 0xa7, 0x91, 0x8a, 0x1f, 0xe9, 0xe8, 0xfb, 0x55, 0xdd, 0xde, 0x4f, 0x7b, 0xb3, - 0xd8, 0x43, 0xc0, 0xec, 0x33, 0x0d, 0x91, 0xbd, 0x59, 0xf6, 0x19, 0x86, 0x49, 0xdc, 0xe2, 0x8a, 0xd7, 0xa0, 0xa7, - 0xca, 0x56, 0xee, 0x0d, 0x38, 0xe3, 0x0b, 0x43, 0x07, 0x19, 0x8f, 0x96, 0x2b, 0x8f, 0xdf, 0xf0, 0x00, 0x4e, 0xaa, - 0xb6, 0xdb, 0xa2, 0x2c, 0xed, 0x19, 0x9c, 0x24, 0x8b, 0x78, 0x92, 0x79, 0xf1, 0x65, 0x4a, 0x2f, 0x29, 0xd9, 0x8c, - 0x12, 0xde, 0xd1, 0x17, 0xa2, 0x42, 0x2a, 0xb5, 0x21, 0x5f, 0x95, 0x92, 0x6d, 0x34, 0xa4, 0x52, 0xca, 0x15, 0x57, - 0xe3, 0x72, 0x1a, 0xaf, 0x8c, 0xed, 0x21, 0xbb, 0x85, 0x57, 0xc5, 0xeb, 0x14, 0x21, 0xbd, 0xbe, 0x46, 0x38, 0x71, - 0x53, 0x64, 0x90, 0xf8, 0x70, 0x56, 0xd2, 0xe5, 0xc9, 0x35, 0x58, 0xf3, 0x9c, 0xa3, 0x1c, 0xcc, 0xba, 0x3e, 0x50, - 0xe6, 0x7c, 0x93, 0xf6, 0xa8, 0xc8, 0x57, 0x4e, 0x9d, 0xab, 0x0d, 0xa8, 0xcb, 0x77, 0x02, 0x66, 0xe1, 0x3e, 0x1e, - 0x47, 0x25, 0xe9, 0x8d, 0x32, 0xe2, 0xc3, 0x9d, 0x20, 0xc5, 0x66, 0x9e, 0x8c, 0xc4, 0x3b, 0xda, 0xd8, 0xb9, 0x68, - 0xa4, 0x8f, 0x42, 0x7c, 0x4a, 0x50, 0x43, 0x1a, 0xa3, 0xd9, 0xc5, 0xee, 0x65, 0x90, 0x60, 0x88, 0x2c, 0xd9, 0x82, - 0x20, 0x44, 0x1e, 0x96, 0x31, 0x58, 0x52, 0x1f, 0x4d, 0xad, 0x60, 0x62, 0x99, 0x2b, 0x3f, 0x9c, 0xde, 0xa2, 0x57, - 0xeb, 0x48, 0x86, 0x5c, 0x27, 0xb1, 0x20, 0x6d, 0xc6, 0xcf, 0x75, 0x79, 0xd4, 0xde, 0x02, 0xab, 0xe9, 0x4a, 0xea, - 0x41, 0x63, 0x7a, 0xbc, 0x4e, 0x49, 0xb1, 0xb1, 0xce, 0x3a, 0x55, 0x15, 0xca, 0x7f, 0x9f, 0xad, 0x8a, 0x8b, 0xab, - 0x96, 0x6f, 0x71, 0x54, 0xef, 0x6c, 0x12, 0x02, 0x00, 0x35, 0x3c, 0xa4, 0xfa, 0x01, 0xc6, 0xb0, 0xdc, 0x33, 0xcc, - 0xb2, 0x0f, 0xd7, 0x1b, 0x34, 0x04, 0x6d, 0xc7, 0xe3, 0xc4, 0x16, 0xf9, 0x46, 0x0c, 0x68, 0xa4, 0xd4, 0x04, 0xd8, - 0x66, 0x85, 0x18, 0x3c, 0xeb, 0xf6, 0x27, 0x8a, 0x82, 0xa8, 0xe0, 0x88, 0x01, 0x10, 0x4e, 0x39, 0x2d, 0x3f, 0x2a, - 0xfc, 0xb0, 0x90, 0x60, 0x2a, 0x5e, 0x0e, 0xe4, 0xd3, 0x12, 0x10, 0x14, 0x83, 0xb2, 0x0c, 0x2d, 0x10, 0x82, 0xbe, - 0x99, 0x89, 0x51, 0x07, 0x67, 0x8c, 0xbe, 0x11, 0x31, 0xe0, 0x94, 0x02, 0x10, 0x8f, 0x39, 0x5d, 0x6b, 0x29, 0x5f, - 0x97, 0x2e, 0xfd, 0x8e, 0x9e, 0xca, 0x49, 0xe9, 0x85, 0xb0, 0x4d, 0xaf, 0x62, 0x5e, 0x8b, 0x4a, 0xa2, 0xeb, 0x65, - 0x73, 0x19, 0x1b, 0x9e, 0x2f, 0x5c, 0x9d, 0x56, 0x6f, 0xb6, 0xf0, 0xe1, 0x35, 0x17, 0x1f, 0x3e, 0x24, 0xb7, 0x2d, - 0xa3, 0xe0, 0xc3, 0x4e, 0xc3, 0x36, 0x72, 0x20, 0x08, 0xf0, 0xb7, 0xf5, 0xf5, 0x64, 0x6b, 0xb2, 0x15, 0x2e, 0x48, - 0x0f, 0xfb, 0x06, 0xdf, 0x0e, 0xc1, 0x9f, 0x68, 0xcd, 0x78, 0xcc, 0xd6, 0x3d, 0x34, 0xe4, 0xee, 0x65, 0x8d, 0x5f, - 0x30, 0x41, 0xe7, 0x67, 0x99, 0x79, 0x1f, 0x12, 0x5a, 0xee, 0x4b, 0xda, 0xe8, 0x11, 0xd3, 0x78, 0x14, 0x5d, 0x21, - 0xae, 0xf1, 0x2c, 0x3b, 0x3f, 0x1a, 0x1b, 0xb1, 0x9c, 0x38, 0x62, 0x3b, 0xcd, 0x2e, 0xdb, 0xe4, 0xd2, 0x52, 0x8d, - 0x6f, 0xef, 0x2a, 0x13, 0x8c, 0xaa, 0xa1, 0x7d, 0x5e, 0xd6, 0x67, 0x95, 0xcf, 0xfc, 0xfb, 0xfc, 0xad, 0x8b, 0x2a, - 0xc3, 0x1c, 0xa2, 0x19, 0x5f, 0xe3, 0x67, 0xa8, 0x4b, 0x28, 0xd2, 0x03, 0xf7, 0x7b, 0x99, 0xdd, 0x58, 0x73, 0x26, - 0x3f, 0xc2, 0x77, 0x4a, 0xb2, 0x0b, 0x6c, 0xc7, 0xbf, 0x8d, 0x7a, 0x2a, 0x94, 0x7e, 0xd4, 0x06, 0x16, 0x7f, 0x90, - 0xa4, 0x16, 0x24, 0x43, 0x09, 0x0e, 0xe2, 0xaa, 0x65, 0xef, 0xe9, 0x76, 0x6d, 0xc5, 0x82, 0x70, 0xe9, 0x6c, 0xed, - 0xe5, 0x8d, 0x69, 0x10, 0xe8, 0x44, 0x0b, 0xa3, 0xcd, 0xd9, 0x88, 0x79, 0xbc, 0xa1, 0x6a, 0x98, 0xbe, 0xa1, 0x34, - 0xb4, 0xc6, 0x17, 0xa0, 0x18, 0x26, 0x98, 0x22, 0xc2, 0xde, 0xb4, 0xf7, 0xf8, 0xc5, 0x86, 0xd5, 0x59, 0x50, 0xe3, - 0x55, 0x19, 0x21, 0x13, 0x97, 0x2b, 0x49, 0xf2, 0xe1, 0x3d, 0x81, 0xeb, 0xf8, 0xa7, 0xdd, 0x88, 0x77, 0x3d, 0xbe, - 0x93, 0x87, 0x65, 0x98, 0x98, 0x6e, 0xd1, 0x3a, 0x10, 0x43, 0x1c, 0x5b, 0xa1, 0x90, 0xa5, 0xfe, 0x58, 0xbd, 0x61, - 0x12, 0x8c, 0x9f, 0x1f, 0xac, 0xde, 0xcc, 0x8e, 0xff, 0x88, 0x06, 0x70, 0xee, 0x62, 0x1c, 0x81, 0x11, 0x66, 0x49, - 0x85, 0x1b, 0x65, 0x68, 0xa1, 0x8f, 0x8a, 0xab, 0xa9, 0x72, 0xe0, 0xc8, 0x12, 0xf2, 0x9a, 0xd2, 0xfe, 0x70, 0x3e, - 0xf3, 0xbb, 0x29, 0xf1, 0x33, 0x9d, 0x6e, 0xdf, 0xad, 0x1d, 0x56, 0x30, 0x1d, 0x07, 0xde, 0x1a, 0x29, 0xc8, 0xb1, - 0x14, 0xac, 0x6d, 0x39, 0x93, 0xe2, 0xb8, 0xa9, 0x3d, 0xeb, 0x55, 0x95, 0x9c, 0xd4, 0xfc, 0x6b, 0x9d, 0xac, 0x4d, - 0x3a, 0x73, 0x5b, 0x67, 0xfc, 0x74, 0x82, 0xbb, 0xf9, 0x5e, 0x69, 0x52, 0xf1, 0x3f, 0xcc, 0xaf, 0xb3, 0x64, 0xb5, - 0xf9, 0x78, 0xa1, 0x15, 0xb6, 0x89, 0x64, 0x80, 0xaf, 0xef, 0x34, 0x7d, 0x53, 0x20, 0x21, 0x6c, 0x57, 0xd3, 0xbd, - 0x0f, 0x0d, 0xd0, 0x9c, 0xb2, 0x13, 0xa4, 0xa8, 0x80, 0xd4, 0x9d, 0x58, 0x61, 0x90, 0x63, 0x60, 0x18, 0x3c, 0xf6, - 0x3e, 0xf5, 0x6e, 0x2d, 0x51, 0x57, 0x78, 0x2c, 0x34, 0x76, 0x63, 0xb0, 0x5a, 0x3e, 0x75, 0xe7, 0xff, 0x88, 0x5e, - 0xc1, 0xdf, 0x92, 0xf9, 0x1e, 0xf0, 0x0f, 0x82, 0x5a, 0xb6, 0x5a, 0x54, 0xde, 0x0a, 0xb9, 0x03, 0xfb, 0x78, 0x80, - 0x4f, 0x73, 0xf9, 0x40, 0x62, 0x6f, 0x8f, 0xcd, 0xdc, 0x75, 0x4d, 0xaf, 0xd5, 0x66, 0x6e, 0x75, 0xb4, 0x0c, 0x31, - 0x3a, 0x00, 0x20, 0x65, 0xc0, 0xf8, 0x29, 0xd6, 0x71, 0x67, 0xfc, 0x93, 0x79, 0xd0, 0xe7, 0x74, 0x7f, 0xf7, 0x3e, - 0x84, 0xdf, 0xd2, 0x12, 0xf1, 0x5d, 0xc4, 0xff, 0x1d, 0x5c, 0xf8, 0xd6, 0x31, 0x51, 0x25, 0x65, 0x07, 0x57, 0xe7, - 0xf0, 0x4d, 0xcf, 0x7b, 0x17, 0x57, 0x31, 0x8e, 0xbe, 0x87, 0x65, 0xf1, 0x47, 0x42, 0xa3, 0x29, 0x7c, 0x2d, 0x62, - 0x93, 0x97, 0xd0, 0x70, 0x33, 0x61, 0xb1, 0x8d, 0x2e, 0xcb, 0x1a, 0xc2, 0xeb, 0x7d, 0xa2, 0xb2, 0x8b, 0x27, 0x93, - 0x89, 0xba, 0xbe, 0x64, 0x29, 0xc0, 0xe5, 0xa6, 0x9a, 0xd1, 0x4b, 0xfb, 0x76, 0x8f, 0xba, 0xf4, 0x74, 0xff, 0xc1, - 0x65, 0x04, 0xaf, 0xd3, 0x66, 0xab, 0x3c, 0x37, 0x7d, 0x6a, 0x23, 0x3a, 0xa2, 0x7d, 0x5b, 0x57, 0xea, 0x05, 0x00, - 0x3a, 0xc0, 0x8b, 0xe3, 0x26, 0xba, 0x6a, 0xfa, 0xc7, 0x11, 0x90, 0xd6, 0xfc, 0x1e, 0x9b, 0x55, 0xb9, 0x91, 0x57, - 0x6a, 0x57, 0x09, 0xca, 0x8e, 0xf3, 0xe3, 0xbb, 0xd6, 0x5b, 0x3d, 0xbc, 0x54, 0x50, 0x29, 0xac, 0x6d, 0x7a, 0x6f, - 0xe9, 0xa4, 0xa7, 0x7d, 0x7e, 0x70, 0x5a, 0x50, 0x37, 0x74, 0xa9, 0xf5, 0x65, 0x07, 0x1e, 0xb5, 0x3e, 0x80, 0x9c, - 0xee, 0x60, 0x84, 0x23, 0x7a, 0x7f, 0x25, 0x6d, 0x09, 0xf0, 0x06, 0x68, 0x57, 0x9c, 0x80, 0xb6, 0x1d, 0x77, 0xe3, - 0xe6, 0x5b, 0xf8, 0xb3, 0x47, 0x90, 0x50, 0x5d, 0x75, 0x6e, 0xc9, 0xb4, 0x6b, 0x41, 0x45, 0x48, 0x2a, 0x24, 0x24, - 0x1c, 0x2e, 0x57, 0x97, 0x82, 0x51, 0x12, 0xd0, 0x57, 0x85, 0xc7, 0x43, 0xd9, 0xdb, 0x6e, 0x37, 0xae, 0x95, 0x91, - 0x64, 0x1a, 0xa8, 0x82, 0xc7, 0xd4, 0x1d, 0x72, 0x1f, 0x8f, 0x52, 0xb5, 0x90, 0x1e, 0xeb, 0x1f, 0x10, 0x24, 0x0d, - 0x0a, 0x1e, 0x99, 0x58, 0xdc, 0xd1, 0x40, 0xd4, 0x4a, 0x87, 0x1a, 0x66, 0xf6, 0x8e, 0x0b, 0x2e, 0xe6, 0xa8, 0x34, - 0xec, 0x32, 0xe0, 0x49, 0x66, 0x96, 0x41, 0x9f, 0x20, 0x77, 0x55, 0x3d, 0x15, 0xa6, 0xc3, 0x72, 0xc2, 0x00, 0xf1, - 0x94, 0xfa, 0x95, 0xdb, 0x5c, 0x37, 0xf8, 0x96, 0x24, 0x07, 0x60, 0xc0, 0xae, 0xb7, 0x42, 0xda, 0x2a, 0xdb, 0xa5, - 0xb2, 0xb1, 0x64, 0x25, 0x6c, 0xb8, 0xec, 0x62, 0x15, 0x01, 0xad, 0x20, 0xfa, 0x71, 0x8d, 0x30, 0x92, 0xfe, 0x42, - 0xa6, 0xd9, 0xb0, 0xfd, 0x39, 0xa6, 0xd5, 0x92, 0xdb, 0xb9, 0x25, 0xda, 0x00, 0x0d, 0xf8, 0x31, 0x86, 0xac, 0x25, - 0xb5, 0x26, 0xf6, 0xd6, 0xc5, 0xe4, 0xf9, 0x86, 0xe1, 0x69, 0x63, 0xd6, 0xcb, 0x64, 0xe3, 0xea, 0xc6, 0xa7, 0xb9, - 0x14, 0x1f, 0x0c, 0xba, 0x28, 0x4c, 0xa9, 0x39, 0x56, 0xe4, 0x5f, 0x02, 0xeb, 0xc2, 0x65, 0x42, 0xb2, 0x99, 0xca, - 0x84, 0x80, 0xc6, 0x6e, 0xcf, 0x08, 0x71, 0xf6, 0x03, 0x71, 0x26, 0xef, 0x2b, 0x5a, 0xd4, 0x20, 0x4f, 0x18, 0x8b, - 0x5f, 0xf6, 0xb0, 0xbb, 0x4d, 0xf3, 0xbc, 0x60, 0xcf, 0xb4, 0x62, 0x9d, 0x68, 0x26, 0x5c, 0x4f, 0xc9, 0xea, 0x1a, - 0x21, 0xe9, 0x53, 0xea, 0xf4, 0xc0, 0x8a, 0xa9, 0xbd, 0x53, 0x0a, 0x2c, 0x53, 0x10, 0x86, 0x76, 0xf2, 0xa8, 0x2c, - 0x29, 0xa9, 0x7a, 0x68, 0xbb, 0xb8, 0xa7, 0x50, 0x90, 0x31, 0xe2, 0xea, 0xb1, 0xcf, 0xcf, 0x00, 0x41, 0x79, 0x3a, - 0x83, 0x32, 0x7d, 0x4e, 0xb8, 0x91, 0xe7, 0x0c, 0x2d, 0xf2, 0x62, 0x62, 0x8e, 0x2a, 0x41, 0xd6, 0x48, 0xff, 0x55, - 0x84, 0x5c, 0x68, 0xf0, 0xf0, 0x48, 0x3a, 0x0d, 0xeb, 0x37, 0xc5, 0x0b, 0x0a, 0xce, 0x9f, 0xb2, 0x86, 0x18, 0xe7, - 0x86, 0x90, 0xe0, 0xfe, 0x70, 0x7f, 0xe6, 0x2e, 0x96, 0x11, 0x5a, 0xa5, 0x30, 0x2a, 0x2a, 0x99, 0x79, 0xe1, 0x87, - 0xb0, 0x0d, 0xf3, 0x62, 0x62, 0x50, 0x78, 0xdf, 0xa5, 0xf5, 0x99, 0x70, 0x88, 0xab, 0x6a, 0x8a, 0x79, 0x87, 0x14, - 0x35, 0x18, 0x4a, 0x6e, 0xf1, 0x5c, 0x33, 0x1a, 0x3d, 0xd6, 0x67, 0x46, 0x43, 0x6d, 0x92, 0xfc, 0x6a, 0x4e, 0xb0, - 0xb1, 0xe1, 0xa5, 0x90, 0xaa, 0x45, 0xc7, 0x01, 0xe1, 0x57, 0x1a, 0xc0, 0x5c, 0x68, 0x9a, 0xa7, 0x1d, 0x10, 0xb4, - 0xd2, 0x52, 0x0d, 0xa3, 0xaf, 0x08, 0x1e, 0x22, 0xa9, 0x1b, 0x83, 0x80, 0x8d, 0x60, 0x38, 0x04, 0xb4, 0xc5, 0x2f, - 0x2f, 0x7c, 0xa4, 0x61, 0xaa, 0x76, 0xec, 0x58, 0xce, 0x21, 0xa7, 0xca, 0xe0, 0x11, 0xff, 0x33, 0x11, 0x4c, 0xda, - 0xdc, 0x48, 0xbc, 0xa5, 0xec, 0xa6, 0x8e, 0xd3, 0xcc, 0x41, 0xfe, 0x96, 0x8e, 0xf6, 0x5a, 0xf9, 0xc2, 0x36, 0x99, - 0xb1, 0x57, 0xa3, 0x79, 0x28, 0x00, 0xb5, 0xff, 0x68, 0xdf, 0x65, 0xd1, 0x24, 0x7c, 0x3e, 0xbb, 0xef, 0x06, 0xf5, - 0x10, 0xd9, 0x99, 0x87, 0x62, 0xa5, 0xfb, 0x7a, 0xba, 0x34, 0x12, 0x1d, 0xc2, 0x35, 0xe6, 0x26, 0x9a, 0xed, 0x13, - 0x3d, 0x75, 0x26, 0xfb, 0xf9, 0xe8, 0x12, 0x2f, 0x67, 0x4e, 0x00, 0xd8, 0x23, 0x9e, 0x17, 0xdc, 0x51, 0xe2, 0x30, - 0xb5, 0xa9, 0x9d, 0x60, 0xa7, 0x3b, 0xda, 0xd8, 0xb5, 0x40, 0x29, 0x08, 0xa0, 0xf3, 0x7c, 0xfa, 0x7c, 0xfa, 0x32, - 0x86, 0xed, 0xd8, 0xc1, 0xe4, 0x64, 0x7e, 0xb1, 0x74, 0xcd, 0x6d, 0x91, 0xe9, 0xb0, 0xa4, 0x9b, 0x26, 0xe4, 0xbe, - 0x47, 0xe7, 0x36, 0xcf, 0xfa, 0xd3, 0xee, 0xda, 0x78, 0xa7, 0x21, 0x09, 0x8b, 0x00, 0xe5, 0xc5, 0x2e, 0x71, 0xe2, - 0xc0, 0x0d, 0xe7, 0xfb, 0x82, 0xc5, 0x82, 0x35, 0x12, 0x31, 0x44, 0x01, 0x19, 0x53, 0xff, 0xfc, 0x84, 0xee, 0xfa, - 0x1d, 0x5f, 0x0d, 0xa2, 0xe0, 0x98, 0x34, 0xd4, 0x9d, 0x57, 0x0f, 0xbb, 0x3e, 0xe6, 0x4c, 0x35, 0xc6, 0x7d, 0xee, - 0xfe, 0x80, 0x7d, 0xd7, 0x5a, 0xd3, 0x5c, 0x8f, 0x79, 0x69, 0x3b, 0xc5, 0x73, 0x0e, 0xe7, 0xf1, 0xe1, 0x7e, 0x1e, - 0xfc, 0x66, 0x78, 0x52, 0x29, 0xb6, 0x5d, 0x8e, 0x3c, 0xc9, 0x41, 0xd7, 0xf3, 0x1d, 0xfb, 0x78, 0x8f, 0xe1, 0x1e, - 0x24, 0x81, 0x0f, 0xaa, 0x54, 0x75, 0x96, 0xfb, 0x16, 0x0f, 0xc4, 0x06, 0x41, 0xe1, 0x75, 0x84, 0x78, 0x4d, 0x27, - 0xbf, 0x67, 0x07, 0xd8, 0x80, 0x2b, 0x20, 0x0f, 0xf8, 0x6c, 0xc5, 0x40, 0x5d, 0xc1, 0x90, 0xd9, 0xb7, 0x5b, 0x72, - 0x96, 0x66, 0x05, 0x3a, 0xe9, 0xf6, 0x26, 0x99, 0x5b, 0x0f, 0x34, 0xb0, 0x14, 0x89, 0x7c, 0xc9, 0xef, 0x58, 0x95, - 0x88, 0x45, 0x11, 0x9b, 0x4d, 0x3e, 0xc6, 0x62, 0x09, 0xf5, 0xfa, 0x52, 0xe4, 0x3d, 0x1f, 0x30, 0x67, 0x59, 0xc7, - 0xea, 0x9f, 0xc6, 0xee, 0x6e, 0x17, 0x31, 0xcc, 0xaf, 0x7f, 0xee, 0x81, 0xba, 0x58, 0x9e, 0xa7, 0xea, 0xcc, 0x30, - 0x82, 0xfd, 0x56, 0x2f, 0xb4, 0x1c, 0xb4, 0x31, 0x8f, 0xa9, 0xc9, 0x2d, 0xe9, 0xe3, 0x0b, 0xca, 0x89, 0x0e, 0xd0, - 0xfd, 0x15, 0x4a, 0xf7, 0x43, 0x47, 0x7d, 0xab, 0xfa, 0x7d, 0xe0, 0xa0, 0xea, 0x1c, 0x54, 0x77, 0x9c, 0x24, 0xb6, - 0x2b, 0x8a, 0x63, 0x58, 0x88, 0x6e, 0x0b, 0x76, 0xf8, 0x8c, 0x35, 0xcd, 0x1f, 0xe0, 0x80, 0xbb, 0x9b, 0x8c, 0x29, - 0x92, 0x4c, 0x3a, 0x9b, 0xd4, 0x1e, 0x00, 0xbd, 0x9f, 0xad, 0x73, 0x90, 0xbe, 0x5f, 0x3b, 0x54, 0xfb, 0xf3, 0xf8, - 0x80, 0xf3, 0x7c, 0xd9, 0xc4, 0x5c, 0x91, 0x38, 0x71, 0x85, 0x14, 0x74, 0x86, 0x50, 0xfa, 0x0b, 0x87, 0xbc, 0xcd, - 0xf3, 0xf4, 0xba, 0x99, 0xa8, 0x72, 0x27, 0xbb, 0x74, 0x82, 0x38, 0x78, 0x03, 0x01, 0x1e, 0x97, 0xfd, 0x5e, 0x6a, - 0xda, 0xe6, 0xc9, 0xed, 0x90, 0xd5, 0xea, 0xca, 0x77, 0xda, 0x07, 0x7c, 0x73, 0x93, 0x91, 0xc6, 0xf9, 0x9e, 0x87, - 0x9e, 0xca, 0xbe, 0x91, 0x35, 0x49, 0xed, 0xb7, 0x40, 0xc7, 0x55, 0x49, 0xc7, 0x18, 0x0d, 0x27, 0xf3, 0xe8, 0xbf, - 0x03, 0x31, 0x1c, 0xae, 0xcc, 0xbe, 0xd1, 0x38, 0x52, 0x74, 0xf8, 0xf2, 0xb0, 0x05, 0x47, 0xec, 0x49, 0x7c, 0x2f, - 0x5e, 0xe5, 0x4a, 0x97, 0xe8, 0x04, 0xb8, 0xed, 0x5d, 0x79, 0x63, 0xd3, 0xe5, 0xf3, 0xbf, 0x8f, 0x06, 0xdf, 0x1c, - 0x11, 0x31, 0x05, 0xaa, 0x24, 0xf6, 0xc1, 0xe6, 0x7b, 0x48, 0x68, 0xb2, 0x4b, 0x54, 0x61, 0xe8, 0x81, 0xb7, 0xd9, - 0xc6, 0x2d, 0x1c, 0x71, 0xf5, 0x55, 0x48, 0x80, 0xbd, 0x5c, 0xf7, 0xcc, 0xe8, 0x1e, 0xfc, 0xd4, 0xb4, 0x52, 0x84, - 0xc4, 0x37, 0x17, 0xf7, 0x0d, 0x1b, 0x8d, 0x58, 0xf6, 0x42, 0x66, 0x5d, 0x3c, 0x4a, 0xd1, 0xd3, 0x2a, 0xc3, 0xe9, - 0xa5, 0x3c, 0x27, 0x26, 0xab, 0x2c, 0xc8, 0x86, 0xae, 0x9e, 0xbe, 0xe5, 0xba, 0xf7, 0x56, 0x43, 0xf6, 0x12, 0xdf, - 0xbd, 0x72, 0x17, 0x20, 0xc7, 0xc4, 0xd3, 0x19, 0xd8, 0x05, 0xa9, 0x68, 0xaf, 0x97, 0x15, 0x36, 0x38, 0x56, 0x89, - 0xed, 0x14, 0x7c, 0x20, 0x36, 0x9f, 0x0b, 0x2e, 0x15, 0xa4, 0x2f, 0xc9, 0xfa, 0xfc, 0x2a, 0xc4, 0x1a, 0x98, 0x24, - 0xf0, 0xfe, 0xb3, 0x2c, 0x66, 0xfb, 0x12, 0x07, 0x08, 0x1c, 0x17, 0xef, 0x7b, 0x40, 0xef, 0x6f, 0x39, 0x92, 0x99, - 0x1c, 0xac, 0xc5, 0x7d, 0xc9, 0xcc, 0x08, 0xfe, 0xeb, 0xc7, 0x3b, 0x6b, 0x85, 0x8a, 0x5c, 0x8f, 0x61, 0x42, 0xb1, - 0xfb, 0x6e, 0xe7, 0x38, 0x37, 0x55, 0x82, 0x33, 0xa8, 0xe5, 0xef, 0xef, 0x78, 0x89, 0x86, 0x24, 0xe3, 0x36, 0x80, - 0xba, 0xac, 0x98, 0x74, 0x01, 0x2e, 0xea, 0xad, 0xc8, 0xd8, 0x51, 0xb0, 0xc7, 0x52, 0x6b, 0x76, 0x9c, 0x03, 0xc9, - 0xae, 0x16, 0x1a, 0x6d, 0x89, 0x22, 0xf7, 0x02, 0x62, 0x97, 0xcc, 0xf7, 0x75, 0xc5, 0x91, 0xee, 0x2a, 0x65, 0x4a, - 0x65, 0x4e, 0x39, 0x79, 0x92, 0x52, 0x7f, 0x63, 0xa8, 0x7a, 0xea, 0x0b, 0xec, 0x99, 0xb9, 0x3c, 0x5e, 0xcf, 0x37, - 0x7e, 0x24, 0x78, 0xbf, 0x56, 0x0c, 0x82, 0x58, 0xa1, 0xd9, 0x2e, 0x61, 0x32, 0x50, 0xa3, 0x3c, 0x39, 0x6e, 0x2c, - 0x37, 0x5e, 0xe2, 0x5f, 0x74, 0x95, 0x58, 0x99, 0x9f, 0xf5, 0x05, 0xb9, 0x0e, 0xde, 0xeb, 0x32, 0x2f, 0x49, 0xad, - 0xff, 0xb0, 0x3d, 0x1e, 0x4e, 0xd4, 0xaf, 0x37, 0xcc, 0xf3, 0xbb, 0x81, 0x54, 0x66, 0xdb, 0x51, 0x94, 0x95, 0x19, - 0x51, 0x0e, 0xed, 0x36, 0x01, 0xed, 0xa5, 0x5b, 0x5c, 0x40, 0xdd, 0xd8, 0xa2, 0x4b, 0x88, 0x61, 0xa0, 0xb8, 0x95, - 0x49, 0xa8, 0xce, 0xc6, 0x21, 0x4d, 0x29, 0x64, 0x8f, 0x88, 0xc5, 0x84, 0x85, 0xfa, 0xa7, 0xc3, 0xd3, 0xac, 0x06, - 0x5a, 0xef, 0x91, 0x6a, 0x8e, 0x15, 0xef, 0x1a, 0xaa, 0xb1, 0xb0, 0xd1, 0x2a, 0xff, 0x22, 0xc7, 0x8d, 0x43, 0x94, - 0x37, 0x5d, 0xe8, 0xe8, 0xc2, 0xbf, 0xa6, 0xd2, 0x49, 0x03, 0x2e, 0xce, 0xc5, 0x91, 0x04, 0xfe, 0xdf, 0xba, 0x24, - 0x42, 0xf1, 0x5b, 0xc4, 0x8a, 0x20, 0xbe, 0x36, 0xad, 0xfc, 0x6b, 0x27, 0x7d, 0x4e, 0xbc, 0xa3, 0x5d, 0xa5, 0x9a, - 0x49, 0x78, 0x31, 0x9c, 0xc8, 0x7c, 0x72, 0xe0, 0xc2, 0x57, 0x3e, 0x99, 0xec, 0xfe, 0x48, 0x28, 0x9f, 0xd8, 0xb3, - 0xc9, 0x71, 0x5a, 0x3b, 0xea, 0xfc, 0xe0, 0x97, 0x62, 0x07, 0xf3, 0xb0, 0x68, 0x53, 0x14, 0x8a, 0x5a, 0x1d, 0x8a, - 0x97, 0x45, 0x24, 0x82, 0x26, 0x14, 0xab, 0x87, 0x09, 0xc0, 0xc7, 0x4b, 0x8c, 0x72, 0x9f, 0xb5, 0x75, 0xa4, 0xfa, - 0xde, 0x84, 0x60, 0x65, 0xa0, 0xf6, 0xe8, 0x1c, 0x68, 0x13, 0x9b, 0x7a, 0xcc, 0xf2, 0x52, 0xab, 0x15, 0xee, 0x9a, - 0xd7, 0x71, 0x19, 0x5a, 0x95, 0xfc, 0x13, 0x64, 0x37, 0x9a, 0x53, 0x0c, 0x01, 0x45, 0x5f, 0x6e, 0x26, 0xb8, 0xe5, - 0xbe, 0x3f, 0x60, 0x38, 0x51, 0x9a, 0x15, 0xed, 0x29, 0x7a, 0x29, 0x12, 0xf3, 0x31, 0x96, 0x8e, 0xdf, 0xb3, 0x39, - 0xad, 0x28, 0x7d, 0x76, 0x67, 0xa0, 0xb8, 0x09, 0x74, 0x59, 0x37, 0x35, 0x4e, 0xd8, 0xb3, 0xb4, 0x6c, 0xf7, 0xdc, - 0xca, 0xb1, 0xa2, 0xad, 0x51, 0xc6, 0x4c, 0xaf, 0x34, 0x4b, 0x12, 0x18, 0xfe, 0xb1, 0xd5, 0x38, 0x0a, 0x07, 0xec, - 0x3a, 0xeb, 0xe1, 0x57, 0x68, 0xd8, 0x66, 0xca, 0x3f, 0xd2, 0xe2, 0xb9, 0xf8, 0x64, 0x6a, 0x30, 0xbf, 0x17, 0xa8, - 0x90, 0xb8, 0xf8, 0x4c, 0x34, 0xfd, 0x3e, 0xda, 0x5f, 0x47, 0x05, 0xc8, 0x98, 0x2a, 0x63, 0xe5, 0xff, 0x2b, 0x6d, - 0xd9, 0x6e, 0xc7, 0x71, 0xcd, 0x90, 0xc8, 0xa0, 0xd2, 0xe3, 0x2e, 0xee, 0xe9, 0xd7, 0xd1, 0x7f, 0x89, 0xa8, 0xae, - 0xdc, 0x79, 0x45, 0x5d, 0xf3, 0x5d, 0x52, 0x8b, 0xcc, 0x5e, 0xbf, 0x7b, 0xd5, 0x2a, 0x75, 0x50, 0x63, 0x5b, 0x6c, - 0xbc, 0xae, 0x2d, 0x7e, 0x7d, 0x00, 0xcd, 0xde, 0xe4, 0x37, 0xb3, 0x5d, 0x75, 0x8d, 0xd4, 0xa9, 0xd1, 0xd8, 0x31, - 0x8c, 0xde, 0xde, 0x0c, 0xbb, 0x0d, 0x3e, 0xb6, 0x46, 0x40, 0xab, 0x98, 0xbd, 0xfe, 0xbd, 0x0a, 0x0a, 0x7d, 0xab, - 0x9f, 0xc7, 0xba, 0xc9, 0xb8, 0xfc, 0xa1, 0x82, 0x40, 0x33, 0x4b, 0xe4, 0x51, 0x1e, 0x37, 0x8f, 0xde, 0x7a, 0xe2, - 0xb7, 0x36, 0xcf, 0xdd, 0xe4, 0x9e, 0x7c, 0xda, 0xaf, 0xe2, 0x36, 0x57, 0xf5, 0x2d, 0xe3, 0x2a, 0xe8, 0xb0, 0xdc, - 0x96, 0xaf, 0x0c, 0xbf, 0x57, 0xd0, 0xe1, 0x14, 0xfd, 0xfb, 0xe4, 0x0f, 0x1b, 0xb6, 0x8f, 0xda, 0x94, 0x50, 0x39, - 0x34, 0xbf, 0x51, 0x1f, 0x12, 0x98, 0x22, 0xb3, 0x8b, 0x3a, 0xe7, 0x5c, 0xb4, 0xa3, 0x65, 0x53, 0x6d, 0xad, 0x21, - 0xa1, 0x24, 0x90, 0x6a, 0x09, 0xc6, 0xad, 0xfd, 0x39, 0x69, 0x8f, 0xb8, 0x56, 0x50, 0x0e, 0x9d, 0xa3, 0xcc, 0x6f, - 0x45, 0xc8, 0xe7, 0x39, 0x6c, 0x6f, 0x71, 0xe0, 0x47, 0x10, 0x9f, 0x2b, 0x5a, 0x07, 0xf2, 0xfc, 0x51, 0x56, 0x2e, - 0x67, 0xb5, 0x6f, 0x27, 0x11, 0x33, 0x55, 0x3b, 0xb0, 0xe5, 0x05, 0xaf, 0xcc, 0x16, 0x76, 0xf7, 0xa4, 0x63, 0xbd, - 0xc1, 0xdf, 0x1f, 0x12, 0xd7, 0xa1, 0x1f, 0x79, 0xc9, 0x61, 0x5b, 0xd6, 0x53, 0xea, 0x56, 0xc7, 0x69, 0x37, 0xc5, - 0x62, 0x3b, 0xeb, 0x44, 0x6f, 0x83, 0xed, 0x6a, 0xe7, 0x51, 0x3e, 0x9d, 0x39, 0xc6, 0x35, 0xe9, 0x72, 0x3f, 0xa6, - 0xe9, 0x54, 0x6b, 0x88, 0x96, 0x2d, 0xa5, 0x7b, 0xac, 0x57, 0x2c, 0x60, 0x6b, 0xf6, 0xfe, 0xa1, 0x68, 0xeb, 0xa2, - 0x2d, 0x25, 0x28, 0x66, 0x6a, 0xf3, 0xd6, 0x22, 0x98, 0x3f, 0x92, 0x37, 0xeb, 0xa4, 0xce, 0x44, 0x5b, 0x53, 0x9f, - 0xfc, 0xa3, 0xa9, 0x47, 0xde, 0x17, 0x2c, 0xc5, 0x42, 0x3f, 0xac, 0x77, 0x0b, 0x8c, 0x25, 0xf4, 0x8c, 0xa1, 0x6d, - 0xce, 0xad, 0x23, 0x97, 0x90, 0xe5, 0x30, 0xe5, 0x8a, 0xc3, 0x69, 0x0e, 0x91, 0x25, 0xdd, 0xff, 0x97, 0xb7, 0x5e, - 0xcb, 0x48, 0xaf, 0x4f, 0xe8, 0xb8, 0x53, 0xf8, 0xf3, 0x32, 0x59, 0x40, 0x39, 0xd6, 0x56, 0x7a, 0x5e, 0xd9, 0x17, - 0x91, 0xf9, 0x28, 0x2e, 0xfc, 0x1f, 0xbe, 0xf2, 0x58, 0xfa, 0x9d, 0x75, 0xfd, 0x98, 0xba, 0xe4, 0xaf, 0xb9, 0x8f, - 0x86, 0x4e, 0x5a, 0x08, 0x99, 0xfc, 0x9f, 0x48, 0xca, 0x8e, 0x2c, 0xc2, 0xa3, 0x03, 0x9c, 0xc0, 0xce, 0x9d, 0x6c, - 0x49, 0x2b, 0x21, 0x19, 0x88, 0xae, 0xd1, 0x1c, 0xcd, 0x40, 0x36, 0x69, 0x03, 0x21, 0x3c, 0x6e, 0xce, 0x7d, 0x97, - 0xb9, 0x44, 0xfa, 0x65, 0x1e, 0xcd, 0xd0, 0x3d, 0x33, 0x64, 0xd1, 0x04, 0xa2, 0x23, 0x29, 0xc3, 0x56, 0xdb, 0xee, - 0xaf, 0x26, 0x76, 0x1f, 0x67, 0xd4, 0xb7, 0x07, 0xdc, 0x67, 0x84, 0x94, 0xdb, 0x51, 0x8e, 0x9a, 0x7e, 0xf0, 0x55, - 0x6b, 0x37, 0x87, 0x50, 0x17, 0x33, 0xe4, 0xb2, 0x00, 0x25, 0xbc, 0x58, 0xef, 0xeb, 0xf3, 0x13, 0xfd, 0xf1, 0x97, - 0x89, 0x21, 0xaa, 0x9a, 0x35, 0x69, 0x8a, 0x01, 0xb8, 0x8d, 0x39, 0xdf, 0xed, 0xbc, 0xf3, 0xe1, 0xdc, 0x6c, 0x41, - 0x98, 0xad, 0xa0, 0x18, 0xdd, 0x7c, 0x6c, 0xb0, 0x20, 0x88, 0xd7, 0x9f, 0x28, 0x51, 0xa4, 0x07, 0xf5, 0xc9, 0xd4, - 0x97, 0xb2, 0x90, 0x41, 0x8a, 0x86, 0x45, 0xd1, 0xad, 0x6e, 0x59, 0xd7, 0x05, 0x7f, 0x0a, 0x43, 0x96, 0x6f, 0x60, - 0x78, 0xb2, 0x49, 0xd2, 0xb9, 0x2e, 0x61, 0x8a, 0x27, 0xf3, 0x32, 0x47, 0x2a, 0xf3, 0x3e, 0x43, 0x3b, 0xbd, 0xfd, - 0xe4, 0x1f, 0xd8, 0x0a, 0x87, 0xfa, 0x32, 0x39, 0xf9, 0xdb, 0x07, 0xfe, 0xfe, 0xac, 0x65, 0xc5, 0xd4, 0x72, 0xb5, - 0x98, 0xac, 0xbc, 0x2a, 0x38, 0xa7, 0x24, 0x2a, 0xb8, 0xb4, 0xa2, 0xf3, 0x03, 0x0f, 0x89, 0x6d, 0xfc, 0xa5, 0x40, - 0xe6, 0xe2, 0x91, 0xbd, 0x67, 0x07, 0xb5, 0x46, 0x20, 0x14, 0xc4, 0x2c, 0xaa, 0x05, 0xbe, 0x33, 0x59, 0x37, 0x66, - 0xf6, 0x92, 0x14, 0x68, 0x31, 0x1a, 0x6c, 0xfb, 0xd1, 0x47, 0x43, 0xbc, 0x2a, 0x85, 0x2b, 0xc9, 0xf8, 0xb3, 0x15, - 0xa6, 0x24, 0x0c, 0x59, 0xb9, 0x83, 0xbb, 0x2c, 0x56, 0xae, 0x45, 0x2e, 0x5f, 0xde, 0x7f, 0x9c, 0xaa, 0xda, 0x7b, - 0x44, 0x2c, 0x78, 0xfd, 0x4c, 0x51, 0xd5, 0x1a, 0x50, 0x26, 0xa3, 0x3b, 0xc6, 0x5d, 0x2c, 0xd4, 0x28, 0x6b, 0x66, - 0x57, 0xa0, 0xe6, 0xd8, 0xa6, 0xa2, 0x10, 0xe0, 0x8f, 0xb7, 0x97, 0xca, 0x05, 0x1e, 0xcc, 0x0d, 0x85, 0x28, 0xa3, - 0x2c, 0xdf, 0x99, 0x8c, 0x85, 0xd1, 0x51, 0x2b, 0xc3, 0xbf, 0x89, 0x62, 0xf5, 0xdc, 0xb3, 0xd7, 0xc7, 0x49, 0xaf, - 0x1b, 0x61, 0xa0, 0xa9, 0x2c, 0x9b, 0x6e, 0xdb, 0xd6, 0x6d, 0x85, 0x6f, 0xaa, 0x15, 0xc8, 0x53, 0x80, 0xd6, 0x55, - 0xd8, 0x08, 0x38, 0x83, 0x63, 0xf6, 0x65, 0x80, 0x1e, 0x1a, 0x18, 0xab, 0xbf, 0xb4, 0x62, 0xb8, 0xb5, 0x21, 0xa8, - 0x07, 0xf1, 0xcb, 0x5c, 0x20, 0x64, 0x60, 0x81, 0x1d, 0x8d, 0xdc, 0x89, 0xdf, 0x76, 0x7a, 0x9f, 0x7e, 0xaf, 0x97, - 0x8d, 0xb6, 0x46, 0xc8, 0xac, 0xac, 0xb0, 0xdc, 0xe9, 0xde, 0xe9, 0x21, 0x6a, 0x94, 0x58, 0xe7, 0x2c, 0x34, 0x97, - 0xdd, 0x59, 0x35, 0x08, 0xae, 0x7e, 0x30, 0x28, 0x90, 0x1c, 0x0c, 0xc5, 0x76, 0x19, 0x41, 0xd0, 0x10, 0xd4, 0x47, - 0x79, 0x09, 0xb0, 0x66, 0x90, 0x43, 0x2b, 0xa3, 0xc5, 0xbf, 0xea, 0x8b, 0xfe, 0xd3, 0xff, 0xb1, 0xe8, 0x5d, 0x13, - 0x60, 0xd9, 0x1e, 0xae, 0x67, 0x67, 0x78, 0xc1, 0x0c, 0x1a, 0x15, 0xa3, 0x3d, 0x84, 0x53, 0x73, 0x9a, 0x88, 0x41, - 0x2d, 0x85, 0xd8, 0xfe, 0xc4, 0xa3, 0xe5, 0xe4, 0xc8, 0x43, 0xfe, 0xdb, 0x87, 0x12, 0x16, 0x9d, 0xe6, 0xcb, 0x73, - 0x04, 0x77, 0x05, 0x4e, 0x71, 0x82, 0xd9, 0xc2, 0xfe, 0xc9, 0x97, 0x4f, 0xa5, 0x89, 0x39, 0x74, 0x81, 0xa1, 0xcc, - 0xd5, 0x33, 0x22, 0x6f, 0x17, 0x99, 0xd1, 0xaa, 0x54, 0x09, 0x2d, 0x90, 0x43, 0xa6, 0xfc, 0x3c, 0x66, 0xc1, 0xa8, - 0x61, 0x3f, 0xd7, 0x8d, 0x64, 0x1f, 0x02, 0x33, 0x62, 0x8b, 0xda, 0x5c, 0x14, 0x83, 0x70, 0x85, 0xb8, 0xc9, 0x46, - 0xeb, 0x82, 0x96, 0x9e, 0xd2, 0x2e, 0xa9, 0xc8, 0x4d, 0x3c, 0xee, 0xc7, 0x51, 0xb8, 0xd5, 0xf2, 0x56, 0x8c, 0xde, - 0x83, 0x53, 0x59, 0xef, 0x1f, 0xe3, 0x0f, 0x86, 0x03, 0xc4, 0x51, 0x5c, 0x71, 0x62, 0xf7, 0xc3, 0xc5, 0x5f, 0xce, - 0xdc, 0x9e, 0x02, 0x97, 0x47, 0x6a, 0xf9, 0x72, 0xc5, 0xff, 0x13, 0x1f, 0xdd, 0x85, 0xd4, 0x0c, 0xe5, 0x07, 0xc1, - 0x03, 0x8f, 0xbc, 0x84, 0x8f, 0xfe, 0x0c, 0x3a, 0xfc, 0x6a, 0xe5, 0xb7, 0x53, 0xbf, 0x09, 0xef, 0x2d, 0xdc, 0x5e, - 0x6b, 0xae, 0xd6, 0x35, 0x56, 0x09, 0xe3, 0x0b, 0x6d, 0x3d, 0xfe, 0x92, 0x34, 0x26, 0x8c, 0xb3, 0x73, 0x0e, 0x0b, - 0x8d, 0x20, 0xc1, 0x2c, 0xb8, 0x49, 0x8f, 0x0f, 0x5c, 0xa6, 0x15, 0x51, 0x82, 0x10, 0x92, 0xcc, 0xf7, 0x63, 0xe8, - 0x2a, 0xb1, 0x1d, 0x89, 0x64, 0x54, 0x16, 0x87, 0x46, 0x9c, 0xaa, 0xf8, 0x69, 0x8a, 0x75, 0xc2, 0xa7, 0x9a, 0x81, - 0x87, 0x38, 0x89, 0xbc, 0xef, 0xec, 0xe6, 0x3d, 0x40, 0x2b, 0x0a, 0xd5, 0x0a, 0xfa, 0x2a, 0x9a, 0xb6, 0xfe, 0x7a, - 0x7b, 0x8f, 0x6d, 0x97, 0x3c, 0xa1, 0xd7, 0x73, 0xfc, 0xab, 0xda, 0xd5, 0x5a, 0x39, 0xa5, 0x6b, 0xfd, 0x74, 0xbb, - 0xb0, 0x98, 0x35, 0x7a, 0xbc, 0x98, 0x21, 0x6f, 0x05, 0xde, 0x6a, 0x7c, 0x8a, 0x36, 0x68, 0x82, 0xfb, 0x56, 0x6d, - 0x76, 0xc8, 0x4a, 0xb8, 0xfe, 0xac, 0x9e, 0x54, 0x92, 0x70, 0xa0, 0x31, 0x70, 0x58, 0x74, 0x19, 0xb4, 0x99, 0x3b, - 0x35, 0x70, 0x57, 0x24, 0x87, 0xd6, 0x1f, 0x58, 0xd1, 0x6c, 0xb5, 0x85, 0x0e, 0x34, 0x30, 0x0d, 0x7e, 0x1c, 0x99, - 0x79, 0x2c, 0xff, 0xd0, 0xf3, 0x5f, 0x06, 0x89, 0xae, 0xe3, 0x13, 0xec, 0x43, 0xf2, 0x45, 0x05, 0x4d, 0x87, 0x27, - 0x14, 0x2c, 0x3a, 0xc9, 0xd5, 0x26, 0x77, 0x19, 0x73, 0x28, 0xcb, 0x5d, 0xf5, 0x37, 0x23, 0xd1, 0xe9, 0xab, 0xf7, - 0x7c, 0x47, 0x3a, 0x2d, 0x6c, 0x08, 0x25, 0xce, 0x2f, 0x51, 0x5f, 0x71, 0x70, 0x66, 0xb1, 0x9e, 0xfe, 0xeb, 0xb5, - 0x4e, 0x58, 0x7b, 0xf0, 0x70, 0x58, 0xde, 0xb8, 0x20, 0xbf, 0x30, 0xd2, 0x92, 0x86, 0x01, 0x34, 0x5c, 0xb4, 0x38, - 0x35, 0xcb, 0x39, 0xf0, 0xc8, 0x2b, 0x73, 0xa2, 0x06, 0xaa, 0x3b, 0x7d, 0x1a, 0x1d, 0x94, 0xe0, 0x29, 0x5e, 0x9a, - 0xb2, 0x16, 0xd3, 0xf2, 0xa4, 0xd5, 0x1a, 0x4a, 0xbf, 0xb2, 0x24, 0x5d, 0x2b, 0x7c, 0x3a, 0xd7, 0xb4, 0x6a, 0xa8, - 0xc1, 0xbc, 0x0b, 0x02, 0xac, 0x28, 0x89, 0x5b, 0x9b, 0xe5, 0xdb, 0x6f, 0x7f, 0xd9, 0xe1, 0x18, 0x26, 0x3f, 0x7f, - 0x59, 0xc4, 0x6f, 0x1f, 0x6a, 0x98, 0xc7, 0x3c, 0x10, 0x17, 0x4f, 0x27, 0xfa, 0x39, 0xf5, 0x04, 0xcf, 0xa4, 0x5d, - 0xc4, 0x86, 0xd1, 0x80, 0xf3, 0xb7, 0x75, 0xab, 0x58, 0x58, 0x3b, 0x80, 0x61, 0x2e, 0xe8, 0x6b, 0x00, 0x18, 0x8e, - 0x50, 0x76, 0x21, 0x5a, 0x85, 0xea, 0xbd, 0xd1, 0x20, 0x6d, 0x6c, 0xb5, 0x27, 0x5a, 0x44, 0x10, 0x51, 0xbc, 0x8c, - 0x51, 0x0a, 0x8d, 0x41, 0x5e, 0xe2, 0x52, 0xb5, 0xc2, 0xce, 0xcb, 0x16, 0xfc, 0xb9, 0x70, 0x2a, 0x10, 0x44, 0x4d, - 0x64, 0x16, 0xb2, 0x91, 0x0d, 0x55, 0xda, 0x94, 0xd7, 0x59, 0xad, 0x46, 0x5c, 0xf3, 0xe1, 0xcd, 0x89, 0x05, 0xe4, - 0xec, 0xc0, 0xb6, 0x20, 0x0e, 0xab, 0x66, 0xc8, 0x89, 0x3e, 0xa7, 0x2d, 0xa3, 0xe7, 0x5b, 0xad, 0xb1, 0x53, 0xde, - 0x15, 0xea, 0x7e, 0xce, 0x47, 0x2c, 0x0c, 0x48, 0xed, 0xce, 0xff, 0x27, 0x68, 0x67, 0xdf, 0x97, 0x2b, 0x1d, 0xfe, - 0xe6, 0x6d, 0x31, 0x97, 0xdc, 0x8b, 0xa3, 0xc8, 0x15, 0xc7, 0x54, 0x08, 0x63, 0x5c, 0x84, 0x17, 0xfb, 0xe1, 0x55, - 0x67, 0x50, 0xe7, 0x65, 0x40, 0x43, 0x8e, 0x07, 0xf6, 0xde, 0x83, 0xa0, 0xc5, 0x17, 0x7b, 0x8b, 0xc6, 0x1a, 0x94, - 0x17, 0xc5, 0xb6, 0x0f, 0x20, 0xc3, 0xa6, 0xdc, 0xff, 0x8f, 0x9b, 0x17, 0xb9, 0x4b, 0x36, 0x12, 0x2f, 0x71, 0x29, - 0x5c, 0xb5, 0xf1, 0x77, 0x49, 0x05, 0x9f, 0x36, 0x62, 0x10, 0xcd, 0xb5, 0x93, 0x7f, 0x83, 0x65, 0xcb, 0xea, 0x2e, - 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8f, 0x6f, 0x6e, 0xbc, 0x0a, 0x0b, 0x7b, 0x38, 0x0c, 0x33, 0xde, 0xe3, 0x2e, 0x76, - 0xbd, 0xad, 0xaa, 0xd8, 0x2e, 0x32, 0xe6, 0xa2, 0xa9, 0x35, 0x46, 0x33, 0xb8, 0xb9, 0xa1, 0x85, 0xed, 0xdf, 0x4a, - 0xe8, 0x68, 0xf1, 0xb0, 0x75, 0x17, 0xe2, 0xe5, 0x75, 0xa1, 0x76, 0x14, 0x5c, 0xb2, 0x91, 0x94, 0x2c, 0xc8, 0xb0, - 0xee, 0x3b, 0xce, 0x01, 0x34, 0x85, 0xab, 0x11, 0xb7, 0x6b, 0xd9, 0x7e, 0x2d, 0xfd, 0xcb, 0xf2, 0x71, 0x33, 0xe8, - 0x90, 0x73, 0xa0, 0x10, 0x5f, 0x08, 0xd9, 0x9c, 0x10, 0x9d, 0xb4, 0x6d, 0xf5, 0x5e, 0x84, 0x23, 0xbf, 0x52, 0x64, - 0xea, 0x9f, 0x37, 0x33, 0x4c, 0xb5, 0x1e, 0xc1, 0xc0, 0x0e, 0x09, 0x57, 0xbf, 0xc5, 0xd0, 0xba, 0x65, 0xc0, 0xc6, - 0xaf, 0xe8, 0x6d, 0x3c, 0xab, 0x45, 0x0a, 0xf9, 0x05, 0x51, 0xdf, 0x5a, 0xd1, 0x04, 0xd7, 0xdd, 0x0b, 0x6b, 0x08, - 0xf3, 0x7b, 0x1a, 0x72, 0x0f, 0x6a, 0x03, 0xf9, 0x34, 0xdf, 0xef, 0x52, 0xf3, 0x07, 0x1c, 0xc1, 0x18, 0xe7, 0x1c, - 0xec, 0x9a, 0x7b, 0x6e, 0x8d, 0xa6, 0xaa, 0x6d, 0x03, 0x7b, 0x4b, 0xd7, 0xa3, 0x16, 0x1e, 0xbf, 0xed, 0xde, 0x3a, - 0xcb, 0x0e, 0xe3, 0x4d, 0xb9, 0x80, 0x8a, 0x45, 0x7b, 0xa1, 0xf2, 0x2c, 0x97, 0x31, 0x2e, 0x55, 0x20, 0x4e, 0x60, - 0x41, 0x4a, 0x6a, 0x6e, 0xca, 0x70, 0xcb, 0xd6, 0x65, 0x70, 0x34, 0x21, 0xdd, 0xfa, 0xf3, 0xcc, 0xe7, 0x66, 0x72, - 0x54, 0xd1, 0xa7, 0x08, 0xcc, 0x12, 0x7d, 0x5a, 0xc0, 0x51, 0xa6, 0xaf, 0x4b, 0x11, 0x24, 0xe2, 0xdd, 0xa0, 0xcf, - 0xb5, 0x02, 0x45, 0x21, 0x31, 0xf2, 0x2e, 0x7a, 0xb4, 0x40, 0x3f, 0x78, 0x1a, 0x8c, 0x49, 0x7c, 0xfa, 0xef, 0xb2, - 0x57, 0xf1, 0x29, 0x59, 0xca, 0xfa, 0xde, 0x90, 0x4a, 0xe4, 0x24, 0x0d, 0x91, 0x74, 0x7e, 0xaa, 0xc0, 0xd4, 0x71, - 0xee, 0xcd, 0x5f, 0xa1, 0x1f, 0x7a, 0x2b, 0x26, 0x08, 0xd8, 0x8f, 0x71, 0x11, 0xd7, 0xe5, 0x0b, 0xfb, 0x98, 0x0e, - 0xcc, 0x02, 0xa3, 0xd5, 0x19, 0xf1, 0x40, 0xd2, 0x49, 0xb0, 0x94, 0x5d, 0x33, 0x97, 0x3a, 0x00, 0xe4, 0x6b, 0x93, - 0xcb, 0xde, 0x11, 0xe2, 0x4b, 0x76, 0x7d, 0x47, 0x10, 0x29, 0x53, 0xad, 0xa2, 0x1d, 0xb9, 0x47, 0x9a, 0x08, 0x96, - 0xea, 0x14, 0x2d, 0x6d, 0xb3, 0xed, 0xed, 0xec, 0x78, 0xee, 0xef, 0x72, 0x5f, 0x61, 0x8a, 0x16, 0xd4, 0xdf, 0xc5, - 0x45, 0x52, 0x55, 0x10, 0x21, 0x66, 0x70, 0x83, 0xb3, 0x31, 0xe2, 0x52, 0xa9, 0xe4, 0xcf, 0xf6, 0x40, 0x73, 0xd3, - 0xab, 0xd4, 0x54, 0xb8, 0x1a, 0x0b, 0x9b, 0xd8, 0x52, 0x3b, 0xb0, 0x44, 0x82, 0x07, 0x4f, 0x6f, 0x71, 0x5f, 0x96, - 0xbb, 0x13, 0xc1, 0x69, 0xd1, 0xd2, 0x13, 0x0f, 0xcb, 0x44, 0xbe, 0x93, 0xdd, 0xee, 0x9a, 0x22, 0xcd, 0x1e, 0x37, - 0xe9, 0x0e, 0x47, 0x29, 0x63, 0x55, 0x69, 0xde, 0x81, 0x6b, 0x2e, 0x81, 0x8b, 0x8e, 0x11, 0xad, 0x87, 0x26, 0xf5, - 0x69, 0x00, 0x5a, 0x40, 0xb5, 0x16, 0x39, 0x0e, 0xea, 0x80, 0x89, 0x2b, 0x1a, 0x06, 0x97, 0x00, 0xb1, 0xf3, 0x19, - 0xb2, 0xf3, 0x59, 0xc8, 0xb7, 0x94, 0x9b, 0x6d, 0x90, 0x44, 0xbe, 0x6a, 0x7d, 0x28, 0x36, 0x23, 0xf1, 0xa1, 0xa1, - 0x0f, 0xcf, 0x35, 0xfa, 0xf1, 0xcd, 0x55, 0xbf, 0xe2, 0xad, 0xe3, 0x9c, 0x06, 0x1f, 0x93, 0x74, 0xd1, 0x0a, 0xcf, - 0x65, 0x79, 0xa7, 0x85, 0xa7, 0xf1, 0x14, 0x86, 0x53, 0x65, 0xfd, 0x6a, 0x73, 0xd5, 0xf2, 0xd4, 0x46, 0x51, 0x5f, - 0x49, 0xf1, 0xef, 0xce, 0xc4, 0x6a, 0x89, 0x98, 0x63, 0x52, 0xae, 0x79, 0x5a, 0x4d, 0x4b, 0xc7, 0xff, 0xfc, 0xd0, - 0xf9, 0xa5, 0xec, 0x04, 0xc0, 0x54, 0xc6, 0x18, 0x61, 0xc5, 0x7b, 0x19, 0x35, 0x43, 0xec, 0x25, 0xb3, 0xc3, 0x58, - 0xa3, 0xda, 0x3f, 0xdd, 0x7a, 0x14, 0xb6, 0x25, 0xe9, 0xe1, 0xde, 0x42, 0xf0, 0x85, 0xac, 0xf4, 0xef, 0xb6, 0x8e, - 0xb4, 0xe4, 0xc5, 0x45, 0x8c, 0x92, 0x20, 0x91, 0x8e, 0xa3, 0xb6, 0x56, 0x73, 0x13, 0x16, 0x1a, 0xc6, 0x52, 0x5b, - 0xa7, 0xac, 0x16, 0xb6, 0x14, 0x63, 0x8e, 0x64, 0x3c, 0x32, 0xcf, 0x48, 0xcf, 0x11, 0xde, 0xe5, 0xd6, 0xd1, 0xa0, - 0xea, 0xee, 0xb9, 0xf6, 0xc2, 0x8b, 0xf6, 0x25, 0xe7, 0x9f, 0x5b, 0x49, 0x0d, 0xc5, 0x9d, 0x0c, 0x8d, 0xea, 0x89, - 0xc3, 0xec, 0xda, 0xe4, 0x03, 0x41, 0x13, 0x27, 0x2b, 0x9d, 0xe1, 0xe7, 0xdc, 0xf2, 0x17, 0xc7, 0x53, 0x13, 0xad, - 0x81, 0x6d, 0x47, 0x16, 0x6a, 0x03, 0xfc, 0x06, 0x6f, 0x42, 0xb3, 0x80, 0x96, 0xb0, 0x18, 0xe2, 0xd4, 0xcd, 0x98, - 0x34, 0x49, 0x3a, 0x5d, 0x20, 0xfc, 0x74, 0x9b, 0x99, 0x8e, 0x65, 0x0f, 0x77, 0x39, 0x90, 0xa9, 0xa1, 0x14, 0x8f, - 0xa0, 0xb9, 0x3c, 0x89, 0x6e, 0xc6, 0x54, 0xc2, 0x37, 0x6c, 0x9f, 0xb3, 0xf4, 0x1e, 0xbd, 0x42, 0x9b, 0x9e, 0x05, - 0x2b, 0x8f, 0x1b, 0x41, 0x8b, 0x4c, 0x18, 0x20, 0xbb, 0xe7, 0x00, 0x96, 0x16, 0xdb, 0x8b, 0xa6, 0xa3, 0x23, 0x91, - 0x2d, 0xc6, 0xd6, 0x38, 0xc7, 0xe6, 0x2a, 0xd4, 0x82, 0x9d, 0xe5, 0x25, 0x50, 0x36, 0xb2, 0xc3, 0x3b, 0xc6, 0x9f, - 0xbc, 0x21, 0x01, 0x4c, 0x69, 0xea, 0xd3, 0x2e, 0x7a, 0x15, 0x6c, 0xef, 0xfa, 0x58, 0xc4, 0x81, 0x39, 0x70, 0xc3, - 0x58, 0x1a, 0x3b, 0x53, 0x75, 0xcd, 0x03, 0x5a, 0xa9, 0xaa, 0x2b, 0x06, 0x21, 0x09, 0xc6, 0xbc, 0x3c, 0x15, 0x52, - 0xb3, 0x50, 0x2d, 0xdd, 0x74, 0x6a, 0x9b, 0xa0, 0xb0, 0x38, 0x9e, 0x9a, 0x3d, 0x0c, 0x32, 0x5c, 0xbf, 0x7f, 0x66, - 0x06, 0x48, 0x12, 0xae, 0x04, 0x94, 0xd1, 0xb0, 0xb3, 0x6d, 0xd6, 0x43, 0xbf, 0xdd, 0x24, 0xa2, 0xdd, 0xae, 0x1c, - 0x33, 0xea, 0x83, 0xea, 0x85, 0xe1, 0xf4, 0xce, 0x08, 0x8d, 0x84, 0x04, 0xd8, 0xc8, 0x8f, 0xfa, 0x0b, 0x52, 0xb1, - 0xc4, 0x45, 0xdb, 0x79, 0x61, 0xd6, 0xef, 0xf3, 0x40, 0x66, 0xf0, 0x04, 0x9b, 0xe6, 0x2c, 0x82, 0x6a, 0x24, 0x0b, - 0x12, 0x04, 0x44, 0xd5, 0xb6, 0x4f, 0x55, 0xb5, 0x15, 0x34, 0xce, 0xe3, 0x17, 0x9c, 0x9e, 0x7e, 0x6d, 0x10, 0x54, - 0xe2, 0x5f, 0xd9, 0xbc, 0xc5, 0x6b, 0x60, 0x8b, 0xeb, 0x91, 0xf2, 0x45, 0x5d, 0x96, 0x3f, 0xba, 0xb0, 0x4a, 0xfa, - 0xf7, 0xd6, 0x58, 0x88, 0x2a, 0x7f, 0xba, 0x42, 0x21, 0xa9, 0x3c, 0xba, 0xf3, 0x46, 0xf0, 0x25, 0x3b, 0x89, 0xc6, - 0xa2, 0x9d, 0xf4, 0x84, 0x1d, 0xae, 0x4a, 0x23, 0x88, 0x14, 0xff, 0x62, 0x45, 0x90, 0xb8, 0x2a, 0x5a, 0x76, 0x32, - 0x68, 0x25, 0x7b, 0xa0, 0xce, 0x89, 0x1b, 0xf3, 0x72, 0x6d, 0xca, 0xb7, 0x77, 0x27, 0x3a, 0xc8, 0x1a, 0x93, 0xe0, - 0x51, 0x83, 0x7d, 0xcb, 0x64, 0xbb, 0xec, 0x38, 0xf5, 0xa6, 0xa7, 0xef, 0xb9, 0x19, 0x09, 0x69, 0x09, 0x10, 0xf9, - 0xda, 0x8d, 0xc4, 0xec, 0xd6, 0xe3, 0x6d, 0x47, 0x2c, 0xe6, 0x76, 0x22, 0x4a, 0xa3, 0x8e, 0x6b, 0xf3, 0x10, 0x85, - 0x60, 0x85, 0xb1, 0x44, 0x97, 0x5f, 0x49, 0xe4, 0x16, 0x0b, 0x1b, 0xfb, 0x58, 0x7d, 0xca, 0x61, 0x93, 0x03, 0x84, - 0x70, 0xa9, 0x5b, 0xfd, 0x2b, 0xf4, 0x36, 0x7b, 0x42, 0xbf, 0x62, 0xe4, 0xe0, 0xa1, 0x0c, 0xd6, 0xad, 0x79, 0xd7, - 0x82, 0xc7, 0x2a, 0x2a, 0xf7, 0x61, 0x11, 0x21, 0x14, 0xf7, 0xfb, 0xd1, 0x50, 0xed, 0x5a, 0x62, 0x44, 0xf4, 0x28, - 0x19, 0x48, 0x6d, 0x3a, 0x85, 0x2b, 0x51, 0xc4, 0xe5, 0xa5, 0x1d, 0xcf, 0x67, 0x3b, 0xbb, 0x1b, 0x8d, 0x34, 0xf6, - 0xdd, 0xc0, 0xf1, 0x72, 0x2b, 0xcd, 0x1a, 0x8b, 0xb6, 0xef, 0x67, 0xb7, 0xb6, 0x05, 0xa2, 0x30, 0x62, 0xc4, 0xdc, - 0xb6, 0xf3, 0x09, 0xe9, 0x60, 0x27, 0x9f, 0xb1, 0x8f, 0x0d, 0x8c, 0x67, 0x30, 0x9b, 0xaa, 0xbe, 0xf6, 0xee, 0x67, - 0xf6, 0xbf, 0x0b, 0x6a, 0x23, 0x3f, 0x5f, 0xae, 0x44, 0x08, 0x68, 0x5c, 0xe8, 0x45, 0x86, 0x88, 0x1e, 0x4d, 0xb2, - 0x73, 0xd7, 0xe8, 0x25, 0xf6, 0xba, 0x90, 0x61, 0x87, 0xe3, 0x8f, 0xd6, 0x66, 0x4f, 0x68, 0x8e, 0xbf, 0x9f, 0x5d, - 0x1b, 0xfb, 0x5a, 0x8d, 0x93, 0x2c, 0x58, 0x95, 0x89, 0xd3, 0xf5, 0x7b, 0x8e, 0x28, 0x3e, 0xd3, 0xa9, 0xfb, 0x8e, - 0x36, 0x9e, 0x49, 0xd9, 0x48, 0x2a, 0xdd, 0x48, 0xa0, 0x32, 0x2b, 0x93, 0x77, 0x7b, 0x01, 0x50, 0x6d, 0x04, 0x58, - 0x34, 0x17, 0x9a, 0xa9, 0xec, 0x8b, 0xce, 0xd3, 0x43, 0xa4, 0x1c, 0x0f, 0x6f, 0x8e, 0x96, 0xa1, 0xc5, 0xeb, 0xd3, - 0x9c, 0xfd, 0x9b, 0x5b, 0x0d, 0x1d, 0xed, 0x1d, 0x15, 0x49, 0x73, 0xc1, 0xf4, 0xff, 0x62, 0xc5, 0x34, 0x00, 0x84, - 0x83, 0x06, 0x9c, 0xae, 0x72, 0x83, 0x0b, 0x92, 0x17, 0x98, 0xe6, 0xe2, 0x4c, 0xa0, 0xb5, 0x0d, 0x44, 0x54, 0xb4, - 0xe6, 0x47, 0x97, 0x71, 0xf1, 0x88, 0x76, 0x8e, 0x41, 0x54, 0xd4, 0xdf, 0xf6, 0x99, 0xb4, 0x82, 0xd9, 0xe7, 0x1c, - 0xb8, 0x5e, 0x33, 0x95, 0x12, 0x14, 0x83, 0xed, 0xb6, 0xfd, 0x36, 0x65, 0x10, 0x6a, 0xf4, 0x77, 0x52, 0xa1, 0x03, - 0xa3, 0x20, 0x47, 0x08, 0xe4, 0xdd, 0x1e, 0xf4, 0x59, 0x50, 0xd4, 0x33, 0xe2, 0x80, 0x9d, 0xbf, 0x76, 0x1c, 0xce, - 0x50, 0x7c, 0x9d, 0xfb, 0xf1, 0xdb, 0xba, 0x68, 0x1e, 0xdc, 0xf8, 0x43, 0xff, 0xfe, 0x11, 0x6d, 0x8b, 0xf6, 0x09, - 0x36, 0xc7, 0xcf, 0xe8, 0xf0, 0xb6, 0x19, 0x9c, 0x79, 0x7b, 0x42, 0x23, 0x10, 0x5b, 0x90, 0x3c, 0x17, 0xe8, 0x9c, - 0x43, 0x13, 0x9e, 0x67, 0xcd, 0x4c, 0x7e, 0xfa, 0x26, 0x55, 0xee, 0xa3, 0xec, 0xf8, 0x58, 0x74, 0xbb, 0xc4, 0x33, - 0x94, 0x6e, 0xe7, 0x56, 0x72, 0xdb, 0x87, 0x60, 0xfe, 0xe1, 0xb7, 0xbb, 0xdd, 0x63, 0x65, 0xfe, 0xcf, 0x4f, 0xd6, - 0x44, 0x3f, 0xdb, 0x45, 0xf3, 0xcb, 0x2a, 0x08, 0x0a, 0x5f, 0xee, 0x3a, 0xbd, 0x2c, 0xd0, 0xb8, 0x43, 0xd5, 0xb5, - 0x86, 0xab, 0xb9, 0x9a, 0xb9, 0x67, 0x2e, 0xee, 0x38, 0x9f, 0x91, 0x97, 0xd5, 0xe2, 0x7a, 0x40, 0xbf, 0x7d, 0x35, - 0xe6, 0x3f, 0xbf, 0x84, 0x26, 0xe5, 0xdc, 0xfd, 0x89, 0xf0, 0x7f, 0x83, 0x6b, 0x7a, 0xe7, 0x8e, 0xa2, 0xe0, 0x8c, - 0xeb, 0x9a, 0x61, 0x9b, 0x9c, 0x73, 0xe1, 0xb8, 0x4e, 0x39, 0xf0, 0xea, 0x10, 0x9b, 0x80, 0x30, 0xad, 0x8c, 0x67, - 0x4e, 0x9f, 0x46, 0xf2, 0x67, 0x0c, 0x18, 0x76, 0x1d, 0x82, 0x86, 0x60, 0x40, 0x89, 0xc5, 0xe8, 0xd4, 0x9d, 0x8c, - 0xa9, 0x26, 0x42, 0xd6, 0x80, 0x2d, 0x81, 0x12, 0xad, 0x6f, 0x81, 0x00, 0x5a, 0x3a, 0x81, 0x97, 0x8d, 0x8a, 0x1e, - 0x2d, 0x59, 0xc3, 0xe0, 0x60, 0xfe, 0x47, 0x1c, 0x8e, 0xe0, 0x7c, 0x8b, 0x84, 0xb8, 0x9b, 0x5b, 0x8f, 0xd2, 0xc6, - 0xf4, 0x89, 0xbe, 0x66, 0x1f, 0xf5, 0x14, 0xa4, 0xf9, 0xaf, 0x8b, 0x01, 0x82, 0x61, 0x38, 0x4e, 0x38, 0x5e, 0x25, - 0xf3, 0x0b, 0xa2, 0x76, 0xb1, 0xfe, 0xe5, 0x0c, 0xc6, 0xf6, 0x6f, 0xbc, 0xb6, 0x91, 0xff, 0x7f, 0x83, 0x25, 0xb7, - 0xbf, 0xe4, 0xe6, 0xcb, 0xbf, 0x96, 0xc7, 0x5f, 0xbe, 0xe6, 0x5b, 0xbe, 0x9b, 0x26, 0x78, 0xa7, 0xeb, 0x5e, 0xc9, - 0x50, 0xf3, 0xf3, 0x15, 0x46, 0xb8, 0x86, 0xc1, 0xd1, 0x58, 0x00, 0x1f, 0x2a, 0xda, 0x1c, 0x3d, 0x1b, 0x28, 0x13, - 0xfb, 0x35, 0x1e, 0x51, 0xbd, 0x5e, 0x81, 0x8f, 0x5d, 0x8d, 0x6b, 0x99, 0x5e, 0x26, 0x5a, 0xf3, 0x5c, 0xd9, 0xa5, - 0x86, 0x8a, 0x3b, 0xda, 0x02, 0xbe, 0x41, 0x5f, 0x57, 0xbe, 0xc4, 0x3a, 0xb2, 0xd9, 0x94, 0x27, 0x09, 0x4a, 0x3c, - 0x70, 0xd1, 0xf0, 0xd5, 0x33, 0xdb, 0x62, 0x7d, 0xf8, 0x73, 0xd1, 0x54, 0x13, 0x88, 0x7a, 0x54, 0x63, 0x36, 0x62, - 0xad, 0x55, 0x46, 0xcb, 0xab, 0x61, 0xe8, 0x48, 0xc6, 0xc5, 0xac, 0x32, 0xa1, 0x0c, 0xe8, 0x07, 0x4c, 0xd6, 0x2b, - 0xfa, 0x47, 0x3b, 0x45, 0xbe, 0x54, 0x9f, 0x52, 0xd4, 0xc3, 0xe3, 0x09, 0x8e, 0x53, 0x1f, 0x35, 0xfc, 0xa6, 0x49, - 0x5c, 0x85, 0x6b, 0x38, 0x37, 0x59, 0x73, 0xe6, 0x65, 0x6b, 0x97, 0x3a, 0x98, 0xd3, 0x84, 0xfd, 0x5b, 0xdb, 0x62, - 0xf1, 0x79, 0x12, 0x68, 0xbb, 0x68, 0x26, 0x97, 0xca, 0x5a, 0x10, 0x65, 0xfa, 0xf0, 0x06, 0x12, 0x88, 0xce, 0xb9, - 0x06, 0xea, 0xdb, 0xd4, 0x71, 0x38, 0xb7, 0x68, 0xab, 0x16, 0x2e, 0xad, 0xde, 0x6c, 0xa6, 0x70, 0xc2, 0x67, 0x97, - 0xf6, 0x22, 0x99, 0x68, 0xde, 0xe5, 0x89, 0x64, 0xfa, 0x6e, 0xec, 0xb3, 0x01, 0x71, 0x8b, 0x41, 0xcf, 0xc2, 0x44, - 0x19, 0xae, 0x29, 0xd8, 0x75, 0x95, 0x18, 0xc7, 0x01, 0xe0, 0xec, 0xd3, 0x90, 0x1b, 0x70, 0x78, 0x5d, 0x1b, 0x43, - 0x27, 0xba, 0x5b, 0xf4, 0x4a, 0x0a, 0x42, 0x50, 0xe5, 0xb0, 0xc4, 0xe6, 0x3d, 0xd9, 0x0b, 0xcb, 0x37, 0x78, 0xd8, - 0xb9, 0x53, 0x32, 0xe1, 0x4e, 0xe7, 0x09, 0x53, 0x56, 0xd1, 0x3b, 0xe4, 0x66, 0xc4, 0xeb, 0x0a, 0x8c, 0x29, 0x5c, - 0x01, 0x1b, 0x74, 0x88, 0xba, 0xf1, 0xdb, 0xef, 0x7a, 0xb9, 0xd9, 0xbb, 0x2d, 0x36, 0x33, 0x9e, 0xd1, 0x5a, 0xef, - 0x60, 0xed, 0x2c, 0xbd, 0xb6, 0x33, 0xb2, 0x50, 0x20, 0xc0, 0xc9, 0xdd, 0x66, 0x3d, 0x38, 0x46, 0x34, 0x97, 0xff, - 0x3b, 0x8b, 0x5d, 0x55, 0x4e, 0xbd, 0x31, 0xf4, 0x8a, 0x64, 0xe4, 0x10, 0x80, 0x64, 0x9c, 0x35, 0x1d, 0xa3, 0xd9, - 0xbb, 0xda, 0x76, 0x0e, 0xd3, 0xec, 0xdb, 0x34, 0xd7, 0xef, 0x4f, 0xe6, 0x5e, 0x20, 0x3f, 0x03, 0x37, 0xca, 0xd5, - 0x27, 0x8c, 0x75, 0x0f, 0xb4, 0x34, 0xb3, 0xfa, 0x46, 0x9e, 0xab, 0x19, 0xcb, 0x6d, 0xb0, 0xef, 0x06, 0x15, 0x0f, - 0xb0, 0xa0, 0x3f, 0xc9, 0xcb, 0xf3, 0x77, 0xaa, 0xe6, 0x6e, 0x7a, 0x84, 0x8d, 0x95, 0xcb, 0x70, 0x12, 0x2f, 0x87, - 0xfe, 0x05, 0x47, 0xcf, 0x89, 0xf9, 0x5f, 0x56, 0x24, 0x5d, 0x31, 0xcf, 0x30, 0x99, 0x18, 0xa5, 0x21, 0xc5, 0x19, - 0x2a, 0xe8, 0x7f, 0x58, 0x70, 0xbb, 0x6e, 0xd8, 0x40, 0x8a, 0x7f, 0xe3, 0x3e, 0x3b, 0x9e, 0x7b, 0xab, 0xcc, 0xa4, - 0x97, 0xcd, 0x71, 0x4b, 0xae, 0x6a, 0x5a, 0xcd, 0x7c, 0x56, 0x90, 0x4c, 0xdb, 0xcd, 0x63, 0x5e, 0x19, 0xbf, 0x74, - 0x13, 0xc9, 0x64, 0x4f, 0x67, 0x37, 0x40, 0x6b, 0x07, 0xda, 0xa7, 0xc4, 0xe9, 0x49, 0xa7, 0xab, 0x37, 0x3b, 0xa3, - 0x68, 0x9b, 0x5c, 0xa7, 0x1f, 0x68, 0xbd, 0xa0, 0xa3, 0xdb, 0x59, 0x2b, 0xc9, 0x73, 0x9f, 0xd8, 0x24, 0xc1, 0x4f, - 0xae, 0x63, 0xc1, 0xb1, 0x69, 0x40, 0x3f, 0xce, 0xcb, 0xf3, 0x4d, 0xde, 0x45, 0x06, 0x7c, 0xa6, 0xb0, 0xd9, 0xec, - 0x86, 0x31, 0xc7, 0x86, 0x18, 0x21, 0x48, 0x97, 0xe7, 0xed, 0x69, 0xdd, 0x09, 0x8d, 0xb7, 0x2c, 0x5c, 0x9b, 0x93, - 0x8b, 0xc2, 0xcf, 0xf4, 0xda, 0x34, 0x5c, 0xd0, 0x14, 0xda, 0xe7, 0x7e, 0x9a, 0x84, 0xe9, 0x1e, 0x93, 0xa8, 0x1a, - 0xee, 0xa6, 0x85, 0xfa, 0xb0, 0x50, 0x9e, 0x37, 0xe0, 0x05, 0x2b, 0xdc, 0xf3, 0x39, 0x39, 0x16, 0xf6, 0xe6, 0xbd, - 0xdb, 0x07, 0xb0, 0x5a, 0xcb, 0x3d, 0x66, 0xdc, 0xf1, 0xbe, 0xa3, 0x95, 0xfd, 0xd7, 0xb2, 0xe4, 0x58, 0x87, 0xad, - 0x9a, 0x65, 0xf0, 0x15, 0xa1, 0x39, 0x52, 0x03, 0x4d, 0x7c, 0x40, 0xa0, 0x0a, 0x84, 0x3b, 0x32, 0x6d, 0x67, 0x3c, - 0x65, 0xd4, 0xd1, 0x86, 0xa3, 0xa9, 0x13, 0x3b, 0x1e, 0x9e, 0x14, 0x5b, 0x0c, 0xbf, 0x35, 0xbd, 0x01, 0xcf, 0x7d, - 0x0f, 0xb4, 0xdd, 0xbd, 0x0e, 0x53, 0x7c, 0x65, 0x56, 0xd8, 0xc1, 0xaa, 0xd5, 0x18, 0x84, 0xd8, 0xb4, 0xca, 0xdc, - 0x15, 0x53, 0x02, 0x0c, 0xe7, 0xd4, 0xf8, 0xe2, 0xe0, 0x36, 0x34, 0x72, 0x6f, 0x32, 0x05, 0x4a, 0x1c, 0x5d, 0x0b, - 0x78, 0x92, 0xc6, 0x7c, 0x5a, 0x55, 0xc0, 0xaf, 0x8d, 0x7a, 0x15, 0x06, 0x74, 0xf1, 0x2e, 0x89, 0x1e, 0xf4, 0x90, - 0x22, 0x8e, 0xa7, 0x22, 0x5b, 0x13, 0xc6, 0xba, 0xce, 0xf6, 0xa1, 0x36, 0xf0, 0x7b, 0x45, 0xb5, 0x1f, 0xe0, 0xdd, - 0x06, 0x95, 0x95, 0x77, 0x87, 0xdf, 0x36, 0xb7, 0x24, 0xee, 0x25, 0x87, 0xe2, 0xba, 0xfa, 0x2a, 0x22, 0x03, 0x1e, - 0x94, 0x6a, 0x4d, 0x17, 0xc5, 0xf1, 0x53, 0x0a, 0xc6, 0x32, 0x45, 0x75, 0x32, 0xd3, 0xf6, 0x62, 0x84, 0x68, 0x74, - 0xec, 0x68, 0x73, 0x67, 0xe6, 0xcf, 0x27, 0x44, 0xe4, 0x04, 0xdb, 0xff, 0x54, 0x5e, 0x9c, 0x8d, 0x48, 0x18, 0xec, - 0xdf, 0x36, 0x43, 0x6a, 0x9f, 0xaa, 0x49, 0x9d, 0x86, 0x48, 0xd9, 0x0f, 0x6b, 0x5a, 0xff, 0xbf, 0xf8, 0x5c, 0x18, - 0x0d, 0x44, 0xef, 0xd4, 0x5b, 0x57, 0x4a, 0x60, 0xbb, 0xda, 0xa5, 0xf2, 0x52, 0xfa, 0xbc, 0x6f, 0x75, 0x13, 0x93, - 0xb2, 0xe0, 0x4d, 0xed, 0xcf, 0xd1, 0xfa, 0x49, 0xab, 0x0d, 0xb9, 0x77, 0xfa, 0xd4, 0xe3, 0x10, 0x23, 0x29, 0x27, - 0x88, 0xb1, 0xd4, 0x86, 0x10, 0x81, 0x47, 0x59, 0x83, 0xbb, 0xfe, 0xc9, 0x44, 0x6d, 0x93, 0x06, 0x68, 0x94, 0xe7, - 0x6d, 0xb1, 0xf5, 0xea, 0x4e, 0xe9, 0x8a, 0xdb, 0xe1, 0xca, 0xd6, 0x25, 0x60, 0x3a, 0x31, 0xf8, 0x74, 0x47, 0x77, - 0x0a, 0x78, 0x13, 0xec, 0x26, 0x13, 0xd0, 0x10, 0xc3, 0xd9, 0x7c, 0xf1, 0xcf, 0x96, 0x63, 0x7e, 0xe9, 0x07, 0x6c, - 0x0d, 0x92, 0x06, 0x70, 0x66, 0x00, 0x5b, 0x9f, 0x37, 0x57, 0xaa, 0x6f, 0x0f, 0xff, 0xda, 0x32, 0x7e, 0x47, 0x6e, - 0xf8, 0x7a, 0xdb, 0xd5, 0xc1, 0xf2, 0xc2, 0xb0, 0x43, 0xa0, 0x33, 0xa8, 0x4b, 0x0a, 0x93, 0xde, 0x05, 0xd4, 0xb9, - 0xd7, 0xb8, 0x81, 0x2b, 0x23, 0x84, 0x61, 0xc8, 0x83, 0xca, 0xb9, 0xbd, 0xc2, 0xbd, 0xf5, 0x3d, 0x81, 0x16, 0x20, - 0x3c, 0x54, 0xa1, 0x6d, 0x91, 0x49, 0xe7, 0xde, 0x60, 0xbb, 0x84, 0x75, 0x29, 0xe5, 0x54, 0x6b, 0x4e, 0xd7, 0x21, - 0xf9, 0xb8, 0xad, 0xfa, 0x16, 0x03, 0x72, 0x04, 0xa1, 0xd4, 0x33, 0x64, 0xd7, 0x70, 0x91, 0x5e, 0x6e, 0x8e, 0x74, - 0xca, 0xd7, 0x02, 0x62, 0x9b, 0xba, 0xdb, 0xa2, 0xfb, 0x7c, 0x2b, 0x0f, 0x41, 0x66, 0x9a, 0x4b, 0x40, 0xa2, 0x31, - 0x05, 0xf5, 0xc3, 0x30, 0x29, 0x97, 0xff, 0x5e, 0x23, 0x5e, 0xe7, 0xf1, 0xfa, 0xe7, 0x27, 0xab, 0xea, 0xc3, 0xf6, - 0x07, 0x3f, 0xd0, 0x7b, 0xb1, 0x69, 0xad, 0xde, 0x5e, 0xac, 0xbe, 0x9b, 0x15, 0xd4, 0xcf, 0x2c, 0x99, 0x41, 0x18, - 0x4b, 0x9d, 0x9d, 0xf1, 0x41, 0x5c, 0xf3, 0x1b, 0xb6, 0x5c, 0xde, 0x23, 0xf5, 0x2e, 0x93, 0x34, 0x99, 0xa6, 0xac, - 0x3e, 0xad, 0x4f, 0x3b, 0x45, 0xa0, 0x8d, 0x3a, 0x7a, 0x0d, 0xa7, 0x1c, 0xb8, 0x68, 0xd3, 0xa2, 0xbb, 0xcb, 0x3f, - 0x0b, 0x96, 0x85, 0x6e, 0x7f, 0x5d, 0x0e, 0xd6, 0x0d, 0x9f, 0x57, 0x74, 0x2e, 0x9c, 0xc8, 0xa1, 0x85, 0x05, 0x56, - 0x3b, 0x65, 0x70, 0xa6, 0xde, 0x64, 0x8b, 0x13, 0xdd, 0x44, 0x07, 0x79, 0x65, 0xac, 0xe3, 0xd4, 0x4b, 0xc3, 0x01, - 0xba, 0x66, 0x85, 0xcf, 0xf9, 0xa8, 0xcf, 0xfb, 0x13, 0x3a, 0x53, 0x90, 0xb5, 0xdc, 0x59, 0x14, 0xcb, 0xbb, 0x90, - 0x57, 0x51, 0x7d, 0xb9, 0x18, 0x59, 0x21, 0x94, 0x05, 0x6c, 0x7b, 0x7d, 0x1c, 0x87, 0x22, 0xf7, 0xa4, 0xc4, 0xd3, - 0xce, 0x39, 0x52, 0xee, 0x12, 0xe4, 0xee, 0x8a, 0xc5, 0x69, 0x24, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x86, 0xae, - 0x28, 0x72, 0x8b, 0x21, 0x04, 0x1c, 0x0d, 0x6f, 0x6f, 0xb4, 0x6d, 0xa4, 0x0c, 0x12, 0xc5, 0xce, 0x08, 0xe9, 0x97, - 0xb9, 0xa1, 0x7c, 0xb3, 0x0f, 0xa6, 0x8c, 0x41, 0x04, 0x04, 0x2a, 0xc8, 0x00, 0x2c, 0xfb, 0xca, 0xb9, 0x1a, 0x06, - 0xe3, 0x0c, 0x46, 0x02, 0x2b, 0xa0, 0xd7, 0x45, 0x93, 0x6e, 0xf8, 0x53, 0x78, 0x9a, 0x2a, 0x9e, 0xa6, 0x85, 0xa2, - 0xd1, 0x51, 0x79, 0x36, 0xa5, 0x6b, 0x9e, 0x06, 0x0b, 0x52, 0x4f, 0x9a, 0x1c, 0x36, 0x06, 0xf3, 0x68, 0x24, 0xe1, - 0x9e, 0x9a, 0x8c, 0x62, 0x65, 0x68, 0x1c, 0xfd, 0xb3, 0x3b, 0xc4, 0x39, 0x74, 0x50, 0x0b, 0xde, 0xcc, 0xe8, 0xe1, - 0xcc, 0x0f, 0x41, 0x6a, 0xd8, 0x5c, 0x85, 0xf9, 0x45, 0xa6, 0x4e, 0x75, 0xca, 0x28, 0x4b, 0x8c, 0xb3, 0x60, 0xed, - 0x18, 0x72, 0xa4, 0x7e, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, 0xb6, 0xf4, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, - 0xde, 0xd2, 0xf5, 0x5f, 0xcc, 0x6c, 0xdd, 0x8e, 0x39, 0x7f, 0xe9, 0xe7, 0xbb, 0xe9, 0x43, 0x1f, 0xf3, 0x66, 0xec, - 0x0c, 0x33, 0xba, 0xfe, 0x22, 0x2d, 0x1e, 0x14, 0x0d, 0x8a, 0x7c, 0xa9, 0x31, 0x8e, 0xb4, 0xbf, 0x1f, 0x9a, 0x46, - 0xbb, 0xdb, 0x3b, 0x49, 0x1a, 0x61, 0xcb, 0x11, 0x7a, 0x23, 0x38, 0x76, 0xc5, 0x7f, 0x5c, 0x55, 0xfe, 0x77, 0x4f, - 0xfd, 0xbe, 0x3d, 0x08, 0x5f, 0xd5, 0x4d, 0x1f, 0x46, 0x01, 0x73, 0xd6, 0xba, 0x5d, 0x7d, 0x96, 0x50, 0x43, 0xfa, - 0x6b, 0x82, 0xfa, 0x8d, 0x63, 0xf5, 0x8f, 0x69, 0x4a, 0xfe, 0x62, 0x57, 0xc1, 0xc6, 0x6c, 0xfd, 0x58, 0xd8, 0xa3, - 0x5a, 0x39, 0x3e, 0x77, 0xa7, 0x2d, 0x19, 0xed, 0x49, 0xf9, 0x56, 0x77, 0x78, 0xda, 0x49, 0x59, 0xca, 0xe6, 0x3d, - 0xb5, 0x98, 0x4c, 0x57, 0xdb, 0x4a, 0x1c, 0x91, 0x1e, 0xe4, 0x1b, 0x73, 0x46, 0xe9, 0xf8, 0x7d, 0xe5, 0x8f, 0xbb, - 0x93, 0xd8, 0xcc, 0xd3, 0x93, 0x70, 0x0b, 0xb4, 0x2b, 0xfb, 0x7e, 0x2b, 0xee, 0x3b, 0x29, 0xfe, 0x76, 0xd9, 0xaf, - 0x73, 0x95, 0x02, 0x1e, 0xf7, 0xbe, 0x60, 0xfb, 0xf9, 0x3a, 0x52, 0xd8, 0x8e, 0x14, 0x43, 0xb6, 0xf9, 0xaa, 0x4b, - 0xa2, 0x0a, 0x59, 0xf0, 0x06, 0xf9, 0x20, 0xae, 0x05, 0x20, 0xe7, 0xb4, 0x45, 0x2d, 0xfb, 0x8e, 0x25, 0x51, 0xbe, - 0xab, 0x40, 0x2d, 0x79, 0x76, 0x51, 0xd1, 0xa9, 0x3b, 0xe1, 0xab, 0x53, 0xcf, 0xd2, 0x9c, 0x86, 0xe8, 0x7a, 0x58, - 0xf2, 0x12, 0x95, 0xac, 0x9a, 0xde, 0x4d, 0xf0, 0x2b, 0xf6, 0xda, 0x13, 0x94, 0xbc, 0x23, 0xa5, 0xa1, 0x90, 0x51, - 0xac, 0x41, 0x7d, 0xeb, 0xdc, 0x25, 0x96, 0x74, 0xb4, 0x3c, 0xea, 0x55, 0xf8, 0x62, 0xee, 0xe3, 0xd6, 0x38, 0x2a, - 0xc7, 0x9c, 0x23, 0xd8, 0x93, 0x2a, 0x9d, 0x4c, 0x95, 0x03, 0xc0, 0x9a, 0x66, 0x11, 0x31, 0x48, 0xa9, 0x5d, 0x8e, - 0xbb, 0xf8, 0x16, 0x6c, 0x67, 0x31, 0xc8, 0xd2, 0xd7, 0x36, 0x19, 0x95, 0xce, 0x63, 0x27, 0xba, 0x1f, 0xbb, 0xda, - 0xc0, 0xc3, 0x60, 0x7b, 0xd6, 0x29, 0x57, 0x32, 0x56, 0x1c, 0x65, 0x57, 0x62, 0x6a, 0x79, 0xb6, 0x74, 0xbd, 0x45, - 0x54, 0xac, 0x95, 0x35, 0xbd, 0x0d, 0xd3, 0x53, 0xc1, 0x73, 0x3f, 0x3e, 0x61, 0x71, 0x64, 0xe4, 0x38, 0x93, 0x58, - 0xd5, 0x21, 0xcc, 0x4d, 0x3a, 0x82, 0x27, 0x48, 0x2d, 0x47, 0x32, 0x4f, 0x39, 0xa5, 0x50, 0xa1, 0xff, 0xa5, 0xf1, - 0x08, 0x55, 0x73, 0x75, 0xd3, 0x5b, 0x85, 0xef, 0x10, 0x84, 0xfe, 0x21, 0xba, 0x05, 0xe3, 0x82, 0xf7, 0xef, 0x25, - 0x22, 0xd5, 0x52, 0x28, 0x59, 0x5e, 0x5d, 0xd6, 0x98, 0xa1, 0xcd, 0x3b, 0x4a, 0xc9, 0x50, 0xa0, 0x0a, 0xd3, 0x17, - 0x7c, 0x6e, 0x10, 0x0e, 0xb9, 0x6b, 0x1d, 0x05, 0xb1, 0x22, 0xd8, 0x0d, 0x9d, 0x20, 0xa1, 0xae, 0x0a, 0xb1, 0x2f, - 0xc4, 0x1c, 0x9f, 0xcb, 0xac, 0xd0, 0x03, 0xfe, 0xe4, 0x37, 0xb1, 0xa4, 0xfe, 0x06, 0x46, 0xfe, 0x0d, 0xab, 0xb4, - 0xa1, 0x4f, 0xf9, 0x41, 0xec, 0x73, 0x21, 0x6f, 0x6a, 0xa6, 0xd9, 0x8e, 0xcb, 0x7e, 0xe6, 0xef, 0x4d, 0x78, 0xec, - 0x2d, 0xb1, 0xf3, 0x58, 0x50, 0xb9, 0x8c, 0x21, 0x06, 0xaa, 0x9b, 0xfc, 0x89, 0xd2, 0x3f, 0x9c, 0x4e, 0xfc, 0x66, - 0xbe, 0xb3, 0xb6, 0x3f, 0x5f, 0x85, 0x42, 0xec, 0x75, 0x86, 0x96, 0x30, 0x84, 0xf0, 0x64, 0x3e, 0xbb, 0x30, 0x27, - 0x21, 0x49, 0x45, 0x8b, 0x12, 0xce, 0x70, 0x7f, 0x03, 0x20, 0x03, 0x0d, 0x56, 0xa2, 0x54, 0xd4, 0x8b, 0x3d, 0x82, - 0x49, 0x3e, 0xdb, 0x7a, 0xd8, 0x8b, 0x3c, 0x5a, 0x48, 0xa3, 0x5c, 0xc1, 0x06, 0x30, 0xd5, 0x73, 0x1b, 0x89, 0xc5, - 0x48, 0x2f, 0x5a, 0x4b, 0xbe, 0xd4, 0x12, 0xea, 0x62, 0xe7, 0x61, 0xb0, 0xae, 0x1a, 0x54, 0x76, 0x1e, 0x0b, 0x66, - 0x3a, 0x07, 0x72, 0x5c, 0xa0, 0x51, 0x37, 0x26, 0xc7, 0x14, 0xb3, 0x6a, 0x85, 0x1f, 0xaa, 0x98, 0xb7, 0x74, 0x29, - 0xd8, 0xbc, 0x56, 0x77, 0xc7, 0xbb, 0x86, 0x09, 0x75, 0x68, 0x60, 0x96, 0x24, 0xa8, 0x61, 0x09, 0xeb, 0x0b, 0x3e, - 0x8f, 0xc1, 0x3c, 0x60, 0x9a, 0xb7, 0xd9, 0xed, 0x18, 0xf5, 0x5b, 0x35, 0x9f, 0x7a, 0xab, 0x3c, 0x6f, 0xb9, 0xc3, - 0x2b, 0x35, 0x37, 0xa7, 0xc5, 0x3c, 0x42, 0x44, 0xaf, 0xdb, 0x90, 0xf0, 0x9c, 0xb9, 0x97, 0xb8, 0x90, 0x78, 0xd2, - 0x67, 0x5e, 0x1f, 0x1f, 0x77, 0x22, 0xc7, 0xa8, 0xf4, 0xd6, 0x45, 0xc8, 0xec, 0x83, 0xb2, 0x72, 0x77, 0x78, 0x72, - 0xe9, 0xb4, 0x84, 0x4a, 0xd6, 0xf5, 0x9b, 0x4f, 0x13, 0xa8, 0xc2, 0x60, 0x86, 0xe2, 0x14, 0x9b, 0xea, 0xd1, 0x78, - 0x83, 0x79, 0x04, 0xe3, 0x22, 0x12, 0x6a, 0x30, 0x0f, 0x2e, 0xd1, 0x34, 0x12, 0x31, 0x67, 0xac, 0x6e, 0x07, 0xb0, - 0xe7, 0x4b, 0x4f, 0x31, 0x7b, 0x78, 0x6d, 0x2f, 0x99, 0xe3, 0xf6, 0x25, 0x70, 0x5b, 0xee, 0x4e, 0xb1, 0x9a, 0x3d, - 0x56, 0x49, 0x8d, 0x03, 0xd8, 0x48, 0xa3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, 0x76, 0x7f, 0x82, 0x27, 0x80, 0x63, 0x04, - 0x83, 0x13, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0xb1, 0xf2, 0xcd, 0x27, 0x81, 0x0d, 0x41, 0x64, 0x0a, 0x2b, 0x44, 0x4c, - 0x95, 0x21, 0xfc, 0xbc, 0x8b, 0xb3, 0xaf, 0x2e, 0x13, 0x4d, 0xb5, 0xd1, 0x08, 0xc5, 0x3c, 0xbc, 0x86, 0x9b, 0x79, - 0x60, 0xaa, 0xc7, 0x9a, 0x4e, 0x11, 0xd5, 0x4e, 0x62, 0x6a, 0xf5, 0xac, 0x63, 0xad, 0x5c, 0x6d, 0x8b, 0xc9, 0x27, - 0xea, 0x95, 0x3c, 0x40, 0x23, 0x9a, 0xc9, 0x84, 0x6f, 0x39, 0x33, 0x1f, 0xa6, 0xec, 0x11, 0x7e, 0x1d, 0xc3, 0x87, - 0xc7, 0x8d, 0xc0, 0x28, 0xcf, 0xc9, 0xce, 0x16, 0x32, 0x2e, 0x1c, 0x58, 0xfc, 0x69, 0xc8, 0x98, 0xfb, 0xa2, 0xe8, - 0xa9, 0x4c, 0x2f, 0x26, 0x2f, 0x7f, 0x56, 0xf3, 0x64, 0x1e, 0x08, 0x5b, 0xa3, 0x8a, 0xf4, 0x4b, 0xa3, 0xc5, 0x62, - 0x90, 0x7a, 0x18, 0xc6, 0x40, 0x8a, 0x85, 0x8a, 0x81, 0xa3, 0x4b, 0x75, 0xc0, 0xff, 0x4f, 0x41, 0x8f, 0x21, 0x7b, - 0x46, 0xdb, 0x6d, 0xce, 0xb7, 0xac, 0x27, 0x73, 0x63, 0xdf, 0xd9, 0x76, 0xf2, 0xc6, 0x03, 0x4e, 0x16, 0xfb, 0x85, - 0x59, 0xfc, 0x2e, 0x9f, 0x07, 0x4a, 0xec, 0x25, 0x41, 0x32, 0x0a, 0x90, 0x39, 0x9f, 0x85, 0x87, 0xd0, 0x6b, 0x5e, - 0x09, 0x51, 0xd0, 0x95, 0xe2, 0x4a, 0xa0, 0xf5, 0xe0, 0x34, 0x40, 0xa6, 0xc2, 0x15, 0x04, 0x32, 0x6f, 0x7e, 0x5c, - 0xee, 0x6e, 0x02, 0x69, 0x7b, 0x85, 0x0c, 0x66, 0x6e, 0xf5, 0x12, 0xa9, 0xf3, 0x81, 0x59, 0xbe, 0x64, 0x6f, 0x6c, - 0x59, 0xf7, 0xe0, 0x4c, 0x3f, 0x73, 0x74, 0x1a, 0xb2, 0xb2, 0x16, 0x0a, 0x9b, 0xec, 0xf4, 0x24, 0xaa, 0x2a, 0x45, - 0xf2, 0x8a, 0x72, 0x51, 0x50, 0x54, 0x08, 0xd3, 0xeb, 0x1f, 0x02, 0x42, 0x8e, 0x52, 0x06, 0xed, 0xb1, 0xe5, 0x2b, - 0x8c, 0x08, 0x81, 0x71, 0x21, 0x1a, 0x56, 0x90, 0x29, 0xec, 0xb2, 0x8a, 0x71, 0x9c, 0x9e, 0xa8, 0xba, 0x8b, 0x53, - 0x88, 0x3d, 0xef, 0x86, 0xcc, 0x12, 0x74, 0x6e, 0xb4, 0x35, 0xc6, 0x31, 0xf4, 0x33, 0xd1, 0x3f, 0x82, 0x1b, 0x9d, - 0xc3, 0x1a, 0x15, 0x9c, 0x1a, 0xfb, 0x9c, 0xc5, 0x3b, 0xbe, 0x0a, 0xf7, 0x7b, 0xda, 0x92, 0xde, 0x8e, 0x5d, 0x33, - 0x2b, 0x3f, 0x82, 0x2c, 0xa5, 0x2d, 0x43, 0x12, 0xd5, 0xb5, 0x97, 0x8e, 0x41, 0x53, 0x22, 0xb7, 0x9e, 0xcf, 0xc9, - 0xe8, 0x1b, 0x4c, 0x7e, 0xbc, 0x39, 0xdd, 0x97, 0x84, 0x0e, 0x56, 0x8b, 0x67, 0x2e, 0xbe, 0xc4, 0x26, 0xd0, 0x82, - 0x07, 0x00, 0xce, 0xdf, 0x89, 0xeb, 0xdf, 0x45, 0x0f, 0x0e, 0x63, 0x04, 0xb0, 0x10, 0x6f, 0xc5, 0xb0, 0xf2, 0x36, - 0xa2, 0xb4, 0x02, 0x20, 0xd7, 0xa6, 0x2a, 0xc0, 0x1b, 0x86, 0x6f, 0xb2, 0x64, 0x9f, 0xe3, 0x38, 0xdb, 0xb3, 0x42, - 0xe2, 0x1d, 0xfe, 0x59, 0x1f, 0x5e, 0x99, 0x70, 0x2e, 0xd8, 0x2d, 0x1d, 0xe7, 0x55, 0xdb, 0x88, 0xa4, 0xed, 0x62, - 0x10, 0xe3, 0x0c, 0x12, 0xa9, 0x0f, 0xd2, 0xf7, 0x57, 0x61, 0x21, 0x1a, 0x02, 0xef, 0x8b, 0x0a, 0xec, 0x75, 0x14, - 0x46, 0x93, 0xda, 0x23, 0x1a, 0x41, 0x4f, 0x57, 0x27, 0x24, 0x03, 0x95, 0x42, 0x6c, 0x98, 0x44, 0xfd, 0x4c, 0xb5, - 0xdd, 0x50, 0x7d, 0x53, 0xad, 0xa6, 0x50, 0xe3, 0x13, 0x30, 0x75, 0x28, 0x29, 0x18, 0x73, 0x6d, 0xd8, 0xa7, 0x8f, - 0x1d, 0x51, 0x6b, 0x0d, 0x4e, 0xef, 0x5f, 0x85, 0x81, 0x61, 0xb9, 0xd9, 0x7c, 0xf1, 0x15, 0x76, 0x9d, 0x73, 0x2f, - 0x50, 0x7d, 0x1f, 0xfd, 0x38, 0xae, 0x2e, 0xcb, 0xef, 0x7a, 0x37, 0xb5, 0x10, 0xef, 0xa9, 0xa3, 0x86, 0xfd, 0x94, - 0xc8, 0xf9, 0x2e, 0xc5, 0x7d, 0xdc, 0x51, 0x01, 0xf4, 0x79, 0xc8, 0x48, 0xab, 0x09, 0xc5, 0x05, 0x20, 0x5d, 0xc6, - 0x34, 0x2b, 0x0d, 0x54, 0xa8, 0xd9, 0x68, 0x2f, 0x23, 0xab, 0x0c, 0xc2, 0x41, 0xfb, 0xd5, 0x23, 0x28, 0x96, 0x55, - 0xba, 0xc9, 0x23, 0x80, 0xcd, 0xfa, 0x95, 0xdc, 0xfc, 0x17, 0x01, 0x1b, 0x0c, 0x0b, 0x36, 0x2f, 0xea, 0x25, 0xcf, - 0x79, 0x04, 0x98, 0xe4, 0x8c, 0xeb, 0x41, 0xb4, 0xfe, 0x6b, 0xd3, 0x7c, 0xb0, 0xe5, 0xde, 0x3b, 0x02, 0x49, 0xbd, - 0xac, 0x0d, 0xb0, 0xb2, 0x18, 0x52, 0xef, 0x39, 0x3f, 0x35, 0x32, 0x25, 0x20, 0x20, 0xfe, 0xc2, 0xd7, 0xf5, 0xeb, - 0xb0, 0x5e, 0xab, 0x74, 0xe7, 0x53, 0xd3, 0x5a, 0x15, 0x52, 0x9e, 0xcc, 0x5a, 0x45, 0x3e, 0x71, 0x55, 0x33, 0xc3, - 0xb4, 0x36, 0xaf, 0x4e, 0x4f, 0xfa, 0x0b, 0xca, 0x7d, 0x91, 0x33, 0x00, 0xe1, 0x35, 0x8f, 0x0f, 0x56, 0xef, 0x66, - 0xdf, 0x36, 0xae, 0x56, 0xb6, 0xfb, 0x17, 0x6d, 0x7c, 0x9a, 0xb1, 0x5b, 0xc3, 0x18, 0x54, 0xce, 0xcb, 0xc9, 0x6f, - 0x4a, 0x4a, 0x23, 0x2d, 0xa3, 0xcd, 0xb1, 0xcb, 0xa9, 0xf6, 0xe5, 0xea, 0xdd, 0x1a, 0x84, 0x15, 0x22, 0xb3, 0x07, - 0xcf, 0x08, 0x1f, 0x6f, 0xfd, 0x50, 0x08, 0x55, 0x69, 0xc7, 0x58, 0xde, 0x2c, 0x86, 0xa1, 0xf9, 0x5c, 0x8a, 0xcb, - 0x11, 0xe6, 0x5b, 0xe7, 0xa6, 0x29, 0x64, 0x6d, 0x22, 0xa9, 0xa3, 0xc0, 0xa4, 0xb8, 0x8c, 0x34, 0xe7, 0x5f, 0xc6, - 0x89, 0xe4, 0x5e, 0x29, 0x9f, 0xd4, 0x53, 0xea, 0x2d, 0xd8, 0x08, 0xc2, 0x9f, 0xd4, 0x2d, 0x7b, 0xa1, 0x41, 0xb3, - 0x4d, 0x92, 0xc1, 0xc9, 0xe7, 0x07, 0xbf, 0xc9, 0x5d, 0x7a, 0x0d, 0x91, 0x10, 0x4c, 0xf9, 0xdc, 0x36, 0xdd, 0x64, - 0xac, 0x04, 0xa4, 0xab, 0x1a, 0x6d, 0xd8, 0x4c, 0xd1, 0xf5, 0x79, 0x3f, 0xc8, 0xfb, 0xa1, 0x23, 0xb2, 0x18, 0x5b, - 0x94, 0xf0, 0x0b, 0x47, 0x62, 0x4e, 0xdd, 0x14, 0xa5, 0x35, 0xf4, 0xf6, 0x61, 0x76, 0xbd, 0xdb, 0x6b, 0xb9, 0x24, - 0x1d, 0x4e, 0x2b, 0xd2, 0x2c, 0x00, 0x21, 0xea, 0x14, 0xaa, 0x09, 0x38, 0x50, 0xe6, 0xe5, 0x2f, 0x91, 0x40, 0xca, - 0x0f, 0x70, 0x21, 0xbd, 0xcc, 0xe7, 0x28, 0x82, 0xf3, 0x50, 0xa5, 0x05, 0x17, 0x66, 0x8f, 0x81, 0xdf, 0x75, 0x4d, - 0xbf, 0x05, 0x7f, 0x66, 0x8a, 0x97, 0xc2, 0xc9, 0xf3, 0x72, 0xaf, 0xe1, 0x21, 0x06, 0x1f, 0x9c, 0x55, 0x5f, 0xf4, - 0x72, 0x1a, 0xd7, 0x19, 0xd8, 0xbd, 0xec, 0x81, 0xf9, 0x30, 0xf3, 0x56, 0x00, 0x99, 0xd3, 0xb8, 0xaa, 0xc0, 0x73, - 0x5e, 0xcd, 0xb5, 0x46, 0x39, 0xbd, 0x5f, 0x88, 0x31, 0x0d, 0xa5, 0x62, 0x6b, 0x98, 0x8a, 0x03, 0xc5, 0x45, 0xc9, - 0xbd, 0xac, 0x29, 0x4e, 0x9b, 0xf3, 0x86, 0xa4, 0x7c, 0x47, 0x03, 0x6d, 0x5e, 0xcd, 0x93, 0x7b, 0xfc, 0x8b, 0x7a, - 0xde, 0x7b, 0x1c, 0xbe, 0xbc, 0x99, 0x16, 0x83, 0x9c, 0x0f, 0x90, 0x53, 0x03, 0xc7, 0x6f, 0x4d, 0xf8, 0x63, 0x6e, - 0x69, 0x35, 0xc6, 0x1a, 0x9a, 0xf8, 0xc8, 0x56, 0x00, 0x29, 0xe3, 0x4d, 0x52, 0x2b, 0x7c, 0xa9, 0x43, 0xb1, 0x98, - 0x2c, 0xbf, 0x0b, 0x34, 0xb8, 0xc1, 0xd2, 0x33, 0x1c, 0x52, 0xd4, 0x8b, 0xa2, 0xa5, 0x3f, 0x51, 0x7e, 0x37, 0xee, - 0x3f, 0xed, 0x77, 0x4b, 0x60, 0xee, 0x71, 0x5b, 0x69, 0xb1, 0x91, 0xd0, 0x4d, 0x5b, 0xc9, 0xab, 0x0d, 0x55, 0x77, - 0xe7, 0xae, 0x89, 0xac, 0xe6, 0xba, 0x46, 0xa5, 0x06, 0x61, 0xfc, 0x5e, 0xbb, 0xb1, 0xcd, 0xb4, 0xb5, 0xd2, 0x41, - 0x9f, 0x21, 0xe9, 0xa5, 0xa2, 0xdd, 0xa0, 0x63, 0x4f, 0x4f, 0x68, 0xc7, 0x12, 0xf1, 0x1e, 0x21, 0x71, 0x86, 0x85, - 0x62, 0x5c, 0x98, 0x47, 0xf4, 0x56, 0x7a, 0xc5, 0x61, 0x63, 0xd2, 0xd3, 0x6c, 0x2c, 0xcb, 0x2b, 0x9c, 0xba, 0x2f, - 0x52, 0x40, 0xf1, 0xcf, 0xd1, 0x01, 0xfc, 0x33, 0x5d, 0x83, 0xd6, 0xe0, 0x54, 0x2e, 0x77, 0xf5, 0xba, 0xc4, 0x87, - 0x76, 0xc7, 0x13, 0x09, 0xdd, 0x0e, 0xd1, 0xf8, 0x86, 0xae, 0x70, 0xa3, 0x78, 0x95, 0x51, 0xc7, 0xca, 0xb4, 0x66, - 0xe4, 0xc3, 0x8a, 0xec, 0x5f, 0x20, 0xf2, 0xaa, 0x10, 0x85, 0x20, 0xad, 0x45, 0x34, 0x31, 0xd9, 0x7f, 0x9a, 0xe4, - 0x35, 0xa5, 0x99, 0x6d, 0xf4, 0xa7, 0x4d, 0x4d, 0xdb, 0x11, 0x70, 0xb7, 0x73, 0x13, 0x5d, 0xec, 0xcc, 0xa5, 0xb0, - 0x57, 0x50, 0xda, 0x42, 0xa2, 0x90, 0x75, 0x21, 0x5a, 0x6e, 0x97, 0x5a, 0xf9, 0xad, 0xf2, 0x14, 0x00, 0x10, 0x05, - 0x4d, 0xe8, 0xca, 0x6e, 0xb6, 0x77, 0xc5, 0xd2, 0xd5, 0x43, 0x04, 0x1f, 0x90, 0x12, 0x1c, 0xa0, 0x8b, 0x3c, 0xae, - 0xbb, 0x77, 0xb3, 0x8d, 0xc8, 0x46, 0xb6, 0x68, 0xad, 0x0e, 0xbc, 0x5c, 0xbf, 0xde, 0xe5, 0xff, 0xdf, 0xf7, 0xd8, - 0xfc, 0x05, 0x1c, 0x50, 0xb8, 0x0f, 0x1f, 0x4c, 0x0b, 0x4f, 0x1c, 0x6a, 0xfd, 0xd7, 0x86, 0x12, 0x05, 0x4f, 0xa2, - 0xf1, 0x73, 0xcd, 0x3a, 0x3d, 0x62, 0x14, 0x89, 0x8f, 0xd4, 0x03, 0x89, 0x5a, 0xad, 0x35, 0x3d, 0xae, 0xae, 0xd3, - 0xfa, 0x2f, 0x86, 0x7d, 0xb5, 0xab, 0x18, 0xe2, 0x4e, 0x2f, 0x6e, 0x23, 0x89, 0x42, 0xa1, 0xcf, 0x26, 0x3e, 0x61, - 0xa0, 0xb2, 0xe6, 0x0b, 0x0f, 0x29, 0x96, 0x97, 0xcb, 0xd0, 0x74, 0xa1, 0xc5, 0x6d, 0x81, 0x1a, 0x0f, 0x06, 0x3d, - 0x6b, 0x97, 0x20, 0xcd, 0xae, 0xff, 0x8c, 0x33, 0x9c, 0xb4, 0xd2, 0xea, 0xf3, 0x62, 0x08, 0xd9, 0xc7, 0x3b, 0xa9, - 0x55, 0xa1, 0x8c, 0xb3, 0xc7, 0xaa, 0xac, 0x0d, 0xbf, 0x86, 0x6a, 0x74, 0x8e, 0x55, 0xd4, 0xa6, 0xae, 0xad, 0x76, - 0xc6, 0xa0, 0x54, 0xc7, 0x81, 0x60, 0xd3, 0xd2, 0xc5, 0x20, 0x2d, 0xe2, 0x40, 0x1f, 0x48, 0xf2, 0xb8, 0xa4, 0xf9, - 0x2e, 0x15, 0xf9, 0x72, 0xd1, 0x10, 0x9a, 0xeb, 0xaa, 0xc2, 0x36, 0xe5, 0xb1, 0xa6, 0xa8, 0x8b, 0x9b, 0x1d, 0xeb, - 0xf0, 0x1a, 0x30, 0x8c, 0x17, 0xe0, 0x4a, 0x80, 0x93, 0xf2, 0xd5, 0xa7, 0x06, 0x3b, 0x66, 0x0a, 0x3d, 0x17, 0xfe, - 0xf8, 0xb4, 0x26, 0x13, 0x2b, 0x5e, 0xb5, 0x42, 0x89, 0xab, 0xc4, 0x53, 0x1d, 0x96, 0x4b, 0x37, 0xb1, 0x46, 0xc8, - 0x67, 0xe2, 0xaf, 0xd1, 0x22, 0xec, 0x0d, 0x64, 0x0d, 0xcb, 0x64, 0x32, 0x25, 0x24, 0x4c, 0x90, 0x73, 0xc0, 0x98, - 0x3a, 0xc9, 0x17, 0x97, 0xfe, 0x2c, 0xdc, 0xa1, 0xcf, 0xa6, 0xb5, 0x74, 0xdf, 0x49, 0x85, 0xee, 0x7b, 0x32, 0xe9, - 0x50, 0x4f, 0x1c, 0xc4, 0xcc, 0x14, 0x5c, 0x1d, 0xb7, 0xd8, 0x68, 0x30, 0x38, 0x3a, 0x3b, 0xd6, 0x62, 0x8b, 0x21, - 0x61, 0x03, 0xe6, 0x13, 0xb5, 0x7b, 0x1f, 0x3e, 0x93, 0xf4, 0xcb, 0xd7, 0x4b, 0x84, 0x90, 0xc1, 0xee, 0x44, 0xa9, - 0x19, 0x33, 0xd4, 0x34, 0x33, 0x05, 0xcd, 0xfc, 0xe8, 0x24, 0xd2, 0x1d, 0xde, 0x4c, 0xe8, 0x95, 0x06, 0xb7, 0xee, - 0xa9, 0xbe, 0x5c, 0x91, 0x46, 0x68, 0x8d, 0x39, 0x50, 0xf9, 0x70, 0x5a, 0x17, 0xd7, 0x2b, 0xdb, 0xf5, 0x03, 0x7e, - 0x68, 0xb5, 0x3b, 0x78, 0xd2, 0x20, 0xe3, 0x43, 0x93, 0xe4, 0xbc, 0x06, 0x2b, 0xc0, 0x43, 0x83, 0xa5, 0x68, 0x89, - 0x37, 0x45, 0xcf, 0x26, 0xfb, 0x68, 0xb4, 0x18, 0x8b, 0xb5, 0xfc, 0xfd, 0x9d, 0xa7, 0x7d, 0x21, 0xd5, 0x28, 0x7b, - 0x18, 0xc8, 0xee, 0x13, 0x28, 0x99, 0xa3, 0xd0, 0x9d, 0xcd, 0x50, 0xc5, 0x68, 0x9e, 0x00, 0x63, 0x05, 0xbf, 0xb8, - 0x66, 0x31, 0x9d, 0x33, 0xc7, 0xf9, 0x1a, 0x4e, 0x12, 0x47, 0x4d, 0x9c, 0x5b, 0x4f, 0x04, 0xe5, 0xd5, 0x62, 0x49, - 0xf4, 0x92, 0xa2, 0xa3, 0x8e, 0xd5, 0xf8, 0x8f, 0x89, 0xf5, 0xd4, 0x9c, 0x8e, 0x76, 0x3e, 0x8d, 0x15, 0x54, 0xd2, - 0x02, 0x6a, 0x72, 0x2c, 0xfb, 0x12, 0x0a, 0xdc, 0xff, 0xa7, 0x9a, 0x4a, 0xc5, 0xcb, 0x74, 0xb8, 0x59, 0x73, 0x60, - 0x03, 0xea, 0x08, 0xa0, 0xba, 0x35, 0x23, 0xa3, 0x6f, 0x7c, 0x7f, 0xa1, 0xee, 0xc6, 0x98, 0x03, 0x1d, 0xb4, 0x2d, - 0xfa, 0x1b, 0xe8, 0x91, 0x6c, 0x97, 0x83, 0x78, 0x83, 0xf2, 0x16, 0x4f, 0x02, 0x2f, 0x11, 0x4d, 0xd4, 0x6c, 0xac, - 0xe3, 0xb7, 0xd9, 0x3a, 0x0e, 0xde, 0x3a, 0x00, 0xbf, 0xb0, 0x6c, 0xc6, 0x99, 0x8d, 0xfa, 0x5e, 0x41, 0x0c, 0xf8, - 0x51, 0xec, 0x6c, 0xfc, 0xe9, 0x84, 0xda, 0x93, 0x1d, 0x4e, 0x39, 0x36, 0xca, 0x39, 0x61, 0x7b, 0xa6, 0x12, 0x00, - 0x29, 0x74, 0x51, 0x67, 0xc5, 0xc9, 0x4f, 0xbc, 0x15, 0x3b, 0xe2, 0x31, 0x12, 0x57, 0x88, 0x84, 0xe0, 0x82, 0x2a, - 0xb6, 0x6a, 0xb5, 0xea, 0xdc, 0xfc, 0x4c, 0x86, 0x4d, 0xc6, 0x04, 0x8b, 0x05, 0xbd, 0x7f, 0x46, 0x24, 0x84, 0x69, - 0x43, 0x48, 0x96, 0x26, 0x90, 0x1a, 0x8f, 0x5b, 0xf3, 0x24, 0x6d, 0xba, 0x04, 0x7e, 0x5d, 0x5d, 0x50, 0xa8, 0xb4, - 0xa2, 0xe0, 0xe7, 0x35, 0x1c, 0x7b, 0x8d, 0x30, 0xf6, 0x0c, 0x40, 0x1f, 0x49, 0xa0, 0xcc, 0x48, 0x61, 0x31, 0xb5, - 0xa7, 0x38, 0x82, 0x5a, 0x79, 0xd9, 0xd9, 0xae, 0xef, 0xaa, 0x1e, 0x26, 0xf0, 0x57, 0xcc, 0x81, 0x17, 0x50, 0xe6, - 0x48, 0x73, 0xba, 0x5f, 0xfe, 0x01, 0x20, 0xdc, 0x78, 0xfe, 0x8a, 0x08, 0xe9, 0x50, 0xed, 0x03, 0x74, 0x8d, 0xca, - 0x5e, 0xc5, 0x8c, 0x72, 0xb0, 0xaa, 0x1b, 0xb3, 0x4d, 0xe2, 0xeb, 0xf8, 0xba, 0x06, 0xe6, 0xf7, 0xc4, 0xcf, 0x40, - 0xee, 0x61, 0x64, 0xd9, 0x3a, 0x99, 0xd2, 0x5b, 0x6d, 0xb7, 0xc1, 0x95, 0x12, 0x69, 0xc3, 0x64, 0x59, 0x93, 0x1a, - 0xe8, 0x69, 0x05, 0x16, 0xc1, 0xbf, 0xd1, 0x3b, 0xf6, 0x8d, 0x30, 0x9d, 0x63, 0xdb, 0x35, 0x9c, 0x4d, 0x4a, 0x8f, - 0x73, 0x95, 0x4e, 0x4a, 0x48, 0x4d, 0xc5, 0x97, 0xcc, 0xb8, 0x52, 0x1e, 0x13, 0xce, 0x71, 0x35, 0x18, 0x32, 0x0c, - 0xa9, 0xa0, 0xfe, 0x36, 0x59, 0x4a, 0x53, 0x72, 0x96, 0x08, 0x9f, 0x62, 0xf9, 0x33, 0xaa, 0x25, 0xb7, 0x6d, 0xe0, - 0x98, 0xf6, 0x9a, 0xe5, 0x62, 0xc1, 0x8b, 0xf9, 0x13, 0x04, 0x03, 0x1f, 0x5f, 0x51, 0x4b, 0x9e, 0xcb, 0x83, 0x9d, - 0xc4, 0x48, 0xc6, 0xbf, 0x67, 0xda, 0x0d, 0x91, 0xcb, 0x52, 0x85, 0xc8, 0x4c, 0x7f, 0xe6, 0x61, 0xf5, 0x61, 0x39, - 0xd8, 0x4c, 0x11, 0xd3, 0xbf, 0xdf, 0x3f, 0x35, 0x18, 0xc1, 0x0f, 0x3d, 0x39, 0x6d, 0x46, 0x08, 0x7a, 0x16, 0x1d, - 0x55, 0xd8, 0x23, 0x72, 0xa2, 0x00, 0xc9, 0xb2, 0x47, 0xb1, 0xbe, 0xa4, 0x8e, 0x8e, 0xb1, 0x1e, 0x87, 0x13, 0x56, - 0xf6, 0x1c, 0xc9, 0x73, 0x50, 0x57, 0xcd, 0x92, 0xea, 0xd8, 0x63, 0xc0, 0xea, 0x6f, 0x38, 0x95, 0xae, 0xb9, 0xbb, - 0x41, 0x04, 0x5b, 0x22, 0xed, 0x38, 0x72, 0x09, 0xa0, 0x13, 0x4c, 0x61, 0xc8, 0x79, 0x3e, 0x1e, 0xaa, 0x97, 0xbf, - 0x25, 0x3a, 0x2a, 0x71, 0x43, 0x89, 0x74, 0x4b, 0x94, 0x4e, 0x2f, 0x63, 0xcf, 0xee, 0x96, 0x4a, 0xff, 0xc0, 0x03, - 0x4c, 0xd7, 0x29, 0x04, 0x39, 0xe4, 0x24, 0xe1, 0xad, 0x4c, 0x85, 0xb3, 0x7c, 0xd3, 0x1d, 0xdc, 0xb3, 0x88, 0xf1, - 0x10, 0xee, 0xed, 0x0e, 0xb8, 0x0d, 0x2c, 0x46, 0x8d, 0x66, 0x32, 0x70, 0x31, 0xc5, 0x18, 0x8e, 0x38, 0xa4, 0x9c, - 0x23, 0x96, 0x95, 0x3d, 0xee, 0xe6, 0xec, 0x94, 0x41, 0xb4, 0x88, 0x2e, 0x43, 0x95, 0x36, 0x49, 0x8f, 0x1d, 0xb2, - 0x90, 0xf6, 0x29, 0x9e, 0x11, 0xb6, 0x51, 0xd5, 0x69, 0xa2, 0xef, 0x9e, 0x82, 0xe3, 0x19, 0x3a, 0xc3, 0xae, 0x3d, - 0x3f, 0x51, 0xd8, 0x1b, 0x86, 0x50, 0x7e, 0xc9, 0xaf, 0x32, 0x7f, 0x5d, 0x4d, 0x01, 0xac, 0xd8, 0x86, 0xf9, 0x84, - 0x20, 0xce, 0x5c, 0x71, 0x58, 0xe7, 0xdf, 0x6c, 0x66, 0x2b, 0x37, 0xd6, 0xf0, 0x42, 0xa7, 0x14, 0x6e, 0x1b, 0xfd, - 0x1c, 0xe8, 0xec, 0x8a, 0x84, 0x1f, 0x3d, 0xc7, 0x01, 0x64, 0x23, 0x95, 0x64, 0xae, 0xb8, 0xa7, 0xf6, 0xb7, 0x20, - 0xae, 0x1e, 0xc8, 0xc9, 0xa3, 0x17, 0x24, 0xe8, 0x25, 0xf4, 0xe7, 0xf3, 0xe8, 0x5c, 0xa2, 0x61, 0x6f, 0x94, 0x4f, - 0xde, 0x9f, 0xb1, 0x98, 0x5b, 0xa4, 0xc3, 0xb4, 0x94, 0xbe, 0x87, 0xc9, 0x1c, 0x27, 0x14, 0x49, 0xd5, 0x37, 0x8c, - 0x24, 0x78, 0xf1, 0x4c, 0xa2, 0x73, 0x21, 0x37, 0xe7, 0x34, 0x62, 0xb9, 0x67, 0x95, 0xd5, 0x6b, 0x47, 0x51, 0xde, - 0x71, 0x35, 0x4b, 0xba, 0x49, 0xcd, 0x52, 0xc7, 0x56, 0x15, 0x66, 0x34, 0x32, 0xbe, 0x70, 0xab, 0x17, 0x49, 0x39, - 0x64, 0x83, 0x94, 0x0d, 0x6c, 0x1a, 0x93, 0x85, 0x51, 0x73, 0xb3, 0xf3, 0x45, 0xdc, 0xb1, 0x5d, 0x05, 0xad, 0x52, - 0x25, 0xe9, 0xa0, 0x7e, 0x50, 0xed, 0xfd, 0x40, 0xdb, 0x26, 0xc9, 0xdf, 0xd5, 0xac, 0x8b, 0xef, 0xa1, 0xab, 0x9c, - 0x56, 0x3b, 0x10, 0xe6, 0xa3, 0xa2, 0x1d, 0x03, 0x03, 0x45, 0xf1, 0x60, 0x7b, 0x0a, 0x5d, 0xde, 0x6f, 0x8d, 0x4a, - 0x26, 0x9d, 0x02, 0x9b, 0xb2, 0x2a, 0x98, 0xa6, 0x0a, 0xab, 0xf3, 0x1a, 0xb3, 0xbf, 0x3d, 0x2e, 0x3b, 0x09, 0xec, - 0x25, 0xe3, 0x1e, 0x9f, 0x82, 0xdf, 0x50, 0xbc, 0xc6, 0x1a, 0x72, 0x71, 0x1a, 0x98, 0x49, 0x98, 0x45, 0x69, 0xfd, - 0x76, 0xad, 0x7b, 0xfb, 0xb7, 0x5d, 0x3f, 0xa4, 0xf0, 0x81, 0x1e, 0x27, 0x46, 0xcd, 0xfc, 0xa3, 0xfc, 0x5a, 0x4a, - 0x7c, 0xe9, 0xeb, 0x96, 0xbb, 0xbf, 0x52, 0x27, 0xb1, 0x86, 0x39, 0x0c, 0xad, 0xd8, 0x1a, 0xc9, 0x7e, 0x41, 0x4c, - 0x6f, 0xd7, 0x3b, 0x49, 0xc4, 0x80, 0x73, 0x3d, 0x47, 0x96, 0xf9, 0xcc, 0x15, 0xf4, 0x4c, 0x22, 0x34, 0x4c, 0x57, - 0x33, 0x8e, 0x5a, 0x86, 0x5a, 0x4c, 0x1d, 0xc3, 0x1f, 0x1e, 0x32, 0x19, 0x3b, 0x94, 0xd1, 0x8f, 0x75, 0x7c, 0x9b, - 0x1a, 0xcb, 0x86, 0xaf, 0xa1, 0xdc, 0xb3, 0xcb, 0x3f, 0x3a, 0xd4, 0xe6, 0x71, 0x8f, 0xc7, 0xea, 0x20, 0x5e, 0xad, - 0xf6, 0xec, 0x0d, 0x8a, 0x58, 0x9f, 0xd6, 0xb0, 0x3a, 0xb8, 0xcc, 0xe6, 0xfc, 0x1c, 0x6c, 0x12, 0x5c, 0xbd, 0xd5, - 0xcd, 0x2f, 0x43, 0x74, 0x6b, 0x5c, 0x43, 0x72, 0x7e, 0x76, 0xbe, 0x87, 0x8f, 0xf8, 0xc9, 0xcf, 0xb4, 0x64, 0x9e, - 0xad, 0x13, 0xd8, 0x64, 0xd9, 0xb5, 0x65, 0x7e, 0x94, 0x3b, 0xbc, 0x2f, 0xfe, 0x67, 0x7d, 0x61, 0x03, 0x04, 0x84, - 0xf3, 0x4b, 0xfa, 0xc5, 0xe1, 0x39, 0xdb, 0x20, 0x76, 0xbe, 0xf9, 0xbe, 0x48, 0x73, 0x95, 0x06, 0x77, 0xfe, 0xd8, - 0x19, 0x82, 0x63, 0x04, 0xd8, 0x8b, 0xa0, 0x11, 0x21, 0x99, 0xde, 0x91, 0x52, 0x74, 0xb3, 0xc6, 0x69, 0x25, 0x65, - 0x2d, 0xdc, 0x57, 0xda, 0xd4, 0x5d, 0xb9, 0xbb, 0xa8, 0x88, 0xd9, 0xa5, 0x09, 0x0e, 0x05, 0x16, 0x23, 0x93, 0xb2, - 0x24, 0x85, 0xa6, 0xbc, 0xf8, 0x47, 0x82, 0x1d, 0x01, 0x93, 0x6b, 0xb4, 0x0a, 0xc1, 0x38, 0x9f, 0x77, 0x56, 0xa5, - 0xa7, 0x91, 0x21, 0xa8, 0x1e, 0x79, 0x65, 0x4b, 0x35, 0x8b, 0xa6, 0xa6, 0x7c, 0x97, 0x5a, 0x37, 0x62, 0xd8, 0x7b, - 0xd5, 0x72, 0x82, 0xbc, 0xab, 0xc4, 0xc9, 0x4d, 0x0e, 0xe3, 0x92, 0xf9, 0x1a, 0x41, 0x89, 0x34, 0xb3, 0x77, 0x09, - 0x93, 0x4d, 0xa6, 0x9c, 0xb3, 0x60, 0x5b, 0xc7, 0x20, 0x91, 0x38, 0x96, 0x1d, 0x12, 0x72, 0x95, 0xf6, 0x4d, 0x96, - 0xa2, 0x3a, 0x73, 0x2a, 0x43, 0x3f, 0xed, 0x78, 0x39, 0x47, 0x4c, 0xc7, 0xd9, 0x22, 0x1d, 0x23, 0x06, 0x10, 0xc6, - 0x8c, 0x27, 0x48, 0xd5, 0xbc, 0x94, 0xd1, 0xea, 0xe2, 0x19, 0xae, 0x51, 0x7b, 0x10, 0x98, 0xe8, 0x18, 0xc4, 0xbe, - 0x4e, 0x68, 0x9c, 0x88, 0xe6, 0x44, 0x79, 0xaf, 0xb5, 0xb0, 0xdd, 0x37, 0xb4, 0x2e, 0x99, 0xc2, 0xa5, 0x14, 0x48, - 0x2c, 0xf3, 0xeb, 0x40, 0xf2, 0x42, 0xd3, 0x58, 0xd1, 0x6a, 0x09, 0xc0, 0xd4, 0x16, 0xcf, 0xd3, 0xb7, 0x7c, 0x33, - 0xab, 0xc7, 0xec, 0x33, 0xba, 0x05, 0xb8, 0xf6, 0x29, 0x65, 0x5c, 0x0f, 0x1e, 0x7b, 0xa0, 0x40, 0x03, 0xf4, 0x94, - 0x73, 0xb7, 0xf8, 0x2b, 0xdb, 0x10, 0xaf, 0x43, 0x37, 0xa8, 0x65, 0x89, 0x3e, 0xe7, 0xd7, 0xe2, 0xe2, 0x3f, 0xe5, - 0x2e, 0x08, 0x8c, 0x5c, 0x7c, 0x52, 0xd0, 0xc3, 0x69, 0xa2, 0xcb, 0x84, 0xc7, 0x7b, 0xd4, 0x69, 0x0a, 0xca, 0x0d, - 0xcc, 0xe2, 0x26, 0x8b, 0x26, 0xdd, 0x5d, 0xdb, 0xea, 0xde, 0x1d, 0x8e, 0x35, 0x37, 0x75, 0x88, 0x3d, 0x75, 0x6f, - 0x56, 0x4d, 0x71, 0xf1, 0x6d, 0xdb, 0x64, 0x1a, 0xb6, 0x36, 0x8a, 0x4a, 0x9a, 0xe6, 0x2d, 0x6b, 0x7f, 0x91, 0xed, - 0x34, 0xc0, 0xdb, 0x85, 0x44, 0xd7, 0x7c, 0xb4, 0x04, 0xb1, 0xa5, 0xfc, 0x78, 0x31, 0xe5, 0xb1, 0xa2, 0xc5, 0x19, - 0xd6, 0x4d, 0xaa, 0x4c, 0xf2, 0x0c, 0x1d, 0x4d, 0xa8, 0xf3, 0x7d, 0x1c, 0x56, 0x8d, 0x46, 0xff, 0xbc, 0x4e, 0xcd, - 0x08, 0x93, 0xd0, 0xe8, 0x44, 0x38, 0x73, 0x18, 0x97, 0xc6, 0x88, 0x97, 0x5e, 0x7e, 0xcc, 0x3f, 0x98, 0x53, 0x14, - 0x58, 0x4f, 0x70, 0x5e, 0x0f, 0x6d, 0xe6, 0xc4, 0x21, 0xd0, 0x73, 0x63, 0x94, 0xf5, 0x25, 0xfd, 0xcc, 0x1b, 0x8d, - 0x7d, 0x28, 0xb9, 0x20, 0x08, 0x15, 0x9e, 0x73, 0x1c, 0x32, 0xcc, 0x40, 0x5f, 0x37, 0xd9, 0x02, 0x3f, 0x6b, 0x73, - 0x1e, 0xf6, 0x45, 0xac, 0x2d, 0x47, 0x17, 0x83, 0xaf, 0x9e, 0xd7, 0x31, 0x3f, 0x90, 0xbf, 0x5d, 0x2b, 0xe3, 0x18, - 0x95, 0x68, 0x10, 0xbb, 0x22, 0x6d, 0x0a, 0x80, 0xa8, 0xd4, 0x39, 0x0e, 0xa2, 0x02, 0xc6, 0xda, 0x0f, 0x94, 0x26, - 0x94, 0x91, 0x02, 0x58, 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x23, 0xd9, 0x35, 0xab, 0x8f, 0x91, 0xc5, 0x79, 0xb4, 0xbb, - 0x9a, 0x38, 0x2d, 0xba, 0x7b, 0x71, 0x51, 0x26, 0xc6, 0x3d, 0x2a, 0xda, 0x92, 0xc6, 0xad, 0x01, 0x73, 0x56, 0x74, - 0x6b, 0x32, 0x95, 0xab, 0x3b, 0x76, 0x96, 0xe0, 0xf4, 0xd6, 0x15, 0x58, 0xeb, 0x0e, 0xe6, 0xeb, 0x74, 0x56, 0xdc, - 0x7f, 0xa2, 0x20, 0x4d, 0x23, 0xb0, 0x66, 0x13, 0xa4, 0xfa, 0xd1, 0x92, 0x33, 0x0b, 0x58, 0xa5, 0x49, 0x69, 0x69, - 0x05, 0x0c, 0x3e, 0xdb, 0x88, 0x37, 0x6c, 0xcf, 0x9a, 0x0e, 0xab, 0xd1, 0xf7, 0xbe, 0x53, 0x93, 0xda, 0x23, 0xd3, - 0xdd, 0xf6, 0xe6, 0x14, 0x42, 0xf4, 0x85, 0x29, 0xcd, 0x14, 0x01, 0x70, 0xfe, 0xd3, 0x13, 0xc0, 0xed, 0xdb, 0x83, - 0x60, 0xa9, 0xe4, 0xb9, 0xda, 0x9c, 0xb0, 0x03, 0x22, 0x5b, 0xce, 0x75, 0x47, 0x42, 0x0c, 0x8e, 0x39, 0xa3, 0xa2, - 0x17, 0x24, 0x71, 0x06, 0xad, 0x6c, 0x75, 0x0d, 0xf8, 0xad, 0xc3, 0x81, 0x09, 0x51, 0x8e, 0x60, 0xf0, 0x8e, 0x31, - 0x6c, 0x66, 0x72, 0x9b, 0xd1, 0x40, 0x34, 0x54, 0x43, 0x96, 0x2f, 0x7b, 0xb1, 0x3d, 0xda, 0xd1, 0x7c, 0x60, 0xc9, - 0xfc, 0xe6, 0x13, 0xe1, 0x3e, 0xb6, 0x7b, 0xd8, 0xab, 0xef, 0x85, 0x49, 0x75, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, - 0xb8, 0xae, 0x5e, 0x9a, 0xbd, 0xe9, 0x1f, 0xce, 0xc6, 0x22, 0x07, 0x59, 0x05, 0xfd, 0x79, 0x30, 0x0f, 0x04, 0xd5, - 0xd4, 0x65, 0xb2, 0x08, 0x70, 0xa9, 0x11, 0xa5, 0xd7, 0x3a, 0x23, 0xb0, 0x0d, 0x8c, 0xeb, 0xb1, 0xb9, 0xc2, 0xd3, - 0xf3, 0x59, 0x12, 0x0d, 0x72, 0x28, 0x15, 0x7a, 0xcd, 0xe7, 0xa3, 0x0f, 0x4a, 0xfe, 0xeb, 0xf2, 0xb4, 0xfe, 0x4b, - 0xca, 0x19, 0xa8, 0xa6, 0x9d, 0xca, 0x3f, 0x96, 0x75, 0x10, 0x6f, 0x5b, 0xd7, 0x77, 0xae, 0xe7, 0x3f, 0x4c, 0x48, - 0xa6, 0xce, 0x6d, 0xe8, 0x2c, 0x26, 0x7d, 0xbf, 0x4b, 0xb4, 0x71, 0xb6, 0x22, 0x25, 0x06, 0xaa, 0xf6, 0x05, 0xd9, - 0xa4, 0xde, 0x24, 0xb5, 0xba, 0xf1, 0x91, 0xb6, 0xc8, 0x0a, 0x6e, 0x1a, 0xb2, 0x81, 0xfa, 0x69, 0xef, 0x8e, 0xdd, - 0xbe, 0x3f, 0x99, 0xbb, 0xaf, 0xdd, 0xe6, 0xdf, 0x28, 0xbb, 0xfd, 0xdc, 0x1b, 0x69, 0x36, 0x14, 0x3d, 0x6f, 0xbc, - 0x6c, 0x4b, 0xc6, 0xc1, 0x5b, 0x33, 0x03, 0xc1, 0x61, 0x4e, 0x3e, 0xd6, 0x79, 0x06, 0x24, 0x2d, 0xb3, 0x68, 0x03, - 0x72, 0x8d, 0x4b, 0x1c, 0x50, 0x55, 0xb0, 0xf3, 0x99, 0xa9, 0x36, 0x27, 0x12, 0xd7, 0x3b, 0x59, 0x1e, 0x76, 0x74, - 0x71, 0x87, 0x69, 0x99, 0x6e, 0xe2, 0xc2, 0xd1, 0x0d, 0x3b, 0x25, 0x4d, 0x36, 0x4f, 0x34, 0x9b, 0x4e, 0xbf, 0x4b, - 0xfa, 0xe6, 0x30, 0x90, 0x36, 0x67, 0x3e, 0xdc, 0x74, 0x1e, 0xba, 0xd0, 0x15, 0xee, 0x26, 0x15, 0xa9, 0xb4, 0x9c, - 0x40, 0x55, 0xc7, 0xb6, 0x52, 0x50, 0x94, 0xe2, 0xdf, 0x7c, 0x6f, 0x78, 0x58, 0x15, 0x7c, 0x13, 0x13, 0x49, 0xcc, - 0xd6, 0xaa, 0xf1, 0x85, 0x38, 0xfd, 0x41, 0x99, 0xb7, 0xf3, 0xf9, 0x24, 0x8e, 0x21, 0xff, 0xbd, 0x6a, 0x2a, 0x52, - 0x40, 0x93, 0x38, 0x48, 0xc8, 0xcc, 0xd8, 0x29, 0xfa, 0x78, 0x42, 0xe8, 0x4c, 0x52, 0x3e, 0xb8, 0xcc, 0xc1, 0x2f, - 0xbb, 0x3d, 0xba, 0xad, 0x72, 0x9b, 0x5b, 0x81, 0x3d, 0x55, 0x53, 0xa4, 0x25, 0x85, 0x4c, 0xba, 0x3a, 0x75, 0x6c, - 0x9c, 0xf5, 0xb5, 0xfb, 0x6f, 0x55, 0xc9, 0x9e, 0xbf, 0x3e, 0xe7, 0x6b, 0xe3, 0x90, 0x26, 0x15, 0xff, 0x8e, 0xdb, - 0x75, 0x77, 0x03, 0xc0, 0x9f, 0xb5, 0x4a, 0x89, 0x97, 0xd2, 0x35, 0xdd, 0x57, 0xd1, 0x6e, 0x78, 0xb6, 0xea, 0x27, - 0x4c, 0xd9, 0x9b, 0x91, 0xf2, 0x7e, 0xa2, 0xfe, 0xd2, 0xc3, 0x96, 0xa3, 0x19, 0x70, 0x32, 0xbc, 0xb9, 0x9d, 0x3b, - 0xcc, 0xf9, 0xd7, 0xd8, 0x1a, 0x0e, 0xbb, 0x6f, 0x40, 0x6f, 0x51, 0x1c, 0xb5, 0x6b, 0xa2, 0x64, 0x02, 0x01, 0x13, - 0xc1, 0x81, 0xb8, 0x8f, 0xd5, 0x48, 0x66, 0xed, 0x4b, 0xd8, 0x1d, 0xad, 0x4c, 0x8b, 0x96, 0x6a, 0xcd, 0xa7, 0x42, - 0x99, 0x49, 0x2a, 0x86, 0xd5, 0xc0, 0x9f, 0x5d, 0x39, 0x2d, 0xf8, 0x12, 0x58, 0x5e, 0xee, 0x78, 0x16, 0xb6, 0x0b, - 0x79, 0x7f, 0xfb, 0x60, 0x0d, 0xf8, 0x58, 0x9f, 0xb2, 0xe2, 0xbd, 0xfe, 0x77, 0x61, 0x43, 0x2d, 0x3d, 0xe6, 0xd7, - 0x66, 0xe1, 0x07, 0xe7, 0x35, 0x0e, 0x6e, 0x55, 0xed, 0x54, 0x31, 0x2e, 0x45, 0x14, 0x40, 0x80, 0x57, 0x34, 0x7c, - 0x47, 0x9d, 0xc7, 0xb3, 0xba, 0x44, 0x3f, 0x7e, 0xdf, 0x6d, 0x69, 0x4b, 0x12, 0x10, 0xa5, 0xca, 0x29, 0x72, 0x2b, - 0x27, 0xd7, 0x2c, 0x92, 0xa5, 0x77, 0x66, 0xd3, 0xa8, 0x68, 0x1a, 0x00, 0x48, 0xdf, 0x23, 0xcf, 0x82, 0xe7, 0x50, - 0x6e, 0x25, 0xf1, 0x56, 0xc9, 0x4c, 0x80, 0x89, 0xc2, 0x0f, 0x12, 0x21, 0x0c, 0x88, 0xbc, 0x1b, 0x06, 0x69, 0x6d, - 0x5f, 0xb8, 0x3e, 0x03, 0x58, 0x26, 0xc4, 0x5f, 0xdc, 0x87, 0x5b, 0xe7, 0xd3, 0xc1, 0xc9, 0x8d, 0x1c, 0x22, 0x82, - 0xd9, 0x28, 0xdd, 0x9b, 0x1c, 0x59, 0x65, 0xf7, 0x93, 0xab, 0x56, 0x4f, 0x04, 0x54, 0x5a, 0xbe, 0x57, 0xdc, 0x8c, - 0x38, 0x7f, 0x06, 0xdd, 0x6d, 0x70, 0xe5, 0x2a, 0xe7, 0xb4, 0x53, 0xd9, 0x21, 0xd9, 0xfe, 0xbb, 0x08, 0x5a, 0x94, - 0xcd, 0x14, 0xbe, 0x94, 0x2d, 0x3c, 0xb7, 0xd5, 0x95, 0xdb, 0x00, 0x90, 0x45, 0x62, 0x34, 0x17, 0x0d, 0xef, 0x92, - 0x08, 0xe3, 0xa2, 0xcd, 0x9f, 0xaa, 0x4f, 0xb3, 0x1a, 0x2a, 0xca, 0x46, 0xb5, 0xd9, 0x68, 0x86, 0x0c, 0xc4, 0x13, - 0xf4, 0xf2, 0xab, 0x1d, 0xe0, 0xc7, 0x2a, 0x79, 0xb2, 0x74, 0x1b, 0xf1, 0xb6, 0x3e, 0x49, 0xd4, 0xd3, 0x56, 0xf7, - 0x65, 0x98, 0x2c, 0x68, 0x9e, 0x3e, 0xff, 0xdf, 0x1d, 0xe0, 0x97, 0x90, 0x87, 0x2b, 0x16, 0xbe, 0x53, 0x75, 0x1f, - 0xaf, 0xaa, 0x70, 0xb1, 0x5e, 0x36, 0xe7, 0x83, 0x0e, 0x20, 0x47, 0xaa, 0xfa, 0x7d, 0x0e, 0xd3, 0x90, 0xe5, 0xb7, - 0x46, 0x17, 0x6e, 0x45, 0xc1, 0x81, 0xe7, 0xbd, 0x16, 0x2d, 0xd4, 0xd4, 0x55, 0x46, 0x84, 0x71, 0x4a, 0x50, 0x87, - 0x5b, 0x5d, 0xf0, 0xb4, 0x9b, 0x5b, 0x50, 0x49, 0x9e, 0x77, 0x93, 0x08, 0xe9, 0xc0, 0x7b, 0xb7, 0x52, 0x56, 0xbd, - 0x6e, 0x08, 0xc3, 0x5e, 0x39, 0xbb, 0x0a, 0x95, 0x3a, 0xad, 0xb4, 0x86, 0x1b, 0x5a, 0xb5, 0xa6, 0x68, 0xe0, 0xe4, - 0x94, 0xaa, 0x55, 0x2d, 0x79, 0xd6, 0x74, 0x6e, 0xb2, 0xcd, 0x5c, 0x56, 0x74, 0xdd, 0x21, 0xc3, 0x2b, 0x85, 0x75, - 0x5d, 0x07, 0xd7, 0x70, 0xa2, 0xc1, 0x79, 0xdf, 0x6e, 0x5b, 0x8e, 0x14, 0xd9, 0x2e, 0x56, 0x17, 0xee, 0xe8, 0xf8, - 0x2f, 0x0f, 0x28, 0x3e, 0x1d, 0xb5, 0xe4, 0x51, 0x8c, 0xac, 0xd0, 0x34, 0xb8, 0x06, 0x22, 0xfc, 0x0b, 0xaf, 0x4d, - 0xda, 0x6b, 0x4a, 0x26, 0xd4, 0xad, 0x9b, 0x73, 0x38, 0x48, 0x4b, 0xfc, 0xd2, 0x34, 0x8d, 0xb7, 0x79, 0x7a, 0x1f, - 0x4d, 0x56, 0xb5, 0xb7, 0x88, 0x4d, 0x7a, 0x76, 0x6d, 0x64, 0xb8, 0xc1, 0x84, 0x3c, 0xfe, 0x07, 0x3b, 0x01, 0x3a, - 0x91, 0x92, 0x05, 0x97, 0xe3, 0xca, 0x52, 0x0c, 0xf5, 0x9b, 0x57, 0x26, 0xeb, 0x53, 0x58, 0x64, 0x5e, 0x46, 0xae, - 0x5b, 0x2a, 0x47, 0xc3, 0x0f, 0x7d, 0x92, 0x2a, 0xe2, 0x3c, 0x03, 0x11, 0x78, 0xca, 0x6a, 0xe9, 0x79, 0x8e, 0x59, - 0x1b, 0x47, 0x92, 0xf9, 0x20, 0x24, 0x1f, 0xc6, 0xa5, 0x18, 0x52, 0x6c, 0xdf, 0xd8, 0x52, 0xe5, 0xf8, 0x86, 0x10, - 0x95, 0x13, 0xae, 0xa0, 0x09, 0x63, 0xed, 0x4f, 0x51, 0x51, 0x74, 0x67, 0xb5, 0x24, 0xd8, 0xad, 0x3a, 0x39, 0xa9, - 0xce, 0x34, 0x7f, 0x80, 0xc1, 0xd2, 0x1b, 0x74, 0x74, 0x58, 0x57, 0x63, 0x7e, 0x74, 0xb0, 0xe2, 0xd6, 0x57, 0x36, - 0x99, 0x45, 0xdb, 0x98, 0x71, 0xa6, 0xd4, 0x16, 0xdf, 0x5b, 0x9b, 0x5d, 0x04, 0x66, 0xf7, 0x0a, 0x97, 0x28, 0x22, - 0x67, 0xeb, 0x98, 0x91, 0x54, 0x71, 0xed, 0x10, 0xa9, 0xea, 0x9c, 0xd0, 0xc7, 0x40, 0x8b, 0xcf, 0x38, 0x5d, 0x2d, - 0xc4, 0x36, 0x0e, 0xbb, 0x8e, 0x4c, 0x95, 0xe4, 0x77, 0xd1, 0xe7, 0x7e, 0x2c, 0xc1, 0xe6, 0x02, 0xe2, 0x39, 0xdf, - 0x3b, 0x17, 0x6a, 0x16, 0x76, 0x21, 0xec, 0x60, 0x1a, 0x25, 0xe4, 0x68, 0xbf, 0x56, 0x7e, 0x8e, 0xe0, 0xd5, 0x2b, - 0x3d, 0x93, 0x0d, 0x3f, 0x11, 0xd1, 0xca, 0x52, 0xc2, 0x91, 0x0c, 0xa3, 0xf7, 0x2f, 0xde, 0xdc, 0x70, 0x90, 0xa1, - 0xf0, 0x0c, 0x36, 0x0f, 0x44, 0xc0, 0xed, 0xdd, 0x4f, 0x98, 0xd6, 0x52, 0x29, 0x08, 0xe7, 0x0a, 0x86, 0x04, 0x1b, - 0xe3, 0x52, 0x66, 0x6b, 0x93, 0x35, 0x01, 0x6b, 0xe1, 0x88, 0x3a, 0x68, 0x4c, 0x7a, 0x9e, 0x77, 0x9a, 0xd6, 0x31, - 0xff, 0x29, 0xb8, 0x60, 0xf9, 0x9e, 0x8d, 0xeb, 0x15, 0x04, 0xcd, 0x35, 0xae, 0xb1, 0xa6, 0xbb, 0xe8, 0x41, 0xea, - 0xfd, 0x35, 0x7b, 0xc6, 0x2a, 0x7f, 0xb7, 0xc0, 0x24, 0xd0, 0xa0, 0x50, 0x34, 0xe5, 0x2b, 0xa1, 0x43, 0x88, 0x5e, - 0xcd, 0x1b, 0xff, 0x2a, 0x7a, 0x96, 0x53, 0xcd, 0xe4, 0x76, 0xa3, 0x1a, 0x9a, 0x61, 0xca, 0x14, 0x12, 0xda, 0xc6, - 0x0f, 0x24, 0x5f, 0x76, 0xcb, 0xd4, 0xc2, 0x9c, 0xfd, 0x97, 0x16, 0xc7, 0xb1, 0x85, 0xaa, 0x55, 0x5f, 0x84, 0x39, - 0x4e, 0x4c, 0x5b, 0x77, 0xd9, 0xc8, 0x9d, 0xcd, 0x21, 0xa8, 0xa6, 0x6c, 0x6e, 0xd4, 0xbd, 0x63, 0x3e, 0x32, 0x87, - 0xb7, 0xc8, 0xef, 0x76, 0x64, 0x5e, 0x26, 0x97, 0x7d, 0xfc, 0xac, 0xd7, 0xbf, 0x09, 0x80, 0xc4, 0x36, 0x06, 0x8e, - 0xcd, 0xf3, 0xae, 0xb1, 0x96, 0x1b, 0xd3, 0x45, 0x62, 0x4d, 0x1d, 0x00, 0x0a, 0x9e, 0x72, 0xa0, 0x50, 0x49, 0x53, - 0x12, 0x04, 0xf5, 0x10, 0x72, 0x44, 0x39, 0xbe, 0x5d, 0xc4, 0x5c, 0xd7, 0xab, 0xc9, 0xc6, 0xbf, 0xdc, 0xfa, 0x68, - 0xd5, 0x07, 0xb4, 0xfb, 0x99, 0x8d, 0x7a, 0x58, 0xa4, 0xc6, 0x29, 0x0c, 0xf9, 0x11, 0xe7, 0xb1, 0xa6, 0x41, 0x37, - 0x4e, 0x06, 0x5a, 0x41, 0x2f, 0x15, 0xf8, 0xdf, 0x42, 0x39, 0x63, 0xe5, 0x46, 0x79, 0xa8, 0x58, 0xad, 0x5d, 0xf7, - 0xaf, 0xf8, 0x32, 0x62, 0x12, 0xa6, 0x87, 0x27, 0x60, 0xd6, 0x52, 0xae, 0xe4, 0xe7, 0xf5, 0x36, 0x54, 0x0b, 0x0f, - 0x38, 0xe9, 0xbc, 0xae, 0x3e, 0x07, 0x72, 0x91, 0x35, 0x53, 0x74, 0x68, 0xce, 0xd3, 0xa0, 0x82, 0x09, 0xbf, 0xad, - 0xe7, 0x26, 0x09, 0xba, 0xd4, 0x38, 0x56, 0x1e, 0x76, 0x1f, 0x47, 0xa3, 0xb3, 0x28, 0x27, 0x2e, 0x54, 0x63, 0x97, - 0xe7, 0x59, 0x54, 0x39, 0x2f, 0xf6, 0xa4, 0xab, 0x75, 0x65, 0xad, 0xbd, 0xa5, 0x15, 0xf3, 0xc6, 0x50, 0x4b, 0x52, - 0x73, 0x98, 0xd6, 0x89, 0x34, 0xb3, 0x68, 0x58, 0x99, 0x55, 0x08, 0xde, 0x86, 0xdd, 0x46, 0x88, 0xec, 0x82, 0x83, - 0xb4, 0x10, 0x2f, 0xbd, 0x59, 0x6a, 0x38, 0xc1, 0x53, 0xc8, 0x15, 0xfd, 0xc3, 0x69, 0x61, 0x40, 0x6a, 0x2b, 0x4a, - 0x66, 0xfd, 0xe8, 0xbf, 0xd9, 0x0c, 0xf7, 0x33, 0xd7, 0xca, 0x3b, 0xd4, 0x1f, 0x07, 0xa3, 0xd9, 0x8f, 0x49, 0x9f, - 0x72, 0xde, 0x2e, 0x05, 0x98, 0x2c, 0xc1, 0xb9, 0x17, 0xec, 0xcd, 0x80, 0x96, 0x37, 0x5e, 0x35, 0xb9, 0x21, 0x13, - 0xae, 0x9f, 0x24, 0x71, 0x2e, 0x56, 0x41, 0x7a, 0x09, 0xee, 0xbd, 0x68, 0xa8, 0x95, 0x05, 0xe9, 0xfe, 0x63, 0xb6, - 0xf8, 0x6b, 0x83, 0x91, 0x29, 0x88, 0x4f, 0x9e, 0xb0, 0xb7, 0x24, 0x8d, 0x4f, 0xe0, 0xd6, 0xb1, 0xe1, 0xda, 0xac, - 0x40, 0x1f, 0xfc, 0x79, 0xb2, 0x70, 0x68, 0x0d, 0xfc, 0xe7, 0xbb, 0x7f, 0x19, 0xaa, 0x1e, 0x3c, 0xdb, 0x99, 0x26, - 0xeb, 0x86, 0x9a, 0x48, 0xc3, 0x5f, 0xed, 0x7d, 0x01, 0xb8, 0x08, 0x57, 0x31, 0x03, 0x12, 0xd0, 0x95, 0xae, 0x58, - 0x60, 0x98, 0x02, 0xbb, 0x8c, 0xfe, 0x04, 0xbc, 0xad, 0x5c, 0x63, 0x3a, 0x4c, 0x8a, 0x4d, 0x00, 0xc4, 0x25, 0x01, - 0xf2, 0x96, 0x0e, 0x55, 0x04, 0x3a, 0x38, 0xc4, 0x7a, 0x79, 0x67, 0x12, 0xdf, 0xb9, 0x8f, 0xac, 0xce, 0x81, 0x3f, - 0x0d, 0xc8, 0x76, 0xa1, 0x00, 0x76, 0xcb, 0xbd, 0x5d, 0x87, 0x47, 0x83, 0x0c, 0x29, 0x51, 0x8c, 0x25, 0xf8, 0xf8, - 0x64, 0x1e, 0xf3, 0x98, 0xe7, 0xe3, 0x80, 0x6f, 0xf4, 0x01, 0x54, 0x1c, 0x2a, 0x90, 0xbf, 0x0b, 0x51, 0xa1, 0x2e, - 0xf7, 0xd1, 0x02, 0xc0, 0xe8, 0x13, 0xcc, 0xa1, 0x13, 0xb7, 0xd4, 0x1b, 0x50, 0xe5, 0x7b, 0x90, 0x52, 0x09, 0xfe, - 0x46, 0x26, 0x53, 0xd5, 0x9e, 0x8a, 0x59, 0x55, 0x18, 0x45, 0x24, 0x6c, 0xd4, 0x16, 0xc2, 0x1d, 0x63, 0x46, 0xcd, - 0x8f, 0x9d, 0x79, 0x1c, 0x4b, 0x7b, 0x3d, 0x12, 0x4a, 0x76, 0xc6, 0x7b, 0x0f, 0x4a, 0xe1, 0xe0, 0x2a, 0x80, 0xfb, - 0xb4, 0xfa, 0x9c, 0x4a, 0x8c, 0x99, 0x65, 0xd1, 0xf0, 0x50, 0x7a, 0x93, 0xa8, 0xf1, 0x55, 0x70, 0xfd, 0xcd, 0x40, - 0xbc, 0x8a, 0x3f, 0x7b, 0xdc, 0xf4, 0x71, 0xf5, 0xbf, 0x21, 0xe0, 0xea, 0x2c, 0x5c, 0x39, 0x61, 0x9f, 0x27, 0xc8, - 0xd7, 0x0d, 0xde, 0x2e, 0x5b, 0x4b, 0x34, 0x4f, 0x66, 0xe9, 0x73, 0x67, 0x58, 0xa0, 0xaa, 0xaa, 0xf9, 0x2d, 0x0a, - 0x25, 0x64, 0x91, 0x41, 0x68, 0x48, 0x9a, 0x99, 0x48, 0xed, 0xdc, 0x5b, 0x6e, 0x62, 0x47, 0x1a, 0x78, 0xda, 0xee, - 0x3d, 0xc3, 0xc7, 0x68, 0x30, 0x14, 0xc9, 0x33, 0xb8, 0xf2, 0x06, 0xba, 0x52, 0x49, 0xca, 0xe5, 0x7c, 0x2c, 0xfa, - 0x32, 0xf4, 0x2b, 0xfa, 0x4d, 0x5a, 0x96, 0xc7, 0x5d, 0x24, 0x52, 0xff, 0x57, 0xb9, 0xe6, 0x34, 0xfa, 0xbc, 0x34, - 0xb6, 0x51, 0x31, 0x68, 0x70, 0xdb, 0x14, 0x08, 0x39, 0x53, 0x5a, 0x94, 0x1e, 0x0c, 0x2d, 0x7d, 0xff, 0xc3, 0x55, - 0x58, 0xba, 0xa7, 0xb4, 0x53, 0x9e, 0x5e, 0xf4, 0x52, 0x83, 0x81, 0xf8, 0x77, 0xb2, 0xe4, 0x4d, 0x5f, 0xa9, 0x91, - 0x4c, 0xfc, 0x1f, 0xbc, 0xb4, 0x51, 0x2e, 0x97, 0x3a, 0xa5, 0xd3, 0x0e, 0x8a, 0xa3, 0x2e, 0x39, 0x1e, 0xc5, 0xbe, - 0x65, 0x34, 0x8a, 0x57, 0xca, 0x3e, 0x8b, 0x89, 0x1b, 0xf4, 0x44, 0x34, 0x68, 0xd6, 0x32, 0x80, 0x26, 0x7a, 0x4d, - 0xc9, 0x88, 0x53, 0x77, 0x82, 0x1b, 0x81, 0x32, 0xab, 0x68, 0x43, 0x52, 0x37, 0xbe, 0x31, 0x98, 0x5a, 0x3d, 0xee, - 0x87, 0x21, 0x2a, 0x65, 0x7d, 0xfb, 0x74, 0x44, 0xd5, 0x57, 0xd9, 0xa5, 0xf4, 0xad, 0x62, 0xa3, 0x5d, 0xea, 0x70, - 0xc7, 0x1c, 0xd8, 0xe4, 0x99, 0x41, 0x2d, 0x67, 0x0e, 0x31, 0x3f, 0x3d, 0x8f, 0x36, 0x0e, 0x98, 0x9d, 0x18, 0x62, - 0x8e, 0x3a, 0x57, 0x25, 0x90, 0xc6, 0x60, 0x3a, 0xb1, 0x93, 0x44, 0xea, 0x4b, 0xcb, 0x5e, 0xaf, 0x54, 0x31, 0xa7, - 0x96, 0x96, 0xfd, 0x00, 0x76, 0xf8, 0x4a, 0xcb, 0x4f, 0x54, 0x61, 0x68, 0x76, 0xcb, 0x1a, 0xe1, 0xaf, 0x36, 0xbd, - 0x8e, 0xd7, 0xf1, 0x2a, 0x95, 0xa5, 0x3b, 0x20, 0x86, 0x1c, 0xcc, 0x4e, 0xb0, 0x01, 0x29, 0xa2, 0x65, 0x71, 0xbe, - 0xe6, 0x29, 0x9f, 0x8d, 0x63, 0x89, 0xb5, 0xd1, 0x63, 0xcb, 0xdb, 0xe6, 0xdc, 0xa3, 0x19, 0xa1, 0x22, 0x51, 0x62, - 0xd9, 0xd6, 0xb0, 0xb8, 0x11, 0x0b, 0x4a, 0x88, 0x25, 0xfa, 0x05, 0x3f, 0x23, 0xe2, 0x6a, 0x80, 0xde, 0xa4, 0x76, - 0x06, 0x5d, 0x05, 0x1d, 0x8c, 0xa3, 0x6b, 0xfe, 0x3b, 0x0d, 0x37, 0x85, 0x2e, 0x11, 0xb7, 0x0d, 0x70, 0xc9, 0xc5, - 0x0c, 0x83, 0x3a, 0x85, 0xac, 0x6e, 0xe2, 0x5b, 0x5d, 0xe4, 0x7f, 0x62, 0xf1, 0x27, 0xb8, 0x90, 0x17, 0x97, 0x86, - 0x17, 0xe4, 0xa6, 0xbc, 0xf7, 0x5b, 0xdc, 0xc8, 0x10, 0xad, 0x7c, 0xfa, 0xe8, 0xf2, 0x62, 0x91, 0x66, 0xdc, 0xa9, - 0xe9, 0xad, 0xf1, 0xb9, 0x6e, 0x45, 0x7f, 0x32, 0x9e, 0x9b, 0x71, 0x92, 0x66, 0xe4, 0xa7, 0x7c, 0xc8, 0xef, 0xa1, - 0x54, 0x33, 0x9c, 0x57, 0x73, 0x1d, 0x50, 0xcf, 0x0c, 0x5f, 0x4e, 0x63, 0x1d, 0x98, 0x74, 0x0b, 0xfe, 0xb0, 0x87, - 0x43, 0xd9, 0xb4, 0xb7, 0x4f, 0xde, 0xf0, 0xb9, 0xd5, 0x3d, 0x5d, 0x32, 0x4a, 0x1a, 0x4c, 0x7d, 0x54, 0xb5, 0xdf, - 0x97, 0x68, 0x1c, 0xc4, 0xd3, 0x18, 0x6b, 0x44, 0xff, 0x4b, 0x7c, 0x7c, 0x55, 0x86, 0x37, 0xc0, 0x3c, 0x28, 0x49, - 0x8e, 0xa5, 0x5f, 0x8c, 0x69, 0x84, 0xc8, 0x7b, 0xcc, 0x2f, 0xea, 0xf5, 0x60, 0xe3, 0x32, 0xe4, 0xe2, 0x15, 0xd1, - 0xe3, 0xd9, 0xe2, 0x5b, 0xe8, 0xc2, 0x70, 0x98, 0x9a, 0x00, 0xfe, 0x1f, 0x65, 0x0f, 0xd4, 0x0f, 0xa1, 0x7c, 0x99, - 0x36, 0xb6, 0x9f, 0x6d, 0x9a, 0x65, 0x46, 0xde, 0x9d, 0x27, 0x6b, 0xb6, 0x91, 0xc4, 0xda, 0x34, 0x6a, 0x13, 0x34, - 0x5a, 0xbd, 0xcd, 0xd9, 0x37, 0x36, 0xa6, 0xd1, 0xd0, 0xf7, 0x68, 0xa6, 0xf4, 0xfa, 0x31, 0x7d, 0x71, 0x7d, 0x87, - 0x98, 0x18, 0xf6, 0x9b, 0xd5, 0x3a, 0x24, 0x36, 0xba, 0xdb, 0x71, 0xc6, 0xfa, 0x1e, 0xd1, 0x7d, 0x93, 0xcb, 0x42, - 0x4e, 0x6e, 0x42, 0xa6, 0x12, 0x75, 0xed, 0xdb, 0x6a, 0xd8, 0xde, 0x03, 0x94, 0x51, 0xb3, 0xd4, 0xc0, 0xe8, 0x8b, - 0xd7, 0xe5, 0x0c, 0xc1, 0x35, 0xb7, 0xde, 0xb8, 0x40, 0x64, 0xf0, 0xd1, 0xb4, 0xcc, 0x65, 0x51, 0x03, 0x27, 0x47, - 0xeb, 0x20, 0xfd, 0xf2, 0x20, 0x1e, 0xa9, 0xfa, 0xe2, 0x6d, 0xcd, 0xc0, 0x8a, 0x96, 0xa8, 0x86, 0x0f, 0x7c, 0xbc, - 0x36, 0xce, 0xcb, 0x8c, 0x5f, 0x4e, 0x8e, 0xd2, 0x0d, 0xe3, 0xca, 0xda, 0xee, 0x62, 0x1c, 0xae, 0xba, 0xad, 0x4a, - 0xa6, 0x64, 0xc6, 0xbe, 0x25, 0x99, 0x9f, 0x49, 0xa5, 0xe7, 0x8d, 0x9a, 0x97, 0xb0, 0xd9, 0xf3, 0x67, 0x3a, 0xc5, - 0x95, 0x49, 0x36, 0x0a, 0xdd, 0xff, 0xd1, 0x8d, 0x58, 0x7a, 0x8f, 0x0e, 0x8c, 0x39, 0xb8, 0x7a, 0x4a, 0xcf, 0x43, - 0x5b, 0x0d, 0xef, 0xe9, 0xfb, 0x34, 0x5f, 0x89, 0xcf, 0x7f, 0xe9, 0x86, 0x8d, 0x45, 0x9d, 0xf4, 0x7e, 0xd5, 0x29, - 0x24, 0x0e, 0x6e, 0x45, 0x3b, 0x21, 0x27, 0xf9, 0x09, 0x41, 0x7d, 0xd9, 0xa0, 0xda, 0x00, 0x6c, 0x58, 0xa5, 0xa2, - 0x2e, 0x06, 0x5a, 0x8e, 0x28, 0x5b, 0x0f, 0xfa, 0xda, 0xb4, 0x3d, 0xdd, 0x5f, 0x35, 0xab, 0x6d, 0xeb, 0x65, 0x09, - 0x53, 0x96, 0x4e, 0xdb, 0x85, 0x3a, 0x6d, 0xc9, 0x33, 0xfd, 0x52, 0x17, 0x73, 0xda, 0xc4, 0xc1, 0xcf, 0x95, 0xbf, - 0x87, 0xdb, 0xda, 0x1d, 0xbb, 0xd6, 0xc8, 0x06, 0xc7, 0xed, 0x31, 0xc7, 0xd9, 0x05, 0x22, 0x5a, 0x16, 0xda, 0x1e, - 0xaa, 0x16, 0xa9, 0x3b, 0xf5, 0x9d, 0x09, 0xbb, 0x09, 0x20, 0x54, 0xec, 0x5d, 0x92, 0x3c, 0x7c, 0x96, 0xd9, 0xe8, - 0xc0, 0x6e, 0xb2, 0x52, 0x9b, 0xf8, 0xfa, 0x94, 0x99, 0x96, 0xa2, 0xab, 0x33, 0x6a, 0xe0, 0xce, 0x69, 0x3e, 0x39, - 0x68, 0x26, 0xca, 0x6d, 0x13, 0xd9, 0xf3, 0x91, 0x3a, 0x41, 0x5d, 0xa0, 0x12, 0x35, 0xad, 0x53, 0xcb, 0x08, 0x0a, - 0x37, 0xc9, 0xde, 0x78, 0xa4, 0x9b, 0xb1, 0x62, 0xfb, 0x15, 0xa8, 0x9b, 0xb3, 0x1b, 0x77, 0x60, 0xc8, 0xaa, 0x15, - 0x6a, 0x67, 0x04, 0xc7, 0xd0, 0x7c, 0x2d, 0x29, 0x12, 0x86, 0x95, 0x80, 0x1d, 0x38, 0x52, 0xa4, 0x20, 0xb8, 0xdb, - 0xea, 0xfc, 0x0d, 0x94, 0x1e, 0x51, 0xa2, 0xc2, 0x2b, 0x2a, 0xa7, 0x74, 0x83, 0x5d, 0x3d, 0x17, 0x20, 0x60, 0x0a, - 0x28, 0x36, 0x32, 0x8b, 0xca, 0x76, 0xab, 0x42, 0xf6, 0x72, 0x3d, 0xb8, 0xbc, 0xf9, 0x40, 0xdd, 0xd8, 0xf4, 0xdd, - 0x97, 0x34, 0xe8, 0x84, 0xe2, 0xc1, 0x07, 0xec, 0xb1, 0x15, 0xf1, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, 0xea, 0x4b, - 0xe4, 0x83, 0x69, 0xff, 0xee, 0x97, 0xc3, 0x2a, 0xe0, 0xea, 0x77, 0xba, 0x91, 0x43, 0xc5, 0xbc, 0x1b, 0x10, 0xa2, - 0x90, 0x01, 0x19, 0xd1, 0xd6, 0x7f, 0xb6, 0xf4, 0xb5, 0x44, 0x3b, 0xda, 0xda, 0x27, 0x01, 0xd9, 0x43, 0x6f, 0xb6, - 0xc1, 0x39, 0x19, 0x2c, 0x00, 0x0c, 0xfe, 0x0b, 0xcd, 0x37, 0x89, 0xa5, 0x84, 0x56, 0x45, 0xf0, 0x71, 0x68, 0x66, - 0x6f, 0xcc, 0xa8, 0xfa, 0x34, 0x03, 0xe8, 0x9e, 0x84, 0x50, 0xe6, 0x6c, 0xaf, 0x37, 0x04, 0x75, 0xec, 0x17, 0x8a, - 0xd5, 0x67, 0x70, 0xc3, 0xff, 0xe8, 0xab, 0x5f, 0xe0, 0x5e, 0x45, 0x51, 0x13, 0xbb, 0xa6, 0x68, 0x1c, 0x4a, 0xb8, - 0xc9, 0x85, 0xf5, 0x2e, 0x09, 0x02, 0x8d, 0xfe, 0x2b, 0x35, 0xc5, 0xc8, 0x02, 0xba, 0xb3, 0x85, 0xc0, 0x5a, 0xc1, - 0x48, 0x4a, 0x44, 0x28, 0x65, 0xae, 0x33, 0x8b, 0xb7, 0xec, 0xea, 0x97, 0xb6, 0xc4, 0xea, 0xcd, 0x3b, 0x06, 0x67, - 0xc5, 0xf2, 0xed, 0x79, 0x27, 0x33, 0x2f, 0xb4, 0x2c, 0x10, 0xd5, 0x14, 0xd2, 0x97, 0xbc, 0x85, 0xd1, 0xca, 0x63, - 0xe3, 0x82, 0x69, 0x7d, 0xff, 0x52, 0xaa, 0x6a, 0xe7, 0x45, 0xa8, 0xab, 0x97, 0xd1, 0xc4, 0xc2, 0xad, 0xa5, 0x0c, - 0xec, 0x4a, 0x44, 0xb0, 0x4d, 0x11, 0xc0, 0xe4, 0x6b, 0x20, 0x44, 0x3c, 0xa8, 0x82, 0x52, 0x3d, 0x61, 0x61, 0xdf, - 0xa0, 0xe0, 0xdd, 0x5d, 0x74, 0x8d, 0x6f, 0x81, 0x88, 0xde, 0x96, 0xc0, 0x30, 0x3c, 0x2e, 0x9e, 0x4a, 0x79, 0x53, - 0x12, 0xb0, 0x5d, 0x85, 0xef, 0x45, 0x94, 0x9b, 0xb5, 0x1f, 0x8d, 0x68, 0xab, 0x0d, 0x12, 0xa5, 0x45, 0xf6, 0x1a, - 0x4f, 0x9b, 0xfc, 0xaa, 0x79, 0x67, 0xf7, 0x36, 0x7d, 0xd5, 0x86, 0x30, 0x3c, 0x45, 0x3a, 0x25, 0x6c, 0xbb, 0x48, - 0xc4, 0xfd, 0x1f, 0x67, 0x8a, 0x16, 0xfb, 0x6c, 0x9c, 0x4b, 0xb5, 0xeb, 0x3b, 0x04, 0x8c, 0x9f, 0xd5, 0x43, 0x77, - 0xfd, 0xa9, 0x1c, 0xeb, 0x6f, 0x46, 0x1d, 0x54, 0xe0, 0xe1, 0x6e, 0x96, 0x7e, 0x8d, 0xc6, 0xf7, 0x5a, 0x7c, 0xd9, - 0xfb, 0x8a, 0x00, 0xbc, 0x78, 0x13, 0xef, 0xa2, 0xfd, 0x44, 0x27, 0x70, 0x8c, 0xb0, 0x6d, 0x93, 0x80, 0xb5, 0x8f, - 0x5f, 0x91, 0x14, 0xe4, 0xc8, 0xef, 0x40, 0xfe, 0xb7, 0xc6, 0xdc, 0xf0, 0x1d, 0x15, 0x73, 0x4b, 0x29, 0x5d, 0x25, - 0x4f, 0x4e, 0x61, 0x7b, 0xcc, 0x02, 0xc4, 0x11, 0x38, 0x78, 0x3f, 0xb1, 0x27, 0x7f, 0xba, 0xa0, 0x6e, 0x46, 0x47, - 0x8a, 0x43, 0xb1, 0x9a, 0x9f, 0x1a, 0x1a, 0x29, 0x0f, 0xd3, 0x11, 0x41, 0x4d, 0x68, 0x31, 0x16, 0x8e, 0x2e, 0x49, - 0x00, 0x81, 0x09, 0x50, 0xa7, 0xc8, 0xa2, 0xaf, 0x47, 0x6e, 0xc5, 0xa4, 0x67, 0x5b, 0xb9, 0x74, 0xed, 0x13, 0xde, - 0xd4, 0x9e, 0x81, 0x5b, 0xab, 0xc6, 0x68, 0x75, 0x67, 0x47, 0x65, 0xa5, 0xc7, 0xe4, 0x74, 0x6e, 0xae, 0xc4, 0x72, - 0x4d, 0x71, 0x1f, 0x8e, 0x76, 0x0f, 0xea, 0x1d, 0x51, 0x04, 0x62, 0x4c, 0x94, 0xd9, 0x99, 0x9c, 0xed, 0x37, 0x7a, - 0x00, 0xdf, 0x52, 0x50, 0x2f, 0x98, 0x0f, 0xb8, 0xdc, 0x5b, 0xde, 0x91, 0x79, 0xe0, 0x95, 0x09, 0x47, 0x4d, 0xb9, - 0xf6, 0x66, 0x23, 0xb3, 0x44, 0x4d, 0x78, 0xfe, 0xbf, 0x1a, 0x6a, 0x48, 0x2c, 0x20, 0x93, 0xb1, 0x6f, 0xdf, 0x55, - 0xe4, 0xd3, 0x2c, 0x74, 0xb8, 0xc2, 0x01, 0xd4, 0x71, 0x6a, 0x6a, 0xc0, 0x0d, 0x78, 0xf8, 0x41, 0x42, 0x2b, 0xdf, - 0x25, 0xd4, 0xf8, 0xe7, 0x7e, 0xc6, 0xbe, 0x77, 0x9b, 0x6d, 0x9e, 0xd3, 0x2b, 0xc0, 0xd2, 0xe8, 0xfe, 0x36, 0xe9, - 0x8b, 0x83, 0x06, 0x0c, 0x55, 0x27, 0xaf, 0x16, 0xd3, 0xc6, 0x76, 0xf3, 0xaf, 0xcf, 0xe4, 0xbc, 0xa3, 0xf7, 0xa5, - 0xe7, 0xb6, 0xb9, 0x1f, 0x77, 0x75, 0x57, 0xb1, 0x6e, 0x5e, 0x34, 0xc4, 0x8a, 0x22, 0x2e, 0x3e, 0xac, 0x77, 0xb7, - 0x73, 0xbb, 0x75, 0x24, 0xc5, 0x3b, 0x05, 0x77, 0x4a, 0x4a, 0x75, 0xcf, 0x8c, 0xa1, 0x27, 0xec, 0xbd, 0x6c, 0xdc, - 0xff, 0x72, 0xe9, 0xac, 0xbb, 0xe2, 0xae, 0x72, 0xf0, 0xc6, 0xa4, 0x8b, 0x16, 0xec, 0xfa, 0x45, 0xaf, 0xdf, 0x7c, - 0xa1, 0x7e, 0x5a, 0xd1, 0x2d, 0x4a, 0x28, 0xa0, 0x0d, 0x2d, 0x5f, 0x10, 0xef, 0x84, 0xca, 0x46, 0x77, 0xc2, 0xc9, - 0xd3, 0xe2, 0xbe, 0xfa, 0x4e, 0xc6, 0xe0, 0x2f, 0x90, 0xaf, 0xe6, 0x51, 0xf0, 0xf1, 0x9f, 0xc4, 0x2f, 0x2f, 0x8b, - 0xfa, 0xcd, 0x8b, 0xd7, 0x5e, 0x0b, 0x80, 0x69, 0x9d, 0x1f, 0xf1, 0xe2, 0x7b, 0x4b, 0xe7, 0x41, 0x92, 0x3f, 0x62, - 0x3c, 0xfb, 0x28, 0x4b, 0x80, 0x04, 0x58, 0xa5, 0x7a, 0x67, 0x16, 0xc4, 0xe3, 0xfb, 0x30, 0x11, 0x39, 0x03, 0x09, - 0x1b, 0x14, 0x0a, 0xc2, 0xf8, 0x4e, 0x23, 0xc2, 0x7b, 0x14, 0x31, 0x15, 0x5e, 0x76, 0x7d, 0xbf, 0x4a, 0x71, 0xb0, - 0x02, 0xa3, 0x76, 0xfb, 0x2f, 0x26, 0x53, 0x60, 0x4f, 0x1c, 0x4c, 0xd4, 0x15, 0x4e, 0x78, 0xfc, 0xe1, 0xe4, 0xfe, - 0x25, 0x3d, 0x52, 0x55, 0x87, 0x39, 0x32, 0xbe, 0xb6, 0xaa, 0xea, 0xc5, 0xaf, 0xd0, 0xb6, 0x2f, 0x67, 0xa9, 0xb5, - 0x74, 0xd9, 0xab, 0x81, 0x6c, 0xed, 0x6c, 0xa2, 0xba, 0x3b, 0x59, 0x1e, 0x97, 0x1b, 0xc2, 0x10, 0x88, 0x75, 0xee, - 0xf2, 0xc8, 0x25, 0xdb, 0xc7, 0xc2, 0xc5, 0x29, 0xdb, 0xfc, 0xec, 0x59, 0xfa, 0xcb, 0x42, 0x79, 0xca, 0xb7, 0xde, - 0xc2, 0xdb, 0xaf, 0x89, 0x1e, 0xf4, 0x77, 0xd3, 0x26, 0xca, 0x01, 0xd1, 0x81, 0x83, 0xc6, 0xf7, 0xa7, 0xf7, 0xff, - 0xa8, 0x19, 0x52, 0x3d, 0x6b, 0x49, 0x2b, 0x07, 0x7f, 0x48, 0x9c, 0x2d, 0xcd, 0x61, 0x2a, 0x11, 0x24, 0xe3, 0xda, - 0xf4, 0x32, 0x59, 0x7b, 0xd3, 0x76, 0x97, 0x1d, 0x90, 0xb5, 0xe4, 0x14, 0x88, 0x1a, 0xb9, 0xd7, 0x35, 0xdf, 0x42, - 0xa8, 0x93, 0x58, 0xa6, 0xb6, 0x7b, 0x8d, 0x3a, 0x83, 0xb5, 0x04, 0xd0, 0x20, 0xe6, 0x35, 0xfe, 0x37, 0x43, 0x33, - 0xfe, 0xf6, 0xcd, 0x93, 0x83, 0x1b, 0x46, 0x82, 0xa9, 0xf8, 0x28, 0x80, 0xe1, 0x8c, 0xe0, 0x49, 0xbd, 0xbe, 0xf6, - 0x25, 0x06, 0xfa, 0xa1, 0xa4, 0xea, 0xc5, 0xde, 0xcd, 0xce, 0x2b, 0x70, 0x51, 0xda, 0x3f, 0x50, 0x7c, 0x43, 0x9a, - 0x91, 0x5a, 0xd9, 0xab, 0x7b, 0xef, 0xd4, 0x76, 0xd2, 0x6b, 0xc9, 0x82, 0xe6, 0xc0, 0x4b, 0x06, 0xb7, 0x24, 0x67, - 0x60, 0x79, 0x7f, 0x2e, 0x3d, 0xd9, 0x19, 0xf8, 0x44, 0xea, 0x97, 0xfa, 0x4a, 0xdc, 0x2c, 0x09, 0x65, 0x2c, 0x24, - 0xd5, 0xfd, 0x0a, 0x44, 0xaf, 0xff, 0xe8, 0x46, 0x85, 0x86, 0xbd, 0x3a, 0xdb, 0x31, 0x90, 0x46, 0x8c, 0xf6, 0x2e, - 0xb5, 0xde, 0xee, 0xe9, 0x91, 0x31, 0x7d, 0xde, 0xfb, 0xb9, 0xea, 0xdc, 0x91, 0xd9, 0x86, 0x54, 0xff, 0x54, 0xcc, - 0x5a, 0x52, 0x21, 0xdb, 0x8a, 0xed, 0xb4, 0x02, 0x77, 0x1e, 0x4c, 0xde, 0x1d, 0x98, 0xbb, 0x0f, 0x64, 0x0e, 0x63, - 0xad, 0x2b, 0x55, 0x95, 0x1b, 0x5f, 0xc4, 0xd0, 0xef, 0x03, 0xc9, 0x2c, 0xb2, 0x48, 0xaa, 0xc0, 0x16, 0x6a, 0x23, - 0xef, 0xdd, 0xcf, 0xc5, 0xaa, 0xd3, 0x2f, 0x4d, 0x82, 0x74, 0xff, 0x46, 0xe4, 0x9a, 0x19, 0x79, 0xf3, 0xbe, 0xda, - 0x46, 0x30, 0xac, 0xa3, 0x8d, 0x48, 0xa1, 0x9d, 0x2f, 0x19, 0xfe, 0x33, 0x92, 0x77, 0x62, 0xa6, 0x7f, 0x90, 0xce, - 0xac, 0x1f, 0x84, 0xf1, 0x76, 0xbf, 0x40, 0x73, 0xfe, 0xa1, 0x80, 0x67, 0x2f, 0x14, 0x60, 0x01, 0x69, 0xf4, 0x4a, - 0xea, 0x63, 0x4d, 0x50, 0x4e, 0xb8, 0x32, 0x94, 0x6c, 0x94, 0xd7, 0x52, 0x7b, 0x42, 0xfb, 0xa6, 0x64, 0x03, 0x6c, - 0xe2, 0x3a, 0x76, 0xd1, 0xd4, 0xb1, 0xc0, 0x74, 0xb9, 0x7f, 0x71, 0x6c, 0x0f, 0x52, 0xb9, 0x70, 0x01, 0x5f, 0xe8, - 0x02, 0x77, 0x61, 0x38, 0x40, 0x6b, 0x50, 0xff, 0x71, 0xdc, 0x14, 0xff, 0x50, 0x4a, 0x25, 0xb1, 0xc9, 0x42, 0xa9, - 0x50, 0x7b, 0x88, 0x9f, 0x1b, 0xe5, 0x5a, 0x4f, 0x82, 0x6b, 0xa4, 0x08, 0x08, 0x8e, 0x2b, 0x26, 0x71, 0x35, 0xa5, - 0x21, 0xb8, 0x73, 0xf4, 0x99, 0xd7, 0xf2, 0x2b, 0xa1, 0xec, 0xba, 0xc0, 0x67, 0x60, 0x05, 0x18, 0xec, 0x2f, 0xec, - 0x0b, 0x47, 0x17, 0x2d, 0x67, 0xeb, 0xb3, 0x03, 0x27, 0x40, 0x1e, 0x2b, 0x4f, 0x24, 0x61, 0x6b, 0x72, 0xee, 0x4d, - 0x6e, 0xdf, 0x33, 0x85, 0x68, 0x52, 0x44, 0xd5, 0xe3, 0x17, 0xb8, 0x20, 0x2d, 0xa9, 0x64, 0xa5, 0xa0, 0x55, 0xa8, - 0x40, 0xb4, 0xd1, 0xc6, 0xd5, 0xaa, 0xd3, 0xfb, 0xa7, 0x11, 0x9d, 0x97, 0xc6, 0xda, 0x10, 0x43, 0xe0, 0x88, 0xb5, - 0xf5, 0x53, 0x85, 0x8d, 0x37, 0xc9, 0xba, 0xb8, 0xcf, 0x63, 0xfb, 0x35, 0x43, 0x33, 0x12, 0x6f, 0x2a, 0x6f, 0x9b, - 0xe2, 0x61, 0xc1, 0x1b, 0x27, 0x7a, 0xa1, 0x5f, 0xb0, 0x39, 0xe1, 0xf4, 0xd7, 0x75, 0x97, 0xc9, 0xb1, 0xfa, 0xd8, - 0x43, 0x48, 0xb9, 0x50, 0xa3, 0x42, 0xa4, 0xe7, 0xed, 0xd8, 0x5c, 0xb9, 0xc7, 0xd2, 0xe8, 0x1c, 0xd7, 0xa4, 0x24, - 0xdb, 0xcd, 0xf0, 0xd2, 0xa6, 0x82, 0x38, 0x71, 0x77, 0x3f, 0xa8, 0x05, 0xef, 0xb6, 0x21, 0xad, 0x69, 0xfd, 0xfa, - 0x95, 0x3f, 0xbf, 0x71, 0x56, 0x52, 0x2c, 0x92, 0x45, 0xd4, 0x6c, 0xd7, 0x4f, 0xec, 0xf2, 0x67, 0xd2, 0xfb, 0x2c, - 0xbc, 0xc9, 0xda, 0xbf, 0x1e, 0xe1, 0x4b, 0xae, 0x4d, 0x29, 0x92, 0x29, 0xca, 0xdd, 0xbf, 0x49, 0x90, 0x10, 0x19, - 0xfe, 0x42, 0x00, 0xc6, 0xba, 0xa7, 0x55, 0xf3, 0xd1, 0x59, 0x89, 0xb3, 0x0f, 0xbc, 0x06, 0xe0, 0xa2, 0xe0, 0x0b, - 0xa3, 0x34, 0x5a, 0xb1, 0x18, 0x1c, 0x07, 0x9a, 0xca, 0x07, 0x5c, 0xff, 0x30, 0xa3, 0x42, 0x29, 0x36, 0xd4, 0xf7, - 0x13, 0xa7, 0x65, 0x42, 0x40, 0x23, 0x9d, 0x39, 0xb7, 0x51, 0x2b, 0xf0, 0xed, 0x71, 0x3d, 0x1c, 0xe4, 0x7a, 0xda, - 0x21, 0xf8, 0x34, 0x4d, 0x7e, 0x73, 0xc8, 0xe6, 0xf2, 0xa5, 0xd9, 0xef, 0xa5, 0x1b, 0x26, 0x2f, 0x36, 0xf4, 0x56, - 0xd8, 0x08, 0x03, 0x51, 0x8d, 0x2a, 0x68, 0x24, 0x24, 0x61, 0xa7, 0xbd, 0x26, 0x38, 0x9a, 0xd2, 0x62, 0x2a, 0xfc, - 0xa4, 0xae, 0x4f, 0xc6, 0xd7, 0xa2, 0x31, 0xb5, 0x8e, 0x1b, 0xf1, 0x71, 0x39, 0x9f, 0x01, 0xc8, 0x42, 0xc5, 0x73, - 0x4b, 0xa2, 0xcf, 0x28, 0x38, 0x1e, 0x54, 0x59, 0x31, 0xd2, 0x0e, 0x43, 0x11, 0x72, 0x63, 0xa6, 0x71, 0x1c, 0x17, - 0xfe, 0x82, 0xd3, 0x2a, 0x8d, 0x31, 0xaa, 0xbc, 0xb6, 0xe9, 0xa5, 0xf9, 0x3a, 0xa1, 0x3a, 0x97, 0xf1, 0xd7, 0x93, - 0xef, 0xb9, 0x92, 0x29, 0x40, 0x1e, 0x69, 0xbc, 0x61, 0xef, 0x78, 0x06, 0xbc, 0x99, 0xc1, 0x25, 0x01, 0x48, 0x27, - 0xeb, 0x74, 0x6e, 0xc3, 0x23, 0xd2, 0x09, 0x38, 0x3b, 0xaa, 0xf4, 0xe4, 0xca, 0x4a, 0x32, 0xd6, 0x1d, 0xc6, 0x7c, - 0xc9, 0xc6, 0xa5, 0x8d, 0xb7, 0x53, 0x66, 0x9d, 0xa5, 0xcb, 0x94, 0x88, 0x07, 0x95, 0xa4, 0xf1, 0x32, 0xc0, 0x61, - 0x9a, 0x97, 0x6f, 0xd3, 0x5a, 0x7e, 0xcf, 0x70, 0x93, 0x21, 0x15, 0x4d, 0x56, 0x69, 0x76, 0x01, 0x20, 0xc0, 0xb6, - 0x5d, 0x74, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x8e, 0xec, 0x1d, 0xb5, 0x3b, 0xb3, 0xc7, 0x41, - 0x80, 0x77, 0x75, 0x4b, 0x76, 0x29, 0x13, 0xdf, 0xc4, 0xd0, 0xf5, 0xab, 0x96, 0x00, 0xb8, 0x01, 0x76, 0x59, 0x12, - 0x75, 0x26, 0x73, 0x81, 0x55, 0x79, 0xcc, 0xc3, 0x54, 0xa6, 0x98, 0xaa, 0x05, 0x5b, 0x82, 0x5c, 0x40, 0xb9, 0xbc, - 0x71, 0xb9, 0xae, 0xaf, 0x02, 0x40, 0xd1, 0xc3, 0x38, 0x2a, 0x26, 0x9e, 0x1b, 0xe9, 0x85, 0xbd, 0xaa, 0x40, 0x61, - 0x7c, 0x6a, 0x4b, 0x72, 0x72, 0x29, 0xfd, 0xc9, 0x64, 0xdb, 0x6a, 0xb6, 0xdb, 0xc9, 0x45, 0x42, 0xd7, 0x92, 0xd8, - 0x42, 0x2e, 0xa9, 0xdb, 0xbb, 0x3a, 0xc4, 0xf2, 0x5e, 0x16, 0x30, 0xda, 0x46, 0x67, 0xdd, 0x55, 0x1f, 0xd6, 0x94, - 0x08, 0x27, 0xcb, 0xc6, 0x7c, 0x27, 0xd6, 0x17, 0xa9, 0x35, 0x06, 0x1a, 0x67, 0xde, 0xfa, 0x25, 0x43, 0xcd, 0x04, - 0x9f, 0x54, 0x2f, 0x96, 0xc5, 0x7c, 0xe6, 0x82, 0xa8, 0xd8, 0x2c, 0xee, 0x5f, 0x6d, 0xba, 0xe0, 0x74, 0x4d, 0xda, - 0x0d, 0xa4, 0x1b, 0x58, 0x34, 0xdc, 0x45, 0x84, 0x45, 0xfb, 0x23, 0x9a, 0x15, 0xcb, 0x0a, 0xa3, 0xc7, 0x4f, 0xe6, - 0xd8, 0x53, 0xc1, 0xb1, 0xb4, 0x40, 0xc2, 0x11, 0xbf, 0x79, 0x8d, 0xd5, 0xa2, 0x6e, 0x65, 0x4c, 0x34, 0x96, 0xa6, - 0xfe, 0x61, 0x21, 0x6d, 0xfb, 0x1a, 0xa8, 0xfe, 0x19, 0x7c, 0x12, 0xdb, 0x19, 0x83, 0xbc, 0xb1, 0x0d, 0x6c, 0xe5, - 0x80, 0x3a, 0x09, 0xa5, 0x27, 0x25, 0xe5, 0x6e, 0x2e, 0x50, 0xaa, 0x34, 0xcd, 0x28, 0xf6, 0xbc, 0x4e, 0x34, 0x5d, - 0xd7, 0x08, 0x27, 0x19, 0x39, 0xd1, 0xe7, 0x8d, 0x82, 0xbc, 0xdd, 0xe6, 0xb2, 0x2f, 0x0d, 0x9c, 0x75, 0xe8, 0x36, - 0x9c, 0xc9, 0x28, 0x69, 0x08, 0x09, 0xda, 0x10, 0x66, 0x6d, 0xb2, 0xd5, 0x22, 0xb4, 0x0d, 0x69, 0x51, 0xf0, 0xc3, - 0xee, 0x1b, 0xcc, 0x23, 0xe8, 0xe9, 0x94, 0xf1, 0x87, 0xd3, 0x6f, 0x2e, 0x1f, 0xee, 0x6c, 0x32, 0x27, 0x02, 0x2d, - 0x3a, 0xcf, 0xa7, 0x87, 0xe2, 0x45, 0x81, 0x20, 0x22, 0x68, 0x0e, 0x6f, 0x09, 0x4e, 0x3e, 0x26, 0xf4, 0x5a, 0xf5, - 0x16, 0x75, 0xf8, 0xc4, 0x83, 0xef, 0xda, 0x3e, 0x21, 0x0e, 0x46, 0x6f, 0xda, 0xf2, 0x28, 0xcd, 0x33, 0x09, 0xf5, - 0xd4, 0x15, 0x03, 0x57, 0x95, 0x8c, 0x1c, 0xbf, 0x59, 0x5f, 0x13, 0x62, 0x45, 0xc0, 0x18, 0x52, 0xbd, 0xc5, 0x18, - 0x1c, 0x32, 0xe6, 0xe5, 0x38, 0x18, 0xd7, 0x6c, 0x8a, 0x2c, 0x6b, 0x43, 0xd9, 0x5d, 0xf9, 0xe9, 0x5c, 0x8c, 0x56, - 0xa1, 0x6c, 0x24, 0x9e, 0xe5, 0x51, 0x8a, 0x71, 0x0f, 0xab, 0x9e, 0x46, 0xc4, 0x96, 0x35, 0x75, 0x3e, 0x21, 0xf4, - 0xd9, 0x83, 0x98, 0xb3, 0x0b, 0x53, 0x16, 0x7a, 0x89, 0xa1, 0x2a, 0xbd, 0x0d, 0x98, 0xbe, 0x15, 0x5b, 0x24, 0xda, - 0x8e, 0x44, 0xa2, 0x98, 0xe0, 0x84, 0x38, 0x6c, 0x45, 0x8e, 0x07, 0xab, 0xbd, 0x83, 0xc9, 0xe8, 0x33, 0x4e, 0x0b, - 0xeb, 0x91, 0x98, 0xfd, 0x31, 0x4e, 0x09, 0x03, 0xce, 0xed, 0x4e, 0x4c, 0x79, 0x37, 0x22, 0x1e, 0x7d, 0x20, 0xd7, - 0x6f, 0xa5, 0x45, 0xb0, 0xc7, 0x13, 0x39, 0x52, 0x15, 0xc5, 0x0a, 0x6e, 0x1f, 0x85, 0x0c, 0x4f, 0x5d, 0x38, 0x9a, - 0xb3, 0x61, 0x3c, 0x10, 0x51, 0x6d, 0x5c, 0xd8, 0xb4, 0x96, 0x81, 0x89, 0xc6, 0x8c, 0xd5, 0xe8, 0xe0, 0x02, 0x5e, - 0xe4, 0xfd, 0xef, 0x0b, 0xa6, 0x69, 0x2d, 0x1f, 0x34, 0x83, 0xfe, 0xbb, 0x32, 0xdb, 0x2c, 0x1f, 0xde, 0xd7, 0xcb, - 0x87, 0xfd, 0x44, 0xce, 0xdc, 0xef, 0xaa, 0xb7, 0x9f, 0xfe, 0x69, 0x21, 0x07, 0xf9, 0xb7, 0xbc, 0x0a, 0x83, 0xab, - 0xad, 0xe3, 0x89, 0x1b, 0x5c, 0x4d, 0x5f, 0x3b, 0xe4, 0xb3, 0x2b, 0x6a, 0xdb, 0x70, 0x91, 0x66, 0x3c, 0xb6, 0x3c, - 0x59, 0x83, 0x15, 0x59, 0x54, 0x2b, 0x58, 0x3b, 0xc9, 0x13, 0xdd, 0xf5, 0xd9, 0x25, 0xb8, 0x27, 0x2f, 0x26, 0x32, - 0x65, 0xf6, 0x01, 0xf8, 0x50, 0x22, 0x7f, 0x62, 0xb7, 0xf0, 0xdf, 0x51, 0x05, 0xdd, 0x41, 0xc1, 0x50, 0x6b, 0x49, - 0xd8, 0xe6, 0x0b, 0x25, 0xbf, 0x96, 0x08, 0x7c, 0x51, 0xbd, 0x85, 0x75, 0x43, 0xca, 0x9f, 0x58, 0x6e, 0x4f, 0xa9, - 0x13, 0x4d, 0xa3, 0x3b, 0x79, 0x1a, 0x7e, 0xe9, 0x92, 0xe0, 0xb2, 0x4d, 0xfd, 0xbf, 0xbe, 0xff, 0xaf, 0xd7, 0x09, - 0x26, 0x21, 0xef, 0x20, 0x1e, 0x2e, 0x5f, 0x0c, 0xae, 0x3a, 0xd2, 0xf9, 0x66, 0x1f, 0xbe, 0x89, 0x86, 0xe5, 0x61, - 0xfd, 0xbc, 0xf7, 0x17, 0x5d, 0x7e, 0x6f, 0xa2, 0xef, 0x60, 0xdb, 0xb4, 0xa1, 0xb4, 0x3d, 0xa4, 0x01, 0x4b, 0x8d, - 0x0b, 0x9a, 0x55, 0xf1, 0xd8, 0x14, 0x16, 0xab, 0x7b, 0x7b, 0x4d, 0x9e, 0x72, 0x6c, 0xfd, 0x87, 0xa0, 0x83, 0xcc, - 0xf1, 0x68, 0xb8, 0x2c, 0xcf, 0xd2, 0x2c, 0xd6, 0x31, 0xe8, 0xee, 0x9d, 0x50, 0x7b, 0xb1, 0x18, 0x5a, 0x1b, 0xb5, - 0x45, 0x92, 0x48, 0xe3, 0x5d, 0x5d, 0x6c, 0xea, 0x21, 0x74, 0x69, 0xeb, 0x34, 0x6d, 0x12, 0xc7, 0x38, 0xd9, 0x96, - 0xbd, 0x06, 0xe8, 0x95, 0xbe, 0xe8, 0x2f, 0x58, 0x7a, 0x6d, 0xbf, 0xd6, 0x47, 0x8c, 0x9b, 0x0d, 0xbc, 0x3f, 0x3a, - 0x65, 0xe2, 0xe2, 0xd0, 0xd8, 0xf9, 0x16, 0x27, 0x0e, 0x7b, 0x7e, 0x8d, 0x4b, 0xaa, 0xa9, 0x97, 0x48, 0x1b, 0xc6, - 0x6a, 0x70, 0x62, 0xe9, 0x5f, 0xdb, 0x58, 0x3c, 0x48, 0x8e, 0x48, 0x65, 0x27, 0x33, 0xf5, 0x72, 0xb4, 0xf0, 0xb7, - 0xae, 0xd6, 0xf5, 0x87, 0xf8, 0xe6, 0x1f, 0x88, 0x9d, 0xa8, 0x9d, 0x5e, 0x34, 0x8a, 0x0c, 0x21, 0xd3, 0x53, 0xfc, - 0x8b, 0x5b, 0x28, 0xc3, 0x69, 0xa2, 0xb3, 0x51, 0xee, 0xed, 0x9d, 0x23, 0x3f, 0x24, 0xbc, 0x71, 0xe7, 0x72, 0x59, - 0x61, 0x60, 0xda, 0x01, 0x36, 0x50, 0x41, 0xc6, 0x81, 0xa5, 0xf8, 0x09, 0x66, 0x97, 0x21, 0xca, 0x6e, 0x99, 0x11, - 0x2f, 0x6d, 0xa7, 0xd2, 0x18, 0xb2, 0xf3, 0x22, 0x77, 0xf1, 0x98, 0x38, 0x36, 0x52, 0x1b, 0x9f, 0x14, 0x10, 0x8e, - 0xf5, 0x61, 0xc8, 0xa6, 0xdb, 0x29, 0x79, 0x6a, 0x39, 0x05, 0x9a, 0x47, 0x7e, 0x8f, 0x88, 0x8e, 0xc6, 0xd6, 0x69, - 0x50, 0x7b, 0x16, 0x1f, 0x2d, 0x17, 0xbe, 0x10, 0x2d, 0xef, 0x02, 0x5b, 0x33, 0xe4, 0x05, 0xab, 0xf7, 0x29, 0x10, - 0xe4, 0x36, 0x6c, 0x7f, 0xcf, 0x97, 0xee, 0xef, 0xac, 0x61, 0x88, 0x79, 0xd0, 0x64, 0xcc, 0xd7, 0x1c, 0x56, 0x84, - 0x4d, 0x59, 0xaf, 0x84, 0x7d, 0x1d, 0x9c, 0xba, 0x1e, 0x4e, 0x52, 0xe9, 0xb9, 0x1a, 0xcd, 0xbb, 0x74, 0xa4, 0x34, - 0x65, 0x8a, 0x36, 0xa6, 0x77, 0x7d, 0x4e, 0x36, 0x47, 0x57, 0x74, 0x3c, 0xeb, 0xa0, 0x14, 0x1e, 0x3e, 0xb5, 0xc1, - 0xa9, 0x7b, 0x46, 0x2f, 0xe4, 0xd7, 0x20, 0xbd, 0xa6, 0x45, 0x15, 0xf4, 0x69, 0xf5, 0x83, 0x17, 0x1f, 0xbf, 0x5b, - 0x25, 0xd0, 0xd8, 0xec, 0x93, 0x0d, 0xc1, 0x59, 0x1e, 0x80, 0x1f, 0x16, 0xf8, 0xff, 0x80, 0x3e, 0x20, 0x66, 0x73, - 0xd3, 0xfe, 0x30, 0x87, 0xf2, 0x4d, 0xf3, 0xf5, 0x42, 0x98, 0x16, 0x9d, 0x1f, 0x7c, 0xa8, 0x1b, 0x04, 0xd8, 0x64, - 0xcf, 0xff, 0x2b, 0xc8, 0x01, 0x82, 0x09, 0xe7, 0xef, 0xe3, 0x7a, 0x38, 0xbf, 0xd1, 0xcf, 0x11, 0x99, 0x3b, 0xdc, - 0xcc, 0xde, 0x4d, 0xbb, 0xf4, 0xaa, 0x2c, 0x36, 0x92, 0xd7, 0xc2, 0xa5, 0x8d, 0xcb, 0x69, 0x1b, 0xd1, 0x92, 0x2d, - 0x12, 0x2c, 0x7c, 0x4b, 0x00, 0x70, 0xa4, 0x7b, 0xa8, 0x6d, 0xf3, 0xbf, 0x28, 0xb6, 0x18, 0x2b, 0xb8, 0x9d, 0xd6, - 0xae, 0xae, 0xfd, 0xd0, 0x76, 0x9b, 0x65, 0x0c, 0x30, 0x7a, 0xb0, 0x33, 0x57, 0x19, 0x65, 0xb9, 0x43, 0x9c, 0x3d, - 0x5c, 0x19, 0xb5, 0xcb, 0x98, 0x70, 0x54, 0xeb, 0x66, 0xb5, 0xa7, 0x02, 0x02, 0x35, 0x62, 0xb1, 0x83, 0xae, 0xcc, - 0x8a, 0x48, 0x3a, 0x7b, 0x6f, 0xc6, 0xf0, 0x6e, 0x83, 0xc5, 0x65, 0xcc, 0x88, 0xe4, 0x8d, 0x81, 0x36, 0xb7, 0xe2, - 0xb1, 0x77, 0x7a, 0xf3, 0xe0, 0xfe, 0xf6, 0xe6, 0xf2, 0xe6, 0x76, 0x89, 0xb7, 0x89, 0x2e, 0xd5, 0x1a, 0x99, 0x53, - 0x7b, 0xbe, 0x96, 0x8c, 0x76, 0xc8, 0xf7, 0xb6, 0xd5, 0xba, 0x84, 0x16, 0x49, 0x80, 0x48, 0x2b, 0x24, 0xab, 0xea, - 0x94, 0x01, 0x0e, 0x9d, 0xa6, 0x61, 0xdb, 0xe3, 0x5e, 0x52, 0x28, 0xd8, 0xca, 0x84, 0xa3, 0x3c, 0x3b, 0xf5, 0x54, - 0x23, 0x73, 0xf6, 0x4c, 0x70, 0x5d, 0x2c, 0x24, 0x22, 0xcf, 0xd7, 0x9c, 0x2c, 0x1e, 0x01, 0xcc, 0x9c, 0xdf, 0x4f, - 0xf3, 0x14, 0x97, 0x38, 0x6c, 0xaa, 0x51, 0x46, 0x5f, 0x6f, 0x09, 0xa1, 0xa1, 0x78, 0x39, 0x14, 0xf8, 0x7a, 0xc2, - 0xf5, 0x5d, 0xa4, 0x23, 0x78, 0x42, 0xc7, 0x49, 0xf2, 0x4b, 0x43, 0x66, 0xdf, 0x6f, 0x9a, 0xc9, 0x36, 0xea, 0x8a, - 0xbe, 0x6e, 0xc9, 0x5f, 0x4f, 0xc6, 0x69, 0x6d, 0x70, 0xe9, 0xf8, 0x6f, 0xa0, 0x7b, 0x41, 0x8c, 0x83, 0x85, 0x33, - 0x88, 0xa3, 0xf0, 0x2b, 0xb6, 0x20, 0x2f, 0x3a, 0xef, 0xf9, 0x73, 0x02, 0x70, 0xb9, 0x5b, 0x06, 0x17, 0x26, 0x96, - 0x79, 0xac, 0xcb, 0x18, 0xd9, 0xc9, 0x42, 0x4e, 0x8d, 0xda, 0x57, 0x44, 0xdb, 0x9a, 0x09, 0xec, 0x47, 0x7c, 0x79, - 0x9c, 0x4a, 0x5c, 0x9b, 0x31, 0x8b, 0x8d, 0x18, 0xbc, 0xa9, 0x3c, 0x28, 0x36, 0x98, 0x85, 0xe7, 0xfb, 0xd6, 0x10, - 0x52, 0x6b, 0xd2, 0x61, 0xb0, 0x53, 0x5e, 0xc4, 0x36, 0x70, 0xca, 0x2e, 0x6e, 0xc7, 0x5a, 0x8c, 0x5f, 0xd7, 0x78, - 0xc5, 0x58, 0x47, 0x2d, 0x38, 0xce, 0x7b, 0xcb, 0x61, 0x9b, 0x60, 0x40, 0xff, 0xb1, 0x13, 0x34, 0xf3, 0xca, 0x9d, - 0x6c, 0x1d, 0x10, 0xe4, 0x6c, 0xc8, 0x12, 0x41, 0x0d, 0xbf, 0x26, 0x9b, 0x36, 0x96, 0x17, 0x9d, 0xe3, 0xfb, 0x8c, - 0x69, 0x47, 0xfb, 0x2c, 0x72, 0x11, 0x25, 0xe3, 0x57, 0x12, 0xa4, 0x73, 0x65, 0x37, 0x72, 0x77, 0x23, 0xf2, 0xa0, - 0x4d, 0x49, 0xe8, 0xad, 0x3d, 0x03, 0x37, 0x3c, 0x37, 0x5f, 0xa9, 0x9a, 0xa3, 0x2c, 0x26, 0x02, 0x83, 0x22, 0x8c, - 0x84, 0xf5, 0x57, 0xff, 0x2b, 0x70, 0x50, 0x77, 0x7c, 0x67, 0xbd, 0xa0, 0xe9, 0x01, 0xbb, 0x1b, 0x75, 0x1d, 0x4a, - 0xab, 0x04, 0x05, 0x11, 0x32, 0x17, 0x86, 0x49, 0xdc, 0xbf, 0xef, 0xde, 0xdd, 0xfd, 0xfe, 0x58, 0x94, 0x5d, 0xdd, - 0x2d, 0xf6, 0x63, 0x4b, 0x3e, 0x9b, 0xb1, 0x91, 0xf9, 0x6a, 0xf0, 0x81, 0x8e, 0x49, 0xb7, 0x40, 0xfe, 0x21, 0xb3, - 0xe7, 0x61, 0x9b, 0x41, 0x23, 0xd1, 0xb5, 0x43, 0x32, 0x20, 0x07, 0x3a, 0xe4, 0x93, 0x0d, 0x3c, 0x97, 0x47, 0xdb, - 0xbc, 0xbb, 0xbc, 0xfe, 0x73, 0xb9, 0xf7, 0xa1, 0x2b, 0xea, 0x83, 0xc5, 0x9a, 0x59, 0xfe, 0xce, 0xc9, 0x22, 0x3b, - 0x70, 0xdb, 0xcd, 0x97, 0xe1, 0x14, 0xaf, 0x66, 0xcb, 0x7f, 0xf0, 0xff, 0xdb, 0xe9, 0xc2, 0x9b, 0x3d, 0xe9, 0x44, - 0xe3, 0x98, 0xe3, 0x96, 0xf7, 0xec, 0x4c, 0xbf, 0x6b, 0x33, 0x13, 0xd2, 0x83, 0x51, 0x34, 0xdb, 0x25, 0x9d, 0xc0, - 0xa8, 0x2e, 0x79, 0xb8, 0xb1, 0x4d, 0x29, 0x53, 0x26, 0x33, 0xd2, 0x42, 0x25, 0x73, 0x2b, 0xd4, 0xb9, 0xa0, 0x48, - 0xf3, 0x85, 0x01, 0x12, 0x75, 0x9b, 0xd3, 0xda, 0x95, 0x38, 0xcd, 0xfb, 0xe6, 0xd8, 0xce, 0xc8, 0x16, 0x25, 0xa0, - 0x4d, 0x99, 0x13, 0x9a, 0x4f, 0x9a, 0x42, 0xdd, 0xdd, 0xce, 0x74, 0x46, 0x6f, 0x93, 0x56, 0x75, 0xda, 0xd7, 0x77, - 0xfd, 0x67, 0x6b, 0xe4, 0x3d, 0x4d, 0x5a, 0xdb, 0x82, 0x74, 0x46, 0x72, 0x6a, 0x3a, 0x9f, 0x06, 0xca, 0xd0, 0x16, - 0x1e, 0x67, 0xbe, 0xf5, 0x22, 0x60, 0x4d, 0x96, 0xcc, 0xa6, 0xe8, 0x6d, 0xa9, 0xa8, 0x5b, 0xec, 0xd9, 0xbd, 0x93, - 0xc9, 0xda, 0xde, 0x1e, 0x10, 0x99, 0x62, 0x58, 0x7b, 0x44, 0xd8, 0x2e, 0xa2, 0x77, 0x00, 0xc7, 0x7d, 0xd2, 0x73, - 0xf8, 0xd4, 0xc8, 0xd7, 0x45, 0xf0, 0xa8, 0x94, 0x36, 0x3f, 0x38, 0x7b, 0xd1, 0x1d, 0x1b, 0x8c, 0x97, 0x0e, 0xb7, - 0xa0, 0xe6, 0xba, 0x6c, 0xba, 0xc6, 0xdd, 0xfd, 0xdf, 0xfe, 0xb6, 0xb5, 0xf0, 0x07, 0x8e, 0x0f, 0x32, 0xbb, 0xa1, - 0xbb, 0xb7, 0xfc, 0xa2, 0x8b, 0xb9, 0xf8, 0xb2, 0x9f, 0x66, 0x67, 0x46, 0xb9, 0x29, 0xc8, 0x4e, 0x45, 0xda, 0x63, - 0x12, 0x15, 0x03, 0xd8, 0xd3, 0x4c, 0x96, 0x64, 0x40, 0x0d, 0xab, 0x57, 0xdf, 0xd2, 0xa9, 0x3b, 0x35, 0x67, 0x6a, - 0xcf, 0x34, 0xf6, 0xb9, 0xf0, 0x88, 0xdd, 0x17, 0x6b, 0xd7, 0x69, 0x6b, 0x98, 0x82, 0xd3, 0x8d, 0x2f, 0xfe, 0xf8, - 0xcb, 0x86, 0x40, 0x8d, 0x51, 0xae, 0xf9, 0xaf, 0xb5, 0x03, 0x08, 0xde, 0xdf, 0x45, 0x98, 0x0b, 0xc8, 0xac, 0xba, - 0x7a, 0xaa, 0xf7, 0x23, 0xdb, 0xcd, 0x43, 0x11, 0x3b, 0x67, 0xbb, 0x17, 0x4f, 0x01, 0x14, 0x99, 0x25, 0x85, 0x9c, - 0xab, 0x36, 0xf4, 0xd2, 0x78, 0x97, 0x1e, 0xf6, 0xd3, 0x27, 0x98, 0x93, 0x43, 0x98, 0x3b, 0x08, 0x9a, 0xcd, 0x20, - 0x81, 0x14, 0xb9, 0x20, 0x66, 0x3f, 0x07, 0x47, 0x58, 0x23, 0x95, 0xc1, 0x34, 0x32, 0x46, 0xbb, 0xe7, 0xca, 0x58, - 0x30, 0x4f, 0x7b, 0x5f, 0xe9, 0xe2, 0xae, 0x77, 0xa0, 0x3a, 0x7b, 0x48, 0xca, 0xcd, 0xfa, 0x02, 0x23, 0xa0, 0xd3, - 0x83, 0x56, 0x3f, 0xfd, 0x39, 0x85, 0x6b, 0xd8, 0x2b, 0xbb, 0x8d, 0x95, 0xe8, 0x0e, 0x20, 0x07, 0xe2, 0x12, 0x4e, - 0x59, 0x7b, 0x9e, 0xfa, 0x77, 0xbf, 0xfe, 0x1e, 0xf9, 0x8b, 0xf3, 0x72, 0xe5, 0x87, 0x95, 0x6f, 0x6d, 0x61, 0x0b, - 0x94, 0x5e, 0xe3, 0xde, 0x2e, 0x31, 0x8d, 0x63, 0x69, 0xfa, 0x96, 0xf3, 0x89, 0x5e, 0xe1, 0x89, 0x0d, 0x54, 0x22, - 0x3c, 0xe2, 0x4a, 0x79, 0x68, 0xa3, 0xd9, 0xec, 0xfa, 0x6e, 0xee, 0x02, 0xd7, 0xff, 0xc2, 0x17, 0xd6, 0xfa, 0xed, - 0x7b, 0x1c, 0x26, 0x23, 0x82, 0x37, 0xfa, 0xa3, 0x30, 0x31, 0x42, 0xc9, 0xd9, 0xc9, 0xb0, 0xff, 0x30, 0x3a, 0x7a, - 0xe8, 0x3c, 0xfa, 0x19, 0x13, 0xa5, 0x66, 0x7c, 0xe7, 0x0f, 0x73, 0x39, 0x93, 0xe7, 0x52, 0xb1, 0x40, 0x6b, 0x12, - 0x01, 0x51, 0x31, 0x2a, 0x3a, 0x4c, 0x4e, 0xe3, 0x37, 0x94, 0xe7, 0x0d, 0x0b, 0xe2, 0x22, 0x08, 0x8a, 0x2f, 0x50, - 0xf6, 0x67, 0xd7, 0x0f, 0x5c, 0xdd, 0xb0, 0x63, 0x30, 0x43, 0x3d, 0xd1, 0xd0, 0x6a, 0x42, 0x90, 0xb1, 0xb5, 0x52, - 0x05, 0x01, 0x4a, 0x47, 0x42, 0x8a, 0x41, 0xcd, 0xac, 0xe5, 0x31, 0xe9, 0xaf, 0x5b, 0x06, 0xef, 0x8d, 0x8a, 0xe3, - 0x32, 0x5a, 0xb7, 0x6d, 0xd5, 0x70, 0x6d, 0xca, 0x38, 0x7a, 0x01, 0xa6, 0xc3, 0xce, 0x49, 0x06, 0x1a, 0x46, 0xfc, - 0xaf, 0x81, 0xe1, 0x42, 0x56, 0x9b, 0x6e, 0x17, 0x87, 0x76, 0xed, 0xc6, 0x7c, 0x22, 0xd8, 0x5f, 0x36, 0x4c, 0x23, - 0xcf, 0x7b, 0xfc, 0x32, 0xd8, 0x12, 0xef, 0x59, 0xf8, 0x69, 0x1f, 0x94, 0x9d, 0xaf, 0xc1, 0xca, 0xf8, 0xd9, 0x7c, - 0xbe, 0xfb, 0x72, 0xf5, 0x1d, 0x86, 0x34, 0x17, 0x05, 0x62, 0xcd, 0xeb, 0xe7, 0xf8, 0x54, 0xba, 0x1c, 0x27, 0xc2, - 0xfa, 0x44, 0x34, 0x6e, 0xd6, 0x95, 0x0b, 0x3f, 0xf2, 0xb6, 0xc2, 0x7d, 0xfd, 0x06, 0x3b, 0x28, 0x9f, 0x7c, 0xbf, - 0x1b, 0x0b, 0xc1, 0xd3, 0xa6, 0x24, 0xe4, 0x39, 0xd0, 0x5b, 0xb7, 0x5b, 0x45, 0x4b, 0xbf, 0x96, 0x87, 0x66, 0x99, - 0x87, 0xf3, 0xc9, 0x98, 0x80, 0x88, 0xe0, 0x40, 0xce, 0x42, 0xd1, 0xf4, 0x22, 0x4c, 0xba, 0x08, 0x3e, 0x35, 0x72, - 0x8e, 0x38, 0x9c, 0xc6, 0xfd, 0xae, 0x30, 0xfd, 0x4d, 0x9e, 0x74, 0x19, 0xfb, 0xe9, 0xef, 0xdb, 0x75, 0x11, 0xd2, - 0xef, 0x79, 0x36, 0xfb, 0x2f, 0x34, 0x42, 0xfe, 0x36, 0x8a, 0x8d, 0xc7, 0x28, 0x6f, 0x14, 0x95, 0x08, 0x11, 0xed, - 0x92, 0x48, 0x98, 0xcb, 0xfb, 0x55, 0xc2, 0xc7, 0xaf, 0xe8, 0x85, 0x33, 0xc7, 0x40, 0xa3, 0x8b, 0x1e, 0x4f, 0xd8, - 0xd8, 0xfd, 0x79, 0x1a, 0x63, 0x81, 0x35, 0xc3, 0x9f, 0x05, 0x80, 0x74, 0xda, 0xad, 0x00, 0xd1, 0x86, 0x26, 0xc8, - 0x70, 0x5d, 0xe7, 0x1a, 0xd6, 0x33, 0x87, 0xe0, 0xf3, 0x46, 0xc8, 0x0d, 0xf1, 0x1c, 0x82, 0x82, 0x7b, 0x70, 0x60, - 0x89, 0xe2, 0x9f, 0x59, 0x47, 0x3d, 0x77, 0x98, 0x58, 0xd2, 0x21, 0x0d, 0x89, 0x84, 0x2c, 0xd7, 0xdd, 0xab, 0x51, - 0x01, 0x3e, 0x66, 0xb2, 0x16, 0x54, 0x3c, 0x9b, 0x4d, 0x7e, 0x35, 0xbf, 0x13, 0xa5, 0xd7, 0xd1, 0x91, 0x36, 0x79, - 0x37, 0x58, 0x82, 0xce, 0xdf, 0x19, 0x05, 0x40, 0x2f, 0x55, 0x5a, 0x05, 0x66, 0x42, 0xd8, 0xc4, 0x86, 0xef, 0x18, - 0x26, 0xa3, 0xcd, 0x9c, 0xdf, 0x64, 0x36, 0x0b, 0x13, 0xc8, 0x60, 0x68, 0x15, 0x40, 0x96, 0xed, 0x11, 0xee, 0x52, - 0xda, 0x07, 0xd4, 0xbb, 0xb8, 0xec, 0x73, 0xf4, 0x39, 0x8d, 0x24, 0xec, 0x5e, 0xaa, 0x31, 0x41, 0x5c, 0x45, 0x4b, - 0xcc, 0xb1, 0xb5, 0xe4, 0xd0, 0x42, 0xf4, 0x8e, 0xd0, 0x61, 0x77, 0x97, 0x19, 0x6c, 0x95, 0xd8, 0x7f, 0x78, 0xac, - 0x64, 0x0e, 0x9e, 0xa5, 0x67, 0xc2, 0xd6, 0x88, 0x1d, 0x27, 0x0d, 0x17, 0x24, 0x88, 0x58, 0x08, 0x4f, 0xe7, 0x03, - 0x71, 0x46, 0xb5, 0x88, 0xff, 0xa3, 0xe3, 0x04, 0xfa, 0x4a, 0xa2, 0x88, 0xec, 0x46, 0xa7, 0xfd, 0x1c, 0x0a, 0x18, - 0x89, 0x23, 0x18, 0x85, 0x9f, 0xa1, 0xa4, 0xbb, 0x4c, 0x18, 0xa0, 0x5c, 0x48, 0xec, 0xf0, 0x84, 0x94, 0x98, 0x12, - 0x6a, 0xa4, 0x07, 0x09, 0xc9, 0xcb, 0x22, 0x00, 0x75, 0x08, 0xda, 0xa1, 0xf9, 0x2b, 0x43, 0x03, 0x0f, 0x2e, 0x5f, - 0xa1, 0x24, 0x32, 0x39, 0x8f, 0x51, 0x48, 0x72, 0xeb, 0xbc, 0xcb, 0x96, 0xb4, 0xb0, 0xbf, 0xd5, 0x28, 0xaa, 0x22, - 0x59, 0xdd, 0xcb, 0x1a, 0xe1, 0xd9, 0x9a, 0x49, 0xb0, 0x3e, 0xb9, 0x8e, 0xb5, 0x90, 0x93, 0x09, 0x4c, 0x8b, 0xf6, - 0x6f, 0xab, 0xe4, 0x22, 0xff, 0x4a, 0xcf, 0xe6, 0x85, 0xdf, 0x85, 0xae, 0x7a, 0xa9, 0x3f, 0x93, 0x76, 0xd0, 0x99, - 0x05, 0x47, 0x6a, 0x99, 0x8d, 0x3b, 0xe3, 0xf3, 0xa2, 0x1b, 0xd6, 0x5f, 0x26, 0x55, 0x12, 0xbd, 0xf0, 0x6b, 0x68, - 0x56, 0x61, 0x41, 0xf9, 0x0c, 0x62, 0x5e, 0x23, 0x9a, 0x8d, 0x36, 0x8c, 0x14, 0xe0, 0xc5, 0xe7, 0xe5, 0x39, 0x77, - 0xa0, 0x32, 0x2a, 0xcc, 0xe2, 0x52, 0x49, 0xf0, 0xbd, 0x70, 0xec, 0xd0, 0x3e, 0xd3, 0xa6, 0xc8, 0xde, 0x97, 0x40, - 0x27, 0x8f, 0x68, 0x03, 0x06, 0xee, 0x10, 0x6a, 0x52, 0xa0, 0xb3, 0x71, 0xb8, 0x45, 0xed, 0x2b, 0x33, 0xba, 0x2a, - 0x45, 0xd1, 0x3c, 0xcd, 0x18, 0xa4, 0xba, 0x55, 0x0b, 0x19, 0x19, 0xed, 0xa0, 0xcb, 0xe8, 0xa0, 0x84, 0x8f, 0xe5, - 0xac, 0xf0, 0x78, 0xc8, 0x70, 0x61, 0x92, 0x6c, 0x80, 0x4f, 0x8f, 0xfe, 0xef, 0x0f, 0xce, 0xa9, 0xa5, 0xe3, 0x91, - 0xbc, 0x62, 0x76, 0xc4, 0xd2, 0x4c, 0x41, 0xea, 0x72, 0x92, 0x22, 0x75, 0x8b, 0xa9, 0x65, 0x71, 0xb0, 0x1c, 0x55, - 0x44, 0x9d, 0xde, 0x9e, 0x0a, 0x0a, 0x07, 0x06, 0x2d, 0x8c, 0x34, 0x31, 0xdf, 0x2c, 0x59, 0x7b, 0xa5, 0xe8, 0xde, - 0xc9, 0x08, 0x55, 0xaa, 0x1b, 0x5e, 0xb9, 0x6c, 0xf0, 0xda, 0xdc, 0x7f, 0x90, 0xbf, 0x8b, 0x25, 0xb7, 0x72, 0x0c, - 0x66, 0x23, 0xcc, 0x89, 0xe8, 0xcd, 0x6b, 0x25, 0xe3, 0x6d, 0x5f, 0xcb, 0x70, 0x40, 0xe9, 0x58, 0x9a, 0xa5, 0xab, - 0x66, 0xe7, 0x9a, 0x5f, 0x42, 0x2e, 0xd8, 0x81, 0x98, 0x74, 0x66, 0xad, 0x16, 0xe6, 0xd7, 0x5e, 0x79, 0xe6, 0x48, - 0xcf, 0x49, 0xd0, 0x70, 0xbb, 0xc8, 0x5a, 0x83, 0x58, 0x6f, 0x99, 0xd3, 0x61, 0x4b, 0x5e, 0xbb, 0xb0, 0x29, 0x86, - 0xe1, 0xf8, 0xcc, 0xec, 0x13, 0xcc, 0xf6, 0x4c, 0xb4, 0xc7, 0xfe, 0x67, 0x36, 0x0b, 0x6d, 0x1a, 0x12, 0xae, 0xb8, - 0xf2, 0x41, 0x8a, 0xab, 0x89, 0x3c, 0x9c, 0xc7, 0x8c, 0xde, 0x5c, 0x71, 0x1d, 0x73, 0x7b, 0xb2, 0x17, 0x84, 0x99, - 0x03, 0xfb, 0x6e, 0xfc, 0x30, 0xaa, 0x12, 0x67, 0x52, 0x96, 0x2d, 0xc5, 0x52, 0x0c, 0xf2, 0xbc, 0x0e, 0x71, 0x28, - 0x95, 0x0b, 0x62, 0x57, 0x24, 0xb2, 0xed, 0x59, 0xb2, 0x78, 0xef, 0xfa, 0x69, 0x05, 0xd5, 0x4b, 0x7c, 0x24, 0xbb, - 0x3d, 0x13, 0xda, 0x72, 0x0b, 0xb2, 0x83, 0xae, 0x83, 0x3b, 0xd2, 0xa4, 0x04, 0x6f, 0x8a, 0x32, 0xfa, 0x4b, 0x1d, - 0x29, 0x15, 0x2d, 0xe6, 0x82, 0x99, 0x89, 0x14, 0xb3, 0xb5, 0x4d, 0x42, 0x80, 0x34, 0x49, 0x7b, 0x89, 0x2c, 0x6a, - 0x9e, 0x03, 0x86, 0x6d, 0x61, 0xc8, 0x3d, 0x5f, 0x02, 0x8c, 0xfa, 0x3e, 0x0f, 0x27, 0x73, 0x84, 0x4d, 0xa2, 0xe4, - 0xef, 0xb5, 0xb6, 0x5d, 0xc3, 0xd6, 0xd1, 0x3f, 0x34, 0x84, 0xaf, 0xa6, 0xb2, 0x86, 0x25, 0xcc, 0xaa, 0x10, 0xde, - 0x2a, 0x0d, 0x50, 0xa4, 0x2c, 0xeb, 0xc3, 0x92, 0x80, 0x09, 0x93, 0x82, 0x76, 0x88, 0xe5, 0x2a, 0x8d, 0xd9, 0x69, - 0x11, 0x5b, 0x73, 0x2f, 0x5b, 0x1c, 0x7f, 0xf5, 0xfb, 0x17, 0x47, 0xa4, 0x72, 0x3b, 0x7f, 0xed, 0x20, 0x3b, 0x60, - 0x64, 0xa1, 0x3f, 0x5b, 0x76, 0x74, 0xee, 0xbf, 0x9e, 0xe2, 0x77, 0x09, 0xfc, 0x3d, 0x72, 0x1c, 0x88, 0x87, 0xdc, - 0xb5, 0x9e, 0x0d, 0x54, 0xf7, 0xb8, 0xac, 0xee, 0x7b, 0xe5, 0x1c, 0xa9, 0x70, 0x12, 0x22, 0xdd, 0xe5, 0xb0, 0x04, - 0xab, 0xf7, 0xd7, 0x90, 0x6c, 0x0a, 0xa6, 0x89, 0xc2, 0x46, 0x59, 0xf3, 0xd5, 0x61, 0xb8, 0xd8, 0x60, 0x05, 0x97, - 0x70, 0x30, 0xf4, 0xda, 0x9b, 0x39, 0xbd, 0xd5, 0xec, 0x8e, 0x41, 0x13, 0xd9, 0x74, 0x77, 0x90, 0x8a, 0xed, 0x0d, - 0x09, 0x4f, 0xff, 0x73, 0x23, 0x07, 0x04, 0xc0, 0xd2, 0xac, 0x90, 0x64, 0xf0, 0x55, 0xce, 0x49, 0x26, 0x53, 0x4b, - 0xcd, 0x6e, 0x2b, 0x05, 0x92, 0xbd, 0xf0, 0xdf, 0xa2, 0xba, 0x19, 0xed, 0xa7, 0xe4, 0x0e, 0xfa, 0x26, 0x3b, 0x34, - 0xf0, 0xc6, 0x9c, 0xf6, 0xde, 0xd0, 0xc4, 0xe2, 0x2b, 0x80, 0x88, 0xc3, 0x01, 0x99, 0x78, 0xc6, 0xc2, 0x12, 0x90, - 0x4e, 0xf5, 0x30, 0x88, 0x09, 0x57, 0x91, 0x16, 0x9c, 0x99, 0x7c, 0xf7, 0x0e, 0x53, 0xe4, 0xd3, 0x3e, 0x83, 0xc6, - 0xec, 0xa0, 0x3a, 0x5d, 0x7b, 0x45, 0x87, 0x7e, 0x9d, 0x39, 0x4b, 0x24, 0x3d, 0xe9, 0xcb, 0x8d, 0x63, 0x99, 0x20, - 0x2d, 0x62, 0xca, 0x67, 0x2a, 0xe8, 0x73, 0xa6, 0xb7, 0x7d, 0x13, 0x78, 0x73, 0xd4, 0xb4, 0x32, 0x2a, 0x07, 0xb8, - 0x49, 0xba, 0x29, 0x83, 0x51, 0x91, 0xac, 0x87, 0x01, 0x2a, 0x41, 0x4e, 0x74, 0x1a, 0x1b, 0x6a, 0x8f, 0xc3, 0x20, - 0x71, 0x1b, 0x50, 0xef, 0x35, 0x33, 0x3a, 0x1a, 0xdd, 0xe7, 0xbf, 0xf0, 0xff, 0xc3, 0xf7, 0x7f, 0x16, 0x8d, 0x93, - 0x5e, 0xa8, 0xac, 0xb4, 0x40, 0xaa, 0x19, 0x81, 0x7e, 0x8f, 0x3b, 0xaf, 0xee, 0x61, 0x85, 0xd1, 0xa5, 0x9d, 0xdb, - 0xee, 0xf4, 0xb8, 0x7f, 0x7d, 0x0a, 0x3f, 0x7f, 0xf7, 0x75, 0xcd, 0xaf, 0xf4, 0x5e, 0x9e, 0x29, 0x87, 0xae, 0x71, - 0x23, 0x92, 0x04, 0xc6, 0xab, 0x6b, 0x14, 0x5a, 0x81, 0x2c, 0xbf, 0x40, 0xc1, 0xc7, 0xb7, 0x46, 0xbb, 0x4f, 0xbb, - 0x22, 0xc8, 0x84, 0xbc, 0x55, 0x10, 0xd6, 0x36, 0x1c, 0x0f, 0x6c, 0x16, 0x5d, 0xd0, 0xfb, 0x1d, 0xba, 0x86, 0x9f, - 0x32, 0x5f, 0x5e, 0xcd, 0x05, 0xdf, 0xe0, 0x74, 0x02, 0xba, 0xe5, 0xce, 0x7b, 0x15, 0xd8, 0x21, 0x67, 0xfd, 0xc8, - 0xe8, 0xde, 0x29, 0x64, 0xa3, 0xc4, 0xb4, 0x63, 0xa1, 0xed, 0xda, 0xa9, 0xdb, 0x21, 0x1e, 0xdf, 0x28, 0x05, 0x3c, - 0x3a, 0x6c, 0x6e, 0x9c, 0x34, 0x52, 0xb0, 0x6a, 0x6f, 0x7d, 0x3d, 0xb7, 0xb9, 0x15, 0xcb, 0x07, 0x5b, 0x6f, 0x20, - 0x09, 0xe9, 0xc6, 0x91, 0x33, 0xa5, 0x5e, 0x1b, 0xda, 0xa7, 0xd9, 0xca, 0xcd, 0x4d, 0xd2, 0x71, 0xaf, 0x9e, 0xc6, - 0x09, 0xe3, 0x38, 0x97, 0x54, 0x26, 0x4e, 0x7c, 0x89, 0xf9, 0xf2, 0x44, 0x6c, 0xa6, 0x25, 0x35, 0xba, 0xca, 0x75, - 0x67, 0x4a, 0x14, 0xa4, 0xe8, 0xf9, 0xdb, 0x2c, 0xe1, 0x8a, 0x6b, 0xc2, 0x33, 0x03, 0x35, 0xa1, 0x75, 0xee, 0x5e, - 0x66, 0x78, 0x70, 0x89, 0xfb, 0xe3, 0xc4, 0xbf, 0x50, 0x3d, 0xb1, 0xe5, 0x57, 0x94, 0xb1, 0xf1, 0x66, 0xdd, 0xdd, - 0xbf, 0xa7, 0xc4, 0x7d, 0x7e, 0x2a, 0x8e, 0xa2, 0xf5, 0xf6, 0xfd, 0xe4, 0x2a, 0xd6, 0xf3, 0xa9, 0xe0, 0x1b, 0x45, - 0x00, 0x9c, 0xf4, 0x68, 0x59, 0xee, 0xb4, 0x1a, 0x7c, 0x06, 0x02, 0x22, 0xdf, 0x9d, 0xb3, 0x6b, 0x7f, 0x3c, 0x25, - 0xd3, 0x66, 0x34, 0x97, 0x97, 0x41, 0xb3, 0xaf, 0x11, 0x00, 0xc8, 0x69, 0xcd, 0xc8, 0xc7, 0xf9, 0x10, 0x06, 0x97, - 0xcb, 0x24, 0x73, 0xbb, 0x05, 0x70, 0x01, 0xb9, 0x52, 0xbe, 0x5a, 0x57, 0x31, 0xd4, 0xcc, 0x8b, 0x70, 0x7c, 0xb5, - 0x97, 0x4f, 0xd1, 0x4e, 0x58, 0xda, 0xab, 0xb9, 0x8c, 0x04, 0xd6, 0xab, 0x0e, 0x11, 0x7a, 0xb2, 0x35, 0xf2, 0xf8, - 0x32, 0xf3, 0xdd, 0x96, 0x03, 0x6a, 0x07, 0x96, 0x57, 0x5b, 0xcd, 0x49, 0xd3, 0x6e, 0x79, 0x34, 0xdb, 0x33, 0xaa, - 0xa1, 0x60, 0x39, 0x77, 0xfb, 0x91, 0x1d, 0x67, 0x4b, 0x75, 0x35, 0xb7, 0xfa, 0x82, 0xb0, 0x2d, 0x16, 0xc8, 0xc7, - 0x11, 0xb0, 0xa6, 0x13, 0x5a, 0x92, 0x39, 0x28, 0x4d, 0x3b, 0x0a, 0x40, 0x07, 0xf0, 0x64, 0x1a, 0xf7, 0x94, 0xf4, - 0xdf, 0x81, 0xb7, 0x6b, 0x7d, 0xd2, 0xa1, 0x18, 0x05, 0xcf, 0x3f, 0x9c, 0x01, 0x38, 0xfd, 0xde, 0xda, 0xfb, 0xd9, - 0xbb, 0x35, 0xa0, 0xe6, 0x5a, 0xae, 0x1c, 0xc1, 0x7f, 0x2a, 0x32, 0x65, 0x45, 0xcc, 0xb7, 0x23, 0x54, 0xaa, 0xb0, - 0xdc, 0xab, 0x80, 0xbf, 0xdf, 0x0d, 0xb7, 0xff, 0xaf, 0x8a, 0xc9, 0x3d, 0xfc, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, - 0x6d, 0x58, 0x5b, 0xee, 0x7f, 0x6b, 0xc0, 0xf4, 0xbb, 0x02, 0x35, 0xc1, 0xf6, 0x6f, 0xdf, 0xb9, 0x24, 0x97, 0xf5, - 0xe1, 0xde, 0xc9, 0x4a, 0x0f, 0x53, 0x7a, 0x30, 0xf0, 0x08, 0xff, 0x7f, 0x96, 0x81, 0xec, 0x05, 0x85, 0xc9, 0xc2, - 0xfe, 0xfb, 0x59, 0x2a, 0xa0, 0x9f, 0x12, 0x65, 0x8d, 0x23, 0xde, 0xd6, 0x7e, 0x5a, 0xa3, 0x1f, 0x23, 0xa2, 0x58, - 0xa7, 0x82, 0x7e, 0x55, 0x9f, 0x27, 0x88, 0xef, 0x7d, 0x5c, 0xfa, 0x12, 0x2a, 0x86, 0x07, 0xca, 0xde, 0x5d, 0xc1, - 0xf9, 0x91, 0x6e, 0xc7, 0x45, 0xa1, 0xf9, 0x53, 0xe5, 0x8f, 0xdb, 0x7a, 0xae, 0xf2, 0x7e, 0x45, 0xda, 0x37, 0xb9, - 0xf5, 0x57, 0x51, 0xd2, 0xbd, 0x20, 0x8b, 0x2c, 0x16, 0x77, 0xe7, 0x22, 0xf9, 0xc4, 0xd9, 0x03, 0xdb, 0x39, 0x9b, - 0x47, 0x78, 0x32, 0xa7, 0xb1, 0x48, 0x44, 0x67, 0xe1, 0xf5, 0x40, 0x93, 0x8a, 0x5d, 0x1f, 0xe0, 0xbb, 0x0f, 0xfc, - 0xe4, 0x94, 0x2f, 0x7e, 0xf2, 0x57, 0x3e, 0x46, 0x8f, 0xf5, 0x29, 0x9b, 0x60, 0xf0, 0x4a, 0x97, 0x53, 0x3d, 0x7b, - 0x79, 0x68, 0x48, 0xf4, 0xa6, 0xc6, 0xca, 0x7e, 0xa0, 0x67, 0xab, 0xa9, 0xee, 0x92, 0xb1, 0x42, 0xcb, 0xbb, 0xe2, - 0xf6, 0xd1, 0xba, 0x1a, 0x5f, 0x69, 0xdc, 0x4d, 0xcb, 0xf7, 0x24, 0xea, 0x60, 0x71, 0xf3, 0xe3, 0x4e, 0xbd, 0x6d, - 0x5b, 0xe5, 0xbf, 0x0b, 0xd0, 0x1f, 0x6c, 0xf4, 0x4e, 0xe6, 0x30, 0xa7, 0x57, 0x7e, 0x9e, 0xe3, 0x95, 0xc3, 0x9c, - 0x5d, 0xd9, 0xcd, 0xb9, 0x95, 0xeb, 0x39, 0xff, 0xf0, 0x71, 0x70, 0x93, 0x27, 0xc1, 0x2e, 0x1f, 0x63, 0x88, 0xb3, - 0xb3, 0x0f, 0xc3, 0x2d, 0xe7, 0x8f, 0x11, 0xb7, 0x6d, 0xca, 0x0a, 0x52, 0x4f, 0x7d, 0x3c, 0xf9, 0xf8, 0xde, 0x7a, - 0x97, 0x7e, 0x65, 0xb3, 0xab, 0x3d, 0xad, 0xc6, 0xcb, 0x22, 0x8a, 0xc4, 0x5c, 0x6d, 0xca, 0xfb, 0xad, 0x1b, 0x66, - 0x02, 0x36, 0xed, 0xf9, 0xb6, 0xed, 0xc8, 0xcd, 0x95, 0xea, 0x9f, 0xcf, 0xa8, 0x4b, 0xe6, 0x3b, 0xf2, 0x48, 0x6a, - 0x66, 0xaf, 0xea, 0xcc, 0x3b, 0xd3, 0x44, 0x11, 0x24, 0x08, 0xa2, 0x7c, 0xbe, 0x90, 0xc9, 0xdc, 0xd2, 0x2a, 0x41, - 0xd0, 0xd8, 0x37, 0x60, 0x49, 0x99, 0xac, 0x5b, 0x57, 0xcc, 0x74, 0x06, 0xf2, 0x69, 0x0f, 0x6b, 0xc2, 0x9b, 0xc1, - 0xe1, 0x7c, 0xdd, 0xf5, 0xd9, 0xe5, 0xbd, 0xcf, 0x3d, 0xea, 0xb8, 0xbf, 0x15, 0x37, 0x20, 0x07, 0x73, 0x9f, 0x27, - 0x77, 0x21, 0x6b, 0xac, 0xd3, 0x86, 0x72, 0x4e, 0x75, 0x6d, 0xda, 0x60, 0x88, 0x5e, 0xfd, 0x42, 0x98, 0x48, 0x5b, - 0x3c, 0x9f, 0xd6, 0xd2, 0x37, 0x05, 0x2e, 0x6d, 0x66, 0xd0, 0x69, 0x58, 0x2c, 0x66, 0x12, 0xc2, 0x89, 0x8b, 0x7a, - 0xb4, 0xa9, 0x24, 0x89, 0xf1, 0xb3, 0xfe, 0x5a, 0x2e, 0x23, 0x38, 0x50, 0x0b, 0x4c, 0x5c, 0x17, 0x69, 0xf4, 0x1f, - 0xcc, 0x50, 0x6f, 0x9b, 0xfd, 0xa0, 0xcd, 0x8d, 0x29, 0x7c, 0x85, 0x7e, 0xd2, 0xf4, 0x0a, 0xb5, 0x7b, 0x11, 0x1f, - 0x89, 0x21, 0xf2, 0x01, 0x6c, 0x3b, 0xcc, 0x09, 0xb4, 0x80, 0x73, 0xc4, 0x18, 0x2c, 0x4e, 0x95, 0xea, 0x6c, 0x92, - 0xb7, 0x22, 0x46, 0x5b, 0xb2, 0x1d, 0x6d, 0xd5, 0xb9, 0x1c, 0x5b, 0xb4, 0xb9, 0x91, 0x7d, 0xf3, 0x9f, 0xab, 0x7c, - 0xa3, 0x7d, 0x7f, 0xb5, 0x0a, 0xec, 0x81, 0x91, 0xbf, 0x6b, 0x7f, 0x33, 0x97, 0xb2, 0xec, 0xff, 0x63, 0x72, 0x32, - 0x7b, 0x23, 0x81, 0xf8, 0x95, 0xe7, 0x69, 0x25, 0x9e, 0x84, 0x91, 0xfd, 0x8e, 0x3c, 0xa1, 0xca, 0xb7, 0xd1, 0x96, - 0x96, 0xe5, 0x7e, 0xb7, 0x96, 0x1f, 0x93, 0xe9, 0x5c, 0xbe, 0xf5, 0x84, 0x21, 0xb7, 0xe7, 0x89, 0x78, 0x9f, 0x00, - 0xe7, 0xe6, 0x78, 0x69, 0x9e, 0x7c, 0xe3, 0x91, 0x69, 0xc1, 0x16, 0x80, 0x37, 0x72, 0x76, 0x24, 0xca, 0x49, 0x22, - 0x2d, 0x86, 0x7a, 0xfc, 0xd6, 0xd9, 0xea, 0xef, 0xcd, 0x01, 0x57, 0x00, 0x26, 0x0f, 0xf8, 0x70, 0x24, 0x3f, 0x6e, - 0xdb, 0x09, 0xdb, 0x98, 0x35, 0xc4, 0xe4, 0x61, 0x72, 0x50, 0x7e, 0x15, 0xb4, 0x1a, 0xe9, 0x0b, 0x97, 0x93, 0xcc, - 0x02, 0xe7, 0x90, 0xb8, 0xef, 0x2f, 0x22, 0x9f, 0xfe, 0x5d, 0xe6, 0x4f, 0x0e, 0xce, 0x4c, 0xf1, 0x1f, 0xa3, 0xf1, - 0x40, 0x46, 0xe6, 0x45, 0xfd, 0x53, 0xa3, 0xb5, 0x54, 0x3b, 0x3b, 0x8a, 0x9b, 0x2b, 0x6b, 0x6f, 0xcd, 0x9a, 0x03, - 0xd6, 0x5b, 0x23, 0xf3, 0xc6, 0x32, 0xa2, 0x69, 0x23, 0x7e, 0x09, 0xe7, 0xd5, 0x71, 0x9d, 0x07, 0xe4, 0x37, 0x84, - 0x10, 0xe6, 0xd5, 0x7a, 0xcb, 0x53, 0xb8, 0x5e, 0x2f, 0x75, 0x34, 0xa7, 0xa1, 0xcf, 0x3c, 0x4b, 0x03, 0xcd, 0x80, - 0xe8, 0xd9, 0x79, 0xf5, 0x99, 0xd7, 0x99, 0xb9, 0x18, 0x8f, 0x4e, 0x68, 0xa6, 0x4e, 0xb8, 0xe7, 0x83, 0x19, 0x0b, - 0x14, 0x9b, 0xf8, 0x09, 0x49, 0xe0, 0xf1, 0x93, 0xa3, 0xbc, 0x73, 0x4e, 0xc9, 0xc3, 0x3b, 0x7e, 0x00, 0x0d, 0x40, - 0xe6, 0x1d, 0x24, 0xad, 0xb6, 0xbd, 0xc7, 0x6a, 0x14, 0x09, 0xbe, 0xcc, 0x95, 0xf1, 0xb4, 0xc9, 0x17, 0x6e, 0x36, - 0xb3, 0x7b, 0x57, 0x0f, 0x9e, 0x6f, 0x56, 0xbb, 0xbe, 0xcd, 0x9a, 0xcf, 0x6c, 0xfe, 0xe9, 0xd3, 0x22, 0x2e, 0x67, - 0x94, 0xb9, 0x9e, 0x53, 0xe8, 0x35, 0x23, 0x93, 0x0e, 0xdd, 0x73, 0x89, 0x9d, 0x90, 0x05, 0x4d, 0x6e, 0xe1, 0xa2, - 0x9a, 0x84, 0xfb, 0xda, 0xef, 0x84, 0xd4, 0xa9, 0x5a, 0xd4, 0x1b, 0xa3, 0x27, 0xbb, 0xf8, 0x19, 0x7b, 0xcc, 0x3b, - 0x33, 0x39, 0x91, 0x01, 0x78, 0x51, 0xd9, 0x14, 0x58, 0x9e, 0x35, 0x01, 0x04, 0x65, 0x58, 0x86, 0xd6, 0x12, 0x40, - 0x61, 0x6e, 0xca, 0x07, 0x19, 0xb4, 0xfc, 0x1c, 0x7f, 0x5d, 0x9e, 0x1b, 0x98, 0x37, 0x3e, 0x4e, 0x4e, 0xd0, 0x9c, - 0x14, 0xca, 0x85, 0x88, 0x0f, 0x0a, 0xa0, 0x46, 0x05, 0x9e, 0xd1, 0xbd, 0x0f, 0xf0, 0xdf, 0x0f, 0xfb, 0x75, 0x9d, - 0xf2, 0xef, 0x4f, 0xfe, 0x69, 0xee, 0x3d, 0xf1, 0xaf, 0x4b, 0x49, 0x0a, 0x08, 0x9e, 0xc2, 0xbe, 0xb9, 0xde, 0xbf, - 0x4d, 0xee, 0x55, 0xed, 0x6e, 0x23, 0xa3, 0x3a, 0xb1, 0x30, 0x94, 0xfe, 0x7a, 0xe4, 0xca, 0x37, 0x1f, 0x62, 0xdb, - 0xc3, 0xa6, 0x3f, 0xdc, 0xf7, 0xab, 0x7c, 0x73, 0x21, 0x53, 0xbb, 0x69, 0x45, 0x62, 0x95, 0x62, 0xc0, 0x95, 0x82, - 0x86, 0x39, 0x67, 0x0f, 0xdf, 0xce, 0xd6, 0x46, 0x1a, 0xf1, 0x86, 0xb8, 0x12, 0xab, 0xee, 0x93, 0x50, 0xf9, 0xf6, - 0xfe, 0xf5, 0xd2, 0xb2, 0xf3, 0xb9, 0xf5, 0x0b, 0xc9, 0x00, 0xb3, 0x40, 0xe2, 0x53, 0x71, 0xe4, 0x3e, 0x94, 0x74, - 0x92, 0xa2, 0x78, 0x0c, 0x6d, 0x81, 0x05, 0xa3, 0x21, 0x97, 0xc6, 0x00, 0x59, 0x6a, 0x89, 0x47, 0x5d, 0x4c, 0x2f, - 0xf8, 0xbe, 0xed, 0x06, 0xcd, 0xf7, 0x86, 0x27, 0x1f, 0x7a, 0x6d, 0x62, 0x04, 0xa5, 0x2b, 0xb0, 0xbd, 0xad, 0x18, - 0x91, 0xcb, 0xa5, 0xe4, 0x9f, 0x26, 0x0f, 0x50, 0xb8, 0xef, 0x9e, 0xf8, 0x5c, 0x2c, 0x14, 0xa5, 0xc8, 0x7c, 0x10, - 0x57, 0x83, 0x88, 0x93, 0x06, 0xaa, 0xae, 0x36, 0x76, 0x20, 0xcc, 0xb2, 0x31, 0xa5, 0xc6, 0x0b, 0x1a, 0x10, 0x44, - 0x88, 0x6c, 0x62, 0x05, 0x22, 0xd4, 0xc3, 0xfc, 0x70, 0x43, 0xc7, 0x8a, 0x3a, 0x45, 0x27, 0xa8, 0xa9, 0xb4, 0x86, - 0x34, 0x3d, 0x7a, 0x85, 0x0d, 0x8c, 0x4e, 0x9c, 0x4d, 0x57, 0xe1, 0xbd, 0xe1, 0xce, 0xbe, 0x37, 0x8f, 0x79, 0x2e, - 0xd3, 0x1e, 0x84, 0x4a, 0xc3, 0x58, 0x4f, 0xb7, 0xc4, 0xe9, 0x9e, 0x6d, 0xe6, 0x25, 0xd5, 0x7c, 0x77, 0xb7, 0x67, - 0xed, 0x39, 0x1b, 0x51, 0xbb, 0xad, 0x83, 0xa3, 0xdb, 0x60, 0xac, 0xcf, 0xbb, 0xbb, 0xbc, 0xa0, 0x3d, 0xa9, 0x62, - 0x22, 0x36, 0xd1, 0xa4, 0x01, 0x20, 0xda, 0x51, 0x9a, 0xec, 0xf3, 0x93, 0x9d, 0x1a, 0x08, 0xa5, 0x23, 0x28, 0x6d, - 0x63, 0x33, 0x51, 0x55, 0x6f, 0xf2, 0xb8, 0x8e, 0x9b, 0x30, 0x43, 0x41, 0xcd, 0x7f, 0x3f, 0x0a, 0xb6, 0xdc, 0x19, - 0x98, 0x20, 0xd6, 0x73, 0xdb, 0xd2, 0x5d, 0xc0, 0x03, 0x9c, 0xbe, 0xed, 0xc0, 0x9b, 0x46, 0x7c, 0x1e, 0x1e, 0xa7, - 0xc7, 0xba, 0x17, 0x6e, 0x89, 0x12, 0x23, 0x19, 0x41, 0x06, 0xb9, 0xf6, 0xd8, 0x07, 0x2f, 0x61, 0x91, 0xae, 0x23, - 0xc7, 0x0f, 0xe1, 0x82, 0xc2, 0x84, 0x70, 0x1a, 0xee, 0x5e, 0x14, 0x75, 0x9b, 0xdd, 0xee, 0x89, 0xd1, 0xce, 0x96, - 0xdc, 0xd5, 0x6e, 0x90, 0x79, 0x14, 0xe8, 0xdd, 0x2a, 0x8b, 0xb2, 0xb5, 0x23, 0x1f, 0x36, 0x93, 0x7c, 0x1c, 0x48, - 0xa6, 0xbe, 0xbb, 0x33, 0xb4, 0x3f, 0x90, 0x9d, 0xb6, 0xef, 0x12, 0x5a, 0x1f, 0xa0, 0x9a, 0x56, 0xed, 0xb6, 0x65, - 0xdb, 0xf6, 0x69, 0x19, 0x90, 0x7b, 0xac, 0x7d, 0xe9, 0x46, 0xc6, 0xff, 0xfc, 0x04, 0x23, 0xad, 0x3b, 0xf4, 0x0b, - 0x73, 0x97, 0x9d, 0x46, 0xb6, 0x37, 0x57, 0x4f, 0x51, 0x5a, 0xfb, 0xc0, 0x2c, 0x1a, 0x1f, 0x47, 0x60, 0x7c, 0x06, - 0x4d, 0x84, 0xc1, 0xcf, 0xf0, 0x8b, 0x85, 0x74, 0xb9, 0x22, 0xf7, 0x62, 0x02, 0xe8, 0xdd, 0xe8, 0xcf, 0x9e, 0x41, - 0xb5, 0x54, 0x65, 0x74, 0x9d, 0x14, 0xc5, 0xf4, 0xb7, 0xff, 0x9f, 0xab, 0x81, 0xfa, 0x83, 0x18, 0x85, 0xbe, 0xfc, - 0xe2, 0xe8, 0x5a, 0x57, 0x6c, 0x7a, 0xfe, 0x82, 0xee, 0x03, 0x2e, 0xf1, 0x82, 0x01, 0x3e, 0x8b, 0xc8, 0xdc, 0x24, - 0x73, 0xad, 0xd1, 0x69, 0xec, 0x6d, 0xb0, 0x77, 0x27, 0xff, 0x64, 0x10, 0xf7, 0x0b, 0x68, 0x3b, 0xd3, 0xdd, 0x20, - 0x83, 0x54, 0x9f, 0x13, 0xfd, 0xc3, 0xc0, 0x06, 0xf9, 0xc9, 0xa2, 0x5c, 0x46, 0x38, 0x9f, 0x14, 0x1d, 0x63, 0x15, - 0x62, 0x57, 0x21, 0xf7, 0x8d, 0x74, 0x37, 0x06, 0x76, 0xe8, 0x19, 0x0c, 0xfb, 0xdd, 0x69, 0x53, 0xa9, 0xa0, 0xbd, - 0xaa, 0x46, 0x93, 0xdd, 0x48, 0x6e, 0xed, 0x45, 0x6c, 0xf4, 0x43, 0xc0, 0x10, 0x37, 0x55, 0x8b, 0xdb, 0x01, 0x0b, - 0x87, 0x5d, 0x5c, 0x47, 0x77, 0x04, 0x99, 0x3f, 0x7c, 0x62, 0xc1, 0x15, 0xd9, 0xf9, 0xdf, 0x12, 0x4c, 0xdf, 0x3b, - 0xad, 0xcc, 0xff, 0x53, 0xcc, 0xfe, 0xd0, 0xf3, 0x8a, 0xac, 0x3f, 0x7b, 0xbf, 0x28, 0xba, 0x84, 0xcb, 0x2d, 0x12, - 0xf3, 0x29, 0x34, 0xfd, 0xf5, 0xd6, 0x7c, 0x23, 0x24, 0xee, 0x0f, 0x26, 0x04, 0x9b, 0x94, 0xc5, 0x18, 0x11, 0xfe, - 0xf5, 0xf6, 0xab, 0xf9, 0xd7, 0xa4, 0x25, 0x88, 0xa0, 0xaa, 0xf1, 0x4e, 0x7f, 0xcf, 0x68, 0xf9, 0x01, 0xfe, 0xfd, - 0x81, 0x3f, 0x39, 0xe5, 0xef, 0x9f, 0xfc, 0xd3, 0x2c, 0xbd, 0x25, 0x57, 0xf3, 0x19, 0x72, 0xb0, 0xac, 0x22, 0x01, - 0x2f, 0x5e, 0xcb, 0x91, 0x37, 0x3b, 0x88, 0x07, 0x32, 0xff, 0xea, 0x24, 0x2e, 0xd0, 0x31, 0xf2, 0x21, 0x4f, 0x4b, - 0xf2, 0x82, 0xb1, 0x3b, 0xaa, 0xa5, 0x99, 0xb6, 0xd5, 0xbb, 0x84, 0xda, 0xc5, 0x20, 0x4b, 0x30, 0xdf, 0xff, 0x24, - 0x72, 0x52, 0xd2, 0x98, 0x7f, 0x2b, 0x1f, 0x8f, 0xee, 0x59, 0x1a, 0x98, 0xa2, 0x62, 0xfe, 0xea, 0x45, 0xca, 0x93, - 0xd5, 0x1f, 0xa3, 0x11, 0xf7, 0x8d, 0x99, 0x85, 0xe8, 0x03, 0x3b, 0x43, 0x62, 0xe4, 0xb8, 0x7b, 0x71, 0xd2, 0xf8, - 0xad, 0x4e, 0x90, 0x78, 0xcb, 0x34, 0x48, 0x5f, 0x8b, 0x43, 0xb9, 0x56, 0x8d, 0x4f, 0x3c, 0x58, 0xa4, 0xfd, 0x6d, - 0x77, 0x96, 0xbe, 0xf5, 0xf2, 0xb8, 0x32, 0x7d, 0x99, 0x70, 0x17, 0xc6, 0x22, 0xce, 0x35, 0x56, 0x54, 0x24, 0x46, - 0xe0, 0x10, 0xc5, 0xdb, 0x02, 0x80, 0xd9, 0x28, 0x76, 0x71, 0xfc, 0xc7, 0xef, 0xda, 0xc2, 0x89, 0x44, 0x4b, 0x91, - 0xd4, 0xdc, 0x61, 0x7c, 0xa3, 0xf1, 0x98, 0xc1, 0x78, 0x4f, 0x54, 0xfd, 0xc5, 0xf2, 0x98, 0x95, 0x5a, 0x8f, 0x52, - 0x3c, 0x66, 0x7c, 0x69, 0x34, 0x58, 0x62, 0xcf, 0x43, 0x98, 0xfc, 0x4b, 0xa3, 0xe4, 0xf7, 0x52, 0xec, 0x6a, 0x69, - 0x24, 0xb6, 0x0e, 0xc4, 0x4c, 0x66, 0x71, 0x02, 0xeb, 0x4c, 0x75, 0x4f, 0xce, 0xc6, 0x4b, 0xa5, 0x79, 0x05, 0xad, - 0x0b, 0x7f, 0xa0, 0x9d, 0xe0, 0xd6, 0x5f, 0x3c, 0xbf, 0xe9, 0x56, 0x0e, 0x47, 0xae, 0xd8, 0x6b, 0xfd, 0x3d, 0xde, - 0xee, 0xa9, 0xfa, 0xcb, 0x35, 0xd0, 0x9d, 0x63, 0xb3, 0x49, 0x93, 0xe1, 0x60, 0xe4, 0x13, 0x40, 0x27, 0x48, 0x8e, - 0x66, 0x58, 0xa1, 0xe7, 0x5d, 0x02, 0xb3, 0x5f, 0xf2, 0xe2, 0x10, 0x25, 0x04, 0x7c, 0x6b, 0xb3, 0x98, 0x84, 0xe8, - 0xe1, 0xff, 0xb9, 0x97, 0x7e, 0xbd, 0xb8, 0x5d, 0x8e, 0xb4, 0x05, 0x72, 0xeb, 0x1c, 0x30, 0x0e, 0x7c, 0xb5, 0x31, - 0x50, 0x2e, 0x44, 0x66, 0x44, 0x53, 0x3a, 0x1b, 0x9c, 0x6e, 0x43, 0x3e, 0x5b, 0xf3, 0xf8, 0x46, 0x25, 0x3a, 0xa7, - 0x4e, 0xd2, 0x8c, 0x5b, 0x1b, 0xc4, 0x58, 0x2e, 0x44, 0x43, 0x2c, 0x74, 0x6c, 0x0d, 0x2e, 0x76, 0xdc, 0x0e, 0x8f, - 0xe7, 0xa2, 0x11, 0x3f, 0x92, 0x10, 0x11, 0x9c, 0x8b, 0x99, 0x18, 0xf2, 0xa1, 0x19, 0x01, 0xec, 0xe7, 0x79, 0x7c, - 0x61, 0x1a, 0x66, 0x8f, 0xe0, 0xd9, 0xcb, 0x13, 0xf1, 0x93, 0x46, 0x30, 0x44, 0xc8, 0x86, 0x49, 0x02, 0xd8, 0x63, - 0xb2, 0xd6, 0x6f, 0xdc, 0xda, 0xcb, 0xbe, 0xbf, 0x2c, 0x1b, 0xb7, 0xf3, 0xdf, 0xb1, 0xf8, 0x61, 0x12, 0xf5, 0xea, - 0x9d, 0x08, 0x61, 0x57, 0x8c, 0xde, 0xc9, 0x2a, 0x74, 0x55, 0x44, 0xdf, 0xf7, 0xf0, 0xb1, 0xc6, 0x06, 0xe1, 0x8f, - 0xe1, 0x29, 0x90, 0x37, 0x91, 0xdd, 0xbf, 0x13, 0x5c, 0xdc, 0xf8, 0xd1, 0x9e, 0xc2, 0xce, 0xd8, 0x21, 0x74, 0xa9, - 0x92, 0x49, 0xd1, 0x1d, 0x94, 0x26, 0x9a, 0x6a, 0x78, 0xa1, 0x40, 0x7c, 0x0c, 0x5b, 0x76, 0x35, 0xe3, 0x23, 0xc5, - 0x6f, 0xe3, 0xc5, 0x02, 0xa7, 0x98, 0x60, 0xf4, 0xf0, 0xc0, 0x84, 0xb1, 0x05, 0x6a, 0xf4, 0x10, 0x15, 0x53, 0xce, - 0x63, 0xaa, 0x4b, 0x16, 0x27, 0x7b, 0x65, 0x56, 0x6b, 0xa7, 0x4f, 0x93, 0x54, 0xac, 0x57, 0x58, 0x9e, 0x59, 0xbd, - 0x6a, 0x97, 0x09, 0xf0, 0xc1, 0xff, 0x38, 0x04, 0x26, 0x64, 0x5c, 0x75, 0x6a, 0xfb, 0x30, 0x46, 0x78, 0xf3, 0x3b, - 0xc9, 0x84, 0xb2, 0x49, 0x3e, 0x8c, 0x70, 0x67, 0xf7, 0x44, 0x77, 0x8a, 0x33, 0x26, 0x77, 0x51, 0x0d, 0x83, 0x99, - 0x4e, 0xd0, 0x87, 0xfb, 0x85, 0x39, 0x8f, 0x2b, 0xbc, 0xc7, 0xdf, 0x32, 0xaa, 0x13, 0xe2, 0xf5, 0x45, 0xba, 0x88, - 0x1f, 0x38, 0x05, 0xdb, 0x05, 0x54, 0xc3, 0x08, 0x5c, 0x87, 0xd3, 0xba, 0x23, 0x89, 0xe2, 0x8e, 0x4a, 0x50, 0xdf, - 0x48, 0xf9, 0xbb, 0x63, 0x23, 0x96, 0xa8, 0x1a, 0xe9, 0x2f, 0x4a, 0x79, 0x60, 0x87, 0xf4, 0xa4, 0xd4, 0xe8, 0x98, - 0xa9, 0x53, 0xd3, 0xe0, 0x72, 0x90, 0xbb, 0xe0, 0x95, 0xce, 0xec, 0xc1, 0xb9, 0x58, 0x78, 0xa1, 0x19, 0xa2, 0x1e, - 0xe1, 0xda, 0x78, 0xea, 0x92, 0xc4, 0xa9, 0x6a, 0x49, 0xc2, 0x72, 0xd2, 0xe9, 0x4a, 0x03, 0xf7, 0xea, 0x65, 0x8f, - 0x31, 0x90, 0x26, 0xb3, 0x04, 0xa1, 0x7a, 0x5e, 0x23, 0xbc, 0x46, 0x0a, 0x92, 0x76, 0x1e, 0xf6, 0x37, 0x09, 0x28, - 0x6f, 0xfd, 0x43, 0xbd, 0xa2, 0xc0, 0xf2, 0xa7, 0x82, 0xbc, 0x57, 0xeb, 0x6f, 0x33, 0xea, 0x46, 0x37, 0x09, 0xc3, - 0x6e, 0xfd, 0xc3, 0xc6, 0x2a, 0x35, 0x39, 0x9d, 0xf4, 0x6d, 0xb1, 0x7b, 0x00, 0xf2, 0x72, 0xb7, 0x37, 0xc4, 0x64, - 0x44, 0x10, 0x35, 0x07, 0x2e, 0x42, 0x75, 0xc6, 0xf8, 0x76, 0xa2, 0x1b, 0x35, 0xad, 0x11, 0x62, 0xc9, 0xea, 0x1a, - 0x17, 0x72, 0x57, 0x4c, 0x9c, 0x8c, 0x44, 0xe8, 0x96, 0xe4, 0x5c, 0x7f, 0x80, 0xc3, 0x07, 0x92, 0x29, 0x15, 0xc1, - 0x65, 0x82, 0xa4, 0xfa, 0xbc, 0x89, 0xa0, 0x5b, 0x0d, 0x10, 0x58, 0x02, 0xa9, 0x96, 0xb9, 0x59, 0xdc, 0x32, 0x22, - 0x70, 0x54, 0xcb, 0x57, 0x27, 0x52, 0x38, 0xa3, 0xd9, 0xce, 0x1f, 0x5f, 0xfa, 0xc8, 0xbc, 0x55, 0x85, 0x61, 0x49, - 0x01, 0xe8, 0xca, 0xf8, 0x92, 0x42, 0x90, 0x4a, 0xf9, 0xa2, 0x5b, 0xab, 0x9a, 0xb9, 0x4e, 0x6c, 0xe8, 0xc6, 0x0b, - 0xcc, 0xaf, 0xd5, 0x86, 0x81, 0xcd, 0xdd, 0xae, 0x65, 0xae, 0xd8, 0x20, 0xe7, 0x1d, 0xb5, 0x2d, 0x1f, 0x96, 0xd3, - 0xd1, 0xd5, 0x8c, 0x85, 0x8b, 0xdb, 0xa1, 0x48, 0x7d, 0x60, 0x32, 0xe4, 0x34, 0xba, 0x5f, 0x02, 0x32, 0xff, 0xb4, - 0x34, 0x6a, 0x37, 0x5f, 0x30, 0x7a, 0x0e, 0xbd, 0x8c, 0xe3, 0xd9, 0x45, 0xfe, 0x00, 0xa1, 0xec, 0x0d, 0x4e, 0xa1, - 0xb1, 0x01, 0x9d, 0x8b, 0xf0, 0x99, 0x18, 0x05, 0xd6, 0x91, 0x00, 0xbc, 0x38, 0xb7, 0x71, 0x74, 0x00, 0xa8, 0x35, - 0xaa, 0x80, 0xfb, 0xfd, 0xd1, 0x23, 0x87, 0x28, 0xe2, 0x86, 0xdc, 0x53, 0xd4, 0xa5, 0x3c, 0x9f, 0x48, 0x2b, 0x0b, - 0x1f, 0xa6, 0xc8, 0x2b, 0x7e, 0xa1, 0x17, 0x76, 0x69, 0xe7, 0xa7, 0xa5, 0x9b, 0xf7, 0x4b, 0x4d, 0x3c, 0x95, 0xa3, - 0x9f, 0x53, 0x35, 0x65, 0x50, 0xd2, 0xf5, 0xee, 0x22, 0xa2, 0x03, 0x73, 0x2c, 0x6c, 0xf7, 0x03, 0xa7, 0x9a, 0xb6, - 0xca, 0xe4, 0x6e, 0xe5, 0xa1, 0x02, 0x15, 0x1c, 0xa4, 0xeb, 0x65, 0x7b, 0xef, 0x3f, 0xb1, 0xe1, 0x87, 0x4d, 0xf9, - 0x30, 0xd5, 0x75, 0xda, 0xd3, 0xab, 0xa1, 0x0d, 0x91, 0x83, 0xb4, 0x90, 0xb6, 0xab, 0xc6, 0xbd, 0x35, 0x93, 0xd6, - 0xfe, 0xcd, 0xa6, 0x97, 0xed, 0x14, 0x3b, 0x7f, 0x8c, 0x7a, 0x05, 0x51, 0xe4, 0xfa, 0xbd, 0x74, 0xf5, 0x73, 0xe9, - 0x76, 0x2d, 0x48, 0x3f, 0x50, 0x05, 0xcd, 0x2c, 0xa7, 0xbf, 0x2c, 0xf9, 0xe6, 0x96, 0xd2, 0xc7, 0xf4, 0x87, 0x38, - 0xe7, 0xf8, 0xcc, 0xf0, 0x4c, 0x1d, 0x3d, 0xe8, 0x14, 0x11, 0xcd, 0x38, 0x9b, 0x67, 0xd1, 0x74, 0x16, 0xf0, 0x9a, - 0x54, 0x70, 0x57, 0x3f, 0x1c, 0x3a, 0xd6, 0xb4, 0x8b, 0x90, 0xc5, 0x3e, 0x7e, 0xd8, 0xb5, 0x23, 0xe8, 0x61, 0x14, - 0x14, 0x90, 0xe6, 0x5e, 0x32, 0xca, 0x26, 0x06, 0x7e, 0xeb, 0x25, 0xb0, 0xdd, 0xfb, 0xad, 0x7d, 0x64, 0x77, 0xe2, - 0x95, 0x79, 0x15, 0xf4, 0x8e, 0x44, 0x8d, 0x08, 0x55, 0xdb, 0x0e, 0x71, 0x7d, 0xe5, 0xd8, 0xc4, 0xa6, 0x2c, 0x57, - 0x4c, 0xb8, 0xf8, 0x0d, 0xa0, 0x20, 0x4b, 0x72, 0x08, 0x3a, 0x44, 0x4e, 0x1b, 0xdc, 0x39, 0x3a, 0xd5, 0xa3, 0x16, - 0x7f, 0xe6, 0x0b, 0xf4, 0xb8, 0x26, 0x94, 0x51, 0x40, 0x3b, 0x50, 0xf0, 0x99, 0xec, 0xa0, 0xab, 0x55, 0x76, 0x99, - 0xad, 0xb1, 0x81, 0x08, 0x10, 0x52, 0xd1, 0x9f, 0xa6, 0xa7, 0x05, 0x5d, 0xc2, 0xa5, 0x46, 0x0e, 0xda, 0x97, 0xca, - 0x30, 0x0e, 0x75, 0x74, 0x7d, 0x2a, 0x8f, 0x5f, 0x0d, 0x2c, 0x01, 0xe0, 0xe8, 0x33, 0x08, 0x3b, 0xf8, 0x6c, 0xe7, - 0x8a, 0xc5, 0x65, 0xd0, 0x1d, 0x18, 0xd2, 0xbe, 0xda, 0xb9, 0xea, 0xa7, 0xe8, 0xb7, 0xf6, 0x2e, 0xbe, 0x54, 0xd8, - 0x33, 0x2a, 0xb1, 0x46, 0xe8, 0x10, 0x99, 0x71, 0x8d, 0xbc, 0x7b, 0xcf, 0xbd, 0x1f, 0xdb, 0xe8, 0x15, 0x6c, 0xa1, - 0x4b, 0x48, 0x66, 0x05, 0x2e, 0xfc, 0x47, 0x80, 0x0b, 0x0f, 0x8d, 0x9e, 0x05, 0x56, 0x94, 0x32, 0x03, 0x37, 0x92, - 0xdf, 0xec, 0x1d, 0x2c, 0xb3, 0xf4, 0x96, 0xf0, 0x84, 0xb2, 0x36, 0xca, 0x02, 0x9b, 0x60, 0x9f, 0x1a, 0xa2, 0x3d, - 0x74, 0xfc, 0xa0, 0xfd, 0x09, 0xa7, 0x7f, 0x7f, 0xea, 0x09, 0x1a, 0x0b, 0x3e, 0x46, 0x16, 0xf1, 0x87, 0x69, 0x2f, - 0xdd, 0xed, 0x67, 0x86, 0x46, 0x88, 0x20, 0xde, 0x9a, 0xa5, 0x33, 0x52, 0x49, 0xa5, 0x99, 0x6a, 0xde, 0xef, 0x40, - 0xb0, 0x5b, 0x52, 0x82, 0xdd, 0x08, 0x8b, 0x27, 0xde, 0xb3, 0xf6, 0xe5, 0x05, 0x31, 0x61, 0x31, 0xc5, 0x64, 0xed, - 0x11, 0x40, 0xf1, 0x2e, 0xdc, 0x44, 0x94, 0x74, 0xe5, 0xc7, 0x22, 0x19, 0xc9, 0x9f, 0x49, 0x34, 0x17, 0x49, 0x49, - 0xaf, 0xdd, 0x65, 0x7a, 0xb6, 0x02, 0x55, 0x79, 0xbb, 0xe7, 0x46, 0xed, 0x11, 0x36, 0xbe, 0x1b, 0xd4, 0x81, 0x0f, - 0xc8, 0xf5, 0x2c, 0x71, 0x78, 0xff, 0x12, 0x06, 0x34, 0x14, 0xcb, 0x96, 0x10, 0x17, 0x39, 0xee, 0xf3, 0x95, 0xfa, - 0xc0, 0x38, 0x21, 0x2c, 0xf0, 0xf5, 0x22, 0xd0, 0x9a, 0x83, 0xc4, 0xf7, 0x2b, 0x7e, 0xe1, 0x89, 0x82, 0xfa, 0x78, - 0x71, 0xda, 0x3f, 0xea, 0x4d, 0x5f, 0xd5, 0x4c, 0x93, 0xf3, 0x89, 0x90, 0x50, 0x3e, 0xcf, 0xb3, 0x50, 0x3a, 0x86, - 0x49, 0x8e, 0x4f, 0xfa, 0xe2, 0x92, 0x2e, 0x7c, 0x0c, 0xab, 0xf6, 0x57, 0xa3, 0xb0, 0xea, 0xe2, 0x7d, 0xd2, 0x67, - 0xf4, 0xcb, 0x15, 0x56, 0x8d, 0xf6, 0x0b, 0x17, 0x46, 0x75, 0x28, 0xa9, 0xaf, 0x80, 0x00, 0x06, 0xee, 0x70, 0xc7, - 0xaf, 0x13, 0x35, 0x0d, 0x69, 0xb5, 0x86, 0x20, 0x17, 0xfa, 0x0f, 0x7e, 0x07, 0xbf, 0x6f, 0x39, 0x48, 0x22, 0x07, - 0x1a, 0x3a, 0x94, 0x06, 0x58, 0x69, 0x50, 0x19, 0x54, 0x90, 0xe1, 0xd1, 0xd9, 0x29, 0x72, 0x4b, 0xa2, 0x0a, 0x0c, - 0x35, 0xf5, 0xd4, 0x51, 0x99, 0x00, 0xaf, 0x40, 0xed, 0x07, 0x67, 0x15, 0x21, 0xfa, 0x6b, 0x49, 0x0b, 0xea, 0x14, - 0xe9, 0xf3, 0x4b, 0x0b, 0x40, 0xec, 0x2f, 0x22, 0xdd, 0x69, 0xf8, 0xa4, 0xee, 0x3b, 0x32, 0x00, 0xae, 0x7c, 0x03, - 0x22, 0x20, 0x92, 0xb8, 0xb3, 0x0c, 0x5a, 0xc9, 0x4f, 0xe4, 0x3a, 0x27, 0x51, 0xaa, 0x8b, 0xb2, 0x02, 0x74, 0x6b, - 0x28, 0xe9, 0x2f, 0xda, 0xd1, 0x84, 0xd7, 0xcf, 0x77, 0x38, 0x16, 0xe8, 0x9f, 0x8e, 0xff, 0xb5, 0x40, 0x5a, 0x1a, - 0x02, 0xd7, 0x5b, 0x65, 0x18, 0xd4, 0x77, 0x8a, 0xc0, 0xbc, 0x44, 0xa5, 0x01, 0x25, 0x01, 0xeb, 0x95, 0xfa, 0xfb, - 0x6f, 0x75, 0xf4, 0x15, 0xa8, 0xdd, 0x3a, 0xfa, 0xa9, 0xe7, 0x7b, 0xf8, 0x83, 0xf4, 0x56, 0x3b, 0x40, 0x7f, 0x9c, - 0x67, 0xaa, 0x3f, 0x74, 0x76, 0x3d, 0x62, 0x30, 0x27, 0xe0, 0x82, 0x8c, 0x73, 0x92, 0x1f, 0xc1, 0x56, 0xfc, 0x0f, - 0x8b, 0x54, 0x63, 0xd2, 0xfd, 0xa3, 0x15, 0x78, 0x0d, 0x5d, 0x6a, 0x72, 0x4e, 0xe1, 0x0a, 0xa8, 0x1c, 0xaa, 0xeb, - 0x9c, 0x8a, 0x95, 0x64, 0xe6, 0xbf, 0xac, 0x60, 0xf3, 0xa8, 0x14, 0xa7, 0xcb, 0x0f, 0xaf, 0x5c, 0x62, 0xed, 0xc9, - 0xc5, 0x2f, 0x6e, 0x18, 0x9f, 0x52, 0xef, 0xce, 0xf7, 0xd4, 0x93, 0x0f, 0x3b, 0x26, 0x3f, 0xc0, 0x4f, 0x1f, 0xf6, - 0x9d, 0xe5, 0x94, 0x4f, 0x3f, 0xf9, 0xa5, 0xdf, 0xea, 0xd7, 0x3c, 0xf7, 0x03, 0x77, 0x66, 0x3b, 0xec, 0x1f, 0x09, - 0x6f, 0xa6, 0xcb, 0xbb, 0x86, 0x65, 0xeb, 0x15, 0x93, 0xaf, 0x97, 0x42, 0x9f, 0xfe, 0xe2, 0xfa, 0xa3, 0x07, 0xee, - 0x3d, 0x87, 0x92, 0x66, 0x1c, 0xd5, 0xb9, 0x39, 0x6b, 0xb0, 0xa5, 0x6d, 0x1c, 0x4d, 0x82, 0xad, 0x81, 0x30, 0x19, - 0x1a, 0xa1, 0x89, 0x0a, 0x7a, 0xed, 0x82, 0x52, 0xc1, 0x50, 0x9a, 0xe3, 0xb8, 0x7e, 0x32, 0x09, 0x84, 0xda, 0x22, - 0xa2, 0x6e, 0x4d, 0xab, 0x6c, 0x7c, 0xb0, 0x10, 0x70, 0x06, 0x15, 0xc6, 0x90, 0xdc, 0xeb, 0x0e, 0x04, 0xa6, 0x90, - 0x34, 0xc4, 0xf8, 0x53, 0xf9, 0x38, 0x8a, 0xe2, 0xba, 0x0a, 0x5f, 0x1f, 0xdc, 0x74, 0xe3, 0x94, 0xa3, 0x84, 0x8a, - 0xf2, 0x8e, 0x04, 0x6a, 0x8a, 0x16, 0x6c, 0x29, 0x32, 0x97, 0x23, 0x16, 0xc9, 0x9d, 0xc6, 0xe5, 0x18, 0x42, 0x41, - 0x3a, 0xd0, 0xe9, 0xc4, 0x4a, 0x21, 0xb1, 0x55, 0x21, 0x24, 0x08, 0xcd, 0x6e, 0xcb, 0x6b, 0x15, 0x50, 0x4e, 0xea, - 0xdf, 0xd3, 0x16, 0xf8, 0xba, 0x97, 0xe7, 0xf8, 0xa6, 0x95, 0xce, 0xab, 0xdc, 0xf3, 0xfc, 0xe0, 0xf9, 0xed, 0xf6, - 0x7b, 0x7c, 0x34, 0x63, 0xd5, 0x84, 0x8d, 0x1f, 0xf7, 0x31, 0x21, 0xd4, 0x02, 0x55, 0x04, 0x08, 0xad, 0xb2, 0x06, - 0xd6, 0x75, 0xc8, 0x2c, 0xa1, 0xe1, 0xeb, 0x9f, 0x3a, 0xe4, 0x88, 0x1b, 0x6c, 0xc2, 0x9b, 0xb0, 0xc8, 0xc3, 0x51, - 0x47, 0x7b, 0x03, 0xae, 0xb5, 0x70, 0x40, 0x29, 0x50, 0x67, 0x4b, 0xce, 0x12, 0x41, 0xd4, 0x2d, 0xb3, 0x30, 0x55, - 0xe9, 0x2c, 0xaf, 0x3c, 0x3f, 0x82, 0x5e, 0xb3, 0xbf, 0xd6, 0x49, 0xf0, 0xe4, 0xe9, 0x6c, 0x69, 0x6d, 0x43, 0x81, - 0x9b, 0xd2, 0x2a, 0x9f, 0xac, 0x6d, 0x3c, 0xfa, 0xb1, 0x4f, 0x92, 0x12, 0xba, 0xc4, 0x27, 0x41, 0xea, 0x93, 0xbc, - 0x4b, 0x4b, 0xd7, 0x87, 0x2e, 0xb9, 0x36, 0x54, 0x35, 0x77, 0x23, 0xa6, 0xf2, 0xc3, 0x1b, 0x9a, 0x77, 0xf2, 0x2d, - 0xd2, 0xfd, 0x00, 0xff, 0xfb, 0xb0, 0x33, 0x4e, 0xf9, 0xef, 0x27, 0xff, 0x94, 0x47, 0x76, 0x1d, 0x42, 0xb5, 0x97, - 0x29, 0x78, 0xdf, 0xe6, 0xa3, 0x5f, 0xae, 0xad, 0x46, 0x71, 0x3d, 0xfe, 0xd9, 0xaf, 0x42, 0xf5, 0xf4, 0x17, 0xcb, - 0x8c, 0x4b, 0xdf, 0x4e, 0xd9, 0xcc, 0x2f, 0x8e, 0x39, 0xf3, 0xdc, 0x70, 0xd3, 0x2d, 0xda, 0x90, 0x5e, 0x21, 0xec, - 0xd4, 0xe5, 0x49, 0x17, 0x7d, 0xae, 0x88, 0x7b, 0x71, 0x12, 0x45, 0x0f, 0x51, 0x16, 0x87, 0xd6, 0x94, 0xd3, 0xcc, - 0xec, 0xa3, 0x58, 0x37, 0x1d, 0x29, 0x60, 0x08, 0x17, 0xb0, 0xe0, 0x17, 0x9f, 0x69, 0x3c, 0x63, 0x73, 0xe6, 0xf0, - 0x3f, 0x78, 0x50, 0xb2, 0xcc, 0x19, 0x0f, 0xf2, 0x55, 0x2d, 0x59, 0xbe, 0xe9, 0x60, 0xed, 0xe4, 0x7e, 0x00, 0x7f, - 0x99, 0x59, 0xd3, 0xe1, 0x92, 0x7e, 0x9b, 0xdd, 0xfa, 0x83, 0xd6, 0x52, 0x1e, 0x74, 0x10, 0xb4, 0xd6, 0xa7, 0xfd, - 0x4d, 0x4c, 0xea, 0x03, 0xbe, 0xd5, 0x1c, 0x6c, 0x97, 0xee, 0x9c, 0x47, 0x33, 0x45, 0xfb, 0x95, 0x69, 0x6e, 0xef, - 0xf0, 0x3a, 0x13, 0xad, 0x88, 0xb8, 0x3c, 0x54, 0xf1, 0xd9, 0x0d, 0xe7, 0xc8, 0xcc, 0xee, 0x70, 0x9f, 0x1e, 0x28, - 0x1e, 0x90, 0xcd, 0x15, 0xda, 0x79, 0xf0, 0x10, 0xab, 0xcd, 0x3c, 0xd4, 0x8e, 0xf9, 0xde, 0x74, 0x6e, 0x18, 0xaf, - 0x0c, 0xae, 0x49, 0xa3, 0xe0, 0x7a, 0xbe, 0x35, 0xde, 0x3d, 0x93, 0x3a, 0xea, 0x6c, 0x47, 0x1b, 0xd0, 0x2a, 0xb5, - 0x6b, 0xb2, 0x7a, 0x47, 0xb4, 0x9b, 0xc5, 0xbf, 0x5f, 0x85, 0xeb, 0x7b, 0x07, 0x7b, 0x7e, 0xe3, 0x30, 0x94, 0xa3, - 0x0f, 0xb1, 0xbb, 0xca, 0xff, 0x14, 0x2d, 0xab, 0x6e, 0xad, 0xbb, 0x3a, 0xed, 0xde, 0x49, 0xba, 0xa4, 0xac, 0x8f, - 0x60, 0x30, 0x39, 0x39, 0x77, 0x1d, 0xa5, 0x42, 0x3f, 0x86, 0x9f, 0xa4, 0xbc, 0x3c, 0x5d, 0x1f, 0xd6, 0x79, 0x09, - 0xbd, 0x70, 0xd8, 0x49, 0xeb, 0x1f, 0xbf, 0x5f, 0xe0, 0x13, 0x98, 0x9a, 0x5e, 0x37, 0xa3, 0x61, 0x51, 0x48, 0xda, - 0x1f, 0xc3, 0xce, 0xa5, 0xf1, 0x1b, 0xaa, 0xff, 0xe0, 0xa8, 0x22, 0xb8, 0x3a, 0x2e, 0xb5, 0xa2, 0x8a, 0xef, 0xb3, - 0x4d, 0xdd, 0x62, 0x41, 0xd8, 0xbf, 0x13, 0x39, 0x6a, 0x0c, 0x35, 0x55, 0x5c, 0x5b, 0x54, 0x04, 0x04, 0x89, 0x8b, - 0xfc, 0x5c, 0x3c, 0xac, 0xba, 0x17, 0xbc, 0x29, 0x2a, 0xd0, 0xed, 0x2b, 0x04, 0x55, 0x4e, 0x0a, 0xa6, 0x99, 0xec, - 0x5c, 0x17, 0x7d, 0x5a, 0x7f, 0xda, 0x52, 0xe8, 0x81, 0x70, 0x4c, 0x58, 0x82, 0x85, 0x8a, 0x3b, 0xc8, 0xc1, 0xd3, - 0xe3, 0xf6, 0x82, 0x1f, 0xab, 0x18, 0xed, 0xf8, 0x44, 0x32, 0x07, 0xeb, 0x92, 0x71, 0x03, 0x0f, 0x8e, 0x95, 0x86, - 0xe1, 0x58, 0x01, 0x70, 0x68, 0x76, 0x75, 0x22, 0x7f, 0x68, 0x46, 0xf0, 0x57, 0x24, 0x43, 0xeb, 0x12, 0x35, 0x85, - 0x06, 0xd6, 0x32, 0x7a, 0xae, 0x98, 0x78, 0x31, 0x05, 0x9d, 0x80, 0x20, 0xcb, 0x93, 0x43, 0x7a, 0xb8, 0x8b, 0x64, - 0x51, 0xbd, 0x67, 0x17, 0x8b, 0x48, 0x97, 0x81, 0x06, 0xd3, 0x20, 0xa4, 0xc3, 0x6a, 0xba, 0x6a, 0x6f, 0xee, 0x91, - 0xa5, 0x79, 0x4c, 0x8c, 0x95, 0x86, 0x9e, 0xd5, 0x38, 0xb0, 0xe1, 0x96, 0x09, 0x0b, 0x87, 0xc4, 0xd1, 0xc9, 0x61, - 0x15, 0x91, 0xa0, 0x59, 0xdf, 0x82, 0xac, 0x74, 0x00, 0x1b, 0xf0, 0x30, 0xaf, 0x2e, 0xb1, 0xbb, 0x6d, 0xcd, 0x22, - 0x9e, 0x59, 0x86, 0x61, 0x5d, 0xfc, 0xa7, 0xae, 0x39, 0x61, 0xfb, 0xdf, 0x3c, 0x1e, 0x1e, 0x8b, 0xae, 0x36, 0x16, - 0x4b, 0xb1, 0x07, 0x3d, 0xa2, 0xfb, 0xc3, 0xc7, 0xc3, 0x9b, 0xc0, 0x24, 0x3e, 0xe9, 0x67, 0x16, 0x34, 0x13, 0xdb, - 0xd9, 0xe8, 0x09, 0xfb, 0x68, 0x9b, 0x62, 0x87, 0x54, 0x60, 0x51, 0xd3, 0xd9, 0x09, 0xd5, 0x69, 0x68, 0x24, 0x69, - 0x86, 0x50, 0x58, 0xed, 0x0d, 0x7e, 0x11, 0x62, 0x6f, 0xaf, 0xfb, 0x7b, 0x0e, 0x62, 0x2d, 0x06, 0xa8, 0x41, 0x4d, - 0x8b, 0xc4, 0xee, 0xd2, 0xdd, 0x33, 0x5e, 0x02, 0x55, 0x1d, 0x95, 0x43, 0x0a, 0xb3, 0x5c, 0x8c, 0x68, 0x43, 0x27, - 0x59, 0x62, 0x1d, 0x93, 0xa9, 0x94, 0xb8, 0xfe, 0xbb, 0x04, 0x12, 0x14, 0x1e, 0xd9, 0x91, 0x70, 0xcb, 0x9f, 0x27, - 0xfc, 0xf9, 0x0b, 0xb6, 0x1a, 0x6c, 0xa7, 0x00, 0x5c, 0x3e, 0xfa, 0xfc, 0x0e, 0xe4, 0x2f, 0x54, 0x0c, 0xfc, 0xbc, - 0x70, 0xc2, 0x0b, 0xf0, 0x4f, 0xb0, 0x14, 0x89, 0xe9, 0x5e, 0x4a, 0xf3, 0x14, 0x6b, 0x98, 0x40, 0xaf, 0xcb, 0x7e, - 0xd9, 0x02, 0x87, 0x11, 0xc4, 0xa5, 0xee, 0xdb, 0x05, 0xb4, 0x51, 0x01, 0x28, 0x8b, 0x6a, 0xe0, 0x58, 0xc7, 0xdb, - 0x26, 0x45, 0xdc, 0xf4, 0xab, 0x04, 0x99, 0xd1, 0x2b, 0xb1, 0xb8, 0x0c, 0x5d, 0x5b, 0x39, 0x4e, 0x53, 0xf4, 0x99, - 0x0c, 0x36, 0xcc, 0x3a, 0x15, 0x81, 0x99, 0xf4, 0xf0, 0xa0, 0x6f, 0xd3, 0x9a, 0x6f, 0xd7, 0xf5, 0xf2, 0x6e, 0x93, - 0x5f, 0x77, 0x7c, 0xf9, 0xea, 0xc9, 0x85, 0x94, 0x48, 0x5b, 0xa0, 0x5b, 0xaa, 0xa7, 0xc5, 0xd6, 0xba, 0xd1, 0xf4, - 0xb8, 0xc2, 0xf0, 0x50, 0x19, 0x4d, 0xfd, 0x69, 0x52, 0x98, 0xcd, 0x16, 0xdd, 0xe8, 0x63, 0xff, 0x4a, 0x02, 0x0d, - 0x96, 0x2d, 0xf5, 0xde, 0x9b, 0x05, 0x0b, 0x7a, 0xeb, 0x20, 0x6b, 0xb9, 0xca, 0x91, 0x7b, 0x42, 0x51, 0x5d, 0x20, - 0x28, 0xf2, 0xb0, 0x48, 0x2b, 0xdc, 0x99, 0xbd, 0xcc, 0x06, 0xf4, 0x21, 0xe3, 0x4a, 0xee, 0x9c, 0x03, 0x25, 0xd3, - 0xe6, 0x4d, 0x7a, 0xef, 0x2f, 0x76, 0x7a, 0xec, 0xde, 0x41, 0x86, 0xe5, 0xff, 0x8d, 0xea, 0x6a, 0xbe, 0x25, 0x45, - 0x0a, 0x8f, 0xa2, 0x7d, 0xac, 0x4a, 0xe1, 0x3b, 0xc2, 0x56, 0x0a, 0x54, 0x07, 0xda, 0x57, 0xa4, 0x2e, 0x61, 0x6e, - 0xd6, 0x41, 0x60, 0x65, 0x3a, 0xfc, 0x2b, 0x52, 0x03, 0x7e, 0xb3, 0x05, 0x44, 0x88, 0x9d, 0xec, 0x21, 0x7c, 0x14, - 0x00, 0xc7, 0x15, 0x00, 0xcd, 0x88, 0xdc, 0xe0, 0xe4, 0xe0, 0x21, 0xee, 0x8f, 0x57, 0x77, 0x59, 0x51, 0xe1, 0xbd, - 0x45, 0x58, 0x07, 0xf0, 0xd7, 0x72, 0xb8, 0x9e, 0x97, 0xfe, 0xc2, 0x87, 0xea, 0x09, 0x2a, 0x77, 0xee, 0xeb, 0x82, - 0xa1, 0x3c, 0x95, 0x38, 0x36, 0xd0, 0x55, 0x79, 0x6b, 0xaf, 0xb4, 0x99, 0x04, 0xbb, 0x1b, 0xa1, 0xa9, 0x0e, 0xa3, - 0x21, 0x6e, 0x7e, 0x5b, 0xd9, 0xfa, 0xc3, 0xc5, 0xed, 0x9f, 0xdf, 0x9d, 0x0b, 0x3f, 0xc0, 0x25, 0x06, 0x6c, 0xea, - 0x20, 0xc4, 0x7e, 0xe7, 0xdc, 0x04, 0x42, 0x88, 0x3d, 0x06, 0x93, 0x29, 0x62, 0x26, 0x34, 0x95, 0xa3, 0x10, 0x82, - 0x49, 0xde, 0x52, 0x6d, 0xc8, 0x85, 0x07, 0xd9, 0x21, 0x33, 0x65, 0x6a, 0x13, 0xc2, 0x26, 0xdc, 0xb6, 0x8d, 0x75, - 0x73, 0x65, 0x31, 0x36, 0x77, 0x5b, 0x7d, 0x61, 0x45, 0xe8, 0xed, 0x5d, 0xdf, 0xea, 0xdc, 0xee, 0x9a, 0xfc, 0x08, - 0x3a, 0x64, 0xef, 0x8a, 0x0a, 0x07, 0xbb, 0x93, 0xd3, 0x45, 0xd2, 0x6c, 0x08, 0x24, 0x16, 0x08, 0x81, 0x5f, 0x68, - 0x68, 0x86, 0x8c, 0xf1, 0xc8, 0x2b, 0xdf, 0xb8, 0x2a, 0x3b, 0xf6, 0x12, 0x54, 0xbd, 0x87, 0x98, 0x73, 0x9f, 0x86, - 0x75, 0x1c, 0xc9, 0x61, 0xea, 0x66, 0xe8, 0x87, 0xb0, 0xdd, 0x24, 0x71, 0x99, 0x8e, 0xe4, 0x3e, 0xbb, 0xbf, 0xf4, - 0x7c, 0x37, 0x6a, 0xe1, 0x22, 0xda, 0x14, 0x50, 0x8f, 0x48, 0x76, 0xea, 0xda, 0x8b, 0xf4, 0x63, 0x8e, 0xc4, 0x5d, - 0xd9, 0x5a, 0xd2, 0xfc, 0x28, 0xa0, 0x21, 0x3a, 0xa3, 0xf8, 0xd2, 0xcf, 0x46, 0x7b, 0x9a, 0xff, 0xea, 0x87, 0xab, - 0xb3, 0xff, 0xd1, 0xae, 0x44, 0xa1, 0xe2, 0xc9, 0x31, 0xd0, 0x36, 0x5f, 0x92, 0x72, 0x1d, 0x4b, 0x64, 0x9c, 0xd7, - 0x86, 0x77, 0xcb, 0x06, 0x82, 0x3d, 0xea, 0x1c, 0xd1, 0xfa, 0x05, 0x76, 0x08, 0xdd, 0xd9, 0xd1, 0x40, 0xd7, 0x1e, - 0xfa, 0xe7, 0xfa, 0xdf, 0xfe, 0xe7, 0xd6, 0xae, 0x52, 0x6a, 0xa9, 0x1e, 0x72, 0x47, 0xe5, 0x25, 0x09, 0xd1, 0x01, - 0xa8, 0x48, 0x23, 0x70, 0x5f, 0x6e, 0xad, 0xf9, 0x5d, 0x59, 0x67, 0xfe, 0xa7, 0x05, 0x63, 0x24, 0x72, 0x7a, 0x43, - 0x48, 0xd8, 0x84, 0x24, 0x8e, 0x9d, 0xeb, 0x8c, 0xb3, 0xa4, 0x69, 0x11, 0xba, 0xba, 0x53, 0x8f, 0x04, 0xcb, 0x93, - 0x36, 0xcb, 0xb8, 0x21, 0x5b, 0x6e, 0xbb, 0x49, 0xfa, 0xe8, 0xe7, 0xae, 0xd5, 0x5c, 0x01, 0x41, 0x50, 0xb5, 0x2c, - 0x2f, 0x8d, 0xc8, 0xab, 0x0d, 0xf7, 0x65, 0xf9, 0x6b, 0xf7, 0x53, 0x18, 0x69, 0x51, 0x1b, 0x9c, 0x72, 0xd6, 0xad, - 0x7a, 0x50, 0x2d, 0x45, 0x19, 0x59, 0xf5, 0x21, 0xfa, 0x4f, 0x70, 0x83, 0x97, 0x77, 0x37, 0x47, 0x2f, 0xa6, 0x16, - 0x5e, 0x70, 0x24, 0x67, 0xe2, 0xee, 0xfc, 0x28, 0x4b, 0xec, 0x65, 0xd0, 0x97, 0x88, 0xea, 0x9c, 0x18, 0x6f, 0x8a, - 0x67, 0x06, 0xa2, 0xdb, 0xd4, 0xf7, 0x4d, 0x70, 0x90, 0xf1, 0x0d, 0xb2, 0x3f, 0x27, 0x48, 0x4e, 0x7d, 0xa2, 0xf1, - 0x32, 0x98, 0xb6, 0x23, 0x05, 0xc7, 0xc7, 0x76, 0x0f, 0x38, 0xde, 0xc8, 0xe5, 0x42, 0xf5, 0xad, 0xbb, 0xff, 0xc3, - 0xea, 0x61, 0x76, 0x06, 0xc7, 0x9d, 0x4d, 0xcb, 0x04, 0xaf, 0x58, 0xe2, 0x4f, 0xb5, 0x89, 0xdd, 0x9e, 0x4d, 0xba, - 0xe3, 0x72, 0x7b, 0x38, 0xbb, 0x0b, 0xad, 0x51, 0xee, 0x36, 0x7f, 0x01, 0x48, 0x21, 0xd0, 0x86, 0xfd, 0xa2, 0x70, - 0x10, 0xd4, 0x00, 0x1f, 0x00, 0x23, 0xb4, 0xc4, 0x62, 0x45, 0x9e, 0x68, 0x28, 0xad, 0x72, 0x46, 0x4c, 0x83, 0xe7, - 0x83, 0x77, 0x95, 0xc4, 0xa5, 0xf4, 0x77, 0x61, 0x73, 0x4b, 0x89, 0xcf, 0x9c, 0x7e, 0x7c, 0x9b, 0xea, 0xbb, 0x2e, - 0x39, 0x5b, 0xbe, 0xf7, 0x9c, 0x56, 0x1a, 0x3a, 0xb8, 0x83, 0x8f, 0xd5, 0x16, 0x42, 0x36, 0x6e, 0xa0, 0xdb, 0xec, - 0x0f, 0xb9, 0x67, 0xe7, 0xa9, 0x62, 0x4f, 0xb2, 0x5c, 0x58, 0xac, 0x08, 0x17, 0xae, 0xde, 0x2d, 0x02, 0x58, 0x90, - 0xef, 0x43, 0x1f, 0xcb, 0xac, 0xe4, 0xc7, 0x0f, 0xfc, 0xcf, 0x83, 0x00, 0x8b, 0x92, 0xe5, 0x34, 0xa1, 0xca, 0x9d, - 0x41, 0xcc, 0xb3, 0x9e, 0x91, 0x35, 0x9b, 0x7c, 0xe8, 0x00}; + 0x5b, 0x90, 0x7a, 0x53, 0xc1, 0x6e, 0xc1, 0x56, 0x6f, 0x00, 0x79, 0xaf, 0xf6, 0x6d, 0x2b, 0x05, 0x44, 0x11, 0x6c, + 0x9c, 0x06, 0x03, 0x82, 0x71, 0xa5, 0x64, 0xba, 0x39, 0x78, 0xe4, 0x76, 0x00, 0x6c, 0xbb, 0xaa, 0xb6, 0x41, 0xaa, + 0x9a, 0x70, 0x54, 0x0e, 0x31, 0xb1, 0x27, 0x5a, 0x0c, 0xe6, 0x4f, 0xe4, 0x1a, 0x89, 0x16, 0xe8, 0x24, 0x0c, 0xc4, + 0xa0, 0x60, 0x71, 0x7b, 0x07, 0x92, 0xb2, 0x62, 0xb6, 0x5c, 0x32, 0xac, 0x0d, 0x63, 0xd8, 0x38, 0xf8, 0xf0, 0x15, + 0xdd, 0xce, 0xfe, 0x4e, 0x15, 0x9d, 0xab, 0xfb, 0x0e, 0x21, 0x59, 0x85, 0x78, 0xe1, 0xae, 0xca, 0x1f, 0x7a, 0x37, + 0xc2, 0x07, 0x0d, 0xc2, 0x31, 0x1f, 0x88, 0x73, 0x48, 0x2a, 0x4c, 0xba, 0xd2, 0xbd, 0x41, 0xc1, 0xe2, 0x9d, 0x07, + 0x35, 0xb2, 0xf3, 0xee, 0xab, 0xbf, 0x18, 0xc2, 0xf6, 0xaa, 0xb0, 0x9f, 0xb5, 0xd2, 0xfa, 0x3f, 0xf6, 0x7d, 0x54, + 0x0b, 0xb3, 0xd2, 0xab, 0x5f, 0x04, 0x6e, 0xfc, 0x69, 0xbd, 0x97, 0x2e, 0xb2, 0x64, 0x16, 0xef, 0x3e, 0x91, 0x2b, + 0x71, 0x11, 0xbe, 0xcd, 0xb8, 0x53, 0x58, 0x09, 0xdb, 0x0f, 0x9b, 0x37, 0x7d, 0x0d, 0x07, 0x83, 0x1b, 0x9b, 0xc5, + 0xa1, 0xa2, 0xe7, 0xc8, 0x8e, 0x39, 0x27, 0x54, 0x9d, 0x10, 0x84, 0x65, 0x80, 0xed, 0x72, 0x63, 0x84, 0x60, 0x65, + 0x09, 0x3d, 0x91, 0xd0, 0x17, 0xe9, 0x5b, 0x6f, 0xa9, 0xff, 0x5f, 0xbf, 0x19, 0xbe, 0x8d, 0x2c, 0x45, 0xbe, 0xa4, + 0xee, 0xb2, 0x8e, 0xab, 0xf6, 0x25, 0xb1, 0x13, 0xcf, 0x4b, 0x29, 0x70, 0xf3, 0x70, 0x1a, 0x71, 0xeb, 0x60, 0x02, + 0x80, 0xb6, 0x64, 0x56, 0x7e, 0x96, 0xa9, 0xdf, 0x79, 0x7a, 0x39, 0xd9, 0x2f, 0x99, 0x06, 0xff, 0x44, 0x32, 0x0f, + 0x49, 0x5e, 0x9a, 0x51, 0x37, 0x3b, 0xfb, 0xea, 0x76, 0x1c, 0x8c, 0x90, 0x44, 0x3f, 0x06, 0x17, 0x50, 0x96, 0xaa, + 0xbd, 0x5f, 0x7a, 0xef, 0xaf, 0xf5, 0xfd, 0xd7, 0x2f, 0x5d, 0xbd, 0x98, 0x7a, 0x54, 0x54, 0x66, 0xf6, 0xc2, 0xc0, + 0xdd, 0x76, 0xe7, 0x2e, 0x2b, 0xed, 0xa5, 0x51, 0x22, 0x72, 0x9a, 0x0e, 0x3e, 0x12, 0x5b, 0x1c, 0xc8, 0x2c, 0x36, + 0xad, 0x5e, 0xff, 0xd9, 0xc6, 0xde, 0xf5, 0x2f, 0x57, 0xd3, 0x1a, 0x69, 0xe5, 0x0a, 0xe3, 0xd8, 0x0a, 0x88, 0x38, + 0x12, 0x2b, 0xcb, 0xa4, 0xf8, 0x6a, 0xf6, 0xed, 0x74, 0x85, 0x3d, 0xf9, 0x75, 0x53, 0x96, 0xb5, 0xff, 0x7b, 0xbe, + 0x86, 0x1b, 0x47, 0xce, 0x65, 0xb3, 0x5a, 0xcf, 0xc4, 0x52, 0x94, 0x87, 0x12, 0x77, 0x36, 0x60, 0xdf, 0x57, 0xb5, + 0xaf, 0xdf, 0x23, 0x5f, 0x9e, 0x0f, 0xce, 0x24, 0x3b, 0x36, 0x75, 0x59, 0x4e, 0x87, 0x73, 0xc9, 0x5b, 0x75, 0xaf, + 0xd5, 0xf9, 0xc5, 0xac, 0x8c, 0x54, 0x48, 0x14, 0x20, 0x21, 0xd0, 0x29, 0x79, 0xdf, 0x57, 0x7d, 0xff, 0xeb, 0x5b, + 0x3a, 0x29, 0x0a, 0x95, 0xb2, 0x2b, 0xa8, 0x63, 0xa2, 0xe3, 0x75, 0x6c, 0xdf, 0x39, 0xfc, 0x18, 0x1a, 0xb2, 0x94, + 0xc3, 0x80, 0xbe, 0x24, 0x95, 0x09, 0xf8, 0xff, 0xfa, 0x9a, 0xbd, 0xff, 0xef, 0x9f, 0x2f, 0x89, 0x68, 0x95, 0xd8, + 0xd4, 0x2a, 0x4a, 0xb2, 0xe7, 0x73, 0x48, 0xd2, 0xd3, 0x9b, 0xc7, 0x76, 0x85, 0xc0, 0xba, 0xdc, 0x6e, 0x7a, 0x80, + 0x0e, 0x40, 0x9e, 0xb2, 0xf6, 0x31, 0x97, 0x55, 0xf5, 0x16, 0x15, 0x12, 0xf1, 0xeb, 0xf6, 0xfd, 0x8c, 0xfb, 0x98, + 0x6e, 0x60, 0x06, 0xc3, 0x46, 0x9e, 0x13, 0x8c, 0xeb, 0xf9, 0x69, 0xea, 0xe7, 0xe9, 0x2a, 0x78, 0x61, 0x23, 0x4f, + 0x7e, 0x1c, 0x0f, 0xab, 0x28, 0x12, 0x09, 0xd3, 0xda, 0x39, 0x9d, 0xdb, 0xf5, 0xd3, 0xfa, 0xf6, 0x79, 0x78, 0x48, + 0x3e, 0xa0, 0x56, 0xdf, 0xf0, 0xfb, 0x5f, 0x6f, 0xba, 0xfe, 0xeb, 0xd7, 0xee, 0xe2, 0x89, 0x73, 0xd1, 0x91, 0x52, + 0x09, 0x6f, 0xbd, 0x9a, 0x4b, 0xb3, 0xac, 0xf5, 0xc8, 0x52, 0x38, 0xac, 0x2a, 0xd7, 0x60, 0xac, 0x26, 0xa3, 0x19, + 0x23, 0xbb, 0xd4, 0x9d, 0x41, 0xc1, 0x6a, 0xfb, 0xd4, 0xb7, 0xf7, 0x8b, 0x52, 0x6b, 0xaa, 0x86, 0x85, 0x26, 0x1a, + 0x47, 0xb6, 0x43, 0x90, 0x4d, 0xbc, 0xfd, 0x26, 0x09, 0x1e, 0x02, 0x5a, 0xc2, 0xec, 0xb0, 0x56, 0x0f, 0xbc, 0x2b, + 0x52, 0xd7, 0x76, 0xad, 0x70, 0xf9, 0xa6, 0xfa, 0x5f, 0xbf, 0x91, 0x87, 0x33, 0xa5, 0x7a, 0xd2, 0xed, 0x3b, 0xbe, + 0x94, 0x8b, 0xb9, 0xda, 0x9a, 0x8e, 0x5e, 0x22, 0xe7, 0xf2, 0x64, 0xd0, 0xc5, 0xcd, 0x04, 0x04, 0xf0, 0x76, 0x17, + 0x24, 0x20, 0x8d, 0x0b, 0x14, 0x36, 0x44, 0x82, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, 0x34, 0x55, 0x84, + 0xc8, 0x6e, 0x80, 0x1c, 0x67, 0xd8, 0xb2, 0x7e, 0xdf, 0x59, 0x59, 0x05, 0xaa, 0x01, 0x92, 0x3d, 0xce, 0xac, 0xa4, + 0xb5, 0x16, 0x9b, 0x8a, 0x6b, 0xde, 0x65, 0x7e, 0x17, 0x9d, 0xf1, 0xc3, 0xb0, 0xc2, 0x64, 0x36, 0xd2, 0xd5, 0xb0, + 0x6c, 0x57, 0x96, 0xd3, 0x00, 0x20, 0x78, 0xdf, 0xfb, 0x3f, 0x0a, 0xff, 0xff, 0xc8, 0xe2, 0x44, 0x44, 0x16, 0xa8, + 0xc8, 0xac, 0xe2, 0x9c, 0xac, 0x02, 0x66, 0x54, 0x05, 0x70, 0x46, 0x05, 0xb0, 0x8f, 0x0e, 0xc8, 0xb1, 0x20, 0x68, + 0x34, 0x4d, 0x77, 0x34, 0xec, 0x96, 0xf7, 0x2b, 0x2d, 0x56, 0x1c, 0xca, 0xf5, 0x8c, 0x6c, 0x4b, 0x7e, 0xb7, 0x03, + 0x65, 0xcd, 0x52, 0x5a, 0xe9, 0xe8, 0x7f, 0xd7, 0xd4, 0xb6, 0x1b, 0x3b, 0x02, 0xd5, 0x37, 0x95, 0x0a, 0x21, 0xfb, + 0x7f, 0x52, 0xf8, 0x29, 0x61, 0x52, 0x4c, 0x86, 0xb9, 0x1b, 0xdd, 0x8d, 0xd0, 0xcd, 0x4a, 0x04, 0x25, 0x66, 0x36, + 0x46, 0xe4, 0xa0, 0x24, 0x70, 0xa0, 0xfa, 0x5f, 0x21, 0xd9, 0x6c, 0xda, 0x6e, 0x43, 0xb5, 0x73, 0x33, 0x3b, 0xf2, + 0xf9, 0x15, 0x33, 0x96, 0x10, 0xd3, 0x20, 0x6c, 0xda, 0x73, 0xf4, 0xcd, 0x8f, 0xd6, 0x9e, 0xbe, 0xb3, 0x6a, 0x92, + 0xd4, 0x5d, 0x7e, 0x0b, 0xff, 0x61, 0x80, 0x61, 0xe0, 0xec, 0x5b, 0x16, 0xd3, 0xec, 0x26, 0xfe, 0xba, 0x16, 0x0d, + 0x21, 0x44, 0x08, 0xd4, 0xb6, 0x43, 0xe6, 0xfa, 0xef, 0xbc, 0xb5, 0x3d, 0x71, 0x77, 0x7f, 0x13, 0x42, 0x4a, 0x63, + 0x52, 0x2a, 0x98, 0x71, 0x5f, 0x4c, 0x7d, 0xea, 0xb9, 0x75, 0xdc, 0x34, 0xa9, 0x9b, 0x99, 0xd9, 0xad, 0x45, 0x51, + 0x14, 0xaf, 0x13, 0x04, 0x40, 0xe5, 0x2f, 0x63, 0x62, 0xfd, 0xe8, 0xba, 0xd1, 0xff, 0xad, 0xc8, 0x96, 0x11, 0x86, + 0x08, 0x49, 0xac, 0x6b, 0x25, 0xd8, 0xdc, 0x18, 0x45, 0x9c, 0x5b, 0x1b, 0xc0, 0x8e, 0x8e, 0xd1, 0x6c, 0x41, 0x55, + 0xa0, 0xb1, 0xcd, 0x1d, 0xfc, 0x7c, 0x51, 0x00, 0xa6, 0x91, 0x1e, 0x4a, 0xde, 0x19, 0x9f, 0x10, 0x43, 0x0f, 0x19, + 0x5c, 0x78, 0x74, 0xe4, 0x81, 0x49, 0x75, 0x60, 0x44, 0x7f, 0xe9, 0xe6, 0x96, 0xb0, 0x06, 0x9e, 0x69, 0xb9, 0xe4, + 0x37, 0x82, 0xde, 0xe9, 0x7b, 0x00, 0x62, 0x12, 0x28, 0xd5, 0xed, 0x17, 0x6c, 0x0b, 0x4c, 0x8f, 0x9c, 0xa7, 0xbd, + 0x21, 0x29, 0x78, 0x70, 0xdc, 0xfd, 0xba, 0x0b, 0xa4, 0x5d, 0xca, 0x57, 0xec, 0x92, 0x61, 0xd6, 0xd1, 0x8d, 0xef, + 0xa6, 0xe8, 0x0a, 0xcd, 0x59, 0x0a, 0xea, 0x9c, 0xbb, 0x9e, 0x1b, 0xcb, 0x2f, 0x5a, 0x72, 0xfa, 0xb7, 0xa5, 0x8f, + 0xd9, 0xfb, 0xd2, 0x2f, 0xd4, 0x55, 0xf3, 0x2d, 0x70, 0x12, 0x00, 0xc8, 0xb2, 0x0f, 0x31, 0x2d, 0xc8, 0x92, 0xea, + 0x6b, 0xf9, 0xb9, 0x19, 0x6f, 0x35, 0x0d, 0x26, 0x68, 0x44, 0x36, 0x28, 0x00, 0xd8, 0xbb, 0xef, 0x9e, 0xbd, 0x5b, + 0x59, 0x4a, 0xe9, 0xd3, 0xec, 0x2f, 0xf3, 0xc0, 0x4b, 0xb3, 0x6c, 0x40, 0x8a, 0xb6, 0xa5, 0x1b, 0xf9, 0x50, 0x82, + 0x88, 0x86, 0xcd, 0x05, 0xcf, 0x46, 0x77, 0x6c, 0xe3, 0x51, 0x8b, 0x2f, 0xd6, 0xa8, 0x1c, 0x43, 0x83, 0xf8, 0x7a, + 0xe7, 0xdd, 0x4a, 0x85, 0x96, 0x94, 0xd7, 0xf8, 0x8e, 0xf6, 0x03, 0x26, 0x77, 0x6e, 0xe0, 0x03, 0x8d, 0xeb, 0xcf, + 0xe1, 0xaf, 0xed, 0xb9, 0x1c, 0x9a, 0x44, 0xa6, 0x97, 0xd9, 0x31, 0xce, 0x78, 0x76, 0x3f, 0x22, 0x09, 0x12, 0x8d, + 0xbe, 0xa8, 0x67, 0xfa, 0xf9, 0x5a, 0x73, 0x44, 0x8a, 0x50, 0xdf, 0xdf, 0x63, 0x17, 0xc8, 0x0b, 0xa7, 0x0b, 0xca, + 0xed, 0x7b, 0xdc, 0xff, 0x1c, 0x38, 0xda, 0x47, 0xf7, 0xf8, 0xdd, 0xea, 0x6e, 0x66, 0xdf, 0xbc, 0xc0, 0x63, 0x41, + 0x48, 0x9b, 0x20, 0x61, 0x98, 0xf9, 0xdd, 0x37, 0x11, 0x16, 0xef, 0x7b, 0x0b, 0x62, 0x35, 0xea, 0x4f, 0x7f, 0xfd, + 0xcb, 0x3e, 0xdd, 0xed, 0xf5, 0x88, 0x5f, 0x7f, 0x38, 0x78, 0x7a, 0x6f, 0x98, 0x86, 0xd5, 0x14, 0xda, 0x9e, 0xf5, + 0xcc, 0xf8, 0xb6, 0xad, 0xc2, 0xbe, 0xff, 0xf2, 0xf5, 0xe0, 0xae, 0xe7, 0x30, 0xb4, 0xee, 0x4e, 0x94, 0xc5, 0x23, + 0x86, 0x7f, 0x13, 0x24, 0xfd, 0x33, 0x27, 0xfd, 0xc2, 0xe7, 0x56, 0x80, 0x01, 0xba, 0xa5, 0xe6, 0x43, 0x6b, 0x8c, + 0x17, 0xbe, 0x41, 0x37, 0xc2, 0xc4, 0xfc, 0x0a, 0x4b, 0x29, 0x76, 0xde, 0xbf, 0x18, 0xd3, 0x27, 0xd6, 0x45, 0x4d, + 0x00, 0x44, 0x4a, 0x66, 0x13, 0xc0, 0xa0, 0x44, 0x06, 0x38, 0x1b, 0xc6, 0x75, 0xe9, 0x2e, 0xf4, 0xc8, 0xea, 0x66, + 0xd8, 0xc2, 0xfe, 0xcf, 0x17, 0x38, 0xc0, 0x27, 0xd6, 0x41, 0xc7, 0xcb, 0x4c, 0xc8, 0x1d, 0xb3, 0xe2, 0xff, 0xc7, + 0x4f, 0x6a, 0x72, 0x21, 0x96, 0xc2, 0x66, 0xb6, 0x75, 0x77, 0x8d, 0xdd, 0x48, 0x95, 0x89, 0xad, 0xcc, 0x8a, 0xea, + 0x5b, 0xa8, 0xe4, 0xf7, 0x4e, 0xee, 0x45, 0x95, 0xa2, 0xfa, 0x16, 0xc8, 0x96, 0x67, 0x78, 0xc7, 0xf1, 0xf5, 0x4f, + 0x03, 0xe2, 0xad, 0x94, 0x1c, 0xa5, 0x6a, 0x60, 0xc9, 0x93, 0x43, 0x3f, 0x6d, 0x50, 0x1e, 0x67, 0xa4, 0x0d, 0x38, + 0x72, 0x25, 0x7a, 0x66, 0xd0, 0xc8, 0xbb, 0x4e, 0x1e, 0x8b, 0x2a, 0xff, 0x2e, 0xf1, 0xfb, 0x4a, 0x6a, 0x11, 0x2c, + 0x19, 0xc9, 0x1d, 0x41, 0xcc, 0x16, 0xaa, 0x08, 0xed, 0x28, 0x9c, 0x48, 0x2b, 0x1e, 0xf1, 0x82, 0xf7, 0x7c, 0xbf, + 0x6d, 0x7b, 0x83, 0x84, 0x0b, 0x6f, 0x61, 0xf1, 0x2d, 0x3e, 0xc8, 0xf9, 0xe7, 0x72, 0xb2, 0x96, 0x8a, 0x9e, 0xb2, + 0x79, 0x9a, 0xd8, 0x52, 0xa2, 0x4b, 0x86, 0x40, 0x17, 0x54, 0x47, 0x6e, 0x98, 0x5c, 0x2f, 0x78, 0x7f, 0x83, 0xdb, + 0xe6, 0x17, 0x0b, 0x29, 0x5f, 0xcf, 0xcc, 0x6e, 0xeb, 0x01, 0x50, 0x75, 0xd8, 0x00, 0x3c, 0x65, 0xff, 0xdd, 0xe3, + 0x6e, 0xf2, 0x12, 0x61, 0xe1, 0xb1, 0x5b, 0x22, 0xed, 0xb2, 0x8f, 0x93, 0xa1, 0x57, 0x07, 0xf0, 0xf6, 0x44, 0x05, + 0x10, 0xb9, 0x8a, 0x39, 0x37, 0x9c, 0x88, 0xa4, 0xfe, 0x7d, 0xfa, 0x2d, 0x5d, 0xd8, 0xb0, 0x0d, 0x4d, 0xd0, 0x57, + 0x09, 0xaf, 0xa2, 0xf5, 0x8d, 0x8a, 0x5d, 0x8e, 0x00, 0x64, 0xad, 0x82, 0x99, 0x75, 0xdb, 0x10, 0xab, 0x93, 0x54, + 0x6e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd3, 0x1c, 0xb9, 0xa1, 0xea, 0x18, 0xff, 0xca, 0xd8, 0x9c, 0x4d, 0x34, 0x55, + 0xc3, 0xe2, 0x6f, 0x0d, 0xf2, 0x10, 0x2f, 0xfb, 0x88, 0x06, 0x3d, 0xca, 0xba, 0xe0, 0x1a, 0xb8, 0x0a, 0xf4, 0x92, + 0x1c, 0x3c, 0x73, 0x8d, 0x06, 0xc3, 0x1b, 0x63, 0x07, 0x02, 0x60, 0x93, 0x10, 0xca, 0x02, 0x5b, 0x2b, 0x1d, 0x54, + 0x75, 0xc7, 0xd4, 0xbc, 0xdf, 0xbd, 0x65, 0xa2, 0x4f, 0x45, 0x0b, 0x97, 0xa8, 0xbe, 0x90, 0x58, 0xed, 0xa1, 0xf9, + 0x0f, 0xed, 0xc2, 0x6f, 0x90, 0x20, 0x3c, 0xaf, 0x1d, 0xd0, 0x4f, 0x49, 0x9b, 0x52, 0x85, 0x0a, 0xa3, 0x6c, 0xe3, + 0xca, 0x76, 0x77, 0x45, 0x33, 0x0b, 0xe1, 0x9b, 0x89, 0x66, 0xbd, 0xed, 0xf8, 0xc1, 0x1e, 0x0d, 0x9b, 0x00, 0x5a, + 0x81, 0x05, 0x20, 0xea, 0xcf, 0xd5, 0xb6, 0xfd, 0x2e, 0x6c, 0x06, 0x55, 0x51, 0x92, 0x55, 0xa1, 0x8d, 0xa0, 0x91, + 0x81, 0x41, 0x13, 0x4d, 0xbf, 0xe8, 0x1e, 0xfc, 0xc2, 0x85, 0xb8, 0xa0, 0xb0, 0xa1, 0x74, 0xeb, 0xfa, 0x25, 0x52, + 0x05, 0xa6, 0xb1, 0x72, 0xb9, 0xff, 0x7e, 0x07, 0x1d, 0x7f, 0x5d, 0xec, 0x94, 0x7a, 0xae, 0xaa, 0x09, 0x75, 0x77, + 0x42, 0x13, 0x08, 0x1e, 0x0e, 0xbd, 0x70, 0xfa, 0x47, 0xc2, 0x1d, 0x24, 0xe7, 0xe5, 0xfb, 0xbf, 0x42, 0x0d, 0xfe, + 0x3c, 0xa0, 0x80, 0xf6, 0xaa, 0x7c, 0xde, 0x1d, 0x21, 0x38, 0x51, 0xbf, 0x02, 0x3b, 0xa2, 0xd2, 0x94, 0x1c, 0x51, + 0x58, 0x9c, 0x21, 0xbe, 0x01, 0xba, 0xf9, 0xb6, 0x53, 0xfd, 0xf9, 0xdb, 0x85, 0x13, 0xf1, 0xab, 0x6f, 0x97, 0xec, + 0x6d, 0xa4, 0x44, 0xe0, 0xa1, 0x5a, 0x9f, 0x1b, 0x84, 0x92, 0x0d, 0x96, 0x28, 0x45, 0x5c, 0x26, 0xa2, 0x4a, 0x08, + 0x16, 0x6d, 0x35, 0x6a, 0xe8, 0xd7, 0xeb, 0x2e, 0xb2, 0xae, 0xf1, 0x54, 0x05, 0x5f, 0xa8, 0xdf, 0xf6, 0x0c, 0x9b, + 0x79, 0x4d, 0xe7, 0x62, 0xff, 0x2b, 0x74, 0x4e, 0x2e, 0xb4, 0x76, 0xe9, 0x29, 0x04, 0x10, 0x85, 0x3b, 0xd3, 0x96, + 0x15, 0xc9, 0xd0, 0xae, 0xc0, 0xec, 0x07, 0x06, 0x92, 0x09, 0xf2, 0xc9, 0xfe, 0x4c, 0x0e, 0x21, 0x4d, 0x3c, 0x4e, + 0x46, 0x30, 0xbc, 0xd2, 0x50, 0xfa, 0xe6, 0x62, 0x78, 0xab, 0x5c, 0x9f, 0xc2, 0x2e, 0x88, 0x32, 0x07, 0xbe, 0xed, + 0x72, 0x74, 0x2b, 0x62, 0xf0, 0x8c, 0xc7, 0x8c, 0xb9, 0x77, 0xeb, 0xbd, 0xfb, 0x23, 0x52, 0x1d, 0x0b, 0x41, 0x6a, + 0x18, 0xc8, 0xaf, 0xc5, 0x40, 0x0f, 0xa8, 0x0a, 0x22, 0xf4, 0xd9, 0x58, 0x01, 0x9c, 0xbf, 0x5f, 0x31, 0x46, 0x6e, + 0xa9, 0x9e, 0x4b, 0xab, 0xab, 0x67, 0x15, 0x50, 0xd0, 0x18, 0x1d, 0x4c, 0xdd, 0x1a, 0x84, 0xd3, 0x86, 0xf6, 0xc1, + 0xc3, 0x23, 0xd2, 0x6b, 0x28, 0x62, 0xb1, 0x70, 0x56, 0xb8, 0xd4, 0xea, 0x6a, 0x61, 0x2a, 0x47, 0x7a, 0x24, 0xb9, + 0x72, 0x3b, 0x70, 0xfb, 0xde, 0xb4, 0x06, 0x09, 0x70, 0x8e, 0x18, 0xe2, 0x82, 0x46, 0x78, 0x5c, 0x13, 0x24, 0x48, + 0x48, 0x6f, 0x0c, 0xc8, 0x22, 0xc1, 0x45, 0xa6, 0x24, 0x7a, 0x11, 0x94, 0xda, 0x3d, 0x1d, 0xe9, 0x53, 0x80, 0x8b, + 0x71, 0xb2, 0x5a, 0x80, 0x25, 0x84, 0xf1, 0xba, 0xe6, 0x22, 0xc0, 0x56, 0x06, 0xb8, 0xb1, 0x66, 0x54, 0x70, 0x2e, + 0xec, 0xd0, 0x68, 0xd7, 0xca, 0xcf, 0xef, 0xc7, 0x02, 0x5c, 0x7a, 0xd1, 0x2c, 0x20, 0x10, 0x67, 0x2e, 0xef, 0x03, + 0x08, 0x39, 0x48, 0x5b, 0xa3, 0x37, 0x2d, 0x61, 0xa3, 0x84, 0x7c, 0x5a, 0x74, 0xf9, 0x95, 0x0f, 0x8d, 0x78, 0x58, + 0x2b, 0x6a, 0x2a, 0x41, 0x9f, 0xb1, 0x0d, 0x3e, 0xb8, 0x51, 0x93, 0xae, 0x0f, 0x96, 0x00, 0xa4, 0xc7, 0x32, 0x19, + 0x70, 0x8f, 0xa6, 0x17, 0xbd, 0x06, 0x52, 0xfa, 0xae, 0x1c, 0x39, 0x0e, 0x51, 0x7c, 0xbe, 0x45, 0x31, 0xb8, 0x37, + 0xad, 0xf1, 0x18, 0xc4, 0x07, 0x59, 0x32, 0xbe, 0x59, 0x14, 0x73, 0xac, 0x38, 0x13, 0x21, 0x7f, 0xd9, 0x48, 0x1a, + 0x09, 0x2b, 0x9d, 0xb6, 0x4a, 0x9a, 0x0a, 0x1b, 0x1b, 0xa0, 0x10, 0xa9, 0x87, 0xa0, 0x27, 0xb0, 0xeb, 0x0d, 0x89, + 0x79, 0x38, 0xd2, 0x52, 0xa4, 0x2f, 0x45, 0x5f, 0x73, 0x76, 0xca, 0x80, 0x4d, 0x84, 0x73, 0x73, 0x49, 0xf0, 0xdf, + 0xc4, 0xb6, 0x2e, 0x2e, 0x50, 0x31, 0xa3, 0x95, 0xe0, 0x21, 0x2c, 0x86, 0x97, 0x45, 0x05, 0x22, 0xeb, 0x6d, 0x7a, + 0x99, 0xb4, 0x92, 0x56, 0x79, 0x2c, 0x01, 0xd4, 0x71, 0x4f, 0x56, 0x16, 0x7a, 0x32, 0x1c, 0x61, 0x1f, 0x64, 0x9c, + 0x62, 0x1c, 0xc7, 0x9a, 0xd4, 0x66, 0xe4, 0xba, 0x13, 0x2d, 0x16, 0x32, 0xe3, 0xa1, 0xae, 0xa2, 0x12, 0x12, 0x18, + 0xd5, 0x24, 0x5d, 0x04, 0xde, 0xfa, 0x89, 0xf7, 0x04, 0x90, 0x80, 0xe8, 0x13, 0x3e, 0xf2, 0x93, 0x0c, 0xad, 0x86, + 0x84, 0x62, 0x45, 0xae, 0x21, 0xe7, 0xc5, 0x1b, 0xe5, 0x28, 0x72, 0xa7, 0xd1, 0x89, 0xbf, 0x16, 0xed, 0x9b, 0xc2, + 0xe6, 0x10, 0x84, 0xc3, 0x47, 0x85, 0x5d, 0xe8, 0x49, 0x3b, 0x95, 0x6a, 0x63, 0xa3, 0x9e, 0x87, 0x03, 0xde, 0xda, + 0x94, 0x09, 0x1e, 0xff, 0x5b, 0x43, 0x0d, 0xd1, 0xe6, 0xaf, 0x63, 0x06, 0x6c, 0xb3, 0xcd, 0xf6, 0x74, 0x0b, 0xf8, + 0x93, 0x38, 0xd9, 0x67, 0x50, 0x53, 0x36, 0x0f, 0x16, 0xdb, 0x75, 0x5f, 0x4e, 0x7e, 0x26, 0x53, 0x01, 0xc4, 0x55, + 0x41, 0xd5, 0x63, 0x64, 0x38, 0x20, 0xed, 0xa5, 0xe1, 0x71, 0x31, 0x40, 0x8a, 0x8c, 0xab, 0x92, 0x02, 0x81, 0x66, + 0x33, 0xa2, 0xb8, 0x01, 0xf4, 0xd8, 0x8c, 0xa3, 0xc4, 0x28, 0xb8, 0x41, 0x9e, 0x34, 0xd8, 0x98, 0x03, 0x97, 0x6a, + 0xd1, 0xac, 0xd2, 0xe6, 0x10, 0xd9, 0x03, 0x8b, 0x02, 0xe2, 0xf8, 0xf3, 0x5a, 0x43, 0x82, 0xbc, 0xe1, 0x7c, 0x12, + 0xc2, 0x00, 0xb7, 0x61, 0x04, 0xd9, 0xc3, 0x38, 0x22, 0xa1, 0xb8, 0xa9, 0x23, 0x7d, 0xfd, 0xc8, 0xde, 0x54, 0xde, + 0xef, 0x5a, 0x60, 0x18, 0xc7, 0x83, 0x81, 0xde, 0xbc, 0xd0, 0x92, 0x6e, 0x50, 0x97, 0x10, 0xf3, 0xb3, 0xb3, 0x99, + 0x19, 0x67, 0x6b, 0x8e, 0xe1, 0x61, 0xd8, 0x5c, 0x94, 0xf7, 0xf7, 0x6e, 0x12, 0x20, 0xbf, 0x13, 0x56, 0x7d, 0x72, + 0x12, 0x4f, 0x54, 0xfd, 0x5e, 0xd6, 0x3f, 0x12, 0xaf, 0x7f, 0x18, 0x50, 0xb2, 0xe9, 0xa1, 0x5e, 0xa9, 0x7b, 0x8b, + 0xe5, 0xac, 0xec, 0x9a, 0x82, 0x4a, 0x4b, 0x97, 0x65, 0x8c, 0x03, 0x49, 0xa0, 0x82, 0x7e, 0x29, 0xfb, 0xbc, 0x55, + 0x38, 0x50, 0x41, 0x21, 0x5b, 0x3f, 0x0d, 0xea, 0xe2, 0xf4, 0x2a, 0xc5, 0x2c, 0xc5, 0x18, 0xcf, 0x4e, 0x6d, 0x7d, + 0x1b, 0x90, 0x4e, 0x9d, 0xd2, 0xc0, 0xf3, 0x13, 0xdb, 0xed, 0xf6, 0x89, 0x13, 0x02, 0xb1, 0x52, 0x38, 0x11, 0x9b, + 0x59, 0x6c, 0x7e, 0xd0, 0x88, 0x54, 0x7e, 0x30, 0x0e, 0xc8, 0xca, 0x39, 0x6c, 0x81, 0xec, 0xb9, 0x29, 0x3c, 0x30, + 0xe6, 0x78, 0xdf, 0xf2, 0xd0, 0xad, 0xbf, 0xc3, 0x9f, 0x90, 0x93, 0x19, 0x65, 0xa6, 0xcf, 0xeb, 0xc1, 0x74, 0x57, + 0xdd, 0xb3, 0xc4, 0xe6, 0xcd, 0x75, 0xd2, 0x8b, 0x64, 0xb1, 0x97, 0xa2, 0x49, 0xba, 0x0c, 0x66, 0xed, 0x32, 0x88, + 0x5a, 0x2a, 0x60, 0xda, 0xe9, 0x6d, 0xa6, 0x71, 0x56, 0x40, 0x9f, 0x01, 0x33, 0xbb, 0xbb, 0x04, 0x5c, 0x17, 0x19, + 0x2c, 0xb1, 0x52, 0x88, 0xc2, 0xe3, 0x29, 0xed, 0xde, 0x4f, 0x0c, 0x94, 0x3e, 0x76, 0x81, 0xec, 0xa5, 0xa3, 0x87, + 0xa4, 0x76, 0x84, 0x28, 0xa2, 0x96, 0xfd, 0x21, 0x82, 0x42, 0x8a, 0x33, 0xfc, 0x80, 0xe9, 0xce, 0x47, 0xc8, 0xb8, + 0x00, 0xf9, 0xd9, 0x4c, 0xb4, 0xd5, 0x77, 0x5b, 0xc4, 0xc0, 0xcb, 0x0f, 0x25, 0xee, 0x27, 0xbd, 0x95, 0x6f, 0xc2, + 0xe3, 0x58, 0x71, 0x16, 0xc8, 0x58, 0xa1, 0x30, 0x8c, 0xe6, 0xfc, 0x04, 0x49, 0xd2, 0x7b, 0x38, 0x8f, 0x02, 0xb8, + 0x0c, 0xc1, 0x88, 0x02, 0xb5, 0x8d, 0x60, 0xf6, 0xc2, 0x4c, 0x35, 0xa0, 0xcc, 0x2d, 0x9a, 0x29, 0xc9, 0x5a, 0x3b, + 0x99, 0xe3, 0xcc, 0x73, 0x3f, 0x53, 0x18, 0x00, 0x54, 0x6c, 0xfa, 0xbd, 0x6a, 0xc5, 0xf2, 0x3a, 0x1e, 0x66, 0x6d, + 0xe5, 0x84, 0x98, 0x75, 0xf6, 0xfb, 0x14, 0x4d, 0x52, 0x01, 0xc8, 0x0a, 0xac, 0x4e, 0x8d, 0x49, 0x2a, 0xe7, 0x03, + 0xa3, 0x9b, 0x3a, 0x18, 0x46, 0x2c, 0x43, 0x65, 0x69, 0x1a, 0x06, 0x87, 0x6d, 0xfb, 0x3e, 0xc8, 0xe8, 0xd0, 0xef, + 0x5b, 0xd9, 0x58, 0x0a, 0x81, 0x96, 0x05, 0x5a, 0x3e, 0x0c, 0x68, 0x52, 0x86, 0x2b, 0x45, 0x79, 0x22, 0x47, 0xca, + 0x3d, 0xb2, 0xe4, 0x24, 0xef, 0xfb, 0xa9, 0x69, 0x57, 0x97, 0x0c, 0x88, 0x66, 0x2e, 0x54, 0xc3, 0xd7, 0x2c, 0xf9, + 0x33, 0x4c, 0x98, 0xac, 0xbd, 0x71, 0x98, 0xd7, 0x64, 0x8d, 0x1c, 0x99, 0xaa, 0x0e, 0x18, 0x82, 0x6a, 0x74, 0x39, + 0x36, 0xc6, 0x4f, 0x2c, 0x1a, 0xb5, 0xa1, 0x30, 0xaf, 0x1d, 0x2b, 0x25, 0x67, 0x96, 0x8e, 0x98, 0x77, 0x37, 0x16, + 0x9d, 0xea, 0xa7, 0x07, 0xb2, 0x65, 0xfd, 0x00, 0xdf, 0x59, 0x22, 0xc2, 0x07, 0xcb, 0x1f, 0xce, 0x6f, 0x23, 0xbb, + 0x74, 0x2d, 0x74, 0x4c, 0x6b, 0xeb, 0xf0, 0xa7, 0x66, 0x93, 0x96, 0x2c, 0xf5, 0xdf, 0xcb, 0x00, 0x15, 0xe4, 0x29, + 0xa8, 0x42, 0x75, 0x54, 0x42, 0x94, 0xe1, 0x60, 0x53, 0xad, 0xab, 0xa3, 0xf2, 0xc6, 0xb9, 0xeb, 0x1d, 0xdc, 0xd9, + 0x81, 0x2c, 0xa9, 0x3b, 0xc2, 0x27, 0x17, 0x7d, 0x15, 0x21, 0x45, 0xd8, 0x32, 0x23, 0x77, 0xf6, 0xe5, 0xe9, 0x23, + 0xaf, 0x6f, 0xed, 0x3c, 0x1d, 0x3a, 0x5f, 0x61, 0x90, 0x5d, 0x7b, 0x74, 0x6c, 0x64, 0xcb, 0x8d, 0x68, 0xdb, 0x78, + 0xde, 0x1d, 0xa5, 0xd1, 0x4f, 0x4a, 0x89, 0x57, 0x6e, 0x82, 0xa8, 0xfd, 0xc1, 0x42, 0xf2, 0x19, 0x9e, 0x43, 0xb6, + 0x60, 0xb4, 0x68, 0x4c, 0x6c, 0x3c, 0x07, 0xdc, 0x23, 0x8a, 0xeb, 0x47, 0x8f, 0x05, 0x09, 0x17, 0x9c, 0x01, 0xf6, + 0xd2, 0x9c, 0xdd, 0xb6, 0x06, 0xd8, 0xe5, 0x62, 0xe2, 0x8a, 0x3e, 0x2e, 0xcc, 0xf1, 0xee, 0xfa, 0x85, 0xb2, 0x23, + 0xf1, 0xae, 0xb9, 0x6c, 0x6f, 0x79, 0x2d, 0xa2, 0x34, 0x15, 0x01, 0x4c, 0x13, 0x84, 0x86, 0x32, 0xc7, 0x14, 0xe9, + 0xcd, 0xf4, 0x6a, 0x98, 0x73, 0x27, 0x6b, 0x2e, 0x76, 0x65, 0x50, 0xa8, 0x01, 0x51, 0x19, 0xe2, 0x38, 0x39, 0x4e, + 0x18, 0xd8, 0x6d, 0x02, 0xd0, 0x11, 0xb4, 0x61, 0x48, 0xe8, 0xad, 0x13, 0x40, 0x0b, 0xb1, 0xc8, 0x1f, 0x32, 0x29, + 0x15, 0xa7, 0xbe, 0x97, 0x97, 0x79, 0xf3, 0x82, 0x1b, 0x14, 0x47, 0x08, 0xda, 0x8a, 0xe7, 0xc1, 0x15, 0x43, 0xb7, + 0x47, 0xe1, 0xd0, 0xc6, 0x56, 0xe6, 0x19, 0x7f, 0x96, 0xe8, 0x07, 0xca, 0x6e, 0xec, 0xf5, 0x90, 0x76, 0xaa, 0x39, + 0x28, 0xc7, 0x30, 0xf8, 0x96, 0xe9, 0x51, 0xd2, 0xba, 0x05, 0x2e, 0x86, 0xdf, 0x3c, 0xc4, 0x7b, 0xef, 0xb8, 0x3d, + 0x7d, 0xcc, 0xd3, 0xee, 0xef, 0xc3, 0x67, 0x83, 0xd9, 0x97, 0xf9, 0x80, 0x2e, 0x1e, 0x0e, 0x5c, 0x43, 0x02, 0x33, + 0x12, 0x10, 0xba, 0xd1, 0xf5, 0xd6, 0xbd, 0x43, 0xcd, 0xf3, 0xe0, 0xc4, 0x3d, 0xe5, 0x37, 0x2e, 0x49, 0x17, 0x49, + 0xd7, 0x08, 0x65, 0xef, 0xff, 0x45, 0x0e, 0x4b, 0xcf, 0x23, 0xe3, 0xd1, 0xa6, 0xa6, 0x38, 0x13, 0x9c, 0x5d, 0x0e, + 0xf6, 0x16, 0x24, 0x8c, 0x63, 0xe4, 0x92, 0xc1, 0x38, 0x67, 0x66, 0x4c, 0xc4, 0xd6, 0x1c, 0xa4, 0x8d, 0x0c, 0x79, + 0x9d, 0x22, 0xf7, 0xc5, 0x4e, 0x01, 0xfa, 0x50, 0xc8, 0x69, 0xb7, 0x15, 0xfa, 0x24, 0x60, 0xe0, 0xff, 0x4e, 0x4b, + 0xfb, 0x1e, 0xf9, 0x3e, 0x6d, 0x62, 0x89, 0x14, 0x9b, 0xb1, 0x51, 0xcf, 0xc5, 0xdc, 0x2a, 0x64, 0xc3, 0xfa, 0x45, + 0x84, 0xfa, 0xdd, 0xac, 0x3c, 0x3b, 0xe6, 0x27, 0x12, 0xc0, 0x69, 0xeb, 0x10, 0x6c, 0xe7, 0xf3, 0xad, 0xff, 0x26, + 0xe9, 0xfb, 0xcc, 0xa2, 0x87, 0x73, 0x9d, 0x8c, 0x35, 0x27, 0xb0, 0xa0, 0xd4, 0xdb, 0xb1, 0x73, 0x7d, 0xba, 0xc7, + 0x73, 0xd5, 0x2c, 0xca, 0x20, 0xb9, 0xb6, 0x8b, 0xa4, 0x48, 0x3c, 0xb9, 0x7a, 0xe3, 0x6c, 0xc6, 0xf8, 0x58, 0xfc, + 0xbd, 0x3d, 0x4e, 0xfb, 0x7e, 0xe3, 0x33, 0xda, 0xbb, 0xf4, 0x7f, 0xce, 0xa6, 0xd3, 0xdf, 0x21, 0xe3, 0xb9, 0xae, + 0xd9, 0x52, 0x35, 0x85, 0x54, 0x93, 0x2d, 0x02, 0x50, 0x8d, 0x38, 0xdf, 0x1d, 0x77, 0xfb, 0xef, 0x0a, 0xa2, 0x99, + 0xbf, 0x20, 0xee, 0xbe, 0xd7, 0x52, 0x3d, 0x6d, 0x71, 0x34, 0xe5, 0xac, 0xf7, 0xc8, 0x6e, 0xf6, 0x1e, 0xf0, 0xb6, + 0xb4, 0xfa, 0xa7, 0xfa, 0x4f, 0xf8, 0xdd, 0x62, 0xf3, 0xb7, 0xdd, 0x7c, 0xea, 0xc3, 0xf6, 0xa4, 0xae, 0xb6, 0x78, + 0xb3, 0xd6, 0xdf, 0xec, 0x79, 0xbb, 0xdb, 0x7c, 0xa0, 0xd3, 0xfa, 0x2f, 0xe5, 0x75, 0x35, 0x18, 0x97, 0xea, 0xaf, + 0x40, 0xe2, 0xdf, 0x2a, 0xf4, 0xee, 0x0e, 0x90, 0x2f, 0xd5, 0xec, 0x20, 0xc3, 0xcc, 0xf8, 0x60, 0xbc, 0x0b, 0x5d, + 0x68, 0xeb, 0xf1, 0x6e, 0x14, 0x26, 0x2a, 0xc4, 0xfd, 0xdc, 0x35, 0x33, 0xd5, 0xbb, 0xe4, 0x6a, 0xd2, 0xa5, 0x5f, + 0x1b, 0x14, 0xaf, 0x4d, 0x68, 0xb1, 0x66, 0xc4, 0x36, 0x35, 0xff, 0x05, 0x58, 0xfe, 0xb9, 0xe0, 0x19, 0xc6, 0x4d, + 0xda, 0x8f, 0x6a, 0xbb, 0x52, 0xf9, 0xfe, 0xa7, 0xf1, 0xd7, 0xa6, 0x9e, 0xb2, 0xce, 0x7f, 0xde, 0x7d, 0x5b, 0xfe, + 0x99, 0xcb, 0x8e, 0x4c, 0x55, 0xfd, 0x05, 0xf9, 0xc4, 0xa4, 0x2b, 0xe5, 0x78, 0x3d, 0xcb, 0xfe, 0x5f, 0x84, 0xbb, + 0x7f, 0x3b, 0xff, 0xf2, 0x9f, 0x66, 0xe1, 0x7d, 0x20, 0xcd, 0x4e, 0xc3, 0x17, 0x92, 0xdf, 0xd9, 0xb2, 0x7a, 0x7e, + 0xe7, 0x0b, 0xd4, 0x58, 0x71, 0x8f, 0xac, 0x2f, 0x65, 0x62, 0x55, 0x2e, 0xe0, 0xd6, 0x7f, 0x3b, 0xd5, 0x5f, 0x0f, + 0xe4, 0xf3, 0x9e, 0x92, 0xf9, 0x62, 0xf8, 0xb5, 0x79, 0x73, 0x4f, 0xa7, 0x7a, 0xd7, 0x2f, 0xfc, 0x78, 0x4c, 0x4a, + 0x7f, 0xd5, 0xe3, 0x32, 0xb8, 0xb9, 0x52, 0xff, 0xd5, 0xc2, 0xa7, 0x2b, 0x83, 0xf2, 0xcf, 0xc8, 0xc7, 0xe3, 0xf5, + 0xcd, 0xe2, 0x63, 0xf9, 0x3e, 0x0b, 0x18, 0x27, 0x38, 0xa3, 0xe6, 0x0b, 0xdc, 0x11, 0x54, 0x1f, 0xe2, 0x91, 0xac, + 0x3f, 0x99, 0x55, 0x3c, 0xdc, 0x2b, 0x70, 0xfc, 0x96, 0x57, 0x7e, 0xe6, 0xd2, 0x24, 0x5c, 0x30, 0x4e, 0x7f, 0xc4, + 0xa3, 0xef, 0x3b, 0x18, 0x7d, 0xd0, 0xbb, 0xf1, 0xdd, 0x8c, 0x3a, 0xe2, 0x63, 0xf3, 0xac, 0xab, 0x96, 0xc6, 0x5b, + 0x29, 0x39, 0x61, 0x1b, 0xfd, 0x55, 0xc0, 0x43, 0x0c, 0xda, 0xbe, 0xf7, 0xad, 0xf2, 0x37, 0x7e, 0x17, 0xa6, 0xf7, + 0xd6, 0x8f, 0xbf, 0xbf, 0x12, 0xef, 0xf6, 0xef, 0x0c, 0x13, 0x88, 0xf5, 0xc0, 0xbb, 0xe8, 0xff, 0xa8, 0x86, 0x4f, + 0x48, 0xe6, 0x44, 0x61, 0x4d, 0xdd, 0x2f, 0xd5, 0xf7, 0xe1, 0xe2, 0x41, 0x24, 0x5f, 0x16, 0xef, 0xfb, 0x44, 0x1e, + 0xee, 0xd1, 0xb3, 0xbc, 0x97, 0x46, 0x1c, 0x40, 0x0d, 0x05, 0xc8, 0x82, 0x7c, 0x32, 0x8c, 0xc0, 0xce, 0x73, 0x0a, + 0x3b, 0xa7, 0xaa, 0xcf, 0xee, 0x22, 0xd2, 0xbb, 0xd5, 0xdc, 0x9a, 0x3f, 0x01, 0x4a, 0x61, 0x9b, 0x08, 0xb0, 0xef, + 0xa7, 0x3b, 0x9a, 0xd4, 0x7a, 0x9d, 0x6e, 0xfd, 0xe9, 0xe4, 0x4a, 0x4d, 0xea, 0xb6, 0xba, 0xc8, 0x78, 0xe0, 0x79, + 0x93, 0x13, 0x9e, 0xdd, 0x98, 0xe8, 0x14, 0x63, 0x13, 0x0e, 0xda, 0x99, 0x29, 0xeb, 0xb1, 0x73, 0x1d, 0x12, 0x91, + 0xdd, 0xd0, 0x10, 0x77, 0x99, 0xdb, 0x23, 0xb8, 0x51, 0x11, 0x89, 0x5a, 0x42, 0x7d, 0xf1, 0x7b, 0x26, 0x93, 0x89, + 0x6f, 0xe5, 0x39, 0x1b, 0x7e, 0xe1, 0x7f, 0x56, 0xc9, 0x82, 0x01, 0xc8, 0xc9, 0xd4, 0xc9, 0x23, 0x50, 0xf1, 0x35, + 0x41, 0xb4, 0xf3, 0x59, 0x4e, 0xdc, 0x3b, 0x2c, 0xca, 0x53, 0xcd, 0xcc, 0xf3, 0xbf, 0x6b, 0x60, 0xcd, 0x42, 0x51, + 0xc4, 0x46, 0x34, 0xcb, 0xf6, 0x76, 0x33, 0x8b, 0x7a, 0x1e, 0xbe, 0x02, 0xe1, 0xec, 0x32, 0x00, 0x7d, 0x5b, 0xd5, + 0xb0, 0x96, 0x33, 0xf3, 0x97, 0xde, 0x08, 0x01, 0x6a, 0x1e, 0xf4, 0x30, 0x66, 0xef, 0x4d, 0xc9, 0xfe, 0x51, 0x90, + 0x53, 0x9e, 0x9b, 0x9a, 0xce, 0x19, 0x67, 0xc9, 0x73, 0x38, 0x93, 0x12, 0xd2, 0x4e, 0x7b, 0xa4, 0x22, 0xd2, 0xf0, + 0xda, 0xac, 0x5e, 0x2c, 0x65, 0x7d, 0xb8, 0xe5, 0x85, 0x29, 0x20, 0x0c, 0x48, 0x82, 0xd8, 0x53, 0xf8, 0x39, 0x58, + 0xf4, 0x21, 0x14, 0x45, 0x12, 0xbd, 0x52, 0x38, 0xbd, 0x9d, 0x98, 0xbd, 0x24, 0xa9, 0xd1, 0xe9, 0x11, 0xae, 0xff, + 0xbe, 0xb7, 0x73, 0x8e, 0x9e, 0x49, 0x16, 0xe9, 0xdb, 0xf4, 0x97, 0x51, 0xbb, 0x59, 0xa2, 0xa9, 0xed, 0x0d, 0x00, + 0xce, 0xb1, 0x52, 0xc3, 0xee, 0xfb, 0xa5, 0x91, 0xa2, 0x25, 0xbe, 0xbc, 0x20, 0xa3, 0xa2, 0x4b, 0x5a, 0xea, 0xbb, + 0x38, 0x5d, 0x54, 0x65, 0x1b, 0xfc, 0x3e, 0x39, 0xe0, 0xc5, 0x1b, 0x30, 0x49, 0x5f, 0x91, 0x3e, 0x12, 0x04, 0xa7, + 0xcd, 0xc6, 0x6c, 0x6f, 0xdd, 0x47, 0xf2, 0xd6, 0xc2, 0x7f, 0xd1, 0x5e, 0x58, 0xf5, 0xa2, 0x67, 0x2a, 0x03, 0xdc, + 0x22, 0x5f, 0x96, 0x71, 0x4e, 0x34, 0xad, 0x5a, 0xf0, 0xa2, 0x2b, 0xa8, 0x33, 0xf7, 0x34, 0x6f, 0xed, 0x22, 0xd8, + 0x10, 0xda, 0xe7, 0xc1, 0x2c, 0x59, 0x60, 0x85, 0x20, 0x94, 0xb7, 0x63, 0xeb, 0x19, 0xd7, 0x5f, 0x35, 0xf8, 0x65, + 0xe5, 0x62, 0x29, 0x74, 0x80, 0x61, 0xf2, 0xdb, 0x1a, 0x08, 0x9e, 0xfa, 0x12, 0xca, 0x02, 0xbd, 0x6d, 0xe1, 0xf1, + 0x9a, 0xee, 0xde, 0x9d, 0xe1, 0x84, 0x10, 0xdf, 0x6f, 0xc6, 0x42, 0x79, 0x1e, 0xfd, 0x92, 0xd1, 0x08, 0xcb, 0x1d, + 0x8e, 0x28, 0xa7, 0x47, 0x83, 0x6c, 0x70, 0x7c, 0x67, 0xeb, 0x51, 0x65, 0x59, 0xe6, 0x11, 0x16, 0x9f, 0x92, 0x05, + 0xf6, 0x82, 0xec, 0xe2, 0xfe, 0xd3, 0x75, 0x28, 0x4c, 0xb1, 0x07, 0x6a, 0x72, 0xab, 0xde, 0xa6, 0x5c, 0x3b, 0xfe, + 0x35, 0x5b, 0xe8, 0xc8, 0x6e, 0xf7, 0x90, 0x7e, 0x8b, 0x6b, 0x6b, 0x0c, 0x6d, 0xdf, 0x90, 0x44, 0xe9, 0x34, 0xdd, + 0x3d, 0x03, 0x0a, 0xf4, 0x3f, 0x26, 0x94, 0xfc, 0x85, 0x34, 0xd3, 0xac, 0x4b, 0xb1, 0xab, 0xfd, 0x12, 0xe7, 0x64, + 0xfa, 0xeb, 0x99, 0x87, 0x7a, 0xa9, 0xfe, 0xdf, 0xeb, 0x35, 0x0d, 0x98, 0xe8, 0x8d, 0x69, 0x04, 0x34, 0x90, 0x22, + 0x95, 0x98, 0x6f, 0x2c, 0xa3, 0x06, 0x49, 0x67, 0x99, 0x91, 0x52, 0xae, 0xa3, 0xfb, 0x8d, 0x0a, 0x85, 0x0b, 0xdd, + 0xbd, 0xad, 0xb8, 0x31, 0xa5, 0xb7, 0x45, 0x8f, 0xe2, 0x37, 0xe6, 0xbd, 0x19, 0xc7, 0x71, 0x73, 0x91, 0x21, 0xe1, + 0x02, 0x3d, 0x8b, 0x1e, 0x57, 0xe7, 0x88, 0xd7, 0x44, 0x39, 0x78, 0x04, 0xd1, 0x31, 0xd1, 0x13, 0xe2, 0x66, 0xbc, + 0xf5, 0x16, 0x7c, 0x62, 0x40, 0xbe, 0xe7, 0xcd, 0x12, 0x7c, 0x68, 0x5b, 0xe5, 0x39, 0x06, 0x1d, 0xf0, 0xab, 0xf5, + 0x6c, 0x29, 0x00, 0x0b, 0xb3, 0x29, 0xef, 0x6a, 0x29, 0xd0, 0x85, 0x86, 0xa4, 0xc9, 0xf3, 0x5d, 0x3d, 0x1d, 0xbf, + 0x44, 0xc3, 0x54, 0x24, 0x52, 0xd2, 0x9b, 0xf8, 0x86, 0xf3, 0x78, 0xa0, 0xad, 0x4e, 0x7d, 0x16, 0x7a, 0xb5, 0x55, + 0x9d, 0x9d, 0x77, 0x93, 0xd7, 0x61, 0x41, 0x17, 0x67, 0x1b, 0x50, 0x8e, 0x35, 0x93, 0x6e, 0x4a, 0x56, 0x55, 0x93, + 0xa2, 0x9c, 0x04, 0x86, 0x68, 0x17, 0xe1, 0x0a, 0xca, 0x9f, 0x57, 0x7d, 0x22, 0x95, 0xfa, 0x62, 0x16, 0x7f, 0x7a, + 0xb0, 0x52, 0x15, 0xf1, 0x3f, 0x38, 0xf2, 0x92, 0xed, 0x12, 0x29, 0x96, 0xa5, 0xa2, 0xf7, 0x33, 0x41, 0x5e, 0xfd, + 0xe1, 0x86, 0xe5, 0xba, 0x87, 0xfd, 0x2a, 0xd5, 0x1b, 0xe2, 0x69, 0xac, 0x18, 0x99, 0x5a, 0x5c, 0xf1, 0x96, 0xcb, + 0x53, 0x48, 0x8b, 0xf5, 0x98, 0x97, 0x2e, 0x69, 0xbc, 0x07, 0xde, 0x6e, 0x30, 0x41, 0x3f, 0x49, 0x6e, 0xd7, 0xb1, + 0x38, 0xa8, 0x45, 0x5d, 0xc8, 0xdb, 0x47, 0x63, 0x76, 0xe4, 0x72, 0x03, 0x1f, 0xbf, 0xb8, 0xd3, 0x39, 0x6f, 0xbc, + 0x56, 0xbe, 0xaa, 0x3b, 0xa1, 0xe0, 0xd7, 0x06, 0xa8, 0x26, 0x43, 0x6c, 0x11, 0xa2, 0x05, 0xdf, 0x7c, 0xb4, 0x59, + 0x9e, 0xd0, 0x12, 0x93, 0x66, 0xe5, 0xf2, 0xc5, 0x0b, 0xf3, 0xae, 0xd8, 0x1f, 0x2b, 0xe7, 0x66, 0x2a, 0xe3, 0x2b, + 0x7d, 0xed, 0x2a, 0x72, 0x59, 0x78, 0x8d, 0x42, 0x45, 0x28, 0xaa, 0x48, 0x1b, 0x17, 0xd8, 0xea, 0x66, 0xd8, 0xf2, + 0x99, 0x79, 0xa1, 0x69, 0xda, 0x98, 0x71, 0x52, 0x5c, 0x32, 0xc2, 0x3f, 0xe8, 0x08, 0xf6, 0x45, 0xab, 0x3c, 0xff, + 0xb1, 0x63, 0xb1, 0x70, 0x03, 0xed, 0x38, 0x7a, 0x21, 0x47, 0x25, 0xe9, 0xd1, 0x27, 0x85, 0xb2, 0xca, 0x34, 0xf2, + 0xae, 0xfa, 0xa4, 0xc2, 0x53, 0x74, 0x07, 0x45, 0x8e, 0xc2, 0x96, 0x0c, 0x6b, 0x65, 0x8c, 0xeb, 0x11, 0x7e, 0xd6, + 0xce, 0xde, 0x39, 0xdc, 0xec, 0x41, 0xec, 0xf0, 0x5f, 0x94, 0xe3, 0x73, 0x93, 0x25, 0x1e, 0x46, 0xfa, 0x2a, 0x79, + 0x9b, 0xa7, 0x13, 0x1f, 0xbe, 0xc9, 0x8c, 0xec, 0x96, 0xfa, 0x4f, 0xec, 0xf3, 0x3a, 0x42, 0x44, 0xce, 0xf3, 0x5d, + 0x45, 0x46, 0xa7, 0x70, 0x91, 0xeb, 0x94, 0xd2, 0x47, 0x95, 0x42, 0x02, 0x65, 0x49, 0xe3, 0x96, 0x65, 0xf7, 0x1f, + 0x7f, 0x50, 0xa1, 0xe5, 0x6b, 0x07, 0x66, 0xd2, 0x6d, 0x66, 0x96, 0x48, 0x16, 0x35, 0x46, 0x76, 0xa3, 0xe7, 0x1f, + 0x15, 0x89, 0x04, 0x49, 0x1a, 0x43, 0xa4, 0x73, 0x37, 0xdc, 0xe9, 0xff, 0x0e, 0xf7, 0xec, 0xc6, 0x92, 0xa2, 0x69, + 0x16, 0xca, 0xec, 0x0f, 0xf8, 0xa6, 0xdf, 0x21, 0x87, 0xa6, 0x8a, 0x92, 0x41, 0x0d, 0x6f, 0xe4, 0xdc, 0x86, 0x6e, + 0xcd, 0x83, 0xf5, 0xec, 0x17, 0xd0, 0x67, 0x8c, 0x06, 0x6a, 0xab, 0xd1, 0x4b, 0xd2, 0x37, 0x4a, 0xd4, 0x79, 0x1f, + 0x14, 0x14, 0xd4, 0xdb, 0x40, 0xe7, 0xa6, 0x26, 0x44, 0xbb, 0x5f, 0x04, 0x45, 0x90, 0x85, 0x68, 0xbc, 0xf0, 0xb1, + 0x7c, 0x91, 0xee, 0x49, 0x94, 0x48, 0xa8, 0x76, 0x5c, 0x7c, 0xcf, 0xa5, 0x34, 0x28, 0x78, 0xd4, 0x1a, 0x50, 0xec, + 0xba, 0x40, 0x7d, 0x80, 0x95, 0x55, 0xd6, 0x61, 0xde, 0x0a, 0x52, 0x35, 0x1a, 0x56, 0xdb, 0xcc, 0x2e, 0x4e, 0x9e, + 0x29, 0x32, 0x93, 0x84, 0x3d, 0xeb, 0xef, 0x2a, 0x5e, 0xe6, 0x48, 0x94, 0x95, 0x2d, 0x01, 0xeb, 0x5d, 0xb3, 0xc3, + 0xd1, 0x6c, 0x51, 0x5a, 0xbb, 0x16, 0xf6, 0xaf, 0x6c, 0x54, 0x49, 0x53, 0xaf, 0x63, 0x29, 0x71, 0x0d, 0x1b, 0xb9, + 0x4d, 0x06, 0xe2, 0x63, 0xf9, 0x6d, 0x92, 0x00, 0xe1, 0xbb, 0x78, 0xc4, 0x43, 0x37, 0x59, 0xb1, 0xa9, 0xec, 0x5c, + 0x59, 0xec, 0xf5, 0xe8, 0x05, 0x9c, 0x1e, 0x4d, 0xae, 0x24, 0x47, 0xb7, 0xc5, 0x79, 0x71, 0x57, 0xf1, 0x54, 0xe9, + 0xb2, 0xf8, 0x97, 0xfa, 0x0f, 0x54, 0x6e, 0x0f, 0x2b, 0x84, 0xfd, 0x2d, 0x91, 0xbb, 0x80, 0x94, 0x67, 0x81, 0x10, + 0x6a, 0x89, 0x08, 0x9b, 0x6f, 0x85, 0x28, 0xb0, 0x28, 0xb0, 0x49, 0xf3, 0x38, 0xc7, 0x6a, 0xbd, 0x15, 0x4d, 0x72, + 0x07, 0x92, 0x7b, 0xd8, 0x8d, 0x5b, 0x12, 0xca, 0xbd, 0xf2, 0xd8, 0xe6, 0x2f, 0x51, 0xd0, 0x07, 0x2d, 0x69, 0x5c, + 0x35, 0x02, 0x9c, 0x5e, 0xf2, 0xd5, 0x2b, 0xfd, 0xb6, 0xeb, 0x87, 0x1b, 0xe4, 0x9e, 0x65, 0x22, 0xd2, 0x2e, 0xc4, + 0xc4, 0xa7, 0xbe, 0xea, 0x3a, 0x1b, 0x07, 0xab, 0xb5, 0x8d, 0xf9, 0x78, 0x4a, 0x96, 0xad, 0x67, 0x97, 0x11, 0xbc, + 0xec, 0x38, 0x81, 0xc7, 0x77, 0x44, 0x17, 0x13, 0xd7, 0x48, 0x2a, 0x1a, 0x70, 0xc5, 0xd9, 0x46, 0x53, 0xbc, 0xef, + 0x53, 0xa0, 0xc3, 0xa2, 0xb9, 0x47, 0x65, 0xd0, 0x85, 0x80, 0x8e, 0x77, 0xee, 0x5e, 0x17, 0xc6, 0x6e, 0x9e, 0x28, + 0xad, 0xff, 0xc1, 0xad, 0x26, 0x2a, 0x0d, 0xeb, 0xb0, 0x04, 0x8a, 0x09, 0x39, 0xd1, 0x6e, 0xcc, 0xed, 0xd1, 0x43, + 0xc3, 0x67, 0x75, 0xd1, 0x68, 0x0d, 0xc4, 0x59, 0xe0, 0xf9, 0xdb, 0xb0, 0xb6, 0xb5, 0x11, 0x71, 0xff, 0x6b, 0x32, + 0x8a, 0x5a, 0x6e, 0x45, 0xe5, 0xcf, 0x3a, 0xc2, 0x45, 0x92, 0x81, 0xd9, 0x32, 0xfc, 0x46, 0x84, 0xd5, 0x1f, 0x21, + 0xe6, 0x1e, 0x87, 0x36, 0x21, 0xfd, 0xa5, 0x2d, 0xaf, 0xad, 0x87, 0x41, 0xc8, 0x87, 0x23, 0x9e, 0xa0, 0x88, 0x35, + 0xaa, 0x7b, 0x70, 0x32, 0x6c, 0x9c, 0x03, 0xab, 0xb6, 0x8b, 0x32, 0x0b, 0x67, 0x91, 0x91, 0x62, 0xe6, 0x33, 0xdb, + 0x04, 0x3e, 0x86, 0x0e, 0x3a, 0xa9, 0x3a, 0x75, 0x72, 0x50, 0x0d, 0x02, 0x30, 0x21, 0x0b, 0xed, 0x0b, 0x84, 0xae, + 0x11, 0x2c, 0xcb, 0x4a, 0xa5, 0xd5, 0x7a, 0x00, 0x8b, 0x8f, 0x50, 0xea, 0x17, 0x9f, 0xb8, 0xd5, 0x93, 0xce, 0xc1, + 0x28, 0xe2, 0xd0, 0x93, 0x5e, 0x8a, 0x3e, 0x45, 0x1e, 0x8b, 0x1d, 0x08, 0xb9, 0xb8, 0xf5, 0x4e, 0x36, 0x23, 0x1b, + 0x09, 0x5a, 0x09, 0xee, 0x01, 0x5a, 0xf7, 0xdc, 0x6a, 0x67, 0x3a, 0x21, 0xd0, 0x12, 0x69, 0x8c, 0x90, 0xe8, 0x1e, + 0x62, 0x0e, 0x89, 0x08, 0xf0, 0xa2, 0x60, 0x82, 0x29, 0x85, 0xb2, 0xb3, 0x1e, 0x52, 0xe8, 0xfd, 0x95, 0x65, 0x5c, + 0x4d, 0x64, 0x1e, 0x58, 0x61, 0x20, 0x8c, 0x33, 0x5f, 0x23, 0x0f, 0x09, 0x20, 0x67, 0x68, 0xfb, 0xa3, 0xa6, 0x47, + 0x6b, 0x33, 0x67, 0xda, 0xb8, 0x42, 0x36, 0x3e, 0x07, 0x45, 0xbc, 0x60, 0xc2, 0xf5, 0x59, 0xfd, 0xb8, 0xca, 0x75, + 0xa5, 0xe3, 0xd5, 0x8d, 0x94, 0xfb, 0x2a, 0xfe, 0xec, 0x12, 0x23, 0x59, 0x36, 0xbd, 0x69, 0x2a, 0x3d, 0x9d, 0x5a, + 0x7d, 0x67, 0x35, 0xd0, 0xb3, 0x3d, 0xc0, 0x13, 0x1e, 0x82, 0x4b, 0xcd, 0xc8, 0x2f, 0xb9, 0x04, 0x2d, 0xe0, 0x87, + 0x26, 0xa4, 0x23, 0x15, 0x0c, 0x8b, 0x79, 0x91, 0x96, 0xd3, 0xb2, 0xd8, 0x26, 0x35, 0x65, 0x60, 0x18, 0xc7, 0x64, + 0xa2, 0xc2, 0xa9, 0xfd, 0x03, 0xbf, 0xe7, 0xd9, 0x8c, 0x3c, 0xcd, 0x1a, 0x64, 0xf7, 0x6d, 0x9a, 0xc7, 0x2a, 0x17, + 0xd6, 0xda, 0x0a, 0x10, 0x7e, 0xc7, 0xbb, 0x82, 0xde, 0x48, 0xd1, 0x64, 0x98, 0xc1, 0x68, 0x69, 0xfc, 0xc8, 0xe0, + 0x7f, 0x97, 0x61, 0x55, 0xda, 0xa2, 0x06, 0x6e, 0x5f, 0xc4, 0x52, 0x1f, 0x94, 0x28, 0xd2, 0x56, 0x19, 0x62, 0xcb, + 0x63, 0x15, 0x7e, 0x57, 0x45, 0x47, 0x90, 0x61, 0xbb, 0x7e, 0xe6, 0xa8, 0xcd, 0xb1, 0x1f, 0x0e, 0x59, 0xb1, 0x27, + 0x73, 0x06, 0xc5, 0xc7, 0xfd, 0xc5, 0xa2, 0xab, 0x3a, 0x49, 0xcf, 0x16, 0x81, 0xba, 0x42, 0xc6, 0x53, 0xaf, 0x74, + 0x37, 0x52, 0x58, 0x6a, 0x64, 0x2b, 0xa0, 0x0c, 0x33, 0x54, 0x4b, 0x53, 0x74, 0xfb, 0x3d, 0x2b, 0x84, 0x44, 0x09, + 0x01, 0x46, 0x78, 0xef, 0x85, 0x2e, 0xfa, 0x7f, 0x9a, 0x37, 0xbe, 0x6f, 0x9d, 0x3a, 0x36, 0x0f, 0x47, 0x48, 0x09, + 0x10, 0x32, 0x29, 0xd7, 0xd0, 0x0f, 0x86, 0x82, 0xf1, 0x20, 0x51, 0x30, 0xf8, 0x39, 0xf6, 0x23, 0xe0, 0x66, 0x96, + 0x96, 0x47, 0x7e, 0x11, 0x4d, 0x4c, 0x89, 0xc7, 0x74, 0x46, 0x2a, 0xb7, 0xfb, 0x88, 0xab, 0x47, 0xba, 0x41, 0xf5, + 0x2d, 0x8a, 0x60, 0xf2, 0x2f, 0x35, 0x10, 0xde, 0xbd, 0x8e, 0xb9, 0x74, 0x9b, 0x9a, 0x37, 0x39, 0x00, 0xd3, 0xbd, + 0x2d, 0x51, 0xd7, 0x02, 0xa4, 0xde, 0x34, 0x85, 0x1f, 0xf6, 0x4f, 0x11, 0xb0, 0x38, 0x62, 0xb1, 0x49, 0x9d, 0x9e, + 0x53, 0xed, 0x7d, 0xb1, 0x6c, 0x04, 0xe1, 0xfe, 0x2a, 0xbb, 0xc8, 0x5d, 0x20, 0x90, 0xc9, 0x1a, 0x64, 0x10, 0x8e, + 0x35, 0xc3, 0x7a, 0x47, 0xab, 0xb2, 0xb1, 0x26, 0xad, 0xdd, 0xc7, 0xa5, 0xb4, 0xfb, 0x5a, 0x17, 0x0d, 0xa8, 0x81, + 0x21, 0xbc, 0xd6, 0xa2, 0x6d, 0x25, 0x60, 0x5e, 0xd5, 0xd8, 0x23, 0x98, 0x4b, 0x71, 0x29, 0xae, 0x25, 0x24, 0x1f, + 0x3f, 0x6a, 0x47, 0x8f, 0xd0, 0xd0, 0x64, 0xe3, 0xd3, 0x8d, 0x3c, 0x6d, 0xcf, 0x3f, 0xa8, 0x9d, 0xd8, 0xf7, 0xcb, + 0xe8, 0x40, 0xc8, 0xee, 0xd8, 0xfd, 0xe8, 0x87, 0x6f, 0x06, 0xce, 0x23, 0xda, 0xa9, 0xe1, 0xe1, 0xd0, 0x9b, 0x5c, + 0x2c, 0x99, 0xe6, 0x90, 0x3b, 0xa0, 0x29, 0xe3, 0x63, 0x6b, 0x03, 0x71, 0xad, 0x17, 0x12, 0x36, 0xd3, 0x10, 0x53, + 0xf9, 0x51, 0x63, 0x04, 0xc4, 0x28, 0x36, 0xd8, 0xc0, 0xb4, 0xef, 0x05, 0x6a, 0x36, 0x3f, 0x87, 0x55, 0x4e, 0x6d, + 0x11, 0x33, 0x4b, 0x72, 0x59, 0xa4, 0x05, 0x01, 0x2b, 0x8c, 0x81, 0xb3, 0x50, 0x95, 0x54, 0x2f, 0x4a, 0x24, 0x3d, + 0xc7, 0x11, 0x70, 0x50, 0x2e, 0xed, 0x3f, 0x0f, 0x82, 0x25, 0xa1, 0xf7, 0xb3, 0x30, 0x4b, 0x9b, 0xa5, 0xb4, 0x8c, + 0x2c, 0xa8, 0x84, 0x1a, 0xa9, 0x3e, 0x2f, 0x25, 0x79, 0x9c, 0x14, 0xfc, 0xce, 0xd8, 0x6c, 0x46, 0xf2, 0xe5, 0xe2, + 0xdd, 0xf8, 0x4b, 0xc5, 0xdf, 0x42, 0x32, 0x7d, 0x28, 0x80, 0x05, 0x34, 0x49, 0xaf, 0x31, 0xe8, 0xbe, 0x5e, 0xdc, + 0x96, 0x22, 0xfc, 0x6d, 0x00, 0x5a, 0xa5, 0x79, 0x9d, 0x1d, 0x4f, 0x19, 0xaf, 0x9d, 0xfc, 0x65, 0x9a, 0xa4, 0x29, + 0x18, 0xae, 0x03, 0xf3, 0x0c, 0xdd, 0x94, 0xa0, 0x1f, 0x31, 0x57, 0x5f, 0xaa, 0x97, 0x5c, 0x3c, 0x4d, 0x91, 0xb3, + 0x5b, 0xba, 0xde, 0x73, 0x36, 0x52, 0x81, 0x59, 0xa9, 0x7c, 0xff, 0x95, 0x34, 0x2b, 0xd0, 0xea, 0x13, 0xf7, 0x94, + 0x81, 0xd0, 0xd5, 0xa4, 0x44, 0xba, 0xbb, 0x85, 0x9a, 0x5e, 0x5b, 0x4c, 0x60, 0x2a, 0x55, 0xa8, 0xbd, 0x63, 0xd6, + 0x45, 0xdc, 0xfb, 0x77, 0x74, 0xed, 0x76, 0xe7, 0x56, 0xba, 0x08, 0xd8, 0x63, 0xc2, 0x18, 0x88, 0x1e, 0xc3, 0xa9, + 0x6b, 0xae, 0xb7, 0x95, 0x35, 0xd7, 0x05, 0x7e, 0x96, 0x08, 0xb2, 0x71, 0xe5, 0x0e, 0xac, 0xcc, 0x45, 0x10, 0x30, + 0x7f, 0xdb, 0xf8, 0x85, 0x27, 0x44, 0x26, 0x82, 0xb7, 0xec, 0xf8, 0x18, 0x2f, 0xeb, 0x7d, 0x76, 0xfc, 0x0a, 0xb6, + 0x4e, 0xad, 0x14, 0x36, 0x61, 0x20, 0x95, 0x00, 0xeb, 0xbb, 0xe4, 0xe9, 0x70, 0x61, 0xb6, 0x8a, 0xc2, 0xf5, 0x41, + 0x26, 0xe0, 0xb1, 0xa0, 0x94, 0xd4, 0x25, 0x7c, 0x1f, 0xc7, 0x07, 0x5f, 0x27, 0x0d, 0x58, 0x04, 0x2d, 0x09, 0x38, + 0x5b, 0x8f, 0x34, 0xd8, 0xd4, 0x8b, 0x6a, 0xc7, 0xb7, 0x28, 0x9c, 0xb7, 0x8c, 0xf5, 0x30, 0x08, 0xf7, 0xb8, 0x6d, + 0x5f, 0xe1, 0x00, 0xbf, 0x79, 0x43, 0x3d, 0x3e, 0xf0, 0xe1, 0x35, 0xba, 0x28, 0x3a, 0x54, 0x4d, 0xf1, 0xa7, 0x05, + 0x69, 0x5e, 0x1a, 0xe6, 0x70, 0x6f, 0x25, 0x5d, 0xf0, 0x82, 0xf1, 0x30, 0x22, 0x1a, 0x9b, 0xf4, 0xa0, 0x00, 0x9e, + 0xeb, 0xde, 0xcd, 0xbd, 0x7b, 0x2d, 0x49, 0xb5, 0x88, 0x36, 0x69, 0xe2, 0xbb, 0xb5, 0x66, 0x92, 0x35, 0x20, 0x49, + 0x69, 0xaf, 0xd8, 0x91, 0x50, 0xe2, 0xf5, 0x6f, 0xd2, 0xb3, 0x00, 0xc5, 0x77, 0xb3, 0xeb, 0x31, 0xe8, 0x52, 0xcf, + 0xd2, 0x0b, 0x56, 0x4b, 0xa0, 0x9a, 0xa9, 0x6a, 0xb2, 0xe1, 0x14, 0xd2, 0xd9, 0xd7, 0xc9, 0x2e, 0x3a, 0xa7, 0xa4, + 0x10, 0x4a, 0x19, 0xf5, 0x4c, 0xaa, 0x88, 0xe8, 0x58, 0x06, 0x3f, 0x2b, 0xcc, 0xa5, 0x3b, 0x68, 0x04, 0x16, 0x63, + 0x44, 0x6e, 0xc2, 0x61, 0xdf, 0xb7, 0x29, 0x01, 0xa1, 0x7e, 0xd7, 0x4e, 0x9c, 0xf5, 0x06, 0x07, 0x76, 0xbe, 0xff, + 0x03, 0x5f, 0x2b, 0x9f, 0x80, 0xd0, 0xc3, 0x89, 0x66, 0x49, 0xf1, 0x17, 0x2f, 0x3d, 0xf1, 0x4e, 0xac, 0xa4, 0x6e, + 0x3f, 0xf1, 0x87, 0x7f, 0x91, 0x2a, 0x6a, 0x1c, 0xc4, 0xb9, 0x75, 0x7f, 0x25, 0x0d, 0x8d, 0x1c, 0xad, 0x89, 0x7b, + 0x00, 0xb0, 0xd0, 0x84, 0x8a, 0xb0, 0x9c, 0x91, 0x34, 0xfc, 0x4c, 0xfd, 0xc4, 0x92, 0x27, 0x14, 0x2b, 0x04, 0x48, + 0xe0, 0xfb, 0xf7, 0x12, 0x5c, 0xb9, 0xef, 0x01, 0xfc, 0xc3, 0x62, 0x04, 0x5a, 0xc5, 0x12, 0x0d, 0x75, 0xf3, 0x91, + 0xf5, 0xdd, 0xe1, 0xa2, 0xd5, 0xd9, 0x46, 0x08, 0x2a, 0x74, 0xd7, 0x21, 0x40, 0xd8, 0xa7, 0x11, 0x78, 0xf2, 0xaf, + 0x92, 0xb8, 0xad, 0x64, 0x33, 0x1d, 0x76, 0xd7, 0x79, 0x05, 0xde, 0x3d, 0xe8, 0x17, 0x2b, 0xe3, 0x5d, 0xe5, 0x91, + 0xf5, 0xf1, 0xbf, 0x9f, 0x94, 0x5d, 0x52, 0x1b, 0x64, 0xa5, 0x00, 0xc4, 0x6a, 0xa4, 0xd7, 0x38, 0xd3, 0x54, 0xeb, + 0xd0, 0x5a, 0x93, 0x6d, 0x21, 0x6c, 0x87, 0xb0, 0x82, 0x07, 0xab, 0x19, 0x51, 0x27, 0x34, 0xb6, 0xb8, 0x97, 0x1e, + 0xba, 0xeb, 0xdd, 0x8b, 0xa0, 0xf2, 0x98, 0x1d, 0x32, 0x0f, 0x80, 0xef, 0x71, 0x63, 0x37, 0xc8, 0xac, 0xc0, 0x05, + 0x1c, 0x04, 0x8c, 0x5d, 0xcf, 0x5d, 0x30, 0xe4, 0x7a, 0x16, 0x37, 0x1c, 0xf6, 0x44, 0x03, 0x65, 0xd7, 0x01, 0x4d, + 0xa1, 0x75, 0x52, 0x91, 0xc6, 0xd0, 0x03, 0xbf, 0xaf, 0xc0, 0x3a, 0xeb, 0x51, 0x6c, 0x67, 0xd6, 0xe5, 0xb9, 0x54, + 0x78, 0x5a, 0xbc, 0x5e, 0xdb, 0xf4, 0x31, 0x1d, 0x9a, 0xad, 0x09, 0xdf, 0xeb, 0x2e, 0x60, 0x21, 0xac, 0xd4, 0x25, + 0x49, 0x5e, 0xd6, 0x1f, 0x2f, 0x32, 0x9a, 0x85, 0xc7, 0x5c, 0xda, 0x66, 0xf6, 0xdf, 0xef, 0x5f, 0xa0, 0xb5, 0x42, + 0xe1, 0xd3, 0x51, 0x40, 0x66, 0x25, 0x6d, 0x08, 0xde, 0xea, 0x6f, 0x36, 0xdb, 0x2c, 0xee, 0x5f, 0xdf, 0x55, 0xec, + 0xf5, 0xaf, 0x6f, 0xba, 0x71, 0x93, 0x02, 0xaf, 0x51, 0x50, 0x74, 0x6e, 0xb6, 0x27, 0x38, 0x21, 0xce, 0xad, 0x4a, + 0x58, 0xe7, 0x76, 0xfc, 0xb4, 0xa6, 0x4f, 0xff, 0xe0, 0x1d, 0x77, 0x80, 0x47, 0x2d, 0x4e, 0x96, 0x76, 0x4c, 0x3d, + 0x72, 0x16, 0x75, 0x2f, 0x3d, 0xec, 0x03, 0x9b, 0xc2, 0xe6, 0x96, 0xee, 0x7b, 0xfb, 0xd9, 0x73, 0x69, 0x8e, 0xb7, + 0xfa, 0xab, 0xfc, 0x95, 0xfb, 0xc6, 0x2a, 0x3b, 0x34, 0xac, 0xdd, 0x54, 0x49, 0x31, 0x5b, 0x7a, 0x99, 0xf5, 0x47, + 0xe1, 0x72, 0x9f, 0x3e, 0x17, 0x1a, 0xc5, 0x3d, 0x4e, 0x18, 0xb9, 0x09, 0x21, 0x1f, 0x7e, 0x49, 0x6c, 0x23, 0xf3, + 0x8f, 0x5b, 0x95, 0x31, 0x08, 0x22, 0xcf, 0x8e, 0x5a, 0x2f, 0xcb, 0x9c, 0x53, 0xe2, 0x62, 0x9e, 0x93, 0xe0, 0x17, + 0x34, 0xc2, 0xd1, 0x2a, 0xfb, 0x4b, 0x1d, 0xb6, 0x3b, 0x2c, 0x2b, 0x07, 0x1a, 0x37, 0xfb, 0x04, 0x9c, 0x11, 0x5d, + 0xab, 0xb0, 0xa3, 0xdd, 0xc8, 0xec, 0x62, 0xc3, 0xe1, 0xae, 0xb0, 0x04, 0xfc, 0xfc, 0x05, 0x8c, 0x41, 0xb7, 0x62, + 0xba, 0x52, 0xfb, 0x81, 0x41, 0xaa, 0x6a, 0x0f, 0xa5, 0xb8, 0x87, 0xe6, 0xca, 0xb4, 0x6b, 0xbd, 0xa3, 0x8e, 0x30, + 0xa0, 0x0e, 0xba, 0x0b, 0x1e, 0xb3, 0x02, 0x5c, 0xd7, 0x6d, 0xeb, 0xb8, 0xcb, 0x1a, 0x3b, 0xf1, 0x31, 0x5d, 0xfb, + 0xe7, 0xe0, 0xa8, 0x64, 0x47, 0xb7, 0x15, 0x27, 0xcc, 0xb0, 0xf2, 0xff, 0x14, 0x2e, 0x4f, 0x6f, 0x15, 0x6c, 0x0f, + 0x0d, 0xf5, 0xf9, 0x14, 0x6c, 0x75, 0x03, 0x1b, 0x1c, 0x41, 0x9b, 0x77, 0x72, 0x5d, 0xd2, 0x29, 0x13, 0xb2, 0xa6, + 0xb7, 0xa4, 0x29, 0x13, 0x9c, 0xe4, 0x5c, 0xc1, 0x7c, 0x2e, 0xce, 0x4c, 0x3e, 0x34, 0xa8, 0x15, 0x24, 0x6b, 0xc7, + 0x5e, 0x47, 0x5f, 0x88, 0xec, 0x7a, 0xce, 0xac, 0x75, 0xbf, 0x16, 0x9a, 0xc4, 0x72, 0xa8, 0x03, 0xe7, 0xeb, 0xdc, + 0xfc, 0x09, 0x0c, 0x01, 0x8f, 0xbf, 0xca, 0x18, 0xe7, 0x26, 0xed, 0x39, 0x33, 0xcb, 0x54, 0x2f, 0x15, 0x62, 0xd0, + 0xb7, 0x61, 0x42, 0x15, 0x8d, 0x17, 0xb3, 0xab, 0x54, 0x04, 0x46, 0x3e, 0x2c, 0x28, 0x43, 0x97, 0xe7, 0x1c, 0xe7, + 0x0d, 0xe5, 0x59, 0x64, 0x66, 0x00, 0x6c, 0xb4, 0x5d, 0x46, 0x09, 0xf7, 0x2e, 0xd3, 0x90, 0xd5, 0xa3, 0xb2, 0x79, + 0x8f, 0x3a, 0xbd, 0x68, 0x60, 0x05, 0xae, 0x9c, 0xae, 0x38, 0x9c, 0x14, 0x6a, 0x82, 0xb8, 0xcf, 0xfb, 0x84, 0x58, + 0x36, 0x2e, 0x31, 0x31, 0xcd, 0xb2, 0x2e, 0xef, 0xee, 0x77, 0x11, 0x34, 0x72, 0x42, 0x83, 0x85, 0x77, 0xf8, 0x0b, + 0xd8, 0x1d, 0xaf, 0xac, 0xc9, 0x0d, 0x86, 0xdf, 0x08, 0x24, 0xd3, 0x11, 0x42, 0x19, 0x4b, 0xe0, 0x76, 0xfa, 0xe9, + 0x7e, 0x0b, 0x6e, 0x1d, 0x22, 0x3d, 0x70, 0xb4, 0x10, 0x6c, 0xad, 0xb0, 0x36, 0x95, 0xe3, 0x86, 0x43, 0x71, 0x13, + 0x1a, 0x91, 0x8a, 0x68, 0x75, 0x89, 0x9e, 0xec, 0x0e, 0x41, 0xc4, 0xce, 0x21, 0x4b, 0x10, 0x41, 0x93, 0xa3, 0xfb, + 0x11, 0x5a, 0x96, 0x58, 0x22, 0x0d, 0x89, 0x5c, 0x77, 0x9e, 0xa1, 0x8a, 0x11, 0xd8, 0x76, 0x4a, 0x5d, 0x5b, 0x43, + 0xc1, 0x65, 0x6f, 0xd0, 0x75, 0x33, 0xc1, 0x89, 0x56, 0x42, 0x99, 0xd1, 0x29, 0xb9, 0x8f, 0xe9, 0x53, 0x3f, 0xca, + 0xc9, 0x28, 0x55, 0x37, 0xcc, 0xf5, 0x05, 0x42, 0x11, 0x88, 0x53, 0x97, 0x97, 0x53, 0xb5, 0x25, 0x65, 0xae, 0xb4, + 0x04, 0x73, 0xa4, 0xff, 0xb4, 0x47, 0x0d, 0xd9, 0x7a, 0x37, 0xec, 0xb4, 0xe9, 0x61, 0xd6, 0x42, 0x11, 0x8e, 0xb9, + 0x62, 0xb0, 0xda, 0xed, 0x23, 0x72, 0x6d, 0x83, 0xe9, 0x33, 0xbd, 0x9c, 0x86, 0x74, 0xa7, 0x57, 0x43, 0x33, 0x87, + 0x15, 0x7e, 0x28, 0xca, 0x3d, 0xe6, 0xe3, 0x76, 0x7f, 0x34, 0xf1, 0x59, 0x65, 0xdd, 0x7c, 0xc8, 0x7f, 0x85, 0xf4, + 0x73, 0x59, 0x8a, 0x93, 0xab, 0x1e, 0x78, 0xdb, 0x17, 0x06, 0x42, 0x2a, 0x57, 0x37, 0x9b, 0x5c, 0xc2, 0xb4, 0x13, + 0xb1, 0x4e, 0x64, 0x56, 0xbe, 0x89, 0x6c, 0x36, 0xda, 0x57, 0x7d, 0xaf, 0x5d, 0xbd, 0x29, 0x68, 0x5c, 0xab, 0x5f, + 0x74, 0x4b, 0x67, 0x7f, 0x6f, 0x95, 0x36, 0x74, 0x23, 0x1b, 0xe3, 0x0e, 0x44, 0xdb, 0xa5, 0x15, 0x45, 0x94, 0x5f, + 0x72, 0x72, 0x2f, 0x9d, 0x1f, 0x13, 0x1f, 0x8d, 0xef, 0xd2, 0x3e, 0x87, 0x23, 0x7c, 0x98, 0xfc, 0x0f, 0x27, 0x59, + 0x7f, 0xf7, 0x63, 0xd1, 0x9e, 0xf3, 0xbb, 0xad, 0x3b, 0xd8, 0x72, 0x3b, 0x96, 0x6e, 0xce, 0x65, 0x03, 0x7d, 0x17, + 0xe7, 0xf8, 0x2f, 0xbb, 0x9d, 0x94, 0xf5, 0xc1, 0x32, 0x85, 0x1c, 0x87, 0x09, 0x16, 0xa5, 0x9e, 0x14, 0xfa, 0x90, + 0x37, 0x34, 0xcd, 0x6a, 0x17, 0x93, 0xd7, 0x01, 0x02, 0x3f, 0x16, 0x75, 0xa1, 0x03, 0x99, 0x2a, 0xdd, 0x1a, 0x3f, + 0x1c, 0xd0, 0x47, 0x18, 0x13, 0xaa, 0x89, 0xe4, 0xb7, 0x04, 0x79, 0x17, 0x0a, 0xec, 0x71, 0x13, 0xb0, 0xa6, 0xd1, + 0x41, 0xa6, 0xae, 0x04, 0x49, 0xe4, 0x40, 0x2f, 0x7a, 0x07, 0xa1, 0x9d, 0x73, 0xd1, 0xe8, 0xaf, 0x57, 0xef, 0x9e, + 0x90, 0x9b, 0xad, 0xb2, 0xb3, 0x98, 0xb5, 0x87, 0x81, 0x58, 0xed, 0x4b, 0xdd, 0xf5, 0xba, 0x10, 0x18, 0x36, 0xfe, + 0x9b, 0x8d, 0x39, 0xc0, 0x76, 0x5e, 0x16, 0x7b, 0x57, 0xc0, 0x2f, 0xc1, 0x7f, 0xb5, 0x25, 0x0a, 0x4b, 0x74, 0x66, + 0x46, 0xe9, 0xe0, 0xee, 0x5b, 0xa8, 0x69, 0x08, 0x7a, 0x25, 0x2f, 0x69, 0xc4, 0xad, 0x94, 0xcb, 0x5b, 0x59, 0x63, + 0xf5, 0xd1, 0x30, 0xe5, 0xf1, 0x6b, 0x2d, 0xa0, 0x0b, 0x74, 0x81, 0x18, 0x1a, 0x52, 0x5b, 0xd2, 0x30, 0x05, 0x92, + 0x46, 0x6e, 0x1f, 0xb4, 0xb0, 0xc2, 0x69, 0xda, 0x46, 0x10, 0x27, 0xff, 0x0e, 0xc2, 0x70, 0xce, 0xef, 0xb6, 0x16, + 0x82, 0x1b, 0x88, 0xb4, 0x41, 0x56, 0x4e, 0x85, 0x5d, 0x01, 0xcd, 0xb7, 0x01, 0xa3, 0x15, 0x26, 0x19, 0x32, 0x49, + 0xf7, 0xe3, 0x3f, 0xf2, 0x0e, 0xbf, 0x3a, 0x73, 0x1e, 0x0a, 0x46, 0x0c, 0xb4, 0x43, 0x23, 0x1f, 0x14, 0xdc, 0x4e, + 0x96, 0xbd, 0xa0, 0x2e, 0x89, 0x59, 0xca, 0xe0, 0x14, 0x37, 0x85, 0xbe, 0x7c, 0x1c, 0x0e, 0x2a, 0x78, 0x63, 0x2c, + 0x0e, 0x74, 0x96, 0x82, 0x95, 0x0f, 0x7a, 0x96, 0x4e, 0x04, 0x98, 0x02, 0x9d, 0xc6, 0xd1, 0x6e, 0xc6, 0x5d, 0x29, + 0xdd, 0x0b, 0x50, 0x38, 0x2f, 0xa4, 0xd9, 0x08, 0x0a, 0x60, 0x37, 0x46, 0x4b, 0xf2, 0x8f, 0xbc, 0xc3, 0xf7, 0x33, + 0x71, 0x95, 0x5b, 0xe2, 0xd7, 0xca, 0x47, 0x0c, 0x64, 0x53, 0x7f, 0xb0, 0x7e, 0x4d, 0xcd, 0xd5, 0xee, 0x24, 0x1d, + 0x8e, 0xc3, 0x00, 0x38, 0xe6, 0x28, 0x96, 0x83, 0x58, 0x56, 0x20, 0xc9, 0x39, 0xb1, 0x5c, 0x3f, 0xe6, 0xcf, 0x49, + 0x62, 0x5f, 0xb5, 0x14, 0x57, 0xb8, 0x16, 0x4f, 0x8b, 0xe4, 0xc4, 0x1b, 0xfc, 0x2a, 0xfa, 0xef, 0xf6, 0x52, 0xc6, + 0x30, 0xf7, 0x53, 0x8c, 0x70, 0x43, 0xde, 0x32, 0x9f, 0x26, 0x81, 0x72, 0x56, 0x97, 0x83, 0x32, 0x9f, 0x5d, 0x2c, + 0x59, 0xe7, 0xd9, 0xf8, 0x4e, 0xce, 0x5b, 0xd7, 0xbd, 0xb0, 0x3f, 0x7a, 0x28, 0xdf, 0x1f, 0x2b, 0xff, 0x1e, 0x88, + 0x73, 0x28, 0x86, 0x11, 0x2b, 0x36, 0xea, 0xed, 0x49, 0xbe, 0x96, 0x0d, 0x74, 0xa4, 0x88, 0xf4, 0x95, 0x25, 0x3d, + 0x9f, 0x18, 0xd6, 0x45, 0x34, 0xf7, 0x6f, 0x30, 0x5d, 0x74, 0xf0, 0x0e, 0x13, 0x0c, 0xde, 0x2c, 0x4d, 0x5b, 0xdc, + 0x8f, 0x6d, 0x6a, 0x54, 0x28, 0x9c, 0x19, 0xd4, 0xb6, 0xc6, 0x0b, 0xec, 0x29, 0x5c, 0xfc, 0xc4, 0x39, 0x69, 0x5e, + 0x61, 0xb8, 0xb1, 0xa3, 0x95, 0x68, 0xa4, 0xb5, 0x1c, 0x1d, 0x74, 0xc8, 0xe4, 0xbd, 0x9c, 0x14, 0xb3, 0x48, 0x82, + 0x70, 0x5e, 0x2b, 0x1f, 0x4d, 0xbd, 0xb7, 0xb5, 0x6f, 0x30, 0xee, 0x02, 0x19, 0xb8, 0x4c, 0x16, 0x5a, 0x9a, 0x78, + 0xd9, 0x6d, 0xbe, 0x6d, 0xc3, 0x32, 0xe6, 0x56, 0x94, 0x55, 0x8c, 0x31, 0x89, 0x29, 0xda, 0xc5, 0xb2, 0xf1, 0x08, + 0xa6, 0x2e, 0x91, 0x24, 0x44, 0x96, 0xd1, 0x12, 0x8d, 0x6d, 0x50, 0xfa, 0x22, 0x66, 0x61, 0x30, 0xf2, 0x3f, 0xb3, + 0xf8, 0xcb, 0xb5, 0x7e, 0x2d, 0xcd, 0x14, 0xdd, 0x29, 0xf7, 0x6a, 0x6c, 0xdb, 0xe5, 0xf6, 0x6b, 0x3b, 0x44, 0x79, + 0xfd, 0x0a, 0x9e, 0x02, 0x4d, 0x8a, 0xe0, 0x10, 0x11, 0x68, 0x95, 0xf5, 0x45, 0x2d, 0x6d, 0x4b, 0x47, 0x7e, 0x4a, + 0x36, 0x11, 0xce, 0xf9, 0x21, 0xc4, 0xb3, 0x0a, 0xa2, 0x2e, 0x4b, 0x2f, 0x22, 0x1b, 0xb4, 0xb6, 0x3e, 0xd2, 0xa9, + 0x54, 0xc3, 0x07, 0x86, 0x22, 0xf2, 0x3d, 0xbc, 0x3a, 0x09, 0x5d, 0xda, 0x5a, 0x45, 0x49, 0xbc, 0x44, 0x3a, 0x7e, + 0x22, 0xab, 0x0e, 0x51, 0x24, 0xa8, 0x16, 0x0c, 0x6a, 0x05, 0xb8, 0x1c, 0x54, 0xb5, 0x37, 0x5b, 0x91, 0x08, 0x82, + 0x68, 0xb0, 0x8a, 0x0f, 0xd4, 0xed, 0x28, 0xc8, 0x24, 0xd2, 0x13, 0x63, 0x93, 0xf1, 0xe6, 0x85, 0xe4, 0x5e, 0x91, + 0x46, 0xa0, 0x4f, 0x9c, 0xd4, 0xb3, 0x71, 0x92, 0xf5, 0xfe, 0xa6, 0x8f, 0x1c, 0x1c, 0x37, 0x58, 0x4a, 0x8f, 0x62, + 0x07, 0xc7, 0x7a, 0x4e, 0x64, 0x2b, 0x29, 0xeb, 0x1c, 0x4a, 0x15, 0x6f, 0xc6, 0x28, 0x72, 0x2c, 0x63, 0x32, 0x70, + 0x36, 0x07, 0xd1, 0xb6, 0xa3, 0xf7, 0x94, 0xd8, 0xc8, 0x15, 0xf5, 0x02, 0xa5, 0x4e, 0xfc, 0xef, 0x13, 0xb4, 0xdf, + 0x6e, 0x4f, 0x08, 0xbd, 0x9d, 0x45, 0xb7, 0xf0, 0x45, 0xc7, 0x32, 0x6e, 0x0e, 0xdd, 0x49, 0x88, 0x63, 0x8a, 0x16, + 0x78, 0xc7, 0x0a, 0xc5, 0xb9, 0x68, 0x48, 0xec, 0x72, 0x6c, 0xd4, 0xfc, 0x54, 0x4d, 0x5d, 0xd6, 0x0a, 0xe9, 0x5d, + 0xfe, 0x1b, 0xf3, 0xbb, 0xfc, 0xf9, 0xf1, 0xa9, 0xca, 0xf5, 0x3a, 0x35, 0xc4, 0xe2, 0x0d, 0x2d, 0x13, 0x8d, 0x15, + 0x5e, 0x54, 0xc3, 0x1e, 0x25, 0x5b, 0x8b, 0xf4, 0x62, 0x65, 0xd5, 0x4c, 0xe4, 0x21, 0x09, 0x42, 0xd4, 0xe8, 0x84, + 0xba, 0x5b, 0xb8, 0xd0, 0xf8, 0x1d, 0x46, 0x26, 0x92, 0x01, 0x25, 0xdb, 0xea, 0x96, 0xfa, 0x51, 0x4b, 0x4f, 0x3d, + 0x9f, 0xcc, 0x06, 0x57, 0x4d, 0xa3, 0x71, 0x3a, 0xa6, 0xc6, 0x89, 0xb7, 0x8f, 0x66, 0x7a, 0x8d, 0x06, 0x0b, 0xbc, + 0xb0, 0xbb, 0xfe, 0x0d, 0x74, 0xc4, 0x2d, 0x34, 0x4a, 0x6c, 0x48, 0xd6, 0x18, 0x93, 0x96, 0x30, 0x6d, 0x29, 0xb3, + 0x96, 0x71, 0xd0, 0x06, 0x1c, 0xb6, 0x21, 0x47, 0x6d, 0xc4, 0x71, 0x1b, 0xf3, 0x4b, 0x8b, 0xca, 0xaf, 0x33, 0x7a, + 0x4e, 0x66, 0x0c, 0x9c, 0xce, 0x18, 0xb9, 0xd3, 0x62, 0xe2, 0xee, 0x8c, 0x99, 0x5c, 0xb4, 0xba, 0xa8, 0x8a, 0x6a, + 0x51, 0x95, 0x95, 0xb2, 0x6f, 0x58, 0x92, 0x1b, 0xff, 0xa2, 0x64, 0xd4, 0x87, 0x98, 0x72, 0xd9, 0xea, 0xfe, 0xde, + 0xd3, 0xc9, 0x74, 0xe7, 0x25, 0x4c, 0xbc, 0x89, 0x22, 0x55, 0xe7, 0x96, 0xa9, 0x01, 0xf3, 0xe4, 0x95, 0xf9, 0x0d, + 0x09, 0x0d, 0x2c, 0x29, 0xb6, 0xdb, 0x1f, 0xcf, 0xfe, 0xed, 0x89, 0xaf, 0xaa, 0xee, 0x1b, 0x6f, 0x97, 0x9c, 0x9c, + 0xfb, 0xe0, 0xb9, 0x03, 0x8d, 0xa7, 0xe7, 0x0d, 0x63, 0xf7, 0x7e, 0x65, 0xd1, 0x2d, 0xca, 0x3c, 0x78, 0xd2, 0xf1, + 0x17, 0xe1, 0x5a, 0x32, 0xe9, 0xef, 0xd0, 0x21, 0x59, 0x6a, 0xe4, 0x46, 0xfd, 0xcd, 0x35, 0x68, 0xb4, 0xd3, 0xcc, + 0xd3, 0x8a, 0xb1, 0x7f, 0xa8, 0xd9, 0x90, 0xea, 0xcb, 0xcc, 0x72, 0xbe, 0x1c, 0x2d, 0x2a, 0xe3, 0x9c, 0x56, 0xb8, + 0xb1, 0xe2, 0x98, 0x67, 0xc7, 0x16, 0xf3, 0x49, 0x93, 0x47, 0xd5, 0xf0, 0x98, 0x4b, 0x41, 0x46, 0x62, 0xa1, 0xf7, + 0xfc, 0xd0, 0x1f, 0xb7, 0x26, 0xc3, 0x27, 0x6b, 0xbd, 0xbd, 0x79, 0xf3, 0xe4, 0x8d, 0xa6, 0x09, 0x15, 0xe7, 0x92, + 0xa4, 0x92, 0xce, 0x2d, 0x96, 0x64, 0xde, 0x80, 0x8d, 0x9a, 0x1b, 0xe7, 0x86, 0x42, 0xde, 0x08, 0x8d, 0xdc, 0x4e, + 0x99, 0x84, 0xf4, 0xfe, 0xfa, 0xf7, 0xfa, 0x9b, 0xd5, 0xe3, 0x7c, 0xfa, 0x03, 0xc3, 0x66, 0x02, 0x00, 0x46, 0x4b, + 0xdf, 0xfb, 0xcf, 0xeb, 0x37, 0xd5, 0xd3, 0xca, 0xaf, 0xeb, 0xe7, 0x55, 0xa9, 0x3d, 0x87, 0xd0, 0xc1, 0x1c, 0x5f, + 0xe6, 0x9d, 0x27, 0x1b, 0xb7, 0x2b, 0xb8, 0xdb, 0x0c, 0xdd, 0xb3, 0xd8, 0xc4, 0xc6, 0x64, 0xba, 0xf8, 0xfc, 0xd3, + 0x55, 0x1f, 0x4d, 0x91, 0xda, 0xee, 0xcf, 0xf5, 0x38, 0x1f, 0xf7, 0xf8, 0x3b, 0xf1, 0xcd, 0x8e, 0x38, 0x8b, 0xc2, + 0xa9, 0xfc, 0xe7, 0xa1, 0xf4, 0xb8, 0xfc, 0xc4, 0x45, 0xad, 0xb0, 0x66, 0xf0, 0x2c, 0xbf, 0xf7, 0xb7, 0x11, 0x0f, + 0x3c, 0x35, 0xae, 0xfb, 0xf9, 0x33, 0x96, 0xff, 0x45, 0xc5, 0x2a, 0x0f, 0x8f, 0x6f, 0xf1, 0xdd, 0xac, 0xd6, 0x24, + 0xd2, 0x34, 0x08, 0xc2, 0x8a, 0xfc, 0x50, 0xfd, 0xb0, 0x3c, 0x27, 0x89, 0xae, 0xfd, 0xa7, 0xc7, 0x33, 0x08, 0x1d, + 0x83, 0x78, 0x75, 0x4d, 0x14, 0x0f, 0x3f, 0xa0, 0x7c, 0x3c, 0x04, 0x73, 0x08, 0xf4, 0x5f, 0xdf, 0x8d, 0x09, 0xc7, + 0xce, 0x11, 0x82, 0x08, 0x6b, 0xbd, 0x9f, 0x9f, 0xf9, 0x40, 0x81, 0x0f, 0xa3, 0xff, 0x66, 0x52, 0x4c, 0x01, 0x72, + 0xea, 0x44, 0x4c, 0xff, 0x66, 0xa0, 0x64, 0x05, 0x3a, 0xa8, 0xeb, 0x40, 0xf1, 0xa0, 0x06, 0xdd, 0x4d, 0x8e, 0xe1, + 0x76, 0xce, 0x32, 0x75, 0x76, 0xa9, 0xd3, 0xf3, 0x93, 0x26, 0x64, 0xa7, 0x97, 0x6a, 0x52, 0xc0, 0x65, 0xf9, 0x75, + 0x74, 0xf7, 0x05, 0x64, 0x2c, 0xd0, 0x8d, 0x87, 0xb6, 0x89, 0x6f, 0x0e, 0x72, 0x79, 0xde, 0x98, 0xd7, 0x88, 0x37, + 0xc6, 0x3f, 0x3b, 0x20, 0x1c, 0x72, 0x4f, 0x72, 0xcc, 0x7d, 0xc4, 0x73, 0xe8, 0xfe, 0x94, 0x74, 0x3f, 0x6c, 0xf6, + 0x4e, 0x8b, 0xff, 0xb1, 0xca, 0xd1, 0x85, 0x51, 0xf2, 0xbc, 0xde, 0xe7, 0xa1, 0xb1, 0xb3, 0x32, 0xb5, 0x7a, 0x26, + 0x6d, 0x08, 0x0d, 0x76, 0xfc, 0xbc, 0x39, 0xe5, 0xfe, 0x4c, 0x6c, 0x94, 0x18, 0xcd, 0x40, 0xec, 0x24, 0xd3, 0xa0, + 0x51, 0x44, 0xe0, 0xff, 0x20, 0x06, 0xb5, 0x8b, 0x35, 0x42, 0x21, 0xac, 0xe5, 0x53, 0x68, 0x79, 0x35, 0x8f, 0xde, + 0x48, 0x57, 0xe2, 0xc4, 0x72, 0xa6, 0x39, 0xe6, 0x5c, 0xc5, 0xcf, 0xc9, 0x8e, 0x15, 0xbc, 0xc8, 0xf4, 0x16, 0x8e, + 0xe7, 0x47, 0xcc, 0xf8, 0xdc, 0x43, 0x77, 0x5c, 0x1c, 0x59, 0xb3, 0x80, 0x36, 0xd5, 0x6e, 0x80, 0x6a, 0x90, 0xc0, + 0xb5, 0x08, 0xfd, 0x5e, 0x25, 0x38, 0xd2, 0x9c, 0x97, 0xb5, 0x18, 0xf5, 0x44, 0x1e, 0x39, 0x1b, 0x5c, 0x8c, 0x7a, + 0x52, 0x79, 0x01, 0xc1, 0xa7, 0xa0, 0xdb, 0x06, 0xd5, 0x64, 0xd9, 0xbf, 0x24, 0xcd, 0x61, 0xa0, 0xd7, 0x58, 0x80, + 0x59, 0xf3, 0x8f, 0x52, 0xff, 0xfb, 0x4d, 0xc9, 0xbd, 0x21, 0xfe, 0x03, 0x20, 0xe6, 0xea, 0xa6, 0xcd, 0xb3, 0x51, + 0x95, 0x0b, 0xed, 0x12, 0x4e, 0x2f, 0x55, 0xbc, 0x86, 0x4d, 0x85, 0x72, 0x4a, 0x02, 0x51, 0x27, 0x9c, 0x2d, 0x1d, + 0x21, 0x3c, 0x4f, 0xd6, 0x0e, 0x4d, 0xe8, 0x3d, 0x60, 0xeb, 0x5d, 0x4b, 0xfb, 0x28, 0xe7, 0xf2, 0xec, 0xeb, 0xfc, + 0x64, 0x5f, 0x4e, 0x32, 0x19, 0xff, 0x89, 0x9a, 0xc6, 0x2b, 0xd4, 0x27, 0x15, 0xbd, 0x7e, 0x3e, 0x56, 0x94, 0xa4, + 0xb1, 0x1d, 0xf1, 0xab, 0xad, 0xc0, 0xff, 0x4a, 0x5f, 0x8b, 0x58, 0x75, 0xfa, 0x46, 0x8f, 0xa3, 0x2e, 0xe7, 0xd2, + 0xbf, 0xbc, 0xb1, 0x64, 0x6d, 0x59, 0x02, 0x13, 0xdb, 0x3d, 0xdf, 0x96, 0xc1, 0xac, 0xb5, 0x8a, 0x4d, 0xde, 0x6d, + 0x45, 0xe9, 0x6b, 0x75, 0x6d, 0xd2, 0x6e, 0x3c, 0x80, 0xcb, 0x63, 0xb5, 0x52, 0x33, 0x92, 0x64, 0xa6, 0x77, 0xbe, + 0x7b, 0xce, 0xa5, 0x52, 0xa1, 0xc4, 0x1d, 0x32, 0xbe, 0x3b, 0x30, 0x76, 0x7f, 0xae, 0xa1, 0x1a, 0x9d, 0x1b, 0xe1, + 0x69, 0xe9, 0x10, 0x02, 0x4f, 0x1c, 0xf7, 0xc7, 0xbe, 0x6c, 0x1b, 0x9d, 0xd1, 0xe9, 0x1c, 0xad, 0x8b, 0xc6, 0x3f, + 0xba, 0x55, 0x34, 0x9b, 0xbd, 0xad, 0x2c, 0x36, 0x8f, 0xcd, 0xf2, 0x28, 0x73, 0xf1, 0x3f, 0xf1, 0xa7, 0xe1, 0x54, + 0xe7, 0x40, 0xb6, 0x74, 0x35, 0x65, 0x12, 0xc8, 0x11, 0x5e, 0xcf, 0xf5, 0x0e, 0x48, 0x3e, 0x77, 0x4b, 0xa0, 0x0c, + 0x45, 0x56, 0x33, 0x2a, 0xae, 0x8a, 0x15, 0x99, 0x67, 0xd6, 0x24, 0x78, 0xa1, 0x77, 0xa0, 0x39, 0x8b, 0x35, 0x6b, + 0x24, 0x71, 0xde, 0x43, 0xca, 0x8e, 0x7c, 0xd8, 0xc8, 0x1c, 0xc2, 0xc3, 0x26, 0x7e, 0xd6, 0x63, 0x02, 0x85, 0x13, + 0x03, 0xe8, 0xed, 0x2f, 0xc0, 0xea, 0xcf, 0x14, 0xeb, 0x83, 0xec, 0x74, 0xd6, 0xae, 0xe9, 0x0f, 0x97, 0x79, 0x9f, + 0xd8, 0xd3, 0xf5, 0xdb, 0xb0, 0x76, 0x4c, 0x2d, 0xed, 0x3c, 0xc0, 0xce, 0x6b, 0xf8, 0xae, 0x43, 0xb5, 0xaf, 0x11, + 0xba, 0x1f, 0xb9, 0xc9, 0x63, 0x0a, 0x1d, 0x7b, 0xfc, 0x27, 0xc0, 0x43, 0x0a, 0x5d, 0x05, 0xee, 0x53, 0x58, 0x3f, + 0x0e, 0xc0, 0x5d, 0x0a, 0xd5, 0x13, 0xb8, 0x4d, 0x61, 0x44, 0xfc, 0x5e, 0x79, 0x93, 0x82, 0x7d, 0x14, 0xee, 0xf2, + 0xbe, 0xac, 0xe8, 0xcd, 0xbb, 0x3e, 0xde, 0x3e, 0x2a, 0x57, 0xde, 0xd3, 0xfb, 0x7a, 0xbc, 0x5b, 0xbd, 0x09, 0x4c, + 0x9f, 0xa8, 0xc4, 0x9b, 0x02, 0xcf, 0x9f, 0xb0, 0xe2, 0x5d, 0x1e, 0xaf, 0x9b, 0x77, 0x71, 0xa5, 0x7b, 0x75, 0xff, + 0x3f, 0xb4, 0x35, 0xe6, 0xed, 0x1c, 0xdf, 0x6d, 0x2b, 0xe7, 0x59, 0xde, 0xee, 0x9d, 0xfd, 0xeb, 0x59, 0x3c, 0x80, + 0xd3, 0x14, 0x9a, 0x0a, 0x9c, 0xa4, 0x50, 0x56, 0xe0, 0x38, 0x85, 0x53, 0x6d, 0x9a, 0x16, 0xd8, 0x4d, 0x41, 0x37, + 0xe0, 0x28, 0x85, 0xcd, 0x37, 0xb0, 0x97, 0x42, 0xf1, 0xbc, 0xb5, 0xc0, 0x7e, 0x0a, 0x7a, 0x05, 0x0e, 0x04, 0xf2, + 0x2a, 0xef, 0xf0, 0x9f, 0x8d, 0xe3, 0x37, 0x18, 0x7b, 0xa8, 0xf6, 0x0c, 0x37, 0xfa, 0x1b, 0x18, 0xce, 0x5d, 0x8e, + 0x5d, 0x7d, 0x3a, 0x03, 0x97, 0xcc, 0xbf, 0x85, 0xd6, 0x9b, 0x44, 0xf8, 0x63, 0x40, 0x12, 0xab, 0xd3, 0x7d, 0x05, + 0xbc, 0xda, 0x1f, 0x7a, 0x3e, 0x67, 0x61, 0xee, 0xc2, 0x2b, 0x06, 0xac, 0x62, 0x51, 0x9e, 0xfa, 0xbf, 0x0c, 0x21, + 0xbb, 0x6d, 0x48, 0x32, 0x23, 0xdb, 0x0f, 0x8b, 0x13, 0xa3, 0x3e, 0x29, 0x4d, 0x6c, 0x55, 0x3a, 0x43, 0x45, 0x93, + 0x9b, 0xe0, 0x51, 0x52, 0xaa, 0xc0, 0xdc, 0x45, 0xf7, 0x44, 0xf8, 0x66, 0xbd, 0xc3, 0xf5, 0x53, 0x52, 0x21, 0x4a, + 0x86, 0xf4, 0xeb, 0xbf, 0x9c, 0x4d, 0x4f, 0xa9, 0xf5, 0xe4, 0x45, 0xfc, 0xc9, 0xf7, 0xd5, 0xb5, 0x29, 0x30, 0x79, + 0x66, 0x72, 0x99, 0xa7, 0x6d, 0xf5, 0x1e, 0xdb, 0x21, 0x59, 0xbb, 0x3d, 0x05, 0x2f, 0x89, 0xf5, 0x6f, 0x72, 0xcd, + 0x02, 0x7b, 0x4f, 0x30, 0xa7, 0x61, 0x89, 0x12, 0x25, 0x46, 0x62, 0xbc, 0xea, 0x41, 0x61, 0xcc, 0x70, 0x8d, 0xbf, + 0x4a, 0xed, 0xdf, 0xce, 0xa6, 0x3a, 0x01, 0x0b, 0x39, 0xd7, 0x61, 0x78, 0xe0, 0x24, 0xa4, 0x1c, 0xb2, 0x48, 0x68, + 0xa3, 0x99, 0x4e, 0xaa, 0xa7, 0x5a, 0x3d, 0xd8, 0x8d, 0x96, 0x27, 0xa2, 0x77, 0xed, 0xa8, 0x9c, 0x89, 0xa0, 0xbb, + 0x81, 0xd3, 0x1c, 0xfa, 0x63, 0x5a, 0xf2, 0x32, 0x80, 0x14, 0xbe, 0xf1, 0x76, 0x6a, 0xec, 0x5f, 0xe2, 0x3b, 0xb6, + 0xa2, 0x5c, 0xe1, 0x4f, 0xf0, 0x1b, 0xb6, 0x36, 0x9b, 0xbf, 0x61, 0x75, 0x79, 0xb8, 0x15, 0xb0, 0x02, 0x30, 0x7f, + 0x67, 0xcd, 0xf6, 0xe9, 0x08, 0x27, 0x93, 0xb7, 0x82, 0xb2, 0xd2, 0x80, 0x85, 0xf1, 0x36, 0x01, 0xbf, 0x15, 0x06, + 0x37, 0xdb, 0x9b, 0x33, 0x31, 0x77, 0x22, 0x5a, 0x5c, 0x06, 0x76, 0x0f, 0x6e, 0xd4, 0xc2, 0x4a, 0xdd, 0x1c, 0xf6, + 0xf7, 0xea, 0x06, 0x25, 0x2e, 0x82, 0xb0, 0x55, 0x75, 0x40, 0xd6, 0xb8, 0x8e, 0x22, 0x9f, 0x87, 0x7d, 0xb3, 0xdd, + 0x5b, 0xa9, 0x25, 0x5b, 0xde, 0xeb, 0xb5, 0xea, 0x27, 0x55, 0x4d, 0x9f, 0xce, 0xb1, 0xec, 0x34, 0x66, 0xc9, 0x4f, + 0x5b, 0x7b, 0x78, 0xc5, 0x15, 0x82, 0x68, 0xd5, 0x14, 0x33, 0xf3, 0x41, 0x1d, 0x34, 0x61, 0xae, 0xc2, 0xe3, 0x98, + 0x60, 0x80, 0xd9, 0x79, 0x78, 0x11, 0x42, 0x07, 0xc1, 0x76, 0xce, 0xc1, 0x56, 0xf1, 0xb4, 0x69, 0x2d, 0x0b, 0x68, + 0x1a, 0x8d, 0xfd, 0x28, 0x6b, 0xfc, 0x41, 0x36, 0x6a, 0x9d, 0x5a, 0xda, 0x1e, 0x47, 0x4f, 0x31, 0x7f, 0x1b, 0x50, + 0x11, 0xd0, 0x66, 0x90, 0xb3, 0x41, 0xa3, 0x72, 0xf1, 0xdf, 0x09, 0xa4, 0x33, 0xed, 0xdf, 0x70, 0x36, 0xa6, 0x35, + 0x68, 0xf6, 0x8d, 0xf6, 0x43, 0x4c, 0xdf, 0x17, 0x6c, 0x11, 0xbd, 0xe4, 0xb8, 0xe5, 0x29, 0x1a, 0xb8, 0x4a, 0xa6, + 0x4b, 0x70, 0x84, 0x2e, 0xca, 0xbd, 0xf7, 0x49, 0xf8, 0x93, 0x00, 0xd6, 0x8f, 0x3e, 0xa6, 0x53, 0xb6, 0x0e, 0x0e, + 0x95, 0xb1, 0x47, 0xcd, 0x32, 0x56, 0xf0, 0x4a, 0x7a, 0x23, 0x33, 0x00, 0x02, 0x01, 0xcf, 0x65, 0x87, 0x3f, 0xd5, + 0x07, 0xb9, 0x2a, 0xc0, 0x6a, 0xe9, 0x66, 0x3b, 0x1d, 0x6a, 0xcd, 0x8f, 0x79, 0x5b, 0xda, 0xd1, 0xa3, 0x77, 0xb4, + 0xbd, 0xac, 0xc1, 0x05, 0x39, 0x72, 0x09, 0x3a, 0x4b, 0x65, 0x54, 0xe1, 0x3a, 0x34, 0xe0, 0x7c, 0x29, 0xd4, 0x28, + 0x5a, 0xf4, 0x9b, 0x1b, 0x7d, 0xcb, 0x5e, 0x1e, 0x41, 0x63, 0xce, 0xfb, 0x4d, 0x36, 0x57, 0x2d, 0x10, 0x84, 0x39, + 0xb6, 0xa5, 0xf7, 0x1f, 0x13, 0x9c, 0x6f, 0x5f, 0xb0, 0xdd, 0x72, 0xcb, 0x03, 0xb6, 0xfe, 0x89, 0x47, 0x15, 0x8a, + 0x9d, 0x78, 0x56, 0x56, 0x67, 0x57, 0x6d, 0xad, 0x31, 0xa4, 0xff, 0x6a, 0xbd, 0x6b, 0x6b, 0x5a, 0x7b, 0x07, 0x3c, + 0x08, 0x84, 0x74, 0xb8, 0x1c, 0x48, 0xc4, 0x7a, 0x4b, 0x87, 0x87, 0x12, 0xe1, 0x80, 0xec, 0x01, 0xb3, 0x73, 0x1b, + 0xda, 0xb3, 0x87, 0x07, 0xb8, 0x97, 0x39, 0xd0, 0x80, 0x5c, 0x1e, 0x1e, 0xe5, 0xd9, 0xfd, 0x01, 0x09, 0xf0, 0x16, + 0x0a, 0x58, 0x6a, 0x80, 0x75, 0x47, 0x4c, 0xb8, 0x7c, 0x20, 0xcb, 0xce, 0x8b, 0x40, 0xc7, 0x95, 0xd3, 0xc0, 0x46, + 0x0f, 0x1e, 0x42, 0xf1, 0x64, 0x73, 0xac, 0x71, 0x6e, 0x4d, 0x7a, 0xe1, 0x08, 0xc9, 0x98, 0xb9, 0x47, 0x8c, 0x1c, + 0x52, 0x1f, 0x26, 0xa6, 0x8b, 0x49, 0x7a, 0x5c, 0xb1, 0x2e, 0x86, 0xc0, 0x8e, 0x60, 0xe9, 0x0b, 0xc4, 0xde, 0x64, + 0x2c, 0x61, 0x82, 0x58, 0x47, 0x83, 0x18, 0xc2, 0xc6, 0x1d, 0x96, 0xa6, 0x6e, 0x02, 0x16, 0x81, 0xeb, 0x45, 0x90, + 0x4b, 0x61, 0x8d, 0x67, 0xe1, 0xdd, 0x3b, 0x9f, 0xc6, 0xdb, 0xfd, 0xaf, 0xf8, 0xd0, 0xa8, 0x36, 0x5a, 0x94, 0xbe, + 0xee, 0x00, 0xc6, 0xec, 0x57, 0xe0, 0x33, 0x05, 0x42, 0x9c, 0xfb, 0xfb, 0x57, 0x58, 0xe6, 0xf0, 0xda, 0x06, 0x19, + 0x8c, 0xcc, 0xbe, 0x1c, 0xd8, 0xa4, 0x96, 0x48, 0xe6, 0x2b, 0x86, 0xb7, 0x80, 0x55, 0xe9, 0x4b, 0xa2, 0x36, 0xcc, + 0xdd, 0xf8, 0xae, 0x0e, 0x1a, 0x6d, 0xe5, 0x47, 0x68, 0x1c, 0x4c, 0xde, 0xea, 0xc4, 0x40, 0x86, 0x78, 0x12, 0xab, + 0xbe, 0xb8, 0x68, 0x6b, 0x90, 0x34, 0x3d, 0x06, 0x14, 0x8a, 0x5d, 0xbc, 0xbd, 0x60, 0xbb, 0xa4, 0x06, 0xb0, 0xb1, + 0x31, 0x69, 0x98, 0x1d, 0xb5, 0x26, 0xa6, 0xed, 0x3d, 0x3e, 0x4a, 0x9b, 0x23, 0x77, 0x0f, 0x6b, 0x2a, 0xdb, 0x9d, + 0x27, 0x4a, 0x1c, 0x73, 0x70, 0x86, 0x5f, 0x1f, 0x98, 0x80, 0x7c, 0x3f, 0x3e, 0x11, 0x87, 0x83, 0xaf, 0xc7, 0x09, + 0x94, 0x88, 0x42, 0x2d, 0xc0, 0x03, 0x11, 0x10, 0xc7, 0xee, 0x08, 0x20, 0xeb, 0x7d, 0xbc, 0x94, 0xad, 0x56, 0xbd, + 0x9c, 0x5e, 0x6c, 0x34, 0x01, 0x42, 0x7c, 0xca, 0x21, 0x48, 0xc9, 0xe2, 0xc1, 0x01, 0xc4, 0x0c, 0x54, 0x30, 0x65, + 0x37, 0xbc, 0x51, 0x18, 0x0b, 0x2d, 0x51, 0x9d, 0xc0, 0xc5, 0x11, 0xa8, 0xe9, 0x27, 0x3f, 0x64, 0x03, 0x18, 0x4a, + 0xa9, 0x09, 0x92, 0xae, 0x1c, 0x10, 0xa0, 0x4b, 0x44, 0x42, 0xfc, 0x72, 0x31, 0x40, 0x80, 0x0d, 0xd6, 0x9b, 0xe0, + 0xa6, 0x49, 0x8d, 0xe1, 0x70, 0xff, 0x94, 0x17, 0xad, 0xef, 0x53, 0x20, 0x1b, 0x13, 0x68, 0x5e, 0xfc, 0xe8, 0x48, + 0x2d, 0x74, 0x19, 0x1a, 0x2e, 0x29, 0xd6, 0xb2, 0x1f, 0xa6, 0xc5, 0x96, 0xa9, 0x41, 0x88, 0xa0, 0x1f, 0xfc, 0xfa, + 0x32, 0xa3, 0x91, 0x5c, 0x7c, 0x10, 0x7e, 0x08, 0xee, 0x05, 0x78, 0x1c, 0x19, 0x24, 0x29, 0x05, 0x9c, 0x46, 0x95, + 0x08, 0xf7, 0xb8, 0x0b, 0x39, 0x82, 0xe8, 0xf7, 0xb8, 0x4d, 0x8d, 0x16, 0x45, 0xaa, 0x70, 0xd3, 0xef, 0xdb, 0xdb, + 0x45, 0x7d, 0x0d, 0x0f, 0xf0, 0x23, 0x20, 0xbe, 0x26, 0x6e, 0x8c, 0x57, 0x21, 0x9f, 0x92, 0x01, 0x61, 0x02, 0x6a, + 0x42, 0x19, 0x73, 0x0e, 0x37, 0xe6, 0x8a, 0x2c, 0x14, 0x92, 0x41, 0xc3, 0x6d, 0x5d, 0xc2, 0x98, 0x14, 0xc7, 0x89, + 0x40, 0xfc, 0x9e, 0x12, 0x4b, 0x9e, 0x5a, 0x00, 0xf0, 0xad, 0xa2, 0xb9, 0x75, 0xd0, 0x26, 0x13, 0xc4, 0xc9, 0xbe, + 0xc7, 0xf2, 0xdd, 0x66, 0x7f, 0xc6, 0x5f, 0x48, 0x3a, 0x4e, 0x12, 0xf1, 0xae, 0xa7, 0x29, 0xc2, 0x3e, 0x87, 0xaa, + 0x2e, 0x38, 0x04, 0x58, 0xfc, 0x10, 0x16, 0x0c, 0xb2, 0xc1, 0x51, 0xac, 0x07, 0x82, 0xa0, 0x98, 0x84, 0xb6, 0xb3, + 0x10, 0xb7, 0xc1, 0xea, 0x18, 0x95, 0x35, 0x12, 0x24, 0x93, 0x35, 0x13, 0xa2, 0xa6, 0x7e, 0xa2, 0x37, 0x3c, 0xa9, + 0x1d, 0xcf, 0xdd, 0xc4, 0xf4, 0x1a, 0xf9, 0xb1, 0xba, 0x34, 0xd6, 0xe7, 0xbd, 0x85, 0xe4, 0x63, 0xc0, 0x27, 0x89, + 0x0d, 0xd1, 0xfc, 0xc3, 0xb0, 0x6c, 0x18, 0x27, 0x25, 0x1b, 0x4b, 0x35, 0x3a, 0xeb, 0xcc, 0xe3, 0x3d, 0x3f, 0xbf, + 0x5a, 0x0c, 0x49, 0x89, 0xef, 0xe1, 0x0b, 0x59, 0xdb, 0xd1, 0xfa, 0x53, 0xd6, 0x03, 0xa2, 0x3a, 0x13, 0xe0, 0x3d, + 0x56, 0xb3, 0x09, 0x8d, 0x82, 0x0c, 0xe2, 0x7a, 0x6b, 0xb4, 0xd7, 0x9b, 0x6c, 0xfb, 0x25, 0xb7, 0x47, 0xf5, 0x2b, + 0x88, 0xbc, 0xc2, 0xec, 0x7a, 0x3f, 0x6a, 0x87, 0x00, 0x1e, 0x2f, 0xb8, 0x5b, 0x03, 0xf7, 0x5c, 0xc5, 0x82, 0xe4, + 0xcd, 0x54, 0xe8, 0x9c, 0x73, 0x3f, 0xa4, 0xce, 0xd1, 0xbb, 0x71, 0xe3, 0xff, 0x34, 0x57, 0x96, 0x65, 0x96, 0xc2, + 0x64, 0x0c, 0x09, 0x95, 0x08, 0xcf, 0xdd, 0x16, 0xd6, 0x45, 0x79, 0x28, 0x8d, 0xae, 0x31, 0xa8, 0x47, 0x9d, 0x55, + 0x9a, 0x46, 0xb2, 0xf8, 0x1e, 0xed, 0x68, 0xbd, 0x30, 0x15, 0xa0, 0x59, 0x4a, 0xa9, 0x65, 0xd9, 0x3e, 0x97, 0x4b, + 0xa1, 0xef, 0xb4, 0x15, 0xfe, 0xfc, 0x0c, 0xf7, 0xdc, 0xa4, 0xdb, 0x0d, 0xf6, 0x1b, 0xdb, 0xc1, 0x8d, 0xc1, 0x34, + 0x7f, 0xfd, 0xbc, 0x19, 0x66, 0x83, 0x19, 0xcc, 0xc5, 0xb3, 0xbc, 0xc7, 0xb1, 0x2a, 0x6e, 0x5a, 0x1d, 0xf8, 0x27, + 0x37, 0x29, 0x36, 0x3f, 0x60, 0x86, 0x56, 0x7b, 0x97, 0x2b, 0x12, 0xce, 0xd7, 0xbc, 0x80, 0xbe, 0xc4, 0x2c, 0x26, + 0xcc, 0xe7, 0x7c, 0x1a, 0x10, 0x40, 0x55, 0x91, 0x3f, 0x4a, 0x29, 0x58, 0xd9, 0x12, 0xb9, 0x81, 0x0f, 0x54, 0x7b, + 0x40, 0xed, 0x64, 0xce, 0x57, 0x76, 0x48, 0x5d, 0x85, 0x5d, 0x81, 0x91, 0x9d, 0x93, 0x6b, 0x3b, 0x6e, 0xfb, 0x4f, + 0x97, 0x62, 0xbf, 0x58, 0x76, 0xd2, 0x73, 0xf4, 0x49, 0x2c, 0x9a, 0x85, 0x8e, 0x1e, 0xc9, 0xe9, 0x6b, 0xee, 0xef, + 0x8a, 0x48, 0x9e, 0xbf, 0xc1, 0xe5, 0x67, 0x29, 0x24, 0xf8, 0x47, 0x29, 0x6d, 0xb7, 0x23, 0xe6, 0x13, 0x5e, 0x43, + 0x69, 0xce, 0x42, 0xcb, 0x35, 0xd8, 0x00, 0x48, 0x18, 0x65, 0x34, 0x2a, 0xab, 0x6d, 0xfc, 0x75, 0x42, 0xa3, 0xfc, + 0x4b, 0x89, 0x05, 0x35, 0x98, 0x63, 0x44, 0xc5, 0x6b, 0x22, 0x84, 0xe7, 0xfe, 0x32, 0x17, 0xc7, 0x62, 0xd1, 0xe6, + 0xfe, 0x36, 0x67, 0x0b, 0x46, 0x65, 0xb6, 0x5a, 0x5f, 0x89, 0x1e, 0xda, 0x5d, 0x5d, 0xbc, 0x4c, 0xd7, 0xe6, 0xae, + 0x0f, 0x00, 0xe5, 0xa4, 0x0f, 0x96, 0x2e, 0xbc, 0x5e, 0x9f, 0x21, 0xc3, 0x06, 0xaf, 0x0b, 0xae, 0x22, 0xed, 0x07, + 0x48, 0xcd, 0x72, 0x6e, 0x6b, 0x57, 0x89, 0x9a, 0xec, 0x1b, 0x15, 0xa0, 0xef, 0x65, 0xce, 0x63, 0xa6, 0xd1, 0x47, + 0xad, 0x43, 0x8d, 0x18, 0x24, 0x42, 0xab, 0x88, 0xf8, 0xb3, 0xc9, 0x38, 0x0a, 0x45, 0xbc, 0x31, 0x61, 0xac, 0x50, + 0x20, 0x67, 0xf7, 0xdf, 0x3a, 0xbf, 0xba, 0xb2, 0x9f, 0x4e, 0x9a, 0xb2, 0x2e, 0x77, 0xed, 0x2e, 0xf8, 0xf4, 0xea, + 0x25, 0x26, 0x18, 0x17, 0x9f, 0xea, 0x95, 0xf7, 0x96, 0xbf, 0xea, 0x79, 0x7a, 0x77, 0x1d, 0x36, 0xf7, 0x11, 0xaa, + 0xc2, 0xaa, 0xb8, 0x63, 0xe6, 0x49, 0xd3, 0xfa, 0xcb, 0xf7, 0xa2, 0xf6, 0x8b, 0x1e, 0x1b, 0xe8, 0x65, 0x44, 0x71, + 0x3f, 0xd5, 0x5e, 0x3f, 0x28, 0x24, 0x8e, 0x5f, 0x27, 0x44, 0xc5, 0x55, 0xcb, 0xc2, 0xa7, 0x13, 0xac, 0x22, 0xab, + 0xe9, 0x9c, 0x44, 0x35, 0x10, 0xd9, 0x4c, 0x83, 0x00, 0x49, 0xe5, 0x29, 0xed, 0x21, 0xac, 0xdd, 0xd0, 0x2f, 0xef, + 0xc1, 0x08, 0x85, 0x0b, 0xd2, 0x4f, 0x32, 0xa7, 0xd4, 0xe6, 0x74, 0x46, 0x56, 0xe3, 0x80, 0x80, 0xdf, 0xff, 0xf7, + 0xcd, 0x57, 0xc2, 0xd4, 0x3e, 0x85, 0xf1, 0x59, 0xd1, 0x36, 0x41, 0x94, 0xdf, 0x43, 0x96, 0xb5, 0x17, 0xb9, 0xc8, + 0x2a, 0xd5, 0x65, 0xf2, 0x60, 0xcd, 0x6f, 0x62, 0x6c, 0xcb, 0xc3, 0x8d, 0x35, 0x5a, 0xc8, 0xe9, 0x36, 0x9a, 0x41, + 0xa1, 0x62, 0x4c, 0x7a, 0xf5, 0xe7, 0x15, 0x9b, 0xc7, 0x91, 0xc7, 0xaf, 0xf2, 0x29, 0x90, 0xc0, 0x6d, 0x62, 0x05, + 0x47, 0xcd, 0x4e, 0x45, 0x4d, 0x1f, 0x9e, 0xf3, 0xe5, 0xf1, 0x05, 0x50, 0x6d, 0xa8, 0x71, 0xc6, 0xbc, 0x56, 0x94, + 0x35, 0xa9, 0x23, 0x19, 0xcf, 0xbb, 0x0c, 0xb4, 0x9c, 0xa8, 0xe8, 0xbd, 0x5a, 0x52, 0xf4, 0x29, 0x5b, 0xbb, 0x0c, + 0xdf, 0x9a, 0x4c, 0xc8, 0x04, 0x05, 0x47, 0x20, 0xd2, 0xce, 0xc5, 0x0a, 0xed, 0xbf, 0x79, 0x52, 0xdf, 0x9b, 0xf1, + 0x49, 0x62, 0x44, 0x49, 0xc9, 0x77, 0x1f, 0x35, 0x5a, 0x08, 0xa2, 0xce, 0x86, 0x9b, 0xa4, 0x3f, 0xf3, 0xaa, 0x1c, + 0x13, 0x58, 0xe3, 0x48, 0x0c, 0xae, 0x2a, 0xfa, 0x09, 0x25, 0x5c, 0x21, 0xdd, 0x4e, 0x49, 0xc2, 0xd9, 0x23, 0xb4, + 0xa7, 0x79, 0xf5, 0xfd, 0x54, 0x95, 0x1f, 0x48, 0x04, 0x44, 0xb5, 0x19, 0x3a, 0x31, 0xf7, 0xf4, 0x75, 0xed, 0xd2, + 0x13, 0xfe, 0xfb, 0x52, 0xb9, 0x90, 0x3e, 0x8f, 0x17, 0xf3, 0xff, 0x7c, 0x33, 0xae, 0x23, 0x6d, 0xa3, 0xbe, 0xed, + 0x9a, 0x16, 0xed, 0xc8, 0xb2, 0x3e, 0x45, 0x0a, 0x0a, 0x43, 0x08, 0x25, 0x3f, 0x42, 0x58, 0x89, 0x6e, 0x8a, 0xae, + 0x22, 0x83, 0x35, 0x67, 0xc0, 0x0a, 0xaf, 0xea, 0xc0, 0xad, 0x22, 0x9f, 0xec, 0xbc, 0x62, 0x8b, 0xba, 0x4e, 0xa5, + 0x9b, 0x38, 0xe3, 0x77, 0x62, 0x82, 0x54, 0x6d, 0xdf, 0xf3, 0xc7, 0x3a, 0xa9, 0x39, 0xf9, 0x93, 0x8f, 0xf9, 0xd8, + 0x9d, 0xf4, 0xd7, 0x9d, 0xaf, 0xdb, 0x84, 0xb0, 0xe3, 0xa5, 0x4d, 0x4b, 0xb1, 0xc6, 0xdb, 0x60, 0x28, 0x5f, 0x89, + 0xa2, 0x4d, 0x7c, 0x8c, 0xc2, 0xbf, 0x29, 0xb4, 0x4f, 0x92, 0xb6, 0x59, 0x03, 0x45, 0x17, 0x6b, 0x7e, 0xfc, 0x6b, + 0x42, 0x83, 0x50, 0x0c, 0xd8, 0xd4, 0xf7, 0x32, 0x06, 0xed, 0xd3, 0x16, 0x0d, 0x1f, 0x7b, 0xf1, 0x01, 0x23, 0x4e, + 0x57, 0x3f, 0x06, 0xa8, 0x27, 0x8c, 0x63, 0x37, 0x4d, 0x2e, 0x92, 0x86, 0x51, 0xf1, 0x6a, 0x1c, 0xad, 0xdf, 0xdf, + 0xa7, 0xb1, 0x18, 0xfa, 0x6d, 0x06, 0x1f, 0x73, 0x73, 0x6e, 0xde, 0x1d, 0x93, 0x73, 0x72, 0x5e, 0x9e, 0x01, 0x39, + 0x74, 0x25, 0x78, 0x9c, 0x5c, 0x46, 0x69, 0x03, 0x6d, 0x3f, 0x6b, 0xec, 0x70, 0x28, 0xcb, 0xfb, 0xaa, 0x7a, 0x61, + 0xbf, 0xdb, 0xa4, 0xe0, 0x66, 0xcb, 0x37, 0xc5, 0xcf, 0xf2, 0xdf, 0xc0, 0x94, 0x30, 0x5f, 0x84, 0x24, 0xdf, 0x55, + 0xf9, 0xf5, 0xb1, 0x1f, 0x02, 0x78, 0x65, 0x94, 0x98, 0xb5, 0xab, 0xc2, 0xbc, 0x44, 0x3c, 0xc9, 0x9f, 0x2a, 0x42, + 0x10, 0x9d, 0x38, 0x64, 0xc9, 0xaf, 0x47, 0xc2, 0x66, 0x0c, 0x63, 0x73, 0x73, 0x91, 0x29, 0x7d, 0x4b, 0x93, 0x04, + 0x95, 0xe4, 0xa4, 0x02, 0x46, 0x2a, 0xc3, 0x19, 0xfe, 0x34, 0x97, 0x25, 0x7a, 0x8e, 0xd0, 0x7d, 0x8d, 0x6a, 0xdf, + 0x69, 0xdc, 0x26, 0xd7, 0x6a, 0x6e, 0xdc, 0x66, 0xfb, 0xee, 0xc9, 0x31, 0xf4, 0x38, 0xfb, 0x64, 0x42, 0xad, 0x3a, + 0xe1, 0xdc, 0xcd, 0xc3, 0xcb, 0xb8, 0x27, 0x7d, 0x43, 0x5b, 0x63, 0xe1, 0x6a, 0x0e, 0xf3, 0x23, 0xfd, 0x2e, 0xc6, + 0x90, 0xa7, 0xae, 0xb8, 0xdd, 0xa7, 0x71, 0xb4, 0x5e, 0x71, 0x0b, 0x32, 0x94, 0x5a, 0xf1, 0x01, 0x1b, 0xe5, 0x07, + 0x60, 0x8d, 0x0f, 0x01, 0xf9, 0xf6, 0x05, 0x17, 0xa8, 0x35, 0xcc, 0x2c, 0x2f, 0x3e, 0xbf, 0x98, 0x43, 0x38, 0xb9, + 0xa7, 0x4d, 0x0a, 0xb7, 0xdc, 0xa4, 0xe5, 0x6d, 0xd6, 0x4f, 0xd1, 0xf6, 0x90, 0xcb, 0x9e, 0xae, 0x3f, 0x61, 0x24, + 0x72, 0xe2, 0x84, 0xfb, 0xba, 0xb6, 0x58, 0xdf, 0x0f, 0xa3, 0xe2, 0xb4, 0x91, 0xeb, 0x91, 0x81, 0xab, 0x77, 0xf4, + 0x6e, 0x48, 0x3c, 0x55, 0xf3, 0x6b, 0xc5, 0xaa, 0x6e, 0x82, 0x7f, 0x1e, 0xab, 0x21, 0xed, 0x54, 0x5c, 0xec, 0xaf, + 0xce, 0x4e, 0xb2, 0xfc, 0x53, 0x0b, 0x48, 0x2f, 0x38, 0x76, 0x4d, 0x19, 0x6e, 0x21, 0xce, 0x77, 0x73, 0x3c, 0xbd, + 0xd4, 0xd2, 0x38, 0xa7, 0x88, 0x22, 0xa4, 0xb7, 0x82, 0xbf, 0xc7, 0xf0, 0xf5, 0x8c, 0xee, 0xa0, 0x11, 0x49, 0xce, + 0xbf, 0x3c, 0xa3, 0x59, 0xf9, 0xb5, 0xdd, 0x0a, 0x73, 0x07, 0x49, 0x5b, 0xc9, 0xe1, 0x0c, 0xd6, 0x86, 0x84, 0x0b, + 0xc9, 0x96, 0xa6, 0x4b, 0xaa, 0x3a, 0x60, 0x23, 0x7d, 0xd2, 0x27, 0x67, 0x1b, 0x9e, 0x88, 0x06, 0xc1, 0xf9, 0xf3, + 0x90, 0x0e, 0x96, 0xe3, 0xa5, 0x0d, 0x7d, 0x0a, 0x38, 0x5b, 0x36, 0x3e, 0xe8, 0xd4, 0x9a, 0x74, 0x3e, 0x52, 0x97, + 0x98, 0xe2, 0x27, 0xb6, 0xd2, 0x7d, 0x62, 0xbb, 0xd6, 0xa8, 0x7e, 0x5d, 0xdf, 0x6d, 0xea, 0x14, 0x99, 0x3a, 0x6d, + 0xca, 0x2d, 0xe4, 0xaa, 0xce, 0x77, 0x97, 0x1e, 0x6b, 0x19, 0xe4, 0xea, 0x97, 0x65, 0xbf, 0x49, 0xd0, 0xcd, 0xeb, + 0x7f, 0xca, 0xb5, 0xb3, 0xe5, 0x5a, 0xf9, 0x0c, 0x9a, 0xac, 0xae, 0xb5, 0xe9, 0xe6, 0x06, 0x56, 0x56, 0x48, 0x11, + 0x8a, 0x44, 0x48, 0x5b, 0x2d, 0xcf, 0x63, 0xf9, 0x12, 0x4e, 0xfc, 0xfd, 0x51, 0x30, 0x91, 0xa3, 0xa2, 0xb3, 0x50, + 0x37, 0xdb, 0x20, 0xa3, 0xe7, 0xe9, 0x01, 0xf7, 0x2a, 0xca, 0xd9, 0xc6, 0xed, 0x06, 0x51, 0x32, 0x7b, 0x5e, 0xc8, + 0x02, 0xf5, 0x58, 0xae, 0x5b, 0x61, 0xd3, 0xdd, 0x7c, 0xb6, 0x0b, 0x6a, 0x99, 0x2c, 0x8c, 0x9e, 0xb4, 0xc1, 0x42, + 0x22, 0x96, 0xdc, 0x02, 0x2b, 0xb2, 0x65, 0x90, 0xd5, 0xc5, 0x2b, 0xa0, 0x11, 0x6a, 0x5b, 0xf4, 0xc2, 0xe2, 0x0d, + 0x0a, 0x4c, 0x6e, 0x70, 0x16, 0x9d, 0x56, 0xbc, 0x35, 0x26, 0xfe, 0xd7, 0xee, 0x19, 0x37, 0x7d, 0xb8, 0x25, 0x5d, + 0x44, 0xb9, 0x71, 0x79, 0x5b, 0x53, 0xdf, 0xe6, 0x18, 0xe8, 0x7a, 0xcb, 0xab, 0x6a, 0xe4, 0x12, 0xb0, 0xc7, 0x65, + 0x68, 0x24, 0xdd, 0xfc, 0xbc, 0x06, 0x33, 0xa7, 0x33, 0x27, 0x90, 0xf0, 0xa2, 0x91, 0x51, 0x30, 0xf1, 0xf3, 0x85, + 0x68, 0x47, 0x35, 0x63, 0xa0, 0xc0, 0x07, 0xa4, 0xc1, 0x6d, 0x8e, 0x4b, 0xb3, 0x15, 0x9b, 0x45, 0x68, 0x4d, 0x99, + 0x63, 0xc2, 0xab, 0x6e, 0xc6, 0x51, 0x35, 0x06, 0xbb, 0x78, 0x18, 0x6d, 0xc6, 0x5b, 0xdb, 0x24, 0x01, 0x55, 0xd2, + 0x02, 0x38, 0xfd, 0x7c, 0x25, 0x52, 0xa3, 0xe4, 0x52, 0x40, 0xf0, 0x97, 0x53, 0xa0, 0x2d, 0xb7, 0x86, 0x6e, 0x62, + 0x10, 0x6e, 0x3a, 0x57, 0x70, 0xcb, 0x38, 0xf9, 0xc5, 0x70, 0x5a, 0x55, 0xf1, 0x82, 0x94, 0x89, 0x95, 0x1d, 0xf3, + 0x83, 0xad, 0x79, 0x9b, 0x6d, 0x97, 0xef, 0x03, 0xf9, 0x7d, 0xbf, 0xef, 0x5b, 0x6a, 0x5c, 0x9f, 0xef, 0xf2, 0x82, + 0x1d, 0x37, 0x91, 0xd6, 0x4a, 0x14, 0x59, 0x04, 0x8d, 0x76, 0x39, 0xb9, 0x80, 0xf7, 0xa0, 0xe6, 0xee, 0xce, 0xa8, + 0x8d, 0xac, 0xf0, 0x5e, 0xc1, 0xf6, 0x67, 0x99, 0xaf, 0x10, 0xe8, 0xe0, 0x01, 0x0c, 0xf5, 0x89, 0x22, 0x68, 0x24, + 0x42, 0x02, 0x58, 0x3f, 0x6f, 0x08, 0x30, 0x75, 0x8d, 0x92, 0x4d, 0xf0, 0x96, 0xf6, 0x47, 0x37, 0x1e, 0xb2, 0x74, + 0x19, 0xf1, 0x84, 0x48, 0x51, 0x78, 0x00, 0xed, 0xed, 0x23, 0x84, 0x19, 0xf3, 0x54, 0x8d, 0xf8, 0xf5, 0xd4, 0x9e, + 0x5e, 0x18, 0x67, 0xfb, 0x53, 0xfa, 0xff, 0xb9, 0x48, 0x55, 0x9e, 0x8f, 0xe9, 0xcc, 0x79, 0xfb, 0x43, 0xf1, 0xc1, + 0x93, 0x1b, 0x76, 0x0f, 0xe0, 0xd0, 0xb8, 0x9c, 0xac, 0x51, 0xd1, 0xfa, 0x4b, 0xc7, 0xa1, 0x89, 0xe7, 0xcf, 0xb2, + 0xaa, 0xf8, 0xd1, 0x7f, 0xaa, 0xe6, 0x3a, 0x9d, 0xb9, 0x88, 0xb3, 0x2b, 0xb9, 0x15, 0x94, 0x4e, 0xc0, 0x1f, 0xc6, + 0x6b, 0x8d, 0xb9, 0xc4, 0xbd, 0xe1, 0x66, 0xd7, 0xa3, 0xfa, 0xe3, 0x26, 0x03, 0xe3, 0xfd, 0x5b, 0xc9, 0x06, 0xe4, + 0x79, 0x5a, 0x8c, 0x39, 0x7a, 0xe1, 0x9d, 0x2e, 0x90, 0x81, 0xb0, 0x7b, 0xb6, 0xf1, 0x98, 0x28, 0x34, 0x7a, 0x89, + 0x14, 0x2e, 0xd8, 0x3b, 0xb6, 0x03, 0xb2, 0xdb, 0xcf, 0x77, 0xdb, 0x3a, 0xa0, 0xb4, 0x9b, 0xf0, 0xfa, 0x65, 0xcb, + 0x2a, 0x6f, 0x6e, 0xf9, 0x56, 0x99, 0x54, 0xdc, 0xd7, 0x36, 0xc4, 0x7a, 0xe4, 0x14, 0x3b, 0x80, 0x80, 0xc8, 0x62, + 0x09, 0x8d, 0x3b, 0x37, 0x17, 0x1e, 0x1f, 0x4f, 0x9e, 0x95, 0x8c, 0x3a, 0x57, 0xaf, 0xdf, 0xca, 0xba, 0x8a, 0x29, + 0xdb, 0x4b, 0xcf, 0x09, 0x7d, 0x3b, 0x05, 0xee, 0x89, 0x65, 0x34, 0x80, 0x56, 0x7a, 0xcc, 0x19, 0xb1, 0xc6, 0x89, + 0x47, 0xb4, 0x94, 0xc8, 0x3a, 0x94, 0x6f, 0x37, 0x62, 0x4b, 0x08, 0xd5, 0x2e, 0xb5, 0xd7, 0x8d, 0x06, 0x62, 0xfb, + 0x06, 0x10, 0x06, 0x90, 0xcc, 0x62, 0xcd, 0xf5, 0xa5, 0x90, 0x1e, 0xd7, 0x40, 0xa1, 0x76, 0xdf, 0x9c, 0xed, 0x35, + 0x29, 0x9f, 0x4b, 0x33, 0x07, 0xb4, 0xd4, 0xad, 0xf1, 0x7b, 0x60, 0x59, 0xac, 0xb7, 0x0e, 0xfb, 0x7e, 0x9c, 0x31, + 0xed, 0xc2, 0x68, 0x71, 0x6a, 0x3c, 0x41, 0x3d, 0xa8, 0x6b, 0x14, 0x84, 0x72, 0xb0, 0x95, 0xa4, 0x1d, 0xe0, 0x74, + 0x8a, 0xd9, 0x14, 0x80, 0xdb, 0xed, 0x48, 0x9e, 0x30, 0x49, 0x81, 0xe3, 0xb9, 0x86, 0x78, 0x12, 0x57, 0xf4, 0x97, + 0x40, 0xa1, 0x0a, 0x09, 0xc6, 0x8d, 0xf3, 0x48, 0xa8, 0x7f, 0x3f, 0x20, 0x92, 0xcb, 0x65, 0x92, 0x6c, 0x97, 0x2d, + 0x0d, 0x45, 0xad, 0xc0, 0x0f, 0xe8, 0xdb, 0xb8, 0x3d, 0xa4, 0xef, 0xc2, 0x87, 0xc3, 0xda, 0xda, 0x57, 0x1e, 0x61, + 0x16, 0x8e, 0x3d, 0x81, 0xdd, 0x19, 0x66, 0xc5, 0xfd, 0x9f, 0xcf, 0xf1, 0xeb, 0x0f, 0xef, 0x19, 0xd7, 0x1d, 0xfd, + 0x24, 0xf6, 0x7e, 0xd8, 0xd1, 0x71, 0xb3, 0x49, 0x71, 0x31, 0xb3, 0xdf, 0xb4, 0x91, 0xff, 0x75, 0xf1, 0x6c, 0xe2, + 0x9e, 0xde, 0xf1, 0x3b, 0x3d, 0x13, 0x7b, 0x39, 0x51, 0x55, 0xfe, 0xb8, 0x3f, 0x37, 0xf2, 0xfa, 0xac, 0xbf, 0xea, + 0x73, 0xd6, 0xe3, 0xda, 0xc3, 0x78, 0xfb, 0x8c, 0xeb, 0xa9, 0xe5, 0xf5, 0x61, 0xbf, 0x39, 0x1d, 0xf8, 0x3b, 0x0b, + 0x8a, 0xf7, 0xca, 0x15, 0xd3, 0x0a, 0x6d, 0xfc, 0x80, 0x72, 0x7a, 0xf0, 0x47, 0x6c, 0x88, 0x32, 0xb6, 0xc1, 0xf5, + 0x27, 0xb8, 0xce, 0x5a, 0xe1, 0x6c, 0xe0, 0x42, 0x94, 0x1e, 0xe9, 0xd7, 0x39, 0xbd, 0xd2, 0xf1, 0x30, 0x7e, 0xaa, + 0x6b, 0xe1, 0x58, 0xaa, 0x70, 0x66, 0x27, 0xe5, 0x78, 0xbb, 0x8d, 0xf5, 0x0c, 0xbe, 0x37, 0x0b, 0x4a, 0xaf, 0x32, + 0xd8, 0xc8, 0x15, 0xf3, 0x3e, 0x0e, 0x6a, 0xdb, 0x07, 0x1f, 0x8d, 0xf1, 0x6d, 0x9f, 0x8e, 0x2f, 0xda, 0xa4, 0x58, + 0xd9, 0xe3, 0x19, 0x03, 0x19, 0x1c, 0x7e, 0xc1, 0x88, 0x1d, 0xfa, 0xbf, 0x31, 0x55, 0xe9, 0x45, 0x54, 0x1d, 0x5b, + 0x99, 0x02, 0xd4, 0xc3, 0x36, 0x8e, 0x9f, 0xa8, 0x8d, 0xdd, 0x6a, 0x24, 0xe0, 0xf0, 0xda, 0xfd, 0x7a, 0x55, 0x10, + 0xc6, 0xf9, 0x7d, 0x80, 0xf7, 0x80, 0xca, 0xc2, 0x3e, 0x24, 0xee, 0xd0, 0x3e, 0x26, 0xe2, 0xfe, 0x5f, 0xfa, 0x1a, + 0x12, 0xd6, 0xab, 0xfd, 0x80, 0xaa, 0x86, 0x9f, 0x30, 0xc3, 0x9b, 0x2f, 0x97, 0xe3, 0x42, 0x2e, 0x42, 0x9e, 0xc7, + 0xca, 0xda, 0x59, 0xe7, 0xe6, 0x52, 0x16, 0x01, 0x97, 0x05, 0x58, 0xb1, 0xd5, 0xf7, 0x3f, 0xd6, 0x79, 0x4f, 0x03, + 0x88, 0xaf, 0x4b, 0x21, 0xc5, 0xd2, 0x8c, 0x4b, 0x2a, 0xa3, 0x4d, 0x45, 0xf4, 0x6f, 0x64, 0x48, 0x93, 0x39, 0x96, + 0x33, 0x67, 0xe9, 0x03, 0x09, 0x3e, 0x59, 0x30, 0xb0, 0x78, 0x0e, 0xaa, 0x95, 0xa4, 0x99, 0x10, 0x31, 0x91, 0x44, + 0x03, 0xd4, 0x3c, 0xa9, 0x2a, 0x28, 0x3c, 0xd5, 0x70, 0x6d, 0xf5, 0xc2, 0x29, 0x00, 0x24, 0x07, 0x44, 0x45, 0x2d, + 0x3c, 0xa5, 0xc5, 0x4b, 0x4d, 0xc7, 0x6f, 0xbb, 0xa5, 0x1d, 0x7b, 0x7b, 0x8f, 0xfc, 0x45, 0x4c, 0x4e, 0x44, 0xc5, + 0xd6, 0x26, 0x22, 0x81, 0xb7, 0x00, 0xb2, 0x39, 0x56, 0x8c, 0x03, 0x3a, 0x7e, 0xa3, 0x69, 0xb8, 0x8d, 0x1c, 0x95, + 0xf0, 0x0e, 0x46, 0xda, 0x62, 0x2e, 0x98, 0x6e, 0xa4, 0xd5, 0x10, 0x57, 0xaf, 0xd0, 0xaa, 0xb4, 0xd9, 0xc6, 0xc0, + 0x99, 0x6b, 0x31, 0x8a, 0xd7, 0x51, 0x31, 0x27, 0x64, 0x81, 0xf3, 0x70, 0x6e, 0x86, 0xb3, 0xb1, 0x06, 0xa5, 0x71, + 0xd4, 0x15, 0xa7, 0xf3, 0x6d, 0xb6, 0xee, 0xda, 0x77, 0x32, 0xcf, 0xb3, 0xc8, 0x26, 0xed, 0x66, 0x17, 0xd4, 0x38, + 0x57, 0x8c, 0xf9, 0x88, 0x1d, 0x9f, 0x71, 0xe9, 0xb9, 0x85, 0x61, 0x12, 0x1a, 0x8c, 0x9d, 0xd6, 0x2f, 0xd0, 0xf3, + 0x19, 0xdb, 0x15, 0x2e, 0xa0, 0x3c, 0x31, 0x16, 0xad, 0x20, 0x58, 0xbe, 0xad, 0x7f, 0x29, 0xf2, 0x30, 0x1b, 0x77, + 0x78, 0x60, 0x37, 0x4d, 0x3a, 0xf3, 0x7e, 0x78, 0x1e, 0x57, 0xd7, 0xb1, 0x9b, 0x65, 0x4f, 0x4c, 0x6e, 0x04, 0x54, + 0xac, 0x62, 0x9b, 0x97, 0x15, 0xf7, 0x50, 0x91, 0x4f, 0x5a, 0x28, 0xad, 0x52, 0xaa, 0x5e, 0x69, 0x4f, 0x46, 0x48, + 0x73, 0xb5, 0x9e, 0x81, 0x71, 0x21, 0xf0, 0x3e, 0x49, 0x2f, 0xbb, 0x6b, 0xcb, 0xdb, 0x74, 0x80, 0xb4, 0xf6, 0x36, + 0x7e, 0x79, 0x1d, 0x20, 0xce, 0xd5, 0xec, 0xa9, 0xe8, 0xf1, 0x8b, 0x20, 0x54, 0x9e, 0x4d, 0xd3, 0x0a, 0xea, 0xe2, + 0x8e, 0xae, 0xce, 0x61, 0x0d, 0x76, 0x9f, 0x7f, 0x16, 0xb6, 0x52, 0xf9, 0x7f, 0x7e, 0x93, 0xe8, 0x01, 0x3b, 0xec, + 0x21, 0x4d, 0x47, 0xf5, 0xa5, 0x9a, 0xdc, 0x05, 0x3e, 0x83, 0xd9, 0x8f, 0x1f, 0x74, 0x80, 0x65, 0xde, 0x9f, 0x8f, + 0x02, 0xbd, 0xb6, 0xda, 0x92, 0xf6, 0x64, 0x98, 0x6b, 0x82, 0xc1, 0x7d, 0xaf, 0x3b, 0x66, 0x2f, 0x9b, 0x8c, 0x4d, + 0x2c, 0x12, 0xe0, 0x83, 0xd0, 0x18, 0xc8, 0xfe, 0xc9, 0xfd, 0x9b, 0xa1, 0x2c, 0xcf, 0x7d, 0x38, 0x2b, 0xbc, 0x2e, + 0xdb, 0x67, 0xc2, 0x19, 0x6a, 0x91, 0x45, 0xca, 0x6a, 0x96, 0x5f, 0xda, 0x76, 0x0d, 0xd6, 0x4d, 0x59, 0xce, 0x5e, + 0xff, 0x98, 0xf2, 0x8d, 0x46, 0xa9, 0x4c, 0x86, 0xd5, 0x4e, 0x2a, 0x1d, 0x1e, 0x21, 0x90, 0x7a, 0x31, 0x96, 0x05, + 0xf3, 0x42, 0xf4, 0xf2, 0xf3, 0x91, 0x36, 0xb5, 0x17, 0x20, 0x08, 0xcc, 0xd5, 0x1e, 0x59, 0x2c, 0xf9, 0xba, 0x0d, + 0x80, 0xde, 0xb4, 0xd6, 0x57, 0x90, 0x50, 0xe5, 0xec, 0xb6, 0x60, 0x09, 0x7e, 0x92, 0xd6, 0x88, 0xc3, 0x8e, 0x2e, + 0xd8, 0x71, 0x1b, 0x73, 0x0c, 0xb0, 0x5c, 0xbb, 0xc9, 0x69, 0x38, 0x79, 0xc7, 0xdb, 0x8b, 0xe5, 0x64, 0x09, 0x2f, + 0xdc, 0xb8, 0x3d, 0x4c, 0xc3, 0x35, 0x6c, 0x6c, 0xf9, 0x24, 0x5d, 0x3c, 0xb5, 0xcb, 0xac, 0x49, 0xe8, 0xd3, 0x71, + 0xca, 0x77, 0x49, 0xc1, 0xf3, 0xdc, 0xc9, 0xec, 0xd0, 0xc5, 0xaa, 0x90, 0xcf, 0x5e, 0xdd, 0x0f, 0x2b, 0x0e, 0xab, + 0x07, 0x0f, 0xff, 0x87, 0xec, 0xda, 0x6c, 0x1e, 0x1a, 0x57, 0x6e, 0xb2, 0xec, 0x5c, 0x08, 0x91, 0x8e, 0x07, 0x62, + 0xa4, 0xfc, 0xd5, 0x3f, 0xa3, 0x2b, 0x77, 0x9a, 0xd9, 0xfe, 0xb5, 0x30, 0xc6, 0xc1, 0xdf, 0xd8, 0x56, 0x7b, 0xc8, + 0x1d, 0x54, 0xd7, 0x94, 0x9d, 0xd2, 0x7b, 0x76, 0x6c, 0xa3, 0x4f, 0x46, 0x34, 0xe8, 0x79, 0x7d, 0x33, 0x01, 0x72, + 0xde, 0x5f, 0xb4, 0x2d, 0x3e, 0x62, 0x04, 0xe4, 0x8d, 0x2e, 0x4f, 0xed, 0x3b, 0xc0, 0x70, 0x6d, 0xff, 0xb0, 0x02, + 0xa0, 0x9c, 0xb5, 0xa7, 0xb4, 0xc7, 0xed, 0xc3, 0x78, 0x20, 0x60, 0x61, 0x0d, 0xd6, 0x44, 0x65, 0x5f, 0x22, 0x5b, + 0x52, 0xb7, 0x40, 0x99, 0x0a, 0x0f, 0xb1, 0x63, 0x45, 0x38, 0x9f, 0xf4, 0x00, 0xb3, 0xb0, 0x74, 0xe6, 0x06, 0x1e, + 0x34, 0x83, 0x3a, 0xfe, 0x4e, 0x58, 0xb9, 0xee, 0x29, 0x75, 0x8f, 0x4c, 0x95, 0x31, 0x58, 0xea, 0x28, 0x95, 0x2c, + 0x78, 0x0e, 0xa6, 0x63, 0x09, 0x45, 0x8d, 0x6b, 0x97, 0x64, 0x10, 0x23, 0x5e, 0xbb, 0x80, 0x8e, 0x7e, 0x77, 0x73, + 0x70, 0x02, 0x3b, 0x24, 0xf3, 0x05, 0xc9, 0x6e, 0x1e, 0x21, 0x5b, 0x31, 0x1e, 0x99, 0xee, 0x46, 0x5c, 0xac, 0x58, + 0xb0, 0xc4, 0x12, 0xda, 0xa6, 0xe3, 0xbc, 0xe6, 0x0c, 0x64, 0x90, 0x47, 0x95, 0x8a, 0x52, 0xde, 0x6f, 0xc6, 0xf6, + 0x09, 0x49, 0xc3, 0x58, 0xfd, 0x04, 0xf3, 0x7a, 0xdc, 0x4a, 0x7c, 0x7a, 0x63, 0xa3, 0x67, 0x29, 0xea, 0x54, 0xa8, + 0x2f, 0xac, 0xa3, 0x62, 0x45, 0x24, 0xeb, 0x58, 0x6b, 0x2b, 0x0c, 0x8e, 0x0f, 0x33, 0x56, 0xe2, 0xb9, 0x27, 0xec, + 0x7f, 0x6c, 0xa4, 0xe1, 0xbe, 0x1b, 0x14, 0x72, 0x7d, 0xda, 0xb8, 0xb6, 0x62, 0x3e, 0x64, 0x69, 0x3a, 0x54, 0x9e, + 0x33, 0x5e, 0xdc, 0xc1, 0x83, 0x7c, 0x1f, 0x43, 0x9d, 0x09, 0xb2, 0x05, 0xa4, 0x2d, 0xc1, 0xa4, 0x85, 0xc9, 0xa4, + 0x80, 0xf5, 0x77, 0xa0, 0x36, 0x66, 0xf5, 0xc8, 0x93, 0x49, 0x14, 0xb4, 0xd1, 0x69, 0x5c, 0x56, 0xb3, 0x52, 0xcd, + 0xc8, 0x19, 0x27, 0x4f, 0x9c, 0x71, 0x8a, 0x9a, 0x1f, 0x06, 0x80, 0xf6, 0x7c, 0x18, 0x63, 0x90, 0x47, 0x08, 0x85, + 0xe2, 0xe3, 0x3a, 0x01, 0x69, 0xab, 0xb6, 0x59, 0x87, 0x04, 0x09, 0xfc, 0xa1, 0xd2, 0x34, 0x6a, 0x7b, 0x68, 0x34, + 0x41, 0x70, 0x9d, 0xd1, 0xad, 0x53, 0x3c, 0x60, 0x9a, 0x76, 0x74, 0x7b, 0xb7, 0xbc, 0xce, 0xf1, 0x88, 0xc4, 0x6c, + 0x95, 0xf9, 0xaa, 0x28, 0x91, 0xd8, 0x4c, 0x7b, 0x6c, 0x1c, 0x41, 0x38, 0xdd, 0xae, 0x0d, 0xda, 0x5d, 0xd5, 0x05, + 0x17, 0x68, 0xe2, 0x14, 0x85, 0x40, 0x6e, 0xae, 0x15, 0x3a, 0xa9, 0xc9, 0x51, 0x77, 0x40, 0x73, 0x53, 0x9d, 0x97, + 0x19, 0xb6, 0x7f, 0xc2, 0x9d, 0x4a, 0x2f, 0xc4, 0x22, 0x37, 0xf8, 0xab, 0x8f, 0xdc, 0xae, 0xb6, 0x41, 0x1b, 0xaf, + 0xd6, 0x49, 0x2b, 0xaf, 0xb6, 0xe1, 0x48, 0x56, 0x1a, 0x3a, 0x73, 0x19, 0xc6, 0xe6, 0xda, 0x4b, 0x19, 0x9d, 0xa7, + 0x17, 0x61, 0xdc, 0xa9, 0xcd, 0xf3, 0x11, 0x43, 0xce, 0x6d, 0xca, 0xc7, 0xf4, 0x6c, 0xbc, 0xfe, 0x67, 0xfe, 0xef, + 0xea, 0x84, 0x85, 0x0d, 0x6b, 0xbd, 0x13, 0x49, 0x23, 0x50, 0x49, 0x54, 0x8b, 0xbb, 0x0e, 0xda, 0x7b, 0x89, 0x71, + 0x6a, 0x9f, 0x1b, 0x0d, 0x92, 0xbe, 0x3f, 0x61, 0x24, 0x03, 0x41, 0xac, 0x29, 0x69, 0xf5, 0xfe, 0x75, 0x62, 0x2b, + 0xfa, 0x95, 0x20, 0xf1, 0x1f, 0xdf, 0x75, 0xbd, 0x95, 0x44, 0xa4, 0x41, 0xd3, 0x4e, 0x85, 0xcc, 0x06, 0xf0, 0xab, + 0x4f, 0x1f, 0x4a, 0x34, 0x31, 0x94, 0x9e, 0x5c, 0x21, 0xb0, 0x6b, 0x2f, 0x4e, 0xd7, 0x67, 0xde, 0xf0, 0xa6, 0xe2, + 0x0d, 0xc4, 0xe6, 0xaf, 0xfb, 0xc9, 0x9b, 0x95, 0x5f, 0x03, 0x5e, 0x16, 0xdc, 0xa1, 0xce, 0x6e, 0x54, 0xc2, 0x0f, + 0x1a, 0xce, 0x02, 0xe4, 0x28, 0x3f, 0xe9, 0x5f, 0x83, 0x0f, 0x1f, 0x0d, 0xde, 0xf0, 0xce, 0xa1, 0x7a, 0x53, 0x45, + 0x90, 0xe3, 0x92, 0x9c, 0x56, 0x16, 0x59, 0x1a, 0xae, 0x5b, 0xb0, 0x3a, 0x78, 0x83, 0x99, 0xa6, 0x6f, 0x6f, 0xc9, + 0xe9, 0x06, 0xa4, 0x15, 0xe1, 0x49, 0xec, 0x27, 0xd6, 0x29, 0x6c, 0xe2, 0x8b, 0x38, 0xdf, 0xaa, 0x68, 0x30, 0xde, + 0xde, 0xda, 0x89, 0x89, 0xd4, 0x07, 0xb0, 0x36, 0x2f, 0xde, 0x00, 0x6b, 0xbb, 0xf4, 0xcd, 0xef, 0x97, 0x59, 0xe4, + 0x12, 0x29, 0x73, 0x43, 0x1e, 0xee, 0x6b, 0x33, 0xa2, 0xae, 0x84, 0x42, 0x8e, 0xd0, 0xaa, 0x70, 0x95, 0x18, 0x51, + 0x72, 0x7a, 0xdb, 0xd5, 0xed, 0x24, 0x21, 0x16, 0x0a, 0xf5, 0x75, 0x25, 0x92, 0xd1, 0x4a, 0xc9, 0xf5, 0x3d, 0x72, + 0xa9, 0xaa, 0x3f, 0x82, 0x51, 0xaa, 0x6a, 0x68, 0xc8, 0xb5, 0x09, 0x08, 0xec, 0x6a, 0x2a, 0x2e, 0xe1, 0xc8, 0xb3, + 0xb6, 0x2c, 0xe1, 0xd2, 0x18, 0x94, 0x25, 0x5a, 0x0c, 0x32, 0xb5, 0xc8, 0x3b, 0x2f, 0xe9, 0x9a, 0xc7, 0x02, 0x9b, + 0x38, 0x62, 0xb1, 0x66, 0xfa, 0x31, 0x0f, 0xdb, 0x26, 0x5b, 0x0a, 0xda, 0x03, 0xbe, 0xe7, 0x26, 0x93, 0xf9, 0x4c, + 0xda, 0xeb, 0x9b, 0xf0, 0x92, 0x1b, 0x41, 0xa8, 0xed, 0xd1, 0x14, 0x11, 0x76, 0x7e, 0xe2, 0x0d, 0xce, 0xa0, 0x6a, + 0x9e, 0x89, 0xe5, 0x6a, 0xbd, 0xdd, 0x39, 0x83, 0xf4, 0x4d, 0xf8, 0xdb, 0x03, 0x79, 0xc0, 0x4d, 0xd9, 0x50, 0xe4, + 0xa4, 0x99, 0x27, 0x4e, 0x93, 0x27, 0xaa, 0xd5, 0x8f, 0x67, 0x28, 0xa3, 0x6e, 0x22, 0x62, 0xbd, 0xd9, 0xae, 0x14, + 0x29, 0xee, 0x25, 0xdd, 0xa5, 0x0e, 0xd7, 0x6e, 0x5e, 0x99, 0xd1, 0x8e, 0x42, 0x9f, 0xde, 0xad, 0x60, 0x85, 0x1a, + 0x6f, 0xfc, 0x98, 0x8d, 0x37, 0xe2, 0x82, 0x08, 0xf0, 0x21, 0x46, 0xcb, 0x82, 0x4e, 0x13, 0x2d, 0x66, 0x4f, 0x0f, + 0xca, 0xe7, 0x2e, 0xed, 0xd4, 0x55, 0xcb, 0xf8, 0x7a, 0xf8, 0xa0, 0x0d, 0x39, 0x6b, 0xd5, 0x18, 0xa7, 0xe5, 0x62, + 0x39, 0xbb, 0x3c, 0x42, 0x49, 0x71, 0xb8, 0x96, 0xdd, 0xfc, 0x2f, 0xda, 0xdc, 0xb0, 0xa1, 0xe6, 0x58, 0x38, 0xdd, + 0x69, 0x42, 0x63, 0x64, 0x37, 0x84, 0x83, 0xad, 0xa1, 0x16, 0x54, 0x10, 0xe9, 0x4f, 0xcc, 0xe1, 0xd9, 0xdb, 0x2c, + 0x05, 0x87, 0x8a, 0x11, 0x29, 0x1a, 0xf5, 0xd0, 0x29, 0x97, 0x89, 0x75, 0x8d, 0x5c, 0x4b, 0x8a, 0xf1, 0x27, 0xa3, + 0x9f, 0x48, 0xb3, 0xfc, 0x47, 0xe0, 0xe5, 0xd2, 0xb8, 0x34, 0xf8, 0x8d, 0xbf, 0x8d, 0xa1, 0x87, 0x27, 0x4f, 0x74, + 0x71, 0x61, 0xe3, 0xf0, 0x6f, 0xb8, 0xec, 0x42, 0x31, 0x66, 0x5b, 0x66, 0xbc, 0xb3, 0x5c, 0x9a, 0xbc, 0xa5, 0x0b, + 0x79, 0xca, 0x43, 0xe7, 0x0e, 0x9c, 0x10, 0x6d, 0x2c, 0x3b, 0xa0, 0xbe, 0x02, 0xe3, 0xdc, 0x87, 0xcc, 0xb8, 0xc8, + 0x16, 0x5d, 0xb9, 0xfe, 0x9a, 0x8b, 0x0e, 0x40, 0x2d, 0x12, 0x59, 0x5f, 0xd8, 0xc7, 0x58, 0xbb, 0x78, 0x5d, 0x6b, + 0xcf, 0x87, 0x28, 0xa6, 0x3e, 0xd7, 0x2b, 0x80, 0xa2, 0xc0, 0x68, 0xc3, 0x36, 0x76, 0x28, 0x21, 0x40, 0xba, 0x95, + 0x2d, 0xfa, 0x76, 0x8f, 0x46, 0x69, 0xa5, 0x54, 0x38, 0x67, 0x29, 0x1c, 0x95, 0xda, 0xc1, 0x22, 0x24, 0x16, 0xf1, + 0xa1, 0x74, 0x7e, 0x41, 0x24, 0x64, 0x3c, 0x67, 0x43, 0x54, 0x38, 0x49, 0x95, 0xe2, 0xf9, 0xb1, 0x9e, 0xb9, 0x6e, + 0x13, 0x8d, 0xd9, 0xa0, 0xfe, 0xc5, 0x67, 0xb7, 0xd4, 0xa9, 0x03, 0x88, 0x17, 0xbc, 0x73, 0x12, 0xfc, 0xb2, 0x00, + 0xe1, 0x9f, 0x1a, 0x17, 0xbd, 0xc8, 0xf2, 0x18, 0x8a, 0x94, 0x10, 0xe9, 0x9d, 0xc6, 0x4e, 0x64, 0xe8, 0xf4, 0x44, + 0x64, 0x01, 0xa3, 0x6b, 0x1b, 0xc8, 0x21, 0x1e, 0xfb, 0x31, 0xcb, 0x04, 0x2f, 0x40, 0x61, 0xa3, 0xd8, 0x44, 0x8b, + 0x7a, 0x59, 0xad, 0xa9, 0x59, 0x50, 0x13, 0x57, 0xa0, 0x47, 0xd3, 0x53, 0x5c, 0x07, 0x5e, 0xfb, 0xfa, 0x58, 0xc5, + 0xa2, 0x3d, 0x29, 0xd0, 0x04, 0x2b, 0x1c, 0xd0, 0x15, 0x8e, 0xc7, 0x0f, 0xe8, 0xdc, 0x3e, 0xa6, 0x1a, 0x9a, 0x58, + 0x15, 0xce, 0x6a, 0x8f, 0x39, 0x16, 0xd3, 0xda, 0x54, 0x79, 0xdd, 0x44, 0xa2, 0x41, 0x73, 0x5f, 0xd8, 0xc3, 0x67, + 0x7a, 0xb5, 0xd5, 0x62, 0x1c, 0x45, 0xfd, 0xe7, 0x5d, 0x84, 0x6f, 0xd0, 0xc6, 0xad, 0x16, 0xbe, 0x12, 0x54, 0xe5, + 0x05, 0x3a, 0x22, 0x20, 0x8e, 0xd6, 0x42, 0x64, 0xe6, 0x26, 0x05, 0x05, 0x55, 0x61, 0xbf, 0x67, 0x94, 0x57, 0x5f, + 0x6f, 0xca, 0xde, 0x8e, 0x33, 0xac, 0x37, 0x96, 0x1f, 0x8d, 0x11, 0xeb, 0x26, 0x24, 0x9c, 0x24, 0xbf, 0x83, 0xbf, + 0xa9, 0x19, 0xf4, 0x1f, 0xc0, 0xe9, 0xa3, 0x3e, 0xcc, 0xf8, 0x5d, 0x3d, 0x69, 0x02, 0x5d, 0x99, 0x6b, 0x06, 0xcf, + 0x8b, 0x53, 0x77, 0xa2, 0x90, 0x8d, 0x3d, 0xab, 0x65, 0x89, 0x1f, 0xb3, 0xa4, 0xeb, 0x35, 0xf1, 0xe8, 0x52, 0x66, + 0x50, 0x42, 0x28, 0x0d, 0x8c, 0xdd, 0x86, 0x22, 0xb3, 0xde, 0x03, 0xda, 0x1d, 0xb6, 0x31, 0x03, 0xeb, 0x29, 0x9a, + 0x24, 0x8d, 0xe3, 0x57, 0x9f, 0x7e, 0xa4, 0x36, 0x15, 0x43, 0x1a, 0xb6, 0x03, 0x94, 0x4d, 0x32, 0x14, 0x2b, 0xcc, + 0xfa, 0x6f, 0xd0, 0x7b, 0xbb, 0x6f, 0x87, 0xfd, 0x0a, 0xfe, 0xc8, 0x6f, 0x8f, 0x9a, 0x50, 0x36, 0x87, 0x15, 0x0e, + 0x1b, 0xb4, 0xe6, 0x5b, 0x32, 0x75, 0x50, 0x22, 0x0c, 0xe6, 0x05, 0x2a, 0x53, 0x3e, 0x0c, 0xe7, 0x24, 0x93, 0x90, + 0x19, 0x86, 0xbd, 0x9d, 0x58, 0x83, 0xb6, 0x7d, 0xb7, 0x52, 0x5a, 0xdd, 0xd5, 0xd3, 0x0c, 0x0e, 0x69, 0x96, 0xde, + 0xb6, 0x81, 0x81, 0x0e, 0xd7, 0xae, 0x58, 0xa1, 0x9f, 0x67, 0x13, 0x1a, 0x29, 0xc6, 0x80, 0x51, 0x4d, 0x80, 0xec, + 0x56, 0x71, 0xf3, 0x6c, 0xc3, 0x16, 0x49, 0xc4, 0xb4, 0x3f, 0xbd, 0x3a, 0x93, 0x83, 0x8a, 0xf6, 0x22, 0xfc, 0x96, + 0x85, 0x84, 0x70, 0x07, 0x7e, 0xd2, 0x8f, 0x5b, 0x49, 0xbd, 0x95, 0xd9, 0xe6, 0xd6, 0x1b, 0x6a, 0xe7, 0x96, 0x9a, + 0xb9, 0x93, 0x88, 0xf2, 0x64, 0x90, 0x01, 0x37, 0x60, 0xca, 0x46, 0x3f, 0x3a, 0x96, 0x4d, 0x89, 0x4e, 0x94, 0x07, + 0x8a, 0xcd, 0x5a, 0x06, 0xa1, 0x1b, 0x63, 0xba, 0x70, 0x8d, 0xd4, 0xc6, 0x04, 0xa0, 0x64, 0xc3, 0x6c, 0x31, 0x6d, + 0xfa, 0xdb, 0xe7, 0x22, 0xec, 0x0f, 0xf1, 0x40, 0x94, 0xdd, 0x83, 0xa8, 0x83, 0x8e, 0xe8, 0xbf, 0x2f, 0x60, 0x95, + 0xc1, 0x0b, 0xd6, 0x6f, 0x12, 0x1a, 0x3a, 0xe0, 0x2f, 0x6b, 0x2f, 0xd7, 0x22, 0xe5, 0xbc, 0xd5, 0x9d, 0x73, 0xf5, + 0x12, 0xae, 0xbf, 0xb5, 0x67, 0x4a, 0x88, 0x18, 0x2d, 0x4a, 0x40, 0x05, 0x0d, 0xca, 0x27, 0xb0, 0xba, 0x09, 0x54, + 0xf5, 0x36, 0xa5, 0x66, 0x2e, 0x2e, 0xec, 0xcf, 0xdf, 0x66, 0x83, 0x42, 0xeb, 0xe1, 0x83, 0x8c, 0x94, 0x47, 0x10, + 0x44, 0xaa, 0xc6, 0xc2, 0x37, 0x10, 0xf3, 0xaa, 0xa2, 0x74, 0x2d, 0xbe, 0x0d, 0x84, 0x7b, 0x9f, 0x52, 0xb3, 0xa0, + 0x1f, 0x44, 0x44, 0x17, 0xaa, 0xbd, 0x42, 0x46, 0x85, 0x78, 0x7e, 0x1b, 0x65, 0xc8, 0x92, 0x53, 0x53, 0x04, 0x6a, + 0x06, 0x4e, 0x5b, 0xeb, 0xf2, 0x60, 0xa3, 0xf1, 0x81, 0x79, 0x2a, 0xf8, 0xff, 0x3a, 0x7a, 0x09, 0xdf, 0xdd, 0x37, + 0x01, 0xc2, 0xda, 0x7f, 0x1e, 0xd5, 0x5d, 0xbd, 0x69, 0x2e, 0xc4, 0xec, 0x11, 0x7f, 0x1c, 0x02, 0x4f, 0xa7, 0xb9, + 0x77, 0xb1, 0x2a, 0xc1, 0xc0, 0x8e, 0x45, 0x0e, 0x7f, 0xd4, 0xf5, 0x34, 0x7f, 0xbe, 0xaa, 0x9a, 0xc4, 0xb2, 0x86, + 0x22, 0x7e, 0x8e, 0x67, 0x73, 0xa1, 0x3a, 0x51, 0x9a, 0x4c, 0x60, 0x84, 0x23, 0xad, 0x29, 0x49, 0x1e, 0xc1, 0xba, + 0xac, 0x3d, 0x34, 0x7b, 0xbf, 0xb5, 0x92, 0xe8, 0x19, 0x0f, 0xf9, 0xf9, 0x9b, 0xa1, 0x59, 0x9e, 0x8f, 0x28, 0x4f, + 0xbb, 0x97, 0x03, 0x1a, 0xf5, 0xce, 0x09, 0xab, 0xca, 0x05, 0xb1, 0x34, 0xf6, 0x11, 0x54, 0x73, 0x9e, 0xeb, 0x1a, + 0x0b, 0xc1, 0x55, 0x8f, 0xff, 0x06, 0x8e, 0x1a, 0xb5, 0xa1, 0xd2, 0xb3, 0x51, 0xb4, 0x36, 0xb8, 0x7c, 0x4b, 0x07, + 0x98, 0x02, 0x0a, 0x84, 0x5a, 0xb3, 0x3b, 0xaf, 0xdc, 0xf2, 0xc4, 0x03, 0xa9, 0xf7, 0xcc, 0x37, 0xce, 0xc0, 0x7c, + 0x95, 0xee, 0x5a, 0xe6, 0xb5, 0xdb, 0x54, 0xf1, 0x3d, 0xf4, 0x12, 0x54, 0x51, 0xc0, 0xdf, 0x85, 0x5d, 0x29, 0x89, + 0xac, 0xc3, 0x25, 0x88, 0xcb, 0xbe, 0x9d, 0xa1, 0x80, 0xd1, 0x7b, 0xc5, 0x15, 0xbb, 0xe1, 0x5d, 0xe7, 0x51, 0x99, + 0x43, 0x59, 0x93, 0x0f, 0xf0, 0x85, 0x97, 0xa3, 0xd5, 0xd7, 0xf6, 0x24, 0x19, 0x13, 0xfe, 0x1d, 0x90, 0x8c, 0x09, + 0x33, 0xa2, 0x12, 0xf3, 0x5c, 0x05, 0x1e, 0x98, 0x7f, 0xed, 0x21, 0xb7, 0xac, 0x47, 0xeb, 0xac, 0x03, 0xad, 0xe7, + 0xd4, 0xbb, 0x68, 0xe0, 0xf7, 0xa4, 0xb5, 0x03, 0x01, 0x00, 0xb2, 0x0e, 0x9d, 0x43, 0xcd, 0xad, 0x20, 0x5d, 0x55, + 0xb7, 0x87, 0x65, 0xe6, 0xb2, 0x6b, 0xb2, 0x66, 0x47, 0x8e, 0xf8, 0x25, 0x89, 0x2e, 0x50, 0x63, 0x7b, 0xca, 0x7b, + 0x7c, 0x9f, 0xd8, 0x16, 0xbc, 0x8c, 0xea, 0x0b, 0xe7, 0xa6, 0x09, 0x15, 0xf4, 0x83, 0x49, 0x15, 0xc4, 0x7a, 0x42, + 0x02, 0x66, 0xeb, 0xbe, 0x45, 0xd5, 0x7c, 0xcb, 0x57, 0xf6, 0xca, 0x84, 0x7c, 0xc2, 0xd5, 0xb3, 0xa2, 0x0a, 0x24, + 0xad, 0x2f, 0x06, 0x18, 0x0a, 0xe4, 0x12, 0x84, 0xe0, 0x12, 0x14, 0x1d, 0x8c, 0xf1, 0x04, 0x1c, 0x22, 0xce, 0x4b, + 0x8d, 0x87, 0xc9, 0xfd, 0x37, 0x6e, 0x62, 0x0d, 0x46, 0xc2, 0xe0, 0x8a, 0x0d, 0x80, 0x43, 0x2b, 0xd0, 0xea, 0x57, + 0xfb, 0xec, 0x0b, 0xdf, 0x0f, 0xd4, 0x25, 0xab, 0x09, 0xd9, 0x17, 0x51, 0x43, 0xf7, 0x02, 0x64, 0xf1, 0x2c, 0x8e, + 0x4b, 0xa2, 0x33, 0xbe, 0xf1, 0xd0, 0x43, 0x21, 0x0d, 0x42, 0xfe, 0x27, 0xa3, 0xe0, 0x04, 0xcc, 0x24, 0x2a, 0xda, + 0x12, 0x1e, 0xdd, 0xe8, 0x40, 0x03, 0xbb, 0xb1, 0x6e, 0x6a, 0xe1, 0x4e, 0x4c, 0xa5, 0xd5, 0x0d, 0x63, 0x58, 0x65, + 0x84, 0xa6, 0x91, 0xba, 0xdb, 0x9a, 0xb9, 0xba, 0x58, 0xed, 0x8e, 0x67, 0xdf, 0xff, 0x0d, 0x97, 0x32, 0x5b, 0x94, + 0x10, 0x67, 0x12, 0x63, 0xe2, 0x54, 0x2d, 0xbf, 0x11, 0x71, 0xe7, 0x7e, 0xa7, 0x00, 0x44, 0x9f, 0x71, 0x1a, 0x6d, + 0x36, 0x52, 0xd3, 0x03, 0x76, 0x07, 0x3c, 0x50, 0xfc, 0x21, 0xd8, 0xf8, 0x34, 0x79, 0xc8, 0xd6, 0x4a, 0x26, 0x97, + 0xb6, 0xae, 0x6b, 0x3b, 0xf5, 0x2e, 0x7e, 0xcc, 0xb1, 0xbd, 0xb5, 0x92, 0x3c, 0x15, 0x21, 0xe3, 0xe8, 0x93, 0x8d, + 0x27, 0xd4, 0x39, 0xe4, 0xe7, 0xc0, 0x00, 0xba, 0xf5, 0xba, 0xfe, 0x8f, 0x44, 0x84, 0xa7, 0x23, 0x06, 0x32, 0x4c, + 0x0c, 0x9e, 0x39, 0xc3, 0xa9, 0x57, 0x20, 0x3f, 0x86, 0x61, 0x9a, 0x00, 0x7d, 0x22, 0xc9, 0x15, 0xf8, 0x82, 0x60, + 0xf8, 0x48, 0x2d, 0x1b, 0xe2, 0x7d, 0x15, 0x3e, 0xac, 0xa6, 0x16, 0xc3, 0xa2, 0x07, 0x8b, 0x48, 0xe4, 0x81, 0x1c, + 0x60, 0x7d, 0x60, 0xc9, 0x0a, 0x23, 0x02, 0x1f, 0xb3, 0xbd, 0x71, 0xac, 0x00, 0x8c, 0x76, 0xc8, 0x75, 0xfe, 0xf2, + 0x29, 0xf8, 0x1b, 0x2f, 0x54, 0x8a, 0x7d, 0x43, 0x56, 0xfc, 0x23, 0x23, 0x58, 0x1c, 0x0f, 0xa3, 0x69, 0x74, 0x12, + 0xd0, 0x4c, 0x0e, 0xdd, 0x2a, 0x21, 0x86, 0xd9, 0x77, 0x01, 0xe3, 0xd2, 0x95, 0x93, 0xe4, 0xad, 0xfa, 0xc0, 0x58, + 0x90, 0x6e, 0x13, 0x0d, 0xb2, 0xf0, 0x97, 0x05, 0xad, 0xa4, 0x41, 0x5c, 0x93, 0xf7, 0x6e, 0xa6, 0x50, 0xda, 0x97, + 0xae, 0xc3, 0xd4, 0x5d, 0x49, 0xe0, 0xba, 0x12, 0x23, 0x81, 0x5f, 0x66, 0x0d, 0x8a, 0x7c, 0x8e, 0x98, 0xc7, 0xf1, + 0x0e, 0x80, 0x3b, 0x81, 0xe6, 0xc8, 0x21, 0x3b, 0x4f, 0xc4, 0xee, 0x9e, 0xc0, 0x1f, 0xcb, 0x1f, 0x89, 0xfa, 0xe5, + 0xf1, 0x28, 0x3b, 0xa0, 0x68, 0x7f, 0x93, 0x58, 0xaa, 0x42, 0x09, 0xa0, 0x91, 0x2d, 0x50, 0xe9, 0x0a, 0xe0, 0x32, + 0x70, 0x88, 0x58, 0x3d, 0xb3, 0x1e, 0x01, 0x3d, 0xf6, 0xf0, 0x67, 0xa7, 0xaf, 0x7d, 0x5d, 0x13, 0x56, 0x79, 0xdb, + 0x98, 0xac, 0xb3, 0x05, 0xe7, 0x5c, 0x57, 0x27, 0x69, 0xe6, 0xd5, 0x3d, 0x6d, 0xa8, 0x5f, 0x92, 0xb4, 0x6d, 0x2d, + 0xca, 0xc0, 0xf4, 0x73, 0x92, 0x86, 0x50, 0xe8, 0x8f, 0xe5, 0x99, 0x86, 0x52, 0xf3, 0x42, 0x77, 0x1e, 0xc5, 0xb7, + 0x54, 0x3b, 0xa4, 0x76, 0x5d, 0x9a, 0xf6, 0x11, 0xe1, 0x95, 0x34, 0xf6, 0x4c, 0x06, 0x1f, 0x41, 0x58, 0x1a, 0x8a, + 0x13, 0x73, 0x76, 0x09, 0x00, 0x09, 0x43, 0x0e, 0xee, 0x44, 0xde, 0xa6, 0xd8, 0x13, 0xd0, 0xd2, 0xa6, 0x76, 0xef, + 0xaa, 0xc1, 0x84, 0x2a, 0x51, 0xf2, 0xc0, 0xad, 0x6d, 0xf1, 0x58, 0x28, 0x93, 0xe8, 0x9f, 0x4d, 0x49, 0xa8, 0x24, + 0x7f, 0xea, 0xfc, 0x8f, 0x3f, 0x28, 0x22, 0x9d, 0x00, 0xb7, 0xac, 0x6a, 0xff, 0xdc, 0x89, 0x77, 0x32, 0xc4, 0x21, + 0x23, 0x23, 0xfc, 0x17, 0x95, 0xd1, 0xc7, 0x13, 0xb8, 0x24, 0x7c, 0xa4, 0x3d, 0xc8, 0x55, 0xf7, 0x44, 0x9d, 0x83, + 0x51, 0x1e, 0x6d, 0x60, 0x62, 0x7e, 0x9e, 0x86, 0xb3, 0x6e, 0x32, 0xb0, 0x30, 0xcb, 0x90, 0xcf, 0x8b, 0xed, 0xc1, + 0x01, 0x5f, 0x09, 0xc0, 0x17, 0x1a, 0x26, 0x1f, 0x73, 0x82, 0x6a, 0xc3, 0xc9, 0x94, 0xeb, 0xec, 0x6e, 0x9c, 0x6a, + 0xa9, 0x82, 0x76, 0x60, 0x42, 0x00, 0xf4, 0x5c, 0x70, 0x0b, 0x07, 0xcd, 0xcf, 0x9b, 0x7c, 0xc2, 0xc9, 0xa7, 0x7e, + 0x25, 0x7d, 0xd1, 0x18, 0x6a, 0x7d, 0x9e, 0x11, 0xb4, 0x34, 0x03, 0x6e, 0xe1, 0x72, 0x08, 0x5b, 0x38, 0x86, 0x05, + 0x19, 0x2f, 0x84, 0xf1, 0x02, 0x4a, 0xe0, 0xcb, 0x21, 0xc4, 0x00, 0xb6, 0x3f, 0x52, 0xb2, 0x9c, 0x50, 0xed, 0x59, + 0xd9, 0xa3, 0x00, 0x41, 0x64, 0xf2, 0xeb, 0x97, 0x8f, 0xff, 0x85, 0x22, 0xb0, 0x0a, 0xa8, 0x4d, 0x07, 0x90, 0xad, + 0x45, 0xc4, 0xb5, 0xf2, 0x54, 0x85, 0x79, 0xa5, 0x04, 0x93, 0xde, 0xf5, 0x0f, 0xaf, 0x7b, 0xab, 0xa0, 0x0f, 0x4b, + 0xcd, 0x31, 0x1b, 0x4d, 0x84, 0x4f, 0x19, 0xfd, 0x79, 0x6d, 0x1d, 0x20, 0xb7, 0x61, 0xf5, 0xc6, 0x95, 0x34, 0x0c, + 0x1a, 0xb5, 0x5f, 0xb2, 0x92, 0xd2, 0xea, 0x46, 0xce, 0x33, 0x4c, 0xbd, 0xe5, 0x1f, 0xee, 0x02, 0x3e, 0x06, 0xac, + 0x30, 0x3f, 0xd0, 0x4b, 0xed, 0x85, 0x57, 0x80, 0xdf, 0x18, 0x11, 0xe4, 0xbe, 0x6d, 0x89, 0x82, 0x4c, 0x6d, 0xbd, + 0x36, 0x95, 0x1e, 0xe6, 0x58, 0x4f, 0xbc, 0xcf, 0xc9, 0xbe, 0x78, 0xe7, 0x5e, 0x2b, 0xc1, 0x7c, 0x48, 0xe2, 0xbb, + 0x88, 0x28, 0x3d, 0x58, 0x4c, 0x8d, 0xa9, 0xf9, 0x03, 0xc0, 0x45, 0xe1, 0xe1, 0xd4, 0xfb, 0x37, 0xd9, 0x25, 0xaf, + 0x6d, 0x2f, 0x2f, 0x79, 0x1c, 0xf7, 0x77, 0x37, 0xfd, 0x86, 0x1f, 0x86, 0xaf, 0xd5, 0x8d, 0xa6, 0xc0, 0xf4, 0x2c, + 0x13, 0xc1, 0x35, 0xfc, 0x41, 0x52, 0x6e, 0x1f, 0x90, 0xb5, 0x0d, 0x9b, 0xe7, 0xd4, 0xda, 0x74, 0xed, 0x06, 0xbe, + 0x72, 0x3a, 0xbe, 0x7c, 0xf9, 0xfe, 0x03, 0x85, 0x72, 0x08, 0x3f, 0x1d, 0x13, 0x03, 0xa9, 0x2b, 0x74, 0x70, 0x27, + 0x9e, 0xe9, 0x71, 0x01, 0xfd, 0xe0, 0xd4, 0x06, 0xe4, 0x0f, 0xd7, 0xda, 0x0a, 0xbb, 0x35, 0xe3, 0x25, 0xea, 0x43, + 0x8f, 0xb0, 0xcd, 0xb2, 0xb0, 0xec, 0xb6, 0x6a, 0x00, 0x65, 0xc1, 0xe2, 0x1b, 0x38, 0x4d, 0x4d, 0x49, 0x0e, 0x9f, + 0xb5, 0xb7, 0x8b, 0x56, 0xdf, 0x63, 0x01, 0xee, 0x1f, 0x90, 0x14, 0x54, 0x08, 0xff, 0x5b, 0xb4, 0x7f, 0xd0, 0x14, + 0x88, 0x2f, 0x49, 0xa1, 0x06, 0xc3, 0x47, 0x9e, 0x60, 0xfd, 0x49, 0x11, 0x35, 0x56, 0xf2, 0xdc, 0x7b, 0x08, 0x68, + 0x5c, 0xde, 0x20, 0xf4, 0x1a, 0xbc, 0xaa, 0x1c, 0x1e, 0x94, 0x37, 0x51, 0xce, 0x78, 0x6a, 0xf2, 0xbe, 0x2e, 0x31, + 0xa1, 0xb7, 0xb7, 0x55, 0xaa, 0x78, 0xaa, 0x7a, 0xa4, 0x3c, 0x24, 0x01, 0xd2, 0x45, 0x81, 0x8b, 0x36, 0x1d, 0xe7, + 0x67, 0xc1, 0x9c, 0x15, 0xf8, 0x52, 0x6e, 0x24, 0xca, 0x2f, 0xc6, 0xcc, 0x6c, 0xe4, 0xaf, 0x37, 0x2e, 0x37, 0x5e, + 0xdd, 0xd6, 0x4a, 0x34, 0xd7, 0x92, 0x02, 0x5d, 0xae, 0xa3, 0xbf, 0xba, 0x11, 0x86, 0x72, 0x48, 0xf9, 0x4f, 0x28, + 0x4c, 0x6c, 0x81, 0x14, 0xe4, 0x25, 0x91, 0xff, 0x1e, 0x96, 0xb3, 0x85, 0xaf, 0x62, 0x1f, 0xa0, 0x6c, 0x24, 0xf6, + 0x07, 0x22, 0x45, 0xa6, 0xdd, 0x58, 0xb6, 0xfb, 0xbf, 0x16, 0x6f, 0xfe, 0x55, 0x95, 0x2f, 0xd5, 0xb3, 0x44, 0x14, + 0xea, 0x9c, 0x94, 0xcf, 0x30, 0xda, 0xe2, 0x7f, 0x86, 0x22, 0xad, 0x42, 0x0f, 0x6d, 0x0f, 0x3c, 0x0c, 0xad, 0x49, + 0x60, 0xcb, 0x7b, 0x3a, 0x04, 0x1b, 0x54, 0x9b, 0xd8, 0x72, 0x1a, 0x75, 0x56, 0xb4, 0x2a, 0xf7, 0xd8, 0x73, 0xed, + 0x19, 0xd4, 0xa3, 0x58, 0xe5, 0xa7, 0xe6, 0xd2, 0x80, 0x85, 0x01, 0x7f, 0x03, 0xf1, 0x55, 0xcc, 0xb9, 0xde, 0xad, + 0xe3, 0xb7, 0xcd, 0x4d, 0x58, 0x69, 0xa8, 0x5b, 0x00, 0x19, 0x17, 0x0c, 0x98, 0x3d, 0xf3, 0x04, 0x82, 0x62, 0x50, + 0x06, 0x03, 0x4e, 0xd3, 0xe7, 0x39, 0x67, 0x09, 0xf4, 0x91, 0xbd, 0x82, 0x03, 0x12, 0x42, 0xab, 0x58, 0x33, 0x91, + 0x2f, 0x40, 0x91, 0xae, 0xda, 0xe4, 0xcc, 0xb5, 0xa8, 0xa7, 0x09, 0xad, 0x02, 0x99, 0xc7, 0x0a, 0xa6, 0xcf, 0xbe, + 0x51, 0xc8, 0xa5, 0x30, 0x93, 0x3b, 0x7f, 0x41, 0xf3, 0x38, 0xcc, 0xd0, 0x45, 0x7e, 0x4a, 0x43, 0xb6, 0x73, 0x73, + 0xbf, 0x7d, 0x90, 0xc4, 0x27, 0xea, 0xc4, 0x7c, 0xc2, 0xfc, 0x57, 0x6f, 0xde, 0x75, 0x6f, 0x9a, 0xf3, 0xab, 0x69, + 0xfe, 0x5a, 0x41, 0xb3, 0x3f, 0x2e, 0xae, 0x50, 0xea, 0x8f, 0x58, 0xae, 0x9a, 0x56, 0x3e, 0xb2, 0x5f, 0x8d, 0x93, + 0x11, 0x91, 0xd0, 0x5e, 0x96, 0xd7, 0x31, 0x69, 0xf6, 0x9e, 0x5b, 0xb8, 0x6f, 0xc3, 0x4b, 0xc3, 0x62, 0xb9, 0x94, + 0x29, 0xad, 0x97, 0xc4, 0xfa, 0xc8, 0x05, 0xfe, 0x58, 0x22, 0x53, 0x1b, 0x6f, 0xf2, 0x8e, 0x74, 0x7e, 0x55, 0x77, + 0x79, 0x9c, 0x30, 0x98, 0xb9, 0x1b, 0x0b, 0x83, 0x3e, 0xd8, 0xcd, 0xd7, 0x91, 0xb7, 0x32, 0x04, 0xbd, 0x28, 0xdd, + 0xcd, 0x6e, 0x77, 0x9f, 0xa1, 0x60, 0xa5, 0x64, 0xc8, 0x96, 0x94, 0xf1, 0x47, 0x47, 0x0d, 0xf9, 0x4b, 0xa9, 0xcf, + 0xff, 0x4c, 0x22, 0x6e, 0xec, 0x7e, 0x79, 0xea, 0x44, 0x06, 0x5f, 0x90, 0xbb, 0x63, 0x24, 0xcb, 0xa7, 0x40, 0x21, + 0xec, 0x48, 0xb0, 0xf9, 0x4e, 0xb7, 0x09, 0x0e, 0x89, 0x34, 0x82, 0x86, 0xfa, 0xa8, 0x12, 0x81, 0x0a, 0xf1, 0x39, + 0x7d, 0x49, 0x1d, 0x3d, 0xeb, 0x5f, 0x8e, 0x7d, 0x06, 0x82, 0x56, 0x25, 0x32, 0x2a, 0x9d, 0x5c, 0x26, 0xa7, 0x30, + 0x82, 0x48, 0x50, 0x04, 0xb9, 0x49, 0x43, 0xf8, 0x70, 0x94, 0x5e, 0x3c, 0x29, 0x0d, 0x6b, 0x70, 0x0d, 0x1e, 0x4f, + 0x10, 0x93, 0x8c, 0x71, 0xeb, 0xdd, 0x6e, 0xdc, 0x9f, 0xde, 0x36, 0x60, 0xf5, 0x8f, 0x04, 0x9a, 0x20, 0xdc, 0x97, + 0x5c, 0xa0, 0x27, 0xe0, 0xb8, 0x16, 0x5c, 0xfb, 0x04, 0x86, 0x46, 0x07, 0x6a, 0xe9, 0xc8, 0x9d, 0x22, 0xff, 0x06, + 0x3c, 0xbb, 0x5b, 0x01, 0xe1, 0xda, 0xe5, 0x7d, 0x16, 0xd5, 0x12, 0x81, 0x5a, 0x67, 0x12, 0xcd, 0x6a, 0x11, 0xaa, + 0x6d, 0xbb, 0x01, 0x57, 0xc7, 0x50, 0xec, 0xa1, 0xf1, 0x17, 0xb0, 0xf0, 0x7c, 0xf2, 0xce, 0xc6, 0xc9, 0x78, 0x48, + 0x5f, 0xb5, 0x19, 0x2d, 0x9e, 0x7c, 0x6c, 0x39, 0xa6, 0xd2, 0x41, 0x0a, 0x1e, 0x2d, 0x08, 0xc2, 0x22, 0x7d, 0xe6, + 0x11, 0xb3, 0x1d, 0xe7, 0x7d, 0x00, 0x67, 0x71, 0x81, 0xee, 0x85, 0x11, 0x3c, 0x3c, 0xb6, 0x17, 0x07, 0x16, 0xb4, + 0x9f, 0x6b, 0x9d, 0xad, 0x48, 0x8b, 0x11, 0xee, 0x45, 0xcb, 0x5d, 0xc5, 0xb8, 0x8e, 0x3c, 0xc2, 0x97, 0xc1, 0xfb, + 0xee, 0x20, 0xc9, 0x73, 0x2b, 0x1c, 0x1c, 0x05, 0x3c, 0x90, 0x27, 0x46, 0x32, 0x46, 0x33, 0xf9, 0xf6, 0x67, 0x72, + 0xb7, 0x67, 0xbf, 0x19, 0x6e, 0x76, 0xc1, 0x45, 0x55, 0xa4, 0xcb, 0x6b, 0xbe, 0xee, 0xd6, 0xd1, 0xe5, 0x6b, 0x00, + 0xbe, 0x55, 0xf4, 0xa6, 0x2b, 0xac, 0x66, 0xb2, 0x11, 0x15, 0xce, 0xdf, 0xe5, 0x08, 0xae, 0x3c, 0xb7, 0x07, 0x15, + 0x63, 0xf0, 0x1e, 0x53, 0x9f, 0xd5, 0xda, 0xdb, 0x97, 0xba, 0x4d, 0x3f, 0xed, 0xb7, 0xdd, 0x68, 0x1a, 0xb5, 0xf8, + 0xfd, 0xf8, 0xc2, 0xa2, 0x63, 0x88, 0x74, 0x99, 0xf2, 0x65, 0xfa, 0x9b, 0x53, 0x56, 0x81, 0xb3, 0x50, 0x80, 0x6e, + 0xdd, 0x70, 0x31, 0x96, 0xf2, 0xdd, 0xd8, 0x42, 0xd4, 0xd7, 0x57, 0xa1, 0xb4, 0x27, 0xf6, 0xdc, 0xef, 0x1a, 0x0e, + 0x64, 0xf0, 0x6c, 0xbc, 0x0a, 0x3b, 0xba, 0x0a, 0xcf, 0x24, 0xde, 0xe7, 0xd7, 0xb9, 0xec, 0x3d, 0x53, 0x37, 0xef, + 0x10, 0xf8, 0x5f, 0x33, 0xbc, 0xf2, 0xb7, 0x4a, 0x98, 0xf3, 0x15, 0xff, 0x4a, 0xfc, 0xce, 0xd1, 0x0d, 0x17, 0xd1, + 0x65, 0xeb, 0x84, 0x56, 0xac, 0xf8, 0x75, 0xde, 0x7f, 0xfb, 0xf0, 0x29, 0x7a, 0x30, 0xae, 0x47, 0x86, 0x5f, 0xa5, + 0x3c, 0x87, 0x75, 0x9b, 0x46, 0x65, 0xfe, 0x54, 0xe0, 0xc5, 0x3a, 0x7f, 0x51, 0x30, 0xea, 0x4d, 0xf2, 0x57, 0xcf, + 0xbf, 0x4e, 0x5f, 0x3c, 0x90, 0x5c, 0xf8, 0x8f, 0x79, 0x7b, 0xb4, 0x1d, 0x81, 0x8b, 0xe7, 0x8f, 0x5e, 0x45, 0xe7, + 0xfa, 0xd3, 0xd6, 0x27, 0x31, 0x88, 0x7d, 0xa9, 0x8e, 0x30, 0x37, 0xde, 0xa3, 0x45, 0xd8, 0x67, 0xf4, 0x13, 0x7b, + 0x4a, 0x56, 0xaf, 0x40, 0xe4, 0x09, 0x5a, 0x9d, 0x9d, 0x23, 0x82, 0x3f, 0x44, 0x7f, 0xe4, 0x97, 0xa8, 0xd1, 0xce, + 0xb3, 0x7f, 0xd9, 0xd6, 0xff, 0xff, 0xa7, 0xeb, 0xb9, 0x19, 0x2d, 0x1a, 0xe0, 0xa5, 0xff, 0x0b, 0x44, 0xdb, 0xd9, + 0xde, 0x08, 0x52, 0x03, 0x17, 0x1e, 0xf1, 0xb3, 0x5b, 0xcb, 0xba, 0xfc, 0xf2, 0xb9, 0x9a, 0x2d, 0xa3, 0x09, 0x95, + 0x93, 0x0b, 0x4d, 0x93, 0xa4, 0x86, 0x0c, 0x5e, 0x33, 0x49, 0x7f, 0x4d, 0xcb, 0xc0, 0xbb, 0x2d, 0xa9, 0x45, 0xe6, + 0x24, 0x1f, 0x67, 0x48, 0xc5, 0xe2, 0x59, 0xb7, 0xa9, 0x36, 0x1e, 0x3d, 0x8d, 0xde, 0x0c, 0x08, 0x5f, 0x59, 0x40, + 0xcf, 0xc1, 0x52, 0xd3, 0x95, 0x1b, 0x3b, 0x4b, 0xf7, 0xb6, 0x19, 0x87, 0x22, 0x82, 0xa6, 0x6e, 0x5d, 0x6e, 0x5b, + 0x1f, 0x95, 0x54, 0x72, 0xe6, 0xcd, 0x01, 0x02, 0xbc, 0xf8, 0x7e, 0xbc, 0x2d, 0x7d, 0xde, 0x0f, 0x72, 0x95, 0x46, + 0x18, 0xd6, 0xf1, 0x52, 0x3a, 0x8b, 0x57, 0x9b, 0x55, 0x08, 0xda, 0x05, 0x10, 0x67, 0x2d, 0x74, 0x8d, 0x80, 0xa6, + 0x45, 0xbc, 0xc7, 0x95, 0x20, 0x9b, 0x1a, 0x54, 0xb2, 0x94, 0x86, 0x0f, 0xf4, 0x07, 0x10, 0x83, 0xae, 0xb6, 0x91, + 0x0a, 0x6e, 0x1c, 0xbb, 0x4f, 0x65, 0x20, 0x99, 0xc4, 0xf7, 0xaf, 0xb2, 0x4a, 0x58, 0x1b, 0xc5, 0x78, 0x29, 0xb4, + 0x4f, 0x7e, 0xcd, 0x6d, 0xaa, 0x26, 0x07, 0x3d, 0xfb, 0x8f, 0x7b, 0x81, 0xee, 0x89, 0xa2, 0xed, 0x8c, 0x31, 0x35, + 0xcf, 0xb9, 0x07, 0x66, 0x91, 0x02, 0x8d, 0x21, 0xf4, 0xa0, 0x7f, 0x4f, 0xe8, 0xa1, 0x9e, 0x54, 0x45, 0x79, 0xb1, + 0x62, 0x5c, 0xbe, 0x9a, 0x4e, 0x0b, 0x69, 0x67, 0x1c, 0xbb, 0x0e, 0x77, 0x03, 0xff, 0xbd, 0xfa, 0x57, 0x1f, 0xc6, + 0x67, 0xfb, 0x18, 0xd3, 0x9e, 0xcf, 0x54, 0x4d, 0xfd, 0x38, 0xad, 0xfa, 0x6d, 0x70, 0x56, 0x79, 0x3e, 0xdf, 0x2a, + 0x2d, 0x10, 0x89, 0x44, 0xa1, 0xcc, 0x3c, 0xcf, 0xb7, 0x7d, 0x1a, 0x2d, 0x13, 0xdb, 0xf8, 0xd6, 0x0d, 0x8a, 0x7a, + 0x2f, 0xaf, 0x26, 0x0a, 0x80, 0x6e, 0x2c, 0x29, 0xa4, 0x5b, 0x62, 0x0b, 0x20, 0x9d, 0xcf, 0xb1, 0x27, 0x09, 0xac, + 0xb6, 0x26, 0xf3, 0x00, 0x0a, 0x59, 0xa2, 0x4d, 0x12, 0x23, 0xd2, 0x2f, 0x00, 0xe2, 0x35, 0x42, 0x79, 0x91, 0xfd, + 0x02, 0x69, 0x80, 0x55, 0x11, 0xe5, 0x8d, 0x4a, 0xe4, 0x2c, 0x6f, 0x32, 0x46, 0x19, 0x2c, 0xff, 0x07, 0xfc, 0xca, + 0x7c, 0x89, 0x40, 0x89, 0xc9, 0x6b, 0x87, 0x96, 0xce, 0x22, 0x4f, 0x2b, 0x6c, 0xf7, 0x43, 0x98, 0xcf, 0xd8, 0xf5, + 0xd9, 0x74, 0x33, 0xb3, 0x24, 0xb6, 0xb8, 0x6a, 0x6e, 0x3e, 0x73, 0xb8, 0x6d, 0x0b, 0xc9, 0xb6, 0xd5, 0x03, 0x7b, + 0x92, 0xee, 0xea, 0x87, 0x9b, 0xa7, 0x36, 0xfd, 0x48, 0xe1, 0xbc, 0x9a, 0xc8, 0xbc, 0x1c, 0x3e, 0xf2, 0xba, 0x77, + 0x2d, 0x42, 0x8d, 0x8d, 0x27, 0xe1, 0xa1, 0xe6, 0xbd, 0x6b, 0x13, 0xbe, 0xf2, 0xbf, 0x8a, 0xe3, 0x69, 0x55, 0xd6, + 0xfd, 0x7a, 0x1e, 0x1b, 0x1f, 0x31, 0x3e, 0x6a, 0x6d, 0xca, 0x0c, 0xc8, 0x43, 0xb5, 0xe7, 0xba, 0x93, 0xa7, 0xb4, + 0xdd, 0x8c, 0x99, 0x6e, 0x39, 0x17, 0x8a, 0xcc, 0xcc, 0xf6, 0x28, 0x17, 0x3c, 0xad, 0xf9, 0x7a, 0x0b, 0xe5, 0x2c, + 0x2d, 0xc7, 0x99, 0xda, 0x29, 0x5d, 0xcf, 0xe5, 0xda, 0xa3, 0x9a, 0x40, 0x0e, 0x29, 0x36, 0xea, 0x5d, 0x26, 0x41, + 0x90, 0xf0, 0xb1, 0xb4, 0x74, 0xeb, 0x0c, 0x28, 0x9f, 0x57, 0xb9, 0x2f, 0xd1, 0xd4, 0xaf, 0xae, 0x5d, 0x90, 0x71, + 0xb7, 0x03, 0x91, 0xd8, 0x56, 0x32, 0xcc, 0x8a, 0x48, 0x03, 0x0f, 0x4e, 0x4d, 0x6d, 0xcf, 0xba, 0xec, 0xac, 0xda, + 0x9a, 0x39, 0xa0, 0x03, 0x26, 0x8f, 0x96, 0x61, 0x3e, 0xe6, 0x05, 0x7f, 0xae, 0x39, 0xdb, 0x68, 0xd4, 0x2f, 0x55, + 0xd8, 0xb6, 0x19, 0x16, 0x3d, 0x29, 0xc0, 0x3f, 0x94, 0xc0, 0x9b, 0x0a, 0x32, 0x00, 0x5c, 0xba, 0x36, 0x1c, 0xc1, + 0x65, 0xcb, 0x42, 0x42, 0xb2, 0xad, 0x5e, 0x7b, 0x0b, 0x10, 0x6c, 0xb6, 0xa4, 0x04, 0x0a, 0xc5, 0xcd, 0xa0, 0x79, + 0x8b, 0x6f, 0xb5, 0x47, 0x92, 0x36, 0xbe, 0x98, 0xe1, 0xee, 0x93, 0x20, 0xf0, 0xe6, 0x37, 0x07, 0xb6, 0xe8, 0x87, + 0x31, 0xce, 0x20, 0x0c, 0xcb, 0xba, 0xbf, 0x64, 0x46, 0x3c, 0xf7, 0x51, 0x7a, 0x1b, 0x7f, 0xbb, 0x08, 0xde, 0x44, + 0xf2, 0x6b, 0x0c, 0xd6, 0x68, 0x9c, 0xbc, 0xe0, 0x92, 0xf7, 0x62, 0x13, 0x78, 0xeb, 0xe7, 0x70, 0xc6, 0x34, 0x92, + 0xe7, 0xb1, 0xba, 0xf9, 0xd3, 0xd8, 0xad, 0x47, 0xbe, 0x7f, 0xf9, 0xfd, 0x2e, 0x94, 0xa4, 0x35, 0xf2, 0x20, 0x85, + 0x5c, 0x64, 0x80, 0x3a, 0x05, 0x2f, 0x5b, 0xa2, 0x6e, 0x65, 0x45, 0x9e, 0x1c, 0xf6, 0xf2, 0xfb, 0x1f, 0xcd, 0xed, + 0xf8, 0x72, 0x83, 0xb4, 0x89, 0x06, 0x88, 0xd1, 0xa9, 0x92, 0x2e, 0x11, 0xc7, 0xd7, 0xe1, 0x3f, 0xfe, 0x30, 0x9a, + 0x6f, 0x9c, 0x89, 0x77, 0xdb, 0x68, 0x11, 0xb5, 0x95, 0xe4, 0xf9, 0x71, 0xf8, 0xc8, 0x73, 0x0b, 0x6b, 0xff, 0x33, + 0x6d, 0x34, 0x8d, 0x79, 0xa1, 0x4e, 0x4f, 0x98, 0xf1, 0x77, 0x98, 0xf1, 0xff, 0xa5, 0xc7, 0x7f, 0x5e, 0xfd, 0xff, + 0xf6, 0xfe, 0x4b, 0xd0, 0xd5, 0xf1, 0xf2, 0xfe, 0xaf, 0x59, 0xfe, 0x35, 0x7f, 0x84, 0x75, 0xfc, 0x6e, 0x67, 0xf3, + 0xb5, 0x4a, 0xb3, 0x29, 0x1f, 0xad, 0xed, 0x3c, 0x21, 0x60, 0x34, 0xcf, 0x4a, 0x14, 0xcc, 0x73, 0x5c, 0x9d, 0x9b, + 0x51, 0xfe, 0xd8, 0x11, 0x16, 0x7e, 0x31, 0xbe, 0x8b, 0xce, 0x75, 0x70, 0x2f, 0xe7, 0xdf, 0x48, 0xe1, 0xbe, 0x38, + 0xa6, 0xd8, 0x56, 0xd6, 0x4a, 0xfa, 0x3e, 0x74, 0xec, 0x88, 0xc0, 0xf6, 0x73, 0xff, 0x95, 0x95, 0xb1, 0x27, 0x83, + 0xb7, 0x21, 0x35, 0x6b, 0xc6, 0xe0, 0x0b, 0x6d, 0xa6, 0x95, 0xc3, 0x15, 0xf7, 0x6a, 0x6c, 0x43, 0x1b, 0x94, 0xa6, + 0x1b, 0x80, 0x90, 0x54, 0xd0, 0x20, 0xac, 0xb3, 0xdf, 0xfe, 0x72, 0xd1, 0x7e, 0x84, 0x22, 0x9f, 0xfe, 0x00, 0xac, + 0x57, 0x8e, 0xaa, 0xc0, 0x91, 0x18, 0x64, 0xc6, 0x2e, 0x05, 0xbd, 0xc1, 0x0c, 0x0f, 0xf5, 0xf4, 0xb6, 0x60, 0xcd, + 0x67, 0x09, 0xad, 0xd1, 0xaf, 0xc8, 0x70, 0x7d, 0x89, 0x24, 0x41, 0x88, 0xd3, 0x50, 0xf9, 0x7f, 0xe2, 0x89, 0x48, + 0x9a, 0x4e, 0x13, 0x45, 0xe5, 0x94, 0x55, 0xfd, 0x2a, 0xd1, 0xec, 0x05, 0xcd, 0x99, 0xbd, 0x4c, 0x8a, 0x41, 0x67, + 0x41, 0x50, 0x5c, 0xd1, 0xe3, 0x92, 0xab, 0x72, 0x26, 0xc4, 0x43, 0xec, 0x8f, 0xb1, 0x4c, 0x2c, 0xcc, 0x39, 0x46, + 0x7b, 0xe7, 0x47, 0xc8, 0x4a, 0xb2, 0x16, 0x36, 0x64, 0x0f, 0xba, 0xd3, 0x47, 0x4f, 0xa0, 0x41, 0xd7, 0x7f, 0xbc, + 0x82, 0x20, 0x7c, 0xe0, 0xdd, 0xea, 0x66, 0x54, 0xde, 0x35, 0xa3, 0x75, 0xf0, 0xf1, 0x62, 0xe0, 0xe8, 0x22, 0x10, + 0x1c, 0x4a, 0xec, 0x57, 0x1f, 0x24, 0x95, 0x9f, 0x4c, 0x9b, 0xb0, 0x3e, 0x1c, 0x07, 0xed, 0xb7, 0x90, 0x9c, 0x21, + 0x87, 0x96, 0x4b, 0x47, 0x25, 0x10, 0x27, 0xf9, 0x73, 0x60, 0xd9, 0xb6, 0x57, 0x92, 0xd1, 0xe3, 0x4c, 0xba, 0x65, + 0xf3, 0xd9, 0x23, 0x11, 0x56, 0x12, 0xb1, 0x51, 0xc1, 0x51, 0xae, 0xca, 0xc4, 0xfc, 0xa2, 0x3d, 0x2c, 0x6d, 0xc4, + 0xa1, 0xde, 0x66, 0x36, 0xec, 0x22, 0xd0, 0xdf, 0xca, 0x21, 0x69, 0xc5, 0xab, 0xc0, 0x49, 0x21, 0xdd, 0xf3, 0x84, + 0x85, 0x5b, 0x98, 0xdf, 0x7d, 0xe1, 0x76, 0xd8, 0x77, 0xd1, 0x6f, 0x91, 0xbd, 0xd7, 0x83, 0x6e, 0x04, 0xbb, 0xae, + 0x7a, 0xfd, 0x7d, 0x1d, 0x07, 0xfc, 0xdf, 0x4b, 0x26, 0xa4, 0xc0, 0x22, 0xc8, 0x17, 0xbc, 0x3c, 0x00, 0x03, 0x3f, + 0xb0, 0xef, 0x60, 0x12, 0xb2, 0xff, 0x18, 0x26, 0x08, 0xd9, 0x4e, 0xaa, 0x87, 0x76, 0x2c, 0xb8, 0x32, 0x1d, 0xb6, + 0x98, 0xb7, 0x82, 0x34, 0x48, 0x75, 0xef, 0x58, 0x28, 0x51, 0x22, 0xe3, 0xcc, 0x93, 0x2d, 0x01, 0x68, 0xd5, 0x8a, + 0xf0, 0x32, 0x20, 0xbf, 0x6a, 0x14, 0x14, 0xf4, 0x07, 0x98, 0x4d, 0xc1, 0x27, 0xa0, 0x83, 0x8b, 0x09, 0x13, 0x53, + 0x26, 0x1d, 0xb7, 0xab, 0xa3, 0x01, 0xa2, 0xa1, 0x73, 0x1e, 0x16, 0xb3, 0x7c, 0x9a, 0xea, 0xa5, 0x67, 0xbf, 0x81, + 0x2e, 0xda, 0x6d, 0xb3, 0x4f, 0x67, 0x1b, 0x82, 0x85, 0x0d, 0xa4, 0x59, 0x75, 0x12, 0xe1, 0xf9, 0x43, 0x9f, 0x98, + 0x01, 0x69, 0x8e, 0xb7, 0x4d, 0xc8, 0xca, 0x29, 0x08, 0x99, 0xd6, 0xcb, 0x43, 0xfd, 0xd6, 0x79, 0x2f, 0x90, 0xdf, + 0xce, 0xf8, 0x84, 0x0b, 0x46, 0x6b, 0x85, 0xc7, 0x44, 0xa8, 0x60, 0x84, 0xc4, 0x46, 0x40, 0x02, 0xbc, 0xc1, 0x6c, + 0x80, 0xee, 0x27, 0xa5, 0xba, 0xd3, 0x99, 0x63, 0xdc, 0x10, 0x0e, 0xf6, 0xa9, 0x12, 0xb8, 0xc9, 0xa8, 0xd0, 0x3f, + 0x91, 0xa9, 0x21, 0xd9, 0x6b, 0x50, 0x8c, 0x8f, 0x80, 0x0b, 0x32, 0x0b, 0x4a, 0x75, 0x18, 0x20, 0xf7, 0xb8, 0x1f, + 0x88, 0x0f, 0x7e, 0x88, 0xba, 0x1f, 0x71, 0x47, 0x9e, 0x77, 0xd3, 0x42, 0xd3, 0x1e, 0x71, 0x17, 0x34, 0xd8, 0xe6, + 0xfd, 0xfd, 0x4c, 0xef, 0x4d, 0xe5, 0x68, 0x81, 0xbe, 0x4f, 0x41, 0xa6, 0x52, 0x8f, 0xd7, 0x32, 0x55, 0x7b, 0x58, + 0x41, 0x2a, 0x81, 0xb2, 0x8c, 0xd9, 0x3c, 0xce, 0x56, 0xed, 0xb5, 0xb7, 0x51, 0xc4, 0x2f, 0xd2, 0x68, 0x35, 0x6c, + 0x05, 0x38, 0xdb, 0x3c, 0xd1, 0xb5, 0x9b, 0xec, 0x38, 0x14, 0xd1, 0xd1, 0x13, 0xe6, 0xac, 0x4c, 0x10, 0x9b, 0xd7, + 0x5c, 0xcb, 0xcd, 0x3a, 0x3a, 0x1b, 0xf5, 0x1d, 0x97, 0x3e, 0xc9, 0x4d, 0x49, 0xc1, 0x25, 0x2f, 0xdf, 0x5f, 0x25, + 0xaa, 0xf2, 0xb2, 0xec, 0xfb, 0xb4, 0x3a, 0xf3, 0xcc, 0x98, 0x7d, 0xad, 0x92, 0x97, 0xdf, 0x6a, 0x5a, 0x26, 0xff, + 0x9a, 0x06, 0x5b, 0xc7, 0xbe, 0xad, 0x8a, 0xaa, 0xdf, 0x12, 0x87, 0xcc, 0x5b, 0x29, 0x59, 0x81, 0x13, 0x58, 0x13, + 0x17, 0x99, 0x4f, 0xd1, 0x0b, 0xd3, 0x1d, 0x9c, 0x03, 0x00, 0x65, 0xd0, 0x24, 0xf8, 0xbf, 0xf8, 0x1a, 0x63, 0xcc, + 0x57, 0x8c, 0xc6, 0x1c, 0x37, 0x2c, 0xcf, 0x6f, 0xcd, 0x17, 0x78, 0x0b, 0xc8, 0x42, 0x5b, 0xd8, 0xc1, 0x63, 0x4d, + 0xba, 0x1b, 0xd2, 0x4e, 0x7d, 0xfa, 0xde, 0x77, 0xf8, 0xef, 0x82, 0xc2, 0xa4, 0x52, 0x20, 0xc3, 0xe5, 0xaa, 0x9b, + 0x11, 0x5a, 0xad, 0x9b, 0xff, 0xed, 0xee, 0x66, 0x54, 0x1c, 0x99, 0xf7, 0x20, 0xc3, 0x0d, 0x64, 0xac, 0xc5, 0x30, + 0x6c, 0x9a, 0x49, 0xb6, 0x3c, 0x86, 0xe8, 0xa3, 0xa6, 0xae, 0xf1, 0xba, 0x2b, 0x77, 0x37, 0x87, 0x0e, 0x6d, 0x60, + 0x70, 0xd7, 0xfe, 0x1c, 0x1e, 0x06, 0xf2, 0xa2, 0x28, 0xe2, 0x36, 0x3a, 0x44, 0x84, 0x9b, 0x98, 0xb1, 0x5a, 0xf2, + 0xff, 0x15, 0x33, 0x4d, 0x3e, 0x33, 0x1b, 0x9c, 0xac, 0x9b, 0xba, 0x62, 0x05, 0xfd, 0xb3, 0x51, 0xda, 0xbf, 0xca, + 0x3a, 0x6f, 0x05, 0x7f, 0xb4, 0x4a, 0x8c, 0x7d, 0x26, 0x39, 0xb4, 0xbc, 0xd0, 0xc7, 0x11, 0x2f, 0xfa, 0xf7, 0x01, + 0x09, 0x77, 0xfe, 0xb1, 0x8a, 0xba, 0x3a, 0x79, 0xa9, 0xaf, 0x6f, 0x57, 0xc2, 0x1e, 0x12, 0x3d, 0x23, 0x0a, 0x0d, + 0xd7, 0x5c, 0xe7, 0xe5, 0xd2, 0x07, 0x1b, 0x51, 0x41, 0xe7, 0xcb, 0x24, 0x88, 0xc6, 0x86, 0x4d, 0x35, 0x55, 0x17, + 0x9d, 0x33, 0x89, 0x50, 0x46, 0x3c, 0x36, 0x81, 0x3e, 0x0c, 0x16, 0x4b, 0x8d, 0x55, 0xcb, 0xc7, 0x6f, 0xd5, 0xe8, + 0x4f, 0x72, 0x76, 0x89, 0x46, 0x39, 0x7f, 0xc3, 0xac, 0xcf, 0xfa, 0xf8, 0x90, 0xd1, 0xbd, 0x7f, 0x27, 0xb9, 0xac, + 0xbf, 0xec, 0x2b, 0x4d, 0xb0, 0x39, 0x77, 0xa3, 0x36, 0x8f, 0x5d, 0x38, 0xc6, 0x3e, 0x42, 0x40, 0xd0, 0x37, 0x94, + 0xd3, 0x42, 0x0f, 0x31, 0x1d, 0x2d, 0xf7, 0x20, 0xbf, 0xad, 0x88, 0x92, 0x68, 0xd8, 0x2d, 0x8e, 0x87, 0xf4, 0x66, + 0x5b, 0xdc, 0x65, 0x43, 0x1d, 0x07, 0xdd, 0x4a, 0x58, 0x02, 0x8d, 0x29, 0x0d, 0xdf, 0x43, 0x8f, 0x9d, 0x2d, 0x99, + 0x5e, 0xee, 0x8c, 0x62, 0x4f, 0xf0, 0x73, 0x42, 0x7d, 0x03, 0xee, 0x78, 0xe0, 0x4b, 0x1c, 0x6a, 0x69, 0x76, 0x23, + 0x2f, 0xd4, 0x0a, 0xd5, 0xa9, 0xd5, 0xe0, 0x0b, 0x35, 0x7e, 0x3c, 0x23, 0x09, 0xf6, 0xf4, 0x55, 0x8d, 0x8b, 0x8f, + 0xd7, 0x72, 0xa1, 0x1c, 0x5d, 0x64, 0x0b, 0x34, 0x3b, 0x4f, 0xd3, 0x8e, 0x50, 0x8f, 0x95, 0xd4, 0xd5, 0xa7, 0x13, + 0x40, 0x45, 0x28, 0x6e, 0xe5, 0x50, 0x90, 0x7e, 0x96, 0xb9, 0x7b, 0x9c, 0x63, 0xa1, 0x06, 0xd0, 0x99, 0x96, 0x49, + 0xa7, 0x2e, 0xa4, 0xc5, 0x3f, 0x24, 0x98, 0xd8, 0xfe, 0x81, 0xa2, 0x00, 0x4a, 0x52, 0xe7, 0xd0, 0xc8, 0xef, 0xeb, + 0x4e, 0x63, 0x8c, 0x39, 0x78, 0x06, 0x0e, 0x84, 0xf5, 0x94, 0xbc, 0xf6, 0x0c, 0xda, 0x35, 0x94, 0x34, 0xe8, 0xb6, + 0xed, 0x71, 0x69, 0xdd, 0x6f, 0x87, 0x26, 0x8b, 0x84, 0x16, 0xaa, 0x2b, 0xd4, 0xc6, 0xb2, 0x74, 0xd2, 0x9d, 0x75, + 0x43, 0x8a, 0x4f, 0x14, 0x6e, 0x61, 0x2e, 0x5b, 0x95, 0xaf, 0x9c, 0x1b, 0x2c, 0xe1, 0xd2, 0x28, 0xb1, 0xe4, 0xef, + 0x7b, 0x40, 0x10, 0x85, 0xaa, 0x3c, 0x13, 0x44, 0x48, 0x6a, 0x87, 0x03, 0x26, 0x8a, 0xf9, 0x7c, 0x13, 0x09, 0x1a, + 0x7c, 0xf5, 0xa3, 0x82, 0xa4, 0x50, 0x09, 0x08, 0x80, 0xc1, 0x40, 0x0a, 0x28, 0xbf, 0x78, 0x32, 0xee, 0x16, 0x3a, + 0xe7, 0x44, 0xfc, 0x40, 0x09, 0x32, 0xe4, 0xcf, 0x7f, 0x9a, 0x10, 0x06, 0x6d, 0x00, 0xc9, 0x59, 0x70, 0xc0, 0x0c, + 0x0b, 0xfd, 0x69, 0xa4, 0xab, 0x96, 0xc4, 0x52, 0x8b, 0x3d, 0x8f, 0xdb, 0x90, 0x5e, 0xb0, 0xe2, 0x12, 0x4a, 0xba, + 0x31, 0x7c, 0xec, 0x75, 0x48, 0x79, 0xd9, 0x6b, 0x7c, 0xc0, 0xc4, 0xc2, 0x70, 0x91, 0xab, 0x9c, 0xa6, 0xb0, 0x4d, + 0xc0, 0x63, 0x3e, 0x1c, 0xa4, 0xde, 0x10, 0x3c, 0x64, 0x95, 0x8d, 0x4e, 0x32, 0x03, 0x07, 0x7f, 0x9f, 0x0b, 0x09, + 0x29, 0x8c, 0x63, 0x18, 0xe2, 0x37, 0x89, 0xe5, 0x44, 0x36, 0xf3, 0x36, 0xce, 0xd0, 0xe9, 0x07, 0xec, 0x3a, 0x50, + 0x77, 0x36, 0x95, 0x10, 0xec, 0x25, 0x1d, 0x13, 0x51, 0x4a, 0x75, 0x19, 0x14, 0x9f, 0x11, 0xc5, 0xa5, 0x1f, 0xe1, + 0x4c, 0x87, 0x9f, 0xb8, 0x97, 0x01, 0x91, 0x98, 0x89, 0xc8, 0xd9, 0xe0, 0x48, 0x9e, 0xc9, 0x96, 0xb5, 0x74, 0x51, + 0xd3, 0xfe, 0x47, 0x82, 0xee, 0x88, 0x5c, 0x9c, 0x9f, 0x65, 0xa1, 0xee, 0xb4, 0xb2, 0xce, 0x26, 0x8b, 0xd3, 0x0f, + 0xde, 0x75, 0xb7, 0xaa, 0xa2, 0x84, 0xf7, 0x80, 0x06, 0x99, 0xdc, 0xb9, 0x55, 0xcb, 0xd8, 0xea, 0xf6, 0x9d, 0xab, + 0x83, 0xe6, 0xda, 0x41, 0x45, 0x12, 0xf9, 0xf9, 0x26, 0xcf, 0x12, 0x33, 0x8d, 0x3e, 0x40, 0xc9, 0x5a, 0x72, 0x70, + 0xa9, 0x01, 0x6a, 0x0c, 0xf8, 0x72, 0xcf, 0xa4, 0xf6, 0x51, 0x07, 0xbe, 0x13, 0x13, 0x22, 0x17, 0xb9, 0x57, 0x9a, + 0x46, 0x5e, 0x4e, 0xef, 0x36, 0x2c, 0xf2, 0x23, 0xbf, 0xfa, 0x39, 0xb3, 0x3c, 0xa5, 0x67, 0x95, 0x30, 0x8b, 0x15, + 0x1e, 0xd1, 0xcd, 0x30, 0x8f, 0xe0, 0xa3, 0xae, 0xfa, 0x73, 0x03, 0x68, 0xf5, 0xe0, 0x4d, 0x47, 0xa3, 0x08, 0xe0, + 0xb9, 0xe9, 0x2a, 0x71, 0x39, 0x3f, 0xe1, 0x06, 0x86, 0x3d, 0x4c, 0x30, 0x10, 0x12, 0x65, 0x26, 0x0c, 0x00, 0x76, + 0x0e, 0xf1, 0x5b, 0xcc, 0xef, 0x75, 0xc3, 0xa6, 0x5a, 0xe0, 0x9c, 0x29, 0x0b, 0xb8, 0x5e, 0x46, 0x9a, 0x0b, 0xa8, + 0x0b, 0xb2, 0x9f, 0xb4, 0x11, 0x63, 0xfb, 0x4c, 0x09, 0x27, 0x8c, 0x9b, 0x01, 0x8d, 0x0d, 0x9a, 0x95, 0x4f, 0xcc, + 0x4d, 0x02, 0x9f, 0x2a, 0x11, 0xb9, 0xb4, 0x47, 0x22, 0xf9, 0x0c, 0x25, 0x70, 0x84, 0x5f, 0xa4, 0xff, 0x03, 0x44, + 0x7a, 0x3b, 0x27, 0x68, 0x6f, 0x43, 0xc6, 0xfb, 0x52, 0x4b, 0x9c, 0xb4, 0x8c, 0xed, 0x1e, 0x8a, 0xc3, 0xeb, 0x60, + 0x44, 0xd7, 0x58, 0xae, 0x6b, 0x34, 0x7e, 0x49, 0xa9, 0x2e, 0xb6, 0xfb, 0x44, 0x0a, 0x0c, 0x00, 0xbd, 0x37, 0x82, + 0xc6, 0x5b, 0xff, 0xd7, 0x05, 0x0e, 0xb3, 0xba, 0x24, 0x94, 0xf6, 0x40, 0x7c, 0x93, 0x7f, 0x63, 0x1a, 0x0e, 0x0a, + 0xdc, 0xd4, 0x4a, 0xbc, 0xd7, 0x76, 0x77, 0xe9, 0x50, 0xf0, 0xf3, 0x75, 0x18, 0x32, 0x7f, 0xc1, 0x11, 0x36, 0x90, + 0xd3, 0x76, 0xfa, 0x55, 0x35, 0xd2, 0xce, 0x20, 0xc3, 0x15, 0x79, 0x41, 0x2a, 0x89, 0xfc, 0xa8, 0x27, 0xab, 0x4b, + 0x2c, 0xec, 0x14, 0x07, 0x80, 0xee, 0x38, 0x86, 0x4d, 0x1b, 0x1b, 0xcd, 0x13, 0xcf, 0xc1, 0x99, 0xeb, 0x14, 0x00, + 0x78, 0xdf, 0x89, 0xc1, 0x84, 0x39, 0xe6, 0x28, 0x5b, 0x81, 0x7a, 0x3c, 0xc9, 0x1c, 0x1c, 0xe7, 0xa3, 0xfa, 0xf8, + 0x84, 0x6d, 0x56, 0x5c, 0x5e, 0x00, 0xc4, 0xe1, 0x38, 0x29, 0x0c, 0x86, 0x44, 0xbd, 0x4f, 0x45, 0xd6, 0xd1, 0x74, + 0xd1, 0x3c, 0xb9, 0x69, 0xec, 0xde, 0x07, 0xa7, 0x86, 0x04, 0xa8, 0x0a, 0xa6, 0x61, 0xfd, 0x9f, 0x81, 0xe0, 0x25, + 0x7b, 0x57, 0xa0, 0xd9, 0x86, 0x83, 0x52, 0xf8, 0xc8, 0x21, 0xed, 0x90, 0x14, 0xea, 0x70, 0x2e, 0xa2, 0x79, 0x16, + 0x82, 0xa7, 0x0d, 0x64, 0x44, 0x5e, 0x4c, 0xde, 0x6b, 0x57, 0xb6, 0xeb, 0x72, 0x8f, 0xd2, 0x2d, 0xce, 0x1a, 0xab, + 0xd9, 0xa4, 0x47, 0xf4, 0xa0, 0x49, 0x15, 0x40, 0x36, 0x81, 0x0a, 0xaa, 0x90, 0x06, 0x1b, 0x3f, 0x07, 0x40, 0xbd, + 0xdc, 0xf0, 0xb6, 0xc6, 0xbd, 0x2c, 0x13, 0xba, 0xad, 0xd1, 0x50, 0x93, 0x30, 0xb8, 0x0f, 0x0c, 0x3a, 0x83, 0x38, + 0x51, 0x3b, 0xcf, 0x78, 0xe8, 0x24, 0x73, 0x21, 0xf4, 0xf8, 0x0b, 0xfc, 0x22, 0xf1, 0xc2, 0xaa, 0xcc, 0xad, 0xe0, + 0x59, 0x4a, 0xe9, 0x3d, 0x06, 0x6b, 0xf5, 0x6f, 0xf7, 0xb3, 0xa3, 0xd2, 0x40, 0x03, 0x9e, 0x23, 0xc9, 0xdd, 0xbc, + 0x3d, 0xd3, 0xa3, 0x3b, 0xfe, 0xf2, 0xea, 0x1b, 0x4f, 0x97, 0xd9, 0x68, 0x74, 0x54, 0x94, 0xf8, 0xc8, 0xe9, 0xc1, + 0x76, 0x66, 0x2d, 0x71, 0xfd, 0x06, 0x24, 0x80, 0x5d, 0x6d, 0x3c, 0x6d, 0xc3, 0xcb, 0x3a, 0xed, 0x49, 0x13, 0xe4, + 0xca, 0xfe, 0xa3, 0xb6, 0xa7, 0x8f, 0x78, 0xf4, 0xc4, 0x94, 0x23, 0x4a, 0x46, 0x11, 0xa8, 0x7e, 0xa0, 0x00, 0xf2, + 0x12, 0x9a, 0x92, 0x2e, 0x08, 0x7c, 0x65, 0x50, 0xb4, 0x1c, 0x30, 0x06, 0x28, 0x47, 0x7d, 0xa7, 0x39, 0x7d, 0xd3, + 0xb3, 0x5c, 0x09, 0x78, 0x6f, 0x51, 0x55, 0x9e, 0x5b, 0xd9, 0x86, 0x4b, 0x79, 0xed, 0xe2, 0xd0, 0x1a, 0xeb, 0x69, + 0xb5, 0xb6, 0xeb, 0x54, 0x3a, 0x7c, 0x8a, 0x63, 0xe4, 0xba, 0xc6, 0x33, 0x08, 0x68, 0x1e, 0x68, 0x92, 0x77, 0xda, + 0xae, 0xa3, 0x59, 0x0d, 0x87, 0x11, 0x7d, 0x5e, 0x51, 0xac, 0x82, 0x1b, 0x64, 0xbe, 0x55, 0xda, 0xa7, 0x35, 0x18, + 0xd6, 0x29, 0x29, 0x7d, 0x56, 0xbf, 0xd2, 0x13, 0x3f, 0xe5, 0x4d, 0xdf, 0x37, 0x25, 0xe1, 0xdb, 0xe4, 0x4b, 0xea, + 0xd4, 0xa5, 0xe9, 0x71, 0x7a, 0xe4, 0x50, 0x8e, 0x1d, 0xdc, 0xbd, 0xf2, 0x2b, 0xf4, 0x3a, 0x33, 0x50, 0x3f, 0x73, + 0x73, 0xda, 0x5d, 0x2b, 0x6a, 0xca, 0x92, 0xea, 0xe9, 0xeb, 0x5c, 0xbd, 0x0b, 0x6f, 0x6b, 0x22, 0x12, 0xdc, 0x9f, + 0xf1, 0x58, 0x91, 0xb9, 0x16, 0x46, 0x7e, 0x58, 0x45, 0x0d, 0x76, 0xad, 0xd4, 0x88, 0x3b, 0xb3, 0x84, 0x9e, 0x14, + 0xbb, 0xf9, 0x2a, 0x89, 0x60, 0x54, 0x19, 0x99, 0x3c, 0x9d, 0xe5, 0x84, 0xa0, 0x5f, 0x31, 0x88, 0x97, 0x75, 0x8d, + 0x17, 0xd7, 0x6a, 0xca, 0x3c, 0x75, 0xeb, 0x11, 0xd7, 0x9f, 0x6f, 0x43, 0xed, 0x7b, 0x02, 0xae, 0xb4, 0xa9, 0x63, + 0x1e, 0x8d, 0xe1, 0x4b, 0x46, 0x72, 0x5e, 0xd0, 0xd4, 0x04, 0xec, 0x17, 0x10, 0x41, 0x94, 0x7f, 0x34, 0xdb, 0x93, + 0x9c, 0x92, 0xed, 0x2f, 0x7c, 0x73, 0xdf, 0x2a, 0x3e, 0x68, 0x3d, 0xfd, 0xa3, 0x48, 0xd1, 0xf4, 0x92, 0x50, 0x54, + 0x54, 0x06, 0xcd, 0x5b, 0x4a, 0x7d, 0xce, 0xf3, 0x2f, 0x75, 0xc9, 0x92, 0x51, 0x98, 0x25, 0x99, 0x25, 0x7d, 0x00, + 0x34, 0xf5, 0x35, 0xe4, 0x8c, 0xa2, 0xf1, 0x33, 0x4a, 0xfe, 0x35, 0xfc, 0x38, 0xed, 0xee, 0xd1, 0x77, 0xef, 0x4a, + 0x1b, 0x92, 0x40, 0x95, 0xde, 0xd2, 0x1f, 0xd3, 0x52, 0x5f, 0x14, 0x8d, 0x2b, 0x45, 0x3b, 0xc3, 0xfc, 0xb4, 0x78, + 0xb6, 0xe0, 0x17, 0xcf, 0x16, 0xbc, 0xf6, 0x82, 0xb9, 0x89, 0x75, 0xab, 0x82, 0x97, 0xc7, 0xb8, 0xc6, 0x50, 0x62, + 0xa7, 0x76, 0xfc, 0x47, 0x47, 0x60, 0x4a, 0xff, 0xa9, 0x51, 0x06, 0xfa, 0x53, 0x06, 0x4e, 0x33, 0x37, 0xcc, 0x28, + 0xba, 0xf1, 0xc2, 0x08, 0x33, 0xe7, 0x49, 0x13, 0x7c, 0x4d, 0x63, 0x0d, 0x76, 0xb5, 0x9c, 0x65, 0x08, 0x45, 0x8c, + 0x1f, 0x15, 0xb6, 0xa0, 0xed, 0x4c, 0xf8, 0x09, 0x44, 0x2b, 0x40, 0xef, 0x39, 0x37, 0xc7, 0xd1, 0xce, 0x52, 0xdf, + 0x3a, 0xa7, 0x98, 0x3e, 0x9c, 0x88, 0xec, 0x81, 0xa6, 0xee, 0x39, 0x9d, 0xf8, 0x25, 0x91, 0xb1, 0xa8, 0xdf, 0x9f, + 0x43, 0xdb, 0x22, 0xdd, 0xab, 0x11, 0x38, 0x05, 0x20, 0x6f, 0x48, 0x18, 0xfe, 0x45, 0x43, 0x79, 0x8d, 0x3c, 0x52, + 0xa9, 0x4c, 0x9f, 0x77, 0x5a, 0xd3, 0x89, 0x2c, 0x2d, 0xb4, 0x93, 0x31, 0xb6, 0xac, 0x4a, 0x14, 0x5b, 0x99, 0xf7, + 0x0c, 0x12, 0xc9, 0xe7, 0x2f, 0x32, 0x5a, 0xac, 0xa9, 0x21, 0x40, 0xb3, 0x0a, 0xb5, 0x75, 0xe1, 0xe9, 0x15, 0x2a, + 0x06, 0x86, 0x82, 0xb2, 0xef, 0x87, 0xd8, 0x1a, 0x3e, 0xb0, 0x9f, 0xf5, 0x1e, 0x12, 0xaf, 0xbd, 0xc0, 0x44, 0x10, + 0xae, 0x37, 0x05, 0x71, 0x6b, 0x97, 0x64, 0x04, 0x37, 0x54, 0x2f, 0xd8, 0x98, 0x63, 0x67, 0xa7, 0x70, 0x76, 0xec, + 0xec, 0x24, 0x67, 0x16, 0x5d, 0xc9, 0x4c, 0xbd, 0x22, 0xb1, 0x64, 0x85, 0x1d, 0xbc, 0xfc, 0x3a, 0xaf, 0xe4, 0x10, + 0x0b, 0x40, 0x95, 0x96, 0x5c, 0x95, 0x16, 0xc4, 0xcc, 0x35, 0x90, 0x06, 0x75, 0x20, 0xf0, 0x12, 0xbf, 0x99, 0x7c, + 0x00, 0x8c, 0x1d, 0x9c, 0xa3, 0xa3, 0x72, 0xda, 0x18, 0xf6, 0xbb, 0x2a, 0x13, 0x28, 0xaa, 0xe6, 0x83, 0x29, 0xc9, + 0x1b, 0x3c, 0x33, 0x2d, 0xd9, 0x43, 0x21, 0x7c, 0xc1, 0xbb, 0x33, 0x63, 0x8a, 0xf9, 0xed, 0x1b, 0x15, 0xfd, 0xbc, + 0xa2, 0x51, 0xa8, 0x39, 0x54, 0x5f, 0x68, 0x9e, 0xe8, 0x01, 0x99, 0xa6, 0x38, 0xb9, 0xf8, 0x50, 0x0a, 0xf9, 0xf8, + 0x77, 0xf6, 0x05, 0xf1, 0xf6, 0x76, 0xb1, 0xad, 0xc0, 0x09, 0xab, 0xd8, 0x09, 0x6d, 0xae, 0xf9, 0x67, 0xea, 0x20, + 0x6b, 0x66, 0x35, 0xde, 0x19, 0x9f, 0x5f, 0xd5, 0xd8, 0x24, 0x9d, 0x21, 0xa8, 0xe0, 0x69, 0x67, 0x08, 0xda, 0xf2, + 0x93, 0xa4, 0x80, 0x08, 0x34, 0x0e, 0xd4, 0x65, 0x33, 0x91, 0x03, 0x73, 0x01, 0x95, 0x2c, 0x67, 0xb8, 0xe6, 0xb5, + 0x3f, 0x74, 0x2d, 0x32, 0x4f, 0xa0, 0x45, 0xf3, 0x68, 0xa7, 0xa7, 0xea, 0xc8, 0xd7, 0xde, 0xa5, 0xd6, 0x4d, 0x2d, + 0x96, 0x25, 0x5c, 0xcf, 0xc8, 0x4d, 0xac, 0xcb, 0xdb, 0x00, 0xcd, 0xe4, 0xd3, 0x28, 0xfc, 0x89, 0xa9, 0x29, 0x35, + 0x91, 0x31, 0x64, 0x5b, 0x48, 0x55, 0xdb, 0x28, 0xd1, 0x36, 0xa4, 0xdd, 0xce, 0x4f, 0x5b, 0x48, 0xf1, 0x53, 0x5b, + 0x16, 0xd2, 0xfe, 0xf5, 0x0a, 0x4a, 0x49, 0xf8, 0x20, 0x5c, 0x4c, 0x00, 0x84, 0xfb, 0xd0, 0x29, 0x0b, 0x70, 0xe1, + 0x8e, 0xa3, 0xb0, 0xd7, 0x3b, 0x6b, 0xae, 0xa6, 0xc5, 0xe6, 0x07, 0xdd, 0xe7, 0x61, 0x50, 0x8e, 0xf3, 0x9a, 0x3c, + 0x15, 0xdc, 0xf8, 0x23, 0x0b, 0x85, 0x82, 0xf1, 0x6e, 0x22, 0x66, 0xa5, 0xe8, 0xb5, 0x25, 0xc5, 0xda, 0xa9, 0x80, + 0x1a, 0x84, 0xdd, 0x40, 0x55, 0x33, 0xa6, 0x34, 0x95, 0x96, 0x60, 0xf9, 0xbc, 0xd3, 0xf4, 0x9f, 0xd3, 0xf6, 0x47, + 0x42, 0x48, 0xad, 0x6c, 0x43, 0xe1, 0x01, 0x94, 0xe8, 0xb4, 0xcf, 0xfd, 0x45, 0xf0, 0xea, 0xab, 0x4f, 0xd7, 0xd1, + 0x48, 0x8e, 0x12, 0xb3, 0xa8, 0xbb, 0x76, 0x73, 0x7a, 0xfd, 0x9f, 0x91, 0xbc, 0x14, 0xcd, 0x36, 0x4c, 0x03, 0xc5, + 0xcd, 0x5c, 0xf3, 0x5c, 0xd0, 0x45, 0xce, 0x71, 0x41, 0xc5, 0x0b, 0xc7, 0xb5, 0xac, 0xa9, 0xc6, 0x57, 0xba, 0x8a, + 0x41, 0xa5, 0x8c, 0x87, 0x0d, 0x9e, 0x13, 0x8d, 0x30, 0x5c, 0xaf, 0x1c, 0x36, 0x15, 0x4a, 0x5f, 0x09, 0x1c, 0x36, + 0xb5, 0x11, 0x22, 0x59, 0xc3, 0x51, 0xc3, 0x9d, 0x61, 0x49, 0x2b, 0x7d, 0xe5, 0x36, 0x88, 0x76, 0xeb, 0xd3, 0x1c, + 0x3c, 0x0a, 0x3e, 0xb3, 0xc3, 0x23, 0x3c, 0xa9, 0x49, 0x4e, 0x11, 0x3c, 0xc8, 0x93, 0x87, 0xfa, 0x40, 0x77, 0x7e, + 0x29, 0xd1, 0x5e, 0xc1, 0x22, 0xe3, 0x31, 0xcd, 0xf3, 0x10, 0x3a, 0xa6, 0x5b, 0x09, 0x6d, 0xd7, 0x0b, 0xf6, 0xc2, + 0xb8, 0x7a, 0x48, 0x11, 0x4d, 0x09, 0xf4, 0x3f, 0x8d, 0x31, 0x3b, 0xab, 0x97, 0x0f, 0xef, 0x33, 0x66, 0x60, 0x3b, + 0xae, 0xdd, 0x40, 0x81, 0xec, 0xfb, 0xbf, 0x8e, 0xc2, 0x9b, 0x58, 0xf8, 0x69, 0x9f, 0xd4, 0x6f, 0x9d, 0x75, 0x8e, + 0xfd, 0x0b, 0xbb, 0x4d, 0x96, 0x5e, 0x39, 0x8a, 0x6b, 0x14, 0x60, 0x72, 0x2c, 0x3d, 0xaa, 0xef, 0x45, 0xc1, 0x9e, + 0xf0, 0x40, 0x9c, 0xac, 0x62, 0xff, 0x90, 0x5e, 0x1b, 0x00, 0x4c, 0x61, 0x72, 0x9f, 0x56, 0xf6, 0xab, 0x1f, 0x6e, + 0x6c, 0xb0, 0xe5, 0x4a, 0x85, 0x7d, 0x0d, 0x87, 0xeb, 0x55, 0x42, 0xb0, 0xdb, 0xaa, 0xeb, 0x81, 0x90, 0x9b, 0x8c, + 0x37, 0xc5, 0xe0, 0xad, 0x05, 0x5e, 0xb0, 0x5d, 0xc7, 0xc2, 0x9b, 0xd8, 0x6c, 0x7d, 0xa1, 0xf6, 0x82, 0x8f, 0xf2, + 0xa8, 0x3f, 0xcb, 0x83, 0xfe, 0x3c, 0xd6, 0x01, 0xfc, 0xe1, 0x39, 0x61, 0x95, 0x7f, 0x92, 0x18, 0x1c, 0x61, 0x61, + 0xcd, 0x6c, 0x34, 0x34, 0x17, 0xc6, 0x8d, 0x19, 0x3d, 0xf5, 0xc9, 0xc5, 0xa1, 0xb8, 0xd9, 0x5a, 0x02, 0x97, 0xe8, + 0xd4, 0x2c, 0xfd, 0xf7, 0x06, 0x4f, 0x42, 0xa4, 0xbc, 0x55, 0xfa, 0x03, 0xb4, 0x8b, 0xd5, 0x97, 0xff, 0xd3, 0x4a, + 0x38, 0x60, 0x9c, 0x46, 0xe9, 0x22, 0x7e, 0xbf, 0x82, 0x1b, 0xf9, 0x27, 0x5b, 0x58, 0xbd, 0x13, 0x7f, 0xd4, 0xa6, + 0xf6, 0xf4, 0x69, 0x58, 0xe8, 0x0b, 0x63, 0x94, 0xb0, 0x18, 0xc6, 0x4b, 0x63, 0x77, 0x07, 0x33, 0x36, 0x6c, 0x9f, + 0x6f, 0x24, 0x7c, 0xe8, 0x9f, 0x17, 0x82, 0x3a, 0xce, 0xa9, 0xd9, 0xd2, 0x8a, 0x46, 0xbf, 0x5d, 0xc2, 0xd6, 0x40, + 0x02, 0xcc, 0x33, 0xbf, 0x84, 0xc0, 0xc9, 0x24, 0x6a, 0x12, 0x12, 0x58, 0xed, 0x4c, 0xff, 0x6a, 0x55, 0xf1, 0xfb, + 0x7c, 0xe8, 0x10, 0xde, 0xd6, 0xae, 0xe2, 0xfb, 0x42, 0xb8, 0x99, 0xd4, 0xcd, 0x06, 0xe9, 0xc7, 0xb2, 0x4d, 0x63, + 0xe7, 0x00, 0xbe, 0x52, 0x3d, 0x14, 0x90, 0x13, 0xd4, 0x3b, 0x9d, 0xd7, 0x1d, 0xea, 0x88, 0x83, 0x74, 0x31, 0xdb, + 0xa0, 0xa9, 0x37, 0x2b, 0xdf, 0x76, 0xdc, 0x68, 0x46, 0x43, 0xe3, 0xdc, 0x20, 0x85, 0x83, 0x6f, 0x04, 0xe8, 0x6c, + 0xba, 0xc7, 0x0d, 0xd2, 0x49, 0x33, 0x34, 0xfd, 0xd6, 0x11, 0xa5, 0x9a, 0x84, 0xd9, 0x64, 0x0b, 0x8b, 0xa3, 0xb4, + 0xa3, 0xd6, 0x5d, 0xe1, 0xf6, 0xcd, 0x85, 0x83, 0x96, 0x53, 0xb4, 0x49, 0x24, 0x8a, 0xc4, 0x51, 0xcb, 0x29, 0x7d, + 0x74, 0x8a, 0x62, 0x84, 0x8e, 0xb3, 0x8b, 0xcd, 0xab, 0x98, 0x69, 0xb8, 0x12, 0x15, 0x73, 0x7f, 0x81, 0xef, 0xc6, + 0xba, 0x7b, 0x8a, 0x49, 0xa9, 0x74, 0x49, 0x75, 0x17, 0xb3, 0x05, 0xbe, 0x8e, 0xf9, 0x0b, 0xab, 0x57, 0x17, 0xaf, + 0x17, 0x56, 0x93, 0xe9, 0x16, 0xfc, 0xb4, 0x69, 0xfd, 0x16, 0x92, 0x96, 0x03, 0x42, 0x15, 0xff, 0x4c, 0xa6, 0x78, + 0xd5, 0x58, 0x43, 0x4a, 0x36, 0x47, 0x9a, 0x7e, 0xaf, 0xd0, 0xe4, 0x23, 0x8d, 0xce, 0xd2, 0xd5, 0xa9, 0x58, 0xa5, + 0x9f, 0xaa, 0x14, 0xf1, 0xad, 0xda, 0x84, 0x51, 0x41, 0x2b, 0x73, 0x47, 0x75, 0x6f, 0xdf, 0xae, 0x23, 0x44, 0x9f, + 0x97, 0x84, 0x72, 0xec, 0x72, 0xa9, 0x03, 0x1d, 0x20, 0xbe, 0xed, 0x14, 0x30, 0x2f, 0xc7, 0xa8, 0xdd, 0xbc, 0x1b, + 0x0b, 0x09, 0xf9, 0x87, 0xa4, 0x8e, 0x93, 0xd1, 0xa5, 0xf8, 0xb9, 0xee, 0xf9, 0x59, 0xde, 0x89, 0x60, 0x3e, 0xfa, + 0x36, 0x62, 0x50, 0x96, 0x60, 0xf3, 0x5f, 0xe7, 0x81, 0x02, 0x93, 0x40, 0x93, 0x6b, 0x23, 0x4e, 0x35, 0xa9, 0xfa, + 0x5a, 0x82, 0xc2, 0x34, 0xbd, 0xaa, 0x15, 0xb9, 0xa9, 0x96, 0x11, 0x0b, 0xf6, 0x80, 0x3a, 0x53, 0x74, 0x0b, 0xc0, + 0x22, 0x8c, 0xcf, 0xc4, 0xd9, 0xf2, 0x45, 0xa6, 0xd4, 0x58, 0x0e, 0x15, 0x3b, 0xf6, 0xeb, 0xd9, 0xfd, 0xf5, 0x1f, + 0xcd, 0xdf, 0xfe, 0xfa, 0xda, 0xab, 0x47, 0x59, 0x3a, 0x84, 0xfb, 0x9d, 0x75, 0x0c, 0x83, 0x02, 0x44, 0x65, 0xfb, + 0x6d, 0x89, 0xbf, 0xe6, 0x55, 0x94, 0x74, 0xd6, 0xc6, 0xbd, 0x49, 0xc2, 0xa7, 0x35, 0x23, 0xdf, 0x06, 0x16, 0x7c, + 0x6b, 0x98, 0x5d, 0xea, 0xe0, 0x39, 0xd5, 0xa3, 0x9d, 0x02, 0x8e, 0x83, 0xc1, 0xbf, 0x91, 0xda, 0x26, 0x0c, 0x30, + 0xe4, 0x24, 0x9a, 0x2f, 0x74, 0x65, 0x79, 0x9e, 0xa5, 0x64, 0x47, 0x4c, 0xdf, 0x73, 0xc1, 0x8f, 0xbc, 0x2e, 0xf1, + 0x16, 0x6e, 0x08, 0xb0, 0x09, 0xca, 0x1a, 0x03, 0xc7, 0x29, 0x6e, 0xe4, 0xdb, 0x0a, 0xef, 0x21, 0xb0, 0x33, 0x85, + 0x5b, 0x3c, 0xbf, 0xdb, 0x8b, 0x23, 0x04, 0xa7, 0xe0, 0x93, 0x95, 0xd9, 0xac, 0xe8, 0xa5, 0x7f, 0x99, 0x95, 0xf4, + 0xc8, 0x28, 0x77, 0x9b, 0x3c, 0x6d, 0xd9, 0x9a, 0x02, 0x30, 0x83, 0x67, 0x0c, 0x58, 0x70, 0xa7, 0x98, 0xc6, 0x9f, + 0xde, 0xf7, 0x11, 0x6b, 0x75, 0xcb, 0x97, 0xd3, 0x3a, 0x76, 0xef, 0x53, 0x92, 0x40, 0x8d, 0xb3, 0xeb, 0xc7, 0xcb, + 0xb8, 0x6e, 0xdd, 0x67, 0x56, 0xb7, 0x1e, 0x4b, 0xf1, 0xdf, 0x57, 0xab, 0xf3, 0x25, 0x7a, 0x95, 0xf0, 0x26, 0x15, + 0xf5, 0xa4, 0x92, 0x73, 0x8b, 0xbc, 0xbc, 0x72, 0x2e, 0x06, 0xe4, 0xd9, 0x51, 0xbb, 0x51, 0x85, 0x16, 0x5b, 0x63, + 0xb1, 0x3e, 0xcd, 0x24, 0x43, 0x7d, 0xaf, 0xe1, 0x5e, 0x9f, 0x5e, 0xae, 0xc2, 0xf2, 0x34, 0xaa, 0x5d, 0x5a, 0x5f, + 0x6e, 0x94, 0xe4, 0xba, 0xf8, 0x81, 0xb5, 0xb5, 0xf0, 0xe6, 0x60, 0xa3, 0x65, 0x4c, 0xb4, 0x92, 0xd5, 0xd3, 0x4a, + 0x56, 0x4e, 0x13, 0x97, 0x7b, 0xbd, 0xe8, 0x02, 0x39, 0xfe, 0x60, 0xd0, 0xaa, 0xe5, 0x83, 0xc6, 0xac, 0xb6, 0x0f, + 0x3a, 0xa5, 0x5a, 0x9f, 0x14, 0x16, 0xf1, 0xc8, 0x1a, 0x70, 0xb0, 0xb1, 0x56, 0x4a, 0xa6, 0x95, 0x6d, 0x32, 0xae, + 0xd0, 0x0f, 0xa9, 0x6a, 0xd5, 0xfb, 0x1f, 0xa6, 0xb8, 0xc1, 0xd5, 0xc6, 0x9f, 0x05, 0xb9, 0xfe, 0x53, 0x61, 0x47, + 0x39, 0xe8, 0x28, 0xb4, 0xfe, 0xe6, 0x7f, 0xa8, 0xf9, 0x11, 0xdc, 0x0c, 0xb1, 0x95, 0xd9, 0x5b, 0x10, 0xb5, 0x2b, + 0x09, 0xe4, 0x7b, 0xc0, 0xb5, 0x02, 0xa4, 0x62, 0xaf, 0x57, 0xa2, 0x75, 0x9a, 0x04, 0x63, 0x43, 0x90, 0x39, 0x8b, + 0xd8, 0x05, 0xa9, 0x1d, 0xdd, 0x66, 0x46, 0x75, 0xf3, 0x13, 0xaf, 0xf1, 0xa7, 0x4a, 0xa8, 0xbe, 0x7c, 0xa3, 0xb0, + 0x78, 0xc2, 0x03, 0x6a, 0x9f, 0x82, 0x46, 0x75, 0xad, 0x29, 0xa6, 0xb4, 0x20, 0x32, 0x91, 0x31, 0xf8, 0x20, 0x43, + 0x83, 0xb8, 0x5d, 0xb6, 0x5e, 0x90, 0xee, 0xc9, 0xbb, 0xdd, 0xaf, 0x92, 0x5e, 0xda, 0x27, 0x90, 0xfa, 0x16, 0x4d, + 0x60, 0xb6, 0x52, 0xd0, 0x6e, 0x61, 0xbd, 0xbd, 0x60, 0xee, 0x85, 0xb8, 0x72, 0xe1, 0xc0, 0x9a, 0x30, 0xd6, 0xbb, + 0x9a, 0xe7, 0x86, 0xf5, 0xaf, 0x7f, 0xb6, 0x57, 0x8d, 0x5c, 0x54, 0xa6, 0x75, 0x5e, 0x06, 0xc8, 0x4e, 0x5c, 0xe6, + 0xf6, 0x59, 0xca, 0x7b, 0x16, 0x11, 0x34, 0xe4, 0x99, 0x5b, 0xf1, 0x25, 0x6c, 0xfa, 0x1a, 0x36, 0xdf, 0xb5, 0x4f, + 0x6d, 0xb5, 0x62, 0x92, 0x54, 0xa3, 0x3c, 0x71, 0xdd, 0x05, 0x06, 0xed, 0x0f, 0x2e, 0xcd, 0x4e, 0xe7, 0xee, 0x67, + 0xda, 0x03, 0x8e, 0x59, 0x8b, 0xde, 0x36, 0xe0, 0xc8, 0x87, 0xf4, 0x90, 0xba, 0x3b, 0xb9, 0xcd, 0x2d, 0x80, 0xdb, + 0x42, 0x5f, 0x5a, 0x5a, 0xe6, 0x9b, 0x58, 0x6e, 0xae, 0xce, 0x8b, 0x34, 0xbd, 0x50, 0xd6, 0x6d, 0x2f, 0xc1, 0xd1, + 0x26, 0xcf, 0x65, 0x83, 0x6b, 0x54, 0x0a, 0x97, 0x81, 0xff, 0x17, 0x25, 0x45, 0xbf, 0x16, 0x03, 0xc1, 0xd8, 0x31, + 0xe9, 0x2b, 0xbd, 0x3a, 0xe2, 0x4a, 0x89, 0x0e, 0xfc, 0x11, 0x54, 0x27, 0x7b, 0x03, 0x4d, 0xea, 0xcc, 0xde, 0x25, + 0x25, 0x42, 0xbb, 0xa7, 0x69, 0x73, 0x29, 0xa1, 0xfe, 0x7a, 0xc1, 0x87, 0xb7, 0xfd, 0xe2, 0xf6, 0x6c, 0xef, 0x2b, + 0xf7, 0x9e, 0x77, 0x2b, 0x55, 0xb3, 0x3f, 0xcb, 0x89, 0x3d, 0x3b, 0xf6, 0xd3, 0x34, 0x1f, 0xf4, 0xf4, 0x93, 0xfb, + 0x0f, 0x2f, 0xcc, 0x79, 0xc2, 0x0e, 0xb4, 0x76, 0x7b, 0x5c, 0xf3, 0x55, 0x28, 0x15, 0x9c, 0x08, 0x1b, 0x5f, 0x16, + 0xbd, 0x35, 0xe4, 0x82, 0x93, 0x72, 0x12, 0xc5, 0xd4, 0x5e, 0x34, 0xc7, 0x5b, 0x70, 0x93, 0x9f, 0x76, 0x17, 0x81, + 0x14, 0x5a, 0xe5, 0xb9, 0xfa, 0x5f, 0xec, 0x18, 0x8b, 0x97, 0xb9, 0xeb, 0x30, 0xb7, 0x13, 0xaa, 0x88, 0x3f, 0xb7, + 0x44, 0x93, 0xff, 0x70, 0xfc, 0xaf, 0xa3, 0x3f, 0xb5, 0x24, 0x1f, 0x79, 0x3b, 0xa1, 0xe3, 0x89, 0xab, 0x64, 0xf7, + 0x1a, 0x65, 0x76, 0x16, 0x53, 0x4f, 0x55, 0xe7, 0x33, 0x49, 0x66, 0x5d, 0xe5, 0x13, 0xc2, 0xe1, 0xd1, 0xfc, 0x10, + 0xee, 0x96, 0xc5, 0x9a, 0xac, 0xcc, 0x15, 0x65, 0x57, 0x68, 0x9f, 0x53, 0x0f, 0xc4, 0xd6, 0x64, 0x7e, 0xa0, 0x73, + 0x2f, 0x92, 0x91, 0x49, 0xa5, 0x2c, 0x6b, 0x87, 0x48, 0xc3, 0xcb, 0x5d, 0x9e, 0xf2, 0x3e, 0x3f, 0x54, 0x54, 0xb6, + 0x43, 0xe6, 0xb9, 0xfb, 0x3a, 0x33, 0x40, 0xa3, 0x98, 0xa3, 0x2b, 0xe0, 0x96, 0x80, 0x79, 0x6a, 0x34, 0x7b, 0xd6, + 0x5c, 0x95, 0x4c, 0xda, 0xcb, 0x35, 0xf4, 0xb9, 0x67, 0x9a, 0xc9, 0x36, 0x76, 0x11, 0x32, 0x2d, 0x57, 0x65, 0x6b, + 0xe9, 0x33, 0x5f, 0x73, 0xe7, 0x99, 0x07, 0xfc, 0xf4, 0x55, 0x72, 0x89, 0xfa, 0x7a, 0xda, 0x9a, 0xb4, 0x3c, 0x5b, + 0x50, 0xa8, 0x71, 0x8a, 0xc2, 0x1b, 0x28, 0x26, 0x1a, 0xaa, 0xc2, 0x3c, 0x9e, 0xfc, 0x0c, 0x7b, 0x6a, 0xc9, 0xc1, + 0x74, 0xc6, 0x97, 0x9a, 0xee, 0xa7, 0xe6, 0xac, 0x3e, 0x23, 0x07, 0xad, 0xb1, 0x3a, 0xdb, 0x7e, 0xf1, 0xdc, 0x1f, + 0xbc, 0x3f, 0x0d, 0x90, 0xf8, 0x7a, 0x98, 0x7c, 0x8d, 0xad, 0xd4, 0xe4, 0xcf, 0xd7, 0xdf, 0xd7, 0xab, 0x40, 0xb2, + 0x39, 0xdf, 0xbb, 0xbe, 0x0b, 0x16, 0x4a, 0x7f, 0x18, 0x58, 0x31, 0xbb, 0x31, 0x7a, 0x94, 0x22, 0x44, 0xe1, 0x1e, + 0x4b, 0x11, 0x79, 0xab, 0x87, 0xc1, 0xdf, 0x12, 0x71, 0x32, 0x5c, 0xa2, 0x80, 0xc6, 0xe7, 0xd3, 0x4c, 0x2b, 0xae, + 0x88, 0x22, 0x81, 0xbd, 0x16, 0x35, 0x93, 0x6c, 0x13, 0x8c, 0xa0, 0x45, 0x2d, 0x07, 0x32, 0x9c, 0xc5, 0x82, 0x2f, + 0x18, 0x69, 0xce, 0xed, 0x9a, 0xc5, 0xc4, 0x85, 0x8c, 0xb7, 0x57, 0x11, 0x33, 0xda, 0xad, 0x07, 0x0c, 0xe7, 0x33, + 0x03, 0xcd, 0xc5, 0xb8, 0x22, 0x36, 0x7f, 0x84, 0x23, 0x4a, 0xee, 0xb5, 0x90, 0x7d, 0x3f, 0x23, 0xf5, 0x09, 0x43, + 0xc6, 0x24, 0x63, 0xbb, 0x61, 0xc6, 0xe4, 0x7d, 0x91, 0xa7, 0xab, 0xc1, 0xa2, 0xfb, 0x60, 0xb7, 0x16, 0xae, 0x2d, + 0x20, 0xeb, 0x70, 0x18, 0x7a, 0x5f, 0xde, 0x47, 0x81, 0xd2, 0x6c, 0x5f, 0x5f, 0x3d, 0xc0, 0xfe, 0x6e, 0x45, 0x26, + 0x06, 0x24, 0x69, 0x1b, 0x50, 0x78, 0xdc, 0x52, 0xdf, 0xd6, 0xa8, 0xf5, 0x2c, 0xab, 0xb9, 0x97, 0x25, 0xd5, 0x68, + 0xe3, 0x8b, 0x45, 0x7f, 0x31, 0x25, 0x12, 0xc9, 0x3c, 0x08, 0xd6, 0x48, 0xf8, 0x9b, 0xf7, 0x24, 0x75, 0xc5, 0x79, + 0xea, 0x7d, 0xc2, 0x45, 0x4c, 0xa4, 0x37, 0x50, 0xa4, 0x4c, 0x5b, 0x2f, 0xfe, 0xdd, 0x57, 0xe8, 0xf4, 0xe6, 0x63, + 0x13, 0x2b, 0x17, 0x03, 0x40, 0x98, 0x89, 0x16, 0xf1, 0x38, 0xf4, 0xb4, 0x87, 0x58, 0xa4, 0x27, 0x4b, 0xbd, 0xc4, + 0x65, 0x3a, 0x2e, 0x94, 0x2f, 0x57, 0x0b, 0x41, 0xda, 0x50, 0xa4, 0xbe, 0x0b, 0xf9, 0xc2, 0x07, 0x57, 0x82, 0x55, + 0xf2, 0x0d, 0x93, 0xc9, 0xf9, 0xb3, 0xbc, 0x6f, 0x7e, 0x0b, 0x2c, 0x7e, 0xd7, 0xe0, 0x25, 0xee, 0x7d, 0x1f, 0x7c, + 0x8d, 0x06, 0x5a, 0xfd, 0xcf, 0x56, 0x8c, 0x62, 0x88, 0x65, 0xb5, 0x08, 0x3e, 0xd5, 0x6e, 0x7a, 0x8a, 0x96, 0x7c, + 0xc9, 0x93, 0xbb, 0xf0, 0x92, 0xd4, 0xda, 0xc6, 0x61, 0xd6, 0xde, 0xa3, 0xdc, 0xd0, 0x7b, 0xad, 0x16, 0xa4, 0x43, + 0xcc, 0xae, 0xe0, 0x32, 0xe3, 0x05, 0x26, 0xeb, 0xcf, 0x52, 0x58, 0x2c, 0xf2, 0x8b, 0x2a, 0xd2, 0x9e, 0xb2, 0xcc, + 0x87, 0x6c, 0xa6, 0x75, 0x4d, 0xc9, 0xa2, 0x80, 0x4b, 0x94, 0x95, 0x42, 0x6c, 0xe4, 0xe2, 0xb3, 0x56, 0x80, 0x35, + 0xf0, 0x0a, 0x84, 0x62, 0x92, 0x9a, 0xbc, 0x71, 0xf5, 0xdf, 0x9a, 0xfc, 0xab, 0x3a, 0xe6, 0xdf, 0x54, 0x32, 0xff, + 0xfa, 0x7c, 0x4d, 0x1b, 0x7f, 0x6f, 0xf4, 0x25, 0xf1, 0xad, 0x94, 0x80, 0x12, 0x5b, 0x29, 0xbe, 0x23, 0x70, 0x1a, + 0x5d, 0x19, 0xec, 0xc6, 0x03, 0x0b, 0x2b, 0x21, 0xcf, 0x4d, 0x4e, 0x33, 0xad, 0x47, 0xb6, 0xa8, 0xfe, 0xce, 0x1e, + 0x38, 0x49, 0x7a, 0x2d, 0xfd, 0xbb, 0x19, 0x4f, 0x51, 0x20, 0x59, 0xe4, 0x12, 0x3b, 0x91, 0x87, 0xd8, 0x20, 0x40, + 0x90, 0x8b, 0x1c, 0xd0, 0x61, 0xaa, 0x26, 0x12, 0x91, 0xfa, 0xcf, 0x40, 0x0e, 0x2b, 0x60, 0xc0, 0x21, 0x90, 0x23, + 0x31, 0x30, 0x92, 0xe3, 0x13, 0x11, 0x17, 0x92, 0x77, 0x22, 0x2b, 0x42, 0xac, 0x06, 0x76, 0xbc, 0x41, 0x19, 0x6e, + 0x8b, 0xe4, 0x39, 0x0a, 0x14, 0x65, 0xe5, 0x8c, 0x65, 0xc4, 0xd6, 0xea, 0x59, 0xe7, 0xb4, 0x5e, 0xad, 0xa9, 0x73, + 0xc9, 0xd4, 0x69, 0x76, 0xe9, 0x64, 0xbe, 0x00, 0xf6, 0xb5, 0x28, 0x03, 0x7b, 0xd6, 0x01, 0xec, 0xd4, 0x8a, 0x13, + 0x53, 0x71, 0xd9, 0x73, 0xd6, 0x00, 0xd0, 0xd1, 0xb3, 0x06, 0x31, 0x33, 0xe8, 0x5c, 0xb3, 0x5c, 0x83, 0x04, 0x2e, + 0x5c, 0xa2, 0x5e, 0x1a, 0x4a, 0x5b, 0xcf, 0x2c, 0x0a, 0xbf, 0x45, 0xf9, 0xfc, 0x1c, 0x9a, 0x70, 0x11, 0x25, 0xec, + 0xb2, 0xb8, 0xfc, 0x29, 0x5e, 0xe3, 0xa3, 0x5a, 0xd3, 0xca, 0x4b, 0xbb, 0x35, 0xa6, 0xe7, 0x92, 0x82, 0x2d, 0xba, + 0xaa, 0xcf, 0x7b, 0xba, 0xa4, 0x8b, 0xb8, 0x8f, 0x9e, 0x12, 0x05, 0xca, 0xda, 0x15, 0x07, 0x0c, 0x2d, 0xd9, 0x89, + 0xc6, 0xa6, 0x68, 0xe9, 0xed, 0xdd, 0x76, 0xe9, 0xb6, 0x26, 0x43, 0x8e, 0x03, 0x85, 0x1d, 0x01, 0x51, 0x53, 0xdc, + 0x09, 0x8a, 0xba, 0xf2, 0xe1, 0x06, 0xa7, 0x39, 0x9d, 0x19, 0xbe, 0x15, 0x24, 0x9b, 0x08, 0x7c, 0xce, 0x8f, 0xde, + 0x4b, 0xa9, 0xab, 0xaf, 0x74, 0x3a, 0xf4, 0xb0, 0xd9, 0xc0, 0x41, 0x5e, 0xb0, 0x7d, 0x22, 0x75, 0x5a, 0x11, 0x52, + 0x11, 0x7f, 0x5f, 0xf0, 0x55, 0xba, 0xd7, 0x69, 0x43, 0x99, 0xaf, 0x59, 0xb1, 0x03, 0xd9, 0x88, 0xb5, 0x37, 0x52, + 0xde, 0xf6, 0x98, 0x9a, 0xf6, 0x9f, 0x18, 0xb8, 0x3f, 0xb7, 0xbc, 0x5e, 0x3c, 0x85, 0x29, 0x5e, 0x61, 0xa4, 0x6a, + 0xb1, 0x19, 0x8e, 0x39, 0x37, 0xee, 0xe5, 0x9a, 0x3d, 0xeb, 0xa9, 0x14, 0x50, 0x2c, 0x2b, 0x7c, 0xae, 0xca, 0xec, + 0x4d, 0xbe, 0x84, 0x5e, 0x58, 0xde, 0x7d, 0x9f, 0xf5, 0xf5, 0xaa, 0xf3, 0xad, 0x82, 0x57, 0xf5, 0x3b, 0xed, 0x17, + 0xcb, 0x29, 0x0d, 0xaf, 0x7a, 0x34, 0x71, 0x35, 0x98, 0x9d, 0x47, 0xa7, 0x80, 0x9a, 0x29, 0x00, 0x3e, 0x62, 0x53, + 0xd0, 0x15, 0xca, 0x23, 0x70, 0xde, 0x48, 0x98, 0xbd, 0x11, 0x10, 0xbd, 0x59, 0x33, 0x45, 0xf2, 0x45, 0xfb, 0x13, + 0x9b, 0x2e, 0x2e, 0x51, 0xb6, 0xf2, 0x21, 0xed, 0x0e, 0xf1, 0x42, 0x8e, 0x33, 0x2b, 0xa1, 0x6b, 0xc9, 0x6e, 0x9b, + 0xc9, 0xd6, 0x24, 0x4c, 0x00, 0xb0, 0x22, 0x67, 0x91, 0x2f, 0x5d, 0x9f, 0xd9, 0x86, 0xb2, 0x35, 0xc1, 0x08, 0x43, + 0xc3, 0x27, 0xea, 0xde, 0xf9, 0x53, 0xb3, 0xe2, 0xed, 0xc0, 0x88, 0x49, 0xf1, 0x9c, 0x31, 0xfc, 0x3c, 0xfc, 0xf2, + 0xad, 0x4e, 0x59, 0x63, 0x2f, 0xac, 0xcc, 0x0a, 0x22, 0x1e, 0x30, 0x13, 0x20, 0xf9, 0xdf, 0xe5, 0x32, 0xea, 0x8d, + 0xf2, 0x54, 0x62, 0x72, 0x6f, 0x17, 0x18, 0x2a, 0x40, 0x9c, 0x53, 0x4d, 0xa7, 0x14, 0x6f, 0x56, 0x07, 0x61, 0x76, + 0x3e, 0x28, 0x39, 0x62, 0x83, 0x25, 0x0c, 0xf5, 0x61, 0xd7, 0x62, 0x73, 0x89, 0x6b, 0xd9, 0x51, 0x27, 0xb1, 0x16, + 0xca, 0x14, 0x7f, 0xb8, 0xac, 0x30, 0x22, 0xc4, 0x45, 0x4d, 0x27, 0xe2, 0xa3, 0x29, 0xda, 0xd1, 0x6a, 0x02, 0xee, + 0x7a, 0x3a, 0xe5, 0xe3, 0xba, 0xbe, 0xb8, 0x74, 0x0d, 0x32, 0x71, 0x51, 0x60, 0x29, 0x2f, 0x93, 0x5f, 0x19, 0x3f, + 0x02, 0x5b, 0x78, 0xa0, 0x13, 0x1e, 0x27, 0x59, 0x9d, 0x20, 0xc6, 0x40, 0x34, 0x8b, 0xf0, 0x2a, 0x7a, 0x01, 0x92, + 0x9a, 0xe9, 0x32, 0x38, 0x6d, 0x5b, 0xae, 0x18, 0x49, 0xfb, 0xba, 0x12, 0x5d, 0x4b, 0xbe, 0x54, 0x84, 0x7c, 0xd9, + 0x0e, 0x67, 0x77, 0x1e, 0x9d, 0x6e, 0x67, 0x56, 0xc4, 0x8d, 0x4f, 0x3a, 0x09, 0x2e, 0x83, 0xbe, 0x21, 0xd9, 0xa1, + 0x3c, 0xa0, 0xad, 0x5f, 0xe6, 0x64, 0x4c, 0xbe, 0xe2, 0x6c, 0x43, 0x8a, 0x4a, 0x9e, 0x29, 0xdd, 0xce, 0x47, 0x57, + 0x71, 0xaa, 0x37, 0x58, 0x0f, 0x42, 0xe5, 0x00, 0x43, 0x6a, 0x12, 0x7e, 0xc4, 0xad, 0xdc, 0x58, 0xfb, 0xae, 0x4e, + 0x2a, 0xbc, 0x82, 0x33, 0x1d, 0xca, 0xb6, 0x95, 0xb9, 0xcb, 0x6c, 0x94, 0x64, 0xcb, 0x92, 0xe0, 0xbf, 0x5b, 0x45, + 0xb1, 0xe6, 0xc1, 0x79, 0x18, 0x95, 0xef, 0x8b, 0x5c, 0x3d, 0xac, 0xa7, 0xec, 0xed, 0x24, 0x94, 0xf0, 0x89, 0xa5, + 0xe3, 0xf4, 0xdb, 0x01, 0xe3, 0x94, 0x9d, 0x48, 0x5a, 0x20, 0xa7, 0xff, 0xc2, 0xb7, 0x9d, 0x06, 0x21, 0xc4, 0x3b, + 0x65, 0xbd, 0x5a, 0x00, 0x38, 0x97, 0x32, 0x3e, 0xab, 0xff, 0x02, 0x54, 0xb2, 0xeb, 0x8b, 0x71, 0x3f, 0xe0, 0xd1, + 0xa6, 0x95, 0xdf, 0x8e, 0x24, 0xcc, 0xee, 0xba, 0x7c, 0x03, 0x3d, 0x8e, 0x65, 0x07, 0x2b, 0xec, 0xab, 0x04, 0x79, + 0xe6, 0xb9, 0x48, 0x81, 0x65, 0x13, 0xc5, 0xfc, 0xa6, 0xa1, 0x4f, 0xc0, 0xc1, 0x4c, 0x77, 0x06, 0x8d, 0xd9, 0x55, + 0xad, 0xbe, 0xc6, 0xf1, 0xa2, 0x2c, 0x09, 0x5e, 0xa4, 0x31, 0x0a, 0xab, 0xb9, 0x9c, 0x87, 0xaa, 0x42, 0xe5, 0xcc, + 0x75, 0x33, 0xd6, 0xd5, 0x6d, 0xb6, 0xbb, 0x47, 0x9b, 0x13, 0xa0, 0x4a, 0x6f, 0xcc, 0x58, 0x82, 0x8a, 0xe8, 0xa0, + 0x9f, 0xb1, 0xbb, 0xca, 0xa0, 0xe3, 0x95, 0x35, 0x9f, 0x88, 0x01, 0xb7, 0x36, 0xa3, 0x22, 0x4a, 0x28, 0x1a, 0xeb, + 0xac, 0x42, 0xb5, 0xd7, 0x83, 0x6d, 0xab, 0x36, 0x10, 0x6d, 0x32, 0xa9, 0x40, 0x52, 0x11, 0xfe, 0xa2, 0xfc, 0xda, + 0xd2, 0x5e, 0xcf, 0x74, 0x46, 0x3a, 0xa8, 0x4a, 0x73, 0xce, 0x9c, 0x33, 0x3b, 0x60, 0x31, 0x5e, 0x1f, 0x6f, 0x84, + 0xa7, 0x80, 0x6c, 0x11, 0xde, 0x1c, 0xc0, 0xed, 0x6d, 0x2b, 0x0a, 0x07, 0xbb, 0xe9, 0x21, 0xaf, 0xd2, 0x36, 0x8e, + 0x80, 0x01, 0x79, 0x89, 0x93, 0xb9, 0x05, 0x12, 0x15, 0x06, 0x7e, 0x85, 0x60, 0x83, 0x25, 0x3b, 0x29, 0x2d, 0x2e, + 0x8f, 0xed, 0x62, 0x87, 0x4f, 0xcb, 0x7a, 0xb9, 0xf6, 0x06, 0xfd, 0xb5, 0xc6, 0x39, 0xf8, 0xd8, 0x21, 0x74, 0xf9, + 0xc7, 0x6c, 0x95, 0x26, 0xe9, 0xdf, 0x8a, 0x31, 0x2d, 0x2f, 0x92, 0x9c, 0x66, 0xdc, 0xe9, 0x5b, 0xe3, 0xc2, 0x47, + 0xef, 0xb9, 0x64, 0xf1, 0xbd, 0xdc, 0x1e, 0x89, 0x7e, 0x25, 0x18, 0xfa, 0xcb, 0xfa, 0x7a, 0x32, 0x88, 0xb6, 0x9d, + 0xa6, 0x0b, 0xcd, 0x2b, 0xb8, 0x94, 0xa2, 0xe2, 0x56, 0xc3, 0x0f, 0x05, 0x14, 0x49, 0xf9, 0xa8, 0x7d, 0x2c, 0x91, + 0xb5, 0x58, 0x39, 0x93, 0xed, 0x3f, 0xcb, 0x71, 0x86, 0x21, 0xef, 0xac, 0x55, 0x65, 0x55, 0xf9, 0x44, 0x17, 0xb6, + 0x45, 0xaf, 0xd4, 0x0b, 0xb9, 0xec, 0x18, 0x76, 0xbe, 0xb5, 0x37, 0x40, 0x89, 0xff, 0xe5, 0x96, 0xb7, 0xe1, 0x4c, + 0xb0, 0x0b, 0x59, 0x1d, 0x80, 0x0f, 0x8a, 0x52, 0xb2, 0xcd, 0x0b, 0x81, 0x48, 0xd7, 0x5d, 0x30, 0x8f, 0x3a, 0x62, + 0x51, 0xf0, 0x4b, 0xf7, 0x2a, 0xbc, 0xea, 0x27, 0x67, 0x51, 0x19, 0xa0, 0x59, 0x9e, 0xc7, 0x23, 0xd7, 0xc4, 0xc2, + 0xa2, 0xe4, 0xa5, 0x9a, 0xaf, 0xc6, 0x27, 0x36, 0x85, 0xad, 0x16, 0x14, 0xa7, 0xc9, 0x26, 0xe9, 0xfe, 0x40, 0x61, + 0x14, 0x16, 0xf8, 0x8f, 0x6b, 0x9f, 0x98, 0x67, 0x90, 0x68, 0x2e, 0x00, 0xa5, 0xc4, 0xfb, 0x42, 0xbd, 0x1e, 0x55, + 0x59, 0x72, 0xa0, 0xb0, 0xe3, 0x1b, 0x59, 0xbd, 0xf2, 0x3b, 0x95, 0x1a, 0x15, 0xf4, 0xfa, 0xa7, 0xb2, 0xcb, 0x02, + 0xa0, 0xed, 0xa0, 0x5a, 0x4d, 0x2d, 0xeb, 0x29, 0x17, 0xdd, 0xe1, 0x0e, 0x5e, 0xf9, 0x4e, 0xeb, 0x39, 0x9a, 0x0b, + 0x4b, 0x88, 0xb3, 0xef, 0xb1, 0x2c, 0x59, 0xce, 0x7e, 0xd6, 0xbc, 0xd0, 0x8d, 0x32, 0x7d, 0xb9, 0xd7, 0xf3, 0x99, + 0x2c, 0x5c, 0x95, 0x00, 0x33, 0xf2, 0xea, 0x72, 0x00, 0xe0, 0x13, 0x53, 0xba, 0xc2, 0x68, 0x1d, 0x47, 0x59, 0xe6, + 0x98, 0xc6, 0x3e, 0xf7, 0x90, 0xa6, 0x6f, 0x4e, 0xdc, 0x22, 0x97, 0xda, 0x6b, 0xb3, 0x0a, 0xc7, 0xc9, 0xc4, 0x3a, + 0xbe, 0xc8, 0x74, 0xa6, 0x07, 0x49, 0x97, 0x5e, 0xce, 0x80, 0x4c, 0xad, 0xee, 0xc0, 0x5c, 0x35, 0x09, 0xa0, 0xa7, + 0xef, 0x8a, 0x2c, 0x8f, 0xc9, 0xfe, 0xbc, 0x37, 0xbb, 0xf8, 0x8c, 0x74, 0xa3, 0x53, 0xf4, 0xd9, 0x31, 0x2d, 0xd7, + 0xac, 0x48, 0x00, 0x28, 0x17, 0x84, 0xbd, 0x71, 0x4c, 0x62, 0x0b, 0x5a, 0xb6, 0xeb, 0x05, 0x08, 0x1d, 0x01, 0x48, + 0xee, 0x8b, 0x02, 0xdf, 0xcf, 0xce, 0x35, 0x2f, 0x86, 0x2c, 0x7c, 0x9e, 0xa1, 0x5f, 0x0f, 0xb8, 0x2e, 0x13, 0x82, + 0x89, 0x7c, 0x86, 0x86, 0xbf, 0xca, 0xbc, 0x89, 0xb3, 0x11, 0xd1, 0xb5, 0xbf, 0x4f, 0xe9, 0xe3, 0x0a, 0x8e, 0x1f, + 0x2a, 0xe0, 0xf7, 0x03, 0xb3, 0x37, 0xd4, 0x3f, 0x7a, 0x31, 0xa8, 0x86, 0x47, 0x96, 0x9f, 0x2a, 0x30, 0x9a, 0x39, + 0xf0, 0x00, 0x11, 0x44, 0x92, 0xd9, 0x57, 0x71, 0x5b, 0xda, 0x1d, 0x46, 0x01, 0x01, 0x8c, 0x59, 0x93, 0x5d, 0x08, + 0x13, 0x80, 0x75, 0xee, 0x9b, 0xd1, 0x45, 0x0f, 0x7a, 0x6c, 0xf3, 0x51, 0xb9, 0x16, 0xe5, 0x18, 0x8c, 0x69, 0xcc, + 0x17, 0x36, 0xec, 0x09, 0xb6, 0xd1, 0x08, 0x47, 0xaf, 0x60, 0x08, 0x97, 0x34, 0xee, 0x55, 0x3a, 0x17, 0xbe, 0xf7, + 0x2a, 0xca, 0x82, 0x18, 0xbb, 0x6f, 0xc6, 0xa9, 0x01, 0xb2, 0x64, 0xff, 0xb4, 0x60, 0xc9, 0xa9, 0xb3, 0xaf, 0xe9, + 0xe4, 0xd9, 0xc7, 0xdc, 0xf0, 0x4e, 0x9e, 0x83, 0x43, 0xd3, 0x52, 0x4f, 0xeb, 0xfc, 0x0d, 0x5a, 0x68, 0x05, 0xf3, + 0x82, 0x76, 0x76, 0x06, 0x58, 0x5a, 0xa1, 0xb6, 0xa6, 0xb6, 0xe4, 0x0d, 0xfb, 0xa1, 0x95, 0x95, 0x62, 0x30, 0x0d, + 0x20, 0x89, 0x1d, 0x88, 0x46, 0xa1, 0xfd, 0xd0, 0xf7, 0xb7, 0xb9, 0xef, 0x65, 0x89, 0xdf, 0xba, 0xbe, 0x8e, 0x95, + 0x56, 0x8f, 0x7f, 0x3e, 0x0f, 0x97, 0x24, 0x62, 0xbf, 0x56, 0xc1, 0xca, 0x64, 0x63, 0x05, 0x2e, 0xaa, 0xcf, 0x38, + 0x96, 0x7c, 0x28, 0x38, 0xe5, 0x66, 0x85, 0x94, 0x99, 0xec, 0xf3, 0xb0, 0x80, 0xc6, 0xda, 0x8c, 0x6a, 0x50, 0x2b, + 0xe6, 0x60, 0x4e, 0x8f, 0x0a, 0x84, 0xc7, 0x14, 0x40, 0x95, 0x2f, 0x4e, 0x7d, 0xf9, 0x75, 0xce, 0x91, 0x90, 0x4b, + 0xd3, 0xd4, 0xfd, 0xef, 0x52, 0x91, 0xf3, 0x0e, 0x82, 0x10, 0xc3, 0x23, 0xe8, 0x1b, 0x94, 0x5f, 0xfc, 0x89, 0xbf, + 0xf8, 0xba, 0xf8, 0xb9, 0x60, 0xe6, 0x9b, 0x66, 0x39, 0xb3, 0x78, 0x8b, 0x59, 0x6f, 0x1d, 0xb2, 0x15, 0x61, 0x91, + 0xd2, 0x4c, 0x43, 0xce, 0x04, 0xcd, 0xb3, 0xa0, 0x80, 0xcd, 0x7c, 0xae, 0xf5, 0x26, 0x20, 0x3d, 0x90, 0x04, 0xf7, + 0xaf, 0x12, 0x5d, 0x0e, 0x54, 0x4d, 0x47, 0x51, 0x0a, 0x1e, 0x80, 0x9b, 0x4a, 0xa8, 0x01, 0xea, 0xa4, 0xe1, 0x29, + 0xb4, 0x62, 0x2c, 0xc1, 0xb3, 0x2c, 0x62, 0x9d, 0x06, 0x30, 0x1a, 0x49, 0x3c, 0xac, 0x51, 0xb8, 0x3a, 0xcf, 0x26, + 0x63, 0x56, 0xc7, 0xbc, 0xad, 0x2e, 0xb2, 0x3b, 0xd2, 0x04, 0x9f, 0xb9, 0x4e, 0xc5, 0xde, 0xee, 0x38, 0x60, 0x4a, + 0x4d, 0x03, 0x07, 0x99, 0x4a, 0xf3, 0x40, 0xa1, 0x69, 0x5c, 0x0b, 0x30, 0xd0, 0xc9, 0x59, 0x2d, 0x4a, 0x88, 0xad, + 0xb8, 0x01, 0x10, 0x47, 0x3a, 0xfa, 0x20, 0x85, 0x0d, 0x3f, 0x30, 0x96, 0xfc, 0x11, 0xf0, 0x98, 0x3f, 0x78, 0x08, + 0x08, 0x51, 0xda, 0x08, 0x79, 0x62, 0x0d, 0x5a, 0x59, 0x2c, 0x0c, 0x7e, 0x2b, 0xda, 0xcb, 0x9e, 0xe2, 0xf3, 0x8d, + 0xba, 0x1f, 0x08, 0x51, 0xb7, 0xc1, 0x9a, 0x45, 0x46, 0x73, 0x37, 0xf8, 0xaf, 0xf9, 0x3d, 0x49, 0xa4, 0x50, 0x2c, + 0x15, 0xb9, 0x8f, 0x28, 0x6f, 0x31, 0x6e, 0x21, 0x6f, 0xed, 0xe0, 0xe3, 0x56, 0x18, 0xa8, 0x23, 0xad, 0x16, 0x92, + 0xf2, 0x16, 0x53, 0xcd, 0xb8, 0xa3, 0x60, 0x35, 0x51, 0x6a, 0xf8, 0x1c, 0x49, 0xba, 0x7a, 0x8e, 0xcd, 0x4c, 0xfc, + 0x63, 0x66, 0x9a, 0xa7, 0x26, 0x1f, 0x15, 0x75, 0x93, 0xd9, 0xb8, 0xb1, 0xe0, 0xe8, 0x09, 0xcf, 0x84, 0xbc, 0x4b, + 0x1d, 0xed, 0x54, 0x6f, 0x21, 0xe5, 0x21, 0xc3, 0x14, 0xc4, 0x7a, 0x40, 0xef, 0x68, 0x6a, 0x74, 0xeb, 0x6e, 0x4c, + 0x0f, 0x12, 0x88, 0xd5, 0xa9, 0x1d, 0xa1, 0x2d, 0x6e, 0x0f, 0x31, 0x5c, 0x56, 0x5d, 0x0a, 0x14, 0xa9, 0x55, 0x9e, + 0xf2, 0x59, 0x82, 0x12, 0xb0, 0x49, 0x51, 0x9f, 0x73, 0x1c, 0xd6, 0x45, 0x41, 0xed, 0x33, 0x85, 0x48, 0x16, 0xca, + 0x34, 0x5f, 0x06, 0x5f, 0x44, 0x33, 0x68, 0x00, 0xc9, 0x80, 0xaf, 0xf6, 0x9b, 0x6b, 0xe8, 0x46, 0x20, 0x6f, 0xb3, + 0x26, 0xca, 0xe6, 0xc3, 0x39, 0xc4, 0xb6, 0xb6, 0xf7, 0x1b, 0xb4, 0x9e, 0x85, 0x7a, 0x97, 0xf2, 0xac, 0xb0, 0xad, + 0x5c, 0x05, 0x5a, 0x72, 0x72, 0xb2, 0x91, 0xc7, 0x40, 0x1d, 0x61, 0xdb, 0x63, 0x64, 0x4e, 0xe0, 0x5f, 0x6a, 0xb3, + 0x16, 0x84, 0x67, 0x36, 0xb2, 0xe0, 0x0f, 0x74, 0x31, 0xd8, 0x30, 0xde, 0xc4, 0x3f, 0xa3, 0xec, 0xb9, 0x7b, 0xed, + 0x25, 0xab, 0xa0, 0x1e, 0x8e, 0xda, 0x09, 0x9d, 0xb6, 0xc9, 0xb7, 0x2d, 0x08, 0x84, 0xe4, 0xe3, 0xa5, 0x88, 0xee, + 0x84, 0x59, 0xd2, 0xaa, 0x96, 0xd8, 0xf3, 0xe6, 0xa7, 0xf1, 0x9e, 0xd7, 0xfb, 0x82, 0x85, 0xa8, 0xb9, 0x37, 0x1b, + 0xd6, 0xf5, 0xc6, 0xf2, 0xee, 0xbd, 0x32, 0xb3, 0xe8, 0x6c, 0xcc, 0x65, 0x01, 0x93, 0xea, 0x9e, 0x40, 0x2f, 0x96, + 0x27, 0xfd, 0xb1, 0xcd, 0x54, 0xe3, 0x58, 0x24, 0xf3, 0x28, 0x4e, 0x09, 0x6f, 0x0c, 0x68, 0xf4, 0x6b, 0x8a, 0x24, + 0x91, 0x79, 0x06, 0x8b, 0xcc, 0x58, 0x79, 0x1b, 0x7c, 0x43, 0xcc, 0x4c, 0x44, 0x34, 0xc8, 0x4e, 0x60, 0x8e, 0xc6, + 0x02, 0xe1, 0x0f, 0x71, 0x86, 0x26, 0xbe, 0xa3, 0x9b, 0x97, 0x9c, 0x4c, 0x5d, 0x80, 0x0b, 0x70, 0xbb, 0x7a, 0x06, + 0xfd, 0x70, 0xb3, 0x55, 0x84, 0x94, 0x92, 0x0a, 0x5c, 0x74, 0xac, 0x35, 0xf9, 0x3b, 0xa5, 0x98, 0x68, 0xdd, 0x88, + 0xea, 0x4b, 0x07, 0x60, 0xdf, 0x1d, 0xd4, 0xe7, 0x96, 0x34, 0x56, 0x92, 0xcf, 0x83, 0x2e, 0x35, 0x7d, 0x10, 0x2b, + 0xe4, 0x19, 0x9f, 0x1c, 0x81, 0x70, 0x87, 0xdf, 0x5d, 0xda, 0x4c, 0xd0, 0xdb, 0x44, 0x1b, 0x97, 0x0c, 0xf0, 0x8b, + 0x1c, 0x23, 0xec, 0x62, 0x86, 0x9c, 0xad, 0x19, 0xbf, 0x4c, 0x8e, 0x8c, 0x17, 0x84, 0x3f, 0x15, 0x9e, 0x97, 0x76, + 0xd3, 0x04, 0xc4, 0x3f, 0x10, 0x5d, 0x34, 0x18, 0x9d, 0x04, 0xf3, 0xcc, 0xcb, 0x65, 0x71, 0x51, 0x55, 0xd0, 0x60, + 0x9f, 0xbb, 0x5e, 0xc9, 0x96, 0x6f, 0xcf, 0xff, 0x71, 0x6e, 0x75, 0x53, 0xe2, 0xc8, 0x43, 0x57, 0xe2, 0xaa, 0x97, + 0x7b, 0x7e, 0xd2, 0xbd, 0xd5, 0x4e, 0xb8, 0xdf, 0xc8, 0x55, 0x5f, 0x21, 0x84, 0x7f, 0xf2, 0x07, 0x0d, 0xc1, 0xca, + 0x23, 0x58, 0xb3, 0x94, 0x72, 0xc7, 0xd5, 0x72, 0xdb, 0x0f, 0xf6, 0x3e, 0x60, 0xa5, 0x73, 0x17, 0x16, 0xe3, 0x09, + 0x12, 0x94, 0x17, 0xca, 0xd7, 0x62, 0x8c, 0xb3, 0xdd, 0xac, 0xc6, 0xa1, 0x15, 0xc4, 0x63, 0xcf, 0x72, 0xb8, 0xa8, + 0x43, 0x84, 0x2e, 0x1d, 0x5c, 0x5e, 0xc9, 0xe2, 0x81, 0xa3, 0x4c, 0xd3, 0x18, 0xcf, 0x56, 0x20, 0x39, 0x79, 0xfa, + 0xf0, 0x40, 0x8f, 0x90, 0x80, 0xd1, 0xe7, 0xce, 0x5b, 0x4a, 0x86, 0x6d, 0xd5, 0xb7, 0x09, 0xa0, 0xcd, 0x17, 0x34, + 0x87, 0x68, 0xc5, 0xc8, 0x34, 0x78, 0xed, 0x5d, 0x6c, 0xb5, 0x92, 0x39, 0x09, 0xad, 0x46, 0xac, 0x41, 0x52, 0xbf, + 0xd3, 0xa4, 0x0f, 0xe6, 0x67, 0xb9, 0x85, 0xda, 0xc9, 0x58, 0xed, 0x84, 0x33, 0x3b, 0x9d, 0xf3, 0x2d, 0xfb, 0xf5, + 0x8c, 0xe9, 0x3c, 0x47, 0x36, 0x5f, 0x7a, 0xcd, 0xd7, 0x9f, 0x87, 0xfc, 0xd3, 0x53, 0x79, 0x9b, 0xb0, 0x80, 0xfd, + 0x36, 0x35, 0xa8, 0x27, 0xd6, 0xed, 0x92, 0x6a, 0x29, 0x9a, 0x63, 0x71, 0x44, 0x11, 0xb1, 0x5d, 0xc0, 0x11, 0x7a, + 0x1f, 0xf1, 0x6b, 0x56, 0x67, 0xa2, 0xe4, 0x3c, 0x83, 0x77, 0x0a, 0x63, 0x25, 0x92, 0xbc, 0x22, 0x8d, 0x4c, 0xa4, + 0x75, 0x43, 0xde, 0x26, 0x79, 0xa9, 0xc9, 0xe9, 0xe8, 0x74, 0xec, 0x3d, 0xfe, 0x67, 0x40, 0x25, 0x21, 0x50, 0x81, + 0xd2, 0x3e, 0xdf, 0x1d, 0x31, 0x44, 0x93, 0x29, 0x4a, 0x91, 0xac, 0xa5, 0xe8, 0x2f, 0x31, 0x2b, 0x4d, 0x59, 0xdd, + 0x9d, 0x80, 0xeb, 0x36, 0x4e, 0x12, 0x77, 0x1b, 0x33, 0x99, 0x87, 0x13, 0xd8, 0x9f, 0xcb, 0x75, 0x7e, 0x88, 0xc1, + 0x96, 0x87, 0xa7, 0x25, 0x82, 0x5f, 0x47, 0x15, 0xbc, 0x1e, 0x44, 0x10, 0x1c, 0x67, 0x23, 0x22, 0xf6, 0x9b, 0x21, + 0x7b, 0x27, 0x2f, 0x00, 0x28, 0xce, 0xef, 0xe3, 0xe6, 0x79, 0x9d, 0x9f, 0x00, 0x45, 0x38, 0x2a, 0xfc, 0xb0, 0x33, + 0x82, 0x41, 0x15, 0xde, 0xc9, 0x22, 0x6b, 0xcc, 0x8e, 0x97, 0x2b, 0x9a, 0x73, 0x32, 0xb3, 0x55, 0x4f, 0x48, 0x22, + 0x48, 0x33, 0xcc, 0x7a, 0x10, 0x8c, 0x18, 0xbf, 0xac, 0x27, 0x83, 0xd1, 0x59, 0x92, 0x2c, 0x6c, 0x1a, 0x4e, 0xa4, + 0x6d, 0x84, 0x18, 0xc9, 0x76, 0x29, 0xc5, 0xa4, 0x6b, 0xcf, 0x36, 0x67, 0xcd, 0x17, 0x42, 0x51, 0xc0, 0x6e, 0x29, + 0x81, 0x18, 0xe7, 0x50, 0x42, 0xc3, 0x68, 0xca, 0x9f, 0x8b, 0x13, 0xc4, 0x3a, 0xf2, 0xd2, 0x54, 0x68, 0xb3, 0xc1, + 0x9d, 0x0f, 0x48, 0x11, 0xc6, 0xfd, 0x19, 0x38, 0x66, 0xb2, 0x52, 0x5c, 0x32, 0x87, 0xb7, 0x3b, 0x52, 0xac, 0x63, + 0xf6, 0x82, 0x60, 0xf0, 0x1c, 0x5b, 0x98, 0x58, 0xa4, 0xa2, 0x8f, 0x24, 0x15, 0x5c, 0x96, 0xea, 0xfe, 0x3d, 0x6c, + 0xbb, 0x6d, 0x0a, 0x62, 0x9b, 0x93, 0x30, 0x53, 0x8d, 0xc7, 0xd5, 0xa3, 0x0d, 0xb8, 0xfe, 0x1c, 0xa0, 0x91, 0x26, + 0xab, 0x74, 0x65, 0x7d, 0x73, 0xbf, 0xa9, 0xc7, 0x8a, 0x79, 0x7c, 0xf0, 0x89, 0x80, 0x35, 0xee, 0x80, 0x29, 0x6b, + 0x30, 0x24, 0x1c, 0x8a, 0xb0, 0xd9, 0x01, 0x98, 0x62, 0xfd, 0x28, 0x22, 0x71, 0xef, 0xa2, 0x4d, 0x02, 0x32, 0x2d, + 0xd7, 0x39, 0x37, 0x4b, 0xfd, 0xce, 0x24, 0xfc, 0x24, 0x86, 0x30, 0xc6, 0x21, 0x8e, 0x10, 0x8d, 0x25, 0xea, 0xf5, + 0x6b, 0x3c, 0xf6, 0xd2, 0x92, 0xff, 0xc9, 0xc6, 0xf9, 0x9d, 0x12, 0x9a, 0x63, 0xcb, 0xa6, 0xcd, 0x16, 0x74, 0xfb, + 0x5a, 0xd2, 0x52, 0xec, 0x2a, 0x8a, 0x4f, 0x1e, 0xf9, 0x41, 0x65, 0x78, 0x7f, 0x77, 0x49, 0xac, 0x07, 0xad, 0x24, + 0xb8, 0x35, 0x23, 0xbc, 0xbf, 0x4b, 0x27, 0xfc, 0x70, 0x10, 0xf1, 0x6e, 0x91, 0xd1, 0xb6, 0x98, 0x9a, 0x6d, 0x60, + 0x71, 0xe9, 0x43, 0x05, 0xb0, 0x8b, 0x0c, 0xeb, 0xf4, 0x1a, 0x77, 0xbb, 0xd2, 0xec, 0x1e, 0x21, 0x3c, 0x49, 0x95, + 0x9d, 0x6b, 0xb3, 0x98, 0xcb, 0x02, 0x3a, 0x49, 0xa5, 0x22, 0x9a, 0x49, 0xe3, 0xd0, 0x52, 0xe1, 0xdf, 0x05, 0x49, + 0x6a, 0x63, 0xdc, 0xfd, 0xd9, 0x19, 0x46, 0x54, 0x41, 0x4d, 0x49, 0x49, 0x1d, 0xc6, 0x64, 0xc7, 0x20, 0xfe, 0xb7, + 0xc7, 0x1e, 0x52, 0xaf, 0x59, 0x68, 0x99, 0x51, 0x1e, 0x7f, 0x37, 0x4c, 0x3b, 0x59, 0xe3, 0x91, 0xd7, 0xf5, 0x4e, + 0xd1, 0xd6, 0xb7, 0x70, 0xb6, 0xa1, 0x1b, 0xde, 0x74, 0xf5, 0x0c, 0xe3, 0xf1, 0x15, 0xfc, 0xbc, 0x81, 0x49, 0x4f, + 0xa4, 0x26, 0xee, 0x7c, 0x53, 0x72, 0x62, 0xab, 0x9e, 0x2a, 0xb0, 0x14, 0x4f, 0xc4, 0x6a, 0x57, 0x51, 0x32, 0xb5, + 0x51, 0x83, 0xe1, 0x8c, 0x35, 0xf4, 0xc9, 0xa9, 0xe1, 0x9c, 0x67, 0x80, 0x87, 0x97, 0xae, 0x4f, 0x21, 0x53, 0x3f, + 0x8d, 0x71, 0x29, 0x20, 0x4e, 0xc4, 0xb3, 0x0b, 0x2f, 0x31, 0xbe, 0x71, 0x7d, 0x0a, 0xf6, 0xd6, 0xa4, 0xab, 0x78, + 0x6a, 0x58, 0x85, 0x53, 0x9b, 0xab, 0xe1, 0xd4, 0xd6, 0x59, 0x0f, 0xfb, 0xb7, 0x14, 0xb9, 0x12, 0x50, 0x94, 0x1c, + 0x65, 0x2a, 0xae, 0x5c, 0x1b, 0xc6, 0xed, 0xb5, 0xf3, 0xc7, 0x54, 0x5d, 0x62, 0x28, 0x29, 0x51, 0xda, 0x3c, 0xb1, + 0x2d, 0x30, 0x92, 0x75, 0x13, 0xdc, 0xd2, 0x6b, 0xb9, 0xb4, 0xfb, 0xe2, 0x0e, 0x49, 0xa1, 0x96, 0xb4, 0xf6, 0x3c, + 0x89, 0x3e, 0xd6, 0xdc, 0xd2, 0xc6, 0x43, 0x62, 0xef, 0xf4, 0x58, 0x45, 0xfa, 0xf9, 0x52, 0x1d, 0x6a, 0x77, 0x20, + 0xe0, 0x32, 0x6d, 0x20, 0xbf, 0x6c, 0x0b, 0x44, 0xf6, 0x7c, 0x45, 0xb2, 0xf1, 0x87, 0x0a, 0x38, 0x1d, 0x38, 0xc5, + 0x04, 0x60, 0x65, 0x2a, 0x94, 0x4e, 0x12, 0x58, 0x16, 0x1f, 0xa1, 0x6a, 0x31, 0x37, 0x2d, 0xae, 0x0f, 0x8c, 0x78, + 0x7e, 0x9b, 0x10, 0x0f, 0x00, 0x71, 0x3d, 0x43, 0xd4, 0x15, 0x88, 0xfa, 0xcc, 0x8c, 0x81, 0x84, 0x1e, 0xb2, 0xef, + 0x0f, 0x98, 0xb9, 0x63, 0x3a, 0xf1, 0x52, 0xa5, 0xdc, 0x46, 0xcb, 0xc7, 0x72, 0x58, 0xa5, 0x99, 0x26, 0xc5, 0x35, + 0x09, 0x55, 0xf2, 0x8a, 0x06, 0x56, 0xb9, 0x6c, 0xf7, 0x5f, 0x7d, 0xe0, 0x35, 0x6c, 0x73, 0x3e, 0x5e, 0x3c, 0xc6, + 0xb7, 0x02, 0x45, 0xa3, 0x8a, 0xd9, 0x2a, 0x37, 0x18, 0x13, 0xd3, 0x8b, 0x03, 0xb1, 0xd4, 0xac, 0xe9, 0xce, 0x3c, + 0x87, 0xf6, 0x4d, 0xf1, 0xa0, 0x4c, 0xa5, 0x0a, 0x54, 0x70, 0x8d, 0x30, 0x56, 0x59, 0xb3, 0xa8, 0x4b, 0xc4, 0xfb, + 0xed, 0xd0, 0xbc, 0x94, 0x25, 0xa6, 0x88, 0x1d, 0x54, 0xd4, 0x19, 0x3e, 0xe7, 0xe1, 0xd6, 0xde, 0x7d, 0x76, 0x64, + 0x43, 0xc5, 0xc4, 0x94, 0x84, 0xf4, 0x64, 0x63, 0x4a, 0x92, 0x45, 0xe3, 0x99, 0xba, 0xa9, 0xbe, 0x86, 0xf1, 0x08, + 0x07, 0x6b, 0x3f, 0x66, 0x37, 0x40, 0x15, 0xd2, 0xe6, 0xa6, 0xda, 0xcc, 0xc1, 0x67, 0xb5, 0xe5, 0xdf, 0x96, 0x9e, + 0xde, 0x96, 0x2e, 0x7c, 0xd1, 0x2d, 0xe9, 0xe0, 0xd7, 0xf8, 0xd7, 0xa6, 0x09, 0x3f, 0xdd, 0x0c, 0x90, 0x9e, 0xef, + 0x72, 0x81, 0x28, 0x71, 0xad, 0x19, 0x03, 0xc5, 0x1b, 0xa4, 0x89, 0xa6, 0xc0, 0x1c, 0x8c, 0x76, 0xe0, 0x1f, 0x04, + 0x35, 0xa0, 0x12, 0x7a, 0x73, 0x45, 0x59, 0x5c, 0x7b, 0x9e, 0x0d, 0xfd, 0x18, 0x3a, 0x91, 0xbc, 0xfb, 0xa5, 0xd1, + 0x18, 0x05, 0xed, 0x7e, 0x89, 0x65, 0x02, 0x8e, 0xec, 0xa2, 0x95, 0x05, 0x33, 0x01, 0x6b, 0x81, 0x1d, 0x9a, 0x47, + 0x17, 0x7c, 0xbb, 0x2e, 0x19, 0x30, 0xa4, 0xcc, 0x5a, 0xfb, 0x74, 0xd5, 0xd1, 0xf8, 0x5a, 0x43, 0xb1, 0xd2, 0xb8, + 0x00, 0x86, 0x44, 0x15, 0x75, 0x3c, 0x59, 0x17, 0x1d, 0x30, 0x36, 0x97, 0x7c, 0x33, 0x44, 0x64, 0xce, 0x63, 0x83, + 0x41, 0x4c, 0x58, 0x3b, 0x56, 0x7f, 0xbe, 0xd0, 0x72, 0xa0, 0x69, 0x3e, 0x1f, 0x48, 0x94, 0xb6, 0x73, 0x08, 0x6d, + 0x27, 0x4a, 0xd7, 0x8d, 0x68, 0x0e, 0x84, 0x7b, 0xbf, 0x88, 0xc6, 0x19, 0x36, 0xde, 0xb9, 0x2c, 0xae, 0xaf, 0xba, + 0xba, 0x1f, 0x55, 0x23, 0x1e, 0x06, 0x5c, 0xbb, 0x85, 0x48, 0x9a, 0xf5, 0x77, 0xd4, 0x5b, 0x65, 0x94, 0x3e, 0x1d, + 0xef, 0x96, 0xbc, 0x6c, 0xed, 0x97, 0xfd, 0x9f, 0xcc, 0x3c, 0xe4, 0xf7, 0x85, 0x29, 0x54, 0x1f, 0x0d, 0x3d, 0xa2, + 0x6e, 0x1c, 0xe0, 0x7c, 0x6b, 0x13, 0x32, 0xb4, 0x60, 0x11, 0x19, 0x8f, 0xc0, 0xdc, 0x94, 0xa3, 0xbb, 0xde, 0x57, + 0x6c, 0xf8, 0x66, 0xc9, 0xbe, 0xd0, 0x95, 0x68, 0x5a, 0x47, 0xb8, 0x8b, 0x56, 0x92, 0x38, 0xa3, 0x91, 0x0e, 0x9d, + 0x51, 0xfd, 0x12, 0x3d, 0xef, 0x52, 0x60, 0x6b, 0xb9, 0xda, 0xf9, 0x9d, 0x95, 0x7c, 0x08, 0xa7, 0x63, 0x5c, 0x9b, + 0x0b, 0x48, 0xe3, 0x32, 0x71, 0x72, 0x58, 0x00, 0xcb, 0xde, 0xde, 0x2b, 0xe9, 0x70, 0x40, 0x6a, 0x3c, 0x16, 0xb3, + 0x43, 0x8a, 0x70, 0x03, 0x3a, 0x87, 0x06, 0x4b, 0x54, 0x09, 0xc7, 0x45, 0xec, 0xfa, 0xa6, 0xe2, 0x95, 0xab, 0xa0, + 0x0c, 0xca, 0x84, 0x75, 0x5b, 0xfe, 0x6d, 0xc9, 0xe7, 0xbe, 0x0d, 0x42, 0xce, 0x85, 0x0c, 0xee, 0x55, 0x09, 0x14, + 0x9b, 0x37, 0x82, 0xd8, 0x1a, 0xd3, 0x3d, 0xb0, 0x52, 0x9d, 0xb2, 0x58, 0x4f, 0x6c, 0xb6, 0x05, 0xf5, 0xa4, 0x61, + 0xe6, 0xf6, 0x1c, 0x41, 0x74, 0x07, 0xa1, 0x8f, 0xf7, 0xae, 0x8f, 0x52, 0x5e, 0xf9, 0xe5, 0xf9, 0x3e, 0x64, 0x85, + 0x62, 0x63, 0x0b, 0x3d, 0xa9, 0xf3, 0x70, 0x93, 0x07, 0x2d, 0xa2, 0x48, 0xf5, 0x5a, 0xac, 0x58, 0x01, 0x3b, 0xa2, + 0x0c, 0xff, 0x1e, 0x5c, 0x60, 0x1b, 0x58, 0x87, 0x4b, 0x00, 0x73, 0x37, 0xc6, 0xed, 0xd4, 0x53, 0xe5, 0x27, 0x1a, + 0x3f, 0x23, 0x82, 0x8b, 0x30, 0x45, 0x24, 0xb4, 0x4f, 0x15, 0x5f, 0xd1, 0x81, 0xc7, 0xb2, 0x7c, 0x6a, 0xc6, 0x9b, + 0x7c, 0xa9, 0x58, 0xaf, 0xfc, 0xf2, 0x90, 0xbd, 0xd0, 0xf8, 0x79, 0xd2, 0x12, 0xe2, 0xf2, 0x25, 0x82, 0x55, 0x25, + 0x5f, 0x8d, 0xd0, 0x47, 0xde, 0xc3, 0x97, 0x1b, 0x76, 0xd0, 0xf9, 0x80, 0x4a, 0xa6, 0x71, 0x81, 0x6f, 0x38, 0x2f, + 0xcd, 0xaa, 0x09, 0x33, 0x44, 0xf8, 0xc4, 0x69, 0x03, 0xc7, 0x57, 0xbe, 0x34, 0x74, 0x29, 0x3e, 0x15, 0x00, 0x7b, + 0x92, 0x74, 0x0e, 0x65, 0x32, 0xc7, 0x52, 0x24, 0x0e, 0x26, 0x95, 0xd9, 0x13, 0x48, 0x30, 0x5b, 0xac, 0xd2, 0x55, + 0xe7, 0x56, 0x8c, 0x6b, 0x32, 0x01, 0x30, 0xc6, 0x39, 0xd0, 0x9c, 0x99, 0xad, 0xd8, 0x21, 0x73, 0x62, 0x45, 0x05, + 0xf6, 0x7f, 0x8c, 0xbd, 0xc2, 0xdd, 0x67, 0xa6, 0x1f, 0xb3, 0x31, 0xdf, 0xf4, 0x3a, 0x34, 0x9b, 0xdc, 0x70, 0x79, + 0xb7, 0x5e, 0xcc, 0x89, 0x30, 0x5b, 0x40, 0x79, 0x1a, 0xd9, 0x48, 0x74, 0xd4, 0x40, 0xea, 0x1a, 0x48, 0x76, 0xf6, + 0xcd, 0x65, 0x6f, 0xf5, 0x59, 0x01, 0x31, 0xd1, 0xcd, 0x0c, 0xd4, 0xed, 0x2f, 0xf8, 0xb6, 0x3a, 0x15, 0x4c, 0x10, + 0xc0, 0x63, 0xd7, 0x86, 0x73, 0x21, 0x0b, 0xd5, 0xe9, 0xf6, 0xd3, 0x0e, 0x29, 0xfb, 0x59, 0x67, 0x52, 0xfe, 0x42, + 0x5b, 0x84, 0x11, 0x45, 0xa8, 0xae, 0x43, 0xcc, 0xb6, 0xa5, 0x1f, 0x84, 0x13, 0x70, 0xdc, 0x85, 0xd2, 0xf1, 0x01, + 0x5f, 0x52, 0x81, 0x08, 0xb9, 0x16, 0xe2, 0x6e, 0xd3, 0xd0, 0xb2, 0x82, 0xb7, 0xcd, 0x86, 0xd4, 0x4d, 0x3a, 0x7a, + 0x03, 0xaf, 0xe8, 0x66, 0xdd, 0xcb, 0xf4, 0x00, 0x64, 0x3c, 0x9a, 0x89, 0x81, 0x33, 0x6e, 0xdf, 0xde, 0x76, 0x2e, + 0x4d, 0x98, 0x17, 0x9d, 0x6c, 0x06, 0xaf, 0xe6, 0xc6, 0x9d, 0xb5, 0x0b, 0x67, 0xe3, 0xc3, 0x86, 0x66, 0x9b, 0xc7, + 0x1b, 0x6d, 0x1f, 0x66, 0xd7, 0xb3, 0xae, 0x5e, 0x96, 0x79, 0x99, 0x3e, 0xeb, 0xbb, 0x93, 0x5b, 0x35, 0x7f, 0x86, + 0x68, 0xb0, 0x19, 0xc8, 0x4c, 0x31, 0x49, 0xc2, 0x00, 0x30, 0x5a, 0x70, 0x7b, 0x13, 0xcd, 0xa0, 0x0b, 0x18, 0x28, + 0x4b, 0x93, 0xee, 0xe6, 0x8a, 0xe3, 0x97, 0x79, 0xaf, 0x54, 0xed, 0x85, 0x1b, 0x24, 0x0a, 0x4e, 0x83, 0xfd, 0x27, + 0x7e, 0xf7, 0x1f, 0x45, 0xdc, 0xcc, 0xf0, 0x95, 0x04, 0xa0, 0xb5, 0x60, 0xe1, 0x71, 0x62, 0x8b, 0xcd, 0xb2, 0x06, + 0x92, 0x52, 0x8b, 0xca, 0x7f, 0xd0, 0xf8, 0x51, 0x41, 0x5e, 0x9d, 0x6e, 0x0e, 0x31, 0xe0, 0x18, 0x8d, 0xda, 0x32, + 0xfd, 0xb8, 0x29, 0xc9, 0x70, 0x8a, 0x36, 0xb9, 0x8c, 0x68, 0x3e, 0x21, 0x1b, 0x0e, 0x01, 0x00, 0x4a, 0x95, 0x61, + 0x8d, 0xa4, 0x57, 0x93, 0xc4, 0xad, 0x0c, 0x47, 0x18, 0xa9, 0x02, 0xa3, 0x6f, 0xd6, 0x98, 0x5a, 0x08, 0xb5, 0x38, + 0x12, 0xc6, 0x76, 0x06, 0x29, 0xc7, 0xc0, 0x1c, 0xc4, 0x15, 0xf0, 0xec, 0xe4, 0x93, 0xda, 0x93, 0x96, 0x25, 0x14, + 0xfb, 0x4e, 0xc9, 0xd9, 0x6b, 0x3a, 0x28, 0x60, 0xd4, 0x75, 0xde, 0x86, 0xd3, 0x3c, 0x23, 0x4c, 0xf9, 0xd2, 0x8f, + 0xfe, 0x60, 0xdb, 0x03, 0xcf, 0x10, 0xaa, 0x02, 0xe1, 0xe3, 0x5c, 0x4d, 0x45, 0x54, 0xaa, 0x9c, 0x8b, 0xb4, 0xfd, + 0xf1, 0x88, 0x24, 0xdb, 0xc4, 0x7f, 0x40, 0x2c, 0xa5, 0x40, 0xf1, 0xf7, 0x9d, 0x13, 0x4d, 0x96, 0x98, 0x25, 0xf9, + 0x52, 0x9d, 0x26, 0x79, 0xf3, 0x35, 0x9c, 0x63, 0x35, 0x15, 0xff, 0x19, 0xa2, 0xa0, 0x69, 0x20, 0x84, 0xd6, 0x5b, + 0x9a, 0x6d, 0x40, 0xe9, 0xd6, 0x99, 0x6d, 0xe1, 0x9c, 0x07, 0x3c, 0x03, 0xb8, 0x98, 0x6d, 0xc6, 0x5d, 0x2a, 0x8d, + 0xa8, 0xf5, 0xca, 0x40, 0xba, 0x9d, 0x02, 0x0e, 0x51, 0x5b, 0x1f, 0xcc, 0x0e, 0x45, 0xef, 0x82, 0x17, 0x4c, 0x7e, + 0x06, 0x1f, 0x0a, 0x2a, 0xb5, 0xa0, 0xdb, 0x8b, 0xd9, 0x97, 0xd4, 0xa8, 0xca, 0x4b, 0xb3, 0xa1, 0xb6, 0xce, 0x5f, + 0x6b, 0x31, 0xe5, 0x2e, 0x00, 0x9d, 0xd0, 0x86, 0xad, 0x43, 0x06, 0x9e, 0xac, 0xe9, 0x53, 0x6e, 0x9a, 0x71, 0xc9, + 0xbe, 0x28, 0xc3, 0xdc, 0x8f, 0x88, 0xcd, 0xd8, 0xf7, 0xbe, 0x49, 0xad, 0xf9, 0x39, 0x87, 0xa7, 0xd6, 0xd5, 0x5a, + 0xc1, 0xd8, 0x3a, 0x7d, 0xd9, 0x38, 0x8a, 0x57, 0xf5, 0x4f, 0x80, 0x77, 0xf1, 0x79, 0xcd, 0xc8, 0xf4, 0xb5, 0x38, + 0x34, 0x22, 0x14, 0xb9, 0xde, 0x30, 0x04, 0x66, 0x22, 0x0c, 0xaf, 0xbb, 0x0b, 0xc1, 0xf4, 0xba, 0x52, 0x90, 0xe0, + 0xe0, 0xc6, 0x52, 0xec, 0x37, 0x7a, 0x7e, 0x65, 0xff, 0x50, 0x44, 0x43, 0x33, 0x15, 0xc0, 0x67, 0x33, 0x09, 0xd1, + 0x8f, 0x33, 0xb3, 0xe1, 0xc9, 0x83, 0xed, 0x6d, 0x44, 0x6d, 0x22, 0x81, 0x49, 0xe2, 0x32, 0x24, 0x51, 0xde, 0x25, + 0x5a, 0x90, 0xba, 0x84, 0xeb, 0x4f, 0x23, 0xf3, 0x4d, 0xa9, 0xca, 0x7c, 0x45, 0xe2, 0x5b, 0xd3, 0xb8, 0x7f, 0x08, + 0xa7, 0x79, 0x7d, 0x75, 0xfb, 0xbc, 0x65, 0xdd, 0x97, 0x7b, 0xb0, 0x95, 0x85, 0xff, 0x42, 0xdb, 0x98, 0xba, 0x6a, + 0x9d, 0x2e, 0x27, 0x62, 0xfc, 0x25, 0xea, 0x65, 0xec, 0x60, 0xbc, 0xed, 0x37, 0xb8, 0xd5, 0x08, 0x53, 0x7b, 0xf3, + 0x6b, 0x8e, 0x4c, 0x3d, 0x48, 0xdd, 0x00, 0x0d, 0x2b, 0x76, 0xa9, 0xca, 0x52, 0x5b, 0xfe, 0xd9, 0xad, 0xe7, 0x3b, + 0x19, 0x8e, 0x0e, 0x9f, 0x43, 0x1a, 0xf3, 0x5d, 0x6f, 0xbe, 0x79, 0xcd, 0xa4, 0x67, 0x9d, 0x46, 0x11, 0xdd, 0x8a, + 0x61, 0x3b, 0x46, 0x87, 0x43, 0x52, 0xb8, 0x2b, 0x49, 0x35, 0xc1, 0x3e, 0x51, 0x54, 0x8e, 0x06, 0x42, 0x18, 0x30, + 0xb1, 0x27, 0x61, 0xbb, 0x2f, 0x14, 0x70, 0xda, 0xd0, 0xbd, 0xab, 0x0e, 0x54, 0x42, 0x89, 0x8c, 0xbd, 0xac, 0xc6, + 0x37, 0xa5, 0x8a, 0x7c, 0x88, 0x57, 0xf0, 0xb0, 0xf4, 0x9a, 0x72, 0x97, 0x0c, 0x20, 0xf7, 0xea, 0xf4, 0xe6, 0x9f, + 0xb3, 0x7b, 0xee, 0xb3, 0x90, 0x6f, 0x7c, 0xed, 0xaf, 0x76, 0xdf, 0x5f, 0xe8, 0x60, 0x5e, 0xc1, 0x2a, 0xee, 0x5f, + 0xfe, 0x50, 0x29, 0x0a, 0x35, 0xea, 0x07, 0x79, 0x60, 0x7b, 0xe9, 0x71, 0x53, 0x16, 0xd6, 0x02, 0x13, 0x72, 0xe5, + 0xcd, 0x99, 0x06, 0xc2, 0x38, 0x8e, 0x7f, 0xcd, 0x29, 0xa4, 0x6c, 0xdc, 0x9c, 0x3c, 0xe3, 0xd1, 0x58, 0x11, 0xea, + 0x50, 0x97, 0x9b, 0x79, 0xd7, 0x71, 0x46, 0x8e, 0xbb, 0xa6, 0xe8, 0x8f, 0xe6, 0xe2, 0x5f, 0xcd, 0x3e, 0x43, 0xf8, + 0x15, 0x70, 0x3a, 0xe0, 0x3a, 0x65, 0xc6, 0x2e, 0x18, 0xed, 0x2e, 0x49, 0xc3, 0xc3, 0xc7, 0x76, 0xb0, 0xb5, 0xff, + 0xf1, 0xda, 0x83, 0x8a, 0x08, 0x21, 0x87, 0x9f, 0x1d, 0x3a, 0x39, 0xe8, 0xc3, 0xaa, 0x72, 0x7a, 0xd1, 0x17, 0x2c, + 0x2b, 0xd8, 0x42, 0x0d, 0x30, 0x25, 0xe8, 0x7e, 0x85, 0x96, 0x17, 0xbb, 0xa6, 0x7f, 0x78, 0xe6, 0xf3, 0x2c, 0xf2, + 0xc1, 0x02, 0x7e, 0x77, 0xa8, 0x92, 0x47, 0x6d, 0x2c, 0x5f, 0x68, 0xc9, 0xb7, 0x86, 0x14, 0x18, 0x55, 0x90, 0x36, + 0xc4, 0xc3, 0x51, 0x75, 0x39, 0x17, 0x5c, 0xa0, 0xfa, 0xd1, 0xa3, 0xb8, 0x4c, 0x51, 0x00, 0x58, 0xae, 0xb4, 0x40, + 0x38, 0x1f, 0x20, 0x42, 0xa1, 0x61, 0x35, 0x09, 0x99, 0x7e, 0x9e, 0xed, 0xa6, 0x06, 0xa1, 0xf1, 0xbe, 0xb4, 0xf6, + 0x23, 0xca, 0xc8, 0x9c, 0xa2, 0x29, 0x5d, 0xa5, 0xb6, 0x19, 0xf2, 0xc0, 0xb7, 0xb4, 0x2c, 0x00, 0x46, 0x4b, 0x24, + 0x1f, 0x36, 0x16, 0x91, 0xb5, 0xaf, 0xe7, 0x84, 0xbb, 0xcc, 0x7e, 0xf4, 0x4d, 0xcd, 0x2f, 0xb6, 0x4d, 0x83, 0xf3, + 0x87, 0xc8, 0x75, 0xee, 0x06, 0xc9, 0xc6, 0x26, 0x5e, 0xb9, 0x8d, 0x6f, 0x47, 0xf4, 0x87, 0x76, 0x59, 0x7f, 0xcb, + 0x30, 0x01, 0x75, 0x26, 0x2d, 0xe1, 0x1a, 0x80, 0x72, 0x18, 0xc2, 0xd3, 0x38, 0x14, 0x2f, 0x97, 0x3c, 0x44, 0x13, + 0x8d, 0x04, 0x4a, 0x60, 0x85, 0x37, 0xec, 0xa2, 0xaa, 0x7e, 0x3d, 0xf0, 0xff, 0x1b, 0x68, 0xaa, 0xfa, 0x36, 0xb3, + 0xd4, 0x4d, 0x4b, 0x40, 0xdb, 0x86, 0x04, 0xab, 0xa0, 0xc2, 0x11, 0xb6, 0x96, 0xa4, 0x32, 0x18, 0xb6, 0x9e, 0x7c, + 0xd8, 0x10, 0xb1, 0x99, 0x8c, 0x33, 0xad, 0xdf, 0x0e, 0x33, 0xdb, 0x2f, 0x05, 0xde, 0x10, 0x8b, 0xc6, 0x5c, 0xd4, + 0xb8, 0xf6, 0x34, 0x42, 0x20, 0x13, 0xa4, 0xd1, 0x9d, 0xd1, 0xd6, 0xc5, 0xf8, 0xda, 0xba, 0x24, 0x9f, 0x91, 0x75, + 0x72, 0xba, 0xc3, 0x07, 0x03, 0x21, 0xee, 0xa3, 0x5c, 0x30, 0xa3, 0xd4, 0x56, 0xe2, 0x6a, 0x88, 0x65, 0xd1, 0x4e, + 0x64, 0x11, 0x00, 0x23, 0xc0, 0xfe, 0x60, 0x5e, 0x6b, 0xd2, 0xe4, 0x0d, 0xe1, 0xcb, 0xd5, 0x38, 0x1d, 0x6b, 0xfd, + 0x36, 0x2c, 0x9b, 0x0e, 0x4c, 0xe1, 0x7a, 0x58, 0x9d, 0xc6, 0xb3, 0xf7, 0x6a, 0x8b, 0xd1, 0x9f, 0xf7, 0xe8, 0x05, + 0xbc, 0x41, 0x90, 0xc1, 0xa9, 0x98, 0x6c, 0x69, 0x7c, 0xd8, 0x43, 0xbc, 0x90, 0xea, 0x7c, 0x10, 0xb4, 0x1d, 0xd5, + 0x1e, 0x50, 0xce, 0x5f, 0x0b, 0xd4, 0x7d, 0x24, 0x3c, 0x13, 0x20, 0x23, 0x05, 0xe5, 0x89, 0xd6, 0xa7, 0xe8, 0xa1, + 0x07, 0x3e, 0xe9, 0xea, 0x9a, 0xb5, 0xa0, 0x93, 0x20, 0xd1, 0x10, 0x27, 0x27, 0x31, 0xfa, 0xe6, 0xc5, 0x03, 0x08, + 0xd2, 0x72, 0x4d, 0x86, 0xd2, 0x42, 0x1b, 0xc5, 0x19, 0x9b, 0xc4, 0x14, 0xd6, 0xff, 0xdc, 0x4e, 0x73, 0xa4, 0xe1, + 0xe0, 0x12, 0x25, 0x6f, 0x35, 0x91, 0x42, 0x82, 0x75, 0x52, 0x27, 0xbd, 0x9f, 0xb0, 0x1b, 0xdc, 0xf5, 0x8e, 0x0f, + 0x25, 0x11, 0x82, 0x09, 0xa1, 0x90, 0x9f, 0x96, 0xe1, 0xfc, 0x51, 0xe0, 0x37, 0x35, 0x0a, 0xce, 0x78, 0x5c, 0xc9, + 0x86, 0xa0, 0xd0, 0xef, 0xd9, 0x83, 0x5d, 0x38, 0x41, 0xd8, 0x74, 0xf8, 0xd0, 0x95, 0xb2, 0x0c, 0x82, 0x94, 0xde, + 0xeb, 0xbc, 0x0d, 0x15, 0xc9, 0x04, 0xd4, 0x42, 0xbb, 0x1e, 0x67, 0x15, 0x76, 0x73, 0x84, 0x7e, 0x2b, 0x36, 0xf8, + 0xb2, 0xb3, 0x05, 0x04, 0xd7, 0xd0, 0xc2, 0xe0, 0xa2, 0x42, 0x66, 0xb7, 0x88, 0x9e, 0x60, 0x72, 0x16, 0xb9, 0xc3, + 0x97, 0xb4, 0x50, 0xb9, 0x64, 0x25, 0x3d, 0x97, 0x3e, 0xf8, 0x5d, 0x76, 0xb4, 0x8a, 0x1b, 0x67, 0x6d, 0x94, 0x6a, + 0x74, 0x8b, 0x99, 0xef, 0x1f, 0x31, 0xc7, 0x25, 0xb1, 0x51, 0x0b, 0x2e, 0x19, 0xba, 0x32, 0x65, 0x29, 0x0b, 0x1c, + 0x71, 0x20, 0x82, 0xba, 0xcd, 0x77, 0xc4, 0x2b, 0xaa, 0x3b, 0xd9, 0x6b, 0x83, 0x0d, 0x5a, 0x87, 0xac, 0x95, 0xc2, + 0x9b, 0xb4, 0x42, 0x17, 0xb1, 0x8a, 0x19, 0xb8, 0x1c, 0x6f, 0xbf, 0x34, 0x19, 0xa0, 0x9b, 0x23, 0x71, 0xe7, 0x74, + 0x06, 0x45, 0x66, 0x78, 0xd1, 0xbf, 0x92, 0x56, 0x69, 0x50, 0xd6, 0x5b, 0xc9, 0x61, 0xac, 0xa3, 0xf9, 0x61, 0xb8, + 0xbf, 0x8a, 0x5f, 0xd3, 0x1d, 0xe5, 0xbf, 0x55, 0x7f, 0x39, 0x50, 0x55, 0x5e, 0x68, 0x15, 0x87, 0x6a, 0x1b, 0x27, + 0x21, 0xa1, 0x9f, 0x6c, 0xdf, 0xb7, 0xef, 0xbf, 0x19, 0x71, 0x8d, 0x5b, 0xda, 0x38, 0xdc, 0x6b, 0x71, 0xd0, 0xa2, + 0xbc, 0xff, 0x0f, 0xa5, 0x99, 0x01, 0x6c, 0xd2, 0xa1, 0x19, 0x32, 0x57, 0x1e, 0x7d, 0xa5, 0x5f, 0x8d, 0x19, 0x09, + 0x33, 0x7b, 0xcd, 0x18, 0xe3, 0xb5, 0xef, 0xfe, 0x9e, 0xa2, 0x85, 0x45, 0x93, 0x3c, 0x39, 0x2f, 0x05, 0xe3, 0xaa, + 0x2e, 0x7e, 0x76, 0xc7, 0x93, 0xf0, 0x3f, 0xa8, 0xda, 0xbe, 0x3c, 0x08, 0x31, 0x77, 0x3d, 0x85, 0x68, 0x83, 0x59, + 0xf2, 0x29, 0x6f, 0x7a, 0xba, 0xc6, 0x92, 0xc6, 0x4f, 0x66, 0xe5, 0xba, 0x75, 0xcd, 0x4e, 0x02, 0x60, 0xdc, 0x1f, + 0x9b, 0x3f, 0x2c, 0x2a, 0xf4, 0xed, 0x66, 0x2a, 0x81, 0xaf, 0x0c, 0xb3, 0x79, 0x9f, 0x05, 0xe0, 0x6f, 0x70, 0x96, + 0xd3, 0x72, 0x9e, 0x5a, 0x52, 0x3c, 0xf5, 0x4b, 0x6c, 0xd5, 0xaf, 0x1c, 0xd9, 0x50, 0x1e, 0x7f, 0xdd, 0xb0, 0x12, + 0xa8, 0xb8, 0x1b, 0x98, 0x60, 0xfa, 0xf7, 0xc9, 0xc8, 0x71, 0x14, 0x36, 0xb6, 0x51, 0x40, 0x56, 0x1f, 0x6f, 0x7e, + 0x3f, 0xcb, 0x36, 0xfc, 0xe3, 0x71, 0xb2, 0x6e, 0x20, 0x50, 0x83, 0x45, 0xd6, 0xdd, 0xf5, 0x9e, 0x05, 0x48, 0x65, + 0x77, 0x2b, 0xea, 0x8b, 0xc3, 0xd0, 0x7f, 0xfc, 0xdc, 0x19, 0xd5, 0xbb, 0x70, 0x8e, 0x71, 0x84, 0xd4, 0x2f, 0x61, + 0x7f, 0xff, 0x64, 0xd2, 0x2f, 0xcf, 0x9c, 0xff, 0x24, 0xea, 0x17, 0xa9, 0x7a, 0x43, 0x17, 0x12, 0xc7, 0x3e, 0x6c, + 0x7e, 0x9a, 0x23, 0x0f, 0x76, 0x3e, 0xcf, 0x44, 0x6a, 0xac, 0xc7, 0x52, 0x1d, 0x57, 0xc9, 0xca, 0x0f, 0x3e, 0x5c, + 0x6a, 0x5f, 0x2c, 0x59, 0x5a, 0xed, 0x5e, 0xd1, 0xf7, 0x68, 0x6e, 0xa0, 0xf5, 0xd8, 0x07, 0xef, 0xa6, 0x4f, 0xb5, + 0xfb, 0x18, 0xdd, 0x3d, 0xbd, 0x92, 0x38, 0xdb, 0x2a, 0x4d, 0x6c, 0xe1, 0xb3, 0xa3, 0xd7, 0x89, 0xb4, 0x14, 0x5a, + 0x19, 0x61, 0x7a, 0xca, 0x1e, 0xc1, 0x12, 0x24, 0x4b, 0xab, 0xde, 0xb1, 0x6b, 0x2e, 0xd2, 0x98, 0xfe, 0xf4, 0xc4, + 0x4a, 0x8f, 0x7b, 0xcd, 0x6a, 0x7a, 0x98, 0x5f, 0x19, 0x33, 0xe3, 0x0c, 0x09, 0x9e, 0x42, 0x24, 0xa0, 0xb3, 0x05, + 0xe5, 0x13, 0x4d, 0x66, 0x25, 0xac, 0xbe, 0x3a, 0x53, 0x82, 0x30, 0x2b, 0x1b, 0x77, 0x29, 0x67, 0xda, 0xe8, 0x34, + 0xc7, 0x72, 0x5d, 0x3a, 0x8f, 0xcb, 0xd5, 0x71, 0x50, 0xff, 0xa6, 0x43, 0x18, 0xce, 0x36, 0x9c, 0x1f, 0xa9, 0x9e, + 0x18, 0x25, 0x5f, 0x90, 0x7f, 0x11, 0x2a, 0xd8, 0xa8, 0xbe, 0x79, 0x82, 0x0e, 0x64, 0x52, 0xef, 0x8f, 0xdf, 0xed, + 0x8f, 0xef, 0x61, 0x0c, 0xc3, 0x36, 0x68, 0x2b, 0x28, 0x55, 0x45, 0xb9, 0x14, 0x6d, 0x9c, 0x77, 0x3d, 0x2e, 0xbb, + 0xfc, 0xa6, 0x0f, 0x34, 0xfa, 0xe5, 0x79, 0xe7, 0x5a, 0x5a, 0x7a, 0x44, 0xa6, 0x5e, 0x24, 0x0a, 0x31, 0xd6, 0x52, + 0x78, 0xb3, 0x74, 0xa2, 0xe2, 0x80, 0xe1, 0xae, 0xc9, 0xc8, 0x33, 0x73, 0xc6, 0x6e, 0x25, 0xed, 0x08, 0x16, 0x86, + 0x75, 0xd3, 0xb5, 0x94, 0x64, 0x99, 0xf5, 0xe9, 0x5e, 0x9d, 0x08, 0x2b, 0x38, 0xbc, 0x11, 0xdb, 0x13, 0xd2, 0xfc, + 0x69, 0x22, 0x99, 0x93, 0xd7, 0xfb, 0x12, 0x30, 0x4b, 0x5c, 0x3a, 0x9b, 0x7c, 0x46, 0x9a, 0xe2, 0x5f, 0x07, 0x95, + 0xe9, 0x8b, 0x6f, 0xac, 0x26, 0xd4, 0xbe, 0x4a, 0x56, 0xa9, 0x38, 0xc7, 0x17, 0x14, 0x29, 0xf6, 0x8c, 0xf6, 0x4c, + 0x76, 0xe8, 0x46, 0x63, 0x6f, 0x73, 0x4f, 0x29, 0xa4, 0xcc, 0x62, 0xdf, 0x4b, 0xd0, 0xbf, 0x22, 0xcc, 0x30, 0x09, + 0x4a, 0xf0, 0xf2, 0x3f, 0xe0, 0xc6, 0x1c, 0x38, 0xa2, 0xde, 0x3b, 0x8f, 0x89, 0x45, 0x0b, 0x75, 0xe8, 0x86, 0x0c, + 0xab, 0x74, 0x22, 0x7e, 0xbd, 0x44, 0xd1, 0xb4, 0x0f, 0x6b, 0x84, 0x79, 0xe1, 0x2b, 0xed, 0x6f, 0x13, 0x01, 0x34, + 0x08, 0x4b, 0x43, 0x0c, 0xec, 0xea, 0x26, 0x6d, 0x61, 0xb8, 0xd5, 0x13, 0x68, 0x0a, 0x17, 0xaf, 0xe9, 0x78, 0xfa, + 0x5a, 0xa4, 0x13, 0x4a, 0x7a, 0x94, 0x8b, 0xc9, 0xb1, 0x16, 0xcb, 0x31, 0x7b, 0x2c, 0x7f, 0x27, 0xd7, 0xcb, 0xb3, + 0x08, 0x4d, 0x4f, 0x05, 0x16, 0x39, 0x08, 0x9c, 0x71, 0x69, 0xa5, 0x54, 0xef, 0x30, 0x78, 0x99, 0x99, 0x28, 0xfc, + 0x40, 0x5e, 0x06, 0x0b, 0xa5, 0x93, 0x1f, 0xb4, 0xea, 0xef, 0x3d, 0x45, 0x61, 0xf6, 0xf4, 0x10, 0x45, 0xc7, 0xa8, + 0xb3, 0xbb, 0x8e, 0x41, 0xf5, 0xa7, 0x35, 0xf5, 0x6b, 0xf8, 0x05, 0xa3, 0x0b, 0x24, 0x32, 0x73, 0x0c, 0x24, 0x8f, + 0xc0, 0x1f, 0xef, 0xb0, 0xc9, 0x7d, 0xe6, 0x6c, 0x87, 0xe4, 0xf1, 0xea, 0x6d, 0xc5, 0x01, 0x5d, 0x32, 0x56, 0x4b, + 0x1e, 0xa2, 0xf6, 0xaa, 0x96, 0xf5, 0xa7, 0xe5, 0x98, 0x77, 0x0b, 0xb7, 0xa3, 0xc7, 0x53, 0x1c, 0xb0, 0xbd, 0xdf, + 0x9d, 0x09, 0x8b, 0x43, 0x9c, 0x1f, 0x1b, 0xd5, 0xed, 0x18, 0x5d, 0x96, 0x01, 0x3e, 0xad, 0x0f, 0xb4, 0x41, 0x10, + 0xd7, 0x67, 0x07, 0xaa, 0x3b, 0xf7, 0x15, 0x2f, 0x4c, 0x8f, 0xd7, 0x24, 0x94, 0x96, 0xf2, 0x64, 0x6c, 0xc8, 0x3a, + 0x80, 0xa2, 0x51, 0xcc, 0x51, 0x10, 0xa2, 0x08, 0x10, 0x72, 0x48, 0x49, 0xf2, 0x6a, 0x0f, 0x40, 0x11, 0x6b, 0xa1, + 0x72, 0xd0, 0x1c, 0xf7, 0x7e, 0x10, 0xc4, 0x30, 0x63, 0xfa, 0x0f, 0xf1, 0x43, 0x78, 0xb6, 0xc3, 0x32, 0x96, 0x19, + 0xaf, 0x71, 0x95, 0xae, 0xcf, 0x81, 0x72, 0xe9, 0xe6, 0xad, 0xfa, 0x4d, 0x4f, 0x80, 0x69, 0x7d, 0x16, 0x84, 0x2d, + 0x22, 0x77, 0x09, 0x42, 0x64, 0xd7, 0x05, 0x7a, 0xf5, 0x40, 0xb6, 0x3b, 0xf4, 0x43, 0xaf, 0x20, 0x52, 0xfa, 0x5a, + 0x10, 0x7e, 0x45, 0x7e, 0x10, 0x16, 0x3c, 0xdf, 0x50, 0x94, 0x06, 0x88, 0x9e, 0x42, 0xad, 0x3b, 0x7d, 0xab, 0xe2, + 0x1c, 0x3b, 0xa8, 0xdb, 0xcc, 0xc2, 0xf6, 0xa7, 0x13, 0xf1, 0xb1, 0xac, 0x8b, 0x97, 0x74, 0xe9, 0xae, 0xde, 0xb7, + 0x0c, 0x7b, 0x00, 0xc4, 0x52, 0x85, 0x9d, 0xa1, 0x12, 0x81, 0xaf, 0xf3, 0x82, 0x87, 0x14, 0xbd, 0x4a, 0xb6, 0xf7, + 0xdd, 0xef, 0xbd, 0x42, 0x47, 0x7c, 0xd9, 0x16, 0x7d, 0xc2, 0x57, 0xd5, 0x24, 0x5e, 0x5f, 0xd9, 0x2b, 0xf7, 0xb6, + 0xea, 0xf9, 0xf3, 0x61, 0x14, 0x67, 0xf1, 0x8e, 0xa6, 0x4b, 0x8d, 0xde, 0x27, 0xab, 0xbf, 0x03, 0xb5, 0xa8, 0x7d, + 0x97, 0xe8, 0xf4, 0x72, 0xe4, 0x98, 0xf9, 0xa2, 0xa4, 0x69, 0xdd, 0xe1, 0x34, 0x7f, 0x95, 0x59, 0x8f, 0xaf, 0xf4, + 0x9c, 0x59, 0xcd, 0xf4, 0xc1, 0xcf, 0x54, 0xdb, 0x73, 0x19, 0x00, 0x5b, 0xc7, 0xa7, 0xcf, 0xc7, 0xbd, 0x0d, 0xab, + 0xd5, 0x17, 0xfd, 0x88, 0x75, 0xd1, 0x0d, 0x3d, 0xd7, 0x13, 0x84, 0xf4, 0x9c, 0xee, 0x1d, 0x58, 0xa5, 0x1f, 0x1b, + 0x29, 0xfa, 0x36, 0xc5, 0xbe, 0x67, 0x45, 0x2e, 0x48, 0xc7, 0xae, 0x7a, 0xc3, 0x6d, 0x16, 0xfa, 0x66, 0xda, 0x52, + 0x5f, 0xd4, 0xa8, 0x6d, 0x89, 0xcf, 0x67, 0xa9, 0x64, 0x22, 0xea, 0x17, 0x37, 0x5c, 0x59, 0xdf, 0x79, 0x07, 0xc9, + 0x6a, 0x95, 0xc0, 0x5d, 0x91, 0x5c, 0xe9, 0xd2, 0x7f, 0x1f, 0x46, 0xcf, 0x53, 0x0e, 0xab, 0xa5, 0x9c, 0xa6, 0xa7, + 0xa8, 0xec, 0x8d, 0x9d, 0x94, 0xf9, 0x49, 0xf2, 0xef, 0xfc, 0xf0, 0x64, 0xb1, 0x9b, 0x18, 0xf5, 0xf9, 0x88, 0xd7, + 0xf9, 0xfb, 0x2a, 0x63, 0x14, 0xc4, 0xd0, 0xee, 0xab, 0x9c, 0x26, 0x6d, 0x95, 0xf8, 0xd8, 0x7b, 0x45, 0xb1, 0xc9, + 0xf2, 0xe8, 0xa9, 0xc2, 0x24, 0xf8, 0x69, 0x44, 0xce, 0xfc, 0x5c, 0x4d, 0xc2, 0xc4, 0x78, 0xba, 0xb4, 0xfa, 0x1e, + 0x9e, 0xba, 0x0b, 0x67, 0xbd, 0xc7, 0x08, 0x69, 0x8c, 0xff, 0x39, 0x66, 0x58, 0xe2, 0xd5, 0x99, 0xe5, 0xdb, 0xe0, + 0xc6, 0x74, 0x58, 0x4a, 0x1a, 0xce, 0x71, 0x30, 0xa1, 0x1b, 0x8c, 0x7a, 0xab, 0x04, 0x35, 0x54, 0x84, 0x83, 0x02, + 0x22, 0xfb, 0x88, 0x66, 0x51, 0x56, 0x24, 0x40, 0x91, 0x69, 0xf1, 0xb7, 0x39, 0xb6, 0xc8, 0x0f, 0x2d, 0xf6, 0xcb, + 0xf2, 0xbd, 0xbe, 0x0a, 0xa2, 0xfe, 0x36, 0x01, 0x45, 0xa8, 0x0d, 0x59, 0x9b, 0x80, 0x29, 0x44, 0x31, 0x35, 0xc1, + 0xa7, 0x05, 0x45, 0xa1, 0x32, 0xf1, 0x2a, 0x6c, 0x0d, 0x16, 0x0e, 0xb5, 0xb4, 0xa8, 0x35, 0xe9, 0xbc, 0x05, 0xe4, + 0x68, 0xbf, 0x75, 0xf1, 0x5c, 0x76, 0x6a, 0x3c, 0x4c, 0xaa, 0x3d, 0x24, 0x22, 0xc1, 0x3c, 0xce, 0x46, 0xc0, 0x6e, + 0xf3, 0x29, 0xbe, 0x14, 0xd0, 0x64, 0x49, 0xdd, 0xc5, 0x6f, 0xba, 0xed, 0x04, 0x54, 0x46, 0x2b, 0x0d, 0x05, 0x09, + 0xdf, 0x1d, 0x8d, 0x07, 0xaa, 0x0a, 0xd9, 0x65, 0xbc, 0xc3, 0x25, 0x37, 0x22, 0xcc, 0x52, 0x74, 0x87, 0x5f, 0x92, + 0xfe, 0xdd, 0x51, 0x99, 0x93, 0x9d, 0xd6, 0xb4, 0x77, 0x1b, 0x06, 0x5f, 0xc4, 0xe8, 0xcc, 0x00, 0x47, 0xf6, 0x3a, + 0xc0, 0x06, 0xce, 0x63, 0x84, 0x09, 0x38, 0x5e, 0x54, 0x64, 0xb2, 0xce, 0x2f, 0xd9, 0xbd, 0xb8, 0xca, 0x1c, 0x1c, + 0x08, 0x51, 0x0b, 0x3f, 0xe0, 0x46, 0x0b, 0xc8, 0x70, 0x30, 0x4b, 0xe8, 0xb1, 0x50, 0x3c, 0x37, 0x00, 0xef, 0x95, + 0x36, 0x90, 0x80, 0xdc, 0xec, 0x49, 0x01, 0xc9, 0xfc, 0x85, 0x59, 0x03, 0xc2, 0x87, 0x64, 0x26, 0x73, 0x72, 0x06, + 0xa5, 0xc4, 0x1a, 0x00, 0x45, 0xc8, 0x2c, 0x00, 0x9f, 0x35, 0xef, 0x37, 0x6f, 0x5f, 0x4e, 0x15, 0x3b, 0x1d, 0x80, + 0x7f, 0x50, 0x8a, 0x4c, 0x6e, 0x46, 0x42, 0x19, 0x38, 0xbf, 0x00, 0x93, 0x0d, 0x58, 0xfd, 0x18, 0x86, 0xdf, 0xf5, + 0x0c, 0x23, 0x97, 0xd1, 0xc2, 0xea, 0x42, 0x52, 0x94, 0xee, 0xad, 0x0b, 0x91, 0x2a, 0x65, 0x33, 0x6a, 0x43, 0x86, + 0x2d, 0xf8, 0x3c, 0x55, 0x9f, 0x78, 0xad, 0x4c, 0x8e, 0x9a, 0x85, 0xcd, 0x3a, 0xb1, 0x85, 0x4c, 0x58, 0x9c, 0x26, + 0xe7, 0xe6, 0x2d, 0x4f, 0xb3, 0x88, 0x57, 0x2e, 0x49, 0x93, 0x96, 0x45, 0x85, 0xd8, 0xc6, 0x4c, 0x95, 0x0d, 0x7f, + 0x72, 0x9c, 0xc7, 0xb3, 0x01, 0x23, 0x7f, 0xb6, 0xa0, 0xeb, 0xed, 0x43, 0x2c, 0x12, 0x72, 0x56, 0x5b, 0xf3, 0xcd, + 0x2e, 0xb5, 0xcd, 0xbd, 0xb1, 0x73, 0xfa, 0xd8, 0xfa, 0xcb, 0x47, 0x32, 0x3b, 0x57, 0x54, 0x84, 0xdd, 0x71, 0x90, + 0x74, 0x89, 0xa9, 0x8a, 0x2b, 0xa7, 0x3e, 0x1b, 0x2e, 0x89, 0xf3, 0x1a, 0xdf, 0x5d, 0x82, 0x5d, 0xde, 0xe4, 0xff, + 0x92, 0xe2, 0xf8, 0x02, 0xb8, 0xa2, 0x08, 0x9c, 0x96, 0x5a, 0x28, 0xa2, 0x78, 0xca, 0x99, 0xe5, 0x16, 0x68, 0xd5, + 0x53, 0xb5, 0xb6, 0xd4, 0x5d, 0x31, 0xc2, 0xb3, 0xd8, 0x0a, 0x43, 0x20, 0xd3, 0x59, 0x90, 0xe5, 0x24, 0x36, 0x38, + 0xe8, 0x73, 0x41, 0x90, 0xcc, 0x85, 0x72, 0x37, 0xee, 0xb1, 0x8d, 0x35, 0x1b, 0x8c, 0x76, 0x96, 0x5a, 0x24, 0xe7, + 0x51, 0x91, 0xbd, 0x2f, 0x77, 0x0b, 0xf6, 0x6d, 0x07, 0x14, 0x25, 0x52, 0x59, 0xfa, 0x3a, 0x52, 0xc2, 0x63, 0xde, + 0xda, 0x4c, 0x23, 0x8c, 0x61, 0xc1, 0x8e, 0x36, 0xb6, 0xcd, 0x65, 0x48, 0x2c, 0x6b, 0x1b, 0x46, 0x95, 0xa1, 0xd9, + 0x88, 0x3c, 0x85, 0xf2, 0xa8, 0xbe, 0x09, 0xda, 0x90, 0x4a, 0xf6, 0xf0, 0xae, 0xa1, 0xb0, 0x48, 0xe9, 0x23, 0xd8, + 0xa2, 0xf9, 0x22, 0xd1, 0xed, 0x51, 0x63, 0x43, 0x76, 0xac, 0x92, 0x1c, 0xa6, 0xcb, 0x06, 0xe9, 0xf3, 0x28, 0x50, + 0xea, 0x2a, 0x91, 0x10, 0x14, 0x12, 0xe6, 0xd9, 0x1b, 0x3e, 0x35, 0x2d, 0xf7, 0x08, 0x08, 0x66, 0x9f, 0x57, 0xbd, + 0xa8, 0x1b, 0x21, 0xe2, 0x43, 0x11, 0x39, 0x7e, 0xaf, 0x1c, 0x86, 0xee, 0x6d, 0x2a, 0x86, 0x5b, 0x1b, 0x1f, 0x4f, + 0x92, 0x29, 0xd1, 0xb4, 0x43, 0xa4, 0x0b, 0x24, 0x56, 0x00, 0xb1, 0x2c, 0x9d, 0x4a, 0x50, 0x0a, 0x3d, 0x05, 0x3b, + 0x9e, 0x8f, 0x37, 0xe9, 0xb4, 0xc5, 0x48, 0x73, 0x59, 0x9a, 0xff, 0xe6, 0xc3, 0x30, 0x3d, 0x4d, 0xec, 0xae, 0xfe, + 0xc2, 0xfd, 0xdc, 0x7d, 0xb3, 0x61, 0x88, 0x62, 0x97, 0x6c, 0x10, 0x81, 0xf0, 0x77, 0xd1, 0xb4, 0xb0, 0x60, 0x2a, + 0xb4, 0x1b, 0xc7, 0xc6, 0x2f, 0x93, 0x61, 0xcf, 0x74, 0xba, 0x23, 0x50, 0xfc, 0x1a, 0x42, 0x87, 0x2b, 0xa0, 0x01, + 0x21, 0x50, 0x3f, 0x8b, 0x5c, 0x0b, 0xe3, 0xde, 0xe6, 0x3f, 0xa2, 0x98, 0x83, 0x01, 0x02, 0x39, 0x15, 0xe4, 0x5e, + 0x70, 0x46, 0x12, 0x67, 0x1d, 0x69, 0x59, 0x7f, 0xea, 0xba, 0x4d, 0xe9, 0xc8, 0xde, 0xb7, 0x82, 0x03, 0x45, 0x7b, + 0xb9, 0x95, 0xe9, 0x3f, 0x80, 0xbd, 0xb0, 0x2b, 0xcb, 0x7f, 0x3c, 0x17, 0x4d, 0x15, 0x19, 0xf5, 0xd4, 0x55, 0xf5, + 0x76, 0x64, 0xcc, 0x4c, 0x66, 0xe3, 0x91, 0x5f, 0x06, 0xed, 0xbe, 0x15, 0xc1, 0xc6, 0x2b, 0xd7, 0xf1, 0xf1, 0xc9, + 0xc8, 0x20, 0xb6, 0xab, 0x0b, 0xd5, 0x8c, 0x09, 0x44, 0x1e, 0xa6, 0xd2, 0x6e, 0x6c, 0xf3, 0x3a, 0xfd, 0xe4, 0x6e, + 0xfd, 0xf6, 0x9b, 0x54, 0x71, 0x6e, 0x85, 0x4d, 0x32, 0xdd, 0xc4, 0x0b, 0xf7, 0xdc, 0xef, 0xda, 0x66, 0xf3, 0xb6, + 0xdb, 0xa5, 0x88, 0xae, 0x6d, 0x04, 0x9d, 0x0f, 0xb5, 0xdd, 0x40, 0xe3, 0x67, 0xda, 0xc4, 0xd7, 0xf9, 0x4f, 0x55, + 0x03, 0x1d, 0xff, 0x89, 0x53, 0xb6, 0x45, 0x1c, 0xb5, 0xe5, 0x52, 0x0a, 0xdf, 0xe0, 0x2b, 0x13, 0xbe, 0x02, 0x77, + 0xe5, 0xc4, 0xf0, 0xec, 0x55, 0xe9, 0x6d, 0x67, 0x3f, 0xfa, 0xc9, 0x9a, 0x7a, 0x12, 0x83, 0xd2, 0x57, 0xc1, 0x3e, + 0x40, 0x5f, 0xa8, 0x1a, 0x22, 0x75, 0xf7, 0xee, 0x2b, 0x81, 0x13, 0x15, 0xe2, 0x3f, 0x08, 0x06, 0x46, 0x69, 0x53, + 0xaa, 0x5f, 0x6c, 0x1d, 0x31, 0xdb, 0x51, 0xe5, 0xb4, 0x7a, 0xd6, 0x07, 0x8f, 0x9f, 0x7b, 0xbf, 0xf9, 0x8f, 0xd4, + 0x3a, 0xc0, 0x2a, 0xab, 0xc3, 0x2f, 0xcb, 0x39, 0x6d, 0xbf, 0xd2, 0xcd, 0x85, 0x62, 0x7a, 0xa1, 0xf5, 0x26, 0x6e, + 0xbd, 0xce, 0xe6, 0xc3, 0xb9, 0x56, 0x84, 0x96, 0x97, 0xfa, 0xe2, 0xd3, 0xf3, 0xbf, 0x1d, 0x8d, 0x75, 0xbf, 0xb7, + 0xdd, 0x56, 0xaa, 0xf6, 0x36, 0x12, 0x46, 0xaa, 0xac, 0x77, 0x8c, 0x1d, 0xba, 0xc6, 0x78, 0x34, 0x86, 0x44, 0xb2, + 0x58, 0x9d, 0x02, 0x0e, 0x9d, 0x10, 0xf9, 0x3a, 0x89, 0x3b, 0x75, 0x12, 0xcd, 0x2c, 0x17, 0x41, 0x22, 0x45, 0xfa, + 0x36, 0x20, 0x6a, 0xe1, 0x90, 0x01, 0x0f, 0xe3, 0xd6, 0x64, 0x10, 0xd6, 0x75, 0x2c, 0x13, 0xa1, 0xda, 0xe1, 0xf5, + 0x29, 0xf5, 0x0a, 0x06, 0xd6, 0x14, 0x49, 0x1b, 0x89, 0x68, 0x4b, 0xdd, 0x7f, 0x35, 0xdd, 0x0f, 0xea, 0xcd, 0x8d, + 0xfd, 0x94, 0xb7, 0x51, 0x8b, 0xe6, 0x5e, 0xd4, 0x30, 0xac, 0x46, 0xd6, 0xcc, 0xb0, 0xcd, 0x23, 0xff, 0x23, 0x29, + 0x70, 0xe8, 0x3a, 0x00, 0xd0, 0x7e, 0x80, 0x36, 0x28, 0x86, 0x11, 0x98, 0xfd, 0xb8, 0x68, 0x23, 0xb5, 0x29, 0xbf, + 0x30, 0xab, 0x6e, 0x39, 0xb2, 0x5b, 0x04, 0x61, 0x4d, 0x96, 0x01, 0xe0, 0x2b, 0x1b, 0x6e, 0x03, 0x50, 0x34, 0x82, + 0xb2, 0xa9, 0x17, 0xb8, 0x2d, 0xfe, 0x1d, 0x9a, 0x35, 0x8f, 0x07, 0x45, 0xcf, 0x88, 0x0a, 0x2a, 0xcb, 0x08, 0xcf, + 0xbf, 0xba, 0x50, 0xae, 0xa4, 0xe1, 0x5b, 0x7a, 0x6e, 0x65, 0x6b, 0xce, 0x7b, 0xbb, 0x8a, 0xfe, 0xb9, 0x5d, 0xcf, + 0xaf, 0xd9, 0x06, 0xcb, 0x08, 0x8f, 0xdc, 0x7e, 0xf9, 0x91, 0x6e, 0xc2, 0xb1, 0x8f, 0x22, 0x3b, 0x2c, 0x4c, 0x41, + 0x70, 0xa8, 0x35, 0xda, 0x94, 0xfc, 0x62, 0x0f, 0x28, 0xcc, 0x1e, 0x36, 0x1c, 0x30, 0xd8, 0x54, 0x19, 0x26, 0x91, + 0x3d, 0x05, 0xbf, 0x6c, 0x83, 0x18, 0x4c, 0xa2, 0xa1, 0x24, 0xe0, 0xa6, 0x74, 0xcd, 0x09, 0xd9, 0x99, 0x53, 0xff, + 0x51, 0x23, 0xac, 0xe7, 0x09, 0x43, 0xd4, 0xc3, 0x34, 0xd3, 0xca, 0xaa, 0x59, 0x78, 0x6b, 0x58, 0xea, 0x1a, 0x82, + 0x94, 0xb2, 0x48, 0xe8, 0x7d, 0xeb, 0x04, 0xb5, 0x81, 0x09, 0xd3, 0x3d, 0x2a, 0xe3, 0xf0, 0x71, 0x9d, 0x16, 0x67, + 0xa2, 0x18, 0xad, 0xac, 0xd7, 0x18, 0xcb, 0xdc, 0x78, 0xcd, 0xcb, 0xa2, 0x99, 0x17, 0xbd, 0x3e, 0xd9, 0x90, 0xf0, + 0xfc, 0x39, 0x14, 0x89, 0x62, 0x63, 0x86, 0xda, 0x8d, 0xe7, 0xc4, 0xa7, 0xf9, 0x46, 0x53, 0x24, 0xb6, 0xf4, 0x9a, + 0x61, 0x25, 0xb3, 0x95, 0x30, 0xbd, 0x5a, 0x95, 0x19, 0xe1, 0xba, 0xc3, 0xb1, 0xcf, 0xf4, 0x70, 0x34, 0x05, 0x3f, + 0x02, 0x6c, 0xee, 0x74, 0xe4, 0xc6, 0xc3, 0xff, 0x01, 0xf2, 0xa8, 0xe6, 0xd1, 0x0a, 0xb9, 0x5c, 0x1e, 0x62, 0x13, + 0x0f, 0x35, 0xc7, 0xee, 0xaf, 0x61, 0xfd, 0xe7, 0x2d, 0xba, 0xa2, 0xed, 0x85, 0x56, 0x29, 0x91, 0x83, 0x36, 0xb1, + 0x2e, 0xdb, 0xc3, 0xa0, 0xb5, 0x88, 0x84, 0x13, 0x55, 0x9d, 0xf5, 0xc2, 0x3c, 0xce, 0xa5, 0xff, 0xc7, 0x4f, 0xb5, + 0x15, 0x04, 0x01, 0x61, 0x7e, 0x17, 0xbb, 0x13, 0x48, 0x71, 0x3e, 0x6b, 0xc8, 0x8c, 0x13, 0xfe, 0x95, 0x27, 0x7c, + 0x4f, 0x33, 0xb2, 0x92, 0xf9, 0x97, 0x32, 0x89, 0x4e, 0x71, 0xd5, 0x1c, 0xf1, 0x3a, 0x65, 0x0c, 0xa6, 0xb7, 0x0c, + 0x72, 0x2e, 0xc8, 0x67, 0x68, 0xca, 0xb9, 0x23, 0xeb, 0x4d, 0x81, 0xa7, 0x11, 0x18, 0x43, 0x01, 0xb2, 0x42, 0x57, + 0x99, 0x9d, 0x76, 0x86, 0x31, 0x30, 0xe4, 0x5e, 0x01, 0x1e, 0x5c, 0x09, 0xa0, 0x92, 0x81, 0x5f, 0xc5, 0x9e, 0x95, + 0x98, 0x7f, 0xb9, 0xa8, 0xd0, 0xee, 0x35, 0xc0, 0x5f, 0xa1, 0xe0, 0x12, 0xd5, 0x42, 0x81, 0x13, 0x01, 0x5d, 0x12, + 0x5c, 0xa0, 0x39, 0x89, 0x10, 0x5b, 0x0d, 0x08, 0x6a, 0x1b, 0xb7, 0x5c, 0x1c, 0xf0, 0xce, 0x7b, 0x59, 0xf1, 0xd5, + 0x75, 0x01, 0x1c, 0x0f, 0xf3, 0xfc, 0xdb, 0xca, 0x5c, 0xf6, 0x73, 0x02, 0x11, 0x17, 0x16, 0x66, 0x8e, 0x28, 0xe7, + 0xb4, 0x20, 0xcb, 0x5c, 0x84, 0x32, 0x5e, 0x6b, 0x98, 0xec, 0x84, 0xb3, 0x8c, 0xb4, 0xfb, 0xd0, 0x99, 0x48, 0x5f, + 0xbc, 0xcb, 0x20, 0xec, 0x90, 0xb5, 0x27, 0x52, 0xb9, 0x9d, 0x45, 0x13, 0xd0, 0xe7, 0x5b, 0x5f, 0xbb, 0xbe, 0xa7, + 0x8d, 0x35, 0x98, 0xbc, 0x6b, 0x36, 0x45, 0x0c, 0xa5, 0xf9, 0x62, 0x82, 0x99, 0xa7, 0xfd, 0x31, 0xcf, 0xc1, 0x22, + 0x7d, 0x99, 0xf4, 0xb2, 0x62, 0xa2, 0x3e, 0xb2, 0x83, 0x60, 0x91, 0x24, 0x86, 0xdc, 0x1a, 0x74, 0x14, 0x54, 0xe4, + 0x6d, 0xb4, 0x90, 0x15, 0xcb, 0x9a, 0x83, 0x9d, 0xf7, 0xdf, 0xb9, 0x62, 0x65, 0x62, 0x60, 0xc7, 0x18, 0x63, 0x9e, + 0x3c, 0x5a, 0xe3, 0xad, 0xdd, 0x5b, 0xae, 0xd0, 0x31, 0x69, 0xc0, 0x49, 0x21, 0x32, 0x2e, 0x5d, 0x62, 0xae, 0xad, + 0x99, 0x2d, 0x6b, 0x6a, 0xe1, 0x3f, 0x3d, 0x2b, 0x63, 0x60, 0xcc, 0x13, 0x41, 0x7e, 0x2e, 0xad, 0x76, 0xcc, 0x9b, + 0xb0, 0x57, 0x02, 0x4e, 0x9d, 0xcb, 0x5c, 0x12, 0x01, 0x5e, 0x2a, 0xfd, 0x4f, 0xdf, 0xfd, 0x0a, 0x09, 0x30, 0x28, + 0x1b, 0x7d, 0x91, 0x56, 0x04, 0x8f, 0x56, 0x83, 0x2f, 0x06, 0x96, 0x88, 0x82, 0x0b, 0xa3, 0x05, 0xde, 0x32, 0xfa, + 0xc2, 0x46, 0x1b, 0x5c, 0xa1, 0x19, 0xe9, 0xb8, 0x4c, 0xed, 0xa3, 0x7d, 0x1f, 0xc0, 0xae, 0x80, 0xd9, 0xda, 0x35, + 0x20, 0x88, 0x96, 0xba, 0x30, 0xa8, 0x48, 0xe1, 0x5a, 0xeb, 0x84, 0xf1, 0x3a, 0x71, 0xdb, 0x38, 0xdc, 0x87, 0x00, + 0x8c, 0xc0, 0x5d, 0xd1, 0x03, 0x0b, 0x44, 0xa5, 0x1e, 0x1d, 0x8d, 0x4b, 0x79, 0x51, 0x97, 0x18, 0xc9, 0x74, 0xdd, + 0x0f, 0xdb, 0xdf, 0xbb, 0x87, 0xbd, 0xf8, 0x94, 0xae, 0x07, 0xda, 0x6d, 0xe9, 0xa5, 0xe8, 0xa1, 0x87, 0xd6, 0x3d, + 0x68, 0x5e, 0x81, 0xde, 0xcb, 0x66, 0x93, 0x44, 0xdd, 0x17, 0xf4, 0xb6, 0x61, 0xfb, 0x5f, 0xda, 0xd0, 0xc0, 0x50, + 0xb5, 0x98, 0x89, 0x52, 0x91, 0x05, 0x61, 0x2c, 0xf4, 0xf7, 0x31, 0xdd, 0x2b, 0xb3, 0x23, 0x5f, 0x31, 0x37, 0xe3, + 0x30, 0x0f, 0x1a, 0xbd, 0x4b, 0xd5, 0x1f, 0x8c, 0xb9, 0x33, 0x34, 0x04, 0x3d, 0x28, 0x0f, 0x90, 0x06, 0x89, 0x41, + 0xab, 0x52, 0x28, 0xe0, 0x12, 0x52, 0xc9, 0x7e, 0x77, 0xf4, 0xcb, 0x4d, 0xbb, 0x6a, 0x0c, 0xc1, 0xa7, 0x77, 0x0e, + 0x10, 0x50, 0xb0, 0x8a, 0x83, 0x34, 0x48, 0xde, 0x90, 0xc3, 0x88, 0xe9, 0x3b, 0x0e, 0x70, 0x75, 0xe0, 0x77, 0xa5, + 0xc4, 0x79, 0x46, 0x08, 0x3d, 0xfe, 0x2f, 0x54, 0xbd, 0x6f, 0x2f, 0x85, 0x19, 0x94, 0x0d, 0xcf, 0x6b, 0x6a, 0x7a, + 0x36, 0xb4, 0x85, 0xfd, 0xbf, 0x4b, 0xc5, 0xfc, 0x96, 0x79, 0xa9, 0xc4, 0x96, 0xca, 0x07, 0x8c, 0xc1, 0x0f, 0x7f, + 0x78, 0x53, 0x73, 0xb1, 0xe4, 0x8d, 0x92, 0xca, 0x82, 0xda, 0xb9, 0xb9, 0xce, 0x6c, 0x60, 0x4f, 0x39, 0x29, 0xb6, + 0xa1, 0x9f, 0x86, 0xfb, 0x21, 0xe7, 0x0a, 0xe8, 0x38, 0xd5, 0x18, 0x2e, 0x24, 0xc1, 0xae, 0x83, 0x9d, 0x8c, 0x6a, + 0x73, 0xc3, 0xe0, 0x5a, 0x89, 0xef, 0x80, 0xb7, 0x03, 0x4c, 0x81, 0xef, 0xe7, 0x7b, 0xf9, 0x33, 0x42, 0xec, 0xb1, + 0x4c, 0x24, 0x01, 0x54, 0x62, 0x45, 0x4f, 0x39, 0x94, 0xb7, 0x8a, 0x6f, 0x65, 0x9e, 0x6a, 0xee, 0xcd, 0xd5, 0x65, + 0x06, 0x5a, 0x2c, 0x32, 0x8a, 0x2f, 0xc0, 0x8e, 0xea, 0x59, 0xfc, 0x17, 0xfa, 0x09, 0x8c, 0xe8, 0xc2, 0xc9, 0x4d, + 0x05, 0x8c, 0x6d, 0x23, 0x1d, 0x4e, 0x75, 0x2f, 0x51, 0xc4, 0x65, 0xa3, 0x11, 0x83, 0x37, 0x58, 0xe2, 0x95, 0x56, + 0x69, 0x7b, 0x4c, 0x82, 0x97, 0x8a, 0x09, 0x5b, 0x8c, 0x0a, 0xda, 0x48, 0x5f, 0x8c, 0x34, 0xd7, 0xa8, 0xdf, 0x8f, + 0xd7, 0xf6, 0x4b, 0x2b, 0x74, 0xcf, 0xe6, 0xa3, 0x82, 0xa0, 0xf1, 0x86, 0x00, 0x02, 0xec, 0x5e, 0x82, 0xae, 0xb8, + 0x63, 0xc8, 0x54, 0xc9, 0xe0, 0x3b, 0x85, 0x47, 0xac, 0xfa, 0xd3, 0xcd, 0xcf, 0xe5, 0x96, 0x95, 0x21, 0x65, 0xdb, + 0xdb, 0xdc, 0xbc, 0x1f, 0x61, 0xd3, 0x38, 0xc3, 0x88, 0x19, 0xf5, 0x0c, 0x18, 0xc3, 0x12, 0x00, 0xab, 0xb8, 0xa0, + 0xde, 0x3c, 0x74, 0x99, 0xdd, 0x30, 0xbd, 0x5e, 0xe9, 0x69, 0x1a, 0x44, 0xb0, 0xb7, 0xec, 0x4d, 0x12, 0xb6, 0x2b, + 0x1b, 0x2f, 0xa1, 0x63, 0xde, 0x7a, 0xc8, 0x59, 0x42, 0xdc, 0x10, 0xd6, 0xc2, 0xdd, 0x4b, 0xc4, 0x7d, 0xee, 0x62, + 0x7d, 0x22, 0x12, 0x1e, 0xf5, 0x02, 0xdd, 0xcb, 0x97, 0x15, 0xc8, 0x99, 0x66, 0xe9, 0xfd, 0x2f, 0x58, 0xeb, 0xca, + 0x65, 0x83, 0x66, 0xa0, 0x47, 0x07, 0xc5, 0x44, 0xcb, 0xe0, 0x02, 0x54, 0x14, 0xbb, 0x9a, 0x58, 0xe6, 0xd1, 0x04, + 0x28, 0xa4, 0x2c, 0x29, 0x4d, 0x26, 0x33, 0x56, 0x50, 0x60, 0x1a, 0xec, 0xbc, 0x78, 0xc0, 0xa0, 0x62, 0x93, 0xa9, + 0x4c, 0xac, 0x2c, 0x24, 0x09, 0x0e, 0x66, 0x85, 0xe6, 0x7a, 0x95, 0xdb, 0x41, 0x08, 0x59, 0x1d, 0x60, 0xdf, 0xac, + 0x64, 0x02, 0x6a, 0x1f, 0xe6, 0xb1, 0x63, 0x54, 0x52, 0x40, 0xbf, 0x10, 0x42, 0x6e, 0x77, 0x87, 0x3b, 0x6a, 0x8e, + 0x4e, 0x2f, 0x72, 0x97, 0x0c, 0x29, 0xf2, 0xdd, 0x17, 0x81, 0x63, 0x66, 0xe4, 0x32, 0xab, 0x84, 0xa8, 0x7b, 0x2b, + 0x5a, 0xc6, 0x2f, 0xe8, 0xef, 0x5c, 0xfa, 0x84, 0xd2, 0x82, 0x58, 0x74, 0x38, 0xa8, 0x01, 0xb2, 0xcd, 0x0e, 0x73, + 0x58, 0xda, 0xcd, 0x0b, 0x4b, 0xf0, 0x59, 0xfe, 0x36, 0xf6, 0xec, 0x27, 0x4f, 0xd7, 0xd5, 0x37, 0x5f, 0xc3, 0x28, + 0xe6, 0x5e, 0x6f, 0x34, 0x79, 0xbb, 0xc3, 0x08, 0xe1, 0x44, 0xda, 0xed, 0xf6, 0xd0, 0xc3, 0x15, 0x24, 0x60, 0x83, + 0x83, 0x4b, 0xaf, 0x6e, 0x9f, 0xac, 0x7f, 0xd5, 0x85, 0x39, 0xff, 0x99, 0x06, 0x70, 0x08, 0x19, 0x42, 0xda, 0x04, + 0x41, 0x0f, 0x43, 0x05, 0x6b, 0x2a, 0xb6, 0x32, 0x96, 0x25, 0xfd, 0x80, 0x58, 0xdf, 0xe0, 0xb2, 0x95, 0x65, 0xd4, + 0x42, 0xf0, 0xfc, 0x17, 0x07, 0x08, 0xde, 0x16, 0x9c, 0xfd, 0xd7, 0xc8, 0xc2, 0xf7, 0x8e, 0x0d, 0x52, 0xfa, 0x58, + 0x79, 0x67, 0xb8, 0x6c, 0xaa, 0xd9, 0xc0, 0x8e, 0xac, 0x5c, 0xef, 0xe9, 0x4d, 0x85, 0x32, 0xda, 0x8c, 0x1a, 0xd5, + 0xa6, 0xcc, 0xd2, 0x18, 0xbe, 0x47, 0xb3, 0xa8, 0x4f, 0x52, 0xbd, 0x61, 0x6f, 0xb6, 0x16, 0xb5, 0x83, 0xa9, 0xc6, + 0xf0, 0xde, 0xfe, 0xa9, 0xd9, 0x04, 0x81, 0xd2, 0x09, 0x76, 0xdc, 0x81, 0x8f, 0x94, 0x9e, 0x22, 0xa6, 0x1d, 0x44, + 0xfc, 0xbd, 0x95, 0xec, 0xe8, 0xf7, 0x38, 0x8a, 0x9f, 0x91, 0x31, 0x00, 0x31, 0xba, 0x2d, 0x4c, 0x41, 0xa4, 0x84, + 0xe6, 0x07, 0x2f, 0x14, 0xc4, 0x53, 0xa2, 0x01, 0x50, 0x76, 0x9b, 0xba, 0x02, 0xfb, 0x8c, 0x2f, 0x59, 0x5b, 0xcd, + 0x61, 0x3a, 0xd0, 0xb2, 0x60, 0xbd, 0xcb, 0xe9, 0x39, 0x53, 0x96, 0x5c, 0x6b, 0x37, 0x28, 0xc4, 0xfd, 0x57, 0xcb, + 0xbb, 0x05, 0x96, 0xb3, 0xc7, 0xbf, 0xdf, 0xc8, 0x4f, 0xdc, 0x2a, 0x1b, 0xc2, 0xac, 0x87, 0x4c, 0x91, 0x25, 0x39, + 0x0c, 0x32, 0xad, 0xa5, 0xfb, 0x07, 0x32, 0x68, 0x6e, 0xb7, 0xf5, 0x14, 0xd6, 0xe4, 0xf9, 0xe0, 0xcb, 0x0e, 0x64, + 0x67, 0x0a, 0x61, 0xa0, 0x7f, 0xd9, 0xde, 0x5e, 0x80, 0xce, 0x4d, 0x86, 0xb8, 0xbb, 0xe2, 0x8d, 0x73, 0x51, 0xde, + 0xf8, 0xe5, 0xb6, 0x13, 0x56, 0xd0, 0xb6, 0x88, 0xa6, 0x41, 0xb5, 0xfc, 0x3d, 0xa2, 0xbc, 0xd8, 0xac, 0xb6, 0x7c, + 0x3e, 0x55, 0x46, 0x4f, 0x2f, 0x41, 0x37, 0xe8, 0x07, 0x43, 0xc4, 0xb7, 0x9f, 0xb5, 0xe3, 0x23, 0xd3, 0x96, 0x3f, + 0xb5, 0xed, 0x19, 0x22, 0xfa, 0xd9, 0xee, 0x11, 0xed, 0xd8, 0x03, 0x68, 0x78, 0x58, 0xa9, 0xa1, 0x83, 0xde, 0x43, + 0xc1, 0x3c, 0xc5, 0x5b, 0x90, 0xc3, 0xe6, 0xc1, 0xf2, 0x0e, 0x10, 0xd9, 0x42, 0xb9, 0x64, 0x6f, 0x21, 0xbd, 0xf3, + 0xf6, 0xcc, 0xc9, 0xe0, 0x91, 0x9e, 0x20, 0x9e, 0x22, 0x80, 0x74, 0x0c, 0x26, 0xbb, 0x75, 0xa9, 0xf5, 0x6c, 0xa2, + 0x00, 0x3b, 0xa7, 0x70, 0x1a, 0xf3, 0x5c, 0xd2, 0x08, 0x82, 0x3d, 0x6b, 0x12, 0x69, 0x09, 0x51, 0xe8, 0xa3, 0xb3, + 0x6d, 0xfb, 0x24, 0x2f, 0x23, 0x5f, 0x87, 0xd8, 0xac, 0xd2, 0xdf, 0x58, 0xe5, 0xc4, 0xd5, 0x23, 0x9f, 0xcf, 0x5d, + 0xe8, 0xe7, 0xcc, 0x20, 0x42, 0xbb, 0xb0, 0x92, 0xd1, 0xa8, 0xc8, 0x34, 0x7a, 0x45, 0xb2, 0x97, 0x0a, 0x21, 0x19, + 0x46, 0x37, 0x46, 0xb1, 0x87, 0x23, 0x67, 0x53, 0xc9, 0x12, 0x76, 0x61, 0x89, 0xf3, 0x5f, 0xea, 0x0c, 0xf4, 0x52, + 0x15, 0x4d, 0xe6, 0xa2, 0x9c, 0x6b, 0x87, 0x34, 0x19, 0x00, 0x43, 0x8d, 0xb7, 0x09, 0x9e, 0xf6, 0xa8, 0xc6, 0xab, + 0x56, 0xe4, 0x48, 0xd8, 0x7c, 0x5c, 0xc4, 0x8e, 0xf1, 0x80, 0x3c, 0x62, 0x1c, 0x0f, 0x3e, 0xc7, 0x83, 0x06, 0x48, + 0xfe, 0x44, 0x0a, 0x3e, 0x7a, 0x5e, 0x31, 0x07, 0xb3, 0x0d, 0x6c, 0xcf, 0x44, 0x53, 0x05, 0xb3, 0x93, 0xf5, 0x1e, + 0x50, 0x47, 0xc5, 0x50, 0x38, 0x32, 0xec, 0xc1, 0x70, 0xa6, 0xde, 0xb1, 0xf5, 0x39, 0x3b, 0x68, 0x79, 0x50, 0x25, + 0x19, 0x08, 0x5c, 0x7c, 0x18, 0x71, 0x8d, 0x4f, 0xea, 0x05, 0xd0, 0x1c, 0x79, 0xa5, 0xc5, 0xc7, 0xa3, 0x61, 0xc2, + 0x11, 0x43, 0x46, 0x7f, 0xb4, 0x31, 0xd5, 0x90, 0x6e, 0x97, 0xae, 0x77, 0x13, 0xbe, 0x4a, 0xc9, 0xd2, 0xcd, 0x51, + 0xf6, 0x9a, 0xc6, 0x03, 0xcd, 0x75, 0x33, 0xdb, 0x97, 0x7f, 0xc7, 0x74, 0x8e, 0xcc, 0x45, 0xc2, 0xba, 0x29, 0xb7, + 0xa8, 0xe3, 0x2e, 0x3e, 0x1c, 0x8e, 0x8c, 0x61, 0x7b, 0xf0, 0x44, 0xee, 0x30, 0xc7, 0xb1, 0xbf, 0xb2, 0xe0, 0x46, + 0xe9, 0x25, 0xc7, 0xe2, 0xab, 0xd9, 0x84, 0x2c, 0x66, 0x29, 0x50, 0xb1, 0xea, 0xb7, 0x01, 0xb6, 0xd8, 0x8a, 0x5a, + 0x27, 0x51, 0xef, 0x33, 0x8d, 0x98, 0x5b, 0xb6, 0x3c, 0x22, 0x08, 0xf2, 0x8d, 0xac, 0xa6, 0x79, 0xd4, 0x58, 0x06, + 0xa8, 0x6b, 0x12, 0x8b, 0x5a, 0xee, 0x50, 0x90, 0x59, 0xe8, 0x20, 0xa4, 0xd7, 0x29, 0x8c, 0x47, 0x2e, 0x57, 0xc8, + 0x74, 0xa9, 0xf3, 0x80, 0x17, 0x2b, 0xc7, 0x46, 0xbf, 0xfe, 0x78, 0x20, 0xaf, 0x48, 0xc4, 0x72, 0x82, 0x2f, 0xe1, + 0xd2, 0x98, 0x31, 0x90, 0x4c, 0xb4, 0x4f, 0x45, 0x2b, 0xf6, 0x63, 0x44, 0x5d, 0x48, 0xf4, 0x58, 0x70, 0x44, 0xb2, + 0x23, 0x61, 0x7f, 0x28, 0x8a, 0x21, 0x89, 0xc7, 0x9c, 0x63, 0x1a, 0x78, 0xdf, 0x16, 0xbd, 0xed, 0x70, 0x68, 0x5b, + 0x94, 0xd7, 0x8a, 0x0b, 0x74, 0xca, 0x92, 0x1b, 0xe0, 0x25, 0xaf, 0x7e, 0xc2, 0xee, 0x1a, 0x07, 0xe5, 0xeb, 0xe2, + 0xee, 0xed, 0x26, 0xc1, 0xc0, 0x3b, 0x88, 0xf3, 0x7a, 0x19, 0xc5, 0xf1, 0xbb, 0x5d, 0xf0, 0xea, 0x98, 0xcf, 0x08, + 0x18, 0x3c, 0x42, 0x3a, 0x91, 0xed, 0x35, 0x27, 0x78, 0xf8, 0xa1, 0xd4, 0x1f, 0x0b, 0x28, 0x67, 0x85, 0xbf, 0x51, + 0xa6, 0xb6, 0x8d, 0x2e, 0xa4, 0xe4, 0xe3, 0x52, 0x7a, 0x17, 0x62, 0xc4, 0x80, 0x5c, 0xed, 0xca, 0xf7, 0x62, 0x55, + 0x7a, 0x54, 0x6a, 0xc4, 0x17, 0xf4, 0x8a, 0xa1, 0x35, 0x46, 0xbd, 0xe3, 0x66, 0x9d, 0x08, 0x13, 0x83, 0xaf, 0xa8, + 0x9d, 0xb4, 0xcd, 0x98, 0x08, 0x81, 0x34, 0x59, 0xb4, 0x7e, 0xb2, 0x88, 0xc2, 0x42, 0x28, 0x62, 0xc2, 0x12, 0x2d, + 0x87, 0x04, 0x04, 0x91, 0x21, 0x8d, 0xf0, 0x98, 0xbb, 0x96, 0x03, 0xe3, 0x01, 0x8c, 0xa5, 0xb8, 0xf7, 0x8f, 0xaf, + 0x46, 0x30, 0x05, 0x11, 0x3c, 0xd5, 0x95, 0x17, 0x49, 0x43, 0x63, 0x35, 0xcc, 0x43, 0x73, 0x21, 0x47, 0x19, 0x78, + 0x33, 0x27, 0x58, 0x5c, 0xb5, 0x32, 0xc2, 0x4d, 0x7f, 0xb6, 0xfb, 0x50, 0xcf, 0x9d, 0x83, 0x36, 0x27, 0xcb, 0x59, + 0xb2, 0xd2, 0x1f, 0x6d, 0x4f, 0x10, 0x81, 0xc8, 0x60, 0x06, 0x52, 0x57, 0x04, 0x42, 0x42, 0x1c, 0x45, 0x92, 0x9b, + 0x27, 0x87, 0x08, 0xc4, 0xe7, 0xe5, 0x17, 0xfa, 0x20, 0x03, 0x4a, 0x64, 0xbd, 0xbe, 0x59, 0x01, 0xd3, 0x13, 0x4e, + 0x21, 0xc5, 0x1e, 0xab, 0x82, 0x41, 0x46, 0x24, 0xcc, 0x16, 0x27, 0x0c, 0x99, 0xd7, 0x57, 0xbf, 0x77, 0x38, 0x35, + 0x3c, 0xe8, 0x00, 0x30, 0xaa, 0x1c, 0x41, 0x21, 0x92, 0x3f, 0x29, 0x60, 0x58, 0x21, 0xe1, 0xdd, 0x9b, 0xe4, 0xc2, + 0x89, 0x6c, 0x63, 0x55, 0x79, 0x25, 0xac, 0x7e, 0xa8, 0x81, 0x67, 0x24, 0x04, 0xa6, 0xa8, 0x18, 0xdb, 0xbf, 0xff, + 0x59, 0x55, 0x49, 0x1a, 0x2f, 0x92, 0x94, 0x7e, 0xed, 0x71, 0x5b, 0xa8, 0x85, 0x86, 0x49, 0x9a, 0x1d, 0xea, 0x6d, + 0x67, 0x12, 0x39, 0xe3, 0x10, 0x72, 0x16, 0x62, 0x00, 0x88, 0x97, 0xc1, 0xe0, 0x43, 0xeb, 0x63, 0xda, 0x01, 0xa7, + 0x5f, 0xbb, 0x67, 0x65, 0xf4, 0xa3, 0x35, 0xcf, 0xe8, 0xc2, 0xf9, 0xe9, 0x51, 0xad, 0x26, 0x7e, 0x48, 0xe0, 0xac, + 0x84, 0x5e, 0x8a, 0x59, 0x35, 0x1e, 0x67, 0xae, 0xf8, 0x7a, 0x74, 0x6a, 0xab, 0x40, 0xac, 0x2a, 0x0d, 0x37, 0xc2, + 0x78, 0xf6, 0x40, 0xb2, 0x79, 0x14, 0x7e, 0xa4, 0x92, 0x71, 0xaf, 0x38, 0xc2, 0x0c, 0xd1, 0x06, 0x7a, 0xce, 0x0b, + 0x58, 0xce, 0xca, 0x22, 0x19, 0x79, 0x1d, 0x0a, 0x9a, 0xde, 0x38, 0xe4, 0x21, 0x53, 0x1c, 0x9c, 0xc9, 0x0a, 0x9f, + 0xd3, 0xa3, 0xe6, 0xc6, 0x28, 0xab, 0x60, 0x63, 0x34, 0x9f, 0x96, 0x9e, 0x3c, 0x90, 0x4d, 0x63, 0x9a, 0xd2, 0xa2, + 0xa4, 0x21, 0x71, 0xa9, 0x6a, 0xe6, 0x68, 0x1e, 0x98, 0x43, 0xac, 0x6f, 0x5f, 0x70, 0xf6, 0x88, 0xe7, 0xe3, 0x82, + 0x14, 0xa4, 0xcd, 0xf4, 0xa8, 0xe4, 0xfa, 0xf3, 0x33, 0x20, 0xac, 0xbc, 0x7d, 0xb0, 0xe1, 0xd7, 0x15, 0x12, 0xd9, + 0xde, 0xbc, 0x1c, 0xa0, 0x68, 0xc2, 0xaf, 0x1d, 0x6c, 0xd6, 0x57, 0x96, 0x38, 0xbe, 0x35, 0x5b, 0x15, 0x44, 0x4e, + 0x66, 0x46, 0xbf, 0xee, 0x05, 0xac, 0x15, 0x61, 0xca, 0xd9, 0xd9, 0xe6, 0x1a, 0xa0, 0xa5, 0xe0, 0x38, 0x2a, 0x46, + 0x7c, 0x54, 0xcf, 0x48, 0x65, 0x26, 0xbd, 0xc6, 0x42, 0x97, 0xe1, 0x0b, 0x35, 0xf5, 0x5a, 0xd4, 0x7c, 0xe4, 0x43, + 0x46, 0x84, 0x9d, 0x46, 0xb8, 0xf8, 0xc6, 0xc0, 0x6b, 0x79, 0x1a, 0x9d, 0x07, 0x7a, 0x2f, 0x36, 0x5b, 0x9e, 0xf8, + 0xee, 0xba, 0x4d, 0x8e, 0x8f, 0xb1, 0x35, 0x5b, 0x36, 0x63, 0xf9, 0xe9, 0xf5, 0x27, 0xa3, 0x2a, 0xa1, 0x66, 0xeb, + 0xbe, 0x9f, 0xba, 0x7e, 0x3d, 0x34, 0xcf, 0xf3, 0x36, 0x6d, 0x1b, 0xe7, 0xe6, 0xde, 0x80, 0x6c, 0x2f, 0x0a, 0xe6, + 0xb9, 0xd0, 0x9c, 0x36, 0xb4, 0x3e, 0xbd, 0x84, 0x59, 0x99, 0xd9, 0xd0, 0x76, 0x7d, 0xad, 0x7f, 0xa9, 0x28, 0x8c, + 0xd8, 0xfa, 0x80, 0x13, 0x51, 0x4a, 0x54, 0x5a, 0xe5, 0xe7, 0x4b, 0x6f, 0x45, 0x48, 0x9e, 0xcb, 0x7e, 0x19, 0x4d, + 0xff, 0x09, 0xbd, 0x56, 0x26, 0x42, 0xf1, 0x35, 0x73, 0xee, 0x59, 0x2d, 0xf9, 0xd7, 0x52, 0xb1, 0x74, 0xac, 0x71, + 0xd5, 0x7a, 0x5e, 0xc6, 0x93, 0x6b, 0xb8, 0x3e, 0x4e, 0xd1, 0x7a, 0xc6, 0x48, 0x7f, 0x0e, 0xae, 0x44, 0xa4, 0x16, + 0x97, 0xbe, 0x03, 0x73, 0x25, 0x0a, 0xc9, 0xd5, 0x54, 0x7a, 0xf6, 0x56, 0xf5, 0x38, 0xd1, 0x3c, 0x23, 0x73, 0xef, + 0xca, 0xbe, 0x59, 0x95, 0xd6, 0x5e, 0x93, 0x57, 0x29, 0x1c, 0x9f, 0xe0, 0x3a, 0xb9, 0x77, 0x4f, 0x31, 0x25, 0x88, + 0x10, 0xba, 0x38, 0xed, 0x0b, 0xbf, 0x42, 0x38, 0xe0, 0xf5, 0xd4, 0x69, 0xdd, 0x5e, 0x52, 0x2d, 0x41, 0x9c, 0xab, + 0x3b, 0x9c, 0xb3, 0x5b, 0x73, 0xb6, 0x90, 0x1d, 0x67, 0x59, 0xa1, 0x9e, 0x6e, 0x0e, 0x19, 0x76, 0x28, 0x78, 0x86, + 0x5c, 0xb7, 0x57, 0xd3, 0x67, 0x23, 0x32, 0x71, 0xab, 0xdd, 0xbe, 0x45, 0x72, 0x79, 0x1a, 0x00, 0xc1, 0x18, 0xfe, + 0x79, 0xd1, 0x9e, 0x8c, 0xce, 0x84, 0x05, 0xb3, 0x21, 0x90, 0x06, 0x8c, 0x19, 0x24, 0xc2, 0xe3, 0x3f, 0x91, 0xff, + 0x57, 0x93, 0xdf, 0x78, 0x31, 0xce, 0xa9, 0xe3, 0x37, 0xef, 0x35, 0xa0, 0x24, 0x66, 0xc1, 0x89, 0x0d, 0xaf, 0x82, + 0x6c, 0x99, 0xb6, 0x81, 0x63, 0xb0, 0x4c, 0x7f, 0x0c, 0xca, 0xd8, 0x0b, 0x48, 0x32, 0xf1, 0x8e, 0x84, 0xea, 0x74, + 0xd6, 0x5e, 0x1c, 0x09, 0x5c, 0xce, 0x99, 0xe4, 0xe8, 0x02, 0x1b, 0x33, 0xc1, 0xd3, 0xee, 0x30, 0xd2, 0xcf, 0x50, + 0xbc, 0x96, 0xab, 0xdb, 0xc8, 0x00, 0xa1, 0x04, 0x13, 0xea, 0x13, 0xd2, 0xfe, 0xed, 0xe1, 0x88, 0x81, 0x44, 0x81, + 0x26, 0x0b, 0x76, 0x80, 0x4d, 0xa1, 0xae, 0xdd, 0x3c, 0x96, 0x36, 0xc6, 0x23, 0x69, 0x94, 0x61, 0x71, 0x59, 0x91, + 0xd1, 0x4a, 0x5f, 0x39, 0x9a, 0x2d, 0x1c, 0xfb, 0xce, 0x62, 0xb0, 0xd0, 0x86, 0xab, 0x97, 0x09, 0xba, 0x9f, 0x3a, + 0xf2, 0xca, 0xff, 0x6a, 0xb2, 0xea, 0xd6, 0x67, 0x6f, 0xf2, 0x95, 0x43, 0x46, 0xdc, 0x5e, 0x3d, 0x7f, 0x8c, 0x47, + 0x4f, 0xb5, 0xd2, 0x87, 0x11, 0x67, 0x18, 0x54, 0xb9, 0x2d, 0x08, 0xcf, 0x6a, 0x32, 0x6c, 0x74, 0x14, 0xf4, 0x03, + 0x4d, 0x09, 0x66, 0xec, 0xc7, 0xd4, 0x04, 0x58, 0xf2, 0xa4, 0xb3, 0xb0, 0xf2, 0x7a, 0x76, 0x1d, 0x6f, 0x73, 0x81, + 0xe5, 0x13, 0x8e, 0x3d, 0xd8, 0xc4, 0x0a, 0x9b, 0x0a, 0x9b, 0x24, 0x2e, 0x3c, 0xb1, 0xb2, 0x8c, 0x78, 0xe1, 0x0a, + 0x5b, 0xa7, 0x3c, 0x95, 0xc2, 0x6e, 0xe8, 0xca, 0xaf, 0xf5, 0xca, 0x8b, 0xd1, 0x79, 0x1d, 0xa3, 0x9b, 0xe4, 0x26, + 0x86, 0x60, 0x30, 0xec, 0x46, 0x4e, 0xfa, 0xf6, 0x40, 0xc9, 0xe0, 0x06, 0x0d, 0xca, 0xd7, 0x91, 0xb5, 0x42, 0x3c, + 0xd7, 0x95, 0x0b, 0x67, 0x9e, 0x00, 0x98, 0x2f, 0xaf, 0x17, 0xda, 0x44, 0x07, 0x3b, 0xbe, 0x9f, 0xf7, 0x05, 0x0b, + 0x78, 0xd9, 0x21, 0x96, 0x95, 0x37, 0x3b, 0xfd, 0x05, 0x6e, 0x38, 0x73, 0x6d, 0x9b, 0x51, 0x6d, 0xa1, 0x97, 0xe8, + 0xc8, 0xdc, 0xb3, 0x64, 0xab, 0x89, 0x80, 0xb3, 0x03, 0xc1, 0xa2, 0x24, 0xe6, 0x09, 0x82, 0x25, 0x7e, 0xc2, 0x03, + 0x59, 0xd8, 0x2f, 0xcd, 0xa5, 0xe8, 0x89, 0xf6, 0xfa, 0xa5, 0xf9, 0x9c, 0x5f, 0x84, 0x43, 0x7c, 0xae, 0x28, 0xeb, + 0xa1, 0xce, 0xe3, 0x20, 0x8a, 0xa3, 0x5f, 0x33, 0x95, 0xd0, 0xfe, 0x31, 0x5a, 0x94, 0x34, 0x76, 0x59, 0xb8, 0xd2, + 0xca, 0x9a, 0x70, 0x95, 0x76, 0x93, 0x41, 0x5e, 0x89, 0x67, 0x5e, 0x65, 0x5d, 0xd6, 0x1c, 0xdf, 0x83, 0xba, 0x1d, + 0x39, 0xfb, 0xac, 0xa1, 0x4a, 0x0e, 0xd0, 0xfe, 0xe0, 0xa1, 0xb3, 0x08, 0x6a, 0x08, 0xae, 0x6e, 0x7c, 0x82, 0x38, + 0xe0, 0x32, 0x08, 0xa9, 0x0c, 0xfb, 0x52, 0xc9, 0xbf, 0x91, 0x32, 0x8a, 0xff, 0xab, 0x34, 0xaf, 0x1e, 0x18, 0x84, + 0xaf, 0xbb, 0x9b, 0x5f, 0x01, 0xb2, 0xb5, 0x30, 0x33, 0xb8, 0xc9, 0x6d, 0x13, 0xf7, 0x45, 0x39, 0x68, 0x1b, 0xac, + 0x97, 0x16, 0xa1, 0x0f, 0x1a, 0x8f, 0x34, 0x61, 0xf5, 0x39, 0x5c, 0x0b, 0x02, 0x37, 0x75, 0xfe, 0x78, 0x3c, 0xc9, + 0xd4, 0x14, 0x9a, 0xc6, 0xee, 0x4c, 0x5a, 0x8e, 0x30, 0x90, 0x30, 0x40, 0x36, 0x3e, 0xb0, 0x6d, 0xe9, 0xf6, 0x66, + 0x11, 0x5c, 0xaf, 0x41, 0x50, 0xca, 0x96, 0x45, 0x07, 0x47, 0x63, 0xb6, 0xc1, 0x9c, 0xee, 0x13, 0x8d, 0xc8, 0xae, + 0x60, 0x38, 0x0b, 0x23, 0xd7, 0x5f, 0x9c, 0x35, 0xeb, 0x2e, 0x28, 0x52, 0x3d, 0xf2, 0xa1, 0xd8, 0x46, 0x00, 0x4f, + 0xa8, 0xf4, 0xf1, 0xc0, 0x23, 0x8a, 0x56, 0x87, 0x14, 0x1e, 0x16, 0x85, 0x43, 0xbe, 0xc1, 0x38, 0x1d, 0xa1, 0x3e, + 0x39, 0x82, 0x31, 0x45, 0x7e, 0xf8, 0x8b, 0x85, 0xf1, 0xb5, 0x7c, 0x81, 0x79, 0x5a, 0x69, 0x11, 0x77, 0x3d, 0xe5, + 0xb6, 0xcf, 0xed, 0xe1, 0x13, 0x2f, 0x21, 0x1b, 0xa1, 0xdf, 0x47, 0x7e, 0xd4, 0x6c, 0xfd, 0xe7, 0x01, 0xe6, 0xdb, + 0xc1, 0x1a, 0x4c, 0x38, 0x2a, 0x78, 0xa4, 0x1f, 0x5d, 0x99, 0x76, 0x83, 0x82, 0xf5, 0x21, 0x94, 0x32, 0x3a, 0x71, + 0xd0, 0xed, 0x6a, 0xe6, 0xbf, 0x3c, 0x76, 0x31, 0x02, 0x59, 0x48, 0xe2, 0xe7, 0xa5, 0xec, 0xdb, 0xba, 0x0c, 0x6b, + 0x69, 0xe9, 0xe6, 0x69, 0x22, 0x86, 0xcb, 0x24, 0xa8, 0xbc, 0xea, 0x11, 0x11, 0x23, 0x52, 0x16, 0x4c, 0xbd, 0x8c, + 0xbf, 0xe3, 0x3b, 0x63, 0x17, 0xb5, 0x6e, 0x23, 0xb5, 0x6e, 0xaf, 0x7a, 0xb3, 0xb5, 0xeb, 0xc3, 0x36, 0x0e, 0xf0, + 0xde, 0xd2, 0x4f, 0x50, 0xa0, 0xf1, 0x4a, 0x3b, 0xfa, 0xed, 0x40, 0x4c, 0xf8, 0x87, 0xd8, 0x35, 0x89, 0xee, 0x0b, + 0x86, 0x2b, 0xb5, 0xc9, 0xda, 0x06, 0xc6, 0x08, 0xc5, 0x5a, 0x9e, 0x47, 0x70, 0x9e, 0x8d, 0x1c, 0x15, 0xda, 0x65, + 0x8c, 0xcf, 0xc8, 0x8e, 0xf1, 0x4f, 0xc8, 0xca, 0x16, 0x46, 0x70, 0x4f, 0x72, 0x2a, 0x92, 0xe8, 0xfc, 0x14, 0x05, + 0xf2, 0x46, 0xeb, 0x12, 0x1d, 0x78, 0x7d, 0xd1, 0x2c, 0x1e, 0xfe, 0x1e, 0x2d, 0x29, 0x44, 0x38, 0x78, 0x7c, 0x47, + 0x84, 0x50, 0xab, 0x29, 0x54, 0x47, 0x5b, 0x0c, 0x32, 0x7b, 0x7c, 0x4a, 0x36, 0x5f, 0x64, 0x1b, 0x1c, 0xb1, 0x04, + 0x3f, 0xa9, 0xec, 0xc7, 0x95, 0x4d, 0xfc, 0x48, 0xff, 0x43, 0x69, 0xc9, 0xa9, 0x8e, 0xd7, 0x74, 0x55, 0x43, 0x53, + 0xe8, 0x0a, 0xb5, 0x11, 0x1d, 0x87, 0xfd, 0x2b, 0x94, 0x49, 0x9d, 0x6a, 0xda, 0x20, 0x6a, 0x1d, 0xf4, 0x3d, 0x5a, + 0x70, 0xbf, 0xf2, 0x3a, 0xf2, 0x45, 0x0c, 0x22, 0x27, 0xe8, 0x57, 0x62, 0x73, 0x25, 0x9f, 0xa7, 0xd1, 0x9d, 0xb7, + 0x54, 0xb2, 0xb1, 0x11, 0x2a, 0xca, 0xda, 0xdb, 0xe4, 0x52, 0xca, 0x5b, 0x4f, 0xe8, 0x29, 0xf7, 0xf2, 0xc1, 0x6c, + 0x93, 0xc6, 0x22, 0x22, 0x4e, 0x36, 0x1e, 0xae, 0xe3, 0x0d, 0x79, 0xa1, 0xd8, 0x82, 0x91, 0x0a, 0x5a, 0x83, 0x97, + 0x9d, 0xb3, 0x8c, 0xf2, 0x95, 0x38, 0x5e, 0xe4, 0x6f, 0xbb, 0xd9, 0x20, 0x9e, 0x1f, 0x06, 0xde, 0x47, 0x12, 0xea, + 0xac, 0x40, 0xc2, 0x1c, 0x77, 0x90, 0x05, 0xcb, 0x73, 0x25, 0x8f, 0x40, 0x32, 0x30, 0x52, 0xb4, 0x0d, 0xd3, 0xb9, + 0x14, 0x1f, 0xb4, 0x83, 0x8d, 0xb3, 0x41, 0x10, 0x1c, 0xd8, 0xf9, 0xfd, 0xfc, 0xeb, 0x5b, 0x1a, 0x83, 0xd3, 0xdb, + 0x2d, 0xc3, 0xff, 0x13, 0x5c, 0x9a, 0x45, 0xb4, 0x9c, 0xfe, 0x14, 0x63, 0xbe, 0xfc, 0x3f, 0xb9, 0x5b, 0x68, 0x1d, + 0xb4, 0xf0, 0x81, 0xed, 0x8e, 0x56, 0xdd, 0x46, 0x92, 0xda, 0xda, 0x0d, 0x06, 0x14, 0x66, 0x48, 0x39, 0x29, 0xa3, + 0x7a, 0x87, 0x46, 0x2f, 0x9c, 0x6e, 0x8e, 0x02, 0x30, 0xf7, 0xc1, 0xca, 0x7b, 0xca, 0x93, 0xdd, 0xbd, 0x02, 0x2b, + 0xb1, 0x1e, 0x0d, 0x90, 0xa3, 0xd4, 0xfe, 0x7d, 0xe1, 0xd4, 0xba, 0xa7, 0x25, 0xab, 0x6c, 0x38, 0x7f, 0xd1, 0x55, + 0x82, 0xb0, 0xc1, 0xd5, 0x53, 0xae, 0xcb, 0x2d, 0x7d, 0x5a, 0xa9, 0xca, 0x18, 0x1f, 0x0a, 0x09, 0x60, 0xa7, 0xaa, + 0x64, 0xdd, 0x19, 0xbf, 0x94, 0x62, 0x77, 0xac, 0xd9, 0xc9, 0x5f, 0x6f, 0x80, 0xdf, 0x2b, 0xe6, 0x75, 0x57, 0x8f, + 0xd6, 0x13, 0xd8, 0x93, 0x4b, 0x8f, 0xa1, 0x42, 0x60, 0x87, 0x97, 0x34, 0xd8, 0x7d, 0x90, 0x36, 0x0b, 0x93, 0x03, + 0x87, 0xe8, 0x34, 0x12, 0x3c, 0x57, 0x69, 0x69, 0xe4, 0xc4, 0x5b, 0x79, 0x62, 0xb7, 0x2e, 0x6e, 0xd2, 0x54, 0xc2, + 0x21, 0xa3, 0x90, 0x67, 0xf0, 0x86, 0x73, 0x89, 0xd2, 0xb3, 0xd9, 0xb4, 0xc9, 0x68, 0xc2, 0x79, 0x9a, 0xdf, 0x87, + 0x93, 0x6b, 0xac, 0x3e, 0xea, 0x98, 0xf4, 0x02, 0x38, 0x4b, 0xd1, 0x1a, 0xf1, 0xab, 0x03, 0x03, 0x0d, 0x2e, 0x2f, + 0xec, 0x25, 0x0b, 0xc1, 0x18, 0x6d, 0x63, 0x8f, 0x49, 0x07, 0x0e, 0xa1, 0xbe, 0x4e, 0x19, 0xc2, 0x0c, 0x2b, 0x88, + 0x60, 0x9a, 0xe2, 0xcc, 0xe1, 0x37, 0x70, 0xcf, 0x0a, 0x8c, 0x0a, 0xb9, 0x89, 0x0e, 0x23, 0xe0, 0x0a, 0xb7, 0x03, + 0x44, 0x76, 0xe6, 0x63, 0xc6, 0x6c, 0x9d, 0x71, 0xd8, 0xaf, 0x5c, 0x62, 0xd3, 0x1e, 0xa9, 0xfe, 0x8e, 0xdb, 0x7e, + 0x3b, 0xe1, 0xcf, 0x05, 0x8e, 0x62, 0x03, 0x71, 0x4f, 0xcb, 0x59, 0x4a, 0x2d, 0x1c, 0x1f, 0x47, 0x33, 0x8c, 0x43, + 0xe9, 0x9c, 0x32, 0xc9, 0x36, 0x0a, 0x9b, 0x01, 0xa4, 0xed, 0xe6, 0x90, 0x4c, 0x99, 0xa4, 0xb1, 0x38, 0x11, 0x85, + 0x2c, 0xfc, 0x12, 0xac, 0xcd, 0x2f, 0x36, 0x9f, 0xc0, 0x51, 0x85, 0xb9, 0xba, 0x23, 0xf0, 0x6e, 0xa1, 0xcc, 0x4b, + 0xe9, 0x28, 0xf4, 0x28, 0x4c, 0x9d, 0xb1, 0xd5, 0x0b, 0xeb, 0x94, 0x21, 0x64, 0x23, 0x5b, 0x67, 0x89, 0x16, 0x65, + 0x83, 0x7f, 0x1c, 0xff, 0x6b, 0x90, 0xd8, 0xf6, 0x20, 0xd8, 0xde, 0x32, 0x65, 0xa7, 0xef, 0x2d, 0xbf, 0xfb, 0x44, + 0x4f, 0x74, 0x07, 0x1c, 0x06, 0x5c, 0x75, 0x7a, 0xee, 0xa7, 0x3e, 0xbc, 0xcb, 0x06, 0xff, 0x0d, 0x37, 0x7e, 0x0a, + 0x5f, 0xa5, 0x8f, 0x0a, 0xe7, 0xfa, 0xca, 0x7b, 0x43, 0x1e, 0x6d, 0x53, 0xf3, 0x3b, 0x4f, 0x54, 0xbc, 0x21, 0xdf, + 0x4d, 0xbc, 0x9a, 0x13, 0xef, 0xc9, 0xe7, 0x9c, 0x6f, 0xa7, 0x4e, 0xc0, 0x62, 0xb0, 0x07, 0x3b, 0x64, 0xd7, 0x7b, + 0x6d, 0x54, 0x8c, 0x5f, 0x99, 0xdb, 0xfb, 0x1f, 0x59, 0xef, 0x65, 0x11, 0x0d, 0x74, 0x03, 0x98, 0xc0, 0x69, 0xeb, + 0x10, 0xe5, 0x86, 0x2c, 0xb1, 0xec, 0x50, 0xa5, 0x89, 0x0e, 0x15, 0x21, 0x5d, 0x02, 0xb0, 0x7c, 0xe2, 0xf8, 0xc3, + 0x8a, 0xd3, 0x4a, 0xd2, 0x60, 0x88, 0xb5, 0x98, 0xdd, 0xa6, 0xd3, 0xfa, 0x71, 0xca, 0xe4, 0x5f, 0x01, 0xe3, 0x75, + 0x82, 0xb7, 0x48, 0x7f, 0xbe, 0x7c, 0x67, 0xf9, 0x39, 0xd1, 0x6f, 0xe4, 0x42, 0xff, 0x53, 0xf8, 0xba, 0x90, 0x26, + 0xf5, 0x3a, 0xff, 0x6c, 0xa7, 0xfa, 0x1d, 0x4a, 0x4b, 0x96, 0x83, 0xbc, 0x54, 0xdf, 0xd7, 0x9d, 0xfe, 0x43, 0xf9, + 0xfa, 0xd8, 0xc9, 0x06, 0x82, 0x5b, 0x9e, 0xfd, 0x64, 0x45, 0x44, 0xcf, 0xb6, 0x3f, 0x70, 0x32, 0x93, 0xdc, 0xcd, + 0xf5, 0xc8, 0xea, 0x24, 0xab, 0x82, 0x87, 0xbd, 0x4a, 0xdf, 0x33, 0xd3, 0xc3, 0x3d, 0x37, 0xe5, 0x9f, 0x44, 0x2a, + 0xf0, 0x44, 0x43, 0x63, 0x33, 0x54, 0x23, 0x14, 0x8f, 0xd3, 0x80, 0xcd, 0x9f, 0x34, 0xaf, 0x07, 0x0d, 0x56, 0x2e, + 0x15, 0x28, 0xaa, 0xd6, 0x9e, 0xa0, 0x03, 0x53, 0x50, 0x38, 0xda, 0x12, 0x02, 0x54, 0xb0, 0x2c, 0x6a, 0x48, 0xf4, + 0x23, 0x0d, 0x56, 0xb8, 0xd1, 0xc1, 0xdf, 0x82, 0x15, 0x41, 0x50, 0xb7, 0x36, 0xe6, 0x75, 0x57, 0x63, 0x28, 0x8c, + 0xfa, 0x31, 0x98, 0xa0, 0xfc, 0x0d, 0xd4, 0x4b, 0x5b, 0x0c, 0x57, 0xab, 0x06, 0x7c, 0x50, 0xcd, 0x49, 0xbc, 0x6c, + 0xb6, 0x09, 0x9b, 0xdc, 0x20, 0x65, 0x91, 0xc3, 0x1e, 0xfa, 0x04, 0xd5, 0x51, 0xa4, 0x72, 0x11, 0x17, 0xb3, 0xe6, + 0xc2, 0x6c, 0x4a, 0x76, 0xf3, 0xc0, 0x65, 0x6f, 0xe4, 0x99, 0x44, 0xaf, 0xf6, 0xfe, 0x1b, 0x89, 0xe8, 0x80, 0x25, + 0x40, 0xbc, 0x62, 0x61, 0xca, 0x60, 0x60, 0x08, 0xd1, 0xb6, 0x68, 0x1c, 0x8c, 0x5e, 0xf3, 0xe5, 0x6a, 0x31, 0xdf, + 0xcd, 0x66, 0x24, 0x1b, 0x8d, 0x7e, 0x2d, 0xa0, 0x55, 0x3d, 0x6d, 0xfa, 0x37, 0x2c, 0xee, 0x27, 0xf9, 0xe1, 0x53, + 0xef, 0x3c, 0x8b, 0xe8, 0xa9, 0x07, 0xf8, 0xf2, 0x3c, 0x10, 0xc2, 0xf4, 0xfc, 0x05, 0xf4, 0x40, 0x88, 0xb6, 0x31, + 0x17, 0x96, 0x3c, 0x52, 0xe5, 0x7f, 0x5e, 0x95, 0x4f, 0xb0, 0xa0, 0x0e, 0x4d, 0xc2, 0x44, 0x01, 0xb3, 0x46, 0xce, + 0x62, 0xf3, 0x19, 0xf3, 0xbc, 0x4e, 0xb3, 0x77, 0x9d, 0xc4, 0x0d, 0xcb, 0x73, 0xf9, 0x6b, 0xcc, 0x13, 0xae, 0x1f, + 0xb2, 0x33, 0x2c, 0xea, 0x44, 0xd5, 0x80, 0x5f, 0x96, 0x16, 0x3f, 0x81, 0xd6, 0xa5, 0x81, 0x90, 0x58, 0x79, 0x85, + 0xcd, 0x63, 0xa9, 0xd2, 0x37, 0xe4, 0x35, 0xd2, 0x1d, 0x0e, 0x9e, 0x8f, 0xe1, 0xbe, 0x3b, 0xc0, 0x73, 0x52, 0xfd, + 0xfc, 0x89, 0x78, 0x4c, 0x04, 0x61, 0x1b, 0x84, 0xe8, 0xf6, 0xe5, 0x3a, 0xbd, 0xfd, 0x6d, 0x34, 0xe6, 0x46, 0x69, + 0x25, 0xdc, 0x3a, 0xb9, 0xea, 0xc4, 0x78, 0x79, 0x89, 0x9a, 0x13, 0xb7, 0xd3, 0xce, 0xe3, 0x20, 0x52, 0x5a, 0x8d, + 0x65, 0x1b, 0xe3, 0x34, 0x45, 0xe1, 0x91, 0x47, 0x02, 0x76, 0xe4, 0x25, 0x9c, 0x04, 0x54, 0xff, 0x63, 0x7c, 0xe6, + 0x9d, 0x25, 0xb0, 0x02, 0x89, 0x3f, 0x5f, 0xdc, 0x7a, 0xd4, 0xff, 0x33, 0x68, 0xad, 0x7a, 0x26, 0xbd, 0x33, 0x49, + 0x26, 0x7c, 0x76, 0x37, 0xe0, 0x5d, 0xd7, 0x46, 0x4c, 0x3e, 0x51, 0x31, 0x36, 0x20, 0xb5, 0xdf, 0xc6, 0xbe, 0x36, + 0xa3, 0xf4, 0xe6, 0x23, 0x7a, 0x06, 0xae, 0x7e, 0x44, 0xb8, 0xac, 0xd7, 0xd6, 0x7e, 0x07, 0x02, 0x74, 0x82, 0xe5, + 0x74, 0xe0, 0xb4, 0xcb, 0x17, 0xed, 0x93, 0x30, 0x5a, 0x00, 0xa9, 0xdc, 0x40, 0x66, 0x3c, 0xa2, 0x3a, 0x93, 0x31, + 0x36, 0x49, 0x8f, 0x1e, 0x74, 0xc2, 0xee, 0xdf, 0x01, 0x6b, 0x79, 0xc5, 0xb1, 0x76, 0xee, 0x20, 0x78, 0x92, 0x9c, + 0xbc, 0xaa, 0x67, 0x17, 0x6c, 0x69, 0x19, 0xcb, 0x43, 0x7f, 0x1e, 0x82, 0x98, 0x2e, 0xef, 0x6d, 0x23, 0x28, 0xa1, + 0x72, 0xf5, 0x07, 0x41, 0xa1, 0xcf, 0xfa, 0x17, 0x5b, 0x65, 0x53, 0x9d, 0xc7, 0x3e, 0xec, 0xbd, 0xeb, 0xab, 0xc2, + 0xc9, 0x45, 0xf3, 0x7e, 0x14, 0x87, 0x54, 0x75, 0x54, 0xbe, 0xb5, 0x58, 0xf6, 0xda, 0xec, 0x64, 0xa1, 0x3d, 0xf2, + 0x45, 0xfb, 0xd4, 0x1a, 0xb4, 0xd2, 0xb2, 0x28, 0xa4, 0xcd, 0x5c, 0xf4, 0xce, 0x67, 0xcc, 0x22, 0x8e, 0x88, 0xc0, + 0x72, 0xeb, 0x17, 0xf9, 0x23, 0xb6, 0x74, 0x44, 0x59, 0xf8, 0x46, 0x68, 0xea, 0x98, 0x93, 0x87, 0x13, 0x70, 0x5b, + 0x19, 0xde, 0x66, 0x20, 0x46, 0xb5, 0xc8, 0x21, 0x02, 0xfd, 0x8b, 0x63, 0x89, 0x38, 0x57, 0xbf, 0x50, 0x63, 0xe4, + 0x42, 0x0d, 0x42, 0x88, 0x5e, 0x0b, 0x65, 0xe6, 0xe3, 0xbc, 0x4b, 0xb2, 0x36, 0x66, 0x5f, 0xa1, 0x55, 0x63, 0x66, + 0xb6, 0x7a, 0x38, 0xb0, 0x45, 0xd0, 0xed, 0x25, 0x7e, 0x3b, 0x3b, 0x08, 0xdf, 0x4f, 0x45, 0x2e, 0xae, 0x05, 0x73, + 0xb1, 0x8f, 0x53, 0xe3, 0xd3, 0xfd, 0x87, 0x81, 0x62, 0x04, 0x87, 0xab, 0xf2, 0x8a, 0xd6, 0xb3, 0xe1, 0xfd, 0xc0, + 0xd7, 0xb1, 0x39, 0x26, 0xf3, 0xcc, 0x38, 0x58, 0xb1, 0x76, 0xc1, 0xbb, 0x1a, 0x26, 0xac, 0x22, 0x46, 0xb8, 0x5c, + 0x35, 0xc5, 0xda, 0x7c, 0x06, 0xeb, 0x23, 0x48, 0xe2, 0xca, 0x57, 0xe8, 0x8c, 0x0c, 0x0e, 0x66, 0x35, 0x1a, 0xf4, + 0xf3, 0xbe, 0xb4, 0xee, 0x11, 0x08, 0x73, 0x01, 0xb8, 0x7b, 0x73, 0x41, 0x81, 0x1c, 0x40, 0x76, 0xdf, 0x47, 0x00, + 0x19, 0x09, 0xcc, 0x4c, 0x24, 0x48, 0xd2, 0xaa, 0xb5, 0x8f, 0x79, 0x71, 0x09, 0x89, 0x1e, 0x02, 0x82, 0x59, 0x2b, + 0x77, 0x89, 0xea, 0x95, 0xd8, 0x9c, 0x30, 0x04, 0x5a, 0x7b, 0x56, 0x44, 0x4f, 0xd9, 0xfd, 0xab, 0x23, 0x10, 0xfe, + 0xa9, 0xb0, 0x78, 0xd6, 0x39, 0x53, 0x8c, 0xe7, 0x91, 0x65, 0xb6, 0xe0, 0xdf, 0x16, 0x96, 0x8b, 0xf7, 0x50, 0xcc, + 0xa1, 0x1b, 0x93, 0x39, 0x09, 0xbb, 0xef, 0x71, 0x50, 0x12, 0xa8, 0x7f, 0x14, 0xe6, 0x6e, 0x9c, 0xa3, 0x18, 0x3b, + 0x19, 0xe7, 0x12, 0x6a, 0xc5, 0x52, 0xb3, 0x11, 0x58, 0x73, 0xf2, 0x5c, 0x98, 0x4c, 0x2d, 0xf5, 0x49, 0x85, 0x12, + 0x76, 0x66, 0x4a, 0x52, 0x26, 0xe7, 0x45, 0xc1, 0x51, 0x53, 0x51, 0x99, 0xe2, 0x20, 0x94, 0x9f, 0xce, 0xfa, 0xc5, + 0xee, 0xf9, 0x11, 0xdb, 0xf1, 0x6a, 0x70, 0xdb, 0x90, 0xa9, 0x51, 0x53, 0xe0, 0xcf, 0x8c, 0x87, 0xe9, 0xff, 0xe4, + 0x20, 0x9d, 0x87, 0xf0, 0xce, 0xf4, 0xcb, 0x29, 0xb7, 0x81, 0x18, 0x3f, 0xd0, 0xc2, 0x5b, 0x5a, 0x8d, 0x12, 0xa9, + 0xff, 0x4a, 0xe2, 0x73, 0x74, 0xc2, 0x4a, 0x28, 0x25, 0x89, 0x4b, 0x38, 0xa4, 0xba, 0x63, 0xcc, 0xa8, 0x8c, 0x6e, + 0x41, 0x14, 0x34, 0xae, 0xd3, 0x88, 0x2c, 0xdc, 0x2a, 0x3a, 0xba, 0xf8, 0xc5, 0x9f, 0xd9, 0x87, 0xc1, 0x97, 0xc1, + 0x81, 0x40, 0x8e, 0x06, 0x41, 0xfb, 0xc3, 0x2b, 0x6c, 0x78, 0xd9, 0x79, 0xa1, 0x8e, 0x05, 0xe2, 0x51, 0xa7, 0x5e, + 0x42, 0x26, 0x21, 0xff, 0xd0, 0xa9, 0x12, 0x08, 0xe4, 0xcd, 0x0e, 0xab, 0xdf, 0xa0, 0x9f, 0x77, 0xda, 0x2d, 0x37, + 0x75, 0x13, 0x7a, 0x22, 0x84, 0x00, 0x48, 0x6c, 0x8d, 0x04, 0x91, 0xb7, 0x1a, 0x44, 0x52, 0x1d, 0x76, 0x5f, 0xe9, + 0x85, 0x20, 0xe0, 0x46, 0x6d, 0x34, 0x1a, 0x21, 0xf3, 0x0a, 0xb6, 0xc3, 0x4c, 0xc0, 0x38, 0x97, 0x51, 0xc6, 0x2f, + 0xf0, 0x50, 0x78, 0x25, 0x09, 0xbe, 0xa6, 0x4c, 0x7b, 0x0e, 0xa2, 0x5b, 0x6e, 0x2e, 0x3a, 0x1e, 0xc0, 0x20, 0x7a, + 0x02, 0xe6, 0x4f, 0xe6, 0xbf, 0x65, 0x67, 0xa4, 0x68, 0x20, 0x57, 0x7b, 0x87, 0x4b, 0xc6, 0xfc, 0xa9, 0xe4, 0x49, + 0x75, 0x4b, 0x81, 0x21, 0x72, 0xf1, 0xb2, 0xeb, 0x8f, 0x61, 0xae, 0xa8, 0x1d, 0xe0, 0x7d, 0xa2, 0x61, 0xf5, 0x62, + 0x3d, 0xa9, 0x6f, 0x8d, 0xc4, 0x7f, 0x51, 0x19, 0x1b, 0xe3, 0xa8, 0xf4, 0x42, 0x3c, 0xe9, 0x6e, 0xef, 0xac, 0xde, + 0x45, 0xae, 0xd6, 0xc4, 0x83, 0xc1, 0x5a, 0xb7, 0x42, 0x2b, 0xa7, 0xb6, 0xfc, 0x36, 0x87, 0x4b, 0x5f, 0x99, 0xb8, + 0x35, 0x5d, 0x20, 0x86, 0x82, 0xd2, 0xf1, 0xb8, 0xfc, 0x0c, 0x4f, 0x76, 0xf2, 0xa4, 0x33, 0x66, 0x66, 0x21, 0x3e, + 0xdd, 0xd9, 0x3c, 0xd3, 0x1f, 0x87, 0x2c, 0x21, 0x65, 0xaa, 0x9b, 0x9f, 0xe6, 0x85, 0x2f, 0x66, 0x3e, 0xcf, 0x27, + 0x9c, 0x71, 0x0b, 0x2b, 0xb4, 0x5e, 0x33, 0x7e, 0x4e, 0x18, 0x0e, 0xef, 0x2c, 0x4d, 0x94, 0x25, 0xa3, 0xe1, 0x1f, + 0x3f, 0xdf, 0x2d, 0x6d, 0xbe, 0xf3, 0xd3, 0xf1, 0x76, 0x12, 0x93, 0x02, 0x1b, 0xa5, 0x03, 0xc1, 0xf7, 0x80, 0xb2, + 0x97, 0xef, 0x6c, 0xcc, 0xe4, 0x7e, 0xd0, 0x41, 0x81, 0x61, 0x0b, 0x81, 0x0b, 0xad, 0x3f, 0xe4, 0x3d, 0xd6, 0x3b, + 0x55, 0x9e, 0xed, 0xa7, 0xe9, 0xbe, 0x2a, 0x0a, 0x05, 0x3f, 0xbb, 0xf5, 0xd8, 0x5b, 0x07, 0xcd, 0x91, 0x96, 0x30, + 0x79, 0x26, 0xd5, 0xe4, 0x67, 0x62, 0xaa, 0x08, 0x96, 0xbf, 0xfe, 0x32, 0xb9, 0xc8, 0x5d, 0xaf, 0x71, 0x10, 0xa6, + 0x66, 0xc2, 0xd4, 0xaf, 0x95, 0xb7, 0x23, 0xf5, 0x4f, 0xe9, 0xbb, 0x2b, 0x50, 0x57, 0x64, 0x2d, 0x40, 0xa4, 0x34, + 0x0c, 0xa9, 0x56, 0x87, 0x15, 0xa7, 0x6e, 0x83, 0x95, 0x1d, 0xbe, 0x80, 0x1b, 0x25, 0x67, 0x09, 0x51, 0xd1, 0xa6, + 0x26, 0x03, 0x87, 0x41, 0xa0, 0x30, 0x54, 0x14, 0x87, 0x47, 0x58, 0x7c, 0xd9, 0xe1, 0x45, 0xd3, 0x45, 0xb1, 0xe1, + 0xd5, 0x7e, 0xa2, 0x8c, 0x33, 0xb6, 0x8b, 0x0a, 0x40, 0x2d, 0x22, 0xfc, 0xf8, 0x34, 0xc0, 0xca, 0x9f, 0xf0, 0xb1, + 0x7b, 0x12, 0x96, 0x1e, 0x74, 0x29, 0x6a, 0xd9, 0x52, 0x4a, 0x53, 0x5b, 0xd4, 0x35, 0xce, 0x50, 0x71, 0xec, 0xf0, + 0xc8, 0x7a, 0x84, 0xf1, 0xdc, 0xe9, 0x22, 0xf8, 0x2c, 0x36, 0xc8, 0x23, 0x95, 0x20, 0xca, 0xdd, 0x32, 0x6e, 0x3d, + 0xe8, 0x63, 0x2e, 0x07, 0x61, 0xfb, 0x0c, 0xa5, 0x72, 0x11, 0x2b, 0x09, 0x2e, 0x83, 0xf2, 0x8f, 0x1e, 0xaa, 0x4c, + 0x74, 0xf2, 0x9e, 0x3a, 0xb6, 0x1d, 0x68, 0xac, 0xe9, 0x21, 0x89, 0x36, 0x6e, 0xd5, 0x62, 0x5c, 0x31, 0x75, 0x7a, + 0x6e, 0x89, 0x29, 0x41, 0x7e, 0x73, 0x39, 0xda, 0x9a, 0xba, 0x04, 0x62, 0x49, 0x89, 0xf8, 0x94, 0x4b, 0xfe, 0xae, + 0xeb, 0x24, 0xbe, 0x60, 0x2b, 0xb2, 0x64, 0xdc, 0xaa, 0xdd, 0x46, 0x5a, 0xcf, 0x05, 0x21, 0xf3, 0x2f, 0x35, 0x08, + 0x07, 0x9f, 0x2e, 0x58, 0xae, 0xc5, 0x47, 0xeb, 0xaf, 0x69, 0xd2, 0xa6, 0x07, 0x15, 0xb4, 0xd4, 0x41, 0x25, 0x2f, + 0x6b, 0xe6, 0x11, 0x57, 0xb3, 0x30, 0xbe, 0xa6, 0xdf, 0x5d, 0x72, 0x50, 0xd9, 0x19, 0x04, 0xf1, 0xe9, 0x20, 0xad, + 0x15, 0x79, 0xaa, 0x70, 0xaf, 0xd4, 0x5f, 0x89, 0x53, 0x0d, 0xa4, 0xf3, 0x02, 0x56, 0x08, 0xb9, 0x8e, 0x1f, 0xb8, + 0xda, 0x44, 0x80, 0x65, 0x99, 0xde, 0x6f, 0x2e, 0xa5, 0xd4, 0xf9, 0x01, 0xc0, 0xb3, 0xed, 0xa2, 0x5f, 0xa0, 0x39, + 0x01, 0x8c, 0x28, 0x50, 0x77, 0x21, 0xde, 0xea, 0x86, 0x8c, 0xb1, 0xfd, 0x92, 0xf6, 0xb0, 0x65, 0x3b, 0x06, 0x48, + 0x80, 0x91, 0x65, 0x58, 0xdc, 0x7b, 0x94, 0x8a, 0xd6, 0x74, 0x66, 0x63, 0x54, 0x95, 0xb4, 0x62, 0x7f, 0x79, 0x93, + 0xc8, 0xec, 0xd7, 0x8d, 0x8b, 0xa6, 0xbc, 0xb6, 0x48, 0x25, 0x8a, 0x13, 0x64, 0x65, 0xaa, 0xc8, 0x28, 0x8c, 0xb5, + 0xa3, 0x64, 0x81, 0xc7, 0xc5, 0x9e, 0x30, 0xa6, 0xff, 0x34, 0x15, 0x28, 0xdf, 0xbf, 0x6b, 0x1a, 0xa9, 0x50, 0x21, + 0xec, 0xc9, 0x72, 0x1a, 0x5b, 0xd1, 0xa7, 0xe2, 0x64, 0x4d, 0x22, 0xfd, 0xb7, 0x01, 0x06, 0x53, 0x1b, 0xf0, 0xe4, + 0x06, 0x29, 0x96, 0x10, 0x3e, 0x29, 0xdd, 0x67, 0x4d, 0x74, 0xa3, 0x32, 0xc0, 0x99, 0x1b, 0x37, 0x67, 0x2b, 0x0d, + 0x5c, 0xd9, 0x3a, 0x08, 0x53, 0x61, 0xe1, 0xce, 0xa6, 0x41, 0x8a, 0x4b, 0x8e, 0x94, 0x4c, 0xbf, 0x16, 0xc4, 0x8b, + 0x23, 0xfc, 0x2a, 0x7f, 0x72, 0x8b, 0x4c, 0x57, 0xa8, 0x2a, 0xa5, 0x53, 0xcc, 0x61, 0x7a, 0x98, 0x96, 0x2e, 0xe9, + 0xe5, 0x84, 0x77, 0x9e, 0x1f, 0xce, 0x05, 0x3d, 0x6d, 0xd5, 0x6a, 0xd5, 0x50, 0x18, 0xd0, 0x49, 0x47, 0x80, 0x78, + 0xd4, 0xf4, 0x97, 0xf0, 0xba, 0x92, 0x9b, 0x17, 0x71, 0x4d, 0x81, 0xe3, 0xb4, 0x7d, 0xed, 0xdc, 0x5f, 0x2e, 0xab, + 0x85, 0x1c, 0x24, 0x60, 0x2c, 0xa3, 0x0f, 0x81, 0xdc, 0xe9, 0xe9, 0xb3, 0xd2, 0xb2, 0x46, 0xd6, 0x27, 0x9b, 0x2d, + 0x3e, 0x79, 0x3f, 0x78, 0x81, 0x25, 0xdb, 0xe0, 0xe1, 0xad, 0xbe, 0xa6, 0xed, 0x64, 0x83, 0xb0, 0x16, 0x8d, 0x83, + 0x28, 0x56, 0xa0, 0x1d, 0xd9, 0x8a, 0xac, 0xcb, 0x9c, 0x64, 0x5f, 0x5f, 0xe4, 0x3f, 0xcf, 0x8a, 0x50, 0xa2, 0x05, + 0x8d, 0x9c, 0xc3, 0x1a, 0x2e, 0xe8, 0xa0, 0x34, 0x01, 0x83, 0x32, 0x00, 0x1b, 0x65, 0xec, 0xea, 0x34, 0x14, 0xf0, + 0x31, 0x46, 0x14, 0xca, 0x99, 0xcb, 0xd9, 0x5b, 0x5c, 0x58, 0x8b, 0x53, 0x66, 0x56, 0x9a, 0x7e, 0xa6, 0x85, 0xf9, + 0x7a, 0x23, 0x49, 0x10, 0xd9, 0x5a, 0x4e, 0x57, 0xae, 0x4b, 0xf4, 0xf4, 0x28, 0x28, 0x50, 0x59, 0x49, 0xc9, 0xb9, + 0x7c, 0x5e, 0xa1, 0xb3, 0x92, 0xf2, 0x2b, 0x4b, 0x4c, 0xc0, 0xd8, 0x26, 0x76, 0x8f, 0x9f, 0xcb, 0xca, 0xa7, 0x3c, + 0x66, 0x7c, 0xfa, 0xd3, 0xb6, 0xbe, 0x53, 0x58, 0x40, 0xa0, 0xe6, 0x0f, 0x6b, 0xae, 0xf4, 0xda, 0x8c, 0x81, 0x58, + 0x38, 0x31, 0xc0, 0xe7, 0xf0, 0x51, 0x01, 0xa3, 0xd4, 0x6c, 0x07, 0x13, 0x29, 0xd1, 0x92, 0x90, 0xc8, 0xb4, 0x1d, + 0xb4, 0x3e, 0x8b, 0x41, 0x59, 0x31, 0xc1, 0x35, 0xc5, 0x15, 0x6f, 0x57, 0x3b, 0x6a, 0x68, 0x5d, 0x23, 0x83, 0x78, + 0xa8, 0xa4, 0x3f, 0x3b, 0xde, 0x8f, 0x50, 0x10, 0x67, 0xa5, 0xc2, 0x5b, 0x9c, 0x6d, 0xed, 0xf8, 0x19, 0x05, 0xf7, + 0xc2, 0x5b, 0xb0, 0x31, 0x86, 0xa6, 0x6c, 0xb2, 0x62, 0xff, 0x6c, 0x06, 0xc4, 0x5e, 0xdf, 0x46, 0x86, 0xbb, 0xcd, + 0x8a, 0xc3, 0x07, 0xb3, 0xe5, 0x1f, 0xb1, 0xc7, 0xee, 0x3e, 0x79, 0x51, 0xac, 0x71, 0x6a, 0x0f, 0x6b, 0xc6, 0xb7, + 0xdf, 0x5b, 0x2e, 0x48, 0x8f, 0xe6, 0xda, 0x12, 0xd1, 0x13, 0xd3, 0x13, 0x0c, 0x0b, 0xa4, 0xc8, 0xea, 0x55, 0xca, + 0x54, 0xdb, 0x1b, 0xd6, 0x5e, 0x5a, 0x72, 0x55, 0x68, 0x0f, 0xc5, 0xec, 0xb2, 0x97, 0xe7, 0xb2, 0xe3, 0xeb, 0xe2, + 0xa3, 0x32, 0x6b, 0x8e, 0x95, 0x5f, 0x08, 0x53, 0x61, 0xaf, 0x0a, 0x72, 0x4a, 0x07, 0xeb, 0x08, 0xd5, 0x61, 0x98, + 0x2a, 0x1e, 0x3d, 0xb7, 0x25, 0xa4, 0x06, 0xbc, 0x1f, 0x5e, 0xe4, 0xf9, 0x55, 0xb4, 0xab, 0x00, 0x86, 0x4b, 0x01, + 0x07, 0x8f, 0x26, 0x08, 0x5c, 0x92, 0x10, 0x78, 0x9b, 0x41, 0x1f, 0xae, 0xdf, 0xbc, 0x7d, 0x0d, 0x65, 0x96, 0x33, + 0x6c, 0xa9, 0x38, 0xfb, 0x40, 0x7a, 0xb6, 0x2b, 0x92, 0xfa, 0x9e, 0x9a, 0xad, 0xb8, 0x35, 0xa6, 0x29, 0x12, 0x03, + 0xca, 0xae, 0x5a, 0xd3, 0xbd, 0x52, 0xd7, 0xf4, 0xec, 0x3c, 0x58, 0xd7, 0x12, 0xed, 0x0a, 0xa2, 0x52, 0x7f, 0x40, + 0xa2, 0xaf, 0x14, 0xda, 0x39, 0xb6, 0xae, 0x87, 0x3a, 0xaa, 0xa0, 0x5a, 0xc7, 0x08, 0xa9, 0xb6, 0xa5, 0x54, 0xfd, + 0x52, 0xeb, 0x70, 0xe9, 0x35, 0xc1, 0x70, 0xf4, 0xe0, 0x61, 0xbc, 0x4b, 0xd4, 0xa4, 0xdc, 0x5f, 0xf8, 0x12, 0xd6, + 0xdd, 0xee, 0x35, 0xf6, 0x7f, 0x51, 0xcf, 0xd6, 0x45, 0x37, 0xf1, 0x3e, 0xc8, 0xff, 0x57, 0x0f, 0x18, 0x99, 0x3c, + 0x7c, 0x38, 0xae, 0xb2, 0xde, 0x66, 0x31, 0x35, 0x25, 0x7f, 0x9d, 0x6b, 0xfa, 0x6a, 0xa5, 0x9d, 0x9a, 0xbb, 0x3b, + 0x39, 0xfb, 0x0d, 0x9b, 0x13, 0x87, 0x30, 0x4c, 0x94, 0xc8, 0xdd, 0x95, 0xc9, 0xa6, 0xeb, 0x72, 0xa9, 0xc1, 0x77, + 0x4b, 0x83, 0x90, 0xbc, 0x46, 0xe3, 0x87, 0x30, 0xcb, 0xa5, 0x44, 0x6c, 0x00, 0xcf, 0x9c, 0x99, 0xa8, 0x87, 0x8d, + 0x2d, 0x25, 0x88, 0xb2, 0x2a, 0x16, 0x5f, 0x65, 0x6a, 0xe7, 0xa8, 0x2a, 0x8d, 0xe2, 0xb9, 0x7b, 0xc3, 0x03, 0x86, + 0x64, 0xe2, 0xec, 0x57, 0xd0, 0xbb, 0xd0, 0x40, 0xba, 0x1d, 0xbb, 0x1f, 0xf0, 0x13, 0x29, 0xd1, 0xe7, 0xc1, 0x58, + 0x80, 0xd8, 0x22, 0x99, 0x65, 0x50, 0x28, 0x7e, 0x71, 0x2b, 0x5c, 0x25, 0x6a, 0x33, 0xde, 0xb3, 0x97, 0x2a, 0x6e, + 0x03, 0x33, 0xab, 0x96, 0x8f, 0x4c, 0x85, 0x10, 0x7b, 0xd5, 0x89, 0x7a, 0x96, 0x50, 0x36, 0xa3, 0x1e, 0xfe, 0xbe, + 0xa3, 0x1c, 0x8d, 0x28, 0xed, 0x68, 0x50, 0x8d, 0x85, 0xf7, 0x3b, 0x63, 0x7c, 0x67, 0xb6, 0x3f, 0x46, 0x88, 0x39, + 0xaf, 0x88, 0x83, 0x43, 0x38, 0x61, 0x78, 0xb5, 0xb5, 0x1c, 0x95, 0x21, 0x28, 0xdc, 0xf3, 0x4d, 0xcf, 0xcd, 0x46, + 0x59, 0x88, 0x19, 0x6f, 0xeb, 0xbc, 0x8f, 0x73, 0x19, 0xb9, 0x91, 0x99, 0x69, 0x18, 0x9b, 0x92, 0xe0, 0x1e, 0x70, + 0xa1, 0x24, 0xb0, 0x9c, 0xcb, 0xbf, 0x04, 0xc3, 0x9c, 0xd8, 0xfa, 0x07, 0xb6, 0xce, 0xf4, 0x3e, 0x1a, 0xc8, 0x55, + 0x8b, 0xfc, 0x8f, 0x76, 0xa5, 0xe9, 0x5f, 0x3a, 0x6b, 0x35, 0xcf, 0xd8, 0xc0, 0x0a, 0x1f, 0x50, 0x1d, 0x38, 0x40, + 0xaa, 0x17, 0x25, 0x41, 0xdc, 0x14, 0x5a, 0xf4, 0x32, 0x57, 0x9d, 0x68, 0xb4, 0x57, 0x6c, 0xc5, 0x38, 0xaf, 0xfd, + 0x97, 0xdb, 0x3d, 0x11, 0x73, 0x14, 0xa9, 0xa3, 0x86, 0x64, 0x2b, 0xf6, 0x87, 0xab, 0x4c, 0xe5, 0x9d, 0xe7, 0x2b, + 0x5f, 0xc1, 0x4b, 0xed, 0xef, 0xc8, 0x30, 0x24, 0xea, 0x42, 0xf5, 0xac, 0x80, 0xd7, 0xc7, 0x3f, 0x82, 0x7b, 0xa3, + 0x80, 0x28, 0xf8, 0x59, 0x21, 0xec, 0x9e, 0xcd, 0x6e, 0x3d, 0x1e, 0xfc, 0x3a, 0xae, 0xad, 0x75, 0x83, 0x67, 0x8a, + 0xff, 0xf8, 0x60, 0x15, 0x0e, 0x79, 0xe0, 0x7c, 0xa2, 0x77, 0xf7, 0xf3, 0xcb, 0x2f, 0x35, 0x7a, 0xfe, 0x42, 0xd8, + 0xcb, 0x56, 0x3a, 0x50, 0xd7, 0x28, 0x7e, 0xe2, 0x70, 0xac, 0x14, 0x35, 0xfc, 0x63, 0x9c, 0x38, 0x1f, 0xae, 0x8f, + 0x92, 0x69, 0x01, 0x16, 0x62, 0x1a, 0xba, 0x25, 0x71, 0x5e, 0x14, 0x67, 0xbd, 0xbb, 0x80, 0x9a, 0x4e, 0x7b, 0x80, + 0x52, 0x52, 0xcc, 0x13, 0x29, 0xd1, 0x5d, 0xfc, 0x9e, 0x9b, 0x4e, 0xee, 0xdc, 0xbe, 0x38, 0xac, 0x0f, 0x86, 0x6d, + 0x37, 0x19, 0xe3, 0x4f, 0x55, 0x9e, 0x30, 0xe2, 0x85, 0xb1, 0x2a, 0xe4, 0xf7, 0x08, 0x03, 0xfa, 0x7d, 0x38, 0x51, + 0x11, 0x7d, 0x3f, 0x00, 0xb8, 0xa7, 0x6e, 0x02, 0xaa, 0xf5, 0xf9, 0x4d, 0xef, 0x0a, 0x88, 0x26, 0x78, 0x51, 0xc9, + 0x6b, 0x80, 0x84, 0x5c, 0x5c, 0x9b, 0x72, 0x78, 0x37, 0x54, 0x24, 0xf4, 0xa1, 0x74, 0xce, 0xf4, 0x46, 0x06, 0x88, + 0xca, 0x31, 0x22, 0xbc, 0xe9, 0x4e, 0xf4, 0xa6, 0xbe, 0x87, 0x3f, 0x37, 0x63, 0xcf, 0x05, 0x86, 0x75, 0x6b, 0x7a, + 0xa6, 0x9f, 0x81, 0x6a, 0xc6, 0x9f, 0x7b, 0xd1, 0xd2, 0x53, 0xdb, 0x9a, 0x55, 0x8c, 0xc3, 0x5f, 0xcc, 0x83, 0x91, + 0xac, 0x2f, 0x2e, 0x22, 0xcc, 0x08, 0x6e, 0x56, 0x51, 0x2f, 0x2f, 0x59, 0xc2, 0xec, 0x6c, 0xd5, 0x38, 0xd0, 0x8c, + 0xb6, 0xa5, 0x07, 0xd7, 0xf9, 0x21, 0x96, 0xf1, 0x50, 0x1d, 0x5a, 0x3b, 0x8e, 0x6b, 0x9f, 0x41, 0x71, 0xb5, 0xc4, + 0x3f, 0x97, 0xf3, 0x25, 0xae, 0xf7, 0xcf, 0xfd, 0xb4, 0xd2, 0xdb, 0x54, 0xb3, 0x8f, 0xb9, 0xa5, 0x97, 0x24, 0xa4, + 0xef, 0x76, 0x18, 0xb0, 0x34, 0x19, 0x4c, 0xbe, 0x21, 0x39, 0xb0, 0x41, 0x95, 0x7c, 0x7a, 0xa0, 0xe7, 0x42, 0x07, + 0x2b, 0xa0, 0x1d, 0xf8, 0x0d, 0xcf, 0xeb, 0xb5, 0x10, 0x39, 0xdc, 0x20, 0x99, 0x00, 0x9d, 0x91, 0xc9, 0x85, 0xac, + 0xaa, 0x30, 0x81, 0x68, 0x2e, 0x21, 0x1a, 0xd4, 0x6d, 0x03, 0x67, 0x7c, 0x30, 0x29, 0x61, 0x3a, 0xdd, 0x2d, 0x95, + 0xce, 0x2b, 0x92, 0xa8, 0xeb, 0xfd, 0x30, 0xde, 0x0f, 0xcf, 0x3c, 0xc2, 0xbc, 0xdc, 0xee, 0x75, 0x91, 0xe5, 0xe5, + 0xd4, 0x42, 0xbb, 0x8f, 0xd9, 0xd1, 0x34, 0x5c, 0xea, 0x2e, 0xd8, 0x79, 0x60, 0x52, 0x5d, 0xd8, 0x83, 0x7d, 0x94, + 0x22, 0x4c, 0x73, 0xc9, 0xc8, 0xb2, 0xe8, 0xd2, 0x0c, 0xde, 0xe9, 0x00, 0x4f, 0x4b, 0xc4, 0x93, 0x20, 0xd2, 0xa4, + 0x17, 0x1b, 0x56, 0xd1, 0xe0, 0x6e, 0xd0, 0x9d, 0x19, 0x34, 0x54, 0x2c, 0x96, 0xea, 0xd1, 0x95, 0x72, 0x77, 0x62, + 0x69, 0x56, 0xd4, 0xf3, 0x81, 0x98, 0xec, 0xf9, 0x7a, 0x43, 0xaa, 0x14, 0x13, 0x16, 0xd1, 0xe8, 0xd3, 0x0f, 0x59, + 0xc5, 0x51, 0xc2, 0x62, 0xa5, 0xb8, 0xaa, 0xc8, 0xa9, 0xf1, 0xe6, 0x65, 0x56, 0x22, 0xed, 0xb0, 0x4c, 0x3c, 0x85, + 0x7c, 0x47, 0xd3, 0x4e, 0xcb, 0xac, 0xad, 0x62, 0x31, 0x7b, 0x02, 0x29, 0x11, 0x87, 0x75, 0x86, 0xb7, 0x65, 0x8e, + 0xd3, 0x60, 0x6d, 0xc9, 0xa9, 0x5f, 0xd0, 0x97, 0x30, 0xfb, 0x8c, 0xd5, 0x27, 0xa9, 0xd7, 0x91, 0x04, 0x28, 0xfe, + 0x4d, 0x1f, 0x04, 0x85, 0x5b, 0xfa, 0x7f, 0x7b, 0x6d, 0x38, 0x54, 0x0f, 0x75, 0xcf, 0x10, 0xab, 0x22, 0x15, 0xce, + 0xdd, 0x57, 0xe7, 0x93, 0x42, 0x3a, 0x99, 0x39, 0xe6, 0x91, 0x68, 0x2b, 0x2e, 0x07, 0x37, 0x2a, 0x23, 0x6a, 0x3a, + 0x7d, 0x50, 0x9d, 0xe1, 0xae, 0xde, 0xe7, 0x1a, 0xc2, 0xeb, 0x6a, 0x9f, 0xbb, 0xd3, 0x5b, 0xb1, 0xc5, 0x63, 0xae, + 0x4e, 0xdb, 0x89, 0x4b, 0xbb, 0xd4, 0xe9, 0x87, 0x23, 0xa8, 0xb8, 0x4c, 0xc4, 0x6c, 0x82, 0x0e, 0x2e, 0x8b, 0xa6, + 0x28, 0x75, 0xe9, 0x76, 0x92, 0x6b, 0x70, 0x07, 0x42, 0xaa, 0x72, 0x97, 0x19, 0x6e, 0xba, 0x10, 0x29, 0x3e, 0x93, + 0xae, 0x21, 0x92, 0xa2, 0x34, 0xbd, 0xe0, 0x34, 0x32, 0x72, 0xb7, 0x53, 0x99, 0x49, 0xeb, 0x90, 0x1a, 0xc7, 0x94, + 0x13, 0xf6, 0x32, 0x46, 0x70, 0xd0, 0xaa, 0x2f, 0x4b, 0x55, 0xe8, 0xfa, 0xa6, 0x67, 0xcb, 0x75, 0xfd, 0x87, 0x8f, + 0xc7, 0xcb, 0x51, 0x88, 0x2e, 0x6c, 0xaf, 0x94, 0x8e, 0x2c, 0xbd, 0x97, 0x8c, 0xb8, 0xe0, 0x50, 0xce, 0x5e, 0x0d, + 0x09, 0xb8, 0xa5, 0x57, 0x2c, 0xd2, 0xba, 0x71, 0x2d, 0xcb, 0xb4, 0x7b, 0xe5, 0x94, 0x49, 0x21, 0x56, 0xc6, 0x1a, + 0xc1, 0xfb, 0x69, 0xc4, 0xb0, 0xe9, 0x4d, 0xd8, 0x90, 0x4c, 0xcd, 0x5c, 0x6f, 0x28, 0x73, 0xf9, 0xa9, 0xf1, 0x23, + 0x36, 0x1a, 0x87, 0x60, 0xe8, 0xcc, 0x75, 0x1e, 0x0b, 0xe3, 0x0a, 0x66, 0x54, 0x23, 0xcb, 0x81, 0xb5, 0xd5, 0xda, + 0x0b, 0xb7, 0xa3, 0xde, 0x1c, 0x48, 0x7e, 0xe7, 0x65, 0xa6, 0x1a, 0xe3, 0xa0, 0xc5, 0x66, 0xed, 0x48, 0x23, 0x0a, + 0xbc, 0x78, 0x7a, 0x15, 0x41, 0xd1, 0xef, 0x49, 0x33, 0xc8, 0x41, 0x4b, 0xf5, 0xf5, 0xcf, 0x49, 0x89, 0xed, 0x98, + 0xa6, 0x05, 0x86, 0x59, 0xa5, 0x81, 0xbf, 0x26, 0x95, 0x86, 0x17, 0x36, 0x9f, 0x1f, 0xed, 0x12, 0xb9, 0xdc, 0xf3, + 0xac, 0xe6, 0x00, 0xc3, 0x74, 0xcc, 0x8d, 0x7f, 0x8f, 0xa2, 0x9f, 0x6c, 0x1c, 0x83, 0xd1, 0xd3, 0x2f, 0x4a, 0x3d, + 0x9b, 0x49, 0x7b, 0x5e, 0x53, 0x17, 0x70, 0x3c, 0x19, 0xe9, 0x00, 0x3c, 0x48, 0x27, 0x76, 0x1f, 0xc0, 0x25, 0x63, + 0x2f, 0x41, 0x17, 0xbb, 0xaf, 0x01, 0x48, 0xb6, 0x63, 0x8b, 0xdc, 0x8a, 0x91, 0xaf, 0x92, 0x4a, 0x79, 0x29, 0x7f, + 0x25, 0xb3, 0x11, 0xc0, 0xbe, 0x4a, 0x2f, 0x0f, 0xb8, 0x1b, 0xa5, 0xb7, 0x03, 0x82, 0xdd, 0x02, 0x61, 0xdf, 0x6d, + 0xd5, 0xa8, 0x81, 0xdd, 0x5f, 0x98, 0xb1, 0x69, 0x01, 0x1b, 0x19, 0xfa, 0xc3, 0xad, 0x4f, 0x94, 0x53, 0x10, 0x7e, + 0xff, 0xd2, 0xdc, 0x8d, 0x2b, 0x33, 0x18, 0x25, 0xb6, 0x43, 0x60, 0x3e, 0x53, 0xf9, 0x12, 0xe5, 0x27, 0xe1, 0xe5, + 0x6a, 0xd7, 0x9f, 0x95, 0x73, 0x29, 0xe6, 0xce, 0x35, 0xfc, 0x36, 0x1a, 0x3f, 0x2a, 0xed, 0x3a, 0xcf, 0xa2, 0x4b, + 0xdc, 0xe7, 0xfe, 0x3e, 0x80, 0x23, 0x6f, 0xcc, 0x87, 0x89, 0x7c, 0x27, 0x19, 0x56, 0x68, 0xf3, 0x76, 0x23, 0x3d, + 0xfc, 0xf6, 0x8d, 0xd4, 0x23, 0x7e, 0xac, 0x8a, 0xe0, 0xd7, 0x4d, 0x01, 0x6c, 0x82, 0x53, 0xcf, 0x5f, 0x37, 0xa9, + 0xe3, 0xc7, 0x4b, 0x48, 0xfa, 0x26, 0xcc, 0xdd, 0xbb, 0xd9, 0xe0, 0xe9, 0x10, 0x9e, 0x65, 0x44, 0x07, 0x03, 0x99, + 0x5b, 0x93, 0x1b, 0xf4, 0x5f, 0x30, 0xcd, 0xb7, 0x83, 0xc0, 0x26, 0x9e, 0x25, 0x15, 0x5f, 0x74, 0xf7, 0x36, 0x34, + 0x75, 0x10, 0x15, 0x0d, 0xc4, 0x25, 0x1b, 0xb8, 0xd9, 0x0a, 0xca, 0x73, 0x63, 0xa8, 0xb3, 0xe7, 0x88, 0xdd, 0x56, + 0xda, 0xbd, 0x95, 0x8b, 0x57, 0x94, 0xa8, 0x11, 0x50, 0x21, 0xe8, 0x2e, 0x7f, 0x28, 0xf7, 0x25, 0xdd, 0x59, 0x69, + 0xca, 0x5c, 0x24, 0x98, 0xd7, 0x05, 0x55, 0x3f, 0x80, 0x04, 0xb4, 0x0f, 0x09, 0xa8, 0xd0, 0x7d, 0xf9, 0x35, 0x93, + 0x79, 0xeb, 0x49, 0xac, 0xab, 0xf0, 0xc3, 0x00, 0x0e, 0xff, 0xa5, 0x21, 0x23, 0x21, 0x7b, 0xb9, 0x5f, 0xd7, 0x43, + 0xdd, 0xd2, 0x71, 0x1b, 0xab, 0x79, 0xa0, 0xac, 0x23, 0x1c, 0x27, 0x56, 0xdb, 0xef, 0x06, 0xa4, 0xe5, 0xb8, 0xbf, + 0xaa, 0xe9, 0xd2, 0x6e, 0x5e, 0x87, 0x61, 0x1d, 0xb6, 0x86, 0xe5, 0x17, 0xe6, 0x8a, 0x87, 0xf6, 0x1c, 0xfe, 0xdb, + 0x57, 0xc6, 0x97, 0x34, 0xfb, 0xbf, 0x15, 0x4f, 0x83, 0x44, 0xd3, 0x67, 0x29, 0x92, 0x30, 0x4a, 0xf7, 0x27, 0x12, + 0x25, 0x0d, 0x24, 0x72, 0x70, 0x2f, 0xdf, 0xd2, 0xf8, 0x57, 0xa5, 0x2c, 0x43, 0x87, 0xcb, 0x66, 0x07, 0x32, 0x6f, + 0x9d, 0xbb, 0xbf, 0x1c, 0x7a, 0x0b, 0x54, 0xe9, 0x14, 0x26, 0x2f, 0x3d, 0x5c, 0xb1, 0x65, 0xcf, 0x62, 0xe8, 0xa7, + 0x60, 0x2a, 0x46, 0xb2, 0x19, 0x26, 0xe6, 0x2a, 0x85, 0xc8, 0x2f, 0x8f, 0x3a, 0xb9, 0xbb, 0xe5, 0x6f, 0x6e, 0x7d, + 0xbc, 0x28, 0x79, 0x63, 0x76, 0x66, 0x7b, 0x3e, 0x76, 0xfb, 0x3d, 0x2b, 0x72, 0x27, 0xec, 0x74, 0xf4, 0x0e, 0xb9, + 0xe6, 0x4e, 0x68, 0x2a, 0x60, 0xb9, 0x38, 0x4f, 0xad, 0xd4, 0xc4, 0xa0, 0x44, 0x28, 0x23, 0xf1, 0x0f, 0xd1, 0x36, + 0xec, 0x25, 0x55, 0xf7, 0x1e, 0x84, 0x62, 0xdb, 0x23, 0x11, 0x48, 0xf1, 0x8f, 0x82, 0x52, 0x4a, 0x58, 0x97, 0x46, + 0x99, 0x29, 0x3f, 0xa1, 0xb0, 0x03, 0x07, 0x01, 0x1f, 0x12, 0x68, 0x69, 0x28, 0xeb, 0xbf, 0xdf, 0x30, 0xea, 0xb2, + 0x1f, 0x4b, 0xf2, 0x57, 0x8d, 0xea, 0x5a, 0xa2, 0x7f, 0xbc, 0xcc, 0x4f, 0x69, 0x0a, 0x1e, 0x14, 0x7a, 0x5d, 0x3b, + 0xdd, 0x27, 0x4c, 0x6d, 0x57, 0x2e, 0x12, 0x5f, 0xda, 0x53, 0xfe, 0x08, 0x6a, 0xd3, 0xd4, 0xd8, 0x5c, 0x2f, 0x54, + 0x33, 0xa5, 0x28, 0x2b, 0xbc, 0x6a, 0x2c, 0xb4, 0xe2, 0x90, 0x54, 0x49, 0x9c, 0x33, 0xf7, 0xd8, 0xd5, 0x9b, 0xf0, + 0x82, 0x30, 0x50, 0x60, 0x92, 0x59, 0x6c, 0x44, 0x5f, 0xa1, 0x2f, 0xe9, 0xcb, 0x74, 0xb5, 0x1f, 0x19, 0xf0, 0x06, + 0x87, 0xa3, 0x55, 0x0d, 0xf9, 0x2a, 0x25, 0xaa, 0x44, 0x31, 0x88, 0x52, 0xc7, 0x6f, 0x60, 0x0b, 0xcc, 0xcf, 0x27, + 0x0b, 0xfa, 0xba, 0xac, 0x39, 0x65, 0xbf, 0x59, 0xf3, 0x27, 0x43, 0x7e, 0x3c, 0x6e, 0x91, 0xbb, 0x8e, 0xc8, 0x25, + 0x42, 0xd4, 0x9f, 0xdf, 0x76, 0xad, 0x27, 0x22, 0x9f, 0xd7, 0x66, 0xb1, 0xd8, 0xe5, 0x02, 0xf6, 0x9b, 0xb3, 0x72, + 0xe3, 0xc4, 0xae, 0x3f, 0xf2, 0xc4, 0x33, 0xf9, 0xc4, 0x6d, 0x18, 0x28, 0xef, 0x61, 0xbd, 0xb0, 0x74, 0x4d, 0x02, + 0x50, 0x62, 0xe8, 0xd3, 0xaf, 0x50, 0xad, 0xec, 0x58, 0x6c, 0x2e, 0x79, 0x52, 0x86, 0x40, 0xf1, 0xf5, 0xfd, 0x25, + 0xf9, 0x34, 0x56, 0x20, 0xa5, 0x61, 0x1e, 0x81, 0x45, 0x31, 0x14, 0x35, 0xd4, 0x72, 0xf1, 0x06, 0x6f, 0x60, 0x08, + 0x5f, 0x68, 0x75, 0xb8, 0x6c, 0x37, 0x08, 0x77, 0xc9, 0x8e, 0x95, 0x4e, 0x29, 0x57, 0xe3, 0x00, 0x84, 0x97, 0x3f, + 0x02, 0x50, 0x17, 0x6a, 0x4d, 0xb0, 0xb7, 0x72, 0xb2, 0xdf, 0xdc, 0x11, 0x34, 0xc0, 0x7b, 0xff, 0x2c, 0xfe, 0x74, + 0xfc, 0x41, 0x21, 0x75, 0x27, 0xe5, 0xb5, 0x54, 0xba, 0xd5, 0x7a, 0x4b, 0xba, 0x57, 0xb0, 0xdd, 0x5c, 0xf5, 0x26, + 0xa3, 0x54, 0xeb, 0xfc, 0x3e, 0x19, 0x28, 0x30, 0x53, 0x4d, 0x28, 0x5d, 0x1c, 0x49, 0xed, 0x92, 0x9e, 0x2e, 0x6b, + 0xe8, 0x6f, 0x39, 0xb1, 0x15, 0xec, 0x8f, 0xab, 0x63, 0xc9, 0xb7, 0xf8, 0xfc, 0x2b, 0xc0, 0xde, 0x95, 0x1f, 0xfe, + 0x24, 0xcc, 0xcf, 0x45, 0x97, 0x36, 0xea, 0x91, 0xa3, 0x9e, 0xf7, 0xb7, 0x3c, 0xfa, 0x09, 0xb2, 0x1d, 0x9b, 0x87, + 0xbc, 0xdf, 0xbf, 0xf9, 0xb5, 0x6b, 0xfc, 0xd4, 0x4e, 0x36, 0xa1, 0xd9, 0xb5, 0xf2, 0x5e, 0x7e, 0x0f, 0xfe, 0xe4, + 0x76, 0x8f, 0x4c, 0xaa, 0x61, 0x75, 0x06, 0x7e, 0x18, 0x64, 0x85, 0x5e, 0xfd, 0xb4, 0x67, 0x98, 0x93, 0x7d, 0x88, + 0x1a, 0xdc, 0xe4, 0x86, 0xc6, 0xae, 0x19, 0xd3, 0xb0, 0xad, 0xaf, 0xf1, 0x5c, 0xa3, 0x9c, 0xef, 0x6b, 0xd5, 0x90, + 0xeb, 0xac, 0xa7, 0xd5, 0xf3, 0x8d, 0x09, 0x9c, 0x01, 0x6e, 0x75, 0xc5, 0x2c, 0xa4, 0x20, 0xf9, 0xd6, 0x9e, 0x83, + 0xdb, 0x6a, 0x20, 0xe4, 0x9d, 0x73, 0x9f, 0x48, 0x81, 0x3f, 0xed, 0x7a, 0x27, 0x93, 0x55, 0xbf, 0xf1, 0xad, 0xda, + 0x6d, 0xff, 0xef, 0x46, 0xfc, 0xa3, 0x90, 0x3a, 0x7d, 0xce, 0x9f, 0x42, 0x58, 0x88, 0x6f, 0x74, 0x82, 0x2b, 0xe8, + 0x56, 0x95, 0xc2, 0xbc, 0x97, 0x36, 0xe7, 0xbd, 0x32, 0x07, 0x2d, 0x29, 0xe3, 0x09, 0x5b, 0x5c, 0xd4, 0xdb, 0x6e, + 0x46, 0xe9, 0x16, 0xe6, 0x47, 0x57, 0x2a, 0xb0, 0x20, 0x21, 0x49, 0x53, 0x64, 0xf0, 0x4f, 0x72, 0xe4, 0xb9, 0x0a, + 0x21, 0xdd, 0x68, 0xd2, 0x51, 0x67, 0xb5, 0xb8, 0xa9, 0xe3, 0x93, 0xf8, 0xb4, 0x46, 0xbb, 0xd6, 0x09, 0xff, 0x40, + 0xff, 0x3a, 0xd5, 0x4a, 0xfe, 0xfb, 0x54, 0x37, 0xf2, 0x5f, 0x67, 0x3a, 0x91, 0xff, 0x3e, 0xd3, 0xae, 0x87, 0x57, + 0x8f, 0xac, 0xab, 0x27, 0xd6, 0xd5, 0x33, 0x6b, 0xcc, 0x90, 0x1e, 0x5a, 0xe7, 0x3a, 0xff, 0xec, 0xc4, 0xf9, 0xa4, + 0xb5, 0x64, 0x9f, 0x6f, 0x95, 0xc2, 0x92, 0xf5, 0x6f, 0x27, 0xcd, 0x7c, 0x56, 0x4d, 0xe5, 0xe3, 0x01, 0x2a, 0x4f, + 0x3e, 0x0e, 0xea, 0x5c, 0x45, 0x44, 0x8d, 0x59, 0x51, 0x7b, 0xca, 0xec, 0xee, 0x9d, 0x78, 0x32, 0x7d, 0x88, 0xe8, + 0x6d, 0xe9, 0x66, 0xa8, 0xf4, 0x40, 0x7e, 0x6a, 0xd8, 0xb1, 0x11, 0xf5, 0xa0, 0xf1, 0xd2, 0xdd, 0x23, 0x31, 0xbe, + 0x5f, 0x0a, 0x11, 0x2b, 0xd2, 0x0a, 0x8a, 0x6f, 0x30, 0xf5, 0x50, 0xab, 0x16, 0x7b, 0xee, 0xc7, 0x6c, 0xe9, 0x5e, + 0x52, 0x62, 0x10, 0xc6, 0x76, 0x85, 0xff, 0x2c, 0xc0, 0xaa, 0xf8, 0x99, 0x59, 0x3a, 0x6d, 0xe6, 0x68, 0xe9, 0xf4, + 0x4b, 0xb6, 0x20, 0x5e, 0x86, 0x31, 0xdd, 0x91, 0x64, 0xec, 0x2e, 0x14, 0x5c, 0x41, 0x36, 0x7f, 0x8c, 0x8a, 0x7f, + 0x8a, 0xd5, 0xc3, 0xd3, 0x07, 0x65, 0x18, 0xfc, 0x4f, 0x13, 0xed, 0xa0, 0x1d, 0xa1, 0x8e, 0x71, 0xba, 0x25, 0x15, + 0xee, 0x0b, 0x14, 0xaf, 0xe7, 0xfe, 0x14, 0x55, 0xdf, 0x3a, 0x25, 0x24, 0x2e, 0x67, 0xdb, 0xcf, 0xdd, 0x1c, 0x7a, + 0xb2, 0xcf, 0x8f, 0x29, 0xc8, 0x4d, 0x37, 0xfc, 0x26, 0x58, 0x65, 0xf3, 0xc6, 0x6a, 0x57, 0x4f, 0xe2, 0xf2, 0x97, + 0xff, 0xd3, 0x7e, 0x9e, 0x40, 0xfb, 0xfd, 0x49, 0x3f, 0xf2, 0xd3, 0xe3, 0x18, 0x9d, 0x78, 0x33, 0x47, 0x1f, 0x7e, + 0x2e, 0xca, 0x37, 0xfb, 0x54, 0x3d, 0x4e, 0x76, 0xf3, 0x47, 0xf4, 0x1c, 0xfd, 0xd4, 0x6d, 0x35, 0xfd, 0xc7, 0x09, + 0xb4, 0xcf, 0x9f, 0xf5, 0xe3, 0xb3, 0x3b, 0x68, 0xfa, 0x23, 0xd3, 0xe4, 0x91, 0xcd, 0xf2, 0x95, 0xc5, 0x47, 0x59, + 0xd7, 0x38, 0xdc, 0x4c, 0x73, 0xad, 0x2b, 0x3c, 0xbd, 0xe9, 0x78, 0xa8, 0x8a, 0xc5, 0x31, 0x3e, 0x3d, 0x9e, 0xe0, + 0x43, 0x36, 0xfa, 0xcc, 0xe8, 0x52, 0x44, 0xef, 0xc9, 0x31, 0x44, 0x97, 0xcd, 0xa7, 0xe4, 0x2c, 0x9e, 0x3b, 0x47, + 0x5b, 0xe5, 0x1a, 0x59, 0x18, 0xb5, 0x86, 0xa7, 0xb8, 0x31, 0xfc, 0x9e, 0x53, 0x0e, 0x0c, 0x56, 0x22, 0xb5, 0x87, + 0xa9, 0x62, 0x7a, 0x4b, 0xa2, 0x4f, 0x4a, 0x71, 0xd4, 0x7e, 0x1b, 0x5d, 0x0d, 0x85, 0x27, 0x0f, 0x1c, 0xd5, 0x55, + 0x39, 0x7c, 0xc6, 0x49, 0xef, 0xdc, 0x88, 0xfa, 0xcb, 0xe0, 0x9b, 0x38, 0xd3, 0xa5, 0xeb, 0x4f, 0xd7, 0x91, 0x4f, + 0xba, 0x49, 0x53, 0x56, 0x6f, 0xab, 0xe9, 0x62, 0x8c, 0xce, 0x24, 0xcf, 0x82, 0x94, 0x10, 0x61, 0xac, 0xf0, 0xfc, + 0xf3, 0x69, 0xdb, 0x84, 0x09, 0xdb, 0x24, 0xaf, 0x05, 0x55, 0x44, 0xff, 0xf1, 0x90, 0x3a, 0x1c, 0xc4, 0x86, 0xea, + 0x5d, 0xdf, 0x1e, 0x33, 0xac, 0xcd, 0x8c, 0x78, 0xab, 0xc8, 0x3d, 0x0e, 0x92, 0x59, 0x16, 0x1f, 0x54, 0x9b, 0xe2, + 0xf7, 0xea, 0xc4, 0x38, 0x8d, 0x1a, 0x8f, 0x70, 0x66, 0xa6, 0xcd, 0xd9, 0x8e, 0x17, 0xf5, 0xae, 0xd6, 0x2f, 0x4f, + 0xc7, 0x87, 0xfe, 0xe1, 0x10, 0x2e, 0xe5, 0x61, 0x41, 0x7c, 0x5a, 0x3c, 0x8b, 0x1d, 0x1b, 0x27, 0xe3, 0xf0, 0x3f, + 0xb5, 0x23, 0xe3, 0x4e, 0x51, 0xc2, 0xa9, 0x7e, 0x9a, 0xd2, 0x59, 0xee, 0xa3, 0xe2, 0x1e, 0xb0, 0x1d, 0xce, 0x85, + 0xdb, 0x3d, 0x8f, 0x8c, 0xe8, 0x40, 0x55, 0x5f, 0xbf, 0x83, 0xe6, 0x5f, 0xe3, 0xfa, 0x0e, 0x14, 0xb1, 0xbe, 0xbf, + 0x9c, 0x62, 0x4e, 0x57, 0xe0, 0x98, 0x6f, 0xf9, 0x8e, 0x55, 0x13, 0xcf, 0xea, 0xaf, 0x87, 0xa7, 0x58, 0x85, 0x43, + 0xc1, 0x49, 0xc1, 0x21, 0xb1, 0x69, 0xca, 0x50, 0x38, 0xac, 0x11, 0x7e, 0xf5, 0x69, 0xea, 0x74, 0x71, 0x02, 0xe7, + 0x06, 0xc1, 0x54, 0x0b, 0xda, 0xf3, 0x63, 0x24, 0xde, 0x96, 0xa7, 0x85, 0x22, 0x1b, 0x9c, 0xa3, 0xf2, 0xd7, 0xcc, + 0x62, 0xe7, 0x70, 0x91, 0xff, 0xf3, 0x84, 0x3f, 0x1c, 0x43, 0xd0, 0xc8, 0xb2, 0x63, 0xf1, 0x9b, 0x49, 0x19, 0xde, + 0x3e, 0xe6, 0x5a, 0xb1, 0xa9, 0x27, 0xe3, 0x1f, 0x0e, 0x69, 0x66, 0x1f, 0x3d, 0xa2, 0xac, 0x40, 0xb4, 0xdd, 0xd9, + 0x56, 0x3f, 0x19, 0xa2, 0x96, 0x67, 0xca, 0x93, 0xfd, 0x04, 0xef, 0xd2, 0x0f, 0xf6, 0x83, 0x71, 0x3c, 0x48, 0x42, + 0x43, 0x65, 0xa5, 0x3f, 0x46, 0x85, 0x22, 0x9d, 0xaf, 0xf5, 0xa9, 0x0e, 0x5c, 0x09, 0x05, 0x4c, 0xb9, 0xd6, 0x5c, + 0x33, 0x1c, 0xdb, 0xf2, 0x2c, 0x2f, 0x8c, 0x2d, 0xc0, 0xa7, 0xfc, 0x2a, 0x44, 0x1b, 0x9c, 0x1b, 0x51, 0x16, 0xc8, + 0x44, 0x17, 0x45, 0x5f, 0xb3, 0x38, 0x34, 0xbb, 0x6a, 0x30, 0x4e, 0x43, 0x7f, 0xbd, 0x76, 0x3d, 0xd7, 0x29, 0x65, + 0x2d, 0x72, 0xe7, 0xa6, 0x63, 0x19, 0x36, 0x14, 0x39, 0xe5, 0x66, 0x3e, 0x91, 0x42, 0xdd, 0x40, 0x6f, 0x01, 0xae, + 0x9b, 0xf1, 0xc7, 0x2c, 0x90, 0xc4, 0x6a, 0x00, 0x06, 0x59, 0xfc, 0x8e, 0x00, 0x40, 0x49, 0x5f, 0x94, 0x81, 0x37, + 0x1c, 0x6e, 0x78, 0x5d, 0xd0, 0x5b, 0xed, 0xca, 0xe5, 0x29, 0x16, 0xee, 0xec, 0xf6, 0x3f, 0xaa, 0x27, 0xcf, 0xa1, + 0xb2, 0x23, 0xf3, 0xe9, 0xac, 0xb9, 0x87, 0xb8, 0x95, 0x21, 0xbf, 0x20, 0xe0, 0x02, 0x24, 0x50, 0x3a, 0xc2, 0x39, + 0xe3, 0x92, 0x6b, 0xdc, 0x55, 0xb3, 0x84, 0x12, 0x2c, 0xa1, 0xe3, 0xe7, 0x56, 0xd1, 0x81, 0x7a, 0x57, 0x4f, 0xb7, + 0xee, 0x41, 0x4a, 0xc9, 0xa7, 0x15, 0xeb, 0xc4, 0xf1, 0xfa, 0x35, 0x89, 0xe8, 0xc9, 0x43, 0x79, 0x9a, 0x73, 0x01, + 0xf9, 0x2d, 0x1b, 0x15, 0x33, 0xf3, 0x54, 0x8f, 0xfc, 0xd4, 0x14, 0xeb, 0xf6, 0x70, 0x07, 0xf4, 0xb4, 0x81, 0xf8, + 0x41, 0x71, 0x3f, 0x8b, 0xbc, 0xc6, 0xc3, 0x2c, 0x30, 0x8b, 0x98, 0x5a, 0x8d, 0x34, 0x3b, 0x52, 0x12, 0xd6, 0x42, + 0x26, 0x68, 0xae, 0x33, 0xb2, 0x69, 0xd7, 0x68, 0x17, 0x05, 0x46, 0x34, 0x1d, 0x6c, 0xaf, 0x91, 0x0c, 0xba, 0x8d, + 0xeb, 0x88, 0x10, 0x43, 0x05, 0xe8, 0xe3, 0x20, 0x14, 0xca, 0x3e, 0xa3, 0xf2, 0x22, 0x37, 0xeb, 0xe7, 0x42, 0x30, + 0x5a, 0x98, 0xa1, 0xaa, 0x1c, 0xbb, 0xa6, 0x40, 0xbe, 0x88, 0x8d, 0x20, 0x3b, 0xe5, 0xe3, 0x65, 0x3b, 0x55, 0x3d, + 0xdc, 0x44, 0xd5, 0x3f, 0xb0, 0xde, 0x5e, 0xb4, 0x7d, 0xc0, 0x2f, 0xb5, 0x23, 0xb7, 0x05, 0xae, 0x46, 0xe3, 0x9c, + 0x24, 0x8e, 0xdc, 0x3c, 0xce, 0xf5, 0x83, 0x59, 0x9f, 0xb4, 0xd6, 0x0e, 0xf2, 0x29, 0x02, 0x56, 0x29, 0x75, 0x92, + 0x5e, 0xfb, 0x28, 0xe3, 0xf1, 0x20, 0x21, 0x29, 0x5f, 0x30, 0x3e, 0x9b, 0x7d, 0xe6, 0x45, 0xc9, 0x02, 0xb3, 0x88, + 0x4a, 0xac, 0xc1, 0x74, 0x6c, 0x97, 0xc8, 0x48, 0x77, 0x02, 0xa7, 0x72, 0xac, 0x28, 0xec, 0x6e, 0x57, 0xb3, 0x6f, + 0x26, 0x6f, 0x4d, 0xea, 0x3b, 0xc6, 0x5c, 0xd0, 0x6b, 0xa3, 0xb4, 0x01, 0xb4, 0x07, 0x03, 0x87, 0xd5, 0x85, 0xd9, + 0x69, 0x35, 0xdb, 0xd4, 0x33, 0x62, 0x73, 0xd3, 0xd3, 0xd5, 0x44, 0x3f, 0x43, 0xc0, 0x38, 0x36, 0x8a, 0x7b, 0x6c, + 0x11, 0x6b, 0xe4, 0x35, 0xb5, 0x84, 0xd9, 0xb2, 0x70, 0x2b, 0x46, 0x73, 0x02, 0x63, 0x8c, 0xc9, 0x41, 0x0c, 0x9e, + 0x9b, 0xc3, 0x66, 0x4d, 0x4c, 0xa0, 0x6a, 0x7f, 0x53, 0x46, 0x96, 0xac, 0x62, 0x96, 0x06, 0x32, 0x2c, 0x03, 0x65, + 0xef, 0x85, 0x96, 0x3e, 0xda, 0xb9, 0x10, 0x6a, 0xda, 0xb6, 0xec, 0x36, 0x74, 0x48, 0x81, 0x0f, 0x4c, 0xb7, 0x3b, + 0x07, 0xae, 0xd8, 0xa3, 0xe0, 0x9d, 0xc1, 0xe3, 0x0f, 0xb3, 0x67, 0xc9, 0xef, 0x79, 0xa1, 0xca, 0xf5, 0x89, 0x8e, + 0x76, 0x0b, 0xc8, 0xc4, 0xec, 0xda, 0x96, 0x8f, 0xf6, 0x39, 0x3d, 0x64, 0xb8, 0x82, 0x8c, 0x23, 0x49, 0x11, 0x95, + 0xaf, 0xf4, 0x2a, 0xcb, 0x58, 0xb0, 0xcc, 0x65, 0xcc, 0x92, 0x9a, 0x4c, 0xaa, 0xbd, 0x9b, 0xc1, 0x93, 0xd7, 0x2c, + 0x4c, 0xa6, 0xb0, 0x66, 0x9b, 0x5d, 0x29, 0x47, 0x13, 0x44, 0x26, 0x71, 0x92, 0x64, 0x74, 0x06, 0x1f, 0x04, 0xa2, + 0xe4, 0x44, 0x50, 0xcd, 0xbe, 0x1f, 0xd5, 0x64, 0xad, 0x83, 0x51, 0x49, 0x95, 0xc1, 0xeb, 0x26, 0x45, 0x84, 0x26, + 0x49, 0xbe, 0x76, 0xc4, 0x64, 0x5b, 0xc7, 0xb9, 0x62, 0x95, 0x65, 0x1b, 0x47, 0x16, 0xb9, 0xd2, 0x90, 0x4a, 0x13, + 0xbd, 0xa0, 0x74, 0xe5, 0x5d, 0x28, 0x80, 0x88, 0x43, 0x2b, 0xc8, 0xed, 0xa5, 0x31, 0x13, 0x88, 0xf4, 0xc8, 0xfa, + 0x70, 0x64, 0x2b, 0xe9, 0x62, 0xa3, 0x14, 0x2c, 0x9e, 0x10, 0x16, 0x19, 0x7b, 0xc6, 0xea, 0x6f, 0xbf, 0x6b, 0x8a, + 0xb5, 0xdf, 0x1e, 0xd8, 0x9e, 0xff, 0xdd, 0xfb, 0xfd, 0x48, 0x01, 0x18, 0x71, 0x2f, 0x47, 0x44, 0xfc, 0x56, 0xe7, + 0xb7, 0x88, 0xdf, 0x7c, 0xfe, 0x6d, 0x78, 0x81, 0xae, 0x6b, 0x6c, 0x98, 0x69, 0xe7, 0x56, 0x95, 0x8e, 0xd8, 0x10, + 0x0b, 0xef, 0xf5, 0x29, 0xe9, 0x69, 0x22, 0xc3, 0xfe, 0xd1, 0xcc, 0x0a, 0xd5, 0xf4, 0x29, 0x21, 0xda, 0xc0, 0x64, + 0x84, 0x94, 0xbd, 0x14, 0xcc, 0xba, 0x75, 0xea, 0xe6, 0xb6, 0x18, 0x9f, 0x8f, 0x89, 0x75, 0xcb, 0xbf, 0xd2, 0xc5, + 0xc5, 0x84, 0x61, 0xd0, 0x15, 0x6f, 0xde, 0xb3, 0xe1, 0x50, 0xaa, 0x30, 0x06, 0x9a, 0xc3, 0x59, 0x54, 0x11, 0xa3, + 0x96, 0x71, 0xe7, 0x0e, 0xb8, 0x8e, 0x1e, 0xf0, 0x1b, 0xaa, 0x6a, 0x2c, 0x19, 0x9d, 0xbe, 0xad, 0x63, 0xc8, 0xd7, + 0x91, 0x55, 0x1c, 0xbf, 0xce, 0x53, 0xd0, 0xfb, 0x6e, 0x2a, 0xd7, 0xae, 0x2a, 0x88, 0x7e, 0x96, 0x20, 0xb1, 0x26, + 0x1f, 0x77, 0x6c, 0x95, 0x1b, 0x7f, 0x3e, 0xd5, 0x54, 0xdb, 0x20, 0xb4, 0x2c, 0xc5, 0x82, 0x9d, 0x88, 0x05, 0x2b, + 0xc2, 0xa7, 0x2f, 0x62, 0xd0, 0x38, 0xab, 0x02, 0x67, 0x1f, 0xac, 0x5c, 0xc5, 0x87, 0x2f, 0x01, 0x3a, 0xa9, 0xea, + 0xff, 0x20, 0x71, 0x9d, 0x9d, 0x6e, 0xc9, 0x5f, 0xfb, 0x33, 0x25, 0x82, 0x49, 0x4b, 0x08, 0x81, 0x33, 0xe2, 0xb7, + 0xbe, 0x3c, 0x41, 0x06, 0xb0, 0x66, 0xb4, 0x6b, 0xbf, 0x9c, 0x0c, 0xd3, 0x90, 0x10, 0x35, 0x6b, 0xd8, 0xbb, 0x78, + 0x85, 0x0e, 0x44, 0x62, 0xd0, 0xe4, 0x4d, 0xf0, 0x2b, 0xd5, 0x52, 0xb9, 0xe6, 0x9f, 0x77, 0x73, 0xb9, 0x38, 0xb2, + 0x71, 0x64, 0x65, 0xa1, 0xc0, 0xd7, 0x01, 0xf4, 0x09, 0x9a, 0x13, 0x17, 0xfe, 0x38, 0x4b, 0x5a, 0x64, 0x67, 0xf2, + 0x40, 0xdd, 0x40, 0xc9, 0x62, 0xa5, 0x78, 0x5f, 0x02, 0x1f, 0x94, 0xc1, 0x36, 0x7c, 0x26, 0x71, 0x51, 0x65, 0x4d, + 0xab, 0x7e, 0x8c, 0x5b, 0x88, 0x98, 0x09, 0x65, 0x20, 0x24, 0x39, 0x2b, 0x71, 0x43, 0x65, 0xc5, 0xd1, 0x9d, 0xc5, + 0x02, 0x4c, 0x90, 0xcc, 0x46, 0x04, 0xfe, 0x25, 0x2c, 0x9e, 0x8b, 0x9f, 0xe9, 0xbd, 0x0d, 0x34, 0x31, 0x22, 0x92, + 0x5d, 0xf4, 0x6a, 0x45, 0x0f, 0x76, 0x69, 0x0c, 0x1f, 0x12, 0xc5, 0xb1, 0x7d, 0xde, 0x0f, 0x1a, 0x35, 0x00, 0x0a, + 0x16, 0xdb, 0x92, 0xba, 0x64, 0xde, 0x5e, 0x7b, 0xb9, 0xab, 0xc3, 0xdd, 0x55, 0x08, 0x0a, 0x7c, 0xb6, 0x99, 0x54, + 0x1e, 0x09, 0x64, 0x8d, 0x2d, 0xe6, 0x89, 0xe8, 0x15, 0xd3, 0x95, 0xd1, 0x45, 0x91, 0xad, 0xe3, 0x37, 0x04, 0x8a, + 0x9c, 0x5d, 0x22, 0x31, 0x65, 0x3f, 0x47, 0xb9, 0xe4, 0x42, 0x63, 0x75, 0x24, 0x2f, 0x76, 0x35, 0x88, 0x97, 0xa9, + 0x09, 0x30, 0x05, 0x79, 0x67, 0x46, 0x23, 0x44, 0x54, 0x92, 0x48, 0x11, 0x90, 0x98, 0x4b, 0x3e, 0xc5, 0x43, 0xc8, + 0x4f, 0x15, 0x12, 0x5a, 0x32, 0x94, 0xff, 0xe1, 0x3a, 0xc1, 0xb7, 0x0a, 0x78, 0x91, 0xd4, 0x2f, 0x3c, 0x70, 0x5b, + 0xda, 0xeb, 0x94, 0x0d, 0x12, 0xf0, 0xfd, 0xf4, 0xf0, 0x59, 0x67, 0x0f, 0xe2, 0x27, 0x45, 0x40, 0xf0, 0x41, 0xaf, + 0x6a, 0xb7, 0x4c, 0xa1, 0x92, 0x6a, 0x48, 0xb9, 0x1f, 0x5d, 0x72, 0x3a, 0xe1, 0xf0, 0x02, 0xfe, 0xf1, 0xfd, 0x7c, + 0x03, 0x73, 0xf0, 0x95, 0xae, 0x9a, 0x48, 0xde, 0x0d, 0x83, 0x3d, 0x85, 0xf4, 0x12, 0x0e, 0x6d, 0x5f, 0x23, 0xcc, + 0x76, 0xae, 0xb5, 0xd9, 0xfe, 0xc4, 0x50, 0xa7, 0xd3, 0x8f, 0xdf, 0xc4, 0x46, 0x8d, 0x14, 0xb7, 0x4e, 0xc4, 0x42, + 0x49, 0x3f, 0x7b, 0x72, 0x63, 0x69, 0x3a, 0x56, 0x6f, 0x43, 0xcd, 0xe3, 0x9b, 0x63, 0x3d, 0x79, 0xb3, 0x6c, 0xc9, + 0x07, 0x98, 0x70, 0xcc, 0xb7, 0xa2, 0xe7, 0x59, 0xd9, 0x0b, 0xa6, 0xd6, 0x1f, 0x34, 0x42, 0x62, 0xa8, 0x22, 0xa9, + 0xd7, 0xc0, 0xfb, 0x3a, 0xad, 0x3d, 0xab, 0x67, 0x44, 0xe9, 0xd4, 0x54, 0xac, 0x79, 0xa1, 0x5e, 0x28, 0x53, 0x95, + 0x5a, 0xe6, 0xce, 0x56, 0xd9, 0x53, 0x2c, 0x2f, 0x65, 0x32, 0xc2, 0x7e, 0x02, 0x51, 0x89, 0xef, 0xa1, 0x9e, 0xc4, + 0xba, 0x33, 0xa7, 0x4f, 0xcc, 0xa4, 0x81, 0xf1, 0x11, 0x31, 0x02, 0xab, 0x78, 0x1b, 0x18, 0x26, 0x6a, 0x8d, 0x0b, + 0xdd, 0x91, 0xd1, 0x3a, 0x7c, 0xc3, 0x3d, 0x61, 0x7d, 0x2f, 0xc8, 0x6e, 0xf8, 0xef, 0x99, 0x70, 0xdb, 0xcb, 0x3c, + 0x9a, 0x29, 0xbd, 0x79, 0x7c, 0x1c, 0xd1, 0xf4, 0x96, 0xca, 0x91, 0x2d, 0xe8, 0xae, 0xd7, 0xb0, 0xf1, 0x47, 0x41, + 0xf5, 0x58, 0xba, 0x19, 0x19, 0x31, 0x8e, 0x07, 0x83, 0x24, 0xe8, 0x43, 0xce, 0xaf, 0xa4, 0xe5, 0x79, 0x48, 0x5b, + 0x4c, 0xd8, 0x83, 0xe5, 0x14, 0x99, 0x18, 0x2e, 0xc1, 0xdc, 0xe6, 0x6c, 0xde, 0x7c, 0xe3, 0x8f, 0xc3, 0x9e, 0x4a, + 0x54, 0xc8, 0x83, 0x73, 0xdf, 0xca, 0x38, 0x4d, 0x1a, 0x28, 0x96, 0x31, 0x97, 0xf9, 0x61, 0x53, 0x47, 0xdb, 0xa1, + 0x50, 0x4d, 0xed, 0x9c, 0x7e, 0x9d, 0xec, 0xd3, 0x5e, 0x1d, 0xc9, 0x00, 0x59, 0x03, 0xa1, 0x0a, 0x02, 0x3e, 0xaf, + 0x29, 0x02, 0xc0, 0x72, 0x04, 0x8f, 0xf8, 0x83, 0x30, 0x7e, 0xfa, 0x46, 0xd2, 0x49, 0x58, 0xec, 0x7a, 0x01, 0x47, + 0xaf, 0x03, 0x68, 0xa3, 0x9e, 0xdb, 0x7e, 0x04, 0xa0, 0x5c, 0xac, 0xaf, 0x12, 0x6d, 0x23, 0x75, 0x08, 0xfb, 0xbe, + 0x35, 0xdb, 0xd1, 0x46, 0x9b, 0xe7, 0xd2, 0x68, 0x34, 0xb4, 0x59, 0x1d, 0xe8, 0x1e, 0xa9, 0x00, 0xd0, 0x65, 0x43, + 0xe1, 0xeb, 0xfb, 0x87, 0x28, 0xdd, 0x08, 0x76, 0xc1, 0x19, 0x7c, 0xb9, 0x74, 0xcc, 0xb7, 0x70, 0x34, 0x9f, 0x99, + 0x7a, 0x2b, 0x3f, 0x83, 0xfa, 0xba, 0xdb, 0x05, 0xe0, 0x57, 0x2e, 0x72, 0xc0, 0xf4, 0x3b, 0x9b, 0xe2, 0xa0, 0xb7, + 0x1c, 0xbd, 0xc6, 0xe9, 0xcc, 0x0c, 0x58, 0xc8, 0xb3, 0x6b, 0xe5, 0x43, 0x72, 0x03, 0x59, 0x5c, 0x40, 0x43, 0x76, + 0x0b, 0xb8, 0xf2, 0x4c, 0x97, 0x28, 0x49, 0x13, 0x84, 0x9e, 0xc0, 0x63, 0x35, 0x73, 0xb0, 0xec, 0x7d, 0x39, 0xd1, + 0xf3, 0x5c, 0x3e, 0x05, 0x8d, 0x14, 0xa8, 0x74, 0x5e, 0x52, 0x16, 0x90, 0x73, 0xa8, 0x83, 0x10, 0x33, 0x1d, 0xf4, + 0x92, 0xa9, 0xa6, 0x32, 0x87, 0x46, 0x48, 0x7e, 0x50, 0x90, 0x9c, 0xc0, 0xb9, 0xf9, 0x6a, 0x1d, 0xf5, 0xcb, 0x45, + 0x65, 0xbd, 0xa8, 0xc8, 0x04, 0xb7, 0x12, 0x1f, 0xb2, 0xfa, 0xc6, 0xc8, 0xe8, 0x68, 0x1d, 0x56, 0x9e, 0xc6, 0xf9, + 0x81, 0x07, 0x87, 0xe0, 0xc8, 0x1e, 0x62, 0x01, 0xa0, 0x89, 0xdb, 0x1c, 0xc2, 0x9f, 0xf9, 0xc8, 0x14, 0xb8, 0x35, + 0x0c, 0x09, 0x02, 0x02, 0x3e, 0xb1, 0x04, 0x8e, 0x99, 0x41, 0xc4, 0xb1, 0xd5, 0xe6, 0x0f, 0x98, 0x48, 0xab, 0xbc, + 0x31, 0x62, 0x13, 0x4e, 0x5c, 0xe3, 0x12, 0x29, 0x64, 0x6f, 0x4d, 0x76, 0xc2, 0x22, 0x0b, 0x1b, 0x72, 0xe4, 0x63, + 0xed, 0x65, 0x92, 0xf7, 0x65, 0x16, 0x2d, 0x29, 0x51, 0x77, 0x29, 0x52, 0xbc, 0x6e, 0x1f, 0xa2, 0xd5, 0x5a, 0xb5, + 0xd4, 0x71, 0xe8, 0x2e, 0x58, 0xcf, 0xfb, 0xbf, 0x7e, 0x2b, 0xa5, 0x7e, 0x72, 0x3e, 0x06, 0x55, 0xdc, 0x05, 0x85, + 0x35, 0x47, 0xc2, 0xd6, 0x4d, 0x93, 0x35, 0x79, 0x68, 0xbf, 0xec, 0x85, 0xae, 0xbb, 0x8d, 0xa8, 0x6a, 0x29, 0xf5, + 0x98, 0x17, 0x22, 0x1f, 0x86, 0x3e, 0x56, 0x8c, 0x50, 0x15, 0x1a, 0x5b, 0x3a, 0xe4, 0x71, 0x62, 0xe9, 0xf4, 0x41, + 0xe8, 0x5d, 0x0e, 0xf7, 0x21, 0x96, 0x87, 0x95, 0x24, 0xca, 0x8c, 0xa9, 0x44, 0x34, 0x8e, 0x80, 0xd1, 0xc6, 0xd8, + 0x6d, 0x04, 0x4e, 0x09, 0x36, 0x67, 0xd6, 0xbf, 0x62, 0x3c, 0xf1, 0x35, 0x74, 0x24, 0x19, 0x34, 0xe3, 0x87, 0x98, + 0xcf, 0x78, 0x23, 0x3a, 0x0c, 0x0d, 0x9a, 0xfe, 0x61, 0x9b, 0x8f, 0xbd, 0x96, 0xd0, 0x8f, 0x38, 0x84, 0x73, 0xde, + 0xf9, 0xa1, 0xfd, 0x62, 0x35, 0xe4, 0x6b, 0xd8, 0xbf, 0xf2, 0x94, 0xbf, 0xf2, 0x35, 0xdc, 0x87, 0x3c, 0xe5, 0x43, + 0xbe, 0x86, 0xfc, 0x90, 0x27, 0xc9, 0xe0, 0xf4, 0x7c, 0xa5, 0x3e, 0xf7, 0xd7, 0x42, 0x9d, 0x5c, 0x9e, 0x09, 0xad, + 0xe4, 0xa0, 0x17, 0xdf, 0x25, 0xda, 0x67, 0x02, 0x19, 0x3e, 0x2e, 0xa6, 0x44, 0x88, 0x43, 0x56, 0x96, 0x2e, 0x01, + 0x74, 0x1a, 0xe0, 0xdd, 0xeb, 0xeb, 0xbb, 0xfe, 0x15, 0xb6, 0x48, 0x1a, 0x03, 0xf1, 0xb8, 0x0f, 0xfa, 0xa9, 0x4e, + 0xdd, 0x78, 0x6e, 0x2b, 0x20, 0xe4, 0xca, 0x91, 0x80, 0x93, 0x8c, 0x76, 0x84, 0x10, 0xbd, 0x73, 0xbf, 0x67, 0x66, + 0xe6, 0xdb, 0xf7, 0xd0, 0x6b, 0xe1, 0x30, 0x87, 0x00, 0x39, 0xcb, 0x92, 0xc1, 0x5e, 0xec, 0x5f, 0xaf, 0x3e, 0x46, + 0xfa, 0xd4, 0x0c, 0x50, 0xd1, 0xa0, 0x6a, 0xb2, 0x3f, 0xe6, 0xc8, 0x48, 0x7a, 0xf9, 0x8f, 0x79, 0x97, 0x94, 0xa5, + 0xcb, 0x64, 0x08, 0xdc, 0x13, 0xb4, 0xdc, 0xcf, 0x82, 0x84, 0x4c, 0x33, 0xcb, 0x06, 0x51, 0x5b, 0x4e, 0x33, 0xe6, + 0x91, 0x1e, 0x4b, 0xb5, 0x54, 0x16, 0xee, 0x7c, 0xc7, 0xcf, 0xf8, 0x3f, 0x98, 0x84, 0xe6, 0x57, 0x83, 0xf2, 0x45, + 0xce, 0xac, 0xbb, 0x2b, 0x6c, 0x69, 0x0d, 0xa6, 0x25, 0x92, 0xa5, 0xc5, 0xb9, 0xd5, 0x98, 0x56, 0x90, 0xd6, 0x23, + 0x4f, 0x43, 0x34, 0xba, 0x49, 0x22, 0x36, 0x72, 0x6a, 0x3d, 0xe9, 0xda, 0x52, 0x93, 0xcc, 0x8a, 0xa5, 0x57, 0xb2, + 0xf7, 0xcd, 0x37, 0xd4, 0xa7, 0xe6, 0x72, 0x39, 0xc0, 0x26, 0xd3, 0x4d, 0xb1, 0x35, 0x05, 0xde, 0x25, 0x49, 0x11, + 0x1a, 0x02, 0xe5, 0xa8, 0x6d, 0x26, 0xbb, 0x4b, 0x55, 0x2d, 0xa7, 0x6a, 0x84, 0x48, 0x7d, 0x55, 0x61, 0xa9, 0x8e, + 0xe2, 0xe1, 0xc5, 0xbe, 0x88, 0xdd, 0x07, 0x71, 0x9d, 0xa5, 0x69, 0xb4, 0x59, 0xab, 0xad, 0x85, 0x3c, 0x06, 0x5f, + 0xee, 0x1a, 0x62, 0x00, 0xeb, 0x88, 0x46, 0x67, 0xf1, 0xe5, 0xd9, 0x35, 0x3c, 0x76, 0x68, 0xbf, 0xf6, 0xc1, 0x49, + 0x8b, 0xed, 0xa9, 0x14, 0x6e, 0x7d, 0x46, 0x06, 0x81, 0x44, 0xe2, 0x03, 0x00, 0x06, 0x00, 0x98, 0xea, 0x25, 0x45, + 0x35, 0x32, 0x68, 0x25, 0x0a, 0xf4, 0x48, 0xc1, 0x7d, 0x74, 0x19, 0x5a, 0x0e, 0x0e, 0x7f, 0x44, 0x4a, 0xab, 0x1d, + 0xb2, 0xc4, 0x44, 0xa6, 0x85, 0x92, 0x39, 0x4c, 0x68, 0xa5, 0xc5, 0x18, 0xb4, 0x44, 0xe1, 0x3d, 0x41, 0x3a, 0x6a, + 0x49, 0x80, 0xfa, 0xf2, 0xe8, 0x40, 0xc2, 0xe9, 0xbd, 0x79, 0xbe, 0x36, 0x7e, 0x2d, 0x6f, 0x9b, 0xe5, 0xba, 0x23, + 0x5b, 0xc1, 0x14, 0x92, 0x21, 0xd8, 0xe5, 0x6c, 0x95, 0x33, 0xfa, 0x08, 0x71, 0x12, 0xcb, 0x92, 0xd7, 0x56, 0xb9, + 0x59, 0x8c, 0x3e, 0x74, 0xcd, 0x7d, 0xd1, 0x0f, 0x75, 0xcf, 0x8f, 0x40, 0x70, 0x44, 0xb0, 0x08, 0x9e, 0xe3, 0xb4, + 0x6e, 0xf2, 0x52, 0x52, 0x13, 0xa4, 0x28, 0xf0, 0x21, 0xfd, 0xfc, 0x06, 0x43, 0x05, 0xdb, 0x6c, 0xc3, 0x21, 0x47, + 0x03, 0xcd, 0x77, 0x35, 0xfe, 0x7a, 0x75, 0x02, 0xd6, 0x92, 0xce, 0x53, 0xdb, 0xb6, 0x89, 0x3d, 0xe6, 0x8a, 0xb4, + 0xd3, 0x56, 0x08, 0xf5, 0xb9, 0xf8, 0xec, 0x67, 0xcf, 0x89, 0xaa, 0xfb, 0xf2, 0x43, 0xf0, 0xbd, 0x5d, 0x54, 0xed, + 0xb5, 0x05, 0x94, 0x1f, 0x67, 0x52, 0x6a, 0xb6, 0x0e, 0x8a, 0xd2, 0xe3, 0xd1, 0x88, 0x16, 0xb7, 0xb7, 0x94, 0xbd, + 0x1f, 0x24, 0xc1, 0x4d, 0xa6, 0x56, 0xfe, 0xdb, 0xbb, 0xdb, 0x93, 0x7c, 0x8f, 0x82, 0xcc, 0xbd, 0x16, 0xce, 0x33, + 0x73, 0x09, 0x41, 0x01, 0x22, 0x23, 0x28, 0xb3, 0x31, 0x6f, 0x03, 0xf3, 0x0e, 0xcc, 0x2f, 0xe8, 0x51, 0xa9, 0x38, + 0x90, 0x9c, 0xd5, 0xc5, 0xa8, 0x98, 0x94, 0x03, 0x2f, 0x71, 0xfd, 0x5d, 0x1a, 0x12, 0x10, 0xb8, 0x46, 0x5d, 0x06, + 0x8b, 0xc4, 0x3e, 0x51, 0x7c, 0x04, 0x67, 0xfb, 0xc6, 0x0e, 0x32, 0xbb, 0xe1, 0x7d, 0x5d, 0x5c, 0xc0, 0x1d, 0x84, + 0xcf, 0xd2, 0x53, 0x10, 0xa1, 0xa9, 0xfb, 0xdf, 0xb8, 0xa8, 0x14, 0xbe, 0xd9, 0x20, 0x63, 0xcf, 0x2f, 0xeb, 0x00, + 0xe4, 0xd2, 0x34, 0x0a, 0x83, 0x19, 0x7f, 0x72, 0xa4, 0x5f, 0x85, 0x1e, 0x52, 0x5d, 0x8b, 0xba, 0x4b, 0x72, 0x3f, + 0x74, 0xec, 0x1c, 0x8a, 0x54, 0xb1, 0xad, 0xc3, 0xf9, 0xa2, 0x91, 0xa9, 0x49, 0xff, 0xc2, 0xe3, 0x9d, 0x4d, 0xb7, + 0xdf, 0x60, 0x2e, 0x85, 0x40, 0x36, 0x32, 0xb1, 0xe9, 0xa4, 0x1d, 0x95, 0xea, 0xca, 0x9d, 0x17, 0x15, 0xea, 0xad, + 0x65, 0x2f, 0xe9, 0xe8, 0xc3, 0x8a, 0x5c, 0x4a, 0xd8, 0x12, 0x49, 0x53, 0xb8, 0x54, 0xc6, 0x58, 0x3a, 0x33, 0x77, + 0xe7, 0xbb, 0xb8, 0x92, 0xc6, 0x01, 0x3e, 0x86, 0xa1, 0x6c, 0xc4, 0xdf, 0x0f, 0x90, 0x86, 0x6a, 0x6a, 0xdd, 0x0a, + 0x64, 0x82, 0x65, 0x85, 0x12, 0x3a, 0x54, 0x50, 0x7c, 0xe0, 0xfb, 0xce, 0xe0, 0xc6, 0x49, 0xc9, 0xc6, 0xdf, 0x37, + 0xeb, 0x1e, 0x93, 0x87, 0x33, 0x93, 0xbb, 0x00, 0xaa, 0xd8, 0x6b, 0x05, 0xce, 0x0c, 0xa1, 0x70, 0x72, 0x1c, 0xd7, + 0x32, 0x27, 0xc8, 0x3a, 0x7a, 0xdb, 0x03, 0x6f, 0x91, 0x76, 0xd7, 0x45, 0x9a, 0x52, 0xed, 0x28, 0xd8, 0xc6, 0x09, + 0x38, 0xeb, 0xfb, 0x0f, 0x4a, 0xe3, 0x4a, 0xea, 0xf2, 0x79, 0x5a, 0x64, 0xdb, 0x33, 0xe2, 0x60, 0x57, 0xb5, 0x29, + 0xca, 0xa2, 0x08, 0x23, 0x0c, 0x46, 0x08, 0x5b, 0x96, 0x18, 0xc7, 0x44, 0x6c, 0x12, 0x0a, 0xa3, 0x8f, 0xca, 0x6a, + 0xe5, 0x3a, 0x96, 0x7e, 0xd5, 0x59, 0x21, 0x75, 0x44, 0x7b, 0x1f, 0xbc, 0xc4, 0x24, 0x65, 0x79, 0x4e, 0xb6, 0xf8, + 0xf4, 0x42, 0xad, 0x4f, 0xa9, 0xf6, 0xc0, 0xde, 0xdc, 0x1c, 0x24, 0x4d, 0xbe, 0x27, 0x21, 0x1e, 0x16, 0x9d, 0xd7, + 0x06, 0xe7, 0xe5, 0x69, 0xdc, 0xfd, 0x59, 0x37, 0x2d, 0x5b, 0x17, 0xe2, 0x14, 0x55, 0x47, 0xbd, 0xc9, 0xe9, 0xb5, + 0xcf, 0x3f, 0x11, 0xea, 0x84, 0x41, 0xc3, 0xcc, 0x69, 0x89, 0x89, 0x48, 0xd7, 0x65, 0x1e, 0x98, 0x08, 0xee, 0x3d, + 0x83, 0x61, 0x87, 0xe4, 0x71, 0xb2, 0x30, 0x9d, 0xb0, 0x0b, 0x51, 0xd9, 0x26, 0x67, 0xbe, 0xe7, 0xe6, 0x5f, 0x0f, + 0x64, 0x18, 0xf6, 0x69, 0x41, 0xcb, 0x79, 0xfd, 0xa6, 0x77, 0x7f, 0xb9, 0xe8, 0xa9, 0x3f, 0x06, 0xd7, 0x15, 0x9a, + 0xb0, 0x78, 0x4d, 0x87, 0xfd, 0x2f, 0xa2, 0x9f, 0xb8, 0xcf, 0xf2, 0x9e, 0x46, 0x33, 0x86, 0xc6, 0xac, 0x89, 0xfa, + 0x9d, 0x99, 0x1d, 0x85, 0x20, 0x39, 0xb1, 0x93, 0xb3, 0xfa, 0x11, 0x90, 0x88, 0x31, 0xb5, 0x9b, 0x83, 0x61, 0x76, + 0x8c, 0xb3, 0xb0, 0x68, 0xd1, 0x97, 0x87, 0x9c, 0x56, 0x00, 0x86, 0x97, 0xca, 0x2f, 0xbb, 0x76, 0x68, 0xca, 0xe3, + 0x84, 0x5a, 0x2b, 0xb8, 0x16, 0x32, 0x47, 0x55, 0x6d, 0xa2, 0xb5, 0x14, 0x81, 0x59, 0x1c, 0xeb, 0xf6, 0x53, 0x5d, + 0xff, 0x01, 0x46, 0x5f, 0xf3, 0xb0, 0x3d, 0x7f, 0x92, 0xd8, 0x52, 0xeb, 0x73, 0xbe, 0x25, 0x7a, 0x19, 0x7b, 0xaf, + 0x13, 0xb5, 0x09, 0x96, 0x6c, 0xc9, 0xca, 0x35, 0x45, 0xb8, 0x89, 0xa1, 0xea, 0x1a, 0x42, 0xb9, 0x41, 0xe2, 0x1b, + 0x32, 0x81, 0xd5, 0xf9, 0xa5, 0xce, 0xd2, 0xb3, 0x84, 0x76, 0x79, 0xa0, 0x9d, 0x9d, 0x30, 0xd2, 0x45, 0xe1, 0xff, + 0x4e, 0x26, 0x84, 0xe0, 0xca, 0x86, 0x67, 0x4b, 0xa8, 0x8b, 0xe2, 0xe2, 0xaa, 0x5d, 0x40, 0xf1, 0xeb, 0xf5, 0xbb, + 0xf5, 0xbf, 0xa5, 0xef, 0x70, 0xd9, 0x20, 0xf6, 0xd7, 0x88, 0x7a, 0x9a, 0xcc, 0xb0, 0xda, 0xe8, 0x16, 0xc3, 0xfe, + 0xd1, 0xf4, 0x8d, 0x24, 0x76, 0x0a, 0x17, 0xdf, 0x77, 0x4a, 0x1c, 0xef, 0xa6, 0x29, 0x6b, 0xa2, 0xf1, 0xbf, 0x51, + 0xd3, 0xe0, 0x14, 0xbe, 0xbe, 0xc1, 0xa9, 0xe0, 0x61, 0xd7, 0xd4, 0x50, 0xec, 0xee, 0x17, 0x2b, 0x9a, 0xd6, 0x5a, + 0x57, 0x18, 0xa0, 0x0a, 0x1f, 0x41, 0x4e, 0x45, 0xbe, 0x97, 0xfb, 0x8a, 0x2f, 0xf2, 0x47, 0xdf, 0xbc, 0x74, 0x84, + 0x35, 0x97, 0x42, 0xcd, 0xad, 0x4c, 0xf2, 0xd3, 0xf2, 0x22, 0xe9, 0x96, 0x18, 0x94, 0x73, 0xcb, 0xfc, 0x7a, 0x07, + 0x8a, 0x4a, 0xcc, 0xb6, 0x2b, 0x37, 0x08, 0xd3, 0x3a, 0x17, 0xe1, 0xbd, 0xb6, 0x12, 0x29, 0x6a, 0x8d, 0x59, 0xce, + 0xb4, 0xa4, 0x1e, 0x9b, 0xcf, 0x44, 0x1d, 0xb8, 0x01, 0x31, 0xfa, 0x9e, 0x29, 0x79, 0x0d, 0x08, 0xbb, 0xe7, 0xe1, + 0xfb, 0x64, 0x79, 0x19, 0xe6, 0x5a, 0x59, 0x52, 0x4d, 0xd6, 0x3d, 0x55, 0x48, 0x1a, 0x13, 0x7a, 0x6b, 0x97, 0x79, + 0xb9, 0x55, 0x67, 0x78, 0xb2, 0x4e, 0xef, 0x59, 0xea, 0x07, 0x78, 0x5d, 0x25, 0x0f, 0x15, 0x1e, 0x2c, 0xdc, 0xb8, + 0x00, 0x5a, 0x56, 0xde, 0xea, 0x1c, 0x47, 0xb7, 0x79, 0x4a, 0xd6, 0x66, 0x83, 0xd7, 0x44, 0x2c, 0xa0, 0x64, 0x7b, + 0xb0, 0xdd, 0xc6, 0xca, 0x21, 0x1a, 0x6f, 0x1f, 0x59, 0x48, 0xd1, 0x75, 0x83, 0x36, 0x2f, 0x0f, 0x98, 0xc3, 0x51, + 0x75, 0x75, 0xa3, 0x9c, 0xbd, 0xc4, 0xfc, 0x60, 0xa4, 0x40, 0x41, 0x23, 0x7b, 0xc1, 0xa2, 0x4a, 0xbd, 0x8f, 0xad, + 0x57, 0x7d, 0xbb, 0x16, 0x7e, 0x24, 0x82, 0x91, 0xda, 0x28, 0xe1, 0x79, 0x8a, 0xe4, 0xd9, 0xb1, 0x9b, 0x27, 0x27, + 0x64, 0x64, 0x5e, 0xba, 0x02, 0x92, 0xb0, 0xe0, 0xa1, 0x09, 0xc2, 0xe2, 0x54, 0x32, 0x82, 0x88, 0x7d, 0xce, 0xdc, + 0x40, 0xa8, 0x1a, 0xae, 0x22, 0xc0, 0xcd, 0x93, 0x5e, 0xd2, 0x3c, 0x96, 0xdb, 0x62, 0xcc, 0xea, 0x34, 0x13, 0x6a, + 0x79, 0x26, 0xa2, 0x44, 0x7e, 0x5e, 0x0f, 0xf9, 0x08, 0xe8, 0xd0, 0x6d, 0xc2, 0xb9, 0x58, 0x63, 0x27, 0x56, 0xa9, + 0xb5, 0xa0, 0xf0, 0xdb, 0xb1, 0xc9, 0xda, 0x6f, 0x32, 0xa3, 0x67, 0x30, 0xff, 0x2c, 0x46, 0xb2, 0x9b, 0x3e, 0x8a, + 0xe3, 0x3e, 0x40, 0x01, 0x99, 0x6f, 0xe8, 0x20, 0xf9, 0x6d, 0xa9, 0x1e, 0xd7, 0xbb, 0x51, 0x2e, 0xc4, 0x93, 0x2c, + 0xf2, 0x40, 0xaa, 0x9d, 0xaf, 0x72, 0x5c, 0x7a, 0xe4, 0xd6, 0x0f, 0x54, 0x03, 0x42, 0x20, 0xcb, 0x0d, 0xa4, 0xf0, + 0x06, 0x07, 0xce, 0x9b, 0x38, 0x22, 0xa1, 0xac, 0x67, 0x22, 0x98, 0x2c, 0x4a, 0xf1, 0x5e, 0xfc, 0xe2, 0xd7, 0xee, + 0x2f, 0x16, 0x67, 0x7d, 0xb1, 0x87, 0xcd, 0xf2, 0xc5, 0x7b, 0x0d, 0xc4, 0x56, 0x15, 0x1e, 0x2c, 0x59, 0x4c, 0x0f, + 0x5e, 0xef, 0x11, 0x36, 0xf6, 0x0c, 0xef, 0xc1, 0x27, 0xfd, 0x5a, 0x42, 0xa5, 0xcd, 0xa5, 0xe8, 0x80, 0xfd, 0x30, + 0xdc, 0x64, 0xdf, 0x08, 0x13, 0xd2, 0xc5, 0xfa, 0x44, 0xff, 0x19, 0x24, 0x79, 0xb7, 0xeb, 0xef, 0xeb, 0x45, 0xe4, + 0x06, 0x2b, 0x05, 0xd9, 0xd8, 0x6d, 0x76, 0x90, 0x35, 0x64, 0x25, 0x53, 0x63, 0x82, 0x50, 0x06, 0xe9, 0x0b, 0x51, + 0x97, 0xf7, 0x57, 0x6d, 0x78, 0x98, 0xae, 0xb6, 0x96, 0x15, 0xc5, 0xb7, 0xf2, 0x5f, 0x85, 0xee, 0x78, 0x8e, 0x8e, + 0xa4, 0xbe, 0x73, 0x88, 0x3f, 0x7b, 0x1d, 0x34, 0x11, 0xaa, 0x02, 0xf2, 0xd7, 0xda, 0x0b, 0xe7, 0xd6, 0x53, 0x4e, + 0xee, 0xce, 0xa7, 0x5b, 0xb9, 0x08, 0xe9, 0x07, 0x86, 0x5e, 0xb6, 0xd8, 0xe8, 0xc5, 0x63, 0x3a, 0xd6, 0xa1, 0x25, + 0x12, 0xe3, 0x73, 0x60, 0xa6, 0x4e, 0x5d, 0x63, 0x62, 0x3a, 0xeb, 0x8f, 0x91, 0x15, 0x58, 0x80, 0x31, 0xd6, 0xc2, + 0x4f, 0x57, 0xe1, 0xdb, 0xe9, 0x37, 0x84, 0x20, 0x70, 0x9b, 0x34, 0xf1, 0xd3, 0xd5, 0x53, 0x6c, 0x7e, 0x53, 0x31, + 0x57, 0xc4, 0xb6, 0x1c, 0x68, 0xd1, 0xaa, 0x86, 0x3a, 0xb3, 0x13, 0x14, 0x84, 0x29, 0x12, 0x85, 0x31, 0x57, 0x47, + 0x89, 0x41, 0xd4, 0x72, 0xea, 0x2e, 0x64, 0x9b, 0x0a, 0xb5, 0x25, 0xb9, 0x28, 0x28, 0xe1, 0x88, 0x4d, 0xe2, 0x4c, + 0x35, 0x07, 0xa8, 0x5f, 0xdb, 0xb4, 0x09, 0x67, 0xbd, 0xe0, 0xde, 0xa9, 0xa0, 0x50, 0x53, 0xc3, 0xe0, 0x15, 0x1b, + 0x83, 0x57, 0xe5, 0x0c, 0xed, 0xf0, 0x22, 0xfd, 0xbe, 0xf9, 0x44, 0x5b, 0x4b, 0x73, 0xb3, 0xec, 0xdf, 0xcb, 0xc3, + 0x1f, 0x0d, 0x6f, 0xbf, 0x73, 0x26, 0xc4, 0x45, 0xf3, 0xa1, 0xa7, 0x5e, 0xe2, 0x71, 0x83, 0x62, 0x0f, 0xcd, 0x8c, + 0x19, 0x76, 0x9f, 0x69, 0xe9, 0x30, 0xc6, 0xed, 0xc4, 0x2d, 0xed, 0x41, 0x37, 0x2a, 0x8c, 0x3d, 0x3d, 0xdf, 0x40, + 0xeb, 0xad, 0xf0, 0xb6, 0xb5, 0x3b, 0x6d, 0x7c, 0x3e, 0x1d, 0x03, 0xe8, 0x1b, 0x6d, 0xba, 0x6c, 0x1e, 0xba, 0x4c, + 0xc6, 0x22, 0xd1, 0x76, 0xc8, 0x17, 0xcb, 0xc3, 0xef, 0xbd, 0xad, 0x4d, 0x7b, 0x0b, 0xd7, 0x91, 0x21, 0x83, 0xb4, + 0x54, 0x89, 0x54, 0xd1, 0xa3, 0x0b, 0xe4, 0xd5, 0x4c, 0xb4, 0x72, 0x8d, 0x3a, 0xe3, 0xf5, 0xed, 0x52, 0x65, 0xf9, + 0x63, 0x0b, 0x51, 0xa5, 0x97, 0xff, 0x02, 0x31, 0xcf, 0x0e, 0x93, 0x81, 0xe1, 0x14, 0x42, 0x63, 0xf7, 0x7f, 0x80, + 0xd3, 0x2e, 0x03, 0x6a, 0x42, 0xcd, 0xcb, 0x45, 0x17, 0x49, 0x71, 0xf9, 0xe9, 0x7e, 0x37, 0x04, 0xf1, 0x7c, 0x75, + 0x16, 0x5c, 0x7b, 0x49, 0x92, 0x4a, 0xfc, 0xa5, 0x34, 0x4d, 0x38, 0xc9, 0xb6, 0x22, 0x7e, 0x55, 0x9f, 0x00, 0x48, + 0x21, 0x5e, 0x69, 0x16, 0x69, 0xe2, 0x2d, 0xe9, 0xaa, 0x90, 0x51, 0xf1, 0x21, 0x85, 0x6f, 0x65, 0xb4, 0x3d, 0x9a, + 0x61, 0x74, 0x8d, 0x25, 0x76, 0x10, 0xba, 0x61, 0x9a, 0x30, 0x02, 0x1d, 0xd8, 0xc9, 0x00, 0x89, 0xbc, 0x53, 0x0e, + 0x31, 0x57, 0x4d, 0x4c, 0xc1, 0x0f, 0x49, 0xbd, 0x97, 0x20, 0xb7, 0xa0, 0x79, 0x56, 0xd6, 0x84, 0xd8, 0xe4, 0xc8, + 0xfd, 0x3e, 0x39, 0xe0, 0x7a, 0x61, 0x73, 0xb0, 0x51, 0xe9, 0x38, 0xb9, 0xcf, 0xf0, 0x6f, 0x3b, 0x49, 0x01, 0xb5, + 0x5b, 0xc5, 0x5c, 0x8e, 0xd3, 0x5c, 0xd0, 0x62, 0xfa, 0x6f, 0x06, 0x92, 0x83, 0xfe, 0x91, 0xa0, 0x81, 0xa5, 0xc3, + 0x4f, 0x74, 0x6b, 0xf0, 0x2f, 0x6c, 0x35, 0xcd, 0x4a, 0x64, 0xb5, 0xa7, 0x58, 0x7b, 0xe6, 0x65, 0xf2, 0xed, 0xa4, + 0xfe, 0x35, 0xaf, 0x49, 0xac, 0x7e, 0xe2, 0xa6, 0x16, 0x8f, 0x5c, 0x9f, 0x72, 0x70, 0x7a, 0xaa, 0xc7, 0x5e, 0xd8, + 0x75, 0x9a, 0x95, 0x0c, 0x51, 0x9c, 0x4b, 0xb6, 0xeb, 0xe2, 0x6f, 0x2f, 0x12, 0x41, 0x79, 0x9b, 0x80, 0x11, 0x12, + 0x10, 0xb9, 0x60, 0xf6, 0x34, 0x64, 0x72, 0xd4, 0x57, 0x9b, 0x87, 0xc3, 0x0a, 0x81, 0xe6, 0xa1, 0x70, 0x3f, 0xcc, + 0x54, 0xca, 0x2e, 0x0e, 0x01, 0x55, 0xba, 0x7f, 0x8d, 0x69, 0x35, 0xff, 0x9b, 0x24, 0xf1, 0x27, 0xab, 0x3f, 0x6c, + 0x55, 0x0d, 0xd1, 0x10, 0x17, 0x46, 0x29, 0x1a, 0x4f, 0x19, 0x0b, 0x3d, 0xa3, 0x67, 0x4e, 0x22, 0x4b, 0x41, 0xff, + 0xec, 0x3c, 0x9c, 0xd7, 0xfa, 0xb4, 0x45, 0x35, 0x70, 0x94, 0x44, 0xb1, 0x65, 0x06, 0x46, 0xbc, 0x00, 0x24, 0x66, + 0x7a, 0x90, 0x15, 0x2d, 0xf8, 0xda, 0x76, 0x65, 0xc5, 0x9c, 0x65, 0x60, 0xf5, 0x43, 0xd4, 0x1f, 0x6e, 0xda, 0x1b, + 0x7a, 0x4b, 0x2b, 0xe3, 0x2d, 0x3d, 0xde, 0xd3, 0x66, 0xd6, 0x2f, 0x6d, 0xa0, 0xe9, 0x52, 0x95, 0x3c, 0x7d, 0x7f, + 0xdf, 0xf7, 0xc5, 0xfd, 0x79, 0x3f, 0x15, 0x57, 0x6c, 0xef, 0xe7, 0x81, 0x4a, 0x4e, 0xfc, 0x73, 0xd4, 0xaf, 0x27, + 0x33, 0xaa, 0x09, 0xd7, 0x6d, 0xdd, 0xb7, 0xc2, 0x23, 0x5f, 0x4f, 0x2c, 0x1c, 0x49, 0x5d, 0xa1, 0xe4, 0x3d, 0x69, + 0xd9, 0xa0, 0x7b, 0x8a, 0x20, 0xdf, 0x57, 0x40, 0x29, 0x05, 0x34, 0x1f, 0x5c, 0x22, 0x44, 0x69, 0x6a, 0x5d, 0xba, + 0xf1, 0x86, 0xca, 0xcd, 0x07, 0x66, 0x39, 0x1b, 0x82, 0x8f, 0x13, 0xf0, 0x8b, 0x79, 0x50, 0x3f, 0xae, 0xc2, 0x34, + 0x33, 0x54, 0xf6, 0x80, 0x6c, 0x82, 0x92, 0x13, 0xa9, 0x47, 0x5f, 0xd4, 0x91, 0x40, 0xa3, 0xa8, 0x57, 0x9e, 0x75, + 0xbf, 0xd0, 0x45, 0xae, 0x34, 0xff, 0xbf, 0x84, 0x92, 0x0d, 0xf5, 0xe7, 0xe3, 0x4b, 0x69, 0xb0, 0x40, 0xdf, 0x2f, + 0xfc, 0xf6, 0xf2, 0xa2, 0xd1, 0xe3, 0xd2, 0x77, 0x37, 0x64, 0xb9, 0xc1, 0x71, 0x6f, 0x9e, 0xcd, 0x4b, 0x29, 0x05, + 0xe1, 0xb9, 0xe9, 0xaf, 0xcc, 0xd6, 0x89, 0x82, 0xb0, 0xd9, 0x5c, 0x70, 0x10, 0xa0, 0x6a, 0xd9, 0x03, 0x4c, 0xb5, + 0x42, 0x76, 0xea, 0x18, 0x84, 0xf2, 0xdb, 0xc4, 0x7b, 0xf9, 0x7e, 0x7e, 0xbd, 0xe3, 0x91, 0xb9, 0x72, 0xc8, 0x13, + 0x55, 0x76, 0x51, 0x74, 0xb7, 0x08, 0x8f, 0x05, 0xc2, 0x9b, 0x3f, 0x4c, 0x63, 0xbe, 0xae, 0x7b, 0x0a, 0x80, 0x19, + 0x00, 0x9f, 0x10, 0x22, 0x28, 0xd8, 0xcc, 0x74, 0x73, 0x3f, 0xdc, 0xab, 0xa4, 0x6a, 0x78, 0x0a, 0x6c, 0x22, 0x28, + 0xb8, 0xce, 0xd4, 0x63, 0x71, 0x06, 0x9b, 0x7e, 0x44, 0x84, 0x50, 0x9a, 0xe5, 0xb8, 0x19, 0x37, 0xc0, 0x3c, 0x17, + 0x6d, 0xcc, 0xf0, 0x34, 0xd6, 0x84, 0x78, 0x9f, 0xd8, 0x64, 0x4a, 0xc7, 0x05, 0xf9, 0xb2, 0x8b, 0x57, 0xee, 0xfc, + 0x18, 0x65, 0xee, 0x89, 0xc1, 0xb7, 0xc8, 0x1d, 0x73, 0x3f, 0xe2, 0x13, 0x56, 0xd9, 0xb4, 0xbe, 0x04, 0x36, 0x6e, + 0x69, 0x5d, 0x98, 0x68, 0xfe, 0x5b, 0x68, 0x49, 0xe4, 0x0b, 0x76, 0x6d, 0x33, 0x1e, 0xa1, 0xbe, 0xf2, 0xc9, 0xe0, + 0x81, 0x37, 0xff, 0xda, 0xa3, 0xfb, 0x8b, 0x09, 0x84, 0x62, 0x78, 0x2f, 0xdb, 0xc9, 0x5a, 0xde, 0xcb, 0x52, 0x81, + 0xeb, 0x55, 0xbc, 0x26, 0x8f, 0xe9, 0x38, 0x8c, 0xc4, 0xe8, 0x68, 0x50, 0x00, 0xf7, 0x4d, 0xd1, 0xdb, 0x88, 0x71, + 0xa2, 0xa0, 0x0a, 0x55, 0xce, 0xf4, 0x32, 0x8e, 0xb2, 0xbc, 0x4a, 0x1a, 0xfc, 0x6d, 0x3f, 0x6f, 0x52, 0x04, 0x04, + 0x1f, 0xe8, 0x80, 0x9b, 0xfd, 0xd9, 0x98, 0xd3, 0x9a, 0xb6, 0xa4, 0x62, 0x8d, 0x07, 0x44, 0x8e, 0xe8, 0xff, 0x38, + 0x64, 0xb9, 0x66, 0xe8, 0x3e, 0x1a, 0x74, 0x43, 0xc8, 0x1b, 0x11, 0x19, 0x19, 0x0c, 0x90, 0xcd, 0x57, 0x9b, 0xb9, + 0x86, 0x81, 0x30, 0x09, 0xeb, 0x16, 0x0f, 0xfd, 0x12, 0x70, 0x94, 0x8f, 0xb9, 0xdb, 0xbe, 0x60, 0x98, 0xc8, 0x2b, + 0xca, 0x2f, 0x29, 0x38, 0x17, 0x9a, 0x99, 0xb7, 0x1c, 0x80, 0x39, 0xcd, 0x14, 0x14, 0xa6, 0x38, 0x18, 0x95, 0x6d, + 0xad, 0x1f, 0xd2, 0xbc, 0x16, 0xa8, 0x52, 0x30, 0x5c, 0x91, 0xb9, 0xa8, 0x92, 0xbb, 0x9a, 0x77, 0x13, 0x11, 0xa1, + 0xe3, 0xd8, 0x31, 0x67, 0x58, 0x67, 0x0a, 0x32, 0x32, 0x4d, 0x91, 0x6f, 0x1f, 0x21, 0x09, 0x97, 0x88, 0x5a, 0x44, + 0xf7, 0xcb, 0xb9, 0x36, 0xbb, 0x35, 0xa6, 0xa9, 0xae, 0x1d, 0xd2, 0x84, 0x4d, 0x0c, 0x6a, 0xfa, 0x12, 0xc5, 0x87, + 0xd2, 0xf8, 0xed, 0x4e, 0xfb, 0x18, 0x46, 0xb2, 0xb1, 0xf4, 0xdc, 0x38, 0x5c, 0x8d, 0x23, 0xea, 0x58, 0x3d, 0x95, + 0xa2, 0xc6, 0x56, 0x65, 0x0a, 0x6d, 0x91, 0x45, 0x08, 0x80, 0xf3, 0x95, 0xb9, 0x9a, 0xdf, 0x0a, 0x1f, 0x34, 0x67, + 0x9a, 0x55, 0x2a, 0x15, 0x9f, 0x68, 0xd1, 0x54, 0x46, 0x62, 0x71, 0x9b, 0xcb, 0x7d, 0x62, 0xfc, 0xae, 0x95, 0x1b, + 0xc0, 0x6f, 0xd1, 0x2d, 0x77, 0xd5, 0x0c, 0xdc, 0x64, 0x6f, 0xf4, 0x9c, 0x55, 0x06, 0x72, 0x17, 0x32, 0x6f, 0xd0, + 0x70, 0x2d, 0xd9, 0x6e, 0xcd, 0xfb, 0xba, 0x2c, 0xf4, 0x65, 0xec, 0xf2, 0xdb, 0x5c, 0x83, 0x56, 0x7f, 0x1a, 0x76, + 0x57, 0x1a, 0x8e, 0xac, 0x04, 0x3d, 0x0d, 0xe6, 0x80, 0x94, 0xd7, 0xba, 0x7f, 0xbb, 0xaa, 0x00, 0xf8, 0x9b, 0xe9, + 0x22, 0xd1, 0x7c, 0x09, 0xdf, 0x40, 0x63, 0xa0, 0x74, 0x1e, 0xd8, 0xca, 0xd7, 0xb3, 0x76, 0x18, 0xf4, 0xbe, 0x9a, + 0x49, 0x0b, 0xaf, 0xcb, 0x9b, 0x10, 0xf6, 0x0a, 0x97, 0x24, 0xd6, 0x78, 0x58, 0xcd, 0x60, 0x61, 0x1e, 0xee, 0xb0, + 0x52, 0x9b, 0xca, 0x9f, 0x10, 0xd5, 0x25, 0xda, 0xf3, 0xba, 0x8b, 0x25, 0x36, 0x2e, 0xec, 0xfb, 0x25, 0xb9, 0xa0, + 0x3a, 0x50, 0xf4, 0x41, 0x32, 0x31, 0xc7, 0x96, 0x1d, 0x08, 0x5e, 0x1e, 0x56, 0x62, 0x40, 0xc1, 0xbe, 0xe5, 0xa8, + 0x4f, 0x54, 0x1c, 0x40, 0x52, 0x8a, 0x91, 0xf4, 0x8a, 0x57, 0xc4, 0xde, 0xb4, 0x0a, 0x28, 0xfb, 0xdd, 0xba, 0xef, + 0xd9, 0x2a, 0x7f, 0x32, 0xd7, 0xfa, 0xa4, 0xdf, 0x23, 0xe9, 0xbd, 0xa2, 0x7e, 0x1c, 0x80, 0x33, 0xdb, 0xac, 0x7d, + 0x02, 0x67, 0x1e, 0x4b, 0xf7, 0xda, 0x70, 0xd1, 0xee, 0xab, 0x02, 0x98, 0x10, 0x4c, 0x87, 0xaa, 0x35, 0xe3, 0x73, + 0xf9, 0xc4, 0x96, 0xed, 0x9e, 0xf4, 0x9d, 0x14, 0x43, 0x6c, 0x90, 0x31, 0x3c, 0x4b, 0xe4, 0x9c, 0x9a, 0xc7, 0xd3, + 0xa7, 0xa7, 0x7a, 0x26, 0xa5, 0xe7, 0xd9, 0x47, 0x47, 0x1c, 0x28, 0x51, 0x23, 0x4b, 0x86, 0xb6, 0x6f, 0xf5, 0xd1, + 0x0b, 0x5e, 0x0b, 0x80, 0x14, 0x4b, 0x20, 0x4d, 0x33, 0x2a, 0xce, 0xf1, 0xc9, 0x07, 0x09, 0x92, 0xc1, 0x5d, 0x49, + 0xe8, 0x93, 0x16, 0x6a, 0x0d, 0x7e, 0x20, 0x2f, 0xca, 0x8d, 0x03, 0x40, 0xed, 0x1e, 0x32, 0x45, 0xb1, 0x9c, 0x37, + 0xb2, 0x13, 0xee, 0x21, 0x1a, 0x87, 0x7a, 0x54, 0x9a, 0xa7, 0x9c, 0x5e, 0x40, 0xb4, 0x5c, 0xe6, 0xc9, 0x8c, 0x3d, + 0x7b, 0xbe, 0x41, 0xc3, 0x29, 0xb4, 0xf1, 0x25, 0x4e, 0x5b, 0xa7, 0xfe, 0x54, 0x43, 0x71, 0x79, 0x36, 0x5f, 0x26, + 0xea, 0x88, 0x3d, 0xa2, 0x0b, 0xcd, 0xe8, 0x82, 0xde, 0x98, 0xcb, 0x9d, 0xfb, 0x59, 0x01, 0x02, 0x1d, 0x95, 0x17, + 0x43, 0x27, 0x31, 0xc6, 0xab, 0xf4, 0x84, 0x3b, 0x5e, 0x28, 0xa5, 0xfa, 0x00, 0x3e, 0x7f, 0x08, 0xc2, 0x5f, 0x89, + 0xf7, 0x8e, 0x5a, 0x7d, 0xe3, 0x16, 0x27, 0x26, 0x3c, 0x28, 0xc0, 0x4c, 0x87, 0x48, 0x8d, 0x24, 0x74, 0x04, 0xda, + 0x47, 0x81, 0x90, 0xac, 0xa4, 0x5b, 0x53, 0x5e, 0x87, 0x75, 0xea, 0x30, 0x07, 0x3f, 0x2e, 0x18, 0xaf, 0xe5, 0x4d, + 0x37, 0xa2, 0xb7, 0xbe, 0x6e, 0x05, 0xd9, 0x79, 0xdc, 0x83, 0xc8, 0xf8, 0x62, 0x67, 0x8c, 0x29, 0xda, 0x29, 0xa6, + 0x25, 0x15, 0xb3, 0x8f, 0x14, 0xa1, 0xbf, 0x5c, 0x17, 0x67, 0xb6, 0xa6, 0x84, 0xda, 0xc1, 0x04, 0x09, 0xa1, 0xa7, + 0x0a, 0x25, 0x58, 0xb2, 0xfa, 0xe0, 0x25, 0x2e, 0xd2, 0xc1, 0xb6, 0x2a, 0x82, 0x27, 0xf5, 0x7c, 0xf8, 0x6b, 0x47, + 0x84, 0x70, 0x9a, 0xa5, 0x48, 0x88, 0xc5, 0xf6, 0xb1, 0x9a, 0x48, 0x2a, 0x18, 0xd3, 0x3c, 0xe5, 0x03, 0xf6, 0xa0, + 0xf6, 0xe1, 0x26, 0xf5, 0x55, 0xdc, 0x8f, 0xae, 0x97, 0xf8, 0x73, 0x5d, 0x38, 0x0f, 0x86, 0x1a, 0x6f, 0xa9, 0x9c, + 0xb9, 0x1e, 0x35, 0x41, 0x63, 0xe0, 0xd2, 0xa8, 0x3f, 0x43, 0xea, 0xa0, 0xca, 0xc2, 0x78, 0x16, 0xbf, 0x04, 0x71, + 0x6e, 0x8d, 0x29, 0xf7, 0x67, 0x48, 0xe2, 0x71, 0x6f, 0xd4, 0x9f, 0x3d, 0xba, 0xcb, 0x74, 0x85, 0x00, 0xbb, 0x56, + 0xcb, 0x76, 0xd5, 0x5e, 0x42, 0x2e, 0x76, 0xe2, 0x76, 0xa6, 0x55, 0x49, 0xc0, 0x68, 0x4e, 0x53, 0xfd, 0x3d, 0x3e, + 0x0d, 0xf1, 0x2b, 0xd8, 0x70, 0x9f, 0x12, 0x54, 0x4b, 0x32, 0x9f, 0xbe, 0x44, 0x39, 0x7d, 0xa8, 0xb5, 0x6b, 0x83, + 0xc8, 0xa5, 0xeb, 0x08, 0x4f, 0x96, 0x0b, 0x39, 0x3b, 0x4e, 0xe8, 0xde, 0xfc, 0x05, 0x71, 0xa6, 0xa8, 0x45, 0x4d, + 0x81, 0x64, 0xa3, 0xc5, 0x77, 0x3a, 0xb7, 0xd0, 0x72, 0xb9, 0x1c, 0x85, 0x67, 0xdd, 0xfb, 0xb4, 0x5f, 0x91, 0x74, + 0xb5, 0x5e, 0x1b, 0xdd, 0x46, 0x77, 0x2d, 0x55, 0x64, 0x41, 0x1d, 0x1f, 0x29, 0xe3, 0xe5, 0xd0, 0x4a, 0x71, 0xf3, + 0xaa, 0x2c, 0x98, 0xe7, 0x94, 0x7a, 0x75, 0xd9, 0xf7, 0xe7, 0xb7, 0x3e, 0x41, 0x98, 0xb0, 0x47, 0xb5, 0x82, 0x5e, + 0x61, 0xbb, 0x95, 0xb7, 0x15, 0xac, 0x36, 0x69, 0x91, 0xb2, 0x33, 0xa0, 0x2d, 0x8e, 0x4f, 0x31, 0xed, 0x14, 0x05, + 0x8f, 0x3a, 0x6d, 0x74, 0x55, 0x08, 0x13, 0x9e, 0x54, 0xfc, 0xb7, 0x03, 0x33, 0x71, 0x84, 0x73, 0x43, 0x6e, 0x6f, + 0x2b, 0xb9, 0x3e, 0x1e, 0x8c, 0x9e, 0x4e, 0x84, 0x84, 0x06, 0x6d, 0x0c, 0x5e, 0xe5, 0xe0, 0xaf, 0xbf, 0x0b, 0xb1, + 0xc2, 0x87, 0x04, 0x2e, 0x87, 0x6e, 0x94, 0xeb, 0x81, 0x71, 0xcd, 0x17, 0xe8, 0x84, 0x5c, 0x3c, 0x70, 0x90, 0xd9, + 0x91, 0x4f, 0xc8, 0xc8, 0x6f, 0xcc, 0x20, 0x70, 0x4e, 0x4e, 0x56, 0x8c, 0x22, 0x84, 0x0e, 0x76, 0x1e, 0x05, 0x3a, + 0x86, 0x24, 0xe1, 0x57, 0xc7, 0x89, 0xa4, 0xb5, 0xce, 0x7b, 0x5a, 0x7f, 0x78, 0x51, 0x40, 0xf2, 0x0e, 0x62, 0xea, + 0xbe, 0x26, 0x61, 0xf2, 0x1a, 0x13, 0xb7, 0x15, 0xa3, 0xff, 0xcc, 0x4d, 0x60, 0xb6, 0xca, 0xc0, 0x06, 0x2b, 0x73, + 0x3c, 0x9d, 0x89, 0xc2, 0xb3, 0x54, 0x81, 0x79, 0x76, 0xe4, 0xac, 0x94, 0x28, 0x10, 0x28, 0x4a, 0x2d, 0x6d, 0x56, + 0xeb, 0x70, 0x45, 0x39, 0x76, 0x9f, 0x65, 0x0b, 0x95, 0x80, 0x54, 0x47, 0x93, 0x69, 0x6d, 0xf0, 0x81, 0xbb, 0xb3, + 0x5b, 0xc9, 0x28, 0x58, 0x2e, 0xfc, 0x5b, 0xa1, 0x77, 0xa8, 0xa6, 0x22, 0xa6, 0x48, 0xeb, 0xd6, 0x2a, 0x25, 0x45, + 0xd2, 0x00, 0xad, 0xb3, 0x2c, 0x28, 0x82, 0x90, 0x1e, 0xf1, 0x55, 0xb3, 0x80, 0x07, 0xb3, 0xda, 0x22, 0x9b, 0x15, + 0xdc, 0x13, 0xc1, 0xd9, 0x9a, 0x42, 0x89, 0x59, 0xcb, 0x6c, 0xdf, 0x9e, 0x6e, 0xd2, 0xd6, 0x6d, 0x45, 0xcb, 0xa0, + 0x09, 0x7d, 0x4a, 0xd3, 0xe4, 0xdf, 0xb5, 0xd9, 0xc2, 0xe1, 0x03, 0x63, 0x0e, 0x2f, 0x5d, 0x33, 0x0f, 0x00, 0x95, + 0x5a, 0xf4, 0xeb, 0x44, 0x9f, 0x7e, 0xa5, 0x91, 0x1b, 0x52, 0x80, 0x1e, 0x94, 0x82, 0x6c, 0xe4, 0x6b, 0xea, 0xc0, + 0x9d, 0x12, 0x6d, 0x02, 0xcb, 0xad, 0x88, 0x65, 0xc1, 0xea, 0xae, 0xf8, 0xfb, 0x0b, 0xd0, 0xa0, 0x2f, 0x6f, 0x18, + 0xd0, 0x4f, 0xd4, 0xde, 0x1f, 0xea, 0x50, 0x29, 0xc9, 0xed, 0xe9, 0xd2, 0xed, 0x88, 0x02, 0x6a, 0xad, 0x5e, 0x15, + 0x15, 0x9c, 0x67, 0xca, 0x00, 0xd2, 0x0e, 0x69, 0xb0, 0x61, 0x30, 0xea, 0x23, 0xf0, 0xc1, 0x7a, 0x1d, 0xc7, 0x6d, + 0x7b, 0x29, 0xba, 0x97, 0xb3, 0x3b, 0x36, 0x6a, 0x90, 0x09, 0x56, 0x4e, 0x8c, 0x61, 0x74, 0x9f, 0x77, 0xbd, 0xa7, + 0x8e, 0x89, 0x97, 0x4d, 0xaa, 0xa7, 0x98, 0x00, 0x2c, 0x98, 0x29, 0xd8, 0xa6, 0x92, 0x5a, 0x99, 0x10, 0xb4, 0x2d, + 0xe7, 0xca, 0x9a, 0x33, 0x45, 0x39, 0x7b, 0x73, 0xc8, 0xcb, 0x73, 0x73, 0x69, 0x1d, 0x45, 0x14, 0x35, 0x42, 0xda, + 0x2e, 0x8a, 0x97, 0x62, 0xc5, 0xc5, 0x47, 0x02, 0xf7, 0x46, 0xa8, 0x4c, 0x39, 0xee, 0xb8, 0x2a, 0x53, 0xfa, 0xe0, + 0x16, 0xbf, 0x67, 0x4c, 0x22, 0x9e, 0xc0, 0xe4, 0x33, 0x66, 0xc1, 0xf9, 0x42, 0x3f, 0xe2, 0x5d, 0x22, 0xbf, 0xf0, + 0xba, 0x68, 0x2b, 0xfb, 0x4c, 0x8b, 0xa0, 0xd5, 0x7b, 0x38, 0xdd, 0x9a, 0xac, 0xb9, 0x3a, 0x23, 0x47, 0x80, 0xef, + 0x58, 0xb2, 0x47, 0x32, 0x76, 0xe0, 0xb3, 0x58, 0xf4, 0xe0, 0x18, 0x12, 0x9e, 0x31, 0x82, 0xdb, 0x63, 0x9e, 0xcd, + 0xb8, 0x1c, 0x9f, 0xb5, 0x2e, 0x9e, 0xf3, 0xda, 0xeb, 0x5a, 0x91, 0x9e, 0x92, 0xd9, 0x3c, 0xe2, 0x4d, 0x43, 0xd2, + 0x79, 0xff, 0xb9, 0x47, 0x38, 0xe7, 0x1a, 0x58, 0xc5, 0x9d, 0x70, 0x5d, 0xaa, 0xd0, 0xe7, 0xe7, 0x7b, 0xe8, 0xb3, + 0x51, 0xd2, 0x5d, 0x5c, 0xa7, 0x3c, 0x9a, 0x7e, 0xb6, 0x24, 0x1e, 0xf6, 0x38, 0x1e, 0x5f, 0xd2, 0xdf, 0xd6, 0x36, + 0x40, 0xd9, 0x6a, 0x1b, 0x23, 0xd4, 0xa6, 0x39, 0x05, 0x7e, 0xbf, 0xcf, 0x71, 0x74, 0x34, 0x9e, 0xda, 0x35, 0xf0, + 0xe9, 0x7d, 0x01, 0xba, 0xaa, 0xb4, 0x7a, 0xe7, 0xe9, 0x1d, 0x2e, 0xcc, 0x06, 0xb9, 0xd7, 0x88, 0x2c, 0x83, 0xb9, + 0x5c, 0x70, 0xb2, 0xab, 0x7e, 0x48, 0xa5, 0xb4, 0x9f, 0xf9, 0xef, 0x07, 0x5d, 0x4e, 0xf7, 0xc9, 0x61, 0x1b, 0xc8, + 0x95, 0x38, 0x33, 0x2a, 0xac, 0xbe, 0x69, 0x69, 0x49, 0x3f, 0xe3, 0x32, 0x0c, 0x04, 0x44, 0xf9, 0xbf, 0x78, 0x38, + 0x48, 0xc8, 0x5b, 0x27, 0x24, 0x45, 0xd5, 0x9a, 0xd5, 0x24, 0x2f, 0xf6, 0x23, 0xa4, 0xe0, 0x50, 0x24, 0x4b, 0x5f, + 0xb4, 0x3f, 0x97, 0x88, 0x42, 0x06, 0x81, 0x51, 0x06, 0x49, 0x10, 0xad, 0xa3, 0x5b, 0x3d, 0xed, 0x24, 0xbd, 0x3c, + 0x40, 0x5f, 0xe9, 0xf9, 0xfb, 0x11, 0x0e, 0x41, 0x59, 0x73, 0xfd, 0xdc, 0x8a, 0x6c, 0xe7, 0xcf, 0x5d, 0x55, 0x58, + 0x07, 0x44, 0x2c, 0x66, 0x39, 0x5a, 0xcc, 0x8b, 0xa2, 0x64, 0xef, 0xba, 0x03, 0xf8, 0x15, 0xde, 0x99, 0x73, 0x55, + 0x5c, 0xc8, 0x31, 0x7d, 0x25, 0xae, 0xe8, 0x1c, 0x1e, 0xd1, 0x4a, 0xda, 0x96, 0xc8, 0xfe, 0x72, 0x68, 0x97, 0x9c, + 0x50, 0xa1, 0x15, 0x6e, 0x69, 0x36, 0xa7, 0xe7, 0x00, 0xc2, 0x8a, 0x2f, 0x08, 0xa5, 0xdc, 0xf3, 0x4a, 0xa7, 0x0e, + 0x86, 0xce, 0xdc, 0xa4, 0x08, 0x7d, 0x37, 0x66, 0x4e, 0x25, 0xf9, 0xd1, 0x8f, 0xed, 0xa2, 0x0a, 0xfb, 0x9f, 0xc3, + 0x95, 0x12, 0xc9, 0x7d, 0xef, 0x56, 0xb7, 0x24, 0xda, 0xf4, 0xb2, 0x22, 0x99, 0x63, 0x1d, 0xed, 0x73, 0x5a, 0x16, + 0xef, 0xae, 0x04, 0x23, 0x98, 0x3d, 0x30, 0x23, 0x9c, 0x8b, 0x41, 0x31, 0x6e, 0x99, 0x0a, 0x0b, 0xe6, 0x21, 0x72, + 0xbb, 0xeb, 0xa2, 0xca, 0x9d, 0x4c, 0x6e, 0xce, 0xf3, 0xf0, 0xb2, 0xb0, 0x62, 0xa1, 0x14, 0xbb, 0x38, 0xb7, 0x7e, + 0xe3, 0xde, 0xb7, 0xd4, 0x85, 0x25, 0xff, 0x1a, 0x4f, 0x23, 0x3c, 0x3d, 0xc2, 0xa8, 0xfc, 0x00, 0xbb, 0xb1, 0x13, + 0x7d, 0x25, 0x06, 0xe8, 0xf1, 0x9e, 0x1c, 0xbf, 0x5c, 0xde, 0x8b, 0x8e, 0x33, 0x9c, 0x30, 0xd2, 0xb8, 0xcd, 0x17, + 0xc4, 0xe9, 0x30, 0x37, 0x69, 0xc6, 0x8a, 0x7a, 0x24, 0x82, 0xf1, 0xd2, 0xfa, 0xb7, 0x2d, 0x4f, 0xf3, 0xf7, 0xf9, + 0x33, 0xc9, 0x17, 0xd3, 0x15, 0xf0, 0xf5, 0xe0, 0xcf, 0xd3, 0xfe, 0x40, 0x22, 0x10, 0x3d, 0x84, 0x23, 0x3d, 0xa6, + 0x65, 0x69, 0xf7, 0xec, 0xd8, 0x22, 0xf4, 0xfa, 0xb3, 0x44, 0x50, 0xea, 0x85, 0x52, 0xea, 0x0d, 0xca, 0x38, 0x25, + 0x81, 0x4d, 0x97, 0x42, 0x88, 0xf2, 0xfd, 0xdf, 0x38, 0x79, 0x8a, 0xf0, 0xb3, 0xe6, 0x94, 0xf6, 0x2a, 0x6a, 0x0a, + 0xea, 0x8c, 0x02, 0x60, 0x25, 0xee, 0xe3, 0x01, 0xb4, 0x6c, 0xa8, 0x0b, 0xae, 0x30, 0xa8, 0x5a, 0x95, 0x93, 0x40, + 0x9d, 0x6c, 0x14, 0x11, 0xb9, 0x29, 0xbe, 0x8b, 0x88, 0xc8, 0x1a, 0x06, 0xe5, 0x1c, 0x6c, 0x99, 0xce, 0x25, 0xc3, + 0xee, 0x36, 0xb5, 0xbc, 0xf0, 0x5e, 0x4d, 0x7a, 0xcc, 0xca, 0x76, 0xb8, 0x8f, 0x1c, 0x1d, 0x67, 0xb7, 0x7c, 0x91, + 0x38, 0x4c, 0xe2, 0x5a, 0xbd, 0xb7, 0x87, 0xac, 0xdd, 0x21, 0xe9, 0xaf, 0x05, 0x37, 0xdd, 0x21, 0xb3, 0x50, 0xda, + 0xbe, 0x3e, 0xfb, 0xa9, 0xba, 0xc3, 0xc0, 0x1b, 0x00, 0x4f, 0x31, 0xee, 0xfe, 0x6a, 0x6e, 0x43, 0xf5, 0xf8, 0x67, + 0x0f, 0x5d, 0x91, 0x48, 0x0b, 0xcc, 0x62, 0x0f, 0x87, 0x75, 0xd9, 0x4a, 0xdd, 0xb5, 0x71, 0x6e, 0x03, 0xe2, 0x8c, + 0x94, 0x90, 0x54, 0x0e, 0xd9, 0x28, 0x59, 0x1e, 0x51, 0x06, 0x6b, 0xbd, 0xbd, 0x74, 0x17, 0x73, 0x0f, 0xc3, 0x05, + 0x80, 0x92, 0x80, 0x65, 0x7b, 0xac, 0xb5, 0xfb, 0x00, 0x30, 0x42, 0xab, 0xc6, 0xcc, 0xe8, 0x55, 0xdc, 0x2a, 0xeb, + 0xc5, 0x8a, 0xcc, 0xa8, 0x1f, 0x6a, 0x22, 0x77, 0x07, 0x52, 0xd1, 0x56, 0xa8, 0x2c, 0xbf, 0x94, 0x4a, 0x4f, 0xab, + 0x02, 0xad, 0xd4, 0xd5, 0x8a, 0x0e, 0xba, 0x91, 0x92, 0xa2, 0x44, 0xdb, 0xb9, 0x00, 0xb9, 0xf2, 0x66, 0x18, 0x78, + 0x13, 0xd8, 0x2a, 0x32, 0x22, 0x81, 0x6b, 0xe1, 0xa9, 0x88, 0x24, 0x2f, 0xea, 0xae, 0x55, 0x35, 0x29, 0x8d, 0xb3, + 0x06, 0x9e, 0x6e, 0x29, 0xf2, 0x0b, 0x8d, 0x30, 0x2d, 0xf5, 0x41, 0x06, 0x89, 0xb4, 0x48, 0xe4, 0x7c, 0x5e, 0xbb, + 0x1f, 0xa2, 0x8e, 0x53, 0x74, 0x3c, 0x24, 0xdb, 0x6e, 0xbb, 0x14, 0x25, 0x87, 0x89, 0xee, 0x24, 0x16, 0xd3, 0x11, + 0x03, 0x95, 0xb2, 0x21, 0xc7, 0xd2, 0x6b, 0xd7, 0x8a, 0x13, 0xb8, 0xf8, 0x0f, 0xf9, 0xd8, 0xe6, 0xd9, 0x86, 0x61, + 0x0b, 0x2d, 0xcb, 0x11, 0xfd, 0xe5, 0xa5, 0x84, 0x0e, 0xd2, 0x12, 0x3d, 0xe4, 0x07, 0xc5, 0xb2, 0xab, 0x90, 0x35, + 0xe8, 0xa0, 0x71, 0xee, 0x4c, 0x66, 0x0b, 0x89, 0x94, 0x69, 0x52, 0x6b, 0x5a, 0x6c, 0x42, 0xc4, 0x33, 0x3f, 0x58, + 0x15, 0xa2, 0x46, 0x3c, 0xc8, 0x54, 0x58, 0x0a, 0xce, 0x16, 0x41, 0xe2, 0x4b, 0x9c, 0x1d, 0xce, 0x8b, 0xdd, 0x60, + 0x91, 0x45, 0xef, 0x30, 0xea, 0xcb, 0x61, 0x5f, 0xb7, 0x22, 0x36, 0xbd, 0x35, 0x2e, 0x3c, 0xaf, 0x99, 0xb5, 0x6a, + 0x47, 0x8c, 0x39, 0x43, 0x18, 0x29, 0x04, 0xf9, 0xe8, 0xd3, 0x11, 0xce, 0x8a, 0x53, 0x81, 0x0d, 0x1b, 0xd7, 0xb1, + 0xc3, 0xd9, 0x87, 0xba, 0x8b, 0xa0, 0xe1, 0xb9, 0x3a, 0x22, 0x48, 0xcc, 0x78, 0x83, 0x51, 0x2b, 0x34, 0xdf, 0xe8, + 0x3a, 0x6f, 0xcd, 0x74, 0xf3, 0x8d, 0xa4, 0x47, 0x69, 0xe1, 0x91, 0xdf, 0x62, 0x52, 0x71, 0xe6, 0xd6, 0x7e, 0x90, + 0x25, 0xd6, 0xfd, 0x0f, 0x41, 0xfc, 0x8a, 0x80, 0xea, 0x24, 0x21, 0x20, 0x40, 0x43, 0xeb, 0x7a, 0xa1, 0xd9, 0x56, + 0x58, 0x09, 0x0a, 0xcf, 0x55, 0xf0, 0x5f, 0x92, 0xa2, 0x61, 0xd2, 0x84, 0x26, 0x1e, 0x95, 0xfb, 0xb1, 0x83, 0x05, + 0xe2, 0x2c, 0x20, 0x8a, 0xc1, 0x49, 0x50, 0x09, 0x09, 0xb7, 0x54, 0x42, 0x7b, 0xa1, 0x15, 0x13, 0x2c, 0x80, 0x69, + 0x4f, 0x5c, 0x4a, 0x81, 0x62, 0xda, 0x8a, 0xa3, 0x39, 0x56, 0x43, 0x80, 0x61, 0x90, 0x51, 0x7f, 0x04, 0x5d, 0xac, + 0x61, 0x9a, 0x8c, 0xf7, 0xbb, 0x78, 0xe1, 0xe9, 0xe6, 0x74, 0x85, 0x52, 0x16, 0xf9, 0x2c, 0xc0, 0x09, 0xcd, 0xf8, + 0xa4, 0x00, 0xf5, 0x45, 0xbd, 0xb4, 0xf1, 0xdc, 0x3a, 0x9e, 0x83, 0x27, 0xe7, 0x8d, 0xe0, 0x6d, 0x1c, 0x54, 0xee, + 0x60, 0x0f, 0x60, 0x91, 0xd7, 0x5c, 0x33, 0x92, 0xcc, 0x18, 0x1e, 0x0d, 0xf3, 0x8c, 0xb9, 0x53, 0x42, 0xdb, 0x33, + 0xb9, 0x09, 0x5c, 0x9b, 0x06, 0xab, 0x86, 0xa5, 0x1f, 0xaf, 0xae, 0xd7, 0x5c, 0x1f, 0x40, 0xee, 0xdb, 0x96, 0x12, + 0x76, 0x37, 0x22, 0x8d, 0x31, 0x60, 0x9b, 0x50, 0xbd, 0x3f, 0x21, 0x9b, 0xa6, 0x5a, 0xd6, 0xc1, 0x61, 0xce, 0x2f, + 0x12, 0x54, 0xee, 0x41, 0xdb, 0x54, 0x16, 0xa1, 0xd7, 0x3c, 0xee, 0x89, 0x3e, 0x4f, 0xb8, 0x21, 0x58, 0x83, 0xd4, + 0x89, 0x8b, 0xab, 0xf2, 0x24, 0x41, 0x37, 0x5a, 0x6a, 0x2b, 0x96, 0x07, 0x03, 0x2e, 0xca, 0xb1, 0x1b, 0x92, 0x52, + 0xc1, 0x51, 0x92, 0xf4, 0x34, 0x96, 0x6a, 0x97, 0xdb, 0x6f, 0x33, 0x2e, 0xf5, 0x8e, 0x12, 0x9a, 0xd0, 0x69, 0x21, + 0x23, 0x0d, 0x84, 0x02, 0xb5, 0xb9, 0xbf, 0x4c, 0xdf, 0x8c, 0x3e, 0xc3, 0xb0, 0x91, 0x8b, 0xe1, 0x01, 0x94, 0xb3, + 0xda, 0x71, 0x38, 0xc7, 0xc3, 0xb2, 0x90, 0x5e, 0x30, 0x99, 0x21, 0xb2, 0x44, 0x2e, 0x7f, 0xd4, 0xa4, 0xe4, 0x02, + 0x1d, 0x4b, 0x6b, 0x1e, 0xd0, 0xae, 0x4e, 0x70, 0xa0, 0x3b, 0x7c, 0xd5, 0xc9, 0x57, 0x75, 0x14, 0xc9, 0x1c, 0x43, + 0xe7, 0xc0, 0xe2, 0x54, 0xcb, 0xb3, 0x91, 0x9d, 0xee, 0x0e, 0x70, 0x5e, 0x4a, 0xb7, 0x0b, 0x70, 0xd7, 0xfe, 0xc5, + 0x89, 0x8b, 0xe7, 0xb6, 0xd5, 0x60, 0x8b, 0xce, 0x74, 0x08, 0xe7, 0xcf, 0xd4, 0xcd, 0x09, 0x6f, 0xa1, 0xcb, 0xa9, + 0xfd, 0xb9, 0xe0, 0xfa, 0xe3, 0x15, 0xdd, 0x6e, 0xeb, 0x82, 0xc3, 0x72, 0x94, 0xb3, 0x2e, 0x89, 0x54, 0xb2, 0xd2, + 0x1b, 0x7d, 0x3e, 0x90, 0xa7, 0x0d, 0xb6, 0x5f, 0x28, 0x98, 0x39, 0x75, 0x50, 0xac, 0x62, 0x92, 0xd9, 0xe1, 0xc1, + 0xe4, 0xbb, 0xb2, 0x58, 0x32, 0x56, 0x27, 0xb3, 0xdc, 0x81, 0x71, 0x4b, 0x6b, 0xef, 0x57, 0x76, 0x29, 0xe3, 0xcb, + 0x88, 0x72, 0x2b, 0xaf, 0x8d, 0x83, 0x4c, 0xdb, 0x25, 0xb2, 0xdc, 0xd6, 0xb7, 0xcb, 0x34, 0x7b, 0x48, 0xd2, 0xed, + 0x04, 0xc9, 0x77, 0x06, 0x9f, 0x18, 0x52, 0xa2, 0x17, 0x52, 0xeb, 0xf1, 0xb5, 0x77, 0x95, 0x38, 0x45, 0xbc, 0x2a, + 0x06, 0x61, 0x65, 0x7d, 0x8e, 0x2d, 0x69, 0x16, 0xa8, 0x63, 0x15, 0x49, 0xdc, 0x2a, 0x24, 0x7e, 0x69, 0xf5, 0x17, + 0xb6, 0xdc, 0xa8, 0xfc, 0x14, 0x89, 0x77, 0x88, 0xfe, 0x72, 0x5c, 0xa2, 0x7b, 0xad, 0x0a, 0x44, 0x19, 0xe6, 0xa9, + 0x9c, 0xb1, 0x60, 0xe9, 0xe6, 0x89, 0x2c, 0x9a, 0x3d, 0x5f, 0x6e, 0xa0, 0x49, 0x94, 0x88, 0xcd, 0x85, 0x5e, 0xe6, + 0xce, 0x19, 0xe8, 0xe8, 0x24, 0xac, 0x53, 0xab, 0xc9, 0xc4, 0x1e, 0x83, 0xb3, 0x97, 0xac, 0xe8, 0x09, 0xae, 0x7b, + 0xce, 0x3b, 0xfb, 0xaf, 0xb9, 0x70, 0x3a, 0x34, 0xfb, 0xe9, 0xfc, 0x98, 0x61, 0x96, 0x8e, 0x14, 0xb8, 0x25, 0x76, + 0xab, 0x3b, 0x11, 0x65, 0x4c, 0xfb, 0xc4, 0x58, 0x5d, 0xdf, 0x76, 0x8a, 0x8e, 0xc9, 0xbf, 0x99, 0xa7, 0xe1, 0xdc, + 0x39, 0x51, 0x62, 0x37, 0x39, 0x61, 0xb7, 0xd6, 0xdd, 0xf3, 0xe0, 0x67, 0x84, 0x18, 0xa5, 0x14, 0x6c, 0x82, 0x7a, + 0xab, 0xaa, 0x02, 0xe6, 0x69, 0x58, 0x34, 0x63, 0x4f, 0x14, 0x91, 0x5d, 0x7f, 0x27, 0x66, 0x8e, 0x29, 0x8b, 0x2e, + 0x59, 0x93, 0xc1, 0x54, 0x4d, 0xa9, 0x3b, 0x92, 0x1a, 0xb9, 0x83, 0x84, 0xec, 0x6f, 0x8d, 0x14, 0x81, 0x7a, 0xa3, + 0x71, 0x71, 0x6f, 0x0d, 0x8c, 0x69, 0xa0, 0xd9, 0xd6, 0x2c, 0x1d, 0xa8, 0x03, 0x37, 0xda, 0xd6, 0x85, 0x4a, 0xd5, + 0x76, 0xe1, 0xeb, 0x57, 0xfb, 0xbc, 0xcf, 0xac, 0x05, 0x6d, 0x18, 0xfa, 0x19, 0xd8, 0x26, 0xc5, 0xfd, 0x17, 0x22, + 0x4d, 0x15, 0xa5, 0xd8, 0x77, 0x20, 0x9b, 0x75, 0x6f, 0xad, 0x82, 0x90, 0x93, 0xaa, 0xf4, 0x7d, 0x9a, 0xf5, 0xa4, + 0xd3, 0x95, 0x65, 0x65, 0xb6, 0x8d, 0xdf, 0xee, 0x86, 0xed, 0x83, 0x85, 0xcd, 0x2b, 0x95, 0x4e, 0xa4, 0x83, 0x08, + 0x0c, 0x83, 0xe7, 0xd0, 0x97, 0x7e, 0xa0, 0xf2, 0x7b, 0xa0, 0xfa, 0xac, 0x8c, 0x1d, 0xae, 0xbd, 0xd0, 0x78, 0x01, + 0x5d, 0x90, 0x70, 0x3f, 0x4d, 0x2a, 0xa7, 0x61, 0x52, 0x83, 0x8e, 0xb6, 0xba, 0x4e, 0x2c, 0x0f, 0x44, 0x80, 0x7f, + 0x28, 0x50, 0x8d, 0x99, 0x01, 0x76, 0x3d, 0x09, 0x6c, 0xab, 0x59, 0xd6, 0x43, 0x2f, 0x38, 0x9c, 0xae, 0xa0, 0xbb, + 0x97, 0x5f, 0x31, 0x0e, 0x72, 0x87, 0x5d, 0x29, 0xb0, 0x3e, 0x39, 0x72, 0x2c, 0x50, 0x3b, 0x47, 0x0d, 0x0c, 0xbb, + 0x45, 0x6d, 0xb8, 0xef, 0x53, 0x6a, 0x76, 0x43, 0xb8, 0x1b, 0x1c, 0xb8, 0xa5, 0x62, 0xdb, 0xf2, 0xa8, 0xd2, 0xfc, + 0x65, 0x3b, 0x50, 0x46, 0xeb, 0x8d, 0x51, 0xef, 0xed, 0xee, 0x43, 0x49, 0x4a, 0xdb, 0xcf, 0x97, 0xf9, 0x24, 0xd9, + 0x7b, 0x65, 0x96, 0xba, 0x7a, 0x3f, 0x35, 0xb9, 0x5d, 0xad, 0xa9, 0xd2, 0x99, 0x0a, 0x0e, 0x85, 0x72, 0x9e, 0x5d, + 0xb9, 0x93, 0x12, 0x2b, 0x6c, 0xee, 0xa5, 0x1b, 0x41, 0x7a, 0xec, 0x24, 0x53, 0x62, 0x42, 0x48, 0x9d, 0xfd, 0x76, + 0x67, 0xee, 0x0f, 0x57, 0xdf, 0x92, 0xa2, 0xbe, 0xe3, 0xa6, 0xe5, 0x78, 0xe9, 0xb7, 0xcb, 0x8d, 0x32, 0x98, 0x46, + 0xd1, 0x60, 0x69, 0x19, 0x1c, 0x74, 0xd7, 0x32, 0xc0, 0xb9, 0x4b, 0xfc, 0x5d, 0x3f, 0xae, 0x68, 0xda, 0x00, 0x5d, + 0x16, 0xfb, 0x84, 0x72, 0x49, 0x1c, 0x94, 0xf0, 0x48, 0xd3, 0x26, 0x4d, 0x88, 0x14, 0x39, 0xd8, 0xb6, 0x90, 0x81, + 0x21, 0x59, 0x88, 0x62, 0x50, 0xf9, 0x55, 0xae, 0x4e, 0x78, 0x9d, 0xcf, 0x16, 0xbc, 0x84, 0x28, 0x5c, 0x95, 0x71, + 0x75, 0xa3, 0x66, 0x31, 0xaf, 0x0e, 0x3b, 0xa9, 0xa6, 0x0d, 0x0d, 0x63, 0xd4, 0x11, 0xb9, 0xdb, 0xf8, 0xe0, 0x9d, + 0x2d, 0xd4, 0x0c, 0x16, 0xdf, 0xa9, 0x09, 0xf8, 0x6b, 0x7d, 0xf1, 0x16, 0x42, 0x0e, 0x71, 0x9e, 0x56, 0x68, 0x78, + 0xa1, 0xac, 0xd1, 0xb8, 0x17, 0xb2, 0x1a, 0xfb, 0xb9, 0xcb, 0x20, 0x6d, 0x38, 0x19, 0x94, 0x8e, 0xc3, 0xa5, 0x7c, + 0x97, 0xd4, 0x2d, 0xbd, 0x41, 0x89, 0xb8, 0x0e, 0x60, 0x27, 0x6a, 0xa9, 0x74, 0x51, 0x49, 0xeb, 0xa7, 0x86, 0xf2, + 0x64, 0xd8, 0x4b, 0xe7, 0x64, 0x60, 0xcc, 0xe8, 0x3c, 0xd4, 0x8c, 0x41, 0xb4, 0x86, 0x65, 0xd8, 0xa0, 0x7d, 0xac, + 0x5e, 0x20, 0xfb, 0x44, 0xd3, 0xaa, 0x33, 0x74, 0xd8, 0xc9, 0x84, 0x5f, 0xaa, 0x53, 0x31, 0x65, 0xfe, 0x95, 0x99, + 0xb6, 0xcd, 0xfb, 0x6e, 0x34, 0x94, 0x37, 0x97, 0x7e, 0xcc, 0xf9, 0x15, 0x97, 0x02, 0x97, 0x0b, 0x68, 0x0d, 0xf7, + 0x90, 0x7f, 0xc3, 0xbc, 0xec, 0xd7, 0x76, 0x60, 0x02, 0x11, 0xa7, 0x1a, 0x8d, 0x73, 0x4a, 0x8e, 0xa6, 0x3a, 0xe7, + 0x7d, 0x13, 0xce, 0x28, 0x95, 0x06, 0x64, 0xd4, 0xb2, 0x48, 0x26, 0xc1, 0x4c, 0x07, 0xcd, 0x0b, 0x67, 0x1b, 0xed, + 0xa4, 0xd1, 0xc1, 0xeb, 0x4d, 0xdc, 0x75, 0x41, 0x93, 0x5e, 0x11, 0x3f, 0x76, 0xd4, 0x56, 0x8c, 0x53, 0x17, 0x2e, + 0x02, 0xcf, 0xe4, 0x2c, 0x8b, 0x43, 0x99, 0xf4, 0x7a, 0x45, 0xd5, 0xb2, 0xa4, 0xb3, 0x54, 0x0f, 0xe8, 0x12, 0xd4, + 0xe3, 0xd3, 0xa2, 0xbc, 0x62, 0x35, 0x98, 0xef, 0x40, 0xd9, 0x6b, 0x97, 0xd0, 0xf3, 0x7d, 0xa1, 0x0e, 0x32, 0x1a, + 0xbb, 0xf3, 0xf9, 0x92, 0x1a, 0x93, 0x03, 0xe7, 0x4d, 0xf3, 0x0a, 0x67, 0xd7, 0x5b, 0x52, 0x0b, 0xa1, 0x4f, 0xda, + 0xa0, 0x67, 0x89, 0x84, 0xbf, 0x83, 0x3a, 0x9c, 0xdd, 0x20, 0xa9, 0x33, 0x6c, 0xca, 0xe9, 0xa7, 0xa0, 0x35, 0xe1, + 0x62, 0x23, 0x0b, 0xdb, 0x87, 0x1e, 0x54, 0x9b, 0x47, 0x76, 0x71, 0xb8, 0xa3, 0x98, 0x36, 0x83, 0xb0, 0x96, 0xe0, + 0xa1, 0x34, 0xf4, 0x16, 0x9b, 0xfe, 0x7c, 0x23, 0xc3, 0xe5, 0x26, 0xc9, 0xc2, 0x95, 0xe9, 0xd1, 0x10, 0x60, 0xd7, + 0xee, 0xf7, 0xb6, 0x3a, 0x05, 0x7f, 0x09, 0x0f, 0x46, 0x31, 0x7d, 0x3e, 0x7b, 0x65, 0x80, 0xfd, 0x44, 0x4f, 0xa7, + 0xfb, 0xa6, 0x50, 0x3a, 0x87, 0x5c, 0x62, 0x5d, 0x18, 0x63, 0x8c, 0xa3, 0x7a, 0xb7, 0xa3, 0x8c, 0xbd, 0xe4, 0xd8, + 0x01, 0x0f, 0x85, 0x0f, 0x77, 0x94, 0xf2, 0xaa, 0x1d, 0x6b, 0x37, 0xb9, 0xe6, 0x1b, 0xf9, 0x88, 0x1c, 0xbd, 0xa4, + 0x18, 0xa4, 0x65, 0x23, 0xa0, 0x19, 0x83, 0x97, 0x48, 0x0b, 0xd2, 0x36, 0xf4, 0xb3, 0xcc, 0x75, 0x42, 0xa1, 0x05, + 0x9c, 0x9e, 0x31, 0xa8, 0x28, 0x2c, 0x3a, 0xaa, 0xa4, 0xfd, 0x87, 0x03, 0x42, 0x06, 0xa3, 0xd5, 0xda, 0x6c, 0xcb, + 0xf6, 0xa6, 0xc9, 0x1f, 0x6c, 0x3f, 0xd1, 0x9b, 0xe9, 0x43, 0x7e, 0x7a, 0x1c, 0x03, 0x5f, 0x35, 0xb7, 0x6b, 0x3c, + 0xaf, 0xf7, 0x5e, 0x55, 0x93, 0x6f, 0xfd, 0x55, 0x8e, 0x8f, 0xa1, 0x86, 0x64, 0xe9, 0x44, 0xe9, 0xf2, 0xb0, 0xf7, + 0xb3, 0x3e, 0xb1, 0x4f, 0x16, 0x26, 0xd3, 0x3b, 0x93, 0xd8, 0x8c, 0xd7, 0x9d, 0x6f, 0x30, 0xae, 0x8c, 0x78, 0x65, + 0xfd, 0x56, 0x9f, 0xc9, 0xc1, 0xf6, 0x12, 0x30, 0x52, 0xaf, 0x2c, 0x05, 0x0e, 0x0a, 0x3a, 0x71, 0x08, 0x1e, 0x22, + 0xcf, 0x71, 0xe6, 0x86, 0x2f, 0x6a, 0x5d, 0x93, 0x88, 0xc8, 0x97, 0xf5, 0x2c, 0x4f, 0x21, 0x73, 0x24, 0x6c, 0xb9, + 0x9e, 0x3e, 0x06, 0x4e, 0x95, 0xb6, 0xec, 0x2f, 0x9b, 0xad, 0xe6, 0xfa, 0x10, 0xfc, 0x23, 0xd2, 0x5d, 0xfc, 0x1a, + 0xc7, 0x23, 0x8d, 0x64, 0x21, 0x55, 0xb5, 0x90, 0x5b, 0x16, 0x0d, 0x16, 0x32, 0x8c, 0x2f, 0x2b, 0x53, 0xd9, 0x8b, + 0x3b, 0x50, 0x22, 0x5f, 0xdf, 0xc2, 0x19, 0x0e, 0x87, 0xd0, 0xf9, 0xeb, 0x9b, 0x2a, 0x43, 0x56, 0x3f, 0xef, 0xd9, + 0x88, 0x63, 0xac, 0x8f, 0xad, 0xb7, 0x37, 0xbd, 0x5b, 0x81, 0xc8, 0x19, 0x27, 0xdb, 0xa7, 0x5f, 0x71, 0xbf, 0x56, + 0xf8, 0x7a, 0xd8, 0x54, 0xf8, 0xf5, 0xd6, 0xc5, 0x81, 0xac, 0x20, 0xe3, 0x09, 0x0b, 0x46, 0x20, 0xc5, 0x63, 0x83, + 0x0e, 0x1a, 0xa7, 0x0c, 0xa8, 0x37, 0xb0, 0xaf, 0x9b, 0x3a, 0xf2, 0xf5, 0x65, 0xf6, 0xb7, 0xe9, 0xb2, 0x1f, 0x40, + 0x96, 0x7d, 0xfe, 0x01, 0x1b, 0xb6, 0xa5, 0xbb, 0x01, 0xb3, 0x37, 0x90, 0x19, 0x99, 0xf6, 0x4b, 0xa4, 0x8f, 0x30, + 0x68, 0x9b, 0xcb, 0x00, 0xae, 0x4d, 0xfa, 0xf3, 0xf9, 0x18, 0x42, 0x0c, 0x21, 0x2c, 0xe3, 0x9d, 0x1b, 0xef, 0x46, + 0xfa, 0xa6, 0xd1, 0x2d, 0x52, 0xfc, 0x17, 0xf1, 0x2c, 0x0b, 0x38, 0x0f, 0x91, 0x3a, 0xc1, 0x55, 0xbd, 0x6c, 0x4f, + 0x90, 0x2a, 0xd7, 0xe2, 0xf5, 0xe1, 0x1b, 0x89, 0xc5, 0x9e, 0x88, 0x8f, 0x39, 0xd4, 0x39, 0x64, 0x3a, 0x89, 0x66, + 0xe9, 0x2b, 0x75, 0x40, 0x28, 0x27, 0x60, 0x7e, 0x96, 0x58, 0xeb, 0x94, 0x1c, 0xc2, 0xdb, 0x37, 0xff, 0x26, 0xca, + 0x3d, 0x78, 0x2c, 0x29, 0x86, 0x29, 0x5a, 0x88, 0x31, 0x8e, 0x8b, 0xa7, 0x75, 0x9d, 0x90, 0x11, 0xeb, 0xcf, 0xcf, + 0x56, 0x99, 0xad, 0x81, 0x1a, 0x49, 0x43, 0xe1, 0x90, 0x1b, 0x1d, 0x33, 0x0b, 0x93, 0x0b, 0xe3, 0x6c, 0xdd, 0x16, + 0xef, 0x24, 0xf2, 0xa8, 0x7c, 0x33, 0x0e, 0x8f, 0xd4, 0xe3, 0x90, 0x8d, 0xb4, 0xca, 0x92, 0x4e, 0xb8, 0x13, 0x0c, + 0x87, 0xc9, 0xa2, 0x8c, 0xcd, 0x2c, 0xa4, 0x10, 0xad, 0xe4, 0x04, 0x20, 0x7b, 0x38, 0x41, 0x2d, 0x04, 0x66, 0x95, + 0x61, 0x65, 0x28, 0x0c, 0x88, 0x38, 0x08, 0x77, 0x9f, 0xfc, 0xb1, 0xc0, 0xfe, 0x56, 0x1e, 0x43, 0xf2, 0xe1, 0x97, + 0x38, 0x42, 0x0f, 0xc6, 0xb5, 0x50, 0x06, 0x13, 0x21, 0x7a, 0xcb, 0x18, 0xce, 0x53, 0x9d, 0x78, 0x8b, 0xde, 0x3a, + 0xd1, 0x0d, 0x24, 0x04, 0x71, 0xb3, 0x96, 0xf3, 0x0d, 0xac, 0x28, 0x0b, 0x1c, 0x34, 0x61, 0x9d, 0x15, 0x5b, 0xb1, + 0x4d, 0xc1, 0x43, 0x94, 0xe4, 0x00, 0xf8, 0x32, 0x40, 0xae, 0x4e, 0xb2, 0x2b, 0x25, 0xb0, 0x0e, 0xe1, 0xa4, 0x60, + 0xa6, 0x31, 0xb2, 0xe6, 0xd5, 0xa6, 0xf6, 0x61, 0x56, 0x8d, 0x6f, 0x00, 0xa6, 0xbe, 0x72, 0x4e, 0xd8, 0x66, 0x97, + 0x8e, 0x6a, 0xb1, 0x2d, 0x16, 0xfd, 0x8f, 0x7b, 0x51, 0x03, 0x5e, 0xbd, 0x1e, 0x67, 0xff, 0x0b, 0x46, 0xe7, 0x0e, + 0x88, 0x7e, 0x75, 0xef, 0xb0, 0xcd, 0x01, 0x9b, 0x64, 0x55, 0xdb, 0x48, 0x9c, 0x0e, 0x78, 0x4e, 0xaa, 0x75, 0x92, + 0x46, 0x41, 0xf5, 0xc4, 0xa6, 0x7b, 0x1d, 0x59, 0x71, 0xd6, 0x44, 0x01, 0x5b, 0xc5, 0x1a, 0xe1, 0x82, 0xf1, 0xe5, + 0x42, 0xdc, 0x6c, 0xbb, 0x00, 0x86, 0x30, 0xd6, 0xac, 0xb8, 0xc6, 0x07, 0xbf, 0x3d, 0x05, 0xd4, 0x13, 0x96, 0x78, + 0x08, 0xfb, 0x1a, 0x84, 0x93, 0xf9, 0xf0, 0xb3, 0x59, 0xdf, 0x7c, 0x83, 0xaa, 0xcb, 0x10, 0xf3, 0xfc, 0x24, 0xa7, + 0xc7, 0xdf, 0x2e, 0x3f, 0x74, 0x3a, 0x4b, 0x3f, 0xe3, 0x3a, 0x4b, 0x84, 0x79, 0xf7, 0xd3, 0x1f, 0x4d, 0x6b, 0x03, + 0x6f, 0xd1, 0x55, 0x73, 0x51, 0x33, 0xce, 0x9d, 0x3d, 0x27, 0x9b, 0x08, 0x7b, 0x4a, 0x80, 0x4a, 0x35, 0x57, 0xf5, + 0x9b, 0x22, 0xf5, 0x31, 0xb6, 0xa9, 0xe2, 0xe3, 0x09, 0xd0, 0x52, 0xbe, 0xb9, 0xa3, 0x0b, 0x26, 0x41, 0xd6, 0xfd, + 0x7c, 0xcb, 0xa8, 0xd0, 0xc0, 0xb0, 0x1f, 0x13, 0xc2, 0x79, 0xfa, 0x89, 0x80, 0x91, 0xb4, 0x93, 0x4d, 0xfa, 0x20, + 0xe9, 0xb1, 0x89, 0x22, 0xe7, 0x4c, 0xc3, 0xf8, 0x8c, 0x13, 0x68, 0x0c, 0x58, 0x5a, 0x16, 0x1d, 0xca, 0x4a, 0xdb, + 0xc4, 0x9f, 0xc8, 0x77, 0x63, 0x13, 0x5b, 0x0d, 0x41, 0x1a, 0x4c, 0x80, 0x36, 0xc3, 0xe9, 0x0c, 0x74, 0x41, 0x17, + 0xbd, 0xb9, 0x79, 0x6f, 0xb9, 0xf9, 0x30, 0x32, 0x0f, 0x5d, 0xfe, 0x9c, 0xd8, 0x8a, 0xb7, 0x26, 0x75, 0x4e, 0xd5, + 0xb5, 0x2e, 0xe9, 0x4c, 0x7f, 0xc2, 0xb6, 0x12, 0x4b, 0x88, 0xbc, 0xa3, 0xfd, 0x21, 0x3c, 0x84, 0xb4, 0x45, 0xc9, + 0x89, 0xed, 0x9f, 0x14, 0x2b, 0x39, 0x9e, 0x6c, 0x2c, 0xfb, 0x69, 0x53, 0xfb, 0x5b, 0xa4, 0x83, 0xdd, 0x57, 0xea, + 0x87, 0x55, 0x5c, 0x12, 0x35, 0x5c, 0x8b, 0x2e, 0x28, 0xfd, 0x0b, 0xd3, 0x49, 0x62, 0xd5, 0xe5, 0x18, 0xf7, 0x2c, + 0x99, 0x63, 0x7d, 0x0c, 0x0a, 0x4f, 0x57, 0x91, 0x4c, 0xe8, 0xbc, 0x86, 0xba, 0x34, 0xbd, 0xeb, 0xea, 0x14, 0xe1, + 0x0d, 0x65, 0xce, 0x5b, 0x6d, 0x89, 0xda, 0xe9, 0x7d, 0xcd, 0xff, 0x6e, 0x50, 0x64, 0x93, 0x91, 0x9c, 0x07, 0xce, + 0x60, 0x2d, 0xc9, 0xe0, 0x51, 0x89, 0x28, 0x2a, 0x1f, 0x62, 0xf3, 0x45, 0xae, 0xa0, 0x97, 0xa7, 0x88, 0x8a, 0xbb, + 0x65, 0xb1, 0xf3, 0x31, 0x7f, 0x50, 0x5b, 0xa2, 0x0e, 0x4b, 0x2a, 0x4a, 0x60, 0x65, 0xdd, 0x4f, 0x23, 0x2e, 0xf5, + 0x9f, 0xe2, 0xf6, 0xfb, 0x95, 0xc7, 0x70, 0x45, 0xde, 0xdb, 0x14, 0x5d, 0xd1, 0x0e, 0x8e, 0xba, 0x61, 0xd9, 0x2d, + 0x7f, 0x48, 0x03, 0x92, 0x3d, 0xb7, 0x7a, 0x78, 0x08, 0x9f, 0x27, 0xff, 0xb0, 0xac, 0xfd, 0x65, 0x55, 0x49, 0x0f, + 0xa5, 0x91, 0x42, 0x1f, 0xa9, 0xe6, 0xc7, 0x15, 0xdd, 0xde, 0x4f, 0xad, 0x5b, 0xaf, 0x1f, 0x60, 0xf6, 0x51, 0x86, + 0xc8, 0xda, 0x2c, 0x5b, 0xf5, 0x01, 0x2a, 0x18, 0x5a, 0xf1, 0x19, 0xf4, 0x44, 0xd3, 0xa4, 0x5e, 0x79, 0x33, 0x3a, + 0x33, 0x73, 0x90, 0x71, 0x68, 0xb9, 0xfc, 0xf1, 0x1b, 0x11, 0x13, 0x93, 0xaa, 0xa5, 0xb6, 0x28, 0xc3, 0xf5, 0x82, + 0x93, 0x28, 0x11, 0x4f, 0x30, 0xa7, 0xdf, 0xa5, 0xf4, 0x82, 0x39, 0x14, 0xac, 0x70, 0x8e, 0x3e, 0x9f, 0x95, 0x72, + 0x29, 0x09, 0xf9, 0xb6, 0x84, 0x6c, 0xa1, 0x21, 0x94, 0x52, 0x6e, 0x39, 0x1a, 0x97, 0x73, 0x38, 0x65, 0x6c, 0xf6, + 0x14, 0x26, 0x3e, 0x15, 0xaf, 0x62, 0xde, 0xe8, 0xf5, 0x35, 0x62, 0x91, 0x72, 0xd9, 0x05, 0x09, 0x0b, 0x67, 0x24, + 0x97, 0x18, 0xd9, 0x04, 0x2b, 0x9c, 0x5b, 0xa8, 0x06, 0xb3, 0xae, 0x0d, 0x94, 0xaa, 0x6f, 0x40, 0x8f, 0x86, 0x7c, + 0xd5, 0xd4, 0xb9, 0xea, 0x7f, 0x3a, 0xa1, 0x11, 0x2f, 0x0b, 0xdf, 0x71, 0x1f, 0x4a, 0x4f, 0xaf, 0x90, 0x11, 0xd7, + 0x6d, 0x27, 0x1d, 0x68, 0xc6, 0xc8, 0x48, 0x98, 0xa3, 0x45, 0x9d, 0x8b, 0x06, 0xda, 0x28, 0xc4, 0x95, 0x04, 0x2d, + 0xa4, 0x11, 0x92, 0x54, 0xec, 0x5c, 0x06, 0x4e, 0x1a, 0x48, 0x4f, 0x12, 0x14, 0x32, 0xe4, 0x61, 0xee, 0x7f, 0x25, + 0x65, 0xd1, 0xd4, 0xc2, 0x25, 0xe6, 0xb7, 0xf2, 0xfd, 0xa9, 0x2d, 0x5a, 0xb5, 0x0e, 0x14, 0x90, 0xca, 0x23, 0xd6, + 0x2c, 0x9b, 0x71, 0xaf, 0x38, 0x2a, 0xc7, 0xa3, 0xd2, 0xd6, 0x94, 0x9a, 0xae, 0x68, 0x1e, 0x34, 0xa5, 0x87, 0xe9, + 0x94, 0xd8, 0x1a, 0xcb, 0xab, 0x53, 0x4b, 0xa5, 0xfa, 0xf7, 0x99, 0xa5, 0xba, 0x38, 0x6a, 0xf9, 0x26, 0xb0, 0xd8, + 0x9d, 0x83, 0x09, 0x0d, 0xf7, 0x99, 0xcd, 0xa7, 0x30, 0x2c, 0xa7, 0xcc, 0xb2, 0xec, 0xc1, 0xd2, 0x66, 0x42, 0xd0, + 0xe6, 0x3b, 0x8c, 0x13, 0xf2, 0x8c, 0x18, 0x50, 0x48, 0xa9, 0x91, 0xaf, 0xcd, 0x06, 0x31, 0xf8, 0x89, 0xdb, 0x9f, + 0xe8, 0x22, 0x41, 0xc1, 0x11, 0x3d, 0x1f, 0x1c, 0x72, 0x3c, 0x7e, 0x90, 0xa9, 0x19, 0x46, 0xb0, 0x14, 0x2f, 0x67, + 0xd6, 0xd3, 0x12, 0x10, 0x10, 0x4d, 0xf2, 0x5e, 0xbd, 0x11, 0x81, 0x9a, 0x59, 0x09, 0x51, 0x07, 0x27, 0x0c, 0xbf, + 0x08, 0x31, 0xe0, 0x8c, 0x02, 0x10, 0x8e, 0x39, 0x3d, 0x20, 0x87, 0xaf, 0x73, 0x96, 0x7e, 0x4b, 0x4b, 0xe5, 0xa8, + 0xed, 0x45, 0x61, 0x9a, 0x3e, 0x8e, 0x05, 0x0e, 0x95, 0x04, 0xd5, 0x4b, 0x61, 0xb4, 0xd8, 0xf0, 0x7b, 0xe1, 0xea, + 0xd0, 0x27, 0x6f, 0xee, 0xc3, 0x6b, 0xce, 0x3a, 0x7c, 0x4c, 0xc2, 0x8e, 0x49, 0xc1, 0x85, 0x9d, 0xba, 0x6c, 0xe4, + 0x40, 0x00, 0x60, 0x6f, 0xeb, 0xcf, 0x13, 0xde, 0x66, 0xcb, 0x58, 0xd0, 0xf1, 0xf6, 0x0d, 0x3e, 0x1c, 0x02, 0x3f, + 0xea, 0xed, 0x68, 0x99, 0xa4, 0x7b, 0xd2, 0x90, 0xba, 0x97, 0x35, 0x6c, 0xc1, 0xe4, 0x9c, 0x5f, 0xa0, 0xa3, 0xb7, + 0x99, 0xa3, 0xe4, 0xbe, 0xe8, 0xeb, 0x01, 0x21, 0x8d, 0x07, 0x65, 0x70, 0x84, 0x35, 0x9e, 0x31, 0x23, 0x6f, 0xf5, + 0xcd, 0x76, 0xce, 0x5a, 0x60, 0x2b, 0xb4, 0xb6, 0xda, 0x20, 0x66, 0xa1, 0xfa, 0xb7, 0x37, 0x95, 0x00, 0x46, 0xd0, + 0xb0, 0xcf, 0x4b, 0xfa, 0x46, 0xd5, 0xa9, 0x7f, 0x9f, 0x7b, 0x73, 0x51, 0x64, 0x98, 0x93, 0x28, 0xc6, 0x57, 0xcc, + 0x29, 0xfa, 0x45, 0x29, 0x52, 0x03, 0xb7, 0x79, 0x99, 0x95, 0x58, 0x73, 0x46, 0x3d, 0xc2, 0x73, 0x4a, 0x32, 0x07, + 0x6c, 0xc5, 0xbf, 0x8d, 0x76, 0x2a, 0x94, 0x7c, 0x54, 0xff, 0x15, 0x7f, 0x90, 0xa0, 0x80, 0x91, 0xe1, 0x4e, 0x07, + 0x61, 0xd5, 0xb2, 0xee, 0x74, 0xdb, 0x83, 0x8f, 0x2b, 0xa2, 0xa5, 0xb3, 0xd5, 0x95, 0xd7, 0x63, 0xe7, 0x6f, 0x8f, + 0xbf, 0xfd, 0x67, 0x63, 0x11, 0x33, 0x8e, 0x37, 0xe0, 0xa7, 0x88, 0xdb, 0x50, 0x0a, 0x1a, 0xe1, 0xcb, 0xf0, 0x71, + 0x64, 0x98, 0x7f, 0x93, 0x79, 0x37, 0xed, 0xf5, 0x7d, 0xb1, 0xe7, 0xe9, 0x2c, 0xa8, 0xd6, 0xc6, 0x49, 0xce, 0x4a, + 0x5c, 0xae, 0xe4, 0xc8, 0x87, 0xaf, 0xc4, 0xad, 0xe3, 0x7b, 0xab, 0x12, 0xce, 0xf5, 0xf8, 0x46, 0x8e, 0x95, 0x61, + 0x50, 0xba, 0x45, 0xe7, 0x40, 0x2c, 0xc3, 0xd7, 0x12, 0x09, 0xd9, 0xe9, 0x07, 0x84, 0x61, 0xf4, 0x8b, 0x9f, 0x1f, + 0x4d, 0x98, 0x59, 0xed, 0x1f, 0x39, 0x18, 0x8e, 0x5d, 0x4c, 0x23, 0x30, 0x42, 0x2c, 0xa1, 0x90, 0xd2, 0x41, 0x1f, + 0xc1, 0x95, 0x54, 0xd9, 0x07, 0xdc, 0xce, 0x7c, 0x42, 0x65, 0x7f, 0x64, 0x67, 0x7d, 0xef, 0x44, 0x7c, 0x52, 0xb3, + 0xfb, 0xbd, 0x56, 0x55, 0x7b, 0x77, 0xbd, 0x16, 0x59, 0x62, 0x07, 0x4b, 0x60, 0x87, 0xc5, 0x8c, 0xc5, 0x96, 0x18, + 0x2e, 0x68, 0xcf, 0xea, 0x78, 0x0f, 0x4c, 0xc6, 0xf0, 0x63, 0x15, 0xb3, 0x4c, 0x0e, 0xd2, 0x6d, 0x95, 0xe9, 0xd9, + 0x1e, 0x95, 0x9b, 0x3f, 0x54, 0x96, 0xec, 0xe1, 0xff, 0x33, 0x3f, 0xce, 0x60, 0x8e, 0xe2, 0xeb, 0x45, 0x96, 0xe4, + 0x86, 0x7a, 0xcd, 0x7e, 0xfc, 0xab, 0xb1, 0xed, 0x31, 0x24, 0x82, 0xcd, 0xdd, 0x6a, 0x6b, 0x3f, 0x03, 0x14, 0xa7, + 0xac, 0x02, 0x29, 0x4a, 0xa6, 0x63, 0x8e, 0x6c, 0xd0, 0xa1, 0x38, 0x18, 0x04, 0x8f, 0xbb, 0x4f, 0xad, 0x5a, 0xe0, + 0xe9, 0x0a, 0x57, 0x20, 0x63, 0x37, 0x96, 0xb5, 0xd5, 0xcf, 0xda, 0x78, 0x3f, 0xa2, 0x27, 0x21, 0xb0, 0x64, 0xbd, + 0x0f, 0xf0, 0x51, 0xb0, 0x97, 0x0d, 0x00, 0xca, 0x5b, 0xbe, 0xb6, 0x6f, 0x9f, 0x9f, 0x53, 0xa7, 0xb9, 0x6c, 0x3f, + 0xb1, 0x77, 0xe2, 0x33, 0x67, 0xae, 0xaa, 0xb3, 0xdc, 0xd2, 0x7d, 0x0c, 0x81, 0x20, 0x46, 0xc3, 0x03, 0x42, 0x06, + 0x8c, 0x9e, 0xe2, 0x1d, 0x67, 0xc6, 0x3f, 0x9b, 0x27, 0x35, 0x4e, 0xf6, 0x1f, 0xde, 0x58, 0x78, 0x2d, 0x2d, 0x81, + 0xde, 0x45, 0xf8, 0xdf, 0xde, 0x95, 0x67, 0x1d, 0x13, 0x4d, 0x50, 0x75, 0x70, 0xb5, 0x53, 0x5f, 0xf5, 0x26, 0x37, + 0x6f, 0x15, 0x63, 0xcf, 0xfb, 0xd8, 0x16, 0x3e, 0x12, 0x0a, 0x4d, 0xe1, 0xa3, 0x2d, 0x9b, 0xaf, 0xca, 0x75, 0xe8, + 0x07, 0xb3, 0x6c, 0x74, 0x49, 0xd6, 0x10, 0x4e, 0xef, 0x13, 0x59, 0x6c, 0x3b, 0x99, 0x4d, 0xc4, 0xf5, 0x47, 0xc0, + 0x00, 0x1e, 0xeb, 0xa2, 0xf6, 0x54, 0xdd, 0x96, 0x7a, 0xd4, 0xa5, 0x9e, 0xfb, 0x9d, 0xe6, 0xed, 0xb9, 0xb8, 0xd9, + 0xa6, 0xf7, 0x05, 0x9f, 0x5a, 0x8b, 0x8e, 0x20, 0xdf, 0xd2, 0x8d, 0x72, 0x01, 0x80, 0x0c, 0xf0, 0xc2, 0xb8, 0x89, + 0x2e, 0xab, 0xfd, 0xb1, 0xf7, 0xa3, 0x35, 0xb6, 0xc7, 0x66, 0x53, 0x6e, 0x64, 0x87, 0xd9, 0xc5, 0x81, 0xb2, 0xe3, + 0xd8, 0xf8, 0x0e, 0x7b, 0x8d, 0x87, 0x17, 0x6a, 0x46, 0x0a, 0x6b, 0x89, 0xde, 0x9b, 0x3a, 0xa9, 0x67, 0x9f, 0x1b, + 0x9c, 0x15, 0xee, 0x8b, 0xb9, 0x14, 0xde, 0x27, 0x8e, 0x5a, 0x1d, 0x00, 0x98, 0x6e, 0x60, 0x82, 0x23, 0x3a, 0xfd, + 0x58, 0x12, 0xfc, 0x77, 0x1d, 0x74, 0x2b, 0x4e, 0xe0, 0xb6, 0x14, 0x77, 0xa3, 0x96, 0xcb, 0xf7, 0xb3, 0x83, 0x90, + 0x52, 0x5c, 0x75, 0x76, 0x20, 0xf2, 0x3a, 0x50, 0x11, 0x72, 0x0a, 0x09, 0x01, 0x87, 0x4b, 0xd9, 0xa5, 0x60, 0x92, + 0x04, 0xf4, 0x53, 0xe1, 0xbe, 0x50, 0xf6, 0x92, 0xdb, 0x8d, 0xda, 0xf2, 0x47, 0x32, 0x04, 0x54, 0xcd, 0xc5, 0xb4, + 0xb6, 0x45, 0x70, 0x3c, 0x75, 0xc4, 0x7c, 0x7a, 0xac, 0xbf, 0x39, 0x90, 0xf4, 0x34, 0xf0, 0xc8, 0xc0, 0xe2, 0x6d, + 0x89, 0xd1, 0xd5, 0x8e, 0x37, 0xac, 0xec, 0x1d, 0x17, 0x5b, 0xcc, 0x41, 0x3d, 0xb1, 0xc2, 0x80, 0xf7, 0x31, 0x32, + 0x35, 0xe9, 0xc1, 0x55, 0xec, 0x54, 0x58, 0x0e, 0xcb, 0xc9, 0x02, 0xc4, 0x51, 0xea, 0x97, 0x2f, 0x73, 0xde, 0xe8, + 0x6b, 0xd6, 0x12, 0xca, 0xb0, 0x94, 0x63, 0x75, 0xb9, 0x4c, 0x1e, 0x36, 0x86, 0xac, 0x38, 0x9f, 0xb6, 0x9d, 0xa5, + 0xa2, 0x09, 0x2b, 0x88, 0x76, 0x5c, 0x23, 0x84, 0x64, 0xbf, 0x90, 0x4e, 0xd6, 0xec, 0xf0, 0x0b, 0x96, 0xd5, 0x92, + 0xd2, 0xb9, 0x25, 0xd9, 0x93, 0x19, 0xf0, 0x73, 0x04, 0x19, 0x49, 0x4a, 0x4c, 0xec, 0xa4, 0x0b, 0xc1, 0x63, 0x0d, + 0xc3, 0xd3, 0xa2, 0xac, 0x97, 0xc9, 0xa2, 0xd5, 0x8d, 0x4e, 0x3d, 0x29, 0x1e, 0x18, 0x74, 0x90, 0x58, 0x52, 0x73, + 0x88, 0xc8, 0x3f, 0x99, 0xa8, 0x0b, 0x41, 0x84, 0x64, 0xd3, 0x91, 0x4c, 0x25, 0x25, 0xeb, 0x45, 0x88, 0x23, 0x1f, + 0x90, 0x2b, 0x79, 0x44, 0x96, 0xe4, 0xd5, 0x77, 0x90, 0xc9, 0x3b, 0xd1, 0x4a, 0x8a, 0xed, 0x6c, 0x08, 0x71, 0xcf, + 0xdc, 0x64, 0x0c, 0x41, 0x26, 0x3c, 0x4f, 0xc9, 0xd8, 0x1a, 0x19, 0xe9, 0x13, 0xf2, 0xe4, 0xc0, 0x42, 0xa9, 0xbd, + 0x4a, 0x0a, 0x2c, 0x4b, 0x90, 0x85, 0x76, 0xf2, 0xa7, 0x2c, 0xa9, 0xe5, 0x91, 0x03, 0xdb, 0xa7, 0xf5, 0x84, 0x82, + 0x4c, 0x11, 0x21, 0xc7, 0x3e, 0x37, 0x02, 0x18, 0xe5, 0x61, 0x05, 0x4a, 0xe7, 0x39, 0xe1, 0x45, 0x9e, 0x23, 0x4a, + 0xe4, 0xc5, 0xc0, 0x1a, 0x55, 0xbc, 0xab, 0x91, 0xfa, 0x2b, 0x08, 0xb9, 0x50, 0xe0, 0xe1, 0x5e, 0x74, 0x7a, 0x9e, + 0xdf, 0x14, 0xeb, 0x2f, 0x18, 0x6f, 0xca, 0xea, 0xa2, 0x95, 0x1b, 0x46, 0x8a, 0x66, 0xc4, 0xf9, 0x99, 0xbb, 0x78, + 0x82, 0x4f, 0x95, 0x8c, 0xa8, 0x1c, 0xc5, 0x8c, 0x0b, 0xdf, 0x87, 0xc9, 0xbf, 0x8b, 0x6e, 0x41, 0xd1, 0x7d, 0xdb, + 0xac, 0x8d, 0x44, 0x43, 0x5c, 0x95, 0x93, 0xcf, 0x7b, 0xa4, 0xa6, 0xc1, 0x50, 0x71, 0x8b, 0xe7, 0x99, 0x51, 0xef, + 0x21, 0x3e, 0x33, 0x0a, 0x6a, 0x93, 0x84, 0x2b, 0x39, 0xc1, 0xc6, 0x84, 0x97, 0x7c, 0xa9, 0x16, 0x19, 0xc5, 0xec, + 0xbe, 0x52, 0xf9, 0xe5, 0x42, 0xd1, 0x3c, 0x4d, 0x50, 0x50, 0x4a, 0x4b, 0xd5, 0x88, 0xbe, 0x1a, 0x78, 0x88, 0x9c, + 0x6e, 0x74, 0x7e, 0x1b, 0xb9, 0x70, 0x08, 0x64, 0x8b, 0x57, 0x5e, 0xf8, 0x4c, 0xc3, 0x52, 0xed, 0xd0, 0x3e, 0x83, + 0x25, 0x4e, 0x95, 0xd1, 0x11, 0xfe, 0x67, 0x22, 0x58, 0xb4, 0xb9, 0x11, 0x78, 0x4b, 0x59, 0x49, 0x1d, 0xa7, 0x7e, + 0x83, 0xf2, 0x9e, 0x8e, 0xf2, 0x5a, 0xf9, 0xca, 0x24, 0x99, 0x31, 0x57, 0xa3, 0x31, 0x28, 0xc8, 0xc7, 0x8b, 0xf9, + 0x26, 0x00, 0x93, 0xe8, 0x76, 0x62, 0x33, 0x68, 0x87, 0xc8, 0xaa, 0x3c, 0x14, 0x77, 0x9a, 0xaf, 0xa7, 0xf3, 0x46, + 0x9e, 0x43, 0xb8, 0x85, 0xda, 0x44, 0xa3, 0x6e, 0xa2, 0xab, 0x26, 0xa0, 0x4c, 0xf2, 0x73, 0xd8, 0x01, 0x5e, 0xca, + 0x9c, 0x00, 0xac, 0x47, 0x6a, 0x4c, 0x70, 0x3b, 0x10, 0x7f, 0xa9, 0x75, 0xf5, 0x9c, 0x72, 0xba, 0xad, 0x9a, 0x55, + 0x0b, 0x14, 0x7b, 0x00, 0x2a, 0xcf, 0x9f, 0xdf, 0x9e, 0x7a, 0x1b, 0xc1, 0x56, 0xec, 0x60, 0x54, 0x32, 0xe7, 0x2a, + 0xcb, 0x06, 0xa5, 0x76, 0xcb, 0xb9, 0x69, 0x20, 0xbe, 0x7b, 0x50, 0x5d, 0xbd, 0xe0, 0x8f, 0x3b, 0x6b, 0xe3, 0x1d, + 0x07, 0xa8, 0x3d, 0xf2, 0x93, 0x17, 0x9a, 0xf4, 0x01, 0xc1, 0x1b, 0x4e, 0xd7, 0x09, 0xab, 0x09, 0x63, 0x24, 0x62, + 0x86, 0x02, 0x32, 0xa5, 0xfe, 0xb9, 0x0b, 0x34, 0xe7, 0x5f, 0xbc, 0xef, 0x40, 0xc1, 0xa1, 0x68, 0xe0, 0x3a, 0xaf, + 0x1e, 0x5e, 0xfa, 0x94, 0x1d, 0xc5, 0x18, 0xf7, 0x2d, 0xd7, 0x5b, 0xac, 0xb9, 0xd6, 0x8a, 0xf3, 0xbb, 0x74, 0x3f, + 0xb4, 0x9b, 0xe2, 0xf9, 0x06, 0xdd, 0x27, 0xb7, 0x8f, 0x73, 0xe0, 0x4f, 0x54, 0xc9, 0xa4, 0x58, 0x57, 0x38, 0xf2, + 0xa8, 0x02, 0x4d, 0xbd, 0xb7, 0x6d, 0xe3, 0x0d, 0xc6, 0x1b, 0x10, 0xfd, 0x3d, 0xa8, 0xe2, 0xa6, 0x33, 0xdc, 0xb7, + 0xba, 0xe5, 0xa4, 0x09, 0x14, 0x5a, 0x45, 0x10, 0x57, 0x5c, 0xe0, 0xe7, 0xbd, 0x00, 0x39, 0xc0, 0x1e, 0x20, 0x0d, + 0xf0, 0x68, 0x45, 0x0f, 0x21, 0x63, 0x4c, 0x6c, 0x4b, 0x2d, 0x39, 0x8b, 0x1d, 0x7b, 0x38, 0x69, 0xf2, 0x26, 0x59, + 0x1b, 0xb7, 0xf4, 0xb0, 0x10, 0x6d, 0x7d, 0xc5, 0xb3, 0x7e, 0x13, 0x72, 0x12, 0x20, 0x56, 0x5b, 0x7c, 0x4a, 0xa6, + 0x1c, 0xb7, 0xfb, 0x2b, 0x89, 0x1f, 0x7d, 0x9c, 0xd8, 0x71, 0x08, 0xa4, 0xf6, 0xa9, 0x29, 0x5c, 0x6f, 0x77, 0xd1, + 0x77, 0xaf, 0x1f, 0x7f, 0x4b, 0x57, 0xd1, 0xf5, 0xa7, 0x69, 0x77, 0xdd, 0xe9, 0xed, 0x7b, 0x2d, 0xc9, 0xb2, 0xcc, + 0x7a, 0xd7, 0x9f, 0x26, 0x77, 0x8c, 0x1b, 0xaf, 0x28, 0x07, 0x1a, 0x58, 0xef, 0xdf, 0xa0, 0xb4, 0x3b, 0xb4, 0xd0, + 0x37, 0xab, 0x0f, 0xa3, 0x02, 0x9b, 0xaa, 0xc1, 0x66, 0x87, 0x93, 0x9c, 0xcc, 0x89, 0x62, 0xe8, 0x0f, 0xa2, 0x13, + 0xb0, 0x0e, 0x5f, 0xb2, 0xa5, 0xf9, 0x03, 0x1c, 0xe0, 0xfa, 0xc2, 0x07, 0x4c, 0x68, 0xa2, 0xcd, 0x06, 0x5b, 0xeb, + 0x7f, 0xf7, 0xa9, 0x77, 0x8e, 0xd1, 0x8f, 0x6b, 0xfb, 0xcd, 0x3f, 0x1d, 0x6f, 0x71, 0x8e, 0x77, 0x45, 0xd2, 0x0e, + 0xe4, 0xc8, 0x19, 0x92, 0xdc, 0xee, 0xe2, 0xb0, 0x9f, 0xd9, 0xe5, 0x69, 0xee, 0xbe, 0xfb, 0xa9, 0x98, 0x60, 0x72, + 0x27, 0x67, 0xa9, 0x02, 0xf1, 0xef, 0x06, 0x01, 0x70, 0xb7, 0xec, 0xd7, 0x51, 0xd3, 0xd6, 0x4b, 0xee, 0x3c, 0xab, + 0x5a, 0x8d, 0xf5, 0x76, 0xeb, 0x00, 0xff, 0x5d, 0xf8, 0x00, 0x69, 0xac, 0xe7, 0xbe, 0xc7, 0xba, 0x66, 0x64, 0x0d, + 0x82, 0xdd, 0xe6, 0x61, 0x54, 0x95, 0x70, 0x88, 0x41, 0x3c, 0x91, 0x07, 0x7f, 0x01, 0xa2, 0xdf, 0xed, 0xcd, 0xfe, + 0xd3, 0xe1, 0x00, 0xe8, 0xe0, 0x8f, 0x37, 0x59, 0x73, 0x88, 0x3d, 0x81, 0x75, 0x07, 0x8c, 0x73, 0xa3, 0x49, 0x74, + 0x02, 0x5c, 0xf2, 0xae, 0x3c, 0x59, 0x74, 0xf9, 0xdc, 0xc7, 0x40, 0xe8, 0x7a, 0x8f, 0x84, 0x25, 0xd0, 0x58, 0x60, + 0x0d, 0x6c, 0xfc, 0xa0, 0x58, 0xfe, 0xb5, 0xb7, 0x54, 0x3d, 0x5d, 0xb7, 0x86, 0x79, 0xad, 0xe3, 0xf2, 0x8d, 0x38, + 0xda, 0x29, 0xc4, 0xb3, 0x5e, 0xca, 0x6b, 0xa2, 0x37, 0x0d, 0x7e, 0x6e, 0x1a, 0x7b, 0xa0, 0xe0, 0x23, 0xbe, 0xb8, + 0x30, 0x6f, 0x58, 0xef, 0xf6, 0xb3, 0x03, 0x98, 0x35, 0xe2, 0x30, 0x60, 0xa7, 0x05, 0xbf, 0xe9, 0x61, 0x3c, 0x27, + 0x66, 0x2b, 0x28, 0x08, 0x31, 0x57, 0x4f, 0x5e, 0x73, 0xcd, 0x6b, 0xb3, 0x22, 0x6b, 0x89, 0xcf, 0xb8, 0x76, 0x01, + 0xa0, 0x25, 0x1a, 0x65, 0xee, 0x5b, 0x90, 0x3a, 0xe5, 0xf5, 0xb2, 0x9c, 0x09, 0x8e, 0x05, 0xad, 0x9d, 0x80, 0xa7, + 0xc3, 0xb9, 0x98, 0x37, 0x29, 0x1c, 0x7d, 0xc5, 0xa2, 0xdb, 0x57, 0x21, 0x95, 0x58, 0x28, 0x0b, 0x1f, 0x3e, 0x8b, + 0x29, 0xd9, 0xec, 0x0d, 0x10, 0x58, 0x0c, 0xde, 0x77, 0x41, 0x7b, 0xdd, 0x30, 0x64, 0xe9, 0xe0, 0x60, 0x25, 0xee, + 0xf2, 0x6e, 0x44, 0x94, 0x3f, 0x7e, 0xfc, 0xcf, 0x4a, 0x76, 0x23, 0x97, 0x61, 0x78, 0x91, 0xd8, 0x3d, 0xcb, 0x36, + 0xdf, 0xa6, 0x31, 0x6a, 0xc8, 0x69, 0xf9, 0x87, 0x3a, 0x6e, 0x69, 0x46, 0x8a, 0x33, 0x1f, 0x40, 0xbe, 0x2d, 0xbb, + 0x08, 0x01, 0x06, 0xf3, 0x96, 0x44, 0x6c, 0xd3, 0xaf, 0x47, 0x88, 0x35, 0xfb, 0x7c, 0x03, 0xc9, 0x9d, 0xd6, 0x14, + 0xda, 0x12, 0x45, 0xce, 0x05, 0x15, 0x5d, 0x32, 0xce, 0xd7, 0x15, 0x36, 0xba, 0xc7, 0x31, 0x52, 0x29, 0x63, 0xdc, + 0xe4, 0x89, 0xa6, 0xfc, 0xc6, 0x42, 0x35, 0xf8, 0xcb, 0xec, 0x89, 0xb1, 0x3c, 0x1f, 0x0f, 0x89, 0x3e, 0x12, 0xfe, + 0x3a, 0x4e, 0xcc, 0xa0, 0xee, 0xee, 0xaf, 0x74, 0x09, 0xb3, 0x65, 0xea, 0xb5, 0xc1, 0x48, 0x54, 0x6e, 0x64, 0xef, + 0x2f, 0xe2, 0x10, 0x2b, 0xf3, 0x9c, 0x2f, 0x08, 0x0f, 0xbc, 0xd7, 0x28, 0x5e, 0x90, 0x3a, 0xff, 0x91, 0xcc, 0xf1, + 0x50, 0xa2, 0xe0, 0x35, 0xcc, 0x73, 0xef, 0x1d, 0x21, 0x40, 0xdb, 0x56, 0xc0, 0xc9, 0x3c, 0x49, 0x0e, 0xed, 0x2f, + 0x01, 0x75, 0xa5, 0x1b, 0xe4, 0x41, 0xb8, 0xd8, 0x5a, 0x93, 0x10, 0xdf, 0xff, 0xc4, 0xad, 0x44, 0x42, 0x74, 0x36, + 0xec, 0x68, 0x0a, 0x80, 0x3d, 0xe4, 0x0c, 0x26, 0xac, 0x69, 0x7f, 0x3a, 0x4e, 0x98, 0x55, 0x39, 0xeb, 0x5d, 0xa8, + 0xaa, 0x58, 0x39, 0x55, 0x03, 0x25, 0x01, 0x8d, 0x66, 0xda, 0x46, 0x8e, 0x44, 0x43, 0x94, 0x17, 0x0d, 0x70, 0x74, + 0x60, 0xdb, 0x04, 0x99, 0xd4, 0xe1, 0xdb, 0x0c, 0x8a, 0x24, 0xb0, 0xff, 0x6b, 0x28, 0x84, 0xe2, 0xb6, 0xec, 0x17, + 0xb1, 0xf0, 0xda, 0x34, 0xd8, 0xd7, 0x4e, 0xf6, 0x9c, 0x73, 0x8e, 0x76, 0x41, 0x34, 0x93, 0xb0, 0x7d, 0xbc, 0x88, + 0xf9, 0xa8, 0x61, 0x9a, 0xab, 0x3c, 0x55, 0x63, 0xbf, 0x09, 0x5d, 0x76, 0x07, 0xbd, 0x26, 0x47, 0x69, 0xc9, 0xa8, + 0xfd, 0x08, 0x6c, 0xd8, 0xc1, 0xf8, 0x2b, 0x5a, 0x17, 0x39, 0x3d, 0xad, 0x36, 0xfa, 0x66, 0x11, 0x09, 0xa0, 0x09, + 0xc1, 0xea, 0xd3, 0x04, 0xde, 0xc3, 0x25, 0x7a, 0x79, 0xcf, 0xd8, 0x06, 0x52, 0x79, 0x6f, 0x82, 0xa3, 0x31, 0x50, + 0x9f, 0xe4, 0x1c, 0x68, 0x11, 0x53, 0x2d, 0x66, 0x77, 0xa9, 0x45, 0x0a, 0x77, 0xa9, 0xeb, 0xb0, 0x02, 0x6a, 0x71, + 0xfc, 0x33, 0x02, 0xf7, 0x0c, 0x82, 0x31, 0x90, 0x68, 0x56, 0x33, 0x41, 0x72, 0xfb, 0xfe, 0x80, 0x11, 0x58, 0x49, + 0xcf, 0xda, 0x53, 0xf3, 0x52, 0x24, 0xe4, 0x23, 0x98, 0x86, 0xdf, 0x33, 0x83, 0x14, 0x92, 0xbe, 0xb0, 0x0d, 0x90, + 0x24, 0x00, 0x5d, 0x56, 0x82, 0xc6, 0x99, 0x09, 0x4e, 0xe4, 0x62, 0x4d, 0xc7, 0x3d, 0x37, 0x76, 0x2c, 0x64, 0xeb, + 0xe9, 0x62, 0xa6, 0x17, 0x98, 0x25, 0xf9, 0x0b, 0x7f, 0x23, 0x33, 0x8e, 0x9a, 0xff, 0x75, 0x0d, 0xf1, 0xf0, 0xcb, + 0x24, 0x4e, 0x99, 0xf2, 0x8e, 0xb4, 0x38, 0x2e, 0x67, 0x31, 0x35, 0x88, 0xdf, 0x0b, 0x94, 0x13, 0xb8, 0x78, 0x23, + 0x52, 0x1f, 0x83, 0xdb, 0x75, 0x34, 0x00, 0xa0, 0x34, 0xd6, 0x67, 0xde, 0xbf, 0x94, 0xc7, 0x78, 0x3b, 0x36, 0xcf, + 0x0c, 0x89, 0x08, 0x2a, 0x2d, 0xee, 0xe0, 0x9a, 0x76, 0x1d, 0xfc, 0x8b, 0x72, 0x9a, 0x2b, 0x77, 0x5e, 0x50, 0xce, + 0x7c, 0x8f, 0x94, 0x20, 0xb3, 0x97, 0xed, 0x5e, 0xb6, 0x02, 0x1d, 0x84, 0xd6, 0x16, 0x56, 0x1e, 0xd3, 0x16, 0x7f, + 0x3e, 0x8d, 0xd5, 0x26, 0xf0, 0x9b, 0x21, 0x55, 0x5d, 0x3d, 0x37, 0x68, 0xd4, 0x3f, 0x22, 0x8b, 0xde, 0x26, 0x84, + 0xdd, 0x1a, 0x9f, 0xcf, 0x0a, 0x40, 0x0b, 0xc4, 0x5e, 0xfd, 0x6f, 0x09, 0x16, 0xfa, 0x1a, 0x3f, 0x8f, 0x75, 0x75, + 0x71, 0xf9, 0x24, 0x19, 0x59, 0xf1, 0x43, 0x2f, 0x93, 0x6a, 0x59, 0x58, 0x2a, 0xa6, 0x01, 0xc8, 0x86, 0xdf, 0xef, + 0xaa, 0x67, 0xd9, 0x4f, 0xa7, 0x36, 0x5f, 0xf4, 0x74, 0x15, 0x3f, 0x07, 0x19, 0x96, 0x3c, 0x65, 0xf0, 0xdf, 0xe2, + 0xd6, 0xe0, 0x14, 0xfd, 0xdb, 0xe0, 0x87, 0x89, 0xed, 0xb3, 0x12, 0x24, 0x54, 0x84, 0xe7, 0x36, 0xea, 0xbb, 0x04, + 0xa4, 0x88, 0xee, 0x50, 0xe6, 0x55, 0x8d, 0x1d, 0x25, 0x1b, 0x6a, 0xfb, 0x19, 0x12, 0x6a, 0xe2, 0xa8, 0x86, 0x5f, + 0xdc, 0x38, 0xfc, 0x42, 0xc8, 0x21, 0xce, 0xd1, 0x93, 0x43, 0xc7, 0x26, 0xf3, 0x9b, 0xe1, 0xb2, 0x79, 0x1c, 0x2e, + 0xb7, 0xb0, 0xef, 0x23, 0x93, 0x9e, 0x2b, 0x1a, 0xcf, 0xf1, 0xec, 0xd1, 0xa2, 0x58, 0xce, 0xea, 0xde, 0x4a, 0x20, + 0x46, 0x36, 0x51, 0x5f, 0xcb, 0x0b, 0x5e, 0x9e, 0xcd, 0xac, 0x7e, 0x49, 0xe2, 0xdd, 0xd1, 0x5f, 0xdf, 0x0e, 0xd7, + 0x81, 0x1f, 0x69, 0xb8, 0x61, 0x5b, 0xc6, 0x93, 0x2d, 0xcc, 0x0e, 0x23, 0xd7, 0xc5, 0xea, 0x32, 0xcb, 0x90, 0xb7, + 0x50, 0xfc, 0xec, 0x0f, 0xa3, 0x5c, 0x32, 0x35, 0x06, 0x3f, 0xba, 0xdc, 0x8f, 0x69, 0x38, 0x95, 0x18, 0xa2, 0x95, + 0x9c, 0x74, 0x8f, 0xb5, 0x1d, 0x2b, 0x20, 0xcb, 0xde, 0x3f, 0x1a, 0x9d, 0xbb, 0x98, 0x97, 0x12, 0x75, 0x1c, 0x34, + 0xcf, 0x53, 0x1e, 0x94, 0xdb, 0x85, 0xb6, 0xd9, 0x3b, 0xe2, 0xd3, 0xd6, 0xc6, 0x05, 0xd0, 0x6e, 0x0d, 0x5d, 0x68, + 0x5d, 0xb0, 0x80, 0x84, 0xbe, 0x4b, 0xed, 0x16, 0x58, 0x49, 0xd6, 0x32, 0x86, 0x2e, 0x39, 0xbb, 0x4e, 0x5c, 0x43, + 0x95, 0xc3, 0x86, 0x4b, 0x96, 0x93, 0x2c, 0x11, 0x93, 0xed, 0xff, 0xcb, 0x1b, 0x94, 0x30, 0xd2, 0xcb, 0x12, 0x3a, + 0xde, 0x14, 0xbe, 0xb0, 0xc8, 0x02, 0x1e, 0xb7, 0xc8, 0xe8, 0x79, 0xf9, 0x90, 0x44, 0xc1, 0xa1, 0xb8, 0xe0, 0x7e, + 0xf8, 0xf2, 0x5d, 0x1d, 0xf7, 0xd6, 0xec, 0x63, 0xca, 0x91, 0xbf, 0xaa, 0x0a, 0x44, 0x5b, 0x97, 0x45, 0x4c, 0xfe, + 0x4f, 0x24, 0x67, 0x45, 0xd6, 0xa2, 0xa3, 0x03, 0x68, 0x6e, 0xe7, 0x4c, 0xb6, 0x84, 0xa5, 0x90, 0xcc, 0x43, 0x97, + 0x66, 0x0e, 0x16, 0x80, 0xae, 0x68, 0x81, 0x5d, 0x3c, 0x66, 0xcc, 0xbd, 0xcb, 0x92, 0xd3, 0xda, 0x65, 0x1e, 0x2d, + 0xa0, 0xb9, 0x70, 0x4b, 0xa2, 0x09, 0x44, 0x37, 0x52, 0x82, 0x35, 0xb6, 0x9d, 0xdb, 0x73, 0xff, 0x3e, 0x8e, 0xa8, + 0x2f, 0x0f, 0x38, 0x27, 0xc4, 0xe1, 0xdb, 0x51, 0x6e, 0x9a, 0x7e, 0xe0, 0x65, 0xab, 0x33, 0x07, 0x13, 0x17, 0xf3, + 0xeb, 0x01, 0x3c, 0x49, 0xbb, 0xce, 0xa6, 0xe8, 0xf6, 0x69, 0xed, 0xf1, 0x97, 0x84, 0x2e, 0x29, 0x96, 0x35, 0x64, + 0x32, 0x7d, 0x24, 0x61, 0xce, 0xf7, 0x3a, 0xef, 0xc3, 0x40, 0x73, 0x13, 0x70, 0x37, 0x29, 0x14, 0xbd, 0xb9, 0xcf, + 0x27, 0x1c, 0x07, 0x64, 0xb5, 0x37, 0x8a, 0xe9, 0xd1, 0x03, 0xdd, 0xe4, 0x02, 0x87, 0xe7, 0x23, 0x08, 0x91, 0x30, + 0x2b, 0xb8, 0xd5, 0xb5, 0xea, 0x1a, 0xe8, 0xa7, 0xf0, 0x63, 0x9d, 0x09, 0x0c, 0x4b, 0xf6, 0x72, 0x74, 0xae, 0xcb, + 0x50, 0x72, 0x47, 0x5c, 0xe6, 0x50, 0xf0, 0xee, 0x29, 0xf2, 0xe4, 0xfc, 0xf1, 0xdf, 0x33, 0x01, 0x43, 0xcd, 0x22, + 0x27, 0x7f, 0xcf, 0xb4, 0xf3, 0x53, 0xc0, 0x89, 0xa9, 0x30, 0xb5, 0xd8, 0xaa, 0xbc, 0x01, 0x9a, 0x53, 0x12, 0x14, + 0x1c, 0x56, 0xd1, 0xf9, 0x1d, 0x85, 0xc5, 0x25, 0xfe, 0xb0, 0x90, 0x19, 0x34, 0xb2, 0xe9, 0x75, 0x50, 0xa9, 0x74, + 0xfb, 0x04, 0xb1, 0x87, 0xaa, 0x7d, 0x6f, 0xcf, 0xd6, 0x84, 0x99, 0x1d, 0x8a, 0x02, 0xea, 0x46, 0xf1, 0xa6, 0x1f, + 0x5a, 0x6f, 0x81, 0x97, 0x05, 0xb0, 0x92, 0x4c, 0x3f, 0x1b, 0x20, 0x25, 0xe1, 0xc7, 0xca, 0x19, 0xdc, 0x70, 0x58, + 0xb9, 0x80, 0x5b, 0xbe, 0x5c, 0x3e, 0x20, 0xbb, 0xa6, 0x3b, 0x22, 0x02, 0x5d, 0x3f, 0x59, 0xb2, 0x6b, 0xc5, 0x94, + 0xc1, 0xe8, 0x46, 0x71, 0x17, 0xfa, 0x34, 0xca, 0x2e, 0x57, 0x56, 0xa0, 0xc6, 0x58, 0x9f, 0xa2, 0x26, 0xbf, 0x1f, + 0x2f, 0x9b, 0xca, 0xf5, 0x0f, 0x2e, 0x27, 0x72, 0x92, 0x8c, 0x32, 0x74, 0x67, 0xd2, 0xe7, 0x6c, 0x8e, 0x9a, 0x05, + 0xfc, 0x9f, 0x56, 0xab, 0x9e, 0x7b, 0xb8, 0x7d, 0x98, 0xf4, 0x42, 0x04, 0x03, 0xbd, 0xc2, 0xb2, 0xe9, 0x76, 0x23, + 0xdb, 0x56, 0xf8, 0xb6, 0x48, 0x81, 0xf8, 0x04, 0x68, 0x7e, 0x8d, 0x44, 0x80, 0x33, 0xf3, 0xcb, 0xbe, 0x04, 0x50, + 0x63, 0xe5, 0xe2, 0xf8, 0x83, 0x0a, 0x82, 0xe7, 0xb3, 0x9e, 0x7b, 0x01, 0x8b, 0x0b, 0x84, 0xcc, 0xbd, 0x27, 0x0a, + 0x6c, 0x6b, 0xe2, 0x4c, 0xfc, 0x66, 0x90, 0xeb, 0xf8, 0x6b, 0x35, 0xbd, 0xb5, 0x61, 0xa1, 0xb3, 0x92, 0xc2, 0xf2, + 0xa0, 0x47, 0xbb, 0x87, 0x88, 0x91, 0xae, 0xcf, 0x37, 0xe9, 0x37, 0x44, 0x23, 0xfa, 0x2d, 0x2a, 0x9e, 0x7e, 0x30, + 0x20, 0x90, 0x2c, 0x0b, 0xb7, 0xb7, 0xe9, 0x51, 0x51, 0x10, 0xd4, 0x7b, 0x18, 0xfc, 0x57, 0x23, 0xea, 0x4d, 0x1f, + 0x42, 0x80, 0xbf, 0x6a, 0x83, 0x7e, 0xea, 0x9f, 0x2c, 0x72, 0xd7, 0x0c, 0xd8, 0xb5, 0x87, 0xb0, 0xec, 0x0c, 0x1f, + 0x98, 0x41, 0x93, 0x62, 0xb2, 0x87, 0x70, 0x69, 0x4e, 0x13, 0x30, 0xa8, 0x77, 0x13, 0xcb, 0x9f, 0xb8, 0xa7, 0x9c, + 0x88, 0x3e, 0xe4, 0x77, 0x53, 0x8a, 0x00, 0xa7, 0xf9, 0xd2, 0x1c, 0xc1, 0x15, 0x81, 0x53, 0x5c, 0x60, 0xb6, 0x30, + 0x7f, 0xf2, 0xf5, 0x4d, 0x29, 0x60, 0x84, 0xcf, 0x17, 0x28, 0x03, 0x72, 0x46, 0x64, 0xe6, 0x90, 0xd1, 0xac, 0xea, + 0x08, 0xa1, 0x03, 0x72, 0x50, 0xa8, 0xdf, 0x8b, 0x59, 0x30, 0x62, 0xd8, 0x2f, 0x75, 0x22, 0xc9, 0x87, 0xc0, 0x88, + 0xd8, 0x42, 0xf3, 0xd6, 0xe4, 0x0e, 0x12, 0x44, 0x0f, 0x72, 0xa6, 0x51, 0x41, 0x79, 0x57, 0xc9, 0xcb, 0x29, 0x52, + 0x13, 0x0f, 0x7b, 0x13, 0x94, 0x53, 0x2d, 0x6f, 0x56, 0xd0, 0x7b, 0x70, 0xca, 0xe7, 0xfd, 0x93, 0xbc, 0x33, 0x60, + 0x81, 0x38, 0xaa, 0xec, 0x38, 0xb1, 0x5a, 0xe5, 0x6a, 0x1b, 0x47, 0x4e, 0x55, 0xc1, 0x95, 0x68, 0xa5, 0xbd, 0x9b, + 0xe7, 0x3f, 0x95, 0x17, 0x9b, 0x22, 0x6b, 0x62, 0xf2, 0x83, 0xe0, 0xc2, 0x23, 0xaf, 0xe0, 0xa3, 0x51, 0x87, 0xc3, + 0xaf, 0x95, 0x16, 0x82, 0x58, 0x20, 0x0c, 0x97, 0x6f, 0x7b, 0x85, 0xfd, 0x0a, 0x57, 0xe4, 0xb8, 0x84, 0xd6, 0x85, + 0xae, 0x1e, 0x7f, 0x49, 0x16, 0x13, 0xe4, 0xc8, 0x9c, 0xfd, 0xca, 0x8d, 0x18, 0xc1, 0x2c, 0x78, 0x49, 0x8f, 0x76, + 0x3c, 0xa6, 0x15, 0x41, 0x82, 0x10, 0x8a, 0xcc, 0xf3, 0x63, 0xe8, 0x26, 0xb1, 0x99, 0x50, 0xa4, 0x4d, 0x16, 0x83, + 0x06, 0x9c, 0x71, 0xb5, 0x21, 0x8a, 0x35, 0xc7, 0xa7, 0x7c, 0xdf, 0x43, 0x5c, 0x44, 0xde, 0xf5, 0xe8, 0x66, 0x38, + 0x80, 0x36, 0xdc, 0xac, 0x54, 0xf4, 0xa7, 0x88, 0x74, 0xf5, 0xd7, 0xca, 0xfb, 0xd0, 0x77, 0x88, 0x93, 0x79, 0x5c, + 0x2d, 0xbf, 0x82, 0x43, 0xa9, 0xe4, 0x13, 0xb8, 0xc2, 0x4f, 0x71, 0x08, 0x0b, 0x51, 0x91, 0x5e, 0x59, 0x88, 0x50, + 0xde, 0x0a, 0xf2, 0x56, 0x91, 0x4f, 0x4a, 0x1f, 0x34, 0xb1, 0x7d, 0xcb, 0x6e, 0xb6, 0xaf, 0x4a, 0xb8, 0x7d, 0x9f, + 0x9e, 0x8c, 0x05, 0xe7, 0x80, 0x46, 0x8f, 0x61, 0xd1, 0x64, 0xd0, 0x62, 0xac, 0xd2, 0xc0, 0x5d, 0x91, 0xc5, 0xa7, + 0xfe, 0xc0, 0x92, 0xf4, 0xc5, 0x67, 0x1a, 0x68, 0x1e, 0xa9, 0xff, 0x26, 0x14, 0xc6, 0xb1, 0xfc, 0xa3, 0x2f, 0x9f, + 0x89, 0x44, 0xd5, 0xd5, 0x1d, 0xc5, 0x1a, 0xc5, 0x3c, 0x1b, 0x98, 0x75, 0xba, 0xa3, 0x81, 0x55, 0x47, 0xf1, 0x4a, + 0xcd, 0x6d, 0x4c, 0x39, 0x14, 0x50, 0x57, 0xbd, 0xdd, 0x40, 0x54, 0xfa, 0x6a, 0x35, 0x5f, 0x11, 0x4e, 0x0b, 0x67, + 0x64, 0x12, 0xe7, 0xd6, 0xa8, 0x42, 0x1b, 0x9c, 0x59, 0xbd, 0xa7, 0xfd, 0x7a, 0xa5, 0x3a, 0xd6, 0xfa, 0x3b, 0xec, + 0x17, 0x37, 0x0e, 0xc8, 0xcf, 0x0f, 0x04, 0xce, 0x30, 0x80, 0x62, 0x0b, 0x8c, 0x43, 0xa1, 0x9c, 0x4d, 0x1c, 0x79, + 0x79, 0x89, 0x72, 0x82, 0xe2, 0x4e, 0x9f, 0x06, 0x07, 0x25, 0x70, 0x82, 0x95, 0x86, 0x8c, 0x85, 0xb0, 0x1c, 0x68, + 0xb9, 0x0b, 0xc5, 0x5d, 0x59, 0xa2, 0xad, 0x25, 0x36, 0x9d, 0x5b, 0x3c, 0x35, 0x50, 0x67, 0xba, 0x05, 0x81, 0x55, + 0x94, 0x88, 0xad, 0x55, 0xe4, 0xd2, 0x6f, 0x7d, 0x69, 0x30, 0x8c, 0xa3, 0x7b, 0x5f, 0xeb, 0x69, 0x37, 0x95, 0x38, + 0xf6, 0xe0, 0x2d, 0xf3, 0xfc, 0x9c, 0xe8, 0xc5, 0x54, 0x23, 0x3b, 0x13, 0x6f, 0x11, 0x0b, 0x46, 0x83, 0x92, 0xb6, + 0xad, 0x5a, 0xda, 0xc2, 0xd6, 0x01, 0xf4, 0x6f, 0x41, 0x1d, 0xff, 0x6f, 0xb8, 0x41, 0xd9, 0x41, 0xe8, 0x14, 0xaa, + 0xd5, 0xfa, 0x3c, 0xcb, 0xc6, 0xc6, 0x7a, 0xc7, 0x1c, 0x09, 0x44, 0x04, 0x2f, 0x61, 0x94, 0xc2, 0xcc, 0x1c, 0x2f, + 0xb1, 0xa5, 0x4a, 0x6d, 0xa7, 0x63, 0xf3, 0xe1, 0x6c, 0xac, 0x3a, 0x90, 0x43, 0x4d, 0x74, 0xde, 0xb4, 0x11, 0x0d, + 0x55, 0x4a, 0x94, 0x17, 0xc9, 0xac, 0x46, 0x5a, 0xf3, 0xe1, 0x25, 0xb0, 0x45, 0xc4, 0xec, 0xc0, 0xa6, 0x20, 0x06, + 0x2b, 0x66, 0xc8, 0xa9, 0x1a, 0x27, 0xbd, 0x45, 0x2f, 0x97, 0x59, 0x63, 0xeb, 0xd1, 0xa6, 0xe3, 0x98, 0x9f, 0x6e, + 0x3d, 0x16, 0x0f, 0x84, 0xb7, 0xe7, 0x7f, 0x2a, 0x94, 0xb2, 0x1f, 0xc7, 0xce, 0xda, 0xef, 0xcd, 0x71, 0x21, 0x16, + 0xcd, 0xf3, 0x83, 0xc8, 0x0d, 0xbf, 0x54, 0x08, 0x5f, 0x04, 0xc0, 0x8b, 0x6d, 0xf0, 0xaa, 0x21, 0xa8, 0x7d, 0x7f, + 0x45, 0x41, 0x8e, 0x3b, 0xf5, 0xde, 0x83, 0xd0, 0xb2, 0x2e, 0xf6, 0xf2, 0x8c, 0xd5, 0x25, 0x1d, 0x5a, 0x63, 0x88, + 0x44, 0x4f, 0x44, 0xb1, 0xf6, 0x1f, 0x37, 0xaf, 0xb2, 0xa0, 0x3e, 0x12, 0x2e, 0x71, 0xd1, 0x43, 0xf1, 0xf1, 0x57, + 0x49, 0x33, 0x37, 0x6d, 0x54, 0xa6, 0x67, 0xae, 0x9c, 0xfc, 0x0b, 0x1c, 0x5b, 0x56, 0x57, 0x28, 0x0f, 0xd7, 0x0d, + 0x4c, 0xf8, 0x7b, 0x73, 0xe3, 0xd7, 0xb8, 0xb2, 0xc6, 0xa5, 0x8b, 0xf1, 0x4e, 0xe9, 0x62, 0xc5, 0xdb, 0xc6, 0x15, + 0x4b, 0x45, 0xc6, 0x1c, 0x34, 0xb5, 0xfa, 0x67, 0x06, 0xb9, 0xfd, 0x59, 0x98, 0xfe, 0x2d, 0x85, 0x0e, 0x12, 0x0f, + 0xb3, 0xbb, 0x10, 0x1f, 0xaf, 0x0b, 0xb9, 0x9a, 0xe0, 0x92, 0x84, 0xa4, 0x24, 0x3f, 0x86, 0x6d, 0xdf, 0x71, 0xf2, + 0x9c, 0x29, 0x1c, 0x8d, 0xb8, 0x5d, 0x26, 0xf9, 0x95, 0xf0, 0x3f, 0x95, 0x8d, 0xeb, 0x4e, 0x9b, 0x35, 0x07, 0x0a, + 0xf0, 0x79, 0x97, 0x85, 0x09, 0xd1, 0xd1, 0xda, 0x46, 0xed, 0x45, 0xb8, 0xf1, 0x2b, 0x45, 0x82, 0xfe, 0x25, 0xa3, + 0x50, 0xd8, 0xbc, 0x47, 0x2e, 0xb0, 0x4d, 0xc1, 0xd3, 0x6f, 0xc1, 0xb5, 0x4a, 0x19, 0x30, 0xf1, 0x2b, 0xd8, 0x26, + 0x9f, 0x98, 0xb9, 0x9b, 0xf4, 0x82, 0xa8, 0x2f, 0xab, 0x68, 0x82, 0xeb, 0xca, 0x85, 0xd5, 0x95, 0xf1, 0x3d, 0x75, + 0x7d, 0x04, 0xb9, 0x78, 0x7c, 0x9a, 0xe7, 0x77, 0xa9, 0x69, 0x03, 0xf6, 0x5e, 0x8c, 0x63, 0xfc, 0x75, 0xc5, 0x3c, + 0xb3, 0x7a, 0x52, 0x55, 0xa6, 0x80, 0xf7, 0xf4, 0xe3, 0x2b, 0xee, 0xf1, 0x9b, 0x87, 0x6d, 0xb0, 0xf4, 0x3f, 0xfa, + 0x99, 0x27, 0xa0, 0x2c, 0xd1, 0x8e, 0x2b, 0x8d, 0xdd, 0x32, 0xc6, 0x96, 0x0a, 0xc2, 0x05, 0x2c, 0x48, 0x45, 0x8d, + 0x5d, 0x1e, 0x6a, 0xd9, 0x7c, 0xdb, 0x1c, 0x9a, 0x90, 0x66, 0xfd, 0x71, 0xd6, 0x73, 0x33, 0x30, 0xaa, 0x68, 0xc3, + 0x03, 0x66, 0x85, 0x36, 0x24, 0xe0, 0x60, 0xa1, 0xc1, 0xa4, 0x08, 0x02, 0xe9, 0x6e, 0xd0, 0xe3, 0x82, 0x3e, 0x51, + 0x08, 0x6c, 0xbc, 0x8b, 0x16, 0x24, 0xd0, 0xfe, 0x9f, 0x02, 0x7d, 0x12, 0x1b, 0xfa, 0x7b, 0xcc, 0xc6, 0xb1, 0xe1, + 0x58, 0xca, 0xe8, 0xde, 0x23, 0x95, 0xc0, 0x49, 0xea, 0x1e, 0xe9, 0xfc, 0x54, 0x1e, 0xa9, 0xed, 0xdc, 0x92, 0xbf, + 0x44, 0x3f, 0x8e, 0xc6, 0xd8, 0xf9, 0xed, 0xe7, 0xa8, 0x26, 0xa6, 0xf3, 0x16, 0xb6, 0xb8, 0xf6, 0xc8, 0x32, 0x3f, + 0xab, 0x33, 0xd0, 0x81, 0x84, 0x93, 0x58, 0x29, 0xbb, 0x54, 0x2e, 0xf9, 0x7f, 0xc8, 0xd3, 0x26, 0x97, 0xd6, 0x08, + 0xe2, 0x4b, 0x56, 0x7d, 0x47, 0x10, 0x19, 0x53, 0xcd, 0xaa, 0x8a, 0xde, 0x23, 0x29, 0x62, 0xa5, 0xda, 0x55, 0x8d, + 0xd7, 0x6c, 0x33, 0x3b, 0x1b, 0x9d, 0x7b, 0xa1, 0x7e, 0x2f, 0x2c, 0x45, 0x57, 0xb4, 0xdf, 0xc5, 0x36, 0x52, 0x65, + 0x13, 0x11, 0x66, 0x70, 0x87, 0xa3, 0x11, 0x62, 0x4b, 0xa9, 0xa4, 0xcf, 0x76, 0x41, 0xba, 0xe7, 0x65, 0xaa, 0x26, + 0x5c, 0x8e, 0x84, 0x45, 0x6c, 0xa9, 0x8d, 0x57, 0xb2, 0xd3, 0x83, 0x27, 0xb7, 0xb8, 0x1d, 0xcb, 0xdd, 0x80, 0xe0, + 0x34, 0x64, 0xe9, 0x89, 0x63, 0x65, 0x22, 0xdd, 0xc9, 0xae, 0x73, 0x4d, 0x91, 0x62, 0xf7, 0x99, 0x74, 0xfb, 0xa1, + 0x94, 0x7e, 0xaa, 0x34, 0xe6, 0xc0, 0x35, 0x8e, 0xc0, 0x45, 0xc3, 0x88, 0x3e, 0x5e, 0x93, 0xf9, 0xd4, 0x07, 0xe9, + 0x49, 0x2d, 0x00, 0xc7, 0x41, 0xe9, 0x2c, 0x71, 0xb9, 0xc4, 0x0e, 0xfc, 0x24, 0xec, 0xac, 0x7a, 0x76, 0x1e, 0x0b, + 0xf9, 0x4c, 0xb5, 0xd9, 0x3a, 0x48, 0xe4, 0x9b, 0x9a, 0x87, 0x62, 0xd5, 0x0e, 0x0b, 0x0f, 0x7c, 0xbc, 0xc3, 0xe7, + 0xc7, 0xbb, 0xab, 0x6c, 0xc5, 0xcb, 0xc6, 0x39, 0x0d, 0x16, 0x97, 0x38, 0xd1, 0xf2, 0xcb, 0x65, 0x65, 0x83, 0x85, + 0x27, 0xf1, 0xe8, 0x7f, 0x53, 0x65, 0xfc, 0x4a, 0x86, 0x62, 0x39, 0x68, 0xbd, 0x2a, 0xab, 0xa4, 0xb8, 0x75, 0x7b, + 0x64, 0x91, 0x44, 0xf4, 0x30, 0x29, 0x97, 0x3a, 0xad, 0x6a, 0xa5, 0xc3, 0xdf, 0x4f, 0xe8, 0x8e, 0xb2, 0x0a, 0x00, + 0x53, 0x09, 0xfd, 0x83, 0x15, 0xdf, 0x65, 0xd4, 0xe8, 0xb0, 0x17, 0x2c, 0x96, 0x7d, 0x8e, 0xe2, 0x5f, 0xdb, 0xf3, + 0x30, 0x2c, 0x4b, 0xd2, 0x5d, 0xbd, 0x85, 0xd8, 0x0b, 0xfe, 0xf0, 0xc0, 0x69, 0x14, 0xa9, 0xc5, 0x8b, 0xab, 0xd0, + 0x24, 0xde, 0x21, 0x1d, 0x3f, 0x6d, 0x2d, 0xff, 0x26, 0xac, 0x24, 0xf6, 0x79, 0x5c, 0xcd, 0xb5, 0x6a, 0xd7, 0x52, + 0xb4, 0x38, 0x94, 0xd6, 0x48, 0x2f, 0x43, 0x7d, 0x0d, 0xf1, 0x26, 0xb7, 0xb6, 0xc4, 0x23, 0xee, 0x5e, 0x4a, 0xcf, + 0xb8, 0x68, 0x17, 0x72, 0xbe, 0xdf, 0x4a, 0x4a, 0x28, 0xee, 0xe4, 0xb1, 0x51, 0x3c, 0xb1, 0x9f, 0x5d, 0x92, 0x7c, + 0x20, 0x48, 0x71, 0xb1, 0xd2, 0xe9, 0x77, 0xce, 0x0e, 0xcf, 0x4a, 0x1d, 0x96, 0x68, 0x75, 0x6a, 0x3b, 0xb0, 0x12, + 0xef, 0xd9, 0xd7, 0x78, 0x13, 0xab, 0x04, 0xf4, 0xce, 0x85, 0x46, 0x5c, 0xba, 0x19, 0x11, 0xba, 0x48, 0xa7, 0x09, + 0x84, 0xbf, 0xdc, 0xfa, 0x25, 0xf1, 0xec, 0x7e, 0x2e, 0x07, 0x12, 0x35, 0xd4, 0x81, 0x43, 0x28, 0x2c, 0x5f, 0x44, + 0x33, 0x63, 0x2a, 0xd1, 0x1b, 0xb6, 0xab, 0x59, 0xea, 0x0e, 0x5f, 0x98, 0x4d, 0x4f, 0x7e, 0x95, 0xa3, 0x0d, 0x71, + 0x78, 0x26, 0xec, 0x8f, 0xdd, 0xe3, 0xff, 0x4a, 0x93, 0xe5, 0x45, 0xd3, 0xd1, 0x11, 0xc8, 0x16, 0x2d, 0x6b, 0x7c, + 0x63, 0x73, 0x0d, 0x5a, 0xc1, 0xce, 0xbc, 0x12, 0x28, 0x19, 0xda, 0xd2, 0x1d, 0x7d, 0x4f, 0x5e, 0x93, 0x00, 0xc6, + 0x32, 0xb5, 0x6e, 0x67, 0xbb, 0xf2, 0x2c, 0x18, 0x45, 0xb9, 0xe5, 0xc0, 0x1a, 0xb8, 0x6e, 0x0c, 0x8d, 0x9d, 0x31, + 0xba, 0xe6, 0xff, 0xac, 0x14, 0xd3, 0x15, 0x73, 0x90, 0x04, 0x5b, 0x5e, 0x1e, 0x06, 0xa9, 0xd9, 0xa7, 0x96, 0xae, + 0x33, 0xb5, 0x44, 0x50, 0x98, 0x15, 0x4f, 0x4d, 0x1a, 0xfa, 0x05, 0xec, 0xdf, 0xde, 0x98, 0x0e, 0x82, 0x7c, 0x2b, + 0x99, 0xc6, 0x68, 0x50, 0x39, 0x2f, 0xd4, 0x43, 0x6f, 0xbe, 0x70, 0x20, 0xbb, 0x5d, 0x59, 0x64, 0x54, 0x3b, 0xd4, + 0x0b, 0xb3, 0xe9, 0x9d, 0x81, 0x19, 0x89, 0x08, 0xb0, 0x11, 0x1f, 0xf5, 0x57, 0x84, 0x62, 0x89, 0x89, 0xb4, 0xf2, + 0x46, 0x9f, 0xdf, 0xe7, 0xc2, 0x42, 0xe7, 0x09, 0x36, 0xbd, 0x59, 0x34, 0xa3, 0x91, 0x00, 0x23, 0xe8, 0x8b, 0x9c, + 0xe5, 0x9c, 0xd5, 0x20, 0xb4, 0x3a, 0xa5, 0xe1, 0x16, 0x9c, 0x1e, 0x77, 0xad, 0x09, 0x94, 0xdb, 0x5f, 0x3a, 0x7b, + 0xab, 0xd7, 0xc2, 0xf6, 0xd6, 0x23, 0xd5, 0x8b, 0x3a, 0x1f, 0x7f, 0x70, 0x65, 0xe6, 0xf2, 0xef, 0x6d, 0x66, 0x22, + 0xa9, 0xfc, 0xf9, 0x0a, 0x89, 0xa0, 0xf2, 0xf0, 0x56, 0x1b, 0xc1, 0x85, 0xec, 0xe8, 0x19, 0xb3, 0x75, 0xd2, 0x0a, + 0xb6, 0x7f, 0x53, 0xfc, 0x40, 0x64, 0xf8, 0x17, 0x33, 0x70, 0xc4, 0x59, 0xc8, 0xb2, 0xa3, 0x40, 0x2b, 0xca, 0x03, + 0x35, 0x4e, 0xbc, 0x98, 0x8f, 0xe5, 0xba, 0x7c, 0x7b, 0x73, 0xa2, 0x82, 0xac, 0xb1, 0x08, 0x1e, 0xd6, 0xcb, 0x37, + 0x29, 0x93, 0x65, 0xc7, 0xa7, 0x37, 0x3d, 0x6e, 0xcf, 0x8d, 0x08, 0x48, 0x8b, 0x67, 0xc8, 0xe7, 0x4a, 0x24, 0x66, + 0x37, 0x1a, 0x2f, 0x39, 0x62, 0x31, 0x96, 0x12, 0x51, 0x2a, 0x74, 0x5c, 0x0b, 0x87, 0x28, 0xc4, 0x2a, 0x8c, 0x24, + 0xa8, 0xfc, 0x72, 0x61, 0x69, 0x16, 0x61, 0x62, 0x1f, 0x8b, 0x2b, 0x39, 0x4c, 0xb1, 0x87, 0x36, 0xd3, 0x7e, 0x52, + 0xd7, 0xf8, 0x8f, 0x51, 0xd7, 0xd7, 0x13, 0xea, 0x15, 0x43, 0x7b, 0x0d, 0xa5, 0xa9, 0x4e, 0x26, 0x56, 0x2c, 0x78, + 0xa4, 0x46, 0xe3, 0x3e, 0x34, 0x02, 0x84, 0xe2, 0xf6, 0x71, 0xd0, 0xb1, 0xad, 0x58, 0x62, 0xc4, 0x69, 0x51, 0x32, + 0xb3, 0xb4, 0xe9, 0xd8, 0xad, 0xa4, 0x43, 0x5a, 0x5e, 0xea, 0xf0, 0xfc, 0xc6, 0xbe, 0xee, 0x0a, 0x23, 0x8d, 0x79, + 0x37, 0x70, 0xbb, 0xdc, 0x74, 0x45, 0x45, 0xd1, 0x66, 0x64, 0x43, 0x5d, 0x0f, 0x88, 0x42, 0x88, 0x0d, 0x73, 0x6b, + 0x28, 0x4e, 0x46, 0x3b, 0xda, 0x61, 0x81, 0x79, 0x6c, 0x60, 0x1c, 0x83, 0x59, 0x47, 0xb5, 0xb1, 0x13, 0x59, 0xd6, + 0xbf, 0xe7, 0xb5, 0x8d, 0xf8, 0x7c, 0xb9, 0x26, 0x40, 0x40, 0xe3, 0x41, 0x2f, 0x7b, 0x45, 0xe4, 0xa0, 0x97, 0x21, + 0x97, 0xd8, 0x38, 0x21, 0x43, 0x63, 0xe3, 0xfb, 0x83, 0xd9, 0x93, 0x99, 0xe3, 0xe7, 0x33, 0x83, 0xb1, 0x8f, 0xd5, + 0xfc, 0xc8, 0x82, 0x43, 0x99, 0x34, 0x5d, 0x3f, 0x72, 0x44, 0xef, 0x99, 0x56, 0xdc, 0x77, 0x38, 0x58, 0x26, 0x65, + 0x96, 0x4c, 0xba, 0x19, 0x40, 0x65, 0xb0, 0x92, 0x77, 0x3b, 0x3f, 0x5c, 0x69, 0x88, 0x7e, 0x68, 0x2e, 0x16, 0x53, + 0xd9, 0x0e, 0xce, 0x53, 0x43, 0xa4, 0x2c, 0x0d, 0x6f, 0x8e, 0x06, 0x21, 0xc4, 0xf5, 0x69, 0xbe, 0xfe, 0x75, 0x54, + 0x3b, 0x9b, 0x4d, 0x4d, 0x91, 0x34, 0x15, 0x4c, 0xcf, 0x58, 0x29, 0x0d, 0x8e, 0x41, 0x80, 0x01, 0x27, 0x0b, 0x39, + 0x6f, 0x7b, 0xe4, 0xfc, 0xd3, 0x20, 0xd6, 0x03, 0x5a, 0xeb, 0x5e, 0x64, 0x44, 0x62, 0x1f, 0xda, 0x8a, 0x4b, 0x54, + 0x9d, 0xca, 0x06, 0xa0, 0xa2, 0xfe, 0xda, 0xeb, 0xd1, 0x0a, 0xfe, 0x9e, 0x83, 0xae, 0x7a, 0x8d, 0x2f, 0xda, 0x7b, + 0xa2, 0xdf, 0x34, 0xf5, 0x7f, 0xa2, 0x0c, 0xc2, 0xf6, 0x32, 0xa1, 0x03, 0x6f, 0x20, 0x0b, 0x08, 0xf8, 0x9d, 0x1e, + 0xf4, 0x05, 0xe0, 0x91, 0x18, 0x72, 0x40, 0x8e, 0x9f, 0x5b, 0x03, 0x35, 0xae, 0xf6, 0x3a, 0xf7, 0xfd, 0x37, 0x1f, + 0x1c, 0xe9, 0x83, 0x6b, 0x1c, 0xba, 0xc7, 0x27, 0x12, 0x59, 0xc8, 0x8e, 0xb3, 0x74, 0x78, 0x21, 0xa7, 0xdb, 0xfa, + 0xa8, 0xa4, 0xdb, 0xf1, 0x44, 0xe1, 0x1f, 0x5a, 0x90, 0xbc, 0xcd, 0xe3, 0xd9, 0x81, 0xa6, 0xfa, 0x76, 0x26, 0x35, + 0x62, 0xd3, 0xdd, 0x4e, 0xa9, 0x4f, 0xb2, 0x12, 0x8e, 0x85, 0xc1, 0x36, 0x06, 0xe3, 0x2a, 0xb7, 0x73, 0x2b, 0xb7, + 0x39, 0xac, 0x35, 0x7d, 0xf1, 0xed, 0x6e, 0x6f, 0x5a, 0xe8, 0xfd, 0x4b, 0xfb, 0x9c, 0x8e, 0xa1, 0x99, 0x3b, 0x0c, + 0x08, 0x0a, 0x5f, 0x28, 0x4e, 0x2f, 0xd3, 0xd7, 0xb7, 0xc3, 0xf8, 0x18, 0xda, 0xf9, 0xaa, 0xd8, 0x09, 0x32, 0x8f, + 0xca, 0x45, 0x6a, 0xf3, 0x99, 0x71, 0x59, 0x4d, 0x6e, 0x8b, 0xf3, 0xdb, 0x53, 0x32, 0xef, 0xf9, 0x15, 0x34, 0xa8, + 0xc7, 0xfe, 0xa3, 0x86, 0xbf, 0x3c, 0xad, 0x61, 0x5d, 0x29, 0xca, 0x80, 0xdd, 0xd6, 0x35, 0x20, 0x9b, 0x9c, 0xf3, + 0xe0, 0xb8, 0x56, 0x38, 0xf0, 0x6a, 0x17, 0x9d, 0x43, 0x5c, 0x56, 0xc6, 0xf5, 0xa6, 0x4f, 0xbb, 0xdc, 0xcf, 0xb8, + 0x53, 0xd8, 0x75, 0x70, 0x12, 0xb1, 0x81, 0x07, 0x15, 0x7d, 0x40, 0x77, 0xd2, 0x87, 0x7a, 0xd8, 0xab, 0x06, 0x42, + 0x08, 0x8c, 0x6f, 0xbe, 0x50, 0xe6, 0xcf, 0xd2, 0xea, 0xbb, 0xac, 0x55, 0x31, 0x96, 0x64, 0x0d, 0x9c, 0x9d, 0xde, + 0x1f, 0x71, 0x18, 0x62, 0xc7, 0x9b, 0x04, 0xc4, 0x59, 0xe6, 0x46, 0xcc, 0x49, 0x10, 0x7d, 0xc8, 0x3a, 0xea, 0xe9, + 0x47, 0xf3, 0x1f, 0x10, 0x01, 0x02, 0x16, 0x1c, 0x27, 0x02, 0x61, 0xc8, 0x7c, 0x85, 0xf0, 0x9d, 0xbe, 0xfd, 0xf0, + 0x0b, 0xa6, 0xb6, 0x6f, 0x74, 0xd7, 0xc8, 0xff, 0x6b, 0x38, 0xe4, 0xf6, 0x57, 0x9e, 0x2e, 0x0f, 0xf9, 0x93, 0xcb, + 0x3e, 0x7f, 0xbb, 0x77, 0xd3, 0xe4, 0xee, 0xe4, 0xe6, 0x63, 0x05, 0xd4, 0xfa, 0x7c, 0x95, 0x1e, 0xa1, 0x62, 0x44, + 0x19, 0x73, 0xa7, 0x87, 0x31, 0x6d, 0x96, 0x9d, 0x0d, 0x2e, 0x11, 0xfb, 0x35, 0x2e, 0x4f, 0xbd, 0x86, 0x09, 0x6c, + 0x57, 0xe1, 0x5a, 0x3a, 0x97, 0x49, 0xd6, 0x3c, 0x53, 0xe6, 0xa8, 0x60, 0x2c, 0x6c, 0x4c, 0x00, 0x6f, 0x60, 0xa7, + 0xcb, 0x77, 0xfa, 0xd6, 0x8b, 0xbe, 0x94, 0x07, 0x09, 0x6a, 0x1e, 0x70, 0x11, 0xe8, 0xea, 0x99, 0x6d, 0xb1, 0xf1, + 0xfb, 0x39, 0xd1, 0xd1, 0x04, 0x92, 0xfa, 0xe3, 0x31, 0x6a, 0xaf, 0x72, 0x57, 0xda, 0x2a, 0xaa, 0x85, 0x9e, 0xed, + 0x89, 0xd0, 0xa7, 0x4c, 0x26, 0x03, 0x76, 0x01, 0x5f, 0xf5, 0x92, 0xbe, 0xb4, 0x35, 0xe4, 0x53, 0xe5, 0x29, 0x17, + 0x2c, 0x1c, 0x4f, 0x70, 0x9c, 0xf6, 0xa8, 0x3e, 0x10, 0x4c, 0xe2, 0x2a, 0x58, 0xc3, 0xbe, 0x64, 0x55, 0xe9, 0x45, + 0x73, 0x32, 0x0c, 0x2e, 0xa7, 0xc9, 0xfa, 0x37, 0xb6, 0xc5, 0xd2, 0xf7, 0x24, 0xd0, 0x6e, 0xd1, 0xc8, 0x66, 0x8c, + 0x85, 0x0c, 0x65, 0x3a, 0x68, 0x03, 0x09, 0x40, 0x67, 0x4d, 0x67, 0xc5, 0xa7, 0xa9, 0xa5, 0x70, 0x6e, 0x92, 0x18, + 0x0b, 0x97, 0xe6, 0x48, 0x36, 0x53, 0x30, 0xe1, 0x75, 0x4b, 0x7b, 0x9e, 0x4d, 0x32, 0xef, 0xcb, 0x24, 0xa6, 0x7c, + 0x2f, 0x70, 0xef, 0x20, 0x9c, 0x48, 0xe8, 0x55, 0xc8, 0x52, 0x28, 0xb5, 0x04, 0xdb, 0x98, 0xb9, 0xf0, 0x37, 0x00, + 0xa2, 0x7c, 0x1a, 0x63, 0x03, 0xf6, 0xaf, 0xd1, 0x10, 0x3a, 0xb1, 0xfd, 0xc1, 0x5a, 0x49, 0x61, 0x06, 0xaa, 0x2c, + 0x94, 0xd8, 0x9c, 0x25, 0x7b, 0x71, 0xf8, 0x06, 0x17, 0x3a, 0x77, 0x4a, 0x61, 0x9f, 0xd3, 0x39, 0xc1, 0x54, 0x55, + 0xce, 0x1b, 0x72, 0x13, 0xe2, 0xf9, 0x46, 0x92, 0x46, 0xcb, 0x21, 0x76, 0x11, 0x73, 0xbd, 0xf8, 0xed, 0xdf, 0x47, + 0xb8, 0xd9, 0x94, 0x16, 0x9b, 0xd9, 0xce, 0x08, 0xcf, 0x3b, 0x38, 0x3a, 0x23, 0x8f, 0x5d, 0x8f, 0x2c, 0x0d, 0xfe, + 0xf1, 0x4d, 0x6e, 0x97, 0xeb, 0x9d, 0x13, 0x40, 0x3d, 0xf9, 0xef, 0x45, 0xed, 0x6a, 0x72, 0x1a, 0x89, 0xa1, 0xb1, + 0x91, 0x91, 0x05, 0x00, 0x12, 0x18, 0x6b, 0x3a, 0x36, 0xb3, 0x29, 0xda, 0x76, 0x82, 0x68, 0xf6, 0xf3, 0x47, 0x5c, + 0xbf, 0x37, 0x1b, 0xbe, 0xc0, 0x7d, 0xdc, 0xb1, 0x51, 0x5c, 0x3e, 0xb0, 0x89, 0x1c, 0xfa, 0xad, 0x16, 0x33, 0xfa, + 0x46, 0x26, 0xdc, 0x88, 0xf5, 0x39, 0xb4, 0xdb, 0xa0, 0xc2, 0x01, 0x90, 0xf9, 0x93, 0x7c, 0x3c, 0xff, 0x57, 0xaa, + 0xb9, 0x13, 0xc6, 0xac, 0xb1, 0x72, 0x69, 0x4c, 0xe2, 0xe4, 0xd0, 0x5e, 0x70, 0xd4, 0x9c, 0xd0, 0x3e, 0xac, 0x08, + 0x7a, 0x8c, 0xb6, 0x31, 0x99, 0x81, 0xd0, 0x90, 0x62, 0x05, 0x63, 0xb0, 0x1f, 0x56, 0x9f, 0x5d, 0x77, 0xbf, 0x40, + 0x8a, 0x7b, 0xe3, 0x3a, 0x33, 0x9e, 0x9b, 0x4c, 0x66, 0x3a, 0x8f, 0x2d, 0x78, 0x4b, 0x5c, 0x34, 0xad, 0x56, 0x3e, + 0x6b, 0x77, 0x4c, 0xdb, 0xbe, 0x63, 0xba, 0x8a, 0x5f, 0xc7, 0x87, 0x64, 0xb6, 0x37, 0xe7, 0x10, 0x40, 0x8b, 0xfa, + 0xec, 0x13, 0xfc, 0xe4, 0xa2, 0xd3, 0xd4, 0x9b, 0x6d, 0x68, 0x68, 0xbb, 0x5c, 0x9f, 0x1f, 0xb4, 0x3a, 0x41, 0xc7, + 0x90, 0xb3, 0x66, 0x50, 0xf4, 0x3e, 0xb1, 0xf3, 0x12, 0x9f, 0x58, 0xa7, 0x82, 0x71, 0xd2, 0x80, 0x7e, 0x9c, 0x93, + 0x97, 0xbb, 0xdc, 0x3c, 0x06, 0xf2, 0x53, 0x8a, 0x23, 0x74, 0xc3, 0xe8, 0x61, 0x4d, 0xf4, 0xbd, 0x47, 0x8f, 0x2d, + 0x5b, 0xb3, 0x0d, 0x40, 0x63, 0x72, 0x85, 0x2b, 0x4b, 0xb2, 0x4d, 0xf8, 0x98, 0x1e, 0x5c, 0xa3, 0x05, 0x4d, 0x9f, + 0x7d, 0xf6, 0x37, 0x17, 0xd0, 0xd9, 0x63, 0x02, 0xb5, 0xc4, 0xb3, 0x74, 0x50, 0x2f, 0x14, 0xca, 0x73, 0x04, 0x46, + 0x5e, 0x62, 0x9e, 0x55, 0xd3, 0xa1, 0xa6, 0x75, 0x8f, 0x4e, 0x4f, 0x5d, 0x6a, 0x2d, 0xbb, 0x98, 0xb1, 0x40, 0x34, + 0x47, 0x2b, 0xb3, 0xaf, 0x04, 0xfd, 0x50, 0x83, 0x8d, 0x99, 0x05, 0xf0, 0x8a, 0x5c, 0x6f, 0xa4, 0xa6, 0x27, 0xf1, + 0x1e, 0xe1, 0x8a, 0x40, 0xb8, 0x23, 0x8a, 0x94, 0xf1, 0x14, 0x88, 0xa3, 0x75, 0xbc, 0x9e, 0x4e, 0xec, 0x38, 0x78, + 0x52, 0x90, 0x17, 0x7e, 0x6b, 0x46, 0x02, 0x9e, 0xfd, 0x11, 0x48, 0xca, 0x5e, 0x07, 0x21, 0xba, 0xca, 0x12, 0xdb, + 0x5b, 0x35, 0x16, 0x77, 0x1f, 0x36, 0x2d, 0x32, 0x77, 0xc5, 0x90, 0x9d, 0x85, 0x73, 0x45, 0xeb, 0x62, 0xd9, 0x76, + 0x4f, 0xe4, 0xee, 0x6c, 0xc5, 0x41, 0x62, 0xe1, 0x7a, 0xe7, 0x13, 0x32, 0xe5, 0xc3, 0x98, 0xd2, 0xf5, 0xda, 0xa8, + 0x55, 0xbb, 0xcc, 0x91, 0x17, 0x29, 0xe2, 0xed, 0x5a, 0x48, 0x11, 0x8b, 0x53, 0x11, 0xad, 0x09, 0x5f, 0x1d, 0x24, + 0x0d, 0x6a, 0x7d, 0xbf, 0xee, 0x6c, 0xf6, 0x83, 0x3c, 0xb7, 0x4e, 0x25, 0xe5, 0xe1, 0xf0, 0xd7, 0xe6, 0xdb, 0x11, + 0xf7, 0xa2, 0x41, 0xf1, 0xa5, 0xea, 0x2a, 0x12, 0xcd, 0xed, 0x95, 0xea, 0x4c, 0x17, 0xc5, 0xef, 0x53, 0x76, 0xca, + 0x61, 0x8a, 0xf1, 0xd9, 0x74, 0xda, 0xdd, 0x27, 0x0f, 0x42, 0xc7, 0xee, 0xba, 0xdc, 0x99, 0xf9, 0x7a, 0xc7, 0xde, + 0x9c, 0x70, 0xfa, 0x9f, 0xca, 0x8a, 0xb3, 0x11, 0xd1, 0xff, 0xfa, 0x37, 0x2f, 0xc0, 0xb7, 0x4e, 0xbb, 0x2e, 0x9d, + 0x1a, 0x48, 0xa1, 0x85, 0x35, 0x6d, 0xec, 0x5f, 0xfc, 0x44, 0x0a, 0x01, 0xa1, 0x77, 0x9e, 0x57, 0x57, 0x48, 0x60, + 0x9b, 0xda, 0xc5, 0xd4, 0xed, 0xbe, 0xd6, 0x4b, 0x4c, 0xca, 0x12, 0xd7, 0x75, 0xf8, 0x85, 0xa5, 0x9f, 0x84, 0x69, + 0xc8, 0xbd, 0xd3, 0xa6, 0xd1, 0x86, 0x18, 0x41, 0x39, 0xbb, 0x17, 0x4b, 0x4d, 0x08, 0x5d, 0xdc, 0x51, 0x16, 0x60, + 0xd7, 0x3f, 0x9e, 0xa2, 0xc9, 0x95, 0x08, 0xf5, 0xc7, 0x78, 0x13, 0xb6, 0x5c, 0xdd, 0x29, 0x4d, 0x61, 0x3b, 0x4c, + 0xd9, 0x67, 0x08, 0xf4, 0x1a, 0x31, 0xf8, 0x7c, 0x7b, 0x0b, 0x07, 0x7b, 0x23, 0x34, 0x91, 0x49, 0xb7, 0x10, 0xb3, + 0xa3, 0xf1, 0xdb, 0x9f, 0xa9, 0xc6, 0xfc, 0xdc, 0xb7, 0x58, 0xee, 0x90, 0x9e, 0x00, 0x47, 0x3a, 0xe0, 0xf1, 0x3c, + 0x1d, 0x29, 0xbe, 0x0d, 0xfa, 0xb5, 0x49, 0xfe, 0xd7, 0xb8, 0xe1, 0x1b, 0x4d, 0x37, 0x84, 0xa7, 0xab, 0xc2, 0x0e, + 0x7d, 0xce, 0x60, 0x2e, 0xa9, 0x4b, 0xfa, 0xf0, 0x4f, 0x27, 0x9d, 0x71, 0x7d, 0x53, 0x44, 0x06, 0x03, 0x97, 0x05, + 0x93, 0xb3, 0xeb, 0x0e, 0xf3, 0xd2, 0xf7, 0x04, 0x32, 0x30, 0x78, 0x18, 0x47, 0x48, 0x22, 0x93, 0x81, 0xbd, 0xc1, + 0x84, 0xbe, 0xba, 0x94, 0x70, 0xc6, 0x6b, 0x4a, 0xd3, 0xa1, 0xea, 0xb8, 0xd9, 0xf4, 0x42, 0x81, 0x71, 0x04, 0xa1, + 0xc4, 0x33, 0x60, 0x15, 0xa8, 0x48, 0xcf, 0x99, 0xe5, 0x9c, 0xf2, 0x5b, 0xe7, 0xb0, 0x75, 0x9d, 0xd5, 0xa8, 0x3e, + 0x3f, 0x97, 0x85, 0x00, 0x91, 0xe6, 0xda, 0x99, 0xb4, 0x94, 0x7a, 0xfa, 0xe1, 0x91, 0x94, 0xc3, 0xff, 0x20, 0x89, + 0x57, 0x79, 0x3e, 0xfe, 0xf5, 0xe3, 0x44, 0x55, 0x3d, 0xf8, 0x76, 0xd1, 0x07, 0xba, 0x6f, 0x5e, 0x8f, 0x6a, 0xe5, + 0xf9, 0x8a, 0xfd, 0xe2, 0x22, 0xe3, 0xc2, 0xfc, 0x13, 0x83, 0x30, 0x06, 0x3a, 0xb3, 0xe0, 0x2b, 0x62, 0xc5, 0xaf, + 0xf9, 0xec, 0xb4, 0x07, 0x6a, 0x8e, 0xe4, 0x4c, 0xa6, 0x28, 0xab, 0x75, 0xeb, 0xdd, 0x4e, 0x0d, 0x88, 0x48, 0x47, + 0x6f, 0xc6, 0xe9, 0x06, 0x2e, 0x70, 0x5a, 0x75, 0x86, 0xfa, 0x59, 0xb0, 0x22, 0xb9, 0xfd, 0x0d, 0x59, 0xbc, 0xeb, + 0xbe, 0xdf, 0x51, 0xb9, 0x72, 0x12, 0x87, 0x26, 0xd6, 0x7e, 0xda, 0x29, 0x80, 0x99, 0xba, 0xb3, 0x4d, 0xd1, 0x73, + 0x1d, 0x1d, 0x1c, 0x53, 0x06, 0x0e, 0xa7, 0x9e, 0x1f, 0x24, 0x34, 0x7c, 0x15, 0xbe, 0xe8, 0xa3, 0x6e, 0xf7, 0x47, + 0x0c, 0xa4, 0x20, 0x23, 0xb9, 0xb3, 0x27, 0x96, 0x57, 0x21, 0x6f, 0xa2, 0xc6, 0x71, 0x31, 0xa3, 0x42, 0x28, 0xfb, + 0xd7, 0xf2, 0x72, 0x3f, 0x0c, 0xc9, 0x5d, 0x93, 0x12, 0x6f, 0x76, 0xae, 0x91, 0x72, 0x96, 0x60, 0x6e, 0x47, 0x2c, + 0x47, 0x33, 0xa8, 0xd7, 0x7d, 0x7a, 0xd7, 0xe1, 0x33, 0x34, 0x45, 0x8f, 0x1b, 0x74, 0xa1, 0xd0, 0xa8, 0x5b, 0x5b, + 0xa3, 0x6d, 0x1a, 0xa5, 0x89, 0xc8, 0xa9, 0x22, 0xa4, 0x0f, 0xf3, 0xcd, 0xe4, 0x9b, 0x1d, 0x90, 0x32, 0x06, 0x0f, + 0xd0, 0xa4, 0x7a, 0x05, 0x10, 0x69, 0xbe, 0x7c, 0xaa, 0xa4, 0xdb, 0xcf, 0x5e, 0x24, 0xfd, 0x04, 0x34, 0x4e, 0x34, + 0xe9, 0x1a, 0x3f, 0xa1, 0x4c, 0x6b, 0x8a, 0xa3, 0x09, 0x49, 0x34, 0x5a, 0x26, 0xcf, 0x86, 0xda, 0x91, 0xd7, 0x82, + 0x95, 0xa1, 0x27, 0x0d, 0x16, 0x81, 0xe0, 0x00, 0x89, 0x24, 0x5c, 0x53, 0x92, 0x61, 0x8c, 0x0b, 0x84, 0xd1, 0xbf, + 0xb0, 0x25, 0x1d, 0x62, 0xed, 0x66, 0xc1, 0x84, 0x8c, 0xee, 0xcf, 0xf8, 0x25, 0x0c, 0x0d, 0xab, 0x66, 0x18, 0x4f, + 0xd2, 0x71, 0xaa, 0x35, 0x46, 0x51, 0x5a, 0x9c, 0x05, 0x93, 0x5a, 0xc8, 0xa1, 0xc6, 0x00, 0xdb, 0x8d, 0xe3, 0x69, + 0x4d, 0xd9, 0x32, 0x62, 0x26, 0xdd, 0xdb, 0xda, 0x51, 0xa7, 0xb9, 0xa5, 0x9f, 0x7b, 0x21, 0xb3, 0x0d, 0x39, 0xe6, + 0xbc, 0xa5, 0x5f, 0x36, 0xd1, 0x87, 0x16, 0xeb, 0x66, 0x1c, 0x08, 0x33, 0xfc, 0xb9, 0xe5, 0x90, 0x78, 0x54, 0x30, + 0xa8, 0xf2, 0xa4, 0x46, 0x2b, 0xd2, 0xf6, 0xbe, 0xaf, 0x8e, 0xe6, 0xb6, 0xa9, 0x48, 0x1a, 0x82, 0xdc, 0x08, 0x4d, + 0x04, 0x8e, 0x5d, 0xe9, 0x1f, 0x67, 0x75, 0xff, 0xdd, 0x43, 0x1f, 0x49, 0x83, 0xf0, 0xe5, 0x9a, 0xe9, 0x20, 0x14, + 0x30, 0x57, 0xad, 0xdb, 0xd4, 0x67, 0x71, 0x35, 0xa2, 0xbf, 0x22, 0x64, 0xcc, 0x38, 0x56, 0xfd, 0x98, 0x66, 0xe4, + 0x77, 0xfa, 0x1a, 0x39, 0x26, 0xef, 0xc7, 0xcc, 0x6a, 0x55, 0xf2, 0xe1, 0xa9, 0x3b, 0x5d, 0xc9, 0x68, 0x46, 0xca, + 0xb3, 0xba, 0xc3, 0xd2, 0x56, 0x88, 0x39, 0x8b, 0xf7, 0xe4, 0x7a, 0x36, 0x5d, 0x65, 0x2b, 0xf1, 0x43, 0x7a, 0x70, + 0xaf, 0x8f, 0x99, 0xa4, 0xc3, 0x0f, 0x59, 0x7e, 0xdd, 0x9d, 0x00, 0x21, 0x4f, 0x4f, 0xc0, 0xac, 0x6e, 0x5d, 0xd9, + 0x69, 0xad, 0xb8, 0xef, 0x24, 0xdb, 0x36, 0x5c, 0xbf, 0xe6, 0x8f, 0x79, 0xf0, 0x70, 0xef, 0xcb, 0x36, 0x17, 0x4f, + 0xc3, 0xc7, 0xc9, 0x52, 0x0b, 0x21, 0xf1, 0x55, 0x97, 0x42, 0x15, 0xa3, 0xe0, 0x0d, 0xe3, 0x41, 0x5c, 0xc8, 0x1f, + 0xe7, 0xb4, 0x35, 0x2d, 0x3b, 0xb5, 0x92, 0x78, 0xac, 0xab, 0x30, 0x2d, 0xf9, 0x75, 0x51, 0xcd, 0x79, 0x66, 0xe2, + 0x55, 0xa7, 0x9e, 0xa1, 0x39, 0x8d, 0xc9, 0xf5, 0xf0, 0x9e, 0x97, 0x68, 0x64, 0xd9, 0xf0, 0x6e, 0xc2, 0x5b, 0xb1, + 0x57, 0x9e, 0xa1, 0xdc, 0x1d, 0x29, 0x35, 0x84, 0x02, 0x62, 0x04, 0x1a, 0x57, 0xe7, 0x2e, 0xad, 0xa4, 0xb3, 0xe4, + 0x51, 0x63, 0xe0, 0x8b, 0x39, 0x8f, 0x5b, 0x63, 0xa1, 0x1c, 0x6b, 0x0e, 0x61, 0x46, 0xaa, 0x70, 0x32, 0xd5, 0x0d, + 0xe0, 0xce, 0x34, 0x43, 0x88, 0x26, 0x4a, 0xcd, 0x29, 0xee, 0xe2, 0x6b, 0x34, 0x99, 0x6c, 0xe8, 0x18, 0xf4, 0x2c, + 0xaf, 0xc8, 0x34, 0x1e, 0x07, 0xd0, 0x7d, 0xe0, 0xeb, 0x06, 0x89, 0x05, 0xdb, 0xb2, 0x4e, 0xf8, 0x2a, 0x70, 0xe2, + 0x28, 0xab, 0x12, 0x53, 0xc3, 0xb3, 0xa1, 0xdb, 0x1f, 0xe8, 0x88, 0xb5, 0xa2, 0xa6, 0xbb, 0x23, 0x26, 0x28, 0xf8, + 0xee, 0xfb, 0x2f, 0x78, 0x77, 0x64, 0xe2, 0x38, 0x83, 0x38, 0xae, 0x5d, 0x78, 0x9b, 0x74, 0x04, 0x4d, 0x30, 0x56, + 0x96, 0x63, 0x9e, 0x72, 0x49, 0xa1, 0xf6, 0xfc, 0x97, 0x86, 0x23, 0x54, 0xc9, 0x35, 0x44, 0x6f, 0x19, 0xba, 0x43, + 0xb0, 0x6b, 0x1f, 0xa2, 0x53, 0x11, 0x1f, 0x78, 0x7f, 0x81, 0x48, 0x98, 0x4b, 0xa1, 0xcc, 0xb2, 0x5e, 0xed, 0xb1, + 0x80, 0x3a, 0xef, 0x29, 0xc7, 0x46, 0x01, 0x2b, 0x4b, 0xaf, 0x58, 0xab, 0x4e, 0xd9, 0xe1, 0xd7, 0x3a, 0x12, 0x62, + 0x63, 0xae, 0x1b, 0x1a, 0x3f, 0x91, 0xae, 0x02, 0x89, 0xcd, 0x7b, 0xb5, 0x9c, 0x8d, 0xa2, 0x50, 0x1f, 0xbe, 0xe4, + 0x93, 0xb6, 0x52, 0x3f, 0x41, 0x82, 0x3f, 0xe1, 0x90, 0x88, 0xf9, 0x94, 0x1f, 0x24, 0x56, 0x75, 0xb9, 0xa9, 0x59, + 0x66, 0xdb, 0x21, 0xf9, 0x97, 0x5f, 0x88, 0x3f, 0x7b, 0x8f, 0x25, 0x78, 0xac, 0x30, 0x43, 0xc2, 0x18, 0xa3, 0xd4, + 0x4b, 0xfe, 0x68, 0x81, 0x8f, 0xe7, 0x6e, 0x7e, 0xf5, 0xdb, 0x59, 0x3b, 0xfc, 0x82, 0x81, 0x42, 0x8c, 0xfa, 0x42, + 0x4b, 0x0a, 0xf6, 0xee, 0x64, 0x71, 0xbb, 0x20, 0x27, 0xa1, 0x48, 0x45, 0x89, 0x12, 0xc6, 0x90, 0xb6, 0x01, 0xd0, + 0x4d, 0x80, 0x4a, 0x94, 0x6a, 0x1a, 0xd1, 0x23, 0xf8, 0x01, 0x9f, 0x6d, 0xde, 0x1e, 0x64, 0x1d, 0x4c, 0xa4, 0x36, + 0x2e, 0x63, 0x03, 0x98, 0xe2, 0xb9, 0xb5, 0xc3, 0xfb, 0x65, 0x04, 0xad, 0x75, 0xac, 0xd4, 0x10, 0xea, 0x22, 0xe7, + 0x7e, 0xf0, 0x19, 0x75, 0x37, 0xd9, 0x39, 0xcc, 0xd3, 0x0c, 0x0c, 0xe4, 0x78, 0x40, 0xb3, 0x6d, 0x4c, 0x96, 0x28, + 0x66, 0xd9, 0x0c, 0xbf, 0x54, 0x2f, 0x6f, 0xb4, 0xa5, 0x20, 0x69, 0xad, 0xce, 0x9e, 0x29, 0x86, 0x09, 0x1b, 0x58, + 0x60, 0x3e, 0x40, 0xd8, 0xc2, 0x12, 0xb6, 0x8e, 0x3d, 0x87, 0xfe, 0x68, 0x6c, 0xce, 0x71, 0x76, 0xb2, 0xe9, 0x5c, + 0xcb, 0xc6, 0x93, 0x1f, 0x15, 0xe7, 0x3c, 0x4d, 0xca, 0x41, 0x25, 0x54, 0x5b, 0xb1, 0x40, 0x87, 0xe8, 0x56, 0x1f, + 0x2a, 0x9d, 0x33, 0xf7, 0x9c, 0x90, 0x88, 0xa7, 0x73, 0xcc, 0xb5, 0xc7, 0xfb, 0x15, 0x25, 0x10, 0x2a, 0xbc, 0x75, + 0xf1, 0x31, 0x3b, 0x40, 0x56, 0x1e, 0x0a, 0x4f, 0xb6, 0x9c, 0x96, 0x48, 0x09, 0x4e, 0xbf, 0x79, 0x9d, 0x3c, 0x15, + 0x18, 0x19, 0x8a, 0x35, 0x26, 0xd5, 0x90, 0x78, 0x83, 0x11, 0x7a, 0x71, 0x11, 0xc9, 0x15, 0x98, 0x3b, 0x97, 0x66, + 0xea, 0x7a, 0x21, 0x67, 0x2c, 0xcf, 0x3d, 0xd8, 0xe3, 0xa5, 0xa7, 0x96, 0x5d, 0x78, 0xec, 0x5e, 0x32, 0xc7, 0xeb, + 0xf3, 0x90, 0x66, 0xb0, 0x3b, 0x85, 0xb5, 0x7a, 0xac, 0x8a, 0x82, 0x01, 0x58, 0x57, 0xc8, 0xca, 0xce, 0x34, 0x29, + 0x07, 0xca, 0x4f, 0x50, 0xdb, 0x41, 0xfd, 0x1b, 0x23, 0x11, 0x8c, 0xdf, 0x6d, 0xdd, 0xd7, 0x6e, 0xc9, 0x84, 0x99, + 0x8f, 0x02, 0x1b, 0xa2, 0xc7, 0x14, 0x66, 0x6c, 0x98, 0x2a, 0x63, 0xdc, 0x79, 0x0f, 0x83, 0xae, 0x2e, 0xdb, 0x4c, + 0xe5, 0x68, 0x7c, 0xb1, 0x8c, 0xab, 0x61, 0xa6, 0xef, 0xde, 0x03, 0x66, 0xbc, 0xda, 0xf3, 0x28, 0xe2, 0xd8, 0x49, + 0xcc, 0xa9, 0x9e, 0x51, 0xed, 0x6b, 0x2f, 0xdb, 0x74, 0x87, 0x98, 0xf0, 0xee, 0x0e, 0xde, 0x3b, 0x86, 0x99, 0x4c, + 0xe8, 0xe4, 0x40, 0x66, 0x42, 0xca, 0x1e, 0xa0, 0x89, 0x0c, 0x1d, 0x1e, 0x37, 0xe6, 0xa2, 0x3c, 0x4b, 0x32, 0x0b, + 0x0b, 0x17, 0xf6, 0x4d, 0xfa, 0x6f, 0xb8, 0x98, 0xfb, 0x22, 0xd0, 0xe6, 0x30, 0x5d, 0x37, 0xd9, 0xbc, 0x67, 0x15, + 0x9b, 0x2c, 0x1d, 0xb2, 0xd6, 0xa8, 0x12, 0xfd, 0x22, 0x31, 0x29, 0x3b, 0x84, 0x1e, 0x86, 0x6e, 0x10, 0xc5, 0x82, + 0xc5, 0xbe, 0xd1, 0x45, 0x3b, 0xc0, 0x47, 0x27, 0xe1, 0xb1, 0xf8, 0x9e, 0xee, 0x5c, 0x69, 0xce, 0xb7, 0xbb, 0x93, + 0xdf, 0xa8, 0x68, 0xd4, 0x34, 0x12, 0x1b, 0x95, 0xf8, 0x58, 0xec, 0xe5, 0xa6, 0xd2, 0x76, 0xf9, 0xd8, 0xd3, 0x5f, + 0xcc, 0xc8, 0x28, 0x1d, 0xcc, 0x99, 0x0e, 0x1e, 0xc2, 0xab, 0x79, 0x25, 0x8a, 0x7b, 0xae, 0x94, 0x70, 0x82, 0x9a, + 0x0b, 0x4e, 0x1d, 0x54, 0x29, 0x3c, 0x41, 0xa0, 0xd0, 0xfa, 0xc7, 0x75, 0xfd, 0x00, 0x48, 0xdb, 0xb3, 0x63, 0x30, + 0xf7, 0x55, 0x2f, 0x51, 0xa6, 0xee, 0x99, 0xd4, 0x0a, 0x68, 0x63, 0xab, 0xb8, 0x07, 0x12, 0xf4, 0x2d, 0x87, 0x94, + 0x90, 0x95, 0x79, 0x50, 0xd8, 0x2c, 0xa7, 0x27, 0xc9, 0x54, 0xe9, 0xcc, 0x5a, 0x51, 0x2e, 0xee, 0x89, 0x0a, 0xe1, + 0xd6, 0xfa, 0xfb, 0x80, 0x10, 0xa3, 0x94, 0xc1, 0x68, 0x62, 0xe2, 0x32, 0x42, 0x06, 0x8c, 0x0b, 0xc9, 0xb0, 0x82, + 0x48, 0x61, 0x97, 0x33, 0x8c, 0xc7, 0x74, 0x79, 0xd6, 0x9e, 0x9d, 0x87, 0xed, 0x7b, 0x6e, 0xc8, 0x1d, 0x82, 0xce, + 0xc6, 0x89, 0x4d, 0xe3, 0xe7, 0x67, 0xe2, 0x7d, 0x04, 0x37, 0x2a, 0x87, 0x35, 0x1a, 0x38, 0x35, 0xe6, 0x39, 0x8b, + 0xaf, 0xe2, 0x63, 0xbc, 0xad, 0x67, 0x4b, 0xae, 0x74, 0xec, 0x98, 0x3b, 0xf2, 0x63, 0x77, 0xa5, 0xb4, 0x29, 0x48, + 0xa2, 0x9e, 0xf6, 0xb4, 0x31, 0xe8, 0x76, 0xc8, 0xcd, 0x97, 0x0b, 0x0b, 0x7d, 0x83, 0xae, 0x8f, 0xf6, 0x01, 0xf7, + 0xe9, 0x20, 0xa2, 0x6a, 0xf1, 0x5d, 0x8b, 0x2f, 0x52, 0x10, 0x68, 0x89, 0x7d, 0x40, 0xde, 0xbb, 0x13, 0xe7, 0xbe, + 0x8b, 0x81, 0x1b, 0xfa, 0x07, 0x60, 0x21, 0xdd, 0x8a, 0xfb, 0xc9, 0xdb, 0x48, 0xd2, 0x0a, 0x80, 0x55, 0x9b, 0xc6, + 0x81, 0x23, 0x61, 0xfa, 0x02, 0x4b, 0xf6, 0x45, 0xce, 0x25, 0x9f, 0x14, 0x8a, 0xee, 0xf0, 0xb7, 0xf0, 0xe2, 0xf9, + 0x09, 0xe7, 0x64, 0xdd, 0xd2, 0xf1, 0x5d, 0xb5, 0x29, 0x91, 0x6a, 0xa9, 0x18, 0x24, 0x30, 0x23, 0x14, 0x39, 0x0f, + 0xd2, 0xb7, 0x17, 0xd9, 0x23, 0xfe, 0x01, 0xef, 0xf1, 0x0c, 0xdc, 0x74, 0x10, 0x26, 0xb3, 0xd9, 0x23, 0x1a, 0xaf, + 0x6f, 0x55, 0x27, 0xec, 0x02, 0x95, 0xc2, 0x68, 0x98, 0xc4, 0xf9, 0x4c, 0x95, 0x64, 0x38, 0xbe, 0xa9, 0x12, 0x52, + 0x38, 0xf1, 0x09, 0x88, 0xdb, 0x98, 0xdc, 0x8b, 0xb9, 0x12, 0xd5, 0xe9, 0xb6, 0x63, 0x68, 0xad, 0xfe, 0xfb, 0xf7, + 0x37, 0xe1, 0x7f, 0x90, 0x6c, 0xfa, 0x1b, 0x5f, 0x65, 0xe7, 0x9d, 0x13, 0xc1, 0xec, 0x21, 0x09, 0xdf, 0x38, 0xb3, + 0xac, 0x47, 0xbc, 0x26, 0x56, 0x48, 0xf7, 0xd4, 0xc9, 0xc2, 0x6e, 0x18, 0x72, 0xd5, 0x14, 0x9b, 0x4f, 0xbb, 0x54, + 0x80, 0x3e, 0xf6, 0x92, 0xad, 0x9a, 0x50, 0x4e, 0x00, 0x4a, 0x65, 0x3c, 0xb3, 0x52, 0x47, 0x83, 0x9a, 0x8d, 0xf2, + 0x32, 0x72, 0x46, 0x1f, 0x0b, 0xdd, 0x56, 0xb3, 0x20, 0x4b, 0x56, 0xe9, 0xa6, 0x86, 0x3a, 0x6b, 0xd6, 0xee, 0xcd, + 0xe7, 0xff, 0x6e, 0x3d, 0x2b, 0x13, 0x44, 0xf5, 0x46, 0x8d, 0xfe, 0xac, 0x97, 0x70, 0x45, 0x1c, 0xc7, 0xeb, 0x1d, + 0x9f, 0xd5, 0x7f, 0xb7, 0xf8, 0x47, 0xab, 0x5a, 0xf7, 0x12, 0x08, 0xcd, 0xcb, 0x5a, 0x00, 0xb3, 0x8a, 0x21, 0xbd, + 0x9e, 0x75, 0xe2, 0xc8, 0x86, 0x00, 0x7c, 0xf8, 0x13, 0xb7, 0x6b, 0xf7, 0x7e, 0x67, 0xa2, 0x6d, 0x7b, 0xe2, 0x8c, + 0x55, 0x05, 0x94, 0x27, 0xba, 0x79, 0x4c, 0x34, 0x63, 0x55, 0x77, 0x85, 0x69, 0xf6, 0x7f, 0x52, 0x4e, 0xfa, 0xcb, + 0x92, 0xb9, 0x9a, 0x11, 0x00, 0xe2, 0x34, 0x8f, 0x89, 0xaa, 0x77, 0x33, 0xed, 0xbd, 0xab, 0xe7, 0xf4, 0xda, 0xa2, + 0xb5, 0xcf, 0x64, 0x2b, 0x35, 0x8c, 0x41, 0xd7, 0x3c, 0x51, 0x7d, 0x53, 0x72, 0x19, 0x69, 0x15, 0x6d, 0xcc, 0x1b, + 0x7f, 0x6a, 0x4d, 0xae, 0xde, 0xa5, 0xae, 0x30, 0x42, 0x64, 0xd6, 0xdf, 0x19, 0xc9, 0x97, 0x37, 0x7f, 0x38, 0xb1, + 0x17, 0xcb, 0x24, 0x2c, 0x6f, 0xd4, 0x8a, 0xb0, 0x31, 0x56, 0x81, 0x85, 0x7c, 0xf9, 0x16, 0xcd, 0x34, 0x85, 0xa5, + 0x4d, 0x24, 0x67, 0x94, 0xfe, 0x28, 0x2e, 0xeb, 0x54, 0xed, 0x5d, 0x88, 0x95, 0xbd, 0x16, 0xda, 0x4f, 0x7f, 0x95, + 0xd4, 0x63, 0xd9, 0x59, 0x04, 0x9d, 0x0c, 0xa0, 0xa1, 0x5a, 0xb5, 0xe7, 0x88, 0x5d, 0x70, 0xc6, 0x66, 0xf1, 0xd2, + 0x19, 0xe6, 0x9d, 0x61, 0x10, 0x82, 0xd3, 0x24, 0xc7, 0x82, 0x9b, 0x8c, 0x73, 0x00, 0x6d, 0x55, 0xa3, 0x9e, 0xab, + 0x14, 0x4f, 0x9f, 0xf7, 0x42, 0x59, 0xf8, 0x39, 0xa0, 0xba, 0x73, 0x47, 0x12, 0x6e, 0xe1, 0xe8, 0xf8, 0x89, 0xab, + 0xe2, 0xb2, 0x86, 0xee, 0x51, 0xcc, 0x9c, 0xb7, 0xcf, 0x84, 0x2b, 0xb6, 0xe1, 0xb4, 0x12, 0xcc, 0x09, 0x00, 0xd6, + 0x4d, 0xb0, 0x6e, 0xbe, 0x81, 0xaa, 0x2e, 0x9d, 0x4b, 0x46, 0x72, 0x7d, 0x80, 0x0b, 0xe1, 0x65, 0xbe, 0xf1, 0x1e, + 0x38, 0x09, 0x2a, 0x2d, 0x78, 0x30, 0x7b, 0x0c, 0xe6, 0xd5, 0x34, 0xf8, 0x43, 0x70, 0x67, 0xa6, 0x8e, 0x50, 0x1c, + 0x79, 0x4e, 0xad, 0x97, 0xee, 0xa5, 0x1d, 0x1f, 0xac, 0x54, 0x4f, 0x9c, 0x43, 0x19, 0xd7, 0x39, 0xd8, 0x3e, 0xea, + 0xbd, 0xd0, 0x7e, 0xc1, 0xac, 0x0f, 0xbc, 0xa6, 0x09, 0x8f, 0x03, 0xaf, 0x73, 0x45, 0xb5, 0x33, 0x5a, 0xe9, 0xb5, + 0x42, 0x8c, 0x70, 0xe8, 0x14, 0xf3, 0xe7, 0x37, 0x31, 0xca, 0xa0, 0xb7, 0x28, 0xb9, 0x57, 0xb5, 0xc4, 0x69, 0xf7, + 0xbb, 0x21, 0xe9, 0xdf, 0x55, 0x40, 0xfd, 0x9f, 0x19, 0x0f, 0x77, 0xbf, 0xba, 0x97, 0xb3, 0x17, 0xd1, 0xe6, 0xcd, + 0xb8, 0xba, 0x98, 0xd1, 0x2e, 0x40, 0x69, 0x60, 0xf1, 0xad, 0x9b, 0xfd, 0x98, 0xc7, 0x59, 0x8d, 0x31, 0x86, 0x26, + 0xa1, 0xb1, 0x89, 0x60, 0x63, 0xbc, 0x49, 0x6c, 0x05, 0x2f, 0x45, 0x10, 0x8b, 0xc9, 0xe4, 0x47, 0x1d, 0x06, 0xd7, + 0x8c, 0x3c, 0xfd, 0x86, 0x14, 0xe7, 0xa2, 0x68, 0xa5, 0xc7, 0x93, 0x1f, 0xc5, 0x96, 0x84, 0x7b, 0xb5, 0xdf, 0x2c, + 0x49, 0xb9, 0xe7, 0x25, 0xa5, 0xc5, 0xba, 0x60, 0x2b, 0xd9, 0x5a, 0x6b, 0xea, 0x9f, 0xda, 0x35, 0x51, 0xd1, 0x78, + 0x1a, 0xde, 0xa8, 0x7e, 0x90, 0x5f, 0x67, 0x37, 0x36, 0x0b, 0xb9, 0x56, 0x38, 0x68, 0xfa, 0x91, 0x5e, 0x74, 0xdd, + 0x86, 0x36, 0xee, 0xf4, 0x44, 0xeb, 0x18, 0x22, 0xde, 0xc1, 0x25, 0x5e, 0x30, 0x2f, 0x47, 0xb9, 0x5d, 0xc4, 0x5c, + 0x65, 0x4e, 0xec, 0xae, 0x25, 0xf3, 0xcc, 0xa2, 0xb2, 0x3c, 0xe9, 0x34, 0x79, 0x41, 0x02, 0x49, 0x7b, 0x0e, 0x0e, + 0xc0, 0xdf, 0xd2, 0x35, 0x6f, 0x76, 0xa0, 0x6b, 0xb9, 0xe9, 0xd5, 0x21, 0xde, 0xb5, 0x1f, 0x1e, 0xc9, 0xb4, 0x8d, + 0x80, 0xc6, 0x37, 0x34, 0x0e, 0x80, 0x4c, 0x57, 0x34, 0x6d, 0x6c, 0x1c, 0x04, 0x98, 0x50, 0x91, 0xbd, 0x4b, 0x04, + 0x9c, 0x0a, 0xde, 0x07, 0x32, 0x56, 0x64, 0xd2, 0xae, 0xfd, 0xb3, 0x41, 0x26, 0x21, 0x2d, 0x64, 0xa3, 0x3e, 0x6d, + 0x6a, 0x6f, 0x26, 0xff, 0x76, 0x2b, 0x77, 0x49, 0xc5, 0xd6, 0x92, 0x9d, 0x6d, 0x41, 0x4e, 0x0b, 0x49, 0x3e, 0x56, + 0x01, 0xe1, 0x58, 0xb3, 0xd8, 0xc8, 0x0f, 0x05, 0x4f, 0x80, 0x62, 0x28, 0x5a, 0x42, 0x33, 0x76, 0xb3, 0x3d, 0xd8, + 0x5e, 0x47, 0x0f, 0x89, 0x7b, 0x40, 0xca, 0x39, 0x32, 0x17, 0x79, 0x4c, 0x77, 0xef, 0x6c, 0x5b, 0x8f, 0xad, 0x6b, + 0xf1, 0x59, 0x1d, 0x6c, 0x6e, 0xbd, 0xa2, 0xca, 0xff, 0x3f, 0x74, 0x35, 0x7f, 0x1e, 0x07, 0x70, 0xf0, 0xee, 0x83, + 0x4e, 0x21, 0xb5, 0xa1, 0x56, 0x6f, 0xb7, 0x35, 0x51, 0x88, 0x26, 0x7a, 0xfe, 0x58, 0xb1, 0x4a, 0x2f, 0x31, 0xca, + 0xc2, 0x97, 0x54, 0xe2, 0x74, 0xbb, 0xfc, 0xa9, 0x4b, 0x86, 0xb3, 0xab, 0x64, 0xfd, 0xd9, 0x30, 0x8f, 0x7e, 0x13, + 0x43, 0x5c, 0xe5, 0xc5, 0x6d, 0x04, 0x43, 0x28, 0xf4, 0xd8, 0xf9, 0x07, 0x74, 0x52, 0xd6, 0x7c, 0x22, 0x81, 0x62, + 0x79, 0xaa, 0x0c, 0x0d, 0x28, 0xd2, 0xdb, 0x0c, 0x51, 0x4d, 0x14, 0xa3, 0x9d, 0xb5, 0x42, 0x90, 0x46, 0x37, 0xfa, + 0x2f, 0x03, 0x9b, 0x34, 0xcb, 0xea, 0x73, 0xe2, 0x04, 0xd9, 0xbe, 0x3b, 0xe9, 0x33, 0x96, 0x0b, 0xbe, 0x1e, 0xc7, + 0x65, 0x23, 0x78, 0x1b, 0x8a, 0xd0, 0x39, 0x66, 0x50, 0x9b, 0x3a, 0xaf, 0xda, 0x19, 0x42, 0x39, 0x8e, 0x03, 0xb9, + 0xa6, 0xa5, 0xdd, 0x01, 0x5a, 0xc4, 0x73, 0x9e, 0x4e, 0xf0, 0x98, 0xa4, 0xf9, 0x3e, 0x07, 0x79, 0x37, 0x09, 0x82, + 0x26, 0xfa, 0xba, 0x83, 0x0b, 0xf2, 0x58, 0xd1, 0xb5, 0x83, 0xd9, 0x1b, 0xeb, 0xef, 0xea, 0xb0, 0x88, 0xe7, 0x18, + 0x42, 0xc6, 0x0d, 0x29, 0x72, 0xc5, 0xdd, 0xac, 0x54, 0x99, 0xc2, 0xcb, 0x85, 0x1f, 0x98, 0x07, 0xb6, 0xad, 0x3a, + 0xa2, 0x66, 0x27, 0x71, 0x95, 0x1a, 0xed, 0xe9, 0xf7, 0x69, 0x9b, 0x58, 0xa3, 0xe3, 0x33, 0xe3, 0xd7, 0xe8, 0xa3, + 0xf6, 0xe2, 0xb1, 0x06, 0xe6, 0x22, 0x8b, 0x12, 0xf6, 0x25, 0xc8, 0x39, 0x52, 0x4c, 0x7d, 0xef, 0x26, 0x96, 0xfe, + 0x0c, 0x6c, 0xd0, 0x5e, 0xd3, 0x4a, 0xaa, 0x0f, 0xdc, 0xa0, 0xdf, 0x1e, 0x0d, 0x1a, 0xf4, 0x12, 0xcf, 0x30, 0x77, + 0x09, 0x1e, 0xdf, 0xcc, 0x29, 0x51, 0xbf, 0x03, 0xf2, 0x72, 0xac, 0xc1, 0x16, 0x0b, 0xc2, 0x02, 0xc2, 0x88, 0xda, + 0xaf, 0xf7, 0x5f, 0x6a, 0xde, 0xe5, 0xeb, 0x39, 0x42, 0xac, 0x60, 0x3f, 0xa2, 0x9c, 0x8c, 0x77, 0x2a, 0x9a, 0x99, + 0x7b, 0x66, 0xde, 0xdf, 0xf3, 0x74, 0x4f, 0x37, 0x37, 0xf3, 0x4a, 0xeb, 0xb3, 0xee, 0xa9, 0x3e, 0x55, 0x91, 0x26, + 0x66, 0xf5, 0x65, 0x87, 0xf2, 0xc1, 0x3c, 0xb8, 0x73, 0x95, 0xed, 0xdc, 0x01, 0x1d, 0x74, 0xd6, 0x1d, 0xfc, 0x30, + 0xf7, 0x8a, 0x0f, 0x4d, 0x81, 0xd3, 0xff, 0x97, 0x80, 0x87, 0x06, 0x43, 0xd1, 0x92, 0x66, 0x8a, 0x79, 0x0d, 0x36, + 0x2f, 0xb4, 0x58, 0x89, 0x8d, 0xfb, 0x3d, 0x8d, 0xc7, 0x36, 0x9f, 0x2b, 0x94, 0x3d, 0xfc, 0x67, 0x0f, 0x05, 0x94, + 0xc5, 0x51, 0xcc, 0xce, 0x66, 0xa1, 0xa2, 0xd8, 0x25, 0xc0, 0x14, 0xc1, 0x77, 0x97, 0x2c, 0x36, 0x73, 0x42, 0x9b, + 0xaf, 0x60, 0xad, 0xe9, 0xd3, 0xc4, 0x74, 0xbe, 0x0a, 0x41, 0x05, 0xb3, 0x58, 0x33, 0xbc, 0x24, 0xe9, 0xa1, 0x23, + 0x35, 0xed, 0x63, 0x46, 0x3d, 0x35, 0x94, 0xd1, 0xd6, 0xfd, 0xad, 0xa7, 0x14, 0x1e, 0x49, 0x93, 0x0b, 0x5d, 0x93, + 0x50, 0x00, 0xff, 0x4f, 0xb5, 0x91, 0x4a, 0x93, 0x89, 0xb0, 0x59, 0x55, 0x64, 0xcb, 0xe9, 0xc8, 0x3f, 0xfe, 0xaa, + 0xd6, 0xc5, 0x90, 0xf8, 0xe1, 0x44, 0xdd, 0x93, 0x98, 0x83, 0x1c, 0xb4, 0x38, 0x85, 0x19, 0x68, 0x8d, 0x6c, 0x9b, + 0xa3, 0x9a, 0x25, 0x79, 0x79, 0x27, 0x81, 0xa7, 0x87, 0x26, 0xfa, 0xd5, 0x57, 0x69, 0xdb, 0xac, 0x3d, 0xef, 0x82, + 0x74, 0x00, 0xe1, 0xe0, 0x98, 0x19, 0x2f, 0x36, 0x7a, 0x7b, 0x09, 0xbe, 0xdf, 0x47, 0xb5, 0xb3, 0x0b, 0x94, 0x09, + 0xb5, 0x6f, 0x74, 0xe8, 0xf5, 0x6d, 0xae, 0x39, 0x61, 0x37, 0xa6, 0x32, 0xff, 0x28, 0x34, 0x4f, 0x67, 0xa5, 0xc7, + 0xc7, 0xdf, 0xa9, 0x9d, 0xe8, 0x18, 0x45, 0x4b, 0x82, 0xc4, 0xde, 0x82, 0x6a, 0xb4, 0xac, 0x35, 0xdb, 0x58, 0xf8, + 0x4c, 0x86, 0x05, 0xc6, 0x04, 0xdf, 0x26, 0xf3, 0xfe, 0x86, 0x48, 0x08, 0xf3, 0x85, 0x50, 0x1c, 0x4c, 0xdd, 0x69, + 0xbc, 0xd2, 0x5c, 0x2a, 0x5b, 0xd3, 0x25, 0xfe, 0xc1, 0xcc, 0x82, 0x42, 0xe6, 0x13, 0x05, 0xbf, 0xcc, 0xe1, 0xb8, + 0x6b, 0x84, 0xad, 0x67, 0x50, 0xf0, 0x81, 0x39, 0x0c, 0x10, 0x29, 0x8c, 0x6e, 0xeb, 0x29, 0x1e, 0x20, 0xb3, 0x2e, + 0x43, 0x9a, 0x61, 0xbf, 0x09, 0x18, 0x81, 0x57, 0x94, 0x37, 0x2b, 0xa0, 0xbc, 0x91, 0xe6, 0x6d, 0x57, 0x1e, 0x01, + 0xca, 0x5d, 0x48, 0x3a, 0x28, 0xa1, 0x17, 0x53, 0xfb, 0xa0, 0xb2, 0x7a, 0x82, 0x56, 0x31, 0x93, 0x1b, 0xac, 0xe6, + 0x46, 0x90, 0x49, 0x42, 0x1c, 0x9f, 0xd3, 0x80, 0xe1, 0x4e, 0xc2, 0x0b, 0xc4, 0x1c, 0x46, 0x04, 0xe9, 0xe4, 0x76, + 0xde, 0x2a, 0x53, 0x74, 0xe5, 0x42, 0xda, 0x22, 0x59, 0xe6, 0xa3, 0x06, 0xf2, 0x59, 0x82, 0x05, 0xf0, 0x0f, 0x0c, + 0x8a, 0x3d, 0x12, 0x36, 0x73, 0x2c, 0xb9, 0x86, 0x41, 0xa4, 0xf4, 0xf4, 0x56, 0x99, 0xa2, 0x0e, 0x57, 0x54, 0x42, + 0xc8, 0x0c, 0x98, 0xe0, 0x4b, 0x38, 0xbe, 0xd5, 0xa0, 0xc1, 0xd0, 0x9d, 0x82, 0xda, 0x67, 0xc0, 0x49, 0x53, 0x6a, + 0x96, 0xc4, 0x9e, 0x52, 0xf8, 0xd3, 0x8c, 0x45, 0xd8, 0x34, 0x0f, 0x94, 0xef, 0x9a, 0xa9, 0x62, 0xc1, 0x1b, 0xf9, + 0x13, 0xf8, 0x0e, 0x93, 0xae, 0x28, 0x81, 0xef, 0xe3, 0x61, 0xbc, 0xc3, 0x28, 0xc4, 0x3f, 0x66, 0xba, 0x0d, 0x09, + 0xcb, 0x62, 0x86, 0x00, 0xa4, 0xdf, 0xb8, 0x2b, 0x3e, 0x2c, 0xcf, 0x9a, 0x49, 0xe2, 0xd6, 0xef, 0xf7, 0xff, 0x69, + 0x20, 0xb3, 0x0f, 0x3d, 0x91, 0xcd, 0xe6, 0x30, 0x06, 0x14, 0x9d, 0x4c, 0xd8, 0xa3, 0x71, 0xe2, 0x41, 0x01, 0xd7, + 0xa3, 0x73, 0x5d, 0x49, 0x6d, 0x3d, 0xc4, 0x7b, 0x10, 0x26, 0xac, 0xac, 0x1a, 0xc5, 0xb3, 0xbf, 0x6f, 0xba, 0xe9, + 0xd4, 0x71, 0xa0, 0x80, 0xd9, 0x5f, 0x77, 0xaa, 0x43, 0x77, 0x77, 0x83, 0xc4, 0xb5, 0x44, 0xdb, 0x70, 0xc4, 0xfb, + 0xa1, 0x01, 0x4c, 0xd9, 0xc9, 0x79, 0x71, 0x1e, 0xa6, 0x97, 0xbf, 0x1c, 0x3a, 0x2a, 0x39, 0xeb, 0x12, 0x91, 0x49, + 0xb6, 0x92, 0x6c, 0xc6, 0x5e, 0xcc, 0xad, 0x8c, 0xfe, 0x84, 0x27, 0xe8, 0xac, 0xf3, 0x30, 0x0a, 0x0a, 0x15, 0xe1, + 0x2d, 0x80, 0xc2, 0x59, 0xb6, 0xe9, 0x74, 0xf0, 0x5a, 0xc4, 0x34, 0x08, 0xd7, 0x75, 0x07, 0x54, 0xfa, 0x96, 0x92, + 0x21, 0x33, 0x05, 0x70, 0x11, 0xc5, 0x58, 0x8c, 0x04, 0xa5, 0x8c, 0x23, 0x0e, 0x95, 0xf5, 0xed, 0xe6, 0x48, 0x61, + 0x10, 0x7d, 0xb4, 0x43, 0xd7, 0xa1, 0x45, 0xd1, 0x7f, 0x8b, 0x45, 0xc8, 0xf7, 0x14, 0xa7, 0x84, 0x9b, 0x34, 0x35, + 0xf9, 0xa1, 0x0f, 0x2f, 0x60, 0x71, 0x06, 0x46, 0x77, 0x67, 0xb7, 0x3c, 0x8a, 0xbb, 0x1b, 0xfa, 0x18, 0x7e, 0xd1, + 0xcf, 0x32, 0x3b, 0xa7, 0xa6, 0xf0, 0x55, 0xec, 0xe2, 0x7b, 0x22, 0x90, 0x63, 0xce, 0x36, 0xcc, 0xf3, 0x0f, 0xb6, + 0xaf, 0x05, 0x89, 0xd5, 0xad, 0xc0, 0x29, 0x05, 0xdb, 0x7a, 0xa5, 0x01, 0x9d, 0x5d, 0x89, 0xf0, 0xfe, 0x8d, 0xef, + 0x81, 0x16, 0x51, 0x49, 0x76, 0x8a, 0x47, 0x4e, 0x7f, 0x0b, 0xe2, 0xcc, 0x81, 0x9c, 0xa2, 0x7a, 0x32, 0x82, 0x5e, + 0x40, 0x5b, 0x3e, 0x8f, 0x2e, 0x39, 0x19, 0xd6, 0x45, 0xf9, 0x44, 0x7b, 0x8e, 0xc9, 0xce, 0xa2, 0x14, 0x86, 0xa4, + 0xf4, 0x3d, 0xcc, 0x06, 0x07, 0x20, 0x3b, 0xaa, 0x7e, 0x58, 0x24, 0x61, 0xf3, 0xce, 0x24, 0x33, 0x17, 0x21, 0x39, + 0xa7, 0xf5, 0xca, 0xbd, 0x88, 0xcc, 0x5c, 0x3b, 0x8a, 0xb2, 0x8e, 0xab, 0x49, 0xd2, 0xcd, 0x66, 0x96, 0x3a, 0xa5, + 0x1a, 0x63, 0x24, 0x21, 0xa3, 0x13, 0xaf, 0x7a, 0x91, 0x94, 0x41, 0xd6, 0x44, 0xc5, 0xb2, 0xa6, 0x21, 0x59, 0x04, + 0xf4, 0x21, 0xf6, 0xba, 0xa8, 0x5c, 0xd4, 0xae, 0xa2, 0x55, 0xa9, 0xb2, 0x73, 0x50, 0xcf, 0x73, 0x13, 0xf4, 0x40, + 0xca, 0x26, 0xbb, 0xdf, 0x6e, 0x45, 0x97, 0x90, 0x43, 0x67, 0x38, 0xad, 0x66, 0x20, 0x8c, 0x97, 0xb1, 0xd6, 0xb1, + 0x2f, 0x50, 0xd4, 0xc0, 0xb5, 0xd3, 0xa0, 0xcb, 0xdb, 0xad, 0xd1, 0xc5, 0xe4, 0x51, 0x60, 0x4a, 0x56, 0xe5, 0xd2, + 0x54, 0xe1, 0x6c, 0x9e, 0x5f, 0xf6, 0x77, 0xc6, 0xb7, 0x5d, 0x3a, 0x0e, 0x54, 0x30, 0xc3, 0xbb, 0x60, 0x0f, 0x13, + 0xaf, 0x71, 0x82, 0x9c, 0x98, 0x3a, 0xf6, 0x11, 0x21, 0xd1, 0x56, 0xff, 0x7a, 0xad, 0x99, 0xf9, 0x63, 0x3f, 0xa6, + 0xdc, 0x3d, 0xd0, 0xcb, 0x91, 0xdd, 0x6c, 0xe1, 0xa5, 0x7c, 0x58, 0x42, 0x7c, 0xe1, 0x6c, 0x2e, 0xdd, 0x66, 0xe8, + 0xd2, 0xe7, 0x2f, 0x87, 0x31, 0x15, 0x5b, 0x22, 0x39, 0x1c, 0x88, 0xcd, 0xed, 0x3a, 0x27, 0x49, 0x14, 0xf0, 0x3e, + 0xcf, 0x11, 0x01, 0xcf, 0x5c, 0xf6, 0x9c, 0x49, 0x94, 0x16, 0xe9, 0x68, 0xa4, 0x4f, 0xc7, 0xa0, 0xe2, 0x53, 0xa1, + 0x84, 0xc1, 0x7d, 0x66, 0x13, 0x83, 0xfc, 0xf9, 0xb1, 0x48, 0xb7, 0xa9, 0x31, 0x6c, 0xf8, 0x0a, 0x6e, 0x15, 0x54, + 0x7e, 0xff, 0x13, 0x8d, 0xbb, 0xe6, 0x87, 0xd5, 0xd1, 0x7b, 0xfc, 0x5c, 0x41, 0x1b, 0x3c, 0xba, 0x3a, 0x0f, 0xdb, + 0x78, 0x07, 0x80, 0xe6, 0xdc, 0x16, 0x4c, 0x11, 0x6c, 0xbc, 0x75, 0x89, 0x5f, 0x86, 0xa4, 0xd6, 0xf8, 0x84, 0x40, + 0x7d, 0x36, 0xcc, 0xc3, 0xe4, 0x7d, 0xf2, 0x23, 0x1c, 0x99, 0x67, 0xa7, 0x04, 0xbc, 0x51, 0x76, 0xe5, 0x91, 0x7e, + 0x94, 0xa7, 0xbb, 0x2f, 0xbe, 0x9f, 0x5b, 0x58, 0x7f, 0x80, 0xe3, 0xf8, 0x45, 0xfd, 0xfd, 0xf0, 0x90, 0xed, 0x0f, + 0x5b, 0xff, 0xfd, 0x89, 0x92, 0xdf, 0x2a, 0x0d, 0xde, 0xfc, 0xf1, 0x42, 0x08, 0x4e, 0x0d, 0x6a, 0x98, 0xc5, 0xc8, + 0x70, 0xe9, 0x17, 0x51, 0x8a, 0x49, 0xd6, 0x18, 0xad, 0xa4, 0xa5, 0x85, 0xf7, 0x4a, 0x9b, 0xb3, 0x2b, 0xb7, 0x57, + 0x05, 0x71, 0x67, 0x69, 0xea, 0x83, 0x02, 0x93, 0x51, 0x45, 0xe0, 0x48, 0xa1, 0x6a, 0x2d, 0x61, 0x91, 0xfa, 0x8d, + 0x80, 0xae, 0xd5, 0x6b, 0x65, 0x60, 0x9c, 0xaf, 0x77, 0xb6, 0xc9, 0x3c, 0x23, 0x5b, 0xd0, 0x3c, 0xf2, 0xd2, 0x9a, + 0xb7, 0x22, 0xaa, 0xaa, 0xd6, 0x1d, 0xb6, 0x7a, 0x11, 0x23, 0xd6, 0xdd, 0x3c, 0x05, 0xc6, 0x3b, 0xc2, 0x03, 0xdc, + 0xdc, 0x30, 0x0a, 0xed, 0x56, 0x4f, 0xca, 0xd3, 0xec, 0xdd, 0x21, 0xdd, 0x68, 0x32, 0x85, 0xc6, 0x82, 0x2d, 0x5d, + 0x45, 0x87, 0xc4, 0x31, 0xe5, 0x90, 0x90, 0x33, 0xb4, 0x6f, 0xb0, 0x64, 0xd3, 0xa9, 0xda, 0x0c, 0xd7, 0x68, 0xc7, + 0x13, 0x0d, 0x31, 0x1d, 0x74, 0x45, 0x3a, 0x44, 0x0f, 0xc0, 0x14, 0x33, 0x9e, 0x26, 0x1d, 0x2d, 0xec, 0xae, 0xd5, + 0x88, 0x33, 0x4a, 0x07, 0xa3, 0x81, 0x51, 0xa2, 0xab, 0xe8, 0xf5, 0x0d, 0x42, 0xe7, 0x44, 0x76, 0x7b, 0xca, 0x5b, + 0xa5, 0x86, 0xf5, 0x99, 0xa1, 0x75, 0xa9, 0x12, 0x61, 0xa5, 0x38, 0xb1, 0xec, 0xae, 0x4c, 0xfb, 0x4a, 0x8b, 0xab, + 0xdc, 0xd0, 0xb6, 0x01, 0x50, 0x3d, 0x2d, 0xf1, 0x7a, 0xf2, 0x9a, 0xaf, 0xf6, 0xf4, 0xa4, 0x4d, 0x9f, 0x5b, 0x50, + 0xd3, 0x2e, 0x05, 0xe6, 0xf5, 0x6e, 0xa3, 0xee, 0x2b, 0xd3, 0xf0, 0xae, 0x2a, 0x26, 0x89, 0xbf, 0xb4, 0x0f, 0x71, + 0xa5, 0x43, 0xd2, 0xb0, 0x17, 0x5d, 0xc1, 0x6a, 0x71, 0x09, 0x9b, 0xf2, 0x04, 0x04, 0x46, 0x4b, 0x5a, 0x52, 0x70, + 0x83, 0xaa, 0xa2, 0xaf, 0x84, 0x57, 0xcf, 0xa7, 0xd3, 0x14, 0xac, 0xfb, 0xcd, 0xc4, 0x26, 0x8b, 0x3e, 0xcf, 0x5d, + 0x59, 0x73, 0xde, 0x1b, 0x1e, 0x55, 0x1d, 0xdb, 0x9c, 0x02, 0x74, 0xb7, 0xd3, 0x16, 0xda, 0xe2, 0x47, 0xb6, 0xc9, + 0x34, 0x6a, 0xad, 0x15, 0x95, 0xfc, 0xcc, 0x3b, 0xae, 0xfc, 0x2b, 0x65, 0xab, 0x02, 0xd5, 0x26, 0x24, 0x26, 0xe6, + 0xa3, 0x15, 0x88, 0x1d, 0x74, 0x3e, 0xe6, 0x2f, 0x74, 0x95, 0x2c, 0xce, 0x78, 0x6e, 0x72, 0x64, 0x52, 0x63, 0x78, + 0x68, 0x42, 0xd1, 0xf6, 0x71, 0xb0, 0xe9, 0x60, 0xed, 0x2f, 0xe9, 0xd4, 0xbc, 0x26, 0x0a, 0xfe, 0x9c, 0x08, 0x3b, + 0x41, 0xe3, 0xcb, 0x98, 0xe8, 0xd2, 0xe6, 0xa7, 0xfc, 0xad, 0xdb, 0x07, 0xd9, 0x7a, 0x05, 0xab, 0xf5, 0xd0, 0xea, + 0xf6, 0xec, 0x22, 0x3c, 0x37, 0x44, 0x59, 0x9f, 0x72, 0x8d, 0x79, 0xbd, 0x8a, 0x0d, 0x24, 0x8f, 0xc8, 0x41, 0x85, + 0x57, 0x4e, 0x3f, 0x06, 0x05, 0xe0, 0xe7, 0x4d, 0x76, 0x84, 0x5f, 0xb5, 0x30, 0x0f, 0xfb, 0x04, 0x56, 0x8e, 0x07, + 0x8f, 0x6e, 0x3a, 0x73, 0x5e, 0x43, 0x58, 0x20, 0x7f, 0x39, 0x4f, 0xc6, 0x23, 0xc6, 0xb2, 0x43, 0xea, 0x8a, 0xb4, + 0x27, 0x00, 0x90, 0x52, 0x34, 0x1c, 0x44, 0xc5, 0xc6, 0xc9, 0x0f, 0x94, 0xa6, 0x05, 0x44, 0x81, 0x3a, 0x9d, 0x71, + 0x0c, 0xd4, 0x0d, 0xda, 0xb1, 0x6d, 0x66, 0x4b, 0x8d, 0xc5, 0x6b, 0xb4, 0x9f, 0x9a, 0xf4, 0x2c, 0xba, 0x04, 0x6f, + 0xd1, 0x22, 0xc6, 0x2f, 0xc6, 0xb4, 0x66, 0x8b, 0x1b, 0xfd, 0xc4, 0x4e, 0xc0, 0x8d, 0xd1, 0x6d, 0x9c, 0xdd, 0xb2, + 0xb3, 0x44, 0xa5, 0x37, 0xdf, 0x40, 0xf0, 0xae, 0xb7, 0x5b, 0xbb, 0xb1, 0xd2, 0xfe, 0x33, 0x05, 0xe3, 0x2a, 0x99, + 0x1b, 0x88, 0x20, 0x55, 0x8f, 0x96, 0xfc, 0x59, 0x20, 0xb1, 0xf5, 0x5c, 0xda, 0x5a, 0x00, 0x83, 0xef, 0xf6, 0xe1, + 0x35, 0xd3, 0xb3, 0x96, 0xc3, 0x6a, 0xf0, 0xbd, 0x6f, 0xdf, 0x8c, 0xd6, 0xc7, 0x74, 0xb7, 0xbd, 0xdb, 0xc7, 0x0e, + 0x7d, 0x52, 0x4a, 0x89, 0x1b, 0x00, 0xce, 0x7d, 0xbe, 0x83, 0x49, 0xb6, 0xd9, 0x6b, 0x96, 0x0a, 0x9e, 0xab, 0xdd, + 0x9e, 0x30, 0x40, 0xdc, 0xcf, 0xb9, 0xde, 0x48, 0x18, 0xc1, 0x31, 0xe7, 0x75, 0xf3, 0x92, 0x64, 0xcc, 0x20, 0x8d, + 0x8d, 0xa1, 0x83, 0xba, 0xb6, 0x15, 0xb0, 0x20, 0xca, 0x89, 0x0b, 0x3e, 0x2d, 0x86, 0x0d, 0x22, 0x95, 0x19, 0x4d, + 0x44, 0x41, 0x35, 0x44, 0xf7, 0x72, 0xf0, 0xda, 0x81, 0x8e, 0x13, 0x07, 0x03, 0xe6, 0x5f, 0x7d, 0x02, 0xdb, 0xc7, + 0x0e, 0xb7, 0x07, 0x85, 0x38, 0xf6, 0x82, 0xa4, 0x22, 0x9d, 0xb6, 0x2e, 0x99, 0xeb, 0xe0, 0xad, 0xab, 0x96, 0x66, + 0x6f, 0xaa, 0x0f, 0xd4, 0xd7, 0xd0, 0xe3, 0x78, 0xea, 0xe7, 0x83, 0xb9, 0x03, 0xab, 0xa2, 0x2e, 0xca, 0x04, 0xc0, + 0x75, 0x6d, 0x28, 0x6d, 0x6b, 0x20, 0x60, 0x33, 0x79, 0x5a, 0x49, 0xe6, 0x0a, 0x2f, 0xe7, 0x66, 0xf3, 0x33, 0x9f, + 0x23, 0xf4, 0x9a, 0xf7, 0xab, 0xb7, 0xaa, 0xf6, 0x79, 0x69, 0x1e, 0x9e, 0xaa, 0x42, 0x05, 0xaa, 0x59, 0x67, 0xec, + 0x79, 0x06, 0x1b, 0x24, 0xc8, 0xd6, 0xb8, 0xed, 0xe3, 0xe1, 0x6f, 0x26, 0x16, 0xd3, 0x85, 0x6d, 0xe8, 0x25, 0x26, + 0x6f, 0xbf, 0xcb, 0x6c, 0x01, 0xa4, 0x48, 0x49, 0x7d, 0xc6, 0x97, 0x8c, 0x68, 0x52, 0xaf, 0x97, 0x5a, 0xd5, 0xf8, + 0x48, 0xab, 0x56, 0xfb, 0x07, 0x86, 0xac, 0x9f, 0x7f, 0xf4, 0x4f, 0xc6, 0x6e, 0x2f, 0xfe, 0x7d, 0xf3, 0xe4, 0xb5, + 0xdb, 0xc7, 0xd6, 0x62, 0xeb, 0x3f, 0x76, 0x26, 0xea, 0x86, 0x9e, 0xe7, 0xb5, 0x7f, 0xb7, 0x0a, 0x34, 0x78, 0x4f, + 0x85, 0x2f, 0x0c, 0x83, 0x3b, 0xf9, 0x66, 0x80, 0x17, 0x90, 0xad, 0xcc, 0xa2, 0xad, 0x83, 0x6b, 0x5c, 0xe3, 0xff, + 0xb8, 0x42, 0x8c, 0xe9, 0xa5, 0xda, 0x78, 0x80, 0xfe, 0xbc, 0xa3, 0xe5, 0xa6, 0xc1, 0xb7, 0x1d, 0x36, 0x65, 0x9e, + 0x89, 0x0b, 0xeb, 0x87, 0x75, 0x4a, 0x9a, 0x6b, 0x8e, 0xd7, 0x4d, 0xe7, 0xdd, 0x25, 0x8f, 0xa6, 0x30, 0xe0, 0x32, + 0x97, 0xa1, 0xdb, 0x5c, 0x38, 0x74, 0xbe, 0x89, 0xad, 0x9f, 0x54, 0xa2, 0xd2, 0x54, 0x02, 0x55, 0xfd, 0xda, 0x52, + 0x45, 0x19, 0xea, 0xd8, 0xfa, 0xb7, 0x0d, 0x2f, 0x56, 0xe5, 0xde, 0xc4, 0x03, 0xcc, 0xc8, 0x56, 0x20, 0x86, 0x0b, + 0x7e, 0x86, 0xa9, 0x35, 0xae, 0x1c, 0x68, 0xcc, 0x0e, 0xff, 0x8b, 0x48, 0x2a, 0x41, 0x40, 0x5b, 0x38, 0xd8, 0xc7, + 0xcc, 0xb8, 0x27, 0x3a, 0xa6, 0x0e, 0x3a, 0xb3, 0x93, 0x0f, 0x4e, 0x71, 0xf0, 0x5d, 0xbb, 0xdb, 0xa1, 0xdb, 0x0c, + 0xdb, 0x3b, 0x45, 0x4f, 0x9d, 0x14, 0x5b, 0x49, 0xe1, 0xae, 0xae, 0xa8, 0x1d, 0xe9, 0x74, 0xbe, 0x76, 0x57, 0x08, + 0x6a, 0x76, 0x05, 0xd1, 0x34, 0xbe, 0x36, 0x9e, 0x68, 0x72, 0xf0, 0x17, 0xfe, 0x25, 0x24, 0xf0, 0x65, 0x6f, 0x62, + 0x90, 0xbe, 0xce, 0xd0, 0x5d, 0xba, 0x8a, 0xee, 0x42, 0xba, 0xaa, 0x1f, 0x61, 0x15, 0xb3, 0x1f, 0xc1, 0x7d, 0xa2, + 0xf7, 0xe2, 0xcd, 0x86, 0xa1, 0xb1, 0xc2, 0x64, 0x68, 0x73, 0x1b, 0x32, 0xcc, 0xf9, 0x6d, 0x48, 0xd1, 0xc6, 0xa6, + 0x1b, 0x90, 0x57, 0xe4, 0x64, 0x76, 0x4d, 0x94, 0x4d, 0x97, 0x2e, 0x22, 0x38, 0x08, 0xf7, 0xa1, 0x9a, 0xd0, 0x9e, + 0x3d, 0x09, 0x3e, 0xcd, 0xca, 0x34, 0x61, 0xa9, 0xe6, 0x72, 0x5c, 0x20, 0x33, 0xd9, 0xc4, 0x00, 0xe6, 0xc3, 0xd8, + 0xe5, 0xb3, 0xc7, 0x1d, 0xd8, 0x7b, 0xb1, 0xe3, 0xa1, 0xdb, 0x1e, 0x94, 0xed, 0xa3, 0x83, 0xd5, 0xe7, 0xf3, 0xfe, + 0x2a, 0xb3, 0xdd, 0xeb, 0xbd, 0x74, 0x1b, 0x66, 0xe9, 0x31, 0xcf, 0x66, 0x8b, 0xa5, 0x9e, 0xdf, 0x20, 0xaf, 0x66, + 0xa7, 0x4a, 0x71, 0x29, 0x9e, 0x00, 0xf0, 0xbb, 0xac, 0xe1, 0x07, 0x92, 0x16, 0xcf, 0xea, 0xf4, 0xfc, 0x48, 0x9b, + 0xb6, 0x92, 0xc5, 0x10, 0x10, 0x9d, 0xca, 0x29, 0xea, 0xc6, 0xd6, 0x66, 0x50, 0xa4, 0xd3, 0xee, 0xcc, 0x66, 0x48, + 0xe1, 0x59, 0xf9, 0xcf, 0x66, 0xce, 0x3e, 0x74, 0xd2, 0xa0, 0xdc, 0x1e, 0x1c, 0xdc, 0x2a, 0x95, 0x49, 0x47, 0xa2, + 0xf0, 0x52, 0x51, 0x20, 0x44, 0x10, 0xe7, 0x41, 0xaf, 0xbc, 0xa4, 0x35, 0xa2, 0x62, 0x4d, 0x88, 0x1f, 0xb5, 0x06, + 0xd7, 0xe0, 0xd6, 0xfe, 0xf6, 0x3c, 0xc0, 0x0d, 0x1c, 0x72, 0x94, 0xf7, 0x29, 0xcf, 0x9b, 0xdc, 0xb1, 0xa2, 0xfb, + 0x89, 0xc1, 0x5c, 0x03, 0x03, 0x2a, 0x29, 0xdf, 0x2b, 0x6e, 0xc6, 0x98, 0x3f, 0xfd, 0x7e, 0x15, 0xc2, 0x4a, 0x7d, + 0xb1, 0xca, 0x61, 0x07, 0xe4, 0xdb, 0xaf, 0x20, 0x68, 0x51, 0x36, 0x51, 0xf8, 0x9a, 0xaf, 0xf0, 0xec, 0xd6, 0x66, + 0xa9, 0xff, 0xc7, 0x3d, 0x49, 0xcd, 0x5c, 0xfc, 0xbb, 0x4b, 0x47, 0x8d, 0x6f, 0x36, 0x7e, 0xa5, 0x5b, 0x99, 0xd5, + 0x48, 0x51, 0xd6, 0xae, 0xc9, 0x46, 0xf3, 0x33, 0x30, 0x4e, 0xd0, 0x8b, 0xaf, 0xd8, 0x81, 0x9f, 0x77, 0x49, 0xaa, + 0xd2, 0xad, 0xa5, 0x9f, 0xfb, 0x2b, 0xc9, 0x78, 0xca, 0xe8, 0x57, 0x19, 0x6e, 0x14, 0x34, 0x27, 0x5f, 0xfa, 0x3f, + 0x0c, 0xe0, 0x1d, 0x28, 0xc3, 0xd9, 0x0a, 0x7f, 0xad, 0xe3, 0x2e, 0x7e, 0xdd, 0x85, 0x9b, 0xf9, 0xb2, 0x11, 0x06, + 0xda, 0x43, 0x20, 0xa7, 0xea, 0xf7, 0x39, 0x9e, 0xb8, 0x0c, 0xd3, 0x99, 0x26, 0xbc, 0x8a, 0x82, 0xe5, 0xce, 0x7b, + 0xed, 0x9b, 0x34, 0x1b, 0x8f, 0x17, 0x24, 0x16, 0x27, 0x78, 0x45, 0xd8, 0xea, 0x42, 0xc9, 0xb7, 0xb9, 0x85, 0xa6, + 0xc0, 0x2b, 0xdd, 0xec, 0x41, 0xda, 0x2f, 0x93, 0x9d, 0x25, 0xab, 0x9e, 0x33, 0x84, 0x11, 0x1b, 0x7b, 0x74, 0x95, + 0x26, 0xf5, 0x59, 0x69, 0x8d, 0x36, 0x34, 0x63, 0x4d, 0xa7, 0xe6, 0x72, 0x40, 0xaa, 0x55, 0xb5, 0xc2, 0x59, 0x57, + 0xb9, 0xc0, 0x36, 0x73, 0x4a, 0xd1, 0x67, 0x07, 0x05, 0x9e, 0x25, 0xac, 0xeb, 0x1c, 0xb8, 0x86, 0x12, 0x0d, 0xce, + 0x6b, 0x76, 0xdb, 0x80, 0xac, 0x44, 0x7e, 0x61, 0x40, 0x09, 0x1b, 0x8f, 0x7f, 0xb1, 0x43, 0xf1, 0xed, 0xd9, 0x6a, + 0x19, 0xc1, 0xc8, 0x8a, 0x49, 0xfd, 0x9d, 0x23, 0xb1, 0x3f, 0x3f, 0xa3, 0xb4, 0xb7, 0x5c, 0x4c, 0xa8, 0x5b, 0x36, + 0xab, 0xd8, 0x6f, 0xa5, 0x84, 0xa3, 0x69, 0xaa, 0x96, 0x78, 0x7a, 0x1f, 0x29, 0xab, 0xd6, 0x5b, 0xc0, 0x06, 0x2d, + 0xaa, 0x36, 0x22, 0x5e, 0x30, 0x21, 0x7e, 0xff, 0xc1, 0x46, 0x80, 0x47, 0xa4, 0x64, 0xb2, 0xe5, 0x38, 0xab, 0x14, + 0xc3, 0xf9, 0xe6, 0x63, 0xb3, 0x5d, 0x4f, 0x58, 0xe4, 0x23, 0x8c, 0x58, 0xb7, 0x54, 0xc1, 0xba, 0x1f, 0xf6, 0x24, + 0xf5, 0xe8, 0x39, 0x3a, 0xc2, 0x61, 0x54, 0x41, 0x2b, 0x7a, 0x73, 0xf6, 0x0a, 0x49, 0x53, 0xc8, 0x44, 0x90, 0x7c, + 0x18, 0x97, 0x62, 0xc8, 0xad, 0x7d, 0x23, 0x4f, 0x95, 0xef, 0x1b, 0x30, 0x54, 0xde, 0xb7, 0x84, 0x26, 0xc8, 0x9a, + 0x9f, 0xa2, 0xa2, 0xe7, 0xce, 0x6e, 0x45, 0xb0, 0x5a, 0x74, 0x72, 0x52, 0x95, 0x69, 0x7e, 0x02, 0xa1, 0x65, 0x2e, + 0xc8, 0x66, 0xbf, 0xae, 0x86, 0xfc, 0xe8, 0xe4, 0xbc, 0x8d, 0x19, 0x67, 0x33, 0x64, 0x1b, 0x2b, 0xce, 0x94, 0xd3, + 0xe2, 0x5b, 0x73, 0xb7, 0x87, 0xbc, 0xec, 0xae, 0x03, 0x05, 0x0f, 0x87, 0x12, 0x9a, 0xf1, 0xe7, 0xea, 0x9f, 0x27, + 0x41, 0x55, 0xe5, 0x84, 0x36, 0xfe, 0x59, 0x7c, 0xc6, 0xe7, 0x6a, 0xc1, 0x97, 0x70, 0xd8, 0x31, 0x00, 0x54, 0x02, + 0xeb, 0x62, 0xa8, 0xfd, 0x54, 0x80, 0xdd, 0xef, 0x0d, 0x69, 0x7c, 0xef, 0x9c, 0xa4, 0x59, 0xd8, 0xc7, 0xae, 0xbd, + 0x69, 0x72, 0x90, 0xa3, 0xed, 0x5a, 0x85, 0x37, 0xea, 0xab, 0x3e, 0xd6, 0x33, 0xcb, 0xf0, 0x03, 0x08, 0x2d, 0xcd, + 0x25, 0x90, 0x63, 0x18, 0x83, 0x7e, 0xf1, 0xe6, 0x7f, 0xfd, 0x02, 0x5c, 0x40, 0xb0, 0x45, 0xc1, 0xf3, 0x6d, 0xaf, + 0x7c, 0xc2, 0xb4, 0x94, 0x4a, 0x21, 0x38, 0x67, 0xfd, 0x47, 0xb0, 0x21, 0x2e, 0xed, 0x4e, 0x6d, 0x32, 0x61, 0x38, + 0x25, 0x15, 0xd1, 0x06, 0x8d, 0xd9, 0xce, 0x73, 0x4e, 0xf3, 0x60, 0xf3, 0xcf, 0x82, 0x8b, 0x92, 0xef, 0x9b, 0x99, + 0x9e, 0x3d, 0x50, 0x75, 0xe6, 0xda, 0x6a, 0x7a, 0x82, 0x1e, 0xa4, 0xce, 0x5f, 0x8b, 0x65, 0xac, 0xee, 0x77, 0x4b, + 0x4a, 0x22, 0x1b, 0x13, 0x0a, 0x36, 0xb4, 0xa1, 0xbb, 0x26, 0x88, 0x39, 0x8d, 0x6b, 0xbb, 0x15, 0xfd, 0xde, 0x89, + 0x66, 0x20, 0xdd, 0x28, 0x87, 0x65, 0x98, 0x32, 0x84, 0xe4, 0x96, 0xf1, 0x1d, 0x59, 0x97, 0x5d, 0xd9, 0x58, 0x84, + 0xb2, 0x7f, 0xb7, 0xe5, 0x70, 0x4a, 0xa1, 0x6a, 0xd4, 0x17, 0x60, 0x48, 0x89, 0x69, 0x9b, 0x2c, 0x8b, 0xb8, 0xb3, + 0x05, 0x05, 0xcd, 0x94, 0x8d, 0x9d, 0xda, 0x75, 0x84, 0x21, 0x73, 0xf8, 0x35, 0xb2, 0x27, 0x1d, 0x99, 0xa7, 0xc8, + 0x65, 0x93, 0x9e, 0xf5, 0xfa, 0x73, 0x07, 0x28, 0x6c, 0x5f, 0xe0, 0x94, 0x3c, 0xcf, 0x69, 0xaa, 0xa1, 0x96, 0x1b, + 0xd2, 0x45, 0x51, 0x25, 0x38, 0x3a, 0x27, 0x78, 0x81, 0x23, 0x84, 0xca, 0x96, 0x92, 0xa0, 0x1e, 0x0f, 0xa1, 0x4a, + 0x24, 0x47, 0xc7, 0x09, 0xcc, 0x75, 0xbc, 0x9a, 0x6b, 0xfc, 0x37, 0x24, 0x8f, 0x36, 0x7e, 0x80, 0xb8, 0x96, 0xd9, + 0xc8, 0xc7, 0x43, 0x6a, 0x98, 0xc2, 0x58, 0x1f, 0x29, 0xf8, 0x6a, 0x1a, 0xc2, 0xa2, 0xc9, 0x40, 0x1a, 0x18, 0x9c, + 0x02, 0xff, 0x2d, 0x5c, 0x33, 0x56, 0x5e, 0xb9, 0x0e, 0x15, 0xab, 0xb4, 0x6b, 0xfa, 0x55, 0xff, 0xcc, 0xd8, 0x8b, + 0xa8, 0x6f, 0x77, 0x18, 0x7b, 0x96, 0x6a, 0x05, 0x3f, 0xcf, 0xb5, 0x61, 0x7c, 0x37, 0x74, 0x9a, 0x74, 0x9e, 0x53, + 0x5f, 0x39, 0x70, 0x51, 0x6c, 0xa2, 0x68, 0x33, 0x7a, 0x4d, 0x9d, 0x9a, 0x25, 0x9c, 0xea, 0xb8, 0x49, 0xb2, 0x2e, + 0x31, 0x8e, 0xa4, 0x17, 0xfb, 0xfa, 0x46, 0x63, 0xaa, 0x68, 0x25, 0xbe, 0x53, 0x51, 0xae, 0x80, 0xb3, 0x10, 0x84, + 0x56, 0xec, 0x89, 0x57, 0xcb, 0xca, 0x4a, 0x7c, 0xa4, 0x05, 0xf3, 0x46, 0x54, 0x20, 0xc8, 0x13, 0xd2, 0x3a, 0x71, + 0x27, 0x46, 0x66, 0x15, 0x72, 0xb7, 0x21, 0xc9, 0x08, 0x11, 0x5d, 0xb0, 0x97, 0xd0, 0xdb, 0xa5, 0xab, 0xb3, 0xa7, + 0x00, 0x2f, 0x10, 0x23, 0xfa, 0x07, 0xd3, 0xc2, 0x72, 0xd4, 0x4e, 0x94, 0xe8, 0x4e, 0xf6, 0x6f, 0x36, 0xff, 0x7e, + 0xac, 0x4a, 0x50, 0xa8, 0xbd, 0x0e, 0x01, 0xb3, 0x16, 0x93, 0x9e, 0xa4, 0x6d, 0x93, 0x02, 0x28, 0x96, 0xa0, 0x0d, + 0x7e, 0x5d, 0x0d, 0xa4, 0xbb, 0xf6, 0xde, 0x97, 0x46, 0x4c, 0xb8, 0x7c, 0x96, 0x92, 0x57, 0x19, 0xd5, 0x32, 0x7b, + 0xde, 0xb5, 0x17, 0x94, 0x96, 0xc0, 0xd5, 0x2f, 0x31, 0xa7, 0x3f, 0xef, 0x60, 0x46, 0x26, 0xc4, 0xb4, 0x67, 0xcc, + 0xcb, 0x66, 0x3d, 0xa6, 0xbe, 0xad, 0x63, 0xb1, 0xb5, 0x59, 0x3b, 0x7c, 0xf0, 0xc7, 0xd1, 0x9d, 0xa2, 0x35, 0xee, + 0x9f, 0xcb, 0x7f, 0xdb, 0x70, 0xdf, 0x7a, 0x67, 0xab, 0xd0, 0x5c, 0x5d, 0x27, 0xdb, 0xe8, 0xbe, 0x57, 0x3b, 0xc7, + 0x8a, 0x58, 0x7c, 0x1b, 0x63, 0xd7, 0x1d, 0xa0, 0xe3, 0xbb, 0x46, 0x81, 0xfb, 0x13, 0xd8, 0xe5, 0xf3, 0xe3, 0xf3, + 0x6a, 0x41, 0x8c, 0x23, 0xd9, 0x7a, 0x36, 0xf3, 0x0f, 0x97, 0x44, 0x77, 0xb7, 0xf4, 0x1e, 0x45, 0x20, 0xfa, 0x3e, + 0xa9, 0x97, 0x75, 0x26, 0xe3, 0x0b, 0xf2, 0xc8, 0xea, 0x15, 0xf8, 0xcd, 0x74, 0xd7, 0x1e, 0xdb, 0x89, 0x33, 0xc7, + 0xe6, 0x97, 0xcf, 0xf0, 0x48, 0x90, 0xe1, 0x9c, 0x21, 0xc6, 0x29, 0xea, 0xf8, 0x51, 0x2f, 0xe6, 0x4c, 0x3e, 0x92, + 0x02, 0xbe, 0xde, 0x74, 0x4e, 0x71, 0xa8, 0xa6, 0x30, 0x17, 0x1a, 0x4d, 0x3a, 0xb1, 0x8f, 0x14, 0x00, 0xda, 0x9e, + 0x98, 0x12, 0x33, 0x71, 0x39, 0xbd, 0x01, 0x75, 0xbd, 0x07, 0x29, 0x95, 0xf3, 0x17, 0x31, 0x99, 0x71, 0xea, 0x39, + 0x98, 0x55, 0x7d, 0x51, 0xcc, 0x3f, 0xc1, 0xcc, 0xd4, 0xa8, 0x4d, 0x01, 0x4f, 0x8b, 0x19, 0x35, 0x3d, 0xb6, 0xdf, + 0x08, 0x49, 0xda, 0x6b, 0x96, 0x70, 0xb1, 0x33, 0x3e, 0x77, 0x50, 0x0a, 0xff, 0x56, 0x01, 0x3c, 0xa3, 0xd5, 0x67, + 0x55, 0xf2, 0x1c, 0x50, 0x16, 0xc3, 0xf6, 0xa5, 0x17, 0x7b, 0x1a, 0x5f, 0x05, 0xd7, 0x9f, 0x15, 0xc4, 0x56, 0xfc, + 0xfb, 0x97, 0x9b, 0xbe, 0xae, 0xf6, 0x16, 0xa2, 0x4f, 0x9d, 0x85, 0x27, 0x27, 0xbc, 0xde, 0x09, 0xe2, 0x74, 0x83, + 0xfd, 0x29, 0x6b, 0x89, 0xc1, 0xc9, 0x82, 0x7f, 0x6c, 0x45, 0x11, 0xaa, 0x8e, 0xfa, 0x98, 0xc5, 0x9d, 0x84, 0x2c, + 0x2b, 0x18, 0x86, 0x91, 0x41, 0xa6, 0x03, 0xfc, 0xd9, 0x97, 0xea, 0x8b, 0x8b, 0x68, 0xe0, 0xa5, 0x35, 0xfb, 0x9d, + 0x4f, 0xe1, 0x58, 0xd1, 0x85, 0x4f, 0xe1, 0xa7, 0x77, 0xa1, 0x02, 0x6c, 0x7d, 0x2d, 0x93, 0x33, 0x49, 0xf4, 0x65, + 0xd8, 0x57, 0x0c, 0x97, 0x34, 0x25, 0x8f, 0xbb, 0xa8, 0x92, 0xf3, 0xbf, 0xca, 0x75, 0x3f, 0xa3, 0x2f, 0xa9, 0xc6, + 0x3a, 0x0a, 0x46, 0xdd, 0xd5, 0x36, 0xa5, 0x77, 0x9c, 0x29, 0x29, 0xca, 0xd5, 0x0b, 0x4d, 0xfb, 0xfa, 0x93, 0xab, + 0xaf, 0xf4, 0x55, 0xd2, 0x4e, 0x35, 0x7a, 0xc2, 0x4b, 0x75, 0xd3, 0x81, 0x7f, 0xcb, 0xc9, 0xbd, 0x78, 0x2b, 0x35, + 0xb2, 0x37, 0xfd, 0x0f, 0xb6, 0x5d, 0x93, 0x73, 0x25, 0x4e, 0xb9, 0x60, 0x07, 0xe5, 0xd0, 0xe5, 0x38, 0x9e, 0xc4, + 0xb6, 0x55, 0x34, 0x8a, 0x2d, 0xe5, 0x96, 0x05, 0xce, 0x8d, 0x79, 0x22, 0x13, 0x24, 0x6a, 0x19, 0xae, 0x19, 0x5e, + 0x53, 0x80, 0x70, 0xba, 0x94, 0xe0, 0x66, 0xc0, 0x74, 0xea, 0x76, 0x4c, 0xe4, 0x74, 0xec, 0x35, 0x7e, 0x68, 0x84, + 0x10, 0x95, 0x72, 0xbe, 0x4d, 0x19, 0x51, 0xf5, 0x59, 0x76, 0x57, 0xf2, 0x56, 0x29, 0xd1, 0xb6, 0xea, 0x98, 0x8b, + 0x72, 0x60, 0xd1, 0x0b, 0x06, 0xad, 0x9c, 0x39, 0x89, 0xf5, 0xe9, 0x39, 0x69, 0xe3, 0x7f, 0xd9, 0x89, 0x1d, 0xe6, + 0xc8, 0xfb, 0x28, 0x75, 0x67, 0x0c, 0xe2, 0x9b, 0x3a, 0x49, 0x82, 0xbe, 0xb8, 0xea, 0x06, 0x4e, 0x59, 0x9c, 0x9a, + 0x5a, 0x5d, 0x03, 0xb0, 0x45, 0x0b, 0xad, 0x3e, 0x50, 0xf5, 0x40, 0xec, 0x57, 0xb5, 0xc1, 0x5f, 0x2b, 0x5e, 0xa6, + 0xf3, 0xb4, 0x0f, 0x15, 0x6b, 0xa4, 0x03, 0x43, 0x0e, 0xee, 0x4c, 0xb0, 0x06, 0xa1, 0x40, 0xc9, 0xe2, 0x5c, 0xc9, + 0x23, 0x8c, 0x8d, 0xe3, 0x88, 0xb5, 0x04, 0xc5, 0x94, 0xb7, 0x7d, 0x60, 0x07, 0x17, 0x88, 0x6e, 0xc4, 0x85, 0x65, + 0x1b, 0x51, 0xb4, 0x20, 0x29, 0x4a, 0x8e, 0x15, 0xea, 0x05, 0xdf, 0x08, 0xb1, 0x18, 0xc0, 0x5c, 0xd2, 0x37, 0x8b, + 0x89, 0x82, 0x0a, 0xc6, 0xe1, 0x0d, 0xfe, 0x6d, 0xe2, 0x12, 0xa1, 0x2f, 0xc4, 0x6b, 0xe3, 0x5b, 0x32, 0x5f, 0x60, + 0x4f, 0xa7, 0x20, 0xeb, 0x25, 0xbe, 0xdd, 0x7c, 0xf6, 0x1b, 0x56, 0xbf, 0x81, 0xb9, 0x9a, 0x5f, 0x26, 0xce, 0x59, + 0x4d, 0x79, 0xe7, 0xba, 0x3d, 0xcb, 0x02, 0xcd, 0xd9, 0xf8, 0xde, 0xa1, 0x6a, 0x82, 0x66, 0x7c, 0x41, 0xd3, 0x9b, + 0x8b, 0xb1, 0x2e, 0xd0, 0xdf, 0x5b, 0xcd, 0x2d, 0x30, 0x89, 0x0b, 0xd6, 0x53, 0xde, 0xe7, 0xf7, 0xa6, 0x4d, 0x03, + 0xeb, 0xc5, 0x9c, 0x03, 0x34, 0x2f, 0xc3, 0xa7, 0xd3, 0x4a, 0x7b, 0x46, 0x93, 0x82, 0x3f, 0xdc, 0xe0, 0xd0, 0x32, + 0xed, 0xd7, 0xcf, 0x5e, 0xf4, 0xba, 0xe1, 0x5f, 0x2e, 0x03, 0x38, 0xea, 0x5f, 0x46, 0x42, 0xc7, 0xde, 0x19, 0xe7, + 0x56, 0x41, 0x1c, 0x8d, 0xb1, 0x21, 0xf4, 0x3f, 0x12, 0xe7, 0x33, 0x32, 0x78, 0x06, 0x76, 0x41, 0x05, 0x42, 0x92, + 0x7e, 0xb1, 0xa2, 0x39, 0x2c, 0x6f, 0x31, 0x6d, 0xd4, 0x72, 0xc1, 0xb4, 0x65, 0xb8, 0xc5, 0xcb, 0x56, 0x1b, 0x8b, + 0xea, 0xcb, 0xe7, 0xc2, 0x60, 0x12, 0x56, 0x91, 0xfb, 0x3f, 0xce, 0x00, 0xd4, 0x4f, 0x20, 0x79, 0x0c, 0x5b, 0xdf, + 0x2e, 0xfa, 0xd5, 0xb2, 0x40, 0xaf, 0xcc, 0x93, 0x0d, 0x5a, 0xe3, 0x32, 0x46, 0xd4, 0x85, 0xe9, 0x75, 0x6d, 0xae, + 0xa1, 0x7b, 0x63, 0x7d, 0x1a, 0x09, 0x7d, 0x07, 0x0b, 0xf1, 0xed, 0xc7, 0xb4, 0xd1, 0x71, 0x07, 0x71, 0x53, 0xd8, + 0x6f, 0x55, 0x9b, 0xc8, 0x59, 0xeb, 0xb9, 0x89, 0x82, 0xe2, 0x1a, 0x51, 0x7d, 0x93, 0x73, 0x87, 0x8f, 0x6e, 0xa2, + 0xa3, 0xf2, 0x1a, 0xef, 0x2d, 0xd5, 0xd4, 0xd7, 0x00, 0x2d, 0xd4, 0x1d, 0x6a, 0xa0, 0xe7, 0xc5, 0xab, 0x22, 0x02, + 0x9e, 0xa9, 0x73, 0xfc, 0x25, 0x2a, 0x78, 0x04, 0x1f, 0xcd, 0xab, 0x52, 0xaa, 0xda, 0x37, 0x21, 0xab, 0x83, 0x5c, + 0x93, 0x07, 0x7e, 0x48, 0x75, 0x1d, 0xde, 0x46, 0x01, 0x1a, 0x3c, 0xa2, 0x1a, 0x3c, 0xb2, 0xfe, 0xbc, 0x38, 0x4f, + 0x31, 0x7e, 0x3a, 0x05, 0x4b, 0x37, 0x02, 0x4b, 0x1b, 0xfb, 0xf2, 0xe2, 0xb0, 0xb9, 0x64, 0x55, 0x00, 0x92, 0x19, + 0xf5, 0x52, 0x2c, 0x7e, 0x26, 0x15, 0x9e, 0x37, 0xaa, 0xac, 0x6e, 0xb3, 0xa3, 0x8f, 0x74, 0x6e, 0x2b, 0x13, 0x10, + 0x0a, 0xfd, 0xfe, 0x91, 0x09, 0x95, 0x78, 0x55, 0x68, 0x04, 0x01, 0x7a, 0xab, 0xc1, 0x79, 0x35, 0xca, 0x7e, 0xfe, + 0x75, 0xeb, 0x3e, 0x2d, 0x5e, 0xa2, 0x61, 0x2f, 0xdd, 0xa8, 0xb1, 0xa0, 0x93, 0x60, 0x30, 0x25, 0x8c, 0x82, 0xdc, + 0x82, 0x76, 0xa4, 0x77, 0x12, 0xbd, 0x19, 0xa8, 0x4f, 0x0b, 0xaa, 0xfe, 0xdf, 0xee, 0xa7, 0x54, 0xf4, 0x13, 0x81, + 0x16, 0xf2, 0x64, 0xeb, 0x01, 0x5f, 0x1b, 0xbe, 0xc5, 0xf9, 0xab, 0x46, 0xba, 0x90, 0x5c, 0x52, 0x10, 0x1b, 0x99, + 0xb2, 0x19, 0x69, 0x90, 0x56, 0x3c, 0x73, 0x4d, 0xea, 0x42, 0x4a, 0xbb, 0x69, 0xf0, 0xb3, 0x95, 0xd7, 0x20, 0xd5, + 0xe4, 0xd1, 0x15, 0x6b, 0x2f, 0x6e, 0x5c, 0xc6, 0x1b, 0x67, 0xd7, 0x47, 0xb4, 0x2a, 0xb4, 0x2c, 0x54, 0x2b, 0xd2, + 0xa5, 0xd4, 0x77, 0x66, 0x79, 0x89, 0x00, 0xf6, 0x88, 0xbd, 0x0b, 0x17, 0xed, 0x9b, 0x65, 0x16, 0x39, 0xb0, 0xcd, + 0x3d, 0x0b, 0xdb, 0x5e, 0x1f, 0x12, 0xf9, 0x52, 0xfc, 0xcc, 0x8c, 0xea, 0x62, 0xd5, 0x34, 0x9f, 0x1d, 0x0c, 0x12, + 0xad, 0x36, 0x11, 0x67, 0xe2, 0xa4, 0x47, 0x20, 0x0a, 0x53, 0xa2, 0x9f, 0x45, 0xb1, 0x8c, 0x20, 0xfb, 0x47, 0xf6, + 0x86, 0x23, 0xdd, 0x84, 0x15, 0x87, 0xef, 0x01, 0xfb, 0x37, 0xfb, 0x6f, 0x1b, 0x46, 0x30, 0xad, 0xe0, 0xbc, 0x10, + 0x2c, 0x42, 0xe3, 0x2d, 0x86, 0x46, 0xb8, 0x9f, 0x04, 0x24, 0xde, 0x48, 0x71, 0x82, 0xfa, 0xdc, 0x8e, 0xaf, 0x5e, + 0x1d, 0xd2, 0x23, 0xcc, 0x50, 0x78, 0x36, 0xe5, 0x94, 0x67, 0xb0, 0x8f, 0xe7, 0xa2, 0xfb, 0x97, 0xea, 0x10, 0x1b, + 0x05, 0x47, 0xca, 0x52, 0xab, 0x42, 0xd6, 0x71, 0xdd, 0xbf, 0x5b, 0x1d, 0x73, 0x36, 0x36, 0x7d, 0xe5, 0x25, 0x0d, + 0x5a, 0x69, 0x48, 0xf4, 0x80, 0x1d, 0xe3, 0xd9, 0x86, 0x24, 0x3b, 0x56, 0x9a, 0x84, 0x18, 0xcd, 0x24, 0xd6, 0xc1, + 0xb4, 0x7f, 0xf4, 0xca, 0xb3, 0x56, 0xec, 0xba, 0xe6, 0x74, 0x6d, 0x06, 0xa9, 0xd0, 0x36, 0x22, 0xac, 0x26, 0xa6, + 0xbb, 0x88, 0x76, 0xfa, 0x33, 0x55, 0xbf, 0x1e, 0x29, 0xd3, 0xd8, 0x4f, 0x50, 0x28, 0x4f, 0xf0, 0x66, 0xbb, 0x2b, + 0x27, 0x77, 0x09, 0x00, 0x4d, 0xff, 0x72, 0xdd, 0x85, 0x73, 0xa6, 0x8a, 0x56, 0x3d, 0xf0, 0x69, 0xd2, 0x35, 0x2f, + 0xe1, 0x50, 0xcd, 0x68, 0x04, 0xe0, 0x3c, 0x09, 0xa1, 0xcb, 0xd9, 0x9e, 0x6b, 0x08, 0x9a, 0xd6, 0xf3, 0xb4, 0xce, + 0x9e, 0x11, 0x3d, 0xff, 0xa9, 0xcf, 0x7c, 0x21, 0x5d, 0x51, 0x14, 0xb5, 0x29, 0x6b, 0x8a, 0xa1, 0xa1, 0x8d, 0x33, + 0xb9, 0xe1, 0xb4, 0x8b, 0x16, 0x21, 0x9d, 0xd9, 0x4b, 0x7d, 0x8a, 0x75, 0xa5, 0xdb, 0xce, 0x06, 0x16, 0x96, 0x06, + 0x26, 0x50, 0x72, 0x54, 0x69, 0x71, 0x9d, 0x59, 0xbe, 0x54, 0x5b, 0xb7, 0x74, 0x9e, 0xcb, 0x17, 0x79, 0x1a, 0xc6, + 0xe7, 0x5f, 0x01, 0x77, 0x72, 0xe4, 0x02, 0xcb, 0xbc, 0xa2, 0x5a, 0x42, 0xfa, 0x94, 0x5f, 0xc3, 0x68, 0xe1, 0xb1, + 0xf1, 0xc0, 0xb4, 0xba, 0x7f, 0xb0, 0x54, 0x95, 0xf3, 0x82, 0xa9, 0x31, 0x8f, 0x49, 0x93, 0x02, 0x37, 0xb9, 0x0d, + 0xea, 0x4a, 0x0c, 0xb0, 0x4d, 0x91, 0x7f, 0xf2, 0xa3, 0x20, 0x43, 0x3c, 0x90, 0xd1, 0xa8, 0x06, 0xea, 0x34, 0x73, + 0xbc, 0xb3, 0x4b, 0x5d, 0xac, 0xda, 0xde, 0x82, 0x62, 0x78, 0x5b, 0xea, 0x82, 0xe1, 0x99, 0xe2, 0xa9, 0x84, 0x37, + 0xe5, 0x0a, 0xf6, 0xaf, 0x12, 0xa1, 0xa1, 0x72, 0xa1, 0xf6, 0xc3, 0x31, 0x6c, 0xb5, 0x0b, 0x81, 0xd2, 0x6f, 0x1a, + 0x1a, 0x85, 0x86, 0xac, 0x57, 0xcd, 0xab, 0xba, 0xb7, 0x79, 0xab, 0x36, 0x84, 0xa1, 0x29, 0xd2, 0xb9, 0x60, 0xdb, + 0xc5, 0x1e, 0xee, 0xff, 0x14, 0x43, 0x11, 0x52, 0x2b, 0xe7, 0xe2, 0x43, 0x3e, 0xee, 0x20, 0x60, 0x7e, 0x52, 0x0f, + 0xfe, 0xfa, 0xa3, 0x30, 0xe4, 0x7f, 0x56, 0x7a, 0xa0, 0xe2, 0x87, 0xfd, 0x22, 0xfc, 0x2a, 0xf3, 0xb7, 0x86, 0x94, + 0x93, 0x77, 0x7d, 0xdb, 0x05, 0x00, 0x2d, 0x5f, 0xc8, 0x81, 0xbc, 0xeb, 0xcc, 0x8d, 0x91, 0xb5, 0x6d, 0x32, 0xaf, + 0xd6, 0xf1, 0x2b, 0x81, 0x82, 0xd8, 0xf8, 0x2d, 0x94, 0xfd, 0xd9, 0x90, 0x1b, 0xfe, 0xc3, 0xc1, 0xdc, 0x52, 0x42, + 0x57, 0x59, 0x93, 0x53, 0xca, 0x0e, 0x19, 0x01, 0xd2, 0x08, 0x1c, 0x47, 0x3e, 0x33, 0xa0, 0xbf, 0x8d, 0x2b, 0xfa, + 0xe9, 0x15, 0xb7, 0xa1, 0x58, 0x4d, 0x4f, 0x75, 0x8d, 0x90, 0x87, 0xe9, 0x42, 0x76, 0x33, 0xa1, 0x89, 0x58, 0x38, + 0x2e, 0x47, 0x02, 0xd9, 0x9b, 0xc8, 0x74, 0x02, 0x2d, 0xd8, 0x9a, 0xe5, 0xd6, 0x48, 0xae, 0x6a, 0x2b, 0xa7, 0xcb, + 0xfa, 0xe4, 0x48, 0xea, 0x55, 0x81, 0x1b, 0x79, 0xeb, 0x7c, 0x51, 0x67, 0x47, 0x45, 0xa5, 0x67, 0xc8, 0xdb, 0xdc, + 0xc2, 0x89, 0xe5, 0x93, 0xe2, 0x37, 0x9c, 0xe4, 0xee, 0xd5, 0x7a, 0xa0, 0x48, 0xc2, 0x54, 0x28, 0xb3, 0x17, 0x39, + 0xdb, 0x6e, 0xf4, 0xe0, 0xbd, 0xa5, 0xa0, 0x57, 0x90, 0x0d, 0xb6, 0xdc, 0x5d, 0xdd, 0x29, 0xbd, 0xc0, 0xb3, 0x12, + 0x4e, 0x9b, 0x71, 0xed, 0x85, 0x46, 0x66, 0x49, 0x96, 0x90, 0xf6, 0xbf, 0xba, 0xc7, 0x90, 0x58, 0x5e, 0x6e, 0xc4, + 0xbe, 0xf9, 0xba, 0x0b, 0x43, 0xc9, 0x42, 0x87, 0x0f, 0xec, 0xc1, 0x7b, 0x4c, 0xc5, 0x9b, 0xae, 0x06, 0x3c, 0xf4, + 0x20, 0xa1, 0x94, 0xef, 0xa2, 0xd4, 0xc7, 0xdf, 0x30, 0x7d, 0x7d, 0xef, 0x56, 0x6c, 0xf6, 0x80, 0x17, 0x81, 0x81, + 0xd1, 0xb3, 0x6d, 0xd2, 0xe3, 0x53, 0xd7, 0x11, 0xaa, 0x06, 0x5c, 0xcd, 0xbf, 0xee, 0xa4, 0x37, 0xbb, 0x7d, 0x1a, + 0xf7, 0x76, 0x3f, 0xc4, 0xef, 0x65, 0x63, 0x2a, 0x0f, 0xf5, 0x44, 0xb1, 0xae, 0xcf, 0x5b, 0x62, 0x44, 0x11, 0x27, + 0x1e, 0xd6, 0x7d, 0x6e, 0x54, 0x67, 0x1d, 0x49, 0xf7, 0x6e, 0xc0, 0x8e, 0x92, 0x36, 0x9d, 0x7d, 0xda, 0xe9, 0xb2, + 0x7c, 0x4d, 0x6b, 0x0f, 0x5f, 0x1f, 0x78, 0xe9, 0x36, 0xbf, 0xee, 0x14, 0xb5, 0x31, 0xdb, 0xa2, 0xc9, 0xba, 0xbe, + 0xe3, 0xe2, 0x45, 0xf3, 0xe2, 0x47, 0xcd, 0x6d, 0x55, 0x1d, 0x99, 0x16, 0xb3, 0x7c, 0x9e, 0x0f, 0x90, 0xfc, 0x3e, + 0x3d, 0x05, 0x27, 0x4f, 0xf1, 0xdb, 0xee, 0x1b, 0xde, 0x82, 0x8f, 0xee, 0x5e, 0x8d, 0x4b, 0x59, 0xef, 0x3f, 0xf3, + 0x5b, 0x5e, 0x62, 0xfd, 0xa2, 0x6a, 0xdb, 0xab, 0x41, 0x51, 0xda, 0xd4, 0xfb, 0x2d, 0xff, 0xbc, 0x33, 0x43, 0x46, + 0xfe, 0x99, 0xda, 0xd9, 0x64, 0x2c, 0x01, 0xf4, 0x5f, 0x95, 0xaa, 0x9d, 0x59, 0xe0, 0x8d, 0x67, 0x30, 0x11, 0x0f, + 0x04, 0xaa, 0x5f, 0x50, 0xc8, 0x4c, 0xf1, 0x9d, 0xc6, 0x80, 0xf7, 0x78, 0x74, 0x2a, 0x3c, 0x5e, 0xf6, 0x7e, 0x15, + 0xe3, 0xe0, 0x19, 0x46, 0xec, 0xf6, 0x3f, 0x0e, 0xa2, 0x40, 0x2a, 0x1c, 0x0c, 0xd2, 0x15, 0xce, 0x74, 0xfc, 0xc9, + 0xc0, 0xfe, 0x25, 0xfd, 0x53, 0x75, 0x86, 0xf1, 0x31, 0xbe, 0x72, 0x63, 0xd4, 0x12, 0x5f, 0xa2, 0x7d, 0x9b, 0x2c, + 0xc2, 0xda, 0xf3, 0x64, 0xaf, 0xee, 0xf2, 0x6a, 0x83, 0x88, 0xea, 0xc9, 0x64, 0x79, 0xdc, 0xac, 0x22, 0x4c, 0x00, + 0x45, 0xaa, 0x97, 0x07, 0x2e, 0x43, 0x7e, 0x9f, 0x3f, 0x3f, 0x21, 0xce, 0x2d, 0x9e, 0x11, 0x3f, 0x98, 0x4f, 0x4e, + 0xf8, 0xa8, 0x7b, 0x6d, 0xfd, 0x6d, 0x22, 0x80, 0x2e, 0x99, 0xda, 0x36, 0x39, 0x60, 0x38, 0x70, 0x90, 0xf4, 0xee, + 0xf0, 0xe6, 0x5f, 0x0d, 0x41, 0x28, 0x5f, 0xad, 0x60, 0x69, 0xf5, 0x27, 0x88, 0xd9, 0xd2, 0x98, 0x84, 0x9c, 0x40, + 0x10, 0xae, 0x8d, 0x8f, 0x1d, 0x64, 0x1e, 0xd8, 0x54, 0x0b, 0x2c, 0x2d, 0x39, 0x05, 0xa2, 0x36, 0xee, 0x55, 0xcd, + 0xbd, 0x48, 0x73, 0x32, 0xca, 0xd4, 0xe6, 0x19, 0xab, 0xd6, 0x52, 0x4d, 0x06, 0xfe, 0xc3, 0xbc, 0xc6, 0xfe, 0xac, + 0x70, 0x41, 0x5f, 0xba, 0x79, 0x72, 0xf0, 0xb0, 0x48, 0x30, 0x07, 0x1f, 0x05, 0x30, 0x94, 0x11, 0xfc, 0xa7, 0x96, + 0x5b, 0x39, 0x8f, 0x81, 0x77, 0x28, 0xa9, 0x6a, 0xb1, 0xfb, 0xd2, 0x68, 0x06, 0xce, 0xca, 0xe8, 0x07, 0xf2, 0xbd, + 0xe4, 0x16, 0xf6, 0xf1, 0x23, 0x5f, 0xd0, 0x76, 0x94, 0x33, 0x55, 0x24, 0x54, 0x8d, 0xf7, 0xb6, 0x7f, 0xcb, 0x8a, + 0xfe, 0x95, 0xf7, 0x97, 0x72, 0xc6, 0xab, 0x02, 0x9f, 0x78, 0xc6, 0xa7, 0xf9, 0x72, 0x5a, 0x3c, 0x2a, 0xae, 0x58, + 0x48, 0xb2, 0xa8, 0xf2, 0xd0, 0xeb, 0x3f, 0x89, 0x15, 0x0a, 0x5e, 0xd1, 0xd9, 0x0a, 0x60, 0x8b, 0x18, 0x1d, 0x54, + 0x2a, 0xab, 0x7d, 0x95, 0x47, 0xc6, 0xbc, 0x79, 0xe7, 0x47, 0x61, 0x80, 0x5c, 0xb6, 0xa1, 0xaa, 0x7b, 0x2a, 0xfa, + 0x1a, 0x52, 0x61, 0xd9, 0x8a, 0x4d, 0xef, 0x19, 0x9e, 0x3a, 0x98, 0x7c, 0x4f, 0x2c, 0x77, 0x1f, 0x50, 0x1c, 0xc6, + 0x9a, 0x53, 0xaa, 0x2a, 0x33, 0x3e, 0x8f, 0x9c, 0x7e, 0x3e, 0x85, 0x67, 0xf4, 0x58, 0x64, 0xab, 0xbf, 0xe6, 0xc3, + 0x5a, 0xd8, 0xc2, 0xb7, 0x85, 0x50, 0x83, 0x5e, 0xe8, 0x05, 0xd7, 0xeb, 0x4b, 0x38, 0x88, 0x99, 0x11, 0x37, 0xef, + 0x6b, 0x93, 0x08, 0x64, 0xfd, 0x6c, 0xc4, 0x35, 0xd9, 0xfa, 0xc2, 0xc2, 0x7e, 0x8b, 0xf0, 0x8d, 0x84, 0xe8, 0x4f, + 0xe4, 0x31, 0xeb, 0x07, 0xc9, 0x74, 0xdd, 0x4e, 0x4e, 0xd5, 0x3f, 0x14, 0xf0, 0x6a, 0xc4, 0xfd, 0x15, 0x10, 0x3e, + 0x1f, 0xcb, 0xf5, 0x38, 0x13, 0x04, 0x05, 0x8f, 0xb5, 0x0a, 0x42, 0x79, 0x1b, 0xb5, 0x25, 0xb4, 0xde, 0x2a, 0x08, + 0x60, 0x33, 0xd6, 0xb1, 0x8b, 0x9f, 0x8e, 0xa5, 0x3f, 0x97, 0xfb, 0x3b, 0xa7, 0xf4, 0xc0, 0x8d, 0x0b, 0x0f, 0xf0, + 0x85, 0xef, 0x11, 0xbb, 0xd0, 0x88, 0x67, 0x0d, 0x62, 0x3f, 0x8e, 0xb7, 0x9a, 0xde, 0xd6, 0xa9, 0x76, 0xd8, 0x5c, + 0xa1, 0x54, 0x57, 0xde, 0x4b, 0x78, 0x1b, 0xe6, 0x3c, 0x4f, 0x22, 0xcf, 0x8f, 0x62, 0x1e, 0x38, 0xae, 0x94, 0xc4, + 0x99, 0x94, 0x86, 0xe0, 0xc7, 0x51, 0x27, 0x58, 0xf9, 0x31, 0x33, 0xf6, 0x59, 0x58, 0xdf, 0xf7, 0x0c, 0x3b, 0xf6, + 0x27, 0x5e, 0x07, 0x47, 0x27, 0x2c, 0xa7, 0xe6, 0x66, 0x07, 0xc6, 0x4f, 0x81, 0x2a, 0x4f, 0x08, 0xc2, 0xd6, 0xac, + 0xdc, 0x9b, 0xdc, 0xbe, 0xee, 0x12, 0xa2, 0xd9, 0x10, 0x55, 0x8f, 0x5d, 0xe0, 0xea, 0x65, 0x49, 0xa5, 0x2a, 0xd5, + 0x53, 0x85, 0x0a, 0x43, 0x6b, 0xb5, 0x2d, 0x66, 0x9c, 0xde, 0xbb, 0x11, 0x5c, 0xb8, 0x34, 0xd2, 0x0c, 0x2f, 0x04, + 0x16, 0x58, 0x3b, 0x3d, 0x55, 0xca, 0x68, 0xa5, 0x50, 0x17, 0xf5, 0x79, 0x5c, 0xbf, 0x86, 0x2e, 0x7b, 0xe1, 0x4d, + 0x65, 0x6d, 0x53, 0x34, 0x2c, 0xd8, 0x86, 0x89, 0xae, 0xd3, 0x95, 0xba, 0x9c, 0x7d, 0xf4, 0x57, 0xf5, 0x8c, 0xe6, + 0x58, 0x75, 0xec, 0x49, 0x08, 0xb5, 0x50, 0x83, 0x42, 0xa4, 0xd7, 0xdb, 0x01, 0x88, 0xdc, 0x13, 0xd2, 0xe0, 0x1c, + 0x0b, 0x36, 0x92, 0xed, 0x5c, 0xc1, 0xa6, 0xcd, 0x01, 0x71, 0xe2, 0xe7, 0x7e, 0x10, 0x07, 0x3e, 0x69, 0x43, 0x9a, + 0xf3, 0xb8, 0xfd, 0xd2, 0xdd, 0x1e, 0x58, 0xc9, 0x53, 0x56, 0x28, 0x32, 0x66, 0xbb, 0xab, 0x42, 0x4c, 0x7e, 0x4e, + 0xa6, 0x1e, 0x7c, 0x37, 0x60, 0xfd, 0xab, 0xe1, 0xcc, 0x09, 0xaf, 0x4b, 0x91, 0x45, 0x11, 0x64, 0xff, 0x3a, 0x8e, + 0x1c, 0x01, 0xec, 0x17, 0x5c, 0xa7, 0x58, 0xf7, 0x2d, 0xd5, 0x7c, 0x69, 0xa5, 0xc4, 0xcb, 0xfb, 0xa9, 0xc4, 0x8e, + 0x45, 0xc1, 0x07, 0x01, 0x69, 0xb0, 0xe2, 0xe3, 0x38, 0x06, 0x34, 0x95, 0x0d, 0xb8, 0xee, 0x61, 0x86, 0x15, 0xa5, + 0xdb, 0x3d, 0xbe, 0x8f, 0x4f, 0x71, 0x42, 0xc0, 0x1f, 0x9d, 0x39, 0x58, 0xa4, 0x15, 0x6c, 0xe9, 0x71, 0x78, 0x71, + 0xb0, 0xea, 0x69, 0x9b, 0xa4, 0xb8, 0xe6, 0xc7, 0x6f, 0x8e, 0xd5, 0x5c, 0xb6, 0x34, 0x6b, 0xbd, 0x74, 0xf7, 0xc7, + 0x8b, 0x03, 0x6a, 0x2b, 0x6c, 0x64, 0x81, 0xa8, 0x06, 0x15, 0xb4, 0x0e, 0xb2, 0xaf, 0xd3, 0x4e, 0xa9, 0x81, 0x66, + 0xb4, 0x98, 0xca, 0x3e, 0xa9, 0xe7, 0x93, 0xb1, 0xb5, 0x68, 0x3c, 0xad, 0xc3, 0x26, 0xec, 0x98, 0x9c, 0xa7, 0x60, + 0x64, 0x92, 0xe2, 0xb9, 0x9c, 0xe1, 0x33, 0x0a, 0x20, 0x8a, 0xba, 0x2a, 0x01, 0x5a, 0x5d, 0x28, 0xf6, 0xda, 0x98, + 0x29, 0x01, 0x52, 0xe1, 0xcf, 0x2b, 0xad, 0xcb, 0x08, 0xc5, 0x91, 0xd7, 0x36, 0xaf, 0x34, 0x5f, 0x27, 0xb4, 0x0e, + 0x71, 0xec, 0xf5, 0x64, 0xbd, 0xad, 0x60, 0x0a, 0x50, 0x43, 0x86, 0xae, 0xa9, 0x03, 0xbe, 0xfb, 0xdd, 0x0c, 0x80, + 0x3f, 0x88, 0x3c, 0xb2, 0x4e, 0x34, 0x1b, 0x1e, 0x92, 0x47, 0xc0, 0xd9, 0x43, 0xe5, 0x2a, 0xae, 0xac, 0xec, 0x62, + 0xdd, 0x16, 0xb8, 0x57, 0xb2, 0xf1, 0x65, 0x13, 0xe4, 0x94, 0x3d, 0x67, 0xa9, 0x65, 0x43, 0xc4, 0x81, 0x4a, 0x52, + 0x9b, 0x6c, 0xb0, 0x94, 0x66, 0xf3, 0x2d, 0x2a, 0xcd, 0xf5, 0xd6, 0xf9, 0xc7, 0x80, 0x34, 0x9a, 0xab, 0xd2, 0xdc, + 0x01, 0x0a, 0x00, 0x93, 0x76, 0xf1, 0x4c, 0x93, 0x23, 0x0a, 0x51, 0x58, 0xc0, 0xa0, 0x82, 0xab, 0xb1, 0x77, 0xd4, + 0xec, 0xcc, 0x0e, 0x80, 0x1d, 0x77, 0x75, 0x2b, 0x76, 0xa9, 0x60, 0xbc, 0x89, 0x81, 0xea, 0x57, 0xe3, 0x40, 0xd1, + 0xa6, 0xa3, 0xcb, 0xa2, 0xe8, 0x42, 0x32, 0x57, 0x97, 0x2a, 0x4f, 0xf0, 0x10, 0x95, 0x29, 0x36, 0x6a, 0x22, 0x1c, + 0x40, 0xae, 0x57, 0xbe, 0x6e, 0x7c, 0xad, 0xe3, 0xeb, 0x41, 0x10, 0x70, 0x3f, 0x91, 0x34, 0x92, 0x80, 0x8d, 0xbc, + 0xc2, 0x3e, 0xae, 0x40, 0x5f, 0x7c, 0x6a, 0x2b, 0x72, 0x72, 0xa9, 0xd7, 0x92, 0xc9, 0x92, 0xd5, 0x6c, 0x7f, 0x93, + 0x13, 0x84, 0x3e, 0x25, 0x29, 0x85, 0x9c, 0x4e, 0x77, 0x50, 0x75, 0xc8, 0xe3, 0x75, 0x2c, 0x60, 0x92, 0x8d, 0x5e, + 0xba, 0xad, 0x2d, 0xac, 0xb9, 0x10, 0xde, 0x28, 0x1b, 0x61, 0x4e, 0xac, 0x2b, 0x52, 0xf3, 0x0b, 0x34, 0x5e, 0xbc, + 0xf1, 0x57, 0x2c, 0xb4, 0x7e, 0xe0, 0x2b, 0xd5, 0x89, 0x65, 0xb1, 0x9b, 0x39, 0x19, 0x2a, 0x25, 0x8b, 0xdb, 0xad, + 0x75, 0x08, 0x91, 0xa7, 0x49, 0x9b, 0x81, 0x5c, 0x02, 0x16, 0xc1, 0x13, 0x44, 0x58, 0x74, 0x18, 0x0a, 0x9b, 0xe6, + 0x3a, 0x7e, 0x1e, 0x3e, 0x9a, 0x10, 0x4b, 0xed, 0x8a, 0xa5, 0x25, 0x11, 0x7e, 0xf8, 0xcd, 0x36, 0x56, 0x89, 0xba, + 0xb5, 0x30, 0x49, 0x58, 0x9a, 0xde, 0xfb, 0x45, 0xdd, 0xa5, 0xaf, 0x80, 0x74, 0x58, 0x86, 0xad, 0x88, 0xdd, 0x8b, + 0xd1, 0xdd, 0xb8, 0x04, 0x48, 0x38, 0x92, 0x4e, 0x0a, 0xcd, 0x4b, 0x4a, 0xca, 0xcf, 0x5c, 0xdd, 0xa8, 0xd2, 0x0c, + 0xa2, 0x94, 0xf3, 0x3a, 0x51, 0x68, 0xb9, 0x27, 0x36, 0x09, 0x11, 0x19, 0x3e, 0x2f, 0x12, 0xe4, 0xad, 0xd6, 0x6f, + 0x7b, 0xe8, 0x20, 0xc0, 0x86, 0x4e, 0x01, 0x7a, 0x8c, 0x92, 0x61, 0x10, 0x98, 0x0d, 0x85, 0x3d, 0x1b, 0x54, 0x94, + 0x20, 0xb4, 0x2d, 0x98, 0x13, 0xa1, 0xcb, 0x37, 0x99, 0x66, 0x98, 0xfc, 0x3c, 0xed, 0xf2, 0xf1, 0xdd, 0x19, 0x2e, + 0x8f, 0x95, 0x77, 0x36, 0x9a, 0xf7, 0x80, 0xf4, 0x9c, 0xb4, 0xe9, 0xa1, 0x34, 0x51, 0x7a, 0x0f, 0x51, 0x4f, 0x0e, + 0xaf, 0x09, 0x56, 0xa1, 0x25, 0x4c, 0x8d, 0xe9, 0x56, 0xbb, 0xfb, 0x42, 0xa2, 0x77, 0x6d, 0xae, 0x10, 0xa5, 0xb5, + 0x1b, 0x6a, 0xb5, 0x87, 0xe6, 0x99, 0xa4, 0x79, 0xda, 0x95, 0xfa, 0x8e, 0x6b, 0x0a, 0x70, 0xda, 0x66, 0x7d, 0x4e, + 0xa0, 0x35, 0x00, 0x2d, 0x48, 0x0d, 0x12, 0x23, 0xe8, 0x89, 0x31, 0x4f, 0xc5, 0xde, 0x38, 0x5f, 0x53, 0x64, 0x15, + 0x13, 0x9a, 0x04, 0xbc, 0xed, 0xbd, 0x84, 0x70, 0x06, 0x81, 0x90, 0x48, 0xc7, 0xa3, 0x14, 0xab, 0xee, 0x17, 0xef, + 0x24, 0xc2, 0x96, 0x13, 0x35, 0x8c, 0x10, 0xce, 0x41, 0x83, 0x58, 0x80, 0x0a, 0x53, 0x1a, 0x06, 0x87, 0x01, 0x6b, + 0x06, 0x19, 0xd0, 0x79, 0x2b, 0xa5, 0x48, 0xb8, 0x20, 0x87, 0x44, 0xd1, 0x77, 0x25, 0xc4, 0x21, 0x2b, 0x72, 0x69, + 0xa0, 0xda, 0x3b, 0x18, 0x8d, 0x37, 0xe3, 0xb4, 0x94, 0x2e, 0x71, 0x46, 0x7d, 0x8c, 0x62, 0xa6, 0x80, 0x73, 0xfb, + 0x11, 0x73, 0xdd, 0x8d, 0xc8, 0xc5, 0xd0, 0xc7, 0x75, 0x5b, 0x69, 0x89, 0xeb, 0xe1, 0x9c, 0x22, 0x41, 0x15, 0x8d, + 0x0a, 0x6e, 0x1b, 0x85, 0xc8, 0x4e, 0x5d, 0x30, 0xaa, 0x42, 0x88, 0xc4, 0x10, 0xd5, 0x56, 0x85, 0xc5, 0x15, 0xb7, + 0x98, 0x24, 0xcc, 0x38, 0x8b, 0x88, 0x16, 0xf0, 0x3c, 0xdb, 0xff, 0x29, 0x8a, 0xde, 0x3c, 0xf2, 0x05, 0x55, 0xa0, + 0xff, 0xf6, 0x04, 0x63, 0xfc, 0xf8, 0xd6, 0x0f, 0x1f, 0xf7, 0x14, 0x4f, 0x3f, 0xef, 0xa9, 0x5f, 0x7f, 0xe2, 0xe3, + 0x48, 0x9e, 0xf1, 0x8b, 0xfd, 0x5b, 0x0c, 0x96, 0x19, 0x30, 0x65, 0x05, 0xcb, 0xfe, 0x6e, 0x65, 0x7a, 0xe7, 0x84, + 0x9c, 0xb6, 0xe1, 0x62, 0xcb, 0x78, 0x6c, 0x75, 0xb2, 0x06, 0x2a, 0xb2, 0x38, 0x56, 0xb0, 0x32, 0xcb, 0xd7, 0x3c, + 0xd7, 0x67, 0x97, 0xde, 0x9e, 0xb8, 0x23, 0x51, 0x25, 0x77, 0x1e, 0x80, 0x93, 0x92, 0xf5, 0xa3, 0x6f, 0x23, 0xff, + 0x11, 0xd5, 0x6e, 0x3b, 0x28, 0x11, 0x4a, 0x2c, 0xc9, 0x7e, 0x55, 0x5a, 0xd3, 0xaf, 0xb7, 0x98, 0xb3, 0xa6, 0x96, + 0x1b, 0x86, 0x87, 0x51, 0xfe, 0x48, 0xbe, 0xdc, 0xb1, 0x3e, 0x34, 0x8d, 0xe7, 0xe4, 0x69, 0xe8, 0xa5, 0x8b, 0x88, + 0x55, 0x58, 0xd0, 0xff, 0xab, 0xa7, 0xff, 0xbf, 0x18, 0x24, 0xd2, 0xe1, 0xb7, 0x41, 0x8f, 0x37, 0x0c, 0x10, 0x93, + 0x73, 0xbe, 0xd1, 0xc7, 0x3b, 0xf1, 0xaf, 0x3c, 0xcc, 0x9f, 0xb3, 0xfd, 0xdd, 0xe0, 0xef, 0xeb, 0xb2, 0xef, 0xfa, + 0xb5, 0x69, 0x0b, 0x69, 0x37, 0x48, 0xe3, 0x95, 0x1a, 0x13, 0x34, 0xab, 0xc6, 0x91, 0xd1, 0x54, 0x8f, 0x47, 0x55, + 0x88, 0xac, 0x29, 0xc7, 0x4e, 0x7f, 0x08, 0x3a, 0x28, 0x78, 0x1c, 0x0d, 0x95, 0xe5, 0x99, 0x34, 0x47, 0xb5, 0x0d, + 0x4c, 0xf6, 0x66, 0xd4, 0x56, 0x2c, 0x16, 0xd6, 0xd6, 0x6c, 0xe2, 0xd9, 0xa3, 0xf1, 0xae, 0x56, 0xc6, 0xc6, 0x03, + 0xa9, 0x27, 0x17, 0xa7, 0x19, 0x91, 0x58, 0x8c, 0x91, 0x6d, 0xb9, 0xa9, 0x2f, 0x7b, 0xe5, 0x2d, 0xfa, 0xf3, 0x8a, + 0x3f, 0x9a, 0x9b, 0xba, 0x88, 0x51, 0xaf, 0x07, 0xdd, 0x1f, 0x9e, 0x2b, 0x71, 0x71, 0x58, 0xec, 0x7c, 0x8d, 0x0f, + 0x87, 0x1d, 0xbf, 0xda, 0x9c, 0x63, 0xea, 0x25, 0xc1, 0x86, 0x7e, 0x1a, 0x1c, 0xcd, 0xfd, 0xa3, 0xc1, 0x15, 0x03, + 0x7a, 0x20, 0x95, 0x9b, 0x22, 0xcd, 0x08, 0x30, 0x51, 0x3c, 0xd6, 0x5c, 0xaf, 0x73, 0x0f, 0xf1, 0xd5, 0xb6, 0x40, + 0x62, 0xc4, 0xe9, 0xf4, 0x62, 0x48, 0x24, 0x98, 0x98, 0x9e, 0xd2, 0x5e, 0x5c, 0x3e, 0x19, 0xde, 0x22, 0x3a, 0x1b, + 0xd7, 0xde, 0xde, 0xf9, 0xcc, 0x77, 0x89, 0x6b, 0x7c, 0x61, 0xb9, 0xcc, 0x2e, 0x30, 0x8d, 0x78, 0x0d, 0x54, 0x88, + 0x71, 0x60, 0x28, 0x7e, 0x82, 0xfe, 0x72, 0x21, 0x02, 0xb5, 0xcc, 0x68, 0x97, 0xb6, 0x37, 0x69, 0xec, 0xd8, 0x79, + 0x2e, 0x77, 0x09, 0x94, 0x38, 0x2e, 0x52, 0x6b, 0xbe, 0x73, 0x3f, 0x38, 0xd6, 0x85, 0xe1, 0xbe, 0x6e, 0xa3, 0xe4, + 0xdb, 0xca, 0xa9, 0x6e, 0x79, 0x14, 0xee, 0x88, 0xe1, 0x68, 0x6c, 0x53, 0xfa, 0x99, 0x2d, 0x72, 0xa3, 0x7c, 0xd2, + 0x0b, 0x51, 0xfe, 0x04, 0xd8, 0x9a, 0xe1, 0x2e, 0x58, 0xaf, 0xcf, 0x01, 0xa2, 0xae, 0xae, 0xd6, 0xf6, 0x7c, 0x31, + 0xfa, 0x5d, 0xe1, 0xde, 0xf2, 0x20, 0xc1, 0x98, 0xb6, 0x39, 0x9e, 0xc8, 0xbe, 0x72, 0x5a, 0x09, 0x5d, 0xe7, 0xe0, + 0x34, 0x71, 0x7f, 0x3c, 0x87, 0x9e, 0xab, 0x91, 0xbc, 0x4b, 0x09, 0x97, 0x29, 0x53, 0x92, 0x31, 0xbd, 0xbb, 0x3a, + 0xc0, 0x76, 0xe8, 0xa0, 0x48, 0xb3, 0x0e, 0xc2, 0x20, 0xe1, 0xa9, 0x0d, 0x3e, 0xdd, 0x33, 0x06, 0x1f, 0x3f, 0x53, + 0xce, 0x2b, 0x5a, 0x55, 0x09, 0x9f, 0x57, 0x1f, 0xf2, 0xfb, 0xef, 0x50, 0x41, 0xd6, 0x37, 0x6b, 0x64, 0xc3, 0xae, + 0x2c, 0x0f, 0x10, 0xe7, 0x51, 0x84, 0xfd, 0x80, 0xce, 0x7e, 0xcc, 0xc2, 0xa6, 0x7d, 0x18, 0x3f, 0xf9, 0xa6, 0xe9, + 0x7a, 0xde, 0x99, 0xd6, 0x9c, 0x1f, 0x7c, 0xd8, 0x2b, 0xe1, 0x40, 0xb7, 0xb3, 0xf4, 0xbf, 0x88, 0x18, 0x20, 0x18, + 0x6c, 0xfe, 0xbe, 0x9c, 0x0f, 0xcf, 0x1e, 0xf2, 0x73, 0x44, 0xe4, 0x0e, 0x37, 0xb1, 0x77, 0xfc, 0x2e, 0xaf, 0x2a, + 0xc3, 0x06, 0xf2, 0x8a, 0x73, 0x19, 0xe1, 0xf2, 0xd6, 0xba, 0x6b, 0xc5, 0xb6, 0x24, 0x0b, 0xae, 0x25, 0x40, 0x61, + 0x64, 0x72, 0xc8, 0xed, 0xf2, 0x3f, 0x2b, 0xb6, 0x20, 0x21, 0xaa, 0x9d, 0xd4, 0x5d, 0xbd, 0x77, 0xae, 0x36, 0x55, + 0x1e, 0xfb, 0x87, 0x8f, 0x72, 0xe6, 0x0c, 0xa3, 0x0a, 0x77, 0x6c, 0xb3, 0x87, 0x2a, 0xa3, 0x36, 0x19, 0x13, 0x87, + 0x2a, 0xed, 0xac, 0xef, 0xa9, 0x58, 0x7a, 0x8c, 0x58, 0x62, 0x20, 0x23, 0x33, 0x1b, 0x92, 0xf6, 0xde, 0xec, 0x17, + 0x5e, 0x2f, 0xae, 0xb8, 0x4c, 0x08, 0x20, 0x6b, 0x63, 0xa0, 0xab, 0xad, 0x34, 0xec, 0xed, 0xf6, 0x7e, 0xfa, 0x28, + 0xbb, 0x3e, 0xe8, 0x1f, 0xe6, 0x0f, 0x5c, 0xaa, 0x35, 0x2b, 0xa7, 0xd6, 0xb2, 0xed, 0x15, 0xed, 0xd0, 0xeb, 0x2d, + 0xb3, 0xe9, 0x12, 0xd6, 0x23, 0xc9, 0xa2, 0xa5, 0x3c, 0xae, 0xaa, 0x4e, 0xd5, 0xb0, 0xdb, 0x34, 0x75, 0x9f, 0x39, + 0xbe, 0x43, 0x0a, 0x65, 0x59, 0x99, 0xd2, 0x27, 0xcf, 0x9c, 0x78, 0xaa, 0x28, 0x83, 0x39, 0x13, 0xdc, 0x96, 0x93, + 0x11, 0xa9, 0x88, 0xd7, 0x18, 0xcd, 0x0f, 0x01, 0xab, 0xb8, 0xae, 0x9f, 0x78, 0x14, 0x97, 0x0e, 0xae, 0xb3, 0xa1, + 0x6e, 0x3e, 0x5f, 0x13, 0x92, 0x96, 0x89, 0xf3, 0x69, 0xc0, 0xd7, 0x40, 0xd7, 0x47, 0x91, 0x02, 0xc0, 0x71, 0x26, + 0x93, 0xca, 0x7e, 0xd4, 0x91, 0xf3, 0x7e, 0xd3, 0x7c, 0xb5, 0x3e, 0xbb, 0xc8, 0xd7, 0xad, 0xf1, 0xab, 0xe1, 0x34, + 0x8f, 0x9e, 0x96, 0x9e, 0xf6, 0xf5, 0x79, 0xa6, 0x12, 0xc5, 0xfe, 0xca, 0x99, 0xbd, 0x51, 0xde, 0x15, 0xab, 0xec, + 0x2e, 0x7a, 0x78, 0xd7, 0xcf, 0x09, 0x70, 0xf8, 0x6e, 0x57, 0x20, 0xf2, 0xc3, 0xb2, 0x79, 0x8a, 0xcb, 0xa9, 0xb1, + 0x53, 0x94, 0x82, 0x19, 0x8d, 0xad, 0x88, 0x67, 0x6a, 0x26, 0xb0, 0x5e, 0xed, 0xe5, 0x61, 0x5a, 0x36, 0xa4, 0x19, + 0x7f, 0x58, 0x8b, 0xd1, 0x0e, 0x93, 0x07, 0x59, 0x06, 0xb3, 0xc8, 0xfa, 0xd0, 0x1c, 0x9d, 0xba, 0x62, 0xd2, 0xf6, + 0xd4, 0x29, 0x0b, 0xb7, 0x0f, 0xd6, 0xd8, 0x25, 0xe5, 0x50, 0x95, 0xe7, 0xef, 0xd7, 0x78, 0xe5, 0xb9, 0x48, 0xc6, + 0x3b, 0x70, 0xde, 0xb2, 0xdf, 0xc6, 0x09, 0x62, 0xdc, 0xd8, 0x6a, 0x7c, 0x16, 0x1b, 0x77, 0x82, 0x96, 0x09, 0xe4, + 0xec, 0xc1, 0x02, 0x9c, 0x86, 0x37, 0x45, 0xa6, 0xb5, 0xfc, 0x6c, 0x08, 0x78, 0x6f, 0xe8, 0x77, 0x75, 0x0b, 0x00, + 0x8b, 0xc8, 0x7b, 0xbd, 0x52, 0x9c, 0x2e, 0x8d, 0xc3, 0xc7, 0xdd, 0x95, 0xe2, 0x51, 0xda, 0x4d, 0x74, 0x77, 0xca, + 0x33, 0x48, 0x41, 0xbc, 0x7c, 0xa5, 0x5a, 0x8c, 0xaa, 0x97, 0xc8, 0x09, 0x04, 0x2c, 0x52, 0x8a, 0xff, 0xac, 0x7b, + 0x02, 0x2b, 0xd5, 0x77, 0xfc, 0xaa, 0x7a, 0x41, 0xac, 0x01, 0xbb, 0x6d, 0xb9, 0x85, 0x9e, 0x2a, 0x81, 0x7c, 0x00, + 0x99, 0x0b, 0xc0, 0xc0, 0xfd, 0xbb, 0x6e, 0xc2, 0xf5, 0x9f, 0x47, 0x99, 0x6f, 0x75, 0x5b, 0xae, 0xcf, 0xe6, 0xd1, + 0xd9, 0x8c, 0x9d, 0x90, 0x2f, 0x27, 0x7d, 0x09, 0x8a, 0xc9, 0xa6, 0x80, 0xfa, 0x21, 0xb3, 0x0f, 0xdb, 0xae, 0x72, + 0x46, 0x40, 0xb5, 0x7d, 0xae, 0x20, 0x61, 0xa0, 0xe5, 0x9e, 0xac, 0xcd, 0x47, 0xbe, 0xd2, 0xe6, 0xed, 0xfc, 0xfc, + 0xef, 0xbc, 0xe5, 0xa1, 0x83, 0xba, 0xff, 0x8a, 0xc5, 0x55, 0xfe, 0x4e, 0x46, 0x91, 0xed, 0xc3, 0x76, 0xf3, 0x6e, + 0x24, 0xc4, 0x05, 0xa7, 0xfc, 0x07, 0x9f, 0xbf, 0x94, 0x2e, 0xbc, 0xde, 0xc5, 0xa0, 0xf4, 0x11, 0x6a, 0xdc, 0x98, + 0xdb, 0x22, 0x91, 0xeb, 0x4a, 0x20, 0xf2, 0xd8, 0xc1, 0xa8, 0xe7, 0xb5, 0x4b, 0x6e, 0x00, 0xa3, 0x6e, 0xc7, 0xc3, + 0x03, 0x6d, 0x4a, 0x7f, 0x32, 0xe1, 0x46, 0x0b, 0x55, 0xc4, 0x1d, 0xa3, 0xe6, 0x03, 0x45, 0xe2, 0x15, 0x06, 0x08, + 0xd0, 0xad, 0xcf, 0xa3, 0xe8, 0x6d, 0x9a, 0xf7, 0x43, 0xb1, 0x9d, 0xa6, 0x2c, 0x50, 0xc0, 0x78, 0x32, 0x47, 0xb4, + 0xec, 0x89, 0x7d, 0xba, 0x3b, 0x1d, 0x56, 0x46, 0x6f, 0x71, 0x6d, 0xea, 0x72, 0xaf, 0xaf, 0xda, 0xce, 0xd6, 0x09, + 0xf7, 0x34, 0x6c, 0xe3, 0x0a, 0x12, 0x36, 0x72, 0x2a, 0x7a, 0xae, 0xe8, 0x6b, 0x3a, 0x2b, 0xe1, 0x1a, 0xf3, 0x2d, + 0x02, 0x60, 0x4d, 0x06, 0xf9, 0x4b, 0x31, 0x3d, 0x43, 0x45, 0xde, 0xb3, 0x39, 0x7b, 0x27, 0xd3, 0x29, 0x7b, 0x6b, + 0x48, 0x29, 0x17, 0x98, 0xcf, 0x1e, 0x10, 0xa6, 0x79, 0xe8, 0x6d, 0x24, 0xc9, 0xcc, 0xd3, 0x96, 0xbc, 0xa9, 0xee, + 0x69, 0x22, 0x78, 0x50, 0xca, 0xb3, 0xde, 0x4f, 0xde, 0x0d, 0xeb, 0x82, 0xf1, 0xbc, 0x23, 0x1c, 0x28, 0x3e, 0x97, + 0xbd, 0x09, 0xee, 0x3e, 0xcf, 0x7f, 0x34, 0x27, 0xdb, 0x5a, 0x1b, 0xe4, 0xe6, 0x27, 0x59, 0xbf, 0x90, 0xf3, 0x89, + 0x27, 0xbd, 0xfa, 0xf8, 0x93, 0x7e, 0x91, 0x08, 0x65, 0xd7, 0xa9, 0x09, 0xf6, 0x88, 0x3f, 0x4f, 0x30, 0x80, 0xcd, + 0x62, 0xb2, 0xa4, 0x1a, 0x2d, 0xab, 0x28, 0x6f, 0xe9, 0xb4, 0x99, 0xe2, 0x97, 0xda, 0xd3, 0x69, 0xac, 0xf0, 0x56, + 0x0b, 0xcf, 0xd8, 0x6e, 0xc1, 0xda, 0x66, 0xda, 0x92, 0x25, 0xa7, 0x74, 0xed, 0x83, 0x1d, 0x7f, 0x58, 0x03, 0xa8, + 0x22, 0xca, 0x95, 0xf4, 0xb2, 0x12, 0x7f, 0xe0, 0xb3, 0x5d, 0x84, 0x57, 0x03, 0xaf, 0xaa, 0x99, 0xa7, 0x5a, 0x3d, + 0xb0, 0xdd, 0xf4, 0x69, 0x6f, 0x25, 0x3b, 0xde, 0x51, 0x9c, 0xf0, 0x2a, 0xa1, 0xe3, 0x5c, 0xb6, 0xd0, 0xf5, 0xd3, + 0x5d, 0x58, 0xd8, 0xf7, 0x5f, 0xa0, 0x47, 0x0e, 0x26, 0x6e, 0xe7, 0x67, 0xf6, 0x0a, 0x5a, 0x07, 0x8a, 0x6c, 0x0f, + 0xaf, 0x3b, 0x2b, 0x2c, 0xc2, 0x08, 0x29, 0xff, 0xa5, 0xe1, 0x2d, 0xda, 0xbd, 0x2a, 0x2d, 0xc1, 0xf8, 0xec, 0x5d, + 0xd5, 0xd8, 0xb6, 0x03, 0x65, 0x3a, 0x5b, 0x47, 0xca, 0x05, 0xed, 0x80, 0x91, 0x82, 0xd3, 0x9d, 0x55, 0xdf, 0xff, + 0x3a, 0x99, 0x6a, 0x75, 0x8f, 0xed, 0x70, 0x26, 0xba, 0x53, 0x8c, 0x03, 0x68, 0x09, 0x85, 0xac, 0xad, 0x4e, 0xfd, + 0x7b, 0x9f, 0xad, 0xd7, 0xbc, 0x63, 0x5a, 0xac, 0x34, 0x2f, 0x78, 0x42, 0x6b, 0x1b, 0x9e, 0xb4, 0x18, 0xf7, 0x56, + 0x29, 0x27, 0x42, 0x82, 0x86, 0x6e, 0x39, 0x1f, 0xe4, 0x15, 0x1e, 0xd4, 0x40, 0x25, 0xb8, 0x36, 0x0e, 0xa1, 0x0e, + 0xad, 0x2d, 0xeb, 0xdd, 0x95, 0x18, 0xb7, 0xc0, 0xb5, 0xec, 0xc6, 0xd9, 0x1d, 0xce, 0xad, 0xc3, 0x46, 0xab, 0x91, + 0xdd, 0xe8, 0x0f, 0x43, 0x0f, 0x22, 0x85, 0x9b, 0x1d, 0x4d, 0xb7, 0x1d, 0x46, 0x7b, 0x0e, 0x9d, 0x17, 0x6d, 0x8c, + 0x89, 0x30, 0x33, 0x69, 0x33, 0xdf, 0xc5, 0xe5, 0x4c, 0x1b, 0x96, 0xf2, 0x01, 0x5a, 0x03, 0x08, 0x88, 0xb2, 0x50, + 0xd1, 0x2e, 0x72, 0x9a, 0xed, 0x42, 0x6d, 0xb8, 0xa1, 0x44, 0x2c, 0x82, 0x40, 0xde, 0x40, 0xc8, 0x9f, 0x6a, 0x17, + 0x7e, 0x4d, 0xb0, 0x51, 0x30, 0x83, 0x39, 0xd1, 0x50, 0x63, 0x42, 0x90, 0x3e, 0xb5, 0x52, 0x96, 0x3e, 0xe4, 0x8c, + 0x84, 0xd0, 0x82, 0x1a, 0x55, 0xcb, 0x23, 0x72, 0x9b, 0x6e, 0xe6, 0xf0, 0xb9, 0xa8, 0x38, 0x2a, 0xbd, 0x74, 0x9b, + 0x79, 0x06, 0x1f, 0x75, 0x18, 0x7b, 0x2e, 0xc0, 0x38, 0xd8, 0x39, 0x09, 0xe0, 0x2f, 0xe2, 0x7f, 0x0d, 0xc0, 0x13, + 0x2c, 0x2a, 0xd3, 0x5a, 0x57, 0x6f, 0x60, 0xca, 0x29, 0x8a, 0xd9, 0xf2, 0x14, 0xbd, 0x89, 0xbd, 0xd6, 0xbe, 0x0c, + 0xa4, 0xc4, 0x47, 0x16, 0x3a, 0x7a, 0xeb, 0xc9, 0x4e, 0xcf, 0x40, 0x64, 0xfc, 0x6a, 0xec, 0xfd, 0x71, 0x73, 0xb5, + 0x1b, 0x86, 0xf8, 0x16, 0x05, 0xec, 0xcc, 0x7b, 0xe7, 0xf8, 0xe4, 0xb3, 0x38, 0x4c, 0xe8, 0xcd, 0x41, 0x68, 0x5c, + 0xcf, 0x42, 0xc9, 0xf8, 0xc8, 0xcb, 0x85, 0xfb, 0xb2, 0x0d, 0xb6, 0x33, 0x3e, 0xf9, 0xf4, 0xd0, 0x07, 0x82, 0x87, + 0x4c, 0x49, 0x50, 0x73, 0xa0, 0xbb, 0x36, 0x8d, 0x80, 0xa5, 0x37, 0x79, 0xa1, 0x99, 0xd7, 0xc1, 0xb2, 0x67, 0x28, + 0x40, 0x08, 0x70, 0x20, 0x47, 0xa0, 0x68, 0x7a, 0x37, 0x1a, 0x70, 0x11, 0x7c, 0x58, 0xe4, 0x1c, 0xfe, 0x37, 0x0d, + 0xf7, 0x5d, 0xee, 0xf9, 0xeb, 0x5c, 0x0c, 0x3e, 0xb5, 0x43, 0xdf, 0xb7, 0x03, 0xe1, 0xca, 0xef, 0x78, 0x11, 0x7c, + 0x72, 0x89, 0x90, 0xae, 0x0d, 0x5e, 0x63, 0xe2, 0xdd, 0x8d, 0x90, 0xfb, 0x50, 0x78, 0xb9, 0xc4, 0x03, 0xe6, 0xda, + 0xf4, 0xc6, 0x9c, 0xf9, 0xad, 0xe8, 0x4d, 0x33, 0x47, 0x07, 0xa3, 0x23, 0xbb, 0x1f, 0x61, 0x6d, 0xe7, 0x5f, 0xfa, + 0x57, 0x60, 0x8d, 0xee, 0x67, 0x91, 0x7c, 0x3a, 0xde, 0x56, 0x00, 0x4b, 0x83, 0x0f, 0x64, 0x38, 0xaf, 0x63, 0x0c, + 0x6b, 0xe8, 0x3e, 0xea, 0x7e, 0x25, 0xc0, 0x86, 0x30, 0x0e, 0x95, 0x81, 0xa9, 0x37, 0x30, 0x45, 0xee, 0xff, 0xb3, + 0x8a, 0xfa, 0xb8, 0x61, 0x62, 0x2e, 0x87, 0x34, 0x00, 0x12, 0x0a, 0x7e, 0xee, 0x1e, 0x13, 0xad, 0xd8, 0x43, 0x46, + 0x6b, 0x94, 0x89, 0x47, 0xb2, 0xc9, 0xaf, 0x7a, 0x77, 0xa4, 0xac, 0x0f, 0x7c, 0x2f, 0x9b, 0xbc, 0x4f, 0x98, 0x7b, + 0xce, 0xdf, 0x69, 0x03, 0xa8, 0x5c, 0x8a, 0xb3, 0x8a, 0x7a, 0x09, 0x58, 0x13, 0x39, 0x7e, 0x5a, 0x98, 0x0c, 0x37, + 0x6a, 0x7e, 0x93, 0x45, 0xe0, 0x1e, 0x90, 0xa6, 0xd0, 0x2c, 0x28, 0x57, 0xc8, 0x22, 0xf9, 0x90, 0x9c, 0x3e, 0x20, + 0xd6, 0x85, 0xbc, 0x0d, 0xb5, 0xc5, 0x32, 0x12, 0x93, 0x7b, 0x89, 0x89, 0x57, 0xde, 0x32, 0xb6, 0xc4, 0x58, 0xb4, + 0xa6, 0xec, 0x52, 0x88, 0xbc, 0x51, 0x65, 0xd8, 0xd4, 0x65, 0x06, 0x13, 0xa5, 0x75, 0x3f, 0x3c, 0xc6, 0x51, 0x95, + 0x9e, 0x49, 0x8f, 0x80, 0xad, 0x70, 0xb6, 0x98, 0xd4, 0x55, 0x90, 0xc0, 0xf9, 0x40, 0x78, 0x28, 0x1f, 0x88, 0x15, + 0xaa, 0xb8, 0xf8, 0x13, 0x0e, 0x27, 0xd0, 0x2d, 0xc9, 0x2d, 0xab, 0x8e, 0xeb, 0x78, 0x9f, 0x43, 0x8e, 0x22, 0x51, + 0x02, 0x6d, 0xf0, 0x3b, 0x15, 0xd2, 0x43, 0x06, 0x0b, 0x50, 0x0e, 0x03, 0x3a, 0x3c, 0x18, 0x25, 0xa6, 0xe0, 0xf0, + 0xf0, 0x20, 0x12, 0x79, 0x59, 0xc8, 0x9f, 0x0e, 0xce, 0x3a, 0x54, 0x7d, 0x65, 0xf0, 0xdf, 0xc1, 0xb5, 0x45, 0x28, + 0x4e, 0x4c, 0xac, 0x63, 0x14, 0x1c, 0xdc, 0xba, 0x4d, 0x65, 0xc3, 0x9f, 0x7a, 0x7f, 0xad, 0xf0, 0x68, 0xe9, 0xc1, + 0xea, 0xbc, 0xad, 0x02, 0x9e, 0x0d, 0x4a, 0x8f, 0x35, 0x4f, 0xac, 0x7d, 0xc5, 0xc9, 0x81, 0x04, 0xa6, 0x49, 0x6f, + 0x6b, 0xcb, 0xf8, 0x05, 0xf1, 0xcb, 0x3d, 0x0b, 0x2f, 0xfc, 0x76, 0xd4, 0x12, 0x8b, 0xf5, 0xa9, 0x14, 0x7b, 0x2d, + 0x0d, 0x37, 0xd2, 0x06, 0x59, 0xbf, 0xd3, 0x3a, 0xcf, 0x8d, 0x45, 0x7a, 0x63, 0xff, 0x48, 0xc4, 0xdb, 0x19, 0xea, + 0x53, 0x28, 0xb1, 0x9e, 0x41, 0xf4, 0x6a, 0x48, 0x7d, 0xd1, 0x1a, 0x91, 0xa2, 0x70, 0xd9, 0xea, 0xf2, 0x22, 0x66, + 0x60, 0x8c, 0x68, 0xf5, 0x8a, 0x2d, 0x25, 0x86, 0xf7, 0x42, 0xa4, 0x56, 0xe9, 0xa9, 0xee, 0x8a, 0x62, 0xd3, 0x25, + 0x65, 0xd3, 0x46, 0x68, 0x2b, 0x0a, 0xec, 0x20, 0x94, 0xa2, 0x40, 0x2b, 0xe3, 0xb0, 0x87, 0x7a, 0x8b, 0xcc, 0x68, + 0xa3, 0x14, 0x36, 0xf3, 0x34, 0x02, 0xb8, 0xb9, 0x55, 0x13, 0x69, 0x17, 0x25, 0xce, 0x65, 0xb4, 0x4c, 0xb2, 0xde, + 0xb2, 0x52, 0xb8, 0x2f, 0x64, 0x38, 0x31, 0x3a, 0x36, 0xc0, 0x97, 0xc7, 0xff, 0xef, 0x0f, 0x60, 0xcd, 0xd2, 0x61, + 0x48, 0x5e, 0x43, 0x75, 0x84, 0xd0, 0x8c, 0x3d, 0xea, 0x72, 0x80, 0x22, 0x75, 0x6d, 0xa9, 0x65, 0x6e, 0x47, 0x39, + 0xc6, 0x85, 0x2b, 0xcf, 0xdb, 0xc5, 0x82, 0x0e, 0x0b, 0x23, 0x3e, 0xcc, 0x37, 0x18, 0x4b, 0xae, 0x14, 0xdd, 0x32, + 0x19, 0x81, 0x49, 0x75, 0xc5, 0x0b, 0xe7, 0x0b, 0x5e, 0xc9, 0xf4, 0x07, 0xf9, 0x48, 0x4e, 0xa5, 0x31, 0x1b, 0xab, + 0x0d, 0xa1, 0x26, 0x82, 0x36, 0x4f, 0x4b, 0xa4, 0xdb, 0x2e, 0x4d, 0x2c, 0x50, 0x18, 0x96, 0x46, 0xe8, 0xaa, 0x49, + 0x58, 0xf3, 0xb3, 0xab, 0x05, 0x89, 0x87, 0x49, 0x57, 0xcd, 0x55, 0x70, 0x6e, 0xed, 0xb1, 0xd3, 0x47, 0x7a, 0x2c, + 0x82, 0x56, 0xb3, 0x0b, 0xa5, 0x35, 0x68, 0xcd, 0x2d, 0xb3, 0x36, 0x6c, 0xc0, 0x2b, 0xe7, 0x32, 0xc5, 0x19, 0x35, + 0xbc, 0xb1, 0x31, 0x84, 0xc9, 0x4f, 0xc5, 0x79, 0xf2, 0x7f, 0x66, 0x0b, 0x97, 0xa6, 0x6e, 0xdd, 0x14, 0x57, 0x1c, + 0x48, 0x31, 0x1f, 0xc4, 0xc3, 0x79, 0x11, 0xc9, 0x9b, 0xeb, 0x5e, 0x46, 0x9c, 0x0e, 0xf4, 0x82, 0xac, 0x62, 0x87, + 0xbe, 0x93, 0x1f, 0xf5, 0xa8, 0xc4, 0x19, 0x8c, 0x65, 0x03, 0xb1, 0x04, 0x82, 0xf8, 0xae, 0x7d, 0x88, 0xe4, 0xc6, + 0xa5, 0x5a, 0x97, 0x07, 0xb2, 0xe5, 0x45, 0x90, 0x78, 0xe7, 0xee, 0x5e, 0x33, 0xc6, 0x4b, 0x7c, 0x42, 0x3e, 0x5e, + 0x10, 0xbc, 0x72, 0x0b, 0xe4, 0x0e, 0xd7, 0xc1, 0x03, 0xf1, 0x51, 0x82, 0x17, 0x23, 0x89, 0x7b, 0xa9, 0x43, 0x85, + 0xa0, 0x45, 0x4f, 0x30, 0x22, 0x91, 0x7c, 0xb5, 0xb6, 0x2e, 0x88, 0x02, 0x4d, 0xb0, 0x5e, 0x3c, 0x8a, 0x9a, 0x56, + 0x9f, 0xa0, 0xcc, 0x08, 0xb9, 0x63, 0xab, 0x83, 0x1e, 0xdf, 0xe7, 0xa1, 0x60, 0xf6, 0xae, 0x49, 0x84, 0xfb, 0x5d, + 0x56, 0xb7, 0x3b, 0x20, 0x19, 0xfe, 0xa4, 0x55, 0xf7, 0x72, 0x0a, 0x69, 0x48, 0x43, 0x59, 0x7c, 0xf0, 0x56, 0x09, + 0x4e, 0x1e, 0xb2, 0xac, 0x4f, 0x8b, 0x31, 0x23, 0x25, 0x05, 0x25, 0x86, 0xe5, 0x52, 0x49, 0xd9, 0xe1, 0x10, 0x5b, + 0x62, 0x2f, 0xba, 0x3e, 0xfc, 0xbe, 0xa5, 0x0f, 0x00, 0x0f, 0xe5, 0x66, 0xfa, 0xda, 0x42, 0x54, 0xc0, 0xd0, 0xcc, + 0x7e, 0xca, 0xa7, 0xf5, 0xec, 0x7f, 0x3f, 0x60, 0x1f, 0x33, 0xf6, 0x9b, 0xc7, 0x38, 0xe0, 0xa7, 0x3c, 0xb4, 0x7c, + 0x8d, 0x8a, 0xee, 0x71, 0x5a, 0xcd, 0x7d, 0x69, 0x86, 0x18, 0x38, 0x09, 0x1e, 0xee, 0x72, 0x48, 0x83, 0xfc, 0xb3, + 0x35, 0x24, 0x9b, 0x60, 0x69, 0x2c, 0xb0, 0x42, 0xd6, 0x7c, 0xba, 0x0b, 0x2e, 0xb6, 0x92, 0x82, 0x27, 0x35, 0xb0, + 0xca, 0xf5, 0x26, 0xe6, 0xdc, 0xa4, 0x66, 0x77, 0x04, 0x12, 0xc8, 0x26, 0xb3, 0xbd, 0xa4, 0xe4, 0xaf, 0x89, 0x29, + 0xe9, 0xf7, 0x8d, 0x84, 0x08, 0x80, 0x95, 0x3e, 0x21, 0xba, 0xe0, 0xab, 0x58, 0x93, 0x4c, 0x3a, 0x96, 0x1a, 0xd5, + 0x56, 0x0a, 0xe8, 0x7a, 0xe1, 0x9f, 0xbd, 0xb9, 0x19, 0xcd, 0xa6, 0xe4, 0x4e, 0xe5, 0x0d, 0xf9, 0x14, 0xfc, 0xb5, + 0x19, 0x6d, 0xad, 0x86, 0x89, 0xa1, 0x8f, 0x01, 0xb4, 0xf7, 0x07, 0x78, 0xe1, 0xd1, 0x0a, 0x4b, 0x0a, 0x74, 0x8a, + 0x85, 0xce, 0x4b, 0x98, 0x7b, 0x58, 0x70, 0x54, 0xf2, 0xdd, 0x3b, 0xcc, 0xe3, 0xfa, 0xd6, 0x11, 0x24, 0x65, 0x3b, + 0xd3, 0xe9, 0x52, 0x2b, 0x12, 0xd0, 0xeb, 0x8c, 0x55, 0x22, 0xae, 0x49, 0x4e, 0x6e, 0xf8, 0xca, 0xc8, 0x68, 0x11, + 0x63, 0x1c, 0x53, 0x41, 0x1f, 0x2f, 0xbd, 0xcd, 0x0b, 0xc3, 0xbb, 0x3d, 0xa6, 0x95, 0x1e, 0x39, 0xc0, 0x55, 0xc2, + 0x4c, 0x19, 0xb4, 0x89, 0x78, 0xdc, 0x0f, 0x10, 0x05, 0x62, 0xa1, 0xd3, 0xc8, 0x51, 0x6a, 0xec, 0xfe, 0x88, 0xbd, + 0x80, 0x32, 0xaf, 0x99, 0x41, 0xd1, 0xf0, 0x5b, 0xfd, 0x95, 0xff, 0x8f, 0x1f, 0x67, 0x5e, 0xed, 0x47, 0x6f, 0x52, + 0x56, 0x9a, 0x03, 0xd5, 0xc8, 0x01, 0x77, 0x8f, 0xdb, 0x3b, 0xd7, 0x10, 0x61, 0x78, 0x2e, 0xab, 0xf1, 0x4e, 0x0f, + 0xed, 0xf6, 0x39, 0xfc, 0x9c, 0xdd, 0xae, 0xf9, 0xdd, 0xef, 0xfe, 0x44, 0x1e, 0x74, 0x0d, 0x17, 0x11, 0x1d, 0x30, + 0x5e, 0x5e, 0x6d, 0xd0, 0x9c, 0x67, 0xf9, 0x01, 0xec, 0x3d, 0xbe, 0x35, 0x52, 0x7d, 0xaa, 0x78, 0x85, 0x08, 0xc8, + 0x5b, 0xa5, 0xba, 0x4a, 0xc4, 0xbe, 0xc0, 0x66, 0x91, 0x01, 0x7d, 0xd6, 0xa1, 0x6b, 0xb5, 0x53, 0xc4, 0xcb, 0xcb, + 0x39, 0xe1, 0x87, 0x9b, 0x4e, 0x40, 0x93, 0xdc, 0x79, 0xcb, 0x3b, 0x5b, 0xe2, 0xac, 0xa7, 0x8c, 0x76, 0x9d, 0x5c, + 0x35, 0x0a, 0x48, 0x3b, 0x26, 0x22, 0xd3, 0xd6, 0xdc, 0x76, 0xed, 0xf8, 0x4a, 0xa1, 0xdf, 0xe1, 0xd5, 0xe5, 0x86, + 0x47, 0x43, 0x39, 0xa9, 0x36, 0xc9, 0xab, 0x2d, 0x9b, 0xc9, 0x49, 0x3f, 0xda, 0xda, 0x43, 0xf0, 0xd1, 0x0d, 0x1f, + 0x67, 0xca, 0x7e, 0xa7, 0x61, 0x9f, 0x67, 0xad, 0xfd, 0x55, 0xc2, 0x70, 0x2f, 0x9f, 0xa4, 0x09, 0xda, 0x38, 0xa7, + 0x54, 0x62, 0x0e, 0x78, 0x89, 0xde, 0xf2, 0x20, 0x6c, 0xa6, 0x29, 0xd5, 0xab, 0xca, 0xe5, 0x66, 0x4a, 0xe4, 0x9c, + 0xe8, 0xb1, 0xdb, 0x2c, 0x6e, 0x8a, 0x6b, 0xb0, 0x33, 0x03, 0x26, 0xa1, 0xb5, 0xef, 0xb6, 0x23, 0x3b, 0x38, 0xb7, + 0xfd, 0x61, 0xfc, 0x17, 0x98, 0x27, 0xf2, 0x7c, 0x8e, 0x15, 0x1b, 0xaf, 0xe7, 0xef, 0xfe, 0x1e, 0x03, 0xf6, 0xf9, + 0x98, 0x0d, 0x79, 0xe9, 0xed, 0xc7, 0xd1, 0x3c, 0xee, 0xc7, 0xc3, 0xc0, 0x37, 0x0c, 0x65, 0x38, 0xe0, 0xd1, 0x32, + 0xdd, 0xe9, 0x30, 0xb5, 0x19, 0xd9, 0x13, 0xea, 0xee, 0x9c, 0xb9, 0xe1, 0xe3, 0x4f, 0x22, 0x6c, 0x86, 0xb3, 0x75, + 0x19, 0x24, 0xfa, 0x0a, 0x01, 0xc5, 0x38, 0x8d, 0x18, 0xd7, 0x3b, 0x9f, 0x36, 0xa1, 0xb6, 0x95, 0xa4, 0x67, 0xb7, + 0x40, 0x4d, 0x80, 0xaa, 0x94, 0x2f, 0xd7, 0x45, 0x34, 0x34, 0xf3, 0x24, 0x94, 0x5e, 0xee, 0xe9, 0x73, 0xb4, 0x63, + 0x03, 0x7b, 0x39, 0xa7, 0xa1, 0x94, 0xf4, 0xb2, 0xab, 0x06, 0x37, 0xb0, 0x95, 0xa8, 0xf1, 0x22, 0xe2, 0xdd, 0x66, + 0x0f, 0x25, 0x03, 0xcb, 0x53, 0x12, 0x73, 0xc0, 0xb4, 0x9b, 0x14, 0x55, 0xf6, 0x0c, 0xab, 0x21, 0x98, 0xc7, 0xdd, + 0x7e, 0x66, 0x87, 0xd7, 0x52, 0x54, 0xcd, 0x2d, 0xb6, 0x00, 0x6b, 0x8b, 0x14, 0xe2, 0x70, 0x44, 0x49, 0xd3, 0x11, + 0xe9, 0xc8, 0xf8, 0x93, 0xa6, 0x44, 0x02, 0x10, 0x1d, 0xfe, 0x33, 0xcd, 0xf4, 0x50, 0xf4, 0xdf, 0x8b, 0x57, 0x6b, + 0x73, 0xaf, 0x5d, 0x30, 0x72, 0x9a, 0x7f, 0x38, 0x1d, 0x6f, 0xfa, 0xb9, 0xb5, 0x8f, 0x33, 0xd7, 0xab, 0x5b, 0x1b, + 0x73, 0xbd, 0xb0, 0xe7, 0xfe, 0x49, 0x24, 0xcf, 0x0a, 0x94, 0x6f, 0x47, 0x60, 0x54, 0x41, 0xb8, 0x97, 0x01, 0x76, + 0xbf, 0x17, 0xae, 0xff, 0x5f, 0xe5, 0x9d, 0x1f, 0xe4, 0xf7, 0xff, 0xb6, 0x86, 0xff, 0xcb, 0x6e, 0xba, 0xda, 0x60, + 0xff, 0x5b, 0x03, 0x94, 0xdf, 0x66, 0xa9, 0x1d, 0x48, 0xff, 0xd6, 0x09, 0xe1, 0x22, 0x4e, 0x27, 0x77, 0x02, 0x2b, + 0x3d, 0x4d, 0xce, 0xc1, 0xc0, 0x03, 0xfb, 0xff, 0x59, 0x0e, 0x40, 0x2f, 0xe0, 0x8b, 0x27, 0xd9, 0xb6, 0x9f, 0xe1, + 0x05, 0xb8, 0x53, 0xa2, 0x8c, 0x70, 0xc8, 0xeb, 0xca, 0xaf, 0xf8, 0xfa, 0x39, 0x24, 0x78, 0x75, 0x0a, 0xe6, 0xa7, + 0x93, 0x50, 0x59, 0x9e, 0x20, 0xee, 0xbb, 0x78, 0xb2, 0xd5, 0xa5, 0x84, 0x0f, 0x54, 0xeb, 0x43, 0x97, 0xe2, 0x23, + 0x7e, 0x47, 0xdd, 0x48, 0xe2, 0x27, 0xda, 0x3f, 0x6a, 0xf3, 0x91, 0xa7, 0x76, 0x41, 0xbc, 0x37, 0xb9, 0xf5, 0x17, + 0x11, 0xce, 0x3d, 0x21, 0xa9, 0x35, 0x09, 0x55, 0xe7, 0x24, 0x71, 0xc4, 0xd9, 0x1d, 0xda, 0x6a, 0x98, 0x93, 0xf0, + 0x9f, 0xaa, 0x2f, 0xb5, 0x4e, 0xae, 0x03, 0x11, 0x4d, 0xef, 0xb1, 0xd3, 0x65, 0x10, 0xa0, 0x06, 0xeb, 0xb3, 0xbc, + 0xa5, 0xdf, 0xf9, 0x1c, 0x9f, 0xaf, 0x26, 0xba, 0xb3, 0xa1, 0x7b, 0x34, 0xf2, 0x65, 0xfc, 0xf6, 0x21, 0x24, 0xd5, + 0xa4, 0x86, 0x1c, 0x4c, 0x24, 0x3a, 0xe7, 0xeb, 0xf4, 0x8b, 0xa8, 0xee, 0x5b, 0x0b, 0x8e, 0xb5, 0x39, 0xeb, 0x20, + 0x63, 0x98, 0x31, 0x18, 0x56, 0xd0, 0x00, 0x16, 0x63, 0x1c, 0x32, 0xef, 0xe8, 0x6e, 0x3f, 0x5a, 0xdb, 0xff, 0xfb, + 0x3c, 0x33, 0x20, 0xed, 0xf9, 0xc0, 0x5b, 0xd5, 0x47, 0xe1, 0x90, 0xb6, 0xef, 0xe9, 0xc1, 0xbe, 0x45, 0xa4, 0x17, + 0x31, 0xfd, 0x1a, 0xde, 0x9a, 0xc7, 0xcf, 0x47, 0x45, 0x69, 0x51, 0x47, 0x65, 0xf1, 0xc2, 0x1d, 0x1a, 0xf7, 0xd7, + 0xf0, 0xd9, 0x98, 0x77, 0x67, 0x83, 0x00, 0x32, 0x26, 0x5a, 0xc7, 0x6b, 0xb1, 0xff, 0xc5, 0x73, 0x3a, 0x0f, 0xe6, + 0xdb, 0x83, 0x63, 0x15, 0xb1, 0xf9, 0xd8, 0x4a, 0x2d, 0xd1, 0x37, 0x59, 0x9c, 0x6d, 0x21, 0x74, 0x65, 0x3b, 0x78, + 0xf6, 0xa4, 0x26, 0xaa, 0xce, 0x4e, 0xc8, 0x7b, 0x6a, 0xf3, 0xa2, 0xcb, 0x36, 0x7b, 0xb0, 0x49, 0x1b, 0x43, 0xe3, + 0x29, 0x75, 0x95, 0x6d, 0x5b, 0x19, 0x5f, 0x9b, 0xee, 0xeb, 0xef, 0x5f, 0x62, 0x69, 0xed, 0x04, 0x1d, 0x0a, 0x67, + 0x33, 0x62, 0xa6, 0xe0, 0x07, 0x14, 0x48, 0xb8, 0x61, 0x28, 0x89, 0x37, 0xc1, 0xaf, 0xa3, 0x36, 0x99, 0x12, 0x4c, + 0xc3, 0x68, 0xf6, 0xfd, 0x6b, 0x0f, 0x37, 0x3b, 0x7a, 0x11, 0x50, 0xe7, 0x8f, 0xac, 0xdb, 0x70, 0x32, 0x24, 0x84, + 0x8b, 0xbb, 0x75, 0x72, 0x0b, 0x3a, 0x26, 0xf2, 0x88, 0x23, 0x69, 0xc9, 0xdd, 0x79, 0xff, 0x88, 0x65, 0x3f, 0x5b, + 0xff, 0x89, 0x77, 0xb5, 0xa9, 0xec, 0x85, 0x92, 0x4d, 0xed, 0x67, 0xe8, 0x58, 0x94, 0x00, 0x4a, 0xa8, 0xbc, 0xb3, + 0x36, 0x67, 0x8f, 0xc6, 0xaa, 0xca, 0xe8, 0xb7, 0xbc, 0xae, 0x66, 0xc5, 0x82, 0xc7, 0xdd, 0xe2, 0x38, 0x8e, 0x8f, + 0xd5, 0x43, 0xdb, 0xfb, 0x15, 0x32, 0x95, 0xef, 0xf0, 0xb9, 0x7a, 0x23, 0x9f, 0x36, 0x16, 0xc9, 0xab, 0x87, 0x87, + 0x2c, 0xe4, 0xf3, 0xba, 0x39, 0x3a, 0xd1, 0xe4, 0x72, 0x8c, 0x4a, 0x16, 0x6b, 0xf9, 0x10, 0x69, 0x3b, 0x8b, 0x9d, + 0x44, 0x2f, 0xa5, 0x55, 0x67, 0x2c, 0x2c, 0x05, 0xdc, 0x97, 0x51, 0xb9, 0x42, 0x5d, 0x4d, 0x4a, 0x1d, 0x06, 0x72, + 0x1d, 0xa8, 0x0a, 0x36, 0xb4, 0x78, 0x64, 0x66, 0x05, 0xbf, 0xf0, 0xe9, 0x11, 0x11, 0x0c, 0x6c, 0x7b, 0x81, 0x8f, + 0xa7, 0xa9, 0xc5, 0xdc, 0xe0, 0x0b, 0x55, 0xc6, 0x3b, 0x5f, 0xf2, 0x39, 0x3a, 0x6b, 0x54, 0x48, 0x16, 0x43, 0x8e, + 0x46, 0x71, 0x8b, 0x56, 0xd2, 0xfe, 0x4b, 0xf2, 0x3e, 0x73, 0x4a, 0x89, 0x96, 0x5a, 0x82, 0x02, 0xd2, 0x34, 0x4d, + 0x77, 0x4d, 0xe9, 0x7b, 0xf1, 0x68, 0x9e, 0xd6, 0x68, 0x9b, 0xdb, 0x59, 0x0a, 0x09, 0xa2, 0x9b, 0xa2, 0x13, 0x8d, + 0xf4, 0x62, 0x00, 0x52, 0xae, 0x1f, 0x7a, 0x23, 0x64, 0xef, 0x74, 0xa6, 0x96, 0xf0, 0xe0, 0x94, 0x03, 0x61, 0xe5, + 0x9d, 0x35, 0x76, 0x9a, 0x46, 0xd7, 0x4a, 0xf6, 0x8e, 0xdf, 0xca, 0xe9, 0xa6, 0x39, 0x88, 0xaf, 0xa1, 0x7d, 0xed, + 0x55, 0x0a, 0x6c, 0x71, 0xad, 0xb6, 0x36, 0x17, 0xca, 0xba, 0xf4, 0x41, 0x8e, 0xdc, 0x2c, 0x30, 0x36, 0xe9, 0xad, + 0x73, 0xd9, 0xbb, 0x2e, 0x4a, 0x65, 0x0b, 0xbf, 0x56, 0xa5, 0x3d, 0xc1, 0x8a, 0x81, 0xe0, 0x38, 0x7e, 0x55, 0x10, + 0xcb, 0x6a, 0x54, 0xdb, 0xf1, 0x12, 0x2f, 0x0e, 0x8c, 0x55, 0xa8, 0xe7, 0xe8, 0x9d, 0x77, 0x84, 0x1a, 0xac, 0x27, + 0xa9, 0x50, 0xb2, 0xc9, 0x2c, 0x50, 0xac, 0xe2, 0x2e, 0x07, 0xf6, 0x4b, 0x50, 0x06, 0xe0, 0x7f, 0x32, 0x55, 0x76, + 0x7f, 0xaa, 0x39, 0x39, 0xb7, 0x4c, 0xed, 0x97, 0x92, 0x5c, 0xf3, 0xf3, 0xcc, 0xfa, 0x69, 0x30, 0xca, 0x68, 0x06, + 0x98, 0x97, 0xea, 0x5a, 0x76, 0x9e, 0xce, 0x14, 0xd7, 0xe0, 0x0f, 0x26, 0x49, 0x4f, 0xfb, 0xcf, 0x43, 0x0e, 0x7d, + 0x76, 0xea, 0xf9, 0xbd, 0x43, 0xce, 0x54, 0x7e, 0xfb, 0x69, 0x1e, 0x3c, 0xfd, 0xe3, 0x13, 0xfe, 0xfa, 0xf1, 0x5f, + 0xfa, 0x14, 0x9d, 0xe0, 0xcf, 0xd9, 0x4b, 0xe8, 0xa3, 0xda, 0x25, 0xdc, 0x8f, 0x56, 0xed, 0x01, 0x1a, 0x7d, 0x76, + 0xc1, 0x92, 0x57, 0x17, 0x8c, 0x03, 0x4a, 0xb5, 0x66, 0x2c, 0xb7, 0xfa, 0x9e, 0xb8, 0x7e, 0xb2, 0xd9, 0x2b, 0x5d, + 0x1a, 0xb8, 0x35, 0xb6, 0x9f, 0x97, 0x55, 0x0b, 0xd7, 0xbd, 0x32, 0xc9, 0xeb, 0xf7, 0x67, 0xd8, 0x13, 0xff, 0x3b, + 0x04, 0xc8, 0x0f, 0x08, 0x3c, 0x5a, 0x8d, 0x4b, 0x5f, 0xaa, 0x61, 0xa9, 0xaa, 0xe6, 0xa5, 0xa2, 0x5a, 0x96, 0x16, + 0xd5, 0xed, 0xe1, 0xe7, 0x27, 0x7e, 0xcf, 0x63, 0x5d, 0x98, 0x77, 0x25, 0xc8, 0xd9, 0xa6, 0x97, 0xa1, 0x92, 0x1b, + 0xee, 0x0a, 0x76, 0x2b, 0x85, 0x1f, 0xed, 0xe2, 0xd3, 0xbb, 0x1b, 0xf0, 0x56, 0x09, 0x7a, 0x35, 0xd3, 0x1c, 0x4f, + 0xd0, 0x2d, 0x26, 0x11, 0x20, 0x66, 0xa5, 0xa3, 0xbd, 0x0f, 0x1d, 0x0a, 0xca, 0x83, 0xec, 0x5a, 0x73, 0x8b, 0xfb, + 0x09, 0x26, 0xd4, 0xdf, 0x30, 0x01, 0x25, 0x63, 0x41, 0x54, 0x23, 0xa1, 0x46, 0x13, 0xde, 0x8a, 0x44, 0x00, 0xc4, + 0xfb, 0xa5, 0x4e, 0x72, 0x2f, 0x97, 0xa9, 0x50, 0x9d, 0x7b, 0x0b, 0x20, 0xf5, 0x54, 0x53, 0x5a, 0xea, 0x8b, 0x1a, + 0x06, 0xa9, 0xb8, 0xa6, 0x8c, 0x54, 0x09, 0x57, 0x7d, 0xc0, 0xfa, 0x86, 0xc5, 0xbc, 0xa2, 0x97, 0xac, 0x0d, 0x97, + 0xff, 0xd3, 0xfc, 0xe5, 0x98, 0x2d, 0xe4, 0x65, 0x27, 0x64, 0x8e, 0x65, 0x59, 0x8f, 0xac, 0x52, 0x8d, 0x97, 0xd6, + 0xe7, 0xb1, 0x97, 0xbf, 0xac, 0x05, 0xa2, 0x10, 0xd1, 0xe7, 0x75, 0x8c, 0xaa, 0x5c, 0x85, 0xbd, 0x0a, 0x64, 0x19, + 0x42, 0x6e, 0xd2, 0x50, 0x5a, 0x6f, 0x11, 0x8b, 0x16, 0x4b, 0x3c, 0x7d, 0x3f, 0xc8, 0xad, 0x19, 0x04, 0x6f, 0x03, + 0x88, 0x03, 0xba, 0xad, 0x4b, 0x2e, 0xf8, 0xff, 0xa8, 0x7f, 0x7a, 0x79, 0xf6, 0x3f, 0xa5, 0xba, 0x32, 0x22, 0xcf, + 0xd0, 0x77, 0x9a, 0x3c, 0x01, 0x0a, 0x62, 0xb0, 0x43, 0x34, 0x90, 0xf7, 0x53, 0xdf, 0xa1, 0x47, 0x20, 0x3c, 0x0e, + 0x05, 0x67, 0x30, 0x34, 0x55, 0x78, 0xa3, 0x41, 0x66, 0x3c, 0x1c, 0x3a, 0x11, 0x32, 0x34, 0x51, 0xe7, 0x74, 0x28, + 0x4b, 0x75, 0x25, 0xb3, 0xe6, 0x5f, 0x57, 0x31, 0x06, 0xfb, 0xf1, 0x72, 0xe5, 0xcb, 0x07, 0xed, 0x7e, 0xcf, 0xfe, + 0x64, 0x2e, 0x4c, 0xd1, 0x3b, 0xa9, 0x5b, 0x63, 0xd6, 0x1c, 0xf1, 0xc0, 0xb0, 0x3c, 0x8c, 0x1e, 0xf5, 0x84, 0xd8, + 0x6c, 0x87, 0x1e, 0x37, 0xed, 0x9b, 0x2c, 0xc3, 0x3c, 0xdc, 0x1f, 0x14, 0x76, 0x3f, 0x66, 0xde, 0xe5, 0xae, 0xc7, + 0x05, 0xbb, 0x3d, 0x1c, 0xd4, 0xaf, 0x41, 0xc1, 0x7f, 0xe4, 0x1d, 0x6b, 0x7b, 0x8c, 0xad, 0x47, 0x5e, 0x78, 0x9b, + 0x32, 0x5d, 0xd1, 0xca, 0x11, 0x0b, 0x27, 0x26, 0xd4, 0x18, 0x24, 0x31, 0x5c, 0xe5, 0x99, 0x7b, 0x0f, 0x41, 0x9c, + 0x71, 0x4e, 0x44, 0x7e, 0x22, 0x5b, 0x64, 0x7c, 0x5e, 0x7a, 0x6d, 0xb6, 0x6b, 0x42, 0x39, 0x46, 0xa8, 0x1c, 0x08, + 0xde, 0x05, 0x95, 0x43, 0xfb, 0xf1, 0xea, 0xa3, 0xcc, 0x16, 0xf5, 0x4f, 0xaf, 0x0c, 0xab, 0xe2, 0x2b, 0x7d, 0xdc, + 0xaa, 0x7f, 0x76, 0x74, 0x00, 0xaa, 0x7f, 0x40, 0xfa, 0x3d, 0xa5, 0xbc, 0x2e, 0x24, 0x1f, 0x99, 0x44, 0x73, 0xb3, + 0xa5, 0xc5, 0xba, 0x0b, 0x4b, 0x6d, 0x25, 0x8b, 0x43, 0x9d, 0xb7, 0x86, 0xd7, 0xb5, 0x6f, 0x4d, 0x8f, 0x0e, 0xf5, + 0x8b, 0xd4, 0xd6, 0xe7, 0xbf, 0xc3, 0x7d, 0xfd, 0x86, 0x51, 0xad, 0xb6, 0xc6, 0xa5, 0x27, 0xe9, 0xd3, 0x62, 0x51, + 0xd1, 0xd0, 0xc5, 0x3e, 0xfd, 0x2e, 0x1a, 0x1a, 0xe8, 0xd8, 0xb3, 0xb6, 0x5e, 0x69, 0x9c, 0xee, 0x0b, 0x74, 0xd0, + 0x69, 0x39, 0x42, 0xd2, 0xbd, 0x61, 0x60, 0x10, 0xa0, 0x98, 0xc1, 0x26, 0xc4, 0x74, 0xcb, 0xcf, 0x4e, 0xa3, 0x99, + 0xbb, 0x13, 0x6e, 0x7f, 0xb1, 0x3e, 0x01, 0xd5, 0x2f, 0xf3, 0x77, 0xaa, 0x68, 0x3e, 0xe2, 0x8f, 0x78, 0xd0, 0x86, + 0x44, 0xbe, 0x0e, 0x89, 0xf5, 0xb4, 0x31, 0x96, 0x6e, 0x88, 0xd8, 0xae, 0xab, 0x27, 0x0f, 0x2b, 0xaf, 0x6d, 0x34, + 0x75, 0xf9, 0x95, 0x6d, 0x5b, 0xfa, 0xbc, 0xf2, 0x80, 0x81, 0xe3, 0xae, 0x87, 0x0e, 0x7c, 0x25, 0xc9, 0xd8, 0x82, + 0xf7, 0x4a, 0xe2, 0x7f, 0x89, 0xfd, 0x3b, 0x39, 0x62, 0x9b, 0x1a, 0xa8, 0x59, 0xea, 0xee, 0x04, 0x9b, 0x35, 0xb5, + 0x90, 0x34, 0x47, 0x8f, 0x69, 0xf5, 0xd3, 0xf2, 0x98, 0xef, 0x76, 0x1e, 0x5b, 0x3f, 0xfb, 0x28, 0x0b, 0x2a, 0x4c, + 0xcf, 0xd8, 0x21, 0x70, 0xc6, 0xb0, 0xa8, 0x8c, 0x45, 0x99, 0xdc, 0xdb, 0x94, 0x13, 0x69, 0xb2, 0x7c, 0x1f, 0x7e, + 0xe7, 0x82, 0x0a, 0xe8, 0x35, 0x3e, 0x8f, 0xee, 0x50, 0x7e, 0x5c, 0xf6, 0x06, 0x3c, 0x3d, 0x48, 0x99, 0xea, 0x0e, + 0x3a, 0xa5, 0xe9, 0xd3, 0xbc, 0xfe, 0xb8, 0x1f, 0xfd, 0x84, 0xeb, 0x1f, 0xff, 0x93, 0x4c, 0x8f, 0x5f, 0x43, 0x32, + 0x4c, 0x82, 0xd3, 0x14, 0x76, 0xb5, 0xf2, 0xff, 0xdd, 0x32, 0xf5, 0x4a, 0x5c, 0x0c, 0x6f, 0xea, 0xf8, 0x01, 0x51, + 0x34, 0xeb, 0x23, 0xcb, 0x98, 0x4f, 0xdb, 0xf2, 0xc3, 0xb6, 0x54, 0x87, 0xb8, 0xc8, 0x9d, 0xcb, 0x92, 0xd8, 0x35, + 0x28, 0xd3, 0x1a, 0x29, 0xed, 0x33, 0xe6, 0xb0, 0x37, 0x93, 0x76, 0x2f, 0x2d, 0x6d, 0x29, 0xa4, 0xe0, 0x68, 0x8a, + 0x33, 0x1a, 0xc0, 0x7d, 0xac, 0x49, 0xdf, 0xda, 0x35, 0x7a, 0x3e, 0x1e, 0xcb, 0x4a, 0xae, 0x24, 0x9d, 0xcb, 0x52, + 0x0e, 0x1f, 0x71, 0x2b, 0xf7, 0x11, 0x23, 0x20, 0xe6, 0xc5, 0xaa, 0xd2, 0x02, 0x33, 0x44, 0x0d, 0x2e, 0x95, 0x8e, + 0xb1, 0x54, 0x06, 0x13, 0xb5, 0xbe, 0xbc, 0xa0, 0x5d, 0xbe, 0x81, 0x03, 0xa9, 0x3b, 0xef, 0x61, 0x75, 0x62, 0xa9, + 0xd0, 0xe5, 0xd0, 0xde, 0x96, 0xf4, 0xc4, 0xe5, 0x7c, 0x24, 0x90, 0xc6, 0x02, 0x54, 0x78, 0x6c, 0x5f, 0xe2, 0xcf, + 0x22, 0xf2, 0x47, 0x61, 0xf3, 0x22, 0xce, 0x06, 0x9a, 0x82, 0x56, 0x50, 0x8d, 0x69, 0xf4, 0x5f, 0x56, 0x09, 0x41, + 0x4a, 0xc1, 0x56, 0xd4, 0x1c, 0xf0, 0x0c, 0xd9, 0x38, 0x89, 0x44, 0x60, 0x87, 0xe9, 0xe0, 0x42, 0xdb, 0x2f, 0x64, + 0x89, 0xd6, 0x4f, 0x23, 0x63, 0x0f, 0x49, 0x78, 0xf8, 0x72, 0x99, 0xe8, 0x95, 0x38, 0x13, 0x6f, 0xe9, 0x5b, 0x0b, + 0xfe, 0x79, 0x5d, 0x0b, 0xf6, 0xd9, 0x20, 0x7b, 0x89, 0x8f, 0x3c, 0x0c, 0xf1, 0x74, 0x85, 0xdb, 0xee, 0x41, 0xe5, + 0x5e, 0x12, 0x0f, 0x6b, 0x7b, 0x7b, 0x70, 0xbe, 0xb3, 0xf6, 0xb4, 0x56, 0xad, 0x0f, 0x94, 0x6b, 0x4c, 0xfb, 0xe1, + 0xf5, 0x97, 0xf7, 0xad, 0x29, 0x95, 0x7e, 0x14, 0xba, 0x99, 0x84, 0xb1, 0xf2, 0x6c, 0xef, 0x4c, 0xf6, 0x61, 0x48, + 0x4f, 0xf5, 0x80, 0xd3, 0x8e, 0x12, 0xb7, 0x64, 0x35, 0x1e, 0x65, 0x6f, 0x12, 0xf4, 0xa9, 0xac, 0x68, 0x20, 0xa2, + 0x9a, 0x7f, 0x3f, 0x19, 0x0b, 0xcc, 0x0c, 0xc4, 0xe0, 0xe3, 0xb9, 0x6d, 0xc9, 0x2c, 0xe0, 0x7e, 0xcc, 0xdf, 0x36, + 0xd1, 0xa4, 0x1d, 0x3b, 0x08, 0x87, 0x51, 0x30, 0xef, 0xd5, 0x5b, 0xc2, 0xfd, 0x50, 0xca, 0xcf, 0xc0, 0xcf, 0x8e, + 0x81, 0x13, 0x9c, 0x15, 0xf1, 0x32, 0xb4, 0xdf, 0x10, 0xce, 0xc8, 0x44, 0xf0, 0xa3, 0xe2, 0xee, 0x00, 0xdb, 0x4d, + 0x73, 0xb8, 0xc7, 0x3f, 0x3d, 0x1b, 0x70, 0x27, 0x29, 0x7d, 0xc9, 0x24, 0x07, 0xef, 0x56, 0x19, 0x92, 0x2d, 0x15, + 0x39, 0xd9, 0xc4, 0x72, 0xda, 0x53, 0x8e, 0x70, 0x7b, 0xa7, 0x4b, 0xbf, 0xa7, 0x3c, 0x3a, 0xef, 0xc5, 0xa5, 0xde, + 0x43, 0x3c, 0x7a, 0xea, 0x6d, 0x83, 0xb6, 0xcd, 0xd2, 0xd2, 0x9c, 0x94, 0x2e, 0x75, 0xa6, 0x6b, 0x97, 0x89, 0xd1, + 0x95, 0x2f, 0x9a, 0x77, 0xc8, 0x15, 0x86, 0x28, 0x3d, 0x75, 0x60, 0xb3, 0xda, 0xa7, 0x44, 0x89, 0xd4, 0x61, 0x95, + 0x48, 0x7a, 0x14, 0x29, 0xc4, 0x27, 0x67, 0x89, 0xa0, 0xf7, 0x69, 0x6c, 0x01, 0xa5, 0x65, 0x35, 0x79, 0x14, 0xbd, + 0x62, 0xde, 0x8b, 0xdb, 0xd8, 0x29, 0x34, 0x8b, 0x4d, 0x36, 0x9b, 0xc9, 0xde, 0x4b, 0xff, 0xf5, 0xdf, 0xb9, 0xae, + 0xa0, 0xdf, 0x8f, 0xe9, 0x12, 0xff, 0x7a, 0x0d, 0xf0, 0x5e, 0x8d, 0x82, 0xe8, 0x61, 0x8a, 0xba, 0x2b, 0xe6, 0x80, + 0x2e, 0x84, 0xf0, 0x55, 0xa4, 0xab, 0x1a, 0x79, 0xba, 0x54, 0xfc, 0x49, 0xb2, 0xdb, 0x08, 0x9b, 0x3a, 0x6d, 0x4b, + 0x06, 0x68, 0x5f, 0x81, 0xeb, 0x24, 0xeb, 0x35, 0x8a, 0xc8, 0x1d, 0x14, 0xfd, 0x27, 0x7f, 0xd6, 0xc4, 0xcf, 0x16, + 0xf1, 0x63, 0x98, 0xf2, 0xb1, 0x4f, 0x32, 0xc6, 0x20, 0xe6, 0x14, 0x72, 0x13, 0x88, 0x77, 0x63, 0xc2, 0x96, 0x3c, + 0x83, 0x46, 0xbf, 0x37, 0x4d, 0x29, 0x55, 0x59, 0x2f, 0xab, 0xb6, 0x64, 0xd7, 0x8e, 0x5b, 0x7b, 0x16, 0xd3, 0xfc, + 0x18, 0x58, 0x8d, 0xdf, 0x8b, 0x14, 0xaf, 0x1c, 0x15, 0x76, 0xb7, 0xb8, 0x2a, 0x8e, 0x21, 0x78, 0xfd, 0xf8, 0xf3, + 0x20, 0x70, 0x22, 0x3b, 0xdd, 0x5b, 0x02, 0xe5, 0xbb, 0x6b, 0xe3, 0xf4, 0x37, 0xf9, 0xea, 0xf7, 0x7d, 0x74, 0x8f, + 0xfa, 0x33, 0xa6, 0xce, 0x5e, 0x25, 0x9c, 0x6e, 0x11, 0xfd, 0xcf, 0xa1, 0x2d, 0x2f, 0xb7, 0xe6, 0x8e, 0xaa, 0x70, + 0x9f, 0x18, 0xdf, 0x7b, 0x52, 0x26, 0xa3, 0x3d, 0xf8, 0xdb, 0x9d, 0x7a, 0xfe, 0xc7, 0x84, 0x23, 0x08, 0x6f, 0xba, + 0xf1, 0x41, 0xbf, 0xa7, 0x74, 0xfc, 0x34, 0x2f, 0x9f, 0xfe, 0xe1, 0x09, 0x97, 0x3f, 0xfe, 0x27, 0x39, 0xf6, 0x8e, + 0xb9, 0x34, 0xef, 0x80, 0xdd, 0x7d, 0x16, 0xf1, 0x74, 0xf2, 0x5a, 0x2e, 0x91, 0x3f, 0x55, 0x3d, 0x5e, 0x09, 0x2f, + 0x0f, 0x76, 0x02, 0x16, 0x68, 0x11, 0x79, 0xcf, 0xe6, 0x25, 0x68, 0xc1, 0x90, 0x1d, 0xc5, 0xd1, 0xc4, 0x9b, 0x01, + 0xa6, 0x42, 0x6a, 0x35, 0x88, 0x0e, 0xcc, 0x77, 0xdf, 0xc9, 0x7c, 0x20, 0xcc, 0x1a, 0x26, 0x54, 0x71, 0x27, 0xde, + 0xa5, 0x1e, 0x49, 0x4a, 0x75, 0x55, 0xef, 0x45, 0xa2, 0xcc, 0x7e, 0x40, 0x7a, 0xcc, 0x02, 0x63, 0x26, 0x42, 0x03, + 0xf0, 0x0c, 0x01, 0x91, 0xc3, 0x48, 0x4e, 0x92, 0xbe, 0xd5, 0x81, 0x11, 0xef, 0x38, 0x4d, 0x95, 0xaf, 0x04, 0x90, + 0x9f, 0x65, 0xe5, 0xf1, 0xdd, 0x5d, 0x9a, 0xd9, 0x70, 0x47, 0xe7, 0x5b, 0xef, 0x82, 0x6f, 0x68, 0xd2, 0x55, 0xb9, + 0xa7, 0x02, 0xc2, 0xc6, 0xd5, 0x25, 0x64, 0xc4, 0x39, 0xe4, 0x50, 0xa6, 0x60, 0x07, 0x52, 0x89, 0x75, 0xe8, 0xc9, + 0xc0, 0x1f, 0xbd, 0x2e, 0x01, 0x11, 0x4b, 0x29, 0x79, 0x92, 0xb3, 0xdd, 0x18, 0x8e, 0x4d, 0xe4, 0xe2, 0x3d, 0xa9, + 0x7b, 0x6f, 0x70, 0xbc, 0x86, 0x2a, 0x89, 0x54, 0x6b, 0x21, 0xad, 0x4a, 0xba, 0xef, 0x6c, 0x0f, 0x37, 0x9c, 0xfc, + 0x63, 0x6d, 0xe4, 0x8f, 0x4c, 0xee, 0xf1, 0x9e, 0x31, 0x69, 0x1e, 0x70, 0x96, 0xcd, 0xa2, 0x00, 0x46, 0x99, 0x6a, + 0x97, 0x9c, 0x75, 0x94, 0x4b, 0x2d, 0x4a, 0x5a, 0x06, 0xbe, 0x42, 0x91, 0xe4, 0xe6, 0x37, 0x7a, 0xbd, 0xe9, 0x7b, + 0x34, 0x97, 0x10, 0xe8, 0x95, 0x7e, 0xce, 0xd7, 0x7b, 0xba, 0x7a, 0xdf, 0x55, 0xb6, 0xb3, 0x0b, 0x56, 0x69, 0xac, + 0xf7, 0x86, 0x5b, 0x01, 0xc8, 0x02, 0xb1, 0xce, 0x0d, 0xcb, 0xed, 0xbe, 0x47, 0xd4, 0xeb, 0x33, 0x9f, 0xd8, 0x13, + 0x19, 0x51, 0xba, 0x45, 0x24, 0xba, 0x20, 0xe2, 0xff, 0x3f, 0xf7, 0x69, 0x2c, 0x26, 0xb7, 0xad, 0x91, 0x2a, 0xbf, + 0x6e, 0x9d, 0xe5, 0xc5, 0xfe, 0x2d, 0xd7, 0x15, 0x82, 0x62, 0x64, 0x06, 0x32, 0x45, 0xd3, 0x34, 0xbb, 0x0f, 0x93, + 0x19, 0x5b, 0x22, 0x34, 0xa2, 0x4c, 0x4a, 0xcb, 0x35, 0xd2, 0x42, 0x42, 0x2b, 0x07, 0x90, 0x61, 0x52, 0xda, 0x85, + 0x16, 0xd7, 0x3a, 0x24, 0x83, 0xe7, 0xb3, 0x49, 0x8f, 0xa7, 0x84, 0x24, 0x70, 0x73, 0xad, 0x22, 0xc2, 0x1c, 0xd5, + 0x16, 0x84, 0xf0, 0x63, 0x7f, 0x01, 0x3a, 0x61, 0x52, 0x03, 0xdf, 0x68, 0xf1, 0x2e, 0x08, 0x02, 0xb4, 0x78, 0x42, + 0x72, 0x0c, 0x0e, 0x40, 0x6a, 0xc9, 0x4a, 0x7f, 0x90, 0xa4, 0xeb, 0xb0, 0x3f, 0x1f, 0x33, 0x6e, 0xce, 0xa7, 0x9d, + 0xe9, 0xc9, 0x04, 0xe8, 0xd5, 0x07, 0x0e, 0xc3, 0x76, 0xc7, 0xc0, 0xf0, 0x28, 0xe8, 0xd3, 0x44, 0xf7, 0x7b, 0xb8, + 0xe9, 0xb2, 0xdd, 0x97, 0x43, 0x4c, 0x04, 0x8b, 0x99, 0xec, 0x66, 0x1c, 0xe1, 0xec, 0x86, 0x8d, 0xf6, 0x48, 0xb5, + 0xc6, 0x7e, 0x1f, 0x94, 0x2a, 0x36, 0x34, 0xdd, 0x49, 0xcf, 0x2c, 0xc3, 0xec, 0x16, 0x9a, 0xac, 0x2a, 0x03, 0x4e, + 0xa2, 0x02, 0x9c, 0x48, 0x61, 0xdb, 0xe8, 0xd8, 0xf0, 0xa6, 0x28, 0x81, 0xe6, 0xa1, 0x25, 0x46, 0x9f, 0x02, 0xef, + 0x52, 0x52, 0xf1, 0x8b, 0xd5, 0x98, 0x4a, 0xb2, 0xa1, 0x49, 0x8a, 0xcc, 0x72, 0x7c, 0xba, 0x8b, 0xdc, 0xb0, 0x3c, + 0x61, 0x3a, 0xb5, 0x66, 0x59, 0x91, 0x49, 0xd1, 0xfd, 0x7f, 0xf5, 0xe4, 0x90, 0x90, 0x56, 0xd5, 0xdc, 0x4d, 0x95, + 0x72, 0xf8, 0x8c, 0x5b, 0xc9, 0x04, 0xae, 0x89, 0x2f, 0xf4, 0x6c, 0x67, 0xdf, 0x80, 0xee, 0x94, 0x1a, 0x14, 0x77, + 0x21, 0x07, 0x85, 0x19, 0x35, 0xd8, 0xfb, 0x0b, 0xa2, 0xc7, 0xa3, 0xe4, 0xa6, 0xf1, 0x77, 0x0e, 0x57, 0xa8, 0x7a, + 0x23, 0xe9, 0xb4, 0x7f, 0xe0, 0x22, 0x70, 0x54, 0xa7, 0xc6, 0x98, 0x77, 0x37, 0x5a, 0xb7, 0x17, 0x55, 0xdc, 0x21, + 0x03, 0xec, 0x6b, 0x79, 0xd7, 0x02, 0x6b, 0xaf, 0x78, 0xd3, 0x48, 0x6e, 0x91, 0x8f, 0xff, 0xda, 0x67, 0xb7, 0xc5, + 0x2d, 0x5a, 0x64, 0x6a, 0xbb, 0x3c, 0x58, 0xf4, 0x65, 0x1b, 0x36, 0xa3, 0xd3, 0xb3, 0xbf, 0xb9, 0x90, 0xcd, 0x67, + 0x06, 0xb5, 0xc3, 0x4f, 0x1f, 0x4f, 0x5d, 0x1c, 0x38, 0x45, 0x2c, 0xf1, 0x10, 0x4e, 0xda, 0x56, 0xab, 0xcb, 0x14, + 0xbd, 0xec, 0xbe, 0x05, 0x92, 0x60, 0x16, 0xe7, 0x53, 0x0f, 0x5f, 0x88, 0x57, 0x28, 0x38, 0x6c, 0x1f, 0xf6, 0x57, + 0x71, 0x24, 0x6f, 0xfd, 0x53, 0xbd, 0x71, 0xd0, 0xf2, 0xab, 0x9c, 0xbb, 0x97, 0xeb, 0x77, 0x5d, 0x9b, 0xf2, 0x2a, + 0xee, 0xd7, 0xad, 0x7f, 0xda, 0x10, 0xa5, 0x62, 0x4f, 0x26, 0x3d, 0x9f, 0x9b, 0xe5, 0xc7, 0xef, 0x57, 0x26, 0x94, + 0x2f, 0x46, 0x18, 0x50, 0xab, 0x1f, 0xc2, 0x4c, 0x47, 0x8a, 0x6f, 0x92, 0x9a, 0xb2, 0x06, 0xad, 0x50, 0x4c, 0x59, + 0x6d, 0xe2, 0x7c, 0xe8, 0xa0, 0xd9, 0x48, 0x87, 0xc3, 0x6e, 0x49, 0xac, 0xf5, 0xd3, 0x54, 0x4f, 0x23, 0x70, 0x08, + 0x82, 0xf3, 0x83, 0x4a, 0x2d, 0x39, 0xc6, 0x73, 0x6e, 0xd5, 0x33, 0x64, 0x31, 0xa2, 0xca, 0x64, 0xcc, 0xe4, 0xe6, + 0x0d, 0x15, 0x46, 0x95, 0x79, 0xe8, 0x00, 0x0a, 0x47, 0x32, 0xdb, 0x71, 0xe3, 0x8b, 0xc7, 0x4c, 0x53, 0xd5, 0x0b, + 0x22, 0xbe, 0x7f, 0x5d, 0xe7, 0x8e, 0x84, 0x0e, 0xa4, 0xee, 0x1d, 0x91, 0xa9, 0x55, 0x9b, 0x8c, 0x0e, 0x68, 0xe8, + 0x3a, 0x8a, 0xcc, 0x8f, 0x55, 0x55, 0x91, 0x4d, 0xd5, 0xae, 0x4c, 0x46, 0x91, 0x43, 0xac, 0x3b, 0x4a, 0x59, 0x4e, + 0x96, 0xb5, 0xd1, 0xb5, 0x89, 0xc8, 0x6a, 0xb7, 0x25, 0x91, 0x6a, 0x3f, 0x48, 0x83, 0xd3, 0xd0, 0x7b, 0x0a, 0xb0, + 0xf9, 0xd4, 0x92, 0xa4, 0x5d, 0x4b, 0xd1, 0xf0, 0xb1, 0xf3, 0xd2, 0x5d, 0x77, 0x17, 0x96, 0x23, 0x84, 0x71, 0x4a, + 0x70, 0x0a, 0x2a, 0x2d, 0xe8, 0x18, 0x84, 0x37, 0x62, 0xba, 0x68, 0xf7, 0x00, 0xe0, 0xd9, 0xb9, 0xcc, 0x5e, 0x01, + 0x40, 0xca, 0xac, 0x02, 0x4d, 0xf3, 0xc7, 0x8d, 0x38, 0x94, 0x39, 0xd9, 0x91, 0x6a, 0x8a, 0x98, 0x14, 0xdf, 0x13, + 0x0d, 0x75, 0x82, 0xec, 0xc7, 0x94, 0x46, 0xfc, 0x41, 0x1e, 0x6c, 0xcb, 0xce, 0xb9, 0xdd, 0x98, 0x22, 0xc7, 0xc4, + 0x93, 0xa1, 0x15, 0xb9, 0x41, 0x3c, 0xe9, 0x7b, 0x7c, 0xad, 0xba, 0x70, 0xe5, 0xc1, 0xec, 0xf2, 0xe2, 0xfd, 0x31, + 0xff, 0x77, 0x1b, 0x85, 0xda, 0xe4, 0x61, 0xc5, 0x9f, 0x02, 0xb2, 0x3b, 0xa4, 0xcb, 0x63, 0x73, 0x89, 0x7f, 0xe5, + 0xc2, 0x0f, 0x9b, 0xd0, 0x61, 0x17, 0xd3, 0x69, 0x46, 0x2f, 0x83, 0x14, 0x84, 0x3d, 0x0b, 0x9f, 0x96, 0x4c, 0xe3, + 0x26, 0xc9, 0x24, 0xad, 0x7f, 0xb7, 0x29, 0xad, 0x69, 0xa4, 0xc6, 0x51, 0x77, 0x83, 0xf2, 0x84, 0x9f, 0xdf, 0x45, + 0xcd, 0x8f, 0xbd, 0xdb, 0xa6, 0x20, 0x9a, 0x60, 0x15, 0x86, 0x88, 0x72, 0xfa, 0xcd, 0x12, 0x67, 0x6e, 0x09, 0x7b, + 0x48, 0x79, 0xb5, 0x8d, 0x35, 0x3e, 0xdd, 0xbc, 0x54, 0x5b, 0x1f, 0x74, 0x4f, 0x55, 0xf5, 0x37, 0xdb, 0x86, 0xa2, + 0xd1, 0x29, 0xe1, 0x15, 0x45, 0x23, 0x3b, 0xf5, 0xc3, 0x21, 0x5b, 0x8d, 0xa2, 0x10, 0x59, 0xcc, 0xe2, 0x87, 0x5d, + 0x2a, 0x02, 0x1a, 0x86, 0xd9, 0xfc, 0xd3, 0xec, 0x4a, 0x46, 0x9e, 0x44, 0xb3, 0x6f, 0x3d, 0x63, 0xdb, 0xae, 0xdf, + 0xda, 0x67, 0x76, 0xeb, 0x3d, 0x66, 0x6b, 0x67, 0x77, 0x28, 0xa4, 0x83, 0x18, 0xf7, 0x6b, 0xd7, 0x16, 0x73, 0xf5, + 0x34, 0x64, 0x95, 0x8f, 0x2b, 0x46, 0x38, 0xfc, 0x1a, 0xe8, 0xe2, 0x33, 0x66, 0x41, 0x68, 0xd7, 0x38, 0x6d, 0x1f, + 0x0e, 0xd0, 0x9a, 0x1e, 0xcc, 0xf4, 0x4c, 0x0f, 0xd0, 0x6e, 0x4e, 0x10, 0xa0, 0x81, 0x12, 0x4f, 0xf0, 0xbf, 0x92, + 0x38, 0x57, 0xd9, 0xed, 0xfc, 0x5a, 0x23, 0x2b, 0xae, 0x3f, 0xa4, 0x82, 0x3e, 0x8d, 0x36, 0x13, 0x3a, 0x77, 0x4b, + 0xc5, 0x3b, 0x50, 0x5c, 0x2b, 0xc3, 0xee, 0x26, 0xa0, 0xcd, 0x53, 0xf1, 0xfb, 0xaa, 0xff, 0x28, 0xa0, 0x86, 0x1e, + 0x9b, 0xa3, 0xc4, 0x3d, 0xdb, 0xaa, 0x62, 0x56, 0x19, 0xb4, 0x03, 0x06, 0x83, 0xbf, 0xb6, 0x9a, 0xd6, 0xc8, 0xe6, + 0xe9, 0xef, 0x22, 0x7a, 0x4d, 0xdd, 0x19, 0xb9, 0x5f, 0xc1, 0x75, 0x1f, 0x59, 0xab, 0x86, 0x4e, 0xda, 0x73, 0xa7, + 0x61, 0x1b, 0x79, 0x82, 0x09, 0x74, 0x50, 0xb1, 0xa9, 0xc1, 0x05, 0xfb, 0x48, 0xd1, 0xb2, 0x56, 0x83, 0x66, 0x51, + 0x27, 0x72, 0x97, 0x81, 0x0a, 0xf1, 0x6d, 0x52, 0x06, 0xcb, 0x32, 0xb4, 0x8a, 0x38, 0x1e, 0x65, 0x36, 0xb8, 0x02, + 0x53, 0xe0, 0xad, 0x34, 0x94, 0xcd, 0x9e, 0xe0, 0x89, 0xd2, 0x12, 0x4e, 0x7e, 0x78, 0xe2, 0x35, 0x6a, 0x09, 0x3e, + 0x87, 0xa6, 0xfd, 0x07, 0x69, 0x69, 0xe6, 0xfa, 0x93, 0x23, 0x3d, 0x78, 0x0e, 0x6f, 0xcd, 0x04, 0xbe, 0x4b, 0x3c, + 0x1d, 0xb9, 0xf6, 0xfc, 0x43, 0xe2, 0x81, 0x5d, 0x61, 0x22, 0x24, 0x21, 0x2c, 0x5c, 0x7b, 0xa7, 0xad, 0xc5, 0xff, + 0x70, 0x06, 0x8c, 0x11, 0x23, 0x6c, 0x07, 0x05, 0x4e, 0x1f, 0xb6, 0x51, 0x84, 0x30, 0x5f, 0x7e, 0xcd, 0x8e, 0x91, + 0xdc, 0x54, 0x5e, 0x5c, 0xc4, 0x18, 0xc1, 0x56, 0xce, 0x4a, 0xfc, 0x80, 0x88, 0x4c, 0xe6, 0x05, 0xc3, 0x36, 0xfc, + 0x1e, 0xdf, 0xf5, 0xdd, 0xc4, 0xf7, 0x80, 0xf5, 0x8c, 0x0f, 0xd5, 0x73, 0xdf, 0xcf, 0x91, 0x44, 0xeb, 0x69, 0xfb, + 0x83, 0x20, 0x58, 0x6c, 0xba, 0xb5, 0x33, 0xb5, 0x86, 0xfe, 0x41, 0x98, 0xe0, 0xf6, 0xbc, 0xa9, 0x28, 0x56, 0xe2, + 0xf2, 0xfa, 0x82, 0x37, 0x3c, 0x1e, 0x60, 0x9f, 0xde, 0x59, 0xbb, 0x7b, 0x73, 0x97, 0xde, 0x8d, 0x3b, 0xf1, 0xa4, + 0x7f, 0x47, 0x3d, 0xe4, 0x6b, 0x9e, 0x31, 0xa3, 0x5d, 0x95, 0x65, 0xbf, 0xa4, 0xdf, 0x39, 0xa7, 0x33, 0x1d, 0xc1, + 0x44, 0xfa, 0x1b, 0xf8, 0xfa, 0x58, 0x6c, 0x7f, 0x21, 0x39, 0x46, 0xd3, 0x05, 0x66, 0x8d, 0xd4, 0x0b, 0x0b, 0x6d, + 0xda, 0x17, 0xdd, 0x2d, 0x40, 0xc5, 0x02, 0x55, 0x78, 0xe0, 0xed, 0xc8, 0x1f, 0x71, 0xbb, 0xd2, 0x8b, 0x81, 0x65, + 0xf6, 0x8f, 0x9c, 0xfd, 0xc9, 0xeb, 0x50, 0x89, 0xbe, 0x88, 0xd6, 0x27, 0x94, 0xa9, 0xb0, 0x4b, 0x44, 0x39, 0x72, + 0x23, 0x8e, 0x3e, 0x1d, 0x3d, 0x89, 0x80, 0x0d, 0x52, 0x37, 0x22, 0xac, 0xb8, 0x27, 0x9f, 0x45, 0x69, 0x40, 0x2f, + 0x80, 0xd4, 0x0f, 0x67, 0x1c, 0xea, 0xfa, 0x37, 0x61, 0x26, 0x5a, 0x1c, 0xc6, 0x73, 0x5f, 0x66, 0x55, 0x68, 0xdd, + 0xf3, 0x28, 0x3e, 0x49, 0xe4, 0x7b, 0xf7, 0xd8, 0xe2, 0x48, 0x70, 0xe6, 0x9b, 0xa0, 0x17, 0xf2, 0xa4, 0xbf, 0x65, + 0x41, 0x74, 0xe7, 0x17, 0x52, 0xab, 0x12, 0xb9, 0xb9, 0xc0, 0xb1, 0x60, 0x99, 0x43, 0x0e, 0x7f, 0xd6, 0x9e, 0xa5, + 0xf5, 0x3b, 0x18, 0xd5, 0x30, 0x8f, 0xff, 0x5c, 0x7c, 0xca, 0x42, 0x91, 0xa9, 0x17, 0x8f, 0x3f, 0x45, 0x69, 0x10, + 0xdd, 0x9e, 0x44, 0x28, 0xb6, 0x91, 0xba, 0x44, 0x90, 0x28, 0x1c, 0x67, 0x6a, 0xdf, 0xdf, 0xe5, 0xd9, 0x70, 0x17, + 0xcd, 0x3f, 0x0d, 0xa0, 0x27, 0xbf, 0x4a, 0xeb, 0xef, 0x17, 0x7f, 0x4a, 0x8a, 0xe0, 0xf6, 0xac, 0x9f, 0xce, 0xfc, + 0xd8, 0x59, 0xe9, 0x62, 0x10, 0x3d, 0x82, 0xd5, 0xb8, 0xa2, 0x4a, 0x7e, 0x06, 0x3f, 0xb1, 0xfd, 0x61, 0xe1, 0x66, + 0xc4, 0xbf, 0x8f, 0x4f, 0xee, 0xe2, 0x7c, 0x3a, 0x57, 0x58, 0x75, 0x38, 0x03, 0xa2, 0x86, 0xd1, 0xa5, 0xea, 0x62, + 0xc7, 0x91, 0xf9, 0x97, 0x05, 0x6b, 0x3c, 0x8b, 0x04, 0xa6, 0xf3, 0x0f, 0x2f, 0x3f, 0x62, 0xe4, 0xc9, 0x62, 0xb2, + 0xbf, 0xf8, 0x42, 0x9d, 0x38, 0xb8, 0xa7, 0xdd, 0xd6, 0xaf, 0x44, 0xc9, 0xa7, 0xf9, 0xe3, 0xe3, 0xfe, 0xba, 0x9f, + 0xf0, 0xe3, 0xc7, 0xbf, 0xf4, 0x57, 0xd9, 0x9a, 0x67, 0xdf, 0x85, 0x33, 0xca, 0x61, 0xb7, 0x17, 0x31, 0x3b, 0xd9, + 0xbf, 0xd7, 0x1f, 0x5f, 0x63, 0x4f, 0xee, 0xef, 0x19, 0x3e, 0xfd, 0xf6, 0xf2, 0xfe, 0x5d, 0x78, 0xb7, 0x90, 0xcb, + 0x8c, 0xbd, 0x39, 0x37, 0xd7, 0xa5, 0xac, 0xa5, 0xd9, 0x7a, 0x91, 0x80, 0x24, 0x88, 0x89, 0x0d, 0x2a, 0xf0, 0x44, + 0x12, 0x2d, 0xcb, 0x20, 0x47, 0x30, 0xe4, 0xe4, 0x38, 0xec, 0xce, 0x79, 0xc6, 0x82, 0x54, 0x19, 0x51, 0x5e, 0xa2, + 0x38, 0xdb, 0x7a, 0xcc, 0x00, 0x9c, 0x81, 0xf7, 0x11, 0xc8, 0xef, 0x6a, 0x10, 0x07, 0x4d, 0x06, 0x69, 0xf0, 0xed, + 0xa7, 0xae, 0x77, 0x64, 0xc3, 0x75, 0x65, 0xbc, 0xde, 0xbb, 0x97, 0x89, 0x93, 0x7d, 0x09, 0x66, 0xe3, 0x1d, 0x4a, + 0x99, 0x29, 0xc2, 0xdb, 0xcc, 0x33, 0xe7, 0x21, 0x16, 0x8e, 0x47, 0x92, 0x39, 0x88, 0x3f, 0x2d, 0x5d, 0xc1, 0xe9, + 0x38, 0xc9, 0x21, 0x3e, 0x55, 0xc1, 0x17, 0x0c, 0xbd, 0xce, 0xe6, 0xd3, 0xca, 0x9c, 0x9c, 0xac, 0xda, 0x70, 0x05, + 0xbe, 0xbd, 0xf5, 0x39, 0xbe, 0x6a, 0x61, 0xf3, 0x03, 0xbf, 0x73, 0xe1, 0xc1, 0xf6, 0xf1, 0xf5, 0x6b, 0xbf, 0x68, + 0xc6, 0x62, 0x09, 0x6b, 0xff, 0x58, 0xfa, 0x82, 0x50, 0x78, 0x2a, 0x04, 0x10, 0xfa, 0x82, 0x1a, 0x58, 0xce, 0x21, + 0x33, 0x67, 0x86, 0x9e, 0xbf, 0x66, 0x89, 0x23, 0x5a, 0xb0, 0xf1, 0x6b, 0xc3, 0xc2, 0x02, 0x4b, 0xed, 0xe5, 0x0d, + 0x58, 0x89, 0x85, 0x3d, 0xc6, 0x99, 0xe9, 0x6c, 0x8e, 0x99, 0x13, 0xf0, 0xb6, 0x65, 0x66, 0xa2, 0x0a, 0x9c, 0xe5, + 0x07, 0x5a, 0x9f, 0xa0, 0x5a, 0xc9, 0xbf, 0xba, 0x30, 0xae, 0x68, 0x83, 0xb3, 0xb9, 0xb4, 0x35, 0x04, 0xae, 0x4a, + 0x9a, 0x7c, 0x4c, 0xd6, 0x71, 0x27, 0x07, 0x3f, 0x4b, 0x03, 0x3e, 0x6b, 0x7c, 0x16, 0xe2, 0xb2, 0x24, 0xef, 0xd1, + 0x9c, 0xf5, 0xa1, 0x73, 0xad, 0x0d, 0x16, 0x6e, 0xec, 0x87, 0x29, 0xf8, 0xf0, 0x9a, 0x6c, 0xb7, 0xb5, 0x0f, 0x70, + 0x9f, 0xe6, 0xcd, 0xc7, 0x1d, 0xf4, 0x84, 0x9b, 0x1f, 0xff, 0x13, 0xf6, 0xed, 0xf2, 0x83, 0x2a, 0x85, 0x29, 0xf8, + 0xb8, 0xec, 0x8b, 0x22, 0xb2, 0xfd, 0x1e, 0xfa, 0x1e, 0xf8, 0x71, 0xd0, 0x70, 0xa1, 0x5f, 0xba, 0xcb, 0x18, 0x8d, + 0xe7, 0x4e, 0xb0, 0xda, 0x43, 0xe3, 0xba, 0x1e, 0x8c, 0xaa, 0x6c, 0x83, 0x61, 0x8d, 0x90, 0xa0, 0xcb, 0x63, 0x2b, + 0xfb, 0x2c, 0xc8, 0x06, 0x63, 0x25, 0x7b, 0x40, 0x09, 0x7b, 0xd0, 0x96, 0xd3, 0x00, 0x2c, 0x24, 0x1f, 0x37, 0xed, + 0x10, 0x68, 0xc8, 0x6a, 0x30, 0xdc, 0xe7, 0xaf, 0x89, 0xae, 0x2c, 0xad, 0x03, 0xfd, 0x07, 0xf7, 0x3d, 0x9a, 0x29, + 0xe2, 0xbe, 0x3c, 0xab, 0x29, 0xcb, 0x9d, 0xf6, 0xc9, 0x52, 0x1e, 0x7b, 0x18, 0x9e, 0x67, 0x0a, 0x39, 0x9d, 0xd3, + 0xaf, 0xb3, 0x35, 0x0e, 0xd2, 0x4a, 0x79, 0xd2, 0xbe, 0x4e, 0x5b, 0x5f, 0xf6, 0x9d, 0x88, 0xd5, 0x09, 0xee, 0x6a, + 0xa8, 0xd5, 0x4b, 0xaf, 0x0d, 0x86, 0xd3, 0x41, 0xfb, 0x0d, 0xe8, 0x6e, 0x69, 0x7d, 0x3b, 0xa9, 0x96, 0x48, 0x9c, + 0x1e, 0xe2, 0x76, 0x30, 0x9b, 0xa1, 0xb0, 0xb3, 0xad, 0xae, 0x2e, 0x09, 0x1c, 0xa0, 0xa9, 0x15, 0xf8, 0x70, 0xb7, + 0x88, 0xd5, 0x54, 0x1e, 0xe2, 0x63, 0x20, 0x77, 0x08, 0x38, 0x2f, 0xab, 0x90, 0xf3, 0x91, 0x61, 0x2d, 0xd6, 0x34, + 0xc3, 0x01, 0x53, 0x52, 0x07, 0x35, 0xdc, 0x28, 0x6b, 0xac, 0x8a, 0x96, 0x29, 0xb6, 0x3a, 0xfc, 0xba, 0xfd, 0xf3, + 0x35, 0x42, 0x90, 0xf5, 0x9b, 0x1f, 0x0b, 0xa2, 0x93, 0x41, 0x76, 0x8f, 0x38, 0x3e, 0x47, 0xc7, 0x5e, 0xae, 0xd6, + 0x5d, 0x94, 0x76, 0x27, 0x9b, 0xa9, 0xf2, 0xf9, 0x08, 0xf4, 0x92, 0x63, 0x70, 0xd8, 0x0e, 0x92, 0xe1, 0xc7, 0xd0, + 0x91, 0x50, 0x97, 0x97, 0xd4, 0x9a, 0x75, 0xf8, 0x61, 0xcf, 0xab, 0x5e, 0xce, 0x62, 0x37, 0x3d, 0x03, 0x8c, 0x53, + 0x6e, 0x7a, 0x7b, 0xac, 0x06, 0x00, 0x5b, 0x28, 0xbe, 0x86, 0x7d, 0x48, 0xc0, 0x3b, 0x14, 0xfd, 0xc1, 0xce, 0xc3, + 0x70, 0x51, 0x5c, 0xaa, 0x2c, 0x1d, 0x3f, 0x4e, 0xa3, 0x3a, 0x40, 0xf0, 0xf7, 0x78, 0xc2, 0xca, 0xd2, 0x42, 0x0d, + 0xee, 0x5c, 0x9a, 0xb8, 0x50, 0x04, 0xe2, 0x10, 0xfb, 0x59, 0xab, 0xea, 0xfe, 0x7d, 0xed, 0x8a, 0x00, 0xd4, 0xbe, + 0xa4, 0x83, 0x7b, 0x61, 0x87, 0xf9, 0x01, 0x6b, 0x5d, 0x23, 0x7c, 0x5e, 0xab, 0x29, 0x33, 0x3c, 0x10, 0x7c, 0x09, + 0xcf, 0xd5, 0x41, 0x59, 0x1d, 0xe4, 0x18, 0x29, 0x20, 0x59, 0x41, 0x74, 0x49, 0x90, 0x12, 0x3d, 0x11, 0x9b, 0xd1, + 0x3a, 0x32, 0x15, 0xd8, 0xb8, 0xb1, 0xc0, 0x30, 0xec, 0x12, 0x08, 0xf6, 0xc0, 0xb2, 0xe6, 0xe4, 0x95, 0xfe, 0xc0, + 0x6f, 0x11, 0x35, 0xac, 0x43, 0x94, 0x10, 0x6a, 0x56, 0x53, 0x11, 0x08, 0xaf, 0x8a, 0x98, 0x27, 0x93, 0xc9, 0x09, + 0xf0, 0xae, 0x3d, 0x51, 0xf4, 0x74, 0x67, 0xc7, 0xa2, 0x32, 0xcf, 0x2e, 0x52, 0xe1, 0x2a, 0x03, 0xaa, 0xc5, 0x81, + 0x2b, 0x87, 0x45, 0x74, 0x55, 0x4a, 0xee, 0x81, 0xcd, 0x7c, 0x03, 0xe7, 0x3a, 0x0d, 0xda, 0xca, 0xb1, 0x43, 0xc3, + 0x15, 0x5e, 0x14, 0x14, 0x0e, 0x94, 0xb2, 0x3b, 0x45, 0x98, 0xe6, 0xd6, 0x53, 0x91, 0x05, 0x0e, 0x60, 0x01, 0xf7, + 0xe6, 0xee, 0x22, 0x03, 0xb6, 0x8f, 0x86, 0x70, 0x6a, 0x01, 0x7a, 0x6f, 0xf3, 0x9f, 0xba, 0xcc, 0x69, 0xf3, 0x5f, + 0xbe, 0xa1, 0x6e, 0xad, 0x99, 0x4c, 0x8b, 0x5e, 0x86, 0xe4, 0x9b, 0xde, 0xaa, 0xbf, 0x7b, 0x31, 0x83, 0xc1, 0x7b, + 0x92, 0xcb, 0xac, 0x4f, 0x02, 0x4e, 0xbd, 0x0d, 0x1f, 0xa8, 0x8f, 0xb6, 0xa1, 0x75, 0x08, 0x01, 0x16, 0x87, 0x30, + 0x76, 0x82, 0x3d, 0xfc, 0x8c, 0x98, 0x4b, 0x11, 0xc6, 0x6b, 0xec, 0x05, 0x5f, 0xba, 0xd6, 0x9b, 0x9b, 0x62, 0xcf, + 0xce, 0xab, 0x45, 0x08, 0xa5, 0xa7, 0x69, 0x12, 0x9f, 0x5d, 0xba, 0x5d, 0xc6, 0x73, 0xd0, 0x44, 0x46, 0xa1, 0x10, + 0x91, 0x3c, 0x17, 0x34, 0x2d, 0xb4, 0xbd, 0x03, 0xea, 0x18, 0x44, 0xa5, 0x80, 0xf5, 0xf0, 0xa0, 0xd0, 0xe2, 0xeb, + 0xa7, 0xd9, 0x33, 0xd4, 0x9f, 0xd8, 0x39, 0xe1, 0x5f, 0x1d, 0xf8, 0x29, 0x11, 0xfb, 0x2d, 0x5a, 0xe0, 0xdc, 0xfc, + 0x6a, 0x28, 0xc0, 0xfe, 0x88, 0x09, 0x7f, 0x85, 0x01, 0x8c, 0x8c, 0xe0, 0xff, 0xf2, 0x4b, 0x56, 0x54, 0x30, 0xcc, + 0x4b, 0xe1, 0x9d, 0xe2, 0x23, 0x14, 0xd0, 0xf3, 0x92, 0x26, 0x5b, 0xc0, 0x79, 0x4b, 0x4d, 0xd7, 0x05, 0x90, 0x31, + 0x06, 0x20, 0x10, 0x57, 0x9f, 0x30, 0xef, 0x56, 0xa3, 0x64, 0x6f, 0xd3, 0x6f, 0x06, 0x68, 0xc6, 0xcd, 0x88, 0xd9, + 0x64, 0x68, 0xc1, 0xd2, 0x71, 0x34, 0xc2, 0x4f, 0xa3, 0x58, 0xff, 0xfa, 0x54, 0x09, 0xa8, 0xa4, 0x7b, 0x01, 0x7f, + 0x9b, 0x96, 0x78, 0x4b, 0xe3, 0xfc, 0x5e, 0xe3, 0x5b, 0xb7, 0x6f, 0xfd, 0xf2, 0xf1, 0xc3, 0xd5, 0x42, 0x58, 0xad, + 0x4f, 0x3e, 0xa5, 0xad, 0x73, 0x83, 0xe8, 0x51, 0xa8, 0x71, 0x28, 0x84, 0x46, 0xf2, 0x38, 0xc9, 0xc8, 0x66, 0xb3, + 0xac, 0x77, 0x21, 0xff, 0xd8, 0xd5, 0x7b, 0xc9, 0x95, 0x0d, 0xf2, 0xee, 0x2e, 0x30, 0x3b, 0xbb, 0xb5, 0x25, 0x6b, + 0x9e, 0xca, 0xa1, 0x1b, 0x3c, 0x53, 0x2d, 0x1d, 0x29, 0x2c, 0xf0, 0x48, 0xcb, 0xd8, 0x99, 0x3d, 0xbf, 0x06, 0x34, + 0x15, 0xe7, 0x0a, 0xea, 0x9c, 0x05, 0xa5, 0x41, 0xc1, 0x9f, 0xf4, 0x46, 0xde, 0xec, 0xb0, 0xd8, 0xbd, 0x83, 0xac, + 0x8e, 0xff, 0x37, 0xd2, 0xa8, 0xee, 0x12, 0x1a, 0x85, 0x67, 0xd1, 0x5b, 0xab, 0x0a, 0xdd, 0x3b, 0xdc, 0x55, 0x72, + 0x50, 0xfb, 0xda, 0xa6, 0x18, 0xad, 0x61, 0xae, 0xd6, 0xbe, 0xde, 0x65, 0xda, 0xcb, 0x3b, 0xe2, 0x1f, 0x7e, 0xb2, + 0x39, 0x42, 0x08, 0x99, 0xec, 0x9e, 0xfa, 0x14, 0x00, 0xbe, 0x15, 0x00, 0xc4, 0x08, 0xbf, 0x60, 0xdd, 0xe0, 0x29, + 0x76, 0x8f, 0x67, 0xb7, 0xa5, 0x16, 0xee, 0x23, 0xc4, 0x58, 0x3b, 0xee, 0xd7, 0x12, 0x1e, 0x09, 0xfc, 0xb6, 0x75, + 0xea, 0x71, 0xa8, 0x77, 0xf6, 0xd3, 0x4e, 0x22, 0x3e, 0xc6, 0x46, 0x5a, 0x0f, 0xe7, 0xd8, 0x92, 0xdf, 0x50, 0x3b, + 0x71, 0x72, 0xd7, 0xd2, 0x59, 0xf4, 0x0b, 0x01, 0xfc, 0xe5, 0xb7, 0x95, 0x35, 0x3f, 0x5c, 0xd8, 0xfe, 0x4b, 0xff, + 0x65, 0x61, 0xff, 0x39, 0xb7, 0x80, 0x8d, 0x04, 0x8c, 0x58, 0xdf, 0x8c, 0x1b, 0x0f, 0x18, 0xb1, 0x63, 0x00, 0xa4, + 0x83, 0x18, 0x01, 0x4d, 0x79, 0x28, 0x04, 0x2f, 0xa2, 0x37, 0x8a, 0xce, 0xcd, 0x98, 0x06, 0xb2, 0xf2, 0x9a, 0x4c, + 0xf5, 0x41, 0xd8, 0xf8, 0x59, 0xb7, 0xb6, 0x70, 0x93, 0x0f, 0x63, 0xbd, 0xb4, 0xe6, 0xcc, 0x02, 0xd0, 0xa7, 0xb8, + 0xbf, 0x55, 0xa9, 0xcd, 0x35, 0xf6, 0xe6, 0xb4, 0x93, 0x1f, 0x7e, 0x0e, 0x7b, 0xbb, 0xe3, 0xcf, 0x85, 0xb9, 0x74, + 0xf4, 0xf9, 0xe5, 0xcc, 0x98, 0x5a, 0xd7, 0xda, 0xfd, 0xd1, 0xc2, 0x03, 0x6f, 0x50, 0xd9, 0x28, 0xdb, 0xe7, 0x12, + 0xa4, 0x8d, 0x84, 0x71, 0x27, 0x4e, 0x83, 0xad, 0x7c, 0x23, 0x59, 0x4a, 0xdd, 0xda, 0xcc, 0x00, 0xb6, 0x9b, 0xe0, + 0x2d, 0xa3, 0x8b, 0xde, 0x17, 0x96, 0xe9, 0xe9, 0x2e, 0xae, 0xdd, 0x22, 0xda, 0xa1, 0x5c, 0xb3, 0x88, 0x67, 0x6a, + 0xc1, 0x93, 0xe4, 0x62, 0x0e, 0xb8, 0x81, 0x32, 0xb1, 0xa4, 0x7d, 0x9d, 0x39, 0x43, 0x64, 0x45, 0x7e, 0xa5, 0x9f, + 0x1a, 0x7f, 0xbf, 0x8d, 0xbf, 0x9a, 0xdb, 0x6c, 0xd7, 0xaf, 0xeb, 0x94, 0x28, 0xd4, 0xb4, 0xd8, 0xf7, 0xd9, 0xa2, + 0x27, 0x8c, 0xed, 0x63, 0x4e, 0x8c, 0xd5, 0x5a, 0xf3, 0xee, 0x7b, 0x3d, 0x75, 0x9e, 0x6a, 0x1f, 0x51, 0xf3, 0x05, + 0xf6, 0xfb, 0xa0, 0xbd, 0xeb, 0xf5, 0x67, 0xf1, 0xa1, 0x6f, 0x2f, 0xbe, 0x7c, 0x5c, 0xaa, 0x4f, 0x4c, 0xcd, 0xd1, + 0x43, 0x76, 0xa8, 0x3c, 0xc1, 0x14, 0x3e, 0x50, 0x26, 0xa2, 0x02, 0xde, 0xbb, 0xcd, 0xfb, 0xec, 0x45, 0xd7, 0x92, + 0xff, 0xa8, 0x41, 0x0b, 0x09, 0x6b, 0xee, 0x50, 0x15, 0xac, 0x3b, 0xe2, 0xbf, 0xce, 0x79, 0xad, 0x2c, 0x6b, 0x2b, + 0x42, 0xcb, 0x87, 0x1d, 0xbe, 0xf3, 0x54, 0xeb, 0x63, 0xdc, 0x62, 0x27, 0xb9, 0xdd, 0xf2, 0x4c, 0x14, 0xb7, 0xa0, + 0xea, 0x72, 0x04, 0x82, 0xb4, 0x01, 0x19, 0x69, 0x2b, 0x46, 0x2d, 0xdc, 0x27, 0xed, 0xd7, 0xf6, 0xbb, 0x10, 0x4b, + 0x4f, 0x6b, 0x9a, 0xb2, 0xd2, 0x4d, 0xec, 0x45, 0x4a, 0x11, 0x42, 0x66, 0x7d, 0xf0, 0xfa, 0x93, 0x9a, 0x61, 0x73, + 0x77, 0xb7, 0x3a, 0x23, 0x3a, 0x16, 0xae, 0x51, 0x22, 0x2b, 0xe2, 0x6e, 0xe3, 0x30, 0x8b, 0xcf, 0xa5, 0x7f, 0x96, + 0xe7, 0x60, 0xce, 0x09, 0xed, 0xa6, 0x78, 0xa1, 0x19, 0xba, 0xe9, 0x1c, 0x3f, 0x30, 0x0c, 0x24, 0xbd, 0x40, 0xfe, + 0x3a, 0x95, 0xe3, 0x94, 0x23, 0x6a, 0x2d, 0x2b, 0xd1, 0xb6, 0xa0, 0x60, 0xf1, 0xd8, 0xdc, 0x01, 0xbe, 0x1b, 0x7e, + 0x5c, 0x60, 0xbe, 0x79, 0xf7, 0x19, 0xa2, 0x87, 0xf2, 0x40, 0xcd, 0x3b, 0xab, 0x95, 0x09, 0xde, 0x90, 0xc6, 0x9f, + 0x4a, 0x12, 0xbb, 0x37, 0x34, 0x69, 0x75, 0xd3, 0xbd, 0xb1, 0xd9, 0x2d, 0x65, 0x0e, 0xf3, 0xb0, 0xe9, 0x8a, 0x62, + 0x14, 0xf0, 0xac, 0x7b, 0x3b, 0x94, 0x95, 0x02, 0x16, 0xe0, 0x04, 0xea, 0x83, 0x5a, 0x58, 0x2c, 0x8f, 0x13, 0xf5, + 0x98, 0x59, 0x0e, 0x7c, 0x6d, 0xf0, 0xb2, 0x8f, 0xce, 0x12, 0xb0, 0x94, 0x6a, 0x21, 0x6d, 0x2a, 0x29, 0x7e, 0x99, + 0x93, 0xd3, 0xdb, 0x54, 0x13, 0xb5, 0xc9, 0xed, 0x7e, 0xdf, 0x71, 0x06, 0xad, 0xe4, 0xe0, 0x0e, 0x8e, 0xbd, 0x1e, + 0x84, 0x6c, 0x54, 0x40, 0xa6, 0xd9, 0x9f, 0xf2, 0xc8, 0x4e, 0x4b, 0xf9, 0x9c, 0xd4, 0xb4, 0x29, 0x02, 0xd6, 0x6c, + 0xbc, 0x9b, 0x36, 0x92, 0x62, 0xed, 0x0c, 0x47, 0x3c, 0x37, 0x8d, 0x8b, 0xef, 0xf3, 0x1f, 0x7b, 0xca, 0x16, 0xc2, + 0xea, 0x69, 0x7c, 0xd4, 0x3b, 0xbd, 0x32, 0xad, 0x1a, 0x2a, 0x73, 0x36, 0x96, 0xf0, 0x01}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From d6bf137026ca568c61c4b590a31490de57ab034e Mon Sep 17 00:00:00 2001 From: sebcaps Date: Mon, 26 Jan 2026 07:07:29 +0100 Subject: [PATCH 0422/2030] [mhz19] Fix Uninitialized var warning message (#13526) --- esphome/components/mhz19/mhz19.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index 00e6e14d85..259d597b44 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -155,6 +155,9 @@ void MHZ19Component::dump_config() { case MHZ19_DETECTION_RANGE_0_10000PPM: range_str = "0 to 10000ppm"; break; + default: + range_str = "default"; + break; } ESP_LOGCONFIG(TAG, " Detection range: %s", range_str); } From f7937ef9526ac5005e43a559681d515908327721 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:13:18 -1000 Subject: [PATCH 0423/2030] [ota] Improve error message when device closes connection without responding (#13562) --- esphome/espota2.py | 6 ++++++ tests/unit_tests/test_espota2.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/esphome/espota2.py b/esphome/espota2.py index 6349ad0fa8..28d9649abd 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -154,6 +154,12 @@ def check_error(data: list[int] | bytes, expect: int | list[int] | None) -> None """ if not expect: return + if not data: + raise OTAError( + "Error: Device closed connection without responding. " + "This may indicate the device ran out of memory, " + "a network issue, or the connection was interrupted." + ) dat = data[0] if dat == RESPONSE_ERROR_MAGIC: raise OTAError("Error: Invalid magic byte") diff --git a/tests/unit_tests/test_espota2.py b/tests/unit_tests/test_espota2.py index 02f965782b..1885b769f1 100644 --- a/tests/unit_tests/test_espota2.py +++ b/tests/unit_tests/test_espota2.py @@ -192,6 +192,20 @@ def test_check_error_unexpected_response() -> None: espota2.check_error([0x7F], [espota2.RESPONSE_OK, espota2.RESPONSE_AUTH_OK]) +def test_check_error_empty_data() -> None: + """Test check_error raises error when device closes connection without responding.""" + with pytest.raises( + espota2.OTAError, match="Device closed connection without responding" + ): + espota2.check_error([], [espota2.RESPONSE_OK]) + + # Also test with empty bytes + with pytest.raises( + espota2.OTAError, match="Device closed connection without responding" + ): + espota2.check_error(b"", [espota2.RESPONSE_OK]) + + def test_send_check_with_various_data_types(mock_socket: Mock) -> None: """Test send_check handles different data types.""" From 40ea65b1c0493192f0ef08ded2a30147934155cd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 26 Jan 2026 17:34:55 -1000 Subject: [PATCH 0424/2030] [socket] ESP8266: call delay(0) instead of esp_delay(0, cb) for zero timeout (#13530) --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 429f59ceca..a9c2eda4e8 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -29,6 +29,14 @@ void socket_delay(uint32_t ms) { // Use esp_delay with a callback that checks if socket data arrived. // This allows the delay to exit early when socket_wake() is called by // lwip recv_fn/accept_fn callbacks, reducing socket latency. + // + // When ms is 0, we must use delay(0) because esp_delay(0, callback) + // exits immediately without yielding, which can cause watchdog timeouts + // when the main loop runs in high-frequency mode (e.g., during light effects). + if (ms == 0) { + delay(0); + return; + } s_socket_woke = false; esp_delay(ms, []() { return !s_socket_woke; }); } From 4ec8846198cdc2013bebe540477b3f02b49decd3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Jan 2026 09:08:46 -1000 Subject: [PATCH 0425/2030] [web_server] Add name_id to SSE for entity ID format migration (#13535) --- esphome/components/web_server/web_server.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 0525c93096..ee34cf2043 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -527,7 +527,19 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J memcpy(p, name.c_str(), name_len); p[name_len] = '\0'; - root[ESPHOME_F("id")] = id_buf; + // name_id: new format {prefix}/{device?}/{name} - frontend should prefer this + // Remove in 2026.8.0 when id switches to new format permanently + root[ESPHOME_F("name_id")] = id_buf; + + // id: old format {prefix}-{object_id} for backward compatibility + // Will switch to new format in 2026.8.0 + char legacy_buf[ESPHOME_DOMAIN_MAX_LEN + 1 + OBJECT_ID_MAX_LEN]; + char *lp = legacy_buf; + memcpy(lp, prefix, prefix_len); + lp += prefix_len; + *lp++ = '-'; + obj->write_object_id_to(lp, sizeof(legacy_buf) - (lp - legacy_buf)); + root[ESPHOME_F("id")] = legacy_buf; if (start_config == DETAIL_ALL) { root[ESPHOME_F("domain")] = prefix; From a20d42ca0beb22c644364604221db6cf00bbcc6c Mon Sep 17 00:00:00 2001 From: esphomebot Date: Wed, 28 Jan 2026 08:21:26 +1300 Subject: [PATCH 0426/2030] Update webserver local assets to 20260127-190637 (#13573) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/web_server/server_index_v2.h | 2595 ++- .../components/web_server/server_index_v3.h | 14600 ++++++++-------- 2 files changed, 8598 insertions(+), 8597 deletions(-) diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index 7c24ae28c6..cc37db6a6b 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -10,1307 +10,1306 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP const uint8_t INDEX_GZ[] PROGMEM = { - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdc, 0x48, 0xb6, 0xd8, 0xb3, - 0xe7, 0x2b, 0x40, 0x34, 0x2f, 0x85, 0x1c, 0x66, 0xa1, 0x16, 0x92, 0x12, 0x85, 0x62, 0x56, 0x0d, 0x45, 0xa9, 0x47, - 0x3d, 0xad, 0x6d, 0x44, 0xa9, 0x7b, 0xa6, 0xd9, 0x1c, 0x12, 0x04, 0xb2, 0x0a, 0xd9, 0x42, 0x01, 0xd5, 0x89, 0x2c, - 0x2e, 0x5d, 0x85, 0x1b, 0xfe, 0x00, 0x47, 0x38, 0xc2, 0x4f, 0x7e, 0x71, 0xf8, 0x3e, 0xf8, 0x23, 0xfc, 0x7c, 0x3f, - 0xc5, 0x3f, 0x60, 0x7f, 0x82, 0xe3, 0xe4, 0x02, 0x24, 0x6a, 0xa1, 0xa8, 0x9e, 0x9e, 0xeb, 0xfb, 0xe0, 0xe8, 0x68, - 0xaa, 0x90, 0xc8, 0xe5, 0xe4, 0xc9, 0x93, 0x67, 0xcf, 0xc4, 0xd1, 0x56, 0x9c, 0x47, 0xe2, 0x6e, 0x4a, 0x9d, 0x44, - 0x4c, 0xd2, 0xc1, 0x91, 0xfe, 0x4b, 0xc3, 0x78, 0x70, 0x94, 0xb2, 0xec, 0x93, 0xc3, 0x69, 0x4a, 0x58, 0x94, 0x67, - 0x4e, 0xc2, 0xe9, 0x88, 0xc4, 0xa1, 0x08, 0x03, 0x36, 0x09, 0xc7, 0xd4, 0x69, 0x0f, 0x8e, 0x26, 0x54, 0x84, 0x4e, - 0x94, 0x84, 0xbc, 0xa0, 0x82, 0x7c, 0xfc, 0xf0, 0x75, 0xeb, 0x70, 0x70, 0x54, 0x44, 0x9c, 0x4d, 0x85, 0x03, 0x5d, - 0x92, 0x49, 0x1e, 0xcf, 0x52, 0x3a, 0x68, 0xb7, 0x6f, 0x6e, 0x6e, 0xfc, 0x9f, 0x8a, 0xdf, 0x45, 0x79, 0x56, 0x08, - 0xe7, 0x39, 0xb9, 0x61, 0x59, 0x9c, 0xdf, 0x60, 0x2e, 0xc8, 0x73, 0xff, 0x34, 0x09, 0xe3, 0xfc, 0xe6, 0x7d, 0x9e, - 0x8b, 0x9d, 0x1d, 0x4f, 0x3d, 0xde, 0x9d, 0x9c, 0x9e, 0x12, 0x42, 0xae, 0x73, 0x16, 0x3b, 0x9d, 0xc5, 0xa2, 0x2e, - 0xf4, 0xb3, 0x50, 0xb0, 0x6b, 0xaa, 0x9a, 0xa0, 0x9d, 0x1d, 0x37, 0x8c, 0xf3, 0xa9, 0xa0, 0xf1, 0xa9, 0xb8, 0x4b, - 0xe9, 0x69, 0x42, 0xa9, 0x28, 0x5c, 0x96, 0x39, 0xcf, 0xf3, 0x68, 0x36, 0xa1, 0x99, 0xf0, 0xa7, 0x3c, 0x17, 0x39, - 0x40, 0xb2, 0xb3, 0xe3, 0x72, 0x3a, 0x4d, 0xc3, 0x88, 0xc2, 0xfb, 0x93, 0xd3, 0xd3, 0xba, 0x45, 0x5d, 0x09, 0x67, - 0x82, 0x9c, 0xde, 0x4d, 0xae, 0xf2, 0xd4, 0x43, 0x38, 0x11, 0x24, 0xa3, 0x37, 0xce, 0xf7, 0x34, 0xfc, 0xf4, 0x3a, - 0x9c, 0xf6, 0xa3, 0x34, 0x2c, 0x0a, 0xe7, 0x58, 0xcc, 0xe5, 0x14, 0xf8, 0x2c, 0x12, 0x39, 0xf7, 0x04, 0xa6, 0x98, - 0xa1, 0x39, 0x1b, 0x79, 0x22, 0x61, 0x85, 0x7f, 0xb1, 0x1d, 0x15, 0xc5, 0x7b, 0x5a, 0xcc, 0x52, 0xb1, 0x4d, 0xb6, - 0x3a, 0x98, 0x6d, 0x11, 0x92, 0x09, 0x24, 0x12, 0x9e, 0xdf, 0x38, 0x2f, 0x38, 0xcf, 0xb9, 0xe7, 0x9e, 0x9c, 0x9e, - 0xaa, 0x1a, 0x0e, 0x2b, 0x9c, 0x2c, 0x17, 0x4e, 0xd5, 0x5f, 0x78, 0x95, 0x52, 0xdf, 0xf9, 0x58, 0x50, 0xe7, 0x72, - 0x96, 0x15, 0xe1, 0x88, 0x9e, 0x9c, 0x9e, 0x5e, 0x3a, 0x39, 0x77, 0x2e, 0xa3, 0xa2, 0xb8, 0x74, 0x58, 0x56, 0x08, - 0x1a, 0xc6, 0xbe, 0x8b, 0xfa, 0x72, 0xb0, 0xa8, 0x28, 0x3e, 0xd0, 0x5b, 0x41, 0x04, 0x96, 0x8f, 0x82, 0xd0, 0x72, - 0x4c, 0x85, 0x53, 0x54, 0xf3, 0xf2, 0xd0, 0x3c, 0xa5, 0xc2, 0x11, 0x44, 0xbe, 0xcf, 0xfb, 0x0a, 0xf7, 0x54, 0x3d, - 0x8a, 0x3e, 0x1b, 0x79, 0x5c, 0xec, 0xec, 0x88, 0x0a, 0xcf, 0x48, 0x4d, 0xcd, 0x61, 0x84, 0x6e, 0x99, 0xb2, 0x9d, - 0x1d, 0xea, 0xa7, 0x34, 0x1b, 0x8b, 0x84, 0x10, 0xd2, 0xed, 0xb3, 0x9d, 0x1d, 0x4f, 0x90, 0x44, 0xf8, 0x63, 0x2a, - 0x3c, 0x8a, 0x10, 0xae, 0x5b, 0xef, 0xec, 0x78, 0x0a, 0x09, 0x39, 0x51, 0x88, 0x6b, 0xe0, 0x18, 0xf9, 0x1a, 0xfb, - 0xa7, 0x77, 0x59, 0xe4, 0xd9, 0xf0, 0x23, 0xcc, 0x76, 0x76, 0x12, 0xe1, 0x17, 0xd0, 0x23, 0x16, 0x08, 0x95, 0x9c, - 0x8a, 0x19, 0xcf, 0x1c, 0x51, 0x8a, 0xfc, 0x54, 0x70, 0x96, 0x8d, 0x3d, 0x34, 0x37, 0x65, 0x56, 0xc3, 0xb2, 0x54, - 0xe0, 0xbe, 0x17, 0x24, 0x23, 0x03, 0x18, 0xf1, 0x58, 0x78, 0xb0, 0x8a, 0xf9, 0xc8, 0xc9, 0x08, 0x71, 0x0b, 0xd9, - 0xd6, 0x1d, 0x66, 0x41, 0xb6, 0xeb, 0xba, 0x58, 0x41, 0x89, 0x33, 0x81, 0xf0, 0x27, 0xe2, 0x65, 0xd8, 0xf7, 0x7d, - 0x81, 0xc8, 0x60, 0x6e, 0xb0, 0x92, 0x59, 0xf3, 0x1c, 0x66, 0x67, 0x9d, 0xf3, 0x40, 0xf8, 0x9c, 0xc6, 0xb3, 0x88, - 0x7a, 0x1e, 0xc3, 0x1c, 0xe7, 0x88, 0x0c, 0xd8, 0xae, 0x57, 0x90, 0x01, 0x2c, 0xf7, 0xd2, 0x5a, 0x13, 0xb2, 0xd5, - 0x41, 0x1a, 0xc6, 0x0a, 0x40, 0xc0, 0xb0, 0x86, 0xa7, 0x20, 0xc4, 0xcd, 0x66, 0x93, 0x2b, 0xca, 0xdd, 0xaa, 0x5a, - 0xbf, 0x41, 0x16, 0xb3, 0x82, 0x3a, 0x51, 0x51, 0x38, 0xa3, 0x59, 0x16, 0x09, 0x96, 0x67, 0x8e, 0xbb, 0x5b, 0xec, - 0xba, 0x8a, 0x1c, 0x2a, 0x6a, 0x70, 0x51, 0x89, 0x3c, 0x8e, 0x76, 0xb3, 0xb3, 0x7c, 0xb7, 0x7b, 0x8e, 0x01, 0x4a, - 0xd4, 0xd7, 0xfd, 0x69, 0x04, 0x50, 0x9c, 0xc1, 0x1c, 0x4b, 0xfc, 0x4c, 0xc0, 0x2c, 0xe5, 0x14, 0xb9, 0x18, 0x66, - 0xfe, 0xea, 0x46, 0x21, 0xc2, 0x9f, 0x84, 0x53, 0x8f, 0x92, 0x01, 0x95, 0xc4, 0x15, 0x66, 0x11, 0xc0, 0xda, 0x58, - 0xb7, 0x21, 0x0d, 0xa8, 0x5f, 0x93, 0x14, 0x0a, 0x84, 0x3f, 0xca, 0xf9, 0x8b, 0x30, 0x4a, 0xa0, 0x5d, 0x45, 0x30, - 0xb1, 0xd9, 0x6f, 0x11, 0xa7, 0xa1, 0xa0, 0x2f, 0x52, 0x0a, 0x4f, 0x9e, 0x2b, 0x5b, 0xba, 0x08, 0x73, 0xf2, 0xdc, - 0x4f, 0x99, 0x78, 0x93, 0x67, 0x11, 0xed, 0x73, 0x8b, 0xba, 0x18, 0xac, 0xfb, 0xb1, 0x10, 0x9c, 0x5d, 0xcd, 0x04, - 0xf5, 0xdc, 0x0c, 0x6a, 0xb8, 0x98, 0x23, 0xcc, 0x7c, 0x41, 0x6f, 0xc5, 0x49, 0x9e, 0x09, 0x9a, 0x09, 0x42, 0x0d, - 0x52, 0x71, 0xe6, 0x87, 0xd3, 0x29, 0xcd, 0xe2, 0x93, 0x84, 0xa5, 0xb1, 0xc7, 0x50, 0x89, 0x4a, 0x1c, 0x09, 0x02, - 0x73, 0x24, 0x83, 0x2c, 0x80, 0x3f, 0x9b, 0x67, 0xe3, 0x09, 0x32, 0x90, 0x9b, 0x82, 0x12, 0xd7, 0xed, 0x8f, 0x72, - 0xee, 0xe9, 0x19, 0x38, 0xf9, 0xc8, 0x11, 0x30, 0xc6, 0xfb, 0x59, 0x4a, 0x0b, 0x44, 0x77, 0x09, 0xab, 0x96, 0x51, - 0x23, 0xf8, 0x3d, 0x50, 0x7c, 0x89, 0xbc, 0x0c, 0x05, 0x59, 0xff, 0x3a, 0xe4, 0xce, 0x0f, 0x7a, 0x47, 0xfd, 0x64, - 0xb8, 0x59, 0x2c, 0xc8, 0x4f, 0xbe, 0xe0, 0xb3, 0x42, 0xd0, 0xf8, 0xc3, 0xdd, 0x94, 0x16, 0xf8, 0xa5, 0x20, 0xb1, - 0x18, 0xc6, 0xc2, 0xa7, 0x93, 0xa9, 0xb8, 0x3b, 0x95, 0x8c, 0x31, 0x70, 0x5d, 0x3c, 0x83, 0x9a, 0x9c, 0x86, 0x11, - 0x30, 0x33, 0x8d, 0xad, 0x77, 0x79, 0x7a, 0x37, 0x62, 0x69, 0x7a, 0x3a, 0x9b, 0x4e, 0x73, 0x2e, 0xb0, 0x10, 0x64, - 0x2e, 0xf2, 0x1a, 0x37, 0xb0, 0x98, 0xf3, 0xe2, 0x86, 0x89, 0x28, 0xf1, 0x04, 0x9a, 0x47, 0x61, 0x41, 0x9d, 0x67, - 0x79, 0x9e, 0xd2, 0x10, 0x66, 0x9d, 0x0d, 0x5f, 0x8a, 0x20, 0x9b, 0xa5, 0x69, 0xff, 0x8a, 0xd3, 0xf0, 0x53, 0x5f, - 0xbe, 0x7e, 0x7b, 0xf5, 0x13, 0x8d, 0x44, 0x20, 0x7f, 0x1f, 0x73, 0x1e, 0xde, 0x41, 0x45, 0x42, 0xa0, 0xda, 0x30, - 0x0b, 0xfe, 0x74, 0xfa, 0xf6, 0x8d, 0xaf, 0x76, 0x09, 0x1b, 0xdd, 0x79, 0x59, 0xb5, 0xf3, 0xb2, 0x12, 0x8f, 0x78, - 0x3e, 0x59, 0x1a, 0x5a, 0xa1, 0x2d, 0xeb, 0x6f, 0x00, 0x81, 0x92, 0x6c, 0x4b, 0x75, 0x6d, 0x43, 0xf0, 0x46, 0x12, - 0x3d, 0xbc, 0x24, 0x66, 0xdc, 0x59, 0x9a, 0x06, 0xaa, 0xd8, 0xcb, 0xd0, 0xfd, 0xd0, 0x0a, 0x7e, 0x37, 0xa7, 0x44, - 0xc2, 0x39, 0x05, 0x11, 0x03, 0x30, 0x46, 0xa1, 0x88, 0x92, 0x39, 0x95, 0x9d, 0x95, 0x06, 0x62, 0x5a, 0x96, 0xf8, - 0x45, 0x45, 0xf0, 0x02, 0x00, 0x91, 0x9c, 0x8a, 0x88, 0xc5, 0x02, 0x26, 0x8c, 0xf0, 0x9f, 0xc8, 0x3c, 0x34, 0xf3, - 0x09, 0xb6, 0x3a, 0x18, 0x36, 0x66, 0xa0, 0xd8, 0x0b, 0x8e, 0xf2, 0xec, 0x9a, 0x72, 0x41, 0x79, 0x20, 0x04, 0xe6, - 0x74, 0x94, 0x02, 0x18, 0x5b, 0x5d, 0x9c, 0x84, 0xc5, 0x49, 0x12, 0x66, 0x63, 0x1a, 0x07, 0x2f, 0x44, 0x89, 0xa9, - 0x20, 0xee, 0x88, 0x65, 0x61, 0xca, 0x7e, 0xa1, 0xb1, 0xab, 0x05, 0xc2, 0x0b, 0x87, 0xde, 0x0a, 0x9a, 0xc5, 0x85, - 0xf3, 0xf2, 0xc3, 0xeb, 0x57, 0x7a, 0x29, 0x1b, 0x32, 0x02, 0xcd, 0x8b, 0xd9, 0x94, 0x72, 0x0f, 0x61, 0x2d, 0x23, - 0x5e, 0x30, 0xc9, 0x1f, 0x5f, 0x87, 0x53, 0x55, 0xc2, 0x8a, 0x8f, 0xd3, 0x38, 0x14, 0xf4, 0x1d, 0xcd, 0x62, 0x96, - 0x8d, 0xc9, 0x56, 0x57, 0x95, 0x27, 0xa1, 0x7e, 0x11, 0x57, 0x45, 0x17, 0xdb, 0x2f, 0x52, 0x39, 0xf3, 0xea, 0x71, - 0xe6, 0xa1, 0xb2, 0x10, 0xa1, 0x60, 0x91, 0x13, 0xc6, 0xf1, 0x37, 0x19, 0x13, 0x4c, 0x02, 0xc8, 0x61, 0x81, 0x80, - 0x4a, 0xa9, 0x92, 0x16, 0x06, 0x70, 0x0f, 0x61, 0xcf, 0xd3, 0x32, 0x20, 0x41, 0x7a, 0xc5, 0x76, 0x76, 0x6a, 0x8e, - 0x3f, 0xa4, 0x81, 0x7a, 0x49, 0xce, 0xce, 0x91, 0x3f, 0x9d, 0x15, 0xb0, 0xd4, 0x66, 0x08, 0x10, 0x30, 0xf9, 0x55, - 0x41, 0xf9, 0x35, 0x8d, 0x2b, 0xf2, 0x28, 0x3c, 0x34, 0x5f, 0x1a, 0x43, 0xef, 0x0c, 0x41, 0xce, 0xce, 0xfb, 0x36, - 0xeb, 0xa6, 0x9a, 0xd4, 0x79, 0x3e, 0xa5, 0x5c, 0x30, 0x5a, 0x54, 0xdc, 0xc4, 0x03, 0x41, 0x5a, 0x71, 0x14, 0x4e, - 0xcc, 0xfc, 0xa6, 0x1e, 0xc3, 0x14, 0x35, 0x78, 0x86, 0x91, 0xb5, 0x2f, 0xae, 0xa5, 0xd0, 0xe0, 0x98, 0x21, 0x2c, - 0x14, 0xa4, 0x1c, 0xa1, 0x12, 0x61, 0x61, 0xc0, 0x55, 0xdc, 0x48, 0x8f, 0x76, 0x07, 0xd2, 0x9a, 0xfc, 0x49, 0x4a, - 0x6b, 0xe0, 0x69, 0xa1, 0xa0, 0x3b, 0x3b, 0x1e, 0xf5, 0x2b, 0xb2, 0x20, 0x5b, 0x5d, 0xbd, 0x46, 0x16, 0xb2, 0x36, - 0x80, 0x0d, 0x03, 0x0b, 0x4c, 0x11, 0xde, 0xa2, 0x7e, 0x96, 0x1f, 0x47, 0x11, 0x2d, 0x8a, 0x9c, 0xef, 0xec, 0x6c, - 0xc9, 0xfa, 0x95, 0x42, 0x01, 0x6b, 0xf8, 0xf6, 0x26, 0xab, 0x21, 0x40, 0xb5, 0x90, 0xd5, 0xa2, 0x41, 0x80, 0xa8, - 0x92, 0x3a, 0x87, 0x3b, 0x34, 0xba, 0x47, 0xe0, 0x5e, 0x5c, 0xb8, 0xbb, 0x02, 0x6b, 0x34, 0x8c, 0xa9, 0x19, 0xfa, - 0xee, 0x39, 0x55, 0xda, 0x95, 0xd4, 0x3d, 0x56, 0x30, 0xa3, 0x76, 0x90, 0x1f, 0xd3, 0x11, 0xcb, 0xac, 0x69, 0x37, - 0x40, 0xc2, 0x02, 0x73, 0x54, 0x5a, 0x0b, 0xba, 0xb6, 0x6b, 0xa9, 0xd6, 0xa8, 0x95, 0x9b, 0x8f, 0xa5, 0x2a, 0x61, - 0x2d, 0xe3, 0x19, 0x3d, 0x2f, 0xb1, 0x44, 0xbd, 0x99, 0x4d, 0x2e, 0x01, 0x3d, 0x13, 0xe7, 0x7d, 0xfd, 0x9e, 0x70, - 0x85, 0x39, 0x4e, 0x7f, 0x9e, 0xd1, 0x42, 0x28, 0x3a, 0xf6, 0x04, 0xce, 0x31, 0x03, 0x7e, 0x9d, 0x67, 0x23, 0x36, - 0x9e, 0x71, 0xd0, 0x78, 0x60, 0x33, 0xd2, 0x6c, 0x36, 0xa1, 0xe6, 0x69, 0x1d, 0x6c, 0x6f, 0xa7, 0x20, 0x13, 0x0b, - 0xa0, 0xe9, 0xfb, 0xc9, 0x09, 0x60, 0x15, 0x68, 0xb1, 0xf8, 0x93, 0xe9, 0xa4, 0x5e, 0xca, 0x4a, 0x4b, 0x5b, 0x5a, - 0x13, 0x2a, 0x90, 0x96, 0xc9, 0x5b, 0x5d, 0x0d, 0xbe, 0x38, 0x27, 0x5b, 0x9d, 0x8a, 0x86, 0x35, 0x56, 0x15, 0x38, - 0x0a, 0x89, 0x6f, 0x55, 0x57, 0x48, 0x8a, 0xf8, 0x06, 0xb9, 0xf8, 0xc9, 0x0a, 0xa5, 0x26, 0xe4, 0x0c, 0x94, 0x0d, - 0x3f, 0x39, 0xdf, 0x44, 0x4e, 0x86, 0x1f, 0x78, 0x62, 0xf5, 0x5d, 0xcd, 0x36, 0xae, 0x9b, 0x6c, 0x63, 0x69, 0x1a, - 0xee, 0xb4, 0x6a, 0xe2, 0x56, 0x54, 0xa6, 0x37, 0x7a, 0xfd, 0x0a, 0x33, 0x09, 0x4c, 0x3d, 0x25, 0xab, 0x8b, 0x37, - 0xe1, 0x84, 0x16, 0x1e, 0x45, 0x78, 0x53, 0x05, 0x45, 0x9e, 0x50, 0xe5, 0xdc, 0x92, 0x9d, 0x1c, 0x64, 0x27, 0x43, - 0x4a, 0x35, 0x6b, 0x6e, 0x38, 0x8e, 0xe9, 0x19, 0x3f, 0xaf, 0x35, 0x3a, 0x6b, 0xf2, 0x52, 0x28, 0x17, 0xa4, 0xb1, - 0xdd, 0x54, 0x99, 0x42, 0x9a, 0xd4, 0x1c, 0x0a, 0x84, 0xb7, 0x3a, 0xcb, 0x2b, 0x69, 0x6a, 0xd5, 0x73, 0x3c, 0x3b, - 0x87, 0x75, 0x90, 0x22, 0xc3, 0x67, 0x85, 0xfc, 0xb7, 0xb1, 0xd3, 0x00, 0x6d, 0xa7, 0x40, 0x18, 0xfe, 0x28, 0x0d, - 0x85, 0xd7, 0x6d, 0x77, 0x40, 0x1d, 0xbd, 0xa6, 0x20, 0x51, 0x10, 0x5a, 0x9d, 0x0a, 0xf5, 0x67, 0x59, 0x91, 0xb0, - 0x91, 0xf0, 0x22, 0x21, 0x59, 0x0a, 0x4d, 0x0b, 0xea, 0x88, 0x86, 0x52, 0x2c, 0xd9, 0x4d, 0x04, 0xc4, 0x56, 0x69, - 0x60, 0xd4, 0x40, 0x2a, 0xd9, 0x16, 0x70, 0x87, 0x5a, 0xa1, 0xae, 0xb9, 0x8c, 0xa9, 0xcd, 0x40, 0x69, 0xec, 0x0e, - 0x55, 0x8f, 0x81, 0x66, 0x06, 0xcc, 0xd2, 0x5b, 0x59, 0x60, 0x73, 0x08, 0x5d, 0x28, 0x7c, 0x91, 0xbf, 0xca, 0x6f, - 0x28, 0x3f, 0x09, 0x01, 0xf8, 0x40, 0x35, 0x2f, 0x95, 0x20, 0x90, 0xfc, 0x5e, 0xf4, 0x0d, 0xbd, 0x5c, 0xc8, 0x89, - 0xbf, 0xe3, 0xf9, 0x84, 0x15, 0x14, 0xd4, 0x35, 0x85, 0xff, 0x0c, 0xf6, 0x99, 0xdc, 0x90, 0x20, 0x6c, 0x68, 0x45, - 0x5f, 0xc7, 0xaf, 0x9a, 0xf4, 0x75, 0xb1, 0xfd, 0x62, 0x6c, 0x18, 0x60, 0x73, 0x1b, 0x23, 0xec, 0x69, 0xa3, 0xc2, - 0x92, 0x73, 0x7e, 0x82, 0xb4, 0x88, 0x5f, 0x2c, 0x84, 0x65, 0xbb, 0x35, 0x14, 0x46, 0xaa, 0xb6, 0x0d, 0x2a, 0xc3, - 0x38, 0x06, 0xd5, 0x8e, 0xe7, 0x69, 0x6a, 0x89, 0x2a, 0xcc, 0xfa, 0x95, 0x70, 0xba, 0xd8, 0x7e, 0x71, 0x7a, 0x9f, - 0x7c, 0x82, 0xf7, 0xb6, 0x88, 0x32, 0x80, 0x66, 0x31, 0xe5, 0x60, 0x4b, 0x5a, 0xab, 0xa5, 0xa5, 0xec, 0x49, 0x9e, - 0x65, 0x34, 0x12, 0x34, 0x06, 0x53, 0x85, 0x11, 0xe1, 0x27, 0x79, 0x21, 0xaa, 0xc2, 0x1a, 0x7a, 0x66, 0x41, 0xcf, - 0xfc, 0x28, 0x4c, 0x53, 0x4f, 0x99, 0x25, 0x93, 0xfc, 0x9a, 0xae, 0x81, 0xba, 0xdf, 0x00, 0xb9, 0xea, 0x86, 0x5a, - 0xdd, 0x50, 0xbf, 0x98, 0xa6, 0x2c, 0xa2, 0x95, 0xe8, 0x3a, 0xf5, 0x59, 0x16, 0xd3, 0x5b, 0xe0, 0x23, 0x68, 0x30, - 0x18, 0x74, 0x70, 0x17, 0x95, 0x0a, 0xe1, 0xf3, 0x15, 0xc4, 0xde, 0x23, 0x34, 0x81, 0xc8, 0xc8, 0x60, 0xbe, 0x96, - 0xad, 0x21, 0x4b, 0x52, 0x32, 0x63, 0x5e, 0x29, 0xee, 0x8c, 0x70, 0x4c, 0x53, 0x2a, 0xa8, 0xe1, 0xe6, 0xa0, 0x44, - 0xab, 0xad, 0xfb, 0xbe, 0xc2, 0x5f, 0x45, 0x4e, 0x66, 0x97, 0x99, 0x35, 0x2f, 0x2a, 0x73, 0xbd, 0x5e, 0x9e, 0x1a, - 0xdb, 0x43, 0xa1, 0x96, 0x27, 0x14, 0x22, 0x8c, 0x12, 0x65, 0xa7, 0x7b, 0x2b, 0x53, 0xaa, 0xfb, 0xd0, 0x9c, 0xbd, - 0xda, 0x44, 0xcf, 0x0c, 0x98, 0xeb, 0x50, 0x70, 0xaa, 0x99, 0x02, 0x05, 0xd3, 0x4f, 0x2d, 0xdb, 0x49, 0x98, 0xa6, - 0x57, 0x61, 0xf4, 0xa9, 0x49, 0xfd, 0x35, 0x19, 0x90, 0x65, 0x6e, 0x6c, 0xbd, 0xb2, 0x58, 0x96, 0x3d, 0x6f, 0xc3, - 0xa5, 0x1b, 0x1b, 0xc5, 0xdb, 0xea, 0xd4, 0x64, 0xdf, 0x5c, 0xe8, 0x8d, 0xd4, 0x2e, 0x21, 0x62, 0x7a, 0x66, 0x1e, - 0x70, 0x81, 0xcf, 0x52, 0x9c, 0xe1, 0x07, 0x9a, 0xee, 0xc0, 0xe0, 0x28, 0x97, 0x00, 0x11, 0x68, 0x5e, 0xc6, 0xac, - 0xd8, 0x8c, 0x81, 0xdf, 0x04, 0xca, 0xe7, 0xd6, 0x08, 0x0f, 0x05, 0xb4, 0xe2, 0x71, 0x5a, 0x6b, 0xae, 0x20, 0xd3, - 0xfa, 0x84, 0x61, 0x34, 0xdf, 0x82, 0xee, 0x22, 0xe9, 0xfd, 0xad, 0x7a, 0x05, 0x5a, 0x19, 0x40, 0xc1, 0xfb, 0xb6, - 0x3a, 0xd1, 0xa0, 0x00, 0xcd, 0x53, 0x99, 0x14, 0xb9, 0x79, 0xc3, 0x82, 0xd4, 0x1a, 0xbb, 0x32, 0xc2, 0x35, 0xcb, - 0x2d, 0x88, 0xe7, 0x79, 0x1c, 0x8c, 0x38, 0xa3, 0xdb, 0xd7, 0x93, 0xe0, 0x2b, 0x93, 0xe0, 0xbe, 0x65, 0x68, 0xa1, - 0x9a, 0x96, 0xad, 0xe6, 0x81, 0x10, 0xc8, 0xae, 0x05, 0xfa, 0xaa, 0x0f, 0x0c, 0x1a, 0x55, 0xfc, 0x36, 0x25, 0x02, - 0x17, 0xda, 0xca, 0xd1, 0xa4, 0x06, 0x1c, 0xa3, 0x6e, 0x92, 0x23, 0xb5, 0x37, 0x1a, 0x26, 0x6f, 0x8e, 0x2d, 0x11, - 0x9f, 0x6a, 0xb3, 0x46, 0x23, 0x89, 0x22, 0xbd, 0x38, 0x0d, 0xad, 0xd8, 0x42, 0x0b, 0xce, 0x09, 0x57, 0x9a, 0xb0, - 0x52, 0x7c, 0x96, 0x91, 0x53, 0xf5, 0xbb, 0x45, 0x48, 0x5e, 0xe3, 0x86, 0xfb, 0x6b, 0x74, 0xab, 0x1c, 0xe1, 0xc8, - 0x28, 0xa5, 0x45, 0x3d, 0x71, 0x42, 0x5c, 0xe3, 0x93, 0x70, 0x87, 0xf3, 0x86, 0x5d, 0x18, 0x58, 0xd5, 0xca, 0x00, - 0x78, 0x6a, 0xb1, 0x0e, 0xdf, 0xeb, 0x88, 0xa6, 0xd1, 0x8f, 0x85, 0xf1, 0xa2, 0x81, 0x71, 0x0b, 0xb5, 0xb9, 0xe2, - 0x5d, 0xf9, 0x39, 0x89, 0x9a, 0x8d, 0x3d, 0x8a, 0x0b, 0xb5, 0x10, 0x2b, 0x58, 0x5c, 0x56, 0x3e, 0x25, 0x11, 0x82, - 0x19, 0xcb, 0x41, 0xbd, 0xb3, 0x25, 0x84, 0x07, 0xc0, 0xb3, 0xc5, 0x62, 0x85, 0xec, 0xd6, 0xea, 0xa0, 0xc8, 0xaf, - 0x2d, 0xc3, 0xc5, 0xe2, 0x85, 0x40, 0x9e, 0xd6, 0x7e, 0x31, 0x45, 0x43, 0xc3, 0x73, 0x8f, 0x5f, 0x41, 0x2d, 0xa9, - 0x8c, 0xd6, 0x25, 0x95, 0xd9, 0xd0, 0xa4, 0xda, 0xe6, 0x42, 0x09, 0x8b, 0x71, 0x9f, 0xac, 0xf0, 0x2f, 0x59, 0xa8, - 0x05, 0x75, 0x3d, 0xe5, 0x13, 0xdd, 0x35, 0x43, 0x08, 0x05, 0x5c, 0x5a, 0x32, 0x5b, 0xeb, 0x8c, 0xcb, 0x9d, 0x1d, - 0x6e, 0x75, 0x74, 0x51, 0x31, 0x8a, 0x9f, 0x3c, 0x10, 0xca, 0xc5, 0x5d, 0x26, 0xb5, 0x97, 0x9f, 0x8c, 0x18, 0x5a, - 0x31, 0x4d, 0x3b, 0x7d, 0xb0, 0xc9, 0xc3, 0x9b, 0x90, 0x09, 0xa7, 0xea, 0x45, 0xd9, 0xe4, 0x1e, 0x45, 0x73, 0xad, - 0x6c, 0xf8, 0x9c, 0x82, 0xfa, 0x08, 0x5c, 0xc1, 0x28, 0xd1, 0x8a, 0xf0, 0xa3, 0x84, 0x82, 0x3f, 0xd8, 0xe8, 0x11, - 0x95, 0x6d, 0xb8, 0xa5, 0xe5, 0x88, 0xee, 0x78, 0x3d, 0xec, 0xe5, 0x72, 0xf3, 0x86, 0x2d, 0x30, 0xa5, 0x7c, 0x94, - 0xf3, 0x89, 0x79, 0x57, 0x2e, 0x3d, 0x6b, 0xde, 0xc8, 0x46, 0xde, 0xda, 0xbe, 0xb5, 0x05, 0xd0, 0x5f, 0x32, 0xbc, - 0x6b, 0x93, 0xbd, 0x21, 0x4c, 0x2b, 0xf9, 0xab, 0xdc, 0x82, 0x86, 0x32, 0xb9, 0x6d, 0xe2, 0x6b, 0x9f, 0x6a, 0x5f, - 0xb9, 0x4d, 0xb6, 0xba, 0xfd, 0xca, 0xee, 0x33, 0xd4, 0xd0, 0x57, 0xee, 0x0d, 0x2d, 0x54, 0xf3, 0x59, 0x1a, 0x6b, - 0x60, 0x19, 0xc2, 0x54, 0xd3, 0xd1, 0x0d, 0x4b, 0xd3, 0xba, 0xf4, 0x4b, 0x38, 0x3b, 0xd7, 0x9c, 0x3d, 0x37, 0x9c, - 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd5, 0x5d, 0xdd, 0x3c, 0x5f, 0xd9, 0x9e, 0xb9, 0xe2, 0xe9, 0x5c, 0xda, 0xd2, 0x30, - 0xde, 0xcc, 0x40, 0x80, 0x2a, 0xdd, 0xeb, 0x93, 0xa7, 0x5d, 0x31, 0x60, 0x04, 0x2a, 0x4f, 0x26, 0xb5, 0xdd, 0x14, - 0x9f, 0x3c, 0x84, 0x79, 0x49, 0x2b, 0xca, 0x3e, 0x7e, 0x01, 0xbe, 0x3a, 0x6b, 0x3a, 0x20, 0xc6, 0x64, 0xf1, 0x17, - 0xa9, 0x51, 0x66, 0x76, 0x4c, 0xcf, 0x8e, 0x9b, 0xd9, 0x01, 0xaf, 0xaf, 0x67, 0x17, 0xdf, 0xcf, 0xed, 0xe5, 0xf4, - 0x58, 0x35, 0xbd, 0x7a, 0xbd, 0x17, 0x0b, 0x6f, 0xa9, 0x04, 0xdc, 0xf8, 0xda, 0x48, 0xe1, 0x55, 0xef, 0xc0, 0x03, - 0x6c, 0xcc, 0x40, 0x41, 0xa9, 0x26, 0x5d, 0x09, 0xb9, 0x57, 0x9f, 0x73, 0xf2, 0x48, 0x6f, 0xbd, 0x6a, 0x7f, 0x92, - 0x4f, 0xa6, 0xa0, 0x8f, 0x2d, 0x91, 0xf4, 0x98, 0xea, 0x01, 0xeb, 0xf7, 0xe5, 0x9a, 0xb2, 0x46, 0x1b, 0xb9, 0x1f, - 0x1b, 0xd4, 0x54, 0xd9, 0xcc, 0x5b, 0x9d, 0x72, 0x56, 0x15, 0x55, 0x8c, 0x63, 0x9d, 0x63, 0xe5, 0x64, 0xd9, 0x2d, - 0x63, 0x5e, 0xbc, 0xf5, 0x98, 0xe2, 0xc3, 0x0c, 0x78, 0x9d, 0xc5, 0x7e, 0x0c, 0xb9, 0xdb, 0xeb, 0x5f, 0xd6, 0xc8, - 0x99, 0x97, 0x4b, 0xe8, 0x9b, 0x97, 0xe5, 0x0b, 0x6d, 0x67, 0xe3, 0x17, 0x9b, 0x0d, 0xe2, 0xfa, 0x9d, 0xb6, 0x17, - 0xcf, 0xce, 0xf1, 0x8b, 0x55, 0xed, 0x91, 0xcc, 0x27, 0x79, 0x4c, 0x03, 0x37, 0x9f, 0xd2, 0xcc, 0x2d, 0xc1, 0xbb, - 0xaa, 0x17, 0x7f, 0x26, 0xbc, 0xf9, 0xfb, 0xa6, 0x9b, 0x35, 0x78, 0x51, 0x82, 0x0b, 0xec, 0x87, 0x55, 0x07, 0xec, - 0x77, 0x94, 0x17, 0x52, 0x17, 0xad, 0xd4, 0xda, 0x1f, 0x6a, 0xc1, 0xf4, 0x43, 0xb0, 0xb1, 0x7e, 0x6d, 0x85, 0xb8, - 0x5d, 0xff, 0xb1, 0xbf, 0xe7, 0x22, 0xe9, 0x1e, 0xfe, 0x56, 0xef, 0xf8, 0x9f, 0x8d, 0x7b, 0xf8, 0x94, 0xfc, 0xdc, - 0xf4, 0x0e, 0x4f, 0x05, 0x39, 0x1d, 0x9e, 0x1a, 0xa3, 0x39, 0x4f, 0x59, 0x74, 0xe7, 0xb9, 0x29, 0x13, 0x2d, 0x08, - 0xc1, 0xb9, 0x78, 0xae, 0x5e, 0x80, 0x5f, 0x51, 0xba, 0xb5, 0x4b, 0x63, 0xee, 0x61, 0x26, 0x88, 0xbb, 0x9d, 0x32, - 0xb1, 0xed, 0xe2, 0x3b, 0x72, 0x09, 0x3f, 0xb6, 0xe7, 0xde, 0xeb, 0x50, 0x24, 0x3e, 0x0f, 0xb3, 0x38, 0x9f, 0x78, - 0x68, 0xd7, 0x75, 0x91, 0x5f, 0x48, 0x93, 0xe3, 0x29, 0x2a, 0xb7, 0x2f, 0xf1, 0xa9, 0x20, 0xee, 0xd0, 0xdd, 0xbd, - 0xc3, 0xaf, 0x05, 0xb9, 0x3c, 0xda, 0x9e, 0x9f, 0x8a, 0x72, 0x70, 0x89, 0x8f, 0x2b, 0xcf, 0x3d, 0x7e, 0x43, 0x3c, - 0x44, 0x06, 0xc7, 0x1a, 0x9a, 0x93, 0x7c, 0xa2, 0x3c, 0xf8, 0x2e, 0xc2, 0xef, 0x65, 0x7c, 0xa5, 0x66, 0x37, 0x3a, - 0xc4, 0xb2, 0x45, 0xdc, 0x5c, 0x7a, 0x09, 0xdc, 0x9d, 0x1d, 0xab, 0xac, 0x52, 0x16, 0xf0, 0x89, 0x20, 0x0d, 0x9b, - 0x1c, 0xbf, 0x92, 0x91, 0x9a, 0x13, 0xe1, 0x65, 0xc8, 0x74, 0xe3, 0x19, 0x77, 0xb4, 0xde, 0x9b, 0xd9, 0x99, 0x72, - 0x32, 0xf8, 0x4c, 0x50, 0x1e, 0x8a, 0x9c, 0x9f, 0x23, 0x5b, 0x01, 0xc1, 0x7f, 0x26, 0x97, 0x67, 0xce, 0x7f, 0xf8, - 0xdd, 0x8f, 0xa3, 0x1f, 0xf9, 0xf9, 0x25, 0xfe, 0x48, 0xda, 0x47, 0xde, 0x30, 0xf0, 0xb6, 0x5a, 0xad, 0xc5, 0x8f, - 0xed, 0xb3, 0xbf, 0x85, 0xad, 0x5f, 0x8e, 0x5b, 0x3f, 0x9c, 0xa3, 0x85, 0xf7, 0x63, 0x7b, 0x78, 0xa6, 0x9f, 0xce, - 0xfe, 0x36, 0xf8, 0xb1, 0x38, 0xff, 0xbd, 0x2a, 0xdc, 0x46, 0xa8, 0x3d, 0xc6, 0x63, 0x41, 0xda, 0xad, 0xd6, 0xa0, - 0x3d, 0xc6, 0x13, 0x41, 0xda, 0xf0, 0xef, 0x0d, 0x79, 0x4f, 0xc7, 0x2f, 0x6e, 0xa7, 0xde, 0xe5, 0x60, 0xb1, 0x3d, - 0xff, 0x73, 0x09, 0xbd, 0x9e, 0xfd, 0xed, 0xc7, 0x1f, 0x0b, 0xf7, 0xd1, 0x80, 0xb4, 0xcf, 0x77, 0x91, 0x07, 0xa5, - 0xbf, 0x27, 0xf2, 0xaf, 0x37, 0x0c, 0xce, 0xfe, 0xa6, 0xa1, 0x70, 0x1f, 0xfd, 0x78, 0x79, 0x34, 0x20, 0xe7, 0x0b, - 0xcf, 0x5d, 0x3c, 0x42, 0x0b, 0x84, 0x16, 0xdb, 0xe8, 0x12, 0xbb, 0x63, 0x17, 0xe1, 0x91, 0x20, 0xed, 0x47, 0xed, - 0x31, 0xbe, 0x10, 0xa4, 0xed, 0xb6, 0xc7, 0xf8, 0xad, 0x20, 0xed, 0xbf, 0x79, 0xc3, 0x40, 0xb9, 0xd9, 0x16, 0xd2, - 0xc3, 0xb1, 0x80, 0x20, 0x47, 0xc8, 0x69, 0xb8, 0x10, 0x4c, 0xa4, 0x14, 0x6d, 0xb7, 0x19, 0xfe, 0x24, 0xd1, 0xe4, - 0x09, 0xf0, 0xc3, 0x80, 0x79, 0xe7, 0xcd, 0x2f, 0x60, 0xb1, 0x81, 0x66, 0xb6, 0x83, 0x0c, 0x2b, 0x57, 0x40, 0x11, - 0x08, 0x7c, 0x1d, 0xa6, 0x33, 0x5a, 0x04, 0xb4, 0x44, 0x38, 0x25, 0x9f, 0x84, 0xd7, 0x45, 0xf8, 0x1b, 0x01, 0x3f, - 0x7a, 0x08, 0x9f, 0xe8, 0x40, 0x26, 0xec, 0x64, 0x45, 0x54, 0x59, 0xae, 0x54, 0x16, 0x17, 0xe1, 0xf1, 0x9a, 0x97, - 0x22, 0x01, 0x07, 0x03, 0xc2, 0xd7, 0x8d, 0xb0, 0x27, 0xbe, 0x25, 0x86, 0x24, 0x3e, 0x70, 0x4a, 0xbf, 0x0f, 0xd3, - 0x4f, 0x94, 0x7b, 0xc7, 0xb8, 0xdb, 0x7b, 0x8a, 0xa5, 0x1f, 0x7a, 0xab, 0x8b, 0xfa, 0x55, 0xcc, 0xea, 0x9d, 0x50, - 0xa1, 0x02, 0x90, 0xb2, 0x4d, 0x77, 0x0c, 0xac, 0xf8, 0x56, 0xb6, 0xe2, 0xb3, 0xe2, 0xe1, 0x8d, 0x8b, 0x9a, 0xf1, - 0x51, 0x96, 0x5d, 0x87, 0x29, 0x8b, 0x1d, 0x41, 0x27, 0xd3, 0x34, 0x14, 0xd4, 0xd1, 0xf3, 0x75, 0x42, 0xe8, 0xc8, - 0xad, 0x74, 0x86, 0xa9, 0x65, 0x73, 0x4e, 0x4d, 0xe0, 0x09, 0xf6, 0x8a, 0x07, 0x51, 0x2a, 0xad, 0x77, 0x3c, 0xaf, - 0x83, 0x60, 0xcb, 0x71, 0xbe, 0x56, 0x17, 0x7c, 0x61, 0xe7, 0x52, 0x3e, 0x83, 0x1e, 0x0d, 0x52, 0xb4, 0x37, 0x74, - 0x8f, 0x8a, 0xeb, 0xf1, 0xc0, 0x85, 0x18, 0x4d, 0x41, 0x3e, 0x4a, 0xd7, 0x10, 0x54, 0x88, 0x48, 0xa7, 0x1f, 0x1d, - 0xd1, 0x7e, 0xb4, 0xbb, 0x6b, 0xb4, 0xe8, 0x90, 0x64, 0x67, 0x91, 0x6a, 0x9e, 0xe0, 0x18, 0xcf, 0x48, 0xab, 0x8b, - 0xa7, 0xa4, 0x23, 0x9b, 0xf4, 0xa7, 0x47, 0xa1, 0x1e, 0x66, 0x67, 0xc7, 0x2b, 0xfc, 0x34, 0x2c, 0xc4, 0x37, 0x60, - 0xef, 0x93, 0x29, 0x8e, 0x49, 0xe1, 0xd3, 0x5b, 0x1a, 0x79, 0x21, 0xc2, 0xb1, 0xe6, 0x34, 0xa8, 0x8f, 0xa6, 0xc4, - 0xaa, 0x06, 0x66, 0x04, 0xf9, 0x38, 0x8c, 0xcf, 0xba, 0xe7, 0x84, 0x10, 0x77, 0xab, 0xd5, 0x72, 0x87, 0x05, 0x19, - 0x8b, 0x00, 0x4a, 0x2c, 0x65, 0x99, 0x4c, 0xa0, 0xa8, 0x67, 0x15, 0x79, 0x6f, 0x85, 0x2f, 0x68, 0x21, 0x3c, 0x28, - 0x06, 0x0f, 0x00, 0x37, 0x84, 0xed, 0x1e, 0xb5, 0xdd, 0x5d, 0x28, 0x95, 0xc4, 0x89, 0x70, 0x41, 0x6e, 0x50, 0x10, - 0x9f, 0xed, 0x9d, 0xdb, 0x02, 0x40, 0x16, 0xc2, 0xe0, 0x37, 0xc3, 0xf8, 0xac, 0x23, 0x07, 0x1f, 0xb8, 0x43, 0xaf, - 0x20, 0x5c, 0x69, 0x68, 0x43, 0x1e, 0x7c, 0x94, 0x53, 0x45, 0x81, 0x06, 0x4e, 0x8f, 0x3b, 0x23, 0xad, 0x5e, 0xe0, - 0xcd, 0xec, 0x49, 0xb4, 0x60, 0x30, 0x8d, 0x05, 0x9c, 0x10, 0xa8, 0x8f, 0x0b, 0x02, 0x23, 0xd6, 0xcd, 0x6e, 0x02, - 0xfd, 0xfc, 0xc8, 0x7d, 0x34, 0xbc, 0x10, 0xc1, 0x48, 0xa8, 0xe1, 0x2f, 0xc4, 0x62, 0x01, 0xff, 0x8e, 0xc4, 0xb0, - 0x20, 0x37, 0xb2, 0x68, 0xac, 0x8b, 0x26, 0x50, 0xf4, 0x31, 0x00, 0x50, 0x31, 0xaf, 0xb4, 0x2c, 0xb5, 0x26, 0x13, - 0x22, 0x61, 0xdf, 0xd9, 0xc9, 0xce, 0xa2, 0xdd, 0xee, 0x39, 0x38, 0xf9, 0xb9, 0x28, 0xbe, 0x67, 0x22, 0xf1, 0xdc, - 0xf6, 0xc0, 0x45, 0x43, 0xd7, 0x81, 0xa5, 0xed, 0xe7, 0xbb, 0x44, 0x61, 0x38, 0xdc, 0x7d, 0x2d, 0x82, 0xd9, 0x80, - 0x74, 0x86, 0x1e, 0x53, 0x2c, 0x3c, 0x41, 0x38, 0xd4, 0x8c, 0xb3, 0x83, 0x67, 0x68, 0x97, 0x89, 0x5d, 0xf3, 0x3c, - 0x43, 0xbb, 0x77, 0xbb, 0x13, 0x14, 0x84, 0xbb, 0x77, 0xbb, 0xde, 0x8c, 0x10, 0xd2, 0xea, 0x55, 0xcd, 0x8c, 0xf8, - 0x8b, 0x50, 0x30, 0x31, 0xfe, 0xce, 0x33, 0xb9, 0x1d, 0xf2, 0x5d, 0x2f, 0x3b, 0xa3, 0xe7, 0x8b, 0x85, 0x7b, 0x34, - 0x1c, 0xb8, 0x68, 0xd7, 0x33, 0x84, 0xd6, 0x36, 0x94, 0x86, 0x10, 0x66, 0xe7, 0xa5, 0x8e, 0x27, 0x3d, 0x6b, 0xc4, - 0x8e, 0xe6, 0xf5, 0x66, 0xb7, 0x78, 0x00, 0x2d, 0x2b, 0x43, 0x46, 0x29, 0xac, 0x53, 0x98, 0xa6, 0x21, 0xe6, 0x9c, - 0x74, 0x70, 0x41, 0x8c, 0xfb, 0x3a, 0x22, 0xa2, 0x26, 0xf8, 0x90, 0xd4, 0xd5, 0xf1, 0x59, 0x82, 0xe3, 0x73, 0xf2, - 0x5c, 0x19, 0x24, 0x7d, 0xe3, 0x1c, 0xa7, 0x29, 0x79, 0xb6, 0x14, 0xc5, 0x4d, 0x20, 0xc0, 0x72, 0xeb, 0x47, 0x33, - 0xce, 0x69, 0x26, 0xde, 0xe4, 0xb1, 0xd6, 0xd3, 0x68, 0x0a, 0xa6, 0x12, 0x84, 0x67, 0x31, 0x28, 0x69, 0x3d, 0xb3, - 0x33, 0x66, 0x2b, 0xaf, 0xa7, 0x64, 0xa6, 0xf4, 0x27, 0x19, 0xb4, 0xed, 0x4f, 0xb5, 0x65, 0xec, 0x21, 0x3c, 0xd3, - 0xd1, 0x5c, 0xcf, 0xf7, 0xfd, 0xa9, 0x1f, 0xc1, 0x6b, 0x18, 0xa0, 0x40, 0xa5, 0xdc, 0x47, 0x1e, 0x27, 0xb7, 0x7e, - 0x46, 0x6f, 0xe5, 0xa8, 0x1e, 0xaa, 0x25, 0xb3, 0xd9, 0x5e, 0x47, 0x51, 0x5f, 0xb2, 0x1b, 0xee, 0x67, 0x79, 0x4c, - 0x01, 0x3d, 0x10, 0xbf, 0xd7, 0x45, 0x49, 0x58, 0xd8, 0x41, 0xaa, 0x1a, 0xbe, 0x33, 0xdb, 0x7f, 0x3d, 0x05, 0xa7, - 0xaf, 0xb4, 0xf4, 0xaa, 0xca, 0xca, 0x13, 0x8e, 0x10, 0x1b, 0x79, 0x53, 0x1f, 0x82, 0x7b, 0x92, 0x84, 0x18, 0xd8, - 0x72, 0x53, 0x9b, 0xa8, 0xee, 0xaa, 0x3e, 0x27, 0x24, 0x3e, 0x2b, 0x76, 0x77, 0xa5, 0x23, 0x7a, 0xa6, 0x48, 0x62, - 0x8a, 0xf0, 0xa4, 0xda, 0x5b, 0xa6, 0xde, 0x3b, 0xd2, 0x1c, 0xc9, 0x9b, 0x34, 0x1d, 0xba, 0xbb, 0x4c, 0x20, 0xe9, - 0x2b, 0x14, 0xde, 0x1d, 0xc2, 0x23, 0xd2, 0xf6, 0xce, 0xfc, 0xe1, 0x1f, 0xce, 0xd1, 0xd0, 0xf3, 0x7f, 0x8f, 0xda, - 0x8a, 0x71, 0x4c, 0x50, 0x3f, 0x54, 0x43, 0xcc, 0x65, 0x14, 0xb3, 0x8b, 0xa5, 0x2f, 0x31, 0xc8, 0x71, 0x16, 0x4e, - 0x68, 0x30, 0x82, 0x3d, 0x6e, 0xe8, 0xe6, 0x1d, 0x06, 0x3a, 0x0a, 0x46, 0x9a, 0x93, 0xf8, 0xee, 0xf0, 0x67, 0x51, - 0x3d, 0x0d, 0xdd, 0xe1, 0xd7, 0xf5, 0xd3, 0x1f, 0xdc, 0xe1, 0x77, 0x22, 0xf8, 0xae, 0xd4, 0xee, 0xee, 0xc6, 0x10, - 0x8f, 0xcd, 0x10, 0xa5, 0x5a, 0x18, 0x0b, 0x73, 0x33, 0xc4, 0x57, 0x1c, 0x1d, 0x53, 0x54, 0xb2, 0x51, 0xc5, 0x8a, - 0xb8, 0x2f, 0xc2, 0x31, 0xa0, 0xd4, 0x5a, 0x01, 0x6e, 0x47, 0xf7, 0xeb, 0x09, 0x03, 0xa1, 0x18, 0x6a, 0x05, 0x54, - 0x4e, 0x07, 0x1d, 0x34, 0x6f, 0xd4, 0x95, 0x1a, 0x53, 0x33, 0x9a, 0x5e, 0x71, 0xe9, 0x09, 0xe9, 0xf4, 0x27, 0x47, - 0xd3, 0xfe, 0x64, 0x77, 0x17, 0x71, 0x43, 0x58, 0xb3, 0xb3, 0xc9, 0x39, 0x7e, 0x03, 0x5e, 0x3d, 0x9b, 0x92, 0x70, - 0x63, 0x7a, 0x3d, 0x3d, 0xbd, 0xdd, 0xdd, 0xbc, 0x44, 0x7d, 0xab, 0xe9, 0x54, 0x35, 0x2d, 0x4b, 0x85, 0x93, 0x65, - 0x42, 0x3b, 0x44, 0xb2, 0x04, 0x52, 0xa2, 0x08, 0x21, 0xa7, 0x02, 0xad, 0xed, 0x15, 0xfa, 0x84, 0xe6, 0x72, 0xc7, - 0x02, 0xf3, 0x54, 0x32, 0xc2, 0x03, 0x2c, 0x40, 0xd3, 0xca, 0x15, 0x7c, 0x87, 0x67, 0xbb, 0x5d, 0x49, 0xe4, 0xad, - 0x6e, 0xbf, 0xd9, 0xd7, 0x93, 0xba, 0x2f, 0x3c, 0xdb, 0x25, 0x77, 0x15, 0x96, 0xca, 0x7c, 0x77, 0xb7, 0x6c, 0xc6, - 0x3b, 0xcd, 0xbe, 0x6d, 0x44, 0x20, 0x8e, 0x97, 0x53, 0x33, 0x8c, 0x7c, 0xad, 0x25, 0x2a, 0xf3, 0x59, 0x96, 0x51, - 0x0e, 0x32, 0x94, 0x08, 0xcc, 0xca, 0xb2, 0x92, 0xeb, 0x6f, 0x41, 0x88, 0x62, 0x4a, 0x32, 0xe0, 0x3b, 0xd2, 0xec, - 0xc2, 0x39, 0x2e, 0x70, 0x24, 0xb9, 0x06, 0x21, 0xe4, 0xc4, 0x24, 0xb5, 0x08, 0xc9, 0x81, 0x42, 0xc2, 0x2c, 0x89, - 0xc4, 0x09, 0xf5, 0x2f, 0xb6, 0x4f, 0xf2, 0x7b, 0x4d, 0xb2, 0x33, 0x76, 0x1e, 0xc8, 0x6a, 0xa9, 0xe6, 0x5b, 0x09, - 0x79, 0xef, 0x09, 0x54, 0x85, 0x47, 0x7c, 0xc9, 0xfe, 0x9e, 0x33, 0x4e, 0xa5, 0x06, 0xbe, 0x6d, 0xcc, 0xbe, 0xb0, - 0xa9, 0x3e, 0x86, 0xb6, 0xf3, 0x06, 0x10, 0x09, 0xf2, 0xd7, 0xcb, 0xc9, 0x4a, 0xb5, 0x8b, 0xed, 0xe3, 0xb7, 0xeb, - 0x4c, 0xe0, 0xc5, 0x42, 0x1b, 0xbf, 0x21, 0x68, 0x36, 0x38, 0xa9, 0x21, 0x0d, 0xf5, 0x8f, 0xc0, 0x0b, 0xa5, 0x82, - 0x94, 0x78, 0x19, 0x50, 0xd1, 0xc5, 0xf6, 0xf1, 0x07, 0x2f, 0x93, 0xae, 0x25, 0x84, 0xed, 0x69, 0x7b, 0x05, 0xf1, - 0x22, 0x42, 0x91, 0x9a, 0x7b, 0xc5, 0xb8, 0x0a, 0x4b, 0x7c, 0x07, 0x91, 0x7c, 0x09, 0xf6, 0xc3, 0x19, 0x3b, 0x27, - 0xa1, 0xc6, 0x00, 0x09, 0x11, 0x0e, 0x1b, 0x66, 0x19, 0x81, 0x05, 0x90, 0x63, 0x9d, 0xc2, 0x4a, 0xf8, 0x4a, 0xf1, - 0x43, 0x38, 0x94, 0xa3, 0x8a, 0x52, 0x89, 0x8e, 0x9f, 0x56, 0x72, 0xd3, 0x6a, 0x6b, 0xf4, 0x3b, 0xb0, 0x9c, 0xcc, - 0xc3, 0x1b, 0xdd, 0x75, 0x55, 0xf0, 0xdc, 0x24, 0x91, 0x5d, 0x6c, 0x1f, 0xbf, 0xd6, 0x79, 0x64, 0xd3, 0xd0, 0x70, - 0xfb, 0x15, 0x0b, 0xf3, 0xf8, 0xb5, 0x5f, 0xbf, 0x95, 0x95, 0x2f, 0xb6, 0x8f, 0x3f, 0xae, 0xab, 0x06, 0xe5, 0xe5, - 0xac, 0x36, 0xf1, 0x25, 0x7c, 0x73, 0x9a, 0x06, 0x73, 0x2d, 0x1a, 0x02, 0x56, 0x62, 0x29, 0x8e, 0x02, 0x5e, 0x56, - 0x9e, 0x91, 0xe7, 0x38, 0x27, 0x32, 0x0e, 0xd4, 0x5c, 0x35, 0xad, 0xe4, 0xb1, 0x3c, 0x3b, 0x8d, 0xf2, 0x29, 0xdd, - 0x10, 0x1c, 0x3a, 0x46, 0x3e, 0x9b, 0x40, 0x02, 0x8d, 0x04, 0x9d, 0xe1, 0xad, 0x0e, 0xea, 0x37, 0x85, 0x57, 0x2e, - 0x89, 0xb4, 0x68, 0x48, 0x16, 0x1c, 0x91, 0x0e, 0x0e, 0x49, 0x07, 0x27, 0x84, 0x9f, 0x75, 0x94, 0x78, 0xe8, 0xd7, - 0xa1, 0x5c, 0x25, 0x64, 0x22, 0x42, 0x48, 0xa2, 0x76, 0xab, 0x12, 0xbf, 0x71, 0x3f, 0x91, 0xae, 0x47, 0x29, 0xd1, - 0x63, 0x65, 0xb4, 0x7a, 0x05, 0x2e, 0x64, 0xc7, 0xa7, 0xec, 0x2a, 0x85, 0xec, 0x12, 0x98, 0x15, 0x16, 0x28, 0xa8, - 0xaa, 0x76, 0x75, 0xd5, 0xc4, 0x97, 0xeb, 0x54, 0xe0, 0xc4, 0x07, 0xc6, 0x8d, 0x13, 0x9d, 0x8c, 0x53, 0xac, 0x36, - 0x79, 0xbc, 0xb3, 0xe3, 0xa9, 0x46, 0xdf, 0x0b, 0xaf, 0x7a, 0x5f, 0x87, 0xee, 0xbe, 0x53, 0xbc, 0x22, 0x46, 0x12, - 0xfe, 0xdd, 0xdd, 0xf0, 0xbc, 0x8c, 0xb6, 0x08, 0xf1, 0x92, 0x26, 0x06, 0x0d, 0xf0, 0x52, 0xd3, 0x6b, 0x4e, 0x7f, - 0x77, 0xb7, 0x0a, 0xd3, 0x36, 0xb1, 0x75, 0x8c, 0xf3, 0xf2, 0xda, 0xab, 0xf2, 0x7f, 0x3a, 0x2b, 0x59, 0x53, 0x06, - 0x04, 0xc4, 0x6c, 0x9a, 0x65, 0x66, 0x32, 0xd6, 0x96, 0x60, 0x50, 0xef, 0x1b, 0x9d, 0xb8, 0x80, 0x65, 0x8e, 0x95, - 0xae, 0x64, 0xd8, 0x59, 0x0f, 0x05, 0xa6, 0x12, 0x84, 0xa5, 0xa0, 0xd2, 0x6e, 0xa9, 0xc9, 0xfb, 0xf5, 0x6a, 0xe6, - 0x25, 0xe6, 0x48, 0xfb, 0xb8, 0x24, 0x14, 0x12, 0x59, 0xbd, 0x0a, 0x29, 0x2f, 0xc9, 0x78, 0x33, 0xc9, 0x1f, 0x5b, - 0x24, 0xff, 0x8c, 0x50, 0x8b, 0xfc, 0x95, 0x87, 0xc3, 0xcf, 0xb5, 0x6b, 0x81, 0x9b, 0x57, 0x27, 0x53, 0x02, 0x3e, - 0xb4, 0x26, 0x46, 0xb9, 0x1d, 0x57, 0xdc, 0xc0, 0x50, 0xec, 0x1d, 0x22, 0xbd, 0x90, 0xd8, 0x04, 0x81, 0xbd, 0x3a, - 0xaa, 0x06, 0x43, 0xaf, 0x73, 0xe9, 0xd9, 0x1c, 0xf0, 0xf8, 0xe3, 0xfd, 0x01, 0xd1, 0x93, 0xe9, 0xea, 0xce, 0xb5, - 0x32, 0x40, 0x61, 0xd6, 0xd6, 0xc6, 0x6d, 0xe6, 0x83, 0xc2, 0xf8, 0x55, 0x20, 0xbb, 0xc9, 0x7c, 0x96, 0x36, 0xa1, - 0x91, 0x7f, 0x00, 0x6d, 0xb7, 0x2b, 0x6b, 0x50, 0xab, 0x5b, 0xe0, 0x47, 0x2a, 0x0f, 0x35, 0xe4, 0x1b, 0xd8, 0xc7, - 0xb1, 0xac, 0x40, 0xb3, 0x78, 0xfd, 0xeb, 0x67, 0xa5, 0x26, 0x13, 0x05, 0x1a, 0x9a, 0x03, 0xff, 0x53, 0x24, 0x0f, - 0x74, 0x23, 0xe5, 0x02, 0x20, 0x68, 0x2c, 0xf1, 0x54, 0x23, 0xcc, 0x75, 0x6b, 0xe7, 0xfb, 0xcb, 0x2d, 0x42, 0xc6, - 0xb5, 0xf3, 0xf1, 0x7d, 0x9d, 0x7d, 0x05, 0x64, 0x81, 0x02, 0x30, 0x1e, 0xab, 0x02, 0x15, 0xbf, 0x3c, 0x31, 0xd5, - 0xa5, 0x01, 0xe9, 0xd7, 0xfa, 0xb6, 0x15, 0xdb, 0x94, 0x5e, 0x39, 0xf5, 0xde, 0xa0, 0x61, 0xe9, 0xed, 0x36, 0xbc, - 0x7d, 0x25, 0x24, 0x8c, 0xf0, 0xfc, 0x41, 0xd6, 0x36, 0xfd, 0x96, 0x9f, 0x96, 0x53, 0x58, 0x96, 0x16, 0xc5, 0x67, - 0x59, 0x41, 0xb9, 0x78, 0x46, 0x47, 0x39, 0x87, 0x90, 0x45, 0x85, 0x13, 0x54, 0x6e, 0x5b, 0x6e, 0x3b, 0x39, 0x3f, - 0x2b, 0x4e, 0xb0, 0x34, 0x41, 0xf9, 0xeb, 0x93, 0x8c, 0x5a, 0x5f, 0x2c, 0xb7, 0x1a, 0xef, 0xec, 0xbc, 0xaf, 0xd1, - 0xa4, 0xa1, 0x94, 0x50, 0x58, 0x4c, 0x4b, 0xa9, 0x34, 0x3a, 0x94, 0xbb, 0xed, 0x55, 0x2e, 0x00, 0xc3, 0x30, 0x6c, - 0xde, 0xf3, 0x92, 0x88, 0x72, 0xbc, 0xcc, 0xe2, 0xb5, 0x6b, 0x82, 0xd9, 0x66, 0x0b, 0x70, 0x78, 0x30, 0xb4, 0x95, - 0xaf, 0x88, 0xd7, 0x29, 0xb1, 0x15, 0x0c, 0x27, 0x80, 0x2c, 0x0f, 0xc2, 0xbd, 0x76, 0xd8, 0x83, 0xaf, 0x33, 0x4a, - 0xde, 0x81, 0x5e, 0x99, 0x60, 0xee, 0x27, 0x90, 0x04, 0xdb, 0xd8, 0xb2, 0x08, 0x61, 0x2e, 0x0d, 0x1a, 0x2b, 0x97, - 0xe0, 0xf8, 0xe5, 0x3a, 0x8f, 0xb2, 0x21, 0x6a, 0x2a, 0xa5, 0x0e, 0xd4, 0xc8, 0x51, 0xd5, 0xc0, 0xbf, 0xf6, 0x98, - 0x56, 0xdc, 0x4c, 0xdc, 0x0c, 0x18, 0xf0, 0x4f, 0xc2, 0x53, 0xb1, 0x28, 0x90, 0x19, 0x85, 0x3f, 0xf3, 0x1a, 0x43, - 0xf7, 0x0b, 0xd9, 0x0c, 0x6b, 0xc4, 0x45, 0x36, 0x9a, 0x0a, 0x19, 0xd7, 0x3b, 0xa9, 0x79, 0xe9, 0xb5, 0xca, 0xa3, - 0x16, 0x86, 0x0b, 0xd6, 0x99, 0x24, 0xd6, 0xf4, 0xaf, 0x55, 0x6a, 0x74, 0x55, 0x09, 0xd4, 0x30, 0x7a, 0xe3, 0x3c, - 0x93, 0x6b, 0x40, 0x4b, 0xa0, 0xaf, 0xf9, 0x89, 0xb0, 0x56, 0xd4, 0xf8, 0xb0, 0xe5, 0x98, 0x96, 0xd4, 0x7f, 0x0f, - 0xb9, 0x2e, 0xcb, 0x7b, 0xfe, 0xa5, 0x94, 0x85, 0x0c, 0xf3, 0x06, 0x63, 0xcf, 0x25, 0x63, 0x47, 0xa0, 0xa7, 0x99, - 0xf4, 0xef, 0xa1, 0x4e, 0x79, 0xd1, 0xb9, 0x8b, 0x9e, 0x26, 0xb1, 0x37, 0x55, 0xb8, 0xdc, 0xfa, 0xbd, 0xb4, 0x1a, - 0x01, 0x23, 0x90, 0x06, 0x84, 0x35, 0x67, 0xcf, 0x11, 0xe6, 0xbb, 0xbb, 0x7d, 0x7e, 0x44, 0x6b, 0x17, 0x49, 0x0d, - 0x23, 0x83, 0x88, 0x2e, 0x10, 0x7c, 0x43, 0x86, 0x72, 0x84, 0xab, 0x3c, 0x74, 0x0e, 0xae, 0xf6, 0xe3, 0xf7, 0x9e, - 0xcd, 0xd5, 0xec, 0xba, 0x55, 0xd0, 0x14, 0xe6, 0xe3, 0xd5, 0xf1, 0x96, 0x77, 0xf7, 0x67, 0x78, 0x00, 0xdc, 0x5b, - 0x5d, 0x0c, 0xd9, 0x68, 0xa8, 0x2f, 0x14, 0x4b, 0xa8, 0x76, 0x5f, 0x1f, 0xd5, 0x89, 0x89, 0xf6, 0x60, 0x7d, 0x51, - 0x9b, 0xb2, 0x82, 0xf0, 0xb2, 0x2c, 0x68, 0x1d, 0xdf, 0x5f, 0xca, 0xc0, 0x94, 0xc2, 0x65, 0xd5, 0xd9, 0x7e, 0x32, - 0x25, 0x02, 0x5b, 0x84, 0xfa, 0x6e, 0x53, 0xe8, 0xa3, 0x06, 0x13, 0xf6, 0xb5, 0x16, 0x8a, 0xdf, 0xad, 0x13, 0x8a, - 0x38, 0xd7, 0x5b, 0x5e, 0x0a, 0xc4, 0xee, 0x03, 0x04, 0xa2, 0x76, 0xb2, 0x1b, 0x99, 0x08, 0xea, 0x48, 0x43, 0x26, - 0xf2, 0xa6, 0x4c, 0xcc, 0x31, 0xd3, 0xab, 0x31, 0xe8, 0x2d, 0x16, 0xec, 0xac, 0x03, 0x4e, 0x24, 0xd7, 0x85, 0x9f, - 0x5d, 0xf5, 0xd3, 0xe2, 0xc4, 0xca, 0x09, 0xec, 0xb1, 0xca, 0x64, 0x41, 0x3e, 0xa4, 0x39, 0x7b, 0x32, 0x2b, 0x4b, - 0xd2, 0xb4, 0xa6, 0x20, 0x4d, 0xe0, 0x84, 0x55, 0x51, 0x26, 0x80, 0x58, 0xca, 0x0a, 0x6d, 0x40, 0x7a, 0x6b, 0xd3, - 0xff, 0x8c, 0x79, 0xf9, 0x79, 0x4d, 0xb4, 0x21, 0x57, 0x94, 0xfa, 0xd0, 0x48, 0x38, 0xd0, 0x10, 0x68, 0xfd, 0x70, - 0x4b, 0x9a, 0xa0, 0xb5, 0x28, 0x47, 0xb6, 0x1c, 0xc2, 0x1d, 0x70, 0xa1, 0x6d, 0xbd, 0x57, 0x01, 0xde, 0x35, 0xd2, - 0x04, 0x17, 0x16, 0x5d, 0xbf, 0x24, 0xa2, 0xc1, 0x4a, 0x22, 0xa2, 0x2d, 0x25, 0x9c, 0x48, 0x32, 0x15, 0x24, 0x3f, - 0xeb, 0x9c, 0x83, 0x02, 0xda, 0x0f, 0x8f, 0xf2, 0xda, 0x04, 0x0e, 0x77, 0x77, 0x51, 0x62, 0x46, 0x8d, 0xce, 0xd8, - 0x6e, 0x78, 0x8e, 0x29, 0x0e, 0x95, 0x61, 0x72, 0xb2, 0xb3, 0xe3, 0x25, 0xf5, 0xb8, 0x67, 0xe1, 0x39, 0xc2, 0xc5, - 0x62, 0xe1, 0x49, 0xb0, 0x12, 0xb4, 0x58, 0x24, 0x36, 0x58, 0xf2, 0x35, 0x34, 0x1b, 0x0f, 0x05, 0x19, 0x4b, 0x01, - 0x38, 0x06, 0x08, 0x77, 0x89, 0x97, 0x68, 0xe7, 0x5e, 0x02, 0xce, 0xa8, 0xdd, 0xfc, 0x2c, 0xdc, 0xed, 0x9e, 0x5b, - 0x8c, 0xeb, 0x2c, 0x3c, 0x27, 0x49, 0x59, 0xec, 0xec, 0x6c, 0x71, 0x2d, 0x22, 0x7f, 0x02, 0x51, 0xf6, 0x93, 0x94, - 0x2c, 0xaa, 0x43, 0x7b, 0x35, 0x96, 0x9d, 0x01, 0x15, 0x45, 0xe9, 0x65, 0x35, 0xf5, 0x1a, 0x59, 0x10, 0x55, 0x25, - 0xac, 0x63, 0xc1, 0x43, 0xb0, 0xec, 0x2b, 0x32, 0xff, 0x59, 0x54, 0x69, 0xd6, 0xdf, 0xad, 0x4d, 0xae, 0xf6, 0x7d, - 0x3f, 0xe4, 0x63, 0x19, 0xc9, 0x30, 0xe9, 0x14, 0x92, 0xf8, 0xf7, 0x34, 0x98, 0xd6, 0xc0, 0x67, 0xd5, 0x58, 0xe7, - 0x44, 0x81, 0x6f, 0x54, 0x1b, 0x73, 0xa2, 0xe4, 0x97, 0xb5, 0x5e, 0x06, 0x05, 0xc9, 0xd7, 0xbf, 0x16, 0x92, 0x7d, - 0x0d, 0x89, 0x22, 0x8f, 0x25, 0x9c, 0x6d, 0xc0, 0xc5, 0x2f, 0x62, 0x09, 0x67, 0x9b, 0x71, 0x5b, 0x31, 0x84, 0x4d, - 0xf0, 0x59, 0xbc, 0x41, 0x01, 0x5a, 0x17, 0x58, 0x50, 0x1e, 0x2c, 0xeb, 0x5e, 0x8a, 0x95, 0x82, 0x30, 0x15, 0xc4, - 0x63, 0xcd, 0x0d, 0x50, 0x6b, 0xa3, 0x96, 0xe1, 0xcb, 0x82, 0x31, 0xb2, 0x5c, 0x02, 0xcd, 0xd4, 0x15, 0x20, 0x27, - 0xed, 0x6b, 0x87, 0x54, 0x84, 0x2d, 0xa5, 0xc4, 0xf9, 0x51, 0x38, 0x15, 0x33, 0x0e, 0xaa, 0x14, 0x37, 0xbf, 0xa1, - 0x18, 0xce, 0x82, 0xc8, 0x32, 0xf8, 0x01, 0x05, 0xd3, 0xb0, 0x28, 0xd8, 0xb5, 0x2a, 0xd3, 0xbf, 0x71, 0x41, 0x0c, - 0x29, 0x73, 0xa5, 0x13, 0xe6, 0xa8, 0x9f, 0x6b, 0x3a, 0x6d, 0xa2, 0xed, 0xc5, 0x35, 0xcd, 0xc4, 0x2b, 0x56, 0x08, - 0x9a, 0xc1, 0xf4, 0x6b, 0x8a, 0x83, 0x19, 0x71, 0x04, 0x1b, 0xb6, 0xd1, 0x2a, 0x8c, 0xe3, 0x7b, 0x9b, 0x88, 0xa6, - 0x0e, 0x94, 0x84, 0x59, 0x9c, 0xaa, 0x41, 0xec, 0x84, 0x46, 0x93, 0xc4, 0x59, 0xd5, 0xb4, 0xf3, 0x69, 0x6a, 0x65, - 0x43, 0x72, 0x77, 0x8f, 0x11, 0x23, 0x09, 0x8c, 0xf4, 0xbc, 0x57, 0x6b, 0x81, 0x80, 0xf7, 0x86, 0x45, 0xb0, 0x67, - 0x82, 0x85, 0xc5, 0x51, 0xfd, 0x26, 0x9c, 0x86, 0x6e, 0xbe, 0x5f, 0x7b, 0xb0, 0x6d, 0x9d, 0x70, 0x90, 0x74, 0xf2, - 0x78, 0xb3, 0x65, 0xf5, 0xda, 0x48, 0x0e, 0x23, 0x2d, 0xd8, 0x43, 0x19, 0x33, 0x9a, 0x1b, 0xf2, 0x42, 0x66, 0x2b, - 0x6e, 0x0b, 0xf2, 0x33, 0x9c, 0x1c, 0x7a, 0x29, 0x26, 0xe9, 0xd2, 0x01, 0x99, 0xfe, 0x76, 0xa5, 0xfd, 0x6f, 0x0b, - 0xef, 0x19, 0x7e, 0x0d, 0x61, 0xdd, 0x6f, 0xeb, 0xea, 0xab, 0xe1, 0xdc, 0x6f, 0x6b, 0x04, 0x7d, 0x1b, 0xac, 0xd4, - 0xb3, 0xc2, 0xb8, 0x3d, 0xff, 0xd0, 0xef, 0xb8, 0x46, 0x5b, 0xfa, 0x41, 0x05, 0x91, 0x54, 0xaa, 0xa5, 0xdc, 0x0f, - 0xb8, 0x4e, 0x54, 0x83, 0x84, 0xb9, 0xa6, 0x85, 0x44, 0x75, 0x8a, 0xa1, 0xd2, 0xe1, 0x37, 0x2d, 0x8f, 0x96, 0x31, - 0xb9, 0xb2, 0x33, 0xde, 0x85, 0x5c, 0x6c, 0xc3, 0x2e, 0x2b, 0x56, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0x0f, 0x1b, - 0xa2, 0x3e, 0x0b, 0x30, 0xe4, 0xea, 0x30, 0x90, 0xdd, 0x3f, 0x29, 0x8c, 0xee, 0xd6, 0xb4, 0x32, 0xde, 0x80, 0xfd, - 0x8f, 0x70, 0x64, 0x8e, 0xc8, 0x51, 0xcd, 0x81, 0x69, 0x30, 0x2f, 0x2b, 0xa7, 0x40, 0xa1, 0x94, 0xb7, 0x0c, 0xe1, - 0xa2, 0x94, 0xe1, 0xed, 0xbf, 0xe0, 0xbf, 0x6a, 0x96, 0x78, 0x51, 0x71, 0x9c, 0x17, 0x0f, 0xe5, 0x88, 0x0a, 0xfc, - 0x2a, 0x7a, 0x0f, 0x74, 0x2c, 0x29, 0xb4, 0x34, 0x54, 0xf4, 0x3c, 0xd7, 0x13, 0xd9, 0x98, 0x97, 0x8a, 0x69, 0x95, - 0x51, 0x23, 0x87, 0x59, 0x93, 0xc8, 0x69, 0xac, 0x6c, 0x51, 0xed, 0xaa, 0xc6, 0xb8, 0x68, 0x03, 0x16, 0xeb, 0xc0, - 0xe2, 0x62, 0xe1, 0x35, 0x51, 0x4d, 0x98, 0x15, 0xc7, 0x40, 0x98, 0x59, 0x09, 0x15, 0x0d, 0xcd, 0x5a, 0xb5, 0xf1, - 0xd0, 0x72, 0x3e, 0x91, 0xd1, 0xcd, 0x1b, 0x70, 0xd8, 0x2e, 0x04, 0xd5, 0xdc, 0xf6, 0x29, 0x60, 0x35, 0xbb, 0x6a, - 0x20, 0x0b, 0x43, 0x3f, 0x54, 0xb9, 0xb2, 0x75, 0x52, 0xeb, 0x1a, 0xfc, 0xa2, 0x7b, 0xb2, 0x65, 0x35, 0xea, 0x56, - 0xdf, 0x5b, 0xb9, 0x46, 0xcf, 0xf3, 0x4d, 0xb9, 0x46, 0x0d, 0x6d, 0x77, 0xab, 0x83, 0xee, 0xcf, 0x4b, 0x55, 0x63, - 0xad, 0xaf, 0xf2, 0x2b, 0x86, 0xeb, 0x02, 0x6d, 0x2a, 0x34, 0x1b, 0xae, 0x72, 0x52, 0x96, 0x17, 0xd5, 0x69, 0x02, - 0x99, 0xba, 0x73, 0xa1, 0xe8, 0x5f, 0x5b, 0x8d, 0xf2, 0x50, 0xae, 0xf7, 0x17, 0x32, 0x4e, 0xf3, 0xab, 0x30, 0xfd, - 0x00, 0xe3, 0xd5, 0x2f, 0x5f, 0xde, 0xc5, 0x3c, 0x14, 0x54, 0x73, 0x97, 0x1a, 0x86, 0xbf, 0x58, 0x30, 0xfc, 0x45, - 0xf1, 0xe9, 0xba, 0x3d, 0x9e, 0xbf, 0xaa, 0x3a, 0x08, 0x2e, 0x4a, 0xc3, 0x32, 0xee, 0xc4, 0xfa, 0x31, 0x96, 0x59, - 0xd8, 0x5d, 0xc5, 0xc2, 0xee, 0x84, 0xb7, 0xdc, 0x95, 0xe7, 0xfd, 0x75, 0x7d, 0x2f, 0xab, 0x9c, 0xed, 0xaf, 0xf5, - 0xc6, 0xff, 0x6b, 0x70, 0x6f, 0x1b, 0x8b, 0xcb, 0xed, 0xf9, 0x7b, 0x32, 0x59, 0x45, 0x81, 0xfc, 0x0a, 0x92, 0x0e, - 0x04, 0x19, 0x58, 0x87, 0x0e, 0x6a, 0x39, 0x65, 0xf2, 0x80, 0xbc, 0x68, 0x56, 0x88, 0x7c, 0xa2, 0xfb, 0x2c, 0xf4, - 0x49, 0x23, 0xf9, 0x12, 0x5c, 0xd1, 0x32, 0xd6, 0x1e, 0x34, 0xcf, 0x72, 0xcd, 0x3f, 0xb1, 0x2c, 0x0e, 0x38, 0xd6, - 0x52, 0xa4, 0x08, 0xf2, 0x92, 0x98, 0x6c, 0xe3, 0xd5, 0x77, 0x78, 0xc4, 0x32, 0x56, 0x24, 0x94, 0x7b, 0x05, 0x9a, - 0x6f, 0x1a, 0xac, 0x80, 0x80, 0x8c, 0x1a, 0x0c, 0xff, 0xa9, 0x3e, 0xf5, 0xe7, 0x43, 0x6f, 0xe0, 0x07, 0x9a, 0x50, - 0x91, 0xe4, 0x31, 0xa4, 0xa5, 0xf8, 0x71, 0x75, 0xa8, 0x69, 0x67, 0x67, 0xcb, 0x73, 0xa5, 0x5b, 0x02, 0x0e, 0x80, - 0xdb, 0x6f, 0xd0, 0x70, 0x0e, 0xe7, 0x73, 0xea, 0xa1, 0x29, 0x9a, 0xd3, 0xe5, 0xa3, 0x2c, 0xc2, 0xff, 0x44, 0xef, - 0x70, 0x86, 0xca, 0x32, 0x50, 0x50, 0xbb, 0x23, 0x46, 0xd3, 0xd8, 0xc5, 0x9f, 0xe8, 0x5d, 0x50, 0x9d, 0x19, 0x97, - 0x47, 0x9c, 0xe5, 0x02, 0xba, 0xf9, 0x4d, 0xe6, 0xe2, 0x7a, 0x90, 0x60, 0x5e, 0xe2, 0x9c, 0xb3, 0x31, 0x10, 0xe7, - 0xb7, 0xf4, 0x2e, 0x50, 0xfd, 0x31, 0xeb, 0xbc, 0x1e, 0x9a, 0x1b, 0xd4, 0xfb, 0x56, 0xb1, 0xbd, 0x0c, 0xda, 0xa0, - 0x38, 0x93, 0x6d, 0xcf, 0x49, 0xa3, 0x5e, 0x6d, 0x1e, 0x22, 0x54, 0x3e, 0x74, 0x2a, 0xf8, 0x5b, 0x5b, 0xb4, 0x89, - 0x46, 0xe6, 0xeb, 0x52, 0x23, 0x0a, 0x0d, 0xea, 0x4c, 0x8f, 0x6d, 0x2f, 0x33, 0xbb, 0x4e, 0x1f, 0x42, 0xb0, 0x1c, - 0x61, 0xdf, 0x0a, 0xdd, 0x69, 0xf0, 0x27, 0x95, 0x10, 0x52, 0x47, 0x92, 0xbe, 0xa9, 0xdb, 0x39, 0xdb, 0x1e, 0xe0, - 0x1d, 0x12, 0x5a, 0x42, 0x79, 0x26, 0xb3, 0x34, 0xd9, 0xa2, 0x7f, 0x16, 0xc4, 0x9b, 0x9b, 0x29, 0x04, 0x99, 0x8d, - 0x45, 0x51, 0x02, 0x15, 0x6a, 0xfa, 0x52, 0x09, 0x80, 0x6c, 0xe4, 0xb1, 0x15, 0xa9, 0x99, 0x4b, 0xa9, 0xe9, 0x5b, - 0x18, 0xdf, 0x20, 0x25, 0xa9, 0x44, 0x86, 0x54, 0x22, 0xa5, 0xd0, 0xd3, 0x8b, 0xab, 0x49, 0xc8, 0x5e, 0xd0, 0xea, - 0x04, 0x9d, 0x5a, 0xf3, 0xbc, 0x01, 0x96, 0x27, 0xfb, 0x41, 0x65, 0x00, 0x53, 0xa2, 0xaa, 0x42, 0x59, 0x1d, 0xcd, - 0x36, 0xe9, 0xad, 0x9e, 0x3c, 0xeb, 0x24, 0xa7, 0x45, 0x0c, 0x4a, 0xbc, 0x08, 0xcd, 0x33, 0x2f, 0xc2, 0x39, 0xa4, - 0x23, 0x16, 0x65, 0x05, 0x3f, 0xb5, 0x57, 0xa3, 0x91, 0xac, 0xbc, 0xfe, 0x94, 0x1f, 0x28, 0xf3, 0x02, 0x52, 0x34, - 0x71, 0x66, 0x78, 0x4a, 0xe6, 0xc9, 0xe3, 0x76, 0xd6, 0xb2, 0xfd, 0x45, 0x27, 0xe8, 0x68, 0xc0, 0xfe, 0x2c, 0xbc, - 0xb9, 0x35, 0x0b, 0xfb, 0x44, 0xb7, 0x3e, 0xf5, 0xa7, 0x83, 0x7d, 0x75, 0x0e, 0xa9, 0xc7, 0xc9, 0x92, 0xc4, 0xb9, - 0x3f, 0xd5, 0xf2, 0xe7, 0x19, 0xe5, 0x77, 0xa7, 0x14, 0x52, 0x9d, 0x73, 0x38, 0xf0, 0x5b, 0x2f, 0x43, 0x9d, 0xa7, - 0x3e, 0xcc, 0xa5, 0xb2, 0x52, 0x36, 0xcf, 0x01, 0x2e, 0x9f, 0x12, 0x2c, 0x65, 0xb4, 0xd1, 0x72, 0xc4, 0xa8, 0xdd, - 0x42, 0x37, 0x9e, 0x9f, 0xa4, 0x7d, 0x06, 0xfe, 0xb5, 0x1a, 0xd3, 0x3a, 0x58, 0x80, 0x0b, 0xfb, 0x4c, 0xea, 0x19, - 0x3f, 0x5f, 0xf6, 0xca, 0x40, 0x11, 0x84, 0xef, 0xf2, 0xcd, 0x53, 0x5d, 0x97, 0x34, 0xbb, 0x79, 0xaa, 0x8d, 0xa0, - 0x9f, 0x4c, 0xf8, 0xc1, 0x7a, 0x9c, 0xea, 0x04, 0x33, 0x2b, 0x4b, 0x54, 0x02, 0x78, 0x7f, 0xec, 0x7b, 0xde, 0x1f, - 0x75, 0xca, 0xa0, 0x0f, 0xb1, 0xd8, 0xd3, 0x34, 0x37, 0x4c, 0xbc, 0x1e, 0xff, 0x8f, 0x2b, 0xe3, 0xff, 0xd1, 0x3a, - 0x75, 0x0a, 0xa6, 0xd1, 0x38, 0xa3, 0xb1, 0x61, 0x9d, 0x48, 0x11, 0xa0, 0xd4, 0xdb, 0x0a, 0x41, 0x3e, 0x5d, 0x06, - 0xa0, 0x71, 0xcd, 0x47, 0x79, 0x26, 0x5a, 0xa3, 0x70, 0xc2, 0xd2, 0xbb, 0x60, 0xc6, 0x5a, 0x93, 0x3c, 0xcb, 0x8b, - 0x69, 0x18, 0x51, 0x5c, 0xdc, 0x15, 0x82, 0x4e, 0x5a, 0x33, 0x86, 0x5f, 0xd2, 0xf4, 0x9a, 0x0a, 0x16, 0x85, 0xd8, - 0x3d, 0xe6, 0x2c, 0x4c, 0x9d, 0x37, 0x21, 0xe7, 0xf9, 0x8d, 0x8b, 0xdf, 0xe7, 0x57, 0xb9, 0xc8, 0xf1, 0xdb, 0xdb, - 0xbb, 0x31, 0xcd, 0xf0, 0xc7, 0xab, 0x59, 0x26, 0x66, 0xb8, 0x08, 0xb3, 0xa2, 0x55, 0x50, 0xce, 0x46, 0xfd, 0x28, - 0x4f, 0x73, 0xde, 0x82, 0x8c, 0xed, 0x09, 0x0d, 0x52, 0x36, 0x4e, 0x84, 0x13, 0x87, 0xfc, 0x53, 0xbf, 0xd5, 0x9a, - 0x72, 0x36, 0x09, 0xf9, 0x5d, 0x4b, 0xd6, 0x08, 0xbe, 0xea, 0xec, 0x85, 0x4f, 0x47, 0xfb, 0x7d, 0xc1, 0xc3, 0xac, - 0x60, 0xb0, 0x4c, 0x41, 0x98, 0xa6, 0xce, 0xde, 0x41, 0x67, 0x52, 0x6c, 0xa9, 0x40, 0x5e, 0x98, 0x89, 0xf2, 0x12, - 0x7f, 0x00, 0xb8, 0xfd, 0x2b, 0x91, 0xe1, 0xab, 0x99, 0x10, 0x79, 0x36, 0x8f, 0x66, 0xbc, 0xc8, 0x79, 0x30, 0xcd, - 0x59, 0x26, 0x28, 0xef, 0x5f, 0xe5, 0x3c, 0xa6, 0xbc, 0xc5, 0xc3, 0x98, 0xcd, 0x8a, 0x60, 0x7f, 0x7a, 0xdb, 0x07, - 0xcd, 0x62, 0xcc, 0xf3, 0x59, 0x16, 0xeb, 0xb1, 0x58, 0x96, 0x50, 0xce, 0x84, 0xfd, 0x42, 0x5e, 0x64, 0x12, 0xa4, - 0x2c, 0xa3, 0x21, 0x6f, 0x8d, 0xa1, 0x31, 0x98, 0x45, 0x9d, 0x98, 0x8e, 0x31, 0x1f, 0x5f, 0x85, 0x5e, 0xb7, 0xf7, - 0x04, 0x9b, 0xff, 0xfd, 0x03, 0xe4, 0x74, 0xd6, 0x17, 0x77, 0x3b, 0x9d, 0x7f, 0x42, 0xfd, 0xa5, 0x51, 0x24, 0x40, - 0x41, 0x77, 0x7a, 0xeb, 0x14, 0x39, 0x64, 0xb4, 0xad, 0x6b, 0xd9, 0x9f, 0x86, 0x31, 0xe4, 0x03, 0x07, 0xbd, 0xe9, - 0x6d, 0x09, 0xb3, 0x0b, 0x54, 0x8a, 0xa9, 0x9e, 0xa4, 0x7e, 0x9a, 0xff, 0x5a, 0x88, 0x0f, 0xd7, 0x43, 0xdc, 0x33, - 0x10, 0xd7, 0x58, 0x6f, 0xc5, 0x33, 0x2e, 0x63, 0xab, 0x41, 0xb7, 0x50, 0x80, 0x24, 0xf9, 0x35, 0xe5, 0x06, 0x0e, - 0xf9, 0xf0, 0xab, 0xc1, 0xe8, 0xad, 0x07, 0xe3, 0xf0, 0x73, 0x60, 0xf0, 0x2c, 0x9e, 0x37, 0xd7, 0xb5, 0xcb, 0xe9, - 0xa4, 0x9f, 0x50, 0xa0, 0xa7, 0xa0, 0x07, 0xbf, 0x6f, 0x58, 0x2c, 0x12, 0xf5, 0x53, 0x92, 0xf3, 0x8d, 0x7a, 0x77, - 0xd0, 0xe9, 0xa8, 0xe7, 0x82, 0xfd, 0x42, 0x83, 0xae, 0x0f, 0x15, 0xca, 0x4b, 0xfc, 0xd7, 0xea, 0x34, 0x6f, 0x93, - 0x7b, 0xe2, 0x3f, 0xda, 0xc7, 0x7c, 0xad, 0x14, 0xc5, 0xfa, 0x50, 0x34, 0xce, 0x8d, 0xac, 0x54, 0xc2, 0x07, 0xdc, - 0x76, 0x92, 0x3b, 0x12, 0x36, 0xa8, 0x8e, 0x71, 0xb2, 0xe1, 0x1f, 0x55, 0xde, 0x45, 0x00, 0x91, 0x0e, 0x2b, 0xd5, - 0xb0, 0xe8, 0xe7, 0x03, 0xd2, 0xe9, 0xe7, 0xad, 0x16, 0xf2, 0x0a, 0x92, 0x9d, 0xe5, 0x3a, 0x39, 0xcf, 0x63, 0xc3, - 0x42, 0x1a, 0xdb, 0x1c, 0x05, 0x05, 0x9c, 0x35, 0x5d, 0x2c, 0x78, 0x9d, 0x90, 0x21, 0x4f, 0x6b, 0xfc, 0x55, 0xe8, - 0x0a, 0x98, 0x5b, 0x9c, 0x3c, 0x34, 0xd7, 0xbb, 0x64, 0x86, 0x57, 0xa4, 0x79, 0x24, 0x31, 0xe7, 0x4f, 0x43, 0x91, - 0x80, 0x97, 0xa2, 0x12, 0x3f, 0x75, 0x0a, 0x93, 0xdb, 0x76, 0xd1, 0x30, 0xab, 0xf2, 0xdb, 0x20, 0x8f, 0x2f, 0x2b, - 0xa1, 0x97, 0x2b, 0x41, 0xa0, 0xc7, 0xba, 0xff, 0x8f, 0xc2, 0x92, 0xd4, 0x99, 0xcf, 0xb2, 0x28, 0x9d, 0xc5, 0xb4, - 0x90, 0x3d, 0xd4, 0xe2, 0x1c, 0xee, 0x86, 0xa8, 0x6a, 0xc9, 0x26, 0xd0, 0xbb, 0xcc, 0xe6, 0x81, 0x8a, 0x70, 0x8b, - 0x4a, 0xf5, 0xdc, 0x92, 0xcf, 0x75, 0xdb, 0x37, 0x75, 0xb2, 0x28, 0xb4, 0xf4, 0x67, 0x19, 0xfb, 0x79, 0x46, 0x2f, - 0x58, 0x6c, 0x9d, 0xdc, 0xa5, 0x59, 0x94, 0xc7, 0xf4, 0xe3, 0xfb, 0x6f, 0x20, 0xdb, 0x3d, 0xcf, 0x80, 0xc4, 0x32, - 0xe5, 0xef, 0xc2, 0x9c, 0x64, 0x7e, 0x4c, 0xaf, 0x59, 0x44, 0x87, 0x97, 0xdb, 0xf3, 0xb5, 0x15, 0xd5, 0x6b, 0x54, - 0xb6, 0x2f, 0xc1, 0x7f, 0xa7, 0xa0, 0xbc, 0xdc, 0x9e, 0x5f, 0x89, 0xb2, 0xbd, 0x3d, 0xcf, 0xfc, 0x38, 0x9f, 0x84, - 0x2c, 0x83, 0xdf, 0xbc, 0xdc, 0x9e, 0x33, 0xf8, 0x21, 0xca, 0xcb, 0xb2, 0x4e, 0x14, 0xad, 0x20, 0xb2, 0xa6, 0xa0, - 0x71, 0xd7, 0x45, 0xfe, 0x4f, 0x39, 0xcb, 0x64, 0xd1, 0x7d, 0x3d, 0x53, 0xd3, 0x2b, 0x20, 0xf9, 0x17, 0xa2, 0x0c, - 0x66, 0x63, 0x2e, 0x5f, 0x3c, 0xd4, 0x5c, 0xa6, 0x99, 0x60, 0x32, 0x2d, 0xde, 0x84, 0x73, 0x92, 0xb0, 0xb8, 0x88, - 0xd4, 0x49, 0xd4, 0xa2, 0x3e, 0x75, 0x11, 0x4a, 0xc4, 0x2a, 0x0b, 0x98, 0x72, 0x69, 0xec, 0xd3, 0xcd, 0x47, 0x25, - 0xb3, 0xfb, 0x8c, 0xbf, 0x8a, 0xaa, 0x8a, 0x7c, 0xc6, 0x23, 0x88, 0xf5, 0x6a, 0x95, 0x62, 0xd5, 0x2b, 0xe6, 0x4a, - 0xfd, 0xcd, 0xc5, 0xc2, 0x4a, 0xb2, 0x15, 0x70, 0xa6, 0xaf, 0xbe, 0xb6, 0x83, 0xca, 0x78, 0xa2, 0x3a, 0x0b, 0xa3, - 0xf5, 0x07, 0x33, 0x25, 0x50, 0x88, 0x62, 0x99, 0x2f, 0xea, 0xe5, 0x64, 0x90, 0xd7, 0x38, 0x27, 0x84, 0x30, 0x9f, - 0xc5, 0x32, 0x90, 0x07, 0x8a, 0x45, 0xab, 0x0b, 0x91, 0x21, 0x16, 0xd7, 0x1a, 0x1e, 0xd3, 0x78, 0x5e, 0x2c, 0xe0, - 0x6c, 0x8a, 0xac, 0xab, 0x9c, 0x2a, 0xa0, 0x83, 0x31, 0xac, 0x5e, 0x06, 0x39, 0xae, 0xba, 0x0c, 0xa0, 0x52, 0xd9, - 0x57, 0xe8, 0x53, 0xc8, 0x22, 0x06, 0x9d, 0xc7, 0x4a, 0x45, 0x28, 0x10, 0xb6, 0x5f, 0x57, 0x47, 0xf8, 0x1b, 0xf8, - 0xee, 0x2c, 0x2d, 0x8b, 0xb2, 0xa7, 0x96, 0x17, 0xcb, 0x2f, 0x72, 0x2e, 0x3c, 0x2f, 0xc2, 0x21, 0x22, 0x83, 0x48, - 0x52, 0xed, 0x51, 0x28, 0xff, 0x19, 0xb6, 0xba, 0x41, 0xb7, 0xf2, 0x84, 0x34, 0x4e, 0x56, 0xab, 0x3c, 0x33, 0x7d, - 0x3a, 0x17, 0xc0, 0xc5, 0xd5, 0x6f, 0x35, 0x9f, 0xfa, 0xb9, 0x9a, 0x16, 0xd6, 0x9c, 0x4b, 0x49, 0x7d, 0xaf, 0x01, - 0x84, 0x8c, 0xbb, 0x6d, 0x18, 0x0a, 0x95, 0xf5, 0xbc, 0xab, 0x5d, 0x7c, 0xa9, 0xb4, 0x9d, 0x0b, 0x8b, 0x8c, 0x2f, - 0x99, 0xf1, 0xd7, 0x35, 0x09, 0xac, 0xd4, 0x18, 0xb1, 0x58, 0xc0, 0xba, 0x6a, 0x0a, 0x96, 0x3b, 0x92, 0xad, 0xa5, - 0x52, 0x5f, 0x3d, 0x52, 0x45, 0x16, 0xeb, 0xab, 0xc8, 0xac, 0xc7, 0x75, 0x80, 0x81, 0x07, 0xa0, 0x10, 0x66, 0x0a, - 0xc0, 0x4c, 0x46, 0x14, 0x8e, 0x24, 0x69, 0xd6, 0x82, 0xe7, 0x4a, 0x8d, 0x0f, 0xdc, 0x77, 0x6f, 0x4f, 0x3f, 0xb8, - 0x18, 0xee, 0x34, 0xa3, 0xbc, 0x08, 0xe6, 0xae, 0x4e, 0x26, 0x6c, 0x41, 0x60, 0xda, 0x0d, 0xdc, 0x70, 0x0a, 0xa7, - 0xb3, 0x25, 0xf7, 0x6c, 0xdf, 0xb6, 0x6e, 0x6e, 0x6e, 0x5a, 0x70, 0x74, 0xac, 0x35, 0xe3, 0xa9, 0xe2, 0x2b, 0xb1, - 0x5b, 0x96, 0xc8, 0x17, 0x09, 0xcd, 0xaa, 0x5b, 0x8f, 0xf2, 0x94, 0xfa, 0x69, 0x3e, 0x56, 0x07, 0x5f, 0x97, 0xfd, - 0x10, 0xe9, 0xe5, 0x91, 0xbc, 0xcd, 0x6b, 0x70, 0x24, 0xd4, 0x3d, 0x6a, 0x82, 0xc3, 0xcf, 0x01, 0x44, 0xa9, 0x8e, - 0xda, 0x22, 0x91, 0x0f, 0xa7, 0xb0, 0x6d, 0xe4, 0xd3, 0xf6, 0x7c, 0x85, 0xc8, 0x86, 0xd0, 0x45, 0x32, 0x50, 0x53, - 0x2b, 0x64, 0xad, 0xcb, 0x20, 0xbd, 0xbc, 0x2c, 0x8f, 0xda, 0xd0, 0x57, 0xdb, 0xf4, 0x7b, 0x95, 0xc7, 0x77, 0xa6, - 0x7d, 0x45, 0x78, 0x70, 0xab, 0x53, 0x46, 0x06, 0xd0, 0x05, 0x8c, 0x1b, 0x0f, 0x24, 0xce, 0x34, 0xaf, 0x3c, 0xab, - 0x1f, 0xca, 0x73, 0x07, 0x38, 0x63, 0x09, 0x25, 0x40, 0x97, 0xd0, 0x79, 0x5c, 0x35, 0x90, 0xdb, 0x5a, 0x15, 0x6d, - 0x02, 0x50, 0x55, 0xac, 0xb7, 0x8b, 0xf2, 0x67, 0xd7, 0x64, 0x61, 0x20, 0x8e, 0x6d, 0xe0, 0x2f, 0x11, 0xfc, 0x2b, - 0x01, 0x3f, 0x6a, 0x2b, 0x34, 0x5d, 0xda, 0xf7, 0xcb, 0xa8, 0x9b, 0x1f, 0x2a, 0x64, 0x9e, 0x15, 0x02, 0x7f, 0x10, - 0xf8, 0xd3, 0xa5, 0xac, 0x6a, 0xd4, 0x01, 0xd0, 0x53, 0x41, 0x6d, 0xea, 0x18, 0xbd, 0x2f, 0xca, 0xd3, 0x34, 0x9c, - 0x16, 0x34, 0x30, 0x3f, 0xb4, 0x66, 0x00, 0x0a, 0xc6, 0xaa, 0x2a, 0xa6, 0x13, 0x9c, 0x4e, 0x40, 0x61, 0x5b, 0xd5, - 0x13, 0xaf, 0x43, 0xee, 0xb5, 0x5a, 0x51, 0xeb, 0x6a, 0x8c, 0x4a, 0x91, 0xcc, 0x6d, 0xbd, 0xe2, 0x71, 0xa7, 0xd3, - 0x87, 0x6c, 0xd4, 0x56, 0x98, 0xb2, 0x71, 0x16, 0xa4, 0x74, 0x24, 0x4a, 0x01, 0xc7, 0x04, 0xe7, 0x46, 0x91, 0xf3, - 0x7b, 0x07, 0x9c, 0x4e, 0x1c, 0x1f, 0xfe, 0xde, 0x3f, 0x70, 0x29, 0xe2, 0x20, 0x13, 0x49, 0x4b, 0x66, 0x3d, 0xc3, - 0x99, 0x0d, 0x91, 0x34, 0x9e, 0xe7, 0xd6, 0x40, 0x11, 0x05, 0x25, 0xb7, 0x14, 0xdc, 0x11, 0x09, 0x16, 0xdc, 0xae, - 0x97, 0xa1, 0xf9, 0xca, 0x0c, 0x56, 0x75, 0xad, 0x3d, 0x54, 0x16, 0xd2, 0x34, 0x59, 0xad, 0x6c, 0x14, 0xd6, 0xe6, - 0xd3, 0x0a, 0xfa, 0x2c, 0xd5, 0xba, 0x54, 0xae, 0xfd, 0xb9, 0x6a, 0xf1, 0x10, 0x64, 0x36, 0x94, 0x7e, 0x6c, 0xb7, - 0x40, 0x25, 0xcb, 0xa6, 0x33, 0x71, 0x26, 0xc3, 0x0a, 0x1c, 0x0e, 0xa8, 0x9c, 0x63, 0xab, 0x04, 0x70, 0x70, 0x3e, - 0x57, 0xc0, 0x44, 0x61, 0x1a, 0x79, 0x00, 0x91, 0xd3, 0x72, 0x0e, 0x39, 0x9d, 0xa0, 0xfe, 0x84, 0x65, 0x2d, 0xf5, - 0xee, 0xc0, 0x52, 0x0c, 0xfd, 0x27, 0xf0, 0x54, 0xfa, 0xb2, 0x37, 0x2c, 0xb3, 0x87, 0xd7, 0xe0, 0xf2, 0xf2, 0xbc, - 0x2c, 0xfb, 0xb9, 0xf0, 0xce, 0xbe, 0xf1, 0xd0, 0x39, 0xfe, 0xc5, 0xba, 0x21, 0xc7, 0x35, 0x3b, 0xc9, 0xc5, 0x3d, - 0xb4, 0xa1, 0x8a, 0xbd, 0x17, 0x64, 0xb5, 0x5f, 0x08, 0x54, 0x7c, 0xe5, 0xb9, 0xb4, 0x98, 0xb6, 0x14, 0xcb, 0x6b, - 0x49, 0x92, 0x75, 0xa1, 0x29, 0xd2, 0xbe, 0x72, 0x4a, 0xe7, 0x92, 0x9b, 0xe9, 0x43, 0x32, 0xca, 0x9d, 0x73, 0x5e, - 0x1d, 0xaa, 0xd2, 0xcf, 0xf6, 0x31, 0x2a, 0xd4, 0x60, 0x37, 0x97, 0xc7, 0x4d, 0xd6, 0x08, 0xca, 0x45, 0x75, 0x91, - 0x60, 0x98, 0xa6, 0x30, 0xe0, 0xa5, 0xd1, 0x48, 0xec, 0x7b, 0x57, 0xce, 0xc4, 0xb9, 0x87, 0x4a, 0xbd, 0x4f, 0x9f, - 0x49, 0xa5, 0xde, 0xba, 0xbd, 0x70, 0x4b, 0x98, 0x70, 0x9d, 0x12, 0xd1, 0x0c, 0x12, 0x0e, 0x1a, 0x89, 0xe9, 0xfd, - 0x9a, 0xb5, 0x29, 0x93, 0xc0, 0x91, 0x13, 0x22, 0x2e, 0xcf, 0x62, 0xd7, 0xf9, 0x43, 0x94, 0xb2, 0xe8, 0x13, 0x71, - 0xb7, 0xe7, 0x1e, 0x5a, 0x3d, 0x77, 0x2a, 0xb9, 0x82, 0xe1, 0xf3, 0xa8, 0x19, 0xca, 0xc8, 0x7d, 0x8b, 0x85, 0xab, - 0xab, 0x89, 0xdc, 0x01, 0xe8, 0x4d, 0x47, 0x6d, 0x35, 0xce, 0xe0, 0xb2, 0xbc, 0xa8, 0xaf, 0x1c, 0xab, 0xa1, 0x00, - 0x34, 0xab, 0x72, 0x47, 0x12, 0x15, 0x71, 0x3f, 0x4b, 0x69, 0xae, 0xa3, 0x98, 0x1a, 0xc0, 0x29, 0x34, 0x7f, 0x73, - 0x9d, 0x3f, 0x54, 0x65, 0xb4, 0xf2, 0x29, 0xc9, 0xa4, 0x18, 0xe2, 0xc2, 0x58, 0xe0, 0x48, 0xf0, 0x63, 0x2a, 0x42, - 0x96, 0xaa, 0x26, 0x7d, 0xe3, 0x02, 0x59, 0x9a, 0xd1, 0x62, 0xc1, 0x9b, 0x73, 0x61, 0x4d, 0x0c, 0xca, 0x99, 0x1d, - 0xb5, 0x6b, 0xb8, 0xe5, 0xcc, 0xe4, 0x9e, 0xb4, 0x83, 0xb3, 0xf5, 0x0c, 0xd5, 0x3b, 0xe7, 0x0f, 0x91, 0x3c, 0xb6, - 0x05, 0x00, 0x16, 0x1a, 0x40, 0x48, 0x1b, 0x50, 0xc7, 0x92, 0xbc, 0x90, 0x14, 0xbe, 0x08, 0xf9, 0x98, 0x8a, 0x25, - 0xc4, 0x86, 0x2a, 0x4b, 0xb8, 0x6f, 0x52, 0x04, 0x56, 0xa0, 0x4d, 0x9a, 0xd0, 0x82, 0x12, 0x5d, 0x0e, 0x41, 0x0f, - 0x26, 0x6b, 0xd5, 0xe9, 0x08, 0x81, 0xbc, 0x95, 0x8b, 0xc3, 0xa5, 0x84, 0x29, 0xa4, 0x84, 0x51, 0x9c, 0xc0, 0x91, - 0x63, 0x49, 0x10, 0x4b, 0xd7, 0x19, 0x2a, 0xc8, 0x69, 0xac, 0x60, 0x26, 0xb9, 0x6c, 0x55, 0x94, 0x47, 0x6d, 0x55, - 0x5b, 0x89, 0x00, 0x55, 0x09, 0x90, 0x20, 0xf7, 0x69, 0x8d, 0x03, 0xc8, 0x2c, 0xb7, 0xf1, 0x10, 0xb3, 0xeb, 0x8a, - 0xd8, 0xe4, 0x01, 0xb6, 0xc1, 0x51, 0x1a, 0x5e, 0xd1, 0x74, 0xb0, 0x3d, 0xcf, 0x17, 0x8b, 0x4e, 0x79, 0xd4, 0x56, - 0x8f, 0xce, 0x91, 0xe4, 0x1b, 0xea, 0xe2, 0x51, 0xb9, 0xc4, 0x70, 0x2a, 0x14, 0xf2, 0x6d, 0x4d, 0xa2, 0x59, 0xa0, - 0x3b, 0x28, 0x5d, 0x47, 0xa6, 0xb8, 0xc8, 0x4a, 0x95, 0x1e, 0x55, 0xba, 0x0e, 0x8b, 0x57, 0xcb, 0x0a, 0x41, 0xa7, - 0x50, 0x1a, 0x2d, 0x16, 0xdd, 0xd2, 0x75, 0x26, 0x2c, 0x83, 0xa7, 0x7c, 0xb1, 0x90, 0x07, 0x2e, 0x27, 0x2c, 0xf3, - 0x3a, 0x40, 0xb6, 0xae, 0x33, 0x09, 0x6f, 0xe5, 0x84, 0xcd, 0x9b, 0xf0, 0xd6, 0xeb, 0xea, 0x57, 0x7e, 0x85, 0x1f, - 0x0e, 0x14, 0x57, 0xaf, 0x68, 0xa8, 0x57, 0x34, 0xc6, 0x33, 0x75, 0x94, 0x8c, 0x78, 0x31, 0x09, 0xd7, 0xaf, 0x68, - 0x6c, 0x56, 0x74, 0xb6, 0x61, 0x45, 0x67, 0xf7, 0xac, 0x68, 0xa2, 0x57, 0xcf, 0xa9, 0x70, 0x57, 0x2c, 0x16, 0xdd, - 0x4e, 0x8d, 0xbd, 0xa3, 0x76, 0xcc, 0xae, 0x61, 0x35, 0x40, 0x3b, 0x14, 0x6c, 0x42, 0xd7, 0x13, 0x65, 0x13, 0xc5, - 0xf4, 0x8b, 0x30, 0x59, 0x63, 0x21, 0x6f, 0x62, 0xc1, 0xa6, 0xeb, 0x2a, 0xea, 0xf9, 0x5b, 0x52, 0x36, 0x03, 0x3c, - 0x70, 0xc0, 0x43, 0x64, 0x2e, 0x22, 0xf5, 0xdc, 0x0f, 0x2e, 0x76, 0x1d, 0xd7, 0x90, 0xf5, 0x65, 0x79, 0x01, 0x32, - 0x42, 0xce, 0xef, 0x41, 0xb4, 0x08, 0xb5, 0xdd, 0xc1, 0x66, 0x9a, 0x83, 0x04, 0x85, 0x9b, 0x9c, 0xc7, 0x6e, 0xa0, - 0xaa, 0x7e, 0x11, 0xaa, 0x26, 0x2c, 0xd3, 0xe9, 0x6e, 0x1b, 0x69, 0xad, 0x7e, 0x6f, 0x53, 0x5c, 0xef, 0xe0, 0x40, - 0xd5, 0x98, 0x86, 0x42, 0x50, 0x9e, 0x69, 0xca, 0x75, 0xdd, 0x7f, 0x17, 0x54, 0xb8, 0x86, 0xaf, 0x24, 0x66, 0x01, - 0x0c, 0x01, 0x6a, 0x3d, 0x5f, 0xf3, 0x7c, 0x25, 0x9e, 0xb6, 0x6a, 0x05, 0xf7, 0x0e, 0xd9, 0xb6, 0x86, 0x2a, 0x02, - 0xd3, 0x67, 0x36, 0xa1, 0xf1, 0x85, 0x64, 0xd0, 0xc3, 0xf4, 0x52, 0x2b, 0xac, 0x4b, 0xe2, 0xae, 0x6e, 0x80, 0xdd, - 0x1f, 0x67, 0xbd, 0x27, 0xfb, 0x27, 0x2e, 0x56, 0x3c, 0x3e, 0x1f, 0x8d, 0x5c, 0x54, 0x3a, 0x0f, 0x6b, 0xd6, 0xdd, - 0xff, 0x71, 0xf6, 0xf5, 0x8b, 0xce, 0xd7, 0x55, 0xe3, 0x0c, 0x88, 0x48, 0x67, 0x58, 0x18, 0x51, 0x65, 0xc1, 0x6b, - 0x66, 0x34, 0x0a, 0xb3, 0xcd, 0xd3, 0x39, 0xb3, 0xa7, 0x53, 0x4c, 0x29, 0x8d, 0x81, 0x38, 0xf1, 0x4a, 0xe9, 0x45, - 0x4a, 0xaf, 0xa9, 0xb9, 0xfe, 0x71, 0xcd, 0x60, 0x6b, 0x5a, 0x44, 0xf9, 0x2c, 0x13, 0x3a, 0xd5, 0x44, 0xb3, 0x5a, - 0x6b, 0x4a, 0x97, 0x72, 0x0e, 0xb6, 0x09, 0x71, 0xa7, 0xe4, 0x5c, 0x53, 0x7a, 0x95, 0x97, 0xd8, 0xb5, 0x00, 0xd8, - 0x08, 0xd9, 0x70, 0x43, 0x79, 0xd0, 0xc1, 0x9d, 0x4d, 0xb0, 0xe1, 0x2e, 0x0a, 0x5c, 0xf7, 0xdc, 0xe0, 0x49, 0x7a, - 0x8b, 0x1b, 0x37, 0x76, 0x6c, 0xc4, 0xd7, 0x67, 0x31, 0x70, 0xc5, 0xa1, 0xb3, 0x8c, 0x16, 0xc5, 0x46, 0x04, 0x54, - 0x8b, 0x88, 0xdd, 0xba, 0xb6, 0xbb, 0xa1, 0x17, 0xdc, 0xc1, 0xb0, 0xc3, 0x24, 0xc0, 0x55, 0xcc, 0x5a, 0xd7, 0xa2, - 0xa3, 0x11, 0x8d, 0x2a, 0x67, 0x3b, 0x44, 0x1f, 0x47, 0x2c, 0x15, 0x10, 0x84, 0x93, 0xd1, 0x31, 0xf7, 0x4d, 0x9e, - 0x51, 0x17, 0x99, 0x7c, 0x5a, 0x0d, 0xbf, 0x96, 0xff, 0xeb, 0xe1, 0x51, 0x3d, 0x36, 0x61, 0xd1, 0xa3, 0x2c, 0x16, - 0xc6, 0x17, 0xd4, 0x28, 0x6f, 0x22, 0x32, 0x97, 0xce, 0x9e, 0x4d, 0x1b, 0xe8, 0x61, 0xdb, 0x64, 0xde, 0xfd, 0xfa, - 0xa0, 0xdb, 0x29, 0x5d, 0xec, 0x42, 0x77, 0x0f, 0xdd, 0x25, 0xb2, 0xd5, 0x1e, 0xb4, 0x9a, 0x65, 0x5f, 0xd2, 0xae, - 0xd7, 0x7d, 0xda, 0x75, 0xb1, 0xba, 0xc8, 0x01, 0x95, 0x15, 0x33, 0x88, 0xc0, 0xfd, 0xfc, 0x77, 0x4f, 0xa5, 0xd9, - 0xf9, 0xc3, 0xe0, 0x79, 0xdc, 0xed, 0xb8, 0xd8, 0x2d, 0x44, 0x3e, 0xfd, 0x82, 0x29, 0xec, 0xb9, 0xd8, 0x8d, 0xd2, - 0xbc, 0xa0, 0xf6, 0x1c, 0x94, 0x3a, 0xfb, 0xf7, 0x4f, 0x42, 0x41, 0x34, 0xe5, 0xb4, 0x28, 0x1c, 0xbb, 0x7f, 0x4d, - 0x4a, 0x9f, 0x61, 0x98, 0x6b, 0x29, 0xae, 0xa0, 0x42, 0xe2, 0x45, 0xdd, 0xb1, 0x60, 0x53, 0x95, 0x2a, 0x5b, 0x21, - 0x36, 0x29, 0x02, 0x2a, 0xc6, 0xa6, 0xb4, 0xab, 0xcf, 0x8e, 0xbc, 0x66, 0xeb, 0xa9, 0x81, 0x55, 0x54, 0x7e, 0x75, - 0x80, 0x46, 0xc9, 0x84, 0x65, 0x17, 0x6b, 0x4a, 0xc3, 0xdb, 0x35, 0xa5, 0xa0, 0xb2, 0x55, 0xd0, 0xe9, 0xfb, 0x7f, - 0x3e, 0x8f, 0xf5, 0x5a, 0xf1, 0xb1, 0x41, 0x8c, 0xa5, 0x73, 0xf3, 0x33, 0x90, 0x5a, 0xcb, 0x20, 0x7b, 0xf8, 0xf5, - 0xc3, 0x41, 0xc9, 0x97, 0x0c, 0x57, 0xf5, 0xf2, 0xf7, 0xcd, 0x10, 0x4a, 0x5b, 0x10, 0x41, 0x48, 0xbf, 0x68, 0xae, - 0xf4, 0xf6, 0xf3, 0x04, 0x67, 0x69, 0x55, 0x7f, 0xc7, 0xd2, 0xeb, 0x7b, 0x04, 0x96, 0xd7, 0x7e, 0x4d, 0xb1, 0x56, - 0x7c, 0xaa, 0xf5, 0x8f, 0x52, 0x36, 0xa9, 0x49, 0x60, 0x15, 0x4c, 0xa9, 0xf1, 0x40, 0x3a, 0x99, 0xdd, 0x89, 0x52, - 0x7d, 0x2e, 0xe0, 0x90, 0x2c, 0xdc, 0x43, 0x32, 0xe3, 0xf4, 0x22, 0xcd, 0x6f, 0x96, 0x6f, 0x56, 0xdb, 0x5c, 0x39, - 0x61, 0xe3, 0xc4, 0x3a, 0xf9, 0x46, 0x49, 0xb5, 0x08, 0xf7, 0x0e, 0x50, 0xfe, 0xeb, 0xbf, 0xf8, 0xfe, 0xbf, 0xfe, - 0xcb, 0x67, 0xab, 0x42, 0xf7, 0xe5, 0x25, 0x16, 0x75, 0xb7, 0x9b, 0x77, 0xd7, 0xfa, 0x91, 0x9a, 0x38, 0x5f, 0x5f, - 0x67, 0x65, 0x11, 0xe0, 0xfd, 0xca, 0x12, 0xac, 0x14, 0xaa, 0xdd, 0xe7, 0xfc, 0x1a, 0xc0, 0x60, 0x5e, 0x9f, 0x85, - 0x0c, 0x2a, 0xfd, 0x5d, 0xa0, 0x5d, 0xa2, 0xe0, 0x41, 0x2b, 0xf2, 0xeb, 0x31, 0xfc, 0xb9, 0x39, 0xfc, 0x9d, 0xe0, - 0x6b, 0xff, 0x44, 0x7a, 0x79, 0x59, 0xa5, 0x38, 0xda, 0x4d, 0xe1, 0x02, 0x85, 0xe1, 0x4a, 0x89, 0x56, 0x3c, 0x82, - 0x0e, 0x1a, 0xc8, 0x03, 0x9a, 0x24, 0xbd, 0x7c, 0x0d, 0xb7, 0x26, 0x1d, 0x5d, 0x71, 0xe3, 0xe0, 0xbd, 0x47, 0x38, - 0x40, 0x17, 0xcd, 0x59, 0xc9, 0x4e, 0x57, 0x24, 0x03, 0x94, 0x82, 0xb9, 0x01, 0x60, 0xe2, 0xf4, 0x52, 0x5b, 0x9b, - 0x27, 0xca, 0x0d, 0x13, 0x2c, 0x93, 0xb6, 0x76, 0xcf, 0x34, 0x90, 0x8e, 0x9d, 0x0f, 0x12, 0x5f, 0xb2, 0x32, 0xad, - 0xad, 0x7b, 0xe9, 0xea, 0x02, 0x3b, 0xa2, 0x62, 0x3f, 0xd7, 0x61, 0x7a, 0xfd, 0x30, 0xc6, 0xb7, 0x59, 0xa0, 0x2e, - 0x9c, 0xc5, 0x3f, 0x5a, 0x25, 0x58, 0xb4, 0x16, 0xeb, 0xf4, 0x81, 0x9b, 0x50, 0x50, 0x7e, 0x91, 0x40, 0x96, 0x15, - 0xff, 0x0c, 0x73, 0x82, 0x95, 0xc6, 0x54, 0xfe, 0x65, 0x44, 0xdf, 0x52, 0xfd, 0x0f, 0xe2, 0x54, 0x0c, 0x52, 0x24, - 0x61, 0x28, 0x6b, 0x11, 0xfe, 0x3f, 0xdf, 0xfa, 0x77, 0xc3, 0xb7, 0xee, 0x1f, 0xa2, 0x71, 0x00, 0xfb, 0x8b, 0x17, - 0xf2, 0xdf, 0x37, 0xbb, 0xe3, 0x92, 0xdd, 0xfd, 0x0a, 0x46, 0xc7, 0xff, 0x31, 0x8c, 0x4e, 0xda, 0xc8, 0x86, 0xd3, - 0xe9, 0x8b, 0x77, 0xec, 0xf7, 0xe1, 0x4d, 0x78, 0x57, 0xef, 0xab, 0xf4, 0xf2, 0xf8, 0x26, 0xbc, 0xab, 0x17, 0x61, - 0x33, 0xbb, 0x58, 0xee, 0x63, 0xe8, 0xbe, 0x7d, 0xe3, 0x06, 0xee, 0xdb, 0xaf, 0xbf, 0x76, 0xf1, 0x65, 0x41, 0xc5, - 0x10, 0x0a, 0xc9, 0xf6, 0x7c, 0x6b, 0xb9, 0x22, 0xb8, 0x51, 0x60, 0x8a, 0x32, 0xd4, 0x86, 0x8b, 0x06, 0x30, 0xac, - 0xb8, 0xc8, 0x33, 0x1b, 0x9a, 0x77, 0x60, 0xd9, 0x7f, 0x29, 0x38, 0xb2, 0x97, 0x15, 0x78, 0x64, 0xe9, 0x32, 0x40, - 0xb2, 0xb0, 0x01, 0x51, 0x7d, 0x1f, 0xd1, 0xfd, 0xfc, 0xbf, 0xbe, 0x73, 0x41, 0x5d, 0x25, 0x12, 0x0d, 0xd3, 0xcb, - 0x2f, 0x11, 0x1f, 0x6a, 0xb0, 0xda, 0x63, 0x67, 0xdc, 0x9d, 0x61, 0xb9, 0x3d, 0x8f, 0x76, 0x76, 0xd8, 0xd0, 0xc5, - 0xf2, 0x12, 0xa8, 0x72, 0x9d, 0x70, 0xe1, 0xf0, 0x27, 0x87, 0x3f, 0x45, 0xcd, 0xa8, 0x59, 0x36, 0xe2, 0x21, 0xa7, - 0xf1, 0x66, 0x26, 0x5d, 0x5d, 0x9e, 0xa4, 0x49, 0x43, 0x65, 0x77, 0x17, 0x17, 0x32, 0xaf, 0x69, 0xc2, 0x40, 0x1f, - 0xdd, 0xb2, 0x3f, 0x11, 0xa4, 0x6f, 0x5b, 0xab, 0xbe, 0x30, 0x60, 0x23, 0x9c, 0x12, 0x5e, 0x25, 0x52, 0xc0, 0x95, - 0x9d, 0x3a, 0xf5, 0x04, 0xbb, 0x48, 0x7a, 0xdd, 0x63, 0x32, 0x90, 0x39, 0x15, 0xdf, 0x64, 0xc2, 0x8b, 0x7d, 0xc1, - 0xd9, 0xc4, 0x43, 0xb8, 0xdb, 0x41, 0xc8, 0x38, 0x1b, 0x62, 0x32, 0xd8, 0x62, 0xc5, 0x9b, 0xf0, 0x8d, 0x17, 0xcb, - 0x5b, 0xbe, 0xe4, 0x77, 0x81, 0xe0, 0x04, 0xe6, 0xb3, 0xd9, 0x68, 0x44, 0xb9, 0x67, 0x4e, 0x17, 0xfe, 0x7e, 0x1f, - 0x0e, 0x30, 0xc3, 0xdb, 0xe7, 0xa1, 0x08, 0xbf, 0x63, 0xf4, 0xc6, 0x2b, 0x50, 0x3f, 0xaf, 0x6f, 0x7e, 0x8c, 0xf1, - 0x4c, 0x26, 0x2e, 0x14, 0x54, 0x7c, 0x93, 0x89, 0xbd, 0x9e, 0x37, 0xfb, 0xfd, 0x3e, 0x8e, 0xe1, 0x3e, 0x0d, 0x93, - 0x32, 0xae, 0x2e, 0x42, 0xf9, 0xc8, 0x32, 0x71, 0xa8, 0xce, 0x78, 0x16, 0x48, 0xbb, 0x0f, 0xab, 0x74, 0x1b, 0x27, - 0xac, 0x3a, 0x8c, 0xc9, 0x20, 0xd9, 0x25, 0xea, 0xc4, 0xa7, 0xbc, 0xc2, 0xf7, 0x24, 0x09, 0xf9, 0x09, 0x9c, 0x26, - 0x07, 0x40, 0xaf, 0x44, 0x1e, 0x7a, 0x49, 0xf5, 0x99, 0x28, 0xaf, 0xfd, 0xe3, 0x6e, 0x7b, 0x8c, 0x65, 0xc6, 0x4d, - 0x5d, 0xd4, 0x86, 0xa2, 0x0b, 0xbb, 0x88, 0xec, 0x6e, 0xb7, 0x31, 0xec, 0xc1, 0xfe, 0x5a, 0x1f, 0xad, 0x59, 0xba, - 0xd6, 0x0d, 0x0f, 0xa7, 0x55, 0xdc, 0xe0, 0x24, 0xe4, 0x9c, 0x51, 0xee, 0x78, 0x2f, 0x7f, 0x41, 0xc1, 0xbf, 0xfe, - 0xcb, 0xfa, 0xf8, 0x81, 0x0e, 0x19, 0x38, 0x90, 0xb9, 0xd2, 0x92, 0xb9, 0xde, 0xc4, 0x8d, 0x54, 0x43, 0xd7, 0x84, - 0x3b, 0xf6, 0x0e, 0x3b, 0x9d, 0x8e, 0x0e, 0x09, 0x74, 0xd5, 0x4f, 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x90, 0x91, 0x6c, - 0xe2, 0xaa, 0x00, 0xe5, 0x61, 0x67, 0x7a, 0xeb, 0x0e, 0x60, 0x3b, 0x68, 0x28, 0xde, 0xd3, 0x29, 0x0d, 0xc5, 0x17, - 0x8d, 0xcf, 0x65, 0x93, 0x6a, 0xf8, 0xae, 0x19, 0xba, 0x1e, 0x77, 0x69, 0xd0, 0x83, 0xe5, 0x41, 0x3f, 0xb0, 0x89, - 0xbc, 0x17, 0x6a, 0xd3, 0xa8, 0xd2, 0x53, 0xdd, 0x18, 0x53, 0xa8, 0x16, 0xae, 0x23, 0x31, 0x9e, 0xe4, 0x69, 0x4c, - 0x39, 0x71, 0xa9, 0x3f, 0xf6, 0x9d, 0xa7, 0x9d, 0x4e, 0x07, 0xb7, 0xf6, 0x0f, 0x3a, 0x1d, 0x7c, 0xf0, 0xb8, 0x83, - 0x5b, 0xf0, 0xc7, 0xf7, 0xfd, 0x25, 0x18, 0xee, 0x8b, 0xda, 0x76, 0x3b, 0x9c, 0x4e, 0x34, 0x80, 0xf7, 0x86, 0x15, - 0xeb, 0x3d, 0x01, 0xb7, 0x57, 0xeb, 0x7d, 0xaf, 0x24, 0x9b, 0xbe, 0x3d, 0x41, 0xe7, 0xba, 0x4a, 0x7f, 0x61, 0x51, - 0x07, 0x4d, 0xa9, 0xba, 0x55, 0xf0, 0x1b, 0x4d, 0x08, 0x81, 0x73, 0x02, 0x57, 0xa3, 0xca, 0x78, 0x29, 0x64, 0x1e, - 0xc1, 0xd7, 0xd7, 0x44, 0xc8, 0x32, 0xf8, 0x30, 0x97, 0x89, 0x9a, 0x1a, 0x46, 0x55, 0x2c, 0x65, 0xf4, 0x3e, 0x52, - 0x61, 0xe9, 0x75, 0x04, 0x71, 0xfe, 0x08, 0xe1, 0xf0, 0x21, 0x0d, 0xf4, 0x0a, 0x42, 0xfd, 0xe4, 0x21, 0xf5, 0x0d, - 0xf6, 0xcf, 0x1f, 0xc9, 0x44, 0xa8, 0xad, 0x68, 0xb1, 0xd8, 0x0a, 0x17, 0x8b, 0xad, 0xe4, 0xe1, 0x33, 0x54, 0xcb, - 0x6b, 0x8e, 0x58, 0xc0, 0xb5, 0xa2, 0x0a, 0xe8, 0x6f, 0xa0, 0x3c, 0x88, 0xb0, 0x02, 0x49, 0x3d, 0x85, 0x58, 0x0f, - 0xa8, 0x1e, 0x93, 0x72, 0x09, 0x29, 0x31, 0x89, 0x94, 0x7d, 0xbe, 0x58, 0x68, 0xe2, 0xc7, 0x33, 0x12, 0x56, 0x45, - 0x5d, 0x17, 0x4f, 0x49, 0x52, 0x3d, 0xba, 0x12, 0xe4, 0xa9, 0xe6, 0x52, 0x35, 0xc4, 0x37, 0x21, 0xcf, 0x6c, 0x80, - 0xdf, 0xe4, 0x8e, 0x1e, 0xd6, 0x99, 0xf2, 0xfc, 0x9a, 0x41, 0xc2, 0xcd, 0xd2, 0xc0, 0x13, 0x02, 0xb7, 0x8a, 0xf5, - 0xed, 0x50, 0xb8, 0xd5, 0xc1, 0x07, 0xc3, 0x67, 0xe1, 0x0a, 0xcb, 0x6a, 0x82, 0x41, 0xac, 0xe7, 0x16, 0xcc, 0xcc, - 0xb4, 0xde, 0x87, 0x37, 0xc1, 0xd4, 0x3c, 0xbc, 0x50, 0xb9, 0x3d, 0xc1, 0xa4, 0x3a, 0xb6, 0xf3, 0x8e, 0xbc, 0x81, - 0xd8, 0x8f, 0x6b, 0xf8, 0x36, 0x5c, 0xe2, 0xa9, 0x78, 0xdc, 0xfb, 0x57, 0xa7, 0x34, 0xe4, 0x51, 0xf2, 0x2e, 0xe4, - 0xe1, 0xa4, 0xe8, 0x8f, 0xcc, 0x15, 0x61, 0x86, 0x02, 0x2e, 0x46, 0x32, 0xbb, 0x2a, 0x8b, 0xee, 0x5c, 0x1c, 0x23, - 0x5c, 0xbf, 0x57, 0x10, 0x28, 0x3f, 0xb7, 0x8b, 0x67, 0xf6, 0x2b, 0x58, 0x67, 0x17, 0x4f, 0x10, 0x56, 0x49, 0x4b, - 0xef, 0x7e, 0xcb, 0x74, 0x25, 0x0c, 0xf9, 0x35, 0xc1, 0xc8, 0xaf, 0x3f, 0xa1, 0x67, 0x12, 0x98, 0x3e, 0x2c, 0x25, - 0x30, 0xad, 0x41, 0xa3, 0xc3, 0x69, 0x31, 0xcd, 0xb3, 0x82, 0xba, 0xf8, 0x03, 0xb4, 0x53, 0xf7, 0x3c, 0xdb, 0x0d, - 0x57, 0x68, 0xae, 0x6a, 0x2a, 0xdf, 0xa8, 0x76, 0x10, 0xd4, 0xf9, 0xf0, 0x97, 0x2a, 0x8e, 0x6f, 0xe2, 0x3b, 0x32, - 0xcb, 0x9d, 0xd1, 0x0d, 0x89, 0xb8, 0x9c, 0x7e, 0x36, 0x11, 0x37, 0x7d, 0x50, 0x22, 0xae, 0xbc, 0x3e, 0xe5, 0x37, - 0x4d, 0xc4, 0x65, 0xd4, 0x4a, 0xc4, 0x05, 0x39, 0xf7, 0xf5, 0x83, 0xf2, 0x39, 0x4d, 0xf6, 0x5d, 0x7e, 0x53, 0x90, - 0xae, 0x8e, 0x81, 0xa4, 0xf9, 0x18, 0x92, 0x39, 0xff, 0xf1, 0xb9, 0x99, 0x69, 0x3e, 0xb6, 0x33, 0x33, 0xe1, 0xab, - 0x27, 0x40, 0x76, 0x38, 0x27, 0x73, 0xf7, 0xc7, 0xdb, 0xee, 0xb3, 0xb3, 0x6e, 0x7f, 0xaf, 0x3b, 0x71, 0x03, 0x17, - 0x9c, 0x8e, 0xb2, 0xa0, 0xd3, 0xdf, 0xdb, 0x83, 0x82, 0x1b, 0xab, 0xa0, 0x07, 0x05, 0xcc, 0x2a, 0x38, 0x80, 0x82, - 0xc8, 0x2a, 0x78, 0x0c, 0x05, 0xb1, 0x55, 0xf0, 0x04, 0x0a, 0xae, 0xdd, 0xf2, 0x8c, 0x55, 0xd9, 0xc6, 0x4f, 0x90, - 0xbc, 0x1e, 0x71, 0x2b, 0x6f, 0x1e, 0x0d, 0x8f, 0x88, 0xa9, 0xf2, 0xa4, 0xba, 0x56, 0xa2, 0xb5, 0x6f, 0x6e, 0x41, - 0xbc, 0xfc, 0xdd, 0x25, 0xb0, 0xd6, 0x08, 0xae, 0x47, 0x80, 0x98, 0xa4, 0xaa, 0xb9, 0x67, 0x5e, 0xbb, 0x41, 0x95, - 0x92, 0xdb, 0xc1, 0x3d, 0x93, 0x94, 0x1b, 0xb8, 0x48, 0xf2, 0x25, 0xf5, 0xe2, 0x60, 0x37, 0xd6, 0xdd, 0xc2, 0x05, - 0x83, 0xf5, 0xed, 0x9e, 0x7b, 0x08, 0x4f, 0x8c, 0x02, 0x44, 0x3d, 0xf8, 0xba, 0xc3, 0x07, 0x36, 0xa1, 0x66, 0xbf, - 0x98, 0x01, 0x1c, 0x99, 0xb6, 0xdc, 0x8f, 0x6a, 0xc5, 0xe8, 0x1d, 0x1e, 0xd5, 0x17, 0xca, 0x7e, 0x20, 0xea, 0x82, - 0xbe, 0x1c, 0xab, 0x30, 0xd7, 0x14, 0x8b, 0x70, 0x1c, 0x40, 0xda, 0x26, 0x64, 0x8c, 0x04, 0x23, 0x42, 0x48, 0x67, - 0x38, 0x0b, 0xde, 0xe1, 0x9b, 0x84, 0x66, 0xc1, 0xa4, 0xec, 0x57, 0xeb, 0xaf, 0xb2, 0x46, 0x3f, 0x54, 0xb7, 0x90, - 0x4b, 0x9a, 0xa8, 0xdf, 0x2a, 0x28, 0x5b, 0x15, 0xed, 0x6c, 0xc8, 0x33, 0xb4, 0x94, 0x9d, 0x51, 0x9a, 0xdf, 0xb4, - 0x40, 0xdc, 0xaf, 0xcd, 0x3d, 0x84, 0xb9, 0x55, 0xb9, 0x87, 0xaf, 0x00, 0xd6, 0xea, 0xe9, 0x43, 0x38, 0xae, 0x7e, - 0xbf, 0xa6, 0x45, 0x11, 0x8e, 0x75, 0xcd, 0xcd, 0xb9, 0x86, 0x12, 0x44, 0x3b, 0xcf, 0xd0, 0x00, 0x01, 0x09, 0x81, - 0x80, 0x10, 0x08, 0xe8, 0xea, 0xfc, 0x40, 0x98, 0x79, 0x33, 0xb5, 0x50, 0xa2, 0xaa, 0x59, 0x24, 0xc2, 0x71, 0x5d, - 0x70, 0x34, 0xe5, 0x54, 0x27, 0x2d, 0x02, 0x16, 0xcb, 0xa3, 0x36, 0x14, 0xa8, 0xd7, 0x1b, 0x52, 0x08, 0x0d, 0x77, - 0xd9, 0x9c, 0x48, 0xe8, 0x98, 0x14, 0x42, 0xfb, 0xd8, 0x4b, 0x75, 0xe6, 0x65, 0x35, 0x71, 0xed, 0xab, 0x6e, 0x04, - 0xff, 0xe9, 0xb4, 0xb8, 0xaf, 0x46, 0xa3, 0xd1, 0xbd, 0x29, 0x85, 0x5f, 0xc5, 0x23, 0xda, 0xa3, 0x07, 0x7d, 0x38, - 0x12, 0xd1, 0xd2, 0x89, 0x68, 0xdd, 0x52, 0xe2, 0x6e, 0xfe, 0xb0, 0xca, 0x90, 0xb3, 0x26, 0x92, 0xf9, 0xc3, 0xd3, - 0x0b, 0xcb, 0x29, 0xa7, 0xf3, 0x49, 0xc8, 0xc7, 0x2c, 0x0b, 0x3a, 0xa5, 0x7f, 0xad, 0xf3, 0xf1, 0xbe, 0x3a, 0x3c, - 0x3c, 0x2c, 0xfd, 0xd8, 0x3c, 0x75, 0xe2, 0xb8, 0xf4, 0xa3, 0x79, 0x35, 0x8d, 0x4e, 0x67, 0x34, 0x2a, 0x7d, 0x66, - 0x0a, 0xf6, 0x7a, 0x51, 0xbc, 0xd7, 0x2b, 0xfd, 0x1b, 0xab, 0x46, 0xe9, 0x53, 0xfd, 0xc4, 0x69, 0xdc, 0x38, 0x57, - 0xf1, 0xa4, 0xd3, 0x29, 0x7d, 0x45, 0x68, 0x73, 0x88, 0xc9, 0xa9, 0x9f, 0x41, 0x38, 0x13, 0x79, 0x79, 0x59, 0x96, - 0xfd, 0x54, 0x78, 0x67, 0xdb, 0xfa, 0xce, 0x4a, 0xf5, 0x91, 0xc7, 0x12, 0x9d, 0xe3, 0xaf, 0xed, 0xcc, 0x39, 0x20, - 0x66, 0x99, 0x31, 0x97, 0x9a, 0xc4, 0xba, 0xc6, 0x6b, 0xa0, 0x2c, 0xf9, 0xfa, 0x6b, 0x92, 0xd6, 0x09, 0x75, 0xc0, - 0xc7, 0xa0, 0xa6, 0xba, 0x5a, 0x3d, 0xdb, 0x24, 0x3d, 0x8a, 0xcf, 0x4b, 0x8f, 0xab, 0x87, 0x08, 0x8f, 0xe2, 0x37, - 0x17, 0x1e, 0x99, 0x2d, 0x3c, 0x14, 0xeb, 0xb8, 0x11, 0xc4, 0x8d, 0x12, 0x1a, 0x7d, 0xba, 0xca, 0x6f, 0x5b, 0xb0, - 0x25, 0xb8, 0x2b, 0xc5, 0xca, 0xf5, 0xaf, 0x3d, 0x26, 0x60, 0x3a, 0xb3, 0xbe, 0x10, 0x29, 0x75, 0xfc, 0xb7, 0x19, - 0x71, 0xdf, 0x9a, 0xc0, 0x9e, 0x2a, 0x19, 0x8d, 0x88, 0xfb, 0x76, 0x34, 0x72, 0xcd, 0xcd, 0x3b, 0xa1, 0xa0, 0xb2, - 0xd6, 0x9b, 0x46, 0x89, 0xac, 0x05, 0x86, 0x7e, 0x5d, 0x66, 0x17, 0xe8, 0xbc, 0x3b, 0x3b, 0xc7, 0x4e, 0xbf, 0x89, - 0x59, 0x01, 0x5b, 0x0d, 0x3e, 0x5c, 0xd9, 0xbc, 0xf9, 0x3f, 0x6b, 0x7c, 0xa6, 0xa9, 0x02, 0x78, 0xcd, 0xb7, 0xa5, - 0x96, 0xaf, 0x9d, 0x1b, 0x53, 0xa3, 0xe2, 0x3f, 0xbb, 0xfb, 0x26, 0xf6, 0x6e, 0x04, 0x2a, 0x59, 0xf1, 0x36, 0x5b, - 0xba, 0x52, 0x42, 0xc1, 0x48, 0x88, 0x3d, 0xad, 0x52, 0xe4, 0xe3, 0x71, 0x2a, 0x4f, 0xaa, 0x34, 0x0c, 0x6e, 0xd5, - 0x7c, 0xd8, 0x98, 0x6f, 0x60, 0x37, 0xd4, 0xdf, 0xee, 0x90, 0x1f, 0x33, 0x56, 0x47, 0x91, 0xaf, 0xf5, 0x57, 0x6d, - 0x65, 0x4c, 0x70, 0xae, 0x79, 0xfc, 0x5c, 0x1d, 0x60, 0x15, 0x98, 0xc5, 0xaa, 0x39, 0x8b, 0xcb, 0x52, 0x1f, 0xfd, - 0x8f, 0x59, 0x31, 0x05, 0xed, 0x49, 0xb5, 0xa4, 0x9f, 0x63, 0xe1, 0xc5, 0x8d, 0x95, 0xdc, 0xd6, 0x58, 0xae, 0xd2, - 0xd8, 0x69, 0x2a, 0x5b, 0xe8, 0x46, 0x94, 0xae, 0x36, 0xd9, 0x0c, 0x12, 0x5d, 0x47, 0xe1, 0x53, 0xa5, 0xdd, 0x59, - 0x33, 0x84, 0xcc, 0x9f, 0x6a, 0x41, 0xcc, 0x2b, 0x53, 0x50, 0xda, 0x56, 0x96, 0x7c, 0xa3, 0xb0, 0x25, 0x53, 0xc5, - 0x8a, 0x69, 0x98, 0x19, 0x63, 0x4e, 0xf1, 0x83, 0xed, 0x79, 0xbd, 0xf2, 0xa5, 0x6b, 0xc0, 0x56, 0xc4, 0x3b, 0x38, - 0x6a, 0x43, 0x83, 0x81, 0xd3, 0x00, 0x3d, 0x5b, 0xc9, 0x30, 0xbb, 0x3f, 0xd7, 0xfb, 0xd3, 0xa5, 0x5f, 0xdc, 0x60, - 0xbf, 0xb8, 0x71, 0x7e, 0x3f, 0x6f, 0xdd, 0xd0, 0xab, 0x4f, 0x4c, 0xb4, 0x44, 0x38, 0x6d, 0x81, 0xf7, 0x54, 0x66, - 0x86, 0x68, 0xf6, 0x2c, 0x75, 0x74, 0x65, 0xfa, 0xf5, 0x67, 0x05, 0xa4, 0x84, 0x4b, 0x33, 0x2a, 0xc8, 0xf2, 0x8c, - 0xf6, 0x9b, 0x67, 0x03, 0xed, 0x0c, 0x63, 0x83, 0xad, 0xf3, 0x79, 0x0e, 0x29, 0xe4, 0xe2, 0x2e, 0xe8, 0x68, 0xb6, - 0xde, 0x31, 0xe9, 0xc3, 0x9d, 0xb5, 0xf5, 0x03, 0x8d, 0xdc, 0x5d, 0x29, 0xbd, 0xf8, 0x6a, 0x1a, 0xf5, 0xa6, 0x34, - 0xe8, 0xcf, 0x9d, 0x94, 0x83, 0x7c, 0x12, 0xf3, 0xbf, 0x75, 0xc4, 0x70, 0xb9, 0x58, 0x9e, 0x94, 0x7b, 0x08, 0x64, - 0x41, 0x38, 0x12, 0x94, 0xe3, 0x87, 0xd4, 0xbc, 0x92, 0x97, 0x5a, 0xcc, 0x41, 0xcc, 0x04, 0xdd, 0xc3, 0xe9, 0xed, - 0xc3, 0xbb, 0xbf, 0x7f, 0xfa, 0xa5, 0xc6, 0x91, 0xb9, 0xe4, 0xd5, 0x75, 0xfb, 0xb0, 0x11, 0xd2, 0xf0, 0x2e, 0x60, - 0x99, 0x94, 0x79, 0x57, 0x90, 0x14, 0xd2, 0x9f, 0xe6, 0xfa, 0xc8, 0x27, 0xa7, 0xa9, 0xfc, 0xae, 0xbb, 0x5e, 0x8a, - 0xbd, 0xc7, 0xd3, 0x5b, 0xb3, 0x1a, 0xdd, 0xa5, 0xa3, 0x9c, 0xbf, 0xe9, 0x89, 0xcd, 0xcd, 0x47, 0x44, 0x9b, 0xa7, - 0x0e, 0x0f, 0xa6, 0xb7, 0x7d, 0x25, 0x68, 0x5b, 0x5c, 0x41, 0xd5, 0x99, 0xde, 0xda, 0x67, 0x56, 0xeb, 0x8e, 0x1c, - 0x7f, 0xaf, 0x70, 0x68, 0x58, 0xd0, 0x3e, 0x7c, 0xc6, 0x8a, 0x45, 0x61, 0xaa, 0x85, 0xf9, 0x84, 0xc5, 0x71, 0x4a, - 0xfb, 0x46, 0x5e, 0x3b, 0xdd, 0xc7, 0x70, 0xe4, 0xd3, 0x5e, 0xb2, 0xe6, 0xaa, 0x58, 0xc8, 0xab, 0xf0, 0x14, 0x5e, - 0x15, 0x79, 0x0a, 0x1f, 0x91, 0x5c, 0x8b, 0x4e, 0x7d, 0x16, 0xb2, 0x53, 0x23, 0x4f, 0xfe, 0x6e, 0xce, 0xe5, 0xa0, - 0xf3, 0x4f, 0x7d, 0xb9, 0xe0, 0x9d, 0xbe, 0xc8, 0xa7, 0x41, 0x6b, 0xaf, 0x39, 0x11, 0x78, 0x55, 0x4d, 0x01, 0xaf, - 0x99, 0x16, 0x06, 0x69, 0xa5, 0xf8, 0xb4, 0xe3, 0x77, 0x75, 0x99, 0xec, 0x00, 0x8c, 0xd0, 0xaa, 0xa8, 0x6c, 0x4e, - 0xe6, 0x1f, 0xb3, 0x5b, 0x9e, 0xae, 0xdf, 0x2d, 0x4f, 0xcd, 0x6e, 0xb9, 0x9f, 0x62, 0xbf, 0x1a, 0x75, 0xe1, 0xbf, - 0x7e, 0x3d, 0xa1, 0xa0, 0xe3, 0xec, 0x4d, 0x6f, 0x1d, 0xd0, 0xd3, 0x5a, 0xbd, 0xe9, 0xad, 0x3a, 0xb1, 0x0b, 0x89, - 0x6b, 0x1d, 0x38, 0xc3, 0x8a, 0x3b, 0x0e, 0x14, 0xc2, 0xff, 0x9d, 0xc6, 0xab, 0xee, 0x3e, 0xbc, 0x83, 0x56, 0x07, - 0xab, 0xef, 0x7a, 0xf7, 0x6f, 0xda, 0x20, 0xcb, 0x85, 0x17, 0x18, 0x6e, 0x8c, 0x7c, 0x11, 0x5e, 0x5d, 0xd1, 0x38, - 0x18, 0xe5, 0xd1, 0xac, 0xf8, 0x67, 0x0d, 0xbf, 0x46, 0xe2, 0xbd, 0x5b, 0x7a, 0xa9, 0x1f, 0xd3, 0x54, 0x9d, 0x1f, - 0x36, 0x3d, 0xcc, 0xab, 0x75, 0x0a, 0x8a, 0x28, 0x4c, 0xa9, 0xd7, 0xf3, 0xf7, 0xd7, 0x6c, 0x82, 0x7f, 0x93, 0xb5, - 0x59, 0x3b, 0x99, 0xbf, 0x17, 0x19, 0xf7, 0x22, 0xe1, 0x8b, 0x70, 0x60, 0xaf, 0x61, 0xe7, 0x70, 0x3d, 0xb8, 0x67, - 0x66, 0xa4, 0x73, 0x23, 0x14, 0xb4, 0xdc, 0x89, 0xe9, 0x28, 0x9c, 0xa5, 0xe2, 0xfe, 0x5e, 0x37, 0x51, 0xc6, 0x4a, - 0xaf, 0xf7, 0x30, 0xf4, 0xba, 0xee, 0x03, 0xb9, 0xf4, 0x57, 0x4f, 0xf7, 0xe1, 0x3f, 0x75, 0xf8, 0xe5, 0xaa, 0xd6, - 0xd5, 0x95, 0xd5, 0x0b, 0xba, 0xfa, 0x75, 0x43, 0x19, 0x57, 0x22, 0x5c, 0xea, 0xe3, 0x0f, 0xad, 0x0d, 0x5a, 0xe5, - 0x83, 0xaa, 0x6b, 0x2d, 0xeb, 0x8b, 0x6a, 0x7f, 0x59, 0xe7, 0x0f, 0xac, 0x1b, 0x29, 0xcd, 0xb5, 0x59, 0x57, 0x7f, - 0xd7, 0x7e, 0xa5, 0xb2, 0xc1, 0xb8, 0xac, 0x7f, 0x4d, 0xae, 0x2a, 0x13, 0x45, 0xa5, 0xa2, 0x82, 0x95, 0x72, 0xad, - 0xac, 0x94, 0x9c, 0x92, 0xcb, 0xa3, 0xe1, 0xed, 0x24, 0x75, 0xae, 0xd5, 0xe5, 0x3b, 0xc4, 0xed, 0xfa, 0x1d, 0xd7, - 0x91, 0x4e, 0x3a, 0xf8, 0x06, 0x98, 0xfb, 0xf1, 0xc3, 0xd7, 0xad, 0x43, 0x77, 0x08, 0x9a, 0xd6, 0xf5, 0x58, 0x6a, - 0x76, 0xaf, 0xc2, 0x3b, 0xca, 0x2f, 0x7a, 0xda, 0x05, 0xaf, 0xf2, 0xc5, 0x65, 0x99, 0xd3, 0x73, 0x9d, 0xdb, 0x49, - 0x9a, 0x15, 0xc4, 0x4d, 0x84, 0x98, 0x06, 0xed, 0xf6, 0xcd, 0xcd, 0x8d, 0x7f, 0xb3, 0xe7, 0xe7, 0x7c, 0xdc, 0xee, - 0x75, 0x3a, 0x1d, 0xf8, 0x9c, 0x88, 0xeb, 0x5c, 0x33, 0x7a, 0xf3, 0x2c, 0xbf, 0x25, 0x6e, 0xc7, 0xe9, 0x38, 0xdd, - 0xde, 0xa1, 0xd3, 0xed, 0xed, 0xfb, 0x8f, 0x0f, 0xdd, 0xc1, 0xef, 0x1c, 0xe7, 0x28, 0xa6, 0xa3, 0x02, 0x7e, 0x38, - 0xce, 0x91, 0x54, 0xbc, 0xd4, 0x6f, 0xc7, 0xf1, 0xa3, 0xb4, 0x68, 0x75, 0x9d, 0xb9, 0x7e, 0x74, 0x1c, 0xb8, 0xa2, - 0x28, 0x70, 0xbe, 0x1a, 0xf5, 0x46, 0xfb, 0xa3, 0xa7, 0x7d, 0x5d, 0x5c, 0xfe, 0xae, 0x51, 0x1d, 0xab, 0x7f, 0x7b, - 0x56, 0xb3, 0x42, 0xf0, 0xfc, 0x13, 0xd5, 0xae, 0x7d, 0x07, 0x44, 0xcf, 0xda, 0xa6, 0xbd, 0xd5, 0x91, 0xba, 0x87, - 0x57, 0xd1, 0xa8, 0x57, 0x57, 0x97, 0x30, 0xb6, 0x2b, 0x20, 0x8f, 0xda, 0x06, 0xf4, 0x23, 0x1b, 0x4d, 0xdd, 0xd6, - 0x3a, 0x44, 0x75, 0x5d, 0x3d, 0xc7, 0xb1, 0x99, 0xdf, 0x11, 0x9c, 0x88, 0x37, 0xba, 0xaa, 0x84, 0xc0, 0x75, 0x62, - 0xe2, 0xbe, 0xee, 0xf6, 0x0e, 0x71, 0xb7, 0xfb, 0xd8, 0x7f, 0x7c, 0x18, 0x75, 0xf0, 0xbe, 0xbf, 0xdf, 0xda, 0xf3, - 0x1f, 0xe3, 0xc3, 0xd6, 0x21, 0x3e, 0x7c, 0x79, 0x18, 0xb5, 0xf6, 0xfd, 0x7d, 0xdc, 0x69, 0x1d, 0x42, 0x61, 0xeb, - 0xb0, 0x75, 0x78, 0xdd, 0xda, 0x3f, 0x8c, 0x3a, 0xb2, 0xb4, 0xe7, 0x1f, 0x1c, 0xb4, 0xba, 0x1d, 0xff, 0xe0, 0x00, - 0x1f, 0xf8, 0x8f, 0x1f, 0xb7, 0xba, 0x7b, 0xfe, 0xe3, 0xc7, 0xaf, 0x0e, 0x0e, 0xfd, 0x3d, 0x78, 0xb7, 0xb7, 0x17, - 0xed, 0xf9, 0xdd, 0x6e, 0x0b, 0xfe, 0xe0, 0x43, 0xbf, 0xa7, 0x7e, 0x74, 0xbb, 0xfe, 0x5e, 0x17, 0x77, 0xd2, 0x83, - 0x9e, 0xff, 0xf8, 0x29, 0x96, 0x7f, 0x65, 0x35, 0x2c, 0xff, 0x40, 0x37, 0xf8, 0xa9, 0xdf, 0x7b, 0xac, 0x7e, 0xc9, - 0x0e, 0xaf, 0xf7, 0x0f, 0x7f, 0x70, 0xdb, 0x1b, 0xe7, 0xd0, 0x55, 0x73, 0x38, 0x3c, 0xf0, 0xf7, 0xf6, 0xf0, 0x7e, - 0xd7, 0x3f, 0xdc, 0x4b, 0x5a, 0xfb, 0x3d, 0xff, 0xf1, 0x93, 0xa8, 0xd5, 0xf5, 0x9f, 0x3c, 0xc1, 0x9d, 0xd6, 0x9e, - 0xdf, 0xc3, 0x5d, 0x7f, 0x7f, 0x4f, 0xfe, 0xd8, 0xf3, 0x7b, 0xd7, 0x4f, 0x9e, 0xfa, 0x8f, 0x0f, 0x92, 0xc7, 0xfe, - 0xfe, 0x77, 0xfb, 0x87, 0x7e, 0x6f, 0x2f, 0xd9, 0x7b, 0xec, 0xf7, 0x9e, 0x5c, 0x3f, 0xf6, 0xf7, 0x93, 0x56, 0xef, - 0xf1, 0xbd, 0x2d, 0xbb, 0x3d, 0x1f, 0x70, 0x24, 0x5f, 0xc3, 0x0b, 0xac, 0x5f, 0xc0, 0xff, 0x89, 0x6c, 0xfb, 0x6f, - 0xd8, 0x4d, 0xb1, 0xda, 0xf4, 0xa9, 0x7f, 0xf8, 0x24, 0x52, 0xd5, 0xa1, 0xa0, 0x65, 0x6a, 0x40, 0x93, 0xeb, 0x96, - 0x1a, 0x56, 0x76, 0xd7, 0x32, 0x1d, 0x99, 0xff, 0xf5, 0x60, 0xd7, 0x2d, 0x18, 0x58, 0x8d, 0xfb, 0xff, 0xb4, 0x9f, - 0x6a, 0xc9, 0x8f, 0xda, 0x63, 0x45, 0xfa, 0xe3, 0xc1, 0xef, 0xd4, 0xb7, 0x82, 0x7e, 0x77, 0x89, 0xc3, 0x4d, 0x8e, - 0x8f, 0xf4, 0xf3, 0x8e, 0x8f, 0x84, 0x3e, 0xc4, 0xf3, 0x91, 0xfe, 0xe6, 0x9e, 0x8f, 0x70, 0xd9, 0x6d, 0x7e, 0x2b, - 0x56, 0x1c, 0x1c, 0xcb, 0x56, 0xf1, 0x37, 0xc2, 0x3b, 0xcb, 0xe1, 0xbb, 0xd4, 0x65, 0xff, 0x56, 0x90, 0x84, 0xda, - 0x7e, 0xa0, 0x1c, 0x58, 0xec, 0xad, 0x50, 0x3c, 0x36, 0xda, 0x84, 0x90, 0xf8, 0xf3, 0x08, 0xf9, 0xfe, 0x21, 0xf8, - 0x88, 0x7f, 0x73, 0x7c, 0x44, 0x36, 0x3e, 0x1a, 0x9e, 0x7c, 0xe9, 0x69, 0x90, 0x9e, 0x82, 0x53, 0xf9, 0xec, 0xc1, - 0x95, 0x1c, 0xbb, 0x6e, 0x9b, 0x5e, 0xcb, 0xc8, 0x9d, 0x0a, 0xae, 0xbf, 0xfc, 0x92, 0xa0, 0x83, 0xba, 0x7f, 0x87, - 0xb8, 0xda, 0x2d, 0x33, 0x95, 0x52, 0x47, 0x3f, 0x54, 0x42, 0xa9, 0xe7, 0x77, 0xfc, 0x4e, 0xe5, 0xd2, 0x81, 0x3b, - 0x97, 0xc8, 0x3c, 0x17, 0x61, 0xb0, 0xd5, 0xc5, 0x69, 0x3e, 0x86, 0x9b, 0x98, 0xe4, 0xb7, 0xe9, 0xe0, 0xc4, 0x43, - 0xa4, 0x3e, 0x0b, 0x08, 0xe9, 0x13, 0xda, 0xd1, 0x13, 0xf2, 0x4f, 0x7f, 0x86, 0x20, 0xa6, 0x89, 0x49, 0x4c, 0xc0, - 0xdb, 0xf1, 0x9a, 0xc6, 0x2c, 0xf4, 0x5c, 0x6f, 0xca, 0xe9, 0x88, 0xf2, 0xa2, 0xd5, 0xb8, 0x0c, 0x48, 0xde, 0x03, - 0x84, 0x5c, 0x0d, 0xe1, 0x88, 0xc3, 0xb7, 0x96, 0xc8, 0x99, 0xf6, 0x37, 0xba, 0xda, 0x00, 0x73, 0x4b, 0x6c, 0x4a, - 0x38, 0xc8, 0xda, 0x5a, 0x69, 0x73, 0x95, 0xd6, 0xd6, 0xf5, 0x7b, 0x07, 0xc8, 0x91, 0xc5, 0xf0, 0x15, 0x9b, 0xbf, - 0x7a, 0xad, 0xbd, 0xce, 0x3f, 0x21, 0xab, 0x59, 0xd5, 0xd1, 0xb9, 0x76, 0xb7, 0x65, 0xd5, 0xb7, 0x0e, 0x97, 0xc2, - 0xae, 0xae, 0xa2, 0x88, 0xaf, 0xd4, 0xdc, 0x5d, 0xd4, 0xcf, 0x74, 0xd2, 0x9c, 0xba, 0x6f, 0x70, 0xc4, 0xc6, 0x9e, - 0x75, 0x97, 0x45, 0xa6, 0xbe, 0x92, 0x03, 0x57, 0xe1, 0x23, 0x54, 0xd6, 0x55, 0x32, 0x34, 0x97, 0xd1, 0x16, 0x96, - 0x39, 0xd9, 0x62, 0xe1, 0x65, 0xe0, 0x22, 0x27, 0x16, 0x4e, 0xe1, 0x19, 0x35, 0x90, 0x9c, 0xe1, 0x0a, 0x20, 0x89, - 0x60, 0x92, 0xa9, 0x7f, 0xeb, 0x62, 0xf3, 0x43, 0x3b, 0xbe, 0xfc, 0x34, 0xcc, 0xc6, 0x40, 0x85, 0x61, 0x36, 0x5e, - 0x71, 0xab, 0xa9, 0x80, 0xd1, 0x52, 0x69, 0xdd, 0x55, 0xed, 0x3e, 0x2b, 0x9e, 0xdd, 0x7d, 0xd0, 0xd7, 0x69, 0xbb, - 0xe0, 0x9d, 0x96, 0xf1, 0x8d, 0xfa, 0xd3, 0x3f, 0xbb, 0xe4, 0xd1, 0xd1, 0x84, 0x8a, 0x50, 0x1d, 0x56, 0x03, 0x7d, - 0x02, 0x72, 0x59, 0x1c, 0x6d, 0x8d, 0xea, 0xa0, 0x3e, 0x51, 0x17, 0x08, 0x28, 0x51, 0x8f, 0x1d, 0x7d, 0x0f, 0x5d, - 0x4b, 0x2e, 0x0d, 0xe9, 0x62, 0xe5, 0x8f, 0x89, 0x42, 0x79, 0x1c, 0x99, 0x64, 0xb9, 0x3b, 0x78, 0x54, 0xe5, 0xba, - 0x6c, 0x5a, 0x84, 0x94, 0x65, 0x9f, 0xce, 0x38, 0x4d, 0xff, 0x99, 0x3c, 0x62, 0x51, 0x9e, 0x3d, 0x3a, 0x77, 0x51, - 0x5f, 0xf8, 0x09, 0xa7, 0x23, 0xf2, 0x08, 0x64, 0x7c, 0x20, 0xad, 0x0f, 0x60, 0x84, 0xbb, 0xb7, 0x93, 0x14, 0x4b, - 0x8d, 0xe9, 0x01, 0x0a, 0x91, 0x02, 0xd7, 0xed, 0x1d, 0xb8, 0x8e, 0xb2, 0x89, 0xe5, 0xef, 0x81, 0x12, 0xa7, 0x52, - 0x09, 0x70, 0xba, 0x3d, 0xff, 0x20, 0xe9, 0xf9, 0x4f, 0xaf, 0x9f, 0xf8, 0x87, 0x49, 0xf7, 0xc9, 0x75, 0x0b, 0xfe, - 0xed, 0xf9, 0x4f, 0xd3, 0x56, 0xcf, 0x7f, 0x0a, 0xff, 0x7f, 0xb7, 0xef, 0x1f, 0x24, 0xad, 0xae, 0x7f, 0x78, 0xbd, - 0xe7, 0xef, 0xbd, 0xea, 0xf6, 0xfc, 0x3d, 0xa7, 0xeb, 0xa8, 0x76, 0xc0, 0xae, 0x15, 0x77, 0x7e, 0xb4, 0xb4, 0x21, - 0xd6, 0x04, 0xe3, 0xd4, 0x81, 0x3b, 0x17, 0xcb, 0x33, 0xd2, 0xf6, 0xfe, 0xd4, 0xce, 0xba, 0xe7, 0x21, 0x87, 0xcf, - 0xa6, 0x36, 0xf7, 0x6e, 0xe3, 0x1d, 0x6e, 0xf0, 0x8b, 0x35, 0x43, 0x4c, 0x65, 0x04, 0xdc, 0xbe, 0xc8, 0x0d, 0x6e, - 0x41, 0x93, 0x5f, 0x99, 0x32, 0x97, 0xed, 0x6f, 0x26, 0x6d, 0x55, 0xd1, 0x5c, 0xe8, 0x2f, 0x99, 0x05, 0x93, 0xdf, - 0xf3, 0x93, 0x83, 0x7c, 0x13, 0x97, 0xcb, 0xe3, 0xc3, 0xb9, 0x3f, 0x9e, 0x5b, 0x77, 0xd9, 0xd1, 0x3a, 0xc8, 0x1f, - 0x33, 0xb8, 0x7d, 0xb0, 0x2c, 0x0d, 0xe8, 0x0d, 0x37, 0x6d, 0x8d, 0x25, 0xc9, 0x2f, 0x68, 0x31, 0x74, 0xa1, 0xc8, - 0x0d, 0x5c, 0xe9, 0xe2, 0x73, 0xab, 0x4f, 0xc7, 0x56, 0x84, 0x5d, 0x17, 0x60, 0x79, 0xe3, 0x04, 0xec, 0x5a, 0xc0, - 0x8f, 0x8b, 0x76, 0x76, 0x36, 0xee, 0x17, 0xa9, 0x40, 0xc2, 0x5c, 0xeb, 0x2f, 0x4e, 0xda, 0xac, 0xc8, 0xb5, 0x11, - 0x5d, 0xf5, 0x2b, 0x51, 0x88, 0x34, 0x9e, 0xae, 0x68, 0x28, 0xfc, 0x30, 0x53, 0x27, 0x08, 0x2c, 0x86, 0x85, 0xbb, - 0x74, 0x0f, 0x95, 0xb9, 0x08, 0x55, 0x52, 0x98, 0xbd, 0xcf, 0x73, 0x11, 0x9a, 0x9b, 0x99, 0x42, 0xd1, 0x38, 0x38, - 0x9f, 0xf4, 0x06, 0x6f, 0x3f, 0x1c, 0x3b, 0x6a, 0x7b, 0x1e, 0xb5, 0x93, 0xde, 0xe0, 0x48, 0xfa, 0x4c, 0x54, 0xd8, - 0x9f, 0xa8, 0xb0, 0xbf, 0xa3, 0x2f, 0xa6, 0x81, 0x48, 0x5a, 0xd9, 0x56, 0xd3, 0x96, 0x36, 0x83, 0xf2, 0xf6, 0x4e, - 0x66, 0xa9, 0x60, 0xf0, 0xc5, 0xa4, 0xb6, 0x8c, 0xf9, 0xcb, 0x1c, 0x02, 0x73, 0x08, 0x55, 0x6b, 0x87, 0x57, 0x22, - 0x33, 0xbe, 0xe1, 0x11, 0x4b, 0xa9, 0x39, 0x76, 0xaa, 0xbb, 0xaa, 0x12, 0x7e, 0x56, 0x6b, 0x17, 0xb3, 0x2b, 0x48, - 0x7a, 0x30, 0xe9, 0x45, 0x1f, 0x75, 0x83, 0x23, 0x39, 0x14, 0x44, 0xee, 0x95, 0x98, 0x36, 0xdf, 0x86, 0x6d, 0x2e, - 0xa9, 0x9e, 0xbd, 0x96, 0x10, 0x70, 0x3d, 0x48, 0xb2, 0x37, 0xa8, 0xdc, 0xc5, 0xf6, 0xbb, 0xf2, 0xa8, 0x9d, 0xec, - 0x0d, 0x2e, 0x83, 0xb1, 0xee, 0xef, 0x55, 0x3e, 0x5e, 0xdf, 0x57, 0x9a, 0x8f, 0x87, 0xf2, 0x1c, 0xbc, 0xba, 0x30, - 0xca, 0x28, 0xbf, 0x79, 0xea, 0x0e, 0x8e, 0xb4, 0x32, 0xe0, 0xc8, 0xb0, 0xba, 0x7b, 0xd0, 0x31, 0x47, 0xeb, 0xd3, - 0x7c, 0x0c, 0x1b, 0x52, 0x35, 0xb1, 0x06, 0x69, 0x78, 0xdc, 0x93, 0xee, 0xe0, 0x28, 0x74, 0x24, 0x6f, 0x91, 0xcc, - 0xa3, 0x08, 0xda, 0xd0, 0x38, 0xc9, 0x27, 0xd4, 0x67, 0x79, 0xfb, 0x86, 0x5e, 0xb5, 0xc2, 0x29, 0xab, 0xdd, 0xdb, - 0xa0, 0x74, 0x54, 0x43, 0xe6, 0x4b, 0x29, 0x56, 0xbd, 0xda, 0xdd, 0xb6, 0x0f, 0x36, 0x8f, 0x71, 0xcd, 0x49, 0x9f, - 0x9c, 0x05, 0x56, 0x3e, 0x38, 0x6a, 0x87, 0x4b, 0x18, 0x91, 0xfc, 0xbe, 0xd4, 0x8e, 0x76, 0x30, 0x6c, 0xae, 0x64, - 0x7e, 0x97, 0x12, 0x07, 0xc6, 0x21, 0xaf, 0x05, 0x75, 0xe9, 0x0e, 0xfe, 0xd7, 0x7f, 0xfb, 0x1f, 0xda, 0xc7, 0x7e, - 0xd4, 0x4e, 0xba, 0xa6, 0xaf, 0xa5, 0x55, 0x29, 0x8f, 0xe0, 0x72, 0x9c, 0x3a, 0x28, 0x4c, 0x6f, 0x5b, 0x63, 0xce, - 0xe2, 0x56, 0x12, 0xa6, 0x23, 0x77, 0xb0, 0x19, 0x9b, 0x2a, 0xff, 0xb0, 0x65, 0xc2, 0xa9, 0xab, 0x45, 0x40, 0xaf, - 0xbf, 0xea, 0xd6, 0x05, 0x93, 0xd2, 0x25, 0xb7, 0xb6, 0x7d, 0x07, 0x43, 0xbd, 0xfb, 0x1a, 0xf7, 0x30, 0x64, 0xfa, - 0x83, 0xd3, 0x9a, 0x03, 0x66, 0x8d, 0xeb, 0x17, 0x4a, 0xd7, 0xa9, 0x82, 0x5a, 0xff, 0xe7, 0xbf, 0xff, 0xa7, 0xff, - 0x62, 0x1e, 0x21, 0x56, 0xf5, 0xbf, 0xfe, 0xeb, 0x7f, 0xfc, 0xdf, 0xff, 0xf3, 0x3f, 0x43, 0xfe, 0x99, 0x8e, 0x67, - 0x49, 0xa6, 0xe2, 0xd4, 0xc1, 0x2c, 0xc5, 0x5d, 0x1c, 0x38, 0xd5, 0x36, 0x61, 0x85, 0x60, 0x51, 0xf3, 0x42, 0x86, - 0x53, 0x39, 0xa0, 0xdc, 0x99, 0x1a, 0x3a, 0xb9, 0xc3, 0xcb, 0x9a, 0xa0, 0x1a, 0x28, 0x97, 0x84, 0x5b, 0x1e, 0xb5, - 0x01, 0xdf, 0x0f, 0xbb, 0xc3, 0xc6, 0xaf, 0x96, 0x63, 0x6e, 0xc8, 0x04, 0x4a, 0xca, 0xba, 0xdc, 0x81, 0xd8, 0xca, - 0x1c, 0x1e, 0x83, 0x9e, 0x55, 0x2c, 0x57, 0xaf, 0xd1, 0xa6, 0xff, 0xd3, 0xac, 0x10, 0x6c, 0x04, 0x28, 0x57, 0x7e, - 0x62, 0x19, 0xc6, 0x6e, 0x81, 0xae, 0x98, 0xde, 0x95, 0xb2, 0x17, 0x45, 0xa0, 0xfb, 0x87, 0xff, 0x54, 0xfe, 0x61, - 0x02, 0x1a, 0x99, 0xe3, 0x4d, 0xc2, 0x5b, 0x6d, 0x9e, 0x3f, 0xee, 0x74, 0xa6, 0xb7, 0x68, 0x5e, 0x8f, 0x80, 0x37, - 0x0d, 0x26, 0xe9, 0xd8, 0xee, 0x50, 0xc6, 0xbf, 0x2b, 0x37, 0x76, 0xc7, 0x01, 0x5f, 0xb8, 0xd3, 0x29, 0xcb, 0xdf, - 0xcf, 0xa5, 0x27, 0x95, 0xfd, 0x02, 0x71, 0x6a, 0xed, 0x74, 0xbe, 0xca, 0xed, 0xc9, 0xcd, 0xad, 0x56, 0x3d, 0xd5, - 0x2a, 0xe9, 0xae, 0x5e, 0xcd, 0x62, 0xc7, 0xd9, 0xed, 0x08, 0xf9, 0x3e, 0xc4, 0xbc, 0x93, 0x2e, 0x4e, 0x7a, 0xf3, - 0xaa, 0x7b, 0x21, 0xf2, 0x89, 0x1d, 0x58, 0xa7, 0x21, 0x8d, 0xe8, 0xc8, 0x38, 0xeb, 0xf5, 0x7b, 0x15, 0x34, 0x2f, - 0x93, 0xbd, 0x35, 0x63, 0x69, 0x90, 0x64, 0x40, 0xdd, 0xe9, 0x94, 0x5f, 0xc1, 0x0e, 0x9c, 0x8f, 0xd2, 0x3c, 0x14, - 0x81, 0x24, 0xd8, 0xbe, 0x1d, 0x9e, 0x0f, 0x81, 0x27, 0xe5, 0x73, 0x0b, 0x9e, 0xbe, 0xaa, 0x0a, 0x6e, 0xf3, 0xe6, - 0x05, 0x3a, 0xa5, 0x2f, 0x9b, 0xdb, 0x5d, 0x29, 0xaf, 0xdb, 0xf7, 0x3a, 0xea, 0xfd, 0xb2, 0xe1, 0xae, 0xd2, 0x02, - 0xa9, 0x87, 0xd6, 0xbf, 0x57, 0x72, 0x5d, 0xbd, 0xfd, 0x8b, 0xf0, 0x5c, 0x09, 0xa6, 0xbb, 0x5c, 0x4b, 0x16, 0x42, - 0xad, 0x97, 0xe4, 0xfb, 0xca, 0x64, 0x0a, 0xa7, 0x53, 0x59, 0x11, 0xf5, 0x8f, 0xda, 0x4a, 0xd3, 0x05, 0xee, 0x21, - 0x53, 0x3a, 0x54, 0x06, 0x85, 0xae, 0xa4, 0xb7, 0x82, 0xfa, 0xa5, 0x73, 0x2b, 0xe0, 0x43, 0xe4, 0x83, 0xff, 0x0b, - 0x64, 0xce, 0x91, 0xa6, 0x21, 0x98, 0x00, 0x00}; + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdb, 0x48, 0xb6, 0xe0, 0xf3, + 0xd4, 0x57, 0x40, 0x28, 0xb5, 0x8c, 0x2c, 0x26, 0xc1, 0x45, 0x92, 0x2d, 0x83, 0x4a, 0xb2, 0x65, 0xd9, 0xd5, 0x76, + 0x97, 0xb7, 0xb6, 0xec, 0xda, 0x58, 0x6c, 0x09, 0x02, 0x92, 0x44, 0x96, 0x41, 0x80, 0x05, 0x24, 0xb5, 0x14, 0x89, + 0x1b, 0xf3, 0x01, 0x13, 0x31, 0x11, 0xf3, 0x34, 0x2f, 0x13, 0x73, 0x1f, 0xe6, 0x23, 0xe6, 0xf9, 0x7e, 0xca, 0xfd, + 0x81, 0x99, 0x4f, 0x98, 0x38, 0xb9, 0x00, 0x09, 0x2e, 0xb2, 0x5c, 0x55, 0x7d, 0xef, 0x7d, 0x98, 0xa8, 0x28, 0x99, + 0x48, 0xe4, 0x72, 0xf2, 0xe4, 0xc9, 0xb3, 0x67, 0xe2, 0x78, 0x27, 0x4c, 0x03, 0x7e, 0x3b, 0xa3, 0x56, 0xc4, 0xa7, + 0x71, 0xff, 0x58, 0xfd, 0xa5, 0x7e, 0xd8, 0x3f, 0x8e, 0x59, 0xf2, 0xd1, 0xca, 0x68, 0x4c, 0x58, 0x90, 0x26, 0x56, + 0x94, 0xd1, 0x31, 0x09, 0x7d, 0xee, 0x7b, 0x6c, 0xea, 0x4f, 0xa8, 0xd5, 0xea, 0x1f, 0x4f, 0x29, 0xf7, 0xad, 0x20, + 0xf2, 0xb3, 0x9c, 0x72, 0xf2, 0xe1, 0xfd, 0xd7, 0xcd, 0xa3, 0xfe, 0x71, 0x1e, 0x64, 0x6c, 0xc6, 0x2d, 0xe8, 0x92, + 0x4c, 0xd3, 0x70, 0x1e, 0xd3, 0x7e, 0xab, 0x75, 0x7d, 0x7d, 0xed, 0xfe, 0x9c, 0x7f, 0x11, 0xa4, 0x49, 0xce, 0xad, + 0xa7, 0xe4, 0x9a, 0x25, 0x61, 0x7a, 0x8d, 0x73, 0x4e, 0x9e, 0xba, 0x67, 0x91, 0x1f, 0xa6, 0xd7, 0xef, 0xd2, 0x94, + 0xef, 0xed, 0x39, 0xf2, 0xf1, 0xf6, 0xf4, 0xec, 0x8c, 0x10, 0x72, 0x95, 0xb2, 0xd0, 0x6a, 0x2f, 0x97, 0x55, 0xa1, + 0x9b, 0xf8, 0x9c, 0x5d, 0x51, 0xd9, 0x04, 0xed, 0xed, 0xd9, 0x7e, 0x98, 0xce, 0x38, 0x0d, 0xcf, 0xf8, 0x6d, 0x4c, + 0xcf, 0x22, 0x4a, 0x79, 0x6e, 0xb3, 0xc4, 0x7a, 0x9a, 0x06, 0xf3, 0x29, 0x4d, 0xb8, 0x3b, 0xcb, 0x52, 0x9e, 0x02, + 0x24, 0x7b, 0x7b, 0x76, 0x46, 0x67, 0xb1, 0x1f, 0x50, 0x78, 0x7f, 0x7a, 0x76, 0x56, 0xb5, 0xa8, 0x2a, 0xe1, 0x84, + 0x93, 0xb3, 0xdb, 0xe9, 0x65, 0x1a, 0x3b, 0x08, 0x47, 0x9c, 0x24, 0xf4, 0xda, 0xfa, 0x8e, 0xfa, 0x1f, 0x5f, 0xf9, + 0xb3, 0x5e, 0x10, 0xfb, 0x79, 0x6e, 0x9d, 0xf0, 0x85, 0x98, 0x42, 0x36, 0x0f, 0x78, 0x9a, 0x39, 0x1c, 0x53, 0xcc, + 0xd0, 0x82, 0x8d, 0x1d, 0x1e, 0xb1, 0xdc, 0x3d, 0xdf, 0x0d, 0xf2, 0xfc, 0x1d, 0xcd, 0xe7, 0x31, 0xdf, 0x25, 0x3b, + 0x6d, 0xcc, 0x76, 0x08, 0x49, 0x38, 0xe2, 0x51, 0x96, 0x5e, 0x5b, 0xcf, 0xb2, 0x2c, 0xcd, 0x1c, 0xfb, 0xf4, 0xec, + 0x4c, 0xd6, 0xb0, 0x58, 0x6e, 0x25, 0x29, 0xb7, 0xca, 0xfe, 0xfc, 0xcb, 0x98, 0xba, 0xd6, 0x87, 0x9c, 0x5a, 0x17, + 0xf3, 0x24, 0xf7, 0xc7, 0xf4, 0xf4, 0xec, 0xec, 0xc2, 0x4a, 0x33, 0xeb, 0x22, 0xc8, 0xf3, 0x0b, 0x8b, 0x25, 0x39, + 0xa7, 0x7e, 0xe8, 0xda, 0xa8, 0x27, 0x06, 0x0b, 0xf2, 0xfc, 0x3d, 0xbd, 0xe1, 0x84, 0x63, 0xf1, 0xc8, 0x09, 0x2d, + 0x26, 0x94, 0x5b, 0x79, 0x39, 0x2f, 0x07, 0x2d, 0x62, 0xca, 0x2d, 0x4e, 0xc4, 0xfb, 0xb4, 0x27, 0x71, 0x4f, 0xe5, + 0x23, 0xef, 0xb1, 0xb1, 0x93, 0xf3, 0xbd, 0x3d, 0x5e, 0xe2, 0x19, 0xc9, 0xa9, 0x59, 0x8c, 0xd0, 0x1d, 0x5d, 0xb6, + 0xb7, 0x47, 0xdd, 0x98, 0x26, 0x13, 0x1e, 0x11, 0x42, 0x3a, 0x3d, 0xb6, 0xb7, 0xe7, 0x70, 0x12, 0x71, 0x77, 0x42, + 0xb9, 0x43, 0x11, 0xc2, 0x55, 0xeb, 0xbd, 0x3d, 0x47, 0x22, 0x21, 0x25, 0x12, 0x71, 0x35, 0x1c, 0x23, 0x57, 0x61, + 0xff, 0xec, 0x36, 0x09, 0x1c, 0x13, 0x7e, 0x84, 0xd9, 0xde, 0x5e, 0xc4, 0xdd, 0x1c, 0x7a, 0xc4, 0x1c, 0xa1, 0x22, + 0xa3, 0x7c, 0x9e, 0x25, 0x16, 0x2f, 0x78, 0x7a, 0xc6, 0x33, 0x96, 0x4c, 0x1c, 0xb4, 0xd0, 0x65, 0x46, 0xc3, 0xa2, + 0x90, 0xe0, 0xbe, 0xe3, 0x24, 0x21, 0x7d, 0x18, 0xf1, 0x84, 0x3b, 0xb0, 0x8a, 0xe9, 0xd8, 0x4a, 0x08, 0xb1, 0x73, + 0xd1, 0xd6, 0x1e, 0x24, 0x5e, 0xd2, 0xb0, 0x6d, 0x2c, 0xa1, 0xc4, 0x09, 0x47, 0xf8, 0x23, 0x71, 0x12, 0xec, 0xba, + 0x2e, 0x47, 0xa4, 0xbf, 0xd0, 0x58, 0x49, 0x8c, 0x79, 0x0e, 0x92, 0x61, 0x7b, 0xe4, 0x71, 0x37, 0xa3, 0xe1, 0x3c, + 0xa0, 0x8e, 0xc3, 0x70, 0x8e, 0x53, 0x44, 0xfa, 0xac, 0xe1, 0x64, 0xa4, 0x0f, 0xcb, 0x9d, 0xd5, 0xd7, 0x9a, 0x90, + 0x9d, 0x36, 0x52, 0x30, 0x66, 0x1a, 0x40, 0xc0, 0xb0, 0x82, 0x27, 0x23, 0xc4, 0x4e, 0xe6, 0xd3, 0x4b, 0x9a, 0xd9, + 0x65, 0xb5, 0x5e, 0x8d, 0x2c, 0xe6, 0x39, 0xb5, 0x82, 0x3c, 0xb7, 0xc6, 0xf3, 0x24, 0xe0, 0x2c, 0x4d, 0x2c, 0xbb, + 0x91, 0x35, 0x6c, 0x49, 0x0e, 0x25, 0x35, 0xd8, 0xa8, 0x40, 0x4e, 0x8e, 0x1a, 0xc9, 0x30, 0x6d, 0x74, 0x46, 0x18, + 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0x4f, 0x38, 0xcc, 0x52, 0x4c, 0x31, 0xe7, + 0x83, 0xc4, 0x5d, 0xdf, 0x28, 0x84, 0xbb, 0x53, 0x7f, 0xe6, 0x50, 0xd2, 0xa7, 0x82, 0xb8, 0xfc, 0x24, 0x00, 0x58, + 0x6b, 0xeb, 0x36, 0xa0, 0x1e, 0x75, 0x2b, 0x92, 0x42, 0x1e, 0x77, 0xc7, 0x69, 0xf6, 0xcc, 0x0f, 0x22, 0x68, 0x57, + 0x12, 0x4c, 0xa8, 0xf7, 0x5b, 0x90, 0x51, 0x9f, 0xd3, 0x67, 0x31, 0x85, 0x27, 0xc7, 0x16, 0x2d, 0x6d, 0x84, 0x73, + 0xf2, 0xd4, 0x8d, 0x19, 0x7f, 0x9d, 0x26, 0x01, 0xed, 0xe5, 0x06, 0x75, 0x31, 0x58, 0xf7, 0x13, 0xce, 0x33, 0x76, + 0x39, 0xe7, 0xd4, 0xb1, 0x13, 0xa8, 0x61, 0xe3, 0x1c, 0x61, 0xe6, 0x72, 0x7a, 0xc3, 0x4f, 0xd3, 0x84, 0xd3, 0x84, + 0x13, 0xaa, 0x91, 0x8a, 0x13, 0xd7, 0x9f, 0xcd, 0x68, 0x12, 0x9e, 0x46, 0x2c, 0x0e, 0x1d, 0x86, 0x0a, 0x54, 0xe0, + 0x80, 0x13, 0x98, 0x23, 0xe9, 0x27, 0x1e, 0xfc, 0xd9, 0x3e, 0x1b, 0x87, 0x93, 0xbe, 0xd8, 0x14, 0x94, 0xd8, 0x76, + 0x6f, 0x9c, 0x66, 0x8e, 0x9a, 0x81, 0x95, 0x8e, 0x2d, 0x0e, 0x63, 0xbc, 0x9b, 0xc7, 0x34, 0x47, 0xb4, 0x41, 0x58, + 0xb9, 0x8c, 0x0a, 0xc1, 0xef, 0x80, 0xe2, 0x0b, 0xe4, 0x24, 0xc8, 0x4b, 0x7a, 0x57, 0x7e, 0x66, 0xfd, 0xa8, 0x76, + 0xd4, 0xcf, 0x9a, 0x9b, 0x85, 0x9c, 0xfc, 0xec, 0xf2, 0x6c, 0x9e, 0x73, 0x1a, 0xbe, 0xbf, 0x9d, 0xd1, 0x1c, 0x3f, + 0xe7, 0x24, 0xe4, 0x83, 0x90, 0xbb, 0x74, 0x3a, 0xe3, 0xb7, 0x67, 0x82, 0x31, 0x7a, 0xb6, 0x8d, 0xe7, 0x50, 0x33, + 0xa3, 0x7e, 0x00, 0xcc, 0x4c, 0x61, 0xeb, 0x6d, 0x1a, 0xdf, 0x8e, 0x59, 0x1c, 0x9f, 0xcd, 0x67, 0xb3, 0x34, 0xe3, + 0x98, 0x73, 0xb2, 0xe0, 0x69, 0x85, 0x1b, 0x58, 0xcc, 0x45, 0x7e, 0xcd, 0x78, 0x10, 0x39, 0x1c, 0x2d, 0x02, 0x3f, + 0xa7, 0xd6, 0x93, 0x34, 0x8d, 0xa9, 0x0f, 0xb3, 0x4e, 0x06, 0xcf, 0xb9, 0x97, 0xcc, 0xe3, 0xb8, 0x77, 0x99, 0x51, + 0xff, 0x63, 0x4f, 0xbc, 0x7e, 0x73, 0xf9, 0x33, 0x0d, 0xb8, 0x27, 0x7e, 0x9f, 0x64, 0x99, 0x7f, 0x0b, 0x15, 0x09, + 0x81, 0x6a, 0x83, 0xc4, 0xfb, 0xeb, 0xd9, 0x9b, 0xd7, 0xae, 0xdc, 0x25, 0x6c, 0x7c, 0xeb, 0x24, 0xe5, 0xce, 0x4b, + 0x0a, 0x3c, 0xce, 0xd2, 0xe9, 0xca, 0xd0, 0x12, 0x6d, 0x49, 0x6f, 0x0b, 0x08, 0x94, 0x24, 0x3b, 0xb2, 0x6b, 0x13, + 0x82, 0xd7, 0x82, 0xe8, 0xe1, 0x25, 0xd1, 0xe3, 0xce, 0xe3, 0xd8, 0x93, 0xc5, 0x4e, 0x82, 0xee, 0x86, 0x96, 0x67, + 0xb7, 0x0b, 0x4a, 0x04, 0x9c, 0x33, 0x10, 0x31, 0x00, 0x63, 0xe0, 0xf3, 0x20, 0x5a, 0x50, 0xd1, 0x59, 0xa1, 0x21, + 0xa6, 0x45, 0x81, 0x9f, 0x95, 0x04, 0xcf, 0x01, 0x10, 0xc1, 0xa9, 0x08, 0x5f, 0x2e, 0x61, 0xc2, 0x08, 0xff, 0x95, + 0x2c, 0x7c, 0x3d, 0x1f, 0x6f, 0xa7, 0x8d, 0x61, 0x63, 0x7a, 0x92, 0xbd, 0xe0, 0x20, 0x4d, 0xae, 0x68, 0xc6, 0x69, + 0xe6, 0x71, 0x8e, 0x33, 0x3a, 0x8e, 0x01, 0x8c, 0x9d, 0x0e, 0x8e, 0xfc, 0xfc, 0x34, 0xf2, 0x93, 0x09, 0x0d, 0xbd, + 0x67, 0xbc, 0xc0, 0x94, 0x13, 0x7b, 0xcc, 0x12, 0x3f, 0x66, 0xbf, 0xd2, 0xd0, 0x56, 0x02, 0xe1, 0x99, 0x45, 0x6f, + 0x38, 0x4d, 0xc2, 0xdc, 0x7a, 0xfe, 0xfe, 0xd5, 0x4b, 0xb5, 0x94, 0x35, 0x19, 0x81, 0x16, 0xf9, 0x7c, 0x46, 0x33, + 0x07, 0x61, 0x25, 0x23, 0x9e, 0x31, 0xc1, 0x1f, 0x5f, 0xf9, 0x33, 0x59, 0xc2, 0xf2, 0x0f, 0xb3, 0xd0, 0xe7, 0xf4, + 0x2d, 0x4d, 0x42, 0x96, 0x4c, 0xc8, 0x4e, 0x47, 0x96, 0x47, 0xbe, 0x7a, 0x11, 0x96, 0x45, 0xe7, 0xbb, 0xcf, 0x62, + 0x31, 0xf3, 0xf2, 0x71, 0xee, 0xa0, 0x22, 0xe7, 0x3e, 0x67, 0x81, 0xe5, 0x87, 0xe1, 0x8b, 0x84, 0x71, 0x26, 0x00, + 0xcc, 0x60, 0x81, 0x80, 0x4a, 0xa9, 0x94, 0x16, 0x1a, 0x70, 0x07, 0x61, 0xc7, 0x51, 0x32, 0x20, 0x42, 0x6a, 0xc5, + 0xf6, 0xf6, 0x2a, 0x8e, 0x3f, 0xa0, 0x9e, 0x7c, 0x49, 0x86, 0x23, 0xe4, 0xce, 0xe6, 0x39, 0x2c, 0xb5, 0x1e, 0x02, + 0x04, 0x4c, 0x7a, 0x99, 0xd3, 0xec, 0x8a, 0x86, 0x25, 0x79, 0xe4, 0x0e, 0x5a, 0xac, 0x8c, 0xa1, 0x76, 0x06, 0x27, + 0xc3, 0x51, 0xcf, 0x64, 0xdd, 0x54, 0x91, 0x7a, 0x96, 0xce, 0x68, 0xc6, 0x19, 0xcd, 0x4b, 0x6e, 0xe2, 0x80, 0x20, + 0x2d, 0x39, 0x4a, 0x4e, 0xf4, 0xfc, 0x66, 0x0e, 0xc3, 0x14, 0xd5, 0x78, 0x86, 0x96, 0xb5, 0xcf, 0xae, 0x84, 0xd0, + 0xc8, 0x31, 0x43, 0x98, 0x4b, 0x48, 0x73, 0x84, 0x0a, 0x84, 0xb9, 0x06, 0x57, 0x72, 0x23, 0x35, 0xda, 0x2d, 0x48, + 0x6b, 0xf2, 0x57, 0x21, 0xad, 0x81, 0xa7, 0xf9, 0x9c, 0xee, 0xed, 0x39, 0xd4, 0x2d, 0xc9, 0x82, 0xec, 0x74, 0xd4, + 0x1a, 0x19, 0xc8, 0xda, 0x02, 0x36, 0x0c, 0xcc, 0x31, 0x45, 0x78, 0x87, 0xba, 0x49, 0x7a, 0x12, 0x04, 0x34, 0xcf, + 0xd3, 0x6c, 0x6f, 0x6f, 0x47, 0xd4, 0x2f, 0x15, 0x0a, 0x58, 0xc3, 0x37, 0xd7, 0x49, 0x05, 0x01, 0xaa, 0x84, 0xac, + 0x12, 0x0d, 0x1c, 0x44, 0x95, 0xd0, 0x39, 0xec, 0x81, 0xd6, 0x3d, 0x3c, 0xfb, 0xfc, 0xdc, 0x6e, 0x70, 0xac, 0xd0, + 0x30, 0xa1, 0x7a, 0xe8, 0xdb, 0xa7, 0x54, 0x6a, 0x57, 0x42, 0xf7, 0x58, 0xc3, 0x8c, 0xdc, 0x41, 0x6e, 0x48, 0xc7, + 0x2c, 0x31, 0xa6, 0x5d, 0x03, 0x09, 0x73, 0x9c, 0xa3, 0xc2, 0x58, 0xd0, 0x8d, 0x5d, 0x0b, 0xb5, 0x46, 0xae, 0xdc, + 0x62, 0x22, 0x54, 0x09, 0x63, 0x19, 0x87, 0x74, 0x54, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x54, 0x00, 0x3a, 0xe4, 0xa3, + 0x9e, 0x7a, 0x4f, 0x72, 0x89, 0xb9, 0x8c, 0xfe, 0x32, 0xa7, 0x39, 0x97, 0x74, 0xec, 0x70, 0x9c, 0x62, 0x06, 0xfc, + 0x3a, 0x4d, 0xc6, 0x6c, 0x32, 0xcf, 0x40, 0xe3, 0x81, 0xcd, 0x48, 0x93, 0xf9, 0x94, 0xea, 0xa7, 0x4d, 0xb0, 0xbd, + 0x99, 0x81, 0x4c, 0xcc, 0x81, 0xa6, 0xef, 0x26, 0x27, 0x80, 0x95, 0xa3, 0xe5, 0xf2, 0xaf, 0xba, 0x93, 0x6a, 0x29, + 0x4b, 0x2d, 0x6d, 0x65, 0x4d, 0x28, 0x47, 0x4a, 0x26, 0xef, 0x74, 0x14, 0xf8, 0x7c, 0x44, 0x76, 0xda, 0x25, 0x0d, + 0x2b, 0xac, 0x4a, 0x70, 0x24, 0x12, 0xdf, 0xc8, 0xae, 0x90, 0x10, 0xf1, 0x35, 0x72, 0x71, 0xa3, 0x35, 0x4a, 0x8d, + 0xc8, 0x10, 0x94, 0x0d, 0x37, 0x1a, 0x6d, 0x23, 0x27, 0xcd, 0x0f, 0x1c, 0xbe, 0xfe, 0xae, 0x62, 0x1b, 0x57, 0x75, + 0xb6, 0xb1, 0x32, 0x0d, 0x7b, 0x56, 0x36, 0xb1, 0x4b, 0x2a, 0x53, 0x1b, 0xbd, 0x7a, 0x85, 0x99, 0x00, 0xa6, 0x9a, + 0x92, 0xd1, 0xc5, 0x6b, 0x7f, 0x4a, 0x73, 0x87, 0x22, 0xbc, 0xad, 0x82, 0x24, 0x4f, 0xa8, 0x32, 0x32, 0x64, 0x67, + 0x0e, 0xb2, 0x93, 0x21, 0xa9, 0x9a, 0xd5, 0x37, 0x5c, 0x8e, 0xe9, 0x30, 0x1f, 0x55, 0x1a, 0x9d, 0x31, 0x79, 0x21, + 0x94, 0x15, 0x7d, 0x6b, 0xfc, 0xc9, 0x32, 0x89, 0x34, 0xa1, 0x39, 0xe4, 0x08, 0xef, 0xb4, 0x57, 0x57, 0x52, 0xd7, + 0xaa, 0xe6, 0x38, 0x1c, 0xc1, 0x3a, 0x08, 0x91, 0xe1, 0xb2, 0x5c, 0xfc, 0x5b, 0xdb, 0x69, 0x80, 0xb6, 0x33, 0x20, + 0x0c, 0x77, 0x1c, 0xfb, 0xdc, 0xe9, 0xb4, 0xda, 0xa0, 0x8e, 0x5e, 0x51, 0x90, 0x28, 0x08, 0xad, 0x4f, 0x85, 0xba, + 0xf3, 0x24, 0x8f, 0xd8, 0x98, 0x3b, 0x01, 0x17, 0x2c, 0x85, 0xc6, 0x39, 0xb5, 0x78, 0x4d, 0x29, 0x16, 0xec, 0x26, + 0x00, 0x62, 0x2b, 0x35, 0x30, 0xaa, 0x21, 0x15, 0x6c, 0x0b, 0xb8, 0x43, 0xa5, 0x50, 0x57, 0x5c, 0x46, 0xd7, 0x66, + 0xa0, 0x34, 0x76, 0x06, 0xb2, 0x47, 0x4f, 0x31, 0x03, 0x66, 0xe8, 0xad, 0xcc, 0x33, 0x39, 0x84, 0x2a, 0xe4, 0x2e, + 0x4f, 0x5f, 0xa6, 0xd7, 0x34, 0x3b, 0xf5, 0x01, 0x78, 0x4f, 0x36, 0x2f, 0xa4, 0x20, 0x10, 0xfc, 0x9e, 0xf7, 0x34, + 0xbd, 0x9c, 0x8b, 0x89, 0xbf, 0xcd, 0xd2, 0x29, 0xcb, 0x29, 0xa8, 0x6b, 0x12, 0xff, 0x09, 0xec, 0x33, 0xb1, 0x21, + 0x41, 0xd8, 0xd0, 0x92, 0xbe, 0x4e, 0x5e, 0xd6, 0xe9, 0xeb, 0x7c, 0xf7, 0xd9, 0x44, 0x33, 0xc0, 0xfa, 0x36, 0x46, + 0xd8, 0x51, 0x46, 0x85, 0x21, 0xe7, 0xdc, 0x08, 0x29, 0x11, 0xbf, 0x5c, 0x72, 0xc3, 0x76, 0xab, 0x29, 0x8c, 0x54, + 0x6e, 0x1b, 0x54, 0xf8, 0x61, 0x08, 0xaa, 0x5d, 0x96, 0xc6, 0xb1, 0x21, 0xaa, 0x30, 0xeb, 0x95, 0xc2, 0xe9, 0x7c, + 0xf7, 0xd9, 0xd9, 0x5d, 0xf2, 0x09, 0xde, 0x9b, 0x22, 0x4a, 0x03, 0x9a, 0x84, 0x34, 0x03, 0x5b, 0xd2, 0x58, 0x2d, + 0x25, 0x65, 0x4f, 0xd3, 0x24, 0xa1, 0x01, 0xa7, 0x21, 0x98, 0x2a, 0x8c, 0x70, 0x37, 0x4a, 0x73, 0x5e, 0x16, 0x56, + 0xd0, 0x33, 0x03, 0x7a, 0xe6, 0x06, 0x7e, 0x1c, 0x3b, 0xd2, 0x2c, 0x99, 0xa6, 0x57, 0x74, 0x03, 0xd4, 0xbd, 0x1a, + 0xc8, 0x65, 0x37, 0xd4, 0xe8, 0x86, 0xba, 0xf9, 0x2c, 0x66, 0x01, 0x2d, 0x45, 0xd7, 0x99, 0xcb, 0x92, 0x90, 0xde, + 0x00, 0x1f, 0x41, 0xfd, 0x7e, 0xbf, 0x8d, 0x3b, 0xa8, 0x90, 0x08, 0x5f, 0xac, 0x21, 0xf6, 0x0e, 0xa1, 0x09, 0x44, + 0x46, 0xfa, 0x8b, 0x8d, 0x6c, 0x0d, 0x19, 0x92, 0x92, 0x69, 0xf3, 0x4a, 0x72, 0x67, 0x84, 0x43, 0x1a, 0x53, 0x4e, + 0x35, 0x37, 0x07, 0x25, 0x5a, 0x6e, 0xdd, 0x77, 0x25, 0xfe, 0x4a, 0x72, 0xd2, 0xbb, 0x4c, 0xaf, 0x79, 0x5e, 0x9a, + 0xeb, 0xd5, 0xf2, 0x54, 0xd8, 0x1e, 0x70, 0xb9, 0x3c, 0x3e, 0xe7, 0x7e, 0x10, 0x49, 0x3b, 0xdd, 0x59, 0x9b, 0x52, + 0xd5, 0x87, 0xe2, 0xec, 0xe5, 0x26, 0x7a, 0xa2, 0xc1, 0xdc, 0x84, 0x82, 0x33, 0xc5, 0x14, 0x28, 0x98, 0x7e, 0x72, + 0xd9, 0x4e, 0xfd, 0x38, 0xbe, 0xf4, 0x83, 0x8f, 0x75, 0xea, 0xaf, 0xc8, 0x80, 0xac, 0x72, 0x63, 0xe3, 0x95, 0xc1, + 0xb2, 0xcc, 0x79, 0x6b, 0x2e, 0x5d, 0xdb, 0x28, 0xce, 0x4e, 0xbb, 0x22, 0xfb, 0xfa, 0x42, 0x6f, 0xa5, 0x76, 0x01, + 0x11, 0x53, 0x33, 0x73, 0x80, 0x0b, 0x7c, 0x92, 0xe2, 0x34, 0x3f, 0x50, 0x74, 0x07, 0x06, 0x47, 0xb1, 0x02, 0x08, + 0x47, 0x8b, 0x22, 0x64, 0xf9, 0x76, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x35, 0x46, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x53, + 0x5a, 0x73, 0x09, 0x99, 0xd2, 0x27, 0x34, 0xa3, 0xf9, 0x06, 0x74, 0x17, 0x41, 0xef, 0x6f, 0xe4, 0x2b, 0xd0, 0xca, + 0x00, 0x8a, 0xbc, 0x67, 0xaa, 0x13, 0x35, 0x0a, 0x50, 0x3c, 0x95, 0x09, 0x91, 0x9b, 0xd6, 0x2c, 0x48, 0xa5, 0xb1, + 0x4b, 0x23, 0x5c, 0xb1, 0xdc, 0x8c, 0x38, 0x8e, 0x93, 0x83, 0x11, 0xa7, 0x75, 0xfb, 0x6a, 0x12, 0xf9, 0xda, 0x24, + 0x72, 0xd7, 0x30, 0xb4, 0x50, 0x45, 0xcb, 0x46, 0x73, 0x8f, 0x73, 0x64, 0xd6, 0x02, 0x7d, 0xd5, 0x05, 0x06, 0x8d, + 0x4a, 0x7e, 0x1b, 0x13, 0x8e, 0x33, 0x65, 0xe5, 0x28, 0x52, 0x03, 0x8e, 0x51, 0x35, 0x49, 0x91, 0xdc, 0x1b, 0x35, + 0x93, 0x37, 0xc5, 0x19, 0x5a, 0x51, 0xee, 0x8b, 0x42, 0x21, 0x89, 0x22, 0xb5, 0x38, 0x35, 0xad, 0xd8, 0x40, 0x0b, + 0x4e, 0x89, 0xd2, 0x84, 0xa5, 0xe2, 0xb3, 0x8a, 0x9c, 0xb2, 0xdf, 0x1d, 0x42, 0xd2, 0x0a, 0x37, 0x35, 0x95, 0x52, + 0xeb, 0x56, 0x29, 0xc2, 0x91, 0x56, 0x4a, 0xb3, 0x6a, 0xe2, 0x84, 0xd8, 0xda, 0x27, 0x61, 0x0f, 0x16, 0x35, 0xbb, + 0xd0, 0x33, 0xaa, 0x15, 0x1e, 0xf0, 0xd4, 0x6c, 0x13, 0xbe, 0x37, 0x11, 0x4d, 0xad, 0x1f, 0x03, 0xe3, 0x59, 0x0d, + 0xe3, 0x06, 0x6a, 0x53, 0xc9, 0xbb, 0xd2, 0x11, 0x89, 0xea, 0x8d, 0x1d, 0x8a, 0x33, 0xb9, 0x10, 0x6b, 0x58, 0x5c, + 0x55, 0x3e, 0x05, 0x11, 0x82, 0x19, 0x9b, 0x83, 0x7a, 0x67, 0x4a, 0x08, 0x07, 0x80, 0x67, 0xcb, 0xe5, 0x1a, 0xd9, + 0x6d, 0xd4, 0x41, 0x91, 0x5b, 0x59, 0x86, 0xcb, 0xe5, 0x33, 0x8e, 0x1c, 0xa5, 0xfd, 0x62, 0x8a, 0x06, 0x9a, 0xe7, + 0x9e, 0xbc, 0x84, 0x5a, 0x42, 0x19, 0xad, 0x4a, 0x4a, 0xb3, 0xa1, 0x4e, 0xb5, 0xf5, 0x85, 0xe2, 0x06, 0xe3, 0x3e, + 0x5d, 0xe3, 0x5f, 0xa2, 0x50, 0x09, 0xea, 0x6a, 0xca, 0xa7, 0xaa, 0x6b, 0x86, 0x10, 0xf2, 0x72, 0x61, 0xc9, 0xec, + 0x6c, 0x32, 0x2e, 0xf7, 0xf6, 0x72, 0xa3, 0xa3, 0xf3, 0x92, 0x51, 0xfc, 0xec, 0x80, 0x50, 0xce, 0x6f, 0x13, 0xa1, + 0xbd, 0xfc, 0xac, 0xc5, 0xd0, 0x9a, 0x69, 0xda, 0xee, 0x81, 0x4d, 0xee, 0x5f, 0xfb, 0x8c, 0x5b, 0x65, 0x2f, 0xd2, + 0x26, 0x77, 0x28, 0x5a, 0x28, 0x65, 0xc3, 0xcd, 0x28, 0xa8, 0x8f, 0xc0, 0x15, 0xb4, 0x12, 0x2d, 0x09, 0x3f, 0x88, + 0x28, 0xf8, 0x83, 0xb5, 0x1e, 0x51, 0xda, 0x86, 0x3b, 0x4a, 0x8e, 0xa8, 0x8e, 0x37, 0xc3, 0x5e, 0xac, 0x36, 0xaf, + 0xd9, 0x02, 0x33, 0x9a, 0x8d, 0xd3, 0x6c, 0xaa, 0xdf, 0x15, 0x2b, 0xcf, 0x8a, 0x37, 0xb2, 0xb1, 0xb3, 0xb1, 0x6f, + 0x65, 0x01, 0xf4, 0x56, 0x0c, 0xef, 0xca, 0x64, 0xaf, 0x09, 0xd3, 0x52, 0xfe, 0x4a, 0xb7, 0xa0, 0xa6, 0xcc, 0xdc, + 0x34, 0xf1, 0x95, 0x4f, 0xb5, 0x27, 0xdd, 0x26, 0x3b, 0x9d, 0x5e, 0x69, 0xf7, 0x69, 0x6a, 0xe8, 0x49, 0xf7, 0x86, + 0x12, 0xaa, 0xe9, 0x3c, 0x0e, 0x15, 0xb0, 0x0c, 0x61, 0xaa, 0xe8, 0xe8, 0x9a, 0xc5, 0x71, 0x55, 0xfa, 0x39, 0x9c, + 0x3d, 0x57, 0x9c, 0x3d, 0xd5, 0x9c, 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd9, 0x5d, 0xd5, 0x3c, 0x5d, 0xdb, 0x9e, 0xa9, + 0xe4, 0xe9, 0xb9, 0xb0, 0xa5, 0x61, 0xbc, 0xb9, 0x86, 0x00, 0x95, 0xba, 0xd7, 0x47, 0x47, 0xb9, 0x62, 0xc0, 0x08, + 0x94, 0x9e, 0x4c, 0x6a, 0xba, 0x29, 0x3e, 0x3a, 0x08, 0xe7, 0x05, 0x2d, 0x29, 0xfb, 0xe4, 0x19, 0xf8, 0xea, 0x8c, + 0xe9, 0x80, 0x18, 0x13, 0xc5, 0x9f, 0xa5, 0x46, 0xe9, 0xd9, 0x31, 0x35, 0xbb, 0x5c, 0xcf, 0x0e, 0x78, 0x7d, 0x35, + 0xbb, 0xf0, 0x6e, 0x6e, 0x2f, 0xa6, 0xc7, 0xca, 0xe9, 0x55, 0xeb, 0xbd, 0x5c, 0x3a, 0x2b, 0x25, 0xe0, 0xc6, 0x57, + 0x46, 0x4a, 0x56, 0xf6, 0x0e, 0x3c, 0xc0, 0xc4, 0x0c, 0x14, 0x14, 0x72, 0xd2, 0xa5, 0x90, 0x7b, 0xf9, 0x29, 0x27, + 0x8f, 0xf0, 0xd6, 0xcb, 0xf6, 0xa7, 0xe9, 0x74, 0x06, 0xfa, 0xd8, 0x0a, 0x49, 0x4f, 0xa8, 0x1a, 0xb0, 0x7a, 0x5f, + 0x6c, 0x28, 0xab, 0xb5, 0x11, 0xfb, 0xb1, 0x46, 0x4d, 0xa5, 0xcd, 0xbc, 0xd3, 0x2e, 0xe6, 0x65, 0x51, 0xc9, 0x38, + 0x36, 0x39, 0x56, 0x4e, 0x57, 0xdd, 0x32, 0xfa, 0xc5, 0x1b, 0x87, 0x49, 0x3e, 0xcc, 0x80, 0xd7, 0x19, 0xec, 0x47, + 0x93, 0xbb, 0xb9, 0xfe, 0x45, 0x85, 0x9c, 0x45, 0xb1, 0x82, 0xbe, 0x45, 0x51, 0x3c, 0x53, 0x76, 0x36, 0x7e, 0xb6, + 0xdd, 0x20, 0xae, 0xde, 0x29, 0x7b, 0x71, 0x38, 0xc2, 0xcf, 0xd6, 0xb5, 0x47, 0xb2, 0x98, 0xa6, 0x21, 0xf5, 0xec, + 0x74, 0x46, 0x13, 0xbb, 0x00, 0xef, 0xaa, 0x5a, 0xfc, 0x39, 0x77, 0x16, 0xef, 0xea, 0x6e, 0x56, 0xef, 0x59, 0x01, + 0x2e, 0xb0, 0x1f, 0xd7, 0x1d, 0xb0, 0xdf, 0xd2, 0x2c, 0x17, 0xba, 0x68, 0xa9, 0xd6, 0xfe, 0x58, 0x09, 0xa6, 0x1f, + 0xbd, 0xad, 0xf5, 0x2b, 0x2b, 0xc4, 0xee, 0xb8, 0x0f, 0xdd, 0x7d, 0x1b, 0x09, 0xf7, 0xf0, 0x37, 0x6a, 0xc7, 0xff, + 0xa2, 0xdd, 0xc3, 0x67, 0xe4, 0x97, 0xba, 0x77, 0x78, 0xc6, 0xc9, 0xd9, 0xe0, 0x4c, 0x1b, 0xcd, 0x69, 0xcc, 0x82, + 0x5b, 0xc7, 0x8e, 0x19, 0x6f, 0x42, 0x08, 0xce, 0xc6, 0x0b, 0xf9, 0x02, 0xfc, 0x8a, 0xc2, 0xad, 0x5d, 0x68, 0x73, + 0x0f, 0x33, 0x4e, 0xec, 0xdd, 0x98, 0xf1, 0x5d, 0x1b, 0xdf, 0x92, 0x0b, 0xf8, 0xb1, 0xbb, 0x70, 0x5e, 0xf9, 0x3c, + 0x72, 0x33, 0x3f, 0x09, 0xd3, 0xa9, 0x83, 0x1a, 0xb6, 0x8d, 0xdc, 0x5c, 0x98, 0x1c, 0x8f, 0x51, 0xb1, 0x7b, 0x81, + 0xcf, 0x38, 0xb1, 0x07, 0x76, 0xe3, 0x16, 0xbf, 0xe2, 0xe4, 0xe2, 0x78, 0x77, 0x71, 0xc6, 0x8b, 0xfe, 0x05, 0x3e, + 0x29, 0x3d, 0xf7, 0xf8, 0x35, 0x71, 0x10, 0xe9, 0x9f, 0x28, 0x68, 0x4e, 0xd3, 0xa9, 0xf4, 0xe0, 0xdb, 0x08, 0xbf, + 0x13, 0xf1, 0x95, 0x8a, 0xdd, 0xa8, 0x10, 0xcb, 0x0e, 0xb1, 0x53, 0xe1, 0x25, 0xb0, 0xf7, 0xf6, 0x8c, 0xb2, 0x52, + 0x59, 0xc0, 0xa7, 0x9c, 0xd4, 0x6c, 0x72, 0xfc, 0x52, 0x44, 0x6a, 0x4e, 0xb9, 0x93, 0x20, 0xdd, 0x8d, 0xa3, 0xdd, + 0xd1, 0x6a, 0x6f, 0x26, 0x43, 0xe9, 0x64, 0x70, 0x19, 0xa7, 0x99, 0xcf, 0xd3, 0x6c, 0x84, 0x4c, 0x05, 0x04, 0xff, + 0x8d, 0x5c, 0x0c, 0xad, 0xff, 0xf4, 0xc5, 0x4f, 0xe3, 0x9f, 0xb2, 0xd1, 0x05, 0xfe, 0x40, 0x5a, 0xc7, 0xce, 0xc0, + 0x73, 0x76, 0x9a, 0xcd, 0xe5, 0x4f, 0xad, 0xe1, 0xdf, 0xfd, 0xe6, 0xaf, 0x27, 0xcd, 0x1f, 0x47, 0x68, 0xe9, 0xfc, + 0xd4, 0x1a, 0x0c, 0xd5, 0xd3, 0xf0, 0xef, 0xfd, 0x9f, 0xf2, 0xd1, 0x57, 0xb2, 0x70, 0x17, 0xa1, 0xd6, 0x04, 0x4f, + 0x38, 0x69, 0x35, 0x9b, 0xfd, 0xd6, 0x04, 0x4f, 0x39, 0x69, 0xc1, 0xbf, 0xd7, 0xe4, 0x1d, 0x9d, 0x3c, 0xbb, 0x99, + 0x39, 0x17, 0xfd, 0xe5, 0xee, 0xe2, 0x6f, 0x05, 0xf4, 0x3a, 0xfc, 0xfb, 0x4f, 0x3f, 0xe5, 0xf6, 0x83, 0x3e, 0x69, + 0x8d, 0x1a, 0xc8, 0x81, 0xd2, 0xaf, 0x88, 0xf8, 0xeb, 0x0c, 0xbc, 0xe1, 0xdf, 0x15, 0x14, 0xf6, 0x83, 0x9f, 0x2e, + 0x8e, 0xfb, 0x64, 0xb4, 0x74, 0xec, 0xe5, 0x03, 0xb4, 0x44, 0x68, 0xb9, 0x8b, 0x2e, 0xb0, 0x3d, 0xb1, 0x11, 0x1e, + 0x73, 0xd2, 0x7a, 0xd0, 0x9a, 0xe0, 0x73, 0x4e, 0x5a, 0x76, 0x6b, 0x82, 0xdf, 0x70, 0xd2, 0xfa, 0xbb, 0x33, 0xf0, + 0xa4, 0x9b, 0x6d, 0x29, 0x3c, 0x1c, 0x4b, 0x08, 0x72, 0xf8, 0x19, 0xf5, 0x97, 0x9c, 0xf1, 0x98, 0xa2, 0xdd, 0x16, + 0xc3, 0x1f, 0x05, 0x9a, 0x1c, 0x0e, 0x7e, 0x18, 0x30, 0xef, 0x9c, 0xc5, 0x39, 0x2c, 0x36, 0xd0, 0xcc, 0xae, 0x97, + 0x60, 0xe9, 0x0a, 0xc8, 0x3d, 0x8e, 0xaf, 0xfc, 0x78, 0x4e, 0x73, 0x8f, 0x16, 0x08, 0xc7, 0xe4, 0x23, 0x77, 0x3a, + 0x08, 0xbf, 0xe0, 0xf0, 0xa3, 0x8b, 0xf0, 0xa9, 0x0a, 0x64, 0xc2, 0x4e, 0x96, 0x44, 0x95, 0xa4, 0x52, 0x65, 0xb1, + 0x11, 0x9e, 0x6c, 0x78, 0xc9, 0x23, 0x70, 0x30, 0x20, 0x7c, 0x55, 0x0b, 0x7b, 0xe2, 0x1b, 0xa2, 0x49, 0xe2, 0x7d, + 0x46, 0xe9, 0x77, 0x7e, 0xfc, 0x91, 0x66, 0xce, 0x09, 0xee, 0x74, 0x1f, 0x63, 0xe1, 0x87, 0xde, 0xe9, 0xa0, 0x5e, + 0x19, 0xb3, 0x7a, 0xcb, 0x65, 0xa8, 0x00, 0xa4, 0x6c, 0xdd, 0x1d, 0x03, 0x2b, 0xbe, 0x93, 0xac, 0xf9, 0xac, 0x32, + 0xff, 0xda, 0x46, 0xf5, 0xf8, 0x28, 0x4b, 0xae, 0xfc, 0x98, 0x85, 0x16, 0xa7, 0xd3, 0x59, 0xec, 0x73, 0x6a, 0xa9, + 0xf9, 0x5a, 0x3e, 0x74, 0x64, 0x97, 0x3a, 0xc3, 0xcc, 0xb0, 0x39, 0x67, 0x3a, 0xf0, 0x04, 0x7b, 0xc5, 0x81, 0x28, + 0x95, 0xd2, 0x3b, 0x9e, 0x56, 0x41, 0xb0, 0xd5, 0x38, 0x5f, 0xb3, 0x03, 0xbe, 0xb0, 0x91, 0x90, 0xcf, 0x39, 0x86, + 0xa0, 0x25, 0x21, 0xdd, 0x81, 0x7d, 0x9c, 0x5f, 0x4d, 0xfa, 0x36, 0xc4, 0x68, 0x32, 0xf2, 0x41, 0xb8, 0x86, 0xa0, + 0x42, 0x44, 0xda, 0xbd, 0xe8, 0x98, 0xf6, 0xa2, 0x46, 0x43, 0x6b, 0xd1, 0x3e, 0x49, 0x86, 0x91, 0x6c, 0x1e, 0xe0, + 0x10, 0xcf, 0x49, 0xb3, 0x83, 0x67, 0xa4, 0x2d, 0x9a, 0xf4, 0x66, 0xc7, 0xbe, 0x1a, 0x66, 0x6f, 0xcf, 0xc9, 0xdc, + 0xd8, 0xcf, 0xf9, 0x0b, 0xb0, 0xf7, 0xc9, 0x0c, 0x87, 0x24, 0x73, 0xe9, 0x0d, 0x0d, 0x1c, 0x1f, 0xe1, 0x50, 0x71, + 0x1a, 0xd4, 0x43, 0x33, 0x62, 0x54, 0x03, 0x33, 0x82, 0x7c, 0x18, 0x84, 0xc3, 0xce, 0x88, 0x10, 0x62, 0xef, 0x34, + 0x9b, 0xf6, 0x20, 0x23, 0x13, 0xee, 0x41, 0x89, 0xa1, 0x2c, 0x93, 0x29, 0x14, 0x75, 0x8d, 0x22, 0xe7, 0x0d, 0x77, + 0x39, 0xcd, 0xb9, 0x03, 0xc5, 0xe0, 0x01, 0xc8, 0x35, 0x61, 0xdb, 0xc7, 0x2d, 0xbb, 0x01, 0xa5, 0x82, 0x38, 0x11, + 0xce, 0xc8, 0x35, 0xf2, 0xc2, 0xe1, 0xfe, 0xc8, 0x14, 0x00, 0xa2, 0x10, 0x06, 0xbf, 0x1e, 0x84, 0xc3, 0xb6, 0x18, + 0xbc, 0x6f, 0x0f, 0x9c, 0x8c, 0xe4, 0x52, 0x43, 0x1b, 0xe4, 0xde, 0x07, 0x31, 0x55, 0xe4, 0x29, 0xe0, 0xd4, 0xb8, + 0x73, 0xd2, 0xec, 0x7a, 0xce, 0xdc, 0x9c, 0x44, 0x13, 0x06, 0x53, 0x58, 0xc0, 0x01, 0x81, 0xfa, 0x38, 0x23, 0x30, + 0x62, 0xd5, 0xec, 0xda, 0x53, 0xcf, 0x0f, 0xec, 0x07, 0x83, 0x73, 0xee, 0x8d, 0xb9, 0x1c, 0xfe, 0x9c, 0x2f, 0x97, + 0xf0, 0xef, 0x98, 0x0f, 0x32, 0x72, 0x2d, 0x8a, 0x26, 0xaa, 0x68, 0x0a, 0x45, 0x1f, 0x3c, 0x00, 0x15, 0xe7, 0xa5, + 0x96, 0x25, 0xd7, 0x64, 0x4a, 0x04, 0xec, 0x7b, 0x7b, 0xc9, 0x30, 0x6a, 0x74, 0x46, 0xe0, 0xe4, 0xcf, 0x78, 0xfe, + 0x1d, 0xe3, 0x91, 0x63, 0xb7, 0xfa, 0x36, 0x1a, 0xd8, 0x16, 0x2c, 0x6d, 0x2f, 0x6d, 0x10, 0x89, 0x61, 0xbf, 0xf1, + 0x8a, 0x7b, 0xf3, 0x3e, 0x69, 0x0f, 0x1c, 0xa6, 0x5c, 0x7a, 0x08, 0xfb, 0x8a, 0x71, 0xb6, 0xf1, 0x1c, 0x35, 0x18, + 0x6f, 0xe8, 0xe7, 0x39, 0x6a, 0xdc, 0x36, 0xa6, 0xc8, 0xf3, 0x1b, 0xb7, 0x0d, 0x67, 0x4e, 0x08, 0x69, 0x76, 0xcb, + 0x66, 0x5a, 0xfc, 0x45, 0xc8, 0x9b, 0x6a, 0x7f, 0xe7, 0x50, 0x6c, 0x87, 0xb4, 0xe1, 0x24, 0x43, 0x3a, 0x5a, 0x2e, + 0xed, 0xe3, 0x41, 0xdf, 0x46, 0x0d, 0x47, 0x13, 0x5a, 0x4b, 0x53, 0x1a, 0x42, 0x98, 0x8d, 0x0a, 0x15, 0x4f, 0x7a, + 0x52, 0x8b, 0x1d, 0x2d, 0xaa, 0xcd, 0x6e, 0xf0, 0x00, 0x5a, 0x94, 0x86, 0x8c, 0x54, 0x58, 0x67, 0x30, 0x4d, 0x4d, + 0xcc, 0x29, 0x69, 0xe3, 0x8c, 0x68, 0xf7, 0x75, 0x44, 0x78, 0x45, 0xf0, 0x3e, 0xa9, 0xaa, 0xe3, 0x61, 0x80, 0xc3, + 0x11, 0x79, 0x2a, 0x0d, 0x92, 0x9e, 0x76, 0x8e, 0xd3, 0x98, 0x3c, 0x59, 0x89, 0xe2, 0x06, 0x10, 0x60, 0xb9, 0x71, + 0x83, 0x79, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcf, 0x62, 0x50, 0xd2, + 0xba, 0x7a, 0x67, 0xcc, 0xd7, 0x5e, 0xcf, 0xc8, 0x5c, 0xea, 0x4f, 0x22, 0x68, 0xdb, 0x9b, 0x29, 0xcb, 0xd8, 0x41, + 0x78, 0xae, 0xa2, 0xb9, 0x8e, 0xeb, 0xba, 0x33, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, 0x8f, 0x9c, 0x9c, + 0xdc, 0xb8, 0x09, 0xbd, 0x11, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0x1d, 0x47, 0x3d, 0xc1, 0x6e, 0x72, 0x37, + 0x49, 0x43, 0x0a, 0xe8, 0x81, 0xf8, 0xbd, 0x2a, 0x8a, 0xfc, 0xdc, 0x0c, 0x52, 0x55, 0xf0, 0x0d, 0x4d, 0xff, 0xf5, + 0x0c, 0x9c, 0xbe, 0x42, 0xd9, 0x2a, 0x2b, 0x4b, 0x4f, 0x38, 0x42, 0x6c, 0xec, 0xcc, 0x5c, 0x08, 0xee, 0x09, 0x12, + 0x62, 0x60, 0xcb, 0xcd, 0x4c, 0xa2, 0xba, 0x2d, 0xfb, 0x9c, 0x92, 0x70, 0x98, 0x35, 0x1a, 0xc2, 0x11, 0x3d, 0x97, + 0x24, 0x31, 0x43, 0x78, 0x5a, 0xee, 0x2d, 0x5d, 0xef, 0x2d, 0xa9, 0x8f, 0xe4, 0x4c, 0xeb, 0x0e, 0xdd, 0x06, 0xe3, + 0x48, 0xf8, 0x0a, 0xb9, 0x73, 0x8b, 0xf0, 0x98, 0xb4, 0x9c, 0xa1, 0x3b, 0xf8, 0xf3, 0x08, 0x0d, 0x1c, 0xf7, 0x2b, + 0xd4, 0x92, 0x8c, 0x63, 0x8a, 0x7a, 0xbe, 0x1c, 0x62, 0x21, 0xa2, 0x98, 0x1d, 0x2c, 0x7c, 0x89, 0x5e, 0x8a, 0x13, + 0x7f, 0x4a, 0xbd, 0x31, 0xec, 0x71, 0x4d, 0x37, 0x6f, 0x31, 0xd0, 0x91, 0x37, 0x56, 0x9c, 0xc4, 0xb5, 0x07, 0xbf, + 0xf0, 0xf2, 0x69, 0x60, 0x0f, 0xbe, 0xae, 0x9e, 0xfe, 0x6c, 0x0f, 0xbe, 0xe5, 0xde, 0xb7, 0x85, 0x72, 0x77, 0xd7, + 0x86, 0x78, 0xa8, 0x87, 0x28, 0xe4, 0xc2, 0x18, 0x98, 0x9b, 0xa3, 0x75, 0x47, 0xc7, 0x0c, 0x15, 0x6c, 0x5c, 0xb2, + 0xa2, 0xdc, 0xe5, 0xfe, 0x04, 0x50, 0x6a, 0xac, 0x40, 0x6e, 0x46, 0xf7, 0xab, 0x09, 0x03, 0xa1, 0x68, 0x6a, 0x05, + 0x54, 0xce, 0xfa, 0x6d, 0xb4, 0xa8, 0xd5, 0x15, 0x1a, 0x53, 0x3d, 0x9a, 0x5e, 0x72, 0xe9, 0x29, 0x69, 0xf7, 0xa6, + 0xc7, 0xb3, 0xde, 0xb4, 0xd1, 0x40, 0xb9, 0x26, 0xac, 0xf9, 0x70, 0x3a, 0xc2, 0xaf, 0xc1, 0xab, 0x67, 0x52, 0x12, + 0xae, 0x4d, 0xaf, 0xab, 0xa6, 0xd7, 0x68, 0xa4, 0x05, 0xea, 0x19, 0x4d, 0x67, 0xb2, 0x69, 0x51, 0x48, 0x9c, 0xac, + 0x12, 0xda, 0x11, 0x12, 0x25, 0x90, 0x12, 0x45, 0x08, 0x39, 0xe3, 0x68, 0x63, 0xaf, 0xd0, 0x27, 0x34, 0x17, 0x3b, + 0x16, 0x98, 0xa7, 0x94, 0x11, 0x0e, 0x60, 0x01, 0x9a, 0x96, 0xae, 0xe0, 0x5b, 0x3c, 0x6f, 0x74, 0x04, 0x91, 0x37, + 0x3b, 0xbd, 0x7a, 0x5f, 0x8f, 0xaa, 0xbe, 0xf0, 0xbc, 0x41, 0x6e, 0x4b, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0xe3, + 0x9d, 0x7a, 0xdf, 0xd6, 0x22, 0x10, 0x27, 0xab, 0xa9, 0x19, 0x5a, 0xbe, 0x56, 0x12, 0x95, 0xb9, 0x2c, 0x49, 0x68, + 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, 0x12, 0xe0, 0x3b, 0xc2, 0xec, + 0xc2, 0x29, 0xce, 0x70, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x54, 0x27, 0xb5, 0x70, 0xc1, 0x81, 0x7c, 0xc2, 0x0c, 0x89, + 0x94, 0x13, 0xea, 0x9e, 0xef, 0x9e, 0xa6, 0x77, 0x9a, 0x64, 0x43, 0x36, 0xf2, 0x44, 0xb5, 0x58, 0xf1, 0xad, 0x80, + 0xbc, 0x73, 0x38, 0x2a, 0xc3, 0x23, 0xae, 0x60, 0x7f, 0x4f, 0x59, 0x46, 0x85, 0x06, 0xbe, 0xab, 0xcd, 0x3e, 0xbf, + 0xae, 0x3e, 0xfa, 0xa6, 0xf3, 0x06, 0x10, 0x19, 0x80, 0x6f, 0x27, 0x25, 0x6b, 0xd5, 0xce, 0x77, 0x4f, 0xde, 0x6c, + 0x32, 0x81, 0x97, 0x4b, 0x65, 0xfc, 0xfa, 0xa0, 0xd9, 0xe0, 0xa0, 0x82, 0xd4, 0x57, 0x3f, 0x3c, 0xc7, 0x17, 0x0a, + 0x52, 0xe0, 0x24, 0x40, 0x45, 0xe7, 0xbb, 0x27, 0xef, 0x9d, 0x44, 0xb8, 0x96, 0x10, 0x36, 0xa7, 0xed, 0x64, 0xc4, + 0x89, 0x08, 0x45, 0x72, 0xee, 0x25, 0xe3, 0xca, 0x0c, 0xf1, 0xed, 0x45, 0xe2, 0x25, 0xd8, 0x0f, 0x43, 0x36, 0x22, + 0xbe, 0xc2, 0x00, 0xf1, 0x11, 0xf6, 0x6b, 0x66, 0x19, 0x81, 0x05, 0x10, 0x63, 0x9d, 0xc1, 0x4a, 0xb8, 0x52, 0xf1, + 0x43, 0xd8, 0x17, 0xa3, 0xf2, 0x42, 0x8a, 0x8e, 0x9f, 0xd7, 0x72, 0xd3, 0x2a, 0x6b, 0xf4, 0x5b, 0xb0, 0x9c, 0xf4, + 0xc3, 0x6b, 0xd5, 0x75, 0x59, 0xf0, 0x54, 0x27, 0x91, 0x9d, 0xef, 0x9e, 0xbc, 0x52, 0x79, 0x64, 0x33, 0x5f, 0x73, + 0xfb, 0x35, 0x0b, 0xf3, 0xe4, 0x95, 0x5b, 0xbd, 0x15, 0x95, 0xcf, 0x77, 0x4f, 0x3e, 0x6c, 0xaa, 0x06, 0xe5, 0xc5, + 0xbc, 0x32, 0xf1, 0x05, 0x7c, 0x0b, 0x1a, 0x7b, 0x0b, 0x25, 0x1a, 0x3c, 0x56, 0x60, 0x21, 0x8e, 0xbc, 0xbc, 0x28, + 0x3d, 0x23, 0x4f, 0x71, 0x4a, 0x44, 0x1c, 0xa8, 0xbe, 0x6a, 0x4a, 0xc9, 0x63, 0x69, 0x72, 0x16, 0xa4, 0x33, 0xba, + 0x25, 0x38, 0x74, 0x82, 0x5c, 0x36, 0x85, 0x04, 0x1a, 0x01, 0x3a, 0xc3, 0x3b, 0x6d, 0xd4, 0xab, 0x0b, 0xaf, 0x54, + 0x10, 0x69, 0x56, 0x93, 0x2c, 0x38, 0x22, 0x6d, 0xec, 0x93, 0x36, 0x0e, 0x48, 0x3e, 0x6c, 0x4b, 0xf1, 0xd0, 0x0b, + 0xca, 0x7e, 0xa5, 0x90, 0x81, 0xdc, 0xb0, 0x40, 0xee, 0x56, 0x29, 0x7e, 0xc3, 0x5e, 0x20, 0x5c, 0x8f, 0x42, 0xa2, + 0x87, 0xd2, 0x68, 0x75, 0x32, 0x9c, 0x89, 0x8e, 0xcf, 0xd8, 0x65, 0x0c, 0xd9, 0x25, 0x30, 0x2b, 0xcc, 0x91, 0x57, + 0x56, 0xed, 0xa8, 0xaa, 0x81, 0x2b, 0xd6, 0x29, 0xc3, 0x81, 0x0b, 0x8c, 0x1b, 0x07, 0x2a, 0x19, 0x27, 0x5f, 0x6f, + 0xf2, 0x70, 0x6f, 0xcf, 0x91, 0x8d, 0xbe, 0xe3, 0x4e, 0xa6, 0xdf, 0x57, 0xa1, 0xbb, 0x6f, 0x25, 0xaf, 0x08, 0x91, + 0x80, 0xbf, 0xd1, 0xf0, 0x47, 0x05, 0xc4, 0xa1, 0x9d, 0xa0, 0x8e, 0x41, 0x0d, 0xbc, 0xd0, 0xf4, 0xea, 0xd3, 0x6f, + 0x34, 0xca, 0x30, 0x6d, 0x1d, 0x5b, 0x27, 0x38, 0x2d, 0xae, 0x9c, 0x32, 0xff, 0xa7, 0xbd, 0x96, 0x35, 0xa5, 0x41, + 0x40, 0xcc, 0xa4, 0x59, 0xa6, 0x27, 0x63, 0x6c, 0x09, 0x06, 0xf5, 0x5e, 0xa8, 0xc4, 0x05, 0x2c, 0x72, 0xac, 0x54, + 0x25, 0xcd, 0xce, 0xba, 0xc8, 0xd3, 0x95, 0x20, 0x2c, 0x05, 0x95, 0x1a, 0x85, 0x22, 0xef, 0x57, 0xeb, 0x99, 0x97, + 0x38, 0x47, 0xca, 0xc7, 0x25, 0xa0, 0x10, 0xc8, 0xea, 0x96, 0x48, 0x79, 0x4e, 0x26, 0xdb, 0x49, 0xfe, 0xc4, 0x20, + 0xf9, 0x27, 0x84, 0x1a, 0xe4, 0x2f, 0x3d, 0x1c, 0x6e, 0xaa, 0x5c, 0x0b, 0xb9, 0x7e, 0x75, 0x3a, 0x23, 0xe0, 0x43, + 0xab, 0x63, 0xb4, 0x16, 0x57, 0xdc, 0xc2, 0x50, 0xcc, 0x1d, 0x22, 0xbc, 0x90, 0x58, 0x07, 0x81, 0x9d, 0x2a, 0xaa, + 0x06, 0x43, 0x6f, 0x72, 0xe9, 0x99, 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0x01, 0xd1, 0xd3, 0xd9, 0xfa, 0xce, 0x35, 0x32, + 0x40, 0x61, 0xd6, 0xc6, 0xc6, 0xad, 0xe7, 0x83, 0xc2, 0xf8, 0x65, 0x20, 0xbb, 0xce, 0x7c, 0x56, 0x36, 0xa1, 0x96, + 0x7f, 0x00, 0x6d, 0xa7, 0x23, 0x6a, 0x50, 0xa3, 0x5b, 0xe0, 0x47, 0x32, 0x0f, 0xd5, 0xcf, 0xb6, 0xb0, 0x8f, 0x13, + 0x51, 0x81, 0x26, 0xe1, 0xe6, 0xd7, 0x4f, 0x0a, 0x45, 0x26, 0x12, 0x34, 0xb4, 0x00, 0xfe, 0x27, 0x49, 0x1e, 0xe8, + 0x46, 0xc8, 0x05, 0x40, 0xd0, 0x44, 0xe0, 0xa9, 0x42, 0x98, 0x6d, 0x57, 0xce, 0xf7, 0xe7, 0x3b, 0x84, 0x4c, 0x2a, + 0xe7, 0xe3, 0xbb, 0x2a, 0xfb, 0x0a, 0xc8, 0x02, 0x79, 0x60, 0x3c, 0x96, 0x05, 0x32, 0x7e, 0x79, 0xaa, 0xab, 0x0b, + 0x03, 0xd2, 0xad, 0xf4, 0x6d, 0x23, 0xb6, 0x29, 0xbc, 0x72, 0xf2, 0xbd, 0x46, 0xc3, 0xca, 0xdb, 0x5d, 0x78, 0xfb, + 0x92, 0x0b, 0x18, 0xe1, 0xf9, 0xbd, 0xa8, 0xad, 0xfb, 0x2d, 0x3e, 0xae, 0xa6, 0xb0, 0xac, 0x2c, 0x8a, 0xcb, 0x92, + 0x9c, 0x66, 0xfc, 0x09, 0x1d, 0xa7, 0x19, 0x84, 0x2c, 0x4a, 0x9c, 0xa0, 0x62, 0xd7, 0x70, 0xdb, 0x89, 0xf9, 0x19, + 0x71, 0x82, 0x95, 0x09, 0x8a, 0x5f, 0x1f, 0x45, 0xd4, 0xfa, 0x7c, 0xb5, 0xd5, 0x64, 0x6f, 0xef, 0x5d, 0x85, 0x26, + 0x05, 0xa5, 0x80, 0xc2, 0x60, 0x5a, 0x52, 0xa5, 0x51, 0xa1, 0xdc, 0x5d, 0xa7, 0x74, 0x01, 0x68, 0x86, 0x61, 0xf2, + 0x9e, 0xe7, 0x84, 0x17, 0x93, 0x55, 0x16, 0xaf, 0x5c, 0x13, 0xcc, 0x34, 0x5b, 0x80, 0xc3, 0x83, 0xa1, 0x2d, 0x7d, + 0x45, 0x79, 0x95, 0x12, 0x5b, 0xc2, 0x70, 0x0a, 0xc8, 0x72, 0x84, 0x11, 0x62, 0x50, 0xe0, 0x46, 0xa3, 0xe4, 0x2d, + 0xe8, 0x95, 0x11, 0xce, 0xdd, 0x08, 0x92, 0x60, 0x6b, 0x5b, 0x16, 0x21, 0x2c, 0x33, 0x73, 0x8c, 0x5c, 0x82, 0x93, + 0xe7, 0x9b, 0x3c, 0xca, 0x9a, 0xa8, 0xa9, 0x90, 0x3a, 0x50, 0x23, 0x45, 0x65, 0x03, 0xf7, 0xca, 0x61, 0x4a, 0x71, + 0xd3, 0x71, 0x33, 0x60, 0xc0, 0x3f, 0x73, 0x47, 0xc6, 0xa2, 0x40, 0x66, 0x64, 0xee, 0xdc, 0xa9, 0x0d, 0xdd, 0xcb, + 0x44, 0x33, 0xac, 0x10, 0x17, 0x99, 0x68, 0xca, 0x44, 0x5c, 0xef, 0xb4, 0xe2, 0xa5, 0x57, 0x32, 0x8f, 0x9a, 0x6b, + 0x2e, 0x58, 0x65, 0x92, 0x18, 0xd3, 0xbf, 0x92, 0xa9, 0xd1, 0x65, 0x25, 0x50, 0xc3, 0xe8, 0xb5, 0xf5, 0x44, 0xac, + 0x01, 0x2d, 0x80, 0xbe, 0x16, 0xa7, 0xdc, 0x58, 0x51, 0xed, 0xc3, 0x16, 0x63, 0x1a, 0x52, 0xff, 0x1d, 0xe4, 0xba, + 0xac, 0xee, 0xf9, 0xe7, 0x42, 0x16, 0x32, 0x9c, 0xd7, 0x18, 0x7b, 0x2a, 0x18, 0x3b, 0x02, 0x3d, 0x4d, 0xa7, 0x7f, + 0x0f, 0x54, 0xca, 0x8b, 0xca, 0x5d, 0x74, 0x14, 0x89, 0xbd, 0x2e, 0xc3, 0xe5, 0xc6, 0xef, 0x95, 0xd5, 0xf0, 0x18, + 0x81, 0x34, 0x20, 0xac, 0x38, 0x7b, 0x8a, 0x70, 0xde, 0x68, 0xf4, 0xf2, 0x63, 0x5a, 0xb9, 0x48, 0x2a, 0x18, 0x19, + 0x44, 0x74, 0x81, 0xe0, 0x6b, 0x32, 0x14, 0x62, 0xfe, 0x3a, 0x3f, 0x3b, 0x07, 0x57, 0xfb, 0xc9, 0x3b, 0xc7, 0xe4, + 0x6a, 0x66, 0xdd, 0x32, 0x68, 0x0a, 0xf3, 0x71, 0xaa, 0x78, 0xcb, 0xdb, 0xbb, 0x33, 0x3c, 0x00, 0xee, 0x9d, 0x0e, + 0x86, 0x6c, 0x34, 0xd4, 0xe3, 0x92, 0x25, 0x94, 0xbb, 0xaf, 0x87, 0xaa, 0xc4, 0x44, 0x73, 0xb0, 0x1e, 0xaf, 0x4c, + 0x59, 0x4e, 0xf2, 0xa2, 0xc8, 0x69, 0x15, 0xdf, 0x5f, 0xc9, 0xc0, 0x14, 0xc2, 0x65, 0xdd, 0xd9, 0x7e, 0x3a, 0x23, + 0x1c, 0x1b, 0x84, 0xfa, 0x76, 0x5b, 0xe8, 0xa3, 0x02, 0x13, 0xf6, 0xb5, 0x12, 0x8a, 0xdf, 0x6e, 0x12, 0x8a, 0x38, + 0x55, 0x5b, 0x5e, 0x08, 0xc4, 0xce, 0x3d, 0x04, 0xa2, 0x72, 0xb2, 0x6b, 0x99, 0x08, 0xea, 0x48, 0x4d, 0x26, 0xd6, + 0x97, 0x94, 0xa4, 0x98, 0xa9, 0xd5, 0xe8, 0x77, 0x97, 0x4b, 0x36, 0x6c, 0x83, 0x13, 0xc9, 0xb6, 0xe1, 0x67, 0x47, + 0xfe, 0x34, 0x38, 0xb1, 0x74, 0x02, 0x3b, 0xac, 0x34, 0x59, 0x90, 0x0b, 0x69, 0xce, 0x8e, 0xc8, 0xca, 0x12, 0x34, + 0xad, 0x28, 0x48, 0x11, 0x38, 0x61, 0x65, 0x94, 0x09, 0x20, 0x16, 0xb2, 0x42, 0x19, 0x90, 0xce, 0xc6, 0xf4, 0x3f, + 0x6d, 0x5e, 0x7e, 0x5a, 0x13, 0xad, 0xc9, 0x15, 0xa9, 0x3e, 0xd4, 0x12, 0x0e, 0x14, 0x04, 0x4a, 0x3f, 0xdc, 0x11, + 0x26, 0x68, 0x25, 0xca, 0x91, 0x29, 0x87, 0x70, 0x1b, 0x5c, 0x68, 0x3b, 0xef, 0x64, 0x80, 0x77, 0x83, 0x34, 0xc1, + 0x99, 0x41, 0xd7, 0xcf, 0x09, 0xaf, 0xb1, 0x92, 0x88, 0x28, 0x4b, 0x09, 0x07, 0x82, 0x4c, 0x39, 0x49, 0x87, 0xed, + 0x11, 0x28, 0xa0, 0x3d, 0xff, 0x38, 0xad, 0x4c, 0x60, 0xbf, 0xd1, 0x40, 0x81, 0x1e, 0x35, 0x1a, 0xb2, 0x86, 0x3f, + 0xc2, 0x14, 0xfb, 0xd2, 0x30, 0x39, 0xdd, 0xdb, 0x73, 0x82, 0x6a, 0xdc, 0xa1, 0x3f, 0x42, 0x38, 0x5b, 0x2e, 0x1d, + 0x01, 0x56, 0x80, 0x96, 0xcb, 0xc0, 0x04, 0x4b, 0xbc, 0x86, 0x66, 0x93, 0x01, 0x27, 0x13, 0x21, 0x00, 0x27, 0x00, + 0x61, 0x83, 0x38, 0x81, 0x72, 0xee, 0x05, 0xe0, 0x8c, 0x6a, 0xa4, 0x43, 0xbf, 0xd1, 0x19, 0x19, 0x8c, 0x6b, 0xe8, + 0x8f, 0x48, 0x50, 0x40, 0x72, 0x6b, 0xae, 0x44, 0xe4, 0xcf, 0x20, 0xca, 0x7e, 0x16, 0x92, 0x45, 0x76, 0x68, 0xae, + 0xc6, 0xaa, 0x33, 0xa0, 0xa4, 0x28, 0xb5, 0xac, 0xba, 0x5e, 0x2d, 0x0b, 0xa2, 0xac, 0x84, 0x55, 0x2c, 0x78, 0x00, + 0x96, 0x7d, 0x49, 0xe6, 0xbf, 0xf0, 0x32, 0xcd, 0xfa, 0xdb, 0x8d, 0xc9, 0xd5, 0xae, 0xeb, 0xfa, 0xd9, 0x44, 0x44, + 0x32, 0x74, 0x14, 0x56, 0x10, 0xff, 0xbe, 0x02, 0xd3, 0x18, 0x78, 0x58, 0x8e, 0x35, 0x22, 0x12, 0x7c, 0xad, 0xda, + 0xe8, 0x13, 0x25, 0xbf, 0x6e, 0xf4, 0x32, 0x48, 0x48, 0xbe, 0xfe, 0xad, 0x90, 0x1c, 0x28, 0x48, 0x24, 0x79, 0xac, + 0xe0, 0x6c, 0x0b, 0x2e, 0x7e, 0xe5, 0x2b, 0x38, 0xdb, 0x8e, 0xdb, 0x92, 0x21, 0x6c, 0x83, 0xcf, 0xe0, 0x0d, 0x12, + 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x70, 0x55, 0xf7, 0x92, 0xac, 0x14, 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, + 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0x4d, 0x90, 0xe1, 0x12, 0xa8, 0xa7, 0xae, 0x00, 0x39, 0x29, 0x5f, 0x3b, 0xa4, 0x22, + 0xec, 0x48, 0x25, 0xce, 0x0d, 0xfc, 0x19, 0x9f, 0x67, 0xa0, 0x4a, 0xe5, 0xfa, 0x37, 0x14, 0xc3, 0x59, 0x10, 0x51, + 0x06, 0x3f, 0xa0, 0x60, 0xe6, 0xe7, 0x39, 0xbb, 0x92, 0x65, 0xea, 0x37, 0xce, 0x88, 0x26, 0xe5, 0x5c, 0xea, 0x84, + 0x29, 0xea, 0xa5, 0x8a, 0x4e, 0xeb, 0x68, 0x7b, 0x76, 0x45, 0x13, 0xfe, 0x92, 0xe5, 0x9c, 0x26, 0x30, 0xfd, 0x8a, + 0xe2, 0x60, 0x46, 0x39, 0x82, 0x0d, 0x5b, 0x6b, 0xe5, 0x87, 0xe1, 0x9d, 0x4d, 0x78, 0x5d, 0x07, 0x8a, 0xfc, 0x24, + 0x8c, 0xe5, 0x20, 0x66, 0x42, 0xa3, 0x4e, 0xe2, 0x2c, 0x6b, 0x9a, 0xf9, 0x34, 0x95, 0xb2, 0x21, 0xb8, 0xbb, 0xc3, + 0x88, 0x96, 0x04, 0x5a, 0x7a, 0xde, 0xa9, 0xb5, 0x40, 0xc0, 0x7b, 0xcb, 0x22, 0x98, 0x33, 0xc1, 0xdc, 0xe0, 0xa8, + 0x6e, 0x1d, 0x4e, 0x4d, 0x37, 0xdf, 0x6d, 0x3c, 0xd8, 0xb6, 0x49, 0x38, 0x08, 0x3a, 0x79, 0xb8, 0xdd, 0xb2, 0x7a, + 0xa5, 0x25, 0x87, 0x96, 0x16, 0xec, 0xbe, 0x8c, 0x19, 0x2d, 0x34, 0x79, 0x21, 0xbd, 0x15, 0x77, 0x39, 0xf9, 0x05, + 0x4e, 0x0e, 0x3d, 0xe7, 0xd3, 0x78, 0xe5, 0x80, 0x4c, 0x6f, 0xb7, 0xd4, 0xfe, 0x77, 0xb9, 0xf3, 0x04, 0xbf, 0x82, + 0xb0, 0xee, 0x37, 0x55, 0xf5, 0xf5, 0x70, 0xee, 0x37, 0x15, 0x82, 0xbe, 0xf1, 0xd6, 0xea, 0x19, 0x61, 0xdc, 0xae, + 0x7b, 0xe4, 0xb6, 0x6d, 0xad, 0x2d, 0xfd, 0x28, 0x83, 0x48, 0x32, 0xd5, 0x52, 0xec, 0x07, 0x5c, 0x25, 0xaa, 0x41, + 0xc2, 0x5c, 0xdd, 0x42, 0xa2, 0x2a, 0xc5, 0x50, 0xea, 0xf0, 0xdb, 0x96, 0x47, 0xc9, 0x98, 0x54, 0xda, 0x19, 0x6f, + 0xfd, 0x8c, 0xef, 0xc2, 0x2e, 0xcb, 0xd6, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0xf7, 0x1b, 0xc2, 0x30, 0xb6, 0x73, + 0x79, 0x18, 0xc8, 0xec, 0x9f, 0x64, 0x5a, 0x77, 0xab, 0x5b, 0x19, 0xaf, 0xc1, 0xfe, 0x47, 0x38, 0xd2, 0x47, 0xe4, + 0xa8, 0xe2, 0xc0, 0xd4, 0x5b, 0x14, 0xa5, 0x53, 0x20, 0x93, 0xca, 0x5b, 0x82, 0x70, 0x56, 0x88, 0xf0, 0xf6, 0xf7, + 0xf8, 0x07, 0xc5, 0x12, 0xcf, 0x4b, 0x8e, 0xf3, 0xec, 0xbe, 0x1c, 0x51, 0x82, 0x5f, 0x46, 0xef, 0x81, 0x8e, 0x05, + 0x85, 0x16, 0x9a, 0x8a, 0x9e, 0xa6, 0x6a, 0x22, 0x5b, 0xf3, 0x52, 0x31, 0x2d, 0x33, 0x6a, 0xc4, 0x30, 0x1b, 0x12, + 0x39, 0xb5, 0x95, 0xcd, 0xcb, 0x5d, 0x55, 0x1b, 0x17, 0x6d, 0xc1, 0x62, 0x15, 0x58, 0x5c, 0x2e, 0x9d, 0x3a, 0xaa, + 0x09, 0x33, 0xe2, 0x18, 0x08, 0x33, 0x23, 0xa1, 0xa2, 0xa6, 0x59, 0xcb, 0x36, 0x0e, 0x5a, 0xcd, 0x27, 0xd2, 0xba, + 0x79, 0x0d, 0x0e, 0xd3, 0x85, 0x20, 0x9b, 0x9b, 0x3e, 0x05, 0x2c, 0x67, 0x57, 0x0e, 0x64, 0x60, 0xe8, 0xc7, 0x32, + 0x57, 0xb6, 0x4a, 0x6a, 0xdd, 0x80, 0x5f, 0x74, 0x47, 0xb6, 0xac, 0x42, 0xdd, 0xfa, 0x7b, 0x23, 0xd7, 0xe8, 0x69, + 0xba, 0x2d, 0xd7, 0xa8, 0xa6, 0xed, 0xee, 0xb4, 0xd1, 0xdd, 0x79, 0xa9, 0x72, 0xac, 0xcd, 0x55, 0x7e, 0xc3, 0x70, + 0x1d, 0xa0, 0x4d, 0x89, 0x66, 0xcd, 0x55, 0x4e, 0x8b, 0xe2, 0xbc, 0x3c, 0x4d, 0x20, 0x52, 0x77, 0xce, 0x25, 0xfd, + 0x2b, 0xab, 0x51, 0x1c, 0xca, 0x75, 0xbe, 0x27, 0x93, 0x38, 0xbd, 0xf4, 0xe3, 0xf7, 0x30, 0x5e, 0xf5, 0xf2, 0xf9, + 0x6d, 0x98, 0xf9, 0x9c, 0x2a, 0xee, 0x52, 0xc1, 0xf0, 0xbd, 0x01, 0xc3, 0xf7, 0x92, 0x4f, 0x57, 0xed, 0xf1, 0xe2, + 0x65, 0xd9, 0x81, 0x77, 0x5e, 0x68, 0x96, 0x71, 0xcb, 0x37, 0x8f, 0xb1, 0xca, 0xc2, 0x6e, 0x4b, 0x16, 0x76, 0xcb, + 0x9d, 0xd5, 0xae, 0x1c, 0xe7, 0x87, 0xcd, 0xbd, 0xac, 0x73, 0xb6, 0x1f, 0xaa, 0x8d, 0xff, 0x83, 0x77, 0x67, 0x1b, + 0x83, 0xcb, 0xed, 0xbb, 0xfb, 0x22, 0x59, 0x45, 0x82, 0xfc, 0x12, 0x92, 0x0e, 0x38, 0xe9, 0x1b, 0x87, 0x0e, 0x2a, + 0x39, 0xa5, 0xf3, 0x80, 0x9c, 0x60, 0x9e, 0xf3, 0x74, 0xaa, 0xfa, 0xcc, 0xd5, 0x49, 0x23, 0xf1, 0x12, 0x5c, 0xd1, + 0x22, 0xd6, 0xee, 0xd5, 0xcf, 0x72, 0x2d, 0x3e, 0xb2, 0x24, 0xf4, 0x72, 0xac, 0xa4, 0x48, 0xee, 0xa5, 0x05, 0xd1, + 0xd9, 0xc6, 0xeb, 0xef, 0xf0, 0x98, 0x25, 0x2c, 0x8f, 0x68, 0xe6, 0x64, 0x68, 0xb1, 0x6d, 0xb0, 0x0c, 0x02, 0x32, + 0x72, 0x30, 0xfc, 0xd7, 0xea, 0xd4, 0x9f, 0x0b, 0xbd, 0x81, 0x1f, 0x68, 0x4a, 0x79, 0x94, 0x86, 0x90, 0x96, 0xe2, + 0x86, 0xe5, 0xa1, 0xa6, 0xbd, 0xbd, 0x1d, 0xc7, 0x16, 0x6e, 0x09, 0x38, 0x00, 0x6e, 0xbe, 0x41, 0x83, 0x05, 0x9c, + 0xcf, 0xa9, 0x86, 0xa6, 0x68, 0x41, 0x57, 0x8f, 0xb2, 0x70, 0xf7, 0x23, 0xbd, 0xc5, 0x09, 0x2a, 0x0a, 0x4f, 0x42, + 0x6d, 0x8f, 0x19, 0x8d, 0x43, 0x1b, 0x7f, 0xa4, 0xb7, 0x5e, 0x79, 0x66, 0x5c, 0x1c, 0x71, 0x16, 0x0b, 0x68, 0xa7, + 0xd7, 0x89, 0x8d, 0xab, 0x41, 0xbc, 0x45, 0x81, 0xd3, 0x8c, 0x4d, 0x80, 0x38, 0xbf, 0xa1, 0xb7, 0x9e, 0xec, 0x8f, + 0x19, 0xe7, 0xf5, 0xd0, 0x42, 0xa3, 0xde, 0x35, 0x8a, 0xcd, 0x65, 0x50, 0x06, 0xc5, 0x50, 0xb4, 0x1d, 0x91, 0x5a, + 0xbd, 0xca, 0x3c, 0x44, 0xa8, 0xb8, 0xef, 0x54, 0xf0, 0x37, 0xa6, 0x68, 0xe3, 0xb5, 0xcc, 0xd7, 0x95, 0x46, 0x14, + 0x1a, 0x54, 0x99, 0x1e, 0xbb, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, 0x84, 0x60, 0x38, 0xc2, 0xbe, 0xe1, 0xaa, 0x53, 0xef, + 0xaf, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xa8, 0xda, 0x59, 0xbb, 0x0e, 0xe0, 0x1d, 0x12, 0x5a, 0x7c, 0x71, 0x26, + 0xb3, 0xd0, 0xd9, 0xa2, 0x7f, 0xe3, 0xc4, 0x59, 0xe8, 0x29, 0x78, 0x89, 0x89, 0x45, 0x5e, 0x00, 0x15, 0x2a, 0xfa, + 0x92, 0x09, 0x80, 0x6c, 0xec, 0xb0, 0x35, 0xa9, 0x99, 0x0a, 0xa9, 0xe9, 0x1a, 0x18, 0xdf, 0x22, 0x25, 0xa9, 0x40, + 0x86, 0x50, 0x22, 0x85, 0xd0, 0x53, 0x8b, 0xab, 0x48, 0xc8, 0x5c, 0xd0, 0xf2, 0x04, 0x9d, 0x5c, 0xf3, 0xb4, 0x06, + 0x96, 0x23, 0xfa, 0x41, 0x85, 0x07, 0x53, 0xa2, 0xb2, 0x42, 0x51, 0x1e, 0xcd, 0xd6, 0xe9, 0xad, 0x4e, 0xe6, 0xea, + 0x69, 0x11, 0x8d, 0x12, 0x27, 0x42, 0x8b, 0xc4, 0x89, 0x70, 0x0a, 0xe9, 0x88, 0x59, 0x51, 0xc2, 0x4f, 0xcd, 0xd5, + 0xa8, 0x25, 0x2b, 0x6f, 0x3e, 0xe5, 0x07, 0xca, 0x3c, 0x87, 0x14, 0x4d, 0x9c, 0x68, 0x9e, 0x92, 0x38, 0xe2, 0xb8, + 0x9d, 0xb1, 0x6c, 0xdf, 0xab, 0x04, 0x1d, 0x05, 0xd8, 0xdf, 0xb8, 0xb3, 0x30, 0x66, 0x61, 0x9e, 0xe8, 0x56, 0xa7, + 0xfe, 0x54, 0xb0, 0xaf, 0xca, 0x21, 0x75, 0x72, 0xb2, 0x22, 0x71, 0xee, 0x4e, 0xb5, 0xfc, 0x65, 0x4e, 0xb3, 0xdb, + 0x33, 0x0a, 0xa9, 0xce, 0x29, 0x1c, 0xf8, 0xad, 0x96, 0xa1, 0xca, 0x53, 0x1f, 0xa4, 0x42, 0x59, 0x29, 0xea, 0xe7, + 0x00, 0x57, 0x4f, 0x09, 0x16, 0x22, 0xda, 0x68, 0x38, 0x62, 0xe4, 0x6e, 0xa1, 0x5b, 0xcf, 0x4f, 0xd2, 0x1e, 0x03, + 0xff, 0x5a, 0x85, 0x69, 0x15, 0x2c, 0xc0, 0x99, 0x79, 0x26, 0x75, 0x98, 0x8f, 0x56, 0xbd, 0x32, 0x50, 0x04, 0xe1, + 0xbb, 0x74, 0xfb, 0x54, 0x37, 0x25, 0xcd, 0x6e, 0x9f, 0x6a, 0x2d, 0xe8, 0x27, 0x12, 0x7e, 0xb0, 0x1a, 0xa7, 0x3c, + 0xc1, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0x5f, 0x7a, 0x8e, 0xf3, 0x17, 0x95, 0x32, 0xe8, 0x42, 0x2c, 0xf6, 0x2c, + 0x4e, 0x35, 0x13, 0xaf, 0xc6, 0xff, 0xcb, 0xda, 0xf8, 0x7f, 0x31, 0x4e, 0x9d, 0x82, 0x69, 0x34, 0x49, 0x68, 0xa8, + 0x59, 0x27, 0x92, 0x04, 0x28, 0xf4, 0xb6, 0x8c, 0x93, 0x8f, 0x17, 0x1e, 0x68, 0x5c, 0x8b, 0x71, 0x9a, 0xf0, 0xe6, + 0xd8, 0x9f, 0xb2, 0xf8, 0xd6, 0x9b, 0xb3, 0xe6, 0x34, 0x4d, 0xd2, 0x7c, 0xe6, 0x07, 0x14, 0xe7, 0xb7, 0x39, 0xa7, + 0xd3, 0xe6, 0x9c, 0xe1, 0xe7, 0x34, 0xbe, 0xa2, 0x9c, 0x05, 0x3e, 0xb6, 0x4f, 0x32, 0xe6, 0xc7, 0xd6, 0x6b, 0x3f, + 0xcb, 0xd2, 0x6b, 0x1b, 0xbf, 0x4b, 0x2f, 0x53, 0x9e, 0xe2, 0x37, 0x37, 0xb7, 0x13, 0x9a, 0xe0, 0x0f, 0x97, 0xf3, + 0x84, 0xcf, 0x71, 0xee, 0x27, 0x79, 0x33, 0xa7, 0x19, 0x1b, 0xf7, 0x82, 0x34, 0x4e, 0xb3, 0x26, 0x64, 0x6c, 0x4f, + 0xa9, 0x17, 0xb3, 0x49, 0xc4, 0xad, 0xd0, 0xcf, 0x3e, 0xf6, 0x9a, 0xcd, 0x59, 0xc6, 0xa6, 0x7e, 0x76, 0xdb, 0x14, + 0x35, 0xbc, 0x2f, 0xdb, 0xfb, 0xfe, 0xe3, 0xf1, 0x41, 0x8f, 0x67, 0x7e, 0x92, 0x33, 0x58, 0x26, 0xcf, 0x8f, 0x63, + 0x6b, 0xff, 0xb0, 0x3d, 0xcd, 0x77, 0x64, 0x20, 0xcf, 0x4f, 0x78, 0x71, 0x81, 0xdf, 0x03, 0xdc, 0xee, 0x25, 0x4f, + 0xf0, 0xe5, 0x9c, 0xf3, 0x34, 0x59, 0x04, 0xf3, 0x2c, 0x4f, 0x33, 0x6f, 0x96, 0xb2, 0x84, 0xd3, 0xac, 0x77, 0x99, + 0x66, 0x21, 0xcd, 0x9a, 0x99, 0x1f, 0xb2, 0x79, 0xee, 0x1d, 0xcc, 0x6e, 0x7a, 0xa0, 0x59, 0x4c, 0xb2, 0x74, 0x9e, + 0x84, 0x6a, 0x2c, 0x96, 0x44, 0x34, 0x63, 0xdc, 0x7c, 0x21, 0x2e, 0x32, 0xf1, 0x62, 0x96, 0x50, 0x3f, 0x6b, 0x4e, + 0xa0, 0x31, 0x98, 0x45, 0xed, 0x90, 0x4e, 0x70, 0x36, 0xb9, 0xf4, 0x9d, 0x4e, 0xf7, 0x11, 0xd6, 0xff, 0xbb, 0x87, + 0xc8, 0x6a, 0x6f, 0x2e, 0xee, 0xb4, 0xdb, 0x7f, 0x42, 0xbd, 0x95, 0x51, 0x04, 0x40, 0x5e, 0x67, 0x76, 0x63, 0xe5, + 0x29, 0x64, 0xb4, 0x6d, 0x6a, 0xd9, 0x9b, 0xf9, 0x21, 0xe4, 0x03, 0x7b, 0xdd, 0xd9, 0x4d, 0x01, 0xb3, 0xf3, 0x64, + 0x8a, 0xa9, 0x9a, 0xa4, 0x7a, 0x5a, 0xfc, 0x56, 0x88, 0x8f, 0x36, 0x43, 0xdc, 0xd5, 0x10, 0x57, 0x58, 0x6f, 0x86, + 0xf3, 0x4c, 0xc4, 0x56, 0xbd, 0x4e, 0x2e, 0x01, 0x89, 0xd2, 0x2b, 0x9a, 0x69, 0x38, 0xc4, 0xc3, 0x6f, 0x06, 0xa3, + 0xbb, 0x19, 0x8c, 0xa3, 0x4f, 0x81, 0x91, 0x25, 0xe1, 0xa2, 0xbe, 0xae, 0x9d, 0x8c, 0x4e, 0x7b, 0x11, 0x05, 0x7a, + 0xf2, 0xba, 0xf0, 0xfb, 0x9a, 0x85, 0x3c, 0x92, 0x3f, 0x05, 0x39, 0x5f, 0xcb, 0x77, 0x87, 0xed, 0xb6, 0x7c, 0xce, + 0xd9, 0xaf, 0xd4, 0xeb, 0xb8, 0x50, 0xa1, 0xb8, 0xc0, 0x3f, 0x94, 0xa7, 0x79, 0xeb, 0xdc, 0x13, 0xff, 0xc5, 0x3c, + 0xe6, 0x6b, 0xa4, 0x28, 0x56, 0x87, 0xa2, 0x71, 0xaa, 0x65, 0xa5, 0x14, 0x3e, 0xe0, 0xb6, 0x13, 0xdc, 0x91, 0xb0, + 0x7e, 0x79, 0x8c, 0x93, 0x0d, 0xfe, 0x22, 0xf3, 0x2e, 0x3c, 0x88, 0x74, 0x18, 0xa9, 0x86, 0x59, 0x2f, 0xed, 0x93, + 0x76, 0x2f, 0x6d, 0x36, 0x91, 0x93, 0x91, 0x64, 0x98, 0xaa, 0xe4, 0x3c, 0x87, 0x0d, 0xa4, 0xb1, 0x9d, 0x23, 0x2f, + 0x83, 0xb3, 0xa6, 0xcb, 0x65, 0x15, 0x06, 0x60, 0xe2, 0xb4, 0xc6, 0x0f, 0x5c, 0x55, 0xc0, 0xb9, 0xc1, 0xc9, 0x7d, + 0x7d, 0xbd, 0x4b, 0xa2, 0x79, 0x45, 0x9c, 0x06, 0x02, 0x73, 0xee, 0xcc, 0xe7, 0x11, 0x78, 0x29, 0x4a, 0xf1, 0x53, + 0xa5, 0x30, 0xd9, 0x2d, 0x1b, 0x0d, 0x92, 0x32, 0xbf, 0x0d, 0xf2, 0xf8, 0x92, 0x02, 0x7a, 0xb9, 0xe4, 0x04, 0x7a, + 0xac, 0xfa, 0xff, 0xc0, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, 0x09, 0xe2, 0x79, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xe1, + 0x6e, 0x88, 0xb2, 0x96, 0x68, 0x02, 0xbd, 0x8b, 0x6c, 0x1e, 0xa8, 0x08, 0xb7, 0xa8, 0x94, 0xcf, 0x4d, 0xf1, 0x5c, + 0xb5, 0x7d, 0x5d, 0x25, 0x8b, 0x42, 0x4b, 0x77, 0x9e, 0xb0, 0x5f, 0xe6, 0xf4, 0x9c, 0x85, 0xc6, 0xc9, 0x5d, 0x9a, + 0x04, 0x69, 0x48, 0x3f, 0xbc, 0x7b, 0x01, 0xd9, 0xee, 0x69, 0x02, 0x24, 0x96, 0x48, 0x7f, 0x17, 0xce, 0x49, 0xe2, + 0x86, 0xf4, 0x8a, 0x05, 0x74, 0x70, 0xb1, 0xbb, 0xd8, 0x58, 0x51, 0xbe, 0x46, 0x45, 0xeb, 0x02, 0xfc, 0x77, 0x12, + 0xca, 0x8b, 0xdd, 0xc5, 0x25, 0x2f, 0x5a, 0xbb, 0x8b, 0xc4, 0x0d, 0xd3, 0xa9, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xbb, + 0x0b, 0x06, 0x3f, 0x78, 0x71, 0x51, 0x54, 0x89, 0xa2, 0x25, 0x44, 0xc6, 0x14, 0x14, 0xee, 0x3a, 0xc8, 0xfd, 0x39, + 0x65, 0x89, 0x28, 0xba, 0xab, 0x67, 0xaa, 0x7b, 0x05, 0x24, 0xff, 0x4a, 0xa4, 0xc1, 0xac, 0xcd, 0xe5, 0xf3, 0xfb, + 0x9a, 0xcb, 0x34, 0xe1, 0x4c, 0xa4, 0xc5, 0xeb, 0x70, 0x4e, 0xe4, 0xe7, 0xe7, 0x81, 0x3c, 0x89, 0x9a, 0x57, 0xa7, + 0x2e, 0x7c, 0x81, 0x58, 0x69, 0x01, 0x53, 0x69, 0xec, 0xd3, 0xed, 0x47, 0x25, 0x93, 0xbb, 0x8c, 0xbf, 0x92, 0xaa, + 0xf2, 0x74, 0x9e, 0x05, 0x10, 0xeb, 0x55, 0x2a, 0xc5, 0xba, 0x57, 0xcc, 0x16, 0xfa, 0x9b, 0x8d, 0xb9, 0x91, 0x64, + 0xcb, 0xe1, 0x4c, 0x5f, 0x75, 0x6d, 0x07, 0x15, 0xf1, 0x44, 0x58, 0x33, 0x26, 0x56, 0xef, 0x9c, 0x85, 0x10, 0x78, + 0x61, 0xa1, 0x4a, 0x58, 0xac, 0x4d, 0x12, 0x54, 0xa4, 0x50, 0x64, 0x90, 0xc2, 0x65, 0x3b, 0x59, 0xb5, 0x0a, 0x84, + 0x10, 0x19, 0xd7, 0x03, 0xe1, 0xdb, 0xec, 0xec, 0xed, 0xe5, 0xd5, 0x89, 0x36, 0xa6, 0x70, 0xbe, 0x5c, 0x72, 0xea, + 0xe4, 0xf2, 0xd4, 0x4d, 0x44, 0x40, 0x19, 0x63, 0x58, 0xbe, 0xf1, 0x32, 0x5c, 0xf6, 0xe4, 0xe5, 0x45, 0x2f, 0x12, + 0x48, 0x94, 0x28, 0x23, 0x1a, 0xa9, 0x27, 0x5a, 0x25, 0xc3, 0xe6, 0xeb, 0xf2, 0x20, 0x7f, 0x0d, 0xeb, 0xed, 0x95, + 0xc5, 0x91, 0x56, 0x55, 0xb4, 0x5a, 0x9a, 0xa7, 0x19, 0x77, 0x1c, 0x1f, 0x07, 0x88, 0xf4, 0x7d, 0x31, 0xfb, 0x63, + 0x99, 0xef, 0x31, 0x68, 0x76, 0xbc, 0x4e, 0xe9, 0x0f, 0xa9, 0x9d, 0xaf, 0x96, 0xd9, 0x66, 0xea, 0x8c, 0x2e, 0xe0, + 0x09, 0x97, 0xbf, 0x15, 0xfa, 0xaa, 0x02, 0x39, 0xbb, 0xea, 0xb9, 0x9c, 0x24, 0x56, 0x0c, 0x4d, 0x2a, 0x03, 0x4e, + 0x0d, 0xaa, 0x61, 0x3a, 0xc2, 0x6c, 0xcb, 0xd8, 0xa8, 0xa8, 0x10, 0x51, 0x6e, 0xee, 0x0b, 0xa9, 0x04, 0x9d, 0x1b, + 0xd4, 0x7d, 0xc1, 0xb4, 0x1b, 0xaf, 0x4e, 0x77, 0x85, 0x42, 0x91, 0xc1, 0x19, 0x36, 0x55, 0x93, 0xb0, 0xdc, 0x92, + 0x64, 0x23, 0xf1, 0xba, 0xf2, 0x91, 0x66, 0xa4, 0x0a, 0x28, 0xae, 0x75, 0x00, 0xc9, 0x90, 0x9b, 0x00, 0x03, 0xc7, + 0x40, 0xce, 0xf5, 0x14, 0x80, 0xc7, 0x8c, 0x29, 0x9c, 0x54, 0x52, 0x1c, 0x07, 0x2f, 0xa4, 0x76, 0xef, 0xd9, 0x6f, + 0xdf, 0x9c, 0xbd, 0xb7, 0x31, 0x5c, 0x75, 0x46, 0xb3, 0xdc, 0x5b, 0xd8, 0x2a, 0xc7, 0xb0, 0x09, 0xf1, 0x6a, 0xdb, + 0xb3, 0xfd, 0x19, 0x1c, 0xda, 0x16, 0x4c, 0xb5, 0x75, 0xd3, 0xbc, 0xbe, 0xbe, 0x6e, 0xc2, 0x89, 0xb2, 0xe6, 0x3c, + 0x8b, 0x25, 0xbb, 0x09, 0xed, 0xa2, 0x40, 0x2e, 0x8f, 0x68, 0x52, 0x5e, 0x86, 0x94, 0xc6, 0xd4, 0x8d, 0xd3, 0x89, + 0x3c, 0x0f, 0xbb, 0xea, 0x9e, 0x88, 0x2f, 0x8e, 0xc5, 0x25, 0x5f, 0xfd, 0x63, 0x2e, 0xaf, 0x57, 0xe3, 0x19, 0xfc, + 0xec, 0x43, 0xf0, 0xea, 0xb8, 0xc5, 0x23, 0xf1, 0x70, 0x06, 0xbb, 0x49, 0x3c, 0xed, 0x2e, 0xd6, 0xa8, 0x6e, 0x00, + 0x5d, 0x44, 0x7d, 0x39, 0xb5, 0x5c, 0xd4, 0xba, 0xf0, 0xe2, 0x8b, 0x8b, 0xe2, 0xb8, 0x05, 0x7d, 0xb5, 0x74, 0xbf, + 0x97, 0x69, 0x78, 0xab, 0xdb, 0x97, 0x94, 0x08, 0x97, 0x3d, 0x25, 0xa4, 0x0f, 0x5d, 0xc0, 0xb8, 0x61, 0x5f, 0xe0, + 0x4c, 0xb1, 0xd0, 0x61, 0xf5, 0x50, 0x8c, 0x2c, 0x60, 0x98, 0x05, 0x94, 0x00, 0xb9, 0x41, 0xe7, 0x61, 0xd9, 0x40, + 0xec, 0x76, 0x59, 0xb4, 0x0d, 0x40, 0x59, 0xb1, 0xda, 0x3f, 0xd2, 0xcd, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, + 0xbf, 0x40, 0xf0, 0xaf, 0x00, 0xfc, 0xb8, 0x25, 0xd1, 0x74, 0x61, 0x5e, 0x3b, 0x23, 0x2f, 0x84, 0x28, 0x91, 0x39, + 0xcc, 0x38, 0x7e, 0xcf, 0xf1, 0xc7, 0x0b, 0x51, 0x55, 0x6b, 0x09, 0xa0, 0xbe, 0x82, 0x36, 0xd5, 0xd6, 0xea, 0x60, + 0x90, 0xc6, 0xb1, 0x3f, 0xcb, 0xa9, 0xa7, 0x7f, 0x28, 0x85, 0x01, 0xf4, 0x8e, 0x75, 0x0d, 0x4d, 0xe5, 0x3d, 0x9d, + 0x82, 0x1e, 0xb7, 0xae, 0x3e, 0x5e, 0xf9, 0x99, 0xd3, 0x6c, 0x06, 0xcd, 0xcb, 0x09, 0x2a, 0x78, 0xb4, 0x30, 0xd5, + 0x8d, 0x87, 0xed, 0x76, 0x0f, 0x92, 0x54, 0x9b, 0x7e, 0xcc, 0x26, 0x89, 0x17, 0xd3, 0x31, 0x2f, 0x38, 0x9c, 0x1e, + 0x5c, 0x68, 0xfd, 0xce, 0xed, 0x1e, 0x66, 0x74, 0x6a, 0xb9, 0xf0, 0xf7, 0xee, 0x81, 0x0b, 0x1e, 0x7a, 0x09, 0x8f, + 0x9a, 0x22, 0x19, 0x1a, 0x8e, 0x72, 0xf0, 0xa8, 0xf6, 0xbc, 0x30, 0x06, 0x0a, 0x28, 0xe8, 0xbe, 0x05, 0xcf, 0x2c, + 0x1e, 0x61, 0x9e, 0x99, 0xf5, 0x12, 0xb4, 0x58, 0x9b, 0xc1, 0xba, 0x0a, 0xb6, 0x8f, 0x8a, 0x5c, 0x58, 0x2c, 0x8b, + 0x35, 0xbc, 0x18, 0xaa, 0x74, 0xc1, 0x92, 0xd9, 0x9c, 0x0f, 0x85, 0xe7, 0x3f, 0x83, 0x33, 0x24, 0x23, 0x6c, 0x94, + 0x00, 0x3c, 0x23, 0xd5, 0x3e, 0xf0, 0xe3, 0xc0, 0x81, 0x4e, 0xac, 0xa6, 0x75, 0x94, 0xd1, 0x29, 0xea, 0x4d, 0x59, + 0xd2, 0x94, 0xef, 0x0e, 0x0d, 0xdd, 0xcd, 0x7d, 0x04, 0x4f, 0x85, 0x2b, 0x7a, 0xc3, 0x22, 0xc1, 0x77, 0xc3, 0xbc, + 0x2e, 0x46, 0x45, 0xd1, 0x4b, 0xb9, 0x33, 0x7c, 0xe1, 0xa0, 0x11, 0xfe, 0xd5, 0xb8, 0xc4, 0xc6, 0xd6, 0x54, 0x6d, + 0xe3, 0x2e, 0xda, 0x52, 0xc5, 0xa4, 0x4b, 0x51, 0xed, 0x57, 0x02, 0x15, 0x5f, 0x3a, 0x36, 0xcd, 0x67, 0x4d, 0xc9, + 0x7e, 0x9a, 0x82, 0x7c, 0x6c, 0x68, 0x8a, 0x94, 0x3b, 0x9b, 0xd2, 0x85, 0xe0, 0x2c, 0xea, 0x1c, 0x8b, 0xf4, 0xb8, + 0x8c, 0xca, 0x73, 0x4f, 0xea, 0xd9, 0x3c, 0xe9, 0x84, 0x6a, 0x5b, 0xff, 0xe2, 0xa4, 0xce, 0xa6, 0x40, 0xfe, 0x97, + 0x77, 0xfd, 0xf9, 0x71, 0x0c, 0x03, 0x5e, 0x68, 0xa5, 0xc1, 0xbc, 0x1a, 0x65, 0xc8, 0x47, 0x0e, 0x2a, 0xd4, 0x9e, + 0x79, 0x22, 0xf4, 0x6e, 0xe3, 0x82, 0xc1, 0x1d, 0xae, 0x23, 0x6a, 0xf2, 0x04, 0x33, 0x83, 0x9c, 0x80, 0x5a, 0xee, + 0x78, 0xaf, 0x62, 0x33, 0x52, 0x6b, 0xb7, 0xc4, 0x84, 0x88, 0x9d, 0x25, 0xa1, 0x6d, 0xfd, 0x39, 0x88, 0x59, 0xf0, + 0x91, 0xd8, 0xbb, 0x0b, 0x07, 0xad, 0x1f, 0x0d, 0x15, 0x3b, 0x54, 0xf3, 0x5c, 0x54, 0x8f, 0x36, 0xa4, 0xae, 0xc1, + 0x4e, 0xe5, 0xed, 0x41, 0x76, 0x1f, 0x54, 0x9b, 0xe3, 0x96, 0x1c, 0xa7, 0x7f, 0x51, 0x9c, 0x57, 0xb7, 0x82, 0x55, + 0x50, 0x00, 0x9a, 0x65, 0xb9, 0x25, 0xe8, 0x8f, 0xd8, 0x72, 0x0b, 0xd5, 0x2c, 0x40, 0x6c, 0xd2, 0x3e, 0xb2, 0x2d, + 0xc9, 0x60, 0x00, 0x4e, 0xae, 0x78, 0x8d, 0x6d, 0xfd, 0xb9, 0x2c, 0xa3, 0xa5, 0xdb, 0x47, 0xe4, 0xad, 0x10, 0x1b, + 0xc6, 0x02, 0x5b, 0xdf, 0x0d, 0x29, 0xf7, 0x59, 0x2c, 0x9b, 0xf4, 0xb4, 0x97, 0x62, 0x65, 0x46, 0xcb, 0x65, 0x5e, + 0x9f, 0x0b, 0xab, 0x63, 0x50, 0xcc, 0xec, 0xb8, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0x87, 0x19, 0x3f, 0xad, 0x66, + 0x28, 0xdf, 0x59, 0x7f, 0x0e, 0xc4, 0xc9, 0x2a, 0x00, 0x30, 0x53, 0x00, 0x42, 0x64, 0x5f, 0x2a, 0x21, 0x8e, 0x4f, + 0x32, 0x97, 0xfb, 0xd9, 0x84, 0xf2, 0x15, 0xc4, 0xfa, 0x32, 0x91, 0xb7, 0xa7, 0xa3, 0xf8, 0x6b, 0xd0, 0x06, 0x75, + 0x68, 0x41, 0xcf, 0x2d, 0x06, 0xa0, 0xaa, 0x92, 0x8d, 0x1a, 0x6f, 0x84, 0x40, 0xf6, 0x89, 0xc5, 0x91, 0xdc, 0x3e, + 0x13, 0xdc, 0x5e, 0xc6, 0xe1, 0x2c, 0x31, 0x96, 0x00, 0xb1, 0xb0, 0xad, 0x81, 0x84, 0x9c, 0x86, 0x12, 0x66, 0x92, + 0x8a, 0x56, 0x59, 0x71, 0xdc, 0x92, 0xb5, 0x25, 0x3b, 0x96, 0x95, 0x00, 0x09, 0x62, 0x9f, 0x56, 0x38, 0x80, 0xe4, + 0x6f, 0x13, 0x0f, 0x21, 0xbb, 0x2a, 0x89, 0x4d, 0x9c, 0x31, 0xeb, 0x1f, 0xc7, 0xfe, 0x25, 0x8d, 0xfb, 0xbb, 0x8b, + 0x74, 0xb9, 0x6c, 0x17, 0xc7, 0x2d, 0xf9, 0x68, 0x1d, 0x0b, 0xbe, 0x21, 0xef, 0x06, 0x15, 0x4b, 0x0c, 0x07, 0x37, + 0x21, 0x25, 0x56, 0xe7, 0x82, 0x79, 0xaa, 0x83, 0xc2, 0xb6, 0x44, 0x16, 0x8a, 0xa8, 0x54, 0xea, 0x34, 0x85, 0x6d, + 0xb1, 0x70, 0xbd, 0x2c, 0xe7, 0x74, 0x06, 0xa5, 0xd1, 0x72, 0xd9, 0x29, 0x6c, 0x6b, 0xca, 0x12, 0x78, 0x4a, 0x97, + 0x4b, 0x71, 0x26, 0x72, 0xca, 0x12, 0xa7, 0x0d, 0x64, 0x6b, 0x5b, 0x53, 0xff, 0x46, 0x4c, 0x58, 0xbf, 0xf1, 0x6f, + 0x9c, 0x8e, 0x7a, 0xe5, 0x96, 0xf8, 0xc9, 0x81, 0xe2, 0xaa, 0x15, 0xf5, 0xd5, 0x8a, 0x86, 0x78, 0x2e, 0x4f, 0x7b, + 0x11, 0x27, 0x24, 0xfe, 0xe6, 0x15, 0x0d, 0xf5, 0x8a, 0xce, 0xb7, 0xac, 0xe8, 0xfc, 0x8e, 0x15, 0x0d, 0xd4, 0xea, + 0x59, 0x25, 0xee, 0xb2, 0xe5, 0xb2, 0xd3, 0xae, 0xb0, 0x77, 0xdc, 0x0a, 0xd9, 0x15, 0xac, 0x06, 0x68, 0x6a, 0x9c, + 0x4d, 0xe9, 0x66, 0xa2, 0xac, 0xa3, 0x98, 0x7e, 0x16, 0x26, 0x2b, 0x2c, 0xa4, 0x75, 0x2c, 0x98, 0x74, 0x5d, 0x06, + 0x26, 0xff, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x10, 0xe9, 0xbb, 0x42, 0x1d, 0xfb, 0xbd, 0x8d, 0x6d, 0xcb, + 0xd6, 0x64, 0x7d, 0x51, 0x9c, 0x83, 0x8c, 0x10, 0xf3, 0xbb, 0x17, 0x2d, 0x42, 0x6d, 0xbb, 0xbf, 0x9d, 0xe6, 0x20, + 0x87, 0xe0, 0x3a, 0xcd, 0x42, 0xdb, 0x93, 0x55, 0x3f, 0x0b, 0x55, 0x53, 0x96, 0xa8, 0x8c, 0xb4, 0xad, 0xb4, 0x56, + 0xbd, 0x37, 0x29, 0xae, 0x7b, 0x78, 0x28, 0x6b, 0xcc, 0x7c, 0xce, 0x69, 0x96, 0x28, 0xca, 0xb5, 0xed, 0xff, 0x10, + 0x54, 0xb8, 0x81, 0xaf, 0x04, 0x7a, 0x01, 0x34, 0x01, 0x2a, 0x9d, 0x5b, 0xf1, 0x7c, 0x29, 0x9e, 0x76, 0x2a, 0x65, + 0xf3, 0x16, 0x99, 0x7a, 0xbf, 0x2c, 0x02, 0x33, 0x64, 0x3e, 0xa5, 0xe1, 0xb9, 0x60, 0xd0, 0x83, 0xf8, 0x42, 0x29, + 0x8f, 0x2b, 0xe2, 0xae, 0x6a, 0x80, 0xed, 0x9f, 0xe6, 0xdd, 0x47, 0x07, 0xa7, 0x36, 0x96, 0x3c, 0x3e, 0x1d, 0x8f, + 0x6d, 0x54, 0x58, 0xf7, 0x6b, 0xd6, 0x39, 0xf8, 0x69, 0xfe, 0xf5, 0xb3, 0xf6, 0xd7, 0x65, 0xe3, 0x04, 0x88, 0x48, + 0x25, 0x41, 0x68, 0x51, 0x65, 0xc0, 0xab, 0x67, 0x34, 0xf6, 0x93, 0xed, 0xd3, 0x19, 0x9a, 0xd3, 0xc9, 0x67, 0x94, + 0x86, 0x40, 0x9c, 0x78, 0xad, 0xf4, 0x3c, 0xa6, 0x57, 0x54, 0xdf, 0xd0, 0xb8, 0x61, 0xb0, 0x0d, 0x2d, 0x82, 0x74, + 0x9e, 0x70, 0x95, 0x0d, 0xa2, 0x58, 0xad, 0x31, 0xa5, 0x0b, 0x31, 0x07, 0x53, 0x9d, 0xbf, 0x95, 0x72, 0xae, 0x2e, + 0xbd, 0x8a, 0x0b, 0x6c, 0x1b, 0x00, 0x6c, 0x85, 0x6c, 0xb0, 0xa5, 0xdc, 0x6b, 0xe3, 0xf6, 0x36, 0xd8, 0x70, 0x07, + 0x79, 0xb6, 0x3d, 0xd2, 0x78, 0x12, 0x0e, 0xdd, 0xda, 0xa5, 0x1a, 0x5b, 0xf1, 0xf5, 0x49, 0x0c, 0x5c, 0x66, 0xd0, + 0x59, 0x42, 0xf3, 0x7c, 0x2b, 0x02, 0xca, 0x45, 0xc4, 0x76, 0x55, 0xdb, 0xde, 0xd2, 0x0b, 0x6e, 0x63, 0xd8, 0x61, + 0x02, 0xe0, 0x32, 0xac, 0xac, 0x6a, 0xd1, 0xf1, 0x98, 0x06, 0xa5, 0x3f, 0x1c, 0x02, 0x84, 0x63, 0x16, 0x73, 0x88, + 0x93, 0x89, 0x00, 0x96, 0xfd, 0x3a, 0x4d, 0xa8, 0x8d, 0x74, 0xca, 0xab, 0x82, 0x5f, 0xc9, 0xff, 0xcd, 0xf0, 0xc8, + 0x1e, 0xeb, 0xb0, 0xa8, 0x51, 0x96, 0x4b, 0xed, 0xae, 0xa9, 0x95, 0xd7, 0x11, 0x99, 0x0a, 0x7f, 0xcc, 0xb6, 0x0d, + 0x74, 0xbf, 0x6d, 0xb2, 0xe8, 0x7c, 0x7d, 0xd8, 0x69, 0x17, 0x36, 0xb6, 0xa1, 0xbb, 0xfb, 0xee, 0x12, 0xd1, 0x6a, + 0x1f, 0x5a, 0xcd, 0x93, 0xcf, 0x69, 0xd7, 0xed, 0x3c, 0xee, 0xd8, 0x58, 0xde, 0xb5, 0x80, 0x8a, 0x92, 0x19, 0x04, + 0xe0, 0x21, 0xfe, 0xdd, 0x53, 0xa9, 0x77, 0x7e, 0x3f, 0x78, 0x1e, 0x76, 0xda, 0x36, 0xb6, 0x73, 0x9e, 0xce, 0x3e, + 0x63, 0x0a, 0xfb, 0x36, 0xb6, 0x83, 0x38, 0xcd, 0xa9, 0x39, 0x07, 0xa9, 0xce, 0xfe, 0xfe, 0x49, 0x48, 0x88, 0x66, + 0x19, 0xcd, 0x73, 0xcb, 0xec, 0x5f, 0x91, 0xd2, 0x27, 0x18, 0xe6, 0x46, 0x8a, 0xcb, 0x29, 0x17, 0x78, 0x91, 0xd7, + 0x20, 0x98, 0x54, 0x25, 0xcb, 0xd6, 0x88, 0x4d, 0x88, 0x80, 0x92, 0xb1, 0x49, 0xed, 0xea, 0x93, 0x23, 0x6f, 0xd8, + 0x7a, 0x72, 0x60, 0x19, 0x38, 0x5f, 0x1f, 0xa0, 0x56, 0x32, 0x65, 0xc9, 0xf9, 0x86, 0x52, 0xff, 0x66, 0x43, 0x29, + 0xa8, 0x6c, 0x25, 0x74, 0xea, 0x8a, 0x9e, 0x4f, 0x63, 0xbd, 0x52, 0x7c, 0x4c, 0x10, 0x43, 0xe1, 0x7f, 0xfc, 0x04, + 0xa4, 0xc6, 0x32, 0x88, 0x1e, 0x7e, 0xfb, 0x70, 0x50, 0xf2, 0x39, 0xc3, 0x95, 0xbd, 0xfc, 0xbe, 0x19, 0x42, 0x69, + 0x13, 0x9c, 0xfc, 0xf1, 0x67, 0xcd, 0x95, 0xde, 0x7c, 0x9a, 0xe0, 0x0c, 0xad, 0xea, 0x77, 0x2c, 0xbd, 0x3a, 0xea, + 0xbf, 0xba, 0xf6, 0x1b, 0x8a, 0x95, 0xe2, 0x53, 0xae, 0x7f, 0x10, 0xb3, 0x69, 0x45, 0x02, 0xeb, 0x60, 0x0a, 0x8d, + 0x07, 0x32, 0xbe, 0xcc, 0x4e, 0xa4, 0xea, 0x73, 0x0e, 0xe7, 0x58, 0xe1, 0xaa, 0x90, 0x79, 0x46, 0xcf, 0xe3, 0xf4, + 0x7a, 0xf5, 0xf2, 0xb3, 0xed, 0x95, 0x23, 0x36, 0x89, 0x8c, 0xc3, 0x69, 0x94, 0x94, 0x8b, 0x70, 0xe7, 0x00, 0xc5, + 0xbf, 0xfc, 0xb3, 0xeb, 0xfe, 0xcb, 0x3f, 0x7f, 0xb2, 0x2a, 0x74, 0x5f, 0x5c, 0x60, 0x5e, 0x75, 0xbb, 0x7d, 0x77, + 0x6d, 0x1e, 0xa9, 0x8e, 0xf3, 0xcd, 0x75, 0xd6, 0x16, 0x01, 0xde, 0xaf, 0x2d, 0xc1, 0x5a, 0xa1, 0xdc, 0x7d, 0xd6, + 0x6f, 0x01, 0x0c, 0xe6, 0xf5, 0x49, 0xc8, 0xa0, 0xd2, 0xef, 0x02, 0xed, 0x02, 0x79, 0xf7, 0x5a, 0x91, 0xdf, 0x8e, + 0xe1, 0x4f, 0xcd, 0xe1, 0x77, 0x82, 0xaf, 0xfc, 0x13, 0xf1, 0xc5, 0x45, 0x99, 0x85, 0x68, 0x36, 0x85, 0x3b, 0x0e, + 0x06, 0x6b, 0x25, 0x4a, 0xf1, 0xf0, 0xda, 0xa8, 0x2f, 0xce, 0x50, 0x92, 0xf8, 0xe2, 0x15, 0x5c, 0x6c, 0x74, 0x7c, + 0x99, 0x69, 0x67, 0xeb, 0x1d, 0xc2, 0x01, 0xba, 0xa8, 0xcf, 0x4a, 0x74, 0xba, 0x26, 0x19, 0xa0, 0x14, 0xcc, 0x0d, + 0x00, 0x13, 0xc7, 0x17, 0xca, 0xda, 0x3c, 0x95, 0x6e, 0x18, 0x6f, 0x95, 0xb4, 0x95, 0x7b, 0xa6, 0x86, 0x74, 0x6c, + 0xbd, 0x17, 0xf8, 0x12, 0x95, 0x69, 0x65, 0xdd, 0x0b, 0x57, 0x17, 0xd8, 0x11, 0x25, 0xfb, 0xb9, 0xf2, 0xe3, 0xab, + 0xfb, 0x31, 0xbe, 0xed, 0x02, 0x75, 0x69, 0x2d, 0xff, 0xd1, 0x2a, 0xc1, 0xb2, 0xb9, 0xdc, 0xa4, 0x0f, 0x5c, 0xfb, + 0x9c, 0x66, 0xe7, 0x11, 0x24, 0x42, 0x65, 0x9f, 0x60, 0x4e, 0xb0, 0xd2, 0x98, 0x8a, 0xbf, 0x8c, 0xa8, 0x8b, 0xa4, + 0xff, 0x41, 0x9c, 0x8a, 0x41, 0x16, 0x23, 0x0c, 0x65, 0x2c, 0xc2, 0xff, 0xe7, 0x5b, 0xff, 0x61, 0xf8, 0xd6, 0xdd, + 0x43, 0xd4, 0xce, 0x48, 0x7f, 0xf6, 0x42, 0xfe, 0xc7, 0x66, 0x77, 0xb9, 0x60, 0x77, 0xbf, 0x81, 0xd1, 0xe5, 0xff, + 0x18, 0x46, 0x27, 0x6c, 0x64, 0xcd, 0xe9, 0xd6, 0x42, 0xcd, 0xb7, 0xae, 0x7f, 0xed, 0xdf, 0x56, 0xfb, 0x2a, 0xbe, + 0x38, 0xb9, 0xf6, 0x6f, 0xab, 0x45, 0xd8, 0xce, 0x2e, 0x56, 0xfb, 0x18, 0xd8, 0x6f, 0x5e, 0xdb, 0x9e, 0xfd, 0xe6, + 0xeb, 0xaf, 0x6d, 0x7c, 0x91, 0x53, 0x3e, 0x80, 0x42, 0xb2, 0xbb, 0xd8, 0x59, 0xad, 0x08, 0x6e, 0x14, 0x98, 0xa2, + 0x08, 0x7b, 0xe1, 0xac, 0x06, 0x0c, 0xcb, 0xcf, 0xd3, 0xc4, 0x84, 0xe6, 0x2d, 0x58, 0xf6, 0x9f, 0x0b, 0x8e, 0xe8, + 0x65, 0x0d, 0x1e, 0x51, 0xba, 0x0a, 0x90, 0x28, 0xac, 0x41, 0x54, 0x5d, 0x19, 0x74, 0x37, 0xff, 0xaf, 0xae, 0x45, + 0x90, 0xb7, 0x7d, 0x44, 0x83, 0xf8, 0xe2, 0x73, 0xc4, 0x87, 0x1c, 0xac, 0xf2, 0xd8, 0x69, 0x77, 0xa7, 0x5f, 0xec, + 0x2e, 0xa2, 0xbd, 0x3d, 0x36, 0xb0, 0xb1, 0xb8, 0xa7, 0xa9, 0xd8, 0x24, 0x5c, 0x72, 0xf8, 0x93, 0xc2, 0x9f, 0xac, + 0x62, 0xd4, 0x2c, 0x19, 0x67, 0x7e, 0x46, 0xc3, 0xed, 0x4c, 0xba, 0xbc, 0xdf, 0x48, 0x91, 0x86, 0x4c, 0xc0, 0xce, + 0xcf, 0x45, 0xea, 0xd1, 0x94, 0x81, 0x3e, 0xba, 0x63, 0x7e, 0xc5, 0x47, 0x5d, 0x88, 0x56, 0x7e, 0x04, 0xc0, 0x44, + 0x38, 0x25, 0x79, 0x99, 0xeb, 0x00, 0xb7, 0x6a, 0xaa, 0xec, 0x10, 0x6c, 0x23, 0xe1, 0x75, 0x0f, 0x49, 0x5f, 0xa4, + 0x3d, 0xbc, 0x48, 0xb8, 0x13, 0xba, 0x3c, 0x63, 0x53, 0x07, 0xe1, 0x4e, 0x1b, 0x21, 0xed, 0x6c, 0x08, 0x49, 0x7f, + 0x87, 0xe5, 0xaf, 0xfd, 0xd7, 0x4e, 0x28, 0x2e, 0xe2, 0x12, 0x9f, 0xee, 0x81, 0x43, 0x92, 0x4f, 0xe6, 0xe3, 0x31, + 0xcd, 0x1c, 0x7d, 0x00, 0xf0, 0xab, 0x03, 0x38, 0x63, 0x0c, 0x6f, 0x9f, 0xfa, 0xdc, 0xff, 0x96, 0xd1, 0x6b, 0x27, + 0x43, 0xbd, 0xb4, 0xba, 0x9c, 0x31, 0xc4, 0x73, 0x44, 0xfa, 0x11, 0x24, 0xc6, 0xbf, 0x48, 0xf8, 0x7e, 0xd7, 0x99, + 0x7f, 0x75, 0x80, 0x43, 0xb8, 0xf2, 0x42, 0x67, 0x75, 0xcb, 0xbb, 0x4a, 0x3e, 0xb0, 0x84, 0x1f, 0xc9, 0x63, 0x98, + 0x19, 0x52, 0xee, 0xc3, 0x32, 0x23, 0xc6, 0xf2, 0xcb, 0x0e, 0x43, 0xd2, 0x0f, 0x1a, 0x44, 0x1e, 0xca, 0x14, 0xb7, + 0xec, 0x9e, 0x46, 0x7e, 0x76, 0x0a, 0x07, 0xbe, 0x01, 0xd0, 0x4b, 0x9e, 0xfa, 0x4e, 0x50, 0x7e, 0xc9, 0xc9, 0x69, + 0xfd, 0xd4, 0x68, 0x4d, 0xb0, 0x48, 0x8a, 0xa9, 0x8a, 0x5a, 0x50, 0x74, 0x6e, 0x16, 0x91, 0xc6, 0x6e, 0x0b, 0xc3, + 0x1e, 0xec, 0x6d, 0xf4, 0xd1, 0xea, 0xa5, 0x6b, 0x5e, 0x67, 0xfe, 0xac, 0x8c, 0x1b, 0x9c, 0xfa, 0x59, 0xc6, 0x68, + 0x66, 0x39, 0xcf, 0x7f, 0x45, 0xde, 0xbf, 0xfc, 0xf3, 0xe6, 0xf8, 0x81, 0x0a, 0x19, 0x58, 0x90, 0x5c, 0xd2, 0x14, + 0xe9, 0xd8, 0xc4, 0x0e, 0x64, 0x43, 0x5b, 0x87, 0x3b, 0xf6, 0x8f, 0xda, 0xed, 0xb6, 0x0a, 0x09, 0x74, 0xe4, 0x4f, + 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x10, 0x51, 0x65, 0x62, 0xcb, 0x00, 0xe5, 0x51, 0x7b, 0x76, 0x63, 0xf7, 0x61, 0x3b, + 0x28, 0x28, 0xde, 0xd1, 0x19, 0xf5, 0xf9, 0x67, 0x8d, 0x9f, 0x89, 0x26, 0xe5, 0xf0, 0x1d, 0x3d, 0x74, 0x35, 0xee, + 0xca, 0xa0, 0x87, 0xab, 0x83, 0xbe, 0x67, 0x53, 0x71, 0x75, 0xd3, 0xb6, 0x51, 0x85, 0xa7, 0xba, 0x36, 0x26, 0x97, + 0x2d, 0x6c, 0x4b, 0x60, 0x3c, 0x4a, 0xe3, 0x90, 0x66, 0xc4, 0xa6, 0xee, 0xc4, 0xb5, 0x1e, 0xb7, 0xdb, 0x6d, 0xdc, + 0x3c, 0x38, 0x6c, 0xb7, 0xf1, 0xe1, 0xc3, 0x36, 0x6e, 0xc2, 0x1f, 0xd7, 0x75, 0x57, 0x60, 0xb8, 0x2b, 0x6a, 0xdb, + 0x69, 0x67, 0x74, 0xaa, 0x00, 0xbc, 0x33, 0xac, 0x58, 0xed, 0x09, 0xb8, 0x60, 0x5a, 0xed, 0x7b, 0x29, 0xd9, 0xd4, + 0x05, 0x07, 0x2a, 0x1d, 0x55, 0xf8, 0x0b, 0xb3, 0x2a, 0x68, 0x4a, 0xe5, 0xc5, 0x7f, 0x2f, 0x14, 0x21, 0x78, 0xd6, + 0x29, 0xdc, 0x5e, 0x2a, 0xe2, 0xa5, 0x90, 0x0a, 0x04, 0x1f, 0x48, 0xe3, 0x3e, 0x4b, 0xe0, 0xdb, 0x59, 0x3a, 0x6a, + 0xaa, 0x19, 0x55, 0xb6, 0x92, 0x74, 0xfb, 0x40, 0x86, 0xa5, 0x37, 0x11, 0xc4, 0xe8, 0x01, 0xc2, 0xfe, 0x7d, 0x1a, + 0xa8, 0x15, 0x84, 0xfa, 0xc1, 0x7d, 0xea, 0x6b, 0xec, 0x8f, 0x1e, 0x88, 0xe4, 0xa4, 0x9d, 0x68, 0xb9, 0xdc, 0xf1, + 0x97, 0xcb, 0x9d, 0xe0, 0xfe, 0x33, 0x94, 0xcb, 0xab, 0x4f, 0x41, 0xc0, 0xcd, 0x9f, 0x12, 0xe8, 0x17, 0x50, 0xee, + 0x45, 0x58, 0x82, 0x24, 0x9f, 0x7c, 0xac, 0x06, 0x94, 0x8f, 0x41, 0xb1, 0x82, 0x94, 0x90, 0x44, 0xd2, 0x3e, 0x5f, + 0x2e, 0x15, 0xf1, 0xe3, 0x39, 0xf1, 0xcb, 0xa2, 0x8e, 0x8d, 0x67, 0x24, 0x28, 0x1f, 0x6d, 0x01, 0xf2, 0x4c, 0x71, + 0xa9, 0x0a, 0xe2, 0x6b, 0x3f, 0x4b, 0x4c, 0x80, 0x5f, 0xa7, 0x96, 0x1a, 0xd6, 0x9a, 0x65, 0xe9, 0x15, 0x83, 0xe4, + 0x97, 0x95, 0x81, 0xa7, 0x04, 0x2e, 0xfe, 0xea, 0x99, 0xa1, 0x70, 0xa3, 0x83, 0xf7, 0x9a, 0xcf, 0xc2, 0x2d, 0x93, + 0xe5, 0x04, 0xbd, 0x50, 0xcd, 0xcd, 0x9b, 0xeb, 0x69, 0xbd, 0xf3, 0xaf, 0xbd, 0x99, 0x7e, 0x78, 0x26, 0xf3, 0x6c, + 0xbc, 0x69, 0x79, 0xb2, 0xe6, 0x2d, 0x79, 0x0d, 0xb1, 0x1f, 0x5b, 0xf3, 0x6d, 0xb8, 0x67, 0x53, 0xf2, 0xb8, 0x77, + 0x2f, 0xcf, 0xa8, 0x9f, 0x05, 0xd1, 0x5b, 0x3f, 0xf3, 0xa7, 0x79, 0x6f, 0xac, 0x6f, 0xf1, 0xd2, 0x14, 0x70, 0x3e, + 0x16, 0x99, 0x4e, 0x49, 0x70, 0x6b, 0xe3, 0x10, 0xe1, 0xea, 0xbd, 0x84, 0x40, 0xfa, 0xb9, 0x6d, 0x3c, 0x37, 0x5f, + 0xc1, 0x3a, 0xdb, 0x78, 0x8a, 0xb0, 0x4c, 0x20, 0x7a, 0xfb, 0x47, 0xa6, 0x0e, 0x61, 0xc8, 0x75, 0xf1, 0xc6, 0x6e, + 0xf5, 0x95, 0x3b, 0x9d, 0x4c, 0xf4, 0x7e, 0x25, 0x99, 0x68, 0x03, 0x1a, 0xad, 0x8c, 0xe6, 0xb3, 0x34, 0xc9, 0xa9, + 0x8d, 0xdf, 0x43, 0x3b, 0x79, 0x15, 0xb3, 0xd9, 0x70, 0x8d, 0xe6, 0xca, 0xa6, 0xe2, 0x8d, 0x6c, 0x07, 0x41, 0x9d, + 0xf7, 0xdf, 0x97, 0x71, 0x7c, 0x1d, 0xdf, 0x11, 0x89, 0xe8, 0x8c, 0x6e, 0xc9, 0x95, 0xcd, 0xe9, 0x27, 0x73, 0x65, + 0xe3, 0x7b, 0xe5, 0xca, 0xe6, 0xf4, 0x8f, 0xce, 0x95, 0x65, 0xd4, 0xc8, 0x95, 0x05, 0x39, 0xf7, 0xf5, 0xbd, 0x52, + 0x2e, 0x75, 0x26, 0x5c, 0x7a, 0x9d, 0x93, 0x8e, 0x8a, 0x81, 0xc4, 0xe9, 0x04, 0xf2, 0x2d, 0xff, 0xf1, 0xe9, 0x93, + 0x71, 0x3a, 0x31, 0x93, 0x27, 0xe1, 0xc3, 0x24, 0x40, 0x76, 0x38, 0x25, 0x0b, 0xfb, 0xa7, 0x9b, 0xce, 0x93, 0x61, + 0xa7, 0xb7, 0xdf, 0x99, 0xda, 0x9e, 0x0d, 0x4e, 0x47, 0x51, 0xd0, 0xee, 0xed, 0xef, 0x43, 0xc1, 0xb5, 0x51, 0xd0, + 0x85, 0x02, 0x66, 0x14, 0x1c, 0x42, 0x41, 0x60, 0x14, 0x3c, 0x84, 0x82, 0xd0, 0x28, 0x78, 0x04, 0x05, 0x57, 0x76, + 0x31, 0x64, 0x65, 0x42, 0xf0, 0x23, 0x24, 0x6e, 0x30, 0xdc, 0x49, 0xeb, 0xa7, 0xb7, 0x23, 0xa2, 0xab, 0x3c, 0x2a, + 0x6f, 0x7e, 0x68, 0x1e, 0xe8, 0x8b, 0x0a, 0x2f, 0xbe, 0xb8, 0x00, 0xd6, 0x0a, 0x17, 0xb1, 0x60, 0x88, 0x49, 0xca, + 0x9a, 0xfb, 0xfa, 0xb5, 0xed, 0x95, 0x59, 0xb3, 0x6d, 0xdc, 0xd5, 0x79, 0xb3, 0x9e, 0x8d, 0x04, 0x5f, 0x92, 0x2f, + 0x0e, 0x1b, 0xa1, 0xea, 0x16, 0xee, 0x00, 0xac, 0x2e, 0xe0, 0xdc, 0x47, 0x78, 0xaa, 0x15, 0x20, 0xea, 0xc0, 0x07, + 0x18, 0xde, 0xb3, 0x29, 0xd5, 0xfb, 0x45, 0x0f, 0x60, 0x89, 0xcc, 0xe2, 0x5e, 0x54, 0x29, 0x46, 0x6f, 0xf1, 0xb8, + 0xba, 0xf3, 0xf5, 0x3d, 0x91, 0x77, 0xe8, 0xa5, 0x58, 0x86, 0xb9, 0x66, 0x98, 0xfb, 0x13, 0x0f, 0x52, 0x28, 0x21, + 0x63, 0xc4, 0x1b, 0x13, 0x42, 0xda, 0x83, 0xb9, 0xf7, 0x16, 0x5f, 0x47, 0x34, 0xf1, 0xa6, 0x45, 0xaf, 0x5c, 0x7f, + 0x99, 0xd2, 0xf9, 0xbe, 0xbc, 0x28, 0x5c, 0xd0, 0x44, 0xf5, 0x56, 0x42, 0xd9, 0x2c, 0x69, 0x67, 0x4b, 0xce, 0x9f, + 0xa1, 0xec, 0x8c, 0xe3, 0xf4, 0xba, 0x09, 0xe2, 0x7e, 0x63, 0x1e, 0x20, 0xcc, 0xad, 0xcc, 0x03, 0x7c, 0x09, 0xb0, + 0x96, 0x4f, 0xef, 0xfd, 0x49, 0xf9, 0xfb, 0x15, 0xcd, 0x73, 0x7f, 0xa2, 0x6a, 0x6e, 0xcf, 0xfb, 0x13, 0x20, 0x9a, + 0x39, 0x7f, 0x1a, 0x08, 0x48, 0xce, 0x03, 0x84, 0x40, 0x40, 0x57, 0xe5, 0xea, 0xc1, 0xcc, 0xeb, 0x69, 0x7e, 0x02, + 0x55, 0xf5, 0x22, 0xee, 0x4f, 0xaa, 0x82, 0xe3, 0x59, 0x46, 0x55, 0x02, 0x21, 0x60, 0xb1, 0x38, 0x6e, 0x41, 0x81, + 0x7c, 0xbd, 0x25, 0x9d, 0x4f, 0x73, 0x97, 0xed, 0x49, 0x7d, 0x96, 0x4e, 0xe7, 0x33, 0x4f, 0xa6, 0x94, 0xc7, 0x52, + 0xd6, 0x33, 0xf2, 0xbe, 0xec, 0x04, 0xf0, 0x9f, 0x3a, 0x78, 0xf1, 0xe5, 0x78, 0x3c, 0xbe, 0x33, 0xbd, 0xef, 0xcb, + 0x70, 0x4c, 0xbb, 0xf4, 0xb0, 0x07, 0xa7, 0x16, 0x9a, 0x2a, 0x11, 0xad, 0x53, 0x08, 0xdc, 0x2d, 0xee, 0x57, 0x19, + 0x72, 0xd6, 0x78, 0xb4, 0xb8, 0x7f, 0xaa, 0x5f, 0x31, 0xcb, 0xe8, 0x62, 0xea, 0x67, 0x13, 0x96, 0x78, 0xed, 0xc2, + 0xbd, 0x5a, 0x28, 0x50, 0x8f, 0x8e, 0x8e, 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x51, 0x4e, 0xa3, + 0xdd, 0x1e, 0x8f, 0x0b, 0x97, 0xe9, 0x82, 0xfd, 0x6e, 0x10, 0xee, 0x77, 0x0b, 0xf7, 0xda, 0xa8, 0x51, 0xb8, 0x54, + 0x3d, 0x65, 0x34, 0xac, 0x1d, 0x7d, 0x78, 0xd4, 0x6e, 0x17, 0xae, 0x24, 0xb4, 0x05, 0xc4, 0xe4, 0xe4, 0x4f, 0xcf, + 0x9f, 0xf3, 0xb4, 0xb8, 0x28, 0x8a, 0x5e, 0xcc, 0x9d, 0xe1, 0xae, 0xba, 0x56, 0x52, 0x7e, 0x87, 0xb1, 0x40, 0x23, + 0xfc, 0xb5, 0x99, 0x39, 0x07, 0xc4, 0x2c, 0x32, 0xe6, 0x62, 0x9d, 0x58, 0x57, 0x7b, 0x0d, 0x94, 0x25, 0x5e, 0x7f, + 0x4d, 0xe2, 0x2a, 0xa1, 0x0e, 0xf8, 0x18, 0xd4, 0x94, 0xb7, 0x9f, 0x27, 0xdb, 0xa4, 0x47, 0xf6, 0x69, 0xe9, 0x71, + 0x79, 0x1f, 0xe1, 0x91, 0xfd, 0xe1, 0xc2, 0x23, 0x31, 0x85, 0x87, 0x64, 0x1d, 0xd7, 0x9c, 0xd8, 0x41, 0x44, 0x83, + 0x8f, 0x97, 0xe9, 0x4d, 0x13, 0xb6, 0x44, 0x66, 0x0b, 0xb1, 0x72, 0xf5, 0x5b, 0x33, 0xf9, 0x75, 0x67, 0xc6, 0x47, + 0x1c, 0x85, 0x8e, 0xff, 0x26, 0x21, 0xf6, 0x1b, 0x1d, 0xd8, 0x93, 0x25, 0xe3, 0x31, 0xb1, 0xdf, 0x8c, 0xc7, 0xb6, + 0xbe, 0x1c, 0xc7, 0xe7, 0x54, 0xd4, 0x7a, 0x5d, 0x2b, 0x11, 0xb5, 0xc0, 0xd0, 0xaf, 0xca, 0xcc, 0x02, 0x95, 0x77, + 0x67, 0xe6, 0xd8, 0xa9, 0x37, 0x21, 0xcb, 0x61, 0xab, 0xc1, 0xb7, 0x25, 0xeb, 0x97, 0xf3, 0x27, 0xb5, 0x2f, 0x29, + 0x95, 0x00, 0x6f, 0xf8, 0xfc, 0xd3, 0xea, 0xcd, 0x70, 0x13, 0xaa, 0x55, 0xfc, 0x27, 0xb7, 0x2f, 0x42, 0xe7, 0x9a, + 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0x95, 0x5b, 0x1f, 0x24, 0x8c, 0x84, 0x98, 0xd3, 0x2a, 0x78, 0x3a, 0x99, 0xc4, 0xe2, + 0x30, 0x49, 0xcd, 0xe0, 0x96, 0xcd, 0x07, 0xb5, 0xf9, 0x7a, 0x66, 0x43, 0xf5, 0x79, 0x0d, 0xf1, 0xbd, 0x61, 0x79, + 0x5a, 0xf8, 0x4a, 0x7d, 0x78, 0x56, 0xc4, 0x04, 0x17, 0x8a, 0xc7, 0x2f, 0xe4, 0x19, 0x53, 0x8e, 0x59, 0x28, 0x9b, + 0xb3, 0xb0, 0x28, 0xd4, 0xe9, 0xfc, 0x90, 0xe5, 0x33, 0xd0, 0x9e, 0x64, 0x4b, 0xfa, 0x29, 0x16, 0x9e, 0x5f, 0x1b, + 0xc9, 0x6d, 0xb5, 0xe5, 0x2a, 0xb4, 0x9d, 0x26, 0xb3, 0x85, 0xae, 0x79, 0x61, 0x2b, 0x93, 0x4d, 0x23, 0xd1, 0xb6, + 0x24, 0x3e, 0x65, 0xda, 0x9d, 0x31, 0x43, 0xc8, 0xfc, 0x29, 0x17, 0x44, 0xbf, 0xd2, 0x05, 0x85, 0x69, 0x65, 0x89, + 0x37, 0x12, 0x5b, 0x22, 0x55, 0x2c, 0x9f, 0xf9, 0x89, 0x36, 0xe6, 0x24, 0x3f, 0xd8, 0x5d, 0x54, 0x2b, 0x5f, 0xd8, + 0x1a, 0x6c, 0x49, 0xbc, 0xfd, 0xe3, 0x16, 0x34, 0xe8, 0x5b, 0x35, 0xd0, 0x93, 0xb5, 0x0c, 0xb3, 0xbb, 0xf3, 0xae, + 0x3f, 0x5e, 0xb8, 0xf9, 0x35, 0x76, 0xf3, 0x6b, 0xeb, 0xab, 0x45, 0xf3, 0x9a, 0x5e, 0x7e, 0x64, 0xbc, 0xc9, 0xfd, + 0x59, 0x13, 0xbc, 0xa7, 0x22, 0x33, 0x44, 0xb1, 0x67, 0xa1, 0xa3, 0x4b, 0xd3, 0xaf, 0x37, 0xcf, 0x21, 0x3d, 0x5b, + 0x98, 0x51, 0x5e, 0x92, 0x26, 0xb4, 0x57, 0x3f, 0xbe, 0x67, 0x66, 0x18, 0x6b, 0x6c, 0x8d, 0x16, 0x29, 0xa4, 0x73, + 0xf3, 0x5b, 0xaf, 0xad, 0xd8, 0x7a, 0x5b, 0xa7, 0x0f, 0xb7, 0x37, 0xd6, 0xf7, 0x14, 0x72, 0x1b, 0x42, 0x7a, 0x65, + 0xeb, 0xf9, 0xcf, 0xdb, 0xf2, 0xbb, 0x3f, 0x75, 0x98, 0x0d, 0xf2, 0x49, 0xf4, 0xff, 0xc6, 0x29, 0xc0, 0xd5, 0x62, + 0x71, 0x98, 0xed, 0x3e, 0x90, 0x79, 0xfe, 0x98, 0xd3, 0x0c, 0xdf, 0xa7, 0xe6, 0xa5, 0xb8, 0x77, 0x62, 0x01, 0x62, + 0xc6, 0xeb, 0x1c, 0xd5, 0x53, 0xb1, 0xef, 0xee, 0xfe, 0xee, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x1e, 0x56, 0xdb, 0xee, + 0xc1, 0x46, 0x88, 0xfd, 0x5b, 0x8f, 0x25, 0x42, 0xe6, 0x5d, 0x42, 0x52, 0x48, 0x6f, 0x96, 0xaa, 0x53, 0x99, 0x19, + 0x8d, 0xc5, 0xa7, 0xd7, 0xd5, 0x52, 0xec, 0x3f, 0x9c, 0xdd, 0xe8, 0xd5, 0xe8, 0xac, 0x9c, 0xb6, 0xfc, 0x43, 0x0f, + 0x55, 0x6e, 0x3f, 0xc5, 0x59, 0x3f, 0x18, 0x78, 0x38, 0xbb, 0xe9, 0x49, 0x41, 0xdb, 0xcc, 0x24, 0x54, 0xed, 0xd9, + 0x8d, 0x79, 0xac, 0xb4, 0xea, 0xc8, 0x72, 0xf7, 0x73, 0x8b, 0xfa, 0x39, 0xed, 0xc1, 0x97, 0xa6, 0x58, 0xe0, 0xc7, + 0x4a, 0x98, 0x4f, 0x59, 0x18, 0xc6, 0xb4, 0xa7, 0xe5, 0xb5, 0xd5, 0x79, 0x08, 0xa7, 0x32, 0xcd, 0x25, 0xab, 0xaf, + 0x8a, 0x81, 0xbc, 0x12, 0x4f, 0xfe, 0x65, 0x9e, 0xc6, 0xf0, 0x9d, 0xc7, 0x8d, 0xe8, 0x54, 0xc7, 0x15, 0xdb, 0x15, + 0xf2, 0xc4, 0xef, 0xfa, 0x5c, 0x0e, 0xdb, 0x7f, 0xea, 0x89, 0x05, 0x6f, 0xf7, 0x78, 0x3a, 0xf3, 0x9a, 0xfb, 0xf5, + 0x89, 0xc0, 0xab, 0x72, 0x0a, 0x78, 0xc3, 0xb4, 0x30, 0x48, 0x2b, 0xc9, 0xa7, 0x2d, 0xb7, 0xa3, 0xca, 0x44, 0x07, + 0x60, 0x84, 0x96, 0x45, 0x45, 0x7d, 0x32, 0xff, 0x98, 0xdd, 0xf2, 0x78, 0xf3, 0x6e, 0x79, 0xac, 0x77, 0xcb, 0xdd, + 0x14, 0xfb, 0xe5, 0xb8, 0x03, 0xff, 0xf5, 0xaa, 0x09, 0x79, 0x6d, 0x6b, 0x7f, 0x76, 0x63, 0x81, 0x9e, 0xd6, 0xec, + 0xce, 0x6e, 0xe4, 0xa1, 0x5a, 0x48, 0x5c, 0x6b, 0xc3, 0x31, 0x53, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, + 0x75, 0x0e, 0xe0, 0x1d, 0xb4, 0x3a, 0x5c, 0x7f, 0xd7, 0xbd, 0x7b, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, + 0xe4, 0x72, 0xff, 0xf2, 0x92, 0x86, 0xde, 0x38, 0x0d, 0xe6, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdc, 0xd2, + 0x2b, 0xfd, 0xe8, 0xa6, 0xf2, 0x88, 0xaf, 0xee, 0x61, 0x51, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, + 0xb0, 0x61, 0x13, 0xfc, 0x9b, 0xac, 0xcd, 0xc6, 0xc9, 0xfc, 0x5e, 0x64, 0xdc, 0x89, 0x84, 0xcf, 0xc2, 0x81, 0xb9, + 0x86, 0xed, 0xa3, 0xcd, 0xe0, 0x0e, 0xf5, 0x48, 0x23, 0x2d, 0x14, 0x94, 0xdc, 0x09, 0xe9, 0xd8, 0x9f, 0xc7, 0xfc, + 0xee, 0x5e, 0xb7, 0x51, 0xc6, 0x5a, 0xaf, 0x77, 0x30, 0xf4, 0xaa, 0xee, 0x3d, 0xb9, 0xf4, 0x97, 0x8f, 0x0f, 0xe0, + 0x3f, 0x79, 0xf8, 0xe5, 0xb2, 0xd2, 0xd5, 0xa5, 0xd5, 0x0b, 0xba, 0xfa, 0x55, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, + 0xe3, 0xf7, 0xad, 0x0d, 0x5a, 0xe5, 0xbd, 0xaa, 0x2b, 0x2d, 0xeb, 0xb3, 0x6a, 0x7f, 0x5e, 0xe7, 0xf7, 0xac, 0x1b, + 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x7a, 0x7e, 0xad, 0xb2, 0xc6, 0xb8, 0xa8, 0x7f, 0x45, 0x2e, 0x4b, 0x13, 0x45, + 0xa6, 0xa2, 0x82, 0x95, 0x72, 0x25, 0xad, 0x94, 0x94, 0x92, 0x8b, 0xe3, 0xc1, 0xcd, 0x34, 0xb6, 0xae, 0xe4, 0xfd, + 0x38, 0xc4, 0xee, 0xb8, 0x6d, 0xdb, 0x12, 0x4e, 0x3a, 0xf8, 0x4c, 0x97, 0xfd, 0xe1, 0xfd, 0xd7, 0xcd, 0x23, 0x7b, + 0x00, 0x9a, 0xd6, 0xd5, 0x44, 0x68, 0x76, 0x2f, 0xfd, 0x5b, 0x9a, 0x9d, 0x77, 0x95, 0x0b, 0x5e, 0xe6, 0x8b, 0x8b, + 0x32, 0xab, 0x6b, 0x5b, 0x37, 0xd3, 0x38, 0xc9, 0x89, 0x1d, 0x71, 0x3e, 0xf3, 0x5a, 0xad, 0xeb, 0xeb, 0x6b, 0xf7, + 0x7a, 0xdf, 0x4d, 0xb3, 0x49, 0xab, 0xdb, 0x6e, 0xb7, 0xe1, 0x8b, 0x1f, 0xb6, 0x75, 0xc5, 0xe8, 0xf5, 0x93, 0xf4, + 0x86, 0xd8, 0x6d, 0xab, 0x6d, 0x75, 0xba, 0x47, 0x56, 0xa7, 0x7b, 0xe0, 0x3e, 0x3c, 0xb2, 0xfb, 0x5f, 0x58, 0xd6, + 0x71, 0x48, 0xc7, 0x39, 0xfc, 0xb0, 0xac, 0x63, 0xa1, 0x78, 0xc9, 0xdf, 0x96, 0xe5, 0x06, 0x71, 0xde, 0xec, 0x58, + 0x0b, 0xf5, 0x68, 0x59, 0x70, 0x8b, 0x90, 0x67, 0x7d, 0x39, 0xee, 0x8e, 0x0f, 0xc6, 0x8f, 0x7b, 0xaa, 0xb8, 0xf8, + 0xa2, 0x56, 0x1d, 0xcb, 0x7f, 0xbb, 0x46, 0xb3, 0x9c, 0x67, 0xe9, 0x47, 0xaa, 0x5c, 0xfb, 0x16, 0x88, 0x9e, 0x8d, + 0x4d, 0xbb, 0xeb, 0x23, 0x75, 0x8e, 0x2e, 0x83, 0x71, 0xb7, 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0x1e, 0xb7, 0x34, + 0xe8, 0xc7, 0x26, 0x9a, 0x3a, 0xcd, 0x4d, 0x88, 0xea, 0xd8, 0x6a, 0x8e, 0x13, 0x3d, 0xbf, 0x63, 0x38, 0xb4, 0xae, + 0x75, 0x55, 0x01, 0x81, 0x6d, 0x85, 0xc4, 0x7e, 0xd5, 0xe9, 0x1e, 0xe1, 0x4e, 0xe7, 0xa1, 0xfb, 0xf0, 0x28, 0x68, + 0xe3, 0x03, 0xf7, 0xa0, 0xb9, 0xef, 0x3e, 0xc4, 0x47, 0xcd, 0x23, 0x7c, 0xf4, 0xfc, 0x28, 0x68, 0x1e, 0xb8, 0x07, + 0xb8, 0xdd, 0x3c, 0x82, 0xc2, 0xe6, 0x51, 0xf3, 0xe8, 0xaa, 0x79, 0x70, 0x14, 0xb4, 0x45, 0x69, 0xd7, 0x3d, 0x3c, + 0x6c, 0x76, 0xda, 0xee, 0xe1, 0x21, 0x3e, 0x74, 0x1f, 0x3e, 0x6c, 0x76, 0xf6, 0xdd, 0x87, 0x0f, 0x5f, 0x1e, 0x1e, + 0xb9, 0xfb, 0xf0, 0x6e, 0x7f, 0x3f, 0xd8, 0x77, 0x3b, 0x9d, 0x26, 0xfc, 0xc1, 0x47, 0x6e, 0x57, 0xfe, 0xe8, 0x74, + 0xdc, 0xfd, 0x0e, 0x6e, 0xc7, 0x87, 0x5d, 0xf7, 0xe1, 0x63, 0x2c, 0xfe, 0x8a, 0x6a, 0x58, 0xfc, 0x81, 0x6e, 0xf0, + 0x63, 0xb7, 0xfb, 0x50, 0xfe, 0x12, 0x1d, 0x5e, 0x1d, 0x1c, 0xfd, 0x68, 0xb7, 0xb6, 0xce, 0xa1, 0x23, 0xe7, 0x70, + 0x74, 0xe8, 0xee, 0xef, 0xe3, 0x83, 0x8e, 0x7b, 0xb4, 0x1f, 0x35, 0x0f, 0xba, 0xee, 0xc3, 0x47, 0x41, 0xb3, 0xe3, + 0x3e, 0x7a, 0x84, 0xdb, 0xcd, 0x7d, 0xb7, 0x8b, 0x3b, 0xee, 0xc1, 0xbe, 0xf8, 0xb1, 0xef, 0x76, 0xaf, 0x1e, 0x3d, + 0x76, 0x1f, 0x1e, 0x46, 0x0f, 0xdd, 0x83, 0x6f, 0x0f, 0x8e, 0xdc, 0xee, 0x7e, 0xb4, 0xff, 0xd0, 0xed, 0x3e, 0xba, + 0x7a, 0xe8, 0x1e, 0x44, 0xcd, 0xee, 0xc3, 0x3b, 0x5b, 0x76, 0xba, 0x2e, 0xe0, 0x48, 0xbc, 0x86, 0x17, 0x58, 0xbd, + 0x80, 0xff, 0x23, 0xd1, 0xf6, 0xdf, 0xb0, 0x9b, 0x7c, 0xbd, 0xe9, 0x63, 0xf7, 0xe8, 0x51, 0x20, 0xab, 0x43, 0x41, + 0x53, 0xd7, 0x80, 0x26, 0x57, 0x4d, 0x39, 0xac, 0xe8, 0xae, 0xa9, 0x3b, 0xd2, 0xff, 0xab, 0xc1, 0xae, 0x9a, 0x30, + 0xb0, 0x1c, 0xf7, 0xdf, 0xb5, 0x9f, 0x72, 0xc9, 0x8f, 0x5b, 0x13, 0x49, 0xfa, 0x93, 0xfe, 0x17, 0xf2, 0x73, 0x3e, + 0x5f, 0x5c, 0x60, 0x7f, 0x9b, 0xe3, 0x23, 0xfe, 0xb4, 0xe3, 0x23, 0xa2, 0xf7, 0xf1, 0x7c, 0xc4, 0x7f, 0xb8, 0xe7, + 0xc3, 0x5f, 0x75, 0x9b, 0xdf, 0xf0, 0x35, 0x07, 0xc7, 0xaa, 0x55, 0xfc, 0x82, 0x3b, 0xc3, 0x14, 0x3e, 0x1d, 0x5d, + 0xf4, 0x6e, 0x38, 0x89, 0xa8, 0xe9, 0x07, 0x4a, 0x81, 0xc5, 0xde, 0x70, 0xc9, 0x63, 0x83, 0x6d, 0x08, 0x09, 0x3f, + 0x8d, 0x90, 0xef, 0xee, 0x83, 0x8f, 0xf0, 0x0f, 0xc7, 0x47, 0x60, 0xe2, 0xa3, 0xe6, 0xc9, 0x17, 0x9e, 0x06, 0xe1, + 0x29, 0x38, 0x13, 0xcf, 0x0e, 0xdc, 0x9a, 0xd1, 0xb0, 0x5b, 0xf4, 0x4a, 0x44, 0xee, 0x64, 0x70, 0xfd, 0xf9, 0xe7, + 0x04, 0x1d, 0xe4, 0x15, 0x39, 0xc4, 0x56, 0x6e, 0x99, 0x99, 0x90, 0x3a, 0xea, 0xa1, 0x14, 0x4a, 0x5d, 0xb7, 0xed, + 0xb6, 0x4b, 0x97, 0x0e, 0x5c, 0x8b, 0x44, 0x16, 0x29, 0xf7, 0xbd, 0x9d, 0x0e, 0x8e, 0xd3, 0x09, 0x5c, 0x96, 0x24, + 0x3e, 0x1f, 0x07, 0x27, 0x1e, 0x02, 0xf9, 0xe5, 0x3e, 0x48, 0x9f, 0x50, 0x8e, 0x1e, 0x3f, 0xfb, 0xf8, 0x37, 0x08, + 0x62, 0xea, 0x98, 0xc4, 0x14, 0xbc, 0x1d, 0xaf, 0x68, 0xc8, 0x7c, 0xc7, 0x76, 0x66, 0x19, 0x1d, 0xd3, 0x2c, 0x6f, + 0xd6, 0xee, 0xeb, 0x11, 0x57, 0xf5, 0x20, 0x5b, 0x41, 0x38, 0xce, 0xe0, 0x73, 0x48, 0x64, 0xa8, 0xfc, 0x8d, 0xb6, + 0x32, 0xc0, 0xec, 0x02, 0xeb, 0x92, 0x0c, 0x64, 0x6d, 0xa5, 0xb4, 0xd9, 0x52, 0x6b, 0xeb, 0xb8, 0xdd, 0x43, 0x64, + 0x89, 0x62, 0xf8, 0xd0, 0xcc, 0x0f, 0x4e, 0x73, 0xbf, 0xfd, 0x27, 0x64, 0x34, 0x2b, 0x3b, 0x1a, 0x29, 0x77, 0x5b, + 0x52, 0x7e, 0x8e, 0x70, 0x25, 0xec, 0x6a, 0x4b, 0x8a, 0xf8, 0x52, 0xce, 0xdd, 0x46, 0xbd, 0x44, 0x25, 0xcd, 0xc9, + 0x2b, 0x01, 0xc7, 0x6c, 0xe2, 0x18, 0xd7, 0x4d, 0x24, 0xf2, 0x43, 0x36, 0x70, 0x5b, 0x3d, 0x42, 0x45, 0x55, 0x25, + 0x41, 0x0b, 0x11, 0x6d, 0x61, 0x89, 0x95, 0x2c, 0x97, 0x4e, 0x02, 0x2e, 0x72, 0x62, 0xe0, 0x14, 0x9e, 0x51, 0x0d, + 0xc9, 0x09, 0x2e, 0x01, 0x12, 0x08, 0x26, 0x89, 0xfc, 0xb7, 0x2a, 0xd6, 0x3f, 0x94, 0xe3, 0xcb, 0x8d, 0xfd, 0x64, + 0x02, 0x54, 0xe8, 0x27, 0x93, 0x35, 0xb7, 0x9a, 0x0c, 0x18, 0xad, 0x94, 0x56, 0x5d, 0x55, 0xee, 0xb3, 0xfc, 0xc9, + 0xed, 0x7b, 0x75, 0xe3, 0xb5, 0x0d, 0xde, 0x69, 0x11, 0xdf, 0xa8, 0xbe, 0xce, 0xd3, 0x20, 0x0f, 0x8e, 0xa7, 0x94, + 0xfb, 0xf2, 0xb0, 0x1a, 0xe8, 0x13, 0x90, 0xcb, 0x62, 0x29, 0x6b, 0x54, 0x05, 0xf5, 0x89, 0x3c, 0xcc, 0x2f, 0x45, + 0x3d, 0xb6, 0xd4, 0x55, 0x71, 0x4d, 0xb1, 0x34, 0xa4, 0x83, 0xa5, 0x3f, 0x26, 0xf0, 0xc5, 0x71, 0x64, 0x92, 0xa4, + 0x76, 0xff, 0x41, 0x99, 0xeb, 0xb2, 0x6d, 0x11, 0x62, 0x96, 0x7c, 0x1c, 0x66, 0x34, 0xfe, 0x27, 0xf2, 0x80, 0x05, + 0x69, 0xf2, 0x60, 0x64, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, 0x8e, 0xc9, 0x03, 0x90, 0xf1, 0x9e, 0xb0, 0x3e, 0x80, 0x11, + 0x36, 0x6e, 0xa6, 0x31, 0x16, 0x1a, 0xd3, 0x3d, 0x14, 0x22, 0x09, 0xae, 0xdd, 0x3d, 0xb4, 0x2d, 0x69, 0x13, 0x8b, + 0xdf, 0x7d, 0x29, 0x4e, 0x85, 0x12, 0x60, 0x75, 0xba, 0xee, 0x61, 0xd4, 0x75, 0x1f, 0x5f, 0x3d, 0x72, 0x8f, 0xa2, + 0xce, 0xa3, 0xab, 0x26, 0xfc, 0xdb, 0x75, 0x1f, 0xc7, 0xcd, 0xae, 0xfb, 0x18, 0xfe, 0xff, 0xf6, 0xc0, 0x3d, 0x8c, + 0x9a, 0x1d, 0xf7, 0xe8, 0x6a, 0xdf, 0xdd, 0x7f, 0xd9, 0xe9, 0xba, 0xfb, 0x56, 0xc7, 0x92, 0xed, 0x80, 0x5d, 0x4b, + 0xee, 0xfc, 0x60, 0x65, 0x43, 0x6c, 0x08, 0xc6, 0xc9, 0x03, 0x77, 0x36, 0x16, 0x67, 0xa4, 0xcd, 0xfd, 0xa9, 0x9c, + 0x75, 0x4f, 0xfd, 0x0c, 0xbe, 0x6c, 0x5a, 0xdf, 0xbb, 0xb5, 0x77, 0xb8, 0xc6, 0x2f, 0x36, 0x0c, 0x31, 0x13, 0x11, + 0x70, 0xf3, 0xae, 0x35, 0xb8, 0xa8, 0x4c, 0x7c, 0x08, 0x4a, 0xdf, 0x87, 0xbf, 0x9d, 0xb4, 0x65, 0x45, 0x7d, 0xe7, + 0xbe, 0x60, 0x16, 0x4c, 0x7c, 0x72, 0x4f, 0x0c, 0xf2, 0x22, 0x2c, 0x56, 0xc7, 0x87, 0x73, 0x7f, 0x59, 0x6a, 0x5c, + 0x37, 0x47, 0xab, 0x20, 0x7f, 0xc8, 0xe0, 0x82, 0xc0, 0xa2, 0xd0, 0xa0, 0xd7, 0xdc, 0xb4, 0x15, 0x96, 0x04, 0xbf, + 0xa0, 0xf9, 0xc0, 0x86, 0x22, 0xdb, 0xb3, 0x85, 0x8b, 0xcf, 0x2e, 0xbf, 0xee, 0x5a, 0x12, 0x76, 0x55, 0x80, 0xc5, + 0xed, 0x0f, 0xb0, 0x6b, 0x01, 0x3f, 0x36, 0xda, 0xdb, 0xdb, 0xba, 0x5f, 0x84, 0x02, 0x09, 0x73, 0xad, 0x3e, 0x0a, + 0x69, 0xb2, 0x22, 0xdb, 0x44, 0x74, 0xd9, 0xaf, 0x40, 0x21, 0x52, 0x78, 0xba, 0xa4, 0x3e, 0x77, 0xfd, 0x44, 0x9e, + 0x20, 0x30, 0x18, 0x16, 0xee, 0xd0, 0x7d, 0x54, 0xa4, 0xdc, 0x97, 0x49, 0x61, 0xe6, 0x3e, 0x4f, 0xb9, 0xaf, 0x2f, + 0x4f, 0xf2, 0x79, 0xed, 0xe0, 0x7c, 0xd4, 0xed, 0xbf, 0x79, 0x7f, 0x62, 0xc9, 0xed, 0x79, 0xdc, 0x8a, 0xba, 0xfd, + 0x63, 0xe1, 0x33, 0x91, 0x61, 0x7f, 0x22, 0xc3, 0xfe, 0x96, 0xba, 0x35, 0x06, 0x22, 0x69, 0x45, 0x4b, 0x4e, 0x5b, + 0xd8, 0x0c, 0xd2, 0xdb, 0x3b, 0x9d, 0xc7, 0x9c, 0xc1, 0x47, 0x8d, 0x5a, 0x22, 0xe6, 0x2f, 0x72, 0x08, 0xf4, 0x21, + 0x54, 0xa5, 0x1d, 0x5e, 0xf2, 0x44, 0xfb, 0x86, 0xc7, 0x2c, 0xa6, 0xfa, 0xd8, 0xa9, 0xea, 0xaa, 0x4c, 0xf8, 0x59, + 0xaf, 0x9d, 0xcf, 0x2f, 0x21, 0xe9, 0x41, 0xa7, 0x17, 0x7d, 0x50, 0x0d, 0x8e, 0xc5, 0x50, 0x10, 0xb9, 0x97, 0x62, + 0x5a, 0x7f, 0xbe, 0xb5, 0xbe, 0xa4, 0x6a, 0xf6, 0x4a, 0x42, 0xc0, 0x55, 0x1d, 0xd1, 0x7e, 0xbf, 0x74, 0x17, 0x9b, + 0xef, 0x8a, 0xe3, 0x56, 0xb4, 0xdf, 0xbf, 0xf0, 0x26, 0xaa, 0xbf, 0x97, 0xe9, 0x64, 0x73, 0x5f, 0x71, 0x3a, 0x19, + 0x88, 0x73, 0xf0, 0xf2, 0x4e, 0x27, 0xad, 0xfc, 0xa6, 0xb1, 0xdd, 0x3f, 0x56, 0xca, 0x80, 0x25, 0xc2, 0xea, 0xf6, + 0x61, 0x5b, 0x1f, 0xad, 0x8f, 0xd3, 0x09, 0x6c, 0x48, 0xd9, 0xc4, 0x18, 0xa4, 0xe6, 0x71, 0x8f, 0x3a, 0xfd, 0x63, + 0xdf, 0x12, 0xbc, 0x45, 0x30, 0x8f, 0xdc, 0x6b, 0x41, 0xe3, 0x28, 0x9d, 0x52, 0x97, 0xa5, 0xad, 0x6b, 0x7a, 0xd9, + 0xf4, 0x67, 0xac, 0x72, 0x6f, 0x83, 0xd2, 0x51, 0x0e, 0x99, 0xae, 0xa4, 0x58, 0x75, 0x2b, 0x77, 0xdb, 0x01, 0xd8, + 0x3c, 0xda, 0x35, 0x27, 0x7c, 0x72, 0x06, 0x58, 0x69, 0xff, 0xb8, 0xe5, 0xaf, 0x60, 0x44, 0xf0, 0xfb, 0x42, 0x39, + 0xda, 0xc1, 0xb0, 0xb9, 0x14, 0xf9, 0x5d, 0x52, 0x1c, 0x68, 0x87, 0xbc, 0x12, 0xd4, 0x85, 0xdd, 0xff, 0xd7, 0xff, + 0xf1, 0xbf, 0x94, 0x8f, 0xfd, 0xb8, 0x15, 0x75, 0x74, 0x5f, 0x2b, 0xab, 0x52, 0x1c, 0xc3, 0x45, 0x35, 0x55, 0x50, + 0x98, 0xde, 0x34, 0x27, 0x19, 0x0b, 0x9b, 0x91, 0x1f, 0x8f, 0xed, 0xfe, 0x76, 0x6c, 0xca, 0xfc, 0xc3, 0xa6, 0x0e, + 0xa7, 0xae, 0x17, 0x01, 0xbd, 0xfe, 0xa6, 0x5b, 0x17, 0x74, 0x4a, 0x97, 0xd8, 0xda, 0xe6, 0x1d, 0x0c, 0xd5, 0xee, + 0xab, 0xdd, 0xc3, 0x90, 0xa8, 0x6f, 0x42, 0x2b, 0x0e, 0x98, 0xd4, 0xae, 0x5f, 0x28, 0x6c, 0xab, 0x0c, 0x6a, 0xfd, + 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x7e, 0x84, 0x58, 0xd5, 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, + 0x85, 0xfc, 0x33, 0x15, 0xcf, 0x12, 0x4c, 0xc5, 0xaa, 0x82, 0x59, 0x92, 0xbb, 0x58, 0x70, 0xaa, 0x6d, 0xca, 0x72, + 0xce, 0x82, 0xfa, 0x85, 0x0c, 0x67, 0x62, 0x40, 0xb1, 0x33, 0x15, 0x74, 0x62, 0x87, 0x17, 0x15, 0x41, 0xd5, 0x50, + 0x2e, 0x08, 0xb7, 0x38, 0x6e, 0x01, 0xbe, 0xef, 0x77, 0x9f, 0x8c, 0x5b, 0x2e, 0xc7, 0x42, 0x93, 0x09, 0x94, 0x14, + 0x55, 0xb9, 0x05, 0xb1, 0x95, 0x05, 0x3c, 0x7a, 0x5d, 0xa3, 0x58, 0xac, 0x5e, 0xad, 0x4d, 0xef, 0xe7, 0x79, 0xce, + 0xd9, 0x18, 0x50, 0x2e, 0xfd, 0xc4, 0x22, 0x8c, 0xdd, 0x04, 0x5d, 0x31, 0xbe, 0x2d, 0x44, 0x2f, 0x92, 0x40, 0x0f, + 0x8e, 0xfe, 0x54, 0xfc, 0x79, 0x0a, 0x1a, 0x99, 0xe5, 0x4c, 0xfd, 0x1b, 0x65, 0x9e, 0x3f, 0x6c, 0xb7, 0x67, 0x37, + 0x68, 0x51, 0x8d, 0x80, 0xb7, 0x0d, 0x26, 0xe8, 0xd8, 0xec, 0x50, 0xc4, 0xbf, 0x4b, 0x37, 0x76, 0xdb, 0x02, 0x5f, + 0xb8, 0xd5, 0x2e, 0x8a, 0xaf, 0x16, 0xc2, 0x93, 0xca, 0x7e, 0x85, 0x38, 0xb5, 0x72, 0x3a, 0x5f, 0xa6, 0xe6, 0xe4, + 0x16, 0x46, 0xab, 0xae, 0x6c, 0x15, 0x75, 0xd6, 0xaf, 0x66, 0x31, 0xe3, 0xec, 0x66, 0x84, 0xfc, 0x00, 0x62, 0xde, + 0x51, 0x07, 0x47, 0xdd, 0x45, 0xd9, 0x3d, 0xe7, 0xe9, 0xd4, 0x0c, 0xac, 0x53, 0x9f, 0x06, 0x74, 0xac, 0x9d, 0xf5, + 0xea, 0xbd, 0x0c, 0x9a, 0x17, 0xd1, 0xfe, 0x86, 0xb1, 0x14, 0x48, 0x22, 0xa0, 0x6e, 0xb5, 0x8b, 0x2f, 0x61, 0x07, + 0x2e, 0xc6, 0x71, 0xea, 0x73, 0x4f, 0x10, 0x6c, 0xcf, 0x0c, 0xcf, 0xfb, 0xc0, 0x93, 0xd2, 0x85, 0x01, 0x4f, 0x4f, + 0x56, 0x05, 0xb7, 0x79, 0xfd, 0x8a, 0xc6, 0xc2, 0x15, 0xcd, 0xcd, 0xae, 0xa4, 0xd7, 0xed, 0x3b, 0x15, 0xf5, 0x7e, + 0x5e, 0x73, 0x57, 0x29, 0x81, 0xd4, 0x45, 0x9b, 0xdf, 0x4b, 0xb9, 0x2e, 0xdf, 0x7e, 0xcf, 0x1d, 0x5b, 0x80, 0x69, + 0xaf, 0xd6, 0x12, 0x85, 0x50, 0xeb, 0x39, 0xf9, 0xae, 0x34, 0x99, 0xfc, 0xd9, 0x4c, 0x54, 0x44, 0xbd, 0xe3, 0x96, + 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, + 0x56, 0x78, 0xff, 0xff, 0x01, 0xa2, 0x89, 0x8c, 0x0d, 0xc4, 0x97, 0x00, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0x20, 0x98, 0x51, 0xd4, 0x8d, 0x56, 0x4b, 0xe5, 0xa2, 0xa8, 0x56, 0xa5, 0x80, 0x56, 0x05, 0xd9, 0x90, 0x89, - 0x0d, 0xfb, 0x77, 0x53, 0xb6, 0xa6, 0x94, 0xb5, 0x35, 0x4d, 0x09, 0x86, 0xa5, 0xbd, 0xe9, 0xf6, 0x5f, 0xc7, 0xd8, - 0xa5, 0xc5, 0x13, 0x67, 0x4e, 0x5c, 0xc8, 0x0a, 0xc3, 0x73, 0x8e, 0xd0, 0xd8, 0x27, 0xb9, 0xf7, 0xbe, 0x4d, 0xff, - 0xbf, 0x7e, 0x63, 0x35, 0x27, 0x95, 0x6f, 0x03, 0x48, 0x26, 0x74, 0x17, 0xcd, 0xb2, 0x2d, 0xa7, 0x0f, 0x84, 0x3d, - 0xe0, 0x49, 0x6c, 0xc9, 0x1d, 0x8d, 0x59, 0x62, 0xf2, 0xff, 0xf3, 0xfc, 0xac, 0xa5, 0xdf, 0x7d, 0x2e, 0x27, 0x83, - 0xa2, 0x56, 0xbd, 0xe9, 0x4a, 0xfd, 0xe5, 0xd8, 0xf8, 0x85, 0x59, 0x77, 0xcf, 0x9c, 0x10, 0x52, 0x98, 0xd0, 0xb6, - 0xf3, 0x17, 0x88, 0xa0, 0xb2, 0xd3, 0xfe, 0xbf, 0xda, 0xfa, 0x8a, 0xbb, 0x92, 0xc8, 0xa5, 0xcf, 0x29, 0xfc, 0x3e, - 0x57, 0x36, 0x86, 0x9e, 0x5e, 0x9e, 0x90, 0xd5, 0xfb, 0x32, 0x3b, 0x78, 0xb0, 0x3f, 0xa8, 0xc0, 0xa7, 0x29, 0x9b, - 0x63, 0xab, 0x96, 0x3f, 0xf2, 0xeb, 0x24, 0x98, 0x30, 0x9c, 0x28, 0xec, 0x20, 0x99, 0x71, 0xca, 0x01, 0x6b, 0xf3, - 0xb6, 0x34, 0x69, 0x05, 0x17, 0xb8, 0x27, 0x2e, 0xd6, 0xc1, 0xcc, 0x73, 0xbe, 0x59, 0xba, 0xac, 0x5a, 0xff, 0x07, - 0x35, 0x91, 0x76, 0x74, 0xc7, 0x0e, 0x72, 0x8d, 0x9d, 0x71, 0xfc, 0x41, 0xf6, 0xdf, 0x9b, 0x6a, 0x95, 0x36, 0x40, - 0xb3, 0xbb, 0xe7, 0x7c, 0x6a, 0x5c, 0x6a, 0x9c, 0x32, 0x88, 0x2b, 0x9d, 0xf3, 0x49, 0x70, 0x41, 0xc8, 0x7e, 0xef, - 0xfd, 0xff, 0x86, 0xed, 0x30, 0x44, 0x77, 0x13, 0x3b, 0x70, 0x94, 0x08, 0x92, 0x58, 0xfa, 0x12, 0xad, 0xe4, 0xff, - 0xff, 0x0d, 0x80, 0xdd, 0x00, 0xa5, 0x05, 0x29, 0x69, 0x8b, 0xe2, 0x70, 0xab, 0x68, 0xd6, 0x19, 0xce, 0xac, 0x3d, - 0xe3, 0x75, 0x53, 0x75, 0xd6, 0x45, 0x36, 0x4a, 0x8c, 0xcf, 0xae, 0x72, 0x1b, 0x85, 0xc6, 0xa6, 0x97, 0x5d, 0x78, - 0xe9, 0x39, 0x15, 0x55, 0xca, 0xed, 0x59, 0x9b, 0x06, 0x63, 0xd8, 0x32, 0x74, 0xf8, 0xac, 0x3a, 0xeb, 0xd9, 0x94, - 0x1b, 0xc2, 0x2d, 0x27, 0xc4, 0xba, 0x6d, 0xa4, 0xda, 0xe1, 0x38, 0xe9, 0x72, 0xee, 0x62, 0xa6, 0x10, 0x42, 0x03, - 0xc1, 0xfb, 0xe3, 0xc6, 0xf4, 0xc2, 0xdd, 0x9c, 0x44, 0x30, 0x31, 0xb6, 0x38, 0x40, 0x3a, 0x05, 0x7e, 0xe8, 0x50, - 0xa7, 0x9b, 0x52, 0x9c, 0x27, 0xe8, 0xf4, 0x37, 0x82, 0x69, 0xb6, 0x87, 0xa0, 0x1c, 0xc3, 0x81, 0x0d, 0x68, 0x64, - 0x79, 0xe6, 0xea, 0xdd, 0x07, 0x36, 0x5e, 0xd7, 0x2f, 0xc8, 0xa0, 0xc7, 0xbb, 0xdd, 0x1c, 0x70, 0x93, 0x92, 0x73, - 0xd7, 0x28, 0x1b, 0x41, 0xd7, 0xac, 0x5a, 0x08, 0xf2, 0x77, 0xfd, 0xf3, 0xb7, 0x37, 0x07, 0x1a, 0x93, 0xe8, 0x1f, - 0x52, 0xd3, 0x52, 0xc2, 0xb3, 0xa0, 0x4b, 0xda, 0x5e, 0xc0, 0xe1, 0x8b, 0x90, 0x87, 0x9e, 0x87, 0x5d, 0xf0, 0x5a, - 0x6b, 0xdd, 0x4e, 0x73, 0x3c, 0x33, 0x66, 0x6c, 0xb9, 0x48, 0xf5, 0x40, 0xcd, 0xf4, 0xce, 0xe1, 0xa0, 0x4b, 0x55, - 0x38, 0xab, 0xce, 0x49, 0xb4, 0xe9, 0x76, 0x89, 0x91, 0x3b, 0x5d, 0x7e, 0x9c, 0x52, 0xba, 0xf9, 0xbb, 0xad, 0x9a, - 0x84, 0x7b, 0x7a, 0x8b, 0x5f, 0xe3, 0xe1, 0x4f, 0x3b, 0x2f, 0xc2, 0x0a, 0x8a, 0x88, 0x78, 0xa4, 0x48, 0xb9, 0x3c, - 0x58, 0x4d, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0xc1, 0x48, 0x01, 0x2b, 0x1a, 0xe7, 0x08, 0xe7, 0x65, 0x7e, 0x9c, - 0x8c, 0x79, 0x59, 0xc4, 0xa7, 0x87, 0xc3, 0x79, 0xe7, 0x0e, 0xd7, 0x9d, 0x9b, 0xbd, 0x59, 0x0f, 0xa6, 0x6e, 0x5f, - 0x7f, 0x17, 0xf2, 0x6e, 0x58, 0x4f, 0xc1, 0xd6, 0x96, 0x5f, 0xbb, 0x5e, 0xf1, 0x0b, 0x35, 0x97, 0xae, 0xeb, 0xf5, - 0x80, 0x9b, 0xa6, 0x09, 0x32, 0x16, 0xda, 0x03, 0xfa, 0x73, 0x55, 0xc9, 0xfa, 0xf3, 0x20, 0x13, 0xca, 0x29, 0xfb, - 0x2e, 0xb8, 0xed, 0xba, 0xc4, 0xb1, 0x78, 0x42, 0xa6, 0x9a, 0xc8, 0x37, 0xf8, 0x8f, 0x80, 0x5a, 0x1e, 0x6c, 0xf0, - 0x28, 0xe4, 0x21, 0x30, 0xae, 0x23, 0x8a, 0xaa, 0xe6, 0x91, 0x50, 0xfd, 0xd6, 0xef, 0xd6, 0x20, 0x83, 0xfc, 0x5b, - 0xa3, 0x31, 0xda, 0x60, 0x08, 0x92, 0x99, 0xbb, 0x4d, 0xb2, 0x0b, 0x80, 0xc0, 0x54, 0x1d, 0x49, 0x69, 0x99, 0x47, - 0xe4, 0xe9, 0x78, 0x8e, 0x91, 0xf9, 0xc0, 0x7b, 0x1c, 0x16, 0xd3, 0x8d, 0xb8, 0xe1, 0x76, 0x00, 0x43, 0xc8, 0xdd, - 0x82, 0xa9, 0x6b, 0xca, 0x20, 0x19, 0xec, 0x14, 0x94, 0x34, 0x29, 0x90, 0x9c, 0x5d, 0xd3, 0x1c, 0x15, 0x01, 0x79, - 0xdd, 0xb5, 0xd3, 0xb1, 0x6f, 0x6b, 0xbc, 0xc5, 0x9b, 0xbf, 0xb3, 0x8e, 0x46, 0xc4, 0xf8, 0xbb, 0x6b, 0xe7, 0x92, - 0x8b, 0xb5, 0x02, 0xa4, 0x93, 0x70, 0xd7, 0x6b, 0xbf, 0x51, 0x3a, 0x6d, 0x9b, 0x39, 0x6c, 0x3f, 0x62, 0x26, 0xed, - 0xdc, 0x7a, 0x8f, 0x73, 0x9d, 0xaa, 0x98, 0x6d, 0x0e, 0x8f, 0x9f, 0x53, 0x24, 0x2a, 0xa9, 0x87, 0xed, 0xb7, 0x51, - 0x02, 0xfb, 0x5e, 0x6e, 0x3a, 0x4f, 0x98, 0xe9, 0x13, 0x9c, 0xf2, 0x8c, 0x58, 0x16, 0x30, 0xe5, 0x02, 0xf1, 0xde, - 0xc6, 0x4a, 0xb3, 0x4d, 0xd0, 0x10, 0xcc, 0xe4, 0x4f, 0xa5, 0x6b, 0x1b, 0xff, 0xb2, 0x88, 0x21, 0xd6, 0x41, 0x82, - 0x0f, 0x3f, 0x57, 0x0d, 0xa1, 0x94, 0xb0, 0x70, 0x9d, 0x8f, 0xef, 0x2a, 0x40, 0xca, 0x29, 0x90, 0x40, 0x42, 0x05, - 0xd4, 0xb9, 0x73, 0x46, 0xb0, 0xed, 0x27, 0x3c, 0xbf, 0x0f, 0xf2, 0x76, 0xb2, 0xc8, 0xf2, 0x5a, 0x64, 0x2b, 0x87, - 0x3b, 0x01, 0xf6, 0x7d, 0x9b, 0xea, 0x01, 0xf3, 0xd1, 0xef, 0x76, 0xb4, 0x39, 0x81, 0x85, 0xdb, 0x7a, 0x30, 0xdb, - 0x78, 0x5e, 0xfa, 0x17, 0x82, 0x5e, 0xf9, 0x1e, 0x44, 0xd3, 0x96, 0xa8, 0xc2, 0x7f, 0x7f, 0xfd, 0x9a, 0x40, 0xdc, - 0xb5, 0xe2, 0xd6, 0xff, 0xf0, 0xee, 0x26, 0x37, 0x44, 0x61, 0x3d, 0x70, 0x5d, 0xaa, 0xd3, 0xa5, 0x5a, 0x5f, 0x83, - 0x00, 0x34, 0x6e, 0x25, 0xd8, 0xdf, 0x14, 0x01, 0xb1, 0xfb, 0xd5, 0xf1, 0xaf, 0xdb, 0x11, 0x42, 0x82, 0xd4, 0xd9, - 0xce, 0x19, 0xf6, 0xbb, 0xf4, 0x41, 0x9b, 0x2d, 0x6a, 0x0a, 0xb3, 0x3f, 0x30, 0xbe, 0x26, 0x50, 0x28, 0x33, 0x9e, - 0x17, 0x99, 0xc4, 0x9d, 0xdc, 0xe1, 0x7a, 0x70, 0x5d, 0xe5, 0x2a, 0x7c, 0x24, 0xd6, 0x2a, 0x91, 0x3c, 0x73, 0xed, - 0x02, 0x7d, 0xb0, 0xe8, 0xc0, 0xae, 0x91, 0x11, 0xfe, 0xf3, 0xa8, 0x0a, 0x5e, 0x39, 0x9a, 0x95, 0x35, 0x5f, 0x8d, - 0x17, 0xbd, 0x05, 0x57, 0x7c, 0xde, 0xa9, 0x87, 0xce, 0xcc, 0xdb, 0xd1, 0xcf, 0x25, 0x83, 0xe4, 0xca, 0x62, 0x12, - 0x0a, 0x75, 0xea, 0x88, 0x32, 0x8b, 0x16, 0x18, 0x9b, 0xf9, 0xcb, 0x17, 0xcf, 0x82, 0x4e, 0x88, 0xb4, 0x9d, 0xca, - 0xce, 0x86, 0x67, 0xfc, 0x60, 0x87, 0x7a, 0x91, 0x9d, 0x4f, 0x48, 0x04, 0x0a, 0xdf, 0xba, 0xed, 0xd9, 0x7f, 0xca, - 0x43, 0xcb, 0x17, 0x5d, 0xfb, 0x93, 0x27, 0xd9, 0xed, 0x36, 0x12, 0xc5, 0x6d, 0x92, 0x90, 0xd8, 0x70, 0xd3, 0x7d, - 0x5c, 0xd6, 0x0a, 0x89, 0x4b, 0x34, 0xd7, 0x4a, 0x3b, 0xa5, 0x63, 0xec, 0xd2, 0x48, 0x59, 0xbb, 0x3d, 0x3e, 0x8b, - 0x1b, 0x7d, 0x15, 0x57, 0x20, 0x43, 0x4c, 0xd5, 0x13, 0xea, 0x9e, 0xc4, 0x35, 0x60, 0x58, 0x70, 0x64, 0x45, 0x73, - 0x21, 0x51, 0x09, 0x09, 0x86, 0xe9, 0xb4, 0x1f, 0x78, 0x29, 0xea, 0x6d, 0x10, 0x07, 0x88, 0x37, 0xf0, 0xf2, 0xfc, - 0x0a, 0x84, 0x15, 0xb5, 0x15, 0x80, 0x13, 0x55, 0x90, 0xf0, 0x15, 0x0a, 0x0c, 0x0a, 0xd4, 0x6b, 0x50, 0x04, 0x7b, - 0x44, 0xef, 0x04, 0x60, 0x90, 0x5b, 0xcd, 0x18, 0xde, 0xb6, 0x46, 0x6f, 0x03, 0x8e, 0xd9, 0xd8, 0x36, 0xcd, 0xa4, - 0x48, 0x61, 0x70, 0x7a, 0x89, 0xc5, 0x14, 0x75, 0xa3, 0xe6, 0xca, 0x92, 0xd8, 0x55, 0xdd, 0xdd, 0x9a, 0x22, 0x8d, - 0x7c, 0x58, 0x0f, 0xd1, 0x77, 0x67, 0xda, 0xe3, 0x02, 0x70, 0x0a, 0xb5, 0x61, 0xe5, 0xf6, 0x25, 0x8f, 0xb5, 0x50, - 0xf0, 0xf7, 0xbc, 0x6e, 0x20, 0xee, 0x45, 0x77, 0xea, 0x72, 0x22, 0x8c, 0xe3, 0x27, 0x03, 0xfb, 0xa9, 0x31, 0xc2, - 0x3d, 0xe4, 0x91, 0xb5, 0xb3, 0xa1, 0x0a, 0x8d, 0x70, 0x3d, 0x24, 0x9f, 0xf7, 0x97, 0xb4, 0xaf, 0x31, 0xd2, 0x71, - 0x71, 0x3e, 0xbc, 0x78, 0x63, 0x30, 0x15, 0xe0, 0x16, 0xad, 0xe7, 0xa0, 0xd9, 0x5a, 0xc6, 0x32, 0x7b, 0x70, 0xc8, - 0x8e, 0xe3, 0xda, 0xe9, 0xda, 0x22, 0xac, 0xda, 0x78, 0x20, 0x31, 0x24, 0xf0, 0x9b, 0x25, 0x86, 0x94, 0xc0, 0x4a, - 0x7c, 0xf4, 0xda, 0x40, 0x08, 0x5c, 0xbf, 0xe6, 0x20, 0x25, 0x98, 0xe5, 0xcb, 0x5f, 0xd2, 0x90, 0x8a, 0x5c, 0x0d, - 0x08, 0x19, 0xa9, 0xcf, 0x28, 0xcf, 0xac, 0xe0, 0x41, 0x71, 0xfc, 0x23, 0x46, 0x87, 0xcf, 0x9f, 0xed, 0x87, 0xc6, - 0xbe, 0x85, 0xf2, 0xa2, 0xac, 0x54, 0x66, 0x8e, 0x72, 0x42, 0x82, 0x22, 0x4b, 0x9e, 0x22, 0xb6, 0xf1, 0x15, 0x2b, - 0x41, 0x05, 0xf0, 0x8d, 0x40, 0xc6, 0xbb, 0x53, 0xc1, 0xb1, 0x89, 0x14, 0x01, 0x86, 0x76, 0x3b, 0x81, 0x84, 0xc0, - 0x20, 0x13, 0x47, 0x92, 0xab, 0xa3, 0x41, 0x62, 0x7f, 0x32, 0x8f, 0x5d, 0x38, 0x23, 0x92, 0xb5, 0x10, 0x24, 0x18, - 0x69, 0xbc, 0x57, 0x46, 0x9a, 0x80, 0xb0, 0x36, 0x40, 0xc7, 0xca, 0x3f, 0x83, 0x15, 0x96, 0x23, 0x30, 0x37, 0x2b, - 0xb8, 0x4b, 0xf3, 0x12, 0x42, 0xf4, 0x87, 0x95, 0x0a, 0xe8, 0xc7, 0x43, 0x7f, 0xce, 0x26, 0x28, 0x52, 0x10, 0xb4, - 0x42, 0x3c, 0xe4, 0x98, 0x4e, 0x14, 0x31, 0x70, 0xfa, 0xc7, 0x3d, 0x2c, 0xf6, 0x03, 0xb1, 0x60, 0x45, 0x45, 0x63, - 0x92, 0xbd, 0x14, 0xf5, 0x31, 0x62, 0xf0, 0x87, 0x19, 0x3b, 0x74, 0x9a, 0xa8, 0xa4, 0x97, 0x2a, 0x15, 0xeb, 0x60, - 0x5d, 0xa8, 0xac, 0x04, 0xe9, 0xd4, 0xe4, 0xe2, 0x1b, 0xa0, 0x28, 0x78, 0x27, 0x5e, 0x75, 0x06, 0x29, 0xbc, 0xd4, - 0x41, 0x2f, 0x40, 0xbf, 0x6c, 0x51, 0xe8, 0x19, 0x57, 0xe7, 0xde, 0xa4, 0x89, 0x2c, 0x61, 0x4f, 0xe8, 0xa0, 0x44, - 0xcb, 0x3f, 0xb8, 0xb0, 0x7a, 0x45, 0x08, 0x8e, 0x3d, 0x1f, 0xfe, 0xff, 0x69, 0x40, 0xfa, 0xf0, 0xa8, 0x87, 0x14, - 0x92, 0x08, 0x9f, 0xb0, 0xe5, 0x80, 0xae, 0x3b, 0x20, 0x29, 0x80, 0x77, 0x95, 0x31, 0x2d, 0x8f, 0x0b, 0xe2, 0xee, - 0x64, 0x4d, 0xcd, 0xd8, 0x2f, 0x13, 0xd0, 0xa9, 0xe0, 0xb8, 0x7a, 0xd7, 0x84, 0x35, 0xef, 0x6d, 0xa4, 0xe8, 0x58, - 0x60, 0x96, 0x40, 0x22, 0x44, 0x7a, 0x7f, 0x16, 0xe7, 0x42, 0xcc, 0xeb, 0x24, 0xb3, 0xdf, 0x72, 0x6a, 0x15, 0xa3, - 0x09, 0x14, 0x8e, 0x63, 0x59, 0xde, 0x93, 0x94, 0xe4, 0x09, 0x8f, 0x11, 0x8e, 0x57, 0x58, 0x47, 0xc1, 0x34, 0xa9, - 0x29, 0x29, 0x71, 0xf8, 0x5f, 0xa6, 0x34, 0x31, 0xd8, 0x95, 0xe8, 0x50, 0x11, 0x20, 0xa5, 0x59, 0x6a, 0x31, 0xf8, - 0x3c, 0x22, 0x1e, 0x0b, 0x80, 0x44, 0x44, 0xa2, 0xf0, 0x2f, 0x5d, 0xc9, 0xcf, 0x3c, 0x85, 0x88, 0xca, 0x4c, 0x83, - 0xce, 0xa2, 0xf7, 0xd5, 0x51, 0x4f, 0xd2, 0x6f, 0x74, 0x18, 0xd5, 0x2c, 0xff, 0x52, 0xf8, 0x90, 0xb8, 0xe1, 0xfe, - 0x59, 0x40, 0xa4, 0x7a, 0x93, 0x53, 0x2a, 0xed, 0x2c, 0xbd, 0xfc, 0xed, 0x0b, 0x14, 0x1b, 0x15, 0xc3, 0xf5, 0x63, - 0x7d, 0xb4, 0x21, 0xea, 0x9c, 0x1b, 0xe2, 0x80, 0x27, 0xac, 0x66, 0x4e, 0xe7, 0x8a, 0xbe, 0xb8, 0x4c, 0x1e, 0x13, - 0x53, 0x73, 0x9a, 0xde, 0xea, 0xe9, 0xb3, 0x48, 0x0e, 0x53, 0x67, 0x2b, 0x30, 0x05, 0x94, 0x61, 0xc5, 0x18, 0x59, - 0x0e, 0x24, 0xb1, 0x58, 0x72, 0xb9, 0x00, 0xa0, 0x45, 0xd6, 0x95, 0x63, 0x86, 0x42, 0xe5, 0x34, 0x32, 0x87, 0x83, - 0x8a, 0x63, 0xa4, 0x5d, 0xa9, 0x3e, 0x33, 0x84, 0x34, 0xea, 0xae, 0x01, 0x46, 0x14, 0x72, 0x96, 0xed, 0xbb, 0x28, - 0xe6, 0x22, 0x3c, 0x11, 0x06, 0xc8, 0xf3, 0x87, 0xd9, 0x66, 0xdd, 0x41, 0xe3, 0xc5, 0xc1, 0x78, 0x41, 0x65, 0xc3, - 0x48, 0xb2, 0x2c, 0x71, 0x50, 0x82, 0xc0, 0x29, 0x02, 0x8d, 0x7d, 0xfa, 0xd6, 0xa9, 0xfc, 0xfd, 0x32, 0x13, 0x89, - 0x87, 0x32, 0x8a, 0x11, 0x8f, 0x2f, 0xaa, 0xac, 0xab, 0x5b, 0x0e, 0x31, 0x7f, 0x78, 0xdb, 0xd8, 0x7e, 0xd3, 0x95, - 0x46, 0xcf, 0x0f, 0x9d, 0x15, 0x92, 0x66, 0x1c, 0xcd, 0xe9, 0xf4, 0x27, 0x71, 0x55, 0x53, 0x6c, 0x04, 0x14, 0x81, - 0xb0, 0xc7, 0x9b, 0x77, 0x4a, 0xa3, 0xbd, 0x13, 0xb0, 0x64, 0x1d, 0x83, 0x3d, 0xa9, 0xf6, 0x98, 0x90, 0xb4, 0xbc, - 0xff, 0x08, 0xcc, 0x95, 0x0a, 0x92, 0x4f, 0xc1, 0x87, 0x23, 0x94, 0x16, 0x14, 0xa2, 0x83, 0x4f, 0xba, 0x0d, 0x99, - 0x26, 0x60, 0xa2, 0x27, 0x41, 0x9e, 0x6d, 0xde, 0xb8, 0xa8, 0x42, 0x08, 0xe0, 0x81, 0xc9, 0xa6, 0x6f, 0xb2, 0xa4, - 0x55, 0xf6, 0xec, 0x3f, 0x87, 0x51, 0x96, 0xe5, 0x12, 0x9a, 0x04, 0xe9, 0x3d, 0x23, 0x72, 0xdb, 0x16, 0x9c, 0x9f, - 0xc5, 0x0a, 0xc9, 0xac, 0x2d, 0x0d, 0x69, 0x39, 0x84, 0x31, 0x28, 0x87, 0x8e, 0x08, 0xbe, 0x0c, 0x19, 0x56, 0x13, - 0x92, 0xe1, 0x5b, 0xfc, 0x07, 0x87, 0x4c, 0x52, 0x72, 0xa4, 0xc9, 0x7e, 0x2f, 0x06, 0x93, 0x5d, 0xe9, 0xa2, 0x02, - 0x1e, 0x66, 0xd3, 0x41, 0x0c, 0xc9, 0x56, 0xef, 0x29, 0xcd, 0x52, 0xcb, 0x11, 0xdc, 0x9d, 0x07, 0x52, 0xb0, 0x0d, - 0xaa, 0x9e, 0x47, 0x67, 0x1c, 0x2d, 0x00, 0xca, 0x5c, 0x92, 0xdc, 0x27, 0xc5, 0x20, 0x9b, 0x48, 0xa1, 0x80, 0x3d, - 0x65, 0x34, 0x86, 0x25, 0xb4, 0xfd, 0x71, 0x84, 0xc1, 0xd2, 0x90, 0x48, 0x91, 0x3e, 0x75, 0x62, 0xa7, 0x14, 0x8f, - 0x50, 0xf9, 0xd8, 0xba, 0x77, 0x50, 0x90, 0x40, 0x75, 0x92, 0x27, 0x08, 0xda, 0x73, 0xa0, 0x77, 0x4c, 0xc0, 0x7c, - 0x24, 0x19, 0xf1, 0xe3, 0x78, 0xbb, 0x62, 0x61, 0xf7, 0x21, 0xc5, 0x9d, 0x99, 0xdd, 0xfc, 0xc5, 0x7c, 0x8e, 0x34, - 0x67, 0x86, 0x4e, 0xea, 0x14, 0x92, 0xd9, 0x38, 0x27, 0xfa, 0x0b, 0xd2, 0xbc, 0x77, 0x11, 0x1d, 0xf1, 0x18, 0x7e, - 0x9f, 0x08, 0xae, 0x8f, 0xe7, 0x30, 0x82, 0xaf, 0xba, 0x28, 0x76, 0xb3, 0xde, 0x8a, 0x14, 0x5a, 0x3b, 0x19, 0xe2, - 0x82, 0xed, 0x3e, 0x18, 0x28, 0xa5, 0x24, 0xa2, 0xe9, 0xf7, 0x4a, 0x43, 0xc6, 0xa6, 0x41, 0x32, 0x63, 0x2b, 0x05, - 0x7a, 0x56, 0x8b, 0x38, 0x95, 0xd8, 0x91, 0x12, 0x74, 0x56, 0x38, 0x67, 0xa8, 0x01, 0x18, 0xed, 0xbc, 0xce, 0x1a, - 0x2c, 0x1d, 0x0c, 0x27, 0xae, 0xa1, 0x64, 0x8b, 0x3c, 0xc6, 0x87, 0x6e, 0xf6, 0x9e, 0xe5, 0x35, 0x40, 0xc1, 0x8f, - 0x8b, 0x20, 0xca, 0x03, 0xd4, 0x8c, 0xe0, 0xd8, 0x34, 0xab, 0x9e, 0xa4, 0x0d, 0xe7, 0x26, 0xbd, 0x19, 0x41, 0x5c, - 0xf6, 0x89, 0x8a, 0xc6, 0xff, 0x7e, 0x1c, 0x99, 0x7e, 0xb5, 0xea, 0x81, 0x94, 0x73, 0x16, 0x4a, 0xe3, 0x1b, 0x34, - 0xe2, 0x91, 0x07, 0xf6, 0xbb, 0xc6, 0x36, 0x4c, 0xa7, 0xa4, 0xa5, 0xc2, 0x7c, 0x55, 0x0d, 0xec, 0x80, 0x70, 0xd4, - 0xb2, 0x74, 0xac, 0x5f, 0x1e, 0x54, 0xf4, 0x7a, 0x9e, 0x7f, 0xb5, 0x7c, 0x6f, 0xd3, 0x02, 0x64, 0x67, 0x0c, 0x07, - 0x33, 0x26, 0x8d, 0x0a, 0xa8, 0x05, 0x64, 0xca, 0x3a, 0xa4, 0xe2, 0x69, 0x52, 0xc2, 0x91, 0x0d, 0x38, 0x1a, 0xb7, - 0x8d, 0xf4, 0x92, 0xf5, 0xd0, 0x01, 0xca, 0xac, 0xc3, 0x17, 0xb7, 0xad, 0xc7, 0x48, 0x35, 0xe0, 0x35, 0x00, 0x9c, - 0x14, 0xa9, 0x90, 0x12, 0x15, 0x52, 0x0e, 0x55, 0x4c, 0x07, 0x9d, 0x72, 0x4d, 0x9d, 0x95, 0x66, 0xe6, 0x5d, 0xdc, - 0xc1, 0x9f, 0x1e, 0x21, 0x84, 0x75, 0x19, 0x08, 0x16, 0xc5, 0x6f, 0x40, 0x10, 0x31, 0x59, 0x33, 0x7d, 0x23, 0x03, - 0x73, 0xbc, 0xa4, 0xe9, 0x57, 0x71, 0xc0, 0x2c, 0x96, 0x5e, 0x25, 0x26, 0xf1, 0x91, 0x51, 0x48, 0xdf, 0x58, 0x02, - 0xa2, 0x6e, 0x66, 0x79, 0x7e, 0xb5, 0xde, 0x33, 0x2e, 0x29, 0xf8, 0x98, 0x6f, 0xf7, 0xa3, 0xc2, 0xe1, 0xdb, 0x23, - 0x87, 0x03, 0x67, 0x90, 0x8a, 0x34, 0x66, 0x90, 0x53, 0xf0, 0xa2, 0x57, 0x98, 0xf1, 0xc7, 0x5c, 0xc9, 0x12, 0x51, - 0x78, 0x1b, 0xf0, 0xf7, 0x2c, 0x45, 0xe8, 0xf6, 0x80, 0xf0, 0x5d, 0xc8, 0xf8, 0xac, 0x84, 0x49, 0xfe, 0x08, 0x63, - 0x24, 0xb9, 0x7c, 0x1f, 0x6e, 0x2a, 0x93, 0xf1, 0xcd, 0x6f, 0x59, 0x14, 0xa8, 0x2c, 0x83, 0x69, 0x6a, 0x50, 0x52, - 0xe7, 0x00, 0x21, 0x8f, 0x9c, 0x57, 0xf5, 0xcc, 0xd4, 0x49, 0x23, 0xd2, 0x46, 0x1f, 0x64, 0x8a, 0x40, 0x74, 0x7a, - 0x10, 0x46, 0x1e, 0x08, 0x01, 0xf0, 0x1c, 0x02, 0x40, 0x4b, 0xe0, 0x0c, 0xe0, 0x98, 0xee, 0xc9, 0xa0, 0x11, 0x1a, - 0xf5, 0x9f, 0xed, 0x49, 0x54, 0xa4, 0x72, 0x1b, 0xdb, 0x0f, 0x7b, 0x8b, 0x44, 0xa3, 0x82, 0x1a, 0x8a, 0x29, 0xe2, - 0x6b, 0xfd, 0x4d, 0xe2, 0xae, 0xf7, 0xc9, 0x33, 0x8c, 0x2d, 0x4d, 0x23, 0x4d, 0x0b, 0x54, 0x3c, 0x75, 0x5f, 0xb0, - 0xb5, 0x27, 0x08, 0x69, 0x12, 0x8a, 0x32, 0x8c, 0xea, 0x9a, 0x2a, 0xc5, 0x2d, 0x1c, 0xc1, 0x51, 0xfa, 0xee, 0x44, - 0xdc, 0xfb, 0xc8, 0xf1, 0xe9, 0xcf, 0x08, 0x6a, 0x7d, 0x7e, 0xf4, 0xb6, 0xc9, 0xe9, 0x97, 0x61, 0x85, 0xbe, 0x12, - 0x11, 0xd1, 0x10, 0x06, 0x76, 0x38, 0xd0, 0x93, 0x86, 0x17, 0x63, 0x17, 0x77, 0x34, 0xd1, 0x83, 0x33, 0xf6, 0x54, - 0x86, 0xf4, 0xed, 0x99, 0xc8, 0xda, 0x16, 0xf5, 0xfa, 0xef, 0xe2, 0x4b, 0x78, 0x72, 0x3e, 0x1e, 0x93, 0x3a, 0x45, - 0x05, 0x9c, 0xa8, 0x55, 0xbd, 0x95, 0xc7, 0x60, 0x66, 0x1e, 0x7d, 0x2b, 0x26, 0x63, 0x9c, 0x9a, 0x91, 0x91, 0xb5, - 0x0b, 0x41, 0x5e, 0xec, 0x20, 0xbf, 0x53, 0x48, 0x7e, 0x74, 0x27, 0x03, 0x1a, 0x51, 0x10, 0x54, 0x8e, 0x1f, 0x28, - 0x94, 0x81, 0xb1, 0x7c, 0x6e, 0x6b, 0x3f, 0x21, 0xf6, 0x8c, 0x62, 0x19, 0xcf, 0x36, 0xe3, 0x39, 0x2f, 0x7f, 0xb1, - 0xa7, 0x41, 0x96, 0xd8, 0x7c, 0x26, 0x9e, 0x8e, 0x78, 0x68, 0x9b, 0x79, 0x41, 0xed, 0x04, 0xf0, 0x5e, 0x6a, 0x97, - 0xe6, 0x7a, 0xaa, 0xf5, 0x87, 0x91, 0xf6, 0x3e, 0x08, 0x52, 0x3e, 0x4f, 0xc2, 0xca, 0x43, 0x14, 0x28, 0xaa, 0x6d, - 0xc1, 0xf3, 0x93, 0x3d, 0xa7, 0x3c, 0x8a, 0x25, 0xb2, 0x59, 0x14, 0xd9, 0xd7, 0xac, 0xab, 0x3c, 0xa5, 0xfe, 0xc9, - 0xa8, 0x0f, 0xfe, 0x4d, 0x11, 0x1f, 0x71, 0xc3, 0x7f, 0x17, 0xab, 0xaa, 0xdf, 0xb4, 0x37, 0x5a, 0x28, 0x7d, 0x01, - 0x2f, 0x2e, 0x8a, 0xcb, 0xad, 0x5f, 0x3e, 0xf6, 0x52, 0x84, 0x26, 0x12, 0xe6, 0x16, 0x71, 0x6a, 0x3b, 0x28, 0x26, - 0xdf, 0xcf, 0x05, 0x74, 0x8a, 0x59, 0x71, 0xeb, 0x17, 0x35, 0x16, 0x1c, 0xde, 0x39, 0xe0, 0xa2, 0xf1, 0x64, 0x36, - 0x17, 0x42, 0xd1, 0x73, 0x50, 0xf5, 0x7b, 0xfb, 0x41, 0x32, 0x1b, 0xae, 0xdf, 0x38, 0x85, 0x13, 0x8b, 0x85, 0x9e, - 0x39, 0x87, 0xbf, 0x57, 0x9b, 0x1b, 0x2f, 0x65, 0xbd, 0xbe, 0x35, 0x7b, 0x7f, 0x8f, 0x9e, 0x53, 0xc6, 0xb6, 0xff, - 0x31, 0x44, 0xc2, 0x13, 0xbf, 0x5e, 0x84, 0x22, 0x5c, 0x13, 0x02, 0x1e, 0x54, 0xd2, 0xcd, 0x62, 0x55, 0x74, 0x9e, - 0xd3, 0x83, 0x77, 0x6b, 0xe1, 0xac, 0x30, 0x9c, 0xc6, 0x8e, 0xd3, 0x2e, 0xaf, 0xe8, 0xa9, 0x97, 0xb6, 0xfa, 0xa9, - 0x8b, 0xc3, 0x5b, 0x24, 0xae, 0x68, 0x39, 0x3e, 0x23, 0xd7, 0x7d, 0xd1, 0x54, 0xfe, 0x49, 0xd0, 0xf3, 0x32, 0xf8, - 0xbc, 0xc4, 0x55, 0x64, 0x6f, 0xbf, 0x6f, 0x57, 0x66, 0xb8, 0x5d, 0x79, 0xe7, 0x66, 0x77, 0xbf, 0xa3, 0xaa, 0xc6, - 0x9d, 0xe9, 0x6c, 0xe4, 0x1f, 0x96, 0x91, 0xd6, 0xd3, 0x2e, 0xdf, 0xfe, 0xaf, 0xd1, 0xef, 0x1f, 0xb7, 0x9e, 0xff, - 0xd2, 0x94, 0x32, 0x9f, 0xea, 0xb6, 0xe3, 0xa9, 0xe5, 0x72, 0x37, 0x56, 0xaf, 0xaf, 0x3f, 0xf9, 0x8c, 0x28, 0x3f, - 0x61, 0x12, 0x6c, 0x47, 0xeb, 0x32, 0xca, 0x95, 0x70, 0x8d, 0x66, 0xf6, 0xab, 0xed, 0x71, 0xfd, 0xb0, 0x9c, 0x66, - 0xf1, 0xea, 0xa3, 0xe4, 0x71, 0xb3, 0xb5, 0xbb, 0x5d, 0xcd, 0x4b, 0x9b, 0x57, 0x0b, 0x4a, 0x63, 0xc2, 0xd7, 0xf6, - 0x23, 0x5b, 0x30, 0xde, 0x04, 0x24, 0x7f, 0x20, 0x6a, 0xbe, 0xab, 0x37, 0x7d, 0x5b, 0x4d, 0xa9, 0x98, 0xe6, 0x34, - 0x11, 0x4d, 0x33, 0xaa, 0x21, 0x4e, 0x8a, 0x30, 0x0e, 0xb6, 0x33, 0xcf, 0x4f, 0x18, 0xe0, 0x9c, 0xca, 0x5d, 0x4c, - 0xfc, 0xcb, 0x4f, 0x53, 0x6d, 0xee, 0x34, 0xcb, 0x11, 0x4c, 0x8e, 0x62, 0x77, 0x72, 0xd8, 0x6e, 0xa0, 0x59, 0xde, - 0xe2, 0x0d, 0x55, 0xa5, 0x94, 0xe7, 0x62, 0x26, 0x81, 0xa2, 0x52, 0x33, 0xe8, 0x70, 0xa0, 0x9b, 0xb9, 0xd9, 0x4f, - 0x87, 0xff, 0x1e, 0xbb, 0x88, 0xe1, 0x14, 0xfe, 0xb9, 0x18, 0x84, 0x50, 0xd8, 0xb7, 0x90, 0x6a, 0xc2, 0x91, 0xb2, - 0xe1, 0x3b, 0x56, 0xe2, 0xef, 0x38, 0x33, 0x61, 0x34, 0x13, 0x61, 0x45, 0xd3, 0x7c, 0x06, 0xdc, 0xe3, 0x82, 0xb1, - 0x27, 0xc2, 0x6f, 0x6d, 0xb7, 0xec, 0xd4, 0xf5, 0xd9, 0xd0, 0x39, 0xc9, 0x02, 0x8e, 0x1b, 0x02, 0x07, 0xd0, 0xb8, - 0x33, 0x2f, 0xb2, 0xb5, 0xae, 0x57, 0x1f, 0x62, 0x2e, 0xba, 0x15, 0x69, 0x32, 0x7e, 0xab, 0xe8, 0xd2, 0xdd, 0x05, - 0x20, 0x69, 0xf5, 0xee, 0xc7, 0x5e, 0x3f, 0x38, 0x72, 0xf3, 0x56, 0xef, 0x65, 0x18, 0x1e, 0x6b, 0xf2, 0x91, 0x86, - 0xed, 0xe4, 0x86, 0x97, 0x2b, 0xd5, 0x44, 0x9b, 0x71, 0x5b, 0x5e, 0xb1, 0xd6, 0x1b, 0xd2, 0x95, 0xdd, 0x79, 0xa8, - 0x72, 0x1b, 0x2f, 0x5b, 0x84, 0xc1, 0x5c, 0x9c, 0xcd, 0xe4, 0x17, 0x48, 0xf4, 0xf5, 0xcd, 0x5c, 0xbe, 0x03, 0xce, - 0x1e, 0xa1, 0x4e, 0xf8, 0xeb, 0x55, 0x4f, 0xa6, 0x31, 0x89, 0x13, 0x9b, 0xf0, 0x70, 0xba, 0x52, 0x2c, 0x14, 0x02, - 0xef, 0xa6, 0x87, 0x20, 0xd1, 0xcf, 0x98, 0x52, 0x99, 0x74, 0x0f, 0x4d, 0x1a, 0x63, 0x5c, 0x9a, 0x65, 0xa3, 0x2e, - 0x2d, 0xe2, 0xa7, 0xcd, 0x35, 0xd3, 0x9a, 0x2d, 0x8d, 0x8a, 0x2a, 0xdb, 0xdc, 0xaf, 0x6a, 0x6f, 0xab, 0x7a, 0xf7, - 0x10, 0x64, 0xb0, 0x73, 0xe5, 0xf9, 0x45, 0x59, 0x69, 0xc6, 0x60, 0xf0, 0x94, 0x6f, 0xc4, 0x02, 0x19, 0xb7, 0x79, - 0x77, 0x98, 0xf8, 0xca, 0xa4, 0xbf, 0x76, 0x0d, 0x34, 0xe6, 0xee, 0x4f, 0xd6, 0xe9, 0xca, 0x1a, 0x23, 0x6e, 0x5b, - 0x2d, 0xe1, 0x02, 0x27, 0x9e, 0x42, 0xb9, 0xe9, 0xf6, 0x9d, 0x2f, 0x0b, 0x93, 0x9a, 0xbc, 0xe0, 0xf5, 0x1b, 0x10, - 0x05, 0xb3, 0x00, 0x01, 0x11, 0xf7, 0xa2, 0xd8, 0x74, 0xc4, 0x22, 0x06, 0x09, 0xf4, 0x06, 0x42, 0xe0, 0x0c, 0x7f, - 0x50, 0xd0, 0xb5, 0x1d, 0x18, 0x01, 0x00, 0xe4, 0x66, 0x43, 0xea, 0xa5, 0x52, 0xb9, 0x27, 0xa2, 0x6a, 0xa8, 0x56, - 0x97, 0x74, 0xd7, 0x5c, 0x97, 0xc0, 0x79, 0x9d, 0xb5, 0xf9, 0x53, 0x09, 0xcb, 0xba, 0x21, 0xce, 0x65, 0x85, 0x02, - 0x13, 0x15, 0xcd, 0x99, 0xa7, 0x82, 0xc0, 0x5a, 0x95, 0xac, 0xf1, 0x2c, 0x85, 0xdd, 0xfd, 0x59, 0xcd, 0xdd, 0x80, - 0xd3, 0xd8, 0x41, 0x98, 0x19, 0xf0, 0xb6, 0x7d, 0xbc, 0x61, 0xec, 0xed, 0xca, 0x59, 0xf0, 0xc8, 0x24, 0x5f, 0x96, - 0xee, 0x7e, 0x82, 0x1b, 0x2b, 0xfd, 0x94, 0x3e, 0x87, 0xb0, 0x24, 0xfc, 0x77, 0x85, 0xe0, 0xba, 0x34, 0xbe, 0xab, - 0x9e, 0x0b, 0x22, 0x78, 0xba, 0x64, 0x6f, 0x13, 0x79, 0x5f, 0x91, 0x13, 0x49, 0xf7, 0xce, 0x1a, 0x1f, 0x89, 0xe5, - 0xe7, 0xda, 0xf8, 0xbb, 0xa7, 0xfa, 0xca, 0x2a, 0x27, 0x91, 0x8d, 0xcf, 0xe5, 0x80, 0x65, 0x9e, 0xf7, 0x29, 0xd4, - 0x58, 0xa0, 0xc7, 0x30, 0x7b, 0xdc, 0xb0, 0x88, 0x9f, 0xc1, 0x16, 0xee, 0x94, 0x9a, 0xc6, 0xb4, 0x92, 0xac, 0x52, - 0x04, 0xce, 0xa7, 0xe0, 0x72, 0xce, 0xd3, 0xed, 0x86, 0xc4, 0x2f, 0xed, 0xa3, 0xb8, 0x0e, 0xfa, 0x69, 0x29, 0x36, - 0x7f, 0xfa, 0x8a, 0x16, 0x92, 0xd8, 0x82, 0xce, 0xcb, 0x16, 0x22, 0x60, 0x2f, 0x3e, 0xa5, 0xec, 0xb6, 0xff, 0x28, - 0xd5, 0x0c, 0x78, 0x95, 0x0f, 0x94, 0xa1, 0x18, 0x33, 0xa4, 0xb4, 0xe2, 0xaa, 0x13, 0x49, 0xd0, 0xdb, 0x3c, 0x15, - 0x02, 0xa7, 0xb0, 0x0f, 0xa5, 0x64, 0xa2, 0x1f, 0xb0, 0xcc, 0x72, 0x97, 0xbe, 0xe4, 0x9a, 0xf5, 0x76, 0xd7, 0x28, - 0x09, 0xcc, 0x04, 0xf9, 0x59, 0xf0, 0x89, 0xdb, 0x9e, 0xdc, 0x2d, 0xb9, 0x22, 0x30, 0x7f, 0x92, 0x89, 0xe0, 0xd8, - 0x40, 0x3e, 0x93, 0x8b, 0x27, 0x91, 0xa8, 0xa4, 0xd0, 0x2e, 0x39, 0x3a, 0x7a, 0xd7, 0x49, 0x6a, 0x15, 0x6b, 0x1d, - 0x0a, 0x1d, 0xb7, 0x71, 0x53, 0x59, 0xc7, 0x73, 0x12, 0xa3, 0xf6, 0xe8, 0x2e, 0x49, 0xdb, 0xec, 0xee, 0x54, 0x1a, - 0xa1, 0x92, 0xea, 0x0a, 0x19, 0x4b, 0x33, 0x92, 0x38, 0x3f, 0xb1, 0x45, 0x88, 0x18, 0x90, 0x58, 0x3a, 0xcb, 0x21, - 0x56, 0xdd, 0xa7, 0x0d, 0xcb, 0x71, 0xe8, 0x94, 0x25, 0x01, 0x45, 0xb3, 0x34, 0x46, 0x07, 0x03, 0xc7, 0xd1, 0x1c, - 0x55, 0x0a, 0x8c, 0x99, 0x97, 0x39, 0xec, 0x7c, 0x95, 0xa1, 0x73, 0x69, 0xa4, 0xd9, 0xf0, 0x75, 0x31, 0xb5, 0x47, - 0xa9, 0xce, 0xb5, 0x11, 0xc9, 0xc8, 0x41, 0x7b, 0x2e, 0x53, 0x11, 0x56, 0x71, 0x51, 0xee, 0xc6, 0x92, 0x59, 0x17, - 0x62, 0x9c, 0x8c, 0xf6, 0x6a, 0xb2, 0x68, 0x55, 0x40, 0x39, 0xbe, 0x64, 0xda, 0x03, 0x2e, 0x59, 0xdb, 0x7e, 0x29, - 0x27, 0x75, 0x81, 0xe6, 0x7c, 0xac, 0x2b, 0xfc, 0x8d, 0x2c, 0x80, 0x31, 0x3b, 0xf2, 0xa5, 0xdd, 0x6e, 0xfe, 0x25, - 0x27, 0xdb, 0x5f, 0xc6, 0x39, 0xf3, 0x98, 0x2b, 0x61, 0xec, 0x5a, 0x4d, 0xf4, 0x64, 0x86, 0x1a, 0x9f, 0x13, 0x70, - 0xc9, 0xeb, 0x27, 0x03, 0xec, 0x8c, 0xc7, 0xb9, 0xa4, 0x9d, 0xd2, 0xa5, 0xd2, 0x52, 0x9c, 0xc6, 0xdc, 0x64, 0x2d, - 0xab, 0xdd, 0x3f, 0x0f, 0xb1, 0x5c, 0xc1, 0xbe, 0xf5, 0x91, 0x75, 0x1f, 0xdf, 0x97, 0x29, 0x6f, 0xbd, 0x9a, 0xd1, - 0xaf, 0xb6, 0xc2, 0x84, 0xbd, 0xa3, 0x6b, 0x0c, 0x93, 0x1d, 0x6b, 0x15, 0xa4, 0x3d, 0xb2, 0xa3, 0x45, 0x32, 0x1e, - 0x4e, 0x68, 0x55, 0x7b, 0x21, 0x43, 0x1e, 0x7e, 0x6e, 0x34, 0x12, 0x8b, 0xa4, 0x58, 0x40, 0xe7, 0x7b, 0x54, 0x57, - 0x4b, 0x8a, 0xe9, 0x49, 0x6b, 0x32, 0x78, 0xd4, 0x99, 0x53, 0xe7, 0xca, 0x2f, 0x2c, 0xf7, 0x55, 0x53, 0x06, 0x03, - 0x71, 0xfd, 0x09, 0xea, 0xae, 0xec, 0x71, 0x2e, 0x31, 0x81, 0x9a, 0xb2, 0x68, 0xe2, 0x48, 0x32, 0xf9, 0xe5, 0xcb, - 0x4c, 0x9b, 0xec, 0xc3, 0x55, 0x24, 0x82, 0x17, 0x23, 0xb1, 0x85, 0xdf, 0xe9, 0x02, 0xcb, 0xa2, 0x3e, 0x6c, 0x1a, - 0x73, 0xe3, 0x28, 0x19, 0xae, 0x50, 0x04, 0x8e, 0x5a, 0x60, 0xa0, 0x24, 0x27, 0x6a, 0xb2, 0x66, 0x76, 0x9e, 0x0e, - 0x5e, 0x5c, 0x68, 0x1d, 0xdf, 0x11, 0x3a, 0xa4, 0x33, 0x94, 0x57, 0xf0, 0xcd, 0xbe, 0xcb, 0x5c, 0x60, 0xaa, 0x25, - 0x7d, 0x8c, 0x5e, 0x33, 0x7d, 0xec, 0x1a, 0xbc, 0x10, 0x3d, 0xb7, 0x96, 0x67, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, - 0x1e, 0x87, 0x77, 0x07, 0x59, 0xb1, 0x88, 0x6c, 0x77, 0x2e, 0x2e, 0x5b, 0x14, 0xe8, 0x14, 0x27, 0xeb, 0x36, 0xa8, - 0xd7, 0xa0, 0x29, 0xe7, 0x58, 0xa5, 0x31, 0x3b, 0x30, 0x43, 0x90, 0x0b, 0x1d, 0xb6, 0x44, 0xa9, 0xf4, 0x23, 0x4e, - 0x04, 0x1b, 0xac, 0xee, 0xcc, 0x66, 0x59, 0xb3, 0xc3, 0x9e, 0x93, 0xfa, 0x9f, 0x78, 0xd7, 0xb6, 0x9c, 0xd7, 0xc2, - 0x48, 0x13, 0xb2, 0xb1, 0x40, 0x7a, 0x94, 0xbf, 0xf9, 0xdb, 0x87, 0x7c, 0x61, 0xfa, 0xf5, 0xb0, 0x2a, 0x64, 0xc6, - 0x4e, 0xe0, 0x00, 0x32, 0x41, 0x06, 0x1f, 0x29, 0x3d, 0x93, 0x82, 0x91, 0xd6, 0xf7, 0xc2, 0x0c, 0xb6, 0x63, 0xb2, - 0x10, 0x1d, 0xab, 0xdd, 0x0c, 0x20, 0x87, 0x36, 0xb6, 0x7c, 0x0d, 0xa5, 0x55, 0x92, 0x96, 0x72, 0x71, 0x40, 0x61, - 0xd5, 0x5b, 0x71, 0xd3, 0x4b, 0xfb, 0x08, 0x4d, 0xbf, 0x4b, 0x06, 0xca, 0x94, 0x80, 0xf6, 0x33, 0xf3, 0x4a, 0x07, - 0x11, 0x1e, 0xa6, 0x34, 0x01, 0xd8, 0x10, 0x2b, 0x5b, 0xec, 0xad, 0xc5, 0xc2, 0x7b, 0xd2, 0x02, 0xd6, 0x34, 0x73, - 0xd8, 0x09, 0x58, 0x5f, 0xee, 0x26, 0x62, 0x53, 0xfe, 0x6c, 0x25, 0xd6, 0x1c, 0x71, 0x11, 0x1f, 0xbd, 0x5f, 0xd7, - 0xa7, 0x29, 0x16, 0xa9, 0x73, 0x6f, 0x3d, 0xc9, 0x00, 0xff, 0xbc, 0x78, 0x0e, 0x9c, 0xde, 0x25, 0xdf, 0xf7, 0xcf, - 0xd6, 0x92, 0xc5, 0xd5, 0xc0, 0xf1, 0x55, 0x2b, 0x93, 0xd3, 0x15, 0x2d, 0x05, 0x65, 0xb0, 0xf9, 0xbe, 0x77, 0x49, - 0x21, 0x6e, 0xa0, 0x3c, 0x9a, 0xf9, 0x08, 0xe3, 0xca, 0x2b, 0x7c, 0x4a, 0x8d, 0x78, 0x68, 0x26, 0x2c, 0x10, 0x49, - 0xad, 0x44, 0xc5, 0x82, 0x54, 0x55, 0x4f, 0x5f, 0x90, 0xa1, 0xe7, 0x02, 0x3e, 0xeb, 0x53, 0x3c, 0x38, 0x5b, 0x3b, - 0x0e, 0xa2, 0x68, 0x2b, 0x7e, 0x56, 0xa8, 0x10, 0xfc, 0x57, 0x81, 0x1a, 0x29, 0x32, 0x02, 0xcc, 0xf5, 0x84, 0xba, - 0x3f, 0x90, 0x27, 0x3c, 0x3f, 0xa5, 0x82, 0xa5, 0x42, 0x4e, 0xea, 0x94, 0x88, 0x28, 0xff, 0xca, 0xcb, 0x26, 0x41, - 0xb3, 0x9c, 0xd2, 0x98, 0x7c, 0xc4, 0x92, 0x08, 0xae, 0x66, 0x4d, 0x3e, 0xfd, 0x88, 0x52, 0xdd, 0xcb, 0x0c, 0xd7, - 0xa6, 0x04, 0x0d, 0x85, 0x6f, 0x3c, 0xe0, 0xe8, 0xd3, 0xed, 0x74, 0x42, 0x6e, 0x4b, 0x19, 0x9c, 0x7c, 0x44, 0x87, - 0xb9, 0xf5, 0xd5, 0x4c, 0xd0, 0xdc, 0x98, 0xb7, 0x0d, 0xc5, 0x2d, 0x21, 0xdb, 0xec, 0xd7, 0xbb, 0x35, 0xf9, 0x3a, - 0xfd, 0xe0, 0x92, 0xa6, 0x4c, 0xe8, 0x62, 0xe2, 0x17, 0x61, 0x86, 0x36, 0xdc, 0xf0, 0xe5, 0x8b, 0xed, 0xe5, 0x70, - 0x1c, 0x20, 0x73, 0x2c, 0xca, 0xef, 0xa8, 0xed, 0x19, 0x50, 0x50, 0x8e, 0xd1, 0x55, 0x6b, 0xc0, 0xd8, 0x8e, 0xad, - 0x75, 0x5f, 0x9e, 0x64, 0x0d, 0x50, 0x4f, 0xb5, 0x72, 0x8a, 0xc1, 0xd8, 0x87, 0x96, 0x6e, 0x03, 0x6c, 0x90, 0x3a, - 0x2c, 0x1c, 0x4c, 0xeb, 0x1f, 0x2d, 0x5e, 0x68, 0x01, 0x22, 0x6f, 0x92, 0xa5, 0x35, 0xde, 0x13, 0x7f, 0x07, 0xd7, - 0x14, 0x7c, 0x8f, 0xe3, 0x07, 0x89, 0xf7, 0x3c, 0xbb, 0xac, 0x28, 0x2a, 0x61, 0x9e, 0x0b, 0x6f, 0x88, 0xb0, 0x62, - 0x82, 0x98, 0x63, 0x1e, 0x72, 0x42, 0xf6, 0x85, 0x5b, 0xd6, 0xb6, 0x3a, 0x04, 0x3c, 0xbc, 0xef, 0xfb, 0xe9, 0x85, - 0x80, 0xa2, 0x2b, 0x3b, 0x77, 0x9c, 0x47, 0x33, 0x60, 0x35, 0x43, 0xbe, 0xc5, 0x76, 0x98, 0x8a, 0x32, 0x4a, 0x08, - 0xe2, 0x06, 0x2b, 0xb0, 0x30, 0xf4, 0xac, 0x71, 0xf5, 0x89, 0xd3, 0x7a, 0xca, 0x00, 0x80, 0x52, 0xda, 0xa1, 0x7b, - 0x86, 0x32, 0x61, 0xf4, 0xd2, 0x2a, 0x50, 0x6e, 0xb9, 0x3a, 0x78, 0xd9, 0xb9, 0xc7, 0x30, 0xb0, 0x33, 0x5b, 0xeb, - 0x4c, 0xe3, 0x40, 0x64, 0x19, 0x08, 0x10, 0x87, 0xba, 0x48, 0x95, 0x86, 0xa2, 0xeb, 0x00, 0xaf, 0x45, 0x7d, 0x92, - 0x61, 0x61, 0x21, 0xee, 0x56, 0xa2, 0x63, 0xc0, 0x34, 0x5e, 0xe3, 0xed, 0x42, 0x2a, 0x04, 0x5e, 0x09, 0x91, 0x07, - 0x12, 0xd9, 0x03, 0xed, 0xa0, 0x6c, 0x00, 0x24, 0xb9, 0x13, 0x5c, 0x29, 0x48, 0x6b, 0x09, 0xe5, 0x64, 0xff, 0x4f, - 0x54, 0x1a, 0x65, 0x02, 0xf2, 0x99, 0x6b, 0x89, 0x49, 0xe3, 0x25, 0x30, 0x17, 0x0e, 0x24, 0x1f, 0x66, 0xb0, 0x93, - 0x05, 0x8d, 0xc8, 0x94, 0xe9, 0xdc, 0x0a, 0xb6, 0xf1, 0xea, 0x4d, 0xd2, 0x48, 0x54, 0x98, 0xfe, 0xe6, 0x57, 0x97, - 0x4f, 0x5d, 0x18, 0x61, 0xf9, 0x5b, 0x2e, 0xfb, 0x1c, 0xf9, 0x4d, 0x18, 0x25, 0xed, 0x6c, 0xf8, 0x52, 0xc9, 0x74, - 0xdc, 0x9e, 0x9f, 0x69, 0x6d, 0xb4, 0x78, 0x0f, 0xf2, 0x05, 0xef, 0x41, 0x75, 0x47, 0x92, 0xec, 0x73, 0x5a, 0x93, - 0xd4, 0x35, 0xaa, 0xca, 0x70, 0x90, 0x68, 0x8c, 0x8b, 0xd4, 0x9a, 0x98, 0x53, 0xb3, 0x78, 0x1a, 0x40, 0x32, 0x8d, - 0xfd, 0x8c, 0x2a, 0x0f, 0x2c, 0x27, 0x36, 0x2f, 0xa6, 0x27, 0xd2, 0x68, 0xba, 0x20, 0x97, 0x9f, 0x52, 0xef, 0x66, - 0x4a, 0xd1, 0xb2, 0x58, 0x86, 0xc3, 0xd9, 0x41, 0x98, 0x23, 0x5d, 0xbe, 0x9a, 0xeb, 0xa3, 0x2f, 0x19, 0x26, 0xa5, - 0x4b, 0x57, 0xf2, 0x67, 0x94, 0x2c, 0x5f, 0x08, 0xab, 0x0f, 0xdb, 0x26, 0x08, 0x64, 0xd4, 0xa0, 0x1c, 0xe1, 0xd6, - 0xf2, 0x00, 0x1b, 0x1b, 0xf2, 0xe0, 0xec, 0xa6, 0x2a, 0x7b, 0x64, 0x9a, 0xb3, 0xa9, 0xa0, 0xf2, 0x46, 0xa3, 0x85, - 0x66, 0x26, 0x9b, 0xaf, 0x2e, 0xbe, 0x4a, 0x90, 0x1b, 0xa7, 0x83, 0xd5, 0x52, 0x7d, 0x68, 0x42, 0x56, 0x1f, 0xc8, - 0xcb, 0xa4, 0xa8, 0xaa, 0x85, 0x22, 0xed, 0x94, 0xfc, 0x34, 0x9a, 0xba, 0xeb, 0x4e, 0x72, 0x42, 0x65, 0x35, 0x89, - 0x8a, 0x02, 0x5b, 0x78, 0x59, 0x08, 0x15, 0x40, 0x71, 0xb7, 0xfb, 0xa1, 0x02, 0xe5, 0xcf, 0x45, 0x0e, 0xee, 0x78, - 0xaf, 0x0e, 0x4c, 0xcb, 0x00, 0x92, 0xfc, 0x4c, 0x26, 0xbd, 0x69, 0xdc, 0xbb, 0x87, 0xf2, 0xf0, 0x59, 0x54, 0x62, - 0xee, 0x43, 0x7e, 0x15, 0x03, 0x8d, 0x59, 0x02, 0xee, 0xb7, 0xcb, 0x5e, 0x7c, 0x94, 0x74, 0x82, 0xcc, 0x50, 0xb9, - 0x36, 0xde, 0x37, 0xf5, 0x48, 0x85, 0x91, 0x4b, 0x81, 0x7c, 0x70, 0xf7, 0xfb, 0x3d, 0x40, 0x31, 0xfe, 0xa2, 0x7d, - 0xf1, 0x3a, 0x29, 0x37, 0x31, 0x04, 0x24, 0x7a, 0x5d, 0x8e, 0x36, 0x08, 0xc8, 0xd1, 0x24, 0x41, 0x7e, 0x3c, 0x9e, - 0x49, 0xbe, 0xec, 0x38, 0xc5, 0x36, 0x95, 0x25, 0xa6, 0xdc, 0xfb, 0xe5, 0x2a, 0x0f, 0x84, 0xfd, 0x39, 0x91, 0x46, - 0xa4, 0x00, 0x30, 0xcc, 0x16, 0x78, 0x04, 0x0e, 0x34, 0xf1, 0xe2, 0x44, 0xad, 0xc2, 0x81, 0x86, 0xcd, 0xd9, 0x8b, - 0x98, 0x54, 0x64, 0xcc, 0x3e, 0x7e, 0x65, 0x5c, 0x30, 0x97, 0xd5, 0x48, 0x5b, 0x11, 0x2d, 0xe7, 0xb2, 0x4a, 0x00, - 0xb5, 0x10, 0x0a, 0xa1, 0xc1, 0x20, 0xc1, 0xf8, 0x46, 0xef, 0x4f, 0xa8, 0x47, 0x14, 0x8a, 0x57, 0xab, 0xc5, 0x44, - 0xbb, 0x7c, 0xc7, 0x2d, 0x4c, 0x97, 0x8c, 0x41, 0x75, 0xaf, 0xd8, 0x23, 0x2f, 0x5e, 0xad, 0xca, 0xed, 0xd8, 0xa9, - 0xea, 0xd6, 0x18, 0xa1, 0xee, 0xe6, 0xb5, 0xce, 0x8d, 0x69, 0x22, 0xb8, 0x2c, 0x68, 0xb6, 0x38, 0xf4, 0x74, 0xfe, - 0xe1, 0xca, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0x27, 0x89, 0x60, 0xa8, 0x51, 0x5e, 0x08, 0x23, 0x52, 0xff, - 0xce, 0x90, 0x7b, 0x96, 0xa2, 0x53, 0x6d, 0x54, 0x97, 0x2d, 0x80, 0x2d, 0x7d, 0x0d, 0x23, 0x43, 0x21, 0x74, 0xc4, - 0x30, 0xd2, 0x2e, 0xf5, 0x51, 0x66, 0x48, 0x16, 0x5d, 0x57, 0x45, 0x90, 0x79, 0xd7, 0x4e, 0xde, 0x24, 0x89, 0x12, - 0x6a, 0xe8, 0x67, 0xe6, 0x93, 0x3a, 0x3b, 0x89, 0x53, 0x5a, 0x4b, 0xa1, 0xe6, 0xa4, 0xba, 0x8e, 0xe9, 0x3b, 0x55, - 0x29, 0xa1, 0x27, 0x8c, 0xdd, 0x7b, 0x33, 0x78, 0xd5, 0xc6, 0x18, 0x9f, 0x6b, 0xfe, 0x79, 0xd2, 0x0e, 0xe3, 0xd0, - 0x03, 0xd4, 0x02, 0x39, 0x85, 0xd6, 0x80, 0xcc, 0xff, 0xdd, 0xd9, 0xd9, 0x9e, 0x10, 0xb6, 0x4d, 0x82, 0x96, 0xcb, - 0xad, 0x5c, 0x4f, 0x42, 0x59, 0x37, 0x4f, 0x5a, 0xe7, 0x24, 0xb1, 0x38, 0xd8, 0x22, 0x39, 0x52, 0xe6, 0x13, 0x7c, - 0xce, 0x79, 0x42, 0xea, 0x07, 0x5b, 0xf8, 0xce, 0xc6, 0x77, 0x15, 0x21, 0xf7, 0x3d, 0x36, 0x2f, 0x63, 0x08, 0x11, - 0x89, 0xc9, 0xdc, 0xab, 0x23, 0x1f, 0x44, 0x91, 0x0b, 0x55, 0x7b, 0xc4, 0x3c, 0x21, 0xc0, 0x54, 0xb5, 0x1f, 0x9c, - 0xf6, 0xe5, 0x42, 0xf6, 0xb7, 0x58, 0x19, 0xa0, 0x9c, 0x33, 0xa9, 0x97, 0xff, 0xf9, 0x52, 0xeb, 0xfe, 0xf7, 0x0b, - 0xac, 0xcb, 0x6d, 0x3b, 0xdf, 0xe9, 0x01, 0x60, 0x00, 0x78, 0x5d, 0x50, 0xb5, 0xca, 0x8b, 0x5d, 0x7d, 0x51, 0x6f, - 0x9b, 0x20, 0x24, 0x01, 0xef, 0x2a, 0xe9, 0xff, 0x3e, 0xd3, 0x40, 0xd0, 0x7c, 0x93, 0xec, 0x8f, 0x6c, 0x10, 0x89, - 0x3c, 0xf5, 0xa4, 0xc5, 0xc7, 0x3b, 0xe1, 0xdd, 0xc1, 0xf8, 0x65, 0x6c, 0x5d, 0xd1, 0x3d, 0xf3, 0x07, 0x09, 0x2c, - 0x07, 0x6a, 0xb7, 0x1e, 0xbd, 0x71, 0x22, 0xd8, 0x29, 0x0a, 0xd4, 0x33, 0x98, 0x12, 0x07, 0x81, 0xa2, 0x91, 0x16, - 0xe0, 0x49, 0x4c, 0x13, 0x4c, 0x0b, 0x08, 0xa9, 0x53, 0x40, 0x62, 0xbe, 0x1d, 0x96, 0x23, 0x78, 0x95, 0x22, 0x27, - 0x9e, 0x38, 0x37, 0xab, 0x0a, 0xe8, 0x3e, 0x44, 0xd5, 0xfc, 0x74, 0xf3, 0x06, 0x77, 0xe0, 0x26, 0xf6, 0x8d, 0xe3, - 0x0f, 0x71, 0xbf, 0xa1, 0x81, 0xe4, 0x1c, 0x12, 0x8b, 0xbc, 0xe6, 0x61, 0x3c, 0x93, 0x84, 0x3a, 0xdc, 0x42, 0x48, - 0xe7, 0x17, 0x30, 0x98, 0x17, 0x4c, 0x63, 0xab, 0xce, 0x22, 0x20, 0xe4, 0x3c, 0xbe, 0x1d, 0xc7, 0xb7, 0x1e, 0xac, - 0x07, 0xd1, 0x5e, 0x44, 0xfc, 0xad, 0x2d, 0x6a, 0x14, 0x2a, 0x0f, 0xa7, 0xd6, 0xd7, 0xd4, 0x70, 0x0c, 0x71, 0xf8, - 0x57, 0x90, 0x48, 0x09, 0x64, 0xb7, 0xed, 0x6b, 0x2e, 0xe8, 0xf4, 0x6e, 0xa7, 0x23, 0xb4, 0xd6, 0x0c, 0x2a, 0x73, - 0xd5, 0xac, 0xc1, 0xca, 0xb4, 0xd3, 0xff, 0x61, 0x73, 0x5b, 0x92, 0x80, 0x20, 0x5a, 0xe9, 0xf7, 0x55, 0x98, 0xb0, - 0xc4, 0x18, 0x03, 0x1e, 0x09, 0x32, 0xe7, 0x29, 0x44, 0x12, 0x0b, 0x30, 0x1c, 0xad, 0xd5, 0xc5, 0x7f, 0x56, 0xdc, - 0xfa, 0xd1, 0xe8, 0x4d, 0x9b, 0x64, 0xca, 0xcd, 0xaa, 0x05, 0xf0, 0xc7, 0x59, 0x65, 0xd9, 0xd6, 0x33, 0x40, 0xca, - 0x93, 0x2c, 0x09, 0x2e, 0xdd, 0x82, 0x93, 0xf2, 0x49, 0x4a, 0x9b, 0xe4, 0xca, 0xfd, 0xc2, 0x55, 0xf6, 0x3d, 0x53, - 0x04, 0x87, 0xf5, 0x4c, 0x73, 0x60, 0x01, 0x16, 0xcc, 0xa5, 0x74, 0xb1, 0xda, 0x19, 0x12, 0x09, 0x56, 0x92, 0x0f, - 0xcb, 0x0c, 0x49, 0x8f, 0x6f, 0xab, 0x8b, 0x84, 0x9c, 0xf1, 0xbc, 0xad, 0x01, 0x07, 0x78, 0x77, 0x2e, 0x46, 0x5a, - 0xef, 0xb0, 0x23, 0xef, 0x9d, 0x92, 0x52, 0x52, 0x35, 0x05, 0xe4, 0xd1, 0x86, 0x20, 0xed, 0x36, 0xc5, 0xa0, 0xbf, - 0x19, 0x2c, 0x8d, 0x7b, 0xcf, 0x25, 0x46, 0x0a, 0xa4, 0xda, 0x99, 0x3e, 0x70, 0xe1, 0x2f, 0xc8, 0xa9, 0xf9, 0xe0, - 0x9d, 0x6d, 0xd8, 0x4f, 0x4b, 0x0e, 0x08, 0xc5, 0xc5, 0x5d, 0x7f, 0xd4, 0x27, 0xb6, 0x58, 0x1c, 0x5c, 0xbe, 0x51, - 0xf6, 0xa8, 0x09, 0xec, 0xc1, 0x07, 0x5a, 0x46, 0x2a, 0x0d, 0x0a, 0x25, 0xc5, 0xbb, 0x73, 0x63, 0xda, 0x5b, 0x9b, - 0x5a, 0x56, 0x58, 0x55, 0x83, 0x55, 0xf5, 0xb1, 0xc4, 0xd2, 0xd2, 0xb6, 0xd8, 0x02, 0x73, 0xdd, 0x7b, 0x01, 0x26, - 0x5f, 0xc7, 0x47, 0x4c, 0x4b, 0x89, 0xee, 0x41, 0xa2, 0x2f, 0xe3, 0x30, 0x80, 0x8b, 0x2a, 0x08, 0x20, 0xbd, 0xae, - 0xe3, 0x48, 0x6c, 0xd6, 0x98, 0xe8, 0xb0, 0x68, 0xd3, 0x08, 0x54, 0x84, 0x1a, 0x18, 0x01, 0x2d, 0xe4, 0xca, 0x54, - 0x2c, 0x9d, 0xf9, 0xec, 0x02, 0x4b, 0x9f, 0xfb, 0x69, 0x5b, 0xdb, 0x5d, 0x31, 0x4b, 0x15, 0x24, 0xa5, 0x51, 0xd7, - 0x1b, 0x7d, 0xbb, 0x76, 0x67, 0x5d, 0xe3, 0x3d, 0x6e, 0xa4, 0x68, 0x6d, 0x2a, 0xd7, 0x47, 0xc9, 0x76, 0xfb, 0xdd, - 0xd2, 0x02, 0xd5, 0xcc, 0x59, 0x5a, 0x3b, 0x45, 0xf6, 0x3b, 0x0a, 0x70, 0xf9, 0x8e, 0x37, 0x18, 0x03, 0x64, 0x39, - 0xd2, 0xc6, 0xdc, 0x9a, 0x7c, 0xe4, 0x1e, 0x68, 0xe7, 0xdf, 0xbf, 0x4a, 0x82, 0xad, 0x3f, 0x2d, 0xc6, 0x65, 0xf0, - 0xcc, 0x61, 0x14, 0x38, 0x0a, 0x1f, 0xbd, 0x47, 0x5e, 0xad, 0x94, 0x31, 0xad, 0xcd, 0xe9, 0x4b, 0x23, 0x0d, 0x3e, - 0xd8, 0x86, 0xb5, 0x48, 0xae, 0xc7, 0xc8, 0xc6, 0x5e, 0xb7, 0xb0, 0x16, 0xc6, 0xe2, 0x8e, 0x21, 0xe5, 0x53, 0x49, - 0x09, 0xdc, 0xad, 0xe0, 0xe9, 0xc9, 0x9f, 0x52, 0x3e, 0x95, 0xd3, 0x4d, 0xae, 0xb3, 0x2f, 0x7f, 0x77, 0x4e, 0x17, - 0x1e, 0x34, 0x02, 0xfb, 0x32, 0x4b, 0x97, 0x55, 0x72, 0x2d, 0x90, 0x97, 0x6e, 0x3c, 0x17, 0xe5, 0xfa, 0xeb, 0x6e, - 0x23, 0x4c, 0x60, 0x9f, 0x2e, 0xf9, 0xdb, 0x7b, 0xf0, 0x7e, 0x2e, 0xe7, 0xf5, 0xb9, 0xb7, 0xa8, 0x93, 0x42, 0xbe, - 0xf9, 0xe4, 0x8b, 0x5d, 0x71, 0x9c, 0x10, 0x1f, 0xe8, 0x43, 0xe3, 0xbd, 0x5f, 0x8b, 0x04, 0xc4, 0x0a, 0xbf, 0x24, - 0x40, 0x44, 0x06, 0x70, 0xbc, 0xf3, 0xcf, 0xb1, 0xdb, 0x2c, 0x8d, 0x11, 0xdb, 0xe4, 0x61, 0x69, 0x4a, 0xda, 0xce, - 0x83, 0x0d, 0xf7, 0x67, 0x85, 0x52, 0x9c, 0x00, 0xcb, 0x33, 0xed, 0xb4, 0x8b, 0xbd, 0x08, 0xae, 0x69, 0x9b, 0x79, - 0xf5, 0x16, 0xf4, 0x84, 0xed, 0x2c, 0xcf, 0x63, 0x7b, 0xcb, 0xcf, 0xea, 0x20, 0xc2, 0x90, 0xbb, 0xe2, 0x4c, 0x5a, - 0x26, 0x90, 0x2a, 0xa6, 0x7d, 0xe3, 0xb8, 0xcd, 0x19, 0x3b, 0xf1, 0x02, 0xd1, 0x3f, 0x4e, 0x35, 0x2a, 0x9a, 0x4f, - 0xcd, 0x07, 0x8e, 0x34, 0x30, 0xf1, 0xab, 0x8d, 0xca, 0x54, 0x8e, 0x75, 0x00, 0x94, 0x2c, 0xd1, 0x9f, 0xb6, 0x28, - 0xad, 0x2b, 0x84, 0x51, 0xe1, 0x76, 0xf9, 0xf7, 0xf7, 0x36, 0xad, 0x62, 0x22, 0xda, 0xa3, 0x2b, 0xcd, 0xd9, 0x87, - 0x13, 0xf1, 0x96, 0x61, 0x07, 0x8a, 0x31, 0xa3, 0x03, 0x99, 0x94, 0xd5, 0x1e, 0x8d, 0x55, 0xe9, 0x46, 0x9e, 0x27, - 0x45, 0xa4, 0xbd, 0x80, 0xf5, 0xbd, 0xe0, 0x90, 0x8f, 0xef, 0x95, 0x21, 0x79, 0x5f, 0x77, 0x04, 0xe5, 0x00, 0xee, - 0x37, 0x4c, 0x1a, 0x7c, 0xf0, 0xcd, 0x5f, 0x72, 0xc5, 0xe8, 0xea, 0x95, 0x53, 0x36, 0xcd, 0xd8, 0x97, 0x1c, 0x26, - 0x57, 0xb8, 0x90, 0xed, 0xd3, 0x18, 0x79, 0xa3, 0x40, 0x72, 0x8e, 0x8d, 0x43, 0x3e, 0x6d, 0x58, 0x6f, 0x47, 0x52, - 0xba, 0x80, 0x90, 0xa9, 0x40, 0xd3, 0x83, 0x3a, 0x58, 0x92, 0x91, 0xd6, 0xa9, 0xbc, 0x8b, 0x8e, 0xfa, 0x3d, 0xeb, - 0x41, 0x73, 0xa5, 0xac, 0x0a, 0x84, 0x9b, 0xe5, 0xe5, 0x44, 0xc5, 0xb2, 0x3d, 0x9b, 0xca, 0xc7, 0xe5, 0x20, 0xb2, - 0x69, 0xda, 0xf9, 0xdb, 0xbe, 0x94, 0x22, 0x82, 0x07, 0xd4, 0x43, 0x08, 0xa1, 0xb4, 0x21, 0x03, 0x3d, 0xf2, 0x74, - 0x0d, 0xef, 0xf4, 0x03, 0x85, 0x7e, 0x3b, 0x0b, 0x82, 0xe0, 0xf8, 0x4a, 0xe8, 0x64, 0xcb, 0x9d, 0xda, 0x75, 0xde, - 0x63, 0x9f, 0xc8, 0x5e, 0x38, 0x79, 0xe5, 0xd2, 0xb4, 0x44, 0xdb, 0xd5, 0x8d, 0x3b, 0xff, 0xd8, 0xe1, 0x27, 0xa5, - 0x29, 0xa2, 0xd6, 0x24, 0x75, 0x3a, 0x58, 0x6e, 0x89, 0xa2, 0x45, 0x83, 0x83, 0x08, 0x74, 0x9c, 0x9c, 0x17, 0x71, - 0xdb, 0x0d, 0x05, 0xbe, 0xe4, 0x93, 0x70, 0x8f, 0x32, 0x16, 0xd0, 0x38, 0x52, 0xd0, 0x95, 0x16, 0x47, 0xb5, 0x32, - 0x86, 0x62, 0xcc, 0xde, 0x60, 0x0c, 0x65, 0x05, 0x1a, 0xac, 0x63, 0xeb, 0x45, 0xba, 0x1b, 0xa7, 0xbc, 0x86, 0x66, - 0x40, 0xe3, 0x7e, 0xea, 0x6b, 0x66, 0x84, 0x30, 0x34, 0xe1, 0xed, 0xd1, 0x3b, 0x77, 0x6c, 0x7f, 0xa5, 0xbe, 0x20, - 0x0c, 0x85, 0x18, 0xb0, 0x8b, 0x47, 0x31, 0x5b, 0x58, 0x22, 0x01, 0x71, 0xe5, 0x3e, 0x38, 0x30, 0xcb, 0xf2, 0xe0, - 0x1d, 0xa2, 0x42, 0x7b, 0x6c, 0xe3, 0xa6, 0x78, 0x4a, 0xc8, 0x15, 0x18, 0xc6, 0xfe, 0x32, 0x7d, 0x34, 0xf2, 0x54, - 0xd2, 0x7f, 0x11, 0x5a, 0x3f, 0x7b, 0xa4, 0x5b, 0x2c, 0xbb, 0xad, 0x0b, 0x6e, 0xdf, 0xea, 0x9f, 0xa5, 0xae, 0x4c, - 0xa4, 0xff, 0xb1, 0xb1, 0x6e, 0x75, 0xd9, 0x77, 0xfd, 0xfe, 0x43, 0x27, 0xea, 0x20, 0xff, 0xf4, 0x75, 0xdd, 0xe2, - 0x10, 0x8a, 0x27, 0x1f, 0xda, 0x43, 0x03, 0xf1, 0x31, 0xcd, 0x9a, 0x4b, 0x72, 0xde, 0xd0, 0xd0, 0x3f, 0x2b, 0x5c, - 0xfb, 0x51, 0x1f, 0x7a, 0x5c, 0xcc, 0x7f, 0x4e, 0xbe, 0xc3, 0xdd, 0xe8, 0xa3, 0x0b, 0x8f, 0xe4, 0x5c, 0x24, 0x8f, - 0xc9, 0x9e, 0xfe, 0xd8, 0x76, 0x91, 0xd2, 0x08, 0x50, 0x47, 0xaf, 0x9b, 0x96, 0xa6, 0x6b, 0x92, 0xd2, 0x3c, 0x28, - 0x5f, 0xe0, 0xaa, 0x1f, 0xbd, 0x5f, 0xdb, 0x43, 0x21, 0x9f, 0xd8, 0x5e, 0x2e, 0x49, 0xb7, 0xa7, 0x0f, 0x6f, 0x33, - 0xad, 0xce, 0x48, 0x8d, 0x5b, 0xd8, 0x97, 0xdb, 0xa3, 0xd0, 0x81, 0x32, 0x4a, 0xaf, 0x48, 0xbc, 0xc4, 0x38, 0xb9, - 0xc9, 0x0f, 0x4a, 0xcd, 0xb1, 0x7d, 0x1c, 0x79, 0x83, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0xde, 0x83, 0xa1, 0x72, - 0x2a, 0x58, 0x31, 0x2d, 0xe9, 0x89, 0x01, 0xb0, 0x69, 0xf4, 0x4b, 0xa8, 0xb6, 0x3b, 0x81, 0x4e, 0x6f, 0x9a, 0x54, - 0xdb, 0xc4, 0xff, 0xbe, 0x6f, 0xf4, 0x28, 0x59, 0x4a, 0x01, 0x59, 0xf7, 0xfd, 0x64, 0x6c, 0x12, 0x40, 0xa5, 0x79, - 0x96, 0xd5, 0x44, 0xdd, 0x81, 0xa1, 0x57, 0x33, 0x93, 0x3c, 0x7f, 0x8b, 0x0b, 0x3d, 0xee, 0x66, 0x4a, 0x0e, 0x95, - 0x22, 0x6f, 0x91, 0x08, 0xf5, 0x15, 0x7c, 0x1f, 0x49, 0x54, 0xcc, 0x2f, 0xe9, 0xec, 0x71, 0x68, 0xbc, 0x20, 0xd4, - 0x6f, 0xc0, 0x10, 0xf9, 0x21, 0x3a, 0x08, 0x81, 0xdd, 0xb9, 0x5c, 0x41, 0x72, 0x55, 0xdf, 0xcf, 0xa0, 0xee, 0x18, - 0xfd, 0x76, 0x55, 0xbf, 0x76, 0x0f, 0x86, 0x8c, 0x12, 0xbc, 0x46, 0xba, 0x39, 0x74, 0xd0, 0xa8, 0x1d, 0x3d, 0xd3, - 0x53, 0xe5, 0xa3, 0x0b, 0x14, 0x7d, 0xd8, 0x52, 0xe3, 0x89, 0x37, 0x52, 0xd0, 0x73, 0x71, 0xc0, 0x1b, 0xc3, 0x5e, - 0xd5, 0x81, 0xd1, 0x31, 0x7c, 0x7e, 0x29, 0x32, 0x20, 0x49, 0xaa, 0xa7, 0x45, 0xc4, 0x72, 0x28, 0x67, 0x6d, 0xe6, - 0x0e, 0xfa, 0x5e, 0x9c, 0x62, 0x86, 0xef, 0x6e, 0xf8, 0x8b, 0xbf, 0x19, 0x5f, 0xda, 0xe5, 0xda, 0x93, 0x6e, 0x51, - 0x1a, 0xac, 0xdb, 0xfa, 0x0e, 0x7a, 0x33, 0x12, 0x5d, 0xd0, 0xf4, 0xc7, 0x02, 0x11, 0x87, 0x94, 0x88, 0xa6, 0x69, - 0xe8, 0x94, 0x81, 0x23, 0x36, 0xe2, 0x7f, 0xb0, 0xa2, 0x41, 0x50, 0x6a, 0x1e, 0x58, 0x12, 0x2f, 0x07, 0x39, 0x92, - 0xf2, 0x06, 0x42, 0x41, 0x50, 0x53, 0xc1, 0x59, 0x90, 0xd2, 0x8d, 0x69, 0x87, 0xc8, 0x15, 0xb9, 0xae, 0x8f, 0x1b, - 0xf4, 0xe5, 0x2b, 0x39, 0x31, 0xa9, 0x32, 0x72, 0x6b, 0xaa, 0x62, 0xc7, 0xe0, 0x1d, 0xe7, 0xd6, 0x81, 0x7b, 0x83, - 0x22, 0x68, 0x8a, 0x92, 0xa5, 0x97, 0x39, 0x2f, 0x42, 0x5b, 0xe4, 0xba, 0x1e, 0x3d, 0xa8, 0x18, 0x28, 0xa9, 0xb0, - 0xd8, 0x90, 0x56, 0xf4, 0xa7, 0xce, 0x3b, 0x8c, 0xc2, 0x95, 0x76, 0x65, 0xe4, 0xe1, 0x3d, 0x1e, 0x47, 0xef, 0x26, - 0x51, 0x2c, 0xf2, 0x5c, 0x9d, 0xd7, 0x2c, 0xc8, 0xba, 0x9d, 0x26, 0x79, 0xbe, 0x1b, 0xce, 0xa2, 0x62, 0x52, 0xb2, - 0x95, 0x24, 0xaf, 0x59, 0x28, 0x8c, 0xd8, 0xfa, 0xcd, 0xa3, 0x20, 0xf9, 0x2c, 0xba, 0xbd, 0x1f, 0x09, 0xaf, 0x17, - 0x49, 0x66, 0x11, 0xcf, 0xf3, 0x2c, 0xb5, 0x6c, 0xcc, 0xa9, 0x50, 0xa9, 0xce, 0x10, 0xf8, 0x2b, 0x69, 0x7a, 0x53, - 0x26, 0x28, 0xdc, 0xb6, 0xe9, 0x3e, 0x98, 0x8c, 0x88, 0x0e, 0xdf, 0xb9, 0xd1, 0xcc, 0xc7, 0x6f, 0x94, 0x81, 0x1d, - 0xd6, 0xda, 0xd0, 0x76, 0x81, 0x97, 0x5b, 0x95, 0xc1, 0x9e, 0x46, 0x95, 0x32, 0xf2, 0x82, 0xa8, 0x3a, 0xd1, 0x56, - 0x70, 0xe8, 0x87, 0x0d, 0xfe, 0x3d, 0xc2, 0x70, 0xc9, 0x3d, 0xbb, 0x0d, 0x40, 0x0e, 0x59, 0x44, 0x3a, 0x2a, 0xa0, - 0x47, 0x9f, 0xae, 0x66, 0xcc, 0x15, 0xdc, 0x65, 0x0d, 0x82, 0x3b, 0xda, 0x3e, 0xc3, 0x40, 0xd2, 0x1d, 0x2e, 0xb4, - 0x29, 0x7a, 0xd4, 0xdf, 0x36, 0x4b, 0x67, 0xc1, 0x9b, 0x54, 0xc1, 0xcf, 0xb4, 0xe0, 0x84, 0xb7, 0xfd, 0x1e, 0xef, - 0x1b, 0xad, 0xb1, 0x6d, 0x86, 0xc7, 0xc6, 0xbc, 0x3b, 0xc8, 0x1a, 0xab, 0x8b, 0xc5, 0x35, 0x41, 0x2e, 0x25, 0xf9, - 0x88, 0xeb, 0xe5, 0x69, 0x19, 0x7c, 0xaa, 0x9e, 0x2a, 0x56, 0xa0, 0x1c, 0x16, 0x21, 0x14, 0x4c, 0xb3, 0x87, 0xb1, - 0x0e, 0x1f, 0x23, 0x31, 0x28, 0x24, 0x84, 0x05, 0x16, 0xa5, 0xee, 0xc7, 0x42, 0xa7, 0xd2, 0x40, 0x50, 0x42, 0x85, - 0x02, 0x23, 0xce, 0x7b, 0x2d, 0xbd, 0x86, 0xb6, 0xa9, 0x8c, 0x1e, 0x06, 0xbb, 0x58, 0xf6, 0x0e, 0x99, 0xc2, 0x92, - 0x2d, 0x0f, 0x21, 0x37, 0xdc, 0xd8, 0xa7, 0xef, 0xdb, 0xb5, 0x8a, 0x55, 0x33, 0xba, 0x9a, 0xfa, 0xdf, 0x11, 0xa1, - 0x71, 0x00, 0xd9, 0xc7, 0x6b, 0xe9, 0x60, 0x45, 0x8c, 0x9d, 0xe6, 0x23, 0xf5, 0xa2, 0x9c, 0x3f, 0x9b, 0x02, 0x82, - 0x6d, 0x6f, 0xed, 0x58, 0x37, 0x40, 0xe2, 0x76, 0x8e, 0xc9, 0x5e, 0x5d, 0xe2, 0x49, 0xef, 0x83, 0xf2, 0xb9, 0x75, - 0xdb, 0x25, 0x81, 0xcc, 0x17, 0xac, 0x28, 0x06, 0x24, 0x2b, 0x25, 0x78, 0xce, 0x7f, 0x6b, 0x1d, 0x54, 0x90, 0x90, - 0xe7, 0x83, 0x46, 0xb2, 0x32, 0xea, 0xf9, 0x98, 0x08, 0x1c, 0xd4, 0x02, 0x44, 0x63, 0x70, 0x06, 0x25, 0x28, 0x5b, - 0xc6, 0x3e, 0x1c, 0xce, 0x69, 0xf2, 0x12, 0xa1, 0x29, 0xca, 0x87, 0x2c, 0xf6, 0x57, 0x3f, 0x51, 0xa8, 0x9b, 0x1b, - 0xb9, 0x11, 0x1d, 0x0a, 0x5d, 0xbd, 0x6b, 0x6f, 0x32, 0x82, 0x34, 0xda, 0xba, 0xb9, 0x9e, 0x3d, 0x3f, 0xeb, 0xe1, - 0x63, 0x73, 0xba, 0x1e, 0x2e, 0x6f, 0x4a, 0xb5, 0x22, 0x42, 0xfb, 0x7f, 0x56, 0x96, 0x93, 0xff, 0x2c, 0xfa, 0x8b, - 0xcf, 0x8a, 0xfe, 0x94, 0x02, 0x49, 0x5d, 0x44, 0x5c, 0x5c, 0xb3, 0xd1, 0x5c, 0x29, 0x37, 0x6c, 0xaf, 0x9c, 0x27, - 0xbe, 0x72, 0x2e, 0x7f, 0x08, 0x07, 0xd5, 0x4e, 0x38, 0x0b, 0xe0, 0xa4, 0x8c, 0xb8, 0x1c, 0x3c, 0x8b, 0x01, 0xad, - 0xe2, 0x8a, 0x5a, 0x1d, 0x39, 0xcf, 0x1d, 0x6f, 0x1b, 0x6a, 0x2e, 0xea, 0xa1, 0x10, 0xe7, 0x03, 0x31, 0x32, 0x1b, - 0x88, 0xba, 0x09, 0x33, 0xd8, 0xdf, 0x91, 0xb2, 0x93, 0xe5, 0xa2, 0x4b, 0x6d, 0xf7, 0xc4, 0x51, 0xa4, 0xa4, 0x97, - 0xa9, 0xad, 0x40, 0x45, 0xaa, 0x24, 0x75, 0x74, 0x44, 0x14, 0xc2, 0x26, 0x58, 0x50, 0x3c, 0x6a, 0xc2, 0xa8, 0x4d, - 0xc2, 0xed, 0x00, 0x49, 0x8a, 0xd5, 0x28, 0xe3, 0xba, 0xa3, 0x12, 0x34, 0x24, 0xd4, 0x99, 0xa3, 0x03, 0x1a, 0x35, - 0x09, 0x25, 0x43, 0x49, 0xf3, 0x2f, 0x53, 0xd3, 0x98, 0x21, 0xea, 0x0f, 0x8c, 0xd0, 0x3b, 0xb7, 0x21, 0xe0, 0x96, - 0xf9, 0xad, 0x56, 0x2e, 0x8b, 0x04, 0xe2, 0x53, 0xc6, 0x3e, 0x50, 0xad, 0x11, 0xb5, 0x93, 0x2f, 0x54, 0x3a, 0x7c, - 0x09, 0xc5, 0x31, 0xd1, 0xc9, 0x09, 0x67, 0xcf, 0x4c, 0x28, 0x2b, 0xfe, 0x4d, 0xa6, 0xcd, 0x90, 0xb6, 0xf4, 0x41, - 0x8f, 0x4e, 0x24, 0xe1, 0x1c, 0xcb, 0x16, 0xb9, 0xaf, 0x46, 0xba, 0xaa, 0x25, 0x09, 0x43, 0x05, 0x99, 0xcb, 0xc2, - 0xf5, 0x49, 0x78, 0xed, 0x1e, 0x92, 0xf6, 0xb3, 0x0e, 0x2c, 0xb7, 0xcd, 0x4b, 0xec, 0xc2, 0x59, 0xef, 0x41, 0xb4, - 0xf7, 0x4c, 0x08, 0x7c, 0x16, 0xeb, 0x13, 0x29, 0x74, 0xff, 0x60, 0x12, 0x86, 0x84, 0xcf, 0xe0, 0xe1, 0x72, 0xf4, - 0x23, 0x45, 0x57, 0x24, 0x94, 0xb7, 0x6a, 0x5d, 0x12, 0x12, 0x85, 0x7b, 0x8b, 0x45, 0x63, 0x5d, 0x44, 0x43, 0xa1, - 0xb9, 0x78, 0xed, 0x49, 0xf5, 0xbe, 0x17, 0x75, 0x75, 0x8c, 0x50, 0xbd, 0xe0, 0x9f, 0xc1, 0x4f, 0x48, 0x42, 0xa7, - 0xd0, 0xdd, 0x36, 0x2d, 0x20, 0xb3, 0xc3, 0x69, 0x88, 0x02, 0x1e, 0xa2, 0x2a, 0x02, 0xb4, 0x98, 0x36, 0x97, 0x43, - 0x0a, 0xd5, 0xf3, 0x13, 0x9d, 0x7c, 0x40, 0xdd, 0x03, 0x99, 0xb2, 0xed, 0xb4, 0x7c, 0xba, 0x57, 0x38, 0x2c, 0xb5, - 0xbf, 0x89, 0x84, 0x92, 0x99, 0x58, 0x42, 0xdb, 0x98, 0x24, 0x7c, 0xfe, 0x75, 0xeb, 0x4a, 0xc4, 0xf8, 0x90, 0xbe, - 0x1c, 0xc9, 0xb8, 0xc2, 0x3b, 0x95, 0x9c, 0x40, 0xc4, 0xa6, 0xb7, 0x47, 0x21, 0x21, 0x65, 0x6a, 0x7c, 0x20, 0xa5, - 0xa5, 0x77, 0x7b, 0xda, 0x7c, 0x2a, 0x85, 0x1f, 0xaf, 0x3a, 0xd9, 0x73, 0x75, 0xb0, 0x75, 0x94, 0xf6, 0x98, 0x4c, - 0xf6, 0x1f, 0xfa, 0x98, 0xa2, 0x89, 0x81, 0x32, 0x62, 0xec, 0x30, 0x0f, 0xac, 0x12, 0x62, 0xda, 0x50, 0xaa, 0x2c, - 0x25, 0x39, 0x07, 0x0c, 0x3f, 0x4e, 0x1e, 0xa1, 0x80, 0xc1, 0xc4, 0x04, 0x2b, 0xc3, 0xe5, 0x62, 0x69, 0x50, 0x97, - 0x4a, 0x3c, 0x79, 0x2a, 0x4d, 0xae, 0xa7, 0xb1, 0xc4, 0x55, 0x22, 0x81, 0x49, 0x0d, 0x3d, 0x02, 0x18, 0x8f, 0xd4, - 0x8b, 0x6c, 0xfa, 0x0c, 0x9c, 0x96, 0xbe, 0x73, 0x7a, 0xca, 0x24, 0x6f, 0xb4, 0x59, 0x20, 0x98, 0xf0, 0xd8, 0x30, - 0x74, 0x47, 0x95, 0x7c, 0xb4, 0x4f, 0xac, 0xcf, 0x99, 0x45, 0x19, 0x8f, 0x3d, 0x05, 0x18, 0x38, 0xad, 0xf7, 0xe8, - 0x47, 0xd9, 0x74, 0x56, 0x93, 0x71, 0x22, 0x4f, 0x54, 0x52, 0x65, 0xd9, 0x89, 0x49, 0x8d, 0x1e, 0xaa, 0x65, 0x4f, - 0x76, 0x4c, 0x81, 0x04, 0x50, 0x4d, 0x72, 0xf8, 0x19, 0xb8, 0x74, 0x16, 0xda, 0x22, 0x95, 0x24, 0x6c, 0x00, 0xab, - 0xcf, 0x69, 0xdc, 0x38, 0xff, 0xba, 0x8f, 0x02, 0xa8, 0x57, 0x42, 0x4c, 0x54, 0xd0, 0x0a, 0xfb, 0xa0, 0x32, 0x81, - 0x76, 0xcb, 0x29, 0x69, 0x3b, 0xca, 0x48, 0x72, 0x15, 0xd7, 0x81, 0x18, 0xdc, 0xd3, 0x03, 0xb1, 0x88, 0xae, 0x1b, - 0xd8, 0x74, 0x60, 0xc7, 0x6f, 0x8c, 0x97, 0x6a, 0x7b, 0xac, 0xea, 0x4a, 0x92, 0x8f, 0x92, 0x4d, 0xaa, 0x9d, 0x00, - 0xe4, 0x48, 0xa8, 0x5a, 0xe4, 0xa7, 0x4d, 0x29, 0xa5, 0xb5, 0x61, 0xf7, 0x9e, 0x9a, 0x90, 0xeb, 0x55, 0x3d, 0x85, - 0x8f, 0x63, 0x64, 0x0e, 0xf1, 0x18, 0x67, 0x67, 0x88, 0x78, 0xc7, 0x95, 0x85, 0xfb, 0xdb, 0x22, 0xf5, 0x5c, 0x4a, - 0x52, 0x7b, 0x90, 0x4b, 0xb9, 0x4c, 0x3e, 0x98, 0xe6, 0xd2, 0x22, 0x30, 0xe7, 0x45, 0x25, 0x8e, 0x2e, 0x29, 0xc1, - 0x1d, 0x9a, 0x5e, 0x67, 0x39, 0x08, 0x2d, 0x53, 0xcc, 0x06, 0x48, 0x21, 0x20, 0x02, 0xe3, 0x2a, 0x5f, 0xb0, 0x77, - 0xb9, 0x8a, 0x0b, 0x8d, 0x60, 0x29, 0x32, 0x43, 0xaa, 0xed, 0xc4, 0xb4, 0xfb, 0xca, 0x59, 0xf4, 0xd3, 0x72, 0x39, - 0xd2, 0x71, 0x4d, 0x9c, 0x97, 0x92, 0xbc, 0x19, 0x46, 0x86, 0xce, 0x5b, 0x53, 0x6c, 0x75, 0x36, 0xf3, 0xd9, 0x90, - 0x40, 0x48, 0xc0, 0x82, 0x42, 0x2e, 0x4b, 0xd9, 0x99, 0xc7, 0xb4, 0xc7, 0xe3, 0xcc, 0xe8, 0xfe, 0xfa, 0x7d, 0x3d, - 0x9d, 0x96, 0x05, 0x55, 0x79, 0xb8, 0xed, 0x0e, 0x96, 0xc7, 0x41, 0x97, 0x76, 0x59, 0x4c, 0x15, 0xbf, 0x92, 0xec, - 0x27, 0x0d, 0x2f, 0xa3, 0x61, 0xae, 0x79, 0x49, 0xf5, 0x52, 0xcc, 0x70, 0x64, 0x91, 0xe6, 0xab, 0x23, 0xf6, 0xb3, - 0x33, 0xad, 0xad, 0xfc, 0xfb, 0x91, 0x59, 0x3b, 0xda, 0x5e, 0x49, 0x7d, 0xa5, 0x8f, 0x7e, 0xee, 0x83, 0xc5, 0x04, - 0x7f, 0x56, 0x28, 0x17, 0x7a, 0x52, 0x58, 0xa1, 0xfe, 0xb3, 0xae, 0x65, 0x7f, 0x6c, 0x82, 0x0f, 0xed, 0x83, 0x0f, - 0x98, 0x26, 0x34, 0x3f, 0x32, 0xc0, 0xa6, 0x8a, 0x09, 0xcb, 0xb7, 0x15, 0xb6, 0x21, 0xc5, 0xfb, 0xe7, 0x75, 0xcb, - 0x63, 0x9e, 0x8a, 0x29, 0x2f, 0x90, 0x5b, 0xfe, 0x2c, 0x20, 0x12, 0x75, 0x06, 0xd7, 0x43, 0x3e, 0x81, 0x6e, 0xec, - 0x3c, 0x3c, 0x12, 0xb9, 0xe2, 0x36, 0xc3, 0x9d, 0xc2, 0xb7, 0x87, 0xc7, 0xca, 0xbb, 0xb4, 0x52, 0x48, 0xa3, 0xfa, - 0x83, 0x36, 0xc3, 0x1b, 0xab, 0xd1, 0x43, 0x5d, 0x2d, 0x09, 0x61, 0x11, 0x84, 0x87, 0x45, 0xe8, 0xfd, 0x9f, 0xae, - 0x54, 0x48, 0x4c, 0x4e, 0x5b, 0x46, 0x72, 0x0e, 0x84, 0x54, 0xa0, 0x96, 0xe9, 0x3e, 0x65, 0x51, 0xa9, 0xdb, 0x42, - 0x6e, 0xfc, 0x96, 0x7c, 0x44, 0x15, 0x16, 0x3b, 0xbf, 0xd6, 0xdd, 0x27, 0xd2, 0x75, 0x57, 0xd4, 0x85, 0x56, 0x53, - 0x96, 0xa7, 0x68, 0x7a, 0x0e, 0xc4, 0xee, 0x71, 0x95, 0xfc, 0x9e, 0x40, 0x3a, 0xff, 0xb1, 0xe0, 0xef, 0xef, 0x15, - 0x49, 0xa2, 0xf5, 0x45, 0xe3, 0x51, 0xeb, 0x8b, 0x3d, 0x75, 0x68, 0x80, 0xd3, 0x05, 0x24, 0x8f, 0xaf, 0x02, 0x74, - 0x0d, 0x66, 0xe9, 0xaa, 0x63, 0x8e, 0x9b, 0xee, 0x7c, 0xd9, 0x16, 0x69, 0x3d, 0x43, 0x00, 0xed, 0x0d, 0x19, 0x77, - 0xff, 0x21, 0x4e, 0xb4, 0x67, 0x61, 0x82, 0x2e, 0x22, 0xe9, 0x3d, 0xec, 0x28, 0xb9, 0xd5, 0x9c, 0xe5, 0x0e, 0xdd, - 0x81, 0xae, 0x67, 0xbd, 0x88, 0x4a, 0x43, 0x0e, 0x76, 0x52, 0x6a, 0x08, 0x20, 0xda, 0x83, 0x6e, 0x2f, 0x4e, 0xee, - 0xed, 0x62, 0xc5, 0x7a, 0xdb, 0x0e, 0x4d, 0x2c, 0x54, 0x85, 0x2b, 0xac, 0x31, 0xe6, 0x96, 0xe3, 0xf6, 0x70, 0xd6, - 0x39, 0x16, 0x4a, 0xa3, 0xc1, 0xc0, 0xb7, 0xaf, 0xf3, 0xe3, 0x78, 0x61, 0x8f, 0x1c, 0x80, 0xd0, 0xb1, 0x17, 0x65, - 0x52, 0x05, 0x8a, 0x63, 0x19, 0x02, 0x2d, 0xda, 0xad, 0x59, 0xa5, 0x20, 0x17, 0x1e, 0x50, 0x8b, 0x8f, 0x17, 0xfe, - 0xb3, 0xcd, 0xb9, 0xd0, 0x42, 0xe6, 0xa8, 0x9d, 0x96, 0xec, 0x53, 0xbd, 0xa0, 0x00, 0x89, 0x32, 0xc2, 0xb6, 0x56, - 0x32, 0xf5, 0x71, 0x0a, 0x36, 0x21, 0xfb, 0x35, 0x49, 0x72, 0x3a, 0x32, 0x81, 0xd6, 0x79, 0xbb, 0x91, 0xa8, 0x0b, - 0x51, 0xe5, 0xc6, 0xa8, 0x0f, 0x7b, 0x46, 0xc7, 0x13, 0x8c, 0xe4, 0x98, 0xd2, 0xb1, 0xce, 0xbc, 0x7b, 0xab, 0x3d, - 0x76, 0xa7, 0x4d, 0x2b, 0x53, 0x9a, 0x29, 0x88, 0x39, 0x94, 0x49, 0x12, 0x04, 0x24, 0xb6, 0xbe, 0xbb, 0xce, 0x51, - 0x2d, 0xe8, 0x0e, 0x4c, 0x9f, 0x19, 0x8d, 0x02, 0x09, 0xf8, 0x6e, 0x39, 0x23, 0xe7, 0x90, 0xc2, 0xba, 0xb6, 0x50, - 0x91, 0x76, 0x97, 0x57, 0x82, 0x0a, 0xe7, 0x82, 0xd0, 0xec, 0xa0, 0xe0, 0xd4, 0xee, 0x77, 0x9b, 0xa1, 0xae, 0x3a, - 0xfa, 0x80, 0x1b, 0xb0, 0xd9, 0x10, 0xe2, 0x48, 0xdc, 0x78, 0xa1, 0x6c, 0x80, 0x13, 0x37, 0x2a, 0x61, 0x75, 0x62, - 0x7b, 0x72, 0xf4, 0xa3, 0x0b, 0xb5, 0xcc, 0x27, 0x58, 0xa2, 0x8b, 0x9e, 0x57, 0xb6, 0xdd, 0x5e, 0xe6, 0xdb, 0x6a, - 0x5e, 0xa0, 0xd8, 0x26, 0x21, 0xc4, 0x32, 0x4d, 0xe7, 0x98, 0xe7, 0xc2, 0x8f, 0x0e, 0x26, 0xc8, 0x3c, 0x94, 0x82, - 0x56, 0xf5, 0x0a, 0x34, 0x65, 0x97, 0xac, 0x84, 0x7b, 0xb7, 0xbe, 0xc9, 0xa4, 0x5d, 0xb4, 0x56, 0xde, 0x5d, 0x3d, - 0x6d, 0x40, 0xf7, 0xdc, 0xfb, 0x94, 0xfe, 0x25, 0xd0, 0x71, 0xc9, 0x6a, 0xf7, 0xbc, 0x9f, 0x52, 0x4e, 0xe3, 0x9a, - 0x28, 0x25, 0x0a, 0x3f, 0x1c, 0x06, 0xc4, 0xcc, 0x10, 0xe2, 0x8f, 0x7e, 0xe0, 0xcd, 0x5e, 0xec, 0x52, 0xa6, 0x4a, - 0x8b, 0xe2, 0x4f, 0x7a, 0x3f, 0x65, 0xc2, 0xc9, 0x7d, 0xd1, 0x3f, 0x37, 0xc4, 0x77, 0xa2, 0x01, 0x26, 0x62, 0x50, - 0x47, 0xbf, 0x45, 0x60, 0x3d, 0xa2, 0x23, 0x4b, 0xde, 0x2c, 0xff, 0x5d, 0xd6, 0xde, 0x9f, 0x76, 0x16, 0xaf, 0x2d, - 0xa9, 0xc1, 0x46, 0xb7, 0x1b, 0xc3, 0xda, 0xb0, 0xed, 0x29, 0x15, 0x20, 0x32, 0x7a, 0x04, 0xaa, 0x31, 0x5f, 0xcd, - 0x12, 0x14, 0x03, 0x1f, 0x71, 0x02, 0x1c, 0xb9, 0xad, 0x93, 0x95, 0x14, 0xee, 0xde, 0xfa, 0xb6, 0xd7, 0xc4, 0xbe, - 0xb2, 0x4b, 0x58, 0xee, 0xc8, 0x1d, 0xbb, 0xe9, 0x04, 0xaa, 0xa3, 0xb0, 0x57, 0x30, 0xac, 0x68, 0xd1, 0xb5, 0x03, - 0x11, 0x85, 0xde, 0x4e, 0x54, 0x14, 0x3e, 0x66, 0x58, 0x51, 0xd9, 0xd9, 0x01, 0x8c, 0x00, 0xfe, 0x45, 0x1c, 0x9e, - 0xd8, 0xe5, 0xa9, 0x66, 0x31, 0x83, 0x00, 0x63, 0xf8, 0xca, 0x06, 0x67, 0xc6, 0x0b, 0xcb, 0xc0, 0x26, 0x07, 0x80, - 0x5a, 0x47, 0x51, 0x6f, 0x71, 0x8a, 0x0f, 0x53, 0xdf, 0x18, 0xbc, 0xbd, 0x54, 0x4e, 0x47, 0xbc, 0x87, 0xdd, 0x95, - 0x8a, 0x1a, 0x52, 0xb0, 0x85, 0x6f, 0xbb, 0x21, 0x60, 0xa5, 0x30, 0x09, 0xfa, 0x50, 0x4e, 0x9b, 0xcb, 0x93, 0xcf, - 0x54, 0xff, 0x57, 0x4f, 0xc9, 0x54, 0x2c, 0x78, 0xd9, 0x49, 0x4f, 0x67, 0x9c, 0x96, 0xa5, 0xb2, 0xcf, 0xfd, 0xd3, - 0x4e, 0x12, 0x28, 0xf0, 0xed, 0x10, 0xf0, 0xec, 0xff, 0x2c, 0xda, 0xa8, 0x48, 0xad, 0x9a, 0x68, 0xa3, 0xa5, 0x75, - 0xec, 0x11, 0xff, 0x7e, 0x94, 0x76, 0x75, 0xe0, 0xa1, 0xaa, 0xcf, 0x27, 0x79, 0xe6, 0xbf, 0xe2, 0x49, 0xde, 0x10, - 0x75, 0x3b, 0xb1, 0xfb, 0x26, 0xa7, 0x4b, 0x79, 0x3b, 0x99, 0x57, 0x41, 0x7c, 0x47, 0x53, 0x03, 0xb3, 0x39, 0x29, - 0x71, 0xeb, 0xa5, 0xa2, 0xde, 0xe2, 0xc8, 0x23, 0x3a, 0x48, 0x32, 0x8c, 0xe6, 0xfc, 0xdc, 0x4e, 0xfc, 0x78, 0x2e, - 0x58, 0xfc, 0xb8, 0xbf, 0x2f, 0x30, 0x1c, 0x7d, 0x70, 0x12, 0x67, 0xda, 0xd5, 0x18, 0x29, 0x86, 0xaa, 0x14, 0x70, - 0x26, 0x36, 0xb7, 0xed, 0x47, 0x00, 0xe8, 0x3d, 0x70, 0xdc, 0xfb, 0x6e, 0xc1, 0xd9, 0xb3, 0xba, 0xb9, 0x90, 0x49, - 0xe6, 0x15, 0x65, 0x8c, 0x2b, 0x5e, 0xf4, 0x95, 0x2b, 0xf7, 0x3a, 0xc9, 0x03, 0x18, 0x52, 0x41, 0x4e, 0xe4, 0x9d, - 0x96, 0xba, 0xa2, 0xce, 0x42, 0xc8, 0x42, 0xce, 0x05, 0xb8, 0xca, 0xf3, 0xa7, 0xb3, 0x32, 0x8b, 0xe9, 0xdd, 0x5a, - 0xeb, 0x04, 0x08, 0x41, 0xf5, 0x95, 0x0c, 0xc6, 0xa1, 0x27, 0x79, 0x9f, 0x0a, 0x89, 0xb5, 0xe1, 0x1d, 0xb3, 0x1e, - 0x73, 0xf0, 0xc7, 0x84, 0xda, 0x4e, 0xa9, 0x07, 0xf9, 0x46, 0x6a, 0xd3, 0x7b, 0xc6, 0xe3, 0xf6, 0x0d, 0xb7, 0xd3, - 0x04, 0x09, 0x8a, 0x6b, 0x02, 0x2d, 0x97, 0x71, 0x0b, 0x60, 0xa9, 0x33, 0x45, 0xc3, 0x5b, 0xea, 0x7e, 0x62, 0x01, - 0x6b, 0xde, 0xad, 0x8c, 0x27, 0x0e, 0x73, 0xb2, 0x3d, 0x58, 0xbf, 0x2d, 0x86, 0x56, 0xa2, 0x0a, 0x07, 0x2b, 0x7b, - 0xde, 0x6d, 0x3b, 0xfe, 0x60, 0xcf, 0x65, 0x46, 0x84, 0x61, 0x1f, 0x38, 0x0a, 0x53, 0xec, 0xf2, 0x2a, 0x5b, 0x23, - 0x47, 0x18, 0x4e, 0xbe, 0xde, 0xa8, 0x81, 0xe5, 0xc4, 0xce, 0x69, 0xf6, 0x6f, 0xe8, 0x89, 0x40, 0xc6, 0x53, 0x7f, - 0xfc, 0xcc, 0x0c, 0xf5, 0xe0, 0x21, 0xdb, 0xed, 0xd2, 0xd7, 0xd6, 0x76, 0xb9, 0xb6, 0xad, 0x71, 0x8b, 0x68, 0x39, - 0x94, 0xd8, 0xb5, 0x46, 0x2c, 0xdd, 0xa1, 0x0b, 0x1f, 0xd8, 0x02, 0x37, 0xaa, 0x42, 0xe4, 0x2e, 0x37, 0x53, 0x89, - 0x35, 0x14, 0x80, 0xab, 0x9d, 0x17, 0x66, 0xd4, 0x27, 0x92, 0xf1, 0x15, 0x7b, 0x64, 0xa9, 0xf9, 0xa9, 0xcf, 0x3c, - 0xb0, 0x17, 0x8d, 0x42, 0xdf, 0xa4, 0x39, 0xcd, 0x8b, 0xf6, 0x83, 0xec, 0x16, 0xf9, 0x09, 0x42, 0x2b, 0xe1, 0x7c, - 0x7e, 0xd9, 0x7e, 0xd1, 0x2e, 0x66, 0x39, 0xe2, 0x61, 0x7f, 0x53, 0x4f, 0x2b, 0xbd, 0x8f, 0x77, 0x04, 0x0b, 0xb7, - 0x1d, 0x08, 0x26, 0x92, 0x3e, 0x12, 0xf2, 0xf0, 0x9d, 0xf8, 0xff, 0x6b, 0x43, 0xa0, 0x0d, 0x5b, 0x31, 0x5b, 0x1c, - 0x7e, 0x6a, 0x0a, 0xde, 0x41, 0x33, 0x4f, 0xa3, 0xb6, 0xb2, 0xce, 0xaa, 0xda, 0x2c, 0xe0, 0x15, 0x2f, 0x3f, 0x65, - 0x78, 0x81, 0x93, 0x71, 0x8e, 0x64, 0x78, 0x3f, 0x0f, 0x10, 0x25, 0x04, 0x24, 0xc4, 0xe9, 0x75, 0xf7, 0x60, 0x70, - 0x07, 0x6d, 0x7c, 0x09, 0x0a, 0xeb, 0xf9, 0x6c, 0x3c, 0x8f, 0xd9, 0x9b, 0xfc, 0x33, 0xba, 0x9e, 0xe8, 0x34, 0xae, - 0x54, 0x5b, 0xad, 0x5f, 0xbd, 0xf0, 0xdb, 0x43, 0xcd, 0x37, 0xf7, 0x93, 0xfb, 0x6c, 0x92, 0xad, 0x7c, 0xa8, 0x54, - 0x59, 0xde, 0x0d, 0x68, 0x31, 0x44, 0x65, 0x39, 0x4c, 0xa3, 0xdd, 0x86, 0xa3, 0xc3, 0x96, 0xdb, 0x49, 0xad, 0x9d, - 0x80, 0xec, 0xa0, 0x69, 0x51, 0x89, 0x17, 0x56, 0x90, 0x71, 0x9f, 0x72, 0x37, 0xa2, 0xa0, 0x20, 0xba, 0xc9, 0x52, - 0x9d, 0x61, 0x6a, 0x6c, 0x38, 0xf5, 0x80, 0xb2, 0xa0, 0xff, 0x75, 0x60, 0x28, 0x32, 0xa3, 0xb6, 0x30, 0x3f, 0xa6, - 0xca, 0xc9, 0x1f, 0xb7, 0x9c, 0xca, 0xc4, 0xaa, 0x57, 0xe8, 0xd5, 0xeb, 0x7d, 0x6e, 0x9a, 0x4e, 0x0c, 0x14, 0x1f, - 0x70, 0x35, 0x27, 0x58, 0x4d, 0xe4, 0x8b, 0x78, 0xb9, 0xca, 0x9c, 0x7d, 0x00, 0x7e, 0xd1, 0x75, 0x0b, 0x87, 0x69, - 0x79, 0xdb, 0xec, 0x8f, 0xe8, 0xec, 0x4a, 0xf2, 0x62, 0xc9, 0x16, 0x7c, 0x8c, 0x06, 0x70, 0x64, 0x0f, 0xaa, 0xc6, - 0x29, 0xc0, 0x22, 0x91, 0xd8, 0xc2, 0x52, 0x5a, 0x0f, 0xca, 0x05, 0x31, 0xb5, 0x8c, 0xe9, 0x36, 0x7a, 0x3c, 0x2d, - 0x23, 0x40, 0x0b, 0xb5, 0xb5, 0xc2, 0x3b, 0x8a, 0x29, 0x2a, 0x9b, 0x0b, 0xb9, 0x0a, 0x6c, 0xff, 0x9a, 0x52, 0x29, - 0x17, 0xb1, 0xdb, 0xa4, 0xb4, 0x43, 0xfd, 0x87, 0x7e, 0xc5, 0x6a, 0xc9, 0x09, 0x89, 0xd1, 0x47, 0x2e, 0x2e, 0x09, - 0x69, 0x45, 0xa6, 0x39, 0x5c, 0x33, 0x24, 0xf8, 0x73, 0x5a, 0x6b, 0x2f, 0xc5, 0x91, 0x31, 0x67, 0xee, 0x9b, 0xe2, - 0xda, 0x69, 0xab, 0xbf, 0xd8, 0x19, 0x57, 0x02, 0x82, 0xe1, 0xfc, 0x32, 0x97, 0x43, 0x77, 0xee, 0xbd, 0xb4, 0xe7, - 0xbc, 0xcc, 0x10, 0xc1, 0x4c, 0x20, 0xe4, 0x49, 0xe9, 0x5c, 0x74, 0x7d, 0x3a, 0x75, 0x24, 0xb1, 0xb6, 0x3e, 0x65, - 0xc6, 0x64, 0xc2, 0x64, 0x28, 0x28, 0xee, 0x19, 0xbf, 0x3f, 0x81, 0x8c, 0xa0, 0x86, 0xa0, 0xa0, 0xba, 0xee, 0xf1, - 0xf4, 0x65, 0x35, 0xf8, 0xf5, 0xb2, 0x42, 0x49, 0xe8, 0xb8, 0xf4, 0xdf, 0xe6, 0xb2, 0xcb, 0x92, 0x83, 0xbd, 0xbd, - 0x37, 0x30, 0xce, 0xa6, 0xd1, 0x93, 0x9d, 0x98, 0x72, 0xb7, 0x9d, 0xa0, 0x52, 0xf2, 0x9a, 0x52, 0x51, 0xb8, 0xd5, - 0x4b, 0xb4, 0x9e, 0x79, 0xe5, 0x70, 0x97, 0x78, 0x43, 0x59, 0xbc, 0x63, 0xc3, 0x4e, 0xf9, 0xcf, 0x8f, 0x6d, 0xf9, - 0xb2, 0x8d, 0x07, 0x7b, 0xba, 0x3f, 0x09, 0xfa, 0xce, 0xb8, 0xdf, 0x31, 0xf2, 0x57, 0x5f, 0x7c, 0x57, 0x93, 0xbf, - 0xf4, 0x9b, 0xb5, 0x1e, 0xf3, 0xba, 0x87, 0xdf, 0xef, 0xd3, 0x29, 0x7b, 0xe0, 0x6d, 0xe8, 0x9f, 0x47, 0xab, 0x75, - 0x05, 0xe4, 0x43, 0x87, 0xce, 0x7f, 0xe6, 0xfd, 0x33, 0x9f, 0xb9, 0xf4, 0xa7, 0xa3, 0x85, 0xd8, 0x1d, 0xf3, 0x37, - 0x06, 0x6f, 0x1b, 0xb1, 0x7b, 0x29, 0x76, 0x5f, 0xf4, 0x9a, 0x33, 0x0f, 0x53, 0x16, 0x5e, 0x41, 0xd0, 0x52, 0x79, - 0x57, 0xf8, 0x9c, 0xb7, 0x85, 0x6d, 0x3e, 0x14, 0x1e, 0xf2, 0xb1, 0xf0, 0x98, 0x4f, 0x6b, 0x4f, 0x4a, 0xb6, 0xd8, - 0xe3, 0xb8, 0x9a, 0xa8, 0x4a, 0x14, 0x7a, 0xf4, 0xc3, 0xc3, 0xa7, 0x52, 0x2a, 0x6b, 0x7c, 0xe3, 0x99, 0x67, 0x05, - 0x1b, 0x94, 0x10, 0x2b, 0xc3, 0x9b, 0x3a, 0x79, 0x75, 0x52, 0x12, 0x09, 0xf5, 0xcc, 0x5a, 0xd5, 0x41, 0x57, 0x49, - 0x59, 0x70, 0xb7, 0xdc, 0x86, 0x62, 0x7b, 0xb2, 0xb8, 0x8c, 0x5a, 0x43, 0xbd, 0xb7, 0x92, 0x19, 0xbd, 0x46, 0xa8, - 0xac, 0xbd, 0xbd, 0x4f, 0x47, 0x28, 0x2d, 0x27, 0x54, 0x25, 0xee, 0x67, 0x68, 0x15, 0x71, 0x86, 0x2d, 0x41, 0xde, - 0x7f, 0x06, 0x4c, 0x5a, 0x38, 0x6a, 0x5d, 0xae, 0xf7, 0x84, 0xd5, 0xe8, 0xd6, 0x12, 0xe9, 0x8b, 0x3c, 0x9a, 0xba, - 0xee, 0xaa, 0xc0, 0xcd, 0x89, 0x33, 0xf4, 0x1a, 0xf9, 0xed, 0xf0, 0xd8, 0x1a, 0xbb, 0xdc, 0xaa, 0xf9, 0x72, 0xfd, - 0xeb, 0xec, 0x3b, 0x2e, 0xc5, 0x84, 0x01, 0xea, 0x39, 0x0a, 0x91, 0x45, 0x0d, 0x17, 0xfc, 0x4a, 0x40, 0x5a, 0x6c, - 0x85, 0x1f, 0xbd, 0xaf, 0x61, 0x72, 0x81, 0x07, 0xa6, 0xbb, 0x75, 0x74, 0x96, 0x9f, 0xdc, 0xff, 0xf0, 0x9b, 0xff, - 0x19, 0x91, 0x13, 0x34, 0x16, 0x99, 0xfe, 0xb3, 0x9d, 0x1c, 0xc5, 0xa4, 0xb9, 0x74, 0x4b, 0xee, 0x6f, 0xc8, 0x60, - 0xea, 0x7d, 0x0d, 0x25, 0x20, 0xf0, 0x00, 0xa4, 0x94, 0x45, 0x75, 0x26, 0x04, 0xd7, 0xe3, 0x85, 0x45, 0x11, 0x5d, - 0x86, 0xf5, 0x10, 0x37, 0xa7, 0x63, 0x73, 0x53, 0x0d, 0xfe, 0x81, 0x98, 0x04, 0xd5, 0xf0, 0x4b, 0x4a, 0xda, 0xe8, - 0x46, 0x48, 0x29, 0x4c, 0xfb, 0x9d, 0x09, 0xfd, 0xe4, 0x47, 0x1f, 0xfa, 0xc2, 0xe7, 0x3e, 0x66, 0x42, 0xdc, 0x52, - 0xd1, 0xfc, 0x6d, 0xe0, 0x35, 0xb3, 0xfd, 0x6e, 0x85, 0x3f, 0xc8, 0xa7, 0xe3, 0xbd, 0x5f, 0x75, 0xbd, 0xb5, 0x39, - 0x75, 0x43, 0x3d, 0xe2, 0xef, 0x11, 0x44, 0x0d, 0x1f, 0x4b, 0xaf, 0xdd, 0x83, 0x84, 0x73, 0xec, 0x62, 0xb8, 0x2a, - 0xd7, 0xc1, 0xc7, 0x79, 0x99, 0xe7, 0xc6, 0x6c, 0x1a, 0xc1, 0x7d, 0xe1, 0x83, 0xcf, 0x38, 0x33, 0x9a, 0x7d, 0xc6, - 0xb2, 0x6d, 0xad, 0x54, 0x3a, 0xe5, 0xda, 0x52, 0xfb, 0x7e, 0x8d, 0xe2, 0x57, 0x58, 0xdb, 0xa6, 0x5d, 0xdb, 0xf4, - 0x4c, 0xd5, 0x78, 0x1d, 0x81, 0x67, 0xc9, 0x1f, 0xc7, 0x56, 0x58, 0xdf, 0xa2, 0x31, 0x0b, 0x6c, 0x4e, 0x6c, 0x97, - 0xa3, 0x97, 0xbf, 0x18, 0xdb, 0xc7, 0xd0, 0x4b, 0x2d, 0x62, 0x8a, 0x90, 0xbe, 0xac, 0xd2, 0xad, 0xa4, 0x89, 0x1e, - 0xdf, 0x43, 0xa8, 0xc2, 0x7e, 0xef, 0x39, 0x08, 0xd0, 0xd8, 0x6b, 0x2e, 0x28, 0x3a, 0xd7, 0xe9, 0x4a, 0x20, 0x74, - 0xe1, 0xf7, 0xa1, 0x7d, 0x53, 0x74, 0xaa, 0x83, 0xb4, 0x0c, 0x54, 0x13, 0x79, 0xf5, 0x3d, 0xb9, 0x1c, 0xe4, 0x2a, - 0xc3, 0x43, 0x8f, 0x0e, 0xdf, 0xe4, 0xe1, 0xd2, 0xc2, 0x4e, 0x24, 0x7e, 0xf3, 0x33, 0xb7, 0x62, 0xde, 0x6f, 0x47, - 0x47, 0x8b, 0x70, 0x50, 0x59, 0xcb, 0x5b, 0x64, 0x3a, 0x54, 0x40, 0x1a, 0xa8, 0xce, 0x12, 0x89, 0xe5, 0xfc, 0x57, - 0xfa, 0xd1, 0x6d, 0x88, 0x1f, 0xdd, 0x54, 0xf4, 0xfa, 0xb8, 0xb7, 0x02, 0xd0, 0x8d, 0xea, 0x33, 0x50, 0x65, 0xe6, - 0x5c, 0x94, 0xbe, 0xbf, 0xc5, 0xfe, 0xbe, 0x76, 0x11, 0x7d, 0xef, 0xb4, 0x7e, 0x76, 0x42, 0x56, 0xce, 0x3f, 0x7d, - 0x84, 0x8d, 0x0a, 0xea, 0xff, 0x81, 0x6b, 0xda, 0xd7, 0x81, 0x4e, 0x9c, 0x5f, 0xca, 0x44, 0x7a, 0x2e, 0x89, 0xcb, - 0x8c, 0x4f, 0x30, 0x0b, 0x24, 0xed, 0xf8, 0xa3, 0x8b, 0xe2, 0x2a, 0x9c, 0xfb, 0x8c, 0x75, 0x9a, 0x37, 0x4e, 0xad, - 0x0d, 0xf6, 0xeb, 0x1b, 0xdd, 0x64, 0x44, 0xd6, 0xb9, 0x39, 0xc3, 0x9a, 0xd1, 0x47, 0x88, 0xe4, 0x16, 0x4d, 0xa8, - 0x8e, 0x19, 0x2c, 0x0f, 0x7a, 0xf0, 0x9b, 0x74, 0xde, 0x6d, 0xc4, 0x96, 0x99, 0x81, 0x47, 0x23, 0xb6, 0xe1, 0x51, - 0x84, 0x0c, 0x32, 0x70, 0xce, 0x77, 0xd2, 0xfd, 0x50, 0x90, 0x8c, 0x0f, 0x8e, 0xcf, 0x1d, 0xdc, 0x74, 0x2f, 0x0b, - 0x64, 0xa5, 0x1e, 0x43, 0x73, 0xb3, 0x20, 0x6a, 0xb3, 0x4d, 0x79, 0x83, 0x2f, 0xf8, 0xd2, 0xf5, 0x8a, 0x54, 0x57, - 0xda, 0x6a, 0xe9, 0x29, 0x2c, 0xcd, 0x82, 0x81, 0x6c, 0x69, 0xb1, 0x2c, 0x62, 0x0c, 0xd2, 0x70, 0x9d, 0x4d, 0x11, - 0x4a, 0x13, 0x84, 0x3a, 0x14, 0x98, 0x12, 0x05, 0x3a, 0x05, 0xe0, 0xa0, 0x9c, 0xd0, 0x5e, 0x07, 0xbf, 0xa7, 0xeb, - 0x65, 0xd6, 0x7e, 0x7f, 0x6f, 0x38, 0x5f, 0x6f, 0x87, 0x67, 0xec, 0xf5, 0xe4, 0xbf, 0x38, 0x83, 0xfc, 0x9a, 0xe6, - 0xe6, 0xaa, 0x67, 0x2c, 0x17, 0x49, 0xb4, 0x3a, 0x7f, 0xf9, 0x26, 0x53, 0x8f, 0x7e, 0xd0, 0xd5, 0x7a, 0xea, 0x6e, - 0xb2, 0x37, 0x8c, 0x0f, 0xd4, 0x7a, 0x19, 0x4b, 0x8c, 0xd5, 0xaa, 0xe8, 0xff, 0xeb, 0x5a, 0xf8, 0x2a, 0x69, 0x0f, - 0x54, 0x17, 0xe2, 0xfe, 0x4a, 0x8f, 0xcf, 0x08, 0x0e, 0x17, 0x6d, 0x17, 0x27, 0x74, 0xa5, 0xd6, 0xa2, 0x42, 0xb7, - 0x86, 0x19, 0x62, 0xaf, 0x2d, 0xf1, 0x2f, 0xfd, 0x24, 0x4b, 0xd1, 0x77, 0xc7, 0xd0, 0xb9, 0xfc, 0xe1, 0x70, 0x75, - 0xac, 0x9a, 0xe6, 0xa7, 0x77, 0xe3, 0xec, 0xf7, 0x30, 0xb7, 0x7e, 0x57, 0xac, 0xe8, 0x08, 0x05, 0x9e, 0xac, 0x4c, - 0xe8, 0xf5, 0xe5, 0x85, 0x32, 0x93, 0xcd, 0x27, 0xcc, 0x40, 0x4f, 0xde, 0x31, 0xd0, 0x8d, 0x53, 0xed, 0x23, 0x67, - 0xc5, 0xff, 0x2c, 0x47, 0x6d, 0xb6, 0x3b, 0x4c, 0x54, 0xef, 0xf6, 0x8e, 0xdc, 0x07, 0xe8, 0x33, 0xe8, 0x23, 0x53, - 0x01, 0xea, 0xb8, 0x55, 0xc5, 0xb0, 0x99, 0xa4, 0xdd, 0x7d, 0x63, 0x7d, 0xac, 0x97, 0x99, 0x63, 0x9f, 0xd8, 0x02, - 0x10, 0xc7, 0x1f, 0x94, 0x55, 0x81, 0xaf, 0xcf, 0xdf, 0xe2, 0x6d, 0xba, 0xcf, 0x68, 0x08, 0x4c, 0x98, 0xa7, 0x3f, - 0x19, 0xa5, 0xf4, 0xfd, 0xe9, 0x89, 0xd2, 0x6b, 0x83, 0x7b, 0x9a, 0x3d, 0x5d, 0x30, 0x9e, 0xfe, 0x43, 0x50, 0x6b, - 0xef, 0xfd, 0x95, 0x5b, 0xeb, 0x3b, 0x48, 0xb3, 0x33, 0xfa, 0xc1, 0x69, 0x0e, 0x72, 0x2c, 0x4a, 0xab, 0xc7, 0xf9, - 0x11, 0xcd, 0x5c, 0x08, 0xf0, 0x21, 0x2b, 0x0e, 0xfa, 0xe7, 0x18, 0x63, 0xae, 0xe0, 0xc7, 0xe8, 0x8f, 0x0e, 0x42, - 0x6d, 0xe5, 0xd3, 0x7d, 0xf1, 0x77, 0x6a, 0xcd, 0x51, 0xeb, 0x59, 0x15, 0xaa, 0xbe, 0x93, 0xb2, 0xda, 0x64, 0x6b, - 0x05, 0xd0, 0xf8, 0x92, 0xe2, 0xfb, 0x3a, 0x24, 0x04, 0x55, 0x48, 0xc0, 0x2d, 0xab, 0xa4, 0x4b, 0xda, 0x2f, 0x39, - 0xbc, 0x91, 0xde, 0x43, 0xd8, 0x88, 0xbb, 0x8d, 0x5d, 0x1f, 0xd2, 0x9f, 0x29, 0xf2, 0x9b, 0x28, 0x63, 0x6c, 0xbd, - 0x71, 0x99, 0x91, 0x03, 0xff, 0x77, 0x37, 0x08, 0x44, 0x3e, 0x2a, 0x98, 0x25, 0xb5, 0xd3, 0x18, 0x62, 0x69, 0x4a, - 0x31, 0xfa, 0x95, 0xcb, 0xfb, 0xb3, 0xf9, 0xff, 0x61, 0x02, 0x93, 0xf1, 0x9f, 0x44, 0x07, 0xed, 0x2a, 0x42, 0xda, - 0x47, 0x44, 0x17, 0x0f, 0x9a, 0x3f, 0x7e, 0x3b, 0x54, 0x0e, 0xb6, 0xb6, 0x05, 0x55, 0xc6, 0x20, 0xf2, 0x1e, 0xc1, - 0x59, 0x43, 0x07, 0x26, 0x7f, 0xc7, 0xb5, 0xe5, 0x14, 0xa2, 0x7d, 0xf5, 0x5d, 0x49, 0xa9, 0x2b, 0x9f, 0x3e, 0xf4, - 0x7f, 0xd3, 0x00, 0x98, 0xd4, 0xa8, 0xbc, 0x4e, 0x5b, 0xbe, 0xf0, 0x7d, 0xd9, 0x54, 0x64, 0xe3, 0xf8, 0xe8, 0x8a, - 0x8e, 0xb7, 0xc6, 0xb8, 0x5f, 0x44, 0x49, 0xab, 0x6b, 0x3f, 0xdd, 0xb4, 0xa0, 0x1b, 0x47, 0x44, 0x8f, 0xf1, 0x2e, - 0xe6, 0xb6, 0x37, 0xaf, 0x12, 0xeb, 0xf8, 0xa8, 0x4d, 0xed, 0x68, 0x33, 0x85, 0x07, 0x76, 0xc0, 0x63, 0x78, 0x6a, - 0xf9, 0x78, 0xb8, 0xe1, 0x10, 0x44, 0xb0, 0x41, 0x02, 0x8c, 0xa4, 0x24, 0x31, 0x65, 0x49, 0xec, 0x71, 0x38, 0xae, - 0xb4, 0x15, 0x3e, 0x9d, 0x4a, 0x77, 0xc8, 0x1f, 0x6a, 0xbc, 0x4f, 0xaa, 0xe1, 0xb1, 0xcf, 0x38, 0x89, 0x5b, 0x89, - 0xfa, 0x51, 0x1e, 0xc4, 0x56, 0xb0, 0xcf, 0x02, 0x5c, 0x55, 0x84, 0xb3, 0x35, 0x0f, 0x1c, 0xc0, 0x06, 0x09, 0x4c, - 0x29, 0xe2, 0x28, 0x8e, 0xef, 0x7e, 0xd2, 0x4f, 0xfc, 0xdc, 0x8a, 0x65, 0x31, 0x2b, 0x48, 0xf2, 0xfe, 0x73, 0x78, - 0x24, 0x4f, 0xcb, 0x9b, 0x24, 0xd9, 0x64, 0xfe, 0x7e, 0x7c, 0x61, 0x4f, 0x2c, 0x7c, 0xc1, 0x0a, 0xa7, 0x3b, 0xb2, - 0xf4, 0x32, 0x6a, 0x5d, 0xfc, 0x05, 0x4e, 0xb0, 0xbf, 0x4d, 0xef, 0x5d, 0x79, 0x75, 0xbf, 0xea, 0x7d, 0x5f, 0xae, - 0x49, 0xed, 0x97, 0x1b, 0x2d, 0x1e, 0x3f, 0x4f, 0x27, 0x5a, 0xb7, 0x8c, 0x3e, 0xf4, 0xbf, 0x79, 0x76, 0x87, 0x20, - 0xfb, 0x49, 0xd6, 0xde, 0x27, 0xb1, 0xed, 0x07, 0x28, 0x72, 0xdd, 0xdc, 0xaf, 0x10, 0x4e, 0xbf, 0xb3, 0xc0, 0x4b, - 0x09, 0x7e, 0x66, 0x83, 0xaa, 0xc7, 0x6a, 0x39, 0xb9, 0xda, 0xc1, 0xa0, 0x1c, 0x2e, 0x78, 0x02, 0xd6, 0x59, 0xcc, - 0x0c, 0x4a, 0xba, 0xa3, 0xd6, 0xdf, 0x3d, 0xc5, 0xf7, 0xda, 0x66, 0x36, 0x26, 0x22, 0xb9, 0x51, 0xf6, 0xb0, 0x74, - 0x11, 0xce, 0xf2, 0x9d, 0xf3, 0xf1, 0xf7, 0x46, 0xc8, 0x19, 0x56, 0xf9, 0x2e, 0x91, 0x93, 0xcf, 0xf8, 0x94, 0x0d, - 0x57, 0x97, 0x1b, 0x2d, 0x36, 0x88, 0x56, 0xf4, 0x95, 0x38, 0x20, 0x51, 0xb4, 0x5b, 0x3c, 0xef, 0x65, 0x48, 0xfe, - 0x36, 0xb9, 0xc6, 0x01, 0x46, 0x2e, 0xb3, 0x9c, 0xc1, 0x17, 0xd7, 0x8c, 0x81, 0xea, 0x57, 0xd3, 0xfb, 0x60, 0x91, - 0x92, 0x51, 0x69, 0x9e, 0xd1, 0xa8, 0x65, 0x2e, 0xc1, 0xf8, 0x0a, 0x0d, 0xfd, 0x88, 0x7d, 0xfa, 0x7c, 0x23, 0x72, - 0x77, 0x0c, 0xeb, 0x3f, 0x8a, 0xef, 0x01, 0x72, 0xec, 0x0d, 0xea, 0x06, 0xd9, 0xb0, 0x48, 0x6a, 0x44, 0xe3, 0x12, - 0xab, 0x74, 0x41, 0x36, 0xb0, 0x7b, 0x61, 0xef, 0x7f, 0xc7, 0x7f, 0xa6, 0x12, 0x09, 0x43, 0x84, 0x2f, 0x36, 0x32, - 0xe8, 0x06, 0x17, 0xc1, 0xf4, 0x19, 0xe1, 0x41, 0x92, 0xa8, 0xbb, 0x62, 0x2c, 0xf0, 0x04, 0x4a, 0x50, 0x32, 0xcf, - 0xe2, 0xea, 0x0e, 0xfa, 0xff, 0xa5, 0x18, 0xd5, 0xe7, 0xed, 0xf2, 0xa6, 0x12, 0xf5, 0xd0, 0x21, 0xc7, 0x79, 0xc1, - 0x17, 0x60, 0xb3, 0x27, 0x4b, 0x5e, 0x02, 0x31, 0x4c, 0xfe, 0x2b, 0x2c, 0x2c, 0x7d, 0x8a, 0xe5, 0x74, 0xf8, 0x97, - 0x6b, 0x16, 0x7b, 0x7b, 0xb8, 0xe9, 0x84, 0x61, 0x7c, 0x4a, 0xf3, 0x05, 0xbd, 0x5d, 0x37, 0x35, 0x6c, 0xe5, 0xc7, - 0x55, 0x16, 0x4f, 0x9d, 0xfb, 0xe5, 0x9b, 0xbc, 0xb8, 0xb4, 0x67, 0x53, 0x75, 0x7e, 0xf0, 0xdc, 0x17, 0xe3, 0x96, - 0xf1, 0xdf, 0xe8, 0x88, 0x97, 0x5f, 0xbc, 0xaf, 0x48, 0xc4, 0xcc, 0x83, 0xcd, 0x7d, 0x5d, 0x90, 0xd3, 0x2f, 0xd1, - 0x3c, 0x2c, 0x57, 0x94, 0x5e, 0x65, 0x76, 0xd5, 0x0f, 0xdf, 0xe4, 0xd9, 0xa5, 0x97, 0x1d, 0xb4, 0xda, 0x7c, 0xaa, - 0x6d, 0xc0, 0xda, 0x02, 0xfa, 0x2f, 0x4b, 0xb5, 0xd9, 0x86, 0x34, 0x5e, 0xa8, 0x7c, 0x57, 0x1d, 0x51, 0x03, 0xfb, - 0x23, 0x3b, 0x6c, 0x78, 0xa0, 0xff, 0x36, 0xbd, 0x9e, 0x3a, 0xb5, 0xaa, 0xb6, 0x3b, 0x09, 0x70, 0xc6, 0x64, 0xad, - 0x62, 0x8c, 0x04, 0xd1, 0x5d, 0x7a, 0xb3, 0x6d, 0x7c, 0x68, 0xda, 0x52, 0xc1, 0xf7, 0xfd, 0x89, 0x61, 0x8a, 0x7b, - 0xda, 0x70, 0xf1, 0x2c, 0x14, 0xf8, 0x9d, 0xb1, 0x43, 0x4f, 0xf4, 0x00, 0x5d, 0x1f, 0x64, 0xb3, 0x58, 0xb6, 0x4b, - 0x20, 0xcf, 0x33, 0xf8, 0xd9, 0x22, 0x96, 0x45, 0xfa, 0x66, 0x46, 0xf7, 0x8f, 0x9a, 0x20, 0x90, 0xb3, 0xa2, 0x2f, - 0x26, 0x05, 0x25, 0x72, 0x54, 0x53, 0x1f, 0xed, 0x4b, 0x9d, 0xa3, 0x2f, 0x36, 0xc2, 0x1a, 0x4a, 0x20, 0xea, 0x0c, - 0xf9, 0xad, 0x52, 0x70, 0xf3, 0xc4, 0x72, 0x81, 0x06, 0x03, 0x25, 0x5c, 0xce, 0x5f, 0xfc, 0x0f, 0xd9, 0x5a, 0xeb, - 0x02, 0x69, 0x65, 0xc3, 0xfc, 0xaa, 0xca, 0xad, 0xe8, 0xe6, 0x3b, 0x34, 0x35, 0xbd, 0x7a, 0x22, 0x54, 0x78, 0xaf, - 0xdc, 0x3f, 0xab, 0xc8, 0xb8, 0x8e, 0x73, 0x48, 0x73, 0x10, 0xc5, 0x33, 0x29, 0x1b, 0x1a, 0x34, 0x53, 0x0e, 0xb2, - 0xaf, 0x32, 0x40, 0xa2, 0xac, 0xea, 0x28, 0xb6, 0xb8, 0xdc, 0xd0, 0x76, 0x89, 0xdb, 0x96, 0x52, 0x9b, 0x48, 0x5b, - 0xbc, 0xc2, 0x23, 0x4b, 0x88, 0x2e, 0x3b, 0x00, 0x85, 0x48, 0x8e, 0xac, 0x7b, 0xae, 0x48, 0xd1, 0xca, 0xed, 0xdb, - 0xb0, 0xe3, 0x3a, 0x42, 0xeb, 0xae, 0xe6, 0xaa, 0x35, 0x6a, 0x34, 0x32, 0xc9, 0xb0, 0x71, 0x6d, 0xf0, 0xaa, 0x04, - 0x35, 0xd4, 0xd8, 0xc6, 0xa1, 0x4c, 0xff, 0xf3, 0xcc, 0x17, 0x33, 0x67, 0x5a, 0x5f, 0xf2, 0xfd, 0x24, 0xb6, 0x48, - 0x45, 0xc3, 0x7e, 0xc6, 0xbe, 0x89, 0x0c, 0x41, 0x8b, 0x8e, 0x58, 0xf5, 0xa9, 0x58, 0xcd, 0x75, 0x32, 0x28, 0x50, - 0x6a, 0xde, 0x38, 0x6d, 0xae, 0x57, 0xe5, 0xdc, 0x23, 0xae, 0x8c, 0x81, 0xdd, 0x9c, 0xdc, 0xb6, 0xf2, 0xbb, 0x99, - 0x9f, 0x36, 0xce, 0x2b, 0x45, 0x86, 0x33, 0xb6, 0x73, 0x52, 0x9f, 0x17, 0x48, 0x0c, 0x97, 0x16, 0xf3, 0x87, 0x0b, - 0x4a, 0x4d, 0x1d, 0x16, 0x8a, 0x24, 0xa7, 0xa5, 0xa9, 0xc0, 0x6f, 0x3f, 0xbc, 0xf6, 0xca, 0x2c, 0x15, 0x0b, 0x02, - 0x2f, 0x14, 0xf3, 0xe7, 0xc2, 0x0e, 0x16, 0xef, 0x33, 0xa1, 0x83, 0x49, 0x9f, 0xf2, 0xdc, 0xe6, 0x26, 0xef, 0xe5, - 0x85, 0xc3, 0xe4, 0xc5, 0x86, 0xe8, 0x67, 0x11, 0x8d, 0x7e, 0x3a, 0xe8, 0x5c, 0x5b, 0xa8, 0x70, 0xe2, 0x09, 0x92, - 0x6c, 0x4a, 0xa1, 0x7b, 0xcd, 0x23, 0x45, 0x52, 0x83, 0x1c, 0xed, 0x7e, 0x27, 0x17, 0xe3, 0xa4, 0xd5, 0x38, 0x2a, - 0xab, 0x24, 0xe1, 0xf3, 0x83, 0xe4, 0x36, 0xa1, 0x44, 0xf9, 0x2c, 0xd2, 0x8c, 0x24, 0x6b, 0xdc, 0x6b, 0x2b, 0xb8, - 0x46, 0xcc, 0xad, 0x0a, 0x06, 0x9b, 0xfd, 0x44, 0xfa, 0xd5, 0x76, 0xf0, 0x26, 0xc5, 0x83, 0x44, 0x09, 0x86, 0x8b, - 0x73, 0xfa, 0xa1, 0x45, 0x47, 0x7e, 0x9d, 0x8d, 0x30, 0x08, 0x0e, 0xa1, 0x14, 0x2a, 0x6b, 0x29, 0x68, 0xe8, 0xbf, - 0x27, 0x6b, 0x87, 0x14, 0x48, 0x04, 0x7c, 0x4e, 0xde, 0x4d, 0x98, 0x12, 0x9c, 0x3c, 0x95, 0x9c, 0x10, 0xae, 0x2a, - 0x16, 0x6f, 0x4a, 0xee, 0x40, 0x79, 0x0c, 0xdc, 0x8a, 0xa0, 0x0b, 0xaa, 0x13, 0x51, 0x2a, 0x70, 0xf4, 0xf6, 0x29, - 0xba, 0xbb, 0x8b, 0x33, 0x58, 0x88, 0x04, 0xf7, 0x2a, 0xb3, 0x4e, 0x6a, 0xc9, 0x51, 0x46, 0x21, 0x9b, 0xcd, 0x46, - 0x34, 0xfa, 0x84, 0x2b, 0x60, 0xe2, 0x49, 0xfc, 0x1f, 0x51, 0x55, 0x13, 0xad, 0xbb, 0xa1, 0xbb, 0x2e, 0x49, 0x1f, - 0x9a, 0x8e, 0x61, 0x5a, 0x5c, 0xb7, 0x13, 0x92, 0x3a, 0xd3, 0x7e, 0x1b, 0x06, 0xcf, 0x6f, 0xce, 0x57, 0x9b, 0x3f, - 0xde, 0x6e, 0xad, 0x44, 0x51, 0xe4, 0x82, 0xc9, 0xc0, 0x91, 0x11, 0x72, 0xd5, 0x45, 0xdd, 0xf1, 0xb0, 0x35, 0x2d, - 0x92, 0xdc, 0xe9, 0xb8, 0xdd, 0x40, 0x35, 0xbe, 0xfc, 0xc6, 0x75, 0x9b, 0xcd, 0x10, 0xf2, 0x76, 0x7f, 0xf0, 0x34, - 0x39, 0x10, 0x55, 0xe5, 0x5f, 0x4a, 0xd6, 0x0f, 0x03, 0x4f, 0x4a, 0x72, 0xe8, 0xa9, 0x30, 0xee, 0xc9, 0xca, 0x44, - 0x87, 0x89, 0x45, 0x24, 0xff, 0x2f, 0x7f, 0x04, 0x4b, 0x4c, 0x71, 0x2d, 0x15, 0xd8, 0x62, 0x7e, 0x58, 0xdd, 0x5b, - 0x19, 0x03, 0x22, 0x97, 0x00, 0x12, 0x21, 0x6f, 0xc8, 0xd7, 0x49, 0xf2, 0xae, 0x70, 0xed, 0x54, 0xaf, 0x79, 0x62, - 0xe6, 0x91, 0xdf, 0xf9, 0x89, 0x79, 0x9c, 0x6a, 0x82, 0x59, 0x82, 0x2b, 0x26, 0x2e, 0x00, 0xaf, 0xf4, 0x17, 0x55, - 0x6e, 0x0a, 0x04, 0x82, 0xb3, 0xaf, 0xd2, 0x9f, 0x14, 0x54, 0x21, 0x6e, 0x47, 0x42, 0x9b, 0x6a, 0x11, 0x9e, 0xd9, - 0x33, 0x0e, 0x2e, 0x36, 0x39, 0x22, 0x03, 0x03, 0x90, 0xe5, 0xa9, 0xd7, 0xc2, 0x3e, 0x9f, 0xf9, 0x37, 0xda, 0x5e, - 0x5b, 0x65, 0x2b, 0x16, 0x3c, 0x78, 0xed, 0xd5, 0x77, 0xb3, 0x4a, 0xd9, 0x2a, 0xb7, 0xfc, 0x86, 0xce, 0xf0, 0x3e, - 0x83, 0x36, 0xd1, 0xf7, 0x1e, 0x0d, 0x56, 0x28, 0xcd, 0x4f, 0x09, 0x93, 0xb0, 0x10, 0xe6, 0x98, 0x6d, 0x27, 0x54, - 0xcf, 0x99, 0xf5, 0xab, 0x14, 0x55, 0xfe, 0x91, 0x63, 0xdc, 0x75, 0xea, 0x5c, 0x98, 0x67, 0xf2, 0x99, 0x92, 0x6c, - 0x58, 0x03, 0xe3, 0x86, 0xe1, 0xdb, 0xfc, 0x8b, 0x9e, 0x0c, 0xed, 0x51, 0xbf, 0xef, 0xd0, 0xf6, 0x30, 0xaa, 0xd3, - 0xad, 0x10, 0x17, 0x5d, 0x18, 0x82, 0x70, 0xf7, 0x29, 0x2f, 0x48, 0xeb, 0xb0, 0xf6, 0x54, 0xa3, 0xc3, 0xa0, 0xc6, - 0x40, 0x9d, 0x16, 0x83, 0xe5, 0xb4, 0x54, 0x50, 0x36, 0x05, 0x33, 0xd5, 0x06, 0x6e, 0xd8, 0x9a, 0xfb, 0x7f, 0xf9, - 0x1f, 0x21, 0xbc, 0x3f, 0xf0, 0x87, 0xf1, 0xbf, 0x97, 0x48, 0x8e, 0x98, 0xb0, 0xa4, 0x92, 0xbb, 0x77, 0x01, 0xe3, - 0x4f, 0xa1, 0xbf, 0x86, 0xf6, 0xa1, 0x1d, 0x43, 0x7b, 0x20, 0xca, 0xe0, 0xfe, 0x6a, 0x29, 0xc6, 0x4e, 0x01, 0x21, - 0xc6, 0xf2, 0xa2, 0x04, 0x2a, 0x29, 0xc5, 0x81, 0x17, 0x15, 0x00, 0xce, 0xbb, 0x40, 0xc7, 0xa6, 0xd8, 0xf6, 0x92, - 0x20, 0x06, 0x15, 0x10, 0x4d, 0x89, 0x9c, 0x93, 0xb4, 0xaf, 0x38, 0xf1, 0x1e, 0x73, 0x72, 0x62, 0x1f, 0xd4, 0xf5, - 0xf9, 0x86, 0xcb, 0xb1, 0x40, 0xd7, 0x15, 0x63, 0x53, 0xb6, 0xa3, 0xcb, 0x8b, 0xd5, 0xcb, 0x5b, 0x31, 0x89, 0x02, - 0xe9, 0xd2, 0x46, 0x5e, 0x90, 0x8f, 0xb8, 0x3d, 0x5b, 0x96, 0x65, 0xf3, 0xa2, 0x65, 0x9c, 0xaf, 0x0c, 0x90, 0x0d, - 0x50, 0xb4, 0xa5, 0x2f, 0x2c, 0xe4, 0xb0, 0x2c, 0x0d, 0xe5, 0x36, 0x70, 0xae, 0xca, 0xf6, 0xe6, 0x4d, 0x82, 0x34, - 0x3f, 0xe4, 0x75, 0xac, 0x4d, 0x2d, 0xb5, 0xff, 0x6e, 0xab, 0x36, 0xec, 0x68, 0x14, 0xcd, 0x81, 0xe9, 0xa8, 0x73, - 0x98, 0x8f, 0x39, 0x17, 0xe4, 0x59, 0xd4, 0xb6, 0x76, 0xbd, 0x95, 0x3c, 0xbf, 0xf1, 0x2a, 0xce, 0x05, 0x0f, 0xab, - 0x3f, 0x3e, 0xb6, 0xd4, 0xc6, 0xf5, 0x2d, 0xbe, 0xf1, 0x07, 0x7f, 0x0f, 0xa2, 0x54, 0x43, 0x0d, 0xe7, 0x2f, 0x27, - 0xe7, 0xb5, 0x7d, 0x02, 0x2c, 0xa7, 0xad, 0xca, 0x7e, 0x9d, 0x57, 0xb1, 0x30, 0x13, 0x99, 0xef, 0xd2, 0x9a, 0xe8, - 0x4b, 0x4d, 0x16, 0x99, 0xd3, 0xf1, 0x37, 0x6d, 0xf8, 0xed, 0xd2, 0x9b, 0x11, 0x42, 0xc9, 0x8c, 0xd0, 0x8c, 0xa3, - 0x9a, 0x37, 0xff, 0xa1, 0xe5, 0xfb, 0xb2, 0x43, 0x0a, 0xee, 0x78, 0x4b, 0x56, 0x43, 0x79, 0x3b, 0x5d, 0x9b, 0x8f, - 0xbc, 0x2c, 0x40, 0xed, 0xa9, 0x54, 0x82, 0x04, 0x7e, 0x4f, 0x1f, 0x9a, 0x87, 0xcd, 0xa6, 0xaa, 0xbd, 0x5e, 0x1f, - 0x1a, 0x13, 0x61, 0x2a, 0x8f, 0x60, 0x71, 0xb9, 0x51, 0x68, 0x67, 0xf8, 0x95, 0xce, 0xb9, 0x19}; + 0x1b, 0xc3, 0x97, 0x11, 0x55, 0xb5, 0x65, 0x2c, 0x8a, 0x8a, 0x55, 0x0b, 0xd0, 0xba, 0x80, 0x1b, 0x32, 0xb0, 0x81, + 0x4f, 0x27, 0x63, 0xf1, 0x7e, 0x88, 0xe3, 0xd8, 0x52, 0x84, 0x55, 0xe8, 0x35, 0x5b, 0x2b, 0x82, 0xe1, 0xed, 0x1f, + 0xfd, 0xde, 0x63, 0x38, 0x3a, 0x71, 0x78, 0xb0, 0x42, 0x17, 0x15, 0x54, 0x23, 0xe1, 0xaa, 0x28, 0x11, 0x94, 0x23, + 0xb4, 0xf4, 0x91, 0x3c, 0xfc, 0xff, 0xab, 0x5a, 0x56, 0x2d, 0x07, 0xcb, 0x09, 0x6f, 0x79, 0x15, 0x1c, 0xd2, 0x87, + 0x40, 0x38, 0x97, 0xce, 0x9d, 0x87, 0x67, 0xe0, 0xa0, 0x4d, 0x49, 0x1a, 0x27, 0xf0, 0xf5, 0x8d, 0x9d, 0x72, 0x02, + 0x12, 0x45, 0x49, 0x2b, 0x48, 0xe0, 0x6a, 0xff, 0x5f, 0x6d, 0x55, 0xf1, 0x54, 0x12, 0xc1, 0x2f, 0x1e, 0xc8, 0x83, + 0x0c, 0x92, 0x0d, 0x75, 0xd8, 0xf5, 0xdd, 0xc7, 0x75, 0x50, 0x6c, 0xa1, 0xb2, 0x85, 0xad, 0x6d, 0x63, 0xd1, 0x96, + 0x38, 0xaa, 0x65, 0x4d, 0x1e, 0x6c, 0x14, 0x4e, 0x10, 0xed, 0xbe, 0xaf, 0xf3, 0xff, 0xeb, 0xf7, 0xc6, 0x6f, 0xd9, + 0x77, 0x24, 0x81, 0xbb, 0x26, 0xd0, 0x31, 0x81, 0xae, 0x49, 0x8d, 0x23, 0xb0, 0x5a, 0x62, 0xe5, 0x49, 0x4a, 0x17, + 0xa7, 0x66, 0xda, 0xb2, 0x6a, 0x9d, 0xf0, 0x4d, 0xa4, 0x1d, 0x59, 0xe6, 0x00, 0x55, 0x58, 0x63, 0xf9, 0x0c, 0xfe, + 0xa0, 0xbd, 0xa5, 0xfa, 0x75, 0x9f, 0xcb, 0x49, 0x22, 0x0c, 0xe1, 0xd5, 0xb0, 0xd8, 0x13, 0x72, 0xd3, 0x25, 0x4e, + 0x48, 0x1b, 0xa2, 0x76, 0x4f, 0x5c, 0x42, 0xe2, 0x98, 0x6d, 0x9b, 0x80, 0x3e, 0x69, 0x90, 0xcf, 0x69, 0xa5, 0x2e, + 0xc0, 0x47, 0x4f, 0x5c, 0xac, 0x83, 0x99, 0xe7, 0xfc, 0xff, 0xdf, 0x96, 0x7e, 0xa5, 0xd5, 0x2d, 0x98, 0x45, 0x4a, + 0x81, 0x52, 0x20, 0x67, 0x6d, 0x8d, 0xbd, 0xc4, 0x49, 0xb0, 0x41, 0xa8, 0xba, 0xf7, 0xbe, 0x77, 0x47, 0x45, 0x3d, + 0xea, 0xaa, 0x52, 0xcf, 0x6f, 0xb2, 0x2d, 0xea, 0x11, 0x1f, 0x0b, 0x6d, 0x7e, 0xef, 0x55, 0x75, 0xab, 0xaa, 0x5b, + 0xf6, 0x74, 0x4b, 0xf6, 0x18, 0xe7, 0x1c, 0x59, 0xf6, 0xfe, 0x01, 0xd2, 0xff, 0x8b, 0xe4, 0xf9, 0xe7, 0x2c, 0x52, + 0x84, 0x51, 0x02, 0x9c, 0xed, 0xc9, 0x31, 0x0a, 0x01, 0xd3, 0xcd, 0x36, 0xdc, 0x74, 0x55, 0x87, 0x2a, 0x51, 0x4e, + 0xcf, 0x28, 0xc5, 0x71, 0xec, 0x2d, 0x23, 0x97, 0xcb, 0x55, 0x7d, 0xfd, 0xd6, 0x83, 0x1d, 0xc6, 0x0a, 0x21, 0x9e, + 0x5d, 0x46, 0xd3, 0xfc, 0xcd, 0xca, 0x21, 0x21, 0x24, 0xce, 0x75, 0x5d, 0x7f, 0xa6, 0x0d, 0xf7, 0x70, 0x16, 0xd1, + 0xc4, 0x38, 0xe2, 0x00, 0xf9, 0x14, 0x84, 0xa1, 0x23, 0x9d, 0x6e, 0xcc, 0x71, 0xee, 0xa1, 0xc8, 0x1a, 0xc1, 0xb4, + 0xda, 0x43, 0x30, 0xcf, 0xe1, 0xc0, 0x01, 0x34, 0xb2, 0x3c, 0xb7, 0x7f, 0xf5, 0x81, 0xad, 0xdb, 0xf5, 0x23, 0x32, + 0xe8, 0xf1, 0x66, 0xa5, 0x04, 0xdc, 0x46, 0x71, 0x3d, 0x0e, 0x94, 0x8d, 0x00, 0x35, 0xab, 0xb1, 0x1b, 0x92, 0xef, + 0xcd, 0xef, 0x3f, 0x1d, 0x1c, 0x84, 0x98, 0xe9, 0x3f, 0x54, 0xae, 0x9d, 0x84, 0x17, 0xa2, 0x2e, 0x69, 0x5b, 0xc0, + 0xd5, 0x10, 0x62, 0x1e, 0x06, 0x1e, 0xa2, 0xe0, 0xb5, 0xd7, 0xe2, 0xe9, 0xb4, 0xc6, 0x33, 0x43, 0xc6, 0x96, 0x8b, + 0x5c, 0x0f, 0xd4, 0x5c, 0x18, 0x1c, 0x0e, 0xba, 0x54, 0x85, 0xf3, 0x4c, 0x2e, 0xa2, 0x4d, 0xd7, 0x9a, 0x23, 0xba, + 0x9a, 0xf4, 0xba, 0xa4, 0xf4, 0xdc, 0xdf, 0x7c, 0x53, 0x67, 0xdc, 0x17, 0x7a, 0x7e, 0x49, 0x87, 0x3f, 0xe3, 0xbc, + 0x98, 0x12, 0x88, 0xe8, 0x78, 0x4f, 0x91, 0x72, 0x75, 0x32, 0xc8, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0x83, 0x7d, + 0x06, 0x6e, 0x11, 0x1b, 0xc7, 0xf9, 0x71, 0x99, 0x5f, 0x17, 0x63, 0x5e, 0x35, 0xf3, 0xd5, 0xe1, 0x70, 0xd9, 0xbb, + 0xc1, 0x75, 0x93, 0x66, 0x1f, 0xd6, 0x83, 0xa5, 0xdb, 0x37, 0x7f, 0x59, 0xd3, 0xe6, 0x66, 0x37, 0x45, 0x5b, 0x5b, + 0x7e, 0xf1, 0xd4, 0xd3, 0x0b, 0xb5, 0x90, 0xaf, 0xeb, 0x69, 0xc2, 0xcd, 0x5c, 0x30, 0xca, 0x16, 0xda, 0x1d, 0xf0, + 0xb9, 0xea, 0xb2, 0xfc, 0xba, 0x5d, 0x25, 0xf3, 0xe3, 0xe4, 0x1b, 0xf1, 0xdb, 0x25, 0x73, 0x7d, 0x31, 0x43, 0x95, + 0x9a, 0x88, 0x6a, 0xf8, 0x47, 0x20, 0x2d, 0xb7, 0xd7, 0x78, 0x6f, 0xe2, 0xbb, 0xa1, 0x85, 0x75, 0xa4, 0xae, 0x6a, + 0x11, 0x25, 0xb7, 0xdf, 0xcd, 0xab, 0xa1, 0x2c, 0x20, 0xff, 0xd6, 0x84, 0xc8, 0x33, 0xee, 0x86, 0x44, 0x55, 0x79, + 0x98, 0x27, 0x37, 0x80, 0x50, 0xa9, 0x8e, 0x88, 0xb5, 0xcc, 0x13, 0xf0, 0x74, 0x38, 0xc7, 0xd8, 0x86, 0xc0, 0x7b, + 0x1d, 0x9e, 0xa6, 0x3b, 0xf3, 0xc3, 0xb5, 0x00, 0x77, 0xc3, 0xca, 0x83, 0x98, 0xba, 0x41, 0x85, 0x3c, 0xd9, 0x29, + 0xc8, 0x79, 0x52, 0x60, 0x25, 0xbb, 0xa6, 0x39, 0xca, 0x76, 0xf2, 0xa6, 0x7d, 0x57, 0xa3, 0xcc, 0xd6, 0xb8, 0xe7, + 0xcd, 0xdf, 0xf9, 0x24, 0x84, 0x14, 0x7f, 0x63, 0x51, 0x9b, 0x98, 0x4a, 0x48, 0xb8, 0x74, 0x9a, 0x74, 0xbf, 0xf1, + 0x9d, 0x48, 0x62, 0x9e, 0xe7, 0x8a, 0x92, 0x75, 0xc8, 0x64, 0x1b, 0xbf, 0xde, 0x54, 0x9b, 0xb6, 0x5c, 0x42, 0xc3, + 0x1a, 0x1e, 0x3f, 0xa7, 0x59, 0xa4, 0x90, 0x50, 0xb2, 0xa7, 0x25, 0x61, 0x65, 0x41, 0xde, 0x83, 0x2f, 0x53, 0x38, + 0x7c, 0xb9, 0xd3, 0xe7, 0x0b, 0x42, 0x59, 0xb8, 0xa9, 0xc0, 0xc4, 0x7b, 0x1b, 0x2b, 0xcd, 0xd7, 0x51, 0x43, 0x30, + 0x93, 0x3f, 0x13, 0xd6, 0x31, 0xfe, 0x55, 0x33, 0xb5, 0x25, 0x44, 0x09, 0x3e, 0xfc, 0x5c, 0x85, 0xac, 0x1b, 0xc1, + 0xd4, 0xb4, 0x54, 0xf2, 0x05, 0x97, 0x72, 0x0e, 0x24, 0x80, 0x50, 0x03, 0x26, 0x7f, 0xce, 0x9a, 0xbe, 0x9f, 0xf1, + 0xf2, 0x7e, 0xc4, 0x9b, 0x26, 0x24, 0x96, 0x37, 0x92, 0x0d, 0x75, 0xff, 0x64, 0xa0, 0xec, 0x38, 0xa6, 0x7a, 0xc8, + 0x7c, 0x1f, 0x76, 0x7b, 0x1a, 0x19, 0x21, 0xc8, 0x7d, 0x33, 0x42, 0xc3, 0x6c, 0x5e, 0xf0, 0x0b, 0x41, 0xaf, 0x8c, + 0x34, 0xa9, 0x8a, 0x2a, 0xbc, 0xff, 0xf5, 0x0b, 0x21, 0x7a, 0x1c, 0xea, 0xd1, 0xff, 0x4e, 0xe9, 0x2e, 0xd5, 0x12, + 0xc3, 0x7a, 0x28, 0xbc, 0x54, 0xe7, 0x95, 0xaa, 0xcd, 0x05, 0x02, 0x30, 0xe4, 0x56, 0x22, 0xfb, 0x9b, 0x91, 0x04, + 0xec, 0x30, 0x53, 0xfe, 0x75, 0x2d, 0xc2, 0x32, 0xc1, 0xe5, 0xcf, 0x59, 0x65, 0xaf, 0xe2, 0x93, 0x94, 0x3e, 0x9a, + 0x23, 0xaa, 0x2c, 0x61, 0x7c, 0x59, 0x10, 0xa4, 0x3c, 0x9b, 0x17, 0x9b, 0xc6, 0x8d, 0xdc, 0x51, 0x7b, 0x10, 0xaf, + 0x72, 0x1d, 0xc7, 0x12, 0x95, 0xad, 0x72, 0x02, 0x90, 0x3c, 0xbb, 0xef, 0x06, 0x61, 0xb0, 0x9c, 0x10, 0xa9, 0x2e, + 0x23, 0xfc, 0x73, 0xae, 0x0a, 0x6e, 0x25, 0x9a, 0x55, 0xcd, 0xfd, 0x37, 0xe8, 0x62, 0xb7, 0xe0, 0x8e, 0xcf, 0xeb, + 0xb9, 0xe1, 0x2a, 0xbc, 0x29, 0xfc, 0xb6, 0x64, 0x90, 0x5e, 0x59, 0x8e, 0x26, 0xd1, 0xaa, 0x8e, 0x38, 0x89, 0x68, + 0x81, 0xb1, 0xd9, 0x7f, 0xd2, 0xe2, 0xbd, 0xa0, 0x13, 0x2a, 0x6d, 0x2f, 0xd5, 0xe5, 0x74, 0xc6, 0x0f, 0x2e, 0xa8, + 0xd7, 0xc5, 0xf9, 0x94, 0x45, 0x50, 0xe1, 0xdb, 0xd4, 0x9f, 0xe9, 0x9c, 0x7a, 0x9f, 0x2f, 0x37, 0xcd, 0x73, 0x8f, + 0x65, 0xb7, 0x5b, 0x6b, 0x14, 0xb7, 0xae, 0x42, 0x6a, 0xc3, 0x8d, 0x97, 0x71, 0x5b, 0x2b, 0x28, 0xae, 0x08, 0x4f, + 0xb5, 0xa6, 0x89, 0x34, 0x76, 0x89, 0x53, 0x36, 0xc6, 0xfb, 0x77, 0x4b, 0xdc, 0x57, 0x4b, 0x99, 0x32, 0xc4, 0x34, + 0x3c, 0xa1, 0xee, 0x5e, 0x9a, 0x1a, 0x0c, 0x0b, 0x1e, 0xbb, 0x45, 0x7c, 0x21, 0x55, 0x09, 0x0a, 0x46, 0xe5, 0x34, + 0x4f, 0xbc, 0x78, 0xe8, 0x5d, 0xb0, 0x04, 0x88, 0xb7, 0xe8, 0xf2, 0x7e, 0x01, 0xc1, 0x8a, 0xd6, 0x0a, 0xb8, 0x13, + 0x4d, 0x90, 0xf0, 0x02, 0x1d, 0x06, 0x19, 0xea, 0x0d, 0xc8, 0x66, 0x95, 0xe8, 0x9d, 0xb3, 0x63, 0x50, 0x5a, 0xcd, + 0xa2, 0xbd, 0x76, 0x9e, 0xde, 0x05, 0xb6, 0xe4, 0xfc, 0x9c, 0x66, 0x63, 0xc6, 0x48, 0x9c, 0x5e, 0x14, 0x31, 0x65, + 0x9e, 0xa8, 0xb9, 0xb6, 0x44, 0x75, 0x9a, 0xbb, 0x3b, 0x63, 0xc6, 0x89, 0xfd, 0x7a, 0x15, 0x7d, 0xd7, 0xc7, 0x55, + 0xcd, 0x80, 0x0b, 0xcc, 0x86, 0xb5, 0xf1, 0xff, 0x69, 0x28, 0x94, 0x82, 0xbf, 0x9a, 0x75, 0x83, 0xe2, 0x5e, 0x2c, + 0xa7, 0xae, 0x27, 0x42, 0xd7, 0xdf, 0x19, 0xd8, 0x8f, 0x77, 0x84, 0x4f, 0x50, 0x46, 0x36, 0x76, 0xfb, 0xa6, 0x34, + 0xc2, 0xf5, 0x2a, 0xf9, 0xbc, 0x7f, 0x6a, 0xfb, 0x86, 0xfa, 0xfc, 0x58, 0x1c, 0xfb, 0x57, 0x6f, 0x28, 0xa6, 0x0e, + 0xdc, 0xc5, 0xec, 0xb9, 0x68, 0xbe, 0xb5, 0xce, 0xd1, 0x83, 0x87, 0xfc, 0x30, 0xec, 0x9d, 0x6e, 0x2c, 0xa6, 0xa6, + 0x8d, 0x07, 0x1a, 0x43, 0x02, 0xbf, 0x66, 0x0e, 0x6b, 0xf5, 0x40, 0x1c, 0xb1, 0x6a, 0x93, 0x53, 0x91, 0xfa, 0x8d, + 0x2a, 0x63, 0x85, 0x79, 0x2d, 0xae, 0x64, 0x21, 0x95, 0x75, 0x18, 0x28, 0x64, 0xa4, 0x3d, 0xa3, 0xdc, 0xb3, 0x82, + 0x87, 0xb9, 0xfe, 0x5d, 0x70, 0x87, 0xaf, 0xef, 0xed, 0x87, 0x26, 0xbe, 0x85, 0xf1, 0xa2, 0xec, 0x54, 0x66, 0x89, + 0x72, 0xcc, 0x02, 0x51, 0x24, 0xcf, 0x88, 0xe6, 0xf8, 0x9a, 0x8d, 0x21, 0x01, 0x72, 0x23, 0x20, 0xc7, 0xdd, 0x7b, + 0xc5, 0xb1, 0x4d, 0x88, 0x40, 0xa1, 0xdd, 0x2d, 0x90, 0x85, 0x82, 0x4c, 0x12, 0x49, 0xee, 0x8e, 0x86, 0x12, 0xfb, + 0x63, 0xf5, 0xd2, 0x85, 0x5b, 0x44, 0xb2, 0xb1, 0x1b, 0x12, 0x08, 0xa4, 0xf1, 0x3e, 0xd5, 0xe7, 0x02, 0x61, 0x29, + 0x40, 0xc7, 0xc1, 0x3f, 0x49, 0x09, 0xab, 0x99, 0x0c, 0x69, 0x36, 0x70, 0x57, 0xe6, 0x65, 0x37, 0xec, 0x7f, 0x67, + 0xa3, 0x02, 0xc2, 0xf1, 0xa1, 0x7f, 0xec, 0x26, 0x28, 0x32, 0x50, 0xb4, 0x42, 0x3d, 0x14, 0x94, 0x6e, 0x28, 0x62, + 0x50, 0xed, 0x8f, 0x9b, 0xc2, 0xdc, 0xdd, 0xc0, 0x64, 0x89, 0x8a, 0xd6, 0x3c, 0x79, 0x2f, 0xea, 0xdb, 0x88, 0xc1, + 0x27, 0x33, 0x76, 0xe8, 0x66, 0xa2, 0x92, 0x5d, 0xaa, 0x0c, 0xac, 0x83, 0x75, 0x2a, 0x95, 0x02, 0x2f, 0x6a, 0x72, + 0xf7, 0x2d, 0x20, 0x2a, 0xde, 0xa9, 0x8b, 0xce, 0xa0, 0x85, 0x57, 0x5a, 0xe8, 0x0c, 0xfa, 0xe5, 0x8c, 0x42, 0xd2, + 0xb1, 0xa6, 0x76, 0xb9, 0x4e, 0x54, 0x0c, 0xf6, 0x84, 0x0d, 0x4a, 0xb4, 0xfc, 0x43, 0x9b, 0x92, 0x88, 0x30, 0xd7, + 0x3d, 0x1f, 0xfe, 0x71, 0x66, 0x48, 0x1f, 0xde, 0xea, 0x21, 0x95, 0x24, 0xc2, 0x27, 0x7c, 0x39, 0x88, 0xd7, 0x1d, + 0x90, 0x14, 0xb8, 0x77, 0x5d, 0xb1, 0x76, 0x2f, 0x3b, 0xe2, 0xe5, 0x64, 0x4b, 0xcd, 0xb8, 0x2e, 0x53, 0xd0, 0xa8, + 0xe3, 0x78, 0xcb, 0xa7, 0xb0, 0xe1, 0x5d, 0xe9, 0x33, 0x3a, 0x16, 0x98, 0x25, 0x90, 0x08, 0x91, 0xde, 0x3f, 0xba, + 0x73, 0xa1, 0xe6, 0x75, 0x92, 0x19, 0x0a, 0x91, 0x5a, 0x25, 0x37, 0x41, 0x85, 0xe3, 0xa9, 0x42, 0xec, 0x48, 0x4a, + 0xca, 0x84, 0x23, 0x4c, 0x8f, 0x2b, 0xa2, 0xa3, 0xe4, 0x3e, 0x69, 0x2a, 0x19, 0x73, 0xf5, 0xbf, 0x4c, 0x69, 0x82, + 0xd9, 0x95, 0xc3, 0x21, 0x11, 0x20, 0x65, 0x5a, 0x6a, 0x37, 0x78, 0x3f, 0x22, 0x3e, 0x15, 0x80, 0x4a, 0x44, 0xa2, + 0x70, 0xcf, 0x2e, 0xfa, 0xb3, 0x28, 0x21, 0x62, 0x30, 0x13, 0xd3, 0x59, 0xf2, 0xfe, 0x5a, 0xe9, 0xe4, 0x75, 0xa3, + 0xab, 0x51, 0xcd, 0xeb, 0x07, 0x95, 0x8f, 0x98, 0x2b, 0x97, 0x4f, 0x02, 0x19, 0x5b, 0x4d, 0xae, 0xa9, 0xcc, 0xb3, + 0xb2, 0xb8, 0x0a, 0x0b, 0x54, 0x1b, 0xb5, 0x80, 0xeb, 0x73, 0x9d, 0xdb, 0x10, 0x75, 0xce, 0x41, 0xe4, 0x80, 0x1d, + 0x56, 0xb3, 0xd0, 0xd9, 0x31, 0x7d, 0x70, 0x99, 0x1c, 0xe1, 0x34, 0x9d, 0xb9, 0x63, 0x68, 0xa7, 0xf7, 0x22, 0x39, + 0x0c, 0x2e, 0x56, 0xa0, 0x0b, 0x28, 0xa7, 0x86, 0x31, 0x8a, 0x1c, 0x50, 0x62, 0xa9, 0x94, 0x72, 0x01, 0x40, 0x8b, + 0xa2, 0xab, 0xa0, 0x0c, 0x85, 0x2a, 0x69, 0x64, 0x0b, 0x07, 0x2b, 0x8e, 0x11, 0xaf, 0xbd, 0xfa, 0x21, 0x10, 0xb2, + 0x68, 0xbb, 0x06, 0xea, 0x40, 0xa9, 0xe6, 0xad, 0x7f, 0x17, 0xb9, 0xe8, 0xc2, 0xb3, 0x32, 0x40, 0x99, 0x3f, 0xaa, + 0x36, 0xeb, 0x4e, 0x26, 0x2f, 0xae, 0x8c, 0x17, 0xaa, 0x6c, 0x78, 0x90, 0x3c, 0x4b, 0x64, 0x4a, 0x28, 0x70, 0xca, + 0x92, 0xc6, 0x3e, 0xf1, 0xc1, 0x8e, 0xfc, 0xf6, 0x84, 0xb9, 0x39, 0x56, 0x46, 0x35, 0xe2, 0xe9, 0x8b, 0xaa, 0xeb, + 0x9a, 0x21, 0x42, 0xcd, 0x3f, 0x7c, 0xed, 0xac, 0xff, 0xa6, 0x1b, 0x8d, 0xde, 0x91, 0x75, 0xd6, 0xe4, 0xdf, 0x86, + 0xc1, 0x9d, 0xce, 0x9e, 0xd5, 0x55, 0x83, 0x58, 0x2b, 0x28, 0x02, 0xe1, 0x80, 0x07, 0xbf, 0xa9, 0x8e, 0xf6, 0x9b, + 0x80, 0x25, 0xef, 0x18, 0xda, 0x93, 0xea, 0x8a, 0x09, 0x4d, 0xcb, 0xe7, 0x1f, 0x41, 0x73, 0xa5, 0x86, 0xb2, 0x2c, + 0xf8, 0xf0, 0x01, 0x65, 0x06, 0xa5, 0xca, 0x51, 0x3b, 0xdd, 0x86, 0x5c, 0x13, 0x68, 0xa2, 0x27, 0x41, 0x9e, 0xaf, + 0xbf, 0x70, 0x57, 0xa5, 0x32, 0x90, 0x6f, 0x98, 0xec, 0xc2, 0x5d, 0xb2, 0xba, 0xca, 0x39, 0xfb, 0x2f, 0x51, 0xcc, + 0xf3, 0xbc, 0xa7, 0x23, 0x23, 0xbd, 0x67, 0x47, 0x6e, 0x6a, 0xc5, 0xf9, 0x29, 0x4a, 0x48, 0x16, 0x6d, 0x59, 0x68, + 0xcb, 0x11, 0x8c, 0x81, 0x12, 0x3a, 0x12, 0xb9, 0x0c, 0x59, 0xd6, 0xb0, 0xcc, 0xbe, 0xe5, 0x7f, 0xe3, 0x90, 0x49, + 0x4a, 0x72, 0x9a, 0x5c, 0xf7, 0xb2, 0xb8, 0xec, 0xca, 0x12, 0x95, 0xd8, 0x51, 0x6b, 0xba, 0x12, 0x43, 0xf2, 0xd5, + 0x7b, 0xda, 0xb4, 0xd4, 0x7e, 0x84, 0x74, 0x67, 0x46, 0x0a, 0xfa, 0xa0, 0xea, 0x6d, 0x74, 0xc1, 0xd1, 0x06, 0x90, + 0x63, 0x49, 0xf2, 0x3c, 0x29, 0x06, 0xd9, 0x44, 0x0a, 0x25, 0xea, 0x49, 0x0e, 0x63, 0x59, 0xc2, 0xdc, 0x8f, 0x12, + 0xcc, 0xd2, 0xb2, 0x8c, 0x91, 0x3e, 0x2d, 0x62, 0xa7, 0x14, 0x8f, 0x50, 0xf9, 0x38, 0xbb, 0xef, 0xa6, 0xa1, 0x24, + 0xd5, 0x49, 0x99, 0x20, 0x68, 0xcf, 0x81, 0xd0, 0x31, 0x01, 0xf3, 0xbd, 0xa9, 0xe8, 0x2f, 0x7f, 0x8e, 0x2b, 0x16, + 0xf6, 0x1f, 0x52, 0x3c, 0x33, 0xb3, 0x9b, 0x5f, 0x59, 0xce, 0x91, 0xe5, 0xcc, 0xd0, 0x49, 0x9b, 0x42, 0x0a, 0x1b, + 0x67, 0xbb, 0xfe, 0x82, 0x34, 0xef, 0x8d, 0x0e, 0x47, 0x7a, 0x09, 0xbf, 0x2f, 0x04, 0xd7, 0x87, 0x24, 0x8c, 0x90, + 0xab, 0x2e, 0xaa, 0xdd, 0x3c, 0x79, 0x91, 0xc2, 0x6a, 0x47, 0x47, 0x5c, 0x8a, 0xdd, 0xdb, 0x59, 0xc4, 0x5a, 0x91, + 0x0a, 0xf6, 0xbd, 0x32, 0x91, 0x89, 0xcd, 0xa0, 0x04, 0x67, 0x2b, 0x03, 0x7a, 0x56, 0xbb, 0x78, 0x26, 0xaa, 0xa3, + 0x26, 0xd4, 0x59, 0x81, 0x67, 0xa8, 0x01, 0x64, 0xeb, 0xbc, 0x69, 0xc9, 0x9e, 0x0e, 0x96, 0x93, 0xd4, 0x50, 0x9a, + 0x45, 0x04, 0xfe, 0xd0, 0xdd, 0xde, 0x93, 0x88, 0x0c, 0x03, 0x3f, 0xce, 0x46, 0x94, 0x07, 0xa8, 0x19, 0xc3, 0x89, + 0xa5, 0x49, 0x92, 0x35, 0x5c, 0x98, 0xf7, 0x56, 0x04, 0x71, 0xdf, 0xc7, 0xb6, 0x88, 0xfa, 0xdb, 0x51, 0x26, 0xd8, + 0x57, 0xeb, 0x04, 0xa2, 0x62, 0x16, 0xca, 0xe4, 0x5b, 0x42, 0x78, 0xcb, 0x03, 0xc3, 0xd5, 0xf9, 0x86, 0xd9, 0x58, + 0xb5, 0x92, 0x23, 0x5f, 0x55, 0x0b, 0x3b, 0x20, 0x1c, 0xb5, 0x2f, 0x1d, 0xeb, 0x67, 0xb7, 0x2a, 0x7a, 0x3d, 0x2d, + 0xbf, 0xda, 0xd4, 0x95, 0xaa, 0x03, 0xb9, 0x18, 0xa3, 0x6c, 0xc6, 0xa4, 0xd1, 0x00, 0xb5, 0x80, 0x5c, 0x59, 0x47, + 0xaa, 0x78, 0x9a, 0x96, 0x70, 0x88, 0x07, 0x1e, 0xaf, 0xae, 0x1d, 0xe9, 0x25, 0xdb, 0xa1, 0x03, 0xda, 0x7a, 0x87, + 0x6f, 0xbd, 0x76, 0x2d, 0xc6, 0x8d, 0x05, 0xbc, 0x01, 0xa0, 0x12, 0x95, 0x0a, 0x2a, 0xd1, 0x20, 0xe5, 0x52, 0xc5, + 0x75, 0xd0, 0x29, 0xd7, 0xb4, 0x58, 0x59, 0x2b, 0xbc, 0xcb, 0x03, 0xfc, 0x69, 0x07, 0xa4, 0xb2, 0xae, 0x82, 0x62, + 0xd1, 0xfd, 0x16, 0x84, 0x14, 0xe2, 0xcd, 0xf4, 0xcd, 0x1c, 0xcc, 0xc9, 0x92, 0x35, 0x5f, 0xcb, 0x13, 0x61, 0xb1, + 0x72, 0x6b, 0x4e, 0xce, 0x91, 0x51, 0x49, 0xdf, 0xde, 0x03, 0xa2, 0x6e, 0x76, 0x79, 0xbf, 0xf8, 0xd1, 0x33, 0xee, + 0x29, 0xf0, 0xf1, 0x76, 0xbf, 0x1b, 0x1c, 0x7e, 0x78, 0xcb, 0xe1, 0x90, 0x33, 0x48, 0x43, 0x1a, 0x1b, 0xc8, 0x10, + 0xbc, 0x58, 0x15, 0x16, 0xfc, 0xb1, 0x6e, 0x75, 0x89, 0xe8, 0x3c, 0x05, 0xfc, 0x3d, 0x73, 0x17, 0xba, 0x3f, 0x20, + 0x72, 0x17, 0xf2, 0x78, 0xde, 0x65, 0x52, 0x3e, 0x42, 0x1a, 0x49, 0xee, 0xdf, 0x47, 0x9a, 0xca, 0xe4, 0x7c, 0xf3, + 0x97, 0x3c, 0x2a, 0x54, 0xd6, 0xc1, 0x14, 0x1a, 0x94, 0xd4, 0x39, 0x60, 0xd0, 0x46, 0xc6, 0x55, 0xbd, 0x1c, 0x3a, + 0x69, 0xf5, 0x79, 0xb6, 0x07, 0x99, 0x22, 0x10, 0x9d, 0x1e, 0x94, 0x51, 0x06, 0x42, 0x00, 0xbc, 0x80, 0x00, 0x68, + 0x09, 0x06, 0x03, 0xf8, 0x48, 0xf7, 0x74, 0xd0, 0x98, 0x8c, 0xd3, 0xa7, 0x92, 0x0c, 0x75, 0xa9, 0xfc, 0x9a, 0x58, + 0x8f, 0x92, 0x25, 0x62, 0x52, 0x41, 0x0b, 0xc5, 0x8c, 0xe2, 0x53, 0xf3, 0xce, 0xdc, 0xd2, 0xfb, 0x92, 0x19, 0xc6, + 0x99, 0x66, 0xa9, 0xd3, 0x46, 0xf2, 0x91, 0xba, 0x4f, 0x79, 0xb0, 0x4a, 0x10, 0x9e, 0x12, 0xaa, 0x32, 0x3c, 0xd4, + 0x35, 0x53, 0x8a, 0x67, 0x38, 0x86, 0xe3, 0xf2, 0xad, 0x45, 0xea, 0xe0, 0x83, 0xc4, 0xa7, 0xef, 0x63, 0xa8, 0xad, + 0xf9, 0xe3, 0xaf, 0x1d, 0x09, 0xbf, 0x8c, 0x32, 0xcc, 0x95, 0x88, 0x03, 0x2d, 0x53, 0x60, 0x87, 0x0b, 0x3d, 0x4f, + 0xbc, 0xdc, 0x97, 0xb8, 0xa3, 0x40, 0x0f, 0x46, 0xec, 0xa9, 0x0f, 0x99, 0xdb, 0x33, 0x91, 0xb5, 0x2d, 0xea, 0xf5, + 0xdf, 0x17, 0xdf, 0xe5, 0xc9, 0xed, 0x98, 0x27, 0x75, 0x8a, 0x0a, 0xb4, 0x52, 0x7b, 0xcb, 0x7c, 0x5f, 0xcc, 0xc2, + 0xa3, 0xef, 0x56, 0xc8, 0x18, 0x43, 0x33, 0xf2, 0x60, 0x63, 0x44, 0x50, 0x16, 0x3b, 0x98, 0xdf, 0x29, 0x24, 0x3f, + 0x3e, 0xc8, 0x41, 0x23, 0x0a, 0x82, 0xaa, 0xfd, 0x05, 0x85, 0xb2, 0x30, 0xf6, 0x37, 0xbe, 0xf6, 0x3d, 0xb2, 0xea, + 0x14, 0xcb, 0xe3, 0xec, 0x33, 0x3e, 0x67, 0x71, 0xc5, 0xaa, 0x05, 0x59, 0x91, 0x7b, 0x25, 0x9e, 0x8e, 0x59, 0xda, + 0x66, 0xd1, 0xb4, 0x4e, 0x00, 0xef, 0x63, 0xe7, 0xb6, 0xdc, 0x0f, 0xb5, 0xfe, 0x08, 0xe2, 0xea, 0x8b, 0xb0, 0xf6, + 0x3c, 0x08, 0x2b, 0xaf, 0xa2, 0x40, 0x31, 0x6d, 0x4b, 0x7e, 0xde, 0xdb, 0xcf, 0xd8, 0x46, 0xf1, 0x44, 0xb6, 0x9b, + 0xf7, 0xb6, 0x67, 0xdb, 0x38, 0x65, 0x4a, 0xfd, 0x6d, 0xae, 0x0f, 0xfe, 0x0f, 0x11, 0x3f, 0xe6, 0x40, 0xbf, 0x5f, + 0xac, 0xa6, 0xf9, 0xa9, 0xf9, 0x64, 0x85, 0xd2, 0x07, 0xf0, 0xe2, 0xb2, 0x79, 0x31, 0x7a, 0xb5, 0xf6, 0x52, 0xc4, + 0xf2, 0x20, 0xf4, 0x2d, 0x62, 0x68, 0x3b, 0xc8, 0x2e, 0xdf, 0xcf, 0x05, 0xba, 0x60, 0xac, 0x47, 0xbf, 0x01, 0x9e, + 0xb4, 0xda, 0x38, 0x64, 0xe0, 0x32, 0x99, 0x73, 0x13, 0x24, 0xdd, 0x07, 0x55, 0xbf, 0xb7, 0xaf, 0xf2, 0xb8, 0xa2, + 0x07, 0x2e, 0xa8, 0x30, 0xdd, 0x71, 0xd7, 0xb5, 0xba, 0xfa, 0xdb, 0x1d, 0x78, 0x9e, 0x1b, 0xed, 0x45, 0xef, 0x6f, + 0xe2, 0x50, 0xc4, 0x95, 0xec, 0x0b, 0x88, 0x44, 0x26, 0x7e, 0xb3, 0x99, 0x24, 0xf6, 0xe5, 0x02, 0x66, 0x2a, 0x99, + 0x66, 0xb1, 0xb6, 0x74, 0x3b, 0xa7, 0x07, 0xaf, 0x86, 0xe5, 0x6c, 0x30, 0x3c, 0xcb, 0xc0, 0xe5, 0x97, 0xd7, 0xb8, + 0xe3, 0xa6, 0xad, 0x7f, 0xe5, 0x96, 0xf0, 0x25, 0xb2, 0xd4, 0xb5, 0xe4, 0xcf, 0x28, 0xb5, 0x1f, 0x34, 0x95, 0x7f, + 0x12, 0xf4, 0xb4, 0xf4, 0x3e, 0x2f, 0x9d, 0xca, 0xaf, 0xdf, 0xb7, 0x3d, 0xad, 0x16, 0xaf, 0xfe, 0x3a, 0xb9, 0x5e, + 0xff, 0xaf, 0xed, 0x1a, 0x3d, 0xfa, 0x39, 0xbd, 0xb2, 0xbf, 0x13, 0x9b, 0x85, 0x61, 0x77, 0x3d, 0x5d, 0x5c, 0x8b, + 0xea, 0xcf, 0x0f, 0xfc, 0xb3, 0xd3, 0x4a, 0x98, 0x8f, 0xbf, 0xb7, 0x98, 0x4c, 0xad, 0x66, 0xb7, 0xa6, 0x7b, 0xf8, + 0xe9, 0xa7, 0x1e, 0x04, 0xda, 0x95, 0x9c, 0xbb, 0xa6, 0x61, 0x98, 0x45, 0x85, 0x1a, 0x4e, 0xd1, 0x83, 0x3e, 0xda, + 0x1e, 0x37, 0xdf, 0x64, 0xeb, 0xc0, 0xed, 0x65, 0x93, 0x27, 0xcd, 0xd6, 0xf5, 0xb5, 0xc5, 0xf5, 0x5c, 0xa6, 0xcb, + 0x29, 0xb8, 0x91, 0x09, 0x1f, 0xe2, 0xbf, 0x6c, 0xc1, 0x64, 0x15, 0x90, 0xfc, 0x81, 0x14, 0xd7, 0xb7, 0xab, 0xab, + 0x5f, 0x65, 0xb9, 0x12, 0xb3, 0x8e, 0xb4, 0x06, 0x5a, 0x07, 0x41, 0xa3, 0xe6, 0x71, 0x21, 0x66, 0xae, 0xe9, 0x68, + 0x57, 0x72, 0x82, 0x0b, 0x50, 0x18, 0x4d, 0xfd, 0xc7, 0x4f, 0xa1, 0x36, 0xf7, 0x1a, 0xe5, 0x08, 0xae, 0x89, 0x62, + 0xf7, 0x9a, 0xb0, 0xdd, 0x82, 0x71, 0xaa, 0x78, 0x87, 0xaa, 0xca, 0x8d, 0xf6, 0xc5, 0x4c, 0x03, 0xa2, 0xca, 0x72, + 0x12, 0xe0, 0x10, 0x6f, 0x16, 0x6e, 0x92, 0xc4, 0xff, 0x1e, 0xbb, 0x48, 0x99, 0x14, 0xfe, 0xb9, 0x22, 0x64, 0xb1, + 0xd0, 0x2f, 0xb7, 0x8e, 0xd8, 0xd4, 0x0d, 0xab, 0xeb, 0x0f, 0x92, 0x99, 0x90, 0x9a, 0x89, 0xb0, 0xa2, 0x66, 0xbe, + 0x05, 0xdc, 0x93, 0x82, 0x89, 0xe7, 0x22, 0x6f, 0x6d, 0xd7, 0xfc, 0x7d, 0xea, 0xb3, 0xc5, 0x47, 0x91, 0x05, 0xd0, + 0x0d, 0x01, 0x02, 0x1a, 0xd7, 0xa7, 0xc5, 0x7a, 0x6f, 0x3b, 0xef, 0x5f, 0xd2, 0x58, 0x74, 0x3b, 0xe3, 0xca, 0x79, + 0xab, 0x68, 0xec, 0xe9, 0x02, 0x28, 0x69, 0xf5, 0xe5, 0xc7, 0x55, 0x3f, 0xbc, 0xdf, 0xc4, 0xad, 0xde, 0xc7, 0xbb, + 0xfe, 0xb5, 0x50, 0x8e, 0x34, 0x7c, 0x3a, 0xa5, 0xe1, 0xe5, 0x4e, 0x35, 0x31, 0x67, 0x3c, 0x2d, 0xaf, 0x5c, 0xd8, + 0x0d, 0xd9, 0xc6, 0xef, 0x7c, 0x68, 0xeb, 0x81, 0x5f, 0x76, 0x98, 0x22, 0x34, 0x27, 0x9b, 0x29, 0x2f, 0x90, 0x98, + 0xeb, 0x9b, 0xad, 0x38, 0xd8, 0x7b, 0x84, 0x36, 0xe1, 0xaf, 0x97, 0x24, 0x2b, 0xc4, 0xa8, 0xc2, 0x41, 0x5e, 0x1e, + 0xf6, 0x29, 0x4c, 0x82, 0xf5, 0x25, 0x3c, 0x04, 0x8a, 0x3e, 0x62, 0x14, 0xcb, 0xf1, 0x16, 0xea, 0x58, 0x8e, 0x83, + 0xde, 0x2c, 0x1f, 0xb5, 0xb1, 0x8b, 0x9f, 0x31, 0xb0, 0x62, 0xab, 0x90, 0xd3, 0x88, 0x35, 0x5b, 0xf8, 0xde, 0xdc, + 0xfa, 0xa1, 0xde, 0x73, 0x37, 0x24, 0x1c, 0x6e, 0x2b, 0xcf, 0x2f, 0xaa, 0x2d, 0x2b, 0xb5, 0x01, 0xde, 0xd2, 0x9d, + 0x79, 0x50, 0x49, 0x9b, 0xf7, 0x44, 0x76, 0x6f, 0x54, 0xf5, 0xd7, 0x4e, 0x16, 0xe2, 0x97, 0xdf, 0x45, 0xdb, 0x59, + 0x0a, 0x22, 0x5c, 0x84, 0x21, 0xd4, 0x56, 0xa5, 0x47, 0x51, 0x9e, 0xba, 0xfd, 0x14, 0x37, 0xa5, 0xdd, 0x06, 0x19, + 0xe9, 0xfe, 0x0d, 0x90, 0x82, 0x5e, 0x80, 0x40, 0x88, 0x7b, 0xd9, 0x1c, 0x0a, 0x98, 0x64, 0x90, 0x40, 0x2f, 0x13, + 0xac, 0x03, 0xfe, 0xa0, 0xe4, 0xbd, 0xed, 0xc0, 0x03, 0xe0, 0x80, 0xc2, 0x61, 0xa4, 0x7c, 0x65, 0x4e, 0x75, 0x46, + 0x66, 0xcb, 0xaa, 0x75, 0x13, 0x8f, 0xa6, 0xeb, 0x0a, 0x9c, 0x37, 0x15, 0x9b, 0x7f, 0x26, 0x0a, 0xdb, 0x4e, 0xc4, + 0xa9, 0x2c, 0x14, 0x98, 0xa8, 0x31, 0x48, 0x4f, 0x0d, 0x96, 0xad, 0x4a, 0xd3, 0xf8, 0x10, 0xcb, 0x6e, 0x1c, 0xa5, + 0xeb, 0x7a, 0x63, 0xe3, 0xcc, 0x41, 0x98, 0xbd, 0xb1, 0xd7, 0xee, 0xf9, 0x96, 0xb5, 0x37, 0xad, 0x0e, 0xc5, 0x63, + 0x65, 0x71, 0x53, 0xf9, 0xf2, 0xcd, 0xb9, 0x31, 0xe5, 0x59, 0xe6, 0x1c, 0xc2, 0x5a, 0xf0, 0xdf, 0xb0, 0x1b, 0x36, + 0x6d, 0x2c, 0xf9, 0x72, 0x5f, 0x10, 0xc1, 0xee, 0x92, 0xbd, 0xc6, 0xec, 0xb2, 0xa4, 0x0a, 0x43, 0xf0, 0xce, 0x67, + 0x2a, 0x11, 0xcb, 0x1f, 0x51, 0x94, 0x6f, 0x3c, 0xb6, 0xfb, 0xc2, 0x2a, 0xc1, 0xb0, 0x5e, 0x13, 0x78, 0xe1, 0x79, + 0x4b, 0x49, 0x8b, 0x49, 0x79, 0x59, 0x66, 0xf7, 0xcb, 0xee, 0xca, 0x0d, 0xc2, 0xc3, 0xbd, 0xa4, 0x15, 0x62, 0x18, + 0x35, 0x95, 0x2a, 0x70, 0x31, 0x22, 0xea, 0x98, 0xa7, 0xdb, 0xb2, 0xc4, 0x2f, 0x4d, 0x25, 0x49, 0x2d, 0x74, 0x6b, + 0x07, 0x87, 0xdf, 0x59, 0xd2, 0x44, 0x88, 0x2d, 0x28, 0x5e, 0x77, 0x48, 0x60, 0xe7, 0x9c, 0x52, 0xbe, 0x9f, 0x3f, + 0xca, 0x2c, 0x19, 0x5e, 0x95, 0x03, 0x55, 0xc8, 0xce, 0x0c, 0x19, 0xad, 0xb8, 0xeb, 0x44, 0x12, 0xf4, 0x2e, 0x12, + 0x83, 0x15, 0xc2, 0x7e, 0x28, 0xca, 0x12, 0xfd, 0x80, 0x57, 0x93, 0x1b, 0x78, 0x11, 0x58, 0x75, 0xe5, 0xb1, 0x53, + 0x12, 0xe4, 0x00, 0xf9, 0x49, 0x70, 0xd6, 0xc3, 0x4c, 0xee, 0x8e, 0x40, 0x04, 0x8f, 0x77, 0x32, 0x11, 0xd0, 0x06, + 0xf2, 0x55, 0x5d, 0xdc, 0x89, 0x44, 0x15, 0x82, 0xbf, 0x24, 0x77, 0xf4, 0x6e, 0xab, 0x34, 0x1a, 0xed, 0x6c, 0x28, + 0x4c, 0xdc, 0xc6, 0x75, 0xe3, 0x1d, 0x2f, 0x98, 0xa3, 0xcd, 0xe8, 0xae, 0x58, 0x9e, 0xe7, 0xcd, 0x4d, 0x69, 0x04, + 0x4b, 0xea, 0x2b, 0xcc, 0x4b, 0xb3, 0x56, 0x74, 0x64, 0x6c, 0x11, 0x24, 0x06, 0xcc, 0x69, 0x67, 0xc9, 0x62, 0xf5, + 0xdb, 0x58, 0x8b, 0x1c, 0x47, 0x58, 0x96, 0x04, 0x10, 0xcd, 0x0b, 0x91, 0x17, 0x43, 0x8e, 0xa3, 0x25, 0xaa, 0x14, + 0x18, 0x73, 0x8b, 0x18, 0x76, 0xb1, 0xc9, 0xc9, 0x6d, 0x69, 0xa4, 0x68, 0xf8, 0x26, 0xa7, 0xa7, 0xf7, 0xd6, 0xf0, + 0xda, 0x88, 0x64, 0xe4, 0x60, 0x7b, 0x2e, 0xb7, 0x25, 0xac, 0xf2, 0x53, 0xbf, 0x5b, 0x6b, 0x15, 0x2d, 0x97, 0xe3, + 0x60, 0xb4, 0xd7, 0x92, 0x45, 0xbb, 0x01, 0x35, 0x7f, 0xc9, 0xba, 0x87, 0x8c, 0x35, 0xda, 0xb0, 0xd5, 0x41, 0x5d, + 0x88, 0x73, 0x3e, 0xf6, 0x15, 0xfe, 0x46, 0x9e, 0xc0, 0x4c, 0x53, 0x72, 0x91, 0xff, 0xbe, 0xbf, 0x54, 0x25, 0xf9, + 0xeb, 0x60, 0x27, 0x3c, 0x16, 0x6a, 0x64, 0xbf, 0x57, 0x13, 0x33, 0x99, 0x61, 0x87, 0xf7, 0x09, 0xb8, 0x42, 0x7c, + 0x31, 0xc0, 0xce, 0x2c, 0x9d, 0x4b, 0xda, 0xa9, 0x8c, 0x19, 0x97, 0xe2, 0x38, 0x93, 0x26, 0x1b, 0x5b, 0x53, 0x7f, + 0x7b, 0x89, 0x55, 0x4b, 0x9e, 0x5a, 0x9f, 0x5b, 0x5f, 0xe3, 0xe3, 0x1c, 0xf2, 0xd6, 0x87, 0x19, 0xff, 0x64, 0x2b, + 0x4c, 0xd8, 0x3b, 0xa2, 0x45, 0xb0, 0x63, 0xa3, 0x81, 0x9f, 0xde, 0x8b, 0xa3, 0x65, 0x09, 0xda, 0x3f, 0x80, 0x55, + 0x5d, 0x85, 0x9c, 0xc9, 0xf0, 0xf3, 0xa4, 0x91, 0x58, 0x24, 0xc5, 0x02, 0x38, 0xdf, 0xab, 0xd9, 0xef, 0xd5, 0xeb, + 0x93, 0xd5, 0x64, 0xc8, 0xa8, 0xb3, 0xa4, 0x2e, 0xd4, 0x9f, 0x5d, 0xdf, 0x36, 0x75, 0x1d, 0x9c, 0x88, 0xeb, 0x4f, + 0xd0, 0xb6, 0x75, 0xc7, 0xd0, 0x9c, 0xa0, 0xa6, 0x3c, 0x53, 0x1c, 0xeb, 0x4e, 0xbf, 0x19, 0x8f, 0x6c, 0x6e, 0x3e, + 0xda, 0x44, 0x36, 0x5e, 0x8c, 0xc4, 0x16, 0x5e, 0xe8, 0x05, 0xd0, 0xa2, 0xbe, 0xc7, 0x42, 0xfc, 0xe4, 0xe8, 0x19, + 0x4e, 0x60, 0x04, 0x72, 0x2d, 0x64, 0xa0, 0xa4, 0x27, 0x1a, 0xb6, 0x55, 0x73, 0x0e, 0x07, 0x2f, 0x3f, 0xb1, 0x2d, + 0x79, 0x44, 0x07, 0x75, 0x86, 0xfe, 0x4a, 0x3e, 0xdb, 0x4f, 0x15, 0xef, 0x30, 0xd5, 0xf6, 0xeb, 0x72, 0x9c, 0x35, + 0xd3, 0x79, 0xd7, 0x90, 0x85, 0xe8, 0xf9, 0x60, 0x7b, 0x86, 0xd4, 0xb1, 0x8a, 0x56, 0xcd, 0xe2, 0xf5, 0xf0, 0xee, + 0x91, 0x25, 0x66, 0xeb, 0x76, 0x67, 0x74, 0xd8, 0x41, 0x50, 0x43, 0x0c, 0xd6, 0x6d, 0x21, 0x91, 0x19, 0x25, 0xc7, + 0xba, 0x10, 0x1f, 0xc1, 0x0d, 0x41, 0x29, 0xf4, 0xb0, 0x97, 0xd2, 0x4a, 0x3f, 0xea, 0x22, 0x19, 0x26, 0x83, 0x47, + 0xb3, 0x5b, 0x36, 0xd7, 0x62, 0x17, 0x55, 0xfd, 0xb3, 0xec, 0xda, 0x15, 0xf4, 0xd1, 0x14, 0x75, 0x42, 0x0d, 0x22, + 0x90, 0xde, 0xca, 0xdf, 0xe2, 0xf8, 0x92, 0x6e, 0x5c, 0xbf, 0x1e, 0xde, 0x84, 0xcc, 0xf9, 0x00, 0x0e, 0x00, 0xd3, + 0xc9, 0xfb, 0x77, 0x0e, 0x25, 0x55, 0x85, 0x46, 0x5a, 0xdf, 0x91, 0x1b, 0x6c, 0xc7, 0xe4, 0x21, 0x3a, 0xbe, 0x76, + 0x33, 0x40, 0x80, 0x36, 0x16, 0xfa, 0x1c, 0x5a, 0x6f, 0x24, 0xad, 0x04, 0x4b, 0xa0, 0xb3, 0xfa, 0xa1, 0xa5, 0xf0, + 0xd2, 0x90, 0x98, 0xfa, 0x0d, 0x96, 0x45, 0xa2, 0x24, 0xe6, 0xcf, 0xc2, 0x2b, 0xdb, 0xaa, 0xf0, 0x30, 0xc6, 0x0a, + 0xd0, 0x86, 0x58, 0xfb, 0x15, 0xbb, 0x22, 0xb0, 0xf0, 0xde, 0x12, 0xc0, 0xbb, 0x66, 0x8e, 0x02, 0x01, 0xc7, 0x2b, + 0x1c, 0x44, 0x1a, 0x8c, 0x3f, 0x5b, 0x89, 0x23, 0x47, 0x9a, 0xd5, 0x47, 0xef, 0xdb, 0xfd, 0x69, 0x8a, 0x47, 0xea, + 0x1c, 0xb7, 0x9e, 0x64, 0x81, 0x3f, 0xec, 0x9e, 0x0b, 0x2f, 0xac, 0xc8, 0x5e, 0xf6, 0x77, 0xf7, 0x92, 0xc5, 0x4d, + 0x2f, 0xf1, 0x55, 0x2f, 0x93, 0xeb, 0x95, 0x43, 0x0d, 0x6a, 0x60, 0xf3, 0x7d, 0x8f, 0xaa, 0x82, 0xdc, 0x80, 0xbf, + 0x77, 0xf3, 0x11, 0xc6, 0xb5, 0x0b, 0x9c, 0xe3, 0x52, 0x3d, 0xcc, 0x45, 0xcc, 0xa8, 0xa4, 0x76, 0x94, 0x5c, 0x40, + 0xaa, 0x93, 0x94, 0x0b, 0x32, 0xac, 0x5c, 0xa0, 0xb7, 0xfa, 0x14, 0xaf, 0x9c, 0x2d, 0x4d, 0x82, 0x28, 0xea, 0xb9, + 0x7b, 0x85, 0x0a, 0xc1, 0x7f, 0x1d, 0xc8, 0x8c, 0x29, 0x2b, 0x30, 0x57, 0x13, 0xea, 0x30, 0x4b, 0x26, 0xbc, 0x3c, + 0x8a, 0xe1, 0xc5, 0x08, 0x32, 0x6d, 0xa9, 0x22, 0xaa, 0xdf, 0x43, 0xdf, 0xa4, 0x68, 0x56, 0xa3, 0x10, 0x73, 0x8e, + 0x25, 0x15, 0x5c, 0xaf, 0xea, 0x10, 0x7e, 0x44, 0xad, 0xee, 0x15, 0x8e, 0xeb, 0x9c, 0x31, 0xb9, 0xf3, 0xad, 0x07, + 0x9c, 0x9e, 0xc7, 0xe9, 0x01, 0xb9, 0x6d, 0x2a, 0xa2, 0xfa, 0x18, 0x0f, 0x43, 0x58, 0xab, 0x59, 0x66, 0x08, 0x99, + 0xb7, 0x0d, 0xc5, 0xaf, 0x84, 0x66, 0xf3, 0x67, 0x57, 0x43, 0xf2, 0x79, 0xf1, 0xc4, 0x8d, 0xeb, 0x54, 0xc5, 0x12, + 0x93, 0xbc, 0x08, 0x2b, 0xcc, 0xe1, 0xb2, 0x37, 0x63, 0xd1, 0xf9, 0xc9, 0x79, 0x08, 0x09, 0x58, 0x94, 0x8f, 0x68, + 0xed, 0x19, 0x50, 0x50, 0x2d, 0xc7, 0xa9, 0x5a, 0x03, 0xc6, 0xf6, 0x3c, 0x78, 0x4b, 0xf9, 0x2f, 0xdb, 0x03, 0xd4, + 0x93, 0xed, 0x9c, 0x62, 0x30, 0x86, 0xf0, 0x94, 0x6e, 0x03, 0x9c, 0x90, 0xca, 0x16, 0x0e, 0xaa, 0xf5, 0x37, 0x37, + 0x2f, 0xb4, 0x81, 0x12, 0x7f, 0x49, 0x91, 0xd6, 0x8a, 0x14, 0x8f, 0x30, 0x34, 0x05, 0x9f, 0xf1, 0xd8, 0x93, 0x78, + 0xcf, 0xdd, 0x97, 0x35, 0x22, 0x05, 0x71, 0x2e, 0xfc, 0x85, 0x08, 0x2b, 0x47, 0x88, 0x79, 0xca, 0x0d, 0x95, 0x64, + 0x5f, 0xda, 0xb3, 0xfa, 0x2a, 0x0b, 0x78, 0xea, 0xb2, 0x4f, 0xe1, 0x85, 0xc0, 0x1c, 0xae, 0x3d, 0x7a, 0x52, 0x3f, + 0x9a, 0x01, 0xab, 0x7a, 0x6e, 0x31, 0x8d, 0x50, 0x51, 0xb8, 0x84, 0x20, 0x6e, 0x29, 0x41, 0x84, 0x61, 0x66, 0x8d, + 0x87, 0x4f, 0x0c, 0xeb, 0x29, 0x0c, 0x00, 0xa6, 0xa4, 0xa1, 0x7b, 0x86, 0x32, 0x81, 0x7b, 0x69, 0x17, 0x28, 0xcf, + 0x5c, 0x65, 0x5e, 0x4e, 0xee, 0x31, 0x0c, 0x9c, 0xcc, 0xd6, 0x16, 0xd3, 0xc8, 0x88, 0xac, 0x03, 0x2d, 0xd4, 0x91, + 0xbf, 0x57, 0x2b, 0x2b, 0xbb, 0x6e, 0x02, 0xdd, 0x8b, 0x7a, 0x2f, 0xfd, 0x22, 0x42, 0xdc, 0x5e, 0xa5, 0xa7, 0x80, + 0x69, 0xf8, 0x14, 0xf7, 0x33, 0xa9, 0x10, 0x78, 0x15, 0xf4, 0x3c, 0x90, 0xc8, 0x1e, 0xe2, 0x0e, 0xea, 0x06, 0x00, + 0x92, 0x5b, 0xe2, 0x4a, 0x41, 0x5a, 0x1b, 0x52, 0x25, 0xeb, 0x3f, 0xb5, 0xd5, 0x28, 0x01, 0xc8, 0x47, 0xf6, 0xcd, + 0x91, 0xc6, 0x2b, 0x08, 0x2d, 0x5c, 0x48, 0x39, 0xcc, 0xe0, 0x51, 0x13, 0x74, 0x22, 0x33, 0xc1, 0xe6, 0x56, 0xb0, + 0x8d, 0x9f, 0xbc, 0x79, 0x1d, 0x89, 0x0a, 0xd3, 0x8f, 0xe2, 0xdf, 0xab, 0x3b, 0x6e, 0x8a, 0xb2, 0xe2, 0x21, 0xf7, + 0xfd, 0x1c, 0x3f, 0x37, 0x45, 0x49, 0x9a, 0x13, 0xbe, 0x54, 0x32, 0x9d, 0xb4, 0x17, 0x47, 0x6d, 0x8e, 0x96, 0x3d, + 0x00, 0x79, 0xc5, 0x4b, 0x60, 0xdd, 0x63, 0xe5, 0xbb, 0x96, 0x56, 0x99, 0xf9, 0x88, 0xaa, 0x2a, 0x2a, 0x24, 0x9a, + 0xe0, 0x22, 0xb3, 0x26, 0xb6, 0x71, 0x5a, 0x1c, 0x06, 0x90, 0x42, 0x63, 0x58, 0x31, 0xe4, 0xa1, 0xf9, 0xb1, 0x98, + 0x17, 0xe1, 0x89, 0x2c, 0xba, 0x2e, 0x28, 0xe5, 0x67, 0x48, 0x69, 0xa6, 0x8c, 0x6c, 0x8b, 0x65, 0x38, 0x9c, 0x01, + 0xc0, 0x5c, 0xeb, 0x88, 0xa8, 0x54, 0x98, 0xec, 0x98, 0x54, 0xc6, 0x5e, 0xc9, 0x9f, 0xa5, 0x84, 0x88, 0x08, 0xab, + 0xb3, 0x6d, 0x03, 0x62, 0x77, 0x0e, 0xea, 0x11, 0x9e, 0x2d, 0x33, 0xd8, 0xc4, 0xb2, 0x08, 0xce, 0x8a, 0xaa, 0xaa, + 0x46, 0xa3, 0xf9, 0xb0, 0x37, 0x34, 0xde, 0x64, 0xee, 0x0c, 0x85, 0xb0, 0x75, 0x3b, 0x42, 0x50, 0x6e, 0x3c, 0xdb, + 0x86, 0xd6, 0x86, 0x0f, 0x33, 0x37, 0xf5, 0x41, 0x5e, 0x2e, 0xa2, 0xaa, 0xd1, 0x66, 0xcf, 0x53, 0xca, 0xd3, 0x68, + 0xef, 0xa9, 0x3b, 0x29, 0x09, 0x95, 0xdd, 0x24, 0x2a, 0x0a, 0x6c, 0xe1, 0x59, 0x12, 0x12, 0x40, 0x71, 0xfb, 0xeb, + 0x50, 0x83, 0xfc, 0x8b, 0x91, 0x83, 0x03, 0x5f, 0xd5, 0x81, 0xb5, 0x2b, 0x20, 0xcd, 0xcf, 0x64, 0xd2, 0x5b, 0x7c, + 0xef, 0x6e, 0xe8, 0xc3, 0x47, 0x91, 0x22, 0xdc, 0x47, 0x68, 0x1d, 0x27, 0x21, 0x6e, 0x01, 0xf7, 0x9b, 0x6d, 0x2f, + 0x3e, 0x6a, 0x3a, 0x41, 0x66, 0x68, 0x5c, 0x1b, 0x2f, 0x9b, 0x56, 0xa4, 0x16, 0x28, 0x54, 0x20, 0x1f, 0xe9, 0x7e, + 0x2b, 0x01, 0x29, 0xc7, 0xa9, 0xdc, 0x76, 0xaf, 0x93, 0xf2, 0x1c, 0xee, 0x86, 0x8a, 0xe8, 0x75, 0x3d, 0xda, 0x12, + 0xd0, 0x62, 0x4e, 0x06, 0x7e, 0x3a, 0x5a, 0x45, 0xbe, 0x9c, 0x38, 0xc5, 0x39, 0x55, 0x2d, 0xd6, 0x3c, 0xf8, 0x78, + 0x97, 0x07, 0xc2, 0xfe, 0x92, 0x8c, 0x93, 0x31, 0x00, 0x59, 0xc5, 0x02, 0x73, 0xe0, 0x40, 0xed, 0x36, 0x27, 0x6a, + 0x03, 0x0e, 0xd4, 0xea, 0xce, 0x9e, 0xa6, 0x32, 0xd9, 0xa7, 0x94, 0xe3, 0x57, 0xf8, 0x82, 0xa5, 0xac, 0x46, 0xda, + 0x8a, 0x6a, 0x79, 0xae, 0xa5, 0x05, 0x50, 0x4b, 0x65, 0xa9, 0x6c, 0x29, 0xa4, 0x18, 0xdf, 0xec, 0xf1, 0x31, 0x12, + 0xba, 0x52, 0x3c, 0x4f, 0x2e, 0x03, 0xed, 0xf2, 0x37, 0x9e, 0xc2, 0x74, 0xc6, 0x04, 0xa6, 0xa9, 0x89, 0x2b, 0xb2, + 0x79, 0xff, 0xfe, 0xda, 0xa9, 0xb6, 0xec, 0x48, 0xaa, 0x40, 0xda, 0x2c, 0x76, 0x74, 0x69, 0x4c, 0x81, 0xe0, 0xaa, + 0xa1, 0xdb, 0xe2, 0x68, 0x77, 0xfe, 0xe1, 0xce, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0xc7, 0xa5, 0x10, 0x50, + 0xa3, 0xbe, 0x10, 0x4e, 0xa4, 0xfe, 0xc8, 0x90, 0x4b, 0x17, 0xb3, 0x43, 0x6b, 0x54, 0xd7, 0x2d, 0x00, 0x2d, 0x7d, + 0x0f, 0x23, 0x43, 0x21, 0x6c, 0xc4, 0xb0, 0xcf, 0x53, 0xea, 0xe3, 0xca, 0x49, 0x17, 0x5d, 0x62, 0x29, 0x64, 0xde, + 0xc7, 0x24, 0x6f, 0x92, 0x46, 0x89, 0xc8, 0xeb, 0x2c, 0xe5, 0xa4, 0x2e, 0x4e, 0xe2, 0x28, 0x6f, 0x29, 0x64, 0x20, + 0xd5, 0x4d, 0x2a, 0xdd, 0x96, 0x4b, 0x25, 0xf4, 0x58, 0xf6, 0xb7, 0xe4, 0x06, 0xaf, 0xfb, 0x72, 0x1c, 0xfc, 0x31, + 0xf2, 0xcf, 0x13, 0x5b, 0x2c, 0x45, 0x07, 0xd0, 0x83, 0x20, 0xa5, 0x35, 0x40, 0xc2, 0xcf, 0xeb, 0x5b, 0xdf, 0x09, + 0xbe, 0x76, 0x04, 0xb4, 0x42, 0xb0, 0x72, 0xbd, 0x0a, 0x35, 0xdd, 0x5e, 0x36, 0x56, 0x65, 0x54, 0x75, 0xb0, 0x83, + 0x68, 0x89, 0x24, 0x04, 0xf8, 0x9c, 0xbc, 0x43, 0xea, 0x87, 0x9a, 0x74, 0xeb, 0x4b, 0xbe, 0x88, 0xd6, 0xb5, 0x92, + 0x67, 0x04, 0x57, 0xdf, 0xa8, 0xc9, 0xc2, 0xad, 0xe3, 0x27, 0x51, 0xd7, 0x4e, 0xd5, 0x15, 0x31, 0x07, 0x04, 0x98, + 0xaa, 0x86, 0x11, 0x75, 0x9f, 0x24, 0xc9, 0xbf, 0xc4, 0x54, 0x80, 0x0a, 0x96, 0x49, 0xbd, 0xfa, 0xbf, 0x6f, 0xb5, + 0xee, 0x7f, 0xbc, 0xc1, 0xba, 0x9a, 0xe7, 0xb7, 0x77, 0x7a, 0x00, 0x30, 0x80, 0x1f, 0x83, 0xaa, 0x0e, 0x5e, 0x6e, + 0xc7, 0x0b, 0xbb, 0x32, 0x05, 0xa9, 0x09, 0xf8, 0xac, 0x92, 0xfe, 0xcf, 0x91, 0x06, 0x82, 0xe6, 0x6b, 0x64, 0x6d, + 0x6c, 0x46, 0x24, 0x72, 0xdf, 0x65, 0x83, 0x8f, 0x57, 0xe1, 0xd9, 0x11, 0xf8, 0x65, 0x6c, 0x9d, 0xd3, 0x31, 0xcb, + 0x07, 0x09, 0x2c, 0x17, 0x6a, 0xbf, 0x7a, 0xcc, 0xf9, 0x44, 0x88, 0x53, 0x54, 0xa8, 0x27, 0xa8, 0x08, 0x32, 0x81, + 0x62, 0x91, 0x96, 0xa8, 0xe3, 0x2a, 0xce, 0x11, 0x16, 0x10, 0x5a, 0xa7, 0x44, 0x44, 0xbc, 0x1d, 0xd0, 0x11, 0xbc, + 0xad, 0x21, 0x27, 0xee, 0x38, 0x37, 0x6b, 0x1b, 0x98, 0xcb, 0x20, 0xd5, 0xa0, 0xe9, 0xee, 0x0b, 0x6c, 0xc0, 0x43, + 0x9c, 0x37, 0x8e, 0x4f, 0xe2, 0x72, 0x8b, 0x2c, 0x72, 0x0e, 0x45, 0x5d, 0x5e, 0xd4, 0xc8, 0xc4, 0x24, 0xa1, 0x0e, + 0x4f, 0x21, 0xa4, 0xdb, 0x17, 0x30, 0x98, 0x16, 0x4c, 0xe3, 0xac, 0x4e, 0x12, 0xc0, 0x2d, 0x9f, 0xde, 0x0f, 0xc3, + 0x97, 0x1e, 0x6a, 0x07, 0xd1, 0xb9, 0x88, 0xf8, 0x4d, 0xdb, 0xd4, 0x28, 0x4c, 0x1e, 0xae, 0xad, 0xef, 0xa9, 0xe1, + 0x23, 0x24, 0xe1, 0x5f, 0xc3, 0xa2, 0x08, 0x48, 0xdc, 0xa6, 0xb7, 0x5c, 0x30, 0xe9, 0x9d, 0x66, 0x21, 0xb4, 0xd9, + 0x0c, 0x52, 0xa5, 0x6a, 0x3e, 0xc0, 0xca, 0xb4, 0xd3, 0xff, 0xe4, 0xe4, 0xb6, 0x24, 0x05, 0x41, 0xb4, 0xd2, 0xef, + 0x4c, 0x99, 0xb0, 0xc6, 0x98, 0x40, 0xde, 0x15, 0x25, 0x9c, 0x67, 0xd0, 0x49, 0x2c, 0x00, 0x3b, 0x5a, 0x7f, 0x2f, + 0xff, 0x0e, 0x8b, 0xd1, 0xa9, 0xd1, 0x9b, 0x4e, 0x92, 0xa9, 0xd6, 0x7f, 0x7b, 0x00, 0x7f, 0x9c, 0x81, 0xb5, 0x3e, + 0x77, 0x81, 0xb5, 0xdb, 0x4d, 0x12, 0x52, 0xba, 0x25, 0xaf, 0xaa, 0xaf, 0x62, 0xdd, 0xa4, 0x54, 0xee, 0x67, 0xbf, + 0xbf, 0xbd, 0xd8, 0x32, 0x82, 0xc3, 0x3a, 0xa7, 0x18, 0x58, 0x80, 0x0d, 0x73, 0x19, 0x6e, 0x56, 0x3b, 0x81, 0xa0, + 0xa4, 0x97, 0xe4, 0xc3, 0x36, 0x43, 0xb2, 0xe3, 0x53, 0x2d, 0x91, 0xd0, 0x33, 0x9e, 0xf6, 0x35, 0x80, 0xc0, 0xbb, + 0x73, 0x93, 0xd2, 0x7a, 0xf3, 0x19, 0x79, 0xaf, 0x4a, 0x14, 0x91, 0x61, 0x4a, 0x8c, 0x67, 0x4e, 0x08, 0xd2, 0x7e, + 0xcd, 0x60, 0x6b, 0xbf, 0x19, 0x3c, 0x8d, 0x9b, 0x87, 0xe6, 0x88, 0x20, 0x72, 0x31, 0x7d, 0x90, 0xc2, 0x9f, 0x25, + 0xe3, 0xf2, 0x85, 0xcf, 0x6c, 0xc3, 0x75, 0x5a, 0x49, 0x80, 0x73, 0x8a, 0xbb, 0x79, 0xca, 0x33, 0xb1, 0x58, 0x9e, + 0xbc, 0x7c, 0xb5, 0xac, 0xd2, 0x14, 0x38, 0x83, 0x0f, 0x71, 0x19, 0xa9, 0x34, 0xc8, 0x94, 0x14, 0x3f, 0x9e, 0x27, + 0x93, 0x6e, 0x6f, 0x6a, 0x95, 0xb0, 0xab, 0x06, 0x87, 0xea, 0x13, 0x2a, 0x4b, 0x4f, 0xdb, 0x52, 0x0b, 0xcc, 0x63, + 0x1f, 0x04, 0x98, 0x7c, 0x93, 0x7d, 0xcc, 0xda, 0x11, 0x74, 0x0f, 0x4a, 0xe5, 0x32, 0x1e, 0x06, 0xb8, 0xa9, 0x82, + 0x00, 0xd2, 0xc7, 0x7a, 0x0a, 0x73, 0x79, 0x8f, 0x89, 0x0e, 0x8b, 0x1e, 0x46, 0xa0, 0x2e, 0xd4, 0xc2, 0x08, 0xcc, + 0x90, 0x07, 0x53, 0xb1, 0x74, 0xe2, 0x4f, 0x37, 0xd8, 0xfa, 0xdc, 0x8f, 0x73, 0x4d, 0xbb, 0x63, 0x96, 0x06, 0x48, + 0xaa, 0xa3, 0xee, 0x37, 0xfa, 0x46, 0x3d, 0x9e, 0x75, 0x8b, 0xf7, 0x69, 0x33, 0xa6, 0xbd, 0xa9, 0x3c, 0x1e, 0x55, + 0xdb, 0xef, 0xdf, 0x16, 0x97, 0xa8, 0x96, 0x92, 0xa5, 0x3d, 0xc8, 0xbe, 0x3b, 0xa3, 0x00, 0xb7, 0xef, 0x78, 0x13, + 0x1e, 0x20, 0xcf, 0x91, 0x4e, 0xcc, 0x6d, 0xd8, 0x53, 0x9d, 0x03, 0xed, 0xfc, 0xe7, 0x47, 0xa9, 0xb0, 0xf3, 0xf7, + 0xa7, 0x61, 0xe9, 0x3d, 0x49, 0x18, 0x05, 0x8e, 0xd2, 0xef, 0xde, 0x77, 0x59, 0xad, 0xf4, 0x71, 0x81, 0xcb, 0x9d, + 0xd7, 0x56, 0x9c, 0x78, 0xb1, 0x61, 0x3d, 0x25, 0x8f, 0x63, 0x14, 0x63, 0x6f, 0x7a, 0xb2, 0xee, 0x8c, 0xdd, 0x3d, + 0x85, 0xb5, 0x67, 0x3d, 0x25, 0x48, 0xb7, 0x92, 0x1f, 0xf7, 0xfe, 0x23, 0xb6, 0x53, 0x25, 0xdd, 0xf4, 0x07, 0xdb, + 0x2f, 0x3f, 0x3a, 0x3b, 0x88, 0x07, 0xad, 0xb3, 0x32, 0x9d, 0xa5, 0xeb, 0x2a, 0xe9, 0x72, 0xb8, 0x40, 0xde, 0xcd, + 0xc4, 0x73, 0x61, 0xae, 0xbf, 0xce, 0x36, 0x42, 0x05, 0xf6, 0xe5, 0x6a, 0xbc, 0xbd, 0x47, 0xcc, 0xe7, 0x72, 0x2e, + 0xfb, 0xde, 0xa2, 0x29, 0x04, 0x7d, 0x8b, 0x91, 0x72, 0xc1, 0x38, 0x4e, 0x90, 0x0f, 0xb8, 0x34, 0xde, 0x07, 0xb4, + 0x18, 0xa3, 0x5b, 0xf8, 0x79, 0x0c, 0xdb, 0x03, 0x6c, 0xcd, 0xfc, 0x73, 0xc2, 0x63, 0x5e, 0x88, 0x30, 0x4d, 0x1e, + 0x50, 0x53, 0xb2, 0x81, 0x0f, 0x36, 0x9c, 0x9f, 0x15, 0x12, 0xc3, 0x00, 0xcb, 0x23, 0x4f, 0xa7, 0x8d, 0xec, 0x69, + 0xa8, 0x2e, 0xcf, 0x73, 0xb5, 0xde, 0x82, 0x9e, 0x30, 0x9d, 0xe5, 0x65, 0x1a, 0xee, 0xd2, 0x3b, 0x13, 0xec, 0x70, + 0xb9, 0x6b, 0x38, 0x69, 0x99, 0x22, 0x55, 0x8e, 0xf3, 0xc6, 0x71, 0x9a, 0x33, 0x06, 0xe2, 0x29, 0xe6, 0xf5, 0xeb, + 0x54, 0x60, 0xd1, 0x62, 0x5c, 0xbe, 0x40, 0x69, 0x60, 0xea, 0x2f, 0x36, 0x32, 0x53, 0xa1, 0x75, 0x00, 0x31, 0x59, + 0x82, 0x3f, 0x1b, 0xa4, 0xb4, 0xa0, 0x10, 0x8d, 0x0a, 0xb7, 0xd5, 0x3f, 0xdc, 0x15, 0xb5, 0x4a, 0x13, 0xd1, 0xee, + 0x5d, 0xf1, 0xce, 0x10, 0xdb, 0xc5, 0x5b, 0x4e, 0x07, 0x50, 0x8c, 0x1a, 0x1d, 0xd0, 0xa4, 0x60, 0x7b, 0xb4, 0xfe, + 0x26, 0x29, 0xe5, 0x79, 0x66, 0x44, 0xf6, 0x58, 0xc0, 0xfa, 0x6e, 0x70, 0x18, 0x5b, 0x5b, 0x55, 0x58, 0xef, 0x9b, + 0x36, 0xc1, 0x1c, 0x80, 0xfd, 0x96, 0x44, 0xf1, 0xde, 0x27, 0x7f, 0x49, 0x8c, 0xd1, 0xf5, 0x3d, 0x17, 0x59, 0x7a, + 0x63, 0x28, 0x26, 0x48, 0xae, 0x69, 0x56, 0xc9, 0xe2, 0x18, 0x8d, 0x46, 0x41, 0xc9, 0x39, 0x31, 0x8e, 0x50, 0x36, + 0x40, 0x3d, 0x4d, 0x49, 0xe9, 0x02, 0x40, 0x66, 0x58, 0x4d, 0x0f, 0x0a, 0x60, 0x19, 0x8d, 0xb4, 0x40, 0xe5, 0x59, + 0x74, 0x14, 0xee, 0x79, 0x72, 0x9a, 0x6b, 0x66, 0xd5, 0xe0, 0xf0, 0x96, 0x07, 0x8a, 0xca, 0x79, 0x7a, 0x36, 0x99, + 0x8f, 0xe8, 0x20, 0xd2, 0x6b, 0x1a, 0xff, 0xb6, 0xaf, 0x44, 0x74, 0x70, 0x1b, 0x09, 0x16, 0x9c, 0xfd, 0x90, 0x93, + 0x21, 0x72, 0x7f, 0xb5, 0xce, 0xf4, 0x83, 0x0a, 0xfd, 0x6e, 0x35, 0x84, 0x48, 0xf9, 0x4a, 0xd8, 0xd8, 0x94, 0x3b, + 0x35, 0xe8, 0xbc, 0xd3, 0x30, 0x91, 0xa1, 0x70, 0x7c, 0xcf, 0x6d, 0xe9, 0x13, 0x6d, 0x56, 0x37, 0xce, 0xfc, 0xe3, + 0x01, 0x3f, 0x59, 0x9a, 0x22, 0x68, 0x4d, 0xa5, 0x4e, 0x07, 0xe8, 0x96, 0x48, 0x83, 0xa3, 0x7c, 0x60, 0x5e, 0x78, + 0xd0, 0x52, 0xbb, 0xa1, 0x44, 0x57, 0x74, 0x14, 0xee, 0x91, 0xe7, 0x02, 0x1a, 0x67, 0x0a, 0xba, 0x1e, 0x71, 0x54, + 0x3b, 0x63, 0x28, 0xc5, 0x1c, 0x0c, 0xe6, 0x50, 0xd6, 0x64, 0x8d, 0x7d, 0x6c, 0xbd, 0x44, 0x77, 0xe3, 0x19, 0x22, + 0xd7, 0x13, 0x1a, 0x87, 0xa4, 0xeb, 0x99, 0x91, 0xc2, 0x30, 0x84, 0x77, 0x40, 0xf2, 0xee, 0xc4, 0xfa, 0x5c, 0xa9, + 0xa4, 0x1d, 0x69, 0x63, 0x60, 0x17, 0xcf, 0x62, 0xb6, 0xb0, 0x22, 0x3b, 0x71, 0x6d, 0xbd, 0xb6, 0x76, 0xfd, 0x15, + 0xa2, 0xc2, 0x78, 0x6c, 0xeb, 0x70, 0x9e, 0x33, 0x72, 0xc5, 0x0d, 0x13, 0x3f, 0xcb, 0xae, 0xcf, 0x3c, 0x95, 0xf4, + 0x5f, 0x84, 0xd6, 0x4f, 0x5d, 0x71, 0x81, 0x75, 0xb7, 0x4d, 0xec, 0xfa, 0x75, 0x4a, 0x6a, 0x5d, 0xb9, 0x0b, 0xfd, + 0x8f, 0xad, 0xed, 0x58, 0x6d, 0xe6, 0x69, 0xde, 0x7f, 0xe8, 0x44, 0x1d, 0xe4, 0x9f, 0x7e, 0xb5, 0x1b, 0xb9, 0x91, + 0x16, 0x2f, 0xc9, 0xc7, 0xbb, 0x9e, 0xe6, 0x0b, 0x1e, 0xfb, 0xf3, 0x66, 0xd8, 0xf3, 0x32, 0xbf, 0x16, 0xec, 0xcf, + 0xd3, 0xd9, 0x67, 0x8e, 0x1e, 0xdf, 0x1f, 0xd2, 0xc4, 0xa3, 0xe9, 0xf3, 0xe4, 0xcf, 0xe4, 0x5c, 0x24, 0x8f, 0xc9, + 0x5e, 0xf5, 0xb6, 0xed, 0x22, 0xa5, 0x11, 0xa0, 0x8e, 0xde, 0xac, 0xdf, 0x85, 0x74, 0x4d, 0x32, 0x15, 0x0f, 0xca, + 0xa7, 0x7c, 0x20, 0xbe, 0xae, 0xbf, 0x4c, 0xf7, 0x50, 0x88, 0x78, 0x11, 0xf8, 0xef, 0xf9, 0xfe, 0x23, 0xb6, 0x59, + 0x57, 0x5a, 0x9d, 0xcd, 0x8d, 0x1e, 0xba, 0x7d, 0x75, 0x32, 0xf5, 0x89, 0x94, 0x51, 0x7a, 0x5d, 0x88, 0x97, 0x18, + 0x17, 0x37, 0xf9, 0x21, 0xdb, 0x7e, 0x18, 0x9f, 0xd7, 0xf8, 0x81, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0x3e, 0x40, + 0x4d, 0xe5, 0x54, 0xb0, 0x62, 0x5a, 0xa9, 0x4a, 0x03, 0xa0, 0x69, 0xf4, 0x4b, 0x94, 0x7f, 0xa6, 0x07, 0xf2, 0xc3, + 0x1f, 0xbd, 0x75, 0xde, 0x3f, 0xa7, 0xff, 0xbe, 0xff, 0xfc, 0xa3, 0x06, 0x26, 0x05, 0x64, 0xdd, 0x87, 0x95, 0x6d, + 0x12, 0x8e, 0xca, 0xc6, 0x55, 0x56, 0x13, 0x75, 0x07, 0x99, 0x5e, 0xcd, 0x6c, 0xf7, 0xcd, 0x5b, 0xf6, 0xa1, 0x17, + 0xd1, 0x4c, 0xc9, 0xa3, 0x52, 0xe4, 0x1d, 0x72, 0x71, 0xf5, 0x39, 0x7c, 0x19, 0xeb, 0xaa, 0x90, 0x5f, 0xa9, 0x8a, + 0xe7, 0xa5, 0x0f, 0x82, 0xa8, 0x73, 0x72, 0x0c, 0x12, 0xc7, 0x91, 0x07, 0x14, 0xd8, 0x9f, 0xeb, 0x39, 0x74, 0xcf, + 0xeb, 0xcb, 0x09, 0x3c, 0x0d, 0x97, 0xb0, 0x5d, 0xef, 0xbc, 0x4b, 0x1f, 0x6a, 0x32, 0x4a, 0xb0, 0x8d, 0x74, 0x73, + 0xe8, 0xa0, 0x51, 0x3b, 0x7a, 0xe4, 0xe3, 0x9e, 0xf1, 0xd1, 0x05, 0x8a, 0xbe, 0xc7, 0xb9, 0xd1, 0x33, 0x57, 0x0e, + 0xfa, 0x5c, 0xae, 0xbb, 0xa6, 0xbd, 0xaa, 0x13, 0xa3, 0x63, 0x52, 0x79, 0x29, 0x0a, 0x20, 0x49, 0xaa, 0xa7, 0x2d, + 0x52, 0xfb, 0xa9, 0x9c, 0x0d, 0x6c, 0x9e, 0xe1, 0x5e, 0x3c, 0x13, 0x4a, 0x42, 0x37, 0xfc, 0xc5, 0xb9, 0xa6, 0x7d, + 0x61, 0x99, 0xaa, 0x30, 0xb8, 0x61, 0x35, 0x2d, 0x21, 0xe8, 0x35, 0x08, 0x36, 0x0d, 0xee, 0x3f, 0x8e, 0x20, 0xd8, + 0x04, 0x5a, 0x3b, 0x83, 0x94, 0x81, 0x33, 0x36, 0xe2, 0x1f, 0xae, 0x68, 0x10, 0xc9, 0xcd, 0x03, 0x4f, 0xe2, 0xe5, + 0xb0, 0x24, 0x52, 0xde, 0x40, 0x28, 0x08, 0x7a, 0x2a, 0xb8, 0x08, 0x52, 0xd0, 0x98, 0xf6, 0x98, 0x1d, 0xa8, 0x36, + 0x38, 0x6e, 0x80, 0xcb, 0x57, 0x49, 0xd9, 0xa4, 0xda, 0xd4, 0x65, 0xaa, 0x62, 0xc7, 0xe0, 0x91, 0x97, 0xd6, 0x41, + 0x7a, 0x81, 0x22, 0x68, 0x8a, 0x52, 0xa4, 0x57, 0x35, 0x1d, 0x85, 0xb6, 0xa8, 0x36, 0x18, 0x3d, 0xa8, 0x18, 0x28, + 0xa9, 0xb0, 0xd8, 0xc8, 0x46, 0xd1, 0x9f, 0x19, 0x22, 0x8c, 0xc2, 0x0f, 0xed, 0xca, 0xc8, 0x87, 0x8f, 0x6a, 0x98, + 0xbd, 0x9b, 0x44, 0xb1, 0xc8, 0x4b, 0x7d, 0x5e, 0xf3, 0x88, 0x9a, 0x9d, 0x26, 0xf9, 0xfc, 0x66, 0x35, 0x70, 0x8a, + 0x49, 0xc9, 0x4e, 0x78, 0xb7, 0x4a, 0x4c, 0x82, 0x88, 0xad, 0xdf, 0x3e, 0xf5, 0xbc, 0x1b, 0xb8, 0xb4, 0xf7, 0x23, + 0x61, 0x7b, 0x59, 0xf2, 0xe8, 0xf0, 0xb2, 0xa8, 0xb9, 0xf9, 0xc6, 0x9c, 0xea, 0x2a, 0xd5, 0x1b, 0x02, 0x7e, 0x95, + 0x8e, 0x5e, 0x94, 0x09, 0x0a, 0xa7, 0x36, 0xdd, 0x07, 0x93, 0x11, 0xd0, 0xd1, 0xb3, 0x1a, 0xcd, 0xf2, 0xf4, 0xd5, + 0x32, 0xb1, 0xc3, 0xc6, 0xe8, 0x23, 0x0a, 0xbc, 0x6c, 0x55, 0x06, 0x47, 0x1a, 0x55, 0xca, 0xcc, 0x0b, 0xa2, 0xea, + 0x44, 0xad, 0x60, 0x2f, 0x35, 0xf8, 0x0f, 0x08, 0xd3, 0x25, 0x0f, 0x9c, 0x1a, 0x80, 0x1c, 0xb3, 0x88, 0x74, 0x54, + 0x80, 0xdf, 0x3e, 0x4d, 0xcf, 0x98, 0x6b, 0xb8, 0xcb, 0x1a, 0x44, 0x11, 0x6d, 0x1f, 0xb1, 0x44, 0xd2, 0x1d, 0x2e, + 0x8c, 0x29, 0x42, 0xb8, 0x39, 0x2a, 0x04, 0x01, 0xac, 0x30, 0xf8, 0x12, 0xe3, 0x80, 0xb4, 0xa8, 0x7b, 0x14, 0x5e, + 0xb6, 0x0a, 0xbe, 0xcb, 0x05, 0xc7, 0x58, 0xd9, 0xbb, 0x90, 0x58, 0x17, 0xa2, 0x41, 0xb7, 0xfc, 0x7b, 0x84, 0xfc, + 0x6a, 0x68, 0x66, 0xb5, 0xf9, 0x0a, 0xee, 0x5b, 0xaf, 0x9d, 0x4d, 0x26, 0x30, 0xbb, 0x12, 0x55, 0x21, 0x8b, 0x90, + 0xb2, 0x17, 0x22, 0xd3, 0xb4, 0x95, 0x28, 0x39, 0x47, 0x40, 0x12, 0xd8, 0x02, 0x01, 0x36, 0xf8, 0xa1, 0x5a, 0x96, + 0x43, 0x09, 0x55, 0x0d, 0x8c, 0x90, 0xef, 0xc5, 0x02, 0x88, 0x5a, 0x56, 0xbd, 0xa2, 0x0c, 0xec, 0x68, 0xd9, 0xeb, + 0xac, 0x67, 0x40, 0xc9, 0x7e, 0x83, 0x40, 0x78, 0x1b, 0x9e, 0xbe, 0xff, 0x26, 0xe4, 0xd1, 0x99, 0x63, 0x4d, 0x58, + 0x78, 0x44, 0x6e, 0x1c, 0x60, 0xe5, 0x73, 0x5b, 0x82, 0x90, 0x05, 0xa5, 0xdf, 0x95, 0x2b, 0x7b, 0xd4, 0x67, 0xa6, + 0x46, 0x15, 0x82, 0xbc, 0xb9, 0xec, 0x03, 0x69, 0xa9, 0x03, 0xed, 0x1f, 0x90, 0x81, 0xc1, 0x09, 0xdc, 0x3b, 0x55, + 0x84, 0xb2, 0xc7, 0x18, 0xfe, 0xdc, 0xa6, 0xa6, 0x4d, 0xdc, 0xf3, 0x33, 0x98, 0x14, 0x03, 0x92, 0x95, 0x92, 0x7b, + 0x9e, 0xff, 0xae, 0x86, 0x2a, 0x48, 0x28, 0x4c, 0x4b, 0xf0, 0x24, 0x2b, 0x23, 0x84, 0xc8, 0x44, 0xc7, 0x41, 0xe7, + 0x40, 0xbc, 0xba, 0x37, 0x30, 0x9f, 0xd9, 0x31, 0x4b, 0x7e, 0xf7, 0x68, 0xb9, 0x4e, 0xc4, 0xb2, 0x86, 0x1f, 0x46, + 0xb3, 0x1b, 0xfb, 0x89, 0x70, 0xdd, 0xc2, 0x1a, 0x97, 0x06, 0xcf, 0xd0, 0xad, 0xf6, 0xf8, 0x4d, 0xce, 0x50, 0x4c, + 0xdb, 0x74, 0xac, 0x0e, 0xaf, 0xaf, 0xd5, 0xac, 0xb2, 0x85, 0x6a, 0xb7, 0x9c, 0x5f, 0xab, 0x6a, 0xcd, 0xd6, 0x6e, + 0xa1, 0x95, 0xd5, 0xe7, 0x3f, 0x8b, 0xf9, 0x9c, 0xc2, 0x62, 0x7e, 0x30, 0x80, 0xbb, 0x28, 0xe2, 0xc5, 0x89, 0xbb, + 0xe6, 0xda, 0xfe, 0xa0, 0xf6, 0xca, 0xe5, 0xe3, 0x6b, 0x8f, 0xfb, 0xef, 0x22, 0x46, 0xbd, 0xb0, 0x8f, 0x02, 0xb8, + 0x56, 0x23, 0x1e, 0x0f, 0x1f, 0x5d, 0xcc, 0xab, 0x35, 0xf5, 0x49, 0x1d, 0x79, 0xcf, 0x5d, 0xef, 0x5b, 0x5a, 0xb2, + 0x38, 0xad, 0x3c, 0xcd, 0x3e, 0x10, 0x23, 0xb3, 0x81, 0xd6, 0x9b, 0x34, 0x43, 0x86, 0x3b, 0x12, 0x7c, 0xb2, 0x52, + 0xf4, 0xe2, 0x64, 0xf7, 0xd4, 0x20, 0x52, 0xb2, 0xd1, 0xcc, 0x42, 0xa0, 0x96, 0x97, 0x21, 0xd3, 0x74, 0x2c, 0x0a, + 0x51, 0x0e, 0x2c, 0x28, 0x0f, 0x9a, 0x30, 0xc5, 0x93, 0x70, 0x1a, 0x47, 0x92, 0x62, 0x35, 0x0d, 0xb9, 0xcd, 0x49, + 0x89, 0x1a, 0xd2, 0xd5, 0xb9, 0xc1, 0x03, 0xad, 0x16, 0x98, 0xc0, 0xa1, 0x24, 0x05, 0x98, 0x6b, 0xa4, 0x67, 0x88, + 0x28, 0x04, 0x03, 0xf4, 0xfa, 0x96, 0x9d, 0x87, 0xce, 0xbb, 0x93, 0x72, 0x59, 0x53, 0x10, 0x6f, 0x3e, 0xf6, 0xa1, + 0x65, 0xa6, 0x75, 0x27, 0x37, 0x54, 0xf2, 0x7c, 0x09, 0xb5, 0x34, 0x81, 0xfb, 0x84, 0x8b, 0x6a, 0x26, 0x54, 0x21, + 0xff, 0x26, 0xf7, 0xfd, 0x62, 0xef, 0xc2, 0xbc, 0xba, 0x7d, 0x80, 0xcf, 0x8f, 0x97, 0x2a, 0x47, 0xe1, 0x93, 0x91, + 0xdc, 0x6a, 0x25, 0x9f, 0x67, 0x10, 0x32, 0xf3, 0x85, 0x9b, 0xbb, 0x1f, 0xb5, 0xe9, 0xc3, 0x26, 0x7f, 0xd6, 0x81, + 0xe5, 0xb6, 0x79, 0x25, 0x26, 0x7f, 0xac, 0x76, 0x2c, 0xda, 0x7b, 0x77, 0x85, 0x3e, 0x8a, 0xf5, 0xe9, 0x84, 0xbb, + 0x7f, 0xa8, 0x7c, 0x5e, 0x36, 0xfa, 0x48, 0x5d, 0xae, 0x8f, 0x7f, 0x85, 0xee, 0x8b, 0x84, 0x6a, 0x58, 0xe3, 0xbd, + 0x4c, 0xb9, 0x30, 0x7b, 0x81, 0x8d, 0xb9, 0x3a, 0xed, 0x66, 0x52, 0x82, 0x6e, 0xdb, 0xfb, 0x8f, 0xfc, 0x08, 0x67, + 0x11, 0x05, 0x37, 0xf9, 0x9d, 0x19, 0xcb, 0xa1, 0x3f, 0xdf, 0x99, 0x41, 0x2f, 0x1f, 0xc2, 0xde, 0xc5, 0xbb, 0xf4, + 0x01, 0xb9, 0x1e, 0xa7, 0x4a, 0x3e, 0xfb, 0xb1, 0xfe, 0x56, 0xc9, 0x3f, 0x8b, 0x84, 0x79, 0x6b, 0x62, 0x85, 0xb9, + 0x31, 0x49, 0x7e, 0xfb, 0xeb, 0xb6, 0xa5, 0x9d, 0xc9, 0xed, 0x62, 0xd3, 0xba, 0x85, 0x67, 0x42, 0x36, 0x81, 0x89, + 0xd9, 0x2f, 0x52, 0xd0, 0x95, 0x32, 0x35, 0x6e, 0x92, 0xd2, 0xca, 0xb3, 0xce, 0xdb, 0x77, 0xcc, 0x1c, 0xd7, 0xa7, + 0x2a, 0x0b, 0x72, 0xab, 0x28, 0xe4, 0x14, 0xda, 0x63, 0xe4, 0x12, 0x3a, 0x4c, 0x97, 0xdc, 0x45, 0xcc, 0x65, 0x11, + 0xd3, 0x7b, 0x79, 0xee, 0x93, 0x10, 0xd3, 0x66, 0x3b, 0xe5, 0x95, 0xfc, 0x0f, 0xb9, 0x79, 0x90, 0x55, 0x41, 0x1d, + 0x80, 0xe9, 0xfd, 0xd5, 0xfa, 0xf3, 0xd9, 0xd2, 0xe0, 0x54, 0x71, 0xf0, 0xf2, 0x53, 0x69, 0x72, 0xf3, 0xc6, 0x39, + 0xdd, 0x10, 0x95, 0x4a, 0x39, 0x16, 0x83, 0x8e, 0x91, 0xa3, 0x6a, 0x34, 0x8b, 0xf9, 0x04, 0x75, 0xed, 0x24, 0xfe, + 0x78, 0x26, 0x67, 0x35, 0x54, 0x73, 0x17, 0x7c, 0x72, 0x6c, 0x79, 0x37, 0x0d, 0xc5, 0x70, 0x7f, 0xb7, 0x55, 0x3f, + 0x67, 0x74, 0xd6, 0x4d, 0x0f, 0x05, 0x37, 0x70, 0xbe, 0xeb, 0xe1, 0x4b, 0x69, 0xdd, 0xaa, 0x59, 0x2a, 0x51, 0x10, + 0xaa, 0xa4, 0xb9, 0x7a, 0xc3, 0xd4, 0x40, 0x1f, 0x6a, 0xfe, 0x8e, 0x32, 0x98, 0xe2, 0x12, 0x00, 0x35, 0xc9, 0xe1, + 0xdb, 0xd4, 0x42, 0xc9, 0x48, 0x6f, 0x05, 0xe6, 0x18, 0xff, 0x1b, 0x48, 0x43, 0x26, 0x03, 0x6e, 0xf5, 0x35, 0xbf, + 0x99, 0xe4, 0xdf, 0x74, 0xdf, 0x07, 0xe7, 0xd3, 0x38, 0x7d, 0x0d, 0x05, 0xf6, 0x41, 0x7b, 0x9f, 0xf6, 0x9c, 0x29, + 0x69, 0x7b, 0x5c, 0x6d, 0xc5, 0x57, 0xdc, 0x4d, 0x61, 0xf0, 0x4f, 0x0f, 0x84, 0x22, 0xfa, 0x6e, 0xe0, 0x50, 0xb8, + 0x1d, 0x3f, 0x31, 0x8d, 0xa8, 0x43, 0xa6, 0xaa, 0x2f, 0x49, 0x3e, 0xda, 0xfc, 0x21, 0xac, 0x09, 0x8e, 0x1c, 0xe3, + 0xa6, 0x67, 0xa8, 0x88, 0xcc, 0x13, 0xaf, 0x76, 0x0f, 0x9c, 0x9a, 0x80, 0xeb, 0x79, 0x64, 0xde, 0xa7, 0xa9, 0x6d, + 0x70, 0xf1, 0x04, 0xb9, 0x73, 0x03, 0x78, 0xa7, 0x56, 0x57, 0xfb, 0x97, 0x5a, 0xef, 0x42, 0x84, 0x5b, 0x00, 0x51, + 0x8e, 0x5f, 0x64, 0x13, 0xb9, 0x7f, 0x70, 0xe6, 0x62, 0x4e, 0xc3, 0x3d, 0xd2, 0xa1, 0xe4, 0xee, 0x10, 0xb5, 0xce, + 0x2a, 0x67, 0x72, 0xa3, 0x98, 0x25, 0x93, 0x42, 0x00, 0x04, 0xa6, 0x55, 0xbe, 0x22, 0x02, 0xb8, 0x0a, 0x0b, 0x8d, + 0xa6, 0x28, 0xf2, 0x2b, 0xaa, 0xed, 0x67, 0xb4, 0x5b, 0xf6, 0xa3, 0xa3, 0x6b, 0xc7, 0x4c, 0x6a, 0x35, 0x71, 0xe9, + 0x48, 0x0a, 0x66, 0x98, 0xbc, 0xb9, 0x28, 0xe4, 0x15, 0x1f, 0xcc, 0x0f, 0x43, 0x02, 0x53, 0x69, 0x05, 0x85, 0x5c, + 0xaf, 0xb1, 0x33, 0x47, 0xa8, 0xe1, 0x34, 0x6b, 0x3c, 0x3d, 0x7d, 0x5e, 0x8a, 0xd7, 0x8e, 0x53, 0xb5, 0xcd, 0x38, + 0x1d, 0x2c, 0xc2, 0x79, 0x91, 0x76, 0x59, 0xb6, 0x12, 0x81, 0xec, 0xc7, 0xf4, 0x6f, 0xe3, 0xbc, 0xd0, 0xbf, 0x59, + 0xe7, 0x58, 0x9e, 0xc0, 0xc8, 0x12, 0x2d, 0x54, 0xc7, 0xfc, 0xa7, 0x56, 0x6c, 0xad, 0xf0, 0x9d, 0xa8, 0x24, 0xc6, + 0xab, 0x73, 0x69, 0xcf, 0x75, 0xe7, 0x87, 0x10, 0x2c, 0x0f, 0xf0, 0xb3, 0xb8, 0xca, 0xf7, 0x67, 0x85, 0x5b, 0xe9, + 0x3f, 0xeb, 0xe6, 0xef, 0x8a, 0xde, 0x93, 0x8f, 0x1f, 0x52, 0xc4, 0x34, 0x81, 0xf9, 0xae, 0x01, 0x34, 0x55, 0x48, + 0x58, 0x94, 0x2a, 0x6e, 0x43, 0x8e, 0xf7, 0xcf, 0xeb, 0x5e, 0xc4, 0xa2, 0x94, 0x23, 0xbb, 0x8e, 0x3b, 0x7e, 0x29, + 0x30, 0x03, 0x5c, 0xc0, 0xf7, 0x50, 0x4e, 0xa0, 0x1f, 0x3b, 0x8f, 0x8f, 0x44, 0x51, 0x38, 0x65, 0xbc, 0x53, 0x58, + 0xeb, 0xf0, 0x42, 0x79, 0x97, 0x6e, 0x14, 0xd3, 0xa8, 0x89, 0x9f, 0x32, 0xbe, 0xb1, 0x1a, 0x3d, 0xd6, 0x35, 0xba, + 0x1f, 0xcd, 0x8f, 0x82, 0x36, 0xb0, 0x88, 0xbd, 0xff, 0xd3, 0x21, 0xc5, 0xc4, 0xe4, 0xbc, 0x65, 0x2c, 0x70, 0x24, + 0xa4, 0xca, 0xad, 0xcc, 0xf7, 0xa9, 0x88, 0xca, 0xf4, 0x2b, 0x9c, 0xf1, 0x3b, 0x42, 0x44, 0x15, 0x16, 0xfb, 0xa7, + 0xd6, 0x3d, 0x66, 0xd2, 0xcd, 0xa6, 0x3e, 0x55, 0x20, 0x0d, 0x45, 0x9e, 0xaa, 0xe9, 0x25, 0x34, 0xb7, 0xbb, 0xcf, + 0xcf, 0x67, 0x8f, 0x0a, 0xf2, 0xf9, 0xef, 0x0f, 0xfa, 0xfe, 0xbe, 0x90, 0x07, 0xad, 0x6f, 0xe5, 0x33, 0xd4, 0xfe, + 0x75, 0x95, 0x3d, 0x35, 0xc0, 0x99, 0x22, 0x92, 0x97, 0xfc, 0x08, 0xa7, 0x6b, 0x6e, 0x96, 0xbe, 0x7a, 0xca, 0x75, + 0x3f, 0x5d, 0xce, 0x6a, 0x91, 0x1c, 0x33, 0x44, 0xd0, 0xde, 0xc8, 0xb8, 0xc7, 0xf7, 0x59, 0x22, 0x9d, 0x85, 0x09, + 0xba, 0x88, 0xea, 0xf6, 0x68, 0x43, 0xd9, 0xad, 0xe6, 0x2d, 0xf7, 0xc6, 0x1f, 0xe8, 0x7b, 0xd6, 0x8b, 0xa0, 0x34, + 0x94, 0x60, 0xc7, 0xdd, 0xa8, 0x71, 0x44, 0x3a, 0xd7, 0x1d, 0xa4, 0x91, 0x7b, 0xa1, 0x58, 0x52, 0xde, 0x77, 0xb3, + 0xa3, 0x30, 0x69, 0x81, 0x15, 0x76, 0xea, 0xf2, 0xe0, 0x6e, 0x5a, 0x98, 0x75, 0x0a, 0x85, 0xca, 0x74, 0x31, 0xf0, + 0xc5, 0xa6, 0xb4, 0xae, 0x57, 0x0e, 0xc8, 0x01, 0x8c, 0x8e, 0x83, 0x14, 0x26, 0xd5, 0x58, 0x92, 0xca, 0xd0, 0xd1, + 0x72, 0x68, 0x59, 0xaa, 0x14, 0x14, 0xbd, 0x03, 0x0c, 0xca, 0x78, 0xf6, 0xff, 0xc3, 0x9c, 0x0b, 0x83, 0x58, 0x0e, + 0xec, 0x57, 0x64, 0x5f, 0x5d, 0x77, 0xc2, 0x49, 0x54, 0x10, 0xa6, 0xba, 0x91, 0xa9, 0x47, 0x15, 0xd8, 0x84, 0x1c, + 0xd2, 0x24, 0xc9, 0xe9, 0xc0, 0x04, 0x72, 0xe4, 0x69, 0x13, 0x51, 0x17, 0x92, 0xca, 0xe5, 0x97, 0xce, 0xb7, 0x5f, + 0x71, 0xe6, 0x2f, 0x30, 0x92, 0x53, 0x4a, 0xc7, 0x3a, 0x8b, 0xf1, 0x3b, 0xed, 0x7e, 0x3a, 0x6f, 0xfb, 0x9c, 0x5f, + 0x72, 0x80, 0xde, 0x42, 0x55, 0xce, 0x10, 0x90, 0x1e, 0xfa, 0xfe, 0x7a, 0x47, 0xb5, 0xa0, 0x3b, 0x6e, 0xfa, 0xe4, + 0x33, 0xce, 0x5e, 0xad, 0x93, 0xcf, 0x4f, 0xde, 0x28, 0xc4, 0x48, 0x04, 0x5d, 0x3b, 0x52, 0x95, 0x76, 0x9f, 0x6f, + 0xe4, 0x2a, 0x5c, 0xae, 0x41, 0xb3, 0x83, 0xa2, 0x53, 0xda, 0xcf, 0x94, 0xb1, 0xae, 0x7e, 0x4a, 0x0e, 0x1b, 0xb0, + 0xd9, 0x10, 0xe3, 0x48, 0xdc, 0x78, 0xa5, 0x62, 0x80, 0x33, 0x37, 0xaa, 0x61, 0xa5, 0xb7, 0x9d, 0x93, 0x5f, 0xe2, + 0x95, 0x06, 0xcf, 0x13, 0x2c, 0xd1, 0x45, 0x9f, 0x57, 0x8f, 0xd3, 0x51, 0xe6, 0x1b, 0xea, 0xdf, 0xa0, 0xda, 0x26, + 0x5d, 0x88, 0x75, 0x9a, 0xce, 0x21, 0xcf, 0x95, 0x1f, 0xdd, 0x99, 0x20, 0x73, 0x47, 0x85, 0x6b, 0xd5, 0xa0, 0x40, + 0x53, 0xf6, 0xc9, 0x4a, 0x78, 0x74, 0xeb, 0x93, 0x4c, 0xda, 0x47, 0x6b, 0xe5, 0xc3, 0xad, 0x28, 0xfb, 0x77, 0xcf, + 0xbf, 0xf7, 0x99, 0xde, 0x22, 0x1d, 0xd7, 0xac, 0xf6, 0x2f, 0xf8, 0x29, 0xe7, 0x34, 0xde, 0x12, 0xa5, 0x44, 0xe5, + 0x87, 0xe3, 0x80, 0x58, 0xbc, 0x41, 0xfc, 0xd1, 0x0f, 0xdc, 0xec, 0x45, 0xac, 0x2f, 0x55, 0x5a, 0x54, 0x7f, 0xb2, + 0xc7, 0x55, 0x0d, 0x8e, 0x1f, 0xeb, 0xf9, 0x75, 0xac, 0xbc, 0x13, 0x0d, 0xb0, 0x56, 0x02, 0x1f, 0xdb, 0x95, 0x80, + 0x02, 0x22, 0xbd, 0x25, 0x6f, 0xcf, 0xff, 0x77, 0x8b, 0xfd, 0x7e, 0x47, 0xf7, 0xd3, 0xce, 0x8d, 0xaa, 0xd1, 0x69, + 0x53, 0x58, 0x0a, 0xdb, 0xee, 0xb3, 0xc0, 0x45, 0xc6, 0x80, 0x40, 0x35, 0xe6, 0x1f, 0x92, 0x30, 0xa7, 0xc0, 0xbb, + 0x3c, 0x38, 0x8e, 0xfc, 0x96, 0xfa, 0xc6, 0x0a, 0xf7, 0xef, 0xf6, 0xae, 0xb7, 0x20, 0x42, 0x65, 0x9f, 0xa0, 0xdc, + 0x91, 0x3f, 0xf6, 0xd3, 0x0b, 0xd4, 0x47, 0x61, 0xaf, 0x60, 0xd5, 0xd1, 0xa2, 0x6b, 0x07, 0x3a, 0x07, 0xbd, 0x1b, + 0x51, 0x51, 0xf9, 0x98, 0x8d, 0xa5, 0x66, 0x7c, 0x04, 0x30, 0x02, 0x58, 0x0c, 0x71, 0xe2, 0xda, 0x2b, 0xf7, 0x35, + 0xba, 0x02, 0x02, 0x8c, 0xe1, 0x1f, 0x36, 0x38, 0xb7, 0x5e, 0x59, 0x06, 0x9a, 0x1c, 0xe0, 0xd4, 0x26, 0x8b, 0x53, + 0x8b, 0x53, 0xbc, 0xdf, 0xf9, 0xc6, 0xe8, 0xed, 0x05, 0x39, 0x1d, 0xf0, 0x1e, 0x7b, 0x14, 0x15, 0x35, 0x64, 0xa0, + 0x85, 0x6f, 0xbb, 0x21, 0x62, 0x65, 0x30, 0x0b, 0xfa, 0x70, 0xee, 0xfb, 0xf3, 0x4b, 0x2a, 0x54, 0xff, 0x57, 0xaf, + 0xbd, 0xae, 0x5a, 0xf0, 0xc4, 0x35, 0xec, 0x2e, 0xb8, 0x72, 0x4a, 0xed, 0x58, 0xa5, 0xa7, 0x9d, 0x64, 0x50, 0x10, + 0xda, 0x21, 0x85, 0x67, 0xff, 0x67, 0x51, 0x7d, 0x9e, 0x5b, 0xcd, 0xa1, 0xfa, 0xcc, 0x3a, 0x0e, 0x88, 0x7f, 0x3f, + 0xca, 0xbb, 0x3a, 0x08, 0x50, 0x35, 0xe4, 0x93, 0x02, 0xf3, 0x5f, 0xf1, 0x2c, 0x6f, 0x44, 0xba, 0x9d, 0xd9, 0x7d, + 0x8d, 0xcb, 0x99, 0xdc, 0x4e, 0xe6, 0x9b, 0x79, 0xb8, 0xd9, 0x79, 0x7f, 0xbd, 0xa5, 0x4a, 0xda, 0x7a, 0xa5, 0x3e, + 0x3d, 0xe0, 0x38, 0x20, 0xd2, 0x66, 0x19, 0x46, 0x73, 0x7e, 0xee, 0x06, 0xbe, 0x1f, 0x16, 0x61, 0xbe, 0x5f, 0xfb, + 0xb5, 0xe0, 0xc6, 0x24, 0x6f, 0x24, 0x4e, 0xd4, 0xc0, 0x65, 0x8a, 0xa1, 0x2b, 0x05, 0xbc, 0x89, 0x43, 0x5f, 0xc3, + 0x94, 0x1d, 0xf4, 0x5e, 0xb8, 0x1e, 0xf5, 0x74, 0xc4, 0x05, 0xae, 0xba, 0x79, 0x24, 0x93, 0xcc, 0x37, 0x94, 0x31, + 0xde, 0xf0, 0xaa, 0xdf, 0xb8, 0x73, 0xaf, 0x93, 0x32, 0x80, 0x5d, 0x2a, 0x28, 0x7e, 0xbc, 0x6a, 0x55, 0x53, 0x9f, + 0x8a, 0x10, 0xb2, 0x90, 0x4b, 0x01, 0xee, 0xf2, 0xfc, 0x99, 0x7c, 0x1e, 0x5d, 0xdc, 0x0d, 0x55, 0x03, 0xd0, 0x6a, + 0xea, 0xeb, 0x02, 0xc6, 0x91, 0x27, 0x45, 0xca, 0x70, 0x66, 0x6d, 0x78, 0x51, 0xab, 0x4f, 0xb9, 0xa4, 0x21, 0xa3, + 0xb6, 0x53, 0xea, 0x41, 0xbe, 0xd6, 0xd9, 0xec, 0x91, 0x37, 0xb8, 0xa1, 0x65, 0xbb, 0x92, 0x8f, 0x20, 0x8a, 0x26, + 0xc0, 0x72, 0x96, 0xb6, 0x09, 0x32, 0xf8, 0x0e, 0x2d, 0x92, 0xc1, 0x10, 0xb1, 0xc0, 0x9e, 0x77, 0xab, 0xe2, 0xb5, + 0xbd, 0x9c, 0x6a, 0x27, 0xd3, 0xef, 0x72, 0x74, 0xf6, 0x81, 0x3a, 0x1c, 0xac, 0xea, 0x65, 0x17, 0x6a, 0xfd, 0xbb, + 0x1f, 0xda, 0x0a, 0x02, 0x59, 0x03, 0x27, 0x4a, 0x8a, 0xbd, 0x52, 0x65, 0x6b, 0xe4, 0x24, 0xc0, 0x5d, 0x1f, 0xcf, + 0x44, 0x14, 0xb3, 0x74, 0x4e, 0xbf, 0x0b, 0x42, 0x8f, 0x31, 0xac, 0x90, 0x6a, 0x02, 0x8d, 0x9f, 0x5c, 0xd1, 0xdd, + 0x60, 0x35, 0xd9, 0x33, 0xd2, 0x17, 0x63, 0x3d, 0xdd, 0xd9, 0x36, 0xa8, 0x43, 0xfb, 0x6c, 0xb6, 0xaf, 0x2b, 0x8c, + 0x58, 0xf9, 0xa2, 0x1a, 0x7b, 0x61, 0x0b, 0xdc, 0xa9, 0x0b, 0x91, 0xb1, 0x62, 0x66, 0x7a, 0xc2, 0x50, 0x70, 0x5c, + 0x23, 0x1f, 0xe3, 0xc4, 0x4c, 0xa4, 0xb4, 0x2b, 0x76, 0x9a, 0x12, 0x70, 0x0a, 0x84, 0x8e, 0x3d, 0xed, 0xd6, 0x6a, + 0x41, 0xf2, 0x60, 0xe9, 0xb2, 0x1f, 0xe2, 0x7a, 0x3c, 0x2d, 0x29, 0x84, 0x20, 0x5c, 0x9c, 0x9e, 0x75, 0xb3, 0x8c, + 0xe3, 0xc1, 0x94, 0xa6, 0xc3, 0xfe, 0x69, 0x3f, 0xad, 0x0c, 0x3e, 0xde, 0x57, 0x2b, 0x3c, 0x76, 0x20, 0xf8, 0x3c, + 0xfa, 0xde, 0x20, 0xcf, 0xff, 0x34, 0xc9, 0xff, 0x3a, 0x86, 0x40, 0x0d, 0x5b, 0xb1, 0xa0, 0x1b, 0xbe, 0xb1, 0x09, + 0x5e, 0xae, 0x99, 0x57, 0x3a, 0x5b, 0x8b, 0xb3, 0x88, 0x0c, 0x0b, 0x78, 0x7c, 0xf3, 0xe3, 0xfa, 0x23, 0x9c, 0x8d, + 0xcb, 0x18, 0xc3, 0x4b, 0x6e, 0x80, 0x24, 0x21, 0x5c, 0x42, 0xcc, 0x58, 0x77, 0xcf, 0x0d, 0x6e, 0xab, 0x8d, 0xaf, + 0x01, 0xb7, 0x9e, 0x2f, 0xc6, 0xcb, 0x84, 0xf3, 0xe9, 0xcf, 0xca, 0x75, 0x4f, 0xa5, 0xb9, 0x51, 0x6f, 0xb5, 0xfe, + 0xe3, 0xd9, 0xef, 0x1e, 0xb0, 0x24, 0xdc, 0x4f, 0x2d, 0xc3, 0x7c, 0xf2, 0xea, 0x92, 0x89, 0x10, 0xcf, 0x02, 0x5a, + 0x0e, 0x51, 0x88, 0x0f, 0x17, 0x90, 0xe7, 0xee, 0xe8, 0x70, 0xe4, 0x76, 0x9a, 0x4b, 0x23, 0x47, 0x76, 0x30, 0xb4, + 0xa8, 0xa4, 0x0b, 0xab, 0x95, 0x69, 0x9f, 0x4a, 0x37, 0x22, 0x72, 0x20, 0x31, 0x59, 0xb1, 0xcf, 0x30, 0xd3, 0x0e, + 0x9c, 0x7a, 0x40, 0xfc, 0xcf, 0x7f, 0x11, 0x19, 0xca, 0x09, 0x2f, 0xb5, 0xb0, 0x84, 0xa5, 0xca, 0x6c, 0x1f, 0x8f, + 0x9c, 0xca, 0xcc, 0xaa, 0x57, 0x8b, 0x78, 0xeb, 0x8d, 0x86, 0xa6, 0x13, 0x23, 0xc5, 0x07, 0xbe, 0x8c, 0x02, 0x2a, + 0x34, 0xe9, 0xa1, 0x88, 0xd7, 0xf3, 0xcc, 0x39, 0x04, 0xe0, 0x1b, 0x7d, 0xb7, 0x54, 0x75, 0x5d, 0x5f, 0xec, 0x77, + 0x29, 0xf7, 0x25, 0x05, 0xb1, 0xe4, 0xdc, 0x3d, 0xc6, 0x39, 0x1c, 0x39, 0x78, 0x6a, 0x24, 0x15, 0x75, 0x16, 0x89, + 0xc4, 0x82, 0x96, 0xd2, 0xed, 0xb0, 0xdc, 0x03, 0xa6, 0x51, 0xa8, 0x6a, 0xa3, 0xc7, 0x5d, 0x97, 0x00, 0xda, 0xec, + 0x24, 0x84, 0xf7, 0xf0, 0x7d, 0xb6, 0x98, 0x0b, 0xb9, 0xe0, 0x6c, 0x7f, 0x9b, 0x53, 0x29, 0x57, 0xb1, 0x67, 0xa3, + 0xb4, 0x43, 0xf3, 0xed, 0xdc, 0xb3, 0x5a, 0x32, 0x2b, 0x62, 0x0c, 0x91, 0xd3, 0x37, 0x92, 0xb6, 0x0d, 0xd2, 0xe1, + 0x70, 0xcd, 0x90, 0xe0, 0x73, 0x5e, 0x6b, 0x2f, 0xc5, 0x93, 0x71, 0x52, 0xf8, 0x6f, 0x26, 0xd9, 0x79, 0x6d, 0xfd, + 0xa3, 0x3f, 0x24, 0x5b, 0x01, 0xc1, 0x13, 0x7e, 0x35, 0xd9, 0xcc, 0xae, 0xb9, 0xf9, 0xbd, 0x86, 0xf6, 0xd4, 0x52, + 0xb0, 0x66, 0x02, 0xad, 0x4d, 0xca, 0xe7, 0xa2, 0x8f, 0xaf, 0x57, 0x77, 0x24, 0xee, 0xd3, 0x67, 0xd2, 0x35, 0x25, + 0x2f, 0x19, 0x0b, 0xca, 0x37, 0xbc, 0xd9, 0x1f, 0xa3, 0x08, 0xa8, 0x1a, 0x72, 0x05, 0xf5, 0x75, 0x4f, 0xa6, 0xcf, + 0xda, 0x41, 0x58, 0xaf, 0x02, 0x9b, 0x80, 0x22, 0x11, 0xfd, 0xb7, 0x79, 0x8f, 0x3e, 0xe4, 0xd0, 0x1d, 0xb2, 0x37, + 0xb0, 0x9e, 0xac, 0x74, 0x27, 0x11, 0x8a, 0x0a, 0x9f, 0x3b, 0x01, 0xa5, 0x64, 0x07, 0xa5, 0x06, 0x7c, 0xd6, 0x4b, + 0xe4, 0x98, 0xf9, 0xc6, 0xf1, 0x2e, 0xf1, 0x8e, 0xb2, 0xf8, 0xc0, 0x81, 0x9d, 0xea, 0xe7, 0xef, 0x63, 0xf9, 0x72, + 0x8c, 0x07, 0x91, 0xd1, 0xef, 0x45, 0x01, 0xbe, 0xec, 0x37, 0xcd, 0xc8, 0xf3, 0xaf, 0xbf, 0xa5, 0x8d, 0x3c, 0xf3, + 0x6b, 0xa9, 0x84, 0x65, 0xdd, 0x9d, 0x3f, 0x45, 0xbb, 0x94, 0xd8, 0x70, 0x5b, 0xf4, 0xc1, 0x20, 0x97, 0x1b, 0x00, + 0x1f, 0x70, 0x2e, 0xff, 0x99, 0xa3, 0x50, 0x3e, 0x52, 0xeb, 0xf2, 0x64, 0x29, 0xc4, 0x98, 0xfc, 0x8d, 0x51, 0x2d, + 0x67, 0xae, 0x8f, 0xfc, 0x7e, 0xc1, 0x2f, 0x9c, 0x9d, 0xee, 0x07, 0xc8, 0x02, 0x41, 0x8b, 0x15, 0x5d, 0xe9, 0xa1, + 0xa8, 0xa5, 0xaa, 0x18, 0x4a, 0xf3, 0x62, 0x2c, 0x2d, 0x8a, 0x69, 0x63, 0x0f, 0x5e, 0x20, 0x52, 0x70, 0x3d, 0x35, + 0x4b, 0xa6, 0xd0, 0x43, 0xcf, 0xe0, 0x9e, 0xa9, 0xa4, 0xac, 0x75, 0x4e, 0xc3, 0xc0, 0x0a, 0x66, 0xc4, 0x0a, 0x6b, + 0xab, 0x93, 0x96, 0xbd, 0x02, 0x31, 0x96, 0x05, 0x0a, 0x14, 0xaa, 0x83, 0x58, 0x49, 0x15, 0x12, 0xcc, 0xd9, 0x16, + 0x23, 0x3d, 0x5b, 0x49, 0x95, 0xee, 0x34, 0x34, 0xe7, 0x67, 0x85, 0xd1, 0x1b, 0x01, 0xdd, 0xa2, 0xb8, 0xbf, 0x5f, + 0xd7, 0xb0, 0x41, 0x66, 0xa5, 0x2a, 0xaa, 0x17, 0x51, 0x95, 0x69, 0x46, 0x5a, 0x82, 0xec, 0xf9, 0x0c, 0xe4, 0xaa, + 0x72, 0xd4, 0x1e, 0xd3, 0x5e, 0x00, 0xd5, 0xe8, 0xb3, 0xe8, 0xe8, 0x45, 0x9a, 0x43, 0x5d, 0x37, 0x6c, 0xa9, 0x15, + 0x65, 0x52, 0x50, 0xac, 0x91, 0xdf, 0x4e, 0xb2, 0x46, 0x44, 0x76, 0xb3, 0x8b, 0xef, 0xe9, 0xae, 0x92, 0x4d, 0xb2, + 0xf1, 0x69, 0x1c, 0x20, 0xb4, 0x4e, 0x48, 0x2c, 0x6a, 0xbc, 0xe0, 0x2d, 0xe1, 0xd2, 0x72, 0x18, 0x7f, 0x74, 0xbc, + 0xbf, 0xe4, 0x0a, 0x0f, 0xac, 0x48, 0xeb, 0x84, 0x45, 0x7e, 0x32, 0x2e, 0xe0, 0xd7, 0xfe, 0xac, 0x90, 0x59, 0x33, + 0x16, 0xb9, 0xf0, 0x59, 0x94, 0x27, 0xb1, 0xae, 0x2d, 0xdd, 0x93, 0x71, 0xff, 0xd8, 0x99, 0x3a, 0xde, 0x9f, 0x74, + 0x08, 0xfc, 0x02, 0x50, 0xaa, 0x1e, 0x10, 0xfb, 0xc0, 0xf7, 0x78, 0x65, 0x51, 0x04, 0x97, 0xe1, 0xf6, 0x90, 0x8a, + 0xf2, 0x34, 0x77, 0xd5, 0xb4, 0xf2, 0x17, 0x21, 0x09, 0xaa, 0xe1, 0x9b, 0x94, 0xa4, 0x40, 0xe9, 0xa3, 0x1c, 0x26, + 0x3d, 0x62, 0x9f, 0xdf, 0xfb, 0xd2, 0x67, 0xa7, 0xf0, 0xa5, 0x4f, 0xba, 0x66, 0x6d, 0x85, 0xb7, 0xff, 0x36, 0xb0, + 0x83, 0x99, 0x1e, 0xc5, 0xef, 0x87, 0x38, 0x2d, 0xd6, 0x32, 0xea, 0xce, 0x2f, 0x96, 0xbd, 0x0d, 0xf9, 0x3f, 0xfc, + 0xee, 0x82, 0xd3, 0xf0, 0xfd, 0x69, 0xd5, 0xdd, 0x78, 0x5b, 0x39, 0x74, 0xbf, 0x75, 0xbf, 0x6d, 0xa5, 0x5b, 0x3a, + 0x79, 0xe1, 0x7f, 0x7b, 0xef, 0x9c, 0xfb, 0x96, 0x8b, 0xcf, 0x24, 0x33, 0x5e, 0x7d, 0x12, 0xeb, 0x74, 0xac, 0x20, + 0xbd, 0x72, 0x91, 0x49, 0xaf, 0xb7, 0xc6, 0xf1, 0x8b, 0xc4, 0xda, 0xee, 0xc4, 0x9a, 0x7d, 0x50, 0x35, 0x79, 0x8c, + 0xc1, 0xa3, 0xad, 0x2c, 0xa6, 0x3f, 0x58, 0xe7, 0xd1, 0xff, 0x36, 0xb2, 0x39, 0x6e, 0x5c, 0x8e, 0x36, 0x7f, 0xb1, + 0x44, 0x3c, 0x5b, 0xed, 0x57, 0xde, 0xa7, 0xb5, 0x25, 0x8b, 0xbf, 0x49, 0x4b, 0xd2, 0x5a, 0x8c, 0xef, 0xe5, 0x83, + 0x25, 0x7d, 0x8a, 0x3d, 0x07, 0x11, 0x1a, 0xb1, 0xe6, 0x82, 0x1a, 0xb9, 0x4e, 0x57, 0x02, 0xb1, 0x0b, 0x3f, 0x1f, + 0x7a, 0x8a, 0x0b, 0xa4, 0x3a, 0xc8, 0xcb, 0x40, 0x35, 0x51, 0x40, 0x3f, 0x50, 0x53, 0x82, 0x9c, 0x67, 0x7b, 0xc7, + 0xb7, 0x87, 0xaf, 0xf1, 0xf6, 0xcc, 0xd2, 0x46, 0x64, 0x7e, 0x8b, 0x07, 0x47, 0x58, 0x9a, 0xdb, 0x09, 0x93, 0x45, + 0xd8, 0x42, 0xd1, 0xf2, 0x0e, 0xd9, 0x63, 0xf3, 0x4b, 0x03, 0xd5, 0x85, 0x1c, 0xb1, 0x9e, 0xff, 0x5a, 0xef, 0xd2, + 0x15, 0xbc, 0x4b, 0xfb, 0xa2, 0x97, 0x66, 0x3d, 0x04, 0x40, 0x77, 0xea, 0xcf, 0x40, 0x95, 0xb9, 0xa1, 0x28, 0x7d, + 0x7e, 0x9d, 0xb5, 0xa7, 0xda, 0x55, 0xe0, 0xde, 0x69, 0x78, 0x76, 0x42, 0x56, 0x2e, 0x11, 0xfd, 0x18, 0xec, 0x73, + 0x02, 0xfd, 0x41, 0x33, 0xb4, 0xaf, 0x3b, 0x3a, 0x71, 0x09, 0x28, 0x13, 0x75, 0xb8, 0x24, 0x46, 0x30, 0x7e, 0x90, + 0x83, 0x0d, 0xbc, 0x5a, 0xdf, 0xa5, 0x24, 0xae, 0xba, 0x73, 0x08, 0xd1, 0x6b, 0xde, 0xff, 0xea, 0xd7, 0x60, 0xbf, + 0xde, 0xe8, 0x26, 0x23, 0xf2, 0xf7, 0xfc, 0x9c, 0x4b, 0x34, 0x63, 0x88, 0x10, 0x55, 0x2c, 0x5a, 0xf3, 0x1c, 0x0b, + 0x58, 0x9e, 0x97, 0xe0, 0xbb, 0x7c, 0xde, 0x75, 0x62, 0xab, 0x89, 0xa5, 0x6a, 0x30, 0x62, 0x17, 0x0e, 0xde, 0x07, + 0x29, 0x30, 0x70, 0x59, 0x76, 0xd2, 0x7d, 0x47, 0x32, 0x1b, 0x1f, 0x34, 0x07, 0x04, 0x37, 0x3d, 0xc8, 0x02, 0x7f, + 0x23, 0x8c, 0xa1, 0x85, 0x07, 0xeb, 0xa1, 0xd9, 0xa6, 0xbc, 0x06, 0x17, 0xdc, 0x74, 0xa5, 0x22, 0xd5, 0x97, 0xb6, + 0x5a, 0x06, 0x0a, 0x4b, 0xb3, 0x60, 0xe0, 0x5b, 0x5a, 0x2c, 0x8b, 0x10, 0x83, 0x3c, 0x5c, 0xe7, 0x24, 0x84, 0xf2, + 0x04, 0xa1, 0x0e, 0x05, 0x66, 0x3c, 0x38, 0x9d, 0x22, 0x70, 0x30, 0xaf, 0x39, 0xaf, 0x3b, 0xbf, 0x67, 0xc2, 0x32, + 0x4b, 0x8f, 0x7b, 0x0d, 0x97, 0x4b, 0x13, 0x39, 0xd0, 0xbd, 0xd9, 0xfb, 0xdb, 0x2d, 0xf2, 0xbe, 0x11, 0x5a, 0xb1, + 0x0d, 0x17, 0x15, 0x17, 0x59, 0xb4, 0xba, 0xc4, 0xb8, 0x93, 0xae, 0x57, 0xee, 0x85, 0xdd, 0x7a, 0xea, 0x9e, 0xac, + 0x37, 0x4c, 0xe1, 0xd3, 0xb0, 0x8c, 0x25, 0xc4, 0x1a, 0x4b, 0x47, 0xff, 0xbb, 0x2c, 0x7c, 0x96, 0xb5, 0x07, 0x0c, + 0x85, 0xb8, 0x3f, 0xd3, 0xe3, 0x27, 0x00, 0x0e, 0xc7, 0x13, 0x1f, 0x27, 0xe0, 0x40, 0x6b, 0x49, 0xa1, 0x5b, 0x33, + 0x01, 0x11, 0x6b, 0x4b, 0xfe, 0x4b, 0x5f, 0x89, 0x52, 0xf4, 0xd9, 0xb1, 0xeb, 0xdc, 0xe4, 0xfd, 0xdb, 0xea, 0x58, + 0x35, 0x2d, 0x21, 0xef, 0xba, 0x05, 0xea, 0x61, 0xf9, 0xfb, 0xae, 0x58, 0xd1, 0x11, 0x08, 0x3c, 0x7f, 0x63, 0x5a, + 0xac, 0x4f, 0x06, 0x48, 0xd7, 0x83, 0x4f, 0x58, 0x24, 0x9e, 0x82, 0x63, 0x20, 0x8e, 0xab, 0xe1, 0x23, 0xf3, 0xc3, + 0xff, 0x2c, 0x27, 0x56, 0xa6, 0x9d, 0xc9, 0xa9, 0x63, 0xaa, 0x23, 0x83, 0x00, 0xfa, 0x22, 0xf7, 0xb8, 0xee, 0xbf, + 0x3a, 0xb5, 0x54, 0x31, 0x6c, 0xb6, 0x37, 0x71, 0x6b, 0xee, 0xc4, 0x7a, 0xa5, 0xcb, 0xe0, 0xd3, 0xca, 0xfd, 0xe2, + 0xf4, 0x43, 0x26, 0xcc, 0xe0, 0x6c, 0xf1, 0xe5, 0x83, 0x4d, 0x0f, 0x19, 0x0d, 0x80, 0x09, 0x4b, 0xe9, 0x27, 0x83, + 0x94, 0x3e, 0x3f, 0x31, 0x12, 0xda, 0x36, 0xf8, 0x67, 0x6e, 0x2e, 0x47, 0x39, 0xd0, 0x7f, 0x18, 0xec, 0x62, 0xa3, + 0xb7, 0x49, 0x18, 0x3f, 0x40, 0x9a, 0xbd, 0xd1, 0x8f, 0x7a, 0xcd, 0xa1, 0x25, 0x16, 0xe5, 0xd5, 0x93, 0xfc, 0x98, + 0x65, 0x46, 0x01, 0xf8, 0x90, 0xf7, 0x1e, 0xfa, 0xe7, 0x98, 0x62, 0xce, 0xe1, 0xeb, 0xf8, 0xd7, 0x0e, 0x62, 0x6d, + 0xed, 0x74, 0xcd, 0xff, 0xce, 0x5c, 0x78, 0x6a, 0x73, 0xc2, 0x8c, 0xb6, 0x5f, 0xbd, 0xba, 0xda, 0x74, 0x18, 0x01, + 0x34, 0xbe, 0xc2, 0xe8, 0xb1, 0x09, 0xdd, 0x06, 0x66, 0x24, 0xe0, 0x9e, 0x67, 0xd2, 0x95, 0x8e, 0x3f, 0x16, 0xf0, + 0x66, 0xe6, 0x77, 0xa0, 0x09, 0x77, 0x57, 0xd2, 0x68, 0x4b, 0x92, 0x1c, 0xf9, 0x6d, 0xc1, 0x44, 0xb1, 0x75, 0xeb, + 0x26, 0xbc, 0x16, 0xf8, 0xff, 0xf8, 0x41, 0x00, 0xf2, 0x6e, 0x51, 0xb3, 0xa4, 0x76, 0x9a, 0xe6, 0x2b, 0x4d, 0x29, + 0xbb, 0xb0, 0x72, 0x93, 0x5d, 0xce, 0xfc, 0xff, 0x30, 0x82, 0x9b, 0x1c, 0x3e, 0x89, 0x1e, 0xda, 0x57, 0x80, 0xa4, + 0x07, 0x44, 0x17, 0x0f, 0x5a, 0x38, 0x7e, 0x23, 0xca, 0x1c, 0x2c, 0x6c, 0x0b, 0x96, 0x05, 0x83, 0x28, 0x7b, 0x04, + 0xf3, 0x0b, 0x1d, 0x98, 0xfc, 0x4d, 0xef, 0x28, 0xe7, 0x10, 0xe9, 0xd5, 0x77, 0x25, 0xa7, 0xae, 0x9d, 0x5e, 0xfa, + 0xbf, 0x69, 0x02, 0x4c, 0xe6, 0xb6, 0xbe, 0x4e, 0x2d, 0x5f, 0xf8, 0x3c, 0x6b, 0x2f, 0x8a, 0x71, 0xfc, 0xed, 0x8a, + 0x8e, 0x77, 0xc6, 0xac, 0x77, 0x14, 0x35, 0xad, 0xae, 0x7d, 0x75, 0xd3, 0x82, 0x6e, 0x9c, 0x10, 0x3c, 0xc6, 0x87, + 0x58, 0x7e, 0xde, 0x7c, 0x93, 0x50, 0xc7, 0xdf, 0xc6, 0x1e, 0x6f, 0x9b, 0x29, 0x3c, 0xb1, 0x03, 0x7e, 0x47, 0xf7, + 0x96, 0x8e, 0x57, 0x57, 0x4c, 0x7c, 0x08, 0x4e, 0x45, 0x80, 0xd7, 0x93, 0x24, 0xbe, 0x29, 0x89, 0x83, 0x0d, 0xa7, + 0xd6, 0xb6, 0xc2, 0x7d, 0x59, 0xbb, 0x43, 0x16, 0x4e, 0xe3, 0x9b, 0xa8, 0x1b, 0x1e, 0x71, 0xc6, 0x49, 0xdc, 0xea, + 0xa9, 0xef, 0xb6, 0x41, 0x8c, 0xc0, 0xe1, 0x0a, 0x30, 0x3e, 0x11, 0x3e, 0xc4, 0x6c, 0x6a, 0x00, 0xa7, 0x22, 0xb0, + 0xea, 0x87, 0x03, 0x4c, 0xd9, 0xfd, 0x94, 0x0f, 0xe9, 0x88, 0xc0, 0xcc, 0xf4, 0x10, 0xe5, 0xfd, 0xe7, 0xf0, 0x48, + 0xde, 0x9f, 0x4f, 0x86, 0xe1, 0x50, 0xc8, 0xb5, 0xd9, 0xb0, 0x07, 0x56, 0xbe, 0xe0, 0x06, 0xe7, 0x6b, 0xb6, 0xed, + 0xda, 0x84, 0xdc, 0xfc, 0x23, 0x9e, 0x61, 0x97, 0x98, 0xde, 0xdc, 0x3b, 0x5d, 0x47, 0x3d, 0xdf, 0x2b, 0x17, 0x52, + 0xc3, 0x3e, 0xd1, 0xe2, 0xd1, 0xf3, 0x6c, 0xa4, 0x75, 0xc7, 0xc9, 0x5b, 0xfd, 0x4b, 0x72, 0x24, 0x04, 0xc5, 0x4f, + 0xb2, 0xf6, 0x3e, 0x91, 0x6d, 0xdf, 0x05, 0xcf, 0xad, 0xf6, 0x3a, 0x42, 0x77, 0xfa, 0xd3, 0x23, 0x6c, 0x4a, 0xe7, + 0xe7, 0x0e, 0xa0, 0x3a, 0x92, 0xf3, 0xd9, 0xe5, 0x1e, 0x06, 0xe5, 0x70, 0xc5, 0x33, 0x70, 0xb7, 0x62, 0xe6, 0x21, + 0xd2, 0x35, 0x5a, 0x7f, 0xf7, 0x82, 0x37, 0x5c, 0x33, 0x59, 0x1b, 0x91, 0xdc, 0x16, 0xf2, 0x30, 0xc7, 0x08, 0x65, + 0xbe, 0xa0, 0xfc, 0x70, 0xd1, 0x66, 0x72, 0x96, 0x84, 0x2f, 0x24, 0x0a, 0xfc, 0x49, 0x95, 0x67, 0xae, 0x1c, 0x2f, + 0x57, 0x6c, 0x60, 0x2e, 0xe8, 0x8b, 0x51, 0x40, 0x22, 0x73, 0xb7, 0xfc, 0x32, 0xcf, 0x90, 0xfc, 0x35, 0x72, 0x6d, + 0x07, 0x58, 0xbe, 0xce, 0x53, 0x06, 0x37, 0x2e, 0x5a, 0x0b, 0x1d, 0x5f, 0x4a, 0x26, 0x41, 0x91, 0x42, 0xa8, 0xb4, + 0x48, 0x68, 0xd4, 0x2a, 0x15, 0x30, 0x6e, 0xa1, 0xa1, 0xdf, 0x6b, 0xd5, 0xe7, 0x4f, 0xd8, 0xf9, 0x63, 0x94, 0xff, + 0x51, 0x5c, 0x04, 0xc8, 0x91, 0xb7, 0xa8, 0x1b, 0xf0, 0x4c, 0x91, 0xd4, 0x66, 0x8e, 0x4b, 0x24, 0x1c, 0x83, 0x64, + 0x61, 0xb7, 0x61, 0xef, 0x7f, 0xc7, 0xd7, 0x54, 0x90, 0x30, 0x88, 0xf0, 0xeb, 0x2c, 0x83, 0x6e, 0xe0, 0x22, 0x98, + 0x6a, 0x84, 0x07, 0x1c, 0x45, 0xdd, 0x35, 0xab, 0x80, 0x13, 0x28, 0x41, 0xc9, 0x22, 0x89, 0x1f, 0x77, 0xa0, 0xff, + 0x5f, 0x8a, 0x51, 0x7d, 0xd6, 0xd7, 0xb7, 0x15, 0xd4, 0x43, 0x87, 0x02, 0x15, 0x19, 0x37, 0xc0, 0x66, 0x8f, 0x8f, + 0x45, 0x0e, 0xd8, 0x30, 0xf9, 0xaf, 0xb0, 0xb0, 0x52, 0xd9, 0x72, 0x3a, 0xfc, 0xcb, 0x35, 0x8b, 0x83, 0x3d, 0x3c, + 0x4c, 0xe3, 0x30, 0x3e, 0xa5, 0x25, 0x7d, 0x5e, 0xe8, 0xa4, 0x51, 0xd1, 0xf9, 0x71, 0x9e, 0xf5, 0x7d, 0x57, 0xf2, + 0xf8, 0x35, 0x5e, 0x9f, 0xd9, 0x53, 0x74, 0x9d, 0x1f, 0x7e, 0xf4, 0xa3, 0xb1, 0x65, 0xfc, 0x37, 0x7a, 0x61, 0x4f, + 0x17, 0x94, 0x96, 0x81, 0xf7, 0xe9, 0xd1, 0x62, 0x25, 0xfb, 0x82, 0x1c, 0x7d, 0x8c, 0x8e, 0xf6, 0x78, 0x4e, 0xf9, + 0x79, 0x16, 0xe7, 0xfd, 0xed, 0x6b, 0xbc, 0x38, 0xf3, 0xac, 0x5c, 0xeb, 0xcd, 0xa7, 0xde, 0x06, 0xec, 0x2d, 0x70, + 0x3f, 0x89, 0xdd, 0x40, 0x84, 0x93, 0x60, 0x0c, 0xd3, 0xbd, 0x69, 0x44, 0x03, 0xec, 0x77, 0xed, 0xf9, 0xc0, 0x03, + 0xfd, 0xcf, 0xe6, 0xf5, 0xe0, 0xdc, 0x6e, 0x54, 0x53, 0x0a, 0x70, 0xc1, 0x64, 0x45, 0x31, 0x46, 0x82, 0x48, 0x23, + 0xbd, 0x1d, 0x1d, 0xb9, 0xa8, 0x2b, 0x9c, 0x26, 0xba, 0xe4, 0x69, 0xe2, 0x26, 0x65, 0x6b, 0x99, 0x00, 0x50, 0x96, + 0x64, 0xec, 0xd0, 0xf3, 0x7a, 0x80, 0xf4, 0x0e, 0x72, 0x42, 0x2c, 0xc7, 0x25, 0x90, 0x2d, 0x19, 0x7c, 0xfb, 0x0f, + 0xab, 0x40, 0x5e, 0x6f, 0xe8, 0xb0, 0x09, 0x69, 0xf6, 0x38, 0x3d, 0x7d, 0x71, 0x00, 0xae, 0x44, 0xa6, 0x67, 0x9a, + 0x06, 0x17, 0x7d, 0x8e, 0x3e, 0x34, 0xc2, 0x5a, 0x60, 0x2a, 0xea, 0xb4, 0xe5, 0xad, 0x52, 0x71, 0xf3, 0xe0, 0x78, + 0x0a, 0x07, 0x43, 0x33, 0x30, 0x22, 0x7f, 0xfa, 0x0f, 0x1b, 0xc6, 0x72, 0x24, 0xad, 0x6c, 0x98, 0xbf, 0xec, 0x72, + 0x2b, 0x37, 0x4b, 0x12, 0x9a, 0x86, 0x5e, 0x3d, 0x88, 0x15, 0xde, 0xa9, 0xff, 0xe7, 0x41, 0x69, 0x83, 0x38, 0x87, + 0x64, 0x01, 0x51, 0x3c, 0x47, 0x38, 0xc5, 0xa0, 0xc5, 0x6c, 0x90, 0xc3, 0x94, 0x81, 0xc0, 0x2b, 0xab, 0x37, 0x81, + 0x1b, 0x71, 0xb9, 0xec, 0xe9, 0xd4, 0x6b, 0xae, 0x9d, 0xd4, 0x26, 0xb2, 0x08, 0x57, 0xf8, 0xcd, 0x07, 0x80, 0xae, + 0x36, 0xd4, 0x51, 0x08, 0xe4, 0x08, 0x9b, 0xe7, 0x8a, 0x14, 0xdd, 0x78, 0x7c, 0x1b, 0xf6, 0x2d, 0x47, 0x88, 0xcd, + 0x8f, 0xb9, 0x6b, 0x8d, 0x06, 0x8d, 0x4c, 0x32, 0x6c, 0x5c, 0x0a, 0x76, 0x92, 0xa0, 0x87, 0x1a, 0xc7, 0x38, 0x94, + 0x15, 0x7a, 0x1e, 0x19, 0xe3, 0x88, 0xaf, 0x7c, 0xc9, 0x9a, 0x93, 0x68, 0x91, 0x8a, 0x81, 0xfd, 0x1c, 0xbe, 0xce, + 0x0b, 0x41, 0x2e, 0x8e, 0xb8, 0xe9, 0xa9, 0x21, 0xa7, 0x3e, 0x19, 0x14, 0xa8, 0x88, 0x5b, 0xaf, 0x2d, 0x68, 0x98, + 0x47, 0x01, 0x71, 0x6e, 0x16, 0x38, 0xc2, 0x29, 0x2c, 0x6a, 0xff, 0xe0, 0xe8, 0xbc, 0x75, 0xb4, 0x40, 0x90, 0xda, + 0x09, 0x67, 0x38, 0x99, 0xd1, 0x11, 0x32, 0xc3, 0xe5, 0xf1, 0x71, 0x53, 0xd3, 0x5a, 0x53, 0xa7, 0x95, 0x22, 0xc9, + 0x0c, 0x69, 0x26, 0xb0, 0xc4, 0x0f, 0xdb, 0xde, 0x5c, 0xa4, 0x62, 0x45, 0xe0, 0x2d, 0x66, 0xfc, 0x5c, 0xd8, 0x81, + 0xe2, 0xd5, 0x84, 0x0e, 0x6c, 0xaa, 0xfc, 0xdc, 0xe6, 0xa6, 0x27, 0xfc, 0xc2, 0x61, 0xfa, 0x75, 0x26, 0xfa, 0x59, + 0x98, 0xa3, 0xd5, 0x41, 0x2f, 0x5c, 0x21, 0xe3, 0xc4, 0x33, 0x64, 0xd9, 0x94, 0x43, 0xf7, 0x1a, 0x25, 0x8a, 0xa4, + 0x01, 0x39, 0xda, 0x43, 0x4e, 0x2e, 0xf3, 0xa4, 0xd5, 0x34, 0x2a, 0xbb, 0x24, 0xe1, 0x2d, 0x7e, 0xe4, 0x31, 0xa1, + 0x44, 0xf9, 0x3c, 0xcd, 0x33, 0x92, 0xac, 0x71, 0xb7, 0xa3, 0xe0, 0x1a, 0xbd, 0xb5, 0xba, 0xac, 0xd5, 0xb0, 0x9f, + 0xc8, 0xbf, 0x52, 0x47, 0x6f, 0x52, 0x3c, 0x18, 0x04, 0x19, 0x86, 0xab, 0x96, 0xdd, 0x43, 0x8b, 0x1e, 0xfb, 0xa2, + 0xfa, 0x77, 0x83, 0x60, 0xe2, 0x49, 0x21, 0x84, 0x96, 0x91, 0x03, 0xfd, 0x37, 0x55, 0xaa, 0x25, 0x12, 0xde, 0x3b, + 0x9f, 0xb3, 0x77, 0x13, 0xa4, 0x04, 0xb3, 0x4d, 0x95, 0x7b, 0x20, 0x5c, 0x87, 0x80, 0xd7, 0x0d, 0x77, 0xa8, 0x77, + 0x91, 0x5b, 0x11, 0x74, 0x29, 0x05, 0x88, 0x88, 0x00, 0x8c, 0x5e, 0x0c, 0x34, 0x1c, 0xa6, 0x19, 0xac, 0x44, 0x82, + 0x7f, 0x95, 0x85, 0x21, 0xb5, 0xec, 0x28, 0x07, 0xc0, 0x66, 0xb3, 0x11, 0x8c, 0xbe, 0x60, 0x05, 0x7c, 0x36, 0x89, + 0xff, 0xc6, 0xa9, 0x6a, 0xa6, 0x75, 0x23, 0xe5, 0xdd, 0xb8, 0xb1, 0x76, 0x81, 0x18, 0xa6, 0xa5, 0x75, 0x3b, 0x21, + 0x09, 0x28, 0x0d, 0x0b, 0x9f, 0x3c, 0xbf, 0x3d, 0x46, 0xd7, 0xdf, 0x1f, 0x3e, 0x30, 0x49, 0x14, 0x19, 0x55, 0x32, + 0x30, 0x4d, 0x84, 0x8c, 0x6f, 0x11, 0x3a, 0x1e, 0x8e, 0xa6, 0x45, 0x7e, 0xea, 0x75, 0x6c, 0x37, 0x50, 0x8f, 0x2f, + 0xbf, 0xb6, 0xdc, 0x39, 0xd1, 0xda, 0xe9, 0xb8, 0x3f, 0x04, 0x9a, 0x9c, 0x88, 0xaa, 0xb2, 0x18, 0x25, 0xfb, 0x87, + 0x81, 0x6d, 0x24, 0x39, 0xf5, 0x54, 0x18, 0x77, 0x6f, 0x73, 0x4f, 0x87, 0x89, 0x8b, 0x23, 0xff, 0xcb, 0x1f, 0xc1, + 0xb5, 0x52, 0xbc, 0xf2, 0x1d, 0xd8, 0x72, 0x09, 0x57, 0x0e, 0x56, 0x0d, 0x02, 0xa2, 0x94, 0x00, 0x72, 0x1d, 0x1f, + 0x1d, 0xe3, 0x24, 0x79, 0xd7, 0x33, 0xd6, 0xd4, 0x6c, 0x49, 0x69, 0xe6, 0x63, 0x5f, 0x53, 0x69, 0x1e, 0xe7, 0x9a, + 0x60, 0x96, 0x64, 0xd9, 0x49, 0x56, 0x80, 0xd7, 0x74, 0x0d, 0xf3, 0x55, 0x85, 0x40, 0x30, 0xdf, 0x55, 0x99, 0x8b, + 0x53, 0x85, 0xb8, 0x1d, 0x09, 0x6d, 0xaa, 0x45, 0x78, 0xe1, 0xc0, 0x38, 0x9c, 0x5f, 0x33, 0x2d, 0x06, 0x06, 0x20, + 0x57, 0x52, 0x6f, 0x84, 0xf3, 0xf4, 0x20, 0x6f, 0x43, 0xf1, 0xa4, 0xc0, 0x56, 0xac, 0x78, 0xf0, 0xad, 0x97, 0x46, + 0xb3, 0xca, 0x68, 0x97, 0x5b, 0x71, 0xa6, 0xf3, 0xa4, 0xcf, 0x4e, 0x9b, 0xd2, 0xad, 0x87, 0x80, 0x0a, 0xe5, 0xf9, + 0x19, 0xcf, 0xc7, 0x2b, 0xc4, 0x39, 0xe6, 0xac, 0x09, 0xd5, 0x73, 0x61, 0xfd, 0x3a, 0x3d, 0x64, 0xff, 0x7a, 0xbc, + 0xb5, 0xce, 0x54, 0xdc, 0x3c, 0x53, 0xc8, 0x54, 0xfc, 0x15, 0xf7, 0x5e, 0x3c, 0x30, 0x5c, 0x93, 0xc7, 0x90, 0x67, + 0x2a, 0x27, 0x7c, 0x69, 0xa0, 0xe9, 0x20, 0xaa, 0xd3, 0xad, 0x10, 0x57, 0x5d, 0x18, 0xa2, 0x70, 0xf7, 0x29, 0x2f, + 0x48, 0xeb, 0xb0, 0xf7, 0x54, 0xa3, 0xc3, 0xa0, 0xa6, 0x40, 0x9d, 0x16, 0x83, 0x95, 0xb4, 0x5c, 0x50, 0x0e, 0x05, + 0x33, 0xd5, 0x06, 0x1e, 0xd8, 0x9a, 0xff, 0x7f, 0x40, 0x21, 0x7a, 0xdc, 0xf6, 0xaf, 0xfc, 0x05, 0x73, 0xc2, 0x8c, + 0x25, 0x33, 0x3c, 0xbc, 0xda, 0x19, 0x7f, 0x0a, 0xba, 0xb1, 0x6a, 0xa3, 0x8c, 0x55, 0x39, 0x51, 0x06, 0xf7, 0x93, + 0xa5, 0x98, 0x3a, 0x85, 0x0b, 0x31, 0x95, 0x97, 0x7d, 0xa4, 0x92, 0x52, 0x1c, 0x79, 0x51, 0x01, 0xc0, 0xbc, 0x0b, + 0x34, 0x65, 0xca, 0x93, 0x20, 0x09, 0x5c, 0x54, 0x01, 0xd1, 0x8c, 0x97, 0x73, 0x7a, 0xe3, 0x2b, 0x8e, 0x7b, 0xc4, + 0x49, 0x74, 0xe6, 0x10, 0xd4, 0xf5, 0xf9, 0x29, 0x23, 0x62, 0x41, 0xd8, 0x57, 0x8c, 0x43, 0xd9, 0x4e, 0x58, 0x5f, + 0xac, 0xd7, 0x77, 0xde, 0x24, 0x8a, 0xa4, 0x2b, 0xb3, 0x7c, 0xe4, 0xfb, 0x0c, 0x99, 0xad, 0x92, 0x8d, 0x38, 0x86, + 0x32, 0xce, 0x19, 0x8f, 0x62, 0x03, 0x81, 0xb3, 0xa5, 0x2f, 0xb5, 0x90, 0xe3, 0xb2, 0x34, 0x94, 0xc7, 0xc0, 0xb9, + 0x2b, 0xdb, 0x9b, 0xd7, 0xf1, 0x31, 0xe7, 0xfd, 0xb7, 0xeb, 0x4d, 0xad, 0xa8, 0x3f, 0x63, 0xd5, 0x86, 0x7d, 0x81, + 0xa2, 0x79, 0x30, 0xeb, 0x74, 0x8e, 0xf2, 0x88, 0x27, 0x9c, 0x3c, 0x8b, 0x3a, 0xd6, 0xae, 0x8f, 0x92, 0x17, 0x67, + 0xaf, 0xa3, 0xe2, 0x34, 0x88, 0x7e, 0x59, 0xcd, 0x52, 0x07, 0xd7, 0x77, 0xc8, 0x5e, 0xe6, 0x72, 0xed, 0x44, 0xa9, + 0x86, 0x06, 0xce, 0x9f, 0xe4, 0xab, 0xd8, 0x3e, 0xe1, 0x2c, 0x67, 0xa2, 0xca, 0x7e, 0x9d, 0x07, 0xa9, 0x30, 0xe7, + 0xf8, 0xe3, 0xd2, 0x86, 0xe8, 0x2b, 0x22, 0x24, 0xe6, 0xac, 0xfb, 0xce, 0xa6, 0x2c, 0x71, 0xe9, 0xc3, 0x08, 0xa1, + 0x9f, 0x18, 0xa1, 0x19, 0x47, 0x3d, 0x6f, 0xfe, 0xb7, 0x91, 0xef, 0xb3, 0x9e, 0x53, 0x74, 0xc7, 0x7b, 0xb2, 0x1a, + 0x2a, 0xdb, 0xe9, 0x67, 0xee, 0xd4, 0x9e, 0x82, 0x53, 0x7b, 0x82, 0x4a, 0x90, 0xc0, 0xcf, 0x0b, 0xcf, 0xf1, 0xa4, + 0xd9, 0x54, 0x17, 0x4f, 0xdb, 0x5f, 0x8d, 0xcf, 0x2f, 0x95, 0x8d, 0xaf, 0x38, 0xbb, 0x52, 0x68, 0x67, 0x78, 0x4b, + 0x67, 0xae, 0x0c}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index b230f2a906..bd47071dce 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -379,7308 +379,7310 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xd0, 0x69, 0x79, 0x18, 0x5b, 0x98, 0x9e, 0x2f, 0x6e, 0xf7, 0xac, 0x60, 0x80, 0x15, 0xdb, 0xbd, 0x1d, 0x24, 0xa7, 0xea, 0x80, 0x51, 0xc5, 0x36, 0x7f, 0xe1, 0x11, 0x05, 0xdc, 0x30, 0x48, 0x3b, 0x30, 0x72, 0x2a, 0xac, 0xc0, 0x70, 0x75, 0xc3, 0xc7, 0x7a, 0x96, 0xb6, 0x5b, 0xad, 0xef, 0x2a, 0x4c, 0xea, 0xcd, 0xec, 0x92, 0xb6, 0x0b, 0x36, 0xaf, - 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0x76, - 0xa6, 0xcc, 0xc5, 0x8c, 0x15, 0x5c, 0xf7, 0xea, 0x5f, 0x55, 0xc7, 0xbb, 0x73, 0xda, 0x58, 0xf9, 0x78, 0x65, 0x6b, - 0xb8, 0xcb, 0xd8, 0xc7, 0xf0, 0xb1, 0x8b, 0x95, 0x5f, 0x68, 0x11, 0x6f, 0x6d, 0x18, 0x1c, 0xd6, 0x40, 0x9b, 0x60, - 0xce, 0x05, 0x98, 0x8a, 0x0e, 0xf1, 0x57, 0xa0, 0x90, 0xd1, 0x3c, 0x8b, 0x61, 0x44, 0x07, 0xcd, 0x83, 0xd3, 0x82, - 0xcd, 0x91, 0x07, 0x44, 0x72, 0xbf, 0x5b, 0xb0, 0xf9, 0x26, 0x31, 0xd5, 0x57, 0x06, 0x75, 0x69, 0xce, 0xa7, 0x22, - 0xcd, 0x18, 0x6c, 0xab, 0x4d, 0xc2, 0x84, 0xe6, 0xfa, 0xae, 0x59, 0xc8, 0x9b, 0xd5, 0x98, 0xab, 0x45, 0x4e, 0xef, - 0xd2, 0x49, 0xce, 0x6e, 0x7b, 0xa6, 0x54, 0x93, 0x6b, 0x36, 0x57, 0xae, 0x6c, 0x0f, 0xd2, 0x9b, 0x63, 0x6b, 0xce, - 0x01, 0xd0, 0x93, 0x37, 0xdb, 0xfb, 0xda, 0x2f, 0x5a, 0x53, 0x2e, 0xf5, 0x41, 0x4b, 0xf5, 0xe6, 0x5c, 0x34, 0xdd, - 0x40, 0xce, 0x00, 0x23, 0x76, 0x21, 0x1f, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, 0x36, 0x5e, 0x05, 0xd5, 0x3a, - 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x1b, 0xb4, 0xb8, 0x23, 0xd0, 0x57, 0x50, 0xfe, 0x41, 0x0b, 0xdb, - 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xe1, 0xa0, 0xf8, 0xe4, 0xae, 0x09, 0x7f, 0x57, 0xe0, 0xf3, 0xc4, 0x33, - 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, 0x2b, 0x98, 0x7f, 0xda, 0x3a, - 0x68, 0x1d, 0x98, 0xb9, 0xb8, 0x6d, 0x70, 0x76, 0x76, 0xff, 0xf4, 0x01, 0xeb, 0xe5, 0x5c, 0xb0, 0xda, 0x54, 0xbf, - 0x09, 0xea, 0xb0, 0xe1, 0x8e, 0x6b, 0xb8, 0x7d, 0xd0, 0x3e, 0x38, 0x6b, 0x7d, 0xe7, 0xa9, 0x48, 0xce, 0x26, 0xda, - 0xee, 0x9b, 0x1a, 0x59, 0xb9, 0xf0, 0x4d, 0xdf, 0x14, 0x74, 0x91, 0x0a, 0x09, 0x7f, 0x7a, 0xb0, 0xf9, 0x27, 0xb9, - 0xbc, 0x49, 0x67, 0x7c, 0x3c, 0x06, 0x17, 0x2e, 0x28, 0x50, 0x26, 0xb2, 0x3c, 0xe7, 0x0b, 0xc5, 0xed, 0x6a, 0x38, - 0xdc, 0xed, 0x6e, 0x41, 0x35, 0x1c, 0xd0, 0x69, 0x30, 0xa0, 0x6e, 0x35, 0xa0, 0xaa, 0xff, 0x70, 0x84, 0x9d, 0xad, - 0xb9, 0x9a, 0x52, 0xbd, 0x1a, 0x26, 0x7d, 0x5a, 0x2a, 0x0d, 0x30, 0xf7, 0xc6, 0x23, 0xe6, 0x74, 0x69, 0x8e, 0x98, - 0xbe, 0x61, 0x4c, 0x7c, 0x7d, 0x10, 0x57, 0xa9, 0x14, 0xf9, 0x9d, 0xfd, 0x5c, 0x85, 0x5d, 0xd2, 0xa5, 0x96, 0x9b, - 0x64, 0xc4, 0x05, 0x2d, 0xee, 0x3e, 0x2a, 0x26, 0x94, 0x2c, 0x3e, 0xca, 0xc9, 0x64, 0xf5, 0x35, 0x92, 0x77, 0x1f, - 0x6d, 0x12, 0xc5, 0xc5, 0x34, 0x67, 0x96, 0xc0, 0x19, 0x44, 0x70, 0x87, 0x8c, 0x6d, 0xd7, 0x34, 0x59, 0x1b, 0xf4, - 0x26, 0xc9, 0x72, 0x3e, 0xa7, 0x9a, 0x19, 0x38, 0x07, 0xa4, 0xc6, 0x4d, 0xde, 0x52, 0xb9, 0xd6, 0x81, 0xfd, 0x53, - 0x95, 0x86, 0x6d, 0x14, 0x14, 0xf6, 0x4d, 0x72, 0x61, 0xf0, 0xc3, 0x80, 0xc3, 0xec, 0x22, 0xb3, 0x7a, 0x66, 0xed, - 0x02, 0xd8, 0xc1, 0xec, 0x6a, 0x4d, 0x5d, 0x39, 0xba, 0x64, 0x5b, 0xec, 0xb6, 0xbe, 0xab, 0xe7, 0xe6, 0x74, 0xc4, - 0xf2, 0x95, 0xdd, 0xa8, 0x1e, 0xb8, 0x6e, 0xab, 0x86, 0xcb, 0x1c, 0x90, 0x0c, 0x03, 0xa2, 0x61, 0x9a, 0x36, 0x6f, - 0xd8, 0xe8, 0x33, 0xd7, 0x76, 0xcb, 0x34, 0xd5, 0x0d, 0x38, 0x15, 0x99, 0x31, 0x2d, 0x58, 0xb1, 0xf2, 0x84, 0xbc, - 0x55, 0x23, 0xa0, 0xbf, 0x08, 0x73, 0x40, 0x6b, 0x3a, 0x6a, 0x42, 0x88, 0x35, 0x56, 0xac, 0xf6, 0x4d, 0x6e, 0x4e, - 0x6f, 0x1d, 0x8a, 0x3d, 0x68, 0x7d, 0x57, 0x3b, 0x64, 0xcf, 0x5a, 0x2d, 0x7f, 0x44, 0x34, 0x6d, 0x8d, 0xb4, 0x9d, - 0x74, 0xd9, 0xbc, 0x4c, 0xd4, 0x72, 0x91, 0xd6, 0x12, 0x46, 0x52, 0x6b, 0x39, 0xb7, 0x69, 0x7b, 0xa8, 0x51, 0x9d, - 0xf4, 0xb6, 0x3b, 0x8b, 0xdb, 0x03, 0xf3, 0x4f, 0xeb, 0xa0, 0xb5, 0x4b, 0x6a, 0x77, 0xb1, 0xe2, 0x14, 0x79, 0x3c, - 0x86, 0x8e, 0xdb, 0x6c, 0xde, 0x5b, 0x2a, 0x38, 0xee, 0x0d, 0xc4, 0xcd, 0x89, 0xb6, 0x31, 0x93, 0x05, 0xc0, 0x52, - 0x2e, 0xe0, 0x74, 0xb5, 0x87, 0x1d, 0xf4, 0xa1, 0x24, 0x98, 0xc3, 0xef, 0x6d, 0xb4, 0x3e, 0xac, 0xd6, 0x41, 0x35, - 0x30, 0xf8, 0x67, 0xf3, 0x57, 0xc5, 0x9f, 0x3f, 0x61, 0x81, 0x7c, 0xc4, 0x1b, 0x49, 0x77, 0xdd, 0x72, 0x32, 0xd1, - 0x58, 0x57, 0xa2, 0x9a, 0xf1, 0x28, 0x99, 0xd3, 0x5b, 0xeb, 0x5a, 0x32, 0xe7, 0x02, 0x0c, 0xd7, 0x10, 0xd6, 0x81, - 0x89, 0xff, 0x2c, 0x6c, 0x68, 0xac, 0x63, 0x68, 0xf8, 0xb8, 0x93, 0x74, 0xbb, 0x08, 0xb7, 0x70, 0xa7, 0xdb, 0x0d, - 0x64, 0xb2, 0x89, 0xde, 0x57, 0x74, 0x5f, 0x49, 0xb9, 0xa7, 0xe4, 0x89, 0x69, 0xf4, 0xa4, 0xdd, 0x6a, 0x61, 0xe3, - 0x3e, 0x5f, 0x16, 0x16, 0x6a, 0x4f, 0xb3, 0xed, 0x56, 0x0b, 0x9a, 0x85, 0x3f, 0x6e, 0x5e, 0x3f, 0x91, 0x55, 0x2b, - 0x6d, 0xe1, 0x76, 0xda, 0xc6, 0x9d, 0xb4, 0x83, 0x4f, 0xd3, 0x53, 0x7c, 0x96, 0x9e, 0xe1, 0x6e, 0xda, 0xc5, 0xe7, - 0xe9, 0x39, 0xbe, 0x9f, 0xde, 0xc7, 0x17, 0xe9, 0x05, 0x7e, 0x90, 0x3e, 0xc0, 0x0f, 0xd3, 0x76, 0x0b, 0x3f, 0x4a, - 0xdb, 0x6d, 0xfc, 0x38, 0x6d, 0x77, 0xf0, 0x93, 0xb4, 0x7d, 0x8a, 0x9f, 0xa6, 0xed, 0x33, 0xfc, 0x2c, 0x6d, 0x77, - 0x31, 0x85, 0xdc, 0x11, 0xe4, 0x66, 0x90, 0x3b, 0x86, 0x5c, 0x06, 0xb9, 0x93, 0xb4, 0xdd, 0xdd, 0x60, 0x69, 0x43, - 0x6e, 0x44, 0xad, 0x76, 0xe7, 0xf4, 0xac, 0x7b, 0x7e, 0xff, 0xe2, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x7d, 0x16, - 0x0d, 0xf1, 0x9d, 0xf1, 0x7c, 0x91, 0x62, 0xc0, 0x8f, 0xda, 0xdd, 0x21, 0xbe, 0xf5, 0x9f, 0x31, 0x3f, 0xea, 0x9c, - 0xb5, 0xd0, 0xd5, 0xd5, 0xd9, 0xb0, 0x51, 0xe6, 0x3e, 0x32, 0x0e, 0x37, 0x55, 0x16, 0x21, 0x24, 0x86, 0x1c, 0x84, - 0xbf, 0x58, 0x07, 0x1a, 0x16, 0xf3, 0xa4, 0x40, 0x47, 0x47, 0xe6, 0xc7, 0xd4, 0xff, 0x18, 0xf9, 0x1f, 0x34, 0x58, - 0xa4, 0x1b, 0x1a, 0x3b, 0x8f, 0x6b, 0x5d, 0xfa, 0x3b, 0x94, 0xa6, 0x44, 0x07, 0xdc, 0x19, 0xf5, 0xff, 0x57, 0x64, - 0x8d, 0x76, 0xc8, 0x99, 0x55, 0x8c, 0x75, 0xfb, 0x8c, 0xac, 0x8a, 0xb4, 0xd3, 0xed, 0x1e, 0xfd, 0x34, 0xe0, 0x83, - 0xf6, 0x70, 0x78, 0xdc, 0xbe, 0x8f, 0xa7, 0x65, 0x42, 0xc7, 0x26, 0x8c, 0xca, 0x84, 0x53, 0x9b, 0x40, 0x53, 0x5b, - 0x1b, 0x92, 0xce, 0x4c, 0x12, 0x94, 0xd8, 0xa4, 0xa6, 0xed, 0xfb, 0xb6, 0xed, 0x07, 0x60, 0x4d, 0x66, 0x9a, 0x77, - 0x4d, 0x5f, 0x5e, 0x9e, 0xad, 0x5d, 0xa3, 0x78, 0x9a, 0xba, 0xd6, 0x7c, 0xe2, 0xd9, 0x70, 0x88, 0x47, 0x26, 0xb1, - 0x5b, 0x25, 0x9e, 0x0f, 0x87, 0xae, 0xab, 0x07, 0xa6, 0xab, 0xfb, 0x55, 0xd6, 0xc5, 0x70, 0x68, 0xba, 0x44, 0x2e, - 0x76, 0x80, 0xd2, 0x07, 0x9f, 0x4b, 0xfd, 0x0d, 0xbf, 0xec, 0x74, 0xbb, 0x7d, 0xc0, 0x30, 0x63, 0x13, 0xec, 0x61, - 0x74, 0x1d, 0xc0, 0xe8, 0x0b, 0xfc, 0xee, 0xdf, 0xd1, 0xf4, 0x96, 0x96, 0x40, 0xea, 0x47, 0xff, 0x15, 0x35, 0xb4, - 0x81, 0xb9, 0xf9, 0x33, 0xb5, 0x7f, 0x46, 0xa8, 0xf1, 0x99, 0x02, 0xb8, 0x41, 0x23, 0xe5, 0x55, 0xca, 0xa6, 0xc7, - 0x5f, 0x28, 0xb8, 0xf8, 0xcc, 0x54, 0x4e, 0xfb, 0xeb, 0xd9, 0xcd, 0x68, 0x3d, 0x53, 0x5f, 0xd0, 0x9f, 0xf1, 0x9f, - 0xea, 0x38, 0x1e, 0x34, 0x1b, 0x09, 0xfb, 0x73, 0x0c, 0xbe, 0x44, 0xfd, 0x74, 0xcc, 0xa6, 0xa8, 0x3f, 0xf8, 0x53, - 0xe1, 0x61, 0x23, 0xc8, 0xf8, 0x6e, 0x37, 0x05, 0x3c, 0x8d, 0xb6, 0x13, 0xe3, 0xef, 0x50, 0x1f, 0xf5, 0xff, 0x54, - 0xc7, 0x7f, 0xa2, 0x7b, 0x27, 0x81, 0xd6, 0x44, 0xba, 0x2d, 0x5c, 0x85, 0x1f, 0x3a, 0x2e, 0xb7, 0x30, 0xc3, 0xed, - 0x26, 0x83, 0x60, 0x6d, 0xe0, 0x8a, 0x4e, 0x62, 0xd9, 0xe0, 0x27, 0xa7, 0x2d, 0xf4, 0x5d, 0xbb, 0x03, 0xca, 0x95, - 0xa6, 0x38, 0xde, 0xdd, 0xf4, 0x45, 0xf3, 0x14, 0x3f, 0x68, 0x16, 0xb8, 0x8d, 0x70, 0xb3, 0xed, 0xb5, 0xde, 0x03, - 0x15, 0xb7, 0x10, 0x56, 0xf1, 0x05, 0xfc, 0x73, 0x86, 0x86, 0xd5, 0x86, 0x7c, 0x4c, 0xb7, 0x7b, 0x07, 0xbf, 0x59, - 0x12, 0xab, 0x06, 0x3f, 0x39, 0x6f, 0xa1, 0xef, 0xce, 0x4d, 0x47, 0xec, 0x58, 0xef, 0xe9, 0x4a, 0xe2, 0xb3, 0xa6, - 0x84, 0x8e, 0x5a, 0x65, 0x3f, 0x22, 0xee, 0x22, 0x2c, 0xe2, 0x53, 0xf8, 0xa7, 0x1d, 0xf6, 0x73, 0x6f, 0xa7, 0x1f, - 0x33, 0xef, 0x36, 0x4e, 0xba, 0xd6, 0x0d, 0x57, 0xd9, 0x3b, 0xf1, 0x06, 0xbb, 0x6a, 0x9b, 0xcb, 0xbc, 0xf6, 0x09, - 0x7c, 0x20, 0xac, 0x8f, 0x89, 0xc2, 0xec, 0x18, 0xfc, 0x77, 0xc1, 0x6c, 0x45, 0x5d, 0x9e, 0xf6, 0x54, 0xa3, 0x81, - 0xc4, 0x40, 0x0d, 0x8f, 0x49, 0xbb, 0xa9, 0x9b, 0x0c, 0xc3, 0xef, 0x06, 0x29, 0x83, 0xc2, 0x89, 0xaa, 0xd7, 0x57, - 0xae, 0x57, 0x7b, 0xf3, 0xef, 0xb1, 0x83, 0x10, 0xa2, 0xfa, 0xb1, 0x6e, 0x32, 0x74, 0x22, 0x1a, 0xb1, 0xbe, 0x64, - 0xfd, 0xf3, 0xb4, 0x85, 0x0c, 0x76, 0xaa, 0x7e, 0xcc, 0x9a, 0x1c, 0xd2, 0x3b, 0x69, 0xcc, 0x9b, 0x1a, 0x7e, 0x9d, - 0x05, 0xd0, 0x12, 0x80, 0x77, 0x95, 0x37, 0x52, 0x71, 0xd2, 0xe9, 0x76, 0xb1, 0x20, 0x3c, 0x99, 0x9a, 0x5f, 0x8a, - 0xf0, 0x64, 0x64, 0x7e, 0x49, 0x52, 0xc2, 0xcb, 0xf6, 0x8e, 0x0b, 0x12, 0xac, 0xaa, 0x49, 0xa1, 0xb0, 0xa0, 0x05, - 0x3a, 0xe9, 0x78, 0xb3, 0x00, 0x3c, 0xf3, 0x73, 0x00, 0x35, 0x48, 0x61, 0x2c, 0x42, 0x65, 0xb3, 0xc0, 0x39, 0xa1, - 0x57, 0x49, 0xb7, 0x3f, 0x3b, 0x89, 0x3b, 0x4d, 0xd9, 0x2c, 0x50, 0x3a, 0x3b, 0x31, 0x35, 0x71, 0x46, 0x5e, 0x51, - 0xdb, 0x1a, 0x9e, 0xc1, 0x5d, 0x6e, 0x46, 0xb2, 0xe3, 0xf3, 0x56, 0x23, 0xe9, 0x22, 0x3c, 0xc8, 0xd6, 0x2d, 0x9c, - 0xaf, 0xd7, 0x2d, 0x4c, 0xc3, 0x65, 0x10, 0x1e, 0x20, 0xa5, 0xa6, 0x6e, 0x3b, 0x36, 0x4f, 0x9f, 0xc7, 0x1a, 0xec, - 0x12, 0x34, 0x78, 0xfb, 0x68, 0xf0, 0x43, 0x4a, 0xb9, 0xbb, 0x10, 0x44, 0x26, 0x3a, 0xe1, 0x24, 0xd4, 0xdd, 0xbd, - 0x12, 0x7e, 0x5d, 0xdd, 0xc8, 0xef, 0x89, 0xf8, 0x83, 0xc4, 0x36, 0xad, 0x2a, 0xf6, 0x9a, 0xee, 0x16, 0xbb, 0x47, - 0x77, 0x8a, 0x3d, 0xdc, 0x53, 0xec, 0xf1, 0x6e, 0xb1, 0xbf, 0x65, 0xa0, 0x69, 0xe4, 0xdf, 0x9d, 0x9e, 0xb7, 0x1a, - 0xa7, 0x80, 0xac, 0xa7, 0xe7, 0xad, 0xaa, 0xd0, 0x53, 0x5a, 0xad, 0x95, 0x26, 0xbf, 0x50, 0xeb, 0x6b, 0xc1, 0xbd, - 0xd3, 0xb7, 0x59, 0x38, 0xeb, 0x72, 0x5e, 0xfa, 0x97, 0x0f, 0xba, 0x60, 0xcb, 0x22, 0x0c, 0xb5, 0xd3, 0x83, 0xf3, - 0x61, 0x7f, 0xc6, 0xe2, 0x06, 0xa4, 0xa2, 0x74, 0xa2, 0xdd, 0x2f, 0x54, 0x5e, 0x69, 0xff, 0x2d, 0x21, 0xa9, 0x33, - 0x44, 0x58, 0x92, 0x86, 0x1e, 0x9c, 0x0e, 0xcd, 0x79, 0x57, 0xc0, 0xef, 0x33, 0xf3, 0xbb, 0x54, 0x28, 0x39, 0x87, - 0x8c, 0xd9, 0xcd, 0x28, 0xea, 0x0b, 0xf2, 0x9a, 0xc6, 0xc6, 0xc6, 0x1e, 0xa5, 0x65, 0x86, 0xfa, 0x02, 0x19, 0x0f, - 0xcb, 0x0c, 0x41, 0x5e, 0x09, 0xf7, 0x1b, 0xaf, 0x8a, 0x14, 0xec, 0x6d, 0xf0, 0x34, 0x05, 0x5b, 0x1b, 0x3c, 0x4a, - 0x05, 0xf8, 0x83, 0xd0, 0x94, 0x05, 0x56, 0xfc, 0x2f, 0x9c, 0x06, 0xcf, 0xdc, 0x3a, 0x13, 0x83, 0xa5, 0x3d, 0x06, - 0x27, 0xc5, 0xdf, 0x32, 0x86, 0xbf, 0x0d, 0x8d, 0x30, 0x83, 0x36, 0x19, 0xc2, 0x3c, 0x29, 0x08, 0xa4, 0x61, 0x9e, - 0x4c, 0x09, 0x83, 0x26, 0x79, 0x32, 0x22, 0x6c, 0xd0, 0x09, 0xd0, 0xe4, 0x89, 0x81, 0x1d, 0x00, 0x87, 0xd7, 0x2f, - 0xf2, 0xb5, 0x6d, 0x1c, 0x2c, 0x04, 0xa0, 0x09, 0x41, 0x20, 0xe6, 0xc2, 0x00, 0xcc, 0x46, 0x94, 0xfd, 0xd9, 0xa9, - 0xc2, 0x5f, 0xf2, 0x84, 0x1a, 0xea, 0xfd, 0x17, 0x90, 0xd5, 0xf8, 0xde, 0x8a, 0x6d, 0xf0, 0xc1, 0xbd, 0x95, 0xd8, - 0x7c, 0x07, 0x7f, 0x94, 0xfd, 0x03, 0xcc, 0x43, 0x42, 0xd1, 0x06, 0xfd, 0x95, 0x42, 0xb1, 0x3d, 0xa5, 0xd0, 0x5f, - 0x8e, 0x44, 0x2b, 0x45, 0x56, 0xb7, 0x69, 0x34, 0xa6, 0xc5, 0xe7, 0x08, 0xff, 0x91, 0x46, 0x39, 0x70, 0x8b, 0x11, - 0xfe, 0x90, 0x46, 0x05, 0x8b, 0xf0, 0xef, 0x69, 0x34, 0xca, 0x97, 0x11, 0xfe, 0x2d, 0x8d, 0xa6, 0x45, 0x84, 0xdf, - 0x83, 0xb2, 0x76, 0xcc, 0x97, 0xf3, 0x08, 0xbf, 0x4b, 0x23, 0x65, 0xbc, 0x21, 0xf0, 0xc3, 0x34, 0x62, 0x2c, 0xc2, - 0x6f, 0xd3, 0x48, 0xe6, 0x11, 0xbe, 0x4e, 0x23, 0x59, 0x44, 0xf8, 0x51, 0x1a, 0x15, 0x34, 0xc2, 0x8f, 0xd3, 0x08, - 0x0a, 0x4d, 0x23, 0xfc, 0x24, 0x8d, 0xa0, 0x65, 0x15, 0xe1, 0x37, 0x69, 0xc4, 0x45, 0x84, 0x7f, 0x4d, 0x23, 0xbd, - 0x2c, 0xfe, 0x5e, 0x4a, 0xae, 0x22, 0xfc, 0x34, 0x8d, 0x66, 0x3c, 0xc2, 0xaf, 0xd3, 0xa8, 0x90, 0x11, 0x7e, 0x95, - 0x46, 0x34, 0x8f, 0xf0, 0xcb, 0x34, 0xca, 0x59, 0x84, 0x7f, 0x49, 0xa3, 0x31, 0x8b, 0xf0, 0xcf, 0x69, 0x74, 0xc7, - 0xf2, 0x5c, 0x46, 0xf8, 0x59, 0x1a, 0x31, 0x11, 0xe1, 0x9f, 0xd2, 0x28, 0x9b, 0x45, 0xf8, 0x87, 0x34, 0xa2, 0xc5, - 0x67, 0x15, 0xe1, 0xe7, 0x69, 0xc4, 0x68, 0x84, 0x5f, 0xd8, 0x8e, 0xa6, 0x11, 0xfe, 0x31, 0x8d, 0x6e, 0x66, 0xd1, - 0x06, 0x4b, 0x45, 0x56, 0xaf, 0x78, 0xc6, 0x7e, 0x67, 0x69, 0x34, 0x69, 0x4d, 0x2e, 0x26, 0x93, 0x08, 0x53, 0xa1, - 0xf9, 0xdf, 0x4b, 0x76, 0xf3, 0x54, 0x43, 0x22, 0x65, 0xa3, 0xf1, 0xfd, 0x08, 0xd3, 0xbf, 0x97, 0x34, 0x8d, 0x26, - 0x13, 0x53, 0xe0, 0xef, 0x25, 0x9d, 0xd3, 0xe2, 0x0d, 0x4b, 0xa3, 0xfb, 0x93, 0xc9, 0x64, 0x7c, 0x16, 0x61, 0xfa, - 0xcf, 0xf2, 0x83, 0x69, 0xc1, 0x14, 0x18, 0x31, 0x3e, 0x85, 0xba, 0xdd, 0x49, 0x77, 0x9c, 0x45, 0x78, 0xc4, 0xd5, - 0xdf, 0x4b, 0xf8, 0x9e, 0xb0, 0xb3, 0xec, 0x2c, 0xc2, 0xa3, 0x9c, 0x66, 0x9f, 0xd3, 0xa8, 0x65, 0x7e, 0x89, 0x9f, - 0xd8, 0xf8, 0xd5, 0x5c, 0x9a, 0xab, 0x8c, 0x09, 0x1b, 0x65, 0xe3, 0x08, 0x9b, 0xc1, 0x4c, 0xe0, 0xef, 0x17, 0xfe, - 0x96, 0xe9, 0x34, 0xba, 0xa0, 0x9d, 0x11, 0xeb, 0x44, 0x78, 0xf4, 0xfa, 0x46, 0xa4, 0x11, 0xed, 0x76, 0x68, 0x87, - 0x46, 0x78, 0xb4, 0x2c, 0xf2, 0xbb, 0x1b, 0x29, 0xc7, 0x00, 0x84, 0xd1, 0xc5, 0xc5, 0xfd, 0x08, 0x67, 0xf4, 0x17, - 0x0d, 0xb5, 0xbb, 0x93, 0x07, 0x8c, 0xb6, 0x22, 0xfc, 0x13, 0x2d, 0xf4, 0x87, 0xa5, 0x72, 0x03, 0x6d, 0x41, 0x8a, - 0xcc, 0xde, 0x82, 0x9a, 0x3f, 0x1a, 0x77, 0xce, 0x1f, 0xb4, 0x59, 0x84, 0xb3, 0xeb, 0x57, 0xd0, 0xdb, 0xfd, 0x49, - 0xb7, 0x05, 0x1f, 0x02, 0xe4, 0x52, 0x56, 0x40, 0x23, 0xe7, 0x67, 0x0f, 0xba, 0x6c, 0x6c, 0x12, 0x15, 0xcf, 0x3f, - 0x9b, 0xd9, 0x5f, 0xc0, 0x7c, 0xb2, 0x82, 0xcf, 0x95, 0x14, 0x69, 0x34, 0xce, 0xda, 0x67, 0xa7, 0x90, 0x70, 0x47, - 0x85, 0x07, 0xce, 0x2d, 0x54, 0xbd, 0x18, 0x45, 0xf8, 0xd6, 0xa6, 0x5e, 0x8c, 0xcc, 0xc7, 0xf4, 0xed, 0x2f, 0xe2, - 0xf5, 0x38, 0x8d, 0x46, 0x17, 0x17, 0xe7, 0x2d, 0x48, 0xf8, 0x8d, 0xde, 0xa5, 0x11, 0x7d, 0x00, 0xff, 0x41, 0xf6, - 0x87, 0x67, 0xd0, 0x21, 0x8c, 0xf0, 0x76, 0xfa, 0x21, 0xcc, 0xf9, 0x3c, 0xa3, 0x9f, 0x79, 0x1a, 0x8d, 0xc6, 0xa3, - 0xfb, 0xe7, 0x50, 0x6f, 0x4e, 0xa7, 0xcf, 0x34, 0x85, 0x76, 0x5b, 0x2d, 0xd3, 0xf2, 0x5b, 0xfe, 0x85, 0x99, 0xea, - 0xdd, 0xee, 0xf9, 0xa8, 0x03, 0x23, 0xb8, 0x06, 0x85, 0x0a, 0x8c, 0xe7, 0x22, 0x33, 0x0d, 0x5e, 0x67, 0x4f, 0xc7, - 0x69, 0xf4, 0xe0, 0xc1, 0x69, 0x27, 0xcb, 0x22, 0x7c, 0xfb, 0x61, 0x6c, 0x6b, 0x9b, 0x3c, 0x05, 0xb0, 0x4f, 0x23, - 0xf6, 0xe0, 0xc1, 0xf9, 0x7d, 0x0a, 0xdf, 0xcf, 0x4d, 0x5b, 0x17, 0x93, 0x51, 0x76, 0x01, 0x6d, 0xbd, 0x83, 0xe9, - 0x9c, 0x5d, 0x9c, 0x8e, 0x4d, 0x5f, 0xef, 0xcc, 0xa8, 0x3b, 0x93, 0xb3, 0xc9, 0x99, 0xc9, 0x34, 0x43, 0x2d, 0x3f, - 0x7f, 0x65, 0x69, 0x94, 0xb1, 0x71, 0x3b, 0xc2, 0xb7, 0x6e, 0xe1, 0x1e, 0x9c, 0xb5, 0x5a, 0xe3, 0xd3, 0x08, 0x8f, - 0x1f, 0x2e, 0x16, 0x6f, 0x0c, 0x04, 0xdb, 0x67, 0x0f, 0xec, 0xb7, 0xfa, 0x7c, 0x07, 0x4d, 0x8f, 0x0c, 0xd0, 0xc6, - 0x7c, 0x6e, 0x5a, 0x3e, 0x7f, 0x00, 0xff, 0x99, 0x6f, 0xd3, 0x74, 0xf9, 0x2d, 0xc7, 0x53, 0xbb, 0x28, 0x6d, 0xf6, - 0xa0, 0x05, 0x35, 0x26, 0xfc, 0xc3, 0xa8, 0xe0, 0x80, 0x46, 0xa3, 0x0e, 0xfc, 0x5f, 0x84, 0x27, 0xf9, 0xf5, 0x2b, - 0x87, 0xb3, 0x93, 0x09, 0x9d, 0xb4, 0x22, 0x3c, 0x91, 0x1f, 0x94, 0xfe, 0xed, 0xa1, 0x48, 0xa3, 0x4e, 0xe7, 0x62, - 0x64, 0xca, 0x2c, 0x7f, 0x52, 0xdc, 0xe0, 0x71, 0xcb, 0xb4, 0x32, 0xa5, 0x6f, 0xd4, 0xe8, 0x5a, 0xc2, 0x4a, 0xc2, - 0x7f, 0x11, 0x9e, 0x82, 0x16, 0xce, 0xb5, 0x72, 0x61, 0xb7, 0xc3, 0xf4, 0xad, 0x41, 0xcd, 0xf1, 0x7d, 0x80, 0x97, - 0x5f, 0xc6, 0x31, 0xa5, 0xdd, 0x4e, 0x2b, 0xc2, 0x66, 0xd4, 0x17, 0x2d, 0xf8, 0x2f, 0xc2, 0x16, 0x72, 0x06, 0xae, - 0xd3, 0x0f, 0xcf, 0x7e, 0xbe, 0x49, 0x23, 0x3a, 0x9e, 0x4c, 0x60, 0x49, 0xcc, 0x64, 0x7c, 0xb1, 0x99, 0x14, 0xec, - 0xee, 0x97, 0x1b, 0xb7, 0x5d, 0x4c, 0x82, 0x76, 0xd0, 0x39, 0x7f, 0x30, 0x3a, 0x8b, 0xf0, 0x9b, 0x31, 0xa7, 0x02, - 0x56, 0x29, 0x1b, 0x77, 0xb3, 0x6e, 0x66, 0x12, 0xa6, 0x32, 0x8d, 0xce, 0x60, 0xc9, 0x3b, 0x11, 0xe6, 0x5f, 0xae, - 0xef, 0x2c, 0xba, 0x41, 0x6d, 0x87, 0x20, 0x93, 0x16, 0x3b, 0xbf, 0xc8, 0x22, 0x9c, 0xd3, 0x2f, 0xcf, 0x7e, 0x29, - 0xd2, 0x88, 0x9d, 0xb3, 0xf3, 0x09, 0xf5, 0xdf, 0xbf, 0xab, 0x99, 0xa9, 0xd1, 0x9a, 0x74, 0x21, 0xe9, 0x46, 0x98, - 0xb1, 0xde, 0xcf, 0x26, 0x06, 0x43, 0x5e, 0xce, 0xa5, 0xc8, 0x9e, 0x4e, 0x26, 0xd2, 0x62, 0x31, 0x85, 0x4d, 0xf8, - 0x07, 0x40, 0x9b, 0x8e, 0xc7, 0x17, 0xec, 0x3c, 0xc2, 0x7f, 0xd8, 0x5d, 0xe2, 0x26, 0xf0, 0x87, 0xc5, 0x6c, 0xe6, - 0x76, 0xfb, 0x1f, 0x16, 0x28, 0x30, 0xdf, 0x09, 0x9d, 0xd0, 0x71, 0x27, 0xc2, 0x7f, 0x18, 0xb8, 0x8c, 0x4f, 0xe1, - 0x3f, 0x28, 0x00, 0x9d, 0x3d, 0x68, 0x31, 0xf6, 0xa0, 0x65, 0xbe, 0xc2, 0x3c, 0x37, 0xf3, 0xd1, 0x79, 0xd6, 0x8e, - 0xf0, 0x1f, 0x0e, 0x1d, 0x27, 0x13, 0xda, 0x02, 0x74, 0xfc, 0xc3, 0xa1, 0x63, 0xa7, 0x35, 0xea, 0x50, 0xf3, 0x6d, - 0xb1, 0xe6, 0xe2, 0x7e, 0xc6, 0x60, 0x72, 0x7f, 0x58, 0x84, 0xbc, 0x7f, 0xff, 0xe2, 0xe2, 0xc1, 0x03, 0xf8, 0x34, - 0x6d, 0x97, 0x9f, 0x4a, 0x3f, 0xcc, 0x0d, 0x92, 0xb5, 0xb2, 0x33, 0xa0, 0x93, 0x7f, 0x98, 0x31, 0x4e, 0x26, 0x13, - 0xd6, 0x8a, 0x70, 0xce, 0xe7, 0xcc, 0x62, 0x82, 0xfd, 0x6d, 0x3a, 0x3a, 0xed, 0x64, 0xe3, 0xd3, 0x4e, 0x84, 0xf3, - 0x37, 0xcf, 0xcc, 0x6c, 0x5a, 0x30, 0x7b, 0xbf, 0xe5, 0x3c, 0xd6, 0xcc, 0xe9, 0x6b, 0x18, 0x24, 0xac, 0x34, 0x54, - 0x7e, 0x1f, 0xd0, 0xc3, 0xf3, 0xf3, 0x6c, 0x0c, 0x03, 0x7d, 0x0f, 0xdd, 0x02, 0x18, 0xdf, 0xdb, 0xcd, 0x37, 0xa2, - 0xdd, 0x2e, 0x4c, 0xf7, 0xfd, 0x62, 0x59, 0x2c, 0x5e, 0xa6, 0xd1, 0x83, 0xd3, 0xfb, 0xad, 0xf1, 0x28, 0xc2, 0xef, - 0xdd, 0x04, 0x4f, 0xb3, 0xd1, 0xe9, 0xfd, 0x76, 0x84, 0xdf, 0x9b, 0xfd, 0x76, 0x7f, 0x74, 0x7e, 0x01, 0xe7, 0xc6, - 0x7b, 0xb5, 0x28, 0xde, 0x4c, 0x4d, 0x81, 0x09, 0x7d, 0x00, 0xcd, 0xfe, 0x6a, 0x76, 0xe3, 0xb8, 0x0d, 0x1b, 0xf9, - 0xbd, 0xd9, 0x64, 0x06, 0x4f, 0xee, 0xb7, 0xbb, 0x17, 0xdd, 0x08, 0xcf, 0xf9, 0x58, 0x00, 0x81, 0x37, 0x1b, 0xe5, - 0x41, 0xfb, 0xc1, 0xfd, 0x56, 0x84, 0xe7, 0x6f, 0x74, 0xf6, 0x81, 0xce, 0x0d, 0x35, 0x9e, 0x00, 0xcc, 0xe6, 0x5c, - 0xe9, 0xbb, 0xd7, 0xca, 0xd1, 0x63, 0xd6, 0x8e, 0xf0, 0x5c, 0x66, 0x19, 0x55, 0x6f, 0x6c, 0xc2, 0xa8, 0x1b, 0x61, - 0x41, 0xbf, 0xd0, 0x4f, 0xd2, 0x6f, 0xa6, 0x31, 0xa3, 0x63, 0x93, 0x66, 0x70, 0x38, 0xc2, 0x6f, 0xc7, 0x70, 0x19, - 0x99, 0x46, 0x93, 0xf1, 0xa4, 0x0b, 0xe0, 0x01, 0x02, 0x64, 0xb1, 0x1b, 0xa0, 0x01, 0x5f, 0xe3, 0x47, 0xa3, 0x34, - 0x3a, 0x1f, 0x5d, 0xb0, 0xce, 0x69, 0x84, 0x4b, 0x6a, 0x44, 0xbb, 0x90, 0x6f, 0x3e, 0x3f, 0x98, 0x2d, 0x75, 0x66, - 0x13, 0x0c, 0x80, 0xc6, 0xf4, 0x7e, 0x6b, 0x7c, 0x1e, 0xe1, 0xc5, 0x2b, 0xe6, 0xf7, 0x18, 0x63, 0xec, 0x02, 0x60, - 0x09, 0x49, 0x06, 0x81, 0x2e, 0x26, 0xa3, 0x07, 0x17, 0xe6, 0x1b, 0xc0, 0x40, 0x27, 0x8c, 0x01, 0x90, 0x16, 0xaf, - 0x58, 0x09, 0x88, 0xf1, 0xe8, 0x7e, 0x0b, 0xe8, 0xcb, 0x82, 0x2e, 0xe8, 0x1d, 0xbd, 0x79, 0xba, 0x30, 0x73, 0x9a, - 0x8c, 0xbb, 0x11, 0x5e, 0x3c, 0xff, 0x69, 0xb1, 0x9c, 0x4c, 0xcc, 0x84, 0xe8, 0xe8, 0x41, 0x84, 0x17, 0xac, 0x58, - 0xc2, 0x1a, 0x5d, 0x74, 0x4f, 0x27, 0x11, 0x76, 0x68, 0x98, 0xb5, 0xb2, 0x11, 0xdc, 0xb6, 0x2e, 0xe7, 0x69, 0x34, - 0x1e, 0xd3, 0xd6, 0x18, 0xee, 0x5e, 0xe5, 0xcd, 0x2f, 0x85, 0x45, 0x23, 0x66, 0xf0, 0xc1, 0xad, 0x21, 0xcc, 0x17, - 0xe0, 0xf1, 0x61, 0xc4, 0xb2, 0x8c, 0xba, 0xc4, 0xf3, 0xf3, 0xd3, 0x53, 0xc0, 0x3d, 0x3b, 0x43, 0x8b, 0x20, 0xaf, - 0xd5, 0xdd, 0xa8, 0x90, 0x70, 0x74, 0x01, 0x51, 0x05, 0xb2, 0xfa, 0xfa, 0xee, 0x95, 0xa1, 0xab, 0xed, 0xf3, 0x07, - 0xb0, 0x00, 0x8a, 0x8e, 0xc7, 0x2f, 0xed, 0xe1, 0x76, 0x31, 0x3a, 0xeb, 0xb6, 0x4f, 0x23, 0xec, 0x37, 0x02, 0xbd, - 0x68, 0xdd, 0xef, 0x40, 0x09, 0x31, 0xbe, 0xb3, 0x25, 0x26, 0x67, 0xf4, 0xec, 0xbc, 0x15, 0x61, 0xbf, 0x35, 0xd8, - 0xc5, 0xa8, 0x7b, 0x1f, 0x3e, 0xd5, 0x8c, 0xe5, 0xb9, 0xc1, 0xef, 0x2e, 0xc0, 0x45, 0xf1, 0x67, 0x82, 0xa6, 0x11, - 0x6d, 0x75, 0x3b, 0x9d, 0x31, 0x7c, 0xe6, 0x5f, 0x58, 0x91, 0x46, 0x59, 0x0b, 0xfe, 0x8b, 0x70, 0xb0, 0x93, 0xd8, - 0x28, 0xc2, 0x06, 0xef, 0xce, 0x69, 0xd7, 0xec, 0x7d, 0xb7, 0xab, 0x5a, 0x17, 0x2d, 0xd8, 0xb0, 0x6e, 0x53, 0xb9, - 0x2f, 0x25, 0xe4, 0x8d, 0x23, 0xb1, 0x34, 0xc2, 0x01, 0x82, 0x4e, 0xee, 0x4f, 0x22, 0xec, 0x77, 0xdc, 0xd9, 0xf9, - 0x45, 0x07, 0x48, 0x99, 0x06, 0x42, 0x31, 0xee, 0x8c, 0xce, 0x80, 0x34, 0x69, 0xf6, 0xca, 0xe2, 0x49, 0x84, 0xf5, - 0x53, 0xa5, 0x5f, 0xa6, 0xd1, 0xf8, 0x62, 0x34, 0x19, 0x5f, 0x44, 0x58, 0xcb, 0x39, 0xd5, 0xd2, 0x50, 0xc0, 0xd3, - 0xb3, 0xfb, 0x11, 0x36, 0x68, 0xde, 0x62, 0xad, 0x71, 0x2b, 0xc2, 0xee, 0x28, 0x61, 0xec, 0xa2, 0x03, 0xd3, 0xfa, - 0xf1, 0xb9, 0x06, 0x5c, 0x1e, 0xb3, 0xd1, 0x69, 0x84, 0x4b, 0x7a, 0x6f, 0x08, 0x11, 0x7c, 0xa9, 0xb9, 0xfc, 0xec, - 0x58, 0x0f, 0x20, 0x75, 0x7e, 0xc3, 0xc3, 0x32, 0xfc, 0x7c, 0x63, 0xd1, 0x88, 0x9a, 0x2d, 0x1e, 0xdc, 0x46, 0xbf, - 0xa5, 0xb1, 0x67, 0xdb, 0x39, 0x59, 0x6d, 0x70, 0x19, 0xe4, 0xf5, 0x33, 0xbb, 0x53, 0xb1, 0x54, 0x86, 0x93, 0x0d, - 0x52, 0x94, 0x42, 0xde, 0xad, 0xc1, 0x79, 0xae, 0x82, 0x20, 0x29, 0x48, 0xab, 0x27, 0x2e, 0xbd, 0x37, 0x6d, 0x4f, - 0x40, 0xe8, 0x07, 0x48, 0x2f, 0x08, 0x25, 0x1a, 0x22, 0xe4, 0x58, 0x61, 0xd2, 0x3b, 0x19, 0x18, 0x99, 0x52, 0x5a, - 0xb7, 0x05, 0x4a, 0xa8, 0x8f, 0x8d, 0x1f, 0x4b, 0xac, 0x20, 0x7a, 0x14, 0xea, 0x49, 0x62, 0x22, 0x5d, 0xbf, 0x10, - 0x3a, 0x96, 0x6a, 0x50, 0x0c, 0x71, 0xfb, 0x1c, 0x61, 0x88, 0x21, 0x41, 0x06, 0xf2, 0xea, 0xaa, 0x7d, 0x7e, 0x64, - 0x84, 0xbe, 0xab, 0xab, 0x0b, 0xfb, 0x03, 0xfe, 0x1d, 0x56, 0x71, 0xbb, 0x61, 0x7c, 0xef, 0x59, 0x35, 0xc7, 0x9f, - 0x0d, 0x7f, 0xfd, 0x9e, 0xad, 0xd7, 0xf1, 0x7b, 0x46, 0x60, 0xc6, 0xf8, 0x3d, 0x4b, 0xcc, 0x1d, 0x89, 0xf5, 0x10, - 0x22, 0x03, 0xd0, 0x9c, 0xb5, 0x30, 0x44, 0x93, 0xf7, 0x9c, 0xf7, 0x7b, 0x36, 0xe0, 0x75, 0xef, 0xf2, 0x2a, 0x84, - 0xf3, 0xd1, 0xd1, 0xaa, 0x48, 0xb5, 0x15, 0x13, 0xb4, 0x15, 0x13, 0xb4, 0x15, 0x13, 0x74, 0x15, 0x44, 0xff, 0xac, - 0x0f, 0x52, 0x8a, 0x51, 0xb6, 0x38, 0x9e, 0xfa, 0x0d, 0xa8, 0x3d, 0x40, 0x3b, 0xd9, 0xaf, 0x94, 0x1d, 0xa5, 0xae, - 0x62, 0xaf, 0x02, 0x63, 0x6f, 0xa2, 0xd3, 0x76, 0x9c, 0xfc, 0x3b, 0xea, 0x8e, 0x67, 0x35, 0xb1, 0xec, 0xcd, 0x5e, - 0xb1, 0x0c, 0x56, 0xd2, 0x88, 0x66, 0x87, 0x36, 0x1e, 0x89, 0x1e, 0xdc, 0x37, 0x82, 0x59, 0x15, 0x24, 0xaf, 0x01, - 0x49, 0x3d, 0x90, 0x42, 0x2e, 0x8c, 0x94, 0x56, 0xa0, 0x74, 0xac, 0xe3, 0x02, 0x34, 0x94, 0x5e, 0x41, 0x59, 0xc6, - 0x72, 0x6d, 0x18, 0x80, 0x28, 0x2b, 0xa3, 0x59, 0x59, 0xad, 0x0b, 0xa2, 0x0b, 0x68, 0xc2, 0x8c, 0xc4, 0x02, 0x0d, - 0x08, 0xd3, 0x80, 0x70, 0x95, 0x41, 0x9c, 0x71, 0xd9, 0x67, 0x26, 0x5b, 0x99, 0x6c, 0x55, 0x66, 0x4b, 0x9f, 0x6d, - 0x85, 0x44, 0x69, 0xb2, 0x65, 0x99, 0x0d, 0x32, 0x1b, 0x9e, 0xa6, 0x0a, 0x8f, 0x52, 0x69, 0x45, 0xb5, 0x4a, 0xb6, - 0x7a, 0x49, 0x43, 0x6d, 0xee, 0xd1, 0x51, 0x5c, 0xca, 0x49, 0x46, 0x4d, 0x7c, 0x6f, 0xc5, 0x93, 0xc2, 0xc8, 0x40, - 0x3c, 0x99, 0xba, 0xbf, 0xa3, 0xcd, 0xb6, 0xac, 0x54, 0x4c, 0x47, 0x5f, 0x29, 0x89, 0xfe, 0xf2, 0x4a, 0xd4, 0xe7, - 0xdc, 0x44, 0x01, 0xba, 0x24, 0x49, 0xab, 0x75, 0xda, 0x3e, 0x6d, 0x5d, 0xf4, 0xf9, 0x71, 0xbb, 0x93, 0x3c, 0xe8, - 0xa4, 0x46, 0x11, 0xb1, 0x90, 0x37, 0xa0, 0x80, 0x39, 0xe9, 0x24, 0x67, 0xe8, 0xb8, 0x9d, 0xb4, 0xba, 0xdd, 0x26, - 0xfc, 0x83, 0x1f, 0xe9, 0xb2, 0xda, 0x59, 0xeb, 0xac, 0xdb, 0xe7, 0x27, 0x5b, 0x95, 0x62, 0xde, 0x80, 0x82, 0xe8, - 0xc4, 0x54, 0xc2, 0x50, 0xbf, 0x5a, 0xde, 0x7f, 0x76, 0xf4, 0x3c, 0x8f, 0x74, 0x2c, 0xad, 0x2a, 0x0e, 0xa0, 0xea, - 0xbf, 0xa6, 0x06, 0x88, 0xfe, 0x6b, 0x54, 0x46, 0xea, 0x5d, 0x15, 0x20, 0x6a, 0x3f, 0xe7, 0xb1, 0x68, 0xb0, 0xe3, - 0xd8, 0xe6, 0x6b, 0xa8, 0xdb, 0x84, 0xe8, 0x79, 0x78, 0xea, 0x72, 0x55, 0x98, 0x3b, 0x45, 0xa8, 0xa9, 0x20, 0x77, - 0xe4, 0x72, 0x65, 0x98, 0x3b, 0x42, 0xa8, 0x29, 0x21, 0x97, 0xa6, 0x3c, 0xa1, 0x90, 0xa3, 0x13, 0xda, 0x34, 0x90, - 0xac, 0x16, 0xe5, 0x39, 0xf3, 0xc3, 0xe6, 0x13, 0x58, 0x1e, 0x43, 0x50, 0x9c, 0x20, 0x2d, 0xe0, 0x85, 0x95, 0x52, - 0x9b, 0xd3, 0xc2, 0xa5, 0x1a, 0x07, 0x32, 0x1a, 0xf0, 0xcf, 0x31, 0x33, 0xcf, 0x6e, 0xb4, 0xfa, 0xa7, 0xe7, 0xad, - 0xb4, 0x0d, 0xae, 0xe2, 0x20, 0x6b, 0x0b, 0x2b, 0x6b, 0x0b, 0x2f, 0x6b, 0x0b, 0x2f, 0x6b, 0x83, 0x00, 0x1f, 0xf4, - 0xfd, 0xbb, 0xac, 0x99, 0xdf, 0xf0, 0xd2, 0x96, 0xc7, 0x1a, 0x6b, 0xc4, 0x7a, 0xbd, 0x5e, 0x6d, 0xc0, 0xd2, 0xaa, - 0xac, 0x51, 0xa8, 0x4a, 0xfd, 0xb9, 0x2a, 0xd2, 0x16, 0x9e, 0xa6, 0xa0, 0xe5, 0x6e, 0x61, 0x6a, 0x36, 0xb7, 0xa7, - 0x0a, 0xdb, 0x51, 0x7c, 0xfa, 0x5e, 0x9d, 0x7c, 0x45, 0x4e, 0x8d, 0xf6, 0x78, 0x55, 0xa4, 0xdc, 0xd2, 0x0c, 0x6e, - 0x69, 0x06, 0xb7, 0x34, 0x03, 0x1a, 0xc1, 0x65, 0x61, 0x53, 0x36, 0xa1, 0x04, 0xae, 0x04, 0x06, 0xa7, 0x43, 0x08, - 0x62, 0x18, 0x6b, 0x62, 0x46, 0xbd, 0xd5, 0x79, 0x1b, 0x82, 0xb6, 0xd9, 0x92, 0x3a, 0xa1, 0xc6, 0x77, 0xbd, 0x1c, - 0xf3, 0xa7, 0x1a, 0xda, 0x27, 0xf0, 0xa2, 0xce, 0x43, 0x1d, 0xb7, 0xc0, 0x74, 0x25, 0x2a, 0xa2, 0xbe, 0x21, 0x0b, - 0xa9, 0xd1, 0xd9, 0x38, 0x93, 0xf4, 0xcf, 0x5b, 0x9e, 0xc0, 0x96, 0x12, 0x84, 0xef, 0x48, 0x7c, 0x66, 0x55, 0x68, - 0x82, 0xd2, 0xe2, 0xd6, 0x99, 0xcb, 0xd9, 0x23, 0xa1, 0x07, 0x66, 0xf3, 0x3e, 0xe6, 0x55, 0x5f, 0x90, 0x02, 0x62, - 0x3e, 0xa6, 0x26, 0xd1, 0x45, 0x6d, 0x06, 0x27, 0x66, 0x72, 0x43, 0x8d, 0x4b, 0xcf, 0xcf, 0xf6, 0xcf, 0x27, 0x1a, - 0xf8, 0x3c, 0x16, 0xd3, 0x91, 0x77, 0x15, 0xfe, 0x68, 0x62, 0x1b, 0x91, 0xc3, 0x43, 0x6b, 0xd1, 0x6e, 0xbe, 0xb6, - 0x4d, 0xda, 0x4d, 0xa2, 0xc9, 0x86, 0x1d, 0xea, 0xd7, 0xe8, 0x77, 0xef, 0xb1, 0x57, 0x4c, 0x47, 0x28, 0xa0, 0xd9, - 0x06, 0xac, 0xb2, 0x02, 0x96, 0x72, 0xf5, 0x4a, 0x47, 0x4e, 0xe8, 0xdd, 0x8c, 0x79, 0x53, 0x4c, 0x47, 0x7b, 0x9f, - 0x5e, 0xb1, 0x3d, 0xf6, 0x5f, 0xd2, 0xa0, 0x07, 0xaf, 0xda, 0x9e, 0xb1, 0xdb, 0x6f, 0xd5, 0xb9, 0xde, 0x5b, 0x47, - 0xe5, 0xdf, 0xaa, 0xf3, 0x64, 0x5f, 0x9d, 0x39, 0xbf, 0x8d, 0xfd, 0xde, 0xd1, 0x81, 0x1a, 0xdb, 0x98, 0x49, 0x4d, - 0x47, 0x10, 0x2b, 0x1f, 0xfe, 0xda, 0x88, 0x36, 0x3d, 0x4f, 0xc2, 0x61, 0x15, 0x64, 0x3f, 0xe9, 0xa6, 0x0c, 0x53, - 0xd2, 0x39, 0x2e, 0x4c, 0x4c, 0x1b, 0x91, 0xd0, 0xa6, 0x4a, 0x28, 0xce, 0x49, 0x1c, 0xd3, 0xe3, 0x0c, 0x22, 0xf3, - 0xb4, 0xfb, 0x34, 0x8d, 0x69, 0x23, 0x43, 0x27, 0x71, 0xbb, 0x41, 0x8f, 0x33, 0x84, 0x1a, 0x6d, 0xd0, 0x99, 0x4a, - 0xd2, 0x6e, 0xe6, 0x10, 0xab, 0xd3, 0x90, 0xe2, 0xfc, 0x58, 0x24, 0x45, 0x43, 0x1e, 0xab, 0xa4, 0x68, 0x24, 0x5d, - 0x2c, 0x92, 0x69, 0x99, 0x3c, 0x35, 0xc9, 0x53, 0x9b, 0x3c, 0x2a, 0x93, 0x47, 0x26, 0x79, 0x64, 0x93, 0x29, 0x29, - 0x8e, 0x45, 0x42, 0x1b, 0x71, 0xbb, 0x59, 0xa0, 0x63, 0x18, 0x81, 0x1f, 0x3d, 0x11, 0x61, 0x88, 0xf4, 0x8d, 0xb1, - 0x31, 0x5a, 0xc8, 0xdc, 0x05, 0x2d, 0xad, 0x80, 0x54, 0x3a, 0x7e, 0x41, 0x9d, 0x7f, 0x02, 0x30, 0x61, 0x6d, 0xff, - 0xf8, 0x90, 0x7c, 0x9b, 0x2c, 0x97, 0x22, 0x70, 0x6c, 0x03, 0x5b, 0xfc, 0xcf, 0xce, 0x9d, 0x07, 0xa0, 0xba, 0xa1, - 0xf9, 0x62, 0x46, 0x77, 0xbc, 0x87, 0x8b, 0xe9, 0xc8, 0xed, 0xac, 0xb2, 0x19, 0x46, 0x0b, 0x1b, 0xea, 0xba, 0xee, - 0xe7, 0x09, 0xa0, 0xf6, 0xbe, 0xa5, 0x09, 0x35, 0x4a, 0x72, 0x5b, 0x63, 0x5a, 0xb0, 0x3b, 0x95, 0xd1, 0x9c, 0xc5, - 0xd5, 0x01, 0x5c, 0x0d, 0x93, 0x91, 0x27, 0xe0, 0x11, 0x50, 0x1c, 0x27, 0xa7, 0x0d, 0x9d, 0x4c, 0x8f, 0x93, 0xee, - 0x83, 0x86, 0x4e, 0x46, 0xc7, 0x49, 0xbb, 0x5d, 0xe1, 0x6c, 0x52, 0x10, 0x9d, 0x4c, 0x89, 0x06, 0x8d, 0xa1, 0x6d, - 0x54, 0x2e, 0x28, 0x98, 0xb8, 0xfd, 0x1b, 0xc3, 0x68, 0xb8, 0x61, 0x08, 0x36, 0xb5, 0x51, 0x3f, 0x77, 0xc6, 0x10, - 0x76, 0xd3, 0xe9, 0x76, 0x9b, 0x3a, 0x29, 0xb0, 0xb6, 0x2b, 0xd9, 0xd4, 0xc9, 0x14, 0x6b, 0xbb, 0x7c, 0x4d, 0x9d, - 0x8c, 0x6c, 0x53, 0x46, 0x07, 0xc8, 0x44, 0x00, 0xac, 0xe7, 0x2c, 0x80, 0x7c, 0xc7, 0x3b, 0xe9, 0x6c, 0x40, 0x6b, - 0xf8, 0xad, 0x72, 0x4d, 0x5f, 0x50, 0x51, 0x0d, 0xa6, 0x4e, 0xec, 0x6b, 0x45, 0xdb, 0x55, 0x93, 0xec, 0x5f, 0x97, - 0x2d, 0x9b, 0x2d, 0xa4, 0xae, 0x17, 0x7c, 0x51, 0xc3, 0x10, 0x57, 0xca, 0x1d, 0xdc, 0x8f, 0x28, 0x89, 0x21, 0xb6, - 0x9f, 0x39, 0x85, 0x38, 0xf1, 0x7a, 0x64, 0x48, 0xe2, 0x8d, 0xc6, 0x06, 0xc5, 0xc1, 0x79, 0xfb, 0x22, 0xa4, 0xaa, - 0x3b, 0x01, 0xff, 0x08, 0x89, 0x96, 0xc2, 0x9a, 0x84, 0x8e, 0xa3, 0x8a, 0x16, 0xbf, 0x71, 0xda, 0xdd, 0xda, 0x01, - 0x71, 0x74, 0xb4, 0x7d, 0x5e, 0xf8, 0xa7, 0x17, 0x76, 0x9e, 0x5b, 0xa8, 0xec, 0x09, 0xfd, 0x83, 0x50, 0xd6, 0xd2, - 0x98, 0x07, 0x88, 0xe2, 0x43, 0x6f, 0xdd, 0x37, 0x14, 0x7e, 0x50, 0xc5, 0x1d, 0x74, 0x39, 0xcd, 0x73, 0x93, 0x61, - 0xfa, 0x1a, 0x06, 0x63, 0x7b, 0x15, 0x4e, 0xa8, 0xb4, 0x95, 0xfc, 0x97, 0x1d, 0x07, 0x9d, 0xb8, 0x07, 0x6b, 0xc2, - 0x46, 0x3f, 0x85, 0x96, 0xc9, 0x15, 0x6c, 0x9c, 0x4f, 0xfa, 0x7a, 0x5d, 0x7b, 0x9e, 0xc8, 0x3e, 0x82, 0x83, 0x8e, - 0x8e, 0xb8, 0x7a, 0x06, 0xc6, 0xd4, 0x2c, 0x6e, 0x84, 0x87, 0xef, 0xdf, 0xb5, 0xd3, 0xfa, 0x93, 0x39, 0x57, 0xd3, - 0xe0, 0xa0, 0x7b, 0x58, 0xcb, 0xdf, 0xbb, 0x12, 0x7d, 0x9d, 0x72, 0xb7, 0xd6, 0xef, 0x2b, 0x53, 0xf5, 0x9d, 0x87, - 0xb2, 0x8e, 0x8e, 0x78, 0x15, 0xae, 0x2a, 0xfa, 0x2e, 0x42, 0x7d, 0x23, 0x83, 0x3c, 0xcb, 0x25, 0x85, 0x1b, 0x51, - 0xb8, 0x62, 0x48, 0x1b, 0xfc, 0x44, 0xe3, 0x9f, 0xe4, 0xff, 0xa7, 0x46, 0x8e, 0x75, 0xda, 0xe0, 0x81, 0xb9, 0x41, - 0xc8, 0x0a, 0x55, 0x81, 0x22, 0x0d, 0xa4, 0x43, 0xcb, 0x73, 0x54, 0x1e, 0xe6, 0x74, 0xb1, 0xc8, 0xef, 0xcc, 0x5b, - 0x61, 0x01, 0x47, 0x55, 0x5d, 0x34, 0xb9, 0x28, 0x7d, 0xb8, 0x00, 0x9e, 0x1e, 0x70, 0x0f, 0x19, 0x2f, 0xdb, 0xf2, - 0x72, 0x5b, 0x20, 0x90, 0xcc, 0x14, 0x91, 0xcd, 0x76, 0x4f, 0x5d, 0x81, 0x5c, 0xd6, 0x6c, 0x22, 0xed, 0x82, 0x97, - 0x63, 0x0e, 0x32, 0x99, 0xb2, 0x9e, 0xb4, 0x07, 0xb6, 0x20, 0x48, 0x6e, 0xd2, 0x88, 0x6c, 0xfb, 0x4b, 0xf1, 0x49, - 0x0c, 0x68, 0x84, 0xac, 0xc0, 0x17, 0x0a, 0x8b, 0x1c, 0xb8, 0xce, 0xc2, 0x77, 0xfc, 0x95, 0x96, 0x8a, 0x81, 0x1a, - 0x0e, 0x71, 0x61, 0x9e, 0xc7, 0x28, 0xe7, 0x43, 0x55, 0xf0, 0xdc, 0x52, 0x20, 0xa2, 0xf0, 0xf5, 0xfa, 0x10, 0x5e, - 0x33, 0x72, 0x6d, 0x82, 0xeb, 0xad, 0xfb, 0x59, 0xbd, 0x5c, 0x02, 0xe3, 0x60, 0xa4, 0x65, 0x2e, 0x0a, 0x9d, 0xbc, - 0xc9, 0x2e, 0x45, 0xaf, 0xd1, 0x60, 0x26, 0xd0, 0x14, 0x81, 0xa8, 0x72, 0xe0, 0x17, 0x09, 0x7f, 0x6c, 0xec, 0x28, - 0xc5, 0x6c, 0x04, 0x3e, 0x08, 0x0d, 0x5e, 0x4b, 0x58, 0xaf, 0x95, 0x8d, 0xf0, 0x62, 0x72, 0x6c, 0xac, 0x97, 0xb2, - 0x9f, 0x32, 0x94, 0x6c, 0x65, 0xc6, 0xc1, 0xdd, 0x56, 0x7f, 0x53, 0xed, 0xe7, 0x03, 0x6e, 0xaf, 0xf1, 0xb8, 0x89, - 0x9b, 0x60, 0x00, 0xb5, 0xda, 0xda, 0xe0, 0xd6, 0xce, 0x3f, 0xb6, 0x46, 0xc9, 0x6c, 0x1b, 0x82, 0xa2, 0x8c, 0x13, - 0x60, 0x6f, 0x6e, 0x7d, 0xdc, 0x44, 0x65, 0xe6, 0xa4, 0x90, 0x1e, 0x80, 0x1c, 0x3d, 0x24, 0xd0, 0xb9, 0xfd, 0x59, - 0xd1, 0x85, 0x4a, 0x26, 0x2e, 0xc7, 0xf8, 0x43, 0x70, 0x9b, 0x37, 0x88, 0x3e, 0x7e, 0x34, 0x9b, 0xfc, 0xe3, 0xc7, - 0x08, 0x87, 0xc6, 0xf5, 0x51, 0xc0, 0x0b, 0x46, 0xc3, 0x32, 0xb4, 0x96, 0xd9, 0xf8, 0xcd, 0x76, 0x80, 0x76, 0xb4, - 0xc2, 0x3b, 0x58, 0x1e, 0xd3, 0xf8, 0x8e, 0x33, 0xea, 0x80, 0x03, 0xbc, 0xd9, 0x80, 0x0f, 0x7b, 0xaf, 0x62, 0x85, - 0x8e, 0x8e, 0x5e, 0xc5, 0x12, 0xf5, 0xaf, 0x99, 0xb9, 0x73, 0x03, 0x6f, 0xf4, 0x01, 0x37, 0xc3, 0x97, 0x01, 0x02, - 0x5c, 0xb3, 0x6d, 0xc9, 0xe6, 0x8d, 0x89, 0xfd, 0x91, 0x42, 0x6c, 0x71, 0x88, 0x70, 0xec, 0x40, 0x02, 0xbd, 0xbe, - 0x0a, 0xa1, 0xdd, 0x63, 0x84, 0x01, 0x0b, 0x5f, 0xfa, 0x0a, 0xb2, 0x64, 0xce, 0x8a, 0x29, 0x2b, 0xd6, 0xeb, 0xe7, - 0xd4, 0xfa, 0xff, 0x6d, 0x85, 0xaa, 0x54, 0xbd, 0x46, 0x83, 0x9a, 0xf1, 0x83, 0xf8, 0x40, 0x87, 0xf8, 0xf0, 0x55, - 0x5c, 0x20, 0x04, 0x16, 0x46, 0x5c, 0x2c, 0xbd, 0xaf, 0x5b, 0x56, 0x5b, 0x97, 0x02, 0x95, 0x8d, 0xe4, 0xa4, 0x85, - 0x67, 0x24, 0x2b, 0xd7, 0xe8, 0x72, 0xd6, 0x6b, 0x34, 0x72, 0x24, 0xe3, 0x6c, 0x90, 0x0f, 0x31, 0xc7, 0x05, 0x5c, - 0xa6, 0xee, 0xae, 0xc3, 0x82, 0xd5, 0x28, 0x97, 0x9b, 0xef, 0xca, 0x8e, 0x35, 0x7d, 0x47, 0x37, 0x01, 0x30, 0xde, - 0xd1, 0x80, 0x48, 0xec, 0x03, 0xb2, 0xb0, 0x40, 0x56, 0x1e, 0xc8, 0xc2, 0x00, 0x59, 0xa1, 0xfe, 0x02, 0x82, 0x36, - 0x29, 0x94, 0xee, 0x50, 0xf4, 0x7a, 0x78, 0x51, 0xe7, 0xba, 0x82, 0xb9, 0x89, 0x70, 0xe1, 0x96, 0x03, 0xdc, 0x58, - 0xdc, 0xdc, 0x15, 0x59, 0x45, 0x91, 0x89, 0xb4, 0x8b, 0x6f, 0xcd, 0x9f, 0xe4, 0x16, 0xdf, 0xd9, 0x1f, 0x77, 0x81, - 0x32, 0xe9, 0xb7, 0x9a, 0xb6, 0x81, 0xbb, 0xb8, 0x74, 0x51, 0x12, 0x01, 0x5a, 0xbb, 0x20, 0x8b, 0xa2, 0xfe, 0xee, - 0x9c, 0xb2, 0xe1, 0x30, 0x44, 0x83, 0x28, 0x2c, 0x02, 0xd2, 0xf9, 0xe7, 0x9f, 0x11, 0xea, 0x0b, 0x88, 0x66, 0xe4, - 0x4e, 0xb6, 0x66, 0x1b, 0x35, 0xa2, 0x24, 0x4a, 0x63, 0x1f, 0x2c, 0x03, 0x76, 0x46, 0x14, 0x05, 0x6f, 0xce, 0x54, - 0x36, 0x1e, 0xb5, 0x61, 0x98, 0x41, 0x55, 0xe1, 0x3f, 0xae, 0x56, 0xdb, 0xc1, 0x96, 0x0c, 0x54, 0x85, 0x89, 0x74, - 0x83, 0xec, 0x43, 0x6c, 0x8c, 0xb0, 0xa3, 0x23, 0x36, 0x10, 0xc3, 0xe0, 0x65, 0xb5, 0xaa, 0x75, 0x1d, 0x2e, 0x5c, - 0x9c, 0x41, 0xb4, 0xfb, 0xf5, 0xda, 0xfe, 0x25, 0x1f, 0x8c, 0x34, 0x03, 0x4f, 0xe4, 0x05, 0xb7, 0xf1, 0x62, 0xbf, - 0x2c, 0x96, 0x68, 0xf9, 0x0e, 0x2c, 0xfb, 0x5c, 0xec, 0x42, 0xee, 0xa6, 0xda, 0xf6, 0x50, 0x5f, 0x18, 0x8d, 0x42, - 0x10, 0x39, 0xb8, 0x3a, 0xd2, 0xf0, 0x42, 0x87, 0x79, 0xb5, 0x08, 0xc0, 0xb9, 0x2a, 0x03, 0xb9, 0xc2, 0x91, 0x92, - 0x80, 0xa5, 0xb7, 0xa1, 0x93, 0xf0, 0xa3, 0x4e, 0x25, 0x1d, 0x0b, 0x09, 0x50, 0xe0, 0xc8, 0x5c, 0xce, 0x9b, 0x40, - 0xfd, 0x0c, 0xed, 0x21, 0x72, 0xd5, 0x2a, 0xff, 0x5d, 0x97, 0x2d, 0x5d, 0x44, 0xad, 0x68, 0x2e, 0x97, 0x8a, 0x2d, - 0x17, 0x70, 0xbe, 0x97, 0x69, 0x59, 0xce, 0xb3, 0xcf, 0xf5, 0x14, 0x30, 0x88, 0xbc, 0xd5, 0x73, 0x26, 0x96, 0x91, - 0x9b, 0xe7, 0x4b, 0x2b, 0xee, 0xbf, 0x7e, 0x81, 0xdf, 0x93, 0xce, 0xf1, 0x4b, 0xfc, 0x3b, 0x25, 0xef, 0x1b, 0x2f, - 0xf1, 0x94, 0x13, 0xcb, 0x1b, 0x24, 0xaf, 0x5f, 0x5d, 0xbf, 0x78, 0xfb, 0xe2, 0xfd, 0xd3, 0x8f, 0x2f, 0x5e, 0x3e, - 0x7b, 0xf1, 0xf2, 0xc5, 0xdb, 0x0f, 0xf8, 0x27, 0x4a, 0x5e, 0x9e, 0xb4, 0x2f, 0x5a, 0xf8, 0x1d, 0x79, 0x79, 0xd2, - 0xc1, 0xb7, 0x9a, 0xbc, 0x3c, 0x39, 0xc3, 0x33, 0x45, 0x5e, 0x1e, 0x77, 0x4e, 0x4e, 0xf1, 0x52, 0xdb, 0x26, 0x73, - 0x39, 0x6d, 0xb7, 0xf0, 0xdf, 0xee, 0x0b, 0xc4, 0xfb, 0x6a, 0x16, 0x53, 0xb6, 0x65, 0xfc, 0x60, 0xca, 0xd0, 0x91, - 0x32, 0x86, 0x28, 0x97, 0x01, 0x3a, 0x8d, 0x55, 0xdd, 0xb4, 0x01, 0x42, 0x49, 0x83, 0x0d, 0x23, 0xa0, 0x15, 0x27, - 0xae, 0x1d, 0x7e, 0xd2, 0x66, 0xa7, 0x40, 0x9f, 0x78, 0x29, 0x1c, 0x97, 0x2a, 0x9c, 0xb6, 0xd3, 0x62, 0x4c, 0x72, - 0x29, 0x8b, 0x78, 0x09, 0x8c, 0x80, 0xd1, 0x5a, 0xf0, 0x93, 0x32, 0x66, 0x95, 0xb8, 0x24, 0xed, 0x7e, 0x3b, 0x15, - 0x97, 0xa4, 0xd3, 0xef, 0xc0, 0x9f, 0x6e, 0xbf, 0x9b, 0xb6, 0x5b, 0xe8, 0x38, 0x18, 0xc7, 0x0f, 0x35, 0xb4, 0x1e, - 0x0c, 0xb1, 0xeb, 0x42, 0xfd, 0x5d, 0x68, 0xaf, 0xd2, 0x13, 0x4e, 0x1d, 0xdb, 0xee, 0x89, 0x4b, 0x66, 0xf4, 0xb0, - 0xfc, 0x3b, 0x40, 0x6d, 0xe3, 0x56, 0x53, 0x6e, 0x1c, 0xf7, 0x8b, 0x9f, 0x08, 0x54, 0x0b, 0x8c, 0x13, 0xb3, 0x75, - 0x0b, 0x01, 0xd3, 0x68, 0xb2, 0xc1, 0x1c, 0x28, 0x51, 0xb2, 0xd0, 0x3e, 0xb8, 0xbf, 0x6a, 0x4a, 0x94, 0x2c, 0xe4, - 0x22, 0xae, 0xa9, 0x1a, 0x7e, 0x09, 0xcc, 0x1c, 0x0f, 0xb9, 0x7a, 0x49, 0x5f, 0xc6, 0x35, 0x9e, 0x27, 0x64, 0xed, - 0xc2, 0x6d, 0xf1, 0xab, 0xb3, 0xa2, 0xa8, 0x81, 0xab, 0x04, 0xac, 0x1f, 0x55, 0x53, 0x5f, 0xc2, 0x2b, 0x86, 0xac, - 0xa1, 0xaf, 0x48, 0x40, 0x3d, 0x7f, 0x2d, 0xcd, 0xb8, 0x4a, 0x65, 0xb4, 0x57, 0x44, 0x1b, 0xb3, 0x20, 0xaf, 0x88, - 0xbe, 0x54, 0x06, 0x08, 0x92, 0xf0, 0x81, 0x18, 0xc2, 0x81, 0x6f, 0x07, 0x28, 0x0d, 0x9d, 0x03, 0xb5, 0x52, 0x65, - 0x26, 0x64, 0x3e, 0x4d, 0x88, 0x06, 0xd0, 0x3c, 0x55, 0x2a, 0x28, 0xf3, 0x89, 0x25, 0x0a, 0x86, 0xfe, 0x47, 0xb8, - 0x01, 0x8e, 0x63, 0x83, 0x8a, 0xa1, 0x5d, 0x8d, 0xa8, 0xe7, 0xb7, 0x2f, 0x5a, 0x27, 0x2f, 0x83, 0xfc, 0xa5, 0xf2, - 0xf6, 0x1e, 0x9f, 0x02, 0x4a, 0x6e, 0x83, 0x8a, 0xb5, 0xb1, 0x8f, 0x07, 0xd7, 0x0b, 0x01, 0x72, 0xac, 0xd1, 0x89, - 0x79, 0xd0, 0xb1, 0x87, 0xf4, 0x31, 0x69, 0xb7, 0x20, 0x88, 0xdb, 0x1e, 0xca, 0xf7, 0xc7, 0x16, 0x4c, 0x75, 0x72, - 0xdb, 0x04, 0x5a, 0x0d, 0x6f, 0x3c, 0xdd, 0x35, 0x79, 0x72, 0x87, 0x55, 0x80, 0x33, 0xec, 0x98, 0x35, 0xc4, 0xb1, - 0x40, 0x2e, 0xf8, 0xad, 0xdd, 0x00, 0x9a, 0x8a, 0x8e, 0x7d, 0x6b, 0xd0, 0x1b, 0x47, 0x5d, 0x36, 0x93, 0xee, 0xf1, - 0xcb, 0xa3, 0xa3, 0x58, 0x36, 0xc8, 0x7b, 0x84, 0x57, 0x14, 0x6c, 0xb6, 0xc1, 0xf7, 0x8e, 0x5b, 0x26, 0x3e, 0x55, - 0x01, 0x75, 0x9c, 0xa8, 0xda, 0xb1, 0x56, 0x75, 0x56, 0xee, 0x06, 0x3f, 0xa6, 0x0e, 0x6a, 0x04, 0x69, 0x76, 0x74, - 0x9d, 0x10, 0xca, 0x3f, 0xd6, 0x1c, 0xe5, 0x60, 0x5b, 0x36, 0x7e, 0xa7, 0xe8, 0xbb, 0xf7, 0xcd, 0x97, 0x01, 0x1e, - 0xd4, 0x4c, 0x93, 0xde, 0x37, 0xde, 0xa3, 0xef, 0xde, 0x07, 0xae, 0x8e, 0xbc, 0x62, 0x4f, 0x3c, 0x37, 0xf2, 0xab, - 0xe5, 0x4a, 0x7f, 0x05, 0xc9, 0xbe, 0x20, 0xbf, 0x02, 0x96, 0x53, 0xf2, 0x6b, 0x2c, 0x9b, 0x10, 0x02, 0x92, 0xfc, - 0x1a, 0x17, 0xf0, 0x23, 0x27, 0xbf, 0xc6, 0x80, 0xed, 0x78, 0x66, 0x7e, 0x14, 0x25, 0x30, 0xc0, 0xbd, 0x4e, 0x5a, - 0x2f, 0xbb, 0x62, 0xbd, 0x16, 0x47, 0x47, 0xd2, 0xfe, 0xa2, 0x57, 0xd9, 0xd1, 0x51, 0x7e, 0x39, 0xab, 0xfa, 0xe6, - 0x7a, 0x1f, 0x7d, 0x31, 0x08, 0x85, 0x03, 0xd3, 0x34, 0x1e, 0xce, 0x58, 0x67, 0x21, 0xe2, 0x40, 0x03, 0xcd, 0xd3, - 0xce, 0xfd, 0xf3, 0x0b, 0x0c, 0xff, 0xde, 0x0f, 0x0a, 0x82, 0x0e, 0xdf, 0x4e, 0x8c, 0xb4, 0x59, 0xf3, 0xbc, 0xaa, - 0x73, 0x15, 0xe0, 0x33, 0x66, 0xa8, 0x29, 0x8e, 0x8e, 0xf8, 0x65, 0x80, 0xcb, 0x98, 0xa1, 0x46, 0x60, 0xb1, 0xf7, - 0xb4, 0xb4, 0x27, 0x33, 0x5c, 0x13, 0x3c, 0xee, 0xcb, 0x07, 0xc5, 0xf0, 0x52, 0x3b, 0x6a, 0x12, 0x86, 0x00, 0x57, - 0xa4, 0xe5, 0x36, 0x59, 0x4f, 0x34, 0xd5, 0x55, 0xbb, 0x87, 0x24, 0x51, 0x0d, 0x71, 0x75, 0xd5, 0xc6, 0xa0, 0x92, - 0xef, 0x2b, 0x22, 0x53, 0x41, 0xbc, 0x9b, 0xe2, 0x2a, 0x97, 0xa9, 0xc2, 0x33, 0x9e, 0x0a, 0x2f, 0x67, 0xdf, 0xf3, - 0xd6, 0xd3, 0xc6, 0x71, 0xd4, 0xf4, 0xcc, 0xb0, 0xe8, 0xab, 0xd2, 0xe1, 0x11, 0x36, 0xa9, 0x1a, 0xc2, 0xdb, 0x89, - 0x25, 0xe6, 0x31, 0xeb, 0xe5, 0xc7, 0x20, 0x36, 0xb5, 0x6a, 0xb4, 0x21, 0x13, 0x3e, 0x37, 0xa9, 0x82, 0x81, 0x9a, - 0xc2, 0x97, 0x60, 0x64, 0x95, 0x55, 0x86, 0xd9, 0xbe, 0x61, 0x28, 0x20, 0xa0, 0xc0, 0x15, 0x61, 0x81, 0x04, 0x2f, - 0xb2, 0x1a, 0xe1, 0xa8, 0x93, 0x0b, 0x3b, 0xb9, 0x4b, 0x05, 0xdd, 0x89, 0xe1, 0xa5, 0xee, 0x21, 0xd1, 0x68, 0x38, - 0x6e, 0xfb, 0x4a, 0x98, 0x41, 0x34, 0xdb, 0xc3, 0x2b, 0xd6, 0x43, 0xaa, 0xd9, 0x2c, 0x0d, 0x20, 0xaf, 0x5a, 0xeb, - 0xb5, 0xba, 0xf4, 0x8d, 0xf4, 0xfd, 0x39, 0x6e, 0xf8, 0x2e, 0x2f, 0x78, 0xfe, 0x21, 0xc9, 0x20, 0x02, 0xaa, 0x0a, - 0x7c, 0xb6, 0x5c, 0x44, 0x38, 0x32, 0xcf, 0xea, 0xc1, 0x5f, 0xf3, 0x1c, 0x5a, 0x84, 0x23, 0xf7, 0xd2, 0x5e, 0x34, - 0xac, 0x06, 0xab, 0xb2, 0x32, 0x48, 0x3c, 0x4f, 0x3e, 0x02, 0xe3, 0xa0, 0x3f, 0x29, 0xb4, 0xaa, 0x7e, 0x27, 0xb9, - 0x0b, 0x97, 0xa2, 0xfc, 0xe3, 0x6f, 0x6e, 0x54, 0x9b, 0xfd, 0x0e, 0xaa, 0x1c, 0x47, 0xbe, 0x2a, 0x3c, 0xa2, 0xf0, - 0x8d, 0xd7, 0x27, 0xdb, 0xee, 0xd1, 0xf3, 0x55, 0xd9, 0x03, 0x70, 0xde, 0x9b, 0x0d, 0xc2, 0x7f, 0xc8, 0xbd, 0x2f, - 0x20, 0x47, 0x1f, 0xa5, 0x78, 0x42, 0x35, 0x8d, 0x1a, 0xaf, 0x8d, 0xe1, 0x9b, 0x95, 0xb3, 0x7a, 0x5f, 0x1b, 0x07, - 0xfb, 0xb7, 0xba, 0x87, 0x00, 0x16, 0xb5, 0xc7, 0x9a, 0xac, 0xec, 0x6b, 0xc2, 0x96, 0xc8, 0xc0, 0xf4, 0x6d, 0x0f, - 0x3c, 0xfc, 0x18, 0x29, 0xb8, 0x55, 0x5b, 0x3e, 0x89, 0x42, 0x64, 0xd8, 0x9a, 0x33, 0x37, 0xa4, 0xd8, 0x3e, 0x8c, - 0xe3, 0xef, 0x06, 0x85, 0x5c, 0xf7, 0x42, 0xd5, 0x89, 0x69, 0xd5, 0x8d, 0x91, 0x3a, 0xd8, 0x36, 0x0b, 0xce, 0xaa, - 0xde, 0x8d, 0x84, 0x52, 0xbd, 0x6b, 0x67, 0xde, 0x26, 0x6d, 0xb6, 0xcd, 0x63, 0xcf, 0xf6, 0xf5, 0x3b, 0x05, 0x86, - 0xbc, 0x87, 0x65, 0xd0, 0xae, 0x2b, 0x38, 0x76, 0xe3, 0x00, 0xb2, 0x92, 0x5c, 0xad, 0xdc, 0xcb, 0x74, 0x7c, 0x20, - 0x87, 0x9b, 0xf2, 0x9d, 0xba, 0x00, 0x0f, 0x02, 0xa7, 0x80, 0x2c, 0xe4, 0x0c, 0xfc, 0x23, 0x8f, 0x35, 0xfd, 0x10, - 0xff, 0x07, 0x0e, 0xf8, 0x0a, 0x49, 0x53, 0xab, 0x7e, 0x82, 0xf7, 0xa3, 0x40, 0xe1, 0x6d, 0xeb, 0xfe, 0x28, 0x43, - 0x47, 0xdd, 0xba, 0x4e, 0xc5, 0xfa, 0xc2, 0xd6, 0x15, 0x2b, 0x65, 0xe1, 0x80, 0x6a, 0xc5, 0x68, 0x93, 0x3a, 0xbf, - 0x59, 0xf7, 0xe8, 0xd4, 0x43, 0x01, 0xbe, 0x31, 0x5c, 0x8a, 0x67, 0x05, 0x44, 0x11, 0x0b, 0xf5, 0x69, 0xba, 0x08, - 0x5f, 0x55, 0x1e, 0xc0, 0x3d, 0x61, 0xc9, 0x73, 0x96, 0x2f, 0x81, 0xc3, 0x02, 0x29, 0xa0, 0x50, 0x0a, 0x8b, 0xf5, - 0x3a, 0x16, 0x26, 0xb6, 0x84, 0x0b, 0x2d, 0xec, 0xde, 0x10, 0x31, 0xfa, 0x3b, 0xa8, 0x8b, 0xbd, 0x7a, 0xc4, 0x98, - 0xb0, 0xa2, 0xf0, 0xd2, 0xa9, 0xc8, 0x82, 0xbe, 0xf6, 0xf5, 0x21, 0xaa, 0x29, 0xf7, 0x63, 0xa3, 0xef, 0x7d, 0xcb, - 0xe7, 0x4c, 0x2e, 0xe1, 0xf1, 0x26, 0xcc, 0x88, 0x62, 0xda, 0x7f, 0x03, 0x05, 0x81, 0x17, 0x80, 0x78, 0x88, 0x8f, - 0xc0, 0x57, 0x79, 0x5a, 0x47, 0x33, 0xff, 0x24, 0x48, 0x64, 0x42, 0x76, 0x46, 0xfd, 0x08, 0xbc, 0x88, 0x40, 0x84, - 0x22, 0x24, 0x62, 0x62, 0x1c, 0xf5, 0x23, 0xe3, 0x92, 0x15, 0x81, 0xd5, 0x18, 0x28, 0xb9, 0x23, 0x3c, 0x55, 0x15, - 0x11, 0x0b, 0x6b, 0xea, 0xa0, 0x12, 0x4b, 0x8d, 0x99, 0xf6, 0x49, 0xa7, 0x02, 0x61, 0x96, 0x6d, 0x0b, 0xca, 0x7a, - 0x4b, 0x5d, 0x80, 0x25, 0x31, 0xa6, 0xb7, 0x3c, 0xf9, 0x08, 0xdc, 0x1c, 0x1b, 0xbb, 0xa2, 0x2b, 0x7e, 0x0d, 0xea, - 0xe9, 0xb4, 0xc0, 0x1f, 0x0d, 0xc3, 0x36, 0x4e, 0xe9, 0x86, 0x70, 0x9c, 0x91, 0x22, 0xa1, 0xb7, 0x10, 0x5b, 0x63, - 0xce, 0x45, 0x9a, 0xe3, 0x39, 0xbd, 0x4d, 0x67, 0x78, 0xce, 0xc5, 0x13, 0xbb, 0xec, 0xe9, 0x18, 0x92, 0xfc, 0xc7, - 0x72, 0x43, 0xcc, 0xd3, 0x60, 0xef, 0x14, 0x2b, 0x1e, 0x01, 0xaf, 0xa2, 0x62, 0xd4, 0x1b, 0x1b, 0x9b, 0x72, 0xae, - 0x2b, 0xe3, 0xf5, 0x7b, 0x3a, 0xa6, 0x38, 0xc3, 0x39, 0x4a, 0x72, 0x89, 0x59, 0x5f, 0xa4, 0xf7, 0x20, 0xae, 0x76, - 0x86, 0xed, 0xb3, 0x62, 0xfc, 0x96, 0xe5, 0xcf, 0x64, 0xf1, 0xde, 0x6c, 0xf9, 0x1c, 0x41, 0x21, 0x70, 0x51, 0x11, - 0x4d, 0xb8, 0xdd, 0x5b, 0xf6, 0x65, 0xd5, 0x14, 0xbd, 0xb5, 0x4d, 0xb9, 0x21, 0xce, 0x20, 0x20, 0x71, 0x32, 0xe3, - 0x8d, 0x36, 0x66, 0xfd, 0xd6, 0x37, 0x1a, 0x9d, 0xa1, 0xb2, 0x24, 0xc2, 0xb0, 0x56, 0x4d, 0x95, 0x4a, 0x22, 0x9a, - 0xca, 0x49, 0x78, 0x2b, 0x03, 0xec, 0x54, 0xe1, 0x4c, 0x2e, 0x85, 0x4e, 0x65, 0x80, 0x37, 0x79, 0xb5, 0xb9, 0x56, - 0xb7, 0x16, 0x62, 0x1a, 0xdf, 0xd9, 0x1f, 0x0c, 0x7f, 0x34, 0x2a, 0xfe, 0x37, 0x60, 0xd8, 0xa3, 0x52, 0x01, 0xf0, - 0x03, 0xc3, 0x59, 0x80, 0x9c, 0xe5, 0x27, 0x6f, 0x01, 0x7c, 0x96, 0x85, 0xbc, 0x83, 0x54, 0x66, 0x52, 0xef, 0x20, - 0x95, 0x41, 0xaa, 0xf1, 0xa8, 0x3f, 0x14, 0x95, 0xb2, 0x28, 0x6c, 0x90, 0x28, 0x5c, 0xaa, 0x83, 0x25, 0x11, 0x09, - 0xb4, 0x6b, 0x44, 0xb9, 0x39, 0x17, 0x10, 0x5a, 0x11, 0x1a, 0xb7, 0xdf, 0xf4, 0x16, 0xbe, 0xef, 0x6c, 0x3e, 0xf3, - 0xf9, 0x77, 0x36, 0xdf, 0x74, 0xe4, 0x31, 0xbe, 0x7e, 0xdb, 0x69, 0x2c, 0xe3, 0xa5, 0xc3, 0xda, 0x77, 0xe5, 0x43, - 0x36, 0x2d, 0xf3, 0x60, 0x38, 0x69, 0xe3, 0x79, 0x80, 0x94, 0xcd, 0x8a, 0x87, 0xeb, 0xe0, 0x76, 0xeb, 0x38, 0xe6, - 0x4d, 0xd2, 0x46, 0xe8, 0xd8, 0x09, 0x57, 0x22, 0x36, 0x92, 0xd3, 0xf1, 0xfb, 0x13, 0xb8, 0x7b, 0x19, 0xa9, 0x2d, - 0x5f, 0x29, 0x5b, 0xad, 0xd9, 0x6e, 0x1d, 0xf3, 0xbd, 0x55, 0x1a, 0x6d, 0x3c, 0x67, 0x64, 0x05, 0x1e, 0x68, 0xb4, - 0xb0, 0xaa, 0x06, 0x70, 0x59, 0x7d, 0x21, 0x7e, 0x5d, 0xd2, 0xb1, 0xf9, 0x3e, 0xb6, 0x29, 0xaf, 0x96, 0xda, 0x27, - 0x35, 0x39, 0x0c, 0xa2, 0x83, 0x5c, 0xc9, 0x20, 0x27, 0xe6, 0x27, 0x24, 0xe9, 0xa2, 0xcb, 0x76, 0x3f, 0xe9, 0x1e, - 0xf3, 0x63, 0x9e, 0x02, 0x0f, 0x1b, 0x37, 0x7d, 0x85, 0x66, 0xdb, 0xd7, 0x79, 0xbc, 0x1c, 0xf1, 0xcc, 0x35, 0x5f, - 0x75, 0x50, 0xa6, 0xda, 0x39, 0x42, 0x16, 0xa0, 0x98, 0xef, 0x25, 0xc8, 0xae, 0x77, 0x73, 0xcc, 0x53, 0xe8, 0x07, - 0x6a, 0x75, 0x6c, 0xad, 0x72, 0x70, 0xbf, 0x2e, 0x01, 0xc1, 0x7c, 0x47, 0xb5, 0xb9, 0xd8, 0xf4, 0x66, 0x5c, 0x75, - 0x76, 0xcc, 0xab, 0x11, 0x86, 0x65, 0x76, 0xfb, 0xf3, 0x53, 0xab, 0xba, 0x3c, 0x0e, 0x20, 0xf2, 0xeb, 0x92, 0x8b, - 0xb0, 0xd3, 0xb0, 0x5b, 0x97, 0x13, 0x76, 0x5a, 0x9f, 0x65, 0x50, 0x64, 0xb7, 0xd7, 0x9d, 0x99, 0xd6, 0x67, 0x7b, - 0x0d, 0x8e, 0x84, 0x30, 0x29, 0xb3, 0xd2, 0x99, 0x54, 0x31, 0x3f, 0x7e, 0x87, 0x5c, 0xeb, 0xaf, 0x96, 0xda, 0xe7, - 0x97, 0x88, 0x00, 0xd9, 0x55, 0xd7, 0x65, 0x75, 0xe8, 0xa3, 0x6c, 0xe2, 0xe5, 0x31, 0x0f, 0x56, 0xee, 0xe9, 0xed, - 0x42, 0xa6, 0x1e, 0x5f, 0xfb, 0xad, 0x74, 0x07, 0x39, 0x81, 0x78, 0xb8, 0xee, 0xc2, 0xb2, 0x20, 0x67, 0x37, 0x77, - 0x50, 0x32, 0x9c, 0xb8, 0x2f, 0xfd, 0x8e, 0xd9, 0xeb, 0x06, 0x7e, 0x99, 0x74, 0x61, 0xea, 0xdb, 0x3d, 0x1c, 0x77, - 0xa0, 0x0f, 0x03, 0x87, 0xed, 0x06, 0x7d, 0x66, 0x05, 0x91, 0xc7, 0xbc, 0xb0, 0x78, 0x76, 0x45, 0xda, 0x7d, 0x9e, - 0xba, 0xcd, 0x64, 0x44, 0xa3, 0x76, 0x93, 0x07, 0x33, 0x03, 0xfc, 0x72, 0x65, 0xc3, 0x22, 0x7e, 0x9d, 0x02, 0x28, - 0xf9, 0x62, 0xd5, 0xfa, 0x54, 0xf0, 0xaa, 0x37, 0x9c, 0x6e, 0xa7, 0xfb, 0x75, 0x83, 0xdb, 0x5d, 0x0f, 0x4f, 0x78, - 0x88, 0xc6, 0xa2, 0xb5, 0x9f, 0xf8, 0x1c, 0x38, 0xa0, 0xa4, 0x75, 0xbf, 0x0b, 0x2e, 0x94, 0x25, 0x2c, 0x77, 0xcb, - 0x8d, 0x76, 0xca, 0x59, 0x38, 0xda, 0x92, 0x01, 0x77, 0xb0, 0x0d, 0x51, 0xe8, 0xe0, 0xb8, 0x83, 0x93, 0x76, 0xbb, - 0xd3, 0xc5, 0xc9, 0x59, 0x17, 0x06, 0xda, 0x48, 0xba, 0xc7, 0x23, 0x65, 0x01, 0x18, 0xe4, 0x6c, 0x5c, 0xbb, 0x8f, - 0x20, 0x68, 0x55, 0x28, 0x5e, 0xf3, 0xe3, 0x38, 0x6e, 0x27, 0xf7, 0x5b, 0xed, 0xee, 0x45, 0x03, 0x00, 0xd4, 0x74, - 0x1f, 0xae, 0xc6, 0xab, 0xa5, 0xae, 0x57, 0x29, 0x11, 0xbe, 0x5e, 0xad, 0xe1, 0xab, 0x35, 0xda, 0x9b, 0x6a, 0x0a, - 0xbe, 0xaa, 0x13, 0xce, 0x6d, 0x11, 0xaf, 0xb4, 0x09, 0xb7, 0x45, 0x6c, 0x07, 0x12, 0x83, 0x74, 0x9e, 0x74, 0x3b, - 0x5d, 0x64, 0xc7, 0xa2, 0x1d, 0x7e, 0x94, 0xfb, 0x64, 0xa7, 0x48, 0x43, 0x03, 0x92, 0x94, 0xb3, 0x93, 0x4b, 0x90, - 0xa8, 0x39, 0xb9, 0x6a, 0x37, 0xe7, 0x2c, 0xf1, 0x13, 0x30, 0xa9, 0xb0, 0x9c, 0xe5, 0x2a, 0xb8, 0xa4, 0x00, 0x10, - 0x97, 0x60, 0x5c, 0x74, 0xbf, 0xdb, 0xbf, 0x9f, 0x74, 0xcf, 0x3b, 0x96, 0xe8, 0xf1, 0xcb, 0x4e, 0x2d, 0xcd, 0x4c, - 0x3d, 0xe9, 0x9a, 0x34, 0xe8, 0x3a, 0xb9, 0xdf, 0x85, 0x32, 0x2e, 0x25, 0x2c, 0x05, 0xc1, 0x36, 0xaa, 0x62, 0x10, - 0x61, 0x23, 0xad, 0xe5, 0x9e, 0xd7, 0xb2, 0x2f, 0xce, 0x4e, 0xef, 0x77, 0x43, 0xa8, 0x95, 0xb3, 0x30, 0x0b, 0xed, - 0x26, 0xe2, 0x67, 0x07, 0x4b, 0x8b, 0x8e, 0x93, 0x6e, 0xba, 0x33, 0x41, 0xbb, 0x69, 0x8e, 0x0d, 0x0e, 0x04, 0x0a, - 0xc7, 0x17, 0xc2, 0xe9, 0x4b, 0x82, 0xfb, 0xb1, 0xca, 0xd0, 0x24, 0x54, 0x38, 0xfb, 0x7b, 0xca, 0xe0, 0x3d, 0xcd, - 0xf0, 0xaa, 0xf2, 0x31, 0x15, 0x5f, 0xa8, 0x7a, 0x4d, 0x21, 0x82, 0x88, 0x18, 0x46, 0x2e, 0xbe, 0x79, 0x3d, 0xf7, - 0x07, 0x70, 0x11, 0x66, 0x02, 0x2e, 0x34, 0xbd, 0x12, 0xb4, 0xe2, 0x05, 0x3e, 0x86, 0x0e, 0xb5, 0x66, 0x58, 0x7d, - 0x9e, 0x3a, 0x93, 0x82, 0x50, 0xb7, 0xf5, 0x8e, 0x7f, 0xab, 0x5c, 0x52, 0x5e, 0x65, 0x27, 0x5d, 0x94, 0xb8, 0xcb, - 0xf2, 0xa4, 0x8d, 0x92, 0xc0, 0x84, 0xc4, 0x1d, 0xc9, 0xb3, 0x8c, 0x0c, 0xa2, 0xdb, 0x08, 0x47, 0x77, 0x11, 0x8e, - 0xac, 0x0f, 0xf3, 0x6f, 0xe0, 0xc7, 0x1d, 0xe1, 0xc8, 0xba, 0x32, 0x47, 0x38, 0xd2, 0x4c, 0x40, 0x60, 0xb1, 0x68, - 0x88, 0xc7, 0x50, 0xda, 0x78, 0x56, 0x97, 0xa5, 0x1f, 0xfb, 0xaf, 0xd2, 0xf5, 0xda, 0xa6, 0x04, 0x52, 0xe6, 0xd2, - 0xec, 0x50, 0xfb, 0x30, 0x76, 0x44, 0x3d, 0xb3, 0x1e, 0x61, 0x10, 0x40, 0xe8, 0x9d, 0x7f, 0x58, 0xaf, 0x8a, 0x49, - 0xc2, 0x4e, 0x61, 0xa5, 0xc1, 0x15, 0x3d, 0x0a, 0xcf, 0xb0, 0x08, 0x4f, 0x84, 0x2f, 0x0c, 0x62, 0x85, 0xff, 0x9d, - 0x4b, 0xb9, 0xf0, 0xbf, 0xb5, 0x2c, 0x7f, 0xc1, 0x73, 0x2c, 0xce, 0xa2, 0x05, 0x2c, 0xb7, 0x6c, 0x08, 0xa4, 0x11, - 0xab, 0x8f, 0xe0, 0xe3, 0xc4, 0x85, 0xa9, 0x03, 0x89, 0xf0, 0xa3, 0x11, 0xa8, 0xbc, 0x7c, 0xf8, 0xd1, 0x86, 0x4c, - 0x32, 0x9f, 0x10, 0x33, 0x0d, 0xc2, 0x22, 0x4b, 0xb8, 0xd0, 0x98, 0x16, 0x4c, 0xa9, 0xc8, 0xc6, 0x12, 0x8c, 0xa4, - 0xf0, 0x8f, 0x43, 0xfa, 0x94, 0x89, 0x88, 0x4c, 0x87, 0xf5, 0xd9, 0x5a, 0x71, 0x38, 0x97, 0x85, 0x4a, 0xed, 0x4b, - 0x31, 0x1e, 0x8c, 0x8b, 0xf2, 0x19, 0xc6, 0x74, 0x9c, 0x6d, 0xb0, 0xbd, 0xc3, 0x2e, 0x0b, 0xb9, 0x2b, 0xed, 0xb0, - 0xd4, 0x2c, 0xdb, 0x7c, 0x6d, 0x42, 0xaa, 0x36, 0xa3, 0x60, 0xa2, 0xd5, 0x80, 0xaa, 0xc0, 0x1d, 0x50, 0xd8, 0x06, - 0xa5, 0x49, 0x57, 0x65, 0xc9, 0x74, 0x55, 0x2e, 0xc3, 0x59, 0xab, 0xb5, 0xd9, 0xe0, 0x82, 0x99, 0x40, 0x2e, 0x7b, - 0x4b, 0x40, 0xbe, 0x9a, 0xc9, 0x9b, 0x20, 0x57, 0xa5, 0xe5, 0x2c, 0xcd, 0x12, 0x45, 0x81, 0x11, 0x6c, 0xb4, 0xc1, - 0x5f, 0xb8, 0xe2, 0x00, 0x4f, 0x37, 0xbb, 0x91, 0x94, 0x39, 0xa3, 0x10, 0x43, 0x2d, 0x68, 0x72, 0x83, 0x67, 0x7c, - 0xcc, 0xf6, 0xb7, 0x09, 0x66, 0xcc, 0xff, 0x5e, 0x8b, 0x1e, 0x81, 0x2c, 0xbb, 0x67, 0x50, 0x07, 0x16, 0x71, 0x0d, - 0x1d, 0x84, 0x32, 0xf8, 0x24, 0xc4, 0xcd, 0x9c, 0xde, 0xc9, 0xa5, 0x06, 0xb8, 0x2c, 0xb5, 0x7c, 0xed, 0xc2, 0x21, - 0x1c, 0xb6, 0xb0, 0x8f, 0x8c, 0xb0, 0x82, 0x90, 0x01, 0x2d, 0x6c, 0x23, 0x62, 0xb4, 0xb0, 0x0b, 0x54, 0xd0, 0xc2, - 0x26, 0x3c, 0x45, 0x6b, 0x53, 0xc6, 0x36, 0xbb, 0x2b, 0x9f, 0xd4, 0xac, 0x36, 0xc1, 0xc2, 0x49, 0x87, 0x9a, 0xe8, - 0xe0, 0xf6, 0x90, 0x11, 0xde, 0xf8, 0xf1, 0xfa, 0xd5, 0x4b, 0x17, 0xb9, 0x9a, 0x4f, 0xc0, 0x65, 0xd3, 0xa9, 0xc6, - 0xee, 0x6c, 0x88, 0xf9, 0x4a, 0x51, 0x6a, 0x85, 0x53, 0x13, 0xec, 0x53, 0xe8, 0x3c, 0xb1, 0x97, 0x17, 0xcf, 0x64, - 0x31, 0xa7, 0xf6, 0xc6, 0x08, 0xdf, 0x29, 0xf7, 0xf8, 0xbc, 0x79, 0xdf, 0xa6, 0x9a, 0xe4, 0xdb, 0xed, 0xab, 0x88, - 0x45, 0x66, 0xe4, 0x57, 0xd0, 0x06, 0x98, 0xca, 0x7e, 0xe0, 0xac, 0x20, 0x2e, 0xfe, 0x7f, 0x40, 0x5e, 0xde, 0x58, - 0xea, 0x12, 0x45, 0x0d, 0x6e, 0xf0, 0x93, 0x15, 0x3c, 0x0b, 0xae, 0x0b, 0x0d, 0x7b, 0xe4, 0xc4, 0x8b, 0xa8, 0x15, - 0xd5, 0xdf, 0xde, 0x35, 0xaa, 0x04, 0x1f, 0x3b, 0x36, 0xc9, 0x25, 0x88, 0x1e, 0xe5, 0x33, 0x7f, 0x1c, 0x44, 0x13, - 0x7f, 0xf7, 0x7c, 0xd5, 0xf6, 0x74, 0x36, 0xaf, 0xd4, 0x89, 0xe5, 0x95, 0x09, 0x78, 0x38, 0xda, 0x87, 0x74, 0x10, - 0x0e, 0x12, 0x59, 0xa9, 0x3d, 0xf4, 0xb9, 0xa8, 0x17, 0xe7, 0x97, 0x6d, 0xd6, 0x3c, 0x5b, 0xaf, 0xf3, 0xab, 0x36, - 0x6b, 0x77, 0xed, 0xb3, 0x7b, 0x91, 0xca, 0x80, 0xe6, 0xf2, 0x09, 0xcf, 0x22, 0xd0, 0xce, 0x4e, 0x33, 0x13, 0x4e, - 0x61, 0xe3, 0x15, 0x3f, 0x4b, 0x5d, 0xf5, 0x25, 0xc1, 0xb8, 0x94, 0x58, 0x3d, 0x7e, 0x81, 0xfa, 0xed, 0x74, 0xd7, - 0x55, 0xba, 0xd9, 0x3e, 0x0e, 0x2e, 0x5c, 0x0a, 0x84, 0x3b, 0x10, 0xf2, 0x00, 0xf4, 0xbb, 0x2b, 0x01, 0xa6, 0x41, - 0x80, 0xca, 0x0a, 0x44, 0x5a, 0x3e, 0x5f, 0xce, 0x9f, 0x15, 0xd4, 0x2c, 0xc3, 0x13, 0x3e, 0xe5, 0x5a, 0xa5, 0x14, - 0xa4, 0xdb, 0x7d, 0xe9, 0x9b, 0xfd, 0x12, 0x54, 0x56, 0x8b, 0xbf, 0x9b, 0x68, 0x9e, 0x7d, 0x56, 0x6e, 0xe1, 0x10, - 0x36, 0x2b, 0x2b, 0x70, 0x86, 0x36, 0x38, 0x97, 0x53, 0x5a, 0x70, 0x3d, 0x9b, 0xff, 0x5b, 0xab, 0xc3, 0x06, 0x7a, - 0x68, 0x2e, 0xac, 0x00, 0x24, 0x54, 0x8c, 0xd7, 0x6b, 0x7e, 0xf2, 0xed, 0xfb, 0x24, 0xef, 0x13, 0xde, 0xc6, 0x1d, - 0x7c, 0x8a, 0xbb, 0xb8, 0xdd, 0xc2, 0xed, 0x2e, 0x5c, 0xdd, 0x67, 0xf9, 0x72, 0xcc, 0x54, 0x0c, 0xef, 0xaf, 0xe9, - 0xab, 0xe4, 0xe2, 0xb8, 0x7a, 0x75, 0xa0, 0x48, 0x1c, 0xba, 0x04, 0xc1, 0xef, 0x5d, 0xd4, 0xc0, 0x28, 0x0a, 0x43, - 0xd6, 0x4d, 0x43, 0xd5, 0x49, 0xa9, 0x5f, 0xb8, 0x3a, 0xed, 0x83, 0x3d, 0xb7, 0x5d, 0xd9, 0x26, 0x98, 0x7d, 0xdb, - 0x9f, 0x69, 0xf5, 0xb3, 0xa9, 0x4b, 0xc4, 0xf0, 0xd0, 0xab, 0xd0, 0x03, 0x5d, 0x91, 0xf6, 0xd1, 0x11, 0x58, 0x1d, - 0x05, 0xb3, 0xe1, 0x36, 0xfa, 0x01, 0x6f, 0xd6, 0xd2, 0x20, 0x58, 0x01, 0x18, 0x77, 0xbe, 0xe2, 0x64, 0x65, 0x61, - 0xab, 0x81, 0x0a, 0xb3, 0x22, 0x8c, 0xab, 0x17, 0x92, 0x0a, 0x23, 0x44, 0xc3, 0x11, 0xe6, 0x82, 0xa1, 0x1c, 0xb6, - 0xb0, 0x9c, 0x4c, 0x14, 0xd3, 0x70, 0x74, 0x14, 0xec, 0x0b, 0x2b, 0x94, 0x39, 0x45, 0x46, 0x6c, 0xca, 0xc5, 0x43, - 0xfd, 0x07, 0x2b, 0xa4, 0xf9, 0x34, 0x1a, 0x8c, 0x34, 0x32, 0xab, 0x18, 0xe1, 0x2c, 0xe7, 0x0b, 0xa8, 0x3a, 0x2d, - 0xc0, 0xe9, 0x07, 0xfe, 0xf2, 0x71, 0x1a, 0xb6, 0x09, 0xe4, 0xeb, 0x37, 0x1b, 0xd3, 0x05, 0x8f, 0x0b, 0x7a, 0xf3, - 0x4a, 0x3c, 0x86, 0x1d, 0xf5, 0xb0, 0x60, 0x14, 0xb2, 0x21, 0xe9, 0x2d, 0x34, 0x05, 0x1f, 0xd0, 0xe6, 0xcf, 0x06, - 0x70, 0xe9, 0x85, 0xf9, 0xb0, 0x15, 0x7d, 0xec, 0xc6, 0xa4, 0x6c, 0xcb, 0x64, 0x9a, 0x53, 0xba, 0xca, 0xb4, 0x51, - 0xa8, 0xca, 0x29, 0x6c, 0xb0, 0x8b, 0x7a, 0x12, 0x0e, 0x66, 0x4c, 0xd5, 0x2c, 0x1d, 0x0c, 0xcd, 0xdf, 0x57, 0xb6, - 0x64, 0x0b, 0xbb, 0x88, 0x33, 0x1b, 0x6c, 0x1e, 0x4e, 0x0d, 0xca, 0xb7, 0x31, 0xdc, 0xc3, 0xc2, 0xeb, 0x9d, 0x35, - 0xf2, 0x79, 0xe6, 0xc9, 0xe6, 0xd9, 0x66, 0x63, 0x06, 0xa2, 0x52, 0xd0, 0x03, 0xbd, 0xf1, 0xdb, 0xa6, 0x05, 0xdb, - 0xa3, 0xfc, 0xea, 0xb6, 0xf0, 0x9c, 0xc3, 0x63, 0xa4, 0xbe, 0xbd, 0x6b, 0x5d, 0xc8, 0xcf, 0x0e, 0x24, 0xad, 0x20, - 0xc5, 0x4e, 0x27, 0xe8, 0xec, 0x14, 0x07, 0x23, 0x07, 0x7a, 0x7e, 0xfd, 0xd9, 0xc2, 0xda, 0xff, 0x7e, 0x5d, 0x16, - 0x34, 0xf1, 0x74, 0xca, 0x09, 0x65, 0xfe, 0xfc, 0x7c, 0xc5, 0x93, 0x0a, 0x15, 0xdc, 0x2b, 0x5e, 0xb0, 0xa7, 0x6d, - 0xa0, 0xcf, 0x39, 0xfd, 0x64, 0x7f, 0xd8, 0x18, 0x3e, 0xa5, 0x96, 0x2d, 0x2b, 0xa4, 0x52, 0x0f, 0x6d, 0x9a, 0x3d, - 0x7a, 0xe0, 0x88, 0xfc, 0x19, 0xba, 0x00, 0x5e, 0x7f, 0x5c, 0xc8, 0x85, 0x41, 0x04, 0xf7, 0xdb, 0x8d, 0xdb, 0xf8, - 0x0a, 0x80, 0xb7, 0xc3, 0x41, 0xf5, 0x4f, 0x0b, 0xd8, 0xdf, 0xa8, 0x2c, 0xe9, 0xc7, 0xdb, 0xb1, 0xc7, 0x7f, 0x21, - 0x21, 0x6a, 0xbc, 0xc5, 0xc3, 0xc4, 0xa1, 0x53, 0xc9, 0x9a, 0x95, 0x3f, 0x77, 0x4a, 0x02, 0x86, 0xd5, 0x0b, 0x86, - 0x6c, 0xdc, 0x4e, 0x71, 0x9b, 0xf9, 0x1f, 0x54, 0x30, 0x58, 0xf0, 0xb5, 0x91, 0x54, 0x2c, 0x8b, 0xdf, 0x3e, 0x75, - 0xfe, 0xab, 0xce, 0x71, 0x1d, 0xea, 0xda, 0x4b, 0xa1, 0x23, 0x13, 0xa5, 0x39, 0x42, 0x47, 0x47, 0x5b, 0x19, 0x74, - 0x02, 0x80, 0x47, 0x8e, 0xfd, 0xf2, 0xcb, 0xe7, 0xd9, 0x31, 0xa3, 0x79, 0x2c, 0xa2, 0x90, 0xb9, 0xf3, 0xdc, 0x9c, - 0x9d, 0xc8, 0x13, 0xaa, 0x66, 0xbe, 0x30, 0xc0, 0xf1, 0xd1, 0x4e, 0x2a, 0xe0, 0x7b, 0xb4, 0xd9, 0x33, 0x81, 0x2d, - 0x7e, 0xcb, 0x4e, 0x6a, 0x5f, 0x41, 0xbf, 0x40, 0xab, 0x7d, 0x4c, 0xe5, 0xd6, 0x02, 0x47, 0xdb, 0x13, 0xd9, 0x3b, - 0xf4, 0xad, 0x3a, 0x25, 0xeb, 0xf1, 0x62, 0xbf, 0xd1, 0x57, 0x21, 0xf6, 0x25, 0x57, 0xb4, 0x6d, 0xc4, 0xaa, 0xd7, - 0x82, 0x75, 0x65, 0xea, 0x54, 0x5d, 0xf3, 0x56, 0x96, 0x36, 0xa5, 0x5d, 0x92, 0xbd, 0xdb, 0x62, 0xe1, 0x55, 0x78, - 0xa3, 0x51, 0x5e, 0x84, 0x82, 0x3d, 0x96, 0x18, 0xf6, 0x38, 0x81, 0xeb, 0x85, 0xf5, 0x3a, 0x86, 0x3f, 0xfb, 0xc6, - 0xb0, 0xcf, 0x74, 0xe9, 0x37, 0xbe, 0xc5, 0xaf, 0x04, 0x01, 0x8b, 0x9d, 0x1d, 0x24, 0x58, 0x77, 0xb9, 0x41, 0xc3, - 0x71, 0xe2, 0xbf, 0xe0, 0xb9, 0x6c, 0xed, 0x5d, 0x0e, 0x46, 0xd9, 0x57, 0x9e, 0xd8, 0x2b, 0x59, 0xcb, 0x5a, 0xb4, - 0xfb, 0x2d, 0x09, 0x86, 0xd8, 0x4d, 0xe9, 0x1c, 0xb7, 0x92, 0x36, 0x8a, 0x5c, 0xb1, 0x0a, 0xfd, 0xbf, 0x56, 0x24, - 0xb3, 0x99, 0xff, 0x75, 0x7e, 0x7e, 0xee, 0x52, 0x9c, 0xcd, 0x9f, 0x32, 0x1e, 0x70, 0x26, 0x81, 0x7d, 0xe1, 0x19, - 0x33, 0x3a, 0xe4, 0x37, 0x30, 0x14, 0x22, 0xc8, 0x95, 0x70, 0xec, 0x12, 0xbc, 0xf6, 0x08, 0x94, 0x07, 0xd8, 0xbf, - 0x27, 0x5b, 0xe5, 0xfc, 0x73, 0x51, 0x3e, 0x9c, 0x72, 0xd9, 0x20, 0xfb, 0x62, 0x3e, 0x07, 0xd6, 0x4c, 0x06, 0x5e, - 0x48, 0x88, 0xb0, 0xfd, 0x6d, 0x58, 0x5a, 0x67, 0x29, 0x83, 0x23, 0x2d, 0x97, 0xd9, 0xcc, 0x6a, 0xfe, 0xdd, 0x87, - 0x29, 0xeb, 0x9e, 0x1a, 0x82, 0xc8, 0x5d, 0x64, 0xe5, 0xa2, 0x82, 0x46, 0xdf, 0x97, 0x01, 0x40, 0x0f, 0x5e, 0xb2, - 0x25, 0xfb, 0x1e, 0x1f, 0x54, 0x29, 0xf0, 0xf1, 0xb0, 0xe0, 0x34, 0xff, 0x1e, 0x1f, 0x54, 0x81, 0x40, 0xc1, 0x15, - 0xd2, 0xc4, 0xd2, 0xc4, 0xe6, 0x59, 0xed, 0x34, 0x12, 0x40, 0x41, 0xf3, 0xc8, 0x1c, 0x64, 0xcf, 0x5d, 0x8c, 0xc6, - 0xa4, 0x83, 0x5d, 0x70, 0x30, 0x1b, 0x11, 0xd6, 0x06, 0x52, 0x87, 0xb8, 0x75, 0xe5, 0x6c, 0xcc, 0xd7, 0xa3, 0xad, - 0x05, 0x31, 0xca, 0x64, 0x72, 0xf5, 0x8e, 0xc7, 0x3b, 0x8b, 0x85, 0xc2, 0x6a, 0xc1, 0x02, 0xd5, 0xaa, 0x54, 0xe9, - 0x61, 0xf1, 0xdd, 0x82, 0x59, 0x50, 0xc4, 0x6c, 0xbd, 0x87, 0xb7, 0x5c, 0x11, 0x90, 0x92, 0x5d, 0x12, 0xbc, 0x8c, - 0x6e, 0x30, 0x95, 0xac, 0xe6, 0x72, 0xcc, 0x2c, 0xa1, 0x67, 0x4a, 0x47, 0xd8, 0xe4, 0x29, 0x88, 0x24, 0x76, 0xd8, - 0xc2, 0x8e, 0x35, 0x7a, 0x21, 0xbc, 0x90, 0x02, 0xe7, 0xaa, 0x69, 0x62, 0x4e, 0xb9, 0x89, 0x2e, 0xf6, 0x50, 0x2d, - 0x58, 0xa6, 0x2d, 0x02, 0x1c, 0x3a, 0x34, 0x94, 0xe2, 0xb9, 0x01, 0x85, 0x79, 0xd2, 0xdb, 0xa5, 0x3c, 0x86, 0xc5, - 0x0b, 0x52, 0x80, 0xa8, 0x71, 0x31, 0x2d, 0xeb, 0x2c, 0xf2, 0xe5, 0x94, 0x8b, 0x0a, 0x19, 0x0a, 0xa6, 0x16, 0x52, - 0xc0, 0x8b, 0x1a, 0x65, 0x11, 0x43, 0x87, 0x6a, 0xf8, 0x6e, 0x49, 0x58, 0x59, 0xc7, 0x1c, 0x53, 0x5c, 0x54, 0x35, - 0x80, 0xb9, 0x78, 0x68, 0x04, 0x44, 0x1f, 0x5e, 0xf6, 0x95, 0x78, 0x2b, 0x17, 0x55, 0xbe, 0xa7, 0x71, 0x3e, 0x70, - 0xbd, 0xb3, 0x1b, 0x46, 0x1b, 0xf3, 0xe8, 0x55, 0xb0, 0x7d, 0x7f, 0xe3, 0xd5, 0x43, 0x70, 0x1b, 0xf3, 0x6c, 0x56, - 0x99, 0x35, 0x62, 0xe5, 0x1b, 0x11, 0x55, 0x7b, 0xf5, 0xaa, 0x85, 0xb0, 0x15, 0x01, 0x2a, 0x05, 0x1f, 0xef, 0xe4, - 0xbf, 0xd0, 0x36, 0xdf, 0x9e, 0x43, 0x65, 0x78, 0x20, 0x4f, 0x86, 0xaa, 0x1e, 0x70, 0x51, 0x7e, 0x08, 0x60, 0xf1, - 0x23, 0x13, 0x3f, 0x78, 0xdf, 0x05, 0x32, 0x67, 0x2a, 0x96, 0x78, 0x35, 0xa0, 0xc3, 0xd4, 0xca, 0x43, 0xa9, 0x04, - 0xdb, 0x9e, 0x9b, 0x82, 0x6b, 0x1f, 0xa8, 0x18, 0x0f, 0xd8, 0x30, 0x5d, 0xd5, 0x83, 0x19, 0xdb, 0x70, 0xca, 0xde, - 0x9c, 0xd3, 0x44, 0xff, 0xa5, 0x43, 0x9c, 0x13, 0xb0, 0x3d, 0x2e, 0x99, 0xfb, 0x38, 0x43, 0xfd, 0x3a, 0x87, 0xbf, - 0xda, 0xe0, 0x1c, 0x67, 0x28, 0x7d, 0x18, 0xc3, 0x05, 0xd6, 0x06, 0x03, 0xf8, 0x32, 0x4b, 0xaa, 0xc0, 0x23, 0x35, - 0x33, 0x12, 0xab, 0xbb, 0x08, 0x44, 0x2b, 0x1d, 0xde, 0x8e, 0x33, 0x1f, 0x0e, 0xdc, 0x70, 0xaf, 0xcf, 0x8c, 0x70, - 0x38, 0xca, 0xe2, 0xda, 0x39, 0xc3, 0xc9, 0xd5, 0x21, 0xaf, 0x9d, 0x98, 0x60, 0xed, 0x1d, 0x9e, 0x2a, 0xa0, 0x47, - 0x83, 0x53, 0xc5, 0xd2, 0x10, 0x88, 0x99, 0x00, 0xde, 0xcc, 0xe1, 0xd1, 0x16, 0xe0, 0x7c, 0xb4, 0xc1, 0xc1, 0x57, - 0x5a, 0xeb, 0x6a, 0x5b, 0x89, 0xb2, 0xd9, 0xe0, 0xc1, 0x32, 0xc3, 0x93, 0x0c, 0xcf, 0xb3, 0x61, 0x70, 0xdc, 0x7c, - 0xcc, 0x42, 0x93, 0xae, 0xf5, 0xfa, 0x85, 0x33, 0x23, 0x44, 0xf6, 0xa7, 0xa5, 0x3f, 0xa8, 0x0f, 0x08, 0x9f, 0x42, - 0x16, 0xd0, 0x92, 0xbe, 0xfb, 0xdb, 0xb0, 0xaf, 0x85, 0xa3, 0x46, 0xcc, 0x13, 0x4b, 0x46, 0xfa, 0xfe, 0x47, 0x99, - 0x65, 0x5b, 0x6b, 0x44, 0x8b, 0xdb, 0x83, 0xa8, 0xe1, 0xdb, 0xab, 0xce, 0x97, 0x51, 0x69, 0xb6, 0x03, 0x88, 0x62, - 0x8d, 0x93, 0x74, 0xb0, 0x46, 0x72, 0xbd, 0x8e, 0x6d, 0x0a, 0xe1, 0xc9, 0x9c, 0x51, 0xb5, 0x2c, 0xcc, 0x03, 0x7a, - 0xb1, 0x42, 0x89, 0xe1, 0x77, 0xb1, 0xb3, 0x11, 0x85, 0xf7, 0xea, 0x24, 0x18, 0x6e, 0xc4, 0x82, 0xc8, 0x9a, 0xc8, - 0x7d, 0x97, 0x55, 0x96, 0x41, 0x82, 0x08, 0x23, 0xf2, 0xdb, 0xeb, 0x52, 0x61, 0x9f, 0xe8, 0xb3, 0x7f, 0x8c, 0x2f, - 0x20, 0xdc, 0xbc, 0x4d, 0x69, 0x31, 0xa2, 0x53, 0x60, 0x63, 0x21, 0x0e, 0xe1, 0x4e, 0xc2, 0x7a, 0x3d, 0x18, 0xf6, - 0x84, 0x21, 0xcf, 0xee, 0x01, 0xc1, 0xb2, 0xa1, 0xfd, 0x0d, 0xc0, 0x55, 0xb7, 0xa5, 0xe6, 0xda, 0xe8, 0x7e, 0xa8, - 0x79, 0xe3, 0x8c, 0xbb, 0x24, 0xf7, 0x4c, 0x49, 0xf5, 0x12, 0x79, 0xcd, 0x02, 0xdc, 0x84, 0xae, 0xc2, 0x63, 0xbc, - 0xb4, 0x36, 0x9c, 0xe6, 0x41, 0x2b, 0x6a, 0xde, 0xb1, 0x82, 0xe7, 0xb3, 0x09, 0x1b, 0x64, 0x43, 0x3c, 0xf6, 0xe1, - 0xce, 0x0f, 0xdf, 0xc4, 0x63, 0x84, 0x0a, 0x62, 0x60, 0x6a, 0x5d, 0xb6, 0xc7, 0x95, 0xdd, 0xbe, 0xc9, 0x34, 0x0c, - 0x83, 0x31, 0x62, 0x1e, 0x87, 0x46, 0xcc, 0x79, 0xa3, 0x81, 0x96, 0x64, 0x0c, 0x46, 0xcc, 0xcb, 0xa0, 0xb5, 0xa5, - 0x7d, 0xec, 0x34, 0x68, 0x6f, 0x89, 0x50, 0x8f, 0x03, 0x4d, 0xd3, 0xf0, 0xac, 0x49, 0xf5, 0xac, 0xbc, 0x7f, 0x64, - 0xeb, 0xa4, 0x03, 0x8a, 0x84, 0xc9, 0x95, 0x9f, 0x84, 0x75, 0x0d, 0xb7, 0xe3, 0x9e, 0x98, 0x71, 0x3b, 0xdb, 0x06, - 0x35, 0x90, 0x83, 0x6c, 0x38, 0xec, 0x49, 0x6f, 0x25, 0xd1, 0xc2, 0x93, 0xea, 0x21, 0x94, 0x6a, 0xf1, 0xbe, 0xe8, - 0xed, 0x2b, 0x6f, 0xee, 0xdf, 0x57, 0xdd, 0x3e, 0x8f, 0x81, 0x03, 0x3a, 0x84, 0xfb, 0xa1, 0x2a, 0x3e, 0xd8, 0x49, - 0x07, 0xa2, 0xa0, 0xa5, 0xad, 0x9a, 0x40, 0x6a, 0xcd, 0xec, 0x62, 0xdd, 0x54, 0xe8, 0x58, 0x40, 0x18, 0x32, 0x55, - 0x75, 0x77, 0xab, 0x02, 0xd5, 0x10, 0x87, 0x53, 0xff, 0xb1, 0x35, 0x62, 0x8d, 0xa3, 0xce, 0x38, 0x32, 0x46, 0x92, - 0x76, 0xf9, 0xe0, 0xed, 0x23, 0xb0, 0x12, 0xf0, 0x31, 0xa8, 0x4d, 0x92, 0x31, 0x24, 0x78, 0xc3, 0x32, 0x6d, 0xf8, - 0x10, 0xee, 0x10, 0x94, 0x27, 0x36, 0x28, 0xad, 0xab, 0x64, 0x21, 0x17, 0x74, 0x19, 0xa0, 0xe7, 0x97, 0xf2, 0x37, - 0x36, 0x1c, 0x59, 0x00, 0x87, 0x6c, 0x67, 0x9f, 0x80, 0x47, 0x3e, 0xae, 0x10, 0xc4, 0x2f, 0x85, 0x4e, 0x4c, 0xbc, - 0xee, 0x6b, 0xd8, 0xa0, 0x78, 0x01, 0x0e, 0x82, 0x4e, 0x82, 0xc3, 0xe0, 0x5d, 0x66, 0x35, 0xc9, 0x06, 0xb7, 0xe6, - 0x24, 0x5e, 0xac, 0xd7, 0x2d, 0x74, 0xfc, 0x93, 0x79, 0x92, 0x7a, 0x52, 0x2a, 0xdc, 0x27, 0x95, 0xc2, 0x1d, 0x2c, - 0x01, 0xc9, 0x24, 0xd0, 0xb5, 0x63, 0x19, 0xaa, 0xd1, 0x21, 0x5a, 0xfa, 0x0b, 0x88, 0x9d, 0xed, 0x8e, 0x25, 0xd0, - 0xb3, 0xef, 0x14, 0xb0, 0xba, 0xf6, 0xb2, 0x04, 0x32, 0x82, 0xbb, 0xdf, 0x04, 0x46, 0x85, 0x68, 0x7c, 0xfe, 0xcc, - 0xab, 0x16, 0x3c, 0x71, 0xfe, 0x5c, 0x73, 0xc3, 0xba, 0x17, 0xf4, 0xc6, 0x34, 0x1f, 0x4f, 0x70, 0x73, 0x62, 0xc1, - 0x79, 0xd2, 0x81, 0x9f, 0x16, 0xa2, 0x27, 0x1d, 0xec, 0x52, 0xf1, 0xa4, 0x04, 0x72, 0x88, 0x9e, 0xce, 0x40, 0x0a, - 0x58, 0xe9, 0xd8, 0x6a, 0x91, 0xa6, 0x68, 0xbd, 0x9e, 0x5e, 0x92, 0x16, 0x42, 0x2b, 0x75, 0xc3, 0x75, 0x36, 0x03, - 0x1f, 0x69, 0x50, 0x0c, 0xbc, 0xa6, 0x7a, 0x16, 0x23, 0x3c, 0x41, 0xab, 0x31, 0x9b, 0xd0, 0x65, 0xae, 0x53, 0xd5, - 0xe7, 0x89, 0x0d, 0xdc, 0xcb, 0x6c, 0x24, 0xb8, 0x93, 0x0e, 0x9e, 0x1a, 0xfe, 0xf2, 0xbd, 0x31, 0x07, 0x29, 0x32, - 0x93, 0x3c, 0x35, 0x09, 0x98, 0x27, 0x59, 0x2e, 0x15, 0xb3, 0xcd, 0xf4, 0xac, 0x6d, 0x39, 0x84, 0x24, 0x8f, 0x74, - 0xc1, 0x8d, 0x15, 0x65, 0x94, 0xce, 0x88, 0xea, 0xab, 0x93, 0x4e, 0x3a, 0xc5, 0x3c, 0x01, 0x4e, 0xef, 0xad, 0x8c, - 0x59, 0xa3, 0xbc, 0x15, 0x9d, 0xa3, 0xe3, 0x19, 0x16, 0xd5, 0x25, 0xea, 0x1c, 0x1d, 0x4f, 0x11, 0x9e, 0x37, 0xc8, - 0x4c, 0x81, 0xc7, 0x30, 0x17, 0xff, 0x47, 0xca, 0x7f, 0x75, 0xd8, 0x10, 0x62, 0xfa, 0x0d, 0xec, 0x14, 0x36, 0x8e, - 0xd2, 0x9c, 0x80, 0xd7, 0x62, 0xfb, 0x1c, 0x67, 0x64, 0xda, 0xcc, 0x7d, 0xc0, 0x3d, 0xd3, 0x4a, 0xe3, 0x56, 0xa3, - 0xe3, 0x0c, 0x8f, 0xb7, 0x93, 0x62, 0x33, 0xd7, 0x66, 0x9e, 0x66, 0x70, 0xbe, 0x57, 0xa3, 0x70, 0xe5, 0x97, 0xdb, - 0x49, 0x61, 0x79, 0x07, 0xdc, 0xe6, 0x18, 0x8b, 0x26, 0xc5, 0x39, 0x9e, 0x37, 0x5f, 0xe2, 0x79, 0xf3, 0x5d, 0x99, - 0xd1, 0x58, 0x62, 0x01, 0xc1, 0xfb, 0x20, 0x11, 0xcf, 0xab, 0xe4, 0x31, 0x16, 0x0d, 0x53, 0x1e, 0xcf, 0x1b, 0x55, - 0xe9, 0xe6, 0x12, 0x8b, 0x86, 0x29, 0xdd, 0x78, 0x87, 0xe7, 0x8d, 0x97, 0xff, 0x62, 0xd2, 0x51, 0x0a, 0xe8, 0xb2, - 0x40, 0xab, 0xcc, 0x0e, 0xf1, 0xfa, 0xd7, 0x37, 0x6f, 0xdb, 0x1f, 0x3b, 0xc7, 0x53, 0xec, 0xd7, 0x2f, 0x33, 0x38, - 0x96, 0xe9, 0x98, 0x35, 0x01, 0xa2, 0x19, 0xee, 0x1c, 0xcf, 0x70, 0xe7, 0x38, 0x73, 0x4d, 0x6d, 0xe6, 0x0d, 0x72, - 0xab, 0x43, 0x28, 0xea, 0x28, 0x0d, 0xe1, 0xe3, 0x27, 0x9b, 0x4e, 0x51, 0x0d, 0x94, 0xe8, 0x78, 0x5a, 0x03, 0x15, - 0x7c, 0x2f, 0x6b, 0xdf, 0x55, 0xbd, 0x0a, 0x83, 0x2c, 0x94, 0x50, 0xb8, 0xe6, 0x06, 0x3c, 0xb5, 0x14, 0x03, 0x99, - 0x30, 0xc5, 0x02, 0xe5, 0x1b, 0xa0, 0x30, 0xca, 0x13, 0x33, 0xf4, 0x60, 0x3a, 0x26, 0xf1, 0xff, 0xe7, 0xc9, 0x94, - 0x43, 0x2f, 0xb7, 0xcc, 0xce, 0xf4, 0xdc, 0x64, 0xc2, 0xe1, 0x03, 0x8f, 0xf5, 0x7f, 0xed, 0x40, 0xb1, 0x01, 0x29, - 0xfe, 0xbf, 0x74, 0x74, 0x21, 0x18, 0x21, 0x2b, 0x4a, 0x0b, 0x87, 0xf8, 0xdf, 0x1e, 0x56, 0xd0, 0x7d, 0xb1, 0xd3, - 0x7d, 0x61, 0xba, 0x0f, 0x9b, 0x36, 0xaa, 0x9c, 0xb4, 0xaa, 0x64, 0xc9, 0x7f, 0x9d, 0x6e, 0xed, 0x80, 0x46, 0xd4, - 0xe8, 0xd9, 0x34, 0x6c, 0xf0, 0xb0, 0x9d, 0xee, 0x41, 0xe6, 0x0d, 0xb7, 0x2f, 0xa4, 0xc2, 0xe1, 0x1b, 0xdc, 0xa9, - 0x5e, 0xb5, 0xc0, 0x7b, 0x53, 0x19, 0x7d, 0x65, 0x1c, 0x5a, 0x0e, 0xd2, 0x6d, 0x53, 0x6e, 0x63, 0x2c, 0x9d, 0x74, - 0xb1, 0x71, 0x45, 0x84, 0x4a, 0xb7, 0x57, 0xa0, 0x14, 0x9f, 0xe8, 0x26, 0x33, 0x5f, 0x97, 0x3a, 0x31, 0x97, 0x50, - 0x0d, 0xf3, 0x79, 0x77, 0xa5, 0x13, 0x2d, 0x17, 0x36, 0xef, 0xee, 0x12, 0xfa, 0x04, 0x0d, 0x6b, 0x23, 0xb0, 0xdb, - 0xe7, 0xce, 0x0e, 0x32, 0x38, 0x04, 0xc3, 0x03, 0xc8, 0x91, 0x16, 0xdb, 0x07, 0x36, 0xad, 0x61, 0xd7, 0x45, 0xb3, - 0x4c, 0xb4, 0xad, 0x36, 0x4d, 0xae, 0xdd, 0xc3, 0x7c, 0x11, 0xf2, 0x14, 0xa2, 0xb0, 0xfa, 0xf1, 0x3d, 0xec, 0xc6, - 0x4d, 0x8d, 0x91, 0xa8, 0x2b, 0x99, 0x4a, 0xe8, 0x27, 0xb7, 0x98, 0x25, 0x77, 0xc6, 0x8b, 0x51, 0x19, 0x7f, 0x1f, - 0x13, 0x97, 0x3f, 0xaa, 0x24, 0x39, 0xb0, 0xec, 0x6f, 0xb0, 0xe4, 0x16, 0xcc, 0x13, 0xcb, 0x6a, 0x12, 0xeb, 0xe4, - 0x2e, 0x58, 0x44, 0x69, 0x1a, 0xd9, 0x18, 0x06, 0xd4, 0x34, 0x63, 0xd5, 0x83, 0x87, 0x10, 0xe8, 0xa1, 0x5f, 0x96, - 0xd2, 0xae, 0xb3, 0xb4, 0xd6, 0xbd, 0x36, 0xdd, 0x6f, 0x0f, 0xa8, 0x9a, 0xc6, 0xe7, 0x80, 0x6b, 0xfa, 0x57, 0x93, - 0x48, 0x46, 0xec, 0x1f, 0xce, 0x8a, 0xc7, 0xcb, 0xc2, 0x60, 0x9a, 0xe8, 0xeb, 0x24, 0x5b, 0xb4, 0xc1, 0x54, 0x2f, - 0x5b, 0x74, 0x6e, 0xb1, 0xfb, 0xbe, 0xb3, 0xdf, 0x77, 0x58, 0xf4, 0x99, 0xc9, 0x48, 0x99, 0x29, 0xe6, 0xbf, 0xef, - 0xec, 0xf7, 0x1d, 0xde, 0x1d, 0xcc, 0xb5, 0xbf, 0x50, 0x2c, 0xd9, 0x19, 0x2e, 0xc1, 0x84, 0x3c, 0xe0, 0x6e, 0x6a, - 0x59, 0x26, 0x08, 0x6c, 0x2d, 0x01, 0xe2, 0x7c, 0xbe, 0x88, 0x2b, 0x5e, 0x0d, 0x01, 0xf7, 0xe9, 0x5d, 0xdb, 0xab, - 0x54, 0xe0, 0x31, 0x41, 0x23, 0x62, 0x62, 0xdb, 0x98, 0xd7, 0xcd, 0x80, 0xcb, 0x23, 0xba, 0xd4, 0x93, 0x24, 0xc0, - 0xab, 0x1a, 0x95, 0xb7, 0x29, 0x52, 0x7e, 0x91, 0x20, 0xc7, 0x17, 0x7b, 0x44, 0x15, 0x03, 0x58, 0x95, 0x25, 0x7d, - 0x02, 0xa9, 0xe7, 0x07, 0x13, 0xfd, 0x65, 0x1b, 0x79, 0xec, 0x3b, 0xbf, 0x9f, 0x99, 0x9e, 0x15, 0x72, 0x39, 0x9d, - 0x81, 0x0f, 0x2d, 0xb0, 0x0c, 0x85, 0xa9, 0x57, 0xd9, 0xfa, 0xd7, 0x24, 0x37, 0x01, 0x14, 0x4e, 0x37, 0x65, 0x42, - 0x33, 0xbd, 0xa4, 0xb9, 0xb1, 0x24, 0xe5, 0x62, 0xfa, 0x48, 0xde, 0xfe, 0x0c, 0xd8, 0x4d, 0x89, 0x6e, 0xec, 0xc9, - 0x7b, 0x03, 0x3b, 0x00, 0x67, 0x84, 0xed, 0xab, 0xf8, 0x50, 0x81, 0xce, 0x1f, 0xe7, 0x84, 0xed, 0xab, 0xfa, 0x84, - 0xd9, 0xec, 0x19, 0xd9, 0x1a, 0x6e, 0x3f, 0xce, 0x1a, 0x39, 0x3a, 0xe9, 0xa4, 0x79, 0xcf, 0x13, 0x03, 0x0b, 0xd0, - 0x00, 0xb8, 0x3b, 0xdb, 0xb3, 0xbc, 0xbb, 0x21, 0xa0, 0x77, 0xc9, 0xa4, 0xbd, 0x2e, 0x37, 0x29, 0xeb, 0x75, 0xa7, - 0xa2, 0x82, 0x05, 0x9e, 0x05, 0x7b, 0x81, 0xda, 0xaf, 0x3d, 0x14, 0xe7, 0x71, 0xb6, 0x6d, 0x7a, 0x5e, 0xf6, 0xdd, - 0xdb, 0xb3, 0xc8, 0xd8, 0xa6, 0xbd, 0xd9, 0x43, 0x24, 0x2c, 0x27, 0xac, 0x03, 0x4e, 0xb8, 0xaa, 0x1d, 0x10, 0xa0, - 0x8f, 0x81, 0xc8, 0x8d, 0x25, 0x59, 0x6d, 0x2a, 0xa3, 0xfb, 0xc0, 0xef, 0x96, 0x12, 0xe9, 0x46, 0x5b, 0x12, 0x4c, - 0x9f, 0x60, 0xd4, 0x74, 0xe6, 0x69, 0xea, 0xda, 0xab, 0xcb, 0xdb, 0xa2, 0xad, 0x7f, 0x03, 0x1a, 0x9b, 0xed, 0x61, - 0x62, 0x28, 0x83, 0x18, 0xe8, 0x7d, 0xc4, 0x7b, 0x8d, 0x46, 0x86, 0x40, 0x21, 0x93, 0x0d, 0xb1, 0x4c, 0xbc, 0x16, - 0xfd, 0xe8, 0xc8, 0xc0, 0xa3, 0x4a, 0x40, 0x98, 0x82, 0x10, 0x12, 0x76, 0x6d, 0x10, 0x36, 0x5c, 0xae, 0x5a, 0x2e, - 0x6c, 0xa4, 0xda, 0xd0, 0xc1, 0xff, 0x2b, 0x5c, 0xb6, 0x7a, 0x66, 0xb9, 0x28, 0x06, 0x37, 0x73, 0x03, 0x16, 0x09, - 0xd2, 0xa3, 0xcd, 0xf6, 0x50, 0xdc, 0x9f, 0x8b, 0xcd, 0x86, 0x80, 0xc4, 0x1c, 0x26, 0x28, 0x1a, 0xce, 0x8d, 0x31, - 0x56, 0x49, 0xa5, 0x65, 0xad, 0x49, 0xcc, 0x41, 0xc0, 0xe8, 0x70, 0xdd, 0x57, 0xb7, 0x29, 0xc3, 0x77, 0xa9, 0xc0, - 0x37, 0xe0, 0x49, 0x93, 0x4a, 0xec, 0x1e, 0x2f, 0x28, 0x36, 0x44, 0xf7, 0x3c, 0x7b, 0x5b, 0xc0, 0x3a, 0x9b, 0x3d, - 0x22, 0x82, 0xdf, 0xd5, 0xaf, 0x36, 0xf8, 0x6e, 0xe1, 0x97, 0x60, 0xfd, 0x1c, 0x9c, 0xa4, 0x58, 0x34, 0x64, 0xb3, - 0x70, 0x47, 0x06, 0x94, 0xab, 0xf8, 0xe5, 0x30, 0x75, 0xa7, 0x18, 0xae, 0x7d, 0xbc, 0xc4, 0xef, 0xb6, 0xda, 0x6d, - 0xa8, 0xb2, 0xb8, 0xdd, 0x9b, 0xa2, 0x21, 0xab, 0xa6, 0xf7, 0x64, 0x6e, 0xa5, 0xd4, 0xbf, 0xde, 0xe1, 0xd6, 0x4e, - 0xfb, 0x7e, 0x9a, 0x6f, 0x3c, 0x3a, 0x57, 0x4d, 0xfb, 0xd4, 0x5a, 0x11, 0x1c, 0xfc, 0x6c, 0xe1, 0xe6, 0xce, 0x80, - 0x03, 0xf8, 0xf9, 0x3b, 0x9a, 0x57, 0x19, 0x44, 0xa7, 0xb7, 0x9a, 0xf1, 0x75, 0xfc, 0xe7, 0xb8, 0x11, 0xf7, 0xd3, - 0x3f, 0x93, 0x3f, 0xc7, 0x0d, 0xd4, 0x47, 0xf1, 0xe2, 0x76, 0xcd, 0xe6, 0x6b, 0x08, 0xb6, 0x76, 0xef, 0x04, 0xbf, - 0x0e, 0x4b, 0x72, 0x4d, 0x73, 0x9e, 0xad, 0xdd, 0x83, 0x80, 0x6b, 0xf7, 0x2a, 0xd1, 0xda, 0xbc, 0x71, 0xb5, 0x8e, - 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, 0x3d, 0xaa, - 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, 0xf5, 0x3d, - 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, 0x96, 0x34, - 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, 0xf2, 0x5d, - 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, 0x06, 0x5f, - 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, 0x87, 0xae, - 0xf2, 0xf0, 0x1e, 0x32, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, 0x61, 0x3e, - 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, 0x64, 0x85, - 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, 0x0c, 0xcb, - 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, 0xba, 0x8d, - 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, 0xf5, 0xd8, - 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, 0x64, 0x62, - 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, 0xee, 0xdc, - 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, 0x2d, 0x76, - 0xae, 0xde, 0xbd, 0xf0, 0x75, 0xbe, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, 0xce, 0xf4, - 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xec, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, 0x0c, 0x94, - 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, 0x20, 0x07, - 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, 0xdf, 0x83, - 0xbb, 0xb3, 0x7b, 0x1d, 0xb2, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, 0x39, 0xbc, - 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, 0x5a, 0xcc, - 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, 0x4b, 0xe9, - 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, 0xcb, 0x95, - 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, 0xa5, 0xe6, - 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x55, 0xc3, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0x2d, 0x4a, 0x09, 0xb5, 0x3b, 0xe8, - 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, 0xb0, 0xea, - 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, 0x81, 0xd1, - 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, 0x71, 0xac, - 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, 0x36, 0x32, - 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, 0xdb, 0x3c, - 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, 0x92, 0x41, - 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, 0x8b, 0x9a, - 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, 0x06, 0xf6, - 0xe9, 0xca, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, 0x2a, 0xe9, - 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, 0x08, 0xfc, - 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, 0x1e, 0x50, - 0x0c, 0xef, 0xae, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, 0x8b, 0x0b, - 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, 0xbf, 0x93, - 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, 0xa2, 0x30, - 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x5a, 0x3b, 0x65, 0x3a, 0x88, 0x0a, 0xf2, - 0xa4, 0x7c, 0x96, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, 0xc8, 0x34, - 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, 0x10, 0x8a, - 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, 0xeb, 0x85, - 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, 0xea, 0x83, - 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, 0x7f, 0xd2, - 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, 0xa9, 0xc6, - 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, 0x81, 0x55, - 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, 0x84, 0x72, - 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, 0xd8, 0xc2, - 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, 0x6f, 0x32, - 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x3c, 0xb0, 0xea, 0x7b, 0x84, 0x98, - 0x99, 0xf8, 0x4f, 0xf0, 0x2c, 0xf4, 0xb7, 0x9f, 0xa3, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, 0xec, 0x3f, - 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, 0xd6, 0xa1, - 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, 0x2d, 0x94, - 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, 0x5e, 0xb5, - 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, 0x61, 0xdb, - 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, 0xbd, 0x28, - 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, 0x70, 0x19, - 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, 0x00, 0x05, - 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0x4f, 0xf2, 0xd6, 0x5e, 0xd0, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, 0xdb, 0x45, - 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, 0x95, 0x9b, - 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, 0x35, 0x90, - 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, 0x10, 0xf2, - 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, 0xc1, 0xe4, - 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, 0x6c, 0x2a, - 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, 0x4a, 0x55, - 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, 0xb2, 0xe5, - 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0x2c, 0x6c, 0xc2, 0xed, 0x30, 0xcd, 0x32, 0x6d, - 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, 0xdf, 0x06, - 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, 0x62, 0x37, - 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, 0x9e, 0x33, - 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, 0x22, 0x57, - 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, 0x03, 0x6a, - 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, 0x2f, 0x43, - 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, 0x33, 0xd4, - 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, 0x25, 0xc0, - 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, 0xd5, 0x9e, - 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, 0xab, 0x8d, - 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, 0xc8, 0xc1, - 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, 0xc2, 0x14, - 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, 0x80, 0x80, - 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, 0xd8, 0xe5, - 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, 0xc8, 0x81, - 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, 0x96, 0xeb, - 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, 0xc4, 0x19, - 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, 0xac, 0x3e, - 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, 0x6a, 0x8b, - 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, 0x1e, 0x36, - 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, 0xe4, 0xaa, - 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, 0x70, 0x23, - 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, 0xfc, 0x4e, - 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, 0x7a, 0x5f, - 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, 0x03, 0x44, - 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, 0xc8, 0x6e, - 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, 0x4c, 0xd9, - 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, 0x2e, 0x40, - 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, 0xb8, 0x30, - 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, 0x5e, 0x66, - 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, 0xad, 0xcd, - 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, 0x47, 0xf7, - 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, 0x1e, 0x6c, - 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, 0x45, 0x19, - 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, 0x89, 0xa0, - 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, 0x6a, 0xd5, - 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, 0xe5, 0xce, - 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, 0x9c, 0xe3, - 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, 0xe4, 0xb6, - 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, 0xa6, 0x82, - 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, 0xef, 0x3d, - 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, 0x5a, 0xbd, - 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, 0x75, 0x0e, - 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, 0x84, 0x56, - 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, 0xce, 0x86, - 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, 0x8b, 0x5e, - 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, 0xcd, 0xb8, - 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, 0x29, 0x84, - 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, 0x24, 0xf3, - 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, 0xc2, 0x18, - 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, 0x02, 0xff, - 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, 0xcc, 0x06, - 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, 0xf0, 0x93, - 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, 0xb7, 0xc0, - 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, 0x95, 0x12, - 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, 0xc0, 0x3b, - 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, 0xae, 0x9f, - 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, 0x6a, 0xc3, - 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, 0x9a, 0xca, - 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, 0x87, 0x80, - 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, 0x3a, 0x3a, - 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, 0x93, 0x0f, - 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, 0x5a, 0x05, - 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, 0xcd, 0x84, - 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, 0xed, 0xbd, - 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, 0x1f, 0x1f, - 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, 0xf6, 0xca, - 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, 0x67, 0xe4, - 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, 0x9c, 0x7c, - 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, 0x76, 0x17, - 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, 0xbb, 0x81, - 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, 0x25, 0xcb, - 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, 0xf8, 0xcf, - 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, 0x86, 0xa6, - 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, 0x1a, 0x43, - 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, 0x77, 0x21, - 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, 0xd8, 0xfb, - 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, 0x82, 0xc4, - 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, 0x7c, 0x75, - 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, 0xac, 0xaa, - 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, 0xe5, 0xe1, - 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, 0x11, 0xc6, - 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, 0xdd, 0x75, - 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, 0x35, 0x97, - 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, 0xa0, 0x51, - 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, 0xb1, 0x7c, - 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, 0x72, 0xbc, - 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, 0x5d, 0x52, - 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0xfc, 0xff, 0xb2, 0xf7, 0xae, 0xcb, 0x6d, - 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, 0xa8, 0x32, - 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, 0xe0, 0x06, - 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, 0xfd, 0x3a, - 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0x2f, 0xe2, 0x05, 0xad, 0x77, 0x15, 0x0a, 0x8f, - 0xaa, 0x28, 0xe5, 0x56, 0x72, 0x9d, 0x41, 0x10, 0x3b, 0x7a, 0x61, 0xf8, 0x13, 0x08, 0x21, 0x88, 0x30, 0xe1, 0xb7, - 0x61, 0x46, 0xdb, 0x59, 0xa4, 0x93, 0x7e, 0x1f, 0x66, 0xb8, 0x81, 0x95, 0xfc, 0x5c, 0xf5, 0xd9, 0x7e, 0x1b, 0x84, - 0x6c, 0x17, 0x44, 0xec, 0xa6, 0xd8, 0x06, 0xa5, 0x75, 0x24, 0x7e, 0x54, 0x86, 0xbf, 0xa5, 0xd7, 0xcb, 0x43, 0x88, - 0xf7, 0xe9, 0xa5, 0xf9, 0x59, 0xda, 0x8a, 0x02, 0xdc, 0x47, 0xe8, 0x51, 0x1d, 0x08, 0x76, 0xc2, 0x13, 0x1e, 0xc0, - 0xc9, 0x6a, 0x56, 0xf1, 0xf7, 0x29, 0x88, 0x13, 0x05, 0x87, 0x80, 0xab, 0xed, 0xc7, 0xf4, 0x2b, 0x18, 0xbe, 0x74, - 0xb0, 0xe5, 0xf0, 0xa6, 0xd8, 0xf6, 0x58, 0xc9, 0xdf, 0x01, 0xfb, 0x56, 0x4f, 0xc6, 0xea, 0xf6, 0xc0, 0x59, 0x97, - 0x52, 0x74, 0xbc, 0x29, 0x0e, 0x6f, 0xcf, 0x67, 0xfb, 0x6d, 0x10, 0xb1, 0x5d, 0x90, 0x61, 0xad, 0x93, 0x86, 0xe3, - 0x60, 0x08, 0x9f, 0xc5, 0x08, 0xfb, 0xbf, 0xac, 0x07, 0x5e, 0x42, 0x6a, 0x28, 0x70, 0x31, 0xd8, 0x70, 0xb4, 0xb6, - 0xcb, 0x34, 0x70, 0x53, 0x83, 0x5e, 0xdf, 0x53, 0x88, 0xf2, 0x92, 0xd1, 0xdc, 0x08, 0xd6, 0x8d, 0x21, 0x17, 0x87, - 0xe3, 0x66, 0x39, 0xe4, 0x25, 0x4d, 0xa7, 0x41, 0x28, 0xdd, 0x59, 0xd6, 0x90, 0x44, 0xd9, 0x07, 0xa1, 0x76, 0x6d, - 0xd9, 0x6f, 0x03, 0xdb, 0x97, 0x3f, 0x1a, 0xc6, 0xfe, 0xc5, 0xf2, 0xb1, 0x90, 0x2e, 0xe2, 0x39, 0x08, 0xa2, 0xf6, - 0xf3, 0x6c, 0xb8, 0xf1, 0x2f, 0xd6, 0x8f, 0x85, 0xf2, 0x1b, 0xcf, 0x6d, 0x39, 0x24, 0xcd, 0x5a, 0xf8, 0xc2, 0x38, - 0x25, 0xb8, 0x32, 0xb4, 0x1d, 0x0e, 0x42, 0xff, 0x6d, 0xd6, 0x08, 0x6e, 0x6c, 0x68, 0x9f, 0x2f, 0x7c, 0xd8, 0xda, - 0x68, 0xac, 0x29, 0xa6, 0x5b, 0xe8, 0xdf, 0x64, 0xb6, 0xb4, 0xa7, 0x51, 0xc9, 0x8b, 0x53, 0xd3, 0x88, 0x85, 0x30, - 0x60, 0xe8, 0x27, 0xf3, 0x0e, 0x54, 0x73, 0xc7, 0x23, 0x90, 0xc9, 0x07, 0x7a, 0xb0, 0x26, 0xb5, 0xea, 0xaf, 0x61, - 0x26, 0xff, 0x8f, 0x54, 0x58, 0x8c, 0xee, 0xb6, 0x61, 0xa6, 0xfe, 0x88, 0xe4, 0x1f, 0x2c, 0xe7, 0xbb, 0xd4, 0x0b, - 0xb5, 0x1f, 0x0b, 0x2b, 0x30, 0x28, 0x51, 0x35, 0xa0, 0x07, 0x22, 0xa8, 0xca, 0x20, 0xcd, 0xb0, 0x3a, 0x07, 0xfd, - 0xee, 0x69, 0xd5, 0x91, 0x1c, 0xd2, 0x5a, 0x0d, 0xa9, 0x60, 0xaa, 0xd4, 0x20, 0x3f, 0x1c, 0x6e, 0x53, 0xa6, 0xcb, - 0x80, 0x4b, 0xfa, 0x6d, 0xaa, 0x94, 0xc2, 0x5f, 0x10, 0x80, 0xce, 0xc1, 0x3d, 0xbe, 0x1c, 0x03, 0x69, 0x86, 0x85, - 0xdf, 0x9a, 0x1d, 0x5f, 0x93, 0x70, 0x9b, 0x04, 0x17, 0x03, 0x9c, 0xa3, 0xab, 0xb0, 0xbc, 0x4d, 0x21, 0x82, 0xaa, - 0x84, 0xfa, 0x56, 0xa6, 0x41, 0x69, 0xab, 0x41, 0x58, 0x93, 0x50, 0x67, 0x92, 0x8d, 0x4a, 0xdb, 0x8d, 0xc2, 0x6c, - 0x11, 0xd7, 0x33, 0xc2, 0x9a, 0xb3, 0x99, 0x6a, 0x60, 0xd2, 0x70, 0xdc, 0x34, 0x5a, 0x8b, 0x0a, 0x35, 0x85, 0x79, - 0x8d, 0xab, 0x4a, 0x55, 0x77, 0x73, 0x6a, 0x29, 0x2d, 0xdb, 0xab, 0x6e, 0x92, 0x0d, 0xb9, 0x0c, 0x65, 0x18, 0x6c, - 0xe4, 0x08, 0x26, 0x90, 0x24, 0x67, 0xfe, 0x46, 0xfe, 0xa1, 0x36, 0x5d, 0x0b, 0x98, 0x63, 0xcc, 0xb2, 0x61, 0x41, - 0xaf, 0xc0, 0x3d, 0xd0, 0x4a, 0xcf, 0xa7, 0xd9, 0x45, 0x1e, 0x24, 0xc3, 0x42, 0x2f, 0x9b, 0x8c, 0x7f, 0x11, 0x46, - 0x9a, 0xcc, 0x58, 0xc9, 0x22, 0xdb, 0xd5, 0x29, 0x71, 0x1e, 0x27, 0xb0, 0x3d, 0x9a, 0xde, 0xf2, 0x7d, 0x06, 0x51, - 0x41, 0xa0, 0x60, 0xc6, 0x7c, 0xd9, 0xc5, 0x13, 0xdf, 0x67, 0x96, 0xa9, 0xfb, 0x70, 0x30, 0x66, 0x6c, 0xbf, 0xdf, - 0xcf, 0xfb, 0x7d, 0x35, 0xdf, 0xfa, 0xfd, 0xe4, 0xa9, 0xf9, 0xdb, 0x03, 0x06, 0x05, 0x39, 0x11, 0x4d, 0x85, 0x08, - 0xfe, 0x21, 0x79, 0x8c, 0x64, 0x74, 0xc7, 0x7d, 0x6e, 0x79, 0x7e, 0x56, 0x47, 0x20, 0x98, 0x87, 0xc3, 0xa5, 0x02, - 0xbb, 0x96, 0x28, 0x12, 0xb2, 0xfc, 0xc7, 0x60, 0x3c, 0x73, 0x1f, 0x60, 0xc9, 0x00, 0x84, 0xad, 0xf2, 0x74, 0xbd, - 0xe7, 0xab, 0xe0, 0x9d, 0x8e, 0x77, 0x8d, 0x15, 0x19, 0x88, 0x5b, 0x60, 0x23, 0xd6, 0xda, 0x03, 0x72, 0xa6, 0x00, - 0xc7, 0x8b, 0xc3, 0xe1, 0x5c, 0xfe, 0xd2, 0xcd, 0xd6, 0x09, 0x54, 0x0a, 0xdc, 0x1e, 0x9d, 0x1c, 0xfc, 0x0f, 0xa0, - 0x19, 0x94, 0xc3, 0xbc, 0xde, 0xfe, 0xc1, 0x9c, 0xfc, 0xf4, 0x14, 0xff, 0x84, 0x87, 0xe8, 0xf4, 0xdb, 0xbd, 0xf9, - 0x83, 0xa2, 0xf2, 0x70, 0x50, 0x8b, 0xff, 0x9c, 0xf3, 0x0a, 0x7e, 0xe1, 0x9b, 0xc0, 0x6c, 0x32, 0xf5, 0x4e, 0xbe, - 0xc9, 0x73, 0xa6, 0x5e, 0xe3, 0x15, 0x93, 0xef, 0x70, 0x38, 0x17, 0xa3, 0x7a, 0x3b, 0x72, 0xa2, 0x9d, 0x72, 0x8c, - 0x83, 0xc1, 0x7f, 0x11, 0x6d, 0x13, 0x02, 0x0c, 0xe5, 0x12, 0xcd, 0x6c, 0x5c, 0x59, 0xe2, 0x59, 0x3a, 0xbf, 0x9c, - 0xd4, 0xe5, 0x4e, 0x2b, 0x9e, 0xf6, 0xc0, 0xe2, 0xb6, 0x06, 0x2f, 0x80, 0x3b, 0x8b, 0xad, 0x2b, 0x05, 0x87, 0x0b, - 0x88, 0x53, 0x9c, 0x80, 0x08, 0xda, 0xef, 0x4b, 0xbc, 0x57, 0xd0, 0x27, 0xfd, 0x04, 0xc1, 0x90, 0xaf, 0x25, 0xe0, - 0xae, 0xd7, 0xab, 0x31, 0xbe, 0x97, 0x42, 0x70, 0x7d, 0xa6, 0x01, 0x68, 0xc1, 0xef, 0xf2, 0xa1, 0x9c, 0x7e, 0x13, - 0x81, 0x67, 0xcb, 0xde, 0x44, 0xb9, 0xdb, 0xf0, 0xb4, 0x1f, 0x5b, 0x08, 0xc0, 0x52, 0x3c, 0x53, 0x82, 0x05, 0x39, - 0xc5, 0x5c, 0xfc, 0xbf, 0xe0, 0x23, 0xe6, 0x7b, 0xd2, 0x45, 0x6c, 0xbd, 0x7d, 0x74, 0x61, 0x20, 0x81, 0xa6, 0x03, - 0xf0, 0xe3, 0x55, 0x40, 0x57, 0xc6, 0x67, 0xd6, 0xb2, 0x1e, 0xeb, 0xe3, 0x3f, 0x05, 0xf7, 0xe9, 0xc7, 0x0a, 0x1f, - 0x1d, 0x8e, 0xab, 0x74, 0xb4, 0xa3, 0x14, 0x44, 0x47, 0xb7, 0xcf, 0xa7, 0x22, 0xfb, 0xae, 0x02, 0x72, 0xcb, 0x51, - 0x7b, 0x2a, 0x00, 0x8b, 0x2d, 0x1d, 0x81, 0x4f, 0xb3, 0x7c, 0x42, 0xbe, 0xd7, 0x53, 0x71, 0x75, 0xa9, 0xd3, 0xc5, - 0xd3, 0xf1, 0x14, 0xfe, 0x07, 0x62, 0x0f, 0x0b, 0x3b, 0xb7, 0x63, 0xd7, 0xc5, 0x0f, 0xe2, 0x6d, 0x6d, 0x47, 0x7f, - 0xec, 0x20, 0xd2, 0x71, 0x4f, 0x2e, 0xd4, 0x97, 0x90, 0x4a, 0x2e, 0xd4, 0x0d, 0xc4, 0x2e, 0xd4, 0x78, 0xc7, 0x45, - 0xac, 0xf5, 0x37, 0x35, 0x0a, 0x56, 0x02, 0xce, 0xb4, 0x37, 0x60, 0xb0, 0x81, 0x75, 0xcb, 0x32, 0xf8, 0x1b, 0xae, - 0x69, 0x02, 0x37, 0x2c, 0xb2, 0xde, 0x1b, 0x6c, 0xa5, 0x37, 0xe0, 0x68, 0x99, 0x38, 0x97, 0x92, 0xa4, 0x6c, 0x91, - 0x71, 0xf5, 0x28, 0xa4, 0x6a, 0xba, 0xbf, 0x11, 0xf5, 0xbd, 0x10, 0x79, 0xb0, 0x4a, 0x59, 0x54, 0xac, 0x40, 0x66, - 0x0f, 0xfe, 0x1e, 0x32, 0x72, 0x94, 0x03, 0x47, 0xa1, 0x7f, 0x36, 0x81, 0xce, 0x23, 0x22, 0x9d, 0x47, 0x82, 0xad, - 0xd4, 0x43, 0x61, 0xe5, 0x05, 0x44, 0x07, 0xab, 0x23, 0xde, 0x54, 0x9e, 0x84, 0x8a, 0x4d, 0x99, 0xc8, 0xe3, 0xa0, - 0x96, 0x80, 0xb1, 0x82, 0x60, 0xce, 0x72, 0xe9, 0x82, 0x54, 0x35, 0x7a, 0x58, 0x64, 0xee, 0x1f, 0x04, 0xe5, 0xff, - 0x41, 0xe5, 0x84, 0xeb, 0xcb, 0x10, 0xe0, 0x68, 0x7f, 0x00, 0x51, 0x62, 0xac, 0x5f, 0xb4, 0x8c, 0x2e, 0x99, 0xb3, - 0xa9, 0xed, 0x25, 0xc8, 0xd8, 0x0e, 0xbf, 0x42, 0x68, 0xb5, 0x50, 0x64, 0xd1, 0x70, 0xc1, 0x74, 0x7b, 0x4a, 0xab, - 0xee, 0x61, 0xc3, 0x93, 0xd2, 0x43, 0xa5, 0xbe, 0x8d, 0x09, 0x2c, 0xab, 0x94, 0xe1, 0xdb, 0x09, 0x55, 0x27, 0x06, - 0x15, 0xeb, 0x86, 0x2d, 0xe1, 0x10, 0x8b, 0x49, 0x63, 0x9d, 0x0d, 0x78, 0xc4, 0x12, 0xf8, 0x67, 0xc3, 0xc7, 0x6c, - 0xc9, 0xa3, 0xc9, 0xe6, 0x6a, 0xd9, 0xef, 0x97, 0x5e, 0xe8, 0xd5, 0xb3, 0xec, 0x87, 0x68, 0x3e, 0xcb, 0xe7, 0x3e, - 0x2a, 0x2e, 0x26, 0x83, 0xc1, 0xc6, 0xcf, 0x86, 0x43, 0x96, 0x0c, 0x87, 0x93, 0xec, 0x07, 0x78, 0xed, 0x07, 0x1e, - 0xa9, 0x25, 0x95, 0x5c, 0x65, 0xb0, 0xbf, 0x0f, 0x78, 0xe4, 0xb3, 0xce, 0x4f, 0xcb, 0xa6, 0x4b, 0xf7, 0x33, 0xab, - 0x03, 0x22, 0xdd, 0x01, 0x36, 0xde, 0x36, 0xe8, 0xc8, 0xbf, 0xdd, 0x21, 0xa5, 0x6e, 0x32, 0x00, 0xbb, 0xd1, 0x00, - 0x87, 0x4c, 0xf5, 0x52, 0x64, 0xf5, 0x52, 0xa6, 0x7a, 0x49, 0x56, 0x2e, 0xc1, 0x42, 0x62, 0xaa, 0xdc, 0x46, 0x56, - 0x6e, 0xd9, 0x70, 0x3d, 0x1c, 0x6c, 0xad, 0xb8, 0x6c, 0x6e, 0xe1, 0xbe, 0xb0, 0xa2, 0xc0, 0xff, 0x1b, 0xb6, 0x60, - 0x77, 0xf2, 0x18, 0xb8, 0x46, 0xc7, 0xa4, 0xc8, 0xab, 0xd8, 0x1d, 0xbb, 0x01, 0x3b, 0x2c, 0xfc, 0x05, 0xd7, 0xc9, - 0x31, 0xdb, 0xe1, 0xa3, 0xd0, 0x2b, 0xd8, 0x8d, 0x4f, 0x40, 0xbb, 0x60, 0x6b, 0x80, 0x6c, 0x6c, 0x8b, 0x8f, 0x6e, - 0x0f, 0x87, 0x6b, 0xcf, 0x67, 0xf7, 0xf8, 0xe3, 0xfc, 0xf6, 0x70, 0xd8, 0x79, 0x46, 0xbd, 0xf7, 0x86, 0x27, 0xec, - 0x11, 0x4f, 0x26, 0x6f, 0xae, 0x78, 0x3c, 0x19, 0x0c, 0xde, 0xf8, 0x0b, 0x5e, 0xcf, 0xde, 0x80, 0x76, 0xe0, 0x7c, - 0x21, 0x75, 0xcd, 0xde, 0x0d, 0xcf, 0xbc, 0x05, 0x8e, 0xcd, 0x0d, 0x1c, 0xbd, 0xfd, 0xbe, 0x77, 0xcb, 0x23, 0xef, - 0x86, 0x54, 0x4c, 0x2b, 0xae, 0x38, 0xde, 0xb6, 0xb8, 0x9f, 0xae, 0x78, 0x08, 0x8f, 0xb0, 0x2a, 0xd3, 0x37, 0xc1, - 0x23, 0x9f, 0xad, 0x34, 0x0b, 0xdc, 0x3d, 0xe6, 0x58, 0x93, 0x9d, 0xd0, 0x4c, 0xfc, 0x15, 0xf6, 0xcf, 0x1b, 0xd5, - 0x3f, 0x34, 0xff, 0x4b, 0xdd, 0x4f, 0xe0, 0xf6, 0x45, 0x16, 0x24, 0xf6, 0x88, 0xbf, 0x61, 0x77, 0xdc, 0xb0, 0xcd, - 0x9e, 0x99, 0xb2, 0x4f, 0x94, 0x1a, 0x3f, 0x50, 0xea, 0xda, 0x82, 0x64, 0x6e, 0x5d, 0xf9, 0x10, 0x38, 0x1c, 0x90, - 0x9f, 0x6e, 0x11, 0x07, 0xa1, 0x75, 0x93, 0xd5, 0x5c, 0x51, 0xce, 0x85, 0x36, 0xca, 0xbc, 0x1c, 0x58, 0xcc, 0x52, - 0x0a, 0x8d, 0x05, 0x00, 0x82, 0x49, 0xa1, 0xb5, 0xf7, 0x32, 0x80, 0x9c, 0xa0, 0xe1, 0x8f, 0xcd, 0x55, 0x49, 0xd6, - 0xb2, 0x25, 0x21, 0xca, 0x76, 0x3d, 0xbc, 0x44, 0xc8, 0xb4, 0x7e, 0xff, 0x9c, 0x48, 0xd6, 0x26, 0xd5, 0x55, 0x8d, - 0x96, 0x80, 0x8a, 0x2c, 0x01, 0x13, 0xbf, 0xd2, 0x7c, 0x02, 0xf0, 0xa4, 0xe3, 0x41, 0xf5, 0x03, 0xaf, 0x99, 0x20, - 0xb2, 0x8d, 0xca, 0x9f, 0x14, 0x4f, 0x91, 0x8c, 0xa0, 0xf8, 0xa1, 0x56, 0x19, 0x0b, 0xc3, 0x3c, 0x50, 0x40, 0xde, - 0xbd, 0x3b, 0xf5, 0x2d, 0xda, 0x9a, 0x8e, 0x3d, 0x5b, 0xab, 0x50, 0x0b, 0x35, 0x85, 0x4b, 0x0e, 0xd1, 0x15, 0x68, - 0xa0, 0x88, 0x64, 0x3c, 0x79, 0x3d, 0xb8, 0x9c, 0x44, 0x57, 0x5c, 0xa0, 0x33, 0xbe, 0xbe, 0xe9, 0xa6, 0xb3, 0xe8, - 0x87, 0x6a, 0x3e, 0x21, 0x25, 0xd9, 0xe1, 0x90, 0x8d, 0xaa, 0xba, 0x58, 0x4f, 0x43, 0xf9, 0xd3, 0x43, 0xf0, 0xf5, - 0x82, 0x7a, 0x4d, 0x56, 0xa9, 0xfe, 0x81, 0x2a, 0xe5, 0x45, 0xc3, 0x4b, 0xff, 0x87, 0x4a, 0xee, 0x7b, 0x40, 0x5a, - 0xcb, 0x4b, 0x2e, 0xdf, 0x8f, 0x10, 0x63, 0xc4, 0x0f, 0xbc, 0x92, 0x47, 0x2c, 0x54, 0x53, 0xb8, 0xe6, 0x11, 0x82, - 0xbc, 0x65, 0x3a, 0xf8, 0x5b, 0x4f, 0x9c, 0xee, 0x4f, 0x94, 0x76, 0xf1, 0x85, 0xc5, 0xb4, 0x72, 0xa4, 0x1b, 0x90, - 0x83, 0x0d, 0xd3, 0x45, 0x41, 0xb6, 0x29, 0x8d, 0xa0, 0x8d, 0x96, 0x03, 0x1b, 0x4e, 0xa5, 0x36, 0x9c, 0xb9, 0x86, - 0xe0, 0x3e, 0x3f, 0x4f, 0x47, 0x0b, 0xf8, 0x90, 0xea, 0xf6, 0x12, 0x3f, 0x0f, 0x1b, 0x2d, 0x90, 0xd9, 0x11, 0x9f, - 0xd9, 0x44, 0xd2, 0x49, 0x9d, 0x2b, 0x60, 0xb7, 0xb3, 0x6b, 0x90, 0x23, 0x66, 0xee, 0x2b, 0x54, 0xdf, 0xa2, 0x01, - 0x57, 0xc6, 0xda, 0xd7, 0x24, 0x63, 0xe1, 0x55, 0x39, 0x0d, 0x07, 0x00, 0x43, 0x97, 0xd1, 0xd7, 0x96, 0x9b, 0x2c, - 0x7b, 0x5d, 0x40, 0x10, 0x44, 0x49, 0x3c, 0x3e, 0xe0, 0x7d, 0x59, 0x0d, 0x35, 0x4a, 0x3e, 0x96, 0x1d, 0xc3, 0xd7, - 0x4b, 0xf4, 0x77, 0x63, 0x2e, 0x31, 0xe0, 0x75, 0xd5, 0x16, 0x14, 0xce, 0xf3, 0xc3, 0xe1, 0x3c, 0x1f, 0x19, 0xcf, - 0x32, 0x50, 0xad, 0x4c, 0xeb, 0x60, 0x69, 0xe6, 0x8b, 0x85, 0xbf, 0xd8, 0x39, 0x89, 0x88, 0x82, 0xc0, 0x8e, 0x84, - 0x07, 0x91, 0xfa, 0x51, 0xe5, 0xe9, 0x4e, 0xf5, 0xd9, 0x7e, 0x61, 0x13, 0xe9, 0x05, 0x25, 0x93, 0x4f, 0x82, 0xbd, - 0xea, 0xef, 0x20, 0x6c, 0x08, 0x6f, 0x5e, 0xf5, 0x3a, 0xcb, 0xd4, 0xac, 0x04, 0x09, 0x33, 0xe6, 0x08, 0x1e, 0x87, - 0x9d, 0xc6, 0x36, 0x3c, 0x36, 0x62, 0xd9, 0xd2, 0x5b, 0xb3, 0x5b, 0xb6, 0x62, 0x37, 0xaa, 0x4e, 0x0b, 0x1e, 0x4e, - 0x87, 0x97, 0x01, 0xae, 0xbe, 0xf5, 0x39, 0xe7, 0xb7, 0x74, 0x82, 0xad, 0x07, 0x3c, 0x9a, 0x88, 0xd9, 0xfa, 0x87, - 0x48, 0x2d, 0x9e, 0xf5, 0x90, 0x2f, 0x68, 0xfd, 0x89, 0xd9, 0xad, 0x49, 0xbe, 0x1d, 0xf0, 0xc5, 0x64, 0xfd, 0x43, - 0x04, 0xaf, 0xfe, 0x00, 0x56, 0x8c, 0xcc, 0x99, 0x65, 0xeb, 0x1f, 0x22, 0x1c, 0xb3, 0xdb, 0x1f, 0x22, 0x1a, 0xb5, - 0x95, 0xdc, 0x97, 0x6e, 0x1a, 0x10, 0x56, 0x6e, 0x58, 0x0c, 0xaf, 0x81, 0x78, 0xa6, 0x8d, 0xa4, 0x6b, 0x69, 0xe8, - 0x8d, 0x79, 0x38, 0x8d, 0x83, 0x35, 0xb5, 0x42, 0x9e, 0x19, 0x62, 0x16, 0xff, 0x10, 0xcd, 0xd9, 0x0a, 0x2b, 0xb2, - 0xe1, 0xf1, 0xe0, 0x72, 0xb2, 0xb9, 0xe2, 0x6b, 0x20, 0x3f, 0x9b, 0x6c, 0xcc, 0x16, 0x75, 0xc3, 0xc5, 0x6c, 0xf3, - 0x43, 0x34, 0x9f, 0xac, 0xa0, 0x67, 0xed, 0x01, 0xf3, 0x5e, 0x82, 0x08, 0x25, 0x21, 0x35, 0xe5, 0xa6, 0xd7, 0x63, - 0xeb, 0x71, 0x70, 0xcb, 0xd6, 0x97, 0xc1, 0x0d, 0x5b, 0x8f, 0x81, 0x88, 0x83, 0xfa, 0xdd, 0xdb, 0xc0, 0xe2, 0x8b, - 0xd8, 0xfa, 0xd2, 0xa4, 0x6d, 0x7e, 0x88, 0x98, 0x3b, 0x38, 0x0d, 0x5c, 0xb0, 0xd6, 0x99, 0xb7, 0x62, 0x70, 0x09, - 0x59, 0x7a, 0x31, 0xdb, 0x0c, 0x2f, 0xd9, 0x7a, 0x84, 0x53, 0x3d, 0xf1, 0xd9, 0x2d, 0xbf, 0x61, 0x09, 0x5f, 0x35, - 0xf1, 0xd5, 0x06, 0x34, 0xa2, 0x47, 0x19, 0xf4, 0x15, 0xd4, 0x0a, 0x65, 0xb1, 0x30, 0x2a, 0xf7, 0x2d, 0x38, 0xa0, - 0x20, 0x6d, 0x03, 0x04, 0x49, 0x3c, 0xbb, 0xeb, 0x70, 0xfd, 0x51, 0x0a, 0x03, 0x6e, 0x02, 0x33, 0x60, 0x60, 0xfa, - 0x19, 0xfc, 0xb0, 0xd2, 0x25, 0x42, 0x9c, 0xfd, 0x94, 0x92, 0x64, 0x9e, 0xbf, 0x17, 0x69, 0xee, 0x16, 0xae, 0x53, - 0x98, 0x15, 0x05, 0xaa, 0x9f, 0x92, 0xd2, 0xc0, 0x42, 0x25, 0x32, 0x95, 0x82, 0x5f, 0xd6, 0x4e, 0xbb, 0xce, 0x8e, - 0xd1, 0xb9, 0xce, 0x2f, 0x27, 0xce, 0xe9, 0xa4, 0xef, 0x3f, 0x70, 0x0c, 0x5b, 0xc8, 0xc0, 0x85, 0x3f, 0xf5, 0x84, - 0x71, 0x6a, 0x05, 0x62, 0x2a, 0x79, 0xf6, 0x14, 0x3e, 0x13, 0x5a, 0x1d, 0x5d, 0xf8, 0x7e, 0x50, 0x68, 0x93, 0x74, - 0x0b, 0x92, 0x14, 0x3c, 0x45, 0xcf, 0x39, 0x6f, 0x03, 0x95, 0x62, 0x44, 0x0b, 0x22, 0x6d, 0xdd, 0x66, 0x0e, 0xd2, - 0x96, 0xe6, 0xbb, 0x26, 0x7e, 0x0e, 0x0b, 0xb8, 0x88, 0x16, 0xb6, 0x86, 0x47, 0x55, 0xac, 0xdc, 0x9b, 0x3c, 0x47, - 0x38, 0xa3, 0x4b, 0x99, 0x00, 0xb8, 0xde, 0x2f, 0xc2, 0x5a, 0xe1, 0x15, 0x35, 0x8b, 0xbc, 0xa8, 0xe9, 0x93, 0x2d, - 0x70, 0x1f, 0x8b, 0x12, 0x05, 0xce, 0x5a, 0x30, 0x60, 0x2b, 0x2c, 0xd9, 0x49, 0x61, 0x53, 0xb4, 0x84, 0xde, 0x1e, - 0x3f, 0x1d, 0xd4, 0x4c, 0x06, 0xd0, 0x04, 0xd0, 0x78, 0xfc, 0x0b, 0x40, 0x4d, 0x3f, 0xd6, 0x62, 0x5d, 0x05, 0xa5, - 0x52, 0x6e, 0xc2, 0xcf, 0xc0, 0x30, 0xc3, 0x0f, 0x85, 0xdc, 0x26, 0x4a, 0xe4, 0xfc, 0x58, 0x94, 0x62, 0x59, 0x8a, - 0x2a, 0x69, 0x37, 0x14, 0x3c, 0x22, 0xdc, 0x06, 0x8d, 0x99, 0xdb, 0x13, 0x5d, 0xb4, 0x22, 0x94, 0x63, 0xb3, 0x8e, - 0x91, 0x46, 0x99, 0x9d, 0xec, 0x3a, 0x59, 0x68, 0xbf, 0xaf, 0x72, 0xc8, 0x3a, 0x60, 0x8d, 0xe4, 0xeb, 0x35, 0x87, - 0x6e, 0x1b, 0xe5, 0xc5, 0xbd, 0xe7, 0x2b, 0x38, 0xcd, 0xf1, 0xc4, 0xee, 0x7a, 0xdd, 0x29, 0x12, 0xf1, 0x0a, 0x27, - 0x55, 0x3e, 0x92, 0x85, 0xe3, 0xce, 0x9d, 0xd6, 0x62, 0x55, 0xb9, 0xac, 0xa7, 0x16, 0x47, 0x04, 0x3e, 0x95, 0x47, - 0x7b, 0xa1, 0x6d, 0x51, 0x2c, 0x84, 0xd1, 0xa3, 0x13, 0x7e, 0x52, 0x02, 0xeb, 0xeb, 0x70, 0x58, 0xfa, 0x11, 0x47, - 0xbf, 0xd3, 0x68, 0xb4, 0x20, 0xa4, 0xe1, 0xa9, 0x17, 0x8d, 0x16, 0x75, 0x51, 0x87, 0xd9, 0xd3, 0x5c, 0x0f, 0x14, - 0x86, 0x11, 0xa8, 0x1f, 0x5c, 0x65, 0xf0, 0x59, 0x84, 0xa8, 0x79, 0x60, 0x9a, 0x0d, 0xe1, 0xa8, 0x0b, 0x3c, 0xb4, - 0x82, 0x16, 0x33, 0xf3, 0x51, 0x88, 0xe1, 0x43, 0xba, 0x38, 0x7f, 0x42, 0x56, 0x3e, 0xc0, 0xee, 0xd0, 0x5d, 0x28, - 0xe7, 0x4c, 0xc5, 0x00, 0x3f, 0x0a, 0xc8, 0x47, 0x09, 0xb8, 0x19, 0x20, 0x7b, 0x64, 0x09, 0x20, 0x56, 0x8c, 0x8e, - 0x26, 0x9f, 0xfb, 0x5e, 0xa4, 0xe0, 0x9d, 0x7d, 0x96, 0xab, 0x09, 0x43, 0xe1, 0x13, 0x03, 0xdd, 0xfc, 0xc6, 0x6f, - 0xcf, 0x5b, 0x30, 0xb2, 0x4b, 0x52, 0xbc, 0xd6, 0x0c, 0xf7, 0x1b, 0x70, 0x3b, 0x02, 0xca, 0x9a, 0xea, 0x98, 0x64, - 0x9b, 0x86, 0x48, 0x06, 0xcc, 0x88, 0x11, 0x41, 0x65, 0xb9, 0xf0, 0xbf, 0x7b, 0x59, 0x14, 0x38, 0x80, 0xab, 0x99, - 0x0c, 0x5e, 0xbb, 0x30, 0x2a, 0x00, 0xce, 0x69, 0xe8, 0x94, 0xf6, 0xaa, 0xea, 0x90, 0xac, 0x9a, 0x1f, 0xcc, 0xe6, - 0x4d, 0xc3, 0xc4, 0x88, 0x20, 0xba, 0x08, 0x27, 0x98, 0x5e, 0x91, 0xbe, 0x56, 0x72, 0x3a, 0x5a, 0x75, 0xb4, 0x96, - 0x98, 0x98, 0x2b, 0x8a, 0xbf, 0x06, 0x3c, 0x6e, 0xf0, 0xea, 0x24, 0x4d, 0x27, 0xaa, 0x47, 0x8f, 0x5f, 0xa7, 0xe9, - 0xa4, 0xc4, 0x5d, 0xe1, 0x37, 0xe0, 0xa2, 0xd9, 0xe6, 0x43, 0x3f, 0x7e, 0x41, 0x11, 0x17, 0x35, 0xb8, 0xf2, 0x4e, - 0xf5, 0x95, 0xea, 0x23, 0xa8, 0x85, 0x27, 0x46, 0xd6, 0xc2, 0x93, 0x4b, 0xd6, 0x5a, 0x10, 0xcc, 0x6c, 0x0e, 0x5c, - 0xc8, 0xaf, 0x94, 0x22, 0xde, 0x44, 0x42, 0x2d, 0x06, 0xad, 0xc7, 0xcc, 0x59, 0x35, 0x5a, 0xa8, 0xcc, 0x08, 0xed, - 0xdb, 0x5a, 0x74, 0x7e, 0x23, 0x3f, 0xe5, 0xa9, 0x7d, 0xd9, 0x1e, 0xe7, 0xe3, 0x3d, 0xba, 0xab, 0xce, 0x32, 0x93, - 0x32, 0x3e, 0x99, 0x25, 0x28, 0xdc, 0x25, 0xd8, 0x80, 0x24, 0xfb, 0xad, 0x0e, 0x90, 0x51, 0x7b, 0xed, 0x77, 0x9d, - 0xe5, 0xab, 0x9b, 0xad, 0xa1, 0xa8, 0xd4, 0x4a, 0x52, 0x1c, 0x64, 0xb8, 0x6e, 0x2b, 0x1f, 0x2e, 0x2e, 0xa0, 0x67, - 0x8c, 0x44, 0xe6, 0xf9, 0x13, 0xf9, 0x12, 0x9c, 0x33, 0xce, 0x0a, 0x81, 0x09, 0x63, 0xf5, 0xae, 0xb5, 0x54, 0x1a, - 0x52, 0x8c, 0x1d, 0x8d, 0xb2, 0xac, 0xb2, 0x74, 0x99, 0xad, 0x25, 0x6c, 0x59, 0x45, 0x6e, 0x61, 0xb7, 0x99, 0xac, - 0xe6, 0xbb, 0x8a, 0x3b, 0x28, 0xdf, 0x6c, 0x95, 0xf1, 0xbd, 0x44, 0xf6, 0x6e, 0x03, 0x25, 0x3c, 0x1d, 0xfd, 0x05, - 0xe9, 0xb7, 0x19, 0xc6, 0x29, 0xb7, 0x95, 0xb4, 0x00, 0xa7, 0x7f, 0x38, 0xbc, 0xab, 0x30, 0x68, 0x70, 0x84, 0x71, - 0x64, 0xfd, 0xfe, 0xa2, 0xf2, 0x6a, 0x4c, 0xd4, 0xf1, 0x59, 0xfd, 0x7e, 0x45, 0x0f, 0xa7, 0xd5, 0x68, 0x95, 0x6e, - 0x91, 0x9d, 0xd0, 0xc6, 0xca, 0x0f, 0x6a, 0x05, 0xcc, 0xde, 0xfa, 0x7c, 0x3a, 0x00, 0x1d, 0x0b, 0x90, 0x68, 0x36, - 0x13, 0x89, 0x39, 0xe9, 0x9e, 0x84, 0xc7, 0x07, 0x16, 0x38, 0xc0, 0x54, 0xfc, 0x5f, 0xc2, 0x9b, 0x81, 0x0d, 0x1a, - 0x25, 0xfa, 0x1a, 0x5d, 0xd5, 0xe6, 0x46, 0xc7, 0x4b, 0x4f, 0x21, 0x91, 0x15, 0xac, 0x9a, 0xfb, 0x72, 0x03, 0xa7, - 0x3d, 0xd4, 0x1c, 0x2a, 0x4b, 0xf0, 0xb7, 0x5f, 0xe6, 0x87, 0xc3, 0x2a, 0x83, 0xc2, 0x76, 0x6b, 0xa1, 0xbd, 0x31, - 0x4b, 0x35, 0x54, 0x84, 0x83, 0xce, 0x57, 0x62, 0x56, 0x8f, 0xe8, 0xef, 0xf9, 0xe1, 0xb0, 0x22, 0x30, 0xe0, 0xb0, - 0x94, 0x99, 0x68, 0xa1, 0x58, 0x5a, 0x67, 0x33, 0xaa, 0x03, 0x0f, 0x4c, 0xcc, 0x59, 0xb8, 0x03, 0xd0, 0x26, 0xb5, - 0x0a, 0xf4, 0x2a, 0xa2, 0x9f, 0xb8, 0x5f, 0xdb, 0xaf, 0xd7, 0x23, 0xb3, 0x74, 0xe4, 0xc6, 0x58, 0x00, 0x70, 0xe0, - 0x79, 0x4d, 0xf2, 0x9c, 0x7c, 0x0d, 0xed, 0x9e, 0x5c, 0xc8, 0x9f, 0xa0, 0x6c, 0xe1, 0xb9, 0x6a, 0x5a, 0x59, 0xac, - 0xb8, 0xaa, 0x5e, 0x5d, 0xf0, 0xca, 0x64, 0x5a, 0xa5, 0x95, 0xa8, 0x94, 0x60, 0x40, 0x5d, 0xe2, 0xb5, 0xa6, 0x19, - 0xa5, 0x36, 0xea, 0x4c, 0xd4, 0x80, 0x0d, 0xf6, 0x53, 0xb5, 0xd1, 0xc9, 0xb9, 0x7c, 0x7e, 0x69, 0x1c, 0x3e, 0xed, - 0xea, 0xcd, 0x4c, 0xe5, 0xc0, 0x5f, 0x2b, 0x1f, 0x5a, 0x3d, 0x06, 0x3a, 0x20, 0xa7, 0x3f, 0x86, 0xc5, 0xc4, 0xee, - 0xd0, 0xbc, 0xdd, 0x5d, 0x56, 0x17, 0xe9, 0x9d, 0xa6, 0x64, 0x56, 0x6f, 0xf9, 0xcc, 0xea, 0xd1, 0x01, 0x2f, 0x1e, - 0xea, 0xbd, 0xc2, 0x4c, 0x22, 0xb8, 0x18, 0xaa, 0x49, 0x64, 0x77, 0xa0, 0x35, 0x8f, 0x2a, 0x26, 0xc0, 0x0f, 0x4a, - 0xad, 0xe9, 0xbd, 0xdd, 0x15, 0xea, 0x94, 0xc2, 0xe3, 0xd6, 0x92, 0x1f, 0x98, 0x3b, 0xed, 0x5a, 0xe7, 0xe3, 0xf9, - 0xa5, 0xef, 0x37, 0xf2, 0x84, 0x36, 0x3b, 0x93, 0xd3, 0x3f, 0x79, 0xab, 0x7f, 0x98, 0xea, 0x5b, 0xe8, 0x4e, 0xd0, - 0x67, 0xe8, 0xaa, 0xea, 0xae, 0xc4, 0x16, 0x86, 0x7a, 0x62, 0x91, 0x17, 0xf2, 0xa4, 0x35, 0x76, 0x1c, 0xec, 0x0d, - 0x70, 0xe2, 0x97, 0x87, 0x83, 0xb8, 0xca, 0x7d, 0x76, 0xde, 0x35, 0xb2, 0x72, 0x00, 0x2b, 0x88, 0x82, 0x71, 0x6b, - 0x3e, 0xb6, 0x41, 0xba, 0xc4, 0xd5, 0xf8, 0xf8, 0x0d, 0xc5, 0x32, 0xd9, 0x44, 0x5c, 0x5c, 0xe4, 0x3f, 0x3c, 0x01, - 0xd2, 0xb2, 0x7e, 0x3f, 0x7a, 0x7a, 0x39, 0x7d, 0x32, 0x8c, 0x02, 0x70, 0xec, 0xb2, 0x97, 0x97, 0x31, 0x5f, 0x5d, - 0x32, 0xcb, 0x14, 0x16, 0xf9, 0x66, 0x40, 0x75, 0xc9, 0x6a, 0xe9, 0x7a, 0x05, 0x58, 0xba, 0xfc, 0xe6, 0x3e, 0x4c, - 0x0d, 0x68, 0x64, 0xcd, 0xdd, 0x69, 0xae, 0x05, 0x4a, 0x3d, 0xef, 0x67, 0x86, 0x7c, 0x5d, 0x06, 0x5d, 0x41, 0xba, - 0xe7, 0x11, 0xe9, 0xe5, 0x5e, 0x3a, 0xdd, 0xef, 0x4b, 0x01, 0x96, 0xfa, 0x52, 0x7c, 0x06, 0x85, 0x45, 0xe3, 0x1b, - 0x01, 0xda, 0x1a, 0xaa, 0x69, 0xaf, 0x14, 0x55, 0x2f, 0xe8, 0x95, 0xe2, 0x73, 0x4f, 0x0f, 0x95, 0xf9, 0xb2, 0x74, - 0xf4, 0x3f, 0xa1, 0xe6, 0x82, 0x13, 0x62, 0x26, 0xe6, 0x00, 0x2a, 0x41, 0x1b, 0xdf, 0xe2, 0x68, 0xe3, 0x53, 0xbd, - 0x8a, 0x9b, 0x3e, 0xaf, 0xad, 0x65, 0x4e, 0x08, 0x9b, 0xee, 0x25, 0x40, 0x45, 0x5e, 0x09, 0x8f, 0x60, 0xf9, 0xe5, - 0x0f, 0x79, 0xba, 0x42, 0xb4, 0x8e, 0x7b, 0x96, 0xb9, 0x34, 0xf6, 0x2f, 0x0d, 0xa6, 0xaf, 0x6f, 0xb7, 0x45, 0x7e, - 0x6a, 0x62, 0xc2, 0x7a, 0xac, 0xe8, 0x9b, 0xb7, 0xe1, 0x4a, 0xa0, 0xc0, 0xa1, 0x44, 0x62, 0x9b, 0x2a, 0x14, 0xf1, - 0x20, 0xe9, 0xd3, 0x45, 0xeb, 0xd3, 0x00, 0x53, 0x6b, 0x39, 0x30, 0x87, 0x70, 0x15, 0x17, 0x3e, 0x7a, 0xfa, 0x16, - 0xb3, 0x70, 0x3e, 0xf1, 0x3e, 0x78, 0xc5, 0xc8, 0x7c, 0xdc, 0x47, 0xa5, 0x92, 0xfe, 0x79, 0x38, 0xcc, 0xaa, 0xb9, - 0xef, 0xd0, 0x47, 0x7a, 0xa8, 0x72, 0x41, 0xd9, 0x1b, 0x63, 0x12, 0x81, 0xd2, 0x18, 0xef, 0xe3, 0xe0, 0x38, 0xef, - 0xd3, 0x00, 0x52, 0xfb, 0xc4, 0x3b, 0x52, 0x72, 0x78, 0xce, 0x31, 0x27, 0x94, 0x56, 0x84, 0x55, 0x7c, 0x9b, 0xa1, - 0x5c, 0x77, 0x4a, 0xc1, 0x24, 0x87, 0x04, 0xc3, 0x5f, 0x35, 0x6f, 0x62, 0x05, 0xc2, 0xae, 0x99, 0x57, 0xa3, 0x47, - 0x55, 0x12, 0x96, 0x22, 0xee, 0xf7, 0x77, 0x99, 0x67, 0xd8, 0x1b, 0x1e, 0x19, 0x46, 0x0e, 0x96, 0xfb, 0xa3, 0x3a, - 0x11, 0xb9, 0x47, 0x17, 0x18, 0x95, 0x85, 0xe7, 0x0d, 0x5d, 0x69, 0x50, 0x49, 0x76, 0xfc, 0x15, 0xd7, 0x80, 0xda, - 0x1a, 0x23, 0x86, 0x02, 0x46, 0xc1, 0x6b, 0xfb, 0x43, 0xc8, 0xa2, 0x6c, 0xfd, 0x06, 0xc7, 0x7c, 0x70, 0x1f, 0x71, - 0xbc, 0xc3, 0x59, 0x68, 0x09, 0x79, 0x72, 0xc7, 0x20, 0x4d, 0x63, 0x69, 0x04, 0x9c, 0x88, 0x64, 0x1b, 0x4b, 0xe1, - 0x08, 0x20, 0x20, 0xd0, 0x4d, 0x99, 0x61, 0x4c, 0x07, 0x23, 0xcf, 0xa3, 0x9e, 0xf1, 0x5e, 0x85, 0xa7, 0x90, 0x26, - 0xdb, 0xd7, 0xf3, 0xf7, 0x46, 0x90, 0x95, 0x5b, 0xce, 0xf1, 0xb0, 0xf8, 0xc6, 0xd9, 0x57, 0x39, 0x79, 0x8a, 0x59, - 0x46, 0x7a, 0xa7, 0x98, 0x17, 0xf0, 0xa7, 0xb2, 0xd4, 0xe7, 0x28, 0xbd, 0x65, 0x3e, 0x59, 0x45, 0xd2, 0xa5, 0xb7, - 0xe9, 0xf7, 0xe3, 0x91, 0x3a, 0xd4, 0xfc, 0x7d, 0x3c, 0x92, 0x67, 0xd8, 0x86, 0x25, 0x2c, 0xb4, 0x0a, 0xc6, 0x00, - 0x92, 0xd8, 0x88, 0x68, 0x30, 0xda, 0x9b, 0xc3, 0xe1, 0x7c, 0x63, 0xce, 0x92, 0x3d, 0xb8, 0xbe, 0xf2, 0xc4, 0xbc, - 0x03, 0x5f, 0xe6, 0x31, 0x41, 0xc4, 0x66, 0xde, 0x86, 0xd5, 0xe0, 0xc1, 0x0e, 0xae, 0x8f, 0xd8, 0xa2, 0x58, 0xeb, - 0x58, 0x2a, 0xeb, 0xe0, 0xb4, 0x8e, 0x4d, 0x33, 0x52, 0x8a, 0xec, 0x73, 0xec, 0xef, 0xdd, 0xe0, 0xea, 0xda, 0x18, - 0xd4, 0x1a, 0x77, 0x98, 0x3b, 0xa7, 0x02, 0xea, 0x31, 0x5d, 0x41, 0xf5, 0xac, 0x22, 0x5f, 0x7e, 0x6b, 0xe7, 0x80, - 0xa0, 0x11, 0x08, 0x5c, 0x34, 0xfe, 0x77, 0x5d, 0xca, 0x79, 0x17, 0x10, 0xe2, 0xbb, 0x14, 0xf4, 0xe9, 0x0c, 0x36, - 0xb1, 0xf9, 0x04, 0x62, 0xd1, 0x74, 0x9f, 0x6b, 0xcd, 0x7c, 0x31, 0xa2, 0x9d, 0x59, 0x77, 0x8b, 0xdc, 0x6a, 0x21, - 0x92, 0xd1, 0xb3, 0xcd, 0x84, 0xdb, 0x0e, 0xe5, 0x8c, 0x04, 0x4c, 0xd0, 0xda, 0x4a, 0xc9, 0xe7, 0xba, 0xd7, 0x09, - 0xda, 0x03, 0x49, 0xeb, 0xfe, 0xcd, 0xa2, 0x33, 0x4a, 0x4e, 0xae, 0x37, 0x39, 0x83, 0x14, 0x2c, 0xd8, 0x5e, 0xe6, - 0x84, 0x1b, 0xe0, 0x23, 0x9b, 0x25, 0xa7, 0x69, 0x90, 0xc7, 0x42, 0xd7, 0xec, 0x7d, 0x9b, 0x5f, 0x16, 0xd0, 0xa1, - 0x64, 0xd1, 0x08, 0xf1, 0x00, 0x3b, 0x87, 0xe4, 0xaa, 0x40, 0xdd, 0x34, 0xd0, 0x95, 0x2b, 0x67, 0x8a, 0x29, 0x70, - 0x21, 0x14, 0x44, 0xed, 0xe8, 0x24, 0x2a, 0xe7, 0x7d, 0x52, 0x5d, 0xe6, 0xd3, 0x42, 0x9a, 0x06, 0xf2, 0x69, 0xe5, - 0x98, 0x07, 0xee, 0x6c, 0xe3, 0x9a, 0xc0, 0x40, 0xa7, 0xf6, 0xb5, 0x28, 0xe7, 0x58, 0x45, 0xf4, 0x3e, 0x7f, 0x5f, - 0xd9, 0xd3, 0x07, 0x11, 0x36, 0x2a, 0xd0, 0x58, 0x4a, 0x8c, 0x8d, 0x1c, 0xff, 0x96, 0x28, 0x1b, 0x32, 0x04, 0x84, - 0x90, 0x36, 0x72, 0xfa, 0x61, 0x07, 0xad, 0x64, 0xda, 0xff, 0x93, 0xc4, 0x6f, 0x83, 0xbd, 0x9c, 0xfa, 0x53, 0x8f, - 0x78, 0xbc, 0xd6, 0xe8, 0x31, 0x25, 0xdd, 0x06, 0x79, 0xaa, 0x3c, 0x05, 0xc9, 0x84, 0xb1, 0x84, 0x60, 0x51, 0x2e, - 0x78, 0xce, 0x2b, 0x2e, 0xe1, 0x3e, 0x6a, 0x59, 0x11, 0xa1, 0x2a, 0x91, 0xd3, 0xe7, 0x2b, 0xe0, 0x99, 0x80, 0x40, - 0xc7, 0x18, 0x69, 0x54, 0xc1, 0x97, 0xc0, 0x58, 0x48, 0xca, 0x4e, 0x33, 0x12, 0x5c, 0x76, 0x3f, 0x22, 0x51, 0xea, - 0x0b, 0x52, 0x92, 0xbe, 0x11, 0x35, 0x5e, 0x89, 0x55, 0x44, 0x02, 0x19, 0x6a, 0x88, 0x58, 0x55, 0x4f, 0xdd, 0xab, - 0x62, 0x32, 0x18, 0x54, 0xbe, 0x9c, 0x9e, 0x78, 0x43, 0x43, 0xe5, 0x5d, 0x57, 0xb4, 0xd3, 0x33, 0xad, 0x94, 0xb7, - 0x90, 0x96, 0xa0, 0x69, 0x18, 0x69, 0x0e, 0xa5, 0xae, 0xa4, 0xbb, 0x31, 0x88, 0x2f, 0x99, 0xe8, 0xd9, 0x4e, 0xed, - 0x28, 0x6d, 0x49, 0x7b, 0x08, 0xe9, 0xb9, 0x4b, 0x3e, 0x66, 0x21, 0x57, 0x77, 0xca, 0x49, 0x79, 0x15, 0xa2, 0x93, - 0xfb, 0x1e, 0x43, 0x22, 0xd0, 0xe7, 0x1c, 0xc3, 0xba, 0x68, 0xa8, 0x73, 0x58, 0x21, 0x66, 0x0b, 0x25, 0xcc, 0x97, - 0x8c, 0xa7, 0x92, 0x41, 0x03, 0x20, 0x03, 0x3e, 0x7b, 0x19, 0x58, 0xfe, 0x0a, 0xe2, 0x47, 0x1b, 0x1f, 0x0e, 0x5f, - 0x6a, 0x0a, 0xb1, 0xfd, 0x02, 0x9b, 0x21, 0x3c, 0xaa, 0x07, 0x3c, 0xf3, 0x4d, 0x9c, 0xa0, 0xe5, 0x88, 0x93, 0xd9, - 0xd1, 0x44, 0xf6, 0xaa, 0x87, 0x70, 0x2a, 0x2b, 0x50, 0x47, 0x59, 0x67, 0x25, 0xfc, 0x08, 0x53, 0xdd, 0x4a, 0xac, - 0x05, 0xda, 0x5c, 0xad, 0x58, 0x0b, 0xe0, 0xc0, 0xcf, 0x21, 0x78, 0x22, 0x9f, 0x83, 0x8b, 0x41, 0x01, 0x3e, 0x07, - 0xc0, 0x8b, 0xdc, 0xd1, 0xb9, 0x3f, 0x3d, 0xb0, 0xac, 0x46, 0x18, 0x8e, 0x2a, 0x62, 0xfd, 0x9a, 0xed, 0xc8, 0x07, - 0x6e, 0xc7, 0xf8, 0x5c, 0x7b, 0x2c, 0x59, 0x4e, 0x98, 0x99, 0x7b, 0xb5, 0x44, 0xcf, 0x9b, 0x34, 0x6e, 0x46, 0x8f, - 0xf6, 0xb5, 0xfc, 0x5f, 0xd0, 0xcb, 0xa0, 0xbf, 0x85, 0x5b, 0x5e, 0xf3, 0x87, 0xe5, 0x35, 0x60, 0x7a, 0x05, 0x91, - 0x32, 0x6a, 0x44, 0xc6, 0x10, 0x36, 0xa9, 0x6e, 0x6e, 0x93, 0xea, 0x42, 0xc0, 0xd3, 0x11, 0xa9, 0xae, 0x85, 0xb4, - 0x91, 0x4f, 0xeb, 0x40, 0xc6, 0x22, 0xbd, 0xfd, 0xe9, 0x6f, 0xcf, 0x3e, 0xbd, 0xfa, 0xf5, 0xa7, 0xc5, 0xab, 0xb7, - 0x2f, 0x5f, 0xbd, 0x7d, 0xf5, 0xe9, 0x77, 0x82, 0xf0, 0x98, 0x0a, 0x95, 0xe1, 0xfd, 0xbb, 0x8f, 0xaf, 0x9c, 0x0c, - 0x36, 0xcc, 0x58, 0xd6, 0xbe, 0x91, 0x83, 0x21, 0x10, 0xd9, 0x20, 0x64, 0x90, 0x9d, 0x92, 0x39, 0x66, 0x62, 0x8e, - 0xb1, 0x77, 0x02, 0x93, 0x2d, 0xf0, 0x1d, 0xcb, 0xbc, 0x64, 0x44, 0xae, 0x0a, 0xad, 0x1f, 0xd0, 0x82, 0x37, 0xe0, - 0x22, 0x93, 0xe6, 0xb7, 0xbf, 0x12, 0xc4, 0x3e, 0xad, 0xa4, 0xdc, 0x57, 0xdb, 0x9a, 0xe7, 0xdb, 0xfb, 0xbd, 0x84, - 0xf3, 0x9f, 0x4b, 0x23, 0x6a, 0x01, 0x0e, 0xc0, 0xe7, 0xf0, 0xc7, 0x95, 0xb6, 0xa4, 0xc9, 0x2c, 0xda, 0xcf, 0x18, - 0x82, 0x2e, 0x0d, 0x3e, 0x88, 0x3d, 0xf2, 0x52, 0x9f, 0x2c, 0x24, 0x70, 0x47, 0x0c, 0x9f, 0x56, 0x04, 0xbd, 0x62, - 0x44, 0x71, 0xc9, 0x15, 0x2a, 0xa5, 0xe4, 0xdf, 0x28, 0xbb, 0xa8, 0x90, 0xb3, 0x82, 0xdd, 0x29, 0x72, 0x64, 0xfc, - 0x20, 0x98, 0xf8, 0x72, 0x70, 0xff, 0x25, 0xde, 0xe1, 0x4c, 0x71, 0x24, 0x27, 0xfc, 0x63, 0x86, 0x81, 0xfd, 0x39, - 0xf8, 0xbc, 0x3a, 0xcc, 0xcb, 0x1b, 0x7d, 0xca, 0x2d, 0xf9, 0x78, 0xb2, 0xbc, 0x02, 0x83, 0xfd, 0x52, 0x35, 0x77, - 0xcd, 0xeb, 0xd9, 0x72, 0xce, 0xf6, 0xb3, 0x68, 0x1e, 0xdc, 0xb2, 0x59, 0x36, 0x0f, 0x56, 0x0d, 0x5f, 0xb3, 0x1b, - 0xbe, 0xb6, 0xaa, 0xb6, 0xb6, 0xab, 0x36, 0xd9, 0xf0, 0x1b, 0x90, 0x10, 0xae, 0xc1, 0x2f, 0x39, 0x61, 0xb7, 0x3e, - 0xdb, 0x80, 0x44, 0xbb, 0x62, 0x1b, 0xb8, 0x88, 0xad, 0xf9, 0xab, 0xca, 0xdb, 0xb0, 0x92, 0x9d, 0x8f, 0x59, 0x8e, - 0xf3, 0xcf, 0x87, 0x07, 0xb4, 0x17, 0xea, 0x67, 0x97, 0xea, 0xd9, 0x44, 0xd9, 0xcd, 0x36, 0xa3, 0xc5, 0x5d, 0x5a, - 0x6d, 0xc2, 0x0c, 0x3d, 0xcb, 0xe1, 0xa3, 0xad, 0x14, 0xfc, 0xf4, 0x02, 0xbf, 0x64, 0x4d, 0x9c, 0xdf, 0xd3, 0xb6, - 0x5d, 0x95, 0xd8, 0x0a, 0x5a, 0x14, 0x59, 0xad, 0xf0, 0xc0, 0x9c, 0x3f, 0x85, 0x05, 0x8c, 0x3d, 0xc7, 0x39, 0xaf, - 0xfd, 0x11, 0x32, 0xde, 0x3b, 0x00, 0x68, 0x99, 0xe3, 0x00, 0x8f, 0x58, 0x31, 0x8a, 0x06, 0xef, 0xfc, 0x52, 0x59, - 0xad, 0x34, 0x27, 0xa1, 0x6d, 0xc4, 0xaa, 0xe5, 0x48, 0xd5, 0x8c, 0x48, 0x1f, 0xa4, 0xe7, 0x7d, 0x8f, 0xa8, 0x06, - 0x7b, 0x32, 0xaf, 0x03, 0xfb, 0xf4, 0xae, 0xb5, 0xaa, 0x3b, 0xbf, 0xa7, 0x4a, 0x97, 0x1c, 0xd9, 0xf2, 0xd3, 0x65, - 0x78, 0xaf, 0xfe, 0x94, 0x5c, 0x1f, 0x0a, 0x1c, 0xe1, 0xa1, 0x0a, 0x38, 0x5f, 0xaf, 0x44, 0xbb, 0x13, 0x61, 0x57, - 0x2e, 0x01, 0x21, 0xbe, 0xa4, 0x69, 0x8e, 0xc7, 0x11, 0x4d, 0x44, 0xd8, 0xc4, 0xe8, 0x2f, 0xec, 0x3e, 0x94, 0x58, - 0xce, 0x73, 0x0d, 0x4a, 0x2e, 0x19, 0xbc, 0x27, 0xed, 0x35, 0x68, 0x96, 0x57, 0xa5, 0x26, 0x13, 0x39, 0x28, 0x1f, - 0x0e, 0x05, 0xec, 0xa5, 0xc6, 0x4f, 0x13, 0x7e, 0xc2, 0xf2, 0xd6, 0xde, 0x9a, 0x52, 0x54, 0xd2, 0x00, 0x15, 0xf8, - 0x98, 0xc1, 0xff, 0xee, 0x0c, 0xb1, 0x60, 0x8a, 0x8e, 0x1f, 0xce, 0xc4, 0xdc, 0x7a, 0x6e, 0x95, 0x75, 0x94, 0xad, - 0xd1, 0x4e, 0xc0, 0xa9, 0x8e, 0x93, 0x44, 0x38, 0xf5, 0x1e, 0x71, 0x51, 0xf7, 0x72, 0x88, 0xba, 0x61, 0x9f, 0x2a, - 0x1d, 0x6c, 0x39, 0x4d, 0x83, 0x23, 0xf1, 0x2b, 0xf5, 0xd9, 0x7b, 0x2b, 0x88, 0x20, 0x45, 0x36, 0xa2, 0x24, 0x8d, - 0x63, 0x91, 0xc3, 0xf6, 0xbe, 0x90, 0xfb, 0x7f, 0xbf, 0x0f, 0xe1, 0xa4, 0x55, 0x10, 0x97, 0x9e, 0x40, 0x44, 0x38, - 0x3a, 0xfc, 0x88, 0xf0, 0x44, 0xaa, 0x0a, 0xdf, 0xd7, 0x27, 0x6e, 0xcc, 0xee, 0x85, 0x39, 0xaa, 0xb7, 0x00, 0xc3, - 0x58, 0x6f, 0x2d, 0x42, 0x12, 0xad, 0x34, 0xa3, 0xad, 0x07, 0xc4, 0x88, 0x77, 0x6b, 0x8b, 0x0c, 0xc6, 0xda, 0x92, - 0x48, 0x00, 0xbf, 0x25, 0x21, 0x43, 0xdb, 0x46, 0x60, 0xc6, 0xf0, 0x76, 0x56, 0x5c, 0xba, 0x0e, 0xdb, 0x9c, 0xc3, - 0x17, 0xb2, 0xd0, 0xac, 0x23, 0x4a, 0x13, 0x84, 0xfc, 0x03, 0x4e, 0x16, 0x0a, 0xa3, 0x79, 0x71, 0x94, 0x4e, 0x12, - 0xeb, 0xbb, 0xae, 0x52, 0xc1, 0x66, 0xf3, 0x11, 0xf5, 0x65, 0x47, 0xc9, 0xd7, 0xe0, 0xa4, 0xe3, 0x24, 0x8b, 0x1c, - 0x44, 0x2d, 0x2a, 0xe7, 0x63, 0x12, 0x96, 0x76, 0x75, 0xaa, 0xcd, 0x7a, 0x5d, 0x94, 0x75, 0xf5, 0x42, 0x44, 0x8a, - 0xde, 0x47, 0x3d, 0x7a, 0x24, 0x21, 0x15, 0x5a, 0x95, 0xda, 0xe5, 0x11, 0xb8, 0x6d, 0x6a, 0xc5, 0xb6, 0x5c, 0xc2, - 0x12, 0x35, 0xfe, 0x13, 0xf4, 0x51, 0x2e, 0xee, 0x65, 0x80, 0x46, 0xc7, 0x53, 0xf3, 0xd6, 0x03, 0xaf, 0x1c, 0xe5, - 0x97, 0x56, 0x9b, 0xf4, 0x2b, 0x20, 0x33, 0xda, 0x3f, 0x5a, 0x4a, 0x20, 0x33, 0x30, 0x93, 0x96, 0x86, 0x44, 0x8e, - 0x62, 0x96, 0xe6, 0x7f, 0xe2, 0x8a, 0xad, 0x10, 0x69, 0x58, 0xcd, 0x3d, 0xfe, 0x53, 0xe5, 0xd5, 0x72, 0x2d, 0x33, - 0xcd, 0xcd, 0x12, 0xc7, 0x8a, 0xc5, 0x45, 0xbd, 0xae, 0x44, 0x16, 0x08, 0x71, 0x84, 0x69, 0xac, 0xa7, 0xde, 0x28, - 0xad, 0xde, 0x23, 0xa1, 0xcc, 0x4f, 0xd8, 0xdb, 0xb1, 0xd7, 0x83, 0x2c, 0xc4, 0xb1, 0xe5, 0x60, 0xb3, 0xf5, 0x3e, - 0x95, 0xa9, 0x88, 0xcf, 0xea, 0xe2, 0x6c, 0x53, 0x89, 0xb3, 0x3a, 0x11, 0x67, 0x3f, 0x42, 0xce, 0x1f, 0xcf, 0xa8, - 0xe8, 0xb3, 0xfb, 0xb4, 0x4e, 0x8a, 0x4d, 0x4d, 0x4f, 0x5e, 0x62, 0x19, 0x3f, 0x9e, 0x11, 0x57, 0xcd, 0x19, 0x8d, - 0x64, 0x3c, 0x3a, 0x7b, 0x9f, 0x01, 0xc9, 0xeb, 0x59, 0xba, 0x82, 0xc1, 0x3b, 0x0b, 0xf3, 0xf8, 0xac, 0x14, 0xb7, - 0x60, 0x71, 0x2a, 0x3b, 0xdf, 0x83, 0x0c, 0xab, 0xf0, 0x4f, 0x71, 0x06, 0xd0, 0xae, 0x67, 0x69, 0x7d, 0x96, 0x56, - 0x67, 0x79, 0x51, 0x9f, 0x29, 0x29, 0x1c, 0xc2, 0xf8, 0xe1, 0x3d, 0x7d, 0x65, 0x97, 0xb7, 0x59, 0xdc, 0x65, 0x91, - 0x3f, 0x45, 0xaf, 0x22, 0x62, 0xd2, 0xa8, 0x84, 0xd7, 0xee, 0x6f, 0x9b, 0xfb, 0x87, 0xd7, 0x8d, 0xdd, 0xcf, 0xee, - 0x18, 0xd1, 0x05, 0xf5, 0x78, 0x25, 0x29, 0x15, 0x14, 0x10, 0x38, 0xd1, 0xac, 0xf1, 0xe0, 0x8e, 0x03, 0x5e, 0x0d, - 0x6c, 0xc9, 0xd6, 0x3e, 0x7f, 0x1a, 0xcb, 0x30, 0xed, 0x4d, 0x80, 0x7f, 0x95, 0xbd, 0xe9, 0x3a, 0x58, 0xe2, 0x7d, - 0x0b, 0xd9, 0x86, 0x5e, 0xbd, 0xe0, 0xcf, 0xbc, 0x5c, 0xfd, 0xcd, 0x7e, 0x07, 0x20, 0x0c, 0x88, 0x59, 0xf5, 0xd1, - 0xc4, 0xbd, 0xb3, 0xb2, 0xec, 0x9c, 0x2c, 0xbb, 0x1e, 0xfa, 0x35, 0x89, 0x51, 0x69, 0x65, 0x29, 0x9d, 0x2c, 0x25, - 0x64, 0x01, 0x9f, 0x18, 0x4d, 0x6d, 0x04, 0x10, 0xb6, 0xa3, 0x54, 0xbe, 0x50, 0x79, 0x11, 0x85, 0x73, 0x82, 0xe7, - 0x89, 0x18, 0xdd, 0x59, 0xc9, 0x80, 0xe1, 0x10, 0x82, 0x39, 0x68, 0x8b, 0xbd, 0xa1, 0x9b, 0x88, 0xbf, 0x5e, 0x16, - 0xe5, 0xab, 0x98, 0x7c, 0x0a, 0x76, 0x27, 0x1f, 0x97, 0xf0, 0xb8, 0x3c, 0xf9, 0x38, 0x44, 0x8f, 0x84, 0x93, 0x8f, - 0xc1, 0xf7, 0x48, 0xce, 0xeb, 0xae, 0xc7, 0x09, 0x72, 0x0b, 0xe9, 0xfe, 0x76, 0x4c, 0x02, 0x34, 0xaf, 0x61, 0x39, - 0x6a, 0x2a, 0xae, 0x99, 0x19, 0xe3, 0x79, 0xa3, 0xf7, 0xc7, 0x8e, 0xb7, 0x4c, 0xa1, 0x98, 0xc5, 0xbc, 0x86, 0xdf, - 0xb3, 0x2a, 0x50, 0x77, 0xbd, 0x4d, 0x72, 0xcb, 0xac, 0x9e, 0xa3, 0xdd, 0xf7, 0x5d, 0x9d, 0x08, 0x6a, 0x7f, 0x87, - 0x3d, 0xcf, 0xac, 0x77, 0x55, 0x0c, 0x5c, 0xaa, 0x64, 0x87, 0x4c, 0x55, 0xd3, 0x03, 0x95, 0xd2, 0xe0, 0xe9, 0xa5, - 0x75, 0xf9, 0x52, 0x69, 0x23, 0xcf, 0x34, 0xbf, 0x01, 0xbc, 0x98, 0xba, 0x2c, 0x76, 0xdf, 0xdc, 0x57, 0x70, 0x1b, - 0xef, 0xf7, 0xd7, 0x95, 0x67, 0x7e, 0xe2, 0x02, 0xb0, 0x37, 0x15, 0x5a, 0x27, 0x50, 0x6a, 0x58, 0x87, 0xd7, 0x89, - 0x88, 0xfe, 0x6c, 0x97, 0xeb, 0xcc, 0x75, 0xc0, 0x88, 0x22, 0x7e, 0x1b, 0x8f, 0xfe, 0x00, 0xc5, 0xb5, 0xb1, 0x07, - 0x84, 0x75, 0x48, 0xe8, 0x33, 0x02, 0x90, 0x7a, 0xf4, 0x51, 0xf2, 0x27, 0x68, 0x56, 0x34, 0x77, 0x4c, 0x7e, 0xae, - 0xaf, 0x94, 0xfe, 0x7e, 0x5d, 0x79, 0x64, 0x4e, 0x69, 0x9b, 0x69, 0xac, 0xd6, 0x54, 0x02, 0xe1, 0x15, 0x95, 0xac, - 0xc2, 0x67, 0xf3, 0x46, 0xf4, 0xfb, 0xf2, 0x08, 0x4f, 0xab, 0x9f, 0xb6, 0x18, 0xdf, 0x0a, 0x88, 0x46, 0xc2, 0xef, - 0xf7, 0x2b, 0x80, 0x79, 0x91, 0xcd, 0xec, 0x3e, 0x0e, 0xa8, 0x52, 0xa2, 0x69, 0x9c, 0xcd, 0xf3, 0x7b, 0x7a, 0x53, - 0x76, 0xd0, 0xa9, 0x53, 0x05, 0x2e, 0xb8, 0x2a, 0x19, 0xaf, 0xac, 0x27, 0xf2, 0xf9, 0xcd, 0xcd, 0x26, 0xcd, 0xe2, - 0x77, 0xe5, 0x2f, 0x38, 0xb6, 0xba, 0x0e, 0x0f, 0x4c, 0x9d, 0xae, 0x9d, 0x47, 0x5a, 0x7b, 0x21, 0x20, 0xa2, 0x5d, - 0x43, 0xad, 0x17, 0x16, 0x7a, 0xa4, 0x27, 0xc2, 0x39, 0x49, 0xd4, 0xb4, 0x03, 0x2d, 0x8d, 0xd0, 0xd7, 0xd7, 0x9c, - 0xfe, 0xc2, 0x60, 0xed, 0xf3, 0x31, 0x03, 0xb2, 0x12, 0xfd, 0x58, 0x3d, 0x34, 0x36, 0x73, 0xe8, 0x59, 0xab, 0xf2, - 0xcc, 0xab, 0x0e, 0x07, 0xc4, 0x87, 0xd1, 0x5f, 0xf2, 0xfb, 0xfd, 0x17, 0x34, 0xff, 0x98, 0x50, 0xe3, 0x67, 0x9b, - 0x01, 0xba, 0xf6, 0x5d, 0x79, 0x20, 0xea, 0xb9, 0x56, 0x09, 0x42, 0xbc, 0x41, 0x4c, 0x34, 0x23, 0xe6, 0xe0, 0xb4, - 0x43, 0xcd, 0x3f, 0x49, 0x0d, 0x08, 0x51, 0xe2, 0x75, 0x4c, 0x59, 0x90, 0xd3, 0x26, 0x8e, 0xf4, 0xa3, 0x70, 0x22, - 0x3f, 0x88, 0xaa, 0xc8, 0xee, 0xe0, 0x82, 0xc1, 0xd4, 0x7b, 0xda, 0x2f, 0xd1, 0x6f, 0x09, 0x47, 0xce, 0xd1, 0xaa, - 0x10, 0x44, 0x4e, 0x08, 0x6b, 0x0d, 0x61, 0x82, 0xd8, 0x20, 0x5e, 0xf6, 0x5d, 0x92, 0xe1, 0x48, 0xc1, 0x65, 0x1d, - 0x3b, 0xc6, 0x5c, 0x1d, 0x55, 0xaf, 0x01, 0x8c, 0x57, 0x8e, 0xa0, 0xd9, 0x28, 0xb2, 0x4b, 0x88, 0x2a, 0x72, 0x3c, - 0x01, 0xb5, 0x83, 0xd2, 0xd8, 0x4c, 0xcf, 0xc7, 0x41, 0x3e, 0x5a, 0x54, 0xa8, 0x73, 0x62, 0x19, 0xaf, 0x01, 0x58, - 0x3b, 0x57, 0xfd, 0x3c, 0xab, 0xc1, 0x93, 0x86, 0xf8, 0x7c, 0x8c, 0xb6, 0x57, 0x36, 0x07, 0xd5, 0x76, 0x3a, 0x2b, - 0xaf, 0x98, 0x2e, 0x07, 0xc6, 0x7d, 0xc3, 0x2b, 0x8a, 0x33, 0xfc, 0xe0, 0xc1, 0x16, 0xe7, 0x4f, 0x37, 0xd4, 0x7e, - 0xcc, 0x8d, 0x7a, 0x18, 0x68, 0x2d, 0x78, 0x53, 0x10, 0xeb, 0xef, 0xbb, 0x8e, 0x6c, 0xef, 0xb4, 0xc8, 0x68, 0xf2, - 0xd9, 0xcf, 0xdf, 0x97, 0xe9, 0x2a, 0x85, 0xfb, 0x92, 0x93, 0x45, 0x33, 0x0f, 0x81, 0xbd, 0x21, 0x86, 0xeb, 0xa3, - 0xc2, 0x23, 0xca, 0xfa, 0x7d, 0xf8, 0x7d, 0x95, 0x81, 0x29, 0x06, 0xae, 0x2b, 0x04, 0xe3, 0x21, 0x10, 0xc4, 0xc3, - 0x34, 0x3a, 0x19, 0xd4, 0xa0, 0x0d, 0xdf, 0x00, 0x64, 0x06, 0x78, 0x64, 0x2e, 0x3d, 0x02, 0xee, 0x02, 0xd7, 0x9e, - 0x8c, 0xc7, 0xfe, 0xc4, 0x34, 0x34, 0x6a, 0x4a, 0x33, 0x3d, 0x37, 0x7e, 0xd3, 0x51, 0x2d, 0xd7, 0xce, 0x7f, 0x7c, - 0xc9, 0x6f, 0xd0, 0x0b, 0x5a, 0x5e, 0xee, 0x23, 0x75, 0xb9, 0xcf, 0x28, 0x2e, 0x13, 0xc9, 0x61, 0x41, 0x2c, 0x4b, - 0x38, 0xf0, 0x18, 0x95, 0x2c, 0xb6, 0xf4, 0x58, 0x15, 0x2d, 0x5f, 0x94, 0x1b, 0xa4, 0x43, 0x27, 0x04, 0x4b, 0x54, - 0x10, 0x2c, 0x81, 0x71, 0x11, 0x6b, 0xbe, 0x19, 0xe4, 0x2c, 0x9e, 0x6d, 0xe6, 0x1c, 0x09, 0xeb, 0x92, 0xc3, 0xa1, - 0x90, 0x60, 0x33, 0xd9, 0x6c, 0x3d, 0x67, 0x6b, 0x9f, 0x81, 0x12, 0xa0, 0x94, 0x69, 0x82, 0xd2, 0xb4, 0x62, 0x2b, - 0x6e, 0x5a, 0x83, 0xd5, 0x6a, 0xca, 0x56, 0x35, 0x65, 0xe7, 0x34, 0xe5, 0xa8, 0x82, 0x92, 0x13, 0x4a, 0x51, 0x86, - 0x01, 0x8c, 0xd8, 0x24, 0xba, 0xca, 0xd0, 0xc7, 0x3b, 0xe1, 0x11, 0x54, 0x11, 0x91, 0x4f, 0x18, 0x42, 0x60, 0x22, - 0x8a, 0x0b, 0x55, 0x28, 0x06, 0xc8, 0x88, 0x04, 0x82, 0x89, 0x4a, 0x9d, 0x02, 0xf3, 0xd1, 0x54, 0x31, 0x6c, 0xda, - 0x13, 0xe5, 0x7b, 0xea, 0xb8, 0x47, 0xd9, 0xe6, 0x1f, 0x62, 0x17, 0x84, 0xc8, 0xdd, 0xb8, 0x53, 0x3f, 0x23, 0xde, - 0xdb, 0x1d, 0x61, 0xfc, 0x64, 0xc7, 0x2d, 0xc2, 0x15, 0xc1, 0x96, 0x6a, 0x0e, 0xb1, 0x98, 0x57, 0x93, 0x04, 0xb5, - 0x2c, 0x89, 0xbf, 0xe1, 0xc9, 0x20, 0x67, 0x4b, 0xf0, 0xa0, 0x9d, 0xb3, 0x0c, 0xf0, 0x57, 0xac, 0x16, 0xfd, 0x5e, - 0x7b, 0x4b, 0x90, 0x9f, 0x36, 0x76, 0xa3, 0x30, 0x31, 0x82, 0x44, 0xdd, 0xae, 0x0c, 0xe4, 0x87, 0xf7, 0x38, 0x1d, - 0x8f, 0x3d, 0x65, 0xcc, 0xad, 0x4c, 0x2f, 0xd3, 0xb9, 0x92, 0x6f, 0xe4, 0x5e, 0xfa, 0xd0, 0x4b, 0xb0, 0x73, 0xc0, - 0x1b, 0x48, 0x1b, 0xf8, 0x11, 0xb6, 0x0b, 0xaf, 0x0d, 0x12, 0x66, 0x04, 0xd8, 0xe2, 0xf8, 0x18, 0x29, 0x81, 0x21, - 0x1c, 0x67, 0x29, 0x00, 0xd3, 0xe8, 0xcb, 0x6c, 0x65, 0x5f, 0x66, 0xb5, 0x66, 0x4b, 0xe5, 0x74, 0xef, 0xdc, 0xba, - 0x9d, 0xcf, 0x24, 0x00, 0x98, 0xd4, 0x39, 0x10, 0x67, 0x26, 0xd8, 0xa5, 0x49, 0x64, 0xf9, 0x10, 0xe6, 0xb7, 0xe2, - 0x65, 0x59, 0xac, 0x54, 0x57, 0xb4, 0x7d, 0x66, 0xf2, 0x19, 0xe9, 0x24, 0x54, 0x40, 0x41, 0x21, 0xd7, 0xfa, 0xf4, - 0x6d, 0xf8, 0x36, 0x28, 0x34, 0x30, 0x5b, 0x85, 0x7b, 0x9a, 0xac, 0x91, 0x7a, 0xa3, 0xea, 0xf7, 0xc9, 0x35, 0x90, - 0xea, 0xcc, 0xa1, 0x65, 0xcf, 0x2a, 0x0c, 0x10, 0x3b, 0xea, 0x33, 0x12, 0xea, 0x40, 0xea, 0x01, 0x43, 0x88, 0xb6, - 0xe9, 0xe3, 0x4f, 0x86, 0x44, 0x17, 0x60, 0x0b, 0xd1, 0x06, 0x7e, 0xfc, 0x09, 0xf6, 0x59, 0x10, 0x1e, 0xd3, 0xfc, - 0x0d, 0x24, 0x1d, 0x1b, 0x38, 0xad, 0x3e, 0x05, 0x1f, 0x24, 0x39, 0x98, 0xa8, 0x83, 0x97, 0xfb, 0x4b, 0xbf, 0x0f, - 0x5b, 0x76, 0x2e, 0xa5, 0x3a, 0x56, 0xea, 0x6d, 0x5b, 0xfb, 0x41, 0xb4, 0x05, 0x47, 0x16, 0xf1, 0xf7, 0x19, 0x22, - 0x82, 0x99, 0x41, 0x84, 0x5d, 0x0b, 0x75, 0xb7, 0xa7, 0xd4, 0xb2, 0xa8, 0xb7, 0x3d, 0xa5, 0xd4, 0x6d, 0x18, 0xbe, - 0x9b, 0x60, 0xa6, 0xb8, 0xe1, 0x6f, 0x32, 0x2f, 0xd4, 0x1b, 0x8f, 0x71, 0x8c, 0x5f, 0x7b, 0xfe, 0x7e, 0xc9, 0xab, - 0xd9, 0x46, 0x99, 0x30, 0x6f, 0xf9, 0x72, 0x16, 0xca, 0xae, 0x96, 0xc6, 0x9d, 0xcf, 0xde, 0x52, 0xcd, 0x07, 0xff, - 0x70, 0x48, 0x20, 0xde, 0x28, 0xbe, 0xba, 0x6d, 0xe4, 0xd6, 0x35, 0xd9, 0x5c, 0x95, 0x80, 0xfa, 0x7d, 0xbe, 0xc6, - 0xfd, 0x16, 0xeb, 0xdf, 0x3d, 0x0d, 0x32, 0x56, 0x33, 0x5c, 0x31, 0x85, 0x4f, 0x01, 0x60, 0x70, 0x38, 0x15, 0xa4, - 0x05, 0xde, 0xf0, 0x72, 0x78, 0x39, 0xd9, 0x90, 0x49, 0x77, 0xe3, 0x23, 0x77, 0x16, 0xa8, 0x7a, 0xbf, 0xa3, 0x38, - 0x69, 0x90, 0x68, 0xec, 0x35, 0xf8, 0x2c, 0xcb, 0x28, 0x17, 0x4d, 0xdc, 0x87, 0xe4, 0x2b, 0x3d, 0x80, 0xb9, 0x0a, - 0x25, 0x40, 0xf4, 0x1b, 0xcb, 0x62, 0x23, 0xda, 0x16, 0x1b, 0x58, 0x4a, 0xd5, 0x5c, 0xaf, 0xa6, 0xcf, 0x5e, 0x89, - 0xe6, 0x7d, 0x34, 0xe3, 0x94, 0x46, 0x03, 0x8e, 0xd3, 0x28, 0xdc, 0xbe, 0xbb, 0x13, 0xe5, 0x32, 0x03, 0x4b, 0xb6, - 0x0a, 0xa7, 0xb8, 0x6c, 0xd4, 0x19, 0xf1, 0x2c, 0x8f, 0x15, 0x40, 0xc7, 0x43, 0x02, 0xa0, 0xba, 0x20, 0xa0, 0x22, - 0x5a, 0x4a, 0x6f, 0x85, 0x16, 0x0b, 0xf5, 0x86, 0xa3, 0x14, 0xfe, 0x48, 0x7f, 0x1e, 0xe4, 0x53, 0x00, 0x62, 0xd7, - 0xc7, 0xd1, 0xcb, 0xa2, 0xa4, 0x4f, 0x15, 0xb3, 0x5c, 0x0e, 0x26, 0xb0, 0xab, 0x13, 0x19, 0x6a, 0x05, 0x79, 0xab, - 0xae, 0xbc, 0x95, 0xc9, 0xdb, 0x18, 0xa7, 0xe4, 0x07, 0x6e, 0x3a, 0xd6, 0x88, 0x81, 0x57, 0x9e, 0xd6, 0x69, 0x82, - 0x34, 0xb9, 0x00, 0x86, 0x21, 0x7e, 0x9f, 0x79, 0xcf, 0x3c, 0x47, 0xaa, 0x82, 0x64, 0x76, 0x97, 0x79, 0xea, 0x22, - 0xaa, 0xaf, 0x9c, 0x5a, 0x3a, 0x73, 0xfa, 0x11, 0xc0, 0x7b, 0x4c, 0x4d, 0x1a, 0xf2, 0x11, 0x6e, 0x4b, 0xf1, 0xf5, - 0x56, 0x5d, 0xe3, 0xa5, 0xd1, 0xb9, 0x7b, 0xf9, 0xd2, 0x9d, 0x06, 0xfd, 0x14, 0x04, 0xe5, 0x7c, 0x56, 0x0a, 0xd8, - 0x53, 0x66, 0x73, 0xbd, 0x5a, 0xb5, 0x42, 0xeb, 0x70, 0x18, 0x6b, 0x47, 0x21, 0xad, 0xce, 0x02, 0xb6, 0x1a, 0xe9, - 0x94, 0x00, 0x21, 0x38, 0x4e, 0xc3, 0x4e, 0x30, 0xee, 0xd2, 0x69, 0x44, 0xd6, 0x2b, 0x25, 0xe9, 0xc2, 0x0c, 0x92, - 0x7f, 0x92, 0xd7, 0x33, 0xa0, 0x25, 0x80, 0x43, 0x11, 0x4b, 0x78, 0x38, 0x49, 0xae, 0x00, 0x3a, 0x1d, 0x0e, 0x2a, - 0x0d, 0xcd, 0x59, 0xcd, 0x92, 0xf9, 0x24, 0x96, 0xaa, 0xca, 0xc3, 0xc1, 0x53, 0x6e, 0x06, 0xfd, 0x7e, 0x36, 0x2d, - 0x95, 0x0b, 0x40, 0x10, 0xeb, 0xc2, 0x00, 0xf1, 0x48, 0x0b, 0x4f, 0x16, 0x7d, 0x4a, 0xe2, 0x97, 0xb3, 0x64, 0x6e, - 0xb2, 0xe1, 0x1d, 0x18, 0xc1, 0x66, 0x5c, 0x97, 0x94, 0x69, 0x8f, 0xca, 0xef, 0x19, 0x3d, 0xb5, 0x7d, 0xad, 0xd5, - 0x16, 0xb1, 0xae, 0x83, 0xab, 0x12, 0xf5, 0x14, 0x1f, 0x94, 0x24, 0x78, 0xbf, 0x70, 0x6e, 0x46, 0xca, 0xd7, 0x22, - 0xf7, 0x83, 0x76, 0xa6, 0x56, 0x0e, 0x1c, 0x81, 0x1c, 0xab, 0xa8, 0xe4, 0xf5, 0xae, 0x43, 0xf0, 0xe8, 0xae, 0x54, - 0xa0, 0x1c, 0xfc, 0x14, 0xc4, 0xe8, 0xfa, 0xaa, 0xb3, 0x86, 0x9a, 0x69, 0x54, 0x79, 0x04, 0x9d, 0x3a, 0x80, 0x27, - 0x05, 0x2f, 0xb5, 0xfa, 0xf1, 0x70, 0xf0, 0xcc, 0x0f, 0xfe, 0x2e, 0xd3, 0xb7, 0x10, 0x13, 0xe5, 0x54, 0x23, 0x24, - 0xae, 0x94, 0x24, 0xe2, 0xe3, 0x45, 0xcb, 0x8a, 0x51, 0x19, 0xde, 0xf3, 0x4a, 0x95, 0xaf, 0x4e, 0x55, 0x5e, 0x8c, - 0xb4, 0x2d, 0x81, 0xd7, 0xe4, 0x1f, 0x22, 0xd7, 0xbc, 0xf5, 0x75, 0x57, 0x19, 0xfa, 0x48, 0x56, 0xa0, 0x23, 0xd8, - 0xca, 0x52, 0x72, 0xc0, 0x27, 0xd5, 0x5d, 0xb5, 0x6a, 0x7d, 0x4e, 0xd9, 0x46, 0xb8, 0xc9, 0xaf, 0x63, 0x07, 0x47, - 0xca, 0x6f, 0xf0, 0x5c, 0x00, 0x7b, 0x0d, 0xd8, 0x9b, 0x73, 0x56, 0x34, 0x0f, 0x0e, 0x69, 0x5b, 0xa0, 0x91, 0x99, - 0xdb, 0xb9, 0xba, 0x6f, 0xcb, 0xa3, 0x34, 0x86, 0xc8, 0xb4, 0x07, 0xa6, 0x83, 0xcd, 0x28, 0xff, 0x3d, 0xe5, 0xb7, - 0x0a, 0xc7, 0xc0, 0xb7, 0x53, 0xef, 0x00, 0xaa, 0x9e, 0x36, 0xc8, 0x58, 0x33, 0x0c, 0xad, 0xec, 0x72, 0x29, 0xb4, - 0x04, 0x2d, 0x75, 0x13, 0x04, 0xe7, 0x47, 0x44, 0x39, 0x02, 0xd0, 0x45, 0x0a, 0x98, 0xe0, 0xa7, 0xb4, 0xdd, 0xfd, - 0xfe, 0x3a, 0xf5, 0xc8, 0xbd, 0x2b, 0xd4, 0x28, 0xa1, 0x04, 0x63, 0x3f, 0xd1, 0x98, 0x41, 0x47, 0x57, 0xe4, 0x84, - 0x67, 0xad, 0x0e, 0xeb, 0xba, 0x29, 0x83, 0xb2, 0x38, 0xe6, 0xd5, 0x74, 0xf6, 0xc7, 0xa3, 0x7d, 0xdd, 0x20, 0x0b, - 0xf9, 0x1f, 0xac, 0x87, 0x64, 0xd0, 0x3d, 0x08, 0x85, 0xe8, 0xcd, 0x83, 0x19, 0xfe, 0xc7, 0x36, 0x3c, 0xfb, 0x8e, - 0x1b, 0x75, 0x82, 0x98, 0x23, 0x8e, 0x97, 0x9e, 0xa2, 0xad, 0x87, 0x5b, 0x20, 0x5b, 0xe3, 0xe5, 0xad, 0xbd, 0x06, - 0x72, 0x8a, 0xe3, 0xbf, 0xe5, 0x99, 0x5a, 0xd9, 0xe0, 0xa7, 0xa7, 0x6c, 0x07, 0x1e, 0x5e, 0x84, 0x80, 0x62, 0x58, - 0x36, 0xfe, 0xd6, 0x72, 0x9c, 0xd1, 0x7f, 0xf3, 0x88, 0x61, 0xb0, 0x88, 0xfc, 0xf8, 0xb2, 0x14, 0xe2, 0xab, 0xf0, - 0x3e, 0x55, 0xde, 0x2d, 0x39, 0x65, 0xde, 0xea, 0x61, 0x74, 0x5d, 0x92, 0xbe, 0x4b, 0x3e, 0xb6, 0x86, 0xed, 0x0f, - 0xed, 0x7e, 0x33, 0x44, 0x10, 0x42, 0x39, 0x7e, 0xce, 0xe8, 0x84, 0xc6, 0x87, 0xd5, 0xec, 0xf4, 0xfa, 0xbd, 0x73, - 0xbc, 0x60, 0x6b, 0x34, 0xc0, 0xe3, 0xa1, 0x8b, 0x79, 0xa2, 0x86, 0x4e, 0xd7, 0xb5, 0x73, 0xf0, 0xc0, 0x20, 0xcb, - 0x93, 0xef, 0x18, 0x96, 0xd8, 0x9f, 0x44, 0x3c, 0x69, 0xab, 0x36, 0x36, 0x47, 0xaa, 0x8d, 0x9a, 0x81, 0x1f, 0xbc, - 0x82, 0x02, 0xa3, 0x0b, 0xd2, 0x02, 0x8c, 0xc3, 0x11, 0x80, 0xac, 0x18, 0xc7, 0x23, 0x83, 0x09, 0x0c, 0xe9, 0x86, - 0xa2, 0x00, 0x3c, 0x3c, 0x8e, 0x07, 0x21, 0x03, 0x48, 0x17, 0x3c, 0x34, 0x6c, 0x93, 0x90, 0xf2, 0xf3, 0x3c, 0xaf, - 0xd5, 0x10, 0xfa, 0xce, 0x42, 0x75, 0xec, 0x47, 0xda, 0x2b, 0xd6, 0xb5, 0x2a, 0x1d, 0xd9, 0xea, 0x00, 0x7d, 0x43, - 0x06, 0xbe, 0x75, 0x6c, 0x01, 0x10, 0x2d, 0xf1, 0x25, 0xf5, 0x6a, 0x5f, 0xc6, 0xac, 0x50, 0xaf, 0x2f, 0x4c, 0xbb, - 0x5e, 0x48, 0x8b, 0x02, 0x2a, 0x6e, 0x5b, 0xb5, 0x3d, 0x92, 0xf3, 0x1f, 0xde, 0x75, 0xb4, 0xe3, 0xb3, 0x53, 0x63, - 0x4b, 0x28, 0x73, 0x8b, 0x27, 0xb2, 0x3a, 0xda, 0x52, 0x9d, 0xea, 0x03, 0x2e, 0x35, 0xa9, 0xce, 0x0c, 0x0c, 0xaf, - 0x11, 0xa0, 0xdc, 0x42, 0x24, 0x8d, 0xc3, 0xde, 0xf9, 0x64, 0x50, 0x30, 0xb7, 0x48, 0x40, 0x02, 0xdb, 0xd8, 0xda, - 0x45, 0x73, 0xfd, 0xfa, 0x92, 0x7a, 0x55, 0x9b, 0xaa, 0x1e, 0xbc, 0xf1, 0x02, 0x67, 0xef, 0xb4, 0x16, 0x10, 0x40, - 0x61, 0x6b, 0x59, 0x0e, 0xce, 0xdd, 0xae, 0x6a, 0xa9, 0x28, 0xa3, 0x7e, 0xff, 0xfc, 0x4b, 0x8a, 0x8a, 0xd8, 0x53, - 0xc5, 0x29, 0xeb, 0xb7, 0x5b, 0xe6, 0xa2, 0xb2, 0xe4, 0x0d, 0xaa, 0x68, 0xad, 0x8e, 0x9a, 0xca, 0x75, 0x73, 0xd5, - 0x92, 0x09, 0x62, 0x74, 0x9f, 0xae, 0x75, 0xee, 0xd4, 0x7b, 0xaf, 0xe2, 0x88, 0x81, 0xe0, 0xa6, 0x7b, 0x7c, 0x70, - 0x10, 0x1a, 0x15, 0xe5, 0x82, 0x1b, 0xa5, 0x55, 0x25, 0xa5, 0x90, 0xb7, 0x2a, 0x9a, 0x33, 0x7d, 0x04, 0x40, 0x04, - 0x58, 0x25, 0xea, 0xff, 0xf0, 0xa5, 0x31, 0x1e, 0x3c, 0xf0, 0x35, 0xb9, 0x8e, 0xad, 0xf7, 0x4f, 0x6b, 0xa4, 0xd5, - 0xc6, 0x31, 0xa9, 0x55, 0x2f, 0x5b, 0xc5, 0xcb, 0xee, 0x75, 0x2a, 0x06, 0xcf, 0xff, 0xe7, 0x3e, 0x40, 0x8d, 0x68, - 0x29, 0x83, 0x5b, 0x57, 0x03, 0x34, 0x3e, 0x1c, 0x0b, 0xdf, 0xf8, 0x21, 0xe3, 0x7c, 0x30, 0x43, 0x47, 0xb5, 0x39, - 0x38, 0x20, 0x38, 0xaa, 0x7b, 0x34, 0x26, 0xcc, 0xc2, 0xb9, 0x07, 0x81, 0xea, 0x13, 0xf7, 0x19, 0xd7, 0x5e, 0xd0, - 0x26, 0xf0, 0xc9, 0xba, 0xae, 0x29, 0x02, 0x5c, 0xc4, 0xc6, 0x44, 0x0c, 0x71, 0xd9, 0x24, 0x52, 0xdf, 0x8c, 0x41, - 0x01, 0x50, 0x3c, 0xad, 0x48, 0x2e, 0x5d, 0xa4, 0x79, 0x25, 0xca, 0x5a, 0x37, 0xa3, 0x62, 0xc5, 0x10, 0x00, 0x1e, - 0x82, 0xe2, 0xaa, 0x32, 0x13, 0x1a, 0xb1, 0x81, 0x54, 0x96, 0x82, 0x55, 0xc3, 0xc2, 0x6f, 0xda, 0x6f, 0x92, 0x93, - 0xde, 0xf9, 0xb8, 0x75, 0xee, 0xd8, 0xf7, 0x8e, 0x42, 0x4a, 0x7b, 0x28, 0x26, 0x08, 0x82, 0x9f, 0xd6, 0xe1, 0xfc, - 0x19, 0x7f, 0x4a, 0x60, 0x2a, 0xb2, 0x19, 0x03, 0x0e, 0x42, 0x44, 0x66, 0xfc, 0x9e, 0xc3, 0xa7, 0xbc, 0x9c, 0x84, - 0xc3, 0xa1, 0x0f, 0xfa, 0x50, 0x9e, 0xcd, 0xc2, 0xa1, 0x98, 0x4b, 0xef, 0x75, 0xb0, 0xd6, 0x85, 0xbc, 0x9e, 0x84, - 0x88, 0x16, 0x1a, 0xfa, 0xe0, 0xbc, 0xee, 0x9a, 0x23, 0x2c, 0x01, 0x68, 0xe2, 0xe8, 0xcb, 0xfa, 0xfd, 0xc8, 0xd3, - 0x86, 0x16, 0x29, 0x2e, 0x1a, 0x65, 0x36, 0xcb, 0x65, 0x27, 0x6c, 0x5c, 0xbb, 0x05, 0x42, 0xf1, 0x30, 0x6d, 0xa1, - 0x6a, 0x3d, 0xd5, 0xeb, 0xb9, 0x69, 0xf7, 0xdd, 0x83, 0x6a, 0x95, 0x23, 0x9d, 0xb5, 0xe9, 0x4a, 0xad, 0x6e, 0x19, - 0x55, 0xeb, 0x2c, 0x8d, 0xa8, 0x72, 0x93, 0xdc, 0x35, 0x6a, 0xc1, 0x27, 0x1b, 0xba, 0x4c, 0xd9, 0xd9, 0x1a, 0x9c, - 0x38, 0xf2, 0x5c, 0x72, 0xcb, 0x77, 0xe7, 0x15, 0xdd, 0x9d, 0x6a, 0xdf, 0x02, 0xdc, 0x9b, 0x61, 0x43, 0xe6, 0xbc, - 0xc6, 0x4e, 0x83, 0x30, 0x09, 0xfc, 0x88, 0x7d, 0xcc, 0x90, 0x0d, 0x06, 0x74, 0x14, 0xd2, 0xff, 0xda, 0x32, 0x47, - 0x02, 0x26, 0x7f, 0x3d, 0xf7, 0x9b, 0x45, 0x91, 0xc3, 0x62, 0x7c, 0xbf, 0xc1, 0x48, 0x63, 0xb5, 0x06, 0xc3, 0xf2, - 0x16, 0x91, 0x3f, 0xb5, 0x3b, 0xa6, 0xa9, 0x8e, 0x37, 0xeb, 0xb5, 0xe6, 0x57, 0x4f, 0x9f, 0xea, 0xfa, 0xfc, 0xb7, - 0xef, 0x2f, 0xc3, 0x9a, 0xd9, 0x1f, 0x82, 0x50, 0xda, 0xbd, 0x5b, 0x9c, 0x3b, 0x12, 0xbd, 0x63, 0xa5, 0x99, 0x5d, - 0xda, 0x25, 0xbb, 0x34, 0xa5, 0x7d, 0x24, 0xd7, 0xab, 0x6f, 0x94, 0x37, 0x76, 0x5e, 0x31, 0xdd, 0xbf, 0x17, 0x7a, - 0x47, 0x39, 0x55, 0x13, 0x88, 0x68, 0xd2, 0x8e, 0xc4, 0xed, 0x5e, 0x19, 0x3e, 0x99, 0xe4, 0xed, 0x12, 0x8e, 0xba, - 0x86, 0xe5, 0xe6, 0xdb, 0xbf, 0xe4, 0x55, 0x67, 0x85, 0xdb, 0x2f, 0x8d, 0x59, 0xfb, 0x53, 0x10, 0x57, 0xf5, 0xa7, - 0xf7, 0xbe, 0x66, 0x4a, 0xfe, 0xaf, 0x7a, 0x0c, 0x5c, 0xfd, 0x64, 0xda, 0xd1, 0x3d, 0x85, 0xb0, 0xc1, 0xec, 0xe7, - 0xc7, 0x0f, 0x2d, 0xba, 0x46, 0x17, 0x28, 0x92, 0x03, 0xe8, 0xdc, 0x25, 0x23, 0xbc, 0xdf, 0x31, 0xce, 0xfd, 0xab, - 0x5f, 0xd5, 0xe4, 0x08, 0x11, 0xed, 0x22, 0x1c, 0x00, 0xc4, 0x9d, 0xa6, 0xb2, 0x0e, 0x35, 0x40, 0x1f, 0x10, 0x58, - 0x87, 0xbe, 0xcd, 0x00, 0x0e, 0xfa, 0x68, 0xf3, 0x2c, 0x02, 0x79, 0xdd, 0xbb, 0x63, 0xd7, 0x6c, 0xe7, 0xf3, 0xa7, - 0xab, 0xd4, 0xbb, 0x43, 0x87, 0xe0, 0xf3, 0xb1, 0x3f, 0xbd, 0x0c, 0xb4, 0xda, 0xf3, 0x9a, 0x5d, 0x3f, 0x16, 0x6c, - 0xc7, 0x76, 0x8f, 0x11, 0xa9, 0xa8, 0x3b, 0xff, 0xf0, 0xd2, 0x44, 0xcf, 0x3b, 0x2f, 0xdc, 0xf2, 0x25, 0x80, 0x07, - 0xb2, 0x18, 0x50, 0x7c, 0x96, 0xde, 0x2f, 0x2c, 0x01, 0x35, 0xf9, 0x0d, 0x5f, 0x7b, 0x6f, 0x29, 0x75, 0x01, 0x7f, - 0x0e, 0x28, 0x7d, 0x92, 0x73, 0xef, 0x76, 0x78, 0xe3, 0x5f, 0x3c, 0x01, 0xe7, 0x89, 0xd5, 0x70, 0x01, 0x7f, 0x15, - 0x7c, 0xe8, 0xdd, 0x0e, 0x30, 0xb1, 0xe4, 0x43, 0x6f, 0x35, 0x80, 0x54, 0x85, 0x0b, 0x89, 0xb1, 0x0f, 0xbf, 0x05, - 0x39, 0xc3, 0x3f, 0x7e, 0xd7, 0x18, 0xac, 0xbf, 0x05, 0x85, 0x46, 0x63, 0x2d, 0x55, 0xc8, 0x52, 0x2c, 0xce, 0x04, - 0xd8, 0x84, 0xe3, 0x6e, 0x5f, 0xac, 0x6a, 0xb3, 0x16, 0xf4, 0xe7, 0x03, 0xbe, 0x47, 0x63, 0x75, 0x55, 0xce, 0x45, - 0xf9, 0x01, 0xe9, 0x53, 0x1d, 0x1f, 0xa3, 0x62, 0x53, 0x77, 0xa7, 0x53, 0xad, 0x3a, 0xd2, 0x7e, 0x57, 0xae, 0xc1, - 0x8e, 0xd7, 0xc9, 0x91, 0xa5, 0xf0, 0xac, 0xc3, 0xce, 0x4b, 0xa7, 0x44, 0x87, 0x61, 0xbc, 0xdb, 0xaa, 0x67, 0x0c, - 0xe5, 0xb9, 0xc1, 0x98, 0x2e, 0x78, 0xc4, 0x9f, 0x0e, 0x72, 0x19, 0x1a, 0xf3, 0x0e, 0xd9, 0x30, 0x94, 0x0f, 0x2d, - 0x32, 0x24, 0x44, 0xbc, 0x87, 0x4a, 0xc0, 0xb6, 0x05, 0x65, 0x52, 0xc0, 0x59, 0x34, 0xf8, 0xbd, 0xf6, 0x72, 0xe0, - 0x3d, 0x88, 0xfc, 0x46, 0xba, 0x94, 0x4b, 0x6c, 0x74, 0xe2, 0x58, 0x16, 0xda, 0x79, 0x5c, 0x7f, 0x1d, 0x83, 0xfa, - 0xbd, 0xd2, 0x6f, 0x50, 0xce, 0xfe, 0x20, 0x59, 0xa7, 0x8d, 0x27, 0xc6, 0xbf, 0x5d, 0xe5, 0x9f, 0xa2, 0xa5, 0x1e, - 0xfe, 0x3f, 0x63, 0x0a, 0xa5, 0xbf, 0x4e, 0xcb, 0x68, 0xb3, 0x5a, 0x8a, 0x52, 0xe4, 0x91, 0x38, 0xf9, 0x5a, 0x64, - 0xe7, 0xf2, 0x9d, 0x4f, 0xa1, 0x5f, 0x00, 0x5a, 0xf6, 0x09, 0x32, 0xfa, 0x57, 0x26, 0xf8, 0xf0, 0x57, 0xed, 0x5c, - 0x9b, 0xf3, 0xf1, 0x24, 0xbf, 0xb2, 0xf6, 0x6e, 0xc7, 0x8b, 0xc4, 0x28, 0xc6, 0x72, 0x5f, 0x75, 0xb3, 0x72, 0xa2, - 0x92, 0x03, 0x23, 0x5d, 0x93, 0xbd, 0x5c, 0xc9, 0xba, 0x9d, 0x6e, 0x25, 0x10, 0x51, 0x05, 0xde, 0x63, 0x5c, 0xc5, - 0x3e, 0x82, 0xe9, 0xba, 0xe3, 0x32, 0xda, 0xf1, 0x9e, 0xf1, 0xea, 0x44, 0x59, 0xc1, 0xed, 0x46, 0xb4, 0x27, 0x74, - 0xf4, 0xd3, 0xa4, 0xb6, 0x2c, 0x1c, 0x80, 0xdc, 0x25, 0x8c, 0x65, 0x43, 0xb0, 0x62, 0x50, 0xfa, 0x7a, 0x4d, 0xc9, - 0xb2, 0x00, 0x8b, 0xce, 0x2e, 0x23, 0x10, 0xc3, 0xba, 0x69, 0x4e, 0xe8, 0x78, 0xe9, 0xe2, 0xbc, 0xd7, 0x2a, 0x52, - 0xf0, 0x8c, 0x16, 0x1d, 0x73, 0xd3, 0x91, 0x6e, 0x8c, 0xf6, 0xf6, 0xb9, 0x41, 0x48, 0xf1, 0xfc, 0x81, 0xad, 0xd6, - 0xc5, 0x45, 0xe2, 0x15, 0x32, 0xd1, 0x82, 0x58, 0x8a, 0xc0, 0x8c, 0x17, 0x9a, 0x46, 0x98, 0xa0, 0x4c, 0x09, 0x16, - 0xad, 0xd1, 0xa1, 0xfd, 0x61, 0x09, 0xbb, 0xc7, 0x18, 0x01, 0x02, 0x55, 0xa6, 0x5f, 0xc3, 0xd6, 0x84, 0xd9, 0xd4, - 0xc5, 0x06, 0x68, 0xab, 0x18, 0x1a, 0x84, 0xb5, 0x21, 0xe6, 0x43, 0x9a, 0xdf, 0xfe, 0x0b, 0x8b, 0xb1, 0x3d, 0x81, - 0xd8, 0xde, 0xed, 0x9a, 0x84, 0xe9, 0x5e, 0x8b, 0x1b, 0xeb, 0xe5, 0xf6, 0x94, 0x63, 0x6a, 0xc7, 0xda, 0xa8, 0x1d, - 0x6b, 0xa9, 0x77, 0xac, 0xb5, 0xde, 0xb1, 0x6e, 0x1b, 0xfe, 0x2c, 0xf3, 0x62, 0x96, 0x80, 0x7e, 0x77, 0xc5, 0x55, - 0x83, 0xa0, 0x19, 0x1b, 0x76, 0x03, 0xbf, 0x25, 0xd6, 0x6e, 0xe9, 0x5f, 0x2c, 0xd9, 0xc2, 0xf4, 0x81, 0x6e, 0x1d, - 0x60, 0x19, 0x51, 0x93, 0xef, 0x90, 0x77, 0xd3, 0x59, 0x51, 0xb8, 0x3d, 0xb1, 0x85, 0xcf, 0xae, 0xcd, 0x9b, 0x77, - 0x8f, 0x23, 0xc8, 0xbd, 0xe3, 0xde, 0xdd, 0xf0, 0xda, 0xbf, 0xd0, 0x2d, 0x90, 0x93, 0x59, 0xce, 0x40, 0xea, 0x88, - 0x4f, 0x10, 0xad, 0xec, 0x29, 0xdf, 0x09, 0xb9, 0xb3, 0xad, 0x1f, 0xdf, 0xb9, 0xdb, 0xda, 0xed, 0xe3, 0x3b, 0x56, - 0x8d, 0x28, 0x56, 0x9c, 0xa6, 0x48, 0x98, 0x45, 0x1b, 0xe0, 0xa9, 0x97, 0xef, 0x77, 0xec, 0x98, 0xc3, 0xdd, 0xe3, - 0x8e, 0x8e, 0x97, 0x73, 0xc0, 0xee, 0xfe, 0xa3, 0x4d, 0xd8, 0x58, 0xe9, 0x5a, 0x85, 0x0e, 0x77, 0x8f, 0x33, 0x8d, - 0xe7, 0x70, 0x24, 0x9f, 0x8e, 0x35, 0x36, 0x08, 0xea, 0xfa, 0x9c, 0x41, 0xed, 0xd8, 0x7d, 0x4d, 0xd8, 0x65, 0xc7, - 0xbc, 0xd6, 0x35, 0x6f, 0xaf, 0x3c, 0x15, 0x1b, 0x02, 0x3a, 0x7c, 0xad, 0x6e, 0x90, 0x7f, 0x09, 0x9c, 0x22, 0x00, - 0xe4, 0x70, 0xbc, 0xe4, 0xb1, 0xef, 0xd3, 0x2c, 0xad, 0x77, 0xa8, 0xb5, 0xa8, 0x2c, 0xcb, 0xb0, 0xf6, 0x7e, 0xd0, - 0x8a, 0x61, 0xa9, 0xe9, 0x9f, 0x8e, 0x03, 0xb7, 0xb3, 0xdd, 0xca, 0xd8, 0x65, 0x3c, 0x2e, 0x2e, 0x7e, 0x3d, 0x2d, - 0x94, 0x6b, 0x37, 0x6f, 0xe3, 0x37, 0xad, 0x96, 0x2c, 0xad, 0xf5, 0x90, 0x97, 0x96, 0x45, 0x04, 0x02, 0x18, 0x8e, - 0x94, 0x5d, 0x2c, 0xe1, 0x1e, 0x61, 0x75, 0x0f, 0x42, 0xc9, 0xbc, 0x70, 0xf1, 0x84, 0xc5, 0x90, 0x08, 0xb0, 0xdd, - 0xa1, 0x62, 0x5b, 0xb8, 0x78, 0xc2, 0x36, 0xbc, 0xe8, 0xf7, 0x33, 0xd5, 0x29, 0x64, 0xdd, 0x59, 0xf2, 0x8d, 0x6a, - 0x8e, 0x35, 0xd4, 0x6c, 0x6d, 0x92, 0xad, 0x71, 0x6e, 0x2b, 0x3e, 0x6e, 0xdb, 0x8a, 0x8f, 0x95, 0xb5, 0x2e, 0xdd, - 0xeb, 0x3d, 0xaa, 0x0b, 0x60, 0xeb, 0xbf, 0x39, 0x5e, 0xb9, 0x9e, 0xcf, 0x08, 0xe0, 0x6b, 0xc1, 0xc7, 0x93, 0x05, - 0x7a, 0x95, 0x2c, 0xfc, 0x9b, 0x81, 0x1a, 0x7f, 0xa7, 0x73, 0x17, 0x00, 0x5d, 0x49, 0x79, 0x05, 0xe4, 0x1d, 0xe4, - 0x98, 0x5b, 0x76, 0xe5, 0xdd, 0xc9, 0x77, 0xd8, 0x35, 0xaf, 0x67, 0x8b, 0x39, 0xdb, 0x81, 0x53, 0x41, 0x32, 0xb0, - 0x97, 0x15, 0xdb, 0x05, 0xb1, 0x9d, 0xf0, 0x3b, 0x01, 0x53, 0x3e, 0x83, 0x20, 0xae, 0xe0, 0x06, 0xe2, 0xf0, 0xe4, - 0x9f, 0x83, 0xbb, 0xd6, 0x66, 0x7d, 0xc7, 0xac, 0xce, 0x09, 0xd6, 0xcc, 0xea, 0xc1, 0x60, 0xd9, 0x4c, 0x56, 0xfd, - 0xbe, 0xb7, 0xd3, 0x8e, 0x4f, 0xb7, 0x52, 0x27, 0x76, 0x5a, 0xab, 0xb5, 0x60, 0xd7, 0x52, 0xeb, 0x62, 0x0c, 0x3d, - 0x40, 0xfc, 0x74, 0x33, 0xe0, 0x77, 0x1d, 0x6b, 0xcb, 0xbb, 0x66, 0x0b, 0xb6, 0x83, 0x4b, 0x50, 0xd3, 0x5e, 0xf6, - 0x27, 0x95, 0x0b, 0xda, 0xb1, 0x4b, 0xe2, 0xe1, 0x8c, 0x59, 0xa5, 0xcc, 0xac, 0x93, 0xea, 0x4a, 0x74, 0xc6, 0x74, - 0xd6, 0x7a, 0x3e, 0x57, 0xf3, 0x49, 0xa1, 0x41, 0xfd, 0xce, 0x89, 0x8f, 0xa8, 0xe8, 0x3c, 0x81, 0xad, 0x65, 0x05, - 0xb1, 0xda, 0xe7, 0x60, 0xad, 0xd5, 0x2e, 0xfd, 0x5e, 0x3e, 0xe0, 0x36, 0xe5, 0xb0, 0x0e, 0x0c, 0x6a, 0x4e, 0xac, - 0xa8, 0x87, 0x6c, 0xc7, 0xb8, 0xf9, 0xe9, 0xe5, 0x0f, 0x4e, 0x58, 0xb2, 0x62, 0xb5, 0x3f, 0xfd, 0xf5, 0xb1, 0xa7, - 0xbf, 0x53, 0xfb, 0x17, 0xc2, 0x0f, 0xc6, 0xff, 0xa9, 0xdd, 0xd7, 0x5a, 0x8c, 0xca, 0x56, 0x39, 0x42, 0xe3, 0x6e, - 0x25, 0x4d, 0x96, 0x9f, 0x84, 0x27, 0xac, 0x05, 0xcf, 0x72, 0xbd, 0x44, 0xb3, 0x02, 0x56, 0x58, 0xcb, 0x24, 0x5c, - 0x61, 0xac, 0x96, 0xb6, 0xfa, 0x16, 0x4d, 0x73, 0x7c, 0x38, 0xd7, 0x06, 0x65, 0xca, 0xd9, 0x19, 0xb1, 0x1a, 0x2e, - 0xc3, 0xd2, 0x84, 0x22, 0x64, 0xf7, 0x76, 0x70, 0x63, 0xa7, 0x2c, 0xa5, 0x0c, 0xe7, 0x18, 0x4c, 0x78, 0x24, 0x46, - 0x55, 0xbe, 0xbf, 0x2f, 0x29, 0x72, 0xda, 0x96, 0x83, 0x2a, 0x84, 0x7d, 0x24, 0x51, 0x02, 0xb7, 0x22, 0x2d, 0x14, - 0x29, 0x8b, 0xbf, 0x1d, 0xa0, 0x0b, 0xbc, 0x80, 0xba, 0x1a, 0x75, 0xfb, 0xc3, 0x11, 0x0f, 0x1f, 0x98, 0xfa, 0xc0, - 0x88, 0x25, 0x81, 0xda, 0x9e, 0x65, 0xe9, 0x2d, 0xa8, 0xf0, 0x7b, 0xb8, 0x9a, 0x88, 0xfd, 0xdc, 0x92, 0xa2, 0x22, - 0x1b, 0xe9, 0x0d, 0xad, 0xc1, 0x23, 0xb4, 0xa6, 0x3c, 0x77, 0x52, 0x6d, 0xd2, 0x79, 0x47, 0xc8, 0xb1, 0xfa, 0xd6, - 0x12, 0x46, 0xbb, 0xa2, 0x17, 0xf7, 0x8e, 0xde, 0xf3, 0x74, 0xd5, 0x73, 0x7f, 0xe2, 0x8a, 0x79, 0x72, 0x1b, 0x81, - 0xba, 0x15, 0x54, 0xb7, 0x77, 0x2a, 0xc1, 0x82, 0x25, 0xed, 0x3e, 0x7e, 0x3b, 0x6b, 0x07, 0xa2, 0x32, 0x56, 0xe9, - 0x5b, 0x92, 0xb0, 0x27, 0x06, 0x9d, 0x42, 0x55, 0x6e, 0x77, 0x47, 0x5b, 0xe0, 0x3a, 0x66, 0x29, 0x7a, 0x66, 0x8b, - 0xdc, 0x2d, 0xff, 0xee, 0xb9, 0x22, 0x67, 0xbf, 0x04, 0x04, 0xa7, 0xe6, 0x1b, 0xe2, 0xcb, 0x11, 0x1e, 0x55, 0xb7, - 0xc0, 0x71, 0xfa, 0x0e, 0xe0, 0x1f, 0x0e, 0x97, 0xa0, 0x09, 0x88, 0x05, 0xeb, 0xa5, 0x71, 0x8f, 0xf5, 0xe2, 0x62, - 0x73, 0x9b, 0xe4, 0x1b, 0x70, 0x66, 0xa0, 0x54, 0x4b, 0x3f, 0x70, 0xac, 0x16, 0x50, 0xe1, 0x60, 0x76, 0x52, 0x2f, - 0x2c, 0xa3, 0x1e, 0xd3, 0xe7, 0x67, 0xb0, 0x77, 0x84, 0x04, 0xc0, 0xfd, 0xb2, 0x0f, 0x48, 0xc0, 0x43, 0x67, 0x76, - 0x40, 0x38, 0x61, 0x16, 0x55, 0x81, 0x44, 0x72, 0xa4, 0x9f, 0x3d, 0x66, 0x22, 0xf9, 0x83, 0x59, 0xcf, 0x39, 0x25, - 0x7a, 0xac, 0xa7, 0x8e, 0x90, 0x1e, 0xeb, 0x59, 0x47, 0x44, 0x8f, 0xf5, 0xac, 0xe3, 0xa3, 0xc7, 0x7a, 0xe6, 0xd8, - 0xe9, 0x41, 0x60, 0x02, 0x44, 0x1e, 0xb0, 0x1e, 0x4d, 0xa6, 0x9e, 0xe2, 0x1e, 0x20, 0x1a, 0x04, 0xd6, 0x93, 0xc2, - 0x79, 0x0f, 0x90, 0xc7, 0x48, 0xac, 0x0e, 0x7a, 0x7f, 0x19, 0xff, 0xd0, 0x33, 0x32, 0xf2, 0xb8, 0x75, 0x58, 0xfd, - 0xaf, 0xbf, 0x42, 0x00, 0x1c, 0x9e, 0x4d, 0xbd, 0xcb, 0x31, 0x64, 0x95, 0x65, 0x04, 0x92, 0x9f, 0x18, 0x7c, 0xf9, - 0x02, 0xa0, 0xea, 0x33, 0x5d, 0xab, 0xc9, 0x51, 0x7b, 0xcc, 0xa1, 0x2b, 0x06, 0x80, 0x6d, 0x58, 0xa2, 0xaa, 0x16, - 0x36, 0x61, 0x71, 0xfb, 0x19, 0x46, 0x73, 0xd9, 0xf4, 0x82, 0x06, 0xea, 0x11, 0x82, 0x5f, 0x5a, 0x0f, 0xad, 0xb5, - 0x4c, 0x39, 0x74, 0x6d, 0x14, 0x55, 0x36, 0xd4, 0x25, 0xac, 0xd6, 0x22, 0xaa, 0x89, 0x22, 0xe5, 0x92, 0x51, 0x14, - 0x4b, 0x15, 0xec, 0x33, 0x71, 0x0b, 0x51, 0xf3, 0xb4, 0xd5, 0x56, 0xc1, 0xfe, 0x16, 0x10, 0xd6, 0xc2, 0x5a, 0x48, - 0x67, 0x50, 0x7b, 0xa7, 0x1f, 0x29, 0x7f, 0x79, 0x21, 0xb7, 0x73, 0x0b, 0x45, 0xb8, 0x3d, 0x07, 0xe5, 0x4d, 0x5d, - 0x95, 0x8a, 0x68, 0xb4, 0x04, 0x4a, 0x99, 0x13, 0x44, 0x16, 0x20, 0x80, 0xe3, 0x06, 0x02, 0x9f, 0xd7, 0xf8, 0x04, - 0x1a, 0x85, 0x40, 0x7e, 0x60, 0x15, 0xae, 0x3d, 0xa4, 0xa5, 0xd6, 0x88, 0x28, 0x11, 0x3f, 0xba, 0x7a, 0x8e, 0xed, - 0xab, 0xa7, 0xb1, 0xb6, 0x94, 0x26, 0x88, 0x9f, 0x58, 0x6c, 0x21, 0x26, 0x88, 0xea, 0x10, 0x1d, 0xc1, 0x72, 0x42, - 0x88, 0xc2, 0x9f, 0x42, 0x3f, 0x35, 0xf0, 0x97, 0x6c, 0x59, 0xe4, 0x35, 0xc1, 0x62, 0x56, 0x0c, 0xd0, 0xaa, 0x08, - 0x3c, 0xd3, 0xd9, 0x52, 0x99, 0xd3, 0x3c, 0x3a, 0xb2, 0x83, 0xf3, 0xae, 0x83, 0xbd, 0xf4, 0x65, 0xec, 0x64, 0xd9, - 0x34, 0x6a, 0x63, 0x43, 0x24, 0xbc, 0x22, 0xbf, 0xce, 0x52, 0xe3, 0x1c, 0x99, 0xcb, 0xf5, 0x5d, 0x17, 0xb7, 0xb7, - 0xb4, 0x4d, 0x58, 0x85, 0x08, 0x75, 0xdb, 0x50, 0xb9, 0x14, 0x66, 0x63, 0xd3, 0x34, 0xc0, 0x17, 0x8a, 0x4a, 0xa5, - 0x2a, 0xb5, 0x95, 0x4a, 0x4e, 0x78, 0xd7, 0x37, 0xb5, 0x48, 0x5d, 0x11, 0x6c, 0x63, 0x86, 0x7a, 0x28, 0x37, 0x6a, - 0xec, 0xdb, 0x8e, 0x55, 0x7a, 0x87, 0x09, 0x72, 0x46, 0x5e, 0xe4, 0xe0, 0xa2, 0xa4, 0x20, 0x73, 0x35, 0x84, 0xf9, - 0x83, 0x86, 0x4f, 0x0b, 0xcb, 0x3d, 0x94, 0x80, 0xd9, 0x51, 0xc3, 0xa3, 0x08, 0x81, 0x88, 0x4b, 0x65, 0x5f, 0x31, - 0xf1, 0x7b, 0x0a, 0x66, 0xc9, 0x84, 0xee, 0x45, 0x2c, 0x8b, 0xd0, 0xc6, 0x27, 0x49, 0x32, 0xf5, 0x34, 0x05, 0x37, - 0x72, 0x19, 0xe6, 0x68, 0x84, 0x96, 0x7c, 0xe4, 0x40, 0xfa, 0x5a, 0x4e, 0x25, 0xf8, 0x88, 0x3a, 0x05, 0x1c, 0xcf, - 0xcf, 0x0b, 0xeb, 0x27, 0xcb, 0x25, 0xe6, 0xb2, 0x36, 0xff, 0x65, 0x47, 0xc7, 0x60, 0x97, 0xa7, 0x89, 0xe3, 0xea, - 0x3f, 0xaa, 0x92, 0xe2, 0xfe, 0x75, 0x9a, 0x03, 0x8a, 0x60, 0x66, 0x4f, 0x31, 0x3e, 0xf6, 0x59, 0xa6, 0x80, 0xbf, - 0x5d, 0x6f, 0x2d, 0x99, 0xd8, 0x25, 0xed, 0xe6, 0xca, 0xf8, 0xa5, 0x36, 0xec, 0x38, 0x38, 0x37, 0x00, 0xc5, 0x59, - 0xa3, 0xc3, 0xf2, 0x5a, 0xb7, 0xad, 0x0a, 0x15, 0xa8, 0xf5, 0x7f, 0x76, 0x0b, 0x53, 0xde, 0xe6, 0xa5, 0xf2, 0x36, - 0x0f, 0x4d, 0x80, 0x40, 0x64, 0x86, 0x3c, 0x6b, 0x3a, 0x26, 0x89, 0x7b, 0x47, 0x4a, 0xda, 0x77, 0xa4, 0xf8, 0xc1, - 0x3b, 0x12, 0xf2, 0x2d, 0xa1, 0x23, 0xfb, 0x92, 0x93, 0x13, 0x28, 0x33, 0xd8, 0xcb, 0x6b, 0x26, 0xfb, 0x07, 0xb4, - 0x17, 0xce, 0x65, 0x79, 0xc5, 0xdf, 0x08, 0x6f, 0xed, 0x4f, 0xd7, 0xa7, 0x5d, 0x55, 0x6f, 0xbe, 0x31, 0x33, 0x0f, - 0x87, 0xe2, 0x70, 0xa8, 0x4c, 0xd0, 0xee, 0x82, 0x8b, 0x41, 0xce, 0xee, 0xdc, 0xf8, 0xf8, 0x6b, 0x8e, 0x22, 0xb6, - 0x52, 0x1e, 0x49, 0x17, 0x2a, 0x31, 0xbc, 0x34, 0xf0, 0x30, 0x3b, 0x3e, 0x9e, 0xec, 0xae, 0xee, 0x26, 0x83, 0xc1, - 0x4e, 0xf5, 0xed, 0x96, 0xd7, 0xb3, 0xdd, 0x9c, 0xdd, 0xf3, 0x9b, 0xe9, 0x36, 0xd8, 0x37, 0xb0, 0xed, 0xee, 0xae, - 0xc4, 0xe1, 0xb0, 0x7b, 0xca, 0x17, 0xfe, 0xfe, 0x1e, 0x01, 0x9d, 0xf9, 0xf9, 0xb8, 0x8d, 0xf1, 0xf3, 0xa6, 0xed, - 0xaa, 0xb5, 0x03, 0x78, 0xfa, 0x57, 0xde, 0x9b, 0xd9, 0x72, 0xee, 0xb3, 0xf7, 0xfc, 0x1e, 0xfc, 0xf3, 0x71, 0x93, - 0x44, 0xea, 0x13, 0xed, 0x32, 0xf9, 0x06, 0x1c, 0xc8, 0x77, 0x3e, 0xfb, 0xc4, 0xef, 0x67, 0xcb, 0x39, 0x2f, 0x0e, - 0x87, 0x47, 0xd3, 0x10, 0xc9, 0x9a, 0xc2, 0x8a, 0x58, 0x52, 0x3c, 0x3f, 0x08, 0x8f, 0xdf, 0x8b, 0xc8, 0x10, 0x69, - 0xb9, 0x77, 0x87, 0xec, 0x0d, 0x8b, 0xfc, 0x00, 0x3e, 0xc8, 0x76, 0xfe, 0x44, 0xd6, 0x94, 0xee, 0x17, 0xef, 0xfd, - 0xc3, 0x81, 0xfe, 0xfa, 0xe4, 0x1f, 0x0e, 0x8f, 0xd8, 0x3d, 0x82, 0xa3, 0xf3, 0x1d, 0xf4, 0x8f, 0xbe, 0x75, 0x40, - 0x55, 0x86, 0xd7, 0xb3, 0xcd, 0xdc, 0x7f, 0xba, 0x62, 0xb7, 0xc0, 0x85, 0xa2, 0xbc, 0xd0, 0xde, 0xb0, 0x7b, 0xf4, - 0x3a, 0x23, 0x27, 0xa2, 0xd9, 0x6e, 0xee, 0xb3, 0x18, 0x9f, 0xab, 0xfb, 0x62, 0xf2, 0xcd, 0xfb, 0xe2, 0x8e, 0x6d, - 0xbb, 0xef, 0x8b, 0xf2, 0x4d, 0x77, 0xfd, 0x6c, 0xd9, 0x8e, 0xdd, 0xc3, 0x0c, 0xbb, 0xe6, 0x6f, 0x9a, 0x63, 0xc7, - 0xd8, 0x6f, 0xde, 0x18, 0x01, 0x94, 0xd9, 0x82, 0xc5, 0x82, 0x83, 0x52, 0xad, 0xda, 0x96, 0x44, 0x5e, 0xe9, 0x40, - 0xb5, 0x19, 0xc1, 0x7d, 0xb5, 0x90, 0x33, 0xcf, 0x0c, 0xf4, 0x6d, 0x85, 0x68, 0xe1, 0xb0, 0x01, 0x7f, 0xa3, 0xad, - 0x63, 0x0c, 0xd3, 0xac, 0x66, 0xda, 0x16, 0x75, 0xf9, 0x7d, 0xef, 0x99, 0xfc, 0x46, 0x06, 0xb6, 0x10, 0x49, 0xe1, - 0x38, 0xbe, 0x78, 0x72, 0xc2, 0x7f, 0xd5, 0xf2, 0xa8, 0xd5, 0x7e, 0xa1, 0xd4, 0xa7, 0xd7, 0x74, 0x44, 0x13, 0xf7, - 0xa2, 0x2d, 0xc3, 0x1a, 0x65, 0x4d, 0x2d, 0x1d, 0x86, 0x71, 0x0d, 0xfb, 0xf2, 0xc0, 0xa1, 0xef, 0x80, 0x40, 0x5b, - 0xa5, 0x52, 0xa0, 0x85, 0x63, 0x18, 0x85, 0x59, 0x48, 0x79, 0x58, 0x98, 0xa5, 0xbc, 0xc7, 0x02, 0x2d, 0x6e, 0xd5, - 0x3d, 0xa6, 0xb6, 0x5b, 0x10, 0x61, 0xf5, 0x96, 0x71, 0x7e, 0xd9, 0xa8, 0xc2, 0x6d, 0x01, 0x8a, 0x22, 0x28, 0x83, - 0x3d, 0xc9, 0x6d, 0x0b, 0x25, 0xcd, 0x46, 0x61, 0x2d, 0x6e, 0x8b, 0x72, 0xd7, 0x6b, 0xd8, 0x02, 0x2f, 0xa8, 0xfa, - 0x09, 0x61, 0x5b, 0xf6, 0xac, 0x43, 0xb9, 0x48, 0xff, 0x23, 0x4b, 0xcf, 0xf7, 0x5b, 0x73, 0xfe, 0xa7, 0xaf, 0xe8, - 0xa3, 0xf2, 0x3f, 0xbf, 0xa4, 0x9f, 0x0c, 0x96, 0x91, 0x53, 0xea, 0x97, 0x68, 0x74, 0x93, 0xe6, 0x84, 0xb1, 0xe5, - 0xeb, 0xa7, 0xdf, 0x21, 0x53, 0x90, 0x1c, 0x4a, 0xa9, 0xca, 0xc9, 0x1e, 0xfa, 0xc2, 0xeb, 0x3e, 0xcc, 0x04, 0x03, - 0x10, 0x5e, 0xa3, 0x4d, 0x35, 0x61, 0x12, 0x0f, 0xae, 0xe0, 0xff, 0x46, 0x10, 0x83, 0xf6, 0x89, 0xa2, 0x8e, 0x6d, - 0x23, 0x5d, 0xb7, 0x9d, 0x83, 0xe4, 0x4e, 0x5d, 0xf9, 0xa3, 0x72, 0xf2, 0x9f, 0x68, 0x88, 0xbc, 0xe2, 0x0a, 0xb1, - 0xb2, 0xe0, 0x12, 0x8b, 0xa1, 0x22, 0x05, 0xb8, 0x86, 0x20, 0x52, 0x16, 0x25, 0x85, 0x5b, 0x0e, 0xaa, 0x22, 0x00, - 0xe3, 0x6a, 0x75, 0xd4, 0x89, 0xf0, 0x71, 0x6b, 0x2d, 0x42, 0xb0, 0xa2, 0x51, 0x2b, 0x6b, 0x05, 0xbe, 0x20, 0x7d, - 0xe9, 0x50, 0x10, 0xd3, 0xa3, 0x90, 0xaa, 0xd2, 0xa1, 0x40, 0x9a, 0x43, 0xc5, 0x37, 0x06, 0x1b, 0x45, 0x45, 0x7a, - 0xfe, 0xd2, 0xa4, 0xe4, 0xd2, 0x98, 0xf1, 0x5e, 0x94, 0x91, 0xc8, 0xeb, 0xf0, 0x56, 0x4c, 0x0b, 0xe4, 0x1b, 0x3d, - 0x7e, 0x10, 0x5c, 0xc2, 0xbb, 0x21, 0xf7, 0x0a, 0xb0, 0x25, 0x60, 0x07, 0xb8, 0x57, 0x66, 0x94, 0xeb, 0xb4, 0xae, - 0xdf, 0x5a, 0x0f, 0xc5, 0x30, 0x7c, 0x6c, 0x09, 0x6c, 0x47, 0xeb, 0xe8, 0x48, 0x0f, 0x1f, 0xfe, 0xd7, 0x55, 0xcd, - 0x51, 0xa7, 0x72, 0x39, 0x3b, 0x9e, 0xb0, 0x14, 0x31, 0x83, 0xee, 0xaf, 0xdb, 0x6b, 0x01, 0x74, 0xbb, 0x2c, 0xe6, - 0xd9, 0x68, 0x27, 0xff, 0x96, 0x6e, 0xac, 0x28, 0x6d, 0xe2, 0x5d, 0xd6, 0x1b, 0xfb, 0xc3, 0xd1, 0x5f, 0x1e, 0xbf, - 0x9d, 0x10, 0xaa, 0xce, 0x86, 0xad, 0x75, 0x9c, 0xcb, 0xff, 0xfa, 0xeb, 0x98, 0xac, 0x20, 0x28, 0x08, 0xcb, 0x4e, - 0x31, 0x51, 0xc1, 0x28, 0x52, 0xac, 0xf9, 0x78, 0xb2, 0x46, 0x9d, 0xf0, 0xda, 0x5f, 0x6a, 0x9d, 0x30, 0x31, 0xb2, - 0x52, 0xf9, 0x6b, 0x56, 0xb1, 0x5b, 0x95, 0x59, 0x40, 0xe6, 0x41, 0x3e, 0x59, 0x1b, 0x0d, 0xe6, 0x8a, 0xd7, 0xb3, - 0xf5, 0x5c, 0x2a, 0x9f, 0xc1, 0x94, 0xb3, 0x1c, 0x9c, 0x2c, 0x85, 0xdd, 0x91, 0x40, 0xd1, 0x9a, 0xa1, 0x6b, 0x7f, - 0x8a, 0xad, 0x7a, 0x91, 0x56, 0x35, 0xc0, 0x03, 0x42, 0x0c, 0x0c, 0xb5, 0x57, 0x0b, 0x0f, 0xad, 0x05, 0xb0, 0xf6, - 0x47, 0xa5, 0x1f, 0x8c, 0x27, 0x4b, 0xbe, 0x40, 0xfe, 0xe5, 0xc8, 0x51, 0xbb, 0xf7, 0xfb, 0xde, 0x1d, 0x48, 0xc1, - 0x91, 0x6b, 0xa1, 0x40, 0x22, 0xa0, 0x05, 0xdf, 0xf8, 0xca, 0x07, 0xe3, 0x1a, 0xb5, 0xd5, 0xa0, 0xa0, 0x76, 0x74, - 0xcb, 0x63, 0x47, 0xef, 0x7c, 0x77, 0x42, 0x5f, 0xbd, 0xd0, 0xc2, 0xf1, 0x37, 0xce, 0xc8, 0x35, 0x5b, 0x75, 0xc8, - 0x11, 0xcd, 0xa4, 0x43, 0x88, 0x58, 0xb1, 0x35, 0xbb, 0x26, 0x95, 0x73, 0xe7, 0x90, 0x9d, 0x3e, 0x42, 0x95, 0x5e, - 0xeb, 0xe1, 0xed, 0x44, 0xe9, 0x6e, 0x8f, 0x77, 0x93, 0xef, 0xd9, 0x44, 0xc4, 0x60, 0x40, 0x1b, 0x84, 0x33, 0xb2, - 0x0e, 0x91, 0x4a, 0x07, 0x08, 0x81, 0x63, 0x02, 0x9a, 0xfe, 0xfb, 0x5b, 0x12, 0x05, 0x1c, 0x69, 0x23, 0x64, 0x2d, - 0x3b, 0x1c, 0x72, 0xd0, 0x28, 0x37, 0x7f, 0x7a, 0x85, 0x3a, 0xcd, 0x81, 0x79, 0xba, 0x84, 0x3d, 0x07, 0x8f, 0xf4, - 0xe2, 0xf8, 0x48, 0xff, 0xef, 0x68, 0xa2, 0xc6, 0xff, 0xb9, 0x26, 0x4a, 0x69, 0x91, 0x1c, 0xd5, 0xd2, 0x77, 0xa9, - 0xa3, 0xe0, 0x22, 0xef, 0xa8, 0x85, 0xec, 0x59, 0x36, 0x6e, 0x54, 0xf3, 0xfe, 0x7f, 0xad, 0xcc, 0xff, 0xd7, 0xb4, - 0x32, 0x4c, 0xc9, 0x8e, 0xa5, 0x9a, 0x79, 0xa0, 0x55, 0x0c, 0xb3, 0xd7, 0x24, 0x21, 0x32, 0x5c, 0x1a, 0xf0, 0xa3, - 0x0a, 0xf6, 0x71, 0x5a, 0xad, 0xb3, 0x70, 0x87, 0x4a, 0xd4, 0x1b, 0x71, 0x9b, 0xe6, 0xcf, 0xea, 0x7f, 0x8b, 0xb2, - 0x80, 0xa9, 0x7d, 0x5b, 0xa6, 0x71, 0x40, 0x16, 0xfe, 0x2c, 0x2c, 0x71, 0x72, 0x63, 0x1b, 0x5f, 0xcb, 0xf1, 0xb4, - 0x5f, 0x75, 0x66, 0x1e, 0x48, 0xa0, 0x06, 0x96, 0x92, 0x9c, 0xcb, 0xca, 0xe2, 0x1e, 0xa1, 0x9b, 0x7f, 0x2a, 0xcb, - 0xa2, 0xf4, 0x7a, 0x9f, 0x92, 0xb4, 0x3a, 0x5b, 0x89, 0x3a, 0x29, 0x62, 0x05, 0x65, 0x93, 0x02, 0x8c, 0x3e, 0xac, - 0x3c, 0x11, 0x07, 0x67, 0x08, 0xd4, 0x70, 0x56, 0x27, 0x21, 0x00, 0x0d, 0x2b, 0x84, 0xfd, 0x33, 0x68, 0xe1, 0x59, - 0x18, 0x87, 0x6b, 0x80, 0xc9, 0x49, 0xab, 0xb3, 0x75, 0x59, 0xdc, 0xa5, 0xb1, 0x88, 0x47, 0x3d, 0x45, 0xc9, 0xf2, - 0x36, 0x77, 0xe5, 0x5c, 0x7f, 0xff, 0x27, 0x05, 0xb0, 0x1b, 0x30, 0xdb, 0x16, 0xd8, 0x01, 0x40, 0x82, 0x02, 0xd9, - 0x42, 0x9d, 0x46, 0x67, 0x6a, 0xa9, 0xc0, 0x7b, 0xae, 0x07, 0xf8, 0xdb, 0x1c, 0xb0, 0x8c, 0xeb, 0x42, 0x06, 0x8c, - 0x20, 0x80, 0x11, 0x38, 0x28, 0x01, 0x43, 0x67, 0x88, 0xdb, 0xaa, 0x9c, 0xb5, 0xd0, 0x5c, 0xe9, 0xb6, 0xe4, 0xa6, - 0x51, 0xce, 0x56, 0x22, 0x80, 0xbe, 0xba, 0x29, 0x71, 0xba, 0x5c, 0xb6, 0x92, 0xb0, 0x6f, 0xdf, 0xb5, 0x53, 0x45, - 0x1e, 0x1f, 0xa5, 0x21, 0xaf, 0xc0, 0x4f, 0x19, 0x47, 0x92, 0x28, 0x11, 0xbc, 0xcd, 0x1b, 0x33, 0x0e, 0xaf, 0xda, - 0x94, 0x53, 0x7b, 0xb3, 0x5e, 0x00, 0xce, 0x13, 0xb4, 0x65, 0x80, 0xb1, 0x80, 0xc1, 0xb9, 0x10, 0x4b, 0x9e, 0x22, - 0xf8, 0xa5, 0x13, 0x29, 0x8c, 0xbb, 0x1c, 0x86, 0x79, 0x50, 0xf4, 0x2e, 0xa9, 0x3f, 0xfa, 0x7d, 0xd4, 0x26, 0x83, - 0x21, 0xa8, 0x04, 0x50, 0x59, 0x37, 0x48, 0x0c, 0xac, 0x4a, 0x0b, 0x89, 0x4b, 0x88, 0x97, 0xf9, 0x6a, 0x9a, 0x46, - 0xc1, 0xa3, 0x7a, 0x42, 0x08, 0x27, 0x18, 0x1f, 0xe2, 0x06, 0x08, 0x18, 0xac, 0xe2, 0x02, 0x83, 0xe4, 0xb9, 0x44, - 0xf7, 0xc7, 0xf3, 0x1d, 0x03, 0x5c, 0x39, 0xef, 0xa9, 0x76, 0xf5, 0xc0, 0x5e, 0xae, 0xd2, 0x25, 0x23, 0x84, 0x15, - 0xff, 0x17, 0x91, 0xf7, 0xed, 0x30, 0x01, 0xb5, 0x8d, 0xfc, 0x31, 0x48, 0xcc, 0x65, 0xa2, 0x08, 0xe2, 0x51, 0x56, - 0xb0, 0x24, 0x0d, 0x36, 0xa3, 0x24, 0x05, 0x8d, 0x26, 0xc6, 0x90, 0xa9, 0xd0, 0x0e, 0x49, 0xa3, 0xd9, 0x98, 0xec, - 0x63, 0xc8, 0x6b, 0xb8, 0x58, 0x2c, 0xf0, 0xbe, 0xd7, 0x42, 0x75, 0xb0, 0x2d, 0xcd, 0x21, 0xe0, 0x24, 0xc1, 0x9e, - 0xba, 0x22, 0x25, 0x61, 0x36, 0xfa, 0x14, 0x72, 0x6e, 0x40, 0xc7, 0x49, 0x63, 0xa8, 0x3e, 0x30, 0x09, 0xaf, 0x22, - 0x74, 0x52, 0x56, 0x08, 0x0b, 0xb8, 0x6f, 0x64, 0x34, 0x5a, 0x49, 0x83, 0xc0, 0xdb, 0x0c, 0x5b, 0x81, 0x4d, 0x68, - 0xf8, 0xab, 0xcc, 0xc3, 0xb4, 0x9a, 0x95, 0x60, 0xce, 0x37, 0x50, 0x89, 0xf1, 0x64, 0x79, 0xc5, 0x37, 0x2e, 0x56, - 0x62, 0x32, 0x5b, 0xce, 0x27, 0x6b, 0x49, 0x35, 0x97, 0x7b, 0x6b, 0x96, 0xb1, 0x25, 0xec, 0x1f, 0x06, 0xf9, 0xd1, - 0x81, 0x1d, 0x4d, 0x35, 0x6d, 0x12, 0x60, 0x32, 0x9d, 0x73, 0x3e, 0xbc, 0x44, 0x34, 0x59, 0x9d, 0xba, 0x93, 0xa9, - 0x6a, 0x07, 0xd7, 0xe4, 0x4c, 0x4e, 0x8f, 0xd4, 0x53, 0xad, 0x7b, 0xc9, 0x47, 0xdb, 0x61, 0x35, 0xda, 0xfa, 0x01, - 0xb8, 0x75, 0x0a, 0x3b, 0x7d, 0x37, 0xac, 0x46, 0x3b, 0x5f, 0xc3, 0xee, 0x92, 0x42, 0xa0, 0xfa, 0x52, 0xd6, 0x64, - 0x2e, 0x5e, 0x17, 0xf7, 0x5e, 0xc1, 0x9e, 0xf8, 0x03, 0xfd, 0xab, 0x64, 0x4f, 0x7c, 0x9b, 0xc9, 0xf5, 0xb7, 0xb4, - 0x6b, 0x34, 0x66, 0x3a, 0x5e, 0xbb, 0x02, 0x2b, 0x34, 0x40, 0x7e, 0xc1, 0x8e, 0xf6, 0x2a, 0x07, 0x81, 0x00, 0xdd, - 0x4b, 0x70, 0x14, 0x05, 0x44, 0x4d, 0xab, 0xca, 0xa3, 0xd3, 0xbd, 0xbf, 0xc7, 0x37, 0x42, 0xc0, 0x26, 0x4f, 0xad, - 0x7b, 0xcb, 0xd8, 0x3f, 0x1c, 0x20, 0x84, 0x5e, 0x4e, 0xbf, 0xd1, 0x96, 0xd5, 0xa3, 0x1d, 0xcb, 0x7d, 0xc3, 0xa8, - 0xa7, 0x60, 0x0c, 0x43, 0x17, 0x56, 0x31, 0x92, 0x67, 0x40, 0xd6, 0xf8, 0x0d, 0xa2, 0x0b, 0x58, 0xf4, 0x7a, 0x9f, - 0x8e, 0x68, 0x10, 0x01, 0x95, 0x5e, 0x73, 0xd4, 0x22, 0x9f, 0xab, 0x42, 0xf4, 0xde, 0x5b, 0x3b, 0x6f, 0x66, 0x24, - 0xcb, 0xa4, 0x91, 0x6a, 0xb7, 0xb2, 0x58, 0x57, 0xde, 0xec, 0x84, 0x74, 0x31, 0xc7, 0x50, 0x19, 0x3c, 0x0e, 0x40, - 0xe9, 0xf9, 0xef, 0xd0, 0x2b, 0x19, 0x32, 0xcd, 0x12, 0xcd, 0xec, 0xae, 0xf1, 0x27, 0xab, 0xd4, 0x8b, 0x11, 0x31, - 0x1b, 0xd8, 0x42, 0xdc, 0x16, 0x95, 0x6e, 0x8b, 0x42, 0xd9, 0xa2, 0x48, 0x1f, 0x6a, 0x67, 0xba, 0x33, 0x0b, 0x9f, - 0x55, 0xd6, 0x4a, 0xc9, 0xcc, 0xd8, 0x00, 0x6d, 0x17, 0xe1, 0x1b, 0xe8, 0x40, 0x85, 0x90, 0xbf, 0x40, 0x44, 0x24, - 0x02, 0x76, 0x39, 0x75, 0x27, 0x36, 0x1d, 0x92, 0x79, 0x88, 0x59, 0xa1, 0x46, 0x79, 0xc9, 0x93, 0xa3, 0x01, 0xa9, - 0x08, 0x75, 0xbb, 0xdf, 0x3f, 0x5f, 0xba, 0xa0, 0xf6, 0x6b, 0x8a, 0x1d, 0xa3, 0x9b, 0x02, 0xce, 0x05, 0x8f, 0xf2, - 0x9e, 0x7b, 0xe7, 0x80, 0xe6, 0xd8, 0x9e, 0x22, 0x6b, 0xc0, 0xe9, 0x6d, 0x17, 0x02, 0x6c, 0x9f, 0x35, 0x5b, 0xfb, - 0x93, 0xd5, 0x55, 0x34, 0xf5, 0x4a, 0x3e, 0xd3, 0x5d, 0x94, 0xb8, 0x5d, 0x14, 0xcb, 0x2e, 0xda, 0x34, 0x10, 0xec, - 0xb8, 0xf2, 0x03, 0xe0, 0x0d, 0x8d, 0xfa, 0xfd, 0xb2, 0xd5, 0xb3, 0x27, 0x5f, 0x3b, 0xee, 0xd9, 0xcc, 0x67, 0xa5, - 0xe9, 0xd9, 0x7f, 0xa4, 0x6e, 0xcf, 0xca, 0xc9, 0x5e, 0x74, 0x4e, 0xf6, 0xe9, 0x6c, 0x1e, 0x08, 0x2e, 0x77, 0xee, - 0xf3, 0x7c, 0xaa, 0xa7, 0x5d, 0xe5, 0x07, 0xad, 0x21, 0xb2, 0xc6, 0xae, 0xea, 0x5e, 0x57, 0xb0, 0x80, 0x25, 0xb8, - 0x5b, 0x2f, 0xcd, 0x7f, 0xc3, 0xee, 0xef, 0x05, 0xbd, 0x34, 0xff, 0x9d, 0xfe, 0xa4, 0x00, 0x0e, 0x40, 0x63, 0x6a, - 0xb7, 0xc0, 0x43, 0x0c, 0x15, 0x14, 0xee, 0x66, 0xe5, 0xdc, 0xab, 0x01, 0x0e, 0x93, 0xf4, 0x0d, 0xad, 0x5e, 0x69, - 0xb1, 0xeb, 0x65, 0xb2, 0x57, 0x80, 0x87, 0x2a, 0xe4, 0xe1, 0xe1, 0x10, 0x75, 0x0c, 0x3b, 0xa8, 0x23, 0x60, 0xd8, - 0x43, 0x68, 0x6c, 0x81, 0xe7, 0xe3, 0x87, 0x8c, 0xef, 0x05, 0xa8, 0x8d, 0x10, 0x1e, 0xaf, 0x16, 0x65, 0x88, 0x2d, - 0x7b, 0x85, 0x54, 0x52, 0xaf, 0x05, 0xa2, 0x8c, 0x56, 0x01, 0x6d, 0xb5, 0xc7, 0x2c, 0x8d, 0x1f, 0x21, 0x54, 0x2c, - 0xf5, 0x31, 0x84, 0x06, 0x0e, 0xbf, 0xc3, 0x01, 0x24, 0xf8, 0x92, 0x6b, 0xb2, 0xb9, 0x57, 0xf9, 0x1d, 0xed, 0xf3, - 0x87, 0xc3, 0xf9, 0x25, 0x82, 0xd2, 0xa5, 0xf0, 0x91, 0x4a, 0x44, 0xf5, 0x14, 0x37, 0x25, 0x64, 0xb3, 0x64, 0xa5, - 0x1f, 0xfc, 0x43, 0xfd, 0x02, 0x00, 0x59, 0x08, 0xb4, 0x89, 0xcc, 0xfe, 0x74, 0xa6, 0xa2, 0x0b, 0x80, 0x43, 0xfc, - 0xe1, 0x13, 0x44, 0xdf, 0xd0, 0x32, 0x2d, 0x1f, 0x27, 0x3c, 0x04, 0xad, 0x2d, 0xe9, 0x24, 0x62, 0xa5, 0xc0, 0x86, - 0x48, 0xf8, 0x7e, 0xff, 0x3c, 0x96, 0x74, 0xa0, 0x51, 0xab, 0x7b, 0xe3, 0x56, 0xf7, 0xca, 0xd7, 0x75, 0x27, 0x37, - 0x3e, 0x28, 0xda, 0x67, 0xf3, 0x46, 0xe5, 0xfb, 0xbe, 0xce, 0xd9, 0x9d, 0xee, 0x1d, 0x39, 0x27, 0xbe, 0xbf, 0x87, - 0x50, 0xf4, 0xd0, 0x14, 0x59, 0x96, 0x84, 0x01, 0xad, 0xb5, 0x6b, 0xcf, 0x32, 0x3a, 0x78, 0xed, 0x1b, 0x42, 0x44, - 0x9e, 0xe2, 0x93, 0x90, 0x5b, 0x1c, 0x1f, 0x14, 0xe8, 0x9f, 0x19, 0x7f, 0xe6, 0xc4, 0x0f, 0x5b, 0xfd, 0x02, 0x38, - 0x37, 0xdd, 0x7b, 0x77, 0x62, 0xd6, 0x63, 0x28, 0x65, 0xe3, 0xff, 0x7e, 0x9f, 0xc8, 0x02, 0x9d, 0x8e, 0x68, 0x18, - 0x08, 0xee, 0xa2, 0xfa, 0xbf, 0x57, 0xbc, 0xee, 0x59, 0xab, 0xf3, 0xe5, 0xa7, 0x4e, 0x4f, 0x7a, 0xbd, 0x74, 0x2b, - 0x7c, 0x19, 0x26, 0xbe, 0xf3, 0xba, 0xdf, 0xb0, 0xdd, 0x77, 0xbf, 0xbc, 0x3b, 0x7a, 0x19, 0xd8, 0xa4, 0xf0, 0x9d, - 0x4d, 0xc9, 0x67, 0x3d, 0x50, 0xf8, 0xf5, 0x58, 0xaf, 0x2e, 0xd6, 0x3d, 0xd6, 0x43, 0x2d, 0x20, 0x7a, 0x58, 0x80, - 0xfa, 0xaf, 0x67, 0x9f, 0x86, 0xc2, 0x41, 0x36, 0x4e, 0x15, 0x28, 0xb2, 0xe0, 0x4f, 0xc5, 0x68, 0x5d, 0x10, 0x20, - 0xb2, 0xd9, 0xbe, 0x3e, 0x54, 0x27, 0xb3, 0x6f, 0x4a, 0x2d, 0xc9, 0xe0, 0x9b, 0x80, 0xcc, 0x0e, 0xac, 0x9c, 0xa0, - 0x74, 0xdc, 0x1a, 0x70, 0x65, 0x8b, 0xbd, 0xbd, 0xfd, 0x69, 0x90, 0x9d, 0x35, 0x27, 0x8d, 0xf6, 0x61, 0x9f, 0xe6, - 0x01, 0x02, 0x91, 0x4c, 0x45, 0x90, 0x6b, 0xee, 0x2d, 0xe9, 0xa3, 0xc3, 0x39, 0x2f, 0xe4, 0x9f, 0x53, 0xa9, 0x43, - 0x1c, 0x4a, 0xac, 0x81, 0x40, 0xe5, 0x19, 0xaa, 0x1c, 0x36, 0xc8, 0xf1, 0x4b, 0x47, 0x32, 0x93, 0x98, 0x2c, 0x72, - 0xb7, 0x66, 0x2a, 0xfc, 0x40, 0xf0, 0x31, 0xcb, 0x39, 0x70, 0x81, 0xcd, 0xe6, 0xbe, 0x9a, 0xe2, 0xe2, 0x0a, 0xfc, - 0x31, 0x85, 0x5f, 0xf1, 0x14, 0x76, 0xda, 0xfd, 0xba, 0xa8, 0x52, 0xd4, 0x6d, 0x14, 0x16, 0x95, 0x2c, 0x98, 0xd6, - 0x90, 0x26, 0x3a, 0x8c, 0xfe, 0x24, 0x67, 0xa0, 0x20, 0xe4, 0x97, 0x4d, 0x03, 0x8c, 0x54, 0x72, 0x79, 0x50, 0x25, - 0x81, 0x17, 0x60, 0x1b, 0x54, 0x6c, 0x5d, 0x40, 0x90, 0x6d, 0x52, 0x94, 0xe9, 0xd7, 0x22, 0xaf, 0xc3, 0x2c, 0xa8, - 0x46, 0x69, 0xf5, 0xb3, 0xfe, 0x09, 0xcc, 0xdb, 0x54, 0x8c, 0x6a, 0x15, 0x93, 0xdf, 0xe8, 0xf7, 0x8b, 0x41, 0xeb, - 0x43, 0x06, 0x1f, 0xbd, 0x36, 0x0d, 0x7e, 0xeb, 0x34, 0xd8, 0x61, 0xa2, 0x11, 0x00, 0xc9, 0x9c, 0x5a, 0xf2, 0x50, - 0xf4, 0x67, 0x90, 0x63, 0x8d, 0x2a, 0xa7, 0x60, 0xb0, 0xfe, 0xe3, 0xd1, 0x0e, 0x4c, 0xbd, 0x38, 0xda, 0x92, 0x1d, - 0xb4, 0xf2, 0x0d, 0x70, 0xbf, 0x46, 0xb6, 0x98, 0xe5, 0x00, 0xcd, 0x5e, 0x23, 0x32, 0x3e, 0x79, 0x01, 0x8c, 0xd9, - 0x3a, 0x0b, 0x23, 0x11, 0x07, 0x63, 0xd5, 0x98, 0x31, 0x03, 0x03, 0x17, 0xe8, 0x5a, 0x26, 0x25, 0x69, 0x48, 0x07, - 0x03, 0x56, 0xca, 0x16, 0x0e, 0x78, 0xd1, 0x1c, 0xb7, 0xe3, 0x6b, 0x8b, 0xc6, 0x03, 0xdb, 0xc5, 0xf6, 0x77, 0xcf, - 0x8b, 0xed, 0x9b, 0x70, 0x4b, 0x7a, 0x85, 0x9c, 0x25, 0xf4, 0xf3, 0x67, 0xd9, 0x67, 0x0d, 0x27, 0xa7, 0x42, 0x33, - 0xb4, 0x14, 0x09, 0xa5, 0x78, 0xa7, 0x27, 0x05, 0xc6, 0x32, 0x16, 0xfe, 0x1e, 0x38, 0xa7, 0x0b, 0x45, 0xe4, 0x0e, - 0x1c, 0xc7, 0x1f, 0xa1, 0x82, 0x51, 0xc3, 0xc1, 0xcb, 0x18, 0xb6, 0x45, 0x31, 0x0b, 0x09, 0xa7, 0x10, 0x2e, 0x56, - 0x59, 0xbf, 0x2f, 0x7f, 0x51, 0x17, 0x5d, 0x64, 0xb2, 0xee, 0x93, 0x70, 0x64, 0xc6, 0x72, 0xea, 0x85, 0xe4, 0x79, - 0xcf, 0x93, 0x69, 0xf2, 0x38, 0x0f, 0x22, 0x80, 0x7c, 0x0e, 0xef, 0xc2, 0x34, 0x03, 0xab, 0x34, 0x29, 0x3f, 0x42, - 0xe9, 0x8b, 0xcf, 0x2b, 0x3f, 0xd0, 0xd9, 0x73, 0x93, 0x0c, 0x6f, 0x56, 0xad, 0x37, 0xa9, 0x75, 0x5d, 0x3c, 0xe0, - 0x9f, 0x9d, 0xc1, 0xc6, 0xb9, 0xce, 0x04, 0x07, 0x5e, 0x24, 0xb5, 0x5e, 0x33, 0xfe, 0x34, 0xc3, 0x75, 0xa9, 0xda, - 0xe8, 0xa3, 0x10, 0x9d, 0x43, 0xa6, 0x02, 0x14, 0x8a, 0xb4, 0x7f, 0x50, 0x6a, 0x65, 0x52, 0x69, 0x23, 0x01, 0x74, - 0x0f, 0x93, 0x06, 0x5b, 0x0c, 0x65, 0x2c, 0x4d, 0xa2, 0xdc, 0x69, 0x10, 0x57, 0xf6, 0x43, 0x25, 0x71, 0x68, 0x59, - 0x24, 0xff, 0xde, 0xf5, 0xf4, 0x15, 0x52, 0x77, 0xb2, 0x40, 0x66, 0x8c, 0x67, 0x79, 0xfc, 0x09, 0x08, 0xb3, 0x41, - 0x1b, 0x15, 0x85, 0x10, 0xb2, 0x41, 0x0c, 0x1a, 0xcf, 0xf2, 0xf8, 0xb9, 0xa2, 0xf1, 0x90, 0x8f, 0x22, 0x5f, 0xfd, - 0x55, 0xea, 0xbf, 0x42, 0x9f, 0x99, 0xe0, 0x11, 0xaa, 0x89, 0xfe, 0xdd, 0xf3, 0xd9, 0x1d, 0xa8, 0x0d, 0xa3, 0x30, - 0x33, 0xe5, 0x57, 0xbe, 0x29, 0xce, 0x5e, 0x7f, 0x45, 0x57, 0xd9, 0xd6, 0xfd, 0xe8, 0xe5, 0x11, 0x81, 0xb5, 0x31, - 0xba, 0xe2, 0xc6, 0x00, 0x72, 0x98, 0xbc, 0x5f, 0x51, 0x5a, 0x0e, 0x69, 0x10, 0x3a, 0x68, 0x08, 0xa3, 0x25, 0xd1, - 0x07, 0x12, 0x8b, 0x18, 0xc3, 0x0b, 0xf1, 0x8c, 0xd4, 0x64, 0xa2, 0x21, 0x5e, 0x11, 0xfb, 0x21, 0x5a, 0x72, 0x6a, - 0xa2, 0x1b, 0x61, 0x8a, 0x81, 0xc4, 0xce, 0x20, 0x39, 0x49, 0x6a, 0xe5, 0x17, 0xcf, 0x24, 0x61, 0x89, 0x9d, 0x87, - 0x18, 0x4c, 0x6a, 0xe9, 0x4e, 0x6f, 0xaa, 0xf4, 0xfc, 0x48, 0xcb, 0x41, 0xfb, 0x00, 0xec, 0x52, 0xd2, 0xfb, 0x27, - 0x85, 0x22, 0xde, 0x87, 0x71, 0x0c, 0xe1, 0x5b, 0x44, 0x75, 0x05, 0xce, 0xb5, 0x02, 0x8d, 0xd5, 0xc0, 0x43, 0x33, - 0xab, 0xe6, 0x43, 0x4e, 0x3f, 0x95, 0x96, 0x3f, 0x46, 0x34, 0x36, 0x5a, 0x37, 0x87, 0xc3, 0x9e, 0x56, 0xbd, 0x74, - 0x0e, 0xba, 0x6c, 0x26, 0x31, 0x71, 0x03, 0xe9, 0xfa, 0xd1, 0x6f, 0x26, 0xec, 0x45, 0x54, 0xc8, 0xa5, 0x10, 0x14, - 0xb4, 0x3a, 0x10, 0x38, 0x14, 0xde, 0xa2, 0xcc, 0x17, 0x31, 0x6d, 0x20, 0x0c, 0x3e, 0x3f, 0x90, 0x9f, 0x6f, 0x0a, - 0x52, 0xb1, 0x63, 0x5d, 0xfb, 0xfd, 0x65, 0xe9, 0x01, 0x9e, 0x9c, 0x49, 0xf2, 0xb4, 0x19, 0xc2, 0x8a, 0x00, 0x1a, - 0xb3, 0x9a, 0x2c, 0x4e, 0xb8, 0x32, 0x87, 0x2f, 0x2b, 0xaf, 0x64, 0x29, 0x53, 0xe7, 0xa9, 0x5e, 0x00, 0x51, 0xc7, - 0x1b, 0xb4, 0x22, 0xf5, 0x2b, 0x74, 0xf6, 0x9a, 0x95, 0x90, 0xf1, 0xf0, 0x9c, 0xf3, 0x74, 0x74, 0xcf, 0x12, 0x1e, - 0xe1, 0x5f, 0xc9, 0x44, 0x1f, 0x7e, 0xf7, 0x1c, 0x6e, 0xc6, 0x09, 0x8f, 0xdc, 0x66, 0xef, 0xab, 0x70, 0x05, 0x37, - 0xd3, 0x02, 0x90, 0xdc, 0x82, 0xa4, 0x09, 0x28, 0x21, 0x91, 0x09, 0x99, 0x35, 0x25, 0x7f, 0x6d, 0x69, 0x1b, 0xac, - 0x61, 0xd2, 0x79, 0xc0, 0x8b, 0x56, 0x1f, 0xad, 0x26, 0xda, 0x65, 0x96, 0xcf, 0x87, 0x38, 0x43, 0x35, 0xc7, 0xdd, - 0x19, 0xfc, 0x1c, 0xf0, 0x8a, 0x55, 0x4d, 0x3a, 0xda, 0x0d, 0xb8, 0xf0, 0xe4, 0x3a, 0x4f, 0x47, 0x5b, 0xfc, 0x25, - 0xf7, 0x07, 0x80, 0x0e, 0xa6, 0x2e, 0x81, 0x3f, 0x55, 0x5b, 0x4d, 0xa5, 0x7e, 0x6e, 0xed, 0xd7, 0x75, 0x67, 0xb5, - 0x72, 0xcf, 0xba, 0x0c, 0xed, 0x91, 0x21, 0x67, 0xcc, 0x80, 0x3f, 0x67, 0x2c, 0xf9, 0x73, 0xc6, 0x8a, 0x3f, 0x67, - 0xdc, 0x18, 0x19, 0x40, 0x09, 0xee, 0x25, 0x7f, 0xba, 0x47, 0xcc, 0x10, 0xab, 0x41, 0x25, 0xb0, 0xb2, 0x94, 0x73, - 0x1f, 0x39, 0xc5, 0x94, 0x53, 0x86, 0x97, 0x4e, 0x67, 0xee, 0x40, 0xce, 0x83, 0x99, 0x3b, 0x4c, 0xf6, 0xfa, 0xdc, - 0x88, 0x63, 0x69, 0x4c, 0x8a, 0x0a, 0xd2, 0x39, 0x1d, 0x6e, 0x5e, 0x1d, 0xe7, 0x09, 0xcb, 0xf8, 0xb8, 0x7d, 0xa6, - 0x40, 0x88, 0x2d, 0x9e, 0x21, 0x91, 0x52, 0x35, 0xcb, 0x6d, 0xfe, 0x70, 0xa8, 0x47, 0xf7, 0x7a, 0xa7, 0x87, 0x5f, - 0x09, 0xfb, 0x39, 0xf3, 0xec, 0x13, 0x04, 0x30, 0x49, 0xe4, 0x99, 0x84, 0xa3, 0x1f, 0xcb, 0xd1, 0xdf, 0x34, 0xfc, - 0x79, 0x86, 0xea, 0xee, 0x10, 0x98, 0xd8, 0xb2, 0x03, 0x87, 0xe0, 0x74, 0x55, 0x89, 0x04, 0x1c, 0x6c, 0x36, 0x2c, - 0xd2, 0x7b, 0x3c, 0xc4, 0xf9, 0xa0, 0xf0, 0x11, 0x1a, 0x66, 0xf4, 0x7e, 0x7f, 0x23, 0xbc, 0x4a, 0xb6, 0xf2, 0x70, - 0x48, 0x2c, 0x0d, 0x90, 0xa3, 0x8f, 0xa3, 0x3d, 0x4a, 0xa8, 0xfd, 0xa8, 0xd6, 0x9b, 0x4a, 0x3d, 0xc8, 0xcd, 0x2e, - 0x24, 0x06, 0x15, 0x4b, 0xf5, 0xe9, 0x95, 0xea, 0x43, 0xcd, 0x92, 0x43, 0xaa, 0xe3, 0x3e, 0x15, 0xa3, 0xb5, 0x9c, - 0x10, 0xe0, 0x3a, 0x48, 0x34, 0x3a, 0x00, 0xc6, 0xd9, 0x66, 0xcb, 0x4b, 0x6d, 0x9d, 0x28, 0x1d, 0xc7, 0xb9, 0x3e, - 0x8e, 0x0f, 0x07, 0x29, 0x66, 0x5c, 0x1e, 0x89, 0x19, 0x97, 0x0d, 0xc0, 0x9b, 0x75, 0x1e, 0xd4, 0x87, 0xc3, 0x25, - 0x5d, 0x8a, 0x4c, 0x67, 0x1b, 0xe5, 0x67, 0x3d, 0xba, 0x7f, 0x9c, 0xa0, 0xb9, 0xb7, 0xc2, 0xde, 0x8b, 0x64, 0x7b, - 0x26, 0xeb, 0xd4, 0xcb, 0xc8, 0xa7, 0x17, 0xee, 0xd9, 0x25, 0x57, 0x3f, 0xac, 0xbe, 0x9e, 0xfe, 0x26, 0xbc, 0x88, - 0x55, 0xb4, 0x5b, 0x97, 0x4c, 0xd8, 0x5b, 0x4a, 0x25, 0xad, 0xf2, 0xf2, 0xe9, 0xc6, 0x0f, 0x30, 0x33, 0xed, 0xe9, - 0x83, 0x6c, 0x44, 0xf5, 0x67, 0x25, 0x6a, 0x65, 0x98, 0x2c, 0x9c, 0x97, 0x4c, 0x3d, 0x19, 0xf0, 0x98, 0x95, 0x3c, - 0x92, 0x9d, 0xde, 0x18, 0x04, 0x01, 0xac, 0x73, 0xd2, 0xaa, 0x33, 0x8e, 0x46, 0xab, 0xca, 0xc5, 0xe9, 0x2a, 0x17, - 0x18, 0x6e, 0xb7, 0x66, 0x1b, 0x55, 0x67, 0xb9, 0xa9, 0x55, 0xca, 0x77, 0x00, 0x1f, 0xcb, 0x2a, 0x17, 0x74, 0x4c, - 0x99, 0x3a, 0x6f, 0x20, 0x18, 0x5b, 0xd5, 0xb8, 0x70, 0x6a, 0x5c, 0xf0, 0x88, 0xda, 0xdd, 0x34, 0xf5, 0x68, 0x0b, - 0x2c, 0xa5, 0xa3, 0x1d, 0x2f, 0x51, 0xa5, 0xf0, 0x0f, 0xc1, 0xf7, 0x61, 0x1c, 0x3f, 0x2f, 0xb6, 0xea, 0x40, 0xbc, - 0x29, 0xb6, 0x48, 0xfb, 0x22, 0xff, 0x42, 0x1c, 0xf0, 0x5a, 0xd7, 0x94, 0xd7, 0xd6, 0x9c, 0x06, 0xb6, 0x86, 0x91, - 0x92, 0xc2, 0xb9, 0xf9, 0xf3, 0x70, 0xa0, 0x95, 0x5d, 0xab, 0xbb, 0x42, 0xad, 0xc7, 0x1c, 0x36, 0xec, 0x45, 0x16, - 0xee, 0x44, 0x09, 0x8e, 0x5c, 0xf2, 0xaf, 0xc3, 0x41, 0xab, 0x2c, 0xd5, 0x91, 0x3e, 0xdb, 0x7f, 0x0d, 0xc6, 0x0c, - 0x5d, 0x9a, 0x80, 0x65, 0x63, 0x24, 0xff, 0x6a, 0x9a, 0x79, 0xc3, 0x64, 0xcd, 0x14, 0x8e, 0x43, 0xc3, 0x08, 0x69, - 0x40, 0xb7, 0x41, 0x6d, 0x78, 0x32, 0xdf, 0x54, 0xe5, 0x57, 0x77, 0xa4, 0xda, 0x0f, 0x86, 0x97, 0x13, 0x71, 0x4e, - 0x97, 0x24, 0xf5, 0x54, 0x42, 0x49, 0x08, 0x76, 0xe9, 0x03, 0x39, 0xb1, 0x02, 0xb2, 0x96, 0xb1, 0xfc, 0x56, 0x0f, - 0x08, 0xfd, 0xa7, 0xdd, 0x7a, 0xa1, 0xff, 0x34, 0xcd, 0x16, 0xea, 0xfa, 0xc3, 0xe4, 0xbe, 0xa3, 0xd7, 0x1f, 0x1c, - 0xde, 0xa9, 0xab, 0x8a, 0xab, 0x78, 0x54, 0x1b, 0x26, 0xb9, 0x51, 0x16, 0xee, 0x8a, 0x4d, 0xad, 0x96, 0xa7, 0xe3, - 0x30, 0x02, 0x33, 0x82, 0x02, 0x64, 0x5d, 0xb7, 0x11, 0x31, 0xac, 0xe4, 0x32, 0x21, 0x9f, 0x10, 0x90, 0x45, 0xa9, - 0x71, 0x3e, 0x6e, 0x81, 0x4a, 0x04, 0x83, 0xd3, 0xd0, 0x5a, 0x75, 0x93, 0x9f, 0x55, 0x36, 0x76, 0x0b, 0xe4, 0x90, - 0x64, 0xb2, 0xb8, 0x1d, 0xdd, 0x88, 0x65, 0x51, 0x8a, 0xd7, 0x58, 0x0f, 0xd7, 0x6c, 0xe1, 0x3e, 0x03, 0x42, 0xfb, - 0x89, 0xd2, 0xde, 0x44, 0x9a, 0xa0, 0xfb, 0x96, 0xad, 0x00, 0x64, 0x00, 0x45, 0x5d, 0xed, 0xd6, 0xe7, 0xfc, 0x1c, - 0x49, 0x33, 0x1c, 0x46, 0xb7, 0x4f, 0x6f, 0x83, 0xdb, 0xc1, 0x25, 0x6a, 0xa5, 0x2f, 0x59, 0xdc, 0xc2, 0xa0, 0xda, - 0x9b, 0x25, 0x1c, 0xd4, 0xcc, 0x5a, 0x1b, 0x81, 0x60, 0xb2, 0x87, 0x82, 0x8a, 0xb9, 0x82, 0x7d, 0x50, 0xb0, 0x96, - 0xbc, 0x0e, 0x0e, 0xb7, 0xf6, 0x65, 0xa5, 0xb8, 0x78, 0x72, 0x91, 0xb4, 0x2e, 0x2c, 0xe5, 0xc5, 0x93, 0x06, 0x0c, - 0x2e, 0x47, 0xd8, 0x54, 0x60, 0x92, 0x00, 0xd0, 0xad, 0x88, 0x22, 0x5e, 0x94, 0xc2, 0xb6, 0x95, 0xcf, 0x9c, 0xb0, - 0xc1, 0x86, 0xdd, 0xc3, 0xbd, 0x32, 0x28, 0x19, 0x5c, 0x88, 0x71, 0xbb, 0xd9, 0x05, 0xb8, 0x82, 0xa1, 0x30, 0xb6, - 0xe6, 0x5f, 0x33, 0x2f, 0x52, 0x02, 0x6e, 0x86, 0x28, 0x5f, 0x1b, 0x38, 0x99, 0xf4, 0xe4, 0x5a, 0xb2, 0x18, 0xb0, - 0xa0, 0xc1, 0x77, 0xd4, 0xfa, 0x3b, 0x93, 0x7f, 0xe3, 0xe9, 0xa1, 0x1f, 0xfc, 0x9a, 0x79, 0x4b, 0x9f, 0xbd, 0xad, - 0x64, 0xb4, 0x26, 0x89, 0xf2, 0xea, 0xe1, 0x12, 0xe4, 0x86, 0xe5, 0xe8, 0x9e, 0x2d, 0x41, 0x9c, 0x58, 0x8e, 0x12, - 0xca, 0xe8, 0x0a, 0xf7, 0x2a, 0xb3, 0x65, 0x22, 0x90, 0xe2, 0xc0, 0x52, 0xca, 0xbd, 0xc5, 0x3a, 0x58, 0xe2, 0xfe, - 0x44, 0x72, 0x01, 0x25, 0x0f, 0xa0, 0x5c, 0x29, 0x20, 0xe0, 0xd3, 0x01, 0x94, 0x2f, 0xe5, 0x45, 0xf8, 0x13, 0x27, - 0x6a, 0xb0, 0x1c, 0xdd, 0x37, 0xec, 0x67, 0x2f, 0xb4, 0xec, 0x0f, 0xb7, 0x5a, 0xd3, 0xb0, 0xe2, 0xb7, 0x30, 0x2d, - 0x26, 0x6e, 0x5f, 0xae, 0xec, 0xaa, 0xf8, 0x6c, 0xa5, 0xce, 0x6e, 0x6a, 0x48, 0xc2, 0xbe, 0x21, 0xab, 0x00, 0x07, - 0xab, 0x22, 0xee, 0x59, 0x97, 0xfb, 0x30, 0xfa, 0xb2, 0x49, 0x4b, 0x61, 0xa1, 0x4a, 0xfa, 0xfb, 0xa6, 0x14, 0x48, - 0x65, 0xa2, 0x13, 0x2d, 0x04, 0x57, 0x60, 0x10, 0xb8, 0x13, 0x79, 0x0d, 0x80, 0x31, 0xe0, 0x52, 0xa0, 0x2c, 0xdb, - 0x12, 0x42, 0xaa, 0xfb, 0x19, 0xa8, 0xed, 0xc4, 0x5d, 0x1a, 0x91, 0xb5, 0x10, 0x7d, 0x15, 0x8c, 0x99, 0xf3, 0x52, - 0xba, 0xc5, 0xa6, 0xab, 0xcd, 0xea, 0x23, 0x3a, 0x97, 0xb6, 0xdc, 0xfc, 0x84, 0x2d, 0xd6, 0x0a, 0x94, 0x4d, 0x48, - 0xda, 0xce, 0x79, 0x8e, 0xb2, 0x09, 0x2d, 0xed, 0x3d, 0xf5, 0xa8, 0x50, 0x9d, 0x6c, 0xbd, 0x54, 0x4d, 0x2d, 0xc2, - 0x6a, 0x71, 0x51, 0xf9, 0x01, 0xe8, 0xa6, 0xd2, 0xea, 0x59, 0x5d, 0xa3, 0x29, 0xd4, 0x6a, 0xe1, 0xb8, 0xd1, 0xce, - 0xa6, 0xcb, 0xf4, 0x16, 0x71, 0x56, 0xa5, 0x1d, 0xfa, 0x97, 0x4c, 0xbb, 0x5e, 0x76, 0xf4, 0x9b, 0x71, 0x75, 0x81, - 0x0b, 0xb1, 0x01, 0x9f, 0x73, 0x7f, 0x79, 0xbd, 0x27, 0x71, 0xcf, 0x3f, 0x1c, 0x90, 0x3d, 0xa9, 0xfd, 0xa1, 0xfa, - 0xd8, 0x15, 0x0c, 0x59, 0x18, 0xa5, 0xfe, 0x22, 0xe5, 0xbd, 0x47, 0x38, 0xee, 0x9f, 0xab, 0x1e, 0xfb, 0x57, 0xc6, - 0xf7, 0x75, 0xb1, 0x89, 0x12, 0x8a, 0x6a, 0xe8, 0xad, 0x8a, 0x4d, 0x25, 0xe2, 0xe2, 0x3e, 0xef, 0x31, 0x4c, 0x86, - 0xb1, 0x90, 0xa9, 0xf0, 0xa7, 0x4c, 0x05, 0x8f, 0x10, 0x4a, 0xdc, 0xac, 0x7b, 0xa4, 0xdd, 0x84, 0x38, 0xa5, 0x5a, - 0x94, 0x32, 0x19, 0xff, 0xd6, 0x4f, 0xa0, 0x3c, 0xa7, 0x68, 0x99, 0x7e, 0x54, 0xb8, 0x4c, 0xdf, 0xac, 0x8f, 0x4b, - 0xcf, 0x44, 0xa8, 0x33, 0x17, 0x9b, 0x5a, 0xa7, 0x63, 0xec, 0x94, 0x4e, 0x6d, 0xd8, 0xd7, 0x4a, 0x71, 0x59, 0x51, - 0xf8, 0x37, 0x12, 0x59, 0xf5, 0x8c, 0x38, 0xfe, 0x7b, 0xd6, 0x3e, 0xc3, 0x2a, 0xf0, 0xcb, 0x40, 0xde, 0x2f, 0x00, - 0x3e, 0xae, 0xeb, 0x32, 0xbd, 0xd9, 0x00, 0x6d, 0x08, 0x0d, 0x7f, 0xcf, 0x47, 0x06, 0x4c, 0xf7, 0x11, 0xce, 0x90, - 0x1e, 0xea, 0x9c, 0xd3, 0x59, 0x99, 0xce, 0xb9, 0x0a, 0x6b, 0x09, 0xf6, 0x72, 0xd2, 0xe4, 0x72, 0x5d, 0x82, 0x9a, - 0x09, 0xdc, 0x3e, 0xb4, 0x47, 0x84, 0x50, 0x9b, 0xb2, 0x9a, 0x5e, 0x42, 0xcd, 0x3b, 0x39, 0xed, 0x68, 0x52, 0x82, - 0xab, 0x86, 0xce, 0xca, 0xf5, 0x5f, 0x87, 0x43, 0xef, 0x26, 0x2b, 0xa2, 0x3f, 0x7b, 0xe8, 0xef, 0xb8, 0xfd, 0x98, - 0x7e, 0x85, 0x68, 0x19, 0xeb, 0x6f, 0xc8, 0x80, 0x8e, 0x27, 0xc3, 0x9b, 0x62, 0xdb, 0x63, 0x5f, 0x51, 0x83, 0xa5, - 0xaf, 0x1f, 0x1f, 0x41, 0x42, 0xd5, 0xb5, 0x2f, 0x2c, 0x9e, 0x30, 0x4f, 0x89, 0xb6, 0x85, 0x0f, 0x61, 0xa1, 0x5f, - 0x21, 0x32, 0x12, 0xc2, 0x4d, 0x65, 0xf7, 0x28, 0x69, 0x17, 0xfa, 0xd2, 0xd7, 0xb2, 0xaf, 0x7c, 0xe7, 0x02, 0x60, - 0x65, 0x9f, 0xd8, 0x70, 0x4f, 0xfa, 0x53, 0xaa, 0x0f, 0xdb, 0xdf, 0x92, 0x05, 0x14, 0x5a, 0x58, 0x4f, 0xe5, 0xec, - 0xbc, 0x2d, 0x79, 0x95, 0x4d, 0xf7, 0x6b, 0xd8, 0xa3, 0xee, 0xd0, 0x6b, 0x2a, 0x38, 0xbf, 0x34, 0xa3, 0xf7, 0xc5, - 0x50, 0xa8, 0x8e, 0x3a, 0x77, 0x90, 0xdb, 0xd2, 0xba, 0xe4, 0xfc, 0x66, 0xe5, 0x8e, 0xc2, 0xfc, 0x2e, 0x04, 0xcf, - 0xb0, 0xee, 0xdd, 0xc5, 0x79, 0xef, 0x1f, 0xad, 0x39, 0xf2, 0xaf, 0x6c, 0x96, 0x22, 0x16, 0xc9, 0x1c, 0xac, 0x7e, - 0xe8, 0xe7, 0xb1, 0xdf, 0x06, 0x39, 0x1c, 0x37, 0x0d, 0xe8, 0xb0, 0x21, 0xb3, 0xf6, 0x25, 0x02, 0xa7, 0x1a, 0x41, - 0x9a, 0x9a, 0xa0, 0x66, 0x79, 0x88, 0xc4, 0x76, 0x29, 0xdb, 0x06, 0xb9, 0xee, 0x82, 0x69, 0x8e, 0xb4, 0x67, 0xf0, - 0xbe, 0x49, 0x93, 0x54, 0x68, 0x16, 0x8d, 0xae, 0x64, 0xfc, 0x3b, 0xd2, 0x66, 0x4a, 0xf6, 0xd8, 0x1a, 0x78, 0x2f, - 0x41, 0x39, 0x19, 0xa6, 0x18, 0xbe, 0xe3, 0xeb, 0x9d, 0x47, 0x17, 0xf1, 0xb7, 0x63, 0xb6, 0x49, 0xd9, 0x11, 0x4c, - 0x92, 0x8d, 0x6f, 0x28, 0xde, 0xf0, 0xdd, 0x4d, 0x25, 0x4a, 0x00, 0xbd, 0x2c, 0xf8, 0x53, 0x69, 0x73, 0x85, 0x6e, - 0x77, 0xef, 0x28, 0x85, 0x5f, 0xf2, 0xf2, 0x70, 0xd8, 0xa6, 0x5e, 0x08, 0x9d, 0x2f, 0xe2, 0xb7, 0x60, 0x0e, 0x63, - 0x88, 0xcd, 0x08, 0x10, 0xe6, 0xf8, 0x80, 0x3a, 0x58, 0x3f, 0x02, 0xd0, 0x38, 0x81, 0x02, 0x8c, 0xbe, 0xda, 0x16, - 0xf4, 0x2d, 0x2f, 0x2e, 0x22, 0x44, 0x8d, 0x02, 0x4c, 0x94, 0x34, 0x8b, 0x61, 0x38, 0xd0, 0xf9, 0x7d, 0x73, 0x53, - 0x97, 0x02, 0x87, 0xde, 0xb1, 0x0c, 0xff, 0xf3, 0x7f, 0xac, 0x2d, 0xad, 0x2a, 0xdb, 0xad, 0x71, 0x9a, 0xf9, 0xdf, - 0x6e, 0x8b, 0x74, 0x0b, 0x15, 0x8a, 0xe7, 0x1d, 0xaf, 0xdb, 0x9f, 0x21, 0x7a, 0x5f, 0xb7, 0x72, 0x55, 0x6a, 0x37, - 0xcc, 0x94, 0xdf, 0xa7, 0x79, 0x5c, 0xdc, 0x8f, 0xe2, 0xd6, 0x91, 0x37, 0x49, 0xcf, 0x39, 0xff, 0x5c, 0xf5, 0xfb, - 0xde, 0x67, 0x20, 0xe3, 0xbd, 0x16, 0xc6, 0x11, 0x93, 0x38, 0xf8, 0xf6, 0x62, 0x14, 0x6d, 0x4a, 0xd8, 0x90, 0xdb, - 0xa7, 0x25, 0x68, 0x66, 0xfa, 0x7d, 0x94, 0x28, 0xad, 0xf9, 0xfe, 0x6f, 0x39, 0xdf, 0xaf, 0x85, 0xbc, 0x59, 0xc9, - 0x0f, 0x1f, 0xad, 0x30, 0xf0, 0x3d, 0x4e, 0xbf, 0x8a, 0x1e, 0x5b, 0x95, 0x3e, 0x7c, 0x57, 0x5a, 0xfa, 0xac, 0xa2, - 0xfe, 0x8e, 0x8a, 0x9a, 0x6b, 0x31, 0x22, 0xe2, 0x41, 0xd0, 0xce, 0xb6, 0x4b, 0xed, 0x5a, 0x82, 0x76, 0xc1, 0xa6, - 0xb0, 0x3a, 0x79, 0x68, 0xc8, 0xfb, 0xfd, 0x97, 0xb9, 0xd7, 0xe2, 0x75, 0x37, 0x70, 0x97, 0xa5, 0x87, 0x10, 0xc0, - 0x5a, 0x06, 0xca, 0x38, 0xc2, 0xa4, 0x8b, 0xbc, 0x46, 0xd9, 0x74, 0x22, 0xf0, 0x31, 0xcb, 0xae, 0x9c, 0x64, 0x1a, - 0x60, 0x46, 0x35, 0x85, 0x99, 0x00, 0x23, 0xf5, 0x01, 0xeb, 0xa6, 0xa7, 0x55, 0x68, 0xf9, 0x1a, 0x82, 0x75, 0x91, - 0x65, 0x1c, 0xc5, 0x4c, 0x00, 0xb0, 0xf9, 0x00, 0xf2, 0x15, 0x5d, 0x1d, 0x92, 0x56, 0xaa, 0xbc, 0x5f, 0x67, 0x44, - 0x46, 0x93, 0x10, 0xcd, 0x6f, 0xe1, 0x81, 0x7d, 0xdb, 0xcc, 0xa8, 0x52, 0xcf, 0xa8, 0xca, 0x67, 0x38, 0x2c, 0x85, - 0x63, 0xc4, 0xff, 0x5b, 0xaa, 0x7a, 0x44, 0xa0, 0x57, 0x65, 0x5a, 0x45, 0x45, 0x9e, 0x8b, 0x08, 0x11, 0xaa, 0xa5, - 0x73, 0x38, 0xf4, 0x63, 0xbf, 0x8f, 0x03, 0x61, 0x5e, 0x14, 0x0f, 0x75, 0x65, 0x4d, 0x6b, 0x25, 0x05, 0x4e, 0x45, - 0x8d, 0x10, 0x21, 0xbc, 0x7f, 0x00, 0xcf, 0x6a, 0xea, 0xfb, 0x8d, 0x65, 0xa2, 0xfb, 0x92, 0x01, 0xe5, 0x0f, 0xc8, - 0xd7, 0x95, 0x14, 0x67, 0xd2, 0xe4, 0x21, 0x71, 0xc6, 0x01, 0x88, 0xf9, 0xb6, 0x44, 0xa3, 0xb1, 0xff, 0x01, 0x09, - 0x86, 0xea, 0x07, 0x3b, 0xdd, 0xd4, 0xfb, 0x3d, 0x93, 0x38, 0x8a, 0x3e, 0x6d, 0x93, 0xc7, 0x92, 0xa5, 0xd1, 0xc2, - 0xd1, 0x7b, 0xc4, 0x30, 0x0e, 0xa7, 0xf3, 0x31, 0xc9, 0x36, 0x26, 0xab, 0x00, 0xd2, 0xc9, 0x4c, 0x1d, 0x53, 0xea, - 0x68, 0x9c, 0xeb, 0x05, 0x55, 0xe8, 0xb1, 0x2e, 0x79, 0x0e, 0xd6, 0x93, 0x57, 0x5e, 0xe9, 0x4f, 0x85, 0x9c, 0xc3, - 0x46, 0x22, 0x28, 0xfc, 0x00, 0x57, 0x83, 0x95, 0x02, 0x06, 0x53, 0xdf, 0xc2, 0xd7, 0xc4, 0x73, 0x14, 0x3c, 0x0a, - 0xbb, 0x18, 0x5b, 0x2b, 0xdf, 0xf9, 0xa4, 0xa0, 0xdc, 0xb3, 0x62, 0xce, 0x2b, 0xe0, 0x5c, 0x06, 0x85, 0x30, 0x1d, - 0xcf, 0xf2, 0x7f, 0x26, 0x79, 0x3d, 0xb1, 0x21, 0x40, 0x06, 0x7f, 0x4a, 0x9c, 0x96, 0xee, 0xd0, 0x9d, 0x87, 0x9e, - 0x45, 0x1c, 0x36, 0x7a, 0xb4, 0x2e, 0x8b, 0x6d, 0x8a, 0x7a, 0x09, 0xf3, 0x03, 0xf9, 0x79, 0x4b, 0xbe, 0x0f, 0x51, - 0xbc, 0x0d, 0xfe, 0x96, 0xb1, 0x58, 0xe0, 0x5f, 0xff, 0xcc, 0x18, 0x4d, 0xb4, 0xa0, 0x4e, 0x1a, 0x24, 0x2a, 0x16, - 0xc9, 0x04, 0x60, 0x1d, 0xb9, 0xfa, 0xf0, 0x29, 0x31, 0xde, 0x9a, 0x0d, 0x0f, 0x7c, 0xb3, 0x02, 0x9d, 0xfa, 0xdc, - 0x5d, 0xd9, 0x9e, 0xae, 0x46, 0xaa, 0xaa, 0xf1, 0xb7, 0x54, 0x55, 0xe3, 0x6f, 0x29, 0x55, 0xe3, 0xb7, 0x8c, 0xe2, - 0x77, 0x2a, 0x9f, 0x21, 0x73, 0xb2, 0x89, 0x49, 0x3a, 0x7d, 0x6f, 0x38, 0xb1, 0xcb, 0x7e, 0xeb, 0x36, 0x91, 0x67, - 0x26, 0x52, 0xc8, 0xbd, 0x01, 0xa8, 0x99, 0xf8, 0x32, 0x37, 0x9c, 0x12, 0xe7, 0xe7, 0x1e, 0xae, 0xd8, 0xb4, 0xba, - 0xa6, 0x05, 0x0b, 0x6c, 0x5e, 0x66, 0x79, 0xe6, 0x09, 0x6c, 0x9b, 0x32, 0xeb, 0x87, 0xdc, 0x03, 0x08, 0x66, 0x52, - 0x13, 0x00, 0xd2, 0x42, 0x54, 0x0a, 0x91, 0x5f, 0xe3, 0xac, 0x3e, 0xe7, 0xbd, 0x4d, 0x1e, 0x13, 0x69, 0x75, 0xaf, - 0xdf, 0x4f, 0xcf, 0xd2, 0x9c, 0x82, 0x1a, 0x8e, 0xb3, 0x4e, 0x7f, 0xc9, 0x82, 0x34, 0x91, 0xab, 0xf4, 0x9f, 0x6e, - 0x90, 0x97, 0xf1, 0x7d, 0xdd, 0xf6, 0xfc, 0x89, 0xfa, 0x7b, 0x67, 0xfd, 0x6d, 0x81, 0xe0, 0x4e, 0x8e, 0xfd, 0x64, - 0x55, 0xca, 0x23, 0xe3, 0xd2, 0xde, 0xf3, 0x9b, 0xba, 0x28, 0xb2, 0x3a, 0x5d, 0xbf, 0x97, 0x7a, 0x1a, 0xdd, 0x17, - 0x7b, 0x30, 0x06, 0xef, 0x00, 0xf0, 0x4c, 0x87, 0x06, 0x48, 0xdf, 0x33, 0xf2, 0x70, 0x9f, 0x5b, 0xf2, 0x93, 0xca, - 0xda, 0x24, 0x61, 0x45, 0xb1, 0x19, 0xc6, 0x08, 0x25, 0xe3, 0x34, 0xb6, 0x7e, 0xbf, 0xaf, 0xfe, 0xde, 0x61, 0x14, - 0x15, 0x15, 0x77, 0x8c, 0x46, 0x65, 0x55, 0x8f, 0xb6, 0x83, 0xc3, 0xe1, 0x3c, 0xb7, 0x71, 0xb4, 0xf5, 0x0a, 0xd8, - 0x5b, 0xa1, 0x52, 0xf6, 0x4a, 0x84, 0xe5, 0x87, 0x2b, 0xbf, 0xdf, 0x87, 0x7f, 0x65, 0xa4, 0x85, 0xe7, 0x4f, 0xf1, - 0xd7, 0xa2, 0x2e, 0x30, 0x3c, 0x83, 0xd6, 0x68, 0x05, 0xc1, 0x04, 0xff, 0xec, 0x40, 0xbd, 0xb4, 0xd2, 0x3e, 0x80, - 0x6e, 0x05, 0x7a, 0xd0, 0x70, 0x12, 0x27, 0xed, 0x0b, 0x89, 0xba, 0xbd, 0xd5, 0x69, 0xf4, 0x67, 0xc5, 0x72, 0x5e, - 0xc0, 0xe4, 0x70, 0x43, 0x9f, 0x56, 0xe1, 0xf6, 0x13, 0x3c, 0x7d, 0x0d, 0x94, 0x5b, 0x87, 0x43, 0x0e, 0x62, 0x0b, - 0xb8, 0x79, 0xac, 0xc2, 0xcf, 0x45, 0x29, 0x23, 0xea, 0xe3, 0x69, 0x08, 0xda, 0xbb, 0x00, 0x1d, 0xb0, 0x34, 0x88, - 0x57, 0x48, 0x9e, 0xb3, 0x11, 0xc0, 0xb2, 0x03, 0xcb, 0x59, 0xc6, 0x29, 0xcc, 0xb3, 0x7c, 0xaa, 0x56, 0xda, 0x59, - 0x94, 0x78, 0x35, 0xcb, 0xc0, 0x59, 0xe0, 0xa2, 0xf2, 0x59, 0xa6, 0x55, 0x4f, 0x65, 0x82, 0x3e, 0xaf, 0xe4, 0x04, - 0x57, 0x82, 0x93, 0x0d, 0xc8, 0x2f, 0x40, 0x92, 0xa6, 0x94, 0x35, 0xe5, 0xd3, 0x4b, 0xba, 0x21, 0xa3, 0xe7, 0xbc, - 0xe7, 0x45, 0xc3, 0xd0, 0xbf, 0xf0, 0x4a, 0x08, 0xdf, 0xc4, 0x6d, 0x1b, 0xa5, 0xb0, 0xbf, 0x09, 0x2c, 0x3e, 0x61, - 0xaf, 0xbc, 0xa5, 0x3f, 0x1d, 0x07, 0xe1, 0x10, 0xb9, 0xa1, 0x62, 0x0e, 0xec, 0x69, 0xc0, 0x62, 0x13, 0x5f, 0x6d, - 0x26, 0xf1, 0x60, 0xe0, 0xeb, 0x8c, 0xc5, 0x2c, 0x06, 0x1a, 0xe4, 0x78, 0x70, 0x39, 0xd7, 0x27, 0x84, 0x7e, 0x18, - 0x51, 0x39, 0x2a, 0xd0, 0x39, 0x88, 0x06, 0x4b, 0xc0, 0x53, 0x6f, 0x65, 0x83, 0x24, 0xe3, 0x18, 0x92, 0xb8, 0xd6, - 0x24, 0xd5, 0xe1, 0x84, 0xd6, 0x81, 0x8e, 0xab, 0x0b, 0xe8, 0x7c, 0x5c, 0xf7, 0x3e, 0x5e, 0x0d, 0x17, 0x54, 0xfa, - 0x85, 0x18, 0x78, 0xf5, 0x74, 0x1c, 0x5c, 0xd2, 0xad, 0x70, 0xb1, 0x0a, 0xb7, 0xaf, 0xe5, 0x03, 0xc7, 0x1d, 0x95, - 0x34, 0x04, 0x06, 0x6f, 0x0f, 0xdd, 0xcd, 0x8c, 0x77, 0xc8, 0xd1, 0x61, 0x9c, 0xc9, 0x21, 0x56, 0xad, 0xb8, 0x90, - 0xde, 0x08, 0xbe, 0x5d, 0x28, 0xc6, 0xb2, 0xb1, 0x4b, 0x43, 0x51, 0xf8, 0x37, 0x00, 0x3b, 0xd4, 0xfe, 0x4a, 0x25, - 0x1f, 0x23, 0xa3, 0x9a, 0x06, 0x3a, 0x06, 0x60, 0xc9, 0xd2, 0x44, 0x52, 0x45, 0x1a, 0x89, 0x3f, 0xb2, 0xc6, 0xba, - 0xe9, 0xfa, 0x82, 0xa9, 0x6a, 0x98, 0x74, 0x3b, 0x93, 0x58, 0x4e, 0x24, 0xa9, 0xed, 0x3e, 0x22, 0x06, 0x03, 0x1f, - 0x6c, 0xc4, 0x34, 0x13, 0xe1, 0x88, 0x47, 0x25, 0xb2, 0xe8, 0xf2, 0xdb, 0x88, 0x92, 0xb6, 0x2f, 0x2b, 0xb2, 0x05, - 0xc1, 0xf4, 0x24, 0xfa, 0x20, 0x49, 0x39, 0x15, 0x89, 0x34, 0x23, 0x04, 0xf8, 0xf1, 0xa4, 0xbc, 0xd2, 0x9f, 0x83, - 0xa6, 0x95, 0xe0, 0x25, 0x83, 0xe4, 0x91, 0xf8, 0x99, 0x14, 0xcc, 0x62, 0xac, 0x1a, 0x0c, 0xb0, 0x9c, 0xea, 0xb1, - 0x63, 0x92, 0xfe, 0x5b, 0xa7, 0x13, 0xf6, 0x33, 0x2f, 0xb7, 0xb5, 0xbc, 0x69, 0xee, 0x3d, 0xf3, 0x2a, 0x96, 0x6a, - 0x58, 0x06, 0xfd, 0xd7, 0x44, 0xbb, 0x60, 0x6b, 0xcb, 0x98, 0xb0, 0xea, 0x07, 0x90, 0xf6, 0x48, 0x97, 0x57, 0x0d, - 0x73, 0x26, 0x78, 0x74, 0x61, 0xcd, 0x83, 0xe8, 0x42, 0xf8, 0xc8, 0x65, 0x37, 0x49, 0xae, 0xc6, 0x13, 0x3f, 0x1c, - 0x0c, 0x14, 0x00, 0x2d, 0xad, 0x93, 0x62, 0x10, 0x3e, 0x16, 0x72, 0x20, 0x8d, 0x8e, 0xaa, 0x00, 0x8b, 0x65, 0x76, - 0x55, 0x4e, 0xb2, 0xc1, 0xc0, 0x07, 0xb1, 0x31, 0xb1, 0x1b, 0x9a, 0xcd, 0x7d, 0x76, 0xa2, 0x20, 0xab, 0xcd, 0x59, - 0x6b, 0xa6, 0x5b, 0x60, 0x00, 0x30, 0x88, 0x08, 0x96, 0xfb, 0xc4, 0xc8, 0x47, 0xd4, 0xe9, 0x29, 0x8c, 0x80, 0xe0, - 0x97, 0x13, 0x81, 0xc8, 0x45, 0x02, 0xf5, 0x00, 0x33, 0x01, 0x66, 0x54, 0x31, 0xbc, 0x04, 0x76, 0xf1, 0xdc, 0xbc, - 0x62, 0xd0, 0xbf, 0x68, 0x97, 0x48, 0x34, 0x95, 0x38, 0x1a, 0x23, 0xa7, 0xd2, 0x18, 0x19, 0x10, 0xbb, 0x38, 0xfe, - 0x3d, 0xa5, 0x47, 0x41, 0xca, 0x9e, 0x57, 0x86, 0x38, 0x1c, 0xc5, 0x57, 0xb0, 0x6a, 0x1c, 0x0e, 0xb5, 0x79, 0x3d, - 0x9d, 0xd5, 0xf3, 0x81, 0x08, 0xe0, 0xbf, 0xa1, 0x60, 0xbf, 0x6a, 0x2a, 0x72, 0x83, 0xd4, 0x79, 0x38, 0xa4, 0x20, - 0x9f, 0x1a, 0xab, 0x6c, 0xe5, 0xee, 0xa7, 0xb3, 0xb9, 0x35, 0x47, 0x2f, 0x6a, 0x5c, 0xb7, 0x56, 0x37, 0x14, 0x12, - 0xad, 0x69, 0x52, 0x5c, 0x55, 0x93, 0x62, 0xc0, 0x73, 0x5f, 0xa8, 0x2e, 0xb6, 0x46, 0xb0, 0xf0, 0xe7, 0x16, 0x08, - 0x93, 0xfe, 0x56, 0xdc, 0x21, 0x55, 0xe3, 0xae, 0xad, 0x76, 0xdb, 0xca, 0x86, 0x14, 0xcd, 0x87, 0x97, 0xb0, 0x4b, - 0xa7, 0x88, 0xb6, 0x5d, 0x12, 0x7c, 0x01, 0x5a, 0x56, 0x17, 0x22, 0x8f, 0xe9, 0x57, 0xc8, 0x2f, 0xc5, 0xf0, 0xaf, - 0xd2, 0xbd, 0x39, 0xb5, 0x41, 0x0e, 0x60, 0xbb, 0xf7, 0x70, 0x3b, 0x46, 0x0f, 0x64, 0xf0, 0x46, 0xc8, 0x39, 0xe7, - 0x97, 0x53, 0x6b, 0xc6, 0x44, 0xc3, 0x82, 0x95, 0xc3, 0xc8, 0x0f, 0x90, 0xf1, 0x72, 0x0a, 0xac, 0xec, 0x47, 0x45, - 0x5c, 0xfa, 0xc3, 0xc8, 0xbf, 0x78, 0x12, 0x64, 0xdc, 0x8b, 0x86, 0x1d, 0x5f, 0x80, 0xbd, 0xfa, 0xe2, 0x09, 0x8b, - 0x06, 0xbc, 0xba, 0xaa, 0xa7, 0x59, 0x30, 0xcc, 0x58, 0x74, 0x55, 0x0c, 0xc1, 0x87, 0xf6, 0x69, 0x39, 0x08, 0x7d, - 0xdf, 0xec, 0x1c, 0xc6, 0x98, 0x2c, 0x8f, 0xb0, 0x9f, 0xc1, 0x6d, 0x57, 0x4b, 0xcc, 0x60, 0xb2, 0xb9, 0x8d, 0x98, - 0xc1, 0x96, 0xbf, 0x78, 0x62, 0xb8, 0x84, 0xaa, 0xa7, 0x52, 0xb3, 0x51, 0xa0, 0x39, 0xb9, 0x42, 0x73, 0xb2, 0x12, - 0x6a, 0xc9, 0x27, 0x15, 0x4e, 0xd8, 0xf9, 0x24, 0x57, 0x76, 0xa3, 0x31, 0x06, 0x2e, 0xda, 0x5b, 0x93, 0x30, 0x32, - 0xd3, 0x59, 0x8a, 0x06, 0x2c, 0x3c, 0x13, 0xa7, 0x34, 0x06, 0xb4, 0x2f, 0x07, 0x96, 0x36, 0xe4, 0x17, 0x39, 0x33, - 0xd0, 0x36, 0xa4, 0x34, 0x6a, 0x06, 0xfe, 0x4c, 0x4d, 0x98, 0xdf, 0xc0, 0x4a, 0x04, 0x51, 0x5d, 0x80, 0x49, 0x92, - 0x93, 0xd1, 0x48, 0x59, 0x89, 0xe4, 0x1c, 0xf0, 0x3e, 0x80, 0x27, 0x8b, 0xd8, 0xd6, 0xfe, 0x94, 0xfe, 0x57, 0x87, - 0xcf, 0xa5, 0xff, 0x58, 0x00, 0x0b, 0xb9, 0x34, 0x88, 0x0c, 0x14, 0x0e, 0xa9, 0xe5, 0x18, 0x93, 0x38, 0x9e, 0x81, - 0x2f, 0xe1, 0x02, 0x4d, 0x01, 0xfd, 0x41, 0xcd, 0x28, 0x22, 0x0b, 0x7f, 0xf5, 0xec, 0xa6, 0xae, 0xf5, 0x3c, 0x73, - 0x5e, 0x83, 0x66, 0x06, 0x42, 0x7a, 0x9c, 0xaa, 0xb7, 0x21, 0xd1, 0x79, 0xf9, 0x56, 0xbf, 0x4c, 0x88, 0x64, 0x61, - 0xe4, 0xe9, 0xfb, 0x1c, 0xcc, 0x23, 0x8a, 0xd0, 0xc1, 0x95, 0x79, 0x38, 0x9c, 0x0b, 0x0a, 0xdf, 0x51, 0x9e, 0x0f, - 0x38, 0xcd, 0x92, 0x04, 0xb4, 0x81, 0x2c, 0x37, 0x65, 0xae, 0x92, 0x96, 0xa9, 0x7b, 0x0f, 0x56, 0x82, 0x0a, 0xdd, - 0x9c, 0x82, 0x42, 0x19, 0x09, 0x4a, 0x69, 0x35, 0x08, 0xa5, 0x3a, 0x2c, 0x82, 0xc8, 0x21, 0x0b, 0x01, 0x37, 0x53, - 0xd1, 0x68, 0x49, 0xc3, 0x23, 0x9c, 0x1b, 0x28, 0x04, 0x20, 0xb1, 0xa7, 0x8a, 0x32, 0x2e, 0x87, 0x80, 0x8f, 0x12, - 0x0e, 0x71, 0xd6, 0xa4, 0x2d, 0xcf, 0x41, 0x1c, 0xcb, 0x25, 0xbf, 0xad, 0x10, 0x0c, 0x22, 0xf4, 0x19, 0xf2, 0x27, - 0xcb, 0xf9, 0x77, 0xe3, 0x30, 0xed, 0x08, 0x1f, 0x76, 0xb5, 0x05, 0x17, 0xb3, 0x9b, 0xf9, 0x04, 0xe2, 0x5b, 0x6e, - 0xe6, 0xc7, 0x18, 0x22, 0x0b, 0x7f, 0x70, 0x3b, 0x94, 0x5c, 0x51, 0xe8, 0xb2, 0x1e, 0x91, 0x22, 0x7b, 0xba, 0xe6, - 0x08, 0x82, 0x03, 0xad, 0x1a, 0x64, 0x68, 0x24, 0xbe, 0x78, 0x02, 0x59, 0x83, 0x35, 0x7f, 0x5e, 0x91, 0xb3, 0xba, - 0x3f, 0xd9, 0x40, 0x35, 0xc9, 0x64, 0xad, 0xa8, 0x9c, 0xbf, 0x5d, 0x95, 0xe5, 0xc9, 0xaa, 0x0c, 0x57, 0x83, 0xae, - 0xaa, 0x2c, 0x39, 0x52, 0x1b, 0xa0, 0x35, 0x5d, 0x21, 0x86, 0x42, 0xd6, 0x60, 0x69, 0x55, 0x65, 0x4d, 0x7d, 0x02, - 0x81, 0x3e, 0xc0, 0x32, 0x6a, 0xf6, 0xd3, 0xe1, 0x2f, 0xc1, 0x2f, 0x2a, 0x64, 0xa9, 0x4e, 0xeb, 0x4c, 0xfc, 0x16, - 0x2c, 0x19, 0xfe, 0xf1, 0x7b, 0xb0, 0x06, 0x2c, 0x01, 0xb2, 0xdc, 0x6d, 0x6c, 0xb4, 0x5e, 0x15, 0x3f, 0x57, 0xeb, - 0x8b, 0x7e, 0xeb, 0x36, 0x51, 0x2b, 0xc0, 0x08, 0x85, 0x16, 0x01, 0xb6, 0x7a, 0xe0, 0x9e, 0x82, 0x1f, 0x88, 0xe1, - 0x5c, 0x93, 0xd6, 0xd4, 0x09, 0xaf, 0xb3, 0x71, 0x24, 0xa2, 0x7a, 0x0b, 0x17, 0xf7, 0x7a, 0x6b, 0xf1, 0x37, 0x2a, - 0x10, 0x00, 0x59, 0x4c, 0xb1, 0x76, 0xde, 0x90, 0x5e, 0x19, 0x76, 0x12, 0x7a, 0x6f, 0xd8, 0x09, 0xe4, 0xc5, 0x61, - 0xa7, 0xd0, 0x25, 0xda, 0x4e, 0x91, 0x9a, 0x68, 0x3b, 0x69, 0xb1, 0x0a, 0x4b, 0x08, 0x7e, 0xd5, 0xde, 0x3a, 0xca, - 0xf6, 0x45, 0x96, 0x30, 0x6d, 0x01, 0xa3, 0xdc, 0xaa, 0xcf, 0x9c, 0x22, 0x56, 0xca, 0xde, 0xe9, 0xa4, 0xca, 0x5d, - 0xe4, 0x53, 0xab, 0x29, 0x32, 0xf9, 0xf9, 0x71, 0x8b, 0xe4, 0x93, 0xd7, 0xed, 0x86, 0xc9, 0xf4, 0x0f, 0x47, 0x5f, - 0x40, 0x57, 0x64, 0xa7, 0x4f, 0x20, 0x20, 0x53, 0x41, 0xb5, 0xba, 0x55, 0x4c, 0xf3, 0x76, 0x95, 0xdd, 0x5e, 0x28, - 0x31, 0x9c, 0xce, 0x4e, 0xc2, 0xa3, 0xcd, 0x90, 0x81, 0x43, 0x10, 0x28, 0x84, 0x8a, 0x62, 0x78, 0x04, 0x6a, 0x8d, - 0xe4, 0x03, 0xfc, 0x68, 0x77, 0x2a, 0x88, 0xd4, 0x6e, 0x2a, 0x6e, 0x9c, 0xdc, 0x74, 0xbd, 0x14, 0xa8, 0x75, 0x4a, - 0x56, 0x00, 0x25, 0x44, 0xfd, 0x49, 0x6c, 0xeb, 0x6b, 0xb8, 0x62, 0xf3, 0x7d, 0xa3, 0xe8, 0xc9, 0xf5, 0x29, 0xea, - 0x56, 0x5c, 0x9d, 0xa6, 0xad, 0xe6, 0xd8, 0x71, 0x86, 0x1c, 0x3c, 0x2b, 0x08, 0xb6, 0xa3, 0x12, 0xe5, 0x9b, 0x76, - 0xd3, 0x31, 0xb1, 0xd5, 0x3f, 0x8b, 0x6a, 0x73, 0x0b, 0x15, 0x11, 0xf1, 0x51, 0x76, 0xf3, 0xa4, 0xfd, 0x0e, 0xf6, - 0x58, 0xab, 0x41, 0x64, 0x9f, 0xc1, 0x55, 0xae, 0xd3, 0x22, 0xb7, 0x65, 0x70, 0xfe, 0xe1, 0xd5, 0xae, 0xc2, 0x26, - 0xc7, 0xba, 0xba, 0x9a, 0xa9, 0x4e, 0x2a, 0x36, 0x30, 0xd6, 0xb4, 0x96, 0x6a, 0x1e, 0x43, 0xd2, 0x5d, 0x59, 0x9c, - 0x55, 0x49, 0x37, 0x3d, 0x37, 0xce, 0x14, 0x62, 0xe0, 0x6c, 0x35, 0x5a, 0xce, 0x30, 0x44, 0xd7, 0x87, 0x59, 0xe2, - 0xb7, 0x7a, 0xca, 0x7d, 0x1e, 0x6e, 0xfd, 0xae, 0x5e, 0x70, 0x32, 0xd9, 0x4f, 0x8e, 0x73, 0xb7, 0x8b, 0xb4, 0x9f, - 0xf8, 0x36, 0xcc, 0xbf, 0xbe, 0x41, 0xdc, 0x8a, 0xfa, 0x97, 0x0a, 0x80, 0x06, 0x37, 0x79, 0x2c, 0x51, 0xea, 0xf7, - 0xaa, 0xfa, 0x41, 0xcd, 0x54, 0x4d, 0x03, 0xc1, 0x9c, 0x4a, 0x01, 0x7f, 0xb8, 0x5d, 0xb8, 0xe2, 0x11, 0x37, 0x2c, - 0x8c, 0x5f, 0xbc, 0x9a, 0x9d, 0x0a, 0x2a, 0x03, 0x37, 0xe3, 0x2f, 0x9e, 0x60, 0xa7, 0xb0, 0x56, 0x40, 0x56, 0xf8, - 0xe2, 0xe5, 0x0f, 0xbc, 0x5f, 0xf1, 0x2f, 0x5e, 0xf5, 0xc0, 0xfb, 0x88, 0xf3, 0xf2, 0x05, 0x49, 0x9d, 0x10, 0xd5, - 0xe5, 0x0b, 0x61, 0x8a, 0xad, 0xd2, 0xfc, 0x05, 0x29, 0x7c, 0x82, 0xcf, 0xc0, 0x77, 0xb8, 0x0a, 0xb7, 0xe6, 0x37, - 0x78, 0xec, 0x58, 0x6c, 0xbb, 0xd4, 0x17, 0x50, 0x8e, 0xc0, 0x22, 0x72, 0xfb, 0xed, 0xca, 0x7e, 0xb5, 0x30, 0xca, - 0x18, 0xbb, 0x2f, 0x59, 0x89, 0xd2, 0x59, 0xbf, 0x5f, 0x48, 0xc1, 0xc8, 0x2e, 0xac, 0xd1, 0x1e, 0xa5, 0xea, 0xd5, - 0x37, 0x61, 0x1d, 0x25, 0x69, 0x7e, 0x2b, 0xa3, 0x8f, 0x64, 0xd8, 0x91, 0xbe, 0x92, 0x12, 0xed, 0xb5, 0x0a, 0xcb, - 0xd1, 0xec, 0xd7, 0x25, 0x07, 0xca, 0xeb, 0x56, 0x50, 0xbe, 0x6a, 0x02, 0xe8, 0x95, 0x6a, 0x9f, 0x81, 0x56, 0x50, - 0x58, 0x2a, 0x0f, 0x56, 0xe2, 0x5c, 0xf4, 0x59, 0x71, 0x38, 0xa8, 0x8b, 0x21, 0xa1, 0x40, 0x95, 0x38, 0x09, 0x8d, - 0x78, 0x0e, 0x17, 0x42, 0xf1, 0x34, 0xc7, 0xd8, 0x8a, 0x1c, 0x38, 0x90, 0xe1, 0x07, 0x04, 0xde, 0xcb, 0xfe, 0x15, - 0x0c, 0x86, 0x09, 0x6e, 0x64, 0xd4, 0xc9, 0x39, 0xfb, 0x82, 0x81, 0x19, 0xd4, 0x93, 0xda, 0x7d, 0x76, 0xaf, 0x02, - 0x7b, 0xe1, 0x0c, 0x68, 0xef, 0xc6, 0xe8, 0x67, 0x55, 0xac, 0x9d, 0xf4, 0x4f, 0xc5, 0x1a, 0x92, 0xe9, 0xb0, 0x38, - 0xda, 0xa6, 0xe1, 0x91, 0x3c, 0x39, 0x8e, 0x37, 0xfd, 0xc3, 0x61, 0x8c, 0x1f, 0x47, 0xf9, 0xb5, 0x05, 0xbc, 0x8a, - 0x5b, 0x48, 0x63, 0x91, 0xa2, 0x77, 0x20, 0xe6, 0x50, 0xf4, 0x92, 0xfd, 0x96, 0xf1, 0x72, 0x22, 0x28, 0x25, 0x89, - 0x0d, 0xef, 0x48, 0x4f, 0xd3, 0x7a, 0xb4, 0x95, 0x01, 0xfb, 0xf5, 0x68, 0x47, 0x7f, 0x81, 0xe2, 0xd1, 0xc2, 0x5f, - 0xd2, 0xdf, 0xc5, 0xdd, 0xdc, 0x73, 0xbe, 0x69, 0x7c, 0x47, 0x5c, 0xa0, 0x58, 0xb3, 0xfb, 0x6b, 0x5a, 0x3a, 0xeb, - 0x40, 0x70, 0xc0, 0x5b, 0xec, 0xa2, 0x7d, 0xbf, 0x71, 0x9d, 0x9e, 0xf6, 0xdf, 0xbb, 0x35, 0xca, 0xf7, 0x7e, 0x91, - 0x28, 0x07, 0xfb, 0x17, 0x2e, 0x9a, 0xbf, 0xfd, 0x94, 0x21, 0xa9, 0xd0, 0xdc, 0x60, 0x3b, 0xd9, 0x22, 0xac, 0x8d, - 0x71, 0x50, 0xb1, 0xdb, 0x32, 0x8c, 0x80, 0x41, 0x1d, 0xfb, 0x1f, 0x7d, 0x36, 0x6d, 0xc8, 0x3e, 0x00, 0x54, 0xae, - 0x42, 0xc0, 0x1e, 0x80, 0x13, 0x8d, 0x70, 0x03, 0xdc, 0x6a, 0xb4, 0xa4, 0x83, 0xba, 0x2d, 0x18, 0x88, 0x96, 0xb0, - 0x91, 0xb7, 0x5d, 0x9d, 0xbe, 0x21, 0x7c, 0xa8, 0x9d, 0x94, 0x0e, 0xe5, 0x6f, 0x9e, 0xb3, 0xff, 0xd9, 0x61, 0x4d, - 0x4d, 0xf9, 0x08, 0x98, 0x39, 0x2b, 0x91, 0x57, 0x08, 0x9d, 0x22, 0xbf, 0x57, 0x75, 0x25, 0x86, 0xcb, 0x5a, 0x94, - 0x9d, 0xd9, 0xad, 0x13, 0xbd, 0x73, 0x0a, 0x6a, 0xa9, 0x6c, 0x90, 0x93, 0x54, 0x9b, 0x8f, 0xac, 0x15, 0x94, 0xa8, - 0x6b, 0x14, 0x38, 0x3e, 0xe5, 0xda, 0xfd, 0xbf, 0x73, 0x26, 0xa8, 0xd9, 0x46, 0x75, 0x7f, 0xa1, 0x9f, 0xaa, 0x9a, - 0xc4, 0x02, 0x5c, 0x4e, 0xd2, 0xbc, 0xe3, 0x11, 0x56, 0xff, 0x38, 0x59, 0x8a, 0x40, 0x9f, 0x22, 0xda, 0x95, 0x80, - 0x04, 0xed, 0xe4, 0x2c, 0x54, 0x04, 0x0a, 0xf4, 0xf5, 0xe7, 0x9b, 0x34, 0x8b, 0xe5, 0x6a, 0xb6, 0x87, 0x89, 0xb2, - 0x58, 0x0f, 0x11, 0xe4, 0xcc, 0xd4, 0xc1, 0x7e, 0x4f, 0x33, 0x9a, 0x85, 0x57, 0xa6, 0x04, 0x97, 0xe2, 0x2a, 0x2a, - 0x72, 0xf0, 0x39, 0xc4, 0x17, 0x3e, 0x15, 0x72, 0x83, 0x88, 0xa6, 0x3f, 0x4b, 0x54, 0x3b, 0x52, 0x20, 0x87, 0x92, - 0x9f, 0x10, 0x7f, 0xc9, 0xda, 0x18, 0xf7, 0x4b, 0xa7, 0xda, 0xd7, 0x0a, 0xc1, 0xfd, 0xb5, 0x2d, 0x36, 0xaa, 0x3c, - 0xd1, 0x83, 0x4f, 0xb1, 0xfe, 0x27, 0x0b, 0x28, 0xd5, 0x7d, 0x1b, 0x9c, 0x8a, 0x47, 0xe1, 0xa6, 0x2e, 0x3e, 0x22, - 0xb4, 0x40, 0x39, 0xaa, 0x8a, 0x4d, 0x19, 0x11, 0x27, 0xec, 0xa6, 0x2e, 0x7a, 0x9a, 0x03, 0x9d, 0x3a, 0x0c, 0x1c, - 0x50, 0x13, 0x25, 0xa2, 0xd8, 0x2d, 0xe8, 0x9e, 0xe6, 0x58, 0x89, 0x67, 0xb2, 0x74, 0x90, 0x75, 0x22, 0x4d, 0xa8, - 0xdc, 0xd5, 0x55, 0x47, 0xa5, 0x52, 0x37, 0xbc, 0x4c, 0x35, 0xe3, 0xef, 0xd2, 0xfc, 0x89, 0x65, 0xbf, 0x6c, 0xfd, - 0x56, 0xab, 0xbd, 0xb1, 0x7a, 0x54, 0xb2, 0xe6, 0x38, 0x9b, 0x90, 0x94, 0x3e, 0x61, 0xbb, 0x99, 0x74, 0xad, 0x03, - 0x4f, 0x82, 0xcb, 0xa1, 0x27, 0xa0, 0x62, 0xd0, 0xc4, 0xdb, 0x5d, 0xa0, 0x1e, 0x81, 0x67, 0xa0, 0x7c, 0xa2, 0xd6, - 0x01, 0x3f, 0xaf, 0xb5, 0x3c, 0x65, 0x84, 0x61, 0xb5, 0xb3, 0x68, 0x39, 0x38, 0xef, 0x14, 0x81, 0x6b, 0x57, 0x02, - 0xcf, 0x87, 0xea, 0xbd, 0x10, 0x30, 0xdc, 0x3f, 0x15, 0x2a, 0x9b, 0xdd, 0x0c, 0xe7, 0x51, 0xe3, 0xf4, 0x40, 0x7b, - 0xdb, 0xb5, 0x1e, 0xea, 0x5d, 0xb7, 0x73, 0x5b, 0xe9, 0xde, 0xaf, 0x9d, 0x4c, 0xba, 0x80, 0xd6, 0xe6, 0xb3, 0xef, - 0xec, 0x4a, 0xeb, 0xa6, 0xe7, 0xec, 0xc1, 0xd6, 0x2d, 0xd1, 0xb9, 0x20, 0x9a, 0xfc, 0x7e, 0xe0, 0x59, 0xdb, 0x8e, - 0x7e, 0x9b, 0x76, 0x6c, 0x73, 0x0f, 0x75, 0xaf, 0xa0, 0xd6, 0x1b, 0x9a, 0xf7, 0xcf, 0x5c, 0xdb, 0x8e, 0xaf, 0x7e, - 0x5d, 0x77, 0xb8, 0xce, 0x9b, 0xe0, 0xb8, 0xe9, 0xda, 0x56, 0x3b, 0xfb, 0xb9, 0xbb, 0xb7, 0x16, 0x51, 0x98, 0x65, - 0x3f, 0x17, 0xc5, 0x9f, 0x95, 0xbe, 0x23, 0xd0, 0xd1, 0x9d, 0x17, 0x75, 0xba, 0xdc, 0xbd, 0x27, 0x8c, 0x27, 0xaf, - 0x3e, 0x22, 0xba, 0xf5, 0x7d, 0xe6, 0x7e, 0x05, 0xb8, 0x11, 0xdc, 0x41, 0xb4, 0x77, 0x4b, 0x7d, 0x52, 0xab, 0xaf, - 0xf5, 0xda, 0x79, 0x7a, 0x7e, 0xd3, 0xb9, 0xfd, 0xee, 0x9b, 0xa3, 0xad, 0xf7, 0xb8, 0xb0, 0x56, 0x96, 0x9e, 0xaa, - 0x82, 0xbd, 0x59, 0x9e, 0xaa, 0x82, 0xc9, 0x03, 0xaf, 0xd9, 0x2f, 0x68, 0x70, 0xa5, 0xa3, 0x8d, 0xf7, 0x44, 0x0d, - 0xdc, 0xa2, 0xb0, 0x74, 0xf8, 0x25, 0x37, 0x93, 0x6b, 0xdc, 0x5f, 0x2a, 0x72, 0xb1, 0xef, 0x9c, 0xd1, 0x9d, 0x99, - 0x75, 0xaf, 0x2a, 0x5c, 0x2d, 0xc8, 0xd5, 0x81, 0xad, 0x65, 0x17, 0x87, 0x1b, 0x16, 0x51, 0x80, 0x40, 0x4c, 0xaf, - 0xd4, 0xda, 0x1f, 0xd1, 0x20, 0xe4, 0x83, 0x81, 0x5f, 0x60, 0xb0, 0x2a, 0x50, 0xf8, 0x40, 0x91, 0xfc, 0x85, 0x27, - 0x60, 0x17, 0xcf, 0x00, 0xdd, 0x8a, 0xcd, 0x8a, 0x11, 0x22, 0x64, 0xb2, 0x9c, 0xd5, 0x74, 0x06, 0xf9, 0xd4, 0x17, - 0xdf, 0xd9, 0xaa, 0xd3, 0x79, 0x5b, 0x53, 0xe5, 0xd4, 0xa1, 0xd0, 0xdd, 0x4d, 0xdd, 0xb9, 0x75, 0x91, 0xa7, 0x0e, - 0x21, 0x57, 0x2a, 0x56, 0x62, 0x1a, 0x6a, 0x9e, 0xa4, 0x19, 0xf5, 0x57, 0x7b, 0xbf, 0xd7, 0x28, 0x9c, 0xf2, 0xa7, - 0x63, 0x50, 0x85, 0xab, 0x1a, 0xe2, 0x58, 0xaa, 0xe2, 0x91, 0x0d, 0x02, 0xcd, 0xab, 0x5b, 0x95, 0x34, 0x21, 0x93, - 0x1b, 0xe1, 0x53, 0x93, 0x52, 0x9e, 0xa6, 0x4d, 0x5a, 0x29, 0x52, 0x07, 0x1f, 0xd4, 0xa9, 0xc6, 0x73, 0xb3, 0x7a, - 0x0a, 0x60, 0xc6, 0xf9, 0x15, 0xbf, 0x54, 0x5c, 0x46, 0x6d, 0x65, 0x26, 0xed, 0x4f, 0x8e, 0xc6, 0x46, 0x5d, 0x4e, - 0x95, 0x79, 0xc5, 0xa0, 0x4f, 0xbf, 0xd6, 0xe7, 0x1f, 0x30, 0x58, 0xf3, 0x04, 0x76, 0x30, 0x51, 0x29, 0xef, 0x23, - 0x20, 0xbe, 0x4e, 0xd2, 0xdb, 0x04, 0x52, 0xa4, 0x7f, 0xe9, 0x92, 0xa7, 0x0e, 0x63, 0x03, 0x31, 0x66, 0xc5, 0xcc, - 0xe8, 0x7f, 0x70, 0x97, 0xf4, 0x27, 0x21, 0x00, 0x6e, 0xa2, 0x29, 0x74, 0xea, 0x3c, 0xb9, 0xc8, 0x83, 0xe5, 0x85, - 0x87, 0x56, 0x8c, 0x78, 0xf0, 0xd7, 0xa7, 0x21, 0x82, 0x98, 0x63, 0x8a, 0xa7, 0x5f, 0x18, 0xfd, 0x25, 0xb8, 0xc4, - 0x08, 0x42, 0x77, 0xef, 0x1c, 0x86, 0x70, 0xb3, 0x07, 0x19, 0xd4, 0x1f, 0xea, 0x90, 0xa8, 0xe1, 0x2f, 0x95, 0x07, - 0xfd, 0x5f, 0x67, 0xc2, 0x52, 0xfb, 0xe9, 0xe9, 0x00, 0x2a, 0x78, 0x5f, 0xf1, 0x36, 0x22, 0xbe, 0x4f, 0xfc, 0x38, - 0x1e, 0x6c, 0x1e, 0x6f, 0xc0, 0x5a, 0xf7, 0x2c, 0x37, 0xd6, 0x55, 0xc2, 0x06, 0x02, 0xbe, 0xc6, 0xb4, 0xf6, 0xbc, - 0x76, 0xbb, 0x07, 0x7f, 0xf5, 0x2f, 0x42, 0x06, 0x4c, 0x9c, 0xbe, 0xcf, 0x9c, 0xac, 0xd1, 0x45, 0x26, 0xd3, 0x87, - 0x4e, 0xfa, 0x46, 0xa7, 0xfb, 0x4e, 0xf8, 0x47, 0xc5, 0x2c, 0x3e, 0xdc, 0xd2, 0x57, 0x9a, 0x14, 0x77, 0xc0, 0xca, - 0xe6, 0x41, 0x41, 0xa8, 0x73, 0x11, 0x7d, 0x63, 0xca, 0xb7, 0x84, 0x9a, 0x7d, 0x63, 0x49, 0x29, 0xdd, 0x6b, 0xe8, - 0x65, 0x5a, 0xeb, 0xb7, 0x51, 0x82, 0x31, 0xd1, 0xf1, 0xe4, 0x65, 0x3c, 0x56, 0xde, 0xc7, 0xe3, 0x46, 0x2a, 0xe4, - 0x01, 0x88, 0x40, 0xc5, 0xf8, 0xd3, 0x95, 0x27, 0x27, 0xbd, 0x30, 0x5e, 0x85, 0x52, 0x50, 0x18, 0xd0, 0x15, 0x48, - 0x01, 0x8f, 0xda, 0x13, 0x9d, 0x85, 0x5d, 0xc2, 0x3d, 0xba, 0x09, 0x18, 0xeb, 0xf3, 0x2f, 0x80, 0xe6, 0x2e, 0xdc, - 0xe1, 0xc5, 0x00, 0xb5, 0xa9, 0x57, 0x77, 0x1f, 0xd7, 0xea, 0x1c, 0x0e, 0xc1, 0xc1, 0x6a, 0x10, 0xc1, 0xe9, 0x7c, - 0xea, 0x68, 0x96, 0x05, 0xa8, 0x9c, 0x2c, 0x37, 0xf2, 0xe6, 0xd1, 0xa2, 0x57, 0xf7, 0xbd, 0x65, 0x5a, 0x56, 0x75, - 0x90, 0xb1, 0x2c, 0xac, 0x00, 0x57, 0x87, 0xd6, 0x0f, 0xc2, 0x65, 0xe1, 0xfc, 0x81, 0x10, 0xc4, 0xee, 0xd5, 0xb6, - 0xe4, 0xb9, 0x9a, 0xc3, 0x8f, 0x9f, 0xb0, 0x35, 0x97, 0xa8, 0x93, 0xce, 0x44, 0x00, 0x62, 0x4f, 0xcd, 0x2a, 0xba, - 0x06, 0x92, 0x3a, 0xcd, 0x2a, 0xba, 0xa6, 0x66, 0x1b, 0xe3, 0x40, 0x3e, 0x5a, 0xa5, 0x80, 0x7d, 0x37, 0x1d, 0x07, - 0xab, 0xc7, 0xb1, 0xbc, 0x0e, 0xdd, 0x3e, 0xde, 0x28, 0x9f, 0x41, 0xdd, 0x6a, 0x63, 0x4c, 0x6c, 0x37, 0x5f, 0xce, - 0xf5, 0x9b, 0xc1, 0xd2, 0xb7, 0x83, 0xe6, 0x9c, 0xb2, 0x6f, 0x75, 0xd9, 0x2b, 0xbb, 0x6c, 0xea, 0xb9, 0xa3, 0xa2, - 0xd5, 0x18, 0xd0, 0x1b, 0x58, 0xb0, 0x3e, 0x17, 0x69, 0xb6, 0x2a, 0x55, 0x09, 0x78, 0x61, 0xac, 0xd8, 0xad, 0xdf, - 0xc8, 0x0c, 0x49, 0x98, 0xc7, 0x99, 0x78, 0x43, 0xf7, 0x5a, 0x98, 0x1c, 0xc7, 0x22, 0x99, 0x12, 0x3a, 0xa5, 0x3b, - 0xdb, 0xd0, 0xb9, 0x0a, 0xa3, 0x88, 0xd6, 0x4a, 0x2a, 0x8d, 0x04, 0xa6, 0x66, 0x80, 0x92, 0xb9, 0x02, 0xa7, 0x74, - 0xb9, 0xff, 0x1d, 0x89, 0x71, 0xe6, 0x8b, 0x92, 0x19, 0xd0, 0x2d, 0xbf, 0x2e, 0xd6, 0xad, 0x14, 0x19, 0x61, 0xde, - 0x1c, 0xb7, 0xd7, 0xf5, 0x21, 0x90, 0xab, 0x65, 0x8f, 0xa2, 0x71, 0x50, 0xe8, 0x70, 0xa9, 0x12, 0x60, 0x5f, 0x24, - 0x7e, 0x46, 0xd8, 0xd2, 0x1e, 0xc8, 0xed, 0xd1, 0x99, 0x30, 0xe7, 0x9c, 0x94, 0x65, 0xe7, 0xd2, 0x0c, 0x2e, 0x27, - 0xae, 0x04, 0x17, 0xe9, 0x6d, 0x7b, 0x9a, 0xb4, 0xb4, 0x7d, 0x6c, 0x38, 0x47, 0x43, 0xdb, 0xa0, 0x3b, 0xf6, 0x87, - 0xe6, 0x62, 0x11, 0x5b, 0x17, 0x8b, 0x61, 0x67, 0xf6, 0xa3, 0xc5, 0x02, 0xe4, 0x00, 0x70, 0xd4, 0x6d, 0xf8, 0x98, - 0x2d, 0x81, 0xd3, 0x6a, 0x9a, 0x4d, 0xbd, 0x0d, 0xaf, 0x1e, 0xab, 0x9e, 0x5e, 0xf2, 0xfc, 0xb1, 0x30, 0x63, 0xb1, - 0xe1, 0xf9, 0x63, 0xeb, 0xc8, 0xa9, 0x1e, 0x0b, 0x25, 0x5a, 0x17, 0xd0, 0x0c, 0xbc, 0xa6, 0x80, 0x11, 0x4b, 0x26, - 0x53, 0xaa, 0xc8, 0xe3, 0xde, 0x74, 0xa3, 0x06, 0x2f, 0x28, 0x1c, 0x02, 0x29, 0x9d, 0x7e, 0xf1, 0x84, 0xe9, 0xf7, - 0x2e, 0x9e, 0x74, 0xc8, 0xda, 0x86, 0xe9, 0x72, 0x33, 0x4c, 0x06, 0xa5, 0xff, 0xd8, 0x4c, 0x8c, 0x0b, 0x6b, 0x92, - 0x00, 0xe2, 0xdf, 0xd8, 0xef, 0x90, 0xc2, 0xcd, 0xfb, 0xcb, 0x61, 0xfc, 0xc0, 0xfb, 0x31, 0xb2, 0x27, 0x69, 0x86, - 0x58, 0x33, 0xa9, 0x90, 0xbb, 0xaf, 0xd6, 0x3f, 0x26, 0x76, 0x93, 0x3d, 0xb0, 0x00, 0xc4, 0xd6, 0xb4, 0xd5, 0x2d, - 0xef, 0xf7, 0x3d, 0x53, 0x04, 0xf8, 0x41, 0xf9, 0x47, 0x77, 0x86, 0x64, 0x50, 0x76, 0xdd, 0x10, 0xe2, 0x41, 0xd9, - 0x34, 0xed, 0xf5, 0xb6, 0x77, 0xe6, 0xb1, 0xba, 0x4e, 0x3b, 0x8b, 0xab, 0x45, 0x06, 0x69, 0xf5, 0x21, 0x3b, 0xce, - 0xec, 0xb3, 0xa3, 0xa5, 0xd2, 0xfd, 0x3e, 0x44, 0xc4, 0x1d, 0x65, 0x6d, 0xbf, 0xdd, 0x82, 0x6b, 0x38, 0x1a, 0x84, - 0xae, 0xec, 0xed, 0x32, 0xda, 0xb8, 0x10, 0xc7, 0x3d, 0xd3, 0xf9, 0x82, 0x2f, 0x8f, 0xd2, 0xce, 0x83, 0x53, 0x3d, - 0xd1, 0xe7, 0xa6, 0xbb, 0xca, 0xe4, 0x5a, 0x87, 0xd5, 0x18, 0xd4, 0x66, 0x61, 0x0b, 0x77, 0x61, 0x1b, 0x1d, 0xb4, - 0xf6, 0x65, 0xc1, 0x3f, 0x65, 0x00, 0xbe, 0xf4, 0x6c, 0xd9, 0xf6, 0x9a, 0xb4, 0x7a, 0x29, 0xa3, 0x10, 0x5b, 0xda, - 0x5e, 0x7d, 0x3a, 0xca, 0xc7, 0xcd, 0x09, 0xc5, 0x85, 0x1c, 0xe5, 0x07, 0xaf, 0x21, 0xea, 0x5a, 0xd7, 0x71, 0xb1, - 0xe8, 0x70, 0xe3, 0xaa, 0xdb, 0x6e, 0x5c, 0xaf, 0x10, 0x6f, 0x8d, 0x36, 0x29, 0xd4, 0xca, 0xd8, 0x11, 0xbc, 0x2c, - 0x1f, 0x0e, 0x99, 0x18, 0x0e, 0x25, 0x64, 0xea, 0x43, 0xf7, 0x86, 0xa6, 0x7d, 0x7e, 0xda, 0xfa, 0x11, 0x4b, 0x8d, - 0xa3, 0xd8, 0xf0, 0x4e, 0xdf, 0x79, 0x6c, 0x8d, 0x2b, 0xf9, 0x32, 0x98, 0xed, 0x0a, 0xaa, 0xad, 0xf1, 0x86, 0xbd, - 0x9c, 0xff, 0x5c, 0x49, 0x25, 0x7f, 0xfb, 0x33, 0x5c, 0xc3, 0x5b, 0x5b, 0x3a, 0x68, 0xaa, 0x59, 0xce, 0x72, 0x7d, - 0x2f, 0x38, 0xfe, 0xb8, 0x7b, 0x45, 0x30, 0xf8, 0x3d, 0x1d, 0x05, 0xb9, 0x58, 0xaa, 0x35, 0xa0, 0x20, 0x1d, 0xd9, - 0x31, 0x95, 0x05, 0x86, 0x01, 0xbc, 0x21, 0x03, 0xe4, 0x31, 0x85, 0xbb, 0xa1, 0xc2, 0x0b, 0x7f, 0xad, 0xc8, 0x2e, - 0x81, 0x6d, 0xcd, 0xf8, 0x98, 0xe1, 0x0e, 0x42, 0xfe, 0x11, 0xec, 0x96, 0xad, 0xd8, 0x0d, 0x5b, 0x30, 0x24, 0x1b, - 0xc7, 0x61, 0x8c, 0xf9, 0x78, 0x12, 0x5f, 0x89, 0x49, 0x3c, 0xe0, 0x11, 0x3a, 0x46, 0xac, 0x79, 0x3d, 0x8b, 0xe5, - 0x00, 0xb2, 0x5b, 0xae, 0x74, 0x40, 0x08, 0x8d, 0x0d, 0x2d, 0x79, 0x59, 0x18, 0x5c, 0xec, 0xd8, 0x67, 0x24, 0x92, - 0x71, 0x08, 0x16, 0xad, 0x6a, 0x60, 0x61, 0x62, 0x37, 0xbc, 0x98, 0xad, 0xe6, 0xf8, 0xcf, 0xe1, 0x80, 0x00, 0xd8, - 0xc1, 0xbe, 0x61, 0xb7, 0x11, 0x22, 0xbd, 0x2d, 0xf8, 0xad, 0xe5, 0xe9, 0xc2, 0xee, 0xf8, 0x35, 0x1f, 0xb3, 0xf3, - 0x57, 0x1e, 0x44, 0xce, 0x9e, 0x7f, 0x00, 0x34, 0xc4, 0x3b, 0x7e, 0x93, 0x7a, 0x15, 0xbb, 0x21, 0x0a, 0xc2, 0x1b, - 0x70, 0x06, 0xba, 0x83, 0x08, 0xd8, 0x6b, 0xbe, 0xc0, 0x58, 0xb1, 0xb3, 0x74, 0xe9, 0x61, 0x46, 0xa8, 0x3d, 0x9d, - 0x2f, 0x6b, 0x35, 0x09, 0x37, 0x57, 0xcb, 0xc9, 0x60, 0xb0, 0xf1, 0x77, 0x7c, 0x0d, 0x7c, 0x30, 0xe7, 0xaf, 0xbc, - 0x1d, 0x95, 0x0b, 0xff, 0x79, 0x9d, 0x25, 0xef, 0x7c, 0x76, 0x3d, 0xe0, 0x0b, 0xc0, 0x5b, 0x42, 0x07, 0xae, 0x3b, - 0x9f, 0x49, 0xbc, 0xb6, 0x6b, 0x7d, 0x8d, 0x40, 0x22, 0x5f, 0x00, 0x46, 0x4c, 0xcc, 0xef, 0x6b, 0x88, 0xc0, 0xd8, - 0x80, 0x6f, 0xab, 0xf6, 0x88, 0xdf, 0x72, 0x03, 0xf8, 0x95, 0xf9, 0xec, 0x9e, 0x87, 0xfa, 0x67, 0xe2, 0xb3, 0x37, - 0xfc, 0x11, 0x7f, 0xea, 0x49, 0x49, 0xba, 0x9c, 0x3d, 0x9a, 0xc3, 0xf5, 0x50, 0xca, 0xd3, 0x21, 0xfd, 0x6c, 0x0c, - 0x06, 0x10, 0x0a, 0x99, 0x6f, 0x3c, 0x60, 0x4d, 0x0a, 0xf1, 0x2f, 0xe0, 0xdb, 0x51, 0xc2, 0xe6, 0x1b, 0x6f, 0xeb, - 0x6b, 0x79, 0xf3, 0x8d, 0x77, 0xef, 0x53, 0x14, 0x60, 0x15, 0x94, 0xb2, 0xc0, 0x2a, 0x08, 0x1b, 0x6d, 0x84, 0x31, - 0x70, 0xf5, 0xae, 0x31, 0xd4, 0xf5, 0x1c, 0xb1, 0x6d, 0xa5, 0x6f, 0xc3, 0xb7, 0x90, 0x01, 0x1f, 0xbc, 0x2c, 0x4a, - 0xa2, 0xcf, 0xa9, 0x29, 0x92, 0xd6, 0x3d, 0xf7, 0x5b, 0xeb, 0x8e, 0xd6, 0x94, 0xfa, 0xc8, 0xd5, 0xf8, 0x70, 0xa8, - 0x9f, 0x0a, 0x2d, 0x12, 0x4c, 0x41, 0xe3, 0x1a, 0xb4, 0x05, 0x08, 0xfa, 0x3c, 0x40, 0xd6, 0x92, 0x62, 0xc1, 0xb7, - 0xbf, 0x42, 0x0c, 0x5e, 0x99, 0xde, 0xb9, 0x5c, 0x65, 0x24, 0x6c, 0x2f, 0xfc, 0x72, 0x58, 0xfb, 0x13, 0xa7, 0x16, - 0x96, 0x56, 0x73, 0x50, 0x3f, 0xb6, 0xe5, 0x38, 0x5d, 0xb5, 0xc8, 0xeb, 0x50, 0x5a, 0x4e, 0xef, 0xec, 0x9b, 0x2e, - 0x13, 0x6c, 0xec, 0x07, 0x54, 0x1d, 0x59, 0x0d, 0xbb, 0x2f, 0xd4, 0x17, 0x3d, 0x25, 0x13, 0x9a, 0x8f, 0x2a, 0x9a, - 0xe7, 0xd6, 0x37, 0x8f, 0xeb, 0x3f, 0xbd, 0x1c, 0x8a, 0x00, 0xc9, 0x2a, 0x2d, 0x96, 0x22, 0x67, 0x63, 0x3f, 0x1e, - 0x26, 0x99, 0x0a, 0x2f, 0x48, 0x47, 0x77, 0xbf, 0x71, 0x7f, 0xcb, 0x0d, 0x64, 0x85, 0x56, 0x6d, 0x30, 0x56, 0x8a, - 0x96, 0xc1, 0xfa, 0x6a, 0xdc, 0xef, 0x8b, 0xab, 0xf1, 0x54, 0x04, 0x35, 0x10, 0x17, 0x89, 0xa7, 0xe3, 0x69, 0x4d, - 0x2c, 0xa9, 0x5d, 0x81, 0x31, 0x7a, 0x5c, 0x15, 0xb5, 0x4f, 0xfd, 0x14, 0x42, 0x91, 0x6a, 0xcd, 0x1c, 0x6b, 0xdc, - 0x18, 0x11, 0x77, 0x58, 0xb9, 0x76, 0x6a, 0xaf, 0x03, 0xb0, 0xbc, 0x1a, 0x17, 0x84, 0x75, 0x72, 0xec, 0x5c, 0xc0, - 0x6a, 0x34, 0xa4, 0xda, 0x0d, 0xb7, 0x5e, 0x76, 0x7e, 0xf3, 0x65, 0x62, 0x6b, 0x23, 0xdc, 0x52, 0x40, 0x19, 0xe5, - 0x37, 0x96, 0x13, 0x76, 0xa7, 0x7a, 0x47, 0xaa, 0x76, 0xc4, 0x89, 0x0b, 0x58, 0x6e, 0x78, 0x6a, 0xf5, 0x4d, 0x0c, - 0x4e, 0x84, 0xaa, 0x95, 0x0e, 0x77, 0x32, 0x81, 0xb8, 0x5f, 0xdd, 0xd7, 0xbd, 0x12, 0xfc, 0x24, 0xe4, 0xf5, 0x5b, - 0xde, 0x01, 0x60, 0xc5, 0x87, 0xbc, 0x98, 0x16, 0x8e, 0xd6, 0x65, 0x50, 0x06, 0x88, 0xd0, 0x0c, 0x80, 0x4e, 0xae, - 0x0e, 0xa2, 0x34, 0x70, 0xc5, 0x1d, 0x22, 0xfc, 0x34, 0x7a, 0x9c, 0x3f, 0x0d, 0x1f, 0x57, 0xd3, 0xf0, 0x22, 0x0f, - 0xa2, 0x8b, 0x2a, 0x88, 0x1e, 0x57, 0x57, 0xe1, 0xe3, 0x7c, 0x1a, 0x5d, 0xe4, 0x41, 0x78, 0x51, 0x35, 0xf6, 0x5d, - 0xbb, 0xbb, 0x27, 0xe4, 0x6d, 0x57, 0x7f, 0xe4, 0x5c, 0xd9, 0x53, 0xa6, 0xe7, 0xe7, 0xb5, 0x5e, 0xa9, 0xdd, 0xe6, - 0x7a, 0x8d, 0x9a, 0xa9, 0x8f, 0xb2, 0xbf, 0xd9, 0xc6, 0xc2, 0xa3, 0x39, 0x84, 0x3e, 0x23, 0x2d, 0xe6, 0x1e, 0xe7, - 0x7a, 0xb3, 0x27, 0x85, 0x81, 0x11, 0x93, 0x4a, 0x46, 0x4e, 0x2f, 0x70, 0x11, 0xaa, 0x10, 0xc3, 0x5a, 0xba, 0xda, - 0x67, 0x5d, 0x7a, 0x03, 0x75, 0x4d, 0xb1, 0xaf, 0x21, 0x03, 0x2f, 0x9a, 0x5e, 0x06, 0x63, 0x40, 0x8e, 0xc0, 0x3b, - 0x3e, 0x5b, 0xc2, 0x81, 0xb9, 0x06, 0xe8, 0x9b, 0x07, 0x7d, 0x5d, 0x6e, 0xf9, 0x5a, 0xf5, 0xcd, 0x74, 0x3d, 0x52, - 0xca, 0x8f, 0x15, 0xbf, 0xbd, 0x78, 0xc2, 0x6e, 0xb8, 0x46, 0x45, 0x79, 0xae, 0x17, 0xeb, 0x1d, 0x70, 0xd5, 0x3d, - 0x87, 0xdb, 0x2c, 0x1e, 0xbb, 0xf2, 0x80, 0x65, 0x5b, 0x76, 0xcf, 0xde, 0xb0, 0x47, 0xec, 0x3d, 0xfb, 0xc4, 0xbe, - 0xb2, 0x1a, 0x21, 0xca, 0x4b, 0x25, 0xe5, 0xf9, 0x0b, 0x7e, 0x23, 0x6d, 0x8f, 0x12, 0x96, 0xec, 0xde, 0xb6, 0xd3, - 0x0c, 0x37, 0xec, 0x11, 0x5f, 0x0c, 0x57, 0xec, 0x13, 0x64, 0x43, 0xa1, 0x78, 0xb0, 0x62, 0x35, 0x5c, 0x61, 0x29, - 0x83, 0x3e, 0x0d, 0x4b, 0x4b, 0x58, 0x34, 0x85, 0xa2, 0x14, 0xfd, 0x89, 0xd7, 0x84, 0x9d, 0x56, 0x63, 0x21, 0xf2, - 0x43, 0xc3, 0x15, 0xbb, 0xe7, 0x8b, 0xc1, 0x8a, 0x3d, 0xd2, 0x36, 0xa2, 0xc1, 0xc6, 0x2d, 0x8e, 0xc0, 0xac, 0x74, - 0x61, 0x52, 0xa0, 0xde, 0xda, 0x37, 0xc1, 0x0d, 0x7b, 0x83, 0xf5, 0x7b, 0x8f, 0x45, 0xa3, 0xcc, 0x3f, 0x58, 0xb1, - 0xaf, 0x5c, 0x62, 0xa8, 0xb9, 0xe5, 0x49, 0xc7, 0x50, 0x5d, 0x20, 0x5d, 0x11, 0xde, 0x73, 0x7a, 0x91, 0x7d, 0xc5, - 0x32, 0xe8, 0x2b, 0xc3, 0x15, 0xdb, 0x62, 0xed, 0xde, 0x18, 0xe3, 0x96, 0x55, 0x3d, 0x09, 0x0a, 0x8c, 0xb2, 0x4a, - 0x69, 0xb9, 0x38, 0x62, 0xd9, 0xd4, 0x51, 0x83, 0xda, 0x30, 0xa0, 0x0f, 0x46, 0x7f, 0xf1, 0xf5, 0xbb, 0xef, 0xbc, - 0x52, 0xdf, 0x7c, 0x9f, 0x3b, 0xde, 0x95, 0x25, 0x7a, 0x57, 0xfe, 0xc6, 0xcb, 0xd9, 0xf3, 0xf9, 0x44, 0xd7, 0x92, - 0x36, 0x19, 0x72, 0x37, 0x9d, 0x3d, 0xef, 0xf0, 0xb7, 0xfc, 0xcd, 0xf7, 0x1b, 0xab, 0x8f, 0xd5, 0x77, 0x75, 0xf7, - 0xde, 0x0f, 0x36, 0x8d, 0x53, 0xf1, 0xdd, 0xe9, 0x8a, 0x63, 0x3b, 0x6b, 0xed, 0x9d, 0xf9, 0x3f, 0x5c, 0xeb, 0x2d, - 0x8e, 0xdd, 0x1b, 0xbe, 0x1d, 0x6e, 0xec, 0x61, 0x90, 0xdf, 0x97, 0x8a, 0xe3, 0xac, 0xe6, 0xcf, 0xbc, 0x4e, 0x49, - 0x16, 0x50, 0x8d, 0x5e, 0x1b, 0x69, 0xe8, 0x92, 0x99, 0x98, 0x86, 0xf8, 0x22, 0x03, 0x74, 0x2e, 0x10, 0xcf, 0xee, - 0xf8, 0x78, 0x72, 0x77, 0x15, 0x4f, 0xee, 0x06, 0xfc, 0xb5, 0x69, 0x41, 0x7b, 0xc1, 0xdd, 0xf9, 0xec, 0x37, 0x5e, - 0xd8, 0x4b, 0xf2, 0xb9, 0xcf, 0xde, 0x0a, 0x77, 0x95, 0x3e, 0xf7, 0xd9, 0x57, 0xc1, 0x7f, 0x1b, 0x69, 0xb2, 0x0c, - 0xf6, 0xb5, 0xe6, 0xbf, 0x8d, 0x90, 0xf5, 0x83, 0x7d, 0x16, 0xfc, 0x2d, 0xf8, 0x7f, 0x57, 0x09, 0x5a, 0xc6, 0x3f, - 0xd7, 0xea, 0xe7, 0x3b, 0x19, 0x9b, 0x03, 0x6f, 0x42, 0x2b, 0xe8, 0xcd, 0x9b, 0x5a, 0xfe, 0x24, 0x2e, 0x8e, 0x54, - 0x3d, 0x35, 0x1c, 0xb4, 0x58, 0xcc, 0xa2, 0x3e, 0x4a, 0xa7, 0xf2, 0x26, 0xd7, 0x3c, 0x96, 0x16, 0xe6, 0x3b, 0x08, - 0x07, 0xbe, 0xb6, 0x61, 0x0a, 0x76, 0x1c, 0x37, 0x83, 0x6b, 0x06, 0x10, 0x92, 0xd9, 0x74, 0xcb, 0xdf, 0xf0, 0xf7, - 0xfc, 0x2b, 0xdf, 0x05, 0xf7, 0xfc, 0x11, 0xff, 0xc4, 0xeb, 0x9a, 0xef, 0xd8, 0x52, 0x42, 0x9e, 0xd6, 0xdb, 0xcb, - 0x60, 0xcb, 0xea, 0xdd, 0x65, 0x70, 0xcf, 0xea, 0xed, 0x93, 0xe0, 0x0d, 0xab, 0x77, 0x4f, 0x82, 0x47, 0x6c, 0x7b, - 0x19, 0xbc, 0x67, 0xbb, 0xcb, 0xe0, 0x13, 0xdb, 0x3e, 0x09, 0xbe, 0xb2, 0xdd, 0x93, 0xa0, 0x56, 0x48, 0x0f, 0x5f, - 0x85, 0x64, 0x3a, 0xf9, 0x5a, 0x33, 0xc3, 0xaa, 0x1b, 0x7c, 0x16, 0xd6, 0x2f, 0xaa, 0x65, 0xf0, 0xb9, 0x66, 0xba, - 0xcd, 0x81, 0x10, 0x4c, 0xb7, 0x38, 0xb8, 0xa1, 0x27, 0xa6, 0x5d, 0x41, 0x2a, 0x58, 0x57, 0x4b, 0x83, 0x45, 0xdd, - 0xb4, 0x4e, 0x66, 0xc7, 0x3b, 0x31, 0xee, 0xf0, 0x4e, 0x5c, 0xb0, 0x65, 0xd3, 0xe9, 0xaa, 0x73, 0xfa, 0x3c, 0xd0, - 0x47, 0x80, 0xde, 0xfb, 0x2b, 0xe9, 0x41, 0x53, 0x34, 0x3c, 0x57, 0xba, 0xe3, 0xd6, 0x7e, 0x1f, 0x5a, 0xfb, 0x3d, - 0x93, 0x8a, 0xb4, 0x88, 0x45, 0x65, 0x51, 0x55, 0xc8, 0x27, 0x1e, 0x64, 0x5a, 0xab, 0x96, 0x30, 0x52, 0x67, 0x02, - 0x26, 0x7d, 0x41, 0x87, 0x41, 0x4e, 0x76, 0x05, 0xb6, 0xe4, 0x9b, 0x41, 0xc2, 0xd6, 0x3c, 0x9e, 0x0e, 0x93, 0x60, - 0xc9, 0x6e, 0xf9, 0xb0, 0x5b, 0x2c, 0x58, 0xa9, 0x30, 0x26, 0x7d, 0x7d, 0x3a, 0xda, 0xdd, 0x79, 0x6f, 0x95, 0xc6, - 0x71, 0x26, 0x50, 0xe7, 0x56, 0xe9, 0x6d, 0x7e, 0xeb, 0xec, 0xea, 0x6b, 0xb5, 0xcb, 0x83, 0xc0, 0xf0, 0x1b, 0x10, - 0xed, 0x10, 0xef, 0x1d, 0xd4, 0x18, 0xe9, 0x96, 0xcc, 0xba, 0xaf, 0xec, 0x7d, 0x7d, 0x6b, 0xb6, 0xea, 0xff, 0xb4, - 0x08, 0xda, 0xcb, 0x65, 0xef, 0xbf, 0x36, 0xaf, 0xfe, 0xde, 0xf1, 0xea, 0xc6, 0x9f, 0xdc, 0xf3, 0xd7, 0x18, 0x9d, - 0x80, 0x89, 0x6c, 0xc7, 0x5f, 0x8f, 0xb6, 0x8d, 0x53, 0x9e, 0xdc, 0xcb, 0xff, 0xaf, 0x14, 0x68, 0xef, 0xe6, 0x95, - 0xbd, 0x29, 0x6e, 0x79, 0xc7, 0x5e, 0xbe, 0xb4, 0xf6, 0x44, 0x83, 0x50, 0xf2, 0x9a, 0xbb, 0x41, 0xd1, 0xb0, 0x27, - 0x3e, 0xe7, 0xd5, 0xec, 0xf5, 0x7c, 0xb2, 0xe5, 0xc7, 0x3b, 0xe2, 0xeb, 0x8e, 0x1d, 0xf1, 0xb9, 0x3f, 0x58, 0x36, - 0xdf, 0xea, 0xd5, 0xce, 0x9d, 0xdc, 0xa9, 0xf4, 0x8e, 0x1f, 0xef, 0xe3, 0xc3, 0xff, 0xb8, 0xd2, 0xbb, 0xef, 0xae, - 0xb4, 0x5d, 0xe5, 0xee, 0xce, 0x37, 0x1d, 0xdf, 0xc8, 0x5a, 0x63, 0xb8, 0x99, 0x51, 0x30, 0xc2, 0xb4, 0x85, 0x69, - 0x1a, 0x44, 0x96, 0x62, 0x11, 0x12, 0x35, 0x4a, 0xe7, 0x44, 0x9f, 0x05, 0x9d, 0x82, 0x2e, 0x6e, 0xf4, 0x37, 0x7c, - 0xcc, 0x16, 0xc6, 0x65, 0xf3, 0xe6, 0x6a, 0x31, 0x19, 0x0c, 0x6e, 0xfc, 0xfd, 0x1d, 0x0f, 0x67, 0x37, 0x73, 0x76, - 0xcd, 0xef, 0x68, 0x3d, 0x4d, 0x54, 0xe3, 0x8b, 0x87, 0x24, 0xb0, 0x1b, 0xdf, 0x9f, 0x58, 0x44, 0xb0, 0xf6, 0x8d, - 0xf3, 0xc6, 0x1f, 0x48, 0xb3, 0xb4, 0xdc, 0xda, 0x1f, 0x3d, 0xac, 0xa1, 0xb8, 0x01, 0x21, 0xe3, 0x91, 0xad, 0x72, - 0xf8, 0xc4, 0x3f, 0x78, 0xd7, 0xfe, 0xf4, 0x5a, 0x07, 0xdf, 0x4c, 0xd4, 0xb9, 0xf4, 0xe9, 0xe2, 0x09, 0xfb, 0x8d, - 0xbf, 0x96, 0x67, 0xca, 0x5b, 0x21, 0xa7, 0xed, 0x47, 0x24, 0x71, 0xa2, 0xa3, 0xe2, 0xab, 0x9b, 0x48, 0xa0, 0x10, - 0xb0, 0x2b, 0x7c, 0xad, 0xf9, 0xfd, 0xa4, 0x9c, 0x7a, 0x3b, 0x20, 0x79, 0xe5, 0xb6, 0x22, 0xfa, 0x86, 0x73, 0xbe, - 0x18, 0x5e, 0x4e, 0xbf, 0x76, 0xfb, 0xf6, 0xa8, 0xb0, 0x36, 0x15, 0xf1, 0x76, 0x83, 0x41, 0x58, 0x27, 0x33, 0xcb, - 0x5c, 0xf2, 0xa5, 0xaf, 0xb5, 0x99, 0x7b, 0x4c, 0xef, 0x38, 0xd3, 0x0c, 0x19, 0x7d, 0x81, 0x99, 0xe9, 0x70, 0xb8, - 0x3d, 0xc7, 0xf2, 0xf8, 0xf0, 0xd3, 0xe3, 0xf7, 0x83, 0xf7, 0x18, 0xc2, 0x65, 0x85, 0x85, 0x7c, 0xe5, 0xc3, 0xac, - 0x6e, 0x5d, 0x3b, 0x2e, 0x9e, 0x0c, 0x9f, 0x43, 0xde, 0xa0, 0xeb, 0xa1, 0x29, 0xa2, 0x55, 0x7e, 0x47, 0xd1, 0x27, - 0x4a, 0x0e, 0x3a, 0x9e, 0x40, 0xed, 0x90, 0x0b, 0xf7, 0xeb, 0x63, 0x0e, 0x8a, 0x0e, 0x2c, 0xb5, 0xdf, 0x3f, 0x7f, - 0x4d, 0x84, 0xd2, 0x30, 0xde, 0xcf, 0xc3, 0xe8, 0xcf, 0xb8, 0x2c, 0xd6, 0x70, 0xc4, 0x0e, 0xe0, 0x73, 0x8f, 0xf5, - 0x35, 0xec, 0xd6, 0xf7, 0xfd, 0xc0, 0xdb, 0xf2, 0x37, 0xec, 0x2b, 0xf7, 0x2e, 0x87, 0x9f, 0xfc, 0xc7, 0xef, 0x41, - 0x7e, 0x42, 0x9c, 0x14, 0x0c, 0x89, 0xed, 0x28, 0x46, 0xad, 0xc3, 0xcf, 0x35, 0xc4, 0x6a, 0xbd, 0x46, 0xea, 0x2e, - 0x48, 0x7f, 0xaf, 0x90, 0xfd, 0x84, 0xc0, 0x6a, 0x92, 0x3e, 0x05, 0x26, 0xf1, 0x4d, 0x0d, 0x09, 0xa4, 0x69, 0x81, - 0x18, 0x1c, 0x28, 0x3e, 0x15, 0xfc, 0xeb, 0xf0, 0x33, 0xc9, 0x7f, 0x8b, 0x9a, 0x8f, 0xe1, 0x6f, 0x18, 0x9a, 0x49, - 0x75, 0x9f, 0xd6, 0x10, 0x11, 0x0d, 0xa7, 0x5e, 0x58, 0x09, 0x75, 0x32, 0x04, 0xa9, 0x18, 0x72, 0x21, 0x2e, 0x9e, - 0x4c, 0x6e, 0x4a, 0x11, 0xfe, 0x39, 0xc1, 0x67, 0x72, 0xa5, 0xc9, 0x67, 0xf4, 0xa4, 0x91, 0x05, 0xdc, 0xcb, 0xf7, - 0x65, 0xaf, 0x06, 0x8b, 0x7a, 0xc8, 0x6f, 0x6a, 0xf7, 0x7d, 0x39, 0x27, 0xe8, 0x91, 0xfd, 0x80, 0xe6, 0x60, 0xa0, - 0x66, 0x20, 0x65, 0x08, 0x6e, 0xe0, 0xd2, 0xef, 0xa9, 0x82, 0x7c, 0xf9, 0xbd, 0xcf, 0x42, 0x06, 0xae, 0x2c, 0x08, - 0x53, 0x2e, 0x15, 0x52, 0xe0, 0xb8, 0xa9, 0x07, 0x9f, 0x35, 0x3a, 0x89, 0x04, 0x9f, 0x12, 0x90, 0x24, 0x2d, 0x0f, - 0x24, 0x8d, 0x98, 0x0e, 0xc4, 0x85, 0xd2, 0x34, 0x2b, 0x29, 0xe2, 0x10, 0xbb, 0xea, 0x35, 0x12, 0x9e, 0x05, 0x8f, - 0x18, 0xac, 0x1d, 0x29, 0x5a, 0x7c, 0x35, 0xa6, 0x63, 0x1d, 0x36, 0x74, 0x2b, 0x8b, 0xfb, 0x4d, 0x52, 0xa7, 0x91, - 0xb8, 0xf2, 0x56, 0xc8, 0x9f, 0xff, 0x52, 0x22, 0x90, 0xde, 0xd5, 0x40, 0x0c, 0x82, 0x1f, 0xa0, 0xff, 0x80, 0x45, - 0x0e, 0x82, 0x52, 0x5d, 0x86, 0x79, 0x95, 0x51, 0x81, 0xb3, 0x1d, 0xdb, 0xce, 0x99, 0xaa, 0x5b, 0xf0, 0x59, 0x18, - 0x86, 0xb4, 0xb3, 0x55, 0x73, 0x72, 0xab, 0x37, 0x50, 0xcf, 0x24, 0x8e, 0xd4, 0x52, 0x1c, 0x69, 0x6b, 0xee, 0xd3, - 0xa5, 0xd7, 0x2d, 0x2f, 0x68, 0xb8, 0x00, 0xbd, 0x28, 0xdd, 0x75, 0x3e, 0xa1, 0xd0, 0x65, 0x35, 0xae, 0x86, 0xa2, - 0x0e, 0xe5, 0x18, 0x6b, 0x7f, 0xae, 0xe4, 0xf9, 0x1d, 0x58, 0x8f, 0xd0, 0xf0, 0x55, 0xa9, 0x83, 0xd8, 0x7e, 0xa2, - 0x77, 0x9d, 0x4a, 0xfd, 0x0d, 0x00, 0x03, 0xa7, 0x8e, 0x87, 0xfa, 0xa8, 0x9d, 0x42, 0xb6, 0x73, 0x6f, 0x89, 0x51, - 0xb9, 0x12, 0x9e, 0x2a, 0x2d, 0x4f, 0x29, 0xab, 0xbe, 0x16, 0xdc, 0xca, 0xee, 0xb3, 0x01, 0x64, 0xb4, 0x41, 0x81, - 0x3c, 0xa3, 0xb6, 0xc6, 0x83, 0x54, 0xd3, 0x2c, 0x71, 0x0c, 0x1f, 0x14, 0x69, 0x56, 0x81, 0xc5, 0xcb, 0x5c, 0x32, - 0x07, 0x05, 0xcb, 0xf5, 0x66, 0x33, 0xcd, 0x54, 0x5f, 0xe4, 0xf6, 0x46, 0xe3, 0x65, 0xfa, 0x6f, 0x96, 0x0c, 0x78, - 0x74, 0xf1, 0xc4, 0x0f, 0x20, 0x4d, 0x52, 0x3c, 0x40, 0x12, 0x6c, 0x0f, 0x76, 0xb1, 0xc3, 0xb0, 0x55, 0xac, 0xec, - 0xc9, 0xd3, 0xe5, 0x0e, 0x4d, 0xb9, 0x04, 0x97, 0x9c, 0x98, 0xcb, 0xa9, 0xef, 0x4b, 0xd6, 0x1b, 0x8a, 0x53, 0x36, - 0x4d, 0x40, 0x49, 0xa0, 0xdd, 0x82, 0xff, 0xc2, 0xa7, 0x86, 0x4e, 0x0b, 0xb0, 0xd4, 0x76, 0x03, 0xfe, 0x0b, 0xfd, - 0x62, 0xbb, 0x8b, 0xfa, 0x81, 0x79, 0xb0, 0x37, 0x8b, 0x2b, 0x63, 0xc0, 0x49, 0xe2, 0x4a, 0xf3, 0xc8, 0xf5, 0x83, - 0xa2, 0x4f, 0x97, 0xb5, 0x03, 0x67, 0x8a, 0x0b, 0xab, 0xd4, 0x26, 0xe9, 0xb5, 0xdf, 0x52, 0x13, 0x6f, 0xa2, 0xa4, - 0x2a, 0x6c, 0x87, 0xb4, 0x7f, 0x49, 0x39, 0x53, 0xc5, 0x1d, 0xa2, 0x27, 0xbb, 0x89, 0xab, 0xc0, 0x0b, 0xab, 0x8a, - 0x8d, 0x50, 0x9b, 0x91, 0xe5, 0x04, 0x4e, 0xf7, 0x58, 0x5d, 0xf0, 0xb1, 0x5d, 0xcd, 0x2e, 0x58, 0xc9, 0xd6, 0x4c, - 0xba, 0xcf, 0xdb, 0x31, 0x17, 0xf2, 0x4a, 0x2f, 0x8b, 0x56, 0x40, 0x7b, 0x10, 0x38, 0xfc, 0x5c, 0xd3, 0x3d, 0x7a, - 0xb6, 0xd9, 0xa6, 0x36, 0x1b, 0x5b, 0x8b, 0x10, 0x32, 0x10, 0x0d, 0x7d, 0x21, 0x67, 0x14, 0xf9, 0x2a, 0x2d, 0xd7, - 0x6a, 0x63, 0x95, 0xf1, 0x02, 0x13, 0x41, 0x86, 0xb3, 0xf0, 0x0e, 0x3d, 0xad, 0x47, 0x9a, 0x62, 0x12, 0x9c, 0x74, - 0xf1, 0x17, 0x60, 0x43, 0x79, 0x92, 0x9b, 0x03, 0x72, 0x00, 0x95, 0x4b, 0x51, 0x2a, 0x65, 0xf0, 0x6b, 0x75, 0x47, - 0xb6, 0x55, 0xff, 0x9d, 0x06, 0x32, 0xb8, 0x03, 0x7d, 0xdb, 0x0b, 0xad, 0x1d, 0xed, 0x5c, 0xd9, 0x9a, 0xb6, 0x65, - 0x9a, 0xc7, 0xc8, 0x62, 0x03, 0xc8, 0x27, 0xd2, 0x39, 0x10, 0x79, 0x4d, 0x34, 0xde, 0xd9, 0x53, 0x3e, 0x9e, 0x8a, - 0x87, 0xe4, 0xbd, 0xca, 0xf7, 0xcd, 0xbd, 0x3e, 0x18, 0x63, 0xdf, 0x82, 0x32, 0xf1, 0xc1, 0x6a, 0x6b, 0x5d, 0x62, - 0xbd, 0x55, 0x9a, 0x44, 0x37, 0x5c, 0x41, 0xc7, 0x91, 0xb8, 0x41, 0x0c, 0x8e, 0x19, 0xaf, 0xad, 0xb2, 0xf4, 0x15, - 0x96, 0xb9, 0x8e, 0x59, 0x32, 0x64, 0x52, 0xe7, 0x89, 0x82, 0x27, 0x3f, 0x4f, 0x48, 0x46, 0x44, 0xcd, 0xb6, 0x1c, - 0xa5, 0xdc, 0xb4, 0x80, 0xcb, 0x8c, 0x0c, 0xe0, 0x9b, 0x34, 0x01, 0x28, 0x97, 0x2f, 0x41, 0x2a, 0x0d, 0x11, 0x5c, - 0xb3, 0xbd, 0x64, 0x74, 0xe3, 0x68, 0x1d, 0x54, 0x49, 0xe6, 0x0e, 0xce, 0xed, 0x2c, 0x52, 0xea, 0xcd, 0x47, 0x18, - 0x76, 0xf2, 0x3e, 0xac, 0x13, 0xfc, 0x36, 0xa0, 0x26, 0x7d, 0x2a, 0xbc, 0x68, 0x04, 0x68, 0xea, 0x3b, 0x55, 0xc6, - 0xa7, 0xc2, 0xcb, 0x46, 0x5b, 0x96, 0x51, 0x0a, 0xd5, 0x05, 0xb3, 0x5b, 0xd3, 0x85, 0x98, 0x57, 0xd5, 0x40, 0x1b, - 0xe4, 0x76, 0x1d, 0x33, 0xa0, 0x51, 0xdb, 0x95, 0x47, 0x16, 0xe0, 0xd6, 0x4c, 0x04, 0x46, 0xce, 0xbf, 0xcb, 0xaf, - 0x55, 0x38, 0x4f, 0xbf, 0x1f, 0x7a, 0xfb, 0x6d, 0x10, 0x8d, 0xb6, 0x97, 0x6c, 0x17, 0x44, 0xa3, 0xdd, 0x65, 0xc3, - 0xe8, 0xf7, 0x13, 0xfa, 0xfd, 0xa4, 0x01, 0x55, 0x89, 0x30, 0x11, 0xf7, 0xfa, 0x8d, 0x5a, 0xbe, 0x52, 0xeb, 0x77, - 0x6a, 0xf9, 0x52, 0x0d, 0x6f, 0xed, 0x49, 0x24, 0x88, 0x2c, 0x8d, 0xcd, 0xbd, 0x64, 0x4b, 0xb5, 0x54, 0x3a, 0x46, - 0x95, 0x11, 0xb5, 0x74, 0x36, 0xc7, 0x8a, 0x91, 0x76, 0x0e, 0x4a, 0x06, 0x64, 0x5a, 0x5c, 0xd5, 0x98, 0x6e, 0x56, - 0xb4, 0xc4, 0x64, 0x84, 0x95, 0x6d, 0x79, 0xbb, 0x49, 0xd5, 0x74, 0x4e, 0x6e, 0x6e, 0x95, 0x72, 0x73, 0x2b, 0x78, - 0xfe, 0x0d, 0xdd, 0x72, 0xc9, 0xb5, 0x97, 0xd9, 0xb4, 0x50, 0xba, 0x65, 0x5c, 0x83, 0xad, 0x7d, 0x13, 0xc8, 0x32, - 0x1f, 0x28, 0x6a, 0x6c, 0x2f, 0x1a, 0xe5, 0x1b, 0x64, 0x2b, 0x62, 0xd4, 0x29, 0x0b, 0xc6, 0xdf, 0xee, 0xe8, 0x81, - 0x0c, 0x54, 0x55, 0xb5, 0x71, 0x70, 0x67, 0xa5, 0x3f, 0x2c, 0x2f, 0x9e, 0xb0, 0xc4, 0x4a, 0x27, 0x17, 0xaa, 0xd0, - 0x1f, 0x84, 0xe8, 0xa6, 0xb2, 0xe1, 0xe0, 0x50, 0x17, 0x5b, 0x19, 0x10, 0x7a, 0x98, 0xde, 0xdb, 0x58, 0xc9, 0x72, - 0xd7, 0x94, 0x2f, 0x66, 0x3c, 0xe1, 0x38, 0xfa, 0x72, 0xb5, 0x08, 0x6b, 0xb5, 0xc8, 0x4e, 0x80, 0x87, 0xd6, 0x6a, - 0x29, 0xe4, 0x6a, 0x11, 0xce, 0x4c, 0x17, 0x6a, 0xa6, 0x67, 0xa0, 0x80, 0x14, 0x6a, 0x96, 0x27, 0x00, 0x0b, 0x2f, - 0xcc, 0x0c, 0x17, 0x66, 0x86, 0xe3, 0x90, 0x1a, 0xff, 0x07, 0xbd, 0xd7, 0xb9, 0xe7, 0x96, 0xbb, 0xd1, 0x69, 0xc4, - 0xb7, 0xa3, 0x0d, 0xe6, 0xf8, 0x20, 0x9c, 0x54, 0xfd, 0x7e, 0x5a, 0x22, 0x56, 0x8f, 0x81, 0x11, 0x94, 0x43, 0xe5, - 0x68, 0xbf, 0x2c, 0x2c, 0xc9, 0x92, 0xb0, 0x24, 0xf7, 0x6a, 0x9c, 0x4b, 0xcb, 0xc5, 0xab, 0x24, 0x10, 0x89, 0x8c, - 0x97, 0xd2, 0x04, 0x9f, 0xf0, 0x72, 0x64, 0xa4, 0xe6, 0xc9, 0x22, 0xf5, 0x72, 0x96, 0xb1, 0x31, 0x62, 0x18, 0x85, - 0x7e, 0x53, 0xf5, 0xfb, 0x79, 0xe9, 0xe5, 0xd4, 0xce, 0x4f, 0xe0, 0x7a, 0x79, 0xea, 0x2c, 0x72, 0x84, 0xbc, 0x1a, - 0x49, 0x85, 0xe5, 0xb5, 0x52, 0x4f, 0x5f, 0x82, 0x0f, 0xea, 0xee, 0x8d, 0x02, 0x20, 0x2e, 0x72, 0xe9, 0x5f, 0x5b, - 0xc2, 0xa5, 0x29, 0x37, 0x30, 0xe8, 0x21, 0xcf, 0x49, 0x08, 0x95, 0x20, 0x24, 0x85, 0x75, 0xe3, 0xbe, 0x78, 0x32, - 0x71, 0xdd, 0x59, 0x6c, 0x60, 0x82, 0xc3, 0x01, 0x10, 0x0f, 0xa6, 0x5e, 0x34, 0xe0, 0xa5, 0x9a, 0x33, 0x1f, 0xbc, - 0x9c, 0x60, 0x32, 0x40, 0x55, 0x31, 0x70, 0xca, 0x7a, 0x2c, 0x1f, 0x19, 0x37, 0x33, 0xdf, 0x0f, 0xf0, 0xdd, 0xba, - 0x90, 0xe8, 0x0f, 0x0a, 0xa0, 0x20, 0x53, 0x00, 0x05, 0x89, 0x01, 0x28, 0x88, 0x0d, 0x40, 0xc1, 0xa6, 0xe1, 0x2b, - 0xa9, 0xc3, 0x8d, 0x80, 0x2e, 0xc2, 0x87, 0x9e, 0x85, 0x8d, 0x15, 0x8a, 0x67, 0x63, 0x36, 0x66, 0x85, 0xda, 0x79, - 0x72, 0x39, 0x15, 0x3b, 0x8b, 0xb1, 0xae, 0x22, 0xb7, 0x89, 0x17, 0x12, 0x8a, 0x9c, 0x73, 0x23, 0x51, 0x77, 0x3f, - 0xf7, 0x5e, 0x92, 0xb1, 0x64, 0xde, 0xd0, 0xa8, 0xc1, 0xbc, 0xec, 0x3a, 0x80, 0x69, 0xc9, 0xb7, 0x05, 0x0d, 0xa6, - 0x53, 0xe5, 0x11, 0x69, 0x12, 0xd4, 0xce, 0x65, 0x52, 0xe4, 0x84, 0x30, 0x09, 0x7a, 0x25, 0xf8, 0x8d, 0x44, 0xf9, - 0xff, 0xa6, 0x13, 0x3c, 0xc0, 0x31, 0xd1, 0x2a, 0xf9, 0x0a, 0x06, 0xcc, 0x9c, 0x3f, 0x93, 0x4e, 0xd9, 0x08, 0xc5, - 0x58, 0xa6, 0xf1, 0xe8, 0x2b, 0x1b, 0x22, 0xb4, 0xd5, 0x33, 0x34, 0x31, 0x41, 0x1d, 0xe0, 0x11, 0xfd, 0x35, 0xfa, - 0x6a, 0x28, 0x54, 0xba, 0x1a, 0xa9, 0x6b, 0x76, 0xce, 0xf9, 0xdb, 0xda, 0x70, 0x22, 0x63, 0xda, 0x14, 0xf8, 0x06, - 0x04, 0xf2, 0x0d, 0x04, 0x80, 0xab, 0xa6, 0x33, 0x7b, 0x05, 0x70, 0x0e, 0x04, 0xf0, 0x38, 0xef, 0x78, 0xfc, 0x40, - 0x7f, 0x15, 0xc7, 0xbd, 0xd3, 0x34, 0x6c, 0xff, 0x15, 0x18, 0x8b, 0xa1, 0x1c, 0xcf, 0x77, 0x0a, 0x92, 0x3d, 0x4a, - 0x59, 0xba, 0x6a, 0x22, 0x3b, 0x14, 0xeb, 0xd3, 0x9c, 0x32, 0x96, 0xb6, 0xe5, 0x18, 0x6d, 0xbc, 0x7e, 0x88, 0xc7, - 0x37, 0x37, 0x7a, 0xf2, 0x41, 0x0f, 0x6e, 0x6f, 0xaf, 0x5e, 0xf4, 0x98, 0xcd, 0xb7, 0x62, 0xf1, 0xac, 0x88, 0x13, - 0xa7, 0x75, 0xc8, 0x01, 0x0e, 0x72, 0x12, 0x02, 0xe9, 0x18, 0x97, 0x5a, 0x74, 0x50, 0xb3, 0x9c, 0xd7, 0xc0, 0x32, - 0x8b, 0x20, 0x1b, 0x20, 0xaa, 0x69, 0x2a, 0x56, 0xc3, 0x83, 0x52, 0x35, 0xa7, 0x54, 0x6a, 0xdf, 0x70, 0xb6, 0x3a, - 0x7d, 0x62, 0xd5, 0x26, 0xdc, 0xfa, 0xb7, 0xda, 0x13, 0xb4, 0x95, 0x34, 0x10, 0xea, 0xf9, 0x22, 0xbd, 0xa5, 0x28, - 0x1e, 0x67, 0x26, 0x9e, 0xaa, 0xc0, 0xd8, 0xb7, 0x76, 0x04, 0x05, 0x49, 0xd3, 0x75, 0xc0, 0x61, 0x1a, 0x9d, 0xb0, - 0xf8, 0xa7, 0xf4, 0xa1, 0xbc, 0xa8, 0x15, 0x38, 0xc9, 0x3f, 0x85, 0x8b, 0x48, 0x62, 0xa1, 0x5f, 0x12, 0x00, 0x89, - 0x0c, 0x5e, 0x8d, 0x8a, 0xb5, 0x50, 0x01, 0x72, 0x8a, 0xd2, 0x5b, 0xc5, 0xc7, 0xa5, 0x28, 0x55, 0x4a, 0x65, 0x6e, - 0x54, 0x0a, 0x08, 0x6b, 0x03, 0x47, 0x17, 0xf0, 0x05, 0x04, 0xad, 0xe5, 0x6e, 0x6d, 0x7b, 0xde, 0xc8, 0x7c, 0x66, - 0x9a, 0xa7, 0xd5, 0x7b, 0xf5, 0xf7, 0xbb, 0x25, 0x86, 0xd9, 0x78, 0xfa, 0xfb, 0x36, 0x43, 0xb8, 0xf9, 0x1b, 0x86, - 0xe8, 0x16, 0xc0, 0x31, 0x4b, 0x7b, 0x28, 0x64, 0xc1, 0x04, 0x6b, 0xa8, 0xca, 0x53, 0x3e, 0x7b, 0xf9, 0x64, 0x07, - 0x68, 0x6a, 0xe8, 0xe2, 0x46, 0xa7, 0xba, 0x2a, 0x41, 0xf8, 0xbe, 0x2b, 0xd4, 0x63, 0x73, 0xc0, 0xa9, 0x01, 0xa0, - 0x58, 0xe4, 0xb5, 0x1e, 0xdb, 0x3f, 0xe8, 0x8d, 0x7a, 0x03, 0xc4, 0xd3, 0x39, 0x2f, 0xfc, 0x23, 0xfa, 0x75, 0xea, - 0xcf, 0xb8, 0x10, 0x44, 0xbd, 0x9e, 0x84, 0x77, 0xe2, 0x2c, 0x8d, 0x83, 0xb3, 0xde, 0xc0, 0x5c, 0x04, 0x8a, 0xb3, - 0x34, 0x3f, 0x03, 0xb1, 0x1c, 0xe1, 0x11, 0x6b, 0x76, 0x03, 0x88, 0x81, 0xa5, 0x0e, 0x49, 0x56, 0x1d, 0xdb, 0xef, - 0xbf, 0x1c, 0x19, 0xde, 0x74, 0x44, 0x84, 0xd1, 0xbf, 0x2b, 0x10, 0xa0, 0x60, 0x99, 0xd9, 0xce, 0x4c, 0xba, 0xda, - 0xb3, 0x7a, 0xde, 0x6c, 0xf2, 0xae, 0xde, 0xb1, 0x9a, 0x96, 0x53, 0xd3, 0x2a, 0xab, 0x69, 0x93, 0x1c, 0x6a, 0x26, - 0xfa, 0x7d, 0x8d, 0x8f, 0x9a, 0xcf, 0x01, 0x97, 0x0d, 0x93, 0x5f, 0xce, 0xaa, 0x79, 0xbf, 0xef, 0xc9, 0x47, 0xf0, - 0x0b, 0x89, 0xcb, 0xdc, 0x1a, 0xcb, 0xa7, 0xaf, 0x88, 0xcf, 0xcc, 0x20, 0x1e, 0xdd, 0x1c, 0x41, 0x7d, 0x7d, 0x14, - 0x5e, 0xc7, 0x5c, 0x61, 0x33, 0x31, 0x7d, 0x09, 0x83, 0xe7, 0x09, 0x1f, 0xbc, 0xe5, 0xe8, 0x6f, 0xa4, 0x33, 0x53, - 0xb0, 0x90, 0x73, 0x7f, 0xf2, 0x12, 0xa1, 0x93, 0x11, 0xe9, 0x41, 0xa7, 0x13, 0x34, 0x64, 0xbf, 0xbf, 0x80, 0xce, - 0x6c, 0xa5, 0x52, 0xb6, 0x2a, 0x2a, 0xd3, 0x75, 0x5d, 0x94, 0x15, 0x74, 0x2c, 0xfd, 0xbc, 0x11, 0x32, 0xb3, 0x7e, - 0x66, 0x21, 0x3f, 0x2d, 0x24, 0xd6, 0x94, 0x6d, 0x9f, 0xa8, 0x0d, 0xd2, 0xac, 0x0b, 0xd5, 0x05, 0xce, 0x9d, 0xb5, - 0xd7, 0x1b, 0xa1, 0xfe, 0x39, 0x1f, 0xad, 0x8b, 0xb5, 0x07, 0x2e, 0x31, 0xb3, 0x74, 0xae, 0x38, 0x34, 0x72, 0x7f, - 0xf4, 0xb9, 0x48, 0x73, 0xca, 0x03, 0x34, 0x88, 0x62, 0x6e, 0xbf, 0x05, 0xd2, 0x0f, 0xbd, 0x05, 0xb2, 0x8f, 0xce, - 0x39, 0x79, 0x09, 0xe0, 0x74, 0x88, 0x88, 0x5b, 0x91, 0xa0, 0x63, 0xd5, 0x70, 0x67, 0xe1, 0x9e, 0xf6, 0xd2, 0xb8, - 0x97, 0xe6, 0x67, 0x69, 0xbf, 0x6f, 0x00, 0x34, 0x53, 0x44, 0x86, 0xc7, 0x19, 0xb9, 0x4d, 0x5a, 0x08, 0xa6, 0xb4, - 0xff, 0x6a, 0x0c, 0x09, 0x02, 0x01, 0xff, 0xa7, 0xf0, 0xde, 0x03, 0xda, 0x26, 0x6d, 0xc0, 0x55, 0x8f, 0xe9, 0xc0, - 0x6c, 0xc9, 0xd9, 0xaa, 0xb3, 0x01, 0x28, 0xa7, 0x4a, 0xeb, 0x29, 0x8f, 0x6b, 0x8a, 0x88, 0x54, 0x59, 0xa8, 0xdf, - 0x58, 0x4f, 0x26, 0xab, 0x5c, 0x64, 0xc8, 0x51, 0x99, 0xde, 0xd6, 0x8c, 0x10, 0xbb, 0xf4, 0xf3, 0x05, 0x2c, 0xd9, - 0xf8, 0x03, 0x4e, 0xde, 0x12, 0x20, 0x6d, 0x67, 0xed, 0xaa, 0xda, 0xe5, 0xb8, 0xb5, 0x9b, 0x03, 0x92, 0xaf, 0x37, - 0x1a, 0x8d, 0xb4, 0x9f, 0x9c, 0x80, 0xa1, 0xea, 0xa9, 0xa5, 0xd0, 0x63, 0xb5, 0xc2, 0xd6, 0xed, 0xc8, 0x65, 0x96, - 0x0c, 0xe6, 0x0b, 0xe3, 0xf8, 0xda, 0x7c, 0xf4, 0xe1, 0x52, 0x59, 0xbb, 0x8e, 0xf8, 0xfa, 0x4f, 0xb2, 0x5a, 0xdf, - 0xf3, 0xae, 0x6a, 0x02, 0xbe, 0xa8, 0x62, 0x4b, 0xbf, 0xe3, 0x3d, 0xd9, 0xbb, 0xf8, 0xda, 0x47, 0xec, 0x92, 0xef, - 0x79, 0x8b, 0x3a, 0xcf, 0x57, 0xbe, 0x6e, 0x54, 0xe9, 0xf6, 0x5e, 0xb2, 0xc0, 0xb5, 0x77, 0xd4, 0x34, 0xd6, 0x33, - 0x3f, 0x7a, 0x58, 0x84, 0x6c, 0xe7, 0x43, 0xef, 0xab, 0xe6, 0xe9, 0x59, 0x43, 0x6f, 0x52, 0x43, 0x1f, 0x7a, 0x51, - 0xb6, 0x4f, 0x4d, 0x23, 0x7a, 0x0d, 0x1b, 0xfa, 0xd0, 0x5b, 0x72, 0x72, 0x48, 0x30, 0x38, 0x35, 0xe6, 0x0f, 0x0f, - 0xa7, 0x33, 0xfc, 0x1d, 0x03, 0x2a, 0x31, 0x99, 0x4f, 0x8f, 0x69, 0x47, 0x01, 0x66, 0x54, 0xe9, 0xed, 0xd3, 0x03, - 0xdb, 0xf1, 0xb2, 0x1e, 0x5a, 0x7a, 0xf7, 0xe4, 0xe8, 0x76, 0xbc, 0xaa, 0xc6, 0x97, 0x72, 0xc8, 0xf3, 0x7c, 0x36, - 0x1a, 0x8d, 0x84, 0x41, 0xe7, 0xae, 0xf4, 0x06, 0x56, 0x20, 0x83, 0x8b, 0xea, 0x43, 0xb9, 0xf4, 0x76, 0xea, 0xd0, - 0xae, 0xfc, 0x49, 0x7e, 0x38, 0x14, 0x23, 0x73, 0x8c, 0x03, 0xce, 0x49, 0xa1, 0xe4, 0x28, 0x59, 0x4b, 0x10, 0x9d, - 0xd2, 0x78, 0x2a, 0xeb, 0xb5, 0x15, 0x91, 0x57, 0x23, 0xe4, 0x43, 0xf0, 0xb3, 0x07, 0x6a, 0xf1, 0xa7, 0x5a, 0x10, - 0x7b, 0xe8, 0x53, 0xa5, 0x74, 0x88, 0x57, 0x05, 0x84, 0x08, 0x03, 0xde, 0x40, 0x3b, 0x28, 0xc1, 0x61, 0x87, 0x7b, - 0x8f, 0x08, 0xd1, 0x2f, 0xbc, 0x7c, 0x26, 0xc3, 0x95, 0x7b, 0x83, 0x6a, 0xce, 0x00, 0xb1, 0xd2, 0x67, 0xe0, 0x82, - 0x09, 0xa8, 0xa7, 0xf8, 0x14, 0xfd, 0xeb, 0xcd, 0xc3, 0xa6, 0xeb, 0xd3, 0x12, 0x50, 0x11, 0x3d, 0xfb, 0xf9, 0x18, - 0xc0, 0x3b, 0xbb, 0x36, 0x23, 0xed, 0xe5, 0x6f, 0x80, 0x61, 0xa5, 0x24, 0xd1, 0xce, 0x29, 0x11, 0xb8, 0xf3, 0x91, - 0x2d, 0xfd, 0x28, 0x05, 0x62, 0xee, 0x78, 0x92, 0xc8, 0x1e, 0x6c, 0xe4, 0x04, 0x6e, 0x31, 0xe0, 0xd1, 0x01, 0xa8, - 0x5c, 0x29, 0xc8, 0xbd, 0xe6, 0x48, 0xee, 0xf8, 0xb1, 0xf7, 0xe3, 0xa0, 0x1e, 0xfc, 0xd8, 0x3b, 0x4b, 0x49, 0xee, - 0x08, 0xcf, 0xd4, 0x94, 0x10, 0xf1, 0xd9, 0x8f, 0x83, 0x7c, 0x80, 0x67, 0x89, 0x16, 0x69, 0x91, 0x5b, 0x4d, 0xd4, - 0xb8, 0x09, 0x6f, 0x13, 0x49, 0x43, 0x74, 0xd7, 0x79, 0x44, 0x2c, 0x00, 0x24, 0x8b, 0xcf, 0xe6, 0x0d, 0x45, 0xbd, - 0x9b, 0xf0, 0x2d, 0xba, 0xcb, 0x62, 0xbf, 0xbf, 0xca, 0xd3, 0xba, 0xa7, 0x43, 0x65, 0xf0, 0x05, 0xa9, 0x26, 0xc0, - 0xa3, 0xfd, 0x85, 0x39, 0x5e, 0xbd, 0xda, 0x1c, 0x29, 0x0b, 0x55, 0xa2, 0x7e, 0x8b, 0xd5, 0xac, 0x87, 0x88, 0xdc, - 0x59, 0x66, 0xec, 0xed, 0x05, 0xaf, 0xe4, 0xac, 0x8a, 0xed, 0x72, 0x7c, 0x45, 0x58, 0x5b, 0x49, 0x80, 0x8e, 0xd6, - 0x63, 0x6d, 0x8a, 0x91, 0x5f, 0x29, 0x24, 0xe0, 0xa2, 0x63, 0x6b, 0xa1, 0xd8, 0x78, 0x01, 0xfa, 0x92, 0x9d, 0x69, - 0x80, 0xf5, 0x46, 0xaf, 0x22, 0x6e, 0xcb, 0x07, 0x2a, 0xbc, 0xc9, 0x4d, 0x95, 0x59, 0xd9, 0x2c, 0xda, 0xfd, 0x54, - 0xf1, 0x0a, 0x71, 0xeb, 0x8d, 0xda, 0xa3, 0x00, 0xb5, 0x87, 0x16, 0xca, 0x00, 0x5d, 0x9a, 0x66, 0x00, 0xc8, 0x00, - 0x20, 0x53, 0x45, 0x7c, 0x26, 0x40, 0xa5, 0xad, 0x6e, 0x14, 0x38, 0x91, 0x5e, 0x00, 0xe3, 0x02, 0x2b, 0x7d, 0x64, - 0x23, 0x83, 0xc5, 0x16, 0x01, 0x6e, 0x39, 0xd2, 0x87, 0x69, 0x38, 0xd9, 0x46, 0x73, 0x98, 0xa4, 0xf9, 0x5d, 0x98, - 0xa5, 0x12, 0x5a, 0xe2, 0x95, 0xac, 0x31, 0x62, 0x01, 0xe9, 0xfb, 0xf4, 0xa2, 0xc8, 0x62, 0x82, 0x84, 0xb3, 0x9e, - 0x3a, 0x80, 0x6a, 0x72, 0xae, 0x35, 0xad, 0x9e, 0xd5, 0x26, 0x0f, 0x59, 0xa0, 0xb3, 0x07, 0x63, 0x52, 0xcb, 0x0d, - 0x3d, 0xb2, 0xbf, 0x72, 0x3c, 0x23, 0x7c, 0xd7, 0x33, 0x9c, 0xfa, 0xef, 0x63, 0x0d, 0xa4, 0x4c, 0x09, 0x20, 0xc8, - 0xe0, 0x68, 0x42, 0x28, 0x4f, 0xc7, 0x64, 0x6a, 0xf3, 0x23, 0x10, 0x8e, 0x08, 0x5e, 0xc1, 0x73, 0x43, 0xeb, 0x96, - 0x1b, 0x3b, 0x8b, 0x3c, 0x4d, 0x00, 0x59, 0xbc, 0xe0, 0xf7, 0x80, 0xcc, 0xa9, 0x57, 0x85, 0xec, 0xd9, 0x73, 0x31, - 0x9d, 0xcd, 0x83, 0x8f, 0x09, 0xed, 0x5f, 0x4c, 0xf8, 0x4d, 0x77, 0x95, 0x5c, 0x99, 0x5a, 0xf7, 0x26, 0x7a, 0xcc, - 0xe5, 0x4e, 0x9f, 0x56, 0x1c, 0x23, 0x9e, 0xc1, 0x2a, 0x20, 0xe7, 0x6c, 0xc8, 0x9f, 0x9e, 0x03, 0x76, 0xcb, 0x4a, - 0x78, 0x11, 0x7f, 0x1a, 0xca, 0x6a, 0x01, 0xf2, 0x23, 0xe7, 0x91, 0xf9, 0xe5, 0xab, 0xed, 0x50, 0xce, 0x29, 0x8a, - 0x68, 0x39, 0x35, 0x2d, 0x29, 0x64, 0x87, 0x9e, 0x82, 0xc9, 0xd4, 0x96, 0xbf, 0xef, 0x13, 0x97, 0xe4, 0x9b, 0x49, - 0x64, 0x5f, 0x07, 0x58, 0xb3, 0x56, 0xdd, 0x43, 0x37, 0x04, 0x03, 0x44, 0x46, 0x28, 0xb3, 0xb9, 0xbe, 0x5b, 0x0f, - 0x06, 0x0a, 0xe6, 0x57, 0xd0, 0x4d, 0x8b, 0x4e, 0x71, 0x80, 0x9c, 0xb5, 0xae, 0x51, 0xa9, 0x2a, 0x0e, 0x1d, 0xe6, - 0xdd, 0xb2, 0x2a, 0xbb, 0x2c, 0xbd, 0x10, 0xa4, 0x46, 0x5d, 0x05, 0x8b, 0x94, 0x8a, 0x28, 0xde, 0x93, 0x5f, 0x03, - 0x13, 0xcf, 0xac, 0x1c, 0xa5, 0xf1, 0x1c, 0x10, 0x83, 0x14, 0x10, 0xa7, 0xfc, 0x0a, 0xd0, 0x44, 0x17, 0x51, 0x98, - 0xbd, 0x8a, 0xab, 0xa0, 0xb6, 0x9a, 0xfe, 0xa7, 0x03, 0x19, 0x7b, 0x5e, 0xf7, 0xfb, 0x29, 0x31, 0xfa, 0x61, 0x14, - 0x06, 0xfe, 0x3d, 0x9e, 0xee, 0x9b, 0x20, 0x35, 0xaf, 0x7c, 0x84, 0x57, 0x74, 0xb9, 0xb5, 0x29, 0x57, 0x34, 0x2e, - 0xfc, 0x35, 0x82, 0xc3, 0xa7, 0x8e, 0x62, 0xbb, 0x4d, 0x95, 0x53, 0x1b, 0x83, 0x41, 0x08, 0xf7, 0xad, 0x8c, 0xff, - 0x99, 0x78, 0xf9, 0x2c, 0x9a, 0x83, 0xa2, 0x34, 0xd3, 0x7c, 0x21, 0x85, 0x74, 0x13, 0xa0, 0x8f, 0x06, 0xa1, 0x56, - 0x57, 0xbe, 0x49, 0xbc, 0x54, 0x4d, 0x6b, 0xf3, 0x14, 0x6b, 0x14, 0x88, 0x59, 0x34, 0x6f, 0x58, 0x46, 0x87, 0xa4, - 0xba, 0x5c, 0x9a, 0x66, 0xbc, 0xb1, 0x9a, 0xa1, 0x5a, 0x71, 0xd4, 0x04, 0x35, 0x4a, 0x1f, 0xe1, 0x02, 0xf8, 0x0f, - 0xba, 0xe3, 0xa8, 0x46, 0x91, 0xa2, 0x01, 0x9f, 0x20, 0x46, 0xac, 0xd9, 0x3c, 0x61, 0xad, 0xa9, 0x6b, 0x46, 0xbf, - 0x2f, 0x43, 0x86, 0x4c, 0x12, 0xf2, 0xf4, 0xe1, 0x72, 0xfd, 0x40, 0xaa, 0x0b, 0xe0, 0x57, 0xae, 0xd8, 0xac, 0xd7, - 0x9b, 0x03, 0x5c, 0x2f, 0xac, 0x5f, 0xd8, 0xb8, 0x82, 0xf3, 0x4b, 0x82, 0xdf, 0x55, 0x3f, 0xc2, 0x2c, 0x83, 0x2a, - 0x20, 0xe3, 0x8f, 0x05, 0x55, 0x9c, 0xbb, 0x98, 0xd4, 0x2f, 0x47, 0xea, 0x82, 0x32, 0x4b, 0xe7, 0x16, 0x27, 0x08, - 0x38, 0x0f, 0xab, 0x27, 0x90, 0xec, 0xcb, 0xc7, 0x3e, 0xcd, 0x28, 0x50, 0x1d, 0x01, 0x3e, 0x9b, 0xf5, 0x43, 0xd8, - 0x3f, 0x20, 0xb2, 0x50, 0x7f, 0xf3, 0x5a, 0xce, 0x1a, 0x92, 0x07, 0x52, 0xcd, 0x7d, 0x0c, 0xa7, 0xc6, 0x02, 0x5f, - 0x5a, 0xf4, 0xa6, 0x82, 0xd7, 0x84, 0xcc, 0xbd, 0x40, 0x6b, 0xdf, 0x02, 0x8e, 0x10, 0xc1, 0x65, 0x94, 0xe2, 0xb4, - 0xb7, 0xeb, 0x05, 0xc8, 0x6d, 0x6e, 0x41, 0x5e, 0x3f, 0x72, 0xf1, 0x8b, 0x53, 0xa4, 0x67, 0xd1, 0x05, 0x06, 0xba, - 0x20, 0xf3, 0xc6, 0xbf, 0x2a, 0x58, 0xb9, 0x80, 0xde, 0x4b, 0xc5, 0x4a, 0x4e, 0xb6, 0x9d, 0xfa, 0xa3, 0x54, 0xf6, - 0xdb, 0x33, 0x6b, 0x02, 0xbf, 0x4b, 0xec, 0x97, 0xc8, 0xe4, 0x9b, 0x1e, 0x9b, 0x7c, 0x65, 0x58, 0x74, 0x6a, 0x19, - 0x9c, 0xd3, 0x23, 0x83, 0x73, 0x6f, 0x67, 0xd5, 0x26, 0x82, 0xa1, 0x20, 0x09, 0x34, 0x5d, 0x7a, 0x58, 0x37, 0xfd, - 0xf9, 0x49, 0x8b, 0x6a, 0xab, 0xf6, 0xad, 0xfb, 0x71, 0x88, 0x5d, 0xfc, 0x2e, 0xf1, 0x0c, 0x11, 0xa9, 0x0f, 0x74, - 0x60, 0x32, 0x78, 0xe2, 0xb2, 0xdf, 0x87, 0xc2, 0x66, 0xe3, 0xf9, 0xa8, 0x2e, 0x5e, 0x17, 0xf7, 0x80, 0xea, 0x50, - 0x81, 0x5d, 0x0e, 0x65, 0x28, 0x23, 0x36, 0xb5, 0xe5, 0x9e, 0x3f, 0xae, 0xc3, 0x1c, 0xe4, 0x1d, 0x0d, 0x8f, 0x73, - 0x06, 0x62, 0x18, 0x7c, 0xfd, 0xc7, 0x47, 0xfb, 0xb4, 0xf9, 0xf1, 0x0c, 0xbe, 0x3b, 0x3a, 0x7b, 0x8f, 0x74, 0x37, - 0x67, 0xeb, 0xb2, 0xb8, 0x4b, 0x63, 0x71, 0xf6, 0x23, 0xa4, 0xfe, 0x78, 0x56, 0x94, 0x67, 0x3f, 0xaa, 0xca, 0xfc, - 0x78, 0x46, 0x0b, 0x6e, 0xf4, 0x87, 0x35, 0xf1, 0x7e, 0xaf, 0x34, 0x03, 0xda, 0x12, 0x22, 0xb3, 0xb4, 0xfa, 0x11, - 0x94, 0x88, 0x8a, 0x1f, 0x55, 0x46, 0xb5, 0x5a, 0x3b, 0xce, 0xfb, 0x44, 0x23, 0x65, 0xd3, 0x84, 0xc4, 0xd5, 0x12, - 0xd6, 0xa1, 0x9e, 0x9d, 0x36, 0xdf, 0x8e, 0xf3, 0x40, 0x1d, 0x10, 0x39, 0x7f, 0x9a, 0x8f, 0xb6, 0xf4, 0x35, 0xf8, - 0xd6, 0xe1, 0x90, 0x8f, 0x76, 0xe6, 0xa7, 0x4f, 0xd6, 0x4a, 0x19, 0x77, 0x24, 0x7b, 0x07, 0x6b, 0x0b, 0x9c, 0x20, - 0xc0, 0x01, 0xe0, 0x1f, 0x0e, 0xf4, 0x7b, 0x27, 0x7f, 0xab, 0xdd, 0xd2, 0xaa, 0xe7, 0xb3, 0x16, 0x77, 0xc6, 0xab, - 0xda, 0x10, 0xb5, 0xed, 0x25, 0xb6, 0xf4, 0xbe, 0x69, 0x50, 0x53, 0x44, 0x3f, 0x61, 0x35, 0xb1, 0x8a, 0xc3, 0x82, - 0x94, 0x90, 0xc4, 0x70, 0x8c, 0x76, 0xe8, 0x71, 0xba, 0x58, 0x7a, 0x72, 0xdf, 0xe1, 0xe5, 0xd6, 0xf7, 0x01, 0x49, - 0xab, 0x70, 0xfe, 0xce, 0x0b, 0x0d, 0x3c, 0x7a, 0x91, 0x57, 0x45, 0x26, 0x46, 0x82, 0x46, 0xf9, 0x15, 0x89, 0x33, - 0x67, 0x58, 0x8b, 0x33, 0x05, 0x16, 0x16, 0x12, 0x24, 0x78, 0x51, 0x52, 0x7a, 0x70, 0xf6, 0x68, 0x5f, 0x36, 0x7f, - 0x10, 0x3c, 0xc4, 0x68, 0x01, 0x8c, 0x38, 0xbb, 0x76, 0x79, 0xf7, 0x61, 0x99, 0x7b, 0x7f, 0xbc, 0xba, 0xcd, 0x0b, - 0x08, 0xd1, 0x3c, 0x93, 0x8a, 0xd5, 0xf2, 0x0c, 0x18, 0xf3, 0x44, 0x7c, 0x16, 0x56, 0x72, 0x1a, 0x54, 0x1d, 0xc5, - 0xaa, 0x6d, 0x3c, 0xca, 0x3d, 0xa0, 0xf8, 0x7e, 0x9f, 0x00, 0x97, 0xbb, 0xcf, 0x5e, 0x2a, 0xd7, 0x54, 0xd2, 0x23, - 0xcf, 0x21, 0x5a, 0xf2, 0x51, 0x02, 0x14, 0xcf, 0x10, 0x27, 0x29, 0xac, 0x9e, 0x9b, 0x20, 0x15, 0xf9, 0xfa, 0x84, - 0xe2, 0x8b, 0xe6, 0x51, 0xd4, 0xb0, 0x90, 0x25, 0x70, 0x3c, 0x24, 0xb3, 0x6c, 0x8e, 0x2c, 0xe5, 0x69, 0x7b, 0x8a, - 0x74, 0x74, 0x62, 0x89, 0xdf, 0xd6, 0xfc, 0x7a, 0x91, 0x8a, 0xc0, 0xa4, 0x9d, 0x2d, 0xcc, 0xbd, 0x10, 0x86, 0x2a, - 0xe1, 0xde, 0xab, 0x7a, 0x16, 0xca, 0x4d, 0xd1, 0xaa, 0x98, 0x3d, 0x4c, 0x89, 0x19, 0xa6, 0x58, 0x7f, 0x61, 0xc3, - 0xaf, 0x13, 0x2f, 0x06, 0xc3, 0xf5, 0x92, 0x97, 0xb3, 0x8d, 0x59, 0x08, 0x87, 0xc3, 0x66, 0x52, 0xcc, 0x96, 0x10, - 0xe6, 0xba, 0x9c, 0x1f, 0x0e, 0x5d, 0x2d, 0x5b, 0x0b, 0x0f, 0x1e, 0xaa, 0x16, 0x6e, 0x1a, 0x96, 0xc3, 0xcf, 0x64, - 0x16, 0x63, 0xfb, 0x1a, 0x9f, 0xd9, 0x9f, 0x2f, 0xba, 0x67, 0x09, 0x92, 0x6f, 0xac, 0x81, 0x76, 0x6c, 0xd6, 0xee, - 0x70, 0x35, 0x02, 0x92, 0xd2, 0xdd, 0xe8, 0x1c, 0xcb, 0x4e, 0x9e, 0x12, 0xe4, 0x8e, 0x56, 0x60, 0xbf, 0xfb, 0xc6, - 0x9f, 0x68, 0xb1, 0x07, 0xed, 0x36, 0xb6, 0x84, 0xa8, 0xa6, 0x3d, 0x97, 0x2b, 0xc5, 0xd2, 0x0d, 0x96, 0x36, 0x7a, - 0x3e, 0xac, 0xcf, 0x7d, 0x23, 0x07, 0x0a, 0xc6, 0x88, 0xa7, 0xd6, 0x41, 0x34, 0x9b, 0x03, 0x0d, 0x06, 0x9a, 0x47, - 0x78, 0x6a, 0xa1, 0x83, 0x32, 0x6b, 0xc3, 0xfe, 0x29, 0x39, 0x59, 0x1e, 0x87, 0x6f, 0xe1, 0x5f, 0x3e, 0xc3, 0x26, - 0x31, 0xc5, 0xf6, 0xf8, 0xa5, 0x52, 0x54, 0x78, 0x6c, 0x47, 0x5c, 0x6b, 0x1f, 0x45, 0x6d, 0xa8, 0x1c, 0xfe, 0x2d, - 0xec, 0x23, 0xec, 0x0b, 0x9a, 0x20, 0x0c, 0x76, 0xfd, 0x99, 0x40, 0x88, 0x58, 0x88, 0x17, 0xfc, 0x52, 0x49, 0x2a, - 0x3a, 0xe1, 0xb3, 0x5d, 0x09, 0xbc, 0x75, 0x18, 0xd0, 0x27, 0xe4, 0x67, 0x22, 0x61, 0x68, 0x26, 0xf4, 0x8e, 0xfe, - 0x3b, 0xb1, 0x93, 0x4d, 0x72, 0x2b, 0xe4, 0x03, 0x49, 0x25, 0xc1, 0x04, 0x2b, 0x2f, 0x94, 0xaf, 0xdc, 0x0b, 0xa5, - 0xd6, 0x5a, 0xd0, 0xfa, 0xe5, 0x3f, 0x25, 0x9e, 0xc1, 0xdf, 0x03, 0x19, 0x83, 0x6e, 0x23, 0xaa, 0x49, 0x8e, 0xe9, - 0xa3, 0x74, 0x9e, 0x81, 0x0a, 0xe8, 0x6c, 0x9d, 0x85, 0xf5, 0xb2, 0x28, 0x57, 0xad, 0x48, 0x51, 0x59, 0xfa, 0x48, - 0x3d, 0xc6, 0xbc, 0x30, 0x4f, 0x4e, 0xe4, 0x83, 0x47, 0x00, 0x8c, 0x47, 0x79, 0x5a, 0x75, 0x94, 0xd6, 0x0f, 0x2c, - 0x03, 0x46, 0xe0, 0x44, 0x19, 0xf0, 0x08, 0xcb, 0xc0, 0x3c, 0xed, 0x32, 0xd4, 0x20, 0xd6, 0xa8, 0xba, 0x52, 0x1b, - 0xcc, 0x89, 0xa2, 0xe4, 0x53, 0x2c, 0xad, 0x30, 0x86, 0xa6, 0xae, 0x3c, 0xb2, 0x5e, 0x72, 0xc2, 0x9e, 0xec, 0x06, - 0xd2, 0x2d, 0x6c, 0x14, 0xce, 0xa0, 0x6b, 0x59, 0xa2, 0x5c, 0x74, 0xcb, 0x88, 0x32, 0x11, 0x52, 0x3f, 0x7b, 0x38, - 0xd3, 0x6a, 0xbf, 0xb1, 0x93, 0xf6, 0xed, 0x91, 0xa2, 0x17, 0x0c, 0xda, 0xa7, 0x3d, 0x52, 0xea, 0x59, 0x23, 0x97, - 0x81, 0x2d, 0x5d, 0xaa, 0x7a, 0xfe, 0x1b, 0x94, 0xef, 0x60, 0x66, 0x9c, 0xcd, 0xfe, 0xd0, 0x9b, 0xdb, 0xa3, 0x7d, - 0xdd, 0xfc, 0xc1, 0x7a, 0x3d, 0xd8, 0x1a, 0x64, 0xe2, 0x33, 0xc5, 0x42, 0x65, 0x15, 0x62, 0x05, 0x69, 0xff, 0x5b, - 0x78, 0x7f, 0xc0, 0x5b, 0x23, 0x34, 0x2b, 0xe3, 0x61, 0x3e, 0x7a, 0xb4, 0x17, 0xcd, 0x1f, 0x9d, 0x65, 0x5b, 0xb9, - 0x2a, 0x99, 0xed, 0x8f, 0xa3, 0xa4, 0x39, 0x7b, 0xb8, 0x46, 0x52, 0x07, 0xf8, 0x70, 0x7d, 0x86, 0x0f, 0x54, 0x42, - 0xa9, 0x05, 0x55, 0x0d, 0x5a, 0x1f, 0xfb, 0xa3, 0xf5, 0x9c, 0x3e, 0x7e, 0x2c, 0xa7, 0x5b, 0x52, 0x84, 0xf1, 0x03, - 0x83, 0x29, 0x3b, 0x71, 0xea, 0x92, 0x37, 0x43, 0x7a, 0xd7, 0xad, 0x92, 0xba, 0xec, 0x51, 0x22, 0x08, 0x75, 0xb0, - 0x7e, 0xb1, 0x1f, 0xc2, 0xcc, 0x16, 0xfd, 0x61, 0xb3, 0x9a, 0x13, 0x20, 0x22, 0xa0, 0xb5, 0xca, 0xfb, 0xc0, 0x31, - 0x5f, 0x98, 0x35, 0x37, 0xa4, 0x5b, 0x6f, 0xae, 0xb4, 0x57, 0x52, 0x40, 0x3f, 0x07, 0x99, 0xdb, 0x47, 0xb7, 0x5c, - 0xb5, 0xcc, 0x73, 0x69, 0xcb, 0x01, 0x8b, 0x16, 0x02, 0x35, 0x3b, 0x97, 0x0e, 0x07, 0x0a, 0x42, 0x5d, 0x89, 0x2a, - 0xe2, 0xea, 0x28, 0x5a, 0x88, 0x5a, 0xad, 0xda, 0xe5, 0x64, 0x53, 0x21, 0x5b, 0x12, 0x41, 0x46, 0xc9, 0x5e, 0x09, - 0xf5, 0x51, 0xae, 0xf6, 0x4c, 0xc3, 0x01, 0x9a, 0x80, 0x4d, 0x1b, 0xfc, 0x2d, 0x70, 0x2f, 0x83, 0x33, 0xd3, 0x3e, - 0x0d, 0x23, 0xe0, 0x34, 0x87, 0x98, 0x3f, 0xbf, 0xeb, 0x41, 0x05, 0x0f, 0x3a, 0xd2, 0x5f, 0xd5, 0xb3, 0x02, 0xcf, - 0xdc, 0x13, 0xcf, 0x5f, 0x9e, 0x48, 0x2f, 0x73, 0x78, 0xa0, 0x69, 0x10, 0x33, 0xfe, 0xac, 0x2c, 0xc3, 0xdd, 0x68, - 0x59, 0x16, 0x2b, 0x2f, 0xd2, 0xfb, 0x78, 0x26, 0xc5, 0x40, 0x62, 0xc6, 0xcc, 0xe8, 0x2a, 0xd6, 0x71, 0x0e, 0xe3, - 0xde, 0x9e, 0x84, 0x15, 0xda, 0x3f, 0x4b, 0xec, 0x75, 0x01, 0x58, 0x0e, 0x59, 0x83, 0x56, 0x78, 0xa7, 0xdb, 0xdb, - 0x3d, 0x2e, 0xd9, 0x51, 0xdc, 0x00, 0xfa, 0x59, 0x0d, 0x2d, 0x13, 0xd4, 0x32, 0xeb, 0x4e, 0x26, 0x53, 0x24, 0x97, - 0x6f, 0xc3, 0x5e, 0xb2, 0x32, 0x9f, 0x37, 0x72, 0x7b, 0x78, 0x1b, 0xae, 0x44, 0xac, 0x2d, 0xe8, 0xa4, 0x23, 0xe3, - 0x70, 0x2f, 0x34, 0x37, 0xd2, 0xfd, 0xa3, 0x2a, 0x09, 0x4b, 0x11, 0xc3, 0x2d, 0x90, 0xed, 0xd5, 0xb6, 0x12, 0x94, - 0xc0, 0x07, 0xfb, 0xbe, 0x14, 0xcb, 0x74, 0x2b, 0x00, 0xd7, 0x81, 0xff, 0x26, 0x11, 0x09, 0xdd, 0x9d, 0x87, 0x28, - 0xd6, 0xc8, 0xfb, 0x06, 0xd1, 0xd8, 0x3f, 0x81, 0x9c, 0x06, 0x64, 0x22, 0xc5, 0x48, 0x16, 0x0c, 0x7c, 0x00, 0x39, - 0x5f, 0x83, 0x49, 0x6e, 0x9a, 0x7b, 0x7e, 0x90, 0xeb, 0x0e, 0xa6, 0x7d, 0xd0, 0xbd, 0xb8, 0xd6, 0x2c, 0x07, 0xaf, - 0x98, 0x88, 0xff, 0xa3, 0xf6, 0x4a, 0x96, 0xb3, 0xcc, 0x6f, 0xcc, 0x45, 0x27, 0x83, 0xab, 0x86, 0xf0, 0x8b, 0x59, - 0x36, 0xe7, 0xd1, 0x2c, 0xd3, 0x51, 0xff, 0x45, 0x73, 0x54, 0x0a, 0xc0, 0xa9, 0xe3, 0x05, 0x58, 0x43, 0x5f, 0xe9, - 0xa6, 0x15, 0x0f, 0x34, 0xc6, 0x28, 0xa8, 0xd0, 0x41, 0xe8, 0x1f, 0x35, 0x20, 0x6d, 0x30, 0x49, 0x93, 0x50, 0xf9, - 0xe0, 0x82, 0x6e, 0x18, 0x9b, 0x2b, 0x97, 0xab, 0x26, 0x55, 0xcb, 0x2f, 0x47, 0xd4, 0x77, 0xb5, 0xe4, 0x52, 0x6d, - 0x3e, 0x35, 0xca, 0x1a, 0x41, 0x26, 0x47, 0xe9, 0xf7, 0x29, 0x17, 0x6e, 0x65, 0x4c, 0xd6, 0x87, 0x83, 0x57, 0x70, - 0x53, 0xe3, 0x17, 0x39, 0x11, 0x8a, 0xda, 0x43, 0x22, 0x6c, 0xed, 0x56, 0xe8, 0xde, 0xe3, 0x46, 0x69, 0x1e, 0x65, - 0x9b, 0x58, 0x54, 0x5e, 0x2f, 0x01, 0x6b, 0x71, 0x0f, 0x78, 0x51, 0x69, 0xe9, 0x57, 0xac, 0x00, 0xf4, 0x00, 0x29, - 0x6c, 0xbc, 0x40, 0x06, 0xac, 0x77, 0x5e, 0xea, 0xf7, 0xfb, 0xc6, 0x94, 0xff, 0xee, 0x3e, 0x07, 0x92, 0x42, 0x51, - 0xd6, 0x3b, 0x98, 0x40, 0x70, 0xed, 0x24, 0xed, 0x59, 0xcd, 0x9f, 0xae, 0x6b, 0x0f, 0xf8, 0xad, 0x7c, 0x8b, 0xc4, - 0xea, 0x93, 0x7d, 0xb1, 0xd9, 0xa7, 0xd5, 0x47, 0xa3, 0x71, 0x10, 0x2c, 0xad, 0x5e, 0x69, 0x95, 0x43, 0xde, 0xf0, - 0x02, 0x44, 0x2a, 0xeb, 0xea, 0x5a, 0x39, 0x57, 0xd7, 0x82, 0x23, 0x97, 0x6c, 0xc9, 0x73, 0xf8, 0x2f, 0xe4, 0x5e, - 0x79, 0x38, 0x14, 0x7e, 0xbf, 0x9f, 0xce, 0x48, 0x2b, 0x0b, 0xec, 0x69, 0xeb, 0xda, 0x0b, 0xfd, 0xc3, 0xe1, 0x05, - 0x78, 0x8d, 0xf8, 0x87, 0x43, 0xd9, 0xef, 0x7f, 0x30, 0x37, 0x99, 0xf3, 0xb1, 0x52, 0xca, 0x5e, 0xa2, 0xd2, 0xfd, - 0x75, 0xc2, 0x7b, 0xff, 0x7b, 0xf4, 0xbf, 0x47, 0x97, 0x3d, 0xd9, 0xf5, 0x1f, 0x12, 0x3e, 0xc3, 0x1b, 0x3a, 0x53, - 0x97, 0x73, 0x26, 0xdd, 0xdd, 0x95, 0x1f, 0x7a, 0x4f, 0x43, 0xc5, 0xf7, 0xe6, 0xa6, 0x8d, 0xff, 0xa8, 0x8e, 0x34, - 0x09, 0x1d, 0x17, 0xfd, 0xc3, 0xe1, 0x43, 0xa2, 0xf5, 0x69, 0xa9, 0xd2, 0xa7, 0x29, 0x1c, 0x25, 0x43, 0xee, 0xe6, - 0x16, 0xa6, 0x03, 0xfb, 0x71, 0xf3, 0x55, 0xf2, 0xe2, 0x2c, 0x85, 0x6b, 0x6f, 0x3e, 0x4b, 0xe7, 0x53, 0xb0, 0xae, - 0x0c, 0xf3, 0x59, 0x3d, 0x0f, 0x20, 0x75, 0x08, 0x69, 0xd6, 0x34, 0xfc, 0x67, 0xe5, 0x0a, 0xde, 0xda, 0xe3, 0xdd, - 0xc0, 0x45, 0xa9, 0x23, 0x7d, 0xd2, 0x46, 0xd3, 0x25, 0x95, 0xfc, 0x07, 0x91, 0xc7, 0x18, 0xb3, 0xf1, 0x82, 0x78, - 0x3f, 0x8b, 0xfc, 0xba, 0x00, 0xec, 0x22, 0x00, 0x43, 0x4e, 0xe7, 0x8e, 0x24, 0xfe, 0x32, 0xf9, 0xfe, 0x8f, 0xe9, - 0xd2, 0xde, 0x97, 0xc5, 0x6d, 0x29, 0xaa, 0xea, 0xa8, 0xb4, 0xad, 0x2d, 0xd7, 0x03, 0x93, 0x68, 0xbf, 0x2f, 0x99, - 0x44, 0x53, 0x0c, 0x45, 0x81, 0x5b, 0x63, 0x6f, 0x9a, 0x72, 0xc5, 0x58, 0x3d, 0x32, 0xd6, 0xcf, 0xe7, 0xbb, 0x57, - 0xb1, 0x97, 0xfa, 0x41, 0x0a, 0x82, 0xb0, 0x86, 0x52, 0x4a, 0x91, 0x0f, 0xce, 0x67, 0x98, 0x4a, 0xd4, 0xba, 0x94, - 0x2a, 0x7f, 0x18, 0x69, 0x3e, 0x4c, 0x41, 0x2f, 0xfb, 0xef, 0x0a, 0xe6, 0xbf, 0x6e, 0x0f, 0xd6, 0xa7, 0x75, 0x99, - 0x46, 0x15, 0x51, 0xe5, 0x85, 0xa9, 0x36, 0x81, 0x08, 0xfe, 0x54, 0x58, 0x7c, 0xbf, 0x3e, 0x39, 0x12, 0x34, 0x66, - 0xb2, 0xbc, 0x3d, 0x72, 0xbf, 0xb0, 0xaf, 0x5c, 0xc7, 0xf3, 0x3f, 0x37, 0xf3, 0x7f, 0x80, 0xce, 0x90, 0xc5, 0x53, - 0x6e, 0x19, 0x2c, 0x70, 0xf6, 0x4b, 0x57, 0x0f, 0xf8, 0x9b, 0x79, 0xe2, 0x29, 0xd0, 0x31, 0x3f, 0x45, 0x57, 0xc5, - 0x74, 0x56, 0x0c, 0x80, 0xcb, 0xd6, 0x6f, 0xac, 0x39, 0xf1, 0xd5, 0xa2, 0xbc, 0x92, 0x0b, 0x42, 0x5f, 0x57, 0x61, - 0x36, 0xae, 0x8a, 0x4d, 0x25, 0x8a, 0x4d, 0xdd, 0x23, 0xb5, 0x6c, 0x3e, 0xad, 0x6d, 0x85, 0xec, 0xdf, 0x45, 0x8b, - 0xc1, 0xcb, 0xb0, 0x4e, 0x46, 0x59, 0xba, 0x9e, 0x02, 0xbf, 0x5e, 0x00, 0x67, 0x91, 0x79, 0xe5, 0xb3, 0xb3, 0x07, - 0x6c, 0xd1, 0x78, 0x0a, 0xe4, 0xa8, 0xf4, 0x47, 0xde, 0x18, 0x9d, 0x9e, 0xe8, 0xf7, 0xf3, 0x29, 0xc5, 0x7c, 0xfd, - 0x1d, 0xe0, 0xb9, 0x6a, 0xb9, 0x00, 0x7d, 0x19, 0xea, 0xa0, 0x12, 0xa5, 0x56, 0x0c, 0x23, 0x16, 0xfe, 0x2e, 0x90, - 0xc8, 0x99, 0x02, 0x9b, 0x55, 0x94, 0x84, 0x4a, 0x54, 0x4a, 0xb6, 0x26, 0xa8, 0xa5, 0xf7, 0x45, 0x59, 0xef, 0x2b, - 0x70, 0x94, 0x8c, 0xb4, 0x59, 0x4e, 0x9a, 0x71, 0x05, 0xca, 0x5c, 0xf4, 0x83, 0xfd, 0xbd, 0xf2, 0xfc, 0x46, 0xe6, - 0xb3, 0xdc, 0x77, 0x74, 0x4e, 0xdb, 0x71, 0x81, 0x32, 0xb7, 0x9c, 0xb6, 0x5a, 0xf2, 0x98, 0xbc, 0x67, 0xc1, 0xb6, - 0xff, 0x2a, 0x41, 0x8a, 0x45, 0x98, 0x4f, 0xa8, 0xb2, 0xf9, 0x37, 0x84, 0xda, 0xe2, 0xc0, 0x1e, 0xbb, 0x30, 0x11, - 0xff, 0x2d, 0x58, 0x12, 0xc3, 0xac, 0x14, 0x61, 0xbc, 0x03, 0xef, 0x9f, 0x4d, 0x25, 0x46, 0x67, 0xe8, 0xe4, 0x7e, - 0x76, 0x9f, 0xd6, 0xc9, 0xd9, 0xab, 0x17, 0x67, 0x3f, 0xf6, 0x06, 0xc5, 0x28, 0x8d, 0x07, 0xbd, 0x1f, 0xcf, 0x56, - 0x1b, 0x40, 0xcb, 0x14, 0x67, 0x31, 0x99, 0xd2, 0x44, 0x7c, 0x46, 0x86, 0xc1, 0xb3, 0x3a, 0x11, 0x67, 0x34, 0x31, - 0xdd, 0xd7, 0x28, 0x4d, 0xbe, 0x1d, 0x85, 0x39, 0xbc, 0x5c, 0x8a, 0x4d, 0x25, 0x62, 0xb0, 0x53, 0xaa, 0x79, 0x96, - 0xb7, 0xcf, 0xe2, 0x7c, 0xd4, 0x21, 0xab, 0x74, 0xe0, 0x6f, 0x4f, 0xa4, 0x5d, 0x95, 0xae, 0x80, 0xd0, 0x03, 0xe0, - 0xa4, 0x2b, 0x7f, 0x1e, 0x0e, 0x79, 0x02, 0xa1, 0x16, 0xcc, 0xc9, 0x34, 0xa2, 0x1b, 0xd2, 0x35, 0xf6, 0x19, 0x98, - 0x85, 0x94, 0xe6, 0xc1, 0xcd, 0xd5, 0x62, 0xe8, 0xae, 0x58, 0x39, 0x0a, 0xab, 0xb5, 0x88, 0x6a, 0x64, 0x3d, 0x06, - 0xe7, 0x1d, 0x88, 0x00, 0x50, 0xe4, 0xe0, 0x19, 0x8f, 0xfa, 0xfd, 0x48, 0x05, 0xe5, 0xfc, 0x1f, 0xde, 0xde, 0x85, - 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, - 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, - 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, - 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0xec, 0xa5, 0x7a, 0x52, 0xae, 0x5f, 0x16, 0x8e, 0x32, - 0x65, 0x3f, 0xc4, 0x36, 0x46, 0x40, 0x75, 0xcb, 0x62, 0x13, 0x2e, 0x00, 0xb7, 0x73, 0x42, 0x9d, 0xf1, 0x1e, 0x6b, - 0x02, 0x73, 0x9a, 0x10, 0x14, 0xe6, 0x3a, 0x58, 0x18, 0x00, 0x7a, 0xd7, 0x1e, 0x6d, 0x39, 0xe9, 0x12, 0x2c, 0x9e, - 0x1b, 0x58, 0xbc, 0xba, 0x58, 0x54, 0x57, 0x5c, 0xcb, 0x2d, 0x6c, 0x4a, 0x59, 0xc5, 0x10, 0x40, 0xa0, 0x19, 0x33, - 0xec, 0x96, 0xbb, 0x1c, 0xc9, 0xba, 0x28, 0xb8, 0xd8, 0x0b, 0x0c, 0xdd, 0x8c, 0x4b, 0x66, 0x0e, 0xae, 0x66, 0x58, - 0x27, 0x15, 0x05, 0xd8, 0xd5, 0x05, 0xc8, 0x5e, 0x18, 0xea, 0xba, 0x99, 0x2d, 0xd7, 0x81, 0xaf, 0x4b, 0x17, 0xbe, - 0xa4, 0xe0, 0xe5, 0x4a, 0x8a, 0x32, 0xbb, 0xe6, 0x3f, 0xd9, 0x97, 0xcd, 0x58, 0x52, 0x68, 0x47, 0xfa, 0xba, 0xdd, - 0x1d, 0x2d, 0xc6, 0xb1, 0xe5, 0xf8, 0x96, 0x4a, 0xd7, 0x7a, 0x54, 0xbd, 0x10, 0xda, 0x3a, 0xd7, 0x32, 0x4b, 0x53, - 0x2e, 0x5e, 0x89, 0x34, 0x4b, 0xbc, 0xe4, 0x58, 0xc7, 0xaa, 0x76, 0x41, 0xb0, 0x5c, 0x98, 0xe4, 0x67, 0x59, 0x89, - 0xb1, 0x83, 0x1b, 0x8d, 0x6a, 0x45, 0x9d, 0x32, 0x31, 0x30, 0xe4, 0x7b, 0x0c, 0xbe, 0xcd, 0x8a, 0x04, 0x18, 0x7e, - 0x4c, 0xd4, 0x97, 0xf4, 0x14, 0x02, 0x3e, 0xa8, 0xd0, 0xdc, 0xcf, 0x38, 0x82, 0x5f, 0x5b, 0x95, 0x39, 0x30, 0xd9, - 0x5a, 0x05, 0x89, 0xb8, 0x77, 0xd9, 0x5c, 0x2f, 0xa2, 0x85, 0xba, 0x0b, 0xf5, 0xe2, 0xdd, 0xae, 0x97, 0x28, 0x3a, - 0xe0, 0xe4, 0xa7, 0xc1, 0x8b, 0x38, 0xcb, 0x79, 0x7a, 0x50, 0xc9, 0x03, 0xb5, 0xa1, 0x0e, 0x94, 0x33, 0x07, 0xec, - 0xbc, 0x6f, 0xab, 0x03, 0xbd, 0xa6, 0x0f, 0x74, 0x3b, 0x0f, 0xe0, 0x82, 0x81, 0x3b, 0xf7, 0x32, 0xbb, 0xe6, 0xe2, - 0x00, 0x94, 0x81, 0xd6, 0x78, 0xa0, 0x2e, 0xab, 0x91, 0x9a, 0x18, 0x1d, 0xc3, 0x3a, 0xd1, 0x07, 0x73, 0x40, 0x7f, - 0x86, 0xb0, 0xf6, 0xad, 0xb7, 0x2b, 0x7d, 0xd0, 0x06, 0xf4, 0xc5, 0xd2, 0xf4, 0x41, 0x07, 0x8e, 0x57, 0xd1, 0x81, - 0x1b, 0x43, 0xaa, 0x41, 0x5b, 0x8d, 0xac, 0x02, 0xc5, 0x1b, 0xde, 0xe2, 0xdd, 0xbb, 0x96, 0x6c, 0xbd, 0x97, 0x88, - 0xf1, 0x95, 0x89, 0x2a, 0xce, 0xc4, 0xa9, 0x97, 0xca, 0x6b, 0xed, 0x24, 0x23, 0x8c, 0x6f, 0x59, 0x49, 0xfd, 0x1d, - 0x62, 0x6e, 0x91, 0xe6, 0x30, 0x78, 0x15, 0x56, 0x64, 0xc6, 0xfb, 0x7d, 0x39, 0x93, 0x51, 0x39, 0x13, 0x87, 0x65, - 0xa4, 0xc0, 0xda, 0xee, 0x12, 0x01, 0xdd, 0x2b, 0x01, 0xf2, 0x05, 0x40, 0xd5, 0x7d, 0xc2, 0x9f, 0xfb, 0xa4, 0x3e, - 0x9d, 0x42, 0x9f, 0x42, 0x5b, 0xaf, 0xb8, 0x82, 0x78, 0x55, 0x37, 0x46, 0xb6, 0x51, 0x41, 0x8b, 0xc7, 0xf2, 0xac, - 0x36, 0x8c, 0xcd, 0xa9, 0xf5, 0xaf, 0x37, 0x1b, 0x4c, 0xd9, 0x5c, 0xa8, 0x55, 0x18, 0x92, 0xe8, 0x53, 0xe9, 0x45, - 0x12, 0xb1, 0xb0, 0x59, 0xad, 0xcd, 0x6f, 0xc2, 0x80, 0x64, 0x22, 0xc5, 0xfd, 0x6c, 0x89, 0x73, 0x17, 0x8f, 0xe7, - 0x55, 0x5f, 0x6b, 0x69, 0x91, 0x69, 0xf3, 0xad, 0xbe, 0x0c, 0x69, 0x2a, 0x6a, 0x48, 0xa3, 0xce, 0x0c, 0xba, 0x6f, - 0x97, 0xb7, 0xac, 0x46, 0x98, 0x00, 0xaf, 0x74, 0x06, 0xdd, 0x68, 0x3c, 0x10, 0xcb, 0x6a, 0x54, 0xac, 0x85, 0x40, - 0xe0, 0x61, 0xc8, 0x31, 0xb3, 0x84, 0x24, 0xfb, 0xcc, 0x7f, 0x50, 0x71, 0x16, 0x8a, 0xf8, 0xc6, 0x20, 0x7b, 0x57, - 0xd6, 0xb5, 0xbb, 0x8e, 0xfc, 0x9c, 0x58, 0x58, 0xed, 0x3f, 0x34, 0x8f, 0x5a, 0xe3, 0x2c, 0xa0, 0xad, 0x69, 0x75, - 0xc3, 0xe1, 0x1e, 0xd5, 0xb1, 0x28, 0x0d, 0x36, 0xb1, 0x47, 0x96, 0x8b, 0xd6, 0x31, 0x83, 0x06, 0xf4, 0xb7, 0xd9, - 0xd5, 0xfa, 0x0a, 0x01, 0xdc, 0x4a, 0x64, 0x9d, 0xa4, 0xf2, 0x2f, 0x69, 0x8f, 0xba, 0xb6, 0xa7, 0xf2, 0xbf, 0x6d, - 0x53, 0xe5, 0xd0, 0x62, 0xca, 0x63, 0x37, 0x67, 0x81, 0xea, 0x48, 0x10, 0x05, 0x6a, 0xeb, 0x05, 0x53, 0xef, 0x94, - 0x29, 0x3a, 0x40, 0xa0, 0x0b, 0x73, 0x86, 0x7d, 0xc5, 0x11, 0x63, 0x96, 0x4a, 0x0c, 0xa6, 0x3e, 0xc6, 0xa8, 0xa6, - 0xb5, 0x02, 0x74, 0xfd, 0x74, 0x0b, 0x7f, 0xa2, 0xa2, 0x46, 0x43, 0xad, 0x91, 0x14, 0x8a, 0x26, 0x2a, 0x14, 0x59, - 0x5a, 0xe8, 0xb8, 0x0a, 0x9d, 0x44, 0xc2, 0x12, 0xd0, 0x30, 0x21, 0x3a, 0xa9, 0xc0, 0x5b, 0x03, 0x38, 0xf3, 0x71, - 0x51, 0xae, 0x0b, 0x6d, 0x30, 0xf7, 0x32, 0xbe, 0xe6, 0xaf, 0x9e, 0x39, 0xa3, 0xfa, 0x96, 0xb5, 0xbe, 0xa7, 0x05, - 0x79, 0x19, 0x72, 0x8a, 0x0e, 0x4c, 0xec, 0x64, 0x8b, 0xc6, 0x18, 0x65, 0xad, 0xa3, 0x5e, 0xbc, 0xd5, 0xa1, 0x58, - 0xb4, 0x09, 0xde, 0x3d, 0x9e, 0x22, 0xda, 0xf0, 0x50, 0x18, 0xab, 0x6a, 0x7c, 0x2a, 0x59, 0x4b, 0x0f, 0x56, 0xf0, - 0x74, 0x9d, 0xf0, 0x10, 0xf4, 0x48, 0x84, 0x9d, 0x84, 0xc5, 0x3c, 0x5e, 0xc0, 0x71, 0x52, 0x10, 0x50, 0x3b, 0xe8, - 0x2b, 0xf8, 0x7c, 0x81, 0xee, 0xaf, 0x12, 0x3d, 0xc0, 0xd0, 0x82, 0xb8, 0x19, 0x05, 0x75, 0x74, 0x15, 0xaf, 0x1a, - 0x2a, 0x12, 0x3e, 0x2f, 0xc0, 0x76, 0x48, 0xa9, 0xa7, 0x40, 0x0b, 0x95, 0x28, 0xfd, 0x30, 0xf0, 0x1d, 0x1a, 0x03, - 0x5b, 0xeb, 0x00, 0x0d, 0xfd, 0x8c, 0x69, 0x6a, 0x9d, 0xa1, 0xf2, 0x99, 0x77, 0xcf, 0x8c, 0x96, 0x33, 0x8b, 0xc6, - 0xa0, 0x6f, 0xa3, 0x29, 0x8a, 0x73, 0xf2, 0x59, 0x50, 0xc4, 0x69, 0x16, 0xe7, 0xe0, 0xb7, 0x19, 0x17, 0x98, 0x31, - 0x89, 0x2b, 0x7e, 0x29, 0x0b, 0xd0, 0x76, 0xe7, 0x2a, 0xb5, 0xae, 0x41, 0x40, 0xf6, 0x12, 0xac, 0x5e, 0x1a, 0x3a, - 0x2a, 0xe7, 0xdd, 0xa5, 0x4d, 0x21, 0x12, 0x11, 0x82, 0x4d, 0x33, 0x5d, 0xb2, 0xd3, 0x50, 0x69, 0x73, 0x20, 0xd4, - 0x11, 0x1a, 0xf7, 0x4f, 0xc3, 0xd8, 0x6a, 0x8a, 0xad, 0xdd, 0xdb, 0x6e, 0xf7, 0xcf, 0xd2, 0x4b, 0xa7, 0x39, 0xe9, - 0x31, 0xf6, 0xcf, 0x32, 0x2c, 0x46, 0xb6, 0x23, 0x04, 0x96, 0x9c, 0xf7, 0xa9, 0xff, 0x8a, 0x96, 0xf3, 0x04, 0x4c, - 0x47, 0x74, 0xb0, 0x5c, 0xa0, 0xec, 0x18, 0xd0, 0x1d, 0x18, 0x5c, 0xd1, 0xef, 0x83, 0x55, 0x86, 0xb9, 0x90, 0x2c, - 0x49, 0xca, 0xe0, 0x79, 0xea, 0xc1, 0xc1, 0xaf, 0x99, 0x32, 0x77, 0x51, 0xd6, 0xa7, 0x4b, 0x32, 0x4d, 0x91, 0x81, - 0x58, 0x87, 0xdb, 0x2c, 0x8d, 0x12, 0x25, 0x22, 0x5b, 0xa2, 0x7f, 0xa4, 0xa1, 0x58, 0x3a, 0x72, 0x2f, 0x52, 0x25, - 0x42, 0xc5, 0x3c, 0xc5, 0x93, 0x3a, 0xad, 0xd3, 0x11, 0x86, 0x9e, 0x04, 0xa5, 0x5c, 0x0d, 0x03, 0x55, 0x52, 0xbd, - 0x14, 0xb6, 0xc5, 0x6e, 0xa7, 0x2f, 0x56, 0x62, 0x1e, 0x2f, 0xf0, 0xa5, 0xc0, 0x51, 0xfc, 0x27, 0xf7, 0xc2, 0x4e, - 0xa9, 0xed, 0x41, 0xed, 0x88, 0x12, 0xfa, 0x4f, 0x0e, 0x17, 0x89, 0x1f, 0xa4, 0x0e, 0x01, 0x88, 0x16, 0x21, 0x67, - 0xea, 0x20, 0x35, 0xdc, 0xd0, 0x9e, 0xf0, 0xdf, 0x70, 0x7d, 0xc6, 0x19, 0xbd, 0xa9, 0x66, 0xd4, 0x50, 0xbe, 0x1e, - 0xb4, 0x31, 0xea, 0xb3, 0x81, 0xc3, 0x0a, 0x51, 0x68, 0xc3, 0x4e, 0x4a, 0x25, 0x5a, 0x18, 0x4a, 0xf5, 0x97, 0x50, - 0x71, 0xc2, 0x9d, 0x19, 0x65, 0xc9, 0xf8, 0xb4, 0x3c, 0x16, 0xd3, 0xc1, 0xa0, 0x24, 0x95, 0xb1, 0xd0, 0x83, 0xeb, - 0x81, 0xe7, 0xdf, 0x03, 0xb7, 0x10, 0x0f, 0x19, 0x59, 0x0c, 0xb9, 0xc1, 0xc9, 0x6f, 0x71, 0x72, 0xd5, 0xa8, 0x54, - 0x71, 0xac, 0x89, 0x6a, 0xc1, 0x8f, 0x65, 0x18, 0xa0, 0x4f, 0x52, 0x00, 0x26, 0x83, 0x29, 0xbf, 0x05, 0x89, 0xd2, - 0x99, 0xba, 0x21, 0xfd, 0x22, 0x0a, 0x7e, 0xc1, 0x0b, 0x2e, 0x12, 0x57, 0x80, 0xe5, 0x1d, 0x6c, 0xaf, 0xa3, 0x8a, - 0x2a, 0x4c, 0x5e, 0xd3, 0xe3, 0x88, 0x1b, 0xef, 0x3f, 0xd3, 0x63, 0x8b, 0xd9, 0x6a, 0x1d, 0x1b, 0x7c, 0xe6, 0x18, - 0x5c, 0xd0, 0xb5, 0xc4, 0xd6, 0x50, 0x0d, 0x2b, 0x02, 0x03, 0x17, 0x70, 0x10, 0x96, 0x28, 0x8e, 0xad, 0xe4, 0x15, - 0x69, 0x48, 0x69, 0xef, 0x19, 0x8e, 0x36, 0xc9, 0xf1, 0x6d, 0x96, 0xdd, 0x04, 0xce, 0x17, 0x9d, 0x93, 0x66, 0xc2, - 0xda, 0xe0, 0x7d, 0xde, 0x9c, 0x5f, 0x77, 0x0f, 0x09, 0x55, 0x71, 0x6f, 0x78, 0x3b, 0xee, 0x8d, 0x13, 0x7e, 0xcd, - 0xc5, 0x42, 0x87, 0x6a, 0x31, 0x97, 0x2c, 0xbf, 0xb5, 0xde, 0x2d, 0x49, 0x6a, 0x05, 0xb4, 0xcf, 0xb2, 0xa0, 0x26, - 0x02, 0x40, 0xfe, 0xf0, 0x17, 0x08, 0x9d, 0xe1, 0x6f, 0x8f, 0xc1, 0x15, 0x29, 0xbc, 0x73, 0x08, 0x84, 0x35, 0xdd, - 0xdc, 0xab, 0x0d, 0xf8, 0x62, 0xdc, 0x9f, 0x31, 0xf5, 0xf4, 0xdb, 0x4c, 0xee, 0xeb, 0xba, 0x3d, 0xb2, 0x0c, 0x1f, - 0xe1, 0x4a, 0x01, 0xdc, 0x4c, 0xf8, 0x8b, 0x61, 0x26, 0xd5, 0x27, 0x80, 0xa9, 0xa6, 0x83, 0xfb, 0x04, 0x81, 0x01, - 0x54, 0xa2, 0xc5, 0xe8, 0x5a, 0x39, 0xa2, 0x19, 0xb8, 0x35, 0xdd, 0x0a, 0xe3, 0xad, 0x07, 0x2d, 0xf4, 0x4c, 0xc3, - 0x89, 0xff, 0xa0, 0x99, 0x57, 0x05, 0x04, 0xd0, 0xca, 0x08, 0xde, 0x5a, 0x9f, 0xcc, 0x11, 0xe2, 0x13, 0x96, 0x44, - 0x13, 0x16, 0xcf, 0x14, 0x3f, 0x26, 0x74, 0xdb, 0xd4, 0x36, 0x7d, 0x44, 0xfa, 0x8b, 0x6b, 0xd6, 0x4f, 0x59, 0xd6, - 0xbe, 0x3d, 0x54, 0xbc, 0x98, 0x36, 0xe3, 0x20, 0x26, 0xaa, 0x18, 0xff, 0x0b, 0xee, 0x4b, 0xad, 0x00, 0x91, 0xb9, - 0xab, 0x9e, 0x7e, 0xbf, 0x99, 0x2d, 0x07, 0x42, 0xe5, 0x77, 0x06, 0x49, 0x9f, 0x0e, 0xed, 0x07, 0x36, 0x89, 0xda, - 0x42, 0xcf, 0x1f, 0x97, 0xba, 0x89, 0x97, 0xd7, 0xa6, 0x46, 0xb4, 0x42, 0x86, 0xca, 0xd6, 0x01, 0xeb, 0xfb, 0x65, - 0xb8, 0xbf, 0xa8, 0x69, 0xa8, 0x75, 0xcf, 0x5d, 0x8b, 0x82, 0x13, 0x7f, 0x80, 0xb1, 0xb8, 0x90, 0xd4, 0x3a, 0x1e, - 0x93, 0x7e, 0xb4, 0x90, 0xc9, 0x8d, 0xba, 0x3a, 0x39, 0x53, 0xcc, 0x13, 0xb8, 0x00, 0x97, 0x6d, 0x7f, 0x45, 0xa5, - 0x2e, 0xe5, 0xf6, 0x8a, 0xd2, 0xf4, 0x90, 0xb6, 0x57, 0x71, 0xde, 0x16, 0x5c, 0xf0, 0xaf, 0x14, 0x5c, 0x58, 0x07, - 0xeb, 0x8e, 0x3b, 0x65, 0x4f, 0x78, 0xa2, 0x4c, 0x6b, 0x83, 0xbb, 0x6e, 0x30, 0x26, 0xc6, 0x7e, 0x77, 0xc9, 0x93, - 0x4f, 0xc8, 0x82, 0xff, 0x90, 0x09, 0xf0, 0x4c, 0x76, 0xaf, 0x54, 0xfe, 0x97, 0xfe, 0xd5, 0xd6, 0xbe, 0xb3, 0xe6, - 0x9f, 0x9e, 0xf5, 0x70, 0xe7, 0x30, 0xf9, 0xb1, 0x3a, 0x03, 0xba, 0xbd, 0x92, 0x29, 0x07, 0x64, 0x00, 0x6b, 0x91, - 0x8c, 0x06, 0x7c, 0x68, 0x65, 0xd9, 0xf6, 0x9d, 0x56, 0x17, 0x84, 0x3b, 0x09, 0xdc, 0xf4, 0xee, 0xda, 0xcc, 0xcc, - 0xe9, 0x5a, 0x89, 0xa6, 0x4b, 0x63, 0x6b, 0x59, 0xaa, 0x30, 0xde, 0xef, 0x3c, 0xc9, 0xa6, 0xf9, 0xf1, 0x72, 0x9a, - 0x5b, 0xea, 0xb6, 0x75, 0xcb, 0x06, 0xd0, 0x10, 0xbb, 0xd6, 0x56, 0x0e, 0x78, 0xb9, 0x3d, 0x88, 0xe6, 0x6b, 0x45, - 0xe8, 0xa9, 0x12, 0xa1, 0x4f, 0xd3, 0x66, 0x1f, 0xec, 0xaa, 0x5a, 0x37, 0x42, 0x1e, 0x0d, 0x52, 0xcd, 0xc8, 0xbf, - 0xbd, 0xe6, 0xc5, 0x45, 0x2e, 0x6f, 0x00, 0x0e, 0x99, 0xd4, 0x46, 0x61, 0x79, 0x05, 0xee, 0xfc, 0xe8, 0x38, 0xce, - 0xc4, 0x28, 0xc7, 0xb8, 0xad, 0x88, 0x94, 0xac, 0x13, 0x67, 0x80, 0x87, 0xec, 0x4f, 0x9a, 0x0e, 0xed, 0x5a, 0x60, - 0x78, 0x5f, 0xe0, 0xae, 0x72, 0x76, 0xb2, 0xcd, 0xed, 0xa2, 0x6f, 0xce, 0xb0, 0xee, 0x48, 0x69, 0x6d, 0x2c, 0xba, - 0xee, 0x60, 0xad, 0x19, 0xb4, 0x45, 0x28, 0xf9, 0x90, 0x3b, 0x69, 0x3f, 0x07, 0x34, 0x38, 0xcb, 0xd2, 0x5b, 0x6b, - 0x95, 0xbf, 0xd5, 0x42, 0x9c, 0x28, 0xa6, 0x4e, 0x7c, 0x13, 0x25, 0xfa, 0xfc, 0x4c, 0x8c, 0x1b, 0x08, 0xa4, 0xbe, - 0xc4, 0xf8, 0x1a, 0x45, 0x98, 0xc0, 0x75, 0x20, 0x8a, 0xed, 0x89, 0xda, 0x58, 0x8e, 0xa0, 0x13, 0x42, 0xbc, 0x83, - 0x32, 0x8c, 0xd5, 0xc5, 0x81, 0x36, 0x58, 0xfa, 0xba, 0xb5, 0xce, 0x0d, 0xa1, 0x30, 0x4e, 0x60, 0x8a, 0x41, 0x52, - 0x67, 0x9d, 0x65, 0x82, 0x2a, 0x3b, 0x26, 0x9d, 0xf7, 0x01, 0xba, 0xbf, 0x16, 0x4d, 0xf1, 0x75, 0xe7, 0x0e, 0xba, - 0x8b, 0xeb, 0xd7, 0x5a, 0xe4, 0x06, 0x7f, 0xde, 0x12, 0x61, 0x11, 0x38, 0x6b, 0x4d, 0xbe, 0x6a, 0x84, 0x03, 0x53, - 0x92, 0x69, 0xd8, 0xcb, 0x95, 0x4d, 0xf7, 0x6e, 0xd7, 0xeb, 0xdd, 0x29, 0xe2, 0xea, 0x31, 0x56, 0x79, 0x37, 0x73, - 0x7b, 0xa7, 0x5a, 0x8b, 0xfd, 0x9b, 0xb6, 0x9f, 0x62, 0x47, 0xad, 0xb5, 0xdb, 0x0d, 0x27, 0xd4, 0x90, 0x6f, 0x45, - 0x95, 0x56, 0xa7, 0x1b, 0x83, 0x76, 0x08, 0x6d, 0x2d, 0x32, 0xb8, 0x51, 0x3e, 0x73, 0x42, 0x27, 0x15, 0x72, 0xd5, - 0xa9, 0x0b, 0xb6, 0x57, 0xbc, 0x5a, 0xca, 0x34, 0x12, 0x14, 0x6d, 0xce, 0xa3, 0x92, 0x26, 0x72, 0x2d, 0xaa, 0x48, - 0xd6, 0xa8, 0x17, 0xb5, 0x1a, 0x03, 0x04, 0x64, 0x3a, 0x6b, 0x7a, 0x50, 0x05, 0xb3, 0xa1, 0x8c, 0xe4, 0xf4, 0x0d, - 0x58, 0xda, 0x23, 0xc7, 0x5a, 0xdf, 0x55, 0x67, 0x8b, 0x6f, 0xf5, 0x84, 0x60, 0x0a, 0xb3, 0x07, 0x22, 0xc2, 0x35, - 0x8d, 0x21, 0xa7, 0x5d, 0xe2, 0xb2, 0xa6, 0x5b, 0xc2, 0x1d, 0xdc, 0xae, 0x64, 0x27, 0x6e, 0x9e, 0x34, 0x37, 0x57, - 0xb0, 0x93, 0x62, 0x3e, 0x06, 0xed, 0x97, 0x54, 0xd7, 0x2e, 0xcd, 0xad, 0xc7, 0x83, 0x80, 0x06, 0x83, 0xc2, 0xf0, - 0xaf, 0x13, 0xe3, 0xe1, 0x49, 0x03, 0x82, 0xa4, 0x5c, 0x84, 0x63, 0xdf, 0x88, 0x7e, 0x32, 0x95, 0xc7, 0x1c, 0x2d, - 0xde, 0xa1, 0xd5, 0x39, 0x04, 0xf4, 0x12, 0xa1, 0x24, 0x46, 0x55, 0x68, 0x44, 0x50, 0x9e, 0x96, 0xbf, 0x54, 0xd5, - 0x21, 0xa0, 0x90, 0xf6, 0x15, 0x85, 0xb2, 0x4d, 0x62, 0x68, 0x86, 0x5f, 0xce, 0x27, 0x0b, 0x3d, 0x03, 0x03, 0x39, - 0x3f, 0x5a, 0xe8, 0x59, 0x18, 0xc8, 0xf9, 0xa3, 0x45, 0xed, 0xd6, 0x81, 0x26, 0x20, 0x9e, 0x0b, 0x47, 0x27, 0xa5, - 0x55, 0xd9, 0x02, 0xba, 0xbd, 0x8f, 0xa0, 0xff, 0xd3, 0x1e, 0x82, 0x4e, 0x2e, 0xb4, 0x27, 0x37, 0xa0, 0xed, 0x90, - 0x04, 0xf6, 0x8a, 0x49, 0x85, 0x89, 0x45, 0x74, 0xcc, 0xc6, 0x60, 0x88, 0xad, 0x3e, 0x38, 0x66, 0xe3, 0xa9, 0x4f, - 0x82, 0x80, 0xd1, 0x7d, 0x69, 0xc0, 0xc1, 0x6f, 0xf1, 0x2a, 0x7d, 0xb2, 0x15, 0xe8, 0xa6, 0xef, 0xee, 0x86, 0xde, - 0xc5, 0x15, 0x9c, 0xaa, 0xdd, 0x3d, 0x09, 0xdd, 0x64, 0xda, 0xb1, 0x7a, 0x0d, 0x71, 0x43, 0x7e, 0x65, 0x34, 0x1a, - 0xd9, 0x94, 0x90, 0x10, 0xc3, 0x39, 0x34, 0x73, 0x5a, 0x2e, 0x5f, 0xdd, 0x7a, 0xb6, 0x20, 0xc3, 0x4c, 0x6f, 0x99, - 0xac, 0xef, 0xa1, 0xac, 0x7a, 0x0c, 0xed, 0xd0, 0x7b, 0xe4, 0xf8, 0xfe, 0xc1, 0x37, 0x19, 0xbf, 0x70, 0xb8, 0xf6, - 0x70, 0x2e, 0x7c, 0x97, 0x35, 0x23, 0x73, 0xe8, 0x3c, 0xfb, 0x38, 0xde, 0xc3, 0x38, 0xf9, 0x32, 0x0b, 0xe5, 0x8d, - 0xd7, 0xf4, 0xbf, 0x55, 0x7a, 0xb3, 0xc3, 0x21, 0xa7, 0x2b, 0x58, 0x71, 0xb3, 0x2a, 0x34, 0xfc, 0x2c, 0xf2, 0xc6, - 0x11, 0xaf, 0x49, 0x54, 0x75, 0x9f, 0xf7, 0x36, 0x62, 0x69, 0xc7, 0x38, 0x00, 0x38, 0x51, 0xab, 0x86, 0x7d, 0x69, - 0x5c, 0xab, 0x83, 0x18, 0x91, 0x12, 0xb6, 0x4a, 0x1c, 0x09, 0xe5, 0x6f, 0x00, 0xc2, 0x62, 0x28, 0x8e, 0xb7, 0x86, - 0xf5, 0x1e, 0xf6, 0x43, 0x17, 0x68, 0x9a, 0x53, 0xaa, 0x19, 0x00, 0x24, 0x01, 0x7f, 0xf4, 0x74, 0xd3, 0x50, 0xd9, - 0xe6, 0x79, 0x68, 0x59, 0x5d, 0xc1, 0x3d, 0x3d, 0x75, 0x25, 0x03, 0xe3, 0xaa, 0x8e, 0xbd, 0xed, 0xdd, 0xed, 0xd1, - 0x2a, 0xf2, 0xbd, 0x4d, 0x6a, 0x9a, 0x05, 0x90, 0xa2, 0x71, 0xe9, 0x0b, 0x3d, 0x9d, 0x00, 0xad, 0xd7, 0x96, 0x8a, - 0xf6, 0xfb, 0x28, 0x46, 0x8d, 0x0b, 0x05, 0x56, 0x61, 0x82, 0xc2, 0x21, 0xc2, 0x08, 0xa1, 0x3f, 0x97, 0xe1, 0xd6, - 0x17, 0x64, 0x10, 0x0d, 0xd7, 0xa2, 0x43, 0x11, 0x39, 0x5e, 0xb4, 0x2d, 0x55, 0x35, 0x27, 0x4d, 0x5b, 0x02, 0x6f, - 0x22, 0x03, 0xb6, 0xf3, 0x4f, 0x1b, 0x22, 0x57, 0xe1, 0x02, 0x86, 0xef, 0x89, 0x6b, 0x41, 0x74, 0x53, 0x9b, 0x7a, - 0x1b, 0x76, 0x88, 0x8e, 0xa6, 0x78, 0x74, 0xc8, 0x3d, 0x77, 0xcf, 0x6d, 0x11, 0xdf, 0x7c, 0x81, 0xdc, 0x35, 0x9d, - 0xbd, 0x14, 0x61, 0x50, 0xb7, 0x6c, 0xa0, 0x58, 0xc7, 0x4e, 0x50, 0x80, 0x01, 0x5c, 0x3e, 0x03, 0x1d, 0x1b, 0x0c, - 0x2a, 0x82, 0x4f, 0x0a, 0xdb, 0xa6, 0x41, 0xfe, 0x88, 0x77, 0x43, 0x87, 0xd7, 0x96, 0x3c, 0x10, 0xaf, 0xb0, 0x2f, - 0x94, 0x70, 0xf7, 0x82, 0x82, 0xee, 0x28, 0x2f, 0x57, 0x85, 0xab, 0xd2, 0x00, 0x54, 0xd9, 0xf3, 0x5c, 0x6b, 0x4a, - 0x5a, 0xc0, 0x4a, 0x49, 0xdd, 0xf9, 0x4d, 0x70, 0xdc, 0x92, 0xa9, 0xf0, 0xad, 0xba, 0x51, 0xe5, 0xb1, 0x44, 0x91, - 0x8e, 0x3d, 0xdb, 0x39, 0x58, 0x03, 0xe0, 0x29, 0x6c, 0x2f, 0xce, 0x04, 0x7c, 0xee, 0xb4, 0xcb, 0x96, 0xb9, 0x04, - 0x8a, 0xfa, 0x7e, 0x9c, 0x97, 0x3d, 0x5f, 0xee, 0x8e, 0xb6, 0xf7, 0xd0, 0x1b, 0xb1, 0x31, 0x5e, 0x5f, 0x47, 0x4d, - 0xbf, 0x7a, 0x86, 0x2b, 0x4b, 0x41, 0xee, 0x69, 0xaa, 0x47, 0x18, 0x1d, 0x02, 0xd3, 0x94, 0x9f, 0xb0, 0xf1, 0x74, - 0x38, 0x34, 0x64, 0xd0, 0x6b, 0x26, 0x86, 0x02, 0xfb, 0x0a, 0x5a, 0x67, 0x26, 0xae, 0xf1, 0x69, 0xfb, 0x0a, 0x5a, - 0xdd, 0xa2, 0x4c, 0xee, 0x0c, 0x0c, 0x1f, 0x68, 0xc9, 0x14, 0x4c, 0x15, 0xde, 0x10, 0xa9, 0x64, 0x7f, 0x2e, 0xad, - 0xc3, 0xbe, 0x5d, 0x28, 0xb4, 0xd0, 0xc4, 0xaf, 0x32, 0xc4, 0x4f, 0x5d, 0x67, 0xfe, 0x63, 0xda, 0xa7, 0x06, 0xb1, - 0x70, 0x24, 0x06, 0x11, 0xbf, 0x38, 0x55, 0xb6, 0x13, 0x42, 0xc5, 0xc6, 0x43, 0xd7, 0xba, 0x71, 0x24, 0x55, 0x18, - 0x4a, 0xa1, 0xf1, 0xd4, 0x70, 0xdf, 0x0b, 0x1d, 0xbe, 0x0e, 0xb3, 0xb8, 0xcd, 0x1a, 0x49, 0x8d, 0x71, 0x2a, 0x4c, - 0x9c, 0x4a, 0xb9, 0x8a, 0x04, 0x06, 0xca, 0xb3, 0x85, 0x41, 0x80, 0x49, 0x4c, 0x32, 0xb6, 0x16, 0xc2, 0x84, 0xb1, - 0x73, 0x85, 0x69, 0xea, 0x22, 0xf5, 0x9b, 0x81, 0xc9, 0x82, 0x86, 0xfc, 0x1e, 0x8d, 0xd6, 0x54, 0x4d, 0x01, 0x86, - 0x71, 0x94, 0x6a, 0xfc, 0x47, 0x84, 0xda, 0x0c, 0x03, 0x00, 0xdb, 0xbc, 0x93, 0x99, 0xa8, 0x5e, 0x09, 0x84, 0x40, - 0x73, 0xf6, 0x53, 0x71, 0xb5, 0x37, 0x0b, 0x46, 0xd1, 0x6e, 0xaf, 0x7c, 0x3e, 0x70, 0x42, 0x79, 0xaa, 0x2e, 0x50, - 0x2f, 0x64, 0xf1, 0x5a, 0xa6, 0xbc, 0x15, 0x22, 0xf3, 0x40, 0xb2, 0xf7, 0xf9, 0x08, 0xce, 0x2b, 0x74, 0x2a, 0x37, - 0xdb, 0x44, 0x99, 0x25, 0x49, 0xc6, 0x02, 0x63, 0xf3, 0x12, 0xcc, 0xa4, 0x66, 0xc6, 0xf0, 0x6b, 0x88, 0x33, 0xb6, - 0x77, 0x12, 0x6e, 0xef, 0xe6, 0x81, 0x21, 0x4a, 0xb9, 0x68, 0x89, 0x86, 0xad, 0x1d, 0xaf, 0x27, 0xd7, 0x84, 0xfb, - 0xb0, 0x11, 0x6b, 0x32, 0xc6, 0xb8, 0x36, 0x37, 0xb2, 0x7e, 0xb4, 0xc0, 0x83, 0x31, 0x65, 0xfd, 0x09, 0x64, 0x5a, - 0x49, 0x59, 0xe7, 0x0b, 0x23, 0x66, 0x52, 0x89, 0xde, 0xed, 0x1b, 0x9f, 0xd5, 0x5d, 0x44, 0xfd, 0xd6, 0x7e, 0x4f, - 0xea, 0x61, 0xe3, 0x3f, 0x28, 0xac, 0x41, 0x65, 0xc4, 0x65, 0x44, 0x79, 0xe6, 0x40, 0x37, 0x4d, 0x8a, 0x38, 0x3d, - 0x5b, 0xc5, 0x45, 0xc9, 0x53, 0xa8, 0x54, 0x53, 0xb7, 0xa8, 0x37, 0x01, 0x7b, 0x43, 0x24, 0x49, 0xd6, 0xd2, 0xd8, - 0x8a, 0x5d, 0x1a, 0xa4, 0xe7, 0xce, 0x88, 0x4b, 0x2f, 0x2a, 0x34, 0xa4, 0xa5, 0xde, 0x59, 0xa8, 0x64, 0xfe, 0x8a, - 0xff, 0x0c, 0x6a, 0x05, 0x3a, 0xda, 0xa4, 0x18, 0x4f, 0x81, 0x11, 0xdf, 0x0f, 0x66, 0x75, 0x0f, 0x71, 0xd1, 0x04, - 0xa5, 0xde, 0x13, 0x3b, 0x7e, 0x69, 0xf2, 0xf0, 0x2e, 0xe4, 0x9c, 0xc1, 0xa7, 0xf7, 0xb3, 0x44, 0xad, 0x75, 0x24, - 0x46, 0x6a, 0x06, 0xd0, 0x74, 0x50, 0xe6, 0x3c, 0x16, 0xc1, 0xac, 0x67, 0x12, 0xa3, 0x1e, 0xd7, 0xbf, 0x40, 0x43, - 0xed, 0x37, 0x2b, 0xcb, 0xb3, 0x6a, 0xf3, 0x35, 0x1c, 0xd8, 0xd4, 0x56, 0xd0, 0xe3, 0x75, 0x25, 0x2f, 0x2f, 0x55, - 0xb7, 0xfd, 0x42, 0x8c, 0x9c, 0xae, 0x71, 0x2d, 0x9d, 0x57, 0x0b, 0xd6, 0xeb, 0x4e, 0x37, 0x8b, 0xbb, 0x59, 0x46, - 0x03, 0x61, 0x6d, 0xef, 0x13, 0xcd, 0x9f, 0x35, 0xdb, 0xee, 0xe3, 0x2d, 0x88, 0x59, 0x00, 0x10, 0xe9, 0x41, 0x14, - 0x2c, 0xb3, 0x94, 0x07, 0x54, 0xde, 0xc5, 0x51, 0x16, 0x4a, 0x2f, 0x67, 0x19, 0x3f, 0x6d, 0x1a, 0x6b, 0x9d, 0x15, - 0xca, 0xd0, 0xda, 0xe8, 0x4e, 0x57, 0x19, 0x62, 0xfb, 0x49, 0x9c, 0x2d, 0xc0, 0xfd, 0x31, 0x43, 0xa1, 0xa1, 0xb3, - 0x8c, 0x34, 0xd1, 0xf0, 0x5d, 0x77, 0x0c, 0x32, 0x8a, 0x93, 0x75, 0x5e, 0x49, 0xb7, 0xfa, 0xac, 0x8d, 0x84, 0xb9, - 0x87, 0xe8, 0x57, 0x31, 0x78, 0x94, 0xfb, 0xbc, 0x36, 0x3a, 0x99, 0x96, 0x91, 0x76, 0xe7, 0x27, 0xf5, 0x32, 0x4b, - 0xb5, 0x0e, 0xdb, 0x67, 0xd8, 0x5b, 0x63, 0xd2, 0x9b, 0x90, 0x1a, 0x46, 0xe2, 0xcb, 0x19, 0x35, 0x42, 0x40, 0x5b, - 0x8e, 0xbf, 0xc7, 0x67, 0x18, 0x9a, 0x02, 0x4b, 0x15, 0xb7, 0xb0, 0x1b, 0xbe, 0xe6, 0x93, 0x55, 0x0b, 0x40, 0x30, - 0x2b, 0x5f, 0xef, 0xe2, 0x95, 0x50, 0x9f, 0x69, 0x33, 0x00, 0x64, 0x41, 0x29, 0x77, 0xfc, 0x94, 0x4a, 0x07, 0x4b, - 0x14, 0x6d, 0x2f, 0xa7, 0x6f, 0x74, 0x6c, 0x7c, 0x9f, 0x9e, 0x0b, 0xd8, 0x2e, 0xe4, 0xb7, 0xee, 0xd4, 0x4b, 0x54, - 0xa4, 0xb6, 0xcd, 0xba, 0x87, 0x2f, 0x37, 0x68, 0x12, 0x46, 0x50, 0xa6, 0x4c, 0x01, 0x0c, 0x6e, 0xaa, 0x51, 0x30, - 0x69, 0x35, 0x12, 0xb6, 0xd4, 0x93, 0x2c, 0x37, 0x7d, 0x70, 0xaa, 0x3b, 0x04, 0x3d, 0xb7, 0xca, 0xf9, 0xa2, 0x65, - 0xbf, 0x56, 0x70, 0x74, 0x72, 0x35, 0x44, 0xcd, 0xbc, 0xd7, 0x76, 0x64, 0x48, 0xb9, 0x0c, 0x03, 0xc1, 0x94, 0x63, - 0x9e, 0x1e, 0x5b, 0xcf, 0x88, 0xe8, 0x9e, 0xb3, 0xcf, 0x74, 0xab, 0xae, 0x24, 0x20, 0x3a, 0x7e, 0xf7, 0xf8, 0xd5, - 0x55, 0x7c, 0x69, 0x50, 0x94, 0x1a, 0x16, 0x31, 0xca, 0xb4, 0xaf, 0x92, 0x30, 0x78, 0xbf, 0xbc, 0xff, 0x49, 0x65, - 0xa9, 0xfd, 0x1e, 0x6c, 0xad, 0xa8, 0xea, 0x97, 0x92, 0x17, 0x4d, 0x01, 0xd6, 0x5d, 0x96, 0x28, 0x90, 0xfb, 0xbd, - 0x4d, 0x33, 0xdf, 0x44, 0x8d, 0x9b, 0x0d, 0xeb, 0x8d, 0xeb, 0x76, 0xa9, 0x2d, 0xd9, 0x91, 0x95, 0xc8, 0x99, 0xc5, - 0x60, 0xc6, 0x8f, 0x0a, 0x83, 0xd2, 0xb0, 0x45, 0x55, 0x2a, 0x7e, 0x6f, 0x44, 0x70, 0xea, 0x58, 0x55, 0x18, 0xd3, - 0x80, 0xd9, 0x56, 0xd4, 0x1a, 0xd4, 0x41, 0x29, 0x6d, 0x4d, 0x40, 0xb6, 0x7f, 0xb1, 0x82, 0x9a, 0xdf, 0xff, 0x36, - 0x86, 0x7c, 0x4d, 0x29, 0xa8, 0x24, 0x60, 0x67, 0xd0, 0xe8, 0xa9, 0x12, 0x06, 0x52, 0x10, 0x3c, 0x01, 0xca, 0x17, - 0x51, 0x63, 0xb5, 0xdf, 0x57, 0xa7, 0xc6, 0x68, 0x0b, 0x08, 0x2d, 0xa4, 0x47, 0x97, 0x7d, 0xdc, 0xd6, 0x3a, 0x90, - 0x78, 0x70, 0x82, 0xed, 0x5c, 0x5d, 0xa3, 0x91, 0xd0, 0xfc, 0xbe, 0xd1, 0x80, 0xd7, 0xb4, 0x02, 0x85, 0x7a, 0x8e, - 0xa3, 0xa1, 0xb3, 0x43, 0x0a, 0x22, 0x36, 0x68, 0x61, 0xdf, 0x1d, 0x1f, 0x9a, 0x7d, 0x3d, 0x4f, 0x16, 0xa4, 0xa6, - 0xd2, 0x7d, 0xee, 0x96, 0x90, 0xb5, 0xea, 0x50, 0x56, 0x1e, 0xe0, 0x78, 0xa1, 0x64, 0xfe, 0x0e, 0x93, 0x1a, 0xa5, - 0x31, 0xa1, 0x31, 0x62, 0x01, 0x4b, 0x82, 0xf6, 0x7a, 0xa0, 0x7e, 0x19, 0x84, 0x0a, 0x67, 0x7a, 0x22, 0xf1, 0x29, - 0xe5, 0xea, 0xd3, 0x82, 0xd4, 0xd3, 0x82, 0x39, 0xd0, 0x4b, 0xdf, 0xca, 0xaf, 0x6c, 0x7c, 0xb4, 0xbf, 0x77, 0xcd, - 0x85, 0x75, 0x0c, 0x71, 0xb1, 0x85, 0xdf, 0x9c, 0x9a, 0x02, 0xb0, 0xe1, 0xa9, 0x2e, 0xcb, 0x37, 0x6a, 0x22, 0xb3, - 0x38, 0x24, 0x11, 0x48, 0xb6, 0x9b, 0x9b, 0xdb, 0x08, 0xb6, 0xbd, 0x85, 0xda, 0x50, 0x7f, 0x79, 0xdb, 0xfd, 0x8e, - 0xe1, 0xe5, 0x9e, 0xdc, 0xbb, 0x69, 0x43, 0xf9, 0xf2, 0xee, 0x55, 0xf2, 0x7f, 0x55, 0xc9, 0xdd, 0x56, 0x99, 0x75, - 0x5b, 0xbc, 0xdf, 0x75, 0xdc, 0x72, 0x8c, 0x06, 0x81, 0x35, 0x05, 0x06, 0xd2, 0x93, 0xc6, 0x34, 0xd1, 0xd1, 0x95, - 0x19, 0x33, 0x78, 0x74, 0x01, 0x9a, 0xc3, 0x74, 0x9e, 0xc7, 0x00, 0x1c, 0xe0, 0x1f, 0x79, 0x84, 0xfa, 0xa7, 0xf3, - 0x3c, 0x38, 0x0b, 0x06, 0xe5, 0x20, 0xd0, 0x9f, 0xb8, 0xe6, 0x04, 0x0b, 0xd0, 0xb9, 0xc5, 0x0c, 0xe2, 0x4e, 0x5a, - 0x33, 0x87, 0xf8, 0x38, 0x99, 0x0e, 0x06, 0x31, 0xd9, 0x02, 0x48, 0x5f, 0xbc, 0xb0, 0xce, 0x41, 0x85, 0x5e, 0x90, - 0xad, 0xba, 0x8b, 0x66, 0xc5, 0x5e, 0xb5, 0xd3, 0xbc, 0xdf, 0xcf, 0xe7, 0xe5, 0x20, 0x68, 0x54, 0x58, 0x18, 0xef, - 0x3f, 0xda, 0xfc, 0xd2, 0xe8, 0xa4, 0x09, 0x46, 0xac, 0x3d, 0x45, 0xf5, 0x8a, 0xa7, 0x19, 0x6d, 0xdc, 0x8e, 0x95, - 0xf2, 0x05, 0x44, 0xf1, 0xc0, 0x90, 0xb5, 0xf2, 0xee, 0x1d, 0xbc, 0x2e, 0x37, 0xde, 0x1c, 0x51, 0x80, 0xdd, 0x14, - 0xc6, 0x49, 0xcd, 0x45, 0x17, 0x35, 0xf1, 0x0c, 0x76, 0xba, 0x7a, 0x2b, 0xd1, 0x6a, 0xbc, 0x17, 0xef, 0x9b, 0x8d, - 0xbf, 0x91, 0x07, 0xba, 0xcc, 0x83, 0x0b, 0x40, 0x9c, 0x3d, 0x88, 0xab, 0x03, 0x2c, 0xf5, 0x20, 0x18, 0x58, 0xe4, - 0x90, 0x76, 0xb5, 0x7a, 0x28, 0x22, 0x75, 0x1e, 0x83, 0x01, 0x93, 0x69, 0x48, 0x4d, 0xa6, 0xbd, 0x58, 0x41, 0xda, - 0x58, 0x6b, 0x01, 0x6d, 0x38, 0x2c, 0xf6, 0xec, 0x86, 0xdd, 0xe9, 0xd6, 0xa1, 0x50, 0xc2, 0x40, 0xd6, 0x75, 0xf3, - 0x50, 0x6b, 0x78, 0x22, 0xe8, 0x41, 0x35, 0xda, 0x4f, 0x0f, 0xe5, 0x49, 0x7b, 0x2c, 0xc0, 0x45, 0x0f, 0x5f, 0x3e, - 0x17, 0x78, 0xd1, 0xde, 0x43, 0x9e, 0x33, 0x9f, 0x2a, 0x1f, 0xc4, 0x86, 0x5b, 0x86, 0x0f, 0xed, 0xe3, 0x5b, 0x81, - 0x4c, 0xea, 0x8e, 0xa6, 0xb6, 0x76, 0x47, 0xe3, 0x98, 0x40, 0xbf, 0x29, 0x47, 0x29, 0x13, 0x53, 0xcb, 0x92, 0x9d, - 0xf4, 0x72, 0xe5, 0x0d, 0x95, 0xb2, 0x93, 0x65, 0x9b, 0xf3, 0x4b, 0x1b, 0x09, 0xfd, 0xbe, 0x76, 0x07, 0xc2, 0x37, - 0x6a, 0xbd, 0x21, 0x2f, 0x1b, 0x22, 0x96, 0x43, 0xcc, 0xc0, 0xf1, 0x42, 0x2a, 0xd7, 0xee, 0xa2, 0xa9, 0xaa, 0xdb, - 0xdb, 0xca, 0x05, 0x2d, 0xf1, 0x56, 0x0a, 0xac, 0x22, 0x75, 0x7a, 0x3d, 0x95, 0x78, 0xd7, 0x47, 0xb1, 0xfd, 0x08, - 0xd8, 0xc6, 0xc6, 0xd1, 0xd8, 0xb8, 0x45, 0x6c, 0xf1, 0x55, 0x54, 0xd1, 0x82, 0x03, 0x04, 0x77, 0x5b, 0x52, 0x4b, - 0x33, 0x87, 0xb8, 0xaf, 0x78, 0x80, 0xf6, 0x5d, 0x1c, 0xce, 0xa4, 0x02, 0x6c, 0xeb, 0x5a, 0xe7, 0xac, 0x96, 0x03, - 0x36, 0x13, 0x3d, 0xff, 0xb4, 0x6a, 0x24, 0x62, 0x58, 0x65, 0x23, 0x65, 0x85, 0x76, 0xaf, 0x74, 0x09, 0x17, 0x5f, - 0x80, 0x97, 0xed, 0xbb, 0x95, 0xdd, 0x67, 0x4b, 0xec, 0x1f, 0xe6, 0x55, 0x13, 0x3c, 0xf2, 0x1a, 0x6f, 0xef, 0x61, - 0xe2, 0x6b, 0xa5, 0x10, 0x5e, 0xa5, 0x34, 0x94, 0x00, 0x0c, 0x92, 0xa0, 0x86, 0x2b, 0x6d, 0x9b, 0x41, 0x2a, 0x63, - 0xd8, 0xfd, 0xea, 0xad, 0xfe, 0x4f, 0xab, 0x70, 0x51, 0xc9, 0x62, 0x4c, 0x02, 0x9d, 0x53, 0x2d, 0x37, 0x81, 0x05, - 0xcf, 0xf6, 0xc9, 0x11, 0x28, 0xec, 0x04, 0x70, 0x43, 0x09, 0xfb, 0x0b, 0x6f, 0x43, 0x39, 0xfb, 0x6c, 0x25, 0x4f, - 0x6e, 0x5f, 0x52, 0x41, 0x13, 0x32, 0x15, 0x76, 0xff, 0xb6, 0x36, 0xec, 0xb3, 0x50, 0x8e, 0xa4, 0xc0, 0xc5, 0x41, - 0xe7, 0x00, 0xf6, 0x07, 0xb9, 0x8c, 0xcd, 0x67, 0xd2, 0xef, 0xab, 0xf7, 0x4f, 0xf3, 0x2c, 0xf9, 0xb4, 0xf7, 0xde, - 0xf0, 0x34, 0x4b, 0x06, 0x54, 0x22, 0xa6, 0xd6, 0x55, 0x31, 0x5c, 0x6a, 0x17, 0xe3, 0x06, 0xc9, 0x88, 0xef, 0xa4, - 0x0e, 0x31, 0x62, 0x7c, 0x91, 0x3d, 0x92, 0x92, 0xd3, 0x65, 0xdd, 0xd9, 0x73, 0x2d, 0x9a, 0x41, 0x63, 0xb8, 0x3d, - 0xef, 0x25, 0xbd, 0x02, 0x54, 0x80, 0xe8, 0x9e, 0x05, 0xae, 0xe1, 0xcd, 0x25, 0xd1, 0xd8, 0xd2, 0xd3, 0x96, 0x68, - 0xe0, 0x4e, 0x99, 0x90, 0x54, 0x1b, 0x07, 0x58, 0xc4, 0xba, 0xfe, 0x14, 0x16, 0x00, 0xd4, 0x6a, 0x90, 0x5e, 0xe9, - 0x0b, 0x42, 0x55, 0x12, 0x82, 0xd1, 0x89, 0x84, 0x97, 0x01, 0x8d, 0x33, 0x93, 0x68, 0x61, 0x83, 0x03, 0xfa, 0xaa, - 0x32, 0x89, 0xc6, 0x86, 0x3c, 0xa0, 0xdc, 0xa6, 0x01, 0x0c, 0x3e, 0x48, 0x92, 0xe8, 0x4f, 0x4b, 0x93, 0x04, 0x82, - 0x12, 0x94, 0x6f, 0xd0, 0xdf, 0x4b, 0xcf, 0xc7, 0xf2, 0x1f, 0xde, 0xa1, 0xf4, 0x32, 0x2c, 0x40, 0xa6, 0xa8, 0x2b, - 0xa6, 0x19, 0x3b, 0xc9, 0xba, 0x8d, 0x49, 0x3c, 0x4f, 0xbb, 0xeb, 0x42, 0xb9, 0x74, 0x81, 0x5f, 0x59, 0x86, 0x38, - 0xd6, 0x4f, 0xe3, 0x15, 0x3b, 0x0d, 0xb9, 0xc6, 0x4b, 0x7f, 0x1a, 0xaf, 0x70, 0x86, 0x68, 0xd5, 0x4a, 0x20, 0xca, - 0x7f, 0xd5, 0x06, 0x0e, 0x71, 0x9f, 0x60, 0x90, 0x8b, 0xca, 0x7b, 0x20, 0x90, 0xb7, 0x15, 0x44, 0xa4, 0x99, 0x5d, - 0x87, 0x11, 0xa9, 0xf6, 0x92, 0xcc, 0x97, 0xff, 0x90, 0x99, 0xf0, 0xbe, 0x81, 0xc7, 0x66, 0xb3, 0x6c, 0x8a, 0xf9, - 0x42, 0x05, 0x73, 0x70, 0x9f, 0xa8, 0xb8, 0x14, 0x95, 0xff, 0x84, 0x5d, 0xf0, 0x62, 0x3c, 0x78, 0xbd, 0x46, 0x80, - 0xfd, 0xca, 0x7f, 0xf2, 0xc6, 0xec, 0x07, 0xeb, 0xc6, 0x97, 0x99, 0x88, 0x0f, 0x7c, 0x74, 0x4b, 0xf9, 0x68, 0xe3, - 0x65, 0xfa, 0xb5, 0x01, 0x25, 0x32, 0x2a, 0x2b, 0xbe, 0x5a, 0xf1, 0x74, 0x76, 0x93, 0x44, 0xd9, 0xa8, 0xe2, 0x02, - 0xa6, 0x17, 0x1c, 0xef, 0x92, 0xf5, 0x79, 0x96, 0xbc, 0x82, 0xd8, 0x03, 0x2b, 0xa9, 0xb0, 0xf8, 0x61, 0x99, 0xa9, - 0xc5, 0x2c, 0x64, 0x25, 0x05, 0x0f, 0x66, 0x9f, 0x92, 0xe8, 0x87, 0xa5, 0x07, 0x22, 0x67, 0xa6, 0x6c, 0x5b, 0x3b, - 0x42, 0x6d, 0x7c, 0x1d, 0xe9, 0x56, 0x5b, 0x00, 0xc0, 0x3d, 0x5b, 0xa4, 0x91, 0x64, 0x62, 0x38, 0xa9, 0x19, 0x37, - 0xe9, 0x05, 0xa6, 0xc6, 0x35, 0xab, 0x68, 0xe2, 0x2c, 0x64, 0x40, 0xef, 0x4f, 0x73, 0xfd, 0x9c, 0xc1, 0xfd, 0x07, - 0xad, 0x81, 0xcb, 0xe3, 0xa2, 0xdf, 0x97, 0xc7, 0xc5, 0x6e, 0x57, 0x9e, 0xc4, 0xfd, 0xbe, 0x3c, 0x89, 0x0d, 0xff, - 0xa0, 0x14, 0xdb, 0xc6, 0xdc, 0x20, 0xa1, 0xb9, 0x84, 0xa8, 0x45, 0x23, 0xf8, 0x43, 0xb3, 0x9c, 0x8b, 0x28, 0x3f, - 0x4e, 0xfa, 0xfd, 0xde, 0x72, 0x26, 0x06, 0xf9, 0x30, 0x89, 0xf2, 0x61, 0xe2, 0x39, 0x21, 0xbe, 0xf4, 0x9c, 0x10, - 0x15, 0x0d, 0x5c, 0xc1, 0x99, 0x01, 0x88, 0x02, 0x3e, 0xfd, 0xa3, 0xba, 0x96, 0x42, 0xd7, 0x12, 0xab, 0x5a, 0x12, - 0x5d, 0x41, 0xcd, 0x6e, 0x8a, 0xb0, 0xc4, 0x52, 0xe8, 0x92, 0xfd, 0xba, 0x04, 0x9e, 0x28, 0xe7, 0xd5, 0x16, 0x18, - 0xd8, 0x08, 0xef, 0x1c, 0x26, 0x9c, 0xc4, 0xba, 0x06, 0xb4, 0xd3, 0x6d, 0x4d, 0x2f, 0xe8, 0x8a, 0x5e, 0x22, 0x3f, - 0x7b, 0x01, 0x06, 0x4b, 0xc7, 0x2c, 0x9f, 0x0e, 0x06, 0x17, 0x64, 0xc5, 0xca, 0x79, 0x18, 0x0f, 0xc2, 0xf5, 0x2c, - 0x1f, 0x5e, 0x44, 0x17, 0x84, 0x7c, 0x53, 0x2c, 0x68, 0x6f, 0x35, 0x2a, 0x3f, 0x65, 0x10, 0xde, 0x2f, 0x9d, 0x85, - 0x99, 0x89, 0xf3, 0xb1, 0x1a, 0xdd, 0xd2, 0x15, 0xc4, 0xaf, 0x81, 0x1b, 0x09, 0x89, 0xa0, 0x23, 0x97, 0x74, 0x45, - 0xd7, 0x54, 0x9a, 0x19, 0xc6, 0x68, 0xdd, 0xf6, 0x38, 0x49, 0xc0, 0x31, 0xd9, 0x15, 0x1f, 0x8d, 0x55, 0xe1, 0x5d, - 0xdf, 0x11, 0xda, 0xeb, 0x25, 0x6e, 0x90, 0x7e, 0x69, 0x0f, 0x12, 0x30, 0x22, 0x23, 0x35, 0x50, 0x66, 0x64, 0x24, - 0x35, 0x93, 0x8a, 0x43, 0x12, 0xfb, 0x43, 0xa2, 0xc6, 0x21, 0xf1, 0xc7, 0x21, 0xd7, 0xe3, 0x80, 0xdc, 0xfd, 0x92, - 0x8d, 0x69, 0xca, 0xc6, 0x74, 0xad, 0x46, 0x85, 0x5e, 0xd1, 0x73, 0x4d, 0x1d, 0xcf, 0xd8, 0x53, 0x38, 0xb0, 0x07, - 0x61, 0x3e, 0x8b, 0x87, 0x4f, 0xa3, 0xa7, 0x84, 0x7c, 0x23, 0xe9, 0xb5, 0xba, 0x94, 0x41, 0x20, 0xc4, 0x2b, 0x70, - 0x2e, 0x75, 0xa1, 0x4e, 0xae, 0xcc, 0x8e, 0xc3, 0xa7, 0xcb, 0xc6, 0xd3, 0x39, 0x44, 0xf4, 0x41, 0x2b, 0x95, 0x7e, - 0x3f, 0xbc, 0x60, 0xe5, 0xfc, 0x2c, 0x1c, 0x13, 0xc0, 0xe1, 0xd1, 0xc3, 0x79, 0x31, 0xba, 0xa5, 0x17, 0xa3, 0x0d, - 0x01, 0x0b, 0xaf, 0xf1, 0x74, 0x7d, 0xcc, 0xe2, 0xe9, 0x60, 0xb0, 0x46, 0xaa, 0xae, 0x72, 0xaf, 0xc9, 0x82, 0x5e, - 0xe0, 0x44, 0x10, 0x60, 0xe8, 0x33, 0xb1, 0x36, 0x34, 0xfc, 0x29, 0x83, 0x8f, 0x37, 0xec, 0x62, 0xb4, 0xa1, 0xb7, - 0xec, 0xe9, 0x6e, 0x3c, 0x05, 0x66, 0x6a, 0x35, 0x0b, 0x37, 0xc7, 0x97, 0xb3, 0x4b, 0xb6, 0x89, 0x36, 0x27, 0xd0, - 0xd0, 0x2b, 0xb6, 0x41, 0xc0, 0xa5, 0xf4, 0xe1, 0x72, 0xf0, 0x94, 0x1c, 0x0e, 0x06, 0x29, 0x89, 0xc2, 0xeb, 0xd0, - 0x6b, 0xe5, 0x53, 0xba, 0x21, 0x74, 0xc5, 0x6e, 0x71, 0x34, 0x2e, 0x19, 0x7e, 0x70, 0xce, 0x36, 0xf5, 0x75, 0xe8, - 0xed, 0xe6, 0x5c, 0x74, 0x82, 0x18, 0xa1, 0xaf, 0x81, 0xa3, 0x59, 0x2e, 0xcc, 0x04, 0x3c, 0x99, 0x8b, 0x8c, 0x16, - 0x85, 0x66, 0x20, 0xce, 0x4a, 0x40, 0x2c, 0x89, 0xba, 0xdf, 0x6c, 0x74, 0x06, 0xcb, 0xb9, 0xdf, 0xef, 0x55, 0x86, - 0x1e, 0x20, 0x72, 0x66, 0x27, 0x3d, 0xe8, 0xf9, 0xf4, 0x00, 0x3f, 0xd1, 0xab, 0x06, 0x71, 0x32, 0x7f, 0x59, 0x46, - 0x2f, 0x3d, 0xfa, 0xf0, 0x5b, 0x37, 0xe5, 0x91, 0xf9, 0x7f, 0x4e, 0x79, 0x8a, 0x3c, 0x7a, 0x5d, 0x79, 0x40, 0x6c, - 0xde, 0x9a, 0x54, 0x1a, 0x89, 0x6a, 0x74, 0xb6, 0x8a, 0x41, 0x1b, 0x89, 0xda, 0x06, 0xfd, 0x84, 0x16, 0x56, 0x10, - 0x21, 0xe7, 0xe8, 0x19, 0x18, 0xa4, 0x42, 0xa8, 0x1c, 0xb5, 0x28, 0xd1, 0x10, 0x24, 0x97, 0x25, 0x57, 0xe1, 0x73, - 0x08, 0x55, 0xa7, 0x8f, 0x33, 0x11, 0x36, 0xf4, 0x38, 0xf4, 0x01, 0xe0, 0xff, 0xda, 0x23, 0x17, 0x25, 0xbf, 0xc4, - 0xb3, 0xb9, 0x4d, 0x30, 0x0a, 0x96, 0x8b, 0x66, 0x68, 0x1b, 0xc4, 0x7e, 0x2c, 0x09, 0xd6, 0x23, 0x69, 0x3c, 0x2a, - 0xcd, 0x11, 0xe1, 0x47, 0xf1, 0x51, 0xf4, 0x34, 0x36, 0x24, 0x92, 0x23, 0x89, 0xe4, 0x03, 0x20, 0x9c, 0x04, 0xfd, - 0xc5, 0x5d, 0x93, 0x5d, 0x0b, 0xb5, 0xd7, 0xef, 0xc1, 0xbf, 0x96, 0x4c, 0xcb, 0xee, 0x55, 0x8f, 0x7d, 0x45, 0x90, - 0x07, 0x13, 0xe0, 0xf5, 0xe1, 0x5f, 0x4b, 0x9c, 0x41, 0xeb, 0xf9, 0xa2, 0x3a, 0x33, 0xf3, 0x06, 0x37, 0xf2, 0xba, - 0xac, 0x5d, 0x97, 0x2f, 0xf8, 0x01, 0xbf, 0xad, 0xb8, 0x48, 0xcb, 0x83, 0x9f, 0xab, 0x36, 0x9e, 0x53, 0xb9, 0x5e, - 0xb9, 0x38, 0x2b, 0xca, 0x38, 0xd5, 0x93, 0xba, 0x18, 0x6b, 0xd8, 0x86, 0xdf, 0x23, 0xea, 0x4a, 0x5a, 0x8e, 0x9e, - 0x52, 0xae, 0x9a, 0x29, 0x17, 0xeb, 0x3c, 0xff, 0x69, 0x2f, 0x15, 0xa7, 0xb8, 0x99, 0x82, 0x54, 0xa9, 0xe5, 0x02, - 0xaa, 0xe7, 0xa8, 0xe5, 0x6e, 0x69, 0x76, 0x80, 0x73, 0xdb, 0x54, 0x1f, 0x2b, 0xb3, 0x0b, 0x2f, 0xb9, 0x71, 0x7f, - 0x32, 0x65, 0x58, 0x30, 0x0a, 0x6d, 0x56, 0x5d, 0x69, 0xfb, 0x42, 0xeb, 0x34, 0x0c, 0x57, 0x7e, 0xbc, 0x80, 0x74, - 0x01, 0xe3, 0x78, 0x51, 0x32, 0x31, 0x6e, 0x8f, 0xde, 0x0a, 0xe2, 0x6b, 0xb6, 0x02, 0xe9, 0xf7, 0x7b, 0xc2, 0xdb, - 0x75, 0x1d, 0x6d, 0xf7, 0xc4, 0x29, 0xa3, 0x72, 0x15, 0x8b, 0x1f, 0xe3, 0x95, 0x81, 0x4c, 0x56, 0xc7, 0x63, 0x63, - 0x4c, 0xa7, 0x3f, 0x27, 0xa1, 0x5f, 0x08, 0x05, 0x9f, 0xf5, 0xd2, 0xca, 0x93, 0xdb, 0xc3, 0x32, 0xae, 0xd1, 0x2b, - 0x71, 0xa5, 0xfb, 0x66, 0xa4, 0x90, 0x7a, 0xe4, 0xab, 0xa6, 0x80, 0xde, 0x8c, 0x7d, 0x33, 0x15, 0xe6, 0xed, 0x8e, - 0x31, 0x57, 0x08, 0x56, 0xaa, 0xec, 0xf6, 0x9d, 0x1a, 0x53, 0x31, 0x83, 0x29, 0xb6, 0x9d, 0xc5, 0xa4, 0x5b, 0xf9, - 0xa7, 0x9d, 0xfb, 0x75, 0xde, 0xe1, 0xae, 0xa8, 0xdf, 0x02, 0x17, 0x9a, 0x15, 0x65, 0xd5, 0x96, 0x0d, 0xdb, 0xc6, - 0x1b, 0x59, 0x28, 0x36, 0xc0, 0xb2, 0xe7, 0xbe, 0x85, 0x07, 0x88, 0x9b, 0x70, 0xcf, 0x2e, 0x6a, 0xb8, 0x31, 0x7c, - 0x5d, 0x49, 0xbe, 0x2b, 0x8d, 0xb9, 0xf4, 0xa9, 0xd2, 0xc4, 0x70, 0xb2, 0x18, 0x71, 0x91, 0x2e, 0xea, 0xcc, 0xae, - 0x85, 0x2f, 0x78, 0x19, 0xce, 0xf9, 0xc2, 0xe8, 0xa6, 0x74, 0xe9, 0x05, 0xd3, 0x21, 0x53, 0xe8, 0x76, 0xa5, 0xb1, - 0x52, 0x22, 0x6e, 0xcd, 0x32, 0x81, 0xb2, 0x94, 0xb5, 0x12, 0xde, 0x14, 0x2d, 0x5b, 0x49, 0x23, 0xef, 0x99, 0x83, - 0xfb, 0xd8, 0x6f, 0x88, 0x89, 0x6c, 0x02, 0x93, 0xa2, 0xa1, 0x03, 0xda, 0x55, 0x17, 0xbe, 0x19, 0xf5, 0x60, 0x90, - 0x5b, 0x92, 0x88, 0x15, 0xa4, 0x58, 0xc1, 0xba, 0x66, 0xc5, 0x3c, 0x5f, 0xd0, 0x0b, 0x26, 0xe7, 0xe9, 0x82, 0xae, - 0x98, 0x9c, 0xaf, 0xf1, 0x26, 0x74, 0x01, 0x27, 0x24, 0xd9, 0xc6, 0x4a, 0x01, 0x7b, 0x81, 0x97, 0x37, 0x3c, 0x53, - 0x35, 0x2d, 0xbb, 0x54, 0x1c, 0x60, 0x7c, 0x5e, 0x86, 0x61, 0x39, 0xbc, 0x00, 0x6b, 0x89, 0xc3, 0x70, 0x35, 0xe7, - 0x0b, 0xf5, 0x1b, 0xa2, 0xce, 0x27, 0xa1, 0x62, 0x17, 0xec, 0x5e, 0x20, 0xd3, 0xab, 0x39, 0x5f, 0xa8, 0x91, 0xd0, - 0x05, 0x5f, 0x59, 0x63, 0x93, 0xd8, 0x13, 0xb4, 0xcc, 0xe2, 0xf9, 0x78, 0x11, 0xc5, 0x35, 0x2c, 0xc3, 0x0f, 0x6a, - 0x66, 0x5a, 0xf2, 0x9f, 0x5c, 0x6d, 0x68, 0xa2, 0x6f, 0xb0, 0x8a, 0xfc, 0xe1, 0xf1, 0xd1, 0x25, 0x90, 0xb1, 0xb3, - 0x2b, 0x99, 0xf9, 0xd0, 0xf7, 0x91, 0xc1, 0x3d, 0x37, 0xe5, 0x8c, 0xab, 0x20, 0x51, 0x06, 0xee, 0x5e, 0xcd, 0x92, - 0xb1, 0x16, 0xe1, 0xfb, 0x47, 0x45, 0xd1, 0x67, 0xd2, 0x34, 0xa0, 0xfb, 0x48, 0x30, 0x07, 0x7a, 0xaf, 0xd0, 0xe1, - 0xb2, 0xda, 0x66, 0x02, 0xfe, 0x22, 0x41, 0x7e, 0x2b, 0xf4, 0xaa, 0xc6, 0xa0, 0x8a, 0x76, 0x11, 0x4b, 0xff, 0x3e, - 0xe2, 0x47, 0xd9, 0xfc, 0xa7, 0xb9, 0xc7, 0x2b, 0x09, 0x83, 0x1f, 0x52, 0xb3, 0x49, 0xe6, 0xed, 0x15, 0xfb, 0x0e, - 0x3a, 0xea, 0x51, 0x6b, 0xbc, 0xaf, 0x5e, 0x70, 0x0a, 0x31, 0x4a, 0x28, 0x3a, 0x09, 0x06, 0x70, 0xbb, 0x84, 0x14, - 0x77, 0x83, 0xdd, 0x36, 0xaf, 0x79, 0x51, 0x70, 0xbe, 0xae, 0xaa, 0xc0, 0x0f, 0x68, 0x38, 0x5f, 0xec, 0x87, 0x30, - 0x1c, 0xd3, 0xd6, 0x35, 0x0c, 0xc2, 0x8c, 0x61, 0x24, 0x04, 0xaf, 0x7f, 0xd1, 0x23, 0x9a, 0xc4, 0xab, 0x1f, 0xf8, - 0xe7, 0x8c, 0x17, 0x8a, 0x48, 0x83, 0x08, 0xa9, 0x9b, 0xf8, 0x46, 0xa6, 0x49, 0x01, 0x85, 0x00, 0xa3, 0x80, 0x4a, - 0x6c, 0x68, 0x2a, 0xfe, 0x56, 0x8b, 0x0f, 0x7e, 0x6a, 0x3a, 0x1e, 0x8d, 0xeb, 0x56, 0x67, 0x54, 0xd0, 0x19, 0xe8, - 0x51, 0x2b, 0xea, 0x69, 0xd0, 0x4a, 0x30, 0x8d, 0x34, 0x6f, 0xdd, 0x43, 0xe0, 0x95, 0x69, 0xf1, 0xce, 0x03, 0xba, - 0x3d, 0xf3, 0xc1, 0x93, 0xc7, 0xf4, 0xcc, 0xa1, 0x27, 0x57, 0xec, 0xa4, 0xea, 0xa1, 0xf6, 0xde, 0x8c, 0x50, 0xd0, - 0xef, 0x63, 0x0a, 0x74, 0x23, 0xa8, 0xbd, 0xab, 0x7b, 0x25, 0xf7, 0x39, 0x7c, 0xc7, 0x59, 0x6e, 0x01, 0x4b, 0x45, - 0xd6, 0x0a, 0x3c, 0x0a, 0x50, 0x97, 0xca, 0x10, 0xb6, 0x98, 0xc3, 0xa1, 0xb2, 0x5b, 0xb5, 0x1a, 0x4a, 0x72, 0x5c, - 0x8e, 0xc0, 0x21, 0x74, 0x5d, 0x0e, 0xca, 0xd1, 0x32, 0xab, 0xde, 0xe3, 0x6f, 0xcd, 0x3a, 0x24, 0xd9, 0x5d, 0xac, - 0x03, 0xb7, 0xac, 0xc3, 0xf4, 0x93, 0x41, 0x0a, 0x40, 0x93, 0x8d, 0xc0, 0x25, 0x00, 0xef, 0xed, 0x3f, 0x22, 0xd4, - 0xca, 0xf4, 0x4e, 0xc6, 0x42, 0x7d, 0xdf, 0x48, 0x82, 0x12, 0x9a, 0x09, 0x95, 0x63, 0x29, 0x78, 0xe7, 0x91, 0xce, - 0x49, 0x9d, 0x89, 0xf7, 0x20, 0x4e, 0x0b, 0xef, 0xd9, 0x5b, 0x10, 0x9c, 0xb3, 0xa0, 0x1b, 0xbc, 0xcd, 0x6a, 0xa9, - 0x8d, 0x1e, 0x28, 0x80, 0xdf, 0x0d, 0x36, 0x08, 0xf2, 0xd5, 0x18, 0xae, 0x95, 0xbc, 0x09, 0xf9, 0xb0, 0xa0, 0x47, - 0x64, 0x60, 0x9f, 0xc5, 0x30, 0xa6, 0x47, 0xe4, 0xd8, 0x3e, 0x4b, 0x37, 0x80, 0x03, 0xa9, 0x47, 0x95, 0x1e, 0x41, - 0x83, 0xfe, 0x65, 0x5b, 0xe4, 0x0e, 0x40, 0x69, 0x14, 0x31, 0x50, 0x25, 0x88, 0xa8, 0xc5, 0xbf, 0xef, 0xcd, 0xb5, - 0xc1, 0x5c, 0x20, 0xcc, 0xc1, 0x80, 0x83, 0xb8, 0x0d, 0x42, 0x73, 0xc0, 0x6c, 0x6f, 0x23, 0x41, 0x37, 0xd6, 0x30, - 0xb3, 0xa3, 0x3f, 0xdc, 0x4a, 0xf0, 0x4d, 0xd6, 0x1a, 0x75, 0x5e, 0x1c, 0x02, 0x41, 0xf0, 0xa6, 0x50, 0xd5, 0x5e, - 0xf5, 0xc0, 0xc6, 0x5b, 0xf5, 0x63, 0xb7, 0x1b, 0x4f, 0x85, 0xbb, 0xf6, 0x0b, 0x0a, 0x27, 0x9f, 0x92, 0x7f, 0xbd, - 0x37, 0x19, 0x1c, 0x18, 0x19, 0xbe, 0xf4, 0xf6, 0x2f, 0x7c, 0xad, 0xa5, 0x7b, 0x62, 0x50, 0x92, 0x87, 0x47, 0x8a, - 0xfe, 0xdd, 0x29, 0x2b, 0x9f, 0xda, 0xe9, 0xdf, 0xed, 0xcc, 0xfa, 0x3c, 0x1e, 0x4d, 0x76, 0xbb, 0x5e, 0x5c, 0x69, - 0x8f, 0x35, 0xbd, 0x20, 0xd0, 0xb9, 0x9e, 0x1c, 0x1e, 0x41, 0x54, 0x84, 0x66, 0xdc, 0xcd, 0xb2, 0x21, 0x91, 0xf1, - 0xe3, 0x74, 0x96, 0x0d, 0xc1, 0x0e, 0xf7, 0xa2, 0x12, 0x97, 0xa3, 0xd6, 0x06, 0xa7, 0xb7, 0x49, 0x08, 0xa1, 0x1c, - 0xb0, 0xb2, 0x5b, 0xf5, 0x67, 0xa3, 0xcc, 0x84, 0xd4, 0x64, 0x75, 0x3b, 0xa5, 0x7b, 0x98, 0xe6, 0x07, 0x66, 0x04, - 0x07, 0xdc, 0xdb, 0x5f, 0xf5, 0xa7, 0x30, 0xc9, 0x34, 0x39, 0x45, 0xf2, 0x8b, 0xf4, 0x14, 0x92, 0xf6, 0xe8, 0xa9, - 0x22, 0x80, 0x13, 0x6a, 0x3f, 0x86, 0xdf, 0x30, 0xee, 0x3f, 0x34, 0x5f, 0xbb, 0xa9, 0x88, 0x1e, 0x53, 0x2c, 0x53, - 0x93, 0xd3, 0x24, 0x2b, 0x12, 0x88, 0xda, 0xa8, 0x9a, 0x11, 0x3d, 0x72, 0x31, 0x1f, 0x15, 0xe1, 0xf3, 0x6a, 0xfd, - 0x9f, 0x21, 0x7c, 0x46, 0xb2, 0x0b, 0x70, 0x79, 0xc5, 0xe5, 0x79, 0xf8, 0xe4, 0x31, 0x3d, 0x98, 0x7c, 0x77, 0x44, - 0x0f, 0x8e, 0x1e, 0x3d, 0x21, 0x00, 0x8b, 0x76, 0x79, 0x1e, 0x1e, 0x3d, 0x79, 0x42, 0x0f, 0xbe, 0xff, 0x9e, 0x1e, - 0x4c, 0x1e, 0x1d, 0x35, 0xd2, 0x26, 0x4f, 0xbe, 0xa7, 0x07, 0xdf, 0x3d, 0x6e, 0xa4, 0x1d, 0x8d, 0x9f, 0xd0, 0x83, - 0xbf, 0x7f, 0x67, 0xd2, 0xfe, 0x06, 0xd9, 0xbe, 0x3f, 0xc2, 0xff, 0x4c, 0xda, 0xe4, 0xc9, 0x23, 0x7a, 0x30, 0x19, - 0x43, 0x25, 0x4f, 0x5c, 0x25, 0xe3, 0x09, 0x7c, 0xfc, 0x08, 0xfe, 0xfb, 0x1b, 0x81, 0x4d, 0x20, 0xd9, 0x52, 0xa0, - 0xfe, 0x0c, 0x45, 0x9c, 0xa8, 0x9a, 0x48, 0x78, 0x88, 0x99, 0xd5, 0x37, 0x71, 0x18, 0x10, 0x97, 0x0e, 0x05, 0xd1, - 0x83, 0xf1, 0xe8, 0x09, 0x09, 0x7c, 0x78, 0xba, 0x4f, 0x3e, 0xc8, 0xd8, 0x52, 0xcc, 0xb3, 0x6f, 0x96, 0x26, 0xb6, - 0x82, 0x07, 0x60, 0xf5, 0xc1, 0xcf, 0xc5, 0xe5, 0x3c, 0xfb, 0x86, 0xcb, 0xfd, 0x5c, 0x3f, 0xb6, 0x00, 0xe5, 0xfd, - 0x55, 0xcb, 0x3e, 0x15, 0x2a, 0x74, 0x5a, 0x6b, 0xf4, 0xd9, 0x07, 0x4c, 0x1f, 0x0c, 0xbc, 0x1b, 0xf6, 0xcf, 0x7b, - 0xe5, 0xb4, 0xbe, 0xd1, 0x28, 0xd4, 0xa8, 0x3c, 0x24, 0xec, 0x04, 0x8a, 0x1e, 0x0c, 0x80, 0x27, 0x70, 0x65, 0xfc, - 0xfe, 0x1f, 0x96, 0xf1, 0xa1, 0xa3, 0x8c, 0x7f, 0xa0, 0x0c, 0x01, 0x8d, 0x7a, 0x98, 0xdd, 0xf4, 0xb0, 0xd1, 0xad, - 0x5e, 0xb2, 0x54, 0x27, 0x53, 0xd3, 0x33, 0xd8, 0xd7, 0xba, 0x96, 0x07, 0x46, 0x14, 0x2d, 0x2f, 0x0e, 0x52, 0x3e, - 0xab, 0xd8, 0xcf, 0x4b, 0x54, 0x6f, 0x45, 0x8d, 0x37, 0x32, 0x9b, 0x55, 0xec, 0x77, 0xf3, 0x06, 0xb8, 0x19, 0xf6, - 0xa3, 0x7a, 0xf2, 0x03, 0x67, 0x64, 0xd2, 0xb6, 0x47, 0x99, 0x18, 0x01, 0x56, 0x40, 0x06, 0x0e, 0x3c, 0x00, 0x3a, - 0xe8, 0x8f, 0xf6, 0x6e, 0xa7, 0x52, 0x9a, 0x7d, 0xb6, 0x30, 0x80, 0x86, 0x79, 0x9b, 0xb8, 0xb2, 0xab, 0xd4, 0x97, - 0x97, 0xa0, 0x70, 0xab, 0x59, 0xde, 0x5e, 0x61, 0x2a, 0x6e, 0x4f, 0xca, 0x00, 0x70, 0x20, 0xc0, 0x60, 0xac, 0x65, - 0x40, 0xcd, 0x96, 0x8f, 0xb6, 0x5c, 0xa9, 0x27, 0x81, 0x33, 0xb8, 0x90, 0x45, 0xc2, 0xdf, 0x6a, 0xb1, 0x3f, 0x5a, - 0x3f, 0xfa, 0xbe, 0x3d, 0x1e, 0xac, 0x7d, 0x8f, 0x8f, 0xf4, 0x67, 0x8d, 0xeb, 0xc0, 0xb6, 0xe5, 0x1b, 0x2f, 0x6a, - 0x2b, 0xf1, 0x28, 0x81, 0x37, 0x30, 0x11, 0x29, 0x0c, 0x52, 0x2d, 0x70, 0x0c, 0xca, 0x1b, 0x0b, 0xb1, 0x54, 0x5d, - 0xdd, 0xd0, 0x2d, 0x19, 0x82, 0x87, 0x5b, 0x95, 0xaa, 0xc0, 0x51, 0xfd, 0x7e, 0x26, 0x7d, 0xb7, 0x27, 0x63, 0x47, - 0x8e, 0x53, 0x3f, 0x15, 0x0e, 0xfe, 0x9b, 0xd4, 0xb5, 0x7e, 0x99, 0xa5, 0xcc, 0xb2, 0x2c, 0xec, 0x24, 0xd4, 0x72, - 0x8f, 0xca, 0x83, 0xe4, 0x0b, 0x39, 0x44, 0xb2, 0xc0, 0x28, 0x14, 0x64, 0x38, 0xa1, 0x62, 0xb4, 0x16, 0xe5, 0x32, - 0xbb, 0xa8, 0xc2, 0xad, 0x52, 0x28, 0x73, 0x8a, 0xbe, 0xdd, 0xe0, 0x40, 0x42, 0xa2, 0xac, 0x7c, 0x13, 0xbf, 0x09, - 0x11, 0xac, 0x8e, 0x6b, 0x5b, 0x28, 0xee, 0xed, 0x4f, 0x91, 0x76, 0xf1, 0x47, 0xc6, 0x05, 0xd4, 0xc5, 0x62, 0x1a, - 0x4e, 0x6c, 0xec, 0x03, 0xf7, 0x85, 0xd5, 0xf4, 0x00, 0xd4, 0x77, 0xa9, 0xc4, 0x08, 0xea, 0x2b, 0x63, 0x1f, 0xdb, - 0x63, 0x4c, 0xce, 0x20, 0xd6, 0xb0, 0x2e, 0x5b, 0xf5, 0x8d, 0xb0, 0x13, 0x00, 0x6e, 0x84, 0xd6, 0xe8, 0xc8, 0x24, - 0x55, 0x88, 0xe7, 0xa5, 0x0a, 0xdf, 0x9a, 0x11, 0x3a, 0x06, 0x6f, 0x2a, 0xd7, 0x48, 0xe9, 0x0b, 0x06, 0xcd, 0xb1, - 0xad, 0xa3, 0xb0, 0xda, 0xca, 0xb2, 0x13, 0x80, 0x1b, 0xc8, 0x8e, 0xcd, 0xc5, 0x73, 0x56, 0xcd, 0xb3, 0x45, 0x64, - 0x82, 0x02, 0xa6, 0xc2, 0x32, 0x68, 0x6f, 0xee, 0x90, 0xed, 0x38, 0x84, 0x6e, 0xb8, 0x8f, 0x60, 0x3c, 0xed, 0xa6, - 0x60, 0x05, 0xd1, 0x08, 0xf1, 0x30, 0x63, 0x16, 0xdf, 0x2b, 0x4d, 0x79, 0xaa, 0x5a, 0x02, 0x81, 0xa3, 0x10, 0xea, - 0x62, 0xdf, 0x28, 0xc1, 0x65, 0x6a, 0x04, 0x33, 0xd8, 0xb3, 0x23, 0xb5, 0x5d, 0x72, 0x4e, 0x87, 0x6a, 0x4a, 0x4b, - 0x3d, 0xa5, 0xda, 0xd7, 0x50, 0xcc, 0x4b, 0xf4, 0xd0, 0x03, 0xd7, 0x03, 0xed, 0x90, 0x57, 0xd2, 0x89, 0x89, 0xa0, - 0xd3, 0x6a, 0x13, 0x76, 0x6e, 0xa4, 0x5b, 0x56, 0x23, 0xef, 0x18, 0x9a, 0x1d, 0xf1, 0xca, 0x0f, 0xd4, 0x05, 0x10, - 0x21, 0x77, 0xb6, 0xc8, 0x10, 0x67, 0x96, 0x95, 0x2f, 0xa0, 0x2c, 0x8e, 0xd8, 0xba, 0x02, 0xae, 0xa5, 0x60, 0x72, - 0xc9, 0x23, 0x91, 0x22, 0x22, 0xe0, 0xa9, 0xd2, 0xae, 0xef, 0xb5, 0x84, 0xd0, 0x32, 0x05, 0xe2, 0xe6, 0xa2, 0x38, - 0xd7, 0x36, 0x90, 0x05, 0xd0, 0xb7, 0x9f, 0xb2, 0x2b, 0x2f, 0x1c, 0xec, 0xf6, 0x2a, 0x13, 0xcf, 0xf8, 0x45, 0x26, - 0x78, 0x8a, 0x60, 0x57, 0xb7, 0xe6, 0x81, 0x3b, 0xb6, 0x0d, 0x2c, 0xdf, 0x7e, 0x80, 0x05, 0x53, 0x86, 0x5a, 0x29, - 0x91, 0x89, 0x48, 0x40, 0x66, 0x9f, 0xb9, 0x7b, 0x9d, 0x89, 0xd7, 0xf1, 0x2d, 0x78, 0x53, 0x34, 0xf8, 0xe9, 0xd1, - 0x39, 0x7e, 0x89, 0x48, 0xa2, 0x10, 0xc3, 0x16, 0x23, 0x62, 0x21, 0x72, 0xec, 0x98, 0x50, 0xae, 0x04, 0xad, 0xad, - 0x21, 0xf0, 0xe2, 0x4f, 0xab, 0xee, 0x5d, 0x65, 0xc2, 0xd8, 0x67, 0x5c, 0xc5, 0xb7, 0xac, 0x54, 0x60, 0x16, 0x18, - 0xe7, 0xbe, 0x2d, 0x25, 0xb9, 0xca, 0x84, 0x11, 0x90, 0x5c, 0xc5, 0xb7, 0xb4, 0x29, 0xe3, 0xd0, 0x56, 0x74, 0x5e, - 0x9c, 0xdf, 0xfd, 0xe1, 0x97, 0x18, 0x6a, 0x65, 0xdc, 0xef, 0x83, 0xc4, 0x4c, 0xda, 0xa6, 0xcc, 0x64, 0x24, 0x35, - 0x5a, 0x48, 0x45, 0xf9, 0x60, 0x42, 0xf6, 0x57, 0xaa, 0x65, 0x44, 0xed, 0x57, 0xa1, 0x98, 0x8d, 0xa3, 0x09, 0xa1, - 0x93, 0x8e, 0xf5, 0x6e, 0x5a, 0x0b, 0x99, 0x46, 0x4f, 0x22, 0xcf, 0xa7, 0xb3, 0x60, 0xd5, 0xb4, 0x38, 0x66, 0x7c, - 0x5a, 0x0c, 0x06, 0x44, 0xbb, 0x14, 0x6e, 0xb1, 0x1e, 0x30, 0xa5, 0x71, 0xf1, 0xd6, 0x4c, 0xab, 0x5f, 0x48, 0x15, - 0x92, 0xde, 0x33, 0x20, 0x11, 0xd2, 0x05, 0xbb, 0x05, 0x89, 0xa2, 0xe7, 0x7f, 0xa7, 0xb6, 0xe0, 0xbe, 0x07, 0x63, - 0x33, 0xba, 0xaf, 0x67, 0xfc, 0x87, 0xda, 0x16, 0x44, 0x7d, 0x2a, 0x59, 0xaf, 0x23, 0x51, 0x85, 0x5c, 0x84, 0x9f, - 0x1d, 0x0d, 0x31, 0x44, 0xb5, 0xc7, 0x02, 0xb1, 0xbe, 0x3a, 0xe7, 0x05, 0x4e, 0x3f, 0x73, 0x97, 0x2b, 0xd8, 0x16, - 0xb4, 0x32, 0x34, 0xea, 0x4d, 0xfc, 0x26, 0xb2, 0x97, 0x05, 0x5d, 0xe4, 0x33, 0x14, 0xb2, 0xe6, 0x61, 0x58, 0x0d, - 0xdb, 0x83, 0x48, 0x0e, 0xdb, 0x93, 0xd0, 0x68, 0x0c, 0x2c, 0x90, 0x3d, 0x1a, 0x81, 0x8b, 0xd0, 0xca, 0xdf, 0x8e, - 0xc1, 0x85, 0xcb, 0x22, 0xb2, 0x0c, 0x75, 0xfc, 0xa6, 0x76, 0x13, 0x54, 0xaf, 0xd0, 0x69, 0x0a, 0xab, 0x52, 0x26, - 0xf9, 0xf0, 0xeb, 0x85, 0x2c, 0x30, 0x93, 0xd7, 0x65, 0x8f, 0xbe, 0xb6, 0xdb, 0x3b, 0x30, 0x05, 0xeb, 0x3e, 0x79, - 0x5f, 0x3f, 0xec, 0xec, 0x09, 0x18, 0xc5, 0xaa, 0x1c, 0x4d, 0x21, 0xa5, 0xf6, 0x41, 0xa9, 0x3f, 0x85, 0xa9, 0xd0, - 0x1c, 0xbb, 0x05, 0x4c, 0x02, 0xf6, 0x19, 0x52, 0x3d, 0xa6, 0x1d, 0xfb, 0x1c, 0x6d, 0x61, 0x49, 0xc0, 0xe1, 0x1f, - 0x09, 0x59, 0xfb, 0x57, 0x77, 0x99, 0x36, 0x43, 0xb6, 0xcc, 0x17, 0xc0, 0xe7, 0xc3, 0xae, 0x8d, 0x4a, 0x94, 0x4d, - 0x44, 0x92, 0xc2, 0x96, 0xc7, 0x20, 0xed, 0x51, 0x4c, 0x57, 0x05, 0x4f, 0x32, 0x94, 0x52, 0x24, 0xda, 0x27, 0x38, - 0x87, 0x37, 0xb8, 0x1f, 0x55, 0x40, 0x78, 0x15, 0x72, 0x3a, 0x4a, 0xa9, 0xb6, 0x80, 0x51, 0xd4, 0x03, 0x44, 0x79, - 0x19, 0xc8, 0xf1, 0x76, 0xbb, 0x09, 0x5d, 0xb1, 0xe5, 0x70, 0x42, 0x91, 0x94, 0x5c, 0x62, 0xb9, 0x57, 0xa0, 0xf3, - 0x38, 0x67, 0xbd, 0x57, 0x80, 0x45, 0x70, 0x06, 0x7f, 0x63, 0x42, 0xaf, 0xe1, 0x6f, 0x4e, 0xe8, 0x53, 0x16, 0x5e, - 0x0d, 0x2f, 0xc9, 0x61, 0x98, 0x0e, 0x26, 0x4a, 0x30, 0xb6, 0x61, 0x69, 0x19, 0xaa, 0xc4, 0xd5, 0xe1, 0x05, 0x79, - 0x78, 0x41, 0x6f, 0xe9, 0x0d, 0x7d, 0x4d, 0x1f, 0x00, 0xe1, 0xdf, 0x1c, 0x4f, 0xf8, 0x70, 0xf2, 0xb8, 0xdf, 0xef, - 0x9d, 0xf7, 0xfb, 0xbd, 0x33, 0x63, 0x40, 0xa1, 0x77, 0xd1, 0x65, 0x4d, 0xf5, 0xaf, 0xab, 0x7a, 0x31, 0x7d, 0xa0, - 0x36, 0x6e, 0xc2, 0xb3, 0x3c, 0xbc, 0x3a, 0xdc, 0x90, 0x21, 0x3e, 0x5e, 0xe4, 0x52, 0x16, 0xe1, 0xe5, 0xe1, 0x86, - 0xd0, 0x07, 0x27, 0xa0, 0x37, 0xc5, 0xfa, 0x1e, 0x3c, 0xdc, 0xe8, 0xda, 0x08, 0x7d, 0x15, 0x26, 0xb0, 0x4d, 0x6e, - 0x99, 0xbd, 0x6b, 0x4f, 0xc6, 0x10, 0xcb, 0x64, 0xe3, 0x95, 0xb7, 0x79, 0x78, 0x4b, 0x0e, 0x6f, 0xc1, 0x53, 0xd4, - 0x92, 0xbf, 0x59, 0x78, 0xc3, 0x5a, 0x35, 0x3c, 0xdc, 0xd0, 0xd7, 0xad, 0x46, 0x3c, 0xdc, 0x90, 0x28, 0xbc, 0x61, - 0x97, 0xf4, 0x35, 0xbb, 0x22, 0xf4, 0xbc, 0xdf, 0x3f, 0xeb, 0xf7, 0x65, 0xbf, 0xff, 0x73, 0x1c, 0x86, 0xf1, 0xb0, - 0x20, 0x87, 0x92, 0x6e, 0x0e, 0x27, 0xfc, 0x11, 0x99, 0x85, 0xba, 0xf9, 0x6a, 0xc1, 0x59, 0x95, 0xb7, 0xca, 0xb5, - 0xa1, 0x60, 0xad, 0xb0, 0x61, 0xea, 0xe9, 0x01, 0xbd, 0x61, 0x05, 0x7d, 0xcd, 0x62, 0x12, 0x5d, 0x43, 0x2b, 0xce, - 0x67, 0x45, 0x74, 0x43, 0x5f, 0xb3, 0xb3, 0x59, 0x1c, 0xbd, 0xa6, 0x0f, 0x58, 0x3e, 0x9c, 0x40, 0xde, 0xd7, 0xc3, - 0x1b, 0x72, 0xf8, 0x80, 0x44, 0xe1, 0x03, 0xfd, 0x7b, 0x43, 0x2f, 0x79, 0xf8, 0x80, 0x7a, 0xd5, 0x3c, 0x20, 0xa6, - 0xfa, 0x46, 0xed, 0x0f, 0x48, 0xe4, 0x0f, 0xe6, 0x03, 0x6b, 0x4f, 0xf3, 0xce, 0xd1, 0xc6, 0x75, 0x19, 0x6e, 0x08, - 0x5d, 0x97, 0xe1, 0x0d, 0x21, 0xd3, 0xe6, 0xd8, 0xc1, 0x80, 0xce, 0xde, 0x45, 0x09, 0xa1, 0x37, 0x7e, 0xa9, 0x37, - 0x38, 0x86, 0x66, 0x84, 0x74, 0x3f, 0x31, 0x0d, 0xd7, 0xc1, 0x47, 0x0d, 0xd6, 0x71, 0xde, 0xef, 0x87, 0xeb, 0x7e, - 0x1f, 0x22, 0xdd, 0x17, 0x33, 0x13, 0xdb, 0xcd, 0x91, 0x4d, 0x7a, 0x03, 0xda, 0xff, 0x8f, 0x83, 0x01, 0x74, 0xc6, - 0x2b, 0x29, 0xbc, 0x19, 0x7c, 0x7c, 0xb8, 0x21, 0xaa, 0x8e, 0x82, 0x96, 0x32, 0x2c, 0xe8, 0x53, 0x9a, 0x01, 0xe0, - 0xd7, 0xc7, 0xc1, 0x80, 0x44, 0xe6, 0x33, 0x32, 0xfd, 0x78, 0xfc, 0x60, 0x3a, 0x18, 0x7c, 0x34, 0xdb, 0xe4, 0x33, - 0xbb, 0xa3, 0x14, 0x58, 0x7f, 0x67, 0xfd, 0xfe, 0xe7, 0x93, 0x98, 0x9c, 0x17, 0x3c, 0xfe, 0x34, 0x6d, 0xb6, 0xe5, - 0xb3, 0x8b, 0xaa, 0x76, 0xd6, 0xef, 0xaf, 0xfb, 0xfd, 0xd7, 0x80, 0x5d, 0x34, 0x73, 0xbe, 0x9e, 0x20, 0x6d, 0x99, - 0x3b, 0x8a, 0xa4, 0x49, 0x0e, 0x8d, 0xa1, 0x6d, 0xb1, 0x6a, 0xdb, 0xac, 0x23, 0x03, 0x8b, 0xa3, 0x66, 0x45, 0x71, - 0x4d, 0xa2, 0xb0, 0x77, 0xb6, 0xdb, 0xbd, 0x66, 0x8c, 0xc5, 0x04, 0xa4, 0x1f, 0xfe, 0xeb, 0xd7, 0x75, 0x23, 0x86, - 0x58, 0xa9, 0xc4, 0x77, 0xdb, 0xa5, 0x3d, 0x04, 0x22, 0x0e, 0x9b, 0xfe, 0xbd, 0xb9, 0x97, 0x8b, 0xda, 0xf1, 0xad, - 0xbf, 0x03, 0x08, 0x91, 0x64, 0x21, 0x9f, 0xe1, 0x18, 0x94, 0x19, 0x00, 0x99, 0x47, 0x6a, 0xe6, 0x25, 0x80, 0x00, - 0x93, 0xdd, 0x6e, 0x34, 0x1e, 0x4f, 0x68, 0xc1, 0x46, 0x7f, 0x7b, 0xf2, 0xb0, 0x7a, 0x18, 0x06, 0xc1, 0x20, 0x23, - 0x2d, 0x3d, 0x85, 0x5d, 0xac, 0xd5, 0x21, 0x18, 0xc1, 0x6b, 0xf6, 0xf1, 0x3a, 0xfb, 0x6a, 0xf6, 0x11, 0x09, 0x6b, - 0x83, 0x71, 0xe4, 0x22, 0x6d, 0xe9, 0xed, 0xee, 0x60, 0x30, 0xb9, 0x48, 0xbf, 0xc0, 0x76, 0xfa, 0xfc, 0x9b, 0x07, - 0xe3, 0x09, 0x07, 0xa3, 0xbb, 0x28, 0xe8, 0x33, 0x6d, 0xb7, 0xab, 0xfc, 0x4b, 0xe0, 0x1b, 0x4c, 0x05, 0x1d, 0x9b, - 0x65, 0xe1, 0x06, 0x15, 0x51, 0x47, 0xcb, 0xa0, 0xaa, 0x95, 0xed, 0x1c, 0x50, 0x4b, 0xac, 0xca, 0xc4, 0x2d, 0x30, - 0x0c, 0x19, 0xea, 0x72, 0x4f, 0xab, 0xdf, 0x79, 0x21, 0x0d, 0x7c, 0x86, 0x13, 0x11, 0x7a, 0xdc, 0x1a, 0xf7, 0xb9, - 0x35, 0xf1, 0x05, 0x6e, 0xad, 0x44, 0x12, 0x6b, 0x60, 0x49, 0xcd, 0xe5, 0x28, 0x61, 0x27, 0x25, 0xe3, 0xb3, 0x32, - 0x4a, 0x68, 0x0c, 0x0f, 0x92, 0x89, 0x99, 0x8c, 0x12, 0xb4, 0x4f, 0x74, 0x11, 0x06, 0xff, 0x02, 0xcc, 0x7e, 0x9a, - 0xc3, 0x5f, 0x49, 0xa6, 0xc9, 0x31, 0x04, 0x84, 0x38, 0x1e, 0xcf, 0xe2, 0x70, 0x4c, 0xa2, 0xe4, 0x04, 0x9e, 0xe0, - 0xbf, 0x22, 0x1c, 0x93, 0x5a, 0xdf, 0x61, 0xa4, 0xba, 0xdc, 0x26, 0x0c, 0xe0, 0xca, 0xc6, 0xb3, 0x49, 0x64, 0xa5, - 0xbb, 0xf2, 0xe1, 0x68, 0xfc, 0x84, 0x4c, 0xe3, 0x50, 0x0e, 0x12, 0x42, 0xc1, 0xbb, 0x37, 0x2c, 0x87, 0x89, 0x86, - 0x67, 0x03, 0x36, 0xaf, 0x74, 0x6c, 0x9e, 0x84, 0x13, 0x10, 0x86, 0x09, 0x39, 0xd6, 0x3b, 0x90, 0x52, 0xf4, 0x79, - 0x8e, 0xfd, 0xd4, 0x47, 0x10, 0x66, 0x47, 0x2d, 0x15, 0x5f, 0x01, 0xd0, 0x25, 0x0e, 0x0e, 0xb5, 0x67, 0xbe, 0x98, - 0x85, 0xa5, 0x47, 0xa5, 0x4c, 0x75, 0x87, 0xa2, 0x41, 0xf9, 0x4d, 0x83, 0x0e, 0x05, 0x19, 0x4c, 0x68, 0x79, 0x32, - 0xe1, 0x8f, 0x20, 0x80, 0x47, 0x23, 0xe2, 0x97, 0xc2, 0x89, 0x81, 0xf0, 0x2a, 0xc8, 0x40, 0xa5, 0xb5, 0x6a, 0xcc, - 0xc8, 0x56, 0x7c, 0x00, 0x61, 0x52, 0x0e, 0x6e, 0xe4, 0x3a, 0x4f, 0x21, 0x2a, 0xd8, 0x3a, 0xaf, 0x0e, 0x2e, 0xc1, - 0x92, 0x3d, 0xae, 0x20, 0x4e, 0xd8, 0x7a, 0x05, 0xd8, 0xb9, 0x0f, 0xb6, 0x65, 0x7d, 0xa0, 0xbe, 0x3b, 0xc0, 0x96, - 0xc3, 0xab, 0x4a, 0x1e, 0x4c, 0xc6, 0xe3, 0xf1, 0xe8, 0x0f, 0x38, 0x3a, 0x80, 0xd0, 0x92, 0xc8, 0xf0, 0xc9, 0x00, - 0x8d, 0xbb, 0xae, 0xb8, 0x37, 0x2e, 0x14, 0x65, 0xa5, 0x93, 0x09, 0x01, 0xf1, 0xb3, 0xe9, 0x1b, 0xec, 0x2b, 0xae, - 0xe3, 0x9f, 0xec, 0x7f, 0x62, 0x56, 0xb4, 0x5a, 0xa9, 0xa3, 0x77, 0x6f, 0x3f, 0xbc, 0xfa, 0xf8, 0xea, 0xd7, 0xe7, - 0x67, 0xaf, 0xde, 0xbc, 0x78, 0xf5, 0xe6, 0xd5, 0xc7, 0x7f, 0xdf, 0xc3, 0x60, 0xfb, 0xb6, 0x22, 0x76, 0xec, 0xbd, - 0x7b, 0x8c, 0x57, 0x8b, 0x2f, 0x9c, 0x3d, 0x72, 0xb7, 0x58, 0x80, 0x4d, 0x30, 0xdc, 0x82, 0xa0, 0x9a, 0xd1, 0xa8, - 0xf4, 0x3d, 0x01, 0x19, 0x8d, 0x0a, 0xd9, 0x78, 0x58, 0xb1, 0x15, 0x72, 0xf1, 0x8e, 0xe1, 0xe0, 0x23, 0xfb, 0x5b, - 0x71, 0x26, 0xdc, 0x8e, 0xb6, 0x66, 0x45, 0xc0, 0xe7, 0x6b, 0x2d, 0x2a, 0x8f, 0x0b, 0x51, 0x7b, 0xdb, 0x3e, 0x87, - 0x84, 0x7a, 0x44, 0xae, 0x83, 0xf7, 0x6d, 0x90, 0x3d, 0x3e, 0xf2, 0x9e, 0x94, 0x67, 0xa8, 0xcf, 0xd1, 0xf0, 0x51, - 0xe3, 0x19, 0x9d, 0x98, 0x6b, 0xa3, 0x43, 0x3d, 0x2b, 0x60, 0x7f, 0x2b, 0x31, 0x36, 0x98, 0x43, 0xa7, 0x88, 0xf5, - 0xe1, 0x74, 0xbf, 0xfb, 0x37, 0xa3, 0x9f, 0xe1, 0xf8, 0x51, 0xaa, 0x09, 0xa4, 0x45, 0x81, 0xd2, 0x95, 0x21, 0xb7, - 0x3d, 0x0b, 0x0b, 0xf3, 0x33, 0x6c, 0x10, 0x40, 0x7b, 0xd9, 0xb1, 0x24, 0xd0, 0x2c, 0x5e, 0xeb, 0xfa, 0xe7, 0xe5, - 0xcb, 0x44, 0x3b, 0x5f, 0x7c, 0x0b, 0x21, 0x86, 0xfd, 0x2b, 0x42, 0x63, 0xc2, 0xdd, 0x24, 0xbb, 0x4b, 0x8b, 0xb9, - 0x57, 0x5d, 0xc5, 0x78, 0xdc, 0xdd, 0x71, 0xa5, 0x68, 0xde, 0xba, 0xc0, 0x1e, 0xa8, 0x79, 0x1d, 0x2f, 0x59, 0x08, - 0xd8, 0x8c, 0x87, 0x76, 0x91, 0x38, 0xbf, 0x77, 0x3a, 0x21, 0x87, 0x47, 0x53, 0x3e, 0x64, 0x25, 0x15, 0x03, 0x56, - 0xd6, 0x7b, 0xd4, 0x9c, 0xb7, 0x09, 0xb9, 0xd8, 0xa7, 0xe1, 0x62, 0xc8, 0xef, 0xbb, 0x24, 0x7d, 0xe4, 0x0d, 0x87, - 0x6a, 0xdb, 0x5c, 0x0c, 0x69, 0xca, 0xe9, 0x3e, 0x95, 0x01, 0x21, 0xd2, 0x55, 0x5c, 0x91, 0x5a, 0x1f, 0x55, 0x6b, - 0x27, 0xe9, 0xb8, 0xce, 0xb6, 0x5f, 0xb8, 0x64, 0xab, 0xdb, 0xb5, 0x7f, 0xad, 0x6e, 0x5f, 0x98, 0x81, 0xfc, 0xfd, - 0x89, 0xa8, 0x26, 0x06, 0xa2, 0x0b, 0xa8, 0xe0, 0x9f, 0xe0, 0xe5, 0xc9, 0x23, 0xad, 0x00, 0xbd, 0xeb, 0xec, 0xe8, - 0xda, 0xe3, 0x8d, 0x59, 0x6c, 0x2d, 0x71, 0xce, 0x2a, 0xdf, 0x59, 0x5e, 0x95, 0xad, 0xd0, 0x75, 0x04, 0xfb, 0x3d, - 0xec, 0xe8, 0xbb, 0xb7, 0x0d, 0x80, 0x28, 0x85, 0x95, 0x3b, 0xfb, 0x85, 0x77, 0xf6, 0x0b, 0x7b, 0xf6, 0xdb, 0x4d, - 0xa0, 0x7c, 0x58, 0xa1, 0x65, 0x2f, 0xa4, 0xa8, 0x4c, 0x93, 0xc7, 0x4d, 0x5d, 0x16, 0xd2, 0x62, 0x7e, 0x68, 0x69, - 0xd7, 0xe3, 0x31, 0x95, 0xa8, 0x1e, 0x79, 0x89, 0xad, 0x3a, 0x2c, 0xc9, 0xfd, 0xf7, 0xcc, 0xff, 0xd9, 0x1b, 0xe4, - 0x5d, 0x77, 0xbb, 0xff, 0x9b, 0x0b, 0x1d, 0xdc, 0xd6, 0xd6, 0xc2, 0x53, 0x57, 0xc7, 0x05, 0xde, 0xd5, 0xd6, 0xf7, - 0xdf, 0xd5, 0xde, 0x66, 0x7a, 0xd9, 0x55, 0x80, 0x1a, 0x24, 0xd6, 0x57, 0xbc, 0xc8, 0x92, 0xda, 0x2a, 0x34, 0x1e, - 0x70, 0x08, 0xed, 0xe1, 0x1d, 0x5c, 0x20, 0x87, 0x25, 0x84, 0x7e, 0xaa, 0x8c, 0x00, 0xd0, 0x67, 0xb1, 0x1f, 0xf0, - 0x30, 0x23, 0x03, 0x5f, 0xe2, 0x27, 0xa5, 0x2f, 0x2e, 0x3e, 0xdc, 0xcb, 0x4c, 0xd0, 0xab, 0xc4, 0x66, 0x2f, 0x64, - 0x3b, 0xe6, 0x87, 0xff, 0x05, 0x46, 0x83, 0xf0, 0xda, 0x92, 0x1d, 0x8a, 0x8e, 0x59, 0xae, 0xe0, 0xa8, 0x2d, 0xbd, - 0x32, 0x5b, 0xd7, 0xcf, 0x6a, 0x98, 0xe9, 0x33, 0xe5, 0x01, 0xc8, 0xbe, 0x90, 0xbb, 0x9f, 0xea, 0x8a, 0x05, 0x39, - 0x99, 0x8c, 0xa7, 0x44, 0x0c, 0x06, 0xad, 0xe4, 0x63, 0x4c, 0x1e, 0x0e, 0xf7, 0x98, 0x4b, 0xa1, 0xfb, 0xe1, 0x45, - 0xfe, 0x85, 0xfa, 0x1a, 0x5b, 0x92, 0x6c, 0x2b, 0xf6, 0x17, 0x98, 0xc5, 0x02, 0x71, 0x74, 0xf0, 0x8b, 0xf3, 0x05, - 0x2d, 0xa1, 0x0d, 0x95, 0x41, 0x4f, 0x2e, 0x52, 0xe5, 0x23, 0x5b, 0x30, 0x79, 0x3c, 0x9e, 0xf9, 0x3d, 0x77, 0x0c, - 0x0e, 0x21, 0xd1, 0xc4, 0x1a, 0xbf, 0xf8, 0x59, 0x30, 0x8e, 0x43, 0x79, 0x22, 0x1b, 0xdf, 0x95, 0x24, 0x1a, 0x1b, - 0x53, 0x65, 0x7d, 0x95, 0xa8, 0x86, 0x09, 0x79, 0x58, 0x90, 0xc3, 0x82, 0x2e, 0xfd, 0xb1, 0xc4, 0xf4, 0xc3, 0xf8, - 0x70, 0x32, 0x26, 0x0f, 0xe3, 0x87, 0x13, 0x03, 0x37, 0xec, 0xe7, 0xc8, 0x87, 0x4b, 0x72, 0xd8, 0xac, 0x12, 0x4c, - 0x51, 0x4d, 0xcf, 0xfc, 0x4a, 0x92, 0xc1, 0x72, 0x90, 0x3e, 0x6c, 0xe5, 0xc5, 0x5a, 0xf5, 0x78, 0xaf, 0x8f, 0xf9, - 0x94, 0x88, 0xc6, 0x8d, 0x61, 0x4d, 0xaf, 0xe2, 0x3f, 0x65, 0x11, 0x49, 0x09, 0x88, 0x84, 0xa0, 0xde, 0xce, 0x2e, - 0xb2, 0x24, 0x16, 0x69, 0x94, 0xd6, 0x84, 0xa6, 0x27, 0x6c, 0x32, 0x9e, 0xa5, 0x2c, 0x3d, 0x9e, 0x3c, 0x99, 0x4d, - 0x9e, 0x44, 0x47, 0xe3, 0x28, 0x1d, 0x0c, 0x20, 0xf9, 0x68, 0x0c, 0x2e, 0x76, 0xf0, 0x9b, 0x1d, 0xc1, 0xd0, 0x9d, - 0x20, 0x4b, 0x58, 0x40, 0xd3, 0xbe, 0xae, 0x49, 0x7a, 0x38, 0x2f, 0x54, 0x4f, 0xe2, 0x5b, 0xba, 0xf6, 0x1c, 0x5c, - 0xfc, 0x16, 0x5e, 0xb8, 0x16, 0x5e, 0xec, 0xb7, 0x50, 0x68, 0xb2, 0x1d, 0xcb, 0xff, 0x3f, 0x6e, 0x18, 0x77, 0xdd, - 0x25, 0xcc, 0xe2, 0xba, 0xce, 0x46, 0xab, 0x42, 0x56, 0x12, 0x6e, 0x13, 0x4a, 0x14, 0x36, 0x8a, 0x57, 0xab, 0x5c, - 0xbb, 0x88, 0xcd, 0x2b, 0x0a, 0xe0, 0x2e, 0x10, 0xa7, 0x18, 0x58, 0x68, 0x63, 0x20, 0xf7, 0x99, 0x17, 0x92, 0x59, - 0xb5, 0x8f, 0xb9, 0x47, 0xfe, 0x19, 0x82, 0x31, 0xaa, 0x38, 0x19, 0xcf, 0x14, 0xd6, 0xc5, 0x97, 0xe4, 0xbd, 0xff, - 0xc1, 0x51, 0x64, 0x8f, 0x66, 0xd0, 0x13, 0x44, 0xce, 0x23, 0xce, 0x9e, 0x4c, 0x5e, 0x06, 0xee, 0x67, 0xb0, 0xd2, - 0x5f, 0x77, 0x9b, 0xb1, 0xb6, 0x3d, 0xba, 0x17, 0x46, 0x28, 0xfa, 0x19, 0xdf, 0x99, 0x7a, 0x01, 0x97, 0x50, 0x0d, - 0xec, 0xfa, 0xf2, 0x92, 0x97, 0x00, 0x22, 0x94, 0x89, 0x7e, 0xbf, 0xf7, 0xa7, 0x81, 0x26, 0x2d, 0x79, 0xf1, 0x3a, - 0x13, 0xd6, 0x19, 0x07, 0x9a, 0x0a, 0xd4, 0xff, 0x53, 0x65, 0x9f, 0xe9, 0x98, 0xcc, 0xfc, 0xc7, 0xe1, 0x84, 0x44, - 0xcd, 0xd7, 0xe4, 0x0b, 0xa7, 0xe9, 0x17, 0xae, 0x68, 0xff, 0x0d, 0x99, 0xb9, 0xe1, 0x90, 0xa1, 0xfe, 0xd2, 0x31, - 0x4f, 0x46, 0xaf, 0x13, 0xb3, 0x13, 0xc1, 0xaa, 0x19, 0x44, 0x61, 0x2f, 0xe0, 0x41, 0x5d, 0xcb, 0xe2, 0x29, 0xcc, - 0x3e, 0xa8, 0x11, 0xc5, 0x31, 0x1b, 0xcf, 0x42, 0x19, 0x4e, 0xc0, 0xbe, 0x77, 0x32, 0x86, 0xfb, 0x80, 0x0c, 0x3f, - 0x55, 0x21, 0x76, 0x0e, 0xd2, 0x3e, 0x55, 0xa8, 0x98, 0x00, 0x88, 0x40, 0xc8, 0xdb, 0xef, 0x4b, 0x95, 0x84, 0xaf, - 0x4b, 0x4c, 0x29, 0xd4, 0x07, 0xff, 0x1d, 0xa9, 0xba, 0x63, 0xfa, 0xd5, 0xfa, 0xf1, 0x67, 0x42, 0xf1, 0xe9, 0x2e, - 0x25, 0xbe, 0x85, 0xe0, 0xce, 0x31, 0xe8, 0x20, 0x2a, 0x34, 0x63, 0xbb, 0x9f, 0xdf, 0x15, 0x77, 0xf3, 0xbb, 0xe2, - 0xff, 0x1d, 0xbf, 0x2b, 0xee, 0x63, 0x0c, 0x2b, 0x0b, 0x0d, 0x3f, 0x0b, 0xc6, 0x41, 0xf4, 0xdf, 0xe7, 0x13, 0xef, - 0xe4, 0xa9, 0xaf, 0x32, 0x31, 0xbd, 0x83, 0x69, 0xf6, 0x09, 0x0a, 0xc2, 0x2a, 0xee, 0xd3, 0x93, 0x75, 0x65, 0x6f, - 0xad, 0x64, 0x88, 0x79, 0xee, 0x61, 0x8d, 0xc2, 0xca, 0x03, 0xba, 0x47, 0xd5, 0x06, 0x71, 0x22, 0x78, 0x18, 0x33, - 0x2b, 0x7d, 0xdf, 0xed, 0x8c, 0x0a, 0xf3, 0x5e, 0x2e, 0x0a, 0xb2, 0x9b, 0x8f, 0x67, 0xe3, 0x28, 0xc4, 0x06, 0xfc, - 0xb7, 0x19, 0xab, 0x86, 0x6c, 0xbe, 0x93, 0x91, 0xda, 0x33, 0x79, 0x9a, 0xec, 0x93, 0xde, 0x01, 0xef, 0x90, 0x9f, - 0xd7, 0x9f, 0xc2, 0x58, 0x1a, 0x7e, 0x4b, 0x5e, 0xc6, 0x45, 0x56, 0x2d, 0xaf, 0xb2, 0x04, 0x99, 0x2e, 0x78, 0xf1, - 0xd5, 0x4c, 0x97, 0xf7, 0xb1, 0x3e, 0x60, 0x3c, 0xa5, 0x78, 0xdd, 0x10, 0xa5, 0x5f, 0xb4, 0x3c, 0x2b, 0xd4, 0xe5, - 0x49, 0xc5, 0x6c, 0xcf, 0x4a, 0x70, 0x3a, 0x05, 0x13, 0x7c, 0xfd, 0xd3, 0xf5, 0x3e, 0x01, 0x5c, 0x50, 0xa8, 0x39, - 0x2d, 0xe4, 0xca, 0x60, 0x39, 0x59, 0xe8, 0x4e, 0xc0, 0x0c, 0x95, 0x02, 0x2f, 0x50, 0xf0, 0x17, 0x0d, 0x8c, 0xe8, - 0x0b, 0xf7, 0x9b, 0x0c, 0x0c, 0xd2, 0xa5, 0x39, 0x11, 0xc6, 0x8e, 0xdb, 0x49, 0xd2, 0x56, 0x94, 0x33, 0xce, 0xde, - 0xab, 0x2b, 0x05, 0x18, 0xe0, 0x6d, 0x6f, 0xa2, 0x4d, 0x82, 0x5e, 0x0b, 0x4a, 0xe7, 0x0d, 0xdc, 0xcd, 0x32, 0x32, - 0xc2, 0xc5, 0x87, 0x95, 0xc7, 0x82, 0x7b, 0xf6, 0x0b, 0x89, 0xb5, 0xf5, 0x03, 0x63, 0x36, 0x2f, 0x58, 0xa0, 0x50, - 0x81, 0x02, 0xcb, 0x99, 0xb6, 0x34, 0xad, 0x86, 0xfc, 0xf0, 0x08, 0xad, 0x4d, 0xab, 0x01, 0x3f, 0x3c, 0xaa, 0xa3, - 0xec, 0x18, 0xb2, 0x9c, 0xf8, 0x19, 0xd4, 0xeb, 0x3a, 0x32, 0x29, 0x26, 0xbb, 0x57, 0x5f, 0x9e, 0xfa, 0xa3, 0xba, - 0x05, 0xd7, 0x0f, 0x40, 0x00, 0x1b, 0x80, 0x43, 0xa0, 0x1a, 0x2c, 0x8d, 0x08, 0x16, 0x65, 0x0a, 0xed, 0x6b, 0xe8, - 0xbd, 0xd1, 0xf0, 0x5f, 0xe0, 0x2e, 0x22, 0x57, 0xfe, 0x27, 0x08, 0xfc, 0x15, 0x65, 0x5a, 0x99, 0xe2, 0x7f, 0xa2, - 0xd5, 0x2b, 0x94, 0xb3, 0xa6, 0x35, 0x1f, 0x44, 0x6b, 0x22, 0x54, 0x33, 0x86, 0xe0, 0xdf, 0xca, 0x32, 0x6d, 0xa9, - 0xaa, 0xd4, 0x87, 0xc6, 0x6b, 0xad, 0x70, 0x96, 0x8f, 0x23, 0xef, 0x35, 0x86, 0x8e, 0x4d, 0x9c, 0xa5, 0x9c, 0x4a, - 0x9d, 0xbd, 0x39, 0x94, 0x91, 0x03, 0x9c, 0x4e, 0xd8, 0x78, 0x9a, 0x1c, 0xcb, 0x69, 0xe2, 0x20, 0xf3, 0x73, 0x86, - 0x91, 0x55, 0x0d, 0x08, 0x8b, 0xb2, 0xa1, 0xb4, 0x05, 0x98, 0xe4, 0x84, 0x90, 0x29, 0x86, 0xa2, 0xc8, 0x47, 0xba, - 0x1f, 0xd6, 0x9b, 0xd5, 0x7d, 0xf1, 0x4e, 0x03, 0x9c, 0x86, 0x09, 0x04, 0x02, 0x2f, 0xe2, 0x9b, 0x4c, 0x5c, 0x82, - 0xc7, 0xf0, 0x00, 0xbe, 0x04, 0x37, 0xb9, 0x94, 0xfd, 0xab, 0x0a, 0x73, 0x5c, 0x5b, 0xc0, 0xa0, 0xc1, 0xea, 0x41, - 0x74, 0xb8, 0x94, 0x36, 0xbb, 0x0a, 0x10, 0x1b, 0x53, 0x88, 0x65, 0xc1, 0xd6, 0x96, 0x3d, 0xfb, 0x59, 0x35, 0x0d, - 0xad, 0x13, 0x4e, 0xc5, 0x65, 0x0e, 0x51, 0x54, 0x06, 0x31, 0xb8, 0x23, 0x79, 0x7c, 0xde, 0xa9, 0x08, 0x2f, 0x08, - 0xb8, 0x95, 0x25, 0x32, 0x5c, 0xd1, 0xe5, 0xe8, 0x96, 0xae, 0x47, 0x37, 0x74, 0x4c, 0x27, 0x7f, 0x1f, 0xa3, 0x45, - 0xb6, 0x4a, 0xdd, 0xd0, 0xf5, 0x68, 0x49, 0xbf, 0x1f, 0xd3, 0xa3, 0xbf, 0x8d, 0xc9, 0x74, 0x89, 0x87, 0x09, 0xbd, - 0x00, 0xc7, 0x2e, 0x52, 0xa3, 0xa7, 0xa6, 0x6f, 0x70, 0x58, 0x8d, 0xf2, 0x21, 0x1f, 0xe5, 0x94, 0x8f, 0x8a, 0x61, - 0x35, 0x02, 0x4f, 0xc7, 0x6a, 0xc8, 0x47, 0x15, 0xe5, 0xa3, 0xf3, 0x61, 0x35, 0x3a, 0x27, 0xcd, 0xa6, 0xbf, 0xaa, - 0xf8, 0x55, 0xc9, 0x2e, 0x60, 0x5b, 0xc0, 0xf2, 0x75, 0xab, 0x6c, 0x99, 0xfa, 0xab, 0xda, 0x9c, 0xcc, 0x96, 0xb3, - 0xb7, 0xd7, 0x5d, 0x4e, 0x2c, 0x1e, 0xb7, 0x4d, 0x87, 0xab, 0x2f, 0x27, 0xea, 0xa4, 0x57, 0xc8, 0x0f, 0xe3, 0xa9, - 0x50, 0xe7, 0x10, 0x98, 0x49, 0xcc, 0xc2, 0x98, 0x61, 0x33, 0x75, 0x1a, 0x28, 0x70, 0xb2, 0x91, 0xe7, 0xa2, 0x98, - 0x8d, 0x72, 0x0a, 0xef, 0x63, 0x42, 0x22, 0x01, 0x67, 0xd5, 0x49, 0x35, 0x2a, 0x20, 0xe6, 0x08, 0x0b, 0xf1, 0x11, - 0xfa, 0xa5, 0x3e, 0xf2, 0x90, 0xc0, 0x33, 0xec, 0x6b, 0x31, 0x88, 0xe1, 0x88, 0xb7, 0x95, 0x55, 0xb3, 0x30, 0x81, - 0xca, 0xaa, 0x61, 0x69, 0x2a, 0x2b, 0x68, 0x36, 0xaa, 0xfc, 0xca, 0x2a, 0x1c, 0xa3, 0x84, 0x90, 0xa8, 0xd4, 0x95, - 0x81, 0xfa, 0x24, 0x61, 0x61, 0xa9, 0x2b, 0x3b, 0x57, 0x1f, 0x9d, 0xfb, 0x95, 0x9d, 0x83, 0x0b, 0xe9, 0x20, 0xf1, - 0xaf, 0x52, 0x69, 0xda, 0xbe, 0x0e, 0x36, 0x56, 0x15, 0xdd, 0xf2, 0xdb, 0xaa, 0x88, 0xa3, 0x92, 0xba, 0x18, 0xd0, - 0xb8, 0x30, 0x22, 0x49, 0xf5, 0x1a, 0x05, 0x7f, 0x48, 0x10, 0x95, 0xc6, 0xe0, 0xd5, 0x99, 0x74, 0xad, 0xd4, 0x8a, - 0x8a, 0x41, 0x39, 0x28, 0xe0, 0xfe, 0x94, 0xb7, 0x16, 0xd2, 0xcf, 0x10, 0x51, 0x19, 0xca, 0x1b, 0xfc, 0x82, 0xc1, - 0x93, 0xd9, 0x55, 0x1a, 0x26, 0xa3, 0x0d, 0x8d, 0x47, 0x4b, 0x84, 0x83, 0x61, 0xab, 0x54, 0xe1, 0xad, 0x5f, 0x42, - 0xfa, 0x2d, 0x8d, 0x47, 0x37, 0x34, 0xb5, 0x36, 0xa7, 0x06, 0xea, 0xaa, 0x37, 0xa6, 0xb7, 0x11, 0xbc, 0xde, 0x44, - 0x4b, 0x0a, 0x5b, 0xe9, 0x34, 0xcf, 0x2e, 0x45, 0x94, 0x52, 0x44, 0x20, 0x5c, 0x23, 0x72, 0xe0, 0x52, 0xa3, 0x0d, - 0xae, 0x07, 0x50, 0x86, 0x86, 0x0b, 0x5c, 0x0e, 0xe2, 0xd1, 0xd2, 0x23, 0x53, 0x6b, 0x7d, 0x91, 0x45, 0xf8, 0x68, - 0x67, 0xa3, 0xa5, 0x78, 0x46, 0x2c, 0x8c, 0x2b, 0x18, 0x42, 0x5d, 0x58, 0x69, 0x0a, 0x92, 0x2e, 0x70, 0x64, 0x2f, - 0x8c, 0xab, 0x70, 0x0b, 0xa6, 0x45, 0x1b, 0x30, 0x8f, 0x02, 0x85, 0x83, 0x4b, 0x90, 0x7e, 0x42, 0xd9, 0xce, 0x51, - 0x9a, 0x1c, 0xde, 0x04, 0x5d, 0xec, 0x4d, 0x10, 0xd2, 0xae, 0x6e, 0xb2, 0x25, 0x7d, 0x83, 0xed, 0x3d, 0x3a, 0x15, - 0x15, 0x54, 0x9f, 0x5b, 0x30, 0x59, 0xb2, 0x41, 0xd8, 0x12, 0xa6, 0x67, 0xfa, 0x02, 0xb0, 0xa7, 0x0f, 0x8f, 0xf6, - 0xe6, 0xbb, 0x98, 0xbd, 0x39, 0x2c, 0xa3, 0xb1, 0xb2, 0xe0, 0xcd, 0x2d, 0xb1, 0x5b, 0xb2, 0xf1, 0x74, 0x79, 0x5c, - 0x4e, 0x97, 0x48, 0xec, 0x0c, 0xdd, 0x62, 0x7c, 0xbe, 0x5c, 0xd0, 0x04, 0xcf, 0x36, 0x56, 0xcd, 0x97, 0x06, 0x2d, - 0x25, 0x65, 0xb8, 0xde, 0x96, 0xe8, 0xff, 0xaf, 0x2e, 0x7e, 0x29, 0xc0, 0x4b, 0x30, 0x16, 0x00, 0xc2, 0x3d, 0x98, - 0x16, 0xa4, 0x36, 0xca, 0xc6, 0x3a, 0x0d, 0x53, 0x5c, 0x04, 0x26, 0xa5, 0xdf, 0x0f, 0x73, 0x96, 0x12, 0x0f, 0x3a, - 0xd4, 0x8e, 0xd2, 0xaa, 0x61, 0x33, 0x07, 0x3c, 0x92, 0x3a, 0xc7, 0x26, 0x7f, 0x1f, 0xcf, 0x02, 0x35, 0x10, 0x41, - 0x94, 0x1d, 0xe3, 0x23, 0x06, 0x2e, 0x8a, 0x74, 0xdc, 0x4e, 0x57, 0xc4, 0xe5, 0xfe, 0x31, 0x0b, 0x71, 0x92, 0x30, - 0xd7, 0x2c, 0x1b, 0xb2, 0x2a, 0xc2, 0x04, 0x5d, 0x18, 0xd8, 0xaf, 0x0d, 0x59, 0x75, 0x78, 0x04, 0x91, 0x5a, 0x6d, - 0x19, 0x57, 0x5d, 0x65, 0x7c, 0x0f, 0x40, 0xd6, 0x8c, 0xb1, 0xa3, 0xbf, 0x8d, 0x67, 0xea, 0x9b, 0x28, 0xe4, 0x27, - 0x47, 0x7f, 0x83, 0xe4, 0xe3, 0xef, 0x91, 0x99, 0x83, 0xe4, 0x46, 0x41, 0xe7, 0xcd, 0x59, 0xd7, 0x50, 0x9a, 0xb8, - 0xf6, 0x4a, 0xbd, 0xf6, 0xa4, 0x59, 0x7b, 0x05, 0xba, 0x53, 0x1b, 0xde, 0x43, 0xd9, 0xce, 0x82, 0x09, 0x3a, 0x9a, - 0xdd, 0x81, 0x0e, 0xde, 0x29, 0x82, 0x9e, 0x25, 0xa1, 0xf1, 0x08, 0x55, 0x46, 0xbd, 0x18, 0x0f, 0xaa, 0x93, 0x75, - 0xc9, 0x3c, 0x03, 0xe6, 0xd8, 0x9e, 0x43, 0x62, 0x98, 0xab, 0x83, 0x3a, 0x65, 0xe5, 0x30, 0xc7, 0x03, 0x78, 0xcd, - 0xe4, 0x50, 0x0c, 0x72, 0x8d, 0xf2, 0x7d, 0xc1, 0x8a, 0x61, 0x39, 0xc8, 0x35, 0x37, 0x33, 0x6d, 0xc6, 0xa6, 0x4d, - 0x74, 0x78, 0xe6, 0x15, 0x3b, 0x59, 0xf5, 0x80, 0x8f, 0x05, 0x4f, 0x66, 0xdf, 0xf3, 0xf1, 0x01, 0x70, 0x32, 0xdb, - 0xdb, 0x68, 0x49, 0x37, 0x51, 0x4a, 0x6f, 0xa2, 0x35, 0x5d, 0x46, 0x17, 0xc6, 0xc4, 0x38, 0xa9, 0xe1, 0x1c, 0x80, - 0x56, 0x01, 0x24, 0x9e, 0xfa, 0xf5, 0x9e, 0x27, 0x55, 0xb8, 0xa4, 0x29, 0xb8, 0x0d, 0xfb, 0xf6, 0x99, 0x67, 0xbe, - 0x44, 0x6a, 0x8b, 0x18, 0x6b, 0xd6, 0x50, 0x71, 0xeb, 0xad, 0xfb, 0x48, 0xd4, 0xb0, 0x73, 0x5d, 0x6c, 0xa2, 0x6a, - 0x38, 0x99, 0x96, 0x80, 0xd8, 0x5a, 0x0e, 0x87, 0xee, 0x08, 0xd9, 0x3f, 0x7e, 0x74, 0xa0, 0xe7, 0x9e, 0xb4, 0xd8, - 0xb6, 0x2d, 0x7f, 0x60, 0x08, 0x53, 0xfa, 0xe5, 0x23, 0x1f, 0x10, 0x2b, 0xce, 0xe1, 0x6c, 0x04, 0xea, 0x68, 0x85, - 0x4e, 0xff, 0xaa, 0xc2, 0x42, 0x1f, 0xe0, 0xdb, 0xdb, 0x28, 0xa1, 0x9b, 0x28, 0xf7, 0xc8, 0xda, 0xb2, 0x66, 0x72, - 0x7a, 0x96, 0x85, 0xbc, 0x7d, 0xa0, 0x97, 0x0b, 0x00, 0xd1, 0x1a, 0xc4, 0xbe, 0xd4, 0xf5, 0x08, 0x9c, 0x86, 0xd0, - 0x24, 0x34, 0x82, 0xab, 0x0a, 0xc2, 0x08, 0xb8, 0x92, 0xf0, 0x37, 0x98, 0xa8, 0xc0, 0x17, 0xe0, 0x22, 0x93, 0xa6, - 0x39, 0x0f, 0x6a, 0x7f, 0x24, 0x5f, 0x17, 0x6d, 0x6f, 0x57, 0x18, 0x4d, 0x30, 0xf6, 0x44, 0xfb, 0x3c, 0x52, 0x8e, - 0xe2, 0x22, 0x09, 0xb3, 0xd1, 0xad, 0x3a, 0xcf, 0x69, 0x36, 0xda, 0xe8, 0x5f, 0x15, 0x1d, 0xd3, 0x5f, 0x75, 0x40, - 0x1b, 0x25, 0x7d, 0xeb, 0x38, 0x1b, 0xd0, 0x7a, 0xb1, 0x34, 0xfe, 0xd7, 0x72, 0x74, 0x4b, 0xe5, 0x68, 0xe3, 0x5b, - 0x52, 0x4d, 0xa6, 0xc5, 0xb1, 0x40, 0x43, 0xaa, 0xce, 0xef, 0x0b, 0xe0, 0xe7, 0x4a, 0xe3, 0x3b, 0x6d, 0xbe, 0xf7, - 0xda, 0xbf, 0xe9, 0xe4, 0x09, 0x14, 0x4b, 0x54, 0xb0, 0x6a, 0x04, 0x76, 0xec, 0xeb, 0x3c, 0x2e, 0xcc, 0x28, 0xc5, - 0xd4, 0x9a, 0xf4, 0x63, 0xe0, 0x8a, 0x69, 0xaf, 0x00, 0x57, 0x4b, 0x70, 0x12, 0x80, 0x18, 0x9a, 0xb0, 0x67, 0xc7, - 0x10, 0xf5, 0xdc, 0x38, 0x46, 0xc9, 0x86, 0x7b, 0x40, 0xac, 0x65, 0xde, 0xca, 0x25, 0x20, 0x81, 0xb7, 0x1e, 0x26, - 0x05, 0x60, 0x0c, 0x96, 0x4b, 0xa2, 0xf3, 0x78, 0xe8, 0x13, 0xea, 0x85, 0x46, 0x9d, 0x90, 0x8d, 0x2d, 0x81, 0xe3, - 0x0f, 0xeb, 0x43, 0x20, 0x78, 0x95, 0xe7, 0xfa, 0x2b, 0xad, 0xeb, 0x2f, 0x95, 0x9e, 0x3b, 0x96, 0x17, 0xb5, 0xba, - 0x4d, 0x8d, 0x5e, 0x80, 0x85, 0xef, 0x56, 0x99, 0x47, 0x72, 0x8b, 0x90, 0xaa, 0xc0, 0x4a, 0xdd, 0x42, 0x82, 0xf9, - 0x57, 0x72, 0xb6, 0x2a, 0xf3, 0xd5, 0x23, 0xf7, 0xca, 0xd9, 0xf4, 0xf4, 0x37, 0x24, 0x68, 0x9b, 0x8e, 0x34, 0x8f, - 0xb7, 0xe8, 0xf0, 0xd9, 0xb5, 0x96, 0x98, 0x7b, 0x89, 0x8a, 0xe7, 0x53, 0xc0, 0x56, 0xcf, 0xb2, 0x2b, 0xe5, 0x63, - 0xb5, 0x8f, 0xe3, 0x67, 0xce, 0x9f, 0xa4, 0x0a, 0x2f, 0x44, 0x43, 0x09, 0x02, 0xde, 0x1c, 0xc6, 0xae, 0x50, 0x05, - 0x34, 0x34, 0x37, 0x70, 0x9c, 0xab, 0x61, 0xa5, 0x09, 0x98, 0x96, 0xf2, 0xe8, 0x00, 0x87, 0x26, 0x8f, 0xda, 0x4d, - 0xc3, 0xca, 0xd0, 0xb5, 0x46, 0x9f, 0xdb, 0x4a, 0x67, 0xbc, 0xd9, 0xf0, 0xc3, 0xa3, 0x41, 0x85, 0x3f, 0x49, 0x73, - 0x34, 0xda, 0xb9, 0xe1, 0x4e, 0x23, 0x30, 0x73, 0x25, 0x57, 0x64, 0x7f, 0x94, 0xbc, 0xfc, 0x9e, 0x5e, 0x58, 0x40, - 0x7f, 0xfe, 0xfb, 0x62, 0xc2, 0x49, 0x4b, 0x4c, 0x88, 0x96, 0x0e, 0x5a, 0x74, 0xb0, 0xa7, 0xbc, 0xb2, 0x2f, 0xf1, - 0xd2, 0x39, 0xfe, 0xcf, 0xf5, 0x58, 0xfb, 0x0a, 0x84, 0x56, 0x27, 0x0f, 0xdb, 0x93, 0x05, 0xa2, 0x06, 0x54, 0xb3, - 0xab, 0x72, 0x94, 0x69, 0x67, 0x45, 0xb6, 0x0d, 0x99, 0xeb, 0x7e, 0x96, 0x86, 0xcd, 0x64, 0xc7, 0xc2, 0x32, 0xc3, - 0x60, 0xed, 0x54, 0xd1, 0xe7, 0xa0, 0xe5, 0x47, 0xf0, 0xac, 0xa9, 0x3c, 0xf3, 0xd9, 0x2c, 0x23, 0x5e, 0xa0, 0x73, - 0x4e, 0xc5, 0xa2, 0x29, 0x1d, 0x2b, 0x77, 0xbb, 0x12, 0x8d, 0x25, 0xca, 0x28, 0x08, 0x6a, 0x1b, 0x84, 0x5d, 0x97, - 0xee, 0x49, 0x9f, 0xf6, 0xf1, 0x69, 0x05, 0xfa, 0x1e, 0xdf, 0x65, 0x20, 0x31, 0xf5, 0x24, 0x0f, 0x55, 0xa3, 0x39, - 0x3a, 0x79, 0x96, 0xa7, 0x1a, 0x9f, 0x5f, 0xc9, 0xce, 0x9a, 0x77, 0xab, 0x31, 0xc5, 0x7f, 0xa4, 0x6e, 0xdf, 0xb9, - 0x0c, 0x4d, 0xf4, 0xd7, 0xf2, 0xa0, 0xa5, 0xb0, 0xe0, 0xb8, 0x6d, 0xfc, 0xf5, 0xdb, 0xcc, 0x21, 0x86, 0xa5, 0xcb, - 0xe1, 0x4d, 0xe8, 0xd0, 0xdd, 0x55, 0xf6, 0xe6, 0xfa, 0x88, 0x3a, 0x75, 0xb1, 0x6e, 0x03, 0x4a, 0x96, 0xbc, 0x5b, - 0xa7, 0x27, 0x56, 0xfa, 0xf5, 0x30, 0xdc, 0x9b, 0x47, 0xcd, 0xee, 0xee, 0x76, 0x13, 0xd2, 0xb6, 0x0f, 0xc6, 0xfb, - 0x12, 0x16, 0xe2, 0xbc, 0xc3, 0x0e, 0x7e, 0x0e, 0xab, 0x87, 0x7c, 0xf0, 0x3b, 0x8e, 0x33, 0x8c, 0x7e, 0xa6, 0x0c, - 0x7d, 0x5e, 0x14, 0xf2, 0x4a, 0x75, 0xca, 0x17, 0xba, 0xb5, 0x4c, 0xbd, 0xdf, 0xc4, 0x6f, 0x5a, 0x01, 0x62, 0xbc, - 0xae, 0x58, 0x29, 0xde, 0xd0, 0x0a, 0xe3, 0x1a, 0xb8, 0x4d, 0x0e, 0xb5, 0x54, 0x0b, 0x44, 0x5d, 0x7e, 0xf2, 0x90, - 0x47, 0x46, 0x9d, 0x09, 0xdf, 0x3d, 0xe4, 0xbe, 0x74, 0x6d, 0xbf, 0x89, 0x5f, 0x6a, 0xda, 0xe1, 0xfe, 0x40, 0x77, - 0xb4, 0xee, 0xfe, 0xe6, 0xd9, 0xfc, 0x3c, 0x32, 0x5f, 0x0c, 0xb0, 0x59, 0xfb, 0x8c, 0xcb, 0x9e, 0xe1, 0xbe, 0x37, - 0x3d, 0x18, 0x0b, 0x08, 0x24, 0x66, 0xe8, 0x65, 0xe0, 0x02, 0x17, 0xb8, 0x2b, 0x0c, 0x18, 0xe2, 0x9a, 0x96, 0xdc, - 0x6a, 0x2b, 0x5b, 0x1f, 0x79, 0x1b, 0x15, 0x82, 0x75, 0xdd, 0x71, 0x93, 0xe4, 0x10, 0x9c, 0xb0, 0xe5, 0xde, 0xd7, - 0x5e, 0x3b, 0xc3, 0x5f, 0x06, 0xc2, 0xb9, 0x25, 0x7a, 0x46, 0x6d, 0x0f, 0xb5, 0xba, 0xd7, 0xf0, 0x2a, 0x9b, 0xc8, - 0xb3, 0x7e, 0x33, 0x2f, 0x0d, 0xfb, 0x82, 0xd7, 0x52, 0x70, 0x68, 0x6c, 0xb7, 0xc2, 0x2d, 0x16, 0xef, 0x68, 0xb5, - 0xb2, 0xd6, 0x56, 0x7b, 0xad, 0x54, 0xf4, 0xee, 0x35, 0xc7, 0x89, 0xb3, 0x14, 0xb6, 0x1f, 0xde, 0x5f, 0xb0, 0x6b, - 0x02, 0x18, 0xb4, 0x98, 0x2c, 0x50, 0x82, 0x4a, 0xd6, 0xaa, 0x76, 0x3b, 0x25, 0x7e, 0xb9, 0x5f, 0x75, 0x99, 0xed, - 0x3c, 0x7e, 0xdd, 0xa4, 0x7d, 0xe1, 0x73, 0xf4, 0xc3, 0xfc, 0xc1, 0x3a, 0x29, 0x39, 0xc3, 0xb8, 0x96, 0xff, 0x5f, - 0x45, 0x2f, 0x8b, 0x2c, 0x8d, 0xb6, 0x86, 0x07, 0xb3, 0xa1, 0x36, 0x7d, 0x68, 0x8c, 0xca, 0x2d, 0x1b, 0x45, 0x44, - 0xab, 0x5b, 0x10, 0xcc, 0x28, 0xee, 0x4b, 0xb4, 0x79, 0xa5, 0xca, 0xc2, 0x3b, 0x7c, 0x61, 0xa3, 0x37, 0x6c, 0x4f, - 0x08, 0xe5, 0xfb, 0xa7, 0x85, 0x59, 0xb5, 0x54, 0x34, 0xd8, 0x2e, 0xe1, 0x5d, 0x8c, 0x2a, 0xfd, 0x84, 0xc9, 0x96, - 0x05, 0x53, 0xfd, 0xff, 0xb1, 0xc8, 0xd2, 0x36, 0x45, 0x07, 0xa6, 0xb3, 0xe9, 0xd3, 0x49, 0xb7, 0xb8, 0xce, 0x80, - 0x45, 0x04, 0x5b, 0x2a, 0x1c, 0x8f, 0x52, 0xbb, 0x41, 0xc2, 0x44, 0x70, 0x13, 0xf5, 0xb2, 0xa3, 0x65, 0x4a, 0x56, - 0x05, 0x3c, 0xbf, 0x72, 0x95, 0xe9, 0x38, 0x1a, 0xfa, 0xfd, 0xb3, 0xd4, 0x84, 0x7e, 0xa5, 0x5e, 0xaa, 0xe2, 0x3c, - 0x8c, 0xaa, 0x43, 0x85, 0x31, 0x5a, 0xd2, 0x14, 0x8e, 0xc1, 0xec, 0x22, 0x4c, 0xf1, 0x72, 0xb6, 0x4d, 0xd8, 0x57, - 0x0c, 0xe4, 0x52, 0x1b, 0xd4, 0x6b, 0x4a, 0xb4, 0x66, 0xed, 0xcd, 0x9c, 0x12, 0x7a, 0xc1, 0x4a, 0xff, 0x2e, 0xb4, - 0x06, 0x81, 0xa2, 0x6c, 0xa6, 0x4c, 0x37, 0xba, 0x9d, 0x17, 0x34, 0xa1, 0x05, 0x5d, 0x91, 0x1a, 0xf4, 0xbd, 0x4e, - 0xce, 0x8e, 0x4e, 0x76, 0x66, 0xd6, 0x63, 0x56, 0x0c, 0x27, 0xd3, 0x18, 0xae, 0x69, 0xb1, 0xbb, 0xa6, 0x2d, 0x9b, - 0x37, 0xae, 0xc6, 0xc6, 0x69, 0xd0, 0x2e, 0x90, 0xb6, 0x69, 0x6e, 0x3f, 0xf5, 0xb8, 0xfd, 0x75, 0xcd, 0x96, 0xd3, - 0xde, 0x7a, 0xb7, 0xeb, 0xa5, 0x60, 0x23, 0xea, 0xf1, 0xf1, 0x6b, 0x25, 0x5d, 0xb7, 0x5c, 0x7e, 0x0a, 0xcf, 0x1e, - 0x5f, 0xbf, 0xf4, 0xc1, 0xe5, 0x68, 0xd5, 0xe6, 0xee, 0x97, 0xfb, 0xc8, 0x72, 0x5f, 0x35, 0xb4, 0x5c, 0xcf, 0x50, - 0x93, 0x3c, 0x1b, 0xed, 0x1d, 0x6a, 0xc1, 0x72, 0xd6, 0x4d, 0x78, 0x62, 0xb0, 0x63, 0xaf, 0x1a, 0x9b, 0xa3, 0x32, - 0x97, 0xac, 0x06, 0x09, 0xf4, 0x49, 0x9e, 0x69, 0xfa, 0x47, 0x19, 0xe6, 0xa3, 0x5b, 0x9a, 0x03, 0xae, 0x58, 0x65, - 0x2f, 0x19, 0xa4, 0xae, 0xda, 0x4b, 0x5c, 0xf9, 0x0a, 0x87, 0x64, 0x8b, 0x4f, 0x86, 0xa9, 0xfa, 0xe2, 0x92, 0x07, - 0xff, 0x6f, 0xab, 0x56, 0xe9, 0xb9, 0x49, 0x6e, 0x38, 0xfe, 0x75, 0xd2, 0xf6, 0x31, 0x31, 0x48, 0xc0, 0x53, 0xbb, - 0x18, 0xaa, 0x51, 0x55, 0xc4, 0xa2, 0xcc, 0x4d, 0xcc, 0xb1, 0x3b, 0xbb, 0x86, 0x0e, 0xca, 0xe0, 0xd7, 0x0d, 0x9f, - 0x98, 0x3b, 0xb0, 0x15, 0xe8, 0xe8, 0x44, 0x73, 0x19, 0x66, 0xe6, 0x32, 0x4c, 0xbb, 0xb6, 0x0a, 0x0c, 0xaf, 0xda, - 0x2a, 0x89, 0x72, 0x35, 0xea, 0x71, 0x33, 0x4b, 0xcd, 0x5e, 0xe4, 0xdd, 0x6b, 0xd2, 0x93, 0xf8, 0xd3, 0xa5, 0x27, - 0xaf, 0x87, 0x01, 0x91, 0x5f, 0xb3, 0x34, 0x5c, 0xa3, 0x20, 0x38, 0xb5, 0xda, 0x81, 0x34, 0x1f, 0x01, 0x32, 0x3f, - 0x4e, 0xc3, 0x0f, 0x5a, 0x9c, 0x43, 0xb6, 0x4a, 0xe3, 0xc4, 0x96, 0x46, 0x3d, 0x04, 0x77, 0xde, 0x2b, 0x1e, 0x43, - 0xe0, 0xc3, 0x8f, 0xb8, 0x19, 0x54, 0x74, 0x5b, 0x62, 0xa2, 0xb4, 0x79, 0xd4, 0x2d, 0x1f, 0x35, 0x84, 0x4a, 0x56, - 0x86, 0x97, 0x40, 0x7b, 0xf7, 0x04, 0x46, 0x95, 0x13, 0xc8, 0x0c, 0x8b, 0xc3, 0xa3, 0x61, 0xaa, 0x04, 0x45, 0x43, - 0x39, 0x5c, 0xa2, 0x1c, 0x10, 0x93, 0x40, 0x60, 0x54, 0x0c, 0x52, 0x5d, 0x99, 0x7a, 0x31, 0x48, 0xf5, 0xad, 0x8a, - 0xd4, 0x67, 0x59, 0x58, 0x51, 0xdd, 0x22, 0x3a, 0xa6, 0x43, 0x49, 0x97, 0x66, 0xa7, 0xe6, 0x5a, 0x7a, 0xa1, 0x96, - 0xe3, 0x53, 0x9d, 0x06, 0xa3, 0xf8, 0xc1, 0xa5, 0xe8, 0xb7, 0x6a, 0x3f, 0xfb, 0x6f, 0x31, 0xa5, 0x46, 0x6c, 0x6a, - 0x6f, 0x11, 0xc3, 0xaa, 0xfd, 0x98, 0x55, 0x39, 0x68, 0x77, 0x41, 0xd9, 0x58, 0x19, 0xe7, 0xf9, 0x46, 0x30, 0x73, - 0xd0, 0x36, 0x56, 0x4d, 0x1f, 0x7a, 0x23, 0x46, 0xed, 0x8d, 0xa9, 0xc6, 0x3d, 0x81, 0x9f, 0x36, 0x68, 0xba, 0x17, - 0x79, 0x8e, 0x7a, 0xe4, 0xdd, 0xff, 0xcc, 0x91, 0x9d, 0xc9, 0x17, 0xb1, 0x4c, 0xea, 0xf6, 0x31, 0x09, 0x16, 0xaa, - 0x8e, 0xd1, 0x85, 0x1b, 0x99, 0xd2, 0x7e, 0xee, 0x4d, 0x3f, 0xe2, 0x99, 0xdc, 0x6f, 0x87, 0x46, 0x7d, 0x69, 0x58, - 0x4b, 0x8a, 0xa8, 0x2f, 0xe8, 0xad, 0xa9, 0x8e, 0x8e, 0xa8, 0xd7, 0x11, 0x58, 0x5d, 0xd1, 0x16, 0x35, 0x00, 0x93, - 0x71, 0x6d, 0x6b, 0xf3, 0x39, 0x98, 0xda, 0xaa, 0x0a, 0x9e, 0xd0, 0x7d, 0xa1, 0x74, 0x6f, 0x52, 0xd7, 0xad, 0x21, - 0xb6, 0x80, 0x01, 0x81, 0x1b, 0x3d, 0x35, 0xfd, 0x41, 0x13, 0x15, 0x80, 0x06, 0x8d, 0xdb, 0x99, 0xce, 0x91, 0xe8, - 0x77, 0x6a, 0xd3, 0x36, 0x53, 0xbd, 0xaa, 0x7c, 0x00, 0x15, 0x7f, 0x96, 0xce, 0x2e, 0xcc, 0x88, 0x05, 0x30, 0xee, - 0x81, 0x33, 0xd5, 0x3b, 0xcd, 0xc0, 0x7a, 0x22, 0xcf, 0xb3, 0x92, 0x27, 0x52, 0xc0, 0x8c, 0xc8, 0xab, 0x2b, 0x29, - 0x60, 0x18, 0xd4, 0x00, 0xa0, 0x45, 0x73, 0x19, 0x4d, 0xf8, 0xa3, 0x9a, 0xde, 0x95, 0x87, 0x3f, 0xd2, 0xb9, 0xbe, - 0x1b, 0xd7, 0x60, 0xa8, 0xbc, 0xae, 0xf8, 0x5e, 0xa6, 0xef, 0xf8, 0x63, 0x2f, 0xd3, 0x52, 0xae, 0x8b, 0xbd, 0x2c, - 0x8f, 0xbe, 0xe3, 0x4f, 0x74, 0x9e, 0xa3, 0xc7, 0x35, 0x4d, 0xe3, 0xcd, 0x5e, 0x96, 0xbf, 0x7f, 0xf7, 0xd8, 0xe6, - 0x79, 0x34, 0xae, 0xe9, 0x0d, 0xe7, 0x9f, 0x5c, 0xa6, 0x89, 0xae, 0x6a, 0xfc, 0xf8, 0xef, 0x36, 0xd7, 0xe3, 0x9a, - 0x5e, 0x49, 0x51, 0x2d, 0xf7, 0x8a, 0x3a, 0xfa, 0xee, 0xe8, 0xef, 0xfc, 0x3b, 0xd3, 0xbd, 0xa3, 0x9a, 0xfe, 0xb5, - 0x8e, 0x8b, 0x8a, 0x17, 0x7b, 0xc5, 0xfd, 0xed, 0xef, 0x7f, 0x7f, 0x6c, 0x33, 0x3e, 0xae, 0xe9, 0x86, 0xc7, 0x1d, - 0x6d, 0x9f, 0x3c, 0x79, 0xcc, 0xff, 0x56, 0xd7, 0xf4, 0x37, 0xe6, 0x07, 0x47, 0x3d, 0xcd, 0x3c, 0x3d, 0x7c, 0x2e, - 0x9b, 0xa8, 0x01, 0x43, 0x0f, 0x0d, 0x60, 0x29, 0xad, 0x9a, 0xe6, 0x0e, 0xaf, 0x5c, 0x70, 0xfb, 0x3e, 0x8b, 0xd3, - 0x78, 0x05, 0x07, 0xc1, 0x16, 0x8d, 0xb3, 0x0a, 0xe0, 0x54, 0x81, 0xf7, 0x8c, 0x4a, 0x9a, 0x95, 0xf2, 0x37, 0xce, - 0x3f, 0xc1, 0xa0, 0x21, 0xa4, 0x8d, 0x8a, 0x0c, 0xf4, 0x76, 0xa5, 0x23, 0x1b, 0xa1, 0xff, 0x66, 0x33, 0x0e, 0x8e, - 0x0f, 0xa3, 0xd7, 0xef, 0x87, 0x05, 0x13, 0x61, 0x41, 0x08, 0xfd, 0x33, 0x2c, 0xc0, 0xa1, 0xa4, 0x60, 0x5e, 0x3e, - 0xe3, 0x7b, 0xae, 0x8d, 0xc2, 0x42, 0x10, 0xdd, 0x45, 0xf6, 0x01, 0x55, 0x8f, 0xbe, 0x43, 0x37, 0xc4, 0xcb, 0x0a, - 0x0b, 0x86, 0x56, 0x35, 0x30, 0x43, 0x50, 0xfc, 0x6b, 0x1e, 0x4a, 0xf0, 0x89, 0x07, 0xf8, 0xe8, 0x31, 0x99, 0x71, - 0x75, 0xad, 0x7d, 0x7b, 0x11, 0x16, 0x34, 0xd0, 0x6d, 0x87, 0xa0, 0x03, 0x91, 0xff, 0x02, 0x3c, 0x05, 0x06, 0x3e, - 0x2c, 0xec, 0xba, 0x03, 0xcf, 0xe7, 0x37, 0xc3, 0x3a, 0xba, 0xf0, 0xa3, 0xbf, 0x59, 0x17, 0xf6, 0x8c, 0x4c, 0xe5, - 0x71, 0x39, 0x9c, 0x4c, 0x07, 0x03, 0xe9, 0xe2, 0xb8, 0x9d, 0x66, 0xf3, 0xdf, 0xe6, 0x72, 0xb1, 0x40, 0xdd, 0x37, - 0xce, 0xeb, 0x4c, 0xff, 0x8d, 0xb4, 0xf3, 0xc1, 0xeb, 0xd3, 0x7f, 0x9d, 0x7d, 0x38, 0x7d, 0x01, 0xce, 0x07, 0x1f, - 0x9f, 0xff, 0xf8, 0xfc, 0xbd, 0x0a, 0xee, 0xae, 0xe6, 0xbc, 0xdf, 0x77, 0x52, 0x9f, 0x90, 0x0f, 0x2b, 0x72, 0x18, - 0xc6, 0x0f, 0x0b, 0x65, 0xf4, 0x40, 0x8e, 0x99, 0x85, 0x42, 0x86, 0x2a, 0x6a, 0xfb, 0xbb, 0x1c, 0x4e, 0x3c, 0x30, - 0x8b, 0xeb, 0x86, 0x08, 0xd7, 0x6f, 0xb9, 0x0d, 0xb2, 0x26, 0x4f, 0xbc, 0x7e, 0x70, 0x32, 0x95, 0x8e, 0x2d, 0x2c, - 0x18, 0x94, 0x0d, 0x6d, 0x3a, 0xcd, 0xe6, 0xc5, 0xc2, 0xb6, 0xcb, 0x2d, 0x90, 0x51, 0x9a, 0x5d, 0x5c, 0x84, 0x0a, - 0xba, 0xfa, 0x04, 0x34, 0x00, 0xa6, 0x51, 0x85, 0x6b, 0x11, 0x9f, 0xf9, 0xe5, 0x47, 0x63, 0xaf, 0x79, 0x37, 0xa8, - 0x7b, 0x32, 0xcd, 0xaa, 0x1a, 0x03, 0x3a, 0x98, 0x50, 0xee, 0x06, 0xdd, 0x04, 0x93, 0x51, 0x6d, 0xf9, 0x6d, 0x5e, - 0x2d, 0x4c, 0x73, 0xdc, 0x30, 0x54, 0x5e, 0xc9, 0x17, 0xb2, 0x81, 0xc8, 0x40, 0x32, 0x0c, 0x7b, 0x34, 0x46, 0x91, - 0xfa, 0xc1, 0xbe, 0x77, 0xfc, 0x36, 0x97, 0x10, 0x4d, 0x31, 0x03, 0xe9, 0xfc, 0x73, 0xa1, 0x9c, 0xcb, 0x25, 0xe3, - 0x73, 0xb1, 0x38, 0x01, 0xb7, 0xf3, 0xb9, 0x58, 0x44, 0x18, 0x94, 0x2f, 0x83, 0x58, 0x25, 0x60, 0xf7, 0xe2, 0xa0, - 0x47, 0x3a, 0xa1, 0x0d, 0xec, 0x06, 0x92, 0x6c, 0x50, 0xda, 0x95, 0x86, 0x28, 0x77, 0xca, 0xa3, 0x0d, 0x22, 0x0f, - 0xb1, 0x6a, 0x5e, 0xb5, 0x3d, 0xd9, 0xcc, 0xc5, 0x04, 0x57, 0x59, 0xcc, 0xe4, 0x34, 0x3e, 0x66, 0xc5, 0x34, 0x86, - 0x52, 0xe2, 0x34, 0x0d, 0x63, 0x3a, 0xa1, 0x82, 0x90, 0x84, 0xf1, 0x79, 0xbc, 0xa0, 0x09, 0x4a, 0x09, 0x42, 0x08, - 0xf9, 0x31, 0x42, 0xdb, 0x1c, 0x58, 0xf2, 0x76, 0xfb, 0x79, 0x2a, 0xbe, 0x3d, 0xc3, 0x65, 0x54, 0x84, 0x6e, 0xd1, - 0x59, 0xc3, 0xbf, 0x11, 0x15, 0x34, 0xc6, 0x8a, 0x21, 0x08, 0x78, 0x81, 0x51, 0x09, 0x0b, 0x12, 0xb3, 0x0a, 0xa2, - 0x08, 0x94, 0xf3, 0x78, 0xc1, 0x0a, 0xda, 0xb4, 0x39, 0x8d, 0xb5, 0x49, 0x50, 0xcf, 0x61, 0xa9, 0x1d, 0x48, 0xa5, - 0x42, 0xec, 0xf1, 0x99, 0x88, 0x3e, 0x69, 0x43, 0x03, 0x40, 0x81, 0x52, 0x72, 0xf1, 0x9b, 0xaf, 0xf7, 0x70, 0x53, - 0xd0, 0xff, 0x6c, 0x6b, 0xa2, 0x9d, 0xe5, 0xea, 0xd0, 0x9b, 0x2f, 0x68, 0x9c, 0xe7, 0x10, 0x8a, 0xcd, 0x20, 0x90, - 0x8b, 0xac, 0x82, 0x88, 0x16, 0x9b, 0xc0, 0x84, 0x84, 0x83, 0x36, 0xfd, 0x02, 0xa9, 0x0d, 0x31, 0xb9, 0xf2, 0xc4, - 0xc0, 0x6e, 0xab, 0x04, 0x01, 0x47, 0x7a, 0x9e, 0x7d, 0x6e, 0x62, 0xac, 0x69, 0x6a, 0x66, 0xe2, 0x6d, 0x28, 0x44, - 0x83, 0x16, 0x44, 0x33, 0x78, 0xff, 0x5c, 0x71, 0xbc, 0xea, 0xc0, 0x0f, 0x78, 0xe7, 0xe2, 0xcc, 0xab, 0x99, 0x47, - 0xe4, 0xd4, 0xe7, 0x39, 0xa2, 0x5f, 0xf2, 0xb0, 0x1a, 0xe9, 0x64, 0x8c, 0x95, 0xc4, 0x41, 0x6f, 0x83, 0x05, 0x73, - 0x42, 0x57, 0x3c, 0xb4, 0x7c, 0xfc, 0x0b, 0x64, 0x32, 0x4a, 0x6a, 0xac, 0xe8, 0x4a, 0x8b, 0x11, 0xe7, 0x35, 0xcc, - 0xd2, 0x64, 0x45, 0x17, 0x0b, 0x4d, 0x9a, 0x85, 0x32, 0x0d, 0xf0, 0x09, 0xb4, 0x18, 0xb9, 0x87, 0x9a, 0x36, 0x10, - 0x1a, 0xf6, 0x87, 0x80, 0x8f, 0xdc, 0x43, 0x87, 0xff, 0x9f, 0x67, 0x17, 0x88, 0xb4, 0x77, 0x69, 0x22, 0xe3, 0x91, - 0xba, 0x81, 0x83, 0x62, 0x7c, 0xec, 0x9b, 0x89, 0x5f, 0x39, 0xa3, 0xf7, 0x49, 0xe5, 0x3b, 0x7c, 0xb0, 0xfc, 0xf1, - 0xa6, 0x66, 0x56, 0x46, 0xb0, 0x1e, 0x76, 0x3b, 0x5c, 0x10, 0x6d, 0x17, 0x40, 0xea, 0x19, 0xaf, 0x16, 0xbe, 0xf1, - 0x6a, 0x7c, 0x87, 0xf1, 0xaa, 0xb3, 0xfa, 0x0a, 0x73, 0xb2, 0x45, 0x7d, 0x96, 0x92, 0xe7, 0xe7, 0x28, 0x13, 0x6c, - 0xba, 0x9c, 0x95, 0x54, 0xa5, 0x12, 0xda, 0x8b, 0xfd, 0x8c, 0xf1, 0x2d, 0xc1, 0x38, 0x2b, 0x0e, 0x23, 0x81, 0xaa, - 0x54, 0x52, 0x87, 0xbd, 0x02, 0xd4, 0x63, 0xf0, 0xde, 0x60, 0x88, 0x1a, 0x19, 0xbb, 0x69, 0x03, 0xa1, 0xa1, 0xb1, - 0x1e, 0xed, 0x59, 0xeb, 0xd1, 0xdd, 0xae, 0x32, 0xfe, 0x76, 0x72, 0x5d, 0x24, 0x88, 0x2a, 0xac, 0x46, 0x13, 0xe0, - 0x4d, 0x13, 0x7b, 0x5b, 0x72, 0x4a, 0x0b, 0x0c, 0x9f, 0xfd, 0x67, 0x58, 0x3a, 0x95, 0x44, 0x49, 0x66, 0x65, 0x34, - 0x70, 0xe7, 0xe0, 0xb3, 0xb8, 0x82, 0x35, 0x00, 0x91, 0x1c, 0xd1, 0xc3, 0xf5, 0xcf, 0x50, 0xba, 0xcc, 0x92, 0xcc, - 0x24, 0x64, 0xe6, 0x22, 0x6d, 0x67, 0x1d, 0x4c, 0x9c, 0x49, 0xad, 0x37, 0x16, 0x72, 0x68, 0x90, 0x1f, 0x40, 0x19, - 0xe2, 0xf0, 0xc9, 0x07, 0x13, 0x2a, 0x55, 0x28, 0xd5, 0x46, 0x37, 0xbb, 0x81, 0x57, 0x3e, 0x66, 0x57, 0xbc, 0xac, - 0xe2, 0xab, 0x95, 0xb1, 0x24, 0xe6, 0xec, 0x2e, 0xb7, 0x3d, 0x2a, 0xcc, 0xab, 0x37, 0xcf, 0x7f, 0x3c, 0x6d, 0xbc, - 0xda, 0x47, 0x1c, 0x0d, 0xc1, 0xb6, 0x62, 0x8c, 0xd1, 0x5b, 0x7c, 0x1a, 0x4c, 0x94, 0x6b, 0x04, 0x7a, 0x97, 0x82, - 0x7e, 0xfb, 0x6b, 0x3d, 0x01, 0xaf, 0xb8, 0x5e, 0x7e, 0xc9, 0x27, 0xc0, 0x12, 0x15, 0x7a, 0x56, 0x98, 0x9b, 0x95, - 0xd9, 0x9d, 0xdd, 0x8a, 0xcc, 0xb4, 0x2b, 0x8d, 0x0c, 0xc4, 0xab, 0xed, 0x30, 0x16, 0x2e, 0x5d, 0xd3, 0xed, 0x60, - 0x57, 0x4b, 0xcf, 0x12, 0x79, 0xb7, 0x2b, 0xa1, 0x43, 0x76, 0xc0, 0xbd, 0x97, 0xf1, 0x2d, 0xbc, 0x2c, 0xbd, 0x6e, - 0x36, 0x83, 0x27, 0x80, 0x99, 0x70, 0xe1, 0x2c, 0x8b, 0x63, 0x26, 0x92, 0x50, 0xc5, 0xe6, 0x6a, 0x88, 0xbc, 0x15, - 0xa1, 0x35, 0xfb, 0x2b, 0x14, 0x23, 0xb0, 0x3b, 0xf9, 0xf0, 0x29, 0x5b, 0xcd, 0xd6, 0x80, 0x9a, 0x7f, 0x95, 0x09, - 0xa0, 0xb9, 0x76, 0x2d, 0xd8, 0xa6, 0xd0, 0xe6, 0xba, 0x7e, 0x1a, 0xaf, 0xe2, 0x04, 0x54, 0x37, 0xe0, 0x2d, 0x72, - 0xad, 0x45, 0x57, 0x06, 0x5d, 0x94, 0xde, 0x53, 0x8e, 0x25, 0x85, 0x8e, 0xbe, 0xf7, 0x84, 0x3a, 0xf7, 0x0c, 0xe0, - 0x92, 0x46, 0xcd, 0x53, 0x2d, 0x65, 0x2c, 0x00, 0x16, 0x3a, 0x98, 0x29, 0xb2, 0x15, 0xdd, 0x18, 0x4c, 0x0a, 0x78, - 0x6b, 0x80, 0x3f, 0x44, 0x56, 0xa9, 0xbb, 0x62, 0x19, 0x96, 0x9e, 0xfd, 0x75, 0xbf, 0x1f, 0x7b, 0xf6, 0xd7, 0x2b, - 0x4d, 0xeb, 0xe2, 0x76, 0x03, 0x48, 0x8d, 0x01, 0x44, 0x4e, 0xf5, 0x40, 0x98, 0x88, 0x62, 0x4d, 0xdf, 0xbf, 0x53, - 0x93, 0x45, 0x81, 0xd0, 0xef, 0xd5, 0xeb, 0x49, 0x49, 0x40, 0xa7, 0x56, 0xb1, 0x93, 0x81, 0x36, 0xfb, 0x80, 0x80, - 0xa8, 0x7e, 0x46, 0x36, 0x5f, 0x28, 0xe7, 0x62, 0x15, 0x3e, 0x7c, 0x4c, 0x21, 0xa0, 0x70, 0x47, 0x8d, 0xce, 0xdb, - 0x10, 0x09, 0x94, 0x15, 0x8a, 0x58, 0xf3, 0x62, 0x2d, 0x09, 0x99, 0x8f, 0x17, 0x28, 0xb8, 0x72, 0xc0, 0xae, 0x9c, - 0x4d, 0x86, 0x65, 0xc4, 0x59, 0x78, 0xf7, 0x37, 0x93, 0x05, 0x41, 0xcd, 0x95, 0x1f, 0xc8, 0x71, 0x2f, 0x53, 0x63, - 0x4f, 0x35, 0x6a, 0x10, 0x4c, 0x46, 0x10, 0x18, 0x6e, 0xf8, 0x15, 0x1f, 0x1f, 0x2d, 0x08, 0xa8, 0xc8, 0xac, 0x59, - 0x88, 0x79, 0x71, 0xfc, 0x08, 0x50, 0x63, 0x46, 0x47, 0x4f, 0xa6, 0x9c, 0xc1, 0x21, 0x4a, 0xc7, 0x20, 0xa3, 0x15, - 0xf0, 0x5b, 0xa8, 0xdf, 0xad, 0x13, 0xdf, 0x87, 0x7e, 0x15, 0xf4, 0x22, 0x06, 0x86, 0x23, 0x9a, 0x1c, 0x86, 0x7c, - 0x30, 0x19, 0x80, 0xb6, 0xc4, 0xdb, 0x7d, 0x2d, 0xad, 0xb8, 0x39, 0x5d, 0x3a, 0xdd, 0x3f, 0x69, 0x13, 0x24, 0x91, - 0x4a, 0x56, 0x2a, 0x62, 0x00, 0xa1, 0x2c, 0xd5, 0x36, 0x59, 0x83, 0x65, 0x85, 0x59, 0xd2, 0xdc, 0xa0, 0x24, 0xee, - 0x6f, 0x06, 0x8e, 0x51, 0xb3, 0x4e, 0xc3, 0xb2, 0xe5, 0x46, 0x0d, 0xf0, 0x39, 0x09, 0x2b, 0xec, 0x0d, 0x67, 0x26, - 0xbd, 0x33, 0x1d, 0xae, 0x8e, 0x39, 0x7b, 0xcd, 0x11, 0x8c, 0x23, 0xc1, 0x1b, 0x0f, 0x5d, 0x32, 0x0d, 0x15, 0x99, - 0x32, 0x0e, 0xa6, 0x3d, 0xc0, 0xbd, 0xe7, 0x60, 0x1c, 0xc6, 0x06, 0x95, 0x25, 0xf5, 0xa9, 0x77, 0x17, 0x02, 0x41, - 0x5a, 0xeb, 0x65, 0x3e, 0xc3, 0xd3, 0x33, 0x42, 0xd9, 0x1f, 0x72, 0xf8, 0x02, 0xec, 0x28, 0xc8, 0xc9, 0x84, 0x3f, - 0x79, 0xb8, 0x1f, 0xa8, 0x8a, 0x0f, 0x82, 0x83, 0x58, 0xa4, 0x07, 0xc1, 0x40, 0xc0, 0xaf, 0x82, 0x1f, 0x54, 0x52, - 0x1e, 0x5c, 0xc4, 0xc5, 0x41, 0xbc, 0x8a, 0x8b, 0xea, 0xe0, 0x26, 0xab, 0x96, 0x07, 0xa6, 0x43, 0x00, 0xcd, 0x1b, - 0x0c, 0xe2, 0x41, 0x70, 0x10, 0x0c, 0x0a, 0x33, 0xb5, 0x2b, 0x56, 0x36, 0x8e, 0x33, 0x13, 0xa2, 0x2c, 0x68, 0x06, - 0x08, 0x6b, 0x9c, 0x06, 0xc0, 0xa7, 0xae, 0x59, 0x4a, 0x2f, 0x30, 0xdc, 0x80, 0x98, 0xae, 0xa1, 0x0f, 0xc0, 0x23, - 0xaf, 0x69, 0x0c, 0x4b, 0xe0, 0x62, 0x30, 0x20, 0x17, 0x10, 0xb9, 0x60, 0x4d, 0x6d, 0x10, 0x87, 0x70, 0xad, 0xec, - 0xb4, 0xf7, 0x81, 0x99, 0x76, 0x3b, 0x40, 0x54, 0x9e, 0x90, 0x7e, 0xdf, 0x7e, 0x43, 0xfd, 0x0b, 0xf6, 0x12, 0xec, - 0xaf, 0x8a, 0x2a, 0xcc, 0xa5, 0xd2, 0x7c, 0x5f, 0xb2, 0x93, 0x81, 0x8a, 0x38, 0xbc, 0xe7, 0x48, 0xd1, 0x46, 0xe5, - 0xb2, 0xec, 0xc9, 0xb2, 0xe1, 0x2b, 0x71, 0xc5, 0x9d, 0x1f, 0x57, 0x25, 0x65, 0x5e, 0x65, 0x2b, 0xc5, 0xfe, 0xcd, - 0xb8, 0xe6, 0xfe, 0xc0, 0xfa, 0xb3, 0xf9, 0x0a, 0xae, 0xad, 0xde, 0xbb, 0x26, 0xd7, 0x88, 0x9c, 0x25, 0x94, 0x4b, - 0x6a, 0x9b, 0x87, 0xb7, 0xf4, 0x7d, 0x7e, 0xf5, 0x6d, 0xa6, 0xd3, 0xf8, 0xac, 0xc2, 0xc2, 0x85, 0x68, 0x45, 0x70, - 0x68, 0xc8, 0x45, 0xf3, 0x08, 0x30, 0xd7, 0x3e, 0x5b, 0x41, 0x41, 0xea, 0xb3, 0x0a, 0xbd, 0x5b, 0x21, 0xe1, 0x85, - 0x66, 0x97, 0xee, 0x07, 0x52, 0xc6, 0xed, 0xa1, 0x25, 0x4c, 0x5a, 0x5e, 0x84, 0xf7, 0x5e, 0x73, 0x93, 0x7b, 0x16, - 0x62, 0xf4, 0x22, 0xcf, 0x4e, 0xc0, 0x58, 0x77, 0xc9, 0xce, 0x86, 0x27, 0x7e, 0xc3, 0x73, 0xd6, 0xa2, 0xd1, 0x74, - 0xc9, 0x92, 0x7e, 0x3f, 0x06, 0x13, 0xef, 0x94, 0xe5, 0xf0, 0x2b, 0x5f, 0xd0, 0x35, 0x03, 0x4c, 0x31, 0x7a, 0x01, - 0x09, 0x29, 0x22, 0x91, 0xac, 0xd5, 0x49, 0xf2, 0x85, 0xee, 0x02, 0x30, 0xfa, 0xc5, 0x2c, 0x8d, 0x96, 0x77, 0x9a, - 0x59, 0x20, 0x79, 0x86, 0xbe, 0xeb, 0x60, 0x7b, 0x63, 0x1f, 0xa4, 0x9c, 0x1f, 0x8b, 0xe9, 0x60, 0xc0, 0x89, 0x86, - 0x1b, 0x2f, 0x95, 0xb8, 0x56, 0xb7, 0xb8, 0x63, 0x18, 0x4b, 0x7d, 0x5b, 0xc4, 0xe0, 0x80, 0x5d, 0xb4, 0xb2, 0xdb, - 0x07, 0xd8, 0x57, 0x8e, 0x77, 0xa9, 0xb2, 0x3b, 0x3d, 0x66, 0x9a, 0xcb, 0x56, 0x93, 0x4e, 0x2a, 0xee, 0x26, 0xf2, - 0x4d, 0xee, 0xa0, 0xcb, 0xe5, 0x58, 0xf3, 0x96, 0x03, 0x50, 0xd1, 0x8f, 0x14, 0xd5, 0xfd, 0x0a, 0x47, 0x98, 0x7b, - 0xeb, 0x36, 0x9f, 0x1c, 0x9a, 0x02, 0x87, 0xc8, 0x93, 0x36, 0x9a, 0x02, 0xba, 0x77, 0xf1, 0xb0, 0xab, 0xdf, 0x96, - 0xee, 0x02, 0x25, 0xda, 0xab, 0xb8, 0xe1, 0xc7, 0x44, 0x9d, 0xce, 0xb4, 0x21, 0xf4, 0xaf, 0x8c, 0xb8, 0xbf, 0x34, - 0xae, 0xe2, 0x4d, 0xef, 0xf2, 0x19, 0x87, 0x3a, 0xbb, 0x21, 0x14, 0x80, 0xab, 0xf6, 0x74, 0xea, 0xc6, 0x90, 0x5e, - 0x29, 0xd1, 0x6d, 0x70, 0xb0, 0x3b, 0x7d, 0xc6, 0x51, 0xf4, 0x63, 0xd4, 0xc8, 0x37, 0x91, 0x78, 0x28, 0x07, 0xf1, - 0xc3, 0x82, 0x2e, 0x23, 0xf1, 0xb0, 0x18, 0xc4, 0x0f, 0x65, 0x5d, 0xef, 0x9f, 0x2b, 0x77, 0xf7, 0x11, 0x79, 0xd6, - 0xbd, 0xbd, 0x54, 0xc2, 0xc6, 0xc0, 0xb3, 0x6b, 0x01, 0xe1, 0x14, 0x3c, 0x91, 0xad, 0xa5, 0x0f, 0x9d, 0xdb, 0x7d, - 0x6c, 0x99, 0x24, 0x08, 0x7a, 0xde, 0x66, 0x93, 0x28, 0x76, 0xb6, 0x79, 0xf4, 0xe1, 0x14, 0x48, 0xe8, 0x76, 0xdb, - 0xac, 0xab, 0x35, 0xa0, 0x98, 0x86, 0x63, 0x7e, 0x58, 0x8c, 0x6e, 0x7c, 0x77, 0xfd, 0xc3, 0x62, 0xb4, 0x24, 0xc3, - 0x89, 0x99, 0xfc, 0xf8, 0x64, 0x3c, 0x8b, 0xa3, 0x49, 0xdd, 0x71, 0x5a, 0x68, 0xfc, 0x53, 0xef, 0x16, 0x8a, 0xc0, - 0xa9, 0x18, 0xc1, 0x91, 0x53, 0xa1, 0x9c, 0x94, 0x1a, 0x18, 0xfe, 0x07, 0xd5, 0x9e, 0x36, 0xed, 0x75, 0x5c, 0x25, - 0xcb, 0x4c, 0x5c, 0xea, 0xf0, 0xe1, 0x3a, 0xba, 0xb8, 0x0d, 0x68, 0xe7, 0x5d, 0xa6, 0x1d, 0xbf, 0x4e, 0x1a, 0xf4, - 0xc4, 0xd5, 0xcc, 0x80, 0x5b, 0xf7, 0x23, 0x34, 0x43, 0x60, 0xb4, 0x3c, 0x7f, 0x87, 0x98, 0xdb, 0xbf, 0x2a, 0x9b, - 0x5f, 0x45, 0xfb, 0x1c, 0x19, 0x29, 0xdb, 0x64, 0xa4, 0x02, 0x23, 0x4c, 0x29, 0x92, 0xb8, 0x0a, 0x21, 0x90, 0xfd, - 0xd7, 0x14, 0xd7, 0x62, 0xe9, 0xbd, 0x06, 0x61, 0x82, 0xed, 0x82, 0xf6, 0xab, 0xdb, 0xbb, 0xad, 0xb4, 0xd8, 0x23, - 0xf5, 0x7d, 0xee, 0x6c, 0x57, 0x34, 0xf9, 0xfb, 0xba, 0x01, 0x6d, 0x00, 0x51, 0xde, 0xd5, 0x47, 0x25, 0x70, 0x32, - 0xe2, 0x86, 0x12, 0xa3, 0x17, 0x74, 0x75, 0x22, 0xf7, 0xec, 0xd4, 0xbc, 0xa9, 0x98, 0xa9, 0xb8, 0xf2, 0xcd, 0x9e, - 0xf9, 0x0f, 0x86, 0x82, 0x4a, 0x30, 0xf0, 0x36, 0x67, 0x3c, 0x3a, 0xd0, 0xdd, 0x18, 0x9d, 0x16, 0x6c, 0x16, 0xd4, - 0x65, 0xdd, 0xb4, 0xf1, 0xa0, 0x11, 0x07, 0x45, 0xb1, 0x2a, 0xd4, 0x48, 0x78, 0x22, 0x10, 0x30, 0x65, 0x57, 0x3c, - 0x32, 0x82, 0x9a, 0xde, 0x84, 0xc2, 0x86, 0x82, 0xbf, 0x4a, 0x54, 0xd3, 0x9b, 0xd0, 0x26, 0x13, 0xa7, 0x19, 0x44, - 0x30, 0x23, 0xb6, 0xfb, 0x2d, 0xa0, 0xcd, 0xad, 0x19, 0x6d, 0xeb, 0xda, 0x6a, 0xab, 0x90, 0x4b, 0x8a, 0x94, 0xe5, - 0xbf, 0x53, 0x53, 0x41, 0x49, 0x2d, 0x17, 0xbd, 0x49, 0xd3, 0x45, 0x8f, 0x67, 0x46, 0x12, 0xa8, 0xdc, 0x72, 0xc7, - 0xe8, 0x0f, 0x61, 0x81, 0x47, 0x4c, 0x9c, 0x58, 0x30, 0xb7, 0x3a, 0x61, 0xd9, 0x5c, 0x2c, 0x46, 0x2b, 0x09, 0x61, - 0x83, 0x8f, 0x59, 0x36, 0x2f, 0xf5, 0x43, 0xe8, 0x0b, 0x4b, 0x1f, 0x80, 0x5d, 0x6c, 0xb0, 0x92, 0x65, 0x00, 0xbe, - 0x17, 0x74, 0xbb, 0x92, 0x65, 0x24, 0x55, 0xf7, 0xe3, 0x1a, 0x4b, 0x50, 0x69, 0x85, 0x4a, 0x4b, 0x6a, 0x2c, 0x08, - 0x7c, 0x55, 0x75, 0xf9, 0x90, 0xec, 0x2a, 0x50, 0x4f, 0x1d, 0x35, 0xe0, 0x14, 0xa8, 0x2a, 0xb0, 0x20, 0x09, 0x2a, - 0x43, 0x57, 0x05, 0xa6, 0x15, 0x98, 0x66, 0xaa, 0x70, 0x51, 0x66, 0x87, 0xd2, 0xac, 0x97, 0x7c, 0x16, 0x0f, 0xc2, - 0x64, 0x18, 0x93, 0x87, 0x08, 0xb5, 0x7f, 0x98, 0x47, 0xb1, 0x96, 0x4b, 0x5e, 0x3a, 0xbf, 0xf8, 0x9b, 0x2f, 0xd8, - 0xeb, 0x9e, 0x61, 0xb0, 0x00, 0x67, 0x69, 0x7b, 0x95, 0x89, 0x77, 0xb2, 0x15, 0x1c, 0x07, 0xb3, 0x28, 0x87, 0x55, - 0x4f, 0x8e, 0x68, 0x2e, 0x72, 0xed, 0x5d, 0x84, 0xc8, 0x41, 0x66, 0x8f, 0x01, 0x76, 0x23, 0x7c, 0x1d, 0x5a, 0x9b, - 0x5b, 0x5d, 0x21, 0xfe, 0x46, 0x89, 0xc4, 0x4f, 0x52, 0x7e, 0x5a, 0xaf, 0x54, 0xae, 0xca, 0xe0, 0xb1, 0xea, 0x66, - 0xf0, 0x4c, 0xfb, 0x1e, 0x6b, 0xff, 0xd6, 0x76, 0x73, 0xbc, 0xf7, 0xe0, 0x41, 0xeb, 0x7f, 0xeb, 0x49, 0x08, 0xed, - 0x95, 0x93, 0xd4, 0x1d, 0x35, 0x7a, 0x66, 0xb2, 0x46, 0x54, 0xc2, 0xd4, 0xee, 0x54, 0x8e, 0x81, 0x9a, 0x0e, 0xe0, - 0x5a, 0xa2, 0x26, 0xe8, 0x49, 0xc1, 0xc6, 0x70, 0xc4, 0x59, 0x1c, 0xb4, 0xe3, 0x18, 0xc5, 0xcb, 0xb9, 0x12, 0x2f, - 0xe7, 0x27, 0x8c, 0x03, 0xb4, 0x16, 0x20, 0xd5, 0x6b, 0xd8, 0xcf, 0x5c, 0xc1, 0x02, 0x9b, 0x3b, 0xdf, 0x91, 0x05, - 0x32, 0xc4, 0xc9, 0xe6, 0x38, 0xd9, 0xe3, 0x5a, 0xcf, 0xbd, 0xc0, 0xc7, 0x49, 0xbd, 0xf0, 0xea, 0x2a, 0xdb, 0x75, - 0x2d, 0x59, 0x39, 0x2f, 0x06, 0x13, 0x08, 0xca, 0x52, 0xce, 0x8b, 0xe1, 0x64, 0x41, 0x73, 0xf8, 0xb1, 0x68, 0xa0, - 0x43, 0x2c, 0x07, 0x09, 0x5c, 0x3a, 0x7b, 0x0c, 0x78, 0x43, 0xa9, 0xc5, 0xdd, 0x58, 0x47, 0x8e, 0x75, 0x14, 0x87, - 0x61, 0x0c, 0xb8, 0xb2, 0x4e, 0xe0, 0x7d, 0xf7, 0xf5, 0xb1, 0x09, 0xc8, 0xaa, 0x5d, 0xe1, 0xd5, 0x28, 0x77, 0x5d, - 0x69, 0xf4, 0x25, 0xa5, 0x27, 0xbc, 0xe0, 0xa9, 0x64, 0xb7, 0xeb, 0x19, 0x38, 0x5b, 0xe2, 0x21, 0xf1, 0x8e, 0x11, - 0xbd, 0x98, 0x36, 0x32, 0x73, 0x02, 0x67, 0xb6, 0xbb, 0x6c, 0x63, 0x7e, 0xec, 0x00, 0x07, 0x8b, 0x20, 0x24, 0x6e, - 0x08, 0xc3, 0xc4, 0x4e, 0xca, 0xa1, 0x16, 0xc2, 0x75, 0x2d, 0xbc, 0x8e, 0xd3, 0x32, 0x06, 0x17, 0x69, 0x6d, 0x9b, - 0x78, 0x07, 0x5d, 0xf7, 0xfc, 0x98, 0x5b, 0x1d, 0xa3, 0x2d, 0xa4, 0xdf, 0x8e, 0x4e, 0x1f, 0x38, 0x0c, 0x40, 0xd3, - 0x83, 0x59, 0xd5, 0x3e, 0x93, 0xb8, 0x39, 0xed, 0x04, 0x21, 0x11, 0x88, 0xa2, 0x74, 0x46, 0x98, 0xfe, 0xbd, 0xe6, - 0xb2, 0x8a, 0x56, 0xf7, 0xf2, 0xcc, 0x21, 0xcf, 0x42, 0x6f, 0x7b, 0xd0, 0xaa, 0xb9, 0x1b, 0x8c, 0x13, 0xb7, 0xdb, - 0x3b, 0xff, 0x6f, 0x59, 0xd7, 0x56, 0x6b, 0xc4, 0xc3, 0x76, 0xf5, 0x83, 0xc6, 0x5e, 0xed, 0xa9, 0x18, 0x30, 0x97, - 0xd2, 0x3b, 0xa3, 0x4a, 0x5e, 0x64, 0xbc, 0xc4, 0x93, 0xea, 0xb2, 0xe1, 0xe3, 0x7d, 0x93, 0x8d, 0xcc, 0x03, 0x99, - 0x02, 0xe2, 0xf9, 0x87, 0xd4, 0xa8, 0x8f, 0x53, 0x94, 0x80, 0xbf, 0xd3, 0xf1, 0x8d, 0xe8, 0x6b, 0xfb, 0xe2, 0x92, - 0x57, 0x6f, 0x6f, 0x84, 0x79, 0xf1, 0xcc, 0xea, 0xfc, 0xe9, 0xd3, 0xc2, 0x87, 0x0e, 0x47, 0xed, 0x1d, 0x14, 0x59, - 0x32, 0x71, 0x32, 0x31, 0xb2, 0x36, 0x31, 0x7b, 0xad, 0xe0, 0x62, 0xa2, 0x0a, 0x3d, 0xeb, 0xec, 0x09, 0x53, 0x80, - 0xbe, 0x71, 0x8c, 0x4a, 0xc6, 0xb0, 0x60, 0xa0, 0x4e, 0x53, 0x42, 0xf4, 0x50, 0xcc, 0x30, 0x5e, 0x31, 0x80, 0xc2, - 0x14, 0x0a, 0x44, 0xd1, 0xd9, 0x87, 0x03, 0x4d, 0xe8, 0xf7, 0x3f, 0xa4, 0x3a, 0x03, 0x2d, 0xeb, 0x69, 0x01, 0xa2, - 0x3a, 0x88, 0xb6, 0x0a, 0x51, 0xa1, 0x53, 0x5a, 0x66, 0x34, 0x15, 0x74, 0x2d, 0x68, 0x92, 0xd1, 0x0b, 0xae, 0x44, - 0xc5, 0x2b, 0xc1, 0x14, 0x6d, 0x37, 0x84, 0xfd, 0x1f, 0x0d, 0xba, 0xde, 0x8a, 0xb5, 0x86, 0x76, 0x27, 0xc8, 0x08, - 0xcd, 0x17, 0x3a, 0x08, 0x19, 0x2a, 0x27, 0xa1, 0x6b, 0x95, 0xc6, 0x2b, 0x70, 0xc9, 0x34, 0x1b, 0x2d, 0xe3, 0x32, - 0x0c, 0xec, 0x57, 0x81, 0xc5, 0xe4, 0xc0, 0xa4, 0x0f, 0xeb, 0xf3, 0xa7, 0xf2, 0x6a, 0x25, 0x05, 0x17, 0x95, 0x82, - 0xe8, 0x37, 0xb8, 0xef, 0x26, 0xae, 0x3a, 0x6b, 0xd6, 0x4a, 0xef, 0xfb, 0xd6, 0x67, 0x6d, 0xdc, 0x17, 0x06, 0xc7, - 0x60, 0xef, 0x23, 0x62, 0x20, 0x0d, 0x2a, 0xdd, 0xe2, 0xd0, 0x04, 0xe8, 0xd2, 0x21, 0x85, 0x2c, 0x99, 0xca, 0x54, - 0x09, 0x2a, 0xbe, 0xf1, 0x7b, 0x29, 0xab, 0xd1, 0x5f, 0x6b, 0x5e, 0x6c, 0x3e, 0xf0, 0x9c, 0xe3, 0x18, 0x05, 0x49, - 0x2c, 0xae, 0xe3, 0x32, 0x20, 0xbe, 0xe5, 0x55, 0x70, 0x94, 0x9a, 0xb0, 0x31, 0x7b, 0x55, 0xa3, 0xd6, 0xab, 0x40, - 0x5f, 0x19, 0xe5, 0x1b, 0x83, 0xa1, 0x89, 0xa8, 0x82, 0xbe, 0xd7, 0xea, 0x9e, 0x56, 0x37, 0x2c, 0x20, 0xfe, 0x5c, - 0xe9, 0x85, 0x5a, 0xaf, 0x9b, 0x31, 0x37, 0x4c, 0x84, 0xa0, 0xd1, 0xa3, 0x7a, 0xe1, 0xf0, 0xf3, 0xb7, 0xca, 0x92, - 0x08, 0x5e, 0x6c, 0xd3, 0x75, 0x61, 0x62, 0x69, 0x50, 0x1d, 0x30, 0x37, 0xda, 0xe6, 0xfc, 0x12, 0x44, 0x7f, 0xce, - 0x8a, 0x68, 0x52, 0xd7, 0x54, 0x21, 0x18, 0x46, 0xdb, 0xdb, 0x46, 0x3a, 0xdd, 0x80, 0x97, 0x9b, 0xb1, 0x46, 0xd2, - 0x9e, 0x8e, 0x35, 0x2d, 0x78, 0xb9, 0x92, 0xa2, 0x84, 0xe8, 0xce, 0xbd, 0x31, 0xbd, 0x8a, 0x33, 0x51, 0xc5, 0x99, - 0x38, 0x2d, 0x57, 0x3c, 0xa9, 0xde, 0x43, 0x85, 0xda, 0x18, 0x07, 0x5b, 0xaf, 0x46, 0x5d, 0x85, 0x43, 0x7e, 0x75, - 0xf1, 0xfc, 0x76, 0x15, 0x8b, 0x14, 0x46, 0xbd, 0xbe, 0xeb, 0x45, 0x73, 0x3a, 0x56, 0x71, 0xc1, 0x85, 0x89, 0x5a, - 0x4c, 0x2b, 0x16, 0x70, 0x9d, 0x31, 0xa0, 0x5c, 0xc5, 0xee, 0xcc, 0x54, 0x2c, 0xc3, 0xb8, 0x2c, 0x7f, 0xca, 0x4a, - 0xbc, 0x03, 0x40, 0x6b, 0xe0, 0xb4, 0x98, 0x19, 0x10, 0x90, 0x4d, 0x6e, 0x70, 0x11, 0x58, 0x70, 0xf4, 0x78, 0xbc, - 0xba, 0x0d, 0xa8, 0xf7, 0x46, 0xaa, 0xeb, 0x21, 0x0b, 0xc6, 0xa3, 0x27, 0x81, 0x43, 0x0e, 0xf1, 0x3f, 0x7a, 0x7c, - 0x74, 0xf7, 0x37, 0x93, 0x80, 0xd4, 0x53, 0x50, 0x55, 0x18, 0x85, 0x28, 0x4c, 0xfb, 0xeb, 0xb5, 0xba, 0xe5, 0xbe, - 0x3d, 0x2f, 0x79, 0x71, 0x0d, 0xfb, 0x92, 0x4c, 0x33, 0x20, 0xe7, 0x52, 0x25, 0xc0, 0xa2, 0x88, 0xab, 0xaa, 0xc8, - 0xce, 0xc1, 0x44, 0x09, 0x0d, 0xc0, 0xcc, 0xd3, 0x0b, 0x74, 0xf8, 0x88, 0xe6, 0x01, 0xf6, 0x29, 0x58, 0xd4, 0xa4, - 0x2e, 0xa1, 0xb0, 0xe4, 0x00, 0x83, 0xd5, 0xa9, 0xb8, 0xd2, 0x0e, 0xe0, 0xbb, 0xfa, 0x23, 0x5a, 0x4a, 0x8c, 0x35, - 0xab, 0xe7, 0x29, 0x3e, 0x2f, 0x65, 0xbe, 0xae, 0x40, 0x7b, 0x7e, 0x51, 0x45, 0x47, 0x8f, 0x57, 0xb7, 0x53, 0xd5, - 0x8d, 0x08, 0x7a, 0x31, 0x55, 0x38, 0x6f, 0x49, 0x9c, 0x27, 0xe1, 0x64, 0x3c, 0xfe, 0xe6, 0x60, 0x78, 0x00, 0xc9, - 0x64, 0xfa, 0x79, 0xa8, 0x1c, 0xb9, 0x86, 0x93, 0xf1, 0xb8, 0xfe, 0xa3, 0x36, 0x61, 0xbe, 0x4d, 0x3d, 0x1f, 0xfe, - 0x38, 0x56, 0xeb, 0xff, 0xe4, 0xf8, 0x50, 0xff, 0xf8, 0xa3, 0xae, 0xa7, 0x4f, 0x8b, 0x70, 0xfe, 0xef, 0x50, 0xad, - 0xef, 0xd3, 0xa2, 0x88, 0x37, 0x35, 0x59, 0xd0, 0x95, 0x70, 0xde, 0x35, 0xd4, 0x23, 0x0b, 0xf4, 0x88, 0x4c, 0x57, - 0x82, 0xc1, 0x37, 0xef, 0xab, 0x30, 0xe0, 0xe5, 0x6a, 0xc8, 0x45, 0x95, 0x55, 0x9b, 0x21, 0xe6, 0x09, 0xf0, 0x53, - 0x8b, 0x67, 0x56, 0x18, 0xe2, 0x7b, 0x51, 0x70, 0xfe, 0x99, 0x87, 0xca, 0x58, 0x7c, 0x8c, 0xc6, 0xe2, 0x63, 0xaa, - 0xba, 0x31, 0xf9, 0x8e, 0xea, 0xbe, 0x4d, 0xbe, 0x03, 0x93, 0xac, 0xac, 0xfd, 0x8d, 0x32, 0xd6, 0x8c, 0xc6, 0xf4, - 0xfa, 0x45, 0x9e, 0xad, 0xe0, 0x52, 0xb0, 0xd4, 0x3f, 0x6a, 0x42, 0xdf, 0xf3, 0x76, 0xf6, 0xd1, 0x68, 0xf4, 0xa0, - 0xa0, 0xa3, 0xd1, 0xe8, 0x53, 0x56, 0x13, 0x7a, 0x29, 0x3a, 0xde, 0xbf, 0xe7, 0xf4, 0x5c, 0xa6, 0x9b, 0x28, 0x08, - 0xe8, 0x32, 0x4b, 0x53, 0x2e, 0x54, 0x59, 0x4f, 0xd3, 0x76, 0x5e, 0xd5, 0x42, 0x04, 0x42, 0xd2, 0x6d, 0x44, 0x48, - 0x26, 0x42, 0xdf, 0xee, 0xf5, 0x6c, 0x34, 0x1a, 0x3d, 0x4d, 0x4d, 0xb5, 0xee, 0x82, 0xf2, 0x00, 0xcd, 0x29, 0x9c, - 0x9f, 0x02, 0x58, 0x23, 0x99, 0xe8, 0x2f, 0x87, 0xff, 0x35, 0x9c, 0xcd, 0xc7, 0xc3, 0xef, 0x47, 0x8b, 0x87, 0x87, - 0x34, 0x08, 0xfc, 0xd0, 0x0d, 0xa1, 0xb6, 0x6e, 0x99, 0x96, 0xc7, 0xe3, 0x29, 0x29, 0x07, 0xec, 0xb1, 0xf5, 0x2d, - 0xfa, 0xe6, 0x31, 0x20, 0xb3, 0xa2, 0x48, 0x39, 0x70, 0xd2, 0x50, 0xbc, 0x9a, 0xbd, 0x12, 0x80, 0x17, 0x67, 0x23, - 0x3b, 0x18, 0xad, 0xe8, 0x38, 0x82, 0xf2, 0x6a, 0x6b, 0x2a, 0xd2, 0x63, 0x2c, 0x33, 0x51, 0x52, 0xc7, 0xd3, 0xf2, - 0x26, 0xab, 0x92, 0x25, 0x06, 0x7a, 0x8a, 0x4b, 0x1e, 0x7c, 0x13, 0x44, 0x25, 0x3b, 0x7a, 0x32, 0x55, 0x70, 0xc7, - 0x98, 0x94, 0xf2, 0x4b, 0x48, 0xfc, 0x7e, 0x8c, 0x90, 0xb0, 0x44, 0x7b, 0x70, 0x62, 0x8d, 0x2f, 0x72, 0x19, 0x83, - 0x47, 0x6b, 0xa9, 0x79, 0x38, 0x7b, 0x32, 0x5a, 0x7b, 0x94, 0x56, 0x73, 0x24, 0x34, 0x27, 0x94, 0x4c, 0x1e, 0x96, - 0x54, 0x7e, 0x33, 0x41, 0x2f, 0x29, 0x70, 0x33, 0x8f, 0xe0, 0xf8, 0xb7, 0x96, 0x1e, 0xaa, 0x57, 0x6f, 0x53, 0x76, - 0x38, 0xff, 0x3f, 0x25, 0x5d, 0x0c, 0x0e, 0xdd, 0xd0, 0xbc, 0xd3, 0xee, 0xbc, 0x15, 0x32, 0x8e, 0x55, 0xf8, 0x36, - 0x25, 0xd6, 0x18, 0x97, 0xb3, 0x93, 0xad, 0xe9, 0xce, 0xa8, 0x2a, 0xb2, 0xab, 0x90, 0xe8, 0x5e, 0x39, 0x90, 0xd0, - 0x20, 0xca, 0x46, 0xb8, 0x7e, 0xc0, 0x7a, 0xc6, 0xeb, 0xe4, 0x35, 0x2f, 0xaa, 0x2c, 0x51, 0xef, 0xaf, 0x1b, 0xef, - 0xeb, 0xda, 0x04, 0x54, 0x7d, 0x57, 0x30, 0x98, 0xe7, 0xb7, 0x05, 0x80, 0x98, 0x22, 0x0d, 0xf0, 0x09, 0x66, 0x10, - 0xd4, 0xae, 0x99, 0x57, 0x8d, 0xe0, 0x1b, 0xf0, 0xd5, 0xbb, 0x02, 0x30, 0x48, 0x42, 0x90, 0x22, 0x43, 0x68, 0x20, - 0x10, 0x68, 0x18, 0x72, 0x81, 0xc1, 0x4f, 0xbc, 0x38, 0x92, 0xca, 0x29, 0x91, 0x87, 0x01, 0xfe, 0x08, 0xa8, 0x0a, - 0x40, 0x62, 0x3c, 0x0e, 0xe1, 0x85, 0xfa, 0xe5, 0xde, 0xa8, 0x3d, 0xc2, 0x1e, 0xa4, 0x21, 0x04, 0x1b, 0xc2, 0x87, - 0x00, 0x96, 0x14, 0xa1, 0xef, 0x90, 0xcb, 0x08, 0x83, 0x8b, 0x3c, 0x5b, 0xe9, 0xa4, 0x6a, 0xd4, 0xd1, 0x7c, 0x28, - 0xb5, 0x23, 0x39, 0xa0, 0x5e, 0x7a, 0x8c, 0xe9, 0x85, 0x4a, 0x57, 0x45, 0x39, 0xa3, 0x9c, 0x53, 0x3d, 0x31, 0x2e, - 0x6c, 0x21, 0x87, 0x48, 0x38, 0xef, 0x0a, 0x15, 0x0a, 0x87, 0x2f, 0x00, 0x0c, 0x0c, 0xa4, 0x1d, 0xfb, 0xf1, 0x6e, - 0x54, 0xf6, 0x33, 0xce, 0x0e, 0xff, 0x6b, 0x1e, 0x0f, 0x3f, 0x8f, 0x87, 0xdf, 0x2f, 0x06, 0xe1, 0xd0, 0xfe, 0x24, - 0x0f, 0x1f, 0x1c, 0xd2, 0x17, 0xdc, 0x72, 0x69, 0xb0, 0xf0, 0x1b, 0xc1, 0x7e, 0xd4, 0x4a, 0x08, 0xa2, 0x00, 0x6f, - 0x58, 0x6e, 0x35, 0x4e, 0x00, 0xf0, 0x30, 0xf8, 0xdf, 0x01, 0x1a, 0x4d, 0xb9, 0x8b, 0x17, 0xe8, 0x4b, 0xd4, 0xef, - 0x93, 0x47, 0x0d, 0x83, 0x41, 0x10, 0xd7, 0xa8, 0x98, 0x30, 0x44, 0x97, 0x31, 0x51, 0x30, 0xc8, 0x36, 0xfb, 0x6e, - 0xd7, 0x6b, 0x4b, 0xc2, 0xf0, 0x4b, 0x3f, 0xd3, 0xc4, 0xcc, 0x3b, 0xdc, 0xd8, 0x56, 0x72, 0x15, 0x22, 0x56, 0xa0, - 0xfe, 0x95, 0x33, 0x88, 0xbd, 0x79, 0x9d, 0x81, 0x4f, 0x87, 0xfd, 0x62, 0x3c, 0x03, 0x36, 0x0a, 0xee, 0x7c, 0x05, - 0xbf, 0xc8, 0xc0, 0xcd, 0x5b, 0xc4, 0x28, 0x70, 0xb0, 0x4b, 0xa2, 0xdf, 0xef, 0xe5, 0x59, 0x98, 0x6b, 0xdc, 0xe9, - 0xbc, 0x36, 0x6a, 0x08, 0xd4, 0x91, 0x83, 0xfa, 0x41, 0x0f, 0xc1, 0x50, 0x0d, 0x41, 0xd1, 0xd1, 0x16, 0x57, 0xaf, - 0xad, 0xa7, 0x30, 0xbd, 0x55, 0xf5, 0x15, 0xa3, 0x3f, 0x65, 0x26, 0xb0, 0x90, 0x76, 0xcd, 0xb1, 0xae, 0x39, 0x46, - 0xda, 0xd3, 0xef, 0x8b, 0x06, 0xf9, 0xe9, 0x2c, 0x3c, 0x08, 0x54, 0xa9, 0x72, 0xaf, 0x2c, 0xca, 0x6d, 0x69, 0xde, - 0x18, 0xd6, 0x34, 0xcf, 0x6c, 0x9c, 0x9b, 0x59, 0xaf, 0x17, 0x86, 0xe8, 0xe0, 0x89, 0xa5, 0x62, 0x6d, 0x10, 0xee, - 0xc8, 0x24, 0x8c, 0xae, 0x40, 0x76, 0x19, 0x9e, 0x71, 0x82, 0x7c, 0x2a, 0xb0, 0x0f, 0xaa, 0x5a, 0x2f, 0x27, 0x3c, - 0x36, 0xf2, 0x65, 0x23, 0x68, 0x90, 0x97, 0x14, 0xf5, 0x26, 0x6e, 0xc7, 0x3e, 0x6f, 0x21, 0x57, 0x6e, 0xeb, 0x69, - 0x4f, 0x93, 0x8a, 0x1e, 0xeb, 0x55, 0xea, 0x17, 0x58, 0x5a, 0x58, 0xf2, 0x41, 0x68, 0x4f, 0xd3, 0x0a, 0xcc, 0x70, - 0x6d, 0x33, 0x18, 0xfa, 0xe1, 0xf8, 0x09, 0xe8, 0x8c, 0xda, 0x96, 0x10, 0xc6, 0x6e, 0x10, 0x56, 0xde, 0x13, 0xf9, - 0xe6, 0xb1, 0x77, 0x31, 0x08, 0xb9, 0xd9, 0xcc, 0xa2, 0x81, 0xe9, 0x7e, 0x2e, 0x9b, 0xcd, 0xd3, 0xcd, 0xf5, 0xa2, - 0x84, 0x0a, 0xd8, 0x6e, 0x97, 0x82, 0xe0, 0xdf, 0x4f, 0xd9, 0x0c, 0xff, 0x66, 0xfd, 0x7e, 0x2f, 0xc4, 0x5f, 0x1c, - 0x83, 0x19, 0xcd, 0xc5, 0x82, 0x7d, 0x02, 0x19, 0x13, 0x89, 0x30, 0x55, 0x19, 0x03, 0xb2, 0x0a, 0x2c, 0x02, 0xcd, - 0x07, 0x2a, 0x17, 0x66, 0xb2, 0x97, 0x39, 0xd7, 0x90, 0x57, 0xad, 0x71, 0xca, 0x46, 0x59, 0xa2, 0x5c, 0x39, 0xb2, - 0x51, 0x9c, 0x67, 0x71, 0xc9, 0xcb, 0xdd, 0x4e, 0x1f, 0x8e, 0x49, 0xc1, 0x81, 0x5d, 0x57, 0x54, 0xaa, 0x64, 0x1d, - 0xa9, 0x1e, 0x78, 0x69, 0x58, 0xe0, 0x3e, 0xe5, 0xf3, 0xc2, 0xd0, 0x88, 0x03, 0x10, 0x66, 0x30, 0x75, 0x4b, 0xef, - 0x85, 0x05, 0x34, 0xaf, 0x24, 0x64, 0x8b, 0xa9, 0x9e, 0x85, 0x6f, 0xcc, 0xc4, 0xbc, 0x58, 0x40, 0x58, 0x9d, 0x62, - 0xa1, 0x99, 0x4d, 0x9a, 0xb0, 0x18, 0x60, 0xf3, 0x62, 0x32, 0x85, 0xf8, 0xee, 0xaa, 0x9c, 0x78, 0x61, 0xee, 0xdb, - 0x89, 0x43, 0x0e, 0x81, 0x57, 0xb5, 0x41, 0x57, 0xb3, 0x0d, 0x47, 0x1d, 0x29, 0x27, 0x26, 0xbf, 0x9f, 0x2a, 0x08, - 0x71, 0x27, 0x8e, 0x84, 0xcb, 0x9b, 0xed, 0xc2, 0xb3, 0x0e, 0x04, 0x1d, 0x35, 0x38, 0xe5, 0x17, 0x06, 0x47, 0x63, - 0x92, 0x6e, 0xbd, 0x13, 0xa4, 0x08, 0x63, 0xb2, 0x95, 0xec, 0x5c, 0x86, 0x62, 0x1e, 0x2f, 0x40, 0x79, 0x19, 0x2f, - 0xc0, 0xd2, 0xc8, 0x18, 0xa4, 0x82, 0xfc, 0x8e, 0x7b, 0xa1, 0xb0, 0x28, 0xae, 0x10, 0xe9, 0x59, 0xfd, 0x9e, 0x16, - 0xed, 0x50, 0x20, 0x28, 0xee, 0x50, 0xe6, 0xc9, 0x59, 0x8f, 0x05, 0x12, 0x1b, 0x02, 0xc6, 0x57, 0x3a, 0x4d, 0xb5, - 0xd6, 0xbd, 0x31, 0xf3, 0xc0, 0xa7, 0xd9, 0x48, 0xc8, 0xea, 0xec, 0x02, 0x44, 0x4a, 0x3e, 0x3a, 0x3e, 0xf2, 0x8b, - 0xb8, 0xb3, 0xcc, 0x5b, 0xdb, 0xa2, 0x92, 0x9d, 0x6c, 0x01, 0xb4, 0x50, 0x47, 0xcf, 0x52, 0x72, 0x9b, 0x92, 0xd4, - 0x6e, 0x53, 0xc0, 0x4a, 0xf2, 0x17, 0x30, 0x04, 0x5f, 0x3b, 0x10, 0x4e, 0xc7, 0x0a, 0xf1, 0x9a, 0xa6, 0x88, 0x34, - 0x19, 0x96, 0x14, 0xc7, 0xb6, 0x44, 0x14, 0x54, 0x5b, 0x96, 0x1d, 0x0c, 0x13, 0x25, 0xf8, 0x63, 0xea, 0x51, 0xa2, - 0x20, 0xa0, 0x7a, 0xc8, 0x41, 0x82, 0x6d, 0x1b, 0x08, 0x0f, 0xc8, 0x23, 0x7a, 0x63, 0xfd, 0x73, 0xd6, 0x79, 0x76, - 0xa1, 0x79, 0x2e, 0xd7, 0xbb, 0xc2, 0x8c, 0x11, 0x9e, 0x64, 0x26, 0x6c, 0x80, 0x77, 0x9e, 0x19, 0xb5, 0x4d, 0xcf, - 0xc3, 0x6b, 0x7b, 0x8e, 0x11, 0xfa, 0xee, 0x18, 0x74, 0x13, 0xcc, 0xab, 0xc3, 0x66, 0xbd, 0x52, 0x90, 0x1a, 0xa6, - 0x16, 0x4d, 0xcc, 0x7a, 0xd6, 0xa0, 0x7c, 0xb7, 0xeb, 0xe9, 0xb9, 0xba, 0x7b, 0xee, 0x76, 0xbb, 0x1e, 0x76, 0xeb, - 0x63, 0xda, 0x6d, 0x15, 0x5f, 0xa9, 0x0f, 0xda, 0xe3, 0xcf, 0xdd, 0xf8, 0x73, 0x83, 0x6c, 0x52, 0x3a, 0x9a, 0x69, - 0xeb, 0x83, 0xf0, 0xc0, 0xe9, 0xa6, 0xd1, 0xa4, 0x9f, 0xb3, 0x50, 0xd2, 0x4b, 0xd1, 0xa8, 0xae, 0x76, 0x26, 0xa6, - 0xf7, 0xae, 0xff, 0xfb, 0x57, 0x01, 0x1e, 0x71, 0x6a, 0x67, 0xdf, 0xd9, 0xa0, 0xa2, 0xd1, 0x16, 0x8e, 0x14, 0xa1, - 0x07, 0x24, 0xe1, 0xae, 0x96, 0xb5, 0xb8, 0xcd, 0x0f, 0xd9, 0xfd, 0xf4, 0xe9, 0xa7, 0xd4, 0xf7, 0x42, 0x70, 0xcb, - 0x2c, 0x33, 0x07, 0x5e, 0x45, 0x71, 0x40, 0xa3, 0x2e, 0xda, 0x77, 0x95, 0x95, 0x25, 0x78, 0xbd, 0xc0, 0xbd, 0xf2, - 0x03, 0xf7, 0xe1, 0xf7, 0x2e, 0xab, 0xe6, 0x26, 0xfd, 0x90, 0xcd, 0xb3, 0xc5, 0x6e, 0x17, 0xe2, 0xdf, 0xae, 0x16, - 0x39, 0x9a, 0x3c, 0x07, 0x9d, 0x26, 0x46, 0x32, 0x62, 0xba, 0x71, 0xde, 0xe6, 0xff, 0x2c, 0x1a, 0x4e, 0x13, 0xcf, - 0x81, 0x5e, 0xcc, 0x4e, 0x41, 0x26, 0x65, 0x40, 0x0e, 0xc4, 0x4c, 0xaf, 0x19, 0x88, 0x46, 0x26, 0x22, 0xc0, 0x15, - 0xc6, 0x46, 0xa2, 0xd1, 0x09, 0x27, 0x35, 0x01, 0x0b, 0x56, 0x5b, 0xde, 0x7b, 0x4b, 0xdb, 0xaa, 0x62, 0xe3, 0x2d, - 0x69, 0x8e, 0xeb, 0xc0, 0xf9, 0x3a, 0xd8, 0x80, 0x77, 0xba, 0xec, 0x6a, 0x81, 0xdc, 0x2f, 0xaf, 0x69, 0x6f, 0x5c, - 0x27, 0x30, 0x6b, 0xdb, 0xda, 0x32, 0x7e, 0xb6, 0xf4, 0x17, 0x7a, 0x70, 0x95, 0x31, 0xd8, 0xdc, 0x58, 0x69, 0xd8, - 0x7d, 0xe3, 0xf9, 0x52, 0x40, 0x78, 0x3a, 0x9f, 0x1e, 0x7f, 0xc8, 0x3c, 0x7a, 0x0c, 0x44, 0xc7, 0x7c, 0x54, 0xba, - 0x8f, 0xec, 0xee, 0xf5, 0x03, 0x02, 0xce, 0xab, 0x76, 0x41, 0xf3, 0x72, 0x01, 0x81, 0x55, 0xbd, 0xf2, 0x0a, 0xcb, - 0x67, 0xc6, 0xec, 0x12, 0xc8, 0x50, 0x41, 0x20, 0x70, 0x77, 0xd7, 0xb9, 0x10, 0xab, 0x0e, 0x2b, 0x73, 0x9a, 0x84, - 0x9d, 0x84, 0x68, 0xde, 0x1a, 0xcc, 0x82, 0xff, 0x1d, 0x0c, 0xca, 0x41, 0x10, 0x05, 0x51, 0x10, 0x90, 0x41, 0x01, - 0xbf, 0x10, 0x77, 0x8d, 0x60, 0xcc, 0x16, 0xe8, 0xf0, 0x5b, 0xce, 0x7c, 0x46, 0xe4, 0x95, 0x1f, 0xd6, 0xd3, 0x1b, - 0x80, 0x73, 0x29, 0x73, 0x1e, 0xa3, 0xcf, 0xc9, 0x5b, 0xce, 0x32, 0x42, 0xdf, 0x7a, 0xa7, 0xf2, 0x3b, 0xde, 0x08, - 0xf6, 0xb7, 0x3f, 0x6c, 0x2f, 0x40, 0x5e, 0xd1, 0x1b, 0xd3, 0xb7, 0x9c, 0x44, 0x59, 0xc3, 0x99, 0x9a, 0x43, 0xcf, - 0x2a, 0xcb, 0x5a, 0x51, 0x43, 0x6e, 0x50, 0xcc, 0x8d, 0x2c, 0x93, 0x93, 0x69, 0xab, 0x39, 0x15, 0xb8, 0xee, 0xec, - 0x7a, 0x01, 0xc9, 0xa1, 0xd0, 0x2c, 0x9d, 0x0d, 0xe7, 0xed, 0x0e, 0xc5, 0xd6, 0x29, 0xe4, 0x35, 0x44, 0x45, 0x83, - 0x74, 0x04, 0xd4, 0xd0, 0x8a, 0xcb, 0x0a, 0x5c, 0x98, 0x4d, 0x7b, 0xb8, 0x69, 0x8f, 0x69, 0xc6, 0x7b, 0x88, 0x99, - 0xc7, 0xb1, 0x65, 0x60, 0x47, 0xe2, 0x90, 0x9e, 0x9c, 0x2f, 0xd0, 0x3e, 0xbd, 0x75, 0xb5, 0x78, 0x84, 0xb5, 0xe7, - 0xad, 0x90, 0x10, 0x20, 0x3e, 0x4d, 0xa5, 0xbb, 0x5d, 0x10, 0xc0, 0x00, 0xf7, 0xfb, 0x3d, 0xe0, 0x5a, 0x0d, 0x3b, - 0x69, 0x6e, 0xcd, 0x96, 0xd8, 0x2b, 0x0a, 0x8f, 0x81, 0x39, 0x35, 0xff, 0x19, 0x04, 0x14, 0xcf, 0xdd, 0x10, 0xec, - 0x4d, 0xd9, 0xc9, 0xb6, 0xe8, 0xf7, 0x9f, 0x15, 0xf8, 0x80, 0x72, 0x61, 0x10, 0x73, 0xeb, 0x38, 0x1e, 0x86, 0x7d, - 0x52, 0x1f, 0xe2, 0x58, 0xe4, 0x59, 0xe8, 0x08, 0x4b, 0x65, 0x08, 0x0b, 0x57, 0x8c, 0x74, 0x10, 0x07, 0x35, 0xe9, - 0x1c, 0xac, 0xca, 0x05, 0x5f, 0xee, 0xf5, 0x3e, 0x03, 0x4c, 0x7a, 0xe6, 0x0d, 0xcb, 0x1b, 0x0f, 0x10, 0xad, 0xd7, - 0xc3, 0x85, 0xe2, 0x91, 0x89, 0x06, 0x1a, 0x27, 0xbe, 0xb4, 0xec, 0xfa, 0x4c, 0xcb, 0x4a, 0x46, 0xa3, 0x51, 0x55, - 0x2b, 0xc9, 0x87, 0xfd, 0xee, 0xcf, 0x16, 0x8a, 0xa7, 0x8c, 0x53, 0x9e, 0x82, 0xe5, 0xbb, 0xa1, 0x74, 0xf3, 0x05, - 0x5d, 0x71, 0x91, 0xaa, 0x9f, 0x1e, 0xfa, 0x66, 0x83, 0xb8, 0x66, 0x4d, 0x1d, 0x8e, 0x1d, 0x7e, 0x08, 0x80, 0x69, - 0x1f, 0x66, 0x2e, 0x5d, 0xc3, 0xf4, 0x82, 0x78, 0x36, 0x2e, 0x78, 0xe8, 0xf2, 0x00, 0xf6, 0xa1, 0x39, 0x24, 0xf1, - 0x53, 0xf8, 0x39, 0x33, 0x69, 0x1d, 0x9f, 0xe1, 0x6c, 0x46, 0xa5, 0xba, 0x11, 0xb4, 0x5f, 0x43, 0x22, 0x31, 0x48, - 0xcf, 0x0d, 0x86, 0xa2, 0x75, 0xb7, 0x81, 0x2b, 0xbf, 0xa5, 0x77, 0x3e, 0x0d, 0x02, 0xac, 0x6f, 0x2c, 0x06, 0x00, - 0x54, 0xf1, 0x07, 0xaa, 0xae, 0xcc, 0x15, 0xc5, 0x34, 0x4c, 0x25, 0xda, 0x3b, 0x8e, 0xeb, 0xa8, 0x71, 0x1d, 0x16, - 0xac, 0xb4, 0xb6, 0xcd, 0xee, 0x2d, 0x2d, 0x6c, 0x09, 0xa8, 0x16, 0xc4, 0x9d, 0x00, 0x3e, 0x34, 0x52, 0x1d, 0x08, - 0xb2, 0xfb, 0xe0, 0x00, 0x80, 0x37, 0x3c, 0x0f, 0x43, 0xf8, 0x03, 0x0b, 0x07, 0x96, 0xa5, 0xea, 0xe7, 0x72, 0x1a, - 0xc3, 0xb9, 0x9b, 0xab, 0x1d, 0x3e, 0x5b, 0x82, 0x62, 0x53, 0xcd, 0xa9, 0xb9, 0x7c, 0xe5, 0x8d, 0xfd, 0x1e, 0x13, - 0xcc, 0x63, 0x66, 0x1b, 0x7e, 0xeb, 0xe9, 0xb6, 0xbe, 0xc1, 0x6e, 0xe0, 0xa4, 0xbd, 0x70, 0xda, 0x8b, 0xed, 0xd2, - 0x40, 0xfe, 0xd5, 0x0d, 0x21, 0xc2, 0x47, 0x4d, 0x2c, 0xb2, 0x86, 0x4c, 0xc7, 0x62, 0x85, 0xa8, 0x36, 0x15, 0x4f, - 0xb5, 0x81, 0x40, 0x39, 0x55, 0x17, 0xa6, 0x56, 0x2a, 0x13, 0x06, 0x71, 0xa7, 0x84, 0x45, 0x95, 0x01, 0x86, 0x41, - 0x85, 0x14, 0xd7, 0xd6, 0xf3, 0x03, 0x2e, 0xdf, 0xcc, 0xb4, 0xd9, 0x7e, 0xfa, 0x22, 0x8f, 0x2f, 0x77, 0xbb, 0xb0, - 0xfb, 0x05, 0x98, 0xa3, 0x96, 0x4a, 0xc3, 0x08, 0x4e, 0x20, 0x4a, 0x72, 0x7d, 0x47, 0xce, 0x89, 0xe3, 0xe4, 0xda, - 0xcd, 0x9b, 0xed, 0xa5, 0x18, 0x81, 0x05, 0x9c, 0xb8, 0x48, 0x07, 0x5a, 0x2a, 0x49, 0xed, 0x29, 0xe0, 0x6d, 0x7a, - 0x47, 0xa9, 0xf0, 0x6a, 0xa1, 0x49, 0x48, 0xe5, 0xee, 0x25, 0x76, 0xd4, 0x80, 0x73, 0x52, 0x77, 0x10, 0x70, 0xda, - 0xd3, 0x8d, 0xb5, 0x8a, 0x64, 0x93, 0xe0, 0xbd, 0xd2, 0x43, 0x97, 0x68, 0xa7, 0x76, 0xb7, 0xad, 0xca, 0x16, 0x0a, - 0xe6, 0x41, 0xce, 0x12, 0x75, 0x3c, 0xa0, 0xd0, 0x45, 0x1d, 0x0d, 0xf9, 0x82, 0x14, 0x7a, 0xe5, 0x68, 0x55, 0xf3, - 0xbe, 0x64, 0xa0, 0x54, 0xab, 0x20, 0xaf, 0x89, 0x75, 0x5f, 0xcb, 0x1a, 0x8b, 0x2b, 0x27, 0xa4, 0xb0, 0x09, 0x5f, - 0x5b, 0x8a, 0x85, 0x59, 0xec, 0x8d, 0xa9, 0x2f, 0x5c, 0x22, 0xb4, 0xdd, 0x6d, 0x88, 0xd1, 0x06, 0xeb, 0x66, 0xb7, - 0xfb, 0x58, 0x84, 0xf3, 0x6c, 0x41, 0xe5, 0x28, 0x4b, 0x11, 0x52, 0xcd, 0x78, 0x2c, 0xdb, 0x2e, 0x98, 0x89, 0xa1, - 0xae, 0x3d, 0x5e, 0x92, 0x29, 0xd6, 0x26, 0xc9, 0x51, 0x7c, 0x2e, 0x0b, 0xb5, 0xd6, 0x08, 0xc1, 0xc3, 0xfd, 0xd7, - 0x14, 0x62, 0xda, 0x99, 0x75, 0xf7, 0x72, 0xef, 0x86, 0xf8, 0x2b, 0x04, 0x56, 0x28, 0xd9, 0xc7, 0x62, 0x74, 0x9e, - 0x41, 0x30, 0x58, 0x90, 0x35, 0x63, 0x94, 0x60, 0xb5, 0x0e, 0x9a, 0x2d, 0xb7, 0xf7, 0x62, 0x4b, 0x14, 0x20, 0xce, - 0xb3, 0xd0, 0x8c, 0x67, 0xe5, 0x2c, 0x67, 0x32, 0x8a, 0x0d, 0x89, 0x4a, 0x2f, 0x4a, 0xbc, 0xcf, 0xd3, 0x98, 0x1e, - 0xba, 0x35, 0x08, 0xae, 0xab, 0x7b, 0x1b, 0x69, 0xbe, 0x20, 0x44, 0x4d, 0x80, 0x84, 0x8d, 0x6a, 0x4e, 0xad, 0x2b, - 0x71, 0x3f, 0xab, 0xbc, 0xd1, 0x07, 0xf1, 0x95, 0x00, 0x1e, 0xd6, 0xdb, 0xde, 0xe7, 0xc2, 0x63, 0x6d, 0xf0, 0xed, - 0x6e, 0x77, 0x25, 0xe6, 0x41, 0xe0, 0x31, 0x9a, 0xbf, 0x28, 0x89, 0x79, 0x6f, 0x4c, 0x61, 0xc5, 0xfb, 0x2e, 0x7e, - 0xdd, 0xa4, 0xd6, 0x5a, 0xe4, 0xee, 0x71, 0x7d, 0xc0, 0xf3, 0x94, 0x38, 0xda, 0x51, 0x39, 0x95, 0xd6, 0x76, 0x00, - 0xbb, 0x22, 0x30, 0x50, 0xf6, 0x6f, 0x29, 0xdb, 0x82, 0x79, 0x22, 0x58, 0x1f, 0xa1, 0xdf, 0x96, 0xd2, 0x9f, 0x8c, - 0xd1, 0xb8, 0x47, 0xae, 0xab, 0xe8, 0x88, 0xeb, 0x68, 0xf6, 0x3c, 0xfa, 0xdb, 0x93, 0x31, 0x2d, 0x62, 0x91, 0xca, - 0x2b, 0x50, 0x41, 0x80, 0x32, 0x04, 0x1d, 0x21, 0x34, 0x35, 0x00, 0x0d, 0x82, 0x1b, 0x80, 0x7f, 0x77, 0x3a, 0x51, - 0xda, 0x9a, 0x7c, 0x8c, 0x56, 0x55, 0xe4, 0xac, 0x0d, 0xed, 0xa6, 0x92, 0x43, 0xf2, 0xb0, 0x04, 0x7c, 0x4b, 0x6c, - 0x96, 0xb2, 0x41, 0x51, 0x9b, 0x4d, 0xbd, 0x56, 0xec, 0xc8, 0x6d, 0xa3, 0x68, 0xb3, 0x16, 0xb5, 0xdd, 0xc8, 0x7c, - 0x31, 0xbd, 0xb5, 0xc2, 0xc0, 0xa9, 0x69, 0xcd, 0xcd, 0x1e, 0x94, 0x9c, 0xad, 0xcf, 0xe4, 0x26, 0x40, 0x1c, 0x60, - 0xb8, 0x6e, 0xe7, 0x37, 0x0b, 0x42, 0x6f, 0xd9, 0xad, 0x15, 0xab, 0xde, 0x58, 0xb9, 0x88, 0x49, 0xbb, 0x19, 0x4c, - 0xe0, 0x32, 0xce, 0x0a, 0xfb, 0x42, 0xab, 0x1b, 0x8a, 0x8e, 0xb6, 0x49, 0xfb, 0x79, 0x47, 0xbb, 0xe1, 0x82, 0x6f, - 0xc5, 0x3a, 0xce, 0x2d, 0x6b, 0xaa, 0xd0, 0xb4, 0x03, 0xbd, 0x1d, 0x02, 0x9a, 0xb3, 0x31, 0x5d, 0xd2, 0x14, 0x2f, - 0xd0, 0x74, 0x0d, 0x66, 0x3a, 0x17, 0xd0, 0xd7, 0x6e, 0x1f, 0xed, 0x0b, 0xd5, 0x13, 0xe1, 0x2d, 0x51, 0xf0, 0x6d, - 0x49, 0xc1, 0x4b, 0x2d, 0xe7, 0xb1, 0x99, 0x43, 0xc0, 0xa7, 0x51, 0x25, 0x7a, 0x27, 0xc5, 0x25, 0x68, 0x33, 0xe1, - 0x08, 0x34, 0x55, 0x23, 0xb6, 0x72, 0x80, 0xdb, 0x8b, 0xa7, 0x01, 0xa1, 0x20, 0xd5, 0x5d, 0xdb, 0x15, 0x79, 0xcb, - 0x4e, 0xb6, 0xb7, 0x60, 0x26, 0x5c, 0xad, 0xcb, 0xd6, 0x57, 0x36, 0xd9, 0x7d, 0x5c, 0x13, 0x6c, 0xbb, 0x87, 0x1a, - 0x1b, 0xde, 0xd2, 0x1b, 0xb2, 0xbd, 0xe9, 0xf7, 0x43, 0xe8, 0x0f, 0xa1, 0xba, 0x43, 0xb7, 0x9d, 0x1d, 0xba, 0xf5, - 0xda, 0x79, 0x6e, 0xf5, 0x7c, 0xca, 0x3b, 0xe4, 0x23, 0x9a, 0xac, 0xd1, 0x55, 0xbc, 0x81, 0x4d, 0x1d, 0x55, 0x54, - 0x55, 0x1e, 0x25, 0x14, 0x54, 0xe2, 0x19, 0x2f, 0x3f, 0x70, 0x8c, 0xf5, 0xaa, 0x9f, 0xde, 0x69, 0x5e, 0x6d, 0x6d, - 0xd6, 0x66, 0xb9, 0x3e, 0x07, 0x0b, 0x89, 0x73, 0x1e, 0x5d, 0x69, 0x5a, 0x72, 0xe9, 0x83, 0xaa, 0xe2, 0xa8, 0x04, - 0x17, 0x71, 0x96, 0x83, 0x1a, 0xf7, 0xa2, 0xd9, 0xff, 0x50, 0xdb, 0x8e, 0x2d, 0x1b, 0x67, 0xee, 0x75, 0x48, 0xb6, - 0xff, 0x63, 0x03, 0xf5, 0x34, 0xc4, 0x08, 0xb1, 0x66, 0x41, 0x3f, 0x60, 0x10, 0x2b, 0x34, 0x28, 0xd7, 0x49, 0xc2, - 0xcb, 0x32, 0x30, 0x4a, 0xad, 0x35, 0x5b, 0x9b, 0xf3, 0xec, 0x1d, 0x3b, 0x79, 0xd7, 0x63, 0xec, 0x96, 0xd0, 0x44, - 0xeb, 0x84, 0x4c, 0x8d, 0x91, 0xa7, 0x05, 0xd2, 0x1d, 0x8a, 0xb2, 0x8b, 0xf0, 0x01, 0x0a, 0x59, 0xda, 0xfb, 0xdc, - 0x9c, 0xc8, 0xea, 0x1b, 0x6d, 0x84, 0x12, 0xa9, 0x44, 0x90, 0x8d, 0xdf, 0x20, 0x80, 0x31, 0x34, 0x3b, 0x20, 0xdb, - 0x25, 0x7b, 0x4d, 0xcf, 0xac, 0x49, 0x10, 0xbc, 0x7e, 0xa0, 0x12, 0xcd, 0x28, 0x2b, 0xa2, 0xab, 0x8c, 0x7e, 0x36, - 0x21, 0x89, 0xce, 0x42, 0xe2, 0xe7, 0x86, 0xa5, 0x75, 0x1d, 0xa2, 0x98, 0xd9, 0x6c, 0x78, 0xad, 0x88, 0x6a, 0x6c, - 0x2b, 0xe3, 0x63, 0x7e, 0x6b, 0xd3, 0xc8, 0x14, 0xfa, 0x3a, 0x9c, 0xf4, 0xfb, 0xf0, 0x57, 0xd3, 0x0f, 0xbc, 0xa5, - 0xe0, 0x2f, 0xf6, 0x8e, 0xd4, 0x09, 0x0b, 0x00, 0x9e, 0x31, 0xe7, 0x55, 0x73, 0x02, 0xdf, 0xb1, 0x93, 0xed, 0xbb, - 0xf0, 0x75, 0x63, 0xe6, 0x36, 0x21, 0x5e, 0xaa, 0x92, 0x9e, 0x37, 0x4f, 0x66, 0x20, 0x56, 0x56, 0x6b, 0x7e, 0xcb, - 0xac, 0x3e, 0x01, 0x88, 0xd4, 0xad, 0x75, 0xb0, 0xc5, 0x8f, 0x4d, 0x97, 0xc9, 0x36, 0x65, 0x6d, 0x26, 0x4a, 0xa9, - 0x48, 0x9a, 0x8b, 0x00, 0xfa, 0x0d, 0xc3, 0x51, 0x03, 0xdc, 0xb9, 0x1e, 0x7b, 0x33, 0x34, 0xde, 0x98, 0x1a, 0x7a, - 0xb6, 0xd5, 0xcb, 0xdb, 0x51, 0x08, 0x33, 0x16, 0xd1, 0xad, 0x3b, 0x16, 0xc3, 0xd7, 0xf4, 0x01, 0x54, 0xf8, 0x34, - 0xc4, 0xe8, 0xc2, 0xa4, 0xae, 0xa7, 0x6b, 0xb5, 0x95, 0x6e, 0x08, 0xcd, 0x31, 0xaa, 0x91, 0xd7, 0xb6, 0x0d, 0x35, - 0x42, 0x7b, 0x42, 0x79, 0x78, 0x4b, 0x2b, 0x7a, 0x63, 0x59, 0x04, 0x27, 0x3f, 0xf6, 0xf2, 0x13, 0x7a, 0xee, 0x06, - 0xed, 0xa7, 0xa2, 0xad, 0x01, 0xfc, 0x0d, 0xf5, 0xc3, 0x59, 0x3d, 0xb5, 0x52, 0x0e, 0x4f, 0xe1, 0x4b, 0xb6, 0x20, - 0x57, 0xd0, 0x8b, 0x35, 0x66, 0x27, 0x31, 0xe8, 0xa0, 0xf6, 0x76, 0x87, 0x37, 0x29, 0x65, 0x88, 0xd6, 0x88, 0x0e, - 0xf2, 0xea, 0xdf, 0xa0, 0xe9, 0x83, 0xb4, 0x30, 0xa5, 0x6b, 0x14, 0xf0, 0x80, 0xbe, 0xa9, 0xdf, 0xcf, 0xf1, 0xb9, - 0xf6, 0x2c, 0xd3, 0x94, 0x05, 0x32, 0xa1, 0x4b, 0x57, 0x1a, 0x88, 0xca, 0xb7, 0x8e, 0x55, 0x00, 0x56, 0x24, 0x81, - 0x46, 0x24, 0x60, 0xb9, 0xe4, 0x89, 0xcb, 0xb6, 0x68, 0x50, 0x13, 0x95, 0x14, 0xb2, 0x44, 0x12, 0xf8, 0x61, 0x04, - 0x65, 0x8a, 0x62, 0x10, 0xf7, 0xea, 0xe5, 0x15, 0xd7, 0xd4, 0x80, 0x35, 0x45, 0x30, 0xc1, 0x3a, 0x9d, 0x02, 0xb1, - 0x15, 0xeb, 0x15, 0x78, 0xa2, 0xba, 0x8b, 0x24, 0xb2, 0x04, 0x68, 0xa0, 0xe7, 0x4b, 0xa7, 0xdd, 0xf2, 0xf6, 0x44, - 0x4b, 0x15, 0x9b, 0x7b, 0x2f, 0x16, 0x96, 0x7b, 0xac, 0xfc, 0xed, 0x40, 0x7b, 0x61, 0xb5, 0x27, 0xa2, 0x06, 0xab, - 0xc3, 0xb6, 0x9d, 0x1f, 0x4a, 0x43, 0x75, 0xaf, 0x1c, 0x13, 0x50, 0xd1, 0x55, 0x5c, 0x2d, 0xa3, 0x6c, 0x04, 0x7f, - 0x76, 0xbb, 0xe0, 0x30, 0x00, 0x8b, 0xd0, 0x5f, 0xde, 0xff, 0x14, 0x61, 0xb8, 0xaa, 0x5f, 0xde, 0xff, 0xb4, 0xdb, - 0x3d, 0x19, 0x8f, 0x0d, 0x57, 0xe0, 0xd4, 0x3a, 0xc0, 0x1f, 0x18, 0xb6, 0xc1, 0x2e, 0xd9, 0xdd, 0xee, 0x09, 0x70, - 0x10, 0x8a, 0x6d, 0x30, 0xbb, 0x58, 0x39, 0xb6, 0x29, 0x56, 0x43, 0xef, 0x48, 0xc0, 0xee, 0xdb, 0x63, 0x29, 0xf6, - 0xa9, 0x8f, 0x0a, 0x49, 0xa9, 0x17, 0xfd, 0xf3, 0x4e, 0x81, 0x25, 0x05, 0x53, 0xde, 0x60, 0x59, 0x55, 0xab, 0x32, - 0x3a, 0x3c, 0x8c, 0x57, 0xd9, 0xa8, 0xcc, 0x60, 0x9b, 0x97, 0xd7, 0x97, 0x00, 0x30, 0x11, 0xd0, 0xc6, 0xbb, 0xb5, - 0xc8, 0xcc, 0x8b, 0x05, 0x5d, 0x66, 0xb8, 0x26, 0xc1, 0xec, 0x20, 0xe7, 0x56, 0x37, 0x39, 0x25, 0xf6, 0x01, 0x6c, - 0x30, 0x77, 0xbb, 0x06, 0xbf, 0x70, 0x32, 0x7a, 0x32, 0x5b, 0x66, 0xda, 0xc0, 0x95, 0x9b, 0xfd, 0x4f, 0x22, 0x2f, - 0x0d, 0x15, 0x9f, 0x64, 0xfa, 0x3c, 0x03, 0x3e, 0x8f, 0xfd, 0x29, 0x42, 0x9f, 0xe5, 0x6a, 0xb4, 0x06, 0xd8, 0xd8, - 0xec, 0x62, 0x33, 0x4a, 0x39, 0x44, 0xe8, 0x08, 0xac, 0xba, 0x66, 0x99, 0x11, 0xdf, 0xa6, 0xe2, 0xb6, 0xa5, 0x0a, - 0xfb, 0x53, 0x78, 0xce, 0x3b, 0xdc, 0x38, 0x0e, 0xf5, 0x26, 0x51, 0xf8, 0x1c, 0x85, 0xa8, 0x1c, 0x8d, 0x0b, 0x9d, - 0x7c, 0x2d, 0xf3, 0x98, 0x50, 0xcc, 0xe1, 0xde, 0xfd, 0x95, 0x3a, 0x73, 0x19, 0x5f, 0xb8, 0xf7, 0xdc, 0x97, 0x99, - 0x5c, 0x4b, 0x00, 0x89, 0x52, 0xb5, 0xff, 0xfe, 0x05, 0xa9, 0xf1, 0xbf, 0x52, 0xad, 0x01, 0xe8, 0xfd, 0x0e, 0x35, - 0x39, 0x82, 0x80, 0xad, 0x98, 0xfa, 0xd1, 0x05, 0xac, 0x64, 0xfe, 0x27, 0xd4, 0xed, 0x08, 0xb6, 0x55, 0xf1, 0x84, - 0xa2, 0x8a, 0x16, 0x3c, 0x5d, 0x8b, 0x34, 0x16, 0xc9, 0x26, 0xe2, 0xf5, 0x14, 0x4b, 0x62, 0x36, 0x62, 0xd8, 0xef, - 0xcd, 0x2e, 0xbc, 0x2f, 0x1a, 0x26, 0xf1, 0xb4, 0xf4, 0xb7, 0x95, 0xb7, 0x99, 0x2c, 0xe3, 0x8c, 0x4c, 0xb9, 0x42, - 0x30, 0xb7, 0xfa, 0x1e, 0x73, 0x82, 0x3f, 0x3e, 0x7a, 0x4c, 0xe8, 0xb5, 0x9c, 0x96, 0x08, 0xd2, 0x27, 0x52, 0xeb, - 0xba, 0x8a, 0xfd, 0x9a, 0x42, 0x54, 0x0b, 0xc1, 0x20, 0x94, 0xa9, 0x69, 0x9f, 0xe2, 0xfb, 0x6c, 0xd9, 0x7f, 0x9a, - 0xb2, 0x25, 0xd9, 0x0a, 0xe8, 0x98, 0x74, 0xde, 0xaf, 0xde, 0x9e, 0x9d, 0x79, 0xbf, 0x41, 0x13, 0x0e, 0xaa, 0x1b, - 0x68, 0x57, 0x41, 0xa6, 0x31, 0x8a, 0xcd, 0x62, 0xac, 0xdd, 0x9a, 0x88, 0x20, 0x08, 0x77, 0x39, 0x0b, 0xdb, 0xed, - 0x84, 0x78, 0x1b, 0x48, 0xa0, 0xc0, 0xb5, 0x8d, 0x72, 0x12, 0x12, 0x75, 0x21, 0x33, 0xc7, 0x84, 0x64, 0x81, 0x5e, - 0x63, 0x47, 0x01, 0x3d, 0xe5, 0xf6, 0x29, 0xa0, 0x2f, 0x0a, 0x76, 0xca, 0x07, 0xc1, 0x10, 0xe3, 0xcd, 0x06, 0xf4, - 0x93, 0x54, 0x8f, 0xe0, 0x31, 0x0d, 0x2c, 0x17, 0x7d, 0x53, 0x30, 0x84, 0x59, 0xfa, 0x67, 0xca, 0x26, 0xdf, 0xfd, - 0xdd, 0xcd, 0xef, 0x99, 0x16, 0xb3, 0x83, 0x50, 0xdc, 0x5e, 0x4f, 0x80, 0xf8, 0x55, 0xfc, 0x0a, 0xac, 0xcd, 0xb5, - 0xc4, 0xdb, 0x93, 0x3c, 0x08, 0x5f, 0x8e, 0x6e, 0x3f, 0x29, 0xcd, 0x27, 0x10, 0xb4, 0xc7, 0x49, 0xca, 0xdd, 0x77, - 0x1f, 0xa4, 0xab, 0x08, 0x46, 0x0b, 0x10, 0xfc, 0xee, 0xac, 0x64, 0xd3, 0x14, 0xfe, 0x63, 0x9d, 0x2f, 0x30, 0x96, - 0x8a, 0xfc, 0x80, 0xd3, 0xdf, 0x04, 0x07, 0xf7, 0x6f, 0x65, 0xd6, 0x90, 0xe8, 0x4c, 0x7d, 0x04, 0xf4, 0x7f, 0xac, - 0xc7, 0xef, 0x14, 0x25, 0x7d, 0x49, 0x9c, 0x23, 0x7c, 0x13, 0x2f, 0xd1, 0x74, 0xb1, 0x37, 0xae, 0xe9, 0xe7, 0xc2, - 0xbc, 0xd0, 0x0a, 0x0e, 0xfb, 0xd6, 0x28, 0x3c, 0xf0, 0xcc, 0xfb, 0x55, 0x34, 0x04, 0xdd, 0x3f, 0xe2, 0xde, 0xf8, - 0x55, 0xb0, 0x0c, 0x6f, 0xca, 0x59, 0x66, 0xee, 0x70, 0x37, 0x99, 0x48, 0xe5, 0x0d, 0x63, 0xc1, 0x5a, 0x28, 0x73, - 0xde, 0x34, 0x98, 0x6d, 0xeb, 0x48, 0x25, 0xbb, 0xef, 0xff, 0x6c, 0x9c, 0xb0, 0xd9, 0x20, 0xf8, 0x50, 0xc9, 0x22, - 0xbe, 0xe4, 0xc1, 0x54, 0xab, 0x28, 0x32, 0xb0, 0x2b, 0x04, 0xa4, 0x1c, 0xa7, 0xbd, 0x83, 0x27, 0x4b, 0xcd, 0x4c, - 0xc8, 0x6f, 0xab, 0xb3, 0x80, 0xb7, 0x66, 0x34, 0x4f, 0x2b, 0xd8, 0x65, 0xbe, 0x92, 0xe2, 0x87, 0x96, 0x24, 0x1b, - 0xeb, 0x6f, 0xc8, 0xb0, 0xad, 0x7c, 0xe6, 0x0c, 0x30, 0x77, 0x3e, 0x49, 0x15, 0xf4, 0xaf, 0xc7, 0xd8, 0x8d, 0x44, - 0x22, 0x20, 0x9c, 0xc5, 0xc4, 0xad, 0x30, 0xe1, 0x30, 0x5d, 0xa0, 0xa0, 0x18, 0x03, 0x05, 0x7d, 0x90, 0x21, 0xa7, - 0xa7, 0x7c, 0x90, 0x34, 0x66, 0xeb, 0x07, 0x55, 0x22, 0xbd, 0x91, 0x84, 0x6e, 0xe0, 0xf7, 0xb8, 0xc5, 0x03, 0x35, - 0x82, 0x75, 0xba, 0x9b, 0xd3, 0xe1, 0x9b, 0x82, 0x0c, 0xff, 0x09, 0xde, 0x6e, 0xb1, 0xbd, 0x2c, 0x27, 0xb0, 0xb8, - 0x63, 0xaf, 0x78, 0x9a, 0xab, 0x16, 0x27, 0xc4, 0x23, 0x16, 0xb9, 0x4f, 0x2c, 0x60, 0x44, 0x0d, 0xa3, 0xf1, 0x8f, - 0x0f, 0x6f, 0xdf, 0x68, 0x0c, 0xab, 0xdc, 0xff, 0x00, 0x46, 0x54, 0x4b, 0xdb, 0xed, 0x80, 0x2f, 0x47, 0x68, 0xc0, - 0x9e, 0xba, 0xc1, 0xee, 0xf7, 0x4d, 0xda, 0x49, 0xe9, 0x65, 0x73, 0x62, 0xd0, 0x3d, 0xa5, 0xcd, 0x52, 0x19, 0x18, - 0x77, 0x15, 0x8e, 0xe6, 0xc4, 0x46, 0xac, 0xea, 0x7d, 0x18, 0x2e, 0x69, 0x6c, 0x65, 0xe5, 0x76, 0x37, 0xe1, 0xc8, - 0x26, 0xc0, 0xf5, 0x29, 0x68, 0xaf, 0xe6, 0x1c, 0xb4, 0xa0, 0x44, 0x81, 0x23, 0xda, 0xed, 0x42, 0x88, 0x48, 0x52, - 0x0c, 0x27, 0xb3, 0xb0, 0x18, 0x0e, 0xd5, 0xc0, 0x17, 0x84, 0x44, 0x9f, 0x8b, 0x79, 0xb6, 0x50, 0x08, 0x46, 0xfe, - 0x4e, 0xfa, 0xb5, 0x50, 0x9c, 0x72, 0xef, 0x57, 0x41, 0xb6, 0x3f, 0xa6, 0x18, 0x83, 0xd1, 0x69, 0x36, 0x33, 0x90, - 0xb0, 0x9e, 0x56, 0x44, 0xad, 0x23, 0x3b, 0x1b, 0xa0, 0x8a, 0x45, 0xd3, 0x60, 0x50, 0xb7, 0x78, 0x62, 0x3d, 0xa3, - 0xf7, 0xa0, 0x12, 0x44, 0xb5, 0x60, 0x37, 0x86, 0x6b, 0xed, 0xb3, 0x08, 0x25, 0xe5, 0xa4, 0xc9, 0xcc, 0x58, 0xd1, - 0x60, 0x01, 0x42, 0xd2, 0xb8, 0xac, 0x5e, 0xcb, 0x34, 0xbb, 0xc8, 0x00, 0x41, 0xc2, 0xf9, 0x13, 0xca, 0xc6, 0x9b, - 0xa7, 0x6a, 0x5e, 0xba, 0x12, 0x67, 0x16, 0xf6, 0xa4, 0xeb, 0x2d, 0x2d, 0x48, 0x54, 0x00, 0x8d, 0xf2, 0xb5, 0x3c, - 0x3f, 0xef, 0x59, 0x85, 0xec, 0x7f, 0x38, 0x55, 0xb6, 0x43, 0xfc, 0x84, 0x55, 0xc4, 0x3b, 0xad, 0x2b, 0x25, 0xd2, - 0xe8, 0x68, 0x1b, 0x10, 0xc3, 0x96, 0x7d, 0x8b, 0x1a, 0x3e, 0x08, 0xbb, 0xe8, 0x24, 0x3f, 0xe8, 0x29, 0x1e, 0x5b, - 0x03, 0x49, 0x5f, 0x8b, 0xe0, 0x6b, 0x74, 0xa4, 0x13, 0x65, 0x1a, 0x89, 0x29, 0x24, 0xfa, 0xf5, 0x42, 0x6b, 0x2c, - 0xa3, 0xec, 0x2b, 0xf2, 0x7f, 0xd7, 0xdd, 0xfb, 0x55, 0xec, 0x76, 0x30, 0xc9, 0x9e, 0x07, 0x1a, 0x6c, 0x6a, 0xd4, - 0x0a, 0xe1, 0xec, 0x9c, 0x56, 0xa8, 0x1d, 0xeb, 0x85, 0x25, 0x90, 0x07, 0xb0, 0x15, 0x69, 0x50, 0x06, 0xc9, 0x3e, - 0x17, 0x73, 0xb1, 0x70, 0xa2, 0x1c, 0xa9, 0xf0, 0xcf, 0xe4, 0x28, 0xe5, 0x70, 0x15, 0x0b, 0x0b, 0x86, 0xfc, 0xea, - 0xe8, 0xa2, 0x90, 0x57, 0x20, 0x29, 0x31, 0x0c, 0x95, 0xe5, 0x75, 0x71, 0xd5, 0x96, 0x84, 0xf6, 0x36, 0x00, 0x4a, - 0x53, 0x80, 0xe0, 0xa5, 0x51, 0x43, 0xcc, 0xb6, 0x6a, 0x77, 0x45, 0x77, 0x92, 0x03, 0xea, 0x74, 0xd7, 0x6e, 0xbd, - 0x29, 0x5b, 0x75, 0x2b, 0x2e, 0xfc, 0x01, 0x4a, 0x3f, 0xe5, 0x83, 0xc2, 0xa7, 0x12, 0xb8, 0xf1, 0xd5, 0x26, 0xcb, - 0x2e, 0x36, 0xb8, 0xf4, 0xab, 0xc6, 0xf8, 0xf5, 0xfb, 0x3d, 0xb5, 0x10, 0x1a, 0xa9, 0xc0, 0x7c, 0xfb, 0xcc, 0x54, - 0x65, 0x34, 0xa5, 0xf6, 0x12, 0x5c, 0x39, 0xfb, 0x11, 0x54, 0xc4, 0x75, 0x45, 0x6a, 0x53, 0x03, 0x74, 0xe0, 0x65, - 0x85, 0x5b, 0x59, 0x80, 0xc7, 0x4e, 0x40, 0x76, 0x3b, 0x1e, 0x06, 0xfa, 0xd0, 0x09, 0xfc, 0x2d, 0xf9, 0x1a, 0x99, - 0x35, 0xfb, 0xf8, 0x0f, 0x2d, 0xf8, 0xc7, 0x16, 0xfc, 0x84, 0xe2, 0x4e, 0x2b, 0xf3, 0x6f, 0xa5, 0x75, 0x8b, 0xfb, - 0xf7, 0x32, 0x4d, 0x28, 0x2a, 0x13, 0x6a, 0xbf, 0xd2, 0x6a, 0x6d, 0xd4, 0x18, 0x98, 0xfd, 0xa3, 0x84, 0x0f, 0x66, - 0x8d, 0x27, 0xd6, 0x78, 0x32, 0x9c, 0x6e, 0xa5, 0x61, 0x19, 0x50, 0xe8, 0xe7, 0x65, 0xae, 0xa8, 0x7e, 0xfe, 0x79, - 0xcd, 0xd7, 0xbc, 0xd9, 0x62, 0x9b, 0x74, 0x4f, 0x83, 0xbd, 0x3c, 0x9a, 0x52, 0x38, 0x89, 0x3a, 0x37, 0x12, 0x75, - 0x51, 0xb3, 0x0c, 0xd5, 0x09, 0x5e, 0xcd, 0x53, 0x3d, 0xec, 0xcd, 0x44, 0xb4, 0x56, 0x52, 0x96, 0x18, 0xb0, 0xd6, - 0x91, 0x87, 0xe4, 0x6e, 0xad, 0xe3, 0x4e, 0x43, 0x5d, 0x9a, 0x42, 0x4d, 0xb0, 0xc2, 0x05, 0x38, 0x82, 0xde, 0x17, - 0x21, 0x87, 0x6b, 0xaa, 0xd2, 0x2f, 0x68, 0x4a, 0x9e, 0x78, 0x8a, 0x5a, 0xad, 0x48, 0xb7, 0x1f, 0xe5, 0xd8, 0x0d, - 0xdf, 0x38, 0x21, 0x27, 0x46, 0xe8, 0xef, 0x8e, 0xa5, 0x9c, 0xa1, 0xc5, 0x83, 0x3a, 0xc1, 0x7a, 0x79, 0x4b, 0x81, - 0x62, 0x8e, 0x2e, 0xab, 0xae, 0x79, 0x85, 0xb6, 0x2f, 0xcb, 0x7e, 0x3f, 0xb7, 0xf5, 0xa4, 0xec, 0x64, 0xbb, 0x34, - 0xfb, 0x10, 0x15, 0x53, 0xb8, 0xeb, 0x13, 0xcd, 0x5f, 0x85, 0xfa, 0xaa, 0x2d, 0x73, 0x3e, 0xe2, 0x88, 0x13, 0x92, - 0x93, 0xfa, 0x1f, 0x6a, 0xea, 0x95, 0xb8, 0x5f, 0x55, 0xf2, 0x52, 0x18, 0x2b, 0x46, 0x4b, 0x0c, 0x51, 0xa4, 0xdd, - 0x1b, 0xd3, 0x57, 0x05, 0xc0, 0x5f, 0x09, 0xf6, 0x67, 0x1a, 0x6a, 0xe5, 0xb7, 0x68, 0x0b, 0xf8, 0xb7, 0x8a, 0x1b, - 0xb0, 0x0a, 0x0c, 0x30, 0x9a, 0x6c, 0xcf, 0x69, 0x02, 0x07, 0x9c, 0xd0, 0x2a, 0x0a, 0x2a, 0xcc, 0xd0, 0x50, 0x5b, - 0x18, 0x7d, 0x8d, 0x32, 0x6e, 0x95, 0xd9, 0xbb, 0x31, 0x76, 0x5a, 0xe0, 0x35, 0xfc, 0x1b, 0xbd, 0x50, 0xcc, 0x46, - 0x1d, 0xa4, 0x47, 0x27, 0x31, 0xfd, 0x71, 0x0b, 0x27, 0x37, 0x0b, 0x67, 0x59, 0xb3, 0x04, 0xba, 0x03, 0x17, 0xc4, - 0xb8, 0xdf, 0xcf, 0xe1, 0xc8, 0x34, 0x23, 0x5f, 0xb0, 0x9c, 0xc6, 0x6c, 0x49, 0xb5, 0xe7, 0xe1, 0x65, 0x15, 0xe6, - 0x74, 0x69, 0x65, 0xbc, 0x29, 0x03, 0x95, 0xd1, 0x6e, 0x17, 0xc2, 0x9f, 0x6e, 0x6b, 0x97, 0x74, 0xbe, 0x84, 0x0c, - 0xf0, 0x07, 0x24, 0xa2, 0x88, 0x05, 0xfe, 0x1f, 0x35, 0x4e, 0xe9, 0x89, 0xd2, 0x9a, 0x25, 0x10, 0x3c, 0x4e, 0xd5, - 0x4f, 0x2f, 0xd8, 0xba, 0xb1, 0x14, 0x76, 0xbb, 0xb0, 0x99, 0xc0, 0x34, 0xe7, 0x4a, 0xa6, 0x17, 0xa8, 0x93, 0x02, - 0x2a, 0x16, 0x5e, 0xe0, 0xf2, 0x4b, 0x09, 0x85, 0xe6, 0xce, 0x97, 0x0b, 0xa3, 0xc4, 0x84, 0x56, 0xc9, 0xaf, 0x1f, - 0x2a, 0xf3, 0xb5, 0xf1, 0x10, 0xac, 0xd6, 0x61, 0x62, 0x8a, 0x44, 0x85, 0xe8, 0xec, 0x25, 0xc8, 0x72, 0x04, 0xe0, - 0x7a, 0xbe, 0x96, 0x35, 0xe5, 0x6b, 0x88, 0x0b, 0x0f, 0x0d, 0x7a, 0x57, 0xc8, 0xab, 0xac, 0xe4, 0x21, 0xde, 0x13, - 0x3c, 0xcd, 0xe8, 0xdd, 0x06, 0x1f, 0xda, 0xda, 0xa3, 0x27, 0xc8, 0xd6, 0x53, 0xee, 0xd7, 0x2f, 0x45, 0x38, 0x87, - 0xe8, 0x9d, 0x0b, 0xaa, 0xd5, 0xd5, 0x0e, 0x90, 0xcb, 0xb3, 0xbd, 0x7a, 0x07, 0xa7, 0x9b, 0xbe, 0xbe, 0x55, 0xa1, - 0x33, 0x07, 0x90, 0xf6, 0x90, 0xac, 0x6b, 0xae, 0x77, 0x80, 0x3b, 0x12, 0xb3, 0x35, 0xd0, 0x58, 0xb7, 0x35, 0x3b, - 0xed, 0x51, 0x3c, 0x26, 0x32, 0x33, 0x16, 0x29, 0xc6, 0xdc, 0xad, 0xd3, 0xa2, 0x68, 0x8b, 0x66, 0x08, 0xfb, 0x77, - 0x1d, 0xb1, 0x6e, 0x45, 0x9c, 0xbf, 0xdb, 0xf6, 0x05, 0x46, 0xc3, 0x98, 0x6b, 0xf7, 0x3c, 0x43, 0x37, 0x6c, 0xb0, - 0x8d, 0x24, 0x88, 0x48, 0x90, 0x99, 0x3a, 0x10, 0x65, 0x6d, 0x0d, 0xd8, 0xde, 0x71, 0xbd, 0x69, 0x81, 0x9f, 0x37, - 0x31, 0x78, 0x7b, 0xd6, 0x38, 0xa5, 0xf5, 0x35, 0xae, 0x39, 0xae, 0x0a, 0x11, 0xb5, 0x45, 0x0a, 0x80, 0x61, 0xe7, - 0x0b, 0xdc, 0x99, 0x15, 0x06, 0x73, 0xc2, 0x52, 0xc9, 0x5e, 0xe5, 0xfa, 0x73, 0xd8, 0xe2, 0x20, 0x95, 0x2f, 0xbd, - 0xfe, 0xfe, 0xc3, 0x17, 0x5f, 0xa0, 0xdb, 0x9e, 0xf3, 0x23, 0x08, 0x32, 0x81, 0x0e, 0x6a, 0x4a, 0xf5, 0xf8, 0xb2, - 0x00, 0x6a, 0x0f, 0xf3, 0xf0, 0xb2, 0x60, 0x22, 0xbe, 0xce, 0x2e, 0xe3, 0x4a, 0x16, 0xa3, 0x6b, 0x2e, 0x52, 0x59, - 0x58, 0xa9, 0x71, 0x70, 0xba, 0x5a, 0xe5, 0x3c, 0x00, 0x53, 0x79, 0xcb, 0x28, 0x3b, 0x21, 0xa3, 0x1e, 0x5c, 0x2d, - 0x4f, 0xaf, 0xb4, 0xe8, 0xbc, 0xbc, 0xbe, 0x0c, 0x22, 0xfc, 0x75, 0x6e, 0x7e, 0x5c, 0xc5, 0xe5, 0xa7, 0x20, 0xb2, - 0x36, 0x75, 0xe6, 0x07, 0x4a, 0xe5, 0xc1, 0xdf, 0x09, 0x64, 0xba, 0x2f, 0x0b, 0xb0, 0xcc, 0xb6, 0x15, 0x1f, 0xc7, - 0x58, 0xeb, 0x70, 0x42, 0x66, 0xaa, 0x44, 0xef, 0x5d, 0xb2, 0x2e, 0xc0, 0xda, 0x4f, 0x61, 0x3b, 0xab, 0x5c, 0x33, - 0xac, 0x4c, 0x55, 0x64, 0x0c, 0xe0, 0xd7, 0xec, 0x30, 0xb4, 0x4e, 0x34, 0x73, 0xf4, 0x16, 0xd0, 0x0f, 0xe4, 0xf0, - 0x92, 0x16, 0x6b, 0xe6, 0xf9, 0xd8, 0x34, 0x5e, 0x3f, 0x38, 0xbc, 0x74, 0x0b, 0xf6, 0xda, 0xde, 0xc9, 0x51, 0x98, - 0x08, 0x9e, 0xc6, 0x66, 0x7c, 0x91, 0x67, 0x05, 0xec, 0xa0, 0xc9, 0x78, 0x4c, 0xbd, 0xa5, 0xd5, 0xba, 0x39, 0x3a, - 0x64, 0xdb, 0xec, 0x61, 0xf5, 0x90, 0x93, 0x43, 0xde, 0x32, 0xb5, 0x6d, 0x5b, 0xc7, 0x79, 0x9a, 0x7c, 0x65, 0xba, - 0x2f, 0xd7, 0x36, 0x42, 0xbc, 0x72, 0x76, 0x74, 0x5e, 0xd2, 0xad, 0x6f, 0x4a, 0x43, 0xaf, 0x25, 0x00, 0xf3, 0x69, - 0x03, 0xfe, 0x82, 0x15, 0xeb, 0x51, 0xc5, 0xcb, 0x0a, 0x24, 0x2c, 0x28, 0xc2, 0x9b, 0x62, 0x6f, 0x0a, 0x77, 0xe3, - 0xf4, 0x1c, 0x76, 0xe0, 0x62, 0x8a, 0xee, 0x38, 0x31, 0x99, 0x95, 0x46, 0x2b, 0x1a, 0xe9, 0x5f, 0xae, 0x2f, 0xb1, - 0xee, 0x8b, 0x56, 0xe6, 0xd9, 0x9c, 0x0a, 0x9b, 0xde, 0x55, 0x2e, 0x9d, 0xa8, 0xdf, 0x32, 0xe1, 0xca, 0x95, 0x20, - 0x20, 0xd3, 0x82, 0xf5, 0x0a, 0xb3, 0x8b, 0x62, 0x24, 0x64, 0x60, 0xf8, 0x1a, 0xac, 0x45, 0xc9, 0x8d, 0x15, 0xac, - 0x77, 0xcf, 0xd7, 0x09, 0x42, 0x0a, 0x1e, 0xb8, 0x09, 0xfa, 0xa5, 0x75, 0xf3, 0x76, 0x94, 0x28, 0x83, 0xf8, 0xe4, - 0xda, 0x29, 0x07, 0x09, 0x04, 0xe0, 0xc0, 0xaa, 0x90, 0x24, 0x0a, 0x74, 0x1e, 0x5c, 0xcd, 0x38, 0x82, 0xcd, 0x2b, - 0x67, 0x2e, 0x6e, 0x00, 0xe7, 0x95, 0x3f, 0x97, 0x0d, 0xb6, 0xac, 0x47, 0x54, 0x99, 0x33, 0x4e, 0x31, 0xa8, 0x93, - 0x25, 0xe8, 0x2b, 0x4b, 0x69, 0x2f, 0x41, 0xd3, 0x78, 0xc5, 0x56, 0xca, 0x07, 0x80, 0x9e, 0xb3, 0x95, 0x32, 0xf6, - 0xc7, 0xaf, 0xcf, 0xd8, 0x4a, 0x4b, 0x83, 0xa7, 0x57, 0xb3, 0xf3, 0xd9, 0xd9, 0x80, 0x1d, 0x45, 0xa1, 0x36, 0x60, - 0x08, 0x5c, 0x64, 0x82, 0x60, 0x10, 0x6a, 0xfc, 0x97, 0x81, 0x0a, 0x10, 0x46, 0x3c, 0x1e, 0x1b, 0x71, 0xc4, 0xc2, - 0xf1, 0x10, 0x83, 0x81, 0x35, 0x5f, 0x90, 0x80, 0x50, 0x53, 0x1a, 0xfa, 0x7a, 0x86, 0xc3, 0xc9, 0xc1, 0x04, 0x52, - 0x31, 0x33, 0x53, 0x85, 0xb1, 0x31, 0x89, 0x20, 0xfe, 0x6b, 0x67, 0xbd, 0x50, 0x6e, 0x77, 0x8d, 0x06, 0x82, 0x66, - 0xf0, 0x55, 0x15, 0x4f, 0x0e, 0x86, 0x5d, 0x15, 0xe3, 0x28, 0x5c, 0x1b, 0xe5, 0xdb, 0xd9, 0x31, 0x80, 0xf9, 0x9e, - 0x0d, 0x7d, 0xb9, 0xc4, 0xd9, 0xe1, 0x63, 0xf2, 0xf0, 0x31, 0xa1, 0x67, 0xec, 0xec, 0x9b, 0xc7, 0xf4, 0x4c, 0x91, - 0x93, 0x83, 0x49, 0x74, 0xcd, 0x2c, 0x06, 0xce, 0x91, 0x6a, 0x02, 0xbd, 0x1c, 0xad, 0x85, 0x5a, 0x60, 0xda, 0xa1, - 0x29, 0xfc, 0x7e, 0x7c, 0x10, 0x0c, 0xae, 0xdb, 0x4d, 0xbf, 0x6e, 0xb7, 0xd5, 0xf3, 0xea, 0x3a, 0x38, 0x8a, 0xf6, - 0x8b, 0x99, 0xfc, 0x7d, 0x7c, 0xe0, 0xe6, 0x00, 0xeb, 0xbb, 0x7f, 0x4c, 0x4c, 0x93, 0xf6, 0x46, 0xc5, 0xaf, 0xe9, - 0x11, 0xf6, 0xa1, 0x59, 0x64, 0x47, 0x1f, 0x86, 0xff, 0x51, 0x27, 0xea, 0xb3, 0x6f, 0x8e, 0x80, 0x1c, 0x81, 0x0c, - 0x14, 0x4b, 0x04, 0x33, 0x1c, 0x68, 0x0a, 0x28, 0xc8, 0xf4, 0xb8, 0x53, 0x3d, 0xfc, 0x6a, 0xd4, 0xd4, 0x8c, 0x5c, - 0xc3, 0xd4, 0x60, 0x5b, 0xf0, 0x03, 0xd5, 0x0d, 0xfd, 0x8d, 0x46, 0x7b, 0xd2, 0x4e, 0x66, 0xe6, 0x25, 0xb5, 0x71, - 0xee, 0xae, 0x21, 0xa0, 0xb3, 0x83, 0x5b, 0x94, 0xec, 0xdb, 0xe3, 0xcb, 0x03, 0x5c, 0x45, 0x80, 0x1a, 0xc6, 0x82, - 0x6f, 0x07, 0x97, 0x7a, 0x73, 0x1f, 0x04, 0x64, 0xf0, 0x6d, 0x70, 0xf2, 0xed, 0x40, 0x0e, 0x82, 0xe3, 0xc3, 0xcb, - 0x93, 0xc0, 0x19, 0xf7, 0x43, 0xc8, 0x4b, 0x55, 0x51, 0xcc, 0x84, 0xa9, 0x22, 0xb1, 0xb5, 0xe7, 0xb6, 0x5e, 0x65, - 0x7c, 0x46, 0xd3, 0xa9, 0x45, 0x42, 0x0f, 0x53, 0x16, 0x9b, 0xdf, 0xc1, 0x84, 0x5f, 0x05, 0x91, 0x0b, 0x0a, 0x3b, - 0xcb, 0xa3, 0x98, 0x2e, 0xd9, 0xb5, 0x08, 0x53, 0x9a, 0x1c, 0xe6, 0x84, 0x44, 0xe1, 0x52, 0x81, 0x09, 0xaa, 0xd7, - 0x09, 0xc4, 0xb5, 0x75, 0x9f, 0x5f, 0x8b, 0x70, 0x49, 0xf3, 0xc3, 0x84, 0xb4, 0x8a, 0x70, 0x11, 0x6a, 0xb6, 0x35, - 0xbd, 0x60, 0xe1, 0x8a, 0x5e, 0x02, 0x33, 0x15, 0xaf, 0xc3, 0x4b, 0xe0, 0xf2, 0xd6, 0xf3, 0xd5, 0x82, 0x5d, 0x36, - 0xa4, 0x6f, 0x86, 0x2f, 0xbe, 0xb0, 0x3e, 0x79, 0xc0, 0x43, 0x3a, 0x3f, 0xbc, 0x14, 0x6c, 0x00, 0xae, 0x33, 0x7e, - 0xf3, 0x83, 0xbc, 0xd5, 0xf3, 0xd2, 0x9e, 0x62, 0x9c, 0x99, 0x76, 0x62, 0xd2, 0x4e, 0xc8, 0xfd, 0xfb, 0xb6, 0xef, - 0x5e, 0xbc, 0x56, 0x2e, 0xab, 0x96, 0x21, 0x49, 0xd6, 0xca, 0x75, 0x1a, 0x25, 0xa7, 0x56, 0xe0, 0xc9, 0x2e, 0x78, - 0x95, 0x2c, 0xfd, 0x83, 0xca, 0x5a, 0x0d, 0xd8, 0x63, 0xc4, 0xb2, 0x50, 0x38, 0xf6, 0xaf, 0x33, 0x96, 0xac, 0x7d, - 0x81, 0x46, 0x8e, 0xdc, 0xdb, 0xeb, 0x8c, 0x79, 0x31, 0x68, 0x97, 0x6b, 0x2f, 0x74, 0x9f, 0x97, 0x9e, 0xb6, 0x78, - 0x2f, 0xa7, 0xd4, 0x30, 0x12, 0xd1, 0x83, 0xb1, 0x32, 0xa3, 0x54, 0x89, 0x5a, 0x83, 0x46, 0x04, 0x1b, 0xbb, 0x60, - 0xa0, 0xe0, 0x84, 0xca, 0x3d, 0x75, 0xb6, 0x6f, 0xa7, 0x54, 0x7a, 0x40, 0xbb, 0xd4, 0xa8, 0xca, 0xdd, 0x32, 0x93, - 0xac, 0x1a, 0x04, 0xa3, 0x3f, 0x4b, 0x29, 0x66, 0x78, 0x67, 0x64, 0xc1, 0x14, 0xac, 0x04, 0x55, 0x2d, 0xc3, 0x72, - 0xc8, 0x51, 0x8b, 0x67, 0x7c, 0x52, 0xa5, 0xfe, 0xd1, 0x11, 0x34, 0x78, 0xbd, 0x6e, 0x05, 0x0d, 0x7e, 0x3c, 0x7e, - 0xac, 0x07, 0xfa, 0x62, 0xad, 0x1d, 0x0f, 0x7d, 0x7e, 0x1b, 0xf1, 0xc6, 0x75, 0xef, 0xa9, 0xd6, 0x2a, 0x94, 0x81, - 0x16, 0x2b, 0x2a, 0x57, 0x6a, 0x49, 0xef, 0x76, 0x11, 0x00, 0x8b, 0xd8, 0x98, 0x8d, 0xf7, 0x6d, 0xb3, 0x42, 0xd0, - 0xe8, 0xc2, 0x52, 0x1c, 0xb0, 0x44, 0xb7, 0x76, 0x30, 0xa1, 0xf1, 0x09, 0x2b, 0xfb, 0xfd, 0xfc, 0x04, 0xe8, 0xa9, - 0x36, 0x62, 0x2a, 0xe0, 0xc8, 0xff, 0xda, 0x8a, 0x4c, 0x51, 0x60, 0xb3, 0xa6, 0xee, 0xd6, 0x58, 0x46, 0xa2, 0x2f, - 0x53, 0xba, 0x3c, 0xe1, 0x19, 0x30, 0xad, 0xd6, 0x2d, 0xc7, 0x95, 0x7d, 0xc5, 0x91, 0xa7, 0xc2, 0xb2, 0xe2, 0xbc, - 0x0a, 0xc7, 0x5b, 0x8f, 0x6f, 0x70, 0x68, 0xd8, 0xb4, 0x4b, 0x7f, 0x08, 0x61, 0x21, 0xbc, 0xce, 0xe0, 0x36, 0xa2, - 0xed, 0x24, 0x50, 0x79, 0x63, 0xae, 0x13, 0xca, 0xe6, 0x76, 0xb5, 0xf6, 0x0c, 0xd2, 0x89, 0x39, 0x50, 0xaa, 0x11, - 0xb4, 0x46, 0xb3, 0xa0, 0x6a, 0xc4, 0x23, 0x67, 0xfe, 0xe5, 0x0c, 0x62, 0xb5, 0x7c, 0x49, 0x53, 0x29, 0x1a, 0x80, - 0x71, 0x01, 0x5c, 0x9e, 0x7e, 0x79, 0xff, 0xd3, 0x07, 0x1e, 0x17, 0xc9, 0xf2, 0x5d, 0x5c, 0xc4, 0x57, 0x65, 0xb8, - 0x55, 0x63, 0x14, 0xd7, 0x64, 0x2a, 0x06, 0x4c, 0x9a, 0x95, 0xd4, 0xdc, 0x95, 0x9a, 0x10, 0x63, 0x9d, 0xc9, 0xba, - 0xac, 0xe4, 0x55, 0xa3, 0xd2, 0x75, 0x91, 0xe1, 0xc7, 0x2d, 0x9f, 0xd3, 0x43, 0x00, 0x36, 0x35, 0x2e, 0xa4, 0x91, - 0xd4, 0x85, 0x18, 0x73, 0x11, 0xaf, 0xeb, 0xe3, 0x71, 0xa3, 0xeb, 0x25, 0x7b, 0x32, 0x7e, 0x34, 0x7d, 0x9d, 0x85, - 0xd9, 0x40, 0x90, 0x51, 0xb5, 0xe4, 0xa2, 0x65, 0xca, 0xa9, 0x4c, 0x02, 0xd0, 0xc7, 0xb3, 0xc7, 0xd8, 0xd1, 0x78, - 0x4c, 0xb6, 0x6d, 0xf1, 0x00, 0x0f, 0xd7, 0xeb, 0xb0, 0x20, 0x33, 0x5d, 0x47, 0x14, 0x08, 0x7e, 0x5b, 0x05, 0x80, - 0x6c, 0x69, 0xab, 0x32, 0x5c, 0x1a, 0x7b, 0x32, 0x9e, 0x50, 0x89, 0xdd, 0x0e, 0x49, 0xed, 0x55, 0xe8, 0x66, 0x5e, - 0xfa, 0x1e, 0x45, 0xd2, 0xb8, 0x2c, 0xed, 0x55, 0x2a, 0xd5, 0x9e, 0x99, 0xb9, 0xae, 0x41, 0x4c, 0x8a, 0x50, 0xd7, - 0x5d, 0x7a, 0x75, 0xef, 0x37, 0xd7, 0x9a, 0xed, 0x80, 0xf7, 0x1a, 0x34, 0x43, 0xc9, 0x5b, 0xcc, 0x5b, 0x57, 0x44, - 0x4d, 0xaf, 0xd6, 0x60, 0x56, 0x8c, 0xb2, 0xa5, 0xe8, 0x62, 0x4d, 0x41, 0x29, 0x18, 0x5d, 0xae, 0xbd, 0x85, 0xfb, - 0x54, 0x36, 0x2e, 0x2c, 0x99, 0x5e, 0x2d, 0x4a, 0x4a, 0xa8, 0x6e, 0x2a, 0x46, 0x4a, 0x18, 0x29, 0x0d, 0x4f, 0xe5, - 0x7b, 0x81, 0xc7, 0x79, 0x1e, 0x44, 0x2d, 0x2f, 0xb0, 0xd3, 0x8a, 0x9c, 0x82, 0xa3, 0x97, 0xc9, 0x69, 0x28, 0x70, - 0x25, 0x14, 0xa8, 0xeb, 0x50, 0xdd, 0x6f, 0x70, 0xf3, 0xff, 0x56, 0xb0, 0xc0, 0xe3, 0x5b, 0xcf, 0x71, 0x1b, 0xfd, - 0x56, 0xf8, 0xb4, 0xf4, 0x81, 0xf4, 0x5d, 0x5d, 0x3c, 0x69, 0x6f, 0x36, 0x4a, 0x96, 0x59, 0x9e, 0xbe, 0x91, 0x29, - 0x07, 0x91, 0x19, 0x5a, 0x83, 0xb2, 0x13, 0xd1, 0xb8, 0xe1, 0x81, 0x11, 0x63, 0xe3, 0xc6, 0x57, 0x41, 0x20, 0x47, - 0x40, 0xee, 0xe7, 0x2c, 0x95, 0xc9, 0x1a, 0x10, 0x36, 0xb4, 0xfc, 0x44, 0xe3, 0x6d, 0x84, 0xfa, 0xfa, 0x05, 0x6e, - 0x73, 0xa5, 0xef, 0x73, 0x5e, 0x09, 0x5a, 0x09, 0x00, 0x7e, 0x89, 0x57, 0x20, 0xf7, 0x78, 0x0a, 0x75, 0x23, 0x6c, - 0x2f, 0xc7, 0x60, 0x49, 0x88, 0x8e, 0x22, 0x2a, 0x16, 0x28, 0x68, 0x0a, 0x83, 0x28, 0xa2, 0x2e, 0x98, 0xc3, 0xf3, - 0x5c, 0x26, 0x9f, 0xa6, 0xc6, 0x67, 0x7e, 0x18, 0x63, 0x0c, 0xe9, 0x60, 0x10, 0x56, 0xb3, 0x60, 0x38, 0x1e, 0x4d, - 0x8e, 0x9e, 0xc0, 0xb9, 0x1d, 0x8c, 0x03, 0x32, 0x08, 0xea, 0x72, 0x15, 0x0b, 0x5a, 0x5e, 0x5f, 0xda, 0x32, 0xf0, - 0xe3, 0x3a, 0x18, 0xfc, 0x56, 0xb8, 0x51, 0xf9, 0x37, 0x68, 0x4e, 0x36, 0x32, 0x0c, 0x02, 0x7a, 0xb5, 0x26, 0x20, - 0x29, 0xeb, 0x69, 0x7e, 0x52, 0x1f, 0x6e, 0x4c, 0x69, 0xff, 0xcc, 0xe1, 0x05, 0x87, 0x1d, 0x12, 0x28, 0x90, 0xc6, - 0xd3, 0x6c, 0xf4, 0x4a, 0x29, 0x72, 0xdf, 0x15, 0x1c, 0xee, 0xcc, 0x3d, 0x67, 0x7a, 0xe4, 0x14, 0x12, 0xcd, 0x2c, - 0xe0, 0x46, 0xfe, 0x4a, 0x5c, 0xc7, 0x79, 0x96, 0x1e, 0x34, 0xdf, 0x1c, 0x94, 0x1b, 0x51, 0xc5, 0xb7, 0xa3, 0xc0, - 0x58, 0x13, 0x72, 0x5f, 0xf5, 0x04, 0xe8, 0x09, 0xb0, 0x05, 0xc0, 0x80, 0x78, 0xcf, 0xcc, 0x64, 0xc6, 0x23, 0xf0, - 0x08, 0x6c, 0xfa, 0x40, 0x16, 0x1b, 0xe7, 0x92, 0xe4, 0x6f, 0xa6, 0xd2, 0x5e, 0xf5, 0xca, 0xbd, 0x82, 0xac, 0x57, - 0x5b, 0xb9, 0xef, 0xd6, 0x67, 0xdf, 0x74, 0x78, 0x05, 0x9e, 0x49, 0x70, 0x8b, 0xec, 0xf7, 0x9b, 0x82, 0x4a, 0x61, - 0x54, 0xc4, 0x7b, 0xc9, 0x35, 0xfa, 0xb7, 0x7b, 0x63, 0xa3, 0x48, 0x6e, 0x79, 0xff, 0x00, 0xea, 0x4c, 0xde, 0x15, - 0xb7, 0x73, 0x88, 0xda, 0xba, 0x1b, 0x0f, 0xbc, 0x37, 0x68, 0x97, 0x35, 0x47, 0xb0, 0xe5, 0xc5, 0x41, 0x06, 0x63, - 0x81, 0xb3, 0x32, 0x52, 0x6a, 0x5c, 0x43, 0x6a, 0xc1, 0x27, 0x79, 0x7a, 0x07, 0x59, 0xea, 0x49, 0x50, 0xe4, 0x78, - 0x16, 0x43, 0xa6, 0xf1, 0x36, 0x10, 0xfb, 0xad, 0x0c, 0x41, 0x9a, 0xb6, 0xdb, 0x35, 0x47, 0xa0, 0xec, 0x1e, 0x98, - 0x92, 0xd4, 0xb5, 0x31, 0x35, 0xd0, 0xd0, 0x83, 0xa8, 0x91, 0x8a, 0x38, 0x3b, 0x79, 0x0a, 0x3a, 0x44, 0xf0, 0xfd, - 0x4e, 0xb3, 0xb2, 0xe3, 0xc5, 0x84, 0xe0, 0xc9, 0xfb, 0xfc, 0x36, 0x2b, 0xab, 0x32, 0x7a, 0x93, 0xa2, 0x21, 0x54, - 0x22, 0x45, 0xf4, 0x19, 0xe2, 0x0b, 0x96, 0xf8, 0xbb, 0x8c, 0x5e, 0xa4, 0x34, 0x4e, 0x53, 0x4c, 0x7f, 0x56, 0xc0, - 0xcf, 0xa7, 0x80, 0x72, 0x89, 0x3b, 0x21, 0x3a, 0x93, 0x60, 0xaf, 0x06, 0xd1, 0xbd, 0x2a, 0x0e, 0x98, 0xa2, 0xd1, - 0xb5, 0xa0, 0x88, 0x59, 0x87, 0xd9, 0x7f, 0x29, 0x50, 0x28, 0xa4, 0x8a, 0x79, 0x29, 0xec, 0x43, 0xc4, 0xd7, 0x50, - 0xce, 0xe9, 0xbb, 0x57, 0x66, 0x48, 0xa3, 0x5b, 0x49, 0xf5, 0xd6, 0xc6, 0x63, 0x0b, 0x51, 0x7a, 0xa2, 0xf3, 0x35, - 0x3d, 0x8b, 0x57, 0x59, 0xb4, 0x05, 0xfc, 0x89, 0x77, 0xaf, 0x9e, 0x2a, 0x0b, 0x93, 0x57, 0x19, 0x28, 0x0e, 0x4e, - 0xdf, 0xbd, 0x7a, 0x2d, 0xd3, 0x75, 0xce, 0xa3, 0x8d, 0x44, 0xd2, 0x7a, 0xfa, 0xee, 0xd5, 0xcf, 0x68, 0xee, 0xf5, - 0xbe, 0x80, 0xf7, 0x2f, 0x80, 0xb7, 0x8c, 0xf2, 0x35, 0xf4, 0x49, 0xfd, 0x5e, 0xae, 0xb1, 0x53, 0x5e, 0xad, 0x65, - 0xf4, 0x57, 0x5a, 0x7b, 0xd2, 0xaa, 0xbf, 0x0a, 0x9f, 0xda, 0x79, 0x02, 0x9e, 0xdb, 0x3c, 0x13, 0x9f, 0x22, 0x2b, - 0xda, 0x09, 0xa2, 0x6f, 0x0f, 0x6e, 0xaf, 0x72, 0x51, 0x46, 0xf8, 0x82, 0xa1, 0x5d, 0x50, 0x74, 0x78, 0x78, 0x73, - 0x73, 0x33, 0xba, 0x79, 0x34, 0x92, 0xc5, 0xe5, 0xe1, 0xe4, 0xfb, 0xef, 0xbf, 0x3f, 0xc4, 0xb7, 0xc1, 0xb7, 0x6d, - 0xb7, 0xf7, 0x8a, 0xf0, 0x01, 0x0b, 0x10, 0xb1, 0xfb, 0x5b, 0xb8, 0xa2, 0x80, 0x16, 0x6e, 0xf0, 0x6d, 0xf0, 0xad, - 0x3e, 0x74, 0xbe, 0x3d, 0x2e, 0xaf, 0x2f, 0x55, 0xf9, 0x5d, 0x25, 0x1f, 0x8d, 0xc7, 0xe3, 0x43, 0x90, 0x40, 0x7d, - 0x3b, 0xe0, 0x83, 0xe0, 0x24, 0x18, 0x64, 0x70, 0xa1, 0x29, 0xaf, 0x2f, 0x4f, 0x02, 0xcf, 0xe4, 0xb5, 0xc1, 0x22, - 0x3a, 0x10, 0x97, 0xe0, 0xf0, 0x92, 0x06, 0xdf, 0x06, 0xc4, 0xa5, 0x7c, 0x03, 0x29, 0xdf, 0x1c, 0x3d, 0xf1, 0xd3, - 0xfe, 0x97, 0x4a, 0x7b, 0xe4, 0xa7, 0x1d, 0x63, 0xda, 0xa3, 0xa7, 0x7e, 0xda, 0x89, 0x4a, 0x7b, 0xee, 0xa7, 0xfd, - 0x9f, 0x72, 0x00, 0xa9, 0x07, 0xbe, 0xf5, 0xdf, 0xc6, 0x6b, 0x0d, 0x9e, 0x42, 0x51, 0x76, 0x15, 0x5f, 0x72, 0x68, - 0xf4, 0xe0, 0xf6, 0x2a, 0xa7, 0xc1, 0x00, 0xdb, 0xeb, 0x19, 0x79, 0x78, 0x1f, 0x7c, 0xbb, 0x2e, 0xf2, 0x30, 0xf8, - 0x76, 0x80, 0x85, 0x0c, 0xbe, 0x0d, 0xc8, 0xb7, 0xc6, 0x40, 0x46, 0xb0, 0x6d, 0xe0, 0x42, 0xb3, 0x0e, 0x6d, 0xc0, - 0x34, 0x5f, 0x1a, 0x57, 0xd3, 0x7f, 0x15, 0xdd, 0xd9, 0xf0, 0x96, 0xa8, 0xdc, 0x74, 0x83, 0x9a, 0xbe, 0x05, 0xef, - 0x04, 0x68, 0x54, 0x14, 0x5c, 0xc7, 0x45, 0x38, 0x1c, 0x96, 0xd7, 0x97, 0x04, 0xec, 0x32, 0x57, 0x3c, 0xae, 0xa2, - 0x40, 0xc8, 0xa1, 0xfa, 0x19, 0xa8, 0x48, 0x60, 0x01, 0x42, 0x19, 0xc1, 0x7f, 0x41, 0x4d, 0xdf, 0x49, 0xb6, 0x0d, - 0x86, 0x37, 0xfc, 0xfc, 0x53, 0x56, 0x0d, 0x95, 0x68, 0xf1, 0x46, 0x50, 0xf8, 0x01, 0x7f, 0x5d, 0xd5, 0xd1, 0xbf, - 0xc0, 0x8d, 0xbb, 0xa9, 0x61, 0x7f, 0x27, 0x3d, 0x87, 0x36, 0x39, 0xcf, 0x16, 0xd3, 0xd6, 0x81, 0xfe, 0x56, 0x92, - 0x6a, 0x9e, 0x0d, 0x82, 0x61, 0x30, 0xe0, 0x0b, 0xf6, 0x56, 0xce, 0xb9, 0x67, 0x3e, 0x75, 0x2a, 0xfd, 0x69, 0x9e, - 0x65, 0x03, 0xf0, 0x4d, 0x41, 0x7e, 0xe4, 0xf0, 0xbf, 0xe6, 0x43, 0x14, 0x1e, 0x0e, 0x1e, 0x1c, 0x92, 0x59, 0xb0, - 0xba, 0x45, 0x8f, 0xce, 0x28, 0xc8, 0xc4, 0x92, 0x17, 0x59, 0xe5, 0x2d, 0x95, 0xeb, 0x75, 0xdb, 0xcb, 0xe3, 0xce, - 0xb3, 0x79, 0x15, 0x8b, 0x40, 0x9d, 0x73, 0xa0, 0x78, 0x43, 0xd9, 0x53, 0xd9, 0x94, 0x90, 0x6a, 0x43, 0xde, 0xb0, - 0x1c, 0xb0, 0xe0, 0xb8, 0x37, 0x1c, 0x1e, 0x04, 0x03, 0xa7, 0xce, 0x1d, 0x04, 0x07, 0xc3, 0xe1, 0x49, 0xe0, 0xee, - 0x43, 0xd9, 0xc8, 0xdd, 0x19, 0x69, 0xc1, 0xfe, 0x2a, 0xc2, 0x92, 0x82, 0x78, 0x4c, 0x6a, 0xf1, 0x97, 0x06, 0x97, - 0x19, 0x00, 0xf4, 0x91, 0x92, 0x80, 0x19, 0x58, 0x99, 0x01, 0x84, 0x2a, 0xa7, 0x31, 0xbb, 0x05, 0xe6, 0x11, 0x38, - 0x66, 0x05, 0x93, 0x05, 0x88, 0x25, 0x01, 0xce, 0x5d, 0x10, 0xc5, 0xba, 0x90, 0x53, 0x08, 0x02, 0x80, 0x3f, 0x89, - 0x29, 0x05, 0x93, 0x74, 0xec, 0x46, 0x10, 0xc4, 0xf1, 0xd9, 0x8d, 0x68, 0x4d, 0xce, 0x12, 0x1d, 0xcc, 0x48, 0x02, - 0x6c, 0x88, 0x81, 0xe1, 0x83, 0xfb, 0x39, 0x28, 0x3d, 0xac, 0xde, 0x09, 0xb9, 0xe0, 0x0d, 0x77, 0x2c, 0xd4, 0x0d, - 0x5c, 0x3d, 0xe1, 0x20, 0xd8, 0x70, 0xcd, 0x02, 0x8c, 0xaa, 0x62, 0x5d, 0x56, 0x3c, 0xfd, 0xb8, 0x59, 0x41, 0x2c, - 0x40, 0x1c, 0xd0, 0x77, 0x32, 0xcf, 0x92, 0x4d, 0xe8, 0xec, 0xb9, 0xb6, 0x2a, 0xfd, 0xe5, 0xc7, 0xd7, 0x3f, 0x45, - 0x20, 0x72, 0xac, 0x0d, 0xa5, 0xdf, 0x70, 0x3c, 0x9b, 0xfc, 0x88, 0x57, 0xfe, 0xc6, 0xde, 0x70, 0x7b, 0x7a, 0xf4, - 0xfb, 0x50, 0x37, 0xdd, 0xf0, 0xd9, 0x86, 0x8f, 0x5c, 0x71, 0xa8, 0xae, 0xf0, 0xec, 0xb2, 0xd6, 0xbe, 0x11, 0xd2, - 0xfd, 0xf3, 0x4c, 0x79, 0x63, 0x7e, 0xb4, 0x83, 0x61, 0x10, 0x4c, 0xb5, 0x50, 0x12, 0xa2, 0x90, 0x30, 0x25, 0x60, - 0x88, 0x0e, 0xf4, 0xb2, 0x9a, 0x22, 0xe7, 0xa6, 0x46, 0x16, 0xde, 0x0f, 0x98, 0x16, 0x3a, 0x34, 0x72, 0x28, 0x3f, - 0x38, 0x9c, 0x30, 0x66, 0xe1, 0xb7, 0x4a, 0x98, 0x7e, 0xb5, 0xa8, 0x9c, 0x83, 0xe8, 0x01, 0x18, 0xe3, 0x0a, 0x5e, - 0x40, 0x57, 0xd8, 0xa7, 0xb5, 0x8a, 0x12, 0x82, 0x60, 0x7a, 0xc8, 0x01, 0x7a, 0xd8, 0x05, 0x2d, 0x2b, 0x4b, 0x75, - 0xab, 0x72, 0x96, 0x2a, 0xea, 0x32, 0x94, 0x95, 0xb1, 0xc2, 0xc0, 0x2f, 0xd9, 0x2f, 0x05, 0x7a, 0x96, 0x4f, 0x45, - 0x17, 0xbc, 0x10, 0x4a, 0xb0, 0x5c, 0xd7, 0x3b, 0x11, 0x88, 0x3a, 0x3f, 0xf4, 0xae, 0xfa, 0x1a, 0xd7, 0x8f, 0xa7, - 0xaf, 0x65, 0xca, 0xb5, 0x09, 0x85, 0xe6, 0xf3, 0xa5, 0xaf, 0x98, 0x28, 0xd8, 0x07, 0xe8, 0x57, 0xdb, 0x46, 0x9f, - 0x5d, 0xaf, 0xf5, 0x66, 0x50, 0xa2, 0x63, 0x5e, 0xa3, 0xe0, 0x5a, 0x29, 0x14, 0x8c, 0xf6, 0x36, 0xfe, 0x02, 0x47, - 0x6e, 0x75, 0x7b, 0xe8, 0xfd, 0x56, 0xc5, 0x97, 0x6f, 0xd0, 0xb7, 0xd3, 0xfe, 0x1c, 0x55, 0xf2, 0x97, 0xd5, 0x0a, - 0x7c, 0xa8, 0x20, 0xd2, 0x8a, 0xc5, 0xe9, 0x85, 0x7a, 0x3e, 0xbc, 0x3b, 0x7d, 0x03, 0x7e, 0x94, 0xf8, 0xfb, 0xd7, - 0x1f, 0x83, 0x9a, 0x4c, 0xe3, 0x59, 0x61, 0x3e, 0xb4, 0x39, 0x20, 0x54, 0x8b, 0x4b, 0xb3, 0xef, 0x67, 0x71, 0x93, - 0x7d, 0xd7, 0x6c, 0x3d, 0x2d, 0x9a, 0x48, 0x52, 0x86, 0xdb, 0x07, 0x03, 0x02, 0x7d, 0x80, 0x28, 0xce, 0xbe, 0xa0, - 0x31, 0xa4, 0xf9, 0xcc, 0xbe, 0x1f, 0x21, 0xf0, 0xd5, 0x5e, 0x48, 0x35, 0xae, 0xb0, 0x68, 0xf4, 0x90, 0xcf, 0x78, - 0xa4, 0x0c, 0x8b, 0xde, 0x63, 0x02, 0x71, 0x86, 0xd3, 0xea, 0x3d, 0x62, 0x40, 0xe3, 0xdd, 0x40, 0xcb, 0x1e, 0xa2, - 0x8c, 0xba, 0xec, 0x0d, 0x8b, 0xef, 0xd7, 0xeb, 0x30, 0xb3, 0x96, 0x97, 0x43, 0xf8, 0x1b, 0x68, 0x03, 0x70, 0xca, - 0x91, 0xe5, 0xab, 0xcc, 0x46, 0x57, 0x4b, 0x4c, 0x6f, 0x22, 0x88, 0x4d, 0xa4, 0xd3, 0x61, 0xed, 0xea, 0x54, 0xbd, - 0xab, 0x9d, 0xcf, 0x44, 0xaf, 0x02, 0xad, 0x5c, 0xdb, 0x1e, 0x0f, 0xe1, 0x3f, 0xb5, 0xb4, 0xc2, 0x46, 0xd8, 0x73, - 0xf1, 0x85, 0xe7, 0xd8, 0x9c, 0x80, 0x06, 0x57, 0x32, 0x05, 0xe0, 0x2c, 0xad, 0x46, 0xa3, 0x46, 0xd8, 0x67, 0xe5, - 0x7c, 0x0e, 0x5b, 0x0b, 0xf1, 0xb4, 0x00, 0x1c, 0xb8, 0x89, 0xc9, 0xc9, 0xbb, 0x31, 0x39, 0xa7, 0x9f, 0x14, 0xdc, - 0x77, 0x70, 0x56, 0x2e, 0xe3, 0x54, 0xde, 0x00, 0x36, 0x65, 0xe0, 0xa7, 0x62, 0xa9, 0x5e, 0x42, 0xb2, 0xe4, 0xc9, - 0x27, 0xb4, 0xda, 0x48, 0x03, 0xe0, 0x2a, 0xa7, 0xc6, 0x72, 0x4f, 0x81, 0xa6, 0xba, 0x52, 0x54, 0x42, 0x5c, 0x55, - 0x71, 0xb2, 0xfc, 0x80, 0xa9, 0xe1, 0x16, 0x7a, 0x11, 0x05, 0x72, 0xc5, 0x05, 0x90, 0xf4, 0x9c, 0xfd, 0x23, 0xd3, - 0xd8, 0xeb, 0x0f, 0x24, 0x0a, 0x98, 0x34, 0x8a, 0x32, 0x56, 0xca, 0x5e, 0x49, 0x13, 0xfd, 0x2e, 0x08, 0x6a, 0xf7, - 0xf2, 0x2f, 0xa8, 0xfb, 0x29, 0xb4, 0x22, 0x6c, 0x80, 0x17, 0x6a, 0xf0, 0xc3, 0xd4, 0x2e, 0x39, 0x0f, 0xc8, 0xd0, - 0x79, 0x9f, 0xd5, 0x76, 0xab, 0x3f, 0x5d, 0x02, 0xd6, 0x6b, 0x6a, 0x7c, 0x0a, 0xc3, 0x84, 0x98, 0x58, 0xc9, 0x56, - 0x59, 0x69, 0x37, 0x94, 0x69, 0x27, 0x5d, 0x32, 0xaf, 0x85, 0xd3, 0xbc, 0xc7, 0xd8, 0x72, 0xa4, 0x72, 0xf7, 0xfb, - 0xa1, 0xf9, 0xc9, 0x72, 0xfa, 0x40, 0x87, 0xb0, 0xf6, 0xc6, 0x83, 0xe6, 0x44, 0xab, 0xab, 0x3a, 0xfa, 0x01, 0x1d, - 0x80, 0x99, 0xb6, 0x08, 0x95, 0x2e, 0xf8, 0xb6, 0xaf, 0x44, 0xc5, 0x25, 0x09, 0x4b, 0x25, 0x81, 0x9d, 0xdd, 0x94, - 0xec, 0x6c, 0x03, 0xe2, 0x19, 0xee, 0x7a, 0x5a, 0xec, 0x84, 0x34, 0xe1, 0x2d, 0x0e, 0x12, 0x10, 0x75, 0xa8, 0xea, - 0x12, 0xb2, 0x35, 0x86, 0x2e, 0xfe, 0x45, 0x29, 0x4c, 0x58, 0xcb, 0xa4, 0x2a, 0x31, 0x41, 0xa1, 0xca, 0xfd, 0x16, - 0x81, 0x25, 0x0a, 0x76, 0x00, 0x7b, 0xef, 0x46, 0xdd, 0x8c, 0x9a, 0xaa, 0x4e, 0xbd, 0x04, 0x1f, 0xa7, 0x59, 0x57, - 0x41, 0x66, 0x61, 0x57, 0xc5, 0x9a, 0x07, 0x3a, 0x56, 0x97, 0x32, 0x26, 0xee, 0xd2, 0x22, 0x43, 0x7c, 0x64, 0x8c, - 0x2d, 0xac, 0xe1, 0x48, 0xdb, 0xe3, 0xa6, 0x27, 0x08, 0xfd, 0x84, 0x0d, 0x25, 0x70, 0xd3, 0xd9, 0x9e, 0x9a, 0x66, - 0x3e, 0x20, 0xe2, 0x30, 0xa0, 0x40, 0xb2, 0x71, 0x48, 0x73, 0xa4, 0x2f, 0x48, 0x9a, 0x30, 0x50, 0xb6, 0xe2, 0x39, - 0x41, 0x56, 0x14, 0x7a, 0xb6, 0xae, 0x6a, 0x88, 0x9f, 0xcb, 0x30, 0x47, 0x4b, 0x4e, 0x85, 0xa7, 0x09, 0x32, 0xb1, - 0x3b, 0xda, 0x66, 0x26, 0xc3, 0x51, 0xb2, 0xc0, 0xfc, 0x0a, 0xa2, 0xc4, 0x9d, 0x69, 0x56, 0xe5, 0x60, 0x5c, 0xc0, - 0x02, 0xad, 0x7c, 0x0f, 0xea, 0xc6, 0x1a, 0xda, 0x6a, 0x58, 0x66, 0xb7, 0x3f, 0xc1, 0x7e, 0xad, 0x9d, 0xd6, 0x65, - 0x8a, 0xe5, 0x65, 0x0a, 0xd1, 0x5e, 0xc8, 0xfc, 0x46, 0x91, 0xe8, 0x5e, 0x11, 0x86, 0x84, 0x75, 0x94, 0x3d, 0x69, - 0x53, 0x03, 0xe8, 0xa9, 0x17, 0x00, 0xbe, 0x73, 0x2d, 0xc3, 0x2e, 0xd2, 0xfd, 0x55, 0xc1, 0xb8, 0x74, 0x83, 0x20, - 0x45, 0x6f, 0x52, 0x30, 0xe7, 0xf5, 0x28, 0xa9, 0x37, 0xa7, 0x2d, 0x33, 0xaa, 0x8e, 0x8a, 0x90, 0x72, 0x82, 0xff, - 0xe4, 0x95, 0xd4, 0xc4, 0x26, 0x4c, 0xf0, 0xc0, 0x87, 0x79, 0x86, 0x0d, 0xbc, 0xdb, 0x9d, 0xa6, 0x61, 0xd2, 0x66, - 0x1b, 0x52, 0x90, 0x56, 0x98, 0x38, 0x21, 0x50, 0xd9, 0x2b, 0xdc, 0x2f, 0xd8, 0x4e, 0x9a, 0x82, 0x07, 0x61, 0xa3, - 0x81, 0x89, 0x5b, 0x5d, 0x02, 0x8c, 0x66, 0xc2, 0x25, 0xd5, 0xce, 0x4e, 0x5a, 0x58, 0xdf, 0x5e, 0x97, 0x17, 0xb6, - 0x0f, 0x3a, 0x96, 0x5a, 0xd7, 0xf0, 0x40, 0xf3, 0x9a, 0x5d, 0x5c, 0x31, 0x4d, 0x13, 0x8d, 0xf5, 0x90, 0xb2, 0xe4, - 0x58, 0xd7, 0xd3, 0x15, 0xae, 0x96, 0x99, 0x06, 0xba, 0x97, 0x78, 0xa1, 0x07, 0x7c, 0xf0, 0x70, 0x45, 0xa2, 0x0b, - 0x6c, 0x36, 0x5b, 0xd5, 0x64, 0x9a, 0xdf, 0x95, 0x2d, 0x37, 0x01, 0xf2, 0x2c, 0xf5, 0xcd, 0x7d, 0x72, 0xac, 0x69, - 0x9b, 0x9f, 0x04, 0xb8, 0xe6, 0x5e, 0x01, 0x49, 0xc7, 0x12, 0x74, 0xf1, 0x3e, 0xfd, 0x41, 0xa4, 0x66, 0x2a, 0xe8, - 0x9d, 0xf3, 0x45, 0xea, 0xe6, 0x17, 0x60, 0x1b, 0xb5, 0xb5, 0xa6, 0x59, 0xeb, 0x30, 0x51, 0x16, 0xd6, 0xc8, 0x42, - 0x2e, 0xc1, 0x07, 0x73, 0xbf, 0xa9, 0xd3, 0xe7, 0x1d, 0x44, 0xd8, 0xef, 0xa2, 0xc7, 0x23, 0x8c, 0x15, 0x6b, 0x90, - 0x18, 0x56, 0x61, 0x4d, 0x9b, 0xcb, 0x21, 0xca, 0xa9, 0x59, 0x32, 0xd1, 0x92, 0xfa, 0x94, 0x22, 0x4a, 0xc1, 0xdc, - 0x78, 0x5a, 0x36, 0x4c, 0x09, 0x11, 0xb2, 0x42, 0x3a, 0xa0, 0x5a, 0x0b, 0x2d, 0xd5, 0x04, 0x01, 0x0f, 0xbd, 0x2c, - 0x34, 0xa6, 0x20, 0xfa, 0x88, 0x0c, 0x37, 0xe2, 0xc8, 0xe8, 0xfe, 0x18, 0xc5, 0x04, 0x42, 0x77, 0x7b, 0x79, 0x61, - 0xf5, 0x69, 0xd9, 0x56, 0x07, 0x71, 0x8d, 0x69, 0x72, 0x07, 0x41, 0x8d, 0x51, 0xd0, 0xe6, 0x74, 0xa3, 0xff, 0x2e, - 0x42, 0xdf, 0x2e, 0x1c, 0xbb, 0x51, 0x10, 0x09, 0x11, 0x69, 0xbd, 0xa6, 0x62, 0x80, 0xda, 0x79, 0xec, 0x22, 0x56, - 0xe9, 0x6e, 0x21, 0xca, 0x1b, 0x95, 0xf5, 0xeb, 0x75, 0x48, 0x76, 0x3b, 0x2c, 0x0b, 0x7c, 0xd9, 0x9f, 0xae, 0xef, - 0x80, 0x40, 0x7f, 0xb0, 0xfe, 0x22, 0x04, 0xfa, 0xb3, 0xec, 0x6b, 0x20, 0xd0, 0x1f, 0xac, 0xff, 0xa7, 0x21, 0xd0, - 0x9f, 0xae, 0x3d, 0x08, 0x74, 0x35, 0x18, 0xff, 0x2c, 0x58, 0xf0, 0xf6, 0x4d, 0x40, 0x9f, 0x49, 0x16, 0xbc, 0x7d, - 0xf1, 0xc2, 0x13, 0xa6, 0x7f, 0xcc, 0x34, 0x92, 0xbf, 0x91, 0x05, 0x23, 0x6e, 0x0b, 0xbc, 0x42, 0xad, 0x93, 0x0f, - 0x54, 0x94, 0x01, 0x10, 0x7d, 0xf9, 0x5b, 0x56, 0x2d, 0xc3, 0xe0, 0x30, 0x20, 0x33, 0x07, 0x09, 0x3a, 0x9c, 0x34, - 0x6e, 0x6f, 0xbf, 0x88, 0x86, 0x50, 0xc7, 0x46, 0x1e, 0x80, 0xaf, 0x5c, 0xae, 0xb7, 0xfe, 0x0d, 0x11, 0x3f, 0x99, - 0x59, 0xd0, 0xd1, 0xc3, 0x80, 0x80, 0xc7, 0x52, 0xe6, 0x21, 0x70, 0xce, 0xfd, 0x90, 0xd0, 0x3f, 0x16, 0x9e, 0x6d, - 0xd1, 0x2f, 0x22, 0xac, 0xc0, 0xe7, 0xee, 0xaf, 0x35, 0x3f, 0xcb, 0x52, 0xe2, 0xe4, 0xa1, 0x5c, 0x24, 0x32, 0xe5, - 0xbf, 0xbc, 0x7f, 0x65, 0x91, 0xc7, 0x43, 0x05, 0xbd, 0x44, 0x30, 0xa4, 0x71, 0xca, 0xaf, 0xb3, 0x84, 0xcf, 0xfe, - 0x78, 0xb0, 0xed, 0xcc, 0xa8, 0x5e, 0x93, 0xfa, 0xf0, 0x8f, 0x28, 0x08, 0xf4, 0x18, 0xfc, 0xf1, 0x60, 0x9b, 0xd5, - 0x87, 0x0f, 0xb6, 0xd5, 0x28, 0x95, 0x00, 0xef, 0x0d, 0xbf, 0x65, 0xfd, 0x60, 0x5b, 0xc2, 0x0f, 0x5e, 0xff, 0xe1, - 0x01, 0xb3, 0xd9, 0x06, 0x79, 0x7d, 0xb0, 0xca, 0x2b, 0x87, 0x09, 0x7a, 0x4f, 0xc1, 0xc2, 0x14, 0xea, 0xf0, 0xa8, - 0xd6, 0x9e, 0xdc, 0x6f, 0xaa, 0xbb, 0x4e, 0x08, 0x5c, 0x23, 0xdd, 0xc0, 0x21, 0x54, 0x96, 0x60, 0x27, 0x1d, 0x9d, - 0x12, 0xc4, 0xd4, 0x7c, 0x18, 0x28, 0x5b, 0x5f, 0x2f, 0x58, 0xb1, 0x6b, 0x26, 0xc6, 0x77, 0x1a, 0x03, 0x1b, 0x2e, - 0xba, 0x5a, 0xcc, 0xd9, 0x1f, 0xa6, 0xc7, 0xfb, 0x55, 0x48, 0x82, 0x18, 0xd9, 0x7e, 0x9f, 0x78, 0x3d, 0x4b, 0x79, - 0x15, 0x67, 0x39, 0x8b, 0xf3, 0xfc, 0x0f, 0x94, 0x45, 0xfc, 0xf8, 0x55, 0xa0, 0xfb, 0xa3, 0xd1, 0x28, 0x2e, 0x2e, - 0xf1, 0xea, 0x6f, 0xc8, 0x2d, 0xc2, 0x62, 0x67, 0xbc, 0xb4, 0x81, 0x55, 0x96, 0x71, 0x79, 0xa6, 0x23, 0x1a, 0x95, - 0x96, 0x60, 0x97, 0x4b, 0x79, 0x73, 0x06, 0xd1, 0x1d, 0x2c, 0x05, 0x8f, 0x71, 0x00, 0xd5, 0xbd, 0x49, 0x87, 0x5d, - 0x3e, 0x5d, 0xeb, 0x77, 0xe7, 0x71, 0xc9, 0xdf, 0xc5, 0xd5, 0x92, 0xc1, 0x5e, 0xd0, 0x54, 0xbd, 0x90, 0xeb, 0x95, - 0xab, 0xe4, 0x6c, 0x2d, 0x3e, 0x09, 0x79, 0x23, 0x14, 0xed, 0x3d, 0xe3, 0xd7, 0xd0, 0x22, 0xb6, 0x45, 0x9d, 0x95, - 0xe0, 0x49, 0xe5, 0x71, 0xe2, 0x2a, 0x16, 0x40, 0x46, 0x4d, 0x34, 0x80, 0x8e, 0x1c, 0x34, 0xb4, 0x7b, 0x4d, 0x3b, - 0x96, 0x1b, 0x95, 0x45, 0x06, 0x96, 0xb0, 0xcf, 0xa1, 0x74, 0x40, 0x6c, 0x87, 0x70, 0x21, 0x70, 0xf5, 0xc4, 0xab, - 0x51, 0x03, 0xb1, 0x87, 0x96, 0xbe, 0xbb, 0x90, 0x62, 0xb5, 0x0c, 0xda, 0x65, 0x63, 0x98, 0xf0, 0x7a, 0x8d, 0x2e, - 0xc3, 0xa0, 0xf8, 0x2f, 0xdc, 0xa2, 0x44, 0x5c, 0xa4, 0x2c, 0x55, 0x46, 0x67, 0x3d, 0x94, 0x85, 0xe1, 0xb3, 0xa7, - 0xa3, 0xd4, 0x61, 0xe5, 0x3c, 0xb3, 0xbc, 0xad, 0xd2, 0xc4, 0xcf, 0xc1, 0x24, 0xcc, 0xaf, 0x65, 0x2e, 0x75, 0x5c, - 0xf2, 0x33, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0x9c, 0x2d, 0xb3, 0xb2, 0x92, 0xc5, 0x66, 0x61, 0xe0, 0x2e, 0x74, 0x59, - 0xad, 0x49, 0xbc, 0xf3, 0x3b, 0xf0, 0x79, 0x57, 0x01, 0x4c, 0x86, 0x4f, 0xc6, 0xa4, 0xd6, 0xd6, 0xf2, 0xd0, 0x40, - 0x6a, 0x7f, 0xab, 0x7d, 0xe2, 0x9e, 0x6d, 0xd7, 0x68, 0xd3, 0xcf, 0xa1, 0x5d, 0x23, 0x35, 0x4b, 0xa9, 0xe0, 0x7f, - 0xad, 0xb9, 0x89, 0x76, 0x10, 0x3a, 0x24, 0xef, 0xb0, 0x34, 0x86, 0x2e, 0x8a, 0x44, 0x2b, 0x24, 0x28, 0x45, 0x7d, - 0x5b, 0x2f, 0x54, 0x1b, 0x08, 0x51, 0xb7, 0xc5, 0x34, 0x7d, 0x8e, 0xa0, 0xed, 0x20, 0x25, 0xc1, 0xbd, 0x65, 0x63, - 0x7e, 0x75, 0x2d, 0x9f, 0x39, 0x74, 0x67, 0x31, 0xfb, 0x52, 0x86, 0xc1, 0x20, 0xfa, 0x52, 0x16, 0x36, 0xb9, 0x67, - 0x95, 0xaa, 0x2c, 0xc7, 0xc6, 0xf6, 0x72, 0x8a, 0xa6, 0x2c, 0xe1, 0xbb, 0x75, 0xd8, 0x5c, 0xfb, 0x14, 0x67, 0x9f, - 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x54, 0xd7, 0x85, 0x06, 0x2d, 0xd2, 0xda, - 0x9c, 0x5c, 0x5e, 0x82, 0x2c, 0xb3, 0x57, 0x8c, 0xe4, 0xa7, 0xbd, 0x28, 0x9f, 0x7f, 0xbc, 0xfc, 0xf8, 0xf1, 0xdd, - 0x01, 0x2a, 0x7c, 0x7a, 0x07, 0x1f, 0x14, 0x7a, 0xc0, 0xc1, 0x83, 0x6d, 0xa1, 0x55, 0xec, 0xf5, 0x1f, 0xf6, 0xac, - 0x2a, 0x5a, 0x0a, 0x72, 0x03, 0x0a, 0xe8, 0x55, 0xd1, 0x1a, 0xd6, 0xc2, 0x69, 0xb1, 0xfd, 0xcc, 0x4a, 0xbb, 0x14, - 0xa0, 0xee, 0x44, 0xd5, 0x1c, 0x29, 0xbd, 0x3c, 0x44, 0x5a, 0x08, 0xab, 0x3b, 0xb6, 0x5a, 0xd5, 0xb5, 0xd5, 0x64, - 0x51, 0x65, 0xe2, 0xf2, 0x0c, 0x77, 0xff, 0x57, 0x6d, 0x39, 0x33, 0xc3, 0x8a, 0x5e, 0xb4, 0x77, 0x5b, 0x03, 0xaa, - 0x4c, 0x1b, 0xe5, 0xea, 0x3d, 0x04, 0x02, 0xb3, 0xb2, 0x9e, 0xfa, 0x1f, 0x1b, 0x8b, 0x11, 0x3f, 0x4d, 0x01, 0xb9, - 0x01, 0x0f, 0xc4, 0x4e, 0xe2, 0x91, 0x69, 0xdf, 0x0d, 0xca, 0x4d, 0x8e, 0x93, 0x56, 0xc2, 0x6c, 0x38, 0x89, 0x26, - 0xc4, 0xc6, 0x97, 0xd0, 0x34, 0xec, 0xc7, 0xd1, 0xf3, 0x37, 0x1f, 0x5f, 0x7d, 0xfc, 0xf7, 0xd9, 0xd3, 0xd3, 0x8f, - 0xcf, 0x7f, 0x7c, 0xfb, 0xfe, 0xd5, 0xf3, 0x0f, 0x78, 0x42, 0x68, 0xc0, 0xca, 0x70, 0xab, 0xad, 0xa2, 0x9b, 0x65, - 0x45, 0xa2, 0x26, 0xcd, 0xa6, 0x28, 0xc4, 0x28, 0xcc, 0x6c, 0x8b, 0xfc, 0xe5, 0xcd, 0xb3, 0xe7, 0x2f, 0x5e, 0xbd, - 0x79, 0xfe, 0xac, 0xfd, 0xf5, 0x70, 0x52, 0x93, 0xda, 0xcd, 0x9c, 0x8e, 0x90, 0xc2, 0xed, 0x78, 0x75, 0xd0, 0x27, - 0xd4, 0xca, 0xfb, 0xf4, 0x29, 0x83, 0x15, 0xc9, 0x94, 0x9c, 0x1e, 0x7f, 0x7b, 0xf8, 0xbf, 0x6a, 0xe3, 0xed, 0x76, - 0xc0, 0x43, 0x20, 0x19, 0x53, 0xb2, 0x7e, 0x18, 0xd5, 0x8c, 0xaa, 0x97, 0x11, 0x44, 0x7a, 0xd1, 0xa5, 0x81, 0x0d, - 0x74, 0x4a, 0x55, 0x48, 0x85, 0xb3, 0x24, 0xae, 0xf8, 0xa5, 0x2c, 0x36, 0x51, 0x36, 0x6a, 0xa5, 0xd0, 0xc6, 0x02, - 0x88, 0x42, 0x10, 0x2c, 0x37, 0x92, 0x48, 0x4f, 0x11, 0x00, 0x6f, 0x08, 0xdc, 0xa8, 0xce, 0x5d, 0xb4, 0x80, 0x76, - 0xc1, 0x64, 0xb1, 0xdb, 0x75, 0x0c, 0x5a, 0x27, 0xed, 0x8b, 0xe6, 0x99, 0x22, 0x8a, 0x0b, 0x60, 0xcc, 0xe1, 0x78, - 0x53, 0x67, 0x17, 0x33, 0xc7, 0xdd, 0xa9, 0x8e, 0xfa, 0x09, 0xd6, 0x88, 0xee, 0xb5, 0x09, 0x2c, 0xd3, 0x3c, 0x0f, - 0xff, 0xbf, 0xf6, 0x9e, 0x36, 0xb9, 0x6d, 0x23, 0xd9, 0xff, 0x39, 0x05, 0x04, 0x7b, 0x6d, 0xc0, 0x06, 0x20, 0x80, - 0x14, 0x25, 0x9a, 0x14, 0xa8, 0xc4, 0xb6, 0x9c, 0x64, 0x57, 0x89, 0x53, 0xb6, 0xe2, 0xfd, 0xd0, 0xaa, 0x44, 0x90, - 0x1c, 0x92, 0x58, 0x83, 0x00, 0x0b, 0x00, 0x45, 0x2a, 0x34, 0xf6, 0x2c, 0x7b, 0x84, 0x77, 0x86, 0x3d, 0xd9, 0xab, - 0xee, 0x9e, 0x01, 0x06, 0x20, 0x48, 0x51, 0xb1, 0x93, 0xdd, 0x57, 0xf5, 0x2a, 0xb1, 0x4d, 0x0c, 0x66, 0x06, 0x3d, - 0x5f, 0xdd, 0x3d, 0xfd, 0x69, 0x57, 0x30, 0xae, 0x88, 0xf1, 0x5b, 0x29, 0xa5, 0x6d, 0xc6, 0x63, 0x2b, 0xc2, 0x4a, - 0x41, 0x3a, 0x2e, 0x21, 0xba, 0xd5, 0x02, 0xb0, 0x90, 0x29, 0xad, 0xaf, 0x98, 0x87, 0xa0, 0x13, 0x89, 0x30, 0x79, - 0x60, 0x32, 0xb8, 0xa5, 0xd6, 0xb4, 0x13, 0x97, 0x02, 0x5e, 0x46, 0xe5, 0x49, 0x3d, 0x8d, 0xcb, 0xcf, 0xb0, 0x8d, - 0x2b, 0x55, 0x50, 0x64, 0x5b, 0xae, 0x04, 0xa2, 0x85, 0xe1, 0x19, 0x7d, 0xde, 0x4a, 0xa3, 0x8b, 0x68, 0x29, 0xc4, - 0xc3, 0xa7, 0x71, 0x4d, 0x21, 0x9e, 0x8d, 0x8e, 0x77, 0x3a, 0xa4, 0x1f, 0x4e, 0xb6, 0x85, 0x08, 0x64, 0xc5, 0x04, - 0xe7, 0xcc, 0x69, 0x9f, 0xae, 0x4c, 0x37, 0x8f, 0xd7, 0x62, 0xe3, 0x65, 0x7d, 0x3f, 0x4f, 0xfe, 0x5a, 0x62, 0x2c, - 0x32, 0x3e, 0xf5, 0x72, 0xac, 0xd1, 0x9a, 0x6a, 0x7c, 0x7f, 0xb8, 0x7e, 0x2d, 0x77, 0x62, 0xd1, 0x23, 0xa3, 0x5c, - 0x98, 0xf5, 0x55, 0xd8, 0x8a, 0x0d, 0xb5, 0x3a, 0xc0, 0x48, 0xbc, 0x24, 0x86, 0x80, 0xe1, 0x97, 0x11, 0xe3, 0x7f, - 0x1b, 0x57, 0x31, 0x3e, 0x5a, 0xd9, 0xe5, 0x08, 0xff, 0xa7, 0xb7, 0xef, 0x2f, 0x41, 0x7b, 0xe5, 0xa1, 0xba, 0x79, - 0xad, 0x72, 0x4b, 0x15, 0x13, 0xf4, 0x41, 0x6a, 0x47, 0xf5, 0xe6, 0x40, 0x8f, 0xf1, 0x5e, 0x70, 0xb8, 0x32, 0x97, - 0xcb, 0xa5, 0x09, 0x76, 0xab, 0xe6, 0x22, 0x0e, 0x88, 0x07, 0x1c, 0xa9, 0x99, 0x40, 0xe4, 0xac, 0x82, 0xc8, 0x21, - 0xe8, 0x2d, 0xcf, 0x9a, 0xf2, 0x7e, 0x1a, 0x2d, 0xbf, 0x09, 0x02, 0x59, 0x38, 0x23, 0x58, 0x35, 0x2e, 0xaf, 0x28, - 0x21, 0x06, 0x0d, 0x74, 0x4c, 0x96, 0x9f, 0xdc, 0x70, 0xab, 0x80, 0xd1, 0xcd, 0xe0, 0xee, 0x86, 0x6b, 0x1e, 0xf2, - 0xa8, 0xc3, 0xef, 0xfb, 0xa7, 0x23, 0xff, 0x56, 0x41, 0x7e, 0xd2, 0x55, 0xc1, 0x65, 0x2b, 0x60, 0x83, 0x45, 0x9a, - 0x46, 0xa1, 0x19, 0x47, 0x4b, 0xb5, 0x77, 0x4a, 0x0f, 0xa2, 0x82, 0x47, 0x8f, 0xaa, 0xf2, 0xf5, 0x30, 0xf0, 0x87, - 0x1f, 0x5d, 0xf5, 0xf1, 0xda, 0x77, 0x7b, 0x15, 0xae, 0xd1, 0xce, 0xd4, 0x1e, 0xc0, 0xaa, 0x7c, 0x13, 0x04, 0xa7, - 0x87, 0xd4, 0xa2, 0x77, 0x7a, 0x38, 0xf2, 0x6f, 0x7b, 0x52, 0x02, 0x18, 0xae, 0x1d, 0x75, 0x79, 0xa0, 0xcd, 0xdc, - 0x9e, 0x2c, 0xc1, 0xc8, 0x0d, 0x43, 0xa6, 0x15, 0x57, 0x5c, 0x88, 0x28, 0x43, 0xf0, 0x6a, 0x43, 0x14, 0x9a, 0x07, - 0x70, 0xa1, 0xfb, 0xf4, 0x49, 0xcb, 0xad, 0x4d, 0xa7, 0x52, 0x28, 0x36, 0x54, 0xe6, 0x61, 0x15, 0x03, 0xe3, 0xc9, - 0xe8, 0x9a, 0x08, 0x18, 0x17, 0xe8, 0xc6, 0x30, 0x33, 0x30, 0x8f, 0x8e, 0x37, 0x07, 0xbd, 0x22, 0xff, 0x29, 0xdd, - 0x7b, 0x87, 0x90, 0x3b, 0x5b, 0x42, 0xdc, 0xba, 0xa4, 0x59, 0xa1, 0x53, 0xc8, 0xa3, 0x01, 0x82, 0x4a, 0x04, 0xbf, - 0x43, 0xda, 0x0e, 0x2d, 0xd0, 0x21, 0x77, 0x5b, 0x1e, 0x82, 0xc7, 0xcb, 0x44, 0xb6, 0x34, 0x31, 0x2f, 0x67, 0xa5, - 0x15, 0xea, 0x54, 0xd7, 0x4b, 0xc4, 0x86, 0x3c, 0x48, 0xb6, 0x2d, 0x19, 0x68, 0xea, 0xb4, 0xd4, 0xa8, 0xd0, 0x59, - 0xf0, 0xdd, 0x93, 0xd4, 0x43, 0xcc, 0xd0, 0xae, 0x12, 0x23, 0xba, 0x2e, 0x68, 0x53, 0x42, 0x88, 0xb2, 0x13, 0x65, - 0x45, 0x98, 0x66, 0x5a, 0xf5, 0xde, 0xe3, 0x75, 0x88, 0xc4, 0x2c, 0x71, 0x7b, 0xe5, 0x7d, 0x90, 0x7a, 0x03, 0x93, - 0x36, 0xb3, 0xaa, 0x7c, 0x3d, 0x1a, 0x04, 0xf9, 0x62, 0xd3, 0x21, 0x98, 0x7a, 0xe1, 0x28, 0x60, 0x97, 0xde, 0xe0, - 0x3b, 0xac, 0xf3, 0x7a, 0x10, 0xbc, 0x82, 0x0a, 0x99, 0xda, 0x7b, 0xbc, 0x26, 0x72, 0x5d, 0x87, 0xb0, 0x33, 0xda, - 0x02, 0xd5, 0xef, 0xf0, 0xc4, 0x4a, 0x2c, 0xa6, 0xd6, 0x08, 0x2c, 0x91, 0x58, 0xc2, 0xa8, 0x65, 0xc8, 0x78, 0x62, - 0x1f, 0xd8, 0x9b, 0x0a, 0x3f, 0xb5, 0x00, 0x57, 0x24, 0x4e, 0xb0, 0xbc, 0x33, 0x65, 0x60, 0x89, 0x94, 0xbe, 0x8b, - 0x96, 0x02, 0x52, 0x3e, 0x01, 0x14, 0x88, 0xf2, 0xec, 0x7d, 0xff, 0x54, 0x56, 0xfe, 0xa0, 0x84, 0x9c, 0xfa, 0x85, - 0x5f, 0x99, 0xaa, 0x14, 0x69, 0x9e, 0xe6, 0x2b, 0xb5, 0x77, 0x7a, 0x28, 0xd7, 0xee, 0xf5, 0x3b, 0xe7, 0xd2, 0xe0, - 0xb0, 0x57, 0x71, 0x3b, 0xbe, 0x2a, 0x1e, 0xb2, 0x6b, 0x05, 0xee, 0xc2, 0x19, 0x94, 0xc0, 0x1c, 0x95, 0x9b, 0x6c, - 0x90, 0x1f, 0x48, 0x8c, 0x58, 0x10, 0x28, 0xda, 0x3d, 0x02, 0x3f, 0x46, 0x7a, 0x27, 0x5f, 0x42, 0xb2, 0xbf, 0x14, - 0xbd, 0xf5, 0xf9, 0xbf, 0xc5, 0x94, 0xa0, 0x3c, 0x9b, 0x85, 0x49, 0x14, 0xab, 0x30, 0xcc, 0x6a, 0x76, 0x24, 0x45, - 0xca, 0xca, 0x86, 0x03, 0xae, 0x25, 0xab, 0x30, 0x61, 0x87, 0xd5, 0xa6, 0xd2, 0xb8, 0xfb, 0x7a, 0xf1, 0x43, 0xe1, - 0x83, 0xa9, 0x20, 0xad, 0x1c, 0xc0, 0xed, 0x59, 0xa7, 0xae, 0x1e, 0xfb, 0xc6, 0x9f, 0x23, 0x63, 0xe0, 0x19, 0x37, - 0x9e, 0xf1, 0x43, 0x78, 0x9d, 0xd5, 0x2e, 0x5e, 0x9e, 0x31, 0xce, 0x60, 0x5d, 0x0d, 0xe2, 0x2c, 0x95, 0xef, 0x15, - 0xbe, 0xc5, 0x2d, 0x43, 0x2e, 0xbd, 0x78, 0xc2, 0x44, 0xa2, 0x36, 0xf1, 0x56, 0x48, 0x08, 0x74, 0x69, 0x5a, 0x20, - 0x08, 0xd9, 0x01, 0x37, 0xa0, 0xf3, 0xad, 0x61, 0x1a, 0x07, 0x7f, 0x62, 0x77, 0x70, 0x9d, 0x4c, 0xd2, 0x68, 0x0e, - 0x92, 0x29, 0x6f, 0xc2, 0x35, 0x0d, 0x06, 0x30, 0x35, 0xfb, 0x7c, 0xee, 0xd3, 0x27, 0x26, 0xe5, 0x0e, 0x4b, 0xa3, - 0xc9, 0x24, 0x60, 0x9a, 0x94, 0x63, 0x2c, 0xff, 0xcc, 0xd9, 0x81, 0x2d, 0xe2, 0x53, 0xeb, 0xd9, 0xb6, 0x83, 0x55, - 0x70, 0x80, 0x42, 0xa7, 0x0f, 0x88, 0x8b, 0x4c, 0xa8, 0x90, 0x09, 0xd7, 0xc4, 0xb9, 0x28, 0x0e, 0xae, 0x39, 0x8a, - 0x16, 0x83, 0x80, 0x99, 0x78, 0x1a, 0xe0, 0x93, 0xeb, 0xc1, 0x62, 0x30, 0x08, 0x28, 0x29, 0x18, 0x44, 0x59, 0x8b, - 0x12, 0x94, 0x7e, 0x66, 0x7a, 0x17, 0x39, 0xb5, 0xb4, 0x0a, 0x3e, 0x58, 0x46, 0xc2, 0x6d, 0x81, 0x3e, 0x90, 0x82, - 0xa4, 0x73, 0xf3, 0x4c, 0xbb, 0x2a, 0xdc, 0x52, 0x58, 0xa2, 0x76, 0x6b, 0x58, 0x3a, 0xf7, 0x4a, 0x7d, 0x8f, 0x33, - 0xac, 0x78, 0xe1, 0x48, 0x79, 0x45, 0x7b, 0x57, 0x35, 0x54, 0x32, 0xf0, 0xe2, 0x39, 0xe4, 0x54, 0x43, 0x7d, 0xed, - 0x7b, 0x93, 0x30, 0x4a, 0x52, 0x7f, 0xa8, 0x5e, 0x77, 0x5f, 0xfb, 0xda, 0xd5, 0x2c, 0xd5, 0xf4, 0x6b, 0xe3, 0x5b, - 0x39, 0xdb, 0x97, 0xc0, 0x94, 0x98, 0xec, 0x6b, 0x4b, 0x1d, 0xf9, 0xf4, 0xec, 0xaa, 0x27, 0x30, 0x32, 0xd6, 0xf9, - 0xd6, 0x85, 0x5a, 0x95, 0xbc, 0x61, 0x98, 0x10, 0x12, 0xf2, 0x86, 0x7d, 0xab, 0x77, 0x49, 0xd4, 0xf2, 0xcd, 0x62, - 0x8d, 0x4c, 0x43, 0x5a, 0x10, 0x5f, 0x0c, 0x75, 0x2f, 0xfc, 0x43, 0xe9, 0xf9, 0x40, 0xf6, 0x6d, 0x28, 0x91, 0xf1, - 0xfe, 0x37, 0x65, 0x0e, 0xe4, 0xf1, 0x3a, 0xcd, 0xc0, 0xb0, 0x30, 0x8c, 0x52, 0x05, 0xe2, 0xb7, 0xc1, 0x07, 0xfb, - 0x55, 0x5b, 0x68, 0xde, 0xab, 0xa6, 0x67, 0x1c, 0x0b, 0xbc, 0x44, 0x5a, 0x8a, 0xf2, 0x49, 0x08, 0x37, 0x01, 0xa1, - 0x48, 0x4b, 0xd1, 0x9a, 0xb8, 0x07, 0x1e, 0x2c, 0x5f, 0x89, 0x7f, 0x93, 0xf0, 0x7e, 0x99, 0x9e, 0x3f, 0x5e, 0x27, - 0x67, 0x82, 0xa8, 0x7f, 0x9f, 0xe0, 0x5a, 0x02, 0xbb, 0xc2, 0xa9, 0x7c, 0xa6, 0x2a, 0x67, 0x82, 0x12, 0x61, 0xdd, - 0x12, 0x7a, 0xd5, 0x04, 0xbb, 0x1b, 0x8b, 0xc8, 0xf8, 0x3c, 0xfd, 0xb8, 0x60, 0xc0, 0x2a, 0x47, 0x0f, 0x42, 0x32, - 0xe5, 0xbc, 0x55, 0x0a, 0x76, 0xd5, 0x48, 0x30, 0x00, 0x73, 0x71, 0x1e, 0xa1, 0x9f, 0xdd, 0x00, 0x23, 0x09, 0x71, - 0xca, 0xc4, 0x18, 0x8d, 0x48, 0x4e, 0x15, 0xe7, 0x87, 0xf3, 0x45, 0x8a, 0xf1, 0xe7, 0x01, 0x00, 0x96, 0xa9, 0x0a, - 0x5e, 0x12, 0x01, 0xd7, 0x17, 0x97, 0x9f, 0x4c, 0x55, 0xfc, 0xd1, 0x66, 0x19, 0x97, 0xc7, 0x00, 0x8e, 0xc3, 0x61, - 0xa0, 0xf6, 0x06, 0x1e, 0x63, 0x3e, 0x8c, 0xa1, 0x51, 0x24, 0x6f, 0xd1, 0x86, 0x68, 0xe5, 0x50, 0x83, 0x40, 0x86, - 0xd4, 0x4f, 0x57, 0x0b, 0x6a, 0x07, 0x0b, 0x31, 0xa9, 0x4b, 0xc3, 0xec, 0x83, 0x24, 0xf2, 0x0c, 0xe6, 0xce, 0x7d, - 0xbc, 0xf6, 0x72, 0x03, 0x3a, 0xf5, 0x52, 0x25, 0xeb, 0xb9, 0x3e, 0x4e, 0x43, 0x3f, 0xbb, 0x29, 0xdc, 0x59, 0x8b, - 0xf1, 0xc2, 0x96, 0xa4, 0x72, 0x05, 0xed, 0xd9, 0x5c, 0x6e, 0xb5, 0x36, 0x8f, 0xfd, 0x99, 0x17, 0xdf, 0x91, 0x91, - 0x9b, 0x21, 0x5b, 0xc2, 0xe9, 0xaa, 0x42, 0xf4, 0x80, 0x26, 0x80, 0x48, 0x83, 0xaa, 0x7c, 0x9d, 0x97, 0x31, 0x3e, - 0xda, 0xdc, 0xd2, 0x07, 0xbe, 0x75, 0xa3, 0x3e, 0x67, 0x16, 0x49, 0x19, 0xa9, 0x49, 0x57, 0x4b, 0xb6, 0x0c, 0x2f, - 0x29, 0x0f, 0x2f, 0x2c, 0x6f, 0x34, 0x1c, 0x0c, 0x51, 0x0a, 0x82, 0x1b, 0x47, 0x86, 0xa9, 0x2e, 0xeb, 0x57, 0x94, - 0xde, 0xfd, 0xae, 0xcb, 0xc1, 0x60, 0x39, 0x42, 0x58, 0x8e, 0x1a, 0x01, 0xac, 0x27, 0x56, 0x04, 0x78, 0x11, 0xe0, - 0x42, 0x62, 0xe4, 0x40, 0x28, 0x0b, 0xa6, 0x92, 0x6f, 0xa1, 0x18, 0x8e, 0x06, 0xc1, 0x4e, 0x47, 0x23, 0x76, 0xdd, - 0x08, 0x5b, 0xc5, 0xd9, 0xe9, 0x21, 0xd5, 0x26, 0xa2, 0x48, 0x95, 0x60, 0x1a, 0x62, 0x18, 0x61, 0x31, 0x0b, 0x90, - 0x06, 0xdc, 0x75, 0x8a, 0x8b, 0x8e, 0x35, 0x43, 0xe5, 0xb3, 0x73, 0x56, 0x66, 0x78, 0xb0, 0x95, 0xda, 0x3b, 0xc5, - 0xc4, 0x9e, 0x40, 0xd6, 0x21, 0xf4, 0xd5, 0xe9, 0x21, 0x3d, 0x2a, 0x95, 0x13, 0x51, 0x74, 0x22, 0xa4, 0x8e, 0x1d, - 0xde, 0xc1, 0x83, 0x8e, 0x4a, 0x92, 0xb2, 0x39, 0x94, 0x7a, 0x99, 0xaa, 0xcc, 0x38, 0x83, 0xc5, 0x63, 0xec, 0x41, - 0x00, 0x1e, 0x1b, 0x1c, 0x1f, 0x54, 0x65, 0xe6, 0xad, 0x70, 0xe4, 0xe2, 0x8d, 0xb7, 0xd2, 0x1c, 0xfe, 0xaa, 0x38, - 0x6b, 0x49, 0xf9, 0xac, 0x0d, 0xf9, 0xe2, 0x82, 0x77, 0x9d, 0x60, 0xac, 0xb5, 0x29, 0x5a, 0x2d, 0xd5, 0x2c, 0xee, - 0x54, 0x2c, 0xee, 0x68, 0xcb, 0xe2, 0x8e, 0x76, 0x2c, 0x6e, 0xc0, 0x17, 0x52, 0xc9, 0xa7, 0x2e, 0x46, 0x8f, 0xe9, - 0x7c, 0xf2, 0x38, 0x3f, 0xd2, 0xe1, 0xe7, 0x0c, 0xe7, 0xc9, 0x4c, 0x02, 0xb0, 0x18, 0xde, 0x32, 0x57, 0x75, 0xf3, - 0x22, 0x4d, 0xc4, 0xe6, 0xc0, 0xf3, 0x53, 0x37, 0x94, 0x24, 0x03, 0x5a, 0x50, 0x1d, 0x2f, 0xec, 0x52, 0x6c, 0x68, - 0x68, 0xd3, 0x2d, 0x23, 0x9d, 0xee, 0x18, 0xe9, 0xb0, 0x74, 0x74, 0xf9, 0xb0, 0xe9, 0x10, 0xca, 0x83, 0x82, 0x3d, - 0x08, 0x5e, 0x14, 0xb8, 0x65, 0xca, 0xfb, 0x70, 0x3b, 0x8e, 0x95, 0x76, 0xd4, 0xdc, 0x4b, 0x92, 0x65, 0x14, 0x83, - 0x19, 0x02, 0x74, 0xf3, 0xb0, 0x2d, 0x35, 0xf3, 0x43, 0x1e, 0xe1, 0x6c, 0xeb, 0x66, 0x2a, 0xde, 0xcb, 0x5b, 0xaa, - 0xd1, 0x6a, 0x51, 0x8d, 0xb9, 0x97, 0xa6, 0x2c, 0xc6, 0x49, 0xf7, 0x20, 0x15, 0xc6, 0x7f, 0xc9, 0x36, 0xab, 0xc1, - 0x21, 0x81, 0x84, 0xd5, 0x11, 0x43, 0xcf, 0x81, 0x05, 0x23, 0xbd, 0x63, 0xa8, 0xaf, 0xa5, 0x68, 0xa9, 0x71, 0x3e, - 0xf1, 0x3f, 0xe2, 0x71, 0xd5, 0x62, 0xc9, 0x9f, 0xd7, 0x39, 0xd6, 0xad, 0xb9, 0x37, 0x7a, 0x0f, 0xd6, 0x2e, 0x5a, - 0xc3, 0x00, 0xcf, 0x15, 0x39, 0x36, 0x6a, 0x4c, 0x3c, 0xe1, 0xb0, 0x40, 0x92, 0x88, 0x25, 0xb9, 0x5d, 0x30, 0x84, - 0x14, 0xf0, 0xcc, 0xf1, 0xf5, 0xba, 0x91, 0x1d, 0x4e, 0x7c, 0x7d, 0x03, 0x6b, 0x02, 0x6a, 0x0b, 0xdc, 0x5e, 0x2e, - 0x74, 0x0b, 0x0c, 0xe7, 0x58, 0x07, 0x75, 0xe8, 0x15, 0x24, 0x3d, 0xb7, 0xc5, 0x65, 0xba, 0x1f, 0x03, 0xd5, 0x02, - 0xe5, 0xe1, 0x93, 0x09, 0xfe, 0x72, 0xae, 0xb3, 0x27, 0x03, 0xfc, 0xd5, 0xb8, 0xce, 0x55, 0x55, 0x15, 0x29, 0x82, - 0x34, 0x66, 0xb5, 0x57, 0xda, 0x4f, 0x64, 0x94, 0xfd, 0x80, 0x6d, 0xc3, 0x17, 0xf8, 0xd1, 0xe3, 0x75, 0x02, 0x61, - 0x08, 0xe4, 0x31, 0x84, 0x56, 0xac, 0x67, 0xb5, 0xe5, 0x93, 0x2d, 0xe5, 0x03, 0xfd, 0x77, 0x26, 0xfc, 0xb8, 0x4b, - 0xa2, 0x82, 0xa6, 0x94, 0x65, 0x20, 0x37, 0x03, 0x3f, 0xf4, 0xe2, 0xbb, 0x1b, 0xba, 0x85, 0x68, 0x92, 0x90, 0xf7, - 0xa0, 0x10, 0x0e, 0xdc, 0x95, 0x6d, 0x40, 0x52, 0x49, 0x41, 0x75, 0xc7, 0x09, 0xbd, 0xfb, 0xa7, 0x58, 0xe2, 0xef, - 0x4a, 0xd7, 0x58, 0xbe, 0x20, 0xa5, 0x0f, 0xdd, 0x3c, 0x5e, 0x6b, 0x6c, 0xb3, 0x9b, 0xca, 0x68, 0x2b, 0x0c, 0x24, - 0x2c, 0x0f, 0x5e, 0x89, 0x67, 0x23, 0xbf, 0x83, 0x46, 0x1e, 0x83, 0x68, 0x65, 0x3e, 0x5e, 0xa7, 0x67, 0xea, 0xcc, - 0x8b, 0x3f, 0xb2, 0x91, 0x39, 0xf4, 0xe3, 0x61, 0x00, 0xcc, 0xe3, 0x20, 0xf0, 0xc2, 0x8f, 0xfc, 0xd1, 0x8c, 0x16, - 0x29, 0x9a, 0x6d, 0xdd, 0x7b, 0x83, 0x16, 0x73, 0x42, 0x82, 0x44, 0xe4, 0x6a, 0x6b, 0x66, 0x41, 0x79, 0xdf, 0x17, - 0xd7, 0xfa, 0x82, 0x51, 0x2c, 0x6a, 0x19, 0xe0, 0x75, 0x00, 0x96, 0x64, 0x10, 0xc6, 0xc1, 0x50, 0x71, 0xbd, 0x54, - 0x43, 0x1e, 0x2a, 0xe9, 0xd1, 0xf2, 0x3c, 0xc4, 0x37, 0xd8, 0xc3, 0xaf, 0xff, 0x1c, 0x94, 0x3c, 0xe4, 0x73, 0x79, - 0x2f, 0x9f, 0x37, 0x42, 0x28, 0x35, 0xc9, 0x7d, 0xf0, 0x01, 0x1f, 0xe7, 0x0c, 0xe6, 0xf6, 0x4f, 0xcb, 0x8d, 0xbd, - 0x24, 0x59, 0xcc, 0xd8, 0x88, 0x94, 0x61, 0x67, 0x05, 0x50, 0xe5, 0x7b, 0x88, 0x0c, 0xd8, 0xdf, 0x17, 0x8d, 0x93, - 0xa3, 0x57, 0x60, 0xc6, 0x07, 0x0c, 0x65, 0x34, 0x1e, 0xab, 0x85, 0x28, 0xe0, 0x9e, 0x66, 0xce, 0xd1, 0xdf, 0x17, - 0x6f, 0xce, 0xed, 0x37, 0x79, 0xe3, 0x10, 0x18, 0x63, 0x61, 0x93, 0xc4, 0xf9, 0x62, 0x09, 0x5e, 0x31, 0xa2, 0xb1, - 0x17, 0x6e, 0x1f, 0xce, 0x55, 0x69, 0x8b, 0xcf, 0x19, 0x1b, 0x01, 0xc3, 0x6d, 0x6c, 0x94, 0xde, 0x04, 0xec, 0x96, - 0xe5, 0xf6, 0x4e, 0x9b, 0x1f, 0xab, 0x69, 0x81, 0x01, 0x59, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0xfa, 0x38, - 0x06, 0x3e, 0x72, 0xf9, 0x88, 0x55, 0x8e, 0x54, 0xdf, 0x50, 0x25, 0x00, 0xb6, 0x42, 0x76, 0xb6, 0xa5, 0xbc, 0x03, - 0x88, 0x7a, 0x0b, 0x6c, 0x86, 0xa3, 0x77, 0x20, 0x81, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0xb6, - 0xcd, 0x58, 0x9d, 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x01, 0x40, 0x5f, 0x18, 0x21, 0xae, 0xaa, 0x5d, 0x1b, 0xa5, - 0x3c, 0xf2, 0x01, 0xa6, 0x77, 0x0f, 0x59, 0x92, 0x6c, 0x9d, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, - 0xa2, 0xdc, 0xb0, 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x99, 0x71, 0x23, 0xce, 0x78, 0x32, - 0x50, 0xb9, 0x81, 0xdd, 0xb6, 0xf7, 0x4b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0xb5, 0xa0, 0x69, 0x25, 0xd4, 0xbb, 0x21, - 0x55, 0xc2, 0x0e, 0x04, 0x4c, 0x15, 0xfc, 0xca, 0xc6, 0x63, 0x36, 0x4c, 0x13, 0x5d, 0xc8, 0x98, 0xf2, 0x90, 0xea, - 0xa0, 0xb4, 0x3b, 0x70, 0xd5, 0x1f, 0x21, 0xb0, 0x8c, 0x88, 0x3c, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xfa, 0x69, 0xa2, - 0x1e, 0xcb, 0x53, 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x9a, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0xa9, - 0xe7, 0x6e, 0x54, 0xb4, 0xeb, 0xf8, 0xae, 0x9d, 0x37, 0x2d, 0xc7, 0xce, 0x54, 0x03, 0x1c, 0x9a, 0x3f, 0x56, 0xb6, - 0x31, 0x11, 0x28, 0x57, 0xbd, 0x78, 0xfb, 0xea, 0x4f, 0xe7, 0xaf, 0xf7, 0xc5, 0x08, 0xd8, 0x65, 0x13, 0xba, 0x5c, - 0x84, 0x3b, 0x3a, 0xfd, 0xf9, 0xc7, 0x87, 0x75, 0xdb, 0x70, 0x5e, 0x38, 0xaa, 0x41, 0x36, 0xe8, 0x12, 0x5e, 0x1c, - 0x46, 0xb7, 0x2c, 0xfe, 0xec, 0x69, 0x90, 0x3b, 0xaf, 0x07, 0xf7, 0xed, 0x4f, 0xe7, 0x3f, 0xee, 0x0d, 0xea, 0xb1, - 0x63, 0x03, 0x6e, 0x4f, 0xa3, 0xf9, 0x03, 0x46, 0xd7, 0x54, 0x0d, 0x75, 0x18, 0x44, 0x09, 0xdb, 0x02, 0xc1, 0xab, - 0x8b, 0xb7, 0xef, 0x71, 0xba, 0x0a, 0x16, 0x84, 0xba, 0xfa, 0xbc, 0xc1, 0xff, 0xf4, 0xee, 0xfc, 0xfd, 0x7b, 0xd5, - 0xc0, 0x94, 0xdc, 0x89, 0xdc, 0x3b, 0xdf, 0xc4, 0xf7, 0x50, 0x9c, 0xda, 0xbd, 0x4e, 0x54, 0x8d, 0x2e, 0xd2, 0xe5, - 0xd1, 0x50, 0xd9, 0xc6, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x7b, 0x8d, 0xab, 0x06, 0x1f, 0xed, 0x26, - 0xa9, 0xa5, 0x92, 0x99, 0x1f, 0xde, 0xd4, 0x94, 0x7a, 0xab, 0x9a, 0x52, 0xb8, 0x3e, 0x6e, 0xe0, 0xc7, 0x45, 0x34, - 0x93, 0xd8, 0x11, 0xb6, 0xba, 0x7f, 0xba, 0xa4, 0x3b, 0xdc, 0x67, 0x00, 0xcd, 0x53, 0xaa, 0x54, 0xa1, 0xae, 0x29, - 0xe6, 0x17, 0xaf, 0x7c, 0x6e, 0x87, 0x01, 0x58, 0xde, 0x33, 0x59, 0x0d, 0x59, 0x66, 0x55, 0xb9, 0xdf, 0x8c, 0x5b, - 0xb9, 0x15, 0x50, 0x33, 0x52, 0xdd, 0x70, 0x9a, 0x32, 0xf7, 0x46, 0x60, 0xce, 0x6e, 0x0e, 0xa2, 0x34, 0x8d, 0x66, - 0x1d, 0xc7, 0x9e, 0xaf, 0x54, 0xa5, 0x2b, 0x84, 0x1d, 0xdc, 0xda, 0xbe, 0xf3, 0xef, 0x7f, 0x55, 0xd0, 0x3c, 0x95, - 0xdf, 0xa4, 0x6c, 0x36, 0x67, 0xb1, 0x97, 0x2e, 0x62, 0x96, 0x29, 0xff, 0xfe, 0x9f, 0x57, 0x95, 0x8b, 0x7d, 0x57, - 0x6e, 0x43, 0x2c, 0xbd, 0xdc, 0xe4, 0x26, 0x88, 0x96, 0x07, 0x85, 0x5f, 0xdd, 0x3d, 0x95, 0xa7, 0xfe, 0x64, 0x9a, - 0xd7, 0x3e, 0x4b, 0x77, 0x8c, 0x4d, 0x40, 0x4f, 0xfa, 0x00, 0xe5, 0x22, 0x5a, 0x76, 0xfe, 0xfd, 0xaf, 0x5c, 0x60, - 0x73, 0xef, 0xae, 0xab, 0x07, 0xb4, 0xbc, 0xa2, 0xf5, 0x75, 0x36, 0x96, 0x18, 0xde, 0x6f, 0x2c, 0xf0, 0x46, 0x21, - 0xed, 0xca, 0x4d, 0xdd, 0xdc, 0x8e, 0x31, 0x7d, 0xe7, 0x4f, 0xa6, 0x9f, 0x3b, 0x28, 0x98, 0xd0, 0x7b, 0x47, 0x05, - 0x95, 0xbe, 0xc0, 0xb0, 0xfa, 0x9d, 0xfd, 0x17, 0xec, 0x33, 0xc7, 0x75, 0xdf, 0x90, 0xbe, 0xc4, 0x68, 0xb8, 0xe4, - 0xf6, 0x7d, 0xbf, 0x9f, 0xa7, 0xa4, 0x95, 0xdb, 0x83, 0x67, 0xe0, 0xd9, 0x46, 0x09, 0x67, 0x2f, 0x3a, 0xb6, 0x4e, - 0x21, 0x7b, 0xf6, 0x98, 0x10, 0xb4, 0x71, 0xaf, 0x99, 0x8e, 0xed, 0xf8, 0x9a, 0x5c, 0xd5, 0x36, 0xbe, 0xbd, 0x81, - 0xac, 0xa1, 0x14, 0xd3, 0x99, 0xe6, 0x5a, 0x43, 0xa3, 0x1e, 0x9c, 0x65, 0xec, 0xcd, 0x49, 0x49, 0xa0, 0xa0, 0xc6, - 0x04, 0x84, 0x2e, 0x95, 0x5b, 0xf4, 0xad, 0x17, 0xdc, 0xee, 0x77, 0xa1, 0xda, 0x4e, 0xc1, 0x90, 0x34, 0xff, 0xe7, - 0x88, 0x37, 0xd2, 0xe5, 0x07, 0xd3, 0xee, 0xa5, 0x97, 0xb2, 0xf8, 0x66, 0x0a, 0x3e, 0xbd, 0x42, 0x7a, 0x00, 0xd1, - 0x72, 0x77, 0x21, 0xe5, 0x12, 0x5b, 0x5a, 0x83, 0x46, 0x0b, 0x0c, 0xf7, 0xeb, 0x70, 0xf7, 0x17, 0xc2, 0xdc, 0x9d, - 0x73, 0xf0, 0xba, 0xfc, 0xcd, 0xb0, 0xf7, 0x2e, 0xca, 0xf4, 0xff, 0xd8, 0xfb, 0xbf, 0x11, 0x7b, 0xef, 0xfc, 0xce, - 0xaf, 0x59, 0xd8, 0xff, 0x03, 0x58, 0xbe, 0xc3, 0xdc, 0x73, 0x8e, 0xe9, 0x35, 0xcd, 0x73, 0x85, 0x72, 0x55, 0xc6, - 0xab, 0x1b, 0x0a, 0x56, 0x1e, 0x52, 0x8d, 0x5b, 0x0e, 0x7a, 0x88, 0xec, 0x77, 0x1c, 0xe5, 0xdf, 0x1e, 0xd1, 0x27, - 0x94, 0x87, 0x4a, 0xc2, 0xf4, 0x9d, 0x73, 0x23, 0x29, 0x8d, 0xc4, 0x5b, 0x7a, 0x77, 0xfb, 0xe0, 0x1d, 0x01, 0xec, - 0x37, 0x4b, 0xef, 0xae, 0x0e, 0xd8, 0xad, 0xe8, 0xb5, 0xfa, 0xb1, 0x33, 0xf0, 0xe5, 0xe9, 0xa0, 0x23, 0x8f, 0xd1, - 0x4f, 0x58, 0x7a, 0x06, 0x85, 0xee, 0xe3, 0xf5, 0x41, 0xb5, 0x62, 0xd6, 0x07, 0x2f, 0x67, 0x09, 0xf0, 0xa8, 0x04, - 0xb8, 0x9f, 0xdc, 0x44, 0xe1, 0x43, 0x20, 0xff, 0x09, 0x84, 0x3f, 0xbf, 0x1a, 0x74, 0xfc, 0xdc, 0x06, 0xec, 0x58, - 0x5a, 0x05, 0x1e, 0x0b, 0xab, 0xd0, 0x77, 0xeb, 0x65, 0xf5, 0x15, 0x42, 0x8b, 0x34, 0x96, 0x11, 0xa1, 0x55, 0x40, - 0xaf, 0xa2, 0x80, 0x8e, 0xab, 0x42, 0x72, 0xfd, 0x70, 0x1c, 0x7b, 0x31, 0x1b, 0x6d, 0xbf, 0x02, 0x94, 0x2c, 0x95, - 0xef, 0xac, 0x64, 0x31, 0x9f, 0x47, 0x71, 0x9a, 0xdc, 0x60, 0x34, 0x96, 0x99, 0x0f, 0x17, 0x0a, 0xc8, 0x1b, 0x96, - 0xc7, 0xe6, 0x3d, 0xaf, 0x93, 0x6f, 0x1b, 0xcc, 0x2d, 0xa7, 0xd4, 0xe0, 0x3e, 0x36, 0x06, 0xf7, 0xd2, 0x99, 0x4a, - 0xfa, 0x8b, 0xa9, 0x95, 0xc6, 0xfe, 0x4c, 0xd3, 0x0d, 0xc7, 0xd6, 0x75, 0x21, 0x5f, 0x99, 0xba, 0xbd, 0x03, 0x8a, - 0x29, 0x3c, 0xd5, 0x21, 0x36, 0x21, 0xfa, 0xad, 0x80, 0xad, 0xdc, 0xcb, 0xc5, 0x78, 0xcc, 0x62, 0x4d, 0x04, 0x5f, - 0x84, 0xe8, 0xaf, 0x64, 0x0c, 0x08, 0xde, 0x8c, 0x1f, 0x7c, 0xb6, 0x84, 0x2c, 0x4f, 0x45, 0xf0, 0x74, 0xf0, 0xe8, - 0x24, 0x13, 0x72, 0xc8, 0x20, 0x97, 0x36, 0x1b, 0xda, 0xe8, 0xd9, 0x91, 0x31, 0x85, 0x90, 0x4b, 0x85, 0x13, 0x3c, - 0x46, 0xf3, 0xf3, 0xc3, 0xb4, 0x8d, 0x5f, 0x80, 0x0e, 0xe0, 0xf0, 0x06, 0x6e, 0xee, 0xfd, 0xa4, 0x0c, 0xf3, 0x0e, - 0xa7, 0x6e, 0x2f, 0x78, 0xee, 0x92, 0x9e, 0x07, 0xed, 0xf6, 0x5e, 0x4d, 0xbd, 0xf8, 0x55, 0x34, 0x62, 0x08, 0xe8, - 0x20, 0x8d, 0xc0, 0x27, 0x53, 0x0a, 0xb6, 0x83, 0xb1, 0x76, 0xcc, 0x52, 0xfc, 0x9d, 0x43, 0x28, 0xba, 0x91, 0x8b, - 0xdc, 0xe7, 0x8f, 0x0f, 0x0d, 0x38, 0x69, 0xf5, 0x2b, 0x2d, 0x16, 0x8d, 0x2f, 0x75, 0xed, 0x2b, 0x79, 0xb7, 0xbe, - 0xf2, 0xe2, 0xd8, 0x67, 0xb1, 0xa2, 0x7d, 0xf7, 0x8b, 0x2e, 0x6f, 0xda, 0x92, 0x42, 0x87, 0x6b, 0x99, 0x15, 0x8c, - 0x39, 0x37, 0xf6, 0x59, 0x30, 0x72, 0xd5, 0x21, 0x35, 0xcc, 0x95, 0x37, 0xcd, 0xb6, 0x6d, 0xdb, 0x5c, 0x61, 0xea, - 0xd0, 0x4f, 0x50, 0x98, 0xc2, 0x4f, 0x78, 0x28, 0x89, 0x17, 0xdb, 0xc4, 0x45, 0x6c, 0x90, 0xb3, 0x5a, 0x08, 0xdf, - 0x51, 0xd4, 0x9e, 0x87, 0xc0, 0xc6, 0xa3, 0xfb, 0x08, 0xd0, 0x1c, 0x01, 0x56, 0x01, 0x53, 0x05, 0xa0, 0xd6, 0x43, - 0x00, 0xba, 0xf4, 0x67, 0x7e, 0x38, 0x49, 0xb6, 0x42, 0x84, 0x6a, 0xd3, 0x12, 0x3c, 0x29, 0xb5, 0x50, 0x15, 0x5c, - 0xc3, 0x69, 0x14, 0x40, 0xb6, 0x21, 0x95, 0x59, 0x13, 0x4b, 0x79, 0x61, 0xdb, 0xb6, 0x61, 0x1e, 0x41, 0x5e, 0xbf, - 0xd6, 0xb1, 0x6d, 0x98, 0xf0, 0x97, 0x65, 0x59, 0x35, 0xf2, 0xd8, 0xee, 0xcc, 0x0f, 0x4d, 0x7a, 0x6c, 0xd8, 0xfb, - 0xc1, 0x7b, 0xaf, 0x55, 0x6f, 0xc2, 0x75, 0x63, 0x83, 0xdc, 0x41, 0x54, 0x1b, 0xb8, 0x49, 0xd9, 0xd6, 0xcd, 0xa2, - 0xb0, 0x4a, 0x3c, 0xea, 0x45, 0x85, 0x18, 0x0d, 0xca, 0x6f, 0x91, 0x2d, 0x8d, 0xab, 0xd9, 0x2a, 0xd4, 0xef, 0x39, - 0x58, 0x1d, 0xe5, 0x55, 0xb4, 0x08, 0x46, 0x68, 0x0e, 0x05, 0xb6, 0xcb, 0x4a, 0x61, 0x15, 0x5a, 0x49, 0x29, 0x05, - 0x19, 0xc3, 0x31, 0x9d, 0xda, 0x7b, 0x24, 0x4e, 0x51, 0xac, 0x3d, 0xc5, 0x29, 0xbe, 0xaa, 0xdb, 0x82, 0xd7, 0x4f, - 0x21, 0x6a, 0xd0, 0x1e, 0x0d, 0xf8, 0xbe, 0x80, 0xfa, 0xc1, 0x3e, 0xf5, 0xc5, 0xba, 0x5d, 0x3f, 0xa5, 0xd0, 0xb2, - 0xde, 0xa7, 0x4f, 0x07, 0xc3, 0x4f, 0x9f, 0x0e, 0x36, 0xf2, 0x71, 0x6c, 0x1f, 0x21, 0x6d, 0x0c, 0xc6, 0x03, 0x89, - 0x40, 0x74, 0x20, 0x02, 0xfa, 0x7b, 0x28, 0xef, 0x78, 0x3c, 0x26, 0x15, 0x3d, 0x0d, 0x0d, 0xfe, 0x41, 0x7a, 0x0c, - 0xb2, 0xca, 0xa4, 0x4c, 0x5d, 0x8f, 0xc4, 0x3c, 0x9f, 0x3e, 0xf1, 0xe3, 0x66, 0x8c, 0xdc, 0x61, 0x5e, 0xe4, 0xa8, - 0xc6, 0xc2, 0x0d, 0xf2, 0x47, 0x15, 0x41, 0x5e, 0x70, 0x8c, 0x59, 0x40, 0xbc, 0xf4, 0xe2, 0x50, 0x06, 0xf8, 0xc7, - 0x48, 0xe1, 0x9f, 0x55, 0x78, 0xdc, 0xd3, 0x51, 0x75, 0x35, 0xc6, 0x2e, 0xd3, 0x16, 0x84, 0x03, 0x85, 0xa5, 0x9b, - 0xd4, 0xc1, 0xa5, 0xc0, 0xf6, 0x98, 0xfc, 0x54, 0x0c, 0x10, 0xbd, 0xa8, 0xf1, 0xe4, 0x8e, 0xc4, 0xb0, 0xde, 0x79, - 0xcb, 0xce, 0x42, 0x3c, 0x9c, 0x93, 0x49, 0x7c, 0x67, 0x9c, 0x7b, 0x27, 0xcf, 0xc9, 0xb7, 0x70, 0xe2, 0x7e, 0x1b, - 0x6b, 0x73, 0x23, 0x35, 0x54, 0x41, 0x46, 0x54, 0xdd, 0x98, 0xd5, 0x85, 0x51, 0xed, 0xce, 0x78, 0x50, 0x19, 0x4d, - 0x6c, 0x85, 0x9b, 0x31, 0xfa, 0x2a, 0x84, 0xc3, 0x3b, 0x0c, 0x93, 0x5c, 0xbc, 0x27, 0x50, 0x6e, 0x78, 0x8e, 0xbd, - 0x91, 0xfc, 0x0a, 0x16, 0x5c, 0x35, 0xc6, 0xba, 0x41, 0x3e, 0x00, 0x93, 0x2f, 0x69, 0xee, 0x4f, 0x91, 0x93, 0x67, - 0x52, 0x50, 0x57, 0xe1, 0x00, 0x70, 0x53, 0x71, 0x00, 0xa8, 0x99, 0x4f, 0x25, 0x66, 0xc9, 0x3c, 0x0a, 0xe1, 0xae, - 0x78, 0x53, 0x78, 0x75, 0xdd, 0x6c, 0x7a, 0x75, 0xd5, 0x34, 0xc5, 0x37, 0xd4, 0x0e, 0x54, 0xd2, 0x97, 0x7f, 0xa9, - 0x58, 0xe8, 0x0b, 0x52, 0x8f, 0xb9, 0xc8, 0xcf, 0xb7, 0xf9, 0x6f, 0x7f, 0x7f, 0xbf, 0xff, 0xf6, 0xc5, 0x5e, 0xfe, - 0xdb, 0xdf, 0x7f, 0x71, 0xff, 0xed, 0x73, 0xd9, 0x7f, 0x1b, 0x48, 0xf0, 0x39, 0xdb, 0xcb, 0x5d, 0x56, 0xb8, 0xb4, - 0x44, 0xcb, 0xc4, 0x75, 0xb8, 0x66, 0x2d, 0x19, 0x4e, 0x19, 0x98, 0x2a, 0x70, 0x56, 0x37, 0x88, 0x26, 0xe0, 0xd5, - 0xba, 0xdd, 0x6f, 0xf5, 0x4b, 0x79, 0xad, 0x06, 0xd1, 0x44, 0x95, 0xb2, 0xb1, 0x85, 0x22, 0x1b, 0x1b, 0x44, 0xa0, - 0xfb, 0xfb, 0xca, 0x79, 0x79, 0xe5, 0x74, 0x9b, 0x0e, 0x44, 0x33, 0x05, 0xed, 0x33, 0x16, 0xd8, 0xdd, 0x66, 0x13, - 0x0a, 0x96, 0x52, 0x41, 0x03, 0x0a, 0x7c, 0xa9, 0xa0, 0x05, 0x05, 0x43, 0xa9, 0xe0, 0x18, 0x0a, 0x46, 0x52, 0xc1, - 0x09, 0x14, 0xdc, 0xaa, 0xd9, 0x55, 0x98, 0x7b, 0xa7, 0x9f, 0xe8, 0xd7, 0xa5, 0x44, 0x9c, 0xb9, 0xa9, 0x84, 0xa8, - 0x72, 0x62, 0x88, 0xac, 0x10, 0xe6, 0x91, 0xce, 0x79, 0xb4, 0xfe, 0x57, 0x7d, 0xc0, 0xbc, 0x60, 0x39, 0x62, 0x80, - 0xdd, 0x0d, 0xd5, 0x6c, 0x8a, 0xd7, 0x6a, 0x27, 0xf7, 0xe6, 0xb6, 0x8d, 0x86, 0xf0, 0x8e, 0xee, 0x60, 0xac, 0x0e, - 0x51, 0xb9, 0xf5, 0x7c, 0x9a, 0x87, 0x88, 0x5e, 0xb8, 0x45, 0xc8, 0x9b, 0x26, 0x24, 0xca, 0xe1, 0xbc, 0x1a, 0xd3, - 0xc0, 0x5e, 0x06, 0x22, 0x9a, 0x88, 0x53, 0x24, 0x3e, 0xa0, 0xa0, 0xcb, 0x7b, 0xd7, 0x2b, 0x78, 0x38, 0x1e, 0x50, - 0x9d, 0xa0, 0x9f, 0xe5, 0x71, 0xaa, 0x49, 0x97, 0xba, 0x30, 0x52, 0x6f, 0xd2, 0x99, 0x1a, 0x64, 0x48, 0xd5, 0x99, - 0x40, 0xe2, 0x91, 0xb3, 0x51, 0x67, 0x6e, 0x2c, 0xa7, 0x2c, 0xec, 0x8c, 0xb9, 0xab, 0x21, 0xac, 0x3f, 0x79, 0x92, - 0xcc, 0x74, 0xe1, 0x02, 0x85, 0x7b, 0xa2, 0x78, 0x4b, 0x50, 0x9a, 0xf9, 0x56, 0x2a, 0xbc, 0x77, 0x34, 0xd9, 0xc8, - 0xea, 0x4b, 0xf8, 0x5a, 0xbc, 0x66, 0x83, 0xc5, 0x44, 0xb9, 0x88, 0x26, 0xf7, 0xfa, 0x55, 0xc8, 0xaf, 0x00, 0x4a, - 0x95, 0xac, 0x49, 0x4d, 0xb1, 0xbd, 0xf9, 0xb7, 0xe8, 0x31, 0x2b, 0xd7, 0x4f, 0x01, 0x36, 0x25, 0x25, 0xb6, 0x01, - 0xbe, 0x03, 0xb3, 0x2d, 0x79, 0x2e, 0x5c, 0xc0, 0xfc, 0x49, 0xcf, 0x97, 0x9e, 0x04, 0x4f, 0xef, 0x07, 0x96, 0x24, - 0xde, 0x84, 0xc9, 0xa8, 0xa5, 0xd4, 0x39, 0x60, 0xc1, 0x5c, 0x9d, 0x8c, 0x13, 0x08, 0x8c, 0xbd, 0xbf, 0xe1, 0x8f, - 0x02, 0x6e, 0xb2, 0xe0, 0xa7, 0x05, 0x8b, 0x56, 0x38, 0x6f, 0xf8, 0x16, 0x2c, 0x4f, 0xd9, 0x8f, 0x02, 0x90, 0xc8, - 0x2d, 0x0b, 0xaa, 0x85, 0xa9, 0x37, 0xa9, 0x16, 0xd1, 0x5a, 0x67, 0x25, 0xb4, 0xa7, 0x97, 0x1e, 0x05, 0x2e, 0xfc, - 0x0c, 0xbb, 0xfc, 0x20, 0x9a, 0xfc, 0xa6, 0x46, 0xf9, 0x3b, 0x9c, 0x29, 0x7e, 0x08, 0x8d, 0x30, 0xed, 0x5b, 0x38, - 0xc7, 0x8a, 0x05, 0x53, 0xd8, 0x09, 0xd3, 0xa9, 0x89, 0xe1, 0xe3, 0xb4, 0x46, 0xa8, 0x1b, 0x16, 0xae, 0xed, 0xba, - 0x1a, 0x34, 0xb3, 0x13, 0x4f, 0x06, 0x9e, 0xe6, 0x34, 0x4e, 0x0c, 0xf1, 0xc7, 0xb2, 0x5b, 0x7a, 0x86, 0x3d, 0x28, - 0x23, 0xff, 0x76, 0x3d, 0x8e, 0xc2, 0xd4, 0x1c, 0x7b, 0x33, 0x3f, 0xb8, 0xeb, 0xcc, 0xa2, 0x30, 0x4a, 0xe6, 0xde, - 0x90, 0x75, 0x25, 0x7e, 0x14, 0xc3, 0x31, 0xf3, 0x88, 0x80, 0x8e, 0xd5, 0x88, 0xd9, 0x8c, 0x5a, 0xe7, 0xd1, 0x96, - 0xc7, 0x01, 0x5b, 0x65, 0xfc, 0xf3, 0xa5, 0xca, 0x54, 0x15, 0xb7, 0x1c, 0xb5, 0x00, 0x96, 0x99, 0x87, 0x72, 0x86, - 0x04, 0x06, 0x5d, 0x2e, 0x75, 0xec, 0x58, 0x8d, 0x56, 0xcc, 0x66, 0x8a, 0xd5, 0xda, 0xda, 0x79, 0x1c, 0x2d, 0x7b, - 0x00, 0x2d, 0x36, 0x36, 0x13, 0x16, 0x8c, 0xf1, 0x8d, 0x89, 0xd1, 0xa3, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, - 0x6c, 0xd6, 0x85, 0xd7, 0x9d, 0x86, 0x62, 0x4b, 0xfc, 0xf4, 0x89, 0x3d, 0x97, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, - 0x75, 0x47, 0xb1, 0xbb, 0xa0, 0x3f, 0x1e, 0x07, 0xd1, 0xb2, 0x33, 0xf5, 0x47, 0x23, 0x16, 0x76, 0x11, 0xe6, 0xbc, - 0x90, 0x05, 0x81, 0x3f, 0x4f, 0xfc, 0xa4, 0x3b, 0xf3, 0x56, 0xbc, 0xd7, 0xa3, 0x6d, 0xbd, 0x36, 0x79, 0xaf, 0xcd, - 0xbd, 0x7b, 0x95, 0xba, 0x81, 0x48, 0x55, 0xd4, 0x0f, 0x07, 0xad, 0xa5, 0xd8, 0x95, 0x71, 0xee, 0xdd, 0xeb, 0x3c, - 0x66, 0xeb, 0x99, 0x17, 0x4f, 0xfc, 0xb0, 0x63, 0x67, 0xd6, 0xed, 0x9a, 0x36, 0xc6, 0xa3, 0x76, 0xbb, 0x9d, 0x59, - 0x23, 0xf1, 0x64, 0x8f, 0x46, 0x99, 0x35, 0x14, 0x4f, 0xe3, 0xb1, 0x6d, 0x8f, 0xc7, 0x99, 0xe5, 0x8b, 0x82, 0x66, - 0x63, 0x38, 0x6a, 0x36, 0x32, 0x6b, 0x29, 0xd5, 0xc8, 0x2c, 0xc6, 0x9f, 0x62, 0x36, 0xea, 0xe2, 0x46, 0xe2, 0x3e, - 0xcf, 0x27, 0xb6, 0x9d, 0x21, 0x06, 0xb8, 0x2a, 0xe1, 0x26, 0x34, 0x5d, 0xb9, 0x5e, 0xef, 0x5d, 0x53, 0x29, 0x3e, - 0x37, 0x1c, 0xd6, 0xd6, 0x1b, 0x79, 0xf1, 0xc7, 0x6b, 0x45, 0x1a, 0x85, 0xe7, 0x51, 0xb5, 0xb5, 0x98, 0x06, 0x73, - 0xd5, 0x81, 0xb4, 0x1c, 0xdd, 0x41, 0x14, 0xc3, 0x99, 0x8d, 0xbd, 0x91, 0xbf, 0x48, 0x3a, 0x4e, 0x63, 0xbe, 0x12, - 0x45, 0x7c, 0xaf, 0x17, 0x05, 0x78, 0xf6, 0x3a, 0x49, 0x14, 0xf8, 0x23, 0x51, 0xb4, 0xed, 0x2c, 0x39, 0x0d, 0xbd, - 0x8b, 0xfc, 0xab, 0x8f, 0xa1, 0x95, 0xbd, 0x20, 0x50, 0xac, 0x66, 0xa2, 0x30, 0x2f, 0x41, 0x73, 0x39, 0xc5, 0x4e, - 0x68, 0x5e, 0x30, 0x00, 0xad, 0x73, 0x34, 0x5f, 0xe5, 0x7b, 0xde, 0x39, 0x9e, 0xaf, 0xb2, 0xaf, 0x67, 0x6c, 0xe4, - 0x7b, 0x8a, 0x56, 0xec, 0x26, 0xc7, 0x06, 0x93, 0x3a, 0x7d, 0xbd, 0x65, 0x9b, 0x8a, 0x63, 0x01, 0xe9, 0x8b, 0x0e, - 0xfc, 0x19, 0xc8, 0x61, 0xbc, 0x30, 0xcd, 0xb2, 0xfe, 0x75, 0x96, 0x75, 0x2f, 0x7c, 0xed, 0xea, 0xaf, 0x1a, 0xd1, - 0x42, 0x32, 0x41, 0xcd, 0xf4, 0x6b, 0xe3, 0x9c, 0xc9, 0xee, 0x32, 0x40, 0xc6, 0xd0, 0x55, 0x46, 0xae, 0x4c, 0xf4, - 0x76, 0xb3, 0x32, 0x4d, 0x72, 0x5e, 0x9d, 0xbc, 0x6f, 0xca, 0x55, 0x90, 0x02, 0x41, 0x85, 0x73, 0xe6, 0x5e, 0x48, - 0xbe, 0x37, 0xc0, 0xf4, 0x60, 0x65, 0x8a, 0x1d, 0xf4, 0x7a, 0x1b, 0xef, 0x79, 0x79, 0x3f, 0xef, 0xf9, 0xb7, 0x74, - 0x1f, 0xde, 0xf3, 0xf2, 0x8b, 0xf3, 0x9e, 0xaf, 0x37, 0x63, 0x07, 0x5d, 0x46, 0xae, 0x9a, 0x1b, 0x4c, 0x02, 0x69, - 0x8a, 0x29, 0x2a, 0xff, 0xeb, 0xf4, 0xd7, 0x06, 0x71, 0x11, 0xbd, 0x21, 0x51, 0xe0, 0x7c, 0x2a, 0x88, 0x59, 0xdf, - 0x86, 0xee, 0x9f, 0x62, 0xf9, 0x79, 0x3c, 0x76, 0x5f, 0x47, 0x52, 0x41, 0xfe, 0xc4, 0x7d, 0x49, 0x4a, 0x11, 0x94, - 0xe9, 0x4d, 0xee, 0xed, 0x03, 0x39, 0xa6, 0x21, 0x00, 0x2b, 0xb9, 0x76, 0x8f, 0x72, 0x9f, 0xbb, 0x6e, 0x19, 0x04, - 0x2d, 0x77, 0x72, 0x15, 0x61, 0xb6, 0x36, 0x2c, 0xa3, 0x26, 0x4c, 0xc8, 0x00, 0x5e, 0xde, 0x7d, 0x3f, 0xd2, 0x2e, - 0x23, 0x3d, 0xf3, 0x93, 0xb7, 0xd5, 0x20, 0x57, 0x42, 0xcf, 0x25, 0x0f, 0x27, 0xe3, 0x7e, 0x73, 0x52, 0x2c, 0x5b, - 0x7c, 0x4d, 0xcd, 0xcf, 0x4a, 0x23, 0xed, 0xc8, 0x0d, 0xbb, 0x14, 0xd9, 0x7b, 0x83, 0x18, 0xf3, 0x60, 0x30, 0x6b, - 0xce, 0xe5, 0xad, 0xf1, 0x19, 0x62, 0x83, 0x8e, 0xa8, 0xb9, 0x3f, 0xca, 0x32, 0xbd, 0x2b, 0x26, 0x42, 0x22, 0xb4, - 0xec, 0x3e, 0x26, 0x2e, 0x29, 0x84, 0x40, 0x5c, 0xe2, 0x43, 0xd6, 0xcc, 0x97, 0xe0, 0x1f, 0xc0, 0x6d, 0x9f, 0xf9, - 0x9c, 0xa9, 0x0a, 0x4d, 0x1f, 0xf9, 0x8d, 0x48, 0x03, 0x02, 0x83, 0x76, 0xd9, 0xdb, 0xaa, 0xb4, 0x20, 0x9b, 0x8e, - 0xad, 0x34, 0x39, 0xe8, 0xe0, 0x00, 0x91, 0x7c, 0x85, 0x58, 0x88, 0xd0, 0x0e, 0xaf, 0x83, 0x0f, 0x99, 0x9a, 0xf3, - 0x7e, 0xb8, 0xfd, 0x7a, 0xa7, 0x87, 0xd0, 0xa0, 0x57, 0x51, 0xba, 0xdd, 0xe3, 0x97, 0x09, 0xac, 0x44, 0xb2, 0x34, - 0xac, 0x64, 0xa9, 0x3c, 0x5b, 0x8b, 0x28, 0xd8, 0xa9, 0x37, 0x37, 0x41, 0xcb, 0x83, 0xb8, 0x97, 0x63, 0x3c, 0x29, - 0xe0, 0x76, 0x77, 0x91, 0x00, 0x6e, 0x44, 0x39, 0x0a, 0xe2, 0x9f, 0xee, 0x70, 0x11, 0x27, 0x51, 0xdc, 0x99, 0x47, - 0x7e, 0x98, 0xb2, 0x38, 0x23, 0xc1, 0x0a, 0xce, 0x8f, 0x98, 0x9e, 0xeb, 0x75, 0x34, 0xf7, 0x86, 0x7e, 0x7a, 0xd7, - 0xb1, 0x39, 0x4b, 0x61, 0x77, 0x39, 0x77, 0x60, 0xd7, 0xd6, 0xef, 0xf0, 0xd9, 0x7c, 0x8e, 0x8c, 0x5f, 0xbc, 0xc9, - 0xce, 0xc8, 0xdb, 0xbc, 0x2b, 0xbd, 0xa5, 0x38, 0xe0, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x01, 0x2c, 0x0f, 0x4b, 0x6d, - 0x8f, 0xd8, 0xc4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0xd5, 0xd2, 0x15, 0xbb, 0xbe, 0x18, 0x38, 0x1e, 0x7d, - 0x1f, 0xc8, 0x3a, 0xde, 0x38, 0x65, 0xb1, 0xb1, 0x4f, 0xcd, 0x01, 0x1b, 0x47, 0x31, 0xa3, 0x9c, 0x71, 0x4e, 0x7b, - 0xbe, 0xda, 0xbf, 0xfb, 0xdd, 0xc3, 0xaf, 0xef, 0x27, 0x8c, 0x52, 0x4d, 0x74, 0xa6, 0xdf, 0xd3, 0xdb, 0x26, 0x3d, - 0x03, 0xd6, 0x90, 0x66, 0x7e, 0x48, 0x52, 0x10, 0x88, 0xf7, 0x55, 0x9b, 0x9a, 0x63, 0x1e, 0x71, 0x9a, 0x17, 0xb3, - 0xc0, 0x4b, 0xfd, 0x5b, 0xc1, 0x33, 0x36, 0x8f, 0xe7, 0x2b, 0xb1, 0xc6, 0x48, 0xf0, 0x1e, 0xb0, 0x48, 0x15, 0x50, - 0xc4, 0x22, 0x55, 0x8b, 0x71, 0x91, 0xba, 0x1b, 0xa3, 0x11, 0xd1, 0xaa, 0x2b, 0x94, 0xbe, 0x35, 0x5f, 0xc9, 0x24, - 0xba, 0x68, 0x96, 0x53, 0xea, 0x6a, 0x9a, 0x91, 0x99, 0x3f, 0x1a, 0x05, 0x2c, 0x2b, 0x2d, 0x74, 0x79, 0x2d, 0xa5, - 0xc9, 0xc9, 0xe7, 0xc1, 0x1b, 0x24, 0x51, 0xb0, 0x48, 0x59, 0xfd, 0x74, 0x09, 0x89, 0x6e, 0x31, 0x39, 0xf8, 0xbb, - 0x0c, 0x6b, 0x0b, 0xd8, 0x6d, 0xd8, 0x26, 0x76, 0x17, 0xb2, 0x0a, 0x9a, 0xcd, 0x32, 0xe8, 0xf0, 0x2a, 0x07, 0xda, - 0xa8, 0x19, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0xcf, 0xac, 0x96, 0x17, 0x65, 0xe5, 0xc1, - 0xfc, 0x36, 0x67, 0xec, 0x45, 0xfd, 0x19, 0x7b, 0x21, 0xce, 0xd8, 0xee, 0x9d, 0xf9, 0x68, 0xec, 0xc0, 0x7f, 0xdd, - 0x62, 0x40, 0x1d, 0x5b, 0x69, 0xce, 0x57, 0x8a, 0x33, 0x5f, 0x29, 0x66, 0x63, 0xbe, 0x52, 0xb0, 0x6b, 0x74, 0x6f, - 0x31, 0xac, 0x86, 0x6e, 0xd8, 0x0a, 0x14, 0xc2, 0x1f, 0xbb, 0xf4, 0xca, 0x39, 0x82, 0x77, 0xd0, 0xaa, 0xb5, 0xf9, - 0xae, 0xb1, 0xfb, 0xa8, 0xd3, 0x59, 0x12, 0x48, 0x5b, 0xb7, 0x52, 0x6f, 0x30, 0x00, 0x51, 0x66, 0x34, 0x5c, 0x24, - 0xff, 0xe4, 0xf0, 0xf3, 0x49, 0xdc, 0x89, 0x08, 0x2a, 0xfd, 0x88, 0xa6, 0xa0, 0x28, 0xbc, 0x65, 0xa2, 0x87, 0x75, - 0xbe, 0x4e, 0x1d, 0x4a, 0x81, 0xd8, 0xb0, 0x8e, 0x6a, 0x36, 0x79, 0xfd, 0x44, 0xff, 0x66, 0xab, 0xb4, 0x1d, 0xc5, - 0x7c, 0xc6, 0xb4, 0xec, 0x9c, 0x8e, 0x87, 0xcf, 0x06, 0x5f, 0x4d, 0xbb, 0x5d, 0x0f, 0xee, 0x95, 0xf8, 0xd2, 0xb5, - 0x20, 0x2a, 0x9c, 0x6e, 0xf1, 0x50, 0x1c, 0xbb, 0x7b, 0xdd, 0xb6, 0x47, 0x36, 0x7a, 0xdd, 0x41, 0x10, 0x8a, 0xba, - 0x7b, 0x62, 0xf9, 0x47, 0x2f, 0x8e, 0xe0, 0x3f, 0xe2, 0xea, 0xff, 0x96, 0xd6, 0x31, 0xea, 0xaf, 0xd3, 0x12, 0xa3, - 0x4e, 0xac, 0x12, 0x32, 0xe2, 0xfb, 0xd7, 0x1f, 0x8f, 0x1f, 0xd6, 0x60, 0xef, 0xda, 0xe4, 0x19, 0x56, 0xad, 0xfd, - 0x32, 0x8a, 0x02, 0xe6, 0x85, 0x9b, 0xd5, 0xc5, 0xf4, 0x90, 0x9b, 0x7f, 0xea, 0x42, 0x23, 0x71, 0x8f, 0x20, 0xa7, - 0x04, 0x15, 0xdb, 0xd0, 0x55, 0xe2, 0x62, 0xdb, 0x55, 0xe2, 0xdd, 0xfd, 0x57, 0x89, 0x3f, 0xee, 0x75, 0x95, 0x78, - 0xf7, 0xc5, 0xaf, 0x12, 0x17, 0x9b, 0x57, 0x89, 0x8b, 0x48, 0xb8, 0x03, 0x1b, 0x6f, 0x16, 0xfc, 0xe7, 0x07, 0xb2, - 0xf7, 0x7d, 0x17, 0xb9, 0x2d, 0x9b, 0xd2, 0x1a, 0x5e, 0xfe, 0xea, 0x8b, 0x05, 0x6e, 0xc4, 0x77, 0xe8, 0x1d, 0x57, - 0x5c, 0x2d, 0x38, 0x66, 0xc7, 0xef, 0x48, 0xc5, 0x41, 0x14, 0x4e, 0x7e, 0x02, 0x7b, 0x6f, 0x10, 0x07, 0xc6, 0xd2, - 0x0b, 0x3f, 0xf9, 0x29, 0x9a, 0x2f, 0xe6, 0xa8, 0xa8, 0xfa, 0xe0, 0x27, 0xfe, 0x20, 0x60, 0x79, 0x1c, 0x49, 0xd2, - 0xba, 0x72, 0xd9, 0x3a, 0x28, 0x5e, 0xc5, 0x4f, 0x6f, 0x25, 0x7e, 0xa2, 0x8b, 0x2d, 0xff, 0x4d, 0x6e, 0x82, 0x6a, - 0xfd, 0x45, 0x44, 0x58, 0x88, 0x49, 0x40, 0x3f, 0xfc, 0x32, 0x72, 0x11, 0xe9, 0x35, 0xa3, 0x14, 0xee, 0x1b, 0x5b, - 0xfb, 0x61, 0xd5, 0x7e, 0xde, 0x2c, 0x74, 0x23, 0x4f, 0xb3, 0xb1, 0x29, 0xce, 0x9f, 0x45, 0x8b, 0x84, 0x8d, 0xa2, - 0x65, 0xa8, 0x1a, 0x21, 0xd7, 0xab, 0x46, 0x28, 0x53, 0xcf, 0xdb, 0x94, 0x15, 0x8e, 0xaa, 0x35, 0x87, 0x39, 0x34, - 0x49, 0x83, 0x6d, 0xe2, 0x10, 0x55, 0x11, 0xb2, 0xa9, 0x7b, 0xa0, 0x69, 0x91, 0xfb, 0xb0, 0x96, 0xc2, 0xf3, 0x24, - 0xb2, 0xb8, 0x54, 0x38, 0xd1, 0x42, 0x21, 0x5c, 0x14, 0xb1, 0xae, 0x6b, 0x16, 0x8e, 0xbf, 0xa1, 0x20, 0x91, 0xc5, - 0x5b, 0xd0, 0x55, 0x65, 0x0b, 0xbe, 0x1e, 0x3c, 0xf2, 0x33, 0x3d, 0xbe, 0x92, 0xa6, 0xf1, 0xed, 0x2d, 0x8b, 0x03, - 0xef, 0x4e, 0xd3, 0xb3, 0x28, 0xfc, 0x01, 0x26, 0xe0, 0x75, 0xb4, 0x0c, 0xe5, 0x0a, 0x98, 0x90, 0xbd, 0x66, 0x2f, - 0xd5, 0xc6, 0x28, 0x87, 0x98, 0x1d, 0x12, 0x04, 0xbe, 0x35, 0xf7, 0x26, 0xec, 0x2f, 0x06, 0xfd, 0xfb, 0x57, 0x3d, - 0x33, 0xde, 0x45, 0xf9, 0x87, 0x7e, 0x9e, 0xef, 0xf1, 0x99, 0x27, 0x4f, 0x0e, 0xb6, 0x0f, 0x5b, 0x1b, 0x06, 0xcc, - 0x8b, 0x05, 0x14, 0x35, 0xad, 0xf5, 0xad, 0xa7, 0x00, 0xa0, 0xb8, 0x8c, 0x16, 0xc3, 0x29, 0xfa, 0xed, 0x7e, 0xb9, - 0xf1, 0xa6, 0xd0, 0x27, 0x4b, 0xae, 0xec, 0xeb, 0x7c, 0xe8, 0x95, 0xa2, 0x62, 0x16, 0xf0, 0xfb, 0xe7, 0x90, 0x64, - 0xeb, 0x3f, 0x38, 0x0d, 0x9b, 0xbb, 0x26, 0x0f, 0xf9, 0xf5, 0xa0, 0xcd, 0xdb, 0xf5, 0x21, 0x2a, 0x0f, 0x85, 0xaf, - 0x16, 0x4a, 0xba, 0x7a, 0x24, 0x93, 0x55, 0x27, 0x4d, 0x4e, 0x15, 0xb3, 0x2d, 0x0b, 0x8e, 0xf8, 0x0a, 0xb3, 0x4a, - 0x56, 0x23, 0x06, 0xe3, 0xd8, 0xaa, 0x82, 0x64, 0xb8, 0x37, 0x05, 0x43, 0xf4, 0x55, 0x7d, 0x37, 0xf3, 0x43, 0x03, - 0x33, 0xbd, 0x6e, 0xbe, 0xf1, 0x56, 0x90, 0xeb, 0x10, 0x90, 0x5b, 0xf5, 0x15, 0x14, 0x1a, 0x72, 0xb4, 0x20, 0x6f, - 0x34, 0xd2, 0xd4, 0xda, 0x99, 0x10, 0xda, 0xc0, 0xfe, 0x57, 0x8a, 0xa2, 0x28, 0xf9, 0x35, 0x42, 0xc9, 0xef, 0x11, - 0x58, 0x8e, 0xd7, 0x01, 0xd0, 0x96, 0x64, 0xf3, 0x15, 0x95, 0xc0, 0xcd, 0x00, 0xed, 0xa7, 0x45, 0x01, 0x4f, 0xe7, - 0x03, 0xc6, 0x2d, 0x54, 0x20, 0x2e, 0xf4, 0xa0, 0xfa, 0xf6, 0x62, 0xc8, 0xfa, 0xd7, 0x51, 0xf0, 0xc2, 0x8e, 0x6f, - 0xb9, 0x24, 0x58, 0xb1, 0xe9, 0xb1, 0xdf, 0x65, 0xf5, 0x79, 0x5f, 0x42, 0x09, 0x0b, 0x82, 0xd6, 0xa1, 0x92, 0xc6, - 0xd1, 0x60, 0x35, 0xb8, 0x11, 0xef, 0x45, 0xab, 0x74, 0xc6, 0xc2, 0x85, 0x6a, 0x80, 0xd5, 0x09, 0xe6, 0xe1, 0x81, - 0x3a, 0xaf, 0x89, 0xd9, 0x02, 0x6c, 0x53, 0xdf, 0x72, 0x4a, 0xb4, 0x50, 0x98, 0xaa, 0x78, 0xc6, 0x90, 0x07, 0xc0, - 0x49, 0x38, 0x6e, 0xab, 0x52, 0x08, 0xbe, 0xa4, 0x51, 0x19, 0x9b, 0xf3, 0x90, 0x57, 0xc8, 0x29, 0x90, 0x8d, 0x18, - 0x17, 0x17, 0x89, 0x69, 0xd7, 0xbc, 0xea, 0xa2, 0xe5, 0x1a, 0x19, 0xaf, 0x22, 0x28, 0x8a, 0xf5, 0xcd, 0x6e, 0x38, - 0x9c, 0x90, 0x7c, 0x60, 0x6b, 0x3f, 0xc3, 0x8d, 0x7e, 0xb6, 0x0c, 0xfa, 0x23, 0xbb, 0x23, 0x42, 0x42, 0x53, 0xf5, - 0x91, 0xdd, 0x81, 0x71, 0xf8, 0x39, 0x48, 0x53, 0xd4, 0x1d, 0xe8, 0xda, 0x80, 0x74, 0xbe, 0x43, 0x48, 0x48, 0xb1, - 0xe3, 0x00, 0xd9, 0xd9, 0x0e, 0x2c, 0x8e, 0x53, 0x1c, 0x1a, 0x49, 0x57, 0x1c, 0x62, 0x1e, 0xb1, 0x40, 0xab, 0x9d, - 0x63, 0xb3, 0xe6, 0x68, 0xe8, 0xcf, 0x1c, 0xdb, 0x3e, 0xdc, 0xa8, 0x0f, 0x82, 0xec, 0xba, 0xda, 0xba, 0x91, 0xba, - 0x8e, 0x6d, 0xfa, 0xcf, 0xac, 0x46, 0x77, 0x83, 0x46, 0x4b, 0xf9, 0xa2, 0xfa, 0x28, 0xfe, 0xea, 0x3d, 0x5e, 0x6b, - 0x1b, 0x07, 0x52, 0xaf, 0x46, 0x00, 0x40, 0xd8, 0x32, 0x2e, 0xff, 0xea, 0x6f, 0x92, 0x7e, 0xca, 0x56, 0x45, 0xb9, - 0xcb, 0xfb, 0x90, 0xf1, 0x50, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x7e, 0x57, 0x60, - 0x14, 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0x6e, 0x35, 0x56, 0x68, 0xf4, 0x76, 0x72, - 0x0b, 0xd8, 0xff, 0x16, 0xf2, 0x69, 0x0d, 0x20, 0xc6, 0x23, 0xd4, 0x80, 0xfc, 0xa8, 0xf7, 0x76, 0x08, 0x21, 0x79, - 0xe5, 0xee, 0xca, 0x44, 0x72, 0xff, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x9e, 0xdc, 0x3d, 0xb0, 0x4b, - 0x16, 0x8e, 0xca, 0x1d, 0x56, 0xe8, 0xd7, 0xfe, 0xdd, 0x95, 0x30, 0x0a, 0x24, 0x0e, 0x8e, 0x6a, 0x30, 0x4a, 0x16, - 0x85, 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x7b, 0x71, 0x31, 0xd8, 0x80, 0xb2, 0x7e, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0x64, - 0xa7, 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0xb7, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x6f, 0x6a, - 0x5f, 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, - 0x98, 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x6a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, - 0xb7, 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x51, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, - 0xbf, 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, - 0x24, 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, - 0x6f, 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, - 0xe7, 0x36, 0x10, 0x08, 0x64, 0x4d, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x13, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, - 0x49, 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x25, 0x09, 0x42, 0xc7, 0x56, 0xec, 0x6e, 0x0d, 0x03, 0x80, 0xf4, - 0xbf, 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xdd, - 0xfc, 0x26, 0xc9, 0x7b, 0xd6, 0x3c, 0x26, 0x48, 0x59, 0x9c, 0xcf, 0x6b, 0x74, 0x04, 0x1c, 0x7c, 0x97, 0xc5, 0x8b, - 0x10, 0x53, 0xdd, 0x9a, 0x69, 0xec, 0x0d, 0x3f, 0xae, 0xa5, 0xef, 0x71, 0x91, 0x28, 0x88, 0x8b, 0xcb, 0x4a, 0x85, - 0xae, 0x87, 0x99, 0xa1, 0x58, 0xc7, 0x6a, 0x24, 0x92, 0xa0, 0xa6, 0xf3, 0xc8, 0x6e, 0x7a, 0x2f, 0xc6, 0x47, 0x15, - 0xf9, 0x69, 0xa3, 0x55, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa2, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, - 0x66, 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x8d, 0x92, 0x6d, 0x60, 0x8d, 0xfd, - 0x20, 0x30, 0x03, 0x70, 0x63, 0x58, 0x7f, 0xd6, 0xf0, 0xb0, 0x9f, 0x05, 0xe4, 0x24, 0xfc, 0x8c, 0x7e, 0xca, 0x3b, - 0x25, 0x9d, 0x2e, 0x66, 0x83, 0xb5, 0x2c, 0x28, 0x97, 0xe4, 0xe7, 0x9b, 0x32, 0x73, 0xf9, 0xb3, 0xe3, 0xf1, 0xb8, - 0x2c, 0x35, 0xb6, 0x95, 0x23, 0x94, 0xfc, 0x3e, 0xb2, 0x6d, 0xbb, 0x3a, 0xbf, 0xdb, 0x0e, 0x0a, 0x1d, 0x0c, 0x13, - 0x85, 0xf0, 0xed, 0xfb, 0xf7, 0xd4, 0xef, 0x04, 0x2d, 0x75, 0xb5, 0xed, 0x3c, 0xd2, 0x56, 0xfb, 0xaf, 0x00, 0x05, - 0x51, 0xc3, 0x7d, 0xc7, 0x7f, 0x73, 0xaf, 0xec, 0xe8, 0xa9, 0x7a, 0x80, 0x1f, 0xd6, 0xf8, 0x9e, 0xbd, 0xbe, 0x47, - 0xd3, 0x6d, 0xdb, 0x3b, 0xb3, 0x0a, 0xb2, 0x5b, 0xb2, 0x59, 0xea, 0x92, 0xa5, 0x92, 0x9f, 0xb2, 0x59, 0xd2, 0x19, - 0x32, 0x54, 0x90, 0x5a, 0x12, 0xb5, 0x45, 0xab, 0x1e, 0x73, 0x02, 0x76, 0x5c, 0x8e, 0xc0, 0xc3, 0xb6, 0x82, 0xca, - 0xaa, 0x0d, 0xcd, 0x9a, 0xf8, 0x08, 0x52, 0xb1, 0xf5, 0xa6, 0xc2, 0x09, 0xb7, 0x69, 0xcb, 0xfe, 0x43, 0xa9, 0x9e, - 0x02, 0xdc, 0xe9, 0x5a, 0x58, 0x9b, 0x90, 0xf2, 0x04, 0xff, 0xce, 0x95, 0x73, 0x2f, 0xe6, 0xab, 0xb2, 0x71, 0x57, - 0x1b, 0xd4, 0x4d, 0x05, 0x29, 0x23, 0xa8, 0xeb, 0x50, 0x5f, 0x6e, 0x02, 0x34, 0x96, 0xad, 0x5b, 0xc0, 0x82, 0x46, - 0x4c, 0x41, 0x45, 0x47, 0x98, 0x83, 0x8a, 0xd7, 0x59, 0xd8, 0x79, 0x85, 0x7c, 0x1f, 0x7f, 0x41, 0x2e, 0x72, 0x48, - 0x70, 0xf2, 0x07, 0xe3, 0x79, 0x1b, 0x95, 0x7b, 0xa5, 0xad, 0x8a, 0xa6, 0x32, 0xb8, 0x07, 0xc4, 0x8d, 0x54, 0x59, - 0xc4, 0x81, 0x49, 0xe9, 0xe9, 0x35, 0x7d, 0xbd, 0x39, 0xee, 0xed, 0xdd, 0x3b, 0x2d, 0xd0, 0x6b, 0x6c, 0x4e, 0xd5, - 0x5e, 0xaa, 0xbd, 0xaa, 0x0e, 0x5b, 0xc0, 0x09, 0x2b, 0x00, 0x3e, 0xb3, 0x0a, 0x1a, 0x0d, 0x29, 0x15, 0xdc, 0x47, - 0x83, 0xce, 0xdf, 0xca, 0xc8, 0x5a, 0x8c, 0x13, 0xbb, 0xab, 0xaf, 0x42, 0x7d, 0x0b, 0xcd, 0x20, 0xcc, 0x1d, 0xc7, - 0x4e, 0xf8, 0x6c, 0xc2, 0x8e, 0x91, 0xd1, 0x95, 0x83, 0x3b, 0x08, 0x4f, 0xa9, 0x49, 0x69, 0x4f, 0xe8, 0x94, 0xa2, - 0x2e, 0xe1, 0x8f, 0xb5, 0xc2, 0xfb, 0xcb, 0x92, 0x34, 0x9e, 0x07, 0x9d, 0x68, 0xe8, 0x7b, 0xd5, 0x9e, 0xf9, 0xe1, - 0xfe, 0x75, 0xbd, 0xd5, 0xde, 0x75, 0x81, 0x39, 0xdc, 0xbb, 0x32, 0x70, 0x97, 0x58, 0xf9, 0x32, 0x75, 0xff, 0x28, - 0x29, 0x0f, 0xe4, 0x80, 0x89, 0x2a, 0xb6, 0xa2, 0x1b, 0xfd, 0x8f, 0x0b, 0xb7, 0x7f, 0x7a, 0xb6, 0x9a, 0x05, 0xca, - 0x2d, 0x8b, 0x13, 0x48, 0x28, 0xa1, 0x3a, 0x96, 0xad, 0x2a, 0x68, 0xd0, 0xef, 0x87, 0x13, 0x57, 0xfd, 0xf9, 0xf2, - 0x8d, 0xd9, 0x56, 0xcf, 0xc0, 0x1c, 0xe3, 0x76, 0x82, 0x2c, 0xee, 0x85, 0x77, 0xc7, 0xe2, 0x9b, 0x06, 0xf7, 0xf8, - 0x21, 0xe6, 0x16, 0xcb, 0x94, 0x86, 0xba, 0x47, 0xe2, 0x77, 0xe5, 0xd6, 0x67, 0xcb, 0x97, 0xd1, 0xca, 0x55, 0x01, - 0xb1, 0x3a, 0x8d, 0xb6, 0xe2, 0x34, 0x8e, 0xac, 0xe3, 0xb6, 0xda, 0xfb, 0x4a, 0x51, 0x4e, 0x47, 0x6c, 0x9c, 0xf4, - 0x50, 0x1c, 0x73, 0x8a, 0xfc, 0x20, 0xfd, 0x56, 0x14, 0x6b, 0x18, 0x24, 0xa6, 0xa3, 0xac, 0xf9, 0xa3, 0xa2, 0x00, - 0x32, 0xea, 0x28, 0x8f, 0xc6, 0x8d, 0xf1, 0xd1, 0xf8, 0x45, 0x97, 0x17, 0x67, 0x5f, 0x95, 0xaa, 0x1b, 0xf4, 0x6f, - 0x43, 0x6a, 0x96, 0xa4, 0x71, 0xf4, 0x91, 0x71, 0x5e, 0x52, 0xc9, 0x05, 0x45, 0xd5, 0xa6, 0x8d, 0xcd, 0x2f, 0x39, - 0xed, 0xc1, 0x70, 0xdc, 0x28, 0xaa, 0x23, 0x8c, 0x87, 0x39, 0x90, 0xa7, 0x87, 0x02, 0xf4, 0x53, 0x79, 0x9a, 0x1c, - 0xb3, 0x6e, 0xa2, 0x1c, 0x95, 0x8f, 0x71, 0x22, 0xc6, 0x77, 0x0a, 0x79, 0xd5, 0x0a, 0xef, 0xc5, 0x04, 0x9b, 0xb9, - 0xea, 0x0f, 0x4e, 0xa3, 0x6d, 0x38, 0xce, 0xb1, 0x75, 0xdc, 0x1e, 0xda, 0xc6, 0x91, 0x75, 0x64, 0x36, 0xad, 0x63, - 0xa3, 0x6d, 0xb6, 0x8d, 0xf6, 0x77, 0xed, 0xa1, 0x79, 0x64, 0x1d, 0x19, 0xb6, 0xd9, 0x86, 0x42, 0xb3, 0x6d, 0xb6, - 0x6f, 0xcd, 0xa3, 0xf6, 0xd0, 0xc6, 0xd2, 0x86, 0xd5, 0x6a, 0x99, 0x8e, 0x6d, 0xb5, 0x5a, 0x46, 0xcb, 0x3a, 0x3e, - 0x36, 0x9d, 0xa6, 0x75, 0x7c, 0x7c, 0xd1, 0x6a, 0x5b, 0x4d, 0x78, 0xd7, 0x6c, 0x0e, 0x9b, 0x96, 0xe3, 0x98, 0xf0, - 0x97, 0xd1, 0xb6, 0x1a, 0xf4, 0xc3, 0x71, 0xac, 0xa6, 0x63, 0xd8, 0x41, 0xab, 0x61, 0x1d, 0xbf, 0x30, 0xf0, 0x6f, - 0xac, 0x66, 0xe0, 0x5f, 0xd0, 0x8d, 0xf1, 0xc2, 0x6a, 0x1c, 0xd3, 0x2f, 0xec, 0xf0, 0xf6, 0xa8, 0xfd, 0x37, 0xf5, - 0x70, 0xeb, 0x18, 0x1c, 0x1a, 0x43, 0xbb, 0x65, 0x35, 0x9b, 0xc6, 0x91, 0x63, 0xb5, 0x9b, 0x53, 0xf3, 0xa8, 0x61, - 0x1d, 0x9f, 0x0c, 0x4d, 0xc7, 0x3a, 0x39, 0x31, 0x6c, 0xb3, 0x69, 0x35, 0x0c, 0xc7, 0x3a, 0x6a, 0xe2, 0x8f, 0xa6, - 0xd5, 0xb8, 0x3d, 0x79, 0x61, 0x1d, 0xb7, 0xa6, 0xc7, 0xd6, 0xd1, 0x87, 0xa3, 0xb6, 0xd5, 0x68, 0x4e, 0x9b, 0xc7, - 0x56, 0xe3, 0xe4, 0xf6, 0xd8, 0x3a, 0x9a, 0x9a, 0x8d, 0xe3, 0x9d, 0x2d, 0x9d, 0x86, 0x05, 0x73, 0x84, 0xaf, 0xe1, - 0x85, 0xc1, 0x5f, 0xc0, 0x9f, 0x29, 0xb6, 0xfd, 0x1d, 0xbb, 0x49, 0x36, 0x9b, 0xbe, 0xb0, 0xda, 0x27, 0x43, 0xaa, - 0x0e, 0x05, 0xa6, 0xa8, 0x01, 0x4d, 0x6e, 0x4d, 0xfa, 0x2c, 0x76, 0x67, 0x8a, 0x8e, 0xc4, 0x1f, 0xfe, 0xb1, 0x5b, - 0x13, 0x3e, 0x4c, 0xdf, 0xfd, 0x8f, 0xf6, 0x93, 0x2f, 0xf9, 0xe9, 0xe1, 0x84, 0xb6, 0xfe, 0xa4, 0xf7, 0xd5, 0x29, - 0x1c, 0xee, 0x5e, 0xdf, 0xf8, 0x65, 0x9b, 0x52, 0xf2, 0x1f, 0xf7, 0x2b, 0x25, 0x5f, 0x2e, 0xf6, 0x51, 0x4a, 0xfe, - 0xe3, 0x8b, 0x2b, 0x25, 0x7f, 0xa9, 0xfa, 0xd6, 0xbc, 0xa9, 0xe6, 0x9a, 0xfe, 0xe3, 0xba, 0x2a, 0x72, 0x48, 0x3c, - 0xed, 0xea, 0xc7, 0xc5, 0x35, 0xc4, 0x8f, 0x7f, 0x13, 0xb9, 0x2f, 0x17, 0x25, 0x83, 0xcf, 0x08, 0x70, 0xec, 0x9b, - 0x88, 0x70, 0xec, 0x87, 0x85, 0x0b, 0x56, 0x66, 0x9c, 0xcd, 0xf1, 0x47, 0xe6, 0xd4, 0x0b, 0xc6, 0x39, 0x8b, 0x04, - 0x25, 0x5d, 0x2c, 0x06, 0xbf, 0x79, 0x20, 0xcf, 0x70, 0x93, 0x59, 0xcc, 0xc2, 0x04, 0x2c, 0x82, 0xc1, 0x92, 0x63, - 0x1c, 0x67, 0x95, 0xc6, 0x96, 0x88, 0xb8, 0x7f, 0xc3, 0x3d, 0x8a, 0xb7, 0xbe, 0x47, 0x03, 0xe0, 0xfa, 0xde, 0x9d, - 0xcd, 0x7e, 0x15, 0xb0, 0xac, 0x13, 0x06, 0xd2, 0xc0, 0xed, 0xd7, 0xbd, 0x2f, 0x9b, 0xe1, 0x56, 0x0c, 0xaf, 0xb7, - 0x43, 0x0a, 0x90, 0x54, 0xdb, 0x3b, 0x65, 0x33, 0xde, 0xfb, 0x86, 0x59, 0xf3, 0xf9, 0x52, 0xf3, 0x1d, 0x36, 0xc4, - 0x79, 0xc7, 0xd5, 0xa9, 0x5a, 0x97, 0xf8, 0xb4, 0xfa, 0x09, 0x29, 0x2e, 0xa8, 0x85, 0xa1, 0x71, 0xc1, 0xa9, 0xda, - 0x0a, 0xf2, 0x3b, 0xb6, 0xf4, 0xae, 0xd4, 0xa7, 0x6c, 0x9c, 0xfc, 0x6c, 0x8d, 0xf7, 0x0a, 0xff, 0x17, 0xe0, 0x44, - 0x39, 0xc7, 0x33, 0x88, 0xe4, 0x79, 0x5e, 0x4b, 0xfd, 0x92, 0x34, 0x22, 0x9b, 0x3a, 0xeb, 0x4d, 0x5e, 0x74, 0xab, - 0x5b, 0x82, 0xc3, 0x66, 0x82, 0x0b, 0xc2, 0xcf, 0x93, 0x13, 0x40, 0x46, 0x8e, 0x1a, 0xe8, 0xe7, 0xb0, 0xab, 0x33, - 0x51, 0xef, 0x11, 0x6c, 0x62, 0xee, 0x09, 0xa8, 0xc8, 0x21, 0x4d, 0xd7, 0xe3, 0x20, 0xf2, 0xd2, 0x0e, 0xb2, 0x69, - 0x12, 0xcb, 0xdb, 0x40, 0x8f, 0x85, 0xee, 0x0e, 0x63, 0x3a, 0xb9, 0x63, 0xde, 0x09, 0x7a, 0x3e, 0xec, 0xb2, 0xbf, - 0xcb, 0x1d, 0xce, 0xd6, 0x25, 0x73, 0x14, 0xa7, 0x75, 0x62, 0x38, 0xc7, 0x86, 0x75, 0xd2, 0xd2, 0x33, 0x71, 0xe0, - 0xe4, 0x2e, 0x4b, 0x13, 0x02, 0x0e, 0x10, 0x39, 0x98, 0x7e, 0xe8, 0xa7, 0xbe, 0x17, 0x64, 0xc0, 0x0f, 0x97, 0x2f, - 0x29, 0xff, 0x58, 0x24, 0x29, 0x8c, 0x51, 0x30, 0xbd, 0xe8, 0xfc, 0x61, 0x0e, 0x58, 0xba, 0x64, 0x2c, 0xdc, 0x62, - 0x18, 0x53, 0xf5, 0x25, 0xf9, 0xed, 0x2c, 0xeb, 0x33, 0xb2, 0x5a, 0x1b, 0xa4, 0x21, 0xdf, 0x1f, 0xc2, 0xf1, 0x21, - 0xeb, 0x1b, 0xdf, 0x6d, 0x43, 0xb8, 0x3f, 0xdf, 0x8f, 0x70, 0x53, 0xb6, 0x0f, 0xc2, 0xfd, 0xf9, 0x8b, 0x23, 0xdc, - 0xef, 0x64, 0x84, 0x5b, 0xf2, 0x1f, 0x2c, 0x34, 0x4c, 0xef, 0xf1, 0x59, 0x03, 0x17, 0xd9, 0xe7, 0xea, 0x21, 0x31, - 0xf0, 0xaa, 0x5e, 0xe4, 0xa8, 0xfd, 0xf3, 0x42, 0xb6, 0xa0, 0x46, 0x01, 0x28, 0xa6, 0x76, 0xf4, 0xd1, 0x75, 0xd9, - 0x07, 0x57, 0x37, 0x11, 0x86, 0x01, 0xfa, 0xfc, 0x3e, 0x4c, 0x03, 0xeb, 0x1d, 0xbf, 0x47, 0x82, 0x42, 0xf7, 0x4d, - 0x14, 0xcf, 0x3c, 0x4c, 0x31, 0xa2, 0xea, 0xe0, 0x4e, 0x07, 0x0f, 0x36, 0x04, 0x02, 0x19, 0x46, 0xe1, 0x28, 0xd7, - 0x4a, 0x32, 0xf7, 0x8a, 0x38, 0x6e, 0xf5, 0x8e, 0x79, 0xb1, 0x6a, 0xd0, 0x6b, 0x58, 0xdc, 0x67, 0x4d, 0xfb, 0x59, - 0xe3, 0xe8, 0xd9, 0xb1, 0x0d, 0xff, 0x3b, 0xac, 0x99, 0x19, 0xbc, 0xe2, 0x2c, 0x0a, 0xd3, 0x69, 0x51, 0x73, 0x5b, - 0xb5, 0x25, 0x63, 0x1f, 0x8b, 0x5a, 0x27, 0xf5, 0x95, 0x46, 0xde, 0x5d, 0x51, 0xa7, 0xb6, 0xc6, 0x34, 0x5a, 0x48, - 0x60, 0xd5, 0x40, 0xe3, 0x87, 0x0b, 0x90, 0xb3, 0x4b, 0x35, 0xe4, 0xd7, 0x7c, 0xb8, 0xc5, 0xb8, 0x58, 0x33, 0xbb, - 0x16, 0x39, 0x14, 0xd4, 0xae, 0x48, 0x9a, 0x7b, 0xef, 0x0c, 0x72, 0x15, 0xa5, 0x8d, 0x39, 0xa7, 0x30, 0x9b, 0x21, - 0x64, 0x9c, 0x62, 0x62, 0x81, 0x3c, 0x5a, 0xa0, 0x34, 0x5e, 0x84, 0x43, 0x0d, 0x7f, 0x7a, 0x83, 0x44, 0xf3, 0x0f, - 0x63, 0x8b, 0x7f, 0x58, 0xc7, 0x55, 0xf3, 0x7a, 0x76, 0x91, 0x5a, 0x3e, 0x11, 0xab, 0xe2, 0x3d, 0x4b, 0x8d, 0x18, - 0xf5, 0xd8, 0xb4, 0xb4, 0xa6, 0xeb, 0x3d, 0xcb, 0x1b, 0x3e, 0x4b, 0x8d, 0xf0, 0x39, 0xe8, 0x3e, 0x5d, 0xfb, 0xc9, - 0x13, 0xaa, 0x75, 0xe0, 0x8a, 0x61, 0x9d, 0x0d, 0x8b, 0xcc, 0x14, 0x8a, 0x37, 0x89, 0x28, 0x39, 0x45, 0x67, 0x68, - 0x44, 0xcf, 0x9f, 0xf7, 0x5c, 0x47, 0x1f, 0xc4, 0xcc, 0xfb, 0x98, 0x89, 0x70, 0xdf, 0x21, 0x66, 0xa1, 0xbd, 0xd8, - 0xcf, 0xd0, 0x48, 0xaf, 0x75, 0xa5, 0x9d, 0xc3, 0x9d, 0xc9, 0x16, 0xee, 0x08, 0x1c, 0x7b, 0x41, 0x86, 0x7a, 0x32, - 0x28, 0xf0, 0x84, 0xc1, 0x8f, 0xa8, 0x93, 0xdf, 0xba, 0x9a, 0x96, 0x6d, 0xd9, 0x6a, 0xde, 0x70, 0xec, 0x4f, 0xdc, - 0x75, 0x94, 0x7a, 0x9d, 0x03, 0xc7, 0x08, 0xa2, 0x09, 0xf8, 0xd1, 0xa5, 0x7e, 0x1a, 0xb0, 0x8e, 0xaa, 0x82, 0x43, - 0xdd, 0x8c, 0xee, 0xe5, 0x19, 0xf7, 0x6e, 0xf0, 0x62, 0x48, 0x4e, 0x1e, 0xdf, 0x09, 0x57, 0x5c, 0x0c, 0x96, 0xfe, - 0x03, 0x10, 0x43, 0x4d, 0xd5, 0x40, 0x36, 0xc0, 0xe2, 0xc4, 0x94, 0xbd, 0x85, 0x3a, 0x0a, 0xb4, 0xd1, 0x55, 0x3e, - 0x88, 0x71, 0xec, 0xcd, 0x20, 0x7b, 0xee, 0x3a, 0x33, 0x38, 0xa6, 0x55, 0x39, 0xaa, 0x55, 0x9c, 0x17, 0xc7, 0x86, - 0xd2, 0x70, 0x0c, 0xc5, 0x06, 0x74, 0xab, 0x66, 0xc6, 0x3a, 0xbb, 0xee, 0xde, 0x67, 0xf0, 0x40, 0xf8, 0xe5, 0x11, - 0x8d, 0x83, 0x4c, 0x1d, 0xb8, 0x2a, 0x29, 0xa5, 0x24, 0x39, 0x9a, 0x94, 0x35, 0xd3, 0x27, 0xa5, 0xe7, 0x25, 0x5b, - 0xa5, 0x3a, 0x68, 0x8e, 0x44, 0x15, 0x5f, 0x5f, 0xa3, 0xc3, 0xb0, 0x1f, 0x2a, 0xfe, 0xa7, 0x4f, 0x9a, 0x0f, 0xce, - 0x4c, 0xae, 0x34, 0x3f, 0xf0, 0xac, 0x97, 0x26, 0xcc, 0x2f, 0xd4, 0xf4, 0x38, 0x59, 0xe0, 0x69, 0x08, 0xff, 0x16, - 0xc5, 0xe2, 0x07, 0x37, 0x93, 0xb0, 0x02, 0x2f, 0x9c, 0x00, 0x4a, 0xf3, 0xc2, 0xc9, 0x86, 0x39, 0x16, 0xf9, 0x3c, - 0x57, 0x4a, 0x8b, 0xae, 0x0a, 0x53, 0xa9, 0xe4, 0xe5, 0xdd, 0xa5, 0x37, 0xf9, 0xd1, 0x9b, 0x31, 0x4d, 0x05, 0x2a, - 0x87, 0x2e, 0xba, 0x85, 0x26, 0xf7, 0xb9, 0xfb, 0xf4, 0x74, 0xc6, 0x52, 0x8f, 0xd4, 0x40, 0x70, 0xf9, 0x05, 0x76, - 0x40, 0xe1, 0x84, 0x86, 0x07, 0xbc, 0x70, 0x29, 0x97, 0x16, 0xd1, 0x09, 0x43, 0xe1, 0x74, 0xca, 0x44, 0x8b, 0x4f, - 0xd7, 0x31, 0xc8, 0xe1, 0x60, 0xe8, 0x61, 0x3e, 0x1d, 0x37, 0x8c, 0xd4, 0xde, 0xd3, 0xdc, 0x37, 0x73, 0xdb, 0x22, - 0x04, 0x7e, 0xf8, 0xf1, 0x2a, 0x66, 0xc1, 0x3f, 0xdd, 0xa7, 0x40, 0xb8, 0x9f, 0x5e, 0xab, 0x7a, 0x37, 0xb5, 0xa6, - 0x31, 0x1b, 0xbb, 0x4f, 0xe1, 0x42, 0xda, 0x41, 0xf3, 0x58, 0xe0, 0xda, 0x9f, 0xaf, 0x66, 0x81, 0x81, 0xd7, 0x7b, - 0x82, 0x45, 0x6d, 0x36, 0x8a, 0xb8, 0xe6, 0xcd, 0xbd, 0x2e, 0xf5, 0x3d, 0x7e, 0x5b, 0x87, 0x1b, 0xe0, 0xba, 0x74, - 0xc7, 0x76, 0xba, 0x78, 0x7f, 0x1e, 0x04, 0xde, 0xf0, 0x63, 0x97, 0xde, 0x94, 0x1e, 0x4c, 0xa0, 0xd6, 0x43, 0x6f, - 0xde, 0x41, 0xf2, 0x2a, 0x17, 0x82, 0xf7, 0x34, 0x95, 0xe6, 0x9c, 0x5d, 0xed, 0x5e, 0xc6, 0xad, 0xbc, 0xc6, 0x2f, - 0xe3, 0xa7, 0x96, 0x53, 0x3f, 0x65, 0xe2, 0x53, 0xf8, 0x90, 0x65, 0xe2, 0xa2, 0x4e, 0x57, 0x54, 0xbc, 0x58, 0x5b, - 0x4d, 0xc5, 0x69, 0x7f, 0xd7, 0xba, 0x75, 0xec, 0x69, 0xc3, 0xb1, 0xda, 0x1f, 0x9c, 0xf6, 0xb4, 0x69, 0x9d, 0x04, - 0x66, 0xd3, 0x3a, 0x81, 0x3f, 0x1f, 0x4e, 0xac, 0xf6, 0xd4, 0x6c, 0x58, 0x47, 0x1f, 0x9c, 0x46, 0x60, 0xb6, 0xad, - 0x13, 0xf8, 0x73, 0x41, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, - 0x89, 0xbc, 0xd5, 0xe8, 0x75, 0xe7, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0xbb, 0x5a, 0xe8, 0x32, 0x4a, 0x24, 0x2b, - 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0x59, 0x7b, 0x8c, 0x78, 0x9b, 0xfa, 0x0c, 0x96, 0xba, 0xc8, 0x05, 0x8c, - 0xcf, 0x3f, 0xcf, 0x31, 0xfe, 0xba, 0x48, 0xbc, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x89, 0xb6, 0x15, - 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xfc, 0xd6, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, - 0x21, 0x67, 0x9f, 0x1c, 0xf9, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xfa, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, - 0x7c, 0xeb, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0xf2, 0x20, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, - 0x9d, 0x16, 0x90, 0xdd, 0x16, 0x6b, 0xee, 0xb4, 0xa9, 0xa4, 0x9b, 0xce, 0x2e, 0xdf, 0xea, 0x22, 0xd3, 0x91, 0xb0, - 0x9b, 0x12, 0x16, 0x1b, 0x5b, 0x0d, 0x3b, 0x37, 0xec, 0x35, 0x20, 0x55, 0x5c, 0xe5, 0xaa, 0xa3, 0xea, 0xdd, 0x50, - 0x98, 0x1f, 0x84, 0x3b, 0x92, 0xbc, 0xf1, 0xbb, 0x98, 0x0a, 0x53, 0xb3, 0x63, 0x1c, 0xf7, 0x38, 0x88, 0xff, 0xa7, - 0x07, 0x81, 0xce, 0x9a, 0x60, 0x2f, 0x51, 0x39, 0xad, 0x25, 0xe7, 0xbd, 0x9c, 0xae, 0x12, 0x41, 0x65, 0xc9, 0x99, - 0x0a, 0x45, 0x6a, 0x47, 0x45, 0xc7, 0x30, 0x35, 0x37, 0x16, 0xcd, 0xa9, 0x45, 0x51, 0x60, 0xf8, 0x98, 0x50, 0x53, - 0x38, 0x8e, 0xea, 0x4f, 0x9e, 0x6c, 0x25, 0x42, 0x64, 0x9c, 0x93, 0xb0, 0x54, 0x30, 0xe8, 0x9a, 0x2a, 0xe3, 0x37, - 0x55, 0x46, 0x31, 0x79, 0xbf, 0x88, 0x35, 0x84, 0x8d, 0x2b, 0xed, 0x3d, 0xfc, 0x39, 0x60, 0x5e, 0x6a, 0x71, 0x65, - 0xa9, 0x26, 0x11, 0x77, 0xc3, 0x61, 0x4d, 0xb0, 0x6e, 0xe5, 0x69, 0x1a, 0x78, 0x1a, 0x94, 0xc7, 0xeb, 0x3f, 0x2f, - 0x78, 0x54, 0x07, 0xe8, 0xe3, 0x93, 0x5d, 0xc4, 0xe1, 0x7c, 0x9b, 0x7a, 0x14, 0x07, 0x4d, 0x26, 0xb9, 0x51, 0xea, - 0x91, 0x3d, 0x87, 0x8f, 0xa1, 0x6b, 0xea, 0x23, 0x72, 0x49, 0x91, 0x1f, 0x7a, 0x6f, 0x2f, 0xbf, 0x51, 0xf8, 0xfe, - 0x27, 0x6b, 0x01, 0xbc, 0xc8, 0x50, 0xbc, 0x19, 0x97, 0xe2, 0xcd, 0x28, 0x3c, 0x93, 0x31, 0xe4, 0x5c, 0xcd, 0x0e, - 0x69, 0x06, 0x51, 0x00, 0x4d, 0x36, 0x14, 0xb3, 0x45, 0x90, 0xfa, 0x73, 0x2f, 0x4e, 0x0f, 0x31, 0xd8, 0x0c, 0x06, - 0xaf, 0xd9, 0x16, 0x0f, 0x82, 0xcc, 0x30, 0x44, 0x76, 0x90, 0x34, 0x14, 0x76, 0x18, 0x63, 0x3f, 0xc8, 0xcd, 0x30, - 0xc4, 0x07, 0xbc, 0xe1, 0x90, 0xcd, 0x53, 0xb7, 0x14, 0xd4, 0x26, 0x1a, 0xa6, 0x2c, 0x35, 0x93, 0x34, 0x66, 0xde, - 0x4c, 0xcd, 0x83, 0x5c, 0x6d, 0xf6, 0x97, 0x2c, 0x06, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, - 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0x2f, 0xa2, 0x49, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x19, 0x26, 0x09, 0xa3, 0x9b, - 0x0c, 0x48, 0x8b, 0x87, 0x51, 0x70, 0xc3, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xde, 0x29, 0xbf, 0xde, 0x2a, 0x18, - 0xbe, 0x45, 0x6d, 0xd9, 0x90, 0x06, 0x6d, 0x5b, 0x74, 0x8b, 0x43, 0x5e, 0x19, 0x48, 0x13, 0xf5, 0x8c, 0x99, 0x2c, - 0x09, 0x96, 0x4b, 0x60, 0x84, 0x4a, 0x06, 0x33, 0x53, 0xa7, 0x97, 0xbb, 0x53, 0x22, 0x54, 0xc8, 0x2b, 0x7d, 0xfa, - 0xf4, 0xbe, 0xff, 0xef, 0x7f, 0x41, 0xba, 0xcd, 0xa9, 0x23, 0x62, 0x4a, 0x5c, 0xc9, 0xb5, 0x38, 0xf7, 0x69, 0xf4, - 0xd1, 0x58, 0x8a, 0x8d, 0x44, 0xb4, 0x3f, 0xb1, 0xb5, 0xb2, 0xfe, 0xb5, 0x88, 0x53, 0x07, 0x89, 0x7a, 0x75, 0x11, - 0xf9, 0xa2, 0x0f, 0xcb, 0xdb, 0x17, 0x31, 0x51, 0x94, 0xbf, 0xaf, 0x5e, 0x9e, 0x28, 0x45, 0xf8, 0xc4, 0x3a, 0x8b, - 0x1e, 0xda, 0x43, 0xbd, 0x53, 0x4f, 0x41, 0xa6, 0x05, 0xd9, 0x8f, 0xa4, 0x73, 0x08, 0xc3, 0x9c, 0x46, 0x33, 0x66, - 0xf9, 0xd1, 0xe1, 0x92, 0x0d, 0x4c, 0x6f, 0xee, 0x93, 0x5d, 0x0e, 0xca, 0xdd, 0x14, 0xe2, 0xfc, 0x72, 0x73, 0x17, - 0xe2, 0xaf, 0xb3, 0x62, 0x2a, 0xa3, 0x4a, 0x20, 0xb4, 0x46, 0xa1, 0x07, 0x3c, 0xe2, 0x41, 0xc6, 0x44, 0xcd, 0xde, - 0xe9, 0xa1, 0xd7, 0x2b, 0x67, 0x9e, 0xb1, 0x44, 0x06, 0xd5, 0x32, 0x11, 0x38, 0xa3, 0x04, 0x32, 0x22, 0x57, 0x4c, - 0xf1, 0x60, 0x46, 0xe3, 0xb1, 0x9c, 0x2d, 0xc6, 0x2a, 0x83, 0x97, 0x4f, 0x5a, 0xb1, 0xa5, 0xa3, 0x39, 0x7d, 0x69, - 0xf3, 0x13, 0xf9, 0x4f, 0xb5, 0x83, 0x69, 0xa2, 0x60, 0xcc, 0x70, 0xdc, 0x37, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, - 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x85, 0x73, 0x39, 0x70, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0x58, - 0x93, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x9b, 0x30, 0x1e, 0x7a, 0x62, - 0xfb, 0x95, 0x36, 0x28, 0x6c, 0x3c, 0xbe, 0xee, 0x80, 0xdf, 0x45, 0x3f, 0x15, 0x34, 0xaf, 0x7c, 0x4d, 0x18, 0xdd, - 0x0c, 0xbc, 0xbb, 0x48, 0x32, 0x63, 0xe2, 0x11, 0x4d, 0x2e, 0xb0, 0xf4, 0x52, 0x78, 0x12, 0x6f, 0x1c, 0x34, 0x24, - 0x61, 0x90, 0x75, 0x73, 0xf3, 0xb0, 0x15, 0xf4, 0x37, 0x60, 0xf7, 0x9d, 0x35, 0xb9, 0x6e, 0x79, 0x30, 0x88, 0x3c, - 0xb3, 0xe2, 0x1c, 0x96, 0x5e, 0x22, 0x5a, 0xc8, 0x4e, 0x0f, 0x61, 0x7c, 0x10, 0x85, 0xa5, 0xc4, 0x38, 0xf9, 0x3a, - 0x84, 0x7a, 0xf1, 0x12, 0x32, 0xc5, 0xfa, 0x7e, 0x24, 0x78, 0x3e, 0xbc, 0x58, 0x4a, 0xb9, 0xe4, 0xa5, 0x2a, 0x9b, - 0xbc, 0x8c, 0x5d, 0xcf, 0x04, 0xde, 0x9f, 0xa2, 0xf6, 0xc3, 0x02, 0xf3, 0xd3, 0x66, 0xdd, 0x94, 0x89, 0x20, 0x07, - 0x17, 0xe9, 0x96, 0x38, 0x08, 0xdb, 0xaa, 0x10, 0x3f, 0xbb, 0xa3, 0x42, 0xb1, 0x8f, 0x77, 0xd5, 0x2a, 0x38, 0xa7, - 0xa2, 0x9a, 0xa7, 0xa9, 0x8f, 0x70, 0xc7, 0x6f, 0xd4, 0xc6, 0x52, 0x8c, 0xce, 0x90, 0xba, 0x50, 0x55, 0xc8, 0xe2, - 0xbd, 0xf9, 0x9c, 0x2a, 0xeb, 0xdd, 0xd3, 0x43, 0xba, 0x96, 0xf6, 0x68, 0x87, 0xf5, 0x4e, 0xc1, 0x94, 0x9b, 0x16, - 0xdd, 0x9b, 0xcf, 0xf9, 0x92, 0xd2, 0x2f, 0x7a, 0x73, 0x38, 0x4d, 0x67, 0x41, 0xef, 0x7f, 0x01, 0xb9, 0x4b, 0x40, - 0x75, 0x91, 0x7a, 0x03, 0x00}; + 0xe1, 0xd7, 0x47, 0x5a, 0xee, 0x82, 0xd5, 0x42, 0xba, 0x4e, 0x0b, 0x96, 0x9b, 0x28, 0x37, 0x1b, 0xb7, 0x15, 0xaa, + 0x16, 0x77, 0x07, 0xbb, 0x09, 0xfa, 0x2f, 0xc0, 0x6c, 0x73, 0x88, 0xbf, 0x32, 0xa2, 0x8c, 0xe6, 0x59, 0x0c, 0x8d, + 0x1c, 0x34, 0x0f, 0x4e, 0x0b, 0x36, 0x47, 0x7e, 0x50, 0xc9, 0xfd, 0x6e, 0xc1, 0xe6, 0x9b, 0xc4, 0x54, 0x5f, 0x19, + 0x34, 0xa2, 0x39, 0x9f, 0x8a, 0x34, 0x63, 0x80, 0xe2, 0x9b, 0x84, 0x09, 0xcd, 0xf5, 0x5d, 0xb3, 0x90, 0x37, 0xab, + 0x31, 0x57, 0x8b, 0x9c, 0xde, 0xa5, 0x93, 0x9c, 0xdd, 0xf6, 0x4c, 0xa9, 0x26, 0xd7, 0x6c, 0xae, 0x5c, 0xd9, 0x1e, + 0xa4, 0x37, 0xc7, 0xd6, 0xb4, 0x02, 0x66, 0x22, 0x6f, 0xb6, 0xf7, 0x98, 0x07, 0x60, 0x53, 0x2e, 0xf5, 0x41, 0x4b, + 0xf5, 0xe6, 0x5c, 0x34, 0xdd, 0x40, 0xce, 0x60, 0x75, 0x76, 0xa1, 0x10, 0xf4, 0x9f, 0xb0, 0xdb, 0x05, 0x15, 0x63, + 0x36, 0x5e, 0x05, 0xd5, 0x3a, 0x50, 0x2f, 0x2c, 0x95, 0x0a, 0x3d, 0x6b, 0x1a, 0x7b, 0xb0, 0xb8, 0x23, 0xd0, 0x57, + 0xd0, 0xef, 0x41, 0x0b, 0xdb, 0xff, 0x4f, 0xda, 0x28, 0xac, 0x7c, 0x00, 0xa1, 0x99, 0xf8, 0xe4, 0xae, 0x09, 0x7f, + 0x57, 0xe0, 0x7f, 0xc4, 0x33, 0x9a, 0x3b, 0x88, 0xcc, 0xf9, 0x78, 0x9c, 0xd7, 0x46, 0x74, 0x15, 0x74, 0xd6, 0x46, + 0x2b, 0x98, 0x7f, 0xda, 0x3a, 0x68, 0x1d, 0x98, 0xb9, 0x38, 0x94, 0x3c, 0x3b, 0xbb, 0x7f, 0xfa, 0x80, 0xf5, 0x72, + 0x2e, 0x58, 0x6d, 0xaa, 0xdf, 0x04, 0x75, 0xd8, 0x70, 0xc7, 0x35, 0xdc, 0x3e, 0x68, 0x1f, 0x9c, 0xb5, 0xbe, 0xf3, + 0x3b, 0x3a, 0x67, 0x13, 0x6d, 0x71, 0xb8, 0xb6, 0xc5, 0x2f, 0x7c, 0xd3, 0x37, 0x05, 0x5d, 0xa4, 0x42, 0xc2, 0x9f, + 0x1e, 0x6c, 0xc4, 0x49, 0x2e, 0x6f, 0xd2, 0x19, 0x1f, 0x8f, 0xc1, 0x9d, 0x0a, 0x0a, 0x94, 0x89, 0x2c, 0xcf, 0xf9, + 0x42, 0x71, 0xbb, 0x1a, 0x0e, 0xdd, 0xba, 0x5b, 0x50, 0x0d, 0x07, 0x74, 0x1a, 0x0c, 0xa8, 0x5b, 0x0d, 0xa8, 0xea, + 0x3f, 0x1c, 0x61, 0x67, 0x6b, 0xae, 0xa6, 0x54, 0xaf, 0x86, 0x49, 0x9f, 0x96, 0x4a, 0x03, 0xcc, 0xbd, 0x21, 0x87, + 0xa1, 0xf4, 0xcd, 0x11, 0xd3, 0x37, 0x8c, 0x89, 0xaf, 0x0f, 0xe2, 0x2a, 0x95, 0x22, 0xbf, 0xb3, 0x9f, 0xab, 0xb0, + 0x4b, 0xba, 0xd4, 0x72, 0x93, 0x8c, 0xb8, 0xa0, 0xc5, 0xdd, 0x47, 0xc5, 0x84, 0x92, 0xc5, 0x47, 0x39, 0x99, 0xac, + 0xbe, 0x46, 0x7e, 0xee, 0xa3, 0x4d, 0xa2, 0xb8, 0x98, 0xe6, 0xcc, 0x12, 0x1b, 0x83, 0x08, 0x8e, 0xe0, 0xdb, 0x76, + 0x4d, 0x93, 0xb5, 0x41, 0x6f, 0x92, 0x2c, 0xe7, 0x73, 0xaa, 0x99, 0x81, 0x73, 0xb8, 0x49, 0x5d, 0x0d, 0x43, 0x71, + 0x5a, 0x07, 0xf6, 0x4f, 0x55, 0x1a, 0xb6, 0x51, 0x50, 0xd8, 0x37, 0xc9, 0x85, 0xc1, 0x0f, 0x03, 0x0e, 0xb3, 0x8b, + 0xcc, 0xea, 0x99, 0xb5, 0x0b, 0x60, 0x07, 0xb3, 0xab, 0x35, 0x75, 0x55, 0xa3, 0x11, 0xdd, 0xd6, 0x77, 0xf5, 0xdc, + 0x9c, 0x8e, 0x58, 0xbe, 0xb2, 0x1b, 0xd5, 0x03, 0xd7, 0x6d, 0xd5, 0x70, 0x99, 0x03, 0x92, 0x61, 0x40, 0x34, 0x4c, + 0xd3, 0xe6, 0x0d, 0x1b, 0x7d, 0xe6, 0xda, 0x6e, 0x99, 0xa6, 0xba, 0x01, 0x07, 0x1f, 0x33, 0xa6, 0x05, 0x2b, 0x56, + 0x9e, 0xa8, 0xb6, 0x6a, 0xc4, 0xec, 0x17, 0x61, 0x0e, 0x4b, 0x4d, 0x47, 0x4d, 0x08, 0x77, 0xc6, 0x8a, 0xd5, 0xbe, + 0xc9, 0xcd, 0xe9, 0xad, 0x43, 0xb1, 0x07, 0xad, 0xef, 0x6a, 0x07, 0xde, 0x59, 0xab, 0xe5, 0xc9, 0x75, 0xd3, 0xd6, + 0x48, 0xdb, 0x49, 0x97, 0xcd, 0xcb, 0x44, 0x2d, 0x17, 0x69, 0x2d, 0x61, 0x24, 0xb5, 0x96, 0x73, 0x9b, 0xb6, 0x87, + 0x1a, 0xd5, 0xa9, 0x65, 0xbb, 0xb3, 0xb8, 0x3d, 0x30, 0xff, 0xb4, 0x0e, 0x5a, 0xbb, 0x87, 0xf1, 0x2e, 0x56, 0x9c, + 0x22, 0x8f, 0xc7, 0xd0, 0x71, 0x9b, 0xcd, 0x7b, 0x4b, 0x05, 0x47, 0xaf, 0x81, 0xb8, 0x39, 0x5d, 0x36, 0x66, 0xb2, + 0x00, 0x58, 0xca, 0x05, 0x9c, 0x74, 0xf6, 0xe0, 0x81, 0x3e, 0x94, 0x04, 0xd3, 0xf4, 0xbd, 0x8d, 0xd6, 0x87, 0xd5, + 0x3a, 0xa8, 0x06, 0x06, 0xff, 0x6c, 0xfe, 0xaa, 0x78, 0xe5, 0x27, 0x2c, 0x90, 0x55, 0x78, 0x23, 0xe9, 0xae, 0x5b, + 0x4e, 0x3e, 0x19, 0xeb, 0x4a, 0x6c, 0x32, 0xde, 0x1d, 0x73, 0x7a, 0x6b, 0xdd, 0x3c, 0xe6, 0x5c, 0x80, 0x11, 0x19, + 0xc2, 0x3a, 0x30, 0xb7, 0x9f, 0x85, 0x0d, 0x8d, 0x75, 0x0c, 0x0d, 0x1f, 0x77, 0x92, 0x6e, 0x17, 0xe1, 0x16, 0xee, + 0x74, 0xbb, 0x81, 0x7c, 0x34, 0xd1, 0xfb, 0x8a, 0xee, 0x2b, 0x29, 0xf7, 0x94, 0x3c, 0x31, 0x8d, 0x9e, 0xb4, 0x5b, + 0x2d, 0x6c, 0x5c, 0xd9, 0xcb, 0xc2, 0x42, 0xed, 0x69, 0xb6, 0xdd, 0x6a, 0x41, 0xb3, 0xf0, 0xc7, 0xcd, 0xeb, 0x27, + 0xb2, 0x6a, 0xa5, 0x2d, 0xdc, 0x4e, 0xdb, 0xb8, 0x93, 0x76, 0xf0, 0x69, 0x7a, 0x8a, 0xcf, 0xd2, 0x33, 0xdc, 0x4d, + 0xbb, 0xf8, 0x3c, 0x3d, 0xc7, 0xf7, 0xd3, 0xfb, 0xf8, 0x22, 0xbd, 0xc0, 0x0f, 0xd2, 0x07, 0xf8, 0x61, 0xda, 0x6e, + 0xe1, 0x47, 0x69, 0xbb, 0x8d, 0x1f, 0xa7, 0xed, 0x0e, 0x7e, 0x92, 0xb6, 0x4f, 0xf1, 0xd3, 0xb4, 0x7d, 0x86, 0x9f, + 0xa5, 0xed, 0x2e, 0xa6, 0x90, 0x3b, 0x82, 0xdc, 0x0c, 0x72, 0xc7, 0x90, 0xcb, 0x20, 0x77, 0x92, 0xb6, 0xbb, 0x1b, + 0x2c, 0x6d, 0xf8, 0x8b, 0xa8, 0xd5, 0xee, 0x9c, 0x9e, 0x75, 0xcf, 0xef, 0x5f, 0x3c, 0x78, 0xf8, 0xe8, 0xf1, 0x93, + 0xa7, 0xcf, 0xa2, 0x21, 0xbe, 0x33, 0x5e, 0x28, 0x52, 0x0c, 0xf8, 0x51, 0xbb, 0x3b, 0xc4, 0xb7, 0xfe, 0x33, 0xe6, + 0x47, 0x9d, 0xb3, 0x16, 0xba, 0xba, 0x3a, 0x1b, 0x36, 0xca, 0xdc, 0x47, 0xc6, 0xf9, 0xa5, 0xca, 0x22, 0x84, 0xc4, + 0x90, 0x83, 0xf0, 0x17, 0xeb, 0xcc, 0xc2, 0x62, 0x9e, 0x14, 0xe8, 0xe8, 0xc8, 0xfc, 0x98, 0xfa, 0x1f, 0x23, 0xff, + 0x83, 0x06, 0x8b, 0x74, 0x43, 0x63, 0xe7, 0xfd, 0xac, 0x4b, 0xdf, 0x83, 0xd2, 0xac, 0xe7, 0x80, 0x3b, 0x03, 0xfb, + 0xff, 0x8a, 0xac, 0x01, 0x0d, 0x39, 0xb3, 0x4a, 0xaa, 0x6e, 0x9f, 0x91, 0x55, 0x91, 0x76, 0xba, 0xdd, 0xa3, 0x9f, + 0x06, 0x7c, 0xd0, 0x1e, 0x0e, 0x8f, 0xdb, 0xf7, 0xf1, 0xb4, 0x4c, 0xe8, 0xd8, 0x84, 0x51, 0x99, 0x70, 0x6a, 0x13, + 0x68, 0x6a, 0x6b, 0x43, 0xd2, 0x99, 0x49, 0x82, 0x12, 0x9b, 0xd4, 0xb4, 0x7d, 0xdf, 0xb6, 0xfd, 0x00, 0x2c, 0xbb, + 0x4c, 0xf3, 0xae, 0xe9, 0xcb, 0xcb, 0xb3, 0xb5, 0x6b, 0x14, 0x4f, 0x53, 0xd7, 0x9a, 0x4f, 0x3c, 0x1b, 0x0e, 0xf1, + 0xc8, 0x24, 0x76, 0xab, 0xc4, 0xf3, 0xe1, 0xd0, 0x75, 0xf5, 0xc0, 0x74, 0x75, 0xbf, 0xca, 0xba, 0x18, 0x0e, 0x4d, + 0x97, 0xc8, 0xf9, 0xf1, 0x2b, 0x7d, 0xf0, 0xb9, 0xd4, 0xa5, 0xf0, 0xcb, 0x4e, 0xb7, 0xdb, 0x07, 0x0c, 0x33, 0xf6, + 0xb9, 0x1e, 0x46, 0xd7, 0x01, 0x8c, 0xbe, 0xc0, 0xef, 0xfe, 0x1d, 0x4d, 0x6f, 0x69, 0x09, 0xa4, 0x7e, 0xf4, 0x5f, + 0x51, 0x43, 0x1b, 0x98, 0x9b, 0x3f, 0x53, 0xfb, 0x67, 0x84, 0x1a, 0x9f, 0x29, 0x80, 0x1b, 0xb4, 0x43, 0x5e, 0xbd, + 0x6b, 0x7a, 0xfc, 0x85, 0x82, 0xbb, 0xcd, 0x4c, 0xe5, 0xb4, 0xbf, 0x9e, 0xdd, 0x8c, 0xd6, 0x33, 0xf5, 0x05, 0xfd, + 0x19, 0xff, 0xa9, 0x8e, 0xe3, 0x41, 0xb3, 0x91, 0xb0, 0x3f, 0xc7, 0xe0, 0xd7, 0xd3, 0x4f, 0xc7, 0x6c, 0x8a, 0xfa, + 0x83, 0x3f, 0x15, 0x1e, 0x36, 0x82, 0x8c, 0xef, 0x76, 0x53, 0xc0, 0xeb, 0x67, 0x3b, 0x31, 0xfe, 0x0e, 0xf5, 0x51, + 0xff, 0x4f, 0x75, 0xfc, 0x27, 0xba, 0x77, 0x12, 0x68, 0x30, 0xa4, 0xdb, 0xc2, 0x55, 0x28, 0xa0, 0xe3, 0x72, 0x0b, + 0x33, 0xdc, 0x6e, 0x32, 0x08, 0x9c, 0x06, 0x6e, 0xe1, 0x24, 0x96, 0x0d, 0x7e, 0x72, 0xda, 0x42, 0xdf, 0xb5, 0x3b, + 0xa0, 0xe8, 0x68, 0x8a, 0xe3, 0xdd, 0x4d, 0x5f, 0x34, 0x4f, 0xf1, 0x83, 0x66, 0x81, 0xdb, 0x08, 0x37, 0xdb, 0x5e, + 0x03, 0x3d, 0x50, 0x71, 0x0b, 0x61, 0x15, 0x5f, 0xc0, 0x3f, 0x67, 0x68, 0x58, 0x6d, 0xc8, 0xc7, 0x74, 0xbb, 0x77, + 0xf0, 0x61, 0x25, 0xb1, 0x6a, 0xf0, 0x93, 0xf3, 0x16, 0xfa, 0xee, 0xdc, 0x74, 0xc4, 0x8e, 0xf5, 0x9e, 0xae, 0x24, + 0x3e, 0x6b, 0x4a, 0xe8, 0xa8, 0x55, 0xf6, 0x23, 0xe2, 0x2e, 0xc2, 0x22, 0x3e, 0x85, 0x7f, 0xda, 0x61, 0x3f, 0xf7, + 0x76, 0xfa, 0x31, 0xf3, 0x6e, 0xe3, 0xa4, 0x6b, 0x5d, 0x62, 0x95, 0xbd, 0x9f, 0x6e, 0xb0, 0xab, 0xb6, 0xb9, 0x58, + 0x6b, 0x9f, 0xc0, 0x07, 0xc2, 0xfa, 0x98, 0x28, 0xcc, 0x8e, 0xc1, 0x97, 0x16, 0x4c, 0x48, 0xd4, 0xe5, 0x69, 0x4f, + 0x35, 0x1a, 0x48, 0x0c, 0xd4, 0xf0, 0x98, 0xb4, 0x9b, 0xba, 0xc9, 0x30, 0xfc, 0x6e, 0x90, 0x32, 0x40, 0x9b, 0xa8, + 0x7a, 0x7d, 0xe5, 0x7a, 0xb5, 0xb7, 0xf0, 0x1e, 0x3b, 0x08, 0x21, 0xaa, 0x1f, 0xeb, 0x26, 0x43, 0x27, 0xa2, 0x11, + 0xeb, 0x4b, 0xd6, 0x3f, 0x4f, 0x5b, 0xc8, 0x60, 0xa7, 0xea, 0xc7, 0xac, 0xc9, 0x21, 0xbd, 0x93, 0xc6, 0xbc, 0xa9, + 0xe1, 0xd7, 0x59, 0x00, 0x2d, 0x01, 0x78, 0x57, 0x79, 0x06, 0x15, 0x27, 0x9d, 0x6e, 0x17, 0x0b, 0xc2, 0x93, 0xa9, + 0xf9, 0xa5, 0x08, 0x4f, 0x46, 0xe6, 0x97, 0x24, 0x25, 0xbc, 0x6c, 0xef, 0xb8, 0x20, 0xc1, 0xaa, 0x9a, 0x14, 0x0a, + 0x0b, 0x5a, 0xa0, 0x93, 0x8e, 0xbf, 0xa2, 0xc7, 0x33, 0x3f, 0x07, 0x50, 0x49, 0x14, 0xc6, 0x3a, 0x53, 0x36, 0x0b, + 0x9c, 0x13, 0x7a, 0x95, 0x74, 0xfb, 0xb3, 0x93, 0xb8, 0xd3, 0x94, 0xcd, 0x02, 0xa5, 0xb3, 0x13, 0x53, 0x13, 0x67, + 0xe4, 0x15, 0xb5, 0xad, 0xe1, 0x19, 0xdc, 0xab, 0x66, 0x24, 0x3b, 0x3e, 0x6f, 0x35, 0x92, 0x2e, 0xc2, 0x83, 0x6c, + 0xdd, 0xc2, 0xf9, 0x7a, 0xdd, 0xc2, 0x34, 0x5c, 0x06, 0xe1, 0x01, 0x52, 0x6a, 0xcd, 0xb6, 0xe3, 0xe4, 0xf4, 0x79, + 0xac, 0xc1, 0x46, 0x40, 0x83, 0xe7, 0x8d, 0x06, 0x9f, 0xa0, 0x94, 0xbb, 0xcb, 0x39, 0x64, 0x22, 0x05, 0x4e, 0x42, + 0x3d, 0xda, 0x2b, 0xe1, 0xd7, 0xd5, 0x8d, 0xfc, 0x9e, 0x88, 0x3f, 0x48, 0x6c, 0xd3, 0xaa, 0x62, 0xaf, 0xe9, 0x6e, + 0xb1, 0x7b, 0x74, 0xa7, 0xd8, 0xc3, 0x3d, 0xc5, 0x1e, 0xef, 0x16, 0xfb, 0x5b, 0x06, 0x5a, 0x3f, 0xfe, 0xdd, 0xe9, + 0x79, 0xab, 0x71, 0x0a, 0xc8, 0x7a, 0x7a, 0xde, 0xaa, 0x0a, 0x3d, 0xa5, 0xd5, 0x5a, 0x69, 0xf2, 0x0b, 0xb5, 0x7e, + 0x0f, 0xdc, 0x3b, 0x60, 0x9b, 0x85, 0xb3, 0xee, 0xdf, 0xa5, 0xaf, 0xf7, 0xa0, 0x0b, 0x76, 0x25, 0xc2, 0x50, 0x3b, + 0x3d, 0x38, 0x1f, 0xf6, 0x67, 0x2c, 0x6e, 0x40, 0x2a, 0x4a, 0x27, 0xda, 0xfd, 0x42, 0xe5, 0xf5, 0xf2, 0xdf, 0x12, + 0x92, 0x3a, 0x43, 0x84, 0x25, 0x69, 0xe8, 0xc1, 0xe9, 0xd0, 0x9c, 0x77, 0x05, 0xfc, 0x3e, 0x33, 0xbf, 0x4b, 0xe5, + 0x8e, 0x73, 0x8e, 0x98, 0xdd, 0x8c, 0xa2, 0xbe, 0x20, 0xaf, 0x69, 0x6c, 0xec, 0xdd, 0x51, 0x5a, 0x66, 0xa8, 0x2f, + 0x90, 0xf1, 0xb0, 0xcc, 0x10, 0xe4, 0x95, 0x70, 0xbf, 0xf1, 0xaa, 0x48, 0xc1, 0xf6, 0x05, 0x4f, 0x53, 0xb0, 0x7b, + 0xc1, 0xa3, 0x54, 0x80, 0x6f, 0x06, 0x4d, 0x59, 0x60, 0x51, 0xff, 0xc2, 0x69, 0xd3, 0xcc, 0x0d, 0x30, 0x31, 0x58, + 0xda, 0x63, 0x70, 0x52, 0xfc, 0x2d, 0x63, 0xf8, 0xdb, 0xd0, 0x08, 0x33, 0x68, 0x93, 0x21, 0xcc, 0x93, 0x82, 0x40, + 0x1a, 0xe6, 0xc9, 0x94, 0x30, 0x68, 0x92, 0x27, 0x23, 0xc2, 0x06, 0x9d, 0x00, 0x4d, 0x9e, 0x18, 0xd8, 0x01, 0x70, + 0x78, 0xfd, 0x52, 0x5d, 0xdb, 0xc6, 0xe1, 0xb6, 0x1e, 0x9a, 0x10, 0x04, 0xe2, 0x1f, 0x0c, 0xc0, 0x84, 0x43, 0xd9, + 0x9f, 0x9d, 0x2a, 0x14, 0x25, 0x4f, 0xa8, 0xa1, 0xde, 0x7f, 0x01, 0x59, 0x8d, 0xef, 0xad, 0xd8, 0x06, 0x1f, 0xdc, + 0x5b, 0x89, 0xcd, 0x77, 0xf0, 0x47, 0xd9, 0x3f, 0xc0, 0x3c, 0x24, 0x14, 0x6d, 0xd0, 0x5f, 0x29, 0x14, 0xdb, 0x53, + 0x0a, 0xfd, 0xe5, 0x48, 0xb4, 0x52, 0x64, 0x75, 0x9b, 0x46, 0x63, 0x5a, 0x7c, 0x8e, 0xf0, 0x1f, 0x69, 0x94, 0x03, + 0xb7, 0x18, 0xe1, 0x0f, 0x69, 0x54, 0xb0, 0x08, 0xff, 0x9e, 0x46, 0xa3, 0x7c, 0x19, 0xe1, 0xdf, 0xd2, 0x68, 0x5a, + 0x44, 0xf8, 0x3d, 0x28, 0x4e, 0xc7, 0x7c, 0x39, 0x8f, 0xf0, 0xbb, 0x34, 0x52, 0xc6, 0x33, 0x01, 0x3f, 0x4c, 0x23, + 0xc6, 0x22, 0xfc, 0x36, 0x8d, 0x64, 0x1e, 0xe1, 0xeb, 0x34, 0x92, 0x45, 0x84, 0x1f, 0xa5, 0x51, 0x41, 0x23, 0xfc, + 0x38, 0x8d, 0xa0, 0xd0, 0x34, 0xc2, 0x4f, 0xd2, 0x08, 0x5a, 0x56, 0x11, 0x7e, 0x93, 0x46, 0x5c, 0x44, 0xf8, 0xd7, + 0x34, 0xd2, 0xcb, 0xe2, 0xef, 0xa5, 0xe4, 0x2a, 0xc2, 0x4f, 0xd3, 0x68, 0xc6, 0x23, 0xfc, 0x3a, 0x8d, 0x0a, 0x19, + 0xe1, 0x57, 0x69, 0x44, 0xf3, 0x08, 0xbf, 0x4c, 0xa3, 0x9c, 0x45, 0xf8, 0x97, 0x34, 0x1a, 0xb3, 0x08, 0xff, 0x9c, + 0x46, 0x77, 0x2c, 0xcf, 0x65, 0x84, 0x9f, 0xa5, 0x11, 0x13, 0x11, 0xfe, 0x29, 0x8d, 0xb2, 0x59, 0x84, 0x7f, 0x48, + 0x23, 0x5a, 0x7c, 0x56, 0x11, 0x7e, 0x9e, 0x46, 0x8c, 0x46, 0xf8, 0x85, 0xed, 0x68, 0x1a, 0xe1, 0x1f, 0xd3, 0xe8, + 0x66, 0x16, 0x6d, 0xb0, 0x54, 0x64, 0xf5, 0x8a, 0x67, 0xec, 0x77, 0x96, 0x46, 0x93, 0xd6, 0xe4, 0x62, 0x32, 0x89, + 0x30, 0x15, 0x9a, 0xff, 0xbd, 0x64, 0x37, 0x4f, 0x35, 0x24, 0x52, 0x36, 0x1a, 0xdf, 0x8f, 0x30, 0xfd, 0x7b, 0x49, + 0xd3, 0x68, 0x32, 0x31, 0x05, 0xfe, 0x5e, 0xd2, 0x39, 0x2d, 0xde, 0xb0, 0x34, 0xba, 0x3f, 0x99, 0x4c, 0xc6, 0x67, + 0x11, 0xa6, 0xff, 0x2c, 0x3f, 0x98, 0x16, 0x4c, 0x81, 0x11, 0xe3, 0x53, 0xa8, 0xdb, 0x9d, 0x74, 0xc7, 0x59, 0x84, + 0x47, 0x5c, 0xfd, 0xbd, 0x84, 0xef, 0x09, 0x3b, 0xcb, 0xce, 0x22, 0x3c, 0xca, 0x69, 0xf6, 0x39, 0x8d, 0x5a, 0xe6, + 0x97, 0xf8, 0x89, 0x8d, 0x5f, 0xcd, 0xa5, 0xb9, 0x56, 0x98, 0xb0, 0x51, 0x36, 0x8e, 0xb0, 0x19, 0xcc, 0x04, 0xfe, + 0x7e, 0xe1, 0x6f, 0x99, 0x4e, 0xa3, 0x0b, 0xda, 0x19, 0xb1, 0x4e, 0x84, 0x47, 0xaf, 0x6f, 0x44, 0x1a, 0xd1, 0x6e, + 0x87, 0x76, 0x68, 0x84, 0x47, 0xcb, 0x22, 0xbf, 0xbb, 0x91, 0x72, 0x0c, 0x40, 0x18, 0x5d, 0x5c, 0xdc, 0x8f, 0x70, + 0x46, 0x7f, 0xd1, 0x50, 0xbb, 0x3b, 0x79, 0xc0, 0x68, 0x2b, 0xc2, 0x3f, 0xd1, 0x42, 0x7f, 0x58, 0x2a, 0x37, 0xd0, + 0x16, 0xa4, 0xc8, 0xec, 0x2d, 0xa8, 0xdc, 0xa3, 0x71, 0xe7, 0xfc, 0x41, 0x9b, 0x45, 0x38, 0xbb, 0x7e, 0x05, 0xbd, + 0xdd, 0x9f, 0x74, 0x5b, 0xf0, 0x21, 0x40, 0x2e, 0x65, 0x05, 0x34, 0x72, 0x7e, 0xf6, 0xa0, 0xcb, 0xc6, 0x26, 0x51, + 0xf1, 0xfc, 0xb3, 0x99, 0xfd, 0x05, 0xcc, 0x27, 0x2b, 0xf8, 0x5c, 0x49, 0x91, 0x46, 0xe3, 0xac, 0x7d, 0x76, 0x0a, + 0x09, 0x77, 0x54, 0x78, 0xe0, 0xdc, 0x42, 0xd5, 0x8b, 0x51, 0x84, 0x6f, 0x6d, 0xea, 0xc5, 0xc8, 0x7c, 0x4c, 0xdf, + 0xfe, 0x22, 0x5e, 0x8f, 0xd3, 0x68, 0x74, 0x71, 0x71, 0xde, 0x82, 0x84, 0xdf, 0xe8, 0x5d, 0x1a, 0xd1, 0x07, 0xf0, + 0x1f, 0x64, 0x7f, 0x78, 0x06, 0x1d, 0xc2, 0x08, 0x6f, 0xa7, 0x1f, 0xc2, 0x9c, 0xcf, 0x33, 0xfa, 0x99, 0xa7, 0xd1, + 0x68, 0x3c, 0xba, 0x7f, 0x0e, 0xf5, 0xe6, 0x74, 0xfa, 0x4c, 0x53, 0x68, 0xb7, 0xd5, 0x32, 0x2d, 0xbf, 0xe5, 0x5f, + 0x98, 0xa9, 0xde, 0xed, 0x9e, 0x8f, 0x3a, 0x30, 0x82, 0x6b, 0x50, 0xa8, 0xc0, 0x78, 0x2e, 0x32, 0xd3, 0xe0, 0x75, + 0xf6, 0x74, 0x9c, 0x46, 0x0f, 0x1e, 0x9c, 0x76, 0xb2, 0x2c, 0xc2, 0xb7, 0x1f, 0xc6, 0xb6, 0xb6, 0xc9, 0x53, 0x00, + 0xfb, 0x34, 0x62, 0x0f, 0x1e, 0x9c, 0xdf, 0xa7, 0xf0, 0xfd, 0xdc, 0xb4, 0x75, 0x31, 0x19, 0x65, 0x17, 0xd0, 0xd6, + 0x3b, 0x98, 0xce, 0xd9, 0xc5, 0xe9, 0xd8, 0xf4, 0xf5, 0xce, 0x8c, 0xba, 0x33, 0x39, 0x9b, 0x9c, 0x99, 0x4c, 0x33, + 0xd4, 0xf2, 0xf3, 0x57, 0x96, 0x46, 0x19, 0x1b, 0xb7, 0x23, 0x7c, 0xeb, 0x16, 0xee, 0xc1, 0x59, 0xab, 0x35, 0x3e, + 0x8d, 0xf0, 0xf8, 0xe1, 0x62, 0xf1, 0xc6, 0x40, 0xb0, 0x7d, 0xf6, 0xc0, 0x7e, 0xab, 0xcf, 0x77, 0xd0, 0xf4, 0xc8, + 0x00, 0x6d, 0xcc, 0xe7, 0xa6, 0xe5, 0xf3, 0x07, 0xf0, 0x9f, 0xf9, 0x36, 0x4d, 0x97, 0xdf, 0x72, 0x3c, 0xb5, 0x8b, + 0xd2, 0x66, 0x0f, 0x5a, 0x50, 0x63, 0xc2, 0x3f, 0x8c, 0x0a, 0x0e, 0x68, 0x34, 0xea, 0xc0, 0xff, 0x45, 0x78, 0x92, + 0x5f, 0xbf, 0x72, 0x38, 0x3b, 0x99, 0xd0, 0x49, 0x2b, 0xc2, 0x13, 0xf9, 0x41, 0xe9, 0xdf, 0x1e, 0x8a, 0x34, 0xea, + 0x74, 0x2e, 0x46, 0xa6, 0xcc, 0xf2, 0x27, 0xc5, 0x0d, 0x1e, 0xb7, 0x4c, 0x2b, 0x53, 0xfa, 0x46, 0x8d, 0xae, 0x25, + 0xac, 0x24, 0xfc, 0x17, 0xe1, 0x29, 0x68, 0xc4, 0x5c, 0x2b, 0x17, 0x76, 0x3b, 0x4c, 0xdf, 0x1a, 0xd4, 0x1c, 0xdf, + 0x07, 0x78, 0xf9, 0x65, 0x1c, 0x53, 0xda, 0xed, 0xb4, 0x22, 0x6c, 0x46, 0x7d, 0xd1, 0x82, 0xff, 0x22, 0x6c, 0x21, + 0x67, 0xe0, 0x3a, 0xfd, 0xf0, 0xec, 0xe7, 0x9b, 0x34, 0xa2, 0xe3, 0xc9, 0x04, 0x96, 0xc4, 0x4c, 0xc6, 0x17, 0x9b, + 0x49, 0xc1, 0xee, 0x7e, 0xb9, 0x71, 0xdb, 0xc5, 0x24, 0x68, 0x07, 0x9d, 0xf3, 0x07, 0xa3, 0xb3, 0x08, 0xbf, 0x19, + 0x73, 0x2a, 0x60, 0x95, 0xb2, 0x71, 0x37, 0xeb, 0x66, 0x26, 0x61, 0x2a, 0xd3, 0xe8, 0x0c, 0x96, 0xbc, 0x13, 0x61, + 0xfe, 0xe5, 0xfa, 0xce, 0xa2, 0x1b, 0xd4, 0x76, 0x08, 0x32, 0x69, 0xb1, 0xf3, 0x8b, 0x2c, 0xc2, 0x39, 0xfd, 0xf2, + 0xec, 0x97, 0x22, 0x8d, 0xd8, 0x39, 0x3b, 0x9f, 0x50, 0xff, 0xfd, 0xbb, 0x9a, 0x99, 0x1a, 0xad, 0x49, 0x17, 0x92, + 0x6e, 0x84, 0x19, 0xeb, 0xfd, 0x6c, 0x62, 0x30, 0xe4, 0xe5, 0x5c, 0x8a, 0xec, 0xe9, 0x64, 0x22, 0x2d, 0x16, 0x53, + 0xd8, 0x84, 0x7f, 0x00, 0xb4, 0xe9, 0x78, 0x7c, 0xc1, 0xce, 0x23, 0xfc, 0x87, 0xdd, 0x25, 0x6e, 0x02, 0x7f, 0x58, + 0xcc, 0x66, 0x6e, 0xb7, 0xff, 0x61, 0x81, 0x02, 0xf3, 0x9d, 0xd0, 0x09, 0x1d, 0x77, 0x22, 0xfc, 0x87, 0x81, 0xcb, + 0xf8, 0x14, 0xfe, 0x83, 0x02, 0xd0, 0xd9, 0x83, 0x16, 0x63, 0x0f, 0x5a, 0xe6, 0x2b, 0xcc, 0x73, 0x33, 0x1f, 0x9d, + 0x67, 0xed, 0x08, 0xff, 0xe1, 0xd0, 0x71, 0x32, 0xa1, 0x2d, 0x40, 0xc7, 0x3f, 0x1c, 0x3a, 0x76, 0x5a, 0xa3, 0x0e, + 0x35, 0xdf, 0x16, 0x6b, 0x2e, 0xee, 0x67, 0x0c, 0x26, 0xf7, 0x87, 0x45, 0xc8, 0xfb, 0xf7, 0x2f, 0x2e, 0x1e, 0x3c, + 0x80, 0x4f, 0xd3, 0x76, 0xf9, 0xa9, 0xf4, 0xc3, 0xdc, 0x20, 0x59, 0x2b, 0x3b, 0x03, 0x3a, 0xf9, 0x87, 0x19, 0xe3, + 0x64, 0x32, 0x61, 0xad, 0x08, 0xe7, 0x7c, 0xce, 0x2c, 0x26, 0xd8, 0xdf, 0xa6, 0xa3, 0xd3, 0x4e, 0x36, 0x3e, 0xed, + 0x44, 0x38, 0x7f, 0xf3, 0xcc, 0xcc, 0xa6, 0x05, 0xb3, 0xf7, 0x5b, 0xce, 0x63, 0xcd, 0x9c, 0xbe, 0x86, 0x41, 0xc2, + 0x4a, 0x43, 0xe5, 0xf7, 0x01, 0x3d, 0x3c, 0x3f, 0xcf, 0xc6, 0x30, 0xd0, 0xf7, 0xd0, 0x2d, 0x80, 0xf1, 0xbd, 0xdd, + 0x7c, 0x23, 0xda, 0xed, 0xc2, 0x74, 0xdf, 0x2f, 0x96, 0xc5, 0xe2, 0x65, 0x1a, 0x3d, 0x38, 0xbd, 0xdf, 0x1a, 0x8f, + 0x22, 0xfc, 0xde, 0x4d, 0xf0, 0x34, 0x1b, 0x9d, 0xde, 0x6f, 0x47, 0xf8, 0xbd, 0xd9, 0x6f, 0xf7, 0x47, 0xe7, 0x17, + 0x70, 0x6e, 0xbc, 0x57, 0x8b, 0xe2, 0xcd, 0xd4, 0x14, 0x98, 0xd0, 0x07, 0xd0, 0xec, 0xaf, 0x66, 0x37, 0x8e, 0xdb, + 0xb0, 0x91, 0xdf, 0x9b, 0x4d, 0x66, 0xf0, 0xe4, 0x7e, 0xbb, 0x7b, 0xd1, 0x8d, 0xf0, 0x9c, 0x8f, 0x05, 0x10, 0x78, + 0xb3, 0x51, 0x1e, 0xb4, 0x1f, 0xdc, 0x6f, 0x45, 0x78, 0xfe, 0x46, 0x67, 0x1f, 0xe8, 0xdc, 0x50, 0xe3, 0x09, 0xc0, + 0x6c, 0xce, 0x95, 0xbe, 0x7b, 0xad, 0x1c, 0x3d, 0x66, 0xed, 0x08, 0xcf, 0x65, 0x96, 0x51, 0xf5, 0xc6, 0x26, 0x8c, + 0xba, 0x11, 0x16, 0xf4, 0x0b, 0xfd, 0x24, 0xfd, 0x66, 0x1a, 0x33, 0x3a, 0x36, 0x69, 0x06, 0x87, 0x23, 0xfc, 0x76, + 0x0c, 0x17, 0x83, 0x69, 0x34, 0x19, 0x4f, 0xba, 0x00, 0x1e, 0x20, 0x40, 0x16, 0xbb, 0x01, 0x1a, 0xf0, 0x35, 0x7e, + 0x34, 0x4a, 0xa3, 0xf3, 0xd1, 0x05, 0xeb, 0x9c, 0x46, 0xb8, 0xa4, 0x46, 0xb4, 0x0b, 0xf9, 0xe6, 0xf3, 0x83, 0xd9, + 0x52, 0x67, 0x36, 0xc1, 0x00, 0x68, 0x4c, 0xef, 0xb7, 0xc6, 0xe7, 0x11, 0x5e, 0xbc, 0x62, 0x7e, 0x8f, 0x31, 0xc6, + 0x2e, 0x00, 0x96, 0x90, 0x64, 0x10, 0xe8, 0x62, 0x32, 0x7a, 0x70, 0x61, 0xbe, 0x01, 0x0c, 0x74, 0xc2, 0x18, 0x00, + 0x69, 0xf1, 0x8a, 0x95, 0x80, 0x18, 0x8f, 0xee, 0xb7, 0x80, 0xbe, 0x2c, 0xe8, 0x82, 0xde, 0xd1, 0x9b, 0xa7, 0x0b, + 0x33, 0xa7, 0xc9, 0xb8, 0x1b, 0xe1, 0xc5, 0xf3, 0x9f, 0x16, 0xcb, 0xc9, 0xc4, 0x4c, 0x88, 0x8e, 0x1e, 0x44, 0x78, + 0xc1, 0x8a, 0x25, 0xac, 0xd1, 0x45, 0xf7, 0x74, 0x12, 0x61, 0x87, 0x86, 0x59, 0x2b, 0x1b, 0xc1, 0xcd, 0xe7, 0x72, + 0x9e, 0x46, 0xe3, 0x31, 0x6d, 0x8d, 0xe1, 0x1e, 0x54, 0xde, 0xfc, 0x52, 0x58, 0x34, 0x62, 0x06, 0x1f, 0xdc, 0x1a, + 0xc2, 0x7c, 0x01, 0x1e, 0x1f, 0x46, 0x2c, 0xcb, 0xa8, 0x4b, 0x3c, 0x3f, 0x3f, 0x3d, 0x05, 0xdc, 0xb3, 0x33, 0xb4, + 0x08, 0xf2, 0x5a, 0xdd, 0x8d, 0x0a, 0x09, 0x47, 0x17, 0x10, 0x55, 0x20, 0xab, 0xaf, 0xef, 0x5e, 0x19, 0xba, 0xda, + 0x3e, 0x7f, 0x00, 0x0b, 0xa0, 0xe8, 0x78, 0xfc, 0xd2, 0x1e, 0x6e, 0x17, 0xa3, 0xb3, 0x6e, 0xfb, 0x34, 0xc2, 0x7e, + 0x23, 0xd0, 0x8b, 0xd6, 0xfd, 0x0e, 0x94, 0x10, 0xe3, 0x3b, 0x5b, 0x62, 0x72, 0x46, 0xcf, 0xce, 0x5b, 0x11, 0xf6, + 0x5b, 0x83, 0x5d, 0x8c, 0xba, 0xf7, 0xe1, 0x53, 0xcd, 0x58, 0x9e, 0x1b, 0xfc, 0xee, 0x02, 0x5c, 0x14, 0x7f, 0x26, + 0x68, 0x1a, 0xd1, 0x56, 0xb7, 0xd3, 0x19, 0xc3, 0x67, 0xfe, 0x85, 0x15, 0x69, 0x94, 0xb5, 0xe0, 0xbf, 0x08, 0x07, + 0x3b, 0x89, 0x8d, 0x22, 0x6c, 0xf0, 0xee, 0x9c, 0x76, 0xcd, 0xde, 0x77, 0xbb, 0xaa, 0x75, 0xd1, 0x82, 0x0d, 0xeb, + 0x36, 0x95, 0xfb, 0x52, 0x42, 0xde, 0x38, 0x12, 0x4b, 0x23, 0x1c, 0x20, 0xe8, 0xe4, 0xfe, 0x24, 0xc2, 0x7e, 0xc7, + 0x9d, 0x9d, 0x5f, 0x74, 0x80, 0x94, 0x69, 0x20, 0x14, 0xe3, 0xce, 0xe8, 0x0c, 0x48, 0x93, 0x66, 0xaf, 0x2c, 0x9e, + 0x44, 0x58, 0x3f, 0x55, 0xfa, 0x65, 0x1a, 0x8d, 0x2f, 0x46, 0x93, 0xf1, 0x45, 0x84, 0xb5, 0x9c, 0x53, 0x2d, 0x0d, + 0x05, 0x3c, 0x3d, 0xbb, 0x1f, 0x61, 0x83, 0xe6, 0x2d, 0xd6, 0x1a, 0xb7, 0x22, 0xec, 0x8e, 0x12, 0xc6, 0x2e, 0x3a, + 0x30, 0xad, 0x1f, 0x9f, 0x6b, 0xc0, 0xe5, 0x31, 0x1b, 0x9d, 0x46, 0xb8, 0xa4, 0xf7, 0x86, 0x10, 0xc1, 0x97, 0x9a, + 0xcb, 0xcf, 0x8e, 0xf5, 0x00, 0x52, 0xe7, 0x37, 0x3c, 0x2c, 0xc3, 0xcf, 0x37, 0x16, 0x8d, 0xa8, 0xd9, 0xe2, 0xc1, + 0xcd, 0xf0, 0x5b, 0x1a, 0x7b, 0xb6, 0x9d, 0x93, 0xd5, 0x06, 0x97, 0x01, 0x57, 0x3f, 0xb3, 0x3b, 0x15, 0x4b, 0x65, + 0x38, 0xd9, 0x20, 0x45, 0x29, 0xe4, 0x5d, 0x0c, 0x9c, 0x17, 0x29, 0x08, 0x92, 0x82, 0xb4, 0x7a, 0xe2, 0xd2, 0x7b, + 0xb6, 0xf6, 0x04, 0x84, 0x61, 0x80, 0xf4, 0x82, 0x50, 0xa2, 0x21, 0x5a, 0x8d, 0x15, 0x26, 0xbd, 0xc1, 0xbf, 0x91, + 0x29, 0xa5, 0x75, 0x21, 0xa0, 0x84, 0xfa, 0x38, 0xf5, 0xb1, 0xc4, 0x0a, 0x22, 0x39, 0xa1, 0x9e, 0x24, 0x26, 0xea, + 0xf4, 0x0b, 0xa1, 0x63, 0xa9, 0x06, 0xc5, 0x10, 0xb7, 0xcf, 0x11, 0x86, 0x78, 0x0e, 0x64, 0x20, 0xaf, 0xae, 0xda, + 0xe7, 0x47, 0x46, 0xe8, 0xbb, 0xba, 0xba, 0xb0, 0x3f, 0xe0, 0xdf, 0x61, 0x15, 0x43, 0x1b, 0xc6, 0xf7, 0x9e, 0x55, + 0x73, 0xfc, 0xd9, 0xf0, 0xd7, 0xef, 0xd9, 0x7a, 0x1d, 0xbf, 0x67, 0x04, 0x66, 0x8c, 0xdf, 0xb3, 0xc4, 0xdc, 0x91, + 0x58, 0x6f, 0x1d, 0x32, 0x00, 0xcd, 0x59, 0x0b, 0x43, 0x64, 0x77, 0xcf, 0x79, 0xbf, 0x67, 0x03, 0x5e, 0xf7, 0xf4, + 0xae, 0xc2, 0x29, 0x1f, 0x1d, 0xad, 0x8a, 0x54, 0x5b, 0x31, 0x41, 0x5b, 0x31, 0x41, 0x5b, 0x31, 0x41, 0x57, 0x01, + 0xed, 0xcf, 0xfa, 0x20, 0xa5, 0x18, 0x65, 0x8b, 0xe3, 0xa9, 0xdf, 0x80, 0xda, 0x03, 0xb4, 0x93, 0xfd, 0x4a, 0xd9, + 0x51, 0xea, 0x2a, 0xf6, 0x2a, 0x30, 0xf6, 0x26, 0x3a, 0x6d, 0xc7, 0xc9, 0xbf, 0xa3, 0xee, 0x78, 0x56, 0x13, 0xcb, + 0xde, 0xec, 0x15, 0xcb, 0x60, 0x25, 0x8d, 0x68, 0x76, 0x68, 0x63, 0x83, 0xe8, 0xc1, 0x7d, 0x23, 0x98, 0x55, 0x01, + 0xeb, 0x1a, 0x90, 0xd4, 0x03, 0x29, 0xe4, 0xc2, 0x48, 0x69, 0x05, 0x4a, 0xc7, 0x3a, 0x2e, 0x40, 0x43, 0xe9, 0x15, + 0x94, 0x65, 0x5c, 0xd5, 0x86, 0x01, 0x88, 0xb2, 0x32, 0x9a, 0x95, 0xd5, 0xba, 0x20, 0xba, 0x80, 0x26, 0xcc, 0x48, + 0x2c, 0xd0, 0x80, 0x30, 0x0d, 0x08, 0x57, 0x19, 0xc4, 0x19, 0x97, 0x7d, 0x66, 0xb2, 0x95, 0xc9, 0x56, 0x65, 0xb6, + 0xf4, 0xd9, 0x56, 0x48, 0x94, 0x26, 0x5b, 0x96, 0xd9, 0x20, 0xb3, 0xe1, 0x69, 0xaa, 0xf0, 0x28, 0x95, 0x56, 0x54, + 0xab, 0x64, 0xab, 0x97, 0x34, 0xd4, 0xe6, 0x1e, 0x1d, 0xc5, 0xa5, 0x9c, 0x64, 0xd4, 0xc4, 0xf7, 0x56, 0x3c, 0x29, + 0x8c, 0x0c, 0xc4, 0x93, 0xa9, 0xfb, 0x3b, 0xda, 0x6c, 0xcb, 0x4a, 0xc5, 0x74, 0xf4, 0x95, 0x92, 0xe8, 0x2f, 0xaf, + 0x44, 0x7d, 0xce, 0x4d, 0x44, 0x9e, 0x4b, 0x92, 0xb4, 0x5a, 0xa7, 0xed, 0xd3, 0xd6, 0x45, 0x9f, 0x1f, 0xb7, 0x3b, + 0xc9, 0x83, 0x4e, 0x6a, 0x14, 0x11, 0x0b, 0x79, 0x03, 0x0a, 0x98, 0x93, 0x4e, 0x72, 0x86, 0x8e, 0xdb, 0x49, 0xab, + 0xdb, 0x6d, 0xc2, 0x3f, 0xf8, 0x91, 0x2e, 0xab, 0x9d, 0xb5, 0xce, 0xba, 0x7d, 0x7e, 0xb2, 0x55, 0x29, 0xe6, 0x0d, + 0x28, 0x88, 0x4e, 0x4c, 0x25, 0x0c, 0xf5, 0xab, 0xe5, 0xfd, 0x67, 0x47, 0xcf, 0xf3, 0x48, 0xc7, 0xd2, 0xaa, 0xe2, + 0x00, 0xaa, 0xfe, 0x6b, 0x6a, 0x80, 0xe8, 0xbf, 0x46, 0x65, 0xd4, 0xdc, 0x55, 0x01, 0xa2, 0xf6, 0x73, 0x1e, 0x8b, + 0x06, 0x3b, 0x8e, 0x6d, 0xbe, 0x86, 0xba, 0x4d, 0x88, 0x64, 0x87, 0xa7, 0x2e, 0x57, 0x85, 0xb9, 0x53, 0x84, 0x9a, + 0x0a, 0x72, 0x47, 0x2e, 0x57, 0x86, 0xb9, 0x23, 0x84, 0x9a, 0x12, 0x72, 0x69, 0xca, 0x13, 0x0a, 0x39, 0x3a, 0xa1, + 0x4d, 0x03, 0xc9, 0x6a, 0x51, 0x9e, 0x33, 0x3f, 0x6c, 0x3e, 0x81, 0xe5, 0x31, 0x04, 0xc5, 0x09, 0xd2, 0x02, 0x5e, + 0x3b, 0x29, 0xb5, 0x39, 0x2d, 0x5c, 0xaa, 0x71, 0x20, 0xa3, 0x01, 0xff, 0x1c, 0x33, 0xf3, 0x04, 0x46, 0xab, 0x7f, + 0x7a, 0xde, 0x4a, 0xdb, 0xe0, 0xb6, 0x0d, 0xb2, 0xb6, 0xb0, 0xb2, 0xb6, 0xf0, 0xb2, 0xb6, 0xf0, 0xb2, 0x36, 0x08, + 0xf0, 0x41, 0xdf, 0xbf, 0xcb, 0x9a, 0x29, 0x0c, 0x2f, 0xed, 0x6a, 0xac, 0xe1, 0x44, 0xac, 0xd7, 0xeb, 0xd5, 0x06, + 0xac, 0x9e, 0xca, 0x1a, 0x85, 0xaa, 0xd4, 0x9f, 0xab, 0x22, 0x6d, 0xe1, 0x69, 0x0a, 0x5a, 0xee, 0x16, 0xa6, 0x66, + 0x73, 0x7b, 0xaa, 0xb0, 0x1d, 0x51, 0xa7, 0xef, 0xd5, 0xc9, 0x57, 0xe4, 0xd4, 0x68, 0x8f, 0x57, 0x45, 0xca, 0x2d, + 0xcd, 0xe0, 0x96, 0x66, 0x70, 0x4b, 0x33, 0xa0, 0x11, 0x5c, 0x16, 0x36, 0x65, 0x13, 0x4a, 0xe0, 0x4a, 0x60, 0x70, + 0x3a, 0x84, 0x80, 0x82, 0xb1, 0x26, 0x66, 0xd4, 0x5b, 0x9d, 0xb7, 0x21, 0x80, 0x9a, 0x2d, 0xa9, 0x13, 0x6a, 0xfc, + 0xc8, 0xcb, 0x31, 0x7f, 0xaa, 0xa1, 0x7d, 0x02, 0xaf, 0xdb, 0x3c, 0xd4, 0x71, 0x0b, 0xcc, 0x48, 0xa2, 0x22, 0xea, + 0x1b, 0xb2, 0x90, 0x1a, 0x9d, 0x8d, 0x33, 0x0f, 0xff, 0xbc, 0xe5, 0x95, 0x6b, 0x29, 0x41, 0xf8, 0xa6, 0xc3, 0x67, + 0x56, 0x85, 0x09, 0x28, 0xad, 0x5f, 0x9d, 0xe9, 0x9a, 0x3d, 0x12, 0x7a, 0x60, 0xc2, 0xee, 0xe3, 0x4f, 0xf5, 0x05, + 0x29, 0x20, 0xfe, 0x62, 0x6a, 0x12, 0x5d, 0x04, 0x65, 0x70, 0x28, 0x26, 0x37, 0xd4, 0xb8, 0xd7, 0xfc, 0x6c, 0xff, + 0x7c, 0xa2, 0x81, 0xff, 0x61, 0x31, 0x1d, 0x79, 0xb7, 0xdd, 0x8f, 0x26, 0xce, 0x10, 0x39, 0x3c, 0xb4, 0xd6, 0xe5, + 0xe6, 0x6b, 0xdb, 0xbc, 0xdc, 0x24, 0x9a, 0x6c, 0xd8, 0xa1, 0x7e, 0x8d, 0x7e, 0xf7, 0xde, 0x73, 0xc5, 0x74, 0x84, + 0x02, 0x9a, 0x6d, 0xc0, 0x2a, 0x2b, 0x60, 0x29, 0x57, 0xaf, 0x74, 0xaa, 0x84, 0xde, 0xcd, 0x98, 0x37, 0xc5, 0x74, + 0xb4, 0xf7, 0x19, 0x14, 0xdb, 0x63, 0xff, 0x25, 0x0d, 0x7a, 0xf0, 0xaa, 0xed, 0x19, 0xbb, 0xfd, 0x56, 0x9d, 0xeb, + 0xbd, 0x75, 0x54, 0xfe, 0xad, 0x3a, 0x4f, 0xf6, 0xd5, 0x99, 0xf3, 0xdb, 0xd8, 0xef, 0x1d, 0x1d, 0xa8, 0xb1, 0x8d, + 0xc9, 0xd2, 0x74, 0x04, 0x71, 0xeb, 0xe1, 0xaf, 0x8d, 0x2e, 0xd3, 0xf3, 0x24, 0x1c, 0x56, 0x41, 0xf6, 0x93, 0x6e, + 0xca, 0x30, 0x25, 0x9d, 0xe3, 0xc2, 0xc4, 0x97, 0x11, 0x09, 0x6d, 0xaa, 0x84, 0xe2, 0x9c, 0xc4, 0x31, 0x3d, 0xce, + 0x20, 0x4a, 0x4e, 0xbb, 0x4f, 0xd3, 0x98, 0x36, 0x32, 0x74, 0x12, 0xb7, 0x1b, 0xf4, 0x38, 0x43, 0xa8, 0xd1, 0x06, + 0x9d, 0xa9, 0x24, 0xed, 0x66, 0x0e, 0x71, 0x33, 0x0d, 0x29, 0xce, 0x8f, 0x45, 0x52, 0x34, 0xe4, 0xb1, 0x4a, 0x8a, + 0x46, 0xd2, 0xc5, 0x22, 0x99, 0x96, 0xc9, 0x53, 0x93, 0x3c, 0xb5, 0xc9, 0xa3, 0x32, 0x79, 0x64, 0x92, 0x47, 0x36, + 0x99, 0x92, 0xe2, 0x58, 0x24, 0xb4, 0x11, 0xb7, 0x9b, 0x05, 0x3a, 0x86, 0x11, 0xf8, 0xd1, 0x13, 0x11, 0x86, 0x2b, + 0xdf, 0x18, 0x7b, 0x9f, 0x85, 0xcc, 0x5d, 0x00, 0xd1, 0x0a, 0x48, 0xa5, 0x13, 0x16, 0xd4, 0xf9, 0x27, 0x00, 0x13, + 0xd6, 0xf6, 0x8f, 0x0f, 0x8f, 0xb7, 0xc9, 0x72, 0x29, 0x02, 0x27, 0x33, 0xb0, 0x8b, 0xff, 0xec, 0x5c, 0x6b, 0x00, + 0xaa, 0x1b, 0x9a, 0x2f, 0x66, 0x74, 0xc7, 0x93, 0xb7, 0x98, 0x8e, 0xdc, 0xce, 0x2a, 0x9b, 0x61, 0xb4, 0xb0, 0x61, + 0xa7, 0xeb, 0x3e, 0x97, 0x00, 0x6a, 0xef, 0xe7, 0x99, 0x50, 0xa3, 0x24, 0xb7, 0x35, 0xa6, 0x05, 0xbb, 0x53, 0x19, + 0xcd, 0x59, 0x5c, 0x1d, 0xc0, 0xd5, 0x30, 0x19, 0x79, 0x02, 0xd6, 0xf9, 0xc5, 0x71, 0x72, 0xda, 0xd0, 0xc9, 0xf4, + 0x38, 0xe9, 0x3e, 0x68, 0xe8, 0x64, 0x74, 0x9c, 0xb4, 0xdb, 0x15, 0xce, 0x26, 0x05, 0xd1, 0xc9, 0x94, 0x68, 0xd0, + 0x18, 0xda, 0x46, 0xe5, 0x82, 0x82, 0xb9, 0xd9, 0xbf, 0x31, 0x8c, 0x86, 0x1b, 0x86, 0x60, 0x53, 0x1b, 0x81, 0x73, + 0x67, 0x0c, 0x61, 0x37, 0x9d, 0x6e, 0xb7, 0xa9, 0x93, 0x02, 0x6b, 0xbb, 0x92, 0x4d, 0x9d, 0x4c, 0xb1, 0xb6, 0xcb, + 0xd7, 0xd4, 0xc9, 0xc8, 0x36, 0x65, 0x74, 0x80, 0x4c, 0x04, 0xc0, 0x7a, 0xce, 0x02, 0xc8, 0x77, 0xbc, 0xc3, 0xcc, + 0x06, 0xb4, 0x86, 0xdf, 0x2a, 0xd7, 0xf4, 0x05, 0x15, 0xd5, 0x60, 0x76, 0xc4, 0xbe, 0x56, 0xb4, 0x5d, 0x35, 0xc9, + 0xfe, 0x75, 0xd9, 0xb2, 0xd9, 0x42, 0xea, 0x7a, 0xc1, 0x17, 0x35, 0x0c, 0x71, 0xa5, 0xdc, 0xc1, 0xfd, 0x88, 0x92, + 0x18, 0xe2, 0xec, 0x99, 0x53, 0x88, 0x13, 0xaf, 0x47, 0x86, 0x24, 0xde, 0x68, 0x6c, 0x50, 0x1c, 0x9c, 0xb7, 0x2f, + 0x42, 0xaa, 0xba, 0x13, 0x7c, 0x8f, 0x90, 0x68, 0x29, 0xac, 0x79, 0xe6, 0x38, 0xaa, 0x68, 0xf1, 0x1b, 0xa7, 0xdd, + 0xad, 0x1d, 0x10, 0x47, 0x47, 0xdb, 0xe7, 0x85, 0x7f, 0x06, 0x61, 0xe7, 0xe9, 0x83, 0xca, 0xb6, 0xcf, 0x3f, 0xce, + 0x64, 0xad, 0x7e, 0x79, 0x80, 0x28, 0x3e, 0x0c, 0xd6, 0x7d, 0x43, 0xe1, 0x07, 0x55, 0x0c, 0x40, 0x97, 0xd3, 0x3c, + 0x37, 0x19, 0xa6, 0xaf, 0x61, 0x30, 0xb6, 0x57, 0xe1, 0x84, 0x4a, 0xbb, 0xc5, 0x7f, 0xd9, 0x71, 0xd0, 0x89, 0x7b, + 0x3c, 0x26, 0x6c, 0xf4, 0x53, 0x68, 0x25, 0x5c, 0xc1, 0xc6, 0xf9, 0x87, 0xaf, 0xd7, 0xb5, 0xa7, 0x82, 0xec, 0x83, + 0x34, 0xe8, 0xe8, 0x88, 0xab, 0x67, 0x60, 0xd8, 0xcc, 0xe2, 0x46, 0x78, 0xf8, 0xfe, 0x5d, 0x3b, 0xad, 0x3f, 0x99, + 0x73, 0x35, 0x0d, 0x0e, 0xba, 0x87, 0xb5, 0xfc, 0xbd, 0x2b, 0xd1, 0xd7, 0x29, 0x77, 0x6b, 0xfd, 0xbe, 0x32, 0x1b, + 0xdf, 0x79, 0xb4, 0xea, 0xe8, 0x88, 0x57, 0xa1, 0xa3, 0xa2, 0xef, 0x22, 0xd4, 0x37, 0x32, 0xc8, 0xb3, 0x5c, 0x52, + 0xb8, 0x11, 0x85, 0x2b, 0x86, 0xb4, 0xc1, 0x4f, 0x34, 0xfe, 0x49, 0xfe, 0x7f, 0x6a, 0xe4, 0x58, 0xa7, 0x0d, 0x1e, + 0x98, 0x1b, 0x84, 0xac, 0x50, 0x15, 0xb4, 0xd1, 0x40, 0x3a, 0xb4, 0x02, 0x47, 0xe5, 0x61, 0x4e, 0x17, 0x8b, 0xfc, + 0xce, 0xbc, 0xdb, 0x15, 0x70, 0x54, 0xd5, 0x45, 0x93, 0x8b, 0x98, 0x87, 0x0b, 0xe0, 0xe9, 0x01, 0xf7, 0x90, 0xf1, + 0x78, 0x2d, 0x2f, 0xb7, 0x05, 0x02, 0xc9, 0x4c, 0x11, 0xd9, 0x6c, 0xf7, 0xd4, 0x15, 0xc8, 0x65, 0xcd, 0x26, 0xd2, + 0x2e, 0x90, 0x38, 0xe6, 0x20, 0x93, 0x29, 0xeb, 0xd5, 0x7a, 0x60, 0x0b, 0x82, 0xe4, 0x26, 0x8d, 0xc8, 0xb6, 0xbf, + 0x14, 0x9f, 0xc4, 0x80, 0x46, 0xc8, 0x0a, 0x7c, 0xa1, 0xb0, 0xc8, 0x81, 0xeb, 0x2c, 0x7c, 0xc7, 0x5f, 0x69, 0xa9, + 0x18, 0xa8, 0xe1, 0x10, 0x17, 0xe6, 0xa9, 0x8a, 0x72, 0x3e, 0x54, 0x05, 0x4f, 0x1f, 0x05, 0x22, 0x0a, 0x5f, 0xaf, + 0x0f, 0xe1, 0x65, 0x21, 0xd7, 0x26, 0xb8, 0xc1, 0xba, 0x9f, 0xd5, 0x2b, 0x22, 0x30, 0x0e, 0x46, 0x5a, 0xe6, 0xa2, + 0xd0, 0xc9, 0x9b, 0xec, 0x52, 0xf4, 0x1a, 0x0d, 0x66, 0x82, 0x3e, 0x11, 0x88, 0xf0, 0x06, 0x3e, 0x8a, 0xf0, 0xc7, + 0xc6, 0x71, 0x52, 0xcc, 0x46, 0xc3, 0x83, 0x30, 0xdd, 0xb5, 0x84, 0xf5, 0x5a, 0xd9, 0x68, 0x2b, 0x26, 0xc7, 0xc6, + 0x5d, 0x29, 0xfb, 0x29, 0xc3, 0xba, 0x56, 0x66, 0x1c, 0xdc, 0x6d, 0xf5, 0x37, 0xd5, 0x7e, 0x3e, 0xe0, 0xf6, 0x1a, + 0x8f, 0x9b, 0x18, 0x06, 0x06, 0x50, 0xab, 0xad, 0x0d, 0x6e, 0x6d, 0xee, 0x63, 0x6b, 0x20, 0xcc, 0xb6, 0x21, 0x28, + 0x4a, 0x9f, 0x7d, 0x7b, 0x73, 0xeb, 0x63, 0x18, 0x2a, 0x33, 0x27, 0x85, 0xf4, 0x00, 0xe4, 0xe8, 0x21, 0x81, 0xce, + 0xed, 0xcf, 0x8a, 0x2e, 0x54, 0x32, 0x71, 0x39, 0xc6, 0x1f, 0x82, 0xdb, 0xbc, 0x41, 0xf4, 0xf1, 0xa3, 0xd9, 0xe4, + 0x1f, 0x3f, 0x46, 0x38, 0x34, 0x74, 0x8f, 0x02, 0x5e, 0x30, 0x1a, 0x96, 0x61, 0xae, 0xcc, 0xc6, 0x6f, 0xb6, 0x03, + 0xb4, 0xa3, 0x15, 0xde, 0xc1, 0xf2, 0x98, 0xc6, 0x77, 0x1c, 0x43, 0x07, 0x1c, 0xe0, 0xcd, 0x06, 0x7c, 0xd8, 0x7b, + 0x15, 0x2b, 0x74, 0x74, 0xf4, 0x2a, 0x96, 0xa8, 0x7f, 0xcd, 0xcc, 0x9d, 0x1b, 0x78, 0x86, 0x0f, 0xb8, 0x19, 0xbe, + 0x0c, 0x10, 0xe0, 0x9a, 0x6d, 0x4b, 0x36, 0x6f, 0x4c, 0x1c, 0x8e, 0x14, 0xe2, 0x7c, 0x43, 0xb4, 0x61, 0x07, 0x12, + 0xe8, 0xf5, 0x55, 0x08, 0xed, 0x1e, 0x23, 0x0c, 0x58, 0xf8, 0xd2, 0x6f, 0x8f, 0x25, 0x73, 0x56, 0x4c, 0x59, 0xb1, + 0x5e, 0x3f, 0xa7, 0xd6, 0x17, 0x6f, 0x2b, 0x6c, 0xa4, 0xea, 0x35, 0x1a, 0xd4, 0x8c, 0x1f, 0xc4, 0x07, 0x3a, 0xc4, + 0x87, 0xaf, 0xe2, 0x02, 0x21, 0xb0, 0x30, 0xe2, 0x62, 0xe9, 0xfd, 0xce, 0xb2, 0xda, 0xba, 0x14, 0xa8, 0x6c, 0x24, + 0x27, 0x2d, 0x3c, 0x23, 0x59, 0xb9, 0x46, 0x97, 0xb3, 0x5e, 0xa3, 0x91, 0x23, 0x19, 0x67, 0x83, 0x7c, 0x88, 0x39, + 0x2e, 0xe0, 0x32, 0x75, 0x77, 0x1d, 0x16, 0xac, 0x46, 0xb9, 0xdc, 0x7c, 0x57, 0x76, 0xac, 0xe9, 0x3b, 0xba, 0x09, + 0x80, 0xf1, 0x8e, 0x06, 0x44, 0x62, 0x1f, 0x90, 0x85, 0x05, 0xb2, 0xf2, 0x40, 0x16, 0x06, 0xc8, 0x0a, 0xf5, 0x17, + 0x10, 0x40, 0x49, 0xa1, 0x74, 0x87, 0xa2, 0xd7, 0x43, 0x7d, 0x3a, 0x37, 0x12, 0xcc, 0x4d, 0xb4, 0x09, 0xb7, 0x1c, + 0xe0, 0x52, 0xe2, 0xe6, 0xae, 0xc8, 0x2a, 0x8a, 0x4c, 0xd4, 0x5b, 0x7c, 0x6b, 0xfe, 0x24, 0xb7, 0xf8, 0xce, 0xfe, + 0xb8, 0x0b, 0x94, 0x49, 0xbf, 0xd5, 0xb4, 0x0d, 0xdc, 0xc5, 0x88, 0x8b, 0x92, 0x08, 0xd0, 0xda, 0x05, 0x3c, 0x14, + 0xf5, 0x37, 0xe0, 0x94, 0x0d, 0x4d, 0x21, 0x1a, 0x44, 0x61, 0x11, 0x90, 0xce, 0x3f, 0xff, 0x8c, 0x50, 0x5f, 0x40, + 0x64, 0x21, 0x77, 0xb2, 0x35, 0xdb, 0xa8, 0x11, 0x25, 0x51, 0x1a, 0xfb, 0xc0, 0x15, 0xb0, 0x33, 0xa2, 0x28, 0x78, + 0xff, 0xa5, 0xb2, 0xf1, 0xa8, 0x0d, 0xc3, 0x0c, 0xaa, 0x0a, 0xc5, 0x71, 0xb5, 0xda, 0x0e, 0x7c, 0x64, 0xa0, 0x2a, + 0x4c, 0xd4, 0x19, 0x64, 0x1f, 0x45, 0x63, 0x84, 0x1d, 0x1d, 0xb1, 0x81, 0x18, 0x06, 0xaf, 0x9c, 0x55, 0xad, 0xeb, + 0x70, 0xe1, 0xe2, 0x0c, 0x22, 0xcf, 0xaf, 0xd7, 0xf6, 0x2f, 0xf9, 0x60, 0xa4, 0x19, 0x78, 0xae, 0x2e, 0xb8, 0x8d, + 0x17, 0xfb, 0x65, 0xb1, 0x44, 0xcb, 0x77, 0x60, 0xd9, 0xe7, 0xe2, 0x08, 0x72, 0x37, 0xd5, 0xb6, 0x87, 0xfa, 0xc2, + 0x68, 0x14, 0x82, 0x28, 0xbe, 0xd5, 0x91, 0x86, 0x17, 0x3a, 0xcc, 0xab, 0x45, 0xe3, 0xcd, 0x55, 0x19, 0x54, 0x15, + 0x8e, 0x94, 0x04, 0xac, 0xae, 0x0d, 0x9d, 0x84, 0x1f, 0x75, 0x2a, 0xe9, 0x58, 0x48, 0x80, 0x02, 0x47, 0xe6, 0x72, + 0xde, 0x04, 0xcd, 0x67, 0x68, 0x0f, 0x91, 0xab, 0x56, 0xf9, 0xef, 0xba, 0x6c, 0xe9, 0xa2, 0x5b, 0x45, 0x73, 0xb9, + 0x54, 0x6c, 0xb9, 0x80, 0xf3, 0xbd, 0x4c, 0xcb, 0x72, 0x9e, 0x7d, 0xae, 0xa7, 0x80, 0x41, 0xe4, 0xad, 0x9e, 0x33, + 0xb1, 0x8c, 0xdc, 0x3c, 0x5f, 0x5a, 0x71, 0xff, 0xf5, 0x0b, 0xfc, 0x9e, 0x74, 0x8e, 0x5f, 0xe2, 0xdf, 0x29, 0x79, + 0xdf, 0x78, 0x89, 0xa7, 0x9c, 0x58, 0xde, 0x20, 0x79, 0xfd, 0xea, 0xfa, 0xc5, 0xdb, 0x17, 0xef, 0x9f, 0x7e, 0x7c, + 0xf1, 0xf2, 0xd9, 0x8b, 0x97, 0x2f, 0xde, 0x7e, 0xc0, 0x3f, 0x51, 0xf2, 0xf2, 0xa4, 0x7d, 0xd1, 0xc2, 0xef, 0xc8, + 0xcb, 0x93, 0x0e, 0xbe, 0xd5, 0xe4, 0xe5, 0xc9, 0x19, 0x9e, 0x29, 0xf2, 0xf2, 0xb8, 0x73, 0x72, 0x8a, 0x97, 0xda, + 0x36, 0x99, 0xcb, 0x69, 0xbb, 0x85, 0xff, 0x76, 0x5f, 0x20, 0xde, 0x57, 0xb3, 0x98, 0xb2, 0x2d, 0xe3, 0x07, 0x53, + 0x86, 0x8e, 0x94, 0x31, 0x44, 0xb9, 0x0c, 0xd0, 0x69, 0xac, 0xea, 0xa6, 0x0d, 0x10, 0xd6, 0x19, 0x6c, 0x18, 0x01, + 0xad, 0x38, 0x71, 0xed, 0xf0, 0x93, 0x36, 0x3b, 0x05, 0xfa, 0xc4, 0x4b, 0xe1, 0xb8, 0x54, 0xe1, 0xb4, 0x9d, 0x16, + 0x63, 0x92, 0x4b, 0x59, 0xc4, 0x4b, 0x60, 0x04, 0x8c, 0xd6, 0x82, 0x9f, 0x94, 0xf1, 0xa3, 0xc4, 0x25, 0x69, 0xf7, + 0xdb, 0xa9, 0xb8, 0x24, 0x9d, 0x7e, 0x07, 0xfe, 0x74, 0xfb, 0xdd, 0xb4, 0xdd, 0x42, 0xc7, 0xc1, 0x38, 0x7e, 0xa8, + 0xa1, 0xf5, 0x60, 0x88, 0x5d, 0x17, 0xea, 0xef, 0x42, 0x7b, 0x95, 0x9e, 0x70, 0xea, 0xd8, 0x76, 0x4f, 0x5c, 0x32, + 0xa3, 0x87, 0xe5, 0xdf, 0x01, 0x6a, 0x1b, 0x17, 0x97, 0x72, 0xe3, 0xb8, 0x5f, 0xfc, 0x44, 0xa0, 0x5a, 0x90, 0x9a, + 0x98, 0xad, 0x5b, 0x08, 0x98, 0x46, 0x93, 0x0d, 0xe6, 0x40, 0x89, 0x92, 0x85, 0xf6, 0x81, 0xf6, 0x55, 0x53, 0xa2, + 0x64, 0x21, 0x17, 0x71, 0x4d, 0xd5, 0xf0, 0x4b, 0x60, 0xe6, 0x78, 0xc8, 0xd5, 0x4b, 0xfa, 0x32, 0xae, 0xf1, 0x3c, + 0x21, 0x6b, 0x17, 0x6e, 0x8b, 0x5f, 0x9d, 0x15, 0x45, 0x0d, 0x5c, 0x25, 0x60, 0xfd, 0xa8, 0x9a, 0xfa, 0x12, 0x5e, + 0x14, 0x64, 0x0d, 0x7d, 0x45, 0x02, 0xea, 0xf9, 0x6b, 0x69, 0xc6, 0x55, 0x2a, 0xa3, 0xbd, 0x22, 0xda, 0x98, 0x05, + 0x79, 0x45, 0xf4, 0xa5, 0x32, 0x40, 0x90, 0x84, 0x0f, 0xc4, 0x10, 0x0e, 0x7c, 0x3b, 0x40, 0x69, 0xe8, 0x1c, 0xa8, + 0x95, 0x2a, 0x33, 0x21, 0xf3, 0x69, 0xc2, 0x25, 0x80, 0xe6, 0xa9, 0x52, 0x41, 0x99, 0x4f, 0x2c, 0x51, 0x30, 0xf4, + 0x3f, 0xc2, 0x0d, 0x70, 0x1c, 0x1b, 0x54, 0x0c, 0xed, 0x6a, 0x44, 0x3d, 0xbf, 0x7d, 0xd1, 0x3a, 0x79, 0x19, 0xe4, + 0x2f, 0x95, 0xb7, 0xf7, 0xf8, 0x14, 0x50, 0x72, 0x1b, 0xe0, 0xab, 0x8d, 0x7d, 0x6c, 0xb6, 0x5e, 0x08, 0x90, 0x63, + 0x8d, 0x4e, 0xcc, 0xe3, 0x8a, 0x3d, 0xa4, 0x8f, 0x49, 0xbb, 0x05, 0x01, 0xd5, 0xf6, 0x50, 0xbe, 0x3f, 0xb6, 0x60, + 0xaa, 0x93, 0xdb, 0x26, 0xd0, 0x6a, 0x78, 0x6f, 0xe9, 0xae, 0xc9, 0x93, 0x3b, 0xac, 0x02, 0x9c, 0x61, 0xc7, 0xac, + 0x21, 0x8e, 0x05, 0x72, 0x81, 0x68, 0xed, 0x06, 0xd0, 0x54, 0x74, 0xec, 0xbb, 0x7f, 0xde, 0x38, 0xea, 0xb2, 0x99, + 0x74, 0x8f, 0x5f, 0x1e, 0x1d, 0xc5, 0xb2, 0x41, 0xde, 0x23, 0xbc, 0xa2, 0x60, 0xb3, 0x0d, 0x7e, 0x70, 0xdc, 0x32, + 0xf1, 0xa9, 0x0a, 0xa8, 0xe3, 0x44, 0xd5, 0x8e, 0xb5, 0xaa, 0xb3, 0x72, 0x37, 0xf8, 0x31, 0x75, 0x50, 0x23, 0x48, + 0xb3, 0xa3, 0xeb, 0x84, 0x50, 0xfe, 0xb1, 0xe6, 0xb4, 0x06, 0xdb, 0xb2, 0xf1, 0x3b, 0x45, 0xdf, 0xbd, 0x6f, 0xbe, + 0x0c, 0xf0, 0xa0, 0x66, 0x9a, 0xf4, 0xbe, 0xf1, 0x1e, 0x7d, 0xf7, 0x3e, 0x70, 0x3b, 0xe4, 0x15, 0x7b, 0xe2, 0xb9, + 0x91, 0x5f, 0x2d, 0x57, 0xfa, 0x2b, 0x48, 0xf6, 0x05, 0xf9, 0x15, 0xb0, 0x9c, 0x92, 0x5f, 0x63, 0xd9, 0x84, 0x70, + 0x8c, 0xe4, 0xd7, 0xb8, 0x80, 0x1f, 0x39, 0xf9, 0x35, 0x06, 0x6c, 0xc7, 0x33, 0xf3, 0xa3, 0x28, 0x81, 0x01, 0xae, + 0x6e, 0xd2, 0x7a, 0xbc, 0x15, 0xeb, 0xb5, 0x38, 0x3a, 0x92, 0xf6, 0x17, 0xbd, 0xca, 0x8e, 0x8e, 0xf2, 0xcb, 0x59, + 0xd5, 0x37, 0xd7, 0xfb, 0xe8, 0x8b, 0x41, 0x28, 0x1c, 0x98, 0xa6, 0xf1, 0x70, 0xc6, 0x3a, 0x0b, 0x11, 0x07, 0x1a, + 0x68, 0x9e, 0x76, 0xee, 0x9f, 0x5f, 0x60, 0xf8, 0xf7, 0x7e, 0x50, 0x10, 0x74, 0xf8, 0x76, 0x62, 0xa4, 0xcd, 0x9a, + 0xe7, 0x55, 0x9d, 0xab, 0x00, 0x9f, 0x31, 0x43, 0x4d, 0x71, 0x74, 0xc4, 0x2f, 0x03, 0x5c, 0xc6, 0x0c, 0x35, 0x02, + 0x8b, 0xbd, 0xa7, 0xa5, 0x3d, 0x99, 0xe1, 0x9a, 0xe0, 0xa1, 0x5d, 0x3e, 0x28, 0x86, 0x97, 0xda, 0x51, 0x93, 0x30, + 0x1c, 0xb7, 0x22, 0x2d, 0xb7, 0xc9, 0x7a, 0xa2, 0xa9, 0xae, 0xda, 0x3d, 0x24, 0x89, 0x6a, 0x88, 0xab, 0xab, 0x36, + 0x06, 0x95, 0x7c, 0x5f, 0x11, 0x99, 0x0a, 0xe2, 0x5d, 0x06, 0x57, 0xb9, 0x4c, 0x15, 0x9e, 0xf1, 0x54, 0x78, 0x39, + 0xfb, 0x9e, 0xb7, 0x9e, 0x36, 0x4e, 0x9c, 0xa6, 0x67, 0x86, 0x45, 0x5f, 0x95, 0xce, 0x87, 0xb0, 0x49, 0xd5, 0x10, + 0xde, 0x31, 0x2c, 0x31, 0x8f, 0x59, 0x8f, 0x3b, 0x06, 0x71, 0xa2, 0x55, 0xa3, 0x0d, 0x99, 0xf0, 0xb9, 0x49, 0x15, + 0x0c, 0xd4, 0x14, 0xbe, 0x04, 0x23, 0xab, 0xac, 0x32, 0xcc, 0xf6, 0x0d, 0x43, 0x01, 0x01, 0x05, 0xae, 0x08, 0x0b, + 0x24, 0x78, 0x91, 0xd5, 0x08, 0x47, 0x9d, 0x5c, 0xd8, 0xc9, 0x5d, 0x2a, 0xe8, 0x4e, 0x0c, 0x2f, 0x75, 0x0f, 0x89, + 0x46, 0xc3, 0x71, 0xdb, 0x57, 0xc2, 0x0c, 0xa2, 0xd9, 0x1e, 0x5e, 0xb1, 0x1e, 0x52, 0xcd, 0x66, 0x69, 0x00, 0x79, + 0xd5, 0x5a, 0xaf, 0xd5, 0xa5, 0x6f, 0xa4, 0xef, 0xcf, 0x71, 0xc3, 0x77, 0x79, 0xc1, 0xf3, 0x0f, 0x49, 0x06, 0x11, + 0x50, 0x55, 0xe0, 0xb3, 0xe5, 0x22, 0xc2, 0x91, 0x79, 0xe2, 0x0e, 0xfe, 0x9a, 0xa7, 0xc9, 0x22, 0x1c, 0xb9, 0x57, + 0xef, 0xa2, 0x61, 0x35, 0x58, 0x95, 0x95, 0x01, 0xdb, 0x79, 0xf2, 0x11, 0x18, 0x07, 0xfd, 0x49, 0xa1, 0x55, 0xf5, + 0x3b, 0xc9, 0x5d, 0xe8, 0x12, 0xe5, 0x1f, 0x62, 0x73, 0xa3, 0xda, 0xec, 0x77, 0x16, 0xe5, 0x38, 0xf2, 0x55, 0xe1, + 0x41, 0x83, 0x6f, 0xbc, 0x04, 0xd9, 0x76, 0x0f, 0x90, 0xaf, 0xca, 0x1e, 0x80, 0xf3, 0xde, 0x6c, 0x10, 0xfe, 0x43, + 0xee, 0x7d, 0x8d, 0x38, 0xfa, 0x28, 0xc5, 0x13, 0xaa, 0x69, 0xd4, 0x78, 0x6d, 0x0c, 0xdf, 0xac, 0x9c, 0xd5, 0xfb, + 0xda, 0x38, 0xd8, 0xbf, 0xd5, 0x3d, 0x04, 0x93, 0xa8, 0x3d, 0x9c, 0x64, 0x65, 0x5f, 0x13, 0x42, 0x44, 0x06, 0xa6, + 0x6f, 0x7b, 0xe0, 0xe1, 0xc7, 0x48, 0xc1, 0xc5, 0xd9, 0xf2, 0x49, 0x14, 0xa2, 0xb4, 0xd6, 0x1c, 0xab, 0x21, 0xc5, + 0xf6, 0x61, 0x9c, 0x70, 0x37, 0x28, 0xe4, 0xba, 0x17, 0xaa, 0x4e, 0x4c, 0xab, 0x6e, 0x8c, 0xd4, 0xc1, 0xb6, 0x59, + 0x70, 0x56, 0xf5, 0x6e, 0x24, 0x94, 0xea, 0x8d, 0x39, 0xf3, 0x4e, 0x68, 0xb3, 0x6d, 0x1e, 0x5e, 0xb6, 0x2f, 0xd1, + 0x29, 0x30, 0xe4, 0x3d, 0x2c, 0x03, 0x68, 0x5d, 0xc1, 0xb1, 0x1b, 0x07, 0x90, 0x95, 0xe4, 0x6a, 0xe5, 0x5e, 0x89, + 0xe3, 0x03, 0x39, 0xdc, 0x94, 0x6f, 0xc6, 0x05, 0x78, 0x10, 0x38, 0x05, 0x64, 0x21, 0x67, 0xe0, 0x1f, 0x5c, 0xac, + 0xe9, 0x87, 0xf8, 0x3f, 0x70, 0xc0, 0x57, 0x48, 0x9a, 0x5a, 0xf5, 0x13, 0xbc, 0xe5, 0x04, 0x0a, 0x6f, 0x5b, 0xf7, + 0x47, 0x19, 0x3a, 0xcd, 0xd6, 0x75, 0x2a, 0xd6, 0x2f, 0xb5, 0xae, 0x58, 0x29, 0x0b, 0x07, 0x54, 0x2b, 0x46, 0x9b, + 0xd4, 0xf9, 0xb0, 0xba, 0x07, 0xa0, 0x1e, 0x0a, 0xf0, 0x8d, 0xe1, 0x52, 0x3c, 0x2b, 0x20, 0xa2, 0x57, 0xa8, 0x4f, + 0xd3, 0x45, 0xf8, 0xc2, 0xf1, 0x00, 0xee, 0x09, 0x4b, 0x9e, 0xb3, 0x7c, 0x95, 0x1b, 0x16, 0x48, 0x01, 0x85, 0x52, + 0x58, 0xac, 0xd7, 0xb1, 0x30, 0x71, 0x1e, 0x5c, 0x98, 0x5f, 0xf7, 0x9e, 0x87, 0xd1, 0xdf, 0x41, 0x5d, 0xec, 0xd5, + 0x23, 0xc6, 0x84, 0x15, 0x85, 0x97, 0x4e, 0x45, 0x16, 0xf4, 0xb5, 0xaf, 0x0f, 0x51, 0x4d, 0xb9, 0x1f, 0x1b, 0x7d, + 0xef, 0x5b, 0x3e, 0x67, 0x72, 0x09, 0x0f, 0x29, 0x61, 0x46, 0x14, 0xd3, 0xfe, 0x1b, 0x28, 0x08, 0xbc, 0xc6, 0xc3, + 0x43, 0x7c, 0x04, 0xbe, 0xca, 0xd3, 0x3a, 0x9a, 0xf9, 0xe7, 0x39, 0x22, 0x13, 0x3e, 0x33, 0xea, 0x47, 0xe0, 0x45, + 0x04, 0x22, 0x14, 0x21, 0x11, 0x13, 0xe3, 0xa8, 0x1f, 0x19, 0x97, 0xac, 0x08, 0xac, 0xc6, 0x40, 0xc9, 0x1d, 0xe1, + 0xa9, 0xaa, 0x88, 0x58, 0x58, 0x53, 0x07, 0x95, 0x58, 0x6a, 0xcc, 0xb4, 0x4f, 0x3a, 0x15, 0x08, 0xb3, 0x6c, 0x5b, + 0x50, 0xd6, 0x5b, 0xea, 0x02, 0x2c, 0x89, 0x31, 0xbd, 0xe5, 0xc9, 0x47, 0xe0, 0xe6, 0xd8, 0xd8, 0x15, 0x5d, 0xf1, + 0x6b, 0x50, 0x4f, 0xa7, 0x05, 0xfe, 0x68, 0x18, 0xb6, 0x71, 0x4a, 0x37, 0x84, 0xe3, 0x8c, 0x14, 0x09, 0xbd, 0x85, + 0x38, 0x17, 0x73, 0x2e, 0xd2, 0x1c, 0xcf, 0xe9, 0x6d, 0x3a, 0xc3, 0x73, 0x2e, 0x9e, 0xd8, 0x65, 0x4f, 0xc7, 0x90, + 0xe4, 0x3f, 0x96, 0x1b, 0x62, 0x9e, 0xe9, 0x7a, 0xa7, 0x58, 0xf1, 0x08, 0x78, 0x15, 0x15, 0xa3, 0xde, 0xd8, 0xd8, + 0x94, 0x73, 0x5d, 0x19, 0xaf, 0xdf, 0xd3, 0x31, 0xc5, 0x19, 0xce, 0x51, 0x92, 0x4b, 0xcc, 0xfa, 0x22, 0xbd, 0x07, + 0x31, 0xae, 0x33, 0x6c, 0x9f, 0xf8, 0xe2, 0xb7, 0x2c, 0x7f, 0x26, 0x8b, 0xf7, 0x66, 0xcb, 0xe7, 0x08, 0x0a, 0x81, + 0x8b, 0x8a, 0x68, 0xc2, 0xed, 0xde, 0xb2, 0x2f, 0xab, 0xa6, 0xe8, 0xad, 0x6d, 0xca, 0x0d, 0x71, 0x06, 0xc1, 0x81, + 0x93, 0x19, 0x6f, 0xb4, 0x31, 0xeb, 0xb7, 0xbe, 0xd1, 0xe8, 0x0c, 0x95, 0x25, 0x11, 0x86, 0xb5, 0x6a, 0xaa, 0x54, + 0x12, 0xd1, 0x54, 0x4e, 0xc2, 0x5b, 0x19, 0x60, 0xa7, 0x0a, 0x67, 0x72, 0x29, 0x74, 0x2a, 0x03, 0xbc, 0xc9, 0xab, + 0xcd, 0xb5, 0xba, 0xb5, 0x10, 0xd3, 0xf8, 0xce, 0xfe, 0x60, 0xf8, 0xa3, 0x51, 0xf1, 0xbf, 0x01, 0xc3, 0x1e, 0x95, + 0x0a, 0x80, 0x1f, 0x18, 0xce, 0x02, 0xe4, 0x2c, 0x3f, 0x79, 0x0b, 0xe0, 0xb3, 0x2c, 0xe4, 0x1d, 0xa4, 0x32, 0x93, + 0x7a, 0x07, 0xa9, 0x0c, 0x52, 0x8d, 0x77, 0xfb, 0xa1, 0xa8, 0x94, 0x45, 0x61, 0x83, 0x44, 0xe1, 0x52, 0x1d, 0x2c, + 0x89, 0x48, 0xa0, 0x5d, 0x23, 0xca, 0xcd, 0xb9, 0x80, 0x30, 0x87, 0xd0, 0xb8, 0xfd, 0xa6, 0xb7, 0xf0, 0x7d, 0x67, + 0xf3, 0x99, 0xcf, 0xbf, 0xb3, 0xf9, 0xa6, 0x23, 0x8f, 0xf1, 0xf5, 0xdb, 0x4e, 0x63, 0x19, 0x2f, 0x1d, 0xd6, 0xbe, + 0x2b, 0x1f, 0x95, 0x69, 0x99, 0xc7, 0xbb, 0x49, 0x1b, 0xcf, 0x03, 0xa4, 0x6c, 0x56, 0x3c, 0x5c, 0x07, 0xb7, 0x5b, + 0xc7, 0x31, 0x6f, 0x92, 0x36, 0x42, 0xc7, 0x4e, 0xb8, 0x12, 0xb1, 0x91, 0x9c, 0x8e, 0xdf, 0x9f, 0xc0, 0xdd, 0xcb, + 0x48, 0x6d, 0xf9, 0x4a, 0xd9, 0x6a, 0xcd, 0x76, 0xeb, 0x98, 0xef, 0xad, 0xd2, 0x68, 0xe3, 0x39, 0x23, 0x2b, 0xf0, + 0x40, 0xa3, 0x85, 0x55, 0x35, 0x80, 0xcb, 0xea, 0x0b, 0xf1, 0xeb, 0x92, 0x8e, 0xcd, 0xf7, 0xb1, 0x4d, 0x79, 0xb5, + 0xd4, 0x3e, 0xa9, 0xc9, 0x61, 0x10, 0x1d, 0xe4, 0x4a, 0x06, 0x39, 0x31, 0x3f, 0x21, 0x49, 0x17, 0x5d, 0xb6, 0xfb, + 0x49, 0xf7, 0x98, 0x1f, 0xf3, 0x14, 0x78, 0xd8, 0xb8, 0xe9, 0x2b, 0x34, 0xdb, 0xbe, 0xce, 0xe3, 0xe5, 0x88, 0x67, + 0xae, 0xf9, 0xaa, 0x83, 0x32, 0xd5, 0xce, 0x11, 0xb2, 0x00, 0xc5, 0x7c, 0x2f, 0x41, 0x76, 0xbd, 0x9b, 0x63, 0x9e, + 0x42, 0x3f, 0x50, 0xab, 0x63, 0x6b, 0x95, 0x83, 0xfb, 0x75, 0x09, 0x08, 0xe6, 0x3b, 0xaa, 0xcd, 0xc5, 0xa6, 0x37, + 0xe3, 0xaa, 0xb3, 0x63, 0x5e, 0x8d, 0x30, 0x2c, 0xb3, 0xdb, 0x9f, 0x9f, 0x5a, 0xd5, 0xe5, 0x71, 0x00, 0x91, 0x5f, + 0x97, 0x5c, 0x84, 0x9d, 0x86, 0xdd, 0xba, 0x9c, 0xb0, 0xd3, 0xfa, 0x2c, 0x83, 0x22, 0xbb, 0xbd, 0xee, 0xcc, 0xb4, + 0x3e, 0xdb, 0x6b, 0x70, 0x24, 0x84, 0x49, 0x99, 0x95, 0xce, 0xa4, 0x8a, 0xf9, 0xf1, 0x3b, 0xe4, 0x5a, 0x7f, 0xb5, + 0xd4, 0x3e, 0xbf, 0x44, 0x04, 0xc8, 0xae, 0xba, 0x2e, 0xab, 0x43, 0x1f, 0x65, 0x13, 0x2f, 0x8f, 0x79, 0xb0, 0x72, + 0x4f, 0x6f, 0x17, 0x32, 0xf5, 0xf8, 0xda, 0x6f, 0xa5, 0x3b, 0xc8, 0x09, 0xc4, 0xc3, 0x75, 0x17, 0x96, 0x05, 0x39, + 0xbb, 0xb9, 0x83, 0x92, 0xe1, 0xc4, 0x7d, 0xe9, 0x77, 0xcc, 0x5e, 0x37, 0xf0, 0xcb, 0xa4, 0x0b, 0x53, 0xdf, 0xee, + 0xe1, 0xb8, 0x03, 0x7d, 0x18, 0x38, 0x6c, 0x37, 0xe8, 0x33, 0x2b, 0x88, 0x3c, 0xe6, 0x85, 0xc5, 0xb3, 0x2b, 0xd2, + 0xee, 0xf3, 0xd4, 0x6d, 0x26, 0x23, 0x1a, 0xb5, 0x9b, 0x3c, 0x98, 0x19, 0xe0, 0x97, 0x2b, 0x1b, 0x16, 0xf1, 0xeb, + 0x14, 0x40, 0xc9, 0x17, 0xab, 0xd6, 0xa7, 0x82, 0x57, 0xbd, 0xe1, 0x74, 0x3b, 0xdd, 0xaf, 0x1b, 0xdc, 0xee, 0x7a, + 0x78, 0xc2, 0xa3, 0x30, 0x16, 0xad, 0xfd, 0xc4, 0xe7, 0xc0, 0x01, 0x25, 0xad, 0xfb, 0x5d, 0x70, 0xa1, 0x2c, 0x61, + 0xb9, 0x5b, 0x6e, 0xb4, 0x53, 0xce, 0xc2, 0xd1, 0x96, 0x0c, 0xb8, 0x83, 0x6d, 0x88, 0x42, 0x07, 0xc7, 0x1d, 0x9c, + 0xb4, 0xdb, 0x9d, 0x2e, 0x4e, 0xce, 0xba, 0x30, 0xd0, 0x46, 0xd2, 0x3d, 0x1e, 0x29, 0x0b, 0xc0, 0x20, 0x67, 0xe3, + 0xda, 0x7d, 0x04, 0x01, 0xa4, 0x42, 0xf1, 0x9a, 0x1f, 0xc7, 0x71, 0x3b, 0xb9, 0xdf, 0x6a, 0x77, 0x2f, 0x1a, 0x00, + 0xa0, 0xa6, 0xfb, 0x70, 0x35, 0x5e, 0x2d, 0x75, 0xbd, 0x4a, 0x89, 0xf0, 0xf5, 0x6a, 0x0d, 0x5f, 0xad, 0xd1, 0xde, + 0x54, 0x53, 0xf0, 0x55, 0x9d, 0x70, 0x6e, 0x8b, 0x78, 0xa5, 0x4d, 0xb8, 0x2d, 0x62, 0x3b, 0x90, 0x18, 0xa4, 0xf3, + 0xa4, 0xdb, 0xe9, 0x22, 0x3b, 0x16, 0xed, 0xf0, 0xa3, 0xdc, 0x27, 0x3b, 0x45, 0x1a, 0x1a, 0x90, 0xa4, 0x9c, 0x9d, + 0x5c, 0x82, 0x44, 0xcd, 0xc9, 0x55, 0xbb, 0x39, 0x67, 0x89, 0x9f, 0x80, 0x49, 0x85, 0xe5, 0x2c, 0x57, 0xc1, 0x25, + 0x05, 0x80, 0xb8, 0x04, 0xe3, 0xa2, 0xfb, 0xdd, 0xfe, 0xfd, 0xa4, 0x7b, 0xde, 0xb1, 0x44, 0x8f, 0x5f, 0x76, 0x6a, + 0x69, 0x66, 0xea, 0x49, 0xd7, 0xa4, 0x41, 0xd7, 0xc9, 0xfd, 0x2e, 0x94, 0x71, 0x29, 0x61, 0x29, 0x08, 0x7c, 0x51, + 0x15, 0x83, 0x68, 0x17, 0x69, 0x2d, 0xf7, 0xbc, 0x96, 0x7d, 0x71, 0x76, 0x7a, 0xbf, 0x1b, 0x42, 0xad, 0x9c, 0x85, + 0x59, 0x68, 0x37, 0x11, 0x3f, 0x3b, 0x58, 0x5a, 0x74, 0x9c, 0x74, 0xd3, 0x9d, 0x09, 0xda, 0x4d, 0x73, 0x6c, 0x70, + 0x20, 0x50, 0x38, 0xbe, 0x10, 0x4e, 0x5f, 0x12, 0xdc, 0x8f, 0x55, 0x86, 0x26, 0xa1, 0xc2, 0xd9, 0xdf, 0x53, 0x06, + 0x6f, 0x5b, 0x86, 0x57, 0x95, 0x8f, 0xa9, 0xf8, 0x42, 0xd5, 0x6b, 0x0a, 0xd1, 0x3c, 0xc4, 0x30, 0x72, 0xb1, 0xc6, + 0xeb, 0xb9, 0x3f, 0x80, 0x8b, 0x30, 0x13, 0x70, 0xa1, 0xe9, 0x95, 0xa0, 0x15, 0x2f, 0xf0, 0x31, 0x74, 0xa8, 0x35, + 0xc3, 0xea, 0xf3, 0xd4, 0x99, 0x14, 0x84, 0xba, 0xad, 0x77, 0xfc, 0x5b, 0xe5, 0x92, 0xf2, 0x2a, 0x3b, 0xe9, 0xa2, + 0xc4, 0x5d, 0x96, 0x27, 0x6d, 0x94, 0x04, 0x26, 0x24, 0xee, 0x48, 0x9e, 0x65, 0x64, 0x10, 0xdd, 0x46, 0x38, 0xba, + 0x8b, 0x70, 0x64, 0x7d, 0x98, 0x7f, 0x03, 0x3f, 0xee, 0x08, 0x47, 0xd6, 0x95, 0x39, 0xc2, 0x91, 0x66, 0x02, 0x82, + 0x7c, 0x45, 0x43, 0x3c, 0x86, 0xd2, 0xc6, 0xb3, 0xba, 0x2c, 0xfd, 0xd8, 0x7f, 0x95, 0xae, 0xd7, 0x36, 0x25, 0x90, + 0x32, 0x97, 0x66, 0x87, 0xda, 0x47, 0xaa, 0x23, 0xea, 0x99, 0xf5, 0x08, 0x83, 0x00, 0x42, 0xef, 0xfc, 0x23, 0x77, + 0x55, 0x7c, 0x10, 0x76, 0x0a, 0x2b, 0x0d, 0xae, 0xe8, 0x51, 0x78, 0x86, 0x45, 0x78, 0x22, 0x7c, 0x61, 0x10, 0x2b, + 0xfc, 0xef, 0x5c, 0xca, 0x85, 0xff, 0xad, 0x65, 0xf9, 0x0b, 0x9e, 0x46, 0x71, 0x16, 0x2d, 0x60, 0xb9, 0x65, 0xc3, + 0x11, 0x8d, 0x58, 0x7d, 0x04, 0x1f, 0x27, 0x2e, 0x64, 0x1c, 0x48, 0x84, 0x1f, 0x8d, 0x40, 0xe5, 0xe5, 0xc3, 0x8f, + 0x36, 0x7c, 0x91, 0xf9, 0x84, 0xf8, 0x65, 0x10, 0xa2, 0x58, 0xc2, 0x85, 0xc6, 0xb4, 0x60, 0x4a, 0x45, 0x36, 0xae, + 0x5f, 0x24, 0x85, 0x7f, 0xa8, 0xd1, 0xa7, 0x4c, 0x44, 0x64, 0x3a, 0xac, 0xcf, 0xd6, 0x8a, 0xc3, 0xb9, 0x2c, 0x54, + 0x6a, 0x5f, 0x6d, 0xf1, 0x60, 0x5c, 0x94, 0x4f, 0x22, 0xa6, 0xe3, 0x6c, 0x83, 0xed, 0x1d, 0x76, 0x59, 0xc8, 0x5d, + 0x69, 0x87, 0xa5, 0x66, 0xd9, 0xe6, 0x6b, 0x13, 0x52, 0xb5, 0x19, 0x05, 0x13, 0xad, 0x06, 0x54, 0x05, 0xee, 0x80, + 0xc2, 0x36, 0x40, 0x4c, 0xba, 0x2a, 0x4b, 0xa6, 0xab, 0x72, 0x19, 0xce, 0x5a, 0xad, 0xcd, 0x06, 0x17, 0xcc, 0x04, + 0x55, 0xd9, 0x5b, 0x02, 0xf2, 0xd5, 0x4c, 0xde, 0x04, 0xb9, 0x2a, 0x2d, 0x67, 0x69, 0x96, 0x28, 0x0a, 0x8c, 0x60, + 0xa3, 0x0d, 0xfe, 0xc2, 0x15, 0x07, 0x78, 0xba, 0xd9, 0x8d, 0xa4, 0xcc, 0x19, 0x85, 0x78, 0x66, 0x41, 0x93, 0x1b, + 0x3c, 0xe3, 0x63, 0xb6, 0xbf, 0x4d, 0x30, 0x63, 0xfe, 0xf7, 0x5a, 0xf4, 0x08, 0x64, 0xd9, 0x3d, 0x83, 0x3a, 0xb0, + 0x88, 0x6b, 0xe8, 0x20, 0x94, 0xc1, 0x27, 0x21, 0x6e, 0xe6, 0xf4, 0x4e, 0x2e, 0x35, 0xc0, 0x65, 0xa9, 0xe5, 0x6b, + 0x17, 0x0e, 0xe1, 0xb0, 0x85, 0x7d, 0x64, 0x84, 0x15, 0x84, 0x0c, 0x68, 0x61, 0x1b, 0x11, 0xa3, 0x85, 0x5d, 0xa0, + 0x82, 0x16, 0x36, 0xe1, 0x29, 0x5a, 0x9b, 0x32, 0xce, 0xd8, 0x5d, 0xf9, 0xbc, 0x65, 0xb5, 0x09, 0x16, 0x4e, 0x3a, + 0xd4, 0x44, 0x07, 0xb7, 0x87, 0x8c, 0xf0, 0xc6, 0x8f, 0xd7, 0xaf, 0x5e, 0xba, 0x28, 0xd2, 0x7c, 0x02, 0x2e, 0x9b, + 0x4e, 0x35, 0x76, 0x67, 0xc3, 0xbd, 0x57, 0x8a, 0x52, 0x2b, 0x9c, 0x9a, 0xc0, 0x9b, 0x42, 0xe7, 0x89, 0xbd, 0xbc, + 0x78, 0x26, 0x8b, 0x39, 0xb5, 0x37, 0x46, 0xf8, 0x4e, 0xb9, 0x87, 0xe0, 0xcd, 0x5b, 0x33, 0xd5, 0x24, 0xdf, 0x6e, + 0x5f, 0x45, 0x2c, 0x32, 0x23, 0xbf, 0x82, 0x36, 0xc0, 0x54, 0xf6, 0x03, 0x67, 0x05, 0x71, 0xb1, 0xf8, 0x03, 0xf2, + 0xf2, 0xc6, 0x52, 0x97, 0x28, 0x6a, 0x70, 0x83, 0x9f, 0xac, 0xe0, 0x59, 0x70, 0x5d, 0x68, 0xd8, 0x23, 0x27, 0x5e, + 0x44, 0xad, 0xa8, 0xfe, 0x0e, 0xae, 0x51, 0x25, 0xf8, 0x38, 0xae, 0x49, 0x2e, 0x41, 0xf4, 0x28, 0x9f, 0xdc, 0xe3, + 0x20, 0x9a, 0xf8, 0xbb, 0xe7, 0xab, 0xb6, 0xa7, 0xb3, 0x79, 0xa5, 0x4e, 0x2c, 0xaf, 0x4c, 0xc0, 0xc3, 0xd1, 0x3e, + 0x6a, 0x83, 0x70, 0x90, 0xc8, 0x4a, 0xed, 0xa1, 0xcf, 0x45, 0xbd, 0x38, 0xbf, 0x6c, 0xb3, 0xe6, 0xd9, 0x7a, 0x9d, + 0x5f, 0xb5, 0x59, 0xbb, 0x6b, 0x9f, 0xc0, 0x8b, 0x54, 0x06, 0x34, 0x97, 0x4f, 0x78, 0x16, 0x81, 0x76, 0x76, 0x9a, + 0x99, 0x70, 0x0a, 0x1b, 0xaf, 0xf8, 0x59, 0xea, 0xaa, 0x2f, 0x09, 0xc6, 0xa5, 0xc4, 0xea, 0xf1, 0x0b, 0xd4, 0x6f, + 0xa7, 0xbb, 0xae, 0xd2, 0xcd, 0xf6, 0x71, 0x70, 0xe1, 0x52, 0x20, 0xdc, 0x81, 0x90, 0x07, 0xa0, 0xdf, 0x5d, 0x09, + 0x30, 0x0d, 0x02, 0x54, 0x56, 0x20, 0xd2, 0xf2, 0xf9, 0x72, 0xfe, 0xac, 0xa0, 0x66, 0x19, 0x9e, 0xf0, 0x29, 0xd7, + 0x2a, 0xa5, 0x20, 0xdd, 0xee, 0x4b, 0xdf, 0xec, 0x97, 0xa0, 0xb2, 0x5a, 0x2c, 0xdc, 0x44, 0xf3, 0xec, 0xb3, 0x72, + 0x0b, 0x87, 0xb0, 0x59, 0x59, 0x81, 0x33, 0xb4, 0xc1, 0xb9, 0x9c, 0xd2, 0x82, 0xeb, 0xd9, 0xfc, 0xdf, 0x5a, 0x1d, + 0x36, 0xd0, 0x43, 0x73, 0x61, 0x05, 0x20, 0xa1, 0x62, 0xbc, 0x5e, 0xf3, 0x93, 0x6f, 0xdf, 0x27, 0x79, 0x9f, 0xf0, + 0x36, 0xee, 0xe0, 0x53, 0xdc, 0xc5, 0xed, 0x16, 0x6e, 0x77, 0xe1, 0xea, 0x3e, 0xcb, 0x97, 0x63, 0xa6, 0x62, 0x78, + 0x0b, 0x4d, 0x5f, 0x25, 0x17, 0xc7, 0xd5, 0x0b, 0x00, 0x45, 0xe2, 0xd0, 0x25, 0x08, 0x44, 0xef, 0x22, 0xf8, 0x45, + 0x51, 0x18, 0x3e, 0x6e, 0x1a, 0xaa, 0x4e, 0x4a, 0xfd, 0xc2, 0xd5, 0x69, 0x1f, 0xec, 0xb9, 0xed, 0xca, 0x36, 0xc1, + 0xec, 0xdb, 0xfe, 0x4c, 0xab, 0x9f, 0x4d, 0x5d, 0x22, 0x86, 0x87, 0x5e, 0x85, 0x1e, 0xe8, 0x8a, 0xb4, 0x8f, 0x8e, + 0xc0, 0xea, 0x28, 0x98, 0x0d, 0xb7, 0xd1, 0x0f, 0x78, 0xb3, 0x96, 0x06, 0xc1, 0x0a, 0xc0, 0xb8, 0xf3, 0x15, 0x27, + 0x2b, 0x0b, 0x5b, 0x0d, 0x54, 0x98, 0x15, 0x61, 0x8c, 0xbb, 0x90, 0x54, 0x18, 0x21, 0x1a, 0x8e, 0x30, 0x17, 0x0c, + 0xe5, 0xb0, 0x85, 0xe5, 0x64, 0xa2, 0x98, 0x86, 0xa3, 0xa3, 0x60, 0x5f, 0x58, 0xa1, 0xcc, 0x29, 0x32, 0x62, 0x53, + 0x2e, 0x1e, 0xea, 0x3f, 0x58, 0x21, 0xcd, 0xa7, 0xd1, 0x60, 0xa4, 0x91, 0x59, 0xc5, 0x08, 0x67, 0x39, 0x5f, 0x40, + 0xd5, 0x69, 0x01, 0x4e, 0x3f, 0xf0, 0x97, 0x8f, 0xd3, 0xb0, 0x4d, 0x20, 0x5f, 0xbf, 0xd9, 0x98, 0x2e, 0x78, 0x5c, + 0xd0, 0x9b, 0x57, 0xe2, 0x31, 0xec, 0xa8, 0x87, 0x05, 0xa3, 0x90, 0x0d, 0x49, 0x6f, 0xa1, 0x29, 0xf8, 0x80, 0x36, + 0x7f, 0x36, 0x80, 0x4b, 0x2f, 0xcc, 0x87, 0xad, 0xe8, 0xe3, 0x28, 0x26, 0x65, 0x5b, 0x26, 0xd3, 0x9c, 0xd2, 0x55, + 0xa6, 0xa1, 0xb0, 0xd5, 0x14, 0x36, 0xd8, 0x45, 0x3d, 0x09, 0x07, 0x33, 0xa6, 0x6a, 0x96, 0x0e, 0x86, 0xe6, 0xef, + 0x2b, 0x5b, 0xb2, 0x85, 0x5d, 0xc4, 0x99, 0x0d, 0x36, 0x8f, 0x98, 0x06, 0xe5, 0xdb, 0x18, 0xee, 0x61, 0xe1, 0x25, + 0xcd, 0x1a, 0xf9, 0x3c, 0xf3, 0x64, 0xf3, 0x6c, 0xb3, 0x31, 0x03, 0x51, 0x29, 0xe8, 0x81, 0xde, 0xf8, 0x6d, 0xd3, + 0x82, 0xed, 0x51, 0x7e, 0x75, 0x5b, 0x78, 0xce, 0xe1, 0x61, 0x50, 0xdf, 0xde, 0xb5, 0x2e, 0xe4, 0x67, 0x07, 0x92, + 0x56, 0x90, 0x62, 0xa7, 0x13, 0x74, 0x76, 0x8a, 0x83, 0x91, 0x03, 0x3d, 0xbf, 0xfe, 0x6c, 0x61, 0xed, 0x7f, 0xbf, + 0x2e, 0x0b, 0x9a, 0x78, 0x3a, 0xe5, 0x84, 0x32, 0x7f, 0x7e, 0xbe, 0xe2, 0x49, 0x85, 0x0a, 0xee, 0x45, 0x2d, 0xd8, + 0xd3, 0x36, 0xe8, 0xe6, 0x9c, 0x7e, 0xb2, 0x3f, 0x6c, 0x0c, 0x9f, 0x52, 0xcb, 0x96, 0x15, 0x52, 0xa9, 0x87, 0x36, + 0xcd, 0x1e, 0x3d, 0x70, 0x44, 0xfe, 0x0c, 0x5d, 0x00, 0xaf, 0x3f, 0x2e, 0xe4, 0xc2, 0x20, 0x82, 0xfb, 0xed, 0xc6, + 0x6d, 0x7c, 0x05, 0xc0, 0xdb, 0xe1, 0xa0, 0xfa, 0xa7, 0x05, 0xec, 0x6f, 0x54, 0x96, 0xf4, 0xe3, 0xed, 0xd8, 0xe3, + 0xbf, 0x90, 0x10, 0xc1, 0xdd, 0xe2, 0x61, 0xe2, 0xd0, 0xa9, 0x64, 0xcd, 0xca, 0x9f, 0x3b, 0x25, 0x01, 0xc3, 0xea, + 0x05, 0x43, 0x36, 0x6e, 0xa7, 0xb8, 0xcd, 0xfc, 0x0f, 0x2a, 0x18, 0x2c, 0xf8, 0xda, 0x48, 0x2a, 0x96, 0xc5, 0x6f, + 0x9f, 0x3a, 0xff, 0x55, 0xe7, 0xb8, 0x0e, 0x75, 0xed, 0xd5, 0xce, 0x91, 0x89, 0x98, 0x1c, 0xa1, 0xa3, 0xa3, 0xad, + 0x0c, 0x3a, 0x01, 0xc0, 0x23, 0xc7, 0x7e, 0xf9, 0xe5, 0xf3, 0xec, 0x98, 0xd1, 0x3c, 0x16, 0x51, 0xc8, 0xdc, 0x79, + 0x6e, 0xce, 0x4e, 0xe4, 0x09, 0x55, 0x33, 0x5f, 0x18, 0xe0, 0xf8, 0x68, 0x27, 0x15, 0xf0, 0x3d, 0xda, 0xec, 0x99, + 0xc0, 0x16, 0xbf, 0x65, 0x27, 0xb5, 0xaf, 0xa0, 0x5f, 0xa0, 0xd5, 0x3e, 0xa6, 0x72, 0x6b, 0x81, 0xa3, 0xed, 0x89, + 0xec, 0x1d, 0xfa, 0x56, 0x9d, 0x92, 0xf5, 0x78, 0xb1, 0xdf, 0xe8, 0xab, 0x10, 0xfb, 0x92, 0x2b, 0xda, 0x36, 0x62, + 0xd5, 0xcb, 0xbd, 0xba, 0x32, 0x75, 0xaa, 0xae, 0x79, 0x2b, 0x4b, 0x9b, 0xd2, 0x2e, 0xc9, 0xde, 0x6d, 0xb1, 0xf0, + 0x2a, 0xbc, 0xd1, 0x28, 0x2f, 0x42, 0xc1, 0x1e, 0x4b, 0x0c, 0x7b, 0x9c, 0xc0, 0xf5, 0xc2, 0x7a, 0x1d, 0xc3, 0x9f, + 0x7d, 0x63, 0xd8, 0x67, 0xba, 0xf4, 0x1b, 0xdf, 0xe2, 0x57, 0x82, 0xe0, 0xc1, 0xce, 0x0e, 0x12, 0xac, 0xbb, 0xdc, + 0xa0, 0xe1, 0x38, 0xf1, 0x5f, 0xf0, 0x74, 0xb5, 0xf6, 0x2e, 0x07, 0xa3, 0xec, 0x2b, 0xcf, 0xdd, 0x95, 0xac, 0x65, + 0x2d, 0xf2, 0xfc, 0x96, 0x04, 0x43, 0xec, 0xa6, 0x74, 0x8e, 0x5b, 0x49, 0x1b, 0x45, 0xae, 0x58, 0x85, 0xfe, 0x5f, + 0x2b, 0x92, 0xd9, 0xcc, 0xff, 0x3a, 0x3f, 0x3f, 0x77, 0x29, 0xce, 0xe6, 0x4f, 0x19, 0x0f, 0x38, 0x93, 0xc0, 0xbe, + 0xf0, 0x8c, 0x19, 0x1d, 0xf2, 0x1b, 0x18, 0x0a, 0x11, 0xe4, 0x4a, 0x38, 0x76, 0x09, 0x5e, 0x5e, 0x04, 0xca, 0x03, + 0xec, 0xdf, 0x93, 0xad, 0x72, 0xfe, 0xe9, 0x26, 0x1f, 0xda, 0xb8, 0x6c, 0x90, 0x7d, 0x31, 0x9f, 0x03, 0x6b, 0x26, + 0x03, 0xaf, 0x15, 0x44, 0xd8, 0xfe, 0x36, 0x2c, 0xad, 0xb3, 0x94, 0xc1, 0x91, 0x96, 0xcb, 0x6c, 0x66, 0x35, 0xff, + 0xee, 0xc3, 0x94, 0x75, 0xcf, 0xfe, 0x40, 0xe4, 0x2e, 0xb2, 0x72, 0x11, 0x3a, 0xa3, 0xef, 0xcb, 0x60, 0x9c, 0x07, + 0x2f, 0xd9, 0x92, 0x7d, 0x8f, 0x0f, 0xaa, 0x14, 0xf8, 0x78, 0x58, 0x70, 0x9a, 0x7f, 0x8f, 0x0f, 0xaa, 0xa0, 0x9c, + 0xe0, 0x0a, 0x69, 0xe2, 0x5a, 0x62, 0xf3, 0xc4, 0x75, 0x1a, 0x09, 0xa0, 0xa0, 0x79, 0x64, 0x0e, 0xb2, 0xe7, 0x2e, + 0x5e, 0x62, 0xd2, 0xc1, 0x2e, 0x38, 0x98, 0x8d, 0xce, 0x6a, 0x83, 0x9a, 0x43, 0xdc, 0xba, 0x72, 0x36, 0xe6, 0xeb, + 0xd1, 0xd6, 0x82, 0x18, 0x65, 0x32, 0xb9, 0x7a, 0xc7, 0xe3, 0x9d, 0xc5, 0x42, 0x61, 0xb5, 0x60, 0x81, 0x6a, 0x55, + 0xaa, 0xf4, 0xb0, 0xf8, 0x6e, 0xc1, 0x2c, 0x28, 0x62, 0xb6, 0xde, 0xc3, 0x5b, 0xae, 0x08, 0x48, 0xc9, 0x2e, 0x09, + 0x5e, 0x29, 0x37, 0x98, 0xea, 0x1f, 0xa5, 0x07, 0x42, 0xcf, 0x94, 0x8e, 0xb0, 0xc9, 0x53, 0x10, 0x49, 0xec, 0xb0, + 0x85, 0x1d, 0x6b, 0xf4, 0x42, 0x78, 0x21, 0x05, 0xce, 0x55, 0xd3, 0xc4, 0x9c, 0x72, 0x13, 0x5d, 0xec, 0xa1, 0x5a, + 0xb0, 0x4c, 0x5b, 0x04, 0x38, 0x74, 0x68, 0x28, 0xc5, 0x73, 0x03, 0x0a, 0xf3, 0xbc, 0xb6, 0x4b, 0x79, 0x0c, 0x8b, + 0x17, 0xa4, 0x00, 0x51, 0xe3, 0x62, 0x5a, 0xd6, 0x59, 0xe4, 0xcb, 0x29, 0x17, 0x15, 0x32, 0x14, 0x4c, 0x2d, 0xa4, + 0x80, 0xd7, 0x2d, 0xca, 0x22, 0x86, 0x0e, 0xd5, 0xf0, 0xdd, 0x92, 0xb0, 0xb2, 0x8e, 0x39, 0xa6, 0xb8, 0xa8, 0x6a, + 0x00, 0x73, 0xf1, 0xd0, 0x08, 0x88, 0x3e, 0xd4, 0xeb, 0x2b, 0xf1, 0x56, 0x2e, 0xaa, 0x7c, 0x4f, 0xe3, 0x7c, 0x10, + 0x79, 0x67, 0x37, 0x8c, 0x36, 0xe6, 0x01, 0xaa, 0x60, 0xfb, 0xfe, 0xc6, 0xab, 0x47, 0xd9, 0x36, 0xe6, 0x09, 0xab, + 0x32, 0x6b, 0xc4, 0xca, 0xf7, 0x1a, 0xaa, 0xf6, 0xea, 0x55, 0x0b, 0x61, 0x2b, 0x02, 0x54, 0x0a, 0x3e, 0xde, 0xc9, + 0x7f, 0xa1, 0x6d, 0xbe, 0x3d, 0x87, 0xca, 0xf0, 0x40, 0x9e, 0x0c, 0x55, 0x3d, 0xe0, 0xa2, 0xfc, 0x10, 0xc0, 0xe2, + 0x47, 0x26, 0x96, 0xef, 0xbe, 0x0b, 0x64, 0xce, 0x54, 0x2c, 0xf1, 0x6a, 0x40, 0x87, 0xa9, 0x95, 0x87, 0x52, 0x09, + 0xb6, 0x3d, 0x37, 0x05, 0xd7, 0x3e, 0x68, 0x30, 0x1e, 0xb0, 0x61, 0xba, 0xaa, 0x07, 0x16, 0xb6, 0xa1, 0x8d, 0xbd, + 0x39, 0xa7, 0x89, 0xc4, 0x4b, 0x87, 0x38, 0x27, 0x60, 0x7b, 0x5c, 0x32, 0xf7, 0x71, 0x86, 0xfa, 0x75, 0x0e, 0x7f, + 0xb5, 0xc1, 0x39, 0xce, 0x50, 0xfa, 0x30, 0x86, 0x0b, 0xac, 0x0d, 0x06, 0xf0, 0x65, 0x96, 0x54, 0x81, 0x47, 0x6a, + 0x66, 0x24, 0x56, 0x77, 0x11, 0x88, 0x56, 0x3a, 0xbc, 0x1d, 0x67, 0x3e, 0x34, 0xb7, 0xe1, 0x5e, 0x9f, 0x19, 0xe1, + 0x70, 0x94, 0xc5, 0xb5, 0x73, 0x86, 0x93, 0xab, 0x43, 0x5e, 0x3b, 0x31, 0xc1, 0xda, 0x3b, 0x3c, 0x55, 0x40, 0x8f, + 0x06, 0xa7, 0x8a, 0xa5, 0x21, 0x10, 0x33, 0x01, 0xbc, 0x99, 0xc3, 0xa3, 0x2d, 0xc0, 0xf9, 0x68, 0x83, 0x83, 0xaf, + 0xb4, 0xd6, 0xd5, 0xb6, 0x12, 0x65, 0xb3, 0xc1, 0x83, 0x65, 0x86, 0x27, 0x19, 0x9e, 0x67, 0xc3, 0xe0, 0xb8, 0xf9, + 0x98, 0x85, 0x26, 0x5d, 0xeb, 0xf5, 0x0b, 0x67, 0x46, 0x88, 0xec, 0x4f, 0x4b, 0x7f, 0x50, 0x1f, 0x10, 0x3e, 0x85, + 0x2c, 0xa0, 0x25, 0x7d, 0xf7, 0xb7, 0x61, 0x5f, 0xee, 0x46, 0x8d, 0x98, 0x27, 0x96, 0x8c, 0xf4, 0xfd, 0x8f, 0x32, + 0xcb, 0xb6, 0xd6, 0x88, 0x16, 0xb7, 0x07, 0x51, 0xc3, 0xb7, 0x57, 0x9d, 0x2f, 0xa3, 0xd2, 0x6c, 0x07, 0x10, 0xc5, + 0x1a, 0x27, 0xe9, 0x60, 0x8d, 0xe4, 0x7a, 0x1d, 0xdb, 0x14, 0xc2, 0x93, 0x39, 0xa3, 0x6a, 0x59, 0x98, 0xc7, 0xec, + 0x62, 0x85, 0x12, 0xc3, 0xef, 0x62, 0x67, 0x23, 0x0a, 0x6f, 0xc7, 0x49, 0x30, 0xdc, 0x88, 0x05, 0x91, 0x35, 0x91, + 0xfb, 0x2e, 0xab, 0x2c, 0x83, 0x04, 0x11, 0x46, 0xe4, 0xb7, 0xd7, 0xa5, 0xc2, 0x3e, 0x97, 0x67, 0xff, 0x18, 0x5f, + 0x40, 0xb8, 0x79, 0x9b, 0xd2, 0x62, 0x44, 0xa7, 0xc0, 0xc6, 0x42, 0x1c, 0xc2, 0x9d, 0x84, 0xf5, 0x7a, 0x30, 0xec, + 0x09, 0x43, 0x9e, 0xdd, 0x63, 0x7e, 0x65, 0x43, 0xfb, 0x1b, 0x80, 0xab, 0x6e, 0x4b, 0xcd, 0xb5, 0xd1, 0xfd, 0x50, + 0xf3, 0xde, 0x18, 0x77, 0x49, 0xee, 0xc9, 0x90, 0xea, 0x55, 0xf0, 0x9a, 0x05, 0xb8, 0x09, 0x5d, 0x85, 0xc7, 0x78, + 0x69, 0x6d, 0x38, 0xcd, 0xe3, 0x52, 0xd4, 0xbc, 0x29, 0x05, 0x4f, 0x59, 0x13, 0x36, 0xc8, 0x86, 0x78, 0xec, 0x43, + 0x8f, 0x1f, 0xbe, 0x89, 0xc7, 0x08, 0x15, 0xc4, 0xc0, 0xd4, 0xba, 0x6c, 0x8f, 0x2b, 0xbb, 0x7d, 0x93, 0x69, 0x18, + 0x06, 0x63, 0xc4, 0x3c, 0x0e, 0x8d, 0x98, 0xf3, 0x46, 0x03, 0x2d, 0xc9, 0x18, 0x8c, 0x98, 0x97, 0x41, 0x6b, 0x4b, + 0xfb, 0xf0, 0x68, 0xd0, 0xde, 0x12, 0xa1, 0x1e, 0x07, 0x9a, 0xa6, 0xe1, 0x89, 0x91, 0xea, 0x89, 0x77, 0xff, 0xe0, + 0xd5, 0x49, 0x07, 0x14, 0x09, 0x93, 0x2b, 0x3f, 0x09, 0xeb, 0x1a, 0x6e, 0xc7, 0x3d, 0x31, 0xe3, 0x76, 0xb6, 0x0d, + 0x6a, 0x20, 0x07, 0xd9, 0x70, 0xd8, 0x93, 0xde, 0x4a, 0xa2, 0x85, 0x27, 0xd5, 0xa3, 0x24, 0xd5, 0xe2, 0x7d, 0xd1, + 0xdb, 0x57, 0xde, 0xdc, 0xbf, 0x75, 0xba, 0x7d, 0x1e, 0x03, 0x07, 0x74, 0x08, 0xf7, 0x43, 0x55, 0x7c, 0xb0, 0x93, + 0x0e, 0x44, 0x41, 0x4b, 0x5b, 0x35, 0x81, 0xd4, 0x9a, 0xd9, 0xc5, 0xba, 0xa9, 0xd0, 0xb1, 0x80, 0x30, 0x64, 0xaa, + 0xea, 0xee, 0x56, 0x05, 0xaa, 0x21, 0x0e, 0xa7, 0xfe, 0x63, 0x6b, 0xc4, 0x1a, 0x47, 0x9d, 0x71, 0x64, 0x8c, 0x24, + 0xed, 0xf2, 0xc1, 0x3b, 0x44, 0x60, 0x25, 0xe0, 0xe3, 0x41, 0x9b, 0x24, 0x63, 0x48, 0xf0, 0x86, 0x65, 0xda, 0xf0, + 0x21, 0xdc, 0x21, 0x28, 0x4f, 0x6c, 0x50, 0x5a, 0x57, 0xc9, 0x42, 0x2e, 0xe8, 0x32, 0x40, 0xcf, 0x2f, 0xe5, 0x6f, + 0x6c, 0x38, 0xb2, 0x00, 0x0e, 0xd9, 0xce, 0x3e, 0x01, 0x8f, 0x7c, 0x5c, 0x21, 0x88, 0x5f, 0x0a, 0x9d, 0x98, 0xd8, + 0xd9, 0xd7, 0xb0, 0x41, 0xf1, 0x02, 0x1c, 0x04, 0x9d, 0x04, 0x87, 0xc1, 0xbb, 0xcc, 0x6a, 0x92, 0x0d, 0x6e, 0xcd, + 0x49, 0xbc, 0x58, 0xaf, 0x5b, 0xe8, 0xf8, 0x27, 0xf3, 0x3c, 0xf4, 0xa4, 0x54, 0xb8, 0x4f, 0x2a, 0x85, 0x3b, 0x58, + 0x02, 0x92, 0x49, 0xa0, 0x6b, 0xc7, 0x32, 0x54, 0xa3, 0x43, 0xe4, 0xf2, 0x17, 0x10, 0xc7, 0xda, 0x1d, 0x4b, 0xa0, + 0x67, 0xdf, 0x29, 0x60, 0x75, 0xed, 0x65, 0x09, 0x64, 0x04, 0x77, 0xbf, 0x09, 0x8c, 0x0a, 0xd1, 0xf8, 0xfc, 0x99, + 0x17, 0x26, 0x78, 0xe2, 0xfc, 0xb9, 0xe6, 0x86, 0x75, 0x2f, 0xe8, 0x8d, 0x69, 0x3e, 0x9e, 0xe0, 0xe6, 0xc4, 0x82, + 0xf3, 0xa4, 0x03, 0x3f, 0x2d, 0x44, 0x4f, 0x3a, 0xd8, 0xa5, 0xe2, 0x49, 0x09, 0xe4, 0x10, 0x3d, 0x9d, 0x81, 0x14, + 0xb0, 0xd2, 0xb1, 0xd5, 0x22, 0x4d, 0xd1, 0x7a, 0x3d, 0xbd, 0x24, 0x2d, 0x84, 0x56, 0xea, 0x86, 0xeb, 0x6c, 0x06, + 0x3e, 0xd2, 0xa0, 0x18, 0x78, 0x4d, 0xf5, 0x2c, 0x46, 0x78, 0x82, 0x56, 0x63, 0x36, 0xa1, 0xcb, 0x5c, 0xa7, 0xaa, + 0xcf, 0x13, 0x1b, 0xb8, 0x97, 0xd9, 0x48, 0x70, 0x27, 0x1d, 0x3c, 0x35, 0xfc, 0xe5, 0x7b, 0x63, 0x0e, 0x52, 0x64, + 0x26, 0x79, 0x6a, 0x12, 0x30, 0x4f, 0xb2, 0x5c, 0x2a, 0x66, 0x9b, 0xe9, 0x59, 0xdb, 0x72, 0x08, 0x0f, 0x1e, 0xe9, + 0x82, 0x1b, 0x2b, 0xca, 0x28, 0x9d, 0x11, 0xd5, 0x57, 0x27, 0x9d, 0x74, 0x8a, 0x79, 0x02, 0x9c, 0xde, 0x5b, 0x19, + 0xb3, 0x46, 0x79, 0x2b, 0x3a, 0x47, 0xc7, 0x33, 0x2c, 0xaa, 0x4b, 0xd4, 0x39, 0x3a, 0x9e, 0x22, 0x3c, 0x6f, 0x90, + 0x99, 0x02, 0x8f, 0x61, 0x2e, 0xfe, 0x8f, 0x94, 0xff, 0xea, 0xb0, 0x21, 0xc4, 0xf4, 0x1b, 0xd8, 0x29, 0x6c, 0x1c, + 0xa5, 0x39, 0x01, 0xaf, 0xc5, 0xf6, 0x39, 0xce, 0xc8, 0xb4, 0x99, 0xfb, 0x80, 0x7b, 0xa6, 0x95, 0xc6, 0xad, 0x46, + 0xc7, 0x19, 0x1e, 0x6f, 0x27, 0xc5, 0x66, 0xae, 0xcd, 0x3c, 0xcd, 0xe0, 0x7c, 0xaf, 0x46, 0xe1, 0xca, 0x2f, 0xb7, + 0x93, 0xc2, 0xf2, 0x0e, 0xb8, 0xcd, 0x31, 0x16, 0x4d, 0x8a, 0x73, 0x3c, 0x6f, 0xbe, 0xc4, 0xf3, 0xe6, 0xbb, 0x32, + 0xa3, 0xb1, 0xc4, 0x02, 0x82, 0xf7, 0x41, 0x22, 0x9e, 0x57, 0xc9, 0x63, 0x2c, 0x1a, 0xa6, 0x3c, 0x9e, 0x37, 0xaa, + 0xd2, 0xcd, 0x25, 0x16, 0x0d, 0x53, 0xba, 0xf1, 0x0e, 0xcf, 0x1b, 0x2f, 0xff, 0xc5, 0xa4, 0xa3, 0x14, 0xd0, 0x65, + 0x81, 0x56, 0x99, 0x1d, 0xe2, 0xf5, 0xaf, 0x6f, 0xde, 0xb6, 0x3f, 0x76, 0x8e, 0xa7, 0xd8, 0xaf, 0x5f, 0x66, 0x70, + 0x2c, 0xd3, 0x31, 0x6b, 0x02, 0x44, 0x33, 0xdc, 0x39, 0x9e, 0xe1, 0xce, 0x71, 0xe6, 0x9a, 0xda, 0xcc, 0x1b, 0xe4, + 0x56, 0x87, 0x50, 0xd4, 0x51, 0x1a, 0xc2, 0xc7, 0x4f, 0x36, 0x9d, 0xa2, 0x1a, 0x28, 0xd1, 0xf1, 0xb4, 0x06, 0x2a, + 0xf8, 0x5e, 0xd6, 0xbe, 0xab, 0x7a, 0x15, 0x06, 0x59, 0x28, 0xa1, 0x70, 0xcd, 0x0d, 0x78, 0x6a, 0x29, 0x06, 0x32, + 0x61, 0x8a, 0x05, 0xca, 0x37, 0x40, 0x61, 0x94, 0x27, 0x66, 0xe8, 0xc1, 0x74, 0x4c, 0xe2, 0xff, 0xcf, 0x93, 0x29, + 0x87, 0x5e, 0x6e, 0x99, 0x9d, 0xe9, 0xb9, 0xc9, 0x84, 0xc3, 0x07, 0x1e, 0xeb, 0xff, 0xda, 0x81, 0x62, 0x03, 0x52, + 0xfc, 0x7f, 0xe9, 0xe8, 0x42, 0x30, 0x42, 0x56, 0x94, 0x16, 0x0e, 0xf1, 0xbf, 0x3d, 0xac, 0xa0, 0xfb, 0x62, 0xa7, + 0xfb, 0xc2, 0x74, 0x1f, 0x36, 0x6d, 0x54, 0x39, 0x69, 0x55, 0xc9, 0x92, 0xff, 0x3a, 0xdd, 0xda, 0x01, 0x8d, 0xa8, + 0xd1, 0xb3, 0x69, 0xd8, 0xe0, 0x61, 0x3b, 0xdd, 0x83, 0xcc, 0x1b, 0x6e, 0x5f, 0x2b, 0x85, 0xc3, 0x37, 0xb8, 0x53, + 0xbd, 0x6a, 0x81, 0xf7, 0xa6, 0x32, 0xfa, 0xca, 0x38, 0xb4, 0x1c, 0xa4, 0xdb, 0xa6, 0xdc, 0xc6, 0x58, 0x3a, 0xe9, + 0x62, 0xe3, 0x8a, 0x08, 0x95, 0x6e, 0xaf, 0x40, 0x29, 0x3e, 0xd1, 0x4d, 0x66, 0xbe, 0x2e, 0x75, 0x62, 0x2e, 0xa1, + 0x1a, 0xe6, 0xf3, 0xee, 0x4a, 0x27, 0x5a, 0x2e, 0x6c, 0xde, 0xdd, 0x25, 0xf4, 0x09, 0x1a, 0xd6, 0x46, 0x60, 0xb7, + 0xcf, 0x9d, 0x1d, 0x64, 0x70, 0x08, 0x86, 0x07, 0x90, 0x23, 0x2d, 0xb6, 0x0f, 0x6c, 0x5a, 0xc3, 0xae, 0x8b, 0x66, + 0x99, 0x68, 0x5b, 0x6d, 0x9a, 0x5c, 0xbb, 0x87, 0xf9, 0x22, 0xe4, 0x29, 0x44, 0x61, 0xf5, 0xe3, 0x7b, 0xd8, 0x8d, + 0x9b, 0x1a, 0x23, 0x51, 0x57, 0x32, 0x95, 0xd0, 0x4f, 0x6e, 0x31, 0x4b, 0xee, 0x8c, 0x17, 0xa3, 0x32, 0xfe, 0x3e, + 0x26, 0x2e, 0x7f, 0x54, 0x49, 0x72, 0x60, 0xd9, 0xdf, 0x60, 0xc9, 0x2d, 0x98, 0x27, 0x96, 0xd5, 0x24, 0xd6, 0xc9, + 0x5d, 0xb0, 0x88, 0xd2, 0x34, 0xb2, 0x31, 0x0c, 0xa8, 0x69, 0xc6, 0xaa, 0x07, 0x0f, 0x21, 0xd0, 0x43, 0xbf, 0x2c, + 0xa5, 0x5d, 0x67, 0x69, 0xad, 0x7b, 0x6d, 0xba, 0xdf, 0x1e, 0x50, 0x35, 0x8d, 0xcf, 0x01, 0xd7, 0xf4, 0xaf, 0x26, + 0x91, 0x8c, 0xd8, 0x3f, 0x9c, 0x15, 0x8f, 0x97, 0x85, 0xc1, 0x34, 0xd1, 0xd7, 0x49, 0xb6, 0x68, 0x83, 0xa9, 0x5e, + 0xb6, 0xe8, 0xdc, 0x62, 0xf7, 0x7d, 0x67, 0xbf, 0xef, 0xb0, 0xe8, 0x33, 0x93, 0x91, 0x32, 0x53, 0xcc, 0x7f, 0xdf, + 0xd9, 0xef, 0x3b, 0xbc, 0x3b, 0x98, 0x6b, 0x7f, 0xa1, 0x58, 0xb2, 0x33, 0x5c, 0x82, 0x09, 0x79, 0xc0, 0xdd, 0xd4, + 0xb2, 0x4c, 0x10, 0xd8, 0x5a, 0x02, 0xc4, 0xf9, 0x7c, 0x11, 0x57, 0xbc, 0x1a, 0x02, 0xee, 0xd3, 0xbb, 0xb6, 0x57, + 0xa9, 0xc0, 0x63, 0x82, 0x46, 0xc4, 0xc4, 0xb6, 0x31, 0x2f, 0x8d, 0x01, 0x97, 0x47, 0x74, 0xa9, 0x27, 0x49, 0x80, + 0x57, 0x35, 0x2a, 0x6f, 0x53, 0xa4, 0xfc, 0x22, 0x41, 0x8e, 0x2f, 0xf6, 0x88, 0x2a, 0x06, 0xb0, 0x2a, 0x4b, 0xfa, + 0x04, 0x52, 0xcf, 0x0f, 0x26, 0xfa, 0xcb, 0x36, 0xf2, 0xd8, 0x37, 0x77, 0x3f, 0x33, 0x3d, 0x2b, 0xe4, 0x72, 0x3a, + 0x03, 0x1f, 0x5a, 0x60, 0x19, 0x0a, 0x53, 0xaf, 0xb2, 0xf5, 0xaf, 0x49, 0x6e, 0x02, 0x28, 0x9c, 0x6e, 0xca, 0x84, + 0x66, 0x7a, 0x49, 0x73, 0x63, 0x49, 0xca, 0xc5, 0xf4, 0x91, 0xbc, 0xfd, 0x19, 0xb0, 0x9b, 0x12, 0xdd, 0xd8, 0x93, + 0xf7, 0x06, 0x76, 0x00, 0xce, 0x08, 0xdb, 0x57, 0xf1, 0xa1, 0x02, 0x9d, 0x3f, 0xce, 0x09, 0xdb, 0x57, 0xf5, 0x09, + 0xb3, 0xd9, 0x33, 0xb2, 0x35, 0xdc, 0x7e, 0x9c, 0x35, 0x72, 0x74, 0xd2, 0x49, 0xf3, 0x9e, 0x27, 0x06, 0x16, 0xa0, + 0x01, 0x70, 0x77, 0xb6, 0x67, 0x79, 0x77, 0x43, 0x40, 0xef, 0x92, 0x49, 0x7b, 0x5d, 0x6e, 0x52, 0xd6, 0xeb, 0x4e, + 0x45, 0x05, 0x0b, 0x3c, 0x0b, 0xf6, 0x02, 0xb5, 0x5f, 0x7b, 0x28, 0xce, 0xe3, 0x6c, 0xdb, 0xf4, 0xbc, 0xec, 0xbb, + 0xb7, 0x67, 0x91, 0xb1, 0x4d, 0x7b, 0xb3, 0x87, 0x48, 0x58, 0x4e, 0x58, 0x07, 0x9c, 0x70, 0x55, 0x3b, 0x20, 0x40, + 0x1f, 0x03, 0x91, 0x1b, 0x4b, 0xb2, 0xda, 0x54, 0x46, 0xf7, 0x81, 0xdf, 0x2d, 0x25, 0xd2, 0x8d, 0xb6, 0x24, 0x98, + 0x3e, 0xc1, 0xa8, 0xe9, 0xcc, 0x33, 0xd1, 0xb5, 0x17, 0x90, 0xb7, 0x45, 0x5b, 0xff, 0x1e, 0x33, 0x36, 0xdb, 0xc3, + 0xc4, 0x50, 0x06, 0x31, 0xd0, 0xfb, 0x88, 0xf7, 0x1a, 0x8d, 0x0c, 0x81, 0x42, 0x26, 0x1b, 0x62, 0x99, 0x78, 0x2d, + 0xfa, 0xd1, 0x91, 0x81, 0x47, 0x95, 0x80, 0x30, 0x05, 0x21, 0x24, 0xec, 0xda, 0x20, 0x6c, 0xb8, 0x5c, 0xb5, 0x5c, + 0xd8, 0x48, 0xb5, 0xa1, 0x83, 0xff, 0x57, 0xb8, 0x6c, 0xf5, 0xcc, 0x72, 0x51, 0x0c, 0x6e, 0xe6, 0x06, 0x2c, 0x12, + 0xa4, 0x47, 0x9b, 0xed, 0xa1, 0xb8, 0x3f, 0x17, 0x9b, 0x0d, 0x01, 0x89, 0x39, 0x4c, 0x50, 0x34, 0x9c, 0x1b, 0x63, + 0xac, 0x92, 0x4a, 0xcb, 0x5a, 0x93, 0x98, 0x83, 0x80, 0xd1, 0xe1, 0xba, 0xaf, 0x6e, 0x53, 0x86, 0xef, 0x52, 0x81, + 0x6f, 0xc0, 0x93, 0x26, 0x95, 0xd8, 0x3d, 0x5e, 0x50, 0x6c, 0x88, 0xee, 0x79, 0xf6, 0xb6, 0x80, 0x75, 0x36, 0x7b, + 0x44, 0x04, 0xbf, 0xab, 0x5f, 0x6d, 0xf0, 0xdd, 0xc2, 0x2f, 0xc1, 0xfa, 0x39, 0x38, 0x49, 0xb1, 0x68, 0xc8, 0x66, + 0xe1, 0x8e, 0x0c, 0x28, 0x57, 0xf1, 0xcb, 0x61, 0xea, 0x4e, 0x31, 0x5c, 0xfb, 0x78, 0x89, 0xdf, 0x6d, 0xb5, 0xdb, + 0x50, 0x65, 0x71, 0xbb, 0x37, 0x45, 0x43, 0x56, 0x4d, 0xef, 0xc9, 0xdc, 0x4a, 0xa9, 0x7f, 0xbd, 0xc3, 0xad, 0x9d, + 0xf6, 0xfd, 0x34, 0xdf, 0x78, 0x74, 0xae, 0x9a, 0xf6, 0xa9, 0xb5, 0x22, 0x38, 0xf8, 0xd9, 0xc2, 0xcd, 0x9d, 0x01, + 0x07, 0xf0, 0xf3, 0x77, 0x34, 0xaf, 0x32, 0x88, 0x4e, 0x6f, 0x35, 0xe3, 0xeb, 0xf8, 0xcf, 0x71, 0x23, 0xee, 0xa7, + 0x7f, 0x26, 0x7f, 0x8e, 0x1b, 0xa8, 0x8f, 0xe2, 0xc5, 0xed, 0x9a, 0xcd, 0xd7, 0x10, 0x6c, 0xed, 0xde, 0x09, 0x7e, + 0x1d, 0x96, 0xe4, 0x9a, 0xe6, 0x3c, 0x5b, 0xbb, 0xc7, 0xf9, 0xd6, 0x5c, 0xcc, 0x58, 0xc1, 0xf5, 0xda, 0xbc, 0x37, + 0xb5, 0x8e, 0xe5, 0x28, 0x87, 0xc0, 0xc2, 0xf1, 0x41, 0xb3, 0x3f, 0x68, 0x35, 0x1f, 0x0c, 0xed, 0xbf, 0x26, 0xc2, + 0x3d, 0xaa, 0x45, 0x6c, 0x7b, 0xb8, 0xb5, 0xf5, 0x63, 0x30, 0xec, 0x80, 0x50, 0xe0, 0x20, 0x97, 0xbe, 0xca, 0x90, + 0xf5, 0x3d, 0x59, 0xaf, 0x99, 0x8b, 0x66, 0xed, 0x34, 0xf8, 0x65, 0x6c, 0xa6, 0xe3, 0x76, 0xd2, 0xe9, 0x79, 0x31, + 0x96, 0x34, 0x20, 0xd2, 0x34, 0x66, 0x10, 0x48, 0x6a, 0x65, 0x38, 0xac, 0xc5, 0x6d, 0x94, 0x56, 0xf7, 0x47, 0x90, + 0xf2, 0x5d, 0x94, 0xf2, 0x13, 0x02, 0x01, 0xb4, 0x2d, 0x73, 0x54, 0x36, 0xe4, 0x7d, 0x97, 0x9e, 0x1a, 0x67, 0x86, + 0x06, 0x5f, 0xaf, 0x5b, 0x81, 0x6b, 0x52, 0x51, 0x1f, 0xe6, 0x6a, 0x03, 0x61, 0xb8, 0x40, 0xd7, 0xac, 0x88, 0xe8, + 0x87, 0xae, 0xf2, 0xf0, 0x36, 0x31, 0x96, 0x04, 0x9c, 0xf4, 0xfb, 0xa2, 0x5f, 0x90, 0xab, 0x87, 0x31, 0xf8, 0x98, + 0x61, 0x3e, 0xd0, 0x83, 0x62, 0x38, 0x44, 0xa9, 0x73, 0x3a, 0x4b, 0x4d, 0xc4, 0x95, 0xc0, 0x2f, 0xb9, 0x00, 0xbf, + 0x64, 0x85, 0xd8, 0xa0, 0x18, 0x92, 0xa7, 0x59, 0x2c, 0xc1, 0x29, 0x7f, 0x8f, 0xcf, 0xe3, 0x8b, 0xd0, 0xc0, 0xd4, + 0x0c, 0xcb, 0x5c, 0x64, 0x83, 0xc5, 0x9c, 0xb5, 0x04, 0x82, 0x9b, 0x01, 0x77, 0xa9, 0x0d, 0x89, 0xc6, 0x1a, 0x28, + 0xba, 0x8d, 0x42, 0x33, 0xa3, 0x27, 0x3b, 0x6d, 0x0c, 0x22, 0x87, 0x17, 0xe6, 0x1a, 0xc6, 0x22, 0x90, 0xb9, 0x5c, + 0xf5, 0xd8, 0x5f, 0x7e, 0xd8, 0xac, 0x30, 0x78, 0x45, 0xa6, 0x43, 0x77, 0x1c, 0x33, 0xbe, 0xca, 0x13, 0xc7, 0x10, + 0x64, 0x62, 0xa9, 0x74, 0xc3, 0x31, 0x71, 0x25, 0x7d, 0x26, 0x86, 0x6c, 0x37, 0x3c, 0x33, 0x17, 0xba, 0xd9, 0xfe, + 0xee, 0xdc, 0xce, 0x39, 0xe1, 0x46, 0x2b, 0x69, 0xb4, 0x51, 0xcf, 0x0c, 0x55, 0x75, 0xc1, 0xfc, 0x1e, 0x3a, 0x2d, + 0x2d, 0x76, 0xae, 0xde, 0xbd, 0xf0, 0xa5, 0xbc, 0x32, 0xfe, 0x16, 0xab, 0x42, 0x2b, 0x32, 0xdc, 0x6e, 0x21, 0x6f, + 0xce, 0xf4, 0xd0, 0x2b, 0x72, 0xa1, 0x3a, 0xfc, 0x45, 0x3d, 0x61, 0x1e, 0xcf, 0x8c, 0x1a, 0xc2, 0xa3, 0xdf, 0xeb, + 0x0c, 0x94, 0x7f, 0x30, 0x31, 0x99, 0xb3, 0xe4, 0x86, 0x16, 0x22, 0xfe, 0xfe, 0x85, 0x30, 0xb1, 0xaa, 0x0e, 0x60, + 0x20, 0x07, 0xa6, 0xe2, 0x01, 0xdc, 0x9a, 0xf0, 0x09, 0x67, 0xe3, 0xf4, 0x20, 0xfa, 0xbe, 0x21, 0x1a, 0xdf, 0x47, + 0xdf, 0x83, 0xbb, 0xb3, 0x7b, 0xa9, 0xb1, 0x8c, 0x0b, 0xe1, 0xef, 0xb1, 0x1e, 0x96, 0x2a, 0x65, 0xac, 0xbd, 0x6e, + 0x39, 0xbc, 0x90, 0x7a, 0x98, 0xc5, 0x0f, 0x1d, 0xb1, 0xb6, 0x29, 0x58, 0x87, 0x94, 0x14, 0x9e, 0x5d, 0x31, 0xb7, + 0x5a, 0xcc, 0x5d, 0x6a, 0x09, 0x7f, 0x7d, 0xf5, 0xb0, 0x54, 0x41, 0xc3, 0x41, 0xe8, 0x4a, 0x5b, 0x48, 0x80, 0x81, + 0x4b, 0xe9, 0xd3, 0xe9, 0xce, 0x24, 0xf2, 0x31, 0x8b, 0xe1, 0xdd, 0x83, 0xe0, 0xa2, 0x93, 0x6d, 0x85, 0x55, 0x81, + 0xcb, 0x95, 0x2a, 0xea, 0xa5, 0x24, 0x10, 0x80, 0xbe, 0xf4, 0x1e, 0x94, 0x97, 0x45, 0xaf, 0xd1, 0x90, 0xa0, 0x85, + 0xa5, 0xe6, 0x5a, 0x15, 0xd3, 0xc3, 0xf0, 0x85, 0xc1, 0xe0, 0xc3, 0x3b, 0xa4, 0x6d, 0x3d, 0xf3, 0x49, 0x09, 0xb5, + 0x3b, 0xe8, 0x10, 0xac, 0xb2, 0x83, 0xf2, 0x6f, 0x62, 0x8a, 0x6c, 0xfe, 0x80, 0x7d, 0x47, 0x5d, 0x87, 0x43, 0x57, + 0xb0, 0xea, 0xa5, 0x8c, 0x82, 0x01, 0x2b, 0xa7, 0x40, 0xed, 0x9d, 0x64, 0x34, 0x9b, 0x31, 0x50, 0xf7, 0xdb, 0xa2, + 0x81, 0xd1, 0x59, 0xdd, 0x6f, 0xc8, 0x38, 0xfb, 0x08, 0xe3, 0xec, 0xa3, 0xc0, 0x8b, 0x45, 0x92, 0x9f, 0x64, 0xac, + 0x71, 0xac, 0x9a, 0x02, 0x9d, 0x74, 0x80, 0x3b, 0x03, 0x07, 0x1e, 0xb0, 0x45, 0x39, 0x3a, 0xa2, 0xce, 0xe2, 0x9e, + 0x36, 0x32, 0xef, 0xed, 0x09, 0xb5, 0x8b, 0x58, 0xe0, 0x66, 0xcd, 0x4c, 0x0b, 0x5a, 0x2b, 0x8c, 0xf3, 0x78, 0xc0, + 0xdb, 0x3c, 0xab, 0xc5, 0x4f, 0xd8, 0xb2, 0xa6, 0xaa, 0xdf, 0x40, 0x73, 0x54, 0x0b, 0x72, 0xf3, 0xc4, 0x78, 0xab, + 0x92, 0x41, 0x14, 0x0d, 0x2d, 0xa7, 0x42, 0x0c, 0xc9, 0x18, 0xb4, 0x86, 0xc1, 0xad, 0xf6, 0x7a, 0xcd, 0x3d, 0xe2, + 0x8b, 0x9a, 0xb7, 0x9a, 0xb9, 0x05, 0xc8, 0x8a, 0x38, 0x2a, 0xef, 0x4d, 0x22, 0xf0, 0xbe, 0x2d, 0x23, 0xa4, 0xad, + 0x06, 0xf6, 0x19, 0xc9, 0x52, 0xb1, 0xf9, 0x96, 0x4e, 0x87, 0x69, 0x64, 0x47, 0x14, 0xe1, 0x8f, 0x25, 0x24, 0xe1, + 0x2a, 0xe9, 0xa3, 0xca, 0xe4, 0x82, 0xa9, 0x94, 0xe3, 0x8f, 0x85, 0x94, 0xfa, 0xda, 0x7e, 0x49, 0x5c, 0xdd, 0xc9, + 0x08, 0xfc, 0x71, 0xca, 0xf4, 0x5b, 0x5a, 0x4c, 0x19, 0xf8, 0x15, 0xf9, 0xdb, 0xb1, 0x94, 0x92, 0xab, 0x27, 0x22, + 0x1e, 0x50, 0x0c, 0x6f, 0xa0, 0x0e, 0xb1, 0x36, 0x21, 0x50, 0x4a, 0x5c, 0x84, 0x0b, 0xa2, 0xd7, 0x85, 0xbc, 0xbd, + 0x8b, 0x0b, 0xec, 0x1c, 0x00, 0x4b, 0xa7, 0x49, 0x80, 0x7f, 0xf9, 0x98, 0x8f, 0xd5, 0x98, 0x53, 0xa3, 0xeb, 0x77, + 0xbf, 0x93, 0x8f, 0x40, 0x6f, 0x4b, 0x47, 0xc1, 0x41, 0x6b, 0x08, 0xb9, 0x70, 0x17, 0x06, 0x17, 0x5f, 0x61, 0xed, + 0xa2, 0x30, 0xde, 0x58, 0x00, 0xbd, 0xf7, 0x19, 0x58, 0xb0, 0x61, 0x8e, 0x29, 0x3c, 0x20, 0x3b, 0x65, 0x3a, 0x88, + 0x0a, 0xf2, 0xa4, 0x7c, 0x22, 0xb4, 0x56, 0xfb, 0x0d, 0x9b, 0xc0, 0x1d, 0x46, 0xf2, 0xf5, 0xc2, 0x89, 0x03, 0x0f, + 0xc8, 0x34, 0x99, 0x6d, 0xf6, 0xb5, 0x8f, 0x3c, 0xf2, 0x6a, 0x12, 0xef, 0x6b, 0x29, 0xcc, 0x37, 0x2b, 0xba, 0xc1, + 0x10, 0x8a, 0x22, 0xec, 0xf7, 0x46, 0xc5, 0x14, 0x55, 0x06, 0x6d, 0xd0, 0xb0, 0xbc, 0x11, 0x3f, 0xc1, 0x19, 0x43, + 0xeb, 0x85, 0xec, 0x1d, 0x9d, 0x75, 0x38, 0x73, 0x98, 0x31, 0x23, 0x30, 0x2a, 0x2d, 0x0b, 0x3a, 0x05, 0x47, 0xe7, + 0xea, 0x83, 0xa8, 0xb8, 0x3a, 0x56, 0x00, 0x9e, 0x64, 0x06, 0xff, 0xe4, 0xdb, 0x60, 0x3d, 0x6c, 0xd5, 0x0c, 0x53, + 0x7f, 0xd2, 0xbb, 0xae, 0xe5, 0xab, 0x10, 0x47, 0xda, 0x18, 0x42, 0xeb, 0xdc, 0xde, 0x01, 0x8a, 0xb8, 0xa0, 0x17, + 0xa9, 0xc6, 0x1f, 0xd5, 0x72, 0x64, 0xd6, 0xd7, 0xb8, 0x8e, 0x69, 0x83, 0x28, 0xd6, 0x5d, 0x13, 0x7f, 0xac, 0x5e, + 0x64, 0x55, 0x29, 0xb0, 0xce, 0xa0, 0xfc, 0x50, 0xe5, 0x65, 0x43, 0x2a, 0xc9, 0x95, 0xe9, 0x54, 0x9a, 0x4e, 0x2b, + 0x84, 0x72, 0xe9, 0x49, 0x79, 0xff, 0x0a, 0x21, 0x0c, 0x4c, 0x99, 0x3d, 0x58, 0xa5, 0x76, 0xb0, 0x0a, 0x5e, 0xbd, + 0xd8, 0xc2, 0x2a, 0x09, 0xc7, 0x73, 0x89, 0x46, 0x45, 0x85, 0x43, 0x86, 0xf4, 0x85, 0x58, 0x04, 0x09, 0x80, 0x45, + 0x6f, 0x32, 0x97, 0xf7, 0x2d, 0x1c, 0x0a, 0x7b, 0x92, 0x49, 0x38, 0xdd, 0x84, 0xe6, 0xf0, 0x54, 0xaf, 0xea, 0x7b, + 0x84, 0x98, 0x99, 0xf8, 0x4f, 0xf0, 0x44, 0xf3, 0xb7, 0x9f, 0x86, 0x75, 0x16, 0xe4, 0xe9, 0xbf, 0x44, 0x49, 0x68, + 0xec, 0x3f, 0xc7, 0x43, 0x87, 0x84, 0xe1, 0xc0, 0xb7, 0x47, 0x58, 0xe1, 0xe0, 0x4e, 0x11, 0x9f, 0xc1, 0x1d, 0x3e, + 0xd6, 0xa1, 0x07, 0x80, 0x25, 0x14, 0x87, 0x20, 0xdf, 0x42, 0x31, 0x33, 0x6c, 0x4d, 0x56, 0xe1, 0x05, 0x2e, 0x58, + 0x2d, 0x94, 0xf7, 0xb7, 0x2d, 0x2f, 0xa5, 0xd5, 0x2e, 0x79, 0x8d, 0x39, 0x50, 0xf9, 0x19, 0x5e, 0xf8, 0x0a, 0xf3, + 0x76, 0xb4, 0xfb, 0xc2, 0x1f, 0x1d, 0xd0, 0x53, 0x08, 0x18, 0xe9, 0x7e, 0x6f, 0x08, 0xf7, 0x14, 0xbd, 0xcc, 0xc5, + 0x61, 0xdb, 0x41, 0xf7, 0x02, 0x73, 0x75, 0x5d, 0x65, 0x2d, 0xc0, 0x14, 0x1a, 0x1c, 0x54, 0xe1, 0x8c, 0xc0, 0x5c, + 0xbd, 0x28, 0x0b, 0x2e, 0x40, 0xbc, 0xef, 0x0b, 0x93, 0x53, 0x46, 0x03, 0xf8, 0x39, 0x2b, 0x1f, 0x9d, 0xea, 0x73, + 0x70, 0x19, 0x37, 0x6c, 0xe2, 0x5b, 0xe1, 0x53, 0x81, 0x95, 0xb4, 0xc6, 0xa1, 0x11, 0x1d, 0xd3, 0x05, 0x98, 0x6d, + 0x00, 0x05, 0x77, 0xe7, 0xc3, 0xd6, 0x42, 0x05, 0xcf, 0xe3, 0xd6, 0x5e, 0xb3, 0x26, 0xc4, 0x99, 0x34, 0x05, 0x77, + 0xdb, 0x45, 0x11, 0x98, 0xdf, 0xfe, 0x5b, 0x61, 0x91, 0x60, 0x40, 0xa5, 0x26, 0x09, 0xc2, 0x13, 0x94, 0x46, 0xba, + 0x95, 0x9b, 0x09, 0xa4, 0x13, 0x11, 0xde, 0x30, 0xbf, 0xd9, 0x3a, 0x5f, 0x1d, 0x35, 0x10, 0x15, 0x35, 0x50, 0x01, + 0x35, 0x90, 0xf5, 0xed, 0x5f, 0xc0, 0x42, 0xd8, 0x08, 0x55, 0x22, 0x08, 0x88, 0xb0, 0xd0, 0x86, 0x0f, 0x28, 0x92, + 0x10, 0xf2, 0x06, 0x50, 0x31, 0x25, 0xcf, 0xc0, 0x68, 0x1c, 0x5e, 0xef, 0x01, 0xf7, 0x4b, 0xcb, 0x30, 0x78, 0x4e, + 0xc1, 0xe4, 0xbf, 0xf4, 0xf9, 0x50, 0xbd, 0x5c, 0x1d, 0x84, 0xf0, 0x5b, 0x88, 0x15, 0xe1, 0xf8, 0x8b, 0x9f, 0x80, + 0x6c, 0x2a, 0x2c, 0x8f, 0x8e, 0x24, 0x08, 0xfc, 0x10, 0x45, 0x38, 0xe0, 0x19, 0x9e, 0x65, 0x5b, 0x44, 0xcf, 0xcf, + 0x4a, 0x55, 0xb3, 0x92, 0xc1, 0xac, 0x0a, 0x4f, 0xe3, 0xe8, 0x86, 0x30, 0x10, 0x5c, 0xa8, 0xdd, 0x37, 0x08, 0x81, + 0xb2, 0xe5, 0xc6, 0xd0, 0xa5, 0xa7, 0x60, 0x3e, 0x1a, 0x47, 0x6f, 0x18, 0x3c, 0xf2, 0x6b, 0xc2, 0xed, 0x30, 0xcd, + 0x32, 0x6d, 0x98, 0xc7, 0x46, 0xe0, 0xa4, 0x4e, 0x51, 0xf2, 0x49, 0x72, 0x11, 0x47, 0xcd, 0xab, 0x08, 0x35, 0xe0, + 0xdf, 0x06, 0x47, 0x3d, 0x9a, 0xd0, 0xf1, 0xd8, 0x07, 0xbf, 0xc9, 0x88, 0xd9, 0x64, 0xeb, 0xb5, 0xa8, 0x08, 0x7a, + 0x62, 0x37, 0x18, 0xb0, 0x12, 0x6f, 0x81, 0x7d, 0xb0, 0x1c, 0x2c, 0xf9, 0x59, 0xc4, 0xca, 0x9f, 0x52, 0x18, 0xac, + 0x9e, 0x33, 0x84, 0x70, 0x16, 0x84, 0x8d, 0xfe, 0xcf, 0x67, 0x1a, 0xae, 0x9f, 0x9f, 0xaf, 0x63, 0x44, 0xa4, 0x0f, + 0x22, 0x57, 0x63, 0x47, 0x44, 0x10, 0xb6, 0x4c, 0x0f, 0x5c, 0x99, 0xef, 0xbc, 0x75, 0xf5, 0xd0, 0x86, 0x8b, 0x03, + 0x03, 0x6a, 0x14, 0x18, 0xad, 0xe0, 0x9c, 0x94, 0x03, 0x07, 0x25, 0x84, 0x66, 0x45, 0x3c, 0x23, 0x57, 0x10, 0x09, + 0x2f, 0x43, 0x3d, 0x30, 0x2c, 0x08, 0x24, 0xa8, 0x19, 0x48, 0x50, 0x99, 0xaf, 0x3d, 0x86, 0x59, 0xe7, 0x66, 0xb6, + 0x33, 0xd4, 0x73, 0x41, 0x7e, 0x7e, 0xd2, 0xf1, 0x18, 0x58, 0xda, 0xa3, 0xa3, 0x02, 0x22, 0x88, 0x01, 0x05, 0x2f, + 0x25, 0xc0, 0x40, 0x03, 0x5e, 0x6c, 0x69, 0xc0, 0x17, 0xda, 0x78, 0x1d, 0x18, 0x5b, 0x9f, 0x32, 0xc8, 0xc5, 0x3f, + 0xd5, 0x9e, 0x26, 0x84, 0x1c, 0xb6, 0xfa, 0x3a, 0xdd, 0x8d, 0x90, 0xd8, 0xff, 0xa0, 0x4d, 0xa0, 0x31, 0x47, 0xba, + 0xab, 0x8d, 0xf9, 0xa9, 0xa6, 0x47, 0xac, 0x26, 0x21, 0x5d, 0x90, 0x2e, 0xcf, 0xa7, 0xfd, 0x03, 0x57, 0xac, 0xd2, + 0xc8, 0xc1, 0x05, 0xe8, 0xb3, 0x01, 0x01, 0x0a, 0x54, 0x9a, 0x4a, 0xd0, 0x22, 0x2e, 0x92, 0x92, 0x0d, 0xc3, 0x0c, + 0xc2, 0x14, 0x56, 0x2b, 0x41, 0xb7, 0xd6, 0x00, 0x78, 0x67, 0x66, 0xff, 0x94, 0x3e, 0xd8, 0x74, 0xe3, 0xcd, 0x23, + 0x80, 0x80, 0x1c, 0xb6, 0x4b, 0x76, 0x5d, 0x6c, 0x55, 0x66, 0x61, 0x2d, 0x63, 0x2b, 0xb7, 0xeb, 0x31, 0xf6, 0xb3, + 0xd8, 0xe5, 0x13, 0x20, 0x44, 0x6d, 0xc9, 0x34, 0x62, 0x09, 0x43, 0xd6, 0xb5, 0x21, 0x1b, 0x6d, 0x28, 0x3c, 0x95, + 0xc8, 0x81, 0x4b, 0x34, 0x41, 0xf2, 0x1d, 0x97, 0xe0, 0x10, 0x5e, 0x78, 0x84, 0xff, 0x02, 0x2c, 0x52, 0x81, 0x19, + 0x96, 0xeb, 0x35, 0xd4, 0xf3, 0x78, 0x9f, 0x6d, 0x07, 0x27, 0x95, 0x5b, 0x63, 0x97, 0x76, 0xe2, 0x71, 0xd9, 0x84, + 0xc4, 0x19, 0xf4, 0xeb, 0x2b, 0xa2, 0xfe, 0x61, 0x3b, 0x7d, 0xe2, 0xdf, 0x2b, 0x73, 0x3b, 0x10, 0x1b, 0xd6, 0x1b, + 0xac, 0x3e, 0x80, 0x96, 0x3f, 0xca, 0xfc, 0x43, 0x65, 0x81, 0x49, 0x82, 0xda, 0x5e, 0xc4, 0x1e, 0xeb, 0x21, 0x46, + 0x6a, 0x8b, 0xbb, 0x47, 0x88, 0x7f, 0xb4, 0x13, 0xc5, 0x80, 0x27, 0x15, 0xff, 0x1c, 0xa3, 0x1e, 0x84, 0xa2, 0xb6, + 0x1e, 0x36, 0x40, 0x69, 0x57, 0x9b, 0x4a, 0x8c, 0x0c, 0x09, 0xe4, 0x1b, 0x17, 0x5e, 0xd0, 0x9c, 0x44, 0x0a, 0xe4, + 0xe4, 0xaa, 0x8b, 0xf7, 0xd9, 0x96, 0x30, 0xd7, 0xdb, 0xc1, 0x31, 0x73, 0xb5, 0x91, 0x15, 0xf1, 0xcf, 0xc0, 0xce, + 0x70, 0x23, 0x59, 0x3a, 0xf0, 0xa9, 0x1a, 0xf8, 0xfc, 0x9a, 0x1b, 0x8a, 0xa2, 0x50, 0xff, 0x67, 0xfb, 0xc8, 0x1c, + 0xfc, 0x4e, 0x03, 0xf1, 0x31, 0x73, 0x3a, 0x92, 0xad, 0x50, 0x6b, 0xce, 0x8e, 0x97, 0x6d, 0x47, 0x18, 0x14, 0x36, + 0x7a, 0x5f, 0x85, 0xac, 0x62, 0x6f, 0xa7, 0x22, 0x98, 0xd3, 0x8d, 0xaa, 0x9c, 0x53, 0xb9, 0x65, 0x54, 0x4b, 0x4d, + 0x03, 0x44, 0xb8, 0xf2, 0x89, 0xe4, 0x79, 0x66, 0xc2, 0x3f, 0x18, 0x8c, 0xab, 0x47, 0x0a, 0x7f, 0xbe, 0x2f, 0x76, + 0xc8, 0x6e, 0x74, 0xb8, 0xad, 0xa0, 0x79, 0xa1, 0x82, 0x07, 0x1c, 0x95, 0x2c, 0x21, 0x52, 0xe4, 0xea, 0x50, 0xd5, + 0x4c, 0xd9, 0x3e, 0x46, 0x08, 0x21, 0xed, 0x71, 0xd6, 0x0d, 0xad, 0x1e, 0x7a, 0xa4, 0x72, 0x9a, 0xdc, 0xa1, 0xb9, + 0x2e, 0x40, 0x85, 0x11, 0x48, 0x57, 0x9f, 0xd9, 0x5d, 0x2a, 0x21, 0x7a, 0xf9, 0xc6, 0x85, 0x30, 0x76, 0x56, 0x96, + 0xb8, 0x30, 0xa3, 0xb6, 0x61, 0x74, 0xdd, 0xc6, 0x70, 0x36, 0x30, 0x66, 0x1a, 0x94, 0xb4, 0x20, 0xd4, 0x75, 0x8f, + 0x5e, 0x66, 0x26, 0xd0, 0x63, 0x4e, 0x68, 0x83, 0xe1, 0x19, 0xd1, 0x60, 0xd9, 0x54, 0x80, 0x05, 0xdf, 0xaa, 0x48, + 0xad, 0xcd, 0x26, 0x8b, 0x3f, 0xe8, 0xd8, 0x3c, 0xed, 0x97, 0x57, 0xcc, 0x73, 0xe1, 0xa8, 0xdb, 0x6f, 0x99, 0x8f, + 0x47, 0xf7, 0xf4, 0xf5, 0xf5, 0x8b, 0x9f, 0x5f, 0xbd, 0x5c, 0xaf, 0xdb, 0xac, 0xd9, 0x3e, 0xc3, 0x3f, 0xe8, 0x32, + 0x1e, 0x6c, 0x19, 0x05, 0xe8, 0xe8, 0xe8, 0x90, 0x1b, 0x17, 0x9e, 0xcf, 0x7c, 0x01, 0x71, 0x83, 0xf4, 0x10, 0xe7, + 0x45, 0x19, 0x13, 0xe4, 0x36, 0xea, 0x47, 0x77, 0x11, 0x28, 0xa1, 0x82, 0x87, 0x29, 0xb7, 0x67, 0x7f, 0x00, 0x81, + 0x89, 0xa0, 0x3e, 0x44, 0x00, 0x81, 0x78, 0xa5, 0xb8, 0x20, 0xcc, 0x27, 0x40, 0x14, 0xef, 0x09, 0x70, 0xa6, 0x26, + 0x6a, 0xd5, 0x44, 0xc5, 0x05, 0x90, 0x44, 0x1b, 0x8e, 0x92, 0x9e, 0x98, 0x00, 0xde, 0x10, 0x94, 0xd2, 0xfe, 0xea, + 0xe5, 0xce, 0x5d, 0x2a, 0x47, 0xfd, 0x56, 0x9a, 0xe3, 0x99, 0xfb, 0x9c, 0xc1, 0xe7, 0xac, 0xe7, 0x4f, 0x07, 0x71, + 0x9c, 0xe3, 0x25, 0x11, 0xc7, 0xfe, 0x59, 0xc4, 0xd5, 0xa2, 0x60, 0x5f, 0xb8, 0x5c, 0xaa, 0x74, 0x75, 0x9b, 0xca, + 0xe4, 0xb6, 0x39, 0x3e, 0x8e, 0x8b, 0xe4, 0xb6, 0xa9, 0x92, 0x5b, 0x84, 0xef, 0x52, 0x99, 0xdc, 0xd9, 0x94, 0xbb, + 0xa6, 0x82, 0x9b, 0x2f, 0x2c, 0xe0, 0x50, 0xb4, 0x45, 0x1b, 0xcb, 0xed, 0xa2, 0x36, 0xc5, 0x15, 0x0d, 0x30, 0xf8, + 0xef, 0x3d, 0x1b, 0x3f, 0x0c, 0x5f, 0x82, 0x4b, 0x93, 0x26, 0xf2, 0x03, 0x48, 0x3f, 0xad, 0xca, 0xc0, 0x7d, 0x46, + 0x5a, 0xbd, 0xd9, 0xa5, 0x68, 0xb6, 0x7b, 0x8d, 0xc6, 0x0c, 0xf6, 0x6e, 0x46, 0x72, 0x5f, 0x6c, 0xd6, 0x30, 0xf1, + 0x75, 0x0e, 0xb3, 0xf5, 0xfa, 0x30, 0x47, 0x66, 0xc3, 0x4d, 0x59, 0xac, 0x07, 0xb3, 0x21, 0x6e, 0xe1, 0xdf, 0x32, + 0x84, 0x56, 0x6c, 0x30, 0x1b, 0x12, 0x36, 0x98, 0x35, 0xda, 0x43, 0x6b, 0x68, 0x67, 0xb6, 0xe2, 0x06, 0x42, 0x68, + 0xce, 0x86, 0x27, 0xa6, 0xa4, 0x74, 0xf9, 0xf6, 0x8b, 0x56, 0x01, 0xfd, 0x54, 0x2d, 0x78, 0x99, 0xc4, 0x1d, 0xe8, + 0x8b, 0x5e, 0xda, 0xa7, 0x5b, 0x0b, 0x72, 0x7a, 0x52, 0xb9, 0xda, 0x53, 0x84, 0x4d, 0x4f, 0xea, 0xb8, 0x38, 0x36, + 0xcd, 0xb8, 0x2e, 0xa5, 0xfb, 0x0e, 0x35, 0x23, 0xbf, 0x3b, 0x58, 0x00, 0x82, 0x54, 0xf0, 0xc8, 0x0b, 0x17, 0x4e, + 0x29, 0x84, 0x8b, 0x83, 0xca, 0x0e, 0x4c, 0x72, 0xd2, 0xea, 0xe5, 0xc6, 0xd2, 0x3f, 0x77, 0x11, 0x4d, 0x29, 0xa6, + 0x24, 0xf3, 0x25, 0x73, 0x03, 0x16, 0xba, 0x4d, 0x79, 0x66, 0xa0, 0x57, 0x1a, 0xe2, 0x31, 0x81, 0x78, 0x48, 0xbd, + 0xc2, 0x18, 0x78, 0xc5, 0xb3, 0x66, 0x31, 0x60, 0x43, 0x74, 0x72, 0x8a, 0xe9, 0xe0, 0xaf, 0x6c, 0xd1, 0x86, 0xc7, + 0x02, 0xff, 0x1a, 0x92, 0x59, 0x53, 0x96, 0x09, 0x02, 0x12, 0xc6, 0x4d, 0x79, 0x0c, 0x7b, 0x09, 0xe1, 0xcc, 0x56, + 0xcc, 0x06, 0x6c, 0xd8, 0x9c, 0x95, 0x15, 0x3b, 0xbe, 0x62, 0x43, 0x96, 0x09, 0xb6, 0x62, 0xc3, 0x55, 0x0c, 0x40, + 0xf0, 0x93, 0x01, 0x41, 0x08, 0x00, 0x06, 0x00, 0xd0, 0x28, 0x88, 0xe6, 0x8b, 0x15, 0xf1, 0x9b, 0xdd, 0xde, 0xe3, + 0xb7, 0xc0, 0x02, 0xad, 0xb6, 0xff, 0xf7, 0xa1, 0x0c, 0xd8, 0x53, 0x16, 0x26, 0x66, 0x6e, 0x61, 0x55, 0x74, 0x00, + 0x95, 0x12, 0x61, 0x0a, 0x03, 0x99, 0xc3, 0xcc, 0x40, 0x2d, 0xd0, 0x1a, 0xe4, 0x03, 0x3d, 0x6c, 0x66, 0x70, 0xc4, + 0xc0, 0x3b, 0x34, 0x64, 0x66, 0x8c, 0x09, 0xe3, 0x1c, 0xa6, 0x98, 0x19, 0xf0, 0xcc, 0xd2, 0xd6, 0x46, 0x1a, 0x59, + 0xae, 0x9f, 0xf7, 0xff, 0xd6, 0xb1, 0x1a, 0x14, 0xcd, 0xf6, 0x10, 0x1d, 0x12, 0x62, 0x3f, 0x86, 0xb0, 0xc9, 0x5c, + 0x6a, 0xc3, 0x7c, 0x9f, 0x74, 0x52, 0xfb, 0x09, 0x7f, 0x86, 0x1b, 0xb3, 0x03, 0x40, 0x47, 0x86, 0xcd, 0xfa, 0xcb, + 0x9a, 0xca, 0xeb, 0xc3, 0xde, 0x28, 0x95, 0xfb, 0xde, 0x9d, 0x0e, 0xe2, 0x44, 0x86, 0xde, 0x7a, 0xb8, 0x7c, 0xa8, + 0x87, 0x80, 0x19, 0x83, 0xb9, 0x65, 0x46, 0xdf, 0x0a, 0x91, 0x5c, 0x10, 0x09, 0x2c, 0x09, 0xa6, 0x84, 0xc1, 0xde, + 0x3a, 0x3a, 0x32, 0xd5, 0x58, 0x03, 0x9e, 0x27, 0x45, 0x20, 0x18, 0xf8, 0x08, 0xca, 0x80, 0x26, 0xca, 0xdc, 0x86, + 0x93, 0x0f, 0xcc, 0xfd, 0xc2, 0xe5, 0xed, 0x63, 0xe1, 0xb4, 0xad, 0xe6, 0x7a, 0xbc, 0x2c, 0x70, 0x57, 0xde, 0x4b, + 0x5a, 0x05, 0x37, 0xb2, 0x37, 0x79, 0xca, 0xdc, 0xad, 0xfb, 0x52, 0x9d, 0xfd, 0xcd, 0x74, 0xca, 0x66, 0x3a, 0xbb, + 0xcd, 0x84, 0x71, 0x25, 0xbf, 0x66, 0x15, 0x69, 0x4e, 0xd6, 0x44, 0x2d, 0xa8, 0xf8, 0x81, 0x2e, 0x40, 0x3b, 0xca, + 0xed, 0xbd, 0x2a, 0x9c, 0x5c, 0x39, 0xb9, 0x3a, 0xcc, 0x0d, 0x71, 0x45, 0xe6, 0x42, 0x1d, 0x02, 0xbc, 0xbc, 0x28, + 0x1f, 0x1f, 0xe0, 0x52, 0xfc, 0x22, 0xc7, 0x2e, 0xca, 0xa9, 0x90, 0x5a, 0x0a, 0x16, 0x21, 0x83, 0xaa, 0x2e, 0x06, + 0xf6, 0xca, 0xee, 0x3d, 0xd1, 0xe7, 0x83, 0x2a, 0x62, 0xde, 0xd0, 0x3c, 0xf7, 0xf1, 0x2d, 0x4d, 0xb1, 0x53, 0x13, + 0x67, 0xe4, 0x43, 0x16, 0xe7, 0x20, 0x9b, 0x0d, 0xaa, 0xd7, 0x7e, 0x1b, 0x6d, 0x5c, 0x34, 0x63, 0xd1, 0x37, 0x4f, + 0x9c, 0x7c, 0x57, 0x18, 0xe3, 0x00, 0xeb, 0xe8, 0x8f, 0x30, 0xb5, 0x60, 0xcf, 0x12, 0x4f, 0xa1, 0x93, 0x5b, 0x9b, + 0x76, 0x17, 0xa6, 0xdd, 0x99, 0xb4, 0x0e, 0x94, 0x03, 0xd2, 0xec, 0xca, 0x74, 0xee, 0xfc, 0xf7, 0x1d, 0xbc, 0x74, + 0xbb, 0x81, 0x48, 0xdc, 0x8b, 0x47, 0xc6, 0x18, 0xe2, 0x35, 0xd8, 0x88, 0xaa, 0xa3, 0xa3, 0x1f, 0x9c, 0xf7, 0x6d, + 0x25, 0xcb, 0x7e, 0x2d, 0x1c, 0xd8, 0x16, 0x53, 0xe9, 0xf2, 0xc6, 0x32, 0x5b, 0x82, 0x5d, 0xe7, 0xe1, 0xfe, 0x78, + 0xf8, 0xcf, 0x44, 0xc8, 0xb4, 0x58, 0x57, 0xf1, 0x97, 0x72, 0x5c, 0x7a, 0x88, 0x6a, 0x88, 0x40, 0x5a, 0x59, 0x97, + 0x86, 0xa6, 0xa3, 0xd7, 0x33, 0x3a, 0x96, 0x37, 0x6f, 0xa4, 0xd4, 0x43, 0xfb, 0x22, 0xb7, 0x4e, 0xe0, 0xd1, 0xc2, + 0x1a, 0x43, 0x73, 0x57, 0x7a, 0x27, 0xd9, 0x80, 0xa8, 0xf5, 0x71, 0x87, 0x92, 0x48, 0x2c, 0xaa, 0xbb, 0x10, 0x0e, + 0x77, 0x21, 0x98, 0x97, 0x41, 0xdb, 0x20, 0x76, 0xbb, 0x0b, 0xda, 0x06, 0x4e, 0xdd, 0x36, 0x70, 0x7b, 0x30, 0x58, + 0xd8, 0xfb, 0xf0, 0x72, 0x2c, 0xc7, 0xc2, 0xf1, 0x07, 0xaf, 0xed, 0x03, 0x40, 0xa0, 0xf6, 0x61, 0xc5, 0x13, 0x07, + 0x82, 0xc4, 0x19, 0x8e, 0xbe, 0xe7, 0xec, 0xc6, 0x5a, 0x0e, 0xcf, 0x17, 0x4b, 0xcd, 0xc6, 0xe6, 0x8e, 0x1a, 0x54, + 0x7c, 0x75, 0x3f, 0xaf, 0x3f, 0xb2, 0x9a, 0x6e, 0xfc, 0x35, 0x84, 0x91, 0x70, 0xca, 0x0e, 0xa3, 0x90, 0xb0, 0xc1, + 0xac, 0xaa, 0x78, 0x6d, 0x10, 0xef, 0x41, 0x9b, 0x70, 0x82, 0x45, 0xed, 0x82, 0x2a, 0xc2, 0x36, 0xde, 0x58, 0x10, + 0xe5, 0xe1, 0xd5, 0x8e, 0xd1, 0xf4, 0x6a, 0x03, 0x81, 0x8e, 0xfb, 0x51, 0x33, 0x6a, 0xb0, 0xd4, 0x05, 0x65, 0xf6, + 0x11, 0xc6, 0xd5, 0xe5, 0x99, 0x89, 0xd3, 0x5e, 0xea, 0xd5, 0x7f, 0xcc, 0xc0, 0x00, 0x5f, 0x80, 0x97, 0x58, 0x18, + 0xdd, 0x75, 0xa0, 0x1b, 0x50, 0x5f, 0x36, 0xd8, 0x10, 0xad, 0xd7, 0xad, 0xf2, 0x19, 0x28, 0x77, 0xcd, 0x25, 0xec, + 0x35, 0x97, 0x70, 0xd7, 0x5c, 0xc2, 0x5f, 0x73, 0x09, 0x73, 0xcd, 0x25, 0xfc, 0x35, 0x97, 0x07, 0xa1, 0xce, 0xab, + 0xa0, 0x51, 0x31, 0x87, 0xb8, 0x8a, 0xda, 0x46, 0xc6, 0x83, 0x0b, 0xcf, 0x43, 0x96, 0xa8, 0x72, 0xf9, 0x03, 0x98, + 0xb1, 0x7c, 0xdb, 0x56, 0xc2, 0xb8, 0x4d, 0x31, 0x05, 0x91, 0xd3, 0x8f, 0x8e, 0x2a, 0x77, 0xe7, 0x41, 0x6b, 0x98, + 0x72, 0xbc, 0xb2, 0x4e, 0xb4, 0xbf, 0x83, 0x4e, 0xde, 0xfc, 0xfa, 0x90, 0xca, 0x0d, 0x11, 0xce, 0xe4, 0xfe, 0xb0, + 0x5d, 0x52, 0x8a, 0xdc, 0x84, 0x27, 0xe7, 0x89, 0x36, 0x22, 0x08, 0x42, 0x94, 0x28, 0x9c, 0x11, 0x69, 0xf7, 0xbb, + 0x77, 0x85, 0x37, 0xaa, 0x28, 0x6f, 0x56, 0xf2, 0x38, 0x07, 0x27, 0x76, 0x63, 0x85, 0x81, 0x7a, 0xe0, 0x42, 0x90, + 0x99, 0x84, 0xdf, 0x9b, 0xb9, 0x25, 0x67, 0x59, 0x99, 0xf4, 0xa1, 0x99, 0x1b, 0x02, 0xf6, 0xff, 0xb2, 0xf7, 0xae, + 0xcb, 0x6d, 0x23, 0xc9, 0xba, 0xe8, 0xab, 0x48, 0x0c, 0x37, 0x1b, 0x30, 0x8b, 0x14, 0xe5, 0xbd, 0x67, 0x22, 0x0e, + 0xa8, 0x32, 0xc3, 0x96, 0xdb, 0xd3, 0x9e, 0xf1, 0x6d, 0x6c, 0x77, 0x4f, 0xf7, 0x30, 0x78, 0xd8, 0x10, 0x50, 0x14, + 0xe0, 0x06, 0x01, 0x1a, 0x00, 0x25, 0xd2, 0x24, 0xde, 0x7d, 0x47, 0x66, 0xd6, 0x15, 0x04, 0x65, 0xcf, 0x5a, 0x7b, + 0xfd, 0x3a, 0xe7, 0x8f, 0x2d, 0x16, 0x0a, 0x85, 0xba, 0x57, 0x56, 0x5e, 0xbe, 0xaf, 0xe4, 0xe7, 0xaa, 0xcf, 0xf6, + 0xdb, 0x20, 0x64, 0xbb, 0x20, 0x62, 0x37, 0xc5, 0x36, 0x28, 0xad, 0x23, 0xf1, 0xa3, 0x32, 0xfc, 0x2d, 0xbd, 0x5e, + 0x1e, 0x42, 0xbc, 0x4f, 0x2f, 0xcd, 0xcf, 0xd2, 0x56, 0x14, 0xe0, 0x3e, 0x42, 0x8f, 0xea, 0x40, 0xb0, 0x13, 0x9e, + 0xf0, 0x00, 0x4e, 0x56, 0xb3, 0x8a, 0xbf, 0x4f, 0x41, 0x9c, 0x28, 0x38, 0x04, 0x5c, 0x6d, 0x3f, 0xa6, 0x5f, 0xc1, + 0xf0, 0xa5, 0x83, 0x2d, 0x87, 0x37, 0xc5, 0xb6, 0xc7, 0x4a, 0xfe, 0x0e, 0xd8, 0xb7, 0x7a, 0x32, 0x56, 0xb7, 0x07, + 0xce, 0xba, 0x94, 0xa2, 0xe3, 0x4d, 0x71, 0x78, 0x7b, 0x3e, 0xdb, 0x6f, 0x83, 0x88, 0xed, 0x82, 0x0c, 0x6b, 0x9d, + 0x34, 0x1c, 0x07, 0x43, 0xf8, 0x2c, 0x46, 0xd8, 0xff, 0x65, 0x3d, 0xf0, 0x12, 0x52, 0x43, 0x81, 0x8b, 0xc1, 0x86, + 0xa3, 0xb5, 0x5d, 0xa6, 0x81, 0x9b, 0x1a, 0xf4, 0xfa, 0x9e, 0x42, 0x94, 0x97, 0x8c, 0xe6, 0x46, 0xb0, 0x6e, 0x0c, + 0xb9, 0x38, 0x1c, 0x37, 0xcb, 0x21, 0x2f, 0x69, 0x3a, 0x0d, 0x42, 0xe9, 0xce, 0xb2, 0x86, 0x24, 0xca, 0x3e, 0x08, + 0xb5, 0x6b, 0xcb, 0x7e, 0x1b, 0xd8, 0xbe, 0xfc, 0xd1, 0x30, 0xf6, 0x2f, 0x96, 0x8f, 0x85, 0x74, 0x11, 0xcf, 0x41, + 0x10, 0xb5, 0x9f, 0x67, 0xc3, 0x8d, 0x7f, 0xb1, 0x7e, 0x2c, 0x94, 0xdf, 0x78, 0x6e, 0xcb, 0x21, 0x69, 0xd6, 0xc2, + 0x17, 0xc6, 0x29, 0xc1, 0x95, 0xa1, 0xed, 0x70, 0x10, 0xfa, 0x6f, 0xb3, 0x46, 0x70, 0x63, 0x43, 0xfb, 0x7c, 0xe1, + 0xc3, 0xd6, 0x46, 0x63, 0x4d, 0x31, 0xdd, 0x42, 0xff, 0x26, 0xb3, 0xa5, 0x3d, 0x8d, 0x4a, 0x5e, 0x9c, 0x9a, 0x46, + 0x2c, 0x84, 0x01, 0x43, 0x3f, 0x99, 0x77, 0xa0, 0x9a, 0x3b, 0x1e, 0x81, 0x4c, 0x3e, 0xd0, 0x83, 0x35, 0xa9, 0x55, + 0x7f, 0x0d, 0x33, 0xf9, 0x7f, 0xa4, 0xc2, 0x62, 0x74, 0xb7, 0x0d, 0x33, 0xf5, 0x47, 0x24, 0xff, 0x60, 0x39, 0xdf, + 0xa5, 0x5e, 0xa8, 0xfd, 0x58, 0x58, 0x81, 0x41, 0x89, 0xaa, 0x01, 0x3d, 0x10, 0x41, 0x55, 0x06, 0x69, 0x86, 0xd5, + 0x39, 0xe8, 0x77, 0x4f, 0xab, 0x8e, 0xe4, 0x90, 0xd6, 0x6a, 0x48, 0x05, 0x53, 0xa5, 0x06, 0xf9, 0xe1, 0x70, 0x9b, + 0x32, 0x5d, 0x06, 0x5c, 0xd2, 0x6f, 0x53, 0xa5, 0x14, 0xfe, 0x82, 0x00, 0x74, 0x0e, 0xee, 0xf1, 0xe5, 0x18, 0x48, + 0x33, 0x2c, 0xfc, 0xd6, 0xec, 0xf8, 0x9a, 0x84, 0xdb, 0x24, 0xb8, 0x18, 0xe0, 0x1c, 0x5d, 0x85, 0xe5, 0x6d, 0x0a, + 0x11, 0x54, 0x25, 0xd4, 0xb7, 0x32, 0x0d, 0x4a, 0x5b, 0x0d, 0xc2, 0x9a, 0x84, 0x3a, 0x93, 0x6c, 0x54, 0xda, 0x6e, + 0x14, 0x66, 0x8b, 0xb8, 0x9e, 0x11, 0xd6, 0x9c, 0xcd, 0x54, 0x03, 0x93, 0x86, 0xe3, 0xa6, 0xd1, 0x5a, 0x54, 0xa8, + 0x29, 0xcc, 0x6b, 0x5c, 0x55, 0xaa, 0xba, 0x9b, 0x53, 0x4b, 0x69, 0xd9, 0x5e, 0x75, 0x93, 0x6c, 0xc8, 0x65, 0x28, + 0xc3, 0x60, 0x23, 0x47, 0x30, 0x81, 0x24, 0x39, 0xf3, 0x37, 0xf2, 0x0f, 0xb5, 0xe9, 0x5a, 0xc0, 0x1c, 0x63, 0x96, + 0x0d, 0x0b, 0x7a, 0x05, 0xee, 0x81, 0x56, 0x7a, 0x3e, 0xcd, 0x2e, 0xf2, 0x20, 0x19, 0x16, 0x7a, 0xd9, 0x64, 0xfc, + 0x8b, 0x30, 0xd2, 0x64, 0xc6, 0x4a, 0x16, 0xd9, 0xae, 0x4e, 0x89, 0xf3, 0x38, 0x81, 0xed, 0xd1, 0xf4, 0x96, 0xef, + 0x33, 0x88, 0x0a, 0x02, 0x05, 0x33, 0xe6, 0xcb, 0x2e, 0x9e, 0xf8, 0x3e, 0xb3, 0x4c, 0xdd, 0x87, 0x83, 0x31, 0x63, + 0xfb, 0xfd, 0x7e, 0xde, 0xef, 0xab, 0xf9, 0xd6, 0xef, 0x27, 0x4f, 0xcd, 0xdf, 0x1e, 0x30, 0x28, 0xc8, 0x89, 0x68, + 0x2a, 0x44, 0xf0, 0x0f, 0xc9, 0x63, 0x24, 0xa3, 0x3b, 0xee, 0x73, 0xcb, 0xf3, 0xb3, 0x3a, 0x02, 0xc1, 0x3c, 0x1c, + 0x2e, 0x15, 0xd8, 0xb5, 0x44, 0x91, 0x90, 0xe5, 0x3f, 0x06, 0xe3, 0x99, 0xfb, 0x00, 0x4b, 0x06, 0x20, 0x6c, 0x95, + 0xa7, 0xeb, 0x3d, 0x5f, 0x05, 0xef, 0x74, 0xbc, 0x6b, 0xac, 0xc8, 0x40, 0xdc, 0x02, 0x1b, 0xb1, 0xd6, 0x1e, 0x90, + 0x33, 0x05, 0x38, 0x5e, 0x1c, 0x0e, 0xe7, 0xf2, 0x97, 0x6e, 0xb6, 0x4e, 0xa0, 0x52, 0xe0, 0xf6, 0xe8, 0xe4, 0xe0, + 0x7f, 0x00, 0xcd, 0xa0, 0x1c, 0xe6, 0xf5, 0xf6, 0x0f, 0xe6, 0xe4, 0xa7, 0xa7, 0xf8, 0x27, 0x3c, 0x44, 0xa7, 0xdf, + 0xee, 0xcd, 0x1f, 0x14, 0x95, 0x87, 0x83, 0x5a, 0xfc, 0xe7, 0x9c, 0x57, 0xf0, 0x0b, 0xdf, 0x04, 0x66, 0x93, 0xa9, + 0x77, 0xf2, 0x4d, 0x9e, 0x33, 0xf5, 0x1a, 0xaf, 0x98, 0x7c, 0x87, 0xc3, 0xb9, 0x18, 0xd5, 0xdb, 0x91, 0x13, 0xed, + 0x94, 0x63, 0x1c, 0x0c, 0xfe, 0x8b, 0x68, 0x9b, 0x10, 0x60, 0x28, 0x97, 0x68, 0x66, 0xe3, 0xca, 0x12, 0xcf, 0xd2, + 0xf9, 0xe5, 0xa4, 0x2e, 0x77, 0x5a, 0xf1, 0xb4, 0x07, 0x16, 0xb7, 0x35, 0x78, 0x01, 0xdc, 0x59, 0x6c, 0x5d, 0x29, + 0x38, 0x5c, 0x40, 0x9c, 0xe2, 0x04, 0x44, 0xd0, 0x7e, 0x5f, 0xe2, 0xbd, 0x82, 0x3e, 0xe9, 0x27, 0x08, 0x86, 0x7c, + 0x2d, 0x01, 0x77, 0xbd, 0x5e, 0x8d, 0xf1, 0xbd, 0x14, 0x82, 0xeb, 0x33, 0x0d, 0x40, 0x0b, 0x7e, 0x97, 0x0f, 0xe5, + 0xf4, 0x9b, 0x08, 0x3c, 0x5b, 0xf6, 0x26, 0xca, 0xdd, 0x86, 0xa7, 0xfd, 0xd8, 0x42, 0x00, 0x96, 0xe2, 0x99, 0x12, + 0x2c, 0xc8, 0x29, 0xe6, 0xe2, 0xff, 0x05, 0x1f, 0x31, 0xdf, 0x93, 0x2e, 0x62, 0xeb, 0xed, 0xa3, 0x0b, 0x03, 0x09, + 0x34, 0x1d, 0x80, 0x1f, 0xaf, 0x02, 0xba, 0x32, 0x3e, 0xb3, 0x96, 0xf5, 0x58, 0x1f, 0xff, 0x29, 0xb8, 0x4f, 0x3f, + 0x56, 0xf8, 0xe8, 0x70, 0x5c, 0xa5, 0xa3, 0x1d, 0xa5, 0x20, 0x3a, 0xba, 0x7d, 0x3e, 0x15, 0xd9, 0x77, 0x15, 0x90, + 0x5b, 0x8e, 0xda, 0x53, 0x01, 0x58, 0x6c, 0xe9, 0x08, 0x7c, 0x9a, 0xe5, 0x13, 0xf2, 0xbd, 0x9e, 0x8a, 0xab, 0x4b, + 0x9d, 0x2e, 0x9e, 0x8e, 0xa7, 0xf0, 0x3f, 0x10, 0x7b, 0x58, 0xd8, 0xb9, 0x1d, 0xbb, 0x2e, 0x7e, 0x10, 0x6f, 0x6b, + 0x3b, 0xfa, 0x63, 0x07, 0x91, 0x8e, 0x7b, 0x72, 0xa1, 0xbe, 0x84, 0x54, 0x72, 0xa1, 0x6e, 0x20, 0x76, 0xa1, 0xc6, + 0x3b, 0x2e, 0x62, 0xad, 0xbf, 0xa9, 0x51, 0xb0, 0x12, 0x70, 0xa6, 0xbd, 0x01, 0x83, 0x0d, 0xac, 0x5b, 0x96, 0xc1, + 0xdf, 0x70, 0x4d, 0x13, 0xb8, 0x61, 0x91, 0xf5, 0xde, 0x60, 0x2b, 0xbd, 0x01, 0x47, 0xcb, 0xc4, 0xb9, 0x94, 0x24, + 0x65, 0x8b, 0x8c, 0xab, 0x47, 0x21, 0x55, 0xd3, 0xfd, 0x8d, 0xa8, 0xef, 0x85, 0xc8, 0x83, 0x55, 0xca, 0xa2, 0x62, + 0x05, 0x32, 0x7b, 0xf0, 0xf7, 0x90, 0x91, 0xa3, 0x1c, 0x38, 0x0a, 0xfd, 0xb3, 0x09, 0x74, 0x1e, 0x11, 0xe9, 0x3c, + 0x12, 0x6c, 0xa5, 0x1e, 0x0a, 0x2b, 0x2f, 0x20, 0x3a, 0x58, 0x1d, 0xf1, 0xa6, 0xf2, 0x24, 0x54, 0x6c, 0xca, 0x44, + 0x1e, 0x07, 0xb5, 0x04, 0x8c, 0x15, 0x04, 0x73, 0x96, 0x4b, 0x17, 0xa4, 0xaa, 0xd1, 0xc3, 0x22, 0x73, 0xff, 0x20, + 0x28, 0xff, 0x0f, 0x2a, 0x27, 0x5c, 0x5f, 0x86, 0x00, 0x47, 0xfb, 0x03, 0x88, 0x12, 0x63, 0xfd, 0xa2, 0x65, 0x74, + 0xc9, 0x9c, 0x4d, 0x6d, 0x2f, 0x41, 0xc6, 0x76, 0xf8, 0x15, 0x42, 0xab, 0x85, 0x22, 0x8b, 0x86, 0x0b, 0xa6, 0xdb, + 0x53, 0x5a, 0x75, 0x0f, 0x1b, 0x9e, 0x94, 0x1e, 0x2a, 0xf5, 0x6d, 0x4c, 0x60, 0x59, 0xa5, 0x0c, 0xdf, 0x4e, 0xa8, + 0x3a, 0x31, 0xa8, 0x58, 0x37, 0x6c, 0x09, 0x87, 0x58, 0x4c, 0x1a, 0xeb, 0x6c, 0xc0, 0x23, 0x96, 0xc0, 0x3f, 0x1b, + 0x3e, 0x66, 0x4b, 0x1e, 0x4d, 0x36, 0x57, 0xcb, 0x7e, 0xbf, 0xf4, 0x42, 0xaf, 0x9e, 0x65, 0x3f, 0x44, 0xf3, 0x59, + 0x3e, 0xf7, 0x51, 0x71, 0x31, 0x19, 0x0c, 0x36, 0x7e, 0x36, 0x1c, 0xb2, 0x64, 0x38, 0x9c, 0x64, 0x3f, 0xc0, 0x6b, + 0x3f, 0xf0, 0x48, 0x2d, 0xa9, 0xe4, 0x2a, 0x83, 0xfd, 0x7d, 0xc0, 0x23, 0x9f, 0x75, 0x7e, 0x5a, 0x36, 0x5d, 0xba, + 0x9f, 0x59, 0x1d, 0x10, 0xe9, 0x0e, 0xb0, 0xf1, 0xb6, 0x41, 0x47, 0xfe, 0xed, 0x0e, 0x29, 0x75, 0x93, 0x01, 0xd8, + 0x8d, 0x06, 0x38, 0x64, 0xaa, 0x97, 0x22, 0xab, 0x97, 0x32, 0xd5, 0x4b, 0xb2, 0x72, 0x09, 0x16, 0x12, 0x53, 0xe5, + 0x36, 0xb2, 0x72, 0xcb, 0x86, 0xeb, 0xe1, 0x60, 0x6b, 0xc5, 0x65, 0x73, 0x0b, 0xf7, 0x85, 0x15, 0x05, 0xfe, 0xdf, + 0xb0, 0x05, 0xbb, 0x93, 0xc7, 0xc0, 0x35, 0x3a, 0x26, 0x45, 0x5e, 0xc5, 0xee, 0xd8, 0x0d, 0xd8, 0x61, 0xe1, 0x2f, + 0xb8, 0x4e, 0x8e, 0xd9, 0x0e, 0x1f, 0x85, 0x5e, 0xc1, 0x6e, 0x7c, 0x02, 0xda, 0x05, 0x5b, 0x03, 0x64, 0x63, 0x5b, + 0x7c, 0x74, 0x7b, 0x38, 0x5c, 0x7b, 0x3e, 0xbb, 0xc7, 0x1f, 0xe7, 0xb7, 0x87, 0xc3, 0xce, 0x33, 0xea, 0xbd, 0x37, + 0x3c, 0x61, 0x8f, 0x78, 0x32, 0x79, 0x73, 0xc5, 0xe3, 0xc9, 0x60, 0xf0, 0xc6, 0x5f, 0xf0, 0x7a, 0xf6, 0x06, 0xb4, + 0x03, 0xe7, 0x0b, 0xa9, 0x6b, 0xf6, 0x6e, 0x78, 0xe6, 0x2d, 0x70, 0x6c, 0x6e, 0xe0, 0xe8, 0xed, 0xf7, 0xbd, 0x5b, + 0x1e, 0x79, 0x37, 0xa4, 0x62, 0x5a, 0x71, 0xc5, 0xf1, 0xb6, 0xc5, 0xfd, 0x74, 0xc5, 0x43, 0x78, 0x84, 0x55, 0x99, + 0xbe, 0x09, 0x1e, 0xf9, 0x6c, 0xa5, 0x59, 0xe0, 0xee, 0x31, 0xc7, 0x9a, 0xec, 0x84, 0x66, 0xe2, 0xaf, 0xb0, 0x7f, + 0xde, 0xa8, 0xfe, 0xa1, 0xf9, 0x5f, 0xea, 0x7e, 0x02, 0xb7, 0x2f, 0xb2, 0x20, 0xb1, 0x47, 0xfc, 0x0d, 0xbb, 0xe3, + 0x86, 0x6d, 0xf6, 0xcc, 0x94, 0x7d, 0xa2, 0xd4, 0xf8, 0x81, 0x52, 0xd7, 0x16, 0x24, 0x73, 0xeb, 0xca, 0x87, 0xc0, + 0xe1, 0x80, 0xfc, 0x74, 0x8b, 0x38, 0x08, 0xad, 0x9b, 0xac, 0xe6, 0x8a, 0x72, 0x2e, 0xb4, 0x51, 0xe6, 0xe5, 0xc0, + 0x62, 0x96, 0x52, 0x68, 0x2c, 0x00, 0x10, 0x4c, 0x0a, 0xad, 0xbd, 0x97, 0x01, 0xe4, 0x04, 0x0d, 0x7f, 0x6c, 0xae, + 0x4a, 0xb2, 0x96, 0x2d, 0x09, 0x51, 0xb6, 0xeb, 0xe1, 0x25, 0x42, 0xa6, 0xf5, 0xfb, 0xe7, 0x44, 0xb2, 0x36, 0xa9, + 0xae, 0x6a, 0xb4, 0x04, 0x54, 0x64, 0x09, 0x98, 0xf8, 0x95, 0xe6, 0x13, 0x80, 0x27, 0x1d, 0x0f, 0xaa, 0x1f, 0x78, + 0xcd, 0x04, 0x91, 0x6d, 0x54, 0xfe, 0xa4, 0x78, 0x8a, 0x64, 0x04, 0xc5, 0x0f, 0xb5, 0xca, 0x58, 0x18, 0xe6, 0x81, + 0x02, 0xf2, 0xee, 0xdd, 0xa9, 0x6f, 0xd1, 0xd6, 0x74, 0xec, 0xd9, 0x5a, 0x85, 0x5a, 0xa8, 0x29, 0x5c, 0x72, 0x88, + 0xae, 0x40, 0x03, 0x45, 0x24, 0xe3, 0xc9, 0xeb, 0xc1, 0xe5, 0x24, 0xba, 0xe2, 0x02, 0x9d, 0xf1, 0xf5, 0x4d, 0x37, + 0x9d, 0x45, 0x3f, 0x54, 0xf3, 0x09, 0x29, 0xc9, 0x0e, 0x87, 0x6c, 0x54, 0xd5, 0xc5, 0x7a, 0x1a, 0xca, 0x9f, 0x1e, + 0x82, 0xaf, 0x17, 0xd4, 0x6b, 0xb2, 0x4a, 0xf5, 0x0f, 0x54, 0x29, 0x2f, 0x1a, 0x5e, 0xfa, 0x3f, 0x54, 0x72, 0xdf, + 0x03, 0xd2, 0x5a, 0x5e, 0x72, 0xf9, 0x7e, 0x84, 0x18, 0x23, 0x7e, 0xe0, 0x95, 0x3c, 0x62, 0xa1, 0x9a, 0xc2, 0x35, + 0x8f, 0x10, 0xe4, 0x2d, 0xd3, 0xc1, 0xdf, 0x7a, 0xe2, 0x74, 0x7f, 0xa2, 0xb4, 0x8b, 0x2f, 0x2c, 0xa6, 0x95, 0x23, + 0xdd, 0x80, 0x1c, 0x6c, 0x98, 0x2e, 0x0a, 0xb2, 0x4d, 0x69, 0x04, 0x6d, 0xb4, 0x1c, 0xd8, 0x70, 0x2a, 0xb5, 0xe1, + 0xcc, 0x35, 0x04, 0xf7, 0xf9, 0x79, 0x3a, 0x5a, 0xc0, 0x87, 0x54, 0xb7, 0x97, 0xf8, 0x79, 0xd8, 0x68, 0x81, 0xcc, + 0x8e, 0xf8, 0xcc, 0x26, 0x92, 0x4e, 0xea, 0x5c, 0x01, 0xbb, 0x9d, 0x5d, 0x83, 0x1c, 0x31, 0x73, 0x5f, 0xa1, 0xfa, + 0x16, 0x0d, 0xb8, 0x32, 0xd6, 0xbe, 0x26, 0x19, 0x0b, 0xaf, 0xca, 0x69, 0x38, 0x00, 0x18, 0xba, 0x8c, 0xbe, 0xb6, + 0xdc, 0x64, 0xd9, 0xeb, 0x02, 0x82, 0x20, 0x4a, 0xe2, 0xf1, 0x01, 0xef, 0xcb, 0x6a, 0xa8, 0x51, 0xf2, 0xb1, 0xec, + 0x18, 0xbe, 0x5e, 0xa2, 0xbf, 0x1b, 0x73, 0x89, 0x01, 0xaf, 0xab, 0xb6, 0xa0, 0x70, 0x9e, 0x1f, 0x0e, 0xe7, 0xf9, + 0xc8, 0x78, 0x96, 0x81, 0x6a, 0x65, 0x5a, 0x07, 0x4b, 0x33, 0x5f, 0x2c, 0xfc, 0xc5, 0xce, 0x49, 0x44, 0x14, 0x04, + 0x76, 0x24, 0x3c, 0x88, 0xd4, 0x8f, 0x2a, 0x4f, 0x77, 0xaa, 0xcf, 0xf6, 0x0b, 0x9b, 0x48, 0x2f, 0x28, 0x99, 0x7c, + 0x12, 0xec, 0x55, 0x7f, 0x07, 0x61, 0x43, 0x78, 0xf3, 0xaa, 0xd7, 0x59, 0xa6, 0x66, 0x25, 0x48, 0x98, 0x31, 0x47, + 0xf0, 0x38, 0xec, 0x34, 0xb6, 0xe1, 0xb1, 0x11, 0xcb, 0x96, 0xde, 0x9a, 0xdd, 0xb2, 0x15, 0xbb, 0x51, 0x75, 0x5a, + 0xf0, 0x70, 0x3a, 0xbc, 0x0c, 0x70, 0xf5, 0xad, 0xcf, 0x39, 0xbf, 0xa5, 0x13, 0x6c, 0x3d, 0xe0, 0xd1, 0x44, 0xcc, + 0xd6, 0x3f, 0x44, 0x6a, 0xf1, 0xac, 0x87, 0x7c, 0x41, 0xeb, 0x4f, 0xcc, 0x6e, 0x4d, 0xf2, 0xed, 0x80, 0x2f, 0x26, + 0xeb, 0x1f, 0x22, 0x78, 0xf5, 0x07, 0xb0, 0x62, 0x64, 0xce, 0x2c, 0x5b, 0xff, 0x10, 0xe1, 0x98, 0xdd, 0xfe, 0x10, + 0xd1, 0xa8, 0xad, 0xe4, 0xbe, 0x74, 0xd3, 0x80, 0xb0, 0x72, 0xc3, 0x62, 0x78, 0x0d, 0xc4, 0x33, 0x6d, 0x24, 0x5d, + 0x4b, 0x43, 0x6f, 0xcc, 0xc3, 0x69, 0x1c, 0xac, 0xa9, 0x15, 0xf2, 0xcc, 0x10, 0xb3, 0xf8, 0x87, 0x68, 0xce, 0x56, + 0x58, 0x91, 0x0d, 0x8f, 0x07, 0x97, 0x93, 0xcd, 0x15, 0x5f, 0x03, 0xf9, 0xd9, 0x64, 0x63, 0xb6, 0xa8, 0x1b, 0x2e, + 0x66, 0x9b, 0x1f, 0xa2, 0xf9, 0x64, 0x05, 0x3d, 0x6b, 0x0f, 0x98, 0xf7, 0x12, 0x44, 0x28, 0x09, 0xa9, 0x29, 0x37, + 0xbd, 0x1e, 0x5b, 0x8f, 0x83, 0x5b, 0xb6, 0xbe, 0x0c, 0x6e, 0xd8, 0x7a, 0x0c, 0x44, 0x1c, 0xd4, 0xef, 0xde, 0x06, + 0x16, 0x5f, 0xc4, 0xd6, 0x97, 0x26, 0x6d, 0xf3, 0x43, 0xc4, 0xdc, 0xc1, 0x69, 0xe0, 0x82, 0xb5, 0xce, 0xbc, 0x15, + 0x83, 0x4b, 0xc8, 0xd2, 0x8b, 0xd9, 0x66, 0x78, 0xc9, 0xd6, 0x23, 0x9c, 0xea, 0x89, 0xcf, 0x6e, 0xf9, 0x0d, 0x4b, + 0xf8, 0xaa, 0x89, 0xaf, 0x36, 0xa0, 0x11, 0x3d, 0xca, 0xa0, 0xaf, 0xa0, 0x56, 0x28, 0x8b, 0x85, 0x51, 0xb9, 0x6f, + 0xc1, 0x01, 0x05, 0x69, 0x1b, 0x20, 0x48, 0xe2, 0xd9, 0x5d, 0x87, 0xeb, 0x8f, 0x52, 0x18, 0x70, 0x13, 0x98, 0x01, + 0x03, 0xd3, 0xcf, 0xe0, 0x87, 0x95, 0x2e, 0x11, 0xe2, 0xec, 0xa7, 0x94, 0x24, 0xf3, 0xfc, 0xbd, 0x48, 0x73, 0xb7, + 0x70, 0x9d, 0xc2, 0xac, 0x28, 0x50, 0xfd, 0x94, 0x94, 0x06, 0x16, 0x2a, 0x91, 0xa9, 0x14, 0xfc, 0xb2, 0x76, 0xda, + 0x75, 0x76, 0x8c, 0xce, 0x75, 0x7e, 0x39, 0x71, 0x4e, 0x27, 0x7d, 0xff, 0x81, 0x63, 0xd8, 0x42, 0x06, 0x2e, 0xfc, + 0xa9, 0x27, 0x8c, 0x53, 0x2b, 0x10, 0x53, 0xc9, 0xb3, 0xa7, 0xf0, 0x99, 0xd0, 0xea, 0xe8, 0xc2, 0xf7, 0x83, 0x42, + 0x9b, 0xa4, 0x5b, 0x90, 0xa4, 0xe0, 0x29, 0x7a, 0xce, 0x79, 0x1b, 0xa8, 0x14, 0x23, 0x5a, 0x10, 0x69, 0xeb, 0x36, + 0x73, 0x90, 0xb6, 0x34, 0xdf, 0x35, 0xf1, 0x73, 0x58, 0xc0, 0x45, 0xb4, 0xb0, 0x35, 0x3c, 0xaa, 0x62, 0xe5, 0xde, + 0xe4, 0x39, 0xc2, 0x19, 0x5d, 0xca, 0x04, 0xc0, 0xf5, 0x7e, 0x11, 0xd6, 0x0a, 0xaf, 0xa8, 0x59, 0xe4, 0x45, 0x4d, + 0x9f, 0x6c, 0x81, 0xfb, 0x58, 0x94, 0x28, 0x70, 0xd6, 0x82, 0x01, 0x5b, 0x61, 0xc9, 0x4e, 0x0a, 0x9b, 0xa2, 0x25, + 0xf4, 0xf6, 0xf8, 0xe9, 0xa0, 0x66, 0x32, 0x80, 0x26, 0x80, 0xc6, 0xe3, 0x5f, 0x00, 0x6a, 0xfa, 0xb1, 0x16, 0xeb, + 0x2a, 0x28, 0x95, 0x72, 0x13, 0x7e, 0x06, 0x86, 0x19, 0x7e, 0x28, 0xe4, 0x36, 0x51, 0x22, 0xe7, 0xc7, 0xa2, 0x14, + 0xcb, 0x52, 0x54, 0x49, 0xbb, 0xa1, 0xe0, 0x11, 0xe1, 0x36, 0x68, 0xcc, 0xdc, 0x9e, 0xe8, 0xa2, 0x15, 0xa1, 0x1c, + 0x9b, 0x75, 0x8c, 0x34, 0xca, 0xec, 0x64, 0xd7, 0xc9, 0x42, 0xfb, 0x7d, 0x95, 0x43, 0xd6, 0x01, 0x6b, 0x24, 0x5f, + 0xaf, 0x39, 0x74, 0xdb, 0x28, 0x2f, 0xee, 0x3d, 0x5f, 0xc1, 0x69, 0x8e, 0x27, 0x76, 0xd7, 0xeb, 0x4e, 0x91, 0x88, + 0x57, 0x38, 0xa9, 0xf2, 0x91, 0x2c, 0x1c, 0x77, 0xee, 0xb4, 0x16, 0xab, 0xca, 0x65, 0x3d, 0xb5, 0x38, 0x22, 0xf0, + 0xa9, 0x3c, 0xda, 0x0b, 0x6d, 0x8b, 0x62, 0x21, 0x8c, 0x1e, 0x9d, 0xf0, 0x93, 0x12, 0x58, 0x5f, 0x87, 0xc3, 0xd2, + 0x8f, 0x38, 0xfa, 0x9d, 0x46, 0xa3, 0x05, 0x21, 0x0d, 0x4f, 0xbd, 0x68, 0xb4, 0xa8, 0x8b, 0x3a, 0xcc, 0x9e, 0xe6, + 0x7a, 0xa0, 0x30, 0x8c, 0x40, 0xfd, 0xe0, 0x2a, 0x83, 0xcf, 0x22, 0x44, 0xcd, 0x03, 0xd3, 0x6c, 0x08, 0x47, 0x5d, + 0xe0, 0xa1, 0x15, 0xb4, 0x98, 0x99, 0x8f, 0x42, 0x0c, 0x1f, 0xd2, 0xc5, 0xf9, 0x13, 0xb2, 0xf2, 0x01, 0x76, 0x87, + 0xee, 0x42, 0x39, 0x67, 0x2a, 0x06, 0xf8, 0x51, 0x40, 0x3e, 0x4a, 0xc0, 0xcd, 0x00, 0xd9, 0x23, 0x4b, 0x00, 0xb1, + 0x62, 0x74, 0x34, 0xf9, 0xdc, 0xf7, 0x22, 0x05, 0xef, 0xec, 0xb3, 0x5c, 0x4d, 0x18, 0x0a, 0x9f, 0x18, 0xe8, 0xe6, + 0x37, 0x7e, 0x7b, 0xde, 0x82, 0x91, 0x5d, 0x92, 0xe2, 0xb5, 0x66, 0xb8, 0xdf, 0x80, 0xdb, 0x11, 0x50, 0xd6, 0x54, + 0xc7, 0x24, 0xdb, 0x34, 0x44, 0x32, 0x60, 0x46, 0x8c, 0x08, 0x2a, 0xcb, 0x85, 0xff, 0xdd, 0xcb, 0xa2, 0xc0, 0x01, + 0x5c, 0xcd, 0x64, 0xf0, 0xda, 0x85, 0x51, 0x01, 0x70, 0x4e, 0x43, 0xa7, 0xb4, 0x57, 0x55, 0x87, 0x64, 0xd5, 0xfc, + 0x60, 0x36, 0x6f, 0x1a, 0x26, 0x46, 0x04, 0xd1, 0x45, 0x38, 0xc1, 0xf4, 0x8a, 0xf4, 0xb5, 0x92, 0xd3, 0xd1, 0xaa, + 0xa3, 0xb5, 0xc4, 0xc4, 0x5c, 0x51, 0xfc, 0x35, 0xe0, 0x71, 0x83, 0x57, 0x27, 0x69, 0x3a, 0x51, 0x3d, 0x7a, 0xfc, + 0x3a, 0x4d, 0x27, 0x25, 0xee, 0x0a, 0xbf, 0x01, 0x17, 0xcd, 0x36, 0x1f, 0xfa, 0xf1, 0x0b, 0x8a, 0xb8, 0xa8, 0xc1, + 0x95, 0x77, 0xaa, 0xaf, 0x54, 0x1f, 0x41, 0x2d, 0x3c, 0x31, 0xb2, 0x16, 0x9e, 0x5c, 0xb2, 0xd6, 0x82, 0x60, 0x66, + 0x73, 0xe0, 0x42, 0x7e, 0xa5, 0x14, 0xf1, 0x26, 0x12, 0x6a, 0x31, 0x68, 0x3d, 0x66, 0xce, 0xaa, 0xd1, 0x42, 0x65, + 0x46, 0x68, 0xdf, 0xd6, 0xa2, 0xf3, 0x1b, 0xf9, 0x29, 0x4f, 0xed, 0xcb, 0xf6, 0x38, 0x1f, 0xef, 0xd1, 0x5d, 0x75, + 0x96, 0x99, 0x94, 0xf1, 0xc9, 0x2c, 0x41, 0xe1, 0x2e, 0xc1, 0x06, 0x24, 0xd9, 0x6f, 0x75, 0x80, 0x8c, 0xda, 0x6b, + 0xbf, 0xeb, 0x2c, 0x5f, 0xdd, 0x6c, 0x0d, 0x45, 0xa5, 0x56, 0x92, 0xe2, 0x20, 0xc3, 0x75, 0x5b, 0xf9, 0x70, 0x71, + 0x01, 0x3d, 0x63, 0x24, 0x32, 0xcf, 0x9f, 0xc8, 0x97, 0xe0, 0x9c, 0x71, 0x56, 0x08, 0x4c, 0x18, 0xab, 0x77, 0xad, + 0xa5, 0xd2, 0x90, 0x62, 0xec, 0x68, 0x94, 0x65, 0x95, 0xa5, 0xcb, 0x6c, 0x2d, 0x61, 0xcb, 0x2a, 0x72, 0x0b, 0xbb, + 0xcd, 0x64, 0x35, 0xdf, 0x55, 0xdc, 0x41, 0xf9, 0x66, 0xab, 0x8c, 0xef, 0x25, 0xb2, 0x77, 0x1b, 0x28, 0xe1, 0xe9, + 0xe8, 0x2f, 0x48, 0xbf, 0xcd, 0x30, 0x4e, 0xb9, 0xad, 0xa4, 0x05, 0x38, 0xfd, 0xc3, 0xe1, 0x5d, 0x85, 0x41, 0x83, + 0x23, 0x8c, 0x23, 0xeb, 0xf7, 0x17, 0x95, 0x57, 0x63, 0xa2, 0x8e, 0xcf, 0xea, 0xf7, 0x2b, 0x7a, 0x38, 0xad, 0x46, + 0xab, 0x74, 0x8b, 0xec, 0x84, 0x36, 0x56, 0x7e, 0x50, 0x2b, 0x60, 0xf6, 0xd6, 0xe7, 0xd3, 0x01, 0xe8, 0x58, 0x80, + 0x44, 0xb3, 0x99, 0x48, 0xcc, 0x49, 0xf7, 0x24, 0x3c, 0x3e, 0xb0, 0xc0, 0x01, 0xa6, 0xe2, 0xff, 0x12, 0xde, 0x0c, + 0x6c, 0xd0, 0x28, 0xd1, 0xd7, 0xe8, 0xaa, 0x36, 0x37, 0x3a, 0x5e, 0x7a, 0x0a, 0x89, 0xac, 0x60, 0xd5, 0xdc, 0x97, + 0x1b, 0x38, 0xed, 0xa1, 0xe6, 0x50, 0x59, 0x82, 0xbf, 0xfd, 0x32, 0x3f, 0x1c, 0x56, 0x19, 0x14, 0xb6, 0x5b, 0x0b, + 0xed, 0x8d, 0x59, 0xaa, 0xa1, 0x22, 0x1c, 0x74, 0xbe, 0x12, 0xb3, 0x7a, 0x44, 0x7f, 0xcf, 0x0f, 0x87, 0x15, 0x81, + 0x01, 0x87, 0xa5, 0xcc, 0x44, 0x0b, 0xc5, 0xd2, 0x3a, 0x9b, 0x51, 0x1d, 0x78, 0x60, 0x62, 0xce, 0xc2, 0x1d, 0x80, + 0x36, 0xa9, 0x55, 0xa0, 0x57, 0x11, 0xfd, 0xc4, 0xfd, 0xda, 0x7e, 0xbd, 0x1e, 0x99, 0xa5, 0x23, 0x37, 0xc6, 0x02, + 0x80, 0x03, 0xcf, 0x6b, 0x92, 0xe7, 0xe4, 0x6b, 0x68, 0xf7, 0xe4, 0x42, 0xfe, 0x04, 0x65, 0x0b, 0xcf, 0x55, 0xd3, + 0xca, 0x62, 0xc5, 0x55, 0xf5, 0xea, 0x82, 0x57, 0x26, 0xd3, 0x2a, 0xad, 0x44, 0xa5, 0x04, 0x03, 0xea, 0x12, 0xaf, + 0x35, 0xcd, 0x28, 0xb5, 0x51, 0x67, 0xa2, 0x06, 0x6c, 0xb0, 0x9f, 0xaa, 0x8d, 0x4e, 0xce, 0xe5, 0xf3, 0x4b, 0xe3, + 0xf0, 0x69, 0x57, 0x6f, 0x66, 0x2a, 0x07, 0xfe, 0x5a, 0xf9, 0xd0, 0xea, 0x31, 0xd0, 0x01, 0x39, 0xfd, 0x31, 0x2c, + 0x26, 0x76, 0x87, 0xe6, 0xed, 0xee, 0xb2, 0xba, 0x48, 0xef, 0x34, 0x25, 0xb3, 0x7a, 0xcb, 0x67, 0x56, 0x8f, 0x0e, + 0x78, 0xf1, 0x50, 0xef, 0x15, 0x66, 0x12, 0xc1, 0xc5, 0x50, 0x4d, 0x22, 0xbb, 0x03, 0xad, 0x79, 0x54, 0x31, 0x01, + 0x7e, 0x50, 0x6a, 0x4d, 0xef, 0xed, 0xae, 0x50, 0xa7, 0x14, 0x1e, 0xb7, 0x96, 0xfc, 0xc0, 0xdc, 0x69, 0xd7, 0x3a, + 0x1f, 0xcf, 0x2f, 0x7d, 0xbf, 0x91, 0x27, 0xb4, 0xd9, 0x99, 0x9c, 0xfe, 0xc9, 0x5b, 0xfd, 0xc3, 0x54, 0xdf, 0x42, + 0x77, 0x82, 0x3e, 0x43, 0x57, 0x55, 0x77, 0x25, 0xb6, 0x30, 0xd4, 0x13, 0x8b, 0xbc, 0x90, 0x27, 0xad, 0xb1, 0xe3, + 0x60, 0x6f, 0x80, 0x13, 0xbf, 0x3c, 0x1c, 0xc4, 0x55, 0xee, 0xb3, 0xf3, 0xae, 0x91, 0x95, 0x03, 0x58, 0x41, 0x14, + 0x8c, 0x5b, 0xf3, 0xb1, 0x0d, 0xd2, 0x25, 0xae, 0xc6, 0xc7, 0x6f, 0x28, 0x96, 0xc9, 0x26, 0xe2, 0xe2, 0x22, 0xff, + 0xe1, 0x09, 0x90, 0x96, 0xf5, 0xfb, 0xd1, 0xd3, 0xcb, 0xe9, 0x93, 0x61, 0x14, 0x80, 0x63, 0x97, 0xbd, 0xbc, 0x8c, + 0xf9, 0xea, 0x92, 0x59, 0xa6, 0xb0, 0xc8, 0x37, 0x03, 0xaa, 0x4b, 0x56, 0x4b, 0xd7, 0x2b, 0xc0, 0xd2, 0xe5, 0x37, + 0xf7, 0x61, 0x6a, 0x40, 0x23, 0x6b, 0xee, 0x4e, 0x73, 0x2d, 0x50, 0xea, 0x79, 0x3f, 0x33, 0xe4, 0xeb, 0x32, 0xe8, + 0x0a, 0xd2, 0x3d, 0x8f, 0x48, 0x2f, 0xf7, 0xd2, 0xe9, 0x7e, 0x5f, 0x0a, 0xb0, 0xd4, 0x97, 0xe2, 0x33, 0x28, 0x2c, + 0x1a, 0xdf, 0x08, 0xd0, 0xd6, 0x50, 0x4d, 0x7b, 0xa5, 0xa8, 0x7a, 0x41, 0xaf, 0x14, 0x9f, 0x7b, 0x7a, 0xa8, 0xcc, + 0x97, 0xa5, 0xa3, 0xff, 0x09, 0x35, 0x17, 0x9c, 0x10, 0x33, 0x31, 0x07, 0x50, 0x09, 0xda, 0xf8, 0x16, 0x47, 0x1b, + 0x9f, 0xea, 0x55, 0xdc, 0xf4, 0x79, 0x6d, 0x2d, 0x73, 0x42, 0xd8, 0x74, 0x2f, 0x01, 0x2a, 0xf2, 0x4a, 0x78, 0x04, + 0xcb, 0x2f, 0x7f, 0xc8, 0xd3, 0x15, 0xa2, 0x75, 0xdc, 0xb3, 0xcc, 0xa5, 0xb1, 0x7f, 0x69, 0x30, 0x7d, 0x7d, 0xbb, + 0x2d, 0xf2, 0x53, 0x13, 0x13, 0xd6, 0x63, 0x45, 0xdf, 0xbc, 0x0d, 0x57, 0x02, 0x05, 0x0e, 0x25, 0x12, 0xdb, 0x54, + 0xa1, 0x88, 0x07, 0x49, 0x9f, 0x2e, 0x5a, 0x9f, 0x06, 0x98, 0x5a, 0xcb, 0x81, 0x39, 0x84, 0xab, 0xb8, 0xf0, 0xd1, + 0xd3, 0xb7, 0x98, 0x85, 0xf3, 0x89, 0xf7, 0xc1, 0x2b, 0x46, 0xe6, 0xe3, 0x3e, 0x2a, 0x95, 0xf4, 0xcf, 0xc3, 0x61, + 0x56, 0xcd, 0x7d, 0x87, 0x3e, 0xd2, 0x43, 0x95, 0x0b, 0xca, 0xde, 0x18, 0x93, 0x08, 0x94, 0xc6, 0x78, 0x1f, 0x07, + 0xc7, 0x79, 0x9f, 0x06, 0x90, 0xda, 0x27, 0xde, 0x91, 0x92, 0xc3, 0x73, 0x8e, 0x39, 0xa1, 0xb4, 0x22, 0xac, 0xe2, + 0xdb, 0x0c, 0xe5, 0xba, 0x53, 0x0a, 0x26, 0x39, 0x24, 0x18, 0xfe, 0xaa, 0x79, 0x13, 0x2b, 0x10, 0x76, 0xcd, 0xbc, + 0x1a, 0x3d, 0xaa, 0x92, 0xb0, 0x14, 0x71, 0xbf, 0xbf, 0xcb, 0x3c, 0xc3, 0xde, 0xf0, 0xc8, 0x30, 0x72, 0xb0, 0xdc, + 0x1f, 0xd5, 0x89, 0xc8, 0x3d, 0xba, 0xc0, 0xa8, 0x2c, 0x3c, 0x6f, 0xe8, 0x4a, 0x83, 0x4a, 0xb2, 0xe3, 0xaf, 0xb8, + 0x06, 0xd4, 0xd6, 0x18, 0x31, 0x14, 0x30, 0x0a, 0x5e, 0xdb, 0x1f, 0x42, 0x16, 0x65, 0xeb, 0x37, 0x38, 0xe6, 0x83, + 0xfb, 0x88, 0xe3, 0x1d, 0xce, 0x42, 0x4b, 0xc8, 0x93, 0x3b, 0x06, 0x69, 0x1a, 0x4b, 0x23, 0xe0, 0x44, 0x24, 0xdb, + 0x58, 0x0a, 0x47, 0x00, 0x01, 0x81, 0x6e, 0xca, 0x0c, 0x63, 0x3a, 0x18, 0x79, 0x1e, 0xf5, 0x8c, 0xf7, 0x2a, 0x3c, + 0x85, 0x34, 0xd9, 0xbe, 0x9e, 0xbf, 0x37, 0x82, 0xac, 0xdc, 0x72, 0x8e, 0x87, 0xc5, 0x37, 0xce, 0xbe, 0xca, 0xc9, + 0x53, 0xcc, 0x32, 0xd2, 0x3b, 0xc5, 0xbc, 0x80, 0x3f, 0x95, 0xa5, 0x3e, 0x47, 0xe9, 0x2d, 0xf3, 0xc9, 0x2a, 0x92, + 0x2e, 0xbd, 0x4d, 0xbf, 0x1f, 0x8f, 0xd4, 0xa1, 0xe6, 0xef, 0xe3, 0x91, 0x3c, 0xc3, 0x36, 0x2c, 0x61, 0xa1, 0x55, + 0x30, 0x06, 0x90, 0xc4, 0x46, 0x44, 0x83, 0xd1, 0xde, 0x1c, 0x0e, 0xe7, 0x1b, 0x73, 0x96, 0xec, 0xc1, 0xf5, 0x95, + 0x27, 0xe6, 0x1d, 0xf8, 0x32, 0x8f, 0x09, 0x22, 0x36, 0xf3, 0x36, 0xac, 0x06, 0x0f, 0x76, 0x70, 0x7d, 0xc4, 0x16, + 0xc5, 0x5a, 0xc7, 0x52, 0x59, 0x07, 0xa7, 0x75, 0x6c, 0x9a, 0x91, 0x52, 0x64, 0x9f, 0x63, 0x7f, 0xef, 0x06, 0x57, + 0xd7, 0xc6, 0xa0, 0xd6, 0xb8, 0xc3, 0xdc, 0x39, 0x15, 0x50, 0x8f, 0xe9, 0x0a, 0xaa, 0x67, 0x15, 0xf9, 0xf2, 0x5b, + 0x3b, 0x07, 0x04, 0x8d, 0x40, 0xe0, 0xa2, 0xf1, 0xbf, 0xeb, 0x52, 0xce, 0xbb, 0x80, 0x10, 0xdf, 0xa5, 0xa0, 0x4f, + 0x67, 0xb0, 0x89, 0xcd, 0x27, 0x10, 0x8b, 0xa6, 0xfb, 0x5c, 0x6b, 0xe6, 0x8b, 0x11, 0xed, 0xcc, 0xba, 0x5b, 0xe4, + 0x56, 0x0b, 0x91, 0x8c, 0x9e, 0x6d, 0x26, 0xdc, 0x76, 0x28, 0x67, 0x24, 0x60, 0x82, 0xd6, 0x56, 0x4a, 0x3e, 0xd7, + 0xbd, 0x4e, 0xd0, 0x1e, 0x48, 0x5a, 0xf7, 0x6f, 0x16, 0x9d, 0x51, 0x72, 0x72, 0xbd, 0xc9, 0x19, 0xa4, 0x60, 0xc1, + 0xf6, 0x32, 0x27, 0xdc, 0x00, 0x1f, 0xd9, 0x2c, 0x39, 0x4d, 0x83, 0x3c, 0x16, 0xba, 0x66, 0xef, 0xdb, 0xfc, 0xb2, + 0x80, 0x0e, 0x25, 0x8b, 0x46, 0x88, 0x07, 0xd8, 0x39, 0x24, 0x57, 0x05, 0xea, 0xa6, 0x81, 0xae, 0x5c, 0x39, 0x53, + 0x4c, 0x81, 0x0b, 0xa1, 0x20, 0x6a, 0x47, 0x27, 0x51, 0x39, 0xef, 0x93, 0xea, 0x32, 0x9f, 0x16, 0xd2, 0x34, 0x90, + 0x4f, 0x2b, 0xc7, 0x3c, 0x70, 0x67, 0x1b, 0xd7, 0x04, 0x06, 0x3a, 0xb5, 0xaf, 0x45, 0x39, 0xc7, 0x2a, 0xa2, 0xf7, + 0xf9, 0xfb, 0xca, 0x9e, 0x3e, 0x88, 0xb0, 0x51, 0x81, 0xc6, 0x52, 0x62, 0x6c, 0xe4, 0xf8, 0xb7, 0x44, 0xd9, 0x90, + 0x21, 0x20, 0x84, 0xb4, 0x91, 0xd3, 0x0f, 0x3b, 0x68, 0x25, 0xd3, 0xfe, 0x9f, 0x24, 0x7e, 0x1b, 0xec, 0xe5, 0xd4, + 0x9f, 0x7a, 0xc4, 0xe3, 0xb5, 0x46, 0x8f, 0x29, 0xe9, 0x36, 0xc8, 0x53, 0xe5, 0x29, 0x48, 0x26, 0x8c, 0x25, 0x04, + 0x8b, 0x72, 0xc1, 0x73, 0x5e, 0x71, 0x09, 0xf7, 0x51, 0xcb, 0x8a, 0x08, 0x55, 0x89, 0x9c, 0x3e, 0x5f, 0x01, 0xcf, + 0x04, 0x04, 0x3a, 0xc6, 0x48, 0xa3, 0x0a, 0xbe, 0x04, 0xc6, 0x42, 0x52, 0x76, 0x9a, 0x91, 0xe0, 0xb2, 0xfb, 0x11, + 0x89, 0x52, 0x5f, 0x90, 0x92, 0xf4, 0x8d, 0xa8, 0xf1, 0x4a, 0xac, 0x22, 0x12, 0xc8, 0x50, 0x43, 0xc4, 0xaa, 0x7a, + 0xea, 0x5e, 0x15, 0x93, 0xc1, 0xa0, 0xf2, 0xe5, 0xf4, 0xc4, 0x1b, 0x1a, 0x2a, 0xef, 0xba, 0xa2, 0x9d, 0x9e, 0x69, + 0xa5, 0xbc, 0x85, 0xb4, 0x04, 0x4d, 0xc3, 0x48, 0x73, 0x28, 0x75, 0x25, 0xdd, 0x8d, 0x41, 0x7c, 0xc9, 0x44, 0xcf, + 0x76, 0x6a, 0x47, 0x69, 0x4b, 0xda, 0x43, 0x48, 0xcf, 0x5d, 0xf2, 0x31, 0x0b, 0xb9, 0xba, 0x53, 0x4e, 0xca, 0xab, + 0x10, 0x9d, 0xdc, 0xf7, 0x18, 0x12, 0x81, 0x3e, 0xe7, 0x18, 0xd6, 0x45, 0x43, 0x9d, 0xc3, 0x0a, 0x31, 0x5b, 0x28, + 0x61, 0xbe, 0x64, 0x3c, 0x95, 0x0c, 0x1a, 0x00, 0x19, 0xf0, 0xd9, 0xcb, 0xc0, 0xf2, 0x57, 0x10, 0x3f, 0xda, 0xf8, + 0x70, 0xf8, 0x52, 0x53, 0x88, 0xed, 0x17, 0xd8, 0x0c, 0xe1, 0x51, 0x3d, 0xe0, 0x99, 0x6f, 0xe2, 0x04, 0x2d, 0x47, + 0x9c, 0xcc, 0x8e, 0x26, 0xb2, 0x57, 0x3d, 0x84, 0x53, 0x59, 0x81, 0x3a, 0xca, 0x3a, 0x2b, 0xe1, 0x47, 0x98, 0xea, + 0x56, 0x62, 0x2d, 0xd0, 0xe6, 0x6a, 0xc5, 0x5a, 0x00, 0x07, 0x7e, 0x0e, 0xc1, 0x13, 0xf9, 0x1c, 0x5c, 0x0c, 0x0a, + 0xf0, 0x39, 0x00, 0x5e, 0xe4, 0x8e, 0xce, 0xfd, 0xe9, 0x81, 0x65, 0x35, 0xc2, 0x70, 0x54, 0x11, 0xeb, 0xd7, 0x6c, + 0x47, 0x3e, 0x70, 0x3b, 0xc6, 0xe7, 0xda, 0x63, 0xc9, 0x72, 0xc2, 0xcc, 0xdc, 0xab, 0x25, 0x7a, 0xde, 0xa4, 0x71, + 0x33, 0x7a, 0xb4, 0xaf, 0xe5, 0xff, 0x82, 0x5e, 0x06, 0xfd, 0x2d, 0xdc, 0xf2, 0x9a, 0x3f, 0x2c, 0xaf, 0x01, 0xd3, + 0x2b, 0x88, 0x94, 0x51, 0x23, 0x32, 0x86, 0xb0, 0x49, 0x75, 0x73, 0x9b, 0x54, 0x17, 0x02, 0x9e, 0x8e, 0x48, 0x75, + 0x2d, 0xa4, 0x8d, 0x7c, 0x5a, 0x07, 0x32, 0x16, 0xe9, 0xed, 0x4f, 0x7f, 0x7b, 0xf6, 0xe9, 0xd5, 0xaf, 0x3f, 0x2d, + 0x5e, 0xbd, 0x7d, 0xf9, 0xea, 0xed, 0xab, 0x4f, 0xbf, 0x13, 0x84, 0xc7, 0x54, 0xa8, 0x0c, 0xef, 0xdf, 0x7d, 0x7c, + 0xe5, 0x64, 0xb0, 0x61, 0xc6, 0xb2, 0xf6, 0x8d, 0x1c, 0x0c, 0x81, 0xc8, 0x06, 0x21, 0x83, 0xec, 0x94, 0xcc, 0x31, + 0x13, 0x73, 0x8c, 0xbd, 0x13, 0x98, 0x6c, 0x81, 0xef, 0x58, 0xe6, 0x25, 0x23, 0x72, 0x55, 0x68, 0xfd, 0x80, 0x16, + 0xbc, 0x01, 0x17, 0x99, 0x34, 0xbf, 0xfd, 0x95, 0x20, 0xf6, 0x69, 0x25, 0xe5, 0xbe, 0xda, 0xd6, 0x3c, 0xdf, 0xde, + 0xef, 0x25, 0x9c, 0xff, 0x5c, 0x1a, 0x51, 0x0b, 0x70, 0x00, 0x3e, 0x87, 0x3f, 0xae, 0xb4, 0x25, 0x4d, 0x66, 0xd1, + 0x7e, 0xc6, 0x10, 0x74, 0x69, 0xf0, 0x41, 0xec, 0x91, 0x97, 0xfa, 0x64, 0x21, 0x81, 0x3b, 0x62, 0xf8, 0xb4, 0x22, + 0xe8, 0x15, 0x23, 0x8a, 0x4b, 0xae, 0x50, 0x29, 0x25, 0xff, 0x46, 0xd9, 0x45, 0x85, 0x9c, 0x15, 0xec, 0x4e, 0x91, + 0x23, 0xe3, 0x07, 0xc1, 0xc4, 0x97, 0x83, 0xfb, 0x2f, 0xf1, 0x0e, 0x67, 0x8a, 0x23, 0x39, 0xe1, 0x1f, 0x33, 0x0c, + 0xec, 0xcf, 0xc1, 0xe7, 0xd5, 0x61, 0x5e, 0xde, 0xe8, 0x53, 0x6e, 0xc9, 0xc7, 0x93, 0xe5, 0x15, 0x18, 0xec, 0x97, + 0xaa, 0xb9, 0x6b, 0x5e, 0xcf, 0x96, 0x73, 0xb6, 0x9f, 0x45, 0xf3, 0xe0, 0x96, 0xcd, 0xb2, 0x79, 0xb0, 0x6a, 0xf8, + 0x9a, 0xdd, 0xf0, 0xb5, 0x55, 0xb5, 0xb5, 0x5d, 0xb5, 0xc9, 0x86, 0xdf, 0x80, 0x84, 0x70, 0x0d, 0x7e, 0xc9, 0x09, + 0xbb, 0xf5, 0xd9, 0x06, 0x24, 0xda, 0x15, 0xdb, 0xc0, 0x45, 0x6c, 0xcd, 0x5f, 0x55, 0xde, 0x86, 0x95, 0xec, 0x7c, + 0xcc, 0x72, 0x9c, 0x7f, 0x3e, 0x3c, 0xa0, 0xbd, 0x50, 0x3f, 0xbb, 0x54, 0xcf, 0x26, 0xca, 0x6e, 0xb6, 0x19, 0x2d, + 0xee, 0xd2, 0x6a, 0x13, 0x66, 0xe8, 0x59, 0x0e, 0x1f, 0x6d, 0xa5, 0xe0, 0xa7, 0x17, 0xf8, 0x25, 0x6b, 0xe2, 0xfc, + 0x9e, 0xb6, 0xed, 0xaa, 0xc4, 0x56, 0xd0, 0xa2, 0xc8, 0x6a, 0x85, 0x07, 0xe6, 0xfc, 0x29, 0x2c, 0x60, 0xec, 0x39, + 0xce, 0x79, 0xed, 0x8f, 0x90, 0xf1, 0xde, 0x01, 0x40, 0xcb, 0x1c, 0x07, 0x78, 0xc4, 0x8a, 0x51, 0x34, 0x78, 0xe7, + 0x97, 0xca, 0x6a, 0xa5, 0x39, 0x09, 0x6d, 0x23, 0x56, 0x2d, 0x47, 0xaa, 0x66, 0x44, 0xfa, 0x20, 0x3d, 0xef, 0x7b, + 0x44, 0x35, 0xd8, 0x93, 0x79, 0x1d, 0xd8, 0xa7, 0x77, 0xad, 0x55, 0xdd, 0xf9, 0x3d, 0x55, 0xba, 0xe4, 0xc8, 0x96, + 0x9f, 0x2e, 0xc3, 0x7b, 0xf5, 0xa7, 0xe4, 0xfa, 0x50, 0xe0, 0x08, 0x0f, 0x55, 0xc0, 0xf9, 0x7a, 0x25, 0xda, 0x9d, + 0x08, 0xbb, 0x72, 0x09, 0x08, 0xf1, 0x25, 0x4d, 0x73, 0x3c, 0x8e, 0x68, 0x22, 0xc2, 0x26, 0x46, 0x7f, 0x61, 0xf7, + 0xa1, 0xc4, 0x72, 0x9e, 0x6b, 0x50, 0x72, 0xc9, 0xe0, 0x3d, 0x69, 0xaf, 0x41, 0xb3, 0xbc, 0x2a, 0x35, 0x99, 0xc8, + 0x41, 0xf9, 0x70, 0x28, 0x60, 0x2f, 0x35, 0x7e, 0x9a, 0xf0, 0x13, 0x96, 0xb7, 0xf6, 0xd6, 0x94, 0xa2, 0x92, 0x06, + 0xa8, 0xc0, 0xc7, 0x0c, 0xfe, 0x77, 0x67, 0x88, 0x05, 0x53, 0x74, 0xfc, 0x70, 0x26, 0xe6, 0xd6, 0x73, 0xab, 0xac, + 0xa3, 0x6c, 0x8d, 0x76, 0x02, 0x4e, 0x75, 0x9c, 0x24, 0xc2, 0xa9, 0xf7, 0x88, 0x8b, 0xba, 0x97, 0x43, 0xd4, 0x0d, + 0xfb, 0x54, 0xe9, 0x60, 0xcb, 0x69, 0x1a, 0x1c, 0x89, 0x5f, 0xa9, 0xcf, 0xde, 0x5b, 0x41, 0x04, 0x29, 0xb2, 0x11, + 0x25, 0x69, 0x1c, 0x8b, 0x1c, 0xb6, 0xf7, 0x85, 0xdc, 0xff, 0xfb, 0x7d, 0x08, 0x27, 0xad, 0x82, 0xb8, 0xf4, 0x04, + 0x22, 0xc2, 0xd1, 0xe1, 0x47, 0x84, 0x27, 0x52, 0x55, 0xf8, 0xbe, 0x3e, 0x71, 0x63, 0x76, 0x2f, 0xcc, 0x51, 0xbd, + 0x05, 0x18, 0xc6, 0x7a, 0x6b, 0x11, 0x92, 0x68, 0xa5, 0x19, 0x6d, 0x3d, 0x20, 0x46, 0xbc, 0x5b, 0x5b, 0x64, 0x30, + 0xd6, 0x96, 0x44, 0x02, 0xf8, 0x2d, 0x09, 0x19, 0xda, 0x36, 0x02, 0x33, 0x86, 0xb7, 0xb3, 0xe2, 0xd2, 0x75, 0xd8, + 0xe6, 0x1c, 0xbe, 0x90, 0x85, 0x66, 0x1d, 0x51, 0x9a, 0x20, 0xe4, 0x1f, 0x70, 0xb2, 0x50, 0x18, 0xcd, 0x8b, 0xa3, + 0x74, 0x92, 0x58, 0xdf, 0x75, 0x95, 0x0a, 0x36, 0x9b, 0x8f, 0xa8, 0x2f, 0x3b, 0x4a, 0xbe, 0x06, 0x27, 0x1d, 0x27, + 0x59, 0xe4, 0x20, 0x6a, 0x51, 0x39, 0x1f, 0x93, 0xb0, 0xb4, 0xab, 0x53, 0x6d, 0xd6, 0xeb, 0xa2, 0xac, 0xab, 0x17, + 0x22, 0x52, 0xf4, 0x3e, 0xea, 0xd1, 0x23, 0x09, 0xa9, 0xd0, 0xaa, 0xd4, 0x2e, 0x8f, 0xc0, 0x6d, 0x53, 0x2b, 0xb6, + 0xe5, 0x12, 0x96, 0xa8, 0xf1, 0x9f, 0xa0, 0x8f, 0x72, 0x71, 0x2f, 0x03, 0x34, 0x3a, 0x9e, 0x9a, 0xb7, 0x1e, 0x78, + 0xe5, 0x28, 0xbf, 0xb4, 0xda, 0xa4, 0x5f, 0x01, 0x99, 0xd1, 0xfe, 0xd1, 0x52, 0x02, 0x99, 0x81, 0x99, 0xb4, 0x34, + 0x24, 0x72, 0x14, 0xb3, 0x34, 0xff, 0x13, 0x57, 0x6c, 0x85, 0x48, 0xc3, 0x6a, 0xee, 0xf1, 0x9f, 0x2a, 0xaf, 0x96, + 0x6b, 0x99, 0x69, 0x6e, 0x96, 0x38, 0x56, 0x2c, 0x2e, 0xea, 0x75, 0x25, 0xb2, 0x40, 0x88, 0x23, 0x4c, 0x63, 0x3d, + 0xf5, 0x46, 0x69, 0xf5, 0x1e, 0x09, 0x65, 0x7e, 0xc2, 0xde, 0x8e, 0xbd, 0x1e, 0x64, 0x21, 0x8e, 0x2d, 0x07, 0x9b, + 0xad, 0xf7, 0xa9, 0x4c, 0x45, 0x7c, 0x56, 0x17, 0x67, 0x9b, 0x4a, 0x9c, 0xd5, 0x89, 0x38, 0xfb, 0x11, 0x72, 0xfe, + 0x78, 0x46, 0x45, 0x9f, 0xdd, 0xa7, 0x75, 0x52, 0x6c, 0x6a, 0x7a, 0xf2, 0x12, 0xcb, 0xf8, 0xf1, 0x8c, 0xb8, 0x6a, + 0xce, 0x68, 0x24, 0xe3, 0xd1, 0xd9, 0xfb, 0x0c, 0x48, 0x5e, 0xcf, 0xd2, 0x15, 0x0c, 0xde, 0x59, 0x98, 0xc7, 0x67, + 0xa5, 0xb8, 0x05, 0x8b, 0x53, 0xd9, 0xf9, 0x1e, 0x64, 0x58, 0x85, 0x7f, 0x8a, 0x33, 0x80, 0x76, 0x3d, 0x4b, 0xeb, + 0xb3, 0xb4, 0x3a, 0xcb, 0x8b, 0xfa, 0x4c, 0x49, 0xe1, 0x10, 0xc6, 0x0f, 0xef, 0xe9, 0x2b, 0xbb, 0xbc, 0xcd, 0xe2, + 0x2e, 0x8b, 0xfc, 0x29, 0x7a, 0x15, 0x11, 0x93, 0x46, 0x25, 0xbc, 0x76, 0x7f, 0xdb, 0xdc, 0x3f, 0xbc, 0x6e, 0xec, + 0x7e, 0x76, 0xc7, 0x88, 0x2e, 0xa8, 0xc7, 0x2b, 0x49, 0xa9, 0xa0, 0x80, 0xc0, 0x89, 0x66, 0x8d, 0x07, 0x77, 0x1c, + 0xf0, 0x6a, 0x60, 0x4b, 0xb6, 0xf6, 0xf9, 0xd3, 0x58, 0x86, 0x69, 0x6f, 0x02, 0xfc, 0xab, 0xec, 0x4d, 0xd7, 0xc1, + 0x12, 0xef, 0x5b, 0xc8, 0x36, 0xf4, 0xea, 0x05, 0x7f, 0xe6, 0xe5, 0xea, 0x6f, 0xf6, 0x3b, 0x00, 0x61, 0x40, 0xcc, + 0xaa, 0x8f, 0x26, 0xee, 0x9d, 0x95, 0x65, 0xe7, 0x64, 0xd9, 0xf5, 0xd0, 0xaf, 0x49, 0x8c, 0x4a, 0x2b, 0x4b, 0xe9, + 0x64, 0x29, 0x21, 0x0b, 0xf8, 0xc4, 0x68, 0x6a, 0x23, 0x80, 0xb0, 0x1d, 0xa5, 0xf2, 0x85, 0xca, 0x8b, 0x28, 0x9c, + 0x13, 0x3c, 0x4f, 0xc4, 0xe8, 0xce, 0x4a, 0x06, 0x0c, 0x87, 0x10, 0xcc, 0x41, 0x5b, 0xec, 0x0d, 0xdd, 0x44, 0xfc, + 0xf5, 0xb2, 0x28, 0x5f, 0xc5, 0xe4, 0x53, 0xb0, 0x3b, 0xf9, 0xb8, 0x84, 0xc7, 0xe5, 0xc9, 0xc7, 0x21, 0x7a, 0x24, + 0x9c, 0x7c, 0x0c, 0xbe, 0x47, 0x72, 0x5e, 0x77, 0x3d, 0x4e, 0x90, 0x5b, 0x48, 0xf7, 0xb7, 0x63, 0x12, 0xa0, 0x79, + 0x0d, 0xcb, 0x51, 0x53, 0x71, 0xcd, 0xcc, 0x18, 0xcf, 0x1b, 0xbd, 0x3f, 0x76, 0xbc, 0x65, 0x0a, 0xc5, 0x2c, 0xe6, + 0x35, 0xfc, 0x9e, 0x55, 0x81, 0xba, 0xeb, 0x6d, 0x92, 0x5b, 0x66, 0xf5, 0x1c, 0xed, 0xbe, 0xef, 0xea, 0x44, 0x50, + 0xfb, 0x3b, 0xec, 0x79, 0x66, 0xbd, 0xab, 0x62, 0xe0, 0x52, 0x25, 0x3b, 0x64, 0xaa, 0x9a, 0x1e, 0xa8, 0x94, 0x06, + 0x4f, 0x2f, 0xad, 0xcb, 0x97, 0x4a, 0x1b, 0x79, 0xa6, 0xf9, 0x0d, 0xe0, 0xc5, 0xd4, 0x65, 0xb1, 0xfb, 0xe6, 0xbe, + 0x82, 0xdb, 0x78, 0xbf, 0xbf, 0xae, 0x3c, 0xf3, 0x13, 0x17, 0x80, 0xbd, 0xa9, 0xd0, 0x3a, 0x81, 0x52, 0xc3, 0x3a, + 0xbc, 0x4e, 0x44, 0xf4, 0x67, 0xbb, 0x5c, 0x67, 0xae, 0x03, 0x46, 0x14, 0xf1, 0xdb, 0x78, 0xf4, 0x07, 0x28, 0xae, + 0x8d, 0x3d, 0x20, 0xac, 0x43, 0x42, 0x9f, 0x11, 0x80, 0xd4, 0xa3, 0x8f, 0x92, 0x3f, 0x41, 0xb3, 0xa2, 0xb9, 0x63, + 0xf2, 0x73, 0x7d, 0xa5, 0xf4, 0xf7, 0xeb, 0xca, 0x23, 0x73, 0x4a, 0xdb, 0x4c, 0x63, 0xb5, 0xa6, 0x12, 0x08, 0xaf, + 0xa8, 0x64, 0x15, 0x3e, 0x9b, 0x37, 0xa2, 0xdf, 0x97, 0x47, 0x78, 0x5a, 0xfd, 0xb4, 0xc5, 0xf8, 0x56, 0x40, 0x34, + 0x12, 0x7e, 0xbf, 0x5f, 0x01, 0xcc, 0x8b, 0x6c, 0x66, 0xf7, 0x71, 0x40, 0x95, 0x12, 0x4d, 0xe3, 0x6c, 0x9e, 0xdf, + 0xd3, 0x9b, 0xb2, 0x83, 0x4e, 0x9d, 0x2a, 0x70, 0xc1, 0x55, 0xc9, 0x78, 0x65, 0x3d, 0x91, 0xcf, 0x6f, 0x6e, 0x36, + 0x69, 0x16, 0xbf, 0x2b, 0x7f, 0xc1, 0xb1, 0xd5, 0x75, 0x78, 0x60, 0xea, 0x74, 0xed, 0x3c, 0xd2, 0xda, 0x0b, 0x01, + 0x11, 0xed, 0x1a, 0x6a, 0xbd, 0xb0, 0xd0, 0x23, 0x3d, 0x11, 0xce, 0x49, 0xa2, 0xa6, 0x1d, 0x68, 0x69, 0x84, 0xbe, + 0xbe, 0xe6, 0xf4, 0x17, 0x06, 0x6b, 0x9f, 0x8f, 0x19, 0x90, 0x95, 0xe8, 0xc7, 0xea, 0xa1, 0xb1, 0x99, 0x43, 0xcf, + 0x5a, 0x95, 0x67, 0x5e, 0x75, 0x38, 0x20, 0x3e, 0x8c, 0xfe, 0x92, 0xdf, 0xef, 0xbf, 0xa0, 0xf9, 0xc7, 0x84, 0x1a, + 0x3f, 0xdb, 0x0c, 0xd0, 0xb5, 0xef, 0xca, 0x03, 0x51, 0xcf, 0xb5, 0x4a, 0x10, 0xe2, 0x0d, 0x62, 0xa2, 0x19, 0x31, + 0x07, 0xa7, 0x1d, 0x6a, 0xfe, 0x49, 0x6a, 0x40, 0x88, 0x12, 0xaf, 0x63, 0xca, 0x82, 0x9c, 0x36, 0x71, 0xa4, 0x1f, + 0x85, 0x13, 0xf9, 0x41, 0x54, 0x45, 0x76, 0x07, 0x17, 0x0c, 0xa6, 0xde, 0xd3, 0x7e, 0x89, 0x7e, 0x4b, 0x38, 0x72, + 0x8e, 0x56, 0x85, 0x20, 0x72, 0x42, 0x58, 0x6b, 0x08, 0x13, 0xc4, 0x06, 0xf1, 0xb2, 0xef, 0x92, 0x0c, 0x47, 0x0a, + 0x2e, 0xeb, 0xd8, 0x31, 0xe6, 0xea, 0xa8, 0x7a, 0x0d, 0x60, 0xbc, 0x72, 0x04, 0xcd, 0x46, 0x91, 0x5d, 0x42, 0x54, + 0x91, 0xe3, 0x09, 0xa8, 0x1d, 0x94, 0xc6, 0x66, 0x7a, 0x3e, 0x0e, 0xf2, 0xd1, 0xa2, 0x42, 0x9d, 0x13, 0xcb, 0x78, + 0x0d, 0xc0, 0xda, 0xb9, 0xea, 0xe7, 0x59, 0x0d, 0x9e, 0x34, 0xc4, 0xe7, 0x63, 0xb4, 0xbd, 0xb2, 0x39, 0xa8, 0xb6, + 0xd3, 0x59, 0x79, 0xc5, 0x74, 0x39, 0x30, 0xee, 0x1b, 0x5e, 0x51, 0x9c, 0xe1, 0x07, 0x0f, 0xb6, 0x38, 0x7f, 0xba, + 0xa1, 0xf6, 0x63, 0x6e, 0xd4, 0xc3, 0x40, 0x6b, 0xc1, 0x9b, 0x82, 0x58, 0x7f, 0xdf, 0x75, 0x64, 0x7b, 0xa7, 0x45, + 0x46, 0x93, 0xcf, 0x7e, 0xfe, 0xbe, 0x4c, 0x57, 0x29, 0xdc, 0x97, 0x9c, 0x2c, 0x9a, 0x79, 0x08, 0xec, 0x0d, 0x31, + 0x5c, 0x1f, 0x15, 0x1e, 0x51, 0xd6, 0xef, 0xc3, 0xef, 0xab, 0x0c, 0x4c, 0x31, 0x70, 0x5d, 0x21, 0x18, 0x0f, 0x81, + 0x20, 0x1e, 0xa6, 0xd1, 0xc9, 0xa0, 0x06, 0x6d, 0xf8, 0x06, 0x20, 0x33, 0xc0, 0x23, 0x73, 0xe9, 0x11, 0x70, 0x17, + 0xb8, 0xf6, 0x64, 0x3c, 0xf6, 0x27, 0xa6, 0xa1, 0x51, 0x53, 0x9a, 0xe9, 0xb9, 0xf1, 0x9b, 0x8e, 0x6a, 0xb9, 0x76, + 0xfe, 0xe3, 0x4b, 0x7e, 0x83, 0x5e, 0xd0, 0xf2, 0x72, 0x1f, 0xa9, 0xcb, 0x7d, 0x46, 0x71, 0x99, 0x48, 0x0e, 0x0b, + 0x62, 0x59, 0xc2, 0x81, 0xc7, 0xa8, 0x64, 0xb1, 0xa5, 0xc7, 0xaa, 0x68, 0xf9, 0xa2, 0xdc, 0x20, 0x1d, 0x3a, 0x21, + 0x58, 0xa2, 0x82, 0x60, 0x09, 0x8c, 0x8b, 0x58, 0xf3, 0xcd, 0x20, 0x67, 0xf1, 0x6c, 0x33, 0xe7, 0x48, 0x58, 0x97, + 0x1c, 0x0e, 0x85, 0x04, 0x9b, 0xc9, 0x66, 0xeb, 0x39, 0x5b, 0xfb, 0x0c, 0x94, 0x00, 0xa5, 0x4c, 0x13, 0x94, 0xa6, + 0x15, 0x5b, 0x71, 0xd3, 0x1a, 0xac, 0x56, 0x53, 0xb6, 0xaa, 0x29, 0x3b, 0xa7, 0x29, 0x47, 0x15, 0x94, 0x9c, 0x50, + 0x8a, 0x32, 0x0c, 0x60, 0xc4, 0x26, 0xd1, 0x55, 0x86, 0x3e, 0xde, 0x09, 0x8f, 0xa0, 0x8a, 0x88, 0x7c, 0xc2, 0x10, + 0x02, 0x13, 0x51, 0x5c, 0xa8, 0x42, 0x31, 0x40, 0x46, 0x24, 0x10, 0x4c, 0x54, 0xea, 0x14, 0x98, 0x8f, 0xa6, 0x8a, + 0x61, 0xd3, 0x9e, 0x28, 0xdf, 0x53, 0xc7, 0x3d, 0xca, 0x36, 0xff, 0x10, 0xbb, 0x20, 0x44, 0xee, 0xc6, 0x9d, 0xfa, + 0x19, 0xf1, 0xde, 0xee, 0x08, 0xe3, 0x27, 0x3b, 0x6e, 0x11, 0xae, 0x08, 0xb6, 0x54, 0x73, 0x88, 0xc5, 0xbc, 0x9a, + 0x24, 0xa8, 0x65, 0x49, 0xfc, 0x0d, 0x4f, 0x06, 0x39, 0x5b, 0x82, 0x07, 0xed, 0x9c, 0x65, 0x80, 0xbf, 0x62, 0xb5, + 0xe8, 0xf7, 0xda, 0x5b, 0x82, 0xfc, 0xb4, 0xb1, 0x1b, 0x85, 0x89, 0x11, 0x24, 0xea, 0x76, 0x65, 0x20, 0x3f, 0xbc, + 0xc7, 0xe9, 0x78, 0xec, 0x29, 0x63, 0x6e, 0x65, 0x7a, 0x99, 0xce, 0x95, 0x7c, 0x23, 0xf7, 0xd2, 0x87, 0x5e, 0x82, + 0x9d, 0x03, 0xde, 0x40, 0xda, 0xc0, 0x8f, 0xb0, 0x5d, 0x78, 0x6d, 0x90, 0x30, 0x23, 0xc0, 0x16, 0xc7, 0xc7, 0x48, + 0x09, 0x0c, 0xe1, 0x38, 0x4b, 0x01, 0x98, 0x46, 0x5f, 0x66, 0x2b, 0xfb, 0x32, 0xab, 0x35, 0x5b, 0x2a, 0xa7, 0x7b, + 0xe7, 0xd6, 0xed, 0x7c, 0x26, 0x01, 0xc0, 0xa4, 0xce, 0x81, 0x38, 0x33, 0xc1, 0x2e, 0x4d, 0x22, 0xcb, 0x87, 0x30, + 0xbf, 0x15, 0x2f, 0xcb, 0x62, 0xa5, 0xba, 0xa2, 0xed, 0x33, 0x93, 0xcf, 0x48, 0x27, 0xa1, 0x02, 0x0a, 0x0a, 0xb9, + 0xd6, 0xa7, 0x6f, 0xc3, 0xb7, 0x41, 0xa1, 0x81, 0xd9, 0x2a, 0xdc, 0xd3, 0x64, 0x8d, 0xd4, 0x1b, 0x55, 0xbf, 0x4f, + 0xae, 0x81, 0x54, 0x67, 0x0e, 0x2d, 0x7b, 0x56, 0x61, 0x80, 0xd8, 0x51, 0x9f, 0x91, 0x50, 0x07, 0x52, 0x0f, 0x18, + 0x42, 0xb4, 0x4d, 0x1f, 0x7f, 0x32, 0x24, 0xba, 0x00, 0x5b, 0x88, 0x36, 0xf0, 0xe3, 0x4f, 0xb0, 0xcf, 0x82, 0xf0, + 0x98, 0xe6, 0x6f, 0x20, 0xe9, 0xd8, 0xc0, 0x69, 0xf5, 0x29, 0xf8, 0x20, 0xc9, 0xc1, 0x44, 0x1d, 0xbc, 0xdc, 0x5f, + 0xfa, 0x7d, 0xd8, 0xb2, 0x73, 0x29, 0xd5, 0xb1, 0x52, 0x6f, 0xdb, 0xda, 0x0f, 0xa2, 0x2d, 0x38, 0xb2, 0x88, 0xbf, + 0xcf, 0x10, 0x11, 0xcc, 0x0c, 0x22, 0xec, 0x5a, 0xa8, 0xbb, 0x3d, 0xa5, 0x96, 0x45, 0xbd, 0xed, 0x29, 0xa5, 0x6e, + 0xc3, 0xf0, 0xdd, 0x04, 0x33, 0xc5, 0x0d, 0x7f, 0x93, 0x79, 0xa1, 0xde, 0x78, 0x8c, 0x63, 0xfc, 0xda, 0xf3, 0xf7, + 0x4b, 0x5e, 0xcd, 0x36, 0xca, 0x84, 0x79, 0xcb, 0x97, 0xb3, 0x50, 0x76, 0xb5, 0x34, 0xee, 0x7c, 0xf6, 0x96, 0x6a, + 0x3e, 0xf8, 0x87, 0x43, 0x02, 0xf1, 0x46, 0xf1, 0xd5, 0x6d, 0x23, 0xb7, 0xae, 0xc9, 0xe6, 0xaa, 0x04, 0xd4, 0xef, + 0xf3, 0x35, 0xee, 0xb7, 0x58, 0xff, 0xee, 0x69, 0x90, 0xb1, 0x9a, 0xe1, 0x8a, 0x29, 0x7c, 0x0a, 0x00, 0x83, 0xc3, + 0xa9, 0x20, 0x2d, 0xf0, 0x86, 0x97, 0xc3, 0xcb, 0xc9, 0x86, 0x4c, 0xba, 0x1b, 0x1f, 0xb9, 0xb3, 0x40, 0xd5, 0xfb, + 0x1d, 0xc5, 0x49, 0x83, 0x44, 0x63, 0xaf, 0xc1, 0x67, 0x59, 0x46, 0xb9, 0x68, 0xe2, 0x3e, 0x24, 0x5f, 0xe9, 0x01, + 0xcc, 0x55, 0x28, 0x01, 0xa2, 0xdf, 0x58, 0x16, 0x1b, 0xd1, 0xb6, 0xd8, 0xc0, 0x52, 0xaa, 0xe6, 0x7a, 0x35, 0x7d, + 0xf6, 0x4a, 0x34, 0xef, 0xa3, 0x19, 0xa7, 0x34, 0x1a, 0x70, 0x9c, 0x46, 0xe1, 0xf6, 0xdd, 0x9d, 0x28, 0x97, 0x19, + 0x58, 0xb2, 0x55, 0x38, 0xc5, 0x65, 0xa3, 0xce, 0x88, 0x67, 0x79, 0xac, 0x00, 0x3a, 0x1e, 0x12, 0x00, 0xd5, 0x05, + 0x01, 0x15, 0xd1, 0x52, 0x7a, 0x2b, 0xb4, 0x58, 0xa8, 0x37, 0x1c, 0xa5, 0xf0, 0x47, 0xfa, 0xf3, 0x20, 0x9f, 0x02, + 0x10, 0xbb, 0x3e, 0x8e, 0x5e, 0x16, 0x25, 0x7d, 0xaa, 0x98, 0xe5, 0x72, 0x30, 0x81, 0x5d, 0x9d, 0xc8, 0x50, 0x2b, + 0xc8, 0x5b, 0x75, 0xe5, 0xad, 0x4c, 0xde, 0xc6, 0x38, 0x25, 0x3f, 0x70, 0xd3, 0xb1, 0x46, 0x0c, 0xbc, 0xf2, 0xb4, + 0x4e, 0x13, 0xa4, 0xc9, 0x05, 0x30, 0x0c, 0xf1, 0xfb, 0xcc, 0x7b, 0xe6, 0x39, 0x52, 0x15, 0x24, 0xb3, 0xbb, 0xcc, + 0x53, 0x17, 0x51, 0x7d, 0xe5, 0xd4, 0xd2, 0x99, 0xd3, 0x8f, 0x00, 0xde, 0x63, 0x6a, 0xd2, 0x90, 0x8f, 0x70, 0x5b, + 0x8a, 0xaf, 0xb7, 0xea, 0x1a, 0x2f, 0x8d, 0xce, 0xdd, 0xcb, 0x97, 0xee, 0x34, 0xe8, 0xa7, 0x20, 0x28, 0xe7, 0xb3, + 0x52, 0xc0, 0x9e, 0x32, 0x9b, 0xeb, 0xd5, 0xaa, 0x15, 0x5a, 0x87, 0xc3, 0x58, 0x3b, 0x0a, 0x69, 0x75, 0x16, 0xb0, + 0xd5, 0x48, 0xa7, 0x04, 0x08, 0xc1, 0x71, 0x1a, 0x76, 0x82, 0x71, 0x97, 0x4e, 0x23, 0xb2, 0x5e, 0x29, 0x49, 0x17, + 0x66, 0x90, 0xfc, 0x93, 0xbc, 0x9e, 0x01, 0x2d, 0x01, 0x1c, 0x8a, 0x58, 0xc2, 0xc3, 0x49, 0x72, 0x05, 0xd0, 0xe9, + 0x70, 0x50, 0x69, 0x68, 0xce, 0x6a, 0x96, 0xcc, 0x27, 0xb1, 0x54, 0x55, 0x1e, 0x0e, 0x9e, 0x72, 0x33, 0xe8, 0xf7, + 0xb3, 0x69, 0xa9, 0x5c, 0x00, 0x82, 0x58, 0x17, 0x06, 0x88, 0x47, 0x5a, 0x78, 0xb2, 0xe8, 0x53, 0x12, 0xbf, 0x9c, + 0x25, 0x73, 0x93, 0x0d, 0xef, 0xc0, 0x08, 0x36, 0xe3, 0xba, 0xa4, 0x4c, 0x7b, 0x54, 0x7e, 0xcf, 0xe8, 0xa9, 0xed, + 0x6b, 0xad, 0xb6, 0x88, 0x75, 0x1d, 0x5c, 0x95, 0xa8, 0xa7, 0xf8, 0xa0, 0x24, 0xc1, 0xfb, 0x85, 0x73, 0x33, 0x52, + 0xbe, 0x16, 0xb9, 0x1f, 0xb4, 0x33, 0xb5, 0x72, 0xe0, 0x08, 0xe4, 0x58, 0x45, 0x25, 0xaf, 0x77, 0x1d, 0x82, 0x47, + 0x77, 0xa5, 0x02, 0xe5, 0xe0, 0xa7, 0x20, 0x46, 0xd7, 0x57, 0x9d, 0x35, 0xd4, 0x4c, 0xa3, 0xca, 0x23, 0xe8, 0xd4, + 0x01, 0x3c, 0x29, 0x78, 0xa9, 0xd5, 0x8f, 0x87, 0x83, 0x67, 0x7e, 0xf0, 0x77, 0x99, 0xbe, 0x85, 0x98, 0x28, 0xa7, + 0x1a, 0x21, 0x71, 0xa5, 0x24, 0x11, 0x1f, 0x2f, 0x5a, 0x56, 0x8c, 0xca, 0xf0, 0x9e, 0x57, 0xaa, 0x7c, 0x75, 0xaa, + 0xf2, 0x62, 0xa4, 0x6d, 0x09, 0xbc, 0x26, 0xff, 0x10, 0xb9, 0xe6, 0xad, 0xaf, 0xbb, 0xca, 0xd0, 0x47, 0xb2, 0x02, + 0x1d, 0xc1, 0x56, 0x96, 0x92, 0x03, 0x3e, 0xa9, 0xee, 0xaa, 0x55, 0xeb, 0x73, 0xca, 0x36, 0xc2, 0x4d, 0x7e, 0x1d, + 0x3b, 0x38, 0x52, 0x7e, 0x83, 0xe7, 0x02, 0xd8, 0x6b, 0xc0, 0xde, 0x9c, 0xb3, 0xa2, 0x79, 0x70, 0x48, 0xdb, 0x02, + 0x8d, 0xcc, 0xdc, 0xce, 0xd5, 0x7d, 0x5b, 0x1e, 0xa5, 0x31, 0x44, 0xa6, 0x3d, 0x30, 0x1d, 0x6c, 0x46, 0xf9, 0xef, + 0x29, 0xbf, 0x55, 0x38, 0x06, 0xbe, 0x9d, 0x7a, 0x07, 0x50, 0xf5, 0xb4, 0x41, 0xc6, 0x9a, 0x61, 0x68, 0x65, 0x97, + 0x4b, 0xa1, 0x25, 0x68, 0xa9, 0x9b, 0x20, 0x38, 0x3f, 0x22, 0xca, 0x11, 0x80, 0x2e, 0x52, 0xc0, 0x04, 0x3f, 0xa5, + 0xed, 0xee, 0xf7, 0xd7, 0xa9, 0x47, 0xee, 0x5d, 0xa1, 0x46, 0x09, 0x25, 0x18, 0xfb, 0x89, 0xc6, 0x0c, 0x3a, 0xba, + 0x22, 0x27, 0x3c, 0x6b, 0x75, 0x58, 0xd7, 0x4d, 0x19, 0x94, 0xc5, 0x31, 0xaf, 0xa6, 0xb3, 0x3f, 0x1e, 0xed, 0xeb, + 0x06, 0x59, 0xc8, 0xff, 0x60, 0x3d, 0x24, 0x83, 0xee, 0x41, 0x28, 0x44, 0x6f, 0x1e, 0xcc, 0xf0, 0x3f, 0xb6, 0xe1, + 0xd9, 0x77, 0xdc, 0xa8, 0x13, 0xc4, 0x1c, 0x71, 0xbc, 0xf4, 0x14, 0x6d, 0x3d, 0xdc, 0x02, 0xd9, 0x1a, 0x2f, 0x6f, + 0xed, 0x35, 0x90, 0x53, 0x1c, 0xff, 0x2d, 0xcf, 0xd4, 0xca, 0x06, 0x3f, 0x3d, 0x65, 0x3b, 0xf0, 0xf0, 0x22, 0x04, + 0x14, 0xc3, 0xb2, 0xf1, 0xb7, 0x96, 0xe3, 0x8c, 0xfe, 0x9b, 0x47, 0x0c, 0x83, 0x45, 0xe4, 0xc7, 0x97, 0xa5, 0x10, + 0x5f, 0x85, 0xf7, 0xa9, 0xf2, 0x6e, 0xc9, 0x29, 0xf3, 0x56, 0x0f, 0xa3, 0xeb, 0x92, 0xf4, 0x5d, 0xf2, 0xb1, 0x35, + 0x6c, 0x7f, 0x68, 0xf7, 0x9b, 0x21, 0x82, 0x10, 0xca, 0xf1, 0x73, 0x46, 0x27, 0x34, 0x3e, 0xac, 0x66, 0xa7, 0xd7, + 0xef, 0x9d, 0xe3, 0x05, 0x5b, 0xa3, 0x01, 0x1e, 0x0f, 0x5d, 0xcc, 0x13, 0x35, 0x74, 0xba, 0xae, 0x9d, 0x83, 0x07, + 0x06, 0x59, 0x9e, 0x7c, 0xc7, 0xb0, 0xc4, 0xfe, 0x24, 0xe2, 0x49, 0x5b, 0xb5, 0xb1, 0x39, 0x52, 0x6d, 0xd4, 0x0c, + 0xfc, 0xe0, 0x15, 0x14, 0x18, 0x5d, 0x90, 0x16, 0x60, 0x1c, 0x8e, 0x00, 0x64, 0xc5, 0x38, 0x1e, 0x19, 0x4c, 0x60, + 0x48, 0x37, 0x14, 0x05, 0xe0, 0xe1, 0x71, 0x3c, 0x08, 0x19, 0x40, 0xba, 0xe0, 0xa1, 0x61, 0x9b, 0x84, 0x94, 0x9f, + 0xe7, 0x79, 0xad, 0x86, 0xd0, 0x77, 0x16, 0xaa, 0x63, 0x3f, 0xd2, 0x5e, 0xb1, 0xae, 0x55, 0xe9, 0xc8, 0x56, 0x07, + 0xe8, 0x1b, 0x32, 0xf0, 0xad, 0x63, 0x0b, 0x80, 0x68, 0x89, 0x2f, 0xa9, 0x57, 0xfb, 0x32, 0x66, 0x85, 0x7a, 0x7d, + 0x61, 0xda, 0xf5, 0x42, 0x5a, 0x14, 0x50, 0x71, 0xdb, 0xaa, 0xed, 0x91, 0x9c, 0xff, 0xf0, 0xae, 0xa3, 0x1d, 0x9f, + 0x9d, 0x1a, 0x5b, 0x42, 0x99, 0x5b, 0x3c, 0x91, 0xd5, 0xd1, 0x96, 0xea, 0x54, 0x1f, 0x70, 0xa9, 0x49, 0x75, 0x66, + 0x60, 0x78, 0x8d, 0x00, 0xe5, 0x16, 0x22, 0x69, 0x1c, 0xf6, 0xce, 0x27, 0x83, 0x82, 0xb9, 0x45, 0x02, 0x12, 0xd8, + 0xc6, 0xd6, 0x2e, 0x9a, 0xeb, 0xd7, 0x97, 0xd4, 0xab, 0xda, 0x54, 0xf5, 0xe0, 0x8d, 0x17, 0x38, 0x7b, 0xa7, 0xb5, + 0x80, 0x00, 0x0a, 0x5b, 0xcb, 0x72, 0x70, 0xee, 0x76, 0x55, 0x4b, 0x45, 0x19, 0xf5, 0xfb, 0xe7, 0x5f, 0x52, 0x54, + 0xc4, 0x9e, 0x2a, 0x4e, 0x59, 0xbf, 0xdd, 0x32, 0x17, 0x95, 0x25, 0x6f, 0x50, 0x45, 0x6b, 0x75, 0xd4, 0x54, 0xae, + 0x9b, 0xab, 0x96, 0x4c, 0x10, 0xa3, 0xfb, 0x74, 0xad, 0x73, 0xa7, 0xde, 0x7b, 0x15, 0x47, 0x0c, 0x04, 0x37, 0xdd, + 0xe3, 0x83, 0x83, 0xd0, 0xa8, 0x28, 0x17, 0xdc, 0x28, 0xad, 0x2a, 0x29, 0x85, 0xbc, 0x55, 0xd1, 0x9c, 0xe9, 0x23, + 0x00, 0x22, 0xc0, 0x2a, 0x51, 0xff, 0x87, 0x2f, 0x8d, 0xf1, 0xe0, 0x81, 0xaf, 0xc9, 0x75, 0x6c, 0xbd, 0x7f, 0x5a, + 0x23, 0xad, 0x36, 0x8e, 0x49, 0xad, 0x7a, 0xd9, 0x2a, 0x5e, 0x76, 0xaf, 0x53, 0x31, 0x78, 0xfe, 0x3f, 0xf7, 0x01, + 0x6a, 0x44, 0x4b, 0x19, 0xdc, 0xba, 0x1a, 0xa0, 0xf1, 0xe1, 0x58, 0xf8, 0xc6, 0x0f, 0x19, 0xe7, 0x83, 0x19, 0x3a, + 0xaa, 0xcd, 0xc1, 0x01, 0xc1, 0x51, 0xdd, 0xa3, 0x31, 0x61, 0x16, 0xce, 0x3d, 0x08, 0x54, 0x9f, 0xb8, 0xcf, 0xb8, + 0xf6, 0x82, 0x36, 0x81, 0x4f, 0xd6, 0x75, 0x4d, 0x11, 0xe0, 0x22, 0x36, 0x26, 0x62, 0x88, 0xcb, 0x26, 0x91, 0xfa, + 0x66, 0x0c, 0x0a, 0x80, 0xe2, 0x69, 0x45, 0x72, 0xe9, 0x22, 0xcd, 0x2b, 0x51, 0xd6, 0xba, 0x19, 0x15, 0x2b, 0x86, + 0x00, 0xf0, 0x10, 0x14, 0x57, 0x95, 0x99, 0xd0, 0x88, 0x0d, 0xa4, 0xb2, 0x14, 0xac, 0x1a, 0x16, 0x7e, 0xd3, 0x7e, + 0x93, 0x9c, 0xf4, 0xce, 0xc7, 0xad, 0x73, 0xc7, 0xbe, 0x77, 0x14, 0x52, 0xda, 0x43, 0x31, 0x41, 0x10, 0xfc, 0xb4, + 0x0e, 0xe7, 0xcf, 0xf8, 0x53, 0x02, 0x53, 0x91, 0xcd, 0x18, 0x70, 0x10, 0x22, 0x32, 0xe3, 0xf7, 0x1c, 0x3e, 0xe5, + 0xe5, 0x24, 0x1c, 0x0e, 0x7d, 0xd0, 0x87, 0xf2, 0x6c, 0x16, 0x0e, 0xc5, 0x5c, 0x7a, 0xaf, 0x83, 0xb5, 0x2e, 0xe4, + 0xf5, 0x24, 0x44, 0xb4, 0xd0, 0xd0, 0x07, 0xe7, 0x75, 0xd7, 0x1c, 0x61, 0x09, 0x40, 0x13, 0x47, 0x5f, 0xd6, 0xef, + 0x47, 0x9e, 0x36, 0xb4, 0x48, 0x71, 0xd1, 0x28, 0xb3, 0x59, 0x2e, 0x3b, 0x61, 0xe3, 0xda, 0x2d, 0x10, 0x8a, 0x87, + 0x69, 0x0b, 0x55, 0xeb, 0xa9, 0x5e, 0xcf, 0x4d, 0xbb, 0xef, 0x1e, 0x54, 0xab, 0x1c, 0xe9, 0xac, 0x4d, 0x57, 0x6a, + 0x75, 0xcb, 0xa8, 0x5a, 0x67, 0x69, 0x44, 0x95, 0x9b, 0xe4, 0xae, 0x51, 0x0b, 0x3e, 0xd9, 0xd0, 0x65, 0xca, 0xce, + 0xd6, 0xe0, 0xc4, 0x91, 0xe7, 0x92, 0x5b, 0xbe, 0x3b, 0xaf, 0xe8, 0xee, 0x54, 0xfb, 0x16, 0xe0, 0xde, 0x0c, 0x1b, + 0x32, 0xe7, 0x35, 0x76, 0x1a, 0x84, 0x49, 0xe0, 0x47, 0xec, 0x63, 0x86, 0x6c, 0x30, 0xa0, 0xa3, 0x90, 0xfe, 0xd7, + 0x96, 0x39, 0x12, 0x30, 0xf9, 0xeb, 0xb9, 0xdf, 0x2c, 0x8a, 0x1c, 0x16, 0xe3, 0xfb, 0x0d, 0x46, 0x1a, 0xab, 0x35, + 0x18, 0x96, 0xb7, 0x88, 0xfc, 0xa9, 0xdd, 0x31, 0x4d, 0x75, 0xbc, 0x59, 0xaf, 0x35, 0xbf, 0x7a, 0xfa, 0x54, 0xd7, + 0xe7, 0xbf, 0x7d, 0x7f, 0x19, 0xd6, 0xcc, 0xfe, 0x10, 0x84, 0xd2, 0xee, 0xdd, 0xe2, 0xdc, 0x91, 0xe8, 0x1d, 0x2b, + 0xcd, 0xec, 0xd2, 0x2e, 0xd9, 0xa5, 0x29, 0xed, 0x23, 0xb9, 0x5e, 0x7d, 0xa3, 0xbc, 0xb1, 0xf3, 0x8a, 0xe9, 0xfe, + 0xbd, 0xd0, 0x3b, 0xca, 0xa9, 0x9a, 0x40, 0x44, 0x93, 0x76, 0x24, 0x6e, 0xf7, 0xca, 0xf0, 0xc9, 0x24, 0x6f, 0x97, + 0x70, 0xd4, 0x35, 0x2c, 0x37, 0xdf, 0xfe, 0x25, 0xaf, 0x3a, 0x2b, 0xdc, 0x7e, 0x69, 0xcc, 0xda, 0x9f, 0x82, 0xb8, + 0xaa, 0x3f, 0xbd, 0xf7, 0x35, 0x53, 0xf2, 0x7f, 0xd5, 0x63, 0xe0, 0xea, 0x27, 0xd3, 0x8e, 0xee, 0x29, 0x84, 0x0d, + 0x66, 0x3f, 0x3f, 0x7e, 0x68, 0xd1, 0x35, 0xba, 0x40, 0x91, 0x1c, 0x40, 0xe7, 0x2e, 0x19, 0xe1, 0xfd, 0x8e, 0x71, + 0xee, 0x5f, 0xfd, 0xaa, 0x26, 0x47, 0x88, 0x68, 0x17, 0xe1, 0x00, 0x20, 0xee, 0x34, 0x95, 0x75, 0xa8, 0x01, 0xfa, + 0x80, 0xc0, 0x3a, 0xf4, 0x6d, 0x06, 0x70, 0xd0, 0x47, 0x9b, 0x67, 0x11, 0xc8, 0xeb, 0xde, 0x1d, 0xbb, 0x66, 0x3b, + 0x9f, 0x3f, 0x5d, 0xa5, 0xde, 0x1d, 0x3a, 0x04, 0x9f, 0x8f, 0xfd, 0xe9, 0x65, 0xa0, 0xd5, 0x9e, 0xd7, 0xec, 0xfa, + 0xb1, 0x60, 0x3b, 0xb6, 0x7b, 0x8c, 0x48, 0x45, 0xdd, 0xf9, 0x87, 0x97, 0x26, 0x7a, 0xde, 0x79, 0xe1, 0x96, 0x2f, + 0x01, 0x3c, 0x90, 0xc5, 0x80, 0xe2, 0xb3, 0xf4, 0x7e, 0x61, 0x09, 0xa8, 0xc9, 0x6f, 0xf8, 0xda, 0x7b, 0x4b, 0xa9, + 0x0b, 0xf8, 0x73, 0x40, 0xe9, 0x93, 0x9c, 0x7b, 0xb7, 0xc3, 0x1b, 0xff, 0xe2, 0x09, 0x38, 0x4f, 0xac, 0x86, 0x0b, + 0xf8, 0xab, 0xe0, 0x43, 0xef, 0x76, 0x80, 0x89, 0x25, 0x1f, 0x7a, 0xab, 0x01, 0xa4, 0x2a, 0x5c, 0x48, 0x8c, 0x7d, + 0xf8, 0x2d, 0xc8, 0x19, 0xfe, 0xf1, 0xbb, 0xc6, 0x60, 0xfd, 0x2d, 0x28, 0x34, 0x1a, 0x6b, 0xa9, 0x42, 0x96, 0x62, + 0x71, 0x26, 0xc0, 0x26, 0x1c, 0x77, 0xfb, 0x62, 0x55, 0x9b, 0xb5, 0xa0, 0x3f, 0x1f, 0xf0, 0x3d, 0x1a, 0xab, 0xab, + 0x72, 0x2e, 0xca, 0x0f, 0x48, 0x9f, 0xea, 0xf8, 0x18, 0x15, 0x9b, 0xba, 0x3b, 0x9d, 0x6a, 0xd5, 0x91, 0xf6, 0xbb, + 0x72, 0x0d, 0x76, 0xbc, 0x4e, 0x8e, 0x2c, 0x85, 0x67, 0x1d, 0x76, 0x5e, 0x3a, 0x25, 0x3a, 0x0c, 0xe3, 0xdd, 0x56, + 0x3d, 0x63, 0x28, 0xcf, 0x0d, 0xc6, 0x74, 0xc1, 0x23, 0xfe, 0x74, 0x90, 0xcb, 0xd0, 0x98, 0x77, 0xc8, 0x86, 0xa1, + 0x7c, 0x68, 0x91, 0x21, 0x21, 0xe2, 0x3d, 0x54, 0x02, 0xb6, 0x2d, 0x28, 0x93, 0x02, 0xce, 0xa2, 0xc1, 0xef, 0xb5, + 0x97, 0x03, 0xef, 0x41, 0xe4, 0x37, 0xd2, 0xa5, 0x5c, 0x62, 0xa3, 0x13, 0xc7, 0xb2, 0xd0, 0xce, 0xe3, 0xfa, 0xeb, + 0x18, 0xd4, 0xef, 0x95, 0x7e, 0x83, 0x72, 0xf6, 0x07, 0xc9, 0x3a, 0x6d, 0x3c, 0x31, 0xfe, 0xed, 0x2a, 0xff, 0x14, + 0x2d, 0xf5, 0xf0, 0xff, 0x19, 0x53, 0x28, 0xfd, 0x75, 0x5a, 0x46, 0x9b, 0xd5, 0x52, 0x94, 0x22, 0x8f, 0xc4, 0xc9, + 0xd7, 0x22, 0x3b, 0x97, 0xef, 0x7c, 0x0a, 0xfd, 0x02, 0xd0, 0xb2, 0x4f, 0x90, 0xd1, 0xbf, 0x32, 0xc1, 0x87, 0xbf, + 0x6a, 0xe7, 0xda, 0x9c, 0x8f, 0x27, 0xf9, 0x95, 0xb5, 0x77, 0x3b, 0x5e, 0x24, 0x46, 0x31, 0x96, 0xfb, 0xaa, 0x9b, + 0x95, 0x13, 0x95, 0x1c, 0x18, 0xe9, 0x9a, 0xec, 0xe5, 0x4a, 0xd6, 0xed, 0x74, 0x2b, 0x81, 0x88, 0x2a, 0xf0, 0x1e, + 0xe3, 0x2a, 0xf6, 0x11, 0x4c, 0xd7, 0x1d, 0x97, 0xd1, 0x8e, 0xf7, 0x8c, 0x57, 0x27, 0xca, 0x0a, 0x6e, 0x37, 0xa2, + 0x3d, 0xa1, 0xa3, 0x9f, 0x26, 0xb5, 0x65, 0xe1, 0x00, 0xe4, 0x2e, 0x61, 0x2c, 0x1b, 0x82, 0x15, 0x83, 0xd2, 0xd7, + 0x6b, 0x4a, 0x96, 0x05, 0x58, 0x74, 0x76, 0x19, 0x81, 0x18, 0xd6, 0x4d, 0x73, 0x42, 0xc7, 0x4b, 0x17, 0xe7, 0xbd, + 0x56, 0x91, 0x82, 0x67, 0xb4, 0xe8, 0x98, 0x9b, 0x8e, 0x74, 0x63, 0xb4, 0xb7, 0xcf, 0x0d, 0x42, 0x8a, 0xe7, 0x0f, + 0x6c, 0xb5, 0x2e, 0x2e, 0x12, 0xaf, 0x90, 0x89, 0x16, 0xc4, 0x52, 0x04, 0x66, 0xbc, 0xd0, 0x34, 0xc2, 0x04, 0x65, + 0x4a, 0xb0, 0x68, 0x8d, 0x0e, 0xed, 0x0f, 0x4b, 0xd8, 0x3d, 0xc6, 0x08, 0x10, 0xa8, 0x32, 0xfd, 0x1a, 0xb6, 0x26, + 0xcc, 0xa6, 0x2e, 0x36, 0x40, 0x5b, 0xc5, 0xd0, 0x20, 0xac, 0x0d, 0x31, 0x1f, 0xd2, 0xfc, 0xf6, 0x5f, 0x58, 0x8c, + 0xed, 0x09, 0xc4, 0xf6, 0x6e, 0xd7, 0x24, 0x4c, 0xf7, 0x5a, 0xdc, 0x58, 0x2f, 0xb7, 0xa7, 0x1c, 0x53, 0x3b, 0xd6, + 0x46, 0xed, 0x58, 0x4b, 0xbd, 0x63, 0xad, 0xf5, 0x8e, 0x75, 0xdb, 0xf0, 0x67, 0x99, 0x17, 0xb3, 0x04, 0xf4, 0xbb, + 0x2b, 0xae, 0x1a, 0x04, 0xcd, 0xd8, 0xb0, 0x1b, 0xf8, 0x2d, 0xb1, 0x76, 0x4b, 0xff, 0x62, 0xc9, 0x16, 0xa6, 0x0f, + 0x74, 0xeb, 0x00, 0xcb, 0x88, 0x9a, 0x7c, 0x87, 0xbc, 0x9b, 0xce, 0x8a, 0xc2, 0xed, 0x89, 0x2d, 0x7c, 0x76, 0x6d, + 0xde, 0xbc, 0x7b, 0x1c, 0x41, 0xee, 0x1d, 0xf7, 0xee, 0x86, 0xd7, 0xfe, 0x85, 0x6e, 0x81, 0x9c, 0xcc, 0x72, 0x06, + 0x52, 0x47, 0x7c, 0x82, 0x68, 0x65, 0x4f, 0xf9, 0x4e, 0xc8, 0x9d, 0x6d, 0xfd, 0xf8, 0xce, 0xdd, 0xd6, 0x6e, 0x1f, + 0xdf, 0xb1, 0x6a, 0x44, 0xb1, 0xe2, 0x34, 0x45, 0xc2, 0x2c, 0xda, 0x00, 0x4f, 0xbd, 0x7c, 0xbf, 0x63, 0xc7, 0x1c, + 0xee, 0x1e, 0x77, 0x74, 0xbc, 0x9c, 0x03, 0x76, 0xf7, 0x1f, 0x6d, 0xc2, 0xc6, 0x4a, 0xd7, 0x2a, 0x74, 0xb8, 0x7b, + 0x9c, 0x69, 0x3c, 0x87, 0x23, 0xf9, 0x74, 0xac, 0xb1, 0x41, 0x50, 0xd7, 0xe7, 0x0c, 0x6a, 0xc7, 0xee, 0x6b, 0xc2, + 0x2e, 0x3b, 0xe6, 0xb5, 0xae, 0x79, 0x7b, 0xe5, 0xa9, 0xd8, 0x10, 0xd0, 0xe1, 0x6b, 0x75, 0x83, 0xfc, 0x4b, 0xe0, + 0x14, 0x01, 0x20, 0x87, 0xe3, 0x25, 0x8f, 0x7d, 0x9f, 0x66, 0x69, 0xbd, 0x43, 0xad, 0x45, 0x65, 0x59, 0x86, 0xb5, + 0xf7, 0x83, 0x56, 0x0c, 0x4b, 0x4d, 0xff, 0x74, 0x1c, 0xb8, 0x9d, 0xed, 0x56, 0xc6, 0x2e, 0xe3, 0x71, 0x71, 0xf1, + 0xeb, 0x69, 0xa1, 0x5c, 0xbb, 0x79, 0x1b, 0xbf, 0x69, 0xb5, 0x64, 0x69, 0xad, 0x87, 0xbc, 0xb4, 0x2c, 0x22, 0x10, + 0xc0, 0x70, 0xa4, 0xec, 0x62, 0x09, 0xf7, 0x08, 0xab, 0x7b, 0x10, 0x4a, 0xe6, 0x85, 0x8b, 0x27, 0x2c, 0x86, 0x44, + 0x80, 0xed, 0x0e, 0x15, 0xdb, 0xc2, 0xc5, 0x13, 0xb6, 0xe1, 0x45, 0xbf, 0x9f, 0xa9, 0x4e, 0x21, 0xeb, 0xce, 0x92, + 0x6f, 0x54, 0x73, 0xac, 0xa1, 0x66, 0x6b, 0x93, 0x6c, 0x8d, 0x73, 0x5b, 0xf1, 0x71, 0xdb, 0x56, 0x7c, 0xac, 0xac, + 0x75, 0xe9, 0x5e, 0xef, 0x51, 0x5d, 0x00, 0x5b, 0xff, 0xcd, 0xf1, 0xca, 0xf5, 0x7c, 0x46, 0x00, 0x5f, 0x0b, 0x3e, + 0x9e, 0x2c, 0xd0, 0xab, 0x64, 0xe1, 0xdf, 0x0c, 0xd4, 0xf8, 0x3b, 0x9d, 0xbb, 0x00, 0xe8, 0x4a, 0xca, 0x2b, 0x20, + 0xef, 0x20, 0xc7, 0xdc, 0xb2, 0x2b, 0xef, 0x4e, 0xbe, 0xc3, 0xae, 0x79, 0x3d, 0x5b, 0xcc, 0xd9, 0x0e, 0x9c, 0x0a, + 0x92, 0x81, 0xbd, 0xac, 0xd8, 0x2e, 0x88, 0xed, 0x84, 0xdf, 0x09, 0x98, 0xf2, 0x19, 0x04, 0x71, 0x05, 0x37, 0x10, + 0x87, 0x27, 0xff, 0x1c, 0xdc, 0xb5, 0x36, 0xeb, 0x3b, 0x66, 0x75, 0x4e, 0xb0, 0x66, 0x56, 0x0f, 0x06, 0xcb, 0x66, + 0xb2, 0xea, 0xf7, 0xbd, 0x9d, 0x76, 0x7c, 0xba, 0x95, 0x3a, 0xb1, 0xd3, 0x5a, 0xad, 0x05, 0xbb, 0x96, 0x5a, 0x17, + 0x63, 0xe8, 0x01, 0xe2, 0xa7, 0x9b, 0x01, 0xbf, 0xeb, 0x58, 0x5b, 0xde, 0x35, 0x5b, 0xb0, 0x1d, 0x5c, 0x82, 0x9a, + 0xf6, 0xb2, 0x3f, 0xa9, 0x5c, 0xd0, 0x8e, 0x5d, 0x12, 0x0f, 0x67, 0xcc, 0x2a, 0x65, 0x66, 0x9d, 0x54, 0x57, 0xa2, + 0x33, 0xa6, 0xb3, 0xd6, 0xf3, 0xb9, 0x9a, 0x4f, 0x0a, 0x0d, 0xea, 0x77, 0x4e, 0x7c, 0x44, 0x45, 0xe7, 0x09, 0x6c, + 0x2d, 0x2b, 0x88, 0xd5, 0x3e, 0x07, 0x6b, 0xad, 0x76, 0xe9, 0xf7, 0xf2, 0x01, 0xb7, 0x29, 0x87, 0x75, 0x60, 0x50, + 0x73, 0x62, 0x45, 0x3d, 0x64, 0x3b, 0xc6, 0xcd, 0x4f, 0x2f, 0x7f, 0x70, 0xc2, 0x92, 0x15, 0xab, 0xfd, 0xe9, 0xaf, + 0x8f, 0x3d, 0xfd, 0x9d, 0xda, 0xbf, 0x10, 0x7e, 0x30, 0xfe, 0x4f, 0xed, 0xbe, 0xd6, 0x62, 0x54, 0xb6, 0xca, 0x11, + 0x1a, 0x77, 0x2b, 0x69, 0xb2, 0xfc, 0x24, 0x3c, 0x61, 0x2d, 0x78, 0x96, 0xeb, 0x25, 0x9a, 0x15, 0xb0, 0xc2, 0x5a, + 0x26, 0xe1, 0x0a, 0x63, 0xb5, 0xb4, 0xd5, 0xb7, 0x68, 0x9a, 0xe3, 0xc3, 0xb9, 0x36, 0x28, 0x53, 0xce, 0xce, 0x88, + 0xd5, 0x70, 0x19, 0x96, 0x26, 0x14, 0x21, 0xbb, 0xb7, 0x83, 0x1b, 0x3b, 0x65, 0x29, 0x65, 0x38, 0xc7, 0x60, 0xc2, + 0x23, 0x31, 0xaa, 0xf2, 0xfd, 0x7d, 0x49, 0x91, 0xd3, 0xb6, 0x1c, 0x54, 0x21, 0xec, 0x23, 0x89, 0x12, 0xb8, 0x15, + 0x69, 0xa1, 0x48, 0x59, 0xfc, 0xed, 0x00, 0x5d, 0xe0, 0x05, 0xd4, 0xd5, 0xa8, 0xdb, 0x1f, 0x8e, 0x78, 0xf8, 0xc0, + 0xd4, 0x07, 0x46, 0x2c, 0x09, 0xd4, 0xf6, 0x2c, 0x4b, 0x6f, 0x41, 0x85, 0xdf, 0xc3, 0xd5, 0x44, 0xec, 0xe7, 0x96, + 0x14, 0x15, 0xd9, 0x48, 0x6f, 0x68, 0x0d, 0x1e, 0xa1, 0x35, 0xe5, 0xb9, 0x93, 0x6a, 0x93, 0xce, 0x3b, 0x42, 0x8e, + 0xd5, 0xb7, 0x96, 0x30, 0xda, 0x15, 0xbd, 0xb8, 0x77, 0xf4, 0x9e, 0xa7, 0xab, 0x9e, 0xfb, 0x13, 0x57, 0xcc, 0x93, + 0xdb, 0x08, 0xd4, 0xad, 0xa0, 0xba, 0xbd, 0x53, 0x09, 0x16, 0x2c, 0x69, 0xf7, 0xf1, 0xdb, 0x59, 0x3b, 0x10, 0x95, + 0xb1, 0x4a, 0xdf, 0x92, 0x84, 0x3d, 0x31, 0xe8, 0x14, 0xaa, 0x72, 0xbb, 0x3b, 0xda, 0x02, 0xd7, 0x31, 0x4b, 0xd1, + 0x33, 0x5b, 0xe4, 0x6e, 0xf9, 0x77, 0xcf, 0x15, 0x39, 0xfb, 0x25, 0x20, 0x38, 0x35, 0xdf, 0x10, 0x5f, 0x8e, 0xf0, + 0xa8, 0xba, 0x05, 0x8e, 0xd3, 0x77, 0x00, 0xff, 0x70, 0xb8, 0x04, 0x4d, 0x40, 0x2c, 0x58, 0x2f, 0x8d, 0x7b, 0xac, + 0x17, 0x17, 0x9b, 0xdb, 0x24, 0xdf, 0x80, 0x33, 0x03, 0xa5, 0x5a, 0xfa, 0x81, 0x63, 0xb5, 0x80, 0x0a, 0x07, 0xb3, + 0x93, 0x7a, 0x61, 0x19, 0xf5, 0x98, 0x3e, 0x3f, 0x83, 0xbd, 0x23, 0x24, 0x00, 0xee, 0x97, 0x7d, 0x40, 0x02, 0x1e, + 0x3a, 0xb3, 0x03, 0xc2, 0x09, 0xb3, 0xa8, 0x0a, 0x24, 0x92, 0x23, 0xfd, 0xec, 0x31, 0x13, 0xc9, 0x1f, 0xcc, 0x7a, + 0xce, 0x29, 0xd1, 0x63, 0x3d, 0x75, 0x84, 0xf4, 0x58, 0xcf, 0x3a, 0x22, 0x7a, 0xac, 0x67, 0x1d, 0x1f, 0x3d, 0xd6, + 0x33, 0xc7, 0x4e, 0x0f, 0x02, 0x13, 0x20, 0xf2, 0x80, 0xf5, 0x68, 0x32, 0xf5, 0x14, 0xf7, 0x00, 0xd1, 0x20, 0xb0, + 0x9e, 0x14, 0xce, 0x7b, 0x80, 0x3c, 0x46, 0x62, 0x75, 0xd0, 0xfb, 0xcb, 0xf8, 0x87, 0x9e, 0x91, 0x91, 0xc7, 0xad, + 0xc3, 0xea, 0x7f, 0xfd, 0x15, 0x02, 0xe0, 0xf0, 0x6c, 0xea, 0x5d, 0x8e, 0x21, 0xab, 0x2c, 0x23, 0x90, 0xfc, 0xc4, + 0xe0, 0xcb, 0x17, 0x00, 0x55, 0x9f, 0xe9, 0x5a, 0x4d, 0x8e, 0xda, 0x63, 0x0e, 0x5d, 0x31, 0x00, 0x6c, 0xc3, 0x12, + 0x55, 0xb5, 0xb0, 0x09, 0x8b, 0xdb, 0xcf, 0x30, 0x9a, 0xcb, 0xa6, 0x17, 0x34, 0x50, 0x8f, 0x10, 0xfc, 0xd2, 0x7a, + 0x68, 0xad, 0x65, 0xca, 0xa1, 0x6b, 0xa3, 0xa8, 0xb2, 0xa1, 0x2e, 0x61, 0xb5, 0x16, 0x51, 0x4d, 0x14, 0x29, 0x97, + 0x8c, 0xa2, 0x58, 0xaa, 0x60, 0x9f, 0x89, 0x5b, 0x88, 0x9a, 0xa7, 0xad, 0xb6, 0x0a, 0xf6, 0xb7, 0x80, 0xb0, 0x16, + 0xd6, 0x42, 0x3a, 0x83, 0xda, 0x3b, 0xfd, 0x48, 0xf9, 0xcb, 0x0b, 0xb9, 0x9d, 0x5b, 0x28, 0xc2, 0xed, 0x39, 0x28, + 0x6f, 0xea, 0xaa, 0x54, 0x44, 0xa3, 0x25, 0x50, 0xca, 0x9c, 0x20, 0xb2, 0x00, 0x01, 0x1c, 0x37, 0x10, 0xf8, 0xbc, + 0xc6, 0x27, 0xd0, 0x28, 0x04, 0xf2, 0x03, 0xab, 0x70, 0xed, 0x21, 0x2d, 0xb5, 0x46, 0x44, 0x89, 0xf8, 0xd1, 0xd5, + 0x73, 0x6c, 0x5f, 0x3d, 0x8d, 0xb5, 0xa5, 0x34, 0x41, 0xfc, 0xc4, 0x62, 0x0b, 0x31, 0x41, 0x54, 0x87, 0xe8, 0x08, + 0x96, 0x13, 0x42, 0x14, 0xfe, 0x14, 0xfa, 0xa9, 0x81, 0xbf, 0x64, 0xcb, 0x22, 0xaf, 0x09, 0x16, 0xb3, 0x62, 0x80, + 0x56, 0x45, 0xe0, 0x99, 0xce, 0x96, 0xca, 0x9c, 0xe6, 0xd1, 0x91, 0x1d, 0x9c, 0x77, 0x1d, 0xec, 0xa5, 0x2f, 0x63, + 0x27, 0xcb, 0xa6, 0x51, 0x1b, 0x1b, 0x22, 0xe1, 0x15, 0xf9, 0x75, 0x96, 0x1a, 0xe7, 0xc8, 0x5c, 0xae, 0xef, 0xba, + 0xb8, 0xbd, 0xa5, 0x6d, 0xc2, 0x2a, 0x44, 0xa8, 0xdb, 0x86, 0xca, 0xa5, 0x30, 0x1b, 0x9b, 0xa6, 0x01, 0xbe, 0x50, + 0x54, 0x2a, 0x55, 0xa9, 0xad, 0x54, 0x72, 0xc2, 0xbb, 0xbe, 0xa9, 0x45, 0xea, 0x8a, 0x60, 0x1b, 0x33, 0xd4, 0x43, + 0xb9, 0x51, 0x63, 0xdf, 0x76, 0xac, 0xd2, 0x3b, 0x4c, 0x90, 0x33, 0xf2, 0x22, 0x07, 0x17, 0x25, 0x05, 0x99, 0xab, + 0x21, 0xcc, 0x1f, 0x34, 0x7c, 0x5a, 0x58, 0xee, 0xa1, 0x04, 0xcc, 0x8e, 0x1a, 0x1e, 0x45, 0x08, 0x44, 0x5c, 0x2a, + 0xfb, 0x8a, 0x89, 0xdf, 0x53, 0x30, 0x4b, 0x26, 0x74, 0x2f, 0x62, 0x59, 0x84, 0x36, 0x3e, 0x49, 0x92, 0xa9, 0xa7, + 0x29, 0xb8, 0x91, 0xcb, 0x30, 0x47, 0x23, 0xb4, 0xe4, 0x23, 0x07, 0xd2, 0xd7, 0x72, 0x2a, 0xc1, 0x47, 0xd4, 0x29, + 0xe0, 0x78, 0x7e, 0x5e, 0x58, 0x3f, 0x59, 0x2e, 0x31, 0x97, 0xb5, 0xf9, 0x2f, 0x3b, 0x3a, 0x06, 0xbb, 0x3c, 0x4d, + 0x1c, 0x57, 0xff, 0x51, 0x95, 0x14, 0xf7, 0xaf, 0xd3, 0x1c, 0x50, 0x04, 0x33, 0x7b, 0x8a, 0xf1, 0xb1, 0xcf, 0x32, + 0x05, 0xfc, 0xed, 0x7a, 0x6b, 0xc9, 0xc4, 0x2e, 0x69, 0x37, 0x57, 0xc6, 0x2f, 0xb5, 0x61, 0xc7, 0xc1, 0xb9, 0x01, + 0x28, 0xce, 0x1a, 0x1d, 0x96, 0xd7, 0xba, 0x6d, 0x55, 0xa8, 0x40, 0xad, 0xff, 0xb3, 0x5b, 0x98, 0xf2, 0x36, 0x2f, + 0x95, 0xb7, 0x79, 0x68, 0x02, 0x04, 0x22, 0x33, 0xe4, 0x59, 0xd3, 0x31, 0x49, 0xdc, 0x3b, 0x52, 0xd2, 0xbe, 0x23, + 0xc5, 0x0f, 0xde, 0x91, 0x90, 0x6f, 0x09, 0x1d, 0xd9, 0x97, 0x9c, 0x9c, 0x40, 0x99, 0xc1, 0x5e, 0x5e, 0x33, 0xd9, + 0x3f, 0xa0, 0xbd, 0x70, 0x2e, 0xcb, 0x2b, 0xfe, 0x46, 0x78, 0x6b, 0x7f, 0xba, 0x3e, 0xed, 0xaa, 0x7a, 0xf3, 0x8d, + 0x99, 0x79, 0x38, 0x14, 0x87, 0x43, 0x65, 0x82, 0x76, 0x17, 0x5c, 0x0c, 0x72, 0x76, 0xe7, 0xc6, 0xc7, 0x5f, 0x73, + 0x14, 0xb1, 0x95, 0xf2, 0x48, 0xba, 0x50, 0x89, 0xe1, 0xa5, 0x81, 0x87, 0xd9, 0xf1, 0xf1, 0x64, 0x77, 0x75, 0x37, + 0x19, 0x0c, 0x76, 0xaa, 0x6f, 0xb7, 0xbc, 0x9e, 0xed, 0xe6, 0xec, 0x9e, 0xdf, 0x4c, 0xb7, 0xc1, 0xbe, 0x81, 0x6d, + 0x77, 0x77, 0x25, 0x0e, 0x87, 0xdd, 0x53, 0xbe, 0xf0, 0xf7, 0xf7, 0x08, 0xe8, 0xcc, 0xcf, 0xc7, 0x6d, 0x8c, 0x9f, + 0x37, 0x6d, 0x57, 0xad, 0x1d, 0xc0, 0xd3, 0xbf, 0xf2, 0xde, 0xcc, 0x96, 0x73, 0x9f, 0xbd, 0xe7, 0xf7, 0xe0, 0x9f, + 0x8f, 0x9b, 0x24, 0x52, 0x9f, 0x68, 0x97, 0xc9, 0x37, 0xe0, 0x40, 0xbe, 0xf3, 0xd9, 0x27, 0x7e, 0x3f, 0x5b, 0xce, + 0x79, 0x71, 0x38, 0x3c, 0x9a, 0x86, 0x48, 0xd6, 0x14, 0x56, 0xc4, 0x92, 0xe2, 0xf9, 0x41, 0x78, 0xfc, 0x5e, 0x44, + 0x86, 0x48, 0xcb, 0xbd, 0x3b, 0x64, 0x6f, 0x58, 0xe4, 0x07, 0xf0, 0x41, 0xb6, 0xf3, 0x27, 0xb2, 0xa6, 0x74, 0xbf, + 0x78, 0xef, 0x1f, 0x0e, 0xf4, 0xd7, 0x27, 0xff, 0x70, 0x78, 0xc4, 0xee, 0x11, 0x1c, 0x9d, 0xef, 0xa0, 0x7f, 0xf4, + 0xad, 0x03, 0xaa, 0x32, 0xbc, 0x9e, 0x6d, 0xe6, 0xfe, 0xd3, 0x15, 0xbb, 0x05, 0x2e, 0x14, 0xe5, 0x85, 0xf6, 0x86, + 0xdd, 0xa3, 0xd7, 0x19, 0x39, 0x11, 0xcd, 0x76, 0x73, 0x9f, 0xc5, 0xf8, 0x5c, 0xdd, 0x17, 0x93, 0x6f, 0xde, 0x17, + 0x77, 0x6c, 0xdb, 0x7d, 0x5f, 0x94, 0x6f, 0xba, 0xeb, 0x67, 0xcb, 0x76, 0xec, 0x1e, 0x66, 0xd8, 0x35, 0x7f, 0xd3, + 0x1c, 0x3b, 0xc6, 0x7e, 0xf3, 0xc6, 0x08, 0xa0, 0xcc, 0x16, 0x2c, 0x16, 0x1c, 0x94, 0x6a, 0xd5, 0xb6, 0x24, 0xf2, + 0x4a, 0x07, 0xaa, 0xcd, 0x08, 0xee, 0xab, 0x85, 0x9c, 0x79, 0x66, 0xa0, 0x6f, 0x2b, 0x44, 0x0b, 0x87, 0x0d, 0xf8, + 0x1b, 0x6d, 0x1d, 0x63, 0x98, 0x66, 0x35, 0xd3, 0xb6, 0xa8, 0xcb, 0xef, 0x7b, 0xcf, 0xe4, 0x37, 0x32, 0xb0, 0x85, + 0x48, 0x0a, 0xc7, 0xf1, 0xc5, 0x93, 0x13, 0xfe, 0xab, 0x96, 0x47, 0xad, 0xf6, 0x0b, 0xa5, 0x3e, 0xbd, 0xa6, 0x23, + 0x9a, 0xb8, 0x17, 0x6d, 0x19, 0xd6, 0x28, 0x6b, 0x6a, 0xe9, 0x30, 0x8c, 0x6b, 0xd8, 0x97, 0x07, 0x0e, 0x7d, 0x07, + 0x04, 0xda, 0x2a, 0x95, 0x02, 0x2d, 0x1c, 0xc3, 0x28, 0xcc, 0x42, 0xca, 0xc3, 0xc2, 0x2c, 0xe5, 0x3d, 0x16, 0x68, + 0x71, 0xab, 0xee, 0x31, 0xb5, 0xdd, 0x82, 0x08, 0xab, 0xb7, 0x8c, 0xf3, 0xcb, 0x46, 0x15, 0x6e, 0x0b, 0x50, 0x14, + 0x41, 0x19, 0xec, 0x49, 0x6e, 0x5b, 0x28, 0x69, 0x36, 0x0a, 0x6b, 0x71, 0x5b, 0x94, 0xbb, 0x5e, 0xc3, 0x16, 0x78, + 0x41, 0xd5, 0x4f, 0x08, 0xdb, 0xb2, 0x67, 0x1d, 0xca, 0x45, 0xfa, 0x1f, 0x59, 0x7a, 0xbe, 0xdf, 0x9a, 0xf3, 0x3f, + 0x7d, 0x45, 0x1f, 0x95, 0xff, 0xf9, 0x25, 0xfd, 0x64, 0xb0, 0x8c, 0x9c, 0x52, 0xbf, 0x44, 0xa3, 0x9b, 0x34, 0x27, + 0x8c, 0x2d, 0x5f, 0x3f, 0xfd, 0x0e, 0x99, 0x82, 0xe4, 0x50, 0x4a, 0x55, 0x4e, 0xf6, 0xd0, 0x17, 0x5e, 0xf7, 0x61, + 0x26, 0x18, 0x80, 0xf0, 0x1a, 0x6d, 0xaa, 0x09, 0x93, 0x78, 0x70, 0x05, 0xff, 0x37, 0x82, 0x18, 0xb4, 0x4f, 0x14, + 0x75, 0x6c, 0x1b, 0xe9, 0xba, 0xed, 0x1c, 0x24, 0x77, 0xea, 0xca, 0x1f, 0x95, 0x93, 0xff, 0x44, 0x43, 0xe4, 0x15, + 0x57, 0x88, 0x95, 0x05, 0x97, 0x58, 0x0c, 0x15, 0x29, 0xc0, 0x35, 0x04, 0x91, 0xb2, 0x28, 0x29, 0xdc, 0x72, 0x50, + 0x15, 0x01, 0x18, 0x57, 0xab, 0xa3, 0x4e, 0x84, 0x8f, 0x5b, 0x6b, 0x11, 0x82, 0x15, 0x8d, 0x5a, 0x59, 0x2b, 0xf0, + 0x05, 0xe9, 0x4b, 0x87, 0x82, 0x98, 0x1e, 0x85, 0x54, 0x95, 0x0e, 0x05, 0xd2, 0x1c, 0x2a, 0xbe, 0x31, 0xd8, 0x28, + 0x2a, 0xd2, 0xf3, 0x97, 0x26, 0x25, 0x97, 0xc6, 0x8c, 0xf7, 0xa2, 0x8c, 0x44, 0x5e, 0x87, 0xb7, 0x62, 0x5a, 0x20, + 0xdf, 0xe8, 0xf1, 0x83, 0xe0, 0x12, 0xde, 0x0d, 0xb9, 0x57, 0x80, 0x2d, 0x01, 0x3b, 0xc0, 0xbd, 0x32, 0xa3, 0x5c, + 0xa7, 0x75, 0xfd, 0xd6, 0x7a, 0x28, 0x86, 0xe1, 0x63, 0x4b, 0x60, 0x3b, 0x5a, 0x47, 0x47, 0x7a, 0xf8, 0xf0, 0xbf, + 0xae, 0x6a, 0x8e, 0x3a, 0x95, 0xcb, 0xd9, 0xf1, 0x84, 0xa5, 0x88, 0x19, 0x74, 0x7f, 0xdd, 0x5e, 0x0b, 0xa0, 0xdb, + 0x65, 0x31, 0xcf, 0x46, 0x3b, 0xf9, 0xb7, 0x74, 0x63, 0x45, 0x69, 0x13, 0xef, 0xb2, 0xde, 0xd8, 0x1f, 0x8e, 0xfe, + 0xf2, 0xf8, 0xed, 0x84, 0x50, 0x75, 0x36, 0x6c, 0xad, 0xe3, 0x5c, 0xfe, 0xd7, 0x5f, 0xc7, 0x64, 0x05, 0x41, 0x41, + 0x58, 0x76, 0x8a, 0x89, 0x0a, 0x46, 0x91, 0x62, 0xcd, 0xc7, 0x93, 0x35, 0xea, 0x84, 0xd7, 0xfe, 0x52, 0xeb, 0x84, + 0x89, 0x91, 0x95, 0xca, 0x5f, 0xb3, 0x8a, 0xdd, 0xaa, 0xcc, 0x02, 0x32, 0x0f, 0xf2, 0xc9, 0xda, 0x68, 0x30, 0x57, + 0xbc, 0x9e, 0xad, 0xe7, 0x52, 0xf9, 0x0c, 0xa6, 0x9c, 0xe5, 0xe0, 0x64, 0x29, 0xec, 0x8e, 0x04, 0x8a, 0xd6, 0x0c, + 0x5d, 0xfb, 0x53, 0x6c, 0xd5, 0x8b, 0xb4, 0xaa, 0x01, 0x1e, 0x10, 0x62, 0x60, 0xa8, 0xbd, 0x5a, 0x78, 0x68, 0x2d, + 0x80, 0xb5, 0x3f, 0x2a, 0xfd, 0x60, 0x3c, 0x59, 0xf2, 0x05, 0xf2, 0x2f, 0x47, 0x8e, 0xda, 0xbd, 0xdf, 0xf7, 0xee, + 0x40, 0x0a, 0x8e, 0x5c, 0x0b, 0x05, 0x12, 0x01, 0x2d, 0xf8, 0xc6, 0x57, 0x3e, 0x18, 0xd7, 0xa8, 0xad, 0x06, 0x05, + 0xb5, 0xa3, 0x5b, 0x1e, 0x3b, 0x7a, 0xe7, 0xbb, 0x13, 0xfa, 0xea, 0x85, 0x16, 0x8e, 0xbf, 0x71, 0x46, 0xae, 0xd9, + 0xaa, 0x43, 0x8e, 0x68, 0x26, 0x1d, 0x42, 0xc4, 0x8a, 0xad, 0xd9, 0x35, 0xa9, 0x9c, 0x3b, 0x87, 0xec, 0xf4, 0x11, + 0xaa, 0xf4, 0x5a, 0x0f, 0x6f, 0x27, 0x4a, 0x77, 0x7b, 0xbc, 0x9b, 0x7c, 0xcf, 0x26, 0x22, 0x06, 0x03, 0xda, 0x20, + 0x9c, 0x91, 0x75, 0x88, 0x54, 0x3a, 0x40, 0x08, 0x1c, 0x13, 0xd0, 0xf4, 0xdf, 0xdf, 0x92, 0x28, 0xe0, 0x48, 0x1b, + 0x21, 0x6b, 0xd9, 0xe1, 0x90, 0x83, 0x46, 0xb9, 0xf9, 0xd3, 0x2b, 0xd4, 0x69, 0x0e, 0xcc, 0xd3, 0x25, 0xec, 0x39, + 0x78, 0xa4, 0x17, 0xc7, 0x47, 0xfa, 0x7f, 0x47, 0x13, 0x35, 0xfe, 0xcf, 0x35, 0x51, 0x4a, 0x8b, 0xe4, 0xa8, 0x96, + 0xbe, 0x4b, 0x1d, 0x05, 0x17, 0x79, 0x47, 0x2d, 0x64, 0xcf, 0xb2, 0x71, 0xa3, 0x9a, 0xf7, 0xff, 0x6b, 0x65, 0xfe, + 0xbf, 0xa6, 0x95, 0x61, 0x4a, 0x76, 0x2c, 0xd5, 0xcc, 0x03, 0xad, 0x62, 0x98, 0xbd, 0x26, 0x09, 0x91, 0xe1, 0xd2, + 0x80, 0x1f, 0x55, 0xb0, 0x8f, 0xd3, 0x6a, 0x9d, 0x85, 0x3b, 0x54, 0xa2, 0xde, 0x88, 0xdb, 0x34, 0x7f, 0x56, 0xff, + 0x5b, 0x94, 0x05, 0x4c, 0xed, 0xdb, 0x32, 0x8d, 0x03, 0xb2, 0xf0, 0x67, 0x61, 0x89, 0x93, 0x1b, 0xdb, 0xf8, 0x5a, + 0x8e, 0xa7, 0xfd, 0xaa, 0x33, 0xf3, 0x40, 0x02, 0x35, 0xb0, 0x94, 0xe4, 0x5c, 0x56, 0x16, 0xf7, 0x08, 0xdd, 0xfc, + 0x53, 0x59, 0x16, 0xa5, 0xd7, 0xfb, 0x94, 0xa4, 0xd5, 0xd9, 0x4a, 0xd4, 0x49, 0x11, 0x2b, 0x28, 0x9b, 0x14, 0x60, + 0xf4, 0x61, 0xe5, 0x89, 0x38, 0x38, 0x43, 0xa0, 0x86, 0xb3, 0x3a, 0x09, 0x01, 0x68, 0x58, 0x21, 0xec, 0x9f, 0x41, + 0x0b, 0xcf, 0xc2, 0x38, 0x5c, 0x03, 0x4c, 0x4e, 0x5a, 0x9d, 0xad, 0xcb, 0xe2, 0x2e, 0x8d, 0x45, 0x3c, 0xea, 0x29, + 0x4a, 0x96, 0xb7, 0xb9, 0x2b, 0xe7, 0xfa, 0xfb, 0x3f, 0x29, 0x80, 0xdd, 0x80, 0xd9, 0xb6, 0xc0, 0x0e, 0x00, 0x12, + 0x14, 0xc8, 0x16, 0xea, 0x34, 0x3a, 0x53, 0x4b, 0x05, 0xde, 0x73, 0x3d, 0xc0, 0xdf, 0xe6, 0x80, 0x65, 0x5c, 0x17, + 0x32, 0x60, 0x04, 0x01, 0x8c, 0xc0, 0x41, 0x09, 0x18, 0x3a, 0x43, 0xdc, 0x56, 0xe5, 0xac, 0x85, 0xe6, 0x4a, 0xb7, + 0x25, 0x37, 0x8d, 0x72, 0xb6, 0x12, 0x01, 0xf4, 0xd5, 0x4d, 0x89, 0xd3, 0xe5, 0xb2, 0x95, 0x84, 0x7d, 0xfb, 0xae, + 0x9d, 0x2a, 0xf2, 0xf8, 0x28, 0x0d, 0x79, 0x05, 0x7e, 0xca, 0x38, 0x92, 0x44, 0x89, 0xe0, 0x6d, 0xde, 0x98, 0x71, + 0x78, 0xd5, 0xa6, 0x9c, 0xda, 0x9b, 0xf5, 0x02, 0x70, 0x9e, 0xa0, 0x2d, 0x03, 0x8c, 0x05, 0x0c, 0xce, 0x85, 0x58, + 0xf2, 0x14, 0xc1, 0x2f, 0x9d, 0x48, 0x61, 0xdc, 0xe5, 0x30, 0xcc, 0x83, 0xa2, 0x77, 0x49, 0xfd, 0xd1, 0xef, 0xa3, + 0x36, 0x19, 0x0c, 0x41, 0x25, 0x80, 0xca, 0xba, 0x41, 0x62, 0x60, 0x55, 0x5a, 0x48, 0x5c, 0x42, 0xbc, 0xcc, 0x57, + 0xd3, 0x34, 0x0a, 0x1e, 0xd5, 0x13, 0x42, 0x38, 0xc1, 0xf8, 0x10, 0x37, 0x40, 0xc0, 0x60, 0x15, 0x17, 0x18, 0x24, + 0xcf, 0x25, 0xba, 0x3f, 0x9e, 0xef, 0x18, 0xe0, 0xca, 0x79, 0x4f, 0xb5, 0xab, 0x07, 0xf6, 0x72, 0x95, 0x2e, 0x19, + 0x21, 0xac, 0xf8, 0xbf, 0x88, 0xbc, 0x6f, 0x87, 0x09, 0xa8, 0x6d, 0xe4, 0x8f, 0x41, 0x62, 0x2e, 0x13, 0x45, 0x10, + 0x8f, 0xb2, 0x82, 0x25, 0x69, 0xb0, 0x19, 0x25, 0x29, 0x68, 0x34, 0x31, 0x86, 0x4c, 0x85, 0x76, 0x48, 0x1a, 0xcd, + 0xc6, 0x64, 0x1f, 0x43, 0x5e, 0xc3, 0xc5, 0x62, 0x81, 0xf7, 0xbd, 0x16, 0xaa, 0x83, 0x6d, 0x69, 0x0e, 0x01, 0x27, + 0x09, 0xf6, 0xd4, 0x15, 0x29, 0x09, 0xb3, 0xd1, 0xa7, 0x90, 0x73, 0x03, 0x3a, 0x4e, 0x1a, 0x43, 0xf5, 0x81, 0x49, + 0x78, 0x15, 0xa1, 0x93, 0xb2, 0x42, 0x58, 0xc0, 0x7d, 0x23, 0xa3, 0xd1, 0x4a, 0x1a, 0x04, 0xde, 0x66, 0xd8, 0x0a, + 0x6c, 0x42, 0xc3, 0x5f, 0x65, 0x1e, 0xa6, 0xd5, 0xac, 0x04, 0x73, 0xbe, 0x81, 0x4a, 0x8c, 0x27, 0xcb, 0x2b, 0xbe, + 0x71, 0xb1, 0x12, 0x93, 0xd9, 0x72, 0x3e, 0x59, 0x4b, 0xaa, 0xb9, 0xdc, 0x5b, 0xb3, 0x8c, 0x2d, 0x61, 0xff, 0x30, + 0xc8, 0x8f, 0x0e, 0xec, 0x68, 0xaa, 0x69, 0x93, 0x00, 0x93, 0xe9, 0x9c, 0xf3, 0xe1, 0x25, 0xa2, 0xc9, 0xea, 0xd4, + 0x9d, 0x4c, 0x55, 0x3b, 0xb8, 0x26, 0x67, 0x72, 0x7a, 0xa4, 0x9e, 0x6a, 0xdd, 0x4b, 0x3e, 0xda, 0x0e, 0xab, 0xd1, + 0xd6, 0x0f, 0xc0, 0xad, 0x53, 0xd8, 0xe9, 0xbb, 0x61, 0x35, 0xda, 0xf9, 0x1a, 0x76, 0x97, 0x14, 0x02, 0xd5, 0x97, + 0xb2, 0x26, 0x73, 0xf1, 0xba, 0xb8, 0xf7, 0x0a, 0xf6, 0xc4, 0x1f, 0xe8, 0x5f, 0x25, 0x7b, 0xe2, 0xdb, 0x4c, 0xae, + 0xbf, 0xa5, 0x5d, 0xa3, 0x31, 0xd3, 0xf1, 0xda, 0x15, 0x58, 0xa1, 0x01, 0xf2, 0x0b, 0x76, 0xb4, 0x57, 0x39, 0x08, + 0x04, 0xe8, 0x5e, 0x82, 0xa3, 0x28, 0x20, 0x6a, 0x5a, 0x55, 0x1e, 0x9d, 0xee, 0xfd, 0x3d, 0xbe, 0x11, 0x02, 0x36, + 0x79, 0x6a, 0xdd, 0x5b, 0xc6, 0xfe, 0xe1, 0x00, 0x21, 0xf4, 0x72, 0xfa, 0x8d, 0xb6, 0xac, 0x1e, 0xed, 0x58, 0xee, + 0x1b, 0x46, 0x3d, 0x05, 0x63, 0x18, 0xba, 0xb0, 0x8a, 0x91, 0x3c, 0x03, 0xb2, 0xc6, 0x6f, 0x10, 0x5d, 0xc0, 0xa2, + 0xd7, 0xfb, 0x74, 0x44, 0x83, 0x08, 0xa8, 0xf4, 0x9a, 0xa3, 0x16, 0xf9, 0x5c, 0x15, 0xa2, 0xf7, 0xde, 0xda, 0x79, + 0x33, 0x23, 0x59, 0x26, 0x8d, 0x54, 0xbb, 0x95, 0xc5, 0xba, 0xf2, 0x66, 0x27, 0xa4, 0x8b, 0x39, 0x86, 0xca, 0xe0, + 0x71, 0x00, 0x4a, 0xcf, 0x7f, 0x87, 0x5e, 0xc9, 0x90, 0x69, 0x96, 0x68, 0x66, 0x77, 0x8d, 0x3f, 0x59, 0xa5, 0x5e, + 0x8c, 0x88, 0xd9, 0xc0, 0x16, 0xe2, 0xb6, 0xa8, 0x74, 0x5b, 0x14, 0xca, 0x16, 0x45, 0xfa, 0x50, 0x3b, 0xd3, 0x9d, + 0x59, 0xf8, 0xac, 0xb2, 0x56, 0x4a, 0x66, 0xc6, 0x06, 0x68, 0xbb, 0x08, 0xdf, 0x40, 0x07, 0x2a, 0x84, 0xfc, 0x05, + 0x22, 0x22, 0x11, 0xb0, 0xcb, 0xa9, 0x3b, 0xb1, 0xe9, 0x90, 0xcc, 0x43, 0xcc, 0x0a, 0x35, 0xca, 0x4b, 0x9e, 0x1c, + 0x0d, 0x48, 0x45, 0xa8, 0xdb, 0xfd, 0xfe, 0xf9, 0xd2, 0x05, 0xb5, 0x5f, 0x53, 0xec, 0x18, 0xdd, 0x14, 0x70, 0x2e, + 0x78, 0x94, 0xf7, 0xdc, 0x3b, 0x07, 0x34, 0xc7, 0xf6, 0x14, 0x59, 0x03, 0x4e, 0x6f, 0xbb, 0x10, 0x60, 0xfb, 0xac, + 0xd9, 0xda, 0x9f, 0xac, 0xae, 0xa2, 0xa9, 0x57, 0xf2, 0x99, 0xee, 0xa2, 0xc4, 0xed, 0xa2, 0x58, 0x76, 0xd1, 0xa6, + 0x81, 0x60, 0xc7, 0x95, 0x1f, 0x00, 0x6f, 0x68, 0xd4, 0xef, 0x97, 0xad, 0x9e, 0x3d, 0xf9, 0xda, 0x71, 0xcf, 0x66, + 0x3e, 0x2b, 0x4d, 0xcf, 0xfe, 0x23, 0x75, 0x7b, 0x56, 0x4e, 0xf6, 0xa2, 0x73, 0xb2, 0x4f, 0x67, 0xf3, 0x40, 0x70, + 0xb9, 0x73, 0x9f, 0xe7, 0x53, 0x3d, 0xed, 0x2a, 0x3f, 0x68, 0x0d, 0x91, 0x35, 0x76, 0x55, 0xf7, 0xba, 0x82, 0x05, + 0x2c, 0xc1, 0xdd, 0x7a, 0x69, 0xfe, 0x1b, 0x76, 0x7f, 0x2f, 0xe8, 0xa5, 0xf9, 0xef, 0xf4, 0x27, 0x05, 0x70, 0x00, + 0x1a, 0x53, 0xbb, 0x05, 0x1e, 0x62, 0xa8, 0xa0, 0x70, 0x37, 0x2b, 0xe7, 0x5e, 0x0d, 0x70, 0x98, 0xa4, 0x6f, 0x68, + 0xf5, 0x4a, 0x8b, 0x5d, 0x2f, 0x93, 0xbd, 0x02, 0x3c, 0x54, 0x21, 0x0f, 0x0f, 0x87, 0xa8, 0x63, 0xd8, 0x41, 0x1d, + 0x01, 0xc3, 0x1e, 0x42, 0x63, 0x0b, 0x3c, 0x1f, 0x3f, 0x64, 0x7c, 0x2f, 0x40, 0x6d, 0x84, 0xf0, 0x78, 0xb5, 0x28, + 0x43, 0x6c, 0xd9, 0x2b, 0xa4, 0x92, 0x7a, 0x2d, 0x10, 0x65, 0xb4, 0x0a, 0x68, 0xab, 0x3d, 0x66, 0x69, 0xfc, 0x08, + 0xa1, 0x62, 0xa9, 0x8f, 0x21, 0x34, 0x70, 0xf8, 0x1d, 0x0e, 0x20, 0xc1, 0x97, 0x5c, 0x93, 0xcd, 0xbd, 0xca, 0xef, + 0x68, 0x9f, 0x3f, 0x1c, 0xce, 0x2f, 0x11, 0x94, 0x2e, 0x85, 0x8f, 0x54, 0x22, 0xaa, 0xa7, 0xb8, 0x29, 0x21, 0x9b, + 0x25, 0x2b, 0xfd, 0xe0, 0x1f, 0xea, 0x17, 0x00, 0xc8, 0x42, 0xa0, 0x4d, 0x64, 0xf6, 0xa7, 0x33, 0x15, 0x5d, 0x00, + 0x1c, 0xe2, 0x0f, 0x9f, 0x20, 0xfa, 0x86, 0x96, 0x69, 0xf9, 0x38, 0xe1, 0x21, 0x68, 0x6d, 0x49, 0x27, 0x11, 0x2b, + 0x05, 0x36, 0x44, 0xc2, 0xf7, 0xfb, 0xe7, 0xb1, 0xa4, 0x03, 0x8d, 0x5a, 0xdd, 0x1b, 0xb7, 0xba, 0x57, 0xbe, 0xae, + 0x3b, 0xb9, 0xf1, 0x41, 0xd1, 0x3e, 0x9b, 0x37, 0x2a, 0xdf, 0xf7, 0x75, 0xce, 0xee, 0x74, 0xef, 0xc8, 0x39, 0xf1, + 0xfd, 0x3d, 0x84, 0xa2, 0x87, 0xa6, 0xc8, 0xb2, 0x24, 0x0c, 0x68, 0xad, 0x5d, 0x7b, 0x96, 0xd1, 0xc1, 0x6b, 0xdf, + 0x10, 0x22, 0xf2, 0x14, 0x9f, 0x84, 0xdc, 0xe2, 0xf8, 0xa0, 0x40, 0xff, 0xcc, 0xf8, 0x33, 0x27, 0x7e, 0xd8, 0xea, + 0x17, 0xc0, 0xb9, 0xe9, 0xde, 0xbb, 0x13, 0xb3, 0x1e, 0x43, 0x29, 0x1b, 0xff, 0xf7, 0xfb, 0x44, 0x16, 0xe8, 0x74, + 0x44, 0xc3, 0x40, 0x70, 0x17, 0xd5, 0xff, 0xbd, 0xe2, 0x75, 0xcf, 0x5a, 0x9d, 0x2f, 0x3f, 0x75, 0x7a, 0xd2, 0xeb, + 0xa5, 0x5b, 0xe1, 0xcb, 0x30, 0xf1, 0x9d, 0xd7, 0xfd, 0x86, 0xed, 0xbe, 0xfb, 0xe5, 0xdd, 0xd1, 0xcb, 0xc0, 0x26, + 0x85, 0xef, 0x6c, 0x4a, 0x3e, 0xeb, 0x81, 0xc2, 0xaf, 0xc7, 0x7a, 0x75, 0xb1, 0xee, 0xb1, 0x1e, 0x6a, 0x01, 0xd1, + 0xc3, 0x02, 0xd4, 0x7f, 0x3d, 0xfb, 0x34, 0x14, 0x0e, 0xb2, 0x71, 0xaa, 0x40, 0x91, 0x05, 0x7f, 0x2a, 0x46, 0xeb, + 0x82, 0x00, 0x91, 0xcd, 0xf6, 0xf5, 0xa1, 0x3a, 0x99, 0x7d, 0x53, 0x6a, 0x49, 0x06, 0xdf, 0x04, 0x64, 0x76, 0x60, + 0xe5, 0x04, 0xa5, 0xe3, 0xd6, 0x80, 0x2b, 0x5b, 0xec, 0xed, 0xed, 0x4f, 0x83, 0xec, 0xac, 0x39, 0x69, 0xb4, 0x0f, + 0xfb, 0x34, 0x0f, 0x10, 0x88, 0x64, 0x2a, 0x82, 0x5c, 0x73, 0x6f, 0x49, 0x1f, 0x1d, 0xce, 0x79, 0x21, 0xff, 0x9c, + 0x4a, 0x1d, 0xe2, 0x50, 0x62, 0x0d, 0x04, 0x2a, 0xcf, 0x50, 0xe5, 0xb0, 0x41, 0x8e, 0x5f, 0x3a, 0x92, 0x99, 0xc4, + 0x64, 0x91, 0xbb, 0x35, 0x53, 0xe1, 0x07, 0x82, 0x8f, 0x59, 0xce, 0x81, 0x0b, 0x6c, 0x36, 0xf7, 0xd5, 0x14, 0x17, + 0x57, 0xe0, 0x8f, 0x29, 0xfc, 0x8a, 0xa7, 0xb0, 0xd3, 0xee, 0xd7, 0x45, 0x95, 0xa2, 0x6e, 0xa3, 0xb0, 0xa8, 0x64, + 0xc1, 0xb4, 0x86, 0x34, 0xd1, 0x61, 0xf4, 0x27, 0x39, 0x03, 0x05, 0x21, 0xbf, 0x6c, 0x1a, 0x60, 0xa4, 0x92, 0xcb, + 0x83, 0x2a, 0x09, 0xbc, 0x00, 0xdb, 0xa0, 0x62, 0xeb, 0x02, 0x82, 0x6c, 0x93, 0xa2, 0x4c, 0xbf, 0x16, 0x79, 0x1d, + 0x66, 0x41, 0x35, 0x4a, 0xab, 0x9f, 0xf5, 0x4f, 0x60, 0xde, 0xa6, 0x62, 0x54, 0xab, 0x98, 0xfc, 0x46, 0xbf, 0x5f, + 0x0c, 0x5a, 0x1f, 0x32, 0xf8, 0xe8, 0xb5, 0x69, 0xf0, 0x5b, 0xa7, 0xc1, 0x0e, 0x13, 0x8d, 0x00, 0x48, 0xe6, 0xd4, + 0x92, 0x87, 0xa2, 0x3f, 0x83, 0x1c, 0x6b, 0x54, 0x39, 0x05, 0x83, 0xf5, 0x1f, 0x8f, 0x76, 0x60, 0xea, 0xc5, 0xd1, + 0x96, 0xec, 0xa0, 0x95, 0x6f, 0x80, 0xfb, 0x35, 0xb2, 0xc5, 0x2c, 0x07, 0x68, 0xf6, 0x1a, 0x91, 0xf1, 0xc9, 0x0b, + 0x60, 0xcc, 0xd6, 0x59, 0x18, 0x89, 0x38, 0x18, 0xab, 0xc6, 0x8c, 0x19, 0x18, 0xb8, 0x40, 0xd7, 0x32, 0x29, 0x49, + 0x43, 0x3a, 0x18, 0xb0, 0x52, 0xb6, 0x70, 0xc0, 0x8b, 0xe6, 0xb8, 0x1d, 0x5f, 0x5b, 0x34, 0x1e, 0xd8, 0x2e, 0xb6, + 0xbf, 0x7b, 0x5e, 0x6c, 0xdf, 0x84, 0x5b, 0xd2, 0x2b, 0xe4, 0x2c, 0xa1, 0x9f, 0x3f, 0xcb, 0x3e, 0x6b, 0x38, 0x39, + 0x15, 0x9a, 0xa1, 0xa5, 0x48, 0x28, 0xc5, 0x3b, 0x3d, 0x29, 0x30, 0x96, 0xb1, 0xf0, 0xf7, 0xc0, 0x39, 0x5d, 0x28, + 0x22, 0x77, 0xe0, 0x38, 0xfe, 0x08, 0x15, 0x8c, 0x1a, 0x0e, 0x5e, 0xc6, 0xb0, 0x2d, 0x8a, 0x59, 0x48, 0x38, 0x85, + 0x70, 0xb1, 0xca, 0xfa, 0x7d, 0xf9, 0x8b, 0xba, 0xe8, 0x22, 0x93, 0x75, 0x9f, 0x84, 0x23, 0x33, 0x96, 0x53, 0x2f, + 0x24, 0xcf, 0x7b, 0x9e, 0x4c, 0x93, 0xc7, 0x79, 0x10, 0x01, 0xe4, 0x73, 0x78, 0x17, 0xa6, 0x19, 0x58, 0xa5, 0x49, + 0xf9, 0x11, 0x4a, 0x5f, 0x7c, 0x5e, 0xf9, 0x81, 0xce, 0x9e, 0x9b, 0x64, 0x78, 0xb3, 0x6a, 0xbd, 0x49, 0xad, 0xeb, + 0xe2, 0x01, 0xff, 0xec, 0x0c, 0x36, 0xce, 0x75, 0x26, 0x38, 0xf0, 0x22, 0xa9, 0xf5, 0x9a, 0xf1, 0xa7, 0x19, 0xae, + 0x4b, 0xd5, 0x46, 0x1f, 0x85, 0xe8, 0x1c, 0x32, 0x15, 0xa0, 0x50, 0xa4, 0xfd, 0x83, 0x52, 0x2b, 0x93, 0x4a, 0x1b, + 0x09, 0xa0, 0x7b, 0x98, 0x34, 0xd8, 0x62, 0x28, 0x63, 0x69, 0x12, 0xe5, 0x4e, 0x83, 0xb8, 0xb2, 0x1f, 0x2a, 0x89, + 0x43, 0xcb, 0x22, 0xf9, 0xf7, 0xae, 0xa7, 0xaf, 0x90, 0xba, 0x93, 0x05, 0x32, 0x63, 0x3c, 0xcb, 0xe3, 0x4f, 0x40, + 0x98, 0x0d, 0xda, 0xa8, 0x28, 0x84, 0x90, 0x0d, 0x62, 0xd0, 0x78, 0x96, 0xc7, 0xcf, 0x15, 0x8d, 0x87, 0x7c, 0x14, + 0xf9, 0xea, 0xaf, 0x52, 0xff, 0x15, 0xfa, 0xcc, 0x04, 0x8f, 0x50, 0x4d, 0xf4, 0xef, 0x9e, 0xcf, 0xee, 0x40, 0x6d, + 0x18, 0x85, 0x99, 0x29, 0xbf, 0xf2, 0x4d, 0x71, 0xf6, 0xfa, 0x2b, 0xba, 0xca, 0xb6, 0xee, 0x47, 0x2f, 0x8f, 0x08, + 0xac, 0x8d, 0xd1, 0x15, 0x37, 0x06, 0x90, 0xc3, 0xe4, 0xfd, 0x8a, 0xd2, 0x72, 0x48, 0x83, 0xd0, 0x41, 0x43, 0x18, + 0x2d, 0x89, 0x3e, 0x90, 0x58, 0xc4, 0x18, 0x5e, 0x88, 0x67, 0xa4, 0x26, 0x13, 0x0d, 0xf1, 0x8a, 0xd8, 0x0f, 0xd1, + 0x92, 0x53, 0x13, 0xdd, 0x08, 0x53, 0x0c, 0x24, 0x76, 0x06, 0xc9, 0x49, 0x52, 0x2b, 0xbf, 0x78, 0x26, 0x09, 0x4b, + 0xec, 0x3c, 0xc4, 0x60, 0x52, 0x4b, 0x77, 0x7a, 0x53, 0xa5, 0xe7, 0x47, 0x5a, 0x0e, 0xda, 0x07, 0x60, 0x97, 0x92, + 0xde, 0x3f, 0x29, 0x14, 0xf1, 0x3e, 0x8c, 0x63, 0x08, 0xdf, 0x22, 0xaa, 0x2b, 0x70, 0xae, 0x15, 0x68, 0xac, 0x06, + 0x1e, 0x9a, 0x59, 0x35, 0x1f, 0x72, 0xfa, 0xa9, 0xb4, 0xfc, 0x31, 0xa2, 0xb1, 0xd1, 0xba, 0x39, 0x1c, 0xf6, 0xb4, + 0xea, 0xa5, 0x73, 0xd0, 0x65, 0x33, 0x89, 0x89, 0x1b, 0x48, 0xd7, 0x8f, 0x7e, 0x33, 0x61, 0x2f, 0xa2, 0x42, 0x2e, + 0x85, 0xa0, 0xa0, 0xd5, 0x81, 0xc0, 0xa1, 0xf0, 0x16, 0x65, 0xbe, 0x88, 0x69, 0x03, 0x61, 0xf0, 0xf9, 0x81, 0xfc, + 0x7c, 0x53, 0x90, 0x8a, 0x1d, 0xeb, 0xda, 0xef, 0x2f, 0x4b, 0x0f, 0xf0, 0xe4, 0x4c, 0x92, 0xa7, 0xcd, 0x10, 0x56, + 0x04, 0xd0, 0x98, 0xd5, 0x64, 0x71, 0xc2, 0x95, 0x39, 0x7c, 0x59, 0x79, 0x25, 0x4b, 0x99, 0x3a, 0x4f, 0xf5, 0x02, + 0x88, 0x3a, 0xde, 0xa0, 0x15, 0xa9, 0x5f, 0xa1, 0xb3, 0xd7, 0xac, 0x84, 0x8c, 0x87, 0xe7, 0x9c, 0xa7, 0xa3, 0x7b, + 0x96, 0xf0, 0x08, 0xff, 0x4a, 0x26, 0xfa, 0xf0, 0xbb, 0xe7, 0x70, 0x33, 0x4e, 0x78, 0xe4, 0x36, 0x7b, 0x5f, 0x85, + 0x2b, 0xb8, 0x99, 0x16, 0x80, 0xe4, 0x16, 0x24, 0x4d, 0x40, 0x09, 0x89, 0x4c, 0xc8, 0xac, 0x29, 0xf9, 0x6b, 0x4b, + 0xdb, 0x60, 0x0d, 0x93, 0xce, 0x03, 0x5e, 0xb4, 0xfa, 0x68, 0x35, 0xd1, 0x2e, 0xb3, 0x7c, 0x3e, 0xc4, 0x19, 0xaa, + 0x39, 0xee, 0xce, 0xe0, 0xe7, 0x80, 0x57, 0xac, 0x6a, 0xd2, 0xd1, 0x6e, 0xc0, 0x85, 0x27, 0xd7, 0x79, 0x3a, 0xda, + 0xe2, 0x2f, 0xb9, 0x3f, 0x00, 0x74, 0x30, 0x75, 0x09, 0xfc, 0xa9, 0xda, 0x6a, 0x2a, 0xf5, 0x73, 0x6b, 0xbf, 0xae, + 0x3b, 0xab, 0x95, 0x7b, 0xd6, 0x65, 0x68, 0x8f, 0x0c, 0x39, 0x63, 0x06, 0xfc, 0x39, 0x63, 0xc9, 0x9f, 0x33, 0x56, + 0xfc, 0x39, 0xe3, 0xc6, 0xc8, 0x00, 0x4a, 0x70, 0x2f, 0xf9, 0xd3, 0x3d, 0x62, 0x86, 0x58, 0x0d, 0x2a, 0x81, 0x95, + 0xa5, 0x9c, 0xfb, 0xc8, 0x29, 0xa6, 0x9c, 0x32, 0xbc, 0x74, 0x3a, 0x73, 0x07, 0x72, 0x1e, 0xcc, 0xdc, 0x61, 0xb2, + 0xd7, 0xe7, 0x46, 0x1c, 0x4b, 0x63, 0x52, 0x54, 0x90, 0xce, 0xe9, 0x70, 0xf3, 0xea, 0x38, 0x4f, 0x58, 0xc6, 0xc7, + 0xed, 0x33, 0x05, 0x42, 0x6c, 0xf1, 0x0c, 0x89, 0x94, 0xaa, 0x59, 0x6e, 0xf3, 0x87, 0x43, 0x3d, 0xba, 0xd7, 0x3b, + 0x3d, 0xfc, 0x4a, 0xd8, 0xcf, 0x99, 0x67, 0x9f, 0x20, 0x80, 0x49, 0x22, 0xcf, 0x24, 0x1c, 0xfd, 0x58, 0x8e, 0xfe, + 0xa6, 0xe1, 0xcf, 0x33, 0x54, 0x77, 0x87, 0xc0, 0xc4, 0x96, 0x1d, 0x38, 0x04, 0xa7, 0xab, 0x4a, 0x24, 0xe0, 0x60, + 0xb3, 0x61, 0x91, 0xde, 0xe3, 0x21, 0xce, 0x07, 0x85, 0x8f, 0xd0, 0x30, 0xa3, 0xf7, 0xfb, 0x1b, 0xe1, 0x55, 0xb2, + 0x95, 0x87, 0x43, 0x62, 0x69, 0x80, 0x1c, 0x7d, 0x1c, 0xed, 0x51, 0x42, 0xed, 0x47, 0xb5, 0xde, 0x54, 0xea, 0x41, + 0x6e, 0x76, 0x21, 0x31, 0xa8, 0x58, 0xaa, 0x4f, 0xaf, 0x54, 0x1f, 0x6a, 0x96, 0x1c, 0x52, 0x1d, 0xf7, 0xa9, 0x18, + 0xad, 0xe5, 0x84, 0x00, 0xd7, 0x41, 0xa2, 0xd1, 0x01, 0x30, 0xce, 0x36, 0x5b, 0x5e, 0x6a, 0xeb, 0x44, 0xe9, 0x38, + 0xce, 0xf5, 0x71, 0x7c, 0x38, 0x48, 0x31, 0xe3, 0xf2, 0x48, 0xcc, 0xb8, 0x6c, 0x00, 0xde, 0xac, 0xf3, 0xa0, 0x3e, + 0x1c, 0x2e, 0xe9, 0x52, 0x64, 0x3a, 0xdb, 0x28, 0x3f, 0xeb, 0xd1, 0xfd, 0xe3, 0x04, 0xcd, 0xbd, 0x15, 0xf6, 0x5e, + 0x24, 0xdb, 0x33, 0x59, 0xa7, 0x5e, 0x46, 0x3e, 0xbd, 0x70, 0xcf, 0x2e, 0xb9, 0xfa, 0x61, 0xf5, 0xf5, 0xf4, 0x37, + 0xe1, 0x45, 0xac, 0xa2, 0xdd, 0xba, 0x64, 0xc2, 0xde, 0x52, 0x2a, 0x69, 0x95, 0x97, 0x4f, 0x37, 0x7e, 0x80, 0x99, + 0x69, 0x4f, 0x1f, 0x64, 0x23, 0xaa, 0x3f, 0x2b, 0x51, 0x2b, 0xc3, 0x64, 0xe1, 0xbc, 0x64, 0xea, 0xc9, 0x80, 0xc7, + 0xac, 0xe4, 0x91, 0xec, 0xf4, 0xc6, 0x20, 0x08, 0x60, 0x9d, 0x93, 0x56, 0x9d, 0x71, 0x34, 0x5a, 0x55, 0x2e, 0x4e, + 0x57, 0xb9, 0xc0, 0x70, 0xbb, 0x35, 0xdb, 0xa8, 0x3a, 0xcb, 0x4d, 0xad, 0x52, 0xbe, 0x03, 0xf8, 0x58, 0x56, 0xb9, + 0xa0, 0x63, 0xca, 0xd4, 0x79, 0x03, 0xc1, 0xd8, 0xaa, 0xc6, 0x85, 0x53, 0xe3, 0x82, 0x47, 0xd4, 0xee, 0xa6, 0xa9, + 0x47, 0x5b, 0x60, 0x29, 0x1d, 0xed, 0x78, 0x89, 0x2a, 0x85, 0x7f, 0x08, 0xbe, 0x0f, 0xe3, 0xf8, 0x79, 0xb1, 0x55, + 0x07, 0xe2, 0x4d, 0xb1, 0x45, 0xda, 0x17, 0xf9, 0x17, 0xe2, 0x80, 0xd7, 0xba, 0xa6, 0xbc, 0xb6, 0xe6, 0x34, 0xb0, + 0x35, 0x8c, 0x94, 0x14, 0xce, 0xcd, 0x9f, 0x87, 0x03, 0xad, 0xec, 0x5a, 0xdd, 0x15, 0x6a, 0x3d, 0xe6, 0xb0, 0x61, + 0x2f, 0xb2, 0x70, 0x27, 0x4a, 0x70, 0xe4, 0x92, 0x7f, 0x1d, 0x0e, 0x5a, 0x65, 0xa9, 0x8e, 0xf4, 0xd9, 0xfe, 0x6b, + 0x30, 0x66, 0xe8, 0xd2, 0x04, 0x2c, 0x1b, 0x23, 0xf9, 0x57, 0xd3, 0xcc, 0x1b, 0x26, 0x6b, 0xa6, 0x70, 0x1c, 0x1a, + 0x46, 0x48, 0x03, 0xba, 0x0d, 0x6a, 0xc3, 0x93, 0xf9, 0xa6, 0x2a, 0xbf, 0xba, 0x23, 0xd5, 0x7e, 0x30, 0xbc, 0x9c, + 0x88, 0x73, 0xba, 0x24, 0xa9, 0xa7, 0x12, 0x4a, 0x42, 0xb0, 0x4b, 0x1f, 0xc8, 0x89, 0x15, 0x90, 0xb5, 0x8c, 0xe5, + 0xb7, 0x7a, 0x40, 0xe8, 0x3f, 0xed, 0xd6, 0x0b, 0xfd, 0xa7, 0x69, 0xb6, 0x50, 0xd7, 0x1f, 0x26, 0xf7, 0x1d, 0xbd, + 0xfe, 0xe0, 0xf0, 0x4e, 0x5d, 0x55, 0x5c, 0xc5, 0xa3, 0xda, 0x30, 0xc9, 0x8d, 0xb2, 0x70, 0x57, 0x6c, 0x6a, 0xb5, + 0x3c, 0x1d, 0x87, 0x11, 0x98, 0x11, 0x14, 0x20, 0xeb, 0xba, 0x8d, 0x88, 0x61, 0x25, 0x97, 0x09, 0xf9, 0x84, 0x80, + 0x2c, 0x4a, 0x8d, 0xf3, 0x71, 0x0b, 0x54, 0x22, 0x18, 0x9c, 0x86, 0xd6, 0xaa, 0x9b, 0xfc, 0xac, 0xb2, 0xb1, 0x5b, + 0x20, 0x87, 0x24, 0x93, 0xc5, 0xed, 0xe8, 0x46, 0x2c, 0x8b, 0x52, 0xbc, 0xc6, 0x7a, 0xb8, 0x66, 0x0b, 0xf7, 0x19, + 0x10, 0xda, 0x4f, 0x94, 0xf6, 0x26, 0xd2, 0x04, 0xdd, 0xb7, 0x6c, 0x05, 0x20, 0x03, 0x28, 0xea, 0x6a, 0xb7, 0x3e, + 0xe7, 0xe7, 0x48, 0x9a, 0xe1, 0x30, 0xba, 0x7d, 0x7a, 0x1b, 0xdc, 0x0e, 0x2e, 0x51, 0x2b, 0x7d, 0xc9, 0xe2, 0x16, + 0x06, 0xd5, 0xde, 0x2c, 0xe1, 0xa0, 0x66, 0xd6, 0xda, 0x08, 0x04, 0x93, 0x3d, 0x14, 0x54, 0xcc, 0x15, 0xec, 0x83, + 0x82, 0xb5, 0xe4, 0x75, 0x70, 0xb8, 0xb5, 0x2f, 0x2b, 0xc5, 0xc5, 0x93, 0x8b, 0xa4, 0x75, 0x61, 0x29, 0x2f, 0x9e, + 0x34, 0x60, 0x70, 0x39, 0xc2, 0xa6, 0x02, 0x93, 0x04, 0x80, 0x6e, 0x45, 0x14, 0xf1, 0xa2, 0x14, 0xb6, 0xad, 0x7c, + 0xe6, 0x84, 0x0d, 0x36, 0xec, 0x1e, 0xee, 0x95, 0x41, 0xc9, 0xe0, 0x42, 0x8c, 0xdb, 0xcd, 0x2e, 0xc0, 0x15, 0x0c, + 0x85, 0xb1, 0x35, 0xff, 0x9a, 0x79, 0x91, 0x12, 0x70, 0x33, 0x44, 0xf9, 0xda, 0xc0, 0xc9, 0xa4, 0x27, 0xd7, 0x92, + 0xc5, 0x80, 0x05, 0x0d, 0xbe, 0xa3, 0xd6, 0xdf, 0x99, 0xfc, 0x1b, 0x4f, 0x0f, 0xfd, 0xe0, 0xd7, 0xcc, 0x5b, 0xfa, + 0xec, 0x6d, 0x25, 0xa3, 0x35, 0x49, 0x94, 0x57, 0x0f, 0x97, 0x20, 0x37, 0x2c, 0x47, 0xf7, 0x6c, 0x09, 0xe2, 0xc4, + 0x72, 0x94, 0x50, 0x46, 0x57, 0xb8, 0x57, 0x99, 0x2d, 0x13, 0x81, 0x14, 0x07, 0x96, 0x52, 0xee, 0x2d, 0xd6, 0xc1, + 0x12, 0xf7, 0x27, 0x92, 0x0b, 0x28, 0x79, 0x00, 0xe5, 0x4a, 0x01, 0x01, 0x9f, 0x0e, 0xa0, 0x7c, 0x29, 0x2f, 0xc2, + 0x9f, 0x38, 0x51, 0x83, 0xe5, 0xe8, 0xbe, 0x61, 0x3f, 0x7b, 0xa1, 0x65, 0x7f, 0xb8, 0xd5, 0x9a, 0x86, 0x15, 0xbf, + 0x85, 0x69, 0x31, 0x71, 0xfb, 0x72, 0x65, 0x57, 0xc5, 0x67, 0x2b, 0x75, 0x76, 0x53, 0x43, 0x12, 0xf6, 0x0d, 0x59, + 0x05, 0x38, 0x58, 0x15, 0x71, 0xcf, 0xba, 0xdc, 0x87, 0xd1, 0x97, 0x4d, 0x5a, 0x0a, 0x0b, 0x55, 0xd2, 0xdf, 0x37, + 0xa5, 0x40, 0x2a, 0x13, 0x9d, 0x68, 0x21, 0xb8, 0x02, 0x83, 0xc0, 0x9d, 0xc8, 0x6b, 0x00, 0x8c, 0x01, 0x97, 0x02, + 0x65, 0xd9, 0x96, 0x10, 0x52, 0xdd, 0xcf, 0x40, 0x6d, 0x27, 0xee, 0xd2, 0x88, 0xac, 0x85, 0xe8, 0xab, 0x60, 0xcc, + 0x9c, 0x97, 0xd2, 0x2d, 0x36, 0x5d, 0x6d, 0x56, 0x1f, 0xd1, 0xb9, 0xb4, 0xe5, 0xe6, 0x27, 0x6c, 0xb1, 0x56, 0xa0, + 0x6c, 0x42, 0xd2, 0x76, 0xce, 0x73, 0x94, 0x4d, 0x68, 0x69, 0xef, 0xa9, 0x47, 0x85, 0xea, 0x64, 0xeb, 0xa5, 0x6a, + 0x6a, 0x11, 0x56, 0x8b, 0x8b, 0xca, 0x0f, 0x40, 0x37, 0x95, 0x56, 0xcf, 0xea, 0x1a, 0x4d, 0xa1, 0x56, 0x0b, 0xc7, + 0x8d, 0x76, 0x36, 0x5d, 0xa6, 0xb7, 0x88, 0xb3, 0x2a, 0xed, 0xd0, 0xbf, 0x64, 0xda, 0xf5, 0xb2, 0xa3, 0xdf, 0x8c, + 0xab, 0x0b, 0x5c, 0x88, 0x0d, 0xf8, 0x9c, 0xfb, 0xcb, 0xeb, 0x3d, 0x89, 0x7b, 0xfe, 0xe1, 0x80, 0xec, 0x49, 0xed, + 0x0f, 0xd5, 0xc7, 0xae, 0x60, 0xc8, 0xc2, 0x28, 0xf5, 0x17, 0x29, 0xef, 0x3d, 0xc2, 0x71, 0xff, 0x5c, 0xf5, 0xd8, + 0xbf, 0x32, 0xbe, 0xaf, 0x8b, 0x4d, 0x94, 0x50, 0x54, 0x43, 0x6f, 0x55, 0x6c, 0x2a, 0x11, 0x17, 0xf7, 0x79, 0x8f, + 0x61, 0x32, 0x8c, 0x85, 0x4c, 0x85, 0x3f, 0x65, 0x2a, 0x78, 0x84, 0x50, 0xe2, 0x66, 0xdd, 0x23, 0xed, 0x26, 0xc4, + 0x29, 0xd5, 0xa2, 0x94, 0xc9, 0xf8, 0xb7, 0x7e, 0x02, 0xe5, 0x39, 0x45, 0xcb, 0xf4, 0xa3, 0xc2, 0x65, 0xfa, 0x66, + 0x7d, 0x5c, 0x7a, 0x26, 0x42, 0x9d, 0xb9, 0xd8, 0xd4, 0x3a, 0x1d, 0x63, 0xa7, 0x74, 0x6a, 0xc3, 0xbe, 0x56, 0x8a, + 0xcb, 0x8a, 0xc2, 0xbf, 0x91, 0xc8, 0xaa, 0x67, 0xc4, 0xf1, 0xdf, 0xb3, 0xf6, 0x19, 0x56, 0x81, 0x5f, 0x06, 0xf2, + 0x7e, 0x01, 0xf0, 0x71, 0x5d, 0x97, 0xe9, 0xcd, 0x06, 0x68, 0x43, 0x68, 0xf8, 0x7b, 0x3e, 0x32, 0x60, 0xba, 0x8f, + 0x70, 0x86, 0xf4, 0x50, 0xe7, 0x9c, 0xce, 0xca, 0x74, 0xce, 0x55, 0x58, 0x4b, 0xb0, 0x97, 0x93, 0x26, 0x97, 0xeb, + 0x12, 0xd4, 0x4c, 0xe0, 0xf6, 0xa1, 0x3d, 0x22, 0x84, 0xda, 0x94, 0xd5, 0xf4, 0x12, 0x6a, 0xde, 0xc9, 0x69, 0x47, + 0x93, 0x12, 0x5c, 0x35, 0x74, 0x56, 0xae, 0xff, 0x3a, 0x1c, 0x7a, 0x37, 0x59, 0x11, 0xfd, 0xd9, 0x43, 0x7f, 0xc7, + 0xed, 0xc7, 0xf4, 0x2b, 0x44, 0xcb, 0x58, 0x7f, 0x43, 0x06, 0x74, 0x3c, 0x19, 0xde, 0x14, 0xdb, 0x1e, 0xfb, 0x8a, + 0x1a, 0x2c, 0x7d, 0xfd, 0xf8, 0x08, 0x12, 0xaa, 0xae, 0x7d, 0x61, 0xf1, 0x84, 0x79, 0x4a, 0xb4, 0x2d, 0x7c, 0x08, + 0x0b, 0xfd, 0x0a, 0x91, 0x91, 0x10, 0x6e, 0x2a, 0xbb, 0x47, 0x49, 0xbb, 0xd0, 0x97, 0xbe, 0x96, 0x7d, 0xe5, 0x3b, + 0x17, 0x00, 0x2b, 0xfb, 0xc4, 0x86, 0x7b, 0xd2, 0x9f, 0x52, 0x7d, 0xd8, 0xfe, 0x96, 0x2c, 0xa0, 0xd0, 0xc2, 0x7a, + 0x2a, 0x67, 0xe7, 0x6d, 0xc9, 0xab, 0x6c, 0xba, 0x5f, 0xc3, 0x1e, 0x75, 0x87, 0x5e, 0x53, 0xc1, 0xf9, 0xa5, 0x19, + 0xbd, 0x2f, 0x86, 0x42, 0x75, 0xd4, 0xb9, 0x83, 0xdc, 0x96, 0xd6, 0x25, 0xe7, 0x37, 0x2b, 0x77, 0x14, 0xe6, 0x77, + 0x21, 0x78, 0x86, 0x75, 0xef, 0x2e, 0xce, 0x7b, 0xff, 0x68, 0xcd, 0x91, 0x7f, 0x65, 0xb3, 0x14, 0xb1, 0x48, 0xe6, + 0x60, 0xf5, 0x43, 0x3f, 0x8f, 0xfd, 0x36, 0xc8, 0xe1, 0xb8, 0x69, 0x40, 0x87, 0x0d, 0x99, 0xb5, 0x2f, 0x11, 0x38, + 0xd5, 0x08, 0xd2, 0xd4, 0x04, 0x35, 0xcb, 0x43, 0x24, 0xb6, 0x4b, 0xd9, 0x36, 0xc8, 0x75, 0x17, 0x4c, 0x73, 0xa4, + 0x3d, 0x83, 0xf7, 0x4d, 0x9a, 0xa4, 0x42, 0xb3, 0x68, 0x74, 0x25, 0xe3, 0xdf, 0x91, 0x36, 0x53, 0xb2, 0xc7, 0xd6, + 0xc0, 0x7b, 0x09, 0xca, 0xc9, 0x30, 0xc5, 0xf0, 0x1d, 0x5f, 0xef, 0x3c, 0xba, 0x88, 0xbf, 0x1d, 0xb3, 0x4d, 0xca, + 0x8e, 0x60, 0x92, 0x6c, 0x7c, 0x43, 0xf1, 0x86, 0xef, 0x6e, 0x2a, 0x51, 0x02, 0xe8, 0x65, 0xc1, 0x9f, 0x4a, 0x9b, + 0x2b, 0x74, 0xbb, 0x7b, 0x47, 0x29, 0xfc, 0x92, 0x97, 0x87, 0xc3, 0x36, 0xf5, 0x42, 0xe8, 0x7c, 0x11, 0xbf, 0x05, + 0x73, 0x18, 0x43, 0x6c, 0x46, 0x80, 0x30, 0xc7, 0x07, 0xd4, 0xc1, 0xfa, 0x11, 0x80, 0xc6, 0x09, 0x14, 0x60, 0xf4, + 0xd5, 0xb6, 0xa0, 0x6f, 0x79, 0x71, 0x11, 0x21, 0x6a, 0x14, 0x60, 0xa2, 0xa4, 0x59, 0x0c, 0xc3, 0x81, 0xce, 0xef, + 0x9b, 0x9b, 0xba, 0x14, 0x38, 0xf4, 0x8e, 0x65, 0xf8, 0x9f, 0xff, 0x63, 0x6d, 0x69, 0x55, 0xd9, 0x6e, 0x8d, 0xd3, + 0xcc, 0xff, 0x76, 0x5b, 0xa4, 0x5b, 0xa8, 0x50, 0x3c, 0xef, 0x78, 0xdd, 0xfe, 0x0c, 0xd1, 0xfb, 0xba, 0x95, 0xab, + 0x52, 0xbb, 0x61, 0xa6, 0xfc, 0x3e, 0xcd, 0xe3, 0xe2, 0x7e, 0x14, 0xb7, 0x8e, 0xbc, 0x49, 0x7a, 0xce, 0xf9, 0xe7, + 0xaa, 0xdf, 0xf7, 0x3e, 0x03, 0x19, 0xef, 0xb5, 0x30, 0x8e, 0x98, 0xc4, 0xc1, 0xb7, 0x17, 0xa3, 0x68, 0x53, 0xc2, + 0x86, 0xdc, 0x3e, 0x2d, 0x41, 0x33, 0xd3, 0xef, 0xa3, 0x44, 0x69, 0xcd, 0xf7, 0x7f, 0xcb, 0xf9, 0x7e, 0x2d, 0xe4, + 0xcd, 0x4a, 0x7e, 0xf8, 0x68, 0x85, 0x81, 0xef, 0x71, 0xfa, 0x55, 0xf4, 0xd8, 0xaa, 0xf4, 0xe1, 0xbb, 0xd2, 0xd2, + 0x67, 0x15, 0xf5, 0x77, 0x54, 0xd4, 0x5c, 0x8b, 0x11, 0x11, 0x0f, 0x82, 0x76, 0xb6, 0x5d, 0x6a, 0xd7, 0x12, 0xb4, + 0x0b, 0x36, 0x85, 0xd5, 0xc9, 0x43, 0x43, 0xde, 0xef, 0xbf, 0xcc, 0xbd, 0x16, 0xaf, 0xbb, 0x81, 0xbb, 0x2c, 0x3d, + 0x84, 0x00, 0xd6, 0x32, 0x50, 0xc6, 0x11, 0x26, 0x5d, 0xe4, 0x35, 0xca, 0xa6, 0x13, 0x81, 0x8f, 0x59, 0x76, 0xe5, + 0x24, 0xd3, 0x00, 0x33, 0xaa, 0x29, 0xcc, 0x04, 0x18, 0xa9, 0x0f, 0x58, 0x37, 0x3d, 0xad, 0x42, 0xcb, 0xd7, 0x10, + 0xac, 0x8b, 0x2c, 0xe3, 0x28, 0x66, 0x02, 0x80, 0xcd, 0x07, 0x90, 0xaf, 0xe8, 0xea, 0x90, 0xb4, 0x52, 0xe5, 0xfd, + 0x3a, 0x23, 0x32, 0x9a, 0x84, 0x68, 0x7e, 0x0b, 0x0f, 0xec, 0xdb, 0x66, 0x46, 0x95, 0x7a, 0x46, 0x55, 0x3e, 0xc3, + 0x61, 0x29, 0x1c, 0x23, 0xfe, 0xdf, 0x52, 0xd5, 0x23, 0x02, 0xbd, 0x2a, 0xd3, 0x2a, 0x2a, 0xf2, 0x5c, 0x44, 0x88, + 0x50, 0x2d, 0x9d, 0xc3, 0xa1, 0x1f, 0xfb, 0x7d, 0x1c, 0x08, 0xf3, 0xa2, 0x78, 0xa8, 0x2b, 0x6b, 0x5a, 0x2b, 0x29, + 0x70, 0x2a, 0x6a, 0x84, 0x08, 0xe1, 0xfd, 0x03, 0x78, 0x56, 0x53, 0xdf, 0x6f, 0x2c, 0x13, 0xdd, 0x97, 0x0c, 0x28, + 0x7f, 0x40, 0xbe, 0xae, 0xa4, 0x38, 0x93, 0x26, 0x0f, 0x89, 0x33, 0x0e, 0x40, 0xcc, 0xb7, 0x25, 0x1a, 0x8d, 0xfd, + 0x0f, 0x48, 0x30, 0x54, 0x3f, 0xd8, 0xe9, 0xa6, 0xde, 0xef, 0x99, 0xc4, 0x51, 0xf4, 0x69, 0x9b, 0x3c, 0x96, 0x2c, + 0x8d, 0x16, 0x8e, 0xde, 0x23, 0x86, 0x71, 0x38, 0x9d, 0x8f, 0x49, 0xb6, 0x31, 0x59, 0x05, 0x90, 0x4e, 0x66, 0xea, + 0x98, 0x52, 0x47, 0xe3, 0x5c, 0x2f, 0xa8, 0x42, 0x8f, 0x75, 0xc9, 0x73, 0xb0, 0x9e, 0xbc, 0xf2, 0x4a, 0x7f, 0x2a, + 0xe4, 0x1c, 0x36, 0x12, 0x41, 0xe1, 0x07, 0xb8, 0x1a, 0xac, 0x14, 0x30, 0x98, 0xfa, 0x16, 0xbe, 0x26, 0x9e, 0xa3, + 0xe0, 0x51, 0xd8, 0xc5, 0xd8, 0x5a, 0xf9, 0xce, 0x27, 0x05, 0xe5, 0x9e, 0x15, 0x73, 0x5e, 0x01, 0xe7, 0x32, 0x28, + 0x84, 0xe9, 0x78, 0x96, 0xff, 0x33, 0xc9, 0xeb, 0x89, 0x0d, 0x01, 0x32, 0xf8, 0x53, 0xe2, 0xb4, 0x74, 0x87, 0xee, + 0x3c, 0xf4, 0x2c, 0xe2, 0xb0, 0xd1, 0xa3, 0x75, 0x59, 0x6c, 0x53, 0xd4, 0x4b, 0x98, 0x1f, 0xc8, 0xcf, 0x5b, 0xf2, + 0x7d, 0x88, 0xe2, 0x6d, 0xf0, 0xb7, 0x8c, 0xc5, 0x02, 0xff, 0xfa, 0x67, 0xc6, 0x68, 0xa2, 0x05, 0x75, 0xd2, 0x20, + 0x51, 0xb1, 0x48, 0x26, 0x00, 0xeb, 0xc8, 0xd5, 0x87, 0x4f, 0x89, 0xf1, 0xd6, 0x6c, 0x78, 0xe0, 0x9b, 0x15, 0xe8, + 0xd4, 0xe7, 0xee, 0xca, 0xf6, 0x74, 0x35, 0x52, 0x55, 0x8d, 0xbf, 0xa5, 0xaa, 0x1a, 0x7f, 0x4b, 0xa9, 0x1a, 0xbf, + 0x65, 0x14, 0xbf, 0x53, 0xf9, 0x0c, 0x99, 0x93, 0x4d, 0x4c, 0xd2, 0xe9, 0x7b, 0xc3, 0x89, 0x5d, 0xf6, 0x5b, 0xb7, + 0x89, 0x3c, 0x33, 0x91, 0x42, 0xee, 0x0d, 0x40, 0xcd, 0xc4, 0x97, 0xb9, 0xe1, 0x94, 0x38, 0x3f, 0xf7, 0x70, 0xc5, + 0xa6, 0xd5, 0x35, 0x2d, 0x58, 0x60, 0xf3, 0x32, 0xcb, 0x33, 0x4f, 0x60, 0xdb, 0x94, 0x59, 0x3f, 0xe4, 0x1e, 0x40, + 0x30, 0x93, 0x9a, 0x00, 0x90, 0x16, 0xa2, 0x52, 0x88, 0xfc, 0x1a, 0x67, 0xf5, 0x39, 0xef, 0x6d, 0xf2, 0x98, 0x48, + 0xab, 0x7b, 0xfd, 0x7e, 0x7a, 0x96, 0xe6, 0x14, 0xd4, 0x70, 0x9c, 0x75, 0xfa, 0x4b, 0x16, 0xa4, 0x89, 0x5c, 0xa5, + 0xff, 0x74, 0x83, 0xbc, 0x8c, 0xef, 0xeb, 0xb6, 0xe7, 0x4f, 0xd4, 0xdf, 0x3b, 0xeb, 0x6f, 0x0b, 0x04, 0x77, 0x72, + 0xec, 0x27, 0xab, 0x52, 0x1e, 0x19, 0x97, 0xf6, 0x9e, 0xdf, 0xd4, 0x45, 0x91, 0xd5, 0xe9, 0xfa, 0xbd, 0xd4, 0xd3, + 0xe8, 0xbe, 0xd8, 0x83, 0x31, 0x78, 0x07, 0x80, 0x67, 0x3a, 0x34, 0x40, 0xfa, 0x9e, 0x91, 0x87, 0xfb, 0xdc, 0x92, + 0x9f, 0x54, 0xd6, 0x26, 0x09, 0x2b, 0x8a, 0xcd, 0x30, 0x46, 0x28, 0x19, 0xa7, 0xb1, 0xf5, 0xfb, 0x7d, 0xf5, 0xf7, + 0x0e, 0xa3, 0xa8, 0xa8, 0xb8, 0x63, 0x34, 0x2a, 0xab, 0x7a, 0xb4, 0x1d, 0x1c, 0x0e, 0xe7, 0xb9, 0x8d, 0xa3, 0xad, + 0x57, 0xc0, 0xde, 0x0a, 0x95, 0xb2, 0x57, 0x22, 0x2c, 0x3f, 0x5c, 0xf9, 0xfd, 0x3e, 0xfc, 0x2b, 0x23, 0x2d, 0x3c, + 0x7f, 0x8a, 0xbf, 0x16, 0x75, 0x81, 0xe1, 0x19, 0xb4, 0x46, 0x2b, 0x08, 0x26, 0xf8, 0x67, 0x07, 0xea, 0xa5, 0x95, + 0xf6, 0x01, 0x74, 0x2b, 0xd0, 0x83, 0x86, 0x93, 0x38, 0x69, 0x5f, 0x48, 0xd4, 0xed, 0xad, 0x4e, 0xa3, 0x3f, 0x2b, + 0x96, 0xf3, 0x02, 0x26, 0x87, 0x1b, 0xfa, 0xb4, 0x0a, 0xb7, 0x9f, 0xe0, 0xe9, 0x6b, 0xa0, 0xdc, 0x3a, 0x1c, 0x72, + 0x10, 0x5b, 0xc0, 0xcd, 0x63, 0x15, 0x7e, 0x2e, 0x4a, 0x19, 0x51, 0x1f, 0x4f, 0x43, 0xd0, 0xde, 0x05, 0xe8, 0x80, + 0xa5, 0x41, 0xbc, 0x42, 0xf2, 0x9c, 0x8d, 0x00, 0x96, 0x1d, 0x58, 0xce, 0x32, 0x4e, 0x61, 0x9e, 0xe5, 0x53, 0xb5, + 0xd2, 0xce, 0xa2, 0xc4, 0xab, 0x59, 0x06, 0xce, 0x02, 0x17, 0x95, 0xcf, 0x32, 0xad, 0x7a, 0x2a, 0x13, 0xf4, 0x79, + 0x25, 0x27, 0xb8, 0x12, 0x9c, 0x6c, 0x40, 0x7e, 0x01, 0x92, 0x34, 0xa5, 0xac, 0x29, 0x9f, 0x5e, 0xd2, 0x0d, 0x19, + 0x3d, 0xe7, 0x3d, 0x2f, 0x1a, 0x86, 0xfe, 0x85, 0x57, 0x42, 0xf8, 0x26, 0x6e, 0xdb, 0x28, 0x85, 0xfd, 0x4d, 0x60, + 0xf1, 0x09, 0x7b, 0xe5, 0x2d, 0xfd, 0xe9, 0x38, 0x08, 0x87, 0xc8, 0x0d, 0x15, 0x73, 0x60, 0x4f, 0x03, 0x16, 0x9b, + 0xf8, 0x6a, 0x33, 0x89, 0x07, 0x03, 0x5f, 0x67, 0x2c, 0x66, 0x31, 0xd0, 0x20, 0xc7, 0x83, 0xcb, 0xb9, 0x3e, 0x21, + 0xf4, 0xc3, 0x88, 0xca, 0x51, 0x81, 0xce, 0x41, 0x34, 0x58, 0x02, 0x9e, 0x7a, 0x2b, 0x1b, 0x24, 0x19, 0xc7, 0x90, + 0xc4, 0xb5, 0x26, 0xa9, 0x0e, 0x27, 0xb4, 0x0e, 0x74, 0x5c, 0x5d, 0x40, 0xe7, 0xe3, 0xba, 0xf7, 0xf1, 0x6a, 0xb8, + 0xa0, 0xd2, 0x2f, 0xc4, 0xc0, 0xab, 0xa7, 0xe3, 0xe0, 0x92, 0x6e, 0x85, 0x8b, 0x55, 0xb8, 0x7d, 0x2d, 0x1f, 0x38, + 0xee, 0xa8, 0xa4, 0x21, 0x30, 0x78, 0x7b, 0xe8, 0x6e, 0x66, 0xbc, 0x43, 0x8e, 0x0e, 0xe3, 0x4c, 0x0e, 0xb1, 0x6a, + 0xc5, 0x85, 0xf4, 0x46, 0xf0, 0xed, 0x42, 0x31, 0x96, 0x8d, 0x5d, 0x1a, 0x8a, 0xc2, 0xbf, 0x01, 0xd8, 0xa1, 0xf6, + 0x57, 0x2a, 0xf9, 0x18, 0x19, 0xd5, 0x34, 0xd0, 0x31, 0x00, 0x4b, 0x96, 0x26, 0x92, 0x2a, 0xd2, 0x48, 0xfc, 0x91, + 0x35, 0xd6, 0x4d, 0xd7, 0x17, 0x4c, 0x55, 0xc3, 0xa4, 0xdb, 0x99, 0xc4, 0x72, 0x22, 0x49, 0x6d, 0xf7, 0x11, 0x31, + 0x18, 0xf8, 0x60, 0x23, 0xa6, 0x99, 0x08, 0x47, 0x3c, 0x2a, 0x91, 0x45, 0x97, 0xdf, 0x46, 0x94, 0xb4, 0x7d, 0x59, + 0x91, 0x2d, 0x08, 0xa6, 0x27, 0xd1, 0x07, 0x49, 0xca, 0xa9, 0x48, 0xa4, 0x19, 0x21, 0xc0, 0x8f, 0x27, 0xe5, 0x95, + 0xfe, 0x1c, 0x34, 0xad, 0x04, 0x2f, 0x19, 0x24, 0x8f, 0xc4, 0xcf, 0xa4, 0x60, 0x16, 0x63, 0xd5, 0x60, 0x80, 0xe5, + 0x54, 0x8f, 0x1d, 0x93, 0xf4, 0xdf, 0x3a, 0x9d, 0xb0, 0x9f, 0x79, 0xb9, 0xad, 0xe5, 0x4d, 0x73, 0xef, 0x99, 0x57, + 0xb1, 0x54, 0xc3, 0x32, 0xe8, 0xbf, 0x26, 0xda, 0x05, 0x5b, 0x5b, 0xc6, 0x84, 0x55, 0x3f, 0x80, 0xb4, 0x47, 0xba, + 0xbc, 0x6a, 0x98, 0x33, 0xc1, 0xa3, 0x0b, 0x6b, 0x1e, 0x44, 0x17, 0xc2, 0x47, 0x2e, 0xbb, 0x49, 0x72, 0x35, 0x9e, + 0xf8, 0xe1, 0x60, 0xa0, 0x00, 0x68, 0x69, 0x9d, 0x14, 0x83, 0xf0, 0xb1, 0x90, 0x03, 0x69, 0x74, 0x54, 0x05, 0x58, + 0x2c, 0xb3, 0xab, 0x72, 0x92, 0x0d, 0x06, 0x3e, 0x88, 0x8d, 0x89, 0xdd, 0xd0, 0x6c, 0xee, 0xb3, 0x13, 0x05, 0x59, + 0x6d, 0xce, 0x5a, 0x33, 0xdd, 0x02, 0x03, 0x80, 0x41, 0x44, 0xb0, 0xdc, 0x27, 0x46, 0x3e, 0xa2, 0x4e, 0x4f, 0x61, + 0x04, 0x04, 0xbf, 0x9c, 0x08, 0x44, 0x2e, 0x12, 0xa8, 0x07, 0x98, 0x09, 0x30, 0xa3, 0x8a, 0xe1, 0x25, 0xb0, 0x8b, + 0xe7, 0xe6, 0x15, 0x83, 0xfe, 0x45, 0xbb, 0x44, 0xa2, 0xa9, 0xc4, 0xd1, 0x18, 0x39, 0x95, 0xc6, 0xc8, 0x80, 0xd8, + 0xc5, 0xf1, 0xef, 0x29, 0x3d, 0x0a, 0x52, 0xf6, 0xbc, 0x32, 0xc4, 0xe1, 0x28, 0xbe, 0x82, 0x55, 0xe3, 0x70, 0xa8, + 0xcd, 0xeb, 0xe9, 0xac, 0x9e, 0x0f, 0x44, 0x00, 0xff, 0x0d, 0x05, 0xfb, 0x55, 0x53, 0x91, 0x1b, 0xa4, 0xce, 0xc3, + 0x21, 0x05, 0xf9, 0xd4, 0x58, 0x65, 0x2b, 0x77, 0x3f, 0x9d, 0xcd, 0xad, 0x39, 0x7a, 0x51, 0xe3, 0xba, 0xb5, 0xba, + 0xa1, 0x90, 0x68, 0x4d, 0x93, 0xe2, 0xaa, 0x9a, 0x14, 0x03, 0x9e, 0xfb, 0x42, 0x75, 0xb1, 0x35, 0x82, 0x85, 0x3f, + 0xb7, 0x40, 0x98, 0xf4, 0xb7, 0xe2, 0x0e, 0xa9, 0x1a, 0x77, 0x6d, 0xb5, 0xdb, 0x56, 0x36, 0xa4, 0x68, 0x3e, 0xbc, + 0x84, 0x5d, 0x3a, 0x45, 0xb4, 0xed, 0x92, 0xe0, 0x0b, 0xd0, 0xb2, 0xba, 0x10, 0x79, 0x4c, 0xbf, 0x42, 0x7e, 0x29, + 0x86, 0x7f, 0x95, 0xee, 0xcd, 0xa9, 0x0d, 0x72, 0x00, 0xdb, 0xbd, 0x87, 0xdb, 0x31, 0x7a, 0x20, 0x83, 0x37, 0x42, + 0xce, 0x39, 0xbf, 0x9c, 0x5a, 0x33, 0x26, 0x1a, 0x16, 0xac, 0x1c, 0x46, 0x7e, 0x80, 0x8c, 0x97, 0x53, 0x60, 0x65, + 0x3f, 0x2a, 0xe2, 0xd2, 0x1f, 0x46, 0xfe, 0xc5, 0x93, 0x20, 0xe3, 0x5e, 0x34, 0xec, 0xf8, 0x02, 0xec, 0xd5, 0x17, + 0x4f, 0x58, 0x34, 0xe0, 0xd5, 0x55, 0x3d, 0xcd, 0x82, 0x61, 0xc6, 0xa2, 0xab, 0x62, 0x08, 0x3e, 0xb4, 0x4f, 0xcb, + 0x41, 0xe8, 0xfb, 0x66, 0xe7, 0x30, 0xc6, 0x64, 0x79, 0x84, 0xfd, 0x0c, 0x6e, 0xbb, 0x5a, 0x62, 0x06, 0x93, 0xcd, + 0x6d, 0xc4, 0x0c, 0xb6, 0xfc, 0xc5, 0x13, 0xc3, 0x25, 0x54, 0x3d, 0x95, 0x9a, 0x8d, 0x02, 0xcd, 0xc9, 0x15, 0x9a, + 0x93, 0x95, 0x50, 0x4b, 0x3e, 0xa9, 0x70, 0xc2, 0xce, 0x27, 0xb9, 0xb2, 0x1b, 0x8d, 0x31, 0x70, 0xd1, 0xde, 0x9a, + 0x84, 0x91, 0x99, 0xce, 0x52, 0x34, 0x60, 0xe1, 0x99, 0x38, 0xa5, 0x31, 0xa0, 0x7d, 0x39, 0xb0, 0xb4, 0x21, 0xbf, + 0xc8, 0x99, 0x81, 0xb6, 0x21, 0xa5, 0x51, 0x33, 0xf0, 0x67, 0x6a, 0xc2, 0xfc, 0x06, 0x56, 0x22, 0x88, 0xea, 0x02, + 0x4c, 0x92, 0x9c, 0x8c, 0x46, 0xca, 0x4a, 0x24, 0xe7, 0x80, 0xf7, 0x01, 0x3c, 0x59, 0xc4, 0xb6, 0xf6, 0xa7, 0xf4, + 0xbf, 0x3a, 0x7c, 0x2e, 0xfd, 0xc7, 0x02, 0x58, 0xc8, 0xa5, 0x41, 0x64, 0xa0, 0x70, 0x48, 0x2d, 0xc7, 0x98, 0xc4, + 0xf1, 0x0c, 0x7c, 0x09, 0x17, 0x68, 0x0a, 0xe8, 0x0f, 0x6a, 0x46, 0x11, 0x59, 0xf8, 0xab, 0x67, 0x37, 0x75, 0xad, + 0xe7, 0x99, 0xf3, 0x1a, 0x34, 0x33, 0x10, 0xd2, 0xe3, 0x54, 0xbd, 0x0d, 0x89, 0xce, 0xcb, 0xb7, 0xfa, 0x65, 0x42, + 0x24, 0x0b, 0x23, 0x4f, 0xdf, 0xe7, 0x60, 0x1e, 0x51, 0x84, 0x0e, 0xae, 0xcc, 0xc3, 0xe1, 0x5c, 0x50, 0xf8, 0x8e, + 0xf2, 0x7c, 0xc0, 0x69, 0x96, 0x24, 0xa0, 0x0d, 0x64, 0xb9, 0x29, 0x73, 0x95, 0xb4, 0x4c, 0xdd, 0x7b, 0xb0, 0x12, + 0x54, 0xe8, 0xe6, 0x14, 0x14, 0xca, 0x48, 0x50, 0x4a, 0xab, 0x41, 0x28, 0xd5, 0x61, 0x11, 0x44, 0x0e, 0x59, 0x08, + 0xb8, 0x99, 0x8a, 0x46, 0x4b, 0x1a, 0x1e, 0xe1, 0xdc, 0x40, 0x21, 0x00, 0x89, 0x3d, 0x55, 0x94, 0x71, 0x39, 0x04, + 0x7c, 0x94, 0x70, 0x88, 0xb3, 0x26, 0x6d, 0x79, 0x0e, 0xe2, 0x58, 0x2e, 0xf9, 0x6d, 0x85, 0x60, 0x10, 0xa1, 0xcf, + 0x90, 0x3f, 0x59, 0xce, 0xbf, 0x1b, 0x87, 0x69, 0x47, 0xf8, 0xb0, 0xab, 0x2d, 0xb8, 0x98, 0xdd, 0xcc, 0x27, 0x10, + 0xdf, 0x72, 0x33, 0x3f, 0xc6, 0x10, 0x59, 0xf8, 0x83, 0xdb, 0xa1, 0xe4, 0x8a, 0x42, 0x97, 0xf5, 0x88, 0x14, 0xd9, + 0xd3, 0x35, 0x47, 0x10, 0x1c, 0x68, 0xd5, 0x20, 0x43, 0x23, 0xf1, 0xc5, 0x13, 0xc8, 0x1a, 0xac, 0xf9, 0xf3, 0x8a, + 0x9c, 0xd5, 0xfd, 0xc9, 0x06, 0xaa, 0x49, 0x26, 0x6b, 0x45, 0xe5, 0xfc, 0xed, 0xaa, 0x2c, 0x4f, 0x56, 0x65, 0xb8, + 0x1a, 0x74, 0x55, 0x65, 0xc9, 0x91, 0xda, 0x00, 0xad, 0xe9, 0x0a, 0x31, 0x14, 0xb2, 0x06, 0x4b, 0xab, 0x2a, 0x6b, + 0xea, 0x13, 0x08, 0xf4, 0x01, 0x96, 0x51, 0xb3, 0x9f, 0x0e, 0x7f, 0x09, 0x7e, 0x51, 0x21, 0x4b, 0x75, 0x5a, 0x67, + 0xe2, 0xb7, 0x60, 0xc9, 0xf0, 0x8f, 0xdf, 0x83, 0x35, 0x60, 0x09, 0x90, 0xe5, 0x6e, 0x63, 0xa3, 0xf5, 0xaa, 0xf8, + 0xb9, 0x5a, 0x5f, 0xf4, 0x5b, 0xb7, 0x89, 0x5a, 0x01, 0x46, 0x28, 0xb4, 0x08, 0xb0, 0xd5, 0x03, 0xf7, 0x14, 0xfc, + 0x40, 0x0c, 0xe7, 0x9a, 0xb4, 0xa6, 0x4e, 0x78, 0x9d, 0x8d, 0x23, 0x11, 0xd5, 0x5b, 0xb8, 0xb8, 0xd7, 0x5b, 0x8b, + 0xbf, 0x51, 0x81, 0x00, 0xc8, 0x62, 0x8a, 0xb5, 0xf3, 0x86, 0xf4, 0xca, 0xb0, 0x93, 0xd0, 0x7b, 0xc3, 0x4e, 0x20, + 0x2f, 0x0e, 0x3b, 0x85, 0x2e, 0xd1, 0x76, 0x8a, 0xd4, 0x44, 0xdb, 0x49, 0x8b, 0x55, 0x58, 0x42, 0xf0, 0xab, 0xf6, + 0xd6, 0x51, 0xb6, 0x2f, 0xb2, 0x84, 0x69, 0x0b, 0x18, 0xe5, 0x56, 0x7d, 0xe6, 0x14, 0xb1, 0x52, 0xf6, 0x4e, 0x27, + 0x55, 0xee, 0x22, 0x9f, 0x5a, 0x4d, 0x91, 0xc9, 0xcf, 0x8f, 0x5b, 0x24, 0x9f, 0xbc, 0x6e, 0x37, 0x4c, 0xa6, 0x7f, + 0x38, 0xfa, 0x02, 0xba, 0x22, 0x3b, 0x7d, 0x02, 0x01, 0x99, 0x0a, 0xaa, 0xd5, 0xad, 0x62, 0x9a, 0xb7, 0xab, 0xec, + 0xf6, 0x42, 0x89, 0xe1, 0x74, 0x76, 0x12, 0x1e, 0x6d, 0x86, 0x0c, 0x1c, 0x82, 0x40, 0x21, 0x54, 0x14, 0xc3, 0x23, + 0x50, 0x6b, 0x24, 0x1f, 0xe0, 0x47, 0xbb, 0x53, 0x41, 0xa4, 0x76, 0x53, 0x71, 0xe3, 0xe4, 0xa6, 0xeb, 0xa5, 0x40, + 0xad, 0x53, 0xb2, 0x02, 0x28, 0x21, 0xea, 0x4f, 0x62, 0x5b, 0x5f, 0xc3, 0x15, 0x9b, 0xef, 0x1b, 0x45, 0x4f, 0xae, + 0x4f, 0x51, 0xb7, 0xe2, 0xea, 0x34, 0x6d, 0x35, 0xc7, 0x8e, 0x33, 0xe4, 0xe0, 0x59, 0x41, 0xb0, 0x1d, 0x95, 0x28, + 0xdf, 0xb4, 0x9b, 0x8e, 0x89, 0xad, 0xfe, 0x59, 0x54, 0x9b, 0x5b, 0xa8, 0x88, 0x88, 0x8f, 0xb2, 0x9b, 0x27, 0xed, + 0x77, 0xb0, 0xc7, 0x5a, 0x0d, 0x22, 0xfb, 0x0c, 0xae, 0x72, 0x9d, 0x16, 0xb9, 0x2d, 0x83, 0xf3, 0x0f, 0xaf, 0x76, + 0x15, 0x36, 0x39, 0xd6, 0xd5, 0xd5, 0x4c, 0x75, 0x52, 0xb1, 0x81, 0xb1, 0xa6, 0xb5, 0x54, 0xf3, 0x18, 0x92, 0xee, + 0xca, 0xe2, 0xac, 0x4a, 0xba, 0xe9, 0xb9, 0x71, 0xa6, 0x10, 0x03, 0x67, 0xab, 0xd1, 0x72, 0x86, 0x21, 0xba, 0x3e, + 0xcc, 0x12, 0xbf, 0xd5, 0x53, 0xee, 0xf3, 0x70, 0xeb, 0x77, 0xf5, 0x82, 0x93, 0xc9, 0x7e, 0x72, 0x9c, 0xbb, 0x5d, + 0xa4, 0xfd, 0xc4, 0xb7, 0x61, 0xfe, 0xf5, 0x0d, 0xe2, 0x56, 0xd4, 0xbf, 0x54, 0x00, 0x34, 0xb8, 0xc9, 0x63, 0x89, + 0x52, 0xbf, 0x57, 0xd5, 0x0f, 0x6a, 0xa6, 0x6a, 0x1a, 0x08, 0xe6, 0x54, 0x0a, 0xf8, 0xc3, 0xed, 0xc2, 0x15, 0x8f, + 0xb8, 0x61, 0x61, 0xfc, 0xe2, 0xd5, 0xec, 0x54, 0x50, 0x19, 0xb8, 0x19, 0x7f, 0xf1, 0x04, 0x3b, 0x85, 0xb5, 0x02, + 0xb2, 0xc2, 0x17, 0x2f, 0x7f, 0xe0, 0xfd, 0x8a, 0x7f, 0xf1, 0xaa, 0x07, 0xde, 0x47, 0x9c, 0x97, 0x2f, 0x48, 0xea, + 0x84, 0xa8, 0x2e, 0x5f, 0x08, 0x53, 0x6c, 0x95, 0xe6, 0x2f, 0x48, 0xe1, 0x13, 0x7c, 0x06, 0xbe, 0xc3, 0x55, 0xb8, + 0x35, 0xbf, 0xc1, 0x63, 0xc7, 0x62, 0xdb, 0xa5, 0xbe, 0x80, 0x72, 0x04, 0x16, 0x91, 0xdb, 0x6f, 0x57, 0xf6, 0xab, + 0x85, 0x51, 0xc6, 0xd8, 0x7d, 0xc9, 0x4a, 0x94, 0xce, 0xfa, 0xfd, 0x42, 0x0a, 0x46, 0x76, 0x61, 0x8d, 0xf6, 0x28, + 0x55, 0xaf, 0xbe, 0x09, 0xeb, 0x28, 0x49, 0xf3, 0x5b, 0x19, 0x7d, 0x24, 0xc3, 0x8e, 0xf4, 0x95, 0x94, 0x68, 0xaf, + 0x55, 0x58, 0x8e, 0x66, 0xbf, 0x2e, 0x39, 0x50, 0x5e, 0xb7, 0x82, 0xf2, 0x55, 0x13, 0x40, 0xaf, 0x54, 0xfb, 0x0c, + 0xb4, 0x82, 0xc2, 0x52, 0x79, 0xb0, 0x12, 0xe7, 0xa2, 0xcf, 0x8a, 0xc3, 0x41, 0x5d, 0x0c, 0x09, 0x05, 0xaa, 0xc4, + 0x49, 0x68, 0xc4, 0x73, 0xb8, 0x10, 0x8a, 0xa7, 0x39, 0xc6, 0x56, 0xe4, 0xc0, 0x81, 0x0c, 0x3f, 0x20, 0xf0, 0x5e, + 0xf6, 0xaf, 0x60, 0x30, 0x4c, 0x70, 0x23, 0xa3, 0x4e, 0xce, 0xd9, 0x17, 0x0c, 0xcc, 0xa0, 0x9e, 0xd4, 0xee, 0xb3, + 0x7b, 0x15, 0xd8, 0x0b, 0x67, 0x40, 0x7b, 0x37, 0x46, 0x3f, 0xab, 0x62, 0xed, 0xa4, 0x7f, 0x2a, 0xd6, 0x90, 0x4c, + 0x87, 0xc5, 0xd1, 0x36, 0x0d, 0x8f, 0xe4, 0xc9, 0x71, 0xbc, 0xe9, 0x1f, 0x0e, 0x63, 0xfc, 0x38, 0xca, 0xaf, 0x2d, + 0xe0, 0x55, 0xdc, 0x42, 0x1a, 0x8b, 0x14, 0xbd, 0x03, 0x31, 0x87, 0xa2, 0x97, 0xec, 0xb7, 0x8c, 0x97, 0x13, 0x41, + 0x29, 0x49, 0x6c, 0x78, 0x47, 0x7a, 0x9a, 0xd6, 0xa3, 0xad, 0x0c, 0xd8, 0xaf, 0x47, 0x3b, 0xfa, 0x0b, 0x14, 0x8f, + 0x16, 0xfe, 0x92, 0xfe, 0x2e, 0xee, 0xe6, 0x9e, 0xf3, 0x4d, 0xe3, 0x3b, 0xe2, 0x02, 0xc5, 0x9a, 0xdd, 0x5f, 0xd3, + 0xd2, 0x59, 0x07, 0x82, 0x03, 0xde, 0x62, 0x17, 0xed, 0xfb, 0x8d, 0xeb, 0xf4, 0xb4, 0xff, 0xde, 0xad, 0x51, 0xbe, + 0xf7, 0x8b, 0x44, 0x39, 0xd8, 0xbf, 0x70, 0xd1, 0xfc, 0xed, 0xa7, 0x0c, 0x49, 0x85, 0xe6, 0x06, 0xdb, 0xc9, 0x16, + 0x61, 0x6d, 0x8c, 0x83, 0x8a, 0xdd, 0x96, 0x61, 0x04, 0x0c, 0xea, 0xd8, 0xff, 0xe8, 0xb3, 0x69, 0x43, 0xf6, 0x01, + 0xa0, 0x72, 0x15, 0x02, 0xf6, 0x00, 0x9c, 0x68, 0x84, 0x1b, 0xe0, 0x56, 0xa3, 0x25, 0x1d, 0xd4, 0x6d, 0xc1, 0x40, + 0xb4, 0x84, 0x8d, 0xbc, 0xed, 0xea, 0xf4, 0x0d, 0xe1, 0x43, 0xed, 0xa4, 0x74, 0x28, 0x7f, 0xf3, 0x9c, 0xfd, 0xcf, + 0x0e, 0x6b, 0x6a, 0xca, 0x47, 0xc0, 0xcc, 0x59, 0x89, 0xbc, 0x42, 0xe8, 0x14, 0xf9, 0xbd, 0xaa, 0x2b, 0x31, 0x5c, + 0xd6, 0xa2, 0xec, 0xcc, 0x6e, 0x9d, 0xe8, 0x9d, 0x53, 0x50, 0x4b, 0x65, 0x83, 0x9c, 0xa4, 0xda, 0x7c, 0x64, 0xad, + 0xa0, 0x44, 0x5d, 0xa3, 0xc0, 0xf1, 0x29, 0xd7, 0xee, 0xff, 0x9d, 0x33, 0x41, 0xcd, 0x36, 0xaa, 0xfb, 0x0b, 0xfd, + 0x54, 0xd5, 0x24, 0x16, 0xe0, 0x72, 0x92, 0xe6, 0x1d, 0x8f, 0xb0, 0xfa, 0xc7, 0xc9, 0x52, 0x04, 0xfa, 0x14, 0xd1, + 0xae, 0x04, 0x24, 0x68, 0x27, 0x67, 0xa1, 0x22, 0x50, 0xa0, 0xaf, 0x3f, 0xdf, 0xa4, 0x59, 0x2c, 0x57, 0xb3, 0x3d, + 0x4c, 0x94, 0xc5, 0x7a, 0x88, 0x20, 0x67, 0xa6, 0x0e, 0xf6, 0x7b, 0x9a, 0xd1, 0x2c, 0xbc, 0x32, 0x25, 0xb8, 0x14, + 0x57, 0x51, 0x91, 0x83, 0xcf, 0x21, 0xbe, 0xf0, 0xa9, 0x90, 0x1b, 0x44, 0x34, 0xfd, 0x59, 0xa2, 0xda, 0x91, 0x02, + 0x39, 0x94, 0xfc, 0x84, 0xf8, 0x4b, 0xd6, 0xc6, 0xb8, 0x5f, 0x3a, 0xd5, 0xbe, 0x56, 0x08, 0xee, 0xaf, 0x6d, 0xb1, + 0x51, 0xe5, 0x89, 0x1e, 0x7c, 0x8a, 0xf5, 0x3f, 0x59, 0x40, 0xa9, 0xee, 0xdb, 0xe0, 0x54, 0x3c, 0x0a, 0x37, 0x75, + 0xf1, 0x11, 0xa1, 0x05, 0xca, 0x51, 0x55, 0x6c, 0xca, 0x88, 0x38, 0x61, 0x37, 0x75, 0xd1, 0xd3, 0x1c, 0xe8, 0xd4, + 0x61, 0xe0, 0x80, 0x9a, 0x28, 0x11, 0xc5, 0x6e, 0x41, 0xf7, 0x34, 0xc7, 0x4a, 0x3c, 0x93, 0xa5, 0x83, 0xac, 0x13, + 0x69, 0x42, 0xe5, 0xae, 0xae, 0x3a, 0x2a, 0x95, 0xba, 0xe1, 0x65, 0xaa, 0x19, 0x7f, 0x97, 0xe6, 0x4f, 0x2c, 0xfb, + 0x65, 0xeb, 0xb7, 0x5a, 0xed, 0x8d, 0xd5, 0xa3, 0x92, 0x35, 0xc7, 0xd9, 0x84, 0xa4, 0xf4, 0x09, 0xdb, 0xcd, 0xa4, + 0x6b, 0x1d, 0x78, 0x12, 0x5c, 0x0e, 0x3d, 0x01, 0x15, 0x83, 0x26, 0xde, 0xee, 0x02, 0xf5, 0x08, 0x3c, 0x03, 0xe5, + 0x13, 0xb5, 0x0e, 0xf8, 0x79, 0xad, 0xe5, 0x29, 0x23, 0x0c, 0xab, 0x9d, 0x45, 0xcb, 0xc1, 0x79, 0xa7, 0x08, 0x5c, + 0xbb, 0x12, 0x78, 0x3e, 0x54, 0xef, 0x85, 0x80, 0xe1, 0xfe, 0xa9, 0x50, 0xd9, 0xec, 0x66, 0x38, 0x8f, 0x1a, 0xa7, + 0x07, 0xda, 0xdb, 0xae, 0xf5, 0x50, 0xef, 0xba, 0x9d, 0xdb, 0x4a, 0xf7, 0x7e, 0xed, 0x64, 0xd2, 0x05, 0xb4, 0x36, + 0x9f, 0x7d, 0x67, 0x57, 0x5a, 0x37, 0x3d, 0x67, 0x0f, 0xb6, 0x6e, 0x89, 0xce, 0x05, 0xd1, 0xe4, 0xf7, 0x03, 0xcf, + 0xda, 0x76, 0xf4, 0xdb, 0xb4, 0x63, 0x9b, 0x7b, 0xa8, 0x7b, 0x05, 0xb5, 0xde, 0xd0, 0xbc, 0x7f, 0xe6, 0xda, 0x76, + 0x7c, 0xf5, 0xeb, 0xba, 0xc3, 0x75, 0xde, 0x04, 0xc7, 0x4d, 0xd7, 0xb6, 0xda, 0xd9, 0xcf, 0xdd, 0xbd, 0xb5, 0x88, + 0xc2, 0x2c, 0xfb, 0xb9, 0x28, 0xfe, 0xac, 0xf4, 0x1d, 0x81, 0x8e, 0xee, 0xbc, 0xa8, 0xd3, 0xe5, 0xee, 0x3d, 0x61, + 0x3c, 0x79, 0xf5, 0x11, 0xd1, 0xad, 0xef, 0x33, 0xf7, 0x2b, 0xc0, 0x8d, 0xe0, 0x0e, 0xa2, 0xbd, 0x5b, 0xea, 0x93, + 0x5a, 0x7d, 0xad, 0xd7, 0xce, 0xd3, 0xf3, 0x9b, 0xce, 0xed, 0x77, 0xdf, 0x1c, 0x6d, 0xbd, 0xc7, 0x85, 0xb5, 0xb2, + 0xf4, 0x54, 0x15, 0xec, 0xcd, 0xf2, 0x54, 0x15, 0x4c, 0x1e, 0x78, 0xcd, 0x7e, 0x41, 0x83, 0x2b, 0x1d, 0x6d, 0xbc, + 0x27, 0x6a, 0xe0, 0x16, 0x85, 0xa5, 0xc3, 0x2f, 0xb9, 0x99, 0x5c, 0xe3, 0xfe, 0x52, 0x91, 0x8b, 0x7d, 0xe7, 0x8c, + 0xee, 0xcc, 0xac, 0x7b, 0x55, 0xe1, 0x6a, 0x41, 0xae, 0x0e, 0x6c, 0x2d, 0xbb, 0x38, 0xdc, 0xb0, 0x88, 0x02, 0x04, + 0x62, 0x7a, 0xa5, 0xd6, 0xfe, 0x88, 0x06, 0x21, 0x1f, 0x0c, 0xfc, 0x02, 0x83, 0x55, 0x81, 0xc2, 0x07, 0x8a, 0xe4, + 0x2f, 0x3c, 0x01, 0xbb, 0x78, 0x06, 0xe8, 0x56, 0x6c, 0x56, 0x8c, 0x10, 0x21, 0x93, 0xe5, 0xac, 0xa6, 0x33, 0xc8, + 0xa7, 0xbe, 0xf8, 0xce, 0x56, 0x9d, 0xce, 0xdb, 0x9a, 0x2a, 0xa7, 0x0e, 0x85, 0xee, 0x6e, 0xea, 0xce, 0xad, 0x8b, + 0x3c, 0x75, 0x08, 0xb9, 0x52, 0xb1, 0x12, 0xd3, 0x50, 0xf3, 0x24, 0xcd, 0xa8, 0xbf, 0xda, 0xfb, 0xbd, 0x46, 0xe1, + 0x94, 0x3f, 0x1d, 0x83, 0x2a, 0x5c, 0xd5, 0x10, 0xc7, 0x52, 0x15, 0x8f, 0x6c, 0x10, 0x68, 0x5e, 0xdd, 0xaa, 0xa4, + 0x09, 0x99, 0xdc, 0x08, 0x9f, 0x9a, 0x94, 0xf2, 0x34, 0x6d, 0xd2, 0x4a, 0x91, 0x3a, 0xf8, 0xa0, 0x4e, 0x35, 0x9e, + 0x9b, 0xd5, 0x53, 0x00, 0x33, 0xce, 0xaf, 0xf8, 0xa5, 0xe2, 0x32, 0x6a, 0x2b, 0x33, 0x69, 0x7f, 0x72, 0x34, 0x36, + 0xea, 0x72, 0xaa, 0xcc, 0x2b, 0x06, 0x7d, 0xfa, 0xb5, 0x3e, 0xff, 0x80, 0xc1, 0x9a, 0x27, 0xb0, 0x83, 0x89, 0x4a, + 0x79, 0x1f, 0x01, 0xf1, 0x75, 0x92, 0xde, 0x26, 0x90, 0x22, 0xfd, 0x4b, 0x97, 0x3c, 0x75, 0x18, 0x1b, 0x88, 0x31, + 0x2b, 0x66, 0x46, 0xff, 0x83, 0xbb, 0xa4, 0x3f, 0x09, 0x01, 0x70, 0x13, 0x4d, 0xa1, 0x53, 0xe7, 0xc9, 0x45, 0x1e, + 0x2c, 0x2f, 0x3c, 0xb4, 0x62, 0xc4, 0x83, 0xbf, 0x3e, 0x0d, 0x11, 0xc4, 0x1c, 0x53, 0x3c, 0xfd, 0xc2, 0xe8, 0x2f, + 0xc1, 0x25, 0x46, 0x10, 0xba, 0x7b, 0xe7, 0x30, 0x84, 0x9b, 0x3d, 0xc8, 0xa0, 0xfe, 0x50, 0x87, 0x44, 0x0d, 0x7f, + 0xa9, 0x3c, 0xe8, 0xff, 0x3a, 0x13, 0x96, 0xda, 0x4f, 0x4f, 0x07, 0x50, 0xc1, 0xfb, 0x8a, 0xb7, 0x11, 0xf1, 0x7d, + 0xe2, 0xc7, 0xf1, 0x60, 0xf3, 0x78, 0x03, 0xd6, 0xba, 0x67, 0xb9, 0xb1, 0xae, 0x12, 0x36, 0x10, 0xf0, 0x35, 0xa6, + 0xb5, 0xe7, 0xb5, 0xdb, 0x3d, 0xf8, 0xab, 0x7f, 0x11, 0x32, 0x60, 0xe2, 0xf4, 0x7d, 0xe6, 0x64, 0x8d, 0x2e, 0x32, + 0x99, 0x3e, 0x74, 0xd2, 0x37, 0x3a, 0xdd, 0x77, 0xc2, 0x3f, 0x2a, 0x66, 0xf1, 0xe1, 0x96, 0xbe, 0xd2, 0xa4, 0xb8, + 0x03, 0x56, 0x36, 0x0f, 0x0a, 0x42, 0x9d, 0x8b, 0xe8, 0x1b, 0x53, 0xbe, 0x25, 0xd4, 0xec, 0x1b, 0x4b, 0x4a, 0xe9, + 0x5e, 0x43, 0x2f, 0xd3, 0x5a, 0xbf, 0x8d, 0x12, 0x8c, 0x89, 0x8e, 0x27, 0x2f, 0xe3, 0xb1, 0xf2, 0x3e, 0x1e, 0x37, + 0x52, 0x21, 0x0f, 0x40, 0x04, 0x2a, 0xc6, 0x9f, 0xae, 0x3c, 0x39, 0xe9, 0x85, 0xf1, 0x2a, 0x94, 0x82, 0xc2, 0x80, + 0xae, 0x40, 0x0a, 0x78, 0xd4, 0x9e, 0xe8, 0x2c, 0xec, 0x12, 0xee, 0xd1, 0x4d, 0xc0, 0x58, 0x9f, 0x7f, 0x01, 0x34, + 0x77, 0xe1, 0x0e, 0x2f, 0x06, 0xa8, 0x4d, 0xbd, 0xba, 0xfb, 0xb8, 0x56, 0xe7, 0x70, 0x08, 0x0e, 0x56, 0x83, 0x08, + 0x4e, 0xe7, 0x53, 0x47, 0xb3, 0x2c, 0x40, 0xe5, 0x64, 0xb9, 0x91, 0x37, 0x8f, 0x16, 0xbd, 0xba, 0xef, 0x2d, 0xd3, + 0xb2, 0xaa, 0x83, 0x8c, 0x65, 0x61, 0x05, 0xb8, 0x3a, 0xb4, 0x7e, 0x10, 0x2e, 0x0b, 0xe7, 0x0f, 0x84, 0x20, 0x76, + 0xaf, 0xb6, 0x25, 0xcf, 0xd5, 0x1c, 0x7e, 0xfc, 0x84, 0xad, 0xb9, 0x44, 0x9d, 0x74, 0x26, 0x02, 0x10, 0x7b, 0x6a, + 0x56, 0xd1, 0x35, 0x90, 0xd4, 0x69, 0x56, 0xd1, 0x35, 0x35, 0xdb, 0x18, 0x07, 0xf2, 0xd1, 0x2a, 0x05, 0xec, 0xbb, + 0xe9, 0x38, 0x58, 0x3d, 0x8e, 0xe5, 0x75, 0xe8, 0xf6, 0xf1, 0x46, 0xf9, 0x0c, 0xea, 0x56, 0x1b, 0x63, 0x62, 0xbb, + 0xf9, 0x72, 0xae, 0xdf, 0x0c, 0x96, 0xbe, 0x1d, 0x34, 0xe7, 0x94, 0x7d, 0xab, 0xcb, 0x5e, 0xd9, 0x65, 0x53, 0xcf, + 0x1d, 0x15, 0xad, 0xc6, 0x80, 0xde, 0xc0, 0x82, 0xf5, 0xb9, 0x48, 0xb3, 0x55, 0xa9, 0x4a, 0xc0, 0x0b, 0x63, 0xc5, + 0x6e, 0xfd, 0x46, 0x66, 0x48, 0xc2, 0x3c, 0xce, 0xc4, 0x1b, 0xba, 0xd7, 0xc2, 0xe4, 0x38, 0x16, 0xc9, 0x94, 0xd0, + 0x29, 0xdd, 0xd9, 0x86, 0xce, 0x55, 0x18, 0x45, 0xb4, 0x56, 0x52, 0x69, 0x24, 0x30, 0x35, 0x03, 0x94, 0xcc, 0x15, + 0x38, 0xa5, 0xcb, 0xfd, 0xef, 0x48, 0x8c, 0x33, 0x5f, 0x94, 0xcc, 0x80, 0x6e, 0xf9, 0x75, 0xb1, 0x6e, 0xa5, 0xc8, + 0x08, 0xf3, 0xe6, 0xb8, 0xbd, 0xae, 0x0f, 0x81, 0x5c, 0x2d, 0x7b, 0x14, 0x8d, 0x83, 0x42, 0x87, 0x4b, 0x95, 0x00, + 0xfb, 0x22, 0xf1, 0x33, 0xc2, 0x96, 0xf6, 0x40, 0x6e, 0x8f, 0xce, 0x84, 0x39, 0xe7, 0xa4, 0x2c, 0x3b, 0x97, 0x66, + 0x70, 0x39, 0x71, 0x25, 0xb8, 0x48, 0x6f, 0xdb, 0xd3, 0xa4, 0xa5, 0xed, 0x63, 0xc3, 0x39, 0x1a, 0xda, 0x06, 0xdd, + 0xb1, 0x3f, 0x34, 0x17, 0x8b, 0xd8, 0xba, 0x58, 0x0c, 0x3b, 0xb3, 0x1f, 0x2d, 0x16, 0x20, 0x07, 0x80, 0xa3, 0x6e, + 0xc3, 0xc7, 0x6c, 0x09, 0x9c, 0x56, 0xd3, 0x6c, 0xea, 0x6d, 0x78, 0xf5, 0x58, 0xf5, 0xf4, 0x92, 0xe7, 0x8f, 0x85, + 0x19, 0x8b, 0x0d, 0xcf, 0x1f, 0x5b, 0x47, 0x4e, 0xf5, 0x58, 0x28, 0xd1, 0xba, 0x80, 0x66, 0xe0, 0x35, 0x05, 0x8c, + 0x58, 0x32, 0x99, 0x52, 0x45, 0x1e, 0xf7, 0xa6, 0x1b, 0x35, 0x78, 0x41, 0xe1, 0x10, 0x48, 0xe9, 0xf4, 0x8b, 0x27, + 0x4c, 0xbf, 0x77, 0xf1, 0xa4, 0x43, 0xd6, 0x36, 0x4c, 0x97, 0x9b, 0x61, 0x32, 0x28, 0xfd, 0xc7, 0x66, 0x62, 0x5c, + 0x58, 0x93, 0x04, 0x10, 0xff, 0xc6, 0x7e, 0x87, 0x14, 0x6e, 0xde, 0x5f, 0x0e, 0xe3, 0x07, 0xde, 0x8f, 0x91, 0x3d, + 0x49, 0x33, 0xc4, 0x9a, 0x49, 0x85, 0xdc, 0x7d, 0xb5, 0xfe, 0x31, 0xb1, 0x9b, 0xec, 0x81, 0x05, 0x20, 0xb6, 0xa6, + 0xad, 0x6e, 0x79, 0xbf, 0xef, 0x99, 0x22, 0xc0, 0x0f, 0xca, 0x3f, 0xba, 0x33, 0x24, 0x83, 0xb2, 0xeb, 0x86, 0x10, + 0x0f, 0xca, 0xa6, 0x69, 0xaf, 0xb7, 0xbd, 0x33, 0x8f, 0xd5, 0x75, 0xda, 0x59, 0x5c, 0x2d, 0x32, 0x48, 0xab, 0x0f, + 0xd9, 0x71, 0x66, 0x9f, 0x1d, 0x2d, 0x95, 0xee, 0xf7, 0x21, 0x22, 0xee, 0x28, 0x6b, 0xfb, 0xed, 0x16, 0x5c, 0xc3, + 0xd1, 0x20, 0x74, 0x65, 0x6f, 0x97, 0xd1, 0xc6, 0x85, 0x38, 0xee, 0x99, 0xce, 0x17, 0x7c, 0x79, 0x94, 0x76, 0x1e, + 0x9c, 0xea, 0x89, 0x3e, 0x37, 0xdd, 0x55, 0x26, 0xd7, 0x3a, 0xac, 0xc6, 0xa0, 0x36, 0x0b, 0x5b, 0xb8, 0x0b, 0xdb, + 0xe8, 0xa0, 0xb5, 0x2f, 0x0b, 0xfe, 0x29, 0x03, 0xf0, 0xa5, 0x67, 0xcb, 0xb6, 0xd7, 0xa4, 0xd5, 0x4b, 0x19, 0x85, + 0xd8, 0xd2, 0xf6, 0xea, 0xd3, 0x51, 0x3e, 0x6e, 0x4e, 0x28, 0x2e, 0xe4, 0x28, 0x3f, 0x78, 0x0d, 0x51, 0xd7, 0xba, + 0x8e, 0x8b, 0x45, 0x87, 0x1b, 0x57, 0xdd, 0x76, 0xe3, 0x7a, 0x85, 0x78, 0x6b, 0xb4, 0x49, 0xa1, 0x56, 0xc6, 0x8e, + 0xe0, 0x65, 0xf9, 0x70, 0xc8, 0xc4, 0x70, 0x28, 0x21, 0x53, 0x1f, 0xba, 0x37, 0x34, 0xed, 0xf3, 0xd3, 0xd6, 0x8f, + 0x58, 0x6a, 0x1c, 0xc5, 0x86, 0x77, 0xfa, 0xce, 0x63, 0x6b, 0x5c, 0xc9, 0x97, 0xc1, 0x6c, 0x57, 0x50, 0x6d, 0x8d, + 0x37, 0xec, 0xe5, 0xfc, 0xe7, 0x4a, 0x2a, 0xf9, 0xdb, 0x9f, 0xe1, 0x1a, 0xde, 0xda, 0xd2, 0x41, 0x53, 0xcd, 0x72, + 0x96, 0xeb, 0x7b, 0xc1, 0xf1, 0xc7, 0xdd, 0x2b, 0x82, 0xc1, 0xef, 0xe9, 0x28, 0xc8, 0xc5, 0x52, 0xad, 0x01, 0x05, + 0xe9, 0xc8, 0x8e, 0xa9, 0x2c, 0x30, 0x0c, 0xe0, 0x0d, 0x19, 0x20, 0x8f, 0x29, 0xdc, 0x0d, 0x15, 0x5e, 0xf8, 0x6b, + 0x45, 0x76, 0x09, 0x6c, 0x6b, 0xc6, 0xc7, 0x0c, 0x77, 0x10, 0xf2, 0x8f, 0x60, 0xb7, 0x6c, 0xc5, 0x6e, 0xd8, 0x82, + 0x21, 0xd9, 0x38, 0x0e, 0x63, 0xcc, 0xc7, 0x93, 0xf8, 0x4a, 0x4c, 0xe2, 0x01, 0x8f, 0xd0, 0x31, 0x62, 0xcd, 0xeb, + 0x59, 0x2c, 0x07, 0x90, 0xdd, 0x72, 0xa5, 0x03, 0x42, 0x68, 0x6c, 0x68, 0xc9, 0xcb, 0xc2, 0xe0, 0x62, 0xc7, 0x3e, + 0x23, 0x91, 0x8c, 0x43, 0xb0, 0x68, 0x55, 0x03, 0x0b, 0x13, 0xbb, 0xe1, 0xc5, 0x6c, 0x35, 0xc7, 0x7f, 0x0e, 0x07, + 0x04, 0xc0, 0x0e, 0xf6, 0x0d, 0xbb, 0x8d, 0x10, 0xe9, 0x6d, 0xc1, 0x6f, 0x2d, 0x4f, 0x17, 0x76, 0xc7, 0xaf, 0xf9, + 0x98, 0x9d, 0xbf, 0xf2, 0x20, 0x72, 0xf6, 0xfc, 0x03, 0xa0, 0x21, 0xde, 0xf1, 0x9b, 0xd4, 0xab, 0xd8, 0x0d, 0x51, + 0x10, 0xde, 0x80, 0x33, 0xd0, 0x1d, 0x44, 0xc0, 0x5e, 0xf3, 0x05, 0xc6, 0x8a, 0x9d, 0xa5, 0x4b, 0x0f, 0x33, 0x42, + 0xed, 0xe9, 0x7c, 0x59, 0xab, 0x49, 0xb8, 0xb9, 0x5a, 0x4e, 0x06, 0x83, 0x8d, 0xbf, 0xe3, 0x6b, 0xe0, 0x83, 0x39, + 0x7f, 0xe5, 0xed, 0xa8, 0x5c, 0xf8, 0xcf, 0xeb, 0x2c, 0x79, 0xe7, 0xb3, 0xeb, 0x01, 0x5f, 0x00, 0xde, 0x12, 0x3a, + 0x70, 0xdd, 0xf9, 0x4c, 0xe2, 0xb5, 0x5d, 0xeb, 0x6b, 0x04, 0x12, 0xf9, 0x02, 0x30, 0x62, 0x62, 0x7e, 0x5f, 0x43, + 0x04, 0xc6, 0x06, 0x7c, 0x5b, 0xb5, 0x47, 0xfc, 0x96, 0x1b, 0xc0, 0xaf, 0xcc, 0x67, 0xf7, 0x3c, 0xd4, 0x3f, 0x13, + 0x9f, 0xbd, 0xe1, 0x8f, 0xf8, 0x53, 0x4f, 0x4a, 0xd2, 0xe5, 0xec, 0xd1, 0x1c, 0xae, 0x87, 0x52, 0x9e, 0x0e, 0xe9, + 0x67, 0x63, 0x30, 0x80, 0x50, 0xc8, 0x7c, 0xe3, 0x01, 0x6b, 0x52, 0x88, 0x7f, 0x01, 0xdf, 0x8e, 0x12, 0x36, 0xdf, + 0x78, 0x5b, 0x5f, 0xcb, 0x9b, 0x6f, 0xbc, 0x7b, 0x9f, 0xa2, 0x00, 0xab, 0xa0, 0x94, 0x05, 0x56, 0x41, 0xd8, 0x68, + 0x23, 0x8c, 0x81, 0xab, 0x77, 0x8d, 0xa1, 0xae, 0xe7, 0x88, 0x6d, 0x2b, 0x7d, 0x1b, 0xbe, 0x85, 0x0c, 0xf8, 0xe0, + 0x65, 0x51, 0x12, 0x7d, 0x4e, 0x4d, 0x91, 0xb4, 0xee, 0xb9, 0xdf, 0x5a, 0x77, 0xb4, 0xa6, 0xd4, 0x47, 0xae, 0xc6, + 0x87, 0x43, 0xfd, 0x54, 0x68, 0x91, 0x60, 0x0a, 0x1a, 0xd7, 0xa0, 0x2d, 0x40, 0xd0, 0xe7, 0x01, 0xb2, 0x96, 0x14, + 0x0b, 0xbe, 0xfd, 0x15, 0x62, 0xf0, 0xca, 0xf4, 0xce, 0xe5, 0x2a, 0x23, 0x61, 0x7b, 0xe1, 0x97, 0xc3, 0xda, 0x9f, + 0x38, 0xb5, 0xb0, 0xb4, 0x9a, 0x83, 0xfa, 0xb1, 0x2d, 0xc7, 0xe9, 0xaa, 0x45, 0x5e, 0x87, 0xd2, 0x72, 0x7a, 0x67, + 0xdf, 0x74, 0x99, 0x60, 0x63, 0x3f, 0xa0, 0xea, 0xc8, 0x6a, 0xd8, 0x7d, 0xa1, 0xbe, 0xe8, 0x29, 0x99, 0xd0, 0x7c, + 0x54, 0xd1, 0x3c, 0xb7, 0xbe, 0x79, 0x5c, 0xff, 0xe9, 0xe5, 0x50, 0x04, 0x48, 0x56, 0x69, 0xb1, 0x14, 0x39, 0x1b, + 0xfb, 0xf1, 0x30, 0xc9, 0x54, 0x78, 0x41, 0x3a, 0xba, 0xfb, 0x8d, 0xfb, 0x5b, 0x6e, 0x20, 0x2b, 0xb4, 0x6a, 0x83, + 0xb1, 0x52, 0xb4, 0x0c, 0xd6, 0x57, 0xe3, 0x7e, 0x5f, 0x5c, 0x8d, 0xa7, 0x22, 0xa8, 0x81, 0xb8, 0x48, 0x3c, 0x1d, + 0x4f, 0x6b, 0x62, 0x49, 0xed, 0x0a, 0x8c, 0xd1, 0xe3, 0xaa, 0xa8, 0x7d, 0xea, 0xa7, 0x10, 0x8a, 0x54, 0x6b, 0xe6, + 0x58, 0xe3, 0xc6, 0x88, 0xb8, 0xc3, 0xca, 0xb5, 0x53, 0x7b, 0x1d, 0x80, 0xe5, 0xd5, 0xb8, 0x20, 0xac, 0x93, 0x63, + 0xe7, 0x02, 0x56, 0xa3, 0x21, 0xd5, 0x6e, 0xb8, 0xf5, 0xb2, 0xf3, 0x9b, 0x2f, 0x13, 0x5b, 0x1b, 0xe1, 0x96, 0x02, + 0xca, 0x28, 0xbf, 0xb1, 0x9c, 0xb0, 0x3b, 0xd5, 0x3b, 0x52, 0xb5, 0x23, 0x4e, 0x5c, 0xc0, 0x72, 0xc3, 0x53, 0xab, + 0x6f, 0x62, 0x70, 0x22, 0x54, 0xad, 0x74, 0xb8, 0x93, 0x09, 0xc4, 0xfd, 0xea, 0xbe, 0xee, 0x95, 0xe0, 0x27, 0x21, + 0xaf, 0xdf, 0xf2, 0x0e, 0x00, 0x2b, 0x3e, 0xe4, 0xc5, 0xb4, 0x70, 0xb4, 0x2e, 0x83, 0x32, 0x40, 0x84, 0x66, 0x00, + 0x74, 0x72, 0x75, 0x10, 0xa5, 0x81, 0x2b, 0xee, 0x10, 0xe1, 0xa7, 0xd1, 0xe3, 0xfc, 0x69, 0xf8, 0xb8, 0x9a, 0x86, + 0x17, 0x79, 0x10, 0x5d, 0x54, 0x41, 0xf4, 0xb8, 0xba, 0x0a, 0x1f, 0xe7, 0xd3, 0xe8, 0x22, 0x0f, 0xc2, 0x8b, 0xaa, + 0xb1, 0xef, 0xda, 0xdd, 0x3d, 0x21, 0x6f, 0xbb, 0xfa, 0x23, 0xe7, 0xca, 0x9e, 0x32, 0x3d, 0x3f, 0xaf, 0xf5, 0x4a, + 0xed, 0x36, 0xd7, 0x6b, 0xd4, 0x4c, 0x7d, 0x94, 0xfd, 0xcd, 0x36, 0x16, 0x1e, 0xcd, 0x21, 0xf4, 0x19, 0x69, 0x31, + 0xf7, 0x38, 0xd7, 0x9b, 0x3d, 0x29, 0x0c, 0x8c, 0x98, 0x54, 0x32, 0x72, 0x7a, 0x81, 0x8b, 0x50, 0x85, 0x18, 0xd6, + 0xd2, 0xd5, 0x3e, 0xeb, 0xd2, 0x1b, 0xa8, 0x6b, 0x8a, 0x7d, 0x0d, 0x19, 0x78, 0xd1, 0xf4, 0x32, 0x18, 0x03, 0x72, + 0x04, 0xde, 0xf1, 0xd9, 0x12, 0x0e, 0xcc, 0x35, 0x40, 0xdf, 0x3c, 0xe8, 0xeb, 0x72, 0xcb, 0xd7, 0xaa, 0x6f, 0xa6, + 0xeb, 0x91, 0x52, 0x7e, 0xac, 0xf8, 0xed, 0xc5, 0x13, 0x76, 0xc3, 0x35, 0x2a, 0xca, 0x73, 0xbd, 0x58, 0xef, 0x80, + 0xab, 0xee, 0x39, 0xdc, 0x66, 0xf1, 0xd8, 0x95, 0x07, 0x2c, 0xdb, 0xb2, 0x7b, 0xf6, 0x86, 0x3d, 0x62, 0xef, 0xd9, + 0x27, 0xf6, 0x95, 0xd5, 0x08, 0x51, 0x5e, 0x2a, 0x29, 0xcf, 0x5f, 0xf0, 0x1b, 0x69, 0x7b, 0x94, 0xb0, 0x64, 0xf7, + 0xb6, 0x9d, 0x66, 0xb8, 0x61, 0x8f, 0xf8, 0x62, 0xb8, 0x62, 0x9f, 0x20, 0x1b, 0x0a, 0xc5, 0x83, 0x15, 0xab, 0xe1, + 0x0a, 0x4b, 0x19, 0xf4, 0x69, 0x58, 0x5a, 0xc2, 0xa2, 0x29, 0x14, 0xa5, 0xe8, 0x4f, 0xbc, 0x26, 0xec, 0xb4, 0x1a, + 0x0b, 0x91, 0x1f, 0x1a, 0xae, 0xd8, 0x3d, 0x5f, 0x0c, 0x56, 0xec, 0x91, 0xb6, 0x11, 0x0d, 0x36, 0x6e, 0x71, 0x04, + 0x66, 0xa5, 0x0b, 0x93, 0x02, 0xf5, 0xd6, 0xbe, 0x09, 0x6e, 0xd8, 0x1b, 0xac, 0xdf, 0x7b, 0x2c, 0x1a, 0x65, 0xfe, + 0xc1, 0x8a, 0x7d, 0xe5, 0x12, 0x43, 0xcd, 0x2d, 0x4f, 0x3a, 0x86, 0xea, 0x02, 0xe9, 0x8a, 0xf0, 0x9e, 0xd3, 0x8b, + 0xec, 0x2b, 0x96, 0x41, 0x5f, 0x19, 0xae, 0xd8, 0x16, 0x6b, 0xf7, 0xc6, 0x18, 0xb7, 0xac, 0xea, 0x49, 0x50, 0x60, + 0x94, 0x55, 0x4a, 0xcb, 0xc5, 0x11, 0xcb, 0xa6, 0x8e, 0x1a, 0xd4, 0x86, 0x01, 0x7d, 0x30, 0xfa, 0x8b, 0xaf, 0xdf, + 0x7d, 0xe7, 0x95, 0xfa, 0xe6, 0xfb, 0xdc, 0xf1, 0xae, 0x2c, 0xd1, 0xbb, 0xf2, 0x37, 0x5e, 0xce, 0x9e, 0xcf, 0x27, + 0xba, 0x96, 0xb4, 0xc9, 0x90, 0xbb, 0xe9, 0xec, 0x79, 0x87, 0xbf, 0xe5, 0x6f, 0xbe, 0xdf, 0x58, 0x7d, 0xac, 0xbe, + 0xab, 0xbb, 0xf7, 0x7e, 0xb0, 0x69, 0x9c, 0x8a, 0xef, 0x4e, 0x57, 0x1c, 0xdb, 0x59, 0x6b, 0xef, 0xcc, 0xff, 0xe1, + 0x5a, 0x6f, 0x71, 0xec, 0xde, 0xf0, 0xed, 0x70, 0x63, 0x0f, 0x83, 0xfc, 0xbe, 0x54, 0x1c, 0x67, 0x35, 0x7f, 0xe6, + 0x75, 0x4a, 0xb2, 0x80, 0x6a, 0xf4, 0xda, 0x48, 0x43, 0x97, 0xcc, 0xc4, 0x34, 0xc4, 0x17, 0x19, 0xa0, 0x73, 0x81, + 0x78, 0x76, 0xc7, 0xc7, 0x93, 0xbb, 0xab, 0x78, 0x72, 0x37, 0xe0, 0xaf, 0x4d, 0x0b, 0xda, 0x0b, 0xee, 0xce, 0x67, + 0xbf, 0xf1, 0xc2, 0x5e, 0x92, 0xcf, 0x7d, 0xf6, 0x56, 0xb8, 0xab, 0xf4, 0xb9, 0xcf, 0xbe, 0x0a, 0xfe, 0xdb, 0x48, + 0x93, 0x65, 0xb0, 0xaf, 0x35, 0xff, 0x6d, 0x84, 0xac, 0x1f, 0xec, 0xb3, 0xe0, 0x6f, 0xc1, 0xff, 0xbb, 0x4a, 0xd0, + 0x32, 0xfe, 0xb9, 0x56, 0x3f, 0xdf, 0xc9, 0xd8, 0x1c, 0x78, 0x13, 0x5a, 0x41, 0x6f, 0xde, 0xd4, 0xf2, 0x27, 0x71, + 0x71, 0xa4, 0xea, 0xa9, 0xe1, 0xa0, 0xc5, 0x62, 0x16, 0xf5, 0x51, 0x3a, 0x95, 0x37, 0xb9, 0xe6, 0xb1, 0xb4, 0x30, + 0xdf, 0x41, 0x38, 0xf0, 0xb5, 0x0d, 0x53, 0xb0, 0xe3, 0xb8, 0x19, 0x5c, 0x33, 0x80, 0x90, 0xcc, 0xa6, 0x5b, 0xfe, + 0x86, 0xbf, 0xe7, 0x5f, 0xf9, 0x2e, 0xb8, 0xe7, 0x8f, 0xf8, 0x27, 0x5e, 0xd7, 0x7c, 0xc7, 0x96, 0x12, 0xf2, 0xb4, + 0xde, 0x5e, 0x06, 0x5b, 0x56, 0xef, 0x2e, 0x83, 0x7b, 0x56, 0x6f, 0x9f, 0x04, 0x6f, 0x58, 0xbd, 0x7b, 0x12, 0x3c, + 0x62, 0xdb, 0xcb, 0xe0, 0x3d, 0xdb, 0x5d, 0x06, 0x9f, 0xd8, 0xf6, 0x49, 0xf0, 0x95, 0xed, 0x9e, 0x04, 0xb5, 0x42, + 0x7a, 0xf8, 0x2a, 0x24, 0xd3, 0xc9, 0xd7, 0x9a, 0x19, 0x56, 0xdd, 0xe0, 0xb3, 0xb0, 0x7e, 0x51, 0x2d, 0x83, 0xcf, + 0x35, 0xd3, 0x6d, 0x0e, 0x84, 0x60, 0xba, 0xc5, 0xc1, 0x0d, 0x3d, 0x31, 0xed, 0x0a, 0x52, 0xc1, 0xba, 0x5a, 0x1a, + 0x2c, 0xea, 0xa6, 0x75, 0x32, 0x3b, 0xde, 0x89, 0x71, 0x87, 0x77, 0xe2, 0x82, 0x2d, 0x9b, 0x4e, 0x57, 0x9d, 0xd3, + 0xe7, 0x81, 0x3e, 0x02, 0xf4, 0xde, 0x5f, 0x49, 0x0f, 0x9a, 0xa2, 0xe1, 0xb9, 0xd2, 0x1d, 0xb7, 0xf6, 0xfb, 0xd0, + 0xda, 0xef, 0x99, 0x54, 0xa4, 0x45, 0x2c, 0x2a, 0x8b, 0xaa, 0x42, 0x3e, 0xf1, 0x20, 0xd3, 0x5a, 0xb5, 0x84, 0x91, + 0x3a, 0x13, 0x30, 0xe9, 0x0b, 0x3a, 0x0c, 0x72, 0xb2, 0x2b, 0xb0, 0x25, 0xdf, 0x0c, 0x12, 0xb6, 0xe6, 0xf1, 0x74, + 0x98, 0x04, 0x4b, 0x76, 0xcb, 0x87, 0xdd, 0x62, 0xc1, 0x4a, 0x85, 0x31, 0xe9, 0xeb, 0xd3, 0xd1, 0xee, 0xce, 0x7b, + 0xab, 0x34, 0x8e, 0x33, 0x81, 0x3a, 0xb7, 0x4a, 0x6f, 0xf3, 0x5b, 0x67, 0x57, 0x5f, 0xab, 0x5d, 0x1e, 0x04, 0x86, + 0xdf, 0x80, 0x68, 0x87, 0x78, 0xef, 0xa0, 0xc6, 0x48, 0xb7, 0x64, 0xd6, 0x7d, 0x65, 0xef, 0xeb, 0x5b, 0xb3, 0x55, + 0xff, 0xa7, 0x45, 0xd0, 0x5e, 0x2e, 0x7b, 0xff, 0xb5, 0x79, 0xf5, 0xf7, 0x8e, 0x57, 0x37, 0xfe, 0xe4, 0x9e, 0xbf, + 0xc6, 0xe8, 0x04, 0x4c, 0x64, 0x3b, 0xfe, 0x7a, 0xb4, 0x6d, 0x9c, 0xf2, 0xe4, 0x5e, 0xfe, 0x7f, 0xa5, 0x40, 0x7b, + 0x37, 0xaf, 0xec, 0x4d, 0x71, 0xcb, 0x3b, 0xf6, 0xf2, 0xa5, 0xb5, 0x27, 0x1a, 0x84, 0x92, 0xd7, 0xdc, 0x0d, 0x8a, + 0x86, 0x3d, 0xf1, 0x39, 0xaf, 0x66, 0xaf, 0xe7, 0x93, 0x2d, 0x3f, 0xde, 0x11, 0x5f, 0x77, 0xec, 0x88, 0xcf, 0xfd, + 0xc1, 0xb2, 0xf9, 0x56, 0xaf, 0x76, 0xee, 0xe4, 0x4e, 0xa5, 0x77, 0xfc, 0x78, 0x1f, 0x1f, 0xfe, 0xc7, 0x95, 0xde, + 0x7d, 0x77, 0xa5, 0xed, 0x2a, 0x77, 0x77, 0xbe, 0xe9, 0xf8, 0x46, 0xd6, 0x1a, 0xc3, 0xcd, 0x8c, 0x82, 0x11, 0xa6, + 0x2d, 0x4c, 0xd3, 0x20, 0xb2, 0x14, 0x8b, 0x90, 0xa8, 0x51, 0x3a, 0x27, 0xfa, 0x2c, 0xe8, 0x14, 0x74, 0x71, 0xa3, + 0xbf, 0xe1, 0x63, 0xb6, 0x30, 0x2e, 0x9b, 0x37, 0x57, 0x8b, 0xc9, 0x60, 0x70, 0xe3, 0xef, 0xef, 0x78, 0x38, 0xbb, + 0x99, 0xb3, 0x6b, 0x7e, 0x47, 0xeb, 0x69, 0xa2, 0x1a, 0x5f, 0x3c, 0x24, 0x81, 0xdd, 0xf8, 0xfe, 0xc4, 0x22, 0x82, + 0xb5, 0x6f, 0x9c, 0x37, 0xfe, 0x40, 0x9a, 0xa5, 0xe5, 0xd6, 0xfe, 0xe8, 0x61, 0x0d, 0xc5, 0x0d, 0x08, 0x19, 0x8f, + 0x6c, 0x95, 0xc3, 0x27, 0xfe, 0xc1, 0xbb, 0xf6, 0xa7, 0xd7, 0x3a, 0xf8, 0x66, 0xa2, 0xce, 0xa5, 0x4f, 0x17, 0x4f, + 0xd8, 0x6f, 0xfc, 0xb5, 0x3c, 0x53, 0xde, 0x0a, 0x39, 0x6d, 0x3f, 0x22, 0x89, 0x13, 0x1d, 0x15, 0x5f, 0xdd, 0x44, + 0x02, 0x85, 0x80, 0x5d, 0xe1, 0x6b, 0xcd, 0xef, 0x27, 0xe5, 0xd4, 0xdb, 0x01, 0xc9, 0x2b, 0xb7, 0x15, 0xd1, 0x37, + 0x9c, 0xf3, 0xc5, 0xf0, 0x72, 0xfa, 0xb5, 0xdb, 0xb7, 0x47, 0x85, 0xb5, 0xa9, 0x88, 0xb7, 0x1b, 0x0c, 0xc2, 0x3a, + 0x99, 0x59, 0xe6, 0x92, 0x2f, 0x7d, 0xad, 0xcd, 0xdc, 0x63, 0x7a, 0xc7, 0x99, 0x66, 0xc8, 0xe8, 0x0b, 0xcc, 0x4c, + 0x87, 0xc3, 0xed, 0x39, 0x96, 0xc7, 0x87, 0x9f, 0x1e, 0xbf, 0x1f, 0xbc, 0xc7, 0x10, 0x2e, 0x2b, 0x2c, 0xe4, 0x2b, + 0x1f, 0x66, 0x75, 0xeb, 0xda, 0x71, 0xf1, 0x64, 0xf8, 0x1c, 0xf2, 0x06, 0x5d, 0x0f, 0x4d, 0x11, 0xad, 0xf2, 0x3b, + 0x8a, 0x3e, 0x51, 0x72, 0xd0, 0xf1, 0x04, 0x6a, 0x87, 0x5c, 0xb8, 0x5f, 0x1f, 0x73, 0x50, 0x74, 0x60, 0xa9, 0xfd, + 0xfe, 0xf9, 0x6b, 0x22, 0x94, 0x86, 0xf1, 0x7e, 0x1e, 0x46, 0x7f, 0xc6, 0x65, 0xb1, 0x86, 0x23, 0x76, 0x00, 0x9f, + 0x7b, 0xac, 0xaf, 0x61, 0xb7, 0xbe, 0xef, 0x07, 0xde, 0x96, 0xbf, 0x61, 0x5f, 0xb9, 0x77, 0x39, 0xfc, 0xe4, 0x3f, + 0x7e, 0x0f, 0xf2, 0x13, 0xe2, 0xa4, 0x60, 0x48, 0x6c, 0x47, 0x31, 0x6a, 0x1d, 0x7e, 0xae, 0x21, 0x56, 0xeb, 0x35, + 0x52, 0x77, 0x41, 0xfa, 0x7b, 0x85, 0xec, 0x27, 0x04, 0x56, 0x93, 0xf4, 0x29, 0x30, 0x89, 0x6f, 0x6a, 0x48, 0x20, + 0x4d, 0x0b, 0xc4, 0xe0, 0x40, 0xf1, 0xa9, 0xe0, 0x5f, 0x87, 0x9f, 0x49, 0xfe, 0x5b, 0xd4, 0x7c, 0x0c, 0x7f, 0xc3, + 0xd0, 0x4c, 0xaa, 0xfb, 0xb4, 0x86, 0x88, 0x68, 0x38, 0xf5, 0xc2, 0x4a, 0xa8, 0x93, 0x21, 0x48, 0xc5, 0x90, 0x0b, + 0x71, 0xf1, 0x64, 0x72, 0x53, 0x8a, 0xf0, 0xcf, 0x09, 0x3e, 0x93, 0x2b, 0x4d, 0x3e, 0xa3, 0x27, 0x8d, 0x2c, 0xe0, + 0x5e, 0xbe, 0x2f, 0x7b, 0x35, 0x58, 0xd4, 0x43, 0x7e, 0x53, 0xbb, 0xef, 0xcb, 0x39, 0x41, 0x8f, 0xec, 0x07, 0x34, + 0x07, 0x03, 0x35, 0x03, 0x29, 0x43, 0x70, 0x03, 0x97, 0x7e, 0x4f, 0x15, 0xe4, 0xcb, 0xef, 0x7d, 0x16, 0x32, 0x70, + 0x65, 0x41, 0x98, 0x72, 0xa9, 0x90, 0x02, 0xc7, 0x4d, 0x3d, 0xf8, 0xac, 0xd1, 0x49, 0x24, 0xf8, 0x94, 0x80, 0x24, + 0x69, 0x79, 0x20, 0x69, 0xc4, 0x74, 0x20, 0x2e, 0x94, 0xa6, 0x59, 0x49, 0x11, 0x87, 0xd8, 0x55, 0xaf, 0x91, 0xf0, + 0x2c, 0x78, 0xc4, 0x60, 0xed, 0x48, 0xd1, 0xe2, 0xab, 0x31, 0x1d, 0xeb, 0xb0, 0xa1, 0x5b, 0x59, 0xdc, 0x6f, 0x92, + 0x3a, 0x8d, 0xc4, 0x95, 0xb7, 0x42, 0xfe, 0xfc, 0x97, 0x12, 0x81, 0xf4, 0xae, 0x06, 0x62, 0x10, 0xfc, 0x00, 0xfd, + 0x07, 0x2c, 0x72, 0x10, 0x94, 0xea, 0x32, 0xcc, 0xab, 0x8c, 0x0a, 0x9c, 0xed, 0xd8, 0x76, 0xce, 0x54, 0xdd, 0x82, + 0xcf, 0xc2, 0x30, 0xa4, 0x9d, 0xad, 0x9a, 0x93, 0x5b, 0xbd, 0x81, 0x7a, 0x26, 0x71, 0xa4, 0x96, 0xe2, 0x48, 0x5b, + 0x73, 0x9f, 0x2e, 0xbd, 0x6e, 0x79, 0x41, 0xc3, 0x05, 0xe8, 0x45, 0xe9, 0xae, 0xf3, 0x09, 0x85, 0x2e, 0xab, 0x71, + 0x35, 0x14, 0x75, 0x28, 0xc7, 0x58, 0xfb, 0x73, 0x25, 0xcf, 0xef, 0xc0, 0x7a, 0x84, 0x86, 0xaf, 0x4a, 0x1d, 0xc4, + 0xf6, 0x13, 0xbd, 0xeb, 0x54, 0xea, 0x6f, 0x00, 0x18, 0x38, 0x75, 0x3c, 0xd4, 0x47, 0xed, 0x14, 0xb2, 0x9d, 0x7b, + 0x4b, 0x8c, 0xca, 0x95, 0xf0, 0x54, 0x69, 0x79, 0x4a, 0x59, 0xf5, 0xb5, 0xe0, 0x56, 0x76, 0x9f, 0x0d, 0x20, 0xa3, + 0x0d, 0x0a, 0xe4, 0x19, 0xb5, 0x35, 0x1e, 0xa4, 0x9a, 0x66, 0x89, 0x63, 0xf8, 0xa0, 0x48, 0xb3, 0x0a, 0x2c, 0x5e, + 0xe6, 0x92, 0x39, 0x28, 0x58, 0xae, 0x37, 0x9b, 0x69, 0xa6, 0xfa, 0x22, 0xb7, 0x37, 0x1a, 0x2f, 0xd3, 0x7f, 0xb3, + 0x64, 0xc0, 0xa3, 0x8b, 0x27, 0x7e, 0x00, 0x69, 0x92, 0xe2, 0x01, 0x92, 0x60, 0x7b, 0xb0, 0x8b, 0x1d, 0x86, 0xad, + 0x62, 0x65, 0x4f, 0x9e, 0x2e, 0x77, 0x68, 0xca, 0x25, 0xb8, 0xe4, 0xc4, 0x5c, 0x4e, 0x7d, 0x5f, 0xb2, 0xde, 0x50, + 0x9c, 0xb2, 0x69, 0x02, 0x4a, 0x02, 0xed, 0x16, 0xfc, 0x17, 0x3e, 0x35, 0x74, 0x5a, 0x80, 0xa5, 0xb6, 0x1b, 0xf0, + 0x5f, 0xe8, 0x17, 0xdb, 0x5d, 0xd4, 0x0f, 0xcc, 0x83, 0xbd, 0x59, 0x5c, 0x19, 0x03, 0x4e, 0x12, 0x57, 0x9a, 0x47, + 0xae, 0x1f, 0x14, 0x7d, 0xba, 0xac, 0x1d, 0x38, 0x53, 0x5c, 0x58, 0xa5, 0x36, 0x49, 0xaf, 0xfd, 0x96, 0x9a, 0x78, + 0x13, 0x25, 0x55, 0x61, 0x3b, 0xa4, 0xfd, 0x4b, 0xca, 0x99, 0x2a, 0xee, 0x10, 0x3d, 0xd9, 0x4d, 0x5c, 0x05, 0x5e, + 0x58, 0x55, 0x6c, 0x84, 0xda, 0x8c, 0x2c, 0x27, 0x70, 0xba, 0xc7, 0xea, 0x82, 0x8f, 0xed, 0x6a, 0x76, 0xc1, 0x4a, + 0xb6, 0x66, 0xd2, 0x7d, 0xde, 0x8e, 0xb9, 0x90, 0x57, 0x7a, 0x59, 0xb4, 0x02, 0xda, 0x83, 0xc0, 0xe1, 0xe7, 0x9a, + 0xee, 0xd1, 0xb3, 0xcd, 0x36, 0xb5, 0xd9, 0xd8, 0x5a, 0x84, 0x90, 0x81, 0x68, 0xe8, 0x0b, 0x39, 0xa3, 0xc8, 0x57, + 0x69, 0xb9, 0x56, 0x1b, 0xab, 0x8c, 0x17, 0x98, 0x08, 0x32, 0x9c, 0x85, 0x77, 0xe8, 0x69, 0x3d, 0xd2, 0x14, 0x93, + 0xe0, 0xa4, 0x8b, 0xbf, 0x00, 0x1b, 0xca, 0x93, 0xdc, 0x1c, 0x90, 0x03, 0xa8, 0x5c, 0x8a, 0x52, 0x29, 0x83, 0x5f, + 0xab, 0x3b, 0xb2, 0xad, 0xfa, 0xef, 0x34, 0x90, 0xc1, 0x1d, 0xe8, 0xdb, 0x5e, 0x68, 0xed, 0x68, 0xe7, 0xca, 0xd6, + 0xb4, 0x2d, 0xd3, 0x3c, 0x46, 0x16, 0x1b, 0x40, 0x3e, 0x91, 0xce, 0x81, 0xc8, 0x6b, 0xa2, 0xf1, 0xce, 0x9e, 0xf2, + 0xf1, 0x54, 0x3c, 0x24, 0xef, 0x55, 0xbe, 0x6f, 0xee, 0xf5, 0xc1, 0x18, 0xfb, 0x16, 0x94, 0x89, 0x0f, 0x56, 0x5b, + 0xeb, 0x12, 0xeb, 0xad, 0xd2, 0x24, 0xba, 0xe1, 0x0a, 0x3a, 0x8e, 0xc4, 0x0d, 0x62, 0x70, 0xcc, 0x78, 0x6d, 0x95, + 0xa5, 0xaf, 0xb0, 0xcc, 0x75, 0xcc, 0x92, 0x21, 0x93, 0x3a, 0x4f, 0x14, 0x3c, 0xf9, 0x79, 0x42, 0x32, 0x22, 0x6a, + 0xb6, 0xe5, 0x28, 0xe5, 0xa6, 0x05, 0x5c, 0x66, 0x64, 0x00, 0xdf, 0xa4, 0x09, 0x40, 0xb9, 0x7c, 0x09, 0x52, 0x69, + 0x88, 0xe0, 0x9a, 0xed, 0x25, 0xa3, 0x1b, 0x47, 0xeb, 0xa0, 0x4a, 0x32, 0x77, 0x70, 0x6e, 0x67, 0x91, 0x52, 0x6f, + 0x3e, 0xc2, 0xb0, 0x93, 0xf7, 0x61, 0x9d, 0xe0, 0xb7, 0x01, 0x35, 0xe9, 0x53, 0xe1, 0x45, 0x23, 0x40, 0x53, 0xdf, + 0xa9, 0x32, 0x3e, 0x15, 0x5e, 0x36, 0xda, 0xb2, 0x8c, 0x52, 0xa8, 0x2e, 0x98, 0xdd, 0x9a, 0x2e, 0xc4, 0xbc, 0xaa, + 0x06, 0xda, 0x20, 0xb7, 0xeb, 0x98, 0x01, 0x8d, 0xda, 0xae, 0x3c, 0xb2, 0x00, 0xb7, 0x66, 0x22, 0x30, 0x72, 0xfe, + 0x5d, 0x7e, 0xad, 0xc2, 0x79, 0xfa, 0xfd, 0xd0, 0xdb, 0x6f, 0x83, 0x68, 0xb4, 0xbd, 0x64, 0xbb, 0x20, 0x1a, 0xed, + 0x2e, 0x1b, 0x46, 0xbf, 0x9f, 0xd0, 0xef, 0x27, 0x0d, 0xa8, 0x4a, 0x84, 0x89, 0xb8, 0xd7, 0x6f, 0xd4, 0xf2, 0x95, + 0x5a, 0xbf, 0x53, 0xcb, 0x97, 0x6a, 0x78, 0x6b, 0x4f, 0x22, 0x41, 0x64, 0x69, 0x6c, 0xee, 0x25, 0x5b, 0xaa, 0xa5, + 0xd2, 0x31, 0xaa, 0x8c, 0xa8, 0xa5, 0xb3, 0x39, 0x56, 0x8c, 0xb4, 0x73, 0x50, 0x32, 0x20, 0xd3, 0xe2, 0xaa, 0xc6, + 0x74, 0xb3, 0xa2, 0x25, 0x26, 0x23, 0xac, 0x6c, 0xcb, 0xdb, 0x4d, 0xaa, 0xa6, 0x73, 0x72, 0x73, 0xab, 0x94, 0x9b, + 0x5b, 0xc1, 0xf3, 0x6f, 0xe8, 0x96, 0x4b, 0xae, 0xbd, 0xcc, 0xa6, 0x85, 0xd2, 0x2d, 0xe3, 0x1a, 0x6c, 0xed, 0x9b, + 0x40, 0x96, 0xf9, 0x40, 0x51, 0x63, 0x7b, 0xd1, 0x28, 0xdf, 0x20, 0x5b, 0x11, 0xa3, 0x4e, 0x59, 0x30, 0xfe, 0x76, + 0x47, 0x0f, 0x64, 0xa0, 0xaa, 0xaa, 0x8d, 0x83, 0x3b, 0x2b, 0xfd, 0x61, 0x79, 0xf1, 0x84, 0x25, 0x56, 0x3a, 0xb9, + 0x50, 0x85, 0xfe, 0x20, 0x44, 0x37, 0x95, 0x0d, 0x07, 0x87, 0xba, 0xd8, 0xca, 0x80, 0xd0, 0xc3, 0xf4, 0xde, 0xc6, + 0x4a, 0x96, 0xbb, 0xa6, 0x7c, 0x31, 0xe3, 0x09, 0xc7, 0xd1, 0x97, 0xab, 0x45, 0x58, 0xab, 0x45, 0x76, 0x02, 0x3c, + 0xb4, 0x56, 0x4b, 0x21, 0x57, 0x8b, 0x70, 0x66, 0xba, 0x50, 0x33, 0x3d, 0x03, 0x05, 0xa4, 0x50, 0xb3, 0x3c, 0x01, + 0x58, 0x78, 0x61, 0x66, 0xb8, 0x30, 0x33, 0x1c, 0x87, 0xd4, 0xf8, 0x3f, 0xe8, 0xbd, 0xce, 0x3d, 0xb7, 0xdc, 0x8d, + 0x4e, 0x23, 0xbe, 0x1d, 0x6d, 0x30, 0xc7, 0x07, 0xe1, 0xa4, 0xea, 0xf7, 0xd3, 0x12, 0xb1, 0x7a, 0x0c, 0x8c, 0xa0, + 0x1c, 0x2a, 0x47, 0xfb, 0x65, 0x61, 0x49, 0x96, 0x84, 0x25, 0xb9, 0x57, 0xe3, 0x5c, 0x5a, 0x2e, 0x5e, 0x25, 0x81, + 0x48, 0x64, 0xbc, 0x94, 0x26, 0xf8, 0x84, 0x97, 0x23, 0x23, 0x35, 0x4f, 0x16, 0xa9, 0x97, 0xb3, 0x8c, 0x8d, 0x11, + 0xc3, 0x28, 0xf4, 0x9b, 0xaa, 0xdf, 0xcf, 0x4b, 0x2f, 0xa7, 0x76, 0x7e, 0x02, 0xd7, 0xcb, 0x53, 0x67, 0x91, 0x23, + 0xe4, 0xd5, 0x48, 0x2a, 0x2c, 0xaf, 0x95, 0x7a, 0xfa, 0x12, 0x7c, 0x50, 0x77, 0x6f, 0x14, 0x00, 0x71, 0x91, 0x4b, + 0xff, 0xda, 0x12, 0x2e, 0x4d, 0xb9, 0x81, 0x41, 0x0f, 0x79, 0x4e, 0x42, 0xa8, 0x04, 0x21, 0x29, 0xac, 0x1b, 0xf7, + 0xc5, 0x93, 0x89, 0xeb, 0xce, 0x62, 0x03, 0x13, 0x1c, 0x0e, 0x80, 0x78, 0x30, 0xf5, 0xa2, 0x01, 0x2f, 0xd5, 0x9c, + 0xf9, 0xe0, 0xe5, 0x04, 0x93, 0x01, 0xaa, 0x8a, 0x81, 0x53, 0xd6, 0x63, 0xf9, 0xc8, 0xb8, 0x99, 0xf9, 0x7e, 0x80, + 0xef, 0xd6, 0x85, 0x44, 0x7f, 0x50, 0x00, 0x05, 0x99, 0x02, 0x28, 0x48, 0x0c, 0x40, 0x41, 0x6c, 0x00, 0x0a, 0x36, + 0x0d, 0x5f, 0x49, 0x1d, 0x6e, 0x04, 0x74, 0x11, 0x3e, 0xf4, 0x2c, 0x6c, 0xac, 0x50, 0x3c, 0x1b, 0xb3, 0x31, 0x2b, + 0xd4, 0xce, 0x93, 0xcb, 0xa9, 0xd8, 0x59, 0x8c, 0x75, 0x15, 0xb9, 0x4d, 0xbc, 0x90, 0x50, 0xe4, 0x9c, 0x1b, 0x89, + 0xba, 0xfb, 0xb9, 0xf7, 0x92, 0x8c, 0x25, 0xf3, 0x86, 0x46, 0x0d, 0xe6, 0x65, 0xd7, 0x01, 0x4c, 0x4b, 0xbe, 0x2d, + 0x68, 0x30, 0x9d, 0x2a, 0x8f, 0x48, 0x93, 0xa0, 0x76, 0x2e, 0x93, 0x22, 0x27, 0x84, 0x49, 0xd0, 0x2b, 0xc1, 0x6f, + 0x24, 0xca, 0xff, 0x37, 0x9d, 0xe0, 0x01, 0x8e, 0x89, 0x56, 0xc9, 0x57, 0x30, 0x60, 0xe6, 0xfc, 0x99, 0x74, 0xca, + 0x46, 0x28, 0xc6, 0x32, 0x8d, 0x47, 0x5f, 0xd9, 0x10, 0xa1, 0xad, 0x9e, 0xa1, 0x89, 0x09, 0xea, 0x00, 0x8f, 0xe8, + 0xaf, 0xd1, 0x57, 0x43, 0xa1, 0xd2, 0xd5, 0x48, 0x5d, 0xb3, 0x73, 0xce, 0xdf, 0xd6, 0x86, 0x13, 0x19, 0xd3, 0xa6, + 0xc0, 0x37, 0x20, 0x90, 0x6f, 0x20, 0x00, 0x5c, 0x35, 0x9d, 0xd9, 0x2b, 0x80, 0x73, 0x20, 0x80, 0xc7, 0x79, 0xc7, + 0xe3, 0x07, 0xfa, 0xab, 0x38, 0xee, 0x9d, 0xa6, 0x61, 0xfb, 0xaf, 0xc0, 0x58, 0x0c, 0xe5, 0x78, 0xbe, 0x53, 0x90, + 0xec, 0x51, 0xca, 0xd2, 0x55, 0x13, 0xd9, 0xa1, 0x58, 0x9f, 0xe6, 0x94, 0xb1, 0xb4, 0x2d, 0xc7, 0x68, 0xe3, 0xf5, + 0x43, 0x3c, 0xbe, 0xb9, 0xd1, 0x93, 0x0f, 0x7a, 0x70, 0x7b, 0x7b, 0xf5, 0xa2, 0xc7, 0x6c, 0xbe, 0x15, 0x8b, 0x67, + 0x45, 0x9c, 0x38, 0xad, 0x43, 0x0e, 0x70, 0x90, 0x93, 0x10, 0x48, 0xc7, 0xb8, 0xd4, 0xa2, 0x83, 0x9a, 0xe5, 0xbc, + 0x06, 0x96, 0x59, 0x04, 0xd9, 0x00, 0x51, 0x4d, 0x53, 0xb1, 0x1a, 0x1e, 0x94, 0xaa, 0x39, 0xa5, 0x52, 0xfb, 0x86, + 0xb3, 0xd5, 0xe9, 0x13, 0xab, 0x36, 0xe1, 0xd6, 0xbf, 0xd5, 0x9e, 0xa0, 0xad, 0xa4, 0x81, 0x50, 0xcf, 0x17, 0xe9, + 0x2d, 0x45, 0xf1, 0x38, 0x33, 0xf1, 0x54, 0x05, 0xc6, 0xbe, 0xb5, 0x23, 0x28, 0x48, 0x9a, 0xae, 0x03, 0x0e, 0xd3, + 0xe8, 0x84, 0xc5, 0x3f, 0xa5, 0x0f, 0xe5, 0x45, 0xad, 0xc0, 0x49, 0xfe, 0x29, 0x5c, 0x44, 0x12, 0x0b, 0xfd, 0x92, + 0x00, 0x48, 0x64, 0xf0, 0x6a, 0x54, 0xac, 0x85, 0x0a, 0x90, 0x53, 0x94, 0xde, 0x2a, 0x3e, 0x2e, 0x45, 0xa9, 0x52, + 0x2a, 0x73, 0xa3, 0x52, 0x40, 0x58, 0x1b, 0x38, 0xba, 0x80, 0x2f, 0x20, 0x68, 0x2d, 0x77, 0x6b, 0xdb, 0xf3, 0x46, + 0xe6, 0x33, 0xd3, 0x3c, 0xad, 0xde, 0xab, 0xbf, 0xdf, 0x2d, 0x31, 0xcc, 0xc6, 0xd3, 0xdf, 0xb7, 0x19, 0xc2, 0xcd, + 0xdf, 0x30, 0x44, 0xb7, 0x00, 0x8e, 0x59, 0xda, 0x43, 0x21, 0x0b, 0x26, 0x58, 0x43, 0x55, 0x9e, 0xf2, 0xd9, 0xcb, + 0x27, 0x3b, 0x40, 0x53, 0x43, 0x17, 0x37, 0x3a, 0xd5, 0x55, 0x09, 0xc2, 0xf7, 0x5d, 0xa1, 0x1e, 0x9b, 0x03, 0x4e, + 0x0d, 0x00, 0xc5, 0x22, 0xaf, 0xf5, 0xd8, 0xfe, 0x41, 0x6f, 0xd4, 0x1b, 0x20, 0x9e, 0xce, 0x79, 0xe1, 0x1f, 0xd1, + 0xaf, 0x53, 0x7f, 0xc6, 0x85, 0x20, 0xea, 0xf5, 0x24, 0xbc, 0x13, 0x67, 0x69, 0x1c, 0x9c, 0xf5, 0x06, 0xe6, 0x22, + 0x50, 0x9c, 0xa5, 0xf9, 0x19, 0x88, 0xe5, 0x08, 0x8f, 0x58, 0xb3, 0x1b, 0x40, 0x0c, 0x2c, 0x75, 0x48, 0xb2, 0xea, + 0xd8, 0x7e, 0xff, 0xe5, 0xc8, 0xf0, 0xa6, 0x23, 0x22, 0x8c, 0xfe, 0x5d, 0x81, 0x00, 0x05, 0xcb, 0xcc, 0x76, 0x66, + 0xd2, 0xd5, 0x9e, 0xd5, 0xf3, 0x66, 0x93, 0x77, 0xf5, 0x8e, 0xd5, 0xb4, 0x9c, 0x9a, 0x56, 0x59, 0x4d, 0x9b, 0xe4, + 0x50, 0x33, 0xd1, 0xef, 0x6b, 0x7c, 0xd4, 0x7c, 0x0e, 0xb8, 0x6c, 0x98, 0xfc, 0x72, 0x56, 0xcd, 0xfb, 0x7d, 0x4f, + 0x3e, 0x82, 0x5f, 0x48, 0x5c, 0xe6, 0xd6, 0x58, 0x3e, 0x7d, 0x45, 0x7c, 0x66, 0x06, 0xf1, 0xe8, 0xe6, 0x08, 0xea, + 0xeb, 0xa3, 0xf0, 0x3a, 0xe6, 0x0a, 0x9b, 0x89, 0xe9, 0x4b, 0x18, 0x3c, 0x4f, 0xf8, 0xe0, 0x2d, 0x47, 0x7f, 0x23, + 0x9d, 0x99, 0x82, 0x85, 0x9c, 0xfb, 0x93, 0x97, 0x08, 0x9d, 0x8c, 0x48, 0x0f, 0x3a, 0x9d, 0xa0, 0x21, 0xfb, 0xfd, + 0x05, 0x74, 0x66, 0x2b, 0x95, 0xb2, 0x55, 0x51, 0x99, 0xae, 0xeb, 0xa2, 0xac, 0xa0, 0x63, 0xe9, 0xe7, 0x8d, 0x90, + 0x99, 0xf5, 0x33, 0x0b, 0xf9, 0x69, 0x21, 0xb1, 0xa6, 0x6c, 0xfb, 0x44, 0x6d, 0x90, 0x66, 0x5d, 0xa8, 0x2e, 0x70, + 0xee, 0xac, 0xbd, 0xde, 0x08, 0xf5, 0xcf, 0xf9, 0x68, 0x5d, 0xac, 0x3d, 0x70, 0x89, 0x99, 0xa5, 0x73, 0xc5, 0xa1, + 0x91, 0xfb, 0xa3, 0xcf, 0x45, 0x9a, 0x53, 0x1e, 0xa0, 0x41, 0x14, 0x73, 0xfb, 0x2d, 0x90, 0x7e, 0xe8, 0x2d, 0x90, + 0x7d, 0x74, 0xce, 0xc9, 0x4b, 0x00, 0xa7, 0x43, 0x44, 0xdc, 0x8a, 0x04, 0x1d, 0xab, 0x86, 0x3b, 0x0b, 0xf7, 0xb4, + 0x97, 0xc6, 0xbd, 0x34, 0x3f, 0x4b, 0xfb, 0x7d, 0x03, 0xa0, 0x99, 0x22, 0x32, 0x3c, 0xce, 0xc8, 0x6d, 0xd2, 0x42, + 0x30, 0xa5, 0xfd, 0x57, 0x63, 0x48, 0x10, 0x08, 0xf8, 0x3f, 0x85, 0xf7, 0x1e, 0xd0, 0x36, 0x69, 0x03, 0xae, 0x7a, + 0x4c, 0x07, 0x66, 0x4b, 0xce, 0x56, 0x9d, 0x0d, 0x40, 0x39, 0x55, 0x5a, 0x4f, 0x79, 0x5c, 0x53, 0x44, 0xa4, 0xca, + 0x42, 0xfd, 0xc6, 0x7a, 0x32, 0x59, 0xe5, 0x22, 0x43, 0x8e, 0xca, 0xf4, 0xb6, 0x66, 0x84, 0xd8, 0xa5, 0x9f, 0x2f, + 0x60, 0xc9, 0xc6, 0x1f, 0x70, 0xf2, 0x96, 0x00, 0x69, 0x3b, 0x6b, 0x57, 0xd5, 0x2e, 0xc7, 0xad, 0xdd, 0x1c, 0x90, + 0x7c, 0xbd, 0xd1, 0x68, 0xa4, 0xfd, 0xe4, 0x04, 0x0c, 0x55, 0x4f, 0x2d, 0x85, 0x1e, 0xab, 0x15, 0xb6, 0x6e, 0x47, + 0x2e, 0xb3, 0x64, 0x30, 0x5f, 0x18, 0xc7, 0xd7, 0xe6, 0xa3, 0x0f, 0x97, 0xca, 0xda, 0x75, 0xc4, 0xd7, 0x7f, 0x92, + 0xd5, 0xfa, 0x9e, 0x77, 0x55, 0x13, 0xf0, 0x45, 0x15, 0x5b, 0xfa, 0x1d, 0xef, 0xc9, 0xde, 0xc5, 0xd7, 0x3e, 0x62, + 0x97, 0x7c, 0xcf, 0x5b, 0xd4, 0x79, 0xbe, 0xf2, 0x75, 0xa3, 0x4a, 0xb7, 0xf7, 0x92, 0x05, 0xae, 0xbd, 0xa3, 0xa6, + 0xb1, 0x9e, 0xf9, 0xd1, 0xc3, 0x22, 0x64, 0x3b, 0x1f, 0x7a, 0x5f, 0x35, 0x4f, 0xcf, 0x1a, 0x7a, 0x93, 0x1a, 0xfa, + 0xd0, 0x8b, 0xb2, 0x7d, 0x6a, 0x1a, 0xd1, 0x6b, 0xd8, 0xd0, 0x87, 0xde, 0x92, 0x93, 0x43, 0x82, 0xc1, 0xa9, 0x31, + 0x7f, 0x78, 0x38, 0x9d, 0xe1, 0xef, 0x18, 0x50, 0x89, 0xc9, 0x7c, 0x7a, 0x4c, 0x3b, 0x0a, 0x30, 0xa3, 0x4a, 0x6f, + 0x9f, 0x1e, 0xd8, 0x8e, 0x97, 0xf5, 0xd0, 0xd2, 0xbb, 0x27, 0x47, 0xb7, 0xe3, 0x55, 0x35, 0xbe, 0x94, 0x43, 0x9e, + 0xe7, 0xb3, 0xd1, 0x68, 0x24, 0x0c, 0x3a, 0x77, 0xa5, 0x37, 0xb0, 0x02, 0x19, 0x5c, 0x54, 0x1f, 0xca, 0xa5, 0xb7, + 0x53, 0x87, 0x76, 0xe5, 0x4f, 0xf2, 0xc3, 0xa1, 0x18, 0x99, 0x63, 0x1c, 0x70, 0x4e, 0x0a, 0x25, 0x47, 0xc9, 0x5a, + 0x82, 0xe8, 0x94, 0xc6, 0x53, 0x59, 0xaf, 0xad, 0x88, 0xbc, 0x1a, 0x21, 0x1f, 0x82, 0x9f, 0x3d, 0x50, 0x8b, 0x3f, + 0xd5, 0x82, 0xd8, 0x43, 0x9f, 0x2a, 0xa5, 0x43, 0xbc, 0x2a, 0x20, 0x44, 0x18, 0xf0, 0x06, 0xda, 0x41, 0x09, 0x0e, + 0x3b, 0xdc, 0x7b, 0x44, 0x88, 0x7e, 0xe1, 0xe5, 0x33, 0x19, 0xae, 0xdc, 0x1b, 0x54, 0x73, 0x06, 0x88, 0x95, 0x3e, + 0x03, 0x17, 0x4c, 0x40, 0x3d, 0xc5, 0xa7, 0xe8, 0x5f, 0x6f, 0x1e, 0x36, 0x5d, 0x9f, 0x96, 0x80, 0x8a, 0xe8, 0xd9, + 0xcf, 0xc7, 0x00, 0xde, 0xd9, 0xb5, 0x19, 0x69, 0x2f, 0x7f, 0x03, 0x0c, 0x2b, 0x25, 0x89, 0x76, 0x4e, 0x89, 0xc0, + 0x9d, 0x8f, 0x6c, 0xe9, 0x47, 0x29, 0x10, 0x73, 0xc7, 0x93, 0x44, 0xf6, 0x60, 0x23, 0x27, 0x70, 0x8b, 0x01, 0x8f, + 0x0e, 0x40, 0xe5, 0x4a, 0x41, 0xee, 0x35, 0x47, 0x72, 0xc7, 0x8f, 0xbd, 0x1f, 0x07, 0xf5, 0xe0, 0xc7, 0xde, 0x59, + 0x4a, 0x72, 0x47, 0x78, 0xa6, 0xa6, 0x84, 0x88, 0xcf, 0x7e, 0x1c, 0xe4, 0x03, 0x3c, 0x4b, 0xb4, 0x48, 0x8b, 0xdc, + 0x6a, 0xa2, 0xc6, 0x4d, 0x78, 0x9b, 0x48, 0x1a, 0xa2, 0xbb, 0xce, 0x23, 0x62, 0x01, 0x20, 0x59, 0x7c, 0x36, 0x6f, + 0x28, 0xea, 0xdd, 0x84, 0x6f, 0xd1, 0x5d, 0x16, 0xfb, 0xfd, 0x55, 0x9e, 0xd6, 0x3d, 0x1d, 0x2a, 0x83, 0x2f, 0x48, + 0x35, 0x01, 0x1e, 0xed, 0x2f, 0xcc, 0xf1, 0xea, 0xd5, 0xe6, 0x48, 0x59, 0xa8, 0x12, 0xf5, 0x5b, 0xac, 0x66, 0x3d, + 0x44, 0xe4, 0xce, 0x32, 0x63, 0x6f, 0x2f, 0x78, 0x25, 0x67, 0x55, 0x6c, 0x97, 0xe3, 0x2b, 0xc2, 0xda, 0x4a, 0x02, + 0x74, 0xb4, 0x1e, 0x6b, 0x53, 0x8c, 0xfc, 0x4a, 0x21, 0x01, 0x17, 0x1d, 0x5b, 0x0b, 0xc5, 0xc6, 0x0b, 0xd0, 0x97, + 0xec, 0x4c, 0x03, 0xac, 0x37, 0x7a, 0x15, 0x71, 0x5b, 0x3e, 0x50, 0xe1, 0x4d, 0x6e, 0xaa, 0xcc, 0xca, 0x66, 0xd1, + 0xee, 0xa7, 0x8a, 0x57, 0x88, 0x5b, 0x6f, 0xd4, 0x1e, 0x05, 0xa8, 0x3d, 0xb4, 0x50, 0x06, 0xe8, 0xd2, 0x34, 0x03, + 0x40, 0x06, 0x00, 0x99, 0x2a, 0xe2, 0x33, 0x01, 0x2a, 0x6d, 0x75, 0xa3, 0xc0, 0x89, 0xf4, 0x02, 0x18, 0x17, 0x58, + 0xe9, 0x23, 0x1b, 0x19, 0x2c, 0xb6, 0x08, 0x70, 0xcb, 0x91, 0x3e, 0x4c, 0xc3, 0xc9, 0x36, 0x9a, 0xc3, 0x24, 0xcd, + 0xef, 0xc2, 0x2c, 0x95, 0xd0, 0x12, 0xaf, 0x64, 0x8d, 0x11, 0x0b, 0x48, 0xdf, 0xa7, 0x17, 0x45, 0x16, 0x13, 0x24, + 0x9c, 0xf5, 0xd4, 0x01, 0x54, 0x93, 0x73, 0xad, 0x69, 0xf5, 0xac, 0x36, 0x79, 0xc8, 0x02, 0x9d, 0x3d, 0x18, 0x93, + 0x5a, 0x6e, 0xe8, 0x91, 0xfd, 0x95, 0xe3, 0x19, 0xe1, 0xbb, 0x9e, 0xe1, 0xd4, 0x7f, 0x1f, 0x6b, 0x20, 0x65, 0x4a, + 0x00, 0x41, 0x06, 0x47, 0x13, 0x42, 0x79, 0x3a, 0x26, 0x53, 0x9b, 0x1f, 0x81, 0x70, 0x44, 0xf0, 0x0a, 0x9e, 0x1b, + 0x5a, 0xb7, 0xdc, 0xd8, 0x59, 0xe4, 0x69, 0x02, 0xc8, 0xe2, 0x05, 0xbf, 0x07, 0x64, 0x4e, 0xbd, 0x2a, 0x64, 0xcf, + 0x9e, 0x8b, 0xe9, 0x6c, 0x1e, 0x7c, 0x4c, 0x68, 0xff, 0x62, 0xc2, 0x6f, 0xba, 0xab, 0xe4, 0xca, 0xd4, 0xba, 0x37, + 0xd1, 0x63, 0x2e, 0x77, 0xfa, 0xb4, 0xe2, 0x18, 0xf1, 0x0c, 0x56, 0x01, 0x39, 0x67, 0x43, 0xfe, 0xf4, 0x1c, 0xb0, + 0x5b, 0x56, 0xc2, 0x8b, 0xf8, 0xd3, 0x50, 0x56, 0x0b, 0x90, 0x1f, 0x39, 0x8f, 0xcc, 0x2f, 0x5f, 0x6d, 0x87, 0x72, + 0x4e, 0x51, 0x44, 0xcb, 0xa9, 0x69, 0x49, 0x21, 0x3b, 0xf4, 0x14, 0x4c, 0xa6, 0xb6, 0xfc, 0x7d, 0x9f, 0xb8, 0x24, + 0xdf, 0x4c, 0x22, 0xfb, 0x3a, 0xc0, 0x9a, 0xb5, 0xea, 0x1e, 0xba, 0x21, 0x18, 0x20, 0x32, 0x42, 0x99, 0xcd, 0xf5, + 0xdd, 0x7a, 0x30, 0x50, 0x30, 0xbf, 0x82, 0x6e, 0x5a, 0x74, 0x8a, 0x03, 0xe4, 0xac, 0x75, 0x8d, 0x4a, 0x55, 0x71, + 0xe8, 0x30, 0xef, 0x96, 0x55, 0xd9, 0x65, 0xe9, 0x85, 0x20, 0x35, 0xea, 0x2a, 0x58, 0xa4, 0x54, 0x44, 0xf1, 0x9e, + 0xfc, 0x1a, 0x98, 0x78, 0x66, 0xe5, 0x28, 0x8d, 0xe7, 0x80, 0x18, 0xa4, 0x80, 0x38, 0xe5, 0x57, 0x80, 0x26, 0xba, + 0x88, 0xc2, 0xec, 0x55, 0x5c, 0x05, 0xb5, 0xd5, 0xf4, 0x3f, 0x1d, 0xc8, 0xd8, 0xf3, 0xba, 0xdf, 0x4f, 0x89, 0xd1, + 0x0f, 0xa3, 0x30, 0xf0, 0xef, 0xf1, 0x74, 0xdf, 0x04, 0xa9, 0x79, 0xe5, 0x23, 0xbc, 0xa2, 0xcb, 0xad, 0x4d, 0xb9, + 0xa2, 0x71, 0xe1, 0xaf, 0x11, 0x1c, 0x3e, 0x75, 0x14, 0xdb, 0x6d, 0xaa, 0x9c, 0xda, 0x18, 0x0c, 0x42, 0xb8, 0x6f, + 0x65, 0xfc, 0xcf, 0xc4, 0xcb, 0x67, 0xd1, 0x1c, 0x14, 0xa5, 0x99, 0xe6, 0x0b, 0x29, 0xa4, 0x9b, 0x00, 0x7d, 0x34, + 0x08, 0xb5, 0xba, 0xf2, 0x4d, 0xe2, 0xa5, 0x6a, 0x5a, 0x9b, 0xa7, 0x58, 0xa3, 0x40, 0xcc, 0xa2, 0x79, 0xc3, 0x32, + 0x3a, 0x24, 0xd5, 0xe5, 0xd2, 0x34, 0xe3, 0x8d, 0xd5, 0x0c, 0xd5, 0x8a, 0xa3, 0x26, 0xa8, 0x51, 0xfa, 0x08, 0x17, + 0xc0, 0x7f, 0xd0, 0x1d, 0x47, 0x35, 0x8a, 0x14, 0x0d, 0xf8, 0x04, 0x31, 0x62, 0xcd, 0xe6, 0x09, 0x6b, 0x4d, 0x5d, + 0x33, 0xfa, 0x7d, 0x19, 0x32, 0x64, 0x92, 0x90, 0xa7, 0x0f, 0x97, 0xeb, 0x07, 0x52, 0x5d, 0x00, 0xbf, 0x72, 0xc5, + 0x66, 0xbd, 0xde, 0x1c, 0xe0, 0x7a, 0x61, 0xfd, 0xc2, 0xc6, 0x15, 0x9c, 0x5f, 0x12, 0xfc, 0xae, 0xfa, 0x11, 0x66, + 0x19, 0x54, 0x01, 0x19, 0x7f, 0x2c, 0xa8, 0xe2, 0xdc, 0xc5, 0xa4, 0x7e, 0x39, 0x52, 0x17, 0x94, 0x59, 0x3a, 0xb7, + 0x38, 0x41, 0xc0, 0x79, 0x58, 0x3d, 0x81, 0x64, 0x5f, 0x3e, 0xf6, 0x69, 0x46, 0x81, 0xea, 0x08, 0xf0, 0xd9, 0xac, + 0x1f, 0xc2, 0xfe, 0x01, 0x91, 0x85, 0xfa, 0x9b, 0xd7, 0x72, 0xd6, 0x90, 0x3c, 0x90, 0x6a, 0xee, 0x63, 0x38, 0x35, + 0x16, 0xf8, 0xd2, 0xa2, 0x37, 0x15, 0xbc, 0x26, 0x64, 0xee, 0x05, 0x5a, 0xfb, 0x16, 0x70, 0x84, 0x08, 0x2e, 0xa3, + 0x14, 0xa7, 0xbd, 0x5d, 0x2f, 0x40, 0x6e, 0x73, 0x0b, 0xf2, 0xfa, 0x91, 0x8b, 0x5f, 0x9c, 0x22, 0x3d, 0x8b, 0x2e, + 0x30, 0xd0, 0x05, 0x99, 0x37, 0xfe, 0x55, 0xc1, 0xca, 0x05, 0xf4, 0x5e, 0x2a, 0x56, 0x72, 0xb2, 0xed, 0xd4, 0x1f, + 0xa5, 0xb2, 0xdf, 0x9e, 0x59, 0x13, 0xf8, 0x5d, 0x62, 0xbf, 0x44, 0x26, 0xdf, 0xf4, 0xd8, 0xe4, 0x2b, 0xc3, 0xa2, + 0x53, 0xcb, 0xe0, 0x9c, 0x1e, 0x19, 0x9c, 0x7b, 0x3b, 0xab, 0x36, 0x11, 0x0c, 0x05, 0x49, 0xa0, 0xe9, 0xd2, 0xc3, + 0xba, 0xe9, 0xcf, 0x4f, 0x5a, 0x54, 0x5b, 0xb5, 0x6f, 0xdd, 0x8f, 0x43, 0xec, 0xe2, 0x77, 0x89, 0x67, 0x88, 0x48, + 0x7d, 0xa0, 0x03, 0x93, 0xc1, 0x13, 0x97, 0xfd, 0x3e, 0x14, 0x36, 0x1b, 0xcf, 0x47, 0x75, 0xf1, 0xba, 0xb8, 0x07, + 0x54, 0x87, 0x0a, 0xec, 0x72, 0x28, 0x43, 0x19, 0xb1, 0xa9, 0x2d, 0xf7, 0xfc, 0x71, 0x1d, 0xe6, 0x20, 0xef, 0x68, + 0x78, 0x9c, 0x33, 0x10, 0xc3, 0xe0, 0xeb, 0x3f, 0x3e, 0xda, 0xa7, 0xcd, 0x8f, 0x67, 0xf0, 0xdd, 0xd1, 0xd9, 0x7b, + 0xa4, 0xbb, 0x39, 0x5b, 0x97, 0xc5, 0x5d, 0x1a, 0x8b, 0xb3, 0x1f, 0x21, 0xf5, 0xc7, 0xb3, 0xa2, 0x3c, 0xfb, 0x51, + 0x55, 0xe6, 0xc7, 0x33, 0x5a, 0x70, 0xa3, 0x3f, 0xac, 0x89, 0xf7, 0x7b, 0xa5, 0x19, 0xd0, 0x96, 0x10, 0x99, 0xa5, + 0xd5, 0x8f, 0xa0, 0x44, 0x54, 0xfc, 0xa8, 0x32, 0xaa, 0xd5, 0xda, 0x71, 0xde, 0x27, 0x1a, 0x29, 0x9b, 0x26, 0x24, + 0xae, 0x96, 0xb0, 0x0e, 0xf5, 0xec, 0xb4, 0xf9, 0x76, 0x9c, 0x07, 0xea, 0x80, 0xc8, 0xf9, 0xd3, 0x7c, 0xb4, 0xa5, + 0xaf, 0xc1, 0xb7, 0x0e, 0x87, 0x7c, 0xb4, 0x33, 0x3f, 0x7d, 0xb2, 0x56, 0xca, 0xb8, 0x23, 0xd9, 0x3b, 0x58, 0x5b, + 0xe0, 0x04, 0x01, 0x0e, 0x00, 0xff, 0x70, 0xa0, 0xdf, 0x3b, 0xf9, 0x5b, 0xed, 0x96, 0x56, 0x3d, 0x9f, 0xb5, 0xb8, + 0x33, 0x5e, 0xd5, 0x86, 0xa8, 0x6d, 0x2f, 0xb1, 0xa5, 0xf7, 0x4d, 0x83, 0x9a, 0x22, 0xfa, 0x09, 0xab, 0x89, 0x55, + 0x1c, 0x16, 0xa4, 0x84, 0x24, 0x86, 0x63, 0xb4, 0x43, 0x8f, 0xd3, 0xc5, 0xd2, 0x93, 0xfb, 0x0e, 0x2f, 0xb7, 0xbe, + 0x0f, 0x48, 0x5a, 0x85, 0xf3, 0x77, 0x5e, 0x68, 0xe0, 0xd1, 0x8b, 0xbc, 0x2a, 0x32, 0x31, 0x12, 0x34, 0xca, 0xaf, + 0x48, 0x9c, 0x39, 0xc3, 0x5a, 0x9c, 0x29, 0xb0, 0xb0, 0x90, 0x20, 0xc1, 0x8b, 0x92, 0xd2, 0x83, 0xb3, 0x47, 0xfb, + 0xb2, 0xf9, 0x83, 0xe0, 0x21, 0x46, 0x0b, 0x60, 0xc4, 0xd9, 0xb5, 0xcb, 0xbb, 0x0f, 0xcb, 0xdc, 0xfb, 0xe3, 0xd5, + 0x6d, 0x5e, 0x40, 0x88, 0xe6, 0x99, 0x54, 0xac, 0x96, 0x67, 0xc0, 0x98, 0x27, 0xe2, 0xb3, 0xb0, 0x92, 0xd3, 0xa0, + 0xea, 0x28, 0x56, 0x6d, 0xe3, 0x51, 0xee, 0x01, 0xc5, 0xf7, 0xfb, 0x04, 0xb8, 0xdc, 0x7d, 0xf6, 0x52, 0xb9, 0xa6, + 0x92, 0x1e, 0x79, 0x0e, 0xd1, 0x92, 0x8f, 0x12, 0xa0, 0x78, 0x86, 0x38, 0x49, 0x61, 0xf5, 0xdc, 0x04, 0xa9, 0xc8, + 0xd7, 0x27, 0x14, 0x5f, 0x34, 0x8f, 0xa2, 0x86, 0x85, 0x2c, 0x81, 0xe3, 0x21, 0x99, 0x65, 0x73, 0x64, 0x29, 0x4f, + 0xdb, 0x53, 0xa4, 0xa3, 0x13, 0x4b, 0xfc, 0xb6, 0xe6, 0xd7, 0x8b, 0x54, 0x04, 0x26, 0xed, 0x6c, 0x61, 0xee, 0x85, + 0x30, 0x54, 0x09, 0xf7, 0x5e, 0xd5, 0xb3, 0x50, 0x6e, 0x8a, 0x56, 0xc5, 0xec, 0x61, 0x4a, 0xcc, 0x30, 0xc5, 0xfa, + 0x0b, 0x1b, 0x7e, 0x9d, 0x78, 0x31, 0x18, 0xae, 0x97, 0xbc, 0x9c, 0x6d, 0xcc, 0x42, 0x38, 0x1c, 0x36, 0x93, 0x62, + 0xb6, 0x84, 0x30, 0xd7, 0xe5, 0xfc, 0x70, 0xe8, 0x6a, 0xd9, 0x5a, 0x78, 0xf0, 0x50, 0xb5, 0x70, 0xd3, 0xb0, 0x1c, + 0x7e, 0x26, 0xb3, 0x18, 0xdb, 0xd7, 0xf8, 0xcc, 0xfe, 0x7c, 0xd1, 0x3d, 0x4b, 0x90, 0x7c, 0x63, 0x0d, 0xb4, 0x63, + 0xb3, 0x76, 0x87, 0xab, 0x11, 0x90, 0x94, 0xee, 0x46, 0xe7, 0x58, 0x76, 0xf2, 0x94, 0x20, 0x77, 0xb4, 0x02, 0xfb, + 0xdd, 0x37, 0xfe, 0x44, 0x8b, 0x3d, 0x68, 0xb7, 0xb1, 0x25, 0x44, 0x35, 0xed, 0xb9, 0x5c, 0x29, 0x96, 0x6e, 0xb0, + 0xb4, 0xd1, 0xf3, 0x61, 0x7d, 0xee, 0x1b, 0x39, 0x50, 0x30, 0x46, 0x3c, 0xb5, 0x0e, 0xa2, 0xd9, 0x1c, 0x68, 0x30, + 0xd0, 0x3c, 0xc2, 0x53, 0x0b, 0x1d, 0x94, 0x59, 0x1b, 0xf6, 0x4f, 0xc9, 0xc9, 0xf2, 0x38, 0x7c, 0x0b, 0xff, 0xf2, + 0x19, 0x36, 0x89, 0x29, 0xb6, 0xc7, 0x2f, 0x95, 0xa2, 0xc2, 0x63, 0x3b, 0xe2, 0x5a, 0xfb, 0x28, 0x6a, 0x43, 0xe5, + 0xf0, 0x6f, 0x61, 0x1f, 0x61, 0x5f, 0xd0, 0x04, 0x61, 0xb0, 0xeb, 0xcf, 0x04, 0x42, 0xc4, 0x42, 0xbc, 0xe0, 0x97, + 0x4a, 0x52, 0xd1, 0x09, 0x9f, 0xed, 0x4a, 0xe0, 0xad, 0xc3, 0x80, 0x3e, 0x21, 0x3f, 0x13, 0x09, 0x43, 0x33, 0xa1, + 0x77, 0xf4, 0xdf, 0x89, 0x9d, 0x6c, 0x92, 0x5b, 0x21, 0x1f, 0x48, 0x2a, 0x09, 0x26, 0x58, 0x79, 0xa1, 0x7c, 0xe5, + 0x5e, 0x28, 0xb5, 0xd6, 0x82, 0xd6, 0x2f, 0xff, 0x29, 0xf1, 0x0c, 0xfe, 0x1e, 0xc8, 0x18, 0x74, 0x1b, 0x51, 0x4d, + 0x72, 0x4c, 0x1f, 0xa5, 0xf3, 0x0c, 0x54, 0x40, 0x67, 0xeb, 0x2c, 0xac, 0x97, 0x45, 0xb9, 0x6a, 0x45, 0x8a, 0xca, + 0xd2, 0x47, 0xea, 0x31, 0xe6, 0x85, 0x79, 0x72, 0x22, 0x1f, 0x3c, 0x02, 0x60, 0x3c, 0xca, 0xd3, 0xaa, 0xa3, 0xb4, + 0x7e, 0x60, 0x19, 0x30, 0x02, 0x27, 0xca, 0x80, 0x47, 0x58, 0x06, 0xe6, 0x69, 0x97, 0xa1, 0x06, 0xb1, 0x46, 0xd5, + 0x95, 0xda, 0x60, 0x4e, 0x14, 0x25, 0x9f, 0x62, 0x69, 0x85, 0x31, 0x34, 0x75, 0xe5, 0x91, 0xf5, 0x92, 0x13, 0xf6, + 0x64, 0x37, 0x90, 0x6e, 0x61, 0xa3, 0x70, 0x06, 0x5d, 0xcb, 0x12, 0xe5, 0xa2, 0x5b, 0x46, 0x94, 0x89, 0x90, 0xfa, + 0xd9, 0xc3, 0x99, 0x56, 0xfb, 0x8d, 0x9d, 0xb4, 0x6f, 0x8f, 0x14, 0xbd, 0x60, 0xd0, 0x3e, 0xed, 0x91, 0x52, 0xcf, + 0x1a, 0xb9, 0x0c, 0x6c, 0xe9, 0x52, 0xd5, 0xf3, 0xdf, 0xa0, 0x7c, 0x07, 0x33, 0xe3, 0x6c, 0xf6, 0x87, 0xde, 0xdc, + 0x1e, 0xed, 0xeb, 0xe6, 0x0f, 0xd6, 0xeb, 0xc1, 0xd6, 0x20, 0x13, 0x9f, 0x29, 0x16, 0x2a, 0xab, 0x10, 0x2b, 0x48, + 0xfb, 0xdf, 0xc2, 0xfb, 0x03, 0xde, 0x1a, 0xa1, 0x59, 0x19, 0x0f, 0xf3, 0xd1, 0xa3, 0xbd, 0x68, 0xfe, 0xe8, 0x2c, + 0xdb, 0xca, 0x55, 0xc9, 0x6c, 0x7f, 0x1c, 0x25, 0xcd, 0xd9, 0xc3, 0x35, 0x92, 0x3a, 0xc0, 0x87, 0xeb, 0x33, 0x7c, + 0xa0, 0x12, 0x4a, 0x2d, 0xa8, 0x6a, 0xd0, 0xfa, 0xd8, 0x1f, 0xad, 0xe7, 0xf4, 0xf1, 0x63, 0x39, 0xdd, 0x92, 0x22, + 0x8c, 0x1f, 0x18, 0x4c, 0xd9, 0x89, 0x53, 0x97, 0xbc, 0x19, 0xd2, 0xbb, 0x6e, 0x95, 0xd4, 0x65, 0x8f, 0x12, 0x41, + 0xa8, 0x83, 0xf5, 0x8b, 0xfd, 0x10, 0x66, 0xb6, 0xe8, 0x0f, 0x9b, 0xd5, 0x9c, 0x00, 0x11, 0x01, 0xad, 0x55, 0xde, + 0x07, 0x8e, 0xf9, 0xc2, 0xac, 0xb9, 0x21, 0xdd, 0x7a, 0x73, 0xa5, 0xbd, 0x92, 0x02, 0xfa, 0x39, 0xc8, 0xdc, 0x3e, + 0xba, 0xe5, 0xaa, 0x65, 0x9e, 0x4b, 0x5b, 0x0e, 0x58, 0xb4, 0x10, 0xa8, 0xd9, 0xb9, 0x74, 0x38, 0x50, 0x10, 0xea, + 0x4a, 0x54, 0x11, 0x57, 0x47, 0xd1, 0x42, 0xd4, 0x6a, 0xd5, 0x2e, 0x27, 0x9b, 0x0a, 0xd9, 0x92, 0x08, 0x32, 0x4a, + 0xf6, 0x4a, 0xa8, 0x8f, 0x72, 0xb5, 0x67, 0x1a, 0x0e, 0xd0, 0x04, 0x6c, 0xda, 0xe0, 0x6f, 0x81, 0x7b, 0x19, 0x9c, + 0x99, 0xf6, 0x69, 0x18, 0x01, 0xa7, 0x39, 0xc4, 0xfc, 0xf9, 0x5d, 0x0f, 0x2a, 0x78, 0xd0, 0x91, 0xfe, 0xaa, 0x9e, + 0x15, 0x78, 0xe6, 0x9e, 0x78, 0xfe, 0xf2, 0x44, 0x7a, 0x99, 0xc3, 0x03, 0x4d, 0x83, 0x98, 0xf1, 0x67, 0x65, 0x19, + 0xee, 0x46, 0xcb, 0xb2, 0x58, 0x79, 0x91, 0xde, 0xc7, 0x33, 0x29, 0x06, 0x12, 0x33, 0x66, 0x46, 0x57, 0xb1, 0x8e, + 0x73, 0x18, 0xf7, 0xf6, 0x24, 0xac, 0xd0, 0xfe, 0x59, 0x62, 0xaf, 0x0b, 0xc0, 0x72, 0xc8, 0x1a, 0xb4, 0xc2, 0x3b, + 0xdd, 0xde, 0xee, 0x71, 0xc9, 0x8e, 0xe2, 0x06, 0xd0, 0xcf, 0x6a, 0x68, 0x99, 0xa0, 0x96, 0x59, 0x77, 0x32, 0x99, + 0x22, 0xb9, 0x7c, 0x1b, 0xf6, 0x92, 0x95, 0xf9, 0xbc, 0x91, 0xdb, 0xc3, 0xdb, 0x70, 0x25, 0x62, 0x6d, 0x41, 0x27, + 0x1d, 0x19, 0x87, 0x7b, 0xa1, 0xb9, 0x91, 0xee, 0x1f, 0x55, 0x49, 0x58, 0x8a, 0x18, 0x6e, 0x81, 0x6c, 0xaf, 0xb6, + 0x95, 0xa0, 0x04, 0x3e, 0xd8, 0xf7, 0xa5, 0x58, 0xa6, 0x5b, 0x01, 0xb8, 0x0e, 0xfc, 0x37, 0x89, 0x48, 0xe8, 0xee, + 0x3c, 0x44, 0xb1, 0x46, 0xde, 0x37, 0x88, 0xc6, 0xfe, 0x09, 0xe4, 0x34, 0x20, 0x13, 0x29, 0x46, 0xb2, 0x60, 0xe0, + 0x03, 0xc8, 0xf9, 0x1a, 0x4c, 0x72, 0xd3, 0xdc, 0xf3, 0x83, 0x5c, 0x77, 0x30, 0xed, 0x83, 0xee, 0xc5, 0xb5, 0x66, + 0x39, 0x78, 0xc5, 0x44, 0xfc, 0x1f, 0xb5, 0x57, 0xb2, 0x9c, 0x65, 0x7e, 0x63, 0x2e, 0x3a, 0x19, 0x5c, 0x35, 0x84, + 0x5f, 0xcc, 0xb2, 0x39, 0x8f, 0x66, 0x99, 0x8e, 0xfa, 0x2f, 0x9a, 0xa3, 0x52, 0x00, 0x4e, 0x1d, 0x2f, 0xc0, 0x1a, + 0xfa, 0x4a, 0x37, 0xad, 0x78, 0xa0, 0x31, 0x46, 0x41, 0x85, 0x0e, 0x42, 0xff, 0xa8, 0x01, 0x69, 0x83, 0x49, 0x9a, + 0x84, 0xca, 0x07, 0x17, 0x74, 0xc3, 0xd8, 0x5c, 0xb9, 0x5c, 0x35, 0xa9, 0x5a, 0x7e, 0x39, 0xa2, 0xbe, 0xab, 0x25, + 0x97, 0x6a, 0xf3, 0xa9, 0x51, 0xd6, 0x08, 0x32, 0x39, 0x4a, 0xbf, 0x4f, 0xb9, 0x70, 0x2b, 0x63, 0xb2, 0x3e, 0x1c, + 0xbc, 0x82, 0x9b, 0x1a, 0xbf, 0xc8, 0x89, 0x50, 0xd4, 0x1e, 0x12, 0x61, 0x6b, 0xb7, 0x42, 0xf7, 0x1e, 0x37, 0x4a, + 0xf3, 0x28, 0xdb, 0xc4, 0xa2, 0xf2, 0x7a, 0x09, 0x58, 0x8b, 0x7b, 0xc0, 0x8b, 0x4a, 0x4b, 0xbf, 0x62, 0x05, 0xa0, + 0x07, 0x48, 0x61, 0xe3, 0x05, 0x32, 0x60, 0xbd, 0xf3, 0x52, 0xbf, 0xdf, 0x37, 0xa6, 0xfc, 0x77, 0xf7, 0x39, 0x90, + 0x14, 0x8a, 0xb2, 0xde, 0xc1, 0x04, 0x82, 0x6b, 0x27, 0x69, 0xcf, 0x6a, 0xfe, 0x74, 0x5d, 0x7b, 0xc0, 0x6f, 0xe5, + 0x5b, 0x24, 0x56, 0x9f, 0xec, 0x8b, 0xcd, 0x3e, 0xad, 0x3e, 0x1a, 0x8d, 0x83, 0x60, 0x69, 0xf5, 0x4a, 0xab, 0x1c, + 0xf2, 0x86, 0x17, 0x20, 0x52, 0x59, 0x57, 0xd7, 0xca, 0xb9, 0xba, 0x16, 0x1c, 0xb9, 0x64, 0x4b, 0x9e, 0xc3, 0x7f, + 0x21, 0xf7, 0xca, 0xc3, 0xa1, 0xf0, 0xfb, 0xfd, 0x74, 0x46, 0x5a, 0x59, 0x60, 0x4f, 0x5b, 0xd7, 0x5e, 0xe8, 0x1f, + 0x0e, 0x2f, 0xc0, 0x6b, 0xc4, 0x3f, 0x1c, 0xca, 0x7e, 0xff, 0x83, 0xb9, 0xc9, 0x9c, 0x8f, 0x95, 0x52, 0xf6, 0x12, + 0x95, 0xee, 0xaf, 0x13, 0xde, 0xfb, 0xdf, 0xa3, 0xff, 0x3d, 0xba, 0xec, 0xc9, 0xae, 0xff, 0x90, 0xf0, 0x19, 0xde, + 0xd0, 0x99, 0xba, 0x9c, 0x33, 0xe9, 0xee, 0xae, 0xfc, 0xd0, 0x7b, 0x1a, 0x2a, 0xbe, 0x37, 0x37, 0x6d, 0xfc, 0x47, + 0x75, 0xa4, 0x49, 0xe8, 0xb8, 0xe8, 0x1f, 0x0e, 0x1f, 0x12, 0xad, 0x4f, 0x4b, 0x95, 0x3e, 0x4d, 0xe1, 0x28, 0x19, + 0x72, 0x37, 0xb7, 0x30, 0x1d, 0xd8, 0x8f, 0x9b, 0xaf, 0x92, 0x17, 0x67, 0x29, 0x5c, 0x7b, 0xf3, 0x59, 0x3a, 0x9f, + 0x82, 0x75, 0x65, 0x98, 0xcf, 0xea, 0x79, 0x00, 0xa9, 0x43, 0x48, 0xb3, 0xa6, 0xe1, 0x3f, 0x2b, 0x57, 0xf0, 0xd6, + 0x1e, 0xef, 0x06, 0x2e, 0x4a, 0x1d, 0xe9, 0x93, 0x36, 0x9a, 0x2e, 0xa9, 0xe4, 0x3f, 0x88, 0x3c, 0xc6, 0x98, 0x8d, + 0x17, 0xc4, 0xfb, 0x59, 0xe4, 0xd7, 0x05, 0x60, 0x17, 0x01, 0x18, 0x72, 0x3a, 0x77, 0x24, 0xf1, 0x97, 0xc9, 0xf7, + 0x7f, 0x4c, 0x97, 0xf6, 0xbe, 0x2c, 0x6e, 0x4b, 0x51, 0x55, 0x47, 0xa5, 0x6d, 0x6d, 0xb9, 0x1e, 0x98, 0x44, 0xfb, + 0x7d, 0xc9, 0x24, 0x9a, 0x62, 0x28, 0x0a, 0xdc, 0x1a, 0x7b, 0xd3, 0x94, 0x2b, 0xc6, 0xea, 0x91, 0xb1, 0x7e, 0x3e, + 0xdf, 0xbd, 0x8a, 0xbd, 0xd4, 0x0f, 0x52, 0x10, 0x84, 0x35, 0x94, 0x52, 0x8a, 0x7c, 0x70, 0x3e, 0xc3, 0x54, 0xa2, + 0xd6, 0xa5, 0x54, 0xf9, 0xc3, 0x48, 0xf3, 0x61, 0x0a, 0x7a, 0xd9, 0x7f, 0x57, 0x30, 0xff, 0x75, 0x7b, 0xb0, 0x3e, + 0xad, 0xcb, 0x34, 0xaa, 0x88, 0x2a, 0x2f, 0x4c, 0xb5, 0x09, 0x44, 0xf0, 0xa7, 0xc2, 0xe2, 0xfb, 0xf5, 0xc9, 0x91, + 0xa0, 0x31, 0x93, 0xe5, 0xed, 0x91, 0xfb, 0x85, 0x7d, 0xe5, 0x3a, 0x9e, 0xff, 0xb9, 0x99, 0xff, 0x03, 0x74, 0x86, + 0x2c, 0x9e, 0x72, 0xcb, 0x60, 0x81, 0xb3, 0x5f, 0xba, 0x7a, 0xc0, 0xdf, 0xcc, 0x13, 0x4f, 0x81, 0x8e, 0xf9, 0x29, + 0xba, 0x2a, 0xa6, 0xb3, 0x62, 0x00, 0x5c, 0xb6, 0x7e, 0x63, 0xcd, 0x89, 0xaf, 0x16, 0xe5, 0x95, 0x5c, 0x10, 0xfa, + 0xba, 0x0a, 0xb3, 0x71, 0x55, 0x6c, 0x2a, 0x51, 0x6c, 0xea, 0x1e, 0xa9, 0x65, 0xf3, 0x69, 0x6d, 0x2b, 0x64, 0xff, + 0x2e, 0x5a, 0x0c, 0x5e, 0x86, 0x75, 0x32, 0xca, 0xd2, 0xf5, 0x14, 0xf8, 0xf5, 0x02, 0x38, 0x8b, 0xcc, 0x2b, 0x9f, + 0x9d, 0x3d, 0x60, 0x8b, 0xc6, 0x53, 0x20, 0x47, 0xa5, 0x3f, 0xf2, 0xc6, 0xe8, 0xf4, 0x44, 0xbf, 0x9f, 0x4f, 0x29, + 0xe6, 0xeb, 0xef, 0x00, 0xcf, 0x55, 0xcb, 0x05, 0xe8, 0xcb, 0x50, 0x07, 0x95, 0x28, 0xb5, 0x62, 0x18, 0xb1, 0xf0, + 0x77, 0x81, 0x44, 0xce, 0x14, 0xd8, 0xac, 0xa2, 0x24, 0x54, 0xa2, 0x52, 0xb2, 0x35, 0x41, 0x2d, 0xbd, 0x2f, 0xca, + 0x7a, 0x5f, 0x81, 0xa3, 0x64, 0xa4, 0xcd, 0x72, 0xd2, 0x8c, 0x2b, 0x50, 0xe6, 0xa2, 0x1f, 0xec, 0xef, 0x95, 0xe7, + 0x37, 0x32, 0x9f, 0xe5, 0xbe, 0xa3, 0x73, 0xda, 0x8e, 0x0b, 0x94, 0xb9, 0xe5, 0xb4, 0xd5, 0x92, 0xc7, 0xe4, 0x3d, + 0x0b, 0xb6, 0xfd, 0x57, 0x09, 0x52, 0x2c, 0xc2, 0x7c, 0x42, 0x95, 0xcd, 0xbf, 0x21, 0xd4, 0x16, 0x07, 0xf6, 0xd8, + 0x85, 0x89, 0xf8, 0x6f, 0xc1, 0x92, 0x18, 0x66, 0xa5, 0x08, 0xe3, 0x1d, 0x78, 0xff, 0x6c, 0x2a, 0x31, 0x3a, 0x43, + 0x27, 0xf7, 0xb3, 0xfb, 0xb4, 0x4e, 0xce, 0x5e, 0xbd, 0x38, 0xfb, 0xb1, 0x37, 0x28, 0x46, 0x69, 0x3c, 0xe8, 0xfd, + 0x78, 0xb6, 0xda, 0x00, 0x5a, 0xa6, 0x38, 0x8b, 0xc9, 0x94, 0x26, 0xe2, 0x33, 0x32, 0x0c, 0x9e, 0xd5, 0x89, 0x38, + 0xa3, 0x89, 0xe9, 0xbe, 0x46, 0x69, 0xf2, 0xed, 0x28, 0xcc, 0xe1, 0xe5, 0x52, 0x6c, 0x2a, 0x11, 0x83, 0x9d, 0x52, + 0xcd, 0xb3, 0xbc, 0x7d, 0x16, 0xe7, 0xa3, 0x0e, 0x59, 0xa5, 0x03, 0x7f, 0x7b, 0x22, 0xed, 0xaa, 0x74, 0x05, 0x84, + 0x1e, 0x00, 0x27, 0x5d, 0xf9, 0xf3, 0x70, 0xc8, 0x13, 0x08, 0xb5, 0x60, 0x4e, 0xa6, 0x11, 0xdd, 0x90, 0xae, 0xb1, + 0xcf, 0xc0, 0x2c, 0xa4, 0x34, 0x0f, 0x6e, 0xae, 0x16, 0x43, 0x77, 0xc5, 0xca, 0x51, 0x58, 0xad, 0x45, 0x54, 0x23, + 0xeb, 0x31, 0x38, 0xef, 0x40, 0x04, 0x80, 0x22, 0x07, 0xcf, 0x78, 0xd4, 0xef, 0x47, 0x2a, 0x28, 0x27, 0xa1, 0x5f, + 0x14, 0xfa, 0xa5, 0xe1, 0x28, 0x63, 0xfe, 0x3c, 0xd4, 0x1c, 0x01, 0xf5, 0x96, 0x87, 0x8a, 0x2e, 0x00, 0x97, 0x73, + 0xc4, 0x8c, 0xf3, 0x1e, 0x77, 0x81, 0x39, 0x15, 0x05, 0x85, 0xba, 0x0e, 0x96, 0x0a, 0x80, 0xde, 0xd4, 0x47, 0x7a, + 0x4e, 0xfe, 0x1f, 0xde, 0xde, 0x85, 0xbb, 0x6d, 0x1b, 0x6b, 0x17, 0xfe, 0x2b, 0x16, 0x4f, 0xaa, 0x12, 0x11, 0x24, + 0x4b, 0x4e, 0xd2, 0x99, 0x52, 0x86, 0x75, 0xdc, 0x5c, 0x9a, 0xcc, 0x34, 0x97, 0x26, 0x69, 0x3b, 0x53, 0x1d, 0xbd, + 0x2e, 0x4d, 0xc2, 0x16, 0x1b, 0x1a, 0x50, 0x49, 0xca, 0xb6, 0x22, 0xf1, 0xbf, 0x7f, 0x6b, 0x6f, 0x5c, 0x49, 0xd1, + 0x4e, 0xe6, 0x3d, 0xef, 0xf9, 0x56, 0xd6, 0x8a, 0x45, 0x10, 0xc4, 0x1d, 0x1b, 0x1b, 0xfb, 0xf2, 0x6c, 0x97, 0x60, + 0xf1, 0xdc, 0xc0, 0xe2, 0xd5, 0xc5, 0xa2, 0xba, 0xe2, 0x5a, 0x6e, 0x61, 0x53, 0xca, 0x2a, 0x86, 0x00, 0x02, 0xcd, + 0x98, 0x61, 0xb7, 0xdc, 0xe5, 0x48, 0xd6, 0x45, 0xc1, 0xc5, 0x5e, 0x60, 0xe8, 0x66, 0x5c, 0x32, 0x73, 0x70, 0x35, + 0xc3, 0x3a, 0xa9, 0x28, 0xc0, 0xae, 0x2e, 0x40, 0xf6, 0xc2, 0x50, 0xd7, 0xcd, 0x6c, 0xb9, 0x0e, 0x7c, 0x5d, 0xba, + 0xf0, 0x25, 0x05, 0x2f, 0x57, 0x52, 0x94, 0xd9, 0x35, 0xff, 0xc9, 0xbe, 0x6c, 0xc6, 0x92, 0x42, 0x3b, 0xd2, 0xd7, + 0xed, 0xee, 0x68, 0x31, 0x8e, 0x2d, 0xc7, 0xb7, 0x54, 0xba, 0xd6, 0xa3, 0xea, 0x85, 0xd0, 0xd6, 0xb9, 0x96, 0x59, + 0x9a, 0x72, 0xf1, 0x4a, 0xa4, 0x59, 0xe2, 0x25, 0xc7, 0x3a, 0x56, 0xb5, 0x0b, 0x82, 0xe5, 0xc2, 0x24, 0x3f, 0xcb, + 0x4a, 0x8c, 0x1d, 0xdc, 0x68, 0x54, 0x2b, 0xea, 0x94, 0x89, 0x81, 0x21, 0xdf, 0x63, 0xf0, 0x6d, 0x56, 0x24, 0xc0, + 0xf0, 0x63, 0xa2, 0xbe, 0xa4, 0xa7, 0x10, 0xf0, 0x41, 0x85, 0xe6, 0x7e, 0xc6, 0x11, 0xfc, 0xda, 0xaa, 0xcc, 0x81, + 0xc9, 0xd6, 0x2a, 0x48, 0xc4, 0xbd, 0xcb, 0xe6, 0x7a, 0x11, 0x2d, 0xd4, 0x5d, 0xa8, 0x17, 0xef, 0x76, 0xbd, 0x44, + 0xd1, 0x01, 0x27, 0x3f, 0x0d, 0x5e, 0xc4, 0x59, 0xce, 0xd3, 0x83, 0x4a, 0x1e, 0xa8, 0x0d, 0x75, 0xa0, 0x9c, 0x39, + 0x60, 0xe7, 0x7d, 0x5b, 0x1d, 0xe8, 0x35, 0x7d, 0xa0, 0xdb, 0x79, 0x00, 0x17, 0x0c, 0xdc, 0xb9, 0x97, 0xd9, 0x35, + 0x17, 0x07, 0xa0, 0x0c, 0xb4, 0xc6, 0x03, 0x75, 0x59, 0x8d, 0xd4, 0xc4, 0xe8, 0x18, 0xd6, 0x89, 0x3e, 0x98, 0x03, + 0xfa, 0x33, 0x84, 0xb5, 0x6f, 0xbd, 0x5d, 0xe9, 0x83, 0x36, 0xa0, 0x2f, 0x96, 0xa6, 0x0f, 0x3a, 0x70, 0xbc, 0x8a, + 0x0e, 0xdc, 0x18, 0x52, 0x0d, 0xda, 0x6a, 0x64, 0x15, 0x28, 0xde, 0xf0, 0x16, 0xef, 0xde, 0xb5, 0x64, 0xeb, 0xbd, + 0x44, 0x8c, 0xaf, 0x4c, 0x54, 0x71, 0x26, 0x4e, 0xbd, 0x54, 0x5e, 0x6b, 0x27, 0x19, 0x61, 0x7c, 0xcb, 0x4a, 0xea, + 0xef, 0x10, 0x73, 0x8b, 0x34, 0x87, 0xc1, 0xab, 0xb0, 0x22, 0x33, 0xde, 0xef, 0xcb, 0x99, 0x8c, 0xca, 0x99, 0x38, + 0x2c, 0x23, 0x05, 0xd6, 0x76, 0x97, 0x08, 0xe8, 0x5e, 0x09, 0x90, 0x2f, 0x00, 0xaa, 0xee, 0x13, 0xfe, 0xdc, 0x27, + 0xf5, 0xe9, 0x14, 0xfa, 0x14, 0xda, 0x7a, 0xc5, 0x15, 0xc4, 0xab, 0xba, 0x31, 0xb2, 0x8d, 0x0a, 0x5a, 0x3c, 0x96, + 0x67, 0xb5, 0x61, 0x6c, 0x4e, 0xad, 0x7f, 0xbd, 0xd9, 0x60, 0xca, 0xe6, 0x42, 0xad, 0xc2, 0x90, 0x44, 0x9f, 0x4a, + 0x2f, 0x92, 0x88, 0x85, 0xcd, 0x6a, 0x6d, 0x7e, 0x13, 0x06, 0x24, 0x13, 0x29, 0xee, 0x67, 0x4b, 0x9c, 0xbb, 0x78, + 0x3c, 0xaf, 0xfa, 0x5a, 0x4b, 0x8b, 0x4c, 0x9b, 0x6f, 0xf5, 0x65, 0x48, 0x53, 0x51, 0x43, 0x1a, 0x75, 0x66, 0xd0, + 0x7d, 0xbb, 0xbc, 0x65, 0x35, 0xc2, 0x04, 0x78, 0xa5, 0x33, 0xe8, 0x46, 0xe3, 0x81, 0x58, 0x56, 0xa3, 0x62, 0x2d, + 0x04, 0x02, 0x0f, 0x43, 0x8e, 0x99, 0x25, 0x24, 0xd9, 0x67, 0xfe, 0x83, 0x8a, 0xb3, 0x50, 0xc4, 0x37, 0x06, 0xd9, + 0xbb, 0xb2, 0xae, 0xdd, 0x75, 0xe4, 0xe7, 0xc4, 0xc2, 0x6a, 0xff, 0xa1, 0x79, 0xd4, 0x1a, 0x67, 0x01, 0x6d, 0x4d, + 0xab, 0x1b, 0x0e, 0xf7, 0xa8, 0x8e, 0x45, 0x69, 0xb0, 0x89, 0x3d, 0xb2, 0x5c, 0xb4, 0x8e, 0x19, 0x34, 0xa0, 0xbf, + 0xcd, 0xae, 0xd6, 0x57, 0x08, 0xe0, 0x56, 0x22, 0xeb, 0x24, 0x95, 0x7f, 0x49, 0x7b, 0xd4, 0xb5, 0x3d, 0x95, 0xff, + 0x6d, 0x9b, 0x2a, 0x87, 0x16, 0x53, 0x1e, 0xbb, 0x39, 0x0b, 0x54, 0x47, 0x82, 0x28, 0x50, 0x5b, 0x2f, 0x98, 0x7a, + 0xa7, 0x4c, 0xd1, 0x01, 0x02, 0x5d, 0x98, 0x33, 0xec, 0x2b, 0x8e, 0x18, 0xb3, 0x54, 0x62, 0x30, 0xf5, 0x31, 0x46, + 0x35, 0xad, 0x15, 0xa0, 0xeb, 0xa7, 0x5b, 0xf8, 0x13, 0x15, 0x35, 0x1a, 0x6a, 0x8d, 0xa4, 0x50, 0x34, 0x51, 0xa1, + 0xc8, 0xd2, 0x42, 0xc7, 0x55, 0xe8, 0x24, 0x12, 0x96, 0x80, 0x86, 0x09, 0xd1, 0x49, 0x05, 0xde, 0x1a, 0xc0, 0x99, + 0x8f, 0x8b, 0x72, 0x5d, 0x68, 0x83, 0xb9, 0x97, 0xf1, 0x35, 0x7f, 0xf5, 0xcc, 0x19, 0xd5, 0xb7, 0xac, 0xf5, 0x3d, + 0x2d, 0xc8, 0xcb, 0x90, 0x53, 0x74, 0x60, 0x62, 0x27, 0x5b, 0x34, 0xc6, 0x28, 0x6b, 0x1d, 0xf5, 0xe2, 0xad, 0x0e, + 0xc5, 0xa2, 0x4d, 0xf0, 0xee, 0xf1, 0x14, 0xd1, 0x86, 0x87, 0xc2, 0x58, 0x55, 0xe3, 0x53, 0xc9, 0x5a, 0x7a, 0xb0, + 0x82, 0xa7, 0xeb, 0x84, 0x87, 0xa0, 0x47, 0x22, 0xec, 0x24, 0x2c, 0xe6, 0xf1, 0x02, 0x8e, 0x93, 0x82, 0x80, 0xda, + 0x41, 0x5f, 0xc1, 0xe7, 0x0b, 0x74, 0x7f, 0x95, 0xe8, 0x01, 0x86, 0x16, 0xc4, 0xcd, 0x28, 0xa8, 0xa3, 0xab, 0x78, + 0xd5, 0x50, 0x91, 0xf0, 0x79, 0x01, 0xb6, 0x43, 0x4a, 0x3d, 0x05, 0x5a, 0xa8, 0x44, 0xe9, 0x87, 0x81, 0xef, 0xd0, + 0x18, 0xd8, 0x5a, 0x07, 0x68, 0xe8, 0x67, 0x4c, 0x53, 0xeb, 0x0c, 0x95, 0xcf, 0xbc, 0x7b, 0x66, 0xb4, 0x9c, 0x59, + 0x34, 0x06, 0x7d, 0x1b, 0x4d, 0x51, 0x9c, 0x93, 0xcf, 0x82, 0x22, 0x4e, 0xb3, 0x38, 0x07, 0xbf, 0xcd, 0xb8, 0xc0, + 0x8c, 0x49, 0x5c, 0xf1, 0x4b, 0x59, 0x80, 0xb6, 0x3b, 0x57, 0xa9, 0x75, 0x0d, 0x02, 0xb2, 0x97, 0x60, 0xf5, 0xd2, + 0xd0, 0x51, 0x39, 0xef, 0x2e, 0x6d, 0x0a, 0x91, 0x88, 0x10, 0x6c, 0x9a, 0xe9, 0x92, 0x9d, 0x86, 0x4a, 0x9b, 0x03, + 0xa1, 0x8e, 0xd0, 0xb8, 0x7f, 0x1a, 0xc6, 0x56, 0x53, 0x6c, 0xed, 0xde, 0x76, 0xbb, 0x7f, 0x96, 0x5e, 0x3a, 0xcd, + 0x49, 0x8f, 0xb1, 0x7f, 0x96, 0x61, 0x31, 0xb2, 0x1d, 0x21, 0xb0, 0xe4, 0xbc, 0x4f, 0xfd, 0x57, 0xb4, 0x9c, 0x27, + 0x60, 0x3a, 0xa2, 0x83, 0xe5, 0x02, 0x65, 0xc7, 0x80, 0xee, 0xc0, 0xe0, 0x8a, 0x7e, 0x1f, 0xac, 0x32, 0xcc, 0x85, + 0x64, 0x49, 0x52, 0x06, 0xcf, 0x53, 0x0f, 0x0e, 0x7e, 0xcd, 0x94, 0xb9, 0x8b, 0xb2, 0x3e, 0x5d, 0x92, 0x69, 0x8a, + 0x0c, 0xc4, 0x3a, 0xdc, 0x66, 0x69, 0x94, 0x28, 0x11, 0xd9, 0x12, 0xfd, 0x23, 0x0d, 0xc5, 0xd2, 0x91, 0x7b, 0x91, + 0x2a, 0x11, 0x2a, 0xe6, 0x29, 0x9e, 0xd4, 0x69, 0x9d, 0x8e, 0x30, 0xf4, 0x24, 0x28, 0xe5, 0x6a, 0x18, 0xa8, 0x92, + 0xea, 0xa5, 0xb0, 0x2d, 0x76, 0x3b, 0x7d, 0xb1, 0x12, 0xf3, 0x78, 0x81, 0x2f, 0x05, 0x8e, 0xe2, 0x3f, 0xb9, 0x17, + 0x76, 0x4a, 0x6d, 0x0f, 0x6a, 0x47, 0x94, 0xd0, 0x7f, 0x72, 0xb8, 0x48, 0xfc, 0x20, 0x75, 0x08, 0x40, 0xb4, 0x08, + 0x39, 0x53, 0x07, 0xa9, 0xe1, 0x86, 0xf6, 0x84, 0xff, 0x86, 0xeb, 0x33, 0xce, 0xe8, 0x4d, 0x35, 0xa3, 0x86, 0xf2, + 0xf5, 0xa0, 0x8d, 0x51, 0x9f, 0x0d, 0x1c, 0x56, 0x88, 0x42, 0x1b, 0x76, 0x52, 0x2a, 0xd1, 0xc2, 0x50, 0xaa, 0xbf, + 0x84, 0x8a, 0x13, 0xee, 0xcc, 0x28, 0x4b, 0xc6, 0xa7, 0xe5, 0xb1, 0x98, 0x0e, 0x06, 0x25, 0xa9, 0x8c, 0x85, 0x1e, + 0x5c, 0x0f, 0x3c, 0xff, 0x1e, 0xb8, 0x85, 0x78, 0xc8, 0xc8, 0x62, 0xc8, 0x0d, 0x4e, 0x7e, 0x8b, 0x93, 0xab, 0x46, + 0xa5, 0x8a, 0x63, 0x4d, 0x54, 0x0b, 0x7e, 0x2c, 0xc3, 0x00, 0x7d, 0x92, 0x02, 0x30, 0x19, 0x4c, 0xf9, 0x2d, 0x48, + 0x94, 0xce, 0xd4, 0x0d, 0xe9, 0x17, 0x51, 0xf0, 0x0b, 0x5e, 0x70, 0x91, 0xb8, 0x02, 0x2c, 0xef, 0x60, 0x7b, 0x1d, + 0x55, 0x54, 0x61, 0xf2, 0x9a, 0x1e, 0x47, 0xdc, 0x78, 0xff, 0x99, 0x1e, 0x5b, 0xcc, 0x56, 0xeb, 0xd8, 0xe0, 0x33, + 0xc7, 0xe0, 0x82, 0xae, 0x25, 0xb6, 0x86, 0x6a, 0x58, 0x11, 0x18, 0xb8, 0x80, 0x83, 0xb0, 0x44, 0x71, 0x6c, 0x25, + 0xaf, 0x48, 0x43, 0x4a, 0x7b, 0xcf, 0x70, 0xb4, 0x49, 0x8e, 0x6f, 0xb3, 0xec, 0x26, 0x70, 0xbe, 0xe8, 0x9c, 0x34, + 0x13, 0xd6, 0x06, 0xef, 0xf3, 0xe6, 0xfc, 0xba, 0x7b, 0x48, 0xa8, 0x8a, 0x7b, 0xc3, 0xdb, 0x71, 0x6f, 0x9c, 0xf0, + 0x6b, 0x2e, 0x16, 0x3a, 0x54, 0x8b, 0xb9, 0x64, 0xf9, 0xad, 0xf5, 0x6e, 0x49, 0x52, 0x2b, 0xa0, 0x7d, 0x96, 0x05, + 0x35, 0x11, 0x00, 0xf2, 0x87, 0xbf, 0x40, 0xe8, 0x0c, 0x7f, 0x7b, 0x0c, 0xae, 0x48, 0xe1, 0x9d, 0x43, 0x20, 0xac, + 0xe9, 0xe6, 0x5e, 0x6d, 0xc0, 0x17, 0xe3, 0xfe, 0x8c, 0xa9, 0xa7, 0xdf, 0x66, 0x72, 0x5f, 0xd7, 0xed, 0x91, 0x65, + 0xf8, 0x08, 0x57, 0x0a, 0xe0, 0x66, 0xc2, 0x5f, 0x0c, 0x33, 0xa9, 0x3e, 0x01, 0x4c, 0x35, 0x1d, 0xdc, 0x27, 0x08, + 0x0c, 0xa0, 0x12, 0x2d, 0x46, 0xd7, 0xca, 0x11, 0xcd, 0xc0, 0xad, 0xe9, 0x56, 0x18, 0x6f, 0x3d, 0x68, 0xa1, 0x67, + 0x1a, 0x4e, 0xfc, 0x07, 0xcd, 0xbc, 0x2a, 0x20, 0x80, 0x56, 0x46, 0xf0, 0xd6, 0xfa, 0x64, 0x8e, 0x10, 0x9f, 0xb0, + 0x24, 0x9a, 0xb0, 0x78, 0xa6, 0xf8, 0x31, 0xa1, 0xdb, 0xa6, 0xb6, 0xe9, 0x23, 0xd2, 0x5f, 0x5c, 0xb3, 0x7e, 0xca, + 0xb2, 0xf6, 0xed, 0xa1, 0xe2, 0xc5, 0xb4, 0x19, 0x07, 0x31, 0x51, 0xc5, 0xf8, 0x5f, 0x70, 0x5f, 0x6a, 0x05, 0x88, + 0xcc, 0x5d, 0xf5, 0xf4, 0xfb, 0xcd, 0x6c, 0x39, 0x10, 0x2a, 0xbf, 0x33, 0x48, 0xfa, 0x74, 0x68, 0x3f, 0xb0, 0x49, + 0xd4, 0x16, 0x7a, 0xfe, 0xb8, 0xd4, 0x4d, 0xbc, 0xbc, 0x36, 0x35, 0xa2, 0x15, 0x32, 0x54, 0xb6, 0x0e, 0x58, 0xdf, + 0x2f, 0xc3, 0xfd, 0x45, 0x4d, 0x43, 0xad, 0x7b, 0xee, 0x5a, 0x14, 0x9c, 0xf8, 0x03, 0x8c, 0xc5, 0x85, 0xa4, 0xd6, + 0xf1, 0x98, 0xf4, 0xa3, 0x85, 0x4c, 0x6e, 0xd4, 0xd5, 0xc9, 0x99, 0x62, 0x9e, 0xc0, 0x05, 0xb8, 0x6c, 0xfb, 0x2b, + 0x2a, 0x75, 0x29, 0xb7, 0x57, 0x94, 0xa6, 0x87, 0xb4, 0xbd, 0x8a, 0xf3, 0xb6, 0xe0, 0x82, 0x7f, 0xa5, 0xe0, 0xc2, + 0x3a, 0x58, 0x77, 0xdc, 0x29, 0x7b, 0xc2, 0x13, 0x65, 0x5a, 0x1b, 0xdc, 0x75, 0x83, 0x31, 0x31, 0xf6, 0xbb, 0x4b, + 0x9e, 0x7c, 0x42, 0x16, 0xfc, 0x87, 0x4c, 0x80, 0x67, 0xb2, 0x7b, 0xa5, 0xf2, 0xbf, 0xf4, 0xaf, 0xb6, 0xf6, 0x9d, + 0x35, 0xff, 0xf4, 0xac, 0x87, 0x3b, 0x87, 0xc9, 0x8f, 0xd5, 0x19, 0xd0, 0xed, 0x95, 0x4c, 0x39, 0x20, 0x03, 0x58, + 0x8b, 0x64, 0x34, 0xe0, 0x43, 0x2b, 0xcb, 0xb6, 0xef, 0xb4, 0xba, 0x20, 0xdc, 0x49, 0xe0, 0xa6, 0x77, 0xd7, 0x66, + 0x66, 0x4e, 0xd7, 0x4a, 0x34, 0x5d, 0x1a, 0x5b, 0xcb, 0x52, 0x85, 0xf1, 0x7e, 0xe7, 0x49, 0x36, 0xcd, 0x8f, 0x97, + 0xd3, 0xdc, 0x52, 0xb7, 0xad, 0x5b, 0x36, 0x80, 0x86, 0xd8, 0xb5, 0xb6, 0x72, 0xc0, 0xcb, 0xed, 0x41, 0x34, 0x5f, + 0x2b, 0x42, 0x4f, 0x95, 0x08, 0x7d, 0x9a, 0x36, 0xfb, 0x60, 0x57, 0xd5, 0xba, 0x11, 0xf2, 0x68, 0x90, 0x6a, 0x46, + 0xfe, 0xed, 0x35, 0x2f, 0x2e, 0x72, 0x79, 0x03, 0x70, 0xc8, 0xa4, 0x36, 0x0a, 0xcb, 0x2b, 0x70, 0xe7, 0x47, 0xc7, + 0x71, 0x26, 0x46, 0x39, 0xc6, 0x6d, 0x45, 0xa4, 0x64, 0x9d, 0x38, 0x03, 0x3c, 0x64, 0x7f, 0xd2, 0x74, 0x68, 0xd7, + 0x02, 0xc3, 0xfb, 0x02, 0x77, 0x95, 0xb3, 0x93, 0x6d, 0x6e, 0x17, 0x7d, 0x73, 0x86, 0x75, 0x47, 0x4a, 0x6b, 0x63, + 0xd1, 0x75, 0x07, 0x6b, 0xcd, 0xa0, 0x2d, 0x42, 0xc9, 0x87, 0xdc, 0x49, 0xfb, 0x39, 0xa0, 0xc1, 0x59, 0x96, 0xde, + 0x5a, 0xab, 0xfc, 0xad, 0x16, 0xe2, 0x44, 0x31, 0x75, 0xe2, 0x9b, 0x28, 0xd1, 0xe7, 0x67, 0x62, 0xdc, 0x40, 0x20, + 0xf5, 0x25, 0xc6, 0xd7, 0x28, 0xc2, 0x04, 0xae, 0x03, 0x51, 0x6c, 0x4f, 0xd4, 0xc6, 0x72, 0x04, 0x9d, 0x10, 0xe2, + 0x1d, 0x94, 0x61, 0xac, 0x2e, 0x0e, 0xb4, 0xc1, 0xd2, 0xd7, 0xad, 0x75, 0x6e, 0x08, 0x85, 0x71, 0x02, 0x53, 0x0c, + 0x92, 0x3a, 0xeb, 0x2c, 0x13, 0x54, 0xd9, 0x31, 0xe9, 0xbc, 0x0f, 0xd0, 0xfd, 0xb5, 0x68, 0x8a, 0xaf, 0x3b, 0x77, + 0xd0, 0x5d, 0x5c, 0xbf, 0xd6, 0x22, 0x37, 0xf8, 0xf3, 0x96, 0x08, 0x8b, 0xc0, 0x59, 0x6b, 0xf2, 0x55, 0x23, 0x1c, + 0x98, 0x92, 0x4c, 0xc3, 0x5e, 0xae, 0x6c, 0xba, 0x77, 0xbb, 0x5e, 0xef, 0x4e, 0x11, 0x57, 0x8f, 0xb1, 0xca, 0xbb, + 0x99, 0xdb, 0x3b, 0xd5, 0x5a, 0xec, 0xdf, 0xb4, 0xfd, 0x14, 0x3b, 0x6a, 0xad, 0xdd, 0x6e, 0x38, 0xa1, 0x86, 0x7c, + 0x2b, 0xaa, 0xb4, 0x3a, 0xdd, 0x18, 0xb4, 0x43, 0x68, 0x6b, 0x91, 0xc1, 0x8d, 0xf2, 0x99, 0x13, 0x3a, 0xa9, 0x90, + 0xab, 0x4e, 0x5d, 0xb0, 0xbd, 0xe2, 0xd5, 0x52, 0xa6, 0x91, 0xa0, 0x68, 0x73, 0x1e, 0x95, 0x34, 0x91, 0x6b, 0x51, + 0x45, 0xb2, 0x46, 0xbd, 0xa8, 0xd5, 0x18, 0x20, 0x20, 0xd3, 0x59, 0xd3, 0x83, 0x2a, 0x98, 0x0d, 0x65, 0x24, 0xa7, + 0x6f, 0xc0, 0xd2, 0x1e, 0x39, 0xd6, 0xfa, 0xae, 0x3a, 0x5b, 0x7c, 0xab, 0x27, 0x04, 0x53, 0x98, 0x3d, 0x10, 0x11, + 0xae, 0x69, 0x0c, 0x39, 0xed, 0x12, 0x97, 0x35, 0xdd, 0x12, 0xee, 0xe0, 0x76, 0x25, 0x3b, 0x71, 0xf3, 0xa4, 0xb9, + 0xb9, 0x82, 0x9d, 0x14, 0xf3, 0x31, 0x68, 0xbf, 0xa4, 0xba, 0x76, 0x69, 0x6e, 0x3d, 0x1e, 0x04, 0x34, 0x18, 0x14, + 0x86, 0x7f, 0x9d, 0x18, 0x0f, 0x4f, 0x1a, 0x10, 0x24, 0xe5, 0x22, 0x1c, 0xfb, 0x46, 0xf4, 0x93, 0xa9, 0x3c, 0xe6, + 0x68, 0xf1, 0x0e, 0xad, 0xce, 0x21, 0xa0, 0x97, 0x08, 0x25, 0x31, 0xaa, 0x42, 0x23, 0x82, 0xf2, 0xb4, 0xfc, 0xa5, + 0xaa, 0x0e, 0x01, 0x85, 0xb4, 0xaf, 0x28, 0x94, 0x6d, 0x12, 0x43, 0x33, 0xfc, 0x72, 0x3e, 0x59, 0xe8, 0x19, 0x18, + 0xc8, 0xf9, 0xd1, 0x42, 0xcf, 0xc2, 0x40, 0xce, 0x1f, 0x2d, 0x6a, 0xb7, 0x0e, 0x34, 0x01, 0xf1, 0x5c, 0x38, 0x3a, + 0x29, 0xad, 0xca, 0x16, 0xd0, 0xed, 0x7d, 0x04, 0xfd, 0x9f, 0xf6, 0x10, 0x74, 0x72, 0xa1, 0x3d, 0xb9, 0x01, 0x6d, + 0x87, 0x24, 0xb0, 0x57, 0x4c, 0x2a, 0x4c, 0x2c, 0xa2, 0x63, 0x36, 0x06, 0x43, 0x6c, 0xf5, 0xc1, 0x31, 0x1b, 0x4f, + 0x7d, 0x12, 0x04, 0x8c, 0xee, 0x4b, 0x03, 0x0e, 0x7e, 0x8b, 0x57, 0xe9, 0x93, 0xad, 0x40, 0x37, 0x7d, 0x77, 0x37, + 0xf4, 0x2e, 0xae, 0xe0, 0x54, 0xed, 0xee, 0x49, 0xe8, 0x26, 0xd3, 0x8e, 0xd5, 0x6b, 0x88, 0x1b, 0xf2, 0x2b, 0xa3, + 0xd1, 0xc8, 0xa6, 0x84, 0x84, 0x18, 0xce, 0xa1, 0x99, 0xd3, 0x72, 0xf9, 0xea, 0xd6, 0xb3, 0x05, 0x19, 0x66, 0x7a, + 0xcb, 0x64, 0x7d, 0x0f, 0x65, 0xd5, 0x63, 0x68, 0x87, 0xde, 0x23, 0xc7, 0xf7, 0x0f, 0xbe, 0xc9, 0xf8, 0x85, 0xc3, + 0xb5, 0x87, 0x73, 0xe1, 0xbb, 0xac, 0x19, 0x99, 0x43, 0xe7, 0xd9, 0xc7, 0xf1, 0x1e, 0xc6, 0xc9, 0x97, 0x59, 0x28, + 0x6f, 0xbc, 0xa6, 0xff, 0xad, 0xd2, 0x9b, 0x1d, 0x0e, 0x39, 0x5d, 0xc1, 0x8a, 0x9b, 0x55, 0xa1, 0xe1, 0x67, 0x91, + 0x37, 0x8e, 0x78, 0x4d, 0xa2, 0xaa, 0xfb, 0xbc, 0xb7, 0x11, 0x4b, 0x3b, 0xc6, 0x01, 0xc0, 0x89, 0x5a, 0x35, 0xec, + 0x4b, 0xe3, 0x5a, 0x1d, 0xc4, 0x88, 0x94, 0xb0, 0x55, 0xe2, 0x48, 0x28, 0x7f, 0x03, 0x10, 0x16, 0x43, 0x71, 0xbc, + 0x35, 0xac, 0xf7, 0xb0, 0x1f, 0xba, 0x40, 0xd3, 0x9c, 0x52, 0xcd, 0x00, 0x20, 0x09, 0xf8, 0xa3, 0xa7, 0x9b, 0x86, + 0xca, 0x36, 0xcf, 0x43, 0xcb, 0xea, 0x0a, 0xee, 0xe9, 0xa9, 0x2b, 0x19, 0x18, 0x57, 0x75, 0xec, 0x6d, 0xef, 0x6e, + 0x8f, 0x56, 0x91, 0xef, 0x6d, 0x52, 0xd3, 0x2c, 0x80, 0x14, 0x8d, 0x4b, 0x5f, 0xe8, 0xe9, 0x04, 0x68, 0xbd, 0xb6, + 0x54, 0xb4, 0xdf, 0x47, 0x31, 0x6a, 0x5c, 0x28, 0xb0, 0x0a, 0x13, 0x14, 0x0e, 0x11, 0x46, 0x08, 0xfd, 0xb9, 0x0c, + 0xb7, 0xbe, 0x20, 0x83, 0x68, 0xb8, 0x16, 0x1d, 0x8a, 0xc8, 0xf1, 0xa2, 0x6d, 0xa9, 0xaa, 0x39, 0x69, 0xda, 0x12, + 0x78, 0x13, 0x19, 0xb0, 0x9d, 0x7f, 0xda, 0x10, 0xb9, 0x0a, 0x17, 0x30, 0x7c, 0x4f, 0x5c, 0x0b, 0xa2, 0x9b, 0xda, + 0xd4, 0xdb, 0xb0, 0x43, 0x74, 0x34, 0xc5, 0xa3, 0x43, 0xee, 0xb9, 0x7b, 0x6e, 0x8b, 0xf8, 0xe6, 0x0b, 0xe4, 0xae, + 0xe9, 0xec, 0xa5, 0x08, 0x83, 0xba, 0x65, 0x03, 0xc5, 0x3a, 0x76, 0x82, 0x02, 0x0c, 0xe0, 0xf2, 0x19, 0xe8, 0xd8, + 0x60, 0x50, 0x11, 0x7c, 0x52, 0xd8, 0x36, 0x0d, 0xf2, 0x47, 0xbc, 0x1b, 0x3a, 0xbc, 0xb6, 0xe4, 0x81, 0x78, 0x85, + 0x7d, 0xa1, 0x84, 0xbb, 0x17, 0x14, 0x74, 0x47, 0x79, 0xb9, 0x2a, 0x5c, 0x95, 0x06, 0xa0, 0xca, 0x9e, 0xe7, 0x5a, + 0x53, 0xd2, 0x02, 0x56, 0x4a, 0xea, 0xce, 0x6f, 0x82, 0xe3, 0x96, 0x4c, 0x85, 0x6f, 0xd5, 0x8d, 0x2a, 0x8f, 0x25, + 0x8a, 0x74, 0xec, 0xd9, 0xce, 0xc1, 0x1a, 0x00, 0x4f, 0x61, 0x7b, 0x71, 0x26, 0xe0, 0x73, 0xa7, 0x5d, 0xb6, 0xcc, + 0x25, 0x50, 0xd4, 0xf7, 0xe3, 0xbc, 0xec, 0xf9, 0x72, 0x77, 0xb4, 0xbd, 0x87, 0xde, 0x88, 0x8d, 0xf1, 0xfa, 0x3a, + 0x6a, 0xfa, 0xd5, 0x33, 0x5c, 0x59, 0x0a, 0x72, 0x4f, 0x53, 0x3d, 0xc2, 0xe8, 0x10, 0x98, 0xa6, 0xfc, 0x84, 0x8d, + 0xa7, 0xc3, 0xa1, 0x21, 0x83, 0x5e, 0x33, 0x31, 0x14, 0xd8, 0x57, 0xd0, 0x3a, 0x33, 0x71, 0x8d, 0x4f, 0xdb, 0x57, + 0xd0, 0xea, 0x16, 0x65, 0x72, 0x67, 0x60, 0xf8, 0x40, 0x4b, 0xa6, 0x60, 0xaa, 0xf0, 0x86, 0x48, 0x25, 0xfb, 0x73, + 0x69, 0x1d, 0xf6, 0xed, 0x42, 0xa1, 0x85, 0x26, 0x7e, 0x95, 0x21, 0x7e, 0xea, 0x3a, 0xf3, 0x1f, 0xd3, 0x3e, 0x35, + 0x88, 0x85, 0x23, 0x31, 0x88, 0xf8, 0xc5, 0xa9, 0xb2, 0x9d, 0x10, 0x2a, 0x36, 0x1e, 0xba, 0xd6, 0x8d, 0x23, 0xa9, + 0xc2, 0x50, 0x0a, 0x8d, 0xa7, 0x86, 0xfb, 0x5e, 0xe8, 0xf0, 0x75, 0x98, 0xc5, 0x6d, 0xd6, 0x48, 0x6a, 0x8c, 0x53, + 0x61, 0xe2, 0x54, 0xca, 0x55, 0x24, 0x30, 0x50, 0x9e, 0x2d, 0x0c, 0x02, 0x4c, 0x62, 0x92, 0xb1, 0xb5, 0x10, 0x26, + 0x8c, 0x9d, 0x2b, 0x4c, 0x53, 0x17, 0xa9, 0xdf, 0x0c, 0x4c, 0x16, 0x34, 0xe4, 0xf7, 0x68, 0xb4, 0xa6, 0x6a, 0x0a, + 0x30, 0x8c, 0xa3, 0x54, 0xe3, 0x3f, 0x22, 0xd4, 0x66, 0x18, 0x00, 0xd8, 0xe6, 0x9d, 0xcc, 0x44, 0xf5, 0x4a, 0x20, + 0x04, 0x9a, 0xb3, 0x9f, 0x8a, 0xab, 0xbd, 0x59, 0x30, 0x8a, 0x76, 0x7b, 0xe5, 0xf3, 0x81, 0x13, 0xca, 0x53, 0x75, + 0x81, 0x7a, 0x21, 0x8b, 0xd7, 0x32, 0xe5, 0xad, 0x10, 0x99, 0x07, 0x92, 0xbd, 0xcf, 0x47, 0x70, 0x5e, 0xa1, 0x53, + 0xb9, 0xd9, 0x26, 0xca, 0x2c, 0x49, 0x32, 0x16, 0x18, 0x9b, 0x97, 0x60, 0x26, 0x35, 0x33, 0x86, 0x5f, 0x43, 0x9c, + 0xb1, 0xbd, 0x93, 0x70, 0x7b, 0x37, 0x0f, 0x0c, 0x51, 0xca, 0x45, 0x4b, 0x34, 0x6c, 0xed, 0x78, 0x3d, 0xb9, 0x26, + 0xdc, 0x87, 0x8d, 0x58, 0x93, 0x31, 0xc6, 0xb5, 0xb9, 0x91, 0xf5, 0xa3, 0x05, 0x1e, 0x8c, 0x29, 0xeb, 0x4f, 0x20, + 0xd3, 0x4a, 0xca, 0x3a, 0x5f, 0x18, 0x31, 0x93, 0x4a, 0xf4, 0x6e, 0xdf, 0xf8, 0xac, 0xee, 0x22, 0xea, 0xb7, 0xf6, + 0x7b, 0x52, 0x0f, 0x1b, 0xff, 0x41, 0x61, 0x0d, 0x2a, 0x23, 0x2e, 0x23, 0xca, 0x33, 0x07, 0xba, 0x69, 0x52, 0xc4, + 0xe9, 0xd9, 0x2a, 0x2e, 0x4a, 0x9e, 0x42, 0xa5, 0x9a, 0xba, 0x45, 0xbd, 0x09, 0xd8, 0x1b, 0x22, 0x49, 0xb2, 0x96, + 0xc6, 0x56, 0xec, 0xd2, 0x20, 0x3d, 0x77, 0x46, 0x5c, 0x7a, 0x51, 0xa1, 0x21, 0x2d, 0xf5, 0xce, 0x42, 0x25, 0xf3, + 0x57, 0xfc, 0x67, 0x50, 0x2b, 0xd0, 0xd1, 0x26, 0xc5, 0x78, 0x0a, 0x8c, 0xf8, 0x7e, 0x30, 0xab, 0x7b, 0x88, 0x8b, + 0x26, 0x28, 0xf5, 0x9e, 0xd8, 0xf1, 0x4b, 0x93, 0x87, 0x77, 0x21, 0xe7, 0x0c, 0x3e, 0xbd, 0x9f, 0x25, 0x6a, 0xad, + 0x23, 0x31, 0x52, 0x33, 0x80, 0xa6, 0x83, 0x32, 0xe7, 0xb1, 0x08, 0x66, 0x3d, 0x93, 0x18, 0xf5, 0xb8, 0xfe, 0x05, + 0x1a, 0x6a, 0xbf, 0x59, 0x59, 0x9e, 0x55, 0x9b, 0xaf, 0xe1, 0xc0, 0xa6, 0xb6, 0x82, 0x1e, 0xaf, 0x2b, 0x79, 0x79, + 0xa9, 0xba, 0xed, 0x17, 0x62, 0xe4, 0x74, 0x8d, 0x6b, 0xe9, 0xbc, 0x5a, 0xb0, 0x5e, 0x77, 0xba, 0x59, 0xdc, 0xcd, + 0x32, 0x1a, 0x08, 0x6b, 0x7b, 0x9f, 0x68, 0xfe, 0xac, 0xd9, 0x76, 0x1f, 0x6f, 0x41, 0xcc, 0x02, 0x80, 0x48, 0x0f, + 0xa2, 0x60, 0x99, 0xa5, 0x3c, 0xa0, 0xf2, 0x2e, 0x8e, 0xb2, 0x50, 0x7a, 0x39, 0xcb, 0xf8, 0x69, 0xd3, 0x58, 0xeb, + 0xac, 0x50, 0x86, 0xd6, 0x46, 0x77, 0xba, 0xca, 0x10, 0xdb, 0x4f, 0xe2, 0x6c, 0x01, 0xee, 0x8f, 0x19, 0x0a, 0x0d, + 0x9d, 0x65, 0xa4, 0x89, 0x86, 0xef, 0xba, 0x63, 0x90, 0x51, 0x9c, 0xac, 0xf3, 0x4a, 0xba, 0xd5, 0x67, 0x6d, 0x24, + 0xcc, 0x3d, 0x44, 0xbf, 0x8a, 0xc1, 0xa3, 0xdc, 0xe7, 0xb5, 0xd1, 0xc9, 0xb4, 0x8c, 0xb4, 0x3b, 0x3f, 0xa9, 0x97, + 0x59, 0xaa, 0x75, 0xd8, 0x3e, 0xc3, 0xde, 0x1a, 0x93, 0xde, 0x84, 0xd4, 0x30, 0x12, 0x5f, 0xce, 0xa8, 0x11, 0x02, + 0xda, 0x72, 0xfc, 0x3d, 0x3e, 0xc3, 0xd0, 0x14, 0x58, 0xaa, 0xb8, 0x85, 0xdd, 0xf0, 0x35, 0x9f, 0xac, 0x5a, 0x00, + 0x82, 0x59, 0xf9, 0x7a, 0x17, 0xaf, 0x84, 0xfa, 0x4c, 0x9b, 0x01, 0x20, 0x0b, 0x4a, 0xb9, 0xe3, 0xa7, 0x54, 0x3a, + 0x58, 0xa2, 0x68, 0x7b, 0x39, 0x7d, 0xa3, 0x63, 0xe3, 0xfb, 0xf4, 0x5c, 0xc0, 0x76, 0x21, 0xbf, 0x75, 0xa7, 0x5e, + 0xa2, 0x22, 0xb5, 0x6d, 0xd6, 0x3d, 0x7c, 0xb9, 0x41, 0x93, 0x30, 0x82, 0x32, 0x65, 0x0a, 0x60, 0x70, 0x53, 0x8d, + 0x82, 0x49, 0xab, 0x91, 0xb0, 0xa5, 0x9e, 0x64, 0xb9, 0xe9, 0x83, 0x53, 0xdd, 0x21, 0xe8, 0xb9, 0x55, 0xce, 0x17, + 0x2d, 0xfb, 0xb5, 0x82, 0xa3, 0x93, 0xab, 0x21, 0x6a, 0xe6, 0xbd, 0xb6, 0x23, 0x43, 0xca, 0x65, 0x18, 0x08, 0xa6, + 0x1c, 0xf3, 0xf4, 0xd8, 0x7a, 0x46, 0x44, 0xf7, 0x9c, 0x7d, 0xa6, 0x5b, 0x75, 0x25, 0x01, 0xd1, 0xf1, 0xbb, 0xc7, + 0xaf, 0xae, 0xe2, 0x4b, 0x83, 0xa2, 0xd4, 0xb0, 0x88, 0x51, 0xa6, 0x7d, 0x95, 0x84, 0xc1, 0xfb, 0xe5, 0xfd, 0x4f, + 0x2a, 0x4b, 0xed, 0xf7, 0x60, 0x6b, 0x45, 0x55, 0xbf, 0x94, 0xbc, 0x68, 0x0a, 0xb0, 0xee, 0xb2, 0x44, 0x81, 0xdc, + 0xef, 0x6d, 0x9a, 0xf9, 0x26, 0x6a, 0xdc, 0x6c, 0x58, 0x6f, 0x5c, 0xb7, 0x4b, 0x6d, 0xc9, 0x8e, 0xac, 0x44, 0xce, + 0x2c, 0x06, 0x33, 0x7e, 0x54, 0x18, 0x94, 0x86, 0x2d, 0xaa, 0x52, 0xf1, 0x7b, 0x23, 0x82, 0x53, 0xc7, 0xaa, 0xc2, + 0x98, 0x06, 0xcc, 0xb6, 0xa2, 0xd6, 0xa0, 0x0e, 0x4a, 0x69, 0x6b, 0x02, 0xb2, 0xfd, 0x8b, 0x15, 0xd4, 0xfc, 0xfe, + 0xb7, 0x31, 0xe4, 0x6b, 0x4a, 0x41, 0x25, 0x01, 0x3b, 0x83, 0x46, 0x4f, 0x95, 0x30, 0x90, 0x82, 0xe0, 0x09, 0x50, + 0xbe, 0x88, 0x1a, 0xab, 0xfd, 0xbe, 0x3a, 0x35, 0x46, 0x5b, 0x40, 0x68, 0x21, 0x3d, 0xba, 0xec, 0xe3, 0xb6, 0xd6, + 0x81, 0xc4, 0x83, 0x13, 0x6c, 0xe7, 0xea, 0x1a, 0x8d, 0x84, 0xe6, 0xf7, 0x8d, 0x06, 0xbc, 0xa6, 0x15, 0x28, 0xd4, + 0x73, 0x1c, 0x0d, 0x9d, 0x1d, 0x52, 0x10, 0xb1, 0x41, 0x0b, 0xfb, 0xee, 0xf8, 0xd0, 0xec, 0xeb, 0x79, 0xb2, 0x20, + 0x35, 0x95, 0xee, 0x73, 0xb7, 0x84, 0xac, 0x55, 0x87, 0xb2, 0xf2, 0x00, 0xc7, 0x0b, 0x25, 0xf3, 0x77, 0x98, 0xd4, + 0x28, 0x8d, 0x09, 0x8d, 0x11, 0x0b, 0x58, 0x12, 0xb4, 0xd7, 0x03, 0xf5, 0xcb, 0x20, 0x54, 0x38, 0xd3, 0x13, 0x89, + 0x4f, 0x29, 0x57, 0x9f, 0x16, 0xa4, 0x9e, 0x16, 0xcc, 0x81, 0x5e, 0xfa, 0x56, 0x7e, 0x65, 0xe3, 0xa3, 0xfd, 0xbd, + 0x6b, 0x2e, 0xac, 0x63, 0x88, 0x8b, 0x2d, 0xfc, 0xe6, 0xd4, 0x14, 0x80, 0x0d, 0x4f, 0x75, 0x59, 0xbe, 0x51, 0x13, + 0x99, 0xc5, 0x21, 0x89, 0x40, 0xb2, 0xdd, 0xdc, 0xdc, 0x46, 0xb0, 0xed, 0x2d, 0xd4, 0x86, 0xfa, 0xcb, 0xdb, 0xee, + 0x77, 0x0c, 0x2f, 0xf7, 0xe4, 0xde, 0x4d, 0x1b, 0xca, 0x97, 0x77, 0xaf, 0x92, 0xff, 0xab, 0x4a, 0xee, 0xb6, 0xca, + 0xac, 0xdb, 0xe2, 0xfd, 0xae, 0xe3, 0x96, 0x63, 0x34, 0x08, 0xac, 0x29, 0x30, 0x90, 0x9e, 0x34, 0xa6, 0x89, 0x8e, + 0xae, 0xcc, 0x98, 0xc1, 0xa3, 0x0b, 0xd0, 0x1c, 0xa6, 0xf3, 0x3c, 0x06, 0xe0, 0x00, 0xff, 0xc8, 0x23, 0xd4, 0x3f, + 0x9d, 0xe7, 0xc1, 0x59, 0x30, 0x28, 0x07, 0x81, 0xfe, 0xc4, 0x35, 0x27, 0x58, 0x80, 0xce, 0x2d, 0x66, 0x10, 0x77, + 0xd2, 0x9a, 0x39, 0xc4, 0xc7, 0xc9, 0x74, 0x30, 0x88, 0xc9, 0x16, 0x40, 0xfa, 0xe2, 0x85, 0x75, 0x0e, 0x2a, 0xf4, + 0x82, 0x6c, 0xd5, 0x5d, 0x34, 0x2b, 0xf6, 0xaa, 0x9d, 0xe6, 0xfd, 0x7e, 0x3e, 0x2f, 0x07, 0x41, 0xa3, 0xc2, 0xc2, + 0x78, 0xff, 0xd1, 0xe6, 0x97, 0x46, 0x27, 0x4d, 0x30, 0x62, 0xed, 0x29, 0xaa, 0x57, 0x3c, 0xcd, 0x68, 0xe3, 0x76, + 0xac, 0x94, 0x2f, 0x20, 0x8a, 0x07, 0x86, 0xac, 0x95, 0x77, 0xef, 0xe0, 0x75, 0xb9, 0xf1, 0xe6, 0x88, 0x02, 0xec, + 0xa6, 0x30, 0x4e, 0x6a, 0x2e, 0xba, 0xa8, 0x89, 0x67, 0xb0, 0xd3, 0xd5, 0x5b, 0x89, 0x56, 0xe3, 0xbd, 0x78, 0xdf, + 0x6c, 0xfc, 0x8d, 0x3c, 0xd0, 0x65, 0x1e, 0x5c, 0x00, 0xe2, 0xec, 0x41, 0x5c, 0x1d, 0x60, 0xa9, 0x07, 0xc1, 0xc0, + 0x22, 0x87, 0xb4, 0xab, 0xd5, 0x43, 0x11, 0xa9, 0xf3, 0x18, 0x0c, 0x98, 0x4c, 0x43, 0x6a, 0x32, 0xed, 0xc5, 0x0a, + 0xd2, 0xc6, 0x5a, 0x0b, 0x68, 0xc3, 0x61, 0xb1, 0x67, 0x37, 0xec, 0x4e, 0xb7, 0x0e, 0x85, 0x12, 0x06, 0xb2, 0xae, + 0x9b, 0x87, 0x5a, 0xc3, 0x13, 0x41, 0x0f, 0xaa, 0xd1, 0x7e, 0x7a, 0x28, 0x4f, 0xda, 0x63, 0x01, 0x2e, 0x7a, 0xf8, + 0xf2, 0xb9, 0xc0, 0x8b, 0xf6, 0x1e, 0xf2, 0x9c, 0xf9, 0x54, 0xf9, 0x20, 0x36, 0xdc, 0x32, 0x7c, 0x68, 0x1f, 0xdf, + 0x0a, 0x64, 0x52, 0x77, 0x34, 0xb5, 0xb5, 0x3b, 0x1a, 0xc7, 0x04, 0xfa, 0x4d, 0x39, 0x4a, 0x99, 0x98, 0x5a, 0x96, + 0xec, 0xa4, 0x97, 0x2b, 0x6f, 0xa8, 0x94, 0x9d, 0x2c, 0xdb, 0x9c, 0x5f, 0xda, 0x48, 0xe8, 0xf7, 0xb5, 0x3b, 0x10, + 0xbe, 0x51, 0xeb, 0x0d, 0x79, 0xd9, 0x10, 0xb1, 0x1c, 0x62, 0x06, 0x8e, 0x17, 0x52, 0xb9, 0x76, 0x17, 0x4d, 0x55, + 0xdd, 0xde, 0x56, 0x2e, 0x68, 0x89, 0xb7, 0x52, 0x60, 0x15, 0xa9, 0xd3, 0xeb, 0xa9, 0xc4, 0xbb, 0x3e, 0x8a, 0xed, + 0x47, 0xc0, 0x36, 0x36, 0x8e, 0xc6, 0xc6, 0x2d, 0x62, 0x8b, 0xaf, 0xa2, 0x8a, 0x16, 0x1c, 0x20, 0xb8, 0xdb, 0x92, + 0x5a, 0x9a, 0x39, 0xc4, 0x7d, 0xc5, 0x03, 0xb4, 0xef, 0xe2, 0x70, 0x26, 0x15, 0x60, 0x5b, 0xd7, 0x3a, 0x67, 0xb5, + 0x1c, 0xb0, 0x99, 0xe8, 0xf9, 0xa7, 0x55, 0x23, 0x11, 0xc3, 0x2a, 0x1b, 0x29, 0x2b, 0xb4, 0x7b, 0xa5, 0x4b, 0xb8, + 0xf8, 0x02, 0xbc, 0x6c, 0xdf, 0xad, 0xec, 0x3e, 0x5b, 0x62, 0xff, 0x30, 0xaf, 0x9a, 0xe0, 0x91, 0xd7, 0x78, 0x7b, + 0x0f, 0x13, 0x5f, 0x2b, 0x85, 0xf0, 0x2a, 0xa5, 0xa1, 0x04, 0x60, 0x90, 0x04, 0x35, 0x5c, 0x69, 0xdb, 0x0c, 0x52, + 0x19, 0xc3, 0xee, 0x57, 0x6f, 0xf5, 0x7f, 0x5a, 0x85, 0x8b, 0x4a, 0x16, 0x63, 0x12, 0xe8, 0x9c, 0x6a, 0xb9, 0x09, + 0x2c, 0x78, 0xb6, 0x4f, 0x8e, 0x40, 0x61, 0x27, 0x80, 0x1b, 0x4a, 0xd8, 0x5f, 0x78, 0x1b, 0xca, 0xd9, 0x67, 0x2b, + 0x79, 0x72, 0xfb, 0x92, 0x0a, 0x9a, 0x90, 0xa9, 0xb0, 0xfb, 0xb7, 0xb5, 0x61, 0x9f, 0x85, 0x72, 0x24, 0x05, 0x2e, + 0x0e, 0x3a, 0x07, 0xb0, 0x3f, 0xc8, 0x65, 0x6c, 0x3e, 0x93, 0x7e, 0x5f, 0xbd, 0x7f, 0x9a, 0x67, 0xc9, 0xa7, 0xbd, + 0xf7, 0x86, 0xa7, 0x59, 0x32, 0xa0, 0x12, 0x31, 0xb5, 0xae, 0x8a, 0xe1, 0x52, 0xbb, 0x18, 0x37, 0x48, 0x46, 0x7c, + 0x27, 0x75, 0x88, 0x11, 0xe3, 0x8b, 0xec, 0x91, 0x94, 0x9c, 0x2e, 0xeb, 0xce, 0x9e, 0x6b, 0xd1, 0x0c, 0x1a, 0xc3, + 0xed, 0x79, 0x2f, 0xe9, 0x15, 0xa0, 0x02, 0x44, 0xf7, 0x2c, 0x70, 0x0d, 0x6f, 0x2e, 0x89, 0xc6, 0x96, 0x9e, 0xb6, + 0x44, 0x03, 0x77, 0xca, 0x84, 0xa4, 0xda, 0x38, 0xc0, 0x22, 0xd6, 0xf5, 0xa7, 0xb0, 0x00, 0xa0, 0x56, 0x83, 0xf4, + 0x4a, 0x5f, 0x10, 0xaa, 0x92, 0x10, 0x8c, 0x4e, 0x24, 0xbc, 0x0c, 0x68, 0x9c, 0x99, 0x44, 0x0b, 0x1b, 0x1c, 0xd0, + 0x57, 0x95, 0x49, 0x34, 0x36, 0xe4, 0x01, 0xe5, 0x36, 0x0d, 0x60, 0xf0, 0x41, 0x92, 0x44, 0x7f, 0x5a, 0x9a, 0x24, + 0x10, 0x94, 0xa0, 0x7c, 0x83, 0xfe, 0x5e, 0x7a, 0x3e, 0x96, 0xff, 0xf0, 0x0e, 0xa5, 0x97, 0x61, 0x01, 0x32, 0x45, + 0x5d, 0x31, 0xcd, 0xd8, 0x49, 0xd6, 0x6d, 0x4c, 0xe2, 0x79, 0xda, 0x5d, 0x17, 0xca, 0xa5, 0x0b, 0xfc, 0xca, 0x32, + 0xc4, 0xb1, 0x7e, 0x1a, 0xaf, 0xd8, 0x69, 0xc8, 0x35, 0x5e, 0xfa, 0xd3, 0x78, 0x85, 0x33, 0x44, 0xab, 0x56, 0x02, + 0x51, 0xfe, 0xab, 0x36, 0x70, 0x88, 0xfb, 0x04, 0x83, 0x5c, 0x54, 0xde, 0x03, 0x81, 0xbc, 0xad, 0x20, 0x22, 0xcd, + 0xec, 0x3a, 0x8c, 0x48, 0xb5, 0x97, 0x64, 0xbe, 0xfc, 0x87, 0xcc, 0x84, 0xf7, 0x0d, 0x3c, 0x36, 0x9b, 0x65, 0x53, + 0xcc, 0x17, 0x2a, 0x98, 0x83, 0xfb, 0x44, 0xc5, 0xa5, 0xa8, 0xfc, 0x27, 0xec, 0x82, 0x17, 0xe3, 0xc1, 0xeb, 0x35, + 0x02, 0xec, 0x57, 0xfe, 0x93, 0x37, 0x66, 0x3f, 0x58, 0x37, 0xbe, 0xcc, 0x44, 0x7c, 0xe0, 0xa3, 0x5b, 0xca, 0x47, + 0x1b, 0x2f, 0xd3, 0xaf, 0x0d, 0x28, 0x91, 0x51, 0x59, 0xf1, 0xd5, 0x8a, 0xa7, 0xb3, 0x9b, 0x24, 0xca, 0x46, 0x15, + 0x17, 0x30, 0xbd, 0xe0, 0x78, 0x97, 0xac, 0xcf, 0xb3, 0xe4, 0x15, 0xc4, 0x1e, 0x58, 0x49, 0x85, 0xc5, 0x0f, 0xcb, + 0x4c, 0x2d, 0x66, 0x21, 0x2b, 0x29, 0x78, 0x30, 0xfb, 0x94, 0x44, 0x3f, 0x2c, 0x3d, 0x10, 0x39, 0x33, 0x65, 0xdb, + 0xda, 0x11, 0x6a, 0xe3, 0xeb, 0x48, 0xb7, 0xda, 0x02, 0x00, 0xee, 0xd9, 0x22, 0x8d, 0x24, 0x13, 0xc3, 0x49, 0xcd, + 0xb8, 0x49, 0x2f, 0x30, 0x35, 0xae, 0x59, 0x45, 0x13, 0x67, 0x21, 0x03, 0x7a, 0x7f, 0x9a, 0xeb, 0xe7, 0x0c, 0xee, + 0x3f, 0x68, 0x0d, 0x5c, 0x1e, 0x17, 0xfd, 0xbe, 0x3c, 0x2e, 0x76, 0xbb, 0xf2, 0x24, 0xee, 0xf7, 0xe5, 0x49, 0x6c, + 0xf8, 0x07, 0xa5, 0xd8, 0x36, 0xe6, 0x06, 0x09, 0xcd, 0x25, 0x44, 0x2d, 0x1a, 0xc1, 0x1f, 0x9a, 0xe5, 0x5c, 0x44, + 0xf9, 0x71, 0xd2, 0xef, 0xf7, 0x96, 0x33, 0x31, 0xc8, 0x87, 0x49, 0x94, 0x0f, 0x13, 0xcf, 0x09, 0xf1, 0xa5, 0xe7, + 0x84, 0xa8, 0x68, 0xe0, 0x0a, 0xce, 0x0c, 0x40, 0x14, 0xf0, 0xe9, 0x1f, 0xd5, 0xb5, 0x14, 0xba, 0x96, 0x58, 0xd5, + 0x92, 0xe8, 0x0a, 0x6a, 0x76, 0x53, 0x84, 0x25, 0x96, 0x42, 0x97, 0xec, 0xd7, 0x25, 0xf0, 0x44, 0x39, 0xaf, 0xb6, + 0xc0, 0xc0, 0x46, 0x78, 0xe7, 0x30, 0xe1, 0x24, 0xd6, 0x35, 0xa0, 0x9d, 0x6e, 0x6b, 0x7a, 0x41, 0x57, 0xf4, 0x12, + 0xf9, 0xd9, 0x0b, 0x30, 0x58, 0x3a, 0x66, 0xf9, 0x74, 0x30, 0xb8, 0x20, 0x2b, 0x56, 0xce, 0xc3, 0x78, 0x10, 0xae, + 0x67, 0xf9, 0xf0, 0x22, 0xba, 0x20, 0xe4, 0x9b, 0x62, 0x41, 0x7b, 0xab, 0x51, 0xf9, 0x29, 0x83, 0xf0, 0x7e, 0xe9, + 0x2c, 0xcc, 0x4c, 0x9c, 0x8f, 0xd5, 0xe8, 0x96, 0xae, 0x20, 0x7e, 0x0d, 0xdc, 0x48, 0x48, 0x04, 0x1d, 0xb9, 0xa4, + 0x2b, 0xba, 0xa6, 0xd2, 0xcc, 0x30, 0x46, 0xeb, 0xb6, 0xc7, 0x49, 0x02, 0x8e, 0xc9, 0xae, 0xf8, 0x68, 0xac, 0x0a, + 0xef, 0xfa, 0x8e, 0xd0, 0x5e, 0x2f, 0x71, 0x83, 0xf4, 0x4b, 0x7b, 0x90, 0x80, 0x11, 0x19, 0xa9, 0x81, 0x32, 0x23, + 0x23, 0xa9, 0x99, 0x54, 0x1c, 0x92, 0xd8, 0x1f, 0x12, 0x35, 0x0e, 0x89, 0x3f, 0x0e, 0xb9, 0x1e, 0x07, 0xe4, 0xee, + 0x97, 0x6c, 0x4c, 0x53, 0x36, 0xa6, 0x6b, 0x35, 0x2a, 0xf4, 0x8a, 0x9e, 0x6b, 0xea, 0x78, 0xc6, 0x9e, 0xc2, 0x81, + 0x3d, 0x08, 0xf3, 0x59, 0x3c, 0x7c, 0x1a, 0x3d, 0x25, 0xe4, 0x1b, 0x49, 0xaf, 0xd5, 0xa5, 0x0c, 0x02, 0x21, 0x5e, + 0x81, 0x73, 0xa9, 0x0b, 0x75, 0x72, 0x65, 0x76, 0x1c, 0x3e, 0x5d, 0x36, 0x9e, 0xce, 0x21, 0xa2, 0x0f, 0x5a, 0xa9, + 0xf4, 0xfb, 0xe1, 0x05, 0x2b, 0xe7, 0x67, 0xe1, 0x98, 0x00, 0x0e, 0x8f, 0x1e, 0xce, 0x8b, 0xd1, 0x2d, 0xbd, 0x18, + 0x6d, 0x08, 0x58, 0x78, 0x8d, 0xa7, 0xeb, 0x63, 0x16, 0x4f, 0x07, 0x83, 0x35, 0x52, 0x75, 0x95, 0x7b, 0x4d, 0x16, + 0xf4, 0x02, 0x27, 0x82, 0x00, 0x43, 0x9f, 0x89, 0xb5, 0xa1, 0xe1, 0x4f, 0x19, 0x7c, 0xbc, 0x61, 0x17, 0xa3, 0x0d, + 0xbd, 0x65, 0x4f, 0x77, 0xe3, 0x29, 0x30, 0x53, 0xab, 0x59, 0xb8, 0x39, 0xbe, 0x9c, 0x5d, 0xb2, 0x4d, 0xb4, 0x39, + 0x81, 0x86, 0x5e, 0xb1, 0x0d, 0x02, 0x2e, 0xa5, 0x0f, 0x97, 0x83, 0xa7, 0xe4, 0x70, 0x30, 0x48, 0x49, 0x14, 0x5e, + 0x87, 0x5e, 0x2b, 0x9f, 0xd2, 0x0d, 0xa1, 0x2b, 0x76, 0x8b, 0xa3, 0x71, 0xc9, 0xf0, 0x83, 0x73, 0xb6, 0xa9, 0xaf, + 0x43, 0x6f, 0x37, 0xe7, 0xa2, 0x13, 0xc4, 0x08, 0x7d, 0x0d, 0x1c, 0xcd, 0x72, 0x61, 0x26, 0xe0, 0xc9, 0x5c, 0x64, + 0xb4, 0x28, 0x34, 0x03, 0x71, 0x56, 0x02, 0x62, 0x49, 0xd4, 0xfd, 0x66, 0xa3, 0x33, 0x58, 0xce, 0xfd, 0x7e, 0xaf, + 0x32, 0xf4, 0x00, 0x91, 0x33, 0x3b, 0xe9, 0x41, 0xcf, 0xa7, 0x07, 0xf8, 0x89, 0x5e, 0x35, 0x88, 0x93, 0xf9, 0xcb, + 0x32, 0x7a, 0xe9, 0xd1, 0x87, 0xdf, 0xba, 0x29, 0x8f, 0xcc, 0xff, 0x73, 0xca, 0x53, 0xe4, 0xd1, 0xeb, 0xca, 0x03, + 0x62, 0xf3, 0xd6, 0xa4, 0xd2, 0x48, 0x54, 0xa3, 0xb3, 0x55, 0x0c, 0xda, 0x48, 0xd4, 0x36, 0xe8, 0x27, 0xb4, 0xb0, + 0x82, 0x08, 0x39, 0x47, 0xcf, 0xc0, 0x20, 0x15, 0x42, 0xe5, 0xa8, 0x45, 0x89, 0x86, 0x20, 0xb9, 0x2c, 0xb9, 0x0a, + 0x9f, 0x43, 0xa8, 0x3a, 0x7d, 0x9c, 0x89, 0xb0, 0xa1, 0xc7, 0xa1, 0x0f, 0x00, 0xff, 0xd7, 0x1e, 0xb9, 0x28, 0xf9, + 0x25, 0x9e, 0xcd, 0x6d, 0x82, 0x51, 0xb0, 0x5c, 0x34, 0x43, 0xdb, 0x20, 0xf6, 0x63, 0x49, 0xb0, 0x1e, 0x49, 0xe3, + 0x51, 0x69, 0x8e, 0x08, 0x3f, 0x8a, 0x8f, 0xa2, 0xa7, 0xb1, 0x21, 0x91, 0x1c, 0x49, 0x24, 0x1f, 0x00, 0xe1, 0x24, + 0xe8, 0x2f, 0xee, 0x9a, 0xec, 0x5a, 0xa8, 0xbd, 0x7e, 0x0f, 0xfe, 0xb5, 0x64, 0x5a, 0x76, 0xaf, 0x7a, 0xec, 0x2b, + 0x82, 0x3c, 0x98, 0x00, 0xaf, 0x0f, 0xff, 0x5a, 0xe2, 0x0c, 0x5a, 0xcf, 0x17, 0xd5, 0x99, 0x99, 0x37, 0xb8, 0x91, + 0xd7, 0x65, 0xed, 0xba, 0x7c, 0xc1, 0x0f, 0xf8, 0x6d, 0xc5, 0x45, 0x5a, 0x1e, 0xfc, 0x5c, 0xb5, 0xf1, 0x9c, 0xca, + 0xf5, 0xca, 0xc5, 0x59, 0x51, 0xc6, 0xa9, 0x9e, 0xd4, 0xc5, 0x58, 0xc3, 0x36, 0xfc, 0x1e, 0x51, 0x57, 0xd2, 0x72, + 0xf4, 0x94, 0x72, 0xd5, 0x4c, 0xb9, 0x58, 0xe7, 0xf9, 0x4f, 0x7b, 0xa9, 0x38, 0xc5, 0xcd, 0x14, 0xa4, 0x4a, 0x2d, + 0x17, 0x50, 0x3d, 0x47, 0x2d, 0x77, 0x4b, 0xb3, 0x03, 0x9c, 0xdb, 0xa6, 0xfa, 0x58, 0x99, 0x5d, 0x78, 0xc9, 0x8d, + 0xfb, 0x93, 0x29, 0xc3, 0x82, 0x51, 0x68, 0xb3, 0xea, 0x4a, 0xdb, 0x17, 0x5a, 0xa7, 0x61, 0xb8, 0xf2, 0xe3, 0x05, + 0xa4, 0x0b, 0x18, 0xc7, 0x8b, 0x92, 0x89, 0x71, 0x7b, 0xf4, 0x56, 0x10, 0x5f, 0xb3, 0x15, 0x48, 0xbf, 0xdf, 0x13, + 0xde, 0xae, 0xeb, 0x68, 0xbb, 0x27, 0x4e, 0x19, 0x95, 0xab, 0x58, 0xfc, 0x18, 0xaf, 0x0c, 0x64, 0xb2, 0x3a, 0x1e, + 0x1b, 0x63, 0x3a, 0xfd, 0x39, 0x09, 0xfd, 0x42, 0x28, 0xf8, 0xac, 0x97, 0x56, 0x9e, 0xdc, 0x1e, 0x96, 0x71, 0x8d, + 0x5e, 0x89, 0x2b, 0xdd, 0x37, 0x23, 0x85, 0xd4, 0x23, 0x5f, 0x35, 0x05, 0xf4, 0x66, 0xec, 0x9b, 0xa9, 0x30, 0x6f, + 0x77, 0x8c, 0xb9, 0x42, 0xb0, 0x52, 0x65, 0xb7, 0xef, 0xd4, 0x98, 0x8a, 0x19, 0x4c, 0xb1, 0xed, 0x2c, 0x26, 0xdd, + 0xca, 0x3f, 0xed, 0xdc, 0xaf, 0xf3, 0x0e, 0x77, 0x45, 0xfd, 0x16, 0xb8, 0xd0, 0xac, 0x28, 0xab, 0xb6, 0x6c, 0xd8, + 0x36, 0xde, 0xc8, 0x42, 0xb1, 0x01, 0x96, 0x3d, 0xf7, 0x2d, 0x3c, 0x40, 0xdc, 0x84, 0x7b, 0x76, 0x51, 0xc3, 0x8d, + 0xe1, 0xeb, 0x4a, 0xf2, 0x5d, 0x69, 0xcc, 0xa5, 0x4f, 0x95, 0x26, 0x86, 0x93, 0xc5, 0x88, 0x8b, 0x74, 0x51, 0x67, + 0x76, 0x2d, 0x7c, 0xc1, 0xcb, 0x70, 0xce, 0x17, 0x46, 0x37, 0xa5, 0x4b, 0x2f, 0x98, 0x0e, 0x99, 0x42, 0xb7, 0x2b, + 0x8d, 0x95, 0x12, 0x71, 0x6b, 0x96, 0x09, 0x94, 0xa5, 0xac, 0x95, 0xf0, 0xa6, 0x68, 0xd9, 0x4a, 0x1a, 0x79, 0xcf, + 0x1c, 0xdc, 0xc7, 0x7e, 0x43, 0x4c, 0x64, 0x13, 0x98, 0x14, 0x0d, 0x1d, 0xd0, 0xae, 0xba, 0xf0, 0xcd, 0xa8, 0x07, + 0x83, 0xdc, 0x92, 0x44, 0xac, 0x20, 0xc5, 0x0a, 0xd6, 0x35, 0x2b, 0xe6, 0xf9, 0x82, 0x5e, 0x30, 0x39, 0x4f, 0x17, + 0x74, 0xc5, 0xe4, 0x7c, 0x8d, 0x37, 0xa1, 0x0b, 0x38, 0x21, 0xc9, 0x36, 0x56, 0x0a, 0xd8, 0x0b, 0xbc, 0xbc, 0xe1, + 0x99, 0xaa, 0x69, 0xd9, 0xa5, 0xe2, 0x00, 0xe3, 0xf3, 0x32, 0x0c, 0xcb, 0xe1, 0x05, 0x58, 0x4b, 0x1c, 0x86, 0xab, + 0x39, 0x5f, 0xa8, 0xdf, 0x10, 0x75, 0x3e, 0x09, 0x15, 0xbb, 0x60, 0xf7, 0x02, 0x99, 0x5e, 0xcd, 0xf9, 0x42, 0x8d, + 0x84, 0x2e, 0xf8, 0xca, 0x1a, 0x9b, 0xc4, 0x9e, 0xa0, 0x65, 0x16, 0xcf, 0xc7, 0x8b, 0x28, 0xae, 0x61, 0x19, 0x7e, + 0x50, 0x33, 0xd3, 0x92, 0xff, 0xe4, 0x6a, 0x43, 0x13, 0x7d, 0x83, 0x55, 0xe4, 0x0f, 0x8f, 0x8f, 0x2e, 0x81, 0x8c, + 0x9d, 0x5d, 0xc9, 0xcc, 0x87, 0xbe, 0x8f, 0x0c, 0xee, 0xb9, 0x29, 0x67, 0x5c, 0x05, 0x89, 0x32, 0x70, 0xf7, 0x6a, + 0x96, 0x8c, 0xb5, 0x08, 0xdf, 0x3f, 0x2a, 0x8a, 0x3e, 0x93, 0xa6, 0x01, 0xdd, 0x47, 0x82, 0x39, 0xd0, 0x7b, 0x85, + 0x0e, 0x97, 0xd5, 0x36, 0x13, 0xf0, 0x17, 0x09, 0xf2, 0x5b, 0xa1, 0x57, 0x35, 0x06, 0x55, 0xb4, 0x8b, 0x58, 0xfa, + 0xf7, 0x11, 0x3f, 0xca, 0xe6, 0x3f, 0xcd, 0x3d, 0x5e, 0x49, 0x18, 0xfc, 0x90, 0x9a, 0x4d, 0x32, 0x6f, 0xaf, 0xd8, + 0x77, 0xd0, 0x51, 0x8f, 0x5a, 0xe3, 0x7d, 0xf5, 0x82, 0x53, 0x88, 0x51, 0x42, 0xd1, 0x49, 0x30, 0x80, 0xdb, 0x25, + 0xa4, 0xb8, 0x1b, 0xec, 0xb6, 0x79, 0xcd, 0x8b, 0x82, 0xf3, 0x75, 0x55, 0x05, 0x7e, 0x40, 0xc3, 0xf9, 0x62, 0x3f, + 0x84, 0xe1, 0x98, 0xb6, 0xae, 0x61, 0x10, 0x66, 0x0c, 0x23, 0x21, 0x78, 0xfd, 0x8b, 0x1e, 0xd1, 0x24, 0x5e, 0xfd, + 0xc0, 0x3f, 0x67, 0xbc, 0x50, 0x44, 0x1a, 0x44, 0x48, 0xdd, 0xc4, 0x37, 0x32, 0x4d, 0x0a, 0x28, 0x04, 0x18, 0x05, + 0x54, 0x62, 0x43, 0x53, 0xf1, 0xb7, 0x5a, 0x7c, 0xf0, 0x53, 0xd3, 0xf1, 0x68, 0x5c, 0xb7, 0x3a, 0xa3, 0x82, 0xce, + 0x40, 0x8f, 0x5a, 0x51, 0x4f, 0x83, 0x56, 0x82, 0x69, 0xa4, 0x79, 0xeb, 0x1e, 0x02, 0xaf, 0x4c, 0x8b, 0x77, 0x1e, + 0xd0, 0xed, 0x99, 0x0f, 0x9e, 0x3c, 0xa6, 0x67, 0x0e, 0x3d, 0xb9, 0x62, 0x27, 0x55, 0x0f, 0xb5, 0xf7, 0x66, 0x84, + 0x82, 0x7e, 0x1f, 0x53, 0xa0, 0x1b, 0x41, 0xed, 0x5d, 0xdd, 0x2b, 0xb9, 0xcf, 0xe1, 0x3b, 0xce, 0x72, 0x0b, 0x58, + 0x2a, 0xb2, 0x56, 0xe0, 0x51, 0x80, 0xba, 0x54, 0x86, 0xb0, 0xc5, 0x1c, 0x0e, 0x95, 0xdd, 0xaa, 0xd5, 0x50, 0x92, + 0xe3, 0x72, 0x04, 0x0e, 0xa1, 0xeb, 0x72, 0x50, 0x8e, 0x96, 0x59, 0xf5, 0x1e, 0x7f, 0x6b, 0xd6, 0x21, 0xc9, 0xee, + 0x62, 0x1d, 0xb8, 0x65, 0x1d, 0xa6, 0x9f, 0x0c, 0x52, 0x00, 0x9a, 0x6c, 0x04, 0x2e, 0x01, 0x78, 0x6f, 0xff, 0x11, + 0xa1, 0x56, 0xa6, 0x77, 0x32, 0x16, 0xea, 0xfb, 0x46, 0x12, 0x94, 0xd0, 0x4c, 0xa8, 0x1c, 0x4b, 0xc1, 0x3b, 0x8f, + 0x74, 0x4e, 0xea, 0x4c, 0xbc, 0x07, 0x71, 0x5a, 0x78, 0xcf, 0xde, 0x82, 0xe0, 0x9c, 0x05, 0xdd, 0xe0, 0x6d, 0x56, + 0x4b, 0x6d, 0xf4, 0x40, 0x01, 0xfc, 0x6e, 0xb0, 0x41, 0x90, 0xaf, 0xc6, 0x70, 0xad, 0xe4, 0x4d, 0xc8, 0x87, 0x05, + 0x3d, 0x22, 0x03, 0xfb, 0x2c, 0x86, 0x31, 0x3d, 0x22, 0xc7, 0xf6, 0x59, 0xba, 0x01, 0x1c, 0x48, 0x3d, 0xaa, 0xf4, + 0x08, 0x1a, 0xf4, 0x2f, 0xdb, 0x22, 0x77, 0x00, 0x4a, 0xa3, 0x88, 0x81, 0x2a, 0x41, 0x44, 0x2d, 0xfe, 0x7d, 0x6f, + 0xae, 0x0d, 0xe6, 0x02, 0x61, 0x0e, 0x06, 0x1c, 0xc4, 0x6d, 0x10, 0x9a, 0x03, 0x66, 0x7b, 0x1b, 0x09, 0xba, 0xb1, + 0x86, 0x99, 0x1d, 0xfd, 0xe1, 0x56, 0x82, 0x6f, 0xb2, 0xd6, 0xa8, 0xf3, 0xe2, 0x10, 0x08, 0x82, 0x37, 0x85, 0xaa, + 0xf6, 0xaa, 0x07, 0x36, 0xde, 0xaa, 0x1f, 0xbb, 0xdd, 0x78, 0x2a, 0xdc, 0xb5, 0x5f, 0x50, 0x38, 0xf9, 0x94, 0xfc, + 0xeb, 0xbd, 0xc9, 0xe0, 0xc0, 0xc8, 0xf0, 0xa5, 0xb7, 0x7f, 0xe1, 0x6b, 0x2d, 0xdd, 0x13, 0x83, 0x92, 0x3c, 0x3c, + 0x52, 0xf4, 0xef, 0x4e, 0x59, 0xf9, 0xd4, 0x4e, 0xff, 0x6e, 0x67, 0xd6, 0xe7, 0xf1, 0x68, 0xb2, 0xdb, 0xf5, 0xe2, + 0x4a, 0x7b, 0xac, 0xe9, 0x05, 0x81, 0xce, 0xf5, 0xe4, 0xf0, 0x08, 0xa2, 0x22, 0x34, 0xe3, 0x6e, 0x96, 0x0d, 0x89, + 0x8c, 0x1f, 0xa7, 0xb3, 0x6c, 0x08, 0x76, 0xb8, 0x17, 0x95, 0xb8, 0x1c, 0xb5, 0x36, 0x38, 0xbd, 0x4d, 0x42, 0x08, + 0xe5, 0x80, 0x95, 0xdd, 0xaa, 0x3f, 0x1b, 0x65, 0x26, 0xa4, 0x26, 0xab, 0xdb, 0x29, 0xdd, 0xc3, 0x34, 0x3f, 0x30, + 0x23, 0x38, 0xe0, 0xde, 0xfe, 0xaa, 0x3f, 0x85, 0x49, 0xa6, 0xc9, 0x29, 0x92, 0x5f, 0xa4, 0xa7, 0x90, 0xb4, 0x47, + 0x4f, 0x15, 0x01, 0x9c, 0x50, 0xfb, 0x31, 0xfc, 0x86, 0x71, 0xff, 0xa1, 0xf9, 0xda, 0x4d, 0x45, 0xf4, 0x98, 0x62, + 0x99, 0x9a, 0x9c, 0x26, 0x59, 0x91, 0x40, 0xd4, 0x46, 0xd5, 0x8c, 0xe8, 0x91, 0x8b, 0xf9, 0xa8, 0x08, 0x9f, 0x57, + 0xeb, 0xff, 0x0c, 0xe1, 0x33, 0x92, 0x5d, 0x80, 0xcb, 0x2b, 0x2e, 0xcf, 0xc3, 0x27, 0x8f, 0xe9, 0xc1, 0xe4, 0xbb, + 0x23, 0x7a, 0x70, 0xf4, 0xe8, 0x09, 0x01, 0x58, 0xb4, 0xcb, 0xf3, 0xf0, 0xe8, 0xc9, 0x13, 0x7a, 0xf0, 0xfd, 0xf7, + 0xf4, 0x60, 0xf2, 0xe8, 0xa8, 0x91, 0x36, 0x79, 0xf2, 0x3d, 0x3d, 0xf8, 0xee, 0x71, 0x23, 0xed, 0x68, 0xfc, 0x84, + 0x1e, 0xfc, 0xfd, 0x3b, 0x93, 0xf6, 0x37, 0xc8, 0xf6, 0xfd, 0x11, 0xfe, 0x67, 0xd2, 0x26, 0x4f, 0x1e, 0xd1, 0x83, + 0xc9, 0x18, 0x2a, 0x79, 0xe2, 0x2a, 0x19, 0x4f, 0xe0, 0xe3, 0x47, 0xf0, 0xdf, 0xdf, 0x08, 0x6c, 0x02, 0xc9, 0x96, + 0x02, 0xf5, 0x67, 0x28, 0xe2, 0x44, 0xd5, 0x44, 0xc2, 0x43, 0xcc, 0xac, 0xbe, 0x89, 0xc3, 0x80, 0xb8, 0x74, 0x28, + 0x88, 0x1e, 0x8c, 0x47, 0x4f, 0x48, 0xe0, 0xc3, 0xd3, 0x7d, 0xf2, 0x41, 0xc6, 0x96, 0x62, 0x9e, 0x7d, 0xb3, 0x34, + 0xb1, 0x15, 0x3c, 0x00, 0xab, 0x0f, 0x7e, 0x2e, 0x2e, 0xe7, 0xd9, 0x37, 0x5c, 0xee, 0xe7, 0xfa, 0xb1, 0x05, 0x28, + 0xef, 0xaf, 0x5a, 0xf6, 0xa9, 0x50, 0xa1, 0xd3, 0x5a, 0xa3, 0xcf, 0x3e, 0x60, 0xfa, 0x60, 0xe0, 0xdd, 0xb0, 0x7f, + 0xde, 0x2b, 0xa7, 0xf5, 0x8d, 0x46, 0xa1, 0x46, 0xe5, 0x21, 0x61, 0x27, 0x50, 0xf4, 0x60, 0x00, 0x3c, 0x81, 0x2b, + 0xe3, 0xf7, 0xff, 0xb0, 0x8c, 0x0f, 0x1d, 0x65, 0xfc, 0x03, 0x65, 0x08, 0x68, 0xd4, 0xc3, 0xec, 0xa6, 0x87, 0x8d, + 0x6e, 0xf5, 0x92, 0xa5, 0x3a, 0x99, 0x9a, 0x9e, 0xc1, 0xbe, 0xd6, 0xb5, 0x3c, 0x30, 0xa2, 0x68, 0x79, 0x71, 0x90, + 0xf2, 0x59, 0xc5, 0x7e, 0x5e, 0xa2, 0x7a, 0x2b, 0x6a, 0xbc, 0x91, 0xd9, 0xac, 0x62, 0xbf, 0x9b, 0x37, 0xc0, 0xcd, + 0xb0, 0x1f, 0xd5, 0x93, 0x1f, 0x38, 0x23, 0x93, 0xb6, 0x3d, 0xca, 0xc4, 0x08, 0xb0, 0x02, 0x32, 0x70, 0xe0, 0x01, + 0xd0, 0x41, 0x7f, 0xb4, 0x77, 0x3b, 0x95, 0xd2, 0xec, 0xb3, 0x85, 0x01, 0x34, 0xcc, 0xdb, 0xc4, 0x95, 0x5d, 0xa5, + 0xbe, 0xbc, 0x04, 0x85, 0x5b, 0xcd, 0xf2, 0xf6, 0x0a, 0x53, 0x71, 0x7b, 0x52, 0x06, 0x80, 0x03, 0x01, 0x06, 0x63, + 0x2d, 0x03, 0x6a, 0xb6, 0x7c, 0xb4, 0xe5, 0x4a, 0x3d, 0x09, 0x9c, 0xc1, 0x85, 0x2c, 0x12, 0xfe, 0x56, 0x8b, 0xfd, + 0xd1, 0xfa, 0xd1, 0xf7, 0xed, 0xf1, 0x60, 0xed, 0x7b, 0x7c, 0xa4, 0x3f, 0x6b, 0x5c, 0x07, 0xb6, 0x2d, 0xdf, 0x78, + 0x51, 0x5b, 0x89, 0x47, 0x09, 0xbc, 0x81, 0x89, 0x48, 0x61, 0x90, 0x6a, 0x81, 0x63, 0x50, 0xde, 0x58, 0x88, 0xa5, + 0xea, 0xea, 0x86, 0x6e, 0xc9, 0x10, 0x3c, 0xdc, 0xaa, 0x54, 0x05, 0x8e, 0xea, 0xf7, 0x33, 0xe9, 0xbb, 0x3d, 0x19, + 0x3b, 0x72, 0x9c, 0xfa, 0xa9, 0x70, 0xf0, 0xdf, 0xa4, 0xae, 0xf5, 0xcb, 0x2c, 0x65, 0x96, 0x65, 0x61, 0x27, 0xa1, + 0x96, 0x7b, 0x54, 0x1e, 0x24, 0x5f, 0xc8, 0x21, 0x92, 0x05, 0x46, 0xa1, 0x20, 0xc3, 0x09, 0x15, 0xa3, 0xb5, 0x28, + 0x97, 0xd9, 0x45, 0x15, 0x6e, 0x95, 0x42, 0x99, 0x53, 0xf4, 0xed, 0x06, 0x07, 0x12, 0x12, 0x65, 0xe5, 0x9b, 0xf8, + 0x4d, 0x88, 0x60, 0x75, 0x5c, 0xdb, 0x42, 0x71, 0x6f, 0x7f, 0x8a, 0xb4, 0x8b, 0x3f, 0x32, 0x2e, 0xa0, 0x2e, 0x16, + 0xd3, 0x70, 0x62, 0x63, 0x1f, 0xb8, 0x2f, 0xac, 0xa6, 0x07, 0xa0, 0xbe, 0x4b, 0x25, 0x46, 0x50, 0x5f, 0x19, 0xfb, + 0xd8, 0x1e, 0x63, 0x72, 0x06, 0xb1, 0x86, 0x75, 0xd9, 0xaa, 0x6f, 0x84, 0x9d, 0x00, 0x70, 0x23, 0xb4, 0x46, 0x47, + 0x26, 0xa9, 0x42, 0x3c, 0x2f, 0x55, 0xf8, 0xd6, 0x8c, 0xd0, 0x31, 0x78, 0x53, 0xb9, 0x46, 0x4a, 0x5f, 0x30, 0x68, + 0x8e, 0x6d, 0x1d, 0x85, 0xd5, 0x56, 0x96, 0x9d, 0x00, 0xdc, 0x40, 0x76, 0x6c, 0x2e, 0x9e, 0xb3, 0x6a, 0x9e, 0x2d, + 0x22, 0x13, 0x14, 0x30, 0x15, 0x96, 0x41, 0x7b, 0x73, 0x87, 0x6c, 0xc7, 0x21, 0x74, 0xc3, 0x7d, 0x04, 0xe3, 0x69, + 0x37, 0x05, 0x2b, 0x88, 0x46, 0x88, 0x87, 0x19, 0xb3, 0xf8, 0x5e, 0x69, 0xca, 0x53, 0xd5, 0x12, 0x08, 0x1c, 0x85, + 0x50, 0x17, 0xfb, 0x46, 0x09, 0x2e, 0x53, 0x23, 0x98, 0xc1, 0x9e, 0x1d, 0xa9, 0xed, 0x92, 0x73, 0x3a, 0x54, 0x53, + 0x5a, 0xea, 0x29, 0xd5, 0xbe, 0x86, 0x62, 0x5e, 0xa2, 0x87, 0x1e, 0xb8, 0x1e, 0x68, 0x87, 0xbc, 0x92, 0x4e, 0x4c, + 0x04, 0x9d, 0x56, 0x9b, 0xb0, 0x73, 0x23, 0xdd, 0xb2, 0x1a, 0x79, 0xc7, 0xd0, 0xec, 0x88, 0x57, 0x7e, 0xa0, 0x2e, + 0x80, 0x08, 0xb9, 0xb3, 0x45, 0x86, 0x38, 0xb3, 0xac, 0x7c, 0x01, 0x65, 0x71, 0xc4, 0xd6, 0x15, 0x70, 0x2d, 0x05, + 0x93, 0x4b, 0x1e, 0x89, 0x14, 0x11, 0x01, 0x4f, 0x95, 0x76, 0x7d, 0xaf, 0x25, 0x84, 0x96, 0x29, 0x10, 0x37, 0x17, + 0xc5, 0xb9, 0xb6, 0x81, 0x2c, 0x80, 0xbe, 0xfd, 0x94, 0x5d, 0x79, 0xe1, 0x60, 0xb7, 0x57, 0x99, 0x78, 0xc6, 0x2f, + 0x32, 0xc1, 0x53, 0x04, 0xbb, 0xba, 0x35, 0x0f, 0xdc, 0xb1, 0x6d, 0x60, 0xf9, 0xf6, 0x03, 0x2c, 0x98, 0x32, 0xd4, + 0x4a, 0x89, 0x4c, 0x44, 0x02, 0x32, 0xfb, 0xcc, 0xdd, 0xeb, 0x4c, 0xbc, 0x8e, 0x6f, 0xc1, 0x9b, 0xa2, 0xc1, 0x4f, + 0x8f, 0xce, 0xf1, 0x4b, 0x44, 0x12, 0x85, 0x18, 0xb6, 0x18, 0x11, 0x0b, 0x91, 0x63, 0xc7, 0x84, 0x72, 0x25, 0x68, + 0x6d, 0x0d, 0x81, 0x17, 0x7f, 0x5a, 0x75, 0xef, 0x2a, 0x13, 0xc6, 0x3e, 0xe3, 0x2a, 0xbe, 0x65, 0xa5, 0x02, 0xb3, + 0xc0, 0x38, 0xf7, 0x6d, 0x29, 0xc9, 0x55, 0x26, 0x8c, 0x80, 0xe4, 0x2a, 0xbe, 0xa5, 0x4d, 0x19, 0x87, 0xb6, 0xa2, + 0xf3, 0xe2, 0xfc, 0xee, 0x0f, 0xbf, 0xc4, 0x50, 0x2b, 0xe3, 0x7e, 0x1f, 0x24, 0x66, 0xd2, 0x36, 0x65, 0x26, 0x23, + 0xa9, 0xd1, 0x42, 0x2a, 0xca, 0x07, 0x13, 0xb2, 0xbf, 0x52, 0x2d, 0x23, 0x6a, 0xbf, 0x0a, 0xc5, 0x6c, 0x1c, 0x4d, + 0x08, 0x9d, 0x74, 0xac, 0x77, 0xd3, 0x5a, 0xc8, 0x34, 0x7a, 0x12, 0x79, 0x3e, 0x9d, 0x05, 0xab, 0xa6, 0xc5, 0x31, + 0xe3, 0xd3, 0x62, 0x30, 0x20, 0xda, 0xa5, 0x70, 0x8b, 0xf5, 0x80, 0x29, 0x8d, 0x8b, 0xb7, 0x66, 0x5a, 0xfd, 0x42, + 0xaa, 0x90, 0xf4, 0x9e, 0x01, 0x89, 0x90, 0x2e, 0xd8, 0x2d, 0x48, 0x14, 0x3d, 0xff, 0x3b, 0xb5, 0x05, 0xf7, 0x3d, + 0x18, 0x9b, 0xd1, 0x7d, 0x3d, 0xe3, 0x3f, 0xd4, 0xb6, 0x20, 0xea, 0x53, 0xc9, 0x7a, 0x1d, 0x89, 0x2a, 0xe4, 0x22, + 0xfc, 0xec, 0x68, 0x88, 0x21, 0xaa, 0x3d, 0x16, 0x88, 0xf5, 0xd5, 0x39, 0x2f, 0x70, 0xfa, 0x99, 0xbb, 0x5c, 0xc1, + 0xb6, 0xa0, 0x95, 0xa1, 0x51, 0x6f, 0xe2, 0x37, 0x91, 0xbd, 0x2c, 0xe8, 0x22, 0x9f, 0xa1, 0x90, 0x35, 0x0f, 0xc3, + 0x6a, 0xd8, 0x1e, 0x44, 0x72, 0xd8, 0x9e, 0x84, 0x46, 0x63, 0x60, 0x81, 0xec, 0xd1, 0x08, 0x5c, 0x84, 0x56, 0xfe, + 0x76, 0x0c, 0x2e, 0x5c, 0x16, 0x91, 0x65, 0xa8, 0xe3, 0x37, 0xb5, 0x9b, 0xa0, 0x7a, 0x85, 0x4e, 0x53, 0x58, 0x95, + 0x32, 0xc9, 0x87, 0x5f, 0x2f, 0x64, 0x81, 0x99, 0xbc, 0x2e, 0x7b, 0xf4, 0xb5, 0xdd, 0xde, 0x81, 0x29, 0x58, 0xf7, + 0xc9, 0xfb, 0xfa, 0x61, 0x67, 0x4f, 0xc0, 0x28, 0x56, 0xe5, 0x68, 0x0a, 0x29, 0xb5, 0x0f, 0x4a, 0xfd, 0x29, 0x4c, + 0x85, 0xe6, 0xd8, 0x2d, 0x60, 0x12, 0xb0, 0xcf, 0x90, 0xea, 0x31, 0xed, 0xd8, 0xe7, 0x68, 0x0b, 0x4b, 0x02, 0x0e, + 0xff, 0x48, 0xc8, 0xda, 0xbf, 0xba, 0xcb, 0xb4, 0x19, 0xb2, 0x65, 0xbe, 0x00, 0x3e, 0x1f, 0x76, 0x6d, 0x54, 0xa2, + 0x6c, 0x22, 0x92, 0x14, 0xb6, 0x3c, 0x06, 0x69, 0x8f, 0x62, 0xba, 0x2a, 0x78, 0x92, 0xa1, 0x94, 0x22, 0xd1, 0x3e, + 0xc1, 0x39, 0xbc, 0xc1, 0xfd, 0xa8, 0x02, 0xc2, 0xab, 0x90, 0xd3, 0x51, 0x4a, 0xb5, 0x05, 0x8c, 0xa2, 0x1e, 0x20, + 0xca, 0xcb, 0x40, 0x8e, 0xb7, 0xdb, 0x4d, 0xe8, 0x8a, 0x2d, 0x87, 0x13, 0x8a, 0xa4, 0xe4, 0x12, 0xcb, 0xbd, 0x02, + 0x9d, 0xc7, 0x39, 0xeb, 0xbd, 0x02, 0x2c, 0x82, 0x33, 0xf8, 0x1b, 0x13, 0x7a, 0x0d, 0x7f, 0x73, 0x42, 0x9f, 0xb2, + 0xf0, 0x6a, 0x78, 0x49, 0x0e, 0xc3, 0x74, 0x30, 0x51, 0x82, 0xb1, 0x0d, 0x4b, 0xcb, 0x50, 0x25, 0xae, 0x0e, 0x2f, + 0xc8, 0xc3, 0x0b, 0x7a, 0x4b, 0x6f, 0xe8, 0x6b, 0xfa, 0x00, 0x08, 0xff, 0xe6, 0x78, 0xc2, 0x87, 0x93, 0xc7, 0xfd, + 0x7e, 0xef, 0xbc, 0xdf, 0xef, 0x9d, 0x19, 0x03, 0x0a, 0xbd, 0x8b, 0x2e, 0x6b, 0xaa, 0x7f, 0x5d, 0xd5, 0x8b, 0xe9, + 0x03, 0xb5, 0x71, 0x13, 0x9e, 0xe5, 0xe1, 0xd5, 0xe1, 0x86, 0x0c, 0xf1, 0xf1, 0x22, 0x97, 0xb2, 0x08, 0x2f, 0x0f, + 0x37, 0x84, 0x3e, 0x38, 0x01, 0xbd, 0x29, 0xd6, 0xf7, 0xe0, 0xe1, 0x46, 0xd7, 0x46, 0xe8, 0xab, 0x30, 0x81, 0x6d, + 0x72, 0xcb, 0xec, 0x5d, 0x7b, 0x32, 0x86, 0x58, 0x26, 0x1b, 0xaf, 0xbc, 0xcd, 0xc3, 0x5b, 0x72, 0x78, 0x0b, 0x9e, + 0xa2, 0x96, 0xfc, 0xcd, 0xc2, 0x1b, 0xd6, 0xaa, 0xe1, 0xe1, 0x86, 0xbe, 0x6e, 0x35, 0xe2, 0xe1, 0x86, 0x44, 0xe1, + 0x0d, 0xbb, 0xa4, 0xaf, 0xd9, 0x15, 0xa1, 0xe7, 0xfd, 0xfe, 0x59, 0xbf, 0x2f, 0xfb, 0xfd, 0x9f, 0xe3, 0x30, 0x8c, + 0x87, 0x05, 0x39, 0x94, 0x74, 0x73, 0x38, 0xe1, 0x8f, 0xc8, 0x2c, 0xd4, 0xcd, 0x57, 0x0b, 0xce, 0xaa, 0xbc, 0x55, + 0xae, 0x0d, 0x05, 0x6b, 0x85, 0x0d, 0x53, 0x4f, 0x0f, 0xe8, 0x0d, 0x2b, 0xe8, 0x6b, 0x16, 0x93, 0xe8, 0x1a, 0x5a, + 0x71, 0x3e, 0x2b, 0xa2, 0x1b, 0xfa, 0x9a, 0x9d, 0xcd, 0xe2, 0xe8, 0x35, 0x7d, 0xc0, 0xf2, 0xe1, 0x04, 0xf2, 0xbe, + 0x1e, 0xde, 0x90, 0xc3, 0x07, 0x24, 0x0a, 0x1f, 0xe8, 0xdf, 0x1b, 0x7a, 0xc9, 0xc3, 0x07, 0xd4, 0xab, 0xe6, 0x01, + 0x31, 0xd5, 0x37, 0x6a, 0x7f, 0x40, 0x22, 0x7f, 0x30, 0x1f, 0x58, 0x7b, 0x9a, 0x77, 0x8e, 0x36, 0xae, 0xcb, 0x70, + 0x43, 0xe8, 0xba, 0x0c, 0x6f, 0x08, 0x99, 0x36, 0xc7, 0x0e, 0x06, 0x74, 0xf6, 0x2e, 0x4a, 0x08, 0xbd, 0xf1, 0x4b, + 0xbd, 0xc1, 0x31, 0x34, 0x23, 0xa4, 0xfb, 0x89, 0x69, 0xb8, 0x0e, 0x3e, 0x6a, 0xb0, 0x8e, 0xf3, 0x7e, 0x3f, 0x5c, + 0xf7, 0xfb, 0x10, 0xe9, 0xbe, 0x98, 0x99, 0xd8, 0x6e, 0x8e, 0x6c, 0xd2, 0x1b, 0xd0, 0xfe, 0x7f, 0x1c, 0x0c, 0xa0, + 0x33, 0x5e, 0x49, 0xe1, 0xcd, 0xe0, 0xe3, 0xc3, 0x0d, 0x51, 0x75, 0x14, 0xb4, 0x94, 0x61, 0x41, 0x9f, 0xd2, 0x0c, + 0x00, 0xbf, 0x3e, 0x0e, 0x06, 0x24, 0x32, 0x9f, 0x91, 0xe9, 0xc7, 0xe3, 0x07, 0xd3, 0xc1, 0xe0, 0xa3, 0xd9, 0x26, + 0x9f, 0xd9, 0x1d, 0xa5, 0xc0, 0xfa, 0x3b, 0xeb, 0xf7, 0x3f, 0x9f, 0xc4, 0xe4, 0xbc, 0xe0, 0xf1, 0xa7, 0x69, 0xb3, + 0x2d, 0x9f, 0x5d, 0x54, 0xb5, 0xb3, 0x7e, 0x7f, 0xdd, 0xef, 0xbf, 0x06, 0xec, 0xa2, 0x99, 0xf3, 0xf5, 0x04, 0x69, + 0xcb, 0xdc, 0x51, 0x24, 0x4d, 0x72, 0x68, 0x0c, 0x6d, 0x8b, 0x55, 0xdb, 0x66, 0x1d, 0x19, 0x58, 0x1c, 0x35, 0x2b, + 0x8a, 0x6b, 0x12, 0x85, 0xbd, 0xb3, 0xdd, 0xee, 0x35, 0x63, 0x2c, 0x26, 0x20, 0xfd, 0xf0, 0x5f, 0xbf, 0xae, 0x1b, + 0x31, 0xc4, 0x4a, 0x25, 0xbe, 0xdb, 0x2e, 0xed, 0x21, 0x10, 0x71, 0xd8, 0xf4, 0xef, 0xcd, 0xbd, 0x5c, 0xd4, 0x8e, + 0x6f, 0xfd, 0x1d, 0x40, 0x88, 0x24, 0x0b, 0xf9, 0x0c, 0xc7, 0xa0, 0xcc, 0x00, 0xc8, 0x3c, 0x52, 0x33, 0x2f, 0x01, + 0x04, 0x98, 0xec, 0x76, 0xa3, 0xf1, 0x78, 0x42, 0x0b, 0x36, 0xfa, 0xdb, 0x93, 0x87, 0xd5, 0xc3, 0x30, 0x08, 0x06, + 0x19, 0x69, 0xe9, 0x29, 0xec, 0x62, 0xad, 0x0e, 0xc1, 0x08, 0x5e, 0xb3, 0x8f, 0xd7, 0xd9, 0x57, 0xb3, 0x8f, 0x48, + 0x58, 0x1b, 0x8c, 0x23, 0x17, 0x69, 0x4b, 0x6f, 0x77, 0x07, 0x83, 0xc9, 0x45, 0xfa, 0x05, 0xb6, 0xd3, 0xe7, 0xdf, + 0x3c, 0x18, 0x4f, 0x38, 0x18, 0xdd, 0x45, 0x41, 0x9f, 0x69, 0xbb, 0x5d, 0xe5, 0x5f, 0x02, 0xdf, 0x60, 0x2a, 0xe8, + 0xd8, 0x2c, 0x0b, 0x37, 0xa8, 0x88, 0x3a, 0x5a, 0x06, 0x55, 0xad, 0x6c, 0xe7, 0x80, 0x5a, 0x62, 0x55, 0x26, 0x6e, + 0x81, 0x61, 0xc8, 0x50, 0x97, 0x7b, 0x5a, 0xfd, 0xce, 0x0b, 0x69, 0xe0, 0x33, 0x9c, 0x88, 0xd0, 0xe3, 0xd6, 0xb8, + 0xcf, 0xad, 0x89, 0x2f, 0x70, 0x6b, 0x25, 0x92, 0x58, 0x03, 0x4b, 0x6a, 0x2e, 0x47, 0x09, 0x3b, 0x29, 0x19, 0x9f, + 0x95, 0x51, 0x42, 0x63, 0x78, 0x90, 0x4c, 0xcc, 0x64, 0x94, 0xa0, 0x7d, 0xa2, 0x8b, 0x30, 0xf8, 0x17, 0x60, 0xf6, + 0xd3, 0x1c, 0xfe, 0x4a, 0x32, 0x4d, 0x8e, 0x21, 0x20, 0xc4, 0xf1, 0x78, 0x16, 0x87, 0x63, 0x12, 0x25, 0x27, 0xf0, + 0x04, 0xff, 0x15, 0xe1, 0x98, 0xd4, 0xfa, 0x0e, 0x23, 0xd5, 0xe5, 0x36, 0x61, 0x00, 0x57, 0x36, 0x9e, 0x4d, 0x22, + 0x2b, 0xdd, 0x95, 0x0f, 0x47, 0xe3, 0x27, 0x64, 0x1a, 0x87, 0x72, 0x90, 0x10, 0x0a, 0xde, 0xbd, 0x61, 0x39, 0x4c, + 0x34, 0x3c, 0x1b, 0xb0, 0x79, 0xa5, 0x63, 0xf3, 0x24, 0x9c, 0x80, 0x30, 0x4c, 0xc8, 0xb1, 0xde, 0x81, 0x94, 0xa2, + 0xcf, 0x73, 0xec, 0xa7, 0x3e, 0x82, 0x30, 0x3b, 0x6a, 0xa9, 0xf8, 0x0a, 0x80, 0x2e, 0x71, 0x70, 0xa8, 0x3d, 0xf3, + 0xc5, 0x2c, 0x2c, 0x3d, 0x2a, 0x65, 0xaa, 0x3b, 0x14, 0x0d, 0xca, 0x6f, 0x1a, 0x74, 0x28, 0xc8, 0x60, 0x42, 0xcb, + 0x93, 0x09, 0x7f, 0x04, 0x01, 0x3c, 0x1a, 0x11, 0xbf, 0x14, 0x4e, 0x0c, 0x84, 0x57, 0x41, 0x06, 0x2a, 0xad, 0x55, + 0x63, 0x46, 0xb6, 0xe2, 0x03, 0x08, 0x93, 0x72, 0x70, 0x23, 0xd7, 0x79, 0x0a, 0x51, 0xc1, 0xd6, 0x79, 0x75, 0x70, + 0x09, 0x96, 0xec, 0x71, 0x05, 0x71, 0xc2, 0xd6, 0x2b, 0xc0, 0xce, 0x7d, 0xb0, 0x2d, 0xeb, 0x03, 0xf5, 0xdd, 0x01, + 0xb6, 0x1c, 0x5e, 0x55, 0xf2, 0x60, 0x32, 0x1e, 0x8f, 0x47, 0x7f, 0xc0, 0xd1, 0x01, 0x84, 0x96, 0x44, 0x86, 0x4f, + 0x06, 0x68, 0xdc, 0x75, 0xc5, 0xbd, 0x71, 0xa1, 0x28, 0x2b, 0x9d, 0x4c, 0x08, 0x88, 0x9f, 0x4d, 0xdf, 0x60, 0x5f, + 0x71, 0x1d, 0xff, 0x64, 0xff, 0x13, 0xb3, 0xa2, 0xd5, 0x4a, 0x1d, 0xbd, 0x7b, 0xfb, 0xe1, 0xd5, 0xc7, 0x57, 0xbf, + 0x3e, 0x3f, 0x7b, 0xf5, 0xe6, 0xc5, 0xab, 0x37, 0xaf, 0x3e, 0xfe, 0xfb, 0x1e, 0x06, 0xdb, 0xb7, 0x15, 0xb1, 0x63, + 0xef, 0xdd, 0x63, 0xbc, 0x5a, 0x7c, 0xe1, 0xec, 0x91, 0xbb, 0xc5, 0x02, 0x6c, 0x82, 0xe1, 0x16, 0x04, 0xd5, 0x8c, + 0x46, 0xa5, 0xef, 0x09, 0xc8, 0x68, 0x54, 0xc8, 0xc6, 0xc3, 0x8a, 0xad, 0x90, 0x8b, 0x77, 0x0c, 0x07, 0x1f, 0xd9, + 0xdf, 0x8a, 0x33, 0xe1, 0x76, 0xb4, 0x35, 0x2b, 0x02, 0x3e, 0x5f, 0x6b, 0x51, 0x79, 0x5c, 0x88, 0xda, 0xdb, 0xf6, + 0x39, 0x24, 0xd4, 0x23, 0x72, 0x1d, 0xbc, 0x6f, 0x83, 0xec, 0xf1, 0x91, 0xf7, 0xa4, 0x3c, 0x43, 0x7d, 0x8e, 0x86, + 0x8f, 0x1a, 0xcf, 0xe8, 0xc4, 0x5c, 0x1b, 0x1d, 0xea, 0x59, 0x01, 0xfb, 0x5b, 0x89, 0xb1, 0xc1, 0x1c, 0x3a, 0x45, + 0xac, 0x0f, 0xa7, 0xfb, 0xdd, 0xbf, 0x19, 0xfd, 0x0c, 0xc7, 0x8f, 0x52, 0x4d, 0x20, 0x2d, 0x0a, 0x94, 0xae, 0x0c, + 0xb9, 0xed, 0x59, 0x58, 0x98, 0x9f, 0x61, 0x83, 0x00, 0xda, 0xcb, 0x8e, 0x25, 0x81, 0x66, 0xf1, 0x5a, 0xd7, 0x3f, + 0x2f, 0x5f, 0x26, 0xda, 0xf9, 0xe2, 0x5b, 0x08, 0x31, 0xec, 0x5f, 0x11, 0x1a, 0x13, 0xee, 0x26, 0xd9, 0x5d, 0x5a, + 0xcc, 0xbd, 0xea, 0x2a, 0xc6, 0xe3, 0xee, 0x8e, 0x2b, 0x45, 0xf3, 0xd6, 0x05, 0xf6, 0x40, 0xcd, 0xeb, 0x78, 0xc9, + 0x42, 0xc0, 0x66, 0x3c, 0xb4, 0x8b, 0xc4, 0xf9, 0xbd, 0xd3, 0x09, 0x39, 0x3c, 0x9a, 0xf2, 0x21, 0x2b, 0xa9, 0x18, + 0xb0, 0xb2, 0xde, 0xa3, 0xe6, 0xbc, 0x4d, 0xc8, 0xc5, 0x3e, 0x0d, 0x17, 0x43, 0x7e, 0xdf, 0x25, 0xe9, 0x23, 0x6f, + 0x38, 0x54, 0xdb, 0xe6, 0x62, 0x48, 0x53, 0x4e, 0xf7, 0xa9, 0x0c, 0x08, 0x91, 0xae, 0xe2, 0x8a, 0xd4, 0xfa, 0xa8, + 0x5a, 0x3b, 0x49, 0xc7, 0x75, 0xb6, 0xfd, 0xc2, 0x25, 0x5b, 0xdd, 0xae, 0xfd, 0x6b, 0x75, 0xfb, 0xc2, 0x0c, 0xe4, + 0xef, 0x4f, 0x44, 0x35, 0x31, 0x10, 0x5d, 0x40, 0x05, 0xff, 0x04, 0x2f, 0x4f, 0x1e, 0x69, 0x05, 0xe8, 0x5d, 0x67, + 0x47, 0xd7, 0x1e, 0x6f, 0xcc, 0x62, 0x6b, 0x89, 0x73, 0x56, 0xf9, 0xce, 0xf2, 0xaa, 0x6c, 0x85, 0xae, 0x23, 0xd8, + 0xef, 0x61, 0x47, 0xdf, 0xbd, 0x6d, 0x00, 0x44, 0x29, 0xac, 0xdc, 0xd9, 0x2f, 0xbc, 0xb3, 0x5f, 0xd8, 0xb3, 0xdf, + 0x6e, 0x02, 0xe5, 0xc3, 0x0a, 0x2d, 0x7b, 0x21, 0x45, 0x65, 0x9a, 0x3c, 0x6e, 0xea, 0xb2, 0x90, 0x16, 0xf3, 0x43, + 0x4b, 0xbb, 0x1e, 0x8f, 0xa9, 0x44, 0xf5, 0xc8, 0x4b, 0x6c, 0xd5, 0x61, 0x49, 0xee, 0xbf, 0x67, 0xfe, 0xcf, 0xde, + 0x20, 0xef, 0xba, 0xdb, 0xfd, 0xdf, 0x5c, 0xe8, 0xe0, 0xb6, 0xb6, 0x16, 0x9e, 0xba, 0x3a, 0x2e, 0xf0, 0xae, 0xb6, + 0xbe, 0xff, 0xae, 0xf6, 0x36, 0xd3, 0xcb, 0xae, 0x02, 0xd4, 0x20, 0xb1, 0xbe, 0xe2, 0x45, 0x96, 0xd4, 0x56, 0xa1, + 0xf1, 0x80, 0x43, 0x68, 0x0f, 0xef, 0xe0, 0x02, 0x39, 0x2c, 0x21, 0xf4, 0x53, 0x65, 0x04, 0x80, 0x3e, 0x8b, 0xfd, + 0x80, 0x87, 0x19, 0x19, 0xf8, 0x12, 0x3f, 0x29, 0x7d, 0x71, 0xf1, 0xe1, 0x5e, 0x66, 0x82, 0x5e, 0x25, 0x36, 0x7b, + 0x21, 0xdb, 0x31, 0x3f, 0xfc, 0x2f, 0x30, 0x1a, 0x84, 0xd7, 0x96, 0xec, 0x50, 0x74, 0xcc, 0x72, 0x05, 0x47, 0x6d, + 0xe9, 0x95, 0xd9, 0xba, 0x7e, 0x56, 0xc3, 0x4c, 0x9f, 0x29, 0x0f, 0x40, 0xf6, 0x85, 0xdc, 0xfd, 0x54, 0x57, 0x2c, + 0xc8, 0xc9, 0x64, 0x3c, 0x25, 0x62, 0x30, 0x68, 0x25, 0x1f, 0x63, 0xf2, 0x70, 0xb8, 0xc7, 0x5c, 0x0a, 0xdd, 0x0f, + 0x2f, 0xf2, 0x2f, 0xd4, 0xd7, 0xd8, 0x92, 0x64, 0x5b, 0xb1, 0xbf, 0xc0, 0x2c, 0x16, 0x88, 0xa3, 0x83, 0x5f, 0x9c, + 0x2f, 0x68, 0x09, 0x6d, 0xa8, 0x0c, 0x7a, 0x72, 0x91, 0x2a, 0x1f, 0xd9, 0x82, 0xc9, 0xe3, 0xf1, 0xcc, 0xef, 0xb9, + 0x63, 0x70, 0x08, 0x89, 0x26, 0xd6, 0xf8, 0xc5, 0xcf, 0x82, 0x71, 0x1c, 0xca, 0x13, 0xd9, 0xf8, 0xae, 0x24, 0xd1, + 0xd8, 0x98, 0x2a, 0xeb, 0xab, 0x44, 0x35, 0x4c, 0xc8, 0xc3, 0x82, 0x1c, 0x16, 0x74, 0xe9, 0x8f, 0x25, 0xa6, 0x1f, + 0xc6, 0x87, 0x93, 0x31, 0x79, 0x18, 0x3f, 0x9c, 0x18, 0xb8, 0x61, 0x3f, 0x47, 0x3e, 0x5c, 0x92, 0xc3, 0x66, 0x95, + 0x60, 0x8a, 0x6a, 0x7a, 0xe6, 0x57, 0x92, 0x0c, 0x96, 0x83, 0xf4, 0x61, 0x2b, 0x2f, 0xd6, 0xaa, 0xc7, 0x7b, 0x7d, + 0xcc, 0xa7, 0x44, 0x34, 0x6e, 0x0c, 0x6b, 0x7a, 0x15, 0xff, 0x29, 0x8b, 0x48, 0x4a, 0x40, 0x24, 0x04, 0xf5, 0x76, + 0x76, 0x91, 0x25, 0xb1, 0x48, 0xa3, 0xb4, 0x26, 0x34, 0x3d, 0x61, 0x93, 0xf1, 0x2c, 0x65, 0xe9, 0xf1, 0xe4, 0xc9, + 0x6c, 0xf2, 0x24, 0x3a, 0x1a, 0x47, 0xe9, 0x60, 0x00, 0xc9, 0x47, 0x63, 0x70, 0xb1, 0x83, 0xdf, 0xec, 0x08, 0x86, + 0xee, 0x04, 0x59, 0xc2, 0x02, 0x9a, 0xf6, 0x75, 0x4d, 0xd2, 0xc3, 0x79, 0xa1, 0x7a, 0x12, 0xdf, 0xd2, 0xb5, 0xe7, + 0xe0, 0xe2, 0xb7, 0xf0, 0xc2, 0xb5, 0xf0, 0x62, 0xbf, 0x85, 0x42, 0x93, 0xed, 0x58, 0xfe, 0xff, 0x71, 0xc3, 0xb8, + 0xeb, 0x2e, 0x61, 0x16, 0xd7, 0x75, 0x36, 0x5a, 0x15, 0xb2, 0x92, 0x70, 0x9b, 0x50, 0xa2, 0xb0, 0x51, 0xbc, 0x5a, + 0xe5, 0xda, 0x45, 0x6c, 0x5e, 0x51, 0x00, 0x77, 0x81, 0x38, 0xc5, 0xc0, 0x42, 0x1b, 0x03, 0xb9, 0xcf, 0xbc, 0x90, + 0xcc, 0xaa, 0x7d, 0xcc, 0x3d, 0xf2, 0xcf, 0x10, 0x8c, 0x51, 0xc5, 0xc9, 0x78, 0xa6, 0xb0, 0x2e, 0xbe, 0x24, 0xef, + 0xfd, 0x0f, 0x8e, 0x22, 0x7b, 0x34, 0x83, 0x9e, 0x20, 0x72, 0x1e, 0x71, 0xf6, 0x64, 0xf2, 0x32, 0x70, 0x3f, 0x83, + 0x95, 0xfe, 0xba, 0xdb, 0x8c, 0xb5, 0xed, 0xd1, 0xbd, 0x30, 0x42, 0xd1, 0xcf, 0xf8, 0xce, 0xd4, 0x0b, 0xb8, 0x84, + 0x6a, 0x60, 0xd7, 0x97, 0x97, 0xbc, 0x04, 0x10, 0xa1, 0x4c, 0xf4, 0xfb, 0xbd, 0x3f, 0x0d, 0x34, 0x69, 0xc9, 0x8b, + 0xd7, 0x99, 0xb0, 0xce, 0x38, 0xd0, 0x54, 0xa0, 0xfe, 0x9f, 0x2a, 0xfb, 0x4c, 0xc7, 0x64, 0xe6, 0x3f, 0x0e, 0x27, + 0x24, 0x6a, 0xbe, 0x26, 0x5f, 0x38, 0x4d, 0xbf, 0x70, 0x45, 0xfb, 0x6f, 0xc8, 0xcc, 0x0d, 0x87, 0x0c, 0xf5, 0x97, + 0x8e, 0x79, 0x32, 0x7a, 0x9d, 0x98, 0x9d, 0x08, 0x56, 0xcd, 0x20, 0x0a, 0x7b, 0x01, 0x0f, 0xea, 0x5a, 0x16, 0x4f, + 0x61, 0xf6, 0x41, 0x8d, 0x28, 0x8e, 0xd9, 0x78, 0x16, 0xca, 0x70, 0x02, 0xf6, 0xbd, 0x93, 0x31, 0xdc, 0x07, 0x64, + 0xf8, 0xa9, 0x0a, 0xb1, 0x73, 0x90, 0xf6, 0xa9, 0x42, 0xc5, 0x04, 0x40, 0x04, 0x42, 0xde, 0x7e, 0x5f, 0xaa, 0x24, + 0x7c, 0x5d, 0x62, 0x4a, 0xa1, 0x3e, 0xf8, 0xef, 0x48, 0xd5, 0x1d, 0xd3, 0xaf, 0xd6, 0x8f, 0x3f, 0x13, 0x8a, 0x4f, + 0x77, 0x29, 0xf1, 0x2d, 0x04, 0x77, 0x8e, 0x41, 0x07, 0x51, 0xa1, 0x19, 0xdb, 0xfd, 0xfc, 0xae, 0xb8, 0x9b, 0xdf, + 0x15, 0xff, 0xef, 0xf8, 0x5d, 0x71, 0x1f, 0x63, 0x58, 0x59, 0x68, 0xf8, 0x59, 0x30, 0x0e, 0xa2, 0xff, 0x3e, 0x9f, + 0x78, 0x27, 0x4f, 0x7d, 0x95, 0x89, 0xe9, 0x1d, 0x4c, 0xb3, 0x4f, 0x50, 0x10, 0x56, 0x71, 0x9f, 0x9e, 0xac, 0x2b, + 0x7b, 0x6b, 0x25, 0x43, 0xcc, 0x73, 0x0f, 0x6b, 0x14, 0x56, 0x1e, 0xd0, 0x3d, 0xaa, 0x36, 0x88, 0x13, 0xc1, 0xc3, + 0x98, 0x59, 0xe9, 0xfb, 0x6e, 0x67, 0x54, 0x98, 0xf7, 0x72, 0x51, 0x90, 0xdd, 0x7c, 0x3c, 0x1b, 0x47, 0x21, 0x36, + 0xe0, 0xbf, 0xcd, 0x58, 0x35, 0x64, 0xf3, 0x9d, 0x8c, 0xd4, 0x9e, 0xc9, 0xd3, 0x64, 0x9f, 0xf4, 0x0e, 0x78, 0x87, + 0xfc, 0xbc, 0xfe, 0x14, 0xc6, 0xd2, 0xf0, 0x5b, 0xf2, 0x32, 0x2e, 0xb2, 0x6a, 0x79, 0x95, 0x25, 0xc8, 0x74, 0xc1, + 0x8b, 0xaf, 0x66, 0xba, 0xbc, 0x8f, 0xf5, 0x01, 0xe3, 0x29, 0xc5, 0xeb, 0x86, 0x28, 0xfd, 0xa2, 0xe5, 0x59, 0xa1, + 0x2e, 0x4f, 0x2a, 0x66, 0x7b, 0x56, 0x82, 0xd3, 0x29, 0x98, 0xe0, 0xeb, 0x9f, 0xae, 0xf7, 0x09, 0xe0, 0x82, 0x42, + 0xcd, 0x69, 0x21, 0x57, 0x06, 0xcb, 0xc9, 0x42, 0x77, 0x02, 0x66, 0xa8, 0x14, 0x78, 0x81, 0x82, 0xbf, 0x68, 0x60, + 0x44, 0x5f, 0xb8, 0xdf, 0x64, 0x60, 0x90, 0x2e, 0xcd, 0x89, 0x30, 0x76, 0xdc, 0x4e, 0x92, 0xb6, 0xa2, 0x9c, 0x71, + 0xf6, 0x5e, 0x5d, 0x29, 0xc0, 0x00, 0x6f, 0x7b, 0x13, 0x6d, 0x12, 0xf4, 0x5a, 0x50, 0x3a, 0x6f, 0xe0, 0x6e, 0x96, + 0x91, 0x11, 0x2e, 0x3e, 0xac, 0x3c, 0x16, 0xdc, 0xb3, 0x5f, 0x48, 0xac, 0xad, 0x1f, 0x18, 0xb3, 0x79, 0xc1, 0x02, + 0x85, 0x0a, 0x14, 0x58, 0xce, 0xb4, 0xa5, 0x69, 0x35, 0xe4, 0x87, 0x47, 0x68, 0x6d, 0x5a, 0x0d, 0xf8, 0xe1, 0x51, + 0x1d, 0x65, 0xc7, 0x90, 0xe5, 0xc4, 0xcf, 0xa0, 0x5e, 0xd7, 0x91, 0x49, 0x31, 0xd9, 0xbd, 0xfa, 0xf2, 0xd4, 0x1f, + 0xd5, 0x2d, 0xb8, 0x7e, 0x00, 0x02, 0xd8, 0x00, 0x1c, 0x02, 0xd5, 0x60, 0x69, 0x44, 0xb0, 0x28, 0x53, 0x68, 0x5f, + 0x43, 0xef, 0x8d, 0x86, 0xff, 0x02, 0x77, 0x11, 0xb9, 0xf2, 0x3f, 0x41, 0xe0, 0xaf, 0x28, 0xd3, 0xca, 0x14, 0xff, + 0x13, 0xad, 0x5e, 0xa1, 0x9c, 0x35, 0xad, 0xf9, 0x20, 0x5a, 0x13, 0xa1, 0x9a, 0x31, 0x04, 0xff, 0x56, 0x96, 0x69, + 0x4b, 0x55, 0xa5, 0x3e, 0x34, 0x5e, 0x6b, 0x85, 0xb3, 0x7c, 0x1c, 0x79, 0xaf, 0x31, 0x74, 0x6c, 0xe2, 0x2c, 0xe5, + 0x54, 0xea, 0xec, 0xcd, 0xa1, 0x8c, 0x1c, 0xe0, 0x74, 0xc2, 0xc6, 0xd3, 0xe4, 0x58, 0x4e, 0x13, 0x07, 0x99, 0x9f, + 0x33, 0x8c, 0xac, 0x6a, 0x40, 0x58, 0x94, 0x0d, 0xa5, 0x2d, 0xc0, 0x24, 0x27, 0x84, 0x4c, 0x31, 0x14, 0x45, 0x3e, + 0xd2, 0xfd, 0xb0, 0xde, 0xac, 0xee, 0x8b, 0x77, 0x1a, 0xe0, 0x34, 0x4c, 0x20, 0x10, 0x78, 0x11, 0xdf, 0x64, 0xe2, + 0x12, 0x3c, 0x86, 0x07, 0xf0, 0x25, 0xb8, 0xc9, 0xa5, 0xec, 0x5f, 0x55, 0x98, 0xe3, 0xda, 0x02, 0x06, 0x0d, 0x56, + 0x0f, 0xa2, 0xc3, 0xa5, 0xb4, 0xd9, 0x55, 0x80, 0xd8, 0x98, 0x42, 0x2c, 0x0b, 0xb6, 0xb6, 0xec, 0xd9, 0xcf, 0xaa, + 0x69, 0x68, 0x9d, 0x70, 0x2a, 0x2e, 0x73, 0x88, 0xa2, 0x32, 0x88, 0xc1, 0x1d, 0xc9, 0xe3, 0xf3, 0x4e, 0x45, 0x78, + 0x41, 0xc0, 0xad, 0x2c, 0x91, 0xe1, 0x8a, 0x2e, 0x47, 0xb7, 0x74, 0x3d, 0xba, 0xa1, 0x63, 0x3a, 0xf9, 0xfb, 0x18, + 0x2d, 0xb2, 0x55, 0xea, 0x86, 0xae, 0x47, 0x4b, 0xfa, 0xfd, 0x98, 0x1e, 0xfd, 0x6d, 0x4c, 0xa6, 0x4b, 0x3c, 0x4c, + 0xe8, 0x05, 0x38, 0x76, 0x91, 0x1a, 0x3d, 0x35, 0x7d, 0x83, 0xc3, 0x6a, 0x94, 0x0f, 0xf9, 0x28, 0xa7, 0x7c, 0x54, + 0x0c, 0xab, 0x11, 0x78, 0x3a, 0x56, 0x43, 0x3e, 0xaa, 0x28, 0x1f, 0x9d, 0x0f, 0xab, 0xd1, 0x39, 0x69, 0x36, 0xfd, + 0x55, 0xc5, 0xaf, 0x4a, 0x76, 0x01, 0xdb, 0x02, 0x96, 0xaf, 0x5b, 0x65, 0xcb, 0xd4, 0x5f, 0xd5, 0xe6, 0x64, 0xb6, + 0x9c, 0xbd, 0xbd, 0xee, 0x72, 0x62, 0xf1, 0xb8, 0x6d, 0x3a, 0x5c, 0x7d, 0x39, 0x51, 0x27, 0xbd, 0x42, 0x7e, 0x18, + 0x4f, 0x85, 0x3a, 0x87, 0xc0, 0x4c, 0x62, 0x16, 0xc6, 0x0c, 0x9b, 0xa9, 0xd3, 0x40, 0x81, 0x93, 0x8d, 0x3c, 0x17, + 0xc5, 0x6c, 0x94, 0x53, 0x78, 0x1f, 0x13, 0x12, 0x09, 0x38, 0xab, 0x4e, 0xaa, 0x51, 0x01, 0x31, 0x47, 0x58, 0x88, + 0x8f, 0xd0, 0x2f, 0xf5, 0x91, 0x87, 0x04, 0x9e, 0x61, 0x5f, 0x8b, 0x41, 0x0c, 0x47, 0xbc, 0xad, 0xac, 0x9a, 0x85, + 0x09, 0x54, 0x56, 0x0d, 0x4b, 0x53, 0x59, 0x41, 0xb3, 0x51, 0xe5, 0x57, 0x56, 0xe1, 0x18, 0x25, 0x84, 0x44, 0xa5, + 0xae, 0x0c, 0xd4, 0x27, 0x09, 0x0b, 0x4b, 0x5d, 0xd9, 0xb9, 0xfa, 0xe8, 0xdc, 0xaf, 0xec, 0x1c, 0x5c, 0x48, 0x07, + 0x89, 0x7f, 0x95, 0x4a, 0xd3, 0xf6, 0x75, 0xb0, 0xb1, 0xaa, 0xe8, 0x96, 0xdf, 0x56, 0x45, 0x1c, 0x95, 0xd4, 0xc5, + 0x80, 0xc6, 0x85, 0x11, 0x49, 0xaa, 0xd7, 0x28, 0xf8, 0x43, 0x82, 0xa8, 0x34, 0x06, 0xaf, 0xce, 0xa4, 0x6b, 0xa5, + 0x56, 0x54, 0x0c, 0xca, 0x41, 0x01, 0xf7, 0xa7, 0xbc, 0xb5, 0x90, 0x7e, 0x86, 0x88, 0xca, 0x50, 0xde, 0xe0, 0x17, + 0x0c, 0x9e, 0xcc, 0xae, 0xd2, 0x30, 0x19, 0x6d, 0x68, 0x3c, 0x5a, 0x22, 0x1c, 0x0c, 0x5b, 0xa5, 0x0a, 0x6f, 0xfd, + 0x12, 0xd2, 0x6f, 0x69, 0x3c, 0xba, 0xa1, 0xa9, 0xb5, 0x39, 0x35, 0x50, 0x57, 0xbd, 0x31, 0xbd, 0x8d, 0xe0, 0xf5, + 0x26, 0x5a, 0x52, 0xd8, 0x4a, 0xa7, 0x79, 0x76, 0x29, 0xa2, 0x94, 0x22, 0x02, 0xe1, 0x1a, 0x91, 0x03, 0x97, 0x1a, + 0x6d, 0x70, 0x3d, 0x80, 0x32, 0x34, 0x5c, 0xe0, 0x72, 0x10, 0x8f, 0x96, 0x1e, 0x99, 0x5a, 0xeb, 0x8b, 0x2c, 0xc2, + 0x47, 0x3b, 0x1b, 0x2d, 0xc5, 0x33, 0x62, 0x61, 0x5c, 0xc1, 0x10, 0xea, 0xc2, 0x4a, 0x53, 0x90, 0x74, 0x81, 0x23, + 0x7b, 0x61, 0x5c, 0x85, 0x5b, 0x30, 0x2d, 0xda, 0x80, 0x79, 0x14, 0x28, 0x1c, 0x5c, 0x82, 0xf4, 0x13, 0xca, 0x76, + 0x8e, 0xd2, 0xe4, 0xf0, 0x26, 0xe8, 0x62, 0x6f, 0x82, 0x90, 0x76, 0x75, 0x93, 0x2d, 0xe9, 0x1b, 0x6c, 0xef, 0xd1, + 0xa9, 0xa8, 0xa0, 0xfa, 0xdc, 0x82, 0xc9, 0x92, 0x0d, 0xc2, 0x96, 0x30, 0x3d, 0xd3, 0x17, 0x80, 0x3d, 0x7d, 0x78, + 0xb4, 0x37, 0xdf, 0xc5, 0xec, 0xcd, 0x61, 0x19, 0x8d, 0x95, 0x05, 0x6f, 0x6e, 0x89, 0xdd, 0x92, 0x8d, 0xa7, 0xcb, + 0xe3, 0x72, 0xba, 0x44, 0x62, 0x67, 0xe8, 0x16, 0xe3, 0xf3, 0xe5, 0x82, 0x26, 0x78, 0xb6, 0xb1, 0x6a, 0xbe, 0x34, + 0x68, 0x29, 0x29, 0xc3, 0xf5, 0xb6, 0x44, 0xff, 0x7f, 0x75, 0xf1, 0x4b, 0x01, 0x5e, 0x82, 0xb1, 0x00, 0x10, 0xee, + 0xc1, 0xb4, 0x20, 0xb5, 0x51, 0x36, 0xd6, 0x69, 0x98, 0xe2, 0x22, 0x30, 0x29, 0xfd, 0x7e, 0x98, 0xb3, 0x94, 0x78, + 0xd0, 0xa1, 0x76, 0x94, 0x56, 0x0d, 0x9b, 0x39, 0xe0, 0x91, 0xd4, 0x39, 0x36, 0xf9, 0xfb, 0x78, 0x16, 0xa8, 0x81, + 0x08, 0xa2, 0xec, 0x18, 0x1f, 0x31, 0x70, 0x51, 0xa4, 0xe3, 0x76, 0xba, 0x22, 0x2e, 0xf7, 0x8f, 0x59, 0x88, 0x93, + 0x84, 0xb9, 0x66, 0xd9, 0x90, 0x55, 0x11, 0x26, 0xe8, 0xc2, 0xc0, 0x7e, 0x6d, 0xc8, 0xaa, 0xc3, 0x23, 0x88, 0xd4, + 0x6a, 0xcb, 0xb8, 0xea, 0x2a, 0xe3, 0x7b, 0x00, 0xb2, 0x66, 0x8c, 0x1d, 0xfd, 0x6d, 0x3c, 0x53, 0xdf, 0x44, 0x21, + 0x3f, 0x39, 0xfa, 0x1b, 0x24, 0x1f, 0x7f, 0x8f, 0xcc, 0x1c, 0x24, 0x37, 0x0a, 0x3a, 0x6f, 0xce, 0xba, 0x86, 0xd2, + 0xc4, 0xb5, 0x57, 0xea, 0xb5, 0x27, 0xcd, 0xda, 0x2b, 0xd0, 0x9d, 0xda, 0xf0, 0x1e, 0xca, 0x76, 0x16, 0x4c, 0xd0, + 0xd1, 0xec, 0x0e, 0x74, 0xf0, 0x4e, 0x11, 0xf4, 0x2c, 0x09, 0x8d, 0x47, 0xa8, 0x32, 0xea, 0xc5, 0x78, 0x50, 0x9d, + 0xac, 0x4b, 0xe6, 0x19, 0x30, 0xc7, 0xf6, 0x1c, 0x12, 0xc3, 0x5c, 0x1d, 0xd4, 0x29, 0x2b, 0x87, 0x39, 0x1e, 0xc0, + 0x6b, 0x26, 0x87, 0x62, 0x90, 0x6b, 0x94, 0xef, 0x0b, 0x56, 0x0c, 0xcb, 0x41, 0xae, 0xb9, 0x99, 0x69, 0x33, 0x36, + 0x6d, 0xa2, 0xc3, 0x33, 0xaf, 0xd8, 0xc9, 0xaa, 0x07, 0x7c, 0x2c, 0x78, 0x32, 0xfb, 0x9e, 0x8f, 0x0f, 0x80, 0x93, + 0xd9, 0xde, 0x46, 0x4b, 0xba, 0x89, 0x52, 0x7a, 0x13, 0xad, 0xe9, 0x32, 0xba, 0x30, 0x26, 0xc6, 0x49, 0x0d, 0xe7, + 0x00, 0xb4, 0x0a, 0x20, 0xf1, 0xd4, 0xaf, 0xf7, 0x3c, 0xa9, 0xc2, 0x25, 0x4d, 0xc1, 0x6d, 0xd8, 0xb7, 0xcf, 0x3c, + 0xf3, 0x25, 0x52, 0x5b, 0xc4, 0x58, 0xb3, 0x86, 0x8a, 0x5b, 0x6f, 0xdd, 0x47, 0xa2, 0x86, 0x9d, 0xeb, 0x62, 0x13, + 0x55, 0xc3, 0xc9, 0xb4, 0x04, 0xc4, 0xd6, 0x72, 0x38, 0x74, 0x47, 0xc8, 0xfe, 0xf1, 0xa3, 0x03, 0x3d, 0xf7, 0xa4, + 0xc5, 0xb6, 0x6d, 0xf9, 0x03, 0x43, 0x98, 0xd2, 0x2f, 0x1f, 0xf9, 0x80, 0x58, 0x71, 0x0e, 0x67, 0x23, 0x50, 0x47, + 0x2b, 0x74, 0xfa, 0x57, 0x15, 0x16, 0xfa, 0x00, 0xdf, 0xde, 0x46, 0x09, 0xdd, 0x44, 0xb9, 0x47, 0xd6, 0x96, 0x35, + 0x93, 0xd3, 0xb3, 0x2c, 0xe4, 0xed, 0x03, 0xbd, 0x5c, 0x00, 0x88, 0xd6, 0x20, 0xf6, 0xa5, 0xae, 0x47, 0xe0, 0x34, + 0x84, 0x26, 0xa1, 0x11, 0x5c, 0x55, 0x10, 0x46, 0xc0, 0x95, 0x84, 0xbf, 0xc1, 0x44, 0x05, 0xbe, 0x00, 0x17, 0x99, + 0x34, 0xcd, 0x79, 0x50, 0xfb, 0x23, 0xf9, 0xba, 0x68, 0x7b, 0xbb, 0xc2, 0x68, 0x82, 0xb1, 0x27, 0xda, 0xe7, 0x91, + 0x72, 0x14, 0x17, 0x49, 0x98, 0x8d, 0x6e, 0xd5, 0x79, 0x4e, 0xb3, 0xd1, 0x46, 0xff, 0xaa, 0xe8, 0x98, 0xfe, 0xaa, + 0x03, 0xda, 0x28, 0xe9, 0x5b, 0xc7, 0xd9, 0x80, 0xd6, 0x8b, 0xa5, 0xf1, 0xbf, 0x96, 0xa3, 0x5b, 0x2a, 0x47, 0x1b, + 0xdf, 0x92, 0x6a, 0x32, 0x2d, 0x8e, 0x05, 0x1a, 0x52, 0x75, 0x7e, 0x5f, 0x00, 0x3f, 0x57, 0x1a, 0xdf, 0x69, 0xf3, + 0xbd, 0xd7, 0xfe, 0x4d, 0x27, 0x4f, 0xa0, 0x58, 0xa2, 0x82, 0x55, 0x23, 0xb0, 0x63, 0x5f, 0xe7, 0x71, 0x61, 0x46, + 0x29, 0xa6, 0xd6, 0xa4, 0x1f, 0x03, 0x57, 0x4c, 0x7b, 0x05, 0xb8, 0x5a, 0x82, 0x93, 0x00, 0xc4, 0xd0, 0x84, 0x3d, + 0x3b, 0x86, 0xa8, 0xe7, 0xc6, 0x31, 0x4a, 0x36, 0xdc, 0x03, 0x62, 0x2d, 0xf3, 0x56, 0x2e, 0x01, 0x09, 0xbc, 0xf5, + 0x30, 0x29, 0x00, 0x63, 0xb0, 0x5c, 0x12, 0x9d, 0xc7, 0x43, 0x9f, 0x50, 0x2f, 0x34, 0xea, 0x84, 0x6c, 0x6c, 0x09, + 0x1c, 0x7f, 0x58, 0x1f, 0x02, 0xc1, 0xab, 0x3c, 0xd7, 0x5f, 0x69, 0x5d, 0x7f, 0xa9, 0xf4, 0xdc, 0xb1, 0xbc, 0xa8, + 0xd5, 0x6d, 0x6a, 0xf4, 0x02, 0x2c, 0x7c, 0xb7, 0xca, 0x3c, 0x92, 0x5b, 0x84, 0x54, 0x05, 0x56, 0xea, 0x16, 0x12, + 0xcc, 0xbf, 0x92, 0xb3, 0x55, 0x99, 0xaf, 0x1e, 0xb9, 0x57, 0xce, 0xa6, 0xa7, 0xbf, 0x21, 0x41, 0xdb, 0x74, 0xa4, + 0x79, 0xbc, 0x45, 0x87, 0xcf, 0xae, 0xb5, 0xc4, 0xdc, 0x4b, 0x54, 0x3c, 0x9f, 0x02, 0xb6, 0x7a, 0x96, 0x5d, 0x29, + 0x1f, 0xab, 0x7d, 0x1c, 0x3f, 0x73, 0xfe, 0x24, 0x55, 0x78, 0x21, 0x1a, 0x4a, 0x10, 0xf0, 0xe6, 0x30, 0x76, 0x85, + 0x2a, 0xa0, 0xa1, 0xb9, 0x81, 0xe3, 0x5c, 0x0d, 0x2b, 0x4d, 0xc0, 0xb4, 0x94, 0x47, 0x07, 0x38, 0x34, 0x79, 0xd4, + 0x6e, 0x1a, 0x56, 0x86, 0xae, 0x35, 0xfa, 0xdc, 0x56, 0x3a, 0xe3, 0xcd, 0x86, 0x1f, 0x1e, 0x0d, 0x2a, 0xfc, 0x49, + 0x9a, 0xa3, 0xd1, 0xce, 0x0d, 0x77, 0x1a, 0x81, 0x99, 0x2b, 0xb9, 0x22, 0xfb, 0xa3, 0xe4, 0xe5, 0xf7, 0xf4, 0xc2, + 0x02, 0xfa, 0xf3, 0xdf, 0x17, 0x13, 0x4e, 0x5a, 0x62, 0x42, 0xb4, 0x74, 0xd0, 0xa2, 0x83, 0x3d, 0xe5, 0x95, 0x7d, + 0x89, 0x97, 0xce, 0xf1, 0x7f, 0xae, 0xc7, 0xda, 0x57, 0x20, 0xb4, 0x3a, 0x79, 0xd8, 0x9e, 0x2c, 0x10, 0x35, 0xa0, + 0x9a, 0x5d, 0x95, 0xa3, 0x4c, 0x3b, 0x2b, 0xb2, 0x6d, 0xc8, 0x5c, 0xf7, 0xb3, 0x34, 0x6c, 0x26, 0x3b, 0x16, 0x96, + 0x19, 0x06, 0x6b, 0xa7, 0x8a, 0x3e, 0x07, 0x2d, 0x3f, 0x82, 0x67, 0x4d, 0xe5, 0x99, 0xcf, 0x66, 0x19, 0xf1, 0x02, + 0x9d, 0x73, 0x2a, 0x16, 0x4d, 0xe9, 0x58, 0xb9, 0xdb, 0x95, 0x68, 0x2c, 0x51, 0x46, 0x41, 0x50, 0xdb, 0x20, 0xec, + 0xba, 0x74, 0x4f, 0xfa, 0xb4, 0x8f, 0x4f, 0x2b, 0xd0, 0xf7, 0xf8, 0x2e, 0x03, 0x89, 0xa9, 0x27, 0x79, 0xa8, 0x1a, + 0xcd, 0xd1, 0xc9, 0xb3, 0x3c, 0xd5, 0xf8, 0xfc, 0x4a, 0x76, 0xd6, 0xbc, 0x5b, 0x8d, 0x29, 0xfe, 0x23, 0x75, 0xfb, + 0xce, 0x65, 0x68, 0xa2, 0xbf, 0x96, 0x07, 0x2d, 0x85, 0x05, 0xc7, 0x6d, 0xe3, 0xaf, 0xdf, 0x66, 0x0e, 0x31, 0x2c, + 0x5d, 0x0e, 0x6f, 0x42, 0x87, 0xee, 0xae, 0xb2, 0x37, 0xd7, 0x47, 0xd4, 0xa9, 0x8b, 0x75, 0x1b, 0x50, 0xb2, 0xe4, + 0xdd, 0x3a, 0x3d, 0xb1, 0xd2, 0xaf, 0x87, 0xe1, 0xde, 0x3c, 0x6a, 0x76, 0x77, 0xb7, 0x9b, 0x90, 0xb6, 0x7d, 0x30, + 0xde, 0x97, 0xb0, 0x10, 0xe7, 0x1d, 0x76, 0xf0, 0x73, 0x58, 0x3d, 0xe4, 0x83, 0xdf, 0x71, 0x9c, 0x61, 0xf4, 0x33, + 0x65, 0xe8, 0xf3, 0xa2, 0x90, 0x57, 0xaa, 0x53, 0xbe, 0xd0, 0xad, 0x65, 0xea, 0xfd, 0x26, 0x7e, 0xd3, 0x0a, 0x10, + 0xe3, 0x75, 0xc5, 0x4a, 0xf1, 0x86, 0x56, 0x18, 0xd7, 0xc0, 0x6d, 0x72, 0xa8, 0xa5, 0x5a, 0x20, 0xea, 0xf2, 0x93, + 0x87, 0x3c, 0x32, 0xea, 0x4c, 0xf8, 0xee, 0x21, 0xf7, 0xa5, 0x6b, 0xfb, 0x4d, 0xfc, 0x52, 0xd3, 0x0e, 0xf7, 0x07, + 0xba, 0xa3, 0x75, 0xf7, 0x37, 0xcf, 0xe6, 0xe7, 0x91, 0xf9, 0x62, 0x80, 0xcd, 0xda, 0x67, 0x5c, 0xf6, 0x0c, 0xf7, + 0xbd, 0xe9, 0xc1, 0x58, 0x40, 0x20, 0x31, 0x43, 0x2f, 0x03, 0x17, 0xb8, 0xc0, 0x5d, 0x61, 0xc0, 0x10, 0xd7, 0xb4, + 0xe4, 0x56, 0x5b, 0xd9, 0xfa, 0xc8, 0xdb, 0xa8, 0x10, 0xac, 0xeb, 0x8e, 0x9b, 0x24, 0x87, 0xe0, 0x84, 0x2d, 0xf7, + 0xbe, 0xf6, 0xda, 0x19, 0xfe, 0x32, 0x10, 0xce, 0x2d, 0xd1, 0x33, 0x6a, 0x7b, 0xa8, 0xd5, 0xbd, 0x86, 0x57, 0xd9, + 0x44, 0x9e, 0xf5, 0x9b, 0x79, 0x69, 0xd8, 0x17, 0xbc, 0x96, 0x82, 0x43, 0x63, 0xbb, 0x15, 0x6e, 0xb1, 0x78, 0x47, + 0xab, 0x95, 0xb5, 0xb6, 0xda, 0x6b, 0xa5, 0xa2, 0x77, 0xaf, 0x39, 0x4e, 0x9c, 0xa5, 0xb0, 0xfd, 0xf0, 0xfe, 0x82, + 0x5d, 0x13, 0xc0, 0xa0, 0xc5, 0x64, 0x81, 0x12, 0x54, 0xb2, 0x56, 0xb5, 0xdb, 0x29, 0xf1, 0xcb, 0xfd, 0xaa, 0xcb, + 0x6c, 0xe7, 0xf1, 0xeb, 0x26, 0xed, 0x0b, 0x9f, 0xa3, 0x1f, 0xe6, 0x0f, 0xd6, 0x49, 0xc9, 0x19, 0xc6, 0xb5, 0xfc, + 0xff, 0x2a, 0x7a, 0x59, 0x64, 0x69, 0xb4, 0x35, 0x3c, 0x98, 0x0d, 0xb5, 0xe9, 0x43, 0x63, 0x54, 0x6e, 0xd9, 0x28, + 0x22, 0x5a, 0xdd, 0x82, 0x60, 0x46, 0x71, 0x5f, 0xa2, 0xcd, 0x2b, 0x55, 0x16, 0xde, 0xe1, 0x0b, 0x1b, 0xbd, 0x61, + 0x7b, 0x42, 0x28, 0xdf, 0x3f, 0x2d, 0xcc, 0xaa, 0xa5, 0xa2, 0xc1, 0x76, 0x09, 0xef, 0x62, 0x54, 0xe9, 0x27, 0x4c, + 0xb6, 0x2c, 0x98, 0xea, 0xff, 0x8f, 0x45, 0x96, 0xb6, 0x29, 0x3a, 0x30, 0x9d, 0x4d, 0x9f, 0x4e, 0xba, 0xc5, 0x75, + 0x06, 0x2c, 0x22, 0xd8, 0x52, 0xe1, 0x78, 0x94, 0xda, 0x0d, 0x12, 0x26, 0x82, 0x9b, 0xa8, 0x97, 0x1d, 0x2d, 0x53, + 0xb2, 0x2a, 0xe0, 0xf9, 0x95, 0xab, 0x4c, 0xc7, 0xd1, 0xd0, 0xef, 0x9f, 0xa5, 0x26, 0xf4, 0x2b, 0xf5, 0x52, 0x15, + 0xe7, 0x61, 0x54, 0x1d, 0x2a, 0x8c, 0xd1, 0x92, 0xa6, 0x70, 0x0c, 0x66, 0x17, 0x61, 0x8a, 0x97, 0xb3, 0x6d, 0xc2, + 0xbe, 0x62, 0x20, 0x97, 0xda, 0xa0, 0x5e, 0x53, 0xa2, 0x35, 0x6b, 0x6f, 0xe6, 0x94, 0xd0, 0x0b, 0x56, 0xfa, 0x77, + 0xa1, 0x35, 0x08, 0x14, 0x65, 0x33, 0x65, 0xba, 0xd1, 0xed, 0xbc, 0xa0, 0x09, 0x2d, 0xe8, 0x8a, 0xd4, 0xa0, 0xef, + 0x75, 0x72, 0x76, 0x74, 0xb2, 0x33, 0xb3, 0x1e, 0xb3, 0x62, 0x38, 0x99, 0xc6, 0x70, 0x4d, 0x8b, 0xdd, 0x35, 0x6d, + 0xd9, 0xbc, 0x71, 0x35, 0x36, 0x4e, 0x83, 0x76, 0x81, 0xb4, 0x4d, 0x73, 0xfb, 0xa9, 0xc7, 0xed, 0xaf, 0x6b, 0xb6, + 0x9c, 0xf6, 0xd6, 0xbb, 0x5d, 0x2f, 0x05, 0x1b, 0x51, 0x8f, 0x8f, 0x5f, 0x2b, 0xe9, 0xba, 0xe5, 0xf2, 0x53, 0x78, + 0xf6, 0xf8, 0xfa, 0xa5, 0x0f, 0x2e, 0x47, 0xab, 0x36, 0x77, 0xbf, 0xdc, 0x47, 0x96, 0xfb, 0xaa, 0xa1, 0xe5, 0x7a, + 0x86, 0x9a, 0xe4, 0xd9, 0x68, 0xef, 0x50, 0x0b, 0x96, 0xb3, 0x6e, 0xc2, 0x13, 0x83, 0x1d, 0x7b, 0xd5, 0xd8, 0x1c, + 0x95, 0xb9, 0x64, 0x35, 0x48, 0xa0, 0x4f, 0xf2, 0x4c, 0xd3, 0x3f, 0xca, 0x30, 0x1f, 0xdd, 0xd2, 0x1c, 0x70, 0xc5, + 0x2a, 0x7b, 0xc9, 0x20, 0x75, 0xd5, 0x5e, 0xe2, 0xca, 0x57, 0x38, 0x24, 0x5b, 0x7c, 0x32, 0x4c, 0xd5, 0x17, 0x97, + 0x3c, 0xf8, 0x7f, 0x5b, 0xb5, 0x4a, 0xcf, 0x4d, 0x72, 0xc3, 0xf1, 0xaf, 0x93, 0xb6, 0x8f, 0x89, 0x41, 0x02, 0x9e, + 0xda, 0xc5, 0x50, 0x8d, 0xaa, 0x22, 0x16, 0x65, 0x6e, 0x62, 0x8e, 0xdd, 0xd9, 0x35, 0x74, 0x50, 0x06, 0xbf, 0x6e, + 0xf8, 0xc4, 0xdc, 0x81, 0xad, 0x40, 0x47, 0x27, 0x9a, 0xcb, 0x30, 0x33, 0x97, 0x61, 0xda, 0xb5, 0x55, 0x60, 0x78, + 0xd5, 0x56, 0x49, 0x94, 0xab, 0x51, 0x8f, 0x9b, 0x59, 0x6a, 0xf6, 0x22, 0xef, 0x5e, 0x93, 0x9e, 0xc4, 0x9f, 0x2e, + 0x3d, 0x79, 0x3d, 0x0c, 0x88, 0xfc, 0x9a, 0xa5, 0xe1, 0x1a, 0x05, 0xc1, 0xa9, 0xd5, 0x0e, 0xa4, 0xf9, 0x08, 0x90, + 0xf9, 0x71, 0x1a, 0x7e, 0xd0, 0xe2, 0x1c, 0xb2, 0x55, 0x1a, 0x27, 0xb6, 0x34, 0xea, 0x21, 0xb8, 0xf3, 0x5e, 0xf1, + 0x18, 0x02, 0x1f, 0x7e, 0xc4, 0xcd, 0xa0, 0xa2, 0xdb, 0x12, 0x13, 0xa5, 0xcd, 0xa3, 0x6e, 0xf9, 0xa8, 0x21, 0x54, + 0xb2, 0x32, 0xbc, 0x04, 0xda, 0xbb, 0x27, 0x30, 0xaa, 0x9c, 0x40, 0x66, 0x58, 0x1c, 0x1e, 0x0d, 0x53, 0x25, 0x28, + 0x1a, 0xca, 0xe1, 0x12, 0xe5, 0x80, 0x98, 0x04, 0x02, 0xa3, 0x62, 0x90, 0xea, 0xca, 0xd4, 0x8b, 0x41, 0xaa, 0x6f, + 0x55, 0xa4, 0x3e, 0xcb, 0xc2, 0x8a, 0xea, 0x16, 0xd1, 0x31, 0x1d, 0x4a, 0xba, 0x34, 0x3b, 0x35, 0xd7, 0xd2, 0x0b, + 0xb5, 0x1c, 0x9f, 0xea, 0x34, 0x18, 0xc5, 0x0f, 0x2e, 0x45, 0xbf, 0x55, 0xfb, 0xd9, 0x7f, 0x8b, 0x29, 0x35, 0x62, + 0x53, 0x7b, 0x8b, 0x18, 0x56, 0xed, 0xc7, 0xac, 0xca, 0x41, 0xbb, 0x0b, 0xca, 0xc6, 0xca, 0x38, 0xcf, 0x37, 0x82, + 0x99, 0x83, 0xb6, 0xb1, 0x6a, 0xfa, 0xd0, 0x1b, 0x31, 0x6a, 0x6f, 0x4c, 0x35, 0xee, 0x09, 0xfc, 0xb4, 0x41, 0xd3, + 0xbd, 0xc8, 0x73, 0xd4, 0x23, 0xef, 0xfe, 0x67, 0x8e, 0xec, 0x4c, 0xbe, 0x88, 0x65, 0x52, 0xb7, 0x8f, 0x49, 0xb0, + 0x50, 0x75, 0x8c, 0x2e, 0xdc, 0xc8, 0x94, 0xf6, 0x73, 0x6f, 0xfa, 0x11, 0xcf, 0xe4, 0x7e, 0x3b, 0x34, 0xea, 0x4b, + 0xc3, 0x5a, 0x52, 0x44, 0x7d, 0x41, 0x6f, 0x4d, 0x75, 0x74, 0x44, 0xbd, 0x8e, 0xc0, 0xea, 0x8a, 0xb6, 0xa8, 0x01, + 0x98, 0x8c, 0x6b, 0x5b, 0x9b, 0xcf, 0xc1, 0xd4, 0x56, 0x55, 0xf0, 0x84, 0xee, 0x0b, 0xa5, 0x7b, 0x93, 0xba, 0x6e, + 0x0d, 0xb1, 0x05, 0x0c, 0x08, 0xdc, 0xe8, 0xa9, 0xe9, 0x0f, 0x9a, 0xa8, 0x00, 0x34, 0x68, 0xdc, 0xce, 0x74, 0x8e, + 0x44, 0xbf, 0x53, 0x9b, 0xb6, 0x99, 0xea, 0x55, 0xe5, 0x03, 0xa8, 0xf8, 0xb3, 0x74, 0x76, 0x61, 0x46, 0x2c, 0x80, + 0x71, 0x0f, 0x9c, 0xa9, 0xde, 0x69, 0x06, 0xd6, 0x13, 0x79, 0x9e, 0x95, 0x3c, 0x91, 0x02, 0x66, 0x44, 0x5e, 0x5d, + 0x49, 0x01, 0xc3, 0xa0, 0x06, 0x00, 0x2d, 0x9a, 0xcb, 0x68, 0xc2, 0x1f, 0xd5, 0xf4, 0xae, 0x3c, 0xfc, 0x91, 0xce, + 0xf5, 0xdd, 0xb8, 0x06, 0x43, 0xe5, 0x75, 0xc5, 0xf7, 0x32, 0x7d, 0xc7, 0x1f, 0x7b, 0x99, 0x96, 0x72, 0x5d, 0xec, + 0x65, 0x79, 0xf4, 0x1d, 0x7f, 0xa2, 0xf3, 0x1c, 0x3d, 0xae, 0x69, 0x1a, 0x6f, 0xf6, 0xb2, 0xfc, 0xfd, 0xbb, 0xc7, + 0x36, 0xcf, 0xa3, 0x71, 0x4d, 0x6f, 0x38, 0xff, 0xe4, 0x32, 0x4d, 0x74, 0x55, 0xe3, 0xc7, 0x7f, 0xb7, 0xb9, 0x1e, + 0xd7, 0xf4, 0x4a, 0x8a, 0x6a, 0xb9, 0x57, 0xd4, 0xd1, 0x77, 0x47, 0x7f, 0xe7, 0xdf, 0x99, 0xee, 0x1d, 0xd5, 0xf4, + 0xaf, 0x75, 0x5c, 0x54, 0xbc, 0xd8, 0x2b, 0xee, 0x6f, 0x7f, 0xff, 0xfb, 0x63, 0x9b, 0xf1, 0x71, 0x4d, 0x37, 0x3c, + 0xee, 0x68, 0xfb, 0xe4, 0xc9, 0x63, 0xfe, 0xb7, 0xba, 0xa6, 0xbf, 0x31, 0x3f, 0x38, 0xea, 0x69, 0xe6, 0xe9, 0xe1, + 0x73, 0xd9, 0x44, 0x0d, 0x18, 0x7a, 0x68, 0x00, 0x4b, 0x69, 0xd5, 0x34, 0x77, 0x78, 0xe5, 0x82, 0xdb, 0xf7, 0x59, + 0x9c, 0xc6, 0x2b, 0x38, 0x08, 0xb6, 0x68, 0x9c, 0x55, 0x00, 0xa7, 0x0a, 0xbc, 0x67, 0x54, 0xd2, 0xac, 0x94, 0xbf, + 0x71, 0xfe, 0x09, 0x06, 0x0d, 0x21, 0x6d, 0x54, 0x64, 0xa0, 0xb7, 0x2b, 0x1d, 0xd9, 0x08, 0xfd, 0x37, 0x9b, 0x71, + 0x70, 0x7c, 0x18, 0xbd, 0x7e, 0x3f, 0x2c, 0x98, 0x08, 0x0b, 0x42, 0xe8, 0x9f, 0x61, 0x01, 0x0e, 0x25, 0x05, 0xf3, + 0xf2, 0x19, 0xdf, 0x73, 0x6d, 0x14, 0x16, 0x82, 0xe8, 0x2e, 0xb2, 0x0f, 0xa8, 0x7a, 0xf4, 0x1d, 0xba, 0x21, 0x5e, + 0x56, 0x58, 0x30, 0xb4, 0xaa, 0x81, 0x19, 0x82, 0xe2, 0x5f, 0xf3, 0x50, 0x82, 0x4f, 0x3c, 0xc0, 0x47, 0x8f, 0xc9, + 0x8c, 0xab, 0x6b, 0xed, 0xdb, 0x8b, 0xb0, 0xa0, 0x81, 0x6e, 0x3b, 0x04, 0x1d, 0x88, 0xfc, 0x17, 0xe0, 0x29, 0x30, + 0xf0, 0x61, 0x61, 0xd7, 0x1d, 0x78, 0x3e, 0xbf, 0x19, 0xd6, 0xd1, 0x85, 0x1f, 0xfd, 0xcd, 0xba, 0xb0, 0x67, 0x64, + 0x2a, 0x8f, 0xcb, 0xe1, 0x64, 0x3a, 0x18, 0x48, 0x17, 0xc7, 0xed, 0x34, 0x9b, 0xff, 0x36, 0x97, 0x8b, 0x05, 0xea, + 0xbe, 0x71, 0x5e, 0x67, 0xfa, 0x6f, 0xa4, 0x9d, 0x0f, 0x5e, 0x9f, 0xfe, 0xeb, 0xec, 0xc3, 0xe9, 0x0b, 0x70, 0x3e, + 0xf8, 0xf8, 0xfc, 0xc7, 0xe7, 0xef, 0x55, 0x70, 0x77, 0x35, 0xe7, 0xfd, 0xbe, 0x93, 0xfa, 0x84, 0x7c, 0x58, 0x91, + 0xc3, 0x30, 0x7e, 0x58, 0x28, 0xa3, 0x07, 0x72, 0xcc, 0x2c, 0x14, 0x32, 0x54, 0x51, 0xdb, 0xdf, 0xe5, 0x70, 0xe2, + 0x81, 0x59, 0x5c, 0x37, 0x44, 0xb8, 0x7e, 0xcb, 0x6d, 0x90, 0x35, 0x79, 0xe2, 0xf5, 0x83, 0x93, 0xa9, 0x74, 0x6c, + 0x61, 0xc1, 0xa0, 0x6c, 0x68, 0xd3, 0x69, 0x36, 0x2f, 0x16, 0xb6, 0x5d, 0x6e, 0x81, 0x8c, 0xd2, 0xec, 0xe2, 0x22, + 0x54, 0xd0, 0xd5, 0x27, 0xa0, 0x01, 0x30, 0x8d, 0x2a, 0x5c, 0x8b, 0xf8, 0xcc, 0x2f, 0x3f, 0x1a, 0x7b, 0xcd, 0xbb, + 0x41, 0xdd, 0x93, 0x69, 0x56, 0xd5, 0x18, 0xd0, 0xc1, 0x84, 0x72, 0x37, 0xe8, 0x26, 0x98, 0x8c, 0x6a, 0xcb, 0x6f, + 0xf3, 0x6a, 0x61, 0x9a, 0xe3, 0x86, 0xa1, 0xf2, 0x4a, 0xbe, 0x90, 0x0d, 0x44, 0x06, 0x92, 0x61, 0xd8, 0xa3, 0x31, + 0x8a, 0xd4, 0x0f, 0xf6, 0xbd, 0xe3, 0xb7, 0xb9, 0x84, 0x68, 0x8a, 0x19, 0x48, 0xe7, 0x9f, 0x0b, 0xe5, 0x5c, 0x2e, + 0x19, 0x9f, 0x8b, 0xc5, 0x09, 0xb8, 0x9d, 0xcf, 0xc5, 0x22, 0xc2, 0xa0, 0x7c, 0x19, 0xc4, 0x2a, 0x01, 0xbb, 0x17, + 0x07, 0x3d, 0xd2, 0x09, 0x6d, 0x60, 0x37, 0x90, 0x64, 0x83, 0xd2, 0xae, 0x34, 0x44, 0xb9, 0x53, 0x1e, 0x6d, 0x10, + 0x79, 0x88, 0x55, 0xf3, 0xaa, 0xed, 0xc9, 0x66, 0x2e, 0x26, 0xb8, 0xca, 0x62, 0x26, 0xa7, 0xf1, 0x31, 0x2b, 0xa6, + 0x31, 0x94, 0x12, 0xa7, 0x69, 0x18, 0xd3, 0x09, 0x15, 0x84, 0x24, 0x8c, 0xcf, 0xe3, 0x05, 0x4d, 0x50, 0x4a, 0x10, + 0x42, 0xc8, 0x8f, 0x11, 0xda, 0xe6, 0xc0, 0x92, 0xb7, 0xdb, 0xcf, 0x53, 0xf1, 0xed, 0x19, 0x2e, 0xa3, 0x22, 0x74, + 0x8b, 0xce, 0x1a, 0xfe, 0x8d, 0xa8, 0xa0, 0x31, 0x56, 0x0c, 0x41, 0xc0, 0x0b, 0x8c, 0x4a, 0x58, 0x90, 0x98, 0x55, + 0x10, 0x45, 0xa0, 0x9c, 0xc7, 0x0b, 0x56, 0xd0, 0xa6, 0xcd, 0x69, 0xac, 0x4d, 0x82, 0x7a, 0x0e, 0x4b, 0xed, 0x40, + 0x2a, 0x15, 0x62, 0x8f, 0xcf, 0x44, 0xf4, 0x49, 0x1b, 0x1a, 0x00, 0x0a, 0x94, 0x92, 0x8b, 0xdf, 0x7c, 0xbd, 0x87, + 0x9b, 0x82, 0xfe, 0x67, 0x5b, 0x13, 0xed, 0x2c, 0x57, 0x87, 0xde, 0x7c, 0x41, 0xe3, 0x3c, 0x87, 0x50, 0x6c, 0x06, + 0x81, 0x5c, 0x64, 0x15, 0x44, 0xb4, 0xd8, 0x04, 0x26, 0x24, 0x1c, 0xb4, 0xe9, 0x17, 0x48, 0x6d, 0x88, 0xc9, 0x95, + 0x27, 0x06, 0x76, 0x5b, 0x25, 0x08, 0x38, 0xd2, 0xf3, 0xec, 0x73, 0x13, 0x63, 0x4d, 0x53, 0x33, 0x13, 0x6f, 0x43, + 0x21, 0x1a, 0xb4, 0x20, 0x9a, 0xc1, 0xfb, 0xe7, 0x8a, 0xe3, 0x55, 0x07, 0x7e, 0xc0, 0x3b, 0x17, 0x67, 0x5e, 0xcd, + 0x3c, 0x22, 0xa7, 0x3e, 0xcf, 0x11, 0xfd, 0x92, 0x87, 0xd5, 0x48, 0x27, 0x63, 0xac, 0x24, 0x0e, 0x7a, 0x1b, 0x2c, + 0x98, 0x13, 0xba, 0xe2, 0xa1, 0xe5, 0xe3, 0x5f, 0x20, 0x93, 0x51, 0x52, 0x63, 0x45, 0x57, 0x5a, 0x8c, 0x38, 0xaf, + 0x61, 0x96, 0x26, 0x2b, 0xba, 0x58, 0x68, 0xd2, 0x2c, 0x94, 0x69, 0x80, 0x4f, 0xa0, 0xc5, 0xc8, 0x3d, 0xd4, 0xb4, + 0x81, 0xd0, 0xb0, 0x3f, 0x04, 0x7c, 0xe4, 0x1e, 0x3a, 0xfc, 0xff, 0x3c, 0xbb, 0x40, 0xa4, 0xbd, 0x4b, 0x13, 0x19, + 0x8f, 0xd4, 0x0d, 0x1c, 0x14, 0xe3, 0x63, 0xdf, 0x4c, 0xfc, 0xca, 0x19, 0xbd, 0x4f, 0x2a, 0xdf, 0xe1, 0x83, 0xe5, + 0x8f, 0x37, 0x35, 0xb3, 0x32, 0x82, 0xf5, 0xb0, 0xdb, 0xe1, 0x82, 0x68, 0xbb, 0x00, 0x52, 0xcf, 0x78, 0xb5, 0xf0, + 0x8d, 0x57, 0xe3, 0x3b, 0x8c, 0x57, 0x9d, 0xd5, 0x57, 0x98, 0x93, 0x2d, 0xea, 0xb3, 0x94, 0x3c, 0x3f, 0x47, 0x99, + 0x60, 0xd3, 0xe5, 0xac, 0xa4, 0x2a, 0x95, 0xd0, 0x5e, 0xec, 0x67, 0x8c, 0x6f, 0x09, 0xc6, 0x59, 0x71, 0x18, 0x09, + 0x54, 0xa5, 0x92, 0x3a, 0xec, 0x15, 0xa0, 0x1e, 0x83, 0xf7, 0x06, 0x43, 0xd4, 0xc8, 0xd8, 0x4d, 0x1b, 0x08, 0x0d, + 0x8d, 0xf5, 0x68, 0xcf, 0x5a, 0x8f, 0xee, 0x76, 0x95, 0xf1, 0xb7, 0x93, 0xeb, 0x22, 0x41, 0x54, 0x61, 0x35, 0x9a, + 0x00, 0x6f, 0x9a, 0xd8, 0xdb, 0x92, 0x53, 0x5a, 0x60, 0xf8, 0xec, 0x3f, 0xc3, 0xd2, 0xa9, 0x24, 0x4a, 0x32, 0x2b, + 0xa3, 0x81, 0x3b, 0x07, 0x9f, 0xc5, 0x15, 0xac, 0x01, 0x88, 0xe4, 0x88, 0x1e, 0xae, 0x7f, 0x86, 0xd2, 0x65, 0x96, + 0x64, 0x26, 0x21, 0x33, 0x17, 0x69, 0x3b, 0xeb, 0x60, 0xe2, 0x4c, 0x6a, 0xbd, 0xb1, 0x90, 0x43, 0x83, 0xfc, 0x00, + 0xca, 0x10, 0x87, 0x4f, 0x3e, 0x98, 0x50, 0xa9, 0x42, 0xa9, 0x36, 0xba, 0xd9, 0x0d, 0xbc, 0xf2, 0x31, 0xbb, 0xe2, + 0x65, 0x15, 0x5f, 0xad, 0x8c, 0x25, 0x31, 0x67, 0x77, 0xb9, 0xed, 0x51, 0x61, 0x5e, 0xbd, 0x79, 0xfe, 0xe3, 0x69, + 0xe3, 0xd5, 0x3e, 0xe2, 0x68, 0x08, 0xb6, 0x15, 0x63, 0x8c, 0xde, 0xe2, 0xd3, 0x60, 0xa2, 0x5c, 0x23, 0xd0, 0xbb, + 0x14, 0xf4, 0xdb, 0x5f, 0xeb, 0x09, 0x78, 0xc5, 0xf5, 0xf2, 0x4b, 0x3e, 0x01, 0x96, 0xa8, 0xd0, 0xb3, 0xc2, 0xdc, + 0xac, 0xcc, 0xee, 0xec, 0x56, 0x64, 0xa6, 0x5d, 0x69, 0x64, 0x20, 0x5e, 0x6d, 0x87, 0xb1, 0x70, 0xe9, 0x9a, 0x6e, + 0x07, 0xbb, 0x5a, 0x7a, 0x96, 0xc8, 0xbb, 0x5d, 0x09, 0x1d, 0xb2, 0x03, 0xee, 0xbd, 0x8c, 0x6f, 0xe1, 0x65, 0xe9, + 0x75, 0xb3, 0x19, 0x3c, 0x01, 0xcc, 0x84, 0x0b, 0x67, 0x59, 0x1c, 0x33, 0x91, 0x84, 0x2a, 0x36, 0x57, 0x43, 0xe4, + 0xad, 0x08, 0xad, 0xd9, 0x5f, 0xa1, 0x18, 0x81, 0xdd, 0xc9, 0x87, 0x4f, 0xd9, 0x6a, 0xb6, 0x06, 0xd4, 0xfc, 0xab, + 0x4c, 0x00, 0xcd, 0xb5, 0x6b, 0xc1, 0x36, 0x85, 0x36, 0xd7, 0xf5, 0xd3, 0x78, 0x15, 0x27, 0xa0, 0xba, 0x01, 0x6f, + 0x91, 0x6b, 0x2d, 0xba, 0x32, 0xe8, 0xa2, 0xf4, 0x9e, 0x72, 0x2c, 0x29, 0x74, 0xf4, 0xbd, 0x27, 0xd4, 0xb9, 0x67, + 0x00, 0x97, 0x34, 0x6a, 0x9e, 0x6a, 0x29, 0x63, 0x01, 0xb0, 0xd0, 0xc1, 0x4c, 0x91, 0xad, 0xe8, 0xc6, 0x60, 0x52, + 0xc0, 0x5b, 0x03, 0xfc, 0x21, 0xb2, 0x4a, 0xdd, 0x15, 0xcb, 0xb0, 0xf4, 0xec, 0xaf, 0xfb, 0xfd, 0xd8, 0xb3, 0xbf, + 0x5e, 0x69, 0x5a, 0x17, 0xb7, 0x1b, 0x40, 0x6a, 0x0c, 0x20, 0x72, 0xaa, 0x07, 0xc2, 0x44, 0x14, 0x6b, 0xfa, 0xfe, + 0x9d, 0x9a, 0x2c, 0x0a, 0x84, 0x7e, 0xaf, 0x5e, 0x4f, 0x4a, 0x02, 0x3a, 0xb5, 0x8a, 0x9d, 0x0c, 0xb4, 0xd9, 0x07, + 0x04, 0x44, 0xf5, 0x33, 0xb2, 0xf9, 0x42, 0x39, 0x17, 0xab, 0xf0, 0xe1, 0x63, 0x0a, 0x01, 0x85, 0x3b, 0x6a, 0x74, + 0xde, 0x86, 0x48, 0xa0, 0xac, 0x50, 0xc4, 0x9a, 0x17, 0x6b, 0x49, 0xc8, 0x7c, 0xbc, 0x40, 0xc1, 0x95, 0x03, 0x76, + 0xe5, 0x6c, 0x32, 0x2c, 0x23, 0xce, 0xc2, 0xbb, 0xbf, 0x99, 0x2c, 0x08, 0x6a, 0xae, 0xfc, 0x40, 0x8e, 0x7b, 0x99, + 0x1a, 0x7b, 0xaa, 0x51, 0x83, 0x60, 0x32, 0x82, 0xc0, 0x70, 0xc3, 0xaf, 0xf8, 0xf8, 0x68, 0x41, 0x40, 0x45, 0x66, + 0xcd, 0x42, 0xcc, 0x8b, 0xe3, 0x47, 0x80, 0x1a, 0x33, 0x3a, 0x7a, 0x32, 0xe5, 0x0c, 0x0e, 0x51, 0x3a, 0x06, 0x19, + 0xad, 0x80, 0xdf, 0x42, 0xfd, 0x6e, 0x9d, 0xf8, 0x3e, 0xf4, 0xab, 0xa0, 0x17, 0x31, 0x30, 0x1c, 0xd1, 0xe4, 0x30, + 0xe4, 0x83, 0xc9, 0x00, 0xb4, 0x25, 0xde, 0xee, 0x6b, 0x69, 0xc5, 0xcd, 0xe9, 0xd2, 0xe9, 0xfe, 0x49, 0x9b, 0x20, + 0x89, 0x54, 0xb2, 0x52, 0x11, 0x03, 0x08, 0x65, 0xa9, 0xb6, 0xc9, 0x1a, 0x2c, 0x2b, 0xcc, 0x92, 0xe6, 0x06, 0x25, + 0x71, 0x7f, 0x33, 0x70, 0x8c, 0x9a, 0x75, 0x1a, 0x96, 0x2d, 0x37, 0x6a, 0x80, 0xcf, 0x49, 0x58, 0x61, 0x6f, 0x38, + 0x33, 0xe9, 0x9d, 0xe9, 0x70, 0x75, 0xcc, 0xd9, 0x6b, 0x8e, 0x60, 0x1c, 0x09, 0xde, 0x78, 0xe8, 0x92, 0x69, 0xa8, + 0xc8, 0x94, 0x71, 0x30, 0xed, 0x01, 0xee, 0x3d, 0x07, 0xe3, 0x30, 0x36, 0xa8, 0x2c, 0xa9, 0x4f, 0xbd, 0xbb, 0x10, + 0x08, 0xd2, 0x5a, 0x2f, 0xf3, 0x19, 0x9e, 0x9e, 0x11, 0xca, 0xfe, 0x90, 0xc3, 0x17, 0x60, 0x47, 0x41, 0x4e, 0x26, + 0xfc, 0xc9, 0xc3, 0xfd, 0x40, 0x55, 0x7c, 0x10, 0x1c, 0xc4, 0x22, 0x3d, 0x08, 0x06, 0x02, 0x7e, 0x15, 0xfc, 0xa0, + 0x92, 0xf2, 0xe0, 0x22, 0x2e, 0x0e, 0xe2, 0x55, 0x5c, 0x54, 0x07, 0x37, 0x59, 0xb5, 0x3c, 0x30, 0x1d, 0x02, 0x68, + 0xde, 0x60, 0x10, 0x0f, 0x82, 0x83, 0x60, 0x50, 0x98, 0xa9, 0x5d, 0xb1, 0xb2, 0x71, 0x9c, 0x99, 0x10, 0x65, 0x41, + 0x33, 0x40, 0x58, 0xe3, 0x34, 0x00, 0x3e, 0x75, 0xcd, 0x52, 0x7a, 0x81, 0xe1, 0x06, 0xc4, 0x74, 0x0d, 0x7d, 0x00, + 0x1e, 0x79, 0x4d, 0x63, 0x58, 0x02, 0x17, 0x83, 0x01, 0xb9, 0x80, 0xc8, 0x05, 0x6b, 0x6a, 0x83, 0x38, 0x84, 0x6b, + 0x65, 0xa7, 0xbd, 0x0f, 0xcc, 0xb4, 0xdb, 0x01, 0xa2, 0xf2, 0x84, 0xf4, 0xfb, 0xf6, 0x1b, 0xea, 0x5f, 0xb0, 0x97, + 0x60, 0x7f, 0x55, 0x54, 0x61, 0x2e, 0x95, 0xe6, 0xfb, 0x92, 0x9d, 0x0c, 0x54, 0xc4, 0xe1, 0x3d, 0x47, 0x8a, 0x36, + 0x2a, 0x97, 0x65, 0x4f, 0x96, 0x0d, 0x5f, 0x89, 0x2b, 0xee, 0xfc, 0xb8, 0x2a, 0x29, 0xf3, 0x2a, 0x5b, 0x29, 0xf6, + 0x6f, 0xc6, 0x35, 0xf7, 0x07, 0xd6, 0x9f, 0xcd, 0x57, 0x70, 0x6d, 0xf5, 0xde, 0x35, 0xb9, 0x46, 0xe4, 0x2c, 0xa1, + 0x5c, 0x52, 0xdb, 0x3c, 0xbc, 0xa5, 0xef, 0xf3, 0xab, 0x6f, 0x33, 0x9d, 0xc6, 0x67, 0x15, 0x16, 0x2e, 0x44, 0x2b, + 0x82, 0x43, 0x43, 0x2e, 0x9a, 0x47, 0x80, 0xb9, 0xf6, 0xd9, 0x0a, 0x0a, 0x52, 0x9f, 0x55, 0xe8, 0xdd, 0x0a, 0x09, + 0x2f, 0x34, 0xbb, 0x74, 0x3f, 0x90, 0x32, 0x6e, 0x0f, 0x2d, 0x61, 0xd2, 0xf2, 0x22, 0xbc, 0xf7, 0x9a, 0x9b, 0xdc, + 0xb3, 0x10, 0xa3, 0x17, 0x79, 0x76, 0x02, 0xc6, 0xba, 0x4b, 0x76, 0x36, 0x3c, 0xf1, 0x1b, 0x9e, 0xb3, 0x16, 0x8d, + 0xa6, 0x4b, 0x96, 0xf4, 0xfb, 0x31, 0x98, 0x78, 0xa7, 0x2c, 0x87, 0x5f, 0xf9, 0x82, 0xae, 0x19, 0x60, 0x8a, 0xd1, + 0x0b, 0x48, 0x48, 0x11, 0x89, 0x64, 0xad, 0x4e, 0x92, 0x2f, 0x74, 0x17, 0x80, 0xd1, 0x2f, 0x66, 0x69, 0xb4, 0xbc, + 0xd3, 0xcc, 0x02, 0xc9, 0x33, 0xf4, 0x5d, 0x07, 0xdb, 0x1b, 0xfb, 0x20, 0xe5, 0xfc, 0x58, 0x4c, 0x07, 0x03, 0x4e, + 0x34, 0xdc, 0x78, 0xa9, 0xc4, 0xb5, 0xba, 0xc5, 0x1d, 0xc3, 0x58, 0xea, 0xdb, 0x22, 0x06, 0x07, 0xec, 0xa2, 0x95, + 0xdd, 0x3e, 0xc0, 0xbe, 0x72, 0xbc, 0x4b, 0x95, 0xdd, 0xe9, 0x31, 0xd3, 0x5c, 0xb6, 0x9a, 0x74, 0x52, 0x71, 0x37, + 0x91, 0x6f, 0x72, 0x07, 0x5d, 0x2e, 0xc7, 0x9a, 0xb7, 0x1c, 0x80, 0x8a, 0x7e, 0xa4, 0xa8, 0xee, 0x57, 0x38, 0xc2, + 0xdc, 0x5b, 0xb7, 0xf9, 0xe4, 0xd0, 0x14, 0x38, 0x44, 0x9e, 0xb4, 0xd1, 0x14, 0xd0, 0xbd, 0x8b, 0x87, 0x5d, 0xfd, + 0xb6, 0x74, 0x17, 0x28, 0xd1, 0x5e, 0xc5, 0x0d, 0x3f, 0x26, 0xea, 0x74, 0xa6, 0x0d, 0xa1, 0x7f, 0x65, 0xc4, 0xfd, + 0xa5, 0x71, 0x15, 0x6f, 0x7a, 0x97, 0xcf, 0x38, 0xd4, 0xd9, 0x0d, 0xa1, 0x00, 0x5c, 0xb5, 0xa7, 0x53, 0x37, 0x86, + 0xf4, 0x4a, 0x89, 0x6e, 0x83, 0x83, 0xdd, 0xe9, 0x33, 0x8e, 0xa2, 0x1f, 0xa3, 0x46, 0xbe, 0x89, 0xc4, 0x43, 0x39, + 0x88, 0x1f, 0x16, 0x74, 0x19, 0x89, 0x87, 0xc5, 0x20, 0x7e, 0x28, 0xeb, 0x7a, 0xff, 0x5c, 0xb9, 0xbb, 0x8f, 0xc8, + 0xb3, 0xee, 0xed, 0xa5, 0x12, 0x36, 0x06, 0x9e, 0x5d, 0x0b, 0x08, 0xa7, 0xe0, 0x89, 0x6c, 0x2d, 0x7d, 0xe8, 0xdc, + 0xee, 0x63, 0xcb, 0x24, 0x41, 0xd0, 0xf3, 0x36, 0x9b, 0x44, 0xb1, 0xb3, 0xcd, 0xa3, 0x0f, 0xa7, 0x40, 0x42, 0xb7, + 0xdb, 0x66, 0x5d, 0xad, 0x01, 0xc5, 0x34, 0x1c, 0xf3, 0xc3, 0x62, 0x74, 0xe3, 0xbb, 0xeb, 0x1f, 0x16, 0xa3, 0x25, + 0x19, 0x4e, 0xcc, 0xe4, 0xc7, 0x27, 0xe3, 0x59, 0x1c, 0x4d, 0xea, 0x8e, 0xd3, 0x42, 0xe3, 0x9f, 0x7a, 0xb7, 0x50, + 0x04, 0x4e, 0xc5, 0x08, 0x8e, 0x9c, 0x0a, 0xe5, 0xa4, 0xd4, 0xc0, 0xf0, 0x3f, 0xa8, 0xf6, 0xb4, 0x69, 0xaf, 0xe3, + 0x2a, 0x59, 0x66, 0xe2, 0x52, 0x87, 0x0f, 0xd7, 0xd1, 0xc5, 0x6d, 0x40, 0x3b, 0xef, 0x32, 0xed, 0xf8, 0x75, 0xd2, + 0xa0, 0x27, 0xae, 0x66, 0x06, 0xdc, 0xba, 0x1f, 0xa1, 0x19, 0x02, 0xa3, 0xe5, 0xf9, 0x3b, 0xc4, 0xdc, 0xfe, 0x55, + 0xd9, 0xfc, 0x2a, 0xda, 0xe7, 0xc8, 0x48, 0xd9, 0x26, 0x23, 0x15, 0x18, 0x61, 0x4a, 0x91, 0xc4, 0x55, 0x08, 0x81, + 0xec, 0xbf, 0xa6, 0xb8, 0x16, 0x4b, 0xef, 0x35, 0x08, 0x13, 0x6c, 0x17, 0xb4, 0x5f, 0xdd, 0xde, 0x6d, 0xa5, 0xc5, + 0x1e, 0xa9, 0xef, 0x73, 0x67, 0xbb, 0xa2, 0xc9, 0xdf, 0xd7, 0x0d, 0x68, 0x03, 0x88, 0xf2, 0xae, 0x3e, 0x2a, 0x81, + 0x93, 0x11, 0x37, 0x94, 0x18, 0xbd, 0xa0, 0xab, 0x13, 0xb9, 0x67, 0xa7, 0xe6, 0x4d, 0xc5, 0x4c, 0xc5, 0x95, 0x6f, + 0xf6, 0xcc, 0x7f, 0x30, 0x14, 0x54, 0x82, 0x81, 0xb7, 0x39, 0xe3, 0xd1, 0x81, 0xee, 0xc6, 0xe8, 0xb4, 0x60, 0xb3, + 0xa0, 0x2e, 0xeb, 0xa6, 0x8d, 0x07, 0x8d, 0x38, 0x28, 0x8a, 0x55, 0xa1, 0x46, 0xc2, 0x13, 0x81, 0x80, 0x29, 0xbb, + 0xe2, 0x91, 0x11, 0xd4, 0xf4, 0x26, 0x14, 0x36, 0x14, 0xfc, 0x55, 0xa2, 0x9a, 0xde, 0x84, 0x36, 0x99, 0x38, 0xcd, + 0x20, 0x82, 0x19, 0xb1, 0xdd, 0x6f, 0x01, 0x6d, 0x6e, 0xcd, 0x68, 0x5b, 0xd7, 0x56, 0x5b, 0x85, 0x5c, 0x52, 0xa4, + 0x2c, 0xff, 0x9d, 0x9a, 0x0a, 0x4a, 0x6a, 0xb9, 0xe8, 0x4d, 0x9a, 0x2e, 0x7a, 0x3c, 0x33, 0x92, 0x40, 0xe5, 0x96, + 0x3b, 0x46, 0x7f, 0x08, 0x0b, 0x3c, 0x62, 0xe2, 0xc4, 0x82, 0xb9, 0xd5, 0x09, 0xcb, 0xe6, 0x62, 0x31, 0x5a, 0x49, + 0x08, 0x1b, 0x7c, 0xcc, 0xb2, 0x79, 0xa9, 0x1f, 0x42, 0x5f, 0x58, 0xfa, 0x00, 0xec, 0x62, 0x83, 0x95, 0x2c, 0x03, + 0xf0, 0xbd, 0xa0, 0xdb, 0x95, 0x2c, 0x23, 0xa9, 0xba, 0x1f, 0xd7, 0x58, 0x82, 0x4a, 0x2b, 0x54, 0x5a, 0x52, 0x63, + 0x41, 0xe0, 0xab, 0xaa, 0xcb, 0x87, 0x64, 0x57, 0x81, 0x7a, 0xea, 0xa8, 0x01, 0xa7, 0x40, 0x55, 0x81, 0x05, 0x49, + 0x50, 0x19, 0xba, 0x2a, 0x30, 0xad, 0xc0, 0x34, 0x53, 0x85, 0x8b, 0x32, 0x3b, 0x94, 0x66, 0xbd, 0xe4, 0xb3, 0x78, + 0x10, 0x26, 0xc3, 0x98, 0x3c, 0x44, 0xa8, 0xfd, 0xc3, 0x3c, 0x8a, 0xb5, 0x5c, 0xf2, 0xd2, 0xf9, 0xc5, 0xdf, 0x7c, + 0xc1, 0x5e, 0xf7, 0x0c, 0x83, 0x05, 0x38, 0x4b, 0xdb, 0xab, 0x4c, 0xbc, 0x93, 0xad, 0xe0, 0x38, 0x98, 0x45, 0x39, + 0xac, 0x7a, 0x72, 0x44, 0x73, 0x91, 0x6b, 0xef, 0x22, 0x44, 0x0e, 0x32, 0x7b, 0x0c, 0xb0, 0x1b, 0xe1, 0xeb, 0xd0, + 0xda, 0xdc, 0xea, 0x0a, 0xf1, 0x37, 0x4a, 0x24, 0x7e, 0x92, 0xf2, 0xd3, 0x7a, 0xa5, 0x72, 0x55, 0x06, 0x8f, 0x55, + 0x37, 0x83, 0x67, 0xda, 0xf7, 0x58, 0xfb, 0xb7, 0xb6, 0x9b, 0xe3, 0xbd, 0x07, 0x0f, 0x5a, 0xff, 0x5b, 0x4f, 0x42, + 0x68, 0xaf, 0x9c, 0xa4, 0xee, 0xa8, 0xd1, 0x33, 0x93, 0x35, 0xa2, 0x12, 0xa6, 0x76, 0xa7, 0x72, 0x0c, 0xd4, 0x74, + 0x00, 0xd7, 0x12, 0x35, 0x41, 0x4f, 0x0a, 0x36, 0x86, 0x23, 0xce, 0xe2, 0xa0, 0x1d, 0xc7, 0x28, 0x5e, 0xce, 0x95, + 0x78, 0x39, 0x3f, 0x61, 0x1c, 0xa0, 0xb5, 0x00, 0xa9, 0x5e, 0xc3, 0x7e, 0xe6, 0x0a, 0x16, 0xd8, 0xdc, 0xf9, 0x8e, + 0x2c, 0x90, 0x21, 0x4e, 0x36, 0xc7, 0xc9, 0x1e, 0xd7, 0x7a, 0xee, 0x05, 0x3e, 0x4e, 0xea, 0x85, 0x57, 0x57, 0xd9, + 0xae, 0x6b, 0xc9, 0xca, 0x79, 0x31, 0x98, 0x40, 0x50, 0x96, 0x72, 0x5e, 0x0c, 0x27, 0x0b, 0x9a, 0xc3, 0x8f, 0x45, + 0x03, 0x1d, 0x62, 0x39, 0x48, 0xe0, 0xd2, 0xd9, 0x63, 0xc0, 0x1b, 0x4a, 0x2d, 0xee, 0xc6, 0x3a, 0x72, 0xac, 0xa3, + 0x38, 0x0c, 0x63, 0xc0, 0x95, 0x75, 0x02, 0xef, 0xbb, 0xaf, 0x8f, 0x4d, 0x40, 0x56, 0xed, 0x0a, 0xaf, 0x46, 0xb9, + 0xeb, 0x4a, 0xa3, 0x2f, 0x29, 0x3d, 0xe1, 0x05, 0x4f, 0x25, 0xbb, 0x5d, 0xcf, 0xc0, 0xd9, 0x12, 0x0f, 0x89, 0x77, + 0x8c, 0xe8, 0xc5, 0xb4, 0x91, 0x99, 0x13, 0x38, 0xb3, 0xdd, 0x65, 0x1b, 0xf3, 0x63, 0x07, 0x38, 0x58, 0x04, 0x21, + 0x71, 0x43, 0x18, 0x26, 0x76, 0x52, 0x0e, 0xb5, 0x10, 0xae, 0x6b, 0xe1, 0x75, 0x9c, 0x96, 0x31, 0xb8, 0x48, 0x6b, + 0xdb, 0xc4, 0x3b, 0xe8, 0xba, 0xe7, 0xc7, 0xdc, 0xea, 0x18, 0x6d, 0x21, 0xfd, 0x76, 0x74, 0xfa, 0xc0, 0x61, 0x00, + 0x9a, 0x1e, 0xcc, 0xaa, 0xf6, 0x99, 0xc4, 0xcd, 0x69, 0x27, 0x08, 0x89, 0x40, 0x14, 0xa5, 0x33, 0xc2, 0xf4, 0xef, + 0x35, 0x97, 0x55, 0xb4, 0xba, 0x97, 0x67, 0x0e, 0x79, 0x16, 0x7a, 0xdb, 0x83, 0x56, 0xcd, 0xdd, 0x60, 0x9c, 0xb8, + 0xdd, 0xde, 0xf9, 0x7f, 0xcb, 0xba, 0xb6, 0x5a, 0x23, 0x1e, 0xb6, 0xab, 0x1f, 0x34, 0xf6, 0x6a, 0x4f, 0xc5, 0x80, + 0xb9, 0x94, 0xde, 0x19, 0x55, 0xf2, 0x22, 0xe3, 0x25, 0x9e, 0x54, 0x97, 0x0d, 0x1f, 0xef, 0x9b, 0x6c, 0x64, 0x1e, + 0xc8, 0x14, 0x10, 0xcf, 0x3f, 0xa4, 0x46, 0x7d, 0x9c, 0xa2, 0x04, 0xfc, 0x9d, 0x8e, 0x6f, 0x44, 0x5f, 0xdb, 0x17, + 0x97, 0xbc, 0x7a, 0x7b, 0x23, 0xcc, 0x8b, 0x67, 0x56, 0xe7, 0x4f, 0x9f, 0x16, 0x3e, 0x74, 0x38, 0x6a, 0xef, 0xa0, + 0xc8, 0x92, 0x89, 0x93, 0x89, 0x91, 0xb5, 0x89, 0xd9, 0x6b, 0x05, 0x17, 0x13, 0x55, 0xe8, 0x59, 0x67, 0x4f, 0x98, + 0x02, 0xf4, 0x8d, 0x63, 0x54, 0x32, 0x86, 0x05, 0x03, 0x75, 0x9a, 0x12, 0xa2, 0x87, 0x62, 0x86, 0xf1, 0x8a, 0x01, + 0x14, 0xa6, 0x50, 0x20, 0x8a, 0xce, 0x3e, 0x1c, 0x68, 0x42, 0xbf, 0xff, 0x21, 0xd5, 0x19, 0x68, 0x59, 0x4f, 0x0b, + 0x10, 0xd5, 0x41, 0xb4, 0x55, 0x88, 0x0a, 0x9d, 0xd2, 0x32, 0xa3, 0xa9, 0xa0, 0x6b, 0x41, 0x93, 0x8c, 0x5e, 0x70, + 0x25, 0x2a, 0x5e, 0x09, 0xa6, 0x68, 0xbb, 0x21, 0xec, 0xff, 0x68, 0xd0, 0xf5, 0x56, 0xac, 0x35, 0xb4, 0x3b, 0x41, + 0x46, 0x68, 0xbe, 0xd0, 0x41, 0xc8, 0x50, 0x39, 0x09, 0x5d, 0xab, 0x34, 0x5e, 0x81, 0x4b, 0xa6, 0xd9, 0x68, 0x19, + 0x97, 0x61, 0x60, 0xbf, 0x0a, 0x2c, 0x26, 0x07, 0x26, 0x7d, 0x58, 0x9f, 0x3f, 0x95, 0x57, 0x2b, 0x29, 0xb8, 0xa8, + 0x14, 0x44, 0xbf, 0xc1, 0x7d, 0x37, 0x71, 0xd5, 0x59, 0xb3, 0x56, 0x7a, 0xdf, 0xb7, 0x3e, 0x6b, 0xe3, 0xbe, 0x30, + 0x38, 0x06, 0x7b, 0x1f, 0x11, 0x03, 0x69, 0x50, 0xe9, 0x16, 0x87, 0x26, 0x40, 0x97, 0x0e, 0x29, 0x64, 0xc9, 0x54, + 0xa6, 0x4a, 0x50, 0xf1, 0x8d, 0xdf, 0x4b, 0x59, 0x8d, 0xfe, 0x5a, 0xf3, 0x62, 0xf3, 0x81, 0xe7, 0x1c, 0xc7, 0x28, + 0x48, 0x62, 0x71, 0x1d, 0x97, 0x01, 0xf1, 0x2d, 0xaf, 0x82, 0xa3, 0xd4, 0x84, 0x8d, 0xd9, 0xab, 0x1a, 0xb5, 0x5e, + 0x05, 0xfa, 0xca, 0x28, 0xdf, 0x18, 0x0c, 0x4d, 0x44, 0x15, 0xf4, 0xbd, 0x56, 0xf7, 0xb4, 0xba, 0x61, 0x01, 0xf1, + 0xe7, 0x4a, 0x2f, 0xd4, 0x7a, 0xdd, 0x8c, 0xb9, 0x61, 0x22, 0x04, 0x8d, 0x1e, 0xd5, 0x0b, 0x87, 0x9f, 0xbf, 0x55, + 0x96, 0x44, 0xf0, 0x62, 0x9b, 0xae, 0x0b, 0x13, 0x4b, 0x83, 0xea, 0x80, 0xb9, 0xd1, 0x36, 0xe7, 0x97, 0x20, 0xfa, + 0x73, 0x56, 0x44, 0x93, 0xba, 0xa6, 0x0a, 0xc1, 0x30, 0xda, 0xde, 0x36, 0xd2, 0xe9, 0x06, 0xbc, 0xdc, 0x8c, 0x35, + 0x92, 0xf6, 0x74, 0xac, 0x69, 0xc1, 0xcb, 0x95, 0x14, 0x25, 0x44, 0x77, 0xee, 0x8d, 0xe9, 0x55, 0x9c, 0x89, 0x2a, + 0xce, 0xc4, 0x69, 0xb9, 0xe2, 0x49, 0xf5, 0x1e, 0x2a, 0xd4, 0xc6, 0x38, 0xd8, 0x7a, 0x35, 0xea, 0x2a, 0x1c, 0xf2, + 0xab, 0x8b, 0xe7, 0xb7, 0xab, 0x58, 0xa4, 0x30, 0xea, 0xf5, 0x5d, 0x2f, 0x9a, 0xd3, 0xb1, 0x8a, 0x0b, 0x2e, 0x4c, + 0xd4, 0x62, 0x5a, 0xb1, 0x80, 0xeb, 0x8c, 0x01, 0xe5, 0x2a, 0x76, 0x67, 0xa6, 0x62, 0x19, 0xc6, 0x65, 0xf9, 0x53, + 0x56, 0xe2, 0x1d, 0x00, 0x5a, 0x03, 0xa7, 0xc5, 0xcc, 0x80, 0x80, 0x6c, 0x72, 0x83, 0x8b, 0xc0, 0x82, 0xa3, 0xc7, + 0xe3, 0xd5, 0x6d, 0x40, 0xbd, 0x37, 0x52, 0x5d, 0x0f, 0x59, 0x30, 0x1e, 0x3d, 0x09, 0x1c, 0x72, 0x88, 0xff, 0xd1, + 0xe3, 0xa3, 0xbb, 0xbf, 0x99, 0x04, 0xa4, 0x9e, 0x82, 0xaa, 0xc2, 0x28, 0x44, 0x61, 0xda, 0x5f, 0xaf, 0xd5, 0x2d, + 0xf7, 0xed, 0x79, 0xc9, 0x8b, 0x6b, 0xd8, 0x97, 0x64, 0x9a, 0x01, 0x39, 0x97, 0x2a, 0x01, 0x16, 0x45, 0x5c, 0x55, + 0x45, 0x76, 0x0e, 0x26, 0x4a, 0x68, 0x00, 0x66, 0x9e, 0x5e, 0xa0, 0xc3, 0x47, 0x34, 0x0f, 0xb0, 0x4f, 0xc1, 0xa2, + 0x26, 0x75, 0x09, 0x85, 0x25, 0x07, 0x18, 0xac, 0x4e, 0xc5, 0x95, 0x76, 0x00, 0xdf, 0xd5, 0x1f, 0xd1, 0x52, 0x62, + 0xac, 0x59, 0x3d, 0x4f, 0xf1, 0x79, 0x29, 0xf3, 0x75, 0x05, 0xda, 0xf3, 0x8b, 0x2a, 0x3a, 0x7a, 0xbc, 0xba, 0x9d, + 0xaa, 0x6e, 0x44, 0xd0, 0x8b, 0xa9, 0xc2, 0x79, 0x4b, 0xe2, 0x3c, 0x09, 0x27, 0xe3, 0xf1, 0x37, 0x07, 0xc3, 0x03, + 0x48, 0x26, 0xd3, 0xcf, 0x43, 0xe5, 0xc8, 0x35, 0x9c, 0x8c, 0xc7, 0xf5, 0x1f, 0xb5, 0x09, 0xf3, 0x6d, 0xea, 0xf9, + 0xf0, 0xc7, 0xb1, 0x5a, 0xff, 0x27, 0xc7, 0x87, 0xfa, 0xc7, 0x1f, 0x75, 0x3d, 0x7d, 0x5a, 0x84, 0xf3, 0x7f, 0x87, + 0x6a, 0x7d, 0x9f, 0x16, 0x45, 0xbc, 0xa9, 0xc9, 0x82, 0xae, 0x84, 0xf3, 0xae, 0xa1, 0x1e, 0x59, 0xa0, 0x47, 0x64, + 0xba, 0x12, 0x0c, 0xbe, 0x79, 0x5f, 0x85, 0x01, 0x2f, 0x57, 0x43, 0x2e, 0xaa, 0xac, 0xda, 0x0c, 0x31, 0x4f, 0x80, + 0x9f, 0x5a, 0x3c, 0xb3, 0xc2, 0x10, 0xdf, 0x8b, 0x82, 0xf3, 0xcf, 0x3c, 0x54, 0xc6, 0xe2, 0x63, 0x34, 0x16, 0x1f, + 0x53, 0xd5, 0x8d, 0xc9, 0x77, 0x54, 0xf7, 0x6d, 0xf2, 0x1d, 0x98, 0x64, 0x65, 0xed, 0x6f, 0x94, 0xb1, 0x66, 0x34, + 0xa6, 0xd7, 0x2f, 0xf2, 0x6c, 0x05, 0x97, 0x82, 0xa5, 0xfe, 0x51, 0x13, 0xfa, 0x9e, 0xb7, 0xb3, 0x8f, 0x46, 0xa3, + 0x07, 0x05, 0x1d, 0x8d, 0x46, 0x9f, 0xb2, 0x9a, 0xd0, 0x4b, 0xd1, 0xf1, 0xfe, 0x3d, 0xa7, 0xe7, 0x32, 0xdd, 0x44, + 0x41, 0x40, 0x97, 0x59, 0x9a, 0x72, 0xa1, 0xca, 0x7a, 0x9a, 0xb6, 0xf3, 0xaa, 0x16, 0x22, 0x10, 0x92, 0x6e, 0x23, + 0x42, 0x32, 0x11, 0xfa, 0x76, 0xaf, 0x67, 0xa3, 0xd1, 0xe8, 0x69, 0x6a, 0xaa, 0x75, 0x17, 0x94, 0x07, 0x68, 0x4e, + 0xe1, 0xfc, 0x14, 0xc0, 0x1a, 0xc9, 0x44, 0x7f, 0x39, 0xfc, 0xaf, 0xe1, 0x6c, 0x3e, 0x1e, 0x7e, 0x3f, 0x5a, 0x3c, + 0x3c, 0xa4, 0x41, 0xe0, 0x87, 0x6e, 0x08, 0xb5, 0x75, 0xcb, 0xb4, 0x3c, 0x1e, 0x4f, 0x49, 0x39, 0x60, 0x8f, 0xad, + 0x6f, 0xd1, 0x37, 0x8f, 0x01, 0x99, 0x15, 0x45, 0xca, 0x81, 0x93, 0x86, 0xe2, 0xd5, 0xec, 0x95, 0x00, 0xbc, 0x38, + 0x1b, 0xd9, 0xc1, 0x68, 0x45, 0xc7, 0x11, 0x94, 0x57, 0x5b, 0x53, 0x91, 0x1e, 0x63, 0x99, 0x89, 0x92, 0x3a, 0x9e, + 0x96, 0x37, 0x59, 0x95, 0x2c, 0x31, 0xd0, 0x53, 0x5c, 0xf2, 0xe0, 0x9b, 0x20, 0x2a, 0xd9, 0xd1, 0x93, 0xa9, 0x82, + 0x3b, 0xc6, 0xa4, 0x94, 0x5f, 0x42, 0xe2, 0xf7, 0x63, 0x84, 0x84, 0x25, 0xda, 0x83, 0x13, 0x6b, 0x7c, 0x91, 0xcb, + 0x18, 0x3c, 0x5a, 0x4b, 0xcd, 0xc3, 0xd9, 0x93, 0xd1, 0xda, 0xa3, 0xb4, 0x9a, 0x23, 0xa1, 0x39, 0xa1, 0x64, 0xf2, + 0xb0, 0xa4, 0xf2, 0x9b, 0x09, 0x7a, 0x49, 0x81, 0x9b, 0x79, 0x04, 0xc7, 0xbf, 0xb5, 0xf4, 0x50, 0xbd, 0x7a, 0x9b, + 0xb2, 0xc3, 0xf9, 0xff, 0x29, 0xe9, 0x62, 0x70, 0xe8, 0x86, 0xe6, 0x9d, 0x76, 0xe7, 0xad, 0x90, 0x71, 0xac, 0xc2, + 0xb7, 0x29, 0xb1, 0xc6, 0xb8, 0x9c, 0x9d, 0x6c, 0x4d, 0x77, 0x46, 0x55, 0x91, 0x5d, 0x85, 0x44, 0xf7, 0xca, 0x81, + 0x84, 0x06, 0x51, 0x36, 0xc2, 0xf5, 0x03, 0xd6, 0x33, 0x5e, 0x27, 0xaf, 0x79, 0x51, 0x65, 0x89, 0x7a, 0x7f, 0xdd, + 0x78, 0x5f, 0xd7, 0x26, 0xa0, 0xea, 0xbb, 0x82, 0xc1, 0x3c, 0xbf, 0x2d, 0x00, 0xc4, 0x14, 0x69, 0x80, 0x4f, 0x30, + 0x83, 0xa0, 0x76, 0xcd, 0xbc, 0x6a, 0x04, 0xdf, 0x80, 0xaf, 0xde, 0x15, 0x80, 0x41, 0x12, 0x82, 0x14, 0x19, 0x42, + 0x03, 0x81, 0x40, 0xc3, 0x90, 0x0b, 0x0c, 0x7e, 0xe2, 0xc5, 0x91, 0x54, 0x4e, 0x89, 0x3c, 0x0c, 0xf0, 0x47, 0x40, + 0x55, 0x00, 0x12, 0xe3, 0x71, 0x08, 0x2f, 0xd4, 0x2f, 0xf7, 0x46, 0xed, 0x11, 0xf6, 0x20, 0x0d, 0x21, 0xd8, 0x10, + 0x3e, 0x04, 0xb0, 0xa4, 0x08, 0x7d, 0x87, 0x5c, 0x46, 0x18, 0x5c, 0xe4, 0xd9, 0x4a, 0x27, 0x55, 0xa3, 0x8e, 0xe6, + 0x43, 0xa9, 0x1d, 0xc9, 0x01, 0xf5, 0xd2, 0x63, 0x4c, 0x2f, 0x54, 0xba, 0x2a, 0xca, 0x19, 0xe5, 0x9c, 0xea, 0x89, + 0x71, 0x61, 0x0b, 0x39, 0x44, 0xc2, 0x79, 0x57, 0xa8, 0x50, 0x38, 0x7c, 0x01, 0x60, 0x60, 0x20, 0xed, 0xd8, 0x8f, + 0x77, 0xa3, 0xb2, 0x9f, 0x71, 0x76, 0xf8, 0x5f, 0xf3, 0x78, 0xf8, 0x79, 0x3c, 0xfc, 0x7e, 0x31, 0x08, 0x87, 0xf6, + 0x27, 0x79, 0xf8, 0xe0, 0x90, 0xbe, 0xe0, 0x96, 0x4b, 0x83, 0x85, 0xdf, 0x08, 0xf6, 0xa3, 0x56, 0x42, 0x10, 0x05, + 0x78, 0xc3, 0x72, 0xab, 0x71, 0x02, 0x80, 0x87, 0xc1, 0xff, 0x0e, 0xd0, 0x68, 0xca, 0x5d, 0xbc, 0x40, 0x5f, 0xa2, + 0x7e, 0x9f, 0x3c, 0x6a, 0x18, 0x0c, 0x82, 0xb8, 0x46, 0xc5, 0x84, 0x21, 0xba, 0x8c, 0x89, 0x82, 0x41, 0xb6, 0xd9, + 0x77, 0xbb, 0x5e, 0x5b, 0x12, 0x86, 0x5f, 0xfa, 0x99, 0x26, 0x66, 0xde, 0xe1, 0xc6, 0xb6, 0x92, 0xab, 0x10, 0xb1, + 0x02, 0xf5, 0xaf, 0x9c, 0x41, 0xec, 0xcd, 0xeb, 0x0c, 0x7c, 0x3a, 0xec, 0x17, 0xe3, 0x19, 0xb0, 0x51, 0x70, 0xe7, + 0x2b, 0xf8, 0x45, 0x06, 0x6e, 0xde, 0x22, 0x46, 0x81, 0x83, 0x5d, 0x12, 0xfd, 0x7e, 0x2f, 0xcf, 0xc2, 0x5c, 0xe3, + 0x4e, 0xe7, 0xb5, 0x51, 0x43, 0xa0, 0x8e, 0x1c, 0xd4, 0x0f, 0x7a, 0x08, 0x86, 0x6a, 0x08, 0x8a, 0x8e, 0xb6, 0xb8, + 0x7a, 0x6d, 0x3d, 0x85, 0xe9, 0xad, 0xaa, 0xaf, 0x18, 0xfd, 0x29, 0x33, 0x81, 0x85, 0xb4, 0x6b, 0x8e, 0x75, 0xcd, + 0x31, 0xd2, 0x9e, 0x7e, 0x5f, 0x34, 0xc8, 0x4f, 0x67, 0xe1, 0x41, 0xa0, 0x4a, 0x95, 0x7b, 0x65, 0x51, 0x6e, 0x4b, + 0xf3, 0xc6, 0xb0, 0xa6, 0x79, 0x66, 0xe3, 0xdc, 0xcc, 0x7a, 0xbd, 0x30, 0x44, 0x07, 0x4f, 0x2c, 0x15, 0x6b, 0x83, + 0x70, 0x47, 0x26, 0x61, 0x74, 0x05, 0xb2, 0xcb, 0xf0, 0x8c, 0x13, 0xe4, 0x53, 0x81, 0x7d, 0x50, 0xd5, 0x7a, 0x39, + 0xe1, 0xb1, 0x91, 0x2f, 0x1b, 0x41, 0x83, 0xbc, 0xa4, 0xa8, 0x37, 0x71, 0x3b, 0xf6, 0x79, 0x0b, 0xb9, 0x72, 0x5b, + 0x4f, 0x7b, 0x9a, 0x54, 0xf4, 0x58, 0xaf, 0x52, 0xbf, 0xc0, 0xd2, 0xc2, 0x92, 0x0f, 0x42, 0x7b, 0x9a, 0x56, 0x60, + 0x86, 0x6b, 0x9b, 0xc1, 0xd0, 0x0f, 0xc7, 0x4f, 0x40, 0x67, 0xd4, 0xb6, 0x84, 0x30, 0x76, 0x83, 0xb0, 0xf2, 0x9e, + 0xc8, 0x37, 0x8f, 0xbd, 0x8b, 0x41, 0xc8, 0xcd, 0x66, 0x16, 0x0d, 0x4c, 0xf7, 0x73, 0xd9, 0x6c, 0x9e, 0x6e, 0xae, + 0x17, 0x25, 0x54, 0xc0, 0x76, 0xbb, 0x14, 0x04, 0xff, 0x7e, 0xca, 0x66, 0xf8, 0x37, 0xeb, 0xf7, 0x7b, 0x21, 0xfe, + 0xe2, 0x18, 0xcc, 0x68, 0x2e, 0x16, 0xec, 0x13, 0xc8, 0x98, 0x48, 0x84, 0xa9, 0xca, 0x18, 0x90, 0x55, 0x60, 0x11, + 0x68, 0x3e, 0x50, 0xb9, 0x30, 0x93, 0xbd, 0xcc, 0xb9, 0x86, 0xbc, 0x6a, 0x8d, 0x53, 0x36, 0xca, 0x12, 0xe5, 0xca, + 0x91, 0x8d, 0xe2, 0x3c, 0x8b, 0x4b, 0x5e, 0xee, 0x76, 0xfa, 0x70, 0x4c, 0x0a, 0x0e, 0xec, 0xba, 0xa2, 0x52, 0x25, + 0xeb, 0x48, 0xf5, 0xc0, 0x4b, 0xc3, 0x02, 0xf7, 0x29, 0x9f, 0x17, 0x86, 0x46, 0x1c, 0x80, 0x30, 0x83, 0xa9, 0x5b, + 0x7a, 0x2f, 0x2c, 0xa0, 0x79, 0x25, 0x21, 0x5b, 0x4c, 0xf5, 0x2c, 0x7c, 0x63, 0x26, 0xe6, 0xc5, 0x02, 0xc2, 0xea, + 0x14, 0x0b, 0xcd, 0x6c, 0xd2, 0x84, 0xc5, 0x00, 0x9b, 0x17, 0x93, 0x29, 0xc4, 0x77, 0x57, 0xe5, 0xc4, 0x0b, 0x73, + 0xdf, 0x4e, 0x1c, 0x72, 0x08, 0xbc, 0xaa, 0x0d, 0xba, 0x9a, 0x6d, 0x38, 0xea, 0x48, 0x39, 0x31, 0xf9, 0xfd, 0x54, + 0x41, 0x88, 0x3b, 0x71, 0x24, 0x5c, 0xde, 0x6c, 0x17, 0x9e, 0x75, 0x20, 0xe8, 0xa8, 0xc1, 0x29, 0xbf, 0x30, 0x38, + 0x1a, 0x93, 0x74, 0xeb, 0x9d, 0x20, 0x45, 0x18, 0x93, 0xad, 0x64, 0xe7, 0x32, 0x14, 0xf3, 0x78, 0x01, 0xca, 0xcb, + 0x78, 0x01, 0x96, 0x46, 0xc6, 0x20, 0x15, 0xe4, 0x77, 0xdc, 0x0b, 0x85, 0x45, 0x71, 0x85, 0x48, 0xcf, 0xea, 0xf7, + 0xb4, 0x68, 0x87, 0x02, 0x41, 0x71, 0x87, 0x32, 0x4f, 0xce, 0x7a, 0x2c, 0x90, 0xd8, 0x10, 0x30, 0xbe, 0xd2, 0x69, + 0xaa, 0xb5, 0xee, 0x8d, 0x99, 0x07, 0x3e, 0xcd, 0x46, 0x42, 0x56, 0x67, 0x17, 0x20, 0x52, 0xf2, 0xd1, 0xf1, 0x91, + 0x5f, 0xc4, 0x9d, 0x65, 0xde, 0xda, 0x16, 0x95, 0xec, 0x64, 0x0b, 0xa0, 0x85, 0x3a, 0x7a, 0x96, 0x92, 0xdb, 0x94, + 0xa4, 0x76, 0x9b, 0x02, 0x56, 0x92, 0xbf, 0x80, 0x21, 0xf8, 0xda, 0x81, 0x70, 0x3a, 0x56, 0x88, 0xd7, 0x34, 0x45, + 0xa4, 0xc9, 0xb0, 0xa4, 0x38, 0xb6, 0x25, 0xa2, 0xa0, 0xda, 0xb2, 0xec, 0x60, 0x98, 0x28, 0xc1, 0x1f, 0x53, 0x8f, + 0x12, 0x05, 0x01, 0xd5, 0x43, 0x0e, 0x12, 0x6c, 0xdb, 0x40, 0x78, 0x40, 0x1e, 0xd1, 0x1b, 0xeb, 0x9f, 0xb3, 0xce, + 0xb3, 0x0b, 0xcd, 0x73, 0xb9, 0xde, 0x15, 0x66, 0x8c, 0xf0, 0x24, 0x33, 0x61, 0x03, 0xbc, 0xf3, 0xcc, 0xa8, 0x6d, + 0x7a, 0x1e, 0x5e, 0xdb, 0x73, 0x8c, 0xd0, 0x77, 0xc7, 0xa0, 0x9b, 0x60, 0x5e, 0x1d, 0x36, 0xeb, 0x95, 0x82, 0xd4, + 0x30, 0xb5, 0x68, 0x62, 0xd6, 0xb3, 0x06, 0xe5, 0xbb, 0x5d, 0x4f, 0xcf, 0xd5, 0xdd, 0x73, 0xb7, 0xdb, 0xf5, 0xb0, + 0x5b, 0x1f, 0xd3, 0x6e, 0xab, 0xf8, 0x4a, 0x7d, 0xd0, 0x1e, 0x7f, 0xee, 0xc6, 0x9f, 0x1b, 0x64, 0x93, 0xd2, 0xd1, + 0x4c, 0x5b, 0x1f, 0x84, 0x07, 0x4e, 0x37, 0x8d, 0x26, 0xfd, 0x9c, 0x85, 0x92, 0x5e, 0x8a, 0x46, 0x75, 0xb5, 0x33, + 0x31, 0xbd, 0x77, 0xfd, 0xdf, 0xbf, 0x0a, 0xf0, 0x88, 0x53, 0x3b, 0xfb, 0xce, 0x06, 0x15, 0x8d, 0xb6, 0x70, 0xa4, + 0x08, 0x3d, 0x20, 0x09, 0x77, 0xb5, 0xac, 0xc5, 0x6d, 0x7e, 0xc8, 0xee, 0xa7, 0x4f, 0x3f, 0xa5, 0xbe, 0x17, 0x82, + 0x5b, 0x66, 0x99, 0x39, 0xf0, 0x2a, 0x8a, 0x03, 0x1a, 0x75, 0xd1, 0xbe, 0xab, 0xac, 0x2c, 0xc1, 0xeb, 0x05, 0xee, + 0x95, 0x1f, 0xb8, 0x0f, 0xbf, 0x77, 0x59, 0x35, 0x37, 0xe9, 0x87, 0x6c, 0x9e, 0x2d, 0x76, 0xbb, 0x10, 0xff, 0x76, + 0xb5, 0xc8, 0xd1, 0xe4, 0x39, 0xe8, 0x34, 0x31, 0x92, 0x11, 0xd3, 0x8d, 0xf3, 0x36, 0xff, 0x67, 0xd1, 0x70, 0x9a, + 0x78, 0x0e, 0xf4, 0x62, 0x76, 0x0a, 0x32, 0x29, 0x03, 0x72, 0x20, 0x66, 0x7a, 0xcd, 0x40, 0x34, 0x32, 0x11, 0x01, + 0xae, 0x30, 0x36, 0x12, 0x8d, 0x4e, 0x38, 0xa9, 0x09, 0x58, 0xb0, 0xda, 0xf2, 0xde, 0x5b, 0xda, 0x56, 0x15, 0x1b, + 0x6f, 0x49, 0x73, 0x5c, 0x07, 0xce, 0xd7, 0xc1, 0x06, 0xbc, 0xd3, 0x65, 0x57, 0x0b, 0xe4, 0x7e, 0x79, 0x4d, 0x7b, + 0xe3, 0x3a, 0x81, 0x59, 0xdb, 0xd6, 0x96, 0xf1, 0xb3, 0xa5, 0xbf, 0xd0, 0x83, 0xab, 0x8c, 0xc1, 0xe6, 0xc6, 0x4a, + 0xc3, 0xee, 0x1b, 0xcf, 0x97, 0x02, 0xc2, 0xd3, 0xf9, 0xf4, 0xf8, 0x43, 0xe6, 0xd1, 0x63, 0x20, 0x3a, 0xe6, 0xa3, + 0xd2, 0x7d, 0x64, 0x77, 0xaf, 0x1f, 0x10, 0x70, 0x5e, 0xb5, 0x0b, 0x9a, 0x97, 0x0b, 0x08, 0xac, 0xea, 0x95, 0x57, + 0x58, 0x3e, 0x33, 0x66, 0x97, 0x40, 0x86, 0x0a, 0x02, 0x81, 0xbb, 0xbb, 0xce, 0x85, 0x58, 0x75, 0x58, 0x99, 0xd3, + 0x24, 0xec, 0x24, 0x44, 0xf3, 0xd6, 0x60, 0x16, 0xfc, 0xef, 0x60, 0x50, 0x0e, 0x82, 0x28, 0x88, 0x82, 0x80, 0x0c, + 0x0a, 0xf8, 0x85, 0xb8, 0x6b, 0x04, 0x63, 0xb6, 0x40, 0x87, 0xdf, 0x72, 0xe6, 0x33, 0x22, 0xaf, 0xfc, 0xb0, 0x9e, + 0xde, 0x00, 0x9c, 0x4b, 0x99, 0xf3, 0x18, 0x7d, 0x4e, 0xde, 0x72, 0x96, 0x11, 0xfa, 0xd6, 0x3b, 0x95, 0xdf, 0xf1, + 0x46, 0xb0, 0xbf, 0xfd, 0x61, 0x7b, 0x01, 0xf2, 0x8a, 0xde, 0x98, 0xbe, 0xe5, 0x24, 0xca, 0x1a, 0xce, 0xd4, 0x1c, + 0x7a, 0x56, 0x59, 0xd6, 0x8a, 0x1a, 0x72, 0x83, 0x62, 0x6e, 0x64, 0x99, 0x9c, 0x4c, 0x5b, 0xcd, 0xa9, 0xc0, 0x75, + 0x67, 0xd7, 0x0b, 0x48, 0x0e, 0x85, 0x66, 0xe9, 0x6c, 0x38, 0x6f, 0x77, 0x28, 0xb6, 0x4e, 0x21, 0xaf, 0x21, 0x2a, + 0x1a, 0xa4, 0x23, 0xa0, 0x86, 0x56, 0x5c, 0x56, 0xe0, 0xc2, 0x6c, 0xda, 0xc3, 0x4d, 0x7b, 0x4c, 0x33, 0xde, 0x43, + 0xcc, 0x3c, 0x8e, 0x2d, 0x03, 0x3b, 0x12, 0x87, 0xf4, 0xe4, 0x7c, 0x81, 0xf6, 0xe9, 0xad, 0xab, 0xc5, 0x23, 0xac, + 0x3d, 0x6f, 0x85, 0x84, 0x00, 0xf1, 0x69, 0x2a, 0xdd, 0xed, 0x82, 0x00, 0x06, 0xb8, 0xdf, 0xef, 0x01, 0xd7, 0x6a, + 0xd8, 0x49, 0x73, 0x6b, 0xb6, 0xc4, 0x5e, 0x51, 0x78, 0x0c, 0xcc, 0xa9, 0xf9, 0xcf, 0x20, 0xa0, 0x78, 0xee, 0x86, + 0x60, 0x6f, 0xca, 0x4e, 0xb6, 0x45, 0xbf, 0xff, 0xac, 0xc0, 0x07, 0x94, 0x0b, 0x83, 0x98, 0x5b, 0xc7, 0xf1, 0x30, + 0xec, 0x93, 0xfa, 0x10, 0xc7, 0x22, 0xcf, 0x42, 0x47, 0x58, 0x2a, 0x43, 0x58, 0xb8, 0x62, 0xa4, 0x83, 0x38, 0xa8, + 0x49, 0xe7, 0x60, 0x55, 0x2e, 0xf8, 0x72, 0xaf, 0xf7, 0x19, 0x60, 0xd2, 0x33, 0x6f, 0x58, 0xde, 0x78, 0x80, 0x68, + 0xbd, 0x1e, 0x2e, 0x14, 0x8f, 0x4c, 0x34, 0xd0, 0x38, 0xf1, 0xa5, 0x65, 0xd7, 0x67, 0x5a, 0x56, 0x32, 0x1a, 0x8d, + 0xaa, 0x5a, 0x49, 0x3e, 0xec, 0x77, 0x7f, 0xb6, 0x50, 0x3c, 0x65, 0x9c, 0xf2, 0x14, 0x2c, 0xdf, 0x0d, 0xa5, 0x9b, + 0x2f, 0xe8, 0x8a, 0x8b, 0x54, 0xfd, 0xf4, 0xd0, 0x37, 0x1b, 0xc4, 0x35, 0x6b, 0xea, 0x70, 0xec, 0xf0, 0x43, 0x00, + 0x4c, 0xfb, 0x30, 0x73, 0xe9, 0x1a, 0xa6, 0x17, 0xc4, 0xb3, 0x71, 0xc1, 0x43, 0x97, 0x07, 0xb0, 0x0f, 0xcd, 0x21, + 0x89, 0x9f, 0xc2, 0xcf, 0x99, 0x49, 0xeb, 0xf8, 0x0c, 0x67, 0x33, 0x2a, 0xd5, 0x8d, 0xa0, 0xfd, 0x1a, 0x12, 0x89, + 0x41, 0x7a, 0x6e, 0x30, 0x14, 0xad, 0xbb, 0x0d, 0x5c, 0xf9, 0x2d, 0xbd, 0xf3, 0x69, 0x10, 0x60, 0x7d, 0x63, 0x31, + 0x00, 0xa0, 0x8a, 0x3f, 0x50, 0x75, 0x65, 0xae, 0x28, 0xa6, 0x61, 0x2a, 0xd1, 0xde, 0x71, 0x5c, 0x47, 0x8d, 0xeb, + 0xb0, 0x60, 0xa5, 0xb5, 0x6d, 0x76, 0x6f, 0x69, 0x61, 0x4b, 0x40, 0xb5, 0x20, 0xee, 0x04, 0xf0, 0xa1, 0x91, 0xea, + 0x40, 0x90, 0xdd, 0x07, 0x07, 0x00, 0xbc, 0xe1, 0x79, 0x18, 0xc2, 0x1f, 0x58, 0x38, 0xb0, 0x2c, 0x55, 0x3f, 0x97, + 0xd3, 0x18, 0xce, 0xdd, 0x5c, 0xed, 0xf0, 0xd9, 0x12, 0x14, 0x9b, 0x6a, 0x4e, 0xcd, 0xe5, 0x2b, 0x6f, 0xec, 0xf7, + 0x98, 0x60, 0x1e, 0x33, 0xdb, 0xf0, 0x5b, 0x4f, 0xb7, 0xf5, 0x0d, 0x76, 0x03, 0x27, 0xed, 0x85, 0xd3, 0x5e, 0x6c, + 0x97, 0x06, 0xf2, 0xaf, 0x6e, 0x08, 0x11, 0x3e, 0x6a, 0x62, 0x91, 0x35, 0x64, 0x3a, 0x16, 0x2b, 0x44, 0xb5, 0xa9, + 0x78, 0xaa, 0x0d, 0x04, 0xca, 0xa9, 0xba, 0x30, 0xb5, 0x52, 0x99, 0x30, 0x88, 0x3b, 0x25, 0x2c, 0xaa, 0x0c, 0x30, + 0x0c, 0x2a, 0xa4, 0xb8, 0xb6, 0x9e, 0x1f, 0x70, 0xf9, 0x66, 0xa6, 0xcd, 0xf6, 0xd3, 0x17, 0x79, 0x7c, 0xb9, 0xdb, + 0x85, 0xdd, 0x2f, 0xc0, 0x1c, 0xb5, 0x54, 0x1a, 0x46, 0x70, 0x02, 0x51, 0x92, 0xeb, 0x3b, 0x72, 0x4e, 0x1c, 0x27, + 0xd7, 0x6e, 0xde, 0x6c, 0x2f, 0xc5, 0x08, 0x2c, 0xe0, 0xc4, 0x45, 0x3a, 0xd0, 0x52, 0x49, 0x6a, 0x4f, 0x01, 0x6f, + 0xd3, 0x3b, 0x4a, 0x85, 0x57, 0x0b, 0x4d, 0x42, 0x2a, 0x77, 0x2f, 0xb1, 0xa3, 0x06, 0x9c, 0x93, 0xba, 0x83, 0x80, + 0xd3, 0x9e, 0x6e, 0xac, 0x55, 0x24, 0x9b, 0x04, 0xef, 0x95, 0x1e, 0xba, 0x44, 0x3b, 0xb5, 0xbb, 0x6d, 0x55, 0xb6, + 0x50, 0x30, 0x0f, 0x72, 0x96, 0xa8, 0xe3, 0x01, 0x85, 0x2e, 0xea, 0x68, 0xc8, 0x17, 0xa4, 0xd0, 0x2b, 0x47, 0xab, + 0x9a, 0xf7, 0x25, 0x03, 0xa5, 0x5a, 0x05, 0x79, 0x4d, 0xac, 0xfb, 0x5a, 0xd6, 0x58, 0x5c, 0x39, 0x21, 0x85, 0x4d, + 0xf8, 0xda, 0x52, 0x2c, 0xcc, 0x62, 0x6f, 0x4c, 0x7d, 0xe1, 0x12, 0xa1, 0xed, 0x6e, 0x43, 0x8c, 0x36, 0x58, 0x37, + 0xbb, 0xdd, 0xc7, 0x22, 0x9c, 0x67, 0x0b, 0x2a, 0x47, 0x59, 0x8a, 0x90, 0x6a, 0xc6, 0x63, 0xd9, 0x76, 0xc1, 0x4c, + 0x0c, 0x75, 0xed, 0xf1, 0x92, 0x4c, 0xb1, 0x36, 0x49, 0x8e, 0xe2, 0x73, 0x59, 0xa8, 0xb5, 0x46, 0x08, 0x1e, 0xee, + 0xbf, 0xa6, 0x10, 0xd3, 0xce, 0xac, 0xbb, 0x97, 0x7b, 0x37, 0xc4, 0x5f, 0x21, 0xb0, 0x42, 0xc9, 0x3e, 0x16, 0xa3, + 0xf3, 0x0c, 0x82, 0xc1, 0x82, 0xac, 0x19, 0xa3, 0x04, 0xab, 0x75, 0xd0, 0x6c, 0xb9, 0xbd, 0x17, 0x5b, 0xa2, 0x00, + 0x71, 0x9e, 0x85, 0x66, 0x3c, 0x2b, 0x67, 0x39, 0x93, 0x51, 0x6c, 0x48, 0x54, 0x7a, 0x51, 0xe2, 0x7d, 0x9e, 0xc6, + 0xf4, 0xd0, 0xad, 0x41, 0x70, 0x5d, 0xdd, 0xdb, 0x48, 0xf3, 0x05, 0x21, 0x6a, 0x02, 0x24, 0x6c, 0x54, 0x73, 0x6a, + 0x5d, 0x89, 0xfb, 0x59, 0xe5, 0x8d, 0x3e, 0x88, 0xaf, 0x04, 0xf0, 0xb0, 0xde, 0xf6, 0x3e, 0x17, 0x1e, 0x6b, 0x83, + 0x6f, 0x77, 0xbb, 0x2b, 0x31, 0x0f, 0x02, 0x8f, 0xd1, 0xfc, 0x45, 0x49, 0xcc, 0x7b, 0x63, 0x0a, 0x2b, 0xde, 0x77, + 0xf1, 0xeb, 0x26, 0xb5, 0xd6, 0x22, 0x77, 0x8f, 0xeb, 0x03, 0x9e, 0xa7, 0xc4, 0xd1, 0x8e, 0xca, 0xa9, 0xb4, 0xb6, + 0x03, 0xd8, 0x15, 0x81, 0x81, 0xb2, 0x7f, 0x4b, 0xd9, 0x16, 0xcc, 0x13, 0xc1, 0xfa, 0x08, 0xfd, 0xb6, 0x94, 0xfe, + 0x64, 0x8c, 0xc6, 0x3d, 0x72, 0x5d, 0x45, 0x47, 0x5c, 0x47, 0xb3, 0xe7, 0xd1, 0xdf, 0x9e, 0x8c, 0x69, 0x11, 0x8b, + 0x54, 0x5e, 0x81, 0x0a, 0x02, 0x94, 0x21, 0xe8, 0x08, 0xa1, 0xa9, 0x01, 0x68, 0x10, 0xdc, 0x00, 0xfc, 0xbb, 0xd3, + 0x89, 0xd2, 0xd6, 0xe4, 0x63, 0xb4, 0xaa, 0x22, 0x67, 0x6d, 0x68, 0x37, 0x95, 0x1c, 0x92, 0x87, 0x25, 0xe0, 0x5b, + 0x62, 0xb3, 0x94, 0x0d, 0x8a, 0xda, 0x6c, 0xea, 0xb5, 0x62, 0x47, 0x6e, 0x1b, 0x45, 0x9b, 0xb5, 0xa8, 0xed, 0x46, + 0xe6, 0x8b, 0xe9, 0xad, 0x15, 0x06, 0x4e, 0x4d, 0x6b, 0x6e, 0xf6, 0xa0, 0xe4, 0x6c, 0x7d, 0x26, 0x37, 0x01, 0xe2, + 0x00, 0xc3, 0x75, 0x3b, 0xbf, 0x59, 0x10, 0x7a, 0xcb, 0x6e, 0xad, 0x58, 0xf5, 0xc6, 0xca, 0x45, 0x4c, 0xda, 0xcd, + 0x60, 0x02, 0x97, 0x71, 0x56, 0xd8, 0x17, 0x5a, 0xdd, 0x50, 0x74, 0xb4, 0x4d, 0xda, 0xcf, 0x3b, 0xda, 0x0d, 0x17, + 0x7c, 0x2b, 0xd6, 0x71, 0x6e, 0x59, 0x53, 0x85, 0xa6, 0x1d, 0xe8, 0xed, 0x10, 0xd0, 0x9c, 0x8d, 0xe9, 0x92, 0xa6, + 0x78, 0x81, 0xa6, 0x6b, 0x30, 0xd3, 0xb9, 0x80, 0xbe, 0x76, 0xfb, 0x68, 0x5f, 0xa8, 0x9e, 0x08, 0x6f, 0x89, 0x82, + 0x6f, 0x4b, 0x0a, 0x5e, 0x6a, 0x39, 0x8f, 0xcd, 0x1c, 0x02, 0x3e, 0x8d, 0x2a, 0xd1, 0x3b, 0x29, 0x2e, 0x41, 0x9b, + 0x09, 0x47, 0xa0, 0xa9, 0x1a, 0xb1, 0x95, 0x03, 0xdc, 0x5e, 0x3c, 0x0d, 0x08, 0x05, 0xa9, 0xee, 0xda, 0xae, 0xc8, + 0x5b, 0x76, 0xb2, 0xbd, 0x05, 0x33, 0xe1, 0x6a, 0x5d, 0xb6, 0xbe, 0xb2, 0xc9, 0xee, 0xe3, 0x9a, 0x60, 0xdb, 0x3d, + 0xd4, 0xd8, 0xf0, 0x96, 0xde, 0x90, 0xed, 0x4d, 0xbf, 0x1f, 0x42, 0x7f, 0x08, 0xd5, 0x1d, 0xba, 0xed, 0xec, 0xd0, + 0xad, 0xd7, 0xce, 0x73, 0xab, 0xe7, 0x53, 0xde, 0x21, 0x1f, 0xd1, 0x64, 0x8d, 0xae, 0xe2, 0x0d, 0x6c, 0xea, 0xa8, + 0xa2, 0xaa, 0xf2, 0x28, 0xa1, 0xa0, 0x12, 0xcf, 0x78, 0xf9, 0x81, 0x63, 0xac, 0x57, 0xfd, 0xf4, 0x4e, 0xf3, 0x6a, + 0x6b, 0xb3, 0x36, 0xcb, 0xf5, 0x39, 0x58, 0x48, 0x9c, 0xf3, 0xe8, 0x4a, 0xd3, 0x92, 0x4b, 0x1f, 0x54, 0x15, 0x47, + 0x25, 0xb8, 0x88, 0xb3, 0x1c, 0xd4, 0xb8, 0x17, 0xcd, 0xfe, 0x87, 0xda, 0x76, 0x6c, 0xd9, 0x38, 0x73, 0xaf, 0x43, + 0xb2, 0xfd, 0x1f, 0x1b, 0xa8, 0xa7, 0x21, 0x46, 0x88, 0x35, 0x0b, 0xfa, 0x01, 0x83, 0x58, 0xa1, 0x41, 0xb9, 0x4e, + 0x12, 0x5e, 0x96, 0x81, 0x51, 0x6a, 0xad, 0xd9, 0xda, 0x9c, 0x67, 0xef, 0xd8, 0xc9, 0xbb, 0x1e, 0x63, 0xb7, 0x84, + 0x26, 0x5a, 0x27, 0x64, 0x6a, 0x8c, 0x3c, 0x2d, 0x90, 0xee, 0x50, 0x94, 0x5d, 0x84, 0x0f, 0x50, 0xc8, 0xd2, 0xde, + 0xe7, 0xe6, 0x44, 0x56, 0xdf, 0x68, 0x23, 0x94, 0x48, 0x25, 0x82, 0x6c, 0xfc, 0x06, 0x01, 0x8c, 0xa1, 0xd9, 0x01, + 0xd9, 0x2e, 0xd9, 0x6b, 0x7a, 0x66, 0x4d, 0x82, 0xe0, 0xf5, 0x03, 0x95, 0x68, 0x46, 0x59, 0x11, 0x5d, 0x65, 0xf4, + 0xb3, 0x09, 0x49, 0x74, 0x16, 0x12, 0x3f, 0x37, 0x2c, 0xad, 0xeb, 0x10, 0xc5, 0xcc, 0x66, 0xc3, 0x6b, 0x45, 0x54, + 0x63, 0x5b, 0x19, 0x1f, 0xf3, 0x5b, 0x9b, 0x46, 0xa6, 0xd0, 0xd7, 0xe1, 0xa4, 0xdf, 0x87, 0xbf, 0x9a, 0x7e, 0xe0, + 0x2d, 0x05, 0x7f, 0xb1, 0x77, 0xa4, 0x4e, 0x58, 0x00, 0xf0, 0x8c, 0x39, 0xaf, 0x9a, 0x13, 0xf8, 0x8e, 0x9d, 0x6c, + 0xdf, 0x85, 0xaf, 0x1b, 0x33, 0xb7, 0x09, 0xf1, 0x52, 0x95, 0xf4, 0xbc, 0x79, 0x32, 0x03, 0xb1, 0xb2, 0x5a, 0xf3, + 0x5b, 0x66, 0xf5, 0x09, 0x40, 0xa4, 0x6e, 0xad, 0x83, 0x2d, 0x7e, 0x6c, 0xba, 0x4c, 0xb6, 0x29, 0x6b, 0x33, 0x51, + 0x4a, 0x45, 0xd2, 0x5c, 0x04, 0xd0, 0x6f, 0x18, 0x8e, 0x1a, 0xe0, 0xce, 0xf5, 0xd8, 0x9b, 0xa1, 0xf1, 0xc6, 0xd4, + 0xd0, 0xb3, 0xad, 0x5e, 0xde, 0x8e, 0x42, 0x98, 0xb1, 0x88, 0x6e, 0xdd, 0xb1, 0x18, 0xbe, 0xa6, 0x0f, 0xa0, 0xc2, + 0xa7, 0x21, 0x46, 0x17, 0x26, 0x75, 0x3d, 0x5d, 0xab, 0xad, 0x74, 0x43, 0x68, 0x8e, 0x51, 0x8d, 0xbc, 0xb6, 0x6d, + 0xa8, 0x11, 0xda, 0x13, 0xca, 0xc3, 0x5b, 0x5a, 0xd1, 0x1b, 0xcb, 0x22, 0x38, 0xf9, 0xb1, 0x97, 0x9f, 0xd0, 0x73, + 0x37, 0x68, 0x3f, 0x15, 0x6d, 0x0d, 0xe0, 0x6f, 0xa8, 0x1f, 0xce, 0xea, 0xa9, 0x95, 0x72, 0x78, 0x0a, 0x5f, 0xb2, + 0x05, 0xb9, 0x82, 0x5e, 0xac, 0x31, 0x3b, 0x89, 0x41, 0x07, 0xb5, 0xb7, 0x3b, 0xbc, 0x49, 0x29, 0x43, 0xb4, 0x46, + 0x74, 0x90, 0x57, 0xff, 0x06, 0x4d, 0x1f, 0xa4, 0x85, 0x29, 0x5d, 0xa3, 0x80, 0x07, 0xf4, 0x4d, 0xfd, 0x7e, 0x8e, + 0xcf, 0xb5, 0x67, 0x99, 0xa6, 0x2c, 0x90, 0x09, 0x5d, 0xba, 0xd2, 0x40, 0x54, 0xbe, 0x75, 0xac, 0x02, 0xb0, 0x22, + 0x09, 0x34, 0x22, 0x01, 0xcb, 0x25, 0x4f, 0x5c, 0xb6, 0x45, 0x83, 0x9a, 0xa8, 0xa4, 0x90, 0x25, 0x92, 0xc0, 0x0f, + 0x23, 0x28, 0x53, 0x14, 0x83, 0xb8, 0x57, 0x2f, 0xaf, 0xb8, 0xa6, 0x06, 0xac, 0x29, 0x82, 0x09, 0xd6, 0xe9, 0x14, + 0x88, 0xad, 0x58, 0xaf, 0xc0, 0x13, 0xd5, 0x5d, 0x24, 0x91, 0x25, 0x40, 0x03, 0x3d, 0x5f, 0x3a, 0xed, 0x96, 0xb7, + 0x27, 0x5a, 0xaa, 0xd8, 0xdc, 0x7b, 0xb1, 0xb0, 0xdc, 0x63, 0xe5, 0x6f, 0x07, 0xda, 0x0b, 0xab, 0x3d, 0x11, 0x35, + 0x58, 0x1d, 0xb6, 0xed, 0xfc, 0x50, 0x1a, 0xaa, 0x7b, 0xe5, 0x98, 0x80, 0x8a, 0xae, 0xe2, 0x6a, 0x19, 0x65, 0x23, + 0xf8, 0xb3, 0xdb, 0x05, 0x87, 0x01, 0x58, 0x84, 0xfe, 0xf2, 0xfe, 0xa7, 0x08, 0xc3, 0x55, 0xfd, 0xf2, 0xfe, 0xa7, + 0xdd, 0xee, 0xc9, 0x78, 0x6c, 0xb8, 0x02, 0xa7, 0xd6, 0x01, 0xfe, 0xc0, 0xb0, 0x0d, 0x76, 0xc9, 0xee, 0x76, 0x4f, + 0x80, 0x83, 0x50, 0x6c, 0x83, 0xd9, 0xc5, 0xca, 0xb1, 0x4d, 0xb1, 0x1a, 0x7a, 0x47, 0x02, 0x76, 0xdf, 0x1e, 0x4b, + 0xb1, 0x4f, 0x7d, 0x54, 0x48, 0x4a, 0xbd, 0xe8, 0x9f, 0x77, 0x0a, 0x2c, 0x29, 0x98, 0xf2, 0x06, 0xcb, 0xaa, 0x5a, + 0x95, 0xd1, 0xe1, 0x61, 0xbc, 0xca, 0x46, 0x65, 0x06, 0xdb, 0xbc, 0xbc, 0xbe, 0x04, 0x80, 0x89, 0x80, 0x36, 0xde, + 0xad, 0x45, 0x66, 0x5e, 0x2c, 0xe8, 0x32, 0xc3, 0x35, 0x09, 0x66, 0x07, 0x39, 0xb7, 0xba, 0xc9, 0x29, 0xb1, 0x0f, + 0x60, 0x83, 0xb9, 0xdb, 0x35, 0xf8, 0x85, 0x93, 0xd1, 0x93, 0xd9, 0x32, 0xd3, 0x06, 0xae, 0xdc, 0xec, 0x7f, 0x12, + 0x79, 0x69, 0xa8, 0xf8, 0x24, 0xd3, 0xe7, 0x19, 0xf0, 0x79, 0xec, 0x4f, 0x11, 0xfa, 0x2c, 0x57, 0xa3, 0x35, 0xc0, + 0xc6, 0x66, 0x17, 0x9b, 0x51, 0xca, 0x21, 0x42, 0x47, 0x60, 0xd5, 0x35, 0xcb, 0x8c, 0xf8, 0x36, 0x15, 0xb7, 0x2d, + 0x55, 0xd8, 0x9f, 0xc2, 0x73, 0xde, 0xe1, 0xc6, 0x71, 0xa8, 0x37, 0x89, 0xc2, 0xe7, 0x28, 0x44, 0xe5, 0x68, 0x5c, + 0xe8, 0xe4, 0x6b, 0x99, 0xc7, 0x84, 0x62, 0x0e, 0xf7, 0xee, 0xaf, 0xd4, 0x99, 0xcb, 0xf8, 0xc2, 0xbd, 0xe7, 0xbe, + 0xcc, 0xe4, 0x5a, 0x02, 0x48, 0x94, 0xaa, 0xfd, 0xf7, 0x2f, 0x48, 0x8d, 0xff, 0x95, 0x6a, 0x0d, 0x40, 0xef, 0x77, + 0xa8, 0xc9, 0x11, 0x04, 0x6c, 0xc5, 0xd4, 0x8f, 0x2e, 0x60, 0x25, 0xf3, 0x3f, 0xa1, 0x6e, 0x47, 0xb0, 0xad, 0x8a, + 0x27, 0x14, 0x55, 0xb4, 0xe0, 0xe9, 0x5a, 0xa4, 0xb1, 0x48, 0x36, 0x11, 0xaf, 0xa7, 0x58, 0x12, 0xb3, 0x11, 0xc3, + 0x7e, 0x6f, 0x76, 0xe1, 0x7d, 0xd1, 0x30, 0x89, 0xa7, 0xa5, 0xbf, 0xad, 0xbc, 0xcd, 0x64, 0x19, 0x67, 0x64, 0xca, + 0x15, 0x82, 0xb9, 0xd5, 0xf7, 0x98, 0x13, 0xfc, 0xf1, 0xd1, 0x63, 0x42, 0xaf, 0xe5, 0xb4, 0x44, 0x90, 0x3e, 0x91, + 0x5a, 0xd7, 0x55, 0xec, 0xd7, 0x14, 0xa2, 0x5a, 0x08, 0x06, 0xa1, 0x4c, 0x4d, 0xfb, 0x14, 0xdf, 0x67, 0xcb, 0xfe, + 0xd3, 0x94, 0x2d, 0xc9, 0x56, 0x40, 0xc7, 0xa4, 0xf3, 0x7e, 0xf5, 0xf6, 0xec, 0xcc, 0xfb, 0x0d, 0x9a, 0x70, 0x50, + 0xdd, 0x40, 0xbb, 0x0a, 0x32, 0x8d, 0x51, 0x6c, 0x16, 0x63, 0xed, 0xd6, 0x44, 0x04, 0x41, 0xb8, 0xcb, 0x59, 0xd8, + 0x6e, 0x27, 0xc4, 0xdb, 0x40, 0x02, 0x05, 0xae, 0x6d, 0x94, 0x93, 0x90, 0xa8, 0x0b, 0x99, 0x39, 0x26, 0x24, 0x0b, + 0xf4, 0x1a, 0x3b, 0x0a, 0xe8, 0x29, 0xb7, 0x4f, 0x01, 0x7d, 0x51, 0xb0, 0x53, 0x3e, 0x08, 0x86, 0x18, 0x6f, 0x36, + 0xa0, 0x9f, 0xa4, 0x7a, 0x04, 0x8f, 0x69, 0x60, 0xb9, 0xe8, 0x9b, 0x82, 0x21, 0xcc, 0xd2, 0x3f, 0x53, 0x36, 0xf9, + 0xee, 0xef, 0x6e, 0x7e, 0xcf, 0xb4, 0x98, 0x1d, 0x84, 0xe2, 0xf6, 0x7a, 0x02, 0xc4, 0xaf, 0xe2, 0x57, 0x60, 0x6d, + 0xae, 0x25, 0xde, 0x9e, 0xe4, 0x41, 0xf8, 0x72, 0x74, 0xfb, 0x49, 0x69, 0x3e, 0x81, 0xa0, 0x3d, 0x4e, 0x52, 0xee, + 0xbe, 0xfb, 0x20, 0x5d, 0x45, 0x30, 0x5a, 0x80, 0xe0, 0x77, 0x67, 0x25, 0x9b, 0xa6, 0xf0, 0x1f, 0xeb, 0x7c, 0x81, + 0xb1, 0x54, 0xe4, 0x07, 0x9c, 0xfe, 0x26, 0x38, 0xb8, 0x7f, 0x2b, 0xb3, 0x86, 0x44, 0x67, 0xea, 0x23, 0xa0, 0xff, + 0x63, 0x3d, 0x7e, 0xa7, 0x28, 0xe9, 0x4b, 0xe2, 0x1c, 0xe1, 0x9b, 0x78, 0x89, 0xa6, 0x8b, 0xbd, 0x71, 0x4d, 0x3f, + 0x17, 0xe6, 0x85, 0x56, 0x70, 0xd8, 0xb7, 0x46, 0xe1, 0x81, 0x67, 0xde, 0xaf, 0xa2, 0x21, 0xe8, 0xfe, 0x11, 0xf7, + 0xc6, 0xaf, 0x82, 0x65, 0x78, 0x53, 0xce, 0x32, 0x73, 0x87, 0xbb, 0xc9, 0x44, 0x2a, 0x6f, 0x18, 0x0b, 0xd6, 0x42, + 0x99, 0xf3, 0xa6, 0xc1, 0x6c, 0x5b, 0x47, 0x2a, 0xd9, 0x7d, 0xff, 0x67, 0xe3, 0x84, 0xcd, 0x06, 0xc1, 0x87, 0x4a, + 0x16, 0xf1, 0x25, 0x0f, 0xa6, 0x5a, 0x45, 0x91, 0x81, 0x5d, 0x21, 0x20, 0xe5, 0x38, 0xed, 0x1d, 0x3c, 0x59, 0x6a, + 0x66, 0x42, 0x7e, 0x5b, 0x9d, 0x05, 0xbc, 0x35, 0xa3, 0x79, 0x5a, 0xc1, 0x2e, 0xf3, 0x95, 0x14, 0x3f, 0xb4, 0x24, + 0xd9, 0x58, 0x7f, 0x43, 0x86, 0x6d, 0xe5, 0x33, 0x67, 0x80, 0xb9, 0xf3, 0x49, 0xaa, 0xa0, 0x7f, 0x3d, 0xc6, 0x6e, + 0x24, 0x12, 0x01, 0xe1, 0x2c, 0x26, 0x6e, 0x85, 0x09, 0x87, 0xe9, 0x02, 0x05, 0xc5, 0x18, 0x28, 0xe8, 0x83, 0x0c, + 0x39, 0x3d, 0xe5, 0x83, 0xa4, 0x31, 0x5b, 0x3f, 0xa8, 0x12, 0xe9, 0x8d, 0x24, 0x74, 0x03, 0xbf, 0xc7, 0x2d, 0x1e, + 0xa8, 0x11, 0xac, 0xd3, 0xdd, 0x9c, 0x0e, 0xdf, 0x14, 0x64, 0xf8, 0x4f, 0xf0, 0x76, 0x8b, 0xed, 0x65, 0x39, 0x81, + 0xc5, 0x1d, 0x7b, 0xc5, 0xd3, 0x5c, 0xb5, 0x38, 0x21, 0x1e, 0xb1, 0xc8, 0x7d, 0x62, 0x01, 0x23, 0x6a, 0x18, 0x8d, + 0x7f, 0x7c, 0x78, 0xfb, 0x46, 0x63, 0x58, 0xe5, 0xfe, 0x07, 0x30, 0xa2, 0x5a, 0xda, 0x6e, 0x07, 0x7c, 0x39, 0x42, + 0x03, 0xf6, 0xd4, 0x0d, 0x76, 0xbf, 0x6f, 0xd2, 0x4e, 0x4a, 0x2f, 0x9b, 0x13, 0x83, 0xee, 0x29, 0x6d, 0x96, 0xca, + 0xc0, 0xb8, 0xab, 0x70, 0x34, 0x27, 0x36, 0x62, 0x55, 0xef, 0xc3, 0x70, 0x49, 0x63, 0x2b, 0x2b, 0xb7, 0xbb, 0x09, + 0x47, 0x36, 0x01, 0xae, 0x4f, 0x41, 0x7b, 0x35, 0xe7, 0xa0, 0x05, 0x25, 0x0a, 0x1c, 0xd1, 0x6e, 0x17, 0x42, 0x44, + 0x92, 0x62, 0x38, 0x99, 0x85, 0xc5, 0x70, 0xa8, 0x06, 0xbe, 0x20, 0x24, 0xfa, 0x5c, 0xcc, 0xb3, 0x85, 0x42, 0x30, + 0xf2, 0x77, 0xd2, 0xaf, 0x85, 0xe2, 0x94, 0x7b, 0xbf, 0x0a, 0xb2, 0xfd, 0x31, 0xc5, 0x18, 0x8c, 0x4e, 0xb3, 0x99, + 0x81, 0x84, 0xf5, 0xb4, 0x22, 0x6a, 0x1d, 0xd9, 0xd9, 0x00, 0x55, 0x2c, 0x9a, 0x06, 0x83, 0xba, 0xc5, 0x13, 0xeb, + 0x19, 0xbd, 0x07, 0x95, 0x20, 0xaa, 0x05, 0xbb, 0x31, 0x5c, 0x6b, 0x9f, 0x45, 0x28, 0x29, 0x27, 0x4d, 0x66, 0xc6, + 0x8a, 0x06, 0x0b, 0x10, 0x92, 0xc6, 0x65, 0xf5, 0x5a, 0xa6, 0xd9, 0x45, 0x06, 0x08, 0x12, 0xce, 0x9f, 0x50, 0x36, + 0xde, 0x3c, 0x55, 0xf3, 0xd2, 0x95, 0x38, 0xb3, 0xb0, 0x27, 0x5d, 0x6f, 0x69, 0x41, 0xa2, 0x02, 0x68, 0x94, 0xaf, + 0xe5, 0xf9, 0x79, 0xcf, 0x2a, 0x64, 0xff, 0xc3, 0xa9, 0xb2, 0x1d, 0xe2, 0x27, 0xac, 0x22, 0xde, 0x69, 0x5d, 0x29, + 0x91, 0x46, 0x47, 0xdb, 0x80, 0x18, 0xb6, 0xec, 0x5b, 0xd4, 0xf0, 0x41, 0xd8, 0x45, 0x27, 0xf9, 0x41, 0x4f, 0xf1, + 0xd8, 0x1a, 0x48, 0xfa, 0x5a, 0x04, 0x5f, 0xa3, 0x23, 0x9d, 0x28, 0xd3, 0x48, 0x4c, 0x21, 0xd1, 0xaf, 0x17, 0x5a, + 0x63, 0x19, 0x65, 0x5f, 0x91, 0xff, 0xbb, 0xee, 0xde, 0xaf, 0x62, 0xb7, 0x83, 0x49, 0xf6, 0x3c, 0xd0, 0x60, 0x53, + 0xa3, 0x56, 0x08, 0x67, 0xe7, 0xb4, 0x42, 0xed, 0x58, 0x2f, 0x2c, 0x81, 0x3c, 0x80, 0xad, 0x48, 0x83, 0x32, 0x48, + 0xf6, 0xb9, 0x98, 0x8b, 0x85, 0x13, 0xe5, 0x48, 0x85, 0x7f, 0x26, 0x47, 0x29, 0x87, 0xab, 0x58, 0x58, 0x30, 0xe4, + 0x57, 0x47, 0x17, 0x85, 0xbc, 0x02, 0x49, 0x89, 0x61, 0xa8, 0x2c, 0xaf, 0x8b, 0xab, 0xb6, 0x24, 0xb4, 0xb7, 0x01, + 0x50, 0x9a, 0x02, 0x04, 0x2f, 0x8d, 0x1a, 0x62, 0xb6, 0x55, 0xbb, 0x2b, 0xba, 0x93, 0x1c, 0x50, 0xa7, 0xbb, 0x76, + 0xeb, 0x4d, 0xd9, 0xaa, 0x5b, 0x71, 0xe1, 0x0f, 0x50, 0xfa, 0x29, 0x1f, 0x14, 0x3e, 0x95, 0xc0, 0x8d, 0xaf, 0x36, + 0x59, 0x76, 0xb1, 0xc1, 0xa5, 0x5f, 0x35, 0xc6, 0xaf, 0xdf, 0xef, 0xa9, 0x85, 0xd0, 0x48, 0x05, 0xe6, 0xdb, 0x67, + 0xa6, 0x2a, 0xa3, 0x29, 0xb5, 0x97, 0xe0, 0xca, 0xd9, 0x8f, 0xa0, 0x22, 0xae, 0x2b, 0x52, 0x9b, 0x1a, 0xa0, 0x03, + 0x2f, 0x2b, 0xdc, 0xca, 0x02, 0x3c, 0x76, 0x02, 0xb2, 0xdb, 0xf1, 0x30, 0xd0, 0x87, 0x4e, 0xe0, 0x6f, 0xc9, 0xd7, + 0xc8, 0xac, 0xd9, 0xc7, 0x7f, 0x68, 0xc1, 0x3f, 0xb6, 0xe0, 0x27, 0x14, 0x77, 0x5a, 0x99, 0x7f, 0x2b, 0xad, 0x5b, + 0xdc, 0xbf, 0x97, 0x69, 0x42, 0x51, 0x99, 0x50, 0xfb, 0x95, 0x56, 0x6b, 0xa3, 0xc6, 0xc0, 0xec, 0x1f, 0x25, 0x7c, + 0x30, 0x6b, 0x3c, 0xb1, 0xc6, 0x93, 0xe1, 0x74, 0x2b, 0x0d, 0xcb, 0x80, 0x42, 0x3f, 0x2f, 0x73, 0x45, 0xf5, 0xf3, + 0xcf, 0x6b, 0xbe, 0xe6, 0xcd, 0x16, 0xdb, 0xa4, 0x7b, 0x1a, 0xec, 0xe5, 0xd1, 0x94, 0xc2, 0x49, 0xd4, 0xb9, 0x91, + 0xa8, 0x8b, 0x9a, 0x65, 0xa8, 0x4e, 0xf0, 0x6a, 0x9e, 0xea, 0x61, 0x6f, 0x26, 0xa2, 0xb5, 0x92, 0xb2, 0xc4, 0x80, + 0xb5, 0x8e, 0x3c, 0x24, 0x77, 0x6b, 0x1d, 0x77, 0x1a, 0xea, 0xd2, 0x14, 0x6a, 0x82, 0x15, 0x2e, 0xc0, 0x11, 0xf4, + 0xbe, 0x08, 0x39, 0x5c, 0x53, 0x95, 0x7e, 0x41, 0x53, 0xf2, 0xc4, 0x53, 0xd4, 0x6a, 0x45, 0xba, 0xfd, 0x28, 0xc7, + 0x6e, 0xf8, 0xc6, 0x09, 0x39, 0x31, 0x42, 0x7f, 0x77, 0x2c, 0xe5, 0x0c, 0x2d, 0x1e, 0xd4, 0x09, 0xd6, 0xcb, 0x5b, + 0x0a, 0x14, 0x73, 0x74, 0x59, 0x75, 0xcd, 0x2b, 0xb4, 0x7d, 0x59, 0xf6, 0xfb, 0xb9, 0xad, 0x27, 0x65, 0x27, 0xdb, + 0xa5, 0xd9, 0x87, 0xa8, 0x98, 0xc2, 0x5d, 0x9f, 0x68, 0xfe, 0x2a, 0xd4, 0x57, 0x6d, 0x99, 0xf3, 0x11, 0x47, 0x9c, + 0x90, 0x9c, 0xd4, 0xff, 0x50, 0x53, 0xaf, 0xc4, 0xfd, 0xaa, 0x92, 0x97, 0xc2, 0x58, 0x31, 0x5a, 0x62, 0x88, 0x22, + 0xed, 0xde, 0x98, 0xbe, 0x2a, 0x00, 0xfe, 0x4a, 0xb0, 0x3f, 0xd3, 0x50, 0x2b, 0xbf, 0x45, 0x5b, 0xc0, 0xbf, 0x55, + 0xdc, 0x80, 0x55, 0x60, 0x80, 0xd1, 0x64, 0x7b, 0x4e, 0x13, 0x38, 0xe0, 0x84, 0x56, 0x51, 0x50, 0x61, 0x86, 0x86, + 0xda, 0xc2, 0xe8, 0x6b, 0x94, 0x71, 0xab, 0xcc, 0xde, 0x8d, 0xb1, 0xd3, 0x02, 0xaf, 0xe1, 0xdf, 0xe8, 0x85, 0x62, + 0x36, 0xea, 0x20, 0x3d, 0x3a, 0x89, 0xe9, 0x8f, 0x5b, 0x38, 0xb9, 0x59, 0x38, 0xcb, 0x9a, 0x25, 0xd0, 0x1d, 0xb8, + 0x20, 0xc6, 0xfd, 0x7e, 0x0e, 0x47, 0xa6, 0x19, 0xf9, 0x82, 0xe5, 0x34, 0x66, 0x4b, 0xaa, 0x3d, 0x0f, 0x2f, 0xab, + 0x30, 0xa7, 0x4b, 0x2b, 0xe3, 0x4d, 0x19, 0xa8, 0x8c, 0x76, 0xbb, 0x10, 0xfe, 0x74, 0x5b, 0xbb, 0xa4, 0xf3, 0x25, + 0x64, 0x80, 0x3f, 0x20, 0x11, 0x45, 0x2c, 0xf0, 0xff, 0xa8, 0x71, 0x4a, 0x4f, 0x94, 0xd6, 0x2c, 0x81, 0xe0, 0x71, + 0xaa, 0x7e, 0x7a, 0xc1, 0xd6, 0x8d, 0xa5, 0xb0, 0xdb, 0x85, 0xcd, 0x04, 0xa6, 0x39, 0x57, 0x32, 0xbd, 0x40, 0x9d, + 0x14, 0x50, 0xb1, 0xf0, 0x02, 0x97, 0x5f, 0x4a, 0x28, 0x34, 0x77, 0xbe, 0x5c, 0x18, 0x25, 0x26, 0xb4, 0x4a, 0x7e, + 0xfd, 0x50, 0x99, 0xaf, 0x8d, 0x87, 0x60, 0xb5, 0x0e, 0x13, 0x53, 0x24, 0x2a, 0x44, 0x67, 0x2f, 0x41, 0x96, 0x23, + 0x00, 0xd7, 0xf3, 0xb5, 0xac, 0x29, 0x5f, 0x43, 0x5c, 0x78, 0x68, 0xd0, 0xbb, 0x42, 0x5e, 0x65, 0x25, 0x0f, 0xf1, + 0x9e, 0xe0, 0x69, 0x46, 0xef, 0x36, 0xf8, 0xd0, 0xd6, 0x1e, 0x3d, 0x41, 0xb6, 0x9e, 0x72, 0xbf, 0x7e, 0x29, 0xc2, + 0x39, 0x44, 0xef, 0x5c, 0x50, 0xad, 0xae, 0x76, 0x80, 0x5c, 0x9e, 0xed, 0xd5, 0x3b, 0x38, 0xdd, 0xf4, 0xf5, 0xad, + 0x0a, 0x9d, 0x39, 0x80, 0xb4, 0x87, 0x64, 0x5d, 0x73, 0xbd, 0x03, 0xdc, 0x91, 0x98, 0xad, 0x81, 0xc6, 0xba, 0xad, + 0xd9, 0x69, 0x8f, 0xe2, 0x31, 0x91, 0x99, 0xb1, 0x48, 0x31, 0xe6, 0x6e, 0x9d, 0x16, 0x45, 0x5b, 0x34, 0x43, 0xd8, + 0xbf, 0xeb, 0x88, 0x75, 0x2b, 0xe2, 0xfc, 0xdd, 0xb6, 0x2f, 0x30, 0x1a, 0xc6, 0x5c, 0xbb, 0xe7, 0x19, 0xba, 0x61, + 0x83, 0x6d, 0x24, 0x41, 0x44, 0x82, 0xcc, 0xd4, 0x81, 0x28, 0x6b, 0x6b, 0xc0, 0xf6, 0x8e, 0xeb, 0x4d, 0x0b, 0xfc, + 0xbc, 0x89, 0xc1, 0xdb, 0xb3, 0xc6, 0x29, 0xad, 0xaf, 0x71, 0xcd, 0x71, 0x55, 0x88, 0xa8, 0x2d, 0x52, 0x00, 0x0c, + 0x3b, 0x5f, 0xe0, 0xce, 0xac, 0x30, 0x98, 0x13, 0x96, 0x4a, 0xf6, 0x2a, 0xd7, 0x9f, 0xc3, 0x16, 0x07, 0xa9, 0x7c, + 0xe9, 0xf5, 0xf7, 0x1f, 0xbe, 0xf8, 0x02, 0xdd, 0xf6, 0x9c, 0x1f, 0x41, 0x90, 0x09, 0x74, 0x50, 0x53, 0xaa, 0xc7, + 0x97, 0x05, 0x50, 0x7b, 0x98, 0x87, 0x97, 0x05, 0x13, 0xf1, 0x75, 0x76, 0x19, 0x57, 0xb2, 0x18, 0x5d, 0x73, 0x91, + 0xca, 0xc2, 0x4a, 0x8d, 0x83, 0xd3, 0xd5, 0x2a, 0xe7, 0x01, 0x98, 0xca, 0x5b, 0x46, 0xd9, 0x09, 0x19, 0xf5, 0xe0, + 0x6a, 0x79, 0x7a, 0xa5, 0x45, 0xe7, 0xe5, 0xf5, 0x65, 0x10, 0xe1, 0xaf, 0x73, 0xf3, 0xe3, 0x2a, 0x2e, 0x3f, 0x05, + 0x91, 0xb5, 0xa9, 0x33, 0x3f, 0x50, 0x2a, 0x0f, 0xfe, 0x4e, 0x20, 0xd3, 0x7d, 0x59, 0x80, 0x65, 0xb6, 0xad, 0xf8, + 0x38, 0xc6, 0x5a, 0x87, 0x13, 0x32, 0x53, 0x25, 0x7a, 0xef, 0x92, 0x75, 0x01, 0xd6, 0x7e, 0x0a, 0xdb, 0x59, 0xe5, + 0x9a, 0x61, 0x65, 0xaa, 0x22, 0x63, 0x00, 0xbf, 0x66, 0x87, 0xa1, 0x75, 0xa2, 0x99, 0xa3, 0xb7, 0x80, 0x7e, 0x20, + 0x87, 0x97, 0xb4, 0x58, 0x33, 0xcf, 0xc7, 0xa6, 0xf1, 0xfa, 0xc1, 0xe1, 0xa5, 0x5b, 0xb0, 0xd7, 0xf6, 0x4e, 0x8e, + 0xc2, 0x44, 0xf0, 0x34, 0x36, 0xe3, 0x8b, 0x3c, 0x2b, 0x60, 0x07, 0x4d, 0xc6, 0x63, 0xea, 0x2d, 0xad, 0xd6, 0xcd, + 0xd1, 0x21, 0xdb, 0x66, 0x0f, 0xab, 0x87, 0x9c, 0x1c, 0xf2, 0x96, 0xa9, 0x6d, 0xdb, 0x3a, 0xce, 0xd3, 0xe4, 0x2b, + 0xd3, 0x7d, 0xb9, 0xb6, 0x11, 0xe2, 0x95, 0xb3, 0xa3, 0xf3, 0x92, 0x6e, 0x7d, 0x53, 0x1a, 0x7a, 0x2d, 0x01, 0x98, + 0x4f, 0x1b, 0xf0, 0x17, 0xac, 0x58, 0x8f, 0x2a, 0x5e, 0x56, 0x20, 0x61, 0x41, 0x11, 0xde, 0x14, 0x7b, 0x53, 0xb8, + 0x1b, 0xa7, 0xe7, 0xb0, 0x03, 0x17, 0x53, 0x74, 0xc7, 0x89, 0xc9, 0xac, 0x34, 0x5a, 0xd1, 0x48, 0xff, 0x72, 0x7d, + 0x89, 0x75, 0x5f, 0xb4, 0x32, 0xcf, 0xe6, 0x54, 0xd8, 0xf4, 0xae, 0x72, 0xe9, 0x44, 0xfd, 0x96, 0x09, 0x57, 0xae, + 0x04, 0x01, 0x99, 0x16, 0xac, 0x57, 0x98, 0x5d, 0x14, 0x23, 0x21, 0x03, 0xc3, 0xd7, 0x60, 0x2d, 0x4a, 0x6e, 0xac, + 0x60, 0xbd, 0x7b, 0xbe, 0x4e, 0x10, 0x52, 0xf0, 0xc0, 0x4d, 0xd0, 0x2f, 0xad, 0x9b, 0xb7, 0xa3, 0x44, 0x19, 0xc4, + 0x27, 0xd7, 0x4e, 0x39, 0x48, 0x20, 0x00, 0x07, 0x56, 0x85, 0x24, 0x51, 0xa0, 0xf3, 0xe0, 0x6a, 0xc6, 0x11, 0x6c, + 0x5e, 0x39, 0x73, 0x71, 0x03, 0x38, 0xaf, 0xfc, 0xb9, 0x6c, 0xb0, 0x65, 0x3d, 0xa2, 0xca, 0x9c, 0x71, 0x8a, 0x41, + 0x9d, 0x2c, 0x41, 0x5f, 0x59, 0x4a, 0x7b, 0x09, 0x9a, 0xc6, 0x2b, 0xb6, 0x52, 0x3e, 0x00, 0xf4, 0x9c, 0xad, 0x94, + 0xb1, 0x3f, 0x7e, 0x7d, 0xc6, 0x56, 0x5a, 0x1a, 0x3c, 0xbd, 0x9a, 0x9d, 0xcf, 0xce, 0x06, 0xec, 0x28, 0x0a, 0xb5, + 0x01, 0x43, 0xe0, 0x22, 0x13, 0x04, 0x83, 0x50, 0xe3, 0xbf, 0x0c, 0x54, 0x80, 0x30, 0xe2, 0xf1, 0xd8, 0x88, 0x23, + 0x16, 0x8e, 0x87, 0x18, 0x0c, 0xac, 0xf9, 0x82, 0x04, 0x84, 0x9a, 0xd2, 0xd0, 0xd7, 0x33, 0x1c, 0x4e, 0x0e, 0x26, + 0x90, 0x8a, 0x99, 0x99, 0x2a, 0x8c, 0x8d, 0x49, 0x04, 0xf1, 0x5f, 0x3b, 0xeb, 0x85, 0x72, 0xbb, 0x6b, 0x34, 0x10, + 0x34, 0x83, 0xaf, 0xaa, 0x78, 0x72, 0x30, 0xec, 0xaa, 0x18, 0x47, 0xe1, 0xda, 0x28, 0xdf, 0xce, 0x8e, 0x01, 0xcc, + 0xf7, 0x6c, 0xe8, 0xcb, 0x25, 0xce, 0x0e, 0x1f, 0x93, 0x87, 0x8f, 0x09, 0x3d, 0x63, 0x67, 0xdf, 0x3c, 0xa6, 0x67, + 0x8a, 0x9c, 0x1c, 0x4c, 0xa2, 0x6b, 0x66, 0x31, 0x70, 0x8e, 0x54, 0x13, 0xe8, 0xe5, 0x68, 0x2d, 0xd4, 0x02, 0xd3, + 0x0e, 0x4d, 0xe1, 0xf7, 0xe3, 0x83, 0x60, 0x70, 0xdd, 0x6e, 0xfa, 0x75, 0xbb, 0xad, 0x9e, 0x57, 0xd7, 0xc1, 0x51, + 0xb4, 0x5f, 0xcc, 0xe4, 0xef, 0xe3, 0x03, 0x37, 0x07, 0x58, 0xdf, 0xfd, 0x63, 0x62, 0x9a, 0xb4, 0x37, 0x2a, 0x7e, + 0x4d, 0x8f, 0xb0, 0x0f, 0xcd, 0x22, 0x3b, 0xfa, 0x30, 0xfc, 0x8f, 0x3a, 0x51, 0x9f, 0x7d, 0x73, 0x04, 0xe4, 0x08, + 0x64, 0xa0, 0x58, 0x22, 0x98, 0xe1, 0x40, 0x53, 0x40, 0x41, 0xa6, 0xc7, 0x9d, 0xea, 0xe1, 0x57, 0xa3, 0xa6, 0x66, + 0xe4, 0x1a, 0xa6, 0x06, 0xdb, 0x82, 0x1f, 0xa8, 0x6e, 0xe8, 0x6f, 0x34, 0xda, 0x93, 0x76, 0x32, 0x33, 0x2f, 0xa9, + 0x8d, 0x73, 0x77, 0x0d, 0x01, 0x9d, 0x1d, 0xdc, 0xa2, 0x64, 0xdf, 0x1e, 0x5f, 0x1e, 0xe0, 0x2a, 0x02, 0xd4, 0x30, + 0x16, 0x7c, 0x3b, 0xb8, 0xd4, 0x9b, 0xfb, 0x20, 0x20, 0x83, 0x6f, 0x83, 0x93, 0x6f, 0x07, 0x72, 0x10, 0x1c, 0x1f, + 0x5e, 0x9e, 0x04, 0xce, 0xb8, 0x1f, 0x42, 0x5e, 0xaa, 0x8a, 0x62, 0x26, 0x4c, 0x15, 0x89, 0xad, 0x3d, 0xb7, 0xf5, + 0x2a, 0xe3, 0x33, 0x9a, 0x4e, 0x2d, 0x12, 0x7a, 0x98, 0xb2, 0xd8, 0xfc, 0x0e, 0x26, 0xfc, 0x2a, 0x88, 0x5c, 0x50, + 0xd8, 0x59, 0x1e, 0xc5, 0x74, 0xc9, 0xae, 0x45, 0x98, 0xd2, 0xe4, 0x30, 0x27, 0x24, 0x0a, 0x97, 0x0a, 0x4c, 0x50, + 0xbd, 0x4e, 0x20, 0xae, 0xad, 0xfb, 0xfc, 0x5a, 0x84, 0x4b, 0x9a, 0x1f, 0x26, 0xa4, 0x55, 0x84, 0x8b, 0x50, 0xb3, + 0xad, 0xe9, 0x05, 0x0b, 0x57, 0xf4, 0x12, 0x98, 0xa9, 0x78, 0x1d, 0x5e, 0x02, 0x97, 0xb7, 0x9e, 0xaf, 0x16, 0xec, + 0xb2, 0x21, 0x7d, 0x33, 0x7c, 0xf1, 0x85, 0xf5, 0xc9, 0x03, 0x1e, 0xd2, 0xf9, 0xe1, 0xa5, 0x60, 0x03, 0x70, 0x9d, + 0xf1, 0x9b, 0x1f, 0xe4, 0xad, 0x9e, 0x97, 0xf6, 0x14, 0xe3, 0xcc, 0xb4, 0x13, 0x93, 0x76, 0x42, 0xee, 0xdf, 0xb7, + 0x7d, 0xf7, 0xe2, 0xb5, 0x72, 0x59, 0xb5, 0x0c, 0x49, 0xb2, 0x56, 0xae, 0xd3, 0x28, 0x39, 0xb5, 0x02, 0x4f, 0x76, + 0xc1, 0xab, 0x64, 0xe9, 0x1f, 0x54, 0xd6, 0x6a, 0xc0, 0x1e, 0x23, 0x96, 0x85, 0xc2, 0xb1, 0x7f, 0x9d, 0xb1, 0x64, + 0xed, 0x0b, 0x34, 0x72, 0xe4, 0xde, 0x5e, 0x67, 0xcc, 0x8b, 0x41, 0xbb, 0x5c, 0x7b, 0xa1, 0xfb, 0xbc, 0xf4, 0xb4, + 0xc5, 0x7b, 0x39, 0xa5, 0x86, 0x91, 0x88, 0x1e, 0x8c, 0x95, 0x19, 0xa5, 0x4a, 0xd4, 0x1a, 0x34, 0x22, 0xd8, 0xd8, + 0x05, 0x03, 0x05, 0x27, 0x54, 0xee, 0xa9, 0xb3, 0x7d, 0x3b, 0xa5, 0xd2, 0x03, 0xda, 0xa5, 0x46, 0x55, 0xee, 0x96, + 0x99, 0x64, 0xd5, 0x20, 0x18, 0xfd, 0x59, 0x4a, 0x31, 0xc3, 0x3b, 0x23, 0x0b, 0xa6, 0x60, 0x25, 0xa8, 0x6a, 0x19, + 0x96, 0x43, 0x8e, 0x5a, 0x3c, 0xe3, 0x93, 0x2a, 0xf5, 0x8f, 0x8e, 0xa0, 0xc1, 0xeb, 0x75, 0x2b, 0x68, 0xf0, 0xe3, + 0xf1, 0x63, 0x3d, 0xd0, 0x17, 0x6b, 0xed, 0x78, 0xe8, 0xf3, 0xdb, 0x88, 0x37, 0xae, 0x7b, 0x4f, 0xb5, 0x56, 0xa1, + 0x0c, 0xb4, 0x58, 0x51, 0xb9, 0x52, 0x4b, 0x7a, 0xb7, 0x8b, 0x00, 0x58, 0xc4, 0xc6, 0x6c, 0xbc, 0x6f, 0x9b, 0x15, + 0x82, 0x46, 0x17, 0x96, 0xe2, 0x80, 0x25, 0xba, 0xb5, 0x83, 0x09, 0x8d, 0x4f, 0x58, 0xd9, 0xef, 0xe7, 0x27, 0x40, + 0x4f, 0xb5, 0x11, 0x53, 0x01, 0x47, 0xfe, 0xd7, 0x56, 0x64, 0x8a, 0x02, 0x9b, 0x35, 0x75, 0xb7, 0xc6, 0x32, 0x12, + 0x7d, 0x99, 0xd2, 0xe5, 0x09, 0xcf, 0x80, 0x69, 0xb5, 0x6e, 0x39, 0xae, 0xec, 0x2b, 0x8e, 0x3c, 0x15, 0x96, 0x15, + 0xe7, 0x55, 0x38, 0xde, 0x7a, 0x7c, 0x83, 0x43, 0xc3, 0xa6, 0x5d, 0xfa, 0x43, 0x08, 0x0b, 0xe1, 0x75, 0x06, 0xb7, + 0x11, 0x6d, 0x27, 0x81, 0xca, 0x1b, 0x73, 0x9d, 0x50, 0x36, 0xb7, 0xab, 0xb5, 0x67, 0x90, 0x4e, 0xcc, 0x81, 0x52, + 0x8d, 0xa0, 0x35, 0x9a, 0x05, 0x55, 0x23, 0x1e, 0x39, 0xf3, 0x2f, 0x67, 0x10, 0xab, 0xe5, 0x4b, 0x9a, 0x4a, 0xd1, + 0x00, 0x8c, 0x0b, 0xe0, 0xf2, 0xf4, 0xcb, 0xfb, 0x9f, 0x3e, 0xf0, 0xb8, 0x48, 0x96, 0xef, 0xe2, 0x22, 0xbe, 0x2a, + 0xc3, 0xad, 0x1a, 0xa3, 0xb8, 0x26, 0x53, 0x31, 0x60, 0xd2, 0xac, 0xa4, 0xe6, 0xae, 0xd4, 0x84, 0x18, 0xeb, 0x4c, + 0xd6, 0x65, 0x25, 0xaf, 0x1a, 0x95, 0xae, 0x8b, 0x0c, 0x3f, 0x6e, 0xf9, 0x9c, 0x1e, 0x02, 0xb0, 0xa9, 0x71, 0x21, + 0x8d, 0xa4, 0x2e, 0xc4, 0x98, 0x8b, 0x78, 0x5d, 0x1f, 0x8f, 0x1b, 0x5d, 0x2f, 0xd9, 0x93, 0xf1, 0xa3, 0xe9, 0xeb, + 0x2c, 0xcc, 0x06, 0x82, 0x8c, 0xaa, 0x25, 0x17, 0x2d, 0x53, 0x4e, 0x65, 0x12, 0x80, 0x3e, 0x9e, 0x3d, 0xc6, 0x8e, + 0xc6, 0x63, 0xb2, 0x6d, 0x8b, 0x07, 0x78, 0xb8, 0x5e, 0x87, 0x05, 0x99, 0xe9, 0x3a, 0xa2, 0x40, 0xf0, 0xdb, 0x2a, + 0x00, 0x64, 0x4b, 0x5b, 0x95, 0xe1, 0xd2, 0xd8, 0x93, 0xf1, 0x84, 0x4a, 0xec, 0x76, 0x48, 0x6a, 0xaf, 0x42, 0x37, + 0xf3, 0xd2, 0xf7, 0x28, 0x92, 0xc6, 0x65, 0x69, 0xaf, 0x52, 0xa9, 0xf6, 0xcc, 0xcc, 0x75, 0x0d, 0x62, 0x52, 0x84, + 0xba, 0xee, 0xd2, 0xab, 0x7b, 0xbf, 0xb9, 0xd6, 0x6c, 0x07, 0xbc, 0xd7, 0xa0, 0x19, 0x4a, 0xde, 0x62, 0xde, 0xba, + 0x22, 0x6a, 0x7a, 0xb5, 0x06, 0xb3, 0x62, 0x94, 0x2d, 0x45, 0x17, 0x6b, 0x0a, 0x4a, 0xc1, 0xe8, 0x72, 0xed, 0x2d, + 0xdc, 0xa7, 0xb2, 0x71, 0x61, 0xc9, 0xf4, 0x6a, 0x51, 0x52, 0x42, 0x75, 0x53, 0x31, 0x52, 0xc2, 0x48, 0x69, 0x78, + 0x2a, 0xdf, 0x0b, 0x3c, 0xce, 0xf3, 0x20, 0x6a, 0x79, 0x81, 0x9d, 0x56, 0xe4, 0x14, 0x1c, 0xbd, 0x4c, 0x4e, 0x43, + 0x81, 0x2b, 0xa1, 0x40, 0x5d, 0x87, 0xea, 0x7e, 0x83, 0x9b, 0xff, 0xb7, 0x82, 0x05, 0x1e, 0xdf, 0x7a, 0x8e, 0xdb, + 0xe8, 0xb7, 0xc2, 0xa7, 0xa5, 0x0f, 0xa4, 0xef, 0xea, 0xe2, 0x49, 0x7b, 0xb3, 0x51, 0xb2, 0xcc, 0xf2, 0xf4, 0x8d, + 0x4c, 0x39, 0x88, 0xcc, 0xd0, 0x1a, 0x94, 0x9d, 0x88, 0xc6, 0x0d, 0x0f, 0x8c, 0x18, 0x1b, 0x37, 0xbe, 0x0a, 0x02, + 0x39, 0x02, 0x72, 0x3f, 0x67, 0xa9, 0x4c, 0xd6, 0x80, 0xb0, 0xa1, 0xe5, 0x27, 0x1a, 0x6f, 0x23, 0xd4, 0xd7, 0x2f, + 0x70, 0x9b, 0x2b, 0x7d, 0x9f, 0xf3, 0x4a, 0xd0, 0x4a, 0x00, 0xf0, 0x4b, 0xbc, 0x02, 0xb9, 0xc7, 0x53, 0xa8, 0x1b, + 0x61, 0x7b, 0x39, 0x06, 0x4b, 0x42, 0x74, 0x14, 0x51, 0xb1, 0x40, 0x41, 0x53, 0x18, 0x44, 0x11, 0x75, 0xc1, 0x1c, + 0x9e, 0xe7, 0x32, 0xf9, 0x34, 0x35, 0x3e, 0xf3, 0xc3, 0x18, 0x63, 0x48, 0x07, 0x83, 0xb0, 0x9a, 0x05, 0xc3, 0xf1, + 0x68, 0x72, 0xf4, 0x04, 0xce, 0xed, 0x60, 0x1c, 0x90, 0x41, 0x50, 0x97, 0xab, 0x58, 0xd0, 0xf2, 0xfa, 0xd2, 0x96, + 0x81, 0x1f, 0xd7, 0xc1, 0xe0, 0xb7, 0xc2, 0x8d, 0xca, 0xbf, 0x41, 0x73, 0xb2, 0x91, 0x61, 0x10, 0xd0, 0xab, 0x35, + 0x01, 0x49, 0x59, 0x4f, 0xf3, 0x93, 0xfa, 0x70, 0x63, 0x4a, 0xfb, 0x67, 0x0e, 0x2f, 0x38, 0xec, 0x90, 0x40, 0x81, + 0x34, 0x9e, 0x66, 0xa3, 0x57, 0x4a, 0x91, 0xfb, 0xae, 0xe0, 0x70, 0x67, 0xee, 0x39, 0xd3, 0x23, 0xa7, 0x90, 0x68, + 0x66, 0x01, 0x37, 0xf2, 0x57, 0xe2, 0x3a, 0xce, 0xb3, 0xf4, 0xa0, 0xf9, 0xe6, 0xa0, 0xdc, 0x88, 0x2a, 0xbe, 0x1d, + 0x05, 0xc6, 0x9a, 0x90, 0xfb, 0xaa, 0x27, 0x40, 0x4f, 0x80, 0x2d, 0x00, 0x06, 0xc4, 0x7b, 0x66, 0x26, 0x33, 0x1e, + 0x81, 0x47, 0x60, 0xd3, 0x07, 0xb2, 0xd8, 0x38, 0x97, 0x24, 0x7f, 0x33, 0x95, 0xf6, 0xaa, 0x57, 0xee, 0x15, 0x64, + 0xbd, 0xda, 0xca, 0x7d, 0xb7, 0x3e, 0xfb, 0xa6, 0xc3, 0x2b, 0xf0, 0x4c, 0x82, 0x5b, 0x64, 0xbf, 0xdf, 0x14, 0x54, + 0x0a, 0xa3, 0x22, 0xde, 0x4b, 0xae, 0xd1, 0xbf, 0xdd, 0x1b, 0x1b, 0x45, 0x72, 0xcb, 0xfb, 0x07, 0x50, 0x67, 0xf2, + 0xae, 0xb8, 0x9d, 0x43, 0xd4, 0xd6, 0xdd, 0x78, 0xe0, 0xbd, 0x41, 0xbb, 0xac, 0x39, 0x82, 0x2d, 0x2f, 0x0e, 0x32, + 0x18, 0x0b, 0x9c, 0x95, 0x91, 0x52, 0xe3, 0x1a, 0x52, 0x0b, 0x3e, 0xc9, 0xd3, 0x3b, 0xc8, 0x52, 0x4f, 0x82, 0x22, + 0xc7, 0xb3, 0x18, 0x32, 0x8d, 0xb7, 0x81, 0xd8, 0x6f, 0x65, 0x08, 0xd2, 0xb4, 0xdd, 0xae, 0x39, 0x02, 0x65, 0xf7, + 0xc0, 0x94, 0xa4, 0xae, 0x8d, 0xa9, 0x81, 0x86, 0x1e, 0x44, 0x8d, 0x54, 0xc4, 0xd9, 0xc9, 0x53, 0xd0, 0x21, 0x82, + 0xef, 0x77, 0x9a, 0x95, 0x1d, 0x2f, 0x26, 0x04, 0x4f, 0xde, 0xe7, 0xb7, 0x59, 0x59, 0x95, 0xd1, 0x9b, 0x14, 0x0d, + 0xa1, 0x12, 0x29, 0xa2, 0xcf, 0x10, 0x5f, 0xb0, 0xc4, 0xdf, 0x65, 0xf4, 0x22, 0xa5, 0x71, 0x9a, 0x62, 0xfa, 0xb3, + 0x02, 0x7e, 0x3e, 0x05, 0x94, 0x4b, 0xdc, 0x09, 0xd1, 0x99, 0x04, 0x7b, 0x35, 0x88, 0xee, 0x55, 0x71, 0xc0, 0x14, + 0x8d, 0xae, 0x05, 0x45, 0xcc, 0x3a, 0xcc, 0xfe, 0x4b, 0x81, 0x42, 0x21, 0x55, 0xcc, 0x4b, 0x61, 0x1f, 0x22, 0xbe, + 0x86, 0x72, 0x4e, 0xdf, 0xbd, 0x32, 0x43, 0x1a, 0xdd, 0x4a, 0xaa, 0xb7, 0x36, 0x1e, 0x5b, 0x88, 0xd2, 0x13, 0x9d, + 0xaf, 0xe9, 0x59, 0xbc, 0xca, 0xa2, 0x2d, 0xe0, 0x4f, 0xbc, 0x7b, 0xf5, 0x54, 0x59, 0x98, 0xbc, 0xca, 0x40, 0x71, + 0x70, 0xfa, 0xee, 0xd5, 0x6b, 0x99, 0xae, 0x73, 0x1e, 0x6d, 0x24, 0x92, 0xd6, 0xd3, 0x77, 0xaf, 0x7e, 0x46, 0x73, + 0xaf, 0xf7, 0x05, 0xbc, 0x7f, 0x01, 0xbc, 0x65, 0x94, 0xaf, 0xa1, 0x4f, 0xea, 0xf7, 0x72, 0x8d, 0x9d, 0xf2, 0x6a, + 0x2d, 0xa3, 0xbf, 0xd2, 0xda, 0x93, 0x56, 0xfd, 0x55, 0xf8, 0xd4, 0xce, 0x13, 0xf0, 0xdc, 0xe6, 0x99, 0xf8, 0x14, + 0x59, 0xd1, 0x4e, 0x10, 0x7d, 0x7b, 0x70, 0x7b, 0x95, 0x8b, 0x32, 0xc2, 0x17, 0x0c, 0xed, 0x82, 0xa2, 0xc3, 0xc3, + 0x9b, 0x9b, 0x9b, 0xd1, 0xcd, 0xa3, 0x91, 0x2c, 0x2e, 0x0f, 0x27, 0xdf, 0x7f, 0xff, 0xfd, 0x21, 0xbe, 0x0d, 0xbe, + 0x6d, 0xbb, 0xbd, 0x57, 0x84, 0x0f, 0x58, 0x80, 0x88, 0xdd, 0xdf, 0xc2, 0x15, 0x05, 0xb4, 0x70, 0x83, 0x6f, 0x83, + 0x6f, 0xf5, 0xa1, 0xf3, 0xed, 0x71, 0x79, 0x7d, 0xa9, 0xca, 0xef, 0x2a, 0xf9, 0x68, 0x3c, 0x1e, 0x1f, 0x82, 0x04, + 0xea, 0xdb, 0x01, 0x1f, 0x04, 0x27, 0xc1, 0x20, 0x83, 0x0b, 0x4d, 0x79, 0x7d, 0x79, 0x12, 0x78, 0x26, 0xaf, 0x0d, + 0x16, 0xd1, 0x81, 0xb8, 0x04, 0x87, 0x97, 0x34, 0xf8, 0x36, 0x20, 0x2e, 0xe5, 0x1b, 0x48, 0xf9, 0xe6, 0xe8, 0x89, + 0x9f, 0xf6, 0xbf, 0x54, 0xda, 0x23, 0x3f, 0xed, 0x18, 0xd3, 0x1e, 0x3d, 0xf5, 0xd3, 0x4e, 0x54, 0xda, 0x73, 0x3f, + 0xed, 0xff, 0x94, 0x03, 0x48, 0x3d, 0xf0, 0xad, 0xff, 0x36, 0x5e, 0x6b, 0xf0, 0x14, 0x8a, 0xb2, 0xab, 0xf8, 0x92, + 0x43, 0xa3, 0x07, 0xb7, 0x57, 0x39, 0x0d, 0x06, 0xd8, 0x5e, 0xcf, 0xc8, 0xc3, 0xfb, 0xe0, 0xdb, 0x75, 0x91, 0x87, + 0xc1, 0xb7, 0x03, 0x2c, 0x64, 0xf0, 0x6d, 0x40, 0xbe, 0x35, 0x06, 0x32, 0x82, 0x6d, 0x03, 0x17, 0x9a, 0x75, 0x68, + 0x03, 0xa6, 0xf9, 0xd2, 0xb8, 0x9a, 0xfe, 0xab, 0xe8, 0xce, 0x86, 0xb7, 0x44, 0xe5, 0xa6, 0x1b, 0xd4, 0xf4, 0x2d, + 0x78, 0x27, 0x40, 0xa3, 0xa2, 0xe0, 0x3a, 0x2e, 0xc2, 0xe1, 0xb0, 0xbc, 0xbe, 0x24, 0x60, 0x97, 0xb9, 0xe2, 0x71, + 0x15, 0x05, 0x42, 0x0e, 0xd5, 0xcf, 0x40, 0x45, 0x02, 0x0b, 0x10, 0xca, 0x08, 0xfe, 0x0b, 0x6a, 0xfa, 0x4e, 0xb2, + 0x6d, 0x30, 0xbc, 0xe1, 0xe7, 0x9f, 0xb2, 0x6a, 0xa8, 0x44, 0x8b, 0x37, 0x82, 0xc2, 0x0f, 0xf8, 0xeb, 0xaa, 0x8e, + 0xfe, 0x05, 0x6e, 0xdc, 0x4d, 0x0d, 0xfb, 0x3b, 0xe9, 0x39, 0xb4, 0xc9, 0x79, 0xb6, 0x98, 0xb6, 0x0e, 0xf4, 0xb7, + 0x92, 0x54, 0xf3, 0x6c, 0x10, 0x0c, 0x83, 0x01, 0x5f, 0xb0, 0xb7, 0x72, 0xce, 0x3d, 0xf3, 0xa9, 0x53, 0xe9, 0x4f, + 0xf3, 0x2c, 0x1b, 0x80, 0x6f, 0x0a, 0xf2, 0x23, 0x87, 0xff, 0x35, 0x1f, 0xa2, 0xf0, 0x70, 0xf0, 0xe0, 0x90, 0xcc, + 0x82, 0xd5, 0x2d, 0x7a, 0x74, 0x46, 0x41, 0x26, 0x96, 0xbc, 0xc8, 0x2a, 0x6f, 0xa9, 0x5c, 0xaf, 0xdb, 0x5e, 0x1e, + 0x77, 0x9e, 0xcd, 0xab, 0x58, 0x04, 0xea, 0x9c, 0x03, 0xc5, 0x1b, 0xca, 0x9e, 0xca, 0xa6, 0x84, 0x54, 0x1b, 0xf2, + 0x86, 0xe5, 0x80, 0x05, 0xc7, 0xbd, 0xe1, 0xf0, 0x20, 0x18, 0x38, 0x75, 0xee, 0x20, 0x38, 0x18, 0x0e, 0x4f, 0x02, + 0x77, 0x1f, 0xca, 0x46, 0xee, 0xce, 0x48, 0x0b, 0xf6, 0x57, 0x11, 0x96, 0x14, 0xc4, 0x63, 0x52, 0x8b, 0xbf, 0x34, + 0xb8, 0xcc, 0x00, 0xa0, 0x8f, 0x94, 0x04, 0xcc, 0xc0, 0xca, 0x0c, 0x20, 0x54, 0x39, 0x8d, 0xd9, 0x2d, 0x30, 0x8f, + 0xc0, 0x31, 0x2b, 0x98, 0x2c, 0x40, 0x2c, 0x09, 0x70, 0xee, 0x82, 0x28, 0xd6, 0x85, 0x9c, 0x42, 0x10, 0x00, 0xfc, + 0x49, 0x4c, 0x29, 0x98, 0xa4, 0x63, 0x37, 0x82, 0x20, 0x8e, 0xcf, 0x6e, 0x44, 0x6b, 0x72, 0x96, 0xe8, 0x60, 0x46, + 0x12, 0x60, 0x43, 0x0c, 0x0c, 0x1f, 0xdc, 0xcf, 0x41, 0xe9, 0x61, 0xf5, 0x4e, 0xc8, 0x05, 0x6f, 0xb8, 0x63, 0xa1, + 0x6e, 0xe0, 0xea, 0x09, 0x07, 0xc1, 0x86, 0x6b, 0x16, 0x60, 0x54, 0x15, 0xeb, 0xb2, 0xe2, 0xe9, 0xc7, 0xcd, 0x0a, + 0x62, 0x01, 0xe2, 0x80, 0xbe, 0x93, 0x79, 0x96, 0x6c, 0x42, 0x67, 0xcf, 0xb5, 0x55, 0xe9, 0x2f, 0x3f, 0xbe, 0xfe, + 0x29, 0x02, 0x91, 0x63, 0x6d, 0x28, 0xfd, 0x86, 0xe3, 0xd9, 0xe4, 0x47, 0xbc, 0xf2, 0x37, 0xf6, 0x86, 0xdb, 0xd3, + 0xa3, 0xdf, 0x87, 0xba, 0xe9, 0x86, 0xcf, 0x36, 0x7c, 0xe4, 0x8a, 0x43, 0x75, 0x85, 0x67, 0x97, 0xb5, 0xf6, 0x8d, + 0x90, 0xee, 0x9f, 0x67, 0xca, 0x1b, 0xf3, 0xa3, 0x1d, 0x0c, 0x83, 0x60, 0xaa, 0x85, 0x92, 0x10, 0x85, 0x84, 0x29, + 0x01, 0x43, 0x74, 0xa0, 0x97, 0xd5, 0x14, 0x39, 0x37, 0x35, 0xb2, 0xf0, 0x7e, 0xc0, 0xb4, 0xd0, 0xa1, 0x91, 0x43, + 0xf9, 0xc1, 0xe1, 0x84, 0x31, 0x0b, 0xbf, 0x55, 0xc2, 0xf4, 0xab, 0x45, 0xe5, 0x1c, 0x44, 0x0f, 0xc0, 0x18, 0x57, + 0xf0, 0x02, 0xba, 0xc2, 0x3e, 0xad, 0x55, 0x94, 0x10, 0x04, 0xd3, 0x43, 0x0e, 0xd0, 0xc3, 0x2e, 0x68, 0x59, 0x59, + 0xaa, 0x5b, 0x95, 0xb3, 0x54, 0x51, 0x97, 0xa1, 0xac, 0x8c, 0x15, 0x06, 0x7e, 0xc9, 0x7e, 0x29, 0xd0, 0xb3, 0x7c, + 0x2a, 0xba, 0xe0, 0x85, 0x50, 0x82, 0xe5, 0xba, 0xde, 0x89, 0x40, 0xd4, 0xf9, 0xa1, 0x77, 0xd5, 0xd7, 0xb8, 0x7e, + 0x3c, 0x7d, 0x2d, 0x53, 0xae, 0x4d, 0x28, 0x34, 0x9f, 0x2f, 0x7d, 0xc5, 0x44, 0xc1, 0x3e, 0x40, 0xbf, 0xda, 0x36, + 0xfa, 0xec, 0x7a, 0xad, 0x37, 0x83, 0x12, 0x1d, 0xf3, 0x1a, 0x05, 0xd7, 0x4a, 0xa1, 0x60, 0xb4, 0xb7, 0xf1, 0x17, + 0x38, 0x72, 0xab, 0xdb, 0x43, 0xef, 0xb7, 0x2a, 0xbe, 0x7c, 0x83, 0xbe, 0x9d, 0xf6, 0xe7, 0xa8, 0x92, 0xbf, 0xac, + 0x56, 0xe0, 0x43, 0x05, 0x91, 0x56, 0x2c, 0x4e, 0x2f, 0xd4, 0xf3, 0xe1, 0xdd, 0xe9, 0x1b, 0xf0, 0xa3, 0xc4, 0xdf, + 0xbf, 0xfe, 0x18, 0xd4, 0x64, 0x1a, 0xcf, 0x0a, 0xf3, 0xa1, 0xcd, 0x01, 0xa1, 0x5a, 0x5c, 0x9a, 0x7d, 0x3f, 0x8b, + 0x9b, 0xec, 0xbb, 0x66, 0xeb, 0x69, 0xd1, 0x44, 0x92, 0x32, 0xdc, 0x3e, 0x18, 0x10, 0xe8, 0x03, 0x44, 0x71, 0xf6, + 0x05, 0x8d, 0x21, 0xcd, 0x67, 0xf6, 0xfd, 0x08, 0x81, 0xaf, 0xf6, 0x42, 0xaa, 0x71, 0x85, 0x45, 0xa3, 0x87, 0x7c, + 0xc6, 0x23, 0x65, 0x58, 0xf4, 0x1e, 0x13, 0x88, 0x33, 0x9c, 0x56, 0xef, 0x11, 0x03, 0x1a, 0xef, 0x06, 0x5a, 0xf6, + 0x10, 0x65, 0xd4, 0x65, 0x6f, 0x58, 0x7c, 0xbf, 0x5e, 0x87, 0x99, 0xb5, 0xbc, 0x1c, 0xc2, 0xdf, 0x40, 0x1b, 0x80, + 0x53, 0x8e, 0x2c, 0x5f, 0x65, 0x36, 0xba, 0x5a, 0x62, 0x7a, 0x13, 0x41, 0x6c, 0x22, 0x9d, 0x0e, 0x6b, 0x57, 0xa7, + 0xea, 0x5d, 0xed, 0x7c, 0x26, 0x7a, 0x15, 0x68, 0xe5, 0xda, 0xf6, 0x78, 0x08, 0xff, 0xa9, 0xa5, 0x15, 0x36, 0xc2, + 0x9e, 0x8b, 0x2f, 0x3c, 0xc7, 0xe6, 0x04, 0x34, 0xb8, 0x92, 0x29, 0x00, 0x67, 0x69, 0x35, 0x1a, 0x35, 0xc2, 0x3e, + 0x2b, 0xe7, 0x73, 0xd8, 0x5a, 0x88, 0xa7, 0x05, 0xe0, 0xc0, 0x4d, 0x4c, 0x4e, 0xde, 0x8d, 0xc9, 0x39, 0xfd, 0xa4, + 0xe0, 0xbe, 0x83, 0xb3, 0x72, 0x19, 0xa7, 0xf2, 0x06, 0xb0, 0x29, 0x03, 0x3f, 0x15, 0x4b, 0xf5, 0x12, 0x92, 0x25, + 0x4f, 0x3e, 0xa1, 0xd5, 0x46, 0x1a, 0x00, 0x57, 0x39, 0x35, 0x96, 0x7b, 0x0a, 0x34, 0xd5, 0x95, 0xa2, 0x12, 0xe2, + 0xaa, 0x8a, 0x93, 0xe5, 0x07, 0x4c, 0x0d, 0xb7, 0xd0, 0x8b, 0x28, 0x90, 0x2b, 0x2e, 0x80, 0xa4, 0xe7, 0xec, 0x1f, + 0x99, 0xc6, 0x5e, 0x7f, 0x20, 0x51, 0xc0, 0xa4, 0x51, 0x94, 0xb1, 0x52, 0xf6, 0x4a, 0x9a, 0xe8, 0x77, 0x41, 0x50, + 0xbb, 0x97, 0x7f, 0x41, 0xdd, 0x4f, 0xa1, 0x15, 0x61, 0x03, 0xbc, 0x50, 0x83, 0x1f, 0xa6, 0x76, 0xc9, 0x79, 0x40, + 0x86, 0xce, 0xfb, 0xac, 0xb6, 0x5b, 0xfd, 0xe9, 0x12, 0xb0, 0x5e, 0x53, 0xe3, 0x53, 0x18, 0x26, 0xc4, 0xc4, 0x4a, + 0xb6, 0xca, 0x4a, 0xbb, 0xa1, 0x4c, 0x3b, 0xe9, 0x92, 0x79, 0x2d, 0x9c, 0xe6, 0x3d, 0xc6, 0x96, 0x23, 0x95, 0xbb, + 0xdf, 0x0f, 0xcd, 0x4f, 0x96, 0xd3, 0x07, 0x3a, 0x84, 0xb5, 0x37, 0x1e, 0x34, 0x27, 0x5a, 0x5d, 0xd5, 0xd1, 0x0f, + 0xe8, 0x00, 0xcc, 0xb4, 0x45, 0xa8, 0x74, 0xc1, 0xb7, 0x7d, 0x25, 0x2a, 0x2e, 0x49, 0x58, 0x2a, 0x09, 0xec, 0xec, + 0xa6, 0x64, 0x67, 0x1b, 0x10, 0xcf, 0x70, 0xd7, 0xd3, 0x62, 0x27, 0xa4, 0x09, 0x6f, 0x71, 0x90, 0x80, 0xa8, 0x43, + 0x55, 0x97, 0x90, 0xad, 0x31, 0x74, 0xf1, 0x2f, 0x4a, 0x61, 0xc2, 0x5a, 0x26, 0x55, 0x89, 0x09, 0x0a, 0x55, 0xee, + 0xb7, 0x08, 0x2c, 0x51, 0xb0, 0x03, 0xd8, 0x7b, 0x37, 0xea, 0x66, 0xd4, 0x54, 0x75, 0xea, 0x25, 0xf8, 0x38, 0xcd, + 0xba, 0x0a, 0x32, 0x0b, 0xbb, 0x2a, 0xd6, 0x3c, 0xd0, 0xb1, 0xba, 0x94, 0x31, 0x71, 0x97, 0x16, 0x19, 0xe2, 0x23, + 0x63, 0x6c, 0x61, 0x0d, 0x47, 0xda, 0x1e, 0x37, 0x3d, 0x41, 0xe8, 0x27, 0x6c, 0x28, 0x81, 0x9b, 0xce, 0xf6, 0xd4, + 0x34, 0xf3, 0x01, 0x11, 0x87, 0x01, 0x05, 0x92, 0x8d, 0x43, 0x9a, 0x23, 0x7d, 0x41, 0xd2, 0x84, 0x81, 0xb2, 0x15, + 0xcf, 0x09, 0xb2, 0xa2, 0xd0, 0xb3, 0x75, 0x55, 0x43, 0xfc, 0x5c, 0x86, 0x39, 0x5a, 0x72, 0x2a, 0x3c, 0x4d, 0x90, + 0x89, 0xdd, 0xd1, 0x36, 0x33, 0x19, 0x8e, 0x92, 0x05, 0xe6, 0x57, 0x10, 0x25, 0xee, 0x4c, 0xb3, 0x2a, 0x07, 0xe3, + 0x02, 0x16, 0x68, 0xe5, 0x7b, 0x50, 0x37, 0xd6, 0xd0, 0x56, 0xc3, 0x32, 0xbb, 0xfd, 0x09, 0xf6, 0x6b, 0xed, 0xb4, + 0x2e, 0x53, 0x2c, 0x2f, 0x53, 0x88, 0xf6, 0x42, 0xe6, 0x37, 0x8a, 0x44, 0xf7, 0x8a, 0x30, 0x24, 0xac, 0xa3, 0xec, + 0x49, 0x9b, 0x1a, 0x40, 0x4f, 0xbd, 0x00, 0xf0, 0x9d, 0x6b, 0x19, 0x76, 0x91, 0xee, 0xaf, 0x0a, 0xc6, 0xa5, 0x1b, + 0x04, 0x29, 0x7a, 0x93, 0x82, 0x39, 0xaf, 0x47, 0x49, 0xbd, 0x39, 0x6d, 0x99, 0x51, 0x75, 0x54, 0x84, 0x94, 0x13, + 0xfc, 0x27, 0xaf, 0xa4, 0x26, 0x36, 0x61, 0x82, 0x07, 0x3e, 0xcc, 0x33, 0x6c, 0xe0, 0xdd, 0xee, 0x34, 0x0d, 0x93, + 0x36, 0xdb, 0x90, 0x82, 0xb4, 0xc2, 0xc4, 0x09, 0x81, 0xca, 0x5e, 0xe1, 0x7e, 0xc1, 0x76, 0xd2, 0x14, 0x3c, 0x08, + 0x1b, 0x0d, 0x4c, 0xdc, 0xea, 0x12, 0x60, 0x34, 0x13, 0x2e, 0xa9, 0x76, 0x76, 0xd2, 0xc2, 0xfa, 0xf6, 0xba, 0xbc, + 0xb0, 0x7d, 0xd0, 0xb1, 0xd4, 0xba, 0x86, 0x07, 0x9a, 0xd7, 0xec, 0xe2, 0x8a, 0x69, 0x9a, 0x68, 0xac, 0x87, 0x94, + 0x25, 0xc7, 0xba, 0x9e, 0xae, 0x70, 0xb5, 0xcc, 0x34, 0xd0, 0xbd, 0xc4, 0x0b, 0x3d, 0xe0, 0x83, 0x87, 0x2b, 0x12, + 0x5d, 0x60, 0xb3, 0xd9, 0xaa, 0x26, 0xd3, 0xfc, 0xae, 0x6c, 0xb9, 0x09, 0x90, 0x67, 0xa9, 0x6f, 0xee, 0x93, 0x63, + 0x4d, 0xdb, 0xfc, 0x24, 0xc0, 0x35, 0xf7, 0x0a, 0x48, 0x3a, 0x96, 0xa0, 0x8b, 0xf7, 0xe9, 0x0f, 0x22, 0x35, 0x53, + 0x41, 0xef, 0x9c, 0x2f, 0x52, 0x37, 0xbf, 0x00, 0xdb, 0xa8, 0xad, 0x35, 0xcd, 0x5a, 0x87, 0x89, 0xb2, 0xb0, 0x46, + 0x16, 0x72, 0x09, 0x3e, 0x98, 0xfb, 0x4d, 0x9d, 0x3e, 0xef, 0x20, 0xc2, 0x7e, 0x17, 0x3d, 0x1e, 0x61, 0xac, 0x58, + 0x83, 0xc4, 0xb0, 0x0a, 0x6b, 0xda, 0x5c, 0x0e, 0x51, 0x4e, 0xcd, 0x92, 0x89, 0x96, 0xd4, 0xa7, 0x14, 0x51, 0x0a, + 0xe6, 0xc6, 0xd3, 0xb2, 0x61, 0x4a, 0x88, 0x90, 0x15, 0xd2, 0x01, 0xd5, 0x5a, 0x68, 0xa9, 0x26, 0x08, 0x78, 0xe8, + 0x65, 0xa1, 0x31, 0x05, 0xd1, 0x47, 0x64, 0xb8, 0x11, 0x47, 0x46, 0xf7, 0xc7, 0x28, 0x26, 0x10, 0xba, 0xdb, 0xcb, + 0x0b, 0xab, 0x4f, 0xcb, 0xb6, 0x3a, 0x88, 0x6b, 0x4c, 0x93, 0x3b, 0x08, 0x6a, 0x8c, 0x82, 0x36, 0xa7, 0x1b, 0xfd, + 0x77, 0x11, 0xfa, 0x76, 0xe1, 0xd8, 0x8d, 0x82, 0x48, 0x88, 0x48, 0xeb, 0x35, 0x15, 0x03, 0xd4, 0xce, 0x63, 0x17, + 0xb1, 0x4a, 0x77, 0x0b, 0x51, 0xde, 0xa8, 0xac, 0x5f, 0xaf, 0x43, 0xb2, 0xdb, 0x61, 0x59, 0xe0, 0xcb, 0xfe, 0x74, + 0x7d, 0x07, 0x04, 0xfa, 0x83, 0xf5, 0x17, 0x21, 0xd0, 0x9f, 0x65, 0x5f, 0x03, 0x81, 0xfe, 0x60, 0xfd, 0x3f, 0x0d, + 0x81, 0xfe, 0x74, 0xed, 0x41, 0xa0, 0xab, 0xc1, 0xf8, 0x67, 0xc1, 0x82, 0xb7, 0x6f, 0x02, 0xfa, 0x4c, 0xb2, 0xe0, + 0xed, 0x8b, 0x17, 0x9e, 0x30, 0xfd, 0x63, 0xa6, 0x91, 0xfc, 0x8d, 0x2c, 0x18, 0x71, 0x5b, 0xe0, 0x15, 0x6a, 0x9d, + 0x7c, 0xa0, 0xa2, 0x0c, 0x80, 0xe8, 0xcb, 0xdf, 0xb2, 0x6a, 0x19, 0x06, 0x87, 0x01, 0x99, 0x39, 0x48, 0xd0, 0xe1, + 0xa4, 0x71, 0x7b, 0xfb, 0x45, 0x34, 0x84, 0x3a, 0x36, 0xf2, 0x00, 0x7c, 0xe5, 0x72, 0xbd, 0xf5, 0x6f, 0x88, 0xf8, + 0xc9, 0xcc, 0x82, 0x8e, 0x1e, 0x06, 0x04, 0x3c, 0x96, 0x32, 0x0f, 0x81, 0x73, 0xee, 0x87, 0x84, 0xfe, 0xb1, 0xf0, + 0x6c, 0x8b, 0x7e, 0x11, 0x61, 0x05, 0x3e, 0x77, 0x7f, 0xad, 0xf9, 0x59, 0x96, 0x12, 0x27, 0x0f, 0xe5, 0x22, 0x91, + 0x29, 0xff, 0xe5, 0xfd, 0x2b, 0x8b, 0x3c, 0x1e, 0x2a, 0xe8, 0x25, 0x82, 0x21, 0x8d, 0x53, 0x7e, 0x9d, 0x25, 0x7c, + 0xf6, 0xc7, 0x83, 0x6d, 0x67, 0x46, 0xf5, 0x9a, 0xd4, 0x87, 0x7f, 0x44, 0x41, 0xa0, 0xc7, 0xe0, 0x8f, 0x07, 0xdb, + 0xac, 0x3e, 0x7c, 0xb0, 0xad, 0x46, 0xa9, 0x04, 0x78, 0x6f, 0xf8, 0x2d, 0xeb, 0x07, 0xdb, 0x12, 0x7e, 0xf0, 0xfa, + 0x0f, 0x0f, 0x98, 0xcd, 0x36, 0xc8, 0xeb, 0x83, 0x55, 0x5e, 0x39, 0x4c, 0xd0, 0x7b, 0x0a, 0x16, 0xa6, 0x50, 0x87, + 0x47, 0xb5, 0xf6, 0xe4, 0x7e, 0x53, 0xdd, 0x75, 0x42, 0xe0, 0x1a, 0xe9, 0x06, 0x0e, 0xa1, 0xb2, 0x04, 0x3b, 0xe9, + 0xe8, 0x94, 0x20, 0xa6, 0xe6, 0xc3, 0x40, 0xd9, 0xfa, 0x7a, 0xc1, 0x8a, 0x5d, 0x33, 0x31, 0xbe, 0xd3, 0x18, 0xd8, + 0x70, 0xd1, 0xd5, 0x62, 0xce, 0xfe, 0x30, 0x3d, 0xde, 0xaf, 0x42, 0x12, 0xc4, 0xc8, 0xf6, 0xfb, 0xc4, 0xeb, 0x59, + 0xca, 0xab, 0x38, 0xcb, 0x59, 0x9c, 0xe7, 0x7f, 0xa0, 0x2c, 0xe2, 0xc7, 0xaf, 0x02, 0xdd, 0x1f, 0x8d, 0x46, 0x71, + 0x71, 0x89, 0x57, 0x7f, 0x43, 0x6e, 0x11, 0x16, 0x3b, 0xe3, 0xa5, 0x0d, 0xac, 0xb2, 0x8c, 0xcb, 0x33, 0x1d, 0xd1, + 0xa8, 0xb4, 0x04, 0xbb, 0x5c, 0xca, 0x9b, 0x33, 0x88, 0xee, 0x60, 0x29, 0x78, 0x8c, 0x03, 0xa8, 0xee, 0x4d, 0x3a, + 0xec, 0xf2, 0xe9, 0x5a, 0xbf, 0x3b, 0x8f, 0x4b, 0xfe, 0x2e, 0xae, 0x96, 0x0c, 0xf6, 0x82, 0xa6, 0xea, 0x85, 0x5c, + 0xaf, 0x5c, 0x25, 0x67, 0x6b, 0xf1, 0x49, 0xc8, 0x1b, 0xa1, 0x68, 0xef, 0x19, 0xbf, 0x86, 0x16, 0xb1, 0x2d, 0xea, + 0xac, 0x04, 0x4f, 0x2a, 0x8f, 0x13, 0x57, 0xb1, 0x00, 0x32, 0x6a, 0xa2, 0x01, 0x74, 0xe4, 0xa0, 0xa1, 0xdd, 0x6b, + 0xda, 0xb1, 0xdc, 0xa8, 0x2c, 0x32, 0xb0, 0x84, 0x7d, 0x0e, 0xa5, 0x03, 0x62, 0x3b, 0x84, 0x0b, 0x81, 0xab, 0x27, + 0x5e, 0x8d, 0x1a, 0x88, 0x3d, 0xb4, 0xf4, 0xdd, 0x85, 0x14, 0xab, 0x45, 0x30, 0xb0, 0x24, 0xac, 0xee, 0xb3, 0x2c, + 0x05, 0x30, 0xde, 0x2c, 0xd5, 0x9a, 0xf3, 0xc6, 0xc0, 0xe1, 0x85, 0x1b, 0x9d, 0x88, 0xd1, 0x1f, 0xda, 0x2d, 0x53, + 0xc6, 0x98, 0xb2, 0x41, 0x2b, 0x7a, 0x28, 0x1a, 0x93, 0xbe, 0xa6, 0x5a, 0x87, 0x98, 0xf3, 0x4c, 0xf4, 0xb6, 0xca, + 0xb9, 0x67, 0x0e, 0xe6, 0x61, 0x7e, 0xf9, 0x80, 0x16, 0x8a, 0x79, 0xcf, 0xc4, 0xfa, 0x8a, 0x17, 0x59, 0x72, 0xb6, + 0xcc, 0xca, 0x4a, 0x16, 0x9b, 0xc5, 0x34, 0xd6, 0x08, 0x93, 0x9a, 0x53, 0xa2, 0x5f, 0xf7, 0x1d, 0x78, 0x29, 0xaa, + 0x60, 0x26, 0xc3, 0x27, 0x63, 0x52, 0x6b, 0xcb, 0x79, 0xe8, 0x1e, 0xb5, 0xbf, 0x75, 0xaf, 0x5d, 0x82, 0xda, 0x44, + 0xee, 0xd9, 0xf6, 0x92, 0x36, 0x9d, 0x20, 0xda, 0x4d, 0xa0, 0x66, 0x9d, 0x15, 0xfc, 0xaf, 0x35, 0x37, 0xa1, 0x10, + 0x42, 0x07, 0xf3, 0x1d, 0x96, 0xc6, 0x0a, 0x46, 0xd1, 0x6f, 0x55, 0xb7, 0x22, 0xcd, 0xad, 0x17, 0xaa, 0x0d, 0x84, + 0xa8, 0xab, 0x64, 0x9a, 0x3e, 0x47, 0x44, 0x77, 0x10, 0xa1, 0xe0, 0xc6, 0xb3, 0x01, 0xc1, 0xba, 0xd6, 0xd6, 0x5c, + 0x2e, 0x66, 0xf7, 0xbe, 0x1d, 0x0c, 0xa2, 0x7b, 0xdf, 0xb3, 0xc9, 0x3d, 0x2b, 0x77, 0x2e, 0x17, 0xc7, 0xc6, 0x18, + 0x73, 0x8a, 0xb6, 0x2d, 0xe1, 0xbb, 0x75, 0xd8, 0xdc, 0x0c, 0x70, 0x1a, 0x6e, 0xaf, 0x78, 0xb5, 0x94, 0x69, 0x14, + 0xfc, 0xf8, 0xfc, 0x63, 0x60, 0x14, 0xd9, 0xb1, 0x86, 0x30, 0xd2, 0xba, 0x9d, 0x5c, 0x5e, 0x86, 0x31, 0xc4, 0xb2, + 0x1e, 0xc9, 0x4f, 0x7b, 0x31, 0x3f, 0xff, 0x78, 0xf9, 0xf1, 0xe3, 0xbb, 0x03, 0x54, 0xff, 0xf4, 0x0e, 0x3e, 0x28, + 0x2c, 0x81, 0x83, 0x07, 0xdb, 0x58, 0x2b, 0xdc, 0xeb, 0x3f, 0xec, 0xc9, 0x15, 0xb7, 0xd4, 0xe5, 0xc6, 0xad, 0xce, + 0xab, 0xa2, 0x35, 0x8e, 0xb1, 0xd3, 0x69, 0xfb, 0x99, 0x95, 0xae, 0x29, 0x40, 0x4d, 0x8a, 0xaa, 0x39, 0x0a, 0x28, + 0xe4, 0x85, 0xb8, 0x0b, 0x61, 0x75, 0xc7, 0xc6, 0xab, 0xba, 0x36, 0x9e, 0x2c, 0xaa, 0x4c, 0x5c, 0x9e, 0x21, 0x2d, + 0xf8, 0x9a, 0x0d, 0x68, 0x63, 0xbc, 0x29, 0xea, 0xe1, 0xed, 0xb4, 0x82, 0x9d, 0x14, 0x4d, 0xe0, 0x32, 0x6d, 0xa2, + 0xbb, 0xd5, 0xb6, 0x2d, 0xa3, 0xd1, 0xa8, 0xac, 0xa7, 0xfe, 0xc7, 0xc6, 0x7e, 0xc4, 0x4f, 0x53, 0xb0, 0x6e, 0xc0, + 0x11, 0xc1, 0xce, 0x35, 0xed, 0xbb, 0x41, 0x29, 0xca, 0x71, 0xd2, 0x4a, 0x98, 0x0d, 0x27, 0xd1, 0x84, 0xd8, 0x68, + 0x13, 0x9a, 0xa2, 0xfd, 0x38, 0x7a, 0xfe, 0xe6, 0xe3, 0xab, 0x8f, 0xff, 0x3e, 0x7b, 0x7a, 0xfa, 0xf1, 0xf9, 0x8f, + 0x6f, 0xdf, 0xbf, 0x7a, 0xfe, 0x01, 0xcf, 0x0b, 0x0d, 0x5f, 0x19, 0x6e, 0xb5, 0x8d, 0x74, 0xb3, 0xac, 0x48, 0xd4, + 0xa4, 0xd9, 0x14, 0x85, 0x1f, 0x85, 0x99, 0x6d, 0x91, 0xbf, 0xbc, 0x79, 0xf6, 0xfc, 0xc5, 0xab, 0x37, 0xcf, 0x9f, + 0xb5, 0xbf, 0x1e, 0x4e, 0x6a, 0x52, 0xbb, 0x99, 0xd3, 0xf1, 0x52, 0xcc, 0xad, 0x00, 0x70, 0x06, 0x2c, 0xd9, 0xca, + 0x80, 0x6c, 0x99, 0x71, 0xec, 0xa0, 0x59, 0x88, 0x3d, 0xe6, 0xd3, 0xac, 0x4a, 0x8d, 0x64, 0xbf, 0x5f, 0xb9, 0x73, + 0x3f, 0xd3, 0x7b, 0x6f, 0xb7, 0x7b, 0xbb, 0x06, 0x27, 0x76, 0x0d, 0x03, 0x0c, 0x86, 0xad, 0x54, 0xbd, 0x89, 0x4a, + 0x6a, 0x0b, 0x89, 0x2a, 0xaa, 0x82, 0x2d, 0x9c, 0x25, 0x71, 0xc5, 0x2f, 0x65, 0xb1, 0x89, 0xb2, 0x51, 0x2b, 0x85, + 0x36, 0x16, 0x43, 0x14, 0xa2, 0x85, 0xb1, 0x9f, 0x44, 0x7a, 0x6a, 0xf7, 0x8b, 0xa8, 0x63, 0x84, 0xe7, 0x2e, 0x8e, + 0x40, 0xbb, 0x60, 0xb2, 0xd8, 0xed, 0x3a, 0x06, 0xb0, 0x93, 0x12, 0x46, 0xf3, 0x4c, 0x91, 0xc8, 0x45, 0x3d, 0x95, + 0x78, 0xf0, 0xa9, 0x53, 0x8d, 0x99, 0x83, 0xf0, 0x54, 0x31, 0xd4, 0xc0, 0xc7, 0x7a, 0xaf, 0x4d, 0xc8, 0x99, 0xff, + 0xaf, 0xbd, 0x67, 0x5b, 0x6e, 0xdb, 0x48, 0xf6, 0x3d, 0x5f, 0x01, 0xc1, 0x5e, 0x1b, 0xb0, 0x01, 0x08, 0x20, 0x75, + 0xa1, 0x49, 0x81, 0x4a, 0x6c, 0xcb, 0x49, 0x76, 0x95, 0x38, 0x65, 0x2b, 0xde, 0x8b, 0x56, 0x25, 0x82, 0xe4, 0x90, + 0xc4, 0x1a, 0x04, 0x58, 0x00, 0x28, 0x4a, 0xa1, 0xb1, 0xdf, 0xb2, 0x9f, 0x70, 0xbe, 0x61, 0xbf, 0xec, 0x54, 0x77, + 0xcf, 0x00, 0x83, 0x0b, 0x29, 0x2a, 0x76, 0xb2, 0x7b, 0xaa, 0x4e, 0x25, 0xb6, 0x89, 0xc1, 0xcc, 0xa0, 0xe7, 0xd6, + 0xdd, 0xd3, 0xd7, 0x32, 0xa5, 0xb4, 0x2b, 0xf8, 0x57, 0x58, 0x21, 0x57, 0x4a, 0x69, 0xcb, 0x81, 0x98, 0xd3, 0xed, + 0xe3, 0xaa, 0x81, 0x55, 0xa1, 0xb8, 0x27, 0x83, 0x99, 0x60, 0x65, 0xd7, 0x89, 0x79, 0x98, 0x75, 0x69, 0xc3, 0x1b, + 0x81, 0x0b, 0xa6, 0x87, 0x1b, 0x6a, 0x8d, 0xbb, 0x5e, 0x29, 0x14, 0x66, 0x5c, 0x9e, 0xd4, 0x13, 0xaf, 0xfc, 0x0c, + 0x5b, 0xba, 0x52, 0x05, 0x7c, 0x63, 0x2a, 0x95, 0x40, 0x0a, 0x16, 0x9c, 0xd2, 0xe7, 0xad, 0x34, 0x3a, 0x8f, 0x56, + 0x42, 0x70, 0x7c, 0xe2, 0x35, 0x14, 0xe2, 0x39, 0xe9, 0x8e, 0x4e, 0x02, 0xfa, 0xe1, 0x64, 0x1b, 0x28, 0x40, 0x56, + 0x4c, 0x70, 0xce, 0xb6, 0x0e, 0xe8, 0x32, 0x75, 0xfd, 0x78, 0x2d, 0xb6, 0x5c, 0x36, 0xf0, 0xf3, 0xb4, 0xb0, 0x25, + 0x96, 0x23, 0xe3, 0x53, 0x2f, 0x47, 0x21, 0x6d, 0xa8, 0xc6, 0xf7, 0x87, 0xeb, 0x37, 0xf2, 0x2d, 0x16, 0x3d, 0x32, + 0xa2, 0xe9, 0xcd, 0x55, 0xd8, 0x2d, 0x1b, 0x69, 0x4d, 0x80, 0x91, 0xe0, 0x49, 0x0c, 0x01, 0x03, 0x33, 0x23, 0xea, + 0xff, 0x36, 0xae, 0xa2, 0x7e, 0xb4, 0xbf, 0xcb, 0x91, 0xff, 0x4f, 0x6f, 0xdf, 0x5f, 0x80, 0x5e, 0xcb, 0x43, 0x45, + 0xf4, 0x5a, 0xe5, 0x36, 0x2c, 0x26, 0x68, 0x8a, 0xd4, 0xae, 0xea, 0x2d, 0x80, 0x3a, 0xe3, 0x8d, 0x61, 0xff, 0xd6, + 0x5c, 0xad, 0x56, 0x26, 0x58, 0xb4, 0x9a, 0xcb, 0x38, 0x20, 0xee, 0x70, 0xac, 0x66, 0x02, 0xa9, 0xb3, 0x0a, 0x52, + 0x87, 0x70, 0xb8, 0x3c, 0x9f, 0xca, 0xfb, 0x59, 0xb4, 0xfa, 0x26, 0x08, 0x64, 0xb1, 0x8d, 0x60, 0xe2, 0xb8, 0x24, + 0xa3, 0x84, 0x0c, 0x34, 0xd0, 0x3e, 0x59, 0x7e, 0x72, 0xcd, 0xed, 0x05, 0xc6, 0xd7, 0xc3, 0xbb, 0x6b, 0xae, 0x93, + 0xc8, 0xe3, 0x11, 0xbf, 0x1f, 0x9c, 0x8c, 0xfd, 0x1b, 0x05, 0x39, 0x4d, 0x57, 0x05, 0x67, 0xae, 0x80, 0x0d, 0x97, + 0x69, 0x1a, 0x85, 0x66, 0x1c, 0xad, 0xd4, 0xfe, 0x09, 0x3d, 0x88, 0x0a, 0x1e, 0x3d, 0xaa, 0xca, 0xd7, 0xa3, 0xc0, + 0x1f, 0x7d, 0x74, 0xd5, 0xc7, 0x6b, 0xdf, 0xed, 0x57, 0xf8, 0x49, 0x3b, 0x53, 0xfb, 0x00, 0xab, 0xf2, 0x4d, 0x10, + 0x9c, 0xec, 0x53, 0x8b, 0xfe, 0xc9, 0xfe, 0xd8, 0xbf, 0xe9, 0x4b, 0xa9, 0x61, 0xb8, 0xde, 0xd4, 0xe5, 0x21, 0x38, + 0x73, 0x4b, 0xb3, 0x04, 0x63, 0x3a, 0x8c, 0x98, 0x56, 0x5c, 0x7e, 0x21, 0xd6, 0x0c, 0xc1, 0xab, 0x8d, 0x50, 0x9c, + 0x1e, 0xc0, 0x55, 0xef, 0xd3, 0x27, 0x2d, 0xb7, 0x43, 0x9d, 0x49, 0x41, 0xda, 0x50, 0xcd, 0x87, 0x55, 0x0c, 0x8c, + 0x34, 0xa3, 0x6b, 0x22, 0x94, 0x5c, 0xa0, 0x1b, 0xa3, 0xcc, 0xc0, 0x0c, 0x3b, 0xde, 0x02, 0x34, 0x8e, 0xfc, 0xa7, + 0x74, 0x23, 0x1e, 0x41, 0x56, 0x6d, 0x09, 0x89, 0xeb, 0x92, 0xce, 0x85, 0x4e, 0x21, 0x8f, 0x13, 0x08, 0xca, 0x12, + 0xfc, 0x0e, 0xe9, 0x41, 0xb4, 0x40, 0x87, 0xac, 0x6e, 0x79, 0x70, 0x1e, 0x2f, 0x13, 0x79, 0xd4, 0xc4, 0xbc, 0x9c, + 0x96, 0x56, 0xa8, 0x5b, 0x5d, 0x2f, 0x11, 0x35, 0x72, 0x2f, 0xd9, 0xb4, 0x64, 0xa0, 0xc3, 0xd3, 0x52, 0xa3, 0x42, + 0x73, 0xc1, 0xab, 0x4f, 0x52, 0x1c, 0x31, 0x43, 0xbb, 0x4c, 0x8c, 0xe8, 0xaa, 0xa0, 0x53, 0x09, 0x21, 0xca, 0x6e, + 0x94, 0x15, 0x01, 0x9c, 0x69, 0xd5, 0xfb, 0x8f, 0xd7, 0x21, 0x12, 0xb6, 0xc4, 0xed, 0x97, 0xf7, 0x41, 0xea, 0x0d, + 0x4d, 0xda, 0xcc, 0xaa, 0xf2, 0xf5, 0x78, 0x18, 0xe4, 0x8b, 0x4d, 0x87, 0x60, 0xe6, 0x85, 0xe3, 0x80, 0x5d, 0x78, + 0xc3, 0xef, 0xb0, 0xce, 0xeb, 0x61, 0xf0, 0x0a, 0x2a, 0x64, 0x6a, 0xff, 0xf1, 0x9a, 0x48, 0x77, 0x13, 0xc2, 0xce, + 0x68, 0x0b, 0x54, 0xbf, 0xc3, 0x53, 0x2e, 0xb1, 0x98, 0x5a, 0x23, 0xb0, 0x44, 0x6e, 0x29, 0x8e, 0x6d, 0x19, 0x32, + 0x9e, 0xf2, 0x07, 0xf6, 0xa6, 0xc2, 0x4f, 0x2d, 0xc0, 0x15, 0x89, 0x13, 0x2c, 0xef, 0x4c, 0x19, 0x58, 0x22, 0xab, + 0xef, 0xa2, 0x95, 0x80, 0x94, 0x4f, 0x00, 0x85, 0xa8, 0x3c, 0x7d, 0x3f, 0x38, 0x91, 0xd5, 0x42, 0x28, 0x3b, 0xa7, + 0x7e, 0xe1, 0x57, 0xa6, 0x2a, 0x45, 0x02, 0xa8, 0xc5, 0xad, 0xda, 0x3f, 0xd9, 0x97, 0x6b, 0xf7, 0x07, 0xdd, 0x33, + 0x69, 0x70, 0xd8, 0xab, 0xb8, 0x37, 0x5f, 0x16, 0x0f, 0xd9, 0x95, 0x02, 0xb7, 0xe4, 0x0c, 0x4a, 0x60, 0x8e, 0xca, + 0x4d, 0x6a, 0xe4, 0x07, 0x52, 0x26, 0x16, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0x91, 0xde, 0xcd, 0x97, 0x90, 0x2c, + 0x33, 0x45, 0x6f, 0x03, 0xfe, 0x6f, 0x31, 0x25, 0x28, 0xe9, 0x66, 0x61, 0x12, 0xc5, 0x2a, 0x0c, 0xb3, 0x9a, 0x37, + 0x49, 0x91, 0xf2, 0xb5, 0xe1, 0x80, 0x1b, 0xc9, 0x2a, 0x4c, 0xd8, 0x7e, 0xb5, 0xa9, 0x34, 0xee, 0x81, 0x5e, 0xfc, + 0x50, 0xf8, 0x60, 0x2a, 0x48, 0x2b, 0x07, 0x70, 0x73, 0x3e, 0xaa, 0xcb, 0xc7, 0xbe, 0xf1, 0xe7, 0xc8, 0x18, 0x7a, + 0xc6, 0xb5, 0x67, 0xfc, 0x10, 0x5e, 0x65, 0x8d, 0x8b, 0x97, 0xe7, 0x92, 0x33, 0x58, 0x4f, 0x83, 0x08, 0x4c, 0xe5, + 0x4b, 0x85, 0x6f, 0x71, 0x9b, 0x91, 0x0b, 0x2f, 0x9e, 0x32, 0x91, 0xc2, 0x4d, 0xbc, 0x15, 0xb2, 0x03, 0x5d, 0x9a, + 0x16, 0x08, 0x4f, 0xb6, 0xc7, 0x4d, 0xeb, 0x7c, 0x6b, 0x94, 0xc6, 0xc1, 0x9f, 0xd8, 0x1d, 0xb0, 0x59, 0x49, 0x1a, + 0x2d, 0x40, 0x66, 0xe5, 0x4d, 0xb9, 0x0e, 0xc2, 0xd0, 0xd8, 0x6e, 0x9f, 0xfb, 0xf4, 0x89, 0x49, 0x59, 0xc5, 0xd2, + 0x68, 0x3a, 0x0d, 0x98, 0x26, 0x65, 0x1f, 0xcb, 0x3f, 0x73, 0xba, 0x67, 0x8b, 0xc8, 0xd5, 0x7a, 0xb6, 0xe9, 0x60, + 0x89, 0x11, 0xb3, 0x9c, 0x1b, 0x04, 0xc4, 0x45, 0xc6, 0x55, 0xc8, 0x90, 0x6b, 0xe2, 0x5c, 0x14, 0x07, 0xd7, 0x1c, + 0x47, 0xcb, 0x61, 0xc0, 0x4c, 0x3c, 0x0d, 0xf0, 0xc9, 0xf5, 0x70, 0x39, 0x1c, 0x06, 0x94, 0x2e, 0x0c, 0xe2, 0xaf, + 0x45, 0x09, 0xca, 0x45, 0x33, 0xbd, 0x07, 0x83, 0xb2, 0xd2, 0x2a, 0xf8, 0x60, 0x33, 0x09, 0x37, 0x07, 0xfa, 0x40, + 0x0a, 0x32, 0xd0, 0xfa, 0x99, 0x76, 0x55, 0xb8, 0xb1, 0xb0, 0x44, 0xed, 0x35, 0xb0, 0x74, 0xee, 0xa5, 0xfa, 0x1e, + 0x67, 0x58, 0xf1, 0xc2, 0xb1, 0xf2, 0x8a, 0xf6, 0xae, 0x6a, 0xa8, 0x64, 0xfa, 0xc5, 0xb3, 0xcb, 0xa9, 0x86, 0xfa, + 0xda, 0xf7, 0xa6, 0x61, 0x94, 0xa4, 0xfe, 0x48, 0xbd, 0xea, 0xbd, 0xf6, 0xb5, 0xcb, 0x79, 0xaa, 0xe9, 0x57, 0xc6, + 0xb7, 0x72, 0x1e, 0x30, 0x81, 0x29, 0x31, 0x0d, 0xd8, 0x86, 0x3a, 0xf2, 0xe9, 0xd9, 0x56, 0x4f, 0x60, 0x64, 0xac, + 0xf3, 0xad, 0x0b, 0xb5, 0x2a, 0x19, 0xc5, 0x30, 0x55, 0x24, 0x64, 0x14, 0xfb, 0x56, 0xef, 0x91, 0x10, 0xe6, 0x9b, + 0xe5, 0x1a, 0x99, 0x86, 0xb4, 0x20, 0xbe, 0x18, 0x04, 0x5f, 0x78, 0x8e, 0xd2, 0xf3, 0x9e, 0xec, 0xf5, 0x50, 0x22, + 0xe3, 0x83, 0x6f, 0xca, 0x1c, 0xc8, 0xe3, 0x75, 0x9a, 0x81, 0xc9, 0x61, 0x18, 0xa5, 0x0a, 0x44, 0x76, 0x83, 0x0f, + 0x0e, 0xaa, 0x56, 0xd2, 0xbc, 0x57, 0x4d, 0xcf, 0x38, 0x16, 0x78, 0x89, 0xb4, 0x14, 0x25, 0x97, 0x10, 0x88, 0x02, + 0x82, 0x94, 0x96, 0xe2, 0x38, 0x71, 0xdf, 0x3c, 0x58, 0xbe, 0x12, 0xff, 0x26, 0xe1, 0xfd, 0x32, 0x3d, 0x7f, 0xbc, + 0x4e, 0x4e, 0x05, 0x51, 0xff, 0x3e, 0xc1, 0xb5, 0x04, 0x76, 0x85, 0x53, 0xf9, 0x4c, 0x55, 0x4e, 0x05, 0x25, 0xc2, + 0xba, 0x25, 0xf4, 0xaa, 0x09, 0x76, 0x37, 0x16, 0x31, 0xf3, 0xb9, 0x18, 0x45, 0x30, 0x60, 0x95, 0xa3, 0x07, 0xc1, + 0x9a, 0x72, 0xde, 0x2a, 0x05, 0x8b, 0x6b, 0x24, 0x18, 0x80, 0xb9, 0x38, 0x8f, 0x30, 0xc8, 0xae, 0x81, 0x91, 0x84, + 0x08, 0x66, 0x62, 0x8c, 0x46, 0x24, 0x27, 0x91, 0xf3, 0xc3, 0xc5, 0x32, 0xc5, 0xc8, 0xf4, 0x00, 0x00, 0xcb, 0x54, + 0x05, 0x2f, 0x8c, 0x80, 0xeb, 0x8b, 0x0b, 0x4f, 0xa6, 0x2a, 0xfe, 0xb8, 0x5e, 0xc6, 0xa5, 0x33, 0x80, 0xe3, 0x70, + 0x18, 0xa8, 0xd7, 0x81, 0xc7, 0x98, 0x0f, 0x63, 0x64, 0x14, 0x69, 0x5d, 0xb4, 0x11, 0xda, 0x3f, 0x34, 0x20, 0x90, + 0x11, 0xf5, 0xd3, 0xd3, 0x82, 0xc6, 0xc1, 0x42, 0xb4, 0xea, 0xd2, 0x30, 0x07, 0x20, 0xa3, 0x3c, 0x85, 0xb9, 0x73, + 0xe1, 0x52, 0x2f, 0x4c, 0xeb, 0xd4, 0x0b, 0x95, 0xec, 0xea, 0x06, 0x38, 0x0d, 0x83, 0xec, 0xba, 0x70, 0x74, 0x2d, + 0xc6, 0x0b, 0x5b, 0x92, 0xca, 0x15, 0xb4, 0x74, 0x73, 0xb9, 0x3d, 0xdb, 0x22, 0xf6, 0xe7, 0x5e, 0x7c, 0x47, 0xe6, + 0x6f, 0x86, 0x6c, 0x23, 0xa7, 0xab, 0x0a, 0xd1, 0x03, 0x9a, 0x00, 0x22, 0x0d, 0xaa, 0xf2, 0x75, 0x5e, 0xc6, 0xf8, + 0x68, 0x73, 0x1b, 0x20, 0xf8, 0xd6, 0xb5, 0xfa, 0x9c, 0x59, 0x24, 0x7f, 0xa4, 0x26, 0x3d, 0x2d, 0xd9, 0x30, 0xbc, + 0xa4, 0x3c, 0xbc, 0xb0, 0xbc, 0xd1, 0x70, 0x30, 0x44, 0x29, 0x08, 0x6e, 0x1c, 0x19, 0x26, 0xc1, 0x6c, 0x5e, 0x51, + 0x7a, 0xf7, 0xbb, 0x2e, 0x07, 0x83, 0xe5, 0x08, 0x61, 0x39, 0x1a, 0x44, 0xb3, 0x9e, 0x58, 0x11, 0xe0, 0x45, 0x80, + 0x0b, 0x89, 0x91, 0x03, 0xa1, 0xfc, 0x98, 0x4a, 0xbe, 0x85, 0x62, 0x38, 0x1a, 0x04, 0x3b, 0x1d, 0x8d, 0xd8, 0x75, + 0x23, 0x6c, 0x15, 0x67, 0x27, 0xfb, 0x54, 0x9b, 0x88, 0x22, 0x55, 0x82, 0x69, 0x88, 0x61, 0x84, 0xc5, 0x2c, 0x40, + 0x82, 0x70, 0xd7, 0x29, 0x2e, 0x3a, 0xd6, 0x1c, 0xd5, 0xd2, 0xce, 0x69, 0x99, 0xe1, 0xc1, 0x56, 0x6a, 0xff, 0x04, + 0x53, 0x7e, 0x02, 0x59, 0x87, 0xa0, 0x58, 0x27, 0xfb, 0xf4, 0xa8, 0x54, 0x4e, 0x44, 0xd1, 0x89, 0x90, 0x41, 0x76, + 0x79, 0x07, 0x0f, 0x3a, 0x2a, 0x49, 0xca, 0x16, 0x50, 0xea, 0x65, 0xaa, 0x32, 0xe7, 0x0c, 0x16, 0x8f, 0xbe, 0x07, + 0xa1, 0x79, 0x6c, 0x70, 0x89, 0x50, 0x95, 0xb9, 0x77, 0x8b, 0x23, 0x17, 0x6f, 0xbc, 0x5b, 0xcd, 0xe1, 0xaf, 0x8a, + 0xb3, 0x96, 0x94, 0xcf, 0xda, 0xa8, 0x76, 0x43, 0x0e, 0xe0, 0x86, 0x3c, 0x6a, 0x5e, 0xdc, 0x99, 0x58, 0xdc, 0xf1, + 0x86, 0xc5, 0x1d, 0x6f, 0x59, 0xdc, 0x80, 0x2f, 0xa4, 0x92, 0x4f, 0x5d, 0x8c, 0xbe, 0xd4, 0xf9, 0xe4, 0x71, 0x7e, + 0xa4, 0xcb, 0xcf, 0x19, 0xce, 0x93, 0x99, 0x04, 0x60, 0x4b, 0xbc, 0x61, 0xae, 0x9a, 0xe6, 0x45, 0x9a, 0x88, 0xfa, + 0xc0, 0xf3, 0x53, 0x27, 0xc6, 0x0d, 0x29, 0xbc, 0xb5, 0xa0, 0x3a, 0x5e, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x1b, + 0x46, 0x3a, 0xdb, 0x32, 0xd2, 0x51, 0xe9, 0xe8, 0xf2, 0x61, 0xd3, 0x21, 0x94, 0x07, 0x05, 0x7b, 0x10, 0xfc, 0x2b, + 0x70, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x97, 0x24, 0xab, 0x28, 0x06, 0x03, 0x05, 0xe8, + 0xe6, 0x61, 0x5b, 0x6a, 0xee, 0x87, 0x3c, 0xf6, 0xd9, 0xc6, 0xcd, 0x54, 0xbc, 0x97, 0xb7, 0x54, 0xeb, 0xf0, 0x90, + 0x6a, 0x2c, 0xbc, 0x34, 0x65, 0x31, 0x4e, 0xba, 0x07, 0x49, 0x32, 0xfe, 0x4b, 0xb6, 0x59, 0x03, 0x0e, 0x09, 0x24, + 0xac, 0x8e, 0x18, 0x7a, 0x01, 0x2c, 0x18, 0x69, 0x24, 0x43, 0x7d, 0x2d, 0xc5, 0x51, 0x8d, 0xf3, 0x89, 0xff, 0x11, + 0x8f, 0xab, 0x16, 0x4b, 0x9e, 0xbe, 0xce, 0x91, 0x6e, 0x2d, 0xbc, 0xf1, 0x7b, 0xb0, 0x83, 0xd1, 0x5a, 0x06, 0xf8, + 0xb4, 0xc8, 0x51, 0x53, 0x63, 0xe2, 0x09, 0x47, 0x05, 0x92, 0x44, 0x2c, 0xc9, 0x2d, 0x86, 0x21, 0xd8, 0x80, 0x67, + 0x4e, 0xae, 0xd6, 0xad, 0x6c, 0x7f, 0xea, 0xeb, 0x35, 0xac, 0x09, 0xa8, 0x2d, 0x70, 0xfb, 0xb9, 0xd0, 0x2d, 0x30, + 0x9c, 0x23, 0x1d, 0x14, 0xa5, 0x97, 0x90, 0x0e, 0xdd, 0x16, 0x97, 0xe9, 0x41, 0x0c, 0x54, 0x0b, 0xd4, 0x8a, 0x4f, + 0xa6, 0xf8, 0xcb, 0xb9, 0xca, 0x9e, 0x0c, 0xf1, 0x57, 0xeb, 0x2a, 0x57, 0x62, 0x55, 0xa4, 0x08, 0xd2, 0x98, 0xd5, + 0x7e, 0x69, 0x3f, 0x91, 0xb9, 0xf6, 0x03, 0xb6, 0x0d, 0x5f, 0xe0, 0x47, 0x8f, 0xd7, 0x09, 0x04, 0x28, 0x90, 0xc7, + 0x10, 0x5a, 0xb1, 0x9e, 0x35, 0x96, 0x4f, 0x37, 0x94, 0x0f, 0xf5, 0xdf, 0x99, 0xf0, 0xe3, 0x2e, 0x89, 0x0a, 0x9a, + 0x52, 0x96, 0x81, 0x5c, 0x0f, 0xfd, 0xd0, 0x8b, 0xef, 0xae, 0xe9, 0x16, 0xa2, 0x09, 0x16, 0x3f, 0x97, 0xed, 0x10, + 0x2f, 0x5a, 0xb6, 0x0e, 0x49, 0x25, 0x45, 0xd5, 0x1d, 0x27, 0xf4, 0xee, 0x9f, 0x62, 0x89, 0xbf, 0x2b, 0x5d, 0x63, + 0xf9, 0x82, 0x94, 0x3e, 0x74, 0xfd, 0x78, 0xad, 0xb1, 0x7a, 0x37, 0x95, 0xd1, 0x56, 0x18, 0x48, 0x58, 0x1e, 0xbc, + 0x12, 0xcf, 0xc7, 0x7e, 0x17, 0xcd, 0x3f, 0x86, 0xd1, 0xad, 0xf9, 0x78, 0x9d, 0x9e, 0xaa, 0x73, 0x2f, 0xfe, 0xc8, + 0xc6, 0xe6, 0xc8, 0x8f, 0x47, 0x01, 0x30, 0x8f, 0xc3, 0xc0, 0x0b, 0x3f, 0xf2, 0x47, 0x33, 0x5a, 0xa6, 0x68, 0xd0, + 0x75, 0xef, 0x0d, 0x5a, 0xcc, 0x09, 0x09, 0x12, 0x91, 0xab, 0x6d, 0x98, 0x05, 0xe5, 0xfd, 0x40, 0x5c, 0xeb, 0x0b, + 0x46, 0xb1, 0xa8, 0x65, 0x80, 0x3f, 0x02, 0xd8, 0x98, 0x41, 0x80, 0x07, 0x43, 0xc5, 0xf5, 0x52, 0x0d, 0x79, 0xa8, + 0xa4, 0x55, 0xcb, 0x33, 0x14, 0x5f, 0x63, 0x0f, 0xbf, 0xfe, 0x73, 0x50, 0xf2, 0x90, 0xcf, 0xe5, 0xbd, 0x7c, 0xde, + 0x08, 0xa1, 0xd4, 0x24, 0xc7, 0xc2, 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0x2d, 0x37, 0xf6, 0x92, 0x64, 0x39, + 0x67, 0x63, 0x52, 0x89, 0x9d, 0x16, 0x40, 0x95, 0xef, 0x21, 0x32, 0x60, 0x7f, 0x5f, 0xb6, 0x8e, 0x0f, 0x5e, 0x81, + 0x81, 0x1f, 0x30, 0x94, 0xd1, 0x64, 0xa2, 0x16, 0xa2, 0x80, 0x7b, 0x9a, 0x39, 0x07, 0x7f, 0x5f, 0xbe, 0x39, 0xb3, + 0xdf, 0xe4, 0x8d, 0x43, 0x60, 0x8c, 0x85, 0xb5, 0x12, 0xe7, 0x8b, 0x25, 0x78, 0xc5, 0x88, 0x26, 0x5e, 0xb8, 0x79, + 0x38, 0x97, 0xa5, 0x2d, 0xbe, 0x60, 0x6c, 0x0c, 0x0c, 0xb7, 0x51, 0x2b, 0xbd, 0x0e, 0xd8, 0x0d, 0xcb, 0x2d, 0xa1, + 0xea, 0x1f, 0x6b, 0x68, 0x81, 0xa1, 0x5a, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0x06, 0x38, 0x06, 0x3e, 0x72, + 0xf9, 0x88, 0x55, 0x8e, 0xd4, 0xc0, 0x50, 0x25, 0x00, 0x36, 0x42, 0x76, 0xba, 0xa1, 0xbc, 0x0b, 0x88, 0x7a, 0x03, + 0x6c, 0x86, 0xa3, 0x77, 0x21, 0xb5, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0x36, 0xcd, 0x58, 0x93, + 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x0e, 0x40, 0x2f, 0x19, 0x21, 0xae, 0x6a, 0x5c, 0x1b, 0xa5, 0x3c, 0xf2, 0x21, + 0x26, 0x7e, 0x0f, 0x59, 0x92, 0x6c, 0x9c, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, 0xa2, 0xdc, 0xb0, + 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x9e, 0x73, 0xf3, 0xce, 0x78, 0x3a, 0x54, 0xb9, 0xe9, + 0xdd, 0xa6, 0xf7, 0x2b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0x8d, 0xa0, 0x69, 0x25, 0xd4, 0x5b, 0x93, 0x2a, 0x61, 0x07, + 0x02, 0xa6, 0x0a, 0x7e, 0x65, 0x93, 0x09, 0x1b, 0xa5, 0x89, 0x2e, 0x64, 0x4c, 0x79, 0xb0, 0x75, 0x70, 0xb2, 0xdd, + 0x73, 0xd5, 0x1f, 0x21, 0xe4, 0x8c, 0x88, 0x49, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xe6, 0x69, 0xa2, 0x1e, 0xcb, 0x53, + 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x86, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0x11, 0xe8, 0x76, 0x54, + 0xb4, 0xed, 0xf8, 0xae, 0x9d, 0x37, 0x87, 0x8e, 0x9d, 0xa9, 0x06, 0xb8, 0x3a, 0x7f, 0xac, 0x6c, 0x63, 0x22, 0x50, + 0xae, 0x7a, 0xfe, 0xf6, 0xd5, 0x9f, 0xce, 0x5e, 0xef, 0x8a, 0x11, 0xb0, 0xcb, 0x36, 0x74, 0xb9, 0x0c, 0xb7, 0x74, + 0xfa, 0xf3, 0x8f, 0x0f, 0xeb, 0xb6, 0xe5, 0xbc, 0x70, 0x54, 0x83, 0xac, 0xd3, 0x25, 0xbc, 0x38, 0x8a, 0x6e, 0x58, + 0xfc, 0xd9, 0xd3, 0x20, 0x77, 0xde, 0x0c, 0xee, 0xdb, 0x9f, 0xce, 0x7e, 0xdc, 0x19, 0xd4, 0x23, 0xc7, 0x06, 0xdc, + 0x9e, 0x46, 0x8b, 0x07, 0x8c, 0xae, 0xad, 0x1a, 0xea, 0x28, 0x88, 0x12, 0xb6, 0x01, 0x82, 0x57, 0xe7, 0x6f, 0xdf, + 0xe3, 0x74, 0x15, 0x2c, 0x08, 0x75, 0xf5, 0x79, 0x83, 0xff, 0xe9, 0xdd, 0xd9, 0xfb, 0xf7, 0xaa, 0x81, 0xc9, 0xba, + 0x13, 0xb9, 0x77, 0xbe, 0x89, 0xef, 0xa1, 0x38, 0x8d, 0x7b, 0x9d, 0xa8, 0x1a, 0x5d, 0xa4, 0xcb, 0xa3, 0xa1, 0xb2, + 0xda, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x3b, 0x8d, 0xab, 0x01, 0x1f, 0x6d, 0x27, 0xa9, 0xa5, 0x92, + 0xb9, 0x1f, 0x5e, 0x37, 0x94, 0x7a, 0xb7, 0x0d, 0xa5, 0x70, 0x7d, 0xac, 0xe1, 0xc7, 0x65, 0x34, 0x97, 0xd8, 0x11, + 0x76, 0x7b, 0xff, 0x74, 0x49, 0x77, 0xb8, 0xcf, 0x00, 0x9a, 0x27, 0x5b, 0xa9, 0x42, 0xdd, 0x50, 0xcc, 0x2f, 0x5e, + 0xf9, 0xdc, 0x8e, 0x02, 0xb0, 0xc9, 0x67, 0xb2, 0x1a, 0xb2, 0xcc, 0xaa, 0x72, 0x8f, 0x1a, 0xb7, 0x72, 0x2b, 0xa0, + 0x66, 0xa4, 0xba, 0xe1, 0x34, 0x65, 0xe1, 0x8d, 0xc1, 0xd0, 0xdd, 0x1c, 0x46, 0x69, 0x1a, 0xcd, 0xbb, 0x8e, 0xbd, + 0xb8, 0x55, 0x95, 0x9e, 0x10, 0x76, 0x70, 0x3b, 0xfc, 0xee, 0xbf, 0xff, 0x55, 0x41, 0xf3, 0x54, 0x7e, 0x9d, 0xb2, + 0xf9, 0x82, 0xc5, 0x5e, 0xba, 0x8c, 0x59, 0xa6, 0xfc, 0xfb, 0x7f, 0x5e, 0x55, 0x2e, 0xf6, 0x3d, 0xb9, 0x0d, 0xb1, + 0xf4, 0x72, 0x93, 0xeb, 0x20, 0x5a, 0xed, 0x15, 0x1e, 0x77, 0xf7, 0x54, 0x9e, 0xf9, 0xd3, 0x59, 0x5e, 0xfb, 0x34, + 0xdd, 0x32, 0x36, 0x01, 0x3d, 0xe9, 0x03, 0x94, 0xf3, 0x68, 0xd5, 0xfd, 0xf7, 0xbf, 0x72, 0x81, 0xcd, 0xbd, 0xbb, + 0xae, 0x19, 0xd0, 0xf2, 0x8a, 0x36, 0xd7, 0xa9, 0x2d, 0x31, 0xbc, 0xaf, 0x2d, 0x70, 0xad, 0x90, 0x76, 0x65, 0x5d, + 0x37, 0xb7, 0x65, 0x4c, 0xdf, 0xf9, 0xd3, 0xd9, 0xe7, 0x0e, 0x0a, 0x26, 0xf4, 0xde, 0x51, 0x41, 0xa5, 0x2f, 0x30, + 0xac, 0x41, 0x77, 0xf7, 0x05, 0xfb, 0xcc, 0x71, 0xdd, 0x37, 0xa4, 0x2f, 0x31, 0x1a, 0x2e, 0xb9, 0x7d, 0x3f, 0x18, + 0xe4, 0xc9, 0x6a, 0xe5, 0xf6, 0xe0, 0x33, 0x78, 0x5a, 0x2b, 0xe1, 0xec, 0x45, 0xd7, 0xd6, 0x29, 0x98, 0xcf, 0x0e, + 0x13, 0x82, 0xd6, 0xef, 0x0d, 0xd3, 0xb1, 0x19, 0x5f, 0x93, 0x13, 0x5b, 0xed, 0xdb, 0x35, 0x64, 0x0d, 0xa5, 0x98, + 0xe8, 0x34, 0xd7, 0x1a, 0x1a, 0xcd, 0xe0, 0xac, 0x62, 0x6f, 0x41, 0x4a, 0x02, 0x05, 0x35, 0x26, 0x20, 0x74, 0xa9, + 0xdc, 0xa2, 0x6f, 0xbc, 0xe0, 0x66, 0xb7, 0x0b, 0xd5, 0x66, 0x0a, 0x86, 0xa4, 0xf9, 0x3f, 0x47, 0xbc, 0x91, 0x2e, + 0x3f, 0x98, 0x76, 0xaf, 0xbc, 0x94, 0xc5, 0xd7, 0x33, 0xf0, 0xf6, 0x15, 0xd2, 0x03, 0x88, 0xa3, 0xbb, 0x0d, 0x29, + 0x97, 0xd8, 0xd2, 0x06, 0x34, 0x5a, 0x60, 0xb8, 0x5f, 0x87, 0xbb, 0xbf, 0x10, 0xe6, 0xee, 0x9e, 0x81, 0x3f, 0xe6, + 0x6f, 0x86, 0xbd, 0xb7, 0x51, 0xa6, 0xff, 0xc7, 0xde, 0xff, 0x8d, 0xd8, 0x7b, 0xeb, 0x77, 0x7e, 0xcd, 0xc2, 0xfe, + 0x1f, 0xc0, 0xf2, 0x5d, 0xe6, 0x9e, 0x71, 0x4c, 0xaf, 0x69, 0x9e, 0xab, 0xc5, 0xa5, 0xc3, 0x8b, 0x78, 0xb5, 0xa6, + 0x60, 0xe5, 0xc1, 0xd6, 0xb8, 0xe5, 0xa0, 0x87, 0xc8, 0x7e, 0xcb, 0x51, 0xfe, 0xed, 0x11, 0x7d, 0x42, 0x19, 0xaa, + 0x24, 0x4c, 0xdf, 0x3d, 0x33, 0x92, 0xd2, 0x48, 0xbc, 0x95, 0x77, 0xb7, 0x0b, 0xde, 0x11, 0xc0, 0x7e, 0xb3, 0xf2, + 0xee, 0x9a, 0x80, 0xdd, 0x88, 0x5e, 0xab, 0x1f, 0x3b, 0x05, 0x2f, 0x9f, 0x2e, 0xba, 0xf8, 0x18, 0x83, 0x84, 0xa5, + 0xa7, 0x50, 0xe8, 0x3e, 0x5e, 0xef, 0x55, 0x2b, 0x66, 0x03, 0xf0, 0x7f, 0x96, 0x00, 0x8f, 0x4a, 0x80, 0xfb, 0xc9, + 0x75, 0x14, 0x3e, 0x04, 0xf2, 0x9f, 0x40, 0xf8, 0xf3, 0xab, 0x41, 0xc7, 0xcf, 0xd5, 0x60, 0xc7, 0xd2, 0x2a, 0xf0, + 0x58, 0x58, 0x85, 0xbe, 0xd7, 0x2c, 0xab, 0xaf, 0x10, 0x5a, 0xa4, 0xb1, 0x8c, 0x08, 0xad, 0x02, 0x7a, 0x15, 0x05, + 0x74, 0x5c, 0x15, 0x92, 0xeb, 0x87, 0x93, 0xd8, 0x8b, 0xd9, 0x78, 0xf3, 0x15, 0xa0, 0x64, 0x9d, 0x7c, 0x67, 0x25, + 0xcb, 0xc5, 0x22, 0x8a, 0xd3, 0xe4, 0x1a, 0xe3, 0xb4, 0xcc, 0x7d, 0xb8, 0x50, 0x40, 0x46, 0xb1, 0x3c, 0x6a, 0xef, + 0x59, 0x93, 0x7c, 0xdb, 0x60, 0x6e, 0x39, 0xd9, 0x06, 0xf7, 0xbe, 0x31, 0xb8, 0xff, 0xce, 0x4c, 0xd2, 0x5f, 0xcc, + 0xac, 0x34, 0xf6, 0xe7, 0x9a, 0x6e, 0x38, 0xb6, 0xae, 0x0b, 0xf9, 0xca, 0xcc, 0xed, 0xef, 0x51, 0xb4, 0xe1, 0x99, + 0x0e, 0x51, 0x0b, 0xd1, 0xa3, 0x05, 0x6c, 0xe5, 0x5e, 0x2e, 0x27, 0x13, 0x16, 0x6b, 0x22, 0x2c, 0x23, 0xc4, 0x85, + 0x25, 0x63, 0x40, 0xf0, 0x73, 0xfc, 0xe0, 0xb3, 0x15, 0xe4, 0x7f, 0x2a, 0xc2, 0xaa, 0x83, 0xaf, 0x27, 0x99, 0x93, + 0x43, 0x6e, 0xb9, 0xb4, 0xdd, 0xd2, 0xc6, 0xcf, 0x0e, 0x8c, 0x19, 0x04, 0x63, 0x2a, 0xdc, 0xe3, 0x31, 0xce, 0x9f, + 0x1f, 0xa6, 0x1d, 0xfc, 0x02, 0x74, 0x00, 0x87, 0x37, 0x70, 0x73, 0xbf, 0x28, 0x65, 0x94, 0x77, 0x38, 0x73, 0xfb, + 0xc1, 0x73, 0x97, 0xf4, 0x3c, 0x68, 0xb7, 0xf7, 0x6a, 0xe6, 0xc5, 0xaf, 0xa2, 0x31, 0x43, 0x40, 0x87, 0x69, 0x04, + 0xde, 0x9a, 0x52, 0x18, 0x1e, 0x8c, 0xc2, 0x63, 0x96, 0x22, 0xf3, 0xec, 0x43, 0xd1, 0xb5, 0x5c, 0xe4, 0x3e, 0x7f, + 0xbc, 0x6f, 0xc0, 0x49, 0x6b, 0x5e, 0x69, 0xb1, 0x68, 0x7c, 0xa9, 0x1b, 0x5f, 0xc9, 0xbb, 0xf5, 0x95, 0x17, 0xc7, + 0x3e, 0x8b, 0x15, 0xed, 0xbb, 0x5f, 0x74, 0x79, 0xd3, 0x96, 0x14, 0x3a, 0x5c, 0xcb, 0xac, 0x60, 0x34, 0xba, 0x89, + 0xcf, 0x82, 0xb1, 0xab, 0x8e, 0xa8, 0x61, 0xae, 0xbc, 0x69, 0x77, 0x6c, 0xdb, 0xe6, 0x0a, 0x53, 0x87, 0x7e, 0x82, + 0xc2, 0x14, 0x7e, 0xc2, 0x43, 0x49, 0xbc, 0xd8, 0x21, 0x2e, 0xa2, 0x46, 0xce, 0x1a, 0x21, 0x7c, 0x47, 0xf1, 0x7c, + 0x1e, 0x02, 0x1b, 0x8f, 0xfb, 0x23, 0x40, 0x73, 0x04, 0x58, 0x05, 0x4c, 0x15, 0x80, 0x0e, 0x1f, 0x02, 0xd0, 0x85, + 0x3f, 0xf7, 0xc3, 0x69, 0xb2, 0x11, 0x22, 0x54, 0x9b, 0x96, 0xe0, 0x49, 0xa9, 0x85, 0xaa, 0xe0, 0x1a, 0xce, 0xa2, + 0x00, 0xf2, 0x10, 0xa9, 0xcc, 0x9a, 0x5a, 0xca, 0x0b, 0xdb, 0xb6, 0x0d, 0xf3, 0x00, 0x32, 0xfe, 0x1d, 0x1e, 0xd9, + 0x86, 0x09, 0x7f, 0x59, 0x96, 0xd5, 0x20, 0x8f, 0xed, 0xcd, 0xfd, 0xd0, 0xa4, 0xc7, 0x96, 0xbd, 0x1b, 0xbc, 0xf7, + 0x5a, 0xf5, 0x26, 0x5c, 0x37, 0x36, 0xcc, 0x5d, 0x47, 0xb5, 0xa1, 0x9b, 0x94, 0x6d, 0xdd, 0x2c, 0x0a, 0xb8, 0xc4, + 0xe3, 0x61, 0x54, 0x88, 0xd1, 0xb0, 0xfc, 0x16, 0xd9, 0xd2, 0xb8, 0x9a, 0xc7, 0x42, 0xfd, 0x9e, 0x83, 0xd5, 0x55, + 0x5e, 0x45, 0xcb, 0x60, 0x8c, 0xe6, 0x50, 0x60, 0xbb, 0xac, 0x14, 0x56, 0xa1, 0x95, 0x64, 0x53, 0x90, 0x4b, 0x1c, + 0x13, 0xad, 0xbd, 0x47, 0xe2, 0x14, 0xc5, 0xda, 0x53, 0x9c, 0xe2, 0xcb, 0xa6, 0x2d, 0x78, 0xf5, 0x14, 0xe2, 0x09, + 0xed, 0xd0, 0x80, 0xef, 0x0b, 0xa8, 0x1f, 0xec, 0x52, 0x5f, 0xac, 0xdb, 0xd5, 0x53, 0x0a, 0x3a, 0xeb, 0x7d, 0xfa, + 0xb4, 0x37, 0xfa, 0xf4, 0x69, 0xaf, 0x96, 0xa9, 0x63, 0xf3, 0x08, 0x69, 0x63, 0x30, 0x1e, 0x62, 0x04, 0xe2, 0x06, + 0x11, 0xd0, 0xdf, 0x43, 0x79, 0xd7, 0xe3, 0xd1, 0xaa, 0xe8, 0x69, 0x64, 0xf0, 0x0f, 0xd2, 0x63, 0x90, 0x55, 0x26, + 0x65, 0xe6, 0x7a, 0x24, 0xe6, 0xf9, 0xf4, 0x89, 0x1f, 0x37, 0x63, 0xec, 0x8e, 0xf2, 0x22, 0x47, 0x35, 0x96, 0x6e, + 0x90, 0x3f, 0xaa, 0x08, 0xf2, 0x92, 0x63, 0xcc, 0x02, 0xe2, 0x95, 0x17, 0x87, 0x32, 0xc0, 0x3f, 0x46, 0x0a, 0xff, + 0xac, 0xc2, 0x23, 0xa2, 0x8e, 0xab, 0xab, 0x31, 0x71, 0x99, 0xb6, 0x24, 0x1c, 0x28, 0x2c, 0xdd, 0xa4, 0x0e, 0x2e, + 0x04, 0xb6, 0xc7, 0xb4, 0xa8, 0x62, 0x80, 0xe8, 0x5f, 0x8d, 0x27, 0x77, 0x2c, 0x86, 0xf5, 0xce, 0x5b, 0x75, 0x97, + 0xe2, 0xe1, 0x8c, 0x4c, 0xe2, 0xbb, 0x93, 0xdc, 0x6f, 0x79, 0x41, 0x5e, 0x87, 0x53, 0xf7, 0xdb, 0x58, 0x5b, 0x18, + 0xa9, 0xa1, 0x0a, 0x32, 0xa2, 0xea, 0xc6, 0xbc, 0x29, 0xc0, 0x6a, 0x6f, 0xce, 0xc3, 0xcd, 0x68, 0x62, 0x2b, 0x5c, + 0x4f, 0xd0, 0x57, 0x21, 0x1c, 0xdd, 0x61, 0x00, 0xe5, 0xe2, 0x3d, 0x81, 0x72, 0xcd, 0xb3, 0xef, 0x8d, 0xe5, 0x57, + 0xb0, 0xe0, 0xaa, 0x31, 0xd1, 0x0d, 0xf2, 0x01, 0x98, 0x7e, 0x49, 0x73, 0x7f, 0x8a, 0xa9, 0x3c, 0x97, 0xc2, 0xbd, + 0x0a, 0x07, 0x80, 0xeb, 0x8a, 0x03, 0x40, 0xc3, 0x7c, 0x2a, 0x31, 0x4b, 0x16, 0x51, 0x08, 0x77, 0xc5, 0xeb, 0xc2, + 0xc3, 0xeb, 0xba, 0xee, 0xe1, 0xd5, 0xd0, 0x14, 0xdf, 0x50, 0x3b, 0x50, 0x49, 0x5f, 0xfc, 0xa5, 0x62, 0xa1, 0x2f, + 0x48, 0x3d, 0x66, 0x29, 0x3f, 0xdb, 0xe4, 0xd9, 0xfd, 0xfd, 0xfd, 0x9e, 0xdd, 0xe7, 0x3b, 0x79, 0x76, 0x7f, 0xff, + 0xc5, 0x3d, 0xbb, 0xcf, 0x64, 0xcf, 0x6e, 0x20, 0xc1, 0x67, 0x6c, 0x27, 0x47, 0x5a, 0xe1, 0xd2, 0x12, 0xad, 0x12, + 0xd7, 0xe1, 0x9a, 0xb5, 0x64, 0x34, 0x63, 0x60, 0xaa, 0xc0, 0x59, 0xdd, 0x20, 0x9a, 0x82, 0xbf, 0xeb, 0x66, 0x8f, + 0xd6, 0x2f, 0xe5, 0xcf, 0x1a, 0x44, 0x53, 0x55, 0xca, 0xd3, 0x16, 0x8a, 0x3c, 0x6d, 0x10, 0x9b, 0xee, 0xef, 0xb7, + 0xce, 0xcb, 0x4b, 0xa7, 0xd7, 0x76, 0x20, 0xce, 0x29, 0x68, 0x9f, 0xb1, 0xc0, 0xee, 0xb5, 0xdb, 0x50, 0xb0, 0x92, + 0x0a, 0x5a, 0x50, 0xe0, 0x4b, 0x05, 0x87, 0x50, 0x30, 0x92, 0x0a, 0x8e, 0xa0, 0x60, 0x2c, 0x15, 0x1c, 0x43, 0xc1, + 0x8d, 0x9a, 0x5d, 0x86, 0xb9, 0xdf, 0xfa, 0xb1, 0x7e, 0x55, 0x4a, 0xd1, 0x99, 0x9b, 0x4a, 0x88, 0x2a, 0xc7, 0x86, + 0xc8, 0x17, 0x61, 0x1e, 0xe8, 0x9c, 0x47, 0x1b, 0x7c, 0x35, 0x00, 0xcc, 0x0b, 0x96, 0x23, 0x06, 0xd8, 0xdd, 0x50, + 0xcd, 0xb6, 0x78, 0xad, 0x76, 0x73, 0x3f, 0x6f, 0xdb, 0x68, 0x09, 0xbf, 0xe9, 0x2e, 0x46, 0xf1, 0x10, 0x95, 0x0f, + 0x9f, 0xcf, 0xf2, 0xe0, 0xd1, 0x4b, 0xb7, 0x08, 0x86, 0xd3, 0x86, 0x14, 0x3a, 0x9c, 0x57, 0x63, 0x1a, 0xd8, 0xcb, + 0x40, 0xac, 0x13, 0x71, 0x8a, 0xc4, 0x07, 0x14, 0x74, 0x86, 0xef, 0x79, 0x05, 0x0f, 0xc7, 0x43, 0xad, 0x13, 0xf4, + 0xf3, 0x3c, 0x82, 0x35, 0xe9, 0x52, 0x97, 0x46, 0xea, 0x4d, 0xbb, 0x33, 0x83, 0x0c, 0xa9, 0xba, 0x53, 0x48, 0x49, + 0x72, 0x3a, 0xee, 0x2e, 0x8c, 0xd5, 0x8c, 0x85, 0xdd, 0x09, 0x77, 0x3b, 0x84, 0xf5, 0x27, 0x4f, 0x92, 0xb9, 0x2e, + 0x5c, 0xa0, 0x70, 0x4f, 0x14, 0x6f, 0x09, 0x4a, 0x33, 0xdf, 0x4a, 0x85, 0xf7, 0x8e, 0x26, 0x1b, 0x59, 0x7d, 0x09, + 0x5f, 0x8b, 0xd7, 0x6c, 0xb8, 0x9c, 0x2a, 0xe7, 0xd1, 0xf4, 0x5e, 0xbf, 0x0a, 0xf9, 0x15, 0x40, 0xa9, 0x92, 0x35, + 0xa9, 0x29, 0xb6, 0x37, 0xff, 0x16, 0x3d, 0x66, 0xe5, 0xfa, 0x29, 0xc0, 0xa6, 0xa4, 0xc4, 0x36, 0xc0, 0x77, 0x60, + 0xb6, 0x25, 0xcf, 0x85, 0x73, 0x98, 0x3f, 0xe9, 0xf9, 0xc2, 0x93, 0xe0, 0xe9, 0xff, 0xc0, 0x92, 0xc4, 0x9b, 0x32, + 0x19, 0xb5, 0x94, 0x3a, 0x07, 0x2c, 0x98, 0xab, 0x93, 0x71, 0x02, 0x81, 0xb1, 0xf7, 0x6b, 0xfe, 0x28, 0xe0, 0x32, + 0x0b, 0x7e, 0x5a, 0xb0, 0x68, 0x85, 0xf3, 0x86, 0x6f, 0xc1, 0xf2, 0x94, 0xfd, 0x28, 0x00, 0x89, 0xdc, 0xb0, 0xa0, + 0x5a, 0x98, 0x7a, 0xd3, 0x6a, 0x11, 0xad, 0x75, 0x56, 0x42, 0x7b, 0x7a, 0xe9, 0x51, 0xe0, 0xc2, 0xcf, 0xb0, 0xcb, + 0x0f, 0xa2, 0xe9, 0x6f, 0x6a, 0x94, 0xbf, 0xc5, 0x99, 0xe2, 0x87, 0xd0, 0x08, 0xd3, 0x81, 0x85, 0x73, 0xac, 0x58, + 0x30, 0x85, 0xdd, 0x30, 0x9d, 0x99, 0x18, 0x58, 0x4e, 0x6b, 0x85, 0xba, 0x61, 0xe1, 0xda, 0xae, 0xab, 0xe1, 0x34, + 0xbb, 0xf1, 0x74, 0xe8, 0x69, 0x4e, 0xeb, 0xd8, 0x10, 0x7f, 0x2c, 0xfb, 0x50, 0xcf, 0xb0, 0x07, 0x65, 0xec, 0xdf, + 0xac, 0x27, 0x51, 0x98, 0x9a, 0x13, 0x6f, 0xee, 0x07, 0x77, 0xdd, 0x79, 0x14, 0x46, 0xc9, 0xc2, 0x1b, 0xb1, 0x9e, + 0xc4, 0x8f, 0x62, 0xa0, 0x66, 0x1e, 0x2b, 0xd0, 0xb1, 0x5a, 0x31, 0x9b, 0x53, 0xeb, 0x3c, 0x0e, 0xf3, 0x24, 0x60, + 0xb7, 0x19, 0xff, 0x7c, 0xa9, 0x32, 0x55, 0xc5, 0x2d, 0x47, 0x2d, 0x80, 0x65, 0xe6, 0x41, 0x9e, 0x21, 0xb5, 0x41, + 0x8f, 0x4b, 0x1d, 0xbb, 0x56, 0xeb, 0x30, 0x66, 0x73, 0xc5, 0x3a, 0xdc, 0xd8, 0x79, 0x1c, 0xad, 0xfa, 0x00, 0x2d, + 0x36, 0x36, 0x13, 0x16, 0x4c, 0xf0, 0x8d, 0x89, 0x71, 0xa5, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, 0x6c, 0xde, + 0x83, 0xd7, 0xdd, 0x96, 0x62, 0x4b, 0xfc, 0xf4, 0xb1, 0xbd, 0x90, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, 0x75, 0x47, + 0xb1, 0x7b, 0xa0, 0x3f, 0x9e, 0x04, 0xd1, 0xaa, 0x3b, 0xf3, 0xc7, 0x63, 0x16, 0xf6, 0x10, 0xe6, 0xbc, 0x90, 0x05, + 0x81, 0xbf, 0x48, 0xfc, 0xa4, 0x37, 0xf7, 0x6e, 0x79, 0xaf, 0x07, 0x9b, 0x7a, 0x6d, 0xf3, 0x5e, 0xdb, 0x3b, 0xf7, + 0x2a, 0x75, 0x03, 0x31, 0xac, 0xa8, 0x1f, 0x0e, 0xda, 0xa1, 0x62, 0x57, 0xc6, 0xb9, 0x73, 0xaf, 0x8b, 0x98, 0xad, + 0xe7, 0x5e, 0x3c, 0xf5, 0xc3, 0xae, 0x9d, 0x59, 0x37, 0x6b, 0xda, 0x18, 0x8f, 0x3a, 0x9d, 0x4e, 0x66, 0x8d, 0xc5, + 0x93, 0x3d, 0x1e, 0x67, 0xd6, 0x48, 0x3c, 0x4d, 0x26, 0xb6, 0x3d, 0x99, 0x64, 0x96, 0x2f, 0x0a, 0xda, 0xad, 0xd1, + 0xb8, 0xdd, 0xca, 0xac, 0x95, 0x54, 0x23, 0xb3, 0x18, 0x7f, 0x8a, 0xd9, 0xb8, 0x87, 0x1b, 0x89, 0xfb, 0x3f, 0x1f, + 0xdb, 0x76, 0x86, 0x18, 0xe0, 0xb2, 0x84, 0x9b, 0xd0, 0x74, 0xe5, 0x6a, 0xbd, 0x73, 0x4d, 0xa5, 0xf8, 0xdc, 0x68, + 0xd4, 0x58, 0x6f, 0xec, 0xc5, 0x1f, 0xaf, 0x14, 0x69, 0x14, 0x9e, 0x47, 0xd5, 0xd6, 0x62, 0x1a, 0xcc, 0xdb, 0x2e, + 0x24, 0xec, 0xe8, 0x0d, 0xa3, 0x18, 0xce, 0x6c, 0xec, 0x8d, 0xfd, 0x65, 0xd2, 0x75, 0x5a, 0x8b, 0x5b, 0x51, 0xc4, + 0xf7, 0x7a, 0x51, 0x80, 0x67, 0xaf, 0x9b, 0x44, 0x81, 0x3f, 0x16, 0x45, 0x9b, 0xce, 0x92, 0xd3, 0xd2, 0x7b, 0xc8, + 0xbf, 0xfa, 0x18, 0x74, 0xd9, 0x0b, 0x02, 0xc5, 0x6a, 0x27, 0x0a, 0xf3, 0x12, 0x34, 0x97, 0x53, 0xec, 0x84, 0xe6, + 0x05, 0x43, 0xd3, 0x3a, 0x07, 0x8b, 0xdb, 0x7c, 0xcf, 0x3b, 0x47, 0x8b, 0xdb, 0xec, 0xeb, 0x39, 0x1b, 0xfb, 0x9e, + 0xa2, 0x15, 0xbb, 0xc9, 0xb1, 0xc1, 0xa4, 0x4e, 0x5f, 0x6f, 0xd8, 0xa6, 0xe2, 0x58, 0x40, 0x62, 0xa3, 0x3d, 0x7f, + 0x0e, 0x72, 0x18, 0x2f, 0x4c, 0xb3, 0x6c, 0x70, 0x95, 0x65, 0xbd, 0x73, 0x5f, 0xbb, 0xfc, 0xab, 0x46, 0xb4, 0x90, + 0x4c, 0x50, 0x33, 0xfd, 0xca, 0x38, 0x63, 0xb2, 0xbb, 0x0c, 0x90, 0x31, 0x74, 0x95, 0x91, 0x2b, 0x13, 0xbd, 0xad, + 0x57, 0xa6, 0x49, 0xce, 0xab, 0x93, 0xf7, 0x4d, 0xb9, 0x0a, 0x52, 0x20, 0xa8, 0x70, 0xc6, 0xdc, 0x73, 0xc9, 0xf7, + 0x06, 0x98, 0x1e, 0xac, 0x4c, 0x51, 0x85, 0x5e, 0x6f, 0xe2, 0x3d, 0x2f, 0xee, 0xe7, 0x3d, 0xff, 0x96, 0xee, 0xc2, + 0x7b, 0x5e, 0x7c, 0x71, 0xde, 0xf3, 0x75, 0x3d, 0xaa, 0xd0, 0x45, 0xe4, 0xaa, 0xb9, 0xc1, 0x24, 0x90, 0xa6, 0x98, + 0xe2, 0xf5, 0xbf, 0x4e, 0x7f, 0x6d, 0x78, 0x17, 0xd1, 0x1b, 0x12, 0x05, 0xce, 0xa7, 0x82, 0x98, 0xf5, 0x6d, 0xe8, + 0xfe, 0x29, 0x96, 0x9f, 0x27, 0x13, 0xf7, 0x75, 0x24, 0x15, 0xe4, 0x4f, 0xdc, 0x97, 0xa4, 0x14, 0x5b, 0x99, 0xde, + 0xe4, 0xde, 0x3e, 0x90, 0x7d, 0x1a, 0x42, 0xb3, 0x92, 0x6b, 0xf7, 0x38, 0xf7, 0xb9, 0xeb, 0x95, 0x41, 0xd0, 0x72, + 0x27, 0x57, 0x11, 0x80, 0xab, 0x66, 0x19, 0x35, 0x65, 0x42, 0x06, 0xf0, 0xf2, 0xee, 0xfb, 0xb1, 0x76, 0x11, 0xe9, + 0x99, 0x9f, 0xbc, 0xad, 0x86, 0xbf, 0x12, 0x7a, 0x2e, 0x79, 0x38, 0x19, 0xf7, 0x9b, 0x93, 0xa2, 0xdc, 0xe2, 0x6b, + 0x6a, 0x7e, 0x5a, 0x1a, 0x69, 0x57, 0x6e, 0xd8, 0xa3, 0x98, 0xdf, 0x35, 0x62, 0xcc, 0xc3, 0xc4, 0xac, 0x39, 0x97, + 0xb7, 0xc6, 0x67, 0x88, 0x1a, 0x3a, 0xa6, 0xe6, 0xfe, 0x38, 0xcb, 0xf4, 0x9e, 0x98, 0x08, 0x89, 0xd0, 0xb2, 0xfb, + 0x98, 0xb8, 0xa4, 0x10, 0x02, 0x71, 0x89, 0x0f, 0x59, 0x33, 0x5f, 0x80, 0x7f, 0x00, 0xb7, 0x7d, 0xe6, 0x73, 0xa6, + 0x2a, 0x34, 0x7d, 0xe4, 0x37, 0x22, 0x0d, 0x08, 0x0c, 0xda, 0x65, 0x6f, 0xab, 0xd2, 0x82, 0xd4, 0x1d, 0x5b, 0x69, + 0x72, 0xd0, 0xc1, 0x01, 0x62, 0xfc, 0x0a, 0xb1, 0x10, 0xa1, 0x1d, 0x5e, 0x07, 0x1f, 0x32, 0x35, 0xe7, 0xfd, 0x70, + 0xfb, 0xf5, 0x4f, 0xf6, 0xa1, 0x41, 0xbf, 0xa2, 0x74, 0xbb, 0xc7, 0x2f, 0x13, 0x58, 0x89, 0x64, 0x65, 0x58, 0xc9, + 0x4a, 0x79, 0xb6, 0x16, 0xf1, 0xb1, 0x53, 0x6f, 0x61, 0x82, 0x96, 0x07, 0x71, 0x2f, 0xc7, 0x78, 0x52, 0x28, 0xee, + 0xde, 0x32, 0x01, 0xdc, 0x88, 0x72, 0x14, 0xc4, 0x3f, 0xbd, 0xd1, 0x32, 0x4e, 0xa2, 0xb8, 0xbb, 0x88, 0xfc, 0x30, + 0x65, 0x71, 0x46, 0x82, 0x15, 0x9c, 0x1f, 0x31, 0x3d, 0x57, 0xeb, 0x68, 0xe1, 0x8d, 0xfc, 0xf4, 0xae, 0x6b, 0x73, + 0x96, 0xc2, 0xee, 0x71, 0xee, 0xc0, 0x6e, 0xac, 0xdf, 0xe5, 0xb3, 0xf9, 0x1c, 0x19, 0xbf, 0xb8, 0xce, 0xce, 0xc8, + 0xdb, 0xbc, 0x27, 0xbd, 0xa5, 0x08, 0xe1, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x05, 0x2c, 0x0f, 0x4b, 0x6d, 0x8f, 0xd9, + 0xd4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0x75, 0xa8, 0x2b, 0x76, 0x73, 0x31, 0x70, 0x3c, 0xfa, 0x2e, 0x90, + 0x75, 0xbd, 0x49, 0xca, 0x62, 0x63, 0x97, 0x9a, 0x43, 0x36, 0x89, 0x62, 0x46, 0xd9, 0xe4, 0x9c, 0xce, 0xe2, 0x76, + 0xf7, 0xee, 0xb7, 0x0f, 0xbf, 0xb9, 0x9f, 0x30, 0x4a, 0x35, 0xd1, 0x99, 0x7e, 0x4f, 0x6f, 0x75, 0x7a, 0x06, 0xac, + 0x21, 0xcd, 0xfc, 0x88, 0xa4, 0x20, 0x10, 0x09, 0xac, 0x31, 0x69, 0xc7, 0x22, 0xe2, 0x34, 0x2f, 0x66, 0x81, 0x97, + 0xfa, 0x37, 0x82, 0x67, 0x6c, 0x1f, 0x2d, 0x6e, 0xc5, 0x1a, 0x23, 0xc1, 0x7b, 0xc0, 0x22, 0x55, 0x40, 0x11, 0x8b, + 0x54, 0x2d, 0xc6, 0x45, 0xea, 0xd5, 0x46, 0x23, 0xe2, 0x58, 0x57, 0x28, 0xfd, 0xe1, 0xe2, 0x56, 0x26, 0xd1, 0x45, + 0xb3, 0x9c, 0x52, 0x57, 0x13, 0x90, 0xcc, 0xfd, 0xf1, 0x38, 0x60, 0x59, 0x69, 0xa1, 0xcb, 0x6b, 0x29, 0x4d, 0x4e, + 0x3e, 0x0f, 0xde, 0x30, 0x89, 0x82, 0x65, 0xca, 0x9a, 0xa7, 0x4b, 0x48, 0x74, 0x8b, 0xc9, 0xc1, 0xdf, 0x65, 0x58, + 0x0f, 0x81, 0xdd, 0x86, 0x6d, 0x62, 0xf7, 0x20, 0xdf, 0xa0, 0xd9, 0x2e, 0x83, 0x0e, 0xaf, 0x72, 0xa0, 0x8d, 0x86, + 0x81, 0x18, 0x40, 0x96, 0x08, 0x7b, 0x2b, 0x96, 0xc3, 0xcb, 0xf2, 0x9c, 0x6b, 0x79, 0x51, 0x56, 0x1e, 0xcc, 0x6f, + 0x73, 0xc6, 0x5e, 0x34, 0x9f, 0xb1, 0x17, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x8f, 0x26, 0x0e, 0xfc, 0xd7, 0x2b, 0x06, + 0xd4, 0xb5, 0x95, 0xf6, 0xe2, 0x56, 0x71, 0x16, 0xb7, 0x8a, 0xd9, 0x5a, 0xdc, 0x2a, 0xd8, 0x35, 0xba, 0xb7, 0x18, + 0x56, 0x4b, 0x37, 0x6c, 0x05, 0x0a, 0xe1, 0x8f, 0x5d, 0x7a, 0xe5, 0x1c, 0xc0, 0x3b, 0x68, 0x75, 0x58, 0x7f, 0xd7, + 0xda, 0x7e, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0xa9, 0x37, 0x1c, 0x82, 0x28, 0x33, 0x1a, 0x2d, 0x93, 0x7f, + 0x72, 0xf8, 0xf9, 0x24, 0x6e, 0x45, 0x04, 0x95, 0x7e, 0x44, 0x53, 0x50, 0x14, 0xde, 0x30, 0xd1, 0xc3, 0x3a, 0x5f, + 0xa7, 0x2e, 0x25, 0x47, 0x6c, 0x59, 0x07, 0x0d, 0x9b, 0xbc, 0x79, 0xa2, 0x7f, 0xb3, 0x55, 0xda, 0x8c, 0x62, 0x3e, + 0x63, 0x5a, 0xb6, 0x4e, 0xc7, 0xc3, 0x67, 0x83, 0xaf, 0xa6, 0xdd, 0x69, 0x06, 0xf7, 0x52, 0x7c, 0xe9, 0x4a, 0x10, + 0x15, 0x4e, 0xb7, 0x78, 0x28, 0x8e, 0xed, 0xbd, 0x6e, 0xda, 0x23, 0xb5, 0x5e, 0xb7, 0x10, 0x84, 0xa2, 0xee, 0x8e, + 0x58, 0xfe, 0xd1, 0x8b, 0x03, 0xf8, 0x8f, 0xb8, 0xfa, 0xbf, 0xa5, 0x4d, 0x8c, 0xfa, 0xeb, 0xb4, 0xc4, 0xa8, 0x13, + 0xab, 0x84, 0x8c, 0xf8, 0xee, 0xf5, 0x27, 0x93, 0x87, 0x35, 0xd8, 0xb9, 0x36, 0x79, 0x86, 0x55, 0x6b, 0xbf, 0x8c, + 0xa2, 0x80, 0x79, 0x61, 0xbd, 0xba, 0x98, 0x1e, 0x72, 0xf3, 0x4f, 0x5d, 0x68, 0x24, 0xee, 0x11, 0xe4, 0x94, 0xa0, + 0x62, 0x1b, 0xba, 0x4a, 0x9c, 0x6f, 0xba, 0x4a, 0xbc, 0xbb, 0xff, 0x2a, 0xf1, 0xc7, 0x9d, 0xae, 0x12, 0xef, 0xbe, + 0xf8, 0x55, 0xe2, 0xbc, 0x7e, 0x95, 0x38, 0x8f, 0x84, 0x3b, 0xb0, 0xf1, 0x66, 0xc9, 0x7f, 0x7e, 0x20, 0x7b, 0xdf, + 0x77, 0x91, 0x7b, 0x68, 0x53, 0xc2, 0xc3, 0x8b, 0x5f, 0x7d, 0xb1, 0xc0, 0x8d, 0xf8, 0x0e, 0xbd, 0xe3, 0x8a, 0xab, + 0x05, 0xc7, 0xec, 0xf8, 0x1d, 0xa9, 0x38, 0x88, 0xc2, 0xe9, 0x4f, 0x60, 0xef, 0x0d, 0xe2, 0xc0, 0x58, 0x7a, 0xe1, + 0x27, 0x3f, 0x45, 0x8b, 0xe5, 0x02, 0x15, 0x55, 0x1f, 0xfc, 0xc4, 0x1f, 0x06, 0x2c, 0x8f, 0x30, 0x49, 0x5a, 0x57, + 0x2e, 0x5b, 0x07, 0xc5, 0xab, 0xf8, 0xe9, 0xdd, 0x8a, 0x9f, 0xe8, 0x62, 0xcb, 0x7f, 0x93, 0x9b, 0xa0, 0xda, 0x7c, + 0x11, 0x11, 0x16, 0x62, 0x12, 0xd0, 0x0f, 0xbf, 0x8c, 0x9c, 0x8b, 0x58, 0x5e, 0xa5, 0x51, 0x0a, 0xf7, 0x8d, 0x8d, + 0xfd, 0xb0, 0x6a, 0x3f, 0x6f, 0x96, 0xba, 0x91, 0x27, 0xe0, 0xa8, 0x8b, 0xf3, 0xe7, 0xd1, 0x32, 0x61, 0xe3, 0x68, + 0x15, 0xaa, 0x46, 0xc8, 0xf5, 0xaa, 0x11, 0xca, 0xd4, 0xf3, 0x36, 0x65, 0x85, 0xa3, 0x6a, 0x2d, 0x60, 0x0e, 0x4d, + 0xd2, 0x60, 0x9b, 0x38, 0x44, 0x55, 0x84, 0x6c, 0xea, 0xed, 0x69, 0x5a, 0xe4, 0x3e, 0xac, 0xa5, 0xf0, 0x3c, 0x89, + 0x2c, 0x2e, 0x15, 0x4e, 0xb4, 0x50, 0x08, 0x17, 0x45, 0x14, 0xec, 0x86, 0x85, 0xe3, 0x6f, 0x28, 0x42, 0x64, 0xf1, + 0x16, 0x74, 0x55, 0xd9, 0x92, 0xaf, 0x07, 0x8f, 0x09, 0x4d, 0x8f, 0xaf, 0xa4, 0x69, 0x7c, 0x7b, 0xc3, 0xe2, 0xc0, + 0xbb, 0xd3, 0xf4, 0x2c, 0x0a, 0x7f, 0x80, 0x09, 0x78, 0x1d, 0xad, 0x42, 0xb9, 0x02, 0xa6, 0x6a, 0x6f, 0xd8, 0x4b, + 0x8d, 0xd1, 0xcb, 0x21, 0x66, 0x87, 0x04, 0x81, 0x6f, 0x2d, 0xbc, 0x29, 0xfb, 0x8b, 0x41, 0xff, 0xfe, 0x55, 0xcf, + 0x8c, 0x77, 0x51, 0xfe, 0xa1, 0x9f, 0x17, 0x3b, 0x7c, 0xe6, 0xc9, 0x93, 0xbd, 0xcd, 0xc3, 0xd6, 0x46, 0x01, 0xf3, + 0x62, 0x01, 0x45, 0x43, 0x6b, 0x7d, 0xe3, 0x29, 0x00, 0x28, 0x2e, 0xa2, 0xe5, 0x68, 0x86, 0x7e, 0xbb, 0x5f, 0x6e, + 0xbc, 0x29, 0xf4, 0xc9, 0x92, 0x4b, 0xfb, 0x2a, 0x1f, 0x7a, 0xa5, 0xa8, 0x98, 0x05, 0xfc, 0xfe, 0x19, 0xa4, 0xdf, + 0xfa, 0x0f, 0x4e, 0x43, 0x7d, 0xd7, 0xe4, 0x21, 0xbf, 0x1e, 0xb4, 0x79, 0x7b, 0x3e, 0x44, 0xe5, 0xa1, 0xc0, 0xd6, + 0x42, 0x49, 0xd7, 0x8c, 0x64, 0xb2, 0xea, 0xa4, 0xc9, 0x49, 0x64, 0x36, 0xe5, 0xc7, 0x11, 0x5f, 0x61, 0x56, 0xc9, + 0x6a, 0xc4, 0x60, 0x1c, 0x5b, 0x55, 0x90, 0x0c, 0xf7, 0xa6, 0x60, 0x88, 0xbe, 0xaa, 0xef, 0xe6, 0x7e, 0x68, 0x60, + 0x0e, 0xd8, 0xfa, 0x1b, 0xef, 0x16, 0xb2, 0x20, 0x02, 0x72, 0xab, 0xbe, 0x82, 0x42, 0x43, 0x8e, 0x16, 0xe4, 0x8d, + 0xc7, 0x9a, 0xda, 0x38, 0x13, 0x42, 0x1b, 0x38, 0xf8, 0x4a, 0x51, 0x14, 0x25, 0xbf, 0x46, 0x28, 0xf9, 0x3d, 0x02, + 0xcb, 0xf1, 0x3a, 0x00, 0xda, 0x92, 0x6c, 0x71, 0x4b, 0x25, 0x70, 0x33, 0x40, 0xfb, 0x69, 0x51, 0xc0, 0x13, 0xfd, + 0x80, 0x71, 0x0b, 0x15, 0x88, 0x0b, 0x3d, 0xa8, 0xbe, 0xbd, 0x18, 0xf2, 0x01, 0x76, 0x15, 0xbc, 0xb0, 0xe3, 0x5b, + 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, 0xf4, 0x58, 0x73, 0x46, 0x98, 0x50, 0xc2, 0x82, 0xa0, 0x75, 0xa8, 0x24, 0x78, + 0x34, 0x58, 0x03, 0x6e, 0xc4, 0x7b, 0xd1, 0x6d, 0x3a, 0x67, 0xe1, 0x52, 0x35, 0xc0, 0xea, 0x04, 0x33, 0xf4, 0x40, + 0x9d, 0xd7, 0xc4, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0x39, 0x23, 0x5a, 0x28, 0x4c, 0x55, 0x3c, 0x63, 0xc4, 0x03, 0xe0, + 0x24, 0x1c, 0xb7, 0x55, 0x29, 0x04, 0x5f, 0xd2, 0xa8, 0x8c, 0xcd, 0x79, 0xc8, 0x2b, 0xe4, 0x14, 0xc8, 0x46, 0x8c, + 0x8b, 0x8b, 0xc4, 0xb4, 0x6b, 0x5e, 0x75, 0xd1, 0x72, 0x8d, 0x8c, 0x57, 0x11, 0x14, 0xc5, 0x7a, 0xbd, 0x1b, 0x0e, + 0x27, 0xa4, 0x25, 0xd8, 0xd8, 0xcf, 0xa8, 0xd6, 0xcf, 0x86, 0x41, 0x7f, 0x64, 0x77, 0x44, 0x48, 0x68, 0xaa, 0x3e, + 0xb2, 0x3b, 0x30, 0x0e, 0x3f, 0x03, 0x69, 0x8a, 0xba, 0x05, 0x5d, 0x1b, 0x90, 0xe8, 0x77, 0x04, 0xa9, 0x2a, 0xb6, + 0x1c, 0x20, 0x3b, 0xdb, 0x82, 0xc5, 0x29, 0x1c, 0xa9, 0x91, 0xf4, 0xc4, 0x21, 0xe6, 0x11, 0x0b, 0xb4, 0xc6, 0x39, + 0x36, 0x1b, 0x8e, 0x86, 0xfe, 0xcc, 0xb1, 0xed, 0xfd, 0x5a, 0x7d, 0x10, 0x64, 0x37, 0xd5, 0xd6, 0x8d, 0xd4, 0x75, + 0x6c, 0xd3, 0x7f, 0x66, 0xb5, 0x7a, 0x35, 0x1a, 0x2d, 0x65, 0x92, 0x1a, 0xa0, 0xf8, 0xab, 0xff, 0x78, 0xad, 0xd5, + 0x0e, 0xa4, 0x5e, 0x8d, 0x00, 0x80, 0xb0, 0x65, 0x5c, 0xfe, 0x35, 0xa8, 0x93, 0x7e, 0xca, 0x63, 0x45, 0x59, 0xcd, + 0x07, 0x90, 0x0b, 0x51, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x41, 0x4f, 0x60, 0x14, + 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0xd6, 0x35, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, + 0xd8, 0xff, 0x06, 0xf2, 0x69, 0x0d, 0x21, 0xc6, 0x23, 0xd4, 0x80, 0xcc, 0xa9, 0xf7, 0x76, 0x08, 0xe1, 0x79, 0xe5, + 0xee, 0xca, 0x44, 0x72, 0xf7, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x99, 0xdc, 0x3d, 0xb0, 0x4b, 0x16, + 0x8e, 0xcb, 0x1d, 0x56, 0xe8, 0xd7, 0xee, 0xdd, 0x95, 0x30, 0x0a, 0xa4, 0x14, 0x8e, 0x1a, 0x30, 0x4a, 0x16, 0x85, + 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x3b, 0x71, 0x31, 0xd8, 0x80, 0xf2, 0x81, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0xe4, 0xad, + 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0x37, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x89, 0x6a, 0x57, + 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, 0x98, + 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x1a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, 0xb7, + 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x5e, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, 0xbf, + 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, 0x24, + 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, 0x6f, + 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, 0xe7, + 0x36, 0x10, 0x08, 0x64, 0x43, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x2d, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, 0x49, + 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x24, 0x09, 0x42, 0xd7, 0x56, 0xec, 0x5e, 0x03, 0x03, 0x80, 0xf4, 0xbf, + 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xad, 0x7f, + 0x93, 0xe4, 0x3d, 0x6b, 0x1e, 0x13, 0xa4, 0x2c, 0xce, 0xe7, 0x35, 0xba, 0x02, 0x0e, 0xbe, 0xcb, 0xe2, 0x65, 0x88, + 0x49, 0x70, 0xcd, 0x34, 0xf6, 0x46, 0x1f, 0xd7, 0xd2, 0xf7, 0xb8, 0x48, 0x14, 0xc4, 0xc5, 0x65, 0xa5, 0x42, 0xcf, + 0xc3, 0x9c, 0x51, 0xac, 0x6b, 0xb5, 0x12, 0x49, 0x50, 0xd3, 0x7d, 0x64, 0xb7, 0xbd, 0x17, 0x93, 0x83, 0x8a, 0xfc, + 0xb4, 0x75, 0x58, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa3, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, 0x66, + 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x5a, 0xc9, 0x26, 0xb0, 0x26, 0x7e, 0x10, + 0x98, 0x01, 0xb8, 0x31, 0xac, 0x3f, 0x6b, 0x78, 0xd8, 0xcf, 0x12, 0xb2, 0x15, 0x7e, 0x46, 0x3f, 0xe5, 0x9d, 0x92, + 0xce, 0x96, 0xf3, 0xe1, 0x5a, 0x16, 0x94, 0x4b, 0xf2, 0xf3, 0xba, 0xcc, 0x5c, 0xfe, 0xec, 0x64, 0x32, 0x29, 0x4b, + 0x8d, 0x6d, 0xe5, 0x00, 0x25, 0xbf, 0x8f, 0x6c, 0xdb, 0xae, 0xce, 0xef, 0xa6, 0x83, 0x42, 0x07, 0xc3, 0x44, 0x21, + 0x7c, 0xe7, 0xfe, 0x3d, 0xf5, 0x3b, 0x41, 0x4b, 0x5d, 0x6d, 0x3a, 0x8f, 0xb4, 0xd5, 0xfe, 0x2b, 0x40, 0x41, 0xd4, + 0x70, 0xdf, 0xf1, 0xaf, 0xef, 0x95, 0x2d, 0x3d, 0x55, 0x0f, 0xf0, 0xc3, 0x1a, 0xdf, 0xb3, 0xd7, 0x77, 0x68, 0xba, + 0x69, 0x7b, 0x67, 0x56, 0x41, 0x76, 0x4b, 0x36, 0x4b, 0x3d, 0xb2, 0x54, 0xf2, 0x53, 0x36, 0x4f, 0xba, 0x23, 0x86, + 0x0a, 0x52, 0x4b, 0xa2, 0xb6, 0x68, 0xd5, 0x63, 0x4e, 0xc1, 0x8e, 0xcb, 0x11, 0x78, 0xd8, 0x56, 0x50, 0x59, 0x55, + 0xd3, 0xac, 0x89, 0x8f, 0x20, 0x15, 0x5b, 0xd7, 0x15, 0x4e, 0xb8, 0x4d, 0x0f, 0xed, 0x3f, 0x94, 0xea, 0x29, 0xc0, + 0x9d, 0xae, 0x85, 0xb5, 0x09, 0x29, 0x4f, 0xf0, 0xef, 0x5c, 0x39, 0xf7, 0x62, 0x71, 0x5b, 0x36, 0xee, 0xea, 0x80, + 0xba, 0xa9, 0x20, 0x65, 0x04, 0x75, 0x13, 0xea, 0xcb, 0x4d, 0x80, 0x26, 0xb2, 0x75, 0x0b, 0x58, 0xd0, 0x88, 0x29, + 0xa8, 0xe8, 0x08, 0x73, 0x50, 0xf1, 0x3a, 0x0b, 0x3b, 0xaf, 0x90, 0xef, 0xe3, 0x2f, 0xc8, 0x52, 0x0e, 0xe9, 0x4e, + 0xfe, 0x60, 0x3c, 0xef, 0xa0, 0x72, 0xaf, 0xb4, 0x55, 0xd1, 0x54, 0x06, 0xf7, 0x80, 0xb8, 0x91, 0x2a, 0xcb, 0x38, + 0x30, 0x29, 0x71, 0xbd, 0xa6, 0xaf, 0xeb, 0xe3, 0xde, 0xdc, 0xbd, 0x73, 0x08, 0x7a, 0x8d, 0xfa, 0x54, 0xed, 0xa4, + 0xda, 0xab, 0xea, 0xb0, 0x05, 0x9c, 0xb0, 0x02, 0xe0, 0x33, 0xab, 0xa0, 0xd1, 0x90, 0x52, 0xc1, 0x7d, 0x34, 0xe8, + 0xfc, 0xad, 0x8c, 0xac, 0xc5, 0x38, 0xb1, 0xbb, 0xe6, 0x2a, 0xd4, 0xb7, 0xd0, 0x0c, 0xc2, 0xdc, 0x71, 0xec, 0x84, + 0xcf, 0x26, 0xec, 0x18, 0x19, 0x5d, 0x39, 0xb8, 0x83, 0xf0, 0x94, 0x9a, 0x94, 0xfc, 0x84, 0x4e, 0x29, 0xea, 0x12, + 0xfe, 0xd8, 0x28, 0xbc, 0xbf, 0x28, 0x49, 0xe3, 0x79, 0xd0, 0x89, 0x96, 0xbe, 0x53, 0xed, 0xb9, 0x1f, 0xee, 0x5e, + 0xd7, 0xbb, 0xdd, 0xb9, 0x2e, 0x30, 0x87, 0x3b, 0x57, 0x06, 0xee, 0x12, 0x2b, 0x5f, 0xa4, 0xee, 0x1f, 0x25, 0xe5, + 0x81, 0x1c, 0x30, 0x51, 0xc5, 0x56, 0x74, 0xa3, 0xff, 0x71, 0xe9, 0x0e, 0x4e, 0x4e, 0x6f, 0xe7, 0x81, 0x72, 0xc3, + 0xe2, 0x04, 0x12, 0x4a, 0xa8, 0x8e, 0x65, 0xab, 0x0a, 0x1a, 0xf4, 0xfb, 0xe1, 0xd4, 0x55, 0x7f, 0xbe, 0x78, 0x63, + 0x76, 0xd4, 0x53, 0x30, 0xc7, 0xb8, 0x99, 0x22, 0x8b, 0x7b, 0xee, 0xdd, 0xb1, 0xf8, 0xba, 0xc5, 0x3d, 0x7e, 0x88, + 0xb9, 0xc5, 0x32, 0xa5, 0xa5, 0xee, 0x90, 0x12, 0x5e, 0xb9, 0xf1, 0xd9, 0xea, 0x65, 0x74, 0xeb, 0xaa, 0x80, 0x58, + 0x9d, 0x56, 0x47, 0x71, 0x5a, 0x07, 0xd6, 0x51, 0x47, 0xed, 0x7f, 0xa5, 0x28, 0x27, 0x63, 0x36, 0x49, 0xfa, 0x28, + 0x8e, 0x39, 0x41, 0x7e, 0x90, 0x7e, 0x2b, 0x8a, 0x35, 0x0a, 0x12, 0xd3, 0x51, 0xd6, 0xfc, 0x51, 0x51, 0x00, 0x19, + 0x75, 0x95, 0x47, 0x93, 0xd6, 0xe4, 0x60, 0xf2, 0xa2, 0xc7, 0x8b, 0xb3, 0xaf, 0x4a, 0xd5, 0x0d, 0xfa, 0xb7, 0x25, + 0x35, 0x4b, 0xd2, 0x38, 0xfa, 0xc8, 0x38, 0x2f, 0xa9, 0xe4, 0x82, 0xa2, 0x6a, 0xd3, 0x56, 0xfd, 0x4b, 0x4e, 0x67, + 0x38, 0x9a, 0xb4, 0x8a, 0xea, 0x08, 0xe3, 0x7e, 0x0e, 0xe4, 0xc9, 0xbe, 0x00, 0xfd, 0x44, 0x9e, 0x26, 0xc7, 0x6c, + 0x9a, 0x28, 0x47, 0xe5, 0x63, 0x9c, 0x8a, 0xf1, 0x9d, 0x40, 0xc6, 0xb5, 0xc2, 0x7b, 0x31, 0xc1, 0x66, 0xae, 0xfa, + 0x83, 0xd3, 0xea, 0x18, 0x8e, 0x73, 0x64, 0x1d, 0x75, 0x46, 0xb6, 0x71, 0x60, 0x1d, 0x98, 0x6d, 0xeb, 0xc8, 0xe8, + 0x98, 0x1d, 0xa3, 0xf3, 0x5d, 0x67, 0x64, 0x1e, 0x58, 0x07, 0x86, 0x6d, 0x76, 0xa0, 0xd0, 0xec, 0x98, 0x9d, 0x1b, + 0xf3, 0xa0, 0x33, 0xb2, 0xb1, 0xb4, 0x65, 0x1d, 0x1e, 0x9a, 0x8e, 0x6d, 0x1d, 0x1e, 0x1a, 0x87, 0xd6, 0xd1, 0x91, + 0xe9, 0xb4, 0xad, 0xa3, 0xa3, 0xf3, 0xc3, 0x8e, 0xd5, 0x86, 0x77, 0xed, 0xf6, 0xa8, 0x6d, 0x39, 0x8e, 0x09, 0x7f, + 0x19, 0x1d, 0xab, 0x45, 0x3f, 0x1c, 0xc7, 0x6a, 0x3b, 0x86, 0x1d, 0x1c, 0xb6, 0xac, 0xa3, 0x17, 0x06, 0xfe, 0x8d, + 0xd5, 0x0c, 0xfc, 0x0b, 0xba, 0x31, 0x5e, 0x58, 0xad, 0x23, 0xfa, 0x85, 0x1d, 0xde, 0x1c, 0x74, 0xfe, 0xa6, 0xee, + 0x6f, 0x1c, 0x83, 0x43, 0x63, 0xe8, 0x1c, 0x5a, 0xed, 0xb6, 0x71, 0xe0, 0x58, 0x9d, 0xf6, 0xcc, 0x3c, 0x68, 0x59, + 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, 0x6c, 0x5b, 0x2d, 0xc3, 0xb1, 0x0e, 0xda, 0xf8, 0xa3, 0x6d, + 0xb5, 0x6e, 0x8e, 0x5f, 0x58, 0x47, 0x87, 0xb3, 0x23, 0xeb, 0xe0, 0xc3, 0x41, 0xc7, 0x6a, 0xb5, 0x67, 0xed, 0x23, + 0xab, 0x75, 0x7c, 0x73, 0x64, 0x1d, 0xcc, 0xcc, 0xd6, 0xd1, 0xd6, 0x96, 0x4e, 0xcb, 0x82, 0x39, 0xc2, 0xd7, 0xf0, + 0xc2, 0xe0, 0x2f, 0xe0, 0xcf, 0x0c, 0xdb, 0xfe, 0x8e, 0xdd, 0x24, 0xf5, 0xa6, 0x2f, 0xac, 0xce, 0xf1, 0x88, 0xaa, + 0x43, 0x81, 0x29, 0x6a, 0x40, 0x93, 0x1b, 0x93, 0x3e, 0x8b, 0xdd, 0x99, 0xa2, 0x23, 0xf1, 0x87, 0x7f, 0xec, 0xc6, + 0x84, 0x0f, 0xd3, 0x77, 0xff, 0xa3, 0xfd, 0xe4, 0x4b, 0x7e, 0xb2, 0x3f, 0xa5, 0xad, 0x3f, 0xed, 0x7f, 0x75, 0x02, + 0x87, 0xbb, 0x3f, 0x30, 0x7e, 0xd9, 0xa4, 0x94, 0xfc, 0xc7, 0xfd, 0x4a, 0xc9, 0x97, 0xcb, 0x5d, 0x94, 0x92, 0xff, + 0xf8, 0xe2, 0x4a, 0xc9, 0x5f, 0xaa, 0xbe, 0x35, 0x6f, 0xaa, 0x59, 0xa8, 0xff, 0xb8, 0xae, 0x8a, 0x1c, 0x12, 0x4f, + 0xbb, 0xfc, 0x71, 0x79, 0x05, 0xf1, 0xe3, 0xdf, 0x44, 0xee, 0xcb, 0x65, 0xc9, 0xe0, 0x33, 0x02, 0x1c, 0xfb, 0x26, + 0x22, 0x1c, 0xfb, 0x61, 0xe9, 0x82, 0x95, 0x19, 0x67, 0x73, 0xfc, 0xb1, 0x39, 0xf3, 0x82, 0x49, 0xce, 0x22, 0x41, + 0x49, 0x0f, 0x8b, 0xc1, 0x6f, 0x1e, 0xc8, 0x33, 0xdc, 0x64, 0x96, 0xf3, 0x30, 0x01, 0x8b, 0x60, 0xb0, 0xe4, 0x98, + 0xc4, 0x59, 0xa5, 0xb1, 0x25, 0x22, 0xee, 0x5f, 0x73, 0x8f, 0xe2, 0x8d, 0xef, 0xd1, 0x00, 0xb8, 0xb9, 0x77, 0xa7, + 0xde, 0xaf, 0x02, 0x96, 0x75, 0xc2, 0x40, 0x1a, 0xb8, 0xfd, 0xa6, 0xf7, 0x65, 0x33, 0xdc, 0x8a, 0xe1, 0xf5, 0x66, + 0x48, 0x01, 0x92, 0x6a, 0x7b, 0xa7, 0x6c, 0xc6, 0x7b, 0xdf, 0x30, 0x1b, 0x3e, 0x5f, 0x6a, 0xbe, 0xc5, 0x86, 0x38, + 0xef, 0xb8, 0x3a, 0x55, 0xeb, 0x12, 0x9f, 0xd6, 0x3c, 0x21, 0xc5, 0x05, 0xb5, 0x30, 0x34, 0x2e, 0x38, 0x55, 0x5b, + 0x41, 0x7e, 0xc7, 0x96, 0xde, 0x95, 0xfa, 0x94, 0x8d, 0x93, 0x9f, 0xad, 0xf1, 0x5e, 0xe1, 0xff, 0x02, 0x9c, 0x28, + 0xe7, 0x78, 0x86, 0x91, 0x3c, 0xcf, 0x6b, 0xa9, 0x5f, 0x92, 0x46, 0x64, 0x33, 0x67, 0x5d, 0xe7, 0x45, 0x37, 0xba, + 0x25, 0x38, 0x6c, 0x2e, 0xb8, 0x20, 0xfc, 0x3c, 0x39, 0x01, 0x64, 0xe4, 0xa8, 0x81, 0x7e, 0x0e, 0xdb, 0x3a, 0x13, + 0xf5, 0x1e, 0xc1, 0x26, 0xe6, 0x9e, 0x80, 0x8a, 0x1c, 0xd2, 0x74, 0x3d, 0x09, 0x22, 0x2f, 0xed, 0x22, 0x9b, 0x26, + 0xb1, 0xbc, 0x2d, 0xf4, 0x58, 0xe8, 0x6d, 0x31, 0xa6, 0x93, 0x3b, 0xe6, 0x9d, 0xa0, 0xe7, 0xc3, 0x36, 0xfb, 0xbb, + 0xdc, 0xe1, 0x6c, 0x5d, 0x32, 0x47, 0x71, 0x0e, 0x8f, 0x0d, 0xe7, 0xc8, 0xb0, 0x8e, 0x0f, 0xf5, 0x4c, 0x1c, 0x38, + 0xb9, 0xcb, 0xd2, 0x84, 0x80, 0x03, 0x44, 0x0e, 0xa6, 0x1f, 0xfa, 0xa9, 0xef, 0x05, 0x19, 0xf0, 0xc3, 0xe5, 0x4b, + 0xca, 0x3f, 0x96, 0x49, 0x0a, 0x63, 0x14, 0x4c, 0x2f, 0x3a, 0x7f, 0x98, 0x43, 0x96, 0xae, 0x18, 0x0b, 0x37, 0x18, + 0xc6, 0x54, 0x7d, 0x49, 0x7e, 0x3b, 0xcb, 0xfa, 0x8c, 0xac, 0xd6, 0x86, 0x69, 0xc8, 0xf7, 0x87, 0x70, 0x7c, 0xc8, + 0x06, 0xc6, 0x77, 0x9b, 0x10, 0xee, 0xcf, 0xf7, 0x23, 0xdc, 0x94, 0xed, 0x82, 0x70, 0x7f, 0xfe, 0xe2, 0x08, 0xf7, + 0x3b, 0x19, 0xe1, 0x96, 0xfc, 0x07, 0x0b, 0x0d, 0xd3, 0x7b, 0x7c, 0xd6, 0xc0, 0x45, 0xf6, 0xb9, 0xba, 0x4f, 0x0c, + 0xbc, 0xaa, 0x17, 0xd9, 0x6b, 0xff, 0xbc, 0x94, 0x2d, 0xa8, 0x51, 0x00, 0x8a, 0x79, 0x1d, 0x7d, 0x74, 0x5d, 0xf6, + 0xc1, 0xd5, 0x4d, 0x84, 0x61, 0x80, 0x3e, 0xbf, 0x0f, 0xd3, 0xc0, 0x7a, 0xc7, 0xef, 0x91, 0xa0, 0xd0, 0x7d, 0x13, + 0xc5, 0x73, 0x0f, 0x53, 0x8c, 0xa8, 0x3a, 0xb8, 0xd3, 0xc1, 0x83, 0x0d, 0x81, 0x40, 0x46, 0x51, 0x38, 0xce, 0xb5, + 0x92, 0xcc, 0xbd, 0x24, 0x8e, 0x5b, 0xbd, 0x63, 0x5e, 0xac, 0x1a, 0xf4, 0x1a, 0x16, 0xf7, 0x59, 0xdb, 0x7e, 0xd6, + 0x3a, 0x78, 0x76, 0x64, 0xc3, 0xff, 0x0e, 0x6b, 0x67, 0x06, 0xaf, 0x38, 0x8f, 0xc2, 0x74, 0x56, 0xd4, 0xdc, 0x54, + 0x6d, 0xc5, 0xd8, 0xc7, 0xa2, 0xd6, 0x71, 0x73, 0xa5, 0xb1, 0x77, 0x57, 0xd4, 0x69, 0xac, 0x31, 0x8b, 0x96, 0x12, + 0x58, 0x0d, 0xd0, 0xf8, 0xe1, 0x12, 0xe4, 0xec, 0x52, 0x0d, 0xf9, 0x35, 0x1f, 0x6e, 0x31, 0x2e, 0xd6, 0xce, 0xae, + 0x44, 0x0e, 0x05, 0xb5, 0x27, 0xd2, 0xea, 0xdd, 0x3b, 0x83, 0x5c, 0x45, 0x69, 0x63, 0xce, 0x29, 0xcc, 0x6c, 0x08, + 0x19, 0xa7, 0x98, 0x58, 0x20, 0x8f, 0x16, 0x28, 0x8d, 0x97, 0xe1, 0x48, 0xc3, 0x9f, 0xde, 0x30, 0xd1, 0xfc, 0xfd, + 0xd8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xbc, 0xbe, 0x5d, 0x24, 0x9d, 0x4f, 0xc4, 0xaa, 0x78, 0xcf, 0x52, 0x23, 0x46, + 0x3d, 0x36, 0x2d, 0xad, 0xe9, 0x7a, 0xcf, 0xf2, 0x86, 0xcf, 0x52, 0x23, 0x7c, 0x0e, 0xba, 0x4f, 0xd7, 0x7e, 0xf2, + 0x84, 0x6a, 0xed, 0xb9, 0x62, 0x58, 0xa7, 0xa3, 0x22, 0x33, 0x85, 0xe2, 0x4d, 0x23, 0x4a, 0x4e, 0xd1, 0x1d, 0x19, + 0xd1, 0xf3, 0xe7, 0x7d, 0xd7, 0xd1, 0x87, 0x31, 0xf3, 0x3e, 0x66, 0x22, 0xdc, 0x77, 0x88, 0xf9, 0x69, 0xcf, 0x77, + 0x33, 0x34, 0xd2, 0x1b, 0x5d, 0x69, 0x17, 0x70, 0x67, 0xb2, 0x85, 0x3b, 0x02, 0xc7, 0x5e, 0x90, 0xbb, 0x9e, 0x0c, + 0x0a, 0x3c, 0x61, 0xf0, 0x23, 0xea, 0xe4, 0xb7, 0xae, 0xb6, 0x65, 0x5b, 0xb6, 0x9a, 0x37, 0x9c, 0xf8, 0x53, 0x77, + 0x1d, 0xa5, 0x5e, 0x77, 0xcf, 0x31, 0x82, 0x68, 0x0a, 0x7e, 0x74, 0xa9, 0x9f, 0x06, 0xac, 0xab, 0xaa, 0xe0, 0x50, + 0x37, 0xa7, 0x7b, 0x79, 0xc6, 0xbd, 0x1b, 0xbc, 0x18, 0xd2, 0x96, 0xc7, 0x77, 0xc2, 0x15, 0x17, 0x83, 0xa5, 0xff, + 0x00, 0xc4, 0x50, 0x53, 0x35, 0x90, 0x0d, 0xb0, 0x38, 0x31, 0x65, 0x6f, 0xa1, 0xae, 0x02, 0x6d, 0x74, 0x95, 0x0f, + 0x62, 0x12, 0x7b, 0x73, 0xc8, 0xab, 0xbb, 0xce, 0x0c, 0x8e, 0x69, 0x55, 0x8e, 0x6a, 0x15, 0xe7, 0xc5, 0x91, 0xa1, + 0xb4, 0x1c, 0x43, 0xb1, 0x01, 0xdd, 0xaa, 0x99, 0xb1, 0xce, 0xae, 0x7a, 0xf7, 0x19, 0x3c, 0x10, 0x7e, 0x79, 0x44, + 0xe3, 0x20, 0x53, 0x07, 0xae, 0x4a, 0x4a, 0x29, 0x49, 0x8e, 0x26, 0x65, 0xd0, 0xf4, 0x49, 0xe9, 0x79, 0xc1, 0x6e, + 0x53, 0x1d, 0x34, 0x47, 0xa2, 0x8a, 0xaf, 0xaf, 0xd1, 0x61, 0xd8, 0x0f, 0x15, 0xff, 0xd3, 0x27, 0xcd, 0x07, 0x67, + 0x26, 0x57, 0x9a, 0x1f, 0x78, 0xd6, 0x4b, 0x13, 0xe6, 0x17, 0x6a, 0x7a, 0x9c, 0x2c, 0xf0, 0x34, 0x84, 0x7f, 0x8b, + 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0x81, 0x17, 0x4e, 0x01, 0xa5, 0x79, 0xe1, 0xb4, 0x66, 0x8e, 0x45, 0x3e, 0xcf, + 0x95, 0xd2, 0xa2, 0xab, 0xc2, 0x54, 0x2a, 0x79, 0x79, 0x77, 0xe1, 0x4d, 0x7f, 0xf4, 0xe6, 0x4c, 0x53, 0x81, 0xca, + 0xa1, 0x8b, 0x6e, 0xa1, 0xc9, 0x7d, 0xee, 0x3e, 0x3d, 0x99, 0xb3, 0xd4, 0x23, 0x35, 0x10, 0x5c, 0x7e, 0x81, 0x1d, + 0x50, 0x38, 0xa1, 0xe1, 0x01, 0x2f, 0x5c, 0xca, 0xa5, 0x45, 0x74, 0xc2, 0x50, 0x38, 0x9d, 0x32, 0xd1, 0xe2, 0xd3, + 0x75, 0x0c, 0x72, 0x38, 0x18, 0x79, 0x98, 0x4f, 0xc7, 0x0d, 0x23, 0xb5, 0xff, 0x34, 0xf7, 0xcd, 0xdc, 0xb4, 0x08, + 0x81, 0x1f, 0x7e, 0xbc, 0x8c, 0x59, 0xf0, 0x4f, 0xf7, 0x29, 0x10, 0xee, 0xa7, 0x57, 0xaa, 0xde, 0x4b, 0xad, 0x59, + 0xcc, 0x26, 0xee, 0x53, 0xb8, 0x90, 0x76, 0xd1, 0x3c, 0x16, 0xb8, 0xf6, 0xe7, 0xb7, 0xf3, 0xc0, 0xc0, 0xeb, 0x3d, + 0xc1, 0xa2, 0xb6, 0x5b, 0x45, 0x5c, 0xf3, 0xf6, 0x4e, 0x97, 0xfa, 0x3e, 0xbf, 0xad, 0xc3, 0x0d, 0x70, 0x5d, 0xba, + 0x63, 0x3b, 0x3d, 0xbc, 0x3f, 0x0f, 0x03, 0x6f, 0xf4, 0xb1, 0x47, 0x6f, 0x4a, 0x0f, 0x26, 0x50, 0xeb, 0x91, 0xb7, + 0xe8, 0x22, 0x79, 0x95, 0x0b, 0xc1, 0x7b, 0x9a, 0x4a, 0x73, 0xce, 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, + 0xf1, 0x53, 0xab, 0x99, 0x9f, 0x32, 0xf1, 0x29, 0x7c, 0xc8, 0x32, 0x71, 0x51, 0xa7, 0x2b, 0x2a, 0x5e, 0xac, 0xad, + 0xb6, 0xe2, 0x74, 0xbe, 0x3b, 0xbc, 0x71, 0xec, 0x59, 0xcb, 0xb1, 0x3a, 0x1f, 0x9c, 0xce, 0xac, 0x6d, 0x1d, 0x07, + 0x66, 0xdb, 0x3a, 0x86, 0x3f, 0x1f, 0x8e, 0xad, 0xce, 0xcc, 0x6c, 0x59, 0x07, 0x1f, 0x9c, 0x56, 0x60, 0x76, 0xac, + 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, + 0x89, 0xbc, 0x35, 0xe8, 0x75, 0x17, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0x7b, 0x5a, 0xe8, 0x32, 0x4a, 0x2a, 0x2b, + 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0xd9, 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x0c, 0x96, 0xba, 0xc8, 0x08, 0x8c, + 0xcf, 0x3f, 0x2f, 0x30, 0xfe, 0xba, 0x48, 0xc3, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x85, 0xb6, 0x15, + 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xcc, 0xd7, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, + 0x21, 0x67, 0x9f, 0x1c, 0xfb, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xe6, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, + 0x7c, 0xe3, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0x72, 0x2f, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, + 0x9c, 0x43, 0x20, 0xbb, 0x87, 0xac, 0xbd, 0xd5, 0xa6, 0x92, 0x6e, 0x3a, 0xdb, 0x7c, 0xab, 0x8b, 0x4c, 0x47, 0xc2, + 0x6e, 0x4a, 0x58, 0x6c, 0x6c, 0x34, 0xec, 0xac, 0xd9, 0x6b, 0x40, 0xaa, 0xb8, 0xca, 0x55, 0x47, 0xd5, 0x7b, 0xa1, + 0x30, 0x3f, 0x08, 0xb7, 0x24, 0x79, 0xe3, 0x77, 0x31, 0x15, 0xa6, 0x66, 0xcb, 0x38, 0xee, 0x71, 0x10, 0xff, 0x4f, + 0x0f, 0x02, 0x9d, 0x35, 0xc1, 0x5e, 0xa2, 0x72, 0x5a, 0x4b, 0xce, 0x7b, 0x39, 0x5d, 0x25, 0x82, 0xca, 0x92, 0x53, + 0x15, 0x8a, 0xd4, 0xae, 0x8a, 0x8e, 0x61, 0x6a, 0x6e, 0x2c, 0x9a, 0x53, 0x8b, 0xa2, 0xc0, 0xf0, 0x31, 0xa1, 0xa6, + 0x70, 0x1c, 0xd5, 0x9f, 0x3c, 0xd9, 0x48, 0x84, 0xc8, 0x38, 0x27, 0x61, 0xa9, 0x60, 0xd0, 0x35, 0x55, 0xc6, 0x6f, + 0xaa, 0x8c, 0x62, 0xf2, 0x7e, 0x11, 0x6b, 0x08, 0x1b, 0x57, 0xda, 0x7b, 0xf8, 0x73, 0xc8, 0xbc, 0xd4, 0xe2, 0xca, + 0x52, 0x4d, 0x22, 0xee, 0x86, 0xc3, 0xda, 0x60, 0xdd, 0xca, 0xd3, 0x34, 0xf0, 0x34, 0x28, 0x8f, 0xd7, 0x7f, 0x5e, + 0xf2, 0xa8, 0x0e, 0xd0, 0xc7, 0x27, 0xbb, 0x88, 0xc3, 0xf9, 0x36, 0xf5, 0x28, 0x0e, 0x9a, 0x4c, 0x72, 0xa3, 0xd4, + 0x23, 0x7b, 0x0e, 0x1f, 0x43, 0xd7, 0x34, 0x47, 0xe4, 0x92, 0x22, 0x3f, 0xf4, 0xdf, 0x5e, 0x7c, 0xa3, 0xf0, 0xfd, + 0x4f, 0xd6, 0x02, 0x78, 0x91, 0xa1, 0x78, 0x33, 0x2e, 0xc5, 0x9b, 0x51, 0x78, 0x26, 0x63, 0xc8, 0xb9, 0x9a, 0xed, + 0xd3, 0x0c, 0xa2, 0x00, 0x9a, 0x6c, 0x28, 0xe6, 0xcb, 0x20, 0xf5, 0x17, 0x5e, 0x9c, 0xee, 0x63, 0xb0, 0x19, 0x0c, + 0x5e, 0xb3, 0x29, 0x1e, 0x04, 0x99, 0x61, 0x88, 0xec, 0x20, 0x69, 0x28, 0xec, 0x30, 0x26, 0x7e, 0x90, 0x9b, 0x61, + 0x88, 0x0f, 0x78, 0xa3, 0x11, 0x5b, 0xa4, 0x6e, 0x29, 0xa8, 0x4d, 0x34, 0x4a, 0x59, 0x6a, 0x26, 0x69, 0xcc, 0xbc, + 0xb9, 0x9a, 0x07, 0xb9, 0xaa, 0xf7, 0x97, 0x2c, 0x87, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, + 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0xcf, 0xa3, 0x69, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x29, 0x26, 0x09, 0xa3, 0x9b, + 0x0c, 0x48, 0x8b, 0x47, 0x51, 0x70, 0xcd, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xfe, 0x09, 0xbf, 0xde, 0x2a, 0x18, + 0xbe, 0x45, 0x3d, 0xb4, 0x21, 0x0d, 0xda, 0xa6, 0xe8, 0x16, 0xfb, 0xbc, 0x32, 0x90, 0x26, 0xea, 0x19, 0x33, 0x59, + 0x12, 0x2c, 0x17, 0xc0, 0x08, 0x95, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x77, 0xa7, 0x44, 0xa8, 0x90, 0x57, 0xfa, 0xf4, + 0xe9, 0xfd, 0xe0, 0xdf, 0xff, 0x82, 0x74, 0x9b, 0x33, 0x47, 0xc4, 0x94, 0xb8, 0x94, 0x6b, 0x71, 0xee, 0xd3, 0x18, + 0xa0, 0xb1, 0x14, 0x1b, 0x8b, 0x68, 0x7f, 0x62, 0x6b, 0x65, 0x83, 0x2b, 0x11, 0xa7, 0x0e, 0x12, 0xf5, 0xea, 0x22, + 0xf2, 0xc5, 0x00, 0x96, 0x77, 0x20, 0x62, 0xa2, 0x28, 0x7f, 0xbf, 0x7d, 0x79, 0xac, 0x14, 0xe1, 0x13, 0x9b, 0x2c, + 0x7a, 0x68, 0x0f, 0xf5, 0x4f, 0x3c, 0x05, 0x99, 0x16, 0x64, 0x3f, 0x92, 0xee, 0x3e, 0x0c, 0x73, 0x16, 0xcd, 0x99, + 0xe5, 0x47, 0xfb, 0x2b, 0x36, 0x34, 0xbd, 0x85, 0x4f, 0x76, 0x39, 0x28, 0x77, 0x53, 0x88, 0xf3, 0xcb, 0xcd, 0x5d, + 0x88, 0xbf, 0xce, 0x8a, 0xa9, 0x8c, 0x2a, 0x81, 0xd0, 0x5a, 0x85, 0x1e, 0xf0, 0x80, 0x07, 0x19, 0x13, 0x35, 0xfb, + 0x27, 0xfb, 0x5e, 0xbf, 0x9c, 0x79, 0xc6, 0x12, 0x19, 0x54, 0xcb, 0x44, 0xe0, 0x94, 0x12, 0xc8, 0x88, 0x5c, 0x31, + 0xc5, 0x83, 0x19, 0x4d, 0x26, 0x72, 0xb6, 0x18, 0xab, 0x0c, 0x5e, 0x3e, 0x69, 0xc5, 0x96, 0x8e, 0x16, 0xf4, 0xa5, + 0xfa, 0x27, 0xf2, 0x9f, 0x6a, 0x17, 0xd3, 0x44, 0xc1, 0x98, 0xe1, 0xb8, 0xd7, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, + 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x81, 0x73, 0xd9, 0x73, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0xd8, + 0x90, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x75, 0x18, 0xf7, 0x3d, 0xb1, + 0xfd, 0x4a, 0x1b, 0x14, 0x36, 0x1e, 0x5f, 0x77, 0xc0, 0xef, 0xa2, 0x9f, 0x0a, 0x9a, 0x57, 0xbe, 0x26, 0x8c, 0x6e, + 0x06, 0xde, 0x5d, 0x24, 0x99, 0x31, 0xf1, 0x88, 0x26, 0xe7, 0x58, 0x7a, 0x21, 0x3c, 0x89, 0x6b, 0x07, 0x0d, 0x49, + 0x18, 0x64, 0xdd, 0xac, 0x1f, 0xb6, 0x82, 0xfe, 0x06, 0xec, 0xbe, 0xb3, 0x26, 0xd7, 0x2d, 0x0f, 0x06, 0x91, 0x67, + 0x56, 0x9c, 0xc3, 0xd2, 0x4b, 0x44, 0x0b, 0xd9, 0xc9, 0x3e, 0x8c, 0x0f, 0xa2, 0xb0, 0x94, 0x18, 0x27, 0x5f, 0x87, + 0x50, 0x2f, 0x5e, 0x42, 0xa6, 0x58, 0xdf, 0x8f, 0x05, 0xcf, 0x87, 0x17, 0x4b, 0x29, 0x97, 0xbc, 0x54, 0xa5, 0xce, + 0xcb, 0xd8, 0xcd, 0x4c, 0xe0, 0xfd, 0x29, 0x6a, 0x3f, 0x2c, 0x31, 0x3f, 0x6d, 0xd6, 0x4b, 0x99, 0x08, 0x72, 0x70, + 0x9e, 0x6e, 0x88, 0x83, 0xb0, 0xa9, 0x0a, 0xf1, 0xb3, 0x5b, 0x2a, 0x14, 0xfb, 0x78, 0x5b, 0xad, 0x82, 0x73, 0x2a, + 0xaa, 0x79, 0x9a, 0xfa, 0x08, 0x77, 0x7c, 0xad, 0x36, 0x96, 0x62, 0x74, 0x86, 0xd4, 0x85, 0xaa, 0x42, 0x16, 0xef, + 0x2d, 0x16, 0x54, 0x59, 0xef, 0x9d, 0xec, 0xd3, 0xb5, 0xb4, 0x4f, 0x3b, 0xac, 0x7f, 0x02, 0xa6, 0xdc, 0xb4, 0xe8, + 0xde, 0x62, 0xc1, 0x97, 0x94, 0x7e, 0xd1, 0x9b, 0xfd, 0x59, 0x3a, 0x0f, 0xfa, 0xff, 0x0b, 0x3a, 0x5f, 0xcc, 0x86, + 0x37, 0x7a, 0x03, 0x00}; #else // Brotli (default, smaller) const uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0x90, 0x7a, 0x53, 0xc1, 0x6e, 0xc1, 0x56, 0x6f, 0x00, 0x79, 0xaf, 0xf6, 0x6d, 0x2b, 0x05, 0x44, 0x11, 0x6c, - 0x9c, 0x06, 0x03, 0x82, 0x71, 0xa5, 0x64, 0xba, 0x39, 0x78, 0xe4, 0x76, 0x00, 0x6c, 0xbb, 0xaa, 0xb6, 0x41, 0xaa, - 0x9a, 0x70, 0x54, 0x0e, 0x31, 0xb1, 0x27, 0x5a, 0x0c, 0xe6, 0x4f, 0xe4, 0x1a, 0x89, 0x16, 0xe8, 0x24, 0x0c, 0xc4, - 0xa0, 0x60, 0x71, 0x7b, 0x07, 0x92, 0xb2, 0x62, 0xb6, 0x5c, 0x32, 0xac, 0x0d, 0x63, 0xd8, 0x38, 0xf8, 0xf0, 0x15, - 0xdd, 0xce, 0xfe, 0x4e, 0x15, 0x9d, 0xab, 0xfb, 0x0e, 0x21, 0x59, 0x85, 0x78, 0xe1, 0xae, 0xca, 0x1f, 0x7a, 0x37, - 0xc2, 0x07, 0x0d, 0xc2, 0x31, 0x1f, 0x88, 0x73, 0x48, 0x2a, 0x4c, 0xba, 0xd2, 0xbd, 0x41, 0xc1, 0xe2, 0x9d, 0x07, - 0x35, 0xb2, 0xf3, 0xee, 0xab, 0xbf, 0x18, 0xc2, 0xf6, 0xaa, 0xb0, 0x9f, 0xb5, 0xd2, 0xfa, 0x3f, 0xf6, 0x7d, 0x54, - 0x0b, 0xb3, 0xd2, 0xab, 0x5f, 0x04, 0x6e, 0xfc, 0x69, 0xbd, 0x97, 0x2e, 0xb2, 0x64, 0x16, 0xef, 0x3e, 0x91, 0x2b, - 0x71, 0x11, 0xbe, 0xcd, 0xb8, 0x53, 0x58, 0x09, 0xdb, 0x0f, 0x9b, 0x37, 0x7d, 0x0d, 0x07, 0x83, 0x1b, 0x9b, 0xc5, - 0xa1, 0xa2, 0xe7, 0xc8, 0x8e, 0x39, 0x27, 0x54, 0x9d, 0x10, 0x84, 0x65, 0x80, 0xed, 0x72, 0x63, 0x84, 0x60, 0x65, - 0x09, 0x3d, 0x91, 0xd0, 0x17, 0xe9, 0x5b, 0x6f, 0xa9, 0xff, 0x5f, 0xbf, 0x19, 0xbe, 0x8d, 0x2c, 0x45, 0xbe, 0xa4, - 0xee, 0xb2, 0x8e, 0xab, 0xf6, 0x25, 0xb1, 0x13, 0xcf, 0x4b, 0x29, 0x70, 0xf3, 0x70, 0x1a, 0x71, 0xeb, 0x60, 0x02, - 0x80, 0xb6, 0x64, 0x56, 0x7e, 0x96, 0xa9, 0xdf, 0x79, 0x7a, 0x39, 0xd9, 0x2f, 0x99, 0x06, 0xff, 0x44, 0x32, 0x0f, - 0x49, 0x5e, 0x9a, 0x51, 0x37, 0x3b, 0xfb, 0xea, 0x76, 0x1c, 0x8c, 0x90, 0x44, 0x3f, 0x06, 0x17, 0x50, 0x96, 0xaa, - 0xbd, 0x5f, 0x7a, 0xef, 0xaf, 0xf5, 0xfd, 0xd7, 0x2f, 0x5d, 0xbd, 0x98, 0x7a, 0x54, 0x54, 0x66, 0xf6, 0xc2, 0xc0, - 0xdd, 0x76, 0xe7, 0x2e, 0x2b, 0xed, 0xa5, 0x51, 0x22, 0x72, 0x9a, 0x0e, 0x3e, 0x12, 0x5b, 0x1c, 0xc8, 0x2c, 0x36, - 0xad, 0x5e, 0xff, 0xd9, 0xc6, 0xde, 0xf5, 0x2f, 0x57, 0xd3, 0x1a, 0x69, 0xe5, 0x0a, 0xe3, 0xd8, 0x0a, 0x88, 0x38, - 0x12, 0x2b, 0xcb, 0xa4, 0xf8, 0x6a, 0xf6, 0xed, 0x74, 0x85, 0x3d, 0xf9, 0x75, 0x53, 0x96, 0xb5, 0xff, 0x7b, 0xbe, - 0x86, 0x1b, 0x47, 0xce, 0x65, 0xb3, 0x5a, 0xcf, 0xc4, 0x52, 0x94, 0x87, 0x12, 0x77, 0x36, 0x60, 0xdf, 0x57, 0xb5, - 0xaf, 0xdf, 0x23, 0x5f, 0x9e, 0x0f, 0xce, 0x24, 0x3b, 0x36, 0x75, 0x59, 0x4e, 0x87, 0x73, 0xc9, 0x5b, 0x75, 0xaf, - 0xd5, 0xf9, 0xc5, 0xac, 0x8c, 0x54, 0x48, 0x14, 0x20, 0x21, 0xd0, 0x29, 0x79, 0xdf, 0x57, 0x7d, 0xff, 0xeb, 0x5b, - 0x3a, 0x29, 0x0a, 0x95, 0xb2, 0x2b, 0xa8, 0x63, 0xa2, 0xe3, 0x75, 0x6c, 0xdf, 0x39, 0xfc, 0x18, 0x1a, 0xb2, 0x94, - 0xc3, 0x80, 0xbe, 0x24, 0x95, 0x09, 0xf8, 0xff, 0xfa, 0x9a, 0xbd, 0xff, 0xef, 0x9f, 0x2f, 0x89, 0x68, 0x95, 0xd8, - 0xd4, 0x2a, 0x4a, 0xb2, 0xe7, 0x73, 0x48, 0xd2, 0xd3, 0x9b, 0xc7, 0x76, 0x85, 0xc0, 0xba, 0xdc, 0x6e, 0x7a, 0x80, - 0x0e, 0x40, 0x9e, 0xb2, 0xf6, 0x31, 0x97, 0x55, 0xf5, 0x16, 0x15, 0x12, 0xf1, 0xeb, 0xf6, 0xfd, 0x8c, 0xfb, 0x98, - 0x6e, 0x60, 0x06, 0xc3, 0x46, 0x9e, 0x13, 0x8c, 0xeb, 0xf9, 0x69, 0xea, 0xe7, 0xe9, 0x2a, 0x78, 0x61, 0x23, 0x4f, - 0x7e, 0x1c, 0x0f, 0xab, 0x28, 0x12, 0x09, 0xd3, 0xda, 0x39, 0x9d, 0xdb, 0xf5, 0xd3, 0xfa, 0xf6, 0x79, 0x78, 0x48, - 0x3e, 0xa0, 0x56, 0xdf, 0xf0, 0xfb, 0x5f, 0x6f, 0xba, 0xfe, 0xeb, 0xd7, 0xee, 0xe2, 0x89, 0x73, 0xd1, 0x91, 0x52, - 0x09, 0x6f, 0xbd, 0x9a, 0x4b, 0xb3, 0xac, 0xf5, 0xc8, 0x52, 0x38, 0xac, 0x2a, 0xd7, 0x60, 0xac, 0x26, 0xa3, 0x19, - 0x23, 0xbb, 0xd4, 0x9d, 0x41, 0xc1, 0x6a, 0xfb, 0xd4, 0xb7, 0xf7, 0x8b, 0x52, 0x6b, 0xaa, 0x86, 0x85, 0x26, 0x1a, - 0x47, 0xb6, 0x43, 0x90, 0x4d, 0xbc, 0xfd, 0x26, 0x09, 0x1e, 0x02, 0x5a, 0xc2, 0xec, 0xb0, 0x56, 0x0f, 0xbc, 0x2b, - 0x52, 0xd7, 0x76, 0xad, 0x70, 0xf9, 0xa6, 0xfa, 0x5f, 0xbf, 0x91, 0x87, 0x33, 0xa5, 0x7a, 0xd2, 0xed, 0x3b, 0xbe, - 0x94, 0x8b, 0xb9, 0xda, 0x9a, 0x8e, 0x5e, 0x22, 0xe7, 0xf2, 0x64, 0xd0, 0xc5, 0xcd, 0x04, 0x04, 0xf0, 0x76, 0x17, - 0x24, 0x20, 0x8d, 0x0b, 0x14, 0x36, 0x44, 0x82, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, 0x34, 0x55, 0x84, - 0xc8, 0x6e, 0x80, 0x1c, 0x67, 0xd8, 0xb2, 0x7e, 0xdf, 0x59, 0x59, 0x05, 0xaa, 0x01, 0x92, 0x3d, 0xce, 0xac, 0xa4, - 0xb5, 0x16, 0x9b, 0x8a, 0x6b, 0xde, 0x65, 0x7e, 0x17, 0x9d, 0xf1, 0xc3, 0xb0, 0xc2, 0x64, 0x36, 0xd2, 0xd5, 0xb0, - 0x6c, 0x57, 0x96, 0xd3, 0x00, 0x20, 0x78, 0xdf, 0xfb, 0x3f, 0x0a, 0xff, 0xff, 0xc8, 0xe2, 0x44, 0x44, 0x16, 0xa8, - 0xc8, 0xac, 0xe2, 0x9c, 0xac, 0x02, 0x66, 0x54, 0x05, 0x70, 0x46, 0x05, 0xb0, 0x8f, 0x0e, 0xc8, 0xb1, 0x20, 0x68, - 0x34, 0x4d, 0x77, 0x34, 0xec, 0x96, 0xf7, 0x2b, 0x2d, 0x56, 0x1c, 0xca, 0xf5, 0x8c, 0x6c, 0x4b, 0x7e, 0xb7, 0x03, - 0x65, 0xcd, 0x52, 0x5a, 0xe9, 0xe8, 0x7f, 0xd7, 0xd4, 0xb6, 0x1b, 0x3b, 0x02, 0xd5, 0x37, 0x95, 0x0a, 0x21, 0xfb, - 0x7f, 0x52, 0xf8, 0x29, 0x61, 0x52, 0x4c, 0x86, 0xb9, 0x1b, 0xdd, 0x8d, 0xd0, 0xcd, 0x4a, 0x04, 0x25, 0x66, 0x36, - 0x46, 0xe4, 0xa0, 0x24, 0x70, 0xa0, 0xfa, 0x5f, 0x21, 0xd9, 0x6c, 0xda, 0x6e, 0x43, 0xb5, 0x73, 0x33, 0x3b, 0xf2, - 0xf9, 0x15, 0x33, 0x96, 0x10, 0xd3, 0x20, 0x6c, 0xda, 0x73, 0xf4, 0xcd, 0x8f, 0xd6, 0x9e, 0xbe, 0xb3, 0x6a, 0x92, - 0xd4, 0x5d, 0x7e, 0x0b, 0xff, 0x61, 0x80, 0x61, 0xe0, 0xec, 0x5b, 0x16, 0xd3, 0xec, 0x26, 0xfe, 0xba, 0x16, 0x0d, - 0x21, 0x44, 0x08, 0xd4, 0xb6, 0x43, 0xe6, 0xfa, 0xef, 0xbc, 0xb5, 0x3d, 0x71, 0x77, 0x7f, 0x13, 0x42, 0x4a, 0x63, - 0x52, 0x2a, 0x98, 0x71, 0x5f, 0x4c, 0x7d, 0xea, 0xb9, 0x75, 0xdc, 0x34, 0xa9, 0x9b, 0x99, 0xd9, 0xad, 0x45, 0x51, - 0x14, 0xaf, 0x13, 0x04, 0x40, 0xe5, 0x2f, 0x63, 0x62, 0xfd, 0xe8, 0xba, 0xd1, 0xff, 0xad, 0xc8, 0x96, 0x11, 0x86, - 0x08, 0x49, 0xac, 0x6b, 0x25, 0xd8, 0xdc, 0x18, 0x45, 0x9c, 0x5b, 0x1b, 0xc0, 0x8e, 0x8e, 0xd1, 0x6c, 0x41, 0x55, - 0xa0, 0xb1, 0xcd, 0x1d, 0xfc, 0x7c, 0x51, 0x00, 0xa6, 0x91, 0x1e, 0x4a, 0xde, 0x19, 0x9f, 0x10, 0x43, 0x0f, 0x19, - 0x5c, 0x78, 0x74, 0xe4, 0x81, 0x49, 0x75, 0x60, 0x44, 0x7f, 0xe9, 0xe6, 0x96, 0xb0, 0x06, 0x9e, 0x69, 0xb9, 0xe4, - 0x37, 0x82, 0xde, 0xe9, 0x7b, 0x00, 0x62, 0x12, 0x28, 0xd5, 0xed, 0x17, 0x6c, 0x0b, 0x4c, 0x8f, 0x9c, 0xa7, 0xbd, - 0x21, 0x29, 0x78, 0x70, 0xdc, 0xfd, 0xba, 0x0b, 0xa4, 0x5d, 0xca, 0x57, 0xec, 0x92, 0x61, 0xd6, 0xd1, 0x8d, 0xef, - 0xa6, 0xe8, 0x0a, 0xcd, 0x59, 0x0a, 0xea, 0x9c, 0xbb, 0x9e, 0x1b, 0xcb, 0x2f, 0x5a, 0x72, 0xfa, 0xb7, 0xa5, 0x8f, - 0xd9, 0xfb, 0xd2, 0x2f, 0xd4, 0x55, 0xf3, 0x2d, 0x70, 0x12, 0x00, 0xc8, 0xb2, 0x0f, 0x31, 0x2d, 0xc8, 0x92, 0xea, - 0x6b, 0xf9, 0xb9, 0x19, 0x6f, 0x35, 0x0d, 0x26, 0x68, 0x44, 0x36, 0x28, 0x00, 0xd8, 0xbb, 0xef, 0x9e, 0xbd, 0x5b, - 0x59, 0x4a, 0xe9, 0xd3, 0xec, 0x2f, 0xf3, 0xc0, 0x4b, 0xb3, 0x6c, 0x40, 0x8a, 0xb6, 0xa5, 0x1b, 0xf9, 0x50, 0x82, - 0x88, 0x86, 0xcd, 0x05, 0xcf, 0x46, 0x77, 0x6c, 0xe3, 0x51, 0x8b, 0x2f, 0xd6, 0xa8, 0x1c, 0x43, 0x83, 0xf8, 0x7a, - 0xe7, 0xdd, 0x4a, 0x85, 0x96, 0x94, 0xd7, 0xf8, 0x8e, 0xf6, 0x03, 0x26, 0x77, 0x6e, 0xe0, 0x03, 0x8d, 0xeb, 0xcf, - 0xe1, 0xaf, 0xed, 0xb9, 0x1c, 0x9a, 0x44, 0xa6, 0x97, 0xd9, 0x31, 0xce, 0x78, 0x76, 0x3f, 0x22, 0x09, 0x12, 0x8d, - 0xbe, 0xa8, 0x67, 0xfa, 0xf9, 0x5a, 0x73, 0x44, 0x8a, 0x50, 0xdf, 0xdf, 0x63, 0x17, 0xc8, 0x0b, 0xa7, 0x0b, 0xca, - 0xed, 0x7b, 0xdc, 0xff, 0x1c, 0x38, 0xda, 0x47, 0xf7, 0xf8, 0xdd, 0xea, 0x6e, 0x66, 0xdf, 0xbc, 0xc0, 0x63, 0x41, - 0x48, 0x9b, 0x20, 0x61, 0x98, 0xf9, 0xdd, 0x37, 0x11, 0x16, 0xef, 0x7b, 0x0b, 0x62, 0x35, 0xea, 0x4f, 0x7f, 0xfd, - 0xcb, 0x3e, 0xdd, 0xed, 0xf5, 0x88, 0x5f, 0x7f, 0x38, 0x78, 0x7a, 0x6f, 0x98, 0x86, 0xd5, 0x14, 0xda, 0x9e, 0xf5, - 0xcc, 0xf8, 0xb6, 0xad, 0xc2, 0xbe, 0xff, 0xf2, 0xf5, 0xe0, 0xae, 0xe7, 0x30, 0xb4, 0xee, 0x4e, 0x94, 0xc5, 0x23, - 0x86, 0x7f, 0x13, 0x24, 0xfd, 0x33, 0x27, 0xfd, 0xc2, 0xe7, 0x56, 0x80, 0x01, 0xba, 0xa5, 0xe6, 0x43, 0x6b, 0x8c, - 0x17, 0xbe, 0x41, 0x37, 0xc2, 0xc4, 0xfc, 0x0a, 0x4b, 0x29, 0x76, 0xde, 0xbf, 0x18, 0xd3, 0x27, 0xd6, 0x45, 0x4d, - 0x00, 0x44, 0x4a, 0x66, 0x13, 0xc0, 0xa0, 0x44, 0x06, 0x38, 0x1b, 0xc6, 0x75, 0xe9, 0x2e, 0xf4, 0xc8, 0xea, 0x66, - 0xd8, 0xc2, 0xfe, 0xcf, 0x17, 0x38, 0xc0, 0x27, 0xd6, 0x41, 0xc7, 0xcb, 0x4c, 0xc8, 0x1d, 0xb3, 0xe2, 0xff, 0xc7, - 0x4f, 0x6a, 0x72, 0x21, 0x96, 0xc2, 0x66, 0xb6, 0x75, 0x77, 0x8d, 0xdd, 0x48, 0x95, 0x89, 0xad, 0xcc, 0x8a, 0xea, - 0x5b, 0xa8, 0xe4, 0xf7, 0x4e, 0xee, 0x45, 0x95, 0xa2, 0xfa, 0x16, 0xc8, 0x96, 0x67, 0x78, 0xc7, 0xf1, 0xf5, 0x4f, - 0x03, 0xe2, 0xad, 0x94, 0x1c, 0xa5, 0x6a, 0x60, 0xc9, 0x93, 0x43, 0x3f, 0x6d, 0x50, 0x1e, 0x67, 0xa4, 0x0d, 0x38, - 0x72, 0x25, 0x7a, 0x66, 0xd0, 0xc8, 0xbb, 0x4e, 0x1e, 0x8b, 0x2a, 0xff, 0x2e, 0xf1, 0xfb, 0x4a, 0x6a, 0x11, 0x2c, - 0x19, 0xc9, 0x1d, 0x41, 0xcc, 0x16, 0xaa, 0x08, 0xed, 0x28, 0x9c, 0x48, 0x2b, 0x1e, 0xf1, 0x82, 0xf7, 0x7c, 0xbf, - 0x6d, 0x7b, 0x83, 0x84, 0x0b, 0x6f, 0x61, 0xf1, 0x2d, 0x3e, 0xc8, 0xf9, 0xe7, 0x72, 0xb2, 0x96, 0x8a, 0x9e, 0xb2, - 0x79, 0x9a, 0xd8, 0x52, 0xa2, 0x4b, 0x86, 0x40, 0x17, 0x54, 0x47, 0x6e, 0x98, 0x5c, 0x2f, 0x78, 0x7f, 0x83, 0xdb, - 0xe6, 0x17, 0x0b, 0x29, 0x5f, 0xcf, 0xcc, 0x6e, 0xeb, 0x01, 0x50, 0x75, 0xd8, 0x00, 0x3c, 0x65, 0xff, 0xdd, 0xe3, - 0x6e, 0xf2, 0x12, 0x61, 0xe1, 0xb1, 0x5b, 0x22, 0xed, 0xb2, 0x8f, 0x93, 0xa1, 0x57, 0x07, 0xf0, 0xf6, 0x44, 0x05, - 0x10, 0xb9, 0x8a, 0x39, 0x37, 0x9c, 0x88, 0xa4, 0xfe, 0x7d, 0xfa, 0x2d, 0x5d, 0xd8, 0xb0, 0x0d, 0x4d, 0xd0, 0x57, - 0x09, 0xaf, 0xa2, 0xf5, 0x8d, 0x8a, 0x5d, 0x8e, 0x00, 0x64, 0xad, 0x82, 0x99, 0x75, 0xdb, 0x10, 0xab, 0x93, 0x54, - 0x6e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd3, 0x1c, 0xb9, 0xa1, 0xea, 0x18, 0xff, 0xca, 0xd8, 0x9c, 0x4d, 0x34, 0x55, - 0xc3, 0xe2, 0x6f, 0x0d, 0xf2, 0x10, 0x2f, 0xfb, 0x88, 0x06, 0x3d, 0xca, 0xba, 0xe0, 0x1a, 0xb8, 0x0a, 0xf4, 0x92, - 0x1c, 0x3c, 0x73, 0x8d, 0x06, 0xc3, 0x1b, 0x63, 0x07, 0x02, 0x60, 0x93, 0x10, 0xca, 0x02, 0x5b, 0x2b, 0x1d, 0x54, - 0x75, 0xc7, 0xd4, 0xbc, 0xdf, 0xbd, 0x65, 0xa2, 0x4f, 0x45, 0x0b, 0x97, 0xa8, 0xbe, 0x90, 0x58, 0xed, 0xa1, 0xf9, - 0x0f, 0xed, 0xc2, 0x6f, 0x90, 0x20, 0x3c, 0xaf, 0x1d, 0xd0, 0x4f, 0x49, 0x9b, 0x52, 0x85, 0x0a, 0xa3, 0x6c, 0xe3, - 0xca, 0x76, 0x77, 0x45, 0x33, 0x0b, 0xe1, 0x9b, 0x89, 0x66, 0xbd, 0xed, 0xf8, 0xc1, 0x1e, 0x0d, 0x9b, 0x00, 0x5a, - 0x81, 0x05, 0x20, 0xea, 0xcf, 0xd5, 0xb6, 0xfd, 0x2e, 0x6c, 0x06, 0x55, 0x51, 0x92, 0x55, 0xa1, 0x8d, 0xa0, 0x91, - 0x81, 0x41, 0x13, 0x4d, 0xbf, 0xe8, 0x1e, 0xfc, 0xc2, 0x85, 0xb8, 0xa0, 0xb0, 0xa1, 0x74, 0xeb, 0xfa, 0x25, 0x52, - 0x05, 0xa6, 0xb1, 0x72, 0xb9, 0xff, 0x7e, 0x07, 0x1d, 0x7f, 0x5d, 0xec, 0x94, 0x7a, 0xae, 0xaa, 0x09, 0x75, 0x77, - 0x42, 0x13, 0x08, 0x1e, 0x0e, 0xbd, 0x70, 0xfa, 0x47, 0xc2, 0x1d, 0x24, 0xe7, 0xe5, 0xfb, 0xbf, 0x42, 0x0d, 0xfe, - 0x3c, 0xa0, 0x80, 0xf6, 0xaa, 0x7c, 0xde, 0x1d, 0x21, 0x38, 0x51, 0xbf, 0x02, 0x3b, 0xa2, 0xd2, 0x94, 0x1c, 0x51, - 0x58, 0x9c, 0x21, 0xbe, 0x01, 0xba, 0xf9, 0xb6, 0x53, 0xfd, 0xf9, 0xdb, 0x85, 0x13, 0xf1, 0xab, 0x6f, 0x97, 0xec, - 0x6d, 0xa4, 0x44, 0xe0, 0xa1, 0x5a, 0x9f, 0x1b, 0x84, 0x92, 0x0d, 0x96, 0x28, 0x45, 0x5c, 0x26, 0xa2, 0x4a, 0x08, - 0x16, 0x6d, 0x35, 0x6a, 0xe8, 0xd7, 0xeb, 0x2e, 0xb2, 0xae, 0xf1, 0x54, 0x05, 0x5f, 0xa8, 0xdf, 0xf6, 0x0c, 0x9b, - 0x79, 0x4d, 0xe7, 0x62, 0xff, 0x2b, 0x74, 0x4e, 0x2e, 0xb4, 0x76, 0xe9, 0x29, 0x04, 0x10, 0x85, 0x3b, 0xd3, 0x96, - 0x15, 0xc9, 0xd0, 0xae, 0xc0, 0xec, 0x07, 0x06, 0x92, 0x09, 0xf2, 0xc9, 0xfe, 0x4c, 0x0e, 0x21, 0x4d, 0x3c, 0x4e, - 0x46, 0x30, 0xbc, 0xd2, 0x50, 0xfa, 0xe6, 0x62, 0x78, 0xab, 0x5c, 0x9f, 0xc2, 0x2e, 0x88, 0x32, 0x07, 0xbe, 0xed, - 0x72, 0x74, 0x2b, 0x62, 0xf0, 0x8c, 0xc7, 0x8c, 0xb9, 0x77, 0xeb, 0xbd, 0xfb, 0x23, 0x52, 0x1d, 0x0b, 0x41, 0x6a, - 0x18, 0xc8, 0xaf, 0xc5, 0x40, 0x0f, 0xa8, 0x0a, 0x22, 0xf4, 0xd9, 0x58, 0x01, 0x9c, 0xbf, 0x5f, 0x31, 0x46, 0x6e, - 0xa9, 0x9e, 0x4b, 0xab, 0xab, 0x67, 0x15, 0x50, 0xd0, 0x18, 0x1d, 0x4c, 0xdd, 0x1a, 0x84, 0xd3, 0x86, 0xf6, 0xc1, - 0xc3, 0x23, 0xd2, 0x6b, 0x28, 0x62, 0xb1, 0x70, 0x56, 0xb8, 0xd4, 0xea, 0x6a, 0x61, 0x2a, 0x47, 0x7a, 0x24, 0xb9, - 0x72, 0x3b, 0x70, 0xfb, 0xde, 0xb4, 0x06, 0x09, 0x70, 0x8e, 0x18, 0xe2, 0x82, 0x46, 0x78, 0x5c, 0x13, 0x24, 0x48, - 0x48, 0x6f, 0x0c, 0xc8, 0x22, 0xc1, 0x45, 0xa6, 0x24, 0x7a, 0x11, 0x94, 0xda, 0x3d, 0x1d, 0xe9, 0x53, 0x80, 0x8b, - 0x71, 0xb2, 0x5a, 0x80, 0x25, 0x84, 0xf1, 0xba, 0xe6, 0x22, 0xc0, 0x56, 0x06, 0xb8, 0xb1, 0x66, 0x54, 0x70, 0x2e, - 0xec, 0xd0, 0x68, 0xd7, 0xca, 0xcf, 0xef, 0xc7, 0x02, 0x5c, 0x7a, 0xd1, 0x2c, 0x20, 0x10, 0x67, 0x2e, 0xef, 0x03, - 0x08, 0x39, 0x48, 0x5b, 0xa3, 0x37, 0x2d, 0x61, 0xa3, 0x84, 0x7c, 0x5a, 0x74, 0xf9, 0x95, 0x0f, 0x8d, 0x78, 0x58, - 0x2b, 0x6a, 0x2a, 0x41, 0x9f, 0xb1, 0x0d, 0x3e, 0xb8, 0x51, 0x93, 0xae, 0x0f, 0x96, 0x00, 0xa4, 0xc7, 0x32, 0x19, - 0x70, 0x8f, 0xa6, 0x17, 0xbd, 0x06, 0x52, 0xfa, 0xae, 0x1c, 0x39, 0x0e, 0x51, 0x7c, 0xbe, 0x45, 0x31, 0xb8, 0x37, - 0xad, 0xf1, 0x18, 0xc4, 0x07, 0x59, 0x32, 0xbe, 0x59, 0x14, 0x73, 0xac, 0x38, 0x13, 0x21, 0x7f, 0xd9, 0x48, 0x1a, - 0x09, 0x2b, 0x9d, 0xb6, 0x4a, 0x9a, 0x0a, 0x1b, 0x1b, 0xa0, 0x10, 0xa9, 0x87, 0xa0, 0x27, 0xb0, 0xeb, 0x0d, 0x89, - 0x79, 0x38, 0xd2, 0x52, 0xa4, 0x2f, 0x45, 0x5f, 0x73, 0x76, 0xca, 0x80, 0x4d, 0x84, 0x73, 0x73, 0x49, 0xf0, 0xdf, - 0xc4, 0xb6, 0x2e, 0x2e, 0x50, 0x31, 0xa3, 0x95, 0xe0, 0x21, 0x2c, 0x86, 0x97, 0x45, 0x05, 0x22, 0xeb, 0x6d, 0x7a, - 0x99, 0xb4, 0x92, 0x56, 0x79, 0x2c, 0x01, 0xd4, 0x71, 0x4f, 0x56, 0x16, 0x7a, 0x32, 0x1c, 0x61, 0x1f, 0x64, 0x9c, - 0x62, 0x1c, 0xc7, 0x9a, 0xd4, 0x66, 0xe4, 0xba, 0x13, 0x2d, 0x16, 0x32, 0xe3, 0xa1, 0xae, 0xa2, 0x12, 0x12, 0x18, - 0xd5, 0x24, 0x5d, 0x04, 0xde, 0xfa, 0x89, 0xf7, 0x04, 0x90, 0x80, 0xe8, 0x13, 0x3e, 0xf2, 0x93, 0x0c, 0xad, 0x86, - 0x84, 0x62, 0x45, 0xae, 0x21, 0xe7, 0xc5, 0x1b, 0xe5, 0x28, 0x72, 0xa7, 0xd1, 0x89, 0xbf, 0x16, 0xed, 0x9b, 0xc2, - 0xe6, 0x10, 0x84, 0xc3, 0x47, 0x85, 0x5d, 0xe8, 0x49, 0x3b, 0x95, 0x6a, 0x63, 0xa3, 0x9e, 0x87, 0x03, 0xde, 0xda, - 0x94, 0x09, 0x1e, 0xff, 0x5b, 0x43, 0x0d, 0xd1, 0xe6, 0xaf, 0x63, 0x06, 0x6c, 0xb3, 0xcd, 0xf6, 0x74, 0x0b, 0xf8, - 0x93, 0x38, 0xd9, 0x67, 0x50, 0x53, 0x36, 0x0f, 0x16, 0xdb, 0x75, 0x5f, 0x4e, 0x7e, 0x26, 0x53, 0x01, 0xc4, 0x55, - 0x41, 0xd5, 0x63, 0x64, 0x38, 0x20, 0xed, 0xa5, 0xe1, 0x71, 0x31, 0x40, 0x8a, 0x8c, 0xab, 0x92, 0x02, 0x81, 0x66, - 0x33, 0xa2, 0xb8, 0x01, 0xf4, 0xd8, 0x8c, 0xa3, 0xc4, 0x28, 0xb8, 0x41, 0x9e, 0x34, 0xd8, 0x98, 0x03, 0x97, 0x6a, - 0xd1, 0xac, 0xd2, 0xe6, 0x10, 0xd9, 0x03, 0x8b, 0x02, 0xe2, 0xf8, 0xf3, 0x5a, 0x43, 0x82, 0xbc, 0xe1, 0x7c, 0x12, - 0xc2, 0x00, 0xb7, 0x61, 0x04, 0xd9, 0xc3, 0x38, 0x22, 0xa1, 0xb8, 0xa9, 0x23, 0x7d, 0xfd, 0xc8, 0xde, 0x54, 0xde, - 0xef, 0x5a, 0x60, 0x18, 0xc7, 0x83, 0x81, 0xde, 0xbc, 0xd0, 0x92, 0x6e, 0x50, 0x97, 0x10, 0xf3, 0xb3, 0xb3, 0x99, - 0x19, 0x67, 0x6b, 0x8e, 0xe1, 0x61, 0xd8, 0x5c, 0x94, 0xf7, 0xf7, 0x6e, 0x12, 0x20, 0xbf, 0x13, 0x56, 0x7d, 0x72, - 0x12, 0x4f, 0x54, 0xfd, 0x5e, 0xd6, 0x3f, 0x12, 0xaf, 0x7f, 0x18, 0x50, 0xb2, 0xe9, 0xa1, 0x5e, 0xa9, 0x7b, 0x8b, - 0xe5, 0xac, 0xec, 0x9a, 0x82, 0x4a, 0x4b, 0x97, 0x65, 0x8c, 0x03, 0x49, 0xa0, 0x82, 0x7e, 0x29, 0xfb, 0xbc, 0x55, - 0x38, 0x50, 0x41, 0x21, 0x5b, 0x3f, 0x0d, 0xea, 0xe2, 0xf4, 0x2a, 0xc5, 0x2c, 0xc5, 0x18, 0xcf, 0x4e, 0x6d, 0x7d, - 0x1b, 0x90, 0x4e, 0x9d, 0xd2, 0xc0, 0xf3, 0x13, 0xdb, 0xed, 0xf6, 0x89, 0x13, 0x02, 0xb1, 0x52, 0x38, 0x11, 0x9b, - 0x59, 0x6c, 0x7e, 0xd0, 0x88, 0x54, 0x7e, 0x30, 0x0e, 0xc8, 0xca, 0x39, 0x6c, 0x81, 0xec, 0xb9, 0x29, 0x3c, 0x30, - 0xe6, 0x78, 0xdf, 0xf2, 0xd0, 0xad, 0xbf, 0xc3, 0x9f, 0x90, 0x93, 0x19, 0x65, 0xa6, 0xcf, 0xeb, 0xc1, 0x74, 0x57, - 0xdd, 0xb3, 0xc4, 0xe6, 0xcd, 0x75, 0xd2, 0x8b, 0x64, 0xb1, 0x97, 0xa2, 0x49, 0xba, 0x0c, 0x66, 0xed, 0x32, 0x88, - 0x5a, 0x2a, 0x60, 0xda, 0xe9, 0x6d, 0xa6, 0x71, 0x56, 0x40, 0x9f, 0x01, 0x33, 0xbb, 0xbb, 0x04, 0x5c, 0x17, 0x19, - 0x2c, 0xb1, 0x52, 0x88, 0xc2, 0xe3, 0x29, 0xed, 0xde, 0x4f, 0x0c, 0x94, 0x3e, 0x76, 0x81, 0xec, 0xa5, 0xa3, 0x87, - 0xa4, 0x76, 0x84, 0x28, 0xa2, 0x96, 0xfd, 0x21, 0x82, 0x42, 0x8a, 0x33, 0xfc, 0x80, 0xe9, 0xce, 0x47, 0xc8, 0xb8, - 0x00, 0xf9, 0xd9, 0x4c, 0xb4, 0xd5, 0x77, 0x5b, 0xc4, 0xc0, 0xcb, 0x0f, 0x25, 0xee, 0x27, 0xbd, 0x95, 0x6f, 0xc2, - 0xe3, 0x58, 0x71, 0x16, 0xc8, 0x58, 0xa1, 0x30, 0x8c, 0xe6, 0xfc, 0x04, 0x49, 0xd2, 0x7b, 0x38, 0x8f, 0x02, 0xb8, - 0x0c, 0xc1, 0x88, 0x02, 0xb5, 0x8d, 0x60, 0xf6, 0xc2, 0x4c, 0x35, 0xa0, 0xcc, 0x2d, 0x9a, 0x29, 0xc9, 0x5a, 0x3b, - 0x99, 0xe3, 0xcc, 0x73, 0x3f, 0x53, 0x18, 0x00, 0x54, 0x6c, 0xfa, 0xbd, 0x6a, 0xc5, 0xf2, 0x3a, 0x1e, 0x66, 0x6d, - 0xe5, 0x84, 0x98, 0x75, 0xf6, 0xfb, 0x14, 0x4d, 0x52, 0x01, 0xc8, 0x0a, 0xac, 0x4e, 0x8d, 0x49, 0x2a, 0xe7, 0x03, - 0xa3, 0x9b, 0x3a, 0x18, 0x46, 0x2c, 0x43, 0x65, 0x69, 0x1a, 0x06, 0x87, 0x6d, 0xfb, 0x3e, 0xc8, 0xe8, 0xd0, 0xef, - 0x5b, 0xd9, 0x58, 0x0a, 0x81, 0x96, 0x05, 0x5a, 0x3e, 0x0c, 0x68, 0x52, 0x86, 0x2b, 0x45, 0x79, 0x22, 0x47, 0xca, - 0x3d, 0xb2, 0xe4, 0x24, 0xef, 0xfb, 0xa9, 0x69, 0x57, 0x97, 0x0c, 0x88, 0x66, 0x2e, 0x54, 0xc3, 0xd7, 0x2c, 0xf9, - 0x33, 0x4c, 0x98, 0xac, 0xbd, 0x71, 0x98, 0xd7, 0x64, 0x8d, 0x1c, 0x99, 0xaa, 0x0e, 0x18, 0x82, 0x6a, 0x74, 0x39, - 0x36, 0xc6, 0x4f, 0x2c, 0x1a, 0xb5, 0xa1, 0x30, 0xaf, 0x1d, 0x2b, 0x25, 0x67, 0x96, 0x8e, 0x98, 0x77, 0x37, 0x16, - 0x9d, 0xea, 0xa7, 0x07, 0xb2, 0x65, 0xfd, 0x00, 0xdf, 0x59, 0x22, 0xc2, 0x07, 0xcb, 0x1f, 0xce, 0x6f, 0x23, 0xbb, - 0x74, 0x2d, 0x74, 0x4c, 0x6b, 0xeb, 0xf0, 0xa7, 0x66, 0x93, 0x96, 0x2c, 0xf5, 0xdf, 0xcb, 0x00, 0x15, 0xe4, 0x29, - 0xa8, 0x42, 0x75, 0x54, 0x42, 0x94, 0xe1, 0x60, 0x53, 0xad, 0xab, 0xa3, 0xf2, 0xc6, 0xb9, 0xeb, 0x1d, 0xdc, 0xd9, - 0x81, 0x2c, 0xa9, 0x3b, 0xc2, 0x27, 0x17, 0x7d, 0x15, 0x21, 0x45, 0xd8, 0x32, 0x23, 0x77, 0xf6, 0xe5, 0xe9, 0x23, - 0xaf, 0x6f, 0xed, 0x3c, 0x1d, 0x3a, 0x5f, 0x61, 0x90, 0x5d, 0x7b, 0x74, 0x6c, 0x64, 0xcb, 0x8d, 0x68, 0xdb, 0x78, - 0xde, 0x1d, 0xa5, 0xd1, 0x4f, 0x4a, 0x89, 0x57, 0x6e, 0x82, 0xa8, 0xfd, 0xc1, 0x42, 0xf2, 0x19, 0x9e, 0x43, 0xb6, - 0x60, 0xb4, 0x68, 0x4c, 0x6c, 0x3c, 0x07, 0xdc, 0x23, 0x8a, 0xeb, 0x47, 0x8f, 0x05, 0x09, 0x17, 0x9c, 0x01, 0xf6, - 0xd2, 0x9c, 0xdd, 0xb6, 0x06, 0xd8, 0xe5, 0x62, 0xe2, 0x8a, 0x3e, 0x2e, 0xcc, 0xf1, 0xee, 0xfa, 0x85, 0xb2, 0x23, - 0xf1, 0xae, 0xb9, 0x6c, 0x6f, 0x79, 0x2d, 0xa2, 0x34, 0x15, 0x01, 0x4c, 0x13, 0x84, 0x86, 0x32, 0xc7, 0x14, 0xe9, - 0xcd, 0xf4, 0x6a, 0x98, 0x73, 0x27, 0x6b, 0x2e, 0x76, 0x65, 0x50, 0xa8, 0x01, 0x51, 0x19, 0xe2, 0x38, 0x39, 0x4e, - 0x18, 0xd8, 0x6d, 0x02, 0xd0, 0x11, 0xb4, 0x61, 0x48, 0xe8, 0xad, 0x13, 0x40, 0x0b, 0xb1, 0xc8, 0x1f, 0x32, 0x29, - 0x15, 0xa7, 0xbe, 0x97, 0x97, 0x79, 0xf3, 0x82, 0x1b, 0x14, 0x47, 0x08, 0xda, 0x8a, 0xe7, 0xc1, 0x15, 0x43, 0xb7, - 0x47, 0xe1, 0xd0, 0xc6, 0x56, 0xe6, 0x19, 0x7f, 0x96, 0xe8, 0x07, 0xca, 0x6e, 0xec, 0xf5, 0x90, 0x76, 0xaa, 0x39, - 0x28, 0xc7, 0x30, 0xf8, 0x96, 0xe9, 0x51, 0xd2, 0xba, 0x05, 0x2e, 0x86, 0xdf, 0x3c, 0xc4, 0x7b, 0xef, 0xb8, 0x3d, - 0x7d, 0xcc, 0xd3, 0xee, 0xef, 0xc3, 0x67, 0x83, 0xd9, 0x97, 0xf9, 0x80, 0x2e, 0x1e, 0x0e, 0x5c, 0x43, 0x02, 0x33, - 0x12, 0x10, 0xba, 0xd1, 0xf5, 0xd6, 0xbd, 0x43, 0xcd, 0xf3, 0xe0, 0xc4, 0x3d, 0xe5, 0x37, 0x2e, 0x49, 0x17, 0x49, - 0xd7, 0x08, 0x65, 0xef, 0xff, 0x45, 0x0e, 0x4b, 0xcf, 0x23, 0xe3, 0xd1, 0xa6, 0xa6, 0x38, 0x13, 0x9c, 0x5d, 0x0e, - 0xf6, 0x16, 0x24, 0x8c, 0x63, 0xe4, 0x92, 0xc1, 0x38, 0x67, 0x66, 0x4c, 0xc4, 0xd6, 0x1c, 0xa4, 0x8d, 0x0c, 0x79, - 0x9d, 0x22, 0xf7, 0xc5, 0x4e, 0x01, 0xfa, 0x50, 0xc8, 0x69, 0xb7, 0x15, 0xfa, 0x24, 0x60, 0xe0, 0xff, 0x4e, 0x4b, - 0xfb, 0x1e, 0xf9, 0x3e, 0x6d, 0x62, 0x89, 0x14, 0x9b, 0xb1, 0x51, 0xcf, 0xc5, 0xdc, 0x2a, 0x64, 0xc3, 0xfa, 0x45, - 0x84, 0xfa, 0xdd, 0xac, 0x3c, 0x3b, 0xe6, 0x27, 0x12, 0xc0, 0x69, 0xeb, 0x10, 0x6c, 0xe7, 0xf3, 0xad, 0xff, 0x26, - 0xe9, 0xfb, 0xcc, 0xa2, 0x87, 0x73, 0x9d, 0x8c, 0x35, 0x27, 0xb0, 0xa0, 0xd4, 0xdb, 0xb1, 0x73, 0x7d, 0xba, 0xc7, - 0x73, 0xd5, 0x2c, 0xca, 0x20, 0xb9, 0xb6, 0x8b, 0xa4, 0x48, 0x3c, 0xb9, 0x7a, 0xe3, 0x6c, 0xc6, 0xf8, 0x58, 0xfc, - 0xbd, 0x3d, 0x4e, 0xfb, 0x7e, 0xe3, 0x33, 0xda, 0xbb, 0xf4, 0x7f, 0xce, 0xa6, 0xd3, 0xdf, 0x21, 0xe3, 0xb9, 0xae, - 0xd9, 0x52, 0x35, 0x85, 0x54, 0x93, 0x2d, 0x02, 0x50, 0x8d, 0x38, 0xdf, 0x1d, 0x77, 0xfb, 0xef, 0x0a, 0xa2, 0x99, - 0xbf, 0x20, 0xee, 0xbe, 0xd7, 0x52, 0x3d, 0x6d, 0x71, 0x34, 0xe5, 0xac, 0xf7, 0xc8, 0x6e, 0xf6, 0x1e, 0xf0, 0xb6, - 0xb4, 0xfa, 0xa7, 0xfa, 0x4f, 0xf8, 0xdd, 0x62, 0xf3, 0xb7, 0xdd, 0x7c, 0xea, 0xc3, 0xf6, 0xa4, 0xae, 0xb6, 0x78, - 0xb3, 0xd6, 0xdf, 0xec, 0x79, 0xbb, 0xdb, 0x7c, 0xa0, 0xd3, 0xfa, 0x2f, 0xe5, 0x75, 0x35, 0x18, 0x97, 0xea, 0xaf, - 0x40, 0xe2, 0xdf, 0x2a, 0xf4, 0xee, 0x0e, 0x90, 0x2f, 0xd5, 0xec, 0x20, 0xc3, 0xcc, 0xf8, 0x60, 0xbc, 0x0b, 0x5d, - 0x68, 0xeb, 0xf1, 0x6e, 0x14, 0x26, 0x2a, 0xc4, 0xfd, 0xdc, 0x35, 0x33, 0xd5, 0xbb, 0xe4, 0x6a, 0xd2, 0xa5, 0x5f, - 0x1b, 0x14, 0xaf, 0x4d, 0x68, 0xb1, 0x66, 0xc4, 0x36, 0x35, 0xff, 0x05, 0x58, 0xfe, 0xb9, 0xe0, 0x19, 0xc6, 0x4d, - 0xda, 0x8f, 0x6a, 0xbb, 0x52, 0xf9, 0xfe, 0xa7, 0xf1, 0xd7, 0xa6, 0x9e, 0xb2, 0xce, 0x7f, 0xde, 0x7d, 0x5b, 0xfe, - 0x99, 0xcb, 0x8e, 0x4c, 0x55, 0xfd, 0x05, 0xf9, 0xc4, 0xa4, 0x2b, 0xe5, 0x78, 0x3d, 0xcb, 0xfe, 0x5f, 0x84, 0xbb, - 0x7f, 0x3b, 0xff, 0xf2, 0x9f, 0x66, 0xe1, 0x7d, 0x20, 0xcd, 0x4e, 0xc3, 0x17, 0x92, 0xdf, 0xd9, 0xb2, 0x7a, 0x7e, - 0xe7, 0x0b, 0xd4, 0x58, 0x71, 0x8f, 0xac, 0x2f, 0x65, 0x62, 0x55, 0x2e, 0xe0, 0xd6, 0x7f, 0x3b, 0xd5, 0x5f, 0x0f, - 0xe4, 0xf3, 0x9e, 0x92, 0xf9, 0x62, 0xf8, 0xb5, 0x79, 0x73, 0x4f, 0xa7, 0x7a, 0xd7, 0x2f, 0xfc, 0x78, 0x4c, 0x4a, - 0x7f, 0xd5, 0xe3, 0x32, 0xb8, 0xb9, 0x52, 0xff, 0xd5, 0xc2, 0xa7, 0x2b, 0x83, 0xf2, 0xcf, 0xc8, 0xc7, 0xe3, 0xf5, - 0xcd, 0xe2, 0x63, 0xf9, 0x3e, 0x0b, 0x18, 0x27, 0x38, 0xa3, 0xe6, 0x0b, 0xdc, 0x11, 0x54, 0x1f, 0xe2, 0x91, 0xac, - 0x3f, 0x99, 0x55, 0x3c, 0xdc, 0x2b, 0x70, 0xfc, 0x96, 0x57, 0x7e, 0xe6, 0xd2, 0x24, 0x5c, 0x30, 0x4e, 0x7f, 0xc4, - 0xa3, 0xef, 0x3b, 0x18, 0x7d, 0xd0, 0xbb, 0xf1, 0xdd, 0x8c, 0x3a, 0xe2, 0x63, 0xf3, 0xac, 0xab, 0x96, 0xc6, 0x5b, - 0x29, 0x39, 0x61, 0x1b, 0xfd, 0x55, 0xc0, 0x43, 0x0c, 0xda, 0xbe, 0xf7, 0xad, 0xf2, 0x37, 0x7e, 0x17, 0xa6, 0xf7, - 0xd6, 0x8f, 0xbf, 0xbf, 0x12, 0xef, 0xf6, 0xef, 0x0c, 0x13, 0x88, 0xf5, 0xc0, 0xbb, 0xe8, 0xff, 0xa8, 0x86, 0x4f, - 0x48, 0xe6, 0x44, 0x61, 0x4d, 0xdd, 0x2f, 0xd5, 0xf7, 0xe1, 0xe2, 0x41, 0x24, 0x5f, 0x16, 0xef, 0xfb, 0x44, 0x1e, - 0xee, 0xd1, 0xb3, 0xbc, 0x97, 0x46, 0x1c, 0x40, 0x0d, 0x05, 0xc8, 0x82, 0x7c, 0x32, 0x8c, 0xc0, 0xce, 0x73, 0x0a, - 0x3b, 0xa7, 0xaa, 0xcf, 0xee, 0x22, 0xd2, 0xbb, 0xd5, 0xdc, 0x9a, 0x3f, 0x01, 0x4a, 0x61, 0x9b, 0x08, 0xb0, 0xef, - 0xa7, 0x3b, 0x9a, 0xd4, 0x7a, 0x9d, 0x6e, 0xfd, 0xe9, 0xe4, 0x4a, 0x4d, 0xea, 0xb6, 0xba, 0xc8, 0x78, 0xe0, 0x79, - 0x93, 0x13, 0x9e, 0xdd, 0x98, 0xe8, 0x14, 0x63, 0x13, 0x0e, 0xda, 0x99, 0x29, 0xeb, 0xb1, 0x73, 0x1d, 0x12, 0x91, - 0xdd, 0xd0, 0x10, 0x77, 0x99, 0xdb, 0x23, 0xb8, 0x51, 0x11, 0x89, 0x5a, 0x42, 0x7d, 0xf1, 0x7b, 0x26, 0x93, 0x89, - 0x6f, 0xe5, 0x39, 0x1b, 0x7e, 0xe1, 0x7f, 0x56, 0xc9, 0x82, 0x01, 0xc8, 0xc9, 0xd4, 0xc9, 0x23, 0x50, 0xf1, 0x35, - 0x41, 0xb4, 0xf3, 0x59, 0x4e, 0xdc, 0x3b, 0x2c, 0xca, 0x53, 0xcd, 0xcc, 0xf3, 0xbf, 0x6b, 0x60, 0xcd, 0x42, 0x51, - 0xc4, 0x46, 0x34, 0xcb, 0xf6, 0x76, 0x33, 0x8b, 0x7a, 0x1e, 0xbe, 0x02, 0xe1, 0xec, 0x32, 0x00, 0x7d, 0x5b, 0xd5, - 0xb0, 0x96, 0x33, 0xf3, 0x97, 0xde, 0x08, 0x01, 0x6a, 0x1e, 0xf4, 0x30, 0x66, 0xef, 0x4d, 0xc9, 0xfe, 0x51, 0x90, - 0x53, 0x9e, 0x9b, 0x9a, 0xce, 0x19, 0x67, 0xc9, 0x73, 0x38, 0x93, 0x12, 0xd2, 0x4e, 0x7b, 0xa4, 0x22, 0xd2, 0xf0, - 0xda, 0xac, 0x5e, 0x2c, 0x65, 0x7d, 0xb8, 0xe5, 0x85, 0x29, 0x20, 0x0c, 0x48, 0x82, 0xd8, 0x53, 0xf8, 0x39, 0x58, - 0xf4, 0x21, 0x14, 0x45, 0x12, 0xbd, 0x52, 0x38, 0xbd, 0x9d, 0x98, 0xbd, 0x24, 0xa9, 0xd1, 0xe9, 0x11, 0xae, 0xff, - 0xbe, 0xb7, 0x73, 0x8e, 0x9e, 0x49, 0x16, 0xe9, 0xdb, 0xf4, 0x97, 0x51, 0xbb, 0x59, 0xa2, 0xa9, 0xed, 0x0d, 0x00, - 0xce, 0xb1, 0x52, 0xc3, 0xee, 0xfb, 0xa5, 0x91, 0xa2, 0x25, 0xbe, 0xbc, 0x20, 0xa3, 0xa2, 0x4b, 0x5a, 0xea, 0xbb, - 0x38, 0x5d, 0x54, 0x65, 0x1b, 0xfc, 0x3e, 0x39, 0xe0, 0xc5, 0x1b, 0x30, 0x49, 0x5f, 0x91, 0x3e, 0x12, 0x04, 0xa7, - 0xcd, 0xc6, 0x6c, 0x6f, 0xdd, 0x47, 0xf2, 0xd6, 0xc2, 0x7f, 0xd1, 0x5e, 0x58, 0xf5, 0xa2, 0x67, 0x2a, 0x03, 0xdc, - 0x22, 0x5f, 0x96, 0x71, 0x4e, 0x34, 0xad, 0x5a, 0xf0, 0xa2, 0x2b, 0xa8, 0x33, 0xf7, 0x34, 0x6f, 0xed, 0x22, 0xd8, - 0x10, 0xda, 0xe7, 0xc1, 0x2c, 0x59, 0x60, 0x85, 0x20, 0x94, 0xb7, 0x63, 0xeb, 0x19, 0xd7, 0x5f, 0x35, 0xf8, 0x65, - 0xe5, 0x62, 0x29, 0x74, 0x80, 0x61, 0xf2, 0xdb, 0x1a, 0x08, 0x9e, 0xfa, 0x12, 0xca, 0x02, 0xbd, 0x6d, 0xe1, 0xf1, - 0x9a, 0xee, 0xde, 0x9d, 0xe1, 0x84, 0x10, 0xdf, 0x6f, 0xc6, 0x42, 0x79, 0x1e, 0xfd, 0x92, 0xd1, 0x08, 0xcb, 0x1d, - 0x8e, 0x28, 0xa7, 0x47, 0x83, 0x6c, 0x70, 0x7c, 0x67, 0xeb, 0x51, 0x65, 0x59, 0xe6, 0x11, 0x16, 0x9f, 0x92, 0x05, - 0xf6, 0x82, 0xec, 0xe2, 0xfe, 0xd3, 0x75, 0x28, 0x4c, 0xb1, 0x07, 0x6a, 0x72, 0xab, 0xde, 0xa6, 0x5c, 0x3b, 0xfe, - 0x35, 0x5b, 0xe8, 0xc8, 0x6e, 0xf7, 0x90, 0x7e, 0x8b, 0x6b, 0x6b, 0x0c, 0x6d, 0xdf, 0x90, 0x44, 0xe9, 0x34, 0xdd, - 0x3d, 0x03, 0x0a, 0xf4, 0x3f, 0x26, 0x94, 0xfc, 0x85, 0x34, 0xd3, 0xac, 0x4b, 0xb1, 0xab, 0xfd, 0x12, 0xe7, 0x64, - 0xfa, 0xeb, 0x99, 0x87, 0x7a, 0xa9, 0xfe, 0xdf, 0xeb, 0x35, 0x0d, 0x98, 0xe8, 0x8d, 0x69, 0x04, 0x34, 0x90, 0x22, - 0x95, 0x98, 0x6f, 0x2c, 0xa3, 0x06, 0x49, 0x67, 0x99, 0x91, 0x52, 0xae, 0xa3, 0xfb, 0x8d, 0x0a, 0x85, 0x0b, 0xdd, - 0xbd, 0xad, 0xb8, 0x31, 0xa5, 0xb7, 0x45, 0x8f, 0xe2, 0x37, 0xe6, 0xbd, 0x19, 0xc7, 0x71, 0x73, 0x91, 0x21, 0xe1, - 0x02, 0x3d, 0x8b, 0x1e, 0x57, 0xe7, 0x88, 0xd7, 0x44, 0x39, 0x78, 0x04, 0xd1, 0x31, 0xd1, 0x13, 0xe2, 0x66, 0xbc, - 0xf5, 0x16, 0x7c, 0x62, 0x40, 0xbe, 0xe7, 0xcd, 0x12, 0x7c, 0x68, 0x5b, 0xe5, 0x39, 0x06, 0x1d, 0xf0, 0xab, 0xf5, - 0x6c, 0x29, 0x00, 0x0b, 0xb3, 0x29, 0xef, 0x6a, 0x29, 0xd0, 0x85, 0x86, 0xa4, 0xc9, 0xf3, 0x5d, 0x3d, 0x1d, 0xbf, - 0x44, 0xc3, 0x54, 0x24, 0x52, 0xd2, 0x9b, 0xf8, 0x86, 0xf3, 0x78, 0xa0, 0xad, 0x4e, 0x7d, 0x16, 0x7a, 0xb5, 0x55, - 0x9d, 0x9d, 0x77, 0x93, 0xd7, 0x61, 0x41, 0x17, 0x67, 0x1b, 0x50, 0x8e, 0x35, 0x93, 0x6e, 0x4a, 0x56, 0x55, 0x93, - 0xa2, 0x9c, 0x04, 0x86, 0x68, 0x17, 0xe1, 0x0a, 0xca, 0x9f, 0x57, 0x7d, 0x22, 0x95, 0xfa, 0x62, 0x16, 0x7f, 0x7a, - 0xb0, 0x52, 0x15, 0xf1, 0x3f, 0x38, 0xf2, 0x92, 0xed, 0x12, 0x29, 0x96, 0xa5, 0xa2, 0xf7, 0x33, 0x41, 0x5e, 0xfd, - 0xe1, 0x86, 0xe5, 0xba, 0x87, 0xfd, 0x2a, 0xd5, 0x1b, 0xe2, 0x69, 0xac, 0x18, 0x99, 0x5a, 0x5c, 0xf1, 0x96, 0xcb, - 0x53, 0x48, 0x8b, 0xf5, 0x98, 0x97, 0x2e, 0x69, 0xbc, 0x07, 0xde, 0x6e, 0x30, 0x41, 0x3f, 0x49, 0x6e, 0xd7, 0xb1, - 0x38, 0xa8, 0x45, 0x5d, 0xc8, 0xdb, 0x47, 0x63, 0x76, 0xe4, 0x72, 0x03, 0x1f, 0xbf, 0xb8, 0xd3, 0x39, 0x6f, 0xbc, - 0x56, 0xbe, 0xaa, 0x3b, 0xa1, 0xe0, 0xd7, 0x06, 0xa8, 0x26, 0x43, 0x6c, 0x11, 0xa2, 0x05, 0xdf, 0x7c, 0xb4, 0x59, - 0x9e, 0xd0, 0x12, 0x93, 0x66, 0xe5, 0xf2, 0xc5, 0x0b, 0xf3, 0xae, 0xd8, 0x1f, 0x2b, 0xe7, 0x66, 0x2a, 0xe3, 0x2b, - 0x7d, 0xed, 0x2a, 0x72, 0x59, 0x78, 0x8d, 0x42, 0x45, 0x28, 0xaa, 0x48, 0x1b, 0x17, 0xd8, 0xea, 0x66, 0xd8, 0xf2, - 0x99, 0x79, 0xa1, 0x69, 0xda, 0x98, 0x71, 0x52, 0x5c, 0x32, 0xc2, 0x3f, 0xe8, 0x08, 0xf6, 0x45, 0xab, 0x3c, 0xff, - 0xb1, 0x63, 0xb1, 0x70, 0x03, 0xed, 0x38, 0x7a, 0x21, 0x47, 0x25, 0xe9, 0xd1, 0x27, 0x85, 0xb2, 0xca, 0x34, 0xf2, - 0xae, 0xfa, 0xa4, 0xc2, 0x53, 0x74, 0x07, 0x45, 0x8e, 0xc2, 0x96, 0x0c, 0x6b, 0x65, 0x8c, 0xeb, 0x11, 0x7e, 0xd6, - 0xce, 0xde, 0x39, 0xdc, 0xec, 0x41, 0xec, 0xf0, 0x5f, 0x94, 0xe3, 0x73, 0x93, 0x25, 0x1e, 0x46, 0xfa, 0x2a, 0x79, - 0x9b, 0xa7, 0x13, 0x1f, 0xbe, 0xc9, 0x8c, 0xec, 0x96, 0xfa, 0x4f, 0xec, 0xf3, 0x3a, 0x42, 0x44, 0xce, 0xf3, 0x5d, - 0x45, 0x46, 0xa7, 0x70, 0x91, 0xeb, 0x94, 0xd2, 0x47, 0x95, 0x42, 0x02, 0x65, 0x49, 0xe3, 0x96, 0x65, 0xf7, 0x1f, - 0x7f, 0x50, 0xa1, 0xe5, 0x6b, 0x07, 0x66, 0xd2, 0x6d, 0x66, 0x96, 0x48, 0x16, 0x35, 0x46, 0x76, 0xa3, 0xe7, 0x1f, - 0x15, 0x89, 0x04, 0x49, 0x1a, 0x43, 0xa4, 0x73, 0x37, 0xdc, 0xe9, 0xff, 0x0e, 0xf7, 0xec, 0xc6, 0x92, 0xa2, 0x69, - 0x16, 0xca, 0xec, 0x0f, 0xf8, 0xa6, 0xdf, 0x21, 0x87, 0xa6, 0x8a, 0x92, 0x41, 0x0d, 0x6f, 0xe4, 0xdc, 0x86, 0x6e, - 0xcd, 0x83, 0xf5, 0xec, 0x17, 0xd0, 0x67, 0x8c, 0x06, 0x6a, 0xab, 0xd1, 0x4b, 0xd2, 0x37, 0x4a, 0xd4, 0x79, 0x1f, - 0x14, 0x14, 0xd4, 0xdb, 0x40, 0xe7, 0xa6, 0x26, 0x44, 0xbb, 0x5f, 0x04, 0x45, 0x90, 0x85, 0x68, 0xbc, 0xf0, 0xb1, - 0x7c, 0x91, 0xee, 0x49, 0x94, 0x48, 0xa8, 0x76, 0x5c, 0x7c, 0xcf, 0xa5, 0x34, 0x28, 0x78, 0xd4, 0x1a, 0x50, 0xec, - 0xba, 0x40, 0x7d, 0x80, 0x95, 0x55, 0xd6, 0x61, 0xde, 0x0a, 0x52, 0x35, 0x1a, 0x56, 0xdb, 0xcc, 0x2e, 0x4e, 0x9e, - 0x29, 0x32, 0x93, 0x84, 0x3d, 0xeb, 0xef, 0x2a, 0x5e, 0xe6, 0x48, 0x94, 0x95, 0x2d, 0x01, 0xeb, 0x5d, 0xb3, 0xc3, - 0xd1, 0x6c, 0x51, 0x5a, 0xbb, 0x16, 0xf6, 0xaf, 0x6c, 0x54, 0x49, 0x53, 0xaf, 0x63, 0x29, 0x71, 0x0d, 0x1b, 0xb9, - 0x4d, 0x06, 0xe2, 0x63, 0xf9, 0x6d, 0x92, 0x00, 0xe1, 0xbb, 0x78, 0xc4, 0x43, 0x37, 0x59, 0xb1, 0xa9, 0xec, 0x5c, - 0x59, 0xec, 0xf5, 0xe8, 0x05, 0x9c, 0x1e, 0x4d, 0xae, 0x24, 0x47, 0xb7, 0xc5, 0x79, 0x71, 0x57, 0xf1, 0x54, 0xe9, - 0xb2, 0xf8, 0x97, 0xfa, 0x0f, 0x54, 0x6e, 0x0f, 0x2b, 0x84, 0xfd, 0x2d, 0x91, 0xbb, 0x80, 0x94, 0x67, 0x81, 0x10, - 0x6a, 0x89, 0x08, 0x9b, 0x6f, 0x85, 0x28, 0xb0, 0x28, 0xb0, 0x49, 0xf3, 0x38, 0xc7, 0x6a, 0xbd, 0x15, 0x4d, 0x72, - 0x07, 0x92, 0x7b, 0xd8, 0x8d, 0x5b, 0x12, 0xca, 0xbd, 0xf2, 0xd8, 0xe6, 0x2f, 0x51, 0xd0, 0x07, 0x2d, 0x69, 0x5c, - 0x35, 0x02, 0x9c, 0x5e, 0xf2, 0xd5, 0x2b, 0xfd, 0xb6, 0xeb, 0x87, 0x1b, 0xe4, 0x9e, 0x65, 0x22, 0xd2, 0x2e, 0xc4, - 0xc4, 0xa7, 0xbe, 0xea, 0x3a, 0x1b, 0x07, 0xab, 0xb5, 0x8d, 0xf9, 0x78, 0x4a, 0x96, 0xad, 0x67, 0x97, 0x11, 0xbc, - 0xec, 0x38, 0x81, 0xc7, 0x77, 0x44, 0x17, 0x13, 0xd7, 0x48, 0x2a, 0x1a, 0x70, 0xc5, 0xd9, 0x46, 0x53, 0xbc, 0xef, - 0x53, 0xa0, 0xc3, 0xa2, 0xb9, 0x47, 0x65, 0xd0, 0x85, 0x80, 0x8e, 0x77, 0xee, 0x5e, 0x17, 0xc6, 0x6e, 0x9e, 0x28, - 0xad, 0xff, 0xc1, 0xad, 0x26, 0x2a, 0x0d, 0xeb, 0xb0, 0x04, 0x8a, 0x09, 0x39, 0xd1, 0x6e, 0xcc, 0xed, 0xd1, 0x43, - 0xc3, 0x67, 0x75, 0xd1, 0x68, 0x0d, 0xc4, 0x59, 0xe0, 0xf9, 0xdb, 0xb0, 0xb6, 0xb5, 0x11, 0x71, 0xff, 0x6b, 0x32, - 0x8a, 0x5a, 0x6e, 0x45, 0xe5, 0xcf, 0x3a, 0xc2, 0x45, 0x92, 0x81, 0xd9, 0x32, 0xfc, 0x46, 0x84, 0xd5, 0x1f, 0x21, - 0xe6, 0x1e, 0x87, 0x36, 0x21, 0xfd, 0xa5, 0x2d, 0xaf, 0xad, 0x87, 0x41, 0xc8, 0x87, 0x23, 0x9e, 0xa0, 0x88, 0x35, - 0xaa, 0x7b, 0x70, 0x32, 0x6c, 0x9c, 0x03, 0xab, 0xb6, 0x8b, 0x32, 0x0b, 0x67, 0x91, 0x91, 0x62, 0xe6, 0x33, 0xdb, - 0x04, 0x3e, 0x86, 0x0e, 0x3a, 0xa9, 0x3a, 0x75, 0x72, 0x50, 0x0d, 0x02, 0x30, 0x21, 0x0b, 0xed, 0x0b, 0x84, 0xae, - 0x11, 0x2c, 0xcb, 0x4a, 0xa5, 0xd5, 0x7a, 0x00, 0x8b, 0x8f, 0x50, 0xea, 0x17, 0x9f, 0xb8, 0xd5, 0x93, 0xce, 0xc1, - 0x28, 0xe2, 0xd0, 0x93, 0x5e, 0x8a, 0x3e, 0x45, 0x1e, 0x8b, 0x1d, 0x08, 0xb9, 0xb8, 0xf5, 0x4e, 0x36, 0x23, 0x1b, - 0x09, 0x5a, 0x09, 0xee, 0x01, 0x5a, 0xf7, 0xdc, 0x6a, 0x67, 0x3a, 0x21, 0xd0, 0x12, 0x69, 0x8c, 0x90, 0xe8, 0x1e, - 0x62, 0x0e, 0x89, 0x08, 0xf0, 0xa2, 0x60, 0x82, 0x29, 0x85, 0xb2, 0xb3, 0x1e, 0x52, 0xe8, 0xfd, 0x95, 0x65, 0x5c, - 0x4d, 0x64, 0x1e, 0x58, 0x61, 0x20, 0x8c, 0x33, 0x5f, 0x23, 0x0f, 0x09, 0x20, 0x67, 0x68, 0xfb, 0xa3, 0xa6, 0x47, - 0x6b, 0x33, 0x67, 0xda, 0xb8, 0x42, 0x36, 0x3e, 0x07, 0x45, 0xbc, 0x60, 0xc2, 0xf5, 0x59, 0xfd, 0xb8, 0xca, 0x75, - 0xa5, 0xe3, 0xd5, 0x8d, 0x94, 0xfb, 0x2a, 0xfe, 0xec, 0x12, 0x23, 0x59, 0x36, 0xbd, 0x69, 0x2a, 0x3d, 0x9d, 0x5a, - 0x7d, 0x67, 0x35, 0xd0, 0xb3, 0x3d, 0xc0, 0x13, 0x1e, 0x82, 0x4b, 0xcd, 0xc8, 0x2f, 0xb9, 0x04, 0x2d, 0xe0, 0x87, - 0x26, 0xa4, 0x23, 0x15, 0x0c, 0x8b, 0x79, 0x91, 0x96, 0xd3, 0xb2, 0xd8, 0x26, 0x35, 0x65, 0x60, 0x18, 0xc7, 0x64, - 0xa2, 0xc2, 0xa9, 0xfd, 0x03, 0xbf, 0xe7, 0xd9, 0x8c, 0x3c, 0xcd, 0x1a, 0x64, 0xf7, 0x6d, 0x9a, 0xc7, 0x2a, 0x17, - 0xd6, 0xda, 0x0a, 0x10, 0x7e, 0xc7, 0xbb, 0x82, 0xde, 0x48, 0xd1, 0x64, 0x98, 0xc1, 0x68, 0x69, 0xfc, 0xc8, 0xe0, - 0x7f, 0x97, 0x61, 0x55, 0xda, 0xa2, 0x06, 0x6e, 0x5f, 0xc4, 0x52, 0x1f, 0x94, 0x28, 0xd2, 0x56, 0x19, 0x62, 0xcb, - 0x63, 0x15, 0x7e, 0x57, 0x45, 0x47, 0x90, 0x61, 0xbb, 0x7e, 0xe6, 0xa8, 0xcd, 0xb1, 0x1f, 0x0e, 0x59, 0xb1, 0x27, - 0x73, 0x06, 0xc5, 0xc7, 0xfd, 0xc5, 0xa2, 0xab, 0x3a, 0x49, 0xcf, 0x16, 0x81, 0xba, 0x42, 0xc6, 0x53, 0xaf, 0x74, - 0x37, 0x52, 0x58, 0x6a, 0x64, 0x2b, 0xa0, 0x0c, 0x33, 0x54, 0x4b, 0x53, 0x74, 0xfb, 0x3d, 0x2b, 0x84, 0x44, 0x09, - 0x01, 0x46, 0x78, 0xef, 0x85, 0x2e, 0xfa, 0x7f, 0x9a, 0x37, 0xbe, 0x6f, 0x9d, 0x3a, 0x36, 0x0f, 0x47, 0x48, 0x09, - 0x10, 0x32, 0x29, 0xd7, 0xd0, 0x0f, 0x86, 0x82, 0xf1, 0x20, 0x51, 0x30, 0xf8, 0x39, 0xf6, 0x23, 0xe0, 0x66, 0x96, - 0x96, 0x47, 0x7e, 0x11, 0x4d, 0x4c, 0x89, 0xc7, 0x74, 0x46, 0x2a, 0xb7, 0xfb, 0x88, 0xab, 0x47, 0xba, 0x41, 0xf5, - 0x2d, 0x8a, 0x60, 0xf2, 0x2f, 0x35, 0x10, 0xde, 0xbd, 0x8e, 0xb9, 0x74, 0x9b, 0x9a, 0x37, 0x39, 0x00, 0xd3, 0xbd, - 0x2d, 0x51, 0xd7, 0x02, 0xa4, 0xde, 0x34, 0x85, 0x1f, 0xf6, 0x4f, 0x11, 0xb0, 0x38, 0x62, 0xb1, 0x49, 0x9d, 0x9e, - 0x53, 0xed, 0x7d, 0xb1, 0x6c, 0x04, 0xe1, 0xfe, 0x2a, 0xbb, 0xc8, 0x5d, 0x20, 0x90, 0xc9, 0x1a, 0x64, 0x10, 0x8e, - 0x35, 0xc3, 0x7a, 0x47, 0xab, 0xb2, 0xb1, 0x26, 0xad, 0xdd, 0xc7, 0xa5, 0xb4, 0xfb, 0x5a, 0x17, 0x0d, 0xa8, 0x81, - 0x21, 0xbc, 0xd6, 0xa2, 0x6d, 0x25, 0x60, 0x5e, 0xd5, 0xd8, 0x23, 0x98, 0x4b, 0x71, 0x29, 0xae, 0x25, 0x24, 0x1f, - 0x3f, 0x6a, 0x47, 0x8f, 0xd0, 0xd0, 0x64, 0xe3, 0xd3, 0x8d, 0x3c, 0x6d, 0xcf, 0x3f, 0xa8, 0x9d, 0xd8, 0xf7, 0xcb, - 0xe8, 0x40, 0xc8, 0xee, 0xd8, 0xfd, 0xe8, 0x87, 0x6f, 0x06, 0xce, 0x23, 0xda, 0xa9, 0xe1, 0xe1, 0xd0, 0x9b, 0x5c, - 0x2c, 0x99, 0xe6, 0x90, 0x3b, 0xa0, 0x29, 0xe3, 0x63, 0x6b, 0x03, 0x71, 0xad, 0x17, 0x12, 0x36, 0xd3, 0x10, 0x53, - 0xf9, 0x51, 0x63, 0x04, 0xc4, 0x28, 0x36, 0xd8, 0xc0, 0xb4, 0xef, 0x05, 0x6a, 0x36, 0x3f, 0x87, 0x55, 0x4e, 0x6d, - 0x11, 0x33, 0x4b, 0x72, 0x59, 0xa4, 0x05, 0x01, 0x2b, 0x8c, 0x81, 0xb3, 0x50, 0x95, 0x54, 0x2f, 0x4a, 0x24, 0x3d, - 0xc7, 0x11, 0x70, 0x50, 0x2e, 0xed, 0x3f, 0x0f, 0x82, 0x25, 0xa1, 0xf7, 0xb3, 0x30, 0x4b, 0x9b, 0xa5, 0xb4, 0x8c, - 0x2c, 0xa8, 0x84, 0x1a, 0xa9, 0x3e, 0x2f, 0x25, 0x79, 0x9c, 0x14, 0xfc, 0xce, 0xd8, 0x6c, 0x46, 0xf2, 0xe5, 0xe2, - 0xdd, 0xf8, 0x4b, 0xc5, 0xdf, 0x42, 0x32, 0x7d, 0x28, 0x80, 0x05, 0x34, 0x49, 0xaf, 0x31, 0xe8, 0xbe, 0x5e, 0xdc, - 0x96, 0x22, 0xfc, 0x6d, 0x00, 0x5a, 0xa5, 0x79, 0x9d, 0x1d, 0x4f, 0x19, 0xaf, 0x9d, 0xfc, 0x65, 0x9a, 0xa4, 0x29, - 0x18, 0xae, 0x03, 0xf3, 0x0c, 0xdd, 0x94, 0xa0, 0x1f, 0x31, 0x57, 0x5f, 0xaa, 0x97, 0x5c, 0x3c, 0x4d, 0x91, 0xb3, - 0x5b, 0xba, 0xde, 0x73, 0x36, 0x52, 0x81, 0x59, 0xa9, 0x7c, 0xff, 0x95, 0x34, 0x2b, 0xd0, 0xea, 0x13, 0xf7, 0x94, - 0x81, 0xd0, 0xd5, 0xa4, 0x44, 0xba, 0xbb, 0x85, 0x9a, 0x5e, 0x5b, 0x4c, 0x60, 0x2a, 0x55, 0xa8, 0xbd, 0x63, 0xd6, - 0x45, 0xdc, 0xfb, 0x77, 0x74, 0xed, 0x76, 0xe7, 0x56, 0xba, 0x08, 0xd8, 0x63, 0xc2, 0x18, 0x88, 0x1e, 0xc3, 0xa9, - 0x6b, 0xae, 0xb7, 0x95, 0x35, 0xd7, 0x05, 0x7e, 0x96, 0x08, 0xb2, 0x71, 0xe5, 0x0e, 0xac, 0xcc, 0x45, 0x10, 0x30, - 0x7f, 0xdb, 0xf8, 0x85, 0x27, 0x44, 0x26, 0x82, 0xb7, 0xec, 0xf8, 0x18, 0x2f, 0xeb, 0x7d, 0x76, 0xfc, 0x0a, 0xb6, - 0x4e, 0xad, 0x14, 0x36, 0x61, 0x20, 0x95, 0x00, 0xeb, 0xbb, 0xe4, 0xe9, 0x70, 0x61, 0xb6, 0x8a, 0xc2, 0xf5, 0x41, - 0x26, 0xe0, 0xb1, 0xa0, 0x94, 0xd4, 0x25, 0x7c, 0x1f, 0xc7, 0x07, 0x5f, 0x27, 0x0d, 0x58, 0x04, 0x2d, 0x09, 0x38, - 0x5b, 0x8f, 0x34, 0xd8, 0xd4, 0x8b, 0x6a, 0xc7, 0xb7, 0x28, 0x9c, 0xb7, 0x8c, 0xf5, 0x30, 0x08, 0xf7, 0xb8, 0x6d, - 0x5f, 0xe1, 0x00, 0xbf, 0x79, 0x43, 0x3d, 0x3e, 0xf0, 0xe1, 0x35, 0xba, 0x28, 0x3a, 0x54, 0x4d, 0xf1, 0xa7, 0x05, - 0x69, 0x5e, 0x1a, 0xe6, 0x70, 0x6f, 0x25, 0x5d, 0xf0, 0x82, 0xf1, 0x30, 0x22, 0x1a, 0x9b, 0xf4, 0xa0, 0x00, 0x9e, - 0xeb, 0xde, 0xcd, 0xbd, 0x7b, 0x2d, 0x49, 0xb5, 0x88, 0x36, 0x69, 0xe2, 0xbb, 0xb5, 0x66, 0x92, 0x35, 0x20, 0x49, - 0x69, 0xaf, 0xd8, 0x91, 0x50, 0xe2, 0xf5, 0x6f, 0xd2, 0xb3, 0x00, 0xc5, 0x77, 0xb3, 0xeb, 0x31, 0xe8, 0x52, 0xcf, - 0xd2, 0x0b, 0x56, 0x4b, 0xa0, 0x9a, 0xa9, 0x6a, 0xb2, 0xe1, 0x14, 0xd2, 0xd9, 0xd7, 0xc9, 0x2e, 0x3a, 0xa7, 0xa4, - 0x10, 0x4a, 0x19, 0xf5, 0x4c, 0xaa, 0x88, 0xe8, 0x58, 0x06, 0x3f, 0x2b, 0xcc, 0xa5, 0x3b, 0x68, 0x04, 0x16, 0x63, - 0x44, 0x6e, 0xc2, 0x61, 0xdf, 0xb7, 0x29, 0x01, 0xa1, 0x7e, 0xd7, 0x4e, 0x9c, 0xf5, 0x06, 0x07, 0x76, 0xbe, 0xff, - 0x03, 0x5f, 0x2b, 0x9f, 0x80, 0xd0, 0xc3, 0x89, 0x66, 0x49, 0xf1, 0x17, 0x2f, 0x3d, 0xf1, 0x4e, 0xac, 0xa4, 0x6e, - 0x3f, 0xf1, 0x87, 0x7f, 0x91, 0x2a, 0x6a, 0x1c, 0xc4, 0xb9, 0x75, 0x7f, 0x25, 0x0d, 0x8d, 0x1c, 0xad, 0x89, 0x7b, - 0x00, 0xb0, 0xd0, 0x84, 0x8a, 0xb0, 0x9c, 0x91, 0x34, 0xfc, 0x4c, 0xfd, 0xc4, 0x92, 0x27, 0x14, 0x2b, 0x04, 0x48, - 0xe0, 0xfb, 0xf7, 0x12, 0x5c, 0xb9, 0xef, 0x01, 0xfc, 0xc3, 0x62, 0x04, 0x5a, 0xc5, 0x12, 0x0d, 0x75, 0xf3, 0x91, - 0xf5, 0xdd, 0xe1, 0xa2, 0xd5, 0xd9, 0x46, 0x08, 0x2a, 0x74, 0xd7, 0x21, 0x40, 0xd8, 0xa7, 0x11, 0x78, 0xf2, 0xaf, - 0x92, 0xb8, 0xad, 0x64, 0x33, 0x1d, 0x76, 0xd7, 0x79, 0x05, 0xde, 0x3d, 0xe8, 0x17, 0x2b, 0xe3, 0x5d, 0xe5, 0x91, - 0xf5, 0xf1, 0xbf, 0x9f, 0x94, 0x5d, 0x52, 0x1b, 0x64, 0xa5, 0x00, 0xc4, 0x6a, 0xa4, 0xd7, 0x38, 0xd3, 0x54, 0xeb, - 0xd0, 0x5a, 0x93, 0x6d, 0x21, 0x6c, 0x87, 0xb0, 0x82, 0x07, 0xab, 0x19, 0x51, 0x27, 0x34, 0xb6, 0xb8, 0x97, 0x1e, - 0xba, 0xeb, 0xdd, 0x8b, 0xa0, 0xf2, 0x98, 0x1d, 0x32, 0x0f, 0x80, 0xef, 0x71, 0x63, 0x37, 0xc8, 0xac, 0xc0, 0x05, - 0x1c, 0x04, 0x8c, 0x5d, 0xcf, 0x5d, 0x30, 0xe4, 0x7a, 0x16, 0x37, 0x1c, 0xf6, 0x44, 0x03, 0x65, 0xd7, 0x01, 0x4d, - 0xa1, 0x75, 0x52, 0x91, 0xc6, 0xd0, 0x03, 0xbf, 0xaf, 0xc0, 0x3a, 0xeb, 0x51, 0x6c, 0x67, 0xd6, 0xe5, 0xb9, 0x54, - 0x78, 0x5a, 0xbc, 0x5e, 0xdb, 0xf4, 0x31, 0x1d, 0x9a, 0xad, 0x09, 0xdf, 0xeb, 0x2e, 0x60, 0x21, 0xac, 0xd4, 0x25, - 0x49, 0x5e, 0xd6, 0x1f, 0x2f, 0x32, 0x9a, 0x85, 0xc7, 0x5c, 0xda, 0x66, 0xf6, 0xdf, 0xef, 0x5f, 0xa0, 0xb5, 0x42, - 0xe1, 0xd3, 0x51, 0x40, 0x66, 0x25, 0x6d, 0x08, 0xde, 0xea, 0x6f, 0x36, 0xdb, 0x2c, 0xee, 0x5f, 0xdf, 0x55, 0xec, - 0xf5, 0xaf, 0x6f, 0xba, 0x71, 0x93, 0x02, 0xaf, 0x51, 0x50, 0x74, 0x6e, 0xb6, 0x27, 0x38, 0x21, 0xce, 0xad, 0x4a, - 0x58, 0xe7, 0x76, 0xfc, 0xb4, 0xa6, 0x4f, 0xff, 0xe0, 0x1d, 0x77, 0x80, 0x47, 0x2d, 0x4e, 0x96, 0x76, 0x4c, 0x3d, - 0x72, 0x16, 0x75, 0x2f, 0x3d, 0xec, 0x03, 0x9b, 0xc2, 0xe6, 0x96, 0xee, 0x7b, 0xfb, 0xd9, 0x73, 0x69, 0x8e, 0xb7, - 0xfa, 0xab, 0xfc, 0x95, 0xfb, 0xc6, 0x2a, 0x3b, 0x34, 0xac, 0xdd, 0x54, 0x49, 0x31, 0x5b, 0x7a, 0x99, 0xf5, 0x47, - 0xe1, 0x72, 0x9f, 0x3e, 0x17, 0x1a, 0xc5, 0x3d, 0x4e, 0x18, 0xb9, 0x09, 0x21, 0x1f, 0x7e, 0x49, 0x6c, 0x23, 0xf3, - 0x8f, 0x5b, 0x95, 0x31, 0x08, 0x22, 0xcf, 0x8e, 0x5a, 0x2f, 0xcb, 0x9c, 0x53, 0xe2, 0x62, 0x9e, 0x93, 0xe0, 0x17, - 0x34, 0xc2, 0xd1, 0x2a, 0xfb, 0x4b, 0x1d, 0xb6, 0x3b, 0x2c, 0x2b, 0x07, 0x1a, 0x37, 0xfb, 0x04, 0x9c, 0x11, 0x5d, - 0xab, 0xb0, 0xa3, 0xdd, 0xc8, 0xec, 0x62, 0xc3, 0xe1, 0xae, 0xb0, 0x04, 0xfc, 0xfc, 0x05, 0x8c, 0x41, 0xb7, 0x62, - 0xba, 0x52, 0xfb, 0x81, 0x41, 0xaa, 0x6a, 0x0f, 0xa5, 0xb8, 0x87, 0xe6, 0xca, 0xb4, 0x6b, 0xbd, 0xa3, 0x8e, 0x30, - 0xa0, 0x0e, 0xba, 0x0b, 0x1e, 0xb3, 0x02, 0x5c, 0xd7, 0x6d, 0xeb, 0xb8, 0xcb, 0x1a, 0x3b, 0xf1, 0x31, 0x5d, 0xfb, - 0xe7, 0xe0, 0xa8, 0x64, 0x47, 0xb7, 0x15, 0x27, 0xcc, 0xb0, 0xf2, 0xff, 0x14, 0x2e, 0x4f, 0x6f, 0x15, 0x6c, 0x0f, - 0x0d, 0xf5, 0xf9, 0x14, 0x6c, 0x75, 0x03, 0x1b, 0x1c, 0x41, 0x9b, 0x77, 0x72, 0x5d, 0xd2, 0x29, 0x13, 0xb2, 0xa6, - 0xb7, 0xa4, 0x29, 0x13, 0x9c, 0xe4, 0x5c, 0xc1, 0x7c, 0x2e, 0xce, 0x4c, 0x3e, 0x34, 0xa8, 0x15, 0x24, 0x6b, 0xc7, - 0x5e, 0x47, 0x5f, 0x88, 0xec, 0x7a, 0xce, 0xac, 0x75, 0xbf, 0x16, 0x9a, 0xc4, 0x72, 0xa8, 0x03, 0xe7, 0xeb, 0xdc, - 0xfc, 0x09, 0x0c, 0x01, 0x8f, 0xbf, 0xca, 0x18, 0xe7, 0x26, 0xed, 0x39, 0x33, 0xcb, 0x54, 0x2f, 0x15, 0x62, 0xd0, - 0xb7, 0x61, 0x42, 0x15, 0x8d, 0x17, 0xb3, 0xab, 0x54, 0x04, 0x46, 0x3e, 0x2c, 0x28, 0x43, 0x97, 0xe7, 0x1c, 0xe7, - 0x0d, 0xe5, 0x59, 0x64, 0x66, 0x00, 0x6c, 0xb4, 0x5d, 0x46, 0x09, 0xf7, 0x2e, 0xd3, 0x90, 0xd5, 0xa3, 0xb2, 0x79, - 0x8f, 0x3a, 0xbd, 0x68, 0x60, 0x05, 0xae, 0x9c, 0xae, 0x38, 0x9c, 0x14, 0x6a, 0x82, 0xb8, 0xcf, 0xfb, 0x84, 0x58, - 0x36, 0x2e, 0x31, 0x31, 0xcd, 0xb2, 0x2e, 0xef, 0xee, 0x77, 0x11, 0x34, 0x72, 0x42, 0x83, 0x85, 0x77, 0xf8, 0x0b, - 0xd8, 0x1d, 0xaf, 0xac, 0xc9, 0x0d, 0x86, 0xdf, 0x08, 0x24, 0xd3, 0x11, 0x42, 0x19, 0x4b, 0xe0, 0x76, 0xfa, 0xe9, - 0x7e, 0x0b, 0x6e, 0x1d, 0x22, 0x3d, 0x70, 0xb4, 0x10, 0x6c, 0xad, 0xb0, 0x36, 0x95, 0xe3, 0x86, 0x43, 0x71, 0x13, - 0x1a, 0x91, 0x8a, 0x68, 0x75, 0x89, 0x9e, 0xec, 0x0e, 0x41, 0xc4, 0xce, 0x21, 0x4b, 0x10, 0x41, 0x93, 0xa3, 0xfb, - 0x11, 0x5a, 0x96, 0x58, 0x22, 0x0d, 0x89, 0x5c, 0x77, 0x9e, 0xa1, 0x8a, 0x11, 0xd8, 0x76, 0x4a, 0x5d, 0x5b, 0x43, - 0xc1, 0x65, 0x6f, 0xd0, 0x75, 0x33, 0xc1, 0x89, 0x56, 0x42, 0x99, 0xd1, 0x29, 0xb9, 0x8f, 0xe9, 0x53, 0x3f, 0xca, - 0xc9, 0x28, 0x55, 0x37, 0xcc, 0xf5, 0x05, 0x42, 0x11, 0x88, 0x53, 0x97, 0x97, 0x53, 0xb5, 0x25, 0x65, 0xae, 0xb4, - 0x04, 0x73, 0xa4, 0xff, 0xb4, 0x47, 0x0d, 0xd9, 0x7a, 0x37, 0xec, 0xb4, 0xe9, 0x61, 0xd6, 0x42, 0x11, 0x8e, 0xb9, - 0x62, 0xb0, 0xda, 0xed, 0x23, 0x72, 0x6d, 0x83, 0xe9, 0x33, 0xbd, 0x9c, 0x86, 0x74, 0xa7, 0x57, 0x43, 0x33, 0x87, - 0x15, 0x7e, 0x28, 0xca, 0x3d, 0xe6, 0xe3, 0x76, 0x7f, 0x34, 0xf1, 0x59, 0x65, 0xdd, 0x7c, 0xc8, 0x7f, 0x85, 0xf4, - 0x73, 0x59, 0x8a, 0x93, 0xab, 0x1e, 0x78, 0xdb, 0x17, 0x06, 0x42, 0x2a, 0x57, 0x37, 0x9b, 0x5c, 0xc2, 0xb4, 0x13, - 0xb1, 0x4e, 0x64, 0x56, 0xbe, 0x89, 0x6c, 0x36, 0xda, 0x57, 0x7d, 0xaf, 0x5d, 0xbd, 0x29, 0x68, 0x5c, 0xab, 0x5f, - 0x74, 0x4b, 0x67, 0x7f, 0x6f, 0x95, 0x36, 0x74, 0x23, 0x1b, 0xe3, 0x0e, 0x44, 0xdb, 0xa5, 0x15, 0x45, 0x94, 0x5f, - 0x72, 0x72, 0x2f, 0x9d, 0x1f, 0x13, 0x1f, 0x8d, 0xef, 0xd2, 0x3e, 0x87, 0x23, 0x7c, 0x98, 0xfc, 0x0f, 0x27, 0x59, - 0x7f, 0xf7, 0x63, 0xd1, 0x9e, 0xf3, 0xbb, 0xad, 0x3b, 0xd8, 0x72, 0x3b, 0x96, 0x6e, 0xce, 0x65, 0x03, 0x7d, 0x17, - 0xe7, 0xf8, 0x2f, 0xbb, 0x9d, 0x94, 0xf5, 0xc1, 0x32, 0x85, 0x1c, 0x87, 0x09, 0x16, 0xa5, 0x9e, 0x14, 0xfa, 0x90, - 0x37, 0x34, 0xcd, 0x6a, 0x17, 0x93, 0xd7, 0x01, 0x02, 0x3f, 0x16, 0x75, 0xa1, 0x03, 0x99, 0x2a, 0xdd, 0x1a, 0x3f, - 0x1c, 0xd0, 0x47, 0x18, 0x13, 0xaa, 0x89, 0xe4, 0xb7, 0x04, 0x79, 0x17, 0x0a, 0xec, 0x71, 0x13, 0xb0, 0xa6, 0xd1, - 0x41, 0xa6, 0xae, 0x04, 0x49, 0xe4, 0x40, 0x2f, 0x7a, 0x07, 0xa1, 0x9d, 0x73, 0xd1, 0xe8, 0xaf, 0x57, 0xef, 0x9e, - 0x90, 0x9b, 0xad, 0xb2, 0xb3, 0x98, 0xb5, 0x87, 0x81, 0x58, 0xed, 0x4b, 0xdd, 0xf5, 0xba, 0x10, 0x18, 0x36, 0xfe, - 0x9b, 0x8d, 0x39, 0xc0, 0x76, 0x5e, 0x16, 0x7b, 0x57, 0xc0, 0x2f, 0xc1, 0x7f, 0xb5, 0x25, 0x0a, 0x4b, 0x74, 0x66, - 0x46, 0xe9, 0xe0, 0xee, 0x5b, 0xa8, 0x69, 0x08, 0x7a, 0x25, 0x2f, 0x69, 0xc4, 0xad, 0x94, 0xcb, 0x5b, 0x59, 0x63, - 0xf5, 0xd1, 0x30, 0xe5, 0xf1, 0x6b, 0x2d, 0xa0, 0x0b, 0x74, 0x81, 0x18, 0x1a, 0x52, 0x5b, 0xd2, 0x30, 0x05, 0x92, - 0x46, 0x6e, 0x1f, 0xb4, 0xb0, 0xc2, 0x69, 0xda, 0x46, 0x10, 0x27, 0xff, 0x0e, 0xc2, 0x70, 0xce, 0xef, 0xb6, 0x16, - 0x82, 0x1b, 0x88, 0xb4, 0x41, 0x56, 0x4e, 0x85, 0x5d, 0x01, 0xcd, 0xb7, 0x01, 0xa3, 0x15, 0x26, 0x19, 0x32, 0x49, - 0xf7, 0xe3, 0x3f, 0xf2, 0x0e, 0xbf, 0x3a, 0x73, 0x1e, 0x0a, 0x46, 0x0c, 0xb4, 0x43, 0x23, 0x1f, 0x14, 0xdc, 0x4e, - 0x96, 0xbd, 0xa0, 0x2e, 0x89, 0x59, 0xca, 0xe0, 0x14, 0x37, 0x85, 0xbe, 0x7c, 0x1c, 0x0e, 0x2a, 0x78, 0x63, 0x2c, - 0x0e, 0x74, 0x96, 0x82, 0x95, 0x0f, 0x7a, 0x96, 0x4e, 0x04, 0x98, 0x02, 0x9d, 0xc6, 0xd1, 0x6e, 0xc6, 0x5d, 0x29, - 0xdd, 0x0b, 0x50, 0x38, 0x2f, 0xa4, 0xd9, 0x08, 0x0a, 0x60, 0x37, 0x46, 0x4b, 0xf2, 0x8f, 0xbc, 0xc3, 0xf7, 0x33, - 0x71, 0x95, 0x5b, 0xe2, 0xd7, 0xca, 0x47, 0x0c, 0x64, 0x53, 0x7f, 0xb0, 0x7e, 0x4d, 0xcd, 0xd5, 0xee, 0x24, 0x1d, - 0x8e, 0xc3, 0x00, 0x38, 0xe6, 0x28, 0x96, 0x83, 0x58, 0x56, 0x20, 0xc9, 0x39, 0xb1, 0x5c, 0x3f, 0xe6, 0xcf, 0x49, - 0x62, 0x5f, 0xb5, 0x14, 0x57, 0xb8, 0x16, 0x4f, 0x8b, 0xe4, 0xc4, 0x1b, 0xfc, 0x2a, 0xfa, 0xef, 0xf6, 0x52, 0xc6, - 0x30, 0xf7, 0x53, 0x8c, 0x70, 0x43, 0xde, 0x32, 0x9f, 0x26, 0x81, 0x72, 0x56, 0x97, 0x83, 0x32, 0x9f, 0x5d, 0x2c, - 0x59, 0xe7, 0xd9, 0xf8, 0x4e, 0xce, 0x5b, 0xd7, 0xbd, 0xb0, 0x3f, 0x7a, 0x28, 0xdf, 0x1f, 0x2b, 0xff, 0x1e, 0x88, - 0x73, 0x28, 0x86, 0x11, 0x2b, 0x36, 0xea, 0xed, 0x49, 0xbe, 0x96, 0x0d, 0x74, 0xa4, 0x88, 0xf4, 0x95, 0x25, 0x3d, - 0x9f, 0x18, 0xd6, 0x45, 0x34, 0xf7, 0x6f, 0x30, 0x5d, 0x74, 0xf0, 0x0e, 0x13, 0x0c, 0xde, 0x2c, 0x4d, 0x5b, 0xdc, - 0x8f, 0x6d, 0x6a, 0x54, 0x28, 0x9c, 0x19, 0xd4, 0xb6, 0xc6, 0x0b, 0xec, 0x29, 0x5c, 0xfc, 0xc4, 0x39, 0x69, 0x5e, - 0x61, 0xb8, 0xb1, 0xa3, 0x95, 0x68, 0xa4, 0xb5, 0x1c, 0x1d, 0x74, 0xc8, 0xe4, 0xbd, 0x9c, 0x14, 0xb3, 0x48, 0x82, - 0x70, 0x5e, 0x2b, 0x1f, 0x4d, 0xbd, 0xb7, 0xb5, 0x6f, 0x30, 0xee, 0x02, 0x19, 0xb8, 0x4c, 0x16, 0x5a, 0x9a, 0x78, - 0xd9, 0x6d, 0xbe, 0x6d, 0xc3, 0x32, 0xe6, 0x56, 0x94, 0x55, 0x8c, 0x31, 0x89, 0x29, 0xda, 0xc5, 0xb2, 0xf1, 0x08, - 0xa6, 0x2e, 0x91, 0x24, 0x44, 0x96, 0xd1, 0x12, 0x8d, 0x6d, 0x50, 0xfa, 0x22, 0x66, 0x61, 0x30, 0xf2, 0x3f, 0xb3, - 0xf8, 0xcb, 0xb5, 0x7e, 0x2d, 0xcd, 0x14, 0xdd, 0x29, 0xf7, 0x6a, 0x6c, 0xdb, 0xe5, 0xf6, 0x6b, 0x3b, 0x44, 0x79, - 0xfd, 0x0a, 0x9e, 0x02, 0x4d, 0x8a, 0xe0, 0x10, 0x11, 0x68, 0x95, 0xf5, 0x45, 0x2d, 0x6d, 0x4b, 0x47, 0x7e, 0x4a, - 0x36, 0x11, 0xce, 0xf9, 0x21, 0xc4, 0xb3, 0x0a, 0xa2, 0x2e, 0x4b, 0x2f, 0x22, 0x1b, 0xb4, 0xb6, 0x3e, 0xd2, 0xa9, - 0x54, 0xc3, 0x07, 0x86, 0x22, 0xf2, 0x3d, 0xbc, 0x3a, 0x09, 0x5d, 0xda, 0x5a, 0x45, 0x49, 0xbc, 0x44, 0x3a, 0x7e, - 0x22, 0xab, 0x0e, 0x51, 0x24, 0xa8, 0x16, 0x0c, 0x6a, 0x05, 0xb8, 0x1c, 0x54, 0xb5, 0x37, 0x5b, 0x91, 0x08, 0x82, - 0x68, 0xb0, 0x8a, 0x0f, 0xd4, 0xed, 0x28, 0xc8, 0x24, 0xd2, 0x13, 0x63, 0x93, 0xf1, 0xe6, 0x85, 0xe4, 0x5e, 0x91, - 0x46, 0xa0, 0x4f, 0x9c, 0xd4, 0xb3, 0x71, 0x92, 0xf5, 0xfe, 0xa6, 0x8f, 0x1c, 0x1c, 0x37, 0x58, 0x4a, 0x8f, 0x62, - 0x07, 0xc7, 0x7a, 0x4e, 0x64, 0x2b, 0x29, 0xeb, 0x1c, 0x4a, 0x15, 0x6f, 0xc6, 0x28, 0x72, 0x2c, 0x63, 0x32, 0x70, - 0x36, 0x07, 0xd1, 0xb6, 0xa3, 0xf7, 0x94, 0xd8, 0xc8, 0x15, 0xf5, 0x02, 0xa5, 0x4e, 0xfc, 0xef, 0x13, 0xb4, 0xdf, - 0x6e, 0x4f, 0x08, 0xbd, 0x9d, 0x45, 0xb7, 0xf0, 0x45, 0xc7, 0x32, 0x6e, 0x0e, 0xdd, 0x49, 0x88, 0x63, 0x8a, 0x16, - 0x78, 0xc7, 0x0a, 0xc5, 0xb9, 0x68, 0x48, 0xec, 0x72, 0x6c, 0xd4, 0xfc, 0x54, 0x4d, 0x5d, 0xd6, 0x0a, 0xe9, 0x5d, - 0xfe, 0x1b, 0xf3, 0xbb, 0xfc, 0xf9, 0xf1, 0xa9, 0xca, 0xf5, 0x3a, 0x35, 0xc4, 0xe2, 0x0d, 0x2d, 0x13, 0x8d, 0x15, - 0x5e, 0x54, 0xc3, 0x1e, 0x25, 0x5b, 0x8b, 0xf4, 0x62, 0x65, 0xd5, 0x4c, 0xe4, 0x21, 0x09, 0x42, 0xd4, 0xe8, 0x84, - 0xba, 0x5b, 0xb8, 0xd0, 0xf8, 0x1d, 0x46, 0x26, 0x92, 0x01, 0x25, 0xdb, 0xea, 0x96, 0xfa, 0x51, 0x4b, 0x4f, 0x3d, - 0x9f, 0xcc, 0x06, 0x57, 0x4d, 0xa3, 0x71, 0x3a, 0xa6, 0xc6, 0x89, 0xb7, 0x8f, 0x66, 0x7a, 0x8d, 0x06, 0x0b, 0xbc, - 0xb0, 0xbb, 0xfe, 0x0d, 0x74, 0xc4, 0x2d, 0x34, 0x4a, 0x6c, 0x48, 0xd6, 0x18, 0x93, 0x96, 0x30, 0x6d, 0x29, 0xb3, - 0x96, 0x71, 0xd0, 0x06, 0x1c, 0xb6, 0x21, 0x47, 0x6d, 0xc4, 0x71, 0x1b, 0xf3, 0x4b, 0x8b, 0xca, 0xaf, 0x33, 0x7a, - 0x4e, 0x66, 0x0c, 0x9c, 0xce, 0x18, 0xb9, 0xd3, 0x62, 0xe2, 0xee, 0x8c, 0x99, 0x5c, 0xb4, 0xba, 0xa8, 0x8a, 0x6a, - 0x51, 0x95, 0x95, 0xb2, 0x6f, 0x58, 0x92, 0x1b, 0xff, 0xa2, 0x64, 0xd4, 0x87, 0x98, 0x72, 0xd9, 0xea, 0xfe, 0xde, - 0xd3, 0xc9, 0x74, 0xe7, 0x25, 0x4c, 0xbc, 0x89, 0x22, 0x55, 0xe7, 0x96, 0xa9, 0x01, 0xf3, 0xe4, 0x95, 0xf9, 0x0d, - 0x09, 0x0d, 0x2c, 0x29, 0xb6, 0xdb, 0x1f, 0xcf, 0xfe, 0xed, 0x89, 0xaf, 0xaa, 0xee, 0x1b, 0x6f, 0x97, 0x9c, 0x9c, - 0xfb, 0xe0, 0xb9, 0x03, 0x8d, 0xa7, 0xe7, 0x0d, 0x63, 0xf7, 0x7e, 0x65, 0xd1, 0x2d, 0xca, 0x3c, 0x78, 0xd2, 0xf1, - 0x17, 0xe1, 0x5a, 0x32, 0xe9, 0xef, 0xd0, 0x21, 0x59, 0x6a, 0xe4, 0x46, 0xfd, 0xcd, 0x35, 0x68, 0xb4, 0xd3, 0xcc, - 0xd3, 0x8a, 0xb1, 0x7f, 0xa8, 0xd9, 0x90, 0xea, 0xcb, 0xcc, 0x72, 0xbe, 0x1c, 0x2d, 0x2a, 0xe3, 0x9c, 0x56, 0xb8, - 0xb1, 0xe2, 0x98, 0x67, 0xc7, 0x16, 0xf3, 0x49, 0x93, 0x47, 0xd5, 0xf0, 0x98, 0x4b, 0x41, 0x46, 0x62, 0xa1, 0xf7, - 0xfc, 0xd0, 0x1f, 0xb7, 0x26, 0xc3, 0x27, 0x6b, 0xbd, 0xbd, 0x79, 0xf3, 0xe4, 0x8d, 0xa6, 0x09, 0x15, 0xe7, 0x92, - 0xa4, 0x92, 0xce, 0x2d, 0x96, 0x64, 0xde, 0x80, 0x8d, 0x9a, 0x1b, 0xe7, 0x86, 0x42, 0xde, 0x08, 0x8d, 0xdc, 0x4e, - 0x99, 0x84, 0xf4, 0xfe, 0xfa, 0xf7, 0xfa, 0x9b, 0xd5, 0xe3, 0x7c, 0xfa, 0x03, 0xc3, 0x66, 0x02, 0x00, 0x46, 0x4b, - 0xdf, 0xfb, 0xcf, 0xeb, 0x37, 0xd5, 0xd3, 0xca, 0xaf, 0xeb, 0xe7, 0x55, 0xa9, 0x3d, 0x87, 0xd0, 0xc1, 0x1c, 0x5f, - 0xe6, 0x9d, 0x27, 0x1b, 0xb7, 0x2b, 0xb8, 0xdb, 0x0c, 0xdd, 0xb3, 0xd8, 0xc4, 0xc6, 0x64, 0xba, 0xf8, 0xfc, 0xd3, - 0x55, 0x1f, 0x4d, 0x91, 0xda, 0xee, 0xcf, 0xf5, 0x38, 0x1f, 0xf7, 0xf8, 0x3b, 0xf1, 0xcd, 0x8e, 0x38, 0x8b, 0xc2, - 0xa9, 0xfc, 0xe7, 0xa1, 0xf4, 0xb8, 0xfc, 0xc4, 0x45, 0xad, 0xb0, 0x66, 0xf0, 0x2c, 0xbf, 0xf7, 0xb7, 0x11, 0x0f, - 0x3c, 0x35, 0xae, 0xfb, 0xf9, 0x33, 0x96, 0xff, 0x45, 0xc5, 0x2a, 0x0f, 0x8f, 0x6f, 0xf1, 0xdd, 0xac, 0xd6, 0x24, - 0xd2, 0x34, 0x08, 0xc2, 0x8a, 0xfc, 0x50, 0xfd, 0xb0, 0x3c, 0x27, 0x89, 0xae, 0xfd, 0xa7, 0xc7, 0x33, 0x08, 0x1d, - 0x83, 0x78, 0x75, 0x4d, 0x14, 0x0f, 0x3f, 0xa0, 0x7c, 0x3c, 0x04, 0x73, 0x08, 0xf4, 0x5f, 0xdf, 0x8d, 0x09, 0xc7, - 0xce, 0x11, 0x82, 0x08, 0x6b, 0xbd, 0x9f, 0x9f, 0xf9, 0x40, 0x81, 0x0f, 0xa3, 0xff, 0x66, 0x52, 0x4c, 0x01, 0x72, - 0xea, 0x44, 0x4c, 0xff, 0x66, 0xa0, 0x64, 0x05, 0x3a, 0xa8, 0xeb, 0x40, 0xf1, 0xa0, 0x06, 0xdd, 0x4d, 0x8e, 0xe1, - 0x76, 0xce, 0x32, 0x75, 0x76, 0xa9, 0xd3, 0xf3, 0x93, 0x26, 0x64, 0xa7, 0x97, 0x6a, 0x52, 0xc0, 0x65, 0xf9, 0x75, - 0x74, 0xf7, 0x05, 0x64, 0x2c, 0xd0, 0x8d, 0x87, 0xb6, 0x89, 0x6f, 0x0e, 0x72, 0x79, 0xde, 0x98, 0xd7, 0x88, 0x37, - 0xc6, 0x3f, 0x3b, 0x20, 0x1c, 0x72, 0x4f, 0x72, 0xcc, 0x7d, 0xc4, 0x73, 0xe8, 0xfe, 0x94, 0x74, 0x3f, 0x6c, 0xf6, - 0x4e, 0x8b, 0xff, 0xb1, 0xca, 0xd1, 0x85, 0x51, 0xf2, 0xbc, 0xde, 0xe7, 0xa1, 0xb1, 0xb3, 0x32, 0xb5, 0x7a, 0x26, - 0x6d, 0x08, 0x0d, 0x76, 0xfc, 0xbc, 0x39, 0xe5, 0xfe, 0x4c, 0x6c, 0x94, 0x18, 0xcd, 0x40, 0xec, 0x24, 0xd3, 0xa0, - 0x51, 0x44, 0xe0, 0xff, 0x20, 0x06, 0xb5, 0x8b, 0x35, 0x42, 0x21, 0xac, 0xe5, 0x53, 0x68, 0x79, 0x35, 0x8f, 0xde, - 0x48, 0x57, 0xe2, 0xc4, 0x72, 0xa6, 0x39, 0xe6, 0x5c, 0xc5, 0xcf, 0xc9, 0x8e, 0x15, 0xbc, 0xc8, 0xf4, 0x16, 0x8e, - 0xe7, 0x47, 0xcc, 0xf8, 0xdc, 0x43, 0x77, 0x5c, 0x1c, 0x59, 0xb3, 0x80, 0x36, 0xd5, 0x6e, 0x80, 0x6a, 0x90, 0xc0, - 0xb5, 0x08, 0xfd, 0x5e, 0x25, 0x38, 0xd2, 0x9c, 0x97, 0xb5, 0x18, 0xf5, 0x44, 0x1e, 0x39, 0x1b, 0x5c, 0x8c, 0x7a, - 0x52, 0x79, 0x01, 0xc1, 0xa7, 0xa0, 0xdb, 0x06, 0xd5, 0x64, 0xd9, 0xbf, 0x24, 0xcd, 0x61, 0xa0, 0xd7, 0x58, 0x80, - 0x59, 0xf3, 0x8f, 0x52, 0xff, 0xfb, 0x4d, 0xc9, 0xbd, 0x21, 0xfe, 0x03, 0x20, 0xe6, 0xea, 0xa6, 0xcd, 0xb3, 0x51, - 0x95, 0x0b, 0xed, 0x12, 0x4e, 0x2f, 0x55, 0xbc, 0x86, 0x4d, 0x85, 0x72, 0x4a, 0x02, 0x51, 0x27, 0x9c, 0x2d, 0x1d, - 0x21, 0x3c, 0x4f, 0xd6, 0x0e, 0x4d, 0xe8, 0x3d, 0x60, 0xeb, 0x5d, 0x4b, 0xfb, 0x28, 0xe7, 0xf2, 0xec, 0xeb, 0xfc, - 0x64, 0x5f, 0x4e, 0x32, 0x19, 0xff, 0x89, 0x9a, 0xc6, 0x2b, 0xd4, 0x27, 0x15, 0xbd, 0x7e, 0x3e, 0x56, 0x94, 0xa4, - 0xb1, 0x1d, 0xf1, 0xab, 0xad, 0xc0, 0xff, 0x4a, 0x5f, 0x8b, 0x58, 0x75, 0xfa, 0x46, 0x8f, 0xa3, 0x2e, 0xe7, 0xd2, - 0xbf, 0xbc, 0xb1, 0x64, 0x6d, 0x59, 0x02, 0x13, 0xdb, 0x3d, 0xdf, 0x96, 0xc1, 0xac, 0xb5, 0x8a, 0x4d, 0xde, 0x6d, - 0x45, 0xe9, 0x6b, 0x75, 0x6d, 0xd2, 0x6e, 0x3c, 0x80, 0xcb, 0x63, 0xb5, 0x52, 0x33, 0x92, 0x64, 0xa6, 0x77, 0xbe, - 0x7b, 0xce, 0xa5, 0x52, 0xa1, 0xc4, 0x1d, 0x32, 0xbe, 0x3b, 0x30, 0x76, 0x7f, 0xae, 0xa1, 0x1a, 0x9d, 0x1b, 0xe1, - 0x69, 0xe9, 0x10, 0x02, 0x4f, 0x1c, 0xf7, 0xc7, 0xbe, 0x6c, 0x1b, 0x9d, 0xd1, 0xe9, 0x1c, 0xad, 0x8b, 0xc6, 0x3f, - 0xba, 0x55, 0x34, 0x9b, 0xbd, 0xad, 0x2c, 0x36, 0x8f, 0xcd, 0xf2, 0x28, 0x73, 0xf1, 0x3f, 0xf1, 0xa7, 0xe1, 0x54, - 0xe7, 0x40, 0xb6, 0x74, 0x35, 0x65, 0x12, 0xc8, 0x11, 0x5e, 0xcf, 0xf5, 0x0e, 0x48, 0x3e, 0x77, 0x4b, 0xa0, 0x0c, - 0x45, 0x56, 0x33, 0x2a, 0xae, 0x8a, 0x15, 0x99, 0x67, 0xd6, 0x24, 0x78, 0xa1, 0x77, 0xa0, 0x39, 0x8b, 0x35, 0x6b, - 0x24, 0x71, 0xde, 0x43, 0xca, 0x8e, 0x7c, 0xd8, 0xc8, 0x1c, 0xc2, 0xc3, 0x26, 0x7e, 0xd6, 0x63, 0x02, 0x85, 0x13, - 0x03, 0xe8, 0xed, 0x2f, 0xc0, 0xea, 0xcf, 0x14, 0xeb, 0x83, 0xec, 0x74, 0xd6, 0xae, 0xe9, 0x0f, 0x97, 0x79, 0x9f, - 0xd8, 0xd3, 0xf5, 0xdb, 0xb0, 0x76, 0x4c, 0x2d, 0xed, 0x3c, 0xc0, 0xce, 0x6b, 0xf8, 0xae, 0x43, 0xb5, 0xaf, 0x11, - 0xba, 0x1f, 0xb9, 0xc9, 0x63, 0x0a, 0x1d, 0x7b, 0xfc, 0x27, 0xc0, 0x43, 0x0a, 0x5d, 0x05, 0xee, 0x53, 0x58, 0x3f, - 0x0e, 0xc0, 0x5d, 0x0a, 0xd5, 0x13, 0xb8, 0x4d, 0x61, 0x44, 0xfc, 0x5e, 0x79, 0x93, 0x82, 0x7d, 0x14, 0xee, 0xf2, - 0xbe, 0xac, 0xe8, 0xcd, 0xbb, 0x3e, 0xde, 0x3e, 0x2a, 0x57, 0xde, 0xd3, 0xfb, 0x7a, 0xbc, 0x5b, 0xbd, 0x09, 0x4c, - 0x9f, 0xa8, 0xc4, 0x9b, 0x02, 0xcf, 0x9f, 0xb0, 0xe2, 0x5d, 0x1e, 0xaf, 0x9b, 0x77, 0x71, 0xa5, 0x7b, 0x75, 0xff, - 0x3f, 0xb4, 0x35, 0xe6, 0xed, 0x1c, 0xdf, 0x6d, 0x2b, 0xe7, 0x59, 0xde, 0xee, 0x9d, 0xfd, 0xeb, 0x59, 0x3c, 0x80, - 0xd3, 0x14, 0x9a, 0x0a, 0x9c, 0xa4, 0x50, 0x56, 0xe0, 0x38, 0x85, 0x53, 0x6d, 0x9a, 0x16, 0xd8, 0x4d, 0x41, 0x37, - 0xe0, 0x28, 0x85, 0xcd, 0x37, 0xb0, 0x97, 0x42, 0xf1, 0xbc, 0xb5, 0xc0, 0x7e, 0x0a, 0x7a, 0x05, 0x0e, 0x04, 0xf2, - 0x2a, 0xef, 0xf0, 0x9f, 0x8d, 0xe3, 0x37, 0x18, 0x7b, 0xa8, 0xf6, 0x0c, 0x37, 0xfa, 0x1b, 0x18, 0xce, 0x5d, 0x8e, - 0x5d, 0x7d, 0x3a, 0x03, 0x97, 0xcc, 0xbf, 0x85, 0xd6, 0x9b, 0x44, 0xf8, 0x63, 0x40, 0x12, 0xab, 0xd3, 0x7d, 0x05, - 0xbc, 0xda, 0x1f, 0x7a, 0x3e, 0x67, 0x61, 0xee, 0xc2, 0x2b, 0x06, 0xac, 0x62, 0x51, 0x9e, 0xfa, 0xbf, 0x0c, 0x21, - 0xbb, 0x6d, 0x48, 0x32, 0x23, 0xdb, 0x0f, 0x8b, 0x13, 0xa3, 0x3e, 0x29, 0x4d, 0x6c, 0x55, 0x3a, 0x43, 0x45, 0x93, - 0x9b, 0xe0, 0x51, 0x52, 0xaa, 0xc0, 0xdc, 0x45, 0xf7, 0x44, 0xf8, 0x66, 0xbd, 0xc3, 0xf5, 0x53, 0x52, 0x21, 0x4a, - 0x86, 0xf4, 0xeb, 0xbf, 0x9c, 0x4d, 0x4f, 0xa9, 0xf5, 0xe4, 0x45, 0xfc, 0xc9, 0xf7, 0xd5, 0xb5, 0x29, 0x30, 0x79, - 0x66, 0x72, 0x99, 0xa7, 0x6d, 0xf5, 0x1e, 0xdb, 0x21, 0x59, 0xbb, 0x3d, 0x05, 0x2f, 0x89, 0xf5, 0x6f, 0x72, 0xcd, - 0x02, 0x7b, 0x4f, 0x30, 0xa7, 0x61, 0x89, 0x12, 0x25, 0x46, 0x62, 0xbc, 0xea, 0x41, 0x61, 0xcc, 0x70, 0x8d, 0xbf, - 0x4a, 0xed, 0xdf, 0xce, 0xa6, 0x3a, 0x01, 0x0b, 0x39, 0xd7, 0x61, 0x78, 0xe0, 0x24, 0xa4, 0x1c, 0xb2, 0x48, 0x68, - 0xa3, 0x99, 0x4e, 0xaa, 0xa7, 0x5a, 0x3d, 0xd8, 0x8d, 0x96, 0x27, 0xa2, 0x77, 0xed, 0xa8, 0x9c, 0x89, 0xa0, 0xbb, - 0x81, 0xd3, 0x1c, 0xfa, 0x63, 0x5a, 0xf2, 0x32, 0x80, 0x14, 0xbe, 0xf1, 0x76, 0x6a, 0xec, 0x5f, 0xe2, 0x3b, 0xb6, - 0xa2, 0x5c, 0xe1, 0x4f, 0xf0, 0x1b, 0xb6, 0x36, 0x9b, 0xbf, 0x61, 0x75, 0x79, 0xb8, 0x15, 0xb0, 0x02, 0x30, 0x7f, - 0x67, 0xcd, 0xf6, 0xe9, 0x08, 0x27, 0x93, 0xb7, 0x82, 0xb2, 0xd2, 0x80, 0x85, 0xf1, 0x36, 0x01, 0xbf, 0x15, 0x06, - 0x37, 0xdb, 0x9b, 0x33, 0x31, 0x77, 0x22, 0x5a, 0x5c, 0x06, 0x76, 0x0f, 0x6e, 0xd4, 0xc2, 0x4a, 0xdd, 0x1c, 0xf6, - 0xf7, 0xea, 0x06, 0x25, 0x2e, 0x82, 0xb0, 0x55, 0x75, 0x40, 0xd6, 0xb8, 0x8e, 0x22, 0x9f, 0x87, 0x7d, 0xb3, 0xdd, - 0x5b, 0xa9, 0x25, 0x5b, 0xde, 0xeb, 0xb5, 0xea, 0x27, 0x55, 0x4d, 0x9f, 0xce, 0xb1, 0xec, 0x34, 0x66, 0xc9, 0x4f, - 0x5b, 0x7b, 0x78, 0xc5, 0x15, 0x82, 0x68, 0xd5, 0x14, 0x33, 0xf3, 0x41, 0x1d, 0x34, 0x61, 0xae, 0xc2, 0xe3, 0x98, - 0x60, 0x80, 0xd9, 0x79, 0x78, 0x11, 0x42, 0x07, 0xc1, 0x76, 0xce, 0xc1, 0x56, 0xf1, 0xb4, 0x69, 0x2d, 0x0b, 0x68, - 0x1a, 0x8d, 0xfd, 0x28, 0x6b, 0xfc, 0x41, 0x36, 0x6a, 0x9d, 0x5a, 0xda, 0x1e, 0x47, 0x4f, 0x31, 0x7f, 0x1b, 0x50, - 0x11, 0xd0, 0x66, 0x90, 0xb3, 0x41, 0xa3, 0x72, 0xf1, 0xdf, 0x09, 0xa4, 0x33, 0xed, 0xdf, 0x70, 0x36, 0xa6, 0x35, - 0x68, 0xf6, 0x8d, 0xf6, 0x43, 0x4c, 0xdf, 0x17, 0x6c, 0x11, 0xbd, 0xe4, 0xb8, 0xe5, 0x29, 0x1a, 0xb8, 0x4a, 0xa6, - 0x4b, 0x70, 0x84, 0x2e, 0xca, 0xbd, 0xf7, 0x49, 0xf8, 0x93, 0x00, 0xd6, 0x8f, 0x3e, 0xa6, 0x53, 0xb6, 0x0e, 0x0e, - 0x95, 0xb1, 0x47, 0xcd, 0x32, 0x56, 0xf0, 0x4a, 0x7a, 0x23, 0x33, 0x00, 0x02, 0x01, 0xcf, 0x65, 0x87, 0x3f, 0xd5, - 0x07, 0xb9, 0x2a, 0xc0, 0x6a, 0xe9, 0x66, 0x3b, 0x1d, 0x6a, 0xcd, 0x8f, 0x79, 0x5b, 0xda, 0xd1, 0xa3, 0x77, 0xb4, - 0xbd, 0xac, 0xc1, 0x05, 0x39, 0x72, 0x09, 0x3a, 0x4b, 0x65, 0x54, 0xe1, 0x3a, 0x34, 0xe0, 0x7c, 0x29, 0xd4, 0x28, - 0x5a, 0xf4, 0x9b, 0x1b, 0x7d, 0xcb, 0x5e, 0x1e, 0x41, 0x63, 0xce, 0xfb, 0x4d, 0x36, 0x57, 0x2d, 0x10, 0x84, 0x39, - 0xb6, 0xa5, 0xf7, 0x1f, 0x13, 0x9c, 0x6f, 0x5f, 0xb0, 0xdd, 0x72, 0xcb, 0x03, 0xb6, 0xfe, 0x89, 0x47, 0x15, 0x8a, - 0x9d, 0x78, 0x56, 0x56, 0x67, 0x57, 0x6d, 0xad, 0x31, 0xa4, 0xff, 0x6a, 0xbd, 0x6b, 0x6b, 0x5a, 0x7b, 0x07, 0x3c, - 0x08, 0x84, 0x74, 0xb8, 0x1c, 0x48, 0xc4, 0x7a, 0x4b, 0x87, 0x87, 0x12, 0xe1, 0x80, 0xec, 0x01, 0xb3, 0x73, 0x1b, - 0xda, 0xb3, 0x87, 0x07, 0xb8, 0x97, 0x39, 0xd0, 0x80, 0x5c, 0x1e, 0x1e, 0xe5, 0xd9, 0xfd, 0x01, 0x09, 0xf0, 0x16, - 0x0a, 0x58, 0x6a, 0x80, 0x75, 0x47, 0x4c, 0xb8, 0x7c, 0x20, 0xcb, 0xce, 0x8b, 0x40, 0xc7, 0x95, 0xd3, 0xc0, 0x46, - 0x0f, 0x1e, 0x42, 0xf1, 0x64, 0x73, 0xac, 0x71, 0x6e, 0x4d, 0x7a, 0xe1, 0x08, 0xc9, 0x98, 0xb9, 0x47, 0x8c, 0x1c, - 0x52, 0x1f, 0x26, 0xa6, 0x8b, 0x49, 0x7a, 0x5c, 0xb1, 0x2e, 0x86, 0xc0, 0x8e, 0x60, 0xe9, 0x0b, 0xc4, 0xde, 0x64, - 0x2c, 0x61, 0x82, 0x58, 0x47, 0x83, 0x18, 0xc2, 0xc6, 0x1d, 0x96, 0xa6, 0x6e, 0x02, 0x16, 0x81, 0xeb, 0x45, 0x90, - 0x4b, 0x61, 0x8d, 0x67, 0xe1, 0xdd, 0x3b, 0x9f, 0xc6, 0xdb, 0xfd, 0xaf, 0xf8, 0xd0, 0xa8, 0x36, 0x5a, 0x94, 0xbe, - 0xee, 0x00, 0xc6, 0xec, 0x57, 0xe0, 0x33, 0x05, 0x42, 0x9c, 0xfb, 0xfb, 0x57, 0x58, 0xe6, 0xf0, 0xda, 0x06, 0x19, - 0x8c, 0xcc, 0xbe, 0x1c, 0xd8, 0xa4, 0x96, 0x48, 0xe6, 0x2b, 0x86, 0xb7, 0x80, 0x55, 0xe9, 0x4b, 0xa2, 0x36, 0xcc, - 0xdd, 0xf8, 0xae, 0x0e, 0x1a, 0x6d, 0xe5, 0x47, 0x68, 0x1c, 0x4c, 0xde, 0xea, 0xc4, 0x40, 0x86, 0x78, 0x12, 0xab, - 0xbe, 0xb8, 0x68, 0x6b, 0x90, 0x34, 0x3d, 0x06, 0x14, 0x8a, 0x5d, 0xbc, 0xbd, 0x60, 0xbb, 0xa4, 0x06, 0xb0, 0xb1, - 0x31, 0x69, 0x98, 0x1d, 0xb5, 0x26, 0xa6, 0xed, 0x3d, 0x3e, 0x4a, 0x9b, 0x23, 0x77, 0x0f, 0x6b, 0x2a, 0xdb, 0x9d, - 0x27, 0x4a, 0x1c, 0x73, 0x70, 0x86, 0x5f, 0x1f, 0x98, 0x80, 0x7c, 0x3f, 0x3e, 0x11, 0x87, 0x83, 0xaf, 0xc7, 0x09, - 0x94, 0x88, 0x42, 0x2d, 0xc0, 0x03, 0x11, 0x10, 0xc7, 0xee, 0x08, 0x20, 0xeb, 0x7d, 0xbc, 0x94, 0xad, 0x56, 0xbd, - 0x9c, 0x5e, 0x6c, 0x34, 0x01, 0x42, 0x7c, 0xca, 0x21, 0x48, 0xc9, 0xe2, 0xc1, 0x01, 0xc4, 0x0c, 0x54, 0x30, 0x65, - 0x37, 0xbc, 0x51, 0x18, 0x0b, 0x2d, 0x51, 0x9d, 0xc0, 0xc5, 0x11, 0xa8, 0xe9, 0x27, 0x3f, 0x64, 0x03, 0x18, 0x4a, - 0xa9, 0x09, 0x92, 0xae, 0x1c, 0x10, 0xa0, 0x4b, 0x44, 0x42, 0xfc, 0x72, 0x31, 0x40, 0x80, 0x0d, 0xd6, 0x9b, 0xe0, - 0xa6, 0x49, 0x8d, 0xe1, 0x70, 0xff, 0x94, 0x17, 0xad, 0xef, 0x53, 0x20, 0x1b, 0x13, 0x68, 0x5e, 0xfc, 0xe8, 0x48, - 0x2d, 0x74, 0x19, 0x1a, 0x2e, 0x29, 0xd6, 0xb2, 0x1f, 0xa6, 0xc5, 0x96, 0xa9, 0x41, 0x88, 0xa0, 0x1f, 0xfc, 0xfa, - 0x32, 0xa3, 0x91, 0x5c, 0x7c, 0x10, 0x7e, 0x08, 0xee, 0x05, 0x78, 0x1c, 0x19, 0x24, 0x29, 0x05, 0x9c, 0x46, 0x95, - 0x08, 0xf7, 0xb8, 0x0b, 0x39, 0x82, 0xe8, 0xf7, 0xb8, 0x4d, 0x8d, 0x16, 0x45, 0xaa, 0x70, 0xd3, 0xef, 0xdb, 0xdb, - 0x45, 0x7d, 0x0d, 0x0f, 0xf0, 0x23, 0x20, 0xbe, 0x26, 0x6e, 0x8c, 0x57, 0x21, 0x9f, 0x92, 0x01, 0x61, 0x02, 0x6a, - 0x42, 0x19, 0x73, 0x0e, 0x37, 0xe6, 0x8a, 0x2c, 0x14, 0x92, 0x41, 0xc3, 0x6d, 0x5d, 0xc2, 0x98, 0x14, 0xc7, 0x89, - 0x40, 0xfc, 0x9e, 0x12, 0x4b, 0x9e, 0x5a, 0x00, 0xf0, 0xad, 0xa2, 0xb9, 0x75, 0xd0, 0x26, 0x13, 0xc4, 0xc9, 0xbe, - 0xc7, 0xf2, 0xdd, 0x66, 0x7f, 0xc6, 0x5f, 0x48, 0x3a, 0x4e, 0x12, 0xf1, 0xae, 0xa7, 0x29, 0xc2, 0x3e, 0x87, 0xaa, - 0x2e, 0x38, 0x04, 0x58, 0xfc, 0x10, 0x16, 0x0c, 0xb2, 0xc1, 0x51, 0xac, 0x07, 0x82, 0xa0, 0x98, 0x84, 0xb6, 0xb3, - 0x10, 0xb7, 0xc1, 0xea, 0x18, 0x95, 0x35, 0x12, 0x24, 0x93, 0x35, 0x13, 0xa2, 0xa6, 0x7e, 0xa2, 0x37, 0x3c, 0xa9, - 0x1d, 0xcf, 0xdd, 0xc4, 0xf4, 0x1a, 0xf9, 0xb1, 0xba, 0x34, 0xd6, 0xe7, 0xbd, 0x85, 0xe4, 0x63, 0xc0, 0x27, 0x89, - 0x0d, 0xd1, 0xfc, 0xc3, 0xb0, 0x6c, 0x18, 0x27, 0x25, 0x1b, 0x4b, 0x35, 0x3a, 0xeb, 0xcc, 0xe3, 0x3d, 0x3f, 0xbf, - 0x5a, 0x0c, 0x49, 0x89, 0xef, 0xe1, 0x0b, 0x59, 0xdb, 0xd1, 0xfa, 0x53, 0xd6, 0x03, 0xa2, 0x3a, 0x13, 0xe0, 0x3d, - 0x56, 0xb3, 0x09, 0x8d, 0x82, 0x0c, 0xe2, 0x7a, 0x6b, 0xb4, 0xd7, 0x9b, 0x6c, 0xfb, 0x25, 0xb7, 0x47, 0xf5, 0x2b, - 0x88, 0xbc, 0xc2, 0xec, 0x7a, 0x3f, 0x6a, 0x87, 0x00, 0x1e, 0x2f, 0xb8, 0x5b, 0x03, 0xf7, 0x5c, 0xc5, 0x82, 0xe4, - 0xcd, 0x54, 0xe8, 0x9c, 0x73, 0x3f, 0xa4, 0xce, 0xd1, 0xbb, 0x71, 0xe3, 0xff, 0x34, 0x57, 0x96, 0x65, 0x96, 0xc2, - 0x64, 0x0c, 0x09, 0x95, 0x08, 0xcf, 0xdd, 0x16, 0xd6, 0x45, 0x79, 0x28, 0x8d, 0xae, 0x31, 0xa8, 0x47, 0x9d, 0x55, - 0x9a, 0x46, 0xb2, 0xf8, 0x1e, 0xed, 0x68, 0xbd, 0x30, 0x15, 0xa0, 0x59, 0x4a, 0xa9, 0x65, 0xd9, 0x3e, 0x97, 0x4b, - 0xa1, 0xef, 0xb4, 0x15, 0xfe, 0xfc, 0x0c, 0xf7, 0xdc, 0xa4, 0xdb, 0x0d, 0xf6, 0x1b, 0xdb, 0xc1, 0x8d, 0xc1, 0x34, - 0x7f, 0xfd, 0xbc, 0x19, 0x66, 0x83, 0x19, 0xcc, 0xc5, 0xb3, 0xbc, 0xc7, 0xb1, 0x2a, 0x6e, 0x5a, 0x1d, 0xf8, 0x27, - 0x37, 0x29, 0x36, 0x3f, 0x60, 0x86, 0x56, 0x7b, 0x97, 0x2b, 0x12, 0xce, 0xd7, 0xbc, 0x80, 0xbe, 0xc4, 0x2c, 0x26, - 0xcc, 0xe7, 0x7c, 0x1a, 0x10, 0x40, 0x55, 0x91, 0x3f, 0x4a, 0x29, 0x58, 0xd9, 0x12, 0xb9, 0x81, 0x0f, 0x54, 0x7b, - 0x40, 0xed, 0x64, 0xce, 0x57, 0x76, 0x48, 0x5d, 0x85, 0x5d, 0x81, 0x91, 0x9d, 0x93, 0x6b, 0x3b, 0x6e, 0xfb, 0x4f, - 0x97, 0x62, 0xbf, 0x58, 0x76, 0xd2, 0x73, 0xf4, 0x49, 0x2c, 0x9a, 0x85, 0x8e, 0x1e, 0xc9, 0xe9, 0x6b, 0xee, 0xef, - 0x8a, 0x48, 0x9e, 0xbf, 0xc1, 0xe5, 0x67, 0x29, 0x24, 0xf8, 0x47, 0x29, 0x6d, 0xb7, 0x23, 0xe6, 0x13, 0x5e, 0x43, - 0x69, 0xce, 0x42, 0xcb, 0x35, 0xd8, 0x00, 0x48, 0x18, 0x65, 0x34, 0x2a, 0xab, 0x6d, 0xfc, 0x75, 0x42, 0xa3, 0xfc, - 0x4b, 0x89, 0x05, 0x35, 0x98, 0x63, 0x44, 0xc5, 0x6b, 0x22, 0x84, 0xe7, 0xfe, 0x32, 0x17, 0xc7, 0x62, 0xd1, 0xe6, - 0xfe, 0x36, 0x67, 0x0b, 0x46, 0x65, 0xb6, 0x5a, 0x5f, 0x89, 0x1e, 0xda, 0x5d, 0x5d, 0xbc, 0x4c, 0xd7, 0xe6, 0xae, - 0x0f, 0x00, 0xe5, 0xa4, 0x0f, 0x96, 0x2e, 0xbc, 0x5e, 0x9f, 0x21, 0xc3, 0x06, 0xaf, 0x0b, 0xae, 0x22, 0xed, 0x07, - 0x48, 0xcd, 0x72, 0x6e, 0x6b, 0x57, 0x89, 0x9a, 0xec, 0x1b, 0x15, 0xa0, 0xef, 0x65, 0xce, 0x63, 0xa6, 0xd1, 0x47, - 0xad, 0x43, 0x8d, 0x18, 0x24, 0x42, 0xab, 0x88, 0xf8, 0xb3, 0xc9, 0x38, 0x0a, 0x45, 0xbc, 0x31, 0x61, 0xac, 0x50, - 0x20, 0x67, 0xf7, 0xdf, 0x3a, 0xbf, 0xba, 0xb2, 0x9f, 0x4e, 0x9a, 0xb2, 0x2e, 0x77, 0xed, 0x2e, 0xf8, 0xf4, 0xea, - 0x25, 0x26, 0x18, 0x17, 0x9f, 0xea, 0x95, 0xf7, 0x96, 0xbf, 0xea, 0x79, 0x7a, 0x77, 0x1d, 0x36, 0xf7, 0x11, 0xaa, - 0xc2, 0xaa, 0xb8, 0x63, 0xe6, 0x49, 0xd3, 0xfa, 0xcb, 0xf7, 0xa2, 0xf6, 0x8b, 0x1e, 0x1b, 0xe8, 0x65, 0x44, 0x71, - 0x3f, 0xd5, 0x5e, 0x3f, 0x28, 0x24, 0x8e, 0x5f, 0x27, 0x44, 0xc5, 0x55, 0xcb, 0xc2, 0xa7, 0x13, 0xac, 0x22, 0xab, - 0xe9, 0x9c, 0x44, 0x35, 0x10, 0xd9, 0x4c, 0x83, 0x00, 0x49, 0xe5, 0x29, 0xed, 0x21, 0xac, 0xdd, 0xd0, 0x2f, 0xef, - 0xc1, 0x08, 0x85, 0x0b, 0xd2, 0x4f, 0x32, 0xa7, 0xd4, 0xe6, 0x74, 0x46, 0x56, 0xe3, 0x80, 0x80, 0xdf, 0xff, 0xf7, - 0xcd, 0x57, 0xc2, 0xd4, 0x3e, 0x85, 0xf1, 0x59, 0xd1, 0x36, 0x41, 0x94, 0xdf, 0x43, 0x96, 0xb5, 0x17, 0xb9, 0xc8, - 0x2a, 0xd5, 0x65, 0xf2, 0x60, 0xcd, 0x6f, 0x62, 0x6c, 0xcb, 0xc3, 0x8d, 0x35, 0x5a, 0xc8, 0xe9, 0x36, 0x9a, 0x41, - 0xa1, 0x62, 0x4c, 0x7a, 0xf5, 0xe7, 0x15, 0x9b, 0xc7, 0x91, 0xc7, 0xaf, 0xf2, 0x29, 0x90, 0xc0, 0x6d, 0x62, 0x05, - 0x47, 0xcd, 0x4e, 0x45, 0x4d, 0x1f, 0x9e, 0xf3, 0xe5, 0xf1, 0x05, 0x50, 0x6d, 0xa8, 0x71, 0xc6, 0xbc, 0x56, 0x94, - 0x35, 0xa9, 0x23, 0x19, 0xcf, 0xbb, 0x0c, 0xb4, 0x9c, 0xa8, 0xe8, 0xbd, 0x5a, 0x52, 0xf4, 0x29, 0x5b, 0xbb, 0x0c, - 0xdf, 0x9a, 0x4c, 0xc8, 0x04, 0x05, 0x47, 0x20, 0xd2, 0xce, 0xc5, 0x0a, 0xed, 0xbf, 0x79, 0x52, 0xdf, 0x9b, 0xf1, - 0x49, 0x62, 0x44, 0x49, 0xc9, 0x77, 0x1f, 0x35, 0x5a, 0x08, 0xa2, 0xce, 0x86, 0x9b, 0xa4, 0x3f, 0xf3, 0xaa, 0x1c, - 0x13, 0x58, 0xe3, 0x48, 0x0c, 0xae, 0x2a, 0xfa, 0x09, 0x25, 0x5c, 0x21, 0xdd, 0x4e, 0x49, 0xc2, 0xd9, 0x23, 0xb4, - 0xa7, 0x79, 0xf5, 0xfd, 0x54, 0x95, 0x1f, 0x48, 0x04, 0x44, 0xb5, 0x19, 0x3a, 0x31, 0xf7, 0xf4, 0x75, 0xed, 0xd2, - 0x13, 0xfe, 0xfb, 0x52, 0xb9, 0x90, 0x3e, 0x8f, 0x17, 0xf3, 0xff, 0x7c, 0x33, 0xae, 0x23, 0x6d, 0xa3, 0xbe, 0xed, - 0x9a, 0x16, 0xed, 0xc8, 0xb2, 0x3e, 0x45, 0x0a, 0x0a, 0x43, 0x08, 0x25, 0x3f, 0x42, 0x58, 0x89, 0x6e, 0x8a, 0xae, - 0x22, 0x83, 0x35, 0x67, 0xc0, 0x0a, 0xaf, 0xea, 0xc0, 0xad, 0x22, 0x9f, 0xec, 0xbc, 0x62, 0x8b, 0xba, 0x4e, 0xa5, - 0x9b, 0x38, 0xe3, 0x77, 0x62, 0x82, 0x54, 0x6d, 0xdf, 0xf3, 0xc7, 0x3a, 0xa9, 0x39, 0xf9, 0x93, 0x8f, 0xf9, 0xd8, - 0x9d, 0xf4, 0xd7, 0x9d, 0xaf, 0xdb, 0x84, 0xb0, 0xe3, 0xa5, 0x4d, 0x4b, 0xb1, 0xc6, 0xdb, 0x60, 0x28, 0x5f, 0x89, - 0xa2, 0x4d, 0x7c, 0x8c, 0xc2, 0xbf, 0x29, 0xb4, 0x4f, 0x92, 0xb6, 0x59, 0x03, 0x45, 0x17, 0x6b, 0x7e, 0xfc, 0x6b, - 0x42, 0x83, 0x50, 0x0c, 0xd8, 0xd4, 0xf7, 0x32, 0x06, 0xed, 0xd3, 0x16, 0x0d, 0x1f, 0x7b, 0xf1, 0x01, 0x23, 0x4e, - 0x57, 0x3f, 0x06, 0xa8, 0x27, 0x8c, 0x63, 0x37, 0x4d, 0x2e, 0x92, 0x86, 0x51, 0xf1, 0x6a, 0x1c, 0xad, 0xdf, 0xdf, - 0xa7, 0xb1, 0x18, 0xfa, 0x6d, 0x06, 0x1f, 0x73, 0x73, 0x6e, 0xde, 0x1d, 0x93, 0x73, 0x72, 0x5e, 0x9e, 0x01, 0x39, - 0x74, 0x25, 0x78, 0x9c, 0x5c, 0x46, 0x69, 0x03, 0x6d, 0x3f, 0x6b, 0xec, 0x70, 0x28, 0xcb, 0xfb, 0xaa, 0x7a, 0x61, - 0xbf, 0xdb, 0xa4, 0xe0, 0x66, 0xcb, 0x37, 0xc5, 0xcf, 0xf2, 0xdf, 0xc0, 0x94, 0x30, 0x5f, 0x84, 0x24, 0xdf, 0x55, - 0xf9, 0xf5, 0xb1, 0x1f, 0x02, 0x78, 0x65, 0x94, 0x98, 0xb5, 0xab, 0xc2, 0xbc, 0x44, 0x3c, 0xc9, 0x9f, 0x2a, 0x42, - 0x10, 0x9d, 0x38, 0x64, 0xc9, 0xaf, 0x47, 0xc2, 0x66, 0x0c, 0x63, 0x73, 0x73, 0x91, 0x29, 0x7d, 0x4b, 0x93, 0x04, - 0x95, 0xe4, 0xa4, 0x02, 0x46, 0x2a, 0xc3, 0x19, 0xfe, 0x34, 0x97, 0x25, 0x7a, 0x8e, 0xd0, 0x7d, 0x8d, 0x6a, 0xdf, - 0x69, 0xdc, 0x26, 0xd7, 0x6a, 0x6e, 0xdc, 0x66, 0xfb, 0xee, 0xc9, 0x31, 0xf4, 0x38, 0xfb, 0x64, 0x42, 0xad, 0x3a, - 0xe1, 0xdc, 0xcd, 0xc3, 0xcb, 0xb8, 0x27, 0x7d, 0x43, 0x5b, 0x63, 0xe1, 0x6a, 0x0e, 0xf3, 0x23, 0xfd, 0x2e, 0xc6, - 0x90, 0xa7, 0xae, 0xb8, 0xdd, 0xa7, 0x71, 0xb4, 0x5e, 0x71, 0x0b, 0x32, 0x94, 0x5a, 0xf1, 0x01, 0x1b, 0xe5, 0x07, - 0x60, 0x8d, 0x0f, 0x01, 0xf9, 0xf6, 0x05, 0x17, 0xa8, 0x35, 0xcc, 0x2c, 0x2f, 0x3e, 0xbf, 0x98, 0x43, 0x38, 0xb9, - 0xa7, 0x4d, 0x0a, 0xb7, 0xdc, 0xa4, 0xe5, 0x6d, 0xd6, 0x4f, 0xd1, 0xf6, 0x90, 0xcb, 0x9e, 0xae, 0x3f, 0x61, 0x24, - 0x72, 0xe2, 0x84, 0xfb, 0xba, 0xb6, 0x58, 0xdf, 0x0f, 0xa3, 0xe2, 0xb4, 0x91, 0xeb, 0x91, 0x81, 0xab, 0x77, 0xf4, - 0x6e, 0x48, 0x3c, 0x55, 0xf3, 0x6b, 0xc5, 0xaa, 0x6e, 0x82, 0x7f, 0x1e, 0xab, 0x21, 0xed, 0x54, 0x5c, 0xec, 0xaf, - 0xce, 0x4e, 0xb2, 0xfc, 0x53, 0x0b, 0x48, 0x2f, 0x38, 0x76, 0x4d, 0x19, 0x6e, 0x21, 0xce, 0x77, 0x73, 0x3c, 0xbd, - 0xd4, 0xd2, 0x38, 0xa7, 0x88, 0x22, 0xa4, 0xb7, 0x82, 0xbf, 0xc7, 0xf0, 0xf5, 0x8c, 0xee, 0xa0, 0x11, 0x49, 0xce, - 0xbf, 0x3c, 0xa3, 0x59, 0xf9, 0xb5, 0xdd, 0x0a, 0x73, 0x07, 0x49, 0x5b, 0xc9, 0xe1, 0x0c, 0xd6, 0x86, 0x84, 0x0b, - 0xc9, 0x96, 0xa6, 0x4b, 0xaa, 0x3a, 0x60, 0x23, 0x7d, 0xd2, 0x27, 0x67, 0x1b, 0x9e, 0x88, 0x06, 0xc1, 0xf9, 0xf3, - 0x90, 0x0e, 0x96, 0xe3, 0xa5, 0x0d, 0x7d, 0x0a, 0x38, 0x5b, 0x36, 0x3e, 0xe8, 0xd4, 0x9a, 0x74, 0x3e, 0x52, 0x97, - 0x98, 0xe2, 0x27, 0xb6, 0xd2, 0x7d, 0x62, 0xbb, 0xd6, 0xa8, 0x7e, 0x5d, 0xdf, 0x6d, 0xea, 0x14, 0x99, 0x3a, 0x6d, - 0xca, 0x2d, 0xe4, 0xaa, 0xce, 0x77, 0x97, 0x1e, 0x6b, 0x19, 0xe4, 0xea, 0x97, 0x65, 0xbf, 0x49, 0xd0, 0xcd, 0xeb, - 0x7f, 0xca, 0xb5, 0xb3, 0xe5, 0x5a, 0xf9, 0x0c, 0x9a, 0xac, 0xae, 0xb5, 0xe9, 0xe6, 0x06, 0x56, 0x56, 0x48, 0x11, - 0x8a, 0x44, 0x48, 0x5b, 0x2d, 0xcf, 0x63, 0xf9, 0x12, 0x4e, 0xfc, 0xfd, 0x51, 0x30, 0x91, 0xa3, 0xa2, 0xb3, 0x50, - 0x37, 0xdb, 0x20, 0xa3, 0xe7, 0xe9, 0x01, 0xf7, 0x2a, 0xca, 0xd9, 0xc6, 0xed, 0x06, 0x51, 0x32, 0x7b, 0x5e, 0xc8, - 0x02, 0xf5, 0x58, 0xae, 0x5b, 0x61, 0xd3, 0xdd, 0x7c, 0xb6, 0x0b, 0x6a, 0x99, 0x2c, 0x8c, 0x9e, 0xb4, 0xc1, 0x42, - 0x22, 0x96, 0xdc, 0x02, 0x2b, 0xb2, 0x65, 0x90, 0xd5, 0xc5, 0x2b, 0xa0, 0x11, 0x6a, 0x5b, 0xf4, 0xc2, 0xe2, 0x0d, - 0x0a, 0x4c, 0x6e, 0x70, 0x16, 0x9d, 0x56, 0xbc, 0x35, 0x26, 0xfe, 0xd7, 0xee, 0x19, 0x37, 0x7d, 0xb8, 0x25, 0x5d, - 0x44, 0xb9, 0x71, 0x79, 0x5b, 0x53, 0xdf, 0xe6, 0x18, 0xe8, 0x7a, 0xcb, 0xab, 0x6a, 0xe4, 0x12, 0xb0, 0xc7, 0x65, - 0x68, 0x24, 0xdd, 0xfc, 0xbc, 0x06, 0x33, 0xa7, 0x33, 0x27, 0x90, 0xf0, 0xa2, 0x91, 0x51, 0x30, 0xf1, 0xf3, 0x85, - 0x68, 0x47, 0x35, 0x63, 0xa0, 0xc0, 0x07, 0xa4, 0xc1, 0x6d, 0x8e, 0x4b, 0xb3, 0x15, 0x9b, 0x45, 0x68, 0x4d, 0x99, - 0x63, 0xc2, 0xab, 0x6e, 0xc6, 0x51, 0x35, 0x06, 0xbb, 0x78, 0x18, 0x6d, 0xc6, 0x5b, 0xdb, 0x24, 0x01, 0x55, 0xd2, - 0x02, 0x38, 0xfd, 0x7c, 0x25, 0x52, 0xa3, 0xe4, 0x52, 0x40, 0xf0, 0x97, 0x53, 0xa0, 0x2d, 0xb7, 0x86, 0x6e, 0x62, - 0x10, 0x6e, 0x3a, 0x57, 0x70, 0xcb, 0x38, 0xf9, 0xc5, 0x70, 0x5a, 0x55, 0xf1, 0x82, 0x94, 0x89, 0x95, 0x1d, 0xf3, - 0x83, 0xad, 0x79, 0x9b, 0x6d, 0x97, 0xef, 0x03, 0xf9, 0x7d, 0xbf, 0xef, 0x5b, 0x6a, 0x5c, 0x9f, 0xef, 0xf2, 0x82, - 0x1d, 0x37, 0x91, 0xd6, 0x4a, 0x14, 0x59, 0x04, 0x8d, 0x76, 0x39, 0xb9, 0x80, 0xf7, 0xa0, 0xe6, 0xee, 0xce, 0xa8, - 0x8d, 0xac, 0xf0, 0x5e, 0xc1, 0xf6, 0x67, 0x99, 0xaf, 0x10, 0xe8, 0xe0, 0x01, 0x0c, 0xf5, 0x89, 0x22, 0x68, 0x24, - 0x42, 0x02, 0x58, 0x3f, 0x6f, 0x08, 0x30, 0x75, 0x8d, 0x92, 0x4d, 0xf0, 0x96, 0xf6, 0x47, 0x37, 0x1e, 0xb2, 0x74, - 0x19, 0xf1, 0x84, 0x48, 0x51, 0x78, 0x00, 0xed, 0xed, 0x23, 0x84, 0x19, 0xf3, 0x54, 0x8d, 0xf8, 0xf5, 0xd4, 0x9e, - 0x5e, 0x18, 0x67, 0xfb, 0x53, 0xfa, 0xff, 0xb9, 0x48, 0x55, 0x9e, 0x8f, 0xe9, 0xcc, 0x79, 0xfb, 0x43, 0xf1, 0xc1, - 0x93, 0x1b, 0x76, 0x0f, 0xe0, 0xd0, 0xb8, 0x9c, 0xac, 0x51, 0xd1, 0xfa, 0x4b, 0xc7, 0xa1, 0x89, 0xe7, 0xcf, 0xb2, - 0xaa, 0xf8, 0xd1, 0x7f, 0xaa, 0xe6, 0x3a, 0x9d, 0xb9, 0x88, 0xb3, 0x2b, 0xb9, 0x15, 0x94, 0x4e, 0xc0, 0x1f, 0xc6, - 0x6b, 0x8d, 0xb9, 0xc4, 0xbd, 0xe1, 0x66, 0xd7, 0xa3, 0xfa, 0xe3, 0x26, 0x03, 0xe3, 0xfd, 0x5b, 0xc9, 0x06, 0xe4, - 0x79, 0x5a, 0x8c, 0x39, 0x7a, 0xe1, 0x9d, 0x2e, 0x90, 0x81, 0xb0, 0x7b, 0xb6, 0xf1, 0x98, 0x28, 0x34, 0x7a, 0x89, - 0x14, 0x2e, 0xd8, 0x3b, 0xb6, 0x03, 0xb2, 0xdb, 0xcf, 0x77, 0xdb, 0x3a, 0xa0, 0xb4, 0x9b, 0xf0, 0xfa, 0x65, 0xcb, - 0x2a, 0x6f, 0x6e, 0xf9, 0x56, 0x99, 0x54, 0xdc, 0xd7, 0x36, 0xc4, 0x7a, 0xe4, 0x14, 0x3b, 0x80, 0x80, 0xc8, 0x62, - 0x09, 0x8d, 0x3b, 0x37, 0x17, 0x1e, 0x1f, 0x4f, 0x9e, 0x95, 0x8c, 0x3a, 0x57, 0xaf, 0xdf, 0xca, 0xba, 0x8a, 0x29, - 0xdb, 0x4b, 0xcf, 0x09, 0x7d, 0x3b, 0x05, 0xee, 0x89, 0x65, 0x34, 0x80, 0x56, 0x7a, 0xcc, 0x19, 0xb1, 0xc6, 0x89, - 0x47, 0xb4, 0x94, 0xc8, 0x3a, 0x94, 0x6f, 0x37, 0x62, 0x4b, 0x08, 0xd5, 0x2e, 0xb5, 0xd7, 0x8d, 0x06, 0x62, 0xfb, - 0x06, 0x10, 0x06, 0x90, 0xcc, 0x62, 0xcd, 0xf5, 0xa5, 0x90, 0x1e, 0xd7, 0x40, 0xa1, 0x76, 0xdf, 0x9c, 0xed, 0x35, - 0x29, 0x9f, 0x4b, 0x33, 0x07, 0xb4, 0xd4, 0xad, 0xf1, 0x7b, 0x60, 0x59, 0xac, 0xb7, 0x0e, 0xfb, 0x7e, 0x9c, 0x31, - 0xed, 0xc2, 0x68, 0x71, 0x6a, 0x3c, 0x41, 0x3d, 0xa8, 0x6b, 0x14, 0x84, 0x72, 0xb0, 0x95, 0xa4, 0x1d, 0xe0, 0x74, - 0x8a, 0xd9, 0x14, 0x80, 0xdb, 0xed, 0x48, 0x9e, 0x30, 0x49, 0x81, 0xe3, 0xb9, 0x86, 0x78, 0x12, 0x57, 0xf4, 0x97, - 0x40, 0xa1, 0x0a, 0x09, 0xc6, 0x8d, 0xf3, 0x48, 0xa8, 0x7f, 0x3f, 0x20, 0x92, 0xcb, 0x65, 0x92, 0x6c, 0x97, 0x2d, - 0x0d, 0x45, 0xad, 0xc0, 0x0f, 0xe8, 0xdb, 0xb8, 0x3d, 0xa4, 0xef, 0xc2, 0x87, 0xc3, 0xda, 0xda, 0x57, 0x1e, 0x61, - 0x16, 0x8e, 0x3d, 0x81, 0xdd, 0x19, 0x66, 0xc5, 0xfd, 0x9f, 0xcf, 0xf1, 0xeb, 0x0f, 0xef, 0x19, 0xd7, 0x1d, 0xfd, - 0x24, 0xf6, 0x7e, 0xd8, 0xd1, 0x71, 0xb3, 0x49, 0x71, 0x31, 0xb3, 0xdf, 0xb4, 0x91, 0xff, 0x75, 0xf1, 0x6c, 0xe2, - 0x9e, 0xde, 0xf1, 0x3b, 0x3d, 0x13, 0x7b, 0x39, 0x51, 0x55, 0xfe, 0xb8, 0x3f, 0x37, 0xf2, 0xfa, 0xac, 0xbf, 0xea, - 0x73, 0xd6, 0xe3, 0xda, 0xc3, 0x78, 0xfb, 0x8c, 0xeb, 0xa9, 0xe5, 0xf5, 0x61, 0xbf, 0x39, 0x1d, 0xf8, 0x3b, 0x0b, - 0x8a, 0xf7, 0xca, 0x15, 0xd3, 0x0a, 0x6d, 0xfc, 0x80, 0x72, 0x7a, 0xf0, 0x47, 0x6c, 0x88, 0x32, 0xb6, 0xc1, 0xf5, - 0x27, 0xb8, 0xce, 0x5a, 0xe1, 0x6c, 0xe0, 0x42, 0x94, 0x1e, 0xe9, 0xd7, 0x39, 0xbd, 0xd2, 0xf1, 0x30, 0x7e, 0xaa, - 0x6b, 0xe1, 0x58, 0xaa, 0x70, 0x66, 0x27, 0xe5, 0x78, 0xbb, 0x8d, 0xf5, 0x0c, 0xbe, 0x37, 0x0b, 0x4a, 0xaf, 0x32, - 0xd8, 0xc8, 0x15, 0xf3, 0x3e, 0x0e, 0x6a, 0xdb, 0x07, 0x1f, 0x8d, 0xf1, 0x6d, 0x9f, 0x8e, 0x2f, 0xda, 0xa4, 0x58, - 0xd9, 0xe3, 0x19, 0x03, 0x19, 0x1c, 0x7e, 0xc1, 0x88, 0x1d, 0xfa, 0xbf, 0x31, 0x55, 0xe9, 0x45, 0x54, 0x1d, 0x5b, - 0x99, 0x02, 0xd4, 0xc3, 0x36, 0x8e, 0x9f, 0xa8, 0x8d, 0xdd, 0x6a, 0x24, 0xe0, 0xf0, 0xda, 0xfd, 0x7a, 0x55, 0x10, - 0xc6, 0xf9, 0x7d, 0x80, 0xf7, 0x80, 0xca, 0xc2, 0x3e, 0x24, 0xee, 0xd0, 0x3e, 0x26, 0xe2, 0xfe, 0x5f, 0xfa, 0x1a, - 0x12, 0xd6, 0xab, 0xfd, 0x80, 0xaa, 0x86, 0x9f, 0x30, 0xc3, 0x9b, 0x2f, 0x97, 0xe3, 0x42, 0x2e, 0x42, 0x9e, 0xc7, - 0xca, 0xda, 0x59, 0xe7, 0xe6, 0x52, 0x16, 0x01, 0x97, 0x05, 0x58, 0xb1, 0xd5, 0xf7, 0x3f, 0xd6, 0x79, 0x4f, 0x03, - 0x88, 0xaf, 0x4b, 0x21, 0xc5, 0xd2, 0x8c, 0x4b, 0x2a, 0xa3, 0x4d, 0x45, 0xf4, 0x6f, 0x64, 0x48, 0x93, 0x39, 0x96, - 0x33, 0x67, 0xe9, 0x03, 0x09, 0x3e, 0x59, 0x30, 0xb0, 0x78, 0x0e, 0xaa, 0x95, 0xa4, 0x99, 0x10, 0x31, 0x91, 0x44, - 0x03, 0xd4, 0x3c, 0xa9, 0x2a, 0x28, 0x3c, 0xd5, 0x70, 0x6d, 0xf5, 0xc2, 0x29, 0x00, 0x24, 0x07, 0x44, 0x45, 0x2d, - 0x3c, 0xa5, 0xc5, 0x4b, 0x4d, 0xc7, 0x6f, 0xbb, 0xa5, 0x1d, 0x7b, 0x7b, 0x8f, 0xfc, 0x45, 0x4c, 0x4e, 0x44, 0xc5, - 0xd6, 0x26, 0x22, 0x81, 0xb7, 0x00, 0xb2, 0x39, 0x56, 0x8c, 0x03, 0x3a, 0x7e, 0xa3, 0x69, 0xb8, 0x8d, 0x1c, 0x95, - 0xf0, 0x0e, 0x46, 0xda, 0x62, 0x2e, 0x98, 0x6e, 0xa4, 0xd5, 0x10, 0x57, 0xaf, 0xd0, 0xaa, 0xb4, 0xd9, 0xc6, 0xc0, - 0x99, 0x6b, 0x31, 0x8a, 0xd7, 0x51, 0x31, 0x27, 0x64, 0x81, 0xf3, 0x70, 0x6e, 0x86, 0xb3, 0xb1, 0x06, 0xa5, 0x71, - 0xd4, 0x15, 0xa7, 0xf3, 0x6d, 0xb6, 0xee, 0xda, 0x77, 0x32, 0xcf, 0xb3, 0xc8, 0x26, 0xed, 0x66, 0x17, 0xd4, 0x38, - 0x57, 0x8c, 0xf9, 0x88, 0x1d, 0x9f, 0x71, 0xe9, 0xb9, 0x85, 0x61, 0x12, 0x1a, 0x8c, 0x9d, 0xd6, 0x2f, 0xd0, 0xf3, - 0x19, 0xdb, 0x15, 0x2e, 0xa0, 0x3c, 0x31, 0x16, 0xad, 0x20, 0x58, 0xbe, 0xad, 0x7f, 0x29, 0xf2, 0x30, 0x1b, 0x77, - 0x78, 0x60, 0x37, 0x4d, 0x3a, 0xf3, 0x7e, 0x78, 0x1e, 0x57, 0xd7, 0xb1, 0x9b, 0x65, 0x4f, 0x4c, 0x6e, 0x04, 0x54, - 0xac, 0x62, 0x9b, 0x97, 0x15, 0xf7, 0x50, 0x91, 0x4f, 0x5a, 0x28, 0xad, 0x52, 0xaa, 0x5e, 0x69, 0x4f, 0x46, 0x48, - 0x73, 0xb5, 0x9e, 0x81, 0x71, 0x21, 0xf0, 0x3e, 0x49, 0x2f, 0xbb, 0x6b, 0xcb, 0xdb, 0x74, 0x80, 0xb4, 0xf6, 0x36, - 0x7e, 0x79, 0x1d, 0x20, 0xce, 0xd5, 0xec, 0xa9, 0xe8, 0xf1, 0x8b, 0x20, 0x54, 0x9e, 0x4d, 0xd3, 0x0a, 0xea, 0xe2, - 0x8e, 0xae, 0xce, 0x61, 0x0d, 0x76, 0x9f, 0x7f, 0x16, 0xb6, 0x52, 0xf9, 0x7f, 0x7e, 0x93, 0xe8, 0x01, 0x3b, 0xec, - 0x21, 0x4d, 0x47, 0xf5, 0xa5, 0x9a, 0xdc, 0x05, 0x3e, 0x83, 0xd9, 0x8f, 0x1f, 0x74, 0x80, 0x65, 0xde, 0x9f, 0x8f, - 0x02, 0xbd, 0xb6, 0xda, 0x92, 0xf6, 0x64, 0x98, 0x6b, 0x82, 0xc1, 0x7d, 0xaf, 0x3b, 0x66, 0x2f, 0x9b, 0x8c, 0x4d, - 0x2c, 0x12, 0xe0, 0x83, 0xd0, 0x18, 0xc8, 0xfe, 0xc9, 0xfd, 0x9b, 0xa1, 0x2c, 0xcf, 0x7d, 0x38, 0x2b, 0xbc, 0x2e, - 0xdb, 0x67, 0xc2, 0x19, 0x6a, 0x91, 0x45, 0xca, 0x6a, 0x96, 0x5f, 0xda, 0x76, 0x0d, 0xd6, 0x4d, 0x59, 0xce, 0x5e, - 0xff, 0x98, 0xf2, 0x8d, 0x46, 0xa9, 0x4c, 0x86, 0xd5, 0x4e, 0x2a, 0x1d, 0x1e, 0x21, 0x90, 0x7a, 0x31, 0x96, 0x05, - 0xf3, 0x42, 0xf4, 0xf2, 0xf3, 0x91, 0x36, 0xb5, 0x17, 0x20, 0x08, 0xcc, 0xd5, 0x1e, 0x59, 0x2c, 0xf9, 0xba, 0x0d, - 0x80, 0xde, 0xb4, 0xd6, 0x57, 0x90, 0x50, 0xe5, 0xec, 0xb6, 0x60, 0x09, 0x7e, 0x92, 0xd6, 0x88, 0xc3, 0x8e, 0x2e, - 0xd8, 0x71, 0x1b, 0x73, 0x0c, 0xb0, 0x5c, 0xbb, 0xc9, 0x69, 0x38, 0x79, 0xc7, 0xdb, 0x8b, 0xe5, 0x64, 0x09, 0x2f, - 0xdc, 0xb8, 0x3d, 0x4c, 0xc3, 0x35, 0x6c, 0x6c, 0xf9, 0x24, 0x5d, 0x3c, 0xb5, 0xcb, 0xac, 0x49, 0xe8, 0xd3, 0x71, - 0xca, 0x77, 0x49, 0xc1, 0xf3, 0xdc, 0xc9, 0xec, 0xd0, 0xc5, 0xaa, 0x90, 0xcf, 0x5e, 0xdd, 0x0f, 0x2b, 0x0e, 0xab, - 0x07, 0x0f, 0xff, 0x87, 0xec, 0xda, 0x6c, 0x1e, 0x1a, 0x57, 0x6e, 0xb2, 0xec, 0x5c, 0x08, 0x91, 0x8e, 0x07, 0x62, - 0xa4, 0xfc, 0xd5, 0x3f, 0xa3, 0x2b, 0x77, 0x9a, 0xd9, 0xfe, 0xb5, 0x30, 0xc6, 0xc1, 0xdf, 0xd8, 0x56, 0x7b, 0xc8, - 0x1d, 0x54, 0xd7, 0x94, 0x9d, 0xd2, 0x7b, 0x76, 0x6c, 0xa3, 0x4f, 0x46, 0x34, 0xe8, 0x79, 0x7d, 0x33, 0x01, 0x72, - 0xde, 0x5f, 0xb4, 0x2d, 0x3e, 0x62, 0x04, 0xe4, 0x8d, 0x2e, 0x4f, 0xed, 0x3b, 0xc0, 0x70, 0x6d, 0xff, 0xb0, 0x02, - 0xa0, 0x9c, 0xb5, 0xa7, 0xb4, 0xc7, 0xed, 0xc3, 0x78, 0x20, 0x60, 0x61, 0x0d, 0xd6, 0x44, 0x65, 0x5f, 0x22, 0x5b, - 0x52, 0xb7, 0x40, 0x99, 0x0a, 0x0f, 0xb1, 0x63, 0x45, 0x38, 0x9f, 0xf4, 0x00, 0xb3, 0xb0, 0x74, 0xe6, 0x06, 0x1e, - 0x34, 0x83, 0x3a, 0xfe, 0x4e, 0x58, 0xb9, 0xee, 0x29, 0x75, 0x8f, 0x4c, 0x95, 0x31, 0x58, 0xea, 0x28, 0x95, 0x2c, - 0x78, 0x0e, 0xa6, 0x63, 0x09, 0x45, 0x8d, 0x6b, 0x97, 0x64, 0x10, 0x23, 0x5e, 0xbb, 0x80, 0x8e, 0x7e, 0x77, 0x73, - 0x70, 0x02, 0x3b, 0x24, 0xf3, 0x05, 0xc9, 0x6e, 0x1e, 0x21, 0x5b, 0x31, 0x1e, 0x99, 0xee, 0x46, 0x5c, 0xac, 0x58, - 0xb0, 0xc4, 0x12, 0xda, 0xa6, 0xe3, 0xbc, 0xe6, 0x0c, 0x64, 0x90, 0x47, 0x95, 0x8a, 0x52, 0xde, 0x6f, 0xc6, 0xf6, - 0x09, 0x49, 0xc3, 0x58, 0xfd, 0x04, 0xf3, 0x7a, 0xdc, 0x4a, 0x7c, 0x7a, 0x63, 0xa3, 0x67, 0x29, 0xea, 0x54, 0xa8, - 0x2f, 0xac, 0xa3, 0x62, 0x45, 0x24, 0xeb, 0x58, 0x6b, 0x2b, 0x0c, 0x8e, 0x0f, 0x33, 0x56, 0xe2, 0xb9, 0x27, 0xec, - 0x7f, 0x6c, 0xa4, 0xe1, 0xbe, 0x1b, 0x14, 0x72, 0x7d, 0xda, 0xb8, 0xb6, 0x62, 0x3e, 0x64, 0x69, 0x3a, 0x54, 0x9e, - 0x33, 0x5e, 0xdc, 0xc1, 0x83, 0x7c, 0x1f, 0x43, 0x9d, 0x09, 0xb2, 0x05, 0xa4, 0x2d, 0xc1, 0xa4, 0x85, 0xc9, 0xa4, - 0x80, 0xf5, 0x77, 0xa0, 0x36, 0x66, 0xf5, 0xc8, 0x93, 0x49, 0x14, 0xb4, 0xd1, 0x69, 0x5c, 0x56, 0xb3, 0x52, 0xcd, - 0xc8, 0x19, 0x27, 0x4f, 0x9c, 0x71, 0x8a, 0x9a, 0x1f, 0x06, 0x80, 0xf6, 0x7c, 0x18, 0x63, 0x90, 0x47, 0x08, 0x85, - 0xe2, 0xe3, 0x3a, 0x01, 0x69, 0xab, 0xb6, 0x59, 0x87, 0x04, 0x09, 0xfc, 0xa1, 0xd2, 0x34, 0x6a, 0x7b, 0x68, 0x34, - 0x41, 0x70, 0x9d, 0xd1, 0xad, 0x53, 0x3c, 0x60, 0x9a, 0x76, 0x74, 0x7b, 0xb7, 0xbc, 0xce, 0xf1, 0x88, 0xc4, 0x6c, - 0x95, 0xf9, 0xaa, 0x28, 0x91, 0xd8, 0x4c, 0x7b, 0x6c, 0x1c, 0x41, 0x38, 0xdd, 0xae, 0x0d, 0xda, 0x5d, 0xd5, 0x05, - 0x17, 0x68, 0xe2, 0x14, 0x85, 0x40, 0x6e, 0xae, 0x15, 0x3a, 0xa9, 0xc9, 0x51, 0x77, 0x40, 0x73, 0x53, 0x9d, 0x97, - 0x19, 0xb6, 0x7f, 0xc2, 0x9d, 0x4a, 0x2f, 0xc4, 0x22, 0x37, 0xf8, 0xab, 0x8f, 0xdc, 0xae, 0xb6, 0x41, 0x1b, 0xaf, - 0xd6, 0x49, 0x2b, 0xaf, 0xb6, 0xe1, 0x48, 0x56, 0x1a, 0x3a, 0x73, 0x19, 0xc6, 0xe6, 0xda, 0x4b, 0x19, 0x9d, 0xa7, - 0x17, 0x61, 0xdc, 0xa9, 0xcd, 0xf3, 0x11, 0x43, 0xce, 0x6d, 0xca, 0xc7, 0xf4, 0x6c, 0xbc, 0xfe, 0x67, 0xfe, 0xef, - 0xea, 0x84, 0x85, 0x0d, 0x6b, 0xbd, 0x13, 0x49, 0x23, 0x50, 0x49, 0x54, 0x8b, 0xbb, 0x0e, 0xda, 0x7b, 0x89, 0x71, - 0x6a, 0x9f, 0x1b, 0x0d, 0x92, 0xbe, 0x3f, 0x61, 0x24, 0x03, 0x41, 0xac, 0x29, 0x69, 0xf5, 0xfe, 0x75, 0x62, 0x2b, - 0xfa, 0x95, 0x20, 0xf1, 0x1f, 0xdf, 0x75, 0xbd, 0x95, 0x44, 0xa4, 0x41, 0xd3, 0x4e, 0x85, 0xcc, 0x06, 0xf0, 0xab, - 0x4f, 0x1f, 0x4a, 0x34, 0x31, 0x94, 0x9e, 0x5c, 0x21, 0xb0, 0x6b, 0x2f, 0x4e, 0xd7, 0x67, 0xde, 0xf0, 0xa6, 0xe2, - 0x0d, 0xc4, 0xe6, 0xaf, 0xfb, 0xc9, 0x9b, 0x95, 0x5f, 0x03, 0x5e, 0x16, 0xdc, 0xa1, 0xce, 0x6e, 0x54, 0xc2, 0x0f, - 0x1a, 0xce, 0x02, 0xe4, 0x28, 0x3f, 0xe9, 0x5f, 0x83, 0x0f, 0x1f, 0x0d, 0xde, 0xf0, 0xce, 0xa1, 0x7a, 0x53, 0x45, - 0x90, 0xe3, 0x92, 0x9c, 0x56, 0x16, 0x59, 0x1a, 0xae, 0x5b, 0xb0, 0x3a, 0x78, 0x83, 0x99, 0xa6, 0x6f, 0x6f, 0xc9, - 0xe9, 0x06, 0xa4, 0x15, 0xe1, 0x49, 0xec, 0x27, 0xd6, 0x29, 0x6c, 0xe2, 0x8b, 0x38, 0xdf, 0xaa, 0x68, 0x30, 0xde, - 0xde, 0xda, 0x89, 0x89, 0xd4, 0x07, 0xb0, 0x36, 0x2f, 0xde, 0x00, 0x6b, 0xbb, 0xf4, 0xcd, 0xef, 0x97, 0x59, 0xe4, - 0x12, 0x29, 0x73, 0x43, 0x1e, 0xee, 0x6b, 0x33, 0xa2, 0xae, 0x84, 0x42, 0x8e, 0xd0, 0xaa, 0x70, 0x95, 0x18, 0x51, - 0x72, 0x7a, 0xdb, 0xd5, 0xed, 0x24, 0x21, 0x16, 0x0a, 0xf5, 0x75, 0x25, 0x92, 0xd1, 0x4a, 0xc9, 0xf5, 0x3d, 0x72, - 0xa9, 0xaa, 0x3f, 0x82, 0x51, 0xaa, 0x6a, 0x68, 0xc8, 0xb5, 0x09, 0x08, 0xec, 0x6a, 0x2a, 0x2e, 0xe1, 0xc8, 0xb3, - 0xb6, 0x2c, 0xe1, 0xd2, 0x18, 0x94, 0x25, 0x5a, 0x0c, 0x32, 0xb5, 0xc8, 0x3b, 0x2f, 0xe9, 0x9a, 0xc7, 0x02, 0x9b, - 0x38, 0x62, 0xb1, 0x66, 0xfa, 0x31, 0x0f, 0xdb, 0x26, 0x5b, 0x0a, 0xda, 0x03, 0xbe, 0xe7, 0x26, 0x93, 0xf9, 0x4c, - 0xda, 0xeb, 0x9b, 0xf0, 0x92, 0x1b, 0x41, 0xa8, 0xed, 0xd1, 0x14, 0x11, 0x76, 0x7e, 0xe2, 0x0d, 0xce, 0xa0, 0x6a, - 0x9e, 0x89, 0xe5, 0x6a, 0xbd, 0xdd, 0x39, 0x83, 0xf4, 0x4d, 0xf8, 0xdb, 0x03, 0x79, 0xc0, 0x4d, 0xd9, 0x50, 0xe4, - 0xa4, 0x99, 0x27, 0x4e, 0x93, 0x27, 0xaa, 0xd5, 0x8f, 0x67, 0x28, 0xa3, 0x6e, 0x22, 0x62, 0xbd, 0xd9, 0xae, 0x14, - 0x29, 0xee, 0x25, 0xdd, 0xa5, 0x0e, 0xd7, 0x6e, 0x5e, 0x99, 0xd1, 0x8e, 0x42, 0x9f, 0xde, 0xad, 0x60, 0x85, 0x1a, - 0x6f, 0xfc, 0x98, 0x8d, 0x37, 0xe2, 0x82, 0x08, 0xf0, 0x21, 0x46, 0xcb, 0x82, 0x4e, 0x13, 0x2d, 0x66, 0x4f, 0x0f, - 0xca, 0xe7, 0x2e, 0xed, 0xd4, 0x55, 0xcb, 0xf8, 0x7a, 0xf8, 0xa0, 0x0d, 0x39, 0x6b, 0xd5, 0x18, 0xa7, 0xe5, 0x62, - 0x39, 0xbb, 0x3c, 0x42, 0x49, 0x71, 0xb8, 0x96, 0xdd, 0xfc, 0x2f, 0xda, 0xdc, 0xb0, 0xa1, 0xe6, 0x58, 0x38, 0xdd, - 0x69, 0x42, 0x63, 0x64, 0x37, 0x84, 0x83, 0xad, 0xa1, 0x16, 0x54, 0x10, 0xe9, 0x4f, 0xcc, 0xe1, 0xd9, 0xdb, 0x2c, - 0x05, 0x87, 0x8a, 0x11, 0x29, 0x1a, 0xf5, 0xd0, 0x29, 0x97, 0x89, 0x75, 0x8d, 0x5c, 0x4b, 0x8a, 0xf1, 0x27, 0xa3, - 0x9f, 0x48, 0xb3, 0xfc, 0x47, 0xe0, 0xe5, 0xd2, 0xb8, 0x34, 0xf8, 0x8d, 0xbf, 0x8d, 0xa1, 0x87, 0x27, 0x4f, 0x74, - 0x71, 0x61, 0xe3, 0xf0, 0x6f, 0xb8, 0xec, 0x42, 0x31, 0x66, 0x5b, 0x66, 0xbc, 0xb3, 0x5c, 0x9a, 0xbc, 0xa5, 0x0b, - 0x79, 0xca, 0x43, 0xe7, 0x0e, 0x9c, 0x10, 0x6d, 0x2c, 0x3b, 0xa0, 0xbe, 0x02, 0xe3, 0xdc, 0x87, 0xcc, 0xb8, 0xc8, - 0x16, 0x5d, 0xb9, 0xfe, 0x9a, 0x8b, 0x0e, 0x40, 0x2d, 0x12, 0x59, 0x5f, 0xd8, 0xc7, 0x58, 0xbb, 0x78, 0x5d, 0x6b, - 0xcf, 0x87, 0x28, 0xa6, 0x3e, 0xd7, 0x2b, 0x80, 0xa2, 0xc0, 0x68, 0xc3, 0x36, 0x76, 0x28, 0x21, 0x40, 0xba, 0x95, - 0x2d, 0xfa, 0x76, 0x8f, 0x46, 0x69, 0xa5, 0x54, 0x38, 0x67, 0x29, 0x1c, 0x95, 0xda, 0xc1, 0x22, 0x24, 0x16, 0xf1, - 0xa1, 0x74, 0x7e, 0x41, 0x24, 0x64, 0x3c, 0x67, 0x43, 0x54, 0x38, 0x49, 0x95, 0xe2, 0xf9, 0xb1, 0x9e, 0xb9, 0x6e, - 0x13, 0x8d, 0xd9, 0xa0, 0xfe, 0xc5, 0x67, 0xb7, 0xd4, 0xa9, 0x03, 0x88, 0x17, 0xbc, 0x73, 0x12, 0xfc, 0xb2, 0x00, - 0xe1, 0x9f, 0x1a, 0x17, 0xbd, 0xc8, 0xf2, 0x18, 0x8a, 0x94, 0x10, 0xe9, 0x9d, 0xc6, 0x4e, 0x64, 0xe8, 0xf4, 0x44, - 0x64, 0x01, 0xa3, 0x6b, 0x1b, 0xc8, 0x21, 0x1e, 0xfb, 0x31, 0xcb, 0x04, 0x2f, 0x40, 0x61, 0xa3, 0xd8, 0x44, 0x8b, - 0x7a, 0x59, 0xad, 0xa9, 0x59, 0x50, 0x13, 0x57, 0xa0, 0x47, 0xd3, 0x53, 0x5c, 0x07, 0x5e, 0xfb, 0xfa, 0x58, 0xc5, - 0xa2, 0x3d, 0x29, 0xd0, 0x04, 0x2b, 0x1c, 0xd0, 0x15, 0x8e, 0xc7, 0x0f, 0xe8, 0xdc, 0x3e, 0xa6, 0x1a, 0x9a, 0x58, - 0x15, 0xce, 0x6a, 0x8f, 0x39, 0x16, 0xd3, 0xda, 0x54, 0x79, 0xdd, 0x44, 0xa2, 0x41, 0x73, 0x5f, 0xd8, 0xc3, 0x67, - 0x7a, 0xb5, 0xd5, 0x62, 0x1c, 0x45, 0xfd, 0xe7, 0x5d, 0x84, 0x6f, 0xd0, 0xc6, 0xad, 0x16, 0xbe, 0x12, 0x54, 0xe5, - 0x05, 0x3a, 0x22, 0x20, 0x8e, 0xd6, 0x42, 0x64, 0xe6, 0x26, 0x05, 0x05, 0x55, 0x61, 0xbf, 0x67, 0x94, 0x57, 0x5f, - 0x6f, 0xca, 0xde, 0x8e, 0x33, 0xac, 0x37, 0x96, 0x1f, 0x8d, 0x11, 0xeb, 0x26, 0x24, 0x9c, 0x24, 0xbf, 0x83, 0xbf, - 0xa9, 0x19, 0xf4, 0x1f, 0xc0, 0xe9, 0xa3, 0x3e, 0xcc, 0xf8, 0x5d, 0x3d, 0x69, 0x02, 0x5d, 0x99, 0x6b, 0x06, 0xcf, - 0x8b, 0x53, 0x77, 0xa2, 0x90, 0x8d, 0x3d, 0xab, 0x65, 0x89, 0x1f, 0xb3, 0xa4, 0xeb, 0x35, 0xf1, 0xe8, 0x52, 0x66, - 0x50, 0x42, 0x28, 0x0d, 0x8c, 0xdd, 0x86, 0x22, 0xb3, 0xde, 0x03, 0xda, 0x1d, 0xb6, 0x31, 0x03, 0xeb, 0x29, 0x9a, - 0x24, 0x8d, 0xe3, 0x57, 0x9f, 0x7e, 0xa4, 0x36, 0x15, 0x43, 0x1a, 0xb6, 0x03, 0x94, 0x4d, 0x32, 0x14, 0x2b, 0xcc, - 0xfa, 0x6f, 0xd0, 0x7b, 0xbb, 0x6f, 0x87, 0xfd, 0x0a, 0xfe, 0xc8, 0x6f, 0x8f, 0x9a, 0x50, 0x36, 0x87, 0x15, 0x0e, - 0x1b, 0xb4, 0xe6, 0x5b, 0x32, 0x75, 0x50, 0x22, 0x0c, 0xe6, 0x05, 0x2a, 0x53, 0x3e, 0x0c, 0xe7, 0x24, 0x93, 0x90, - 0x19, 0x86, 0xbd, 0x9d, 0x58, 0x83, 0xb6, 0x7d, 0xb7, 0x52, 0x5a, 0xdd, 0xd5, 0xd3, 0x0c, 0x0e, 0x69, 0x96, 0xde, - 0xb6, 0x81, 0x81, 0x0e, 0xd7, 0xae, 0x58, 0xa1, 0x9f, 0x67, 0x13, 0x1a, 0x29, 0xc6, 0x80, 0x51, 0x4d, 0x80, 0xec, - 0x56, 0x71, 0xf3, 0x6c, 0xc3, 0x16, 0x49, 0xc4, 0xb4, 0x3f, 0xbd, 0x3a, 0x93, 0x83, 0x8a, 0xf6, 0x22, 0xfc, 0x96, - 0x85, 0x84, 0x70, 0x07, 0x7e, 0xd2, 0x8f, 0x5b, 0x49, 0xbd, 0x95, 0xd9, 0xe6, 0xd6, 0x1b, 0x6a, 0xe7, 0x96, 0x9a, - 0xb9, 0x93, 0x88, 0xf2, 0x64, 0x90, 0x01, 0x37, 0x60, 0xca, 0x46, 0x3f, 0x3a, 0x96, 0x4d, 0x89, 0x4e, 0x94, 0x07, - 0x8a, 0xcd, 0x5a, 0x06, 0xa1, 0x1b, 0x63, 0xba, 0x70, 0x8d, 0xd4, 0xc6, 0x04, 0xa0, 0x64, 0xc3, 0x6c, 0x31, 0x6d, - 0xfa, 0xdb, 0xe7, 0x22, 0xec, 0x0f, 0xf1, 0x40, 0x94, 0xdd, 0x83, 0xa8, 0x83, 0x8e, 0xe8, 0xbf, 0x2f, 0x60, 0x95, - 0xc1, 0x0b, 0xd6, 0x6f, 0x12, 0x1a, 0x3a, 0xe0, 0x2f, 0x6b, 0x2f, 0xd7, 0x22, 0xe5, 0xbc, 0xd5, 0x9d, 0x73, 0xf5, - 0x12, 0xae, 0xbf, 0xb5, 0x67, 0x4a, 0x88, 0x18, 0x2d, 0x4a, 0x40, 0x05, 0x0d, 0xca, 0x27, 0xb0, 0xba, 0x09, 0x54, - 0xf5, 0x36, 0xa5, 0x66, 0x2e, 0x2e, 0xec, 0xcf, 0xdf, 0x66, 0x83, 0x42, 0xeb, 0xe1, 0x83, 0x8c, 0x94, 0x47, 0x10, - 0x44, 0xaa, 0xc6, 0xc2, 0x37, 0x10, 0xf3, 0xaa, 0xa2, 0x74, 0x2d, 0xbe, 0x0d, 0x84, 0x7b, 0x9f, 0x52, 0xb3, 0xa0, - 0x1f, 0x44, 0x44, 0x17, 0xaa, 0xbd, 0x42, 0x46, 0x85, 0x78, 0x7e, 0x1b, 0x65, 0xc8, 0x92, 0x53, 0x53, 0x04, 0x6a, - 0x06, 0x4e, 0x5b, 0xeb, 0xf2, 0x60, 0xa3, 0xf1, 0x81, 0x79, 0x2a, 0xf8, 0xff, 0x3a, 0x7a, 0x09, 0xdf, 0xdd, 0x37, - 0x01, 0xc2, 0xda, 0x7f, 0x1e, 0xd5, 0x5d, 0xbd, 0x69, 0x2e, 0xc4, 0xec, 0x11, 0x7f, 0x1c, 0x02, 0x4f, 0xa7, 0xb9, - 0x77, 0xb1, 0x2a, 0xc1, 0xc0, 0x8e, 0x45, 0x0e, 0x7f, 0xd4, 0xf5, 0x34, 0x7f, 0xbe, 0xaa, 0x9a, 0xc4, 0xb2, 0x86, - 0x22, 0x7e, 0x8e, 0x67, 0x73, 0xa1, 0x3a, 0x51, 0x9a, 0x4c, 0x60, 0x84, 0x23, 0xad, 0x29, 0x49, 0x1e, 0xc1, 0xba, - 0xac, 0x3d, 0x34, 0x7b, 0xbf, 0xb5, 0x92, 0xe8, 0x19, 0x0f, 0xf9, 0xf9, 0x9b, 0xa1, 0x59, 0x9e, 0x8f, 0x28, 0x4f, - 0xbb, 0x97, 0x03, 0x1a, 0xf5, 0xce, 0x09, 0xab, 0xca, 0x05, 0xb1, 0x34, 0xf6, 0x11, 0x54, 0x73, 0x9e, 0xeb, 0x1a, - 0x0b, 0xc1, 0x55, 0x8f, 0xff, 0x06, 0x8e, 0x1a, 0xb5, 0xa1, 0xd2, 0xb3, 0x51, 0xb4, 0x36, 0xb8, 0x7c, 0x4b, 0x07, - 0x98, 0x02, 0x0a, 0x84, 0x5a, 0xb3, 0x3b, 0xaf, 0xdc, 0xf2, 0xc4, 0x03, 0xa9, 0xf7, 0xcc, 0x37, 0xce, 0xc0, 0x7c, - 0x95, 0xee, 0x5a, 0xe6, 0xb5, 0xdb, 0x54, 0xf1, 0x3d, 0xf4, 0x12, 0x54, 0x51, 0xc0, 0xdf, 0x85, 0x5d, 0x29, 0x89, - 0xac, 0xc3, 0x25, 0x88, 0xcb, 0xbe, 0x9d, 0xa1, 0x80, 0xd1, 0x7b, 0xc5, 0x15, 0xbb, 0xe1, 0x5d, 0xe7, 0x51, 0x99, - 0x43, 0x59, 0x93, 0x0f, 0xf0, 0x85, 0x97, 0xa3, 0xd5, 0xd7, 0xf6, 0x24, 0x19, 0x13, 0xfe, 0x1d, 0x90, 0x8c, 0x09, - 0x33, 0xa2, 0x12, 0xf3, 0x5c, 0x05, 0x1e, 0x98, 0x7f, 0xed, 0x21, 0xb7, 0xac, 0x47, 0xeb, 0xac, 0x03, 0xad, 0xe7, - 0xd4, 0xbb, 0x68, 0xe0, 0xf7, 0xa4, 0xb5, 0x03, 0x01, 0x00, 0xb2, 0x0e, 0x9d, 0x43, 0xcd, 0xad, 0x20, 0x5d, 0x55, - 0xb7, 0x87, 0x65, 0xe6, 0xb2, 0x6b, 0xb2, 0x66, 0x47, 0x8e, 0xf8, 0x25, 0x89, 0x2e, 0x50, 0x63, 0x7b, 0xca, 0x7b, - 0x7c, 0x9f, 0xd8, 0x16, 0xbc, 0x8c, 0xea, 0x0b, 0xe7, 0xa6, 0x09, 0x15, 0xf4, 0x83, 0x49, 0x15, 0xc4, 0x7a, 0x42, - 0x02, 0x66, 0xeb, 0xbe, 0x45, 0xd5, 0x7c, 0xcb, 0x57, 0xf6, 0xca, 0x84, 0x7c, 0xc2, 0xd5, 0xb3, 0xa2, 0x0a, 0x24, - 0xad, 0x2f, 0x06, 0x18, 0x0a, 0xe4, 0x12, 0x84, 0xe0, 0x12, 0x14, 0x1d, 0x8c, 0xf1, 0x04, 0x1c, 0x22, 0xce, 0x4b, - 0x8d, 0x87, 0xc9, 0xfd, 0x37, 0x6e, 0x62, 0x0d, 0x46, 0xc2, 0xe0, 0x8a, 0x0d, 0x80, 0x43, 0x2b, 0xd0, 0xea, 0x57, - 0xfb, 0xec, 0x0b, 0xdf, 0x0f, 0xd4, 0x25, 0xab, 0x09, 0xd9, 0x17, 0x51, 0x43, 0xf7, 0x02, 0x64, 0xf1, 0x2c, 0x8e, - 0x4b, 0xa2, 0x33, 0xbe, 0xf1, 0xd0, 0x43, 0x21, 0x0d, 0x42, 0xfe, 0x27, 0xa3, 0xe0, 0x04, 0xcc, 0x24, 0x2a, 0xda, - 0x12, 0x1e, 0xdd, 0xe8, 0x40, 0x03, 0xbb, 0xb1, 0x6e, 0x6a, 0xe1, 0x4e, 0x4c, 0xa5, 0xd5, 0x0d, 0x63, 0x58, 0x65, - 0x84, 0xa6, 0x91, 0xba, 0xdb, 0x9a, 0xb9, 0xba, 0x58, 0xed, 0x8e, 0x67, 0xdf, 0xff, 0x0d, 0x97, 0x32, 0x5b, 0x94, - 0x10, 0x67, 0x12, 0x63, 0xe2, 0x54, 0x2d, 0xbf, 0x11, 0x71, 0xe7, 0x7e, 0xa7, 0x00, 0x44, 0x9f, 0x71, 0x1a, 0x6d, - 0x36, 0x52, 0xd3, 0x03, 0x76, 0x07, 0x3c, 0x50, 0xfc, 0x21, 0xd8, 0xf8, 0x34, 0x79, 0xc8, 0xd6, 0x4a, 0x26, 0x97, - 0xb6, 0xae, 0x6b, 0x3b, 0xf5, 0x2e, 0x7e, 0xcc, 0xb1, 0xbd, 0xb5, 0x92, 0x3c, 0x15, 0x21, 0xe3, 0xe8, 0x93, 0x8d, - 0x27, 0xd4, 0x39, 0xe4, 0xe7, 0xc0, 0x00, 0xba, 0xf5, 0xba, 0xfe, 0x8f, 0x44, 0x84, 0xa7, 0x23, 0x06, 0x32, 0x4c, - 0x0c, 0x9e, 0x39, 0xc3, 0xa9, 0x57, 0x20, 0x3f, 0x86, 0x61, 0x9a, 0x00, 0x7d, 0x22, 0xc9, 0x15, 0xf8, 0x82, 0x60, - 0xf8, 0x48, 0x2d, 0x1b, 0xe2, 0x7d, 0x15, 0x3e, 0xac, 0xa6, 0x16, 0xc3, 0xa2, 0x07, 0x8b, 0x48, 0xe4, 0x81, 0x1c, - 0x60, 0x7d, 0x60, 0xc9, 0x0a, 0x23, 0x02, 0x1f, 0xb3, 0xbd, 0x71, 0xac, 0x00, 0x8c, 0x76, 0xc8, 0x75, 0xfe, 0xf2, - 0x29, 0xf8, 0x1b, 0x2f, 0x54, 0x8a, 0x7d, 0x43, 0x56, 0xfc, 0x23, 0x23, 0x58, 0x1c, 0x0f, 0xa3, 0x69, 0x74, 0x12, - 0xd0, 0x4c, 0x0e, 0xdd, 0x2a, 0x21, 0x86, 0xd9, 0x77, 0x01, 0xe3, 0xd2, 0x95, 0x93, 0xe4, 0xad, 0xfa, 0xc0, 0x58, - 0x90, 0x6e, 0x13, 0x0d, 0xb2, 0xf0, 0x97, 0x05, 0xad, 0xa4, 0x41, 0x5c, 0x93, 0xf7, 0x6e, 0xa6, 0x50, 0xda, 0x97, - 0xae, 0xc3, 0xd4, 0x5d, 0x49, 0xe0, 0xba, 0x12, 0x23, 0x81, 0x5f, 0x66, 0x0d, 0x8a, 0x7c, 0x8e, 0x98, 0xc7, 0xf1, - 0x0e, 0x80, 0x3b, 0x81, 0xe6, 0xc8, 0x21, 0x3b, 0x4f, 0xc4, 0xee, 0x9e, 0xc0, 0x1f, 0xcb, 0x1f, 0x89, 0xfa, 0xe5, - 0xf1, 0x28, 0x3b, 0xa0, 0x68, 0x7f, 0x93, 0x58, 0xaa, 0x42, 0x09, 0xa0, 0x91, 0x2d, 0x50, 0xe9, 0x0a, 0xe0, 0x32, - 0x70, 0x88, 0x58, 0x3d, 0xb3, 0x1e, 0x01, 0x3d, 0xf6, 0xf0, 0x67, 0xa7, 0xaf, 0x7d, 0x5d, 0x13, 0x56, 0x79, 0xdb, - 0x98, 0xac, 0xb3, 0x05, 0xe7, 0x5c, 0x57, 0x27, 0x69, 0xe6, 0xd5, 0x3d, 0x6d, 0xa8, 0x5f, 0x92, 0xb4, 0x6d, 0x2d, - 0xca, 0xc0, 0xf4, 0x73, 0x92, 0x86, 0x50, 0xe8, 0x8f, 0xe5, 0x99, 0x86, 0x52, 0xf3, 0x42, 0x77, 0x1e, 0xc5, 0xb7, - 0x54, 0x3b, 0xa4, 0x76, 0x5d, 0x9a, 0xf6, 0x11, 0xe1, 0x95, 0x34, 0xf6, 0x4c, 0x06, 0x1f, 0x41, 0x58, 0x1a, 0x8a, - 0x13, 0x73, 0x76, 0x09, 0x00, 0x09, 0x43, 0x0e, 0xee, 0x44, 0xde, 0xa6, 0xd8, 0x13, 0xd0, 0xd2, 0xa6, 0x76, 0xef, - 0xaa, 0xc1, 0x84, 0x2a, 0x51, 0xf2, 0xc0, 0xad, 0x6d, 0xf1, 0x58, 0x28, 0x93, 0xe8, 0x9f, 0x4d, 0x49, 0xa8, 0x24, - 0x7f, 0xea, 0xfc, 0x8f, 0x3f, 0x28, 0x22, 0x9d, 0x00, 0xb7, 0xac, 0x6a, 0xff, 0xdc, 0x89, 0x77, 0x32, 0xc4, 0x21, - 0x23, 0x23, 0xfc, 0x17, 0x95, 0xd1, 0xc7, 0x13, 0xb8, 0x24, 0x7c, 0xa4, 0x3d, 0xc8, 0x55, 0xf7, 0x44, 0x9d, 0x83, - 0x51, 0x1e, 0x6d, 0x60, 0x62, 0x7e, 0x9e, 0x86, 0xb3, 0x6e, 0x32, 0xb0, 0x30, 0xcb, 0x90, 0xcf, 0x8b, 0xed, 0xc1, - 0x01, 0x5f, 0x09, 0xc0, 0x17, 0x1a, 0x26, 0x1f, 0x73, 0x82, 0x6a, 0xc3, 0xc9, 0x94, 0xeb, 0xec, 0x6e, 0x9c, 0x6a, - 0xa9, 0x82, 0x76, 0x60, 0x42, 0x00, 0xf4, 0x5c, 0x70, 0x0b, 0x07, 0xcd, 0xcf, 0x9b, 0x7c, 0xc2, 0xc9, 0xa7, 0x7e, - 0x25, 0x7d, 0xd1, 0x18, 0x6a, 0x7d, 0x9e, 0x11, 0xb4, 0x34, 0x03, 0x6e, 0xe1, 0x72, 0x08, 0x5b, 0x38, 0x86, 0x05, - 0x19, 0x2f, 0x84, 0xf1, 0x02, 0x4a, 0xe0, 0xcb, 0x21, 0xc4, 0x00, 0xb6, 0x3f, 0x52, 0xb2, 0x9c, 0x50, 0xed, 0x59, - 0xd9, 0xa3, 0x00, 0x41, 0x64, 0xf2, 0xeb, 0x97, 0x8f, 0xff, 0x85, 0x22, 0xb0, 0x0a, 0xa8, 0x4d, 0x07, 0x90, 0xad, - 0x45, 0xc4, 0xb5, 0xf2, 0x54, 0x85, 0x79, 0xa5, 0x04, 0x93, 0xde, 0xf5, 0x0f, 0xaf, 0x7b, 0xab, 0xa0, 0x0f, 0x4b, - 0xcd, 0x31, 0x1b, 0x4d, 0x84, 0x4f, 0x19, 0xfd, 0x79, 0x6d, 0x1d, 0x20, 0xb7, 0x61, 0xf5, 0xc6, 0x95, 0x34, 0x0c, - 0x1a, 0xb5, 0x5f, 0xb2, 0x92, 0xd2, 0xea, 0x46, 0xce, 0x33, 0x4c, 0xbd, 0xe5, 0x1f, 0xee, 0x02, 0x3e, 0x06, 0xac, - 0x30, 0x3f, 0xd0, 0x4b, 0xed, 0x85, 0x57, 0x80, 0xdf, 0x18, 0x11, 0xe4, 0xbe, 0x6d, 0x89, 0x82, 0x4c, 0x6d, 0xbd, - 0x36, 0x95, 0x1e, 0xe6, 0x58, 0x4f, 0xbc, 0xcf, 0xc9, 0xbe, 0x78, 0xe7, 0x5e, 0x2b, 0xc1, 0x7c, 0x48, 0xe2, 0xbb, - 0x88, 0x28, 0x3d, 0x58, 0x4c, 0x8d, 0xa9, 0xf9, 0x03, 0xc0, 0x45, 0xe1, 0xe1, 0xd4, 0xfb, 0x37, 0xd9, 0x25, 0xaf, - 0x6d, 0x2f, 0x2f, 0x79, 0x1c, 0xf7, 0x77, 0x37, 0xfd, 0x86, 0x1f, 0x86, 0xaf, 0xd5, 0x8d, 0xa6, 0xc0, 0xf4, 0x2c, - 0x13, 0xc1, 0x35, 0xfc, 0x41, 0x52, 0x6e, 0x1f, 0x90, 0xb5, 0x0d, 0x9b, 0xe7, 0xd4, 0xda, 0x74, 0xed, 0x06, 0xbe, - 0x72, 0x3a, 0xbe, 0x7c, 0xf9, 0xfe, 0x03, 0x85, 0x72, 0x08, 0x3f, 0x1d, 0x13, 0x03, 0xa9, 0x2b, 0x74, 0x70, 0x27, - 0x9e, 0xe9, 0x71, 0x01, 0xfd, 0xe0, 0xd4, 0x06, 0xe4, 0x0f, 0xd7, 0xda, 0x0a, 0xbb, 0x35, 0xe3, 0x25, 0xea, 0x43, - 0x8f, 0xb0, 0xcd, 0xb2, 0xb0, 0xec, 0xb6, 0x6a, 0x00, 0x65, 0xc1, 0xe2, 0x1b, 0x38, 0x4d, 0x4d, 0x49, 0x0e, 0x9f, - 0xb5, 0xb7, 0x8b, 0x56, 0xdf, 0x63, 0x01, 0xee, 0x1f, 0x90, 0x14, 0x54, 0x08, 0xff, 0x5b, 0xb4, 0x7f, 0xd0, 0x14, - 0x88, 0x2f, 0x49, 0xa1, 0x06, 0xc3, 0x47, 0x9e, 0x60, 0xfd, 0x49, 0x11, 0x35, 0x56, 0xf2, 0xdc, 0x7b, 0x08, 0x68, - 0x5c, 0xde, 0x20, 0xf4, 0x1a, 0xbc, 0xaa, 0x1c, 0x1e, 0x94, 0x37, 0x51, 0xce, 0x78, 0x6a, 0xf2, 0xbe, 0x2e, 0x31, - 0xa1, 0xb7, 0xb7, 0x55, 0xaa, 0x78, 0xaa, 0x7a, 0xa4, 0x3c, 0x24, 0x01, 0xd2, 0x45, 0x81, 0x8b, 0x36, 0x1d, 0xe7, - 0x67, 0xc1, 0x9c, 0x15, 0xf8, 0x52, 0x6e, 0x24, 0xca, 0x2f, 0xc6, 0xcc, 0x6c, 0xe4, 0xaf, 0x37, 0x2e, 0x37, 0x5e, - 0xdd, 0xd6, 0x4a, 0x34, 0xd7, 0x92, 0x02, 0x5d, 0xae, 0xa3, 0xbf, 0xba, 0x11, 0x86, 0x72, 0x48, 0xf9, 0x4f, 0x28, - 0x4c, 0x6c, 0x81, 0x14, 0xe4, 0x25, 0x91, 0xff, 0x1e, 0x96, 0xb3, 0x85, 0xaf, 0x62, 0x1f, 0xa0, 0x6c, 0x24, 0xf6, - 0x07, 0x22, 0x45, 0xa6, 0xdd, 0x58, 0xb6, 0xfb, 0xbf, 0x16, 0x6f, 0xfe, 0x55, 0x95, 0x2f, 0xd5, 0xb3, 0x44, 0x14, - 0xea, 0x9c, 0x94, 0xcf, 0x30, 0xda, 0xe2, 0x7f, 0x86, 0x22, 0xad, 0x42, 0x0f, 0x6d, 0x0f, 0x3c, 0x0c, 0xad, 0x49, - 0x60, 0xcb, 0x7b, 0x3a, 0x04, 0x1b, 0x54, 0x9b, 0xd8, 0x72, 0x1a, 0x75, 0x56, 0xb4, 0x2a, 0xf7, 0xd8, 0x73, 0xed, - 0x19, 0xd4, 0xa3, 0x58, 0xe5, 0xa7, 0xe6, 0xd2, 0x80, 0x85, 0x01, 0x7f, 0x03, 0xf1, 0x55, 0xcc, 0xb9, 0xde, 0xad, - 0xe3, 0xb7, 0xcd, 0x4d, 0x58, 0x69, 0xa8, 0x5b, 0x00, 0x19, 0x17, 0x0c, 0x98, 0x3d, 0xf3, 0x04, 0x82, 0x62, 0x50, - 0x06, 0x03, 0x4e, 0xd3, 0xe7, 0x39, 0x67, 0x09, 0xf4, 0x91, 0xbd, 0x82, 0x03, 0x12, 0x42, 0xab, 0x58, 0x33, 0x91, - 0x2f, 0x40, 0x91, 0xae, 0xda, 0xe4, 0xcc, 0xb5, 0xa8, 0xa7, 0x09, 0xad, 0x02, 0x99, 0xc7, 0x0a, 0xa6, 0xcf, 0xbe, - 0x51, 0xc8, 0xa5, 0x30, 0x93, 0x3b, 0x7f, 0x41, 0xf3, 0x38, 0xcc, 0xd0, 0x45, 0x7e, 0x4a, 0x43, 0xb6, 0x73, 0x73, - 0xbf, 0x7d, 0x90, 0xc4, 0x27, 0xea, 0xc4, 0x7c, 0xc2, 0xfc, 0x57, 0x6f, 0xde, 0x75, 0x6f, 0x9a, 0xf3, 0xab, 0x69, - 0xfe, 0x5a, 0x41, 0xb3, 0x3f, 0x2e, 0xae, 0x50, 0xea, 0x8f, 0x58, 0xae, 0x9a, 0x56, 0x3e, 0xb2, 0x5f, 0x8d, 0x93, - 0x11, 0x91, 0xd0, 0x5e, 0x96, 0xd7, 0x31, 0x69, 0xf6, 0x9e, 0x5b, 0xb8, 0x6f, 0xc3, 0x4b, 0xc3, 0x62, 0xb9, 0x94, - 0x29, 0xad, 0x97, 0xc4, 0xfa, 0xc8, 0x05, 0xfe, 0x58, 0x22, 0x53, 0x1b, 0x6f, 0xf2, 0x8e, 0x74, 0x7e, 0x55, 0x77, - 0x79, 0x9c, 0x30, 0x98, 0xb9, 0x1b, 0x0b, 0x83, 0x3e, 0xd8, 0xcd, 0xd7, 0x91, 0xb7, 0x32, 0x04, 0xbd, 0x28, 0xdd, - 0xcd, 0x6e, 0x77, 0x9f, 0xa1, 0x60, 0xa5, 0x64, 0xc8, 0x96, 0x94, 0xf1, 0x47, 0x47, 0x0d, 0xf9, 0x4b, 0xa9, 0xcf, - 0xff, 0x4c, 0x22, 0x6e, 0xec, 0x7e, 0x79, 0xea, 0x44, 0x06, 0x5f, 0x90, 0xbb, 0x63, 0x24, 0xcb, 0xa7, 0x40, 0x21, - 0xec, 0x48, 0xb0, 0xf9, 0x4e, 0xb7, 0x09, 0x0e, 0x89, 0x34, 0x82, 0x86, 0xfa, 0xa8, 0x12, 0x81, 0x0a, 0xf1, 0x39, - 0x7d, 0x49, 0x1d, 0x3d, 0xeb, 0x5f, 0x8e, 0x7d, 0x06, 0x82, 0x56, 0x25, 0x32, 0x2a, 0x9d, 0x5c, 0x26, 0xa7, 0x30, - 0x82, 0x48, 0x50, 0x04, 0xb9, 0x49, 0x43, 0xf8, 0x70, 0x94, 0x5e, 0x3c, 0x29, 0x0d, 0x6b, 0x70, 0x0d, 0x1e, 0x4f, - 0x10, 0x93, 0x8c, 0x71, 0xeb, 0xdd, 0x6e, 0xdc, 0x9f, 0xde, 0x36, 0x60, 0xf5, 0x8f, 0x04, 0x9a, 0x20, 0xdc, 0x97, - 0x5c, 0xa0, 0x27, 0xe0, 0xb8, 0x16, 0x5c, 0xfb, 0x04, 0x86, 0x46, 0x07, 0x6a, 0xe9, 0xc8, 0x9d, 0x22, 0xff, 0x06, - 0x3c, 0xbb, 0x5b, 0x01, 0xe1, 0xda, 0xe5, 0x7d, 0x16, 0xd5, 0x12, 0x81, 0x5a, 0x67, 0x12, 0xcd, 0x6a, 0x11, 0xaa, - 0x6d, 0xbb, 0x01, 0x57, 0xc7, 0x50, 0xec, 0xa1, 0xf1, 0x17, 0xb0, 0xf0, 0x7c, 0xf2, 0xce, 0xc6, 0xc9, 0x78, 0x48, - 0x5f, 0xb5, 0x19, 0x2d, 0x9e, 0x7c, 0x6c, 0x39, 0xa6, 0xd2, 0x41, 0x0a, 0x1e, 0x2d, 0x08, 0xc2, 0x22, 0x7d, 0xe6, - 0x11, 0xb3, 0x1d, 0xe7, 0x7d, 0x00, 0x67, 0x71, 0x81, 0xee, 0x85, 0x11, 0x3c, 0x3c, 0xb6, 0x17, 0x07, 0x16, 0xb4, - 0x9f, 0x6b, 0x9d, 0xad, 0x48, 0x8b, 0x11, 0xee, 0x45, 0xcb, 0x5d, 0xc5, 0xb8, 0x8e, 0x3c, 0xc2, 0x97, 0xc1, 0xfb, - 0xee, 0x20, 0xc9, 0x73, 0x2b, 0x1c, 0x1c, 0x05, 0x3c, 0x90, 0x27, 0x46, 0x32, 0x46, 0x33, 0xf9, 0xf6, 0x67, 0x72, - 0xb7, 0x67, 0xbf, 0x19, 0x6e, 0x76, 0xc1, 0x45, 0x55, 0xa4, 0xcb, 0x6b, 0xbe, 0xee, 0xd6, 0xd1, 0xe5, 0x6b, 0x00, - 0xbe, 0x55, 0xf4, 0xa6, 0x2b, 0xac, 0x66, 0xb2, 0x11, 0x15, 0xce, 0xdf, 0xe5, 0x08, 0xae, 0x3c, 0xb7, 0x07, 0x15, - 0x63, 0xf0, 0x1e, 0x53, 0x9f, 0xd5, 0xda, 0xdb, 0x97, 0xba, 0x4d, 0x3f, 0xed, 0xb7, 0xdd, 0x68, 0x1a, 0xb5, 0xf8, - 0xfd, 0xf8, 0xc2, 0xa2, 0x63, 0x88, 0x74, 0x99, 0xf2, 0x65, 0xfa, 0x9b, 0x53, 0x56, 0x81, 0xb3, 0x50, 0x80, 0x6e, - 0xdd, 0x70, 0x31, 0x96, 0xf2, 0xdd, 0xd8, 0x42, 0xd4, 0xd7, 0x57, 0xa1, 0xb4, 0x27, 0xf6, 0xdc, 0xef, 0x1a, 0x0e, - 0x64, 0xf0, 0x6c, 0xbc, 0x0a, 0x3b, 0xba, 0x0a, 0xcf, 0x24, 0xde, 0xe7, 0xd7, 0xb9, 0xec, 0x3d, 0x53, 0x37, 0xef, - 0x10, 0xf8, 0x5f, 0x33, 0xbc, 0xf2, 0xb7, 0x4a, 0x98, 0xf3, 0x15, 0xff, 0x4a, 0xfc, 0xce, 0xd1, 0x0d, 0x17, 0xd1, - 0x65, 0xeb, 0x84, 0x56, 0xac, 0xf8, 0x75, 0xde, 0x7f, 0xfb, 0xf0, 0x29, 0x7a, 0x30, 0xae, 0x47, 0x86, 0x5f, 0xa5, - 0x3c, 0x87, 0x75, 0x9b, 0x46, 0x65, 0xfe, 0x54, 0xe0, 0xc5, 0x3a, 0x7f, 0x51, 0x30, 0xea, 0x4d, 0xf2, 0x57, 0xcf, - 0xbf, 0x4e, 0x5f, 0x3c, 0x90, 0x5c, 0xf8, 0x8f, 0x79, 0x7b, 0xb4, 0x1d, 0x81, 0x8b, 0xe7, 0x8f, 0x5e, 0x45, 0xe7, - 0xfa, 0xd3, 0xd6, 0x27, 0x31, 0x88, 0x7d, 0xa9, 0x8e, 0x30, 0x37, 0xde, 0xa3, 0x45, 0xd8, 0x67, 0xf4, 0x13, 0x7b, - 0x4a, 0x56, 0xaf, 0x40, 0xe4, 0x09, 0x5a, 0x9d, 0x9d, 0x23, 0x82, 0x3f, 0x44, 0x7f, 0xe4, 0x97, 0xa8, 0xd1, 0xce, - 0xb3, 0x7f, 0xd9, 0xd6, 0xff, 0xff, 0xa7, 0xeb, 0xb9, 0x19, 0x2d, 0x1a, 0xe0, 0xa5, 0xff, 0x0b, 0x44, 0xdb, 0xd9, - 0xde, 0x08, 0x52, 0x03, 0x17, 0x1e, 0xf1, 0xb3, 0x5b, 0xcb, 0xba, 0xfc, 0xf2, 0xb9, 0x9a, 0x2d, 0xa3, 0x09, 0x95, - 0x93, 0x0b, 0x4d, 0x93, 0xa4, 0x86, 0x0c, 0x5e, 0x33, 0x49, 0x7f, 0x4d, 0xcb, 0xc0, 0xbb, 0x2d, 0xa9, 0x45, 0xe6, - 0x24, 0x1f, 0x67, 0x48, 0xc5, 0xe2, 0x59, 0xb7, 0xa9, 0x36, 0x1e, 0x3d, 0x8d, 0xde, 0x0c, 0x08, 0x5f, 0x59, 0x40, - 0xcf, 0xc1, 0x52, 0xd3, 0x95, 0x1b, 0x3b, 0x4b, 0xf7, 0xb6, 0x19, 0x87, 0x22, 0x82, 0xa6, 0x6e, 0x5d, 0x6e, 0x5b, - 0x1f, 0x95, 0x54, 0x72, 0xe6, 0xcd, 0x01, 0x02, 0xbc, 0xf8, 0x7e, 0xbc, 0x2d, 0x7d, 0xde, 0x0f, 0x72, 0x95, 0x46, - 0x18, 0xd6, 0xf1, 0x52, 0x3a, 0x8b, 0x57, 0x9b, 0x55, 0x08, 0xda, 0x05, 0x10, 0x67, 0x2d, 0x74, 0x8d, 0x80, 0xa6, - 0x45, 0xbc, 0xc7, 0x95, 0x20, 0x9b, 0x1a, 0x54, 0xb2, 0x94, 0x86, 0x0f, 0xf4, 0x07, 0x10, 0x83, 0xae, 0xb6, 0x91, - 0x0a, 0x6e, 0x1c, 0xbb, 0x4f, 0x65, 0x20, 0x99, 0xc4, 0xf7, 0xaf, 0xb2, 0x4a, 0x58, 0x1b, 0xc5, 0x78, 0x29, 0xb4, - 0x4f, 0x7e, 0xcd, 0x6d, 0xaa, 0x26, 0x07, 0x3d, 0xfb, 0x8f, 0x7b, 0x81, 0xee, 0x89, 0xa2, 0xed, 0x8c, 0x31, 0x35, - 0xcf, 0xb9, 0x07, 0x66, 0x91, 0x02, 0x8d, 0x21, 0xf4, 0xa0, 0x7f, 0x4f, 0xe8, 0xa1, 0x9e, 0x54, 0x45, 0x79, 0xb1, - 0x62, 0x5c, 0xbe, 0x9a, 0x4e, 0x0b, 0x69, 0x67, 0x1c, 0xbb, 0x0e, 0x77, 0x03, 0xff, 0xbd, 0xfa, 0x57, 0x1f, 0xc6, - 0x67, 0xfb, 0x18, 0xd3, 0x9e, 0xcf, 0x54, 0x4d, 0xfd, 0x38, 0xad, 0xfa, 0x6d, 0x70, 0x56, 0x79, 0x3e, 0xdf, 0x2a, - 0x2d, 0x10, 0x89, 0x44, 0xa1, 0xcc, 0x3c, 0xcf, 0xb7, 0x7d, 0x1a, 0x2d, 0x13, 0xdb, 0xf8, 0xd6, 0x0d, 0x8a, 0x7a, - 0x2f, 0xaf, 0x26, 0x0a, 0x80, 0x6e, 0x2c, 0x29, 0xa4, 0x5b, 0x62, 0x0b, 0x20, 0x9d, 0xcf, 0xb1, 0x27, 0x09, 0xac, - 0xb6, 0x26, 0xf3, 0x00, 0x0a, 0x59, 0xa2, 0x4d, 0x12, 0x23, 0xd2, 0x2f, 0x00, 0xe2, 0x35, 0x42, 0x79, 0x91, 0xfd, - 0x02, 0x69, 0x80, 0x55, 0x11, 0xe5, 0x8d, 0x4a, 0xe4, 0x2c, 0x6f, 0x32, 0x46, 0x19, 0x2c, 0xff, 0x07, 0xfc, 0xca, - 0x7c, 0x89, 0x40, 0x89, 0xc9, 0x6b, 0x87, 0x96, 0xce, 0x22, 0x4f, 0x2b, 0x6c, 0xf7, 0x43, 0x98, 0xcf, 0xd8, 0xf5, - 0xd9, 0x74, 0x33, 0xb3, 0x24, 0xb6, 0xb8, 0x6a, 0x6e, 0x3e, 0x73, 0xb8, 0x6d, 0x0b, 0xc9, 0xb6, 0xd5, 0x03, 0x7b, - 0x92, 0xee, 0xea, 0x87, 0x9b, 0xa7, 0x36, 0xfd, 0x48, 0xe1, 0xbc, 0x9a, 0xc8, 0xbc, 0x1c, 0x3e, 0xf2, 0xba, 0x77, - 0x2d, 0x42, 0x8d, 0x8d, 0x27, 0xe1, 0xa1, 0xe6, 0xbd, 0x6b, 0x13, 0xbe, 0xf2, 0xbf, 0x8a, 0xe3, 0x69, 0x55, 0xd6, - 0xfd, 0x7a, 0x1e, 0x1b, 0x1f, 0x31, 0x3e, 0x6a, 0x6d, 0xca, 0x0c, 0xc8, 0x43, 0xb5, 0xe7, 0xba, 0x93, 0xa7, 0xb4, - 0xdd, 0x8c, 0x99, 0x6e, 0x39, 0x17, 0x8a, 0xcc, 0xcc, 0xf6, 0x28, 0x17, 0x3c, 0xad, 0xf9, 0x7a, 0x0b, 0xe5, 0x2c, - 0x2d, 0xc7, 0x99, 0xda, 0x29, 0x5d, 0xcf, 0xe5, 0xda, 0xa3, 0x9a, 0x40, 0x0e, 0x29, 0x36, 0xea, 0x5d, 0x26, 0x41, - 0x90, 0xf0, 0xb1, 0xb4, 0x74, 0xeb, 0x0c, 0x28, 0x9f, 0x57, 0xb9, 0x2f, 0xd1, 0xd4, 0xaf, 0xae, 0x5d, 0x90, 0x71, - 0xb7, 0x03, 0x91, 0xd8, 0x56, 0x32, 0xcc, 0x8a, 0x48, 0x03, 0x0f, 0x4e, 0x4d, 0x6d, 0xcf, 0xba, 0xec, 0xac, 0xda, - 0x9a, 0x39, 0xa0, 0x03, 0x26, 0x8f, 0x96, 0x61, 0x3e, 0xe6, 0x05, 0x7f, 0xae, 0x39, 0xdb, 0x68, 0xd4, 0x2f, 0x55, - 0xd8, 0xb6, 0x19, 0x16, 0x3d, 0x29, 0xc0, 0x3f, 0x94, 0xc0, 0x9b, 0x0a, 0x32, 0x00, 0x5c, 0xba, 0x36, 0x1c, 0xc1, - 0x65, 0xcb, 0x42, 0x42, 0xb2, 0xad, 0x5e, 0x7b, 0x0b, 0x10, 0x6c, 0xb6, 0xa4, 0x04, 0x0a, 0xc5, 0xcd, 0xa0, 0x79, - 0x8b, 0x6f, 0xb5, 0x47, 0x92, 0x36, 0xbe, 0x98, 0xe1, 0xee, 0x93, 0x20, 0xf0, 0xe6, 0x37, 0x07, 0xb6, 0xe8, 0x87, - 0x31, 0xce, 0x20, 0x0c, 0xcb, 0xba, 0xbf, 0x64, 0x46, 0x3c, 0xf7, 0x51, 0x7a, 0x1b, 0x7f, 0xbb, 0x08, 0xde, 0x44, - 0xf2, 0x6b, 0x0c, 0xd6, 0x68, 0x9c, 0xbc, 0xe0, 0x92, 0xf7, 0x62, 0x13, 0x78, 0xeb, 0xe7, 0x70, 0xc6, 0x34, 0x92, - 0xe7, 0xb1, 0xba, 0xf9, 0xd3, 0xd8, 0xad, 0x47, 0xbe, 0x7f, 0xf9, 0xfd, 0x2e, 0x94, 0xa4, 0x35, 0xf2, 0x20, 0x85, - 0x5c, 0x64, 0x80, 0x3a, 0x05, 0x2f, 0x5b, 0xa2, 0x6e, 0x65, 0x45, 0x9e, 0x1c, 0xf6, 0xf2, 0xfb, 0x1f, 0xcd, 0xed, - 0xf8, 0x72, 0x83, 0xb4, 0x89, 0x06, 0x88, 0xd1, 0xa9, 0x92, 0x2e, 0x11, 0xc7, 0xd7, 0xe1, 0x3f, 0xfe, 0x30, 0x9a, - 0x6f, 0x9c, 0x89, 0x77, 0xdb, 0x68, 0x11, 0xb5, 0x95, 0xe4, 0xf9, 0x71, 0xf8, 0xc8, 0x73, 0x0b, 0x6b, 0xff, 0x33, - 0x6d, 0x34, 0x8d, 0x79, 0xa1, 0x4e, 0x4f, 0x98, 0xf1, 0x77, 0x98, 0xf1, 0xff, 0xa5, 0xc7, 0x7f, 0x5e, 0xfd, 0xff, - 0xf6, 0xfe, 0x4b, 0xd0, 0xd5, 0xf1, 0xf2, 0xfe, 0xaf, 0x59, 0xfe, 0x35, 0x7f, 0x84, 0x75, 0xfc, 0x6e, 0x67, 0xf3, - 0xb5, 0x4a, 0xb3, 0x29, 0x1f, 0xad, 0xed, 0x3c, 0x21, 0x60, 0x34, 0xcf, 0x4a, 0x14, 0xcc, 0x73, 0x5c, 0x9d, 0x9b, - 0x51, 0xfe, 0xd8, 0x11, 0x16, 0x7e, 0x31, 0xbe, 0x8b, 0xce, 0x75, 0x70, 0x2f, 0xe7, 0xdf, 0x48, 0xe1, 0xbe, 0x38, - 0xa6, 0xd8, 0x56, 0xd6, 0x4a, 0xfa, 0x3e, 0x74, 0xec, 0x88, 0xc0, 0xf6, 0x73, 0xff, 0x95, 0x95, 0xb1, 0x27, 0x83, - 0xb7, 0x21, 0x35, 0x6b, 0xc6, 0xe0, 0x0b, 0x6d, 0xa6, 0x95, 0xc3, 0x15, 0xf7, 0x6a, 0x6c, 0x43, 0x1b, 0x94, 0xa6, - 0x1b, 0x80, 0x90, 0x54, 0xd0, 0x20, 0xac, 0xb3, 0xdf, 0xfe, 0x72, 0xd1, 0x7e, 0x84, 0x22, 0x9f, 0xfe, 0x00, 0xac, - 0x57, 0x8e, 0xaa, 0xc0, 0x91, 0x18, 0x64, 0xc6, 0x2e, 0x05, 0xbd, 0xc1, 0x0c, 0x0f, 0xf5, 0xf4, 0xb6, 0x60, 0xcd, - 0x67, 0x09, 0xad, 0xd1, 0xaf, 0xc8, 0x70, 0x7d, 0x89, 0x24, 0x41, 0x88, 0xd3, 0x50, 0xf9, 0x7f, 0xe2, 0x89, 0x48, - 0x9a, 0x4e, 0x13, 0x45, 0xe5, 0x94, 0x55, 0xfd, 0x2a, 0xd1, 0xec, 0x05, 0xcd, 0x99, 0xbd, 0x4c, 0x8a, 0x41, 0x67, - 0x41, 0x50, 0x5c, 0xd1, 0xe3, 0x92, 0xab, 0x72, 0x26, 0xc4, 0x43, 0xec, 0x8f, 0xb1, 0x4c, 0x2c, 0xcc, 0x39, 0x46, - 0x7b, 0xe7, 0x47, 0xc8, 0x4a, 0xb2, 0x16, 0x36, 0x64, 0x0f, 0xba, 0xd3, 0x47, 0x4f, 0xa0, 0x41, 0xd7, 0x7f, 0xbc, - 0x82, 0x20, 0x7c, 0xe0, 0xdd, 0xea, 0x66, 0x54, 0xde, 0x35, 0xa3, 0x75, 0xf0, 0xf1, 0x62, 0xe0, 0xe8, 0x22, 0x10, - 0x1c, 0x4a, 0xec, 0x57, 0x1f, 0x24, 0x95, 0x9f, 0x4c, 0x9b, 0xb0, 0x3e, 0x1c, 0x07, 0xed, 0xb7, 0x90, 0x9c, 0x21, - 0x87, 0x96, 0x4b, 0x47, 0x25, 0x10, 0x27, 0xf9, 0x73, 0x60, 0xd9, 0xb6, 0x57, 0x92, 0xd1, 0xe3, 0x4c, 0xba, 0x65, - 0xf3, 0xd9, 0x23, 0x11, 0x56, 0x12, 0xb1, 0x51, 0xc1, 0x51, 0xae, 0xca, 0xc4, 0xfc, 0xa2, 0x3d, 0x2c, 0x6d, 0xc4, - 0xa1, 0xde, 0x66, 0x36, 0xec, 0x22, 0xd0, 0xdf, 0xca, 0x21, 0x69, 0xc5, 0xab, 0xc0, 0x49, 0x21, 0xdd, 0xf3, 0x84, - 0x85, 0x5b, 0x98, 0xdf, 0x7d, 0xe1, 0x76, 0xd8, 0x77, 0xd1, 0x6f, 0x91, 0xbd, 0xd7, 0x83, 0x6e, 0x04, 0xbb, 0xae, - 0x7a, 0xfd, 0x7d, 0x1d, 0x07, 0xfc, 0xdf, 0x4b, 0x26, 0xa4, 0xc0, 0x22, 0xc8, 0x17, 0xbc, 0x3c, 0x00, 0x03, 0x3f, - 0xb0, 0xef, 0x60, 0x12, 0xb2, 0xff, 0x18, 0x26, 0x08, 0xd9, 0x4e, 0xaa, 0x87, 0x76, 0x2c, 0xb8, 0x32, 0x1d, 0xb6, - 0x98, 0xb7, 0x82, 0x34, 0x48, 0x75, 0xef, 0x58, 0x28, 0x51, 0x22, 0xe3, 0xcc, 0x93, 0x2d, 0x01, 0x68, 0xd5, 0x8a, - 0xf0, 0x32, 0x20, 0xbf, 0x6a, 0x14, 0x14, 0xf4, 0x07, 0x98, 0x4d, 0xc1, 0x27, 0xa0, 0x83, 0x8b, 0x09, 0x13, 0x53, - 0x26, 0x1d, 0xb7, 0xab, 0xa3, 0x01, 0xa2, 0xa1, 0x73, 0x1e, 0x16, 0xb3, 0x7c, 0x9a, 0xea, 0xa5, 0x67, 0xbf, 0x81, - 0x2e, 0xda, 0x6d, 0xb3, 0x4f, 0x67, 0x1b, 0x82, 0x85, 0x0d, 0xa4, 0x59, 0x75, 0x12, 0xe1, 0xf9, 0x43, 0x9f, 0x98, - 0x01, 0x69, 0x8e, 0xb7, 0x4d, 0xc8, 0xca, 0x29, 0x08, 0x99, 0xd6, 0xcb, 0x43, 0xfd, 0xd6, 0x79, 0x2f, 0x90, 0xdf, - 0xce, 0xf8, 0x84, 0x0b, 0x46, 0x6b, 0x85, 0xc7, 0x44, 0xa8, 0x60, 0x84, 0xc4, 0x46, 0x40, 0x02, 0xbc, 0xc1, 0x6c, - 0x80, 0xee, 0x27, 0xa5, 0xba, 0xd3, 0x99, 0x63, 0xdc, 0x10, 0x0e, 0xf6, 0xa9, 0x12, 0xb8, 0xc9, 0xa8, 0xd0, 0x3f, - 0x91, 0xa9, 0x21, 0xd9, 0x6b, 0x50, 0x8c, 0x8f, 0x80, 0x0b, 0x32, 0x0b, 0x4a, 0x75, 0x18, 0x20, 0xf7, 0xb8, 0x1f, - 0x88, 0x0f, 0x7e, 0x88, 0xba, 0x1f, 0x71, 0x47, 0x9e, 0x77, 0xd3, 0x42, 0xd3, 0x1e, 0x71, 0x17, 0x34, 0xd8, 0xe6, - 0xfd, 0xfd, 0x4c, 0xef, 0x4d, 0xe5, 0x68, 0x81, 0xbe, 0x4f, 0x41, 0xa6, 0x52, 0x8f, 0xd7, 0x32, 0x55, 0x7b, 0x58, - 0x41, 0x2a, 0x81, 0xb2, 0x8c, 0xd9, 0x3c, 0xce, 0x56, 0xed, 0xb5, 0xb7, 0x51, 0xc4, 0x2f, 0xd2, 0x68, 0x35, 0x6c, - 0x05, 0x38, 0xdb, 0x3c, 0xd1, 0xb5, 0x9b, 0xec, 0x38, 0x14, 0xd1, 0xd1, 0x13, 0xe6, 0xac, 0x4c, 0x10, 0x9b, 0xd7, - 0x5c, 0xcb, 0xcd, 0x3a, 0x3a, 0x1b, 0xf5, 0x1d, 0x97, 0x3e, 0xc9, 0x4d, 0x49, 0xc1, 0x25, 0x2f, 0xdf, 0x5f, 0x25, - 0xaa, 0xf2, 0xb2, 0xec, 0xfb, 0xb4, 0x3a, 0xf3, 0xcc, 0x98, 0x7d, 0xad, 0x92, 0x97, 0xdf, 0x6a, 0x5a, 0x26, 0xff, - 0x9a, 0x06, 0x5b, 0xc7, 0xbe, 0xad, 0x8a, 0xaa, 0xdf, 0x12, 0x87, 0xcc, 0x5b, 0x29, 0x59, 0x81, 0x13, 0x58, 0x13, - 0x17, 0x99, 0x4f, 0xd1, 0x0b, 0xd3, 0x1d, 0x9c, 0x03, 0x00, 0x65, 0xd0, 0x24, 0xf8, 0xbf, 0xf8, 0x1a, 0x63, 0xcc, - 0x57, 0x8c, 0xc6, 0x1c, 0x37, 0x2c, 0xcf, 0x6f, 0xcd, 0x17, 0x78, 0x0b, 0xc8, 0x42, 0x5b, 0xd8, 0xc1, 0x63, 0x4d, - 0xba, 0x1b, 0xd2, 0x4e, 0x7d, 0xfa, 0xde, 0x77, 0xf8, 0xef, 0x82, 0xc2, 0xa4, 0x52, 0x20, 0xc3, 0xe5, 0xaa, 0x9b, - 0x11, 0x5a, 0xad, 0x9b, 0xff, 0xed, 0xee, 0x66, 0x54, 0x1c, 0x99, 0xf7, 0x20, 0xc3, 0x0d, 0x64, 0xac, 0xc5, 0x30, - 0x6c, 0x9a, 0x49, 0xb6, 0x3c, 0x86, 0xe8, 0xa3, 0xa6, 0xae, 0xf1, 0xba, 0x2b, 0x77, 0x37, 0x87, 0x0e, 0x6d, 0x60, - 0x70, 0xd7, 0xfe, 0x1c, 0x1e, 0x06, 0xf2, 0xa2, 0x28, 0xe2, 0x36, 0x3a, 0x44, 0x84, 0x9b, 0x98, 0xb1, 0x5a, 0xf2, - 0xff, 0x15, 0x33, 0x4d, 0x3e, 0x33, 0x1b, 0x9c, 0xac, 0x9b, 0xba, 0x62, 0x05, 0xfd, 0xb3, 0x51, 0xda, 0xbf, 0xca, - 0x3a, 0x6f, 0x05, 0x7f, 0xb4, 0x4a, 0x8c, 0x7d, 0x26, 0x39, 0xb4, 0xbc, 0xd0, 0xc7, 0x11, 0x2f, 0xfa, 0xf7, 0x01, - 0x09, 0x77, 0xfe, 0xb1, 0x8a, 0xba, 0x3a, 0x79, 0xa9, 0xaf, 0x6f, 0x57, 0xc2, 0x1e, 0x12, 0x3d, 0x23, 0x0a, 0x0d, - 0xd7, 0x5c, 0xe7, 0xe5, 0xd2, 0x07, 0x1b, 0x51, 0x41, 0xe7, 0xcb, 0x24, 0x88, 0xc6, 0x86, 0x4d, 0x35, 0x55, 0x17, - 0x9d, 0x33, 0x89, 0x50, 0x46, 0x3c, 0x36, 0x81, 0x3e, 0x0c, 0x16, 0x4b, 0x8d, 0x55, 0xcb, 0xc7, 0x6f, 0xd5, 0xe8, - 0x4f, 0x72, 0x76, 0x89, 0x46, 0x39, 0x7f, 0xc3, 0xac, 0xcf, 0xfa, 0xf8, 0x90, 0xd1, 0xbd, 0x7f, 0x27, 0xb9, 0xac, - 0xbf, 0xec, 0x2b, 0x4d, 0xb0, 0x39, 0x77, 0xa3, 0x36, 0x8f, 0x5d, 0x38, 0xc6, 0x3e, 0x42, 0x40, 0xd0, 0x37, 0x94, - 0xd3, 0x42, 0x0f, 0x31, 0x1d, 0x2d, 0xf7, 0x20, 0xbf, 0xad, 0x88, 0x92, 0x68, 0xd8, 0x2d, 0x8e, 0x87, 0xf4, 0x66, - 0x5b, 0xdc, 0x65, 0x43, 0x1d, 0x07, 0xdd, 0x4a, 0x58, 0x02, 0x8d, 0x29, 0x0d, 0xdf, 0x43, 0x8f, 0x9d, 0x2d, 0x99, - 0x5e, 0xee, 0x8c, 0x62, 0x4f, 0xf0, 0x73, 0x42, 0x7d, 0x03, 0xee, 0x78, 0xe0, 0x4b, 0x1c, 0x6a, 0x69, 0x76, 0x23, - 0x2f, 0xd4, 0x0a, 0xd5, 0xa9, 0xd5, 0xe0, 0x0b, 0x35, 0x7e, 0x3c, 0x23, 0x09, 0xf6, 0xf4, 0x55, 0x8d, 0x8b, 0x8f, - 0xd7, 0x72, 0xa1, 0x1c, 0x5d, 0x64, 0x0b, 0x34, 0x3b, 0x4f, 0xd3, 0x8e, 0x50, 0x8f, 0x95, 0xd4, 0xd5, 0xa7, 0x13, - 0x40, 0x45, 0x28, 0x6e, 0xe5, 0x50, 0x90, 0x7e, 0x96, 0xb9, 0x7b, 0x9c, 0x63, 0xa1, 0x06, 0xd0, 0x99, 0x96, 0x49, - 0xa7, 0x2e, 0xa4, 0xc5, 0x3f, 0x24, 0x98, 0xd8, 0xfe, 0x81, 0xa2, 0x00, 0x4a, 0x52, 0xe7, 0xd0, 0xc8, 0xef, 0xeb, - 0x4e, 0x63, 0x8c, 0x39, 0x78, 0x06, 0x0e, 0x84, 0xf5, 0x94, 0xbc, 0xf6, 0x0c, 0xda, 0x35, 0x94, 0x34, 0xe8, 0xb6, - 0xed, 0x71, 0x69, 0xdd, 0x6f, 0x87, 0x26, 0x8b, 0x84, 0x16, 0xaa, 0x2b, 0xd4, 0xc6, 0xb2, 0x74, 0xd2, 0x9d, 0x75, - 0x43, 0x8a, 0x4f, 0x14, 0x6e, 0x61, 0x2e, 0x5b, 0x95, 0xaf, 0x9c, 0x1b, 0x2c, 0xe1, 0xd2, 0x28, 0xb1, 0xe4, 0xef, - 0x7b, 0x40, 0x10, 0x85, 0xaa, 0x3c, 0x13, 0x44, 0x48, 0x6a, 0x87, 0x03, 0x26, 0x8a, 0xf9, 0x7c, 0x13, 0x09, 0x1a, - 0x7c, 0xf5, 0xa3, 0x82, 0xa4, 0x50, 0x09, 0x08, 0x80, 0xc1, 0x40, 0x0a, 0x28, 0xbf, 0x78, 0x32, 0xee, 0x16, 0x3a, - 0xe7, 0x44, 0xfc, 0x40, 0x09, 0x32, 0xe4, 0xcf, 0x7f, 0x9a, 0x10, 0x06, 0x6d, 0x00, 0xc9, 0x59, 0x70, 0xc0, 0x0c, - 0x0b, 0xfd, 0x69, 0xa4, 0xab, 0x96, 0xc4, 0x52, 0x8b, 0x3d, 0x8f, 0xdb, 0x90, 0x5e, 0xb0, 0xe2, 0x12, 0x4a, 0xba, - 0x31, 0x7c, 0xec, 0x75, 0x48, 0x79, 0xd9, 0x6b, 0x7c, 0xc0, 0xc4, 0xc2, 0x70, 0x91, 0xab, 0x9c, 0xa6, 0xb0, 0x4d, - 0xc0, 0x63, 0x3e, 0x1c, 0xa4, 0xde, 0x10, 0x3c, 0x64, 0x95, 0x8d, 0x4e, 0x32, 0x03, 0x07, 0x7f, 0x9f, 0x0b, 0x09, - 0x29, 0x8c, 0x63, 0x18, 0xe2, 0x37, 0x89, 0xe5, 0x44, 0x36, 0xf3, 0x36, 0xce, 0xd0, 0xe9, 0x07, 0xec, 0x3a, 0x50, - 0x77, 0x36, 0x95, 0x10, 0xec, 0x25, 0x1d, 0x13, 0x51, 0x4a, 0x75, 0x19, 0x14, 0x9f, 0x11, 0xc5, 0xa5, 0x1f, 0xe1, - 0x4c, 0x87, 0x9f, 0xb8, 0x97, 0x01, 0x91, 0x98, 0x89, 0xc8, 0xd9, 0xe0, 0x48, 0x9e, 0xc9, 0x96, 0xb5, 0x74, 0x51, - 0xd3, 0xfe, 0x47, 0x82, 0xee, 0x88, 0x5c, 0x9c, 0x9f, 0x65, 0xa1, 0xee, 0xb4, 0xb2, 0xce, 0x26, 0x8b, 0xd3, 0x0f, - 0xde, 0x75, 0xb7, 0xaa, 0xa2, 0x84, 0xf7, 0x80, 0x06, 0x99, 0xdc, 0xb9, 0x55, 0xcb, 0xd8, 0xea, 0xf6, 0x9d, 0xab, - 0x83, 0xe6, 0xda, 0x41, 0x45, 0x12, 0xf9, 0xf9, 0x26, 0xcf, 0x12, 0x33, 0x8d, 0x3e, 0x40, 0xc9, 0x5a, 0x72, 0x70, - 0xa9, 0x01, 0x6a, 0x0c, 0xf8, 0x72, 0xcf, 0xa4, 0xf6, 0x51, 0x07, 0xbe, 0x13, 0x13, 0x22, 0x17, 0xb9, 0x57, 0x9a, - 0x46, 0x5e, 0x4e, 0xef, 0x36, 0x2c, 0xf2, 0x23, 0xbf, 0xfa, 0x39, 0xb3, 0x3c, 0xa5, 0x67, 0x95, 0x30, 0x8b, 0x15, - 0x1e, 0xd1, 0xcd, 0x30, 0x8f, 0xe0, 0xa3, 0xae, 0xfa, 0x73, 0x03, 0x68, 0xf5, 0xe0, 0x4d, 0x47, 0xa3, 0x08, 0xe0, - 0xb9, 0xe9, 0x2a, 0x71, 0x39, 0x3f, 0xe1, 0x06, 0x86, 0x3d, 0x4c, 0x30, 0x10, 0x12, 0x65, 0x26, 0x0c, 0x00, 0x76, - 0x0e, 0xf1, 0x5b, 0xcc, 0xef, 0x75, 0xc3, 0xa6, 0x5a, 0xe0, 0x9c, 0x29, 0x0b, 0xb8, 0x5e, 0x46, 0x9a, 0x0b, 0xa8, - 0x0b, 0xb2, 0x9f, 0xb4, 0x11, 0x63, 0xfb, 0x4c, 0x09, 0x27, 0x8c, 0x9b, 0x01, 0x8d, 0x0d, 0x9a, 0x95, 0x4f, 0xcc, - 0x4d, 0x02, 0x9f, 0x2a, 0x11, 0xb9, 0xb4, 0x47, 0x22, 0xf9, 0x0c, 0x25, 0x70, 0x84, 0x5f, 0xa4, 0xff, 0x03, 0x44, - 0x7a, 0x3b, 0x27, 0x68, 0x6f, 0x43, 0xc6, 0xfb, 0x52, 0x4b, 0x9c, 0xb4, 0x8c, 0xed, 0x1e, 0x8a, 0xc3, 0xeb, 0x60, - 0x44, 0xd7, 0x58, 0xae, 0x6b, 0x34, 0x7e, 0x49, 0xa9, 0x2e, 0xb6, 0xfb, 0x44, 0x0a, 0x0c, 0x00, 0xbd, 0x37, 0x82, - 0xc6, 0x5b, 0xff, 0xd7, 0x05, 0x0e, 0xb3, 0xba, 0x24, 0x94, 0xf6, 0x40, 0x7c, 0x93, 0x7f, 0x63, 0x1a, 0x0e, 0x0a, - 0xdc, 0xd4, 0x4a, 0xbc, 0xd7, 0x76, 0x77, 0xe9, 0x50, 0xf0, 0xf3, 0x75, 0x18, 0x32, 0x7f, 0xc1, 0x11, 0x36, 0x90, - 0xd3, 0x76, 0xfa, 0x55, 0x35, 0xd2, 0xce, 0x20, 0xc3, 0x15, 0x79, 0x41, 0x2a, 0x89, 0xfc, 0xa8, 0x27, 0xab, 0x4b, - 0x2c, 0xec, 0x14, 0x07, 0x80, 0xee, 0x38, 0x86, 0x4d, 0x1b, 0x1b, 0xcd, 0x13, 0xcf, 0xc1, 0x99, 0xeb, 0x14, 0x00, - 0x78, 0xdf, 0x89, 0xc1, 0x84, 0x39, 0xe6, 0x28, 0x5b, 0x81, 0x7a, 0x3c, 0xc9, 0x1c, 0x1c, 0xe7, 0xa3, 0xfa, 0xf8, - 0x84, 0x6d, 0x56, 0x5c, 0x5e, 0x00, 0xc4, 0xe1, 0x38, 0x29, 0x0c, 0x86, 0x44, 0xbd, 0x4f, 0x45, 0xd6, 0xd1, 0x74, - 0xd1, 0x3c, 0xb9, 0x69, 0xec, 0xde, 0x07, 0xa7, 0x86, 0x04, 0xa8, 0x0a, 0xa6, 0x61, 0xfd, 0x9f, 0x81, 0xe0, 0x25, - 0x7b, 0x57, 0xa0, 0xd9, 0x86, 0x83, 0x52, 0xf8, 0xc8, 0x21, 0xed, 0x90, 0x14, 0xea, 0x70, 0x2e, 0xa2, 0x79, 0x16, - 0x82, 0xa7, 0x0d, 0x64, 0x44, 0x5e, 0x4c, 0xde, 0x6b, 0x57, 0xb6, 0xeb, 0x72, 0x8f, 0xd2, 0x2d, 0xce, 0x1a, 0xab, - 0xd9, 0xa4, 0x47, 0xf4, 0xa0, 0x49, 0x15, 0x40, 0x36, 0x81, 0x0a, 0xaa, 0x90, 0x06, 0x1b, 0x3f, 0x07, 0x40, 0xbd, - 0xdc, 0xf0, 0xb6, 0xc6, 0xbd, 0x2c, 0x13, 0xba, 0xad, 0xd1, 0x50, 0x93, 0x30, 0xb8, 0x0f, 0x0c, 0x3a, 0x83, 0x38, - 0x51, 0x3b, 0xcf, 0x78, 0xe8, 0x24, 0x73, 0x21, 0xf4, 0xf8, 0x0b, 0xfc, 0x22, 0xf1, 0xc2, 0xaa, 0xcc, 0xad, 0xe0, - 0x59, 0x4a, 0xe9, 0x3d, 0x06, 0x6b, 0xf5, 0x6f, 0xf7, 0xb3, 0xa3, 0xd2, 0x40, 0x03, 0x9e, 0x23, 0xc9, 0xdd, 0xbc, - 0x3d, 0xd3, 0xa3, 0x3b, 0xfe, 0xf2, 0xea, 0x1b, 0x4f, 0x97, 0xd9, 0x68, 0x74, 0x54, 0x94, 0xf8, 0xc8, 0xe9, 0xc1, - 0x76, 0x66, 0x2d, 0x71, 0xfd, 0x06, 0x24, 0x80, 0x5d, 0x6d, 0x3c, 0x6d, 0xc3, 0xcb, 0x3a, 0xed, 0x49, 0x13, 0xe4, - 0xca, 0xfe, 0xa3, 0xb6, 0xa7, 0x8f, 0x78, 0xf4, 0xc4, 0x94, 0x23, 0x4a, 0x46, 0x11, 0xa8, 0x7e, 0xa0, 0x00, 0xf2, - 0x12, 0x9a, 0x92, 0x2e, 0x08, 0x7c, 0x65, 0x50, 0xb4, 0x1c, 0x30, 0x06, 0x28, 0x47, 0x7d, 0xa7, 0x39, 0x7d, 0xd3, - 0xb3, 0x5c, 0x09, 0x78, 0x6f, 0x51, 0x55, 0x9e, 0x5b, 0xd9, 0x86, 0x4b, 0x79, 0xed, 0xe2, 0xd0, 0x1a, 0xeb, 0x69, - 0xb5, 0xb6, 0xeb, 0x54, 0x3a, 0x7c, 0x8a, 0x63, 0xe4, 0xba, 0xc6, 0x33, 0x08, 0x68, 0x1e, 0x68, 0x92, 0x77, 0xda, - 0xae, 0xa3, 0x59, 0x0d, 0x87, 0x11, 0x7d, 0x5e, 0x51, 0xac, 0x82, 0x1b, 0x64, 0xbe, 0x55, 0xda, 0xa7, 0x35, 0x18, - 0xd6, 0x29, 0x29, 0x7d, 0x56, 0xbf, 0xd2, 0x13, 0x3f, 0xe5, 0x4d, 0xdf, 0x37, 0x25, 0xe1, 0xdb, 0xe4, 0x4b, 0xea, - 0xd4, 0xa5, 0xe9, 0x71, 0x7a, 0xe4, 0x50, 0x8e, 0x1d, 0xdc, 0xbd, 0xf2, 0x2b, 0xf4, 0x3a, 0x33, 0x50, 0x3f, 0x73, - 0x73, 0xda, 0x5d, 0x2b, 0x6a, 0xca, 0x92, 0xea, 0xe9, 0xeb, 0x5c, 0xbd, 0x0b, 0x6f, 0x6b, 0x22, 0x12, 0xdc, 0x9f, - 0xf1, 0x58, 0x91, 0xb9, 0x16, 0x46, 0x7e, 0x58, 0x45, 0x0d, 0x76, 0xad, 0xd4, 0x88, 0x3b, 0xb3, 0x84, 0x9e, 0x14, - 0xbb, 0xf9, 0x2a, 0x89, 0x60, 0x54, 0x19, 0x99, 0x3c, 0x9d, 0xe5, 0x84, 0xa0, 0x5f, 0x31, 0x88, 0x97, 0x75, 0x8d, - 0x17, 0xd7, 0x6a, 0xca, 0x3c, 0x75, 0xeb, 0x11, 0xd7, 0x9f, 0x6f, 0x43, 0xed, 0x7b, 0x02, 0xae, 0xb4, 0xa9, 0x63, - 0x1e, 0x8d, 0xe1, 0x4b, 0x46, 0x72, 0x5e, 0xd0, 0xd4, 0x04, 0xec, 0x17, 0x10, 0x41, 0x94, 0x7f, 0x34, 0xdb, 0x93, - 0x9c, 0x92, 0xed, 0x2f, 0x7c, 0x73, 0xdf, 0x2a, 0x3e, 0x68, 0x3d, 0xfd, 0xa3, 0x48, 0xd1, 0xf4, 0x92, 0x50, 0x54, - 0x54, 0x06, 0xcd, 0x5b, 0x4a, 0x7d, 0xce, 0xf3, 0x2f, 0x75, 0xc9, 0x92, 0x51, 0x98, 0x25, 0x99, 0x25, 0x7d, 0x00, - 0x34, 0xf5, 0x35, 0xe4, 0x8c, 0xa2, 0xf1, 0x33, 0x4a, 0xfe, 0x35, 0xfc, 0x38, 0xed, 0xee, 0xd1, 0x77, 0xef, 0x4a, - 0x1b, 0x92, 0x40, 0x95, 0xde, 0xd2, 0x1f, 0xd3, 0x52, 0x5f, 0x14, 0x8d, 0x2b, 0x45, 0x3b, 0xc3, 0xfc, 0xb4, 0x78, - 0xb6, 0xe0, 0x17, 0xcf, 0x16, 0xbc, 0xf6, 0x82, 0xb9, 0x89, 0x75, 0xab, 0x82, 0x97, 0xc7, 0xb8, 0xc6, 0x50, 0x62, - 0xa7, 0x76, 0xfc, 0x47, 0x47, 0x60, 0x4a, 0xff, 0xa9, 0x51, 0x06, 0xfa, 0x53, 0x06, 0x4e, 0x33, 0x37, 0xcc, 0x28, - 0xba, 0xf1, 0xc2, 0x08, 0x33, 0xe7, 0x49, 0x13, 0x7c, 0x4d, 0x63, 0x0d, 0x76, 0xb5, 0x9c, 0x65, 0x08, 0x45, 0x8c, - 0x1f, 0x15, 0xb6, 0xa0, 0xed, 0x4c, 0xf8, 0x09, 0x44, 0x2b, 0x40, 0xef, 0x39, 0x37, 0xc7, 0xd1, 0xce, 0x52, 0xdf, - 0x3a, 0xa7, 0x98, 0x3e, 0x9c, 0x88, 0xec, 0x81, 0xa6, 0xee, 0x39, 0x9d, 0xf8, 0x25, 0x91, 0xb1, 0xa8, 0xdf, 0x9f, - 0x43, 0xdb, 0x22, 0xdd, 0xab, 0x11, 0x38, 0x05, 0x20, 0x6f, 0x48, 0x18, 0xfe, 0x45, 0x43, 0x79, 0x8d, 0x3c, 0x52, - 0xa9, 0x4c, 0x9f, 0x77, 0x5a, 0xd3, 0x89, 0x2c, 0x2d, 0xb4, 0x93, 0x31, 0xb6, 0xac, 0x4a, 0x14, 0x5b, 0x99, 0xf7, - 0x0c, 0x12, 0xc9, 0xe7, 0x2f, 0x32, 0x5a, 0xac, 0xa9, 0x21, 0x40, 0xb3, 0x0a, 0xb5, 0x75, 0xe1, 0xe9, 0x15, 0x2a, - 0x06, 0x86, 0x82, 0xb2, 0xef, 0x87, 0xd8, 0x1a, 0x3e, 0xb0, 0x9f, 0xf5, 0x1e, 0x12, 0xaf, 0xbd, 0xc0, 0x44, 0x10, - 0xae, 0x37, 0x05, 0x71, 0x6b, 0x97, 0x64, 0x04, 0x37, 0x54, 0x2f, 0xd8, 0x98, 0x63, 0x67, 0xa7, 0x70, 0x76, 0xec, - 0xec, 0x24, 0x67, 0x16, 0x5d, 0xc9, 0x4c, 0xbd, 0x22, 0xb1, 0x64, 0x85, 0x1d, 0xbc, 0xfc, 0x3a, 0xaf, 0xe4, 0x10, - 0x0b, 0x40, 0x95, 0x96, 0x5c, 0x95, 0x16, 0xc4, 0xcc, 0x35, 0x90, 0x06, 0x75, 0x20, 0xf0, 0x12, 0xbf, 0x99, 0x7c, - 0x00, 0x8c, 0x1d, 0x9c, 0xa3, 0xa3, 0x72, 0xda, 0x18, 0xf6, 0xbb, 0x2a, 0x13, 0x28, 0xaa, 0xe6, 0x83, 0x29, 0xc9, - 0x1b, 0x3c, 0x33, 0x2d, 0xd9, 0x43, 0x21, 0x7c, 0xc1, 0xbb, 0x33, 0x63, 0x8a, 0xf9, 0xed, 0x1b, 0x15, 0xfd, 0xbc, - 0xa2, 0x51, 0xa8, 0x39, 0x54, 0x5f, 0x68, 0x9e, 0xe8, 0x01, 0x99, 0xa6, 0x38, 0xb9, 0xf8, 0x50, 0x0a, 0xf9, 0xf8, - 0x77, 0xf6, 0x05, 0xf1, 0xf6, 0x76, 0xb1, 0xad, 0xc0, 0x09, 0xab, 0xd8, 0x09, 0x6d, 0xae, 0xf9, 0x67, 0xea, 0x20, - 0x6b, 0x66, 0x35, 0xde, 0x19, 0x9f, 0x5f, 0xd5, 0xd8, 0x24, 0x9d, 0x21, 0xa8, 0xe0, 0x69, 0x67, 0x08, 0xda, 0xf2, - 0x93, 0xa4, 0x80, 0x08, 0x34, 0x0e, 0xd4, 0x65, 0x33, 0x91, 0x03, 0x73, 0x01, 0x95, 0x2c, 0x67, 0xb8, 0xe6, 0xb5, - 0x3f, 0x74, 0x2d, 0x32, 0x4f, 0xa0, 0x45, 0xf3, 0x68, 0xa7, 0xa7, 0xea, 0xc8, 0xd7, 0xde, 0xa5, 0xd6, 0x4d, 0x2d, - 0x96, 0x25, 0x5c, 0xcf, 0xc8, 0x4d, 0xac, 0xcb, 0xdb, 0x00, 0xcd, 0xe4, 0xd3, 0x28, 0xfc, 0x89, 0xa9, 0x29, 0x35, - 0x91, 0x31, 0x64, 0x5b, 0x48, 0x55, 0xdb, 0x28, 0xd1, 0x36, 0xa4, 0xdd, 0xce, 0x4f, 0x5b, 0x48, 0xf1, 0x53, 0x5b, - 0x16, 0xd2, 0xfe, 0xf5, 0x0a, 0x4a, 0x49, 0xf8, 0x20, 0x5c, 0x4c, 0x00, 0x84, 0xfb, 0xd0, 0x29, 0x0b, 0x70, 0xe1, - 0x8e, 0xa3, 0xb0, 0xd7, 0x3b, 0x6b, 0xae, 0xa6, 0xc5, 0xe6, 0x07, 0xdd, 0xe7, 0x61, 0x50, 0x8e, 0xf3, 0x9a, 0x3c, - 0x15, 0xdc, 0xf8, 0x23, 0x0b, 0x85, 0x82, 0xf1, 0x6e, 0x22, 0x66, 0xa5, 0xe8, 0xb5, 0x25, 0xc5, 0xda, 0xa9, 0x80, - 0x1a, 0x84, 0xdd, 0x40, 0x55, 0x33, 0xa6, 0x34, 0x95, 0x96, 0x60, 0xf9, 0xbc, 0xd3, 0xf4, 0x9f, 0xd3, 0xf6, 0x47, - 0x42, 0x48, 0xad, 0x6c, 0x43, 0xe1, 0x01, 0x94, 0xe8, 0xb4, 0xcf, 0xfd, 0x45, 0xf0, 0xea, 0xab, 0x4f, 0xd7, 0xd1, - 0x48, 0x8e, 0x12, 0xb3, 0xa8, 0xbb, 0x76, 0x73, 0x7a, 0xfd, 0x9f, 0x91, 0xbc, 0x14, 0xcd, 0x36, 0x4c, 0x03, 0xc5, - 0xcd, 0x5c, 0xf3, 0x5c, 0xd0, 0x45, 0xce, 0x71, 0x41, 0xc5, 0x0b, 0xc7, 0xb5, 0xac, 0xa9, 0xc6, 0x57, 0xba, 0x8a, - 0x41, 0xa5, 0x8c, 0x87, 0x0d, 0x9e, 0x13, 0x8d, 0x30, 0x5c, 0xaf, 0x1c, 0x36, 0x15, 0x4a, 0x5f, 0x09, 0x1c, 0x36, - 0xb5, 0x11, 0x22, 0x59, 0xc3, 0x51, 0xc3, 0x9d, 0x61, 0x49, 0x2b, 0x7d, 0xe5, 0x36, 0x88, 0x76, 0xeb, 0xd3, 0x1c, - 0x3c, 0x0a, 0x3e, 0xb3, 0xc3, 0x23, 0x3c, 0xa9, 0x49, 0x4e, 0x11, 0x3c, 0xc8, 0x93, 0x87, 0xfa, 0x40, 0x77, 0x7e, - 0x29, 0xd1, 0x5e, 0xc1, 0x22, 0xe3, 0x31, 0xcd, 0xf3, 0x10, 0x3a, 0xa6, 0x5b, 0x09, 0x6d, 0xd7, 0x0b, 0xf6, 0xc2, - 0xb8, 0x7a, 0x48, 0x11, 0x4d, 0x09, 0xf4, 0x3f, 0x8d, 0x31, 0x3b, 0xab, 0x97, 0x0f, 0xef, 0x33, 0x66, 0x60, 0x3b, - 0xae, 0xdd, 0x40, 0x81, 0xec, 0xfb, 0xbf, 0x8e, 0xc2, 0x9b, 0x58, 0xf8, 0x69, 0x9f, 0xd4, 0x6f, 0x9d, 0x75, 0x8e, - 0xfd, 0x0b, 0xbb, 0x4d, 0x96, 0x5e, 0x39, 0x8a, 0x6b, 0x14, 0x60, 0x72, 0x2c, 0x3d, 0xaa, 0xef, 0x45, 0xc1, 0x9e, - 0xf0, 0x40, 0x9c, 0xac, 0x62, 0xff, 0x90, 0x5e, 0x1b, 0x00, 0x4c, 0x61, 0x72, 0x9f, 0x56, 0xf6, 0xab, 0x1f, 0x6e, - 0x6c, 0xb0, 0xe5, 0x4a, 0x85, 0x7d, 0x0d, 0x87, 0xeb, 0x55, 0x42, 0xb0, 0xdb, 0xaa, 0xeb, 0x81, 0x90, 0x9b, 0x8c, - 0x37, 0xc5, 0xe0, 0xad, 0x05, 0x5e, 0xb0, 0x5d, 0xc7, 0xc2, 0x9b, 0xd8, 0x6c, 0x7d, 0xa1, 0xf6, 0x82, 0x8f, 0xf2, - 0xa8, 0x3f, 0xcb, 0x83, 0xfe, 0x3c, 0xd6, 0x01, 0xfc, 0xe1, 0x39, 0x61, 0x95, 0x7f, 0x92, 0x18, 0x1c, 0x61, 0x61, - 0xcd, 0x6c, 0x34, 0x34, 0x17, 0xc6, 0x8d, 0x19, 0x3d, 0xf5, 0xc9, 0xc5, 0xa1, 0xb8, 0xd9, 0x5a, 0x02, 0x97, 0xe8, - 0xd4, 0x2c, 0xfd, 0xf7, 0x06, 0x4f, 0x42, 0xa4, 0xbc, 0x55, 0xfa, 0x03, 0xb4, 0x8b, 0xd5, 0x97, 0xff, 0xd3, 0x4a, - 0x38, 0x60, 0x9c, 0x46, 0xe9, 0x22, 0x7e, 0xbf, 0x82, 0x1b, 0xf9, 0x27, 0x5b, 0x58, 0xbd, 0x13, 0x7f, 0xd4, 0xa6, - 0xf6, 0xf4, 0x69, 0x58, 0xe8, 0x0b, 0x63, 0x94, 0xb0, 0x18, 0xc6, 0x4b, 0x63, 0x77, 0x07, 0x33, 0x36, 0x6c, 0x9f, - 0x6f, 0x24, 0x7c, 0xe8, 0x9f, 0x17, 0x82, 0x3a, 0xce, 0xa9, 0xd9, 0xd2, 0x8a, 0x46, 0xbf, 0x5d, 0xc2, 0xd6, 0x40, - 0x02, 0xcc, 0x33, 0xbf, 0x84, 0xc0, 0xc9, 0x24, 0x6a, 0x12, 0x12, 0x58, 0xed, 0x4c, 0xff, 0x6a, 0x55, 0xf1, 0xfb, - 0x7c, 0xe8, 0x10, 0xde, 0xd6, 0xae, 0xe2, 0xfb, 0x42, 0xb8, 0x99, 0xd4, 0xcd, 0x06, 0xe9, 0xc7, 0xb2, 0x4d, 0x63, - 0xe7, 0x00, 0xbe, 0x52, 0x3d, 0x14, 0x90, 0x13, 0xd4, 0x3b, 0x9d, 0xd7, 0x1d, 0xea, 0x88, 0x83, 0x74, 0x31, 0xdb, - 0xa0, 0xa9, 0x37, 0x2b, 0xdf, 0x76, 0xdc, 0x68, 0x46, 0x43, 0xe3, 0xdc, 0x20, 0x85, 0x83, 0x6f, 0x04, 0xe8, 0x6c, - 0xba, 0xc7, 0x0d, 0xd2, 0x49, 0x33, 0x34, 0xfd, 0xd6, 0x11, 0xa5, 0x9a, 0x84, 0xd9, 0x64, 0x0b, 0x8b, 0xa3, 0xb4, - 0xa3, 0xd6, 0x5d, 0xe1, 0xf6, 0xcd, 0x85, 0x83, 0x96, 0x53, 0xb4, 0x49, 0x24, 0x8a, 0xc4, 0x51, 0xcb, 0x29, 0x7d, - 0x74, 0x8a, 0x62, 0x84, 0x8e, 0xb3, 0x8b, 0xcd, 0xab, 0x98, 0x69, 0xb8, 0x12, 0x15, 0x73, 0x7f, 0x81, 0xef, 0xc6, - 0xba, 0x7b, 0x8a, 0x49, 0xa9, 0x74, 0x49, 0x75, 0x17, 0xb3, 0x05, 0xbe, 0x8e, 0xf9, 0x0b, 0xab, 0x57, 0x17, 0xaf, - 0x17, 0x56, 0x93, 0xe9, 0x16, 0xfc, 0xb4, 0x69, 0xfd, 0x16, 0x92, 0x96, 0x03, 0x42, 0x15, 0xff, 0x4c, 0xa6, 0x78, - 0xd5, 0x58, 0x43, 0x4a, 0x36, 0x47, 0x9a, 0x7e, 0xaf, 0xd0, 0xe4, 0x23, 0x8d, 0xce, 0xd2, 0xd5, 0xa9, 0x58, 0xa5, - 0x9f, 0xaa, 0x14, 0xf1, 0xad, 0xda, 0x84, 0x51, 0x41, 0x2b, 0x73, 0x47, 0x75, 0x6f, 0xdf, 0xae, 0x23, 0x44, 0x9f, - 0x97, 0x84, 0x72, 0xec, 0x72, 0xa9, 0x03, 0x1d, 0x20, 0xbe, 0xed, 0x14, 0x30, 0x2f, 0xc7, 0xa8, 0xdd, 0xbc, 0x1b, - 0x0b, 0x09, 0xf9, 0x87, 0xa4, 0x8e, 0x93, 0xd1, 0xa5, 0xf8, 0xb9, 0xee, 0xf9, 0x59, 0xde, 0x89, 0x60, 0x3e, 0xfa, - 0x36, 0x62, 0x50, 0x96, 0x60, 0xf3, 0x5f, 0xe7, 0x81, 0x02, 0x93, 0x40, 0x93, 0x6b, 0x23, 0x4e, 0x35, 0xa9, 0xfa, - 0x5a, 0x82, 0xc2, 0x34, 0xbd, 0xaa, 0x15, 0xb9, 0xa9, 0x96, 0x11, 0x0b, 0xf6, 0x80, 0x3a, 0x53, 0x74, 0x0b, 0xc0, - 0x22, 0x8c, 0xcf, 0xc4, 0xd9, 0xf2, 0x45, 0xa6, 0xd4, 0x58, 0x0e, 0x15, 0x3b, 0xf6, 0xeb, 0xd9, 0xfd, 0xf5, 0x1f, - 0xcd, 0xdf, 0xfe, 0xfa, 0xda, 0xab, 0x47, 0x59, 0x3a, 0x84, 0xfb, 0x9d, 0x75, 0x0c, 0x83, 0x02, 0x44, 0x65, 0xfb, - 0x6d, 0x89, 0xbf, 0xe6, 0x55, 0x94, 0x74, 0xd6, 0xc6, 0xbd, 0x49, 0xc2, 0xa7, 0x35, 0x23, 0xdf, 0x06, 0x16, 0x7c, - 0x6b, 0x98, 0x5d, 0xea, 0xe0, 0x39, 0xd5, 0xa3, 0x9d, 0x02, 0x8e, 0x83, 0xc1, 0xbf, 0x91, 0xda, 0x26, 0x0c, 0x30, - 0xe4, 0x24, 0x9a, 0x2f, 0x74, 0x65, 0x79, 0x9e, 0xa5, 0x64, 0x47, 0x4c, 0xdf, 0x73, 0xc1, 0x8f, 0xbc, 0x2e, 0xf1, - 0x16, 0x6e, 0x08, 0xb0, 0x09, 0xca, 0x1a, 0x03, 0xc7, 0x29, 0x6e, 0xe4, 0xdb, 0x0a, 0xef, 0x21, 0xb0, 0x33, 0x85, - 0x5b, 0x3c, 0xbf, 0xdb, 0x8b, 0x23, 0x04, 0xa7, 0xe0, 0x93, 0x95, 0xd9, 0xac, 0xe8, 0xa5, 0x7f, 0x99, 0x95, 0xf4, - 0xc8, 0x28, 0x77, 0x9b, 0x3c, 0x6d, 0xd9, 0x9a, 0x02, 0x30, 0x83, 0x67, 0x0c, 0x58, 0x70, 0xa7, 0x98, 0xc6, 0x9f, - 0xde, 0xf7, 0x11, 0x6b, 0x75, 0xcb, 0x97, 0xd3, 0x3a, 0x76, 0xef, 0x53, 0x92, 0x40, 0x8d, 0xb3, 0xeb, 0xc7, 0xcb, - 0xb8, 0x6e, 0xdd, 0x67, 0x56, 0xb7, 0x1e, 0x4b, 0xf1, 0xdf, 0x57, 0xab, 0xf3, 0x25, 0x7a, 0x95, 0xf0, 0x26, 0x15, - 0xf5, 0xa4, 0x92, 0x73, 0x8b, 0xbc, 0xbc, 0x72, 0x2e, 0x06, 0xe4, 0xd9, 0x51, 0xbb, 0x51, 0x85, 0x16, 0x5b, 0x63, - 0xb1, 0x3e, 0xcd, 0x24, 0x43, 0x7d, 0xaf, 0xe1, 0x5e, 0x9f, 0x5e, 0xae, 0xc2, 0xf2, 0x34, 0xaa, 0x5d, 0x5a, 0x5f, - 0x6e, 0x94, 0xe4, 0xba, 0xf8, 0x81, 0xb5, 0xb5, 0xf0, 0xe6, 0x60, 0xa3, 0x65, 0x4c, 0xb4, 0x92, 0xd5, 0xd3, 0x4a, - 0x56, 0x4e, 0x13, 0x97, 0x7b, 0xbd, 0xe8, 0x02, 0x39, 0xfe, 0x60, 0xd0, 0xaa, 0xe5, 0x83, 0xc6, 0xac, 0xb6, 0x0f, - 0x3a, 0xa5, 0x5a, 0x9f, 0x14, 0x16, 0xf1, 0xc8, 0x1a, 0x70, 0xb0, 0xb1, 0x56, 0x4a, 0xa6, 0x95, 0x6d, 0x32, 0xae, - 0xd0, 0x0f, 0xa9, 0x6a, 0xd5, 0xfb, 0x1f, 0xa6, 0xb8, 0xc1, 0xd5, 0xc6, 0x9f, 0x05, 0xb9, 0xfe, 0x53, 0x61, 0x47, - 0x39, 0xe8, 0x28, 0xb4, 0xfe, 0xe6, 0x7f, 0xa8, 0xf9, 0x11, 0xdc, 0x0c, 0xb1, 0x95, 0xd9, 0x5b, 0x10, 0xb5, 0x2b, - 0x09, 0xe4, 0x7b, 0xc0, 0xb5, 0x02, 0xa4, 0x62, 0xaf, 0x57, 0xa2, 0x75, 0x9a, 0x04, 0x63, 0x43, 0x90, 0x39, 0x8b, - 0xd8, 0x05, 0xa9, 0x1d, 0xdd, 0x66, 0x46, 0x75, 0xf3, 0x13, 0xaf, 0xf1, 0xa7, 0x4a, 0xa8, 0xbe, 0x7c, 0xa3, 0xb0, - 0x78, 0xc2, 0x03, 0x6a, 0x9f, 0x82, 0x46, 0x75, 0xad, 0x29, 0xa6, 0xb4, 0x20, 0x32, 0x91, 0x31, 0xf8, 0x20, 0x43, - 0x83, 0xb8, 0x5d, 0xb6, 0x5e, 0x90, 0xee, 0xc9, 0xbb, 0xdd, 0xaf, 0x92, 0x5e, 0xda, 0x27, 0x90, 0xfa, 0x16, 0x4d, - 0x60, 0xb6, 0x52, 0xd0, 0x6e, 0x61, 0xbd, 0xbd, 0x60, 0xee, 0x85, 0xb8, 0x72, 0xe1, 0xc0, 0x9a, 0x30, 0xd6, 0xbb, - 0x9a, 0xe7, 0x86, 0xf5, 0xaf, 0x7f, 0xb6, 0x57, 0x8d, 0x5c, 0x54, 0xa6, 0x75, 0x5e, 0x06, 0xc8, 0x4e, 0x5c, 0xe6, - 0xf6, 0x59, 0xca, 0x7b, 0x16, 0x11, 0x34, 0xe4, 0x99, 0x5b, 0xf1, 0x25, 0x6c, 0xfa, 0x1a, 0x36, 0xdf, 0xb5, 0x4f, - 0x6d, 0xb5, 0x62, 0x92, 0x54, 0xa3, 0x3c, 0x71, 0xdd, 0x05, 0x06, 0xed, 0x0f, 0x2e, 0xcd, 0x4e, 0xe7, 0xee, 0x67, - 0xda, 0x03, 0x8e, 0x59, 0x8b, 0xde, 0x36, 0xe0, 0xc8, 0x87, 0xf4, 0x90, 0xba, 0x3b, 0xb9, 0xcd, 0x2d, 0x80, 0xdb, - 0x42, 0x5f, 0x5a, 0x5a, 0xe6, 0x9b, 0x58, 0x6e, 0xae, 0xce, 0x8b, 0x34, 0xbd, 0x50, 0xd6, 0x6d, 0x2f, 0xc1, 0xd1, - 0x26, 0xcf, 0x65, 0x83, 0x6b, 0x54, 0x0a, 0x97, 0x81, 0xff, 0x17, 0x25, 0x45, 0xbf, 0x16, 0x03, 0xc1, 0xd8, 0x31, - 0xe9, 0x2b, 0xbd, 0x3a, 0xe2, 0x4a, 0x89, 0x0e, 0xfc, 0x11, 0x54, 0x27, 0x7b, 0x03, 0x4d, 0xea, 0xcc, 0xde, 0x25, - 0x25, 0x42, 0xbb, 0xa7, 0x69, 0x73, 0x29, 0xa1, 0xfe, 0x7a, 0xc1, 0x87, 0xb7, 0xfd, 0xe2, 0xf6, 0x6c, 0xef, 0x2b, - 0xf7, 0x9e, 0x77, 0x2b, 0x55, 0xb3, 0x3f, 0xcb, 0x89, 0x3d, 0x3b, 0xf6, 0xd3, 0x34, 0x1f, 0xf4, 0xf4, 0x93, 0xfb, - 0x0f, 0x2f, 0xcc, 0x79, 0xc2, 0x0e, 0xb4, 0x76, 0x7b, 0x5c, 0xf3, 0x55, 0x28, 0x15, 0x9c, 0x08, 0x1b, 0x5f, 0x16, - 0xbd, 0x35, 0xe4, 0x82, 0x93, 0x72, 0x12, 0xc5, 0xd4, 0x5e, 0x34, 0xc7, 0x5b, 0x70, 0x93, 0x9f, 0x76, 0x17, 0x81, - 0x14, 0x5a, 0xe5, 0xb9, 0xfa, 0x5f, 0xec, 0x18, 0x8b, 0x97, 0xb9, 0xeb, 0x30, 0xb7, 0x13, 0xaa, 0x88, 0x3f, 0xb7, - 0x44, 0x93, 0xff, 0x70, 0xfc, 0xaf, 0xa3, 0x3f, 0xb5, 0x24, 0x1f, 0x79, 0x3b, 0xa1, 0xe3, 0x89, 0xab, 0x64, 0xf7, - 0x1a, 0x65, 0x76, 0x16, 0x53, 0x4f, 0x55, 0xe7, 0x33, 0x49, 0x66, 0x5d, 0xe5, 0x13, 0xc2, 0xe1, 0xd1, 0xfc, 0x10, - 0xee, 0x96, 0xc5, 0x9a, 0xac, 0xcc, 0x15, 0x65, 0x57, 0x68, 0x9f, 0x53, 0x0f, 0xc4, 0xd6, 0x64, 0x7e, 0xa0, 0x73, - 0x2f, 0x92, 0x91, 0x49, 0xa5, 0x2c, 0x6b, 0x87, 0x48, 0xc3, 0xcb, 0x5d, 0x9e, 0xf2, 0x3e, 0x3f, 0x54, 0x54, 0xb6, - 0x43, 0xe6, 0xb9, 0xfb, 0x3a, 0x33, 0x40, 0xa3, 0x98, 0xa3, 0x2b, 0xe0, 0x96, 0x80, 0x79, 0x6a, 0x34, 0x7b, 0xd6, - 0x5c, 0x95, 0x4c, 0xda, 0xcb, 0x35, 0xf4, 0xb9, 0x67, 0x9a, 0xc9, 0x36, 0x76, 0x11, 0x32, 0x2d, 0x57, 0x65, 0x6b, - 0xe9, 0x33, 0x5f, 0x73, 0xe7, 0x99, 0x07, 0xfc, 0xf4, 0x55, 0x72, 0x89, 0xfa, 0x7a, 0xda, 0x9a, 0xb4, 0x3c, 0x5b, - 0x50, 0xa8, 0x71, 0x8a, 0xc2, 0x1b, 0x28, 0x26, 0x1a, 0xaa, 0xc2, 0x3c, 0x9e, 0xfc, 0x0c, 0x7b, 0x6a, 0xc9, 0xc1, - 0x74, 0xc6, 0x97, 0x9a, 0xee, 0xa7, 0xe6, 0xac, 0x3e, 0x23, 0x07, 0xad, 0xb1, 0x3a, 0xdb, 0x7e, 0xf1, 0xdc, 0x1f, - 0xbc, 0x3f, 0x0d, 0x90, 0xf8, 0x7a, 0x98, 0x7c, 0x8d, 0xad, 0xd4, 0xe4, 0xcf, 0xd7, 0xdf, 0xd7, 0xab, 0x40, 0xb2, - 0x39, 0xdf, 0xbb, 0xbe, 0x0b, 0x16, 0x4a, 0x7f, 0x18, 0x58, 0x31, 0xbb, 0x31, 0x7a, 0x94, 0x22, 0x44, 0xe1, 0x1e, - 0x4b, 0x11, 0x79, 0xab, 0x87, 0xc1, 0xdf, 0x12, 0x71, 0x32, 0x5c, 0xa2, 0x80, 0xc6, 0xe7, 0xd3, 0x4c, 0x2b, 0xae, - 0x88, 0x22, 0x81, 0xbd, 0x16, 0x35, 0x93, 0x6c, 0x13, 0x8c, 0xa0, 0x45, 0x2d, 0x07, 0x32, 0x9c, 0xc5, 0x82, 0x2f, - 0x18, 0x69, 0xce, 0xed, 0x9a, 0xc5, 0xc4, 0x85, 0x8c, 0xb7, 0x57, 0x11, 0x33, 0xda, 0xad, 0x07, 0x0c, 0xe7, 0x33, - 0x03, 0xcd, 0xc5, 0xb8, 0x22, 0x36, 0x7f, 0x84, 0x23, 0x4a, 0xee, 0xb5, 0x90, 0x7d, 0x3f, 0x23, 0xf5, 0x09, 0x43, - 0xc6, 0x24, 0x63, 0xbb, 0x61, 0xc6, 0xe4, 0x7d, 0x91, 0xa7, 0xab, 0xc1, 0xa2, 0xfb, 0x60, 0xb7, 0x16, 0xae, 0x2d, - 0x20, 0xeb, 0x70, 0x18, 0x7a, 0x5f, 0xde, 0x47, 0x81, 0xd2, 0x6c, 0x5f, 0x5f, 0x3d, 0xc0, 0xfe, 0x6e, 0x45, 0x26, - 0x06, 0x24, 0x69, 0x1b, 0x50, 0x78, 0xdc, 0x52, 0xdf, 0xd6, 0xa8, 0xf5, 0x2c, 0xab, 0xb9, 0x97, 0x25, 0xd5, 0x68, - 0xe3, 0x8b, 0x45, 0x7f, 0x31, 0x25, 0x12, 0xc9, 0x3c, 0x08, 0xd6, 0x48, 0xf8, 0x9b, 0xf7, 0x24, 0x75, 0xc5, 0x79, - 0xea, 0x7d, 0xc2, 0x45, 0x4c, 0xa4, 0x37, 0x50, 0xa4, 0x4c, 0x5b, 0x2f, 0xfe, 0xdd, 0x57, 0xe8, 0xf4, 0xe6, 0x63, - 0x13, 0x2b, 0x17, 0x03, 0x40, 0x98, 0x89, 0x16, 0xf1, 0x38, 0xf4, 0xb4, 0x87, 0x58, 0xa4, 0x27, 0x4b, 0xbd, 0xc4, - 0x65, 0x3a, 0x2e, 0x94, 0x2f, 0x57, 0x0b, 0x41, 0xda, 0x50, 0xa4, 0xbe, 0x0b, 0xf9, 0xc2, 0x07, 0x57, 0x82, 0x55, - 0xf2, 0x0d, 0x93, 0xc9, 0xf9, 0xb3, 0xbc, 0x6f, 0x7e, 0x0b, 0x2c, 0x7e, 0xd7, 0xe0, 0x25, 0xee, 0x7d, 0x1f, 0x7c, - 0x8d, 0x06, 0x5a, 0xfd, 0xcf, 0x56, 0x8c, 0x62, 0x88, 0x65, 0xb5, 0x08, 0x3e, 0xd5, 0x6e, 0x7a, 0x8a, 0x96, 0x7c, - 0xc9, 0x93, 0xbb, 0xf0, 0x92, 0xd4, 0xda, 0xc6, 0x61, 0xd6, 0xde, 0xa3, 0xdc, 0xd0, 0x7b, 0xad, 0x16, 0xa4, 0x43, - 0xcc, 0xae, 0xe0, 0x32, 0xe3, 0x05, 0x26, 0xeb, 0xcf, 0x52, 0x58, 0x2c, 0xf2, 0x8b, 0x2a, 0xd2, 0x9e, 0xb2, 0xcc, - 0x87, 0x6c, 0xa6, 0x75, 0x4d, 0xc9, 0xa2, 0x80, 0x4b, 0x94, 0x95, 0x42, 0x6c, 0xe4, 0xe2, 0xb3, 0x56, 0x80, 0x35, - 0xf0, 0x0a, 0x84, 0x62, 0x92, 0x9a, 0xbc, 0x71, 0xf5, 0xdf, 0x9a, 0xfc, 0xab, 0x3a, 0xe6, 0xdf, 0x54, 0x32, 0xff, - 0xfa, 0x7c, 0x4d, 0x1b, 0x7f, 0x6f, 0xf4, 0x25, 0xf1, 0xad, 0x94, 0x80, 0x12, 0x5b, 0x29, 0xbe, 0x23, 0x70, 0x1a, - 0x5d, 0x19, 0xec, 0xc6, 0x03, 0x0b, 0x2b, 0x21, 0xcf, 0x4d, 0x4e, 0x33, 0xad, 0x47, 0xb6, 0xa8, 0xfe, 0xce, 0x1e, - 0x38, 0x49, 0x7a, 0x2d, 0xfd, 0xbb, 0x19, 0x4f, 0x51, 0x20, 0x59, 0xe4, 0x12, 0x3b, 0x91, 0x87, 0xd8, 0x20, 0x40, - 0x90, 0x8b, 0x1c, 0xd0, 0x61, 0xaa, 0x26, 0x12, 0x91, 0xfa, 0xcf, 0x40, 0x0e, 0x2b, 0x60, 0xc0, 0x21, 0x90, 0x23, - 0x31, 0x30, 0x92, 0xe3, 0x13, 0x11, 0x17, 0x92, 0x77, 0x22, 0x2b, 0x42, 0xac, 0x06, 0x76, 0xbc, 0x41, 0x19, 0x6e, - 0x8b, 0xe4, 0x39, 0x0a, 0x14, 0x65, 0xe5, 0x8c, 0x65, 0xc4, 0xd6, 0xea, 0x59, 0xe7, 0xb4, 0x5e, 0xad, 0xa9, 0x73, - 0xc9, 0xd4, 0x69, 0x76, 0xe9, 0x64, 0xbe, 0x00, 0xf6, 0xb5, 0x28, 0x03, 0x7b, 0xd6, 0x01, 0xec, 0xd4, 0x8a, 0x13, - 0x53, 0x71, 0xd9, 0x73, 0xd6, 0x00, 0xd0, 0xd1, 0xb3, 0x06, 0x31, 0x33, 0xe8, 0x5c, 0xb3, 0x5c, 0x83, 0x04, 0x2e, - 0x5c, 0xa2, 0x5e, 0x1a, 0x4a, 0x5b, 0xcf, 0x2c, 0x0a, 0xbf, 0x45, 0xf9, 0xfc, 0x1c, 0x9a, 0x70, 0x11, 0x25, 0xec, - 0xb2, 0xb8, 0xfc, 0x29, 0x5e, 0xe3, 0xa3, 0x5a, 0xd3, 0xca, 0x4b, 0xbb, 0x35, 0xa6, 0xe7, 0x92, 0x82, 0x2d, 0xba, - 0xaa, 0xcf, 0x7b, 0xba, 0xa4, 0x8b, 0xb8, 0x8f, 0x9e, 0x12, 0x05, 0xca, 0xda, 0x15, 0x07, 0x0c, 0x2d, 0xd9, 0x89, - 0xc6, 0xa6, 0x68, 0xe9, 0xed, 0xdd, 0x76, 0xe9, 0xb6, 0x26, 0x43, 0x8e, 0x03, 0x85, 0x1d, 0x01, 0x51, 0x53, 0xdc, - 0x09, 0x8a, 0xba, 0xf2, 0xe1, 0x06, 0xa7, 0x39, 0x9d, 0x19, 0xbe, 0x15, 0x24, 0x9b, 0x08, 0x7c, 0xce, 0x8f, 0xde, - 0x4b, 0xa9, 0xab, 0xaf, 0x74, 0x3a, 0xf4, 0xb0, 0xd9, 0xc0, 0x41, 0x5e, 0xb0, 0x7d, 0x22, 0x75, 0x5a, 0x11, 0x52, - 0x11, 0x7f, 0x5f, 0xf0, 0x55, 0xba, 0xd7, 0x69, 0x43, 0x99, 0xaf, 0x59, 0xb1, 0x03, 0xd9, 0x88, 0xb5, 0x37, 0x52, - 0xde, 0xf6, 0x98, 0x9a, 0xf6, 0x9f, 0x18, 0xb8, 0x3f, 0xb7, 0xbc, 0x5e, 0x3c, 0x85, 0x29, 0x5e, 0x61, 0xa4, 0x6a, - 0xb1, 0x19, 0x8e, 0x39, 0x37, 0xee, 0xe5, 0x9a, 0x3d, 0xeb, 0xa9, 0x14, 0x50, 0x2c, 0x2b, 0x7c, 0xae, 0xca, 0xec, - 0x4d, 0xbe, 0x84, 0x5e, 0x58, 0xde, 0x7d, 0x9f, 0xf5, 0xf5, 0xaa, 0xf3, 0xad, 0x82, 0x57, 0xf5, 0x3b, 0xed, 0x17, - 0xcb, 0x29, 0x0d, 0xaf, 0x7a, 0x34, 0x71, 0x35, 0x98, 0x9d, 0x47, 0xa7, 0x80, 0x9a, 0x29, 0x00, 0x3e, 0x62, 0x53, - 0xd0, 0x15, 0xca, 0x23, 0x70, 0xde, 0x48, 0x98, 0xbd, 0x11, 0x10, 0xbd, 0x59, 0x33, 0x45, 0xf2, 0x45, 0xfb, 0x13, - 0x9b, 0x2e, 0x2e, 0x51, 0xb6, 0xf2, 0x21, 0xed, 0x0e, 0xf1, 0x42, 0x8e, 0x33, 0x2b, 0xa1, 0x6b, 0xc9, 0x6e, 0x9b, - 0xc9, 0xd6, 0x24, 0x4c, 0x00, 0xb0, 0x22, 0x67, 0x91, 0x2f, 0x5d, 0x9f, 0xd9, 0x86, 0xb2, 0x35, 0xc1, 0x08, 0x43, - 0xc3, 0x27, 0xea, 0xde, 0xf9, 0x53, 0xb3, 0xe2, 0xed, 0xc0, 0x88, 0x49, 0xf1, 0x9c, 0x31, 0xfc, 0x3c, 0xfc, 0xf2, - 0xad, 0x4e, 0x59, 0x63, 0x2f, 0xac, 0xcc, 0x0a, 0x22, 0x1e, 0x30, 0x13, 0x20, 0xf9, 0xdf, 0xe5, 0x32, 0xea, 0x8d, - 0xf2, 0x54, 0x62, 0x72, 0x6f, 0x17, 0x18, 0x2a, 0x40, 0x9c, 0x53, 0x4d, 0xa7, 0x14, 0x6f, 0x56, 0x07, 0x61, 0x76, - 0x3e, 0x28, 0x39, 0x62, 0x83, 0x25, 0x0c, 0xf5, 0x61, 0xd7, 0x62, 0x73, 0x89, 0x6b, 0xd9, 0x51, 0x27, 0xb1, 0x16, - 0xca, 0x14, 0x7f, 0xb8, 0xac, 0x30, 0x22, 0xc4, 0x45, 0x4d, 0x27, 0xe2, 0xa3, 0x29, 0xda, 0xd1, 0x6a, 0x02, 0xee, - 0x7a, 0x3a, 0xe5, 0xe3, 0xba, 0xbe, 0xb8, 0x74, 0x0d, 0x32, 0x71, 0x51, 0x60, 0x29, 0x2f, 0x93, 0x5f, 0x19, 0x3f, - 0x02, 0x5b, 0x78, 0xa0, 0x13, 0x1e, 0x27, 0x59, 0x9d, 0x20, 0xc6, 0x40, 0x34, 0x8b, 0xf0, 0x2a, 0x7a, 0x01, 0x92, - 0x9a, 0xe9, 0x32, 0x38, 0x6d, 0x5b, 0xae, 0x18, 0x49, 0xfb, 0xba, 0x12, 0x5d, 0x4b, 0xbe, 0x54, 0x84, 0x7c, 0xd9, - 0x0e, 0x67, 0x77, 0x1e, 0x9d, 0x6e, 0x67, 0x56, 0xc4, 0x8d, 0x4f, 0x3a, 0x09, 0x2e, 0x83, 0xbe, 0x21, 0xd9, 0xa1, - 0x3c, 0xa0, 0xad, 0x5f, 0xe6, 0x64, 0x4c, 0xbe, 0xe2, 0x6c, 0x43, 0x8a, 0x4a, 0x9e, 0x29, 0xdd, 0xce, 0x47, 0x57, - 0x71, 0xaa, 0x37, 0x58, 0x0f, 0x42, 0xe5, 0x00, 0x43, 0x6a, 0x12, 0x7e, 0xc4, 0xad, 0xdc, 0x58, 0xfb, 0xae, 0x4e, - 0x2a, 0xbc, 0x82, 0x33, 0x1d, 0xca, 0xb6, 0x95, 0xb9, 0xcb, 0x6c, 0x94, 0x64, 0xcb, 0x92, 0xe0, 0xbf, 0x5b, 0x45, - 0xb1, 0xe6, 0xc1, 0x79, 0x18, 0x95, 0xef, 0x8b, 0x5c, 0x3d, 0xac, 0xa7, 0xec, 0xed, 0x24, 0x94, 0xf0, 0x89, 0xa5, - 0xe3, 0xf4, 0xdb, 0x01, 0xe3, 0x94, 0x9d, 0x48, 0x5a, 0x20, 0xa7, 0xff, 0xc2, 0xb7, 0x9d, 0x06, 0x21, 0xc4, 0x3b, - 0x65, 0xbd, 0x5a, 0x00, 0x38, 0x97, 0x32, 0x3e, 0xab, 0xff, 0x02, 0x54, 0xb2, 0xeb, 0x8b, 0x71, 0x3f, 0xe0, 0xd1, - 0xa6, 0x95, 0xdf, 0x8e, 0x24, 0xcc, 0xee, 0xba, 0x7c, 0x03, 0x3d, 0x8e, 0x65, 0x07, 0x2b, 0xec, 0xab, 0x04, 0x79, - 0xe6, 0xb9, 0x48, 0x81, 0x65, 0x13, 0xc5, 0xfc, 0xa6, 0xa1, 0x4f, 0xc0, 0xc1, 0x4c, 0x77, 0x06, 0x8d, 0xd9, 0x55, - 0xad, 0xbe, 0xc6, 0xf1, 0xa2, 0x2c, 0x09, 0x5e, 0xa4, 0x31, 0x0a, 0xab, 0xb9, 0x9c, 0x87, 0xaa, 0x42, 0xe5, 0xcc, - 0x75, 0x33, 0xd6, 0xd5, 0x6d, 0xb6, 0xbb, 0x47, 0x9b, 0x13, 0xa0, 0x4a, 0x6f, 0xcc, 0x58, 0x82, 0x8a, 0xe8, 0xa0, - 0x9f, 0xb1, 0xbb, 0xca, 0xa0, 0xe3, 0x95, 0x35, 0x9f, 0x88, 0x01, 0xb7, 0x36, 0xa3, 0x22, 0x4a, 0x28, 0x1a, 0xeb, - 0xac, 0x42, 0xb5, 0xd7, 0x83, 0x6d, 0xab, 0x36, 0x10, 0x6d, 0x32, 0xa9, 0x40, 0x52, 0x11, 0xfe, 0xa2, 0xfc, 0xda, - 0xd2, 0x5e, 0xcf, 0x74, 0x46, 0x3a, 0xa8, 0x4a, 0x73, 0xce, 0x9c, 0x33, 0x3b, 0x60, 0x31, 0x5e, 0x1f, 0x6f, 0x84, - 0xa7, 0x80, 0x6c, 0x11, 0xde, 0x1c, 0xc0, 0xed, 0x6d, 0x2b, 0x0a, 0x07, 0xbb, 0xe9, 0x21, 0xaf, 0xd2, 0x36, 0x8e, - 0x80, 0x01, 0x79, 0x89, 0x93, 0xb9, 0x05, 0x12, 0x15, 0x06, 0x7e, 0x85, 0x60, 0x83, 0x25, 0x3b, 0x29, 0x2d, 0x2e, - 0x8f, 0xed, 0x62, 0x87, 0x4f, 0xcb, 0x7a, 0xb9, 0xf6, 0x06, 0xfd, 0xb5, 0xc6, 0x39, 0xf8, 0xd8, 0x21, 0x74, 0xf9, - 0xc7, 0x6c, 0x95, 0x26, 0xe9, 0xdf, 0x8a, 0x31, 0x2d, 0x2f, 0x92, 0x9c, 0x66, 0xdc, 0xe9, 0x5b, 0xe3, 0xc2, 0x47, - 0xef, 0xb9, 0x64, 0xf1, 0xbd, 0xdc, 0x1e, 0x89, 0x7e, 0x25, 0x18, 0xfa, 0xcb, 0xfa, 0x7a, 0x32, 0x88, 0xb6, 0x9d, - 0xa6, 0x0b, 0xcd, 0x2b, 0xb8, 0x94, 0xa2, 0xe2, 0x56, 0xc3, 0x0f, 0x05, 0x14, 0x49, 0xf9, 0xa8, 0x7d, 0x2c, 0x91, - 0xb5, 0x58, 0x39, 0x93, 0xed, 0x3f, 0xcb, 0x71, 0x86, 0x21, 0xef, 0xac, 0x55, 0x65, 0x55, 0xf9, 0x44, 0x17, 0xb6, - 0x45, 0xaf, 0xd4, 0x0b, 0xb9, 0xec, 0x18, 0x76, 0xbe, 0xb5, 0x37, 0x40, 0x89, 0xff, 0xe5, 0x96, 0xb7, 0xe1, 0x4c, - 0xb0, 0x0b, 0x59, 0x1d, 0x80, 0x0f, 0x8a, 0x52, 0xb2, 0xcd, 0x0b, 0x81, 0x48, 0xd7, 0x5d, 0x30, 0x8f, 0x3a, 0x62, - 0x51, 0xf0, 0x4b, 0xf7, 0x2a, 0xbc, 0xea, 0x27, 0x67, 0x51, 0x19, 0xa0, 0x59, 0x9e, 0xc7, 0x23, 0xd7, 0xc4, 0xc2, - 0xa2, 0xe4, 0xa5, 0x9a, 0xaf, 0xc6, 0x27, 0x36, 0x85, 0xad, 0x16, 0x14, 0xa7, 0xc9, 0x26, 0xe9, 0xfe, 0x40, 0x61, - 0x14, 0x16, 0xf8, 0x8f, 0x6b, 0x9f, 0x98, 0x67, 0x90, 0x68, 0x2e, 0x00, 0xa5, 0xc4, 0xfb, 0x42, 0xbd, 0x1e, 0x55, - 0x59, 0x72, 0xa0, 0xb0, 0xe3, 0x1b, 0x59, 0xbd, 0xf2, 0x3b, 0x95, 0x1a, 0x15, 0xf4, 0xfa, 0xa7, 0xb2, 0xcb, 0x02, - 0xa0, 0xed, 0xa0, 0x5a, 0x4d, 0x2d, 0xeb, 0x29, 0x17, 0xdd, 0xe1, 0x0e, 0x5e, 0xf9, 0x4e, 0xeb, 0x39, 0x9a, 0x0b, - 0x4b, 0x88, 0xb3, 0xef, 0xb1, 0x2c, 0x59, 0xce, 0x7e, 0xd6, 0xbc, 0xd0, 0x8d, 0x32, 0x7d, 0xb9, 0xd7, 0xf3, 0x99, - 0x2c, 0x5c, 0x95, 0x00, 0x33, 0xf2, 0xea, 0x72, 0x00, 0xe0, 0x13, 0x53, 0xba, 0xc2, 0x68, 0x1d, 0x47, 0x59, 0xe6, - 0x98, 0xc6, 0x3e, 0xf7, 0x90, 0xa6, 0x6f, 0x4e, 0xdc, 0x22, 0x97, 0xda, 0x6b, 0xb3, 0x0a, 0xc7, 0xc9, 0xc4, 0x3a, - 0xbe, 0xc8, 0x74, 0xa6, 0x07, 0x49, 0x97, 0x5e, 0xce, 0x80, 0x4c, 0xad, 0xee, 0xc0, 0x5c, 0x35, 0x09, 0xa0, 0xa7, - 0xef, 0x8a, 0x2c, 0x8f, 0xc9, 0xfe, 0xbc, 0x37, 0xbb, 0xf8, 0x8c, 0x74, 0xa3, 0x53, 0xf4, 0xd9, 0x31, 0x2d, 0xd7, - 0xac, 0x48, 0x00, 0x28, 0x17, 0x84, 0xbd, 0x71, 0x4c, 0x62, 0x0b, 0x5a, 0xb6, 0xeb, 0x05, 0x08, 0x1d, 0x01, 0x48, - 0xee, 0x8b, 0x02, 0xdf, 0xcf, 0xce, 0x35, 0x2f, 0x86, 0x2c, 0x7c, 0x9e, 0xa1, 0x5f, 0x0f, 0xb8, 0x2e, 0x13, 0x82, - 0x89, 0x7c, 0x86, 0x86, 0xbf, 0xca, 0xbc, 0x89, 0xb3, 0x11, 0xd1, 0xb5, 0xbf, 0x4f, 0xe9, 0xe3, 0x0a, 0x8e, 0x1f, - 0x2a, 0xe0, 0xf7, 0x03, 0xb3, 0x37, 0xd4, 0x3f, 0x7a, 0x31, 0xa8, 0x86, 0x47, 0x96, 0x9f, 0x2a, 0x30, 0x9a, 0x39, - 0xf0, 0x00, 0x11, 0x44, 0x92, 0xd9, 0x57, 0x71, 0x5b, 0xda, 0x1d, 0x46, 0x01, 0x01, 0x8c, 0x59, 0x93, 0x5d, 0x08, - 0x13, 0x80, 0x75, 0xee, 0x9b, 0xd1, 0x45, 0x0f, 0x7a, 0x6c, 0xf3, 0x51, 0xb9, 0x16, 0xe5, 0x18, 0x8c, 0x69, 0xcc, - 0x17, 0x36, 0xec, 0x09, 0xb6, 0xd1, 0x08, 0x47, 0xaf, 0x60, 0x08, 0x97, 0x34, 0xee, 0x55, 0x3a, 0x17, 0xbe, 0xf7, - 0x2a, 0xca, 0x82, 0x18, 0xbb, 0x6f, 0xc6, 0xa9, 0x01, 0xb2, 0x64, 0xff, 0xb4, 0x60, 0xc9, 0xa9, 0xb3, 0xaf, 0xe9, - 0xe4, 0xd9, 0xc7, 0xdc, 0xf0, 0x4e, 0x9e, 0x83, 0x43, 0xd3, 0x52, 0x4f, 0xeb, 0xfc, 0x0d, 0x5a, 0x68, 0x05, 0xf3, - 0x82, 0x76, 0x76, 0x06, 0x58, 0x5a, 0xa1, 0xb6, 0xa6, 0xb6, 0xe4, 0x0d, 0xfb, 0xa1, 0x95, 0x95, 0x62, 0x30, 0x0d, - 0x20, 0x89, 0x1d, 0x88, 0x46, 0xa1, 0xfd, 0xd0, 0xf7, 0xb7, 0xb9, 0xef, 0x65, 0x89, 0xdf, 0xba, 0xbe, 0x8e, 0x95, - 0x56, 0x8f, 0x7f, 0x3e, 0x0f, 0x97, 0x24, 0x62, 0xbf, 0x56, 0xc1, 0xca, 0x64, 0x63, 0x05, 0x2e, 0xaa, 0xcf, 0x38, - 0x96, 0x7c, 0x28, 0x38, 0xe5, 0x66, 0x85, 0x94, 0x99, 0xec, 0xf3, 0xb0, 0x80, 0xc6, 0xda, 0x8c, 0x6a, 0x50, 0x2b, - 0xe6, 0x60, 0x4e, 0x8f, 0x0a, 0x84, 0xc7, 0x14, 0x40, 0x95, 0x2f, 0x4e, 0x7d, 0xf9, 0x75, 0xce, 0x91, 0x90, 0x4b, - 0xd3, 0xd4, 0xfd, 0xef, 0x52, 0x91, 0xf3, 0x0e, 0x82, 0x10, 0xc3, 0x23, 0xe8, 0x1b, 0x94, 0x5f, 0xfc, 0x89, 0xbf, - 0xf8, 0xba, 0xf8, 0xb9, 0x60, 0xe6, 0x9b, 0x66, 0x39, 0xb3, 0x78, 0x8b, 0x59, 0x6f, 0x1d, 0xb2, 0x15, 0x61, 0x91, - 0xd2, 0x4c, 0x43, 0xce, 0x04, 0xcd, 0xb3, 0xa0, 0x80, 0xcd, 0x7c, 0xae, 0xf5, 0x26, 0x20, 0x3d, 0x90, 0x04, 0xf7, - 0xaf, 0x12, 0x5d, 0x0e, 0x54, 0x4d, 0x47, 0x51, 0x0a, 0x1e, 0x80, 0x9b, 0x4a, 0xa8, 0x01, 0xea, 0xa4, 0xe1, 0x29, - 0xb4, 0x62, 0x2c, 0xc1, 0xb3, 0x2c, 0x62, 0x9d, 0x06, 0x30, 0x1a, 0x49, 0x3c, 0xac, 0x51, 0xb8, 0x3a, 0xcf, 0x26, - 0x63, 0x56, 0xc7, 0xbc, 0xad, 0x2e, 0xb2, 0x3b, 0xd2, 0x04, 0x9f, 0xb9, 0x4e, 0xc5, 0xde, 0xee, 0x38, 0x60, 0x4a, - 0x4d, 0x03, 0x07, 0x99, 0x4a, 0xf3, 0x40, 0xa1, 0x69, 0x5c, 0x0b, 0x30, 0xd0, 0xc9, 0x59, 0x2d, 0x4a, 0x88, 0xad, - 0xb8, 0x01, 0x10, 0x47, 0x3a, 0xfa, 0x20, 0x85, 0x0d, 0x3f, 0x30, 0x96, 0xfc, 0x11, 0xf0, 0x98, 0x3f, 0x78, 0x08, - 0x08, 0x51, 0xda, 0x08, 0x79, 0x62, 0x0d, 0x5a, 0x59, 0x2c, 0x0c, 0x7e, 0x2b, 0xda, 0xcb, 0x9e, 0xe2, 0xf3, 0x8d, - 0xba, 0x1f, 0x08, 0x51, 0xb7, 0xc1, 0x9a, 0x45, 0x46, 0x73, 0x37, 0xf8, 0xaf, 0xf9, 0x3d, 0x49, 0xa4, 0x50, 0x2c, - 0x15, 0xb9, 0x8f, 0x28, 0x6f, 0x31, 0x6e, 0x21, 0x6f, 0xed, 0xe0, 0xe3, 0x56, 0x18, 0xa8, 0x23, 0xad, 0x16, 0x92, - 0xf2, 0x16, 0x53, 0xcd, 0xb8, 0xa3, 0x60, 0x35, 0x51, 0x6a, 0xf8, 0x1c, 0x49, 0xba, 0x7a, 0x8e, 0xcd, 0x4c, 0xfc, - 0x63, 0x66, 0x9a, 0xa7, 0x26, 0x1f, 0x15, 0x75, 0x93, 0xd9, 0xb8, 0xb1, 0xe0, 0xe8, 0x09, 0xcf, 0x84, 0xbc, 0x4b, - 0x1d, 0xed, 0x54, 0x6f, 0x21, 0xe5, 0x21, 0xc3, 0x14, 0xc4, 0x7a, 0x40, 0xef, 0x68, 0x6a, 0x74, 0xeb, 0x6e, 0x4c, - 0x0f, 0x12, 0x88, 0xd5, 0xa9, 0x1d, 0xa1, 0x2d, 0x6e, 0x0f, 0x31, 0x5c, 0x56, 0x5d, 0x0a, 0x14, 0xa9, 0x55, 0x9e, - 0xf2, 0x59, 0x82, 0x12, 0xb0, 0x49, 0x51, 0x9f, 0x73, 0x1c, 0xd6, 0x45, 0x41, 0xed, 0x33, 0x85, 0x48, 0x16, 0xca, - 0x34, 0x5f, 0x06, 0x5f, 0x44, 0x33, 0x68, 0x00, 0xc9, 0x80, 0xaf, 0xf6, 0x9b, 0x6b, 0xe8, 0x46, 0x20, 0x6f, 0xb3, - 0x26, 0xca, 0xe6, 0xc3, 0x39, 0xc4, 0xb6, 0xb6, 0xf7, 0x1b, 0xb4, 0x9e, 0x85, 0x7a, 0x97, 0xf2, 0xac, 0xb0, 0xad, - 0x5c, 0x05, 0x5a, 0x72, 0x72, 0xb2, 0x91, 0xc7, 0x40, 0x1d, 0x61, 0xdb, 0x63, 0x64, 0x4e, 0xe0, 0x5f, 0x6a, 0xb3, - 0x16, 0x84, 0x67, 0x36, 0xb2, 0xe0, 0x0f, 0x74, 0x31, 0xd8, 0x30, 0xde, 0xc4, 0x3f, 0xa3, 0xec, 0xb9, 0x7b, 0xed, - 0x25, 0xab, 0xa0, 0x1e, 0x8e, 0xda, 0x09, 0x9d, 0xb6, 0xc9, 0xb7, 0x2d, 0x08, 0x84, 0xe4, 0xe3, 0xa5, 0x88, 0xee, - 0x84, 0x59, 0xd2, 0xaa, 0x96, 0xd8, 0xf3, 0xe6, 0xa7, 0xf1, 0x9e, 0xd7, 0xfb, 0x82, 0x85, 0xa8, 0xb9, 0x37, 0x1b, - 0xd6, 0xf5, 0xc6, 0xf2, 0xee, 0xbd, 0x32, 0xb3, 0xe8, 0x6c, 0xcc, 0x65, 0x01, 0x93, 0xea, 0x9e, 0x40, 0x2f, 0x96, - 0x27, 0xfd, 0xb1, 0xcd, 0x54, 0xe3, 0x58, 0x24, 0xf3, 0x28, 0x4e, 0x09, 0x6f, 0x0c, 0x68, 0xf4, 0x6b, 0x8a, 0x24, - 0x91, 0x79, 0x06, 0x8b, 0xcc, 0x58, 0x79, 0x1b, 0x7c, 0x43, 0xcc, 0x4c, 0x44, 0x34, 0xc8, 0x4e, 0x60, 0x8e, 0xc6, - 0x02, 0xe1, 0x0f, 0x71, 0x86, 0x26, 0xbe, 0xa3, 0x9b, 0x97, 0x9c, 0x4c, 0x5d, 0x80, 0x0b, 0x70, 0xbb, 0x7a, 0x06, - 0xfd, 0x70, 0xb3, 0x55, 0x84, 0x94, 0x92, 0x0a, 0x5c, 0x74, 0xac, 0x35, 0xf9, 0x3b, 0xa5, 0x98, 0x68, 0xdd, 0x88, - 0xea, 0x4b, 0x07, 0x60, 0xdf, 0x1d, 0xd4, 0xe7, 0x96, 0x34, 0x56, 0x92, 0xcf, 0x83, 0x2e, 0x35, 0x7d, 0x10, 0x2b, - 0xe4, 0x19, 0x9f, 0x1c, 0x81, 0x70, 0x87, 0xdf, 0x5d, 0xda, 0x4c, 0xd0, 0xdb, 0x44, 0x1b, 0x97, 0x0c, 0xf0, 0x8b, - 0x1c, 0x23, 0xec, 0x62, 0x86, 0x9c, 0xad, 0x19, 0xbf, 0x4c, 0x8e, 0x8c, 0x17, 0x84, 0x3f, 0x15, 0x9e, 0x97, 0x76, - 0xd3, 0x04, 0xc4, 0x3f, 0x10, 0x5d, 0x34, 0x18, 0x9d, 0x04, 0xf3, 0xcc, 0xcb, 0x65, 0x71, 0x51, 0x55, 0xd0, 0x60, - 0x9f, 0xbb, 0x5e, 0xc9, 0x96, 0x6f, 0xcf, 0xff, 0x71, 0x6e, 0x75, 0x53, 0xe2, 0xc8, 0x43, 0x57, 0xe2, 0xaa, 0x97, - 0x7b, 0x7e, 0xd2, 0xbd, 0xd5, 0x4e, 0xb8, 0xdf, 0xc8, 0x55, 0x5f, 0x21, 0x84, 0x7f, 0xf2, 0x07, 0x0d, 0xc1, 0xca, - 0x23, 0x58, 0xb3, 0x94, 0x72, 0xc7, 0xd5, 0x72, 0xdb, 0x0f, 0xf6, 0x3e, 0x60, 0xa5, 0x73, 0x17, 0x16, 0xe3, 0x09, - 0x12, 0x94, 0x17, 0xca, 0xd7, 0x62, 0x8c, 0xb3, 0xdd, 0xac, 0xc6, 0xa1, 0x15, 0xc4, 0x63, 0xcf, 0x72, 0xb8, 0xa8, - 0x43, 0x84, 0x2e, 0x1d, 0x5c, 0x5e, 0xc9, 0xe2, 0x81, 0xa3, 0x4c, 0xd3, 0x18, 0xcf, 0x56, 0x20, 0x39, 0x79, 0xfa, - 0xf0, 0x40, 0x8f, 0x90, 0x80, 0xd1, 0xe7, 0xce, 0x5b, 0x4a, 0x86, 0x6d, 0xd5, 0xb7, 0x09, 0xa0, 0xcd, 0x17, 0x34, - 0x87, 0x68, 0xc5, 0xc8, 0x34, 0x78, 0xed, 0x5d, 0x6c, 0xb5, 0x92, 0x39, 0x09, 0xad, 0x46, 0xac, 0x41, 0x52, 0xbf, - 0xd3, 0xa4, 0x0f, 0xe6, 0x67, 0xb9, 0x85, 0xda, 0xc9, 0x58, 0xed, 0x84, 0x33, 0x3b, 0x9d, 0xf3, 0x2d, 0xfb, 0xf5, - 0x8c, 0xe9, 0x3c, 0x47, 0x36, 0x5f, 0x7a, 0xcd, 0xd7, 0x9f, 0x87, 0xfc, 0xd3, 0x53, 0x79, 0x9b, 0xb0, 0x80, 0xfd, - 0x36, 0x35, 0xa8, 0x27, 0xd6, 0xed, 0x92, 0x6a, 0x29, 0x9a, 0x63, 0x71, 0x44, 0x11, 0xb1, 0x5d, 0xc0, 0x11, 0x7a, - 0x1f, 0xf1, 0x6b, 0x56, 0x67, 0xa2, 0xe4, 0x3c, 0x83, 0x77, 0x0a, 0x63, 0x25, 0x92, 0xbc, 0x22, 0x8d, 0x4c, 0xa4, - 0x75, 0x43, 0xde, 0x26, 0x79, 0xa9, 0xc9, 0xe9, 0xe8, 0x74, 0xec, 0x3d, 0xfe, 0x67, 0x40, 0x25, 0x21, 0x50, 0x81, - 0xd2, 0x3e, 0xdf, 0x1d, 0x31, 0x44, 0x93, 0x29, 0x4a, 0x91, 0xac, 0xa5, 0xe8, 0x2f, 0x31, 0x2b, 0x4d, 0x59, 0xdd, - 0x9d, 0x80, 0xeb, 0x36, 0x4e, 0x12, 0x77, 0x1b, 0x33, 0x99, 0x87, 0x13, 0xd8, 0x9f, 0xcb, 0x75, 0x7e, 0x88, 0xc1, - 0x96, 0x87, 0xa7, 0x25, 0x82, 0x5f, 0x47, 0x15, 0xbc, 0x1e, 0x44, 0x10, 0x1c, 0x67, 0x23, 0x22, 0xf6, 0x9b, 0x21, - 0x7b, 0x27, 0x2f, 0x00, 0x28, 0xce, 0xef, 0xe3, 0xe6, 0x79, 0x9d, 0x9f, 0x00, 0x45, 0x38, 0x2a, 0xfc, 0xb0, 0x33, - 0x82, 0x41, 0x15, 0xde, 0xc9, 0x22, 0x6b, 0xcc, 0x8e, 0x97, 0x2b, 0x9a, 0x73, 0x32, 0xb3, 0x55, 0x4f, 0x48, 0x22, - 0x48, 0x33, 0xcc, 0x7a, 0x10, 0x8c, 0x18, 0xbf, 0xac, 0x27, 0x83, 0xd1, 0x59, 0x92, 0x2c, 0x6c, 0x1a, 0x4e, 0xa4, - 0x6d, 0x84, 0x18, 0xc9, 0x76, 0x29, 0xc5, 0xa4, 0x6b, 0xcf, 0x36, 0x67, 0xcd, 0x17, 0x42, 0x51, 0xc0, 0x6e, 0x29, - 0x81, 0x18, 0xe7, 0x50, 0x42, 0xc3, 0x68, 0xca, 0x9f, 0x8b, 0x13, 0xc4, 0x3a, 0xf2, 0xd2, 0x54, 0x68, 0xb3, 0xc1, - 0x9d, 0x0f, 0x48, 0x11, 0xc6, 0xfd, 0x19, 0x38, 0x66, 0xb2, 0x52, 0x5c, 0x32, 0x87, 0xb7, 0x3b, 0x52, 0xac, 0x63, - 0xf6, 0x82, 0x60, 0xf0, 0x1c, 0x5b, 0x98, 0x58, 0xa4, 0xa2, 0x8f, 0x24, 0x15, 0x5c, 0x96, 0xea, 0xfe, 0x3d, 0x6c, - 0xbb, 0x6d, 0x0a, 0x62, 0x9b, 0x93, 0x30, 0x53, 0x8d, 0xc7, 0xd5, 0xa3, 0x0d, 0xb8, 0xfe, 0x1c, 0xa0, 0x91, 0x26, - 0xab, 0x74, 0x65, 0x7d, 0x73, 0xbf, 0xa9, 0xc7, 0x8a, 0x79, 0x7c, 0xf0, 0x89, 0x80, 0x35, 0xee, 0x80, 0x29, 0x6b, - 0x30, 0x24, 0x1c, 0x8a, 0xb0, 0xd9, 0x01, 0x98, 0x62, 0xfd, 0x28, 0x22, 0x71, 0xef, 0xa2, 0x4d, 0x02, 0x32, 0x2d, - 0xd7, 0x39, 0x37, 0x4b, 0xfd, 0xce, 0x24, 0xfc, 0x24, 0x86, 0x30, 0xc6, 0x21, 0x8e, 0x10, 0x8d, 0x25, 0xea, 0xf5, - 0x6b, 0x3c, 0xf6, 0xd2, 0x92, 0xff, 0xc9, 0xc6, 0xf9, 0x9d, 0x12, 0x9a, 0x63, 0xcb, 0xa6, 0xcd, 0x16, 0x74, 0xfb, - 0x5a, 0xd2, 0x52, 0xec, 0x2a, 0x8a, 0x4f, 0x1e, 0xf9, 0x41, 0x65, 0x78, 0x7f, 0x77, 0x49, 0xac, 0x07, 0xad, 0x24, - 0xb8, 0x35, 0x23, 0xbc, 0xbf, 0x4b, 0x27, 0xfc, 0x70, 0x10, 0xf1, 0x6e, 0x91, 0xd1, 0xb6, 0x98, 0x9a, 0x6d, 0x60, - 0x71, 0xe9, 0x43, 0x05, 0xb0, 0x8b, 0x0c, 0xeb, 0xf4, 0x1a, 0x77, 0xbb, 0xd2, 0xec, 0x1e, 0x21, 0x3c, 0x49, 0x95, - 0x9d, 0x6b, 0xb3, 0x98, 0xcb, 0x02, 0x3a, 0x49, 0xa5, 0x22, 0x9a, 0x49, 0xe3, 0xd0, 0x52, 0xe1, 0xdf, 0x05, 0x49, - 0x6a, 0x63, 0xdc, 0xfd, 0xd9, 0x19, 0x46, 0x54, 0x41, 0x4d, 0x49, 0x49, 0x1d, 0xc6, 0x64, 0xc7, 0x20, 0xfe, 0xb7, - 0xc7, 0x1e, 0x52, 0xaf, 0x59, 0x68, 0x99, 0x51, 0x1e, 0x7f, 0x37, 0x4c, 0x3b, 0x59, 0xe3, 0x91, 0xd7, 0xf5, 0x4e, - 0xd1, 0xd6, 0xb7, 0x70, 0xb6, 0xa1, 0x1b, 0xde, 0x74, 0xf5, 0x0c, 0xe3, 0xf1, 0x15, 0xfc, 0xbc, 0x81, 0x49, 0x4f, - 0xa4, 0x26, 0xee, 0x7c, 0x53, 0x72, 0x62, 0xab, 0x9e, 0x2a, 0xb0, 0x14, 0x4f, 0xc4, 0x6a, 0x57, 0x51, 0x32, 0xb5, - 0x51, 0x83, 0xe1, 0x8c, 0x35, 0xf4, 0xc9, 0xa9, 0xe1, 0x9c, 0x67, 0x80, 0x87, 0x97, 0xae, 0x4f, 0x21, 0x53, 0x3f, - 0x8d, 0x71, 0x29, 0x20, 0x4e, 0xc4, 0xb3, 0x0b, 0x2f, 0x31, 0xbe, 0x71, 0x7d, 0x0a, 0xf6, 0xd6, 0xa4, 0xab, 0x78, - 0x6a, 0x58, 0x85, 0x53, 0x9b, 0xab, 0xe1, 0xd4, 0xd6, 0x59, 0x0f, 0xfb, 0xb7, 0x14, 0xb9, 0x12, 0x50, 0x94, 0x1c, - 0x65, 0x2a, 0xae, 0x5c, 0x1b, 0xc6, 0xed, 0xb5, 0xf3, 0xc7, 0x54, 0x5d, 0x62, 0x28, 0x29, 0x51, 0xda, 0x3c, 0xb1, - 0x2d, 0x30, 0x92, 0x75, 0x13, 0xdc, 0xd2, 0x6b, 0xb9, 0xb4, 0xfb, 0xe2, 0x0e, 0x49, 0xa1, 0x96, 0xb4, 0xf6, 0x3c, - 0x89, 0x3e, 0xd6, 0xdc, 0xd2, 0xc6, 0x43, 0x62, 0xef, 0xf4, 0x58, 0x45, 0xfa, 0xf9, 0x52, 0x1d, 0x6a, 0x77, 0x20, - 0xe0, 0x32, 0x6d, 0x20, 0xbf, 0x6c, 0x0b, 0x44, 0xf6, 0x7c, 0x45, 0xb2, 0xf1, 0x87, 0x0a, 0x38, 0x1d, 0x38, 0xc5, - 0x04, 0x60, 0x65, 0x2a, 0x94, 0x4e, 0x12, 0x58, 0x16, 0x1f, 0xa1, 0x6a, 0x31, 0x37, 0x2d, 0xae, 0x0f, 0x8c, 0x78, - 0x7e, 0x9b, 0x10, 0x0f, 0x00, 0x71, 0x3d, 0x43, 0xd4, 0x15, 0x88, 0xfa, 0xcc, 0x8c, 0x81, 0x84, 0x1e, 0xb2, 0xef, - 0x0f, 0x98, 0xb9, 0x63, 0x3a, 0xf1, 0x52, 0xa5, 0xdc, 0x46, 0xcb, 0xc7, 0x72, 0x58, 0xa5, 0x99, 0x26, 0xc5, 0x35, - 0x09, 0x55, 0xf2, 0x8a, 0x06, 0x56, 0xb9, 0x6c, 0xf7, 0x5f, 0x7d, 0xe0, 0x35, 0x6c, 0x73, 0x3e, 0x5e, 0x3c, 0xc6, - 0xb7, 0x02, 0x45, 0xa3, 0x8a, 0xd9, 0x2a, 0x37, 0x18, 0x13, 0xd3, 0x8b, 0x03, 0xb1, 0xd4, 0xac, 0xe9, 0xce, 0x3c, - 0x87, 0xf6, 0x4d, 0xf1, 0xa0, 0x4c, 0xa5, 0x0a, 0x54, 0x70, 0x8d, 0x30, 0x56, 0x59, 0xb3, 0xa8, 0x4b, 0xc4, 0xfb, - 0xed, 0xd0, 0xbc, 0x94, 0x25, 0xa6, 0x88, 0x1d, 0x54, 0xd4, 0x19, 0x3e, 0xe7, 0xe1, 0xd6, 0xde, 0x7d, 0x76, 0x64, - 0x43, 0xc5, 0xc4, 0x94, 0x84, 0xf4, 0x64, 0x63, 0x4a, 0x92, 0x45, 0xe3, 0x99, 0xba, 0xa9, 0xbe, 0x86, 0xf1, 0x08, - 0x07, 0x6b, 0x3f, 0x66, 0x37, 0x40, 0x15, 0xd2, 0xe6, 0xa6, 0xda, 0xcc, 0xc1, 0x67, 0xb5, 0xe5, 0xdf, 0x96, 0x9e, - 0xde, 0x96, 0x2e, 0x7c, 0xd1, 0x2d, 0xe9, 0xe0, 0xd7, 0xf8, 0xd7, 0xa6, 0x09, 0x3f, 0xdd, 0x0c, 0x90, 0x9e, 0xef, - 0x72, 0x81, 0x28, 0x71, 0xad, 0x19, 0x03, 0xc5, 0x1b, 0xa4, 0x89, 0xa6, 0xc0, 0x1c, 0x8c, 0x76, 0xe0, 0x1f, 0x04, - 0x35, 0xa0, 0x12, 0x7a, 0x73, 0x45, 0x59, 0x5c, 0x7b, 0x9e, 0x0d, 0xfd, 0x18, 0x3a, 0x91, 0xbc, 0xfb, 0xa5, 0xd1, - 0x18, 0x05, 0xed, 0x7e, 0x89, 0x65, 0x02, 0x8e, 0xec, 0xa2, 0x95, 0x05, 0x33, 0x01, 0x6b, 0x81, 0x1d, 0x9a, 0x47, - 0x17, 0x7c, 0xbb, 0x2e, 0x19, 0x30, 0xa4, 0xcc, 0x5a, 0xfb, 0x74, 0xd5, 0xd1, 0xf8, 0x5a, 0x43, 0xb1, 0xd2, 0xb8, - 0x00, 0x86, 0x44, 0x15, 0x75, 0x3c, 0x59, 0x17, 0x1d, 0x30, 0x36, 0x97, 0x7c, 0x33, 0x44, 0x64, 0xce, 0x63, 0x83, - 0x41, 0x4c, 0x58, 0x3b, 0x56, 0x7f, 0xbe, 0xd0, 0x72, 0xa0, 0x69, 0x3e, 0x1f, 0x48, 0x94, 0xb6, 0x73, 0x08, 0x6d, - 0x27, 0x4a, 0xd7, 0x8d, 0x68, 0x0e, 0x84, 0x7b, 0xbf, 0x88, 0xc6, 0x19, 0x36, 0xde, 0xb9, 0x2c, 0xae, 0xaf, 0xba, - 0xba, 0x1f, 0x55, 0x23, 0x1e, 0x06, 0x5c, 0xbb, 0x85, 0x48, 0x9a, 0xf5, 0x77, 0xd4, 0x5b, 0x65, 0x94, 0x3e, 0x1d, - 0xef, 0x96, 0xbc, 0x6c, 0xed, 0x97, 0xfd, 0x9f, 0xcc, 0x3c, 0xe4, 0xf7, 0x85, 0x29, 0x54, 0x1f, 0x0d, 0x3d, 0xa2, - 0x6e, 0x1c, 0xe0, 0x7c, 0x6b, 0x13, 0x32, 0xb4, 0x60, 0x11, 0x19, 0x8f, 0xc0, 0xdc, 0x94, 0xa3, 0xbb, 0xde, 0x57, - 0x6c, 0xf8, 0x66, 0xc9, 0xbe, 0xd0, 0x95, 0x68, 0x5a, 0x47, 0xb8, 0x8b, 0x56, 0x92, 0x38, 0xa3, 0x91, 0x0e, 0x9d, - 0x51, 0xfd, 0x12, 0x3d, 0xef, 0x52, 0x60, 0x6b, 0xb9, 0xda, 0xf9, 0x9d, 0x95, 0x7c, 0x08, 0xa7, 0x63, 0x5c, 0x9b, - 0x0b, 0x48, 0xe3, 0x32, 0x71, 0x72, 0x58, 0x00, 0xcb, 0xde, 0xde, 0x2b, 0xe9, 0x70, 0x40, 0x6a, 0x3c, 0x16, 0xb3, - 0x43, 0x8a, 0x70, 0x03, 0x3a, 0x87, 0x06, 0x4b, 0x54, 0x09, 0xc7, 0x45, 0xec, 0xfa, 0xa6, 0xe2, 0x95, 0xab, 0xa0, - 0x0c, 0xca, 0x84, 0x75, 0x5b, 0xfe, 0x6d, 0xc9, 0xe7, 0xbe, 0x0d, 0x42, 0xce, 0x85, 0x0c, 0xee, 0x55, 0x09, 0x14, - 0x9b, 0x37, 0x82, 0xd8, 0x1a, 0xd3, 0x3d, 0xb0, 0x52, 0x9d, 0xb2, 0x58, 0x4f, 0x6c, 0xb6, 0x05, 0xf5, 0xa4, 0x61, - 0xe6, 0xf6, 0x1c, 0x41, 0x74, 0x07, 0xa1, 0x8f, 0xf7, 0xae, 0x8f, 0x52, 0x5e, 0xf9, 0xe5, 0xf9, 0x3e, 0x64, 0x85, - 0x62, 0x63, 0x0b, 0x3d, 0xa9, 0xf3, 0x70, 0x93, 0x07, 0x2d, 0xa2, 0x48, 0xf5, 0x5a, 0xac, 0x58, 0x01, 0x3b, 0xa2, - 0x0c, 0xff, 0x1e, 0x5c, 0x60, 0x1b, 0x58, 0x87, 0x4b, 0x00, 0x73, 0x37, 0xc6, 0xed, 0xd4, 0x53, 0xe5, 0x27, 0x1a, - 0x3f, 0x23, 0x82, 0x8b, 0x30, 0x45, 0x24, 0xb4, 0x4f, 0x15, 0x5f, 0xd1, 0x81, 0xc7, 0xb2, 0x7c, 0x6a, 0xc6, 0x9b, - 0x7c, 0xa9, 0x58, 0xaf, 0xfc, 0xf2, 0x90, 0xbd, 0xd0, 0xf8, 0x79, 0xd2, 0x12, 0xe2, 0xf2, 0x25, 0x82, 0x55, 0x25, - 0x5f, 0x8d, 0xd0, 0x47, 0xde, 0xc3, 0x97, 0x1b, 0x76, 0xd0, 0xf9, 0x80, 0x4a, 0xa6, 0x71, 0x81, 0x6f, 0x38, 0x2f, - 0xcd, 0xaa, 0x09, 0x33, 0x44, 0xf8, 0xc4, 0x69, 0x03, 0xc7, 0x57, 0xbe, 0x34, 0x74, 0x29, 0x3e, 0x15, 0x00, 0x7b, - 0x92, 0x74, 0x0e, 0x65, 0x32, 0xc7, 0x52, 0x24, 0x0e, 0x26, 0x95, 0xd9, 0x13, 0x48, 0x30, 0x5b, 0xac, 0xd2, 0x55, - 0xe7, 0x56, 0x8c, 0x6b, 0x32, 0x01, 0x30, 0xc6, 0x39, 0xd0, 0x9c, 0x99, 0xad, 0xd8, 0x21, 0x73, 0x62, 0x45, 0x05, - 0xf6, 0x7f, 0x8c, 0xbd, 0xc2, 0xdd, 0x67, 0xa6, 0x1f, 0xb3, 0x31, 0xdf, 0xf4, 0x3a, 0x34, 0x9b, 0xdc, 0x70, 0x79, - 0xb7, 0x5e, 0xcc, 0x89, 0x30, 0x5b, 0x40, 0x79, 0x1a, 0xd9, 0x48, 0x74, 0xd4, 0x40, 0xea, 0x1a, 0x48, 0x76, 0xf6, - 0xcd, 0x65, 0x6f, 0xf5, 0x59, 0x01, 0x31, 0xd1, 0xcd, 0x0c, 0xd4, 0xed, 0x2f, 0xf8, 0xb6, 0x3a, 0x15, 0x4c, 0x10, - 0xc0, 0x63, 0xd7, 0x86, 0x73, 0x21, 0x0b, 0xd5, 0xe9, 0xf6, 0xd3, 0x0e, 0x29, 0xfb, 0x59, 0x67, 0x52, 0xfe, 0x42, - 0x5b, 0x84, 0x11, 0x45, 0xa8, 0xae, 0x43, 0xcc, 0xb6, 0xa5, 0x1f, 0x84, 0x13, 0x70, 0xdc, 0x85, 0xd2, 0xf1, 0x01, - 0x5f, 0x52, 0x81, 0x08, 0xb9, 0x16, 0xe2, 0x6e, 0xd3, 0xd0, 0xb2, 0x82, 0xb7, 0xcd, 0x86, 0xd4, 0x4d, 0x3a, 0x7a, - 0x03, 0xaf, 0xe8, 0x66, 0xdd, 0xcb, 0xf4, 0x00, 0x64, 0x3c, 0x9a, 0x89, 0x81, 0x33, 0x6e, 0xdf, 0xde, 0x76, 0x2e, - 0x4d, 0x98, 0x17, 0x9d, 0x6c, 0x06, 0xaf, 0xe6, 0xc6, 0x9d, 0xb5, 0x0b, 0x67, 0xe3, 0xc3, 0x86, 0x66, 0x9b, 0xc7, - 0x1b, 0x6d, 0x1f, 0x66, 0xd7, 0xb3, 0xae, 0x5e, 0x96, 0x79, 0x99, 0x3e, 0xeb, 0xbb, 0x93, 0x5b, 0x35, 0x7f, 0x86, - 0x68, 0xb0, 0x19, 0xc8, 0x4c, 0x31, 0x49, 0xc2, 0x00, 0x30, 0x5a, 0x70, 0x7b, 0x13, 0xcd, 0xa0, 0x0b, 0x18, 0x28, - 0x4b, 0x93, 0xee, 0xe6, 0x8a, 0xe3, 0x97, 0x79, 0xaf, 0x54, 0xed, 0x85, 0x1b, 0x24, 0x0a, 0x4e, 0x83, 0xfd, 0x27, - 0x7e, 0xf7, 0x1f, 0x45, 0xdc, 0xcc, 0xf0, 0x95, 0x04, 0xa0, 0xb5, 0x60, 0xe1, 0x71, 0x62, 0x8b, 0xcd, 0xb2, 0x06, - 0x92, 0x52, 0x8b, 0xca, 0x7f, 0xd0, 0xf8, 0x51, 0x41, 0x5e, 0x9d, 0x6e, 0x0e, 0x31, 0xe0, 0x18, 0x8d, 0xda, 0x32, - 0xfd, 0xb8, 0x29, 0xc9, 0x70, 0x8a, 0x36, 0xb9, 0x8c, 0x68, 0x3e, 0x21, 0x1b, 0x0e, 0x01, 0x00, 0x4a, 0x95, 0x61, - 0x8d, 0xa4, 0x57, 0x93, 0xc4, 0xad, 0x0c, 0x47, 0x18, 0xa9, 0x02, 0xa3, 0x6f, 0xd6, 0x98, 0x5a, 0x08, 0xb5, 0x38, - 0x12, 0xc6, 0x76, 0x06, 0x29, 0xc7, 0xc0, 0x1c, 0xc4, 0x15, 0xf0, 0xec, 0xe4, 0x93, 0xda, 0x93, 0x96, 0x25, 0x14, - 0xfb, 0x4e, 0xc9, 0xd9, 0x6b, 0x3a, 0x28, 0x60, 0xd4, 0x75, 0xde, 0x86, 0xd3, 0x3c, 0x23, 0x4c, 0xf9, 0xd2, 0x8f, - 0xfe, 0x60, 0xdb, 0x03, 0xcf, 0x10, 0xaa, 0x02, 0xe1, 0xe3, 0x5c, 0x4d, 0x45, 0x54, 0xaa, 0x9c, 0x8b, 0xb4, 0xfd, - 0xf1, 0x88, 0x24, 0xdb, 0xc4, 0x7f, 0x40, 0x2c, 0xa5, 0x40, 0xf1, 0xf7, 0x9d, 0x13, 0x4d, 0x96, 0x98, 0x25, 0xf9, - 0x52, 0x9d, 0x26, 0x79, 0xf3, 0x35, 0x9c, 0x63, 0x35, 0x15, 0xff, 0x19, 0xa2, 0xa0, 0x69, 0x20, 0x84, 0xd6, 0x5b, - 0x9a, 0x6d, 0x40, 0xe9, 0xd6, 0x99, 0x6d, 0xe1, 0x9c, 0x07, 0x3c, 0x03, 0xb8, 0x98, 0x6d, 0xc6, 0x5d, 0x2a, 0x8d, - 0xa8, 0xf5, 0xca, 0x40, 0xba, 0x9d, 0x02, 0x0e, 0x51, 0x5b, 0x1f, 0xcc, 0x0e, 0x45, 0xef, 0x82, 0x17, 0x4c, 0x7e, - 0x06, 0x1f, 0x0a, 0x2a, 0xb5, 0xa0, 0xdb, 0x8b, 0xd9, 0x97, 0xd4, 0xa8, 0xca, 0x4b, 0xb3, 0xa1, 0xb6, 0xce, 0x5f, - 0x6b, 0x31, 0xe5, 0x2e, 0x00, 0x9d, 0xd0, 0x86, 0xad, 0x43, 0x06, 0x9e, 0xac, 0xe9, 0x53, 0x6e, 0x9a, 0x71, 0xc9, - 0xbe, 0x28, 0xc3, 0xdc, 0x8f, 0x88, 0xcd, 0xd8, 0xf7, 0xbe, 0x49, 0xad, 0xf9, 0x39, 0x87, 0xa7, 0xd6, 0xd5, 0x5a, - 0xc1, 0xd8, 0x3a, 0x7d, 0xd9, 0x38, 0x8a, 0x57, 0xf5, 0x4f, 0x80, 0x77, 0xf1, 0x79, 0xcd, 0xc8, 0xf4, 0xb5, 0x38, - 0x34, 0x22, 0x14, 0xb9, 0xde, 0x30, 0x04, 0x66, 0x22, 0x0c, 0xaf, 0xbb, 0x0b, 0xc1, 0xf4, 0xba, 0x52, 0x90, 0xe0, - 0xe0, 0xc6, 0x52, 0xec, 0x37, 0x7a, 0x7e, 0x65, 0xff, 0x50, 0x44, 0x43, 0x33, 0x15, 0xc0, 0x67, 0x33, 0x09, 0xd1, - 0x8f, 0x33, 0xb3, 0xe1, 0xc9, 0x83, 0xed, 0x6d, 0x44, 0x6d, 0x22, 0x81, 0x49, 0xe2, 0x32, 0x24, 0x51, 0xde, 0x25, - 0x5a, 0x90, 0xba, 0x84, 0xeb, 0x4f, 0x23, 0xf3, 0x4d, 0xa9, 0xca, 0x7c, 0x45, 0xe2, 0x5b, 0xd3, 0xb8, 0x7f, 0x08, - 0xa7, 0x79, 0x7d, 0x75, 0xfb, 0xbc, 0x65, 0xdd, 0x97, 0x7b, 0xb0, 0x95, 0x85, 0xff, 0x42, 0xdb, 0x98, 0xba, 0x6a, - 0x9d, 0x2e, 0x27, 0x62, 0xfc, 0x25, 0xea, 0x65, 0xec, 0x60, 0xbc, 0xed, 0x37, 0xb8, 0xd5, 0x08, 0x53, 0x7b, 0xf3, - 0x6b, 0x8e, 0x4c, 0x3d, 0x48, 0xdd, 0x00, 0x0d, 0x2b, 0x76, 0xa9, 0xca, 0x52, 0x5b, 0xfe, 0xd9, 0xad, 0xe7, 0x3b, - 0x19, 0x8e, 0x0e, 0x9f, 0x43, 0x1a, 0xf3, 0x5d, 0x6f, 0xbe, 0x79, 0xcd, 0xa4, 0x67, 0x9d, 0x46, 0x11, 0xdd, 0x8a, - 0x61, 0x3b, 0x46, 0x87, 0x43, 0x52, 0xb8, 0x2b, 0x49, 0x35, 0xc1, 0x3e, 0x51, 0x54, 0x8e, 0x06, 0x42, 0x18, 0x30, - 0xb1, 0x27, 0x61, 0xbb, 0x2f, 0x14, 0x70, 0xda, 0xd0, 0xbd, 0xab, 0x0e, 0x54, 0x42, 0x89, 0x8c, 0xbd, 0xac, 0xc6, - 0x37, 0xa5, 0x8a, 0x7c, 0x88, 0x57, 0xf0, 0xb0, 0xf4, 0x9a, 0x72, 0x97, 0x0c, 0x20, 0xf7, 0xea, 0xf4, 0xe6, 0x9f, - 0xb3, 0x7b, 0xee, 0xb3, 0x90, 0x6f, 0x7c, 0xed, 0xaf, 0x76, 0xdf, 0x5f, 0xe8, 0x60, 0x5e, 0xc1, 0x2a, 0xee, 0x5f, - 0xfe, 0x50, 0x29, 0x0a, 0x35, 0xea, 0x07, 0x79, 0x60, 0x7b, 0xe9, 0x71, 0x53, 0x16, 0xd6, 0x02, 0x13, 0x72, 0xe5, - 0xcd, 0x99, 0x06, 0xc2, 0x38, 0x8e, 0x7f, 0xcd, 0x29, 0xa4, 0x6c, 0xdc, 0x9c, 0x3c, 0xe3, 0xd1, 0x58, 0x11, 0xea, - 0x50, 0x97, 0x9b, 0x79, 0xd7, 0x71, 0x46, 0x8e, 0xbb, 0xa6, 0xe8, 0x8f, 0xe6, 0xe2, 0x5f, 0xcd, 0x3e, 0x43, 0xf8, - 0x15, 0x70, 0x3a, 0xe0, 0x3a, 0x65, 0xc6, 0x2e, 0x18, 0xed, 0x2e, 0x49, 0xc3, 0xc3, 0xc7, 0x76, 0xb0, 0xb5, 0xff, - 0xf1, 0xda, 0x83, 0x8a, 0x08, 0x21, 0x87, 0x9f, 0x1d, 0x3a, 0x39, 0xe8, 0xc3, 0xaa, 0x72, 0x7a, 0xd1, 0x17, 0x2c, - 0x2b, 0xd8, 0x42, 0x0d, 0x30, 0x25, 0xe8, 0x7e, 0x85, 0x96, 0x17, 0xbb, 0xa6, 0x7f, 0x78, 0xe6, 0xf3, 0x2c, 0xf2, - 0xc1, 0x02, 0x7e, 0x77, 0xa8, 0x92, 0x47, 0x6d, 0x2c, 0x5f, 0x68, 0xc9, 0xb7, 0x86, 0x14, 0x18, 0x55, 0x90, 0x36, - 0xc4, 0xc3, 0x51, 0x75, 0x39, 0x17, 0x5c, 0xa0, 0xfa, 0xd1, 0xa3, 0xb8, 0x4c, 0x51, 0x00, 0x58, 0xae, 0xb4, 0x40, - 0x38, 0x1f, 0x20, 0x42, 0xa1, 0x61, 0x35, 0x09, 0x99, 0x7e, 0x9e, 0xed, 0xa6, 0x06, 0xa1, 0xf1, 0xbe, 0xb4, 0xf6, - 0x23, 0xca, 0xc8, 0x9c, 0xa2, 0x29, 0x5d, 0xa5, 0xb6, 0x19, 0xf2, 0xc0, 0xb7, 0xb4, 0x2c, 0x00, 0x46, 0x4b, 0x24, - 0x1f, 0x36, 0x16, 0x91, 0xb5, 0xaf, 0xe7, 0x84, 0xbb, 0xcc, 0x7e, 0xf4, 0x4d, 0xcd, 0x2f, 0xb6, 0x4d, 0x83, 0xf3, - 0x87, 0xc8, 0x75, 0xee, 0x06, 0xc9, 0xc6, 0x26, 0x5e, 0xb9, 0x8d, 0x6f, 0x47, 0xf4, 0x87, 0x76, 0x59, 0x7f, 0xcb, - 0x30, 0x01, 0x75, 0x26, 0x2d, 0xe1, 0x1a, 0x80, 0x72, 0x18, 0xc2, 0xd3, 0x38, 0x14, 0x2f, 0x97, 0x3c, 0x44, 0x13, - 0x8d, 0x04, 0x4a, 0x60, 0x85, 0x37, 0xec, 0xa2, 0xaa, 0x7e, 0x3d, 0xf0, 0xff, 0x1b, 0x68, 0xaa, 0xfa, 0x36, 0xb3, - 0xd4, 0x4d, 0x4b, 0x40, 0xdb, 0x86, 0x04, 0xab, 0xa0, 0xc2, 0x11, 0xb6, 0x96, 0xa4, 0x32, 0x18, 0xb6, 0x9e, 0x7c, - 0xd8, 0x10, 0xb1, 0x99, 0x8c, 0x33, 0xad, 0xdf, 0x0e, 0x33, 0xdb, 0x2f, 0x05, 0xde, 0x10, 0x8b, 0xc6, 0x5c, 0xd4, - 0xb8, 0xf6, 0x34, 0x42, 0x20, 0x13, 0xa4, 0xd1, 0x9d, 0xd1, 0xd6, 0xc5, 0xf8, 0xda, 0xba, 0x24, 0x9f, 0x91, 0x75, - 0x72, 0xba, 0xc3, 0x07, 0x03, 0x21, 0xee, 0xa3, 0x5c, 0x30, 0xa3, 0xd4, 0x56, 0xe2, 0x6a, 0x88, 0x65, 0xd1, 0x4e, - 0x64, 0x11, 0x00, 0x23, 0xc0, 0xfe, 0x60, 0x5e, 0x6b, 0xd2, 0xe4, 0x0d, 0xe1, 0xcb, 0xd5, 0x38, 0x1d, 0x6b, 0xfd, - 0x36, 0x2c, 0x9b, 0x0e, 0x4c, 0xe1, 0x7a, 0x58, 0x9d, 0xc6, 0xb3, 0xf7, 0x6a, 0x8b, 0xd1, 0x9f, 0xf7, 0xe8, 0x05, - 0xbc, 0x41, 0x90, 0xc1, 0xa9, 0x98, 0x6c, 0x69, 0x7c, 0xd8, 0x43, 0xbc, 0x90, 0xea, 0x7c, 0x10, 0xb4, 0x1d, 0xd5, - 0x1e, 0x50, 0xce, 0x5f, 0x0b, 0xd4, 0x7d, 0x24, 0x3c, 0x13, 0x20, 0x23, 0x05, 0xe5, 0x89, 0xd6, 0xa7, 0xe8, 0xa1, - 0x07, 0x3e, 0xe9, 0xea, 0x9a, 0xb5, 0xa0, 0x93, 0x20, 0xd1, 0x10, 0x27, 0x27, 0x31, 0xfa, 0xe6, 0xc5, 0x03, 0x08, - 0xd2, 0x72, 0x4d, 0x86, 0xd2, 0x42, 0x1b, 0xc5, 0x19, 0x9b, 0xc4, 0x14, 0xd6, 0xff, 0xdc, 0x4e, 0x73, 0xa4, 0xe1, - 0xe0, 0x12, 0x25, 0x6f, 0x35, 0x91, 0x42, 0x82, 0x75, 0x52, 0x27, 0xbd, 0x9f, 0xb0, 0x1b, 0xdc, 0xf5, 0x8e, 0x0f, - 0x25, 0x11, 0x82, 0x09, 0xa1, 0x90, 0x9f, 0x96, 0xe1, 0xfc, 0x51, 0xe0, 0x37, 0x35, 0x0a, 0xce, 0x78, 0x5c, 0xc9, - 0x86, 0xa0, 0xd0, 0xef, 0xd9, 0x83, 0x5d, 0x38, 0x41, 0xd8, 0x74, 0xf8, 0xd0, 0x95, 0xb2, 0x0c, 0x82, 0x94, 0xde, - 0xeb, 0xbc, 0x0d, 0x15, 0xc9, 0x04, 0xd4, 0x42, 0xbb, 0x1e, 0x67, 0x15, 0x76, 0x73, 0x84, 0x7e, 0x2b, 0x36, 0xf8, - 0xb2, 0xb3, 0x05, 0x04, 0xd7, 0xd0, 0xc2, 0xe0, 0xa2, 0x42, 0x66, 0xb7, 0x88, 0x9e, 0x60, 0x72, 0x16, 0xb9, 0xc3, - 0x97, 0xb4, 0x50, 0xb9, 0x64, 0x25, 0x3d, 0x97, 0x3e, 0xf8, 0x5d, 0x76, 0xb4, 0x8a, 0x1b, 0x67, 0x6d, 0x94, 0x6a, - 0x74, 0x8b, 0x99, 0xef, 0x1f, 0x31, 0xc7, 0x25, 0xb1, 0x51, 0x0b, 0x2e, 0x19, 0xba, 0x32, 0x65, 0x29, 0x0b, 0x1c, - 0x71, 0x20, 0x82, 0xba, 0xcd, 0x77, 0xc4, 0x2b, 0xaa, 0x3b, 0xd9, 0x6b, 0x83, 0x0d, 0x5a, 0x87, 0xac, 0x95, 0xc2, - 0x9b, 0xb4, 0x42, 0x17, 0xb1, 0x8a, 0x19, 0xb8, 0x1c, 0x6f, 0xbf, 0x34, 0x19, 0xa0, 0x9b, 0x23, 0x71, 0xe7, 0x74, - 0x06, 0x45, 0x66, 0x78, 0xd1, 0xbf, 0x92, 0x56, 0x69, 0x50, 0xd6, 0x5b, 0xc9, 0x61, 0xac, 0xa3, 0xf9, 0x61, 0xb8, - 0xbf, 0x8a, 0x5f, 0xd3, 0x1d, 0xe5, 0xbf, 0x55, 0x7f, 0x39, 0x50, 0x55, 0x5e, 0x68, 0x15, 0x87, 0x6a, 0x1b, 0x27, - 0x21, 0xa1, 0x9f, 0x6c, 0xdf, 0xb7, 0xef, 0xbf, 0x19, 0x71, 0x8d, 0x5b, 0xda, 0x38, 0xdc, 0x6b, 0x71, 0xd0, 0xa2, - 0xbc, 0xff, 0x0f, 0xa5, 0x99, 0x01, 0x6c, 0xd2, 0xa1, 0x19, 0x32, 0x57, 0x1e, 0x7d, 0xa5, 0x5f, 0x8d, 0x19, 0x09, - 0x33, 0x7b, 0xcd, 0x18, 0xe3, 0xb5, 0xef, 0xfe, 0x9e, 0xa2, 0x85, 0x45, 0x93, 0x3c, 0x39, 0x2f, 0x05, 0xe3, 0xaa, - 0x2e, 0x7e, 0x76, 0xc7, 0x93, 0xf0, 0x3f, 0xa8, 0xda, 0xbe, 0x3c, 0x08, 0x31, 0x77, 0x3d, 0x85, 0x68, 0x83, 0x59, - 0xf2, 0x29, 0x6f, 0x7a, 0xba, 0xc6, 0x92, 0xc6, 0x4f, 0x66, 0xe5, 0xba, 0x75, 0xcd, 0x4e, 0x02, 0x60, 0xdc, 0x1f, - 0x9b, 0x3f, 0x2c, 0x2a, 0xf4, 0xed, 0x66, 0x2a, 0x81, 0xaf, 0x0c, 0xb3, 0x79, 0x9f, 0x05, 0xe0, 0x6f, 0x70, 0x96, - 0xd3, 0x72, 0x9e, 0x5a, 0x52, 0x3c, 0xf5, 0x4b, 0x6c, 0xd5, 0xaf, 0x1c, 0xd9, 0x50, 0x1e, 0x7f, 0xdd, 0xb0, 0x12, - 0xa8, 0xb8, 0x1b, 0x98, 0x60, 0xfa, 0xf7, 0xc9, 0xc8, 0x71, 0x14, 0x36, 0xb6, 0x51, 0x40, 0x56, 0x1f, 0x6f, 0x7e, - 0x3f, 0xcb, 0x36, 0xfc, 0xe3, 0x71, 0xb2, 0x6e, 0x20, 0x50, 0x83, 0x45, 0xd6, 0xdd, 0xf5, 0x9e, 0x05, 0x48, 0x65, - 0x77, 0x2b, 0xea, 0x8b, 0xc3, 0xd0, 0x7f, 0xfc, 0xdc, 0x19, 0xd5, 0xbb, 0x70, 0x8e, 0x71, 0x84, 0xd4, 0x2f, 0x61, - 0x7f, 0xff, 0x64, 0xd2, 0x2f, 0xcf, 0x9c, 0xff, 0x24, 0xea, 0x17, 0xa9, 0x7a, 0x43, 0x17, 0x12, 0xc7, 0x3e, 0x6c, - 0x7e, 0x9a, 0x23, 0x0f, 0x76, 0x3e, 0xcf, 0x44, 0x6a, 0xac, 0xc7, 0x52, 0x1d, 0x57, 0xc9, 0xca, 0x0f, 0x3e, 0x5c, - 0x6a, 0x5f, 0x2c, 0x59, 0x5a, 0xed, 0x5e, 0xd1, 0xf7, 0x68, 0x6e, 0xa0, 0xf5, 0xd8, 0x07, 0xef, 0xa6, 0x4f, 0xb5, - 0xfb, 0x18, 0xdd, 0x3d, 0xbd, 0x92, 0x38, 0xdb, 0x2a, 0x4d, 0x6c, 0xe1, 0xb3, 0xa3, 0xd7, 0x89, 0xb4, 0x14, 0x5a, - 0x19, 0x61, 0x7a, 0xca, 0x1e, 0xc1, 0x12, 0x24, 0x4b, 0xab, 0xde, 0xb1, 0x6b, 0x2e, 0xd2, 0x98, 0xfe, 0xf4, 0xc4, - 0x4a, 0x8f, 0x7b, 0xcd, 0x6a, 0x7a, 0x98, 0x5f, 0x19, 0x33, 0xe3, 0x0c, 0x09, 0x9e, 0x42, 0x24, 0xa0, 0xb3, 0x05, - 0xe5, 0x13, 0x4d, 0x66, 0x25, 0xac, 0xbe, 0x3a, 0x53, 0x82, 0x30, 0x2b, 0x1b, 0x77, 0x29, 0x67, 0xda, 0xe8, 0x34, - 0xc7, 0x72, 0x5d, 0x3a, 0x8f, 0xcb, 0xd5, 0x71, 0x50, 0xff, 0xa6, 0x43, 0x18, 0xce, 0x36, 0x9c, 0x1f, 0xa9, 0x9e, - 0x18, 0x25, 0x5f, 0x90, 0x7f, 0x11, 0x2a, 0xd8, 0xa8, 0xbe, 0x79, 0x82, 0x0e, 0x64, 0x52, 0xef, 0x8f, 0xdf, 0xed, - 0x8f, 0xef, 0x61, 0x0c, 0xc3, 0x36, 0x68, 0x2b, 0x28, 0x55, 0x45, 0xb9, 0x14, 0x6d, 0x9c, 0x77, 0x3d, 0x2e, 0xbb, - 0xfc, 0xa6, 0x0f, 0x34, 0xfa, 0xe5, 0x79, 0xe7, 0x5a, 0x5a, 0x7a, 0x44, 0xa6, 0x5e, 0x24, 0x0a, 0x31, 0xd6, 0x52, - 0x78, 0xb3, 0x74, 0xa2, 0xe2, 0x80, 0xe1, 0xae, 0xc9, 0xc8, 0x33, 0x73, 0xc6, 0x6e, 0x25, 0xed, 0x08, 0x16, 0x86, - 0x75, 0xd3, 0xb5, 0x94, 0x64, 0x99, 0xf5, 0xe9, 0x5e, 0x9d, 0x08, 0x2b, 0x38, 0xbc, 0x11, 0xdb, 0x13, 0xd2, 0xfc, - 0x69, 0x22, 0x99, 0x93, 0xd7, 0xfb, 0x12, 0x30, 0x4b, 0x5c, 0x3a, 0x9b, 0x7c, 0x46, 0x9a, 0xe2, 0x5f, 0x07, 0x95, - 0xe9, 0x8b, 0x6f, 0xac, 0x26, 0xd4, 0xbe, 0x4a, 0x56, 0xa9, 0x38, 0xc7, 0x17, 0x14, 0x29, 0xf6, 0x8c, 0xf6, 0x4c, - 0x76, 0xe8, 0x46, 0x63, 0x6f, 0x73, 0x4f, 0x29, 0xa4, 0xcc, 0x62, 0xdf, 0x4b, 0xd0, 0xbf, 0x22, 0xcc, 0x30, 0x09, - 0x4a, 0xf0, 0xf2, 0x3f, 0xe0, 0xc6, 0x1c, 0x38, 0xa2, 0xde, 0x3b, 0x8f, 0x89, 0x45, 0x0b, 0x75, 0xe8, 0x86, 0x0c, - 0xab, 0x74, 0x22, 0x7e, 0xbd, 0x44, 0xd1, 0xb4, 0x0f, 0x6b, 0x84, 0x79, 0xe1, 0x2b, 0xed, 0x6f, 0x13, 0x01, 0x34, - 0x08, 0x4b, 0x43, 0x0c, 0xec, 0xea, 0x26, 0x6d, 0x61, 0xb8, 0xd5, 0x13, 0x68, 0x0a, 0x17, 0xaf, 0xe9, 0x78, 0xfa, - 0x5a, 0xa4, 0x13, 0x4a, 0x7a, 0x94, 0x8b, 0xc9, 0xb1, 0x16, 0xcb, 0x31, 0x7b, 0x2c, 0x7f, 0x27, 0xd7, 0xcb, 0xb3, - 0x08, 0x4d, 0x4f, 0x05, 0x16, 0x39, 0x08, 0x9c, 0x71, 0x69, 0xa5, 0x54, 0xef, 0x30, 0x78, 0x99, 0x99, 0x28, 0xfc, - 0x40, 0x5e, 0x06, 0x0b, 0xa5, 0x93, 0x1f, 0xb4, 0xea, 0xef, 0x3d, 0x45, 0x61, 0xf6, 0xf4, 0x10, 0x45, 0xc7, 0xa8, - 0xb3, 0xbb, 0x8e, 0x41, 0xf5, 0xa7, 0x35, 0xf5, 0x6b, 0xf8, 0x05, 0xa3, 0x0b, 0x24, 0x32, 0x73, 0x0c, 0x24, 0x8f, - 0xc0, 0x1f, 0xef, 0xb0, 0xc9, 0x7d, 0xe6, 0x6c, 0x87, 0xe4, 0xf1, 0xea, 0x6d, 0xc5, 0x01, 0x5d, 0x32, 0x56, 0x4b, - 0x1e, 0xa2, 0xf6, 0xaa, 0x96, 0xf5, 0xa7, 0xe5, 0x98, 0x77, 0x0b, 0xb7, 0xa3, 0xc7, 0x53, 0x1c, 0xb0, 0xbd, 0xdf, - 0x9d, 0x09, 0x8b, 0x43, 0x9c, 0x1f, 0x1b, 0xd5, 0xed, 0x18, 0x5d, 0x96, 0x01, 0x3e, 0xad, 0x0f, 0xb4, 0x41, 0x10, - 0xd7, 0x67, 0x07, 0xaa, 0x3b, 0xf7, 0x15, 0x2f, 0x4c, 0x8f, 0xd7, 0x24, 0x94, 0x96, 0xf2, 0x64, 0x6c, 0xc8, 0x3a, - 0x80, 0xa2, 0x51, 0xcc, 0x51, 0x10, 0xa2, 0x08, 0x10, 0x72, 0x48, 0x49, 0xf2, 0x6a, 0x0f, 0x40, 0x11, 0x6b, 0xa1, - 0x72, 0xd0, 0x1c, 0xf7, 0x7e, 0x10, 0xc4, 0x30, 0x63, 0xfa, 0x0f, 0xf1, 0x43, 0x78, 0xb6, 0xc3, 0x32, 0x96, 0x19, - 0xaf, 0x71, 0x95, 0xae, 0xcf, 0x81, 0x72, 0xe9, 0xe6, 0xad, 0xfa, 0x4d, 0x4f, 0x80, 0x69, 0x7d, 0x16, 0x84, 0x2d, - 0x22, 0x77, 0x09, 0x42, 0x64, 0xd7, 0x05, 0x7a, 0xf5, 0x40, 0xb6, 0x3b, 0xf4, 0x43, 0xaf, 0x20, 0x52, 0xfa, 0x5a, - 0x10, 0x7e, 0x45, 0x7e, 0x10, 0x16, 0x3c, 0xdf, 0x50, 0x94, 0x06, 0x88, 0x9e, 0x42, 0xad, 0x3b, 0x7d, 0xab, 0xe2, - 0x1c, 0x3b, 0xa8, 0xdb, 0xcc, 0xc2, 0xf6, 0xa7, 0x13, 0xf1, 0xb1, 0xac, 0x8b, 0x97, 0x74, 0xe9, 0xae, 0xde, 0xb7, - 0x0c, 0x7b, 0x00, 0xc4, 0x52, 0x85, 0x9d, 0xa1, 0x12, 0x81, 0xaf, 0xf3, 0x82, 0x87, 0x14, 0xbd, 0x4a, 0xb6, 0xf7, - 0xdd, 0xef, 0xbd, 0x42, 0x47, 0x7c, 0xd9, 0x16, 0x7d, 0xc2, 0x57, 0xd5, 0x24, 0x5e, 0x5f, 0xd9, 0x2b, 0xf7, 0xb6, - 0xea, 0xf9, 0xf3, 0x61, 0x14, 0x67, 0xf1, 0x8e, 0xa6, 0x4b, 0x8d, 0xde, 0x27, 0xab, 0xbf, 0x03, 0xb5, 0xa8, 0x7d, - 0x97, 0xe8, 0xf4, 0x72, 0xe4, 0x98, 0xf9, 0xa2, 0xa4, 0x69, 0xdd, 0xe1, 0x34, 0x7f, 0x95, 0x59, 0x8f, 0xaf, 0xf4, - 0x9c, 0x59, 0xcd, 0xf4, 0xc1, 0xcf, 0x54, 0xdb, 0x73, 0x19, 0x00, 0x5b, 0xc7, 0xa7, 0xcf, 0xc7, 0xbd, 0x0d, 0xab, - 0xd5, 0x17, 0xfd, 0x88, 0x75, 0xd1, 0x0d, 0x3d, 0xd7, 0x13, 0x84, 0xf4, 0x9c, 0xee, 0x1d, 0x58, 0xa5, 0x1f, 0x1b, - 0x29, 0xfa, 0x36, 0xc5, 0xbe, 0x67, 0x45, 0x2e, 0x48, 0xc7, 0xae, 0x7a, 0xc3, 0x6d, 0x16, 0xfa, 0x66, 0xda, 0x52, - 0x5f, 0xd4, 0xa8, 0x6d, 0x89, 0xcf, 0x67, 0xa9, 0x64, 0x22, 0xea, 0x17, 0x37, 0x5c, 0x59, 0xdf, 0x79, 0x07, 0xc9, - 0x6a, 0x95, 0xc0, 0x5d, 0x91, 0x5c, 0xe9, 0xd2, 0x7f, 0x1f, 0x46, 0xcf, 0x53, 0x0e, 0xab, 0xa5, 0x9c, 0xa6, 0xa7, - 0xa8, 0xec, 0x8d, 0x9d, 0x94, 0xf9, 0x49, 0xf2, 0xef, 0xfc, 0xf0, 0x64, 0xb1, 0x9b, 0x18, 0xf5, 0xf9, 0x88, 0xd7, - 0xf9, 0xfb, 0x2a, 0x63, 0x14, 0xc4, 0xd0, 0xee, 0xab, 0x9c, 0x26, 0x6d, 0x95, 0xf8, 0xd8, 0x7b, 0x45, 0xb1, 0xc9, - 0xf2, 0xe8, 0xa9, 0xc2, 0x24, 0xf8, 0x69, 0x44, 0xce, 0xfc, 0x5c, 0x4d, 0xc2, 0xc4, 0x78, 0xba, 0xb4, 0xfa, 0x1e, - 0x9e, 0xba, 0x0b, 0x67, 0xbd, 0xc7, 0x08, 0x69, 0x8c, 0xff, 0x39, 0x66, 0x58, 0xe2, 0xd5, 0x99, 0xe5, 0xdb, 0xe0, - 0xc6, 0x74, 0x58, 0x4a, 0x1a, 0xce, 0x71, 0x30, 0xa1, 0x1b, 0x8c, 0x7a, 0xab, 0x04, 0x35, 0x54, 0x84, 0x83, 0x02, - 0x22, 0xfb, 0x88, 0x66, 0x51, 0x56, 0x24, 0x40, 0x91, 0x69, 0xf1, 0xb7, 0x39, 0xb6, 0xc8, 0x0f, 0x2d, 0xf6, 0xcb, - 0xf2, 0xbd, 0xbe, 0x0a, 0xa2, 0xfe, 0x36, 0x01, 0x45, 0xa8, 0x0d, 0x59, 0x9b, 0x80, 0x29, 0x44, 0x31, 0x35, 0xc1, - 0xa7, 0x05, 0x45, 0xa1, 0x32, 0xf1, 0x2a, 0x6c, 0x0d, 0x16, 0x0e, 0xb5, 0xb4, 0xa8, 0x35, 0xe9, 0xbc, 0x05, 0xe4, - 0x68, 0xbf, 0x75, 0xf1, 0x5c, 0x76, 0x6a, 0x3c, 0x4c, 0xaa, 0x3d, 0x24, 0x22, 0xc1, 0x3c, 0xce, 0x46, 0xc0, 0x6e, - 0xf3, 0x29, 0xbe, 0x14, 0xd0, 0x64, 0x49, 0xdd, 0xc5, 0x6f, 0xba, 0xed, 0x04, 0x54, 0x46, 0x2b, 0x0d, 0x05, 0x09, - 0xdf, 0x1d, 0x8d, 0x07, 0xaa, 0x0a, 0xd9, 0x65, 0xbc, 0xc3, 0x25, 0x37, 0x22, 0xcc, 0x52, 0x74, 0x87, 0x5f, 0x92, - 0xfe, 0xdd, 0x51, 0x99, 0x93, 0x9d, 0xd6, 0xb4, 0x77, 0x1b, 0x06, 0x5f, 0xc4, 0xe8, 0xcc, 0x00, 0x47, 0xf6, 0x3a, - 0xc0, 0x06, 0xce, 0x63, 0x84, 0x09, 0x38, 0x5e, 0x54, 0x64, 0xb2, 0xce, 0x2f, 0xd9, 0xbd, 0xb8, 0xca, 0x1c, 0x1c, - 0x08, 0x51, 0x0b, 0x3f, 0xe0, 0x46, 0x0b, 0xc8, 0x70, 0x30, 0x4b, 0xe8, 0xb1, 0x50, 0x3c, 0x37, 0x00, 0xef, 0x95, - 0x36, 0x90, 0x80, 0xdc, 0xec, 0x49, 0x01, 0xc9, 0xfc, 0x85, 0x59, 0x03, 0xc2, 0x87, 0x64, 0x26, 0x73, 0x72, 0x06, - 0xa5, 0xc4, 0x1a, 0x00, 0x45, 0xc8, 0x2c, 0x00, 0x9f, 0x35, 0xef, 0x37, 0x6f, 0x5f, 0x4e, 0x15, 0x3b, 0x1d, 0x80, - 0x7f, 0x50, 0x8a, 0x4c, 0x6e, 0x46, 0x42, 0x19, 0x38, 0xbf, 0x00, 0x93, 0x0d, 0x58, 0xfd, 0x18, 0x86, 0xdf, 0xf5, - 0x0c, 0x23, 0x97, 0xd1, 0xc2, 0xea, 0x42, 0x52, 0x94, 0xee, 0xad, 0x0b, 0x91, 0x2a, 0x65, 0x33, 0x6a, 0x43, 0x86, - 0x2d, 0xf8, 0x3c, 0x55, 0x9f, 0x78, 0xad, 0x4c, 0x8e, 0x9a, 0x85, 0xcd, 0x3a, 0xb1, 0x85, 0x4c, 0x58, 0x9c, 0x26, - 0xe7, 0xe6, 0x2d, 0x4f, 0xb3, 0x88, 0x57, 0x2e, 0x49, 0x93, 0x96, 0x45, 0x85, 0xd8, 0xc6, 0x4c, 0x95, 0x0d, 0x7f, - 0x72, 0x9c, 0xc7, 0xb3, 0x01, 0x23, 0x7f, 0xb6, 0xa0, 0xeb, 0xed, 0x43, 0x2c, 0x12, 0x72, 0x56, 0x5b, 0xf3, 0xcd, - 0x2e, 0xb5, 0xcd, 0xbd, 0xb1, 0x73, 0xfa, 0xd8, 0xfa, 0xcb, 0x47, 0x32, 0x3b, 0x57, 0x54, 0x84, 0xdd, 0x71, 0x90, - 0x74, 0x89, 0xa9, 0x8a, 0x2b, 0xa7, 0x3e, 0x1b, 0x2e, 0x89, 0xf3, 0x1a, 0xdf, 0x5d, 0x82, 0x5d, 0xde, 0xe4, 0xff, - 0x92, 0xe2, 0xf8, 0x02, 0xb8, 0xa2, 0x08, 0x9c, 0x96, 0x5a, 0x28, 0xa2, 0x78, 0xca, 0x99, 0xe5, 0x16, 0x68, 0xd5, - 0x53, 0xb5, 0xb6, 0xd4, 0x5d, 0x31, 0xc2, 0xb3, 0xd8, 0x0a, 0x43, 0x20, 0xd3, 0x59, 0x90, 0xe5, 0x24, 0x36, 0x38, - 0xe8, 0x73, 0x41, 0x90, 0xcc, 0x85, 0x72, 0x37, 0xee, 0xb1, 0x8d, 0x35, 0x1b, 0x8c, 0x76, 0x96, 0x5a, 0x24, 0xe7, - 0x51, 0x91, 0xbd, 0x2f, 0x77, 0x0b, 0xf6, 0x6d, 0x07, 0x14, 0x25, 0x52, 0x59, 0xfa, 0x3a, 0x52, 0xc2, 0x63, 0xde, - 0xda, 0x4c, 0x23, 0x8c, 0x61, 0xc1, 0x8e, 0x36, 0xb6, 0xcd, 0x65, 0x48, 0x2c, 0x6b, 0x1b, 0x46, 0x95, 0xa1, 0xd9, - 0x88, 0x3c, 0x85, 0xf2, 0xa8, 0xbe, 0x09, 0xda, 0x90, 0x4a, 0xf6, 0xf0, 0xae, 0xa1, 0xb0, 0x48, 0xe9, 0x23, 0xd8, - 0xa2, 0xf9, 0x22, 0xd1, 0xed, 0x51, 0x63, 0x43, 0x76, 0xac, 0x92, 0x1c, 0xa6, 0xcb, 0x06, 0xe9, 0xf3, 0x28, 0x50, - 0xea, 0x2a, 0x91, 0x10, 0x14, 0x12, 0xe6, 0xd9, 0x1b, 0x3e, 0x35, 0x2d, 0xf7, 0x08, 0x08, 0x66, 0x9f, 0x57, 0xbd, - 0xa8, 0x1b, 0x21, 0xe2, 0x43, 0x11, 0x39, 0x7e, 0xaf, 0x1c, 0x86, 0xee, 0x6d, 0x2a, 0x86, 0x5b, 0x1b, 0x1f, 0x4f, - 0x92, 0x29, 0xd1, 0xb4, 0x43, 0xa4, 0x0b, 0x24, 0x56, 0x00, 0xb1, 0x2c, 0x9d, 0x4a, 0x50, 0x0a, 0x3d, 0x05, 0x3b, - 0x9e, 0x8f, 0x37, 0xe9, 0xb4, 0xc5, 0x48, 0x73, 0x59, 0x9a, 0xff, 0xe6, 0xc3, 0x30, 0x3d, 0x4d, 0xec, 0xae, 0xfe, - 0xc2, 0xfd, 0xdc, 0x7d, 0xb3, 0x61, 0x88, 0x62, 0x97, 0x6c, 0x10, 0x81, 0xf0, 0x77, 0xd1, 0xb4, 0xb0, 0x60, 0x2a, - 0xb4, 0x1b, 0xc7, 0xc6, 0x2f, 0x93, 0x61, 0xcf, 0x74, 0xba, 0x23, 0x50, 0xfc, 0x1a, 0x42, 0x87, 0x2b, 0xa0, 0x01, - 0x21, 0x50, 0x3f, 0x8b, 0x5c, 0x0b, 0xe3, 0xde, 0xe6, 0x3f, 0xa2, 0x98, 0x83, 0x01, 0x02, 0x39, 0x15, 0xe4, 0x5e, - 0x70, 0x46, 0x12, 0x67, 0x1d, 0x69, 0x59, 0x7f, 0xea, 0xba, 0x4d, 0xe9, 0xc8, 0xde, 0xb7, 0x82, 0x03, 0x45, 0x7b, - 0xb9, 0x95, 0xe9, 0x3f, 0x80, 0xbd, 0xb0, 0x2b, 0xcb, 0x7f, 0x3c, 0x17, 0x4d, 0x15, 0x19, 0xf5, 0xd4, 0x55, 0xf5, - 0x76, 0x64, 0xcc, 0x4c, 0x66, 0xe3, 0x91, 0x5f, 0x06, 0xed, 0xbe, 0x15, 0xc1, 0xc6, 0x2b, 0xd7, 0xf1, 0xf1, 0xc9, - 0xc8, 0x20, 0xb6, 0xab, 0x0b, 0xd5, 0x8c, 0x09, 0x44, 0x1e, 0xa6, 0xd2, 0x6e, 0x6c, 0xf3, 0x3a, 0xfd, 0xe4, 0x6e, - 0xfd, 0xf6, 0x9b, 0x54, 0x71, 0x6e, 0x85, 0x4d, 0x32, 0xdd, 0xc4, 0x0b, 0xf7, 0xdc, 0xef, 0xda, 0x66, 0xf3, 0xb6, - 0xdb, 0xa5, 0x88, 0xae, 0x6d, 0x04, 0x9d, 0x0f, 0xb5, 0xdd, 0x40, 0xe3, 0x67, 0xda, 0xc4, 0xd7, 0xf9, 0x4f, 0x55, - 0x03, 0x1d, 0xff, 0x89, 0x53, 0xb6, 0x45, 0x1c, 0xb5, 0xe5, 0x52, 0x0a, 0xdf, 0xe0, 0x2b, 0x13, 0xbe, 0x02, 0x77, - 0xe5, 0xc4, 0xf0, 0xec, 0x55, 0xe9, 0x6d, 0x67, 0x3f, 0xfa, 0xc9, 0x9a, 0x7a, 0x12, 0x83, 0xd2, 0x57, 0xc1, 0x3e, - 0x40, 0x5f, 0xa8, 0x1a, 0x22, 0x75, 0xf7, 0xee, 0x2b, 0x81, 0x13, 0x15, 0xe2, 0x3f, 0x08, 0x06, 0x46, 0x69, 0x53, - 0xaa, 0x5f, 0x6c, 0x1d, 0x31, 0xdb, 0x51, 0xe5, 0xb4, 0x7a, 0xd6, 0x07, 0x8f, 0x9f, 0x7b, 0xbf, 0xf9, 0x8f, 0xd4, - 0x3a, 0xc0, 0x2a, 0xab, 0xc3, 0x2f, 0xcb, 0x39, 0x6d, 0xbf, 0xd2, 0xcd, 0x85, 0x62, 0x7a, 0xa1, 0xf5, 0x26, 0x6e, - 0xbd, 0xce, 0xe6, 0xc3, 0xb9, 0x56, 0x84, 0x96, 0x97, 0xfa, 0xe2, 0xd3, 0xf3, 0xbf, 0x1d, 0x8d, 0x75, 0xbf, 0xb7, - 0xdd, 0x56, 0xaa, 0xf6, 0x36, 0x12, 0x46, 0xaa, 0xac, 0x77, 0x8c, 0x1d, 0xba, 0xc6, 0x78, 0x34, 0x86, 0x44, 0xb2, - 0x58, 0x9d, 0x02, 0x0e, 0x9d, 0x10, 0xf9, 0x3a, 0x89, 0x3b, 0x75, 0x12, 0xcd, 0x2c, 0x17, 0x41, 0x22, 0x45, 0xfa, - 0x36, 0x20, 0x6a, 0xe1, 0x90, 0x01, 0x0f, 0xe3, 0xd6, 0x64, 0x10, 0xd6, 0x75, 0x2c, 0x13, 0xa1, 0xda, 0xe1, 0xf5, - 0x29, 0xf5, 0x0a, 0x06, 0xd6, 0x14, 0x49, 0x1b, 0x89, 0x68, 0x4b, 0xdd, 0x7f, 0x35, 0xdd, 0x0f, 0xea, 0xcd, 0x8d, - 0xfd, 0x94, 0xb7, 0x51, 0x8b, 0xe6, 0x5e, 0xd4, 0x30, 0xac, 0x46, 0xd6, 0xcc, 0xb0, 0xcd, 0x23, 0xff, 0x23, 0x29, - 0x70, 0xe8, 0x3a, 0x00, 0xd0, 0x7e, 0x80, 0x36, 0x28, 0x86, 0x11, 0x98, 0xfd, 0xb8, 0x68, 0x23, 0xb5, 0x29, 0xbf, - 0x30, 0xab, 0x6e, 0x39, 0xb2, 0x5b, 0x04, 0x61, 0x4d, 0x96, 0x01, 0xe0, 0x2b, 0x1b, 0x6e, 0x03, 0x50, 0x34, 0x82, - 0xb2, 0xa9, 0x17, 0xb8, 0x2d, 0xfe, 0x1d, 0x9a, 0x35, 0x8f, 0x07, 0x45, 0xcf, 0x88, 0x0a, 0x2a, 0xcb, 0x08, 0xcf, - 0xbf, 0xba, 0x50, 0xae, 0xa4, 0xe1, 0x5b, 0x7a, 0x6e, 0x65, 0x6b, 0xce, 0x7b, 0xbb, 0x8a, 0xfe, 0xb9, 0x5d, 0xcf, - 0xaf, 0xd9, 0x06, 0xcb, 0x08, 0x8f, 0xdc, 0x7e, 0xf9, 0x91, 0x6e, 0xc2, 0xb1, 0x8f, 0x22, 0x3b, 0x2c, 0x4c, 0x41, - 0x70, 0xa8, 0x35, 0xda, 0x94, 0xfc, 0x62, 0x0f, 0x28, 0xcc, 0x1e, 0x36, 0x1c, 0x30, 0xd8, 0x54, 0x19, 0x26, 0x91, - 0x3d, 0x05, 0xbf, 0x6c, 0x83, 0x18, 0x4c, 0xa2, 0xa1, 0x24, 0xe0, 0xa6, 0x74, 0xcd, 0x09, 0xd9, 0x99, 0x53, 0xff, - 0x51, 0x23, 0xac, 0xe7, 0x09, 0x43, 0xd4, 0xc3, 0x34, 0xd3, 0xca, 0xaa, 0x59, 0x78, 0x6b, 0x58, 0xea, 0x1a, 0x82, - 0x94, 0xb2, 0x48, 0xe8, 0x7d, 0xeb, 0x04, 0xb5, 0x81, 0x09, 0xd3, 0x3d, 0x2a, 0xe3, 0xf0, 0x71, 0x9d, 0x16, 0x67, - 0xa2, 0x18, 0xad, 0xac, 0xd7, 0x18, 0xcb, 0xdc, 0x78, 0xcd, 0xcb, 0xa2, 0x99, 0x17, 0xbd, 0x3e, 0xd9, 0x90, 0xf0, - 0xfc, 0x39, 0x14, 0x89, 0x62, 0x63, 0x86, 0xda, 0x8d, 0xe7, 0xc4, 0xa7, 0xf9, 0x46, 0x53, 0x24, 0xb6, 0xf4, 0x9a, - 0x61, 0x25, 0xb3, 0x95, 0x30, 0xbd, 0x5a, 0x95, 0x19, 0xe1, 0xba, 0xc3, 0xb1, 0xcf, 0xf4, 0x70, 0x34, 0x05, 0x3f, - 0x02, 0x6c, 0xee, 0x74, 0xe4, 0xc6, 0xc3, 0xff, 0x01, 0xf2, 0xa8, 0xe6, 0xd1, 0x0a, 0xb9, 0x5c, 0x1e, 0x62, 0x13, - 0x0f, 0x35, 0xc7, 0xee, 0xaf, 0x61, 0xfd, 0xe7, 0x2d, 0xba, 0xa2, 0xed, 0x85, 0x56, 0x29, 0x91, 0x83, 0x36, 0xb1, - 0x2e, 0xdb, 0xc3, 0xa0, 0xb5, 0x88, 0x84, 0x13, 0x55, 0x9d, 0xf5, 0xc2, 0x3c, 0xce, 0xa5, 0xff, 0xc7, 0x4f, 0xb5, - 0x15, 0x04, 0x01, 0x61, 0x7e, 0x17, 0xbb, 0x13, 0x48, 0x71, 0x3e, 0x6b, 0xc8, 0x8c, 0x13, 0xfe, 0x95, 0x27, 0x7c, - 0x4f, 0x33, 0xb2, 0x92, 0xf9, 0x97, 0x32, 0x89, 0x4e, 0x71, 0xd5, 0x1c, 0xf1, 0x3a, 0x65, 0x0c, 0xa6, 0xb7, 0x0c, - 0x72, 0x2e, 0xc8, 0x67, 0x68, 0xca, 0xb9, 0x23, 0xeb, 0x4d, 0x81, 0xa7, 0x11, 0x18, 0x43, 0x01, 0xb2, 0x42, 0x57, - 0x99, 0x9d, 0x76, 0x86, 0x31, 0x30, 0xe4, 0x5e, 0x01, 0x1e, 0x5c, 0x09, 0xa0, 0x92, 0x81, 0x5f, 0xc5, 0x9e, 0x95, - 0x98, 0x7f, 0xb9, 0xa8, 0xd0, 0xee, 0x35, 0xc0, 0x5f, 0xa1, 0xe0, 0x12, 0xd5, 0x42, 0x81, 0x13, 0x01, 0x5d, 0x12, - 0x5c, 0xa0, 0x39, 0x89, 0x10, 0x5b, 0x0d, 0x08, 0x6a, 0x1b, 0xb7, 0x5c, 0x1c, 0xf0, 0xce, 0x7b, 0x59, 0xf1, 0xd5, - 0x75, 0x01, 0x1c, 0x0f, 0xf3, 0xfc, 0xdb, 0xca, 0x5c, 0xf6, 0x73, 0x02, 0x11, 0x17, 0x16, 0x66, 0x8e, 0x28, 0xe7, - 0xb4, 0x20, 0xcb, 0x5c, 0x84, 0x32, 0x5e, 0x6b, 0x98, 0xec, 0x84, 0xb3, 0x8c, 0xb4, 0xfb, 0xd0, 0x99, 0x48, 0x5f, - 0xbc, 0xcb, 0x20, 0xec, 0x90, 0xb5, 0x27, 0x52, 0xb9, 0x9d, 0x45, 0x13, 0xd0, 0xe7, 0x5b, 0x5f, 0xbb, 0xbe, 0xa7, - 0x8d, 0x35, 0x98, 0xbc, 0x6b, 0x36, 0x45, 0x0c, 0xa5, 0xf9, 0x62, 0x82, 0x99, 0xa7, 0xfd, 0x31, 0xcf, 0xc1, 0x22, - 0x7d, 0x99, 0xf4, 0xb2, 0x62, 0xa2, 0x3e, 0xb2, 0x83, 0x60, 0x91, 0x24, 0x86, 0xdc, 0x1a, 0x74, 0x14, 0x54, 0xe4, - 0x6d, 0xb4, 0x90, 0x15, 0xcb, 0x9a, 0x83, 0x9d, 0xf7, 0xdf, 0xb9, 0x62, 0x65, 0x62, 0x60, 0xc7, 0x18, 0x63, 0x9e, - 0x3c, 0x5a, 0xe3, 0xad, 0xdd, 0x5b, 0xae, 0xd0, 0x31, 0x69, 0xc0, 0x49, 0x21, 0x32, 0x2e, 0x5d, 0x62, 0xae, 0xad, - 0x99, 0x2d, 0x6b, 0x6a, 0xe1, 0x3f, 0x3d, 0x2b, 0x63, 0x60, 0xcc, 0x13, 0x41, 0x7e, 0x2e, 0xad, 0x76, 0xcc, 0x9b, - 0xb0, 0x57, 0x02, 0x4e, 0x9d, 0xcb, 0x5c, 0x12, 0x01, 0x5e, 0x2a, 0xfd, 0x4f, 0xdf, 0xfd, 0x0a, 0x09, 0x30, 0x28, - 0x1b, 0x7d, 0x91, 0x56, 0x04, 0x8f, 0x56, 0x83, 0x2f, 0x06, 0x96, 0x88, 0x82, 0x0b, 0xa3, 0x05, 0xde, 0x32, 0xfa, - 0xc2, 0x46, 0x1b, 0x5c, 0xa1, 0x19, 0xe9, 0xb8, 0x4c, 0xed, 0xa3, 0x7d, 0x1f, 0xc0, 0xae, 0x80, 0xd9, 0xda, 0x35, - 0x20, 0x88, 0x96, 0xba, 0x30, 0xa8, 0x48, 0xe1, 0x5a, 0xeb, 0x84, 0xf1, 0x3a, 0x71, 0xdb, 0x38, 0xdc, 0x87, 0x00, - 0x8c, 0xc0, 0x5d, 0xd1, 0x03, 0x0b, 0x44, 0xa5, 0x1e, 0x1d, 0x8d, 0x4b, 0x79, 0x51, 0x97, 0x18, 0xc9, 0x74, 0xdd, - 0x0f, 0xdb, 0xdf, 0xbb, 0x87, 0xbd, 0xf8, 0x94, 0xae, 0x07, 0xda, 0x6d, 0xe9, 0xa5, 0xe8, 0xa1, 0x87, 0xd6, 0x3d, - 0x68, 0x5e, 0x81, 0xde, 0xcb, 0x66, 0x93, 0x44, 0xdd, 0x17, 0xf4, 0xb6, 0x61, 0xfb, 0x5f, 0xda, 0xd0, 0xc0, 0x50, - 0xb5, 0x98, 0x89, 0x52, 0x91, 0x05, 0x61, 0x2c, 0xf4, 0xf7, 0x31, 0xdd, 0x2b, 0xb3, 0x23, 0x5f, 0x31, 0x37, 0xe3, - 0x30, 0x0f, 0x1a, 0xbd, 0x4b, 0xd5, 0x1f, 0x8c, 0xb9, 0x33, 0x34, 0x04, 0x3d, 0x28, 0x0f, 0x90, 0x06, 0x89, 0x41, - 0xab, 0x52, 0x28, 0xe0, 0x12, 0x52, 0xc9, 0x7e, 0x77, 0xf4, 0xcb, 0x4d, 0xbb, 0x6a, 0x0c, 0xc1, 0xa7, 0x77, 0x0e, - 0x10, 0x50, 0xb0, 0x8a, 0x83, 0x34, 0x48, 0xde, 0x90, 0xc3, 0x88, 0xe9, 0x3b, 0x0e, 0x70, 0x75, 0xe0, 0x77, 0xa5, - 0xc4, 0x79, 0x46, 0x08, 0x3d, 0xfe, 0x2f, 0x54, 0xbd, 0x6f, 0x2f, 0x85, 0x19, 0x94, 0x0d, 0xcf, 0x6b, 0x6a, 0x7a, - 0x36, 0xb4, 0x85, 0xfd, 0xbf, 0x4b, 0xc5, 0xfc, 0x96, 0x79, 0xa9, 0xc4, 0x96, 0xca, 0x07, 0x8c, 0xc1, 0x0f, 0x7f, - 0x78, 0x53, 0x73, 0xb1, 0xe4, 0x8d, 0x92, 0xca, 0x82, 0xda, 0xb9, 0xb9, 0xce, 0x6c, 0x60, 0x4f, 0x39, 0x29, 0xb6, - 0xa1, 0x9f, 0x86, 0xfb, 0x21, 0xe7, 0x0a, 0xe8, 0x38, 0xd5, 0x18, 0x2e, 0x24, 0xc1, 0xae, 0x83, 0x9d, 0x8c, 0x6a, - 0x73, 0xc3, 0xe0, 0x5a, 0x89, 0xef, 0x80, 0xb7, 0x03, 0x4c, 0x81, 0xef, 0xe7, 0x7b, 0xf9, 0x33, 0x42, 0xec, 0xb1, - 0x4c, 0x24, 0x01, 0x54, 0x62, 0x45, 0x4f, 0x39, 0x94, 0xb7, 0x8a, 0x6f, 0x65, 0x9e, 0x6a, 0xee, 0xcd, 0xd5, 0x65, - 0x06, 0x5a, 0x2c, 0x32, 0x8a, 0x2f, 0xc0, 0x8e, 0xea, 0x59, 0xfc, 0x17, 0xfa, 0x09, 0x8c, 0xe8, 0xc2, 0xc9, 0x4d, - 0x05, 0x8c, 0x6d, 0x23, 0x1d, 0x4e, 0x75, 0x2f, 0x51, 0xc4, 0x65, 0xa3, 0x11, 0x83, 0x37, 0x58, 0xe2, 0x95, 0x56, - 0x69, 0x7b, 0x4c, 0x82, 0x97, 0x8a, 0x09, 0x5b, 0x8c, 0x0a, 0xda, 0x48, 0x5f, 0x8c, 0x34, 0xd7, 0xa8, 0xdf, 0x8f, - 0xd7, 0xf6, 0x4b, 0x2b, 0x74, 0xcf, 0xe6, 0xa3, 0x82, 0xa0, 0xf1, 0x86, 0x00, 0x02, 0xec, 0x5e, 0x82, 0xae, 0xb8, - 0x63, 0xc8, 0x54, 0xc9, 0xe0, 0x3b, 0x85, 0x47, 0xac, 0xfa, 0xd3, 0xcd, 0xcf, 0xe5, 0x96, 0x95, 0x21, 0x65, 0xdb, - 0xdb, 0xdc, 0xbc, 0x1f, 0x61, 0xd3, 0x38, 0xc3, 0x88, 0x19, 0xf5, 0x0c, 0x18, 0xc3, 0x12, 0x00, 0xab, 0xb8, 0xa0, - 0xde, 0x3c, 0x74, 0x99, 0xdd, 0x30, 0xbd, 0x5e, 0xe9, 0x69, 0x1a, 0x44, 0xb0, 0xb7, 0xec, 0x4d, 0x12, 0xb6, 0x2b, - 0x1b, 0x2f, 0xa1, 0x63, 0xde, 0x7a, 0xc8, 0x59, 0x42, 0xdc, 0x10, 0xd6, 0xc2, 0xdd, 0x4b, 0xc4, 0x7d, 0xee, 0x62, - 0x7d, 0x22, 0x12, 0x1e, 0xf5, 0x02, 0xdd, 0xcb, 0x97, 0x15, 0xc8, 0x99, 0x66, 0xe9, 0xfd, 0x2f, 0x58, 0xeb, 0xca, - 0x65, 0x83, 0x66, 0xa0, 0x47, 0x07, 0xc5, 0x44, 0xcb, 0xe0, 0x02, 0x54, 0x14, 0xbb, 0x9a, 0x58, 0xe6, 0xd1, 0x04, - 0x28, 0xa4, 0x2c, 0x29, 0x4d, 0x26, 0x33, 0x56, 0x50, 0x60, 0x1a, 0xec, 0xbc, 0x78, 0xc0, 0xa0, 0x62, 0x93, 0xa9, - 0x4c, 0xac, 0x2c, 0x24, 0x09, 0x0e, 0x66, 0x85, 0xe6, 0x7a, 0x95, 0xdb, 0x41, 0x08, 0x59, 0x1d, 0x60, 0xdf, 0xac, - 0x64, 0x02, 0x6a, 0x1f, 0xe6, 0xb1, 0x63, 0x54, 0x52, 0x40, 0xbf, 0x10, 0x42, 0x6e, 0x77, 0x87, 0x3b, 0x6a, 0x8e, - 0x4e, 0x2f, 0x72, 0x97, 0x0c, 0x29, 0xf2, 0xdd, 0x17, 0x81, 0x63, 0x66, 0xe4, 0x32, 0xab, 0x84, 0xa8, 0x7b, 0x2b, - 0x5a, 0xc6, 0x2f, 0xe8, 0xef, 0x5c, 0xfa, 0x84, 0xd2, 0x82, 0x58, 0x74, 0x38, 0xa8, 0x01, 0xb2, 0xcd, 0x0e, 0x73, - 0x58, 0xda, 0xcd, 0x0b, 0x4b, 0xf0, 0x59, 0xfe, 0x36, 0xf6, 0xec, 0x27, 0x4f, 0xd7, 0xd5, 0x37, 0x5f, 0xc3, 0x28, - 0xe6, 0x5e, 0x6f, 0x34, 0x79, 0xbb, 0xc3, 0x08, 0xe1, 0x44, 0xda, 0xed, 0xf6, 0xd0, 0xc3, 0x15, 0x24, 0x60, 0x83, - 0x83, 0x4b, 0xaf, 0x6e, 0x9f, 0xac, 0x7f, 0xd5, 0x85, 0x39, 0xff, 0x99, 0x06, 0x70, 0x08, 0x19, 0x42, 0xda, 0x04, - 0x41, 0x0f, 0x43, 0x05, 0x6b, 0x2a, 0xb6, 0x32, 0x96, 0x25, 0xfd, 0x80, 0x58, 0xdf, 0xe0, 0xb2, 0x95, 0x65, 0xd4, - 0x42, 0xf0, 0xfc, 0x17, 0x07, 0x08, 0xde, 0x16, 0x9c, 0xfd, 0xd7, 0xc8, 0xc2, 0xf7, 0x8e, 0x0d, 0x52, 0xfa, 0x58, - 0x79, 0x67, 0xb8, 0x6c, 0xaa, 0xd9, 0xc0, 0x8e, 0xac, 0x5c, 0xef, 0xe9, 0x4d, 0x85, 0x32, 0xda, 0x8c, 0x1a, 0xd5, - 0xa6, 0xcc, 0xd2, 0x18, 0xbe, 0x47, 0xb3, 0xa8, 0x4f, 0x52, 0xbd, 0x61, 0x6f, 0xb6, 0x16, 0xb5, 0x83, 0xa9, 0xc6, - 0xf0, 0xde, 0xfe, 0xa9, 0xd9, 0x04, 0x81, 0xd2, 0x09, 0x76, 0xdc, 0x81, 0x8f, 0x94, 0x9e, 0x22, 0xa6, 0x1d, 0x44, - 0xfc, 0xbd, 0x95, 0xec, 0xe8, 0xf7, 0x38, 0x8a, 0x9f, 0x91, 0x31, 0x00, 0x31, 0xba, 0x2d, 0x4c, 0x41, 0xa4, 0x84, - 0xe6, 0x07, 0x2f, 0x14, 0xc4, 0x53, 0xa2, 0x01, 0x50, 0x76, 0x9b, 0xba, 0x02, 0xfb, 0x8c, 0x2f, 0x59, 0x5b, 0xcd, - 0x61, 0x3a, 0xd0, 0xb2, 0x60, 0xbd, 0xcb, 0xe9, 0x39, 0x53, 0x96, 0x5c, 0x6b, 0x37, 0x28, 0xc4, 0xfd, 0x57, 0xcb, - 0xbb, 0x05, 0x96, 0xb3, 0xc7, 0xbf, 0xdf, 0xc8, 0x4f, 0xdc, 0x2a, 0x1b, 0xc2, 0xac, 0x87, 0x4c, 0x91, 0x25, 0x39, - 0x0c, 0x32, 0xad, 0xa5, 0xfb, 0x07, 0x32, 0x68, 0x6e, 0xb7, 0xf5, 0x14, 0xd6, 0xe4, 0xf9, 0xe0, 0xcb, 0x0e, 0x64, - 0x67, 0x0a, 0x61, 0xa0, 0x7f, 0xd9, 0xde, 0x5e, 0x80, 0xce, 0x4d, 0x86, 0xb8, 0xbb, 0xe2, 0x8d, 0x73, 0x51, 0xde, - 0xf8, 0xe5, 0xb6, 0x13, 0x56, 0xd0, 0xb6, 0x88, 0xa6, 0x41, 0xb5, 0xfc, 0x3d, 0xa2, 0xbc, 0xd8, 0xac, 0xb6, 0x7c, - 0x3e, 0x55, 0x46, 0x4f, 0x2f, 0x41, 0x37, 0xe8, 0x07, 0x43, 0xc4, 0xb7, 0x9f, 0xb5, 0xe3, 0x23, 0xd3, 0x96, 0x3f, - 0xb5, 0xed, 0x19, 0x22, 0xfa, 0xd9, 0xee, 0x11, 0xed, 0xd8, 0x03, 0x68, 0x78, 0x58, 0xa9, 0xa1, 0x83, 0xde, 0x43, - 0xc1, 0x3c, 0xc5, 0x5b, 0x90, 0xc3, 0xe6, 0xc1, 0xf2, 0x0e, 0x10, 0xd9, 0x42, 0xb9, 0x64, 0x6f, 0x21, 0xbd, 0xf3, - 0xf6, 0xcc, 0xc9, 0xe0, 0x91, 0x9e, 0x20, 0x9e, 0x22, 0x80, 0x74, 0x0c, 0x26, 0xbb, 0x75, 0xa9, 0xf5, 0x6c, 0xa2, - 0x00, 0x3b, 0xa7, 0x70, 0x1a, 0xf3, 0x5c, 0xd2, 0x08, 0x82, 0x3d, 0x6b, 0x12, 0x69, 0x09, 0x51, 0xe8, 0xa3, 0xb3, - 0x6d, 0xfb, 0x24, 0x2f, 0x23, 0x5f, 0x87, 0xd8, 0xac, 0xd2, 0xdf, 0x58, 0xe5, 0xc4, 0xd5, 0x23, 0x9f, 0xcf, 0x5d, - 0xe8, 0xe7, 0xcc, 0x20, 0x42, 0xbb, 0xb0, 0x92, 0xd1, 0xa8, 0xc8, 0x34, 0x7a, 0x45, 0xb2, 0x97, 0x0a, 0x21, 0x19, - 0x46, 0x37, 0x46, 0xb1, 0x87, 0x23, 0x67, 0x53, 0xc9, 0x12, 0x76, 0x61, 0x89, 0xf3, 0x5f, 0xea, 0x0c, 0xf4, 0x52, - 0x15, 0x4d, 0xe6, 0xa2, 0x9c, 0x6b, 0x87, 0x34, 0x19, 0x00, 0x43, 0x8d, 0xb7, 0x09, 0x9e, 0xf6, 0xa8, 0xc6, 0xab, - 0x56, 0xe4, 0x48, 0xd8, 0x7c, 0x5c, 0xc4, 0x8e, 0xf1, 0x80, 0x3c, 0x62, 0x1c, 0x0f, 0x3e, 0xc7, 0x83, 0x06, 0x48, - 0xfe, 0x44, 0x0a, 0x3e, 0x7a, 0x5e, 0x31, 0x07, 0xb3, 0x0d, 0x6c, 0xcf, 0x44, 0x53, 0x05, 0xb3, 0x93, 0xf5, 0x1e, - 0x50, 0x47, 0xc5, 0x50, 0x38, 0x32, 0xec, 0xc1, 0x70, 0xa6, 0xde, 0xb1, 0xf5, 0x39, 0x3b, 0x68, 0x79, 0x50, 0x25, - 0x19, 0x08, 0x5c, 0x7c, 0x18, 0x71, 0x8d, 0x4f, 0xea, 0x05, 0xd0, 0x1c, 0x79, 0xa5, 0xc5, 0xc7, 0xa3, 0x61, 0xc2, - 0x11, 0x43, 0x46, 0x7f, 0xb4, 0x31, 0xd5, 0x90, 0x6e, 0x97, 0xae, 0x77, 0x13, 0xbe, 0x4a, 0xc9, 0xd2, 0xcd, 0x51, - 0xf6, 0x9a, 0xc6, 0x03, 0xcd, 0x75, 0x33, 0xdb, 0x97, 0x7f, 0xc7, 0x74, 0x8e, 0xcc, 0x45, 0xc2, 0xba, 0x29, 0xb7, - 0xa8, 0xe3, 0x2e, 0x3e, 0x1c, 0x8e, 0x8c, 0x61, 0x7b, 0xf0, 0x44, 0xee, 0x30, 0xc7, 0xb1, 0xbf, 0xb2, 0xe0, 0x46, - 0xe9, 0x25, 0xc7, 0xe2, 0xab, 0xd9, 0x84, 0x2c, 0x66, 0x29, 0x50, 0xb1, 0xea, 0xb7, 0x01, 0xb6, 0xd8, 0x8a, 0x5a, - 0x27, 0x51, 0xef, 0x33, 0x8d, 0x98, 0x5b, 0xb6, 0x3c, 0x22, 0x08, 0xf2, 0x8d, 0xac, 0xa6, 0x79, 0xd4, 0x58, 0x06, - 0xa8, 0x6b, 0x12, 0x8b, 0x5a, 0xee, 0x50, 0x90, 0x59, 0xe8, 0x20, 0xa4, 0xd7, 0x29, 0x8c, 0x47, 0x2e, 0x57, 0xc8, - 0x74, 0xa9, 0xf3, 0x80, 0x17, 0x2b, 0xc7, 0x46, 0xbf, 0xfe, 0x78, 0x20, 0xaf, 0x48, 0xc4, 0x72, 0x82, 0x2f, 0xe1, - 0xd2, 0x98, 0x31, 0x90, 0x4c, 0xb4, 0x4f, 0x45, 0x2b, 0xf6, 0x63, 0x44, 0x5d, 0x48, 0xf4, 0x58, 0x70, 0x44, 0xb2, - 0x23, 0x61, 0x7f, 0x28, 0x8a, 0x21, 0x89, 0xc7, 0x9c, 0x63, 0x1a, 0x78, 0xdf, 0x16, 0xbd, 0xed, 0x70, 0x68, 0x5b, - 0x94, 0xd7, 0x8a, 0x0b, 0x74, 0xca, 0x92, 0x1b, 0xe0, 0x25, 0xaf, 0x7e, 0xc2, 0xee, 0x1a, 0x07, 0xe5, 0xeb, 0xe2, - 0xee, 0xed, 0x26, 0xc1, 0xc0, 0x3b, 0x88, 0xf3, 0x7a, 0x19, 0xc5, 0xf1, 0xbb, 0x5d, 0xf0, 0xea, 0x98, 0xcf, 0x08, - 0x18, 0x3c, 0x42, 0x3a, 0x91, 0xed, 0x35, 0x27, 0x78, 0xf8, 0xa1, 0xd4, 0x1f, 0x0b, 0x28, 0x67, 0x85, 0xbf, 0x51, - 0xa6, 0xb6, 0x8d, 0x2e, 0xa4, 0xe4, 0xe3, 0x52, 0x7a, 0x17, 0x62, 0xc4, 0x80, 0x5c, 0xed, 0xca, 0xf7, 0x62, 0x55, - 0x7a, 0x54, 0x6a, 0xc4, 0x17, 0xf4, 0x8a, 0xa1, 0x35, 0x46, 0xbd, 0xe3, 0x66, 0x9d, 0x08, 0x13, 0x83, 0xaf, 0xa8, - 0x9d, 0xb4, 0xcd, 0x98, 0x08, 0x81, 0x34, 0x59, 0xb4, 0x7e, 0xb2, 0x88, 0xc2, 0x42, 0x28, 0x62, 0xc2, 0x12, 0x2d, - 0x87, 0x04, 0x04, 0x91, 0x21, 0x8d, 0xf0, 0x98, 0xbb, 0x96, 0x03, 0xe3, 0x01, 0x8c, 0xa5, 0xb8, 0xf7, 0x8f, 0xaf, - 0x46, 0x30, 0x05, 0x11, 0x3c, 0xd5, 0x95, 0x17, 0x49, 0x43, 0x63, 0x35, 0xcc, 0x43, 0x73, 0x21, 0x47, 0x19, 0x78, - 0x33, 0x27, 0x58, 0x5c, 0xb5, 0x32, 0xc2, 0x4d, 0x7f, 0xb6, 0xfb, 0x50, 0xcf, 0x9d, 0x83, 0x36, 0x27, 0xcb, 0x59, - 0xb2, 0xd2, 0x1f, 0x6d, 0x4f, 0x10, 0x81, 0xc8, 0x60, 0x06, 0x52, 0x57, 0x04, 0x42, 0x42, 0x1c, 0x45, 0x92, 0x9b, - 0x27, 0x87, 0x08, 0xc4, 0xe7, 0xe5, 0x17, 0xfa, 0x20, 0x03, 0x4a, 0x64, 0xbd, 0xbe, 0x59, 0x01, 0xd3, 0x13, 0x4e, - 0x21, 0xc5, 0x1e, 0xab, 0x82, 0x41, 0x46, 0x24, 0xcc, 0x16, 0x27, 0x0c, 0x99, 0xd7, 0x57, 0xbf, 0x77, 0x38, 0x35, - 0x3c, 0xe8, 0x00, 0x30, 0xaa, 0x1c, 0x41, 0x21, 0x92, 0x3f, 0x29, 0x60, 0x58, 0x21, 0xe1, 0xdd, 0x9b, 0xe4, 0xc2, - 0x89, 0x6c, 0x63, 0x55, 0x79, 0x25, 0xac, 0x7e, 0xa8, 0x81, 0x67, 0x24, 0x04, 0xa6, 0xa8, 0x18, 0xdb, 0xbf, 0xff, - 0x59, 0x55, 0x49, 0x1a, 0x2f, 0x92, 0x94, 0x7e, 0xed, 0x71, 0x5b, 0xa8, 0x85, 0x86, 0x49, 0x9a, 0x1d, 0xea, 0x6d, - 0x67, 0x12, 0x39, 0xe3, 0x10, 0x72, 0x16, 0x62, 0x00, 0x88, 0x97, 0xc1, 0xe0, 0x43, 0xeb, 0x63, 0xda, 0x01, 0xa7, - 0x5f, 0xbb, 0x67, 0x65, 0xf4, 0xa3, 0x35, 0xcf, 0xe8, 0xc2, 0xf9, 0xe9, 0x51, 0xad, 0x26, 0x7e, 0x48, 0xe0, 0xac, - 0x84, 0x5e, 0x8a, 0x59, 0x35, 0x1e, 0x67, 0xae, 0xf8, 0x7a, 0x74, 0x6a, 0xab, 0x40, 0xac, 0x2a, 0x0d, 0x37, 0xc2, - 0x78, 0xf6, 0x40, 0xb2, 0x79, 0x14, 0x7e, 0xa4, 0x92, 0x71, 0xaf, 0x38, 0xc2, 0x0c, 0xd1, 0x06, 0x7a, 0xce, 0x0b, - 0x58, 0xce, 0xca, 0x22, 0x19, 0x79, 0x1d, 0x0a, 0x9a, 0xde, 0x38, 0xe4, 0x21, 0x53, 0x1c, 0x9c, 0xc9, 0x0a, 0x9f, - 0xd3, 0xa3, 0xe6, 0xc6, 0x28, 0xab, 0x60, 0x63, 0x34, 0x9f, 0x96, 0x9e, 0x3c, 0x90, 0x4d, 0x63, 0x9a, 0xd2, 0xa2, - 0xa4, 0x21, 0x71, 0xa9, 0x6a, 0xe6, 0x68, 0x1e, 0x98, 0x43, 0xac, 0x6f, 0x5f, 0x70, 0xf6, 0x88, 0xe7, 0xe3, 0x82, - 0x14, 0xa4, 0xcd, 0xf4, 0xa8, 0xe4, 0xfa, 0xf3, 0x33, 0x20, 0xac, 0xbc, 0x7d, 0xb0, 0xe1, 0xd7, 0x15, 0x12, 0xd9, - 0xde, 0xbc, 0x1c, 0xa0, 0x68, 0xc2, 0xaf, 0x1d, 0x6c, 0xd6, 0x57, 0x96, 0x38, 0xbe, 0x35, 0x5b, 0x15, 0x44, 0x4e, - 0x66, 0x46, 0xbf, 0xee, 0x05, 0xac, 0x15, 0x61, 0xca, 0xd9, 0xd9, 0xe6, 0x1a, 0xa0, 0xa5, 0xe0, 0x38, 0x2a, 0x46, - 0x7c, 0x54, 0xcf, 0x48, 0x65, 0x26, 0xbd, 0xc6, 0x42, 0x97, 0xe1, 0x0b, 0x35, 0xf5, 0x5a, 0xd4, 0x7c, 0xe4, 0x43, - 0x46, 0x84, 0x9d, 0x46, 0xb8, 0xf8, 0xc6, 0xc0, 0x6b, 0x79, 0x1a, 0x9d, 0x07, 0x7a, 0x2f, 0x36, 0x5b, 0x9e, 0xf8, - 0xee, 0xba, 0x4d, 0x8e, 0x8f, 0xb1, 0x35, 0x5b, 0x36, 0x63, 0xf9, 0xe9, 0xf5, 0x27, 0xa3, 0x2a, 0xa1, 0x66, 0xeb, - 0xbe, 0x9f, 0xba, 0x7e, 0x3d, 0x34, 0xcf, 0xf3, 0x36, 0x6d, 0x1b, 0xe7, 0xe6, 0xde, 0x80, 0x6c, 0x2f, 0x0a, 0xe6, - 0xb9, 0xd0, 0x9c, 0x36, 0xb4, 0x3e, 0xbd, 0x84, 0x59, 0x99, 0xd9, 0xd0, 0x76, 0x7d, 0xad, 0x7f, 0xa9, 0x28, 0x8c, - 0xd8, 0xfa, 0x80, 0x13, 0x51, 0x4a, 0x54, 0x5a, 0xe5, 0xe7, 0x4b, 0x6f, 0x45, 0x48, 0x9e, 0xcb, 0x7e, 0x19, 0x4d, - 0xff, 0x09, 0xbd, 0x56, 0x26, 0x42, 0xf1, 0x35, 0x73, 0xee, 0x59, 0x2d, 0xf9, 0xd7, 0x52, 0xb1, 0x74, 0xac, 0x71, - 0xd5, 0x7a, 0x5e, 0xc6, 0x93, 0x6b, 0xb8, 0x3e, 0x4e, 0xd1, 0x7a, 0xc6, 0x48, 0x7f, 0x0e, 0xae, 0x44, 0xa4, 0x16, - 0x97, 0xbe, 0x03, 0x73, 0x25, 0x0a, 0xc9, 0xd5, 0x54, 0x7a, 0xf6, 0x56, 0xf5, 0x38, 0xd1, 0x3c, 0x23, 0x73, 0xef, - 0xca, 0xbe, 0x59, 0x95, 0xd6, 0x5e, 0x93, 0x57, 0x29, 0x1c, 0x9f, 0xe0, 0x3a, 0xb9, 0x77, 0x4f, 0x31, 0x25, 0x88, - 0x10, 0xba, 0x38, 0xed, 0x0b, 0xbf, 0x42, 0x38, 0xe0, 0xf5, 0xd4, 0x69, 0xdd, 0x5e, 0x52, 0x2d, 0x41, 0x9c, 0xab, - 0x3b, 0x9c, 0xb3, 0x5b, 0x73, 0xb6, 0x90, 0x1d, 0x67, 0x59, 0xa1, 0x9e, 0x6e, 0x0e, 0x19, 0x76, 0x28, 0x78, 0x86, - 0x5c, 0xb7, 0x57, 0xd3, 0x67, 0x23, 0x32, 0x71, 0xab, 0xdd, 0xbe, 0x45, 0x72, 0x79, 0x1a, 0x00, 0xc1, 0x18, 0xfe, - 0x79, 0xd1, 0x9e, 0x8c, 0xce, 0x84, 0x05, 0xb3, 0x21, 0x90, 0x06, 0x8c, 0x19, 0x24, 0xc2, 0xe3, 0x3f, 0x91, 0xff, - 0x57, 0x93, 0xdf, 0x78, 0x31, 0xce, 0xa9, 0xe3, 0x37, 0xef, 0x35, 0xa0, 0x24, 0x66, 0xc1, 0x89, 0x0d, 0xaf, 0x82, - 0x6c, 0x99, 0xb6, 0x81, 0x63, 0xb0, 0x4c, 0x7f, 0x0c, 0xca, 0xd8, 0x0b, 0x48, 0x32, 0xf1, 0x8e, 0x84, 0xea, 0x74, - 0xd6, 0x5e, 0x1c, 0x09, 0x5c, 0xce, 0x99, 0xe4, 0xe8, 0x02, 0x1b, 0x33, 0xc1, 0xd3, 0xee, 0x30, 0xd2, 0xcf, 0x50, - 0xbc, 0x96, 0xab, 0xdb, 0xc8, 0x00, 0xa1, 0x04, 0x13, 0xea, 0x13, 0xd2, 0xfe, 0xed, 0xe1, 0x88, 0x81, 0x44, 0x81, - 0x26, 0x0b, 0x76, 0x80, 0x4d, 0xa1, 0xae, 0xdd, 0x3c, 0x96, 0x36, 0xc6, 0x23, 0x69, 0x94, 0x61, 0x71, 0x59, 0x91, - 0xd1, 0x4a, 0x5f, 0x39, 0x9a, 0x2d, 0x1c, 0xfb, 0xce, 0x62, 0xb0, 0xd0, 0x86, 0xab, 0x97, 0x09, 0xba, 0x9f, 0x3a, - 0xf2, 0xca, 0xff, 0x6a, 0xb2, 0xea, 0xd6, 0x67, 0x6f, 0xf2, 0x95, 0x43, 0x46, 0xdc, 0x5e, 0x3d, 0x7f, 0x8c, 0x47, - 0x4f, 0xb5, 0xd2, 0x87, 0x11, 0x67, 0x18, 0x54, 0xb9, 0x2d, 0x08, 0xcf, 0x6a, 0x32, 0x6c, 0x74, 0x14, 0xf4, 0x03, - 0x4d, 0x09, 0x66, 0xec, 0xc7, 0xd4, 0x04, 0x58, 0xf2, 0xa4, 0xb3, 0xb0, 0xf2, 0x7a, 0x76, 0x1d, 0x6f, 0x73, 0x81, - 0xe5, 0x13, 0x8e, 0x3d, 0xd8, 0xc4, 0x0a, 0x9b, 0x0a, 0x9b, 0x24, 0x2e, 0x3c, 0xb1, 0xb2, 0x8c, 0x78, 0xe1, 0x0a, - 0x5b, 0xa7, 0x3c, 0x95, 0xc2, 0x6e, 0xe8, 0xca, 0xaf, 0xf5, 0xca, 0x8b, 0xd1, 0x79, 0x1d, 0xa3, 0x9b, 0xe4, 0x26, - 0x86, 0x60, 0x30, 0xec, 0x46, 0x4e, 0xfa, 0xf6, 0x40, 0xc9, 0xe0, 0x06, 0x0d, 0xca, 0xd7, 0x91, 0xb5, 0x42, 0x3c, - 0xd7, 0x95, 0x0b, 0x67, 0x9e, 0x00, 0x98, 0x2f, 0xaf, 0x17, 0xda, 0x44, 0x07, 0x3b, 0xbe, 0x9f, 0xf7, 0x05, 0x0b, - 0x78, 0xd9, 0x21, 0x96, 0x95, 0x37, 0x3b, 0xfd, 0x05, 0x6e, 0x38, 0x73, 0x6d, 0x9b, 0x51, 0x6d, 0xa1, 0x97, 0xe8, - 0xc8, 0xdc, 0xb3, 0x64, 0xab, 0x89, 0x80, 0xb3, 0x03, 0xc1, 0xa2, 0x24, 0xe6, 0x09, 0x82, 0x25, 0x7e, 0xc2, 0x03, - 0x59, 0xd8, 0x2f, 0xcd, 0xa5, 0xe8, 0x89, 0xf6, 0xfa, 0xa5, 0xf9, 0x9c, 0x5f, 0x84, 0x43, 0x7c, 0xae, 0x28, 0xeb, - 0xa1, 0xce, 0xe3, 0x20, 0x8a, 0xa3, 0x5f, 0x33, 0x95, 0xd0, 0xfe, 0x31, 0x5a, 0x94, 0x34, 0x76, 0x59, 0xb8, 0xd2, - 0xca, 0x9a, 0x70, 0x95, 0x76, 0x93, 0x41, 0x5e, 0x89, 0x67, 0x5e, 0x65, 0x5d, 0xd6, 0x1c, 0xdf, 0x83, 0xba, 0x1d, - 0x39, 0xfb, 0xac, 0xa1, 0x4a, 0x0e, 0xd0, 0xfe, 0xe0, 0xa1, 0xb3, 0x08, 0x6a, 0x08, 0xae, 0x6e, 0x7c, 0x82, 0x38, - 0xe0, 0x32, 0x08, 0xa9, 0x0c, 0xfb, 0x52, 0xc9, 0xbf, 0x91, 0x32, 0x8a, 0xff, 0xab, 0x34, 0xaf, 0x1e, 0x18, 0x84, - 0xaf, 0xbb, 0x9b, 0x5f, 0x01, 0xb2, 0xb5, 0x30, 0x33, 0xb8, 0xc9, 0x6d, 0x13, 0xf7, 0x45, 0x39, 0x68, 0x1b, 0xac, - 0x97, 0x16, 0xa1, 0x0f, 0x1a, 0x8f, 0x34, 0x61, 0xf5, 0x39, 0x5c, 0x0b, 0x02, 0x37, 0x75, 0xfe, 0x78, 0x3c, 0xc9, - 0xd4, 0x14, 0x9a, 0xc6, 0xee, 0x4c, 0x5a, 0x8e, 0x30, 0x90, 0x30, 0x40, 0x36, 0x3e, 0xb0, 0x6d, 0xe9, 0xf6, 0x66, - 0x11, 0x5c, 0xaf, 0x41, 0x50, 0xca, 0x96, 0x45, 0x07, 0x47, 0x63, 0xb6, 0xc1, 0x9c, 0xee, 0x13, 0x8d, 0xc8, 0xae, - 0x60, 0x38, 0x0b, 0x23, 0xd7, 0x5f, 0x9c, 0x35, 0xeb, 0x2e, 0x28, 0x52, 0x3d, 0xf2, 0xa1, 0xd8, 0x46, 0x00, 0x4f, - 0xa8, 0xf4, 0xf1, 0xc0, 0x23, 0x8a, 0x56, 0x87, 0x14, 0x1e, 0x16, 0x85, 0x43, 0xbe, 0xc1, 0x38, 0x1d, 0xa1, 0x3e, - 0x39, 0x82, 0x31, 0x45, 0x7e, 0xf8, 0x8b, 0x85, 0xf1, 0xb5, 0x7c, 0x81, 0x79, 0x5a, 0x69, 0x11, 0x77, 0x3d, 0xe5, - 0xb6, 0xcf, 0xed, 0xe1, 0x13, 0x2f, 0x21, 0x1b, 0xa1, 0xdf, 0x47, 0x7e, 0xd4, 0x6c, 0xfd, 0xe7, 0x01, 0xe6, 0xdb, - 0xc1, 0x1a, 0x4c, 0x38, 0x2a, 0x78, 0xa4, 0x1f, 0x5d, 0x99, 0x76, 0x83, 0x82, 0xf5, 0x21, 0x94, 0x32, 0x3a, 0x71, - 0xd0, 0xed, 0x6a, 0xe6, 0xbf, 0x3c, 0x76, 0x31, 0x02, 0x59, 0x48, 0xe2, 0xe7, 0xa5, 0xec, 0xdb, 0xba, 0x0c, 0x6b, - 0x69, 0xe9, 0xe6, 0x69, 0x22, 0x86, 0xcb, 0x24, 0xa8, 0xbc, 0xea, 0x11, 0x11, 0x23, 0x52, 0x16, 0x4c, 0xbd, 0x8c, - 0xbf, 0xe3, 0x3b, 0x63, 0x17, 0xb5, 0x6e, 0x23, 0xb5, 0x6e, 0xaf, 0x7a, 0xb3, 0xb5, 0xeb, 0xc3, 0x36, 0x0e, 0xf0, - 0xde, 0xd2, 0x4f, 0x50, 0xa0, 0xf1, 0x4a, 0x3b, 0xfa, 0xed, 0x40, 0x4c, 0xf8, 0x87, 0xd8, 0x35, 0x89, 0xee, 0x0b, - 0x86, 0x2b, 0xb5, 0xc9, 0xda, 0x06, 0xc6, 0x08, 0xc5, 0x5a, 0x9e, 0x47, 0x70, 0x9e, 0x8d, 0x1c, 0x15, 0xda, 0x65, - 0x8c, 0xcf, 0xc8, 0x8e, 0xf1, 0x4f, 0xc8, 0xca, 0x16, 0x46, 0x70, 0x4f, 0x72, 0x2a, 0x92, 0xe8, 0xfc, 0x14, 0x05, - 0xf2, 0x46, 0xeb, 0x12, 0x1d, 0x78, 0x7d, 0xd1, 0x2c, 0x1e, 0xfe, 0x1e, 0x2d, 0x29, 0x44, 0x38, 0x78, 0x7c, 0x47, - 0x84, 0x50, 0xab, 0x29, 0x54, 0x47, 0x5b, 0x0c, 0x32, 0x7b, 0x7c, 0x4a, 0x36, 0x5f, 0x64, 0x1b, 0x1c, 0xb1, 0x04, - 0x3f, 0xa9, 0xec, 0xc7, 0x95, 0x4d, 0xfc, 0x48, 0xff, 0x43, 0x69, 0xc9, 0xa9, 0x8e, 0xd7, 0x74, 0x55, 0x43, 0x53, - 0xe8, 0x0a, 0xb5, 0x11, 0x1d, 0x87, 0xfd, 0x2b, 0x94, 0x49, 0x9d, 0x6a, 0xda, 0x20, 0x6a, 0x1d, 0xf4, 0x3d, 0x5a, - 0x70, 0xbf, 0xf2, 0x3a, 0xf2, 0x45, 0x0c, 0x22, 0x27, 0xe8, 0x57, 0x62, 0x73, 0x25, 0x9f, 0xa7, 0xd1, 0x9d, 0xb7, - 0x54, 0xb2, 0xb1, 0x11, 0x2a, 0xca, 0xda, 0xdb, 0xe4, 0x52, 0xca, 0x5b, 0x4f, 0xe8, 0x29, 0xf7, 0xf2, 0xc1, 0x6c, - 0x93, 0xc6, 0x22, 0x22, 0x4e, 0x36, 0x1e, 0xae, 0xe3, 0x0d, 0x79, 0xa1, 0xd8, 0x82, 0x91, 0x0a, 0x5a, 0x83, 0x97, - 0x9d, 0xb3, 0x8c, 0xf2, 0x95, 0x38, 0x5e, 0xe4, 0x6f, 0xbb, 0xd9, 0x20, 0x9e, 0x1f, 0x06, 0xde, 0x47, 0x12, 0xea, - 0xac, 0x40, 0xc2, 0x1c, 0x77, 0x90, 0x05, 0xcb, 0x73, 0x25, 0x8f, 0x40, 0x32, 0x30, 0x52, 0xb4, 0x0d, 0xd3, 0xb9, - 0x14, 0x1f, 0xb4, 0x83, 0x8d, 0xb3, 0x41, 0x10, 0x1c, 0xd8, 0xf9, 0xfd, 0xfc, 0xeb, 0x5b, 0x1a, 0x83, 0xd3, 0xdb, - 0x2d, 0xc3, 0xff, 0x13, 0x5c, 0x9a, 0x45, 0xb4, 0x9c, 0xfe, 0x14, 0x63, 0xbe, 0xfc, 0x3f, 0xb9, 0x5b, 0x68, 0x1d, - 0xb4, 0xf0, 0x81, 0xed, 0x8e, 0x56, 0xdd, 0x46, 0x92, 0xda, 0xda, 0x0d, 0x06, 0x14, 0x66, 0x48, 0x39, 0x29, 0xa3, - 0x7a, 0x87, 0x46, 0x2f, 0x9c, 0x6e, 0x8e, 0x02, 0x30, 0xf7, 0xc1, 0xca, 0x7b, 0xca, 0x93, 0xdd, 0xbd, 0x02, 0x2b, - 0xb1, 0x1e, 0x0d, 0x90, 0xa3, 0xd4, 0xfe, 0x7d, 0xe1, 0xd4, 0xba, 0xa7, 0x25, 0xab, 0x6c, 0x38, 0x7f, 0xd1, 0x55, - 0x82, 0xb0, 0xc1, 0xd5, 0x53, 0xae, 0xcb, 0x2d, 0x7d, 0x5a, 0xa9, 0xca, 0x18, 0x1f, 0x0a, 0x09, 0x60, 0xa7, 0xaa, - 0x64, 0xdd, 0x19, 0xbf, 0x94, 0x62, 0x77, 0xac, 0xd9, 0xc9, 0x5f, 0x6f, 0x80, 0xdf, 0x2b, 0xe6, 0x75, 0x57, 0x8f, - 0xd6, 0x13, 0xd8, 0x93, 0x4b, 0x8f, 0xa1, 0x42, 0x60, 0x87, 0x97, 0x34, 0xd8, 0x7d, 0x90, 0x36, 0x0b, 0x93, 0x03, - 0x87, 0xe8, 0x34, 0x12, 0x3c, 0x57, 0x69, 0x69, 0xe4, 0xc4, 0x5b, 0x79, 0x62, 0xb7, 0x2e, 0x6e, 0xd2, 0x54, 0xc2, - 0x21, 0xa3, 0x90, 0x67, 0xf0, 0x86, 0x73, 0x89, 0xd2, 0xb3, 0xd9, 0xb4, 0xc9, 0x68, 0xc2, 0x79, 0x9a, 0xdf, 0x87, - 0x93, 0x6b, 0xac, 0x3e, 0xea, 0x98, 0xf4, 0x02, 0x38, 0x4b, 0xd1, 0x1a, 0xf1, 0xab, 0x03, 0x03, 0x0d, 0x2e, 0x2f, - 0xec, 0x25, 0x0b, 0xc1, 0x18, 0x6d, 0x63, 0x8f, 0x49, 0x07, 0x0e, 0xa1, 0xbe, 0x4e, 0x19, 0xc2, 0x0c, 0x2b, 0x88, - 0x60, 0x9a, 0xe2, 0xcc, 0xe1, 0x37, 0x70, 0xcf, 0x0a, 0x8c, 0x0a, 0xb9, 0x89, 0x0e, 0x23, 0xe0, 0x0a, 0xb7, 0x03, - 0x44, 0x76, 0xe6, 0x63, 0xc6, 0x6c, 0x9d, 0x71, 0xd8, 0xaf, 0x5c, 0x62, 0xd3, 0x1e, 0xa9, 0xfe, 0x8e, 0xdb, 0x7e, - 0x3b, 0xe1, 0xcf, 0x05, 0x8e, 0x62, 0x03, 0x71, 0x4f, 0xcb, 0x59, 0x4a, 0x2d, 0x1c, 0x1f, 0x47, 0x33, 0x8c, 0x43, - 0xe9, 0x9c, 0x32, 0xc9, 0x36, 0x0a, 0x9b, 0x01, 0xa4, 0xed, 0xe6, 0x90, 0x4c, 0x99, 0xa4, 0xb1, 0x38, 0x11, 0x85, - 0x2c, 0xfc, 0x12, 0xac, 0xcd, 0x2f, 0x36, 0x9f, 0xc0, 0x51, 0x85, 0xb9, 0xba, 0x23, 0xf0, 0x6e, 0xa1, 0xcc, 0x4b, - 0xe9, 0x28, 0xf4, 0x28, 0x4c, 0x9d, 0xb1, 0xd5, 0x0b, 0xeb, 0x94, 0x21, 0x64, 0x23, 0x5b, 0x67, 0x89, 0x16, 0x65, - 0x83, 0x7f, 0x1c, 0xff, 0x6b, 0x90, 0xd8, 0xf6, 0x20, 0xd8, 0xde, 0x32, 0x65, 0xa7, 0xef, 0x2d, 0xbf, 0xfb, 0x44, - 0x4f, 0x74, 0x07, 0x1c, 0x06, 0x5c, 0x75, 0x7a, 0xee, 0xa7, 0x3e, 0xbc, 0xcb, 0x06, 0xff, 0x0d, 0x37, 0x7e, 0x0a, - 0x5f, 0xa5, 0x8f, 0x0a, 0xe7, 0xfa, 0xca, 0x7b, 0x43, 0x1e, 0x6d, 0x53, 0xf3, 0x3b, 0x4f, 0x54, 0xbc, 0x21, 0xdf, - 0x4d, 0xbc, 0x9a, 0x13, 0xef, 0xc9, 0xe7, 0x9c, 0x6f, 0xa7, 0x4e, 0xc0, 0x62, 0xb0, 0x07, 0x3b, 0x64, 0xd7, 0x7b, - 0x6d, 0x54, 0x8c, 0x5f, 0x99, 0xdb, 0xfb, 0x1f, 0x59, 0xef, 0x65, 0x11, 0x0d, 0x74, 0x03, 0x98, 0xc0, 0x69, 0xeb, - 0x10, 0xe5, 0x86, 0x2c, 0xb1, 0xec, 0x50, 0xa5, 0x89, 0x0e, 0x15, 0x21, 0x5d, 0x02, 0xb0, 0x7c, 0xe2, 0xf8, 0xc3, - 0x8a, 0xd3, 0x4a, 0xd2, 0x60, 0x88, 0xb5, 0x98, 0xdd, 0xa6, 0xd3, 0xfa, 0x71, 0xca, 0xe4, 0x5f, 0x01, 0xe3, 0x75, - 0x82, 0xb7, 0x48, 0x7f, 0xbe, 0x7c, 0x67, 0xf9, 0x39, 0xd1, 0x6f, 0xe4, 0x42, 0xff, 0x53, 0xf8, 0xba, 0x90, 0x26, - 0xf5, 0x3a, 0xff, 0x6c, 0xa7, 0xfa, 0x1d, 0x4a, 0x4b, 0x96, 0x83, 0xbc, 0x54, 0xdf, 0xd7, 0x9d, 0xfe, 0x43, 0xf9, - 0xfa, 0xd8, 0xc9, 0x06, 0x82, 0x5b, 0x9e, 0xfd, 0x64, 0x45, 0x44, 0xcf, 0xb6, 0x3f, 0x70, 0x32, 0x93, 0xdc, 0xcd, - 0xf5, 0xc8, 0xea, 0x24, 0xab, 0x82, 0x87, 0xbd, 0x4a, 0xdf, 0x33, 0xd3, 0xc3, 0x3d, 0x37, 0xe5, 0x9f, 0x44, 0x2a, - 0xf0, 0x44, 0x43, 0x63, 0x33, 0x54, 0x23, 0x14, 0x8f, 0xd3, 0x80, 0xcd, 0x9f, 0x34, 0xaf, 0x07, 0x0d, 0x56, 0x2e, - 0x15, 0x28, 0xaa, 0xd6, 0x9e, 0xa0, 0x03, 0x53, 0x50, 0x38, 0xda, 0x12, 0x02, 0x54, 0xb0, 0x2c, 0x6a, 0x48, 0xf4, - 0x23, 0x0d, 0x56, 0xb8, 0xd1, 0xc1, 0xdf, 0x82, 0x15, 0x41, 0x50, 0xb7, 0x36, 0xe6, 0x75, 0x57, 0x63, 0x28, 0x8c, - 0xfa, 0x31, 0x98, 0xa0, 0xfc, 0x0d, 0xd4, 0x4b, 0x5b, 0x0c, 0x57, 0xab, 0x06, 0x7c, 0x50, 0xcd, 0x49, 0xbc, 0x6c, - 0xb6, 0x09, 0x9b, 0xdc, 0x20, 0x65, 0x91, 0xc3, 0x1e, 0xfa, 0x04, 0xd5, 0x51, 0xa4, 0x72, 0x11, 0x17, 0xb3, 0xe6, - 0xc2, 0x6c, 0x4a, 0x76, 0xf3, 0xc0, 0x65, 0x6f, 0xe4, 0x99, 0x44, 0xaf, 0xf6, 0xfe, 0x1b, 0x89, 0xe8, 0x80, 0x25, - 0x40, 0xbc, 0x62, 0x61, 0xca, 0x60, 0x60, 0x08, 0xd1, 0xb6, 0x68, 0x1c, 0x8c, 0x5e, 0xf3, 0xe5, 0x6a, 0x31, 0xdf, - 0xcd, 0x66, 0x24, 0x1b, 0x8d, 0x7e, 0x2d, 0xa0, 0x55, 0x3d, 0x6d, 0xfa, 0x37, 0x2c, 0xee, 0x27, 0xf9, 0xe1, 0x53, - 0xef, 0x3c, 0x8b, 0xe8, 0xa9, 0x07, 0xf8, 0xf2, 0x3c, 0x10, 0xc2, 0xf4, 0xfc, 0x05, 0xf4, 0x40, 0x88, 0xb6, 0x31, - 0x17, 0x96, 0x3c, 0x52, 0xe5, 0x7f, 0x5e, 0x95, 0x4f, 0xb0, 0xa0, 0x0e, 0x4d, 0xc2, 0x44, 0x01, 0xb3, 0x46, 0xce, - 0x62, 0xf3, 0x19, 0xf3, 0xbc, 0x4e, 0xb3, 0x77, 0x9d, 0xc4, 0x0d, 0xcb, 0x73, 0xf9, 0x6b, 0xcc, 0x13, 0xae, 0x1f, - 0xb2, 0x33, 0x2c, 0xea, 0x44, 0xd5, 0x80, 0x5f, 0x96, 0x16, 0x3f, 0x81, 0xd6, 0xa5, 0x81, 0x90, 0x58, 0x79, 0x85, - 0xcd, 0x63, 0xa9, 0xd2, 0x37, 0xe4, 0x35, 0xd2, 0x1d, 0x0e, 0x9e, 0x8f, 0xe1, 0xbe, 0x3b, 0xc0, 0x73, 0x52, 0xfd, - 0xfc, 0x89, 0x78, 0x4c, 0x04, 0x61, 0x1b, 0x84, 0xe8, 0xf6, 0xe5, 0x3a, 0xbd, 0xfd, 0x6d, 0x34, 0xe6, 0x46, 0x69, - 0x25, 0xdc, 0x3a, 0xb9, 0xea, 0xc4, 0x78, 0x79, 0x89, 0x9a, 0x13, 0xb7, 0xd3, 0xce, 0xe3, 0x20, 0x52, 0x5a, 0x8d, - 0x65, 0x1b, 0xe3, 0x34, 0x45, 0xe1, 0x91, 0x47, 0x02, 0x76, 0xe4, 0x25, 0x9c, 0x04, 0x54, 0xff, 0x63, 0x7c, 0xe6, - 0x9d, 0x25, 0xb0, 0x02, 0x89, 0x3f, 0x5f, 0xdc, 0x7a, 0xd4, 0xff, 0x33, 0x68, 0xad, 0x7a, 0x26, 0xbd, 0x33, 0x49, - 0x26, 0x7c, 0x76, 0x37, 0xe0, 0x5d, 0xd7, 0x46, 0x4c, 0x3e, 0x51, 0x31, 0x36, 0x20, 0xb5, 0xdf, 0xc6, 0xbe, 0x36, - 0xa3, 0xf4, 0xe6, 0x23, 0x7a, 0x06, 0xae, 0x7e, 0x44, 0xb8, 0xac, 0xd7, 0xd6, 0x7e, 0x07, 0x02, 0x74, 0x82, 0xe5, - 0x74, 0xe0, 0xb4, 0xcb, 0x17, 0xed, 0x93, 0x30, 0x5a, 0x00, 0xa9, 0xdc, 0x40, 0x66, 0x3c, 0xa2, 0x3a, 0x93, 0x31, - 0x36, 0x49, 0x8f, 0x1e, 0x74, 0xc2, 0xee, 0xdf, 0x01, 0x6b, 0x79, 0xc5, 0xb1, 0x76, 0xee, 0x20, 0x78, 0x92, 0x9c, - 0xbc, 0xaa, 0x67, 0x17, 0x6c, 0x69, 0x19, 0xcb, 0x43, 0x7f, 0x1e, 0x82, 0x98, 0x2e, 0xef, 0x6d, 0x23, 0x28, 0xa1, - 0x72, 0xf5, 0x07, 0x41, 0xa1, 0xcf, 0xfa, 0x17, 0x5b, 0x65, 0x53, 0x9d, 0xc7, 0x3e, 0xec, 0xbd, 0xeb, 0xab, 0xc2, - 0xc9, 0x45, 0xf3, 0x7e, 0x14, 0x87, 0x54, 0x75, 0x54, 0xbe, 0xb5, 0x58, 0xf6, 0xda, 0xec, 0x64, 0xa1, 0x3d, 0xf2, - 0x45, 0xfb, 0xd4, 0x1a, 0xb4, 0xd2, 0xb2, 0x28, 0xa4, 0xcd, 0x5c, 0xf4, 0xce, 0x67, 0xcc, 0x22, 0x8e, 0x88, 0xc0, - 0x72, 0xeb, 0x17, 0xf9, 0x23, 0xb6, 0x74, 0x44, 0x59, 0xf8, 0x46, 0x68, 0xea, 0x98, 0x93, 0x87, 0x13, 0x70, 0x5b, - 0x19, 0xde, 0x66, 0x20, 0x46, 0xb5, 0xc8, 0x21, 0x02, 0xfd, 0x8b, 0x63, 0x89, 0x38, 0x57, 0xbf, 0x50, 0x63, 0xe4, - 0x42, 0x0d, 0x42, 0x88, 0x5e, 0x0b, 0x65, 0xe6, 0xe3, 0xbc, 0x4b, 0xb2, 0x36, 0x66, 0x5f, 0xa1, 0x55, 0x63, 0x66, - 0xb6, 0x7a, 0x38, 0xb0, 0x45, 0xd0, 0xed, 0x25, 0x7e, 0x3b, 0x3b, 0x08, 0xdf, 0x4f, 0x45, 0x2e, 0xae, 0x05, 0x73, - 0xb1, 0x8f, 0x53, 0xe3, 0xd3, 0xfd, 0x87, 0x81, 0x62, 0x04, 0x87, 0xab, 0xf2, 0x8a, 0xd6, 0xb3, 0xe1, 0xfd, 0xc0, - 0xd7, 0xb1, 0x39, 0x26, 0xf3, 0xcc, 0x38, 0x58, 0xb1, 0x76, 0xc1, 0xbb, 0x1a, 0x26, 0xac, 0x22, 0x46, 0xb8, 0x5c, - 0x35, 0xc5, 0xda, 0x7c, 0x06, 0xeb, 0x23, 0x48, 0xe2, 0xca, 0x57, 0xe8, 0x8c, 0x0c, 0x0e, 0x66, 0x35, 0x1a, 0xf4, - 0xf3, 0xbe, 0xb4, 0xee, 0x11, 0x08, 0x73, 0x01, 0xb8, 0x7b, 0x73, 0x41, 0x81, 0x1c, 0x40, 0x76, 0xdf, 0x47, 0x00, - 0x19, 0x09, 0xcc, 0x4c, 0x24, 0x48, 0xd2, 0xaa, 0xb5, 0x8f, 0x79, 0x71, 0x09, 0x89, 0x1e, 0x02, 0x82, 0x59, 0x2b, - 0x77, 0x89, 0xea, 0x95, 0xd8, 0x9c, 0x30, 0x04, 0x5a, 0x7b, 0x56, 0x44, 0x4f, 0xd9, 0xfd, 0xab, 0x23, 0x10, 0xfe, - 0xa9, 0xb0, 0x78, 0xd6, 0x39, 0x53, 0x8c, 0xe7, 0x91, 0x65, 0xb6, 0xe0, 0xdf, 0x16, 0x96, 0x8b, 0xf7, 0x50, 0xcc, - 0xa1, 0x1b, 0x93, 0x39, 0x09, 0xbb, 0xef, 0x71, 0x50, 0x12, 0xa8, 0x7f, 0x14, 0xe6, 0x6e, 0x9c, 0xa3, 0x18, 0x3b, - 0x19, 0xe7, 0x12, 0x6a, 0xc5, 0x52, 0xb3, 0x11, 0x58, 0x73, 0xf2, 0x5c, 0x98, 0x4c, 0x2d, 0xf5, 0x49, 0x85, 0x12, - 0x76, 0x66, 0x4a, 0x52, 0x26, 0xe7, 0x45, 0xc1, 0x51, 0x53, 0x51, 0x99, 0xe2, 0x20, 0x94, 0x9f, 0xce, 0xfa, 0xc5, - 0xee, 0xf9, 0x11, 0xdb, 0xf1, 0x6a, 0x70, 0xdb, 0x90, 0xa9, 0x51, 0x53, 0xe0, 0xcf, 0x8c, 0x87, 0xe9, 0xff, 0xe4, - 0x20, 0x9d, 0x87, 0xf0, 0xce, 0xf4, 0xcb, 0x29, 0xb7, 0x81, 0x18, 0x3f, 0xd0, 0xc2, 0x5b, 0x5a, 0x8d, 0x12, 0xa9, - 0xff, 0x4a, 0xe2, 0x73, 0x74, 0xc2, 0x4a, 0x28, 0x25, 0x89, 0x4b, 0x38, 0xa4, 0xba, 0x63, 0xcc, 0xa8, 0x8c, 0x6e, - 0x41, 0x14, 0x34, 0xae, 0xd3, 0x88, 0x2c, 0xdc, 0x2a, 0x3a, 0xba, 0xf8, 0xc5, 0x9f, 0xd9, 0x87, 0xc1, 0x97, 0xc1, - 0x81, 0x40, 0x8e, 0x06, 0x41, 0xfb, 0xc3, 0x2b, 0x6c, 0x78, 0xd9, 0x79, 0xa1, 0x8e, 0x05, 0xe2, 0x51, 0xa7, 0x5e, - 0x42, 0x26, 0x21, 0xff, 0xd0, 0xa9, 0x12, 0x08, 0xe4, 0xcd, 0x0e, 0xab, 0xdf, 0xa0, 0x9f, 0x77, 0xda, 0x2d, 0x37, - 0x75, 0x13, 0x7a, 0x22, 0x84, 0x00, 0x48, 0x6c, 0x8d, 0x04, 0x91, 0xb7, 0x1a, 0x44, 0x52, 0x1d, 0x76, 0x5f, 0xe9, - 0x85, 0x20, 0xe0, 0x46, 0x6d, 0x34, 0x1a, 0x21, 0xf3, 0x0a, 0xb6, 0xc3, 0x4c, 0xc0, 0x38, 0x97, 0x51, 0xc6, 0x2f, - 0xf0, 0x50, 0x78, 0x25, 0x09, 0xbe, 0xa6, 0x4c, 0x7b, 0x0e, 0xa2, 0x5b, 0x6e, 0x2e, 0x3a, 0x1e, 0xc0, 0x20, 0x7a, - 0x02, 0xe6, 0x4f, 0xe6, 0xbf, 0x65, 0x67, 0xa4, 0x68, 0x20, 0x57, 0x7b, 0x87, 0x4b, 0xc6, 0xfc, 0xa9, 0xe4, 0x49, - 0x75, 0x4b, 0x81, 0x21, 0x72, 0xf1, 0xb2, 0xeb, 0x8f, 0x61, 0xae, 0xa8, 0x1d, 0xe0, 0x7d, 0xa2, 0x61, 0xf5, 0x62, - 0x3d, 0xa9, 0x6f, 0x8d, 0xc4, 0x7f, 0x51, 0x19, 0x1b, 0xe3, 0xa8, 0xf4, 0x42, 0x3c, 0xe9, 0x6e, 0xef, 0xac, 0xde, - 0x45, 0xae, 0xd6, 0xc4, 0x83, 0xc1, 0x5a, 0xb7, 0x42, 0x2b, 0xa7, 0xb6, 0xfc, 0x36, 0x87, 0x4b, 0x5f, 0x99, 0xb8, - 0x35, 0x5d, 0x20, 0x86, 0x82, 0xd2, 0xf1, 0xb8, 0xfc, 0x0c, 0x4f, 0x76, 0xf2, 0xa4, 0x33, 0x66, 0x66, 0x21, 0x3e, - 0xdd, 0xd9, 0x3c, 0xd3, 0x1f, 0x87, 0x2c, 0x21, 0x65, 0xaa, 0x9b, 0x9f, 0xe6, 0x85, 0x2f, 0x66, 0x3e, 0xcf, 0x27, - 0x9c, 0x71, 0x0b, 0x2b, 0xb4, 0x5e, 0x33, 0x7e, 0x4e, 0x18, 0x0e, 0xef, 0x2c, 0x4d, 0x94, 0x25, 0xa3, 0xe1, 0x1f, - 0x3f, 0xdf, 0x2d, 0x6d, 0xbe, 0xf3, 0xd3, 0xf1, 0x76, 0x12, 0x93, 0x02, 0x1b, 0xa5, 0x03, 0xc1, 0xf7, 0x80, 0xb2, - 0x97, 0xef, 0x6c, 0xcc, 0xe4, 0x7e, 0xd0, 0x41, 0x81, 0x61, 0x0b, 0x81, 0x0b, 0xad, 0x3f, 0xe4, 0x3d, 0xd6, 0x3b, - 0x55, 0x9e, 0xed, 0xa7, 0xe9, 0xbe, 0x2a, 0x0a, 0x05, 0x3f, 0xbb, 0xf5, 0xd8, 0x5b, 0x07, 0xcd, 0x91, 0x96, 0x30, - 0x79, 0x26, 0xd5, 0xe4, 0x67, 0x62, 0xaa, 0x08, 0x96, 0xbf, 0xfe, 0x32, 0xb9, 0xc8, 0x5d, 0xaf, 0x71, 0x10, 0xa6, - 0x66, 0xc2, 0xd4, 0xaf, 0x95, 0xb7, 0x23, 0xf5, 0x4f, 0xe9, 0xbb, 0x2b, 0x50, 0x57, 0x64, 0x2d, 0x40, 0xa4, 0x34, - 0x0c, 0xa9, 0x56, 0x87, 0x15, 0xa7, 0x6e, 0x83, 0x95, 0x1d, 0xbe, 0x80, 0x1b, 0x25, 0x67, 0x09, 0x51, 0xd1, 0xa6, - 0x26, 0x03, 0x87, 0x41, 0xa0, 0x30, 0x54, 0x14, 0x87, 0x47, 0x58, 0x7c, 0xd9, 0xe1, 0x45, 0xd3, 0x45, 0xb1, 0xe1, - 0xd5, 0x7e, 0xa2, 0x8c, 0x33, 0xb6, 0x8b, 0x0a, 0x40, 0x2d, 0x22, 0xfc, 0xf8, 0x34, 0xc0, 0xca, 0x9f, 0xf0, 0xb1, - 0x7b, 0x12, 0x96, 0x1e, 0x74, 0x29, 0x6a, 0xd9, 0x52, 0x4a, 0x53, 0x5b, 0xd4, 0x35, 0xce, 0x50, 0x71, 0xec, 0xf0, - 0xc8, 0x7a, 0x84, 0xf1, 0xdc, 0xe9, 0x22, 0xf8, 0x2c, 0x36, 0xc8, 0x23, 0x95, 0x20, 0xca, 0xdd, 0x32, 0x6e, 0x3d, - 0xe8, 0x63, 0x2e, 0x07, 0x61, 0xfb, 0x0c, 0xa5, 0x72, 0x11, 0x2b, 0x09, 0x2e, 0x83, 0xf2, 0x8f, 0x1e, 0xaa, 0x4c, - 0x74, 0xf2, 0x9e, 0x3a, 0xb6, 0x1d, 0x68, 0xac, 0xe9, 0x21, 0x89, 0x36, 0x6e, 0xd5, 0x62, 0x5c, 0x31, 0x75, 0x7a, - 0x6e, 0x89, 0x29, 0x41, 0x7e, 0x73, 0x39, 0xda, 0x9a, 0xba, 0x04, 0x62, 0x49, 0x89, 0xf8, 0x94, 0x4b, 0xfe, 0xae, - 0xeb, 0x24, 0xbe, 0x60, 0x2b, 0xb2, 0x64, 0xdc, 0xaa, 0xdd, 0x46, 0x5a, 0xcf, 0x05, 0x21, 0xf3, 0x2f, 0x35, 0x08, - 0x07, 0x9f, 0x2e, 0x58, 0xae, 0xc5, 0x47, 0xeb, 0xaf, 0x69, 0xd2, 0xa6, 0x07, 0x15, 0xb4, 0xd4, 0x41, 0x25, 0x2f, - 0x6b, 0xe6, 0x11, 0x57, 0xb3, 0x30, 0xbe, 0xa6, 0xdf, 0x5d, 0x72, 0x50, 0xd9, 0x19, 0x04, 0xf1, 0xe9, 0x20, 0xad, - 0x15, 0x79, 0xaa, 0x70, 0xaf, 0xd4, 0x5f, 0x89, 0x53, 0x0d, 0xa4, 0xf3, 0x02, 0x56, 0x08, 0xb9, 0x8e, 0x1f, 0xb8, - 0xda, 0x44, 0x80, 0x65, 0x99, 0xde, 0x6f, 0x2e, 0xa5, 0xd4, 0xf9, 0x01, 0xc0, 0xb3, 0xed, 0xa2, 0x5f, 0xa0, 0x39, - 0x01, 0x8c, 0x28, 0x50, 0x77, 0x21, 0xde, 0xea, 0x86, 0x8c, 0xb1, 0xfd, 0x92, 0xf6, 0xb0, 0x65, 0x3b, 0x06, 0x48, - 0x80, 0x91, 0x65, 0x58, 0xdc, 0x7b, 0x94, 0x8a, 0xd6, 0x74, 0x66, 0x63, 0x54, 0x95, 0xb4, 0x62, 0x7f, 0x79, 0x93, - 0xc8, 0xec, 0xd7, 0x8d, 0x8b, 0xa6, 0xbc, 0xb6, 0x48, 0x25, 0x8a, 0x13, 0x64, 0x65, 0xaa, 0xc8, 0x28, 0x8c, 0xb5, - 0xa3, 0x64, 0x81, 0xc7, 0xc5, 0x9e, 0x30, 0xa6, 0xff, 0x34, 0x15, 0x28, 0xdf, 0xbf, 0x6b, 0x1a, 0xa9, 0x50, 0x21, - 0xec, 0xc9, 0x72, 0x1a, 0x5b, 0xd1, 0xa7, 0xe2, 0x64, 0x4d, 0x22, 0xfd, 0xb7, 0x01, 0x06, 0x53, 0x1b, 0xf0, 0xe4, - 0x06, 0x29, 0x96, 0x10, 0x3e, 0x29, 0xdd, 0x67, 0x4d, 0x74, 0xa3, 0x32, 0xc0, 0x99, 0x1b, 0x37, 0x67, 0x2b, 0x0d, - 0x5c, 0xd9, 0x3a, 0x08, 0x53, 0x61, 0xe1, 0xce, 0xa6, 0x41, 0x8a, 0x4b, 0x8e, 0x94, 0x4c, 0xbf, 0x16, 0xc4, 0x8b, - 0x23, 0xfc, 0x2a, 0x7f, 0x72, 0x8b, 0x4c, 0x57, 0xa8, 0x2a, 0xa5, 0x53, 0xcc, 0x61, 0x7a, 0x98, 0x96, 0x2e, 0xe9, - 0xe5, 0x84, 0x77, 0x9e, 0x1f, 0xce, 0x05, 0x3d, 0x6d, 0xd5, 0x6a, 0xd5, 0x50, 0x18, 0xd0, 0x49, 0x47, 0x80, 0x78, - 0xd4, 0xf4, 0x97, 0xf0, 0xba, 0x92, 0x9b, 0x17, 0x71, 0x4d, 0x81, 0xe3, 0xb4, 0x7d, 0xed, 0xdc, 0x5f, 0x2e, 0xab, - 0x85, 0x1c, 0x24, 0x60, 0x2c, 0xa3, 0x0f, 0x81, 0xdc, 0xe9, 0xe9, 0xb3, 0xd2, 0xb2, 0x46, 0xd6, 0x27, 0x9b, 0x2d, - 0x3e, 0x79, 0x3f, 0x78, 0x81, 0x25, 0xdb, 0xe0, 0xe1, 0xad, 0xbe, 0xa6, 0xed, 0x64, 0x83, 0xb0, 0x16, 0x8d, 0x83, - 0x28, 0x56, 0xa0, 0x1d, 0xd9, 0x8a, 0xac, 0xcb, 0x9c, 0x64, 0x5f, 0x5f, 0xe4, 0x3f, 0xcf, 0x8a, 0x50, 0xa2, 0x05, - 0x8d, 0x9c, 0xc3, 0x1a, 0x2e, 0xe8, 0xa0, 0x34, 0x01, 0x83, 0x32, 0x00, 0x1b, 0x65, 0xec, 0xea, 0x34, 0x14, 0xf0, - 0x31, 0x46, 0x14, 0xca, 0x99, 0xcb, 0xd9, 0x5b, 0x5c, 0x58, 0x8b, 0x53, 0x66, 0x56, 0x9a, 0x7e, 0xa6, 0x85, 0xf9, - 0x7a, 0x23, 0x49, 0x10, 0xd9, 0x5a, 0x4e, 0x57, 0xae, 0x4b, 0xf4, 0xf4, 0x28, 0x28, 0x50, 0x59, 0x49, 0xc9, 0xb9, - 0x7c, 0x5e, 0xa1, 0xb3, 0x92, 0xf2, 0x2b, 0x4b, 0x4c, 0xc0, 0xd8, 0x26, 0x76, 0x8f, 0x9f, 0xcb, 0xca, 0xa7, 0x3c, - 0x66, 0x7c, 0xfa, 0xd3, 0xb6, 0xbe, 0x53, 0x58, 0x40, 0xa0, 0xe6, 0x0f, 0x6b, 0xae, 0xf4, 0xda, 0x8c, 0x81, 0x58, - 0x38, 0x31, 0xc0, 0xe7, 0xf0, 0x51, 0x01, 0xa3, 0xd4, 0x6c, 0x07, 0x13, 0x29, 0xd1, 0x92, 0x90, 0xc8, 0xb4, 0x1d, - 0xb4, 0x3e, 0x8b, 0x41, 0x59, 0x31, 0xc1, 0x35, 0xc5, 0x15, 0x6f, 0x57, 0x3b, 0x6a, 0x68, 0x5d, 0x23, 0x83, 0x78, - 0xa8, 0xa4, 0x3f, 0x3b, 0xde, 0x8f, 0x50, 0x10, 0x67, 0xa5, 0xc2, 0x5b, 0x9c, 0x6d, 0xed, 0xf8, 0x19, 0x05, 0xf7, - 0xc2, 0x5b, 0xb0, 0x31, 0x86, 0xa6, 0x6c, 0xb2, 0x62, 0xff, 0x6c, 0x06, 0xc4, 0x5e, 0xdf, 0x46, 0x86, 0xbb, 0xcd, - 0x8a, 0xc3, 0x07, 0xb3, 0xe5, 0x1f, 0xb1, 0xc7, 0xee, 0x3e, 0x79, 0x51, 0xac, 0x71, 0x6a, 0x0f, 0x6b, 0xc6, 0xb7, - 0xdf, 0x5b, 0x2e, 0x48, 0x8f, 0xe6, 0xda, 0x12, 0xd1, 0x13, 0xd3, 0x13, 0x0c, 0x0b, 0xa4, 0xc8, 0xea, 0x55, 0xca, - 0x54, 0xdb, 0x1b, 0xd6, 0x5e, 0x5a, 0x72, 0x55, 0x68, 0x0f, 0xc5, 0xec, 0xb2, 0x97, 0xe7, 0xb2, 0xe3, 0xeb, 0xe2, - 0xa3, 0x32, 0x6b, 0x8e, 0x95, 0x5f, 0x08, 0x53, 0x61, 0xaf, 0x0a, 0x72, 0x4a, 0x07, 0xeb, 0x08, 0xd5, 0x61, 0x98, - 0x2a, 0x1e, 0x3d, 0xb7, 0x25, 0xa4, 0x06, 0xbc, 0x1f, 0x5e, 0xe4, 0xf9, 0x55, 0xb4, 0xab, 0x00, 0x86, 0x4b, 0x01, - 0x07, 0x8f, 0x26, 0x08, 0x5c, 0x92, 0x10, 0x78, 0x9b, 0x41, 0x1f, 0xae, 0xdf, 0xbc, 0x7d, 0x0d, 0x65, 0x96, 0x33, - 0x6c, 0xa9, 0x38, 0xfb, 0x40, 0x7a, 0xb6, 0x2b, 0x92, 0xfa, 0x9e, 0x9a, 0xad, 0xb8, 0x35, 0xa6, 0x29, 0x12, 0x03, - 0xca, 0xae, 0x5a, 0xd3, 0xbd, 0x52, 0xd7, 0xf4, 0xec, 0x3c, 0x58, 0xd7, 0x12, 0xed, 0x0a, 0xa2, 0x52, 0x7f, 0x40, - 0xa2, 0xaf, 0x14, 0xda, 0x39, 0xb6, 0xae, 0x87, 0x3a, 0xaa, 0xa0, 0x5a, 0xc7, 0x08, 0xa9, 0xb6, 0xa5, 0x54, 0xfd, - 0x52, 0xeb, 0x70, 0xe9, 0x35, 0xc1, 0x70, 0xf4, 0xe0, 0x61, 0xbc, 0x4b, 0xd4, 0xa4, 0xdc, 0x5f, 0xf8, 0x12, 0xd6, - 0xdd, 0xee, 0x35, 0xf6, 0x7f, 0x51, 0xcf, 0xd6, 0x45, 0x37, 0xf1, 0x3e, 0xc8, 0xff, 0x57, 0x0f, 0x18, 0x99, 0x3c, - 0x7c, 0x38, 0xae, 0xb2, 0xde, 0x66, 0x31, 0x35, 0x25, 0x7f, 0x9d, 0x6b, 0xfa, 0x6a, 0xa5, 0x9d, 0x9a, 0xbb, 0x3b, - 0x39, 0xfb, 0x0d, 0x9b, 0x13, 0x87, 0x30, 0x4c, 0x94, 0xc8, 0xdd, 0x95, 0xc9, 0xa6, 0xeb, 0x72, 0xa9, 0xc1, 0x77, - 0x4b, 0x83, 0x90, 0xbc, 0x46, 0xe3, 0x87, 0x30, 0xcb, 0xa5, 0x44, 0x6c, 0x00, 0xcf, 0x9c, 0x99, 0xa8, 0x87, 0x8d, - 0x2d, 0x25, 0x88, 0xb2, 0x2a, 0x16, 0x5f, 0x65, 0x6a, 0xe7, 0xa8, 0x2a, 0x8d, 0xe2, 0xb9, 0x7b, 0xc3, 0x03, 0x86, - 0x64, 0xe2, 0xec, 0x57, 0xd0, 0xbb, 0xd0, 0x40, 0xba, 0x1d, 0xbb, 0x1f, 0xf0, 0x13, 0x29, 0xd1, 0xe7, 0xc1, 0x58, - 0x80, 0xd8, 0x22, 0x99, 0x65, 0x50, 0x28, 0x7e, 0x71, 0x2b, 0x5c, 0x25, 0x6a, 0x33, 0xde, 0xb3, 0x97, 0x2a, 0x6e, - 0x03, 0x33, 0xab, 0x96, 0x8f, 0x4c, 0x85, 0x10, 0x7b, 0xd5, 0x89, 0x7a, 0x96, 0x50, 0x36, 0xa3, 0x1e, 0xfe, 0xbe, - 0xa3, 0x1c, 0x8d, 0x28, 0xed, 0x68, 0x50, 0x8d, 0x85, 0xf7, 0x3b, 0x63, 0x7c, 0x67, 0xb6, 0x3f, 0x46, 0x88, 0x39, - 0xaf, 0x88, 0x83, 0x43, 0x38, 0x61, 0x78, 0xb5, 0xb5, 0x1c, 0x95, 0x21, 0x28, 0xdc, 0xf3, 0x4d, 0xcf, 0xcd, 0x46, - 0x59, 0x88, 0x19, 0x6f, 0xeb, 0xbc, 0x8f, 0x73, 0x19, 0xb9, 0x91, 0x99, 0x69, 0x18, 0x9b, 0x92, 0xe0, 0x1e, 0x70, - 0xa1, 0x24, 0xb0, 0x9c, 0xcb, 0xbf, 0x04, 0xc3, 0x9c, 0xd8, 0xfa, 0x07, 0xb6, 0xce, 0xf4, 0x3e, 0x1a, 0xc8, 0x55, - 0x8b, 0xfc, 0x8f, 0x76, 0xa5, 0xe9, 0x5f, 0x3a, 0x6b, 0x35, 0xcf, 0xd8, 0xc0, 0x0a, 0x1f, 0x50, 0x1d, 0x38, 0x40, - 0xaa, 0x17, 0x25, 0x41, 0xdc, 0x14, 0x5a, 0xf4, 0x32, 0x57, 0x9d, 0x68, 0xb4, 0x57, 0x6c, 0xc5, 0x38, 0xaf, 0xfd, - 0x97, 0xdb, 0x3d, 0x11, 0x73, 0x14, 0xa9, 0xa3, 0x86, 0x64, 0x2b, 0xf6, 0x87, 0xab, 0x4c, 0xe5, 0x9d, 0xe7, 0x2b, - 0x5f, 0xc1, 0x4b, 0xed, 0xef, 0xc8, 0x30, 0x24, 0xea, 0x42, 0xf5, 0xac, 0x80, 0xd7, 0xc7, 0x3f, 0x82, 0x7b, 0xa3, - 0x80, 0x28, 0xf8, 0x59, 0x21, 0xec, 0x9e, 0xcd, 0x6e, 0x3d, 0x1e, 0xfc, 0x3a, 0xae, 0xad, 0x75, 0x83, 0x67, 0x8a, - 0xff, 0xf8, 0x60, 0x15, 0x0e, 0x79, 0xe0, 0x7c, 0xa2, 0x77, 0xf7, 0xf3, 0xcb, 0x2f, 0x35, 0x7a, 0xfe, 0x42, 0xd8, - 0xcb, 0x56, 0x3a, 0x50, 0xd7, 0x28, 0x7e, 0xe2, 0x70, 0xac, 0x14, 0x35, 0xfc, 0x63, 0x9c, 0x38, 0x1f, 0xae, 0x8f, - 0x92, 0x69, 0x01, 0x16, 0x62, 0x1a, 0xba, 0x25, 0x71, 0x5e, 0x14, 0x67, 0xbd, 0xbb, 0x80, 0x9a, 0x4e, 0x7b, 0x80, - 0x52, 0x52, 0xcc, 0x13, 0x29, 0xd1, 0x5d, 0xfc, 0x9e, 0x9b, 0x4e, 0xee, 0xdc, 0xbe, 0x38, 0xac, 0x0f, 0x86, 0x6d, - 0x37, 0x19, 0xe3, 0x4f, 0x55, 0x9e, 0x30, 0xe2, 0x85, 0xb1, 0x2a, 0xe4, 0xf7, 0x08, 0x03, 0xfa, 0x7d, 0x38, 0x51, - 0x11, 0x7d, 0x3f, 0x00, 0xb8, 0xa7, 0x6e, 0x02, 0xaa, 0xf5, 0xf9, 0x4d, 0xef, 0x0a, 0x88, 0x26, 0x78, 0x51, 0xc9, - 0x6b, 0x80, 0x84, 0x5c, 0x5c, 0x9b, 0x72, 0x78, 0x37, 0x54, 0x24, 0xf4, 0xa1, 0x74, 0xce, 0xf4, 0x46, 0x06, 0x88, - 0xca, 0x31, 0x22, 0xbc, 0xe9, 0x4e, 0xf4, 0xa6, 0xbe, 0x87, 0x3f, 0x37, 0x63, 0xcf, 0x05, 0x86, 0x75, 0x6b, 0x7a, - 0xa6, 0x9f, 0x81, 0x6a, 0xc6, 0x9f, 0x7b, 0xd1, 0xd2, 0x53, 0xdb, 0x9a, 0x55, 0x8c, 0xc3, 0x5f, 0xcc, 0x83, 0x91, - 0xac, 0x2f, 0x2e, 0x22, 0xcc, 0x08, 0x6e, 0x56, 0x51, 0x2f, 0x2f, 0x59, 0xc2, 0xec, 0x6c, 0xd5, 0x38, 0xd0, 0x8c, - 0xb6, 0xa5, 0x07, 0xd7, 0xf9, 0x21, 0x96, 0xf1, 0x50, 0x1d, 0x5a, 0x3b, 0x8e, 0x6b, 0x9f, 0x41, 0x71, 0xb5, 0xc4, - 0x3f, 0x97, 0xf3, 0x25, 0xae, 0xf7, 0xcf, 0xfd, 0xb4, 0xd2, 0xdb, 0x54, 0xb3, 0x8f, 0xb9, 0xa5, 0x97, 0x24, 0xa4, - 0xef, 0x76, 0x18, 0xb0, 0x34, 0x19, 0x4c, 0xbe, 0x21, 0x39, 0xb0, 0x41, 0x95, 0x7c, 0x7a, 0xa0, 0xe7, 0x42, 0x07, - 0x2b, 0xa0, 0x1d, 0xf8, 0x0d, 0xcf, 0xeb, 0xb5, 0x10, 0x39, 0xdc, 0x20, 0x99, 0x00, 0x9d, 0x91, 0xc9, 0x85, 0xac, - 0xaa, 0x30, 0x81, 0x68, 0x2e, 0x21, 0x1a, 0xd4, 0x6d, 0x03, 0x67, 0x7c, 0x30, 0x29, 0x61, 0x3a, 0xdd, 0x2d, 0x95, - 0xce, 0x2b, 0x92, 0xa8, 0xeb, 0xfd, 0x30, 0xde, 0x0f, 0xcf, 0x3c, 0xc2, 0xbc, 0xdc, 0xee, 0x75, 0x91, 0xe5, 0xe5, - 0xd4, 0x42, 0xbb, 0x8f, 0xd9, 0xd1, 0x34, 0x5c, 0xea, 0x2e, 0xd8, 0x79, 0x60, 0x52, 0x5d, 0xd8, 0x83, 0x7d, 0x94, - 0x22, 0x4c, 0x73, 0xc9, 0xc8, 0xb2, 0xe8, 0xd2, 0x0c, 0xde, 0xe9, 0x00, 0x4f, 0x4b, 0xc4, 0x93, 0x20, 0xd2, 0xa4, - 0x17, 0x1b, 0x56, 0xd1, 0xe0, 0x6e, 0xd0, 0x9d, 0x19, 0x34, 0x54, 0x2c, 0x96, 0xea, 0xd1, 0x95, 0x72, 0x77, 0x62, - 0x69, 0x56, 0xd4, 0xf3, 0x81, 0x98, 0xec, 0xf9, 0x7a, 0x43, 0xaa, 0x14, 0x13, 0x16, 0xd1, 0xe8, 0xd3, 0x0f, 0x59, - 0xc5, 0x51, 0xc2, 0x62, 0xa5, 0xb8, 0xaa, 0xc8, 0xa9, 0xf1, 0xe6, 0x65, 0x56, 0x22, 0xed, 0xb0, 0x4c, 0x3c, 0x85, - 0x7c, 0x47, 0xd3, 0x4e, 0xcb, 0xac, 0xad, 0x62, 0x31, 0x7b, 0x02, 0x29, 0x11, 0x87, 0x75, 0x86, 0xb7, 0x65, 0x8e, - 0xd3, 0x60, 0x6d, 0xc9, 0xa9, 0x5f, 0xd0, 0x97, 0x30, 0xfb, 0x8c, 0xd5, 0x27, 0xa9, 0xd7, 0x91, 0x04, 0x28, 0xfe, - 0x4d, 0x1f, 0x04, 0x85, 0x5b, 0xfa, 0x7f, 0x7b, 0x6d, 0x38, 0x54, 0x0f, 0x75, 0xcf, 0x10, 0xab, 0x22, 0x15, 0xce, - 0xdd, 0x57, 0xe7, 0x93, 0x42, 0x3a, 0x99, 0x39, 0xe6, 0x91, 0x68, 0x2b, 0x2e, 0x07, 0x37, 0x2a, 0x23, 0x6a, 0x3a, - 0x7d, 0x50, 0x9d, 0xe1, 0xae, 0xde, 0xe7, 0x1a, 0xc2, 0xeb, 0x6a, 0x9f, 0xbb, 0xd3, 0x5b, 0xb1, 0xc5, 0x63, 0xae, - 0x4e, 0xdb, 0x89, 0x4b, 0xbb, 0xd4, 0xe9, 0x87, 0x23, 0xa8, 0xb8, 0x4c, 0xc4, 0x6c, 0x82, 0x0e, 0x2e, 0x8b, 0xa6, - 0x28, 0x75, 0xe9, 0x76, 0x92, 0x6b, 0x70, 0x07, 0x42, 0xaa, 0x72, 0x97, 0x19, 0x6e, 0xba, 0x10, 0x29, 0x3e, 0x93, - 0xae, 0x21, 0x92, 0xa2, 0x34, 0xbd, 0xe0, 0x34, 0x32, 0x72, 0xb7, 0x53, 0x99, 0x49, 0xeb, 0x90, 0x1a, 0xc7, 0x94, - 0x13, 0xf6, 0x32, 0x46, 0x70, 0xd0, 0xaa, 0x2f, 0x4b, 0x55, 0xe8, 0xfa, 0xa6, 0x67, 0xcb, 0x75, 0xfd, 0x87, 0x8f, - 0xc7, 0xcb, 0x51, 0x88, 0x2e, 0x6c, 0xaf, 0x94, 0x8e, 0x2c, 0xbd, 0x97, 0x8c, 0xb8, 0xe0, 0x50, 0xce, 0x5e, 0x0d, - 0x09, 0xb8, 0xa5, 0x57, 0x2c, 0xd2, 0xba, 0x71, 0x2d, 0xcb, 0xb4, 0x7b, 0xe5, 0x94, 0x49, 0x21, 0x56, 0xc6, 0x1a, - 0xc1, 0xfb, 0x69, 0xc4, 0xb0, 0xe9, 0x4d, 0xd8, 0x90, 0x4c, 0xcd, 0x5c, 0x6f, 0x28, 0x73, 0xf9, 0xa9, 0xf1, 0x23, - 0x36, 0x1a, 0x87, 0x60, 0xe8, 0xcc, 0x75, 0x1e, 0x0b, 0xe3, 0x0a, 0x66, 0x54, 0x23, 0xcb, 0x81, 0xb5, 0xd5, 0xda, - 0x0b, 0xb7, 0xa3, 0xde, 0x1c, 0x48, 0x7e, 0xe7, 0x65, 0xa6, 0x1a, 0xe3, 0xa0, 0xc5, 0x66, 0xed, 0x48, 0x23, 0x0a, - 0xbc, 0x78, 0x7a, 0x15, 0x41, 0xd1, 0xef, 0x49, 0x33, 0xc8, 0x41, 0x4b, 0xf5, 0xf5, 0xcf, 0x49, 0x89, 0xed, 0x98, - 0xa6, 0x05, 0x86, 0x59, 0xa5, 0x81, 0xbf, 0x26, 0x95, 0x86, 0x17, 0x36, 0x9f, 0x1f, 0xed, 0x12, 0xb9, 0xdc, 0xf3, - 0xac, 0xe6, 0x00, 0xc3, 0x74, 0xcc, 0x8d, 0x7f, 0x8f, 0xa2, 0x9f, 0x6c, 0x1c, 0x83, 0xd1, 0xd3, 0x2f, 0x4a, 0x3d, - 0x9b, 0x49, 0x7b, 0x5e, 0x53, 0x17, 0x70, 0x3c, 0x19, 0xe9, 0x00, 0x3c, 0x48, 0x27, 0x76, 0x1f, 0xc0, 0x25, 0x63, - 0x2f, 0x41, 0x17, 0xbb, 0xaf, 0x01, 0x48, 0xb6, 0x63, 0x8b, 0xdc, 0x8a, 0x91, 0xaf, 0x92, 0x4a, 0x79, 0x29, 0x7f, - 0x25, 0xb3, 0x11, 0xc0, 0xbe, 0x4a, 0x2f, 0x0f, 0xb8, 0x1b, 0xa5, 0xb7, 0x03, 0x82, 0xdd, 0x02, 0x61, 0xdf, 0x6d, - 0xd5, 0xa8, 0x81, 0xdd, 0x5f, 0x98, 0xb1, 0x69, 0x01, 0x1b, 0x19, 0xfa, 0xc3, 0xad, 0x4f, 0x94, 0x53, 0x10, 0x7e, - 0xff, 0xd2, 0xdc, 0x8d, 0x2b, 0x33, 0x18, 0x25, 0xb6, 0x43, 0x60, 0x3e, 0x53, 0xf9, 0x12, 0xe5, 0x27, 0xe1, 0xe5, - 0x6a, 0xd7, 0x9f, 0x95, 0x73, 0x29, 0xe6, 0xce, 0x35, 0xfc, 0x36, 0x1a, 0x3f, 0x2a, 0xed, 0x3a, 0xcf, 0xa2, 0x4b, - 0xdc, 0xe7, 0xfe, 0x3e, 0x80, 0x23, 0x6f, 0xcc, 0x87, 0x89, 0x7c, 0x27, 0x19, 0x56, 0x68, 0xf3, 0x76, 0x23, 0x3d, - 0xfc, 0xf6, 0x8d, 0xd4, 0x23, 0x7e, 0xac, 0x8a, 0xe0, 0xd7, 0x4d, 0x01, 0x6c, 0x82, 0x53, 0xcf, 0x5f, 0x37, 0xa9, - 0xe3, 0xc7, 0x4b, 0x48, 0xfa, 0x26, 0xcc, 0xdd, 0xbb, 0xd9, 0xe0, 0xe9, 0x10, 0x9e, 0x65, 0x44, 0x07, 0x03, 0x99, - 0x5b, 0x93, 0x1b, 0xf4, 0x5f, 0x30, 0xcd, 0xb7, 0x83, 0xc0, 0x26, 0x9e, 0x25, 0x15, 0x5f, 0x74, 0xf7, 0x36, 0x34, - 0x75, 0x10, 0x15, 0x0d, 0xc4, 0x25, 0x1b, 0xb8, 0xd9, 0x0a, 0xca, 0x73, 0x63, 0xa8, 0xb3, 0xe7, 0x88, 0xdd, 0x56, - 0xda, 0xbd, 0x95, 0x8b, 0x57, 0x94, 0xa8, 0x11, 0x50, 0x21, 0xe8, 0x2e, 0x7f, 0x28, 0xf7, 0x25, 0xdd, 0x59, 0x69, - 0xca, 0x5c, 0x24, 0x98, 0xd7, 0x05, 0x55, 0x3f, 0x80, 0x04, 0xb4, 0x0f, 0x09, 0xa8, 0xd0, 0x7d, 0xf9, 0x35, 0x93, - 0x79, 0xeb, 0x49, 0xac, 0xab, 0xf0, 0xc3, 0x00, 0x0e, 0xff, 0xa5, 0x21, 0x23, 0x21, 0x7b, 0xb9, 0x5f, 0xd7, 0x43, - 0xdd, 0xd2, 0x71, 0x1b, 0xab, 0x79, 0xa0, 0xac, 0x23, 0x1c, 0x27, 0x56, 0xdb, 0xef, 0x06, 0xa4, 0xe5, 0xb8, 0xbf, - 0xaa, 0xe9, 0xd2, 0x6e, 0x5e, 0x87, 0x61, 0x1d, 0xb6, 0x86, 0xe5, 0x17, 0xe6, 0x8a, 0x87, 0xf6, 0x1c, 0xfe, 0xdb, - 0x57, 0xc6, 0x97, 0x34, 0xfb, 0xbf, 0x15, 0x4f, 0x83, 0x44, 0xd3, 0x67, 0x29, 0x92, 0x30, 0x4a, 0xf7, 0x27, 0x12, - 0x25, 0x0d, 0x24, 0x72, 0x70, 0x2f, 0xdf, 0xd2, 0xf8, 0x57, 0xa5, 0x2c, 0x43, 0x87, 0xcb, 0x66, 0x07, 0x32, 0x6f, - 0x9d, 0xbb, 0xbf, 0x1c, 0x7a, 0x0b, 0x54, 0xe9, 0x14, 0x26, 0x2f, 0x3d, 0x5c, 0xb1, 0x65, 0xcf, 0x62, 0xe8, 0xa7, - 0x60, 0x2a, 0x46, 0xb2, 0x19, 0x26, 0xe6, 0x2a, 0x85, 0xc8, 0x2f, 0x8f, 0x3a, 0xb9, 0xbb, 0xe5, 0x6f, 0x6e, 0x7d, - 0xbc, 0x28, 0x79, 0x63, 0x76, 0x66, 0x7b, 0x3e, 0x76, 0xfb, 0x3d, 0x2b, 0x72, 0x27, 0xec, 0x74, 0xf4, 0x0e, 0xb9, - 0xe6, 0x4e, 0x68, 0x2a, 0x60, 0xb9, 0x38, 0x4f, 0xad, 0xd4, 0xc4, 0xa0, 0x44, 0x28, 0x23, 0xf1, 0x0f, 0xd1, 0x36, - 0xec, 0x25, 0x55, 0xf7, 0x1e, 0x84, 0x62, 0xdb, 0x23, 0x11, 0x48, 0xf1, 0x8f, 0x82, 0x52, 0x4a, 0x58, 0x97, 0x46, - 0x99, 0x29, 0x3f, 0xa1, 0xb0, 0x03, 0x07, 0x01, 0x1f, 0x12, 0x68, 0x69, 0x28, 0xeb, 0xbf, 0xdf, 0x30, 0xea, 0xb2, - 0x1f, 0x4b, 0xf2, 0x57, 0x8d, 0xea, 0x5a, 0xa2, 0x7f, 0xbc, 0xcc, 0x4f, 0x69, 0x0a, 0x1e, 0x14, 0x7a, 0x5d, 0x3b, - 0xdd, 0x27, 0x4c, 0x6d, 0x57, 0x2e, 0x12, 0x5f, 0xda, 0x53, 0xfe, 0x08, 0x6a, 0xd3, 0xd4, 0xd8, 0x5c, 0x2f, 0x54, - 0x33, 0xa5, 0x28, 0x2b, 0xbc, 0x6a, 0x2c, 0xb4, 0xe2, 0x90, 0x54, 0x49, 0x9c, 0x33, 0xf7, 0xd8, 0xd5, 0x9b, 0xf0, - 0x82, 0x30, 0x50, 0x60, 0x92, 0x59, 0x6c, 0x44, 0x5f, 0xa1, 0x2f, 0xe9, 0xcb, 0x74, 0xb5, 0x1f, 0x19, 0xf0, 0x06, - 0x87, 0xa3, 0x55, 0x0d, 0xf9, 0x2a, 0x25, 0xaa, 0x44, 0x31, 0x88, 0x52, 0xc7, 0x6f, 0x60, 0x0b, 0xcc, 0xcf, 0x27, - 0x0b, 0xfa, 0xba, 0xac, 0x39, 0x65, 0xbf, 0x59, 0xf3, 0x27, 0x43, 0x7e, 0x3c, 0x6e, 0x91, 0xbb, 0x8e, 0xc8, 0x25, - 0x42, 0xd4, 0x9f, 0xdf, 0x76, 0xad, 0x27, 0x22, 0x9f, 0xd7, 0x66, 0xb1, 0xd8, 0xe5, 0x02, 0xf6, 0x9b, 0xb3, 0x72, - 0xe3, 0xc4, 0xae, 0x3f, 0xf2, 0xc4, 0x33, 0xf9, 0xc4, 0x6d, 0x18, 0x28, 0xef, 0x61, 0xbd, 0xb0, 0x74, 0x4d, 0x02, - 0x50, 0x62, 0xe8, 0xd3, 0xaf, 0x50, 0xad, 0xec, 0x58, 0x6c, 0x2e, 0x79, 0x52, 0x86, 0x40, 0xf1, 0xf5, 0xfd, 0x25, - 0xf9, 0x34, 0x56, 0x20, 0xa5, 0x61, 0x1e, 0x81, 0x45, 0x31, 0x14, 0x35, 0xd4, 0x72, 0xf1, 0x06, 0x6f, 0x60, 0x08, - 0x5f, 0x68, 0x75, 0xb8, 0x6c, 0x37, 0x08, 0x77, 0xc9, 0x8e, 0x95, 0x4e, 0x29, 0x57, 0xe3, 0x00, 0x84, 0x97, 0x3f, - 0x02, 0x50, 0x17, 0x6a, 0x4d, 0xb0, 0xb7, 0x72, 0xb2, 0xdf, 0xdc, 0x11, 0x34, 0xc0, 0x7b, 0xff, 0x2c, 0xfe, 0x74, - 0xfc, 0x41, 0x21, 0x75, 0x27, 0xe5, 0xb5, 0x54, 0xba, 0xd5, 0x7a, 0x4b, 0xba, 0x57, 0xb0, 0xdd, 0x5c, 0xf5, 0x26, - 0xa3, 0x54, 0xeb, 0xfc, 0x3e, 0x19, 0x28, 0x30, 0x53, 0x4d, 0x28, 0x5d, 0x1c, 0x49, 0xed, 0x92, 0x9e, 0x2e, 0x6b, - 0xe8, 0x6f, 0x39, 0xb1, 0x15, 0xec, 0x8f, 0xab, 0x63, 0xc9, 0xb7, 0xf8, 0xfc, 0x2b, 0xc0, 0xde, 0x95, 0x1f, 0xfe, - 0x24, 0xcc, 0xcf, 0x45, 0x97, 0x36, 0xea, 0x91, 0xa3, 0x9e, 0xf7, 0xb7, 0x3c, 0xfa, 0x09, 0xb2, 0x1d, 0x9b, 0x87, - 0xbc, 0xdf, 0xbf, 0xf9, 0xb5, 0x6b, 0xfc, 0xd4, 0x4e, 0x36, 0xa1, 0xd9, 0xb5, 0xf2, 0x5e, 0x7e, 0x0f, 0xfe, 0xe4, - 0x76, 0x8f, 0x4c, 0xaa, 0x61, 0x75, 0x06, 0x7e, 0x18, 0x64, 0x85, 0x5e, 0xfd, 0xb4, 0x67, 0x98, 0x93, 0x7d, 0x88, - 0x1a, 0xdc, 0xe4, 0x86, 0xc6, 0xae, 0x19, 0xd3, 0xb0, 0xad, 0xaf, 0xf1, 0x5c, 0xa3, 0x9c, 0xef, 0x6b, 0xd5, 0x90, - 0xeb, 0xac, 0xa7, 0xd5, 0xf3, 0x8d, 0x09, 0x9c, 0x01, 0x6e, 0x75, 0xc5, 0x2c, 0xa4, 0x20, 0xf9, 0xd6, 0x9e, 0x83, - 0xdb, 0x6a, 0x20, 0xe4, 0x9d, 0x73, 0x9f, 0x48, 0x81, 0x3f, 0xed, 0x7a, 0x27, 0x93, 0x55, 0xbf, 0xf1, 0xad, 0xda, - 0x6d, 0xff, 0xef, 0x46, 0xfc, 0xa3, 0x90, 0x3a, 0x7d, 0xce, 0x9f, 0x42, 0x58, 0x88, 0x6f, 0x74, 0x82, 0x2b, 0xe8, - 0x56, 0x95, 0xc2, 0xbc, 0x97, 0x36, 0xe7, 0xbd, 0x32, 0x07, 0x2d, 0x29, 0xe3, 0x09, 0x5b, 0x5c, 0xd4, 0xdb, 0x6e, - 0x46, 0xe9, 0x16, 0xe6, 0x47, 0x57, 0x2a, 0xb0, 0x20, 0x21, 0x49, 0x53, 0x64, 0xf0, 0x4f, 0x72, 0xe4, 0xb9, 0x0a, - 0x21, 0xdd, 0x68, 0xd2, 0x51, 0x67, 0xb5, 0xb8, 0xa9, 0xe3, 0x93, 0xf8, 0xb4, 0x46, 0xbb, 0xd6, 0x09, 0xff, 0x40, - 0xff, 0x3a, 0xd5, 0x4a, 0xfe, 0xfb, 0x54, 0x37, 0xf2, 0x5f, 0x67, 0x3a, 0x91, 0xff, 0x3e, 0xd3, 0xae, 0x87, 0x57, - 0x8f, 0xac, 0xab, 0x27, 0xd6, 0xd5, 0x33, 0x6b, 0xcc, 0x90, 0x1e, 0x5a, 0xe7, 0x3a, 0xff, 0xec, 0xc4, 0xf9, 0xa4, - 0xb5, 0x64, 0x9f, 0x6f, 0x95, 0xc2, 0x92, 0xf5, 0x6f, 0x27, 0xcd, 0x7c, 0x56, 0x4d, 0xe5, 0xe3, 0x01, 0x2a, 0x4f, - 0x3e, 0x0e, 0xea, 0x5c, 0x45, 0x44, 0x8d, 0x59, 0x51, 0x7b, 0xca, 0xec, 0xee, 0x9d, 0x78, 0x32, 0x7d, 0x88, 0xe8, - 0x6d, 0xe9, 0x66, 0xa8, 0xf4, 0x40, 0x7e, 0x6a, 0xd8, 0xb1, 0x11, 0xf5, 0xa0, 0xf1, 0xd2, 0xdd, 0x23, 0x31, 0xbe, - 0x5f, 0x0a, 0x11, 0x2b, 0xd2, 0x0a, 0x8a, 0x6f, 0x30, 0xf5, 0x50, 0xab, 0x16, 0x7b, 0xee, 0xc7, 0x6c, 0xe9, 0x5e, - 0x52, 0x62, 0x10, 0xc6, 0x76, 0x85, 0xff, 0x2c, 0xc0, 0xaa, 0xf8, 0x99, 0x59, 0x3a, 0x6d, 0xe6, 0x68, 0xe9, 0xf4, - 0x4b, 0xb6, 0x20, 0x5e, 0x86, 0x31, 0xdd, 0x91, 0x64, 0xec, 0x2e, 0x14, 0x5c, 0x41, 0x36, 0x7f, 0x8c, 0x8a, 0x7f, - 0x8a, 0xd5, 0xc3, 0xd3, 0x07, 0x65, 0x18, 0xfc, 0x4f, 0x13, 0xed, 0xa0, 0x1d, 0xa1, 0x8e, 0x71, 0xba, 0x25, 0x15, - 0xee, 0x0b, 0x14, 0xaf, 0xe7, 0xfe, 0x14, 0x55, 0xdf, 0x3a, 0x25, 0x24, 0x2e, 0x67, 0xdb, 0xcf, 0xdd, 0x1c, 0x7a, - 0xb2, 0xcf, 0x8f, 0x29, 0xc8, 0x4d, 0x37, 0xfc, 0x26, 0x58, 0x65, 0xf3, 0xc6, 0x6a, 0x57, 0x4f, 0xe2, 0xf2, 0x97, - 0xff, 0xd3, 0x7e, 0x9e, 0x40, 0xfb, 0xfd, 0x49, 0x3f, 0xf2, 0xd3, 0xe3, 0x18, 0x9d, 0x78, 0x33, 0x47, 0x1f, 0x7e, - 0x2e, 0xca, 0x37, 0xfb, 0x54, 0x3d, 0x4e, 0x76, 0xf3, 0x47, 0xf4, 0x1c, 0xfd, 0xd4, 0x6d, 0x35, 0xfd, 0xc7, 0x09, - 0xb4, 0xcf, 0x9f, 0xf5, 0xe3, 0xb3, 0x3b, 0x68, 0xfa, 0x23, 0xd3, 0xe4, 0x91, 0xcd, 0xf2, 0x95, 0xc5, 0x47, 0x59, - 0xd7, 0x38, 0xdc, 0x4c, 0x73, 0xad, 0x2b, 0x3c, 0xbd, 0xe9, 0x78, 0xa8, 0x8a, 0xc5, 0x31, 0x3e, 0x3d, 0x9e, 0xe0, - 0x43, 0x36, 0xfa, 0xcc, 0xe8, 0x52, 0x44, 0xef, 0xc9, 0x31, 0x44, 0x97, 0xcd, 0xa7, 0xe4, 0x2c, 0x9e, 0x3b, 0x47, - 0x5b, 0xe5, 0x1a, 0x59, 0x18, 0xb5, 0x86, 0xa7, 0xb8, 0x31, 0xfc, 0x9e, 0x53, 0x0e, 0x0c, 0x56, 0x22, 0xb5, 0x87, - 0xa9, 0x62, 0x7a, 0x4b, 0xa2, 0x4f, 0x4a, 0x71, 0xd4, 0x7e, 0x1b, 0x5d, 0x0d, 0x85, 0x27, 0x0f, 0x1c, 0xd5, 0x55, - 0x39, 0x7c, 0xc6, 0x49, 0xef, 0xdc, 0x88, 0xfa, 0xcb, 0xe0, 0x9b, 0x38, 0xd3, 0xa5, 0xeb, 0x4f, 0xd7, 0x91, 0x4f, - 0xba, 0x49, 0x53, 0x56, 0x6f, 0xab, 0xe9, 0x62, 0x8c, 0xce, 0x24, 0xcf, 0x82, 0x94, 0x10, 0x61, 0xac, 0xf0, 0xfc, - 0xf3, 0x69, 0xdb, 0x84, 0x09, 0xdb, 0x24, 0xaf, 0x05, 0x55, 0x44, 0xff, 0xf1, 0x90, 0x3a, 0x1c, 0xc4, 0x86, 0xea, - 0x5d, 0xdf, 0x1e, 0x33, 0xac, 0xcd, 0x8c, 0x78, 0xab, 0xc8, 0x3d, 0x0e, 0x92, 0x59, 0x16, 0x1f, 0x54, 0x9b, 0xe2, - 0xf7, 0xea, 0xc4, 0x38, 0x8d, 0x1a, 0x8f, 0x70, 0x66, 0xa6, 0xcd, 0xd9, 0x8e, 0x17, 0xf5, 0xae, 0xd6, 0x2f, 0x4f, - 0xc7, 0x87, 0xfe, 0xe1, 0x10, 0x2e, 0xe5, 0x61, 0x41, 0x7c, 0x5a, 0x3c, 0x8b, 0x1d, 0x1b, 0x27, 0xe3, 0xf0, 0x3f, - 0xb5, 0x23, 0xe3, 0x4e, 0x51, 0xc2, 0xa9, 0x7e, 0x9a, 0xd2, 0x59, 0xee, 0xa3, 0xe2, 0x1e, 0xb0, 0x1d, 0xce, 0x85, - 0xdb, 0x3d, 0x8f, 0x8c, 0xe8, 0x40, 0x55, 0x5f, 0xbf, 0x83, 0xe6, 0x5f, 0xe3, 0xfa, 0x0e, 0x14, 0xb1, 0xbe, 0xbf, - 0x9c, 0x62, 0x4e, 0x57, 0xe0, 0x98, 0x6f, 0xf9, 0x8e, 0x55, 0x13, 0xcf, 0xea, 0xaf, 0x87, 0xa7, 0x58, 0x85, 0x43, - 0xc1, 0x49, 0xc1, 0x21, 0xb1, 0x69, 0xca, 0x50, 0x38, 0xac, 0x11, 0x7e, 0xf5, 0x69, 0xea, 0x74, 0x71, 0x02, 0xe7, - 0x06, 0xc1, 0x54, 0x0b, 0xda, 0xf3, 0x63, 0x24, 0xde, 0x96, 0xa7, 0x85, 0x22, 0x1b, 0x9c, 0xa3, 0xf2, 0xd7, 0xcc, - 0x62, 0xe7, 0x70, 0x91, 0xff, 0xf3, 0x84, 0x3f, 0x1c, 0x43, 0xd0, 0xc8, 0xb2, 0x63, 0xf1, 0x9b, 0x49, 0x19, 0xde, - 0x3e, 0xe6, 0x5a, 0xb1, 0xa9, 0x27, 0xe3, 0x1f, 0x0e, 0x69, 0x66, 0x1f, 0x3d, 0xa2, 0xac, 0x40, 0xb4, 0xdd, 0xd9, - 0x56, 0x3f, 0x19, 0xa2, 0x96, 0x67, 0xca, 0x93, 0xfd, 0x04, 0xef, 0xd2, 0x0f, 0xf6, 0x83, 0x71, 0x3c, 0x48, 0x42, - 0x43, 0x65, 0xa5, 0x3f, 0x46, 0x85, 0x22, 0x9d, 0xaf, 0xf5, 0xa9, 0x0e, 0x5c, 0x09, 0x05, 0x4c, 0xb9, 0xd6, 0x5c, - 0x33, 0x1c, 0xdb, 0xf2, 0x2c, 0x2f, 0x8c, 0x2d, 0xc0, 0xa7, 0xfc, 0x2a, 0x44, 0x1b, 0x9c, 0x1b, 0x51, 0x16, 0xc8, - 0x44, 0x17, 0x45, 0x5f, 0xb3, 0x38, 0x34, 0xbb, 0x6a, 0x30, 0x4e, 0x43, 0x7f, 0xbd, 0x76, 0x3d, 0xd7, 0x29, 0x65, - 0x2d, 0x72, 0xe7, 0xa6, 0x63, 0x19, 0x36, 0x14, 0x39, 0xe5, 0x66, 0x3e, 0x91, 0x42, 0xdd, 0x40, 0x6f, 0x01, 0xae, - 0x9b, 0xf1, 0xc7, 0x2c, 0x90, 0xc4, 0x6a, 0x00, 0x06, 0x59, 0xfc, 0x8e, 0x00, 0x40, 0x49, 0x5f, 0x94, 0x81, 0x37, - 0x1c, 0x6e, 0x78, 0x5d, 0xd0, 0x5b, 0xed, 0xca, 0xe5, 0x29, 0x16, 0xee, 0xec, 0xf6, 0x3f, 0xaa, 0x27, 0xcf, 0xa1, - 0xb2, 0x23, 0xf3, 0xe9, 0xac, 0xb9, 0x87, 0xb8, 0x95, 0x21, 0xbf, 0x20, 0xe0, 0x02, 0x24, 0x50, 0x3a, 0xc2, 0x39, - 0xe3, 0x92, 0x6b, 0xdc, 0x55, 0xb3, 0x84, 0x12, 0x2c, 0xa1, 0xe3, 0xe7, 0x56, 0xd1, 0x81, 0x7a, 0x57, 0x4f, 0xb7, - 0xee, 0x41, 0x4a, 0xc9, 0xa7, 0x15, 0xeb, 0xc4, 0xf1, 0xfa, 0x35, 0x89, 0xe8, 0xc9, 0x43, 0x79, 0x9a, 0x73, 0x01, - 0xf9, 0x2d, 0x1b, 0x15, 0x33, 0xf3, 0x54, 0x8f, 0xfc, 0xd4, 0x14, 0xeb, 0xf6, 0x70, 0x07, 0xf4, 0xb4, 0x81, 0xf8, - 0x41, 0x71, 0x3f, 0x8b, 0xbc, 0xc6, 0xc3, 0x2c, 0x30, 0x8b, 0x98, 0x5a, 0x8d, 0x34, 0x3b, 0x52, 0x12, 0xd6, 0x42, - 0x26, 0x68, 0xae, 0x33, 0xb2, 0x69, 0xd7, 0x68, 0x17, 0x05, 0x46, 0x34, 0x1d, 0x6c, 0xaf, 0x91, 0x0c, 0xba, 0x8d, - 0xeb, 0x88, 0x10, 0x43, 0x05, 0xe8, 0xe3, 0x20, 0x14, 0xca, 0x3e, 0xa3, 0xf2, 0x22, 0x37, 0xeb, 0xe7, 0x42, 0x30, - 0x5a, 0x98, 0xa1, 0xaa, 0x1c, 0xbb, 0xa6, 0x40, 0xbe, 0x88, 0x8d, 0x20, 0x3b, 0xe5, 0xe3, 0x65, 0x3b, 0x55, 0x3d, - 0xdc, 0x44, 0xd5, 0x3f, 0xb0, 0xde, 0x5e, 0xb4, 0x7d, 0xc0, 0x2f, 0xb5, 0x23, 0xb7, 0x05, 0xae, 0x46, 0xe3, 0x9c, - 0x24, 0x8e, 0xdc, 0x3c, 0xce, 0xf5, 0x83, 0x59, 0x9f, 0xb4, 0xd6, 0x0e, 0xf2, 0x29, 0x02, 0x56, 0x29, 0x75, 0x92, - 0x5e, 0xfb, 0x28, 0xe3, 0xf1, 0x20, 0x21, 0x29, 0x5f, 0x30, 0x3e, 0x9b, 0x7d, 0xe6, 0x45, 0xc9, 0x02, 0xb3, 0x88, - 0x4a, 0xac, 0xc1, 0x74, 0x6c, 0x97, 0xc8, 0x48, 0x77, 0x02, 0xa7, 0x72, 0xac, 0x28, 0xec, 0x6e, 0x57, 0xb3, 0x6f, - 0x26, 0x6f, 0x4d, 0xea, 0x3b, 0xc6, 0x5c, 0xd0, 0x6b, 0xa3, 0xb4, 0x01, 0xb4, 0x07, 0x03, 0x87, 0xd5, 0x85, 0xd9, - 0x69, 0x35, 0xdb, 0xd4, 0x33, 0x62, 0x73, 0xd3, 0xd3, 0xd5, 0x44, 0x3f, 0x43, 0xc0, 0x38, 0x36, 0x8a, 0x7b, 0x6c, - 0x11, 0x6b, 0xe4, 0x35, 0xb5, 0x84, 0xd9, 0xb2, 0x70, 0x2b, 0x46, 0x73, 0x02, 0x63, 0x8c, 0xc9, 0x41, 0x0c, 0x9e, - 0x9b, 0xc3, 0x66, 0x4d, 0x4c, 0xa0, 0x6a, 0x7f, 0x53, 0x46, 0x96, 0xac, 0x62, 0x96, 0x06, 0x32, 0x2c, 0x03, 0x65, - 0xef, 0x85, 0x96, 0x3e, 0xda, 0xb9, 0x10, 0x6a, 0xda, 0xb6, 0xec, 0x36, 0x74, 0x48, 0x81, 0x0f, 0x4c, 0xb7, 0x3b, - 0x07, 0xae, 0xd8, 0xa3, 0xe0, 0x9d, 0xc1, 0xe3, 0x0f, 0xb3, 0x67, 0xc9, 0xef, 0x79, 0xa1, 0xca, 0xf5, 0x89, 0x8e, - 0x76, 0x0b, 0xc8, 0xc4, 0xec, 0xda, 0x96, 0x8f, 0xf6, 0x39, 0x3d, 0x64, 0xb8, 0x82, 0x8c, 0x23, 0x49, 0x11, 0x95, - 0xaf, 0xf4, 0x2a, 0xcb, 0x58, 0xb0, 0xcc, 0x65, 0xcc, 0x92, 0x9a, 0x4c, 0xaa, 0xbd, 0x9b, 0xc1, 0x93, 0xd7, 0x2c, - 0x4c, 0xa6, 0xb0, 0x66, 0x9b, 0x5d, 0x29, 0x47, 0x13, 0x44, 0x26, 0x71, 0x92, 0x64, 0x74, 0x06, 0x1f, 0x04, 0xa2, - 0xe4, 0x44, 0x50, 0xcd, 0xbe, 0x1f, 0xd5, 0x64, 0xad, 0x83, 0x51, 0x49, 0x95, 0xc1, 0xeb, 0x26, 0x45, 0x84, 0x26, - 0x49, 0xbe, 0x76, 0xc4, 0x64, 0x5b, 0xc7, 0xb9, 0x62, 0x95, 0x65, 0x1b, 0x47, 0x16, 0xb9, 0xd2, 0x90, 0x4a, 0x13, - 0xbd, 0xa0, 0x74, 0xe5, 0x5d, 0x28, 0x80, 0x88, 0x43, 0x2b, 0xc8, 0xed, 0xa5, 0x31, 0x13, 0x88, 0xf4, 0xc8, 0xfa, - 0x70, 0x64, 0x2b, 0xe9, 0x62, 0xa3, 0x14, 0x2c, 0x9e, 0x10, 0x16, 0x19, 0x7b, 0xc6, 0xea, 0x6f, 0xbf, 0x6b, 0x8a, - 0xb5, 0xdf, 0x1e, 0xd8, 0x9e, 0xff, 0xdd, 0xfb, 0xfd, 0x48, 0x01, 0x18, 0x71, 0x2f, 0x47, 0x44, 0xfc, 0x56, 0xe7, - 0xb7, 0x88, 0xdf, 0x7c, 0xfe, 0x6d, 0x78, 0x81, 0xae, 0x6b, 0x6c, 0x98, 0x69, 0xe7, 0x56, 0x95, 0x8e, 0xd8, 0x10, - 0x0b, 0xef, 0xf5, 0x29, 0xe9, 0x69, 0x22, 0xc3, 0xfe, 0xd1, 0xcc, 0x0a, 0xd5, 0xf4, 0x29, 0x21, 0xda, 0xc0, 0x64, - 0x84, 0x94, 0xbd, 0x14, 0xcc, 0xba, 0x75, 0xea, 0xe6, 0xb6, 0x18, 0x9f, 0x8f, 0x89, 0x75, 0xcb, 0xbf, 0xd2, 0xc5, - 0xc5, 0x84, 0x61, 0xd0, 0x15, 0x6f, 0xde, 0xb3, 0xe1, 0x50, 0xaa, 0x30, 0x06, 0x9a, 0xc3, 0x59, 0x54, 0x11, 0xa3, - 0x96, 0x71, 0xe7, 0x0e, 0xb8, 0x8e, 0x1e, 0xf0, 0x1b, 0xaa, 0x6a, 0x2c, 0x19, 0x9d, 0xbe, 0xad, 0x63, 0xc8, 0xd7, - 0x91, 0x55, 0x1c, 0xbf, 0xce, 0x53, 0xd0, 0xfb, 0x6e, 0x2a, 0xd7, 0xae, 0x2a, 0x88, 0x7e, 0x96, 0x20, 0xb1, 0x26, - 0x1f, 0x77, 0x6c, 0x95, 0x1b, 0x7f, 0x3e, 0xd5, 0x54, 0xdb, 0x20, 0xb4, 0x2c, 0xc5, 0x82, 0x9d, 0x88, 0x05, 0x2b, - 0xc2, 0xa7, 0x2f, 0x62, 0xd0, 0x38, 0xab, 0x02, 0x67, 0x1f, 0xac, 0x5c, 0xc5, 0x87, 0x2f, 0x01, 0x3a, 0xa9, 0xea, - 0xff, 0x20, 0x71, 0x9d, 0x9d, 0x6e, 0xc9, 0x5f, 0xfb, 0x33, 0x25, 0x82, 0x49, 0x4b, 0x08, 0x81, 0x33, 0xe2, 0xb7, - 0xbe, 0x3c, 0x41, 0x06, 0xb0, 0x66, 0xb4, 0x6b, 0xbf, 0x9c, 0x0c, 0xd3, 0x90, 0x10, 0x35, 0x6b, 0xd8, 0xbb, 0x78, - 0x85, 0x0e, 0x44, 0x62, 0xd0, 0xe4, 0x4d, 0xf0, 0x2b, 0xd5, 0x52, 0xb9, 0xe6, 0x9f, 0x77, 0x73, 0xb9, 0x38, 0xb2, - 0x71, 0x64, 0x65, 0xa1, 0xc0, 0xd7, 0x01, 0xf4, 0x09, 0x9a, 0x13, 0x17, 0xfe, 0x38, 0x4b, 0x5a, 0x64, 0x67, 0xf2, - 0x40, 0xdd, 0x40, 0xc9, 0x62, 0xa5, 0x78, 0x5f, 0x02, 0x1f, 0x94, 0xc1, 0x36, 0x7c, 0x26, 0x71, 0x51, 0x65, 0x4d, - 0xab, 0x7e, 0x8c, 0x5b, 0x88, 0x98, 0x09, 0x65, 0x20, 0x24, 0x39, 0x2b, 0x71, 0x43, 0x65, 0xc5, 0xd1, 0x9d, 0xc5, - 0x02, 0x4c, 0x90, 0xcc, 0x46, 0x04, 0xfe, 0x25, 0x2c, 0x9e, 0x8b, 0x9f, 0xe9, 0xbd, 0x0d, 0x34, 0x31, 0x22, 0x92, - 0x5d, 0xf4, 0x6a, 0x45, 0x0f, 0x76, 0x69, 0x0c, 0x1f, 0x12, 0xc5, 0xb1, 0x7d, 0xde, 0x0f, 0x1a, 0x35, 0x00, 0x0a, - 0x16, 0xdb, 0x92, 0xba, 0x64, 0xde, 0x5e, 0x7b, 0xb9, 0xab, 0xc3, 0xdd, 0x55, 0x08, 0x0a, 0x7c, 0xb6, 0x99, 0x54, - 0x1e, 0x09, 0x64, 0x8d, 0x2d, 0xe6, 0x89, 0xe8, 0x15, 0xd3, 0x95, 0xd1, 0x45, 0x91, 0xad, 0xe3, 0x37, 0x04, 0x8a, - 0x9c, 0x5d, 0x22, 0x31, 0x65, 0x3f, 0x47, 0xb9, 0xe4, 0x42, 0x63, 0x75, 0x24, 0x2f, 0x76, 0x35, 0x88, 0x97, 0xa9, - 0x09, 0x30, 0x05, 0x79, 0x67, 0x46, 0x23, 0x44, 0x54, 0x92, 0x48, 0x11, 0x90, 0x98, 0x4b, 0x3e, 0xc5, 0x43, 0xc8, - 0x4f, 0x15, 0x12, 0x5a, 0x32, 0x94, 0xff, 0xe1, 0x3a, 0xc1, 0xb7, 0x0a, 0x78, 0x91, 0xd4, 0x2f, 0x3c, 0x70, 0x5b, - 0xda, 0xeb, 0x94, 0x0d, 0x12, 0xf0, 0xfd, 0xf4, 0xf0, 0x59, 0x67, 0x0f, 0xe2, 0x27, 0x45, 0x40, 0xf0, 0x41, 0xaf, - 0x6a, 0xb7, 0x4c, 0xa1, 0x92, 0x6a, 0x48, 0xb9, 0x1f, 0x5d, 0x72, 0x3a, 0xe1, 0xf0, 0x02, 0xfe, 0xf1, 0xfd, 0x7c, - 0x03, 0x73, 0xf0, 0x95, 0xae, 0x9a, 0x48, 0xde, 0x0d, 0x83, 0x3d, 0x85, 0xf4, 0x12, 0x0e, 0x6d, 0x5f, 0x23, 0xcc, - 0x76, 0xae, 0xb5, 0xd9, 0xfe, 0xc4, 0x50, 0xa7, 0xd3, 0x8f, 0xdf, 0xc4, 0x46, 0x8d, 0x14, 0xb7, 0x4e, 0xc4, 0x42, - 0x49, 0x3f, 0x7b, 0x72, 0x63, 0x69, 0x3a, 0x56, 0x6f, 0x43, 0xcd, 0xe3, 0x9b, 0x63, 0x3d, 0x79, 0xb3, 0x6c, 0xc9, - 0x07, 0x98, 0x70, 0xcc, 0xb7, 0xa2, 0xe7, 0x59, 0xd9, 0x0b, 0xa6, 0xd6, 0x1f, 0x34, 0x42, 0x62, 0xa8, 0x22, 0xa9, - 0xd7, 0xc0, 0xfb, 0x3a, 0xad, 0x3d, 0xab, 0x67, 0x44, 0xe9, 0xd4, 0x54, 0xac, 0x79, 0xa1, 0x5e, 0x28, 0x53, 0x95, - 0x5a, 0xe6, 0xce, 0x56, 0xd9, 0x53, 0x2c, 0x2f, 0x65, 0x32, 0xc2, 0x7e, 0x02, 0x51, 0x89, 0xef, 0xa1, 0x9e, 0xc4, - 0xba, 0x33, 0xa7, 0x4f, 0xcc, 0xa4, 0x81, 0xf1, 0x11, 0x31, 0x02, 0xab, 0x78, 0x1b, 0x18, 0x26, 0x6a, 0x8d, 0x0b, - 0xdd, 0x91, 0xd1, 0x3a, 0x7c, 0xc3, 0x3d, 0x61, 0x7d, 0x2f, 0xc8, 0x6e, 0xf8, 0xef, 0x99, 0x70, 0xdb, 0xcb, 0x3c, - 0x9a, 0x29, 0xbd, 0x79, 0x7c, 0x1c, 0xd1, 0xf4, 0x96, 0xca, 0x91, 0x2d, 0xe8, 0xae, 0xd7, 0xb0, 0xf1, 0x47, 0x41, - 0xf5, 0x58, 0xba, 0x19, 0x19, 0x31, 0x8e, 0x07, 0x83, 0x24, 0xe8, 0x43, 0xce, 0xaf, 0xa4, 0xe5, 0x79, 0x48, 0x5b, - 0x4c, 0xd8, 0x83, 0xe5, 0x14, 0x99, 0x18, 0x2e, 0xc1, 0xdc, 0xe6, 0x6c, 0xde, 0x7c, 0xe3, 0x8f, 0xc3, 0x9e, 0x4a, - 0x54, 0xc8, 0x83, 0x73, 0xdf, 0xca, 0x38, 0x4d, 0x1a, 0x28, 0x96, 0x31, 0x97, 0xf9, 0x61, 0x53, 0x47, 0xdb, 0xa1, - 0x50, 0x4d, 0xed, 0x9c, 0x7e, 0x9d, 0xec, 0xd3, 0x5e, 0x1d, 0xc9, 0x00, 0x59, 0x03, 0xa1, 0x0a, 0x02, 0x3e, 0xaf, - 0x29, 0x02, 0xc0, 0x72, 0x04, 0x8f, 0xf8, 0x83, 0x30, 0x7e, 0xfa, 0x46, 0xd2, 0x49, 0x58, 0xec, 0x7a, 0x01, 0x47, - 0xaf, 0x03, 0x68, 0xa3, 0x9e, 0xdb, 0x7e, 0x04, 0xa0, 0x5c, 0xac, 0xaf, 0x12, 0x6d, 0x23, 0x75, 0x08, 0xfb, 0xbe, - 0x35, 0xdb, 0xd1, 0x46, 0x9b, 0xe7, 0xd2, 0x68, 0x34, 0xb4, 0x59, 0x1d, 0xe8, 0x1e, 0xa9, 0x00, 0xd0, 0x65, 0x43, - 0xe1, 0xeb, 0xfb, 0x87, 0x28, 0xdd, 0x08, 0x76, 0xc1, 0x19, 0x7c, 0xb9, 0x74, 0xcc, 0xb7, 0x70, 0x34, 0x9f, 0x99, - 0x7a, 0x2b, 0x3f, 0x83, 0xfa, 0xba, 0xdb, 0x05, 0xe0, 0x57, 0x2e, 0x72, 0xc0, 0xf4, 0x3b, 0x9b, 0xe2, 0xa0, 0xb7, - 0x1c, 0xbd, 0xc6, 0xe9, 0xcc, 0x0c, 0x58, 0xc8, 0xb3, 0x6b, 0xe5, 0x43, 0x72, 0x03, 0x59, 0x5c, 0x40, 0x43, 0x76, - 0x0b, 0xb8, 0xf2, 0x4c, 0x97, 0x28, 0x49, 0x13, 0x84, 0x9e, 0xc0, 0x63, 0x35, 0x73, 0xb0, 0xec, 0x7d, 0x39, 0xd1, - 0xf3, 0x5c, 0x3e, 0x05, 0x8d, 0x14, 0xa8, 0x74, 0x5e, 0x52, 0x16, 0x90, 0x73, 0xa8, 0x83, 0x10, 0x33, 0x1d, 0xf4, - 0x92, 0xa9, 0xa6, 0x32, 0x87, 0x46, 0x48, 0x7e, 0x50, 0x90, 0x9c, 0xc0, 0xb9, 0xf9, 0x6a, 0x1d, 0xf5, 0xcb, 0x45, - 0x65, 0xbd, 0xa8, 0xc8, 0x04, 0xb7, 0x12, 0x1f, 0xb2, 0xfa, 0xc6, 0xc8, 0xe8, 0x68, 0x1d, 0x56, 0x9e, 0xc6, 0xf9, - 0x81, 0x07, 0x87, 0xe0, 0xc8, 0x1e, 0x62, 0x01, 0xa0, 0x89, 0xdb, 0x1c, 0xc2, 0x9f, 0xf9, 0xc8, 0x14, 0xb8, 0x35, - 0x0c, 0x09, 0x02, 0x02, 0x3e, 0xb1, 0x04, 0x8e, 0x99, 0x41, 0xc4, 0xb1, 0xd5, 0xe6, 0x0f, 0x98, 0x48, 0xab, 0xbc, - 0x31, 0x62, 0x13, 0x4e, 0x5c, 0xe3, 0x12, 0x29, 0x64, 0x6f, 0x4d, 0x76, 0xc2, 0x22, 0x0b, 0x1b, 0x72, 0xe4, 0x63, - 0xed, 0x65, 0x92, 0xf7, 0x65, 0x16, 0x2d, 0x29, 0x51, 0x77, 0x29, 0x52, 0xbc, 0x6e, 0x1f, 0xa2, 0xd5, 0x5a, 0xb5, - 0xd4, 0x71, 0xe8, 0x2e, 0x58, 0xcf, 0xfb, 0xbf, 0x7e, 0x2b, 0xa5, 0x7e, 0x72, 0x3e, 0x06, 0x55, 0xdc, 0x05, 0x85, - 0x35, 0x47, 0xc2, 0xd6, 0x4d, 0x93, 0x35, 0x79, 0x68, 0xbf, 0xec, 0x85, 0xae, 0xbb, 0x8d, 0xa8, 0x6a, 0x29, 0xf5, - 0x98, 0x17, 0x22, 0x1f, 0x86, 0x3e, 0x56, 0x8c, 0x50, 0x15, 0x1a, 0x5b, 0x3a, 0xe4, 0x71, 0x62, 0xe9, 0xf4, 0x41, - 0xe8, 0x5d, 0x0e, 0xf7, 0x21, 0x96, 0x87, 0x95, 0x24, 0xca, 0x8c, 0xa9, 0x44, 0x34, 0x8e, 0x80, 0xd1, 0xc6, 0xd8, - 0x6d, 0x04, 0x4e, 0x09, 0x36, 0x67, 0xd6, 0xbf, 0x62, 0x3c, 0xf1, 0x35, 0x74, 0x24, 0x19, 0x34, 0xe3, 0x87, 0x98, - 0xcf, 0x78, 0x23, 0x3a, 0x0c, 0x0d, 0x9a, 0xfe, 0x61, 0x9b, 0x8f, 0xbd, 0x96, 0xd0, 0x8f, 0x38, 0x84, 0x73, 0xde, - 0xf9, 0xa1, 0xfd, 0x62, 0x35, 0xe4, 0x6b, 0xd8, 0xbf, 0xf2, 0x94, 0xbf, 0xf2, 0x35, 0xdc, 0x87, 0x3c, 0xe5, 0x43, - 0xbe, 0x86, 0xfc, 0x90, 0x27, 0xc9, 0xe0, 0xf4, 0x7c, 0xa5, 0x3e, 0xf7, 0xd7, 0x42, 0x9d, 0x5c, 0x9e, 0x09, 0xad, - 0xe4, 0xa0, 0x17, 0xdf, 0x25, 0xda, 0x67, 0x02, 0x19, 0x3e, 0x2e, 0xa6, 0x44, 0x88, 0x43, 0x56, 0x96, 0x2e, 0x01, - 0x74, 0x1a, 0xe0, 0xdd, 0xeb, 0xeb, 0xbb, 0xfe, 0x15, 0xb6, 0x48, 0x1a, 0x03, 0xf1, 0xb8, 0x0f, 0xfa, 0xa9, 0x4e, - 0xdd, 0x78, 0x6e, 0x2b, 0x20, 0xe4, 0xca, 0x91, 0x80, 0x93, 0x8c, 0x76, 0x84, 0x10, 0xbd, 0x73, 0xbf, 0x67, 0x66, - 0xe6, 0xdb, 0xf7, 0xd0, 0x6b, 0xe1, 0x30, 0x87, 0x00, 0x39, 0xcb, 0x92, 0xc1, 0x5e, 0xec, 0x5f, 0xaf, 0x3e, 0x46, - 0xfa, 0xd4, 0x0c, 0x50, 0xd1, 0xa0, 0x6a, 0xb2, 0x3f, 0xe6, 0xc8, 0x48, 0x7a, 0xf9, 0x8f, 0x79, 0x97, 0x94, 0xa5, - 0xcb, 0x64, 0x08, 0xdc, 0x13, 0xb4, 0xdc, 0xcf, 0x82, 0x84, 0x4c, 0x33, 0xcb, 0x06, 0x51, 0x5b, 0x4e, 0x33, 0xe6, - 0x91, 0x1e, 0x4b, 0xb5, 0x54, 0x16, 0xee, 0x7c, 0xc7, 0xcf, 0xf8, 0x3f, 0x98, 0x84, 0xe6, 0x57, 0x83, 0xf2, 0x45, - 0xce, 0xac, 0xbb, 0x2b, 0x6c, 0x69, 0x0d, 0xa6, 0x25, 0x92, 0xa5, 0xc5, 0xb9, 0xd5, 0x98, 0x56, 0x90, 0xd6, 0x23, - 0x4f, 0x43, 0x34, 0xba, 0x49, 0x22, 0x36, 0x72, 0x6a, 0x3d, 0xe9, 0xda, 0x52, 0x93, 0xcc, 0x8a, 0xa5, 0x57, 0xb2, - 0xf7, 0xcd, 0x37, 0xd4, 0xa7, 0xe6, 0x72, 0x39, 0xc0, 0x26, 0xd3, 0x4d, 0xb1, 0x35, 0x05, 0xde, 0x25, 0x49, 0x11, - 0x1a, 0x02, 0xe5, 0xa8, 0x6d, 0x26, 0xbb, 0x4b, 0x55, 0x2d, 0xa7, 0x6a, 0x84, 0x48, 0x7d, 0x55, 0x61, 0xa9, 0x8e, - 0xe2, 0xe1, 0xc5, 0xbe, 0x88, 0xdd, 0x07, 0x71, 0x9d, 0xa5, 0x69, 0xb4, 0x59, 0xab, 0xad, 0x85, 0x3c, 0x06, 0x5f, - 0xee, 0x1a, 0x62, 0x00, 0xeb, 0x88, 0x46, 0x67, 0xf1, 0xe5, 0xd9, 0x35, 0x3c, 0x76, 0x68, 0xbf, 0xf6, 0xc1, 0x49, - 0x8b, 0xed, 0xa9, 0x14, 0x6e, 0x7d, 0x46, 0x06, 0x81, 0x44, 0xe2, 0x03, 0x00, 0x06, 0x00, 0x98, 0xea, 0x25, 0x45, - 0x35, 0x32, 0x68, 0x25, 0x0a, 0xf4, 0x48, 0xc1, 0x7d, 0x74, 0x19, 0x5a, 0x0e, 0x0e, 0x7f, 0x44, 0x4a, 0xab, 0x1d, - 0xb2, 0xc4, 0x44, 0xa6, 0x85, 0x92, 0x39, 0x4c, 0x68, 0xa5, 0xc5, 0x18, 0xb4, 0x44, 0xe1, 0x3d, 0x41, 0x3a, 0x6a, - 0x49, 0x80, 0xfa, 0xf2, 0xe8, 0x40, 0xc2, 0xe9, 0xbd, 0x79, 0xbe, 0x36, 0x7e, 0x2d, 0x6f, 0x9b, 0xe5, 0xba, 0x23, - 0x5b, 0xc1, 0x14, 0x92, 0x21, 0xd8, 0xe5, 0x6c, 0x95, 0x33, 0xfa, 0x08, 0x71, 0x12, 0xcb, 0x92, 0xd7, 0x56, 0xb9, - 0x59, 0x8c, 0x3e, 0x74, 0xcd, 0x7d, 0xd1, 0x0f, 0x75, 0xcf, 0x8f, 0x40, 0x70, 0x44, 0xb0, 0x08, 0x9e, 0xe3, 0xb4, - 0x6e, 0xf2, 0x52, 0x52, 0x13, 0xa4, 0x28, 0xf0, 0x21, 0xfd, 0xfc, 0x06, 0x43, 0x05, 0xdb, 0x6c, 0xc3, 0x21, 0x47, - 0x03, 0xcd, 0x77, 0x35, 0xfe, 0x7a, 0x75, 0x02, 0xd6, 0x92, 0xce, 0x53, 0xdb, 0xb6, 0x89, 0x3d, 0xe6, 0x8a, 0xb4, - 0xd3, 0x56, 0x08, 0xf5, 0xb9, 0xf8, 0xec, 0x67, 0xcf, 0x89, 0xaa, 0xfb, 0xf2, 0x43, 0xf0, 0xbd, 0x5d, 0x54, 0xed, - 0xb5, 0x05, 0x94, 0x1f, 0x67, 0x52, 0x6a, 0xb6, 0x0e, 0x8a, 0xd2, 0xe3, 0xd1, 0x88, 0x16, 0xb7, 0xb7, 0x94, 0xbd, - 0x1f, 0x24, 0xc1, 0x4d, 0xa6, 0x56, 0xfe, 0xdb, 0xbb, 0xdb, 0x93, 0x7c, 0x8f, 0x82, 0xcc, 0xbd, 0x16, 0xce, 0x33, - 0x73, 0x09, 0x41, 0x01, 0x22, 0x23, 0x28, 0xb3, 0x31, 0x6f, 0x03, 0xf3, 0x0e, 0xcc, 0x2f, 0xe8, 0x51, 0xa9, 0x38, - 0x90, 0x9c, 0xd5, 0xc5, 0xa8, 0x98, 0x94, 0x03, 0x2f, 0x71, 0xfd, 0x5d, 0x1a, 0x12, 0x10, 0xb8, 0x46, 0x5d, 0x06, - 0x8b, 0xc4, 0x3e, 0x51, 0x7c, 0x04, 0x67, 0xfb, 0xc6, 0x0e, 0x32, 0xbb, 0xe1, 0x7d, 0x5d, 0x5c, 0xc0, 0x1d, 0x84, - 0xcf, 0xd2, 0x53, 0x10, 0xa1, 0xa9, 0xfb, 0xdf, 0xb8, 0xa8, 0x14, 0xbe, 0xd9, 0x20, 0x63, 0xcf, 0x2f, 0xeb, 0x00, - 0xe4, 0xd2, 0x34, 0x0a, 0x83, 0x19, 0x7f, 0x72, 0xa4, 0x5f, 0x85, 0x1e, 0x52, 0x5d, 0x8b, 0xba, 0x4b, 0x72, 0x3f, - 0x74, 0xec, 0x1c, 0x8a, 0x54, 0xb1, 0xad, 0xc3, 0xf9, 0xa2, 0x91, 0xa9, 0x49, 0xff, 0xc2, 0xe3, 0x9d, 0x4d, 0xb7, - 0xdf, 0x60, 0x2e, 0x85, 0x40, 0x36, 0x32, 0xb1, 0xe9, 0xa4, 0x1d, 0x95, 0xea, 0xca, 0x9d, 0x17, 0x15, 0xea, 0xad, - 0x65, 0x2f, 0xe9, 0xe8, 0xc3, 0x8a, 0x5c, 0x4a, 0xd8, 0x12, 0x49, 0x53, 0xb8, 0x54, 0xc6, 0x58, 0x3a, 0x33, 0x77, - 0xe7, 0xbb, 0xb8, 0x92, 0xc6, 0x01, 0x3e, 0x86, 0xa1, 0x6c, 0xc4, 0xdf, 0x0f, 0x90, 0x86, 0x6a, 0x6a, 0xdd, 0x0a, - 0x64, 0x82, 0x65, 0x85, 0x12, 0x3a, 0x54, 0x50, 0x7c, 0xe0, 0xfb, 0xce, 0xe0, 0xc6, 0x49, 0xc9, 0xc6, 0xdf, 0x37, - 0xeb, 0x1e, 0x93, 0x87, 0x33, 0x93, 0xbb, 0x00, 0xaa, 0xd8, 0x6b, 0x05, 0xce, 0x0c, 0xa1, 0x70, 0x72, 0x1c, 0xd7, - 0x32, 0x27, 0xc8, 0x3a, 0x7a, 0xdb, 0x03, 0x6f, 0x91, 0x76, 0xd7, 0x45, 0x9a, 0x52, 0xed, 0x28, 0xd8, 0xc6, 0x09, - 0x38, 0xeb, 0xfb, 0x0f, 0x4a, 0xe3, 0x4a, 0xea, 0xf2, 0x79, 0x5a, 0x64, 0xdb, 0x33, 0xe2, 0x60, 0x57, 0xb5, 0x29, - 0xca, 0xa2, 0x08, 0x23, 0x0c, 0x46, 0x08, 0x5b, 0x96, 0x18, 0xc7, 0x44, 0x6c, 0x12, 0x0a, 0xa3, 0x8f, 0xca, 0x6a, - 0xe5, 0x3a, 0x96, 0x7e, 0xd5, 0x59, 0x21, 0x75, 0x44, 0x7b, 0x1f, 0xbc, 0xc4, 0x24, 0x65, 0x79, 0x4e, 0xb6, 0xf8, - 0xf4, 0x42, 0xad, 0x4f, 0xa9, 0xf6, 0xc0, 0xde, 0xdc, 0x1c, 0x24, 0x4d, 0xbe, 0x27, 0x21, 0x1e, 0x16, 0x9d, 0xd7, - 0x06, 0xe7, 0xe5, 0x69, 0xdc, 0xfd, 0x59, 0x37, 0x2d, 0x5b, 0x17, 0xe2, 0x14, 0x55, 0x47, 0xbd, 0xc9, 0xe9, 0xb5, - 0xcf, 0x3f, 0x11, 0xea, 0x84, 0x41, 0xc3, 0xcc, 0x69, 0x89, 0x89, 0x48, 0xd7, 0x65, 0x1e, 0x98, 0x08, 0xee, 0x3d, - 0x83, 0x61, 0x87, 0xe4, 0x71, 0xb2, 0x30, 0x9d, 0xb0, 0x0b, 0x51, 0xd9, 0x26, 0x67, 0xbe, 0xe7, 0xe6, 0x5f, 0x0f, - 0x64, 0x18, 0xf6, 0x69, 0x41, 0xcb, 0x79, 0xfd, 0xa6, 0x77, 0x7f, 0xb9, 0xe8, 0xa9, 0x3f, 0x06, 0xd7, 0x15, 0x9a, - 0xb0, 0x78, 0x4d, 0x87, 0xfd, 0x2f, 0xa2, 0x9f, 0xb8, 0xcf, 0xf2, 0x9e, 0x46, 0x33, 0x86, 0xc6, 0xac, 0x89, 0xfa, - 0x9d, 0x99, 0x1d, 0x85, 0x20, 0x39, 0xb1, 0x93, 0xb3, 0xfa, 0x11, 0x90, 0x88, 0x31, 0xb5, 0x9b, 0x83, 0x61, 0x76, - 0x8c, 0xb3, 0xb0, 0x68, 0xd1, 0x97, 0x87, 0x9c, 0x56, 0x00, 0x86, 0x97, 0xca, 0x2f, 0xbb, 0x76, 0x68, 0xca, 0xe3, - 0x84, 0x5a, 0x2b, 0xb8, 0x16, 0x32, 0x47, 0x55, 0x6d, 0xa2, 0xb5, 0x14, 0x81, 0x59, 0x1c, 0xeb, 0xf6, 0x53, 0x5d, - 0xff, 0x01, 0x46, 0x5f, 0xf3, 0xb0, 0x3d, 0x7f, 0x92, 0xd8, 0x52, 0xeb, 0x73, 0xbe, 0x25, 0x7a, 0x19, 0x7b, 0xaf, - 0x13, 0xb5, 0x09, 0x96, 0x6c, 0xc9, 0xca, 0x35, 0x45, 0xb8, 0x89, 0xa1, 0xea, 0x1a, 0x42, 0xb9, 0x41, 0xe2, 0x1b, - 0x32, 0x81, 0xd5, 0xf9, 0xa5, 0xce, 0xd2, 0xb3, 0x84, 0x76, 0x79, 0xa0, 0x9d, 0x9d, 0x30, 0xd2, 0x45, 0xe1, 0xff, - 0x4e, 0x26, 0x84, 0xe0, 0xca, 0x86, 0x67, 0x4b, 0xa8, 0x8b, 0xe2, 0xe2, 0xaa, 0x5d, 0x40, 0xf1, 0xeb, 0xf5, 0xbb, - 0xf5, 0xbf, 0xa5, 0xef, 0x70, 0xd9, 0x20, 0xf6, 0xd7, 0x88, 0x7a, 0x9a, 0xcc, 0xb0, 0xda, 0xe8, 0x16, 0xc3, 0xfe, - 0xd1, 0xf4, 0x8d, 0x24, 0x76, 0x0a, 0x17, 0xdf, 0x77, 0x4a, 0x1c, 0xef, 0xa6, 0x29, 0x6b, 0xa2, 0xf1, 0xbf, 0x51, - 0xd3, 0xe0, 0x14, 0xbe, 0xbe, 0xc1, 0xa9, 0xe0, 0x61, 0xd7, 0xd4, 0x50, 0xec, 0xee, 0x17, 0x2b, 0x9a, 0xd6, 0x5a, - 0x57, 0x18, 0xa0, 0x0a, 0x1f, 0x41, 0x4e, 0x45, 0xbe, 0x97, 0xfb, 0x8a, 0x2f, 0xf2, 0x47, 0xdf, 0xbc, 0x74, 0x84, - 0x35, 0x97, 0x42, 0xcd, 0xad, 0x4c, 0xf2, 0xd3, 0xf2, 0x22, 0xe9, 0x96, 0x18, 0x94, 0x73, 0xcb, 0xfc, 0x7a, 0x07, - 0x8a, 0x4a, 0xcc, 0xb6, 0x2b, 0x37, 0x08, 0xd3, 0x3a, 0x17, 0xe1, 0xbd, 0xb6, 0x12, 0x29, 0x6a, 0x8d, 0x59, 0xce, - 0xb4, 0xa4, 0x1e, 0x9b, 0xcf, 0x44, 0x1d, 0xb8, 0x01, 0x31, 0xfa, 0x9e, 0x29, 0x79, 0x0d, 0x08, 0xbb, 0xe7, 0xe1, - 0xfb, 0x64, 0x79, 0x19, 0xe6, 0x5a, 0x59, 0x52, 0x4d, 0xd6, 0x3d, 0x55, 0x48, 0x1a, 0x13, 0x7a, 0x6b, 0x97, 0x79, - 0xb9, 0x55, 0x67, 0x78, 0xb2, 0x4e, 0xef, 0x59, 0xea, 0x07, 0x78, 0x5d, 0x25, 0x0f, 0x15, 0x1e, 0x2c, 0xdc, 0xb8, - 0x00, 0x5a, 0x56, 0xde, 0xea, 0x1c, 0x47, 0xb7, 0x79, 0x4a, 0xd6, 0x66, 0x83, 0xd7, 0x44, 0x2c, 0xa0, 0x64, 0x7b, - 0xb0, 0xdd, 0xc6, 0xca, 0x21, 0x1a, 0x6f, 0x1f, 0x59, 0x48, 0xd1, 0x75, 0x83, 0x36, 0x2f, 0x0f, 0x98, 0xc3, 0x51, - 0x75, 0x75, 0xa3, 0x9c, 0xbd, 0xc4, 0xfc, 0x60, 0xa4, 0x40, 0x41, 0x23, 0x7b, 0xc1, 0xa2, 0x4a, 0xbd, 0x8f, 0xad, - 0x57, 0x7d, 0xbb, 0x16, 0x7e, 0x24, 0x82, 0x91, 0xda, 0x28, 0xe1, 0x79, 0x8a, 0xe4, 0xd9, 0xb1, 0x9b, 0x27, 0x27, - 0x64, 0x64, 0x5e, 0xba, 0x02, 0x92, 0xb0, 0xe0, 0xa1, 0x09, 0xc2, 0xe2, 0x54, 0x32, 0x82, 0x88, 0x7d, 0xce, 0xdc, - 0x40, 0xa8, 0x1a, 0xae, 0x22, 0xc0, 0xcd, 0x93, 0x5e, 0xd2, 0x3c, 0x96, 0xdb, 0x62, 0xcc, 0xea, 0x34, 0x13, 0x6a, - 0x79, 0x26, 0xa2, 0x44, 0x7e, 0x5e, 0x0f, 0xf9, 0x08, 0xe8, 0xd0, 0x6d, 0xc2, 0xb9, 0x58, 0x63, 0x27, 0x56, 0xa9, - 0xb5, 0xa0, 0xf0, 0xdb, 0xb1, 0xc9, 0xda, 0x6f, 0x32, 0xa3, 0x67, 0x30, 0xff, 0x2c, 0x46, 0xb2, 0x9b, 0x3e, 0x8a, - 0xe3, 0x3e, 0x40, 0x01, 0x99, 0x6f, 0xe8, 0x20, 0xf9, 0x6d, 0xa9, 0x1e, 0xd7, 0xbb, 0x51, 0x2e, 0xc4, 0x93, 0x2c, - 0xf2, 0x40, 0xaa, 0x9d, 0xaf, 0x72, 0x5c, 0x7a, 0xe4, 0xd6, 0x0f, 0x54, 0x03, 0x42, 0x20, 0xcb, 0x0d, 0xa4, 0xf0, - 0x06, 0x07, 0xce, 0x9b, 0x38, 0x22, 0xa1, 0xac, 0x67, 0x22, 0x98, 0x2c, 0x4a, 0xf1, 0x5e, 0xfc, 0xe2, 0xd7, 0xee, - 0x2f, 0x16, 0x67, 0x7d, 0xb1, 0x87, 0xcd, 0xf2, 0xc5, 0x7b, 0x0d, 0xc4, 0x56, 0x15, 0x1e, 0x2c, 0x59, 0x4c, 0x0f, - 0x5e, 0xef, 0x11, 0x36, 0xf6, 0x0c, 0xef, 0xc1, 0x27, 0xfd, 0x5a, 0x42, 0xa5, 0xcd, 0xa5, 0xe8, 0x80, 0xfd, 0x30, - 0xdc, 0x64, 0xdf, 0x08, 0x13, 0xd2, 0xc5, 0xfa, 0x44, 0xff, 0x19, 0x24, 0x79, 0xb7, 0xeb, 0xef, 0xeb, 0x45, 0xe4, - 0x06, 0x2b, 0x05, 0xd9, 0xd8, 0x6d, 0x76, 0x90, 0x35, 0x64, 0x25, 0x53, 0x63, 0x82, 0x50, 0x06, 0xe9, 0x0b, 0x51, - 0x97, 0xf7, 0x57, 0x6d, 0x78, 0x98, 0xae, 0xb6, 0x96, 0x15, 0xc5, 0xb7, 0xf2, 0x5f, 0x85, 0xee, 0x78, 0x8e, 0x8e, - 0xa4, 0xbe, 0x73, 0x88, 0x3f, 0x7b, 0x1d, 0x34, 0x11, 0xaa, 0x02, 0xf2, 0xd7, 0xda, 0x0b, 0xe7, 0xd6, 0x53, 0x4e, - 0xee, 0xce, 0xa7, 0x5b, 0xb9, 0x08, 0xe9, 0x07, 0x86, 0x5e, 0xb6, 0xd8, 0xe8, 0xc5, 0x63, 0x3a, 0xd6, 0xa1, 0x25, - 0x12, 0xe3, 0x73, 0x60, 0xa6, 0x4e, 0x5d, 0x63, 0x62, 0x3a, 0xeb, 0x8f, 0x91, 0x15, 0x58, 0x80, 0x31, 0xd6, 0xc2, - 0x4f, 0x57, 0xe1, 0xdb, 0xe9, 0x37, 0x84, 0x20, 0x70, 0x9b, 0x34, 0xf1, 0xd3, 0xd5, 0x53, 0x6c, 0x7e, 0x53, 0x31, - 0x57, 0xc4, 0xb6, 0x1c, 0x68, 0xd1, 0xaa, 0x86, 0x3a, 0xb3, 0x13, 0x14, 0x84, 0x29, 0x12, 0x85, 0x31, 0x57, 0x47, - 0x89, 0x41, 0xd4, 0x72, 0xea, 0x2e, 0x64, 0x9b, 0x0a, 0xb5, 0x25, 0xb9, 0x28, 0x28, 0xe1, 0x88, 0x4d, 0xe2, 0x4c, - 0x35, 0x07, 0xa8, 0x5f, 0xdb, 0xb4, 0x09, 0x67, 0xbd, 0xe0, 0xde, 0xa9, 0xa0, 0x50, 0x53, 0xc3, 0xe0, 0x15, 0x1b, - 0x83, 0x57, 0xe5, 0x0c, 0xed, 0xf0, 0x22, 0xfd, 0xbe, 0xf9, 0x44, 0x5b, 0x4b, 0x73, 0xb3, 0xec, 0xdf, 0xcb, 0xc3, - 0x1f, 0x0d, 0x6f, 0xbf, 0x73, 0x26, 0xc4, 0x45, 0xf3, 0xa1, 0xa7, 0x5e, 0xe2, 0x71, 0x83, 0x62, 0x0f, 0xcd, 0x8c, - 0x19, 0x76, 0x9f, 0x69, 0xe9, 0x30, 0xc6, 0xed, 0xc4, 0x2d, 0xed, 0x41, 0x37, 0x2a, 0x8c, 0x3d, 0x3d, 0xdf, 0x40, - 0xeb, 0xad, 0xf0, 0xb6, 0xb5, 0x3b, 0x6d, 0x7c, 0x3e, 0x1d, 0x03, 0xe8, 0x1b, 0x6d, 0xba, 0x6c, 0x1e, 0xba, 0x4c, - 0xc6, 0x22, 0xd1, 0x76, 0xc8, 0x17, 0xcb, 0xc3, 0xef, 0xbd, 0xad, 0x4d, 0x7b, 0x0b, 0xd7, 0x91, 0x21, 0x83, 0xb4, - 0x54, 0x89, 0x54, 0xd1, 0xa3, 0x0b, 0xe4, 0xd5, 0x4c, 0xb4, 0x72, 0x8d, 0x3a, 0xe3, 0xf5, 0xed, 0x52, 0x65, 0xf9, - 0x63, 0x0b, 0x51, 0xa5, 0x97, 0xff, 0x02, 0x31, 0xcf, 0x0e, 0x93, 0x81, 0xe1, 0x14, 0x42, 0x63, 0xf7, 0x7f, 0x80, - 0xd3, 0x2e, 0x03, 0x6a, 0x42, 0xcd, 0xcb, 0x45, 0x17, 0x49, 0x71, 0xf9, 0xe9, 0x7e, 0x37, 0x04, 0xf1, 0x7c, 0x75, - 0x16, 0x5c, 0x7b, 0x49, 0x92, 0x4a, 0xfc, 0xa5, 0x34, 0x4d, 0x38, 0xc9, 0xb6, 0x22, 0x7e, 0x55, 0x9f, 0x00, 0x48, - 0x21, 0x5e, 0x69, 0x16, 0x69, 0xe2, 0x2d, 0xe9, 0xaa, 0x90, 0x51, 0xf1, 0x21, 0x85, 0x6f, 0x65, 0xb4, 0x3d, 0x9a, - 0x61, 0x74, 0x8d, 0x25, 0x76, 0x10, 0xba, 0x61, 0x9a, 0x30, 0x02, 0x1d, 0xd8, 0xc9, 0x00, 0x89, 0xbc, 0x53, 0x0e, - 0x31, 0x57, 0x4d, 0x4c, 0xc1, 0x0f, 0x49, 0xbd, 0x97, 0x20, 0xb7, 0xa0, 0x79, 0x56, 0xd6, 0x84, 0xd8, 0xe4, 0xc8, - 0xfd, 0x3e, 0x39, 0xe0, 0x7a, 0x61, 0x73, 0xb0, 0x51, 0xe9, 0x38, 0xb9, 0xcf, 0xf0, 0x6f, 0x3b, 0x49, 0x01, 0xb5, - 0x5b, 0xc5, 0x5c, 0x8e, 0xd3, 0x5c, 0xd0, 0x62, 0xfa, 0x6f, 0x06, 0x92, 0x83, 0xfe, 0x91, 0xa0, 0x81, 0xa5, 0xc3, - 0x4f, 0x74, 0x6b, 0xf0, 0x2f, 0x6c, 0x35, 0xcd, 0x4a, 0x64, 0xb5, 0xa7, 0x58, 0x7b, 0xe6, 0x65, 0xf2, 0xed, 0xa4, - 0xfe, 0x35, 0xaf, 0x49, 0xac, 0x7e, 0xe2, 0xa6, 0x16, 0x8f, 0x5c, 0x9f, 0x72, 0x70, 0x7a, 0xaa, 0xc7, 0x5e, 0xd8, - 0x75, 0x9a, 0x95, 0x0c, 0x51, 0x9c, 0x4b, 0xb6, 0xeb, 0xe2, 0x6f, 0x2f, 0x12, 0x41, 0x79, 0x9b, 0x80, 0x11, 0x12, - 0x10, 0xb9, 0x60, 0xf6, 0x34, 0x64, 0x72, 0xd4, 0x57, 0x9b, 0x87, 0xc3, 0x0a, 0x81, 0xe6, 0xa1, 0x70, 0x3f, 0xcc, - 0x54, 0xca, 0x2e, 0x0e, 0x01, 0x55, 0xba, 0x7f, 0x8d, 0x69, 0x35, 0xff, 0x9b, 0x24, 0xf1, 0x27, 0xab, 0x3f, 0x6c, - 0x55, 0x0d, 0xd1, 0x10, 0x17, 0x46, 0x29, 0x1a, 0x4f, 0x19, 0x0b, 0x3d, 0xa3, 0x67, 0x4e, 0x22, 0x4b, 0x41, 0xff, - 0xec, 0x3c, 0x9c, 0xd7, 0xfa, 0xb4, 0x45, 0x35, 0x70, 0x94, 0x44, 0xb1, 0x65, 0x06, 0x46, 0xbc, 0x00, 0x24, 0x66, - 0x7a, 0x90, 0x15, 0x2d, 0xf8, 0xda, 0x76, 0x65, 0xc5, 0x9c, 0x65, 0x60, 0xf5, 0x43, 0xd4, 0x1f, 0x6e, 0xda, 0x1b, - 0x7a, 0x4b, 0x2b, 0xe3, 0x2d, 0x3d, 0xde, 0xd3, 0x66, 0xd6, 0x2f, 0x6d, 0xa0, 0xe9, 0x52, 0x95, 0x3c, 0x7d, 0x7f, - 0xdf, 0xf7, 0xc5, 0xfd, 0x79, 0x3f, 0x15, 0x57, 0x6c, 0xef, 0xe7, 0x81, 0x4a, 0x4e, 0xfc, 0x73, 0xd4, 0xaf, 0x27, - 0x33, 0xaa, 0x09, 0xd7, 0x6d, 0xdd, 0xb7, 0xc2, 0x23, 0x5f, 0x4f, 0x2c, 0x1c, 0x49, 0x5d, 0xa1, 0xe4, 0x3d, 0x69, - 0xd9, 0xa0, 0x7b, 0x8a, 0x20, 0xdf, 0x57, 0x40, 0x29, 0x05, 0x34, 0x1f, 0x5c, 0x22, 0x44, 0x69, 0x6a, 0x5d, 0xba, - 0xf1, 0x86, 0xca, 0xcd, 0x07, 0x66, 0x39, 0x1b, 0x82, 0x8f, 0x13, 0xf0, 0x8b, 0x79, 0x50, 0x3f, 0xae, 0xc2, 0x34, - 0x33, 0x54, 0xf6, 0x80, 0x6c, 0x82, 0x92, 0x13, 0xa9, 0x47, 0x5f, 0xd4, 0x91, 0x40, 0xa3, 0xa8, 0x57, 0x9e, 0x75, - 0xbf, 0xd0, 0x45, 0xae, 0x34, 0xff, 0xbf, 0x84, 0x92, 0x0d, 0xf5, 0xe7, 0xe3, 0x4b, 0x69, 0xb0, 0x40, 0xdf, 0x2f, - 0xfc, 0xf6, 0xf2, 0xa2, 0xd1, 0xe3, 0xd2, 0x77, 0x37, 0x64, 0xb9, 0xc1, 0x71, 0x6f, 0x9e, 0xcd, 0x4b, 0x29, 0x05, - 0xe1, 0xb9, 0xe9, 0xaf, 0xcc, 0xd6, 0x89, 0x82, 0xb0, 0xd9, 0x5c, 0x70, 0x10, 0xa0, 0x6a, 0xd9, 0x03, 0x4c, 0xb5, - 0x42, 0x76, 0xea, 0x18, 0x84, 0xf2, 0xdb, 0xc4, 0x7b, 0xf9, 0x7e, 0x7e, 0xbd, 0xe3, 0x91, 0xb9, 0x72, 0xc8, 0x13, - 0x55, 0x76, 0x51, 0x74, 0xb7, 0x08, 0x8f, 0x05, 0xc2, 0x9b, 0x3f, 0x4c, 0x63, 0xbe, 0xae, 0x7b, 0x0a, 0x80, 0x19, - 0x00, 0x9f, 0x10, 0x22, 0x28, 0xd8, 0xcc, 0x74, 0x73, 0x3f, 0xdc, 0xab, 0xa4, 0x6a, 0x78, 0x0a, 0x6c, 0x22, 0x28, - 0xb8, 0xce, 0xd4, 0x63, 0x71, 0x06, 0x9b, 0x7e, 0x44, 0x84, 0x50, 0x9a, 0xe5, 0xb8, 0x19, 0x37, 0xc0, 0x3c, 0x17, - 0x6d, 0xcc, 0xf0, 0x34, 0xd6, 0x84, 0x78, 0x9f, 0xd8, 0x64, 0x4a, 0xc7, 0x05, 0xf9, 0xb2, 0x8b, 0x57, 0xee, 0xfc, - 0x18, 0x65, 0xee, 0x89, 0xc1, 0xb7, 0xc8, 0x1d, 0x73, 0x3f, 0xe2, 0x13, 0x56, 0xd9, 0xb4, 0xbe, 0x04, 0x36, 0x6e, - 0x69, 0x5d, 0x98, 0x68, 0xfe, 0x5b, 0x68, 0x49, 0xe4, 0x0b, 0x76, 0x6d, 0x33, 0x1e, 0xa1, 0xbe, 0xf2, 0xc9, 0xe0, - 0x81, 0x37, 0xff, 0xda, 0xa3, 0xfb, 0x8b, 0x09, 0x84, 0x62, 0x78, 0x2f, 0xdb, 0xc9, 0x5a, 0xde, 0xcb, 0x52, 0x81, - 0xeb, 0x55, 0xbc, 0x26, 0x8f, 0xe9, 0x38, 0x8c, 0xc4, 0xe8, 0x68, 0x50, 0x00, 0xf7, 0x4d, 0xd1, 0xdb, 0x88, 0x71, - 0xa2, 0xa0, 0x0a, 0x55, 0xce, 0xf4, 0x32, 0x8e, 0xb2, 0xbc, 0x4a, 0x1a, 0xfc, 0x6d, 0x3f, 0x6f, 0x52, 0x04, 0x04, - 0x1f, 0xe8, 0x80, 0x9b, 0xfd, 0xd9, 0x98, 0xd3, 0x9a, 0xb6, 0xa4, 0x62, 0x8d, 0x07, 0x44, 0x8e, 0xe8, 0xff, 0x38, - 0x64, 0xb9, 0x66, 0xe8, 0x3e, 0x1a, 0x74, 0x43, 0xc8, 0x1b, 0x11, 0x19, 0x19, 0x0c, 0x90, 0xcd, 0x57, 0x9b, 0xb9, - 0x86, 0x81, 0x30, 0x09, 0xeb, 0x16, 0x0f, 0xfd, 0x12, 0x70, 0x94, 0x8f, 0xb9, 0xdb, 0xbe, 0x60, 0x98, 0xc8, 0x2b, - 0xca, 0x2f, 0x29, 0x38, 0x17, 0x9a, 0x99, 0xb7, 0x1c, 0x80, 0x39, 0xcd, 0x14, 0x14, 0xa6, 0x38, 0x18, 0x95, 0x6d, - 0xad, 0x1f, 0xd2, 0xbc, 0x16, 0xa8, 0x52, 0x30, 0x5c, 0x91, 0xb9, 0xa8, 0x92, 0xbb, 0x9a, 0x77, 0x13, 0x11, 0xa1, - 0xe3, 0xd8, 0x31, 0x67, 0x58, 0x67, 0x0a, 0x32, 0x32, 0x4d, 0x91, 0x6f, 0x1f, 0x21, 0x09, 0x97, 0x88, 0x5a, 0x44, - 0xf7, 0xcb, 0xb9, 0x36, 0xbb, 0x35, 0xa6, 0xa9, 0xae, 0x1d, 0xd2, 0x84, 0x4d, 0x0c, 0x6a, 0xfa, 0x12, 0xc5, 0x87, - 0xd2, 0xf8, 0xed, 0x4e, 0xfb, 0x18, 0x46, 0xb2, 0xb1, 0xf4, 0xdc, 0x38, 0x5c, 0x8d, 0x23, 0xea, 0x58, 0x3d, 0x95, - 0xa2, 0xc6, 0x56, 0x65, 0x0a, 0x6d, 0x91, 0x45, 0x08, 0x80, 0xf3, 0x95, 0xb9, 0x9a, 0xdf, 0x0a, 0x1f, 0x34, 0x67, - 0x9a, 0x55, 0x2a, 0x15, 0x9f, 0x68, 0xd1, 0x54, 0x46, 0x62, 0x71, 0x9b, 0xcb, 0x7d, 0x62, 0xfc, 0xae, 0x95, 0x1b, - 0xc0, 0x6f, 0xd1, 0x2d, 0x77, 0xd5, 0x0c, 0xdc, 0x64, 0x6f, 0xf4, 0x9c, 0x55, 0x06, 0x72, 0x17, 0x32, 0x6f, 0xd0, - 0x70, 0x2d, 0xd9, 0x6e, 0xcd, 0xfb, 0xba, 0x2c, 0xf4, 0x65, 0xec, 0xf2, 0xdb, 0x5c, 0x83, 0x56, 0x7f, 0x1a, 0x76, - 0x57, 0x1a, 0x8e, 0xac, 0x04, 0x3d, 0x0d, 0xe6, 0x80, 0x94, 0xd7, 0xba, 0x7f, 0xbb, 0xaa, 0x00, 0xf8, 0x9b, 0xe9, - 0x22, 0xd1, 0x7c, 0x09, 0xdf, 0x40, 0x63, 0xa0, 0x74, 0x1e, 0xd8, 0xca, 0xd7, 0xb3, 0x76, 0x18, 0xf4, 0xbe, 0x9a, - 0x49, 0x0b, 0xaf, 0xcb, 0x9b, 0x10, 0xf6, 0x0a, 0x97, 0x24, 0xd6, 0x78, 0x58, 0xcd, 0x60, 0x61, 0x1e, 0xee, 0xb0, - 0x52, 0x9b, 0xca, 0x9f, 0x10, 0xd5, 0x25, 0xda, 0xf3, 0xba, 0x8b, 0x25, 0x36, 0x2e, 0xec, 0xfb, 0x25, 0xb9, 0xa0, - 0x3a, 0x50, 0xf4, 0x41, 0x32, 0x31, 0xc7, 0x96, 0x1d, 0x08, 0x5e, 0x1e, 0x56, 0x62, 0x40, 0xc1, 0xbe, 0xe5, 0xa8, - 0x4f, 0x54, 0x1c, 0x40, 0x52, 0x8a, 0x91, 0xf4, 0x8a, 0x57, 0xc4, 0xde, 0xb4, 0x0a, 0x28, 0xfb, 0xdd, 0xba, 0xef, - 0xd9, 0x2a, 0x7f, 0x32, 0xd7, 0xfa, 0xa4, 0xdf, 0x23, 0xe9, 0xbd, 0xa2, 0x7e, 0x1c, 0x80, 0x33, 0xdb, 0xac, 0x7d, - 0x02, 0x67, 0x1e, 0x4b, 0xf7, 0xda, 0x70, 0xd1, 0xee, 0xab, 0x02, 0x98, 0x10, 0x4c, 0x87, 0xaa, 0x35, 0xe3, 0x73, - 0xf9, 0xc4, 0x96, 0xed, 0x9e, 0xf4, 0x9d, 0x14, 0x43, 0x6c, 0x90, 0x31, 0x3c, 0x4b, 0xe4, 0x9c, 0x9a, 0xc7, 0xd3, - 0xa7, 0xa7, 0x7a, 0x26, 0xa5, 0xe7, 0xd9, 0x47, 0x47, 0x1c, 0x28, 0x51, 0x23, 0x4b, 0x86, 0xb6, 0x6f, 0xf5, 0xd1, - 0x0b, 0x5e, 0x0b, 0x80, 0x14, 0x4b, 0x20, 0x4d, 0x33, 0x2a, 0xce, 0xf1, 0xc9, 0x07, 0x09, 0x92, 0xc1, 0x5d, 0x49, - 0xe8, 0x93, 0x16, 0x6a, 0x0d, 0x7e, 0x20, 0x2f, 0xca, 0x8d, 0x03, 0x40, 0xed, 0x1e, 0x32, 0x45, 0xb1, 0x9c, 0x37, - 0xb2, 0x13, 0xee, 0x21, 0x1a, 0x87, 0x7a, 0x54, 0x9a, 0xa7, 0x9c, 0x5e, 0x40, 0xb4, 0x5c, 0xe6, 0xc9, 0x8c, 0x3d, - 0x7b, 0xbe, 0x41, 0xc3, 0x29, 0xb4, 0xf1, 0x25, 0x4e, 0x5b, 0xa7, 0xfe, 0x54, 0x43, 0x71, 0x79, 0x36, 0x5f, 0x26, - 0xea, 0x88, 0x3d, 0xa2, 0x0b, 0xcd, 0xe8, 0x82, 0xde, 0x98, 0xcb, 0x9d, 0xfb, 0x59, 0x01, 0x02, 0x1d, 0x95, 0x17, - 0x43, 0x27, 0x31, 0xc6, 0xab, 0xf4, 0x84, 0x3b, 0x5e, 0x28, 0xa5, 0xfa, 0x00, 0x3e, 0x7f, 0x08, 0xc2, 0x5f, 0x89, - 0xf7, 0x8e, 0x5a, 0x7d, 0xe3, 0x16, 0x27, 0x26, 0x3c, 0x28, 0xc0, 0x4c, 0x87, 0x48, 0x8d, 0x24, 0x74, 0x04, 0xda, - 0x47, 0x81, 0x90, 0xac, 0xa4, 0x5b, 0x53, 0x5e, 0x87, 0x75, 0xea, 0x30, 0x07, 0x3f, 0x2e, 0x18, 0xaf, 0xe5, 0x4d, - 0x37, 0xa2, 0xb7, 0xbe, 0x6e, 0x05, 0xd9, 0x79, 0xdc, 0x83, 0xc8, 0xf8, 0x62, 0x67, 0x8c, 0x29, 0xda, 0x29, 0xa6, - 0x25, 0x15, 0xb3, 0x8f, 0x14, 0xa1, 0xbf, 0x5c, 0x17, 0x67, 0xb6, 0xa6, 0x84, 0xda, 0xc1, 0x04, 0x09, 0xa1, 0xa7, - 0x0a, 0x25, 0x58, 0xb2, 0xfa, 0xe0, 0x25, 0x2e, 0xd2, 0xc1, 0xb6, 0x2a, 0x82, 0x27, 0xf5, 0x7c, 0xf8, 0x6b, 0x47, - 0x84, 0x70, 0x9a, 0xa5, 0x48, 0x88, 0xc5, 0xf6, 0xb1, 0x9a, 0x48, 0x2a, 0x18, 0xd3, 0x3c, 0xe5, 0x03, 0xf6, 0xa0, - 0xf6, 0xe1, 0x26, 0xf5, 0x55, 0xdc, 0x8f, 0xae, 0x97, 0xf8, 0x73, 0x5d, 0x38, 0x0f, 0x86, 0x1a, 0x6f, 0xa9, 0x9c, - 0xb9, 0x1e, 0x35, 0x41, 0x63, 0xe0, 0xd2, 0xa8, 0x3f, 0x43, 0xea, 0xa0, 0xca, 0xc2, 0x78, 0x16, 0xbf, 0x04, 0x71, - 0x6e, 0x8d, 0x29, 0xf7, 0x67, 0x48, 0xe2, 0x71, 0x6f, 0xd4, 0x9f, 0x3d, 0xba, 0xcb, 0x74, 0x85, 0x00, 0xbb, 0x56, - 0xcb, 0x76, 0xd5, 0x5e, 0x42, 0x2e, 0x76, 0xe2, 0x76, 0xa6, 0x55, 0x49, 0xc0, 0x68, 0x4e, 0x53, 0xfd, 0x3d, 0x3e, - 0x0d, 0xf1, 0x2b, 0xd8, 0x70, 0x9f, 0x12, 0x54, 0x4b, 0x32, 0x9f, 0xbe, 0x44, 0x39, 0x7d, 0xa8, 0xb5, 0x6b, 0x83, - 0xc8, 0xa5, 0xeb, 0x08, 0x4f, 0x96, 0x0b, 0x39, 0x3b, 0x4e, 0xe8, 0xde, 0xfc, 0x05, 0x71, 0xa6, 0xa8, 0x45, 0x4d, - 0x81, 0x64, 0xa3, 0xc5, 0x77, 0x3a, 0xb7, 0xd0, 0x72, 0xb9, 0x1c, 0x85, 0x67, 0xdd, 0xfb, 0xb4, 0x5f, 0x91, 0x74, - 0xb5, 0x5e, 0x1b, 0xdd, 0x46, 0x77, 0x2d, 0x55, 0x64, 0x41, 0x1d, 0x1f, 0x29, 0xe3, 0xe5, 0xd0, 0x4a, 0x71, 0xf3, - 0xaa, 0x2c, 0x98, 0xe7, 0x94, 0x7a, 0x75, 0xd9, 0xf7, 0xe7, 0xb7, 0x3e, 0x41, 0x98, 0xb0, 0x47, 0xb5, 0x82, 0x5e, - 0x61, 0xbb, 0x95, 0xb7, 0x15, 0xac, 0x36, 0x69, 0x91, 0xb2, 0x33, 0xa0, 0x2d, 0x8e, 0x4f, 0x31, 0xed, 0x14, 0x05, - 0x8f, 0x3a, 0x6d, 0x74, 0x55, 0x08, 0x13, 0x9e, 0x54, 0xfc, 0xb7, 0x03, 0x33, 0x71, 0x84, 0x73, 0x43, 0x6e, 0x6f, - 0x2b, 0xb9, 0x3e, 0x1e, 0x8c, 0x9e, 0x4e, 0x84, 0x84, 0x06, 0x6d, 0x0c, 0x5e, 0xe5, 0xe0, 0xaf, 0xbf, 0x0b, 0xb1, - 0xc2, 0x87, 0x04, 0x2e, 0x87, 0x6e, 0x94, 0xeb, 0x81, 0x71, 0xcd, 0x17, 0xe8, 0x84, 0x5c, 0x3c, 0x70, 0x90, 0xd9, - 0x91, 0x4f, 0xc8, 0xc8, 0x6f, 0xcc, 0x20, 0x70, 0x4e, 0x4e, 0x56, 0x8c, 0x22, 0x84, 0x0e, 0x76, 0x1e, 0x05, 0x3a, - 0x86, 0x24, 0xe1, 0x57, 0xc7, 0x89, 0xa4, 0xb5, 0xce, 0x7b, 0x5a, 0x7f, 0x78, 0x51, 0x40, 0xf2, 0x0e, 0x62, 0xea, - 0xbe, 0x26, 0x61, 0xf2, 0x1a, 0x13, 0xb7, 0x15, 0xa3, 0xff, 0xcc, 0x4d, 0x60, 0xb6, 0xca, 0xc0, 0x06, 0x2b, 0x73, - 0x3c, 0x9d, 0x89, 0xc2, 0xb3, 0x54, 0x81, 0x79, 0x76, 0xe4, 0xac, 0x94, 0x28, 0x10, 0x28, 0x4a, 0x2d, 0x6d, 0x56, - 0xeb, 0x70, 0x45, 0x39, 0x76, 0x9f, 0x65, 0x0b, 0x95, 0x80, 0x54, 0x47, 0x93, 0x69, 0x6d, 0xf0, 0x81, 0xbb, 0xb3, - 0x5b, 0xc9, 0x28, 0x58, 0x2e, 0xfc, 0x5b, 0xa1, 0x77, 0xa8, 0xa6, 0x22, 0xa6, 0x48, 0xeb, 0xd6, 0x2a, 0x25, 0x45, - 0xd2, 0x00, 0xad, 0xb3, 0x2c, 0x28, 0x82, 0x90, 0x1e, 0xf1, 0x55, 0xb3, 0x80, 0x07, 0xb3, 0xda, 0x22, 0x9b, 0x15, - 0xdc, 0x13, 0xc1, 0xd9, 0x9a, 0x42, 0x89, 0x59, 0xcb, 0x6c, 0xdf, 0x9e, 0x6e, 0xd2, 0xd6, 0x6d, 0x45, 0xcb, 0xa0, - 0x09, 0x7d, 0x4a, 0xd3, 0xe4, 0xdf, 0xb5, 0xd9, 0xc2, 0xe1, 0x03, 0x63, 0x0e, 0x2f, 0x5d, 0x33, 0x0f, 0x00, 0x95, - 0x5a, 0xf4, 0xeb, 0x44, 0x9f, 0x7e, 0xa5, 0x91, 0x1b, 0x52, 0x80, 0x1e, 0x94, 0x82, 0x6c, 0xe4, 0x6b, 0xea, 0xc0, - 0x9d, 0x12, 0x6d, 0x02, 0xcb, 0xad, 0x88, 0x65, 0xc1, 0xea, 0xae, 0xf8, 0xfb, 0x0b, 0xd0, 0xa0, 0x2f, 0x6f, 0x18, - 0xd0, 0x4f, 0xd4, 0xde, 0x1f, 0xea, 0x50, 0x29, 0xc9, 0xed, 0xe9, 0xd2, 0xed, 0x88, 0x02, 0x6a, 0xad, 0x5e, 0x15, - 0x15, 0x9c, 0x67, 0xca, 0x00, 0xd2, 0x0e, 0x69, 0xb0, 0x61, 0x30, 0xea, 0x23, 0xf0, 0xc1, 0x7a, 0x1d, 0xc7, 0x6d, - 0x7b, 0x29, 0xba, 0x97, 0xb3, 0x3b, 0x36, 0x6a, 0x90, 0x09, 0x56, 0x4e, 0x8c, 0x61, 0x74, 0x9f, 0x77, 0xbd, 0xa7, - 0x8e, 0x89, 0x97, 0x4d, 0xaa, 0xa7, 0x98, 0x00, 0x2c, 0x98, 0x29, 0xd8, 0xa6, 0x92, 0x5a, 0x99, 0x10, 0xb4, 0x2d, - 0xe7, 0xca, 0x9a, 0x33, 0x45, 0x39, 0x7b, 0x73, 0xc8, 0xcb, 0x73, 0x73, 0x69, 0x1d, 0x45, 0x14, 0x35, 0x42, 0xda, - 0x2e, 0x8a, 0x97, 0x62, 0xc5, 0xc5, 0x47, 0x02, 0xf7, 0x46, 0xa8, 0x4c, 0x39, 0xee, 0xb8, 0x2a, 0x53, 0xfa, 0xe0, - 0x16, 0xbf, 0x67, 0x4c, 0x22, 0x9e, 0xc0, 0xe4, 0x33, 0x66, 0xc1, 0xf9, 0x42, 0x3f, 0xe2, 0x5d, 0x22, 0xbf, 0xf0, - 0xba, 0x68, 0x2b, 0xfb, 0x4c, 0x8b, 0xa0, 0xd5, 0x7b, 0x38, 0xdd, 0x9a, 0xac, 0xb9, 0x3a, 0x23, 0x47, 0x80, 0xef, - 0x58, 0xb2, 0x47, 0x32, 0x76, 0xe0, 0xb3, 0x58, 0xf4, 0xe0, 0x18, 0x12, 0x9e, 0x31, 0x82, 0xdb, 0x63, 0x9e, 0xcd, - 0xb8, 0x1c, 0x9f, 0xb5, 0x2e, 0x9e, 0xf3, 0xda, 0xeb, 0x5a, 0x91, 0x9e, 0x92, 0xd9, 0x3c, 0xe2, 0x4d, 0x43, 0xd2, - 0x79, 0xff, 0xb9, 0x47, 0x38, 0xe7, 0x1a, 0x58, 0xc5, 0x9d, 0x70, 0x5d, 0xaa, 0xd0, 0xe7, 0xe7, 0x7b, 0xe8, 0xb3, - 0x51, 0xd2, 0x5d, 0x5c, 0xa7, 0x3c, 0x9a, 0x7e, 0xb6, 0x24, 0x1e, 0xf6, 0x38, 0x1e, 0x5f, 0xd2, 0xdf, 0xd6, 0x36, - 0x40, 0xd9, 0x6a, 0x1b, 0x23, 0xd4, 0xa6, 0x39, 0x05, 0x7e, 0xbf, 0xcf, 0x71, 0x74, 0x34, 0x9e, 0xda, 0x35, 0xf0, - 0xe9, 0x7d, 0x01, 0xba, 0xaa, 0xb4, 0x7a, 0xe7, 0xe9, 0x1d, 0x2e, 0xcc, 0x06, 0xb9, 0xd7, 0x88, 0x2c, 0x83, 0xb9, - 0x5c, 0x70, 0xb2, 0xab, 0x7e, 0x48, 0xa5, 0xb4, 0x9f, 0xf9, 0xef, 0x07, 0x5d, 0x4e, 0xf7, 0xc9, 0x61, 0x1b, 0xc8, - 0x95, 0x38, 0x33, 0x2a, 0xac, 0xbe, 0x69, 0x69, 0x49, 0x3f, 0xe3, 0x32, 0x0c, 0x04, 0x44, 0xf9, 0xbf, 0x78, 0x38, - 0x48, 0xc8, 0x5b, 0x27, 0x24, 0x45, 0xd5, 0x9a, 0xd5, 0x24, 0x2f, 0xf6, 0x23, 0xa4, 0xe0, 0x50, 0x24, 0x4b, 0x5f, - 0xb4, 0x3f, 0x97, 0x88, 0x42, 0x06, 0x81, 0x51, 0x06, 0x49, 0x10, 0xad, 0xa3, 0x5b, 0x3d, 0xed, 0x24, 0xbd, 0x3c, - 0x40, 0x5f, 0xe9, 0xf9, 0xfb, 0x11, 0x0e, 0x41, 0x59, 0x73, 0xfd, 0xdc, 0x8a, 0x6c, 0xe7, 0xcf, 0x5d, 0x55, 0x58, - 0x07, 0x44, 0x2c, 0x66, 0x39, 0x5a, 0xcc, 0x8b, 0xa2, 0x64, 0xef, 0xba, 0x03, 0xf8, 0x15, 0xde, 0x99, 0x73, 0x55, - 0x5c, 0xc8, 0x31, 0x7d, 0x25, 0xae, 0xe8, 0x1c, 0x1e, 0xd1, 0x4a, 0xda, 0x96, 0xc8, 0xfe, 0x72, 0x68, 0x97, 0x9c, - 0x50, 0xa1, 0x15, 0x6e, 0x69, 0x36, 0xa7, 0xe7, 0x00, 0xc2, 0x8a, 0x2f, 0x08, 0xa5, 0xdc, 0xf3, 0x4a, 0xa7, 0x0e, - 0x86, 0xce, 0xdc, 0xa4, 0x08, 0x7d, 0x37, 0x66, 0x4e, 0x25, 0xf9, 0xd1, 0x8f, 0xed, 0xa2, 0x0a, 0xfb, 0x9f, 0xc3, - 0x95, 0x12, 0xc9, 0x7d, 0xef, 0x56, 0xb7, 0x24, 0xda, 0xf4, 0xb2, 0x22, 0x99, 0x63, 0x1d, 0xed, 0x73, 0x5a, 0x16, - 0xef, 0xae, 0x04, 0x23, 0x98, 0x3d, 0x30, 0x23, 0x9c, 0x8b, 0x41, 0x31, 0x6e, 0x99, 0x0a, 0x0b, 0xe6, 0x21, 0x72, - 0xbb, 0xeb, 0xa2, 0xca, 0x9d, 0x4c, 0x6e, 0xce, 0xf3, 0xf0, 0xb2, 0xb0, 0x62, 0xa1, 0x14, 0xbb, 0x38, 0xb7, 0x7e, - 0xe3, 0xde, 0xb7, 0xd4, 0x85, 0x25, 0xff, 0x1a, 0x4f, 0x23, 0x3c, 0x3d, 0xc2, 0xa8, 0xfc, 0x00, 0xbb, 0xb1, 0x13, - 0x7d, 0x25, 0x06, 0xe8, 0xf1, 0x9e, 0x1c, 0xbf, 0x5c, 0xde, 0x8b, 0x8e, 0x33, 0x9c, 0x30, 0xd2, 0xb8, 0xcd, 0x17, - 0xc4, 0xe9, 0x30, 0x37, 0x69, 0xc6, 0x8a, 0x7a, 0x24, 0x82, 0xf1, 0xd2, 0xfa, 0xb7, 0x2d, 0x4f, 0xf3, 0xf7, 0xf9, - 0x33, 0xc9, 0x17, 0xd3, 0x15, 0xf0, 0xf5, 0xe0, 0xcf, 0xd3, 0xfe, 0x40, 0x22, 0x10, 0x3d, 0x84, 0x23, 0x3d, 0xa6, - 0x65, 0x69, 0xf7, 0xec, 0xd8, 0x22, 0xf4, 0xfa, 0xb3, 0x44, 0x50, 0xea, 0x85, 0x52, 0xea, 0x0d, 0xca, 0x38, 0x25, - 0x81, 0x4d, 0x97, 0x42, 0x88, 0xf2, 0xfd, 0xdf, 0x38, 0x79, 0x8a, 0xf0, 0xb3, 0xe6, 0x94, 0xf6, 0x2a, 0x6a, 0x0a, - 0xea, 0x8c, 0x02, 0x60, 0x25, 0xee, 0xe3, 0x01, 0xb4, 0x6c, 0xa8, 0x0b, 0xae, 0x30, 0xa8, 0x5a, 0x95, 0x93, 0x40, - 0x9d, 0x6c, 0x14, 0x11, 0xb9, 0x29, 0xbe, 0x8b, 0x88, 0xc8, 0x1a, 0x06, 0xe5, 0x1c, 0x6c, 0x99, 0xce, 0x25, 0xc3, - 0xee, 0x36, 0xb5, 0xbc, 0xf0, 0x5e, 0x4d, 0x7a, 0xcc, 0xca, 0x76, 0xb8, 0x8f, 0x1c, 0x1d, 0x67, 0xb7, 0x7c, 0x91, - 0x38, 0x4c, 0xe2, 0x5a, 0xbd, 0xb7, 0x87, 0xac, 0xdd, 0x21, 0xe9, 0xaf, 0x05, 0x37, 0xdd, 0x21, 0xb3, 0x50, 0xda, - 0xbe, 0x3e, 0xfb, 0xa9, 0xba, 0xc3, 0xc0, 0x1b, 0x00, 0x4f, 0x31, 0xee, 0xfe, 0x6a, 0x6e, 0x43, 0xf5, 0xf8, 0x67, - 0x0f, 0x5d, 0x91, 0x48, 0x0b, 0xcc, 0x62, 0x0f, 0x87, 0x75, 0xd9, 0x4a, 0xdd, 0xb5, 0x71, 0x6e, 0x03, 0xe2, 0x8c, - 0x94, 0x90, 0x54, 0x0e, 0xd9, 0x28, 0x59, 0x1e, 0x51, 0x06, 0x6b, 0xbd, 0xbd, 0x74, 0x17, 0x73, 0x0f, 0xc3, 0x05, - 0x80, 0x92, 0x80, 0x65, 0x7b, 0xac, 0xb5, 0xfb, 0x00, 0x30, 0x42, 0xab, 0xc6, 0xcc, 0xe8, 0x55, 0xdc, 0x2a, 0xeb, - 0xc5, 0x8a, 0xcc, 0xa8, 0x1f, 0x6a, 0x22, 0x77, 0x07, 0x52, 0xd1, 0x56, 0xa8, 0x2c, 0xbf, 0x94, 0x4a, 0x4f, 0xab, - 0x02, 0xad, 0xd4, 0xd5, 0x8a, 0x0e, 0xba, 0x91, 0x92, 0xa2, 0x44, 0xdb, 0xb9, 0x00, 0xb9, 0xf2, 0x66, 0x18, 0x78, - 0x13, 0xd8, 0x2a, 0x32, 0x22, 0x81, 0x6b, 0xe1, 0xa9, 0x88, 0x24, 0x2f, 0xea, 0xae, 0x55, 0x35, 0x29, 0x8d, 0xb3, - 0x06, 0x9e, 0x6e, 0x29, 0xf2, 0x0b, 0x8d, 0x30, 0x2d, 0xf5, 0x41, 0x06, 0x89, 0xb4, 0x48, 0xe4, 0x7c, 0x5e, 0xbb, - 0x1f, 0xa2, 0x8e, 0x53, 0x74, 0x3c, 0x24, 0xdb, 0x6e, 0xbb, 0x14, 0x25, 0x87, 0x89, 0xee, 0x24, 0x16, 0xd3, 0x11, - 0x03, 0x95, 0xb2, 0x21, 0xc7, 0xd2, 0x6b, 0xd7, 0x8a, 0x13, 0xb8, 0xf8, 0x0f, 0xf9, 0xd8, 0xe6, 0xd9, 0x86, 0x61, - 0x0b, 0x2d, 0xcb, 0x11, 0xfd, 0xe5, 0xa5, 0x84, 0x0e, 0xd2, 0x12, 0x3d, 0xe4, 0x07, 0xc5, 0xb2, 0xab, 0x90, 0x35, - 0xe8, 0xa0, 0x71, 0xee, 0x4c, 0x66, 0x0b, 0x89, 0x94, 0x69, 0x52, 0x6b, 0x5a, 0x6c, 0x42, 0xc4, 0x33, 0x3f, 0x58, - 0x15, 0xa2, 0x46, 0x3c, 0xc8, 0x54, 0x58, 0x0a, 0xce, 0x16, 0x41, 0xe2, 0x4b, 0x9c, 0x1d, 0xce, 0x8b, 0xdd, 0x60, - 0x91, 0x45, 0xef, 0x30, 0xea, 0xcb, 0x61, 0x5f, 0xb7, 0x22, 0x36, 0xbd, 0x35, 0x2e, 0x3c, 0xaf, 0x99, 0xb5, 0x6a, - 0x47, 0x8c, 0x39, 0x43, 0x18, 0x29, 0x04, 0xf9, 0xe8, 0xd3, 0x11, 0xce, 0x8a, 0x53, 0x81, 0x0d, 0x1b, 0xd7, 0xb1, - 0xc3, 0xd9, 0x87, 0xba, 0x8b, 0xa0, 0xe1, 0xb9, 0x3a, 0x22, 0x48, 0xcc, 0x78, 0x83, 0x51, 0x2b, 0x34, 0xdf, 0xe8, - 0x3a, 0x6f, 0xcd, 0x74, 0xf3, 0x8d, 0xa4, 0x47, 0x69, 0xe1, 0x91, 0xdf, 0x62, 0x52, 0x71, 0xe6, 0xd6, 0x7e, 0x90, - 0x25, 0xd6, 0xfd, 0x0f, 0x41, 0xfc, 0x8a, 0x80, 0xea, 0x24, 0x21, 0x20, 0x40, 0x43, 0xeb, 0x7a, 0xa1, 0xd9, 0x56, - 0x58, 0x09, 0x0a, 0xcf, 0x55, 0xf0, 0x5f, 0x92, 0xa2, 0x61, 0xd2, 0x84, 0x26, 0x1e, 0x95, 0xfb, 0xb1, 0x83, 0x05, - 0xe2, 0x2c, 0x20, 0x8a, 0xc1, 0x49, 0x50, 0x09, 0x09, 0xb7, 0x54, 0x42, 0x7b, 0xa1, 0x15, 0x13, 0x2c, 0x80, 0x69, - 0x4f, 0x5c, 0x4a, 0x81, 0x62, 0xda, 0x8a, 0xa3, 0x39, 0x56, 0x43, 0x80, 0x61, 0x90, 0x51, 0x7f, 0x04, 0x5d, 0xac, - 0x61, 0x9a, 0x8c, 0xf7, 0xbb, 0x78, 0xe1, 0xe9, 0xe6, 0x74, 0x85, 0x52, 0x16, 0xf9, 0x2c, 0xc0, 0x09, 0xcd, 0xf8, - 0xa4, 0x00, 0xf5, 0x45, 0xbd, 0xb4, 0xf1, 0xdc, 0x3a, 0x9e, 0x83, 0x27, 0xe7, 0x8d, 0xe0, 0x6d, 0x1c, 0x54, 0xee, - 0x60, 0x0f, 0x60, 0x91, 0xd7, 0x5c, 0x33, 0x92, 0xcc, 0x18, 0x1e, 0x0d, 0xf3, 0x8c, 0xb9, 0x53, 0x42, 0xdb, 0x33, - 0xb9, 0x09, 0x5c, 0x9b, 0x06, 0xab, 0x86, 0xa5, 0x1f, 0xaf, 0xae, 0xd7, 0x5c, 0x1f, 0x40, 0xee, 0xdb, 0x96, 0x12, - 0x76, 0x37, 0x22, 0x8d, 0x31, 0x60, 0x9b, 0x50, 0xbd, 0x3f, 0x21, 0x9b, 0xa6, 0x5a, 0xd6, 0xc1, 0x61, 0xce, 0x2f, - 0x12, 0x54, 0xee, 0x41, 0xdb, 0x54, 0x16, 0xa1, 0xd7, 0x3c, 0xee, 0x89, 0x3e, 0x4f, 0xb8, 0x21, 0x58, 0x83, 0xd4, - 0x89, 0x8b, 0xab, 0xf2, 0x24, 0x41, 0x37, 0x5a, 0x6a, 0x2b, 0x96, 0x07, 0x03, 0x2e, 0xca, 0xb1, 0x1b, 0x92, 0x52, - 0xc1, 0x51, 0x92, 0xf4, 0x34, 0x96, 0x6a, 0x97, 0xdb, 0x6f, 0x33, 0x2e, 0xf5, 0x8e, 0x12, 0x9a, 0xd0, 0x69, 0x21, - 0x23, 0x0d, 0x84, 0x02, 0xb5, 0xb9, 0xbf, 0x4c, 0xdf, 0x8c, 0x3e, 0xc3, 0xb0, 0x91, 0x8b, 0xe1, 0x01, 0x94, 0xb3, - 0xda, 0x71, 0x38, 0xc7, 0xc3, 0xb2, 0x90, 0x5e, 0x30, 0x99, 0x21, 0xb2, 0x44, 0x2e, 0x7f, 0xd4, 0xa4, 0xe4, 0x02, - 0x1d, 0x4b, 0x6b, 0x1e, 0xd0, 0xae, 0x4e, 0x70, 0xa0, 0x3b, 0x7c, 0xd5, 0xc9, 0x57, 0x75, 0x14, 0xc9, 0x1c, 0x43, - 0xe7, 0xc0, 0xe2, 0x54, 0xcb, 0xb3, 0x91, 0x9d, 0xee, 0x0e, 0x70, 0x5e, 0x4a, 0xb7, 0x0b, 0x70, 0xd7, 0xfe, 0xc5, - 0x89, 0x8b, 0xe7, 0xb6, 0xd5, 0x60, 0x8b, 0xce, 0x74, 0x08, 0xe7, 0xcf, 0xd4, 0xcd, 0x09, 0x6f, 0xa1, 0xcb, 0xa9, - 0xfd, 0xb9, 0xe0, 0xfa, 0xe3, 0x15, 0xdd, 0x6e, 0xeb, 0x82, 0xc3, 0x72, 0x94, 0xb3, 0x2e, 0x89, 0x54, 0xb2, 0xd2, - 0x1b, 0x7d, 0x3e, 0x90, 0xa7, 0x0d, 0xb6, 0x5f, 0x28, 0x98, 0x39, 0x75, 0x50, 0xac, 0x62, 0x92, 0xd9, 0xe1, 0xc1, - 0xe4, 0xbb, 0xb2, 0x58, 0x32, 0x56, 0x27, 0xb3, 0xdc, 0x81, 0x71, 0x4b, 0x6b, 0xef, 0x57, 0x76, 0x29, 0xe3, 0xcb, - 0x88, 0x72, 0x2b, 0xaf, 0x8d, 0x83, 0x4c, 0xdb, 0x25, 0xb2, 0xdc, 0xd6, 0xb7, 0xcb, 0x34, 0x7b, 0x48, 0xd2, 0xed, - 0x04, 0xc9, 0x77, 0x06, 0x9f, 0x18, 0x52, 0xa2, 0x17, 0x52, 0xeb, 0xf1, 0xb5, 0x77, 0x95, 0x38, 0x45, 0xbc, 0x2a, - 0x06, 0x61, 0x65, 0x7d, 0x8e, 0x2d, 0x69, 0x16, 0xa8, 0x63, 0x15, 0x49, 0xdc, 0x2a, 0x24, 0x7e, 0x69, 0xf5, 0x17, - 0xb6, 0xdc, 0xa8, 0xfc, 0x14, 0x89, 0x77, 0x88, 0xfe, 0x72, 0x5c, 0xa2, 0x7b, 0xad, 0x0a, 0x44, 0x19, 0xe6, 0xa9, - 0x9c, 0xb1, 0x60, 0xe9, 0xe6, 0x89, 0x2c, 0x9a, 0x3d, 0x5f, 0x6e, 0xa0, 0x49, 0x94, 0x88, 0xcd, 0x85, 0x5e, 0xe6, - 0xce, 0x19, 0xe8, 0xe8, 0x24, 0xac, 0x53, 0xab, 0xc9, 0xc4, 0x1e, 0x83, 0xb3, 0x97, 0xac, 0xe8, 0x09, 0xae, 0x7b, - 0xce, 0x3b, 0xfb, 0xaf, 0xb9, 0x70, 0x3a, 0x34, 0xfb, 0xe9, 0xfc, 0x98, 0x61, 0x96, 0x8e, 0x14, 0xb8, 0x25, 0x76, - 0xab, 0x3b, 0x11, 0x65, 0x4c, 0xfb, 0xc4, 0x58, 0x5d, 0xdf, 0x76, 0x8a, 0x8e, 0xc9, 0xbf, 0x99, 0xa7, 0xe1, 0xdc, - 0x39, 0x51, 0x62, 0x37, 0x39, 0x61, 0xb7, 0xd6, 0xdd, 0xf3, 0xe0, 0x67, 0x84, 0x18, 0xa5, 0x14, 0x6c, 0x82, 0x7a, - 0xab, 0xaa, 0x02, 0xe6, 0x69, 0x58, 0x34, 0x63, 0x4f, 0x14, 0x91, 0x5d, 0x7f, 0x27, 0x66, 0x8e, 0x29, 0x8b, 0x2e, - 0x59, 0x93, 0xc1, 0x54, 0x4d, 0xa9, 0x3b, 0x92, 0x1a, 0xb9, 0x83, 0x84, 0xec, 0x6f, 0x8d, 0x14, 0x81, 0x7a, 0xa3, - 0x71, 0x71, 0x6f, 0x0d, 0x8c, 0x69, 0xa0, 0xd9, 0xd6, 0x2c, 0x1d, 0xa8, 0x03, 0x37, 0xda, 0xd6, 0x85, 0x4a, 0xd5, - 0x76, 0xe1, 0xeb, 0x57, 0xfb, 0xbc, 0xcf, 0xac, 0x05, 0x6d, 0x18, 0xfa, 0x19, 0xd8, 0x26, 0xc5, 0xfd, 0x17, 0x22, - 0x4d, 0x15, 0xa5, 0xd8, 0x77, 0x20, 0x9b, 0x75, 0x6f, 0xad, 0x82, 0x90, 0x93, 0xaa, 0xf4, 0x7d, 0x9a, 0xf5, 0xa4, - 0xd3, 0x95, 0x65, 0x65, 0xb6, 0x8d, 0xdf, 0xee, 0x86, 0xed, 0x83, 0x85, 0xcd, 0x2b, 0x95, 0x4e, 0xa4, 0x83, 0x08, - 0x0c, 0x83, 0xe7, 0xd0, 0x97, 0x7e, 0xa0, 0xf2, 0x7b, 0xa0, 0xfa, 0xac, 0x8c, 0x1d, 0xae, 0xbd, 0xd0, 0x78, 0x01, - 0x5d, 0x90, 0x70, 0x3f, 0x4d, 0x2a, 0xa7, 0x61, 0x52, 0x83, 0x8e, 0xb6, 0xba, 0x4e, 0x2c, 0x0f, 0x44, 0x80, 0x7f, - 0x28, 0x50, 0x8d, 0x99, 0x01, 0x76, 0x3d, 0x09, 0x6c, 0xab, 0x59, 0xd6, 0x43, 0x2f, 0x38, 0x9c, 0xae, 0xa0, 0xbb, - 0x97, 0x5f, 0x31, 0x0e, 0x72, 0x87, 0x5d, 0x29, 0xb0, 0x3e, 0x39, 0x72, 0x2c, 0x50, 0x3b, 0x47, 0x0d, 0x0c, 0xbb, - 0x45, 0x6d, 0xb8, 0xef, 0x53, 0x6a, 0x76, 0x43, 0xb8, 0x1b, 0x1c, 0xb8, 0xa5, 0x62, 0xdb, 0xf2, 0xa8, 0xd2, 0xfc, - 0x65, 0x3b, 0x50, 0x46, 0xeb, 0x8d, 0x51, 0xef, 0xed, 0xee, 0x43, 0x49, 0x4a, 0xdb, 0xcf, 0x97, 0xf9, 0x24, 0xd9, - 0x7b, 0x65, 0x96, 0xba, 0x7a, 0x3f, 0x35, 0xb9, 0x5d, 0xad, 0xa9, 0xd2, 0x99, 0x0a, 0x0e, 0x85, 0x72, 0x9e, 0x5d, - 0xb9, 0x93, 0x12, 0x2b, 0x6c, 0xee, 0xa5, 0x1b, 0x41, 0x7a, 0xec, 0x24, 0x53, 0x62, 0x42, 0x48, 0x9d, 0xfd, 0x76, - 0x67, 0xee, 0x0f, 0x57, 0xdf, 0x92, 0xa2, 0xbe, 0xe3, 0xa6, 0xe5, 0x78, 0xe9, 0xb7, 0xcb, 0x8d, 0x32, 0x98, 0x46, - 0xd1, 0x60, 0x69, 0x19, 0x1c, 0x74, 0xd7, 0x32, 0xc0, 0xb9, 0x4b, 0xfc, 0x5d, 0x3f, 0xae, 0x68, 0xda, 0x00, 0x5d, - 0x16, 0xfb, 0x84, 0x72, 0x49, 0x1c, 0x94, 0xf0, 0x48, 0xd3, 0x26, 0x4d, 0x88, 0x14, 0x39, 0xd8, 0xb6, 0x90, 0x81, - 0x21, 0x59, 0x88, 0x62, 0x50, 0xf9, 0x55, 0xae, 0x4e, 0x78, 0x9d, 0xcf, 0x16, 0xbc, 0x84, 0x28, 0x5c, 0x95, 0x71, - 0x75, 0xa3, 0x66, 0x31, 0xaf, 0x0e, 0x3b, 0xa9, 0xa6, 0x0d, 0x0d, 0x63, 0xd4, 0x11, 0xb9, 0xdb, 0xf8, 0xe0, 0x9d, - 0x2d, 0xd4, 0x0c, 0x16, 0xdf, 0xa9, 0x09, 0xf8, 0x6b, 0x7d, 0xf1, 0x16, 0x42, 0x0e, 0x71, 0x9e, 0x56, 0x68, 0x78, - 0xa1, 0xac, 0xd1, 0xb8, 0x17, 0xb2, 0x1a, 0xfb, 0xb9, 0xcb, 0x20, 0x6d, 0x38, 0x19, 0x94, 0x8e, 0xc3, 0xa5, 0x7c, - 0x97, 0xd4, 0x2d, 0xbd, 0x41, 0x89, 0xb8, 0x0e, 0x60, 0x27, 0x6a, 0xa9, 0x74, 0x51, 0x49, 0xeb, 0xa7, 0x86, 0xf2, - 0x64, 0xd8, 0x4b, 0xe7, 0x64, 0x60, 0xcc, 0xe8, 0x3c, 0xd4, 0x8c, 0x41, 0xb4, 0x86, 0x65, 0xd8, 0xa0, 0x7d, 0xac, - 0x5e, 0x20, 0xfb, 0x44, 0xd3, 0xaa, 0x33, 0x74, 0xd8, 0xc9, 0x84, 0x5f, 0xaa, 0x53, 0x31, 0x65, 0xfe, 0x95, 0x99, - 0xb6, 0xcd, 0xfb, 0x6e, 0x34, 0x94, 0x37, 0x97, 0x7e, 0xcc, 0xf9, 0x15, 0x97, 0x02, 0x97, 0x0b, 0x68, 0x0d, 0xf7, - 0x90, 0x7f, 0xc3, 0xbc, 0xec, 0xd7, 0x76, 0x60, 0x02, 0x11, 0xa7, 0x1a, 0x8d, 0x73, 0x4a, 0x8e, 0xa6, 0x3a, 0xe7, - 0x7d, 0x13, 0xce, 0x28, 0x95, 0x06, 0x64, 0xd4, 0xb2, 0x48, 0x26, 0xc1, 0x4c, 0x07, 0xcd, 0x0b, 0x67, 0x1b, 0xed, - 0xa4, 0xd1, 0xc1, 0xeb, 0x4d, 0xdc, 0x75, 0x41, 0x93, 0x5e, 0x11, 0x3f, 0x76, 0xd4, 0x56, 0x8c, 0x53, 0x17, 0x2e, - 0x02, 0xcf, 0xe4, 0x2c, 0x8b, 0x43, 0x99, 0xf4, 0x7a, 0x45, 0xd5, 0xb2, 0xa4, 0xb3, 0x54, 0x0f, 0xe8, 0x12, 0xd4, - 0xe3, 0xd3, 0xa2, 0xbc, 0x62, 0x35, 0x98, 0xef, 0x40, 0xd9, 0x6b, 0x97, 0xd0, 0xf3, 0x7d, 0xa1, 0x0e, 0x32, 0x1a, - 0xbb, 0xf3, 0xf9, 0x92, 0x1a, 0x93, 0x03, 0xe7, 0x4d, 0xf3, 0x0a, 0x67, 0xd7, 0x5b, 0x52, 0x0b, 0xa1, 0x4f, 0xda, - 0xa0, 0x67, 0x89, 0x84, 0xbf, 0x83, 0x3a, 0x9c, 0xdd, 0x20, 0xa9, 0x33, 0x6c, 0xca, 0xe9, 0xa7, 0xa0, 0x35, 0xe1, - 0x62, 0x23, 0x0b, 0xdb, 0x87, 0x1e, 0x54, 0x9b, 0x47, 0x76, 0x71, 0xb8, 0xa3, 0x98, 0x36, 0x83, 0xb0, 0x96, 0xe0, - 0xa1, 0x34, 0xf4, 0x16, 0x9b, 0xfe, 0x7c, 0x23, 0xc3, 0xe5, 0x26, 0xc9, 0xc2, 0x95, 0xe9, 0xd1, 0x10, 0x60, 0xd7, - 0xee, 0xf7, 0xb6, 0x3a, 0x05, 0x7f, 0x09, 0x0f, 0x46, 0x31, 0x7d, 0x3e, 0x7b, 0x65, 0x80, 0xfd, 0x44, 0x4f, 0xa7, - 0xfb, 0xa6, 0x50, 0x3a, 0x87, 0x5c, 0x62, 0x5d, 0x18, 0x63, 0x8c, 0xa3, 0x7a, 0xb7, 0xa3, 0x8c, 0xbd, 0xe4, 0xd8, - 0x01, 0x0f, 0x85, 0x0f, 0x77, 0x94, 0xf2, 0xaa, 0x1d, 0x6b, 0x37, 0xb9, 0xe6, 0x1b, 0xf9, 0x88, 0x1c, 0xbd, 0xa4, - 0x18, 0xa4, 0x65, 0x23, 0xa0, 0x19, 0x83, 0x97, 0x48, 0x0b, 0xd2, 0x36, 0xf4, 0xb3, 0xcc, 0x75, 0x42, 0xa1, 0x05, - 0x9c, 0x9e, 0x31, 0xa8, 0x28, 0x2c, 0x3a, 0xaa, 0xa4, 0xfd, 0x87, 0x03, 0x42, 0x06, 0xa3, 0xd5, 0xda, 0x6c, 0xcb, - 0xf6, 0xa6, 0xc9, 0x1f, 0x6c, 0x3f, 0xd1, 0x9b, 0xe9, 0x43, 0x7e, 0x7a, 0x1c, 0x03, 0x5f, 0x35, 0xb7, 0x6b, 0x3c, - 0xaf, 0xf7, 0x5e, 0x55, 0x93, 0x6f, 0xfd, 0x55, 0x8e, 0x8f, 0xa1, 0x86, 0x64, 0xe9, 0x44, 0xe9, 0xf2, 0xb0, 0xf7, - 0xb3, 0x3e, 0xb1, 0x4f, 0x16, 0x26, 0xd3, 0x3b, 0x93, 0xd8, 0x8c, 0xd7, 0x9d, 0x6f, 0x30, 0xae, 0x8c, 0x78, 0x65, - 0xfd, 0x56, 0x9f, 0xc9, 0xc1, 0xf6, 0x12, 0x30, 0x52, 0xaf, 0x2c, 0x05, 0x0e, 0x0a, 0x3a, 0x71, 0x08, 0x1e, 0x22, - 0xcf, 0x71, 0xe6, 0x86, 0x2f, 0x6a, 0x5d, 0x93, 0x88, 0xc8, 0x97, 0xf5, 0x2c, 0x4f, 0x21, 0x73, 0x24, 0x6c, 0xb9, - 0x9e, 0x3e, 0x06, 0x4e, 0x95, 0xb6, 0xec, 0x2f, 0x9b, 0xad, 0xe6, 0xfa, 0x10, 0xfc, 0x23, 0xd2, 0x5d, 0xfc, 0x1a, - 0xc7, 0x23, 0x8d, 0x64, 0x21, 0x55, 0xb5, 0x90, 0x5b, 0x16, 0x0d, 0x16, 0x32, 0x8c, 0x2f, 0x2b, 0x53, 0xd9, 0x8b, - 0x3b, 0x50, 0x22, 0x5f, 0xdf, 0xc2, 0x19, 0x0e, 0x87, 0xd0, 0xf9, 0xeb, 0x9b, 0x2a, 0x43, 0x56, 0x3f, 0xef, 0xd9, - 0x88, 0x63, 0xac, 0x8f, 0xad, 0xb7, 0x37, 0xbd, 0x5b, 0x81, 0xc8, 0x19, 0x27, 0xdb, 0xa7, 0x5f, 0x71, 0xbf, 0x56, - 0xf8, 0x7a, 0xd8, 0x54, 0xf8, 0xf5, 0xd6, 0xc5, 0x81, 0xac, 0x20, 0xe3, 0x09, 0x0b, 0x46, 0x20, 0xc5, 0x63, 0x83, - 0x0e, 0x1a, 0xa7, 0x0c, 0xa8, 0x37, 0xb0, 0xaf, 0x9b, 0x3a, 0xf2, 0xf5, 0x65, 0xf6, 0xb7, 0xe9, 0xb2, 0x1f, 0x40, - 0x96, 0x7d, 0xfe, 0x01, 0x1b, 0xb6, 0xa5, 0xbb, 0x01, 0xb3, 0x37, 0x90, 0x19, 0x99, 0xf6, 0x4b, 0xa4, 0x8f, 0x30, - 0x68, 0x9b, 0xcb, 0x00, 0xae, 0x4d, 0xfa, 0xf3, 0xf9, 0x18, 0x42, 0x0c, 0x21, 0x2c, 0xe3, 0x9d, 0x1b, 0xef, 0x46, - 0xfa, 0xa6, 0xd1, 0x2d, 0x52, 0xfc, 0x17, 0xf1, 0x2c, 0x0b, 0x38, 0x0f, 0x91, 0x3a, 0xc1, 0x55, 0xbd, 0x6c, 0x4f, - 0x90, 0x2a, 0xd7, 0xe2, 0xf5, 0xe1, 0x1b, 0x89, 0xc5, 0x9e, 0x88, 0x8f, 0x39, 0xd4, 0x39, 0x64, 0x3a, 0x89, 0x66, - 0xe9, 0x2b, 0x75, 0x40, 0x28, 0x27, 0x60, 0x7e, 0x96, 0x58, 0xeb, 0x94, 0x1c, 0xc2, 0xdb, 0x37, 0xff, 0x26, 0xca, - 0x3d, 0x78, 0x2c, 0x29, 0x86, 0x29, 0x5a, 0x88, 0x31, 0x8e, 0x8b, 0xa7, 0x75, 0x9d, 0x90, 0x11, 0xeb, 0xcf, 0xcf, - 0x56, 0x99, 0xad, 0x81, 0x1a, 0x49, 0x43, 0xe1, 0x90, 0x1b, 0x1d, 0x33, 0x0b, 0x93, 0x0b, 0xe3, 0x6c, 0xdd, 0x16, - 0xef, 0x24, 0xf2, 0xa8, 0x7c, 0x33, 0x0e, 0x8f, 0xd4, 0xe3, 0x90, 0x8d, 0xb4, 0xca, 0x92, 0x4e, 0xb8, 0x13, 0x0c, - 0x87, 0xc9, 0xa2, 0x8c, 0xcd, 0x2c, 0xa4, 0x10, 0xad, 0xe4, 0x04, 0x20, 0x7b, 0x38, 0x41, 0x2d, 0x04, 0x66, 0x95, - 0x61, 0x65, 0x28, 0x0c, 0x88, 0x38, 0x08, 0x77, 0x9f, 0xfc, 0xb1, 0xc0, 0xfe, 0x56, 0x1e, 0x43, 0xf2, 0xe1, 0x97, - 0x38, 0x42, 0x0f, 0xc6, 0xb5, 0x50, 0x06, 0x13, 0x21, 0x7a, 0xcb, 0x18, 0xce, 0x53, 0x9d, 0x78, 0x8b, 0xde, 0x3a, - 0xd1, 0x0d, 0x24, 0x04, 0x71, 0xb3, 0x96, 0xf3, 0x0d, 0xac, 0x28, 0x0b, 0x1c, 0x34, 0x61, 0x9d, 0x15, 0x5b, 0xb1, - 0x4d, 0xc1, 0x43, 0x94, 0xe4, 0x00, 0xf8, 0x32, 0x40, 0xae, 0x4e, 0xb2, 0x2b, 0x25, 0xb0, 0x0e, 0xe1, 0xa4, 0x60, - 0xa6, 0x31, 0xb2, 0xe6, 0xd5, 0xa6, 0xf6, 0x61, 0x56, 0x8d, 0x6f, 0x00, 0xa6, 0xbe, 0x72, 0x4e, 0xd8, 0x66, 0x97, - 0x8e, 0x6a, 0xb1, 0x2d, 0x16, 0xfd, 0x8f, 0x7b, 0x51, 0x03, 0x5e, 0xbd, 0x1e, 0x67, 0xff, 0x0b, 0x46, 0xe7, 0x0e, - 0x88, 0x7e, 0x75, 0xef, 0xb0, 0xcd, 0x01, 0x9b, 0x64, 0x55, 0xdb, 0x48, 0x9c, 0x0e, 0x78, 0x4e, 0xaa, 0x75, 0x92, - 0x46, 0x41, 0xf5, 0xc4, 0xa6, 0x7b, 0x1d, 0x59, 0x71, 0xd6, 0x44, 0x01, 0x5b, 0xc5, 0x1a, 0xe1, 0x82, 0xf1, 0xe5, - 0x42, 0xdc, 0x6c, 0xbb, 0x00, 0x86, 0x30, 0xd6, 0xac, 0xb8, 0xc6, 0x07, 0xbf, 0x3d, 0x05, 0xd4, 0x13, 0x96, 0x78, - 0x08, 0xfb, 0x1a, 0x84, 0x93, 0xf9, 0xf0, 0xb3, 0x59, 0xdf, 0x7c, 0x83, 0xaa, 0xcb, 0x10, 0xf3, 0xfc, 0x24, 0xa7, - 0xc7, 0xdf, 0x2e, 0x3f, 0x74, 0x3a, 0x4b, 0x3f, 0xe3, 0x3a, 0x4b, 0x84, 0x79, 0xf7, 0xd3, 0x1f, 0x4d, 0x6b, 0x03, - 0x6f, 0xd1, 0x55, 0x73, 0x51, 0x33, 0xce, 0x9d, 0x3d, 0x27, 0x9b, 0x08, 0x7b, 0x4a, 0x80, 0x4a, 0x35, 0x57, 0xf5, - 0x9b, 0x22, 0xf5, 0x31, 0xb6, 0xa9, 0xe2, 0xe3, 0x09, 0xd0, 0x52, 0xbe, 0xb9, 0xa3, 0x0b, 0x26, 0x41, 0xd6, 0xfd, - 0x7c, 0xcb, 0xa8, 0xd0, 0xc0, 0xb0, 0x1f, 0x13, 0xc2, 0x79, 0xfa, 0x89, 0x80, 0x91, 0xb4, 0x93, 0x4d, 0xfa, 0x20, - 0xe9, 0xb1, 0x89, 0x22, 0xe7, 0x4c, 0xc3, 0xf8, 0x8c, 0x13, 0x68, 0x0c, 0x58, 0x5a, 0x16, 0x1d, 0xca, 0x4a, 0xdb, - 0xc4, 0x9f, 0xc8, 0x77, 0x63, 0x13, 0x5b, 0x0d, 0x41, 0x1a, 0x4c, 0x80, 0x36, 0xc3, 0xe9, 0x0c, 0x74, 0x41, 0x17, - 0xbd, 0xb9, 0x79, 0x6f, 0xb9, 0xf9, 0x30, 0x32, 0x0f, 0x5d, 0xfe, 0x9c, 0xd8, 0x8a, 0xb7, 0x26, 0x75, 0x4e, 0xd5, - 0xb5, 0x2e, 0xe9, 0x4c, 0x7f, 0xc2, 0xb6, 0x12, 0x4b, 0x88, 0xbc, 0xa3, 0xfd, 0x21, 0x3c, 0x84, 0xb4, 0x45, 0xc9, - 0x89, 0xed, 0x9f, 0x14, 0x2b, 0x39, 0x9e, 0x6c, 0x2c, 0xfb, 0x69, 0x53, 0xfb, 0x5b, 0xa4, 0x83, 0xdd, 0x57, 0xea, - 0x87, 0x55, 0x5c, 0x12, 0x35, 0x5c, 0x8b, 0x2e, 0x28, 0xfd, 0x0b, 0xd3, 0x49, 0x62, 0xd5, 0xe5, 0x18, 0xf7, 0x2c, - 0x99, 0x63, 0x7d, 0x0c, 0x0a, 0x4f, 0x57, 0x91, 0x4c, 0xe8, 0xbc, 0x86, 0xba, 0x34, 0xbd, 0xeb, 0xea, 0x14, 0xe1, - 0x0d, 0x65, 0xce, 0x5b, 0x6d, 0x89, 0xda, 0xe9, 0x7d, 0xcd, 0xff, 0x6e, 0x50, 0x64, 0x93, 0x91, 0x9c, 0x07, 0xce, - 0x60, 0x2d, 0xc9, 0xe0, 0x51, 0x89, 0x28, 0x2a, 0x1f, 0x62, 0xf3, 0x45, 0xae, 0xa0, 0x97, 0xa7, 0x88, 0x8a, 0xbb, - 0x65, 0xb1, 0xf3, 0x31, 0x7f, 0x50, 0x5b, 0xa2, 0x0e, 0x4b, 0x2a, 0x4a, 0x60, 0x65, 0xdd, 0x4f, 0x23, 0x2e, 0xf5, - 0x9f, 0xe2, 0xf6, 0xfb, 0x95, 0xc7, 0x70, 0x45, 0xde, 0xdb, 0x14, 0x5d, 0xd1, 0x0e, 0x8e, 0xba, 0x61, 0xd9, 0x2d, - 0x7f, 0x48, 0x03, 0x92, 0x3d, 0xb7, 0x7a, 0x78, 0x08, 0x9f, 0x27, 0xff, 0xb0, 0xac, 0xfd, 0x65, 0x55, 0x49, 0x0f, - 0xa5, 0x91, 0x42, 0x1f, 0xa9, 0xe6, 0xc7, 0x15, 0xdd, 0xde, 0x4f, 0xad, 0x5b, 0xaf, 0x1f, 0x60, 0xf6, 0x51, 0x86, - 0xc8, 0xda, 0x2c, 0x5b, 0xf5, 0x01, 0x2a, 0x18, 0x5a, 0xf1, 0x19, 0xf4, 0x44, 0xd3, 0xa4, 0x5e, 0x79, 0x33, 0x3a, - 0x33, 0x73, 0x90, 0x71, 0x68, 0xb9, 0xfc, 0xf1, 0x1b, 0x11, 0x13, 0x93, 0xaa, 0xa5, 0xb6, 0x28, 0xc3, 0xf5, 0x82, - 0x93, 0x28, 0x11, 0x4f, 0x30, 0xa7, 0xdf, 0xa5, 0xf4, 0x82, 0x39, 0x14, 0xac, 0x70, 0x8e, 0x3e, 0x9f, 0x95, 0x72, - 0x29, 0x09, 0xf9, 0xb6, 0x84, 0x6c, 0xa1, 0x21, 0x94, 0x52, 0x6e, 0x39, 0x1a, 0x97, 0x73, 0x38, 0x65, 0x6c, 0xf6, - 0x14, 0x26, 0x3e, 0x15, 0xaf, 0x62, 0xde, 0xe8, 0xf5, 0x35, 0x62, 0x91, 0x72, 0xd9, 0x05, 0x09, 0x0b, 0x67, 0x24, - 0x97, 0x18, 0xd9, 0x04, 0x2b, 0x9c, 0x5b, 0xa8, 0x06, 0xb3, 0xae, 0x0d, 0x94, 0xaa, 0x6f, 0x40, 0x8f, 0x86, 0x7c, - 0xd5, 0xd4, 0xb9, 0xea, 0x7f, 0x3a, 0xa1, 0x11, 0x2f, 0x0b, 0xdf, 0x71, 0x1f, 0x4a, 0x4f, 0xaf, 0x90, 0x11, 0xd7, - 0x6d, 0x27, 0x1d, 0x68, 0xc6, 0xc8, 0x48, 0x98, 0xa3, 0x45, 0x9d, 0x8b, 0x06, 0xda, 0x28, 0xc4, 0x95, 0x04, 0x2d, - 0xa4, 0x11, 0x92, 0x54, 0xec, 0x5c, 0x06, 0x4e, 0x1a, 0x48, 0x4f, 0x12, 0x14, 0x32, 0xe4, 0x61, 0xee, 0x7f, 0x25, - 0x65, 0xd1, 0xd4, 0xc2, 0x25, 0xe6, 0xb7, 0xf2, 0xfd, 0xa9, 0x2d, 0x5a, 0xb5, 0x0e, 0x14, 0x90, 0xca, 0x23, 0xd6, - 0x2c, 0x9b, 0x71, 0xaf, 0x38, 0x2a, 0xc7, 0xa3, 0xd2, 0xd6, 0x94, 0x9a, 0xae, 0x68, 0x1e, 0x34, 0xa5, 0x87, 0xe9, - 0x94, 0xd8, 0x1a, 0xcb, 0xab, 0x53, 0x4b, 0xa5, 0xfa, 0xf7, 0x99, 0xa5, 0xba, 0x38, 0x6a, 0xf9, 0x26, 0xb0, 0xd8, - 0x9d, 0x83, 0x09, 0x0d, 0xf7, 0x99, 0xcd, 0xa7, 0x30, 0x2c, 0xa7, 0xcc, 0xb2, 0xec, 0xc1, 0xd2, 0x66, 0x42, 0xd0, - 0xe6, 0x3b, 0x8c, 0x13, 0xf2, 0x8c, 0x18, 0x50, 0x48, 0xa9, 0x91, 0xaf, 0xcd, 0x06, 0x31, 0xf8, 0x89, 0xdb, 0x9f, - 0xe8, 0x22, 0x41, 0xc1, 0x11, 0x3d, 0x1f, 0x1c, 0x72, 0x3c, 0x7e, 0x90, 0xa9, 0x19, 0x46, 0xb0, 0x14, 0x2f, 0x67, - 0xd6, 0xd3, 0x12, 0x10, 0x10, 0x4d, 0xf2, 0x5e, 0xbd, 0x11, 0x81, 0x9a, 0x59, 0x09, 0x51, 0x07, 0x27, 0x0c, 0xbf, - 0x08, 0x31, 0xe0, 0x8c, 0x02, 0x10, 0x8e, 0x39, 0x3d, 0x20, 0x87, 0xaf, 0x73, 0x96, 0x7e, 0x4b, 0x4b, 0xe5, 0xa8, - 0xed, 0x45, 0x61, 0x9a, 0x3e, 0x8e, 0x05, 0x0e, 0x95, 0x04, 0xd5, 0x4b, 0x61, 0xb4, 0xd8, 0xf0, 0x7b, 0xe1, 0xea, - 0xd0, 0x27, 0x6f, 0xee, 0xc3, 0x6b, 0xce, 0x3a, 0x7c, 0x4c, 0xc2, 0x8e, 0x49, 0xc1, 0x85, 0x9d, 0xba, 0x6c, 0xe4, - 0x40, 0x00, 0x60, 0x6f, 0xeb, 0xcf, 0x13, 0xde, 0x66, 0xcb, 0x58, 0xd0, 0xf1, 0xf6, 0x0d, 0x3e, 0x1c, 0x02, 0x3f, - 0xea, 0xed, 0x68, 0x99, 0xa4, 0x7b, 0xd2, 0x90, 0xba, 0x97, 0x35, 0x6c, 0xc1, 0xe4, 0x9c, 0x5f, 0xa0, 0xa3, 0xb7, - 0x99, 0xa3, 0xe4, 0xbe, 0xe8, 0xeb, 0x01, 0x21, 0x8d, 0x07, 0x65, 0x70, 0x84, 0x35, 0x9e, 0x31, 0x23, 0x6f, 0xf5, - 0xcd, 0x76, 0xce, 0x5a, 0x60, 0x2b, 0xb4, 0xb6, 0xda, 0x20, 0x66, 0xa1, 0xfa, 0xb7, 0x37, 0x95, 0x00, 0x46, 0xd0, - 0xb0, 0xcf, 0x4b, 0xfa, 0x46, 0xd5, 0xa9, 0x7f, 0x9f, 0x7b, 0x73, 0x51, 0x64, 0x98, 0x93, 0x28, 0xc6, 0x57, 0xcc, - 0x29, 0xfa, 0x45, 0x29, 0x52, 0x03, 0xb7, 0x79, 0x99, 0x95, 0x58, 0x73, 0x46, 0x3d, 0xc2, 0x73, 0x4a, 0x32, 0x07, - 0x6c, 0xc5, 0xbf, 0x8d, 0x76, 0x2a, 0x94, 0x7c, 0x54, 0xff, 0x15, 0x7f, 0x90, 0xa0, 0x80, 0x91, 0xe1, 0x4e, 0x07, - 0x61, 0xd5, 0xb2, 0xee, 0x74, 0xdb, 0x83, 0x8f, 0x2b, 0xa2, 0xa5, 0xb3, 0xd5, 0x95, 0xd7, 0x63, 0xe7, 0x6f, 0x8f, - 0xbf, 0xfd, 0x67, 0x63, 0x11, 0x33, 0x8e, 0x37, 0xe0, 0xa7, 0x88, 0xdb, 0x50, 0x0a, 0x1a, 0xe1, 0xcb, 0xf0, 0x71, - 0x64, 0x98, 0x7f, 0x93, 0x79, 0x37, 0xed, 0xf5, 0x7d, 0xb1, 0xe7, 0xe9, 0x2c, 0xa8, 0xd6, 0xc6, 0x49, 0xce, 0x4a, - 0x5c, 0xae, 0xe4, 0xc8, 0x87, 0xaf, 0xc4, 0xad, 0xe3, 0x7b, 0xab, 0x12, 0xce, 0xf5, 0xf8, 0x46, 0x8e, 0x95, 0x61, - 0x50, 0xba, 0x45, 0xe7, 0x40, 0x2c, 0xc3, 0xd7, 0x12, 0x09, 0xd9, 0xe9, 0x07, 0x84, 0x61, 0xf4, 0x8b, 0x9f, 0x1f, - 0x4d, 0x98, 0x59, 0xed, 0x1f, 0x39, 0x18, 0x8e, 0x5d, 0x4c, 0x23, 0x30, 0x42, 0x2c, 0xa1, 0x90, 0xd2, 0x41, 0x1f, - 0xc1, 0x95, 0x54, 0xd9, 0x07, 0xdc, 0xce, 0x7c, 0x42, 0x65, 0x7f, 0x64, 0x67, 0x7d, 0xef, 0x44, 0x7c, 0x52, 0xb3, - 0xfb, 0xbd, 0x56, 0x55, 0x7b, 0x77, 0xbd, 0x16, 0x59, 0x62, 0x07, 0x4b, 0x60, 0x87, 0xc5, 0x8c, 0xc5, 0x96, 0x18, - 0x2e, 0x68, 0xcf, 0xea, 0x78, 0x0f, 0x4c, 0xc6, 0xf0, 0x63, 0x15, 0xb3, 0x4c, 0x0e, 0xd2, 0x6d, 0x95, 0xe9, 0xd9, - 0x1e, 0x95, 0x9b, 0x3f, 0x54, 0x96, 0xec, 0xe1, 0xff, 0x33, 0x3f, 0xce, 0x60, 0x8e, 0xe2, 0xeb, 0x45, 0x96, 0xe4, - 0x86, 0x7a, 0xcd, 0x7e, 0xfc, 0xab, 0xb1, 0xed, 0x31, 0x24, 0x82, 0xcd, 0xdd, 0x6a, 0x6b, 0x3f, 0x03, 0x14, 0xa7, - 0xac, 0x02, 0x29, 0x4a, 0xa6, 0x63, 0x8e, 0x6c, 0xd0, 0xa1, 0x38, 0x18, 0x04, 0x8f, 0xbb, 0x4f, 0xad, 0x5a, 0xe0, - 0xe9, 0x0a, 0x57, 0x20, 0x63, 0x37, 0x96, 0xb5, 0xd5, 0xcf, 0xda, 0x78, 0x3f, 0xa2, 0x27, 0x21, 0xb0, 0x64, 0xbd, - 0x0f, 0xf0, 0x51, 0xb0, 0x97, 0x0d, 0x00, 0xca, 0x5b, 0xbe, 0xb6, 0x6f, 0x9f, 0x9f, 0x53, 0xa7, 0xb9, 0x6c, 0x3f, - 0xb1, 0x77, 0xe2, 0x33, 0x67, 0xae, 0xaa, 0xb3, 0xdc, 0xd2, 0x7d, 0x0c, 0x81, 0x20, 0x46, 0xc3, 0x03, 0x42, 0x06, - 0x8c, 0x9e, 0xe2, 0x1d, 0x67, 0xc6, 0x3f, 0x9b, 0x27, 0x35, 0x4e, 0xf6, 0x1f, 0xde, 0x58, 0x78, 0x2d, 0x2d, 0x81, - 0xde, 0x45, 0xf8, 0xdf, 0xde, 0x95, 0x67, 0x1d, 0x13, 0x4d, 0x50, 0x75, 0x70, 0xb5, 0x53, 0x5f, 0xf5, 0x26, 0x37, - 0x6f, 0x15, 0x63, 0xcf, 0xfb, 0xd8, 0x16, 0x3e, 0x12, 0x0a, 0x4d, 0xe1, 0xa3, 0x2d, 0x9b, 0xaf, 0xca, 0x75, 0xe8, - 0x07, 0xb3, 0x6c, 0x74, 0x49, 0xd6, 0x10, 0x4e, 0xef, 0x13, 0x59, 0x6c, 0x3b, 0x99, 0x4d, 0xc4, 0xf5, 0x47, 0xc0, - 0x00, 0x1e, 0xeb, 0xa2, 0xf6, 0x54, 0xdd, 0x96, 0x7a, 0xd4, 0xa5, 0x9e, 0xfb, 0x9d, 0xe6, 0xed, 0xb9, 0xb8, 0xd9, - 0xa6, 0xf7, 0x05, 0x9f, 0x5a, 0x8b, 0x8e, 0x20, 0xdf, 0xd2, 0x8d, 0x72, 0x01, 0x80, 0x0c, 0xf0, 0xc2, 0xb8, 0x89, - 0x2e, 0xab, 0xfd, 0xb1, 0xf7, 0xa3, 0x35, 0xb6, 0xc7, 0x66, 0x53, 0x6e, 0x64, 0x87, 0xd9, 0xc5, 0x81, 0xb2, 0xe3, - 0xd8, 0xf8, 0x0e, 0x7b, 0x8d, 0x87, 0x17, 0x6a, 0x46, 0x0a, 0x6b, 0x89, 0xde, 0x9b, 0x3a, 0xa9, 0x67, 0x9f, 0x1b, - 0x9c, 0x15, 0xee, 0x8b, 0xb9, 0x14, 0xde, 0x27, 0x8e, 0x5a, 0x1d, 0x00, 0x98, 0x6e, 0x60, 0x82, 0x23, 0x3a, 0xfd, - 0x58, 0x12, 0xfc, 0x77, 0x1d, 0x74, 0x2b, 0x4e, 0xe0, 0xb6, 0x14, 0x77, 0xa3, 0x96, 0xcb, 0xf7, 0xb3, 0x83, 0x90, - 0x52, 0x5c, 0x75, 0x76, 0x20, 0xf2, 0x3a, 0x50, 0x11, 0x72, 0x0a, 0x09, 0x01, 0x87, 0x4b, 0xd9, 0xa5, 0x60, 0x92, - 0x04, 0xf4, 0x53, 0xe1, 0xbe, 0x50, 0xf6, 0x92, 0xdb, 0x8d, 0xda, 0xf2, 0x47, 0x32, 0x04, 0x54, 0xcd, 0xc5, 0xb4, - 0xb6, 0x45, 0x70, 0x3c, 0x75, 0xc4, 0x7c, 0x7a, 0xac, 0xbf, 0x39, 0x90, 0xf4, 0x34, 0xf0, 0xc8, 0xc0, 0xe2, 0x6d, - 0x89, 0xd1, 0xd5, 0x8e, 0x37, 0xac, 0xec, 0x1d, 0x17, 0x5b, 0xcc, 0x41, 0x3d, 0xb1, 0xc2, 0x80, 0xf7, 0x31, 0x32, - 0x35, 0xe9, 0xc1, 0x55, 0xec, 0x54, 0x58, 0x0e, 0xcb, 0xc9, 0x02, 0xc4, 0x51, 0xea, 0x97, 0x2f, 0x73, 0xde, 0xe8, - 0x6b, 0xd6, 0x12, 0xca, 0xb0, 0x94, 0x63, 0x75, 0xb9, 0x4c, 0x1e, 0x36, 0x86, 0xac, 0x38, 0x9f, 0xb6, 0x9d, 0xa5, - 0xa2, 0x09, 0x2b, 0x88, 0x76, 0x5c, 0x23, 0x84, 0x64, 0xbf, 0x90, 0x4e, 0xd6, 0xec, 0xf0, 0x0b, 0x96, 0xd5, 0x92, - 0xd2, 0xb9, 0x25, 0xd9, 0x93, 0x19, 0xf0, 0x73, 0x04, 0x19, 0x49, 0x4a, 0x4c, 0xec, 0xa4, 0x0b, 0xc1, 0x63, 0x0d, - 0xc3, 0xd3, 0xa2, 0xac, 0x97, 0xc9, 0xa2, 0xd5, 0x8d, 0x4e, 0x3d, 0x29, 0x1e, 0x18, 0x74, 0x90, 0x58, 0x52, 0x73, - 0x88, 0xc8, 0x3f, 0x99, 0xa8, 0x0b, 0x41, 0x84, 0x64, 0xd3, 0x91, 0x4c, 0x25, 0x25, 0xeb, 0x45, 0x88, 0x23, 0x1f, - 0x90, 0x2b, 0x79, 0x44, 0x96, 0xe4, 0xd5, 0x77, 0x90, 0xc9, 0x3b, 0xd1, 0x4a, 0x8a, 0xed, 0x6c, 0x08, 0x71, 0xcf, - 0xdc, 0x64, 0x0c, 0x41, 0x26, 0x3c, 0x4f, 0xc9, 0xd8, 0x1a, 0x19, 0xe9, 0x13, 0xf2, 0xe4, 0xc0, 0x42, 0xa9, 0xbd, - 0x4a, 0x0a, 0x2c, 0x4b, 0x90, 0x85, 0x76, 0xf2, 0xa7, 0x2c, 0xa9, 0xe5, 0x91, 0x03, 0xdb, 0xa7, 0xf5, 0x84, 0x82, - 0x4c, 0x11, 0x21, 0xc7, 0x3e, 0x37, 0x02, 0x18, 0xe5, 0x61, 0x05, 0x4a, 0xe7, 0x39, 0xe1, 0x45, 0x9e, 0x23, 0x4a, - 0xe4, 0xc5, 0xc0, 0x1a, 0x55, 0xbc, 0xab, 0x91, 0xfa, 0x2b, 0x08, 0xb9, 0x50, 0xe0, 0xe1, 0x5e, 0x74, 0x7a, 0x9e, - 0xdf, 0x14, 0xeb, 0x2f, 0x18, 0x6f, 0xca, 0xea, 0xa2, 0x95, 0x1b, 0x46, 0x8a, 0x66, 0xc4, 0xf9, 0x99, 0xbb, 0x78, - 0x82, 0x4f, 0x95, 0x8c, 0xa8, 0x1c, 0xc5, 0x8c, 0x0b, 0xdf, 0x87, 0xc9, 0xbf, 0x8b, 0x6e, 0x41, 0xd1, 0x7d, 0xdb, - 0xac, 0x8d, 0x44, 0x43, 0x5c, 0x95, 0x93, 0xcf, 0x7b, 0xa4, 0xa6, 0xc1, 0x50, 0x71, 0x8b, 0xe7, 0x99, 0x51, 0xef, - 0x21, 0x3e, 0x33, 0x0a, 0x6a, 0x93, 0x84, 0x2b, 0x39, 0xc1, 0xc6, 0x84, 0x97, 0x7c, 0xa9, 0x16, 0x19, 0xc5, 0xec, - 0xbe, 0x52, 0xf9, 0xe5, 0x42, 0xd1, 0x3c, 0x4d, 0x50, 0x50, 0x4a, 0x4b, 0xd5, 0x88, 0xbe, 0x1a, 0x78, 0x88, 0x9c, - 0x6e, 0x74, 0x7e, 0x1b, 0xb9, 0x70, 0x08, 0x64, 0x8b, 0x57, 0x5e, 0xf8, 0x4c, 0xc3, 0x52, 0xed, 0xd0, 0x3e, 0x83, - 0x25, 0x4e, 0x95, 0xd1, 0x11, 0xfe, 0x67, 0x22, 0x58, 0xb4, 0xb9, 0x11, 0x78, 0x4b, 0x59, 0x49, 0x1d, 0xa7, 0x7e, - 0x83, 0xf2, 0x9e, 0x8e, 0xf2, 0x5a, 0xf9, 0xca, 0x24, 0x99, 0x31, 0x57, 0xa3, 0x31, 0x28, 0xc8, 0xc7, 0x8b, 0xf9, - 0x26, 0x00, 0x93, 0xe8, 0x76, 0x62, 0x33, 0x68, 0x87, 0xc8, 0xaa, 0x3c, 0x14, 0x77, 0x9a, 0xaf, 0xa7, 0xf3, 0x46, - 0x9e, 0x43, 0xb8, 0x85, 0xda, 0x44, 0xa3, 0x6e, 0xa2, 0xab, 0x26, 0xa0, 0x4c, 0xf2, 0x73, 0xd8, 0x01, 0x5e, 0xca, - 0x9c, 0x00, 0xac, 0x47, 0x6a, 0x4c, 0x70, 0x3b, 0x10, 0x7f, 0xa9, 0x75, 0xf5, 0x9c, 0x72, 0xba, 0xad, 0x9a, 0x55, - 0x0b, 0x14, 0x7b, 0x00, 0x2a, 0xcf, 0x9f, 0xdf, 0x9e, 0x7a, 0x1b, 0xc1, 0x56, 0xec, 0x60, 0x54, 0x32, 0xe7, 0x2a, - 0xcb, 0x06, 0xa5, 0x76, 0xcb, 0xb9, 0x69, 0x20, 0xbe, 0x7b, 0x50, 0x5d, 0xbd, 0xe0, 0x8f, 0x3b, 0x6b, 0xe3, 0x1d, - 0x07, 0xa8, 0x3d, 0xf2, 0x93, 0x17, 0x9a, 0xf4, 0x01, 0xc1, 0x1b, 0x4e, 0xd7, 0x09, 0xab, 0x09, 0x63, 0x24, 0x62, - 0x86, 0x02, 0x32, 0xa5, 0xfe, 0xb9, 0x0b, 0x34, 0xe7, 0x5f, 0xbc, 0xef, 0x40, 0xc1, 0xa1, 0x68, 0xe0, 0x3a, 0xaf, - 0x1e, 0x5e, 0xfa, 0x94, 0x1d, 0xc5, 0x18, 0xf7, 0x2d, 0xd7, 0x5b, 0xac, 0xb9, 0xd6, 0x8a, 0xf3, 0xbb, 0x74, 0x3f, - 0xb4, 0x9b, 0xe2, 0xf9, 0x06, 0xdd, 0x27, 0xb7, 0x8f, 0x73, 0xe0, 0x4f, 0x54, 0xc9, 0xa4, 0x58, 0x57, 0x38, 0xf2, - 0xa8, 0x02, 0x4d, 0xbd, 0xb7, 0x6d, 0xe3, 0x0d, 0xc6, 0x1b, 0x10, 0xfd, 0x3d, 0xa8, 0xe2, 0xa6, 0x33, 0xdc, 0xb7, - 0xba, 0xe5, 0xa4, 0x09, 0x14, 0x5a, 0x45, 0x10, 0x57, 0x5c, 0xe0, 0xe7, 0xbd, 0x00, 0x39, 0xc0, 0x1e, 0x20, 0x0d, - 0xf0, 0x68, 0x45, 0x0f, 0x21, 0x63, 0x4c, 0x6c, 0x4b, 0x2d, 0x39, 0x8b, 0x1d, 0x7b, 0x38, 0x69, 0xf2, 0x26, 0x59, - 0x1b, 0xb7, 0xf4, 0xb0, 0x10, 0x6d, 0x7d, 0xc5, 0xb3, 0x7e, 0x13, 0x72, 0x12, 0x20, 0x56, 0x5b, 0x7c, 0x4a, 0xa6, - 0x1c, 0xb7, 0xfb, 0x2b, 0x89, 0x1f, 0x7d, 0x9c, 0xd8, 0x71, 0x08, 0xa4, 0xf6, 0xa9, 0x29, 0x5c, 0x6f, 0x77, 0xd1, - 0x77, 0xaf, 0x1f, 0x7f, 0x4b, 0x57, 0xd1, 0xf5, 0xa7, 0x69, 0x77, 0xdd, 0xe9, 0xed, 0x7b, 0x2d, 0xc9, 0xb2, 0xcc, - 0x7a, 0xd7, 0x9f, 0x26, 0x77, 0x8c, 0x1b, 0xaf, 0x28, 0x07, 0x1a, 0x58, 0xef, 0xdf, 0xa0, 0xb4, 0x3b, 0xb4, 0xd0, - 0x37, 0xab, 0x0f, 0xa3, 0x02, 0x9b, 0xaa, 0xc1, 0x66, 0x87, 0x93, 0x9c, 0xcc, 0x89, 0x62, 0xe8, 0x0f, 0xa2, 0x13, - 0xb0, 0x0e, 0x5f, 0xb2, 0xa5, 0xf9, 0x03, 0x1c, 0xe0, 0xfa, 0xc2, 0x07, 0x4c, 0x68, 0xa2, 0xcd, 0x06, 0x5b, 0xeb, - 0x7f, 0xf7, 0xa9, 0x77, 0x8e, 0xd1, 0x8f, 0x6b, 0xfb, 0xcd, 0x3f, 0x1d, 0x6f, 0x71, 0x8e, 0x77, 0x45, 0xd2, 0x0e, - 0xe4, 0xc8, 0x19, 0x92, 0xdc, 0xee, 0xe2, 0xb0, 0x9f, 0xd9, 0xe5, 0x69, 0xee, 0xbe, 0xfb, 0xa9, 0x98, 0x60, 0x72, - 0x27, 0x67, 0xa9, 0x02, 0xf1, 0xef, 0x06, 0x01, 0x70, 0xb7, 0xec, 0xd7, 0x51, 0xd3, 0xd6, 0x4b, 0xee, 0x3c, 0xab, - 0x5a, 0x8d, 0xf5, 0x76, 0xeb, 0x00, 0xff, 0x5d, 0xf8, 0x00, 0x69, 0xac, 0xe7, 0xbe, 0xc7, 0xba, 0x66, 0x64, 0x0d, - 0x82, 0xdd, 0xe6, 0x61, 0x54, 0x95, 0x70, 0x88, 0x41, 0x3c, 0x91, 0x07, 0x7f, 0x01, 0xa2, 0xdf, 0xed, 0xcd, 0xfe, - 0xd3, 0xe1, 0x00, 0xe8, 0xe0, 0x8f, 0x37, 0x59, 0x73, 0x88, 0x3d, 0x81, 0x75, 0x07, 0x8c, 0x73, 0xa3, 0x49, 0x74, - 0x02, 0x5c, 0xf2, 0xae, 0x3c, 0x59, 0x74, 0xf9, 0xdc, 0xc7, 0x40, 0xe8, 0x7a, 0x8f, 0x84, 0x25, 0xd0, 0x58, 0x60, - 0x0d, 0x6c, 0xfc, 0xa0, 0x58, 0xfe, 0xb5, 0xb7, 0x54, 0x3d, 0x5d, 0xb7, 0x86, 0x79, 0xad, 0xe3, 0xf2, 0x8d, 0x38, - 0xda, 0x29, 0xc4, 0xb3, 0x5e, 0xca, 0x6b, 0xa2, 0x37, 0x0d, 0x7e, 0x6e, 0x1a, 0x7b, 0xa0, 0xe0, 0x23, 0xbe, 0xb8, - 0x30, 0x6f, 0x58, 0xef, 0xf6, 0xb3, 0x03, 0x98, 0x35, 0xe2, 0x30, 0x60, 0xa7, 0x05, 0xbf, 0xe9, 0x61, 0x3c, 0x27, - 0x66, 0x2b, 0x28, 0x08, 0x31, 0x57, 0x4f, 0x5e, 0x73, 0xcd, 0x6b, 0xb3, 0x22, 0x6b, 0x89, 0xcf, 0xb8, 0x76, 0x01, - 0xa0, 0x25, 0x1a, 0x65, 0xee, 0x5b, 0x90, 0x3a, 0xe5, 0xf5, 0xb2, 0x9c, 0x09, 0x8e, 0x05, 0xad, 0x9d, 0x80, 0xa7, - 0xc3, 0xb9, 0x98, 0x37, 0x29, 0x1c, 0x7d, 0xc5, 0xa2, 0xdb, 0x57, 0x21, 0x95, 0x58, 0x28, 0x0b, 0x1f, 0x3e, 0x8b, - 0x29, 0xd9, 0xec, 0x0d, 0x10, 0x58, 0x0c, 0xde, 0x77, 0x41, 0x7b, 0xdd, 0x30, 0x64, 0xe9, 0xe0, 0x60, 0x25, 0xee, - 0xf2, 0x6e, 0x44, 0x94, 0x3f, 0x7e, 0xfc, 0xcf, 0x4a, 0x76, 0x23, 0x97, 0x61, 0x78, 0x91, 0xd8, 0x3d, 0xcb, 0x36, - 0xdf, 0xa6, 0x31, 0x6a, 0xc8, 0x69, 0xf9, 0x87, 0x3a, 0x6e, 0x69, 0x46, 0x8a, 0x33, 0x1f, 0x40, 0xbe, 0x2d, 0xbb, - 0x08, 0x01, 0x06, 0xf3, 0x96, 0x44, 0x6c, 0xd3, 0xaf, 0x47, 0x88, 0x35, 0xfb, 0x7c, 0x03, 0xc9, 0x9d, 0xd6, 0x14, - 0xda, 0x12, 0x45, 0xce, 0x05, 0x15, 0x5d, 0x32, 0xce, 0xd7, 0x15, 0x36, 0xba, 0xc7, 0x31, 0x52, 0x29, 0x63, 0xdc, - 0xe4, 0x89, 0xa6, 0xfc, 0xc6, 0x42, 0x35, 0xf8, 0xcb, 0xec, 0x89, 0xb1, 0x3c, 0x1f, 0x0f, 0x89, 0x3e, 0x12, 0xfe, - 0x3a, 0x4e, 0xcc, 0xa0, 0xee, 0xee, 0xaf, 0x74, 0x09, 0xb3, 0x65, 0xea, 0xb5, 0xc1, 0x48, 0x54, 0x6e, 0x64, 0xef, - 0x2f, 0xe2, 0x10, 0x2b, 0xf3, 0x9c, 0x2f, 0x08, 0x0f, 0xbc, 0xd7, 0x28, 0x5e, 0x90, 0x3a, 0xff, 0x91, 0xcc, 0xf1, - 0x50, 0xa2, 0xe0, 0x35, 0xcc, 0x73, 0xef, 0x1d, 0x21, 0x40, 0xdb, 0x56, 0xc0, 0xc9, 0x3c, 0x49, 0x0e, 0xed, 0x2f, - 0x01, 0x75, 0xa5, 0x1b, 0xe4, 0x41, 0xb8, 0xd8, 0x5a, 0x93, 0x10, 0xdf, 0xff, 0xc4, 0xad, 0x44, 0x42, 0x74, 0x36, - 0xec, 0x68, 0x0a, 0x80, 0x3d, 0xe4, 0x0c, 0x26, 0xac, 0x69, 0x7f, 0x3a, 0x4e, 0x98, 0x55, 0x39, 0xeb, 0x5d, 0xa8, - 0xaa, 0x58, 0x39, 0x55, 0x03, 0x25, 0x01, 0x8d, 0x66, 0xda, 0x46, 0x8e, 0x44, 0x43, 0x94, 0x17, 0x0d, 0x70, 0x74, - 0x60, 0xdb, 0x04, 0x99, 0xd4, 0xe1, 0xdb, 0x0c, 0x8a, 0x24, 0xb0, 0xff, 0x6b, 0x28, 0x84, 0xe2, 0xb6, 0xec, 0x17, - 0xb1, 0xf0, 0xda, 0x34, 0xd8, 0xd7, 0x4e, 0xf6, 0x9c, 0x73, 0x8e, 0x76, 0x41, 0x34, 0x93, 0xb0, 0x7d, 0xbc, 0x88, - 0xf9, 0xa8, 0x61, 0x9a, 0xab, 0x3c, 0x55, 0x63, 0xbf, 0x09, 0x5d, 0x76, 0x07, 0xbd, 0x26, 0x47, 0x69, 0xc9, 0xa8, - 0xfd, 0x08, 0x6c, 0xd8, 0xc1, 0xf8, 0x2b, 0x5a, 0x17, 0x39, 0x3d, 0xad, 0x36, 0xfa, 0x66, 0x11, 0x09, 0xa0, 0x09, - 0xc1, 0xea, 0xd3, 0x04, 0xde, 0xc3, 0x25, 0x7a, 0x79, 0xcf, 0xd8, 0x06, 0x52, 0x79, 0x6f, 0x82, 0xa3, 0x31, 0x50, - 0x9f, 0xe4, 0x1c, 0x68, 0x11, 0x53, 0x2d, 0x66, 0x77, 0xa9, 0x45, 0x0a, 0x77, 0xa9, 0xeb, 0xb0, 0x02, 0x6a, 0x71, - 0xfc, 0x33, 0x02, 0xf7, 0x0c, 0x82, 0x31, 0x90, 0x68, 0x56, 0x33, 0x41, 0x72, 0xfb, 0xfe, 0x80, 0x11, 0x58, 0x49, - 0xcf, 0xda, 0x53, 0xf3, 0x52, 0x24, 0xe4, 0x23, 0x98, 0x86, 0xdf, 0x33, 0x83, 0x14, 0x92, 0xbe, 0xb0, 0x0d, 0x90, - 0x24, 0x00, 0x5d, 0x56, 0x82, 0xc6, 0x99, 0x09, 0x4e, 0xe4, 0x62, 0x4d, 0xc7, 0x3d, 0x37, 0x76, 0x2c, 0x64, 0xeb, - 0xe9, 0x62, 0xa6, 0x17, 0x98, 0x25, 0xf9, 0x0b, 0x7f, 0x23, 0x33, 0x8e, 0x9a, 0xff, 0x75, 0x0d, 0xf1, 0xf0, 0xcb, - 0x24, 0x4e, 0x99, 0xf2, 0x8e, 0xb4, 0x38, 0x2e, 0x67, 0x31, 0x35, 0x88, 0xdf, 0x0b, 0x94, 0x13, 0xb8, 0x78, 0x23, - 0x52, 0x1f, 0x83, 0xdb, 0x75, 0x34, 0x00, 0xa0, 0x34, 0xd6, 0x67, 0xde, 0xbf, 0x94, 0xc7, 0x78, 0x3b, 0x36, 0xcf, - 0x0c, 0x89, 0x08, 0x2a, 0x2d, 0xee, 0xe0, 0x9a, 0x76, 0x1d, 0xfc, 0x8b, 0x72, 0x9a, 0x2b, 0x77, 0x5e, 0x50, 0xce, - 0x7c, 0x8f, 0x94, 0x20, 0xb3, 0x97, 0xed, 0x5e, 0xb6, 0x02, 0x1d, 0x84, 0xd6, 0x16, 0x56, 0x1e, 0xd3, 0x16, 0x7f, - 0x3e, 0x8d, 0xd5, 0x26, 0xf0, 0x9b, 0x21, 0x55, 0x5d, 0x3d, 0x37, 0x68, 0xd4, 0x3f, 0x22, 0x8b, 0xde, 0x26, 0x84, - 0xdd, 0x1a, 0x9f, 0xcf, 0x0a, 0x40, 0x0b, 0xc4, 0x5e, 0xfd, 0x6f, 0x09, 0x16, 0xfa, 0x1a, 0x3f, 0x8f, 0x75, 0x75, - 0x71, 0xf9, 0x24, 0x19, 0x59, 0xf1, 0x43, 0x2f, 0x93, 0x6a, 0x59, 0x58, 0x2a, 0xa6, 0x01, 0xc8, 0x86, 0xdf, 0xef, - 0xaa, 0x67, 0xd9, 0x4f, 0xa7, 0x36, 0x5f, 0xf4, 0x74, 0x15, 0x3f, 0x07, 0x19, 0x96, 0x3c, 0x65, 0xf0, 0xdf, 0xe2, - 0xd6, 0xe0, 0x14, 0xfd, 0xdb, 0xe0, 0x87, 0x89, 0xed, 0xb3, 0x12, 0x24, 0x54, 0x84, 0xe7, 0x36, 0xea, 0xbb, 0x04, - 0xa4, 0x88, 0xee, 0x50, 0xe6, 0x55, 0x8d, 0x1d, 0x25, 0x1b, 0x6a, 0xfb, 0x19, 0x12, 0x6a, 0xe2, 0xa8, 0x86, 0x5f, - 0xdc, 0x38, 0xfc, 0x42, 0xc8, 0x21, 0xce, 0xd1, 0x93, 0x43, 0xc7, 0x26, 0xf3, 0x9b, 0xe1, 0xb2, 0x79, 0x1c, 0x2e, - 0xb7, 0xb0, 0xef, 0x23, 0x93, 0x9e, 0x2b, 0x1a, 0xcf, 0xf1, 0xec, 0xd1, 0xa2, 0x58, 0xce, 0xea, 0xde, 0x4a, 0x20, - 0x46, 0x36, 0x51, 0x5f, 0xcb, 0x0b, 0x5e, 0x9e, 0xcd, 0xac, 0x7e, 0x49, 0xe2, 0xdd, 0xd1, 0x5f, 0xdf, 0x0e, 0xd7, - 0x81, 0x1f, 0x69, 0xb8, 0x61, 0x5b, 0xc6, 0x93, 0x2d, 0xcc, 0x0e, 0x23, 0xd7, 0xc5, 0xea, 0x32, 0xcb, 0x90, 0xb7, - 0x50, 0xfc, 0xec, 0x0f, 0xa3, 0x5c, 0x32, 0x35, 0x06, 0x3f, 0xba, 0xdc, 0x8f, 0x69, 0x38, 0x95, 0x18, 0xa2, 0x95, - 0x9c, 0x74, 0x8f, 0xb5, 0x1d, 0x2b, 0x20, 0xcb, 0xde, 0x3f, 0x1a, 0x9d, 0xbb, 0x98, 0x97, 0x12, 0x75, 0x1c, 0x34, - 0xcf, 0x53, 0x1e, 0x94, 0xdb, 0x85, 0xb6, 0xd9, 0x3b, 0xe2, 0xd3, 0xd6, 0xc6, 0x05, 0xd0, 0x6e, 0x0d, 0x5d, 0x68, - 0x5d, 0xb0, 0x80, 0x84, 0xbe, 0x4b, 0xed, 0x16, 0x58, 0x49, 0xd6, 0x32, 0x86, 0x2e, 0x39, 0xbb, 0x4e, 0x5c, 0x43, - 0x95, 0xc3, 0x86, 0x4b, 0x96, 0x93, 0x2c, 0x11, 0x93, 0xed, 0xff, 0xcb, 0x1b, 0x94, 0x30, 0xd2, 0xcb, 0x12, 0x3a, - 0xde, 0x14, 0xbe, 0xb0, 0xc8, 0x02, 0x1e, 0xb7, 0xc8, 0xe8, 0x79, 0xf9, 0x90, 0x44, 0xc1, 0xa1, 0xb8, 0xe0, 0x7e, - 0xf8, 0xf2, 0x5d, 0x1d, 0xf7, 0xd6, 0xec, 0x63, 0xca, 0x91, 0xbf, 0xaa, 0x0a, 0x44, 0x5b, 0x97, 0x45, 0x4c, 0xfe, - 0x4f, 0x24, 0x67, 0x45, 0xd6, 0xa2, 0xa3, 0x03, 0x68, 0x6e, 0xe7, 0x4c, 0xb6, 0x84, 0xa5, 0x90, 0xcc, 0x43, 0x97, - 0x66, 0x0e, 0x16, 0x80, 0xae, 0x68, 0x81, 0x5d, 0x3c, 0x66, 0xcc, 0xbd, 0xcb, 0x92, 0xd3, 0xda, 0x65, 0x1e, 0x2d, - 0xa0, 0xb9, 0x70, 0x4b, 0xa2, 0x09, 0x44, 0x37, 0x52, 0x82, 0x35, 0xb6, 0x9d, 0xdb, 0x73, 0xff, 0x3e, 0x8e, 0xa8, - 0x2f, 0x0f, 0x38, 0x27, 0xc4, 0xe1, 0xdb, 0x51, 0x6e, 0x9a, 0x7e, 0xe0, 0x65, 0xab, 0x33, 0x07, 0x13, 0x17, 0xf3, - 0xeb, 0x01, 0x3c, 0x49, 0xbb, 0xce, 0xa6, 0xe8, 0xf6, 0x69, 0xed, 0xf1, 0x97, 0x84, 0x2e, 0x29, 0x96, 0x35, 0x64, - 0x32, 0x7d, 0x24, 0x61, 0xce, 0xf7, 0x3a, 0xef, 0xc3, 0x40, 0x73, 0x13, 0x70, 0x37, 0x29, 0x14, 0xbd, 0xb9, 0xcf, - 0x27, 0x1c, 0x07, 0x64, 0xb5, 0x37, 0x8a, 0xe9, 0xd1, 0x03, 0xdd, 0xe4, 0x02, 0x87, 0xe7, 0x23, 0x08, 0x91, 0x30, - 0x2b, 0xb8, 0xd5, 0xb5, 0xea, 0x1a, 0xe8, 0xa7, 0xf0, 0x63, 0x9d, 0x09, 0x0c, 0x4b, 0xf6, 0x72, 0x74, 0xae, 0xcb, - 0x50, 0x72, 0x47, 0x5c, 0xe6, 0x50, 0xf0, 0xee, 0x29, 0xf2, 0xe4, 0xfc, 0xf1, 0xdf, 0x33, 0x01, 0x43, 0xcd, 0x22, - 0x27, 0x7f, 0xcf, 0xb4, 0xf3, 0x53, 0xc0, 0x89, 0xa9, 0x30, 0xb5, 0xd8, 0xaa, 0xbc, 0x01, 0x9a, 0x53, 0x12, 0x14, - 0x1c, 0x56, 0xd1, 0xf9, 0x1d, 0x85, 0xc5, 0x25, 0xfe, 0xb0, 0x90, 0x19, 0x34, 0xb2, 0xe9, 0x75, 0x50, 0xa9, 0x74, - 0xfb, 0x04, 0xb1, 0x87, 0xaa, 0x7d, 0x6f, 0xcf, 0xd6, 0x84, 0x99, 0x1d, 0x8a, 0x02, 0xea, 0x46, 0xf1, 0xa6, 0x1f, - 0x5a, 0x6f, 0x81, 0x97, 0x05, 0xb0, 0x92, 0x4c, 0x3f, 0x1b, 0x20, 0x25, 0xe1, 0xc7, 0xca, 0x19, 0xdc, 0x70, 0x58, - 0xb9, 0x80, 0x5b, 0xbe, 0x5c, 0x3e, 0x20, 0xbb, 0xa6, 0x3b, 0x22, 0x02, 0x5d, 0x3f, 0x59, 0xb2, 0x6b, 0xc5, 0x94, - 0xc1, 0xe8, 0x46, 0x71, 0x17, 0xfa, 0x34, 0xca, 0x2e, 0x57, 0x56, 0xa0, 0xc6, 0x58, 0x9f, 0xa2, 0x26, 0xbf, 0x1f, - 0x2f, 0x9b, 0xca, 0xf5, 0x0f, 0x2e, 0x27, 0x72, 0x92, 0x8c, 0x32, 0x74, 0x67, 0xd2, 0xe7, 0x6c, 0x8e, 0x9a, 0x05, - 0xfc, 0x9f, 0x56, 0xab, 0x9e, 0x7b, 0xb8, 0x7d, 0x98, 0xf4, 0x42, 0x04, 0x03, 0xbd, 0xc2, 0xb2, 0xe9, 0x76, 0x23, - 0xdb, 0x56, 0xf8, 0xb6, 0x48, 0x81, 0xf8, 0x04, 0x68, 0x7e, 0x8d, 0x44, 0x80, 0x33, 0xf3, 0xcb, 0xbe, 0x04, 0x50, - 0x63, 0xe5, 0xe2, 0xf8, 0x83, 0x0a, 0x82, 0xe7, 0xb3, 0x9e, 0x7b, 0x01, 0x8b, 0x0b, 0x84, 0xcc, 0xbd, 0x27, 0x0a, - 0x6c, 0x6b, 0xe2, 0x4c, 0xfc, 0x66, 0x90, 0xeb, 0xf8, 0x6b, 0x35, 0xbd, 0xb5, 0x61, 0xa1, 0xb3, 0x92, 0xc2, 0xf2, - 0xa0, 0x47, 0xbb, 0x87, 0x88, 0x91, 0xae, 0xcf, 0x37, 0xe9, 0x37, 0x44, 0x23, 0xfa, 0x2d, 0x2a, 0x9e, 0x7e, 0x30, - 0x20, 0x90, 0x2c, 0x0b, 0xb7, 0xb7, 0xe9, 0x51, 0x51, 0x10, 0xd4, 0x7b, 0x18, 0xfc, 0x57, 0x23, 0xea, 0x4d, 0x1f, - 0x42, 0x80, 0xbf, 0x6a, 0x83, 0x7e, 0xea, 0x9f, 0x2c, 0x72, 0xd7, 0x0c, 0xd8, 0xb5, 0x87, 0xb0, 0xec, 0x0c, 0x1f, - 0x98, 0x41, 0x93, 0x62, 0xb2, 0x87, 0x70, 0x69, 0x4e, 0x13, 0x30, 0xa8, 0x77, 0x13, 0xcb, 0x9f, 0xb8, 0xa7, 0x9c, - 0x88, 0x3e, 0xe4, 0x77, 0x53, 0x8a, 0x00, 0xa7, 0xf9, 0xd2, 0x1c, 0xc1, 0x15, 0x81, 0x53, 0x5c, 0x60, 0xb6, 0x30, - 0x7f, 0xf2, 0xf5, 0x4d, 0x29, 0x60, 0x84, 0xcf, 0x17, 0x28, 0x03, 0x72, 0x46, 0x64, 0xe6, 0x90, 0xd1, 0xac, 0xea, - 0x08, 0xa1, 0x03, 0x72, 0x50, 0xa8, 0xdf, 0x8b, 0x59, 0x30, 0x62, 0xd8, 0x2f, 0x75, 0x22, 0xc9, 0x87, 0xc0, 0x88, - 0xd8, 0x42, 0xf3, 0xd6, 0xe4, 0x0e, 0x12, 0x44, 0x0f, 0x72, 0xa6, 0x51, 0x41, 0x79, 0x57, 0xc9, 0xcb, 0x29, 0x52, - 0x13, 0x0f, 0x7b, 0x13, 0x94, 0x53, 0x2d, 0x6f, 0x56, 0xd0, 0x7b, 0x70, 0xca, 0xe7, 0xfd, 0x93, 0xbc, 0x33, 0x60, - 0x81, 0x38, 0xaa, 0xec, 0x38, 0xb1, 0x5a, 0xe5, 0x6a, 0x1b, 0x47, 0x4e, 0x55, 0xc1, 0x95, 0x68, 0xa5, 0xbd, 0x9b, - 0xe7, 0x3f, 0x95, 0x17, 0x9b, 0x22, 0x6b, 0x62, 0xf2, 0x83, 0xe0, 0xc2, 0x23, 0xaf, 0xe0, 0xa3, 0x51, 0x87, 0xc3, - 0xaf, 0x95, 0x16, 0x82, 0x58, 0x20, 0x0c, 0x97, 0x6f, 0x7b, 0x85, 0xfd, 0x0a, 0x57, 0xe4, 0xb8, 0x84, 0xd6, 0x85, - 0xae, 0x1e, 0x7f, 0x49, 0x16, 0x13, 0xe4, 0xc8, 0x9c, 0xfd, 0xca, 0x8d, 0x18, 0xc1, 0x2c, 0x78, 0x49, 0x8f, 0x76, - 0x3c, 0xa6, 0x15, 0x41, 0x82, 0x10, 0x8a, 0xcc, 0xf3, 0x63, 0xe8, 0x26, 0xb1, 0x99, 0x50, 0xa4, 0x4d, 0x16, 0x83, - 0x06, 0x9c, 0x71, 0xb5, 0x21, 0x8a, 0x35, 0xc7, 0xa7, 0x7c, 0xdf, 0x43, 0x5c, 0x44, 0xde, 0xf5, 0xe8, 0x66, 0x38, - 0x80, 0x36, 0xdc, 0xac, 0x54, 0xf4, 0xa7, 0x88, 0x74, 0xf5, 0xd7, 0xca, 0xfb, 0xd0, 0x77, 0x88, 0x93, 0x79, 0x5c, - 0x2d, 0xbf, 0x82, 0x43, 0xa9, 0xe4, 0x13, 0xb8, 0xc2, 0x4f, 0x71, 0x08, 0x0b, 0x51, 0x91, 0x5e, 0x59, 0x88, 0x50, - 0xde, 0x0a, 0xf2, 0x56, 0x91, 0x4f, 0x4a, 0x1f, 0x34, 0xb1, 0x7d, 0xcb, 0x6e, 0xb6, 0xaf, 0x4a, 0xb8, 0x7d, 0x9f, - 0x9e, 0x8c, 0x05, 0xe7, 0x80, 0x46, 0x8f, 0x61, 0xd1, 0x64, 0xd0, 0x62, 0xac, 0xd2, 0xc0, 0x5d, 0x91, 0xc5, 0xa7, - 0xfe, 0xc0, 0x92, 0xf4, 0xc5, 0x67, 0x1a, 0x68, 0x1e, 0xa9, 0xff, 0x26, 0x14, 0xc6, 0xb1, 0xfc, 0xa3, 0x2f, 0x9f, - 0x89, 0x44, 0xd5, 0xd5, 0x1d, 0xc5, 0x1a, 0xc5, 0x3c, 0x1b, 0x98, 0x75, 0xba, 0xa3, 0x81, 0x55, 0x47, 0xf1, 0x4a, - 0xcd, 0x6d, 0x4c, 0x39, 0x14, 0x50, 0x57, 0xbd, 0xdd, 0x40, 0x54, 0xfa, 0x6a, 0x35, 0x5f, 0x11, 0x4e, 0x0b, 0x67, - 0x64, 0x12, 0xe7, 0xd6, 0xa8, 0x42, 0x1b, 0x9c, 0x59, 0xbd, 0xa7, 0xfd, 0x7a, 0xa5, 0x3a, 0xd6, 0xfa, 0x3b, 0xec, - 0x17, 0x37, 0x0e, 0xc8, 0xcf, 0x0f, 0x04, 0xce, 0x30, 0x80, 0x62, 0x0b, 0x8c, 0x43, 0xa1, 0x9c, 0x4d, 0x1c, 0x79, - 0x79, 0x89, 0x72, 0x82, 0xe2, 0x4e, 0x9f, 0x06, 0x07, 0x25, 0x70, 0x82, 0x95, 0x86, 0x8c, 0x85, 0xb0, 0x1c, 0x68, - 0xb9, 0x0b, 0xc5, 0x5d, 0x59, 0xa2, 0xad, 0x25, 0x36, 0x9d, 0x5b, 0x3c, 0x35, 0x50, 0x67, 0xba, 0x05, 0x81, 0x55, - 0x94, 0x88, 0xad, 0x55, 0xe4, 0xd2, 0x6f, 0x7d, 0x69, 0x30, 0x8c, 0xa3, 0x7b, 0x5f, 0xeb, 0x69, 0x37, 0x95, 0x38, - 0xf6, 0xe0, 0x2d, 0xf3, 0xfc, 0x9c, 0xe8, 0xc5, 0x54, 0x23, 0x3b, 0x13, 0x6f, 0x11, 0x0b, 0x46, 0x83, 0x92, 0xb6, - 0xad, 0x5a, 0xda, 0xc2, 0xd6, 0x01, 0xf4, 0x6f, 0x41, 0x1d, 0xff, 0x6f, 0xb8, 0x41, 0xd9, 0x41, 0xe8, 0x14, 0xaa, - 0xd5, 0xfa, 0x3c, 0xcb, 0xc6, 0xc6, 0x7a, 0xc7, 0x1c, 0x09, 0x44, 0x04, 0x2f, 0x61, 0x94, 0xc2, 0xcc, 0x1c, 0x2f, - 0xb1, 0xa5, 0x4a, 0x6d, 0xa7, 0x63, 0xf3, 0xe1, 0x6c, 0xac, 0x3a, 0x90, 0x43, 0x4d, 0x74, 0xde, 0xb4, 0x11, 0x0d, - 0x55, 0x4a, 0x94, 0x17, 0xc9, 0xac, 0x46, 0x5a, 0xf3, 0xe1, 0x25, 0xb0, 0x45, 0xc4, 0xec, 0xc0, 0xa6, 0x20, 0x06, - 0x2b, 0x66, 0xc8, 0xa9, 0x1a, 0x27, 0xbd, 0x45, 0x2f, 0x97, 0x59, 0x63, 0xeb, 0xd1, 0xa6, 0xe3, 0x98, 0x9f, 0x6e, - 0x3d, 0x16, 0x0f, 0x84, 0xb7, 0xe7, 0x7f, 0x2a, 0x94, 0xb2, 0x1f, 0xc7, 0xce, 0xda, 0xef, 0xcd, 0x71, 0x21, 0x16, - 0xcd, 0xf3, 0x83, 0xc8, 0x0d, 0xbf, 0x54, 0x08, 0x5f, 0x04, 0xc0, 0x8b, 0x6d, 0xf0, 0xaa, 0x21, 0xa8, 0x7d, 0x7f, - 0x45, 0x41, 0x8e, 0x3b, 0xf5, 0xde, 0x83, 0xd0, 0xb2, 0x2e, 0xf6, 0xf2, 0x8c, 0xd5, 0x25, 0x1d, 0x5a, 0x63, 0x88, - 0x44, 0x4f, 0x44, 0xb1, 0xf6, 0x1f, 0x37, 0xaf, 0xb2, 0xa0, 0x3e, 0x12, 0x2e, 0x71, 0xd1, 0x43, 0xf1, 0xf1, 0x57, - 0x49, 0x33, 0x37, 0x6d, 0x54, 0xa6, 0x67, 0xae, 0x9c, 0xfc, 0x0b, 0x1c, 0x5b, 0x56, 0x57, 0x28, 0x0f, 0xd7, 0x0d, - 0x4c, 0xf8, 0x7b, 0x73, 0xe3, 0xd7, 0xb8, 0xb2, 0xc6, 0xa5, 0x8b, 0xf1, 0x4e, 0xe9, 0x62, 0xc5, 0xdb, 0xc6, 0x15, - 0x4b, 0x45, 0xc6, 0x1c, 0x34, 0xb5, 0xfa, 0x67, 0x06, 0xb9, 0xfd, 0x59, 0x98, 0xfe, 0x2d, 0x85, 0x0e, 0x12, 0x0f, - 0xb3, 0xbb, 0x10, 0x1f, 0xaf, 0x0b, 0xb9, 0x9a, 0xe0, 0x92, 0x84, 0xa4, 0x24, 0x3f, 0x86, 0x6d, 0xdf, 0x71, 0xf2, - 0x9c, 0x29, 0x1c, 0x8d, 0xb8, 0x5d, 0x26, 0xf9, 0x95, 0xf0, 0x3f, 0x95, 0x8d, 0xeb, 0x4e, 0x9b, 0x35, 0x07, 0x0a, - 0xf0, 0x79, 0x97, 0x85, 0x09, 0xd1, 0xd1, 0xda, 0x46, 0xed, 0x45, 0xb8, 0xf1, 0x2b, 0x45, 0x82, 0xfe, 0x25, 0xa3, - 0x50, 0xd8, 0xbc, 0x47, 0x2e, 0xb0, 0x4d, 0xc1, 0xd3, 0x6f, 0xc1, 0xb5, 0x4a, 0x19, 0x30, 0xf1, 0x2b, 0xd8, 0x26, - 0x9f, 0x98, 0xb9, 0x9b, 0xf4, 0x82, 0xa8, 0x2f, 0xab, 0x68, 0x82, 0xeb, 0xca, 0x85, 0xd5, 0x95, 0xf1, 0x3d, 0x75, - 0x7d, 0x04, 0xb9, 0x78, 0x7c, 0x9a, 0xe7, 0x77, 0xa9, 0x69, 0x03, 0xf6, 0x5e, 0x8c, 0x63, 0xfc, 0x75, 0xc5, 0x3c, - 0xb3, 0x7a, 0x52, 0x55, 0xa6, 0x80, 0xf7, 0xf4, 0xe3, 0x2b, 0xee, 0xf1, 0x9b, 0x87, 0x6d, 0xb0, 0xf4, 0x3f, 0xfa, - 0x99, 0x27, 0xa0, 0x2c, 0xd1, 0x8e, 0x2b, 0x8d, 0xdd, 0x32, 0xc6, 0x96, 0x0a, 0xc2, 0x05, 0x2c, 0x48, 0x45, 0x8d, - 0x5d, 0x1e, 0x6a, 0xd9, 0x7c, 0xdb, 0x1c, 0x9a, 0x90, 0x66, 0xfd, 0x71, 0xd6, 0x73, 0x33, 0x30, 0xaa, 0x68, 0xc3, - 0x03, 0x66, 0x85, 0x36, 0x24, 0xe0, 0x60, 0xa1, 0xc1, 0xa4, 0x08, 0x02, 0xe9, 0x6e, 0xd0, 0xe3, 0x82, 0x3e, 0x51, - 0x08, 0x6c, 0xbc, 0x8b, 0x16, 0x24, 0xd0, 0xfe, 0x9f, 0x02, 0x7d, 0x12, 0x1b, 0xfa, 0x7b, 0xcc, 0xc6, 0xb1, 0xe1, - 0x58, 0xca, 0xe8, 0xde, 0x23, 0x95, 0xc0, 0x49, 0xea, 0x1e, 0xe9, 0xfc, 0x54, 0x1e, 0xa9, 0xed, 0xdc, 0x92, 0xbf, - 0x44, 0x3f, 0x8e, 0xc6, 0xd8, 0xf9, 0xed, 0xe7, 0xa8, 0x26, 0xa6, 0xf3, 0x16, 0xb6, 0xb8, 0xf6, 0xc8, 0x32, 0x3f, - 0xab, 0x33, 0xd0, 0x81, 0x84, 0x93, 0x58, 0x29, 0xbb, 0x54, 0x2e, 0xf9, 0x7f, 0xc8, 0xd3, 0x26, 0x97, 0xd6, 0x08, - 0xe2, 0x4b, 0x56, 0x7d, 0x47, 0x10, 0x19, 0x53, 0xcd, 0xaa, 0x8a, 0xde, 0x23, 0x29, 0x62, 0xa5, 0xda, 0x55, 0x8d, - 0xd7, 0x6c, 0x33, 0x3b, 0x1b, 0x9d, 0x7b, 0xa1, 0x7e, 0x2f, 0x2c, 0x45, 0x57, 0xb4, 0xdf, 0xc5, 0x36, 0x52, 0x65, - 0x13, 0x11, 0x66, 0x70, 0x87, 0xa3, 0x11, 0x62, 0x4b, 0xa9, 0xa4, 0xcf, 0x76, 0x41, 0xba, 0xe7, 0x65, 0xaa, 0x26, - 0x5c, 0x8e, 0x84, 0x45, 0x6c, 0xa9, 0x8d, 0x57, 0xb2, 0xd3, 0x83, 0x27, 0xb7, 0xb8, 0x1d, 0xcb, 0xdd, 0x80, 0xe0, - 0x34, 0x64, 0xe9, 0x89, 0x63, 0x65, 0x22, 0xdd, 0xc9, 0xae, 0x73, 0x4d, 0x91, 0x62, 0xf7, 0x99, 0x74, 0xfb, 0xa1, - 0x94, 0x7e, 0xaa, 0x34, 0xe6, 0xc0, 0x35, 0x8e, 0xc0, 0x45, 0xc3, 0x88, 0x3e, 0x5e, 0x93, 0xf9, 0xd4, 0x07, 0xe9, - 0x49, 0x2d, 0x00, 0xc7, 0x41, 0xe9, 0x2c, 0x71, 0xb9, 0xc4, 0x0e, 0xfc, 0x24, 0xec, 0xac, 0x7a, 0x76, 0x1e, 0x0b, - 0xf9, 0x4c, 0xb5, 0xd9, 0x3a, 0x48, 0xe4, 0x9b, 0x9a, 0x87, 0x62, 0xd5, 0x0e, 0x0b, 0x0f, 0x7c, 0xbc, 0xc3, 0xe7, - 0xc7, 0xbb, 0xab, 0x6c, 0xc5, 0xcb, 0xc6, 0x39, 0x0d, 0x16, 0x97, 0x38, 0xd1, 0xf2, 0xcb, 0x65, 0x65, 0x83, 0x85, - 0x27, 0xf1, 0xe8, 0x7f, 0x53, 0x65, 0xfc, 0x4a, 0x86, 0x62, 0x39, 0x68, 0xbd, 0x2a, 0xab, 0xa4, 0xb8, 0x75, 0x7b, - 0x64, 0x91, 0x44, 0xf4, 0x30, 0x29, 0x97, 0x3a, 0xad, 0x6a, 0xa5, 0xc3, 0xdf, 0x4f, 0xe8, 0x8e, 0xb2, 0x0a, 0x00, - 0x53, 0x09, 0xfd, 0x83, 0x15, 0xdf, 0x65, 0xd4, 0xe8, 0xb0, 0x17, 0x2c, 0x96, 0x7d, 0x8e, 0xe2, 0x5f, 0xdb, 0xf3, - 0x30, 0x2c, 0x4b, 0xd2, 0x5d, 0xbd, 0x85, 0xd8, 0x0b, 0xfe, 0xf0, 0xc0, 0x69, 0x14, 0xa9, 0xc5, 0x8b, 0xab, 0xd0, - 0x24, 0xde, 0x21, 0x1d, 0x3f, 0x6d, 0x2d, 0xff, 0x26, 0xac, 0x24, 0xf6, 0x79, 0x5c, 0xcd, 0xb5, 0x6a, 0xd7, 0x52, - 0xb4, 0x38, 0x94, 0xd6, 0x48, 0x2f, 0x43, 0x7d, 0x0d, 0xf1, 0x26, 0xb7, 0xb6, 0xc4, 0x23, 0xee, 0x5e, 0x4a, 0xcf, - 0xb8, 0x68, 0x17, 0x72, 0xbe, 0xdf, 0x4a, 0x4a, 0x28, 0xee, 0xe4, 0xb1, 0x51, 0x3c, 0xb1, 0x9f, 0x5d, 0x92, 0x7c, - 0x20, 0x48, 0x71, 0xb1, 0xd2, 0xe9, 0x77, 0xce, 0x0e, 0xcf, 0x4a, 0x1d, 0x96, 0x68, 0x75, 0x6a, 0x3b, 0xb0, 0x12, - 0xef, 0xd9, 0xd7, 0x78, 0x13, 0xab, 0x04, 0xf4, 0xce, 0x85, 0x46, 0x5c, 0xba, 0x19, 0x11, 0xba, 0x48, 0xa7, 0x09, - 0x84, 0xbf, 0xdc, 0xfa, 0x25, 0xf1, 0xec, 0x7e, 0x2e, 0x07, 0x12, 0x35, 0xd4, 0x81, 0x43, 0x28, 0x2c, 0x5f, 0x44, - 0x33, 0x63, 0x2a, 0xd1, 0x1b, 0xb6, 0xab, 0x59, 0xea, 0x0e, 0x5f, 0x98, 0x4d, 0x4f, 0x7e, 0x95, 0xa3, 0x0d, 0x71, - 0x78, 0x26, 0xec, 0x8f, 0xdd, 0xe3, 0xff, 0x4a, 0x93, 0xe5, 0x45, 0xd3, 0xd1, 0x11, 0xc8, 0x16, 0x2d, 0x6b, 0x7c, - 0x63, 0x73, 0x0d, 0x5a, 0xc1, 0xce, 0xbc, 0x12, 0x28, 0x19, 0xda, 0xd2, 0x1d, 0x7d, 0x4f, 0x5e, 0x93, 0x00, 0xc6, - 0x32, 0xb5, 0x6e, 0x67, 0xbb, 0xf2, 0x2c, 0x18, 0x45, 0xb9, 0xe5, 0xc0, 0x1a, 0xb8, 0x6e, 0x0c, 0x8d, 0x9d, 0x31, - 0xba, 0xe6, 0xff, 0xac, 0x14, 0xd3, 0x15, 0x73, 0x90, 0x04, 0x5b, 0x5e, 0x1e, 0x06, 0xa9, 0xd9, 0xa7, 0x96, 0xae, - 0x33, 0xb5, 0x44, 0x50, 0x98, 0x15, 0x4f, 0x4d, 0x1a, 0xfa, 0x05, 0xec, 0xdf, 0xde, 0x98, 0x0e, 0x82, 0x7c, 0x2b, - 0x99, 0xc6, 0x68, 0x50, 0x39, 0x2f, 0xd4, 0x43, 0x6f, 0xbe, 0x70, 0x20, 0xbb, 0x5d, 0x59, 0x64, 0x54, 0x3b, 0xd4, - 0x0b, 0xb3, 0xe9, 0x9d, 0x81, 0x19, 0x89, 0x08, 0xb0, 0x11, 0x1f, 0xf5, 0x57, 0x84, 0x62, 0x89, 0x89, 0xb4, 0xf2, - 0x46, 0x9f, 0xdf, 0xe7, 0xc2, 0x42, 0xe7, 0x09, 0x36, 0xbd, 0x59, 0x34, 0xa3, 0x91, 0x00, 0x23, 0xe8, 0x8b, 0x9c, - 0xe5, 0x9c, 0xd5, 0x20, 0xb4, 0x3a, 0xa5, 0xe1, 0x16, 0x9c, 0x1e, 0x77, 0xad, 0x09, 0x94, 0xdb, 0x5f, 0x3a, 0x7b, - 0xab, 0xd7, 0xc2, 0xf6, 0xd6, 0x23, 0xd5, 0x8b, 0x3a, 0x1f, 0x7f, 0x70, 0x65, 0xe6, 0xf2, 0xef, 0x6d, 0x66, 0x22, - 0xa9, 0xfc, 0xf9, 0x0a, 0x89, 0xa0, 0xf2, 0xf0, 0x56, 0x1b, 0xc1, 0x85, 0xec, 0xe8, 0x19, 0xb3, 0x75, 0xd2, 0x0a, - 0xb6, 0x7f, 0x53, 0xfc, 0x40, 0x64, 0xf8, 0x17, 0x33, 0x70, 0xc4, 0x59, 0xc8, 0xb2, 0xa3, 0x40, 0x2b, 0xca, 0x03, - 0x35, 0x4e, 0xbc, 0x98, 0x8f, 0xe5, 0xba, 0x7c, 0x7b, 0x73, 0xa2, 0x82, 0xac, 0xb1, 0x08, 0x1e, 0xd6, 0xcb, 0x37, - 0x29, 0x93, 0x65, 0xc7, 0xa7, 0x37, 0x3d, 0x6e, 0xcf, 0x8d, 0x08, 0x48, 0x8b, 0x67, 0xc8, 0xe7, 0x4a, 0x24, 0x66, - 0x37, 0x1a, 0x2f, 0x39, 0x62, 0x31, 0x96, 0x12, 0x51, 0x2a, 0x74, 0x5c, 0x0b, 0x87, 0x28, 0xc4, 0x2a, 0x8c, 0x24, - 0xa8, 0xfc, 0x72, 0x61, 0x69, 0x16, 0x61, 0x62, 0x1f, 0x8b, 0x2b, 0x39, 0x4c, 0xb1, 0x87, 0x36, 0xd3, 0x7e, 0x52, - 0xd7, 0xf8, 0x8f, 0x51, 0xd7, 0xd7, 0x13, 0xea, 0x15, 0x43, 0x7b, 0x0d, 0xa5, 0xa9, 0x4e, 0x26, 0x56, 0x2c, 0x78, - 0xa4, 0x46, 0xe3, 0x3e, 0x34, 0x02, 0x84, 0xe2, 0xf6, 0x71, 0xd0, 0xb1, 0xad, 0x58, 0x62, 0xc4, 0x69, 0x51, 0x32, - 0xb3, 0xb4, 0xe9, 0xd8, 0xad, 0xa4, 0x43, 0x5a, 0x5e, 0xea, 0xf0, 0xfc, 0xc6, 0xbe, 0xee, 0x0a, 0x23, 0x8d, 0x79, - 0x37, 0x70, 0xbb, 0xdc, 0x74, 0x45, 0x45, 0xd1, 0x66, 0x64, 0x43, 0x5d, 0x0f, 0x88, 0x42, 0x88, 0x0d, 0x73, 0x6b, - 0x28, 0x4e, 0x46, 0x3b, 0xda, 0x61, 0x81, 0x79, 0x6c, 0x60, 0x1c, 0x83, 0x59, 0x47, 0xb5, 0xb1, 0x13, 0x59, 0xd6, - 0xbf, 0xe7, 0xb5, 0x8d, 0xf8, 0x7c, 0xb9, 0x26, 0x40, 0x40, 0xe3, 0x41, 0x2f, 0x7b, 0x45, 0xe4, 0xa0, 0x97, 0x21, - 0x97, 0xd8, 0x38, 0x21, 0x43, 0x63, 0xe3, 0xfb, 0x83, 0xd9, 0x93, 0x99, 0xe3, 0xe7, 0x33, 0x83, 0xb1, 0x8f, 0xd5, - 0xfc, 0xc8, 0x82, 0x43, 0x99, 0x34, 0x5d, 0x3f, 0x72, 0x44, 0xef, 0x99, 0x56, 0xdc, 0x77, 0x38, 0x58, 0x26, 0x65, - 0x96, 0x4c, 0xba, 0x19, 0x40, 0x65, 0xb0, 0x92, 0x77, 0x3b, 0x3f, 0x5c, 0x69, 0x88, 0x7e, 0x68, 0x2e, 0x16, 0x53, - 0xd9, 0x0e, 0xce, 0x53, 0x43, 0xa4, 0x2c, 0x0d, 0x6f, 0x8e, 0x06, 0x21, 0xc4, 0xf5, 0x69, 0xbe, 0xfe, 0x75, 0x54, - 0x3b, 0x9b, 0x4d, 0x4d, 0x91, 0x34, 0x15, 0x4c, 0xcf, 0x58, 0x29, 0x0d, 0x8e, 0x41, 0x80, 0x01, 0x27, 0x0b, 0x39, - 0x6f, 0x7b, 0xe4, 0xfc, 0xd3, 0x20, 0xd6, 0x03, 0x5a, 0xeb, 0x5e, 0x64, 0x44, 0x62, 0x1f, 0xda, 0x8a, 0x4b, 0x54, - 0x9d, 0xca, 0x06, 0xa0, 0xa2, 0xfe, 0xda, 0xeb, 0xd1, 0x0a, 0xfe, 0x9e, 0x83, 0xae, 0x7a, 0x8d, 0x2f, 0xda, 0x7b, - 0xa2, 0xdf, 0x34, 0xf5, 0x7f, 0xa2, 0x0c, 0xc2, 0xf6, 0x32, 0xa1, 0x03, 0x6f, 0x20, 0x0b, 0x08, 0xf8, 0x9d, 0x1e, - 0xf4, 0x05, 0xe0, 0x91, 0x18, 0x72, 0x40, 0x8e, 0x9f, 0x5b, 0x03, 0x35, 0xae, 0xf6, 0x3a, 0xf7, 0xfd, 0x37, 0x1f, - 0x1c, 0xe9, 0x83, 0x6b, 0x1c, 0xba, 0xc7, 0x27, 0x12, 0x59, 0xc8, 0x8e, 0xb3, 0x74, 0x78, 0x21, 0xa7, 0xdb, 0xfa, - 0xa8, 0xa4, 0xdb, 0xf1, 0x44, 0xe1, 0x1f, 0x5a, 0x90, 0xbc, 0xcd, 0xe3, 0xd9, 0x81, 0xa6, 0xfa, 0x76, 0x26, 0x35, - 0x62, 0xd3, 0xdd, 0x4e, 0xa9, 0x4f, 0xb2, 0x12, 0x8e, 0x85, 0xc1, 0x36, 0x06, 0xe3, 0x2a, 0xb7, 0x73, 0x2b, 0xb7, - 0x39, 0xac, 0x35, 0x7d, 0xf1, 0xed, 0x6e, 0x6f, 0x5a, 0xe8, 0xfd, 0x4b, 0xfb, 0x9c, 0x8e, 0xa1, 0x99, 0x3b, 0x0c, - 0x08, 0x0a, 0x5f, 0x28, 0x4e, 0x2f, 0xd3, 0xd7, 0xb7, 0xc3, 0xf8, 0x18, 0xda, 0xf9, 0xaa, 0xd8, 0x09, 0x32, 0x8f, - 0xca, 0x45, 0x6a, 0xf3, 0x99, 0x71, 0x59, 0x4d, 0x6e, 0x8b, 0xf3, 0xdb, 0x53, 0x32, 0xef, 0xf9, 0x15, 0x34, 0xa8, - 0xc7, 0xfe, 0xa3, 0x86, 0xbf, 0x3c, 0xad, 0x61, 0x5d, 0x29, 0xca, 0x80, 0xdd, 0xd6, 0x35, 0x20, 0x9b, 0x9c, 0xf3, - 0xe0, 0xb8, 0x56, 0x38, 0xf0, 0x6a, 0x17, 0x9d, 0x43, 0x5c, 0x56, 0xc6, 0xf5, 0xa6, 0x4f, 0xbb, 0xdc, 0xcf, 0xb8, - 0x53, 0xd8, 0x75, 0x70, 0x12, 0xb1, 0x81, 0x07, 0x15, 0x7d, 0x40, 0x77, 0xd2, 0x87, 0x7a, 0xd8, 0xab, 0x06, 0x42, - 0x08, 0x8c, 0x6f, 0xbe, 0x50, 0xe6, 0xcf, 0xd2, 0xea, 0xbb, 0xac, 0x55, 0x31, 0x96, 0x64, 0x0d, 0x9c, 0x9d, 0xde, - 0x1f, 0x71, 0x18, 0x62, 0xc7, 0x9b, 0x04, 0xc4, 0x59, 0xe6, 0x46, 0xcc, 0x49, 0x10, 0x7d, 0xc8, 0x3a, 0xea, 0xe9, - 0x47, 0xf3, 0x1f, 0x10, 0x01, 0x02, 0x16, 0x1c, 0x27, 0x02, 0x61, 0xc8, 0x7c, 0x85, 0xf0, 0x9d, 0xbe, 0xfd, 0xf0, - 0x0b, 0xa6, 0xb6, 0x6f, 0x74, 0xd7, 0xc8, 0xff, 0x6b, 0x38, 0xe4, 0xf6, 0x57, 0x9e, 0x2e, 0x0f, 0xf9, 0x93, 0xcb, - 0x3e, 0x7f, 0xbb, 0x77, 0xd3, 0xe4, 0xee, 0xe4, 0xe6, 0x63, 0x05, 0xd4, 0xfa, 0x7c, 0x95, 0x1e, 0xa1, 0x62, 0x44, - 0x19, 0x73, 0xa7, 0x87, 0x31, 0x6d, 0x96, 0x9d, 0x0d, 0x2e, 0x11, 0xfb, 0x35, 0x2e, 0x4f, 0xbd, 0x86, 0x09, 0x6c, - 0x57, 0xe1, 0x5a, 0x3a, 0x97, 0x49, 0xd6, 0x3c, 0x53, 0xe6, 0xa8, 0x60, 0x2c, 0x6c, 0x4c, 0x00, 0x6f, 0x60, 0xa7, - 0xcb, 0x77, 0xfa, 0xd6, 0x8b, 0xbe, 0x94, 0x07, 0x09, 0x6a, 0x1e, 0x70, 0x11, 0xe8, 0xea, 0x99, 0x6d, 0xb1, 0xf1, - 0xfb, 0x39, 0xd1, 0xd1, 0x04, 0x92, 0xfa, 0xe3, 0x31, 0x6a, 0xaf, 0x72, 0x57, 0xda, 0x2a, 0xaa, 0x85, 0x9e, 0xed, - 0x89, 0xd0, 0xa7, 0x4c, 0x26, 0x03, 0x76, 0x01, 0x5f, 0xf5, 0x92, 0xbe, 0xb4, 0x35, 0xe4, 0x53, 0xe5, 0x29, 0x17, - 0x2c, 0x1c, 0x4f, 0x70, 0x9c, 0xf6, 0xa8, 0x3e, 0x10, 0x4c, 0xe2, 0x2a, 0x58, 0xc3, 0xbe, 0x64, 0x55, 0xe9, 0x45, - 0x73, 0x32, 0x0c, 0x2e, 0xa7, 0xc9, 0xfa, 0x37, 0xb6, 0xc5, 0xd2, 0xf7, 0x24, 0xd0, 0x6e, 0xd1, 0xc8, 0x66, 0x8c, - 0x85, 0x0c, 0x65, 0x3a, 0x68, 0x03, 0x09, 0x40, 0x67, 0x4d, 0x67, 0xc5, 0xa7, 0xa9, 0xa5, 0x70, 0x6e, 0x92, 0x18, - 0x0b, 0x97, 0xe6, 0x48, 0x36, 0x53, 0x30, 0xe1, 0x75, 0x4b, 0x7b, 0x9e, 0x4d, 0x32, 0xef, 0xcb, 0x24, 0xa6, 0x7c, - 0x2f, 0x70, 0xef, 0x20, 0x9c, 0x48, 0xe8, 0x55, 0xc8, 0x52, 0x28, 0xb5, 0x04, 0xdb, 0x98, 0xb9, 0xf0, 0x37, 0x00, - 0xa2, 0x7c, 0x1a, 0x63, 0x03, 0xf6, 0xaf, 0xd1, 0x10, 0x3a, 0xb1, 0xfd, 0xc1, 0x5a, 0x49, 0x61, 0x06, 0xaa, 0x2c, - 0x94, 0xd8, 0x9c, 0x25, 0x7b, 0x71, 0xf8, 0x06, 0x17, 0x3a, 0x77, 0x4a, 0x61, 0x9f, 0xd3, 0x39, 0xc1, 0x54, 0x55, - 0xce, 0x1b, 0x72, 0x13, 0xe2, 0xf9, 0x46, 0x92, 0x46, 0xcb, 0x21, 0x76, 0x11, 0x73, 0xbd, 0xf8, 0xed, 0xdf, 0x47, - 0xb8, 0xd9, 0x94, 0x16, 0x9b, 0xd9, 0xce, 0x08, 0xcf, 0x3b, 0x38, 0x3a, 0x23, 0x8f, 0x5d, 0x8f, 0x2c, 0x0d, 0xfe, - 0xf1, 0x4d, 0x6e, 0x97, 0xeb, 0x9d, 0x13, 0x40, 0x3d, 0xf9, 0xef, 0x45, 0xed, 0x6a, 0x72, 0x1a, 0x89, 0xa1, 0xb1, - 0x91, 0x91, 0x05, 0x00, 0x12, 0x18, 0x6b, 0x3a, 0x36, 0xb3, 0x29, 0xda, 0x76, 0x82, 0x68, 0xf6, 0xf3, 0x47, 0x5c, - 0xbf, 0x37, 0x1b, 0xbe, 0xc0, 0x7d, 0xdc, 0xb1, 0x51, 0x5c, 0x3e, 0xb0, 0x89, 0x1c, 0xfa, 0xad, 0x16, 0x33, 0xfa, - 0x46, 0x26, 0xdc, 0x88, 0xf5, 0x39, 0xb4, 0xdb, 0xa0, 0xc2, 0x01, 0x90, 0xf9, 0x93, 0x7c, 0x3c, 0xff, 0x57, 0xaa, - 0xb9, 0x13, 0xc6, 0xac, 0xb1, 0x72, 0x69, 0x4c, 0xe2, 0xe4, 0xd0, 0x5e, 0x70, 0xd4, 0x9c, 0xd0, 0x3e, 0xac, 0x08, - 0x7a, 0x8c, 0xb6, 0x31, 0x99, 0x81, 0xd0, 0x90, 0x62, 0x05, 0x63, 0xb0, 0x1f, 0x56, 0x9f, 0x5d, 0x77, 0xbf, 0x40, - 0x8a, 0x7b, 0xe3, 0x3a, 0x33, 0x9e, 0x9b, 0x4c, 0x66, 0x3a, 0x8f, 0x2d, 0x78, 0x4b, 0x5c, 0x34, 0xad, 0x56, 0x3e, - 0x6b, 0x77, 0x4c, 0xdb, 0xbe, 0x63, 0xba, 0x8a, 0x5f, 0xc7, 0x87, 0x64, 0xb6, 0x37, 0xe7, 0x10, 0x40, 0x8b, 0xfa, - 0xec, 0x13, 0xfc, 0xe4, 0xa2, 0xd3, 0xd4, 0x9b, 0x6d, 0x68, 0x68, 0xbb, 0x5c, 0x9f, 0x1f, 0xb4, 0x3a, 0x41, 0xc7, - 0x90, 0xb3, 0x66, 0x50, 0xf4, 0x3e, 0xb1, 0xf3, 0x12, 0x9f, 0x58, 0xa7, 0x82, 0x71, 0xd2, 0x80, 0x7e, 0x9c, 0x93, - 0x97, 0xbb, 0xdc, 0x3c, 0x06, 0xf2, 0x53, 0x8a, 0x23, 0x74, 0xc3, 0xe8, 0x61, 0x4d, 0xf4, 0xbd, 0x47, 0x8f, 0x2d, - 0x5b, 0xb3, 0x0d, 0x40, 0x63, 0x72, 0x85, 0x2b, 0x4b, 0xb2, 0x4d, 0xf8, 0x98, 0x1e, 0x5c, 0xa3, 0x05, 0x4d, 0x9f, - 0x7d, 0xf6, 0x37, 0x17, 0xd0, 0xd9, 0x63, 0x02, 0xb5, 0xc4, 0xb3, 0x74, 0x50, 0x2f, 0x14, 0xca, 0x73, 0x04, 0x46, - 0x5e, 0x62, 0x9e, 0x55, 0xd3, 0xa1, 0xa6, 0x75, 0x8f, 0x4e, 0x4f, 0x5d, 0x6a, 0x2d, 0xbb, 0x98, 0xb1, 0x40, 0x34, - 0x47, 0x2b, 0xb3, 0xaf, 0x04, 0xfd, 0x50, 0x83, 0x8d, 0x99, 0x05, 0xf0, 0x8a, 0x5c, 0x6f, 0xa4, 0xa6, 0x27, 0xf1, - 0x1e, 0xe1, 0x8a, 0x40, 0xb8, 0x23, 0x8a, 0x94, 0xf1, 0x14, 0x88, 0xa3, 0x75, 0xbc, 0x9e, 0x4e, 0xec, 0x38, 0x78, - 0x52, 0x90, 0x17, 0x7e, 0x6b, 0x46, 0x02, 0x9e, 0xfd, 0x11, 0x48, 0xca, 0x5e, 0x07, 0x21, 0xba, 0xca, 0x12, 0xdb, - 0x5b, 0x35, 0x16, 0x77, 0x1f, 0x36, 0x2d, 0x32, 0x77, 0xc5, 0x90, 0x9d, 0x85, 0x73, 0x45, 0xeb, 0x62, 0xd9, 0x76, - 0x4f, 0xe4, 0xee, 0x6c, 0xc5, 0x41, 0x62, 0xe1, 0x7a, 0xe7, 0x13, 0x32, 0xe5, 0xc3, 0x98, 0xd2, 0xf5, 0xda, 0xa8, - 0x55, 0xbb, 0xcc, 0x91, 0x17, 0x29, 0xe2, 0xed, 0x5a, 0x48, 0x11, 0x8b, 0x53, 0x11, 0xad, 0x09, 0x5f, 0x1d, 0x24, - 0x0d, 0x6a, 0x7d, 0xbf, 0xee, 0x6c, 0xf6, 0x83, 0x3c, 0xb7, 0x4e, 0x25, 0xe5, 0xe1, 0xf0, 0xd7, 0xe6, 0xdb, 0x11, - 0xf7, 0xa2, 0x41, 0xf1, 0xa5, 0xea, 0x2a, 0x12, 0xcd, 0xed, 0x95, 0xea, 0x4c, 0x17, 0xc5, 0xef, 0x53, 0x76, 0xca, - 0x61, 0x8a, 0xf1, 0xd9, 0x74, 0xda, 0xdd, 0x27, 0x0f, 0x42, 0xc7, 0xee, 0xba, 0xdc, 0x99, 0xf9, 0x7a, 0xc7, 0xde, - 0x9c, 0x70, 0xfa, 0x9f, 0xca, 0x8a, 0xb3, 0x11, 0xd1, 0xff, 0xfa, 0x37, 0x2f, 0xc0, 0xb7, 0x4e, 0xbb, 0x2e, 0x9d, - 0x1a, 0x48, 0xa1, 0x85, 0x35, 0x6d, 0xec, 0x5f, 0xfc, 0x44, 0x0a, 0x01, 0xa1, 0x77, 0x9e, 0x57, 0x57, 0x48, 0x60, - 0x9b, 0xda, 0xc5, 0xd4, 0xed, 0xbe, 0xd6, 0x4b, 0x4c, 0xca, 0x12, 0xd7, 0x75, 0xf8, 0x85, 0xa5, 0x9f, 0x84, 0x69, - 0xc8, 0xbd, 0xd3, 0xa6, 0xd1, 0x86, 0x18, 0x41, 0x39, 0xbb, 0x17, 0x4b, 0x4d, 0x08, 0x5d, 0xdc, 0x51, 0x16, 0x60, - 0xd7, 0x3f, 0x9e, 0xa2, 0xc9, 0x95, 0x08, 0xf5, 0xc7, 0x78, 0x13, 0xb6, 0x5c, 0xdd, 0x29, 0x4d, 0x61, 0x3b, 0x4c, - 0xd9, 0x67, 0x08, 0xf4, 0x1a, 0x31, 0xf8, 0x7c, 0x7b, 0x0b, 0x07, 0x7b, 0x23, 0x34, 0x91, 0x49, 0xb7, 0x10, 0xb3, - 0xa3, 0xf1, 0xdb, 0x9f, 0xa9, 0xc6, 0xfc, 0xdc, 0xb7, 0x58, 0xee, 0x90, 0x9e, 0x00, 0x47, 0x3a, 0xe0, 0xf1, 0x3c, - 0x1d, 0x29, 0xbe, 0x0d, 0xfa, 0xb5, 0x49, 0xfe, 0xd7, 0xb8, 0xe1, 0x1b, 0x4d, 0x37, 0x84, 0xa7, 0xab, 0xc2, 0x0e, - 0x7d, 0xce, 0x60, 0x2e, 0xa9, 0x4b, 0xfa, 0xf0, 0x4f, 0x27, 0x9d, 0x71, 0x7d, 0x53, 0x44, 0x06, 0x03, 0x97, 0x05, - 0x93, 0xb3, 0xeb, 0x0e, 0xf3, 0xd2, 0xf7, 0x04, 0x32, 0x30, 0x78, 0x18, 0x47, 0x48, 0x22, 0x93, 0x81, 0xbd, 0xc1, - 0x84, 0xbe, 0xba, 0x94, 0x70, 0xc6, 0x6b, 0x4a, 0xd3, 0xa1, 0xea, 0xb8, 0xd9, 0xf4, 0x42, 0x81, 0x71, 0x04, 0xa1, - 0xc4, 0x33, 0x60, 0x15, 0xa8, 0x48, 0xcf, 0x99, 0xe5, 0x9c, 0xf2, 0x5b, 0xe7, 0xb0, 0x75, 0x9d, 0xd5, 0xa8, 0x3e, - 0x3f, 0x97, 0x85, 0x00, 0x91, 0xe6, 0xda, 0x99, 0xb4, 0x94, 0x7a, 0xfa, 0xe1, 0x91, 0x94, 0xc3, 0xff, 0x20, 0x89, - 0x57, 0x79, 0x3e, 0xfe, 0xf5, 0xe3, 0x44, 0x55, 0x3d, 0xf8, 0x76, 0xd1, 0x07, 0xba, 0x6f, 0x5e, 0x8f, 0x6a, 0xe5, - 0xf9, 0x8a, 0xfd, 0xe2, 0x22, 0xe3, 0xc2, 0xfc, 0x13, 0x83, 0x30, 0x06, 0x3a, 0xb3, 0xe0, 0x2b, 0x62, 0xc5, 0xaf, - 0xf9, 0xec, 0xb4, 0x07, 0x6a, 0x8e, 0xe4, 0x4c, 0xa6, 0x28, 0xab, 0x75, 0xeb, 0xdd, 0x4e, 0x0d, 0x88, 0x48, 0x47, - 0x6f, 0xc6, 0xe9, 0x06, 0x2e, 0x70, 0x5a, 0x75, 0x86, 0xfa, 0x59, 0xb0, 0x22, 0xb9, 0xfd, 0x0d, 0x59, 0xbc, 0xeb, - 0xbe, 0xdf, 0x51, 0xb9, 0x72, 0x12, 0x87, 0x26, 0xd6, 0x7e, 0xda, 0x29, 0x80, 0x99, 0xba, 0xb3, 0x4d, 0xd1, 0x73, - 0x1d, 0x1d, 0x1c, 0x53, 0x06, 0x0e, 0xa7, 0x9e, 0x1f, 0x24, 0x34, 0x7c, 0x15, 0xbe, 0xe8, 0xa3, 0x6e, 0xf7, 0x47, - 0x0c, 0xa4, 0x20, 0x23, 0xb9, 0xb3, 0x27, 0x96, 0x57, 0x21, 0x6f, 0xa2, 0xc6, 0x71, 0x31, 0xa3, 0x42, 0x28, 0xfb, - 0xd7, 0xf2, 0x72, 0x3f, 0x0c, 0xc9, 0x5d, 0x93, 0x12, 0x6f, 0x76, 0xae, 0x91, 0x72, 0x96, 0x60, 0x6e, 0x47, 0x2c, - 0x47, 0x33, 0xa8, 0xd7, 0x7d, 0x7a, 0xd7, 0xe1, 0x33, 0x34, 0x45, 0x8f, 0x1b, 0x74, 0xa1, 0xd0, 0xa8, 0x5b, 0x5b, - 0xa3, 0x6d, 0x1a, 0xa5, 0x89, 0xc8, 0xa9, 0x22, 0xa4, 0x0f, 0xf3, 0xcd, 0xe4, 0x9b, 0x1d, 0x90, 0x32, 0x06, 0x0f, - 0xd0, 0xa4, 0x7a, 0x05, 0x10, 0x69, 0xbe, 0x7c, 0xaa, 0xa4, 0xdb, 0xcf, 0x5e, 0x24, 0xfd, 0x04, 0x34, 0x4e, 0x34, - 0xe9, 0x1a, 0x3f, 0xa1, 0x4c, 0x6b, 0x8a, 0xa3, 0x09, 0x49, 0x34, 0x5a, 0x26, 0xcf, 0x86, 0xda, 0x91, 0xd7, 0x82, - 0x95, 0xa1, 0x27, 0x0d, 0x16, 0x81, 0xe0, 0x00, 0x89, 0x24, 0x5c, 0x53, 0x92, 0x61, 0x8c, 0x0b, 0x84, 0xd1, 0xbf, - 0xb0, 0x25, 0x1d, 0x62, 0xed, 0x66, 0xc1, 0x84, 0x8c, 0xee, 0xcf, 0xf8, 0x25, 0x0c, 0x0d, 0xab, 0x66, 0x18, 0x4f, - 0xd2, 0x71, 0xaa, 0x35, 0x46, 0x51, 0x5a, 0x9c, 0x05, 0x93, 0x5a, 0xc8, 0xa1, 0xc6, 0x00, 0xdb, 0x8d, 0xe3, 0x69, - 0x4d, 0xd9, 0x32, 0x62, 0x26, 0xdd, 0xdb, 0xda, 0x51, 0xa7, 0xb9, 0xa5, 0x9f, 0x7b, 0x21, 0xb3, 0x0d, 0x39, 0xe6, - 0xbc, 0xa5, 0x5f, 0x36, 0xd1, 0x87, 0x16, 0xeb, 0x66, 0x1c, 0x08, 0x33, 0xfc, 0xb9, 0xe5, 0x90, 0x78, 0x54, 0x30, - 0xa8, 0xf2, 0xa4, 0x46, 0x2b, 0xd2, 0xf6, 0xbe, 0xaf, 0x8e, 0xe6, 0xb6, 0xa9, 0x48, 0x1a, 0x82, 0xdc, 0x08, 0x4d, - 0x04, 0x8e, 0x5d, 0xe9, 0x1f, 0x67, 0x75, 0xff, 0xdd, 0x43, 0x1f, 0x49, 0x83, 0xf0, 0xe5, 0x9a, 0xe9, 0x20, 0x14, - 0x30, 0x57, 0xad, 0xdb, 0xd4, 0x67, 0x71, 0x35, 0xa2, 0xbf, 0x22, 0x64, 0xcc, 0x38, 0x56, 0xfd, 0x98, 0x66, 0xe4, - 0x77, 0xfa, 0x1a, 0x39, 0x26, 0xef, 0xc7, 0xcc, 0x6a, 0x55, 0xf2, 0xe1, 0xa9, 0x3b, 0x5d, 0xc9, 0x68, 0x46, 0xca, - 0xb3, 0xba, 0xc3, 0xd2, 0x56, 0x88, 0x39, 0x8b, 0xf7, 0xe4, 0x7a, 0x36, 0x5d, 0x65, 0x2b, 0xf1, 0x43, 0x7a, 0x70, - 0xaf, 0x8f, 0x99, 0xa4, 0xc3, 0x0f, 0x59, 0x7e, 0xdd, 0x9d, 0x00, 0x21, 0x4f, 0x4f, 0xc0, 0xac, 0x6e, 0x5d, 0xd9, - 0x69, 0xad, 0xb8, 0xef, 0x24, 0xdb, 0x36, 0x5c, 0xbf, 0xe6, 0x8f, 0x79, 0xf0, 0x70, 0xef, 0xcb, 0x36, 0x17, 0x4f, - 0xc3, 0xc7, 0xc9, 0x52, 0x0b, 0x21, 0xf1, 0x55, 0x97, 0x42, 0x15, 0xa3, 0xe0, 0x0d, 0xe3, 0x41, 0x5c, 0xc8, 0x1f, - 0xe7, 0xb4, 0x35, 0x2d, 0x3b, 0xb5, 0x92, 0x78, 0xac, 0xab, 0x30, 0x2d, 0xf9, 0x75, 0x51, 0xcd, 0x79, 0x66, 0xe2, - 0x55, 0xa7, 0x9e, 0xa1, 0x39, 0x8d, 0xc9, 0xf5, 0xf0, 0x9e, 0x97, 0x68, 0x64, 0xd9, 0xf0, 0x6e, 0xc2, 0x5b, 0xb1, - 0x57, 0x9e, 0xa1, 0xdc, 0x1d, 0x29, 0x35, 0x84, 0x02, 0x62, 0x04, 0x1a, 0x57, 0xe7, 0x2e, 0xad, 0xa4, 0xb3, 0xe4, - 0x51, 0x63, 0xe0, 0x8b, 0x39, 0x8f, 0x5b, 0x63, 0xa1, 0x1c, 0x6b, 0x0e, 0x61, 0x46, 0xaa, 0x70, 0x32, 0xd5, 0x0d, - 0xe0, 0xce, 0x34, 0x43, 0x88, 0x26, 0x4a, 0xcd, 0x29, 0xee, 0xe2, 0x6b, 0x34, 0x99, 0x6c, 0xe8, 0x18, 0xf4, 0x2c, - 0xaf, 0xc8, 0x34, 0x1e, 0x07, 0xd0, 0x7d, 0xe0, 0xeb, 0x06, 0x89, 0x05, 0xdb, 0xb2, 0x4e, 0xf8, 0x2a, 0x70, 0xe2, - 0x28, 0xab, 0x12, 0x53, 0xc3, 0xb3, 0xa1, 0xdb, 0x1f, 0xe8, 0x88, 0xb5, 0xa2, 0xa6, 0xbb, 0x23, 0x26, 0x28, 0xf8, - 0xee, 0xfb, 0x2f, 0x78, 0x77, 0x64, 0xe2, 0x38, 0x83, 0x38, 0xae, 0x5d, 0x78, 0x9b, 0x74, 0x04, 0x4d, 0x30, 0x56, - 0x96, 0x63, 0x9e, 0x72, 0x49, 0xa1, 0xf6, 0xfc, 0x97, 0x86, 0x23, 0x54, 0xc9, 0x35, 0x44, 0x6f, 0x19, 0xba, 0x43, - 0xb0, 0x6b, 0x1f, 0xa2, 0x53, 0x11, 0x1f, 0x78, 0x7f, 0x81, 0x48, 0x98, 0x4b, 0xa1, 0xcc, 0xb2, 0x5e, 0xed, 0xb1, - 0x80, 0x3a, 0xef, 0x29, 0xc7, 0x46, 0x01, 0x2b, 0x4b, 0xaf, 0x58, 0xab, 0x4e, 0xd9, 0xe1, 0xd7, 0x3a, 0x12, 0x62, - 0x63, 0xae, 0x1b, 0x1a, 0x3f, 0x91, 0xae, 0x02, 0x89, 0xcd, 0x7b, 0xb5, 0x9c, 0x8d, 0xa2, 0x50, 0x1f, 0xbe, 0xe4, - 0x93, 0xb6, 0x52, 0x3f, 0x41, 0x82, 0x3f, 0xe1, 0x90, 0x88, 0xf9, 0x94, 0x1f, 0x24, 0x56, 0x75, 0xb9, 0xa9, 0x59, - 0x66, 0xdb, 0x21, 0xf9, 0x97, 0x5f, 0x88, 0x3f, 0x7b, 0x8f, 0x25, 0x78, 0xac, 0x30, 0x43, 0xc2, 0x18, 0xa3, 0xd4, - 0x4b, 0xfe, 0x68, 0x81, 0x8f, 0xe7, 0x6e, 0x7e, 0xf5, 0xdb, 0x59, 0x3b, 0xfc, 0x82, 0x81, 0x42, 0x8c, 0xfa, 0x42, - 0x4b, 0x0a, 0xf6, 0xee, 0x64, 0x71, 0xbb, 0x20, 0x27, 0xa1, 0x48, 0x45, 0x89, 0x12, 0xc6, 0x90, 0xb6, 0x01, 0xd0, - 0x4d, 0x80, 0x4a, 0x94, 0x6a, 0x1a, 0xd1, 0x23, 0xf8, 0x01, 0x9f, 0x6d, 0xde, 0x1e, 0x64, 0x1d, 0x4c, 0xa4, 0x36, - 0x2e, 0x63, 0x03, 0x98, 0xe2, 0xb9, 0xb5, 0xc3, 0xfb, 0x65, 0x04, 0xad, 0x75, 0xac, 0xd4, 0x10, 0xea, 0x22, 0xe7, - 0x7e, 0xf0, 0x19, 0x75, 0x37, 0xd9, 0x39, 0xcc, 0xd3, 0x0c, 0x0c, 0xe4, 0x78, 0x40, 0xb3, 0x6d, 0x4c, 0x96, 0x28, - 0x66, 0xd9, 0x0c, 0xbf, 0x54, 0x2f, 0x6f, 0xb4, 0xa5, 0x20, 0x69, 0xad, 0xce, 0x9e, 0x29, 0x86, 0x09, 0x1b, 0x58, - 0x60, 0x3e, 0x40, 0xd8, 0xc2, 0x12, 0xb6, 0x8e, 0x3d, 0x87, 0xfe, 0x68, 0x6c, 0xce, 0x71, 0x76, 0xb2, 0xe9, 0x5c, - 0xcb, 0xc6, 0x93, 0x1f, 0x15, 0xe7, 0x3c, 0x4d, 0xca, 0x41, 0x25, 0x54, 0x5b, 0xb1, 0x40, 0x87, 0xe8, 0x56, 0x1f, - 0x2a, 0x9d, 0x33, 0xf7, 0x9c, 0x90, 0x88, 0xa7, 0x73, 0xcc, 0xb5, 0xc7, 0xfb, 0x15, 0x25, 0x10, 0x2a, 0xbc, 0x75, - 0xf1, 0x31, 0x3b, 0x40, 0x56, 0x1e, 0x0a, 0x4f, 0xb6, 0x9c, 0x96, 0x48, 0x09, 0x4e, 0xbf, 0x79, 0x9d, 0x3c, 0x15, - 0x18, 0x19, 0x8a, 0x35, 0x26, 0xd5, 0x90, 0x78, 0x83, 0x11, 0x7a, 0x71, 0x11, 0xc9, 0x15, 0x98, 0x3b, 0x97, 0x66, - 0xea, 0x7a, 0x21, 0x67, 0x2c, 0xcf, 0x3d, 0xd8, 0xe3, 0xa5, 0xa7, 0x96, 0x5d, 0x78, 0xec, 0x5e, 0x32, 0xc7, 0xeb, - 0xf3, 0x90, 0x66, 0xb0, 0x3b, 0x85, 0xb5, 0x7a, 0xac, 0x8a, 0x82, 0x01, 0x58, 0x57, 0xc8, 0xca, 0xce, 0x34, 0x29, - 0x07, 0xca, 0x4f, 0x50, 0xdb, 0x41, 0xfd, 0x1b, 0x23, 0x11, 0x8c, 0xdf, 0x6d, 0xdd, 0xd7, 0x6e, 0xc9, 0x84, 0x99, - 0x8f, 0x02, 0x1b, 0xa2, 0xc7, 0x14, 0x66, 0x6c, 0x98, 0x2a, 0x63, 0xdc, 0x79, 0x0f, 0x83, 0xae, 0x2e, 0xdb, 0x4c, - 0xe5, 0x68, 0x7c, 0xb1, 0x8c, 0xab, 0x61, 0xa6, 0xef, 0xde, 0x03, 0x66, 0xbc, 0xda, 0xf3, 0x28, 0xe2, 0xd8, 0x49, - 0xcc, 0xa9, 0x9e, 0x51, 0xed, 0x6b, 0x2f, 0xdb, 0x74, 0x87, 0x98, 0xf0, 0xee, 0x0e, 0xde, 0x3b, 0x86, 0x99, 0x4c, - 0xe8, 0xe4, 0x40, 0x66, 0x42, 0xca, 0x1e, 0xa0, 0x89, 0x0c, 0x1d, 0x1e, 0x37, 0xe6, 0xa2, 0x3c, 0x4b, 0x32, 0x0b, - 0x0b, 0x17, 0xf6, 0x4d, 0xfa, 0x6f, 0xb8, 0x98, 0xfb, 0x22, 0xd0, 0xe6, 0x30, 0x5d, 0x37, 0xd9, 0xbc, 0x67, 0x15, - 0x9b, 0x2c, 0x1d, 0xb2, 0xd6, 0xa8, 0x12, 0xfd, 0x22, 0x31, 0x29, 0x3b, 0x84, 0x1e, 0x86, 0x6e, 0x10, 0xc5, 0x82, - 0xc5, 0xbe, 0xd1, 0x45, 0x3b, 0xc0, 0x47, 0x27, 0xe1, 0xb1, 0xf8, 0x9e, 0xee, 0x5c, 0x69, 0xce, 0xb7, 0xbb, 0x93, - 0xdf, 0xa8, 0x68, 0xd4, 0x34, 0x12, 0x1b, 0x95, 0xf8, 0x58, 0xec, 0xe5, 0xa6, 0xd2, 0x76, 0xf9, 0xd8, 0xd3, 0x5f, - 0xcc, 0xc8, 0x28, 0x1d, 0xcc, 0x99, 0x0e, 0x1e, 0xc2, 0xab, 0x79, 0x25, 0x8a, 0x7b, 0xae, 0x94, 0x70, 0x82, 0x9a, - 0x0b, 0x4e, 0x1d, 0x54, 0x29, 0x3c, 0x41, 0xa0, 0xd0, 0xfa, 0xc7, 0x75, 0xfd, 0x00, 0x48, 0xdb, 0xb3, 0x63, 0x30, - 0xf7, 0x55, 0x2f, 0x51, 0xa6, 0xee, 0x99, 0xd4, 0x0a, 0x68, 0x63, 0xab, 0xb8, 0x07, 0x12, 0xf4, 0x2d, 0x87, 0x94, - 0x90, 0x95, 0x79, 0x50, 0xd8, 0x2c, 0xa7, 0x27, 0xc9, 0x54, 0xe9, 0xcc, 0x5a, 0x51, 0x2e, 0xee, 0x89, 0x0a, 0xe1, - 0xd6, 0xfa, 0xfb, 0x80, 0x10, 0xa3, 0x94, 0xc1, 0x68, 0x62, 0xe2, 0x32, 0x42, 0x06, 0x8c, 0x0b, 0xc9, 0xb0, 0x82, - 0x48, 0x61, 0x97, 0x33, 0x8c, 0xc7, 0x74, 0x79, 0xd6, 0x9e, 0x9d, 0x87, 0xed, 0x7b, 0x6e, 0xc8, 0x1d, 0x82, 0xce, - 0xc6, 0x89, 0x4d, 0xe3, 0xe7, 0x67, 0xe2, 0x7d, 0x04, 0x37, 0x2a, 0x87, 0x35, 0x1a, 0x38, 0x35, 0xe6, 0x39, 0x8b, - 0xaf, 0xe2, 0x63, 0xbc, 0xad, 0x67, 0x4b, 0xae, 0x74, 0xec, 0x98, 0x3b, 0xf2, 0x63, 0x77, 0xa5, 0xb4, 0x29, 0x48, - 0xa2, 0x9e, 0xf6, 0xb4, 0x31, 0xe8, 0x76, 0xc8, 0xcd, 0x97, 0x0b, 0x0b, 0x7d, 0x83, 0xae, 0x8f, 0xf6, 0x01, 0xf7, - 0xe9, 0x20, 0xa2, 0x6a, 0xf1, 0x5d, 0x8b, 0x2f, 0x52, 0x10, 0x68, 0x89, 0x7d, 0x40, 0xde, 0xbb, 0x13, 0xe7, 0xbe, - 0x8b, 0x81, 0x1b, 0xfa, 0x07, 0x60, 0x21, 0xdd, 0x8a, 0xfb, 0xc9, 0xdb, 0x48, 0xd2, 0x0a, 0x80, 0x55, 0x9b, 0xc6, - 0x81, 0x23, 0x61, 0xfa, 0x02, 0x4b, 0xf6, 0x45, 0xce, 0x25, 0x9f, 0x14, 0x8a, 0xee, 0xf0, 0xb7, 0xf0, 0xe2, 0xf9, - 0x09, 0xe7, 0x64, 0xdd, 0xd2, 0xf1, 0x5d, 0xb5, 0x29, 0x91, 0x6a, 0xa9, 0x18, 0x24, 0x30, 0x23, 0x14, 0x39, 0x0f, - 0xd2, 0xb7, 0x17, 0xd9, 0x23, 0xfe, 0x01, 0xef, 0xf1, 0x0c, 0xdc, 0x74, 0x10, 0x26, 0xb3, 0xd9, 0x23, 0x1a, 0xaf, - 0x6f, 0x55, 0x27, 0xec, 0x02, 0x95, 0xc2, 0x68, 0x98, 0xc4, 0xf9, 0x4c, 0x95, 0x64, 0x38, 0xbe, 0xa9, 0x12, 0x52, - 0x38, 0xf1, 0x09, 0x88, 0xdb, 0x98, 0xdc, 0x8b, 0xb9, 0x12, 0xd5, 0xe9, 0xb6, 0x63, 0x68, 0xad, 0xfe, 0xfb, 0xf7, - 0x37, 0xe1, 0x7f, 0x90, 0x6c, 0xfa, 0x1b, 0x5f, 0x65, 0xe7, 0x9d, 0x13, 0xc1, 0xec, 0x21, 0x09, 0xdf, 0x38, 0xb3, - 0xac, 0x47, 0xbc, 0x26, 0x56, 0x48, 0xf7, 0xd4, 0xc9, 0xc2, 0x6e, 0x18, 0x72, 0xd5, 0x14, 0x9b, 0x4f, 0xbb, 0x54, - 0x80, 0x3e, 0xf6, 0x92, 0xad, 0x9a, 0x50, 0x4e, 0x00, 0x4a, 0x65, 0x3c, 0xb3, 0x52, 0x47, 0x83, 0x9a, 0x8d, 0xf2, - 0x32, 0x72, 0x46, 0x1f, 0x0b, 0xdd, 0x56, 0xb3, 0x20, 0x4b, 0x56, 0xe9, 0xa6, 0x86, 0x3a, 0x6b, 0xd6, 0xee, 0xcd, - 0xe7, 0xff, 0x6e, 0x3d, 0x2b, 0x13, 0x44, 0xf5, 0x46, 0x8d, 0xfe, 0xac, 0x97, 0x70, 0x45, 0x1c, 0xc7, 0xeb, 0x1d, - 0x9f, 0xd5, 0x7f, 0xb7, 0xf8, 0x47, 0xab, 0x5a, 0xf7, 0x12, 0x08, 0xcd, 0xcb, 0x5a, 0x00, 0xb3, 0x8a, 0x21, 0xbd, - 0x9e, 0x75, 0xe2, 0xc8, 0x86, 0x00, 0x7c, 0xf8, 0x13, 0xb7, 0x6b, 0xf7, 0x7e, 0x67, 0xa2, 0x6d, 0x7b, 0xe2, 0x8c, - 0x55, 0x05, 0x94, 0x27, 0xba, 0x79, 0x4c, 0x34, 0x63, 0x55, 0x77, 0x85, 0x69, 0xf6, 0x7f, 0x52, 0x4e, 0xfa, 0xcb, - 0x92, 0xb9, 0x9a, 0x11, 0x00, 0xe2, 0x34, 0x8f, 0x89, 0xaa, 0x77, 0x33, 0xed, 0xbd, 0xab, 0xe7, 0xf4, 0xda, 0xa2, - 0xb5, 0xcf, 0x64, 0x2b, 0x35, 0x8c, 0x41, 0xd7, 0x3c, 0x51, 0x7d, 0x53, 0x72, 0x19, 0x69, 0x15, 0x6d, 0xcc, 0x1b, - 0x7f, 0x6a, 0x4d, 0xae, 0xde, 0xa5, 0xae, 0x30, 0x42, 0x64, 0xd6, 0xdf, 0x19, 0xc9, 0x97, 0x37, 0x7f, 0x38, 0xb1, - 0x17, 0xcb, 0x24, 0x2c, 0x6f, 0xd4, 0x8a, 0xb0, 0x31, 0x56, 0x81, 0x85, 0x7c, 0xf9, 0x16, 0xcd, 0x34, 0x85, 0xa5, - 0x4d, 0x24, 0x67, 0x94, 0xfe, 0x28, 0x2e, 0xeb, 0x54, 0xed, 0x5d, 0x88, 0x95, 0xbd, 0x16, 0xda, 0x4f, 0x7f, 0x95, - 0xd4, 0x63, 0xd9, 0x59, 0x04, 0x9d, 0x0c, 0xa0, 0xa1, 0x5a, 0xb5, 0xe7, 0x88, 0x5d, 0x70, 0xc6, 0x66, 0xf1, 0xd2, - 0x19, 0xe6, 0x9d, 0x61, 0x10, 0x82, 0xd3, 0x24, 0xc7, 0x82, 0x9b, 0x8c, 0x73, 0x00, 0x6d, 0x55, 0xa3, 0x9e, 0xab, - 0x14, 0x4f, 0x9f, 0xf7, 0x42, 0x59, 0xf8, 0x39, 0xa0, 0xba, 0x73, 0x47, 0x12, 0x6e, 0xe1, 0xe8, 0xf8, 0x89, 0xab, - 0xe2, 0xb2, 0x86, 0xee, 0x51, 0xcc, 0x9c, 0xb7, 0xcf, 0x84, 0x2b, 0xb6, 0xe1, 0xb4, 0x12, 0xcc, 0x09, 0x00, 0xd6, - 0x4d, 0xb0, 0x6e, 0xbe, 0x81, 0xaa, 0x2e, 0x9d, 0x4b, 0x46, 0x72, 0x7d, 0x80, 0x0b, 0xe1, 0x65, 0xbe, 0xf1, 0x1e, - 0x38, 0x09, 0x2a, 0x2d, 0x78, 0x30, 0x7b, 0x0c, 0xe6, 0xd5, 0x34, 0xf8, 0x43, 0x70, 0x67, 0xa6, 0x8e, 0x50, 0x1c, - 0x79, 0x4e, 0xad, 0x97, 0xee, 0xa5, 0x1d, 0x1f, 0xac, 0x54, 0x4f, 0x9c, 0x43, 0x19, 0xd7, 0x39, 0xd8, 0x3e, 0xea, - 0xbd, 0xd0, 0x7e, 0xc1, 0xac, 0x0f, 0xbc, 0xa6, 0x09, 0x8f, 0x03, 0xaf, 0x73, 0x45, 0xb5, 0x33, 0x5a, 0xe9, 0xb5, - 0x42, 0x8c, 0x70, 0xe8, 0x14, 0xf3, 0xe7, 0x37, 0x31, 0xca, 0xa0, 0xb7, 0x28, 0xb9, 0x57, 0xb5, 0xc4, 0x69, 0xf7, - 0xbb, 0x21, 0xe9, 0xdf, 0x55, 0x40, 0xfd, 0x9f, 0x19, 0x0f, 0x77, 0xbf, 0xba, 0x97, 0xb3, 0x17, 0xd1, 0xe6, 0xcd, - 0xb8, 0xba, 0x98, 0xd1, 0x2e, 0x40, 0x69, 0x60, 0xf1, 0xad, 0x9b, 0xfd, 0x98, 0xc7, 0x59, 0x8d, 0x31, 0x86, 0x26, - 0xa1, 0xb1, 0x89, 0x60, 0x63, 0xbc, 0x49, 0x6c, 0x05, 0x2f, 0x45, 0x10, 0x8b, 0xc9, 0xe4, 0x47, 0x1d, 0x06, 0xd7, - 0x8c, 0x3c, 0xfd, 0x86, 0x14, 0xe7, 0xa2, 0x68, 0xa5, 0xc7, 0x93, 0x1f, 0xc5, 0x96, 0x84, 0x7b, 0xb5, 0xdf, 0x2c, - 0x49, 0xb9, 0xe7, 0x25, 0xa5, 0xc5, 0xba, 0x60, 0x2b, 0xd9, 0x5a, 0x6b, 0xea, 0x9f, 0xda, 0x35, 0x51, 0xd1, 0x78, - 0x1a, 0xde, 0xa8, 0x7e, 0x90, 0x5f, 0x67, 0x37, 0x36, 0x0b, 0xb9, 0x56, 0x38, 0x68, 0xfa, 0x91, 0x5e, 0x74, 0xdd, - 0x86, 0x36, 0xee, 0xf4, 0x44, 0xeb, 0x18, 0x22, 0xde, 0xc1, 0x25, 0x5e, 0x30, 0x2f, 0x47, 0xb9, 0x5d, 0xc4, 0x5c, - 0x65, 0x4e, 0xec, 0xae, 0x25, 0xf3, 0xcc, 0xa2, 0xb2, 0x3c, 0xe9, 0x34, 0x79, 0x41, 0x02, 0x49, 0x7b, 0x0e, 0x0e, - 0xc0, 0xdf, 0xd2, 0x35, 0x6f, 0x76, 0xa0, 0x6b, 0xb9, 0xe9, 0xd5, 0x21, 0xde, 0xb5, 0x1f, 0x1e, 0xc9, 0xb4, 0x8d, - 0x80, 0xc6, 0x37, 0x34, 0x0e, 0x80, 0x4c, 0x57, 0x34, 0x6d, 0x6c, 0x1c, 0x04, 0x98, 0x50, 0x91, 0xbd, 0x4b, 0x04, - 0x9c, 0x0a, 0xde, 0x07, 0x32, 0x56, 0x64, 0xd2, 0xae, 0xfd, 0xb3, 0x41, 0x26, 0x21, 0x2d, 0x64, 0xa3, 0x3e, 0x6d, - 0x6a, 0x6f, 0x26, 0xff, 0x76, 0x2b, 0x77, 0x49, 0xc5, 0xd6, 0x92, 0x9d, 0x6d, 0x41, 0x4e, 0x0b, 0x49, 0x3e, 0x56, - 0x01, 0xe1, 0x58, 0xb3, 0xd8, 0xc8, 0x0f, 0x05, 0x4f, 0x80, 0x62, 0x28, 0x5a, 0x42, 0x33, 0x76, 0xb3, 0x3d, 0xd8, - 0x5e, 0x47, 0x0f, 0x89, 0x7b, 0x40, 0xca, 0x39, 0x32, 0x17, 0x79, 0x4c, 0x77, 0xef, 0x6c, 0x5b, 0x8f, 0xad, 0x6b, - 0xf1, 0x59, 0x1d, 0x6c, 0x6e, 0xbd, 0xa2, 0xca, 0xff, 0x3f, 0x74, 0x35, 0x7f, 0x1e, 0x07, 0x70, 0xf0, 0xee, 0x83, - 0x4e, 0x21, 0xb5, 0xa1, 0x56, 0x6f, 0xb7, 0x35, 0x51, 0x88, 0x26, 0x7a, 0xfe, 0x58, 0xb1, 0x4a, 0x2f, 0x31, 0xca, - 0xc2, 0x97, 0x54, 0xe2, 0x74, 0xbb, 0xfc, 0xa9, 0x4b, 0x86, 0xb3, 0xab, 0x64, 0xfd, 0xd9, 0x30, 0x8f, 0x7e, 0x13, - 0x43, 0x5c, 0xe5, 0xc5, 0x6d, 0x04, 0x43, 0x28, 0xf4, 0xd8, 0xf9, 0x07, 0x74, 0x52, 0xd6, 0x7c, 0x22, 0x81, 0x62, - 0x79, 0xaa, 0x0c, 0x0d, 0x28, 0xd2, 0xdb, 0x0c, 0x51, 0x4d, 0x14, 0xa3, 0x9d, 0xb5, 0x42, 0x90, 0x46, 0x37, 0xfa, - 0x2f, 0x03, 0x9b, 0x34, 0xcb, 0xea, 0x73, 0xe2, 0x04, 0xd9, 0xbe, 0x3b, 0xe9, 0x33, 0x96, 0x0b, 0xbe, 0x1e, 0xc7, - 0x65, 0x23, 0x78, 0x1b, 0x8a, 0xd0, 0x39, 0x66, 0x50, 0x9b, 0x3a, 0xaf, 0xda, 0x19, 0x42, 0x39, 0x8e, 0x03, 0xb9, - 0xa6, 0xa5, 0xdd, 0x01, 0x5a, 0xc4, 0x73, 0x9e, 0x4e, 0xf0, 0x98, 0xa4, 0xf9, 0x3e, 0x07, 0x79, 0x37, 0x09, 0x82, - 0x26, 0xfa, 0xba, 0x83, 0x0b, 0xf2, 0x58, 0xd1, 0xb5, 0x83, 0xd9, 0x1b, 0xeb, 0xef, 0xea, 0xb0, 0x88, 0xe7, 0x18, - 0x42, 0xc6, 0x0d, 0x29, 0x72, 0xc5, 0xdd, 0xac, 0x54, 0x99, 0xc2, 0xcb, 0x85, 0x1f, 0x98, 0x07, 0xb6, 0xad, 0x3a, - 0xa2, 0x66, 0x27, 0x71, 0x95, 0x1a, 0xed, 0xe9, 0xf7, 0x69, 0x9b, 0x58, 0xa3, 0xe3, 0x33, 0xe3, 0xd7, 0xe8, 0xa3, - 0xf6, 0xe2, 0xb1, 0x06, 0xe6, 0x22, 0x8b, 0x12, 0xf6, 0x25, 0xc8, 0x39, 0x52, 0x4c, 0x7d, 0xef, 0x26, 0x96, 0xfe, - 0x0c, 0x6c, 0xd0, 0x5e, 0xd3, 0x4a, 0xaa, 0x0f, 0xdc, 0xa0, 0xdf, 0x1e, 0x0d, 0x1a, 0xf4, 0x12, 0xcf, 0x30, 0x77, - 0x09, 0x1e, 0xdf, 0xcc, 0x29, 0x51, 0xbf, 0x03, 0xf2, 0x72, 0xac, 0xc1, 0x16, 0x0b, 0xc2, 0x02, 0xc2, 0x88, 0xda, - 0xaf, 0xf7, 0x5f, 0x6a, 0xde, 0xe5, 0xeb, 0x39, 0x42, 0xac, 0x60, 0x3f, 0xa2, 0x9c, 0x8c, 0x77, 0x2a, 0x9a, 0x99, - 0x7b, 0x66, 0xde, 0xdf, 0xf3, 0x74, 0x4f, 0x37, 0x37, 0xf3, 0x4a, 0xeb, 0xb3, 0xee, 0xa9, 0x3e, 0x55, 0x91, 0x26, - 0x66, 0xf5, 0x65, 0x87, 0xf2, 0xc1, 0x3c, 0xb8, 0x73, 0x95, 0xed, 0xdc, 0x01, 0x1d, 0x74, 0xd6, 0x1d, 0xfc, 0x30, - 0xf7, 0x8a, 0x0f, 0x4d, 0x81, 0xd3, 0xff, 0x97, 0x80, 0x87, 0x06, 0x43, 0xd1, 0x92, 0x66, 0x8a, 0x79, 0x0d, 0x36, - 0x2f, 0xb4, 0x58, 0x89, 0x8d, 0xfb, 0x3d, 0x8d, 0xc7, 0x36, 0x9f, 0x2b, 0x94, 0x3d, 0xfc, 0x67, 0x0f, 0x05, 0x94, - 0xc5, 0x51, 0xcc, 0xce, 0x66, 0xa1, 0xa2, 0xd8, 0x25, 0xc0, 0x14, 0xc1, 0x77, 0x97, 0x2c, 0x36, 0x73, 0x42, 0x9b, - 0xaf, 0x60, 0xad, 0xe9, 0xd3, 0xc4, 0x74, 0xbe, 0x0a, 0x41, 0x05, 0xb3, 0x58, 0x33, 0xbc, 0x24, 0xe9, 0xa1, 0x23, - 0x35, 0xed, 0x63, 0x46, 0x3d, 0x35, 0x94, 0xd1, 0xd6, 0xfd, 0xad, 0xa7, 0x14, 0x1e, 0x49, 0x93, 0x0b, 0x5d, 0x93, - 0x50, 0x00, 0xff, 0x4f, 0xb5, 0x91, 0x4a, 0x93, 0x89, 0xb0, 0x59, 0x55, 0x64, 0xcb, 0xe9, 0xc8, 0x3f, 0xfe, 0xaa, - 0xd6, 0xc5, 0x90, 0xf8, 0xe1, 0x44, 0xdd, 0x93, 0x98, 0x83, 0x1c, 0xb4, 0x38, 0x85, 0x19, 0x68, 0x8d, 0x6c, 0x9b, - 0xa3, 0x9a, 0x25, 0x79, 0x79, 0x27, 0x81, 0xa7, 0x87, 0x26, 0xfa, 0xd5, 0x57, 0x69, 0xdb, 0xac, 0x3d, 0xef, 0x82, - 0x74, 0x00, 0xe1, 0xe0, 0x98, 0x19, 0x2f, 0x36, 0x7a, 0x7b, 0x09, 0xbe, 0xdf, 0x47, 0xb5, 0xb3, 0x0b, 0x94, 0x09, - 0xb5, 0x6f, 0x74, 0xe8, 0xf5, 0x6d, 0xae, 0x39, 0x61, 0x37, 0xa6, 0x32, 0xff, 0x28, 0x34, 0x4f, 0x67, 0xa5, 0xc7, - 0xc7, 0xdf, 0xa9, 0x9d, 0xe8, 0x18, 0x45, 0x4b, 0x82, 0xc4, 0xde, 0x82, 0x6a, 0xb4, 0xac, 0x35, 0xdb, 0x58, 0xf8, - 0x4c, 0x86, 0x05, 0xc6, 0x04, 0xdf, 0x26, 0xf3, 0xfe, 0x86, 0x48, 0x08, 0xf3, 0x85, 0x50, 0x1c, 0x4c, 0xdd, 0x69, - 0xbc, 0xd2, 0x5c, 0x2a, 0x5b, 0xd3, 0x25, 0xfe, 0xc1, 0xcc, 0x82, 0x42, 0xe6, 0x13, 0x05, 0xbf, 0xcc, 0xe1, 0xb8, - 0x6b, 0x84, 0xad, 0x67, 0x50, 0xf0, 0x81, 0x39, 0x0c, 0x10, 0x29, 0x8c, 0x6e, 0xeb, 0x29, 0x1e, 0x20, 0xb3, 0x2e, - 0x43, 0x9a, 0x61, 0xbf, 0x09, 0x18, 0x81, 0x57, 0x94, 0x37, 0x2b, 0xa0, 0xbc, 0x91, 0xe6, 0x6d, 0x57, 0x1e, 0x01, - 0xca, 0x5d, 0x48, 0x3a, 0x28, 0xa1, 0x17, 0x53, 0xfb, 0xa0, 0xb2, 0x7a, 0x82, 0x56, 0x31, 0x93, 0x1b, 0xac, 0xe6, - 0x46, 0x90, 0x49, 0x42, 0x1c, 0x9f, 0xd3, 0x80, 0xe1, 0x4e, 0xc2, 0x0b, 0xc4, 0x1c, 0x46, 0x04, 0xe9, 0xe4, 0x76, - 0xde, 0x2a, 0x53, 0x74, 0xe5, 0x42, 0xda, 0x22, 0x59, 0xe6, 0xa3, 0x06, 0xf2, 0x59, 0x82, 0x05, 0xf0, 0x0f, 0x0c, - 0x8a, 0x3d, 0x12, 0x36, 0x73, 0x2c, 0xb9, 0x86, 0x41, 0xa4, 0xf4, 0xf4, 0x56, 0x99, 0xa2, 0x0e, 0x57, 0x54, 0x42, - 0xc8, 0x0c, 0x98, 0xe0, 0x4b, 0x38, 0xbe, 0xd5, 0xa0, 0xc1, 0xd0, 0x9d, 0x82, 0xda, 0x67, 0xc0, 0x49, 0x53, 0x6a, - 0x96, 0xc4, 0x9e, 0x52, 0xf8, 0xd3, 0x8c, 0x45, 0xd8, 0x34, 0x0f, 0x94, 0xef, 0x9a, 0xa9, 0x62, 0xc1, 0x1b, 0xf9, - 0x13, 0xf8, 0x0e, 0x93, 0xae, 0x28, 0x81, 0xef, 0xe3, 0x61, 0xbc, 0xc3, 0x28, 0xc4, 0x3f, 0x66, 0xba, 0x0d, 0x09, - 0xcb, 0x62, 0x86, 0x00, 0xa4, 0xdf, 0xb8, 0x2b, 0x3e, 0x2c, 0xcf, 0x9a, 0x49, 0xe2, 0xd6, 0xef, 0xf7, 0xff, 0x69, - 0x20, 0xb3, 0x0f, 0x3d, 0x91, 0xcd, 0xe6, 0x30, 0x06, 0x14, 0x9d, 0x4c, 0xd8, 0xa3, 0x71, 0xe2, 0x41, 0x01, 0xd7, - 0xa3, 0x73, 0x5d, 0x49, 0x6d, 0x3d, 0xc4, 0x7b, 0x10, 0x26, 0xac, 0xac, 0x1a, 0xc5, 0xb3, 0xbf, 0x6f, 0xba, 0xe9, - 0xd4, 0x71, 0xa0, 0x80, 0xd9, 0x5f, 0x77, 0xaa, 0x43, 0x77, 0x77, 0x83, 0xc4, 0xb5, 0x44, 0xdb, 0x70, 0xc4, 0xfb, - 0xa1, 0x01, 0x4c, 0xd9, 0xc9, 0x79, 0x71, 0x1e, 0xa6, 0x97, 0xbf, 0x1c, 0x3a, 0x2a, 0x39, 0xeb, 0x12, 0x91, 0x49, - 0xb6, 0x92, 0x6c, 0xc6, 0x5e, 0xcc, 0xad, 0x8c, 0xfe, 0x84, 0x27, 0xe8, 0xac, 0xf3, 0x30, 0x0a, 0x0a, 0x15, 0xe1, - 0x2d, 0x80, 0xc2, 0x59, 0xb6, 0xe9, 0x74, 0xf0, 0x5a, 0xc4, 0x34, 0x08, 0xd7, 0x75, 0x07, 0x54, 0xfa, 0x96, 0x92, - 0x21, 0x33, 0x05, 0x70, 0x11, 0xc5, 0x58, 0x8c, 0x04, 0xa5, 0x8c, 0x23, 0x0e, 0x95, 0xf5, 0xed, 0xe6, 0x48, 0x61, - 0x10, 0x7d, 0xb4, 0x43, 0xd7, 0xa1, 0x45, 0xd1, 0x7f, 0x8b, 0x45, 0xc8, 0xf7, 0x14, 0xa7, 0x84, 0x9b, 0x34, 0x35, - 0xf9, 0xa1, 0x0f, 0x2f, 0x60, 0x71, 0x06, 0x46, 0x77, 0x67, 0xb7, 0x3c, 0x8a, 0xbb, 0x1b, 0xfa, 0x18, 0x7e, 0xd1, - 0xcf, 0x32, 0x3b, 0xa7, 0xa6, 0xf0, 0x55, 0xec, 0xe2, 0x7b, 0x22, 0x90, 0x63, 0xce, 0x36, 0xcc, 0xf3, 0x0f, 0xb6, - 0xaf, 0x05, 0x89, 0xd5, 0xad, 0xc0, 0x29, 0x05, 0xdb, 0x7a, 0xa5, 0x01, 0x9d, 0x5d, 0x89, 0xf0, 0xfe, 0x8d, 0xef, - 0x81, 0x16, 0x51, 0x49, 0x76, 0x8a, 0x47, 0x4e, 0x7f, 0x0b, 0xe2, 0xcc, 0x81, 0x9c, 0xa2, 0x7a, 0x32, 0x82, 0x5e, - 0x40, 0x5b, 0x3e, 0x8f, 0x2e, 0x39, 0x19, 0xd6, 0x45, 0xf9, 0x44, 0x7b, 0x8e, 0xc9, 0xce, 0xa2, 0x14, 0x86, 0xa4, - 0xf4, 0x3d, 0xcc, 0x06, 0x07, 0x20, 0x3b, 0xaa, 0x7e, 0x58, 0x24, 0x61, 0xf3, 0xce, 0x24, 0x33, 0x17, 0x21, 0x39, - 0xa7, 0xf5, 0xca, 0xbd, 0x88, 0xcc, 0x5c, 0x3b, 0x8a, 0xb2, 0x8e, 0xab, 0x49, 0xd2, 0xcd, 0x66, 0x96, 0x3a, 0xa5, - 0x1a, 0x63, 0x24, 0x21, 0xa3, 0x13, 0xaf, 0x7a, 0x91, 0x94, 0x41, 0xd6, 0x44, 0xc5, 0xb2, 0xa6, 0x21, 0x59, 0x04, - 0xf4, 0x21, 0xf6, 0xba, 0xa8, 0x5c, 0xd4, 0xae, 0xa2, 0x55, 0xa9, 0xb2, 0x73, 0x50, 0xcf, 0x73, 0x13, 0xf4, 0x40, - 0xca, 0x26, 0xbb, 0xdf, 0x6e, 0x45, 0x97, 0x90, 0x43, 0x67, 0x38, 0xad, 0x66, 0x20, 0x8c, 0x97, 0xb1, 0xd6, 0xb1, - 0x2f, 0x50, 0xd4, 0xc0, 0xb5, 0xd3, 0xa0, 0xcb, 0xdb, 0xad, 0xd1, 0xc5, 0xe4, 0x51, 0x60, 0x4a, 0x56, 0xe5, 0xd2, - 0x54, 0xe1, 0x6c, 0x9e, 0x5f, 0xf6, 0x77, 0xc6, 0xb7, 0x5d, 0x3a, 0x0e, 0x54, 0x30, 0xc3, 0xbb, 0x60, 0x0f, 0x13, - 0xaf, 0x71, 0x82, 0x9c, 0x98, 0x3a, 0xf6, 0x11, 0x21, 0xd1, 0x56, 0xff, 0x7a, 0xad, 0x99, 0xf9, 0x63, 0x3f, 0xa6, - 0xdc, 0x3d, 0xd0, 0xcb, 0x91, 0xdd, 0x6c, 0xe1, 0xa5, 0x7c, 0x58, 0x42, 0x7c, 0xe1, 0x6c, 0x2e, 0xdd, 0x66, 0xe8, - 0xd2, 0xe7, 0x2f, 0x87, 0x31, 0x15, 0x5b, 0x22, 0x39, 0x1c, 0x88, 0xcd, 0xed, 0x3a, 0x27, 0x49, 0x14, 0xf0, 0x3e, - 0xcf, 0x11, 0x01, 0xcf, 0x5c, 0xf6, 0x9c, 0x49, 0x94, 0x16, 0xe9, 0x68, 0xa4, 0x4f, 0xc7, 0xa0, 0xe2, 0x53, 0xa1, - 0x84, 0xc1, 0x7d, 0x66, 0x13, 0x83, 0xfc, 0xf9, 0xb1, 0x48, 0xb7, 0xa9, 0x31, 0x6c, 0xf8, 0x0a, 0x6e, 0x15, 0x54, - 0x7e, 0xff, 0x13, 0x8d, 0xbb, 0xe6, 0x87, 0xd5, 0xd1, 0x7b, 0xfc, 0x5c, 0x41, 0x1b, 0x3c, 0xba, 0x3a, 0x0f, 0xdb, - 0x78, 0x07, 0x80, 0xe6, 0xdc, 0x16, 0x4c, 0x11, 0x6c, 0xbc, 0x75, 0x89, 0x5f, 0x86, 0xa4, 0xd6, 0xf8, 0x84, 0x40, - 0x7d, 0x36, 0xcc, 0xc3, 0xe4, 0x7d, 0xf2, 0x23, 0x1c, 0x99, 0x67, 0xa7, 0x04, 0xbc, 0x51, 0x76, 0xe5, 0x91, 0x7e, - 0x94, 0xa7, 0xbb, 0x2f, 0xbe, 0x9f, 0x5b, 0x58, 0x7f, 0x80, 0xe3, 0xf8, 0x45, 0xfd, 0xfd, 0xf0, 0x90, 0xed, 0x0f, - 0x5b, 0xff, 0xfd, 0x89, 0x92, 0xdf, 0x2a, 0x0d, 0xde, 0xfc, 0xf1, 0x42, 0x08, 0x4e, 0x0d, 0x6a, 0x98, 0xc5, 0xc8, - 0x70, 0xe9, 0x17, 0x51, 0x8a, 0x49, 0xd6, 0x18, 0xad, 0xa4, 0xa5, 0x85, 0xf7, 0x4a, 0x9b, 0xb3, 0x2b, 0xb7, 0x57, - 0x05, 0x71, 0x67, 0x69, 0xea, 0x83, 0x02, 0x93, 0x51, 0x45, 0xe0, 0x48, 0xa1, 0x6a, 0x2d, 0x61, 0x91, 0xfa, 0x8d, - 0x80, 0xae, 0xd5, 0x6b, 0x65, 0x60, 0x9c, 0xaf, 0x77, 0xb6, 0xc9, 0x3c, 0x23, 0x5b, 0xd0, 0x3c, 0xf2, 0xd2, 0x9a, - 0xb7, 0x22, 0xaa, 0xaa, 0xd6, 0x1d, 0xb6, 0x7a, 0x11, 0x23, 0xd6, 0xdd, 0x3c, 0x05, 0xc6, 0x3b, 0xc2, 0x03, 0xdc, - 0xdc, 0x30, 0x0a, 0xed, 0x56, 0x4f, 0xca, 0xd3, 0xec, 0xdd, 0x21, 0xdd, 0x68, 0x32, 0x85, 0xc6, 0x82, 0x2d, 0x5d, - 0x45, 0x87, 0xc4, 0x31, 0xe5, 0x90, 0x90, 0x33, 0xb4, 0x6f, 0xb0, 0x64, 0xd3, 0xa9, 0xda, 0x0c, 0xd7, 0x68, 0xc7, - 0x13, 0x0d, 0x31, 0x1d, 0x74, 0x45, 0x3a, 0x44, 0x0f, 0xc0, 0x14, 0x33, 0x9e, 0x26, 0x1d, 0x2d, 0xec, 0xae, 0xd5, - 0x88, 0x33, 0x4a, 0x07, 0xa3, 0x81, 0x51, 0xa2, 0xab, 0xe8, 0xf5, 0x0d, 0x42, 0xe7, 0x44, 0x76, 0x7b, 0xca, 0x5b, - 0xa5, 0x86, 0xf5, 0x99, 0xa1, 0x75, 0xa9, 0x12, 0x61, 0xa5, 0x38, 0xb1, 0xec, 0xae, 0x4c, 0xfb, 0x4a, 0x8b, 0xab, - 0xdc, 0xd0, 0xb6, 0x01, 0x50, 0x3d, 0x2d, 0xf1, 0x7a, 0xf2, 0x9a, 0xaf, 0xf6, 0xf4, 0xa4, 0x4d, 0x9f, 0x5b, 0x50, - 0xd3, 0x2e, 0x05, 0xe6, 0xf5, 0x6e, 0xa3, 0xee, 0x2b, 0xd3, 0xf0, 0xae, 0x2a, 0x26, 0x89, 0xbf, 0xb4, 0x0f, 0x71, - 0xa5, 0x43, 0xd2, 0xb0, 0x17, 0x5d, 0xc1, 0x6a, 0x71, 0x09, 0x9b, 0xf2, 0x04, 0x04, 0x46, 0x4b, 0x5a, 0x52, 0x70, - 0x83, 0xaa, 0xa2, 0xaf, 0x84, 0x57, 0xcf, 0xa7, 0xd3, 0x14, 0xac, 0xfb, 0xcd, 0xc4, 0x26, 0x8b, 0x3e, 0xcf, 0x5d, - 0x59, 0x73, 0xde, 0x1b, 0x1e, 0x55, 0x1d, 0xdb, 0x9c, 0x02, 0x74, 0xb7, 0xd3, 0x16, 0xda, 0xe2, 0x47, 0xb6, 0xc9, - 0x34, 0x6a, 0xad, 0x15, 0x95, 0xfc, 0xcc, 0x3b, 0xae, 0xfc, 0x2b, 0x65, 0xab, 0x02, 0xd5, 0x26, 0x24, 0x26, 0xe6, - 0xa3, 0x15, 0x88, 0x1d, 0x74, 0x3e, 0xe6, 0x2f, 0x74, 0x95, 0x2c, 0xce, 0x78, 0x6e, 0x72, 0x64, 0x52, 0x63, 0x78, - 0x68, 0x42, 0xd1, 0xf6, 0x71, 0xb0, 0xe9, 0x60, 0xed, 0x2f, 0xe9, 0xd4, 0xbc, 0x26, 0x0a, 0xfe, 0x9c, 0x08, 0x3b, - 0x41, 0xe3, 0xcb, 0x98, 0xe8, 0xd2, 0xe6, 0xa7, 0xfc, 0xad, 0xdb, 0x07, 0xd9, 0x7a, 0x05, 0xab, 0xf5, 0xd0, 0xea, - 0xf6, 0xec, 0x22, 0x3c, 0x37, 0x44, 0x59, 0x9f, 0x72, 0x8d, 0x79, 0xbd, 0x8a, 0x0d, 0x24, 0x8f, 0xc8, 0x41, 0x85, - 0x57, 0x4e, 0x3f, 0x06, 0x05, 0xe0, 0xe7, 0x4d, 0x76, 0x84, 0x5f, 0xb5, 0x30, 0x0f, 0xfb, 0x04, 0x56, 0x8e, 0x07, - 0x8f, 0x6e, 0x3a, 0x73, 0x5e, 0x43, 0x58, 0x20, 0x7f, 0x39, 0x4f, 0xc6, 0x23, 0xc6, 0xb2, 0x43, 0xea, 0x8a, 0xb4, - 0x27, 0x00, 0x90, 0x52, 0x34, 0x1c, 0x44, 0xc5, 0xc6, 0xc9, 0x0f, 0x94, 0xa6, 0x05, 0x44, 0x81, 0x3a, 0x9d, 0x71, - 0x0c, 0xd4, 0x0d, 0xda, 0xb1, 0x6d, 0x66, 0x4b, 0x8d, 0xc5, 0x6b, 0xb4, 0x9f, 0x9a, 0xf4, 0x2c, 0xba, 0x04, 0x6f, - 0xd1, 0x22, 0xc6, 0x2f, 0xc6, 0xb4, 0x66, 0x8b, 0x1b, 0xfd, 0xc4, 0x4e, 0xc0, 0x8d, 0xd1, 0x6d, 0x9c, 0xdd, 0xb2, - 0xb3, 0x44, 0xa5, 0x37, 0xdf, 0x40, 0xf0, 0xae, 0xb7, 0x5b, 0xbb, 0xb1, 0xd2, 0xfe, 0x33, 0x05, 0xe3, 0x2a, 0x99, - 0x1b, 0x88, 0x20, 0x55, 0x8f, 0x96, 0xfc, 0x59, 0x20, 0xb1, 0xf5, 0x5c, 0xda, 0x5a, 0x00, 0x83, 0xef, 0xf6, 0xe1, - 0x35, 0xd3, 0xb3, 0x96, 0xc3, 0x6a, 0xf0, 0xbd, 0x6f, 0xdf, 0x8c, 0xd6, 0xc7, 0x74, 0xb7, 0xbd, 0xdb, 0xc7, 0x0e, - 0x7d, 0x52, 0x4a, 0x89, 0x1b, 0x00, 0xce, 0x7d, 0xbe, 0x83, 0x49, 0xb6, 0xd9, 0x6b, 0x96, 0x0a, 0x9e, 0xab, 0xdd, - 0x9e, 0x30, 0x40, 0xdc, 0xcf, 0xb9, 0xde, 0x48, 0x18, 0xc1, 0x31, 0xe7, 0x75, 0xf3, 0x92, 0x64, 0xcc, 0x20, 0x8d, - 0x8d, 0xa1, 0x83, 0xba, 0xb6, 0x15, 0xb0, 0x20, 0xca, 0x89, 0x0b, 0x3e, 0x2d, 0x86, 0x0d, 0x22, 0x95, 0x19, 0x4d, - 0x44, 0x41, 0x35, 0x44, 0xf7, 0x72, 0xf0, 0xda, 0x81, 0x8e, 0x13, 0x07, 0x03, 0xe6, 0x5f, 0x7d, 0x02, 0xdb, 0xc7, - 0x0e, 0xb7, 0x07, 0x85, 0x38, 0xf6, 0x82, 0xa4, 0x22, 0x9d, 0xb6, 0x2e, 0x99, 0xeb, 0xe0, 0xad, 0xab, 0x96, 0x66, - 0x6f, 0xaa, 0x0f, 0xd4, 0xd7, 0xd0, 0xe3, 0x78, 0xea, 0xe7, 0x83, 0xb9, 0x03, 0xab, 0xa2, 0x2e, 0xca, 0x04, 0xc0, - 0x75, 0x6d, 0x28, 0x6d, 0x6b, 0x20, 0x60, 0x33, 0x79, 0x5a, 0x49, 0xe6, 0x0a, 0x2f, 0xe7, 0x66, 0xf3, 0x33, 0x9f, - 0x23, 0xf4, 0x9a, 0xf7, 0xab, 0xb7, 0xaa, 0xf6, 0x79, 0x69, 0x1e, 0x9e, 0xaa, 0x42, 0x05, 0xaa, 0x59, 0x67, 0xec, - 0x79, 0x06, 0x1b, 0x24, 0xc8, 0xd6, 0xb8, 0xed, 0xe3, 0xe1, 0x6f, 0x26, 0x16, 0xd3, 0x85, 0x6d, 0xe8, 0x25, 0x26, - 0x6f, 0xbf, 0xcb, 0x6c, 0x01, 0xa4, 0x48, 0x49, 0x7d, 0xc6, 0x97, 0x8c, 0x68, 0x52, 0xaf, 0x97, 0x5a, 0xd5, 0xf8, - 0x48, 0xab, 0x56, 0xfb, 0x07, 0x86, 0xac, 0x9f, 0x7f, 0xf4, 0x4f, 0xc6, 0x6e, 0x2f, 0xfe, 0x7d, 0xf3, 0xe4, 0xb5, - 0xdb, 0xc7, 0xd6, 0x62, 0xeb, 0x3f, 0x76, 0x26, 0xea, 0x86, 0x9e, 0xe7, 0xb5, 0x7f, 0xb7, 0x0a, 0x34, 0x78, 0x4f, - 0x85, 0x2f, 0x0c, 0x83, 0x3b, 0xf9, 0x66, 0x80, 0x17, 0x90, 0xad, 0xcc, 0xa2, 0xad, 0x83, 0x6b, 0x5c, 0xe3, 0xff, - 0xb8, 0x42, 0x8c, 0xe9, 0xa5, 0xda, 0x78, 0x80, 0xfe, 0xbc, 0xa3, 0xe5, 0xa6, 0xc1, 0xb7, 0x1d, 0x36, 0x65, 0x9e, - 0x89, 0x0b, 0xeb, 0x87, 0x75, 0x4a, 0x9a, 0x6b, 0x8e, 0xd7, 0x4d, 0xe7, 0xdd, 0x25, 0x8f, 0xa6, 0x30, 0xe0, 0x32, - 0x97, 0xa1, 0xdb, 0x5c, 0x38, 0x74, 0xbe, 0x89, 0xad, 0x9f, 0x54, 0xa2, 0xd2, 0x54, 0x02, 0x55, 0xfd, 0xda, 0x52, - 0x45, 0x19, 0xea, 0xd8, 0xfa, 0xb7, 0x0d, 0x2f, 0x56, 0xe5, 0xde, 0xc4, 0x03, 0xcc, 0xc8, 0x56, 0x20, 0x86, 0x0b, - 0x7e, 0x86, 0xa9, 0x35, 0xae, 0x1c, 0x68, 0xcc, 0x0e, 0xff, 0x8b, 0x48, 0x2a, 0x41, 0x40, 0x5b, 0x38, 0xd8, 0xc7, - 0xcc, 0xb8, 0x27, 0x3a, 0xa6, 0x0e, 0x3a, 0xb3, 0x93, 0x0f, 0x4e, 0x71, 0xf0, 0x5d, 0xbb, 0xdb, 0xa1, 0xdb, 0x0c, - 0xdb, 0x3b, 0x45, 0x4f, 0x9d, 0x14, 0x5b, 0x49, 0xe1, 0xae, 0xae, 0xa8, 0x1d, 0xe9, 0x74, 0xbe, 0x76, 0x57, 0x08, - 0x6a, 0x76, 0x05, 0xd1, 0x34, 0xbe, 0x36, 0x9e, 0x68, 0x72, 0xf0, 0x17, 0xfe, 0x25, 0x24, 0xf0, 0x65, 0x6f, 0x62, - 0x90, 0xbe, 0xce, 0xd0, 0x5d, 0xba, 0x8a, 0xee, 0x42, 0xba, 0xaa, 0x1f, 0x61, 0x15, 0xb3, 0x1f, 0xc1, 0x7d, 0xa2, - 0xf7, 0xe2, 0xcd, 0x86, 0xa1, 0xb1, 0xc2, 0x64, 0x68, 0x73, 0x1b, 0x32, 0xcc, 0xf9, 0x6d, 0x48, 0xd1, 0xc6, 0xa6, - 0x1b, 0x90, 0x57, 0xe4, 0x64, 0x76, 0x4d, 0x94, 0x4d, 0x97, 0x2e, 0x22, 0x38, 0x08, 0xf7, 0xa1, 0x9a, 0xd0, 0x9e, - 0x3d, 0x09, 0x3e, 0xcd, 0xca, 0x34, 0x61, 0xa9, 0xe6, 0x72, 0x5c, 0x20, 0x33, 0xd9, 0xc4, 0x00, 0xe6, 0xc3, 0xd8, - 0xe5, 0xb3, 0xc7, 0x1d, 0xd8, 0x7b, 0xb1, 0xe3, 0xa1, 0xdb, 0x1e, 0x94, 0xed, 0xa3, 0x83, 0xd5, 0xe7, 0xf3, 0xfe, - 0x2a, 0xb3, 0xdd, 0xeb, 0xbd, 0x74, 0x1b, 0x66, 0xe9, 0x31, 0xcf, 0x66, 0x8b, 0xa5, 0x9e, 0xdf, 0x20, 0xaf, 0x66, - 0xa7, 0x4a, 0x71, 0x29, 0x9e, 0x00, 0xf0, 0xbb, 0xac, 0xe1, 0x07, 0x92, 0x16, 0xcf, 0xea, 0xf4, 0xfc, 0x48, 0x9b, - 0xb6, 0x92, 0xc5, 0x10, 0x10, 0x9d, 0xca, 0x29, 0xea, 0xc6, 0xd6, 0x66, 0x50, 0xa4, 0xd3, 0xee, 0xcc, 0x66, 0x48, - 0xe1, 0x59, 0xf9, 0xcf, 0x66, 0xce, 0x3e, 0x74, 0xd2, 0xa0, 0xdc, 0x1e, 0x1c, 0xdc, 0x2a, 0x95, 0x49, 0x47, 0xa2, - 0xf0, 0x52, 0x51, 0x20, 0x44, 0x10, 0xe7, 0x41, 0xaf, 0xbc, 0xa4, 0x35, 0xa2, 0x62, 0x4d, 0x88, 0x1f, 0xb5, 0x06, - 0xd7, 0xe0, 0xd6, 0xfe, 0xf6, 0x3c, 0xc0, 0x0d, 0x1c, 0x72, 0x94, 0xf7, 0x29, 0xcf, 0x9b, 0xdc, 0xb1, 0xa2, 0xfb, - 0x89, 0xc1, 0x5c, 0x03, 0x03, 0x2a, 0x29, 0xdf, 0x2b, 0x6e, 0xc6, 0x98, 0x3f, 0xfd, 0x7e, 0x15, 0xc2, 0x4a, 0x7d, - 0xb1, 0xca, 0x61, 0x07, 0xe4, 0xdb, 0xaf, 0x20, 0x68, 0x51, 0x36, 0x51, 0xf8, 0x9a, 0xaf, 0xf0, 0xec, 0xd6, 0x66, - 0xa9, 0xff, 0xc7, 0x3d, 0x49, 0xcd, 0x5c, 0xfc, 0xbb, 0x4b, 0x47, 0x8d, 0x6f, 0x36, 0x7e, 0xa5, 0x5b, 0x99, 0xd5, - 0x48, 0x51, 0xd6, 0xae, 0xc9, 0x46, 0xf3, 0x33, 0x30, 0x4e, 0xd0, 0x8b, 0xaf, 0xd8, 0x81, 0x9f, 0x77, 0x49, 0xaa, - 0xd2, 0xad, 0xa5, 0x9f, 0xfb, 0x2b, 0xc9, 0x78, 0xca, 0xe8, 0x57, 0x19, 0x6e, 0x14, 0x34, 0x27, 0x5f, 0xfa, 0x3f, - 0x0c, 0xe0, 0x1d, 0x28, 0xc3, 0xd9, 0x0a, 0x7f, 0xad, 0xe3, 0x2e, 0x7e, 0xdd, 0x85, 0x9b, 0xf9, 0xb2, 0x11, 0x06, - 0xda, 0x43, 0x20, 0xa7, 0xea, 0xf7, 0x39, 0x9e, 0xb8, 0x0c, 0xd3, 0x99, 0x26, 0xbc, 0x8a, 0x82, 0xe5, 0xce, 0x7b, - 0xed, 0x9b, 0x34, 0x1b, 0x8f, 0x17, 0x24, 0x16, 0x27, 0x78, 0x45, 0xd8, 0xea, 0x42, 0xc9, 0xb7, 0xb9, 0x85, 0xa6, - 0xc0, 0x2b, 0xdd, 0xec, 0x41, 0xda, 0x2f, 0x93, 0x9d, 0x25, 0xab, 0x9e, 0x33, 0x84, 0x11, 0x1b, 0x7b, 0x74, 0x95, - 0x26, 0xf5, 0x59, 0x69, 0x8d, 0x36, 0x34, 0x63, 0x4d, 0xa7, 0xe6, 0x72, 0x40, 0xaa, 0x55, 0xb5, 0xc2, 0x59, 0x57, - 0xb9, 0xc0, 0x36, 0x73, 0x4a, 0xd1, 0x67, 0x07, 0x05, 0x9e, 0x25, 0xac, 0xeb, 0x1c, 0xb8, 0x86, 0x12, 0x0d, 0xce, - 0x6b, 0x76, 0xdb, 0x80, 0xac, 0x44, 0x7e, 0x61, 0x40, 0x09, 0x1b, 0x8f, 0x7f, 0xb1, 0x43, 0xf1, 0xed, 0xd9, 0x6a, - 0x19, 0xc1, 0xc8, 0x8a, 0x49, 0xfd, 0x9d, 0x23, 0xb1, 0x3f, 0x3f, 0xa3, 0xb4, 0xb7, 0x5c, 0x4c, 0xa8, 0x5b, 0x36, - 0xab, 0xd8, 0x6f, 0xa5, 0x84, 0xa3, 0x69, 0xaa, 0x96, 0x78, 0x7a, 0x1f, 0x29, 0xab, 0xd6, 0x5b, 0xc0, 0x06, 0x2d, - 0xaa, 0x36, 0x22, 0x5e, 0x30, 0x21, 0x7e, 0xff, 0xc1, 0x46, 0x80, 0x47, 0xa4, 0x64, 0xb2, 0xe5, 0x38, 0xab, 0x14, - 0xc3, 0xf9, 0xe6, 0x63, 0xb3, 0x5d, 0x4f, 0x58, 0xe4, 0x23, 0x8c, 0x58, 0xb7, 0x54, 0xc1, 0xba, 0x1f, 0xf6, 0x24, - 0xf5, 0xe8, 0x39, 0x3a, 0xc2, 0x61, 0x54, 0x41, 0x2b, 0x7a, 0x73, 0xf6, 0x0a, 0x49, 0x53, 0xc8, 0x44, 0x90, 0x7c, - 0x18, 0x97, 0x62, 0xc8, 0xad, 0x7d, 0x23, 0x4f, 0x95, 0xef, 0x1b, 0x30, 0x54, 0xde, 0xb7, 0x84, 0x26, 0xc8, 0x9a, - 0x9f, 0xa2, 0xa2, 0xe7, 0xce, 0x6e, 0x45, 0xb0, 0x5a, 0x74, 0x72, 0x52, 0x95, 0x69, 0x7e, 0x02, 0xa1, 0x65, 0x2e, - 0xc8, 0x66, 0xbf, 0xae, 0x86, 0xfc, 0xe8, 0xe4, 0xbc, 0x8d, 0x19, 0x67, 0x33, 0x64, 0x1b, 0x2b, 0xce, 0x94, 0xd3, - 0xe2, 0x5b, 0x73, 0xb7, 0x87, 0xbc, 0xec, 0xae, 0x03, 0x05, 0x0f, 0x87, 0x12, 0x9a, 0xf1, 0xe7, 0xea, 0x9f, 0x27, - 0x41, 0x55, 0xe5, 0x84, 0x36, 0xfe, 0x59, 0x7c, 0xc6, 0xe7, 0x6a, 0xc1, 0x97, 0x70, 0xd8, 0x31, 0x00, 0x54, 0x02, - 0xeb, 0x62, 0xa8, 0xfd, 0x54, 0x80, 0xdd, 0xef, 0x0d, 0x69, 0x7c, 0xef, 0x9c, 0xa4, 0x59, 0xd8, 0xc7, 0xae, 0xbd, - 0x69, 0x72, 0x90, 0xa3, 0xed, 0x5a, 0x85, 0x37, 0xea, 0xab, 0x3e, 0xd6, 0x33, 0xcb, 0xf0, 0x03, 0x08, 0x2d, 0xcd, - 0x25, 0x90, 0x63, 0x18, 0x83, 0x7e, 0xf1, 0xe6, 0x7f, 0xfd, 0x02, 0x5c, 0x40, 0xb0, 0x45, 0xc1, 0xf3, 0x6d, 0xaf, - 0x7c, 0xc2, 0xb4, 0x94, 0x4a, 0x21, 0x38, 0x67, 0xfd, 0x47, 0xb0, 0x21, 0x2e, 0xed, 0x4e, 0x6d, 0x32, 0x61, 0x38, - 0x25, 0x15, 0xd1, 0x06, 0x8d, 0xd9, 0xce, 0x73, 0x4e, 0xf3, 0x60, 0xf3, 0xcf, 0x82, 0x8b, 0x92, 0xef, 0x9b, 0x99, - 0x9e, 0x3d, 0x50, 0x75, 0xe6, 0xda, 0x6a, 0x7a, 0x82, 0x1e, 0xa4, 0xce, 0x5f, 0x8b, 0x65, 0xac, 0xee, 0x77, 0x4b, - 0x4a, 0x22, 0x1b, 0x13, 0x0a, 0x36, 0xb4, 0xa1, 0xbb, 0x26, 0x88, 0x39, 0x8d, 0x6b, 0xbb, 0x15, 0xfd, 0xde, 0x89, - 0x66, 0x20, 0xdd, 0x28, 0x87, 0x65, 0x98, 0x32, 0x84, 0xe4, 0x96, 0xf1, 0x1d, 0x59, 0x97, 0x5d, 0xd9, 0x58, 0x84, - 0xb2, 0x7f, 0xb7, 0xe5, 0x70, 0x4a, 0xa1, 0x6a, 0xd4, 0x17, 0x60, 0x48, 0x89, 0x69, 0x9b, 0x2c, 0x8b, 0xb8, 0xb3, - 0x05, 0x05, 0xcd, 0x94, 0x8d, 0x9d, 0xda, 0x75, 0x84, 0x21, 0x73, 0xf8, 0x35, 0xb2, 0x27, 0x1d, 0x99, 0xa7, 0xc8, - 0x65, 0x93, 0x9e, 0xf5, 0xfa, 0x73, 0x07, 0x28, 0x6c, 0x5f, 0xe0, 0x94, 0x3c, 0xcf, 0x69, 0xaa, 0xa1, 0x96, 0x1b, - 0xd2, 0x45, 0x51, 0x25, 0x38, 0x3a, 0x27, 0x78, 0x81, 0x23, 0x84, 0xca, 0x96, 0x92, 0xa0, 0x1e, 0x0f, 0xa1, 0x4a, - 0x24, 0x47, 0xc7, 0x09, 0xcc, 0x75, 0xbc, 0x9a, 0x6b, 0xfc, 0x37, 0x24, 0x8f, 0x36, 0x7e, 0x80, 0xb8, 0x96, 0xd9, - 0xc8, 0xc7, 0x43, 0x6a, 0x98, 0xc2, 0x58, 0x1f, 0x29, 0xf8, 0x6a, 0x1a, 0xc2, 0xa2, 0xc9, 0x40, 0x1a, 0x18, 0x9c, - 0x02, 0xff, 0x2d, 0x5c, 0x33, 0x56, 0x5e, 0xb9, 0x0e, 0x15, 0xab, 0xb4, 0x6b, 0xfa, 0x55, 0xff, 0xcc, 0xd8, 0x8b, - 0xa8, 0x6f, 0x77, 0x18, 0x7b, 0x96, 0x6a, 0x05, 0x3f, 0xcf, 0xb5, 0x61, 0x7c, 0x37, 0x74, 0x9a, 0x74, 0x9e, 0x53, - 0x5f, 0x39, 0x70, 0x51, 0x6c, 0xa2, 0x68, 0x33, 0x7a, 0x4d, 0x9d, 0x9a, 0x25, 0x9c, 0xea, 0xb8, 0x49, 0xb2, 0x2e, - 0x31, 0x8e, 0xa4, 0x17, 0xfb, 0xfa, 0x46, 0x63, 0xaa, 0x68, 0x25, 0xbe, 0x53, 0x51, 0xae, 0x80, 0xb3, 0x10, 0x84, - 0x56, 0xec, 0x89, 0x57, 0xcb, 0xca, 0x4a, 0x7c, 0xa4, 0x05, 0xf3, 0x46, 0x54, 0x20, 0xc8, 0x13, 0xd2, 0x3a, 0x71, - 0x27, 0x46, 0x66, 0x15, 0x72, 0xb7, 0x21, 0xc9, 0x08, 0x11, 0x5d, 0xb0, 0x97, 0xd0, 0xdb, 0xa5, 0xab, 0xb3, 0xa7, - 0x00, 0x2f, 0x10, 0x23, 0xfa, 0x07, 0xd3, 0xc2, 0x72, 0xd4, 0x4e, 0x94, 0xe8, 0x4e, 0xf6, 0x6f, 0x36, 0xff, 0x7e, - 0xac, 0x4a, 0x50, 0xa8, 0xbd, 0x0e, 0x01, 0xb3, 0x16, 0x93, 0x9e, 0xa4, 0x6d, 0x93, 0x02, 0x28, 0x96, 0xa0, 0x0d, - 0x7e, 0x5d, 0x0d, 0xa4, 0xbb, 0xf6, 0xde, 0x97, 0x46, 0x4c, 0xb8, 0x7c, 0x96, 0x92, 0x57, 0x19, 0xd5, 0x32, 0x7b, - 0xde, 0xb5, 0x17, 0x94, 0x96, 0xc0, 0xd5, 0x2f, 0x31, 0xa7, 0x3f, 0xef, 0x60, 0x46, 0x26, 0xc4, 0xb4, 0x67, 0xcc, - 0xcb, 0x66, 0x3d, 0xa6, 0xbe, 0xad, 0x63, 0xb1, 0xb5, 0x59, 0x3b, 0x7c, 0xf0, 0xc7, 0xd1, 0x9d, 0xa2, 0x35, 0xee, - 0x9f, 0xcb, 0x7f, 0xdb, 0x70, 0xdf, 0x7a, 0x67, 0xab, 0xd0, 0x5c, 0x5d, 0x27, 0xdb, 0xe8, 0xbe, 0x57, 0x3b, 0xc7, - 0x8a, 0x58, 0x7c, 0x1b, 0x63, 0xd7, 0x1d, 0xa0, 0xe3, 0xbb, 0x46, 0x81, 0xfb, 0x13, 0xd8, 0xe5, 0xf3, 0xe3, 0xf3, - 0x6a, 0x41, 0x8c, 0x23, 0xd9, 0x7a, 0x36, 0xf3, 0x0f, 0x97, 0x44, 0x77, 0xb7, 0xf4, 0x1e, 0x45, 0x20, 0xfa, 0x3e, - 0xa9, 0x97, 0x75, 0x26, 0xe3, 0x0b, 0xf2, 0xc8, 0xea, 0x15, 0xf8, 0xcd, 0x74, 0xd7, 0x1e, 0xdb, 0x89, 0x33, 0xc7, - 0xe6, 0x97, 0xcf, 0xf0, 0x48, 0x90, 0xe1, 0x9c, 0x21, 0xc6, 0x29, 0xea, 0xf8, 0x51, 0x2f, 0xe6, 0x4c, 0x3e, 0x92, - 0x02, 0xbe, 0xde, 0x74, 0x4e, 0x71, 0xa8, 0xa6, 0x30, 0x17, 0x1a, 0x4d, 0x3a, 0xb1, 0x8f, 0x14, 0x00, 0xda, 0x9e, - 0x98, 0x12, 0x33, 0x71, 0x39, 0xbd, 0x01, 0x75, 0xbd, 0x07, 0x29, 0x95, 0xf3, 0x17, 0x31, 0x99, 0x71, 0xea, 0x39, - 0x98, 0x55, 0x7d, 0x51, 0xcc, 0x3f, 0xc1, 0xcc, 0xd4, 0xa8, 0x4d, 0x01, 0x4f, 0x8b, 0x19, 0x35, 0x3d, 0xb6, 0xdf, - 0x08, 0x49, 0xda, 0x6b, 0x96, 0x70, 0xb1, 0x33, 0x3e, 0x77, 0x50, 0x0a, 0xff, 0x56, 0x01, 0x3c, 0xa3, 0xd5, 0x67, - 0x55, 0xf2, 0x1c, 0x50, 0x16, 0xc3, 0xf6, 0xa5, 0x17, 0x7b, 0x1a, 0x5f, 0x05, 0xd7, 0x9f, 0x15, 0xc4, 0x56, 0xfc, - 0xfb, 0x97, 0x9b, 0xbe, 0xae, 0xf6, 0x16, 0xa2, 0x4f, 0x9d, 0x85, 0x27, 0x27, 0xbc, 0xde, 0x09, 0xe2, 0x74, 0x83, - 0xfd, 0x29, 0x6b, 0x89, 0xc1, 0xc9, 0x82, 0x7f, 0x6c, 0x45, 0x11, 0xaa, 0x8e, 0xfa, 0x98, 0xc5, 0x9d, 0x84, 0x2c, - 0x2b, 0x18, 0x86, 0x91, 0x41, 0xa6, 0x03, 0xfc, 0xd9, 0x97, 0xea, 0x8b, 0x8b, 0x68, 0xe0, 0xa5, 0x35, 0xfb, 0x9d, - 0x4f, 0xe1, 0x58, 0xd1, 0x85, 0x4f, 0xe1, 0xa7, 0x77, 0xa1, 0x02, 0x6c, 0x7d, 0x2d, 0x93, 0x33, 0x49, 0xf4, 0x65, - 0xd8, 0x57, 0x0c, 0x97, 0x34, 0x25, 0x8f, 0xbb, 0xa8, 0x92, 0xf3, 0xbf, 0xca, 0x75, 0x3f, 0xa3, 0x2f, 0xa9, 0xc6, - 0x3a, 0x0a, 0x46, 0xdd, 0xd5, 0x36, 0xa5, 0x77, 0x9c, 0x29, 0x29, 0xca, 0xd5, 0x0b, 0x4d, 0xfb, 0xfa, 0x93, 0xab, - 0xaf, 0xf4, 0x55, 0xd2, 0x4e, 0x35, 0x7a, 0xc2, 0x4b, 0x75, 0xd3, 0x81, 0x7f, 0xcb, 0xc9, 0xbd, 0x78, 0x2b, 0x35, - 0xb2, 0x37, 0xfd, 0x0f, 0xb6, 0x5d, 0x93, 0x73, 0x25, 0x4e, 0xb9, 0x60, 0x07, 0xe5, 0xd0, 0xe5, 0x38, 0x9e, 0xc4, - 0xb6, 0x55, 0x34, 0x8a, 0x2d, 0xe5, 0x96, 0x05, 0xce, 0x8d, 0x79, 0x22, 0x13, 0x24, 0x6a, 0x19, 0xae, 0x19, 0x5e, - 0x53, 0x80, 0x70, 0xba, 0x94, 0xe0, 0x66, 0xc0, 0x74, 0xea, 0x76, 0x4c, 0xe4, 0x74, 0xec, 0x35, 0x7e, 0x68, 0x84, - 0x10, 0x95, 0x72, 0xbe, 0x4d, 0x19, 0x51, 0xf5, 0x59, 0x76, 0x57, 0xf2, 0x56, 0x29, 0xd1, 0xb6, 0xea, 0x98, 0x8b, - 0x72, 0x60, 0xd1, 0x0b, 0x06, 0xad, 0x9c, 0x39, 0x89, 0xf5, 0xe9, 0x39, 0x69, 0xe3, 0x7f, 0xd9, 0x89, 0x1d, 0xe6, - 0xc8, 0xfb, 0x28, 0x75, 0x67, 0x0c, 0xe2, 0x9b, 0x3a, 0x49, 0x82, 0xbe, 0xb8, 0xea, 0x06, 0x4e, 0x59, 0x9c, 0x9a, - 0x5a, 0x5d, 0x03, 0xb0, 0x45, 0x0b, 0xad, 0x3e, 0x50, 0xf5, 0x40, 0xec, 0x57, 0xb5, 0xc1, 0x5f, 0x2b, 0x5e, 0xa6, - 0xf3, 0xb4, 0x0f, 0x15, 0x6b, 0xa4, 0x03, 0x43, 0x0e, 0xee, 0x4c, 0xb0, 0x06, 0xa1, 0x40, 0xc9, 0xe2, 0x5c, 0xc9, - 0x23, 0x8c, 0x8d, 0xe3, 0x88, 0xb5, 0x04, 0xc5, 0x94, 0xb7, 0x7d, 0x60, 0x07, 0x17, 0x88, 0x6e, 0xc4, 0x85, 0x65, - 0x1b, 0x51, 0xb4, 0x20, 0x29, 0x4a, 0x8e, 0x15, 0xea, 0x05, 0xdf, 0x08, 0xb1, 0x18, 0xc0, 0x5c, 0xd2, 0x37, 0x8b, - 0x89, 0x82, 0x0a, 0xc6, 0xe1, 0x0d, 0xfe, 0x6d, 0xe2, 0x12, 0xa1, 0x2f, 0xc4, 0x6b, 0xe3, 0x5b, 0x32, 0x5f, 0x60, - 0x4f, 0xa7, 0x20, 0xeb, 0x25, 0xbe, 0xdd, 0x7c, 0xf6, 0x1b, 0x56, 0xbf, 0x81, 0xb9, 0x9a, 0x5f, 0x26, 0xce, 0x59, - 0x4d, 0x79, 0xe7, 0xba, 0x3d, 0xcb, 0x02, 0xcd, 0xd9, 0xf8, 0xde, 0xa1, 0x6a, 0x82, 0x66, 0x7c, 0x41, 0xd3, 0x9b, - 0x8b, 0xb1, 0x2e, 0xd0, 0xdf, 0x5b, 0xcd, 0x2d, 0x30, 0x89, 0x0b, 0xd6, 0x53, 0xde, 0xe7, 0xf7, 0xa6, 0x4d, 0x03, - 0xeb, 0xc5, 0x9c, 0x03, 0x34, 0x2f, 0xc3, 0xa7, 0xd3, 0x4a, 0x7b, 0x46, 0x93, 0x82, 0x3f, 0xdc, 0xe0, 0xd0, 0x32, - 0xed, 0xd7, 0xcf, 0x5e, 0xf4, 0xba, 0xe1, 0x5f, 0x2e, 0x03, 0x38, 0xea, 0x5f, 0x46, 0x42, 0xc7, 0xde, 0x19, 0xe7, - 0x56, 0x41, 0x1c, 0x8d, 0xb1, 0x21, 0xf4, 0x3f, 0x12, 0xe7, 0x33, 0x32, 0x78, 0x06, 0x76, 0x41, 0x05, 0x42, 0x92, - 0x7e, 0xb1, 0xa2, 0x39, 0x2c, 0x6f, 0x31, 0x6d, 0xd4, 0x72, 0xc1, 0xb4, 0x65, 0xb8, 0xc5, 0xcb, 0x56, 0x1b, 0x8b, - 0xea, 0xcb, 0xe7, 0xc2, 0x60, 0x12, 0x56, 0x91, 0xfb, 0x3f, 0xce, 0x00, 0xd4, 0x4f, 0x20, 0x79, 0x0c, 0x5b, 0xdf, - 0x2e, 0xfa, 0xd5, 0xb2, 0x40, 0xaf, 0xcc, 0x93, 0x0d, 0x5a, 0xe3, 0x32, 0x46, 0xd4, 0x85, 0xe9, 0x75, 0x6d, 0xae, - 0xa1, 0x7b, 0x63, 0x7d, 0x1a, 0x09, 0x7d, 0x07, 0x0b, 0xf1, 0xed, 0xc7, 0xb4, 0xd1, 0x71, 0x07, 0x71, 0x53, 0xd8, - 0x6f, 0x55, 0x9b, 0xc8, 0x59, 0xeb, 0xb9, 0x89, 0x82, 0xe2, 0x1a, 0x51, 0x7d, 0x93, 0x73, 0x87, 0x8f, 0x6e, 0xa2, - 0xa3, 0xf2, 0x1a, 0xef, 0x2d, 0xd5, 0xd4, 0xd7, 0x00, 0x2d, 0xd4, 0x1d, 0x6a, 0xa0, 0xe7, 0xc5, 0xab, 0x22, 0x02, - 0x9e, 0xa9, 0x73, 0xfc, 0x25, 0x2a, 0x78, 0x04, 0x1f, 0xcd, 0xab, 0x52, 0xaa, 0xda, 0x37, 0x21, 0xab, 0x83, 0x5c, - 0x93, 0x07, 0x7e, 0x48, 0x75, 0x1d, 0xde, 0x46, 0x01, 0x1a, 0x3c, 0xa2, 0x1a, 0x3c, 0xb2, 0xfe, 0xbc, 0x38, 0x4f, - 0x31, 0x7e, 0x3a, 0x05, 0x4b, 0x37, 0x02, 0x4b, 0x1b, 0xfb, 0xf2, 0xe2, 0xb0, 0xb9, 0x64, 0x55, 0x00, 0x92, 0x19, - 0xf5, 0x52, 0x2c, 0x7e, 0x26, 0x15, 0x9e, 0x37, 0xaa, 0xac, 0x6e, 0xb3, 0xa3, 0x8f, 0x74, 0x6e, 0x2b, 0x13, 0x10, - 0x0a, 0xfd, 0xfe, 0x91, 0x09, 0x95, 0x78, 0x55, 0x68, 0x04, 0x01, 0x7a, 0xab, 0xc1, 0x79, 0x35, 0xca, 0x7e, 0xfe, - 0x75, 0xeb, 0x3e, 0x2d, 0x5e, 0xa2, 0x61, 0x2f, 0xdd, 0xa8, 0xb1, 0xa0, 0x93, 0x60, 0x30, 0x25, 0x8c, 0x82, 0xdc, - 0x82, 0x76, 0xa4, 0x77, 0x12, 0xbd, 0x19, 0xa8, 0x4f, 0x0b, 0xaa, 0xfe, 0xdf, 0xee, 0xa7, 0x54, 0xf4, 0x13, 0x81, - 0x16, 0xf2, 0x64, 0xeb, 0x01, 0x5f, 0x1b, 0xbe, 0xc5, 0xf9, 0xab, 0x46, 0xba, 0x90, 0x5c, 0x52, 0x10, 0x1b, 0x99, - 0xb2, 0x19, 0x69, 0x90, 0x56, 0x3c, 0x73, 0x4d, 0xea, 0x42, 0x4a, 0xbb, 0x69, 0xf0, 0xb3, 0x95, 0xd7, 0x20, 0xd5, - 0xe4, 0xd1, 0x15, 0x6b, 0x2f, 0x6e, 0x5c, 0xc6, 0x1b, 0x67, 0xd7, 0x47, 0xb4, 0x2a, 0xb4, 0x2c, 0x54, 0x2b, 0xd2, - 0xa5, 0xd4, 0x77, 0x66, 0x79, 0x89, 0x00, 0xf6, 0x88, 0xbd, 0x0b, 0x17, 0xed, 0x9b, 0x65, 0x16, 0x39, 0xb0, 0xcd, - 0x3d, 0x0b, 0xdb, 0x5e, 0x1f, 0x12, 0xf9, 0x52, 0xfc, 0xcc, 0x8c, 0xea, 0x62, 0xd5, 0x34, 0x9f, 0x1d, 0x0c, 0x12, - 0xad, 0x36, 0x11, 0x67, 0xe2, 0xa4, 0x47, 0x20, 0x0a, 0x53, 0xa2, 0x9f, 0x45, 0xb1, 0x8c, 0x20, 0xfb, 0x47, 0xf6, - 0x86, 0x23, 0xdd, 0x84, 0x15, 0x87, 0xef, 0x01, 0xfb, 0x37, 0xfb, 0x6f, 0x1b, 0x46, 0x30, 0xad, 0xe0, 0xbc, 0x10, - 0x2c, 0x42, 0xe3, 0x2d, 0x86, 0x46, 0xb8, 0x9f, 0x04, 0x24, 0xde, 0x48, 0x71, 0x82, 0xfa, 0xdc, 0x8e, 0xaf, 0x5e, - 0x1d, 0xd2, 0x23, 0xcc, 0x50, 0x78, 0x36, 0xe5, 0x94, 0x67, 0xb0, 0x8f, 0xe7, 0xa2, 0xfb, 0x97, 0xea, 0x10, 0x1b, - 0x05, 0x47, 0xca, 0x52, 0xab, 0x42, 0xd6, 0x71, 0xdd, 0xbf, 0x5b, 0x1d, 0x73, 0x36, 0x36, 0x7d, 0xe5, 0x25, 0x0d, - 0x5a, 0x69, 0x48, 0xf4, 0x80, 0x1d, 0xe3, 0xd9, 0x86, 0x24, 0x3b, 0x56, 0x9a, 0x84, 0x18, 0xcd, 0x24, 0xd6, 0xc1, - 0xb4, 0x7f, 0xf4, 0xca, 0xb3, 0x56, 0xec, 0xba, 0xe6, 0x74, 0x6d, 0x06, 0xa9, 0xd0, 0x36, 0x22, 0xac, 0x26, 0xa6, - 0xbb, 0x88, 0x76, 0xfa, 0x33, 0x55, 0xbf, 0x1e, 0x29, 0xd3, 0xd8, 0x4f, 0x50, 0x28, 0x4f, 0xf0, 0x66, 0xbb, 0x2b, - 0x27, 0x77, 0x09, 0x00, 0x4d, 0xff, 0x72, 0xdd, 0x85, 0x73, 0xa6, 0x8a, 0x56, 0x3d, 0xf0, 0x69, 0xd2, 0x35, 0x2f, - 0xe1, 0x50, 0xcd, 0x68, 0x04, 0xe0, 0x3c, 0x09, 0xa1, 0xcb, 0xd9, 0x9e, 0x6b, 0x08, 0x9a, 0xd6, 0xf3, 0xb4, 0xce, - 0x9e, 0x11, 0x3d, 0xff, 0xa9, 0xcf, 0x7c, 0x21, 0x5d, 0x51, 0x14, 0xb5, 0x29, 0x6b, 0x8a, 0xa1, 0xa1, 0x8d, 0x33, - 0xb9, 0xe1, 0xb4, 0x8b, 0x16, 0x21, 0x9d, 0xd9, 0x4b, 0x7d, 0x8a, 0x75, 0xa5, 0xdb, 0xce, 0x06, 0x16, 0x96, 0x06, - 0x26, 0x50, 0x72, 0x54, 0x69, 0x71, 0x9d, 0x59, 0xbe, 0x54, 0x5b, 0xb7, 0x74, 0x9e, 0xcb, 0x17, 0x79, 0x1a, 0xc6, - 0xe7, 0x5f, 0x01, 0x77, 0x72, 0xe4, 0x02, 0xcb, 0xbc, 0xa2, 0x5a, 0x42, 0xfa, 0x94, 0x5f, 0xc3, 0x68, 0xe1, 0xb1, - 0xf1, 0xc0, 0xb4, 0xba, 0x7f, 0xb0, 0x54, 0x95, 0xf3, 0x82, 0xa9, 0x31, 0x8f, 0x49, 0x93, 0x02, 0x37, 0xb9, 0x0d, - 0xea, 0x4a, 0x0c, 0xb0, 0x4d, 0x91, 0x7f, 0xf2, 0xa3, 0x20, 0x43, 0x3c, 0x90, 0xd1, 0xa8, 0x06, 0xea, 0x34, 0x73, - 0xbc, 0xb3, 0x4b, 0x5d, 0xac, 0xda, 0xde, 0x82, 0x62, 0x78, 0x5b, 0xea, 0x82, 0xe1, 0x99, 0xe2, 0xa9, 0x84, 0x37, - 0xe5, 0x0a, 0xf6, 0xaf, 0x12, 0xa1, 0xa1, 0x72, 0xa1, 0xf6, 0xc3, 0x31, 0x6c, 0xb5, 0x0b, 0x81, 0xd2, 0x6f, 0x1a, - 0x1a, 0x85, 0x86, 0xac, 0x57, 0xcd, 0xab, 0xba, 0xb7, 0x79, 0xab, 0x36, 0x84, 0xa1, 0x29, 0xd2, 0xb9, 0x60, 0xdb, - 0xc5, 0x1e, 0xee, 0xff, 0x14, 0x43, 0x11, 0x52, 0x2b, 0xe7, 0xe2, 0x43, 0x3e, 0xee, 0x20, 0x60, 0x7e, 0x52, 0x0f, - 0xfe, 0xfa, 0xa3, 0x30, 0xe4, 0x7f, 0x56, 0x7a, 0xa0, 0xe2, 0x87, 0xfd, 0x22, 0xfc, 0x2a, 0xf3, 0xb7, 0x86, 0x94, - 0x93, 0x77, 0x7d, 0xdb, 0x05, 0x00, 0x2d, 0x5f, 0xc8, 0x81, 0xbc, 0xeb, 0xcc, 0x8d, 0x91, 0xb5, 0x6d, 0x32, 0xaf, - 0xd6, 0xf1, 0x2b, 0x81, 0x82, 0xd8, 0xf8, 0x2d, 0x94, 0xfd, 0xd9, 0x90, 0x1b, 0xfe, 0xc3, 0xc1, 0xdc, 0x52, 0x42, - 0x57, 0x59, 0x93, 0x53, 0xca, 0x0e, 0x19, 0x01, 0xd2, 0x08, 0x1c, 0x47, 0x3e, 0x33, 0xa0, 0xbf, 0x8d, 0x2b, 0xfa, - 0xe9, 0x15, 0xb7, 0xa1, 0x58, 0x4d, 0x4f, 0x75, 0x8d, 0x90, 0x87, 0xe9, 0x42, 0x76, 0x33, 0xa1, 0x89, 0x58, 0x38, - 0x2e, 0x47, 0x02, 0xd9, 0x9b, 0xc8, 0x74, 0x02, 0x2d, 0xd8, 0x9a, 0xe5, 0xd6, 0x48, 0xae, 0x6a, 0x2b, 0xa7, 0xcb, - 0xfa, 0xe4, 0x48, 0xea, 0x55, 0x81, 0x1b, 0x79, 0xeb, 0x7c, 0x51, 0x67, 0x47, 0x45, 0xa5, 0x67, 0xc8, 0xdb, 0xdc, - 0xc2, 0x89, 0xe5, 0x93, 0xe2, 0x37, 0x9c, 0xe4, 0xee, 0xd5, 0x7a, 0xa0, 0x48, 0xc2, 0x54, 0x28, 0xb3, 0x17, 0x39, - 0xdb, 0x6e, 0xf4, 0xe0, 0xbd, 0xa5, 0xa0, 0x57, 0x90, 0x0d, 0xb6, 0xdc, 0x5d, 0xdd, 0x29, 0xbd, 0xc0, 0xb3, 0x12, - 0x4e, 0x9b, 0x71, 0xed, 0x85, 0x46, 0x66, 0x49, 0x96, 0x90, 0xf6, 0xbf, 0xba, 0xc7, 0x90, 0x58, 0x5e, 0x6e, 0xc4, - 0xbe, 0xf9, 0xba, 0x0b, 0x43, 0xc9, 0x42, 0x87, 0x0f, 0xec, 0xc1, 0x7b, 0x4c, 0xc5, 0x9b, 0xae, 0x06, 0x3c, 0xf4, - 0x20, 0xa1, 0x94, 0xef, 0xa2, 0xd4, 0xc7, 0xdf, 0x30, 0x7d, 0x7d, 0xef, 0x56, 0x6c, 0xf6, 0x80, 0x17, 0x81, 0x81, - 0xd1, 0xb3, 0x6d, 0xd2, 0xe3, 0x53, 0xd7, 0x11, 0xaa, 0x06, 0x5c, 0xcd, 0xbf, 0xee, 0xa4, 0x37, 0xbb, 0x7d, 0x1a, - 0xf7, 0x76, 0x3f, 0xc4, 0xef, 0x65, 0x63, 0x2a, 0x0f, 0xf5, 0x44, 0xb1, 0xae, 0xcf, 0x5b, 0x62, 0x44, 0x11, 0x27, - 0x1e, 0xd6, 0x7d, 0x6e, 0x54, 0x67, 0x1d, 0x49, 0xf7, 0x6e, 0xc0, 0x8e, 0x92, 0x36, 0x9d, 0x7d, 0xda, 0xe9, 0xb2, - 0x7c, 0x4d, 0x6b, 0x0f, 0x5f, 0x1f, 0x78, 0xe9, 0x36, 0xbf, 0xee, 0x14, 0xb5, 0x31, 0xdb, 0xa2, 0xc9, 0xba, 0xbe, - 0xe3, 0xe2, 0x45, 0xf3, 0xe2, 0x47, 0xcd, 0x6d, 0x55, 0x1d, 0x99, 0x16, 0xb3, 0x7c, 0x9e, 0x0f, 0x90, 0xfc, 0x3e, - 0x3d, 0x05, 0x27, 0x4f, 0xf1, 0xdb, 0xee, 0x1b, 0xde, 0x82, 0x8f, 0xee, 0x5e, 0x8d, 0x4b, 0x59, 0xef, 0x3f, 0xf3, - 0x5b, 0x5e, 0x62, 0xfd, 0xa2, 0x6a, 0xdb, 0xab, 0x41, 0x51, 0xda, 0xd4, 0xfb, 0x2d, 0xff, 0xbc, 0x33, 0x43, 0x46, - 0xfe, 0x99, 0xda, 0xd9, 0x64, 0x2c, 0x01, 0xf4, 0x5f, 0x95, 0xaa, 0x9d, 0x59, 0xe0, 0x8d, 0x67, 0x30, 0x11, 0x0f, - 0x04, 0xaa, 0x5f, 0x50, 0xc8, 0x4c, 0xf1, 0x9d, 0xc6, 0x80, 0xf7, 0x78, 0x74, 0x2a, 0x3c, 0x5e, 0xf6, 0x7e, 0x15, - 0xe3, 0xe0, 0x19, 0x46, 0xec, 0xf6, 0x3f, 0x0e, 0xa2, 0x40, 0x2a, 0x1c, 0x0c, 0xd2, 0x15, 0xce, 0x74, 0xfc, 0xc9, - 0xc0, 0xfe, 0x25, 0xfd, 0x53, 0x75, 0x86, 0xf1, 0x31, 0xbe, 0x72, 0x63, 0xd4, 0x12, 0x5f, 0xa2, 0x7d, 0x9b, 0x2c, - 0xc2, 0xda, 0xf3, 0x64, 0xaf, 0xee, 0xf2, 0x6a, 0x83, 0x88, 0xea, 0xc9, 0x64, 0x79, 0xdc, 0xac, 0x22, 0x4c, 0x00, - 0x45, 0xaa, 0x97, 0x07, 0x2e, 0x43, 0x7e, 0x9f, 0x3f, 0x3f, 0x21, 0xce, 0x2d, 0x9e, 0x11, 0x3f, 0x98, 0x4f, 0x4e, - 0xf8, 0xa8, 0x7b, 0x6d, 0xfd, 0x6d, 0x22, 0x80, 0x2e, 0x99, 0xda, 0x36, 0x39, 0x60, 0x38, 0x70, 0x90, 0xf4, 0xee, - 0xf0, 0xe6, 0x5f, 0x0d, 0x41, 0x28, 0x5f, 0xad, 0x60, 0x69, 0xf5, 0x27, 0x88, 0xd9, 0xd2, 0x98, 0x84, 0x9c, 0x40, - 0x10, 0xae, 0x8d, 0x8f, 0x1d, 0x64, 0x1e, 0xd8, 0x54, 0x0b, 0x2c, 0x2d, 0x39, 0x05, 0xa2, 0x36, 0xee, 0x55, 0xcd, - 0xbd, 0x48, 0x73, 0x32, 0xca, 0xd4, 0xe6, 0x19, 0xab, 0xd6, 0x52, 0x4d, 0x06, 0xfe, 0xc3, 0xbc, 0xc6, 0xfe, 0xac, - 0x70, 0x41, 0x5f, 0xba, 0x79, 0x72, 0xf0, 0xb0, 0x48, 0x30, 0x07, 0x1f, 0x05, 0x30, 0x94, 0x11, 0xfc, 0xa7, 0x96, - 0x5b, 0x39, 0x8f, 0x81, 0x77, 0x28, 0xa9, 0x6a, 0xb1, 0xfb, 0xd2, 0x68, 0x06, 0xce, 0xca, 0xe8, 0x07, 0xf2, 0xbd, - 0xe4, 0x16, 0xf6, 0xf1, 0x23, 0x5f, 0xd0, 0x76, 0x94, 0x33, 0x55, 0x24, 0x54, 0x8d, 0xf7, 0xb6, 0x7f, 0xcb, 0x8a, - 0xfe, 0x95, 0xf7, 0x97, 0x72, 0xc6, 0xab, 0x02, 0x9f, 0x78, 0xc6, 0xa7, 0xf9, 0x72, 0x5a, 0x3c, 0x2a, 0xae, 0x58, - 0x48, 0xb2, 0xa8, 0xf2, 0xd0, 0xeb, 0x3f, 0x89, 0x15, 0x0a, 0x5e, 0xd1, 0xd9, 0x0a, 0x60, 0x8b, 0x18, 0x1d, 0x54, - 0x2a, 0xab, 0x7d, 0x95, 0x47, 0xc6, 0xbc, 0x79, 0xe7, 0x47, 0x61, 0x80, 0x5c, 0xb6, 0xa1, 0xaa, 0x7b, 0x2a, 0xfa, - 0x1a, 0x52, 0x61, 0xd9, 0x8a, 0x4d, 0xef, 0x19, 0x9e, 0x3a, 0x98, 0x7c, 0x4f, 0x2c, 0x77, 0x1f, 0x50, 0x1c, 0xc6, - 0x9a, 0x53, 0xaa, 0x2a, 0x33, 0x3e, 0x8f, 0x9c, 0x7e, 0x3e, 0x85, 0x67, 0xf4, 0x58, 0x64, 0xab, 0xbf, 0xe6, 0xc3, - 0x5a, 0xd8, 0xc2, 0xb7, 0x85, 0x50, 0x83, 0x5e, 0xe8, 0x05, 0xd7, 0xeb, 0x4b, 0x38, 0x88, 0x99, 0x11, 0x37, 0xef, - 0x6b, 0x93, 0x08, 0x64, 0xfd, 0x6c, 0xc4, 0x35, 0xd9, 0xfa, 0xc2, 0xc2, 0x7e, 0x8b, 0xf0, 0x8d, 0x84, 0xe8, 0x4f, - 0xe4, 0x31, 0xeb, 0x07, 0xc9, 0x74, 0xdd, 0x4e, 0x4e, 0xd5, 0x3f, 0x14, 0xf0, 0x6a, 0xc4, 0xfd, 0x15, 0x10, 0x3e, - 0x1f, 0xcb, 0xf5, 0x38, 0x13, 0x04, 0x05, 0x8f, 0xb5, 0x0a, 0x42, 0x79, 0x1b, 0xb5, 0x25, 0xb4, 0xde, 0x2a, 0x08, - 0x60, 0x33, 0xd6, 0xb1, 0x8b, 0x9f, 0x8e, 0xa5, 0x3f, 0x97, 0xfb, 0x3b, 0xa7, 0xf4, 0xc0, 0x8d, 0x0b, 0x0f, 0xf0, - 0x85, 0xef, 0x11, 0xbb, 0xd0, 0x88, 0x67, 0x0d, 0x62, 0x3f, 0x8e, 0xb7, 0x9a, 0xde, 0xd6, 0xa9, 0x76, 0xd8, 0x5c, - 0xa1, 0x54, 0x57, 0xde, 0x4b, 0x78, 0x1b, 0xe6, 0x3c, 0x4f, 0x22, 0xcf, 0x8f, 0x62, 0x1e, 0x38, 0xae, 0x94, 0xc4, - 0x99, 0x94, 0x86, 0xe0, 0xc7, 0x51, 0x27, 0x58, 0xf9, 0x31, 0x33, 0xf6, 0x59, 0x58, 0xdf, 0xf7, 0x0c, 0x3b, 0xf6, - 0x27, 0x5e, 0x07, 0x47, 0x27, 0x2c, 0xa7, 0xe6, 0x66, 0x07, 0xc6, 0x4f, 0x81, 0x2a, 0x4f, 0x08, 0xc2, 0xd6, 0xac, - 0xdc, 0x9b, 0xdc, 0xbe, 0xee, 0x12, 0xa2, 0xd9, 0x10, 0x55, 0x8f, 0x5d, 0xe0, 0xea, 0x65, 0x49, 0xa5, 0x2a, 0xd5, - 0x53, 0x85, 0x0a, 0x43, 0x6b, 0xb5, 0x2d, 0x66, 0x9c, 0xde, 0xbb, 0x11, 0x5c, 0xb8, 0x34, 0xd2, 0x0c, 0x2f, 0x04, - 0x16, 0x58, 0x3b, 0x3d, 0x55, 0xca, 0x68, 0xa5, 0x50, 0x17, 0xf5, 0x79, 0x5c, 0xbf, 0x86, 0x2e, 0x7b, 0xe1, 0x4d, - 0x65, 0x6d, 0x53, 0x34, 0x2c, 0xd8, 0x86, 0x89, 0xae, 0xd3, 0x95, 0xba, 0x9c, 0x7d, 0xf4, 0x57, 0xf5, 0x8c, 0xe6, - 0x58, 0x75, 0xec, 0x49, 0x08, 0xb5, 0x50, 0x83, 0x42, 0xa4, 0xd7, 0xdb, 0x01, 0x88, 0xdc, 0x13, 0xd2, 0xe0, 0x1c, - 0x0b, 0x36, 0x92, 0xed, 0x5c, 0xc1, 0xa6, 0xcd, 0x01, 0x71, 0xe2, 0xe7, 0x7e, 0x10, 0x07, 0x3e, 0x69, 0x43, 0x9a, - 0xf3, 0xb8, 0xfd, 0xd2, 0xdd, 0x1e, 0x58, 0xc9, 0x53, 0x56, 0x28, 0x32, 0x66, 0xbb, 0xab, 0x42, 0x4c, 0x7e, 0x4e, - 0xa6, 0x1e, 0x7c, 0x37, 0x60, 0xfd, 0xab, 0xe1, 0xcc, 0x09, 0xaf, 0x4b, 0x91, 0x45, 0x11, 0x64, 0xff, 0x3a, 0x8e, - 0x1c, 0x01, 0xec, 0x17, 0x5c, 0xa7, 0x58, 0xf7, 0x2d, 0xd5, 0x7c, 0x69, 0xa5, 0xc4, 0xcb, 0xfb, 0xa9, 0xc4, 0x8e, - 0x45, 0xc1, 0x07, 0x01, 0x69, 0xb0, 0xe2, 0xe3, 0x38, 0x06, 0x34, 0x95, 0x0d, 0xb8, 0xee, 0x61, 0x86, 0x15, 0xa5, - 0xdb, 0x3d, 0xbe, 0x8f, 0x4f, 0x71, 0x42, 0xc0, 0x1f, 0x9d, 0x39, 0x58, 0xa4, 0x15, 0x6c, 0xe9, 0x71, 0x78, 0x71, - 0xb0, 0xea, 0x69, 0x9b, 0xa4, 0xb8, 0xe6, 0xc7, 0x6f, 0x8e, 0xd5, 0x5c, 0xb6, 0x34, 0x6b, 0xbd, 0x74, 0xf7, 0xc7, - 0x8b, 0x03, 0x6a, 0x2b, 0x6c, 0x64, 0x81, 0xa8, 0x06, 0x15, 0xb4, 0x0e, 0xb2, 0xaf, 0xd3, 0x4e, 0xa9, 0x81, 0x66, - 0xb4, 0x98, 0xca, 0x3e, 0xa9, 0xe7, 0x93, 0xb1, 0xb5, 0x68, 0x3c, 0xad, 0xc3, 0x26, 0xec, 0x98, 0x9c, 0xa7, 0x60, - 0x64, 0x92, 0xe2, 0xb9, 0x9c, 0xe1, 0x33, 0x0a, 0x20, 0x8a, 0xba, 0x2a, 0x01, 0x5a, 0x5d, 0x28, 0xf6, 0xda, 0x98, - 0x29, 0x01, 0x52, 0xe1, 0xcf, 0x2b, 0xad, 0xcb, 0x08, 0xc5, 0x91, 0xd7, 0x36, 0xaf, 0x34, 0x5f, 0x27, 0xb4, 0x0e, - 0x71, 0xec, 0xf5, 0x64, 0xbd, 0xad, 0x60, 0x0a, 0x50, 0x43, 0x86, 0xae, 0xa9, 0x03, 0xbe, 0xfb, 0xdd, 0x0c, 0x80, - 0x3f, 0x88, 0x3c, 0xb2, 0x4e, 0x34, 0x1b, 0x1e, 0x92, 0x47, 0xc0, 0xd9, 0x43, 0xe5, 0x2a, 0xae, 0xac, 0xec, 0x62, - 0xdd, 0x16, 0xb8, 0x57, 0xb2, 0xf1, 0x65, 0x13, 0xe4, 0x94, 0x3d, 0x67, 0xa9, 0x65, 0x43, 0xc4, 0x81, 0x4a, 0x52, - 0x9b, 0x6c, 0xb0, 0x94, 0x66, 0xf3, 0x2d, 0x2a, 0xcd, 0xf5, 0xd6, 0xf9, 0xc7, 0x80, 0x34, 0x9a, 0xab, 0xd2, 0xdc, - 0x01, 0x0a, 0x00, 0x93, 0x76, 0xf1, 0x4c, 0x93, 0x23, 0x0a, 0x51, 0x58, 0xc0, 0xa0, 0x82, 0xab, 0xb1, 0x77, 0xd4, - 0xec, 0xcc, 0x0e, 0x80, 0x1d, 0x77, 0x75, 0x2b, 0x76, 0xa9, 0x60, 0xbc, 0x89, 0x81, 0xea, 0x57, 0xe3, 0x40, 0xd1, - 0xa6, 0xa3, 0xcb, 0xa2, 0xe8, 0x42, 0x32, 0x57, 0x97, 0x2a, 0x4f, 0xf0, 0x10, 0x95, 0x29, 0x36, 0x6a, 0x22, 0x1c, - 0x40, 0xae, 0x57, 0xbe, 0x6e, 0x7c, 0xad, 0xe3, 0xeb, 0x41, 0x10, 0x70, 0x3f, 0x91, 0x34, 0x92, 0x80, 0x8d, 0xbc, - 0xc2, 0x3e, 0xae, 0x40, 0x5f, 0x7c, 0x6a, 0x2b, 0x72, 0x72, 0xa9, 0xd7, 0x92, 0xc9, 0x92, 0xd5, 0x6c, 0x7f, 0x93, - 0x13, 0x84, 0x3e, 0x25, 0x29, 0x85, 0x9c, 0x4e, 0x77, 0x50, 0x75, 0xc8, 0xe3, 0x75, 0x2c, 0x60, 0x92, 0x8d, 0x5e, - 0xba, 0xad, 0x2d, 0xac, 0xb9, 0x10, 0xde, 0x28, 0x1b, 0x61, 0x4e, 0xac, 0x2b, 0x52, 0xf3, 0x0b, 0x34, 0x5e, 0xbc, - 0xf1, 0x57, 0x2c, 0xb4, 0x7e, 0xe0, 0x2b, 0xd5, 0x89, 0x65, 0xb1, 0x9b, 0x39, 0x19, 0x2a, 0x25, 0x8b, 0xdb, 0xad, - 0x75, 0x08, 0x91, 0xa7, 0x49, 0x9b, 0x81, 0x5c, 0x02, 0x16, 0xc1, 0x13, 0x44, 0x58, 0x74, 0x18, 0x0a, 0x9b, 0xe6, - 0x3a, 0x7e, 0x1e, 0x3e, 0x9a, 0x10, 0x4b, 0xed, 0x8a, 0xa5, 0x25, 0x11, 0x7e, 0xf8, 0xcd, 0x36, 0x56, 0x89, 0xba, - 0xb5, 0x30, 0x49, 0x58, 0x9a, 0xde, 0xfb, 0x45, 0xdd, 0xa5, 0xaf, 0x80, 0x74, 0x58, 0x86, 0xad, 0x88, 0xdd, 0x8b, - 0xd1, 0xdd, 0xb8, 0x04, 0x48, 0x38, 0x92, 0x4e, 0x0a, 0xcd, 0x4b, 0x4a, 0xca, 0xcf, 0x5c, 0xdd, 0xa8, 0xd2, 0x0c, - 0xa2, 0x94, 0xf3, 0x3a, 0x51, 0x68, 0xb9, 0x27, 0x36, 0x09, 0x11, 0x19, 0x3e, 0x2f, 0x12, 0xe4, 0xad, 0xd6, 0x6f, - 0x7b, 0xe8, 0x20, 0xc0, 0x86, 0x4e, 0x01, 0x7a, 0x8c, 0x92, 0x61, 0x10, 0x98, 0x0d, 0x85, 0x3d, 0x1b, 0x54, 0x94, - 0x20, 0xb4, 0x2d, 0x98, 0x13, 0xa1, 0xcb, 0x37, 0x99, 0x66, 0x98, 0xfc, 0x3c, 0xed, 0xf2, 0xf1, 0xdd, 0x19, 0x2e, - 0x8f, 0x95, 0x77, 0x36, 0x9a, 0xf7, 0x80, 0xf4, 0x9c, 0xb4, 0xe9, 0xa1, 0x34, 0x51, 0x7a, 0x0f, 0x51, 0x4f, 0x0e, - 0xaf, 0x09, 0x56, 0xa1, 0x25, 0x4c, 0x8d, 0xe9, 0x56, 0xbb, 0xfb, 0x42, 0xa2, 0x77, 0x6d, 0xae, 0x10, 0xa5, 0xb5, - 0x1b, 0x6a, 0xb5, 0x87, 0xe6, 0x99, 0xa4, 0x79, 0xda, 0x95, 0xfa, 0x8e, 0x6b, 0x0a, 0x70, 0xda, 0x66, 0x7d, 0x4e, - 0xa0, 0x35, 0x00, 0x2d, 0x48, 0x0d, 0x12, 0x23, 0xe8, 0x89, 0x31, 0x4f, 0xc5, 0xde, 0x38, 0x5f, 0x53, 0x64, 0x15, - 0x13, 0x9a, 0x04, 0xbc, 0xed, 0xbd, 0x84, 0x70, 0x06, 0x81, 0x90, 0x48, 0xc7, 0xa3, 0x14, 0xab, 0xee, 0x17, 0xef, - 0x24, 0xc2, 0x96, 0x13, 0x35, 0x8c, 0x10, 0xce, 0x41, 0x83, 0x58, 0x80, 0x0a, 0x53, 0x1a, 0x06, 0x87, 0x01, 0x6b, - 0x06, 0x19, 0xd0, 0x79, 0x2b, 0xa5, 0x48, 0xb8, 0x20, 0x87, 0x44, 0xd1, 0x77, 0x25, 0xc4, 0x21, 0x2b, 0x72, 0x69, - 0xa0, 0xda, 0x3b, 0x18, 0x8d, 0x37, 0xe3, 0xb4, 0x94, 0x2e, 0x71, 0x46, 0x7d, 0x8c, 0x62, 0xa6, 0x80, 0x73, 0xfb, - 0x11, 0x73, 0xdd, 0x8d, 0xc8, 0xc5, 0xd0, 0xc7, 0x75, 0x5b, 0x69, 0x89, 0xeb, 0xe1, 0x9c, 0x22, 0x41, 0x15, 0x8d, - 0x0a, 0x6e, 0x1b, 0x85, 0xc8, 0x4e, 0x5d, 0x30, 0xaa, 0x42, 0x88, 0xc4, 0x10, 0xd5, 0x56, 0x85, 0xc5, 0x15, 0xb7, - 0x98, 0x24, 0xcc, 0x38, 0x8b, 0x88, 0x16, 0xf0, 0x3c, 0xdb, 0xff, 0x29, 0x8a, 0xde, 0x3c, 0xf2, 0x05, 0x55, 0xa0, - 0xff, 0xf6, 0x04, 0x63, 0xfc, 0xf8, 0xd6, 0x0f, 0x1f, 0xf7, 0x14, 0x4f, 0x3f, 0xef, 0xa9, 0x5f, 0x7f, 0xe2, 0xe3, - 0x48, 0x9e, 0xf1, 0x8b, 0xfd, 0x5b, 0x0c, 0x96, 0x19, 0x30, 0x65, 0x05, 0xcb, 0xfe, 0x6e, 0x65, 0x7a, 0xe7, 0x84, - 0x9c, 0xb6, 0xe1, 0x62, 0xcb, 0x78, 0x6c, 0x75, 0xb2, 0x06, 0x2a, 0xb2, 0x38, 0x56, 0xb0, 0x32, 0xcb, 0xd7, 0x3c, - 0xd7, 0x67, 0x97, 0xde, 0x9e, 0xb8, 0x23, 0x51, 0x25, 0x77, 0x1e, 0x80, 0x93, 0x92, 0xf5, 0xa3, 0x6f, 0x23, 0xff, - 0x11, 0xd5, 0x6e, 0x3b, 0x28, 0x11, 0x4a, 0x2c, 0xc9, 0x7e, 0x55, 0x5a, 0xd3, 0xaf, 0xb7, 0x98, 0xb3, 0xa6, 0x96, - 0x1b, 0x86, 0x87, 0x51, 0xfe, 0x48, 0xbe, 0xdc, 0xb1, 0x3e, 0x34, 0x8d, 0xe7, 0xe4, 0x69, 0xe8, 0xa5, 0x8b, 0x88, - 0x55, 0x58, 0xd0, 0xff, 0xab, 0xa7, 0xff, 0xbf, 0x18, 0x24, 0xd2, 0xe1, 0xb7, 0x41, 0x8f, 0x37, 0x0c, 0x10, 0x93, - 0x73, 0xbe, 0xd1, 0xc7, 0x3b, 0xf1, 0xaf, 0x3c, 0xcc, 0x9f, 0xb3, 0xfd, 0xdd, 0xe0, 0xef, 0xeb, 0xb2, 0xef, 0xfa, - 0xb5, 0x69, 0x0b, 0x69, 0x37, 0x48, 0xe3, 0x95, 0x1a, 0x13, 0x34, 0xab, 0xc6, 0x91, 0xd1, 0x54, 0x8f, 0x47, 0x55, - 0x88, 0xac, 0x29, 0xc7, 0x4e, 0x7f, 0x08, 0x3a, 0x28, 0x78, 0x1c, 0x0d, 0x95, 0xe5, 0x99, 0x34, 0x47, 0xb5, 0x0d, - 0x4c, 0xf6, 0x66, 0xd4, 0x56, 0x2c, 0x16, 0xd6, 0xd6, 0x6c, 0xe2, 0xd9, 0xa3, 0xf1, 0xae, 0x56, 0xc6, 0xc6, 0x03, - 0xa9, 0x27, 0x17, 0xa7, 0x19, 0x91, 0x58, 0x8c, 0x91, 0x6d, 0xb9, 0xa9, 0x2f, 0x7b, 0xe5, 0x2d, 0xfa, 0xf3, 0x8a, - 0x3f, 0x9a, 0x9b, 0xba, 0x88, 0x51, 0xaf, 0x07, 0xdd, 0x1f, 0x9e, 0x2b, 0x71, 0x71, 0x58, 0xec, 0x7c, 0x8d, 0x0f, - 0x87, 0x1d, 0xbf, 0xda, 0x9c, 0x63, 0xea, 0x25, 0xc1, 0x86, 0x7e, 0x1a, 0x1c, 0xcd, 0xfd, 0xa3, 0xc1, 0x15, 0x03, - 0x7a, 0x20, 0x95, 0x9b, 0x22, 0xcd, 0x08, 0x30, 0x51, 0x3c, 0xd6, 0x5c, 0xaf, 0x73, 0x0f, 0xf1, 0xd5, 0xb6, 0x40, - 0x62, 0xc4, 0xe9, 0xf4, 0x62, 0x48, 0x24, 0x98, 0x98, 0x9e, 0xd2, 0x5e, 0x5c, 0x3e, 0x19, 0xde, 0x22, 0x3a, 0x1b, - 0xd7, 0xde, 0xde, 0xf9, 0xcc, 0x77, 0x89, 0x6b, 0x7c, 0x61, 0xb9, 0xcc, 0x2e, 0x30, 0x8d, 0x78, 0x0d, 0x54, 0x88, - 0x71, 0x60, 0x28, 0x7e, 0x82, 0xfe, 0x72, 0x21, 0x02, 0xb5, 0xcc, 0x68, 0x97, 0xb6, 0x37, 0x69, 0xec, 0xd8, 0x79, - 0x2e, 0x77, 0x09, 0x94, 0x38, 0x2e, 0x52, 0x6b, 0xbe, 0x73, 0x3f, 0x38, 0xd6, 0x85, 0xe1, 0xbe, 0x6e, 0xa3, 0xe4, - 0xdb, 0xca, 0xa9, 0x6e, 0x79, 0x14, 0xee, 0x88, 0xe1, 0x68, 0x6c, 0x53, 0xfa, 0x99, 0x2d, 0x72, 0xa3, 0x7c, 0xd2, - 0x0b, 0x51, 0xfe, 0x04, 0xd8, 0x9a, 0xe1, 0x2e, 0x58, 0xaf, 0xcf, 0x01, 0xa2, 0xae, 0xae, 0xd6, 0xf6, 0x7c, 0x31, - 0xfa, 0x5d, 0xe1, 0xde, 0xf2, 0x20, 0xc1, 0x98, 0xb6, 0x39, 0x9e, 0xc8, 0xbe, 0x72, 0x5a, 0x09, 0x5d, 0xe7, 0xe0, - 0x34, 0x71, 0x7f, 0x3c, 0x87, 0x9e, 0xab, 0x91, 0xbc, 0x4b, 0x09, 0x97, 0x29, 0x53, 0x92, 0x31, 0xbd, 0xbb, 0x3a, - 0xc0, 0x76, 0xe8, 0xa0, 0x48, 0xb3, 0x0e, 0xc2, 0x20, 0xe1, 0xa9, 0x0d, 0x3e, 0xdd, 0x33, 0x06, 0x1f, 0x3f, 0x53, - 0xce, 0x2b, 0x5a, 0x55, 0x09, 0x9f, 0x57, 0x1f, 0xf2, 0xfb, 0xef, 0x50, 0x41, 0xd6, 0x37, 0x6b, 0x64, 0xc3, 0xae, - 0x2c, 0x0f, 0x10, 0xe7, 0x51, 0x84, 0xfd, 0x80, 0xce, 0x7e, 0xcc, 0xc2, 0xa6, 0x7d, 0x18, 0x3f, 0xf9, 0xa6, 0xe9, - 0x7a, 0xde, 0x99, 0xd6, 0x9c, 0x1f, 0x7c, 0xd8, 0x2b, 0xe1, 0x40, 0xb7, 0xb3, 0xf4, 0xbf, 0x88, 0x18, 0x20, 0x18, - 0x6c, 0xfe, 0xbe, 0x9c, 0x0f, 0xcf, 0x1e, 0xf2, 0x73, 0x44, 0xe4, 0x0e, 0x37, 0xb1, 0x77, 0xfc, 0x2e, 0xaf, 0x2a, - 0xc3, 0x06, 0xf2, 0x8a, 0x73, 0x19, 0xe1, 0xf2, 0xd6, 0xba, 0x6b, 0xc5, 0xb6, 0x24, 0x0b, 0xae, 0x25, 0x40, 0x61, - 0x64, 0x72, 0xc8, 0xed, 0xf2, 0x3f, 0x2b, 0xb6, 0x20, 0x21, 0xaa, 0x9d, 0xd4, 0x5d, 0xbd, 0x77, 0xae, 0x36, 0x55, - 0x1e, 0xfb, 0x87, 0x8f, 0x72, 0xe6, 0x0c, 0xa3, 0x0a, 0x77, 0x6c, 0xb3, 0x87, 0x2a, 0xa3, 0x36, 0x19, 0x13, 0x87, - 0x2a, 0xed, 0xac, 0xef, 0xa9, 0x58, 0x7a, 0x8c, 0x58, 0x62, 0x20, 0x23, 0x33, 0x1b, 0x92, 0xf6, 0xde, 0xec, 0x17, - 0x5e, 0x2f, 0xae, 0xb8, 0x4c, 0x08, 0x20, 0x6b, 0x63, 0xa0, 0xab, 0xad, 0x34, 0xec, 0xed, 0xf6, 0x7e, 0xfa, 0x28, - 0xbb, 0x3e, 0xe8, 0x1f, 0xe6, 0x0f, 0x5c, 0xaa, 0x35, 0x2b, 0xa7, 0xd6, 0xb2, 0xed, 0x15, 0xed, 0xd0, 0xeb, 0x2d, - 0xb3, 0xe9, 0x12, 0xd6, 0x23, 0xc9, 0xa2, 0xa5, 0x3c, 0xae, 0xaa, 0x4e, 0xd5, 0xb0, 0xdb, 0x34, 0x75, 0x9f, 0x39, - 0xbe, 0x43, 0x0a, 0x65, 0x59, 0x99, 0xd2, 0x27, 0xcf, 0x9c, 0x78, 0xaa, 0x28, 0x83, 0x39, 0x13, 0xdc, 0x96, 0x93, - 0x11, 0xa9, 0x88, 0xd7, 0x18, 0xcd, 0x0f, 0x01, 0xab, 0xb8, 0xae, 0x9f, 0x78, 0x14, 0x97, 0x0e, 0xae, 0xb3, 0xa1, - 0x6e, 0x3e, 0x5f, 0x13, 0x92, 0x96, 0x89, 0xf3, 0x69, 0xc0, 0xd7, 0x40, 0xd7, 0x47, 0x91, 0x02, 0xc0, 0x71, 0x26, - 0x93, 0xca, 0x7e, 0xd4, 0x91, 0xf3, 0x7e, 0xd3, 0x7c, 0xb5, 0x3e, 0xbb, 0xc8, 0xd7, 0xad, 0xf1, 0xab, 0xe1, 0x34, - 0x8f, 0x9e, 0x96, 0x9e, 0xf6, 0xf5, 0x79, 0xa6, 0x12, 0xc5, 0xfe, 0xca, 0x99, 0xbd, 0x51, 0xde, 0x15, 0xab, 0xec, - 0x2e, 0x7a, 0x78, 0xd7, 0xcf, 0x09, 0x70, 0xf8, 0x6e, 0x57, 0x20, 0xf2, 0xc3, 0xb2, 0x79, 0x8a, 0xcb, 0xa9, 0xb1, - 0x53, 0x94, 0x82, 0x19, 0x8d, 0xad, 0x88, 0x67, 0x6a, 0x26, 0xb0, 0x5e, 0xed, 0xe5, 0x61, 0x5a, 0x36, 0xa4, 0x19, - 0x7f, 0x58, 0x8b, 0xd1, 0x0e, 0x93, 0x07, 0x59, 0x06, 0xb3, 0xc8, 0xfa, 0xd0, 0x1c, 0x9d, 0xba, 0x62, 0xd2, 0xf6, - 0xd4, 0x29, 0x0b, 0xb7, 0x0f, 0xd6, 0xd8, 0x25, 0xe5, 0x50, 0x95, 0xe7, 0xef, 0xd7, 0x78, 0xe5, 0xb9, 0x48, 0xc6, - 0x3b, 0x70, 0xde, 0xb2, 0xdf, 0xc6, 0x09, 0x62, 0xdc, 0xd8, 0x6a, 0x7c, 0x16, 0x1b, 0x77, 0x82, 0x96, 0x09, 0xe4, - 0xec, 0xc1, 0x02, 0x9c, 0x86, 0x37, 0x45, 0xa6, 0xb5, 0xfc, 0x6c, 0x08, 0x78, 0x6f, 0xe8, 0x77, 0x75, 0x0b, 0x00, - 0x8b, 0xc8, 0x7b, 0xbd, 0x52, 0x9c, 0x2e, 0x8d, 0xc3, 0xc7, 0xdd, 0x95, 0xe2, 0x51, 0xda, 0x4d, 0x74, 0x77, 0xca, - 0x33, 0x48, 0x41, 0xbc, 0x7c, 0xa5, 0x5a, 0x8c, 0xaa, 0x97, 0xc8, 0x09, 0x04, 0x2c, 0x52, 0x8a, 0xff, 0xac, 0x7b, - 0x02, 0x2b, 0xd5, 0x77, 0xfc, 0xaa, 0x7a, 0x41, 0xac, 0x01, 0xbb, 0x6d, 0xb9, 0x85, 0x9e, 0x2a, 0x81, 0x7c, 0x00, - 0x99, 0x0b, 0xc0, 0xc0, 0xfd, 0xbb, 0x6e, 0xc2, 0xf5, 0x9f, 0x47, 0x99, 0x6f, 0x75, 0x5b, 0xae, 0xcf, 0xe6, 0xd1, - 0xd9, 0x8c, 0x9d, 0x90, 0x2f, 0x27, 0x7d, 0x09, 0x8a, 0xc9, 0xa6, 0x80, 0xfa, 0x21, 0xb3, 0x0f, 0xdb, 0xae, 0x72, - 0x46, 0x40, 0xb5, 0x7d, 0xae, 0x20, 0x61, 0xa0, 0xe5, 0x9e, 0xac, 0xcd, 0x47, 0xbe, 0xd2, 0xe6, 0xed, 0xfc, 0xfc, - 0xef, 0xbc, 0xe5, 0xa1, 0x83, 0xba, 0xff, 0x8a, 0xc5, 0x55, 0xfe, 0x4e, 0x46, 0x91, 0xed, 0xc3, 0x76, 0xf3, 0x6e, - 0x24, 0xc4, 0x05, 0xa7, 0xfc, 0x07, 0x9f, 0xbf, 0x94, 0x2e, 0xbc, 0xde, 0xc5, 0xa0, 0xf4, 0x11, 0x6a, 0xdc, 0x98, - 0xdb, 0x22, 0x91, 0xeb, 0x4a, 0x20, 0xf2, 0xd8, 0xc1, 0xa8, 0xe7, 0xb5, 0x4b, 0x6e, 0x00, 0xa3, 0x6e, 0xc7, 0xc3, - 0x03, 0x6d, 0x4a, 0x7f, 0x32, 0xe1, 0x46, 0x0b, 0x55, 0xc4, 0x1d, 0xa3, 0xe6, 0x03, 0x45, 0xe2, 0x15, 0x06, 0x08, - 0xd0, 0xad, 0xcf, 0xa3, 0xe8, 0x6d, 0x9a, 0xf7, 0x43, 0xb1, 0x9d, 0xa6, 0x2c, 0x50, 0xc0, 0x78, 0x32, 0x47, 0xb4, - 0xec, 0x89, 0x7d, 0xba, 0x3b, 0x1d, 0x56, 0x46, 0x6f, 0x71, 0x6d, 0xea, 0x72, 0xaf, 0xaf, 0xda, 0xce, 0xd6, 0x09, - 0xf7, 0x34, 0x6c, 0xe3, 0x0a, 0x12, 0x36, 0x72, 0x2a, 0x7a, 0xae, 0xe8, 0x6b, 0x3a, 0x2b, 0xe1, 0x1a, 0xf3, 0x2d, - 0x02, 0x60, 0x4d, 0x06, 0xf9, 0x4b, 0x31, 0x3d, 0x43, 0x45, 0xde, 0xb3, 0x39, 0x7b, 0x27, 0xd3, 0x29, 0x7b, 0x6b, - 0x48, 0x29, 0x17, 0x98, 0xcf, 0x1e, 0x10, 0xa6, 0x79, 0xe8, 0x6d, 0x24, 0xc9, 0xcc, 0xd3, 0x96, 0xbc, 0xa9, 0xee, - 0x69, 0x22, 0x78, 0x50, 0xca, 0xb3, 0xde, 0x4f, 0xde, 0x0d, 0xeb, 0x82, 0xf1, 0xbc, 0x23, 0x1c, 0x28, 0x3e, 0x97, - 0xbd, 0x09, 0xee, 0x3e, 0xcf, 0x7f, 0x34, 0x27, 0xdb, 0x5a, 0x1b, 0xe4, 0xe6, 0x27, 0x59, 0xbf, 0x90, 0xf3, 0x89, - 0x27, 0xbd, 0xfa, 0xf8, 0x93, 0x7e, 0x91, 0x08, 0x65, 0xd7, 0xa9, 0x09, 0xf6, 0x88, 0x3f, 0x4f, 0x30, 0x80, 0xcd, - 0x62, 0xb2, 0xa4, 0x1a, 0x2d, 0xab, 0x28, 0x6f, 0xe9, 0xb4, 0x99, 0xe2, 0x97, 0xda, 0xd3, 0x69, 0xac, 0xf0, 0x56, - 0x0b, 0xcf, 0xd8, 0x6e, 0xc1, 0xda, 0x66, 0xda, 0x92, 0x25, 0xa7, 0x74, 0xed, 0x83, 0x1d, 0x7f, 0x58, 0x03, 0xa8, - 0x22, 0xca, 0x95, 0xf4, 0xb2, 0x12, 0x7f, 0xe0, 0xb3, 0x5d, 0x84, 0x57, 0x03, 0xaf, 0xaa, 0x99, 0xa7, 0x5a, 0x3d, - 0xb0, 0xdd, 0xf4, 0x69, 0x6f, 0x25, 0x3b, 0xde, 0x51, 0x9c, 0xf0, 0x2a, 0xa1, 0xe3, 0x5c, 0xb6, 0xd0, 0xf5, 0xd3, - 0x5d, 0x58, 0xd8, 0xf7, 0x5f, 0xa0, 0x47, 0x0e, 0x26, 0x6e, 0xe7, 0x67, 0xf6, 0x0a, 0x5a, 0x07, 0x8a, 0x6c, 0x0f, - 0xaf, 0x3b, 0x2b, 0x2c, 0xc2, 0x08, 0x29, 0xff, 0xa5, 0xe1, 0x2d, 0xda, 0xbd, 0x2a, 0x2d, 0xc1, 0xf8, 0xec, 0x5d, - 0xd5, 0xd8, 0xb6, 0x03, 0x65, 0x3a, 0x5b, 0x47, 0xca, 0x05, 0xed, 0x80, 0x91, 0x82, 0xd3, 0x9d, 0x55, 0xdf, 0xff, - 0x3a, 0x99, 0x6a, 0x75, 0x8f, 0xed, 0x70, 0x26, 0xba, 0x53, 0x8c, 0x03, 0x68, 0x09, 0x85, 0xac, 0xad, 0x4e, 0xfd, - 0x7b, 0x9f, 0xad, 0xd7, 0xbc, 0x63, 0x5a, 0xac, 0x34, 0x2f, 0x78, 0x42, 0x6b, 0x1b, 0x9e, 0xb4, 0x18, 0xf7, 0x56, - 0x29, 0x27, 0x42, 0x82, 0x86, 0x6e, 0x39, 0x1f, 0xe4, 0x15, 0x1e, 0xd4, 0x40, 0x25, 0xb8, 0x36, 0x0e, 0xa1, 0x0e, - 0xad, 0x2d, 0xeb, 0xdd, 0x95, 0x18, 0xb7, 0xc0, 0xb5, 0xec, 0xc6, 0xd9, 0x1d, 0xce, 0xad, 0xc3, 0x46, 0xab, 0x91, - 0xdd, 0xe8, 0x0f, 0x43, 0x0f, 0x22, 0x85, 0x9b, 0x1d, 0x4d, 0xb7, 0x1d, 0x46, 0x7b, 0x0e, 0x9d, 0x17, 0x6d, 0x8c, - 0x89, 0x30, 0x33, 0x69, 0x33, 0xdf, 0xc5, 0xe5, 0x4c, 0x1b, 0x96, 0xf2, 0x01, 0x5a, 0x03, 0x08, 0x88, 0xb2, 0x50, - 0xd1, 0x2e, 0x72, 0x9a, 0xed, 0x42, 0x6d, 0xb8, 0xa1, 0x44, 0x2c, 0x82, 0x40, 0xde, 0x40, 0xc8, 0x9f, 0x6a, 0x17, - 0x7e, 0x4d, 0xb0, 0x51, 0x30, 0x83, 0x39, 0xd1, 0x50, 0x63, 0x42, 0x90, 0x3e, 0xb5, 0x52, 0x96, 0x3e, 0xe4, 0x8c, - 0x84, 0xd0, 0x82, 0x1a, 0x55, 0xcb, 0x23, 0x72, 0x9b, 0x6e, 0xe6, 0xf0, 0xb9, 0xa8, 0x38, 0x2a, 0xbd, 0x74, 0x9b, - 0x79, 0x06, 0x1f, 0x75, 0x18, 0x7b, 0x2e, 0xc0, 0x38, 0xd8, 0x39, 0x09, 0xe0, 0x2f, 0xe2, 0x7f, 0x0d, 0xc0, 0x13, - 0x2c, 0x2a, 0xd3, 0x5a, 0x57, 0x6f, 0x60, 0xca, 0x29, 0x8a, 0xd9, 0xf2, 0x14, 0xbd, 0x89, 0xbd, 0xd6, 0xbe, 0x0c, - 0xa4, 0xc4, 0x47, 0x16, 0x3a, 0x7a, 0xeb, 0xc9, 0x4e, 0xcf, 0x40, 0x64, 0xfc, 0x6a, 0xec, 0xfd, 0x71, 0x73, 0xb5, - 0x1b, 0x86, 0xf8, 0x16, 0x05, 0xec, 0xcc, 0x7b, 0xe7, 0xf8, 0xe4, 0xb3, 0x38, 0x4c, 0xe8, 0xcd, 0x41, 0x68, 0x5c, - 0xcf, 0x42, 0xc9, 0xf8, 0xc8, 0xcb, 0x85, 0xfb, 0xb2, 0x0d, 0xb6, 0x33, 0x3e, 0xf9, 0xf4, 0xd0, 0x07, 0x82, 0x87, - 0x4c, 0x49, 0x50, 0x73, 0xa0, 0xbb, 0x36, 0x8d, 0x80, 0xa5, 0x37, 0x79, 0xa1, 0x99, 0xd7, 0xc1, 0xb2, 0x67, 0x28, - 0x40, 0x08, 0x70, 0x20, 0x47, 0xa0, 0x68, 0x7a, 0x37, 0x1a, 0x70, 0x11, 0x7c, 0x58, 0xe4, 0x1c, 0xfe, 0x37, 0x0d, - 0xf7, 0x5d, 0xee, 0xf9, 0xeb, 0x5c, 0x0c, 0x3e, 0xb5, 0x43, 0xdf, 0xb7, 0x03, 0xe1, 0xca, 0xef, 0x78, 0x11, 0x7c, - 0x72, 0x89, 0x90, 0xae, 0x0d, 0x5e, 0x63, 0xe2, 0xdd, 0x8d, 0x90, 0xfb, 0x50, 0x78, 0xb9, 0xc4, 0x03, 0xe6, 0xda, - 0xf4, 0xc6, 0x9c, 0xf9, 0xad, 0xe8, 0x4d, 0x33, 0x47, 0x07, 0xa3, 0x23, 0xbb, 0x1f, 0x61, 0x6d, 0xe7, 0x5f, 0xfa, - 0x57, 0x60, 0x8d, 0xee, 0x67, 0x91, 0x7c, 0x3a, 0xde, 0x56, 0x00, 0x4b, 0x83, 0x0f, 0x64, 0x38, 0xaf, 0x63, 0x0c, - 0x6b, 0xe8, 0x3e, 0xea, 0x7e, 0x25, 0xc0, 0x86, 0x30, 0x0e, 0x95, 0x81, 0xa9, 0x37, 0x30, 0x45, 0xee, 0xff, 0xb3, - 0x8a, 0xfa, 0xb8, 0x61, 0x62, 0x2e, 0x87, 0x34, 0x00, 0x12, 0x0a, 0x7e, 0xee, 0x1e, 0x13, 0xad, 0xd8, 0x43, 0x46, - 0x6b, 0x94, 0x89, 0x47, 0xb2, 0xc9, 0xaf, 0x7a, 0x77, 0xa4, 0xac, 0x0f, 0x7c, 0x2f, 0x9b, 0xbc, 0x4f, 0x98, 0x7b, - 0xce, 0xdf, 0x69, 0x03, 0xa8, 0x5c, 0x8a, 0xb3, 0x8a, 0x7a, 0x09, 0x58, 0x13, 0x39, 0x7e, 0x5a, 0x98, 0x0c, 0x37, - 0x6a, 0x7e, 0x93, 0x45, 0xe0, 0x1e, 0x90, 0xa6, 0xd0, 0x2c, 0x28, 0x57, 0xc8, 0x22, 0xf9, 0x90, 0x9c, 0x3e, 0x20, - 0xd6, 0x85, 0xbc, 0x0d, 0xb5, 0xc5, 0x32, 0x12, 0x93, 0x7b, 0x89, 0x89, 0x57, 0xde, 0x32, 0xb6, 0xc4, 0x58, 0xb4, - 0xa6, 0xec, 0x52, 0x88, 0xbc, 0x51, 0x65, 0xd8, 0xd4, 0x65, 0x06, 0x13, 0xa5, 0x75, 0x3f, 0x3c, 0xc6, 0x51, 0x95, - 0x9e, 0x49, 0x8f, 0x80, 0xad, 0x70, 0xb6, 0x98, 0xd4, 0x55, 0x90, 0xc0, 0xf9, 0x40, 0x78, 0x28, 0x1f, 0x88, 0x15, - 0xaa, 0xb8, 0xf8, 0x13, 0x0e, 0x27, 0xd0, 0x2d, 0xc9, 0x2d, 0xab, 0x8e, 0xeb, 0x78, 0x9f, 0x43, 0x8e, 0x22, 0x51, - 0x02, 0x6d, 0xf0, 0x3b, 0x15, 0xd2, 0x43, 0x06, 0x0b, 0x50, 0x0e, 0x03, 0x3a, 0x3c, 0x18, 0x25, 0xa6, 0xe0, 0xf0, - 0xf0, 0x20, 0x12, 0x79, 0x59, 0xc8, 0x9f, 0x0e, 0xce, 0x3a, 0x54, 0x7d, 0x65, 0xf0, 0xdf, 0xc1, 0xb5, 0x45, 0x28, - 0x4e, 0x4c, 0xac, 0x63, 0x14, 0x1c, 0xdc, 0xba, 0x4d, 0x65, 0xc3, 0x9f, 0x7a, 0x7f, 0xad, 0xf0, 0x68, 0xe9, 0xc1, - 0xea, 0xbc, 0xad, 0x02, 0x9e, 0x0d, 0x4a, 0x8f, 0x35, 0x4f, 0xac, 0x7d, 0xc5, 0xc9, 0x81, 0x04, 0xa6, 0x49, 0x6f, - 0x6b, 0xcb, 0xf8, 0x05, 0xf1, 0xcb, 0x3d, 0x0b, 0x2f, 0xfc, 0x76, 0xd4, 0x12, 0x8b, 0xf5, 0xa9, 0x14, 0x7b, 0x2d, - 0x0d, 0x37, 0xd2, 0x06, 0x59, 0xbf, 0xd3, 0x3a, 0xcf, 0x8d, 0x45, 0x7a, 0x63, 0xff, 0x48, 0xc4, 0xdb, 0x19, 0xea, - 0x53, 0x28, 0xb1, 0x9e, 0x41, 0xf4, 0x6a, 0x48, 0x7d, 0xd1, 0x1a, 0x91, 0xa2, 0x70, 0xd9, 0xea, 0xf2, 0x22, 0x66, - 0x60, 0x8c, 0x68, 0xf5, 0x8a, 0x2d, 0x25, 0x86, 0xf7, 0x42, 0xa4, 0x56, 0xe9, 0xa9, 0xee, 0x8a, 0x62, 0xd3, 0x25, - 0x65, 0xd3, 0x46, 0x68, 0x2b, 0x0a, 0xec, 0x20, 0x94, 0xa2, 0x40, 0x2b, 0xe3, 0xb0, 0x87, 0x7a, 0x8b, 0xcc, 0x68, - 0xa3, 0x14, 0x36, 0xf3, 0x34, 0x02, 0xb8, 0xb9, 0x55, 0x13, 0x69, 0x17, 0x25, 0xce, 0x65, 0xb4, 0x4c, 0xb2, 0xde, - 0xb2, 0x52, 0xb8, 0x2f, 0x64, 0x38, 0x31, 0x3a, 0x36, 0xc0, 0x97, 0xc7, 0xff, 0xef, 0x0f, 0x60, 0xcd, 0xd2, 0x61, - 0x48, 0x5e, 0x43, 0x75, 0x84, 0xd0, 0x8c, 0x3d, 0xea, 0x72, 0x80, 0x22, 0x75, 0x6d, 0xa9, 0x65, 0x6e, 0x47, 0x39, - 0xc6, 0x85, 0x2b, 0xcf, 0xdb, 0xc5, 0x82, 0x0e, 0x0b, 0x23, 0x3e, 0xcc, 0x37, 0x18, 0x4b, 0xae, 0x14, 0xdd, 0x32, - 0x19, 0x81, 0x49, 0x75, 0xc5, 0x0b, 0xe7, 0x0b, 0x5e, 0xc9, 0xf4, 0x07, 0xf9, 0x48, 0x4e, 0xa5, 0x31, 0x1b, 0xab, - 0x0d, 0xa1, 0x26, 0x82, 0x36, 0x4f, 0x4b, 0xa4, 0xdb, 0x2e, 0x4d, 0x2c, 0x50, 0x18, 0x96, 0x46, 0xe8, 0xaa, 0x49, - 0x58, 0xf3, 0xb3, 0xab, 0x05, 0x89, 0x87, 0x49, 0x57, 0xcd, 0x55, 0x70, 0x6e, 0xed, 0xb1, 0xd3, 0x47, 0x7a, 0x2c, - 0x82, 0x56, 0xb3, 0x0b, 0xa5, 0x35, 0x68, 0xcd, 0x2d, 0xb3, 0x36, 0x6c, 0xc0, 0x2b, 0xe7, 0x32, 0xc5, 0x19, 0x35, - 0xbc, 0xb1, 0x31, 0x84, 0xc9, 0x4f, 0xc5, 0x79, 0xf2, 0x7f, 0x66, 0x0b, 0x97, 0xa6, 0x6e, 0xdd, 0x14, 0x57, 0x1c, - 0x48, 0x31, 0x1f, 0xc4, 0xc3, 0x79, 0x11, 0xc9, 0x9b, 0xeb, 0x5e, 0x46, 0x9c, 0x0e, 0xf4, 0x82, 0xac, 0x62, 0x87, - 0xbe, 0x93, 0x1f, 0xf5, 0xa8, 0xc4, 0x19, 0x8c, 0x65, 0x03, 0xb1, 0x04, 0x82, 0xf8, 0xae, 0x7d, 0x88, 0xe4, 0xc6, - 0xa5, 0x5a, 0x97, 0x07, 0xb2, 0xe5, 0x45, 0x90, 0x78, 0xe7, 0xee, 0x5e, 0x33, 0xc6, 0x4b, 0x7c, 0x42, 0x3e, 0x5e, - 0x10, 0xbc, 0x72, 0x0b, 0xe4, 0x0e, 0xd7, 0xc1, 0x03, 0xf1, 0x51, 0x82, 0x17, 0x23, 0x89, 0x7b, 0xa9, 0x43, 0x85, - 0xa0, 0x45, 0x4f, 0x30, 0x22, 0x91, 0x7c, 0xb5, 0xb6, 0x2e, 0x88, 0x02, 0x4d, 0xb0, 0x5e, 0x3c, 0x8a, 0x9a, 0x56, - 0x9f, 0xa0, 0xcc, 0x08, 0xb9, 0x63, 0xab, 0x83, 0x1e, 0xdf, 0xe7, 0xa1, 0x60, 0xf6, 0xae, 0x49, 0x84, 0xfb, 0x5d, - 0x56, 0xb7, 0x3b, 0x20, 0x19, 0xfe, 0xa4, 0x55, 0xf7, 0x72, 0x0a, 0x69, 0x48, 0x43, 0x59, 0x7c, 0xf0, 0x56, 0x09, - 0x4e, 0x1e, 0xb2, 0xac, 0x4f, 0x8b, 0x31, 0x23, 0x25, 0x05, 0x25, 0x86, 0xe5, 0x52, 0x49, 0xd9, 0xe1, 0x10, 0x5b, - 0x62, 0x2f, 0xba, 0x3e, 0xfc, 0xbe, 0xa5, 0x0f, 0x00, 0x0f, 0xe5, 0x66, 0xfa, 0xda, 0x42, 0x54, 0xc0, 0xd0, 0xcc, - 0x7e, 0xca, 0xa7, 0xf5, 0xec, 0x7f, 0x3f, 0x60, 0x1f, 0x33, 0xf6, 0x9b, 0xc7, 0x38, 0xe0, 0xa7, 0x3c, 0xb4, 0x7c, - 0x8d, 0x8a, 0xee, 0x71, 0x5a, 0xcd, 0x7d, 0x69, 0x86, 0x18, 0x38, 0x09, 0x1e, 0xee, 0x72, 0x48, 0x83, 0xfc, 0xb3, - 0x35, 0x24, 0x9b, 0x60, 0x69, 0x2c, 0xb0, 0x42, 0xd6, 0x7c, 0xba, 0x0b, 0x2e, 0xb6, 0x92, 0x82, 0x27, 0x35, 0xb0, - 0xca, 0xf5, 0x26, 0xe6, 0xdc, 0xa4, 0x66, 0x77, 0x04, 0x12, 0xc8, 0x26, 0xb3, 0xbd, 0xa4, 0xe4, 0xaf, 0x89, 0x29, - 0xe9, 0xf7, 0x8d, 0x84, 0x08, 0x80, 0x95, 0x3e, 0x21, 0xba, 0xe0, 0xab, 0x58, 0x93, 0x4c, 0x3a, 0x96, 0x1a, 0xd5, - 0x56, 0x0a, 0xe8, 0x7a, 0xe1, 0x9f, 0xbd, 0xb9, 0x19, 0xcd, 0xa6, 0xe4, 0x4e, 0xe5, 0x0d, 0xf9, 0x14, 0xfc, 0xb5, - 0x19, 0x6d, 0xad, 0x86, 0x89, 0xa1, 0x8f, 0x01, 0xb4, 0xf7, 0x07, 0x78, 0xe1, 0xd1, 0x0a, 0x4b, 0x0a, 0x74, 0x8a, - 0x85, 0xce, 0x4b, 0x98, 0x7b, 0x58, 0x70, 0x54, 0xf2, 0xdd, 0x3b, 0xcc, 0xe3, 0xfa, 0xd6, 0x11, 0x24, 0x65, 0x3b, - 0xd3, 0xe9, 0x52, 0x2b, 0x12, 0xd0, 0xeb, 0x8c, 0x55, 0x22, 0xae, 0x49, 0x4e, 0x6e, 0xf8, 0xca, 0xc8, 0x68, 0x11, - 0x63, 0x1c, 0x53, 0x41, 0x1f, 0x2f, 0xbd, 0xcd, 0x0b, 0xc3, 0xbb, 0x3d, 0xa6, 0x95, 0x1e, 0x39, 0xc0, 0x55, 0xc2, - 0x4c, 0x19, 0xb4, 0x89, 0x78, 0xdc, 0x0f, 0x10, 0x05, 0x62, 0xa1, 0xd3, 0xc8, 0x51, 0x6a, 0xec, 0xfe, 0x88, 0xbd, - 0x80, 0x32, 0xaf, 0x99, 0x41, 0xd1, 0xf0, 0x5b, 0xfd, 0x95, 0xff, 0x8f, 0x1f, 0x67, 0x5e, 0xed, 0x47, 0x6f, 0x52, - 0x56, 0x9a, 0x03, 0xd5, 0xc8, 0x01, 0x77, 0x8f, 0xdb, 0x3b, 0xd7, 0x10, 0x61, 0x78, 0x2e, 0xab, 0xf1, 0x4e, 0x0f, - 0xed, 0xf6, 0x39, 0xfc, 0x9c, 0xdd, 0xae, 0xf9, 0xdd, 0xef, 0xfe, 0x44, 0x1e, 0x74, 0x0d, 0x17, 0x11, 0x1d, 0x30, - 0x5e, 0x5e, 0x6d, 0xd0, 0x9c, 0x67, 0xf9, 0x01, 0xec, 0x3d, 0xbe, 0x35, 0x52, 0x7d, 0xaa, 0x78, 0x85, 0x08, 0xc8, - 0x5b, 0xa5, 0xba, 0x4a, 0xc4, 0xbe, 0xc0, 0x66, 0x91, 0x01, 0x7d, 0xd6, 0xa1, 0x6b, 0xb5, 0x53, 0xc4, 0xcb, 0xcb, - 0x39, 0xe1, 0x87, 0x9b, 0x4e, 0x40, 0x93, 0xdc, 0x79, 0xcb, 0x3b, 0x5b, 0xe2, 0xac, 0xa7, 0x8c, 0x76, 0x9d, 0x5c, - 0x35, 0x0a, 0x48, 0x3b, 0x26, 0x22, 0xd3, 0xd6, 0xdc, 0x76, 0xed, 0xf8, 0x4a, 0xa1, 0xdf, 0xe1, 0xd5, 0xe5, 0x86, - 0x47, 0x43, 0x39, 0xa9, 0x36, 0xc9, 0xab, 0x2d, 0x9b, 0xc9, 0x49, 0x3f, 0xda, 0xda, 0x43, 0xf0, 0xd1, 0x0d, 0x1f, - 0x67, 0xca, 0x7e, 0xa7, 0x61, 0x9f, 0x67, 0xad, 0xfd, 0x55, 0xc2, 0x70, 0x2f, 0x9f, 0xa4, 0x09, 0xda, 0x38, 0xa7, - 0x54, 0x62, 0x0e, 0x78, 0x89, 0xde, 0xf2, 0x20, 0x6c, 0xa6, 0x29, 0xd5, 0xab, 0xca, 0xe5, 0x66, 0x4a, 0xe4, 0x9c, - 0xe8, 0xb1, 0xdb, 0x2c, 0x6e, 0x8a, 0x6b, 0xb0, 0x33, 0x03, 0x26, 0xa1, 0xb5, 0xef, 0xb6, 0x23, 0x3b, 0x38, 0xb7, - 0xfd, 0x61, 0xfc, 0x17, 0x98, 0x27, 0xf2, 0x7c, 0x8e, 0x15, 0x1b, 0xaf, 0xe7, 0xef, 0xfe, 0x1e, 0x03, 0xf6, 0xf9, - 0x98, 0x0d, 0x79, 0xe9, 0xed, 0xc7, 0xd1, 0x3c, 0xee, 0xc7, 0xc3, 0xc0, 0x37, 0x0c, 0x65, 0x38, 0xe0, 0xd1, 0x32, - 0xdd, 0xe9, 0x30, 0xb5, 0x19, 0xd9, 0x13, 0xea, 0xee, 0x9c, 0xb9, 0xe1, 0xe3, 0x4f, 0x22, 0x6c, 0x86, 0xb3, 0x75, - 0x19, 0x24, 0xfa, 0x0a, 0x01, 0xc5, 0x38, 0x8d, 0x18, 0xd7, 0x3b, 0x9f, 0x36, 0xa1, 0xb6, 0x95, 0xa4, 0x67, 0xb7, - 0x40, 0x4d, 0x80, 0xaa, 0x94, 0x2f, 0xd7, 0x45, 0x34, 0x34, 0xf3, 0x24, 0x94, 0x5e, 0xee, 0xe9, 0x73, 0xb4, 0x63, - 0x03, 0x7b, 0x39, 0xa7, 0xa1, 0x94, 0xf4, 0xb2, 0xab, 0x06, 0x37, 0xb0, 0x95, 0xa8, 0xf1, 0x22, 0xe2, 0xdd, 0x66, - 0x0f, 0x25, 0x03, 0xcb, 0x53, 0x12, 0x73, 0xc0, 0xb4, 0x9b, 0x14, 0x55, 0xf6, 0x0c, 0xab, 0x21, 0x98, 0xc7, 0xdd, - 0x7e, 0x66, 0x87, 0xd7, 0x52, 0x54, 0xcd, 0x2d, 0xb6, 0x00, 0x6b, 0x8b, 0x14, 0xe2, 0x70, 0x44, 0x49, 0xd3, 0x11, - 0xe9, 0xc8, 0xf8, 0x93, 0xa6, 0x44, 0x02, 0x10, 0x1d, 0xfe, 0x33, 0xcd, 0xf4, 0x50, 0xf4, 0xdf, 0x8b, 0x57, 0x6b, - 0x73, 0xaf, 0x5d, 0x30, 0x72, 0x9a, 0x7f, 0x38, 0x1d, 0x6f, 0xfa, 0xb9, 0xb5, 0x8f, 0x33, 0xd7, 0xab, 0x5b, 0x1b, - 0x73, 0xbd, 0xb0, 0xe7, 0xfe, 0x49, 0x24, 0xcf, 0x0a, 0x94, 0x6f, 0x47, 0x60, 0x54, 0x41, 0xb8, 0x97, 0x01, 0x76, - 0xbf, 0x17, 0xae, 0xff, 0x5f, 0xe5, 0x9d, 0x1f, 0xe4, 0xf7, 0xff, 0xb6, 0x86, 0xff, 0xcb, 0x6e, 0xba, 0xda, 0x60, - 0xff, 0x5b, 0x03, 0x94, 0xdf, 0x66, 0xa9, 0x1d, 0x48, 0xff, 0xd6, 0x09, 0xe1, 0x22, 0x4e, 0x27, 0x77, 0x02, 0x2b, - 0x3d, 0x4d, 0xce, 0xc1, 0xc0, 0x03, 0xfb, 0xff, 0x59, 0x0e, 0x40, 0x2f, 0xe0, 0x8b, 0x27, 0xd9, 0xb6, 0x9f, 0xe1, - 0x05, 0xb8, 0x53, 0xa2, 0x8c, 0x70, 0xc8, 0xeb, 0xca, 0xaf, 0xf8, 0xfa, 0x39, 0x24, 0x78, 0x75, 0x0a, 0xe6, 0xa7, - 0x93, 0x50, 0x59, 0x9e, 0x20, 0xee, 0xbb, 0x78, 0xb2, 0xd5, 0xa5, 0x84, 0x0f, 0x54, 0xeb, 0x43, 0x97, 0xe2, 0x23, - 0x7e, 0x47, 0xdd, 0x48, 0xe2, 0x27, 0xda, 0x3f, 0x6a, 0xf3, 0x91, 0xa7, 0x76, 0x41, 0xbc, 0x37, 0xb9, 0xf5, 0x17, - 0x11, 0xce, 0x3d, 0x21, 0xa9, 0x35, 0x09, 0x55, 0xe7, 0x24, 0x71, 0xc4, 0xd9, 0x1d, 0xda, 0x6a, 0x98, 0x93, 0xf0, - 0x9f, 0xaa, 0x2f, 0xb5, 0x4e, 0xae, 0x03, 0x11, 0x4d, 0xef, 0xb1, 0xd3, 0x65, 0x10, 0xa0, 0x06, 0xeb, 0xb3, 0xbc, - 0xa5, 0xdf, 0xf9, 0x1c, 0x9f, 0xaf, 0x26, 0xba, 0xb3, 0xa1, 0x7b, 0x34, 0xf2, 0x65, 0xfc, 0xf6, 0x21, 0x24, 0xd5, - 0xa4, 0x86, 0x1c, 0x4c, 0x24, 0x3a, 0xe7, 0xeb, 0xf4, 0x8b, 0xa8, 0xee, 0x5b, 0x0b, 0x8e, 0xb5, 0x39, 0xeb, 0x20, - 0x63, 0x98, 0x31, 0x18, 0x56, 0xd0, 0x00, 0x16, 0x63, 0x1c, 0x32, 0xef, 0xe8, 0x6e, 0x3f, 0x5a, 0xdb, 0xff, 0xfb, - 0x3c, 0x33, 0x20, 0xed, 0xf9, 0xc0, 0x5b, 0xd5, 0x47, 0xe1, 0x90, 0xb6, 0xef, 0xe9, 0xc1, 0xbe, 0x45, 0xa4, 0x17, - 0x31, 0xfd, 0x1a, 0xde, 0x9a, 0xc7, 0xcf, 0x47, 0x45, 0x69, 0x51, 0x47, 0x65, 0xf1, 0xc2, 0x1d, 0x1a, 0xf7, 0xd7, - 0xf0, 0xd9, 0x98, 0x77, 0x67, 0x83, 0x00, 0x32, 0x26, 0x5a, 0xc7, 0x6b, 0xb1, 0xff, 0xc5, 0x73, 0x3a, 0x0f, 0xe6, - 0xdb, 0x83, 0x63, 0x15, 0xb1, 0xf9, 0xd8, 0x4a, 0x2d, 0xd1, 0x37, 0x59, 0x9c, 0x6d, 0x21, 0x74, 0x65, 0x3b, 0x78, - 0xf6, 0xa4, 0x26, 0xaa, 0xce, 0x4e, 0xc8, 0x7b, 0x6a, 0xf3, 0xa2, 0xcb, 0x36, 0x7b, 0xb0, 0x49, 0x1b, 0x43, 0xe3, - 0x29, 0x75, 0x95, 0x6d, 0x5b, 0x19, 0x5f, 0x9b, 0xee, 0xeb, 0xef, 0x5f, 0x62, 0x69, 0xed, 0x04, 0x1d, 0x0a, 0x67, - 0x33, 0x62, 0xa6, 0xe0, 0x07, 0x14, 0x48, 0xb8, 0x61, 0x28, 0x89, 0x37, 0xc1, 0xaf, 0xa3, 0x36, 0x99, 0x12, 0x4c, - 0xc3, 0x68, 0xf6, 0xfd, 0x6b, 0x0f, 0x37, 0x3b, 0x7a, 0x11, 0x50, 0xe7, 0x8f, 0xac, 0xdb, 0x70, 0x32, 0x24, 0x84, - 0x8b, 0xbb, 0x75, 0x72, 0x0b, 0x3a, 0x26, 0xf2, 0x88, 0x23, 0x69, 0xc9, 0xdd, 0x79, 0xff, 0x88, 0x65, 0x3f, 0x5b, - 0xff, 0x89, 0x77, 0xb5, 0xa9, 0xec, 0x85, 0x92, 0x4d, 0xed, 0x67, 0xe8, 0x58, 0x94, 0x00, 0x4a, 0xa8, 0xbc, 0xb3, - 0x36, 0x67, 0x8f, 0xc6, 0xaa, 0xca, 0xe8, 0xb7, 0xbc, 0xae, 0x66, 0xc5, 0x82, 0xc7, 0xdd, 0xe2, 0x38, 0x8e, 0x8f, - 0xd5, 0x43, 0xdb, 0xfb, 0x15, 0x32, 0x95, 0xef, 0xf0, 0xb9, 0x7a, 0x23, 0x9f, 0x36, 0x16, 0xc9, 0xab, 0x87, 0x87, - 0x2c, 0xe4, 0xf3, 0xba, 0x39, 0x3a, 0xd1, 0xe4, 0x72, 0x8c, 0x4a, 0x16, 0x6b, 0xf9, 0x10, 0x69, 0x3b, 0x8b, 0x9d, - 0x44, 0x2f, 0xa5, 0x55, 0x67, 0x2c, 0x2c, 0x05, 0xdc, 0x97, 0x51, 0xb9, 0x42, 0x5d, 0x4d, 0x4a, 0x1d, 0x06, 0x72, - 0x1d, 0xa8, 0x0a, 0x36, 0xb4, 0x78, 0x64, 0x66, 0x05, 0xbf, 0xf0, 0xe9, 0x11, 0x11, 0x0c, 0x6c, 0x7b, 0x81, 0x8f, - 0xa7, 0xa9, 0xc5, 0xdc, 0xe0, 0x0b, 0x55, 0xc6, 0x3b, 0x5f, 0xf2, 0x39, 0x3a, 0x6b, 0x54, 0x48, 0x16, 0x43, 0x8e, - 0x46, 0x71, 0x8b, 0x56, 0xd2, 0xfe, 0x4b, 0xf2, 0x3e, 0x73, 0x4a, 0x89, 0x96, 0x5a, 0x82, 0x02, 0xd2, 0x34, 0x4d, - 0x77, 0x4d, 0xe9, 0x7b, 0xf1, 0x68, 0x9e, 0xd6, 0x68, 0x9b, 0xdb, 0x59, 0x0a, 0x09, 0xa2, 0x9b, 0xa2, 0x13, 0x8d, - 0xf4, 0x62, 0x00, 0x52, 0xae, 0x1f, 0x7a, 0x23, 0x64, 0xef, 0x74, 0xa6, 0x96, 0xf0, 0xe0, 0x94, 0x03, 0x61, 0xe5, - 0x9d, 0x35, 0x76, 0x9a, 0x46, 0xd7, 0x4a, 0xf6, 0x8e, 0xdf, 0xca, 0xe9, 0xa6, 0x39, 0x88, 0xaf, 0xa1, 0x7d, 0xed, - 0x55, 0x0a, 0x6c, 0x71, 0xad, 0xb6, 0x36, 0x17, 0xca, 0xba, 0xf4, 0x41, 0x8e, 0xdc, 0x2c, 0x30, 0x36, 0xe9, 0xad, - 0x73, 0xd9, 0xbb, 0x2e, 0x4a, 0x65, 0x0b, 0xbf, 0x56, 0xa5, 0x3d, 0xc1, 0x8a, 0x81, 0xe0, 0x38, 0x7e, 0x55, 0x10, - 0xcb, 0x6a, 0x54, 0xdb, 0xf1, 0x12, 0x2f, 0x0e, 0x8c, 0x55, 0xa8, 0xe7, 0xe8, 0x9d, 0x77, 0x84, 0x1a, 0xac, 0x27, - 0xa9, 0x50, 0xb2, 0xc9, 0x2c, 0x50, 0xac, 0xe2, 0x2e, 0x07, 0xf6, 0x4b, 0x50, 0x06, 0xe0, 0x7f, 0x32, 0x55, 0x76, - 0x7f, 0xaa, 0x39, 0x39, 0xb7, 0x4c, 0xed, 0x97, 0x92, 0x5c, 0xf3, 0xf3, 0xcc, 0xfa, 0x69, 0x30, 0xca, 0x68, 0x06, - 0x98, 0x97, 0xea, 0x5a, 0x76, 0x9e, 0xce, 0x14, 0xd7, 0xe0, 0x0f, 0x26, 0x49, 0x4f, 0xfb, 0xcf, 0x43, 0x0e, 0x7d, - 0x76, 0xea, 0xf9, 0xbd, 0x43, 0xce, 0x54, 0x7e, 0xfb, 0x69, 0x1e, 0x3c, 0xfd, 0xe3, 0x13, 0xfe, 0xfa, 0xf1, 0x5f, - 0xfa, 0x14, 0x9d, 0xe0, 0xcf, 0xd9, 0x4b, 0xe8, 0xa3, 0xda, 0x25, 0xdc, 0x8f, 0x56, 0xed, 0x01, 0x1a, 0x7d, 0x76, - 0xc1, 0x92, 0x57, 0x17, 0x8c, 0x03, 0x4a, 0xb5, 0x66, 0x2c, 0xb7, 0xfa, 0x9e, 0xb8, 0x7e, 0xb2, 0xd9, 0x2b, 0x5d, - 0x1a, 0xb8, 0x35, 0xb6, 0x9f, 0x97, 0x55, 0x0b, 0xd7, 0xbd, 0x32, 0xc9, 0xeb, 0xf7, 0x67, 0xd8, 0x13, 0xff, 0x3b, - 0x04, 0xc8, 0x0f, 0x08, 0x3c, 0x5a, 0x8d, 0x4b, 0x5f, 0xaa, 0x61, 0xa9, 0xaa, 0xe6, 0xa5, 0xa2, 0x5a, 0x96, 0x16, - 0xd5, 0xed, 0xe1, 0xe7, 0x27, 0x7e, 0xcf, 0x63, 0x5d, 0x98, 0x77, 0x25, 0xc8, 0xd9, 0xa6, 0x97, 0xa1, 0x92, 0x1b, - 0xee, 0x0a, 0x76, 0x2b, 0x85, 0x1f, 0xed, 0xe2, 0xd3, 0xbb, 0x1b, 0xf0, 0x56, 0x09, 0x7a, 0x35, 0xd3, 0x1c, 0x4f, - 0xd0, 0x2d, 0x26, 0x11, 0x20, 0x66, 0xa5, 0xa3, 0xbd, 0x0f, 0x1d, 0x0a, 0xca, 0x83, 0xec, 0x5a, 0x73, 0x8b, 0xfb, - 0x09, 0x26, 0xd4, 0xdf, 0x30, 0x01, 0x25, 0x63, 0x41, 0x54, 0x23, 0xa1, 0x46, 0x13, 0xde, 0x8a, 0x44, 0x00, 0xc4, - 0xfb, 0xa5, 0x4e, 0x72, 0x2f, 0x97, 0xa9, 0x50, 0x9d, 0x7b, 0x0b, 0x20, 0xf5, 0x54, 0x53, 0x5a, 0xea, 0x8b, 0x1a, - 0x06, 0xa9, 0xb8, 0xa6, 0x8c, 0x54, 0x09, 0x57, 0x7d, 0xc0, 0xfa, 0x86, 0xc5, 0xbc, 0xa2, 0x97, 0xac, 0x0d, 0x97, - 0xff, 0xd3, 0xfc, 0xe5, 0x98, 0x2d, 0xe4, 0x65, 0x27, 0x64, 0x8e, 0x65, 0x59, 0x8f, 0xac, 0x52, 0x8d, 0x97, 0xd6, - 0xe7, 0xb1, 0x97, 0xbf, 0xac, 0x05, 0xa2, 0x10, 0xd1, 0xe7, 0x75, 0x8c, 0xaa, 0x5c, 0x85, 0xbd, 0x0a, 0x64, 0x19, - 0x42, 0x6e, 0xd2, 0x50, 0x5a, 0x6f, 0x11, 0x8b, 0x16, 0x4b, 0x3c, 0x7d, 0x3f, 0xc8, 0xad, 0x19, 0x04, 0x6f, 0x03, - 0x88, 0x03, 0xba, 0xad, 0x4b, 0x2e, 0xf8, 0xff, 0xa8, 0x7f, 0x7a, 0x79, 0xf6, 0x3f, 0xa5, 0xba, 0x32, 0x22, 0xcf, - 0xd0, 0x77, 0x9a, 0x3c, 0x01, 0x0a, 0x62, 0xb0, 0x43, 0x34, 0x90, 0xf7, 0x53, 0xdf, 0xa1, 0x47, 0x20, 0x3c, 0x0e, - 0x05, 0x67, 0x30, 0x34, 0x55, 0x78, 0xa3, 0x41, 0x66, 0x3c, 0x1c, 0x3a, 0x11, 0x32, 0x34, 0x51, 0xe7, 0x74, 0x28, - 0x4b, 0x75, 0x25, 0xb3, 0xe6, 0x5f, 0x57, 0x31, 0x06, 0xfb, 0xf1, 0x72, 0xe5, 0xcb, 0x07, 0xed, 0x7e, 0xcf, 0xfe, - 0x64, 0x2e, 0x4c, 0xd1, 0x3b, 0xa9, 0x5b, 0x63, 0xd6, 0x1c, 0xf1, 0xc0, 0xb0, 0x3c, 0x8c, 0x1e, 0xf5, 0x84, 0xd8, - 0x6c, 0x87, 0x1e, 0x37, 0xed, 0x9b, 0x2c, 0xc3, 0x3c, 0xdc, 0x1f, 0x14, 0x76, 0x3f, 0x66, 0xde, 0xe5, 0xae, 0xc7, - 0x05, 0xbb, 0x3d, 0x1c, 0xd4, 0xaf, 0x41, 0xc1, 0x7f, 0xe4, 0x1d, 0x6b, 0x7b, 0x8c, 0xad, 0x47, 0x5e, 0x78, 0x9b, - 0x32, 0x5d, 0xd1, 0xca, 0x11, 0x0b, 0x27, 0x26, 0xd4, 0x18, 0x24, 0x31, 0x5c, 0xe5, 0x99, 0x7b, 0x0f, 0x41, 0x9c, - 0x71, 0x4e, 0x44, 0x7e, 0x22, 0x5b, 0x64, 0x7c, 0x5e, 0x7a, 0x6d, 0xb6, 0x6b, 0x42, 0x39, 0x46, 0xa8, 0x1c, 0x08, - 0xde, 0x05, 0x95, 0x43, 0xfb, 0xf1, 0xea, 0xa3, 0xcc, 0x16, 0xf5, 0x4f, 0xaf, 0x0c, 0xab, 0xe2, 0x2b, 0x7d, 0xdc, - 0xaa, 0x7f, 0x76, 0x74, 0x00, 0xaa, 0x7f, 0x40, 0xfa, 0x3d, 0xa5, 0xbc, 0x2e, 0x24, 0x1f, 0x99, 0x44, 0x73, 0xb3, - 0xa5, 0xc5, 0xba, 0x0b, 0x4b, 0x6d, 0x25, 0x8b, 0x43, 0x9d, 0xb7, 0x86, 0xd7, 0xb5, 0x6f, 0x4d, 0x8f, 0x0e, 0xf5, - 0x8b, 0xd4, 0xd6, 0xe7, 0xbf, 0xc3, 0x7d, 0xfd, 0x86, 0x51, 0xad, 0xb6, 0xc6, 0xa5, 0x27, 0xe9, 0xd3, 0x62, 0x51, - 0xd1, 0xd0, 0xc5, 0x3e, 0xfd, 0x2e, 0x1a, 0x1a, 0xe8, 0xd8, 0xb3, 0xb6, 0x5e, 0x69, 0x9c, 0xee, 0x0b, 0x74, 0xd0, - 0x69, 0x39, 0x42, 0xd2, 0xbd, 0x61, 0x60, 0x10, 0xa0, 0x98, 0xc1, 0x26, 0xc4, 0x74, 0xcb, 0xcf, 0x4e, 0xa3, 0x99, - 0xbb, 0x13, 0x6e, 0x7f, 0xb1, 0x3e, 0x01, 0xd5, 0x2f, 0xf3, 0x77, 0xaa, 0x68, 0x3e, 0xe2, 0x8f, 0x78, 0xd0, 0x86, - 0x44, 0xbe, 0x0e, 0x89, 0xf5, 0xb4, 0x31, 0x96, 0x6e, 0x88, 0xd8, 0xae, 0xab, 0x27, 0x0f, 0x2b, 0xaf, 0x6d, 0x34, - 0x75, 0xf9, 0x95, 0x6d, 0x5b, 0xfa, 0xbc, 0xf2, 0x80, 0x81, 0xe3, 0xae, 0x87, 0x0e, 0x7c, 0x25, 0xc9, 0xd8, 0x82, - 0xf7, 0x4a, 0xe2, 0x7f, 0x89, 0xfd, 0x3b, 0x39, 0x62, 0x9b, 0x1a, 0xa8, 0x59, 0xea, 0xee, 0x04, 0x9b, 0x35, 0xb5, - 0x90, 0x34, 0x47, 0x8f, 0x69, 0xf5, 0xd3, 0xf2, 0x98, 0xef, 0x76, 0x1e, 0x5b, 0x3f, 0xfb, 0x28, 0x0b, 0x2a, 0x4c, - 0xcf, 0xd8, 0x21, 0x70, 0xc6, 0xb0, 0xa8, 0x8c, 0x45, 0x99, 0xdc, 0xdb, 0x94, 0x13, 0x69, 0xb2, 0x7c, 0x1f, 0x7e, - 0xe7, 0x82, 0x0a, 0xe8, 0x35, 0x3e, 0x8f, 0xee, 0x50, 0x7e, 0x5c, 0xf6, 0x06, 0x3c, 0x3d, 0x48, 0x99, 0xea, 0x0e, - 0x3a, 0xa5, 0xe9, 0xd3, 0xbc, 0xfe, 0xb8, 0x1f, 0xfd, 0x84, 0xeb, 0x1f, 0xff, 0x93, 0x4c, 0x8f, 0x5f, 0x43, 0x32, - 0x4c, 0x82, 0xd3, 0x14, 0x76, 0xb5, 0xf2, 0xff, 0xdd, 0x32, 0xf5, 0x4a, 0x5c, 0x0c, 0x6f, 0xea, 0xf8, 0x01, 0x51, - 0x34, 0xeb, 0x23, 0xcb, 0x98, 0x4f, 0xdb, 0xf2, 0xc3, 0xb6, 0x54, 0x87, 0xb8, 0xc8, 0x9d, 0xcb, 0x92, 0xd8, 0x35, - 0x28, 0xd3, 0x1a, 0x29, 0xed, 0x33, 0xe6, 0xb0, 0x37, 0x93, 0x76, 0x2f, 0x2d, 0x6d, 0x29, 0xa4, 0xe0, 0x68, 0x8a, - 0x33, 0x1a, 0xc0, 0x7d, 0xac, 0x49, 0xdf, 0xda, 0x35, 0x7a, 0x3e, 0x1e, 0xcb, 0x4a, 0xae, 0x24, 0x9d, 0xcb, 0x52, - 0x0e, 0x1f, 0x71, 0x2b, 0xf7, 0x11, 0x23, 0x20, 0xe6, 0xc5, 0xaa, 0xd2, 0x02, 0x33, 0x44, 0x0d, 0x2e, 0x95, 0x8e, - 0xb1, 0x54, 0x06, 0x13, 0xb5, 0xbe, 0xbc, 0xa0, 0x5d, 0xbe, 0x81, 0x03, 0xa9, 0x3b, 0xef, 0x61, 0x75, 0x62, 0xa9, - 0xd0, 0xe5, 0xd0, 0xde, 0x96, 0xf4, 0xc4, 0xe5, 0x7c, 0x24, 0x90, 0xc6, 0x02, 0x54, 0x78, 0x6c, 0x5f, 0xe2, 0xcf, - 0x22, 0xf2, 0x47, 0x61, 0xf3, 0x22, 0xce, 0x06, 0x9a, 0x82, 0x56, 0x50, 0x8d, 0x69, 0xf4, 0x5f, 0x56, 0x09, 0x41, - 0x4a, 0xc1, 0x56, 0xd4, 0x1c, 0xf0, 0x0c, 0xd9, 0x38, 0x89, 0x44, 0x60, 0x87, 0xe9, 0xe0, 0x42, 0xdb, 0x2f, 0x64, - 0x89, 0xd6, 0x4f, 0x23, 0x63, 0x0f, 0x49, 0x78, 0xf8, 0x72, 0x99, 0xe8, 0x95, 0x38, 0x13, 0x6f, 0xe9, 0x5b, 0x0b, - 0xfe, 0x79, 0x5d, 0x0b, 0xf6, 0xd9, 0x20, 0x7b, 0x89, 0x8f, 0x3c, 0x0c, 0xf1, 0x74, 0x85, 0xdb, 0xee, 0x41, 0xe5, - 0x5e, 0x12, 0x0f, 0x6b, 0x7b, 0x7b, 0x70, 0xbe, 0xb3, 0xf6, 0xb4, 0x56, 0xad, 0x0f, 0x94, 0x6b, 0x4c, 0xfb, 0xe1, - 0xf5, 0x97, 0xf7, 0xad, 0x29, 0x95, 0x7e, 0x14, 0xba, 0x99, 0x84, 0xb1, 0xf2, 0x6c, 0xef, 0x4c, 0xf6, 0x61, 0x48, - 0x4f, 0xf5, 0x80, 0xd3, 0x8e, 0x12, 0xb7, 0x64, 0x35, 0x1e, 0x65, 0x6f, 0x12, 0xf4, 0xa9, 0xac, 0x68, 0x20, 0xa2, - 0x9a, 0x7f, 0x3f, 0x19, 0x0b, 0xcc, 0x0c, 0xc4, 0xe0, 0xe3, 0xb9, 0x6d, 0xc9, 0x2c, 0xe0, 0x7e, 0xcc, 0xdf, 0x36, - 0xd1, 0xa4, 0x1d, 0x3b, 0x08, 0x87, 0x51, 0x30, 0xef, 0xd5, 0x5b, 0xc2, 0xfd, 0x50, 0xca, 0xcf, 0xc0, 0xcf, 0x8e, - 0x81, 0x13, 0x9c, 0x15, 0xf1, 0x32, 0xb4, 0xdf, 0x10, 0xce, 0xc8, 0x44, 0xf0, 0xa3, 0xe2, 0xee, 0x00, 0xdb, 0x4d, - 0x73, 0xb8, 0xc7, 0x3f, 0x3d, 0x1b, 0x70, 0x27, 0x29, 0x7d, 0xc9, 0x24, 0x07, 0xef, 0x56, 0x19, 0x92, 0x2d, 0x15, - 0x39, 0xd9, 0xc4, 0x72, 0xda, 0x53, 0x8e, 0x70, 0x7b, 0xa7, 0x4b, 0xbf, 0xa7, 0x3c, 0x3a, 0xef, 0xc5, 0xa5, 0xde, - 0x43, 0x3c, 0x7a, 0xea, 0x6d, 0x83, 0xb6, 0xcd, 0xd2, 0xd2, 0x9c, 0x94, 0x2e, 0x75, 0xa6, 0x6b, 0x97, 0x89, 0xd1, - 0x95, 0x2f, 0x9a, 0x77, 0xc8, 0x15, 0x86, 0x28, 0x3d, 0x75, 0x60, 0xb3, 0xda, 0xa7, 0x44, 0x89, 0xd4, 0x61, 0x95, - 0x48, 0x7a, 0x14, 0x29, 0xc4, 0x27, 0x67, 0x89, 0xa0, 0xf7, 0x69, 0x6c, 0x01, 0xa5, 0x65, 0x35, 0x79, 0x14, 0xbd, - 0x62, 0xde, 0x8b, 0xdb, 0xd8, 0x29, 0x34, 0x8b, 0x4d, 0x36, 0x9b, 0xc9, 0xde, 0x4b, 0xff, 0xf5, 0xdf, 0xb9, 0xae, - 0xa0, 0xdf, 0x8f, 0xe9, 0x12, 0xff, 0x7a, 0x0d, 0xf0, 0x5e, 0x8d, 0x82, 0xe8, 0x61, 0x8a, 0xba, 0x2b, 0xe6, 0x80, - 0x2e, 0x84, 0xf0, 0x55, 0xa4, 0xab, 0x1a, 0x79, 0xba, 0x54, 0xfc, 0x49, 0xb2, 0xdb, 0x08, 0x9b, 0x3a, 0x6d, 0x4b, - 0x06, 0x68, 0x5f, 0x81, 0xeb, 0x24, 0xeb, 0x35, 0x8a, 0xc8, 0x1d, 0x14, 0xfd, 0x27, 0x7f, 0xd6, 0xc4, 0xcf, 0x16, - 0xf1, 0x63, 0x98, 0xf2, 0xb1, 0x4f, 0x32, 0xc6, 0x20, 0xe6, 0x14, 0x72, 0x13, 0x88, 0x77, 0x63, 0xc2, 0x96, 0x3c, - 0x83, 0x46, 0xbf, 0x37, 0x4d, 0x29, 0x55, 0x59, 0x2f, 0xab, 0xb6, 0x64, 0xd7, 0x8e, 0x5b, 0x7b, 0x16, 0xd3, 0xfc, - 0x18, 0x58, 0x8d, 0xdf, 0x8b, 0x14, 0xaf, 0x1c, 0x15, 0x76, 0xb7, 0xb8, 0x2a, 0x8e, 0x21, 0x78, 0xfd, 0xf8, 0xf3, - 0x20, 0x70, 0x22, 0x3b, 0xdd, 0x5b, 0x02, 0xe5, 0xbb, 0x6b, 0xe3, 0xf4, 0x37, 0xf9, 0xea, 0xf7, 0x7d, 0x74, 0x8f, - 0xfa, 0x33, 0xa6, 0xce, 0x5e, 0x25, 0x9c, 0x6e, 0x11, 0xfd, 0xcf, 0xa1, 0x2d, 0x2f, 0xb7, 0xe6, 0x8e, 0xaa, 0x70, - 0x9f, 0x18, 0xdf, 0x7b, 0x52, 0x26, 0xa3, 0x3d, 0xf8, 0xdb, 0x9d, 0x7a, 0xfe, 0xc7, 0x84, 0x23, 0x08, 0x6f, 0xba, - 0xf1, 0x41, 0xbf, 0xa7, 0x74, 0xfc, 0x34, 0x2f, 0x9f, 0xfe, 0xe1, 0x09, 0x97, 0x3f, 0xfe, 0x27, 0x39, 0xf6, 0x8e, - 0xb9, 0x34, 0xef, 0x80, 0xdd, 0x7d, 0x16, 0xf1, 0x74, 0xf2, 0x5a, 0x2e, 0x91, 0x3f, 0x55, 0x3d, 0x5e, 0x09, 0x2f, - 0x0f, 0x76, 0x02, 0x16, 0x68, 0x11, 0x79, 0xcf, 0xe6, 0x25, 0x68, 0xc1, 0x90, 0x1d, 0xc5, 0xd1, 0xc4, 0x9b, 0x01, - 0xa6, 0x42, 0x6a, 0x35, 0x88, 0x0e, 0xcc, 0x77, 0xdf, 0xc9, 0x7c, 0x20, 0xcc, 0x1a, 0x26, 0x54, 0x71, 0x27, 0xde, - 0xa5, 0x1e, 0x49, 0x4a, 0x75, 0x55, 0xef, 0x45, 0xa2, 0xcc, 0x7e, 0x40, 0x7a, 0xcc, 0x02, 0x63, 0x26, 0x42, 0x03, - 0xf0, 0x0c, 0x01, 0x91, 0xc3, 0x48, 0x4e, 0x92, 0xbe, 0xd5, 0x81, 0x11, 0xef, 0x38, 0x4d, 0x95, 0xaf, 0x04, 0x90, - 0x9f, 0x65, 0xe5, 0xf1, 0xdd, 0x5d, 0x9a, 0xd9, 0x70, 0x47, 0xe7, 0x5b, 0xef, 0x82, 0x6f, 0x68, 0xd2, 0x55, 0xb9, - 0xa7, 0x02, 0xc2, 0xc6, 0xd5, 0x25, 0x64, 0xc4, 0x39, 0xe4, 0x50, 0xa6, 0x60, 0x07, 0x52, 0x89, 0x75, 0xe8, 0xc9, - 0xc0, 0x1f, 0xbd, 0x2e, 0x01, 0x11, 0x4b, 0x29, 0x79, 0x92, 0xb3, 0xdd, 0x18, 0x8e, 0x4d, 0xe4, 0xe2, 0x3d, 0xa9, - 0x7b, 0x6f, 0x70, 0xbc, 0x86, 0x2a, 0x89, 0x54, 0x6b, 0x21, 0xad, 0x4a, 0xba, 0xef, 0x6c, 0x0f, 0x37, 0x9c, 0xfc, - 0x63, 0x6d, 0xe4, 0x8f, 0x4c, 0xee, 0xf1, 0x9e, 0x31, 0x69, 0x1e, 0x70, 0x96, 0xcd, 0xa2, 0x00, 0x46, 0x99, 0x6a, - 0x97, 0x9c, 0x75, 0x94, 0x4b, 0x2d, 0x4a, 0x5a, 0x06, 0xbe, 0x42, 0x91, 0xe4, 0xe6, 0x37, 0x7a, 0xbd, 0xe9, 0x7b, - 0x34, 0x97, 0x10, 0xe8, 0x95, 0x7e, 0xce, 0xd7, 0x7b, 0xba, 0x7a, 0xdf, 0x55, 0xb6, 0xb3, 0x0b, 0x56, 0x69, 0xac, - 0xf7, 0x86, 0x5b, 0x01, 0xc8, 0x02, 0xb1, 0xce, 0x0d, 0xcb, 0xed, 0xbe, 0x47, 0xd4, 0xeb, 0x33, 0x9f, 0xd8, 0x13, - 0x19, 0x51, 0xba, 0x45, 0x24, 0xba, 0x20, 0xe2, 0xff, 0x3f, 0xf7, 0x69, 0x2c, 0x26, 0xb7, 0xad, 0x91, 0x2a, 0xbf, - 0x6e, 0x9d, 0xe5, 0xc5, 0xfe, 0x2d, 0xd7, 0x15, 0x82, 0x62, 0x64, 0x06, 0x32, 0x45, 0xd3, 0x34, 0xbb, 0x0f, 0x93, - 0x19, 0x5b, 0x22, 0x34, 0xa2, 0x4c, 0x4a, 0xcb, 0x35, 0xd2, 0x42, 0x42, 0x2b, 0x07, 0x90, 0x61, 0x52, 0xda, 0x85, - 0x16, 0xd7, 0x3a, 0x24, 0x83, 0xe7, 0xb3, 0x49, 0x8f, 0xa7, 0x84, 0x24, 0x70, 0x73, 0xad, 0x22, 0xc2, 0x1c, 0xd5, - 0x16, 0x84, 0xf0, 0x63, 0x7f, 0x01, 0x3a, 0x61, 0x52, 0x03, 0xdf, 0x68, 0xf1, 0x2e, 0x08, 0x02, 0xb4, 0x78, 0x42, - 0x72, 0x0c, 0x0e, 0x40, 0x6a, 0xc9, 0x4a, 0x7f, 0x90, 0xa4, 0xeb, 0xb0, 0x3f, 0x1f, 0x33, 0x6e, 0xce, 0xa7, 0x9d, - 0xe9, 0xc9, 0x04, 0xe8, 0xd5, 0x07, 0x0e, 0xc3, 0x76, 0xc7, 0xc0, 0xf0, 0x28, 0xe8, 0xd3, 0x44, 0xf7, 0x7b, 0xb8, - 0xe9, 0xb2, 0xdd, 0x97, 0x43, 0x4c, 0x04, 0x8b, 0x99, 0xec, 0x66, 0x1c, 0xe1, 0xec, 0x86, 0x8d, 0xf6, 0x48, 0xb5, - 0xc6, 0x7e, 0x1f, 0x94, 0x2a, 0x36, 0x34, 0xdd, 0x49, 0xcf, 0x2c, 0xc3, 0xec, 0x16, 0x9a, 0xac, 0x2a, 0x03, 0x4e, - 0xa2, 0x02, 0x9c, 0x48, 0x61, 0xdb, 0xe8, 0xd8, 0xf0, 0xa6, 0x28, 0x81, 0xe6, 0xa1, 0x25, 0x46, 0x9f, 0x02, 0xef, - 0x52, 0x52, 0xf1, 0x8b, 0xd5, 0x98, 0x4a, 0xb2, 0xa1, 0x49, 0x8a, 0xcc, 0x72, 0x7c, 0xba, 0x8b, 0xdc, 0xb0, 0x3c, - 0x61, 0x3a, 0xb5, 0x66, 0x59, 0x91, 0x49, 0xd1, 0xfd, 0x7f, 0xf5, 0xe4, 0x90, 0x90, 0x56, 0xd5, 0xdc, 0x4d, 0x95, - 0x72, 0xf8, 0x8c, 0x5b, 0xc9, 0x04, 0xae, 0x89, 0x2f, 0xf4, 0x6c, 0x67, 0xdf, 0x80, 0xee, 0x94, 0x1a, 0x14, 0x77, - 0x21, 0x07, 0x85, 0x19, 0x35, 0xd8, 0xfb, 0x0b, 0xa2, 0xc7, 0xa3, 0xe4, 0xa6, 0xf1, 0x77, 0x0e, 0x57, 0xa8, 0x7a, - 0x23, 0xe9, 0xb4, 0x7f, 0xe0, 0x22, 0x70, 0x54, 0xa7, 0xc6, 0x98, 0x77, 0x37, 0x5a, 0xb7, 0x17, 0x55, 0xdc, 0x21, - 0x03, 0xec, 0x6b, 0x79, 0xd7, 0x02, 0x6b, 0xaf, 0x78, 0xd3, 0x48, 0x6e, 0x91, 0x8f, 0xff, 0xda, 0x67, 0xb7, 0xc5, - 0x2d, 0x5a, 0x64, 0x6a, 0xbb, 0x3c, 0x58, 0xf4, 0x65, 0x1b, 0x36, 0xa3, 0xd3, 0xb3, 0xbf, 0xb9, 0x90, 0xcd, 0x67, - 0x06, 0xb5, 0xc3, 0x4f, 0x1f, 0x4f, 0x5d, 0x1c, 0x38, 0x45, 0x2c, 0xf1, 0x10, 0x4e, 0xda, 0x56, 0xab, 0xcb, 0x14, - 0xbd, 0xec, 0xbe, 0x05, 0x92, 0x60, 0x16, 0xe7, 0x53, 0x0f, 0x5f, 0x88, 0x57, 0x28, 0x38, 0x6c, 0x1f, 0xf6, 0x57, - 0x71, 0x24, 0x6f, 0xfd, 0x53, 0xbd, 0x71, 0xd0, 0xf2, 0xab, 0x9c, 0xbb, 0x97, 0xeb, 0x77, 0x5d, 0x9b, 0xf2, 0x2a, - 0xee, 0xd7, 0xad, 0x7f, 0xda, 0x10, 0xa5, 0x62, 0x4f, 0x26, 0x3d, 0x9f, 0x9b, 0xe5, 0xc7, 0xef, 0x57, 0x26, 0x94, - 0x2f, 0x46, 0x18, 0x50, 0xab, 0x1f, 0xc2, 0x4c, 0x47, 0x8a, 0x6f, 0x92, 0x9a, 0xb2, 0x06, 0xad, 0x50, 0x4c, 0x59, - 0x6d, 0xe2, 0x7c, 0xe8, 0xa0, 0xd9, 0x48, 0x87, 0xc3, 0x6e, 0x49, 0xac, 0xf5, 0xd3, 0x54, 0x4f, 0x23, 0x70, 0x08, - 0x82, 0xf3, 0x83, 0x4a, 0x2d, 0x39, 0xc6, 0x73, 0x6e, 0xd5, 0x33, 0x64, 0x31, 0xa2, 0xca, 0x64, 0xcc, 0xe4, 0xe6, - 0x0d, 0x15, 0x46, 0x95, 0x79, 0xe8, 0x00, 0x0a, 0x47, 0x32, 0xdb, 0x71, 0xe3, 0x8b, 0xc7, 0x4c, 0x53, 0xd5, 0x0b, - 0x22, 0xbe, 0x7f, 0x5d, 0xe7, 0x8e, 0x84, 0x0e, 0xa4, 0xee, 0x1d, 0x91, 0xa9, 0x55, 0x9b, 0x8c, 0x0e, 0x68, 0xe8, - 0x3a, 0x8a, 0xcc, 0x8f, 0x55, 0x55, 0x91, 0x4d, 0xd5, 0xae, 0x4c, 0x46, 0x91, 0x43, 0xac, 0x3b, 0x4a, 0x59, 0x4e, - 0x96, 0xb5, 0xd1, 0xb5, 0x89, 0xc8, 0x6a, 0xb7, 0x25, 0x91, 0x6a, 0x3f, 0x48, 0x83, 0xd3, 0xd0, 0x7b, 0x0a, 0xb0, - 0xf9, 0xd4, 0x92, 0xa4, 0x5d, 0x4b, 0xd1, 0xf0, 0xb1, 0xf3, 0xd2, 0x5d, 0x77, 0x17, 0x96, 0x23, 0x84, 0x71, 0x4a, - 0x70, 0x0a, 0x2a, 0x2d, 0xe8, 0x18, 0x84, 0x37, 0x62, 0xba, 0x68, 0xf7, 0x00, 0xe0, 0xd9, 0xb9, 0xcc, 0x5e, 0x01, - 0x40, 0xca, 0xac, 0x02, 0x4d, 0xf3, 0xc7, 0x8d, 0x38, 0x94, 0x39, 0xd9, 0x91, 0x6a, 0x8a, 0x98, 0x14, 0xdf, 0x13, - 0x0d, 0x75, 0x82, 0xec, 0xc7, 0x94, 0x46, 0xfc, 0x41, 0x1e, 0x6c, 0xcb, 0xce, 0xb9, 0xdd, 0x98, 0x22, 0xc7, 0xc4, - 0x93, 0xa1, 0x15, 0xb9, 0x41, 0x3c, 0xe9, 0x7b, 0x7c, 0xad, 0xba, 0x70, 0xe5, 0xc1, 0xec, 0xf2, 0xe2, 0xfd, 0x31, - 0xff, 0x77, 0x1b, 0x85, 0xda, 0xe4, 0x61, 0xc5, 0x9f, 0x02, 0xb2, 0x3b, 0xa4, 0xcb, 0x63, 0x73, 0x89, 0x7f, 0xe5, - 0xc2, 0x0f, 0x9b, 0xd0, 0x61, 0x17, 0xd3, 0x69, 0x46, 0x2f, 0x83, 0x14, 0x84, 0x3d, 0x0b, 0x9f, 0x96, 0x4c, 0xe3, - 0x26, 0xc9, 0x24, 0xad, 0x7f, 0xb7, 0x29, 0xad, 0x69, 0xa4, 0xc6, 0x51, 0x77, 0x83, 0xf2, 0x84, 0x9f, 0xdf, 0x45, - 0xcd, 0x8f, 0xbd, 0xdb, 0xa6, 0x20, 0x9a, 0x60, 0x15, 0x86, 0x88, 0x72, 0xfa, 0xcd, 0x12, 0x67, 0x6e, 0x09, 0x7b, - 0x48, 0x79, 0xb5, 0x8d, 0x35, 0x3e, 0xdd, 0xbc, 0x54, 0x5b, 0x1f, 0x74, 0x4f, 0x55, 0xf5, 0x37, 0xdb, 0x86, 0xa2, - 0xd1, 0x29, 0xe1, 0x15, 0x45, 0x23, 0x3b, 0xf5, 0xc3, 0x21, 0x5b, 0x8d, 0xa2, 0x10, 0x59, 0xcc, 0xe2, 0x87, 0x5d, - 0x2a, 0x02, 0x1a, 0x86, 0xd9, 0xfc, 0xd3, 0xec, 0x4a, 0x46, 0x9e, 0x44, 0xb3, 0x6f, 0x3d, 0x63, 0xdb, 0xae, 0xdf, - 0xda, 0x67, 0x76, 0xeb, 0x3d, 0x66, 0x6b, 0x67, 0x77, 0x28, 0xa4, 0x83, 0x18, 0xf7, 0x6b, 0xd7, 0x16, 0x73, 0xf5, - 0x34, 0x64, 0x95, 0x8f, 0x2b, 0x46, 0x38, 0xfc, 0x1a, 0xe8, 0xe2, 0x33, 0x66, 0x41, 0x68, 0xd7, 0x38, 0x6d, 0x1f, - 0x0e, 0xd0, 0x9a, 0x1e, 0xcc, 0xf4, 0x4c, 0x0f, 0xd0, 0x6e, 0x4e, 0x10, 0xa0, 0x81, 0x12, 0x4f, 0xf0, 0xbf, 0x92, - 0x38, 0x57, 0xd9, 0xed, 0xfc, 0x5a, 0x23, 0x2b, 0xae, 0x3f, 0xa4, 0x82, 0x3e, 0x8d, 0x36, 0x13, 0x3a, 0x77, 0x4b, - 0xc5, 0x3b, 0x50, 0x5c, 0x2b, 0xc3, 0xee, 0x26, 0xa0, 0xcd, 0x53, 0xf1, 0xfb, 0xaa, 0xff, 0x28, 0xa0, 0x86, 0x1e, - 0x9b, 0xa3, 0xc4, 0x3d, 0xdb, 0xaa, 0x62, 0x56, 0x19, 0xb4, 0x03, 0x06, 0x83, 0xbf, 0xb6, 0x9a, 0xd6, 0xc8, 0xe6, - 0xe9, 0xef, 0x22, 0x7a, 0x4d, 0xdd, 0x19, 0xb9, 0x5f, 0xc1, 0x75, 0x1f, 0x59, 0xab, 0x86, 0x4e, 0xda, 0x73, 0xa7, - 0x61, 0x1b, 0x79, 0x82, 0x09, 0x74, 0x50, 0xb1, 0xa9, 0xc1, 0x05, 0xfb, 0x48, 0xd1, 0xb2, 0x56, 0x83, 0x66, 0x51, - 0x27, 0x72, 0x97, 0x81, 0x0a, 0xf1, 0x6d, 0x52, 0x06, 0xcb, 0x32, 0xb4, 0x8a, 0x38, 0x1e, 0x65, 0x36, 0xb8, 0x02, - 0x53, 0xe0, 0xad, 0x34, 0x94, 0xcd, 0x9e, 0xe0, 0x89, 0xd2, 0x12, 0x4e, 0x7e, 0x78, 0xe2, 0x35, 0x6a, 0x09, 0x3e, - 0x87, 0xa6, 0xfd, 0x07, 0x69, 0x69, 0xe6, 0xfa, 0x93, 0x23, 0x3d, 0x78, 0x0e, 0x6f, 0xcd, 0x04, 0xbe, 0x4b, 0x3c, - 0x1d, 0xb9, 0xf6, 0xfc, 0x43, 0xe2, 0x81, 0x5d, 0x61, 0x22, 0x24, 0x21, 0x2c, 0x5c, 0x7b, 0xa7, 0xad, 0xc5, 0xff, - 0x70, 0x06, 0x8c, 0x11, 0x23, 0x6c, 0x07, 0x05, 0x4e, 0x1f, 0xb6, 0x51, 0x84, 0x30, 0x5f, 0x7e, 0xcd, 0x8e, 0x91, - 0xdc, 0x54, 0x5e, 0x5c, 0xc4, 0x18, 0xc1, 0x56, 0xce, 0x4a, 0xfc, 0x80, 0x88, 0x4c, 0xe6, 0x05, 0xc3, 0x36, 0xfc, - 0x1e, 0xdf, 0xf5, 0xdd, 0xc4, 0xf7, 0x80, 0xf5, 0x8c, 0x0f, 0xd5, 0x73, 0xdf, 0xcf, 0x91, 0x44, 0xeb, 0x69, 0xfb, - 0x83, 0x20, 0x58, 0x6c, 0xba, 0xb5, 0x33, 0xb5, 0x86, 0xfe, 0x41, 0x98, 0xe0, 0xf6, 0xbc, 0xa9, 0x28, 0x56, 0xe2, - 0xf2, 0xfa, 0x82, 0x37, 0x3c, 0x1e, 0x60, 0x9f, 0xde, 0x59, 0xbb, 0x7b, 0x73, 0x97, 0xde, 0x8d, 0x3b, 0xf1, 0xa4, - 0x7f, 0x47, 0x3d, 0xe4, 0x6b, 0x9e, 0x31, 0xa3, 0x5d, 0x95, 0x65, 0xbf, 0xa4, 0xdf, 0x39, 0xa7, 0x33, 0x1d, 0xc1, - 0x44, 0xfa, 0x1b, 0xf8, 0xfa, 0x58, 0x6c, 0x7f, 0x21, 0x39, 0x46, 0xd3, 0x05, 0x66, 0x8d, 0xd4, 0x0b, 0x0b, 0x6d, - 0xda, 0x17, 0xdd, 0x2d, 0x40, 0xc5, 0x02, 0x55, 0x78, 0xe0, 0xed, 0xc8, 0x1f, 0x71, 0xbb, 0xd2, 0x8b, 0x81, 0x65, - 0xf6, 0x8f, 0x9c, 0xfd, 0xc9, 0xeb, 0x50, 0x89, 0xbe, 0x88, 0xd6, 0x27, 0x94, 0xa9, 0xb0, 0x4b, 0x44, 0x39, 0x72, - 0x23, 0x8e, 0x3e, 0x1d, 0x3d, 0x89, 0x80, 0x0d, 0x52, 0x37, 0x22, 0xac, 0xb8, 0x27, 0x9f, 0x45, 0x69, 0x40, 0x2f, - 0x80, 0xd4, 0x0f, 0x67, 0x1c, 0xea, 0xfa, 0x37, 0x61, 0x26, 0x5a, 0x1c, 0xc6, 0x73, 0x5f, 0x66, 0x55, 0x68, 0xdd, - 0xf3, 0x28, 0x3e, 0x49, 0xe4, 0x7b, 0xf7, 0xd8, 0xe2, 0x48, 0x70, 0xe6, 0x9b, 0xa0, 0x17, 0xf2, 0xa4, 0xbf, 0x65, - 0x41, 0x74, 0xe7, 0x17, 0x52, 0xab, 0x12, 0xb9, 0xb9, 0xc0, 0xb1, 0x60, 0x99, 0x43, 0x0e, 0x7f, 0xd6, 0x9e, 0xa5, - 0xf5, 0x3b, 0x18, 0xd5, 0x30, 0x8f, 0xff, 0x5c, 0x7c, 0xca, 0x42, 0x91, 0xa9, 0x17, 0x8f, 0x3f, 0x45, 0x69, 0x10, - 0xdd, 0x9e, 0x44, 0x28, 0xb6, 0x91, 0xba, 0x44, 0x90, 0x28, 0x1c, 0x67, 0x6a, 0xdf, 0xdf, 0xe5, 0xd9, 0x70, 0x17, - 0xcd, 0x3f, 0x0d, 0xa0, 0x27, 0xbf, 0x4a, 0xeb, 0xef, 0x17, 0x7f, 0x4a, 0x8a, 0xe0, 0xf6, 0xac, 0x9f, 0xce, 0xfc, - 0xd8, 0x59, 0xe9, 0x62, 0x10, 0x3d, 0x82, 0xd5, 0xb8, 0xa2, 0x4a, 0x7e, 0x06, 0x3f, 0xb1, 0xfd, 0x61, 0xe1, 0x66, - 0xc4, 0xbf, 0x8f, 0x4f, 0xee, 0xe2, 0x7c, 0x3a, 0x57, 0x58, 0x75, 0x38, 0x03, 0xa2, 0x86, 0xd1, 0xa5, 0xea, 0x62, - 0xc7, 0x91, 0xf9, 0x97, 0x05, 0x6b, 0x3c, 0x8b, 0x04, 0xa6, 0xf3, 0x0f, 0x2f, 0x3f, 0x62, 0xe4, 0xc9, 0x62, 0xb2, - 0xbf, 0xf8, 0x42, 0x9d, 0x38, 0xb8, 0xa7, 0xdd, 0xd6, 0xaf, 0x44, 0xc9, 0xa7, 0xf9, 0xe3, 0xe3, 0xfe, 0xba, 0x9f, - 0xf0, 0xe3, 0xc7, 0xbf, 0xf4, 0x57, 0xd9, 0x9a, 0x67, 0xdf, 0x85, 0x33, 0xca, 0x61, 0xb7, 0x17, 0x31, 0x3b, 0xd9, - 0xbf, 0xd7, 0x1f, 0x5f, 0x63, 0x4f, 0xee, 0xef, 0x19, 0x3e, 0xfd, 0xf6, 0xf2, 0xfe, 0x5d, 0x78, 0xb7, 0x90, 0xcb, - 0x8c, 0xbd, 0x39, 0x37, 0xd7, 0xa5, 0xac, 0xa5, 0xd9, 0x7a, 0x91, 0x80, 0x24, 0x88, 0x89, 0x0d, 0x2a, 0xf0, 0x44, - 0x12, 0x2d, 0xcb, 0x20, 0x47, 0x30, 0xe4, 0xe4, 0x38, 0xec, 0xce, 0x79, 0xc6, 0x82, 0x54, 0x19, 0x51, 0x5e, 0xa2, - 0x38, 0xdb, 0x7a, 0xcc, 0x00, 0x9c, 0x81, 0xf7, 0x11, 0xc8, 0xef, 0x6a, 0x10, 0x07, 0x4d, 0x06, 0x69, 0xf0, 0xed, - 0xa7, 0xae, 0x77, 0x64, 0xc3, 0x75, 0x65, 0xbc, 0xde, 0xbb, 0x97, 0x89, 0x93, 0x7d, 0x09, 0x66, 0xe3, 0x1d, 0x4a, - 0x99, 0x29, 0xc2, 0xdb, 0xcc, 0x33, 0xe7, 0x21, 0x16, 0x8e, 0x47, 0x92, 0x39, 0x88, 0x3f, 0x2d, 0x5d, 0xc1, 0xe9, - 0x38, 0xc9, 0x21, 0x3e, 0x55, 0xc1, 0x17, 0x0c, 0xbd, 0xce, 0xe6, 0xd3, 0xca, 0x9c, 0x9c, 0xac, 0xda, 0x70, 0x05, - 0xbe, 0xbd, 0xf5, 0x39, 0xbe, 0x6a, 0x61, 0xf3, 0x03, 0xbf, 0x73, 0xe1, 0xc1, 0xf6, 0xf1, 0xf5, 0x6b, 0xbf, 0x68, - 0xc6, 0x62, 0x09, 0x6b, 0xff, 0x58, 0xfa, 0x82, 0x50, 0x78, 0x2a, 0x04, 0x10, 0xfa, 0x82, 0x1a, 0x58, 0xce, 0x21, - 0x33, 0x67, 0x86, 0x9e, 0xbf, 0x66, 0x89, 0x23, 0x5a, 0xb0, 0xf1, 0x6b, 0xc3, 0xc2, 0x02, 0x4b, 0xed, 0xe5, 0x0d, - 0x58, 0x89, 0x85, 0x3d, 0xc6, 0x99, 0xe9, 0x6c, 0x8e, 0x99, 0x13, 0xf0, 0xb6, 0x65, 0x66, 0xa2, 0x0a, 0x9c, 0xe5, - 0x07, 0x5a, 0x9f, 0xa0, 0x5a, 0xc9, 0xbf, 0xba, 0x30, 0xae, 0x68, 0x83, 0xb3, 0xb9, 0xb4, 0x35, 0x04, 0xae, 0x4a, - 0x9a, 0x7c, 0x4c, 0xd6, 0x71, 0x27, 0x07, 0x3f, 0x4b, 0x03, 0x3e, 0x6b, 0x7c, 0x16, 0xe2, 0xb2, 0x24, 0xef, 0xd1, - 0x9c, 0xf5, 0xa1, 0x73, 0xad, 0x0d, 0x16, 0x6e, 0xec, 0x87, 0x29, 0xf8, 0xf0, 0x9a, 0x6c, 0xb7, 0xb5, 0x0f, 0x70, - 0x9f, 0xe6, 0xcd, 0xc7, 0x1d, 0xf4, 0x84, 0x9b, 0x1f, 0xff, 0x13, 0xf6, 0xed, 0xf2, 0x83, 0x2a, 0x85, 0x29, 0xf8, - 0xb8, 0xec, 0x8b, 0x22, 0xb2, 0xfd, 0x1e, 0xfa, 0x1e, 0xf8, 0x71, 0xd0, 0x70, 0xa1, 0x5f, 0xba, 0xcb, 0x18, 0x8d, - 0xe7, 0x4e, 0xb0, 0xda, 0x43, 0xe3, 0xba, 0x1e, 0x8c, 0xaa, 0x6c, 0x83, 0x61, 0x8d, 0x90, 0xa0, 0xcb, 0x63, 0x2b, - 0xfb, 0x2c, 0xc8, 0x06, 0x63, 0x25, 0x7b, 0x40, 0x09, 0x7b, 0xd0, 0x96, 0xd3, 0x00, 0x2c, 0x24, 0x1f, 0x37, 0xed, - 0x10, 0x68, 0xc8, 0x6a, 0x30, 0xdc, 0xe7, 0xaf, 0x89, 0xae, 0x2c, 0xad, 0x03, 0xfd, 0x07, 0xf7, 0x3d, 0x9a, 0x29, - 0xe2, 0xbe, 0x3c, 0xab, 0x29, 0xcb, 0x9d, 0xf6, 0xc9, 0x52, 0x1e, 0x7b, 0x18, 0x9e, 0x67, 0x0a, 0x39, 0x9d, 0xd3, - 0xaf, 0xb3, 0x35, 0x0e, 0xd2, 0x4a, 0x79, 0xd2, 0xbe, 0x4e, 0x5b, 0x5f, 0xf6, 0x9d, 0x88, 0xd5, 0x09, 0xee, 0x6a, - 0xa8, 0xd5, 0x4b, 0xaf, 0x0d, 0x86, 0xd3, 0x41, 0xfb, 0x0d, 0xe8, 0x6e, 0x69, 0x7d, 0x3b, 0xa9, 0x96, 0x48, 0x9c, - 0x1e, 0xe2, 0x76, 0x30, 0x9b, 0xa1, 0xb0, 0xb3, 0xad, 0xae, 0x2e, 0x09, 0x1c, 0xa0, 0xa9, 0x15, 0xf8, 0x70, 0xb7, - 0x88, 0xd5, 0x54, 0x1e, 0xe2, 0x63, 0x20, 0x77, 0x08, 0x38, 0x2f, 0xab, 0x90, 0xf3, 0x91, 0x61, 0x2d, 0xd6, 0x34, - 0xc3, 0x01, 0x53, 0x52, 0x07, 0x35, 0xdc, 0x28, 0x6b, 0xac, 0x8a, 0x96, 0x29, 0xb6, 0x3a, 0xfc, 0xba, 0xfd, 0xf3, - 0x35, 0x42, 0x90, 0xf5, 0x9b, 0x1f, 0x0b, 0xa2, 0x93, 0x41, 0x76, 0x8f, 0x38, 0x3e, 0x47, 0xc7, 0x5e, 0xae, 0xd6, - 0x5d, 0x94, 0x76, 0x27, 0x9b, 0xa9, 0xf2, 0xf9, 0x08, 0xf4, 0x92, 0x63, 0x70, 0xd8, 0x0e, 0x92, 0xe1, 0xc7, 0xd0, - 0x91, 0x50, 0x97, 0x97, 0xd4, 0x9a, 0x75, 0xf8, 0x61, 0xcf, 0xab, 0x5e, 0xce, 0x62, 0x37, 0x3d, 0x03, 0x8c, 0x53, - 0x6e, 0x7a, 0x7b, 0xac, 0x06, 0x00, 0x5b, 0x28, 0xbe, 0x86, 0x7d, 0x48, 0xc0, 0x3b, 0x14, 0xfd, 0xc1, 0xce, 0xc3, - 0x70, 0x51, 0x5c, 0xaa, 0x2c, 0x1d, 0x3f, 0x4e, 0xa3, 0x3a, 0x40, 0xf0, 0xf7, 0x78, 0xc2, 0xca, 0xd2, 0x42, 0x0d, - 0xee, 0x5c, 0x9a, 0xb8, 0x50, 0x04, 0xe2, 0x10, 0xfb, 0x59, 0xab, 0xea, 0xfe, 0x7d, 0xed, 0x8a, 0x00, 0xd4, 0xbe, - 0xa4, 0x83, 0x7b, 0x61, 0x87, 0xf9, 0x01, 0x6b, 0x5d, 0x23, 0x7c, 0x5e, 0xab, 0x29, 0x33, 0x3c, 0x10, 0x7c, 0x09, - 0xcf, 0xd5, 0x41, 0x59, 0x1d, 0xe4, 0x18, 0x29, 0x20, 0x59, 0x41, 0x74, 0x49, 0x90, 0x12, 0x3d, 0x11, 0x9b, 0xd1, - 0x3a, 0x32, 0x15, 0xd8, 0xb8, 0xb1, 0xc0, 0x30, 0xec, 0x12, 0x08, 0xf6, 0xc0, 0xb2, 0xe6, 0xe4, 0x95, 0xfe, 0xc0, - 0x6f, 0x11, 0x35, 0xac, 0x43, 0x94, 0x10, 0x6a, 0x56, 0x53, 0x11, 0x08, 0xaf, 0x8a, 0x98, 0x27, 0x93, 0xc9, 0x09, - 0xf0, 0xae, 0x3d, 0x51, 0xf4, 0x74, 0x67, 0xc7, 0xa2, 0x32, 0xcf, 0x2e, 0x52, 0xe1, 0x2a, 0x03, 0xaa, 0xc5, 0x81, - 0x2b, 0x87, 0x45, 0x74, 0x55, 0x4a, 0xee, 0x81, 0xcd, 0x7c, 0x03, 0xe7, 0x3a, 0x0d, 0xda, 0xca, 0xb1, 0x43, 0xc3, - 0x15, 0x5e, 0x14, 0x14, 0x0e, 0x94, 0xb2, 0x3b, 0x45, 0x98, 0xe6, 0xd6, 0x53, 0x91, 0x05, 0x0e, 0x60, 0x01, 0xf7, - 0xe6, 0xee, 0x22, 0x03, 0xb6, 0x8f, 0x86, 0x70, 0x6a, 0x01, 0x7a, 0x6f, 0xf3, 0x9f, 0xba, 0xcc, 0x69, 0xf3, 0x5f, - 0xbe, 0xa1, 0x6e, 0xad, 0x99, 0x4c, 0x8b, 0x5e, 0x86, 0xe4, 0x9b, 0xde, 0xaa, 0xbf, 0x7b, 0x31, 0x83, 0xc1, 0x7b, - 0x92, 0xcb, 0xac, 0x4f, 0x02, 0x4e, 0xbd, 0x0d, 0x1f, 0xa8, 0x8f, 0xb6, 0xa1, 0x75, 0x08, 0x01, 0x16, 0x87, 0x30, - 0x76, 0x82, 0x3d, 0xfc, 0x8c, 0x98, 0x4b, 0x11, 0xc6, 0x6b, 0xec, 0x05, 0x5f, 0xba, 0xd6, 0x9b, 0x9b, 0x62, 0xcf, - 0xce, 0xab, 0x45, 0x08, 0xa5, 0xa7, 0x69, 0x12, 0x9f, 0x5d, 0xba, 0x5d, 0xc6, 0x73, 0xd0, 0x44, 0x46, 0xa1, 0x10, - 0x91, 0x3c, 0x17, 0x34, 0x2d, 0xb4, 0xbd, 0x03, 0xea, 0x18, 0x44, 0xa5, 0x80, 0xf5, 0xf0, 0xa0, 0xd0, 0xe2, 0xeb, - 0xa7, 0xd9, 0x33, 0xd4, 0x9f, 0xd8, 0x39, 0xe1, 0x5f, 0x1d, 0xf8, 0x29, 0x11, 0xfb, 0x2d, 0x5a, 0xe0, 0xdc, 0xfc, - 0x6a, 0x28, 0xc0, 0xfe, 0x88, 0x09, 0x7f, 0x85, 0x01, 0x8c, 0x8c, 0xe0, 0xff, 0xf2, 0x4b, 0x56, 0x54, 0x30, 0xcc, - 0x4b, 0xe1, 0x9d, 0xe2, 0x23, 0x14, 0xd0, 0xf3, 0x92, 0x26, 0x5b, 0xc0, 0x79, 0x4b, 0x4d, 0xd7, 0x05, 0x90, 0x31, - 0x06, 0x20, 0x10, 0x57, 0x9f, 0x30, 0xef, 0x56, 0xa3, 0x64, 0x6f, 0xd3, 0x6f, 0x06, 0x68, 0xc6, 0xcd, 0x88, 0xd9, - 0x64, 0x68, 0xc1, 0xd2, 0x71, 0x34, 0xc2, 0x4f, 0xa3, 0x58, 0xff, 0xfa, 0x54, 0x09, 0xa8, 0xa4, 0x7b, 0x01, 0x7f, - 0x9b, 0x96, 0x78, 0x4b, 0xe3, 0xfc, 0x5e, 0xe3, 0x5b, 0xb7, 0x6f, 0xfd, 0xf2, 0xf1, 0xc3, 0xd5, 0x42, 0x58, 0xad, - 0x4f, 0x3e, 0xa5, 0xad, 0x73, 0x83, 0xe8, 0x51, 0xa8, 0x71, 0x28, 0x84, 0x46, 0xf2, 0x38, 0xc9, 0xc8, 0x66, 0xb3, - 0xac, 0x77, 0x21, 0xff, 0xd8, 0xd5, 0x7b, 0xc9, 0x95, 0x0d, 0xf2, 0xee, 0x2e, 0x30, 0x3b, 0xbb, 0xb5, 0x25, 0x6b, - 0x9e, 0xca, 0xa1, 0x1b, 0x3c, 0x53, 0x2d, 0x1d, 0x29, 0x2c, 0xf0, 0x48, 0xcb, 0xd8, 0x99, 0x3d, 0xbf, 0x06, 0x34, - 0x15, 0xe7, 0x0a, 0xea, 0x9c, 0x05, 0xa5, 0x41, 0xc1, 0x9f, 0xf4, 0x46, 0xde, 0xec, 0xb0, 0xd8, 0xbd, 0x83, 0xac, - 0x8e, 0xff, 0x37, 0xd2, 0xa8, 0xee, 0x12, 0x1a, 0x85, 0x67, 0xd1, 0x5b, 0xab, 0x0a, 0xdd, 0x3b, 0xdc, 0x55, 0x72, - 0x50, 0xfb, 0xda, 0xa6, 0x18, 0xad, 0x61, 0xae, 0xd6, 0xbe, 0xde, 0x65, 0xda, 0xcb, 0x3b, 0xe2, 0x1f, 0x7e, 0xb2, - 0x39, 0x42, 0x08, 0x99, 0xec, 0x9e, 0xfa, 0x14, 0x00, 0xbe, 0x15, 0x00, 0xc4, 0x08, 0xbf, 0x60, 0xdd, 0xe0, 0x29, - 0x76, 0x8f, 0x67, 0xb7, 0xa5, 0x16, 0xee, 0x23, 0xc4, 0x58, 0x3b, 0xee, 0xd7, 0x12, 0x1e, 0x09, 0xfc, 0xb6, 0x75, - 0xea, 0x71, 0xa8, 0x77, 0xf6, 0xd3, 0x4e, 0x22, 0x3e, 0xc6, 0x46, 0x5a, 0x0f, 0xe7, 0xd8, 0x92, 0xdf, 0x50, 0x3b, - 0x71, 0x72, 0xd7, 0xd2, 0x59, 0xf4, 0x0b, 0x01, 0xfc, 0xe5, 0xb7, 0x95, 0x35, 0x3f, 0x5c, 0xd8, 0xfe, 0x4b, 0xff, - 0x65, 0x61, 0xff, 0x39, 0xb7, 0x80, 0x8d, 0x04, 0x8c, 0x58, 0xdf, 0x8c, 0x1b, 0x0f, 0x18, 0xb1, 0x63, 0x00, 0xa4, - 0x83, 0x18, 0x01, 0x4d, 0x79, 0x28, 0x04, 0x2f, 0xa2, 0x37, 0x8a, 0xce, 0xcd, 0x98, 0x06, 0xb2, 0xf2, 0x9a, 0x4c, - 0xf5, 0x41, 0xd8, 0xf8, 0x59, 0xb7, 0xb6, 0x70, 0x93, 0x0f, 0x63, 0xbd, 0xb4, 0xe6, 0xcc, 0x02, 0xd0, 0xa7, 0xb8, - 0xbf, 0x55, 0xa9, 0xcd, 0x35, 0xf6, 0xe6, 0xb4, 0x93, 0x1f, 0x7e, 0x0e, 0x7b, 0xbb, 0xe3, 0xcf, 0x85, 0xb9, 0x74, - 0xf4, 0xf9, 0xe5, 0xcc, 0x98, 0x5a, 0xd7, 0xda, 0xfd, 0xd1, 0xc2, 0x03, 0x6f, 0x50, 0xd9, 0x28, 0xdb, 0xe7, 0x12, - 0xa4, 0x8d, 0x84, 0x71, 0x27, 0x4e, 0x83, 0xad, 0x7c, 0x23, 0x59, 0x4a, 0xdd, 0xda, 0xcc, 0x00, 0xb6, 0x9b, 0xe0, - 0x2d, 0xa3, 0x8b, 0xde, 0x17, 0x96, 0xe9, 0xe9, 0x2e, 0xae, 0xdd, 0x22, 0xda, 0xa1, 0x5c, 0xb3, 0x88, 0x67, 0x6a, - 0xc1, 0x93, 0xe4, 0x62, 0x0e, 0xb8, 0x81, 0x32, 0xb1, 0xa4, 0x7d, 0x9d, 0x39, 0x43, 0x64, 0x45, 0x7e, 0xa5, 0x9f, - 0x1a, 0x7f, 0xbf, 0x8d, 0xbf, 0x9a, 0xdb, 0x6c, 0xd7, 0xaf, 0xeb, 0x94, 0x28, 0xd4, 0xb4, 0xd8, 0xf7, 0xd9, 0xa2, - 0x27, 0x8c, 0xed, 0x63, 0x4e, 0x8c, 0xd5, 0x5a, 0xf3, 0xee, 0x7b, 0x3d, 0x75, 0x9e, 0x6a, 0x1f, 0x51, 0xf3, 0x05, - 0xf6, 0xfb, 0xa0, 0xbd, 0xeb, 0xf5, 0x67, 0xf1, 0xa1, 0x6f, 0x2f, 0xbe, 0x7c, 0x5c, 0xaa, 0x4f, 0x4c, 0xcd, 0xd1, - 0x43, 0x76, 0xa8, 0x3c, 0xc1, 0x14, 0x3e, 0x50, 0x26, 0xa2, 0x02, 0xde, 0xbb, 0xcd, 0xfb, 0xec, 0x45, 0xd7, 0x92, - 0xff, 0xa8, 0x41, 0x0b, 0x09, 0x6b, 0xee, 0x50, 0x15, 0xac, 0x3b, 0xe2, 0xbf, 0xce, 0x79, 0xad, 0x2c, 0x6b, 0x2b, - 0x42, 0xcb, 0x87, 0x1d, 0xbe, 0xf3, 0x54, 0xeb, 0x63, 0xdc, 0x62, 0x27, 0xb9, 0xdd, 0xf2, 0x4c, 0x14, 0xb7, 0xa0, - 0xea, 0x72, 0x04, 0x82, 0xb4, 0x01, 0x19, 0x69, 0x2b, 0x46, 0x2d, 0xdc, 0x27, 0xed, 0xd7, 0xf6, 0xbb, 0x10, 0x4b, - 0x4f, 0x6b, 0x9a, 0xb2, 0xd2, 0x4d, 0xec, 0x45, 0x4a, 0x11, 0x42, 0x66, 0x7d, 0xf0, 0xfa, 0x93, 0x9a, 0x61, 0x73, - 0x77, 0xb7, 0x3a, 0x23, 0x3a, 0x16, 0xae, 0x51, 0x22, 0x2b, 0xe2, 0x6e, 0xe3, 0x30, 0x8b, 0xcf, 0xa5, 0x7f, 0x96, - 0xe7, 0x60, 0xce, 0x09, 0xed, 0xa6, 0x78, 0xa1, 0x19, 0xba, 0xe9, 0x1c, 0x3f, 0x30, 0x0c, 0x24, 0xbd, 0x40, 0xfe, - 0x3a, 0x95, 0xe3, 0x94, 0x23, 0x6a, 0x2d, 0x2b, 0xd1, 0xb6, 0xa0, 0x60, 0xf1, 0xd8, 0xdc, 0x01, 0xbe, 0x1b, 0x7e, - 0x5c, 0x60, 0xbe, 0x79, 0xf7, 0x19, 0xa2, 0x87, 0xf2, 0x40, 0xcd, 0x3b, 0xab, 0x95, 0x09, 0xde, 0x90, 0xc6, 0x9f, - 0x4a, 0x12, 0xbb, 0x37, 0x34, 0x69, 0x75, 0xd3, 0xbd, 0xb1, 0xd9, 0x2d, 0x65, 0x0e, 0xf3, 0xb0, 0xe9, 0x8a, 0x62, - 0x14, 0xf0, 0xac, 0x7b, 0x3b, 0x94, 0x95, 0x02, 0x16, 0xe0, 0x04, 0xea, 0x83, 0x5a, 0x58, 0x2c, 0x8f, 0x13, 0xf5, - 0x98, 0x59, 0x0e, 0x7c, 0x6d, 0xf0, 0xb2, 0x8f, 0xce, 0x12, 0xb0, 0x94, 0x6a, 0x21, 0x6d, 0x2a, 0x29, 0x7e, 0x99, - 0x93, 0xd3, 0xdb, 0x54, 0x13, 0xb5, 0xc9, 0xed, 0x7e, 0xdf, 0x71, 0x06, 0xad, 0xe4, 0xe0, 0x0e, 0x8e, 0xbd, 0x1e, - 0x84, 0x6c, 0x54, 0x40, 0xa6, 0xd9, 0x9f, 0xf2, 0xc8, 0x4e, 0x4b, 0xf9, 0x9c, 0xd4, 0xb4, 0x29, 0x02, 0xd6, 0x6c, - 0xbc, 0x9b, 0x36, 0x92, 0x62, 0xed, 0x0c, 0x47, 0x3c, 0x37, 0x8d, 0x8b, 0xef, 0xf3, 0x1f, 0x7b, 0xca, 0x16, 0xc2, - 0xea, 0x69, 0x7c, 0xd4, 0x3b, 0xbd, 0x32, 0xad, 0x1a, 0x2a, 0x73, 0x36, 0x96, 0xf0, 0x01}; + 0x5b, 0x36, 0x7a, 0x53, 0xc2, 0x36, 0x06, 0x5a, 0x1f, 0xd4, 0x4e, 0x00, 0xb3, 0xd6, 0xea, 0xff, 0x0a, 0xab, 0x51, + 0x94, 0xb1, 0xe6, 0xb0, 0x2e, 0x61, 0xbb, 0x1a, 0x70, 0x3b, 0xd8, 0x06, 0xfd, 0x7d, 0x2f, 0x1a, 0x00, 0x55, 0x35, + 0xe3, 0xa8, 0x1c, 0x62, 0xca, 0xd3, 0xb4, 0x00, 0xdb, 0x5e, 0x43, 0xa7, 0x14, 0x08, 0xa4, 0x51, 0x99, 0x96, 0xb6, + 0xf5, 0x0e, 0x99, 0x80, 0x52, 0x31, 0xe8, 0x10, 0x27, 0x1c, 0x04, 0x11, 0x58, 0xc5, 0x1c, 0xcc, 0xd4, 0x74, 0x4c, + 0x33, 0x11, 0xbb, 0xdb, 0xb0, 0xb4, 0x0a, 0x87, 0x13, 0x12, 0xb4, 0x8f, 0xe7, 0xd1, 0xc8, 0x85, 0x26, 0x07, 0xab, + 0x2e, 0x7a, 0x6e, 0x93, 0xb9, 0x4c, 0xb4, 0x84, 0x5b, 0x59, 0xda, 0xde, 0x2f, 0x74, 0x88, 0x3c, 0x53, 0x3b, 0xfd, + 0x28, 0xf8, 0x60, 0x4b, 0xf2, 0xc2, 0x03, 0xda, 0x33, 0x59, 0xe4, 0x2a, 0x48, 0x26, 0xde, 0x20, 0x6e, 0xcb, 0x83, + 0xef, 0x81, 0x7a, 0x6b, 0x36, 0x9a, 0x3f, 0x38, 0x8e, 0xfd, 0xf9, 0x7e, 0x73, 0xab, 0x6e, 0x85, 0xf0, 0x62, 0xe0, + 0x60, 0x60, 0x23, 0x1b, 0x11, 0xaf, 0x39, 0x32, 0xed, 0x79, 0x20, 0x27, 0x04, 0x1f, 0x6b, 0xf4, 0xd9, 0x97, 0x2f, + 0x38, 0xe4, 0x5b, 0x75, 0xbb, 0xb4, 0xfe, 0xd5, 0xfb, 0x5f, 0xa5, 0xc2, 0x5c, 0x88, 0xc6, 0xdf, 0xd0, 0x1e, 0x10, + 0xa7, 0x44, 0x3b, 0xdd, 0xb8, 0xbd, 0x2c, 0x7a, 0x10, 0x61, 0xbe, 0x8b, 0xbb, 0x3c, 0x10, 0x0e, 0x5f, 0x06, 0xc6, + 0xe0, 0xf2, 0xe6, 0x88, 0xa8, 0xb8, 0xa2, 0xab, 0xf7, 0x6b, 0xab, 0xe9, 0xfb, 0xbd, 0xa6, 0xfe, 0xd7, 0xef, 0x23, + 0xd3, 0x86, 0xa9, 0xdc, 0x57, 0x3a, 0xf7, 0xb8, 0x49, 0x6e, 0x45, 0x76, 0xda, 0xa6, 0x21, 0xc3, 0x2b, 0x0f, 0xac, + 0xc9, 0x85, 0x03, 0x60, 0xdd, 0x28, 0x5d, 0xe5, 0x3b, 0xfb, 0xf3, 0xbb, 0xdc, 0xc2, 0x94, 0xab, 0x90, 0x2b, 0x05, + 0xc8, 0x64, 0x3f, 0x3f, 0xc8, 0x1a, 0xe3, 0xef, 0x17, 0x88, 0x77, 0x9f, 0x18, 0x8d, 0xda, 0xd2, 0xc0, 0xb8, 0x5b, + 0x99, 0x6e, 0xd9, 0x12, 0xaa, 0xdc, 0x2f, 0xeb, 0xff, 0xff, 0xfb, 0x4e, 0xff, 0xbf, 0x7e, 0xed, 0x55, 0x22, 0xe6, + 0x8a, 0x96, 0x64, 0x4c, 0xdf, 0x4b, 0x2c, 0xef, 0x43, 0x42, 0x69, 0x18, 0x37, 0x29, 0x19, 0x40, 0x1f, 0x19, 0x8a, + 0x6b, 0x84, 0xb5, 0x31, 0x6a, 0x1d, 0xd9, 0x57, 0x5b, 0x04, 0xbb, 0xd6, 0xde, 0xfa, 0x52, 0xfd, 0xbe, 0x7e, 0x1f, + 0xe7, 0x5d, 0xc3, 0x72, 0xc9, 0x69, 0x3a, 0x6f, 0xf7, 0x1e, 0x6d, 0x29, 0x74, 0xce, 0x4b, 0xde, 0x98, 0xe5, 0x62, + 0x40, 0x34, 0x7a, 0xba, 0x6d, 0x0c, 0x30, 0x01, 0xd0, 0x92, 0x98, 0x29, 0xed, 0xfb, 0xea, 0xeb, 0x7f, 0xfd, 0x56, + 0x3a, 0x29, 0x0a, 0x1f, 0xd9, 0xb7, 0x84, 0x3a, 0x26, 0xfa, 0xd6, 0xce, 0x76, 0x3a, 0x32, 0x19, 0x0a, 0xb2, 0x94, + 0xc7, 0x80, 0xbe, 0x24, 0x74, 0x27, 0x0a, 0xff, 0x5f, 0x5f, 0xd3, 0xfa, 0xfa, 0x95, 0x08, 0xbb, 0xcc, 0xa5, 0x4e, + 0x51, 0xa8, 0x7b, 0x7f, 0x4f, 0x49, 0xce, 0xb2, 0xec, 0x9e, 0x0a, 0x41, 0xcb, 0xb4, 0x8d, 0x17, 0xe1, 0x00, 0xdc, + 0x13, 0x13, 0x59, 0xf7, 0x30, 0x55, 0xeb, 0xbf, 0x9f, 0x97, 0x0d, 0x67, 0x15, 0x30, 0x14, 0x61, 0x0c, 0x48, 0xaa, + 0xd8, 0x41, 0x5a, 0x75, 0x4b, 0xd3, 0x16, 0xa5, 0xc1, 0xd4, 0xc8, 0x9c, 0x84, 0x1c, 0x78, 0x01, 0xe8, 0x24, 0x45, + 0xca, 0xff, 0x73, 0xbe, 0x2d, 0xad, 0xfe, 0x74, 0x75, 0x79, 0xa2, 0xba, 0x1f, 0x6a, 0x09, 0x10, 0xc6, 0x50, 0xb3, + 0x6c, 0x4a, 0xe7, 0x9f, 0x5d, 0xbf, 0x26, 0x78, 0xa6, 0x37, 0x07, 0xce, 0xa5, 0x55, 0xaf, 0xef, 0x06, 0xd4, 0x72, + 0x4f, 0x48, 0xdf, 0x15, 0x1b, 0xec, 0xd7, 0x48, 0xa6, 0xe5, 0xbd, 0xf3, 0x85, 0x88, 0xaa, 0x1c, 0x80, 0x11, 0xb4, + 0x51, 0x68, 0xa0, 0xbc, 0xbd, 0xf6, 0xaa, 0x6f, 0x55, 0x94, 0x8e, 0x0d, 0x8c, 0xc0, 0x32, 0xcb, 0xaf, 0x77, 0x27, + 0x94, 0x5c, 0xad, 0xbd, 0x6f, 0x92, 0xf0, 0x18, 0x70, 0x5a, 0x6c, 0x58, 0x38, 0x2f, 0xd9, 0x90, 0xa8, 0xf9, 0x9a, + 0xad, 0xc0, 0x05, 0x0a, 0xeb, 0x98, 0xcb, 0xaa, 0x7a, 0x8b, 0x0a, 0x89, 0xf8, 0x75, 0xfb, 0x7e, 0xc6, 0x7d, 0x4c, + 0x37, 0xc3, 0x0c, 0x86, 0x8d, 0x82, 0x27, 0x18, 0xd7, 0x33, 0xb5, 0x4c, 0x5f, 0x6f, 0xa7, 0x52, 0x3e, 0xdd, 0x19, + 0x97, 0x57, 0x40, 0x5b, 0x29, 0xed, 0xd9, 0x0b, 0xb1, 0xcb, 0x58, 0x04, 0x08, 0x0d, 0x20, 0x51, 0xe9, 0x1b, 0x22, + 0xf6, 0x9a, 0x6f, 0xe8, 0xe9, 0xbc, 0x01, 0x2c, 0x70, 0xf8, 0x86, 0x54, 0x72, 0xa5, 0x38, 0x22, 0xd0, 0xcb, 0x95, + 0xe1, 0xc1, 0xb5, 0xb9, 0x59, 0x01, 0xae, 0xd5, 0x5a, 0x4a, 0xfa, 0x13, 0x37, 0x9b, 0xd6, 0xff, 0x3e, 0x2f, 0xce, + 0xdb, 0xec, 0x44, 0xba, 0xfe, 0x92, 0xe3, 0xe4, 0x4a, 0xe9, 0xd9, 0x82, 0x09, 0x25, 0xcc, 0xb0, 0x86, 0x01, 0x93, + 0xa6, 0xd5, 0x3e, 0x3c, 0x24, 0x1f, 0x50, 0xab, 0x6f, 0xf8, 0x83, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, + 0x74, 0x20, 0x44, 0xf6, 0x00, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xcc, 0x2a, 0x50, 0x0d, 0x90, 0x6c, 0x59, + 0xbf, 0xd6, 0x62, 0x53, 0x71, 0xcd, 0xbb, 0xcc, 0xef, 0xa2, 0x33, 0x7e, 0x18, 0x56, 0x64, 0x44, 0x66, 0x23, 0x5d, + 0x0d, 0xcb, 0x36, 0xb2, 0x9c, 0x06, 0xf6, 0xbe, 0xf7, 0x7f, 0x14, 0xfe, 0xff, 0x91, 0xc5, 0x89, 0x88, 0x2c, 0x50, + 0x91, 0x59, 0xc5, 0x39, 0x99, 0x05, 0xcc, 0xa8, 0x0a, 0xe0, 0x8c, 0x0a, 0x60, 0x1f, 0x1d, 0x90, 0x63, 0x41, 0xd0, + 0x68, 0x9a, 0x6c, 0xf6, 0xd1, 0x90, 0x2d, 0x6f, 0x77, 0x5a, 0xac, 0x38, 0x94, 0xeb, 0x19, 0xd9, 0x96, 0xfc, 0x6e, + 0x07, 0xca, 0x9a, 0xa5, 0xb4, 0xd2, 0xd1, 0x7d, 0x73, 0x6f, 0x76, 0xca, 0xa9, 0x23, 0x50, 0x69, 0xd5, 0x56, 0x08, + 0xd7, 0xcc, 0xec, 0x06, 0x76, 0x3f, 0xe7, 0x97, 0x36, 0x1f, 0x37, 0xc5, 0xa4, 0x98, 0x94, 0xe0, 0x80, 0xe4, 0x19, + 0x7b, 0xc6, 0x12, 0x0a, 0xc7, 0xf2, 0xde, 0xa9, 0x3f, 0x86, 0xdf, 0x43, 0x69, 0x61, 0x30, 0x75, 0xa6, 0x69, 0xfa, + 0xef, 0xb6, 0x31, 0xab, 0x2f, 0xd7, 0xca, 0xcc, 0x2d, 0xcd, 0x10, 0x42, 0x0a, 0xa0, 0xa2, 0xeb, 0xff, 0x36, 0xbe, + 0xd6, 0x57, 0x8e, 0xda, 0xfa, 0x75, 0xd4, 0xdd, 0x7e, 0x5c, 0x67, 0x08, 0x10, 0x02, 0xed, 0x3c, 0x64, 0x4a, 0x75, + 0xdb, 0x71, 0x9e, 0x3d, 0x4d, 0x08, 0x21, 0x04, 0xe2, 0xa8, 0xe2, 0xf8, 0x5f, 0x23, 0x9d, 0x4a, 0x1b, 0x02, 0x0d, + 0xa4, 0x48, 0xfd, 0x1b, 0xeb, 0x6f, 0x0d, 0xdb, 0xf7, 0xf4, 0x10, 0x9d, 0xd8, 0xd3, 0x00, 0xa1, 0x36, 0x49, 0xbe, + 0xd8, 0x9a, 0xa7, 0xb5, 0x6d, 0x74, 0x2c, 0x43, 0x2d, 0x7f, 0xdf, 0x4c, 0xbf, 0x6d, 0x30, 0x06, 0x2c, 0x33, 0x25, + 0x81, 0x19, 0xf2, 0xb9, 0x6e, 0x04, 0xf7, 0xcf, 0x4c, 0x26, 0xce, 0x1e, 0x07, 0x80, 0xd3, 0xb1, 0x47, 0x5b, 0x88, + 0x19, 0x28, 0xc7, 0xb9, 0x83, 0x9b, 0x5b, 0x23, 0x98, 0xf6, 0xf6, 0x50, 0xb2, 0xdd, 0x47, 0x21, 0xd6, 0x20, 0x5a, + 0x78, 0x61, 0x76, 0xf4, 0x81, 0xc9, 0xdb, 0x4e, 0x15, 0xbd, 0xa5, 0x5b, 0x7e, 0xc2, 0x1c, 0x81, 0x66, 0xf4, 0x92, + 0x5f, 0x04, 0xf0, 0xbe, 0x7d, 0x0f, 0x45, 0x99, 0x04, 0xca, 0xfe, 0xfa, 0xc9, 0x96, 0x91, 0x9d, 0x9f, 0xb8, 0x6b, + 0x7b, 0xc3, 0xe6, 0xe0, 0x21, 0x83, 0x27, 0x75, 0x98, 0xd9, 0x7e, 0x29, 0x3f, 0xe1, 0x6a, 0x19, 0xe6, 0x36, 0xe6, + 0xf3, 0xfd, 0x14, 0x5d, 0xa1, 0x21, 0x63, 0x41, 0xea, 0xb9, 0xf7, 0x87, 0xc6, 0xf2, 0xc7, 0x64, 0x59, 0x06, 0x6e, + 0xcb, 0x89, 0xc7, 0x92, 0xfa, 0xc5, 0x52, 0x4d, 0xdf, 0x93, 0x26, 0x01, 0x80, 0xac, 0xb5, 0x0d, 0xfd, 0x08, 0x57, + 0x71, 0x7d, 0xad, 0x5c, 0x14, 0xe3, 0x9a, 0x6f, 0x87, 0x09, 0x06, 0x92, 0xf5, 0x13, 0x28, 0x6e, 0x7b, 0xf7, 0x6f, + 0xcf, 0x6e, 0x6d, 0x59, 0x64, 0xd4, 0x74, 0x38, 0xbb, 0x0f, 0x9d, 0x69, 0x03, 0x8a, 0xb8, 0xc3, 0xdd, 0xa7, 0x63, + 0x4d, 0x41, 0x62, 0xc3, 0x21, 0x83, 0xe7, 0x02, 0x1d, 0xcb, 0x3e, 0xa9, 0xa5, 0x24, 0x6b, 0x72, 0xe6, 0xd2, 0x10, + 0x66, 0xa3, 0x73, 0x76, 0x1b, 0x4b, 0x07, 0xdc, 0x96, 0x33, 0xda, 0x45, 0x26, 0xf7, 0xbc, 0x89, 0xef, 0x68, 0xcc, + 0x2f, 0xbb, 0xc0, 0xde, 0xfa, 0x20, 0xdb, 0x42, 0xd0, 0x6c, 0xcc, 0xec, 0xc0, 0x37, 0xde, 0x77, 0xd3, 0x21, 0x09, + 0x12, 0x4d, 0xdf, 0xb7, 0xa0, 0x79, 0x31, 0xfa, 0xb8, 0xee, 0x61, 0xab, 0x50, 0xdf, 0xfe, 0x88, 0x87, 0x19, 0x9e, + 0x78, 0x39, 0x23, 0x5f, 0xef, 0xdd, 0xe6, 0x65, 0xe7, 0xd1, 0x17, 0x31, 0xbe, 0x3d, 0xbb, 0x7d, 0xb9, 0x79, 0x64, + 0xf7, 0x11, 0xd6, 0xbe, 0x1b, 0x12, 0x76, 0x35, 0xbf, 0x77, 0x1b, 0x7e, 0xf4, 0xda, 0x4b, 0x35, 0xab, 0xc9, 0x7f, + 0xfa, 0xfe, 0x13, 0xda, 0xa8, 0x1d, 0xdc, 0xc3, 0xfd, 0x05, 0xc2, 0xb3, 0xa6, 0x38, 0x17, 0x58, 0x73, 0x18, 0x7f, + 0xb6, 0x66, 0xc9, 0x3f, 0x3b, 0x22, 0xf4, 0x39, 0xcc, 0xd7, 0x39, 0x6f, 0xcf, 0x62, 0x6a, 0xfd, 0x4a, 0x44, 0x61, + 0x22, 0x2a, 0x83, 0x26, 0x28, 0xca, 0x2b, 0x27, 0x7d, 0xc7, 0x45, 0x49, 0x20, 0x91, 0xdd, 0x52, 0x2b, 0xa5, 0x75, + 0xe1, 0xe4, 0xde, 0xef, 0x00, 0x02, 0xfd, 0x39, 0xb6, 0x2c, 0xbb, 0xe4, 0xf5, 0x4b, 0x49, 0x7d, 0xc7, 0x3c, 0xcd, + 0x3d, 0x00, 0x91, 0x0a, 0xdd, 0x2c, 0x65, 0x61, 0x89, 0x12, 0x79, 0x36, 0x9e, 0xeb, 0xbc, 0xca, 0xd0, 0x43, 0xb7, + 0xef, 0xdb, 0x25, 0xf2, 0xf0, 0x7c, 0x86, 0x03, 0x7c, 0xc7, 0x9c, 0x53, 0xbd, 0xc2, 0x84, 0xbc, 0x72, 0x56, 0xdc, + 0x8f, 0xa1, 0xd4, 0x68, 0x22, 0x56, 0xe4, 0x66, 0x34, 0xc8, 0x7b, 0x46, 0x6e, 0xaa, 0xfd, 0x52, 0x5b, 0x33, 0x33, + 0xd7, 0xb7, 0xad, 0x96, 0x71, 0x86, 0x72, 0x2f, 0xaa, 0x3a, 0xaa, 0xef, 0x49, 0x20, 0x3d, 0xcb, 0x19, 0xd7, 0x37, + 0x6f, 0x56, 0x94, 0x5f, 0x2b, 0x95, 0x50, 0xf6, 0x0d, 0x35, 0x79, 0xcd, 0xec, 0x4b, 0xea, 0x1a, 0xe6, 0x29, 0xd2, + 0x76, 0x3a, 0xf2, 0x5c, 0x14, 0x32, 0x68, 0x05, 0x7b, 0x9e, 0x3c, 0xba, 0xf6, 0x65, 0x5e, 0xe2, 0x2f, 0x2b, 0xcb, + 0x88, 0x04, 0x68, 0xe4, 0x5f, 0x10, 0xcd, 0x0c, 0x54, 0xc5, 0xd3, 0x64, 0xe1, 0x24, 0x68, 0x71, 0xa2, 0x0d, 0x9e, + 0xfd, 0x7e, 0xdb, 0xec, 0x83, 0x12, 0x2e, 0xaa, 0xd4, 0x7d, 0x4f, 0x13, 0xf2, 0xf0, 0x73, 0x91, 0xac, 0x65, 0xa0, + 0xd7, 0x60, 0x9e, 0x26, 0x20, 0x15, 0x96, 0xc9, 0x58, 0xe8, 0x82, 0x9a, 0xd1, 0x4d, 0x93, 0xe9, 0x11, 0x5f, 0xde, + 0xe2, 0xa2, 0xb8, 0xd5, 0x6a, 0xcb, 0x37, 0xb3, 0xb4, 0x63, 0xda, 0x02, 0xda, 0x1f, 0x3a, 0x81, 0x27, 0x6c, 0x1e, + 0x0b, 0xef, 0x26, 0x27, 0x23, 0x8c, 0x3f, 0xf7, 0x72, 0xa4, 0x1d, 0x6a, 0x77, 0x42, 0xf4, 0xea, 0x40, 0xe0, 0xbe, + 0x50, 0xb6, 0x62, 0xec, 0x4d, 0x12, 0x51, 0xdd, 0x7f, 0x40, 0xb7, 0xf6, 0xbf, 0x59, 0xbb, 0xf4, 0x45, 0xd0, 0x58, + 0x09, 0x47, 0xd2, 0xfa, 0x6d, 0xa8, 0x3d, 0x44, 0x00, 0x4e, 0xaf, 0x82, 0x19, 0x76, 0xdb, 0x80, 0xd9, 0x71, 0x51, + 0x8e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd0, 0x32, 0xba, 0xa9, 0xfd, 0x71, 0xfc, 0x21, 0x63, 0x96, 0xb6, 0x30, 0xb5, + 0xaf, 0x1a, 0x7f, 0x69, 0xd0, 0x48, 0xc5, 0x79, 0xed, 0xd0, 0xc0, 0x4f, 0xec, 0x0b, 0x96, 0x83, 0x23, 0x41, 0x2f, + 0xf3, 0xc1, 0x33, 0x97, 0x6a, 0xb0, 0xbc, 0x39, 0x72, 0xa0, 0x10, 0xb6, 0x14, 0xa1, 0x6c, 0xb0, 0xb5, 0xd2, 0x8a, + 0x55, 0x4f, 0x18, 0x9b, 0xf7, 0xa7, 0xb7, 0x26, 0xb2, 0x29, 0x5b, 0x38, 0x4c, 0xf5, 0x85, 0x82, 0x64, 0x7f, 0x16, + 0x77, 0x59, 0x26, 0xc0, 0x41, 0xc2, 0xf0, 0x82, 0x8e, 0x24, 0xdf, 0x07, 0x6f, 0xfa, 0x2c, 0x58, 0x18, 0x6d, 0x9b, + 0x1f, 0x6d, 0xbd, 0x17, 0xcf, 0x2c, 0x88, 0x6f, 0x16, 0x14, 0xdb, 0xb2, 0xe2, 0x08, 0x4b, 0x35, 0x6c, 0x42, 0x68, + 0x05, 0x11, 0xa8, 0xa9, 0x3f, 0xd7, 0x83, 0x6d, 0xd6, 0xbe, 0x6a, 0x55, 0xa5, 0xb3, 0x24, 0xd5, 0x38, 0x82, 0x42, + 0x0e, 0x06, 0x45, 0x10, 0xba, 0xb3, 0x7b, 0xf0, 0x13, 0x07, 0xe3, 0x42, 0xe0, 0x86, 0x96, 0xa7, 0xae, 0x5b, 0xc7, + 0x2d, 0x03, 0x53, 0x7d, 0xb9, 0xd2, 0x3c, 0xee, 0xa1, 0x75, 0xb0, 0x6b, 0x3b, 0x92, 0xcf, 0xb5, 0x78, 0x42, 0xdf, + 0x9d, 0xe8, 0x04, 0x86, 0x87, 0x23, 0x4f, 0xbc, 0x3c, 0x90, 0x80, 0x87, 0x00, 0xb3, 0xf2, 0xdd, 0x0f, 0xa1, 0x7a, + 0x7d, 0x11, 0x50, 0x40, 0x7c, 0x55, 0x6e, 0xfb, 0x03, 0x04, 0x2b, 0xea, 0x58, 0x00, 0x27, 0x2a, 0x4e, 0xc9, 0x01, + 0x09, 0xc6, 0x11, 0xea, 0x1b, 0xa0, 0x9b, 0x0f, 0x95, 0xf2, 0x2f, 0x5c, 0x4f, 0xbc, 0x28, 0xcf, 0xfa, 0xf9, 0x96, + 0x7c, 0xba, 0x6a, 0x51, 0x70, 0xaa, 0xb6, 0x49, 0xa6, 0x50, 0xba, 0xc1, 0x61, 0x4a, 0x11, 0xa7, 0x89, 0x44, 0x2d, + 0x04, 0x60, 0x5b, 0x45, 0xb4, 0xf4, 0xeb, 0x75, 0xd8, 0xd1, 0x52, 0xd8, 0xb2, 0xe0, 0x0b, 0xf5, 0x43, 0x8d, 0xb0, + 0xd8, 0xa8, 0xed, 0x5c, 0x6a, 0xfe, 0xf3, 0x35, 0xc9, 0x86, 0xd6, 0x2e, 0x7b, 0x0b, 0x41, 0x4d, 0xe1, 0x02, 0xb5, + 0xe5, 0x45, 0x32, 0xb5, 0x83, 0x98, 0xfd, 0xc8, 0x44, 0x72, 0x62, 0x79, 0x65, 0x6f, 0x2a, 0x5b, 0xd7, 0xa6, 0xdd, + 0x37, 0x25, 0x18, 0x7e, 0xd4, 0x52, 0x7a, 0x36, 0xec, 0xfc, 0x5a, 0x59, 0x7a, 0x0c, 0x6b, 0x67, 0x4a, 0x20, 0x70, + 0xf9, 0x17, 0xa7, 0xed, 0x02, 0x93, 0x5b, 0x3d, 0xa6, 0xf4, 0x52, 0x8f, 0xf9, 0xee, 0x75, 0x48, 0x95, 0x2c, 0x04, + 0xc9, 0x61, 0xa0, 0xbf, 0x16, 0x13, 0xa5, 0x40, 0x0b, 0x89, 0x50, 0x6e, 0x23, 0x09, 0x70, 0xff, 0x5e, 0x95, 0x31, + 0xc0, 0xb6, 0x0e, 0x3f, 0x4b, 0xb3, 0xab, 0xe7, 0x62, 0x40, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x11, 0xc2, 0x49, 0x53, + 0x7b, 0xe7, 0x2a, 0x12, 0xc9, 0x51, 0x8a, 0x58, 0x6c, 0x9c, 0x95, 0x2e, 0x35, 0xc2, 0x5a, 0x18, 0xcb, 0xb1, 0x02, + 0x92, 0x33, 0xb7, 0x59, 0x79, 0x7c, 0xdb, 0x1c, 0x24, 0xc0, 0x3d, 0xe2, 0xe2, 0x1f, 0x9c, 0x04, 0xc8, 0x35, 0x41, + 0x82, 0x84, 0xf6, 0xd9, 0x80, 0x4c, 0x18, 0x90, 0x91, 0x31, 0x89, 0x6e, 0x04, 0x92, 0x7b, 0x4d, 0xa7, 0xfa, 0x18, + 0x60, 0x2a, 0x27, 0xab, 0x09, 0x44, 0x42, 0x1c, 0x6f, 0x6a, 0xc3, 0x4e, 0x60, 0x2c, 0x03, 0xec, 0xb8, 0x74, 0x54, + 0x72, 0x2e, 0x0e, 0x30, 0xac, 0x9a, 0xf9, 0x85, 0x4d, 0x97, 0xc0, 0x10, 0x47, 0xb4, 0x0b, 0x28, 0xc8, 0xa9, 0xeb, + 0x73, 0x0b, 0x46, 0x0e, 0x12, 0xd7, 0xe8, 0x4e, 0x8b, 0x64, 0x14, 0x91, 0x97, 0xc4, 0xb8, 0xf8, 0x75, 0x4c, 0x93, + 0xb8, 0x58, 0x4f, 0x73, 0x9f, 0x8a, 0xde, 0xb9, 0x0d, 0xfe, 0x71, 0xa3, 0x27, 0x5d, 0x27, 0x2c, 0x01, 0x58, 0x8f, + 0x94, 0x64, 0xc0, 0xa5, 0x9a, 0x9e, 0xfc, 0x3a, 0x48, 0x09, 0xbc, 0x72, 0xd0, 0x39, 0xc4, 0xf1, 0x85, 0x12, 0xd1, + 0xe0, 0xdf, 0xe4, 0xc8, 0x23, 0xf0, 0xeb, 0x67, 0xcc, 0x30, 0xcd, 0x12, 0xd8, 0x63, 0xe5, 0x99, 0x88, 0xf9, 0xab, + 0x46, 0xd2, 0x48, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x05, 0xc2, 0x1e, 0x80, 0xa6, 0x00, 0xde, + 0x1b, 0x12, 0xf3, 0xe5, 0xa9, 0xa6, 0x24, 0xe5, 0x29, 0x3a, 0x9b, 0xb3, 0x60, 0xfa, 0x2c, 0x2c, 0xa0, 0x9b, 0x63, + 0xca, 0xc3, 0x4d, 0x2c, 0xf3, 0x32, 0xcc, 0x94, 0xcc, 0xa8, 0x25, 0x98, 0x08, 0x93, 0xe1, 0x75, 0x72, 0x01, 0xcb, + 0x7b, 0x9b, 0x66, 0xc6, 0x2d, 0xa3, 0x57, 0xae, 0x4f, 0xa0, 0x79, 0xdc, 0x93, 0x65, 0x91, 0xa6, 0x0c, 0x57, 0x38, + 0x00, 0xe9, 0xaf, 0x98, 0xc7, 0xc2, 0x29, 0x35, 0x2b, 0xb9, 0x71, 0xc3, 0xc5, 0x42, 0x6a, 0x5c, 0xdd, 0x95, 0x77, + 0x22, 0x04, 0x48, 0x65, 0x4b, 0x27, 0x83, 0x67, 0x40, 0xf1, 0x9e, 0x00, 0x02, 0x11, 0x8d, 0xc2, 0x67, 0x7e, 0x92, + 0xa3, 0x55, 0x4e, 0x10, 0x0b, 0x73, 0x55, 0x3b, 0x2f, 0xde, 0x2a, 0x44, 0x94, 0x0b, 0x8e, 0x36, 0x00, 0x5b, 0xb4, + 0x2f, 0x72, 0x9f, 0x41, 0xc0, 0xb7, 0x8f, 0x33, 0xc3, 0x5c, 0x9a, 0x76, 0x48, 0x95, 0xcf, 0xc6, 0xe1, 0xe7, 0xb2, + 0xc0, 0x33, 0x4e, 0x99, 0xd8, 0xfd, 0x67, 0xab, 0xba, 0x21, 0xea, 0xfc, 0x35, 0x75, 0xc0, 0xa9, 0xb6, 0xd9, 0xd9, + 0x8d, 0x41, 0x97, 0xc5, 0xc9, 0x01, 0x93, 0xb2, 0xb3, 0x75, 0xb0, 0xa2, 0x1c, 0xff, 0x72, 0xf2, 0x03, 0x19, 0x0b, + 0x34, 0x5e, 0x15, 0x44, 0x45, 0x46, 0xa6, 0x03, 0x41, 0xbc, 0x34, 0x7c, 0x2e, 0x06, 0x68, 0x91, 0x79, 0x55, 0x52, + 0xa0, 0xd0, 0xac, 0x46, 0x94, 0x37, 0xd0, 0x20, 0x9b, 0xbb, 0x9a, 0x6a, 0x14, 0x1c, 0x21, 0x8f, 0x5a, 0x6c, 0x4c, + 0x8f, 0xc5, 0x52, 0x4c, 0xcb, 0xb4, 0x39, 0x45, 0x12, 0x81, 0xc5, 0x01, 0x71, 0xfd, 0x59, 0xa9, 0xb1, 0x41, 0x94, + 0x79, 0xde, 0x8c, 0x30, 0xe8, 0x6e, 0xe8, 0x49, 0x36, 0x31, 0xd6, 0x4a, 0x10, 0x39, 0x75, 0xd0, 0xd8, 0x8f, 0x5d, + 0x9f, 0xc8, 0xdb, 0x5d, 0x53, 0x4c, 0x75, 0xb9, 0x3f, 0x51, 0x4c, 0x0c, 0x2d, 0xed, 0xfa, 0x79, 0x06, 0x51, 0x3f, + 0x3d, 0x78, 0x9a, 0x72, 0xb6, 0xf6, 0x18, 0x1e, 0xaa, 0xce, 0x25, 0x79, 0xbf, 0xd4, 0x0d, 0x01, 0xf9, 0xb5, 0xc0, + 0xea, 0x91, 0x93, 0x88, 0x22, 0x10, 0xf6, 0xb3, 0xfe, 0x96, 0x30, 0xfa, 0x9b, 0x81, 0x25, 0xbb, 0x1e, 0x6c, 0x4b, + 0x5d, 0x62, 0x2c, 0x6b, 0x65, 0xcd, 0x29, 0x30, 0x5c, 0xba, 0x54, 0x4e, 0x1e, 0x48, 0x3c, 0x54, 0x0e, 0x16, 0xd3, + 0xe7, 0xe9, 0xc2, 0x01, 0x23, 0x85, 0xec, 0xfd, 0x34, 0xc8, 0x8b, 0xd3, 0x8b, 0x24, 0xb5, 0x18, 0x31, 0x76, 0xa9, + 0xb6, 0xb1, 0xf4, 0x08, 0xab, 0xb6, 0x36, 0xf0, 0xfc, 0xc4, 0x76, 0xbb, 0xdd, 0xb0, 0x53, 0x41, 0x56, 0x52, 0x27, + 0x72, 0x33, 0x8b, 0xce, 0x8f, 0x26, 0x91, 0xca, 0x13, 0x46, 0x01, 0x79, 0x39, 0x63, 0x5b, 0x20, 0x8b, 0x6e, 0x8a, + 0x5e, 0x18, 0xe3, 0xd6, 0xb3, 0x5c, 0x7d, 0xeb, 0x37, 0x38, 0x14, 0x92, 0x32, 0x35, 0xcd, 0x94, 0x7b, 0x9d, 0xcd, + 0x77, 0x55, 0x44, 0x8b, 0x72, 0xd6, 0x5c, 0x9b, 0x5f, 0x24, 0xab, 0xbd, 0x14, 0xd9, 0xd2, 0xe9, 0x30, 0x7b, 0x97, + 0x8a, 0xd4, 0x92, 0x04, 0xaa, 0x1d, 0xc7, 0x66, 0x1c, 0xe7, 0x18, 0xf4, 0x56, 0x30, 0xb3, 0x86, 0x97, 0x80, 0xec, + 0x22, 0x85, 0x45, 0x56, 0x5a, 0xbc, 0xd1, 0x2d, 0x25, 0xef, 0x07, 0x89, 0xca, 0xd2, 0xc3, 0x30, 0x93, 0xbe, 0x14, + 0xf6, 0x80, 0x14, 0x8f, 0x50, 0x45, 0x98, 0xbb, 0xdf, 0x45, 0x50, 0xa0, 0x3a, 0xc3, 0x13, 0x98, 0xf6, 0x7c, 0x94, + 0x8e, 0x0b, 0x98, 0x9f, 0xcd, 0x44, 0xbb, 0x7a, 0xb5, 0x06, 0x2c, 0xbc, 0xfa, 0x90, 0xe2, 0x3a, 0xa5, 0xb7, 0xf2, + 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x18, 0x23, 0x49, 0x9a, 0x0f, 0xe7, 0xde, + 0xa0, 0x9b, 0x21, 0x28, 0x11, 0x53, 0xdc, 0x10, 0x62, 0x31, 0xcc, 0x58, 0x03, 0xca, 0xdd, 0xa2, 0x99, 0x93, 0xac, + 0xb9, 0x93, 0x49, 0xce, 0x7c, 0xf7, 0x95, 0x5e, 0xa5, 0x94, 0x10, 0x4d, 0xc7, 0x57, 0x39, 0x59, 0x3e, 0x46, 0xc3, + 0x2c, 0xae, 0x1c, 0x13, 0xb4, 0x4e, 0xe2, 0x84, 0xa2, 0x70, 0x48, 0x50, 0x5b, 0x61, 0xba, 0x53, 0x23, 0x9c, 0x0a, + 0x7a, 0x3f, 0xe9, 0xe6, 0x0e, 0xba, 0x13, 0xdb, 0x50, 0xd1, 0x9a, 0x86, 0x0a, 0x62, 0xdb, 0xbf, 0xf7, 0x33, 0x3a, + 0x74, 0xfc, 0x56, 0x34, 0xa6, 0x42, 0xa0, 0x66, 0x0e, 0x97, 0xe7, 0xbe, 0x98, 0x14, 0xe2, 0x4a, 0x5a, 0x9e, 0x08, + 0x92, 0xb4, 0x8f, 0x8d, 0x79, 0xb1, 0xb7, 0x83, 0xc2, 0x34, 0xac, 0xcb, 0x06, 0x44, 0xad, 0x17, 0x2a, 0xf3, 0xeb, + 0xb6, 0x8c, 0x3b, 0x4d, 0x18, 0xaf, 0x9b, 0x81, 0x98, 0xd7, 0xa0, 0x8d, 0x18, 0x8c, 0x55, 0x3b, 0x0e, 0x40, 0x39, + 0x3a, 0x2d, 0x1b, 0xeb, 0x4b, 0xab, 0x46, 0x6f, 0x68, 0x0c, 0x6c, 0xd7, 0x62, 0x91, 0x04, 0xa4, 0x30, 0x66, 0xdd, + 0x8d, 0x49, 0xa7, 0x0a, 0xea, 0x81, 0xec, 0x59, 0x9f, 0x75, 0x3c, 0x4b, 0x4c, 0xf8, 0x25, 0x03, 0x47, 0xf3, 0xe9, + 0xa4, 0x97, 0xae, 0x89, 0x8e, 0x68, 0x6d, 0x21, 0xfe, 0xd4, 0xe0, 0xd6, 0xe2, 0xa5, 0x0e, 0x7c, 0x05, 0xa0, 0x16, + 0x99, 0x0a, 0x21, 0x51, 0x25, 0x15, 0x57, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x2a, 0xac, 0x7c, 0x72, 0xef, 0x7a, 0x07, + 0x7f, 0xb6, 0x07, 0x4b, 0xeb, 0x0e, 0xf3, 0xc1, 0xc9, 0x5f, 0x45, 0x48, 0x11, 0xf6, 0xcc, 0xd0, 0xc1, 0xc6, 0x3c, + 0x73, 0xe4, 0xe3, 0xb5, 0x1d, 0xf1, 0xad, 0x0b, 0x6f, 0x98, 0xe4, 0xee, 0x3d, 0x72, 0x19, 0xda, 0x52, 0x40, 0xd4, + 0x6d, 0x6e, 0xfb, 0x83, 0x74, 0xfc, 0x49, 0x4a, 0xf1, 0xef, 0x5d, 0x05, 0x51, 0xbb, 0x68, 0x21, 0x79, 0xa7, 0xe7, + 0xc0, 0x1a, 0x8c, 0x26, 0x8d, 0x11, 0x4c, 0xef, 0x01, 0x97, 0x8a, 0xe2, 0xfc, 0xd1, 0x49, 0x98, 0x70, 0xe2, 0x19, + 0xe0, 0x2f, 0x8d, 0x49, 0xd8, 0x16, 0x01, 0x77, 0xbb, 0x18, 0xff, 0xa2, 0xdd, 0x84, 0x41, 0xde, 0x5d, 0xdf, 0x91, + 0x7e, 0xc4, 0x3d, 0x6c, 0x2e, 0xfb, 0x5b, 0x5e, 0x8a, 0x56, 0xa2, 0x8a, 0x10, 0xa6, 0x46, 0x42, 0x43, 0x9d, 0x23, + 0x81, 0x38, 0xa6, 0x89, 0x35, 0xcc, 0xf6, 0x93, 0xf5, 0x61, 0x97, 0x0a, 0xa1, 0x50, 0x04, 0xa2, 0x33, 0x84, 0x1b, + 0x75, 0x9e, 0x30, 0xc0, 0x3b, 0x04, 0xa0, 0x25, 0xe8, 0xc7, 0x10, 0x9f, 0x5b, 0x27, 0x84, 0xe6, 0x62, 0x9e, 0x3e, + 0x66, 0x0a, 0x4a, 0x52, 0x7d, 0x2d, 0x6f, 0xb3, 0xe6, 0x05, 0x67, 0x2a, 0x2e, 0xa0, 0x68, 0x2b, 0x9e, 0xfa, 0xef, + 0x98, 0x8a, 0x3e, 0x8a, 0x4e, 0x6d, 0xcc, 0x69, 0x9e, 0x30, 0xe7, 0x88, 0x7e, 0xa0, 0xee, 0xc6, 0xf5, 0x6e, 0xc3, + 0x9d, 0xca, 0x12, 0xca, 0x32, 0xf4, 0xba, 0x65, 0xba, 0x94, 0xe4, 0x70, 0x8e, 0xf3, 0xfc, 0x57, 0x0c, 0x71, 0xff, + 0x35, 0xc7, 0xa7, 0xf7, 0x59, 0xda, 0x65, 0x7e, 0xf4, 0xe0, 0xa5, 0x05, 0x66, 0x76, 0xc6, 0x6e, 0x1e, 0xf6, 0x58, + 0x47, 0x02, 0x3b, 0xe2, 0x18, 0xea, 0x1a, 0x67, 0xbc, 0xde, 0x8a, 0x78, 0xa0, 0xb6, 0x1e, 0x6c, 0xbc, 0xa7, 0x34, + 0x4c, 0xb7, 0xa4, 0x8b, 0xac, 0x6b, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0xbb, 0xa7, 0xc7, 0x93, 0x3a, 0x69, 0x53, 0x54, + 0x2c, 0x81, 0xce, 0x8d, 0x43, 0xff, 0xe4, 0x2c, 0xcc, 0x63, 0xe8, 0x98, 0xc9, 0x38, 0x5b, 0x67, 0x8c, 0xe7, 0xf6, + 0x33, 0x89, 0xb4, 0x93, 0x81, 0xdf, 0x29, 0x92, 0x9f, 0x7f, 0x58, 0x80, 0x46, 0x14, 0x82, 0xda, 0xed, 0x07, 0x0a, + 0xc5, 0xb1, 0xef, 0x7f, 0x84, 0xb5, 0x7d, 0x8f, 0xd8, 0x85, 0x5d, 0x2c, 0x01, 0xc4, 0x6e, 0x6c, 0xec, 0xff, 0x75, + 0x77, 0xab, 0x91, 0x0d, 0xab, 0x0f, 0x24, 0xd4, 0x57, 0x7b, 0xe6, 0xd9, 0x35, 0xcf, 0x8d, 0x08, 0xce, 0x44, 0x47, + 0xa0, 0x5e, 0xb5, 0xb9, 0xfe, 0x9b, 0xa4, 0xbb, 0x88, 0x22, 0x08, 0x56, 0xd6, 0x20, 0x6b, 0x36, 0xb2, 0xa0, 0x54, + 0xdc, 0x91, 0x1b, 0x7b, 0xbc, 0xc7, 0xf7, 0x76, 0x12, 0x4d, 0x19, 0x25, 0xd7, 0xaa, 0x29, 0x27, 0x0e, 0x63, 0x77, + 0x6f, 0x3c, 0x6b, 0x35, 0x5e, 0x28, 0xfe, 0xa6, 0x06, 0x61, 0xc5, 0x8d, 0xe3, 0x66, 0x83, 0x70, 0xff, 0x6c, 0x51, + 0xa7, 0x6b, 0x91, 0xf1, 0xbc, 0x5a, 0xaf, 0x7d, 0xb6, 0x1b, 0xa9, 0x26, 0xb5, 0x27, 0x34, 0x37, 0x62, 0x9b, 0x77, + 0xdc, 0x6d, 0xc0, 0xe7, 0xc0, 0xc5, 0xd4, 0x91, 0x78, 0xef, 0x51, 0x2f, 0x59, 0xb3, 0xd7, 0x5b, 0x13, 0x1e, 0x1c, + 0x7a, 0x65, 0xb7, 0x7a, 0x22, 0x3e, 0x9f, 0x56, 0xff, 0x74, 0x7f, 0x27, 0x3f, 0xbb, 0x97, 0xb7, 0x6a, 0xca, 0x51, + 0xfa, 0xd4, 0xc4, 0x26, 0x7b, 0x3d, 0x6b, 0x1c, 0xde, 0x6a, 0xdc, 0xee, 0xa4, 0x1b, 0x4d, 0xfb, 0x2f, 0x97, 0x32, + 0x5b, 0xd0, 0x2c, 0x0f, 0x7e, 0x0e, 0x16, 0xdf, 0xb3, 0xd0, 0x7b, 0x15, 0x31, 0xa7, 0x6c, 0x70, 0x48, 0x55, 0x33, + 0xfd, 0x30, 0xde, 0x89, 0x26, 0x6e, 0x3d, 0xda, 0x25, 0xee, 0xa2, 0x46, 0x9c, 0xe4, 0x01, 0xd6, 0x5c, 0xef, 0x0a, + 0xa6, 0xd4, 0x2e, 0xff, 0x04, 0xd2, 0xe2, 0xa5, 0x09, 0x9b, 0xb4, 0xa9, 0xb5, 0x4d, 0x1b, 0xae, 0x02, 0xcb, 0x3f, + 0x16, 0xdb, 0x7c, 0x57, 0xf5, 0x9b, 0x6e, 0xae, 0xf2, 0xf5, 0xcf, 0xe0, 0xc7, 0x6a, 0xaf, 0xe5, 0xa7, 0xff, 0xe1, + 0xfb, 0xff, 0x6a, 0xdc, 0x09, 0x66, 0xbb, 0x39, 0x0b, 0xbe, 0x6a, 0x70, 0x91, 0x65, 0xc3, 0xe7, 0x49, 0xf9, 0xff, + 0xea, 0x7a, 0xf7, 0x8f, 0xab, 0x7f, 0xbf, 0x68, 0x06, 0xf3, 0x11, 0x57, 0x9e, 0x49, 0x5d, 0x9c, 0xfd, 0x37, 0xc4, + 0xd5, 0xd3, 0x7b, 0x1f, 0xb1, 0xc6, 0x15, 0xfb, 0xcd, 0x6e, 0xb2, 0x6c, 0x16, 0x55, 0x96, 0xf0, 0xd4, 0xab, 0x9a, + 0x5d, 0x41, 0x90, 0xcf, 0x7b, 0x9d, 0xcd, 0x47, 0x87, 0x8f, 0x35, 0xa6, 0x7d, 0xa6, 0xdc, 0xfb, 0xfc, 0xc2, 0xf3, + 0x8b, 0x59, 0x39, 0x9e, 0xf7, 0xbc, 0xf4, 0x6a, 0xae, 0xec, 0xc7, 0x9a, 0xe4, 0x4c, 0x67, 0x70, 0xfe, 0x59, 0x39, + 0xbf, 0xf8, 0x7c, 0x7f, 0x76, 0x5f, 0xbe, 0xcc, 0x50, 0xc3, 0x31, 0xcf, 0xac, 0xf9, 0x88, 0x77, 0xa2, 0x56, 0x67, + 0xf1, 0xad, 0xd9, 0xcd, 0xf1, 0x64, 0xc5, 0x11, 0xae, 0xd0, 0x63, 0x3b, 0xac, 0xfc, 0x5d, 0x4f, 0x0d, 0x71, 0xc1, + 0xd0, 0x04, 0x12, 0x0f, 0xfd, 0xdf, 0xc1, 0xd0, 0x0f, 0xbd, 0x97, 0x9f, 0x4d, 0x1a, 0x0e, 0x80, 0xb0, 0xab, 0x96, + 0xc2, 0x6b, 0xa5, 0x3a, 0x62, 0x1b, 0x75, 0x54, 0xf8, 0x40, 0x45, 0x3b, 0x47, 0xdf, 0x5b, 0xde, 0xeb, 0x77, 0xa1, + 0xf4, 0xe0, 0xfa, 0xe1, 0xf1, 0x6b, 0xb1, 0x2e, 0x03, 0xc8, 0x16, 0xc1, 0xe9, 0x86, 0x77, 0xdb, 0xdb, 0x86, 0xe1, + 0x14, 0xaa, 0x3a, 0x51, 0x59, 0x53, 0xeb, 0xcc, 0xbe, 0x8f, 0x16, 0xdd, 0x00, 0x3c, 0x1f, 0xef, 0x13, 0x42, 0xf6, + 0x2e, 0xd2, 0x73, 0xd2, 0x09, 0x23, 0x10, 0xd8, 0x22, 0x0a, 0x6c, 0x1a, 0xe4, 0x7d, 0x7c, 0x87, 0x6e, 0x48, 0xcb, + 0xcf, 0x68, 0xae, 0x3e, 0x77, 0x31, 0xa5, 0xec, 0xe1, 0x6a, 0x6e, 0xb5, 0x4f, 0x01, 0x24, 0xb1, 0x4d, 0x08, 0x58, + 0xfe, 0x93, 0xc7, 0x4d, 0xc3, 0xd6, 0x9b, 0x74, 0xe9, 0x85, 0xd4, 0x9d, 0x9a, 0x34, 0x65, 0x84, 0x91, 0xe9, 0x85, + 0xe7, 0x15, 0x9d, 0x70, 0x97, 0x63, 0xa2, 0x57, 0x8c, 0x8c, 0x59, 0x71, 0xa7, 0xde, 0xb6, 0xbc, 0xfe, 0x5c, 0x07, + 0x41, 0x48, 0x37, 0x36, 0xa4, 0xcb, 0xcc, 0xdd, 0x2b, 0xb8, 0x99, 0x11, 0xb0, 0x79, 0x09, 0x75, 0xc6, 0xef, 0x99, + 0x24, 0xd1, 0x9d, 0x35, 0x4d, 0x9c, 0xf1, 0xb7, 0xd5, 0x6c, 0xa1, 0x8a, 0xc4, 0x0b, 0x73, 0x03, 0x12, 0x84, 0xfa, + 0x86, 0x5a, 0x61, 0xd5, 0x37, 0x98, 0xb4, 0x1f, 0x38, 0x39, 0xcf, 0x34, 0x83, 0x4e, 0xe3, 0x7d, 0x1d, 0x33, 0x26, + 0xba, 0x9a, 0xa2, 0x50, 0x18, 0x6d, 0xe7, 0xcf, 0xe2, 0x66, 0x96, 0xf5, 0x60, 0x02, 0xf0, 0x36, 0x0f, 0xa0, 0x9f, + 0xd7, 0x0a, 0x66, 0xf2, 0x06, 0x3f, 0xfc, 0x12, 0x06, 0x64, 0x7c, 0xe8, 0x41, 0xce, 0xe6, 0x27, 0x05, 0xfd, 0xc7, + 0x20, 0x5e, 0x77, 0x96, 0xb3, 0x5b, 0x42, 0x6b, 0x29, 0xd6, 0x8a, 0x71, 0x96, 0x91, 0xeb, 0xd4, 0x6f, 0xea, 0x2a, + 0x99, 0xaf, 0xed, 0xea, 0x72, 0xf1, 0x6d, 0x4f, 0xee, 0x30, 0x38, 0x05, 0xbc, 0xa0, 0xa1, 0x20, 0x66, 0x2a, 0x3f, + 0xaf, 0xce, 0x6e, 0x28, 0xf5, 0x41, 0x32, 0x7d, 0xae, 0xf0, 0xaa, 0x1a, 0xff, 0x85, 0x45, 0x5f, 0x6a, 0x25, 0xf4, + 0x17, 0x60, 0xf8, 0xd0, 0xb6, 0xcd, 0x84, 0x67, 0x67, 0x0b, 0xf7, 0x34, 0xf9, 0x54, 0x73, 0xb7, 0xda, 0x88, 0x39, + 0xcf, 0x01, 0x81, 0xb4, 0x50, 0x6a, 0xfc, 0x89, 0xd3, 0x12, 0x24, 0xb9, 0xf1, 0xb3, 0x85, 0x32, 0x3a, 0xba, 0xe2, + 0x14, 0xa7, 0x8b, 0xd7, 0x82, 0x55, 0xd4, 0xfe, 0xb6, 0xa9, 0xe3, 0x8b, 0xef, 0xd2, 0xb1, 0x6d, 0xb9, 0x7f, 0x37, + 0x7d, 0xdb, 0xa0, 0x38, 0x13, 0x36, 0x06, 0x7f, 0xe9, 0xbe, 0x6d, 0x0e, 0x34, 0x7c, 0x88, 0x3e, 0x77, 0xaf, 0xfe, + 0xb8, 0x26, 0x5d, 0x81, 0x6e, 0x89, 0xa7, 0x67, 0x3a, 0x28, 0x9a, 0x87, 0x92, 0x8b, 0x17, 0x25, 0xb0, 0x56, 0x30, + 0x9a, 0xce, 0x78, 0x11, 0x9c, 0x14, 0xda, 0xe7, 0x0d, 0x93, 0x9f, 0x16, 0x5c, 0xfb, 0x51, 0x49, 0xef, 0x14, 0x6a, + 0x8c, 0xef, 0xaf, 0x9b, 0x6c, 0xbd, 0x6b, 0x5e, 0x4b, 0xaa, 0x28, 0x8c, 0x7e, 0x87, 0x01, 0xf2, 0xd5, 0x97, 0x25, + 0x32, 0xfa, 0xf6, 0x4e, 0xdd, 0x6a, 0xbe, 0x77, 0x39, 0xd3, 0x19, 0x81, 0x3f, 0xdf, 0x8c, 0x59, 0xd3, 0x74, 0x33, + 0x46, 0x36, 0x02, 0x73, 0x17, 0x10, 0xa5, 0x89, 0x34, 0x28, 0x2b, 0xc8, 0x77, 0x57, 0xc3, 0x56, 0xa9, 0xcd, 0xde, + 0x9f, 0xfd, 0xdf, 0x4f, 0x0b, 0xee, 0x91, 0xf4, 0xe2, 0x8f, 0x1e, 0xaf, 0x63, 0x21, 0xcd, 0xbd, 0x50, 0xe3, 0x67, + 0xed, 0x71, 0xca, 0x6d, 0x3c, 0x40, 0xb3, 0x86, 0x0e, 0x0d, 0xdb, 0x87, 0x74, 0x5c, 0x1c, 0x5f, 0x63, 0xe8, 0xfb, + 0x06, 0x52, 0xc2, 0xd4, 0xe4, 0x3d, 0xa5, 0x15, 0x75, 0x60, 0x04, 0x15, 0xe5, 0x85, 0x72, 0x62, 0xd6, 0x56, 0xf4, + 0x6e, 0xc3, 0xc4, 0xd9, 0xa0, 0xfe, 0x66, 0xcb, 0xcb, 0x1e, 0x7b, 0x1f, 0xf0, 0xf5, 0x4c, 0x01, 0xc7, 0x38, 0xa1, + 0x46, 0xb0, 0x1d, 0xa4, 0xc8, 0x22, 0xf0, 0x09, 0x33, 0x6a, 0x08, 0x65, 0xcd, 0xd4, 0x96, 0xf2, 0x24, 0x48, 0xaf, + 0x2b, 0x2b, 0x5d, 0xd8, 0xe5, 0xdb, 0x2a, 0xba, 0x39, 0xbd, 0x83, 0x3d, 0xf9, 0x5e, 0xf3, 0xde, 0x7a, 0xa9, 0xd4, + 0x6a, 0xda, 0x90, 0xb0, 0x90, 0xb5, 0xc0, 0xae, 0x5b, 0xe7, 0x47, 0xd7, 0x31, 0x66, 0xf1, 0x08, 0x3e, 0x23, 0xd8, + 0x0b, 0x72, 0x53, 0xe7, 0xd6, 0xce, 0x60, 0x61, 0x42, 0xbe, 0xcf, 0xcf, 0x12, 0xb0, 0xb4, 0x63, 0xd3, 0x74, 0x70, + 0x3e, 0xa4, 0xef, 0xa1, 0x77, 0x4b, 0x01, 0x59, 0x38, 0x35, 0x7b, 0x57, 0x8b, 0x02, 0x4f, 0x1c, 0x92, 0x1a, 0xd0, + 0xf7, 0xec, 0x75, 0xfc, 0x46, 0x9f, 0x58, 0x24, 0x52, 0xd3, 0xdb, 0xf8, 0x9b, 0x67, 0xdf, 0xe8, 0xab, 0x53, 0xcf, + 0x84, 0xaf, 0x3e, 0x94, 0x5a, 0xcd, 0x86, 0x06, 0xec, 0x30, 0xd3, 0xc6, 0xb9, 0x0e, 0x4a, 0x7d, 0x33, 0x61, 0x27, + 0xe4, 0x65, 0x71, 0xe3, 0x28, 0x0d, 0xc1, 0x40, 0x7a, 0x11, 0x8f, 0xa2, 0xfc, 0xbe, 0xea, 0xc9, 0xcc, 0xfa, 0x08, + 0x4f, 0x2f, 0x1f, 0xfe, 0xf1, 0xb5, 0x2a, 0xbe, 0xbc, 0xb7, 0x1b, 0xf9, 0xc9, 0x4e, 0x41, 0xe2, 0xd0, 0x54, 0xec, + 0x01, 0x4d, 0x0e, 0x1c, 0x02, 0x71, 0x43, 0x79, 0xec, 0xc3, 0xfe, 0x5c, 0xf3, 0x0d, 0x01, 0x35, 0x56, 0x12, 0x54, + 0x4b, 0x67, 0xfe, 0x72, 0x25, 0x17, 0x2e, 0xde, 0x5d, 0x3c, 0xb7, 0x28, 0x7b, 0xff, 0xf3, 0x96, 0xfe, 0xd1, 0x7e, + 0x6f, 0x28, 0xb7, 0x97, 0x33, 0xff, 0xef, 0x35, 0x85, 0x0b, 0x81, 0x07, 0x24, 0xa9, 0x85, 0xe4, 0x4a, 0x87, 0x8f, + 0xdf, 0x1c, 0xea, 0xbc, 0xc7, 0x74, 0x5f, 0x61, 0x56, 0x17, 0x44, 0xc1, 0xc7, 0x07, 0xa8, 0x6c, 0x03, 0xc5, 0x08, + 0xe1, 0x02, 0x46, 0x1f, 0xee, 0xeb, 0x46, 0x2d, 0x02, 0x69, 0x57, 0xae, 0xfe, 0x78, 0x61, 0xe0, 0x95, 0xc3, 0x6f, + 0x2d, 0xb9, 0x2f, 0x25, 0xbe, 0xd0, 0xd8, 0x9e, 0x5c, 0x4b, 0xe3, 0x89, 0x8c, 0x8a, 0x50, 0x55, 0x91, 0x7c, 0xce, + 0xbd, 0x5a, 0x7d, 0x31, 0x8c, 0x7c, 0x26, 0x30, 0xd7, 0x9b, 0x36, 0x76, 0x9c, 0x54, 0x97, 0xfc, 0xa7, 0x1e, 0x60, + 0x30, 0xd8, 0x97, 0x6d, 0xd3, 0xf4, 0x7e, 0xe7, 0xa4, 0xe1, 0x09, 0x92, 0xc0, 0x1a, 0x0c, 0x5c, 0x95, 0x24, 0x48, + 0x6f, 0xcc, 0x8a, 0x2e, 0x4d, 0xc9, 0x7b, 0xea, 0x29, 0xd9, 0x88, 0xe4, 0x21, 0xa0, 0x23, 0xc1, 0x45, 0xff, 0x51, + 0x6b, 0x23, 0x5c, 0x6b, 0xf9, 0x39, 0x9f, 0x6c, 0xe8, 0x74, 0xb3, 0x2b, 0xb2, 0xa3, 0x0f, 0xa3, 0x3c, 0x9c, 0x3b, + 0x19, 0xe6, 0x61, 0x24, 0xb0, 0x92, 0xb9, 0x79, 0xdc, 0x00, 0xf1, 0x4d, 0x96, 0x64, 0xb7, 0xe4, 0x7f, 0xfc, 0x29, + 0xaf, 0x23, 0xa4, 0x64, 0x5b, 0xdf, 0x55, 0x34, 0x3a, 0x85, 0x93, 0x5c, 0xa7, 0x65, 0x79, 0x21, 0x9c, 0x50, 0x20, + 0x6c, 0x69, 0xd4, 0x48, 0x7e, 0xff, 0xfe, 0xc7, 0x10, 0x2c, 0xfa, 0xf8, 0xa6, 0x99, 0x75, 0x5b, 0x81, 0x31, 0x82, + 0x46, 0x9d, 0x99, 0xdd, 0xe8, 0xf4, 0x26, 0x23, 0x11, 0x28, 0x49, 0x63, 0x8a, 0xb4, 0x87, 0xc3, 0xdd, 0xe6, 0xab, + 0x3f, 0xb2, 0x1d, 0x4b, 0xaa, 0xb6, 0x59, 0xa8, 0x2d, 0x40, 0x80, 0x51, 0xbf, 0x37, 0x10, 0x4d, 0x34, 0x05, 0x05, + 0x2b, 0x6f, 0xe8, 0xdc, 0x8e, 0x6e, 0xcd, 0x6e, 0x41, 0xfb, 0x55, 0xfd, 0x19, 0xa1, 0x83, 0xdb, 0x4a, 0x7a, 0x4e, + 0x4a, 0x55, 0xa4, 0x2e, 0x38, 0xa7, 0x20, 0xb1, 0xb5, 0x0d, 0xb4, 0x7d, 0x6a, 0x4c, 0xe4, 0xfd, 0x45, 0xc5, 0x55, + 0x44, 0x00, 0x02, 0x84, 0x97, 0xe5, 0x5d, 0xc2, 0x27, 0xa3, 0x04, 0x00, 0xd3, 0xe3, 0xd2, 0x4b, 0xc6, 0x52, 0xd1, + 0xf0, 0xb0, 0x55, 0x50, 0x6d, 0xbb, 0x40, 0xe5, 0x80, 0x0b, 0xac, 0xac, 0xc3, 0x3c, 0x13, 0x52, 0x35, 0x29, 0x2e, + 0xba, 0x99, 0x5d, 0xa4, 0x3c, 0xdd, 0xa7, 0xa9, 0x24, 0x6c, 0x5a, 0x7f, 0x67, 0x7c, 0x19, 0x87, 0x68, 0x96, 0xbe, + 0x38, 0x6e, 0x3c, 0x5a, 0xde, 0x8e, 0xa6, 0x03, 0xd3, 0xda, 0x79, 0x12, 0x01, 0xca, 0x4e, 0x95, 0x70, 0xf5, 0x3c, + 0x04, 0x45, 0xa8, 0xf1, 0x43, 0xb7, 0x41, 0xc1, 0x6f, 0xe4, 0xe7, 0xa7, 0x86, 0x02, 0x84, 0xf1, 0xd2, 0x01, 0x0f, + 0xdd, 0xe4, 0xc5, 0x96, 0xb2, 0x73, 0xc0, 0xd8, 0x1b, 0xd1, 0x0b, 0x48, 0x6b, 0x62, 0xea, 0x4e, 0x72, 0x14, 0x5d, + 0x9c, 0x53, 0x5e, 0xc5, 0x2d, 0xd3, 0x65, 0xe9, 0x63, 0xea, 0x9d, 0x08, 0x9f, 0x13, 0x2b, 0x84, 0xff, 0x1d, 0x91, + 0xc3, 0xac, 0x94, 0x69, 0x81, 0x11, 0x6b, 0x89, 0x17, 0x38, 0xdf, 0x09, 0xd1, 0x4c, 0xd5, 0x4c, 0x57, 0x84, 0x79, + 0xaa, 0xaf, 0xf5, 0x9e, 0x3c, 0xc9, 0x1e, 0xa8, 0xf2, 0x61, 0xaf, 0xbb, 0x24, 0x98, 0xd7, 0xb2, 0xa9, 0xb7, 0x61, + 0xa2, 0xb0, 0x0f, 0x16, 0xf2, 0xb8, 0x6a, 0x08, 0x38, 0x3d, 0xf5, 0xab, 0x6f, 0xf5, 0x61, 0xdd, 0xb4, 0x2b, 0x04, + 0x9f, 0x93, 0x44, 0x84, 0x9f, 0xdb, 0x25, 0xce, 0xca, 0xab, 0xeb, 0xec, 0xb3, 0x58, 0xad, 0x41, 0xe6, 0xe5, 0x29, + 0xd1, 0xb6, 0xff, 0xd9, 0x41, 0x79, 0xde, 0x4d, 0x12, 0x3c, 0x4c, 0x47, 0x14, 0x33, 0x71, 0x8e, 0xa4, 0x21, 0x13, + 0xcf, 0xf9, 0xe2, 0x8b, 0x1a, 0xbd, 0x9f, 0x13, 0x4a, 0xc7, 0xa4, 0xf9, 0x8d, 0x0a, 0xa1, 0x0b, 0x09, 0x1d, 0x3f, + 0x74, 0xf9, 0xba, 0xb0, 0x76, 0xf3, 0x89, 0x88, 0xf5, 0x1f, 0xdc, 0x88, 0xa2, 0xd2, 0x79, 0x2c, 0x96, 0x40, 0x32, + 0xc6, 0x4f, 0xf4, 0x1b, 0x33, 0x4f, 0xba, 0x7a, 0xf8, 0x0c, 0x1b, 0x0d, 0xc7, 0x41, 0x9c, 0x03, 0x9e, 0xbf, 0x0c, + 0x7b, 0x5b, 0x1f, 0x15, 0xbf, 0x7f, 0x7d, 0x40, 0x54, 0x6b, 0xb8, 0xa2, 0xf4, 0x67, 0x1c, 0xe2, 0x12, 0xc9, 0x40, + 0x8b, 0x19, 0x7e, 0x21, 0xd2, 0xea, 0x7f, 0x45, 0xce, 0x3d, 0x0e, 0xec, 0x84, 0xfc, 0x17, 0xb7, 0xbd, 0x07, 0x5d, + 0x15, 0x42, 0xde, 0x8e, 0xa8, 0x91, 0x22, 0x0e, 0xef, 0xee, 0xcd, 0xd7, 0xd6, 0x22, 0xe7, 0xc0, 0xac, 0xdd, 0x4d, + 0x99, 0x85, 0xbb, 0x48, 0x6d, 0x31, 0x6d, 0x9a, 0x6d, 0x82, 0x97, 0x61, 0x27, 0x9d, 0x2c, 0x3e, 0xb5, 0x81, 0x50, + 0x55, 0x04, 0x48, 0x25, 0x0b, 0xfd, 0x0b, 0x94, 0xae, 0x5a, 0x2c, 0x43, 0x4b, 0x25, 0xe7, 0xba, 0x12, 0x4b, 0x3f, + 0xa1, 0xc0, 0x20, 0xfd, 0xe2, 0x56, 0x69, 0x3a, 0x2b, 0xa4, 0x88, 0x44, 0x8f, 0xd7, 0x96, 0xdd, 0x5d, 0xa8, 0x3c, + 0x92, 0xee, 0x33, 0x39, 0xc0, 0xf5, 0x4e, 0xaa, 0x8e, 0x95, 0x04, 0xed, 0x40, 0xf7, 0x00, 0xa5, 0x7e, 0x6a, 0x3d, + 0x44, 0x5a, 0x21, 0xf0, 0x12, 0x6e, 0xcc, 0x90, 0x68, 0x1f, 0xa8, 0x87, 0xc4, 0x04, 0xa0, 0x29, 0x38, 0xc1, 0x96, + 0x42, 0xdb, 0xb9, 0x91, 0x5c, 0xa1, 0x80, 0x95, 0xb1, 0x46, 0x35, 0x66, 0x1e, 0x5a, 0x61, 0x22, 0x8e, 0xb3, 0xcd, + 0xc8, 0x43, 0x1c, 0xa9, 0x43, 0xb4, 0xfd, 0x42, 0xe2, 0xa0, 0xc5, 0x99, 0x33, 0x8d, 0x5c, 0x21, 0x1c, 0x9f, 0x82, + 0x34, 0x8c, 0x60, 0xc3, 0xf5, 0x51, 0x6d, 0xac, 0x32, 0x21, 0x72, 0xab, 0x6e, 0x24, 0xed, 0xd7, 0xf1, 0x3b, 0x97, + 0x58, 0xc9, 0xb2, 0xe2, 0x9b, 0xa6, 0xd4, 0x33, 0xe5, 0xd5, 0x67, 0x56, 0x26, 0xbd, 0xdc, 0x47, 0x79, 0xc4, 0x5b, + 0xb0, 0xb8, 0x29, 0xf9, 0x21, 0xa6, 0xa0, 0x06, 0xf0, 0x68, 0x5c, 0x3b, 0x5c, 0x41, 0xb1, 0x18, 0x18, 0x69, 0x3a, + 0xad, 0x1c, 0xf3, 0xa5, 0x9a, 0x0d, 0x0c, 0xf3, 0x18, 0x4f, 0x2c, 0x74, 0x62, 0x7f, 0xcd, 0xf3, 0xb9, 0x45, 0x23, + 0x4f, 0xd3, 0x06, 0x59, 0x7e, 0x9b, 0xd6, 0x6b, 0x95, 0xe3, 0xf1, 0xb6, 0x02, 0x88, 0xdf, 0x41, 0x59, 0x50, 0x0c, + 0x15, 0x4d, 0x8a, 0x19, 0x0c, 0x97, 0xc6, 0x0b, 0x32, 0x01, 0xba, 0x0c, 0x33, 0x6b, 0x8b, 0xaa, 0xbc, 0x3d, 0x16, + 0xc3, 0x7d, 0x50, 0xaa, 0x48, 0x7e, 0xa5, 0x9a, 0x2d, 0x8f, 0x2a, 0xfc, 0xc7, 0x50, 0x1d, 0x43, 0xa4, 0x9d, 0xfc, + 0xab, 0xa3, 0x46, 0xc7, 0x7d, 0x71, 0xc8, 0x8e, 0x3d, 0x3f, 0x63, 0x20, 0x42, 0x4e, 0xba, 0x15, 0x6e, 0xf1, 0x49, + 0x7a, 0xd4, 0x08, 0xf4, 0x15, 0x04, 0x57, 0x6b, 0xde, 0x9d, 0x51, 0x61, 0xab, 0x51, 0x8e, 0x82, 0x32, 0x0c, 0x51, + 0x0d, 0x4f, 0xd1, 0x38, 0xf0, 0xb2, 0xc0, 0x01, 0x13, 0x01, 0x28, 0xe1, 0xb9, 0x24, 0xba, 0xe8, 0x7f, 0x4b, 0x73, + 0xf4, 0x86, 0x15, 0xec, 0xc8, 0x7c, 0xe9, 0x40, 0x8a, 0x80, 0x90, 0x4a, 0xb9, 0xaa, 0x7f, 0x30, 0x10, 0x8e, 0x87, + 0x91, 0xc1, 0xe4, 0x67, 0xc8, 0x87, 0xf2, 0x66, 0x86, 0x97, 0x47, 0x6e, 0x20, 0x4d, 0x4c, 0xa9, 0xc7, 0xb4, 0x46, + 0x6a, 0xb7, 0xdb, 0xc1, 0x55, 0x2a, 0xdd, 0xa0, 0xc6, 0x17, 0x45, 0x30, 0xfa, 0x97, 0x1b, 0x08, 0x3f, 0xfc, 0x2f, + 0x6e, 0x4b, 0xb0, 0x29, 0x7a, 0x8b, 0x03, 0x90, 0xf6, 0x6d, 0xa9, 0xba, 0x1e, 0x20, 0xc6, 0x96, 0x05, 0xfc, 0xe7, + 0xe0, 0x14, 0x11, 0x4b, 0x67, 0x2c, 0x66, 0xab, 0x53, 0x18, 0x72, 0xff, 0x8b, 0xa1, 0x23, 0x08, 0xfb, 0xd7, 0x19, + 0x76, 0x0c, 0x33, 0x40, 0x26, 0x7b, 0x90, 0x8a, 0x38, 0x52, 0x4c, 0x63, 0x1e, 0xad, 0x05, 0x8e, 0x14, 0x69, 0xf1, + 0x3e, 0x2a, 0x15, 0xdd, 0x97, 0x3c, 0x70, 0x40, 0x55, 0x0e, 0xe1, 0xb7, 0x16, 0x7d, 0x2b, 0x21, 0xf3, 0xba, 0xc9, + 0x02, 0x50, 0x17, 0x63, 0x31, 0xd6, 0x13, 0x92, 0x91, 0x9f, 0xb4, 0xa3, 0xc7, 0x68, 0x68, 0xf2, 0xf1, 0xa9, 0xee, + 0xb8, 0xe9, 0x9e, 0xbf, 0x51, 0x43, 0xb1, 0x7f, 0x2f, 0x13, 0x7d, 0x23, 0x8b, 0x64, 0xef, 0xec, 0xb3, 0xd9, 0x19, + 0xe6, 0xa6, 0xa7, 0xc6, 0x48, 0x37, 0xab, 0x3b, 0x9b, 0x2d, 0x53, 0x3b, 0x72, 0x07, 0x34, 0x67, 0x7c, 0x9d, 0xde, + 0x40, 0x1c, 0xef, 0x85, 0xc4, 0xcd, 0x74, 0xc4, 0x94, 0x7e, 0xdc, 0x88, 0x80, 0x1a, 0x45, 0x07, 0x1b, 0x99, 0xf6, + 0x6f, 0x81, 0x9c, 0x4d, 0xd0, 0x41, 0x15, 0x54, 0x5b, 0xcc, 0x4c, 0x0b, 0x39, 0x34, 0xd2, 0x82, 0x82, 0x95, 0xc6, + 0x60, 0xb0, 0x52, 0x95, 0x64, 0x2f, 0x4a, 0x2c, 0x3d, 0xcb, 0x59, 0xe8, 0x50, 0x36, 0x1d, 0x3c, 0x5f, 0x0a, 0x97, + 0x44, 0xbc, 0xac, 0x85, 0x61, 0xda, 0x6c, 0xa5, 0xa5, 0x65, 0x45, 0x25, 0xec, 0xe4, 0xfa, 0xbc, 0x94, 0x85, 0x79, + 0xa2, 0xb6, 0xf1, 0x8c, 0xdc, 0xcc, 0x50, 0xbe, 0x52, 0xfd, 0x30, 0xbd, 0x5f, 0xf8, 0x77, 0x90, 0x40, 0x9f, 0x22, + 0x60, 0x05, 0x5d, 0x12, 0x6c, 0xa4, 0xf4, 0xcf, 0x17, 0x97, 0x35, 0x0a, 0x7f, 0x7a, 0x01, 0xaf, 0xd2, 0xbd, 0x6e, + 0x87, 0xa1, 0xc8, 0xd7, 0x9e, 0x7c, 0x35, 0x9d, 0xfc, 0x91, 0xc2, 0xe1, 0xba, 0x92, 0x9e, 0x4b, 0x6f, 0x16, 0xf4, + 0x73, 0xeb, 0xd5, 0x57, 0xea, 0x2d, 0x54, 0x4f, 0x93, 0x88, 0xdd, 0x2d, 0xbd, 0x8f, 0x9e, 0x8d, 0x42, 0x68, 0x56, + 0xde, 0x7c, 0xff, 0x90, 0xb4, 0x4c, 0xd4, 0x2a, 0x17, 0x77, 0xb3, 0x81, 0xd0, 0xd6, 0x38, 0x47, 0xd8, 0xbb, 0x71, + 0xee, 0x5f, 0x5a, 0x92, 0x00, 0x55, 0x4c, 0x28, 0xbe, 0xa3, 0xd3, 0x40, 0xee, 0x83, 0x3b, 0x3a, 0x7e, 0xbb, 0xf3, + 0xb5, 0x9a, 0x06, 0xf6, 0x08, 0x53, 0x0f, 0xa2, 0xbf, 0xc1, 0xaa, 0x97, 0x5e, 0x2f, 0x17, 0xd8, 0x9c, 0x97, 0x3c, + 0xb0, 0x54, 0x90, 0x95, 0x57, 0xee, 0xc0, 0xa4, 0xf6, 0x08, 0x02, 0xe8, 0x2f, 0x1b, 0x37, 0xf7, 0x77, 0x22, 0x15, + 0xc1, 0x5d, 0x76, 0x9c, 0x8c, 0xd6, 0xf4, 0x3b, 0x3b, 0x8e, 0x05, 0x63, 0xa7, 0x97, 0x09, 0xab, 0x30, 0xd0, 0x8a, + 0xa3, 0xf5, 0x55, 0xf2, 0x8f, 0x2a, 0xc3, 0xac, 0x15, 0x05, 0xec, 0xfd, 0x52, 0x85, 0xf5, 0x41, 0x29, 0xaa, 0x8b, + 0x78, 0x42, 0xc7, 0x93, 0x66, 0xc3, 0x01, 0x8b, 0xa1, 0x45, 0x8c, 0x2d, 0xf6, 0x48, 0x87, 0xcd, 0x38, 0xa9, 0x77, + 0x7c, 0x56, 0xe1, 0xbc, 0x71, 0x1c, 0xb7, 0xc1, 0x6b, 0x8d, 0xca, 0xf2, 0x05, 0x6e, 0xe0, 0x17, 0xaf, 0x54, 0x8f, + 0x7f, 0xf8, 0xf6, 0xba, 0xb8, 0xa8, 0x3a, 0x0c, 0x6d, 0xf1, 0xa7, 0x0d, 0x69, 0x4c, 0x1a, 0xf6, 0x70, 0xfd, 0x4a, + 0x9a, 0x7c, 0xc1, 0xa8, 0xef, 0x90, 0x8d, 0xd9, 0xba, 0x5f, 0x00, 0x8f, 0x79, 0xef, 0x7a, 0xa9, 0x5f, 0x4a, 0x52, + 0x35, 0xa2, 0x15, 0x35, 0xf1, 0xcd, 0x1a, 0x37, 0xc9, 0x5a, 0x90, 0x84, 0xb6, 0x47, 0xed, 0x88, 0x0f, 0xf1, 0xfb, + 0xb7, 0x29, 0x54, 0x81, 0x78, 0x6f, 0x76, 0x5d, 0x06, 0xbb, 0xd5, 0xb3, 0x94, 0x84, 0x95, 0x1b, 0x30, 0x35, 0xd5, + 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0x4c, 0xd2, 0x9a, 0x74, 0x4e, 0x69, 0x21, 0xd4, 0x32, 0xec, 0x9f, 0x92, 0x45, + 0xc4, 0xc7, 0x32, 0xf8, 0xbc, 0x90, 0x53, 0x77, 0xd0, 0x88, 0x2c, 0x46, 0xad, 0xdc, 0x82, 0xdd, 0x8e, 0xd6, 0x3e, + 0x55, 0x09, 0x88, 0xf5, 0xbb, 0x66, 0xe3, 0x6c, 0x14, 0xd8, 0x43, 0xe8, 0x07, 0xdf, 0xf1, 0x36, 0xcb, 0x5d, 0x60, + 0x4a, 0x79, 0xa4, 0xda, 0x52, 0xfa, 0x8c, 0x17, 0x3f, 0xf2, 0x1e, 0x5a, 0xca, 0xdd, 0x7d, 0xc5, 0x1f, 0x3f, 0x5d, + 0xe7, 0xb5, 0x98, 0x4e, 0xe2, 0x5c, 0x9a, 0x63, 0x49, 0xd9, 0x23, 0xc7, 0x71, 0x71, 0xf7, 0x29, 0x14, 0x9a, 0x51, + 0x11, 0x86, 0x34, 0x12, 0x94, 0x9f, 0x29, 0xae, 0xb8, 0xf6, 0x09, 0xad, 0x25, 0x02, 0x64, 0xf0, 0xfd, 0xa3, 0x4c, + 0x57, 0xee, 0xf3, 0x00, 0x7f, 0xb7, 0x68, 0x95, 0xb0, 0x66, 0x51, 0x84, 0x6d, 0x02, 0x92, 0xf5, 0xdd, 0x61, 0x87, + 0xec, 0xec, 0x86, 0x08, 0x02, 0x75, 0xd7, 0x21, 0x40, 0x18, 0xaf, 0x11, 0xca, 0xe5, 0x5f, 0x2b, 0xe3, 0x76, 0x25, + 0x13, 0xea, 0x30, 0xca, 0x2e, 0x28, 0xf0, 0xde, 0x8b, 0x7e, 0xe9, 0x6d, 0x95, 0x1b, 0x5a, 0x4e, 0xd6, 0x47, 0x2f, + 0x3f, 0x29, 0xbb, 0x24, 0x7f, 0xc8, 0x68, 0x01, 0x48, 0xd9, 0x98, 0x66, 0xe3, 0x98, 0xae, 0x5a, 0xb7, 0xcc, 0x47, + 0xd9, 0x06, 0xc3, 0x76, 0x88, 0x51, 0x3c, 0x68, 0xd5, 0x90, 0x5c, 0xb1, 0x69, 0x8f, 0x7b, 0xe9, 0xc1, 0x6d, 0xf7, + 0x7e, 0x38, 0x38, 0x17, 0xf2, 0x88, 0xd9, 0x4b, 0x98, 0x8f, 0x1a, 0xbb, 0x42, 0xa6, 0x19, 0x0e, 0xe2, 0x20, 0x07, + 0xd9, 0x76, 0xdd, 0x05, 0x53, 0x8e, 0x69, 0x71, 0xbb, 0xc5, 0x46, 0x36, 0x90, 0x11, 0x5a, 0xb0, 0xc9, 0xf8, 0x50, + 0x2c, 0xd3, 0xa1, 0x74, 0xdf, 0x63, 0x02, 0xc6, 0x5a, 0x0f, 0x13, 0xbf, 0x66, 0x1d, 0xa2, 0x4b, 0x16, 0xa4, 0xa9, + 0xd1, 0xe3, 0x9b, 0x3e, 0xa5, 0x5b, 0x66, 0x43, 0xc3, 0xf7, 0x3a, 0xcc, 0x1a, 0x0c, 0x2b, 0xf6, 0x89, 0xb2, 0x57, + 0xf5, 0xc7, 0xdb, 0x71, 0x50, 0x4b, 0x39, 0x73, 0x79, 0x9b, 0xd1, 0xbf, 0x99, 0xc3, 0x40, 0xe3, 0x85, 0xc2, 0x7b, + 0x39, 0x81, 0x9a, 0x96, 0x34, 0x29, 0x78, 0xbb, 0xbc, 0x5a, 0x6d, 0xc2, 0xb8, 0x7f, 0xf7, 0xa1, 0x54, 0x5c, 0xff, + 0xee, 0x7d, 0xdd, 0x55, 0xbd, 0x2f, 0x6f, 0x94, 0x4b, 0x3a, 0xaf, 0xd6, 0x57, 0x10, 0xa0, 0xd2, 0x5b, 0x99, 0xb2, + 0x21, 0xdb, 0x83, 0xd7, 0x75, 0xbd, 0x77, 0x55, 0x7e, 0xdc, 0x81, 0xdd, 0x6d, 0x72, 0x16, 0x6b, 0x0b, 0xea, 0xa9, + 0xd3, 0xb8, 0x7b, 0x29, 0xe5, 0x86, 0x83, 0x53, 0x8a, 0xba, 0xc5, 0x37, 0xbc, 0x3f, 0x67, 0xd7, 0xa9, 0x4b, 0xbd, + 0xd5, 0x6f, 0xd7, 0xbf, 0xf2, 0xd4, 0x58, 0xe5, 0xa0, 0x86, 0xf5, 0xab, 0xf6, 0x35, 0x99, 0x5d, 0x83, 0x99, 0x31, + 0x48, 0xe1, 0x72, 0xae, 0x3e, 0x1b, 0x1c, 0x85, 0x79, 0x4e, 0xa8, 0x60, 0x0b, 0x42, 0xfd, 0xf8, 0x25, 0x31, 0x95, + 0xcc, 0x3f, 0x1c, 0x57, 0x46, 0x3f, 0x08, 0x7d, 0xbb, 0x6a, 0xbd, 0x0c, 0x75, 0x4e, 0x91, 0x8f, 0xb9, 0x9a, 0xe0, + 0x97, 0xd4, 0xc1, 0xd1, 0x2c, 0xfc, 0x53, 0x1d, 0xb6, 0x3b, 0x9c, 0x8f, 0x1e, 0x68, 0x5c, 0xed, 0x1b, 0xf0, 0x46, + 0xb4, 0xb3, 0xb0, 0xe3, 0xdd, 0xa7, 0x69, 0xac, 0xc3, 0xe1, 0xcc, 0xb0, 0xa4, 0x8c, 0x38, 0x0c, 0x98, 0x87, 0x6e, + 0xc9, 0x76, 0xb9, 0x6e, 0x93, 0x83, 0x94, 0xf5, 0x1e, 0x4a, 0x31, 0x8f, 0xe6, 0xb9, 0x69, 0xef, 0x79, 0x2f, 0xba, + 0xc2, 0x70, 0x79, 0x30, 0x32, 0x1f, 0xb3, 0x42, 0xaa, 0xae, 0x53, 0xd7, 0x71, 0xa6, 0x35, 0x46, 0xe4, 0x23, 0xc6, + 0xcd, 0xf7, 0x96, 0xb0, 0x68, 0x57, 0xb7, 0x2b, 0x88, 0x33, 0xac, 0xfc, 0x5f, 0x19, 0x9b, 0xa9, 0xa7, 0x0b, 0xb6, + 0xa7, 0x16, 0xfc, 0x79, 0x93, 0xb2, 0xa2, 0x82, 0x1b, 0x1d, 0x41, 0xa9, 0x7f, 0x7c, 0x5e, 0xd4, 0xaa, 0x66, 0x64, + 0xcd, 0x6f, 0x89, 0x77, 0xc6, 0x78, 0x5d, 0xd7, 0x15, 0xb2, 0xdf, 0xc5, 0xa9, 0xd1, 0x87, 0x26, 0x35, 0x8a, 0x64, + 0xfd, 0xa5, 0x68, 0x0e, 0x0c, 0x61, 0x84, 0xc6, 0x9b, 0xb5, 0xce, 0xc9, 0xe0, 0x24, 0xce, 0xaf, 0x3a, 0xb0, 0xde, + 0xce, 0xb1, 0xbd, 0x82, 0x41, 0x10, 0xf8, 0x57, 0x11, 0xa3, 0x55, 0xfd, 0xbc, 0x33, 0x33, 0x54, 0xf5, 0x72, 0x9a, + 0xac, 0x6c, 0xfe, 0x18, 0x53, 0x0d, 0xca, 0x4b, 0xd9, 0x55, 0xf6, 0x89, 0x8c, 0xfa, 0xb1, 0xa0, 0x1e, 0x5d, 0x9e, + 0x33, 0x94, 0xb7, 0x60, 0xcf, 0x52, 0x6f, 0x06, 0x08, 0x91, 0xb6, 0xab, 0x61, 0xc2, 0x31, 0xcc, 0xe9, 0xc8, 0x8a, + 0x55, 0x99, 0xc0, 0x47, 0x11, 0x5f, 0x34, 0xa7, 0x05, 0xce, 0xac, 0x2e, 0x3b, 0xbc, 0x15, 0xa2, 0xa2, 0xb8, 0xe3, + 0x7e, 0x42, 0x6b, 0x3e, 0x0e, 0x33, 0x31, 0x5e, 0xb3, 0x78, 0xde, 0xfd, 0x05, 0x04, 0x4d, 0x9d, 0xd0, 0x60, 0xe1, + 0xdd, 0x0f, 0x05, 0x44, 0xc9, 0x6b, 0x2b, 0x72, 0x92, 0xe1, 0xb7, 0x02, 0xc9, 0x74, 0x84, 0xd0, 0xc2, 0x25, 0x70, + 0xb3, 0xfd, 0x74, 0xdc, 0x05, 0xc7, 0x48, 0x91, 0x58, 0x38, 0x9e, 0x26, 0x6c, 0x3e, 0xb1, 0x26, 0x96, 0xe3, 0xa4, + 0x43, 0xe9, 0x2a, 0x34, 0xd5, 0x2a, 0x06, 0xad, 0xab, 0xfa, 0xc9, 0xde, 0x29, 0x88, 0xdb, 0x96, 0x20, 0xa2, 0x26, + 0xc7, 0x37, 0x1d, 0xb4, 0x3d, 0xb1, 0xc8, 0x1a, 0x65, 0x14, 0xbe, 0xf3, 0x08, 0x65, 0x8c, 0xc0, 0x7d, 0x95, 0x1a, + 0x63, 0x43, 0x59, 0x66, 0x7f, 0x30, 0x7d, 0x33, 0xc1, 0x44, 0x2f, 0xa1, 0xcc, 0x68, 0x95, 0x9c, 0x20, 0xfa, 0x34, + 0x97, 0x72, 0x3c, 0x22, 0xfa, 0x86, 0x85, 0xbf, 0xc4, 0xe2, 0x2a, 0xe6, 0xdd, 0xe5, 0xed, 0x74, 0x6d, 0x91, 0xcf, + 0xd4, 0x16, 0x63, 0x97, 0xcc, 0xa1, 0xf6, 0xb0, 0x21, 0x3b, 0xf1, 0x86, 0x9d, 0x16, 0xa5, 0x7c, 0x3b, 0x4a, 0x11, + 0xf6, 0x5d, 0xd1, 0xbf, 0x5d, 0x6f, 0x0a, 0x73, 0xed, 0x8a, 0xc9, 0xdf, 0xea, 0xeb, 0x19, 0x5a, 0x4f, 0x7c, 0x35, + 0x74, 0x73, 0x58, 0xf3, 0xc7, 0x02, 0xdf, 0x22, 0x2c, 0xb7, 0xb7, 0xd1, 0xc4, 0xb6, 0xce, 0x4b, 0x4f, 0x60, 0xb0, + 0x10, 0x7e, 0x37, 0x4b, 0xf1, 0x80, 0xd5, 0x83, 0xe8, 0x83, 0x02, 0x13, 0x53, 0xb9, 0x7a, 0xb5, 0x62, 0x8f, 0xd0, + 0x1e, 0xc6, 0x3a, 0x91, 0x5a, 0xf9, 0x36, 0xb8, 0x5a, 0xe1, 0x95, 0xbe, 0xde, 0x14, 0xb1, 0x5e, 0x79, 0x58, 0xdb, + 0xea, 0x97, 0xdc, 0xc2, 0xe5, 0xdf, 0xb6, 0x2a, 0x02, 0x7c, 0xc2, 0x55, 0x88, 0x23, 0xd0, 0x77, 0x69, 0x15, 0x05, + 0xf5, 0x97, 0x1c, 0x72, 0xea, 0xfc, 0x88, 0x70, 0x3e, 0x5f, 0x57, 0xf5, 0x1c, 0x47, 0x78, 0xab, 0xfc, 0x0f, 0x96, + 0x26, 0x6f, 0xe2, 0x7a, 0xb4, 0xe7, 0x25, 0x1d, 0x3e, 0xc1, 0xa5, 0x3b, 0x0a, 0x23, 0xbc, 0x94, 0x31, 0x8d, 0x17, + 0xe7, 0x1a, 0x30, 0x7b, 0x83, 0xe4, 0xf5, 0x38, 0x10, 0x95, 0x1c, 0x87, 0x2d, 0x16, 0xb5, 0x9e, 0x14, 0x1a, 0x91, + 0x37, 0xac, 0xca, 0x50, 0x44, 0x4b, 0x62, 0x07, 0x88, 0xfc, 0x58, 0x14, 0x86, 0x0e, 0xd5, 0x22, 0xb4, 0x6b, 0x7c, + 0xbf, 0xa9, 0x8f, 0xd0, 0x12, 0xab, 0x89, 0xf0, 0x61, 0x41, 0xde, 0x03, 0x0c, 0x73, 0x98, 0x24, 0xad, 0xa3, 0x74, + 0x90, 0xe3, 0x2b, 0x41, 0x32, 0x39, 0x30, 0x93, 0xde, 0x41, 0x6c, 0xe7, 0x7c, 0x31, 0x79, 0xbf, 0x11, 0x3f, 0x85, + 0x34, 0x74, 0x95, 0xbd, 0xc6, 0x22, 0xfb, 0x60, 0x82, 0xb5, 0x2f, 0x0f, 0x97, 0x99, 0xd7, 0xe0, 0x27, 0xfc, 0xff, + 0x34, 0x4b, 0x0a, 0xba, 0x0b, 0xb8, 0x98, 0xbd, 0x0f, 0xc3, 0x04, 0x3e, 0x19, 0x4d, 0x54, 0x96, 0xe8, 0x85, 0x05, + 0x4a, 0xd9, 0xef, 0xb7, 0xd0, 0xe0, 0x10, 0xcc, 0x4b, 0xde, 0xf9, 0xaa, 0x5b, 0x29, 0xaf, 0xef, 0xe4, 0xc8, 0xe4, + 0xf3, 0x29, 0xda, 0x1a, 0xb6, 0x56, 0xc0, 0x4b, 0x08, 0x03, 0x41, 0x34, 0xa4, 0xb8, 0xa4, 0xc3, 0x15, 0xc8, 0x1a, + 0xb9, 0x63, 0xd1, 0x4a, 0x19, 0x4e, 0x1b, 0x37, 0x13, 0xb5, 0xfb, 0xb4, 0x10, 0xc3, 0x79, 0x49, 0x87, 0xb1, 0xa4, + 0x0f, 0x4c, 0xb8, 0xc1, 0xb2, 0xad, 0x0a, 0xec, 0x80, 0xe6, 0x79, 0xd1, 0x68, 0x95, 0x9a, 0x0c, 0xa9, 0xa4, 0x93, + 0xf0, 0x11, 0xaf, 0x1d, 0x29, 0x19, 0xeb, 0x44, 0x4e, 0x13, 0x86, 0xb0, 0xfd, 0xd0, 0x48, 0xd4, 0x41, 0x61, 0x4d, + 0x21, 0x38, 0x2f, 0x34, 0xe0, 0xa6, 0x8d, 0xee, 0x07, 0xa8, 0xba, 0xd0, 0x48, 0xb3, 0xd2, 0x16, 0xb9, 0x6e, 0x2c, + 0x0e, 0xca, 0x8f, 0x78, 0x6d, 0x5e, 0x67, 0x55, 0x61, 0x23, 0x91, 0x7b, 0x28, 0x86, 0xb0, 0x19, 0xd3, 0x1f, 0xae, + 0xdc, 0xe3, 0x12, 0xeb, 0xb8, 0xc7, 0x80, 0x2d, 0xaf, 0x90, 0xc6, 0xec, 0x55, 0x72, 0x60, 0x21, 0x03, 0x34, 0xaf, + 0xc4, 0xf0, 0xbe, 0xf5, 0xcb, 0xa1, 0xf1, 0xad, 0x5a, 0x99, 0x4b, 0xcf, 0x84, 0x89, 0x11, 0x1e, 0x08, 0x83, 0x5f, + 0xab, 0x3f, 0x9d, 0xf6, 0xb2, 0x4e, 0x71, 0xbf, 0xca, 0x21, 0x37, 0x27, 0x2c, 0x1a, 0xe8, 0xa0, 0x4c, 0x4e, 0x17, + 0x39, 0x07, 0xf5, 0xcd, 0xdd, 0x82, 0xbc, 0x40, 0x1c, 0x6b, 0x3c, 0x8e, 0x5c, 0xf7, 0x62, 0xde, 0x66, 0x22, 0xd8, + 0x9b, 0x0a, 0xfe, 0x39, 0xc4, 0x29, 0x21, 0x80, 0x35, 0x48, 0x6c, 0xd6, 0xe5, 0x1e, 0xdb, 0xcb, 0xd8, 0xae, 0x13, + 0x99, 0xa2, 0xb2, 0x82, 0xe4, 0xe7, 0x11, 0x76, 0x81, 0x1a, 0x0f, 0x36, 0x49, 0x0f, 0xb2, 0x32, 0x0d, 0x23, 0x96, + 0x6f, 0x57, 0xc5, 0x29, 0xcc, 0x6b, 0xb5, 0x0e, 0x85, 0x20, 0x99, 0xd9, 0x6d, 0x23, 0x9f, 0x33, 0x4f, 0xc2, 0xa0, + 0x63, 0x47, 0x69, 0x83, 0x0a, 0xe5, 0xd8, 0x56, 0xf3, 0x68, 0x82, 0x5e, 0xf6, 0xd6, 0x39, 0x24, 0x73, 0x5b, 0x4e, + 0x0b, 0x56, 0x04, 0x24, 0x1e, 0xd7, 0xe2, 0xa3, 0xa9, 0xbb, 0xa1, 0xce, 0x11, 0x16, 0x39, 0x30, 0xcb, 0x96, 0x89, + 0xa8, 0xc5, 0xa5, 0x67, 0x6e, 0x1a, 0x6c, 0x2a, 0xcb, 0x4c, 0x7a, 0x11, 0xb2, 0x68, 0xa5, 0x89, 0x2d, 0xcc, 0xc5, + 0x38, 0x33, 0x07, 0x96, 0xf6, 0x11, 0x1a, 0x06, 0xcb, 0x48, 0x48, 0x63, 0x4b, 0x96, 0xb7, 0xc8, 0xa9, 0xc0, 0xd1, + 0xfe, 0x67, 0x96, 0x3b, 0x62, 0x2b, 0xf7, 0xd0, 0x82, 0xef, 0xf7, 0x57, 0x51, 0xc3, 0xd0, 0xf6, 0x57, 0xfe, 0xbd, + 0xe4, 0x22, 0xa8, 0x57, 0x90, 0x0f, 0x49, 0x26, 0x15, 0x38, 0x28, 0x0c, 0xd4, 0xc9, 0xb8, 0x11, 0xad, 0x4d, 0x78, + 0x24, 0x87, 0x48, 0x13, 0x79, 0x6d, 0x29, 0x2a, 0x87, 0x22, 0x6b, 0xaf, 0xd4, 0x2a, 0x21, 0x00, 0xbd, 0xf5, 0x4e, + 0xb7, 0x1a, 0x0d, 0x6f, 0xd4, 0x24, 0xca, 0x41, 0x7c, 0x38, 0x0d, 0x4f, 0xda, 0xe8, 0x8a, 0xf3, 0x72, 0xe2, 0x33, + 0x75, 0x77, 0x40, 0xa0, 0x81, 0xb3, 0x80, 0xc3, 0x0b, 0x83, 0x59, 0x5d, 0x55, 0x56, 0xdb, 0x05, 0x09, 0xb2, 0xa9, + 0x7f, 0x41, 0x7f, 0x58, 0x9b, 0x23, 0xb5, 0x49, 0x30, 0x1a, 0x47, 0x93, 0xf5, 0xbf, 0x8b, 0x09, 0xbc, 0xa2, 0x2e, + 0xd0, 0x1e, 0x9f, 0xb6, 0x73, 0x2a, 0x4a, 0xb6, 0xfd, 0xe7, 0x43, 0x39, 0x81, 0xfd, 0x5e, 0x76, 0x62, 0x76, 0x78, + 0x2a, 0x47, 0x3d, 0xbd, 0x4a, 0xc5, 0xd8, 0x43, 0x0c, 0xf5, 0x76, 0x04, 0x2c, 0xeb, 0x1b, 0x6b, 0x96, 0xcd, 0x76, + 0x24, 0x5b, 0x73, 0xf4, 0x72, 0x96, 0x48, 0xee, 0x1e, 0x34, 0x58, 0xce, 0xc4, 0x96, 0xcf, 0xe8, 0x79, 0xbb, 0xb5, + 0xc7, 0xe4, 0xed, 0x2c, 0x3b, 0x82, 0x2f, 0x5a, 0xdf, 0xd8, 0xd5, 0x5e, 0xf4, 0xc8, 0x75, 0xec, 0xc3, 0x04, 0x92, + 0x60, 0xb1, 0x00, 0x17, 0x71, 0xcf, 0x27, 0x67, 0xd6, 0x62, 0x9f, 0x8a, 0xd8, 0x45, 0x5a, 0xa8, 0x9f, 0xd2, 0x32, + 0x22, 0xe9, 0xf0, 0xf2, 0x63, 0xcf, 0x48, 0x1e, 0xd7, 0x51, 0xaa, 0xd4, 0x6f, 0x3d, 0x8e, 0x32, 0xb2, 0xc8, 0x51, + 0x27, 0x5c, 0xc2, 0x63, 0xdb, 0xc9, 0x4e, 0x77, 0xac, 0x5a, 0xc8, 0x3e, 0x80, 0x00, 0x49, 0xc8, 0x96, 0xb4, 0xdd, + 0x45, 0x6a, 0xe4, 0xef, 0x71, 0x31, 0x2c, 0x46, 0x84, 0xf0, 0xb0, 0x6e, 0xf0, 0x4f, 0xba, 0xcc, 0xd4, 0xdb, 0xa9, + 0x7c, 0xf0, 0x82, 0x38, 0x1a, 0x0f, 0x8f, 0xd4, 0x28, 0xb4, 0xfa, 0x64, 0x1c, 0x35, 0x29, 0x9c, 0xa1, 0x95, 0xd3, + 0xf6, 0x6f, 0xa0, 0xb7, 0x53, 0xd3, 0x45, 0xa0, 0x45, 0xe1, 0x8b, 0x47, 0x28, 0x01, 0xb1, 0x44, 0x58, 0x31, 0xa4, + 0x92, 0x30, 0x95, 0x09, 0xb9, 0x64, 0xcc, 0x65, 0xc6, 0x9d, 0x5a, 0x05, 0x77, 0x59, 0x15, 0xf7, 0x58, 0x3d, 0xee, + 0xb3, 0x06, 0x3c, 0xa8, 0x35, 0xe2, 0x21, 0xab, 0xe1, 0x1c, 0xa2, 0x7a, 0x51, 0xbd, 0xac, 0x5e, 0x55, 0xd7, 0xca, + 0x75, 0xaf, 0x43, 0x26, 0x30, 0xfe, 0x25, 0x49, 0xb4, 0xfa, 0x10, 0x2d, 0x4d, 0x79, 0xbe, 0x73, 0xf7, 0xde, 0xfd, + 0x07, 0x0f, 0xc7, 0x05, 0x2a, 0x71, 0x56, 0xf7, 0x6d, 0x59, 0xd2, 0x00, 0xb6, 0x50, 0x3a, 0x7d, 0x4b, 0x49, 0x83, + 0x89, 0x42, 0xdb, 0xf9, 0x93, 0xa5, 0xbf, 0x3c, 0xfe, 0xa0, 0xea, 0xb9, 0x79, 0x56, 0xac, 0xbc, 0xf5, 0x88, 0xd3, + 0x02, 0x2d, 0x9e, 0x5e, 0xb0, 0x90, 0x4e, 0x07, 0x1d, 0xf3, 0x6a, 0x1e, 0xf3, 0x90, 0x51, 0x8f, 0xad, 0x85, 0xa7, + 0x5a, 0xc9, 0xf2, 0x07, 0x1d, 0xc0, 0xb1, 0x38, 0x9e, 0xc9, 0xbe, 0x79, 0x24, 0x66, 0xa2, 0x69, 0xda, 0x6a, 0x42, + 0xd5, 0x3f, 0xdc, 0xba, 0xa1, 0xea, 0xc0, 0xc6, 0xec, 0xf8, 0xed, 0x27, 0x0a, 0xb0, 0x4c, 0x13, 0x98, 0x70, 0xe3, + 0x38, 0x6b, 0x16, 0x2e, 0x66, 0xcb, 0xe6, 0xf9, 0x88, 0x01, 0xea, 0x99, 0x0a, 0xa0, 0x92, 0x1e, 0xf8, 0x67, 0xc7, + 0xfe, 0x74, 0xee, 0x2e, 0x6c, 0x18, 0xfd, 0xce, 0xec, 0x7e, 0xf5, 0x1b, 0x71, 0x02, 0xa9, 0xc7, 0xa2, 0xb2, 0x52, + 0xcd, 0xc4, 0x8b, 0x6a, 0x6f, 0xc4, 0xd1, 0xcd, 0x4c, 0x73, 0x63, 0x6f, 0x6f, 0x82, 0xd1, 0xee, 0xc8, 0x00, 0x88, + 0x40, 0xfd, 0xe7, 0xf4, 0x94, 0xd5, 0xfa, 0x76, 0xfa, 0x4d, 0xca, 0xa6, 0x48, 0x09, 0x3e, 0x2d, 0xfe, 0xe0, 0x9f, + 0xba, 0x6f, 0x5a, 0x6c, 0x85, 0x36, 0xf2, 0xb9, 0xca, 0x89, 0x23, 0x91, 0x27, 0xbe, 0x63, 0xeb, 0xac, 0xf2, 0xb0, + 0xf1, 0x53, 0x58, 0xde, 0x66, 0x5a, 0x5c, 0x8a, 0x63, 0x6d, 0x9c, 0xc3, 0x22, 0x37, 0xff, 0x4c, 0xb5, 0xa3, 0xf1, + 0x8b, 0x7d, 0xfb, 0x2b, 0x53, 0xe5, 0x61, 0x39, 0xbe, 0xf2, 0xef, 0xf2, 0x73, 0xf4, 0x38, 0x2f, 0x72, 0xb5, 0xfe, + 0x3e, 0x35, 0xcb, 0x96, 0x0f, 0x4f, 0x72, 0x5f, 0x71, 0x99, 0xa7, 0xa6, 0xf9, 0xa5, 0xaf, 0x86, 0x3c, 0x77, 0xad, + 0xe9, 0xdd, 0xcd, 0xcf, 0x58, 0xfe, 0x49, 0x35, 0xab, 0xf6, 0xa0, 0x7f, 0x95, 0x3d, 0x3b, 0x9e, 0x8a, 0x11, 0x99, + 0x1a, 0x2b, 0x73, 0x40, 0x75, 0x7f, 0x7e, 0x16, 0x09, 0x6e, 0xfc, 0xa7, 0xc7, 0x25, 0x3d, 0x83, 0xa4, 0xb7, 0x75, + 0xfe, 0x42, 0xe8, 0xa6, 0x9e, 0xf4, 0xe0, 0x10, 0xd4, 0x2b, 0xfe, 0x37, 0x0f, 0xe1, 0x0b, 0x4c, 0x5d, 0x20, 0x10, + 0x6f, 0x60, 0x2a, 0xf4, 0xf3, 0xcb, 0xe8, 0x34, 0xd1, 0xdd, 0xa4, 0x65, 0xaa, 0xa2, 0xa6, 0x94, 0x13, 0x3b, 0x42, + 0xc1, 0xb7, 0x93, 0x91, 0x5e, 0x32, 0xda, 0x3a, 0x7f, 0x2d, 0x74, 0x4b, 0x91, 0xdd, 0x4d, 0xbc, 0x55, 0xe7, 0x3d, + 0x2b, 0xe7, 0xcf, 0xf5, 0x74, 0x7b, 0x82, 0x5d, 0x7d, 0x06, 0x54, 0xcb, 0x02, 0x9c, 0x97, 0x6f, 0x60, 0xda, 0x2f, + 0x02, 0x94, 0xd1, 0x62, 0x35, 0xf4, 0x1b, 0xf5, 0x96, 0xc9, 0xfa, 0xdb, 0x8f, 0x6b, 0x0d, 0xd8, 0x39, 0xfc, 0x73, + 0x03, 0x86, 0xe7, 0x48, 0xf4, 0x1c, 0x41, 0x97, 0xae, 0x31, 0x97, 0x35, 0xda, 0x90, 0x3d, 0xd5, 0xd8, 0xbc, 0x05, + 0x97, 0x82, 0xf0, 0xb6, 0x61, 0x36, 0xcd, 0x7c, 0xac, 0x62, 0xae, 0xce, 0x65, 0x9e, 0x3e, 0x23, 0x21, 0xdf, 0xb7, + 0xac, 0x8d, 0x05, 0x53, 0x10, 0xcc, 0x6c, 0x98, 0x32, 0x96, 0xaf, 0x8b, 0xa6, 0x14, 0x7e, 0x1f, 0xc5, 0xb0, 0xee, + 0x19, 0x8b, 0xa4, 0x60, 0x5d, 0xf9, 0x2f, 0x39, 0xe6, 0x31, 0x8f, 0xa5, 0x83, 0x9e, 0x1b, 0xe6, 0xd1, 0x0c, 0x7c, + 0xcc, 0xa8, 0x4a, 0x9c, 0xc1, 0x8e, 0x17, 0xcf, 0x88, 0x82, 0x16, 0xcd, 0xf5, 0xc7, 0xb6, 0xd6, 0x87, 0x4c, 0xdd, + 0xad, 0x98, 0xcd, 0xcf, 0xf4, 0x6d, 0xb6, 0xe9, 0x80, 0xc9, 0x12, 0x41, 0x98, 0x43, 0xf3, 0x7b, 0xf5, 0xa1, 0xb2, + 0x93, 0x5b, 0xa3, 0xb5, 0x76, 0x46, 0xe3, 0x7c, 0xa8, 0x48, 0x75, 0x0e, 0x7d, 0x91, 0xa8, 0xcb, 0x88, 0x71, 0x93, + 0x2d, 0xbd, 0xdb, 0x2f, 0x4b, 0xe3, 0xbf, 0x96, 0xad, 0x32, 0xe2, 0xa9, 0xb9, 0x02, 0xba, 0xcb, 0x35, 0x5c, 0x56, + 0xc4, 0x64, 0x8a, 0x79, 0xb8, 0x6d, 0xe5, 0x6c, 0x16, 0x72, 0x69, 0x3e, 0x81, 0x33, 0xa0, 0x0a, 0xd7, 0x98, 0x05, + 0xd1, 0x5c, 0xb0, 0x00, 0xd6, 0x02, 0xa7, 0x97, 0x27, 0x73, 0x79, 0xd6, 0x31, 0x4a, 0x8c, 0x65, 0xed, 0x1f, 0x2f, + 0x2f, 0x0d, 0xfa, 0x49, 0x16, 0xf2, 0xcc, 0x77, 0xdc, 0xa9, 0xda, 0xa7, 0x78, 0x3a, 0xfa, 0xdd, 0x4f, 0xf9, 0x7b, + 0x0e, 0xdd, 0x76, 0x49, 0xb6, 0x6f, 0x9f, 0x3a, 0x14, 0xe0, 0x48, 0x17, 0xf2, 0x6b, 0x5b, 0xec, 0xb9, 0x5b, 0xf6, + 0x21, 0xa6, 0x85, 0xb0, 0x31, 0xf3, 0x68, 0x11, 0x70, 0x59, 0xde, 0xbb, 0x51, 0xeb, 0x79, 0x4b, 0x02, 0x2e, 0xf1, + 0x9e, 0x9f, 0xea, 0x68, 0x29, 0x6d, 0x47, 0xee, 0xb3, 0x83, 0x28, 0x67, 0x57, 0x5d, 0x3f, 0x31, 0x37, 0xfe, 0xdb, + 0x9d, 0x3d, 0x53, 0x6b, 0xb5, 0x20, 0x29, 0x97, 0x7e, 0x9e, 0x1f, 0x9a, 0x99, 0x4a, 0x26, 0xf0, 0xf0, 0x02, 0x12, + 0xbf, 0xf0, 0xd3, 0xbf, 0x1f, 0xa8, 0xb2, 0xae, 0x1c, 0x22, 0x3d, 0x03, 0x92, 0xe7, 0xe3, 0xc7, 0xd7, 0x85, 0xc7, + 0x3b, 0xa2, 0x4b, 0xbd, 0x9e, 0xe7, 0x16, 0x12, 0xe7, 0x49, 0x77, 0x4e, 0x5c, 0xad, 0x5c, 0xa0, 0x67, 0xa6, 0x21, + 0xe1, 0x5c, 0xf5, 0x8f, 0x0f, 0x81, 0x7f, 0x05, 0x0e, 0x24, 0xa9, 0xab, 0x0b, 0x15, 0x02, 0x9d, 0xd0, 0x7e, 0xde, + 0x12, 0x48, 0x78, 0xf7, 0x22, 0xd8, 0x62, 0x90, 0x7b, 0x2d, 0xa8, 0xa8, 0x2a, 0x54, 0x30, 0x6f, 0x44, 0x25, 0x78, + 0xe4, 0x1f, 0x30, 0x68, 0x9e, 0x98, 0x99, 0xe1, 0x3c, 0x82, 0x88, 0x24, 0x39, 0xb1, 0x45, 0x7c, 0x00, 0xa0, 0x8e, + 0x77, 0x82, 0xf1, 0x4a, 0xe2, 0x30, 0x42, 0x09, 0x2e, 0xbf, 0x17, 0xad, 0x47, 0x71, 0x67, 0x87, 0x83, 0x7f, 0x41, + 0x9a, 0xc7, 0xed, 0xde, 0x1f, 0x43, 0x7f, 0xf6, 0x01, 0xcd, 0xd0, 0xee, 0x04, 0xf4, 0x71, 0xb7, 0x26, 0xed, 0x7e, + 0x33, 0x3d, 0x13, 0x6d, 0xb7, 0x49, 0x62, 0x73, 0x20, 0x63, 0xde, 0x9e, 0x88, 0x0d, 0x6d, 0xfc, 0x01, 0x7e, 0x6b, + 0x6c, 0x56, 0x5d, 0x26, 0x9e, 0x59, 0x3d, 0x3c, 0x9e, 0x89, 0x27, 0x56, 0xab, 0x8d, 0xd8, 0xb1, 0xfa, 0x3f, 0xd4, + 0xf7, 0xf8, 0x96, 0x55, 0x78, 0x54, 0xfd, 0x17, 0xda, 0x81, 0x87, 0xb0, 0xb1, 0x36, 0x8f, 0x9e, 0x35, 0x6c, 0xf0, + 0x60, 0x75, 0x09, 0x3a, 0xf8, 0xf1, 0x57, 0x06, 0x8f, 0x88, 0xdd, 0x0f, 0x06, 0x2b, 0xab, 0x29, 0xb0, 0x3c, 0xde, + 0x1f, 0xdd, 0xff, 0x3f, 0x6f, 0x1a, 0x1e, 0xba, 0xd6, 0xd3, 0x1a, 0x2c, 0x2a, 0xa1, 0xc2, 0xfc, 0x7f, 0x56, 0x0f, + 0x62, 0xc6, 0x6a, 0x9d, 0x89, 0x29, 0xab, 0x3a, 0x13, 0x13, 0x56, 0xfb, 0xbc, 0x5e, 0x6f, 0x88, 0x1e, 0x2b, 0x5f, + 0x88, 0x31, 0xab, 0xe5, 0x9d, 0xe8, 0xb3, 0xaa, 0xb6, 0x7f, 0x03, 0x31, 0x60, 0xe5, 0x13, 0x31, 0x8c, 0x0c, 0x56, + 0x30, 0xfa, 0x1b, 0x2f, 0x77, 0x32, 0xb4, 0x5b, 0x3d, 0xb7, 0xc6, 0xff, 0x45, 0x27, 0xea, 0xd3, 0xe5, 0xc4, 0x95, + 0x67, 0x12, 0x70, 0xd1, 0xfe, 0x5b, 0x78, 0xbd, 0x09, 0x8f, 0x79, 0x60, 0xa4, 0x62, 0x69, 0x06, 0xc0, 0x38, 0x3f, + 0xfc, 0x4f, 0x77, 0x84, 0xb9, 0x91, 0x04, 0x46, 0x56, 0x29, 0x6b, 0xa3, 0xff, 0x97, 0xae, 0x20, 0x2a, 0x83, 0x6c, + 0xfb, 0xf0, 0xb6, 0x3a, 0x35, 0x7a, 0x0d, 0x6d, 0x18, 0xbd, 0xbc, 0xce, 0x59, 0x17, 0xd0, 0x51, 0x4b, 0x0a, 0xa1, + 0xeb, 0xba, 0x7b, 0x62, 0x7a, 0x5b, 0xbc, 0x23, 0x98, 0x11, 0xd4, 0x44, 0x04, 0x49, 0xd3, 0xfe, 0x4f, 0xce, 0xb6, + 0xe5, 0x58, 0x7b, 0xca, 0x62, 0xf9, 0xf0, 0x7d, 0x75, 0x75, 0x2a, 0x4c, 0x99, 0x09, 0x2e, 0xf3, 0xb0, 0xad, 0xde, + 0x53, 0x3d, 0x8c, 0xa5, 0xdb, 0xd3, 0xf0, 0x12, 0x31, 0x7c, 0x4b, 0xae, 0x5a, 0x10, 0xef, 0x09, 0xe6, 0xd8, 0x2d, + 0x81, 0x58, 0x29, 0x5c, 0x8d, 0xd7, 0x2d, 0x24, 0x8e, 0x19, 0xa9, 0xf1, 0x57, 0xeb, 0xfd, 0xdb, 0xcd, 0x14, 0xa7, + 0xc0, 0xa1, 0xe8, 0x36, 0xe0, 0x1d, 0x11, 0xe5, 0x94, 0x43, 0x96, 0x3c, 0xe2, 0x60, 0x87, 0x13, 0x07, 0x64, 0x99, + 0x26, 0xda, 0xac, 0x95, 0xd7, 0x04, 0xef, 0xea, 0xd1, 0x29, 0x93, 0x63, 0x6b, 0x03, 0xc7, 0x20, 0xf9, 0x17, 0xbc, + 0xea, 0x15, 0xa0, 0x0f, 0xd6, 0x54, 0x5d, 0xe8, 0xdb, 0x97, 0xf3, 0x3b, 0xd5, 0xa6, 0x5d, 0xe1, 0x95, 0xfd, 0x86, + 0xad, 0xce, 0xea, 0x1b, 0x41, 0x6a, 0xdd, 0x6d, 0xa4, 0x21, 0x40, 0xf7, 0x43, 0xbe, 0xbb, 0xa7, 0x23, 0x9c, 0x6c, + 0xed, 0x1c, 0x61, 0xa1, 0x99, 0x11, 0xfa, 0xdb, 0x08, 0xb8, 0x43, 0x01, 0x55, 0xdc, 0xda, 0x33, 0xa3, 0x48, 0x44, + 0xb4, 0x24, 0x15, 0xf1, 0x1e, 0x5c, 0xcf, 0xc6, 0xb0, 0x6c, 0xa4, 0x9d, 0xbd, 0xbe, 0xc9, 0xb6, 0x28, 0x82, 0xb0, + 0x75, 0xbd, 0x23, 0x0c, 0xe4, 0x2f, 0x03, 0xff, 0xd7, 0xea, 0xbd, 0xb4, 0x5a, 0xba, 0xa9, 0x7b, 0x7c, 0x0b, 0x7e, + 0xa8, 0x4b, 0xf9, 0x99, 0xa4, 0x98, 0x9d, 0x26, 0x3e, 0xf5, 0x49, 0x79, 0x8a, 0x97, 0x5d, 0x06, 0x40, 0xe4, 0x7a, + 0x4e, 0xc1, 0x87, 0xbc, 0xdb, 0x4c, 0xa9, 0x8b, 0xcc, 0x63, 0x82, 0x01, 0x66, 0x97, 0xd2, 0xc5, 0x3a, 0x35, 0x5c, + 0x6c, 0xa4, 0x1c, 0x6e, 0x3a, 0x9c, 0x36, 0xf4, 0xaa, 0x18, 0x17, 0x91, 0x1d, 0xdf, 0x35, 0x8d, 0x6f, 0x72, 0x23, + 0xf4, 0xde, 0xb9, 0xe1, 0xa9, 0xcf, 0x18, 0xf3, 0xb7, 0x82, 0x50, 0x19, 0x63, 0x3b, 0x9c, 0xad, 0x28, 0xd5, 0x4a, + 0x7e, 0x39, 0x6c, 0x73, 0xd8, 0xbf, 0xc9, 0xad, 0x6d, 0x0c, 0x18, 0xf1, 0x05, 0xe3, 0xbb, 0x10, 0xbf, 0x2f, 0x58, + 0x23, 0x7a, 0xc1, 0x25, 0xcb, 0x53, 0xb0, 0xf0, 0x50, 0x02, 0x53, 0xb6, 0x87, 0x26, 0xe0, 0xde, 0xe7, 0x26, 0x7e, + 0x3b, 0xe4, 0xe6, 0xd1, 0x87, 0x78, 0x2d, 0x94, 0x2a, 0x11, 0xf6, 0xad, 0x78, 0xd6, 0xa8, 0xe0, 0x99, 0x9b, 0x95, + 0xcc, 0x00, 0x28, 0x04, 0xba, 0xd5, 0x1c, 0xbe, 0xeb, 0x8f, 0x7b, 0x75, 0x80, 0xce, 0x6a, 0x5f, 0xce, 0x84, 0x8c, + 0x91, 0xe7, 0xf4, 0x20, 0xe8, 0xe9, 0xa3, 0x77, 0xbc, 0xbd, 0xac, 0x2a, 0x43, 0x8e, 0xc5, 0xc8, 0xa1, 0x99, 0x3c, + 0x2a, 0x4b, 0x1a, 0xb2, 0xe0, 0x72, 0x2a, 0xd7, 0xa4, 0x5a, 0xf5, 0x25, 0xe9, 0x7d, 0xcd, 0xd9, 0x0e, 0x68, 0xec, + 0x79, 0xbf, 0x85, 0xe0, 0x18, 0x84, 0x90, 0x30, 0x27, 0x36, 0xf7, 0xfe, 0xce, 0x00, 0xe7, 0xdb, 0x97, 0x50, 0x6f, + 0xbe, 0xf9, 0x81, 0x5b, 0xf4, 0x13, 0x8e, 0xa1, 0xb4, 0x38, 0xd5, 0x84, 0xab, 0xa3, 0x37, 0xb2, 0x36, 0x52, 0xd2, + 0x79, 0x1d, 0xbd, 0x1b, 0x1b, 0xc5, 0x78, 0xc7, 0x40, 0x54, 0x44, 0x79, 0xb8, 0x1f, 0x4b, 0xa2, 0x72, 0x73, 0x82, + 0x6b, 0x8a, 0x48, 0x44, 0xe1, 0x20, 0xdd, 0xc5, 0xd5, 0xf8, 0xc2, 0xa1, 0xc6, 0x34, 0x33, 0x07, 0x06, 0x48, 0xaa, + 0x43, 0x5d, 0x9b, 0xdd, 0x37, 0x02, 0xe1, 0x25, 0x17, 0xb0, 0x5c, 0x81, 0xcb, 0x43, 0xfe, 0x22, 0xf5, 0x5d, 0xcc, + 0x3b, 0x6d, 0x42, 0x24, 0xe7, 0xce, 0x80, 0x18, 0x38, 0xa4, 0x08, 0x25, 0xd3, 0x8d, 0x4b, 0x4e, 0xe2, 0xd6, 0x6c, + 0xce, 0x5c, 0x28, 0x19, 0x33, 0xf7, 0x88, 0xfe, 0x83, 0xf7, 0x36, 0x21, 0x5e, 0x70, 0x90, 0x45, 0x25, 0x3a, 0x1b, + 0x46, 0x3a, 0x91, 0xf0, 0x6b, 0x2c, 0xde, 0x60, 0x47, 0x96, 0x06, 0xd1, 0x4d, 0x91, 0x31, 0x84, 0x4d, 0x3b, 0xac, + 0x0e, 0xcd, 0x46, 0x49, 0x42, 0x0e, 0x08, 0xb5, 0xf3, 0x24, 0x27, 0x1d, 0xe1, 0xdd, 0xbb, 0xdc, 0xa6, 0xea, 0xc5, + 0xaf, 0x32, 0xd1, 0xa8, 0x36, 0x11, 0x2b, 0xbf, 0x9e, 0xc8, 0xca, 0xc2, 0x97, 0x02, 0x9a, 0x02, 0x25, 0x49, 0xfe, + 0xf6, 0xd7, 0xb4, 0xcc, 0xd3, 0x6b, 0x1d, 0x64, 0x30, 0x98, 0x7c, 0x25, 0x72, 0x8d, 0x1a, 0xd9, 0xe0, 0x3b, 0xe9, + 0x5c, 0xc6, 0x2a, 0xf7, 0x65, 0x88, 0x78, 0x9a, 0x9b, 0xfe, 0xa5, 0x0f, 0x2a, 0xd4, 0xea, 0x43, 0x23, 0xbb, 0x93, + 0xb6, 0x3e, 0x49, 0xd1, 0x48, 0x56, 0xec, 0xe2, 0x8b, 0x4b, 0x34, 0x5a, 0x32, 0x15, 0x4f, 0xca, 0x22, 0x63, 0x93, + 0x6b, 0xaf, 0x8d, 0x4d, 0xd4, 0x1d, 0x8c, 0x25, 0xb2, 0x34, 0x7c, 0x3b, 0x3d, 0xda, 0x10, 0xb7, 0xf7, 0x50, 0x57, + 0x37, 0x65, 0x1f, 0xde, 0xcd, 0xa8, 0x42, 0x73, 0xb3, 0x4a, 0x9d, 0x71, 0x70, 0x86, 0x5f, 0xaf, 0x50, 0x68, 0x4e, + 0x9f, 0x1a, 0x92, 0xe3, 0xec, 0x6b, 0x69, 0x00, 0xed, 0xab, 0xc9, 0x28, 0x16, 0x61, 0x21, 0xc4, 0x25, 0x1c, 0x80, + 0x5c, 0x3e, 0x4c, 0x97, 0x58, 0x6b, 0x95, 0x2b, 0xe9, 0x95, 0x48, 0x16, 0x28, 0xf1, 0x51, 0x9d, 0x5a, 0xa9, 0xac, + 0xe6, 0x4c, 0x62, 0x06, 0x0a, 0x98, 0xbc, 0x35, 0xbd, 0x91, 0x9e, 0xe5, 0x96, 0xb9, 0x4c, 0x70, 0xe6, 0x42, 0xb4, + 0xe6, 0x87, 0x6f, 0x72, 0x43, 0x56, 0x54, 0xd3, 0x88, 0x14, 0x3f, 0x38, 0x33, 0x10, 0x13, 0x20, 0x96, 0x31, 0xd7, + 0x27, 0x98, 0x60, 0x83, 0xf5, 0x66, 0x4d, 0xd7, 0xb0, 0xa1, 0xfc, 0x74, 0xff, 0xe4, 0x17, 0x63, 0x9e, 0x23, 0x80, + 0x95, 0x99, 0x78, 0x5e, 0xf2, 0xe9, 0x54, 0x29, 0x74, 0x89, 0x28, 0xce, 0x68, 0xd1, 0xd8, 0x99, 0x86, 0x65, 0x6c, + 0x23, 0x43, 0x00, 0xb4, 0x37, 0xf9, 0xf5, 0x65, 0x16, 0x25, 0xb5, 0x32, 0x21, 0xf2, 0x11, 0xd3, 0x8c, 0x3c, 0x39, + 0xd5, 0x21, 0x6b, 0x0d, 0x1e, 0x46, 0x95, 0x48, 0xfe, 0x78, 0x2a, 0xb9, 0x90, 0x44, 0xef, 0x61, 0x3b, 0x54, 0x59, + 0xb2, 0x60, 0xc5, 0x2a, 0x7a, 0xdf, 0xde, 0xee, 0xfa, 0x6b, 0x64, 0xc2, 0x5e, 0x00, 0xa2, 0xd7, 0x1e, 0x1c, 0xe3, + 0x95, 0xc9, 0x27, 0x57, 0x19, 0x2c, 0x28, 0x25, 0x42, 0x4d, 0x38, 0xda, 0x98, 0xcb, 0x32, 0x53, 0x70, 0xd5, 0x23, + 0xd9, 0xb2, 0x94, 0x39, 0xc9, 0xb0, 0xde, 0x06, 0x92, 0xf1, 0x11, 0xb5, 0xfc, 0xb5, 0x60, 0x6f, 0x1d, 0xd4, 0x29, + 0x04, 0x71, 0x92, 0xff, 0xe6, 0xf1, 0xba, 0xc5, 0xf7, 0xcb, 0x4f, 0x9b, 0x2c, 0x46, 0x92, 0xbd, 0x48, 0x53, 0xe9, + 0xbf, 0xd0, 0x2c, 0x0d, 0x0e, 0x4a, 0x4b, 0x6f, 0xcf, 0x05, 0x57, 0x7a, 0x21, 0x8a, 0x59, 0x00, 0x4f, 0x48, 0xa9, + 0x37, 0xba, 0x92, 0x68, 0x9d, 0x61, 0x75, 0x2c, 0xce, 0x6a, 0x11, 0x7a, 0x95, 0x4e, 0x88, 0xc5, 0x53, 0x23, 0xf2, + 0x9b, 0xac, 0x38, 0x47, 0xf7, 0xc6, 0xe3, 0x6b, 0x76, 0xbe, 0x2c, 0x43, 0x65, 0xea, 0x47, 0x88, 0xbe, 0x14, 0x1c, + 0x21, 0x36, 0x12, 0x75, 0x1b, 0x56, 0x8c, 0x10, 0x4c, 0x78, 0x75, 0x62, 0x96, 0x4b, 0xf4, 0xda, 0xfa, 0xe3, 0x7d, + 0xba, 0x67, 0xd5, 0x30, 0x7a, 0x65, 0x3e, 0xfe, 0x25, 0x91, 0xcd, 0x30, 0xfa, 0x13, 0xf8, 0x81, 0xc5, 0x9d, 0x9b, + 0xe9, 0x41, 0x38, 0x31, 0x4f, 0x4a, 0x2a, 0xb3, 0xf9, 0x83, 0xbd, 0xc3, 0x30, 0xba, 0xa0, 0xfb, 0xc1, 0x9b, 0x4e, + 0xad, 0x76, 0xbf, 0x21, 0xba, 0x8a, 0xa7, 0xdd, 0xfd, 0xaa, 0x3f, 0x98, 0x24, 0x0a, 0xd1, 0x8b, 0x06, 0x00, 0x3c, + 0xcd, 0x80, 0x67, 0x92, 0x62, 0x63, 0xf2, 0x66, 0x96, 0xae, 0x9c, 0x13, 0x5f, 0x50, 0xe7, 0xd9, 0x86, 0xac, 0xc9, + 0xbd, 0x24, 0xc8, 0x29, 0x55, 0x6e, 0x0d, 0xca, 0x18, 0x15, 0x55, 0x62, 0x78, 0x9a, 0x46, 0xb0, 0x01, 0x72, 0x4b, + 0x5b, 0x74, 0x3d, 0x23, 0x35, 0xa7, 0x73, 0x48, 0xd5, 0xca, 0x12, 0xdf, 0xa3, 0x3f, 0xca, 0xd0, 0x78, 0x48, 0xc4, + 0x56, 0x5d, 0xd3, 0xdc, 0xaf, 0xeb, 0x5d, 0x3a, 0x6e, 0xf8, 0x9d, 0x89, 0xc2, 0x6f, 0x5e, 0xe0, 0x3d, 0xb7, 0xd0, + 0xd1, 0x06, 0x37, 0x8e, 0xec, 0xe0, 0xcf, 0x60, 0x02, 0x63, 0x3f, 0x6f, 0x86, 0x83, 0xcb, 0x19, 0x9a, 0xaf, 0xa7, + 0xb9, 0xc7, 0xbd, 0x23, 0x6e, 0xd9, 0x5c, 0xe3, 0x7f, 0x73, 0x0b, 0x05, 0xe5, 0xfb, 0xcc, 0xb0, 0xa4, 0xd9, 0xde, + 0x8a, 0xa4, 0xf2, 0x35, 0x03, 0xd8, 0x85, 0x94, 0x9a, 0x0a, 0xb3, 0x69, 0x36, 0x99, 0x60, 0x00, 0x74, 0x91, 0xdf, + 0x5a, 0x2a, 0x88, 0x70, 0x89, 0xc6, 0x80, 0x1b, 0x40, 0x7d, 0x00, 0x86, 0x32, 0xe7, 0x10, 0x1e, 0x82, 0xaf, 0xb0, + 0x91, 0x18, 0xd9, 0x25, 0x18, 0xe3, 0x71, 0xdb, 0xc7, 0xaf, 0xc5, 0x5e, 0xd3, 0xec, 0x94, 0xef, 0x31, 0x36, 0xb1, + 0x79, 0x16, 0x1e, 0xd2, 0x07, 0x39, 0xf3, 0x9d, 0x19, 0x2b, 0xa2, 0x75, 0x7e, 0x2e, 0xec, 0x2f, 0x2d, 0x91, 0x60, + 0xd2, 0x52, 0xdb, 0x1b, 0x90, 0xf2, 0x89, 0x80, 0xa5, 0x34, 0x2f, 0x42, 0x5b, 0x35, 0xc8, 0x03, 0x25, 0xf4, 0x76, + 0x1a, 0xb5, 0xd7, 0x36, 0xeb, 0x85, 0x62, 0x5d, 0x70, 0xdc, 0x6a, 0x01, 0x43, 0x66, 0x38, 0x62, 0x03, 0xd6, 0x81, + 0x2b, 0x99, 0xa9, 0x66, 0xe2, 0x42, 0x9c, 0xd7, 0x99, 0xd1, 0x8c, 0x9f, 0xf3, 0xd4, 0x6e, 0xab, 0xcd, 0x95, 0x38, + 0x43, 0xff, 0xae, 0x5e, 0xbd, 0x99, 0xc6, 0xe8, 0x6e, 0x4c, 0x20, 0xdb, 0x4a, 0x1f, 0x0d, 0x7f, 0x3c, 0x9c, 0xa5, + 0x18, 0x06, 0xdc, 0x9f, 0x53, 0x15, 0xb4, 0xbf, 0x40, 0x79, 0x96, 0x97, 0x36, 0x76, 0x88, 0xd4, 0x64, 0xa0, 0x54, + 0x79, 0xbe, 0x97, 0x6c, 0x95, 0x48, 0xd0, 0x20, 0xb9, 0x91, 0x27, 0xcf, 0xe1, 0x0b, 0x32, 0xe2, 0x8f, 0xc6, 0xef, + 0x2f, 0x20, 0xc2, 0xce, 0x30, 0x93, 0x07, 0x06, 0x33, 0x77, 0x67, 0x03, 0x4f, 0x92, 0xd6, 0x9f, 0x8e, 0x12, 0xcd, + 0x97, 0x9b, 0xbb, 0x92, 0x4c, 0x71, 0x42, 0xf3, 0x93, 0x0f, 0x33, 0x54, 0x14, 0x97, 0x7f, 0xe0, 0x7a, 0xd6, 0x9e, + 0xa4, 0xc0, 0xf5, 0x7e, 0x08, 0x59, 0x11, 0xa9, 0xa8, 0x05, 0xf5, 0xd0, 0x8c, 0xc6, 0xf2, 0x43, 0x73, 0xfb, 0x45, + 0xaf, 0x08, 0x6c, 0xe2, 0x51, 0x8d, 0x9f, 0xf4, 0x5f, 0x3f, 0x30, 0x20, 0xe6, 0xbf, 0x4b, 0x62, 0x45, 0x55, 0xe3, + 0xdc, 0x65, 0x89, 0xaf, 0x60, 0xd5, 0x9f, 0x87, 0x44, 0x11, 0x64, 0xb7, 0x52, 0x84, 0x10, 0x9a, 0x2a, 0x62, 0xda, + 0x03, 0x38, 0xbd, 0x41, 0xdf, 0x51, 0x84, 0x85, 0x0a, 0x37, 0xa6, 0x9f, 0x90, 0x9a, 0x04, 0xa3, 0xd3, 0xd1, 0x40, + 0xe5, 0x80, 0xa4, 0x6f, 0x77, 0xbe, 0xbd, 0x47, 0x26, 0x59, 0xab, 0x5b, 0x99, 0xa4, 0x00, 0x81, 0x36, 0x7c, 0xc8, + 0xed, 0xed, 0x79, 0x9e, 0xe7, 0x2a, 0xab, 0xd7, 0xf1, 0x67, 0x1b, 0x0e, 0x13, 0xdb, 0xb1, 0x35, 0x3c, 0x78, 0xa2, + 0x85, 0x74, 0xfc, 0x45, 0x53, 0x34, 0xe8, 0x1a, 0xf1, 0x11, 0x05, 0xfa, 0x9c, 0x5d, 0x48, 0x1a, 0x37, 0xef, 0xca, + 0x75, 0xe0, 0x32, 0xb8, 0x29, 0x19, 0x1c, 0xd8, 0x9d, 0x0a, 0x99, 0x39, 0x35, 0x17, 0x54, 0x1e, 0x0f, 0xa4, 0xfe, + 0x90, 0xca, 0x8d, 0x59, 0xaa, 0x10, 0x1b, 0x54, 0xa7, 0x06, 0x7c, 0xd9, 0x13, 0x41, 0xcb, 0x13, 0xc8, 0xde, 0xab, + 0x21, 0xc5, 0x98, 0xe4, 0x72, 0x97, 0x03, 0xb6, 0xa1, 0x03, 0xd5, 0xa0, 0xe9, 0x18, 0x40, 0xb8, 0xbb, 0xf8, 0x96, + 0xf4, 0xbf, 0x7d, 0x9c, 0x7e, 0xaa, 0xee, 0x3c, 0x02, 0x4d, 0xb2, 0x56, 0x74, 0xbf, 0xd4, 0xa2, 0x21, 0x48, 0x78, + 0x1b, 0x1e, 0x22, 0xfe, 0xf4, 0x77, 0xe4, 0xd2, 0xc0, 0x5a, 0xd7, 0xa1, 0xff, 0x8e, 0x6c, 0xa6, 0x50, 0xa6, 0x15, + 0x52, 0xea, 0x54, 0x2d, 0x9c, 0x3b, 0x45, 0x59, 0x1a, 0x54, 0x3f, 0x48, 0x65, 0x85, 0x03, 0x09, 0x89, 0x44, 0x45, + 0x19, 0x26, 0x15, 0xaf, 0x69, 0x7d, 0x9f, 0x62, 0x13, 0x9e, 0xdd, 0xad, 0xfc, 0x90, 0x39, 0x88, 0x97, 0xc2, 0x1f, + 0x0f, 0xc6, 0xd7, 0x48, 0x6b, 0xa8, 0x67, 0x87, 0x87, 0x23, 0xcc, 0x51, 0xc4, 0xfa, 0x14, 0x65, 0xa8, 0x04, 0x72, + 0x29, 0xc5, 0x13, 0x86, 0x97, 0x98, 0xa8, 0xe8, 0x1c, 0x72, 0xd0, 0xe6, 0x7c, 0x80, 0x85, 0x87, 0x5e, 0xf0, 0xaf, + 0xe8, 0x21, 0x77, 0xaf, 0x8c, 0x88, 0xa6, 0x32, 0xa5, 0xdb, 0x3a, 0xe5, 0x1e, 0x3a, 0x5b, 0x04, 0xbd, 0x7d, 0xcf, + 0x3f, 0x7d, 0xa7, 0xef, 0xd4, 0xcf, 0x3e, 0xe5, 0x63, 0x7d, 0xca, 0xbf, 0xee, 0xfe, 0x63, 0xdb, 0x21, 0xff, 0x78, + 0xc9, 0xa6, 0x6d, 0x58, 0xd3, 0x6e, 0x4a, 0x54, 0xba, 0x4f, 0x14, 0x66, 0xe2, 0xa5, 0x18, 0xff, 0xb6, 0x28, 0x6b, + 0x7d, 0xb9, 0xb0, 0x82, 0x74, 0x32, 0x9b, 0xf0, 0xf5, 0xaf, 0x0b, 0x47, 0x08, 0x2d, 0x02, 0x3b, 0x49, 0xe9, 0x7c, + 0x92, 0xb5, 0x05, 0x34, 0x97, 0xa4, 0xb3, 0x84, 0x59, 0xc2, 0xd6, 0xf9, 0x04, 0xf4, 0x40, 0xb3, 0xa9, 0x5e, 0xe0, + 0x3a, 0x72, 0x0c, 0xc5, 0xf1, 0x6a, 0xe7, 0xa3, 0xdf, 0xde, 0x8a, 0x6f, 0x31, 0xd8, 0x85, 0xa5, 0x16, 0xd4, 0x8c, + 0x9a, 0x55, 0x0b, 0x38, 0x83, 0xb3, 0x78, 0x16, 0x14, 0xe8, 0xe7, 0x82, 0x21, 0xb8, 0x80, 0xd6, 0x06, 0xfa, 0x60, + 0xda, 0x78, 0x84, 0x45, 0x59, 0xe4, 0x1d, 0xf5, 0xe2, 0x66, 0x5d, 0xf5, 0xde, 0xdf, 0x56, 0x8c, 0x4a, 0xbc, 0xe5, + 0x7f, 0x05, 0x55, 0x22, 0xe9, 0xae, 0x90, 0xc8, 0xbb, 0x2a, 0x3e, 0x5e, 0x9b, 0xd6, 0x07, 0xb1, 0xac, 0xda, 0xb2, + 0xfe, 0x8e, 0xb0, 0x33, 0xe1, 0x71, 0xe8, 0x9e, 0xaa, 0x50, 0x10, 0xd3, 0x38, 0x77, 0xc9, 0xf7, 0x43, 0xbe, 0xea, + 0x7c, 0x37, 0xfc, 0x5b, 0x54, 0xcb, 0x5c, 0xcf, 0x24, 0x02, 0xa2, 0x9c, 0x74, 0xc1, 0xca, 0x61, 0x78, 0xe2, 0x9e, + 0xe6, 0x75, 0x91, 0x9c, 0x17, 0xd4, 0x33, 0x2c, 0x6e, 0xdf, 0xcb, 0x5f, 0x84, 0x6d, 0x8a, 0xca, 0x5f, 0xd8, 0x8c, + 0x3d, 0x1c, 0x51, 0x4d, 0xb7, 0x4f, 0xa8, 0xa0, 0x55, 0xa5, 0x1c, 0x4f, 0xbb, 0xf0, 0x22, 0x72, 0xb6, 0x37, 0xb0, + 0x53, 0xe6, 0xb6, 0x66, 0xdb, 0x1d, 0xe9, 0xef, 0x62, 0x15, 0x45, 0xec, 0x8a, 0xc3, 0x3e, 0xad, 0xa4, 0xeb, 0x8a, + 0x9a, 0xc3, 0x10, 0x8d, 0xe3, 0x0d, 0x14, 0xe5, 0xdb, 0x00, 0x1b, 0x1d, 0x20, 0xf4, 0xdb, 0x06, 0x4f, 0x80, 0x39, + 0xcc, 0xac, 0x36, 0x2e, 0x5e, 0xcd, 0x96, 0x4a, 0xee, 0xa9, 0xea, 0xfd, 0x5b, 0x0e, 0x8c, 0xbd, 0xcd, 0xfe, 0x29, + 0x46, 0x1f, 0xf1, 0xd9, 0xfb, 0xdb, 0x4f, 0x18, 0x82, 0x3c, 0x73, 0xe5, 0x7d, 0xdd, 0x83, 0x98, 0x94, 0xd9, 0x2a, + 0x35, 0x6d, 0x2b, 0x5c, 0x32, 0x08, 0xaf, 0x1d, 0x6d, 0x58, 0xa2, 0x4e, 0x61, 0x7f, 0xad, 0x92, 0xd5, 0x4d, 0x80, + 0xcf, 0x93, 0x5a, 0x62, 0x4e, 0x95, 0xc7, 0xfe, 0xea, 0xc5, 0x49, 0x26, 0x7f, 0x62, 0x02, 0x75, 0x06, 0x97, 0xb0, + 0x29, 0xcb, 0x1f, 0xc4, 0xfe, 0xdd, 0xec, 0x6f, 0x97, 0x46, 0xfe, 0xe6, 0x28, 0xb1, 0x08, 0x29, 0xac, 0x60, 0x5c, + 0xca, 0xd7, 0x4b, 0x3a, 0x80, 0x46, 0x36, 0x29, 0x46, 0x2f, 0x68, 0x5f, 0x7e, 0xee, 0xbe, 0xc2, 0xdc, 0x53, 0x32, + 0x76, 0x71, 0x30, 0xcb, 0xb5, 0x45, 0xe1, 0x48, 0x83, 0x65, 0xf0, 0xa2, 0xb7, 0x3a, 0xc2, 0x47, 0xe6, 0x88, 0x8f, + 0xcf, 0xfb, 0xe5, 0x82, 0x68, 0x51, 0x9a, 0x3f, 0x0e, 0x9e, 0x06, 0x74, 0x5c, 0x6a, 0xdb, 0xf4, 0x1e, 0x39, 0x75, + 0x40, 0xe8, 0x1a, 0x9b, 0x4c, 0x3f, 0x56, 0x28, 0x25, 0x35, 0x4b, 0xdb, 0xe9, 0xb1, 0xb1, 0x53, 0x53, 0xa2, 0xf8, + 0xae, 0xef, 0xba, 0x3b, 0x45, 0xb5, 0xae, 0x9f, 0x72, 0x44, 0x3e, 0xea, 0x82, 0x78, 0x35, 0x72, 0x6d, 0x87, 0x5c, + 0x7d, 0xd9, 0xa9, 0xea, 0x41, 0x5d, 0xec, 0x7f, 0xc8, 0x95, 0x9c, 0x66, 0xe3, 0x5b, 0x6f, 0xd0, 0xea, 0x26, 0x0d, + 0x3d, 0xe4, 0xc0, 0x02, 0x87, 0x14, 0xe1, 0x46, 0x0c, 0x6d, 0x6b, 0x24, 0x78, 0xac, 0x98, 0xc2, 0x83, 0xb8, 0x3f, + 0x8e, 0x4c, 0x80, 0xaa, 0xe8, 0x45, 0xa8, 0x8d, 0x6d, 0x0e, 0x3d, 0x03, 0x5c, 0x0f, 0xe9, 0xaf, 0x82, 0x9c, 0xef, + 0xe0, 0x6e, 0x30, 0x5a, 0x67, 0xcf, 0x8b, 0xf2, 0x81, 0x6a, 0x5c, 0x6f, 0xdb, 0xe1, 0x90, 0x5d, 0x63, 0xb7, 0x8b, + 0xa4, 0x76, 0x59, 0xe8, 0x33, 0x5b, 0x83, 0x91, 0x62, 0x6c, 0xbd, 0x05, 0xbe, 0xd9, 0x96, 0x41, 0x65, 0xd7, 0x7e, + 0x23, 0x29, 0xa1, 0xd1, 0xc5, 0xd0, 0x60, 0xbc, 0x81, 0x40, 0x55, 0xb0, 0x3c, 0x8b, 0x69, 0x2b, 0x61, 0x34, 0x1a, + 0xf7, 0xb4, 0x9f, 0x46, 0xf5, 0xb1, 0xfc, 0x91, 0x6e, 0xa6, 0xdc, 0x48, 0x97, 0x1f, 0xa6, 0xcb, 0x3d, 0x04, 0x53, + 0x61, 0xf9, 0x52, 0xad, 0x24, 0x02, 0x6e, 0xb9, 0x82, 0xd2, 0x60, 0x7f, 0x3f, 0xaf, 0xc0, 0xcc, 0x4b, 0x9e, 0x63, + 0x68, 0x78, 0xb1, 0x51, 0xb1, 0x71, 0xe2, 0xa7, 0xbb, 0x44, 0xcb, 0xa9, 0x19, 0x3c, 0x45, 0x3c, 0x20, 0xd5, 0x6d, + 0x0b, 0x5e, 0x1e, 0x3c, 0x46, 0x23, 0x4b, 0x57, 0xca, 0x2e, 0x93, 0x67, 0xf5, 0x50, 0x8e, 0x2a, 0x71, 0xd0, 0x4b, + 0xa4, 0x51, 0x57, 0xde, 0xfa, 0xc6, 0x4b, 0x60, 0x95, 0xb4, 0x4c, 0x4e, 0xbf, 0xef, 0x88, 0x34, 0x48, 0xb8, 0x94, + 0x42, 0xf1, 0x57, 0x89, 0x90, 0x7a, 0x6f, 0x0d, 0x1d, 0xc3, 0xc0, 0xfd, 0x75, 0x3e, 0xe2, 0xac, 0xf8, 0xec, 0x17, + 0x07, 0xd0, 0xa5, 0x2a, 0x1b, 0xa4, 0x5d, 0xac, 0xdc, 0x99, 0xef, 0xf7, 0xe8, 0x6d, 0x95, 0x62, 0xf1, 0x2d, 0xa3, + 0x9f, 0x58, 0xbc, 0x15, 0x32, 0xd8, 0x3d, 0x3f, 0xc0, 0x83, 0x1d, 0x9a, 0x48, 0x5d, 0x25, 0x04, 0x30, 0x41, 0x27, + 0xbd, 0x9c, 0xbc, 0x42, 0x14, 0xa1, 0x05, 0xee, 0xc9, 0xa1, 0x8d, 0x4a, 0x61, 0xbe, 0x82, 0xf0, 0x8f, 0x72, 0xf9, + 0x1e, 0x03, 0xd3, 0xe0, 0x12, 0x0d, 0xe5, 0x03, 0x22, 0xd2, 0x93, 0x91, 0x14, 0x81, 0x17, 0xf2, 0x3e, 0x11, 0x4c, + 0x5c, 0xa3, 0x75, 0x13, 0xbc, 0xa7, 0xc5, 0xd1, 0x4d, 0xf3, 0xd4, 0xc2, 0x8c, 0xf8, 0x19, 0x13, 0x46, 0xe1, 0x32, + 0xc4, 0x77, 0x16, 0x14, 0x9e, 0x60, 0xa7, 0x1a, 0x54, 0xaf, 0x8f, 0xda, 0xf4, 0x62, 0x37, 0xf8, 0x2b, 0x37, 0x1f, + 0xcf, 0x45, 0x3a, 0xf2, 0x42, 0x5c, 0xf2, 0xdc, 0xf9, 0x01, 0x9a, 0x10, 0x9e, 0xbb, 0x61, 0x77, 0x89, 0x0e, 0xac, + 0x93, 0xc9, 0x86, 0x15, 0x4d, 0xdc, 0x74, 0x02, 0x0c, 0xf2, 0xdc, 0x39, 0xb4, 0x6a, 0xe2, 0xe9, 0x3f, 0x55, 0xb9, + 0x5d, 0xf2, 0xbc, 0xc3, 0xee, 0x9a, 0xda, 0x35, 0x36, 0x06, 0x22, 0xe2, 0x62, 0x34, 0xc7, 0xd2, 0x4b, 0xfc, 0x1c, + 0xee, 0xdc, 0x7b, 0x5c, 0x3f, 0xc5, 0x18, 0x20, 0x1f, 0xde, 0x42, 0xb6, 0x80, 0x9e, 0xc5, 0x79, 0x9f, 0xa1, 0x17, + 0xde, 0xed, 0x25, 0x66, 0x44, 0x72, 0x7f, 0xa6, 0xf5, 0x91, 0x28, 0x47, 0x7a, 0x09, 0x29, 0x4e, 0x70, 0x94, 0xec, + 0x44, 0xc0, 0xfe, 0xbf, 0x10, 0x6d, 0x27, 0x88, 0xf2, 0x6d, 0xc2, 0xcd, 0xdd, 0xed, 0x58, 0xb9, 0x7d, 0xcb, 0x13, + 0x42, 0xa9, 0xf8, 0x84, 0x71, 0x88, 0x69, 0x27, 0x13, 0xbb, 0x23, 0x43, 0x44, 0x0f, 0x4b, 0x70, 0x1d, 0xb8, 0x19, + 0x7e, 0x74, 0xf6, 0x36, 0x8e, 0xe4, 0xe2, 0x73, 0xf5, 0xf3, 0x67, 0xdb, 0x60, 0x71, 0xed, 0xf6, 0xf2, 0x02, 0xc8, + 0x44, 0x3e, 0xea, 0x48, 0xbc, 0xa2, 0x01, 0x1a, 0xa7, 0xd7, 0x80, 0x11, 0xa7, 0x2c, 0x7d, 0x41, 0x87, 0x89, 0xca, + 0x23, 0xf5, 0xa0, 0x11, 0x3f, 0xc2, 0x90, 0xed, 0xb2, 0xac, 0x89, 0xb4, 0x30, 0xda, 0xb7, 0x40, 0xe1, 0x04, 0x58, + 0xb9, 0x0d, 0x0b, 0xf4, 0x6b, 0x21, 0x23, 0xaf, 0x81, 0x86, 0xfa, 0x7c, 0xf3, 0xda, 0xdf, 0x4f, 0xf4, 0x4f, 0x8b, + 0xe6, 0x90, 0x96, 0xd4, 0x23, 0xbf, 0x0f, 0xb6, 0xc7, 0xd6, 0xe2, 0xe7, 0x9d, 0xaf, 0x32, 0xa6, 0x25, 0x18, 0x91, + 0x77, 0x63, 0x08, 0xf9, 0x20, 0xc7, 0x2a, 0x08, 0x25, 0x5f, 0xab, 0x5a, 0x3b, 0xc4, 0x7a, 0xca, 0xdb, 0x14, 0x79, + 0xdb, 0x7c, 0x54, 0x51, 0x58, 0xad, 0xc0, 0xfe, 0xaa, 0xa1, 0xac, 0xc4, 0x0b, 0xfd, 0x57, 0x42, 0xa2, 0x0a, 0x89, + 0x45, 0x07, 0x3d, 0x12, 0xce, 0x3f, 0x08, 0x51, 0xd0, 0xe5, 0x96, 0x6a, 0xd9, 0x6e, 0x5f, 0x1a, 0x0a, 0x57, 0x81, + 0x58, 0x60, 0xb7, 0xf1, 0xbc, 0xad, 0xe3, 0x45, 0x1c, 0x97, 0x99, 0xb5, 0x6f, 0xbc, 0xe2, 0x2b, 0xec, 0x05, 0x81, + 0xfd, 0x1a, 0xce, 0x9a, 0xfc, 0xdf, 0xcf, 0xf0, 0x9a, 0x99, 0xc5, 0xcd, 0xc5, 0xf0, 0x6f, 0x67, 0xb3, 0xfc, 0x62, + 0x78, 0xb3, 0xd9, 0x21, 0xb5, 0x98, 0xd3, 0x68, 0xda, 0x7c, 0x78, 0xfd, 0xf0, 0xf2, 0x20, 0x9d, 0xde, 0xf3, 0x93, + 0xbc, 0x75, 0x76, 0x71, 0x0c, 0x59, 0xf0, 0x09, 0x3f, 0x6b, 0xb0, 0x39, 0xfb, 0xaf, 0xad, 0xd0, 0x1e, 0xd7, 0xde, + 0x33, 0xbb, 0x12, 0xab, 0xd3, 0xd8, 0xeb, 0xed, 0xbe, 0x9a, 0x02, 0xfe, 0x13, 0x81, 0x26, 0xbe, 0xf2, 0xc9, 0xa4, + 0x14, 0x07, 0x40, 0xa0, 0xba, 0x35, 0xf8, 0x7b, 0x18, 0x8c, 0x32, 0x92, 0xf1, 0xf6, 0x13, 0x92, 0xc8, 0xc6, 0xe1, + 0xe9, 0xdc, 0x42, 0xb1, 0x1e, 0xe9, 0xfb, 0x3c, 0xcd, 0xb4, 0x7e, 0x5b, 0x46, 0xd5, 0xa9, 0x81, 0x2c, 0x68, 0x9c, + 0x69, 0x10, 0xac, 0x7f, 0xdb, 0x58, 0x9d, 0x59, 0xf8, 0x66, 0x21, 0xa2, 0x59, 0x16, 0xff, 0x78, 0x4e, 0xb6, 0xd0, + 0xa0, 0xc0, 0x8f, 0x9a, 0x66, 0xde, 0xb5, 0x6e, 0x75, 0x01, 0x21, 0xef, 0x96, 0xa7, 0xf5, 0xa5, 0x3f, 0xff, 0x82, + 0x35, 0xbb, 0xf1, 0x5f, 0x5d, 0x8f, 0xd6, 0x8b, 0x10, 0x25, 0x5b, 0x81, 0x00, 0x71, 0xb1, 0x8d, 0xe3, 0x2d, 0x79, + 0xe3, 0x34, 0x17, 0xc9, 0x3c, 0x7c, 0x75, 0x92, 0x66, 0x05, 0xa1, 0x9a, 0xdf, 0x26, 0xf1, 0x0a, 0xd4, 0x59, 0x89, + 0x8f, 0x8a, 0x77, 0xe3, 0xde, 0xf5, 0xc4, 0xf6, 0xbf, 0xf2, 0x25, 0x14, 0xc4, 0xf7, 0xfb, 0x16, 0xe8, 0x86, 0x9f, + 0x30, 0xc5, 0xdb, 0x8f, 0xd7, 0xe3, 0x37, 0xf9, 0xad, 0xc0, 0x3d, 0x16, 0x78, 0x67, 0xbd, 0x34, 0x97, 0xf2, 0x24, + 0x41, 0x66, 0x05, 0xae, 0xb8, 0xec, 0x07, 0x0f, 0x96, 0x2d, 0x4d, 0x80, 0x66, 0xab, 0xc8, 0x00, 0x19, 0xca, 0x25, + 0x08, 0x69, 0x83, 0x8c, 0xfe, 0x2d, 0x88, 0xa2, 0x24, 0xc7, 0xa7, 0xb3, 0x27, 0xd1, 0x0d, 0x95, 0x3e, 0x39, 0x32, + 0xb0, 0xb2, 0x0e, 0x50, 0x4b, 0x32, 0x54, 0x88, 0x84, 0x90, 0x64, 0x02, 0x60, 0x9f, 0x14, 0x1a, 0x0a, 0x9f, 0x6b, + 0x39, 0xed, 0xfc, 0xc2, 0xb7, 0x4c, 0x90, 0x78, 0x4c, 0x8e, 0x5a, 0xc9, 0x84, 0xb6, 0x7b, 0xad, 0xf9, 0xe8, 0xee, + 0xe2, 0xa9, 0x5d, 0x1c, 0x63, 0x3e, 0xf2, 0x3f, 0x4a, 0x73, 0x22, 0xf2, 0xb5, 0x0e, 0xc0, 0x4a, 0xde, 0x0a, 0x94, + 0x2d, 0x6f, 0x98, 0x17, 0x58, 0xfc, 0x56, 0x4b, 0x76, 0xf5, 0x0c, 0x02, 0xb4, 0x21, 0x9c, 0xb4, 0xe3, 0x5c, 0xe1, + 0xba, 0x99, 0x62, 0x0d, 0xe5, 0xf5, 0x0a, 0x47, 0x15, 0x9a, 0x26, 0xc6, 0x74, 0x73, 0x2d, 0x7a, 0x31, 0xf5, 0x9a, + 0x7a, 0x42, 0x92, 0xbc, 0x08, 0x67, 0xd5, 0x9e, 0xae, 0xfd, 0x67, 0x06, 0x48, 0x3d, 0x27, 0x17, 0xca, 0x36, 0x17, + 0xe3, 0xbb, 0x79, 0xe3, 0x59, 0xc6, 0xcd, 0xbd, 0x57, 0x6b, 0xaf, 0x9e, 0x67, 0xb7, 0x98, 0x8f, 0x25, 0xe4, 0xd3, + 0x0e, 0x31, 0x37, 0xb2, 0x50, 0x72, 0x84, 0x71, 0xd7, 0x86, 0x21, 0x13, 0x37, 0x2e, 0x2c, 0x98, 0x90, 0x1e, 0x1b, + 0x89, 0x71, 0x90, 0x35, 0xdf, 0xd5, 0x7e, 0x71, 0x7c, 0xfb, 0xa3, 0xb8, 0x48, 0x0b, 0xf6, 0xf0, 0xa4, 0xb3, 0x5f, + 0xf9, 0x4c, 0xa3, 0x6e, 0x23, 0x47, 0x02, 0x51, 0x0c, 0x44, 0x02, 0xba, 0x56, 0xa9, 0xd0, 0xcb, 0x8a, 0x79, 0xa8, + 0xc0, 0x67, 0x2d, 0xb4, 0x51, 0xc1, 0xaa, 0x57, 0xf8, 0x89, 0x08, 0x65, 0xa6, 0xd6, 0x6b, 0x80, 0x5c, 0x64, 0x6b, + 0xad, 0x9f, 0xf5, 0x76, 0x6d, 0xb8, 0x9c, 0x27, 0xf0, 0x57, 0xef, 0xe2, 0xd6, 0xc7, 0x04, 0x5d, 0x6e, 0xed, 0x9f, + 0x68, 0xcf, 0x32, 0x46, 0x12, 0x55, 0x9e, 0xc3, 0xd3, 0x0a, 0xe4, 0xeb, 0x8e, 0x34, 0x5e, 0x62, 0x43, 0xf6, 0x16, + 0xa5, 0x9f, 0x52, 0xc6, 0xbd, 0xfc, 0xa4, 0xd8, 0x03, 0xf6, 0xdc, 0x03, 0x82, 0x35, 0xfb, 0x5a, 0x5f, 0x6e, 0x4d, + 0xd3, 0x60, 0xff, 0xa3, 0x03, 0x4f, 0x40, 0xd9, 0xbe, 0x1c, 0x47, 0x18, 0x8f, 0xdc, 0x92, 0x31, 0x65, 0x08, 0x39, + 0xc1, 0x62, 0xbb, 0xd7, 0x1d, 0x6b, 0x68, 0x39, 0x95, 0x28, 0x16, 0x49, 0xee, 0x7e, 0x94, 0xce, 0x68, 0xff, 0xd4, + 0x4e, 0x25, 0xb4, 0xf5, 0xb7, 0x9a, 0x9d, 0x14, 0x4d, 0xd7, 0xf5, 0x0e, 0xe8, 0x3c, 0x4a, 0x94, 0x4f, 0x2c, 0x8f, + 0x5d, 0x7e, 0x79, 0xb7, 0x6b, 0x64, 0xbb, 0x29, 0xb7, 0xb5, 0x37, 0x1a, 0xa9, 0x18, 0x69, 0xe8, 0x81, 0xed, 0x70, + 0xd9, 0x29, 0x6d, 0x02, 0x22, 0x64, 0x54, 0x2f, 0x8e, 0xa4, 0x96, 0xfa, 0x42, 0x9c, 0x75, 0xe7, 0x23, 0xad, 0x68, + 0x2f, 0x82, 0x02, 0x10, 0x5a, 0x1d, 0xa9, 0x92, 0x35, 0x5c, 0x97, 0x11, 0x6c, 0x0f, 0xe3, 0xf5, 0x0d, 0x14, 0x55, + 0x79, 0x7a, 0x2d, 0xd8, 0x8a, 0x1f, 0xc7, 0xa6, 0xf0, 0xb0, 0x8b, 0x0c, 0xf6, 0xe0, 0x66, 0x8e, 0x13, 0x3c, 0x5d, + 0x9b, 0xd3, 0x92, 0x3d, 0xd9, 0x20, 0xb3, 0xe6, 0xeb, 0xdb, 0x21, 0x5e, 0xb8, 0x71, 0x3d, 0x2c, 0xd9, 0x25, 0x1c, + 0x5c, 0xfa, 0x04, 0x3e, 0xf8, 0xb5, 0x1d, 0xb3, 0x41, 0xa1, 0xab, 0xcb, 0x09, 0xf6, 0x92, 0xc6, 0xe7, 0xf9, 0x6f, + 0x66, 0x73, 0x51, 0xb2, 0x02, 0xac, 0xbd, 0xba, 0x6f, 0x11, 0x2e, 0x73, 0x07, 0x5f, 0xfe, 0x3f, 0x75, 0xd4, 0x76, + 0xf3, 0xf9, 0x2d, 0x9c, 0x9b, 0x1c, 0x3c, 0xc3, 0x21, 0xea, 0xf2, 0x40, 0xae, 0x5c, 0xbf, 0xfa, 0x4f, 0xa0, 0xe4, + 0x9d, 0x4e, 0x9a, 0x7f, 0xdd, 0x77, 0x61, 0x31, 0x36, 0x76, 0xd9, 0x3e, 0xe2, 0x84, 0xd1, 0x75, 0xa2, 0xd0, 0x7e, + 0xcf, 0xc4, 0xb6, 0x1a, 0x64, 0x04, 0x8b, 0x90, 0xd7, 0x77, 0xb6, 0x00, 0xf4, 0xfd, 0x65, 0x0f, 0x8b, 0xb7, 0x7e, + 0x45, 0xe2, 0x4d, 0xb1, 0xf0, 0xef, 0x47, 0x64, 0xe1, 0xda, 0xfe, 0x8a, 0x03, 0x04, 0xdb, 0x5a, 0xfb, 0x5a, 0xdc, + 0x72, 0xfb, 0xe8, 0x04, 0x20, 0x28, 0x61, 0x2d, 0x9e, 0x44, 0xed, 0x5f, 0x22, 0x23, 0x52, 0xf7, 0x19, 0x33, 0x35, + 0x4c, 0xc4, 0x9d, 0x15, 0xc7, 0xb0, 0xd2, 0x7d, 0x74, 0xe5, 0x36, 0xb9, 0x1a, 0x44, 0xd1, 0x1e, 0x9a, 0x88, 0x3b, + 0x36, 0x04, 0x79, 0x4f, 0xc8, 0x63, 0x81, 0xaa, 0xac, 0xc2, 0x96, 0x47, 0x29, 0x82, 0xe1, 0x39, 0x74, 0x01, 0xb6, + 0x52, 0xd4, 0x3a, 0x73, 0xc9, 0xe2, 0xc4, 0x81, 0xd7, 0x8f, 0x07, 0xbc, 0x1a, 0xdd, 0xcd, 0x91, 0x40, 0xdc, 0x49, + 0xb2, 0x5b, 0x50, 0xf5, 0xe6, 0x65, 0xe8, 0x56, 0x3c, 0xaf, 0x14, 0x77, 0xa3, 0xad, 0xbe, 0x0d, 0x21, 0x22, 0x0e, + 0xd1, 0xae, 0x1d, 0xa5, 0x07, 0x74, 0x20, 0x8b, 0x2e, 0xaa, 0x9a, 0x94, 0xe0, 0xbf, 0x29, 0xb3, 0x36, 0xa1, 0x86, + 0x09, 0x05, 0x05, 0xe7, 0x6c, 0xdc, 0x4a, 0xf8, 0xf4, 0x46, 0xc6, 0xdc, 0x52, 0xe0, 0x55, 0x68, 0x6e, 0xaa, 0x03, + 0xb9, 0x22, 0x1a, 0x74, 0xc9, 0xb5, 0xed, 0x32, 0xc7, 0x87, 0x59, 0xbb, 0xf0, 0xfc, 0xb9, 0xd8, 0x2f, 0x95, 0x52, + 0xe4, 0xa5, 0xa0, 0x10, 0x71, 0x6a, 0xa3, 0x12, 0x9a, 0xfa, 0x00, 0xd6, 0x74, 0x44, 0x70, 0x67, 0x3c, 0x7a, 0x87, + 0x48, 0xf2, 0x3f, 0x95, 0x52, 0x67, 0x23, 0x79, 0x04, 0x4c, 0xeb, 0x81, 0x49, 0xfd, 0x92, 0x6d, 0x81, 0xe0, 0xf0, + 0x40, 0x7f, 0x0c, 0x14, 0xc9, 0x13, 0x89, 0x58, 0x50, 0xc7, 0xd3, 0xa8, 0x6f, 0xec, 0x4b, 0xb5, 0x27, 0xf7, 0x76, + 0x7c, 0xd6, 0x1e, 0x7b, 0x88, 0x24, 0x63, 0x7e, 0x10, 0x41, 0x12, 0x24, 0xc2, 0x18, 0x8b, 0x3c, 0xc4, 0x40, 0x34, + 0x3f, 0xb9, 0xc1, 0xe0, 0x54, 0x53, 0x6d, 0xfd, 0x58, 0xa2, 0x23, 0x10, 0xa8, 0xcb, 0x34, 0xaa, 0xd8, 0xaa, 0x4c, + 0x10, 0xcc, 0x67, 0xfd, 0xbb, 0x76, 0x44, 0x60, 0xa6, 0x1d, 0x03, 0xb4, 0xc9, 0x1b, 0xcc, 0x47, 0x44, 0x66, 0xcb, + 0xce, 0x27, 0x89, 0x09, 0xa6, 0xae, 0xda, 0x23, 0xb3, 0x71, 0xc6, 0xc9, 0xa6, 0xe9, 0xd4, 0xee, 0xaa, 0x32, 0xb8, + 0x08, 0x2f, 0x5e, 0xa2, 0x11, 0x80, 0xe8, 0x5a, 0xbe, 0x16, 0x9e, 0x1c, 0x08, 0x20, 0xcc, 0x2d, 0x0d, 0xfc, 0x96, + 0x69, 0xfb, 0x27, 0x5d, 0xab, 0x1b, 0x22, 0x36, 0x0a, 0x11, 0xfe, 0xd3, 0x04, 0xd9, 0xf5, 0x5b, 0xab, 0x1d, 0xfb, + 0xfb, 0x4e, 0x5b, 0xf6, 0x5b, 0x8b, 0x59, 0x4a, 0x43, 0x17, 0xc2, 0x86, 0x61, 0x6b, 0x35, 0x14, 0x56, 0xcb, 0x59, + 0x73, 0xe8, 0x80, 0xcc, 0xbc, 0x10, 0x90, 0x65, 0xee, 0x57, 0x3e, 0x42, 0x67, 0x07, 0xf6, 0x3f, 0xf2, 0x9d, 0xe4, + 0x1c, 0x1b, 0x76, 0x88, 0xaf, 0x77, 0xc1, 0xa2, 0x89, 0xac, 0x24, 0x94, 0x8f, 0xa0, 0x7c, 0xae, 0x5d, 0x5a, 0x47, + 0x6a, 0xe7, 0x46, 0x87, 0x46, 0x06, 0xfc, 0xc1, 0x98, 0x09, 0x1c, 0x88, 0x40, 0x2f, 0x05, 0xdd, 0x87, 0xef, 0x3b, + 0x26, 0xd3, 0x6f, 0x0d, 0x04, 0xff, 0xfe, 0x8d, 0xfb, 0x2d, 0x25, 0x60, 0x09, 0x88, 0x3b, 0x2d, 0xa0, 0x1b, 0xc4, + 0xfc, 0x7a, 0x69, 0x88, 0xc9, 0x8b, 0x43, 0x1b, 0xbd, 0x2c, 0x64, 0x78, 0xed, 0xc1, 0xc3, 0xe7, 0x99, 0xf7, 0xb2, + 0x53, 0x71, 0x86, 0x6b, 0xb3, 0x9b, 0x5e, 0xe2, 0xb6, 0xe3, 0xd7, 0x23, 0xbf, 0x45, 0xdc, 0xc0, 0xcd, 0x6e, 0x50, + 0xe6, 0x21, 0xcc, 0x3c, 0x0b, 0xdc, 0xa3, 0x61, 0x4a, 0x7f, 0xc3, 0x42, 0xac, 0x1b, 0xb2, 0xf5, 0x99, 0xc1, 0xea, + 0xb6, 0x8a, 0x41, 0x2c, 0x4f, 0x72, 0x3c, 0xc1, 0xc8, 0x42, 0xba, 0x61, 0x91, 0x93, 0x84, 0x37, 0x49, 0x1c, 0x71, + 0xaf, 0x8d, 0xd9, 0x56, 0x60, 0xea, 0x10, 0x1a, 0x72, 0x7b, 0xfc, 0xbe, 0x0b, 0x09, 0x66, 0x1e, 0x67, 0xa9, 0x8a, + 0x46, 0xea, 0xed, 0x5f, 0x3c, 0xb1, 0x47, 0xf5, 0x11, 0x6a, 0x7b, 0xcb, 0x92, 0xdb, 0xd5, 0xbf, 0xf7, 0xad, 0xd3, + 0x80, 0x5e, 0x30, 0x73, 0xc3, 0x70, 0xdc, 0x37, 0x36, 0x00, 0xd9, 0x48, 0x0a, 0x0c, 0x84, 0xd5, 0x08, 0x56, 0xd2, + 0x62, 0xec, 0xe9, 0x5d, 0xfd, 0xec, 0x18, 0x01, 0x2e, 0x81, 0xf5, 0x63, 0xa5, 0xb0, 0xe1, 0x14, 0xec, 0x7a, 0x03, + 0xf4, 0xdd, 0x76, 0x7b, 0x14, 0x4a, 0x93, 0x1b, 0x1a, 0x78, 0x9f, 0x0d, 0x04, 0x36, 0xfd, 0x14, 0xcf, 0xa1, 0x77, + 0x5d, 0xbf, 0xee, 0xfd, 0xbd, 0x31, 0x10, 0x21, 0xad, 0x91, 0xa0, 0xb5, 0xef, 0x7b, 0x2f, 0x69, 0x66, 0x65, 0x94, + 0xa1, 0x29, 0xdb, 0x54, 0xfb, 0x69, 0x38, 0xb6, 0x2d, 0x8b, 0x40, 0xed, 0x00, 0xaf, 0x5c, 0xe7, 0xe0, 0x3a, 0x53, + 0x14, 0xba, 0x12, 0x1f, 0x4a, 0x27, 0x78, 0xb7, 0x8d, 0x62, 0x12, 0x10, 0xe7, 0x07, 0x2b, 0xb8, 0x41, 0xc8, 0x59, + 0x23, 0x04, 0xd6, 0x66, 0xbb, 0xeb, 0x23, 0xd3, 0x95, 0xf8, 0xb5, 0x07, 0x59, 0x43, 0xa5, 0xa8, 0x14, 0xb8, 0xb4, + 0x38, 0x25, 0x79, 0xd2, 0x60, 0x78, 0x5d, 0x3f, 0xad, 0x69, 0x55, 0x25, 0xbe, 0xd6, 0xc5, 0x4e, 0xa9, 0x80, 0xb9, + 0xcf, 0xe9, 0xa9, 0x75, 0xa4, 0x78, 0x6b, 0xad, 0xad, 0x4f, 0x18, 0xe6, 0xf6, 0xde, 0x69, 0x0f, 0x20, 0x7f, 0xcc, + 0x67, 0x26, 0xc1, 0xc0, 0x88, 0x30, 0xc0, 0x5b, 0xa2, 0x97, 0x33, 0x26, 0x4f, 0xd0, 0x4c, 0x5f, 0xdc, 0xa3, 0xdc, + 0xbb, 0xdc, 0x7d, 0xca, 0x37, 0x2a, 0xb3, 0x47, 0x37, 0x5d, 0x04, 0xb4, 0xd6, 0x4d, 0x94, 0x1a, 0x1e, 0xc7, 0xb5, + 0xcb, 0x0b, 0xb1, 0x94, 0xc4, 0xeb, 0x10, 0xcd, 0xbf, 0xcb, 0x4f, 0x0e, 0x9b, 0x94, 0x95, 0x25, 0xdf, 0x19, 0x4b, + 0xc3, 0x8f, 0x15, 0xf2, 0xc2, 0x46, 0xaa, 0x01, 0x14, 0x57, 0x7a, 0x1d, 0xed, 0x64, 0xed, 0x5d, 0x56, 0x41, 0xa3, + 0x54, 0xc8, 0xd1, 0xa3, 0x35, 0x70, 0x94, 0x3a, 0x21, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xaf, 0x0c, 0x4e, 0x01, 0xb5, + 0xf2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x9a, 0xfc, 0x4c, 0xde, 0x8d, 0xc0, 0x78, 0xca, 0x07, 0x9e, 0xb8, 0xb0, 0x4c, + 0xfc, 0xb7, 0xec, 0x0f, 0x10, 0x95, 0x4c, 0x06, 0x15, 0x08, 0x4c, 0x83, 0x5d, 0x7c, 0x2d, 0x8d, 0xd4, 0x7a, 0x08, + 0xc1, 0xc9, 0xd5, 0x46, 0x7f, 0x30, 0xeb, 0x6b, 0x40, 0xa9, 0x7a, 0x83, 0x8a, 0x46, 0xec, 0xca, 0xf6, 0xd3, 0xbc, + 0x3e, 0x98, 0xa8, 0x7d, 0xa3, 0x81, 0x1b, 0xb6, 0xf9, 0xd5, 0x1e, 0xc5, 0xae, 0x8d, 0xe7, 0x4b, 0x60, 0x13, 0xb5, + 0xbc, 0x65, 0x52, 0x14, 0x1c, 0xda, 0x34, 0xa8, 0x76, 0x04, 0x23, 0x66, 0xba, 0x83, 0xce, 0x5b, 0xdb, 0x20, 0x3a, + 0x1d, 0x9c, 0x46, 0xd0, 0x19, 0x8c, 0x8b, 0x53, 0x5b, 0x35, 0x42, 0x49, 0x8c, 0x2f, 0xc7, 0xd0, 0x2f, 0xb2, 0x78, + 0xa3, 0x66, 0xda, 0x00, 0x5d, 0x49, 0x05, 0xf3, 0x6c, 0xc4, 0x4c, 0x0a, 0xb7, 0xec, 0xb9, 0x5d, 0x8a, 0xff, 0xa5, + 0x3b, 0xd7, 0xf7, 0x3c, 0x11, 0xe4, 0x03, 0x59, 0x3a, 0x0e, 0xfe, 0xb5, 0x98, 0xe1, 0xe7, 0x19, 0x8c, 0x5e, 0x64, + 0xd6, 0xc6, 0x2c, 0xc9, 0x17, 0x7c, 0x67, 0xf8, 0xa5, 0x06, 0x93, 0x9f, 0xb0, 0x9c, 0x21, 0xfa, 0x1a, 0x04, 0x38, + 0x72, 0xb5, 0xeb, 0x69, 0xc3, 0x78, 0x07, 0x8b, 0x17, 0xc5, 0x02, 0x51, 0xd4, 0xfb, 0x6a, 0x8e, 0xc3, 0xe2, 0x9c, + 0xa4, 0x04, 0x33, 0x9b, 0x1a, 0x49, 0x21, 0x64, 0xef, 0x9b, 0x93, 0x57, 0x56, 0x1a, 0x52, 0x9c, 0xc0, 0xcb, 0x81, + 0x5e, 0x23, 0xd2, 0xf1, 0xb1, 0x3a, 0x6b, 0x28, 0x4e, 0x1a, 0x99, 0x62, 0x36, 0xb1, 0x90, 0xce, 0xaa, 0x07, 0x1b, + 0xf3, 0x69, 0x91, 0x2b, 0xaf, 0xeb, 0x08, 0x7f, 0xad, 0xc2, 0x70, 0x96, 0x5e, 0x6f, 0xbe, 0x18, 0x06, 0x1d, 0xfe, + 0xaf, 0xd5, 0x84, 0x6f, 0xf0, 0x6d, 0x3f, 0x5f, 0x44, 0x44, 0xa8, 0xca, 0x0f, 0x74, 0xa2, 0x1d, 0xea, 0xe8, 0x34, + 0xf4, 0xd0, 0xcc, 0x56, 0x50, 0xb0, 0x48, 0xfb, 0x7d, 0x37, 0xbd, 0xf5, 0x35, 0x39, 0x7b, 0xe7, 0xba, 0xa6, 0x35, + 0xc1, 0xfc, 0xf8, 0x35, 0xd0, 0x9a, 0x8d, 0x84, 0x93, 0xe5, 0xf7, 0xc8, 0xde, 0x6c, 0xaf, 0x76, 0x67, 0xd4, 0xbe, + 0x3e, 0x1a, 0xde, 0x34, 0x8f, 0x19, 0x1f, 0x65, 0x93, 0x26, 0x6a, 0x3a, 0x73, 0x2d, 0xe0, 0x73, 0x6a, 0xea, 0x4e, + 0x24, 0x3a, 0x70, 0x76, 0xb5, 0x3c, 0xc5, 0x6f, 0x45, 0x64, 0xfa, 0x35, 0x89, 0xea, 0x96, 0x66, 0x50, 0xe4, 0x52, + 0x5a, 0xa8, 0xba, 0xad, 0x2a, 0x80, 0x7d, 0x8d, 0xa8, 0x19, 0xa8, 0x31, 0x0b, 0xdd, 0x29, 0x1a, 0x21, 0x8d, 0xb5, + 0x8c, 0xed, 0x87, 0x9a, 0x76, 0xa5, 0xaa, 0x1e, 0xdb, 0x25, 0x0e, 0x45, 0x03, 0x34, 0x2d, 0xcc, 0xf5, 0x6f, 0x76, + 0x75, 0xb3, 0x6d, 0x4b, 0xbd, 0x41, 0x5c, 0xf2, 0x9f, 0x87, 0x2d, 0xac, 0x9d, 0x29, 0x85, 0xc3, 0x15, 0xad, 0xe8, + 0x91, 0x6c, 0x1c, 0xb4, 0x0a, 0x83, 0xa8, 0x51, 0x65, 0xda, 0x88, 0x61, 0x44, 0xc2, 0x08, 0x85, 0x42, 0xe1, 0x3e, + 0x62, 0x5d, 0x6c, 0xca, 0xa3, 0x87, 0xd2, 0xea, 0x92, 0x1f, 0xb3, 0x58, 0xa3, 0x79, 0x5a, 0x7b, 0x2c, 0x64, 0xa9, + 0xc3, 0xc7, 0x2b, 0xc1, 0xe8, 0xf7, 0xcb, 0x84, 0x56, 0x6e, 0x31, 0x41, 0xa9, 0x0e, 0x24, 0x76, 0x3b, 0x79, 0x8b, + 0xf4, 0x63, 0x8b, 0x42, 0x12, 0xb2, 0x3f, 0xbd, 0x2c, 0x93, 0xa7, 0x8a, 0xe1, 0x55, 0xe4, 0x2c, 0x47, 0x09, 0xf1, + 0x0e, 0xfc, 0xa4, 0x5f, 0x7f, 0x92, 0x7a, 0xad, 0xba, 0xad, 0x75, 0x54, 0xd4, 0xce, 0x6d, 0xe9, 0x86, 0x71, 0x9d, + 0x0c, 0xaa, 0xe0, 0x06, 0x4c, 0xd2, 0xe8, 0x5b, 0x27, 0xa8, 0x4f, 0x31, 0x9a, 0xf2, 0x6a, 0x07, 0x65, 0x2d, 0xc3, + 0x60, 0x8d, 0xf1, 0x61, 0xf8, 0xc0, 0x64, 0xc6, 0x18, 0x61, 0x6c, 0xc3, 0x1c, 0xf9, 0x6c, 0xfa, 0xeb, 0x17, 0x42, + 0xea, 0x4d, 0x12, 0x11, 0x81, 0x7c, 0x90, 0x7c, 0x30, 0x22, 0xfd, 0xa7, 0x25, 0x56, 0x3b, 0xbc, 0x70, 0x48, 0x9f, + 0xc4, 0x16, 0x0e, 0x84, 0xcd, 0xfa, 0xd1, 0x6f, 0x98, 0x64, 0xde, 0xbe, 0x38, 0x41, 0x7e, 0x09, 0x6e, 0xd8, 0xde, + 0x6a, 0x08, 0xaa, 0x18, 0xad, 0x10, 0xc4, 0x0a, 0x1a, 0x21, 0x9e, 0xc0, 0xf9, 0x26, 0x63, 0xd5, 0xab, 0x25, 0x2e, + 0x73, 0x45, 0x83, 0x7f, 0xf6, 0x6d, 0x5a, 0x24, 0x3d, 0x88, 0xf7, 0x03, 0x59, 0xcf, 0xb0, 0x87, 0xa0, 0xc7, 0xc2, + 0x8a, 0xe4, 0xbb, 0x42, 0x96, 0xae, 0xe3, 0xd3, 0x49, 0xaa, 0xf7, 0xa4, 0x5f, 0x3f, 0xc0, 0x1e, 0xb4, 0xa9, 0x2d, + 0x34, 0x7f, 0x85, 0xaa, 0x0a, 0xf3, 0x7a, 0x33, 0xca, 0xa3, 0x25, 0x9b, 0xee, 0x08, 0x74, 0x10, 0x08, 0xb5, 0xd6, + 0x4b, 0x03, 0x8c, 0xe3, 0xfb, 0xb0, 0x19, 0x3d, 0x7e, 0x5d, 0xc4, 0x84, 0xab, 0x97, 0x2d, 0x45, 0x69, 0x93, 0x46, + 0x8f, 0xfb, 0xae, 0x59, 0x76, 0x19, 0x22, 0x88, 0xc4, 0x1f, 0x47, 0xd0, 0x66, 0x5c, 0x0b, 0x17, 0xd1, 0x09, 0x86, + 0x96, 0x2b, 0x9e, 0xb8, 0x47, 0xdd, 0x2f, 0xbb, 0xe7, 0xdb, 0xe6, 0x49, 0x0c, 0x58, 0x8a, 0xf8, 0xae, 0xac, 0xcd, + 0x39, 0x94, 0xa2, 0x74, 0x9b, 0xc0, 0x2c, 0x47, 0x7a, 0x8c, 0x47, 0xf2, 0x48, 0xd4, 0x01, 0x83, 0x68, 0x54, 0x7c, + 0x67, 0x65, 0xe0, 0x6e, 0xad, 0xb5, 0xf8, 0xf2, 0xf7, 0x7e, 0xfd, 0x7a, 0xb7, 0x42, 0xbd, 0x0c, 0x5e, 0x4e, 0xed, + 0x19, 0xef, 0xbc, 0x20, 0xa5, 0xbe, 0x88, 0xc1, 0xeb, 0xc7, 0xbc, 0x8a, 0x66, 0xdf, 0x35, 0x04, 0xa1, 0x85, 0xcb, + 0x7f, 0x0b, 0x8f, 0x3a, 0x2d, 0xd3, 0xa5, 0xa7, 0xaf, 0xa6, 0x9b, 0x4e, 0x97, 0xef, 0xe8, 0xc1, 0xad, 0x10, 0x21, + 0x61, 0x54, 0x63, 0xed, 0x93, 0x73, 0x8b, 0xc9, 0x97, 0xd1, 0xda, 0xa5, 0x55, 0x51, 0xc1, 0xe7, 0x1c, 0xdd, 0x0d, + 0xaa, 0x5b, 0xb8, 0xa9, 0x72, 0xfb, 0xe8, 0xad, 0xa8, 0xa2, 0xa1, 0x87, 0x0b, 0xa7, 0x44, 0x12, 0x85, 0xc8, 0x4b, + 0x98, 0xd8, 0x7d, 0x37, 0xa4, 0x81, 0x71, 0x75, 0x75, 0x4a, 0x75, 0x83, 0xc7, 0xd0, 0xc3, 0x10, 0x24, 0xae, 0xd9, + 0xf9, 0xff, 0xd2, 0xeb, 0xc1, 0x9b, 0x97, 0x3e, 0x25, 0x99, 0x17, 0xfe, 0x5d, 0x5a, 0xb8, 0xc5, 0x17, 0xfc, 0x8c, + 0x96, 0xa0, 0x65, 0xcb, 0xa3, 0xb2, 0x03, 0xeb, 0xa1, 0x3d, 0xd0, 0xbf, 0xae, 0x27, 0x9b, 0x55, 0x00, 0x5a, 0x5b, + 0x9e, 0x64, 0x34, 0x31, 0x7a, 0x72, 0xde, 0xa1, 0x50, 0x44, 0x42, 0x0e, 0xa3, 0x44, 0xad, 0x75, 0x20, 0xc3, 0x55, + 0x77, 0x5a, 0x0a, 0xb7, 0xb1, 0xbb, 0x9e, 0x59, 0x88, 0xe8, 0x48, 0x2f, 0x49, 0x66, 0x2e, 0x34, 0x21, 0xa8, 0x92, + 0xc8, 0x0f, 0x88, 0x6d, 0x81, 0xe3, 0x41, 0x73, 0x62, 0xeb, 0xa3, 0xd0, 0x52, 0x40, 0x18, 0xb7, 0x57, 0xf1, 0x35, + 0x01, 0x84, 0xd2, 0xba, 0xf3, 0x66, 0xbb, 0x70, 0xf9, 0x37, 0x6d, 0x65, 0x0c, 0x36, 0x3a, 0x77, 0x56, 0x71, 0x81, + 0x5b, 0xdd, 0x8b, 0x21, 0x88, 0x02, 0x25, 0x05, 0x31, 0x9c, 0x04, 0xd5, 0x07, 0x73, 0x20, 0x01, 0x97, 0xc8, 0x83, + 0x52, 0xe3, 0x5c, 0xb8, 0xf1, 0x46, 0x21, 0xc4, 0x62, 0x24, 0xaa, 0x62, 0xb2, 0x41, 0x70, 0x4c, 0x05, 0xda, 0xfd, + 0xf4, 0xdc, 0x7b, 0xe1, 0xfe, 0xa1, 0xa6, 0x56, 0x73, 0xa1, 0x08, 0xa3, 0xdd, 0xc9, 0xbd, 0xa0, 0x85, 0x64, 0xab, + 0x5e, 0xae, 0x91, 0xbd, 0xf0, 0xcd, 0x73, 0xef, 0x2b, 0x25, 0x20, 0xec, 0xdf, 0x19, 0x07, 0x02, 0x60, 0x2e, 0xed, + 0x6a, 0x2d, 0xd1, 0xdf, 0x9e, 0x48, 0xb3, 0xa1, 0xa5, 0x58, 0x37, 0xf3, 0x50, 0x01, 0xd6, 0xd4, 0xea, 0x09, 0x4b, + 0x59, 0xe5, 0x8d, 0x66, 0xa7, 0x86, 0xb7, 0x1d, 0x74, 0x75, 0x92, 0xc2, 0x93, 0xee, 0xff, 0xbd, 0x1f, 0x5e, 0xab, + 0x6e, 0x85, 0xa0, 0x3a, 0x93, 0x74, 0x16, 0x32, 0xd5, 0x7a, 0x1a, 0x53, 0x9c, 0xa4, 0xef, 0x04, 0x45, 0x45, 0x68, + 0xfc, 0x53, 0xd1, 0xd9, 0xf8, 0xa9, 0xeb, 0x03, 0xf7, 0x03, 0x2e, 0x28, 0xbe, 0xc9, 0x3a, 0x7e, 0x98, 0x45, 0x44, + 0x64, 0xe5, 0x67, 0xbb, 0xbc, 0x76, 0xdd, 0xa6, 0x33, 0xf3, 0xd2, 0x6d, 0x74, 0x9b, 0x7f, 0x83, 0x25, 0x1f, 0x8a, + 0x92, 0x97, 0xb4, 0x85, 0xa3, 0x5f, 0xe0, 0x7a, 0x28, 0xd3, 0x81, 0x21, 0x73, 0xeb, 0xba, 0xfe, 0x51, 0x31, 0xd2, + 0xd4, 0x11, 0x4f, 0x99, 0x43, 0x05, 0x9e, 0x9a, 0x9b, 0x4a, 0x0e, 0x94, 0xce, 0x30, 0x5f, 0x13, 0xe1, 0xcd, 0xde, + 0x31, 0xfd, 0x73, 0x41, 0x74, 0x7c, 0x04, 0xd3, 0x86, 0x7c, 0x58, 0x85, 0xe7, 0xe2, 0x58, 0xfd, 0x60, 0x35, 0x89, + 0x3c, 0x89, 0x03, 0xbc, 0x0f, 0x2c, 0x52, 0x61, 0x62, 0xe0, 0x6b, 0x76, 0x3b, 0xce, 0x17, 0x80, 0x19, 0x0f, 0xb9, + 0x4f, 0x77, 0xfc, 0x10, 0x04, 0x8e, 0x17, 0xaa, 0xc5, 0xcd, 0xe1, 0x2d, 0x08, 0x80, 0x8c, 0x59, 0x71, 0x5a, 0x8c, + 0xf2, 0x24, 0x25, 0xe0, 0x99, 0x5c, 0xba, 0x55, 0x43, 0x2a, 0xb3, 0x3f, 0x04, 0x94, 0x4b, 0xd7, 0x42, 0x0a, 0x6e, + 0xd5, 0x17, 0xa6, 0x84, 0x74, 0xd7, 0x68, 0xb0, 0x85, 0x7f, 0x2c, 0x88, 0x25, 0x0d, 0xea, 0x1a, 0xbf, 0xed, 0x57, + 0xee, 0xa4, 0x73, 0xe2, 0x3a, 0x4a, 0x5d, 0x22, 0x89, 0xfb, 0x3c, 0x8c, 0x04, 0x82, 0x99, 0x3d, 0x21, 0xb2, 0x18, + 0x62, 0x1f, 0x47, 0x3b, 0x02, 0xf0, 0x04, 0xa2, 0x23, 0xcf, 0xec, 0x5e, 0x40, 0x7c, 0x7a, 0x82, 0xb0, 0x2c, 0x7f, + 0x23, 0xe3, 0xd7, 0xd7, 0xc3, 0xec, 0x89, 0x62, 0x78, 0x25, 0xf1, 0x54, 0xc5, 0x12, 0x49, 0x43, 0x6b, 0xc0, 0xd2, + 0x15, 0xc9, 0x65, 0xe4, 0x19, 0x71, 0x7e, 0x66, 0x7d, 0x02, 0x7e, 0xec, 0x63, 0x38, 0xf0, 0xeb, 0x40, 0x5f, 0xa4, + 0x54, 0xf9, 0x36, 0x12, 0xe7, 0xd5, 0x7b, 0x73, 0xfd, 0x70, 0x27, 0xe9, 0xea, 0xd5, 0xa3, 0x6d, 0x68, 0x6c, 0x92, + 0xf4, 0x6f, 0xcd, 0x43, 0x80, 0x63, 0x9d, 0xa4, 0x33, 0x14, 0xc6, 0x64, 0x79, 0xd8, 0xb0, 0xea, 0x62, 0xe8, 0xce, + 0x03, 0xee, 0xa6, 0xba, 0x23, 0x75, 0xf8, 0xd2, 0xa4, 0x27, 0x85, 0x59, 0xd2, 0xd8, 0x25, 0xe9, 0xdf, 0xaa, 0x74, + 0x38, 0x54, 0x29, 0x46, 0xe4, 0xb2, 0x22, 0x46, 0xa6, 0x1d, 0xdc, 0x49, 0xfc, 0xb6, 0xe4, 0x9d, 0x80, 0x97, 0x36, + 0xf5, 0x79, 0x57, 0x2b, 0x26, 0xb4, 0x8c, 0xc9, 0x93, 0xb7, 0x76, 0x58, 0x69, 0xa1, 0x54, 0xb2, 0x40, 0x36, 0x65, + 0xa1, 0x51, 0xf0, 0x53, 0xdf, 0xfc, 0xf0, 0x83, 0xa2, 0x32, 0x10, 0x70, 0x3b, 0x58, 0xfd, 0xe3, 0x83, 0x78, 0x19, + 0x43, 0x3c, 0x32, 0x32, 0xa6, 0x7f, 0xc9, 0x50, 0xf7, 0x4f, 0x20, 0x93, 0xf0, 0x75, 0x76, 0xbf, 0x34, 0xf7, 0x17, + 0x6a, 0x1d, 0x8c, 0xeb, 0x68, 0x43, 0x13, 0xf8, 0x26, 0x14, 0xee, 0x87, 0xca, 0xc0, 0x46, 0x29, 0x43, 0xbe, 0x2f, + 0x6d, 0x9e, 0x7b, 0xe2, 0x27, 0x41, 0xf1, 0x69, 0x86, 0x59, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x32, 0xe9, 0xba, 0x43, + 0x6d, 0x7b, 0xab, 0xa9, 0x74, 0x76, 0xd4, 0x31, 0x41, 0xce, 0xf3, 0xa3, 0x19, 0x56, 0x9e, 0xbf, 0x36, 0xf9, 0x06, + 0x81, 0xcf, 0x9d, 0xf7, 0xa6, 0x5a, 0x07, 0x6a, 0xbf, 0x9c, 0x11, 0xb4, 0x2d, 0x03, 0x1c, 0xa9, 0x72, 0xa8, 0x8e, + 0x54, 0x0c, 0x2b, 0x33, 0xde, 0x98, 0xe2, 0xc5, 0x16, 0x7b, 0x9c, 0x2f, 0x21, 0x15, 0xb0, 0x1f, 0x90, 0xb2, 0xe4, + 0x98, 0xd5, 0x22, 0x65, 0x6f, 0x22, 0x05, 0x11, 0xca, 0x6f, 0x5e, 0x1e, 0xfc, 0xdd, 0x64, 0x84, 0x15, 0x58, 0xab, + 0x8e, 0x24, 0x5b, 0x9b, 0xc8, 0x69, 0x2d, 0xa9, 0x8a, 0xf3, 0x46, 0x19, 0x66, 0xbf, 0xeb, 0xcf, 0xcb, 0x26, 0x98, + 0xda, 0xc5, 0xa7, 0xe6, 0x60, 0x8d, 0x16, 0xa6, 0xa7, 0xc2, 0xfe, 0x82, 0x0f, 0x3d, 0x21, 0xbf, 0x19, 0xfc, 0xb2, + 0xaf, 0x6d, 0x18, 0x3c, 0x6a, 0x5f, 0x61, 0x43, 0xa5, 0x75, 0x31, 0xf5, 0xa2, 0x61, 0xb2, 0x2d, 0x7f, 0x7e, 0x2a, + 0xf7, 0x18, 0xb9, 0xc2, 0x8c, 0xc0, 0x1a, 0x95, 0x77, 0xc1, 0x01, 0xe1, 0x63, 0x44, 0x91, 0x1b, 0xb6, 0x45, 0x06, + 0x05, 0xdb, 0x46, 0xd3, 0xae, 0xf4, 0x31, 0x07, 0x79, 0x12, 0x84, 0x4e, 0x76, 0xc2, 0x3b, 0x5f, 0xbd, 0x32, 0x2c, + 0x8b, 0x24, 0xcd, 0x8b, 0xa8, 0xd2, 0x87, 0x55, 0xd5, 0x48, 0xe3, 0xbf, 0x00, 0x60, 0x14, 0xce, 0x97, 0xc2, 0xbf, + 0x29, 0x5c, 0xe3, 0x9d, 0xde, 0xaa, 0x91, 0x72, 0x8e, 0xc7, 0xbc, 0x9b, 0xb1, 0xc3, 0x0f, 0xc2, 0x97, 0xdc, 0xcf, + 0xa8, 0xc0, 0x3c, 0x2d, 0x0b, 0xb3, 0x35, 0xfc, 0x5a, 0x81, 0xdc, 0x3e, 0x12, 0xe7, 0x36, 0x6c, 0xa6, 0x53, 0x7b, + 0xd3, 0x97, 0x1b, 0x84, 0xcc, 0x19, 0xcd, 0xf2, 0xf5, 0x87, 0x87, 0x01, 0x75, 0x11, 0x7e, 0x3b, 0x16, 0xea, 0x51, + 0xb6, 0x74, 0xf0, 0x02, 0x1e, 0xae, 0x69, 0x29, 0x7a, 0xbe, 0xa9, 0x9d, 0xc8, 0x1f, 0x6f, 0x7c, 0x00, 0x6d, 0xef, + 0x75, 0x8c, 0x36, 0xd1, 0x43, 0x4a, 0x01, 0x22, 0x0b, 0x6d, 0xab, 0xaa, 0x66, 0xc8, 0xb2, 0x60, 0xb9, 0x0d, 0xbc, + 0xa7, 0x96, 0x08, 0x87, 0xef, 0xda, 0xd3, 0x85, 0x35, 0xfe, 0x58, 0x00, 0xfc, 0xfb, 0x8c, 0x88, 0x0a, 0xe5, 0x7f, + 0x87, 0xed, 0x19, 0x26, 0x22, 0xee, 0x08, 0xc9, 0x60, 0xc0, 0xc8, 0x43, 0x36, 0x23, 0x29, 0xd8, 0x6a, 0xa5, 0x00, + 0xbe, 0x87, 0x40, 0xe3, 0xba, 0x06, 0x21, 0xd8, 0xa0, 0xd7, 0x40, 0x3c, 0x1c, 0x2f, 0xa8, 0x6b, 0xbc, 0x36, 0x7e, + 0xbb, 0xd6, 0x9a, 0x30, 0xe2, 0xdb, 0xaa, 0x59, 0xbc, 0x56, 0x3d, 0x52, 0x39, 0x92, 0x10, 0x79, 0xa3, 0xa0, 0xd5, + 0x9b, 0x4e, 0xf7, 0xd3, 0x64, 0x44, 0x0a, 0x6a, 0x9d, 0x1b, 0x91, 0xf2, 0x4b, 0xb1, 0x39, 0xf5, 0x87, 0x94, 0x87, + 0x2c, 0x8f, 0xb9, 0x12, 0xd5, 0xb5, 0x08, 0x61, 0xd8, 0x75, 0xf4, 0xaf, 0xa1, 0x84, 0x21, 0x5f, 0x52, 0x19, 0x14, + 0x32, 0x53, 0x59, 0x20, 0x0d, 0xe5, 0x49, 0xe4, 0xee, 0x87, 0xe9, 0xea, 0xdd, 0xab, 0xdc, 0x27, 0xa9, 0x28, 0x89, + 0xdd, 0x85, 0x48, 0x93, 0x89, 0x37, 0xa6, 0xfd, 0xf6, 0x3f, 0x23, 0xe5, 0xdf, 0x54, 0x1d, 0x53, 0x8d, 0x25, 0xb1, + 0xd0, 0x00, 0xa5, 0x7c, 0xc4, 0xd3, 0x36, 0x5d, 0x8e, 0xa2, 0xad, 0xd2, 0x1e, 0x6a, 0x1e, 0x78, 0x58, 0x58, 0x13, + 0xc7, 0x11, 0xf4, 0x74, 0x84, 0xd8, 0x92, 0xda, 0x42, 0xd7, 0xa7, 0x99, 0x67, 0x45, 0x6d, 0x76, 0x8f, 0x54, 0xcb, + 0xe8, 0xa0, 0x35, 0x91, 0x34, 0xfb, 0xa9, 0xcb, 0x34, 0x90, 0x0a, 0x81, 0xef, 0x82, 0xdc, 0x2a, 0x4a, 0x5c, 0xaf, + 0xee, 0xdd, 0x43, 0xb5, 0xf2, 0x3b, 0xff, 0x74, 0x0b, 0x22, 0x23, 0x81, 0x81, 0x14, 0xd1, 0xbc, 0xa0, 0x9f, 0x18, + 0x96, 0xc1, 0x90, 0x33, 0x25, 0xb3, 0x9c, 0xb7, 0x00, 0xed, 0x91, 0xb6, 0x82, 0x0b, 0x12, 0x46, 0xe7, 0x58, 0x2b, + 0x83, 0xcf, 0x91, 0x22, 0x5f, 0xb5, 0xc5, 0xcc, 0x5e, 0xdd, 0xd3, 0x02, 0x53, 0x01, 0xac, 0x2b, 0x05, 0xcb, 0x59, + 0xdf, 0x28, 0xaa, 0xd8, 0xc8, 0xe4, 0xc7, 0x5f, 0xd0, 0x3d, 0xa5, 0x0c, 0x9d, 0x15, 0xae, 0x34, 0x6d, 0x3b, 0x97, + 0xc7, 0xee, 0x83, 0x02, 0x7c, 0xa2, 0x81, 0xcc, 0x4b, 0xf2, 0x9f, 0x9d, 0x6d, 0xd8, 0x7d, 0x52, 0xce, 0x77, 0x13, + 0xfd, 0xde, 0x48, 0xb3, 0xbf, 0x2e, 0x75, 0x28, 0xdb, 0xaf, 0x3c, 0xae, 0x5a, 0xe6, 0x3d, 0xd2, 0xe7, 0xc6, 0x64, + 0x44, 0x26, 0xb4, 0xcb, 0xfa, 0x36, 0xc2, 0xcd, 0xed, 0x33, 0x85, 0xc7, 0x37, 0xbc, 0x9c, 0x3f, 0x69, 0xc5, 0x36, + 0xa5, 0x8e, 0x94, 0xd8, 0x48, 0x14, 0x18, 0x64, 0x91, 0x9f, 0x78, 0x8a, 0x6e, 0xef, 0xa8, 0xad, 0x77, 0xea, 0xae, + 0x93, 0x13, 0x71, 0xe6, 0xea, 0x46, 0x52, 0xa5, 0x11, 0x76, 0xf3, 0x3c, 0xf2, 0xb2, 0x56, 0xd0, 0x8c, 0xd2, 0x43, + 0xed, 0xf6, 0x8e, 0x11, 0x1a, 0x56, 0x4a, 0x8a, 0x6c, 0x51, 0x1b, 0x2d, 0x07, 0x7a, 0xc8, 0x5f, 0x6b, 0x7e, 0xfe, + 0x67, 0x0b, 0x71, 0xe3, 0x70, 0xfa, 0x8a, 0x44, 0x44, 0x61, 0x10, 0xa7, 0x55, 0x24, 0xdb, 0x99, 0x40, 0x61, 0x1c, + 0x4c, 0xb0, 0x75, 0xa3, 0xa9, 0x87, 0x45, 0xa2, 0x96, 0x48, 0xc3, 0xf6, 0x28, 0x0f, 0x81, 0x2a, 0x09, 0x3d, 0x6d, + 0xad, 0x4e, 0xa2, 0xf5, 0x87, 0x6b, 0x9f, 0x11, 0xa1, 0x55, 0x8a, 0xac, 0xca, 0x2b, 0x57, 0x68, 0x04, 0x26, 0x12, + 0x89, 0x8e, 0x20, 0x0e, 0x4d, 0x08, 0x1f, 0x1e, 0xd2, 0x4b, 0xab, 0x22, 0x86, 0x56, 0x5c, 0x43, 0x66, 0x01, 0xc4, + 0x26, 0x63, 0xfa, 0x7a, 0xbf, 0x63, 0x19, 0xd7, 0xcb, 0x83, 0x56, 0xff, 0x91, 0x88, 0x13, 0xa4, 0xfb, 0xa2, 0x03, + 0x8c, 0x06, 0x1c, 0x55, 0xc1, 0xb7, 0x8f, 0xa1, 0xa8, 0x74, 0xa0, 0x5e, 0x8e, 0xdc, 0x22, 0xf2, 0x2b, 0xe0, 0xda, + 0xdd, 0x8a, 0x08, 0xdf, 0x2e, 0x9f, 0xd3, 0xac, 0x96, 0x11, 0xd4, 0xbe, 0x8f, 0x68, 0x95, 0x89, 0xb0, 0xb9, 0xb8, + 0xeb, 0xb1, 0x5c, 0x43, 0xd5, 0x87, 0x56, 0x5c, 0x44, 0xe1, 0xcd, 0x1c, 0xa4, 0x8d, 0xc9, 0x78, 0x49, 0x3f, 0xb5, + 0x1d, 0x95, 0x80, 0x5e, 0x28, 0x0b, 0x4d, 0x06, 0x49, 0xc1, 0xa3, 0xf7, 0x40, 0x98, 0xa4, 0x57, 0xce, 0x98, 0xfd, + 0x94, 0xa7, 0x24, 0x4e, 0xdf, 0x82, 0x76, 0x36, 0x45, 0xf0, 0x70, 0xd5, 0x5e, 0xda, 0x53, 0xd0, 0x7e, 0xcf, 0x74, + 0xb6, 0xbd, 0xac, 0x91, 0x78, 0x2f, 0x3a, 0xf0, 0x2a, 0xfa, 0x3c, 0x32, 0xc3, 0x98, 0xc1, 0xfd, 0x90, 0x90, 0xe4, + 0xb3, 0x94, 0x0a, 0x66, 0x41, 0x0f, 0xe4, 0x51, 0x91, 0x8c, 0xd2, 0x4c, 0xb7, 0xfd, 0x91, 0xe8, 0xfa, 0x69, 0xaa, + 0x76, 0xb5, 0xf6, 0x14, 0x55, 0x5e, 0xbe, 0x5e, 0xf8, 0xed, 0xf4, 0x8c, 0xae, 0xdc, 0x01, 0xc9, 0x7a, 0x46, 0x6f, + 0x5a, 0xb0, 0x5a, 0x28, 0x1d, 0xa9, 0x20, 0xf6, 0x3e, 0x27, 0xb0, 0x18, 0xd7, 0x43, 0x1a, 0xd6, 0xe0, 0x03, 0xa6, + 0x27, 0xab, 0xd3, 0x77, 0xce, 0x7d, 0xd9, 0xff, 0xf6, 0xdd, 0x76, 0x83, 0x35, 0x73, 0xf1, 0x07, 0xb9, 0x4b, 0x40, + 0xcd, 0x21, 0xd3, 0x64, 0xd2, 0x57, 0x69, 0x37, 0x27, 0xaf, 0x12, 0xb3, 0x70, 0x80, 0xfe, 0xdd, 0x1c, 0x72, 0xc2, + 0x3a, 0xde, 0xb8, 0x44, 0xf4, 0xd4, 0xbb, 0x70, 0xda, 0x13, 0x07, 0xf0, 0x2f, 0x18, 0x26, 0x4a, 0x88, 0x64, 0x2e, + 0xe1, 0x61, 0x5e, 0xc2, 0x51, 0xf2, 0x43, 0xb6, 0xcd, 0x54, 0xef, 0xa8, 0x6e, 0xde, 0x14, 0xd8, 0xf3, 0x14, 0x17, + 0xbb, 0x55, 0xc2, 0x8c, 0x55, 0xec, 0xb5, 0xd8, 0x43, 0x8f, 0x37, 0x28, 0x92, 0xcc, 0xf6, 0x19, 0x0d, 0x9d, 0xf9, + 0x4d, 0x7e, 0x7d, 0x71, 0x73, 0x37, 0xfd, 0x7f, 0x5c, 0x9d, 0x18, 0x87, 0x15, 0x7c, 0x36, 0xf4, 0x65, 0xbf, 0x2a, + 0xcb, 0xe7, 0x12, 0x5f, 0xad, 0x96, 0x77, 0x94, 0x8c, 0x7b, 0x9b, 0xf8, 0xc1, 0x00, 0x06, 0x6f, 0x5a, 0x48, 0x1e, + 0x4a, 0x14, 0x61, 0x64, 0xde, 0x1f, 0x2e, 0x29, 0xf0, 0x72, 0xf9, 0x55, 0x70, 0x91, 0x98, 0xfe, 0xb6, 0xf5, 0x4a, + 0x2a, 0xe2, 0x90, 0xaa, 0x23, 0xde, 0x4d, 0x10, 0x69, 0x51, 0x0e, 0x1d, 0xfd, 0xc4, 0x01, 0x93, 0x35, 0x38, 0x10, + 0x81, 0x82, 0xce, 0x67, 0x2f, 0x89, 0xc4, 0x8f, 0xd0, 0x5f, 0x79, 0x16, 0x75, 0xda, 0x8b, 0xf6, 0xb3, 0xed, 0x85, + 0xff, 0x7f, 0xba, 0xb4, 0xaa, 0x73, 0x6c, 0x40, 0xb0, 0xfe, 0x2f, 0x90, 0xb8, 0xd0, 0x0e, 0x4a, 0x90, 0xee, 0x53, + 0xf8, 0xc4, 0x9f, 0xdd, 0x69, 0x96, 0x13, 0x96, 0xaf, 0xd5, 0x6a, 0x19, 0x4f, 0xe8, 0x9c, 0x5c, 0x68, 0x1c, 0x27, + 0x6a, 0xca, 0x10, 0x3c, 0xe3, 0xe8, 0xed, 0xb5, 0x0c, 0xbd, 0xdb, 0x98, 0x4a, 0x82, 0x4e, 0xe2, 0x71, 0xc5, 0x52, + 0xac, 0xa2, 0x75, 0xbf, 0x6a, 0x63, 0xb6, 0x99, 0xc1, 0x19, 0x30, 0xce, 0xb2, 0x80, 0xd1, 0x83, 0xa5, 0x7a, 0x38, + 0x37, 0x0e, 0x98, 0x5e, 0xcb, 0x6b, 0x4c, 0x47, 0x04, 0x8d, 0xdd, 0xf2, 0xf5, 0x7a, 0x14, 0x51, 0x49, 0x26, 0x22, + 0xde, 0x2d, 0xf0, 0x40, 0x2f, 0x7e, 0x3e, 0x56, 0xbd, 0xf6, 0xa4, 0x6e, 0xe5, 0x2b, 0x15, 0x61, 0x59, 0x47, 0x53, + 0x19, 0x30, 0x5e, 0xdd, 0xac, 0x8a, 0xd0, 0xae, 0x84, 0xb8, 0x78, 0x21, 0x7b, 0x02, 0x31, 0x31, 0x92, 0x8f, 0x38, + 0x93, 0x60, 0x93, 0x83, 0x4c, 0x05, 0xe5, 0xe3, 0x43, 0xcd, 0x16, 0x04, 0xa1, 0xab, 0xdb, 0x50, 0x0b, 0x72, 0x2c, + 0x9c, 0x27, 0x92, 0x11, 0x4d, 0x12, 0x03, 0x57, 0x59, 0x49, 0xb0, 0x6a, 0x26, 0xe3, 0x65, 0xd6, 0x9d, 0x15, 0x7b, + 0x60, 0x53, 0xad, 0x39, 0x18, 0xdd, 0xff, 0x98, 0x17, 0x18, 0xa2, 0x28, 0x5a, 0xcf, 0x12, 0xc5, 0xf3, 0x88, 0x79, + 0xc0, 0x2c, 0x4b, 0xa0, 0x51, 0x84, 0x22, 0xf4, 0x6f, 0x89, 0x3d, 0xd4, 0x67, 0x95, 0x91, 0x58, 0x58, 0x0c, 0x27, + 0x54, 0xc5, 0xe9, 0x28, 0xed, 0x95, 0x85, 0xf7, 0xc1, 0x6e, 0x10, 0xc6, 0x57, 0xff, 0xd7, 0xf8, 0xee, 0x6d, 0x0f, + 0xa9, 0xed, 0xf9, 0x38, 0x9b, 0x99, 0x8f, 0xe9, 0x46, 0xef, 0xf6, 0x4f, 0x37, 0x22, 0x36, 0xbb, 0xad, 0x6c, 0x03, + 0x91, 0x4c, 0x14, 0x94, 0x9a, 0x3f, 0xb3, 0xdb, 0x03, 0xb6, 0xe2, 0xa0, 0x78, 0xdd, 0xa9, 0xa8, 0xcf, 0xd6, 0x6a, + 0x2c, 0x01, 0x08, 0xc7, 0x92, 0x46, 0xda, 0x25, 0xb6, 0x20, 0xd2, 0xfa, 0x1c, 0x19, 0x12, 0xbc, 0xb6, 0xce, 0xf3, + 0x00, 0x0e, 0x59, 0x32, 0x4d, 0x04, 0x2b, 0xd2, 0x4b, 0x00, 0x69, 0x1b, 0x21, 0xbd, 0xc8, 0x9e, 0x41, 0x09, 0xc0, + 0xab, 0x88, 0xf6, 0x46, 0x65, 0x22, 0x92, 0x37, 0x59, 0xa3, 0x14, 0xb6, 0xe3, 0x03, 0xe1, 0x65, 0x7e, 0x44, 0xb0, + 0xc4, 0xd4, 0x68, 0xcf, 0x96, 0x4e, 0x13, 0x50, 0x8b, 0xed, 0x34, 0x42, 0x98, 0xef, 0xd7, 0x8d, 0xc1, 0xc3, 0xe1, + 0x62, 0x49, 0x8a, 0x71, 0xb5, 0xde, 0x7c, 0x2c, 0xe5, 0x76, 0xe4, 0x5a, 0xec, 0x98, 0x3b, 0x70, 0x34, 0xe9, 0x9e, + 0xa6, 0x5d, 0xbd, 0xd1, 0xcd, 0xaf, 0xf8, 0xcd, 0xeb, 0x69, 0x89, 0x97, 0xc7, 0x47, 0x42, 0xf7, 0xae, 0x46, 0xa0, + 0xb9, 0x71, 0xce, 0x0f, 0xfd, 0xee, 0x5d, 0x9d, 0xe0, 0x8d, 0xff, 0x95, 0x1a, 0x4f, 0xca, 0xe4, 0xe4, 0x6f, 0xe6, + 0xd0, 0xf8, 0x8c, 0xf1, 0xb4, 0xb8, 0xa9, 0x40, 0xa0, 0x40, 0xd5, 0x01, 0xec, 0xce, 0xa2, 0xd2, 0x7f, 0x33, 0x62, + 0x7c, 0x04, 0x5c, 0x28, 0x3a, 0x35, 0xf8, 0x69, 0x49, 0x78, 0xc6, 0xf3, 0xd9, 0x2d, 0xd4, 0x22, 0x69, 0xa5, 0xce, + 0xc4, 0x4e, 0x1d, 0x7e, 0x2e, 0xf6, 0x0f, 0x2b, 0x22, 0x3a, 0x14, 0xf1, 0x61, 0x37, 0x05, 0x05, 0x41, 0xc3, 0x0b, + 0x62, 0x99, 0xa0, 0x0b, 0xa1, 0x7c, 0xd4, 0xec, 0xbe, 0x4c, 0x52, 0xfd, 0xc3, 0xfe, 0x82, 0x9f, 0x7b, 0xdb, 0xd7, + 0x22, 0x17, 0x4b, 0xa1, 0x59, 0xd9, 0x48, 0x27, 0x0f, 0x2e, 0x15, 0x6d, 0xaf, 0x82, 0xec, 0x6c, 0xde, 0x9a, 0x35, + 0x99, 0x03, 0xc9, 0x22, 0x2d, 0xc2, 0xfa, 0xc8, 0x73, 0xfe, 0xd9, 0xe2, 0x73, 0xba, 0x74, 0xdf, 0x37, 0x63, 0xdb, + 0x64, 0x98, 0xf4, 0x24, 0x81, 0x30, 0x51, 0x82, 0x6f, 0xcb, 0xe8, 0x01, 0x60, 0x7d, 0x6d, 0x39, 0xa2, 0xcc, 0x56, + 0x01, 0x99, 0xc9, 0x76, 0x7e, 0xed, 0x29, 0x20, 0xea, 0x6c, 0x05, 0x12, 0x31, 0x94, 0x3e, 0x03, 0x17, 0x34, 0x3e, + 0xb5, 0x20, 0x49, 0x89, 0x09, 0xc9, 0x0c, 0x1f, 0x01, 0x99, 0x02, 0x6e, 0xbe, 0xf3, 0x64, 0x0b, 0xfd, 0x54, 0xc6, + 0x29, 0xb0, 0x61, 0x5a, 0x0f, 0xe6, 0x2c, 0x8c, 0x67, 0x1a, 0x32, 0xe2, 0xf8, 0xe7, 0x1b, 0x81, 0xd5, 0x88, 0x3c, + 0x8f, 0xcc, 0x6c, 0x24, 0x2e, 0x60, 0x70, 0xd9, 0xf7, 0x92, 0x26, 0x10, 0xd7, 0xaf, 0x71, 0x8d, 0xf9, 0x24, 0x8f, + 0xd7, 0xea, 0xe6, 0xb7, 0xe6, 0x6f, 0x3d, 0x94, 0x67, 0xf9, 0xe2, 0xa4, 0x36, 0xad, 0x15, 0xf4, 0xcb, 0xb5, 0x56, + 0x1b, 0xa0, 0x56, 0xc1, 0xcc, 0x96, 0x8c, 0x5b, 0x69, 0x51, 0x04, 0x8e, 0x9a, 0xe5, 0xad, 0xd9, 0x1d, 0xdf, 0x6e, + 0x90, 0x3f, 0xd1, 0x10, 0x31, 0x3e, 0x55, 0x81, 0x4b, 0xd4, 0xf1, 0x73, 0xf4, 0x36, 0x87, 0x76, 0x18, 0xaf, 0xe2, + 0x87, 0x6d, 0xbc, 0xc8, 0xd8, 0xca, 0xf2, 0xf2, 0x75, 0x74, 0x88, 0x2b, 0x47, 0xeb, 0x30, 0x34, 0xfd, 0x34, 0x8d, + 0x39, 0x52, 0xa8, 0x27, 0xec, 0xf8, 0x7b, 0x0c, 0xf8, 0x4f, 0xed, 0xf1, 0xab, 0xfe, 0x93, 0xe3, 0x5f, 0x86, 0x5d, + 0xe5, 0x65, 0xfe, 0x63, 0x90, 0xbf, 0x87, 0x4f, 0xa9, 0xf2, 0xb3, 0x89, 0x2c, 0x54, 0x9b, 0x43, 0xf2, 0x68, 0x2d, + 0x87, 0x05, 0xfa, 0xea, 0xc3, 0xc9, 0xe9, 0x04, 0xc3, 0x9a, 0x53, 0xe7, 0x07, 0xa4, 0xaf, 0x6b, 0xe2, 0xc2, 0x2f, + 0xc6, 0xa7, 0xab, 0xb9, 0x0c, 0xdd, 0x74, 0xb9, 0x87, 0x54, 0xee, 0x8b, 0x4c, 0xb5, 0xad, 0xac, 0x9d, 0xfd, 0xfd, + 0x60, 0x70, 0x47, 0x04, 0x36, 0x9c, 0x7b, 0xf3, 0x85, 0xe7, 0x9f, 0xf4, 0x9f, 0xee, 0x29, 0x5a, 0x33, 0x16, 0x5f, + 0xe8, 0x33, 0xad, 0x5c, 0xbe, 0x71, 0x6d, 0xca, 0x36, 0xf4, 0x99, 0xda, 0x74, 0x03, 0x20, 0x26, 0x15, 0x34, 0x28, + 0xeb, 0xdc, 0xc7, 0x1f, 0x14, 0x7d, 0x48, 0x28, 0xfa, 0xd2, 0xe7, 0xa3, 0xda, 0x17, 0x06, 0x11, 0x00, 0x49, 0x0c, + 0x33, 0xf3, 0x97, 0x82, 0xee, 0x84, 0x86, 0x07, 0xfa, 0xe6, 0xe9, 0x27, 0x4e, 0x7d, 0x06, 0xde, 0x1a, 0xf5, 0x0f, + 0x52, 0x5c, 0x5f, 0x81, 0x04, 0xb0, 0x70, 0x9e, 0x2e, 0xff, 0x4f, 0x5e, 0x10, 0x42, 0xd2, 0x9c, 0x2c, 0x6a, 0x3b, + 0x57, 0xdd, 0xff, 0x98, 0x6c, 0xf0, 0x11, 0x1b, 0x24, 0xf8, 0x38, 0x29, 0x26, 0x9e, 0x05, 0x41, 0x75, 0x45, 0xcf, + 0x4d, 0xae, 0xfa, 0xb3, 0x8c, 0x43, 0xfe, 0xf7, 0xb1, 0x3c, 0x5f, 0x40, 0xce, 0x63, 0xc6, 0x77, 0x7e, 0x88, 0xb0, + 0x24, 0xa7, 0x61, 0x67, 0x76, 0x5f, 0xed, 0xcf, 0xa3, 0x81, 0xfa, 0x6a, 0x77, 0x7e, 0x03, 0x09, 0xf8, 0xc2, 0x0f, + 0x6b, 0xa8, 0x51, 0xf9, 0xa3, 0x39, 0xad, 0xbd, 0x4a, 0x1b, 0x7d, 0x42, 0x25, 0x22, 0xb8, 0x94, 0x1c, 0xa0, 0xbe, + 0x48, 0x3a, 0x3f, 0x99, 0x38, 0x66, 0xda, 0x94, 0x1c, 0x74, 0xe3, 0x5c, 0x72, 0xa1, 0x1c, 0x5a, 0x49, 0x1d, 0xa5, + 0x80, 0x9c, 0x94, 0xd1, 0x81, 0x15, 0xdd, 0x5e, 0x4a, 0xc6, 0x8f, 0x8a, 0xd0, 0x2e, 0x9b, 0xcd, 0x35, 0x2b, 0x8b, + 0x99, 0x44, 0x8c, 0x54, 0x70, 0x59, 0xb2, 0x32, 0x41, 0xbf, 0xa8, 0x8d, 0xa9, 0x8d, 0x64, 0xba, 0xb7, 0x59, 0x9d, + 0xba, 0x08, 0x34, 0xb8, 0x72, 0x40, 0x5e, 0xf1, 0x2a, 0x60, 0x4b, 0x48, 0x26, 0xcc, 0x22, 0x56, 0x70, 0xa1, 0xdc, + 0xf7, 0x99, 0xfb, 0x60, 0x7f, 0x9c, 0x04, 0xe7, 0x5b, 0x6f, 0xd1, 0xef, 0x12, 0x9c, 0x82, 0xea, 0xf5, 0xe7, 0xd4, + 0xb5, 0xb8, 0xbc, 0x62, 0x0a, 0x0a, 0x1c, 0x83, 0x7c, 0xba, 0xcb, 0x03, 0x22, 0xf0, 0x43, 0xfb, 0xa4, 0x8e, 0xd3, + 0xd6, 0x7f, 0x46, 0xc7, 0x0c, 0xb2, 0x81, 0x54, 0xe7, 0xbe, 0x2c, 0xb0, 0x9d, 0x2e, 0x5b, 0x22, 0xb7, 0x02, 0x77, + 0x4a, 0x75, 0xdb, 0x0b, 0x94, 0x29, 0xd1, 0x51, 0x11, 0x81, 0x6d, 0x06, 0xd0, 0xb3, 0x15, 0xc1, 0x4b, 0x1f, 0x79, + 0xd6, 0x2c, 0x68, 0xe8, 0x8f, 0x88, 0x34, 0x99, 0xd0, 0x80, 0x41, 0x2e, 0x26, 0x5e, 0x4c, 0xbd, 0xf4, 0x98, 0x45, + 0xc7, 0x19, 0x70, 0x67, 0xe7, 0x2c, 0x2c, 0xe6, 0xf5, 0x34, 0xe5, 0x4b, 0x8f, 0x7e, 0x33, 0xbc, 0xec, 0x5e, 0xba, + 0xf9, 0xe9, 0x73, 0xba, 0xc1, 0xc4, 0x06, 0xba, 0x6b, 0x75, 0x1c, 0xcd, 0x83, 0x87, 0x16, 0x30, 0x93, 0xd2, 0x1c, + 0xef, 0x5b, 0xd0, 0xd2, 0xb9, 0x08, 0x99, 0xc8, 0xcb, 0x83, 0x9e, 0xed, 0x1b, 0xd2, 0x50, 0xb3, 0x13, 0xe0, 0xb3, + 0xb3, 0x34, 0x9a, 0x2b, 0x5e, 0xd0, 0x42, 0x09, 0x23, 0xc4, 0x65, 0xfd, 0x13, 0xe0, 0x81, 0xaf, 0x01, 0xca, 0x9f, + 0x94, 0xeb, 0x81, 0x67, 0x8e, 0xb9, 0x43, 0x38, 0xe1, 0xa7, 0x8a, 0xc0, 0xdd, 0x45, 0x85, 0xfe, 0xc9, 0x8c, 0x21, + 0x85, 0x01, 0x5f, 0x15, 0xe3, 0x29, 0xe1, 0x15, 0x68, 0x1a, 0x94, 0x07, 0x87, 0x01, 0xaa, 0x51, 0xf7, 0x7d, 0xed, + 0x53, 0x38, 0xa2, 0x09, 0x0f, 0x79, 0x87, 0xbc, 0x1a, 0xaa, 0x85, 0x26, 0x3e, 0xe4, 0x1d, 0x93, 0xe0, 0x9b, 0x0f, + 0xf7, 0x32, 0x7d, 0x44, 0x95, 0xa3, 0x17, 0xfa, 0x84, 0x05, 0x92, 0x53, 0x3d, 0x5e, 0x4b, 0xd1, 0x5e, 0xd1, 0x1c, + 0x5a, 0x09, 0x54, 0x6c, 0x4c, 0x87, 0x70, 0xe9, 0xd9, 0x5e, 0x7f, 0x7a, 0x93, 0xf8, 0x8b, 0x38, 0x63, 0x0d, 0x7b, + 0x02, 0xce, 0x99, 0x0d, 0xaa, 0xef, 0x64, 0x97, 0xb0, 0x48, 0x92, 0x9e, 0x67, 0x4e, 0xc7, 0x04, 0xb9, 0x79, 0xcd, + 0x1d, 0xdc, 0xcc, 0x43, 0xb9, 0xaa, 0x4f, 0x44, 0xa1, 0x49, 0xdd, 0x49, 0x41, 0xc4, 0x5b, 0xf7, 0xd7, 0x09, 0x6a, + 0x19, 0x75, 0x75, 0xd3, 0xdf, 0x8a, 0x78, 0x64, 0xcc, 0xbf, 0x56, 0x91, 0xd1, 0x2a, 0xf7, 0xdb, 0xd6, 0x5f, 0x57, + 0x66, 0x0f, 0xd9, 0xcf, 0xab, 0x5a, 0xf7, 0x3f, 0x6b, 0xd8, 0x6b, 0x5e, 0x2b, 0x45, 0x11, 0xce, 0x5c, 0x4d, 0x7a, + 0x64, 0xbe, 0x41, 0x2f, 0xee, 0xf6, 0xf0, 0x9c, 0x04, 0x28, 0x13, 0x27, 0x21, 0x0e, 0x24, 0xe4, 0x18, 0x6b, 0xbe, + 0xa2, 0x3d, 0xe6, 0xba, 0x61, 0x51, 0x99, 0x6b, 0x7e, 0x20, 0x68, 0x40, 0x05, 0xf4, 0x87, 0x1d, 0x4e, 0x73, 0x6f, + 0x42, 0xc3, 0x6f, 0x42, 0x3e, 0x43, 0xf0, 0xbb, 0xfc, 0x63, 0x81, 0xa1, 0xd0, 0x52, 0x43, 0x86, 0xeb, 0x54, 0x37, + 0x63, 0xb2, 0xda, 0x04, 0xfe, 0xb7, 0xb4, 0x9b, 0x51, 0x43, 0x64, 0x41, 0x84, 0x0c, 0x30, 0x90, 0xd1, 0x16, 0x03, + 0xaf, 0x69, 0xa6, 0xd9, 0x6a, 0x30, 0x56, 0x1f, 0x36, 0x59, 0x0a, 0x76, 0xaf, 0x9c, 0xa9, 0x1c, 0x06, 0xb5, 0x81, + 0xe1, 0x5d, 0xfa, 0xde, 0x3e, 0x2c, 0xe3, 0x45, 0xad, 0x90, 0xfb, 0xe9, 0x10, 0x19, 0x6e, 0x52, 0xc7, 0x6a, 0xa6, + 0xff, 0x19, 0x33, 0x31, 0x3e, 0x35, 0x38, 0x04, 0x36, 0x8c, 0x5d, 0xd5, 0x82, 0x61, 0xda, 0x28, 0xed, 0x9d, 0xb2, + 0x2e, 0x68, 0x21, 0x2c, 0xad, 0x5a, 0xe3, 0x80, 0x71, 0x4e, 0x2f, 0x2f, 0xd4, 0xe9, 0xc4, 0x9b, 0xfa, 0xdb, 0xc8, + 0x84, 0x0f, 0xfe, 0x35, 0x87, 0xba, 0x5a, 0x18, 0x85, 0xe3, 0xe1, 0xa3, 0x94, 0x07, 0x49, 0x68, 0x89, 0x85, 0xa6, + 0x6c, 0x6e, 0x48, 0x54, 0x87, 0x62, 0x23, 0x28, 0xf8, 0x7c, 0x85, 0x08, 0xb8, 0xc3, 0x61, 0x4b, 0x49, 0xf7, 0x16, + 0xcf, 0x90, 0x24, 0x2a, 0x23, 0x17, 0x9b, 0x60, 0x0f, 0x04, 0xc7, 0xa5, 0xa6, 0xac, 0xe5, 0xf9, 0xaf, 0x92, 0xe8, + 0x9f, 0xa0, 0xe0, 0x25, 0x29, 0xe5, 0xfc, 0x3b, 0x16, 0x7f, 0xd6, 0xd7, 0xc7, 0x88, 0xde, 0xfb, 0x0b, 0xc9, 0x67, + 0x7d, 0xb6, 0x6d, 0x1b, 0x23, 0xf3, 0xf2, 0x66, 0xae, 0x1f, 0xeb, 0xb8, 0x8c, 0x5d, 0xa2, 0x80, 0xe8, 0x6f, 0x58, + 0x2e, 0xd3, 0x3c, 0xc0, 0xf2, 0xb0, 0x3c, 0x8a, 0xfc, 0xb6, 0x22, 0x59, 0xa2, 0x81, 0xb7, 0x38, 0x2d, 0xd2, 0xbb, + 0xed, 0x78, 0x97, 0x2b, 0x75, 0x3a, 0x74, 0x2b, 0x63, 0x49, 0x34, 0xaa, 0x94, 0x43, 0x10, 0x03, 0x77, 0xba, 0x38, + 0x06, 0xbb, 0x33, 0x99, 0x3d, 0x4e, 0xdb, 0x98, 0xea, 0x4e, 0xdc, 0xd1, 0x13, 0xbc, 0xc4, 0x27, 0x2d, 0x35, 0xbb, + 0xa3, 0x17, 0x5a, 0x86, 0x4a, 0xc8, 0xea, 0xf4, 0x85, 0x56, 0x3f, 0x8a, 0x90, 0x24, 0x07, 0xfc, 0xaa, 0xf2, 0x97, + 0xaf, 0xd7, 0x63, 0xa1, 0x52, 0x5d, 0x54, 0x14, 0x68, 0x7e, 0x9e, 0x26, 0x1e, 0xa3, 0xdd, 0x6f, 0xa5, 0xaf, 0xce, + 0x1b, 0xc2, 0x07, 0xa0, 0x02, 0x92, 0x5b, 0x39, 0x34, 0xa4, 0xa1, 0x65, 0x3e, 0x3c, 0xce, 0x50, 0x28, 0x02, 0x74, + 0x26, 0x75, 0xe1, 0xa9, 0x8b, 0xf3, 0xea, 0x1f, 0x13, 0x54, 0x6c, 0x3f, 0xa7, 0x0c, 0x80, 0x93, 0x34, 0x40, 0x34, + 0x1a, 0xcf, 0x59, 0xa7, 0xd1, 0x85, 0x52, 0x3c, 0x03, 0x47, 0xc0, 0x7a, 0x89, 0x5c, 0x7b, 0x45, 0xeb, 0x5a, 0x86, + 0x34, 0xe9, 0xfe, 0xed, 0x51, 0xbf, 0x0d, 0xc1, 0x1d, 0x98, 0x34, 0x12, 0x3a, 0xaa, 0xae, 0x98, 0x1b, 0xc9, 0x38, + 0x50, 0x77, 0xda, 0x4d, 0x29, 0x37, 0x56, 0xd8, 0xcb, 0x5c, 0xb6, 0xaa, 0x63, 0xb9, 0x44, 0x58, 0xc4, 0xc5, 0x51, + 0x62, 0x45, 0x80, 0xef, 0x91, 0x41, 0x54, 0xaa, 0xf2, 0x24, 0x8a, 0x90, 0xe4, 0x0d, 0x16, 0x18, 0x73, 0x0b, 0xfd, + 0x26, 0x12, 0x3c, 0xf8, 0xfa, 0xa7, 0x15, 0x49, 0xa1, 0x12, 0x10, 0x40, 0x83, 0x81, 0x16, 0x50, 0xcd, 0xfc, 0xa3, + 0x51, 0xb7, 0x18, 0x3a, 0xcf, 0xe2, 0x39, 0x25, 0xc9, 0xa0, 0x3f, 0xfe, 0xfb, 0x09, 0x61, 0xd0, 0x06, 0xb0, 0x90, + 0x11, 0x07, 0xdc, 0x30, 0xd7, 0x9b, 0x44, 0xfa, 0x6c, 0x51, 0x2c, 0xb6, 0xd8, 0xcb, 0xb9, 0x4d, 0xe9, 0x05, 0x8d, + 0x97, 0x50, 0xf2, 0x8e, 0xe1, 0x2b, 0xaf, 0x83, 0x99, 0xb7, 0xbc, 0xc6, 0x0d, 0x16, 0xfa, 0x05, 0x8b, 0xae, 0x4a, + 0x72, 0xef, 0x97, 0x3d, 0x00, 0x99, 0x4f, 0x27, 0xaa, 0x37, 0x04, 0x0f, 0x21, 0x65, 0x63, 0xcc, 0x98, 0x73, 0x83, + 0x7b, 0xe7, 0x53, 0x45, 0x0a, 0x23, 0x17, 0x86, 0x00, 0x4e, 0x62, 0x94, 0xd1, 0xa6, 0x9e, 0xce, 0x42, 0x9d, 0x7e, + 0xe1, 0xad, 0x03, 0xf5, 0x6b, 0x53, 0x09, 0xc5, 0x5e, 0xd6, 0x03, 0x22, 0x6a, 0xaa, 0xae, 0x04, 0xe5, 0xa6, 0x44, + 0xf5, 0xed, 0x27, 0x78, 0xa6, 0xe3, 0x50, 0xfc, 0xcc, 0xc0, 0x48, 0x4c, 0x84, 0xe4, 0x6c, 0x90, 0x24, 0x4f, 0xd2, + 0x65, 0x2d, 0x09, 0xea, 0xda, 0xaf, 0x12, 0xc2, 0x23, 0x92, 0x71, 0x7e, 0xd6, 0x87, 0x7a, 0xe0, 0xca, 0x06, 0xbb, + 0x1c, 0x4f, 0xbf, 0x08, 0xd7, 0xdd, 0xa6, 0x3d, 0x35, 0xbc, 0xfb, 0x54, 0x64, 0x72, 0xcb, 0x56, 0xcd, 0x62, 0x63, + 0x82, 0x9f, 0xf8, 0x3c, 0xe8, 0x3e, 0xee, 0x37, 0x24, 0xa1, 0x9f, 0x6f, 0x73, 0x3f, 0xb1, 0xd2, 0xe8, 0x03, 0x78, + 0xd0, 0x58, 0x8a, 0x4b, 0x2b, 0x50, 0x63, 0xc1, 0x97, 0xdb, 0x92, 0xbc, 0xcd, 0x3c, 0xf0, 0x9d, 0xb8, 0x10, 0xba, + 0xc8, 0x7d, 0xe4, 0x6b, 0xe4, 0xad, 0xf4, 0x6e, 0xd5, 0x46, 0xfe, 0xe0, 0x57, 0x7f, 0xc8, 0x4a, 0x4f, 0xe9, 0x8f, + 0xca, 0x9c, 0xc5, 0x37, 0x5c, 0xa2, 0x9b, 0x81, 0x1d, 0xc1, 0x49, 0x5d, 0xf5, 0xe1, 0x0d, 0xa0, 0xb5, 0x85, 0xb7, + 0x1c, 0x4d, 0x13, 0x81, 0xe7, 0x66, 0xb8, 0xc4, 0x15, 0xd9, 0xe0, 0x06, 0x8a, 0x3d, 0x28, 0x60, 0x20, 0x36, 0xca, + 0x74, 0x3c, 0x00, 0xfc, 0x1c, 0xe2, 0x6e, 0xcc, 0xcf, 0xba, 0x66, 0x1b, 0x2d, 0x70, 0x4e, 0x91, 0x05, 0x64, 0x2f, + 0x43, 0x03, 0x0a, 0xd0, 0x09, 0x45, 0x50, 0xda, 0xac, 0xb1, 0x03, 0x26, 0x84, 0x15, 0x46, 0xd3, 0x00, 0xc7, 0x86, + 0x98, 0xb3, 0x97, 0xe6, 0x16, 0x81, 0x2f, 0x97, 0x88, 0x5c, 0xd3, 0x23, 0xa1, 0x7c, 0x86, 0x14, 0x38, 0xd1, 0xcf, + 0xd3, 0x7f, 0x03, 0x26, 0xbd, 0x9b, 0x13, 0xb4, 0xa7, 0x83, 0x69, 0xbf, 0xd4, 0x10, 0x28, 0x2d, 0x23, 0xf7, 0x87, + 0xe6, 0xf9, 0x7a, 0x31, 0xa6, 0x6b, 0xac, 0x76, 0x1b, 0xcd, 0x3f, 0xc5, 0xf5, 0x3c, 0x19, 0xb7, 0x88, 0x5c, 0x18, + 0x00, 0x7e, 0x6f, 0x06, 0x8d, 0xb7, 0xde, 0x4f, 0x2a, 0x3c, 0x67, 0x0d, 0x4b, 0x28, 0xdd, 0x23, 0xf2, 0x6d, 0xfe, + 0x87, 0x69, 0x3a, 0x28, 0x82, 0x53, 0x1b, 0xf2, 0xde, 0x83, 0x7b, 0x58, 0x87, 0x82, 0xa1, 0xaf, 0xc3, 0x94, 0xf9, + 0xc9, 0xce, 0xb2, 0x81, 0xd2, 0xb6, 0xb3, 0x5d, 0x35, 0x25, 0xed, 0x42, 0x32, 0x5c, 0x91, 0x18, 0xa4, 0xda, 0xc8, + 0x8f, 0xb6, 0xb2, 0xb2, 0x66, 0x6e, 0xa7, 0x38, 0xf2, 0x73, 0xa7, 0x33, 0xec, 0xde, 0xd8, 0xac, 0x1b, 0x1e, 0x80, + 0x34, 0xd7, 0x29, 0x00, 0x08, 0xc2, 0xa5, 0x6c, 0xe2, 0x1d, 0x4b, 0x95, 0xed, 0x40, 0x7d, 0xb0, 0xd0, 0x1c, 0x5c, + 0xe7, 0xa3, 0x09, 0xf9, 0xb8, 0xd9, 0xac, 0xf4, 0x3c, 0x07, 0x88, 0xc7, 0x71, 0x52, 0x19, 0x0c, 0x91, 0x82, 0x9f, + 0x4a, 0xb0, 0xc3, 0xd1, 0xe2, 0x3c, 0xfa, 0x6b, 0xe4, 0xbc, 0x4f, 0x50, 0x0d, 0x15, 0x58, 0x15, 0x6c, 0xc3, 0xc6, + 0xd3, 0x8b, 0xc4, 0x65, 0xbb, 0x53, 0xa1, 0x45, 0x87, 0x83, 0x5a, 0xf8, 0xd0, 0x01, 0xfd, 0x90, 0x14, 0x0a, 0x71, + 0x2e, 0xc2, 0x79, 0x16, 0x92, 0xa7, 0x0d, 0x14, 0x46, 0x5e, 0x8c, 0xdf, 0xc6, 0x70, 0xb6, 0xeb, 0x16, 0x23, 0x4b, + 0xd7, 0x74, 0x6b, 0x9c, 0x67, 0x93, 0x1f, 0xd1, 0x13, 0x27, 0x55, 0x24, 0xd9, 0x44, 0x2a, 0xa8, 0x51, 0x1a, 0x6c, + 0xfc, 0x15, 0x00, 0x05, 0x73, 0xc3, 0x6b, 0x1a, 0x8f, 0xb4, 0x4c, 0xc4, 0x5d, 0x8e, 0x06, 0x9b, 0xcc, 0xc1, 0xe3, + 0x60, 0xd0, 0x2b, 0xc4, 0x19, 0xda, 0x05, 0x4e, 0x72, 0xab, 0xc4, 0x1e, 0x7f, 0x91, 0xef, 0x25, 0x5e, 0xd8, 0x94, + 0xa1, 0x47, 0x3c, 0x48, 0x2c, 0x9b, 0x8f, 0xc1, 0xea, 0xfc, 0xbb, 0xfd, 0x90, 0x68, 0x34, 0xd0, 0x01, 0xe8, 0xc8, + 0x97, 0x70, 0xde, 0x13, 0xd3, 0xa4, 0x7b, 0xac, 0xbb, 0xf8, 0xd6, 0xfd, 0xf5, 0x69, 0xf0, 0xdd, 0x21, 0xa3, 0x2f, + 0x70, 0x3b, 0x69, 0xc2, 0x76, 0x6e, 0x5a, 0xeb, 0xfa, 0x03, 0x58, 0x00, 0xa7, 0xcc, 0x78, 0x26, 0x86, 0x97, 0x0d, + 0xfa, 0x46, 0x17, 0xe4, 0xb9, 0xbb, 0x73, 0x1d, 0xf7, 0xe7, 0xb8, 0xf5, 0xe2, 0x94, 0x43, 0x6a, 0x61, 0x11, 0xa8, + 0x19, 0x40, 0x05, 0xe4, 0x65, 0x34, 0x25, 0x5d, 0x10, 0xfc, 0xda, 0xa0, 0xe8, 0x7c, 0x87, 0x31, 0x40, 0xbd, 0xea, + 0x39, 0xcd, 0xfb, 0x5b, 0x4e, 0xf2, 0x42, 0xc4, 0x7b, 0x9b, 0xa6, 0xfa, 0xa7, 0x95, 0x7d, 0xca, 0x94, 0xd7, 0x2f, + 0xcd, 0xd1, 0xd9, 0x84, 0xaa, 0xad, 0xdd, 0xa6, 0x1a, 0xe2, 0x73, 0xbc, 0x64, 0x1e, 0x51, 0xbc, 0x80, 0x81, 0xe6, + 0x81, 0x1f, 0x79, 0xaf, 0xed, 0xdd, 0x68, 0x56, 0x5e, 0xa7, 0x0b, 0xfa, 0x7e, 0x4e, 0xb3, 0x12, 0xbc, 0x67, 0x67, + 0xab, 0x4a, 0xf5, 0x92, 0x0a, 0x86, 0x79, 0xd7, 0x2b, 0x7f, 0x46, 0xbf, 0xd1, 0x13, 0x3f, 0xe5, 0x4d, 0xe3, 0x37, + 0x25, 0xf3, 0xdb, 0x24, 0x4c, 0xea, 0x1c, 0xd6, 0xf4, 0x28, 0xdd, 0x4e, 0x28, 0xe7, 0x41, 0xee, 0x5e, 0xf6, 0x35, + 0xb2, 0xdd, 0x78, 0xa5, 0xfc, 0xe2, 0x8b, 0x96, 0x7f, 0xd7, 0xab, 0xba, 0xd2, 0xa4, 0x79, 0x1a, 0x3b, 0x57, 0x0f, + 0xf5, 0xe9, 0x43, 0x47, 0xa6, 0xfb, 0x23, 0xbe, 0xcc, 0xc8, 0xd0, 0x22, 0x33, 0xdf, 0x55, 0x56, 0x43, 0x5c, 0x6b, + 0x35, 0xf1, 0xee, 0x54, 0xe6, 0xcc, 0x8e, 0xdd, 0x78, 0x91, 0x64, 0x30, 0xaa, 0x8e, 0x4c, 0x0d, 0x89, 0xe4, 0x84, + 0xa8, 0x5f, 0x31, 0x08, 0x98, 0x75, 0x8d, 0x7f, 0xb5, 0xaf, 0x29, 0xb7, 0xe5, 0x5b, 0x8f, 0xb9, 0xfe, 0x36, 0x4e, + 0xb7, 0x5f, 0x13, 0x60, 0xdb, 0x56, 0x5c, 0xea, 0xc5, 0x28, 0xb6, 0x36, 0x32, 0xb1, 0x82, 0x96, 0x27, 0xe0, 0xf0, + 0x80, 0x44, 0xa2, 0xc2, 0xa4, 0xd9, 0x37, 0x92, 0x4a, 0x76, 0xd8, 0xf0, 0xcd, 0x7d, 0xab, 0xb8, 0xa0, 0x8f, 0xf6, + 0x8f, 0x3a, 0x55, 0xd3, 0xcb, 0x42, 0x51, 0x55, 0x1d, 0xf4, 0xa0, 0x29, 0x95, 0xd2, 0xe7, 0x5f, 0xee, 0x4c, 0x12, + 0x10, 0x59, 0x25, 0x81, 0x31, 0x7d, 0x80, 0x62, 0x2a, 0xed, 0x5a, 0x03, 0xa2, 0xc6, 0xbf, 0x21, 0xe1, 0xb7, 0xfa, + 0x31, 0x3d, 0xba, 0x47, 0xdf, 0xfd, 0x5c, 0xda, 0xb5, 0x08, 0x56, 0xe9, 0xad, 0xfe, 0x25, 0x3f, 0xf5, 0x44, 0xd5, + 0xbc, 0x52, 0xbd, 0x33, 0xb4, 0xa7, 0xf9, 0xd3, 0x39, 0x3f, 0x7f, 0x3a, 0xe7, 0x75, 0x30, 0xcc, 0x8c, 0xad, 0x5b, + 0x15, 0xbc, 0x5c, 0xe0, 0xba, 0x84, 0x32, 0x3c, 0xf5, 0xe5, 0x3f, 0x3c, 0x0b, 0x53, 0x19, 0x90, 0x9a, 0x6c, 0x60, + 0x4c, 0x65, 0xe0, 0x74, 0x73, 0x43, 0x47, 0xd3, 0x8d, 0x56, 0x26, 0x9a, 0x19, 0x4f, 0x86, 0x1a, 0x72, 0x1a, 0x73, + 0xb0, 0xa7, 0x87, 0x8c, 0x43, 0xad, 0x66, 0xfc, 0x68, 0xb4, 0x05, 0x6d, 0x40, 0xe1, 0x67, 0x30, 0x53, 0x01, 0x06, + 0xd1, 0xf9, 0x36, 0xce, 0x3e, 0x49, 0x7f, 0x67, 0x99, 0xf3, 0x7c, 0xd9, 0x10, 0xc1, 0xaf, 0x34, 0xe9, 0x76, 0x59, + 0x04, 0xfc, 0x98, 0xd1, 0x58, 0xc6, 0xef, 0xc5, 0xa0, 0x7f, 0x91, 0x3e, 0xaa, 0x11, 0x38, 0x17, 0x20, 0xaf, 0x46, + 0x98, 0x06, 0x8a, 0x86, 0xf6, 0x1a, 0xfa, 0x42, 0xa9, 0x32, 0x7d, 0xed, 0x69, 0x4d, 0x2b, 0xb2, 0xb4, 0xd2, 0x4f, + 0xc6, 0x14, 0xb3, 0x2a, 0x71, 0xec, 0x69, 0xde, 0x37, 0xc8, 0x24, 0x5f, 0x38, 0xcb, 0x68, 0x29, 0xa7, 0xc6, 0x02, + 0xdd, 0x2a, 0xd4, 0xda, 0x85, 0xa7, 0x37, 0x68, 0x1c, 0x18, 0x2a, 0xca, 0xbe, 0x5f, 0x62, 0x8f, 0x78, 0xdf, 0x7e, + 0xc0, 0x47, 0x28, 0xb8, 0xed, 0x39, 0x49, 0x18, 0xa9, 0xfa, 0x5e, 0x51, 0xbc, 0xef, 0x9b, 0x64, 0x24, 0x37, 0x34, + 0x31, 0xd8, 0xa8, 0x85, 0xd3, 0xd3, 0x38, 0x5d, 0x38, 0x3d, 0xc5, 0xa9, 0x45, 0x5b, 0x32, 0xd3, 0xc8, 0x48, 0xac, + 0x5d, 0xe1, 0x44, 0x2d, 0xbf, 0xc9, 0xaf, 0xb2, 0x0d, 0x09, 0x14, 0x95, 0xd6, 0x5e, 0x95, 0x1e, 0xf4, 0x02, 0x36, + 0xe0, 0x4e, 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x2d, 0x40, 0x00, 0x46, 0xf7, 0x3f, 0x58, 0x4d, 0xe9, 0xb4, 0xd1, 0x6e, + 0x4e, 0x39, 0x26, 0x50, 0x72, 0xcd, 0x07, 0x93, 0x90, 0x37, 0x38, 0x71, 0x5e, 0x43, 0xa0, 0x42, 0x1c, 0x43, 0x90, + 0x67, 0xc6, 0x16, 0xf3, 0xfb, 0xb7, 0xaa, 0xfa, 0xa1, 0xa2, 0x53, 0xa8, 0x21, 0x66, 0x5f, 0x68, 0x9e, 0xf0, 0x2b, + 0x72, 0x5e, 0xe6, 0xe4, 0xd2, 0x73, 0x8f, 0xe4, 0xe3, 0xd1, 0xd9, 0x63, 0x24, 0xe8, 0xdb, 0xd5, 0x8e, 0xe6, 0x26, + 0x2c, 0xc5, 0x97, 0xec, 0x67, 0x2a, 0xff, 0x54, 0x2d, 0x14, 0xcf, 0xac, 0xce, 0x3b, 0x65, 0xb1, 0xab, 0x2a, 0x76, + 0x49, 0x67, 0xd0, 0x29, 0x78, 0x33, 0x20, 0x82, 0x8e, 0xe0, 0x24, 0x49, 0x20, 0x11, 0x8d, 0x02, 0xed, 0xd9, 0x4c, + 0x24, 0xc1, 0x5c, 0x80, 0x25, 0xcb, 0x1b, 0x2e, 0x76, 0xed, 0x2f, 0xdd, 0x92, 0xcc, 0x13, 0x70, 0xd1, 0x3c, 0xd3, + 0xe9, 0xe5, 0x3a, 0xf2, 0x39, 0xc2, 0xd4, 0xba, 0xa9, 0xcd, 0xab, 0x84, 0xf3, 0x55, 0xb9, 0x89, 0x95, 0x78, 0x1b, + 0xa8, 0x19, 0xaf, 0x56, 0x2a, 0x7f, 0x62, 0x72, 0x4a, 0x6b, 0x64, 0xa4, 0xb0, 0x3f, 0xa4, 0xaa, 0x6d, 0x94, 0x70, + 0x1b, 0xd2, 0x6f, 0xe7, 0xa7, 0xed, 0x42, 0xf1, 0x5b, 0x3b, 0x18, 0xf2, 0xff, 0xf5, 0x1a, 0xdb, 0x85, 0xa8, 0x51, + 0x60, 0x84, 0x70, 0xb1, 0x08, 0x10, 0x9e, 0x0b, 0xa7, 0x6c, 0x88, 0x85, 0x07, 0x8f, 0xc2, 0xd9, 0xeb, 0xac, 0xab, + 0xde, 0x6f, 0xfe, 0x3e, 0xa8, 0xbf, 0x8f, 0x42, 0xe3, 0x5c, 0xaf, 0xf1, 0x6f, 0x15, 0x3f, 0xfe, 0xd0, 0x42, 0xb1, + 0x81, 0x11, 0x6e, 0x22, 0x68, 0xa5, 0x68, 0xb6, 0x25, 0xd5, 0xfa, 0xaa, 0x80, 0x22, 0x84, 0xdd, 0x49, 0x55, 0x0b, + 0x26, 0xac, 0x3b, 0x3d, 0xc1, 0xf2, 0xf9, 0xc0, 0xe9, 0x3f, 0xa6, 0xed, 0x39, 0x49, 0x54, 0xfa, 0xac, 0x4f, 0x85, + 0x27, 0x4f, 0xa2, 0xd5, 0x3e, 0xf3, 0x2f, 0xc1, 0xad, 0xaf, 0x7e, 0xb5, 0xac, 0x46, 0xca, 0x4c, 0x31, 0x8b, 0xc2, + 0x6b, 0xb7, 0x86, 0x99, 0xf1, 0x8a, 0x62, 0xd2, 0x34, 0x7b, 0x58, 0x0a, 0x8a, 0xbb, 0xba, 0x66, 0x65, 0x4e, 0xe7, + 0x65, 0x46, 0xe6, 0x54, 0x82, 0x71, 0x54, 0x7c, 0x8f, 0x33, 0x7e, 0xa3, 0xad, 0x18, 0x18, 0x75, 0x3c, 0xec, 0xf4, + 0x1c, 0xeb, 0x84, 0x01, 0x7a, 0xe5, 0xb9, 0x89, 0xf0, 0x1a, 0x2f, 0x81, 0x53, 0xa7, 0x36, 0x7d, 0x10, 0x69, 0xe5, + 0xa8, 0x29, 0xcf, 0xb0, 0xc5, 0x94, 0x5e, 0xe3, 0x36, 0x91, 0x76, 0xfb, 0x2f, 0x76, 0x5e, 0x05, 0x9f, 0xd8, 0xd3, + 0x11, 0x1e, 0xd1, 0xa4, 0xb4, 0x08, 0x5e, 0x24, 0xca, 0xc3, 0xf6, 0xc0, 0x73, 0x7e, 0x25, 0xd6, 0x5e, 0x4e, 0x94, + 0xf2, 0x7c, 0xe6, 0x39, 0x88, 0x21, 0x33, 0xb4, 0x84, 0x8e, 0xcf, 0x05, 0x47, 0x62, 0x5c, 0xbd, 0x4f, 0x90, 0xc4, + 0x49, 0xb0, 0xf7, 0xd7, 0x3e, 0x17, 0x69, 0x75, 0xfc, 0xf2, 0x3e, 0x61, 0x21, 0xb6, 0x6b, 0xda, 0x05, 0x2a, 0x64, + 0x3f, 0xf8, 0x53, 0x02, 0x5e, 0x13, 0xf2, 0xb2, 0xef, 0xd4, 0x6e, 0x9d, 0x75, 0xce, 0xff, 0x0b, 0x87, 0x43, 0x8f, + 0x5e, 0x39, 0x9a, 0x6b, 0x26, 0x60, 0x72, 0xc0, 0x51, 0xd5, 0xf7, 0xa2, 0xc4, 0xd1, 0xf0, 0x40, 0xa0, 0xac, 0x12, + 0xff, 0xb0, 0x7e, 0x30, 0x24, 0xa0, 0xf2, 0x88, 0xfb, 0xee, 0xd6, 0xee, 0x9a, 0x76, 0x65, 0x13, 0x2e, 0x57, 0x32, + 0xfe, 0x1b, 0x10, 0xa6, 0xef, 0x03, 0xce, 0xe1, 0xe8, 0xac, 0xfb, 0x02, 0x6e, 0x32, 0xe7, 0x14, 0xa3, 0xb8, 0x96, + 0x7c, 0xc1, 0xf6, 0x94, 0x90, 0xd7, 0xc4, 0x2e, 0xbf, 0x58, 0x47, 0xa1, 0x57, 0x9d, 0xd4, 0xcb, 0xb2, 0xe8, 0xbf, + 0x80, 0x75, 0x82, 0x78, 0x79, 0x9e, 0xe9, 0xb2, 0x6f, 0x12, 0x87, 0x2b, 0xac, 0xb0, 0x99, 0x95, 0x86, 0x66, 0x61, + 0xfa, 0x98, 0xd2, 0x75, 0x2c, 0x30, 0x0e, 0x55, 0xce, 0x76, 0x09, 0x6c, 0x49, 0xaa, 0x99, 0xc6, 0xfb, 0x0d, 0x59, + 0x85, 0x49, 0x4b, 0x2b, 0x8d, 0x17, 0xe8, 0x1e, 0x6b, 0x3c, 0xff, 0x4b, 0x30, 0x4c, 0x18, 0x67, 0x2f, 0xc3, 0xc4, + 0x4f, 0x2a, 0xb8, 0xaa, 0x79, 0x82, 0xc3, 0xe6, 0x9d, 0xf9, 0xab, 0xb6, 0x75, 0xc0, 0x4f, 0xb2, 0x2f, 0x1a, 0xc3, + 0x98, 0x2c, 0x2c, 0x06, 0xee, 0xd2, 0xd8, 0xcf, 0xc1, 0xc2, 0x0d, 0xfb, 0xe8, 0x1b, 0x05, 0x5f, 0xfa, 0xf7, 0x77, + 0xa0, 0x4e, 0x62, 0xd4, 0x75, 0x69, 0x25, 0xa5, 0xbf, 0x46, 0xbe, 0x68, 0x03, 0x88, 0x34, 0x4f, 0x7d, 0x8c, 0x85, + 0x53, 0x41, 0xc4, 0x92, 0x12, 0x61, 0xed, 0x8c, 0x30, 0x6b, 0x65, 0xf9, 0xfe, 0x6c, 0xea, 0x08, 0x05, 0x5d, 0x3b, + 0xcb, 0x9f, 0x73, 0xe9, 0x66, 0x11, 0x5d, 0x37, 0xc0, 0x58, 0x96, 0x1d, 0x51, 0x0e, 0x9e, 0x60, 0xdb, 0xea, 0xae, + 0x88, 0xbc, 0xa1, 0x3e, 0x49, 0xac, 0x4e, 0xe8, 0x23, 0x8e, 0xd6, 0xf9, 0x68, 0x13, 0x4d, 0xbe, 0x59, 0xe5, 0xf2, + 0xd3, 0x26, 0xe6, 0x34, 0xd4, 0xc5, 0x0c, 0x62, 0x38, 0xf8, 0x4e, 0x84, 0xce, 0xa6, 0x7d, 0xdc, 0xa0, 0xcd, 0xc2, + 0x19, 0x9a, 0x86, 0xeb, 0x10, 0x6f, 0x2a, 0x61, 0x51, 0xd9, 0x42, 0xd3, 0x29, 0x9d, 0x70, 0x75, 0x57, 0x98, 0x9b, + 0x73, 0xee, 0xa9, 0xe5, 0x1a, 0xba, 0x26, 0x02, 0x85, 0xe2, 0xb1, 0xe5, 0x1a, 0x7d, 0x75, 0x50, 0xa9, 0x42, 0xa7, + 0xdb, 0x79, 0xf6, 0x2a, 0x16, 0x1c, 0xae, 0x8c, 0xc5, 0x1c, 0x60, 0xe0, 0xa7, 0x71, 0xf2, 0xbe, 0x8a, 0xec, 0x54, + 0x5a, 0x72, 0xde, 0xa5, 0xe4, 0xc0, 0x25, 0xf5, 0xcf, 0x6d, 0x5e, 0x9d, 0x2f, 0x73, 0x9b, 0x29, 0x78, 0x0b, 0x6e, + 0xe9, 0xb4, 0x1e, 0x87, 0xa2, 0xed, 0x10, 0x53, 0xe5, 0x5e, 0x29, 0x25, 0xcf, 0x9a, 0x6a, 0x28, 0x59, 0xe7, 0x18, + 0xeb, 0x8f, 0x0e, 0x51, 0x3e, 0xc4, 0x34, 0xe2, 0x70, 0xa7, 0x62, 0x55, 0xf2, 0x64, 0x25, 0x48, 0x88, 0xd5, 0x36, + 0xcc, 0x0c, 0x5a, 0x59, 0x26, 0xaa, 0x7d, 0x77, 0x9e, 0x47, 0x89, 0x31, 0xbe, 0x32, 0xcb, 0xc2, 0xd7, 0xe5, 0x0e, + 0x74, 0x82, 0x34, 0xb7, 0x9b, 0xc0, 0xb2, 0x5e, 0xa3, 0x11, 0xe6, 0xd3, 0x38, 0x4a, 0x48, 0x40, 0x24, 0xd5, 0x2f, + 0x48, 0x97, 0x12, 0xee, 0x7a, 0xf4, 0x67, 0xf9, 0x20, 0x84, 0xf9, 0xf0, 0xe5, 0x84, 0x53, 0x97, 0x60, 0x3b, 0xde, + 0xe4, 0xb5, 0x02, 0x95, 0x44, 0xd3, 0x6b, 0x2b, 0x4e, 0x75, 0xa9, 0x7a, 0x5b, 0x8c, 0xe2, 0x34, 0xfd, 0xaa, 0x27, + 0xb9, 0xd9, 0x62, 0x61, 0x2c, 0x18, 0x04, 0x1a, 0x50, 0xd1, 0x4d, 0x00, 0xab, 0x31, 0x16, 0x11, 0xaf, 0xcb, 0x0f, + 0x99, 0x54, 0x53, 0x3a, 0x54, 0xed, 0xda, 0xef, 0x0f, 0xee, 0xdd, 0xf0, 0x70, 0xfc, 0xf8, 0x9f, 0xfb, 0xbd, 0x1e, + 0x54, 0x41, 0x97, 0xf0, 0x71, 0x67, 0x3b, 0xa6, 0x42, 0x01, 0xb2, 0xb2, 0x7d, 0x79, 0x01, 0x50, 0x63, 0x2a, 0x4e, + 0xba, 0x6b, 0xeb, 0xde, 0xb4, 0xe0, 0xd3, 0xba, 0x09, 0xdf, 0xfb, 0xe6, 0x7c, 0x6f, 0x98, 0x5a, 0x77, 0xf8, 0xdc, + 0xe5, 0x33, 0x9e, 0x02, 0x99, 0x0b, 0x83, 0xf7, 0x90, 0xe2, 0x26, 0x4c, 0x32, 0xe4, 0x6c, 0x9a, 0x77, 0xda, 0xb2, + 0xbc, 0xd6, 0x52, 0xb2, 0x23, 0x26, 0xec, 0xb9, 0xf2, 0x47, 0xde, 0x93, 0xf8, 0x48, 0x35, 0x04, 0xe0, 0x04, 0xa5, + 0x8d, 0xc0, 0x5c, 0xc5, 0xcd, 0xfc, 0xa9, 0x21, 0x88, 0x08, 0xf4, 0x4c, 0xe1, 0xde, 0xce, 0x1f, 0xce, 0xc6, 0x08, + 0x41, 0x2a, 0xf8, 0x66, 0xa5, 0x36, 0x6b, 0x78, 0xe9, 0x3f, 0x66, 0x67, 0x3b, 0x32, 0xd3, 0xdd, 0x26, 0x51, 0x5b, + 0xb6, 0xa6, 0x02, 0xcc, 0x20, 0x1a, 0x03, 0x17, 0x3c, 0x30, 0xa6, 0xf1, 0xd1, 0x9b, 0x71, 0x62, 0xad, 0xdd, 0xf2, + 0xe5, 0x8c, 0x8f, 0x1c, 0x7d, 0x4e, 0x16, 0xa8, 0x71, 0x77, 0x18, 0xcb, 0xcb, 0xf8, 0x6e, 0x3d, 0x6e, 0x56, 0xf7, + 0x20, 0x0b, 0x08, 0xd0, 0x6b, 0xb1, 0xae, 0x99, 0xe8, 0x55, 0xc2, 0x9d, 0x54, 0x9a, 0x27, 0x95, 0x98, 0x59, 0xe5, + 0xe5, 0xb5, 0xd3, 0xcb, 0x90, 0xbc, 0x0c, 0xd6, 0x6e, 0x54, 0xa1, 0xc7, 0xd6, 0x58, 0xe3, 0xb8, 0x66, 0x92, 0xa5, + 0xf1, 0xd7, 0xf0, 0x51, 0x3f, 0xbc, 0x5c, 0x45, 0xeb, 0xa6, 0x5a, 0xb4, 0x5e, 0x5b, 0x39, 0xcc, 0x97, 0xbc, 0xf8, + 0x85, 0x2d, 0xb6, 0xf0, 0x7a, 0xb1, 0xb9, 0x8f, 0xa8, 0x4c, 0x25, 0xaa, 0xd3, 0x4a, 0x54, 0xa6, 0x89, 0xc9, 0xcf, + 0x9e, 0x77, 0x01, 0x5c, 0x7f, 0xd4, 0xa9, 0x55, 0xfc, 0xa8, 0x32, 0xaa, 0xfc, 0x51, 0x23, 0x54, 0xeb, 0x13, 0x40, + 0x94, 0xc0, 0xac, 0x91, 0x87, 0x99, 0xb5, 0x61, 0x32, 0x29, 0xeb, 0x0b, 0x72, 0x85, 0xc3, 0xb4, 0xaa, 0x56, 0xbd, + 0xff, 0xe5, 0x86, 0xeb, 0x2f, 0x9b, 0xfc, 0x6e, 0xc6, 0xf5, 0xbe, 0x92, 0xfd, 0x60, 0x39, 0x18, 0x2c, 0xb4, 0xf1, + 0xe3, 0x16, 0xea, 0x7e, 0x8c, 0x1e, 0x86, 0xe0, 0xca, 0xf4, 0x35, 0x88, 0xfa, 0x95, 0x20, 0xf3, 0x23, 0xf2, 0x5a, + 0x01, 0x72, 0xb1, 0xd7, 0x37, 0xd2, 0xbb, 0xd6, 0x20, 0x1a, 0x1b, 0x12, 0xa9, 0xb3, 0x48, 0x86, 0x21, 0xb5, 0x7d, + 0xb8, 0xce, 0xe8, 0x68, 0xde, 0xe4, 0x2d, 0xbe, 0xa9, 0x86, 0x26, 0xcc, 0xb7, 0x0a, 0xab, 0x91, 0x9e, 0x93, 0xa6, + 0x29, 0x69, 0x56, 0xf6, 0x4d, 0xd0, 0xaf, 0x5e, 0x44, 0x26, 0x34, 0x06, 0x5f, 0x64, 0x70, 0xe0, 0xb7, 0x2b, 0x3a, + 0x0a, 0xd1, 0x4f, 0x79, 0x73, 0xff, 0x55, 0x30, 0x4a, 0xfd, 0x00, 0xb1, 0x6f, 0xd1, 0x05, 0x66, 0x67, 0x05, 0x7c, + 0x0b, 0xeb, 0xed, 0x05, 0x79, 0x94, 0xc6, 0xce, 0xc2, 0x11, 0x35, 0x61, 0xad, 0xf7, 0xb0, 0x31, 0xb2, 0xde, 0xf9, + 0xe7, 0xba, 0x2b, 0x51, 0x84, 0x4b, 0xcf, 0x65, 0x82, 0xea, 0xc0, 0x45, 0xe5, 0x5b, 0x6a, 0x2f, 0xa5, 0x09, 0xa7, + 0x22, 0x5f, 0x0c, 0x1b, 0xde, 0x87, 0xc3, 0xbe, 0x86, 0xc3, 0x0f, 0x7c, 0xd3, 0x5a, 0x6b, 0x26, 0x5b, 0x35, 0xb2, + 0x0b, 0x2e, 0xb8, 0xc0, 0xb0, 0x83, 0x81, 0xf5, 0xec, 0x7d, 0x1e, 0x82, 0xa6, 0x03, 0x61, 0xc1, 0x58, 0x34, 0xb7, + 0x01, 0x4f, 0x3e, 0x60, 0xa0, 0xd4, 0xcd, 0xdb, 0x6d, 0xd9, 0x22, 0xb9, 0x0d, 0x0c, 0xa9, 0xc5, 0x38, 0xcb, 0xe2, + 0xc0, 0x99, 0x3a, 0x9b, 0xe7, 0xfa, 0x46, 0x19, 0x77, 0xad, 0x44, 0x49, 0x1b, 0xbf, 0x9e, 0x0d, 0xee, 0x19, 0x29, + 0x74, 0x93, 0xff, 0x2f, 0x21, 0xe5, 0x5d, 0xae, 0x0a, 0x82, 0x6e, 0x70, 0xd2, 0xd7, 0x5a, 0xba, 0xc8, 0x4c, 0x44, + 0x77, 0x80, 0x2b, 0x68, 0x52, 0xae, 0x3d, 0x41, 0xd2, 0x67, 0x2b, 0xb7, 0x39, 0x11, 0xdb, 0x3d, 0x23, 0x9d, 0xd9, + 0x12, 0xea, 0xf3, 0x0b, 0x56, 0x97, 0x77, 0xee, 0x28, 0xe5, 0x73, 0x65, 0xcc, 0x78, 0x24, 0xcd, 0xb3, 0x3f, 0x4a, + 0x21, 0x4d, 0xc6, 0xf5, 0x22, 0x32, 0x9f, 0x97, 0xdb, 0x5b, 0x81, 0x07, 0x9e, 0xaa, 0xc0, 0x10, 0xb4, 0xde, 0x4b, + 0x7c, 0xf3, 0x55, 0x0d, 0xca, 0x3a, 0x19, 0x3f, 0x3e, 0x56, 0xbf, 0x35, 0xf6, 0xa2, 0xd2, 0xe4, 0x10, 0xcd, 0xd4, + 0x76, 0x5a, 0xe7, 0x2d, 0xa8, 0x65, 0x6a, 0xd7, 0x09, 0xa4, 0xd1, 0x39, 0xcf, 0x56, 0x91, 0x98, 0x6a, 0xfe, 0x6b, + 0xa6, 0x84, 0xbe, 0xaf, 0x50, 0x25, 0xfe, 0x19, 0x17, 0x89, 0x30, 0xe2, 0x3c, 0x50, 0x0f, 0x61, 0xd5, 0x12, 0x87, + 0xca, 0xbb, 0x31, 0x8c, 0x0b, 0x66, 0xe1, 0x10, 0x1b, 0x65, 0x7e, 0x16, 0x93, 0x4f, 0x97, 0x05, 0x4f, 0xce, 0xaf, + 0x64, 0x99, 0x75, 0xb3, 0x4f, 0x88, 0x87, 0x47, 0xed, 0x21, 0xd5, 0x2d, 0x0b, 0xad, 0x59, 0x59, 0x2f, 0xca, 0x6e, + 0xd4, 0x3e, 0x8b, 0x2f, 0xc8, 0x68, 0xd2, 0x1e, 0x78, 0xdc, 0x4b, 0x12, 0x48, 0x55, 0x2d, 0xdb, 0xcc, 0x21, 0xf2, + 0xf0, 0xf2, 0x21, 0x4f, 0xf9, 0xac, 0x4c, 0x54, 0x94, 0xb6, 0xc3, 0xe0, 0x81, 0xfb, 0x3a, 0x9a, 0xa0, 0x53, 0xac, + 0xd3, 0x15, 0x44, 0x6f, 0xc0, 0xac, 0x37, 0x8a, 0x3d, 0xab, 0xac, 0x4a, 0x36, 0xed, 0xe5, 0x1a, 0xbf, 0x71, 0x90, + 0x16, 0xdc, 0xd8, 0xe3, 0x48, 0x5d, 0x2f, 0x4a, 0xd7, 0xf5, 0x66, 0x6f, 0xb9, 0xd3, 0xea, 0x03, 0x3e, 0xfd, 0x94, + 0x6c, 0xc9, 0x5f, 0x2f, 0x5d, 0x93, 0x56, 0x6e, 0x0b, 0x1a, 0x35, 0xd6, 0x64, 0xbc, 0xe9, 0x4b, 0x10, 0x15, 0x55, + 0x09, 0x9e, 0x53, 0x7e, 0x36, 0x8c, 0x46, 0x32, 0xd1, 0x80, 0x7c, 0x69, 0xed, 0x7e, 0xae, 0x55, 0xbc, 0xb5, 0x3a, + 0x74, 0xca, 0xea, 0xe0, 0xf8, 0xd2, 0xb9, 0xd9, 0xba, 0x28, 0x14, 0x20, 0x01, 0xf6, 0x50, 0x43, 0x8e, 0x9d, 0xd5, + 0x8c, 0xdb, 0xdb, 0x6f, 0x1b, 0x31, 0x90, 0x62, 0x2e, 0xfb, 0xae, 0x1f, 0x22, 0x64, 0x32, 0x23, 0x4c, 0xac, 0x91, + 0xdd, 0x18, 0xa3, 0x09, 0x09, 0xc9, 0x78, 0x2d, 0x84, 0x84, 0xde, 0xea, 0x3c, 0x01, 0x5c, 0x12, 0x4f, 0x06, 0x6b, + 0x0a, 0x66, 0x45, 0x5e, 0x57, 0x5b, 0x71, 0x25, 0x16, 0x89, 0xf0, 0x75, 0x51, 0x23, 0xdb, 0x26, 0x58, 0x41, 0x8b, + 0x62, 0x0e, 0x14, 0x3a, 0xf3, 0x0d, 0x5f, 0x30, 0xe1, 0x9c, 0xdf, 0x75, 0x6b, 0x94, 0x96, 0x99, 0xa0, 0xaf, 0x1a, + 0x16, 0xb6, 0xdb, 0x2f, 0x10, 0xd7, 0x34, 0x03, 0x03, 0x8a, 0xb2, 0x43, 0x35, 0xbf, 0x03, 0x4b, 0x94, 0x9c, 0xb4, + 0x91, 0x9b, 0x5f, 0xa1, 0x63, 0x82, 0x18, 0x58, 0x68, 0x6c, 0x2f, 0x64, 0x2b, 0xd1, 0x9a, 0x1a, 0xb2, 0x11, 0x36, + 0xc1, 0x07, 0xa7, 0xa7, 0x70, 0x6d, 0x02, 0x55, 0xd3, 0x94, 0x46, 0x60, 0x9e, 0xf0, 0x40, 0x69, 0xbe, 0x9f, 0x5d, + 0x10, 0xd8, 0x98, 0xb7, 0x22, 0x8b, 0x03, 0x92, 0x12, 0x1b, 0x58, 0x78, 0xd4, 0x58, 0x2f, 0xef, 0x34, 0x8e, 0x2e, + 0xab, 0x51, 0x57, 0xa4, 0x58, 0x2a, 0x69, 0xc6, 0xa2, 0xc1, 0x98, 0x92, 0x90, 0x64, 0x2d, 0x04, 0x6b, 0x36, 0xfc, + 0xcd, 0x7b, 0x54, 0x7f, 0x6b, 0x2e, 0x60, 0x4f, 0x30, 0xdb, 0x79, 0x31, 0xbd, 0xbe, 0x1a, 0x65, 0xdb, 0xba, 0x85, + 0x79, 0x4f, 0x61, 0xd0, 0x9c, 0x8f, 0x29, 0x65, 0xce, 0x33, 0x40, 0x99, 0x49, 0x16, 0x01, 0x39, 0x0c, 0xb8, 0x07, + 0xa4, 0x2b, 0x2f, 0x0e, 0x7b, 0x19, 0xad, 0x9c, 0xb9, 0xf0, 0xf2, 0x72, 0x75, 0x34, 0x41, 0x39, 0x50, 0xe4, 0xc0, + 0x8b, 0xeb, 0x17, 0x4f, 0x73, 0x2d, 0x56, 0x59, 0x6f, 0x58, 0xa8, 0xae, 0xb7, 0xf4, 0xb9, 0xf5, 0x31, 0xf0, 0xf9, + 0xb5, 0x96, 0x5a, 0x34, 0x7f, 0xe8, 0xb5, 0xd5, 0xa4, 0xa0, 0xdd, 0xbf, 0xf5, 0x64, 0x14, 0x39, 0xa5, 0xd5, 0xb2, + 0xf8, 0x54, 0xbb, 0xe8, 0x29, 0x5a, 0xca, 0x26, 0xef, 0xb2, 0x87, 0xaa, 0x0b, 0xb3, 0xd6, 0x51, 0x98, 0xd5, 0xf6, + 0x28, 0xef, 0xec, 0xbd, 0x36, 0x0b, 0xca, 0x94, 0x56, 0x9f, 0x70, 0xbd, 0xf1, 0x02, 0xaa, 0xf9, 0x96, 0x1a, 0x8b, + 0x63, 0x7e, 0x49, 0x5d, 0xd9, 0x28, 0x7b, 0x9e, 0xd6, 0xb8, 0xbc, 0xeb, 0xa2, 0x17, 0x53, 0xc0, 0x29, 0xca, 0x4a, + 0x17, 0x37, 0x72, 0x09, 0x5d, 0x2b, 0xd2, 0x1a, 0xf8, 0x0c, 0x8c, 0x62, 0xb2, 0x9a, 0x7c, 0x90, 0xf4, 0xdf, 0x99, + 0xf5, 0x57, 0x9d, 0xb9, 0xfe, 0xa6, 0x17, 0xae, 0xbf, 0x5e, 0x54, 0x56, 0x85, 0x7d, 0x63, 0xec, 0x19, 0x70, 0x05, + 0x93, 0x4a, 0x7c, 0xa5, 0x73, 0x8e, 0x08, 0x6a, 0x0c, 0x15, 0xb2, 0x9b, 0x2f, 0x2c, 0x6c, 0x88, 0x3c, 0x3b, 0xbb, + 0xcc, 0xd2, 0x35, 0xd6, 0x98, 0xdc, 0xdf, 0xbb, 0x82, 0x59, 0x17, 0x56, 0x2d, 0xe3, 0x55, 0xce, 0xa5, 0x28, 0x92, + 0x62, 0x72, 0x91, 0x83, 0x14, 0x21, 0x80, 0x90, 0x8b, 0x24, 0xd0, 0x51, 0xda, 0xa2, 0x68, 0x24, 0x14, 0x80, 0xfa, + 0x72, 0xbe, 0x05, 0x08, 0x1c, 0x82, 0x39, 0x21, 0x08, 0x46, 0xf2, 0x2c, 0x20, 0x72, 0x42, 0xf6, 0x4e, 0x54, 0x88, + 0x30, 0xab, 0x83, 0x13, 0x68, 0x50, 0x16, 0xd8, 0xa2, 0x79, 0x99, 0x09, 0x8a, 0x2a, 0x44, 0x84, 0x65, 0xc5, 0xe5, + 0xea, 0x8f, 0x2e, 0x6d, 0xbd, 0x5c, 0x53, 0xe8, 0x92, 0xe5, 0xd3, 0xec, 0x1a, 0xca, 0xfc, 0x00, 0xfc, 0x6b, 0x51, + 0x07, 0xf6, 0xb4, 0x83, 0x34, 0xb0, 0x15, 0x17, 0xa7, 0xe2, 0xfa, 0xe7, 0x9c, 0x02, 0x42, 0x49, 0x4f, 0x2b, 0xc4, + 0x5c, 0xa0, 0x73, 0x0f, 0x71, 0x0d, 0x0a, 0x80, 0xe1, 0x92, 0xf1, 0xc2, 0x50, 0xdb, 0x7a, 0x7a, 0xea, 0xfc, 0x1e, + 0xc9, 0x35, 0x3a, 0x34, 0xf1, 0x22, 0xca, 0xdc, 0x65, 0x61, 0x3b, 0x52, 0xbc, 0xe7, 0x46, 0xb5, 0xc7, 0x94, 0x97, + 0xe7, 0x7b, 0xe8, 0x2f, 0xc4, 0xbc, 0x6d, 0x82, 0xaa, 0xa7, 0x7b, 0x6f, 0xad, 0x8b, 0xc0, 0x8f, 0x5e, 0x16, 0x05, + 0xea, 0xdb, 0x15, 0x23, 0x0d, 0x3d, 0xd9, 0xb1, 0x42, 0x97, 0x69, 0x59, 0xdb, 0xbb, 0xcd, 0xfa, 0xb6, 0x06, 0x83, + 0x8c, 0x7d, 0xa5, 0x78, 0x05, 0x84, 0x4d, 0xf1, 0x64, 0x26, 0xda, 0x6a, 0x08, 0x4e, 0x10, 0xca, 0xe9, 0xea, 0xf0, + 0xad, 0x20, 0x45, 0x45, 0x60, 0xeb, 0x7e, 0xac, 0x3d, 0xd4, 0xbe, 0x1b, 0x4a, 0xa7, 0x67, 0x8f, 0x1a, 0x1c, 0x3d, + 0xe5, 0x05, 0x3b, 0x34, 0x52, 0x97, 0x16, 0x21, 0x55, 0xf1, 0xb6, 0x01, 0xab, 0xf4, 0xe0, 0xd3, 0x06, 0x33, 0x9f, + 0xb1, 0xe2, 0x0e, 0x72, 0x15, 0x1b, 0xd1, 0x08, 0x05, 0xdd, 0x23, 0xf2, 0xf3, 0xfe, 0x82, 0x3d, 0x37, 0xe6, 0x56, + 0xf0, 0x4b, 0xc0, 0x30, 0xd5, 0x2b, 0x4c, 0x58, 0x2d, 0x8d, 0x16, 0x60, 0xe9, 0x8d, 0x67, 0xab, 0x66, 0xaf, 0x7c, + 0x2a, 0x95, 0x14, 0xab, 0x10, 0xbe, 0x53, 0x65, 0x05, 0x27, 0x1f, 0x62, 0x30, 0xc4, 0x4f, 0xdf, 0x56, 0x7e, 0xbd, + 0xea, 0xe6, 0x50, 0xf1, 0xa8, 0xb1, 0xa7, 0x3d, 0x8c, 0x92, 0xda, 0xf0, 0xaa, 0xc3, 0x10, 0x77, 0x67, 0xd9, 0x99, + 0x3d, 0x45, 0xd6, 0x54, 0x02, 0xf8, 0x15, 0x9b, 0xa2, 0x2e, 0x83, 0x8f, 0x88, 0x79, 0x23, 0x60, 0xfe, 0x66, 0x50, + 0x8c, 0xe6, 0x4d, 0x15, 0xad, 0x16, 0xf7, 0x26, 0x74, 0xc9, 0xb8, 0x44, 0xd9, 0xd3, 0x87, 0xf4, 0x3b, 0x24, 0x18, + 0x39, 0xdd, 0xac, 0xb8, 0xaf, 0x07, 0x87, 0x63, 0x1f, 0x5b, 0x97, 0x30, 0x05, 0x40, 0x8b, 0x5c, 0x4c, 0x80, 0xe9, + 0x7a, 0xcd, 0xb1, 0x90, 0xad, 0x0b, 0x49, 0x34, 0x34, 0x85, 0xa2, 0x6e, 0x41, 0x30, 0x31, 0x2a, 0xed, 0xf6, 0x83, + 0xb4, 0x30, 0x9e, 0x33, 0x95, 0x5f, 0x90, 0x1f, 0x4e, 0x7d, 0xd9, 0x1a, 0x7b, 0xa3, 0x63, 0x56, 0x34, 0xf1, 0xa4, + 0x99, 0x80, 0x48, 0x00, 0x2f, 0x17, 0xd1, 0x66, 0x9c, 0xa7, 0x92, 0x9a, 0xd7, 0x76, 0x81, 0x98, 0x01, 0x02, 0x9d, + 0x6a, 0x49, 0xa5, 0x78, 0x73, 0x3e, 0x48, 0x71, 0x10, 0x80, 0xb2, 0x63, 0x36, 0xb4, 0xa5, 0xa0, 0x1e, 0x32, 0xb4, + 0xd9, 0x5c, 0xdb, 0x5a, 0xee, 0xd4, 0xd9, 0xac, 0x45, 0x6d, 0x99, 0x3f, 0xdc, 0xe6, 0x17, 0x11, 0xe3, 0xa2, 0xee, + 0x13, 0x09, 0xd5, 0x14, 0x23, 0xd0, 0x79, 0x02, 0xf2, 0x7a, 0x38, 0xe1, 0xcd, 0x7d, 0xbf, 0x6f, 0xe9, 0x9a, 0x64, + 0xf1, 0xa2, 0xc0, 0xb9, 0x2f, 0x53, 0x78, 0x99, 0x70, 0x02, 0x97, 0x78, 0xa8, 0x33, 0x1f, 0x67, 0x5b, 0x9d, 0x29, + 0x46, 0xa0, 0xa4, 0x16, 0x91, 0x4d, 0x7a, 0x43, 0x90, 0x9a, 0xf1, 0x32, 0x10, 0x6a, 0x47, 0xa9, 0x01, 0xc9, 0xfb, + 0xba, 0x32, 0x5e, 0x4b, 0xb6, 0x2e, 0x42, 0xd9, 0x6c, 0xc7, 0xb5, 0xbb, 0x9c, 0x4e, 0x77, 0x37, 0x2b, 0xe4, 0x0e, + 0x28, 0x9d, 0x0d, 0x97, 0x11, 0xdf, 0xd0, 0xec, 0x40, 0x81, 0xd0, 0x6e, 0xdf, 0x66, 0x65, 0xcc, 0xc2, 0xe2, 0x75, + 0x43, 0x8e, 0x4a, 0xfe, 0x50, 0xde, 0x9d, 0xf5, 0x6e, 0xc3, 0x53, 0xdb, 0xc1, 0x7a, 0x50, 0x28, 0xfb, 0xd8, 0xa7, + 0x46, 0xe1, 0x0f, 0xdc, 0x2a, 0x91, 0x75, 0x08, 0xeb, 0xec, 0xc2, 0x3b, 0x2a, 0xd3, 0x31, 0x6d, 0x3b, 0x9b, 0x87, + 0xcd, 0x46, 0x41, 0xba, 0x2c, 0xe1, 0x78, 0x6d, 0xa5, 0xee, 0xd4, 0xc3, 0x73, 0x37, 0x4a, 0xdf, 0x97, 0x58, 0x5e, + 0xb6, 0x51, 0xf7, 0x76, 0x12, 0x4b, 0xf8, 0xcc, 0x3a, 0x71, 0x09, 0xee, 0x80, 0xb9, 0xca, 0x4e, 0x44, 0x2d, 0x90, + 0xd4, 0x7f, 0xe1, 0xe5, 0x8f, 0x06, 0xe3, 0x92, 0x93, 0xab, 0x5e, 0x4d, 0x20, 0x31, 0x13, 0x32, 0x47, 0xab, 0x77, + 0x03, 0x9a, 0x82, 0xae, 0x6b, 0x91, 0x03, 0x02, 0x4f, 0x6c, 0x7a, 0xf9, 0xed, 0x08, 0xe2, 0xec, 0x2e, 0x27, 0x34, + 0xac, 0xe1, 0x59, 0x76, 0xb1, 0x92, 0xb1, 0x6b, 0x8f, 0xa7, 0xc7, 0x2e, 0x95, 0x96, 0x4d, 0x18, 0xf3, 0xdb, 0xba, + 0xde, 0x28, 0x9e, 0x22, 0xa6, 0x5d, 0x9c, 0xca, 0x18, 0xae, 0x56, 0x9f, 0xe3, 0x79, 0x51, 0x05, 0x49, 0x5c, 0x12, + 0xa5, 0x37, 0xd6, 0x6f, 0xb9, 0x1c, 0x55, 0x15, 0xcb, 0xd9, 0xf9, 0x6d, 0xca, 0xab, 0xdf, 0x83, 0x7f, 0x7c, 0x95, + 0xb1, 0x08, 0xaa, 0x8c, 0xc8, 0x8c, 0x7d, 0x74, 0x11, 0x2d, 0xf4, 0xb3, 0xb6, 0x74, 0x15, 0x5d, 0xaf, 0xcc, 0x6b, + 0x88, 0x20, 0x70, 0xab, 0xea, 0x14, 0x52, 0x66, 0xd1, 0x98, 0x67, 0x15, 0xb3, 0x6b, 0x3d, 0xc6, 0x31, 0x67, 0x03, + 0xe1, 0x26, 0x93, 0x13, 0x24, 0x27, 0xe1, 0x33, 0x95, 0xd9, 0x96, 0x11, 0xf5, 0xc8, 0x6b, 0xa4, 0x8b, 0x9a, 0x35, + 0xe7, 0x6d, 0xd7, 0x59, 0xbc, 0x60, 0x71, 0xde, 0xaf, 0x6e, 0x44, 0x42, 0x80, 0x70, 0x11, 0xfe, 0x1c, 0xc0, 0xff, + 0x6d, 0x33, 0xc5, 0xfd, 0xdd, 0xfc, 0x92, 0x77, 0x4d, 0x1b, 0x07, 0xe0, 0x80, 0x82, 0xc5, 0xc9, 0xe0, 0x02, 0xc9, + 0x08, 0x43, 0xbd, 0x42, 0xb4, 0xc1, 0x52, 0x31, 0xce, 0x2d, 0x3d, 0x8f, 0xec, 0x68, 0xd0, 0xa7, 0xe5, 0xc4, 0x5c, + 0x79, 0x83, 0x31, 0x5b, 0xa3, 0x12, 0x42, 0xed, 0x08, 0x31, 0x85, 0xc9, 0x74, 0x56, 0x16, 0x25, 0x7f, 0x15, 0x26, + 0xb4, 0x82, 0x49, 0x4a, 0x9b, 0x51, 0x63, 0x88, 0x8d, 0x8a, 0x50, 0xbd, 0xe7, 0x94, 0x35, 0x04, 0x73, 0x7b, 0x42, + 0xfa, 0x35, 0x44, 0xd7, 0x3f, 0xd6, 0xcf, 0x13, 0x4e, 0x6a, 0xdb, 0xf9, 0xba, 0xd0, 0x82, 0x83, 0x6b, 0x2a, 0xaa, + 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0xd4, 0x91, 0x3a, 0xd4, 0x12, 0x59, 0x9b, 0x55, 0x3a, 0xd9, 0x61, 0xb4, 0x9c, + 0x4c, 0x89, 0x2b, 0x48, 0x6b, 0x5d, 0x39, 0x57, 0xbe, 0xd1, 0x97, 0x6d, 0xd0, 0x1b, 0x8d, 0x44, 0x2e, 0x3b, 0x8f, + 0x3f, 0xdf, 0xfa, 0x1c, 0xa0, 0xd6, 0xff, 0x6a, 0xed, 0x72, 0xc9, 0x02, 0x76, 0xb1, 0xab, 0x23, 0xf1, 0x7e, 0xde, + 0x0a, 0xb8, 0xbe, 0x10, 0x08, 0x75, 0xdd, 0x85, 0x72, 0xd2, 0x15, 0xab, 0xa2, 0x5f, 0xbe, 0x47, 0xd1, 0xac, 0xb7, + 0x11, 0x94, 0x4d, 0x90, 0xd6, 0xbb, 0x3a, 0x0e, 0x29, 0x21, 0x51, 0x59, 0x4c, 0x75, 0x61, 0x8d, 0x1e, 0xe8, 0x0e, + 0x5b, 0x45, 0x34, 0xa7, 0xe9, 0x26, 0xfb, 0xfe, 0x50, 0xa1, 0x04, 0x22, 0xfc, 0xbf, 0x7b, 0xd3, 0x33, 0xd0, 0x20, + 0x49, 0x5d, 0x80, 0x4a, 0x49, 0xfb, 0x85, 0xd3, 0xfe, 0x50, 0x65, 0x0b, 0x80, 0xc2, 0x1e, 0x6f, 0x14, 0x6d, 0xcb, + 0xef, 0x66, 0x3d, 0x28, 0xd1, 0xfa, 0x3f, 0x2a, 0x43, 0x16, 0x10, 0x6d, 0x47, 0xd7, 0x6a, 0xe9, 0x95, 0x4f, 0x52, + 0x0c, 0x47, 0x13, 0x62, 0xfb, 0x9d, 0xbe, 0x7c, 0x87, 0xea, 0xc2, 0x5a, 0xe2, 0xdc, 0x4b, 0x6a, 0x4b, 0x16, 0xb0, + 0x9f, 0x31, 0x62, 0xba, 0x51, 0xc1, 0x2f, 0x1f, 0x75, 0xb9, 0x9a, 0x85, 0xab, 0x21, 0x60, 0x66, 0x5f, 0x5d, 0xf1, + 0x20, 0x58, 0xc0, 0xd4, 0xb0, 0x30, 0x63, 0xc7, 0x51, 0x9f, 0x39, 0x96, 0xb2, 0xcf, 0x7d, 0x46, 0xd7, 0x37, 0xc7, + 0xfe, 0x11, 0xeb, 0xf6, 0x5b, 0xec, 0x8a, 0x71, 0x3c, 0xb0, 0xaf, 0x2e, 0xb2, 0x81, 0x69, 0x42, 0x92, 0xf5, 0xcb, + 0x29, 0x90, 0xaa, 0xd5, 0x83, 0x98, 0xab, 0x3a, 0x01, 0x8c, 0xf6, 0x5d, 0x51, 0xf0, 0x88, 0x1c, 0x7f, 0x22, 0x8d, + 0x0e, 0x98, 0xe2, 0x0e, 0x84, 0x30, 0x74, 0x47, 0xbc, 0xd9, 0x5b, 0x81, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xf3, + 0x12, 0x5b, 0xd0, 0x36, 0x5a, 0x2f, 0x02, 0x68, 0x88, 0x44, 0xf2, 0x63, 0xe4, 0xf9, 0x70, 0x76, 0xee, 0x41, 0x31, + 0xdc, 0xa4, 0x2e, 0x88, 0xeb, 0xe9, 0x05, 0xdb, 0x65, 0x42, 0x32, 0x51, 0xe8, 0xd0, 0x14, 0x58, 0x59, 0x3b, 0x71, + 0x3a, 0xc0, 0x87, 0xf7, 0xf7, 0xf0, 0xc0, 0x76, 0x54, 0xfc, 0x40, 0x02, 0xb7, 0x2f, 0xac, 0xe0, 0x50, 0x67, 0xc1, + 0x0c, 0x3a, 0xe0, 0x91, 0xde, 0xa7, 0x46, 0x8c, 0x66, 0xd6, 0x3b, 0x40, 0x14, 0x11, 0x65, 0xb6, 0x4d, 0x6e, 0x87, + 0xbb, 0xe3, 0x29, 0x10, 0x20, 0x63, 0x5a, 0x15, 0x96, 0x61, 0x26, 0xb0, 0xc4, 0x7c, 0x33, 0xbe, 0x68, 0xd1, 0x8f, + 0xfd, 0x3e, 0xaa, 0xe4, 0xa2, 0x52, 0x83, 0xb1, 0x8d, 0x79, 0x63, 0x8b, 0x9e, 0xe0, 0x1b, 0x8d, 0x74, 0xf4, 0x0c, + 0x63, 0xb9, 0x84, 0x39, 0x58, 0xe9, 0x1c, 0xf5, 0x23, 0x58, 0x51, 0x05, 0x88, 0xb3, 0x1f, 0xa7, 0x48, 0x0d, 0x98, + 0x25, 0x3f, 0xa4, 0x45, 0x4d, 0x4e, 0x03, 0x7e, 0xcd, 0x40, 0xcf, 0x1e, 0x55, 0xc6, 0x3d, 0x79, 0x09, 0x5c, 0x9a, + 0xde, 0x7a, 0xda, 0x77, 0x6f, 0xc0, 0x31, 0x16, 0xe4, 0x0d, 0xe6, 0xec, 0x4e, 0x30, 0xc5, 0x8a, 0x6d, 0x5d, 0x2d, + 0xf3, 0x6a, 0xfd, 0x40, 0x67, 0x25, 0x18, 0x4e, 0x93, 0x48, 0xe2, 0x04, 0x4c, 0xa3, 0x18, 0x7f, 0x60, 0xbb, 0xbc, + 0xdb, 0xea, 0x13, 0xbf, 0x0d, 0x7f, 0x1d, 0x29, 0x55, 0x9f, 0x7f, 0x12, 0x0b, 0x33, 0x99, 0xd8, 0x6f, 0xe4, 0xe8, + 0x0c, 0x32, 0x2b, 0xf0, 0x55, 0x3d, 0xe3, 0x59, 0xf2, 0x5c, 0x79, 0xca, 0xcd, 0x8a, 0x2d, 0xb3, 0xe0, 0xe7, 0x51, + 0x49, 0x8d, 0xbd, 0x19, 0xd5, 0xa9, 0x56, 0x8c, 0x51, 0x9d, 0x9e, 0x1c, 0x08, 0x97, 0x29, 0xc0, 0x2a, 0x3b, 0x80, + 0xc6, 0xf3, 0xeb, 0xd2, 0x23, 0x11, 0xd9, 0x2a, 0xa6, 0x1e, 0x83, 0x97, 0x8a, 0xa0, 0x77, 0x10, 0x85, 0x18, 0x1c, + 0x49, 0xdf, 0x68, 0xf5, 0xc5, 0x9f, 0xf8, 0x7d, 0xaf, 0x97, 0x70, 0x17, 0xec, 0x7c, 0x53, 0x63, 0xe9, 0x2c, 0x41, + 0x63, 0xf6, 0x3f, 0x87, 0xac, 0x45, 0x58, 0xe4, 0x34, 0xd3, 0x10, 0x34, 0x41, 0xf1, 0x47, 0xd0, 0xc0, 0x66, 0x4d, + 0xd7, 0x7a, 0x13, 0x94, 0x51, 0x48, 0x82, 0xff, 0x57, 0x19, 0x2f, 0x87, 0x2a, 0x27, 0x93, 0xa8, 0x05, 0xf7, 0x89, + 0x9b, 0x6a, 0x68, 0x05, 0xea, 0xec, 0xe1, 0x29, 0xf4, 0x64, 0x2c, 0xa2, 0x67, 0x58, 0xc4, 0x46, 0x9b, 0xc0, 0x78, + 0x24, 0xf3, 0xb0, 0x2e, 0xa2, 0xdd, 0x72, 0x36, 0xc5, 0x57, 0x76, 0xcc, 0xdb, 0x6e, 0x1f, 0xbb, 0x09, 0x95, 0x78, + 0xfa, 0x7d, 0x57, 0xcc, 0xbe, 0xc7, 0xbe, 0x94, 0xd2, 0x3d, 0x70, 0x58, 0x4a, 0xeb, 0x22, 0x28, 0x9c, 0x3a, 0xd8, + 0x02, 0x9a, 0xec, 0xe4, 0x6c, 0x1a, 0x25, 0x58, 0x9c, 0xb9, 0x49, 0xc0, 0xaf, 0x74, 0x12, 0x42, 0x2a, 0x1b, 0xbe, + 0x63, 0x2d, 0xf9, 0x2b, 0x90, 0x6b, 0xfe, 0xe2, 0x69, 0x20, 0x44, 0x6d, 0x23, 0x14, 0x01, 0x6b, 0xe2, 0xca, 0xbc, + 0x33, 0x08, 0xae, 0xe8, 0x2f, 0x7b, 0x0d, 0xff, 0xdc, 0x98, 0xf6, 0xad, 0x90, 0xda, 0xd0, 0xc1, 0x5a, 0x44, 0xc6, + 0xf3, 0x50, 0xf8, 0x6f, 0xf8, 0xd8, 0x73, 0x84, 0x48, 0x22, 0x17, 0xc9, 0x8f, 0x28, 0x6e, 0x31, 0xdd, 0x42, 0xb9, + 0xb5, 0x9d, 0x8f, 0x23, 0x61, 0xd0, 0x3c, 0x6a, 0xf5, 0x92, 0x94, 0xf7, 0xd4, 0x6a, 0xe6, 0x1e, 0x05, 0xb7, 0x8b, + 0xa5, 0x86, 0x17, 0x88, 0xd2, 0xd5, 0x0f, 0x0a, 0xcd, 0xe2, 0x3f, 0x66, 0xb5, 0x79, 0xea, 0xf6, 0x51, 0xc9, 0x37, + 0xc9, 0xca, 0x91, 0x05, 0x27, 0x51, 0xf8, 0x43, 0x08, 0xbc, 0xd4, 0x19, 0x4f, 0xf5, 0x36, 0x62, 0x1e, 0x0a, 0x4d, + 0x41, 0xae, 0x07, 0xed, 0x13, 0x4d, 0x8e, 0xdc, 0x90, 0x63, 0x7a, 0xd0, 0x3e, 0xac, 0x81, 0xed, 0x08, 0x71, 0x71, + 0x9f, 0x88, 0xe1, 0xb4, 0xea, 0x72, 0x02, 0xe4, 0xce, 0x79, 0xd2, 0x32, 0x04, 0x35, 0x72, 0x13, 0xd4, 0xb8, 0x73, + 0x9c, 0xda, 0x45, 0xd1, 0xed, 0x4b, 0x2e, 0x91, 0x62, 0x94, 0xe9, 0xbe, 0xf4, 0xdf, 0xab, 0xad, 0xa2, 0x01, 0x64, + 0x03, 0xbe, 0xde, 0x7b, 0xc7, 0xe8, 0x00, 0xf5, 0x72, 0xeb, 0xa6, 0x6c, 0x5e, 0x9e, 0xd3, 0x6c, 0x6b, 0xb8, 0xc7, + 0xd0, 0xfe, 0x12, 0xea, 0x9c, 0xfb, 0xac, 0xf8, 0xad, 0xbc, 0x0b, 0xc4, 0xe4, 0xe4, 0x66, 0x23, 0x4f, 0x93, 0x75, + 0x84, 0x75, 0x8f, 0xa1, 0xb9, 0x88, 0x7f, 0x69, 0xac, 0x5c, 0x10, 0x9e, 0x58, 0xc9, 0x82, 0xbf, 0x30, 0xcc, 0x60, + 0x53, 0x79, 0x4d, 0x7f, 0x87, 0x39, 0x80, 0xf7, 0xdb, 0xcd, 0x5a, 0x41, 0x3e, 0x25, 0xb5, 0xe3, 0x6b, 0xad, 0xe3, + 0x97, 0x6f, 0xd0, 0x83, 0xd4, 0xc4, 0x63, 0x51, 0x3d, 0x10, 0xb3, 0xa4, 0x37, 0x2f, 0x71, 0xf4, 0xcd, 0x4f, 0x9b, + 0x67, 0x5c, 0xe3, 0xb9, 0x08, 0xc9, 0x80, 0xb5, 0xc1, 0xa5, 0xbd, 0x37, 0x12, 0x77, 0x9f, 0x95, 0xa9, 0x45, 0x6b, + 0x63, 0x26, 0x0a, 0xb4, 0xb0, 0xee, 0x12, 0xf1, 0x7c, 0xf9, 0xa6, 0xbf, 0x76, 0xa4, 0x58, 0x9a, 0x8f, 0x64, 0x1e, + 0x55, 0x29, 0xe1, 0x8f, 0x01, 0x8d, 0x7f, 0x43, 0x5e, 0x24, 0x31, 0xd0, 0x60, 0x91, 0x1a, 0x2b, 0xef, 0x13, 0x70, + 0x88, 0xa1, 0x89, 0xa8, 0x4d, 0xb4, 0x13, 0xb8, 0xa3, 0xf1, 0x89, 0xa4, 0x3e, 0x26, 0x95, 0x34, 0x01, 0x1e, 0xdd, + 0xc5, 0xe4, 0x64, 0xec, 0x02, 0x7c, 0x81, 0xc7, 0xc7, 0xd3, 0x6f, 0xda, 0xd5, 0xd1, 0x0d, 0x52, 0x6e, 0x2a, 0xc8, + 0x26, 0x60, 0xad, 0x05, 0xe0, 0x29, 0xd7, 0x44, 0xf3, 0x8e, 0x54, 0xbf, 0x0c, 0x02, 0xf6, 0xbb, 0x8b, 0x7a, 0xee, + 0x4d, 0x63, 0x65, 0xf9, 0x38, 0xf1, 0x52, 0xd3, 0x08, 0xb1, 0x62, 0x9f, 0x71, 0xca, 0x11, 0x11, 0xef, 0xf0, 0x6b, + 0xeb, 0xcd, 0x22, 0xbd, 0x4d, 0x8a, 0x73, 0x93, 0x01, 0x86, 0x91, 0x6b, 0x84, 0x5f, 0xcc, 0xb4, 0xb3, 0x75, 0xe5, + 0xc3, 0x02, 0xc9, 0x68, 0x29, 0xfc, 0xad, 0xc8, 0xac, 0xb6, 0x59, 0x8b, 0x10, 0xff, 0x50, 0xf4, 0xb3, 0x43, 0x69, + 0x14, 0x90, 0x57, 0x5f, 0x2e, 0x2b, 0x36, 0x39, 0x05, 0x9d, 0xf6, 0xb9, 0x79, 0x67, 0x59, 0x7e, 0xfc, 0xf9, 0x8f, + 0x73, 0x3b, 0x61, 0x8b, 0x99, 0x27, 0x6e, 0xb1, 0x8c, 0xb2, 0xf2, 0xa2, 0xd5, 0x79, 0x4b, 0xd6, 0xcd, 0xec, 0xba, + 0x40, 0x09, 0xff, 0xd4, 0x8f, 0x0e, 0x67, 0xe5, 0x0c, 0x7a, 0x85, 0x56, 0x16, 0xf6, 0x28, 0x6d, 0xdf, 0xda, 0x97, + 0x03, 0x9d, 0xc6, 0x5d, 0xd8, 0x1c, 0x27, 0x48, 0x52, 0x79, 0x28, 0x3f, 0xf3, 0x14, 0x67, 0xdf, 0x59, 0x4d, 0x47, + 0x3b, 0x7a, 0xc7, 0xd1, 0xe5, 0x60, 0xb1, 0x43, 0x94, 0xac, 0x0f, 0xce, 0xb6, 0x59, 0x7c, 0x70, 0x94, 0x69, 0x3e, + 0xe3, 0x15, 0x0b, 0xa4, 0x34, 0x4f, 0x9f, 0x22, 0xe8, 0x09, 0x64, 0x62, 0x0c, 0xbd, 0x0b, 0x36, 0x4d, 0x81, 0x63, + 0xce, 0xb7, 0x89, 0xa0, 0xcd, 0x32, 0x9a, 0x45, 0xf4, 0x62, 0x64, 0x29, 0xbc, 0xf6, 0x8e, 0x7a, 0xae, 0x64, 0x5d, + 0x42, 0xab, 0x23, 0xab, 0x1f, 0x6c, 0xf7, 0x69, 0xe1, 0x07, 0xf3, 0xbb, 0xd5, 0x42, 0x7d, 0x65, 0xac, 0x7e, 0x8c, + 0xcc, 0x52, 0xe7, 0x2c, 0x67, 0xb7, 0xd3, 0xd8, 0xc0, 0xeb, 0x64, 0xb3, 0xf5, 0xeb, 0x76, 0x7f, 0xb9, 0xe4, 0xdf, + 0x66, 0xca, 0xdb, 0x24, 0x47, 0xd8, 0xef, 0x13, 0x59, 0x03, 0xb2, 0x3e, 0x6d, 0x71, 0x96, 0x92, 0x3a, 0x56, 0x49, + 0x94, 0x18, 0xdb, 0x09, 0x5c, 0x61, 0x10, 0x12, 0xcf, 0x66, 0x75, 0x25, 0x4c, 0xce, 0xab, 0x78, 0xa7, 0x30, 0x57, + 0x22, 0x59, 0x2c, 0xf2, 0x04, 0x45, 0xda, 0x37, 0xcb, 0xe5, 0xa5, 0x3c, 0x35, 0xa5, 0x1d, 0x09, 0x8d, 0xbc, 0xa4, + 0xff, 0x0c, 0xb8, 0x24, 0x44, 0x2a, 0x50, 0x89, 0xcf, 0x7d, 0x47, 0x2a, 0xd1, 0xa4, 0x8a, 0x52, 0x14, 0xd4, 0xca, + 0xf4, 0x8f, 0x98, 0x97, 0xa6, 0xb4, 0xee, 0x81, 0xc0, 0x75, 0x9b, 0x2b, 0x89, 0xa7, 0x7f, 0x99, 0xcc, 0x2e, 0x00, + 0xe7, 0x65, 0xb9, 0xc1, 0x2f, 0x63, 0xc2, 0xe5, 0xd1, 0x65, 0x4d, 0x20, 0xd8, 0xf1, 0x06, 0x7e, 0x98, 0x48, 0x10, + 0x1c, 0x57, 0x24, 0x22, 0x16, 0x9c, 0xa1, 0x88, 0xa7, 0x60, 0x00, 0x48, 0xce, 0xbf, 0x4f, 0x9f, 0x17, 0x34, 0x7f, + 0x40, 0x54, 0xe1, 0xa8, 0x02, 0xc4, 0x01, 0x09, 0x06, 0x5d, 0x78, 0x27, 0x8b, 0x6c, 0x35, 0x3b, 0x5e, 0x9e, 0x93, + 0xce, 0x9d, 0x45, 0x44, 0x7a, 0x51, 0x12, 0x41, 0x9c, 0x61, 0xf1, 0x83, 0xa0, 0xc4, 0xe8, 0xf5, 0xba, 0x20, 0x8c, + 0x2e, 0x96, 0x64, 0xa3, 0xd1, 0x20, 0x20, 0xfd, 0x23, 0xc4, 0x4c, 0xb6, 0x4b, 0x39, 0x66, 0x5f, 0x7b, 0xc5, 0x39, + 0x6b, 0xcd, 0x10, 0x4a, 0x06, 0x76, 0x6f, 0x09, 0xa4, 0x3a, 0x87, 0x32, 0x9a, 0x4a, 0x53, 0x7e, 0x21, 0x47, 0x50, + 0xeb, 0xd0, 0x6b, 0x93, 0xa1, 0xdf, 0x06, 0x4f, 0x22, 0x20, 0x45, 0x0a, 0xcf, 0x4b, 0x60, 0xc1, 0x64, 0xe7, 0xb6, + 0x64, 0x16, 0x1f, 0x3f, 0xa4, 0x38, 0xc9, 0x9c, 0xcd, 0x40, 0xff, 0x42, 0x13, 0x5c, 0x2c, 0xd2, 0x11, 0x23, 0xab, + 0xe0, 0x72, 0x58, 0xf7, 0xbf, 0xed, 0x72, 0xe8, 0xa6, 0x20, 0xb7, 0x39, 0x1b, 0x33, 0xe5, 0x78, 0xdc, 0xcd, 0x59, + 0x5f, 0xfa, 0xcb, 0x24, 0x8d, 0x34, 0x15, 0x4a, 0x67, 0xd6, 0x77, 0xf7, 0xbb, 0x7a, 0xec, 0x96, 0x47, 0xf7, 0x16, + 0x10, 0xd0, 0xc6, 0x1d, 0x39, 0x65, 0x05, 0x96, 0x84, 0x63, 0x12, 0x0e, 0x1f, 0x00, 0x73, 0xad, 0x1f, 0x44, 0x25, + 0xfd, 0x5d, 0xb2, 0x4f, 0x07, 0x22, 0x3f, 0xd7, 0x65, 0x7d, 0x96, 0xfa, 0x93, 0x69, 0xf7, 0x71, 0xec, 0xe3, 0x19, + 0xa7, 0x39, 0x42, 0x52, 0x96, 0xe4, 0xd7, 0xcb, 0xcd, 0x71, 0xb6, 0x95, 0xfc, 0x4f, 0x28, 0xce, 0x1f, 0x94, 0xd1, + 0x3a, 0x5b, 0x36, 0x7d, 0xb6, 0x60, 0x38, 0x67, 0x92, 0x96, 0xe0, 0x94, 0x4f, 0xfc, 0x4b, 0xd5, 0xe1, 0xf1, 0x69, + 0x8f, 0x58, 0x0f, 0x22, 0x49, 0xf0, 0x5f, 0x73, 0xc2, 0xe3, 0x53, 0x33, 0xe1, 0x87, 0x67, 0x88, 0x4f, 0x6f, 0x8c, + 0x8e, 0xa9, 0xd4, 0x1c, 0xcb, 0x8a, 0x4b, 0x2f, 0x2a, 0x82, 0x53, 0x5d, 0xd8, 0xe0, 0xd9, 0x9d, 0x3e, 0xa5, 0x39, + 0xcd, 0x41, 0x78, 0x92, 0x66, 0x3b, 0xb7, 0x68, 0xb1, 0xa4, 0x05, 0x94, 0x92, 0xca, 0x49, 0xb4, 0x9a, 0xc6, 0x91, + 0xad, 0x23, 0xcc, 0x0b, 0x9c, 0xdd, 0x46, 0x62, 0x84, 0xb5, 0x33, 0x9e, 0xa8, 0x91, 0x9a, 0x92, 0x9b, 0x3a, 0x22, + 0x59, 0x8f, 0xc1, 0xfc, 0x9f, 0x1f, 0x7b, 0x5c, 0x63, 0x66, 0x67, 0xe1, 0x8a, 0x72, 0xfb, 0x6a, 0xaa, 0x76, 0xb2, + 0xa5, 0x2b, 0xaf, 0x5b, 0x3b, 0xa7, 0xd2, 0xe6, 0xc2, 0x15, 0x87, 0x6e, 0xb8, 0x7a, 0x6d, 0x17, 0x24, 0xd7, 0xcf, + 0x91, 0xdf, 0x0c, 0x83, 0x25, 0x89, 0xd4, 0xcd, 0x9d, 0x27, 0x65, 0x4b, 0xa9, 0xba, 0xaf, 0xc0, 0xe2, 0xb0, 0x34, + 0x54, 0xbb, 0x0a, 0xca, 0xf2, 0x46, 0x0d, 0x61, 0x11, 0xd6, 0xd4, 0x0b, 0x0e, 0xa7, 0x74, 0x9e, 0x05, 0x35, 0xb5, + 0x38, 0x3f, 0x69, 0xd4, 0x5e, 0x52, 0xe4, 0x54, 0x40, 0xbc, 0x89, 0x22, 0x17, 0x2f, 0x51, 0xaf, 0xf2, 0xb8, 0x82, + 0xfd, 0x91, 0x92, 0xaa, 0x9d, 0x5e, 0xa8, 0xc2, 0xe9, 0x99, 0x2a, 0x9f, 0x5e, 0x9e, 0xae, 0x70, 0x98, 0x4b, 0xb5, + 0x2b, 0x91, 0x45, 0x59, 0x52, 0x96, 0xe3, 0xca, 0x95, 0xf1, 0xdc, 0x9e, 0xbb, 0x8c, 0x4c, 0xd5, 0x29, 0x06, 0x93, + 0x32, 0xa5, 0xd5, 0x63, 0xdb, 0x11, 0x43, 0xc3, 0x04, 0x82, 0x5d, 0xd6, 0xca, 0x68, 0x7d, 0xbf, 0x78, 0x62, 0x51, + 0xa8, 0x2d, 0xad, 0x4f, 0x4f, 0x92, 0x90, 0xb5, 0xbe, 0xb4, 0x09, 0x94, 0xd8, 0x79, 0x3f, 0x56, 0xd1, 0x5e, 0x3c, + 0x77, 0xcf, 0xda, 0x83, 0x08, 0xb8, 0x5e, 0xeb, 0xcb, 0x0f, 0xc7, 0xf4, 0x90, 0xbd, 0x6c, 0x91, 0xa2, 0xfc, 0x81, + 0x04, 0xce, 0x07, 0x84, 0x30, 0x13, 0x58, 0x05, 0x0b, 0xe5, 0x95, 0x04, 0x56, 0x81, 0x8f, 0x18, 0xb5, 0x98, 0x9d, + 0x96, 0xde, 0xfb, 0xa4, 0x58, 0xe3, 0x26, 0xc4, 0x0b, 0x40, 0x5e, 0x4f, 0x21, 0xb2, 0x85, 0x28, 0xd0, 0x4c, 0x11, + 0x24, 0xfc, 0x80, 0x7d, 0x78, 0x81, 0xd6, 0x8f, 0xe9, 0xc8, 0x57, 0xb3, 0x72, 0x07, 0x6d, 0x3d, 0xb6, 0xa7, 0x2a, + 0x5d, 0x35, 0x29, 0x3e, 0x4a, 0xbc, 0x93, 0x58, 0x34, 0xf0, 0xca, 0x15, 0x3b, 0xbd, 0xf3, 0x81, 0xdf, 0xb0, 0x2d, + 0x73, 0xfc, 0xf2, 0x34, 0xc7, 0x15, 0xa8, 0x1a, 0x55, 0x68, 0xbb, 0x3d, 0x40, 0xa6, 0xa6, 0x57, 0x09, 0xe2, 0xb0, + 0x69, 0x1a, 0x2e, 0x40, 0x07, 0x0e, 0x51, 0x09, 0xa4, 0x4c, 0x35, 0x0b, 0x34, 0x72, 0x8d, 0x14, 0x36, 0x5b, 0xb3, + 0xa8, 0x4d, 0xd8, 0xe7, 0xdf, 0xd0, 0xbc, 0xb6, 0x2d, 0x9f, 0x88, 0x3b, 0x54, 0xf2, 0x19, 0xbc, 0xf4, 0xe1, 0x1e, + 0xdf, 0x03, 0x76, 0xe4, 0x4a, 0xc5, 0xc8, 0x94, 0xc4, 0xf6, 0x78, 0x41, 0xb5, 0xc9, 0x3c, 0x79, 0x54, 0xa7, 0x26, + 0x6c, 0x28, 0x57, 0x38, 0x61, 0xfb, 0x11, 0xbb, 0x80, 0x77, 0x28, 0x31, 0x37, 0xd5, 0x6f, 0x0e, 0xa1, 0xab, 0x3d, + 0xf0, 0xae, 0x8c, 0x7e, 0x79, 0xf9, 0x62, 0x8b, 0xb7, 0xb9, 0x83, 0xbf, 0xa6, 0xc1, 0xb6, 0x50, 0x1c, 0xea, 0xae, + 0x80, 0xf4, 0xb2, 0x97, 0x2b, 0x45, 0x49, 0x6f, 0xcd, 0xe0, 0xa9, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd2, + 0x83, 0x30, 0x21, 0xc8, 0x01, 0x95, 0xd1, 0xbb, 0x2b, 0xd9, 0xe2, 0x5e, 0xf0, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, + 0xd3, 0x28, 0x8d, 0xba, 0x64, 0x68, 0x8f, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x57, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, + 0xec, 0xd9, 0x3c, 0x86, 0xe1, 0xdb, 0xed, 0xc9, 0x80, 0xb1, 0x65, 0xf6, 0xbe, 0xa7, 0x9b, 0x8f, 0x26, 0xe4, 0x1a, + 0x6a, 0x0d, 0xc7, 0x39, 0x30, 0x64, 0xaa, 0x68, 0xf0, 0xc9, 0x86, 0x68, 0xc2, 0xda, 0x5c, 0x76, 0x5d, 0x08, 0x61, + 0xd0, 0x63, 0x53, 0x58, 0x41, 0x5c, 0x3b, 0xd6, 0xb0, 0xbe, 0x58, 0x46, 0xa0, 0x69, 0x4d, 0x1f, 0xc8, 0x98, 0xb6, + 0x97, 0x08, 0x75, 0x27, 0xca, 0x37, 0xcc, 0x69, 0x16, 0xc4, 0x7d, 0xaf, 0xcb, 0xe7, 0x1a, 0x36, 0x7e, 0xa2, 0x62, + 0xae, 0xa7, 0xba, 0x85, 0x01, 0xea, 0x40, 0x5c, 0x0c, 0xf8, 0x78, 0x1b, 0x42, 0x5f, 0xf9, 0x77, 0xd8, 0xf7, 0x4a, + 0x29, 0x8f, 0x3a, 0x3e, 0x2d, 0x35, 0x72, 0xd4, 0x5e, 0xf6, 0x7f, 0xb2, 0xfa, 0x90, 0x3f, 0x56, 0xa8, 0xd0, 0x84, + 0x34, 0x34, 0x89, 0xba, 0x79, 0x02, 0xb1, 0xed, 0x7b, 0xae, 0xd0, 0x8b, 0x45, 0xa4, 0x3c, 0x02, 0xba, 0x29, 0x8f, + 0x77, 0xab, 0x19, 0x46, 0x7c, 0xab, 0xd7, 0xda, 0x68, 0x4b, 0x34, 0x8b, 0x23, 0xde, 0x45, 0x3b, 0x3b, 0x9c, 0xca, + 0x48, 0xcf, 0x4e, 0xe1, 0x38, 0x27, 0xd1, 0xbb, 0x74, 0xd8, 0x69, 0xae, 0xbe, 0x7e, 0x67, 0x43, 0x1f, 0xe2, 0x6a, + 0x21, 0x6a, 0x7b, 0xce, 0x68, 0x6e, 0x26, 0x2e, 0x10, 0x0b, 0xa0, 0xd9, 0xbb, 0x57, 0xa9, 0xa6, 0xc9, 0x98, 0x71, + 0x59, 0xcc, 0x12, 0x29, 0xc2, 0x0e, 0xe8, 0x25, 0x9a, 0x30, 0x51, 0x75, 0x9c, 0x1b, 0xb1, 0xe7, 0xa3, 0xba, 0x29, + 0x77, 0x25, 0x19, 0x94, 0x45, 0xeb, 0xb6, 0xeb, 0xe5, 0x25, 0xf4, 0x7e, 0x1e, 0x70, 0x5d, 0x1b, 0x2b, 0x38, 0x61, + 0x0b, 0x13, 0x9f, 0x25, 0x41, 0x6e, 0x8d, 0x24, 0x5b, 0x84, 0xa5, 0x7a, 0x67, 0xfe, 0x69, 0xe9, 0xd5, 0x76, 0xa4, + 0x5e, 0x38, 0xcc, 0xdc, 0x9e, 0x85, 0xe5, 0x57, 0xc0, 0xe3, 0xbc, 0xf7, 0xbc, 0x11, 0x9a, 0xf2, 0xc7, 0xab, 0x3d, + 0xa8, 0x88, 0x66, 0x63, 0x47, 0x3d, 0x91, 0x6b, 0xba, 0xa9, 0x82, 0x6b, 0x32, 0xd1, 0xea, 0x41, 0x9c, 0x59, 0xd1, + 0x76, 0x62, 0x19, 0xfc, 0x33, 0xd8, 0xe0, 0x1b, 0xd8, 0x17, 0x4b, 0x00, 0xeb, 0x37, 0xc6, 0x57, 0x21, 0x0f, 0xcb, + 0xf7, 0x74, 0x7e, 0x86, 0xb0, 0xaf, 0x30, 0x57, 0x24, 0x2c, 0x4f, 0x95, 0x5a, 0xc9, 0x41, 0xc5, 0xb4, 0x7c, 0x6e, + 0xc1, 0x27, 0xd5, 0x56, 0x29, 0x5e, 0xff, 0x55, 0x5c, 0xab, 0xd0, 0xf9, 0x79, 0xa2, 0x10, 0xe2, 0xfe, 0x23, 0x12, + 0x55, 0x94, 0x9f, 0x86, 0xdb, 0x66, 0xdf, 0xc3, 0x8f, 0x1b, 0x7e, 0xd0, 0x65, 0x81, 0xca, 0xaa, 0x71, 0x83, 0x71, + 0xb8, 0x3c, 0xcd, 0xaa, 0x11, 0x0b, 0x45, 0xf8, 0xc6, 0xa5, 0x03, 0x47, 0x6f, 0x63, 0xab, 0xe6, 0x52, 0x85, 0x2a, + 0x20, 0xf6, 0x14, 0x7a, 0xde, 0x44, 0x35, 0x52, 0x2a, 0x12, 0x08, 0x93, 0x06, 0xed, 0x12, 0x17, 0xec, 0x16, 0xab, + 0x76, 0xb5, 0xbb, 0x15, 0xf3, 0x9a, 0x4c, 0x04, 0x8c, 0xf1, 0x0e, 0xb4, 0x6e, 0x66, 0x4b, 0x06, 0x74, 0x4e, 0xec, + 0xa8, 0xc0, 0x79, 0x8c, 0x71, 0x70, 0xb8, 0xc7, 0xcd, 0xf4, 0xa4, 0x92, 0x1d, 0x66, 0xe4, 0xa1, 0x39, 0x74, 0x86, + 0x2b, 0x0f, 0xe5, 0x21, 0x2b, 0x71, 0xb6, 0xc0, 0xcb, 0x35, 0x72, 0x95, 0xe8, 0xaa, 0x25, 0x68, 0x78, 0x20, 0xb9, + 0xdb, 0x37, 0xdf, 0xbd, 0xd3, 0xbb, 0x01, 0xa7, 0xd2, 0xdf, 0x0c, 0xd8, 0x1d, 0x2c, 0x78, 0xb7, 0x3a, 0x1d, 0x4b, + 0x0c, 0x00, 0x64, 0xd7, 0xf4, 0x83, 0xb0, 0x85, 0xee, 0x74, 0x87, 0x6b, 0xc7, 0x55, 0x04, 0x6d, 0x88, 0xaa, 0x8c, + 0xa1, 0x23, 0xbb, 0x88, 0x04, 0xb2, 0xeb, 0x88, 0x15, 0xdd, 0x32, 0x16, 0xc2, 0x09, 0x3c, 0xee, 0x01, 0xf5, 0x83, + 0x23, 0xa4, 0x54, 0x44, 0x42, 0xc9, 0x85, 0xf8, 0xdb, 0x34, 0xd4, 0xac, 0xe0, 0x6e, 0xb3, 0x21, 0x76, 0x93, 0x88, + 0xfe, 0xa0, 0x2a, 0xbc, 0x39, 0x8f, 0xf2, 0xad, 0x03, 0x0a, 0x1f, 0xcd, 0xc8, 0xc0, 0x59, 0xda, 0xb7, 0xa7, 0x5d, + 0x7b, 0x37, 0xe6, 0xa5, 0xb4, 0x94, 0x0a, 0xc1, 0xcd, 0x1d, 0x3c, 0xeb, 0x1f, 0x5c, 0x49, 0x13, 0x9b, 0x9a, 0x7d, + 0x99, 0x73, 0xb4, 0x33, 0xe5, 0x79, 0x14, 0x5f, 0x6b, 0xd9, 0xf3, 0xb6, 0x79, 0x36, 0x76, 0x67, 0xb7, 0x8b, 0xfd, + 0x0c, 0x49, 0x61, 0x8b, 0x19, 0xcc, 0x35, 0x89, 0x62, 0x12, 0x18, 0x6d, 0x80, 0xbd, 0x89, 0x66, 0xd8, 0x45, 0x0b, + 0x94, 0xbd, 0x5b, 0x77, 0x6b, 0xc3, 0xf1, 0xdb, 0xcc, 0xd7, 0xaa, 0xf6, 0xc2, 0x9d, 0x12, 0x05, 0xe7, 0xc3, 0xde, + 0x39, 0xaf, 0xff, 0xa3, 0xc4, 0x9b, 0x19, 0xc6, 0x92, 0x48, 0xb4, 0x36, 0x10, 0x3c, 0x4a, 0xeb, 0xb5, 0x59, 0x96, + 0x20, 0x3b, 0xb5, 0xbc, 0xfd, 0x07, 0x1d, 0x20, 0x15, 0xe3, 0xdd, 0xe2, 0xe6, 0x0c, 0x0b, 0x8e, 0x49, 0xa9, 0x2d, + 0x37, 0xbf, 0xfe, 0x49, 0x32, 0xa5, 0xa2, 0x4d, 0xae, 0x27, 0x9a, 0xe7, 0xe2, 0xca, 0x01, 0x80, 0x40, 0x69, 0x36, + 0xac, 0x8b, 0xeb, 0xcd, 0x64, 0x73, 0xab, 0xd0, 0x11, 0x66, 0xaa, 0xc0, 0xf8, 0x9b, 0x55, 0x4a, 0x4f, 0xa9, 0x56, + 0x49, 0xc2, 0xdc, 0x4e, 0x5f, 0xab, 0x44, 0x68, 0x3f, 0x06, 0xe2, 0xdb, 0xc9, 0x77, 0xf5, 0xa7, 0x6c, 0x8b, 0x3c, + 0x8e, 0x03, 0x93, 0xb3, 0xb7, 0x76, 0x50, 0xd0, 0xa8, 0xed, 0x5c, 0x8e, 0xd7, 0x3c, 0x2b, 0xa8, 0x7d, 0xe5, 0x57, + 0xb3, 0xb5, 0xc7, 0x17, 0xee, 0x08, 0xb2, 0x02, 0xa9, 0xc7, 0xe4, 0xc1, 0x34, 0x46, 0xa5, 0xd9, 0x39, 0x2f, 0x76, + 0x58, 0x1e, 0x93, 0x64, 0xd7, 0xf8, 0xcf, 0xc8, 0xa5, 0x14, 0x48, 0xfe, 0xc4, 0xb9, 0x13, 0x2a, 0x16, 0xb3, 0x64, + 0x61, 0x6a, 0xd7, 0x24, 0x2f, 0xdf, 0xc5, 0x75, 0x3c, 0x2d, 0xc7, 0x7f, 0x56, 0x4c, 0xf4, 0x24, 0x10, 0x52, 0xeb, + 0x1d, 0x0d, 0x1e, 0x40, 0xdd, 0x3a, 0x83, 0x6f, 0x64, 0xf3, 0x50, 0x24, 0x83, 0x8c, 0xd9, 0x56, 0xdd, 0xa5, 0x1a, + 0x89, 0x7a, 0xb0, 0x0c, 0xb4, 0xdb, 0x49, 0xe0, 0x12, 0xb5, 0xf6, 0x10, 0x1c, 0x54, 0xf4, 0x3e, 0x54, 0xc1, 0x52, + 0x33, 0x58, 0xaa, 0xac, 0xd4, 0x06, 0x6b, 0x2f, 0xd5, 0xda, 0x32, 0xa3, 0x2b, 0x2f, 0x0f, 0x8e, 0x39, 0x0e, 0x00, + 0x5b, 0xcf, 0xa5, 0x0e, 0x03, 0xe8, 0x44, 0x36, 0x70, 0x03, 0x32, 0x00, 0x65, 0x2d, 0xa1, 0x72, 0xd3, 0x82, 0x73, + 0xad, 0x4d, 0x29, 0x96, 0x80, 0x44, 0x70, 0xc6, 0xfe, 0xe8, 0x51, 0xe9, 0xed, 0xc8, 0x11, 0xae, 0x5a, 0x37, 0x6d, + 0x05, 0x6b, 0xeb, 0x0c, 0x69, 0xe3, 0x31, 0xde, 0x65, 0x3f, 0x01, 0xdf, 0xc5, 0x8b, 0xd6, 0x91, 0x19, 0x6f, 0x71, + 0xa4, 0x20, 0x14, 0xba, 0xde, 0x31, 0x16, 0xa6, 0x04, 0x86, 0xd9, 0xdd, 0x15, 0x61, 0x7a, 0x7b, 0x29, 0x20, 0x58, + 0xb8, 0xb1, 0x16, 0x37, 0x0e, 0xcf, 0x6f, 0x1c, 0x26, 0x8a, 0x70, 0x68, 0xa6, 0x4a, 0xf8, 0x5c, 0xaa, 0x0c, 0x05, + 0x39, 0x35, 0x38, 0x0a, 0xdc, 0xdf, 0xbe, 0x77, 0xb4, 0x28, 0x12, 0x82, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x75, 0xc6, + 0x05, 0xe9, 0xcb, 0xe1, 0xfe, 0x62, 0x6e, 0x87, 0xa9, 0x59, 0x99, 0xb7, 0x48, 0x7c, 0x6f, 0x5a, 0x8c, 0x11, 0xe1, + 0x7c, 0xaf, 0x5d, 0x60, 0x8b, 0xb5, 0xec, 0x6f, 0x3f, 0xee, 0x09, 0x57, 0x16, 0x0e, 0x0c, 0x5d, 0x64, 0xda, 0xab, + 0x75, 0xb7, 0x52, 0xc4, 0xf9, 0x47, 0xf4, 0xc8, 0xfc, 0xc1, 0x38, 0x8e, 0x1d, 0xdc, 0xee, 0x84, 0xda, 0xe7, 0xfc, + 0x86, 0x85, 0x3a, 0xa2, 0xd5, 0x0d, 0xd4, 0xb0, 0x06, 0x97, 0xca, 0x2c, 0x2d, 0xe6, 0x9f, 0xdd, 0xdc, 0x3c, 0x25, + 0xe0, 0x24, 0xf1, 0x05, 0x24, 0xd9, 0xe1, 0x7a, 0xf7, 0xe9, 0x2d, 0x93, 0xbe, 0x0d, 0x92, 0x12, 0xbb, 0x95, 0xca, + 0x76, 0x49, 0xd3, 0x94, 0x1d, 0xee, 0x8a, 0xaa, 0x35, 0xd8, 0x13, 0x13, 0xa5, 0xa3, 0xbe, 0x10, 0x26, 0x4d, 0xec, + 0x4b, 0x18, 0xef, 0x8b, 0x09, 0x9c, 0x37, 0x0c, 0xf1, 0xaa, 0x03, 0xa5, 0x50, 0x22, 0x65, 0x2f, 0xbb, 0xe3, 0x4d, + 0x69, 0x26, 0x1f, 0x51, 0xc5, 0x81, 0x96, 0xde, 0x5a, 0xee, 0x4a, 0x00, 0xd0, 0xbd, 0xba, 0xbc, 0xfc, 0xfd, 0xc1, + 0x7d, 0x8c, 0x95, 0xc8, 0x37, 0xef, 0xf7, 0xc3, 0xd3, 0xfd, 0x17, 0x12, 0xc1, 0x81, 0xe6, 0x71, 0x7a, 0xf9, 0x5d, + 0xa5, 0x8b, 0x5b, 0xd5, 0xf7, 0xab, 0xa0, 0x8c, 0xd4, 0xe3, 0xee, 0x2c, 0x6c, 0x09, 0x26, 0xac, 0x0d, 0x38, 0x67, + 0x3e, 0x08, 0x65, 0x2e, 0xff, 0xfa, 0x2c, 0xce, 0xdd, 0x78, 0x58, 0x78, 0x26, 0xb0, 0xb1, 0x31, 0xd4, 0x61, 0xae, + 0x3b, 0xf3, 0xe9, 0xe0, 0x19, 0xb9, 0xee, 0x1a, 0x32, 0x2c, 0x8d, 0x03, 0xbe, 0xde, 0xfa, 0xf1, 0xfe, 0x3f, 0x8f, + 0x5f, 0x06, 0xe6, 0x81, 0x99, 0xf1, 0x1c, 0x95, 0xf6, 0xb0, 0xa4, 0xc1, 0x61, 0x64, 0x3b, 0xea, 0xda, 0xbf, 0x47, + 0x23, 0x82, 0x8c, 0x10, 0x21, 0xc7, 0xa1, 0x1d, 0x43, 0x39, 0x3d, 0x8e, 0x55, 0x95, 0xf6, 0xa2, 0x37, 0x18, 0x37, + 0xb2, 0x85, 0x22, 0x60, 0x4a, 0xf4, 0xfd, 0xea, 0xac, 0x2a, 0xee, 0x4d, 0xff, 0xf2, 0xe8, 0x8b, 0xec, 0xaa, 0x51, + 0x03, 0xe1, 0x77, 0x24, 0xaa, 0xa2, 0x37, 0x96, 0xef, 0xb4, 0x05, 0x5b, 0x43, 0x0e, 0x8c, 0x1a, 0x49, 0x9b, 0x11, + 0x3b, 0x6f, 0x32, 0xe7, 0x92, 0x2f, 0xd4, 0x58, 0x7a, 0x94, 0x93, 0x65, 0x0a, 0x00, 0xd3, 0x95, 0x16, 0x11, 0x17, + 0x18, 0x82, 0x2b, 0x0e, 0xab, 0x5b, 0xc8, 0x8c, 0xf5, 0x6c, 0x77, 0x16, 0x8d, 0x26, 0x08, 0xd3, 0xfa, 0x90, 0xa8, + 0x30, 0x73, 0xca, 0xa4, 0x0c, 0x97, 0xda, 0x09, 0xc8, 0x93, 0xdf, 0xd2, 0x8a, 0x01, 0x98, 0x31, 0x91, 0x5c, 0x6e, + 0x6c, 0x22, 0xeb, 0x90, 0xcf, 0x49, 0xbf, 0x99, 0xf3, 0xe1, 0x9b, 0x18, 0x1f, 0x5c, 0x9c, 0x06, 0xeb, 0x0f, 0x50, + 0xf2, 0xdc, 0x0d, 0x97, 0xab, 0x4d, 0xda, 0x72, 0x5b, 0xd1, 0x16, 0x8c, 0x89, 0x76, 0x79, 0x61, 0x9b, 0xa8, 0x40, + 0x9f, 0x49, 0x6f, 0xb8, 0x06, 0xa2, 0x1c, 0x06, 0xf1, 0x52, 0x0e, 0xc5, 0xcd, 0xda, 0x23, 0x54, 0x69, 0x2c, 0x50, + 0x03, 0x2b, 0x7c, 0xc2, 0x30, 0xaa, 0x26, 0xd8, 0x7d, 0xff, 0xd8, 0xe0, 0xcb, 0xd5, 0xb7, 0x83, 0x35, 0x6f, 0x5a, + 0x26, 0xda, 0x21, 0x3a, 0x9c, 0x83, 0x8a, 0x87, 0xd8, 0x69, 0x92, 0xd3, 0x60, 0xea, 0x7a, 0x72, 0xb9, 0x21, 0x63, + 0x33, 0x19, 0x69, 0x7a, 0xc0, 0x1d, 0xe6, 0xb6, 0x1f, 0x1a, 0xcc, 0x21, 0x8e, 0x8d, 0xa3, 0xba, 0x71, 0x9d, 0x31, + 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcb, 0x8b, 0xf2, 0xd6, 0xda, 0x34, 0x74, 0x64, 0xdf, 0x9a, 0xee, 0x38, + 0xc2, 0x88, 0x88, 0xc7, 0x4c, 0x17, 0x2c, 0x2c, 0xb5, 0xb3, 0xb8, 0x29, 0x62, 0x39, 0xb6, 0x23, 0xac, 0x06, 0x60, + 0x16, 0xd8, 0xef, 0xcc, 0x4b, 0xef, 0x35, 0x7a, 0x21, 0x7c, 0xb0, 0x91, 0xf3, 0xb2, 0x98, 0x91, 0xb9, 0xef, 0xd0, + 0x14, 0x1e, 0xb8, 0x3f, 0x55, 0xa7, 0x15, 0x1c, 0xc4, 0xda, 0x71, 0xf4, 0xf7, 0x03, 0x6a, 0x89, 0x17, 0x04, 0x21, + 0x9c, 0x8a, 0xcd, 0x96, 0x0e, 0x88, 0x7d, 0x88, 0x65, 0x6a, 0x00, 0x42, 0x50, 0x0e, 0x56, 0xbb, 0x4f, 0x3b, 0x7d, + 0x8f, 0xd0, 0xf7, 0x11, 0xf3, 0x4d, 0x80, 0xcc, 0x14, 0x94, 0x27, 0x6a, 0x9f, 0x92, 0x88, 0x9e, 0xfc, 0xa4, 0x9b, + 0x6c, 0xd6, 0xa6, 0x4e, 0x02, 0xa5, 0x23, 0x4e, 0xde, 0x62, 0x14, 0xce, 0x8b, 0x13, 0x06, 0x74, 0xbd, 0x14, 0x83, + 0x69, 0xe3, 0x8b, 0xe2, 0x95, 0x2d, 0xa7, 0x86, 0xfd, 0x38, 0xb7, 0x35, 0x27, 0x1c, 0x8e, 0x32, 0x51, 0xf6, 0x4e, + 0x95, 0x1e, 0x0a, 0xac, 0x9b, 0x06, 0xea, 0xfd, 0x84, 0x5d, 0x70, 0xb7, 0x3d, 0x3e, 0xa6, 0x72, 0x04, 0x15, 0x42, + 0x21, 0x41, 0x2d, 0x53, 0xfa, 0x23, 0xe6, 0x39, 0x35, 0x62, 0xaf, 0x3c, 0x2a, 0x65, 0x22, 0x88, 0xc7, 0x3e, 0x7b, + 0xb0, 0xc7, 0x16, 0x08, 0x87, 0x1d, 0x4e, 0x74, 0xa5, 0x80, 0x7e, 0x90, 0x36, 0x82, 0x9d, 0x8f, 0x85, 0x22, 0x59, + 0x80, 0x62, 0x68, 0x37, 0xe2, 0xa4, 0xca, 0xee, 0x92, 0xd0, 0xef, 0xc5, 0x02, 0x67, 0x76, 0x2e, 0x81, 0xe4, 0x3a, + 0x5b, 0x18, 0x64, 0x54, 0x08, 0xed, 0x16, 0x12, 0x10, 0xa6, 0x74, 0x91, 0x0f, 0xf8, 0x91, 0x5e, 0x2a, 0x97, 0x0a, + 0xc9, 0xd3, 0xa5, 0xcf, 0xe1, 0x97, 0x1d, 0xb5, 0xe2, 0xc6, 0x5b, 0x1b, 0xe5, 0x1a, 0xe5, 0x62, 0xd6, 0xfc, 0x47, + 0xec, 0x71, 0x89, 0x74, 0x6c, 0x81, 0xb5, 0xa1, 0x1b, 0x54, 0x96, 0xd2, 0xc0, 0x89, 0x07, 0x12, 0xa9, 0xdb, 0x0e, + 0x47, 0xda, 0xa2, 0xf6, 0x93, 0xbd, 0x57, 0xd7, 0xa0, 0xf4, 0xcc, 0x7a, 0x2b, 0x71, 0x68, 0x2a, 0x64, 0x91, 0x55, + 0xd5, 0x80, 0x95, 0x7c, 0x1c, 0xd2, 0x64, 0x88, 0xee, 0x92, 0xc4, 0x93, 0xcc, 0xe9, 0x37, 0x99, 0xe9, 0x45, 0xff, + 0xa3, 0x12, 0x95, 0x0f, 0x65, 0xff, 0x93, 0x1c, 0xcf, 0x3a, 0xa9, 0x1f, 0x85, 0xd3, 0x90, 0xc6, 0x26, 0x13, 0x30, + 0x80, 0xd5, 0x86, 0x39, 0x94, 0x19, 0x2d, 0x5b, 0xc5, 0xb9, 0xdb, 0x46, 0x4a, 0x6c, 0xe8, 0x27, 0x3b, 0x06, 0xec, + 0x8f, 0xbf, 0x02, 0x71, 0xc0, 0x23, 0x66, 0x1c, 0xec, 0xad, 0x98, 0xb4, 0xa9, 0x28, 0xf8, 0x5d, 0x69, 0x34, 0x81, + 0x6b, 0x3a, 0xa4, 0x69, 0x73, 0xe5, 0x18, 0x32, 0xbd, 0x6c, 0xcc, 0x84, 0x98, 0x39, 0x78, 0x46, 0x28, 0xf6, 0xdf, + 0xfd, 0x77, 0x09, 0x8e, 0x16, 0x8d, 0xf2, 0xe4, 0xb4, 0x0e, 0xe6, 0x56, 0x5d, 0x7a, 0xe7, 0x7e, 0x08, 0x69, 0x03, + 0x80, 0xca, 0x9d, 0xed, 0x59, 0x88, 0xbb, 0xdb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, 0x93, 0xf2, 0xae, 0x97, 0x6c, 0x2c, + 0x61, 0x9e, 0x32, 0x2b, 0x87, 0xd6, 0x81, 0x9d, 0xfd, 0x63, 0xfa, 0x1f, 0xc9, 0xf7, 0x9b, 0xfc, 0x7c, 0xb7, 0x46, + 0x14, 0x98, 0x91, 0x57, 0xf4, 0x3e, 0x07, 0xa0, 0xde, 0x40, 0x24, 0x97, 0xe5, 0x3d, 0x5c, 0xd4, 0x3d, 0xfc, 0x65, + 0x2e, 0x1a, 0x1f, 0x78, 0xcc, 0x57, 0x94, 0xdb, 0x0f, 0x1b, 0x1e, 0x08, 0x44, 0xee, 0x02, 0x23, 0x4c, 0xff, 0x3e, + 0x39, 0xe6, 0xe3, 0xa9, 0xf0, 0xca, 0xab, 0x17, 0xb0, 0xea, 0x89, 0x0f, 0xaf, 0xcf, 0xb0, 0xb5, 0xff, 0x44, 0x66, + 0x15, 0x97, 0x60, 0x66, 0xb0, 0xa8, 0xb8, 0x5f, 0x73, 0x65, 0x07, 0x17, 0xad, 0xee, 0x3b, 0x19, 0xff, 0x7c, 0x19, + 0xee, 0xbe, 0x7e, 0xee, 0x14, 0x8d, 0x73, 0x78, 0x8f, 0x71, 0xc4, 0x35, 0x2e, 0xe1, 0xed, 0xc7, 0x67, 0x55, 0x37, + 0xf7, 0x8c, 0x7d, 0xd6, 0x74, 0x63, 0x55, 0x33, 0xb4, 0x21, 0x71, 0xfe, 0xc3, 0xd6, 0x5f, 0x2c, 0xbc, 0xd8, 0xfd, + 0xc4, 0x4e, 0x8a, 0xac, 0x0b, 0x5a, 0xb7, 0x5d, 0xab, 0xf2, 0x83, 0x01, 0x97, 0x3a, 0x1e, 0x4b, 0xb6, 0x3a, 0xbb, + 0x5f, 0x8c, 0x3f, 0x9a, 0x09, 0xb4, 0x3f, 0xfa, 0xe0, 0x66, 0x09, 0x55, 0x7b, 0x9c, 0xd1, 0xdd, 0xb7, 0x3f, 0x7b, + 0x39, 0x76, 0x59, 0x9a, 0xf8, 0xdc, 0x27, 0xc7, 0xc8, 0x13, 0xe9, 0x2d, 0xb4, 0x0a, 0xc3, 0xf4, 0xdc, 0x3d, 0x44, + 0x6a, 0x91, 0x2c, 0x3d, 0x7b, 0x0b, 0x97, 0x9c, 0xd0, 0x99, 0x7e, 0x29, 0x09, 0x75, 0xdb, 0x6b, 0xc5, 0x25, 0x62, + 0x7e, 0x8d, 0xd4, 0xc0, 0x55, 0x12, 0x3c, 0x44, 0x44, 0xa0, 0xb3, 0x17, 0xe5, 0x33, 0x45, 0x75, 0x85, 0x57, 0x7f, + 0x8d, 0xb2, 0x80, 0x57, 0x66, 0xe3, 0x61, 0xe5, 0x4c, 0x1f, 0x9d, 0xd6, 0x59, 0xae, 0xcb, 0x00, 0x72, 0x71, 0x01, + 0x4e, 0xec, 0xdf, 0x72, 0x06, 0xc3, 0xda, 0x86, 0xfb, 0x23, 0x35, 0x1a, 0xa3, 0xe4, 0x1b, 0x02, 0x30, 0x0a, 0x8a, + 0x36, 0xb3, 0xef, 0x36, 0xa4, 0x0b, 0x19, 0xd5, 0xfb, 0xfd, 0xf7, 0xfc, 0xe5, 0xd1, 0x77, 0xbe, 0x5d, 0x7a, 0xad, + 0x85, 0x49, 0x65, 0x91, 0xad, 0xa3, 0x83, 0xec, 0xae, 0x87, 0x6d, 0x90, 0xdf, 0x74, 0x9f, 0x49, 0x37, 0x2f, 0x06, + 0xd8, 0xd2, 0xf6, 0x23, 0x32, 0x8d, 0x24, 0x51, 0xc8, 0xb1, 0x96, 0x22, 0xa8, 0x65, 0x20, 0x15, 0x47, 0x0e, 0x0f, + 0x4f, 0x46, 0xbe, 0x99, 0x33, 0x0e, 0x2d, 0x69, 0x0b, 0xd8, 0x18, 0xd6, 0xdd, 0xd7, 0x52, 0x9b, 0x65, 0xd6, 0xab, + 0x47, 0x76, 0x22, 0xbc, 0xe0, 0x08, 0x4a, 0xec, 0x53, 0x48, 0x0b, 0xab, 0xb1, 0x0c, 0x6e, 0x5e, 0x4f, 0x28, 0xa0, + 0x6d, 0x2e, 0x9d, 0x53, 0xab, 0xc8, 0x57, 0xfc, 0x7c, 0x58, 0x83, 0x21, 0xf9, 0xd6, 0x4a, 0xc1, 0xc6, 0xae, 0x55, + 0xa5, 0xf1, 0x1c, 0x6f, 0x68, 0x52, 0x1c, 0x1d, 0xed, 0x51, 0x76, 0x08, 0x47, 0x63, 0x70, 0x73, 0x6f, 0xa8, 0xa4, + 0x4c, 0x63, 0xdf, 0x4b, 0xd2, 0xbf, 0xea, 0xcb, 0x50, 0x25, 0x24, 0x8a, 0xf9, 0x1f, 0x54, 0x63, 0x0e, 0x3c, 0x52, + 0x1f, 0xbd, 0xc8, 0x04, 0xa3, 0x85, 0x42, 0x74, 0x83, 0x87, 0x9d, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xd2, 0xbd, + 0x24, 0x9a, 0x17, 0xfe, 0xd9, 0x6f, 0x9e, 0x7b, 0x01, 0xd0, 0x29, 0x2c, 0x9d, 0x31, 0x70, 0xca, 0x9a, 0x74, 0xa4, + 0xe0, 0xd6, 0x68, 0xa0, 0x09, 0x6c, 0xc1, 0xd3, 0xa9, 0x0c, 0xb9, 0x28, 0x67, 0x96, 0xf4, 0x64, 0x17, 0x53, 0x6a, + 0xcd, 0xf7, 0x85, 0xb2, 0xb0, 0x7e, 0xb7, 0x79, 0x94, 0x3b, 0x47, 0x66, 0x25, 0x82, 0x45, 0x9e, 0x02, 0xaf, 0x5c, + 0xde, 0x78, 0xd1, 0xe8, 0x39, 0x78, 0x99, 0x9a, 0x79, 0x0e, 0x07, 0x79, 0xe9, 0x2f, 0xbc, 0x78, 0xfb, 0x7e, 0x0f, + 0xfa, 0x1a, 0xb9, 0x0a, 0x8b, 0xa8, 0x07, 0xe4, 0xbc, 0xe3, 0xa8, 0xbb, 0xfb, 0xe0, 0x93, 0x8e, 0x97, 0x5c, 0x35, + 0x3e, 0x84, 0xbf, 0xa4, 0xd1, 0x17, 0x92, 0xa0, 0x39, 0x15, 0x52, 0x60, 0xe0, 0xaf, 0x5b, 0xd8, 0xf8, 0x3e, 0x4b, + 0xb7, 0x23, 0x26, 0x7f, 0xf5, 0xbe, 0xd2, 0x93, 0x5d, 0x8f, 0x49, 0x3d, 0x05, 0x8a, 0x3a, 0x3b, 0x5a, 0x36, 0x23, + 0xad, 0xd4, 0xbc, 0x5b, 0xb8, 0xf5, 0x81, 0x4f, 0xe9, 0xc0, 0x8e, 0x02, 0x77, 0x41, 0x2c, 0x9e, 0x71, 0x7e, 0x6d, + 0x66, 0xb7, 0x3e, 0xfb, 0x2e, 0x03, 0x8c, 0x5a, 0x4f, 0xf4, 0x41, 0x10, 0xdf, 0x67, 0x47, 0xac, 0xbb, 0x04, 0x96, + 0x60, 0x4c, 0x4f, 0xdb, 0x24, 0x9c, 0x96, 0xfb, 0x64, 0x7e, 0xc8, 0xc6, 0x04, 0x8a, 0x4a, 0x31, 0x57, 0x81, 0x4f, + 0x26, 0x40, 0xcc, 0x21, 0x25, 0xdb, 0xab, 0x33, 0xf9, 0x44, 0xcc, 0x85, 0x2a, 0x45, 0x73, 0x31, 0x02, 0x42, 0x90, + 0xc3, 0x8c, 0xed, 0x3f, 0xc2, 0x85, 0x08, 0x70, 0x87, 0x83, 0x2c, 0x73, 0xde, 0xe0, 0xaa, 0xcc, 0x2f, 0x00, 0x73, + 0x19, 0xea, 0xad, 0xc6, 0x4e, 0x8f, 0x61, 0xf9, 0x7d, 0x1a, 0x64, 0xbd, 0x22, 0x77, 0x61, 0x19, 0xc2, 0xeb, 0xa2, + 0x54, 0x8d, 0x40, 0xba, 0x3b, 0x8c, 0xd3, 0xaf, 0x20, 0x61, 0xfa, 0x59, 0x02, 0x9e, 0xa3, 0x38, 0x11, 0x0b, 0xfe, + 0xdc, 0xd0, 0xa5, 0x13, 0xe4, 0x80, 0xa1, 0x1e, 0x9e, 0x5e, 0x51, 0xf7, 0x92, 0x1d, 0xdd, 0x6d, 0x59, 0xa5, 0xec, + 0x6f, 0x27, 0xf2, 0x63, 0xd9, 0x39, 0x5e, 0xf2, 0xa6, 0xbb, 0x89, 0xdf, 0x22, 0x8e, 0x02, 0x88, 0x63, 0x55, 0x76, + 0xa1, 0x4a, 0x44, 0xbe, 0x2e, 0x9c, 0x39, 0xe5, 0x79, 0x64, 0xc9, 0xce, 0xdb, 0xdd, 0x77, 0xa6, 0xd8, 0x91, 0x66, + 0x76, 0xce, 0x7b, 0xc5, 0x4f, 0x95, 0x12, 0xd3, 0x37, 0x0e, 0xce, 0xfd, 0x9d, 0xf4, 0xfd, 0xf1, 0x70, 0x2c, 0xb1, + 0x9e, 0x5f, 0x73, 0xd5, 0xf6, 0x94, 0xaa, 0x65, 0xad, 0xbf, 0x53, 0xbe, 0xa6, 0x6c, 0xdd, 0xec, 0x67, 0xb0, 0x23, + 0xd7, 0xcc, 0x97, 0x2e, 0xa4, 0x77, 0x7d, 0x39, 0xc9, 0xae, 0x0a, 0xec, 0xd1, 0x07, 0x06, 0xd0, 0xb4, 0xae, 0x0c, + 0xc5, 0x57, 0x6a, 0x19, 0xb9, 0x4c, 0x80, 0xd7, 0xc1, 0x4f, 0x5f, 0xcc, 0x7c, 0x39, 0x66, 0xab, 0x77, 0xde, 0x1f, + 0x31, 0x2f, 0xba, 0xb3, 0xe7, 0x7a, 0x87, 0xb8, 0x18, 0xe7, 0x7d, 0x07, 0x66, 0xe9, 0xb7, 0x1e, 0xf3, 0x79, 0x7f, + 0x9d, 0x60, 0x7f, 0x64, 0x45, 0x30, 0xc8, 0xe0, 0xae, 0x7a, 0xc1, 0x71, 0x16, 0x86, 0x68, 0xda, 0x76, 0x5f, 0xd4, + 0xcc, 0x6d, 0x49, 0xd3, 0xe7, 0xbc, 0xa5, 0x12, 0xf6, 0x8b, 0x3b, 0xce, 0xac, 0xef, 0xbc, 0x83, 0xac, 0xb5, 0xea, + 0xd0, 0xaf, 0x48, 0xbd, 0x0c, 0xeb, 0x3f, 0x81, 0x62, 0xbc, 0xec, 0xb0, 0xda, 0x5a, 0x69, 0x7a, 0xae, 0xca, 0xde, + 0xe1, 0x49, 0x05, 0xa0, 0x14, 0x01, 0x9d, 0x75, 0xe3, 0xb8, 0x9b, 0x02, 0xf5, 0xc5, 0x29, 0xda, 0xf5, 0xf7, 0xd7, + 0xc0, 0x28, 0x88, 0xd4, 0xf7, 0xab, 0xbc, 0x27, 0xfd, 0x95, 0xf8, 0x58, 0x78, 0x45, 0xa1, 0xdb, 0xf2, 0xf8, 0x2f, + 0x8a, 0x94, 0xe9, 0x27, 0x21, 0xdc, 0xf9, 0xb9, 0xba, 0x85, 0x89, 0xf9, 0x74, 0xe9, 0xf9, 0x3d, 0x5a, 0x87, 0x2b, + 0x68, 0x7d, 0xe6, 0x07, 0x69, 0xcc, 0xff, 0x39, 0x56, 0x59, 0xe2, 0x1d, 0x9a, 0xe5, 0xdb, 0x04, 0xc7, 0x74, 0x78, + 0x4a, 0x3a, 0xcf, 0x71, 0x42, 0xa1, 0x1b, 0x94, 0x7a, 0xa7, 0x0e, 0x35, 0x93, 0xc0, 0x42, 0x81, 0x93, 0x7e, 0x44, + 0xf3, 0xa8, 0x38, 0x12, 0xc0, 0xc8, 0xf4, 0xfa, 0xdb, 0x5c, 0x5b, 0xe4, 0xc3, 0x5e, 0xfb, 0x65, 0xe3, 0x5e, 0x1f, + 0x05, 0xc9, 0x7f, 0xc7, 0x01, 0x12, 0x6b, 0x43, 0xf6, 0x26, 0x60, 0x19, 0x51, 0xcc, 0x51, 0xf0, 0x6d, 0x41, 0x52, + 0xa8, 0x54, 0x82, 0x0b, 0x7b, 0x84, 0x85, 0x4b, 0x2d, 0x2d, 0x63, 0x2d, 0x3c, 0x6f, 0x01, 0x3a, 0x3a, 0x7c, 0x5d, + 0x7c, 0x97, 0x9d, 0x5e, 0x0c, 0x92, 0x73, 0x8f, 0x10, 0x24, 0xa8, 0xc7, 0x45, 0x09, 0xb8, 0x6f, 0x56, 0xe3, 0x6b, + 0x41, 0x4d, 0x9a, 0xd4, 0x5d, 0x05, 0xa7, 0xbb, 0x50, 0xc0, 0x65, 0x74, 0xd6, 0x40, 0xd0, 0xf0, 0xdd, 0x91, 0x0c, + 0xb0, 0x2a, 0x48, 0x90, 0xb8, 0xe4, 0x87, 0xc4, 0x4a, 0x45, 0x77, 0x78, 0x47, 0x63, 0xbc, 0xa3, 0xb6, 0x2e, 0x3b, + 0xed, 0x6b, 0xef, 0x36, 0x0c, 0xc2, 0x88, 0xf1, 0x99, 0x81, 0x8e, 0xec, 0xed, 0x80, 0x4d, 0x9e, 0x9d, 0xb0, 0x01, + 0x8f, 0xe5, 0x8e, 0x8c, 0xd6, 0xf9, 0x35, 0xcb, 0x17, 0x7b, 0xda, 0xe7, 0x9e, 0x84, 0x8c, 0x8d, 0x23, 0x70, 0xa3, + 0x06, 0x64, 0x4a, 0x98, 0x25, 0xfc, 0xc8, 0xa1, 0xfa, 0x2c, 0x09, 0xfe, 0x2b, 0x6d, 0x40, 0x01, 0x39, 0xda, 0x93, + 0x4a, 0x92, 0x79, 0x0c, 0xb3, 0x26, 0x85, 0x0f, 0xc8, 0x50, 0xe6, 0xf8, 0x69, 0xa8, 0x29, 0xd6, 0x89, 0xa1, 0x1a, + 0x99, 0x26, 0x86, 0xef, 0x1a, 0xf3, 0x57, 0xdc, 0xfc, 0xd9, 0xab, 0xaa, 0xa7, 0x43, 0xf0, 0x10, 0x4a, 0x09, 0xca, + 0xcd, 0x4c, 0x28, 0x03, 0xe8, 0x17, 0x69, 0xb2, 0x01, 0xad, 0x1f, 0xa1, 0xc3, 0xf7, 0x9b, 0x23, 0x38, 0xb9, 0x2c, + 0x55, 0x58, 0x17, 0x3f, 0xfe, 0x4a, 0x60, 0xef, 0xdd, 0x61, 0xba, 0x51, 0xce, 0xe6, 0xd4, 0x96, 0x4c, 0x5d, 0xf0, + 0x75, 0xb9, 0x3e, 0x09, 0x5e, 0x59, 0x20, 0x35, 0x0b, 0xab, 0x75, 0xe2, 0x12, 0x59, 0xb4, 0x38, 0x4d, 0xde, 0xcd, + 0x5f, 0x9e, 0x66, 0x13, 0xaf, 0x5c, 0x0a, 0x4c, 0x7e, 0x16, 0x55, 0xe2, 0x22, 0xb3, 0x5c, 0x36, 0xfc, 0xcd, 0x01, + 0x9f, 0x67, 0x7d, 0x3d, 0xf0, 0xbb, 0xfe, 0x5c, 0xdf, 0x1e, 0xf2, 0x90, 0x50, 0x8b, 0xdb, 0x1a, 0x67, 0x4e, 0x8d, + 0x6d, 0xe6, 0xbd, 0x5d, 0xda, 0xc7, 0x71, 0xcc, 0x7c, 0x44, 0x45, 0xba, 0xa2, 0x24, 0xec, 0x4e, 0x87, 0xa4, 0x53, + 0x4c, 0x56, 0x9c, 0x39, 0xf5, 0x54, 0xb8, 0x2d, 0xce, 0x6b, 0x7c, 0xb8, 0x44, 0x74, 0x82, 0xa9, 0x03, 0x24, 0xd7, + 0xb1, 0x25, 0xb8, 0xab, 0x08, 0x5c, 0x9a, 0x5a, 0xa8, 0xa2, 0x78, 0xc6, 0x59, 0xec, 0x16, 0x52, 0xf3, 0x53, 0xf5, + 0xb8, 0xd4, 0xad, 0x2a, 0xe1, 0x95, 0x6c, 0x85, 0x29, 0x90, 0xc9, 0x8a, 0xa4, 0x39, 0x89, 0x15, 0x0e, 0xfa, 0x9e, + 0x43, 0x92, 0xbd, 0x58, 0xf6, 0xb6, 0x7f, 0xeb, 0x6a, 0xcd, 0x0a, 0xa3, 0x5d, 0xac, 0x16, 0xc5, 0x8b, 0x54, 0x6d, + 0x1f, 0xa8, 0xbb, 0xca, 0x7d, 0xc7, 0x40, 0xa3, 0x46, 0x2a, 0x5b, 0x51, 0x47, 0x6a, 0x78, 0xcc, 0x5f, 0x9b, 0xe9, + 0x88, 0x31, 0x6c, 0xd8, 0xd1, 0x41, 0xb3, 0xb9, 0x0c, 0x8a, 0xa9, 0xc5, 0x61, 0x54, 0x1a, 0xba, 0x8d, 0xc8, 0x57, + 0x28, 0xcf, 0xec, 0x1b, 0x63, 0x43, 0x2c, 0xd9, 0x53, 0xbc, 0x06, 0xc2, 0x24, 0xa5, 0xcf, 0x62, 0x8b, 0xc2, 0xa6, + 0xcd, 0xed, 0x99, 0x63, 0x03, 0x0e, 0xae, 0x92, 0x52, 0xa6, 0xab, 0xc2, 0xab, 0x40, 0x29, 0xac, 0x44, 0x67, 0x09, + 0x21, 0x63, 0x9e, 0xbd, 0xf3, 0x53, 0xd3, 0x73, 0x8f, 0x80, 0x68, 0xf6, 0x05, 0x1c, 0x05, 0x1f, 0xc4, 0x88, 0x8f, + 0x34, 0xe4, 0x1c, 0xbe, 0x72, 0x98, 0xbe, 0xb7, 0x85, 0xe4, 0x47, 0x3f, 0x1f, 0x2f, 0x94, 0x29, 0x49, 0xb5, 0x83, + 0xd0, 0x06, 0x12, 0x67, 0x80, 0x78, 0x96, 0x81, 0x25, 0x28, 0x8d, 0x01, 0x83, 0x83, 0xcf, 0x47, 0xbb, 0x22, 0xd4, + 0x12, 0xa1, 0xbb, 0x2c, 0x5d, 0x80, 0xb3, 0x6e, 0x90, 0xd1, 0x26, 0xf6, 0x70, 0x7f, 0xe1, 0x80, 0xee, 0xc4, 0xe0, + 0xc8, 0xc9, 0xec, 0xb2, 0x25, 0xc1, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, 0x25, 0x52, 0x21, 0xde, 0x58, 0x3a, 0xc0, 0x4c, + 0xa1, 0x3d, 0x55, 0xeb, 0x8e, 0x48, 0xf1, 0x1b, 0xe0, 0x41, 0x34, 0x42, 0x03, 0x47, 0xa2, 0x7e, 0x1e, 0xa3, 0x25, + 0xc6, 0x23, 0xce, 0x7f, 0x4c, 0x2d, 0x07, 0x93, 0x04, 0x72, 0x18, 0xed, 0x1e, 0x3b, 0x13, 0x8a, 0xb3, 0x9d, 0xb4, + 0x6c, 0x3d, 0xfd, 0xdc, 0xa6, 0x0f, 0x66, 0xef, 0x15, 0xde, 0x10, 0x5c, 0x28, 0xfa, 0xcb, 0x2d, 0xcf, 0x30, 0x02, + 0x0c, 0x86, 0xdd, 0x60, 0xfe, 0xfd, 0xe9, 0x24, 0x3a, 0x3c, 0xaa, 0x1f, 0xae, 0x7a, 0x3b, 0x98, 0x3a, 0x93, 0xc1, + 0xf9, 0xe4, 0x97, 0x89, 0xbb, 0xef, 0x44, 0xf2, 0xc5, 0x94, 0x79, 0x8e, 0x7c, 0xd2, 0x09, 0xcc, 0x76, 0x0d, 0xa3, + 0x9a, 0x5a, 0x02, 0x91, 0x88, 0xa9, 0xd0, 0x8d, 0x94, 0xf3, 0x72, 0x7b, 0x4b, 0xe1, 0xfb, 0x6d, 0xaa, 0x52, 0xa5, + 0x46, 0x11, 0x96, 0x9b, 0xf4, 0x83, 0x83, 0xee, 0xf7, 0xa5, 0xbc, 0x5c, 0x4e, 0x6b, 0x91, 0xc7, 0x43, 0x21, 0xea, + 0x7c, 0xa4, 0xbd, 0x7f, 0xa2, 0xf3, 0x33, 0x49, 0xc8, 0xae, 0xff, 0x54, 0x11, 0x60, 0xfc, 0x15, 0xa2, 0xae, 0x4d, + 0x32, 0xa8, 0xd4, 0x4b, 0x2b, 0xbc, 0x83, 0xaf, 0x88, 0xdc, 0x0a, 0xfa, 0x95, 0x51, 0xe5, 0xad, 0x57, 0x6d, 0x97, + 0xb3, 0x2f, 0xb0, 0x60, 0xd3, 0x9a, 0x0e, 0x5e, 0xf9, 0xeb, 0xe0, 0xa8, 0xa0, 0x37, 0x9c, 0x3a, 0x23, 0xf5, 0x10, + 0xef, 0xe7, 0x02, 0x05, 0x27, 0xc4, 0x3f, 0x0a, 0x86, 0x46, 0xe9, 0x5a, 0x6a, 0x63, 0x6c, 0x0f, 0x98, 0xaf, 0x57, + 0x95, 0x71, 0x95, 0xdd, 0x09, 0x1e, 0x3b, 0x37, 0x3e, 0x85, 0x91, 0xb4, 0x3c, 0xc0, 0x39, 0xab, 0x43, 0x07, 0xce, + 0x6b, 0xf6, 0x85, 0x6a, 0x3d, 0x14, 0x33, 0x12, 0x6d, 0x4d, 0xb0, 0x8c, 0x3c, 0x9b, 0xb5, 0xe7, 0xa9, 0x49, 0x66, + 0x35, 0xd2, 0x66, 0x7c, 0x6a, 0xfa, 0xaf, 0x01, 0xb1, 0x1e, 0x74, 0xf9, 0x6d, 0xa5, 0xfa, 0x5a, 0x21, 0xeb, 0x11, + 0xc7, 0x4a, 0x95, 0x6d, 0x83, 0x63, 0x07, 0x6e, 0x35, 0x1e, 0x0f, 0xbe, 0x17, 0xd2, 0x58, 0x9d, 0x04, 0x2e, 0x9d, + 0x50, 0xf9, 0x86, 0x2b, 0x06, 0x76, 0x12, 0xdd, 0x2c, 0x17, 0x51, 0x22, 0x45, 0xfe, 0x36, 0x70, 0x8a, 0xe1, 0x50, + 0x08, 0x0f, 0xe2, 0xdf, 0x24, 0x09, 0xf3, 0x3a, 0x52, 0x9d, 0x58, 0xed, 0xe0, 0x7a, 0x95, 0x1e, 0x05, 0x07, 0x6b, + 0xaa, 0xa4, 0x0d, 0x25, 0xea, 0x52, 0x8f, 0x61, 0x4d, 0x0f, 0x87, 0x7a, 0x71, 0xe3, 0x70, 0xe5, 0x63, 0xcd, 0xa2, + 0xf5, 0x17, 0x35, 0x1c, 0xab, 0x11, 0x36, 0x53, 0x11, 0xcd, 0xec, 0xff, 0x88, 0x2b, 0x1d, 0xb2, 0x0b, 0x80, 0xda, + 0x8f, 0xf8, 0x06, 0x55, 0x31, 0x02, 0xb4, 0x9f, 0x96, 0x6f, 0xa4, 0x3e, 0xe5, 0x19, 0x8b, 0xeb, 0x16, 0x51, 0xe4, + 0x22, 0x18, 0x6b, 0x8a, 0x0d, 0x00, 0x61, 0xd9, 0x02, 0x1b, 0x88, 0xa2, 0x59, 0x94, 0x4d, 0xdd, 0x60, 0xb7, 0x78, + 0x01, 0xd1, 0x9a, 0xc7, 0x67, 0x62, 0xcd, 0x9c, 0x1b, 0xa9, 0x2c, 0x2b, 0x7c, 0xff, 0xea, 0x8a, 0xb9, 0x42, 0x83, + 0xf7, 0xf6, 0xdc, 0xca, 0x1e, 0x9d, 0x0f, 0x76, 0x33, 0xfd, 0x0b, 0xbb, 0x0e, 0x6f, 0xd9, 0x26, 0xcc, 0x08, 0x9f, + 0xdc, 0x3e, 0xfe, 0x8a, 0x35, 0xe1, 0xfc, 0x47, 0x51, 0x31, 0x28, 0x5c, 0x41, 0xb0, 0xa8, 0x35, 0xe3, 0x94, 0xc2, + 0x63, 0x1f, 0xa8, 0xd0, 0x1e, 0x24, 0x26, 0x08, 0xa3, 0x2a, 0x53, 0x25, 0xb2, 0xe7, 0xe2, 0x57, 0x6d, 0x22, 0x83, + 0xc9, 0x38, 0x94, 0x0d, 0xdc, 0xd4, 0xae, 0x39, 0x33, 0x3b, 0x4b, 0xeb, 0xdf, 0x6b, 0x8e, 0x75, 0x58, 0xb0, 0x44, + 0x6b, 0xa8, 0x99, 0x5e, 0x56, 0x2d, 0xc2, 0x5b, 0xc3, 0x74, 0x78, 0x08, 0x52, 0xcb, 0x22, 0xe1, 0x0f, 0xdd, 0x77, + 0xd0, 0x22, 0x18, 0xa3, 0x11, 0x58, 0x19, 0xa7, 0x90, 0xeb, 0xfc, 0x38, 0x25, 0x0a, 0xd4, 0xb2, 0xde, 0x67, 0x2c, + 0x73, 0xe4, 0x35, 0x2b, 0xf3, 0x34, 0x2b, 0x7a, 0x8f, 0xb2, 0xa1, 0xe3, 0xfa, 0x73, 0x26, 0x1a, 0x49, 0x87, 0x86, + 0x3a, 0x1d, 0xe7, 0xc4, 0x95, 0x35, 0x47, 0x53, 0x24, 0xb7, 0xf5, 0x40, 0xda, 0xcd, 0x6c, 0x25, 0x4c, 0xb6, 0xd8, + 0x6c, 0x46, 0xd8, 0xee, 0x68, 0xec, 0x33, 0x4f, 0x1c, 0xd7, 0x10, 0x3d, 0xd0, 0xe6, 0xce, 0x4b, 0x6e, 0x5c, 0xfc, + 0xef, 0xa0, 0x88, 0x6e, 0x1e, 0x8e, 0x08, 0xe6, 0x72, 0x4e, 0x51, 0x3c, 0xdd, 0x1c, 0x87, 0xc0, 0x86, 0xf5, 0x9f, + 0x9b, 0xe8, 0x4a, 0x8e, 0xe7, 0xa8, 0xd2, 0x23, 0x05, 0x71, 0x62, 0x7b, 0x76, 0x0d, 0x49, 0xfb, 0x11, 0x09, 0xcf, + 0x29, 0xeb, 0x6c, 0x74, 0xae, 0x73, 0x5d, 0x7a, 0x1f, 0x7f, 0x25, 0x3d, 0x21, 0x08, 0x0c, 0xf3, 0xa7, 0xb8, 0x9f, + 0xc0, 0x8a, 0x0b, 0xab, 0x52, 0xae, 0x78, 0xe1, 0x5f, 0x73, 0xc6, 0xf7, 0xb4, 0x2a, 0x2b, 0xd9, 0x71, 0x79, 0xa5, + 0x73, 0xd6, 0x50, 0xa5, 0x63, 0xa6, 0xcb, 0x8a, 0xc5, 0xf4, 0x8e, 0xfd, 0xba, 0x36, 0x04, 0x34, 0x74, 0xe7, 0xdc, + 0x51, 0x31, 0x93, 0xe0, 0x69, 0x88, 0xa5, 0x52, 0x80, 0xae, 0xd0, 0x67, 0xe6, 0xe4, 0x9b, 0x61, 0x1e, 0x0c, 0xf9, + 0x59, 0x00, 0x08, 0x57, 0x26, 0xa8, 0xac, 0xc0, 0xb3, 0xe2, 0x5a, 0xd1, 0x79, 0x0d, 0xe6, 0x22, 0xa2, 0xde, 0x6b, + 0xa4, 0xff, 0x00, 0x09, 0x97, 0x60, 0x2f, 0x05, 0x2e, 0x06, 0x74, 0xf9, 0xcc, 0x1d, 0x5a, 0x97, 0x08, 0x31, 0xd6, + 0x80, 0xa4, 0xb6, 0xf1, 0xcb, 0xc5, 0x84, 0x7b, 0xde, 0xcf, 0x03, 0xce, 0xba, 0x7e, 0x06, 0x90, 0x07, 0xf9, 0xf3, + 0x57, 0xb7, 0x72, 0x39, 0xc8, 0x09, 0x48, 0x5c, 0x5c, 0xb8, 0xf2, 0x88, 0x76, 0x4e, 0x8b, 0xb6, 0xcc, 0xd5, 0x28, + 0xe3, 0xb6, 0x06, 0x29, 0x52, 0xb8, 0xd8, 0x48, 0xfb, 0x18, 0xb8, 0x20, 0xe9, 0x89, 0x0d, 0x85, 0x84, 0x1d, 0xbb, + 0xf6, 0x62, 0x2a, 0xb7, 0x33, 0xea, 0x06, 0xfa, 0x62, 0xeb, 0x6f, 0x34, 0xfe, 0xb4, 0xb1, 0x76, 0xa6, 0xef, 0x19, + 0x5c, 0x11, 0xa9, 0x46, 0x9f, 0x57, 0x58, 0x7d, 0xda, 0xef, 0xca, 0x1d, 0xac, 0xd6, 0x97, 0xd1, 0x57, 0x15, 0x1b, + 0xf5, 0x89, 0x0d, 0x82, 0x49, 0x92, 0x54, 0x72, 0x6b, 0x50, 0x52, 0xd0, 0x98, 0xb7, 0x51, 0x43, 0x56, 0x4a, 0x6b, + 0x26, 0x7b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, 0xb1, 0xa5, 0x3e, 0x79, 0xf4, 0xc4, 0x5b, 0xeb, 0xf7, + 0x9c, 0xa1, 0x63, 0xf6, 0x00, 0x81, 0x42, 0x60, 0x5e, 0xba, 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xcb, 0x7f, + 0x66, 0x57, 0xba, 0xc0, 0xd8, 0x27, 0x82, 0xfe, 0x5c, 0xda, 0xed, 0xd4, 0x37, 0x66, 0xef, 0x06, 0x9c, 0x06, 0x98, + 0xb9, 0x78, 0x53, 0xe9, 0xdd, 0xd5, 0xe6, 0x11, 0x0b, 0x60, 0x72, 0x36, 0xfa, 0x97, 0xa6, 0x22, 0xf8, 0xcb, 0xa3, + 0xb3, 0x17, 0xeb, 0x23, 0x0a, 0x05, 0x5f, 0x46, 0x23, 0xde, 0x65, 0xf4, 0x2f, 0x1a, 0x5a, 0xff, 0x03, 0xfb, 0x60, + 0x1b, 0x97, 0x61, 0x0f, 0xed, 0xc3, 0x24, 0x76, 0x45, 0xd0, 0xd6, 0xc6, 0x82, 0x20, 0x6b, 0xea, 0x72, 0x60, 0x44, + 0x8a, 0xdf, 0x5a, 0x27, 0x9d, 0xd7, 0xb1, 0xef, 0xda, 0x89, 0xf3, 0x21, 0x11, 0x23, 0xf0, 0x5b, 0xf4, 0x7c, 0x24, + 0xa1, 0x82, 0x4b, 0x47, 0x2f, 0x13, 0x3c, 0xea, 0x12, 0x27, 0xd5, 0xae, 0x97, 0xa3, 0xf6, 0xcf, 0xfa, 0x66, 0x3f, + 0x18, 0x94, 0xae, 0x1b, 0x86, 0x6f, 0xe9, 0xb5, 0xcc, 0x91, 0x87, 0x77, 0x7d, 0xa3, 0xb5, 0x05, 0xd6, 0xba, 0x6c, + 0x0b, 0x45, 0x9d, 0xf0, 0xfa, 0x5d, 0xe3, 0xf8, 0xbf, 0x94, 0x59, 0xc1, 0x50, 0x98, 0xcc, 0x44, 0xbd, 0xd9, 0x82, + 0x74, 0x16, 0x7a, 0x7b, 0xd7, 0xbf, 0x54, 0x9a, 0x03, 0xb6, 0x98, 0x31, 0x38, 0xd5, 0x83, 0x66, 0xf0, 0x12, 0x0a, + 0x84, 0xb9, 0x77, 0x86, 0xce, 0xa0, 0xfb, 0xd5, 0x09, 0xca, 0x44, 0x31, 0xe8, 0x59, 0x0a, 0x25, 0x6d, 0x42, 0x6a, + 0xdd, 0xef, 0x0d, 0x6e, 0x7d, 0xe8, 0xdf, 0xcc, 0x28, 0xa2, 0x51, 0xef, 0x9c, 0x24, 0xa0, 0xe8, 0x15, 0x07, 0x3a, + 0x51, 0xde, 0x6c, 0x89, 0x11, 0xeb, 0x78, 0x9c, 0xe4, 0xea, 0xe0, 0xf1, 0x4a, 0xc9, 0xf1, 0xaa, 0x10, 0x7a, 0x0e, + 0x60, 0x88, 0x23, 0x70, 0x2f, 0x87, 0x05, 0x74, 0x01, 0xcf, 0xf4, 0x8e, 0x7a, 0x36, 0x73, 0xb4, 0xfb, 0x7f, 0x97, + 0x7b, 0xd4, 0x5b, 0x3c, 0xdb, 0x24, 0x0e, 0x58, 0xd6, 0x34, 0x02, 0xdf, 0xfc, 0xf4, 0xae, 0xd6, 0x63, 0xc9, 0x9b, + 0x2d, 0x95, 0x39, 0xd8, 0x10, 0x5d, 0xa7, 0x45, 0xd2, 0xa7, 0x5c, 0x1d, 0xdb, 0x14, 0x50, 0xc3, 0xfd, 0xb4, 0x73, + 0x45, 0x78, 0x9c, 0xb0, 0x86, 0x73, 0x2a, 0x1c, 0x76, 0x70, 0xb4, 0x11, 0x46, 0x37, 0xe4, 0x18, 0x4b, 0xea, 0x20, + 0xbe, 0x1d, 0xe0, 0x13, 0x7c, 0xbf, 0x30, 0xca, 0x97, 0x0e, 0xf1, 0x47, 0x06, 0x8d, 0x0e, 0x72, 0x89, 0x95, 0x3c, + 0x61, 0xea, 0xaf, 0x95, 0xda, 0xca, 0x75, 0xb9, 0xb9, 0xb7, 0x57, 0xb7, 0x92, 0x59, 0x38, 0xc9, 0x28, 0x3e, 0x92, + 0x1e, 0xd5, 0x2b, 0xf9, 0xcf, 0xed, 0xc6, 0x20, 0x99, 0xb9, 0xbd, 0x7b, 0x27, 0x30, 0x76, 0xa8, 0x74, 0xa2, 0xe0, + 0x5f, 0x22, 0xe1, 0x67, 0xa3, 0x11, 0x29, 0x28, 0x2c, 0xb9, 0x0a, 0x55, 0x68, 0x9f, 0xb9, 0xe9, 0xa5, 0xa2, 0x72, + 0x8c, 0x51, 0x31, 0x9b, 0xf1, 0x8b, 0xa1, 0x1a, 0x23, 0xf5, 0xd3, 0x9c, 0x6d, 0xbf, 0xf5, 0x44, 0xaf, 0x45, 0x73, + 0x20, 0x09, 0x1a, 0x57, 0x02, 0x14, 0xe0, 0x10, 0x13, 0x8c, 0xc9, 0x5d, 0x62, 0xd0, 0x34, 0xc3, 0xf3, 0x14, 0xea, + 0x5a, 0x8d, 0x27, 0x95, 0x6f, 0x6d, 0x97, 0x95, 0x54, 0xb6, 0x13, 0xa3, 0x79, 0x27, 0x41, 0xe2, 0xa8, 0x71, 0x8a, + 0x82, 0x55, 0xf5, 0x0c, 0x29, 0xc3, 0x12, 0x20, 0xad, 0x38, 0x87, 0x6f, 0xcf, 0x43, 0x66, 0x17, 0x96, 0xd8, 0x2b, + 0xdd, 0x2c, 0x85, 0x08, 0x6e, 0x17, 0x15, 0x09, 0xb9, 0xbe, 0x65, 0x93, 0x2c, 0x74, 0xe9, 0x5b, 0x67, 0xe8, 0x12, + 0xd2, 0x87, 0x1c, 0xf5, 0xdb, 0xbd, 0x04, 0x9c, 0x20, 0x8c, 0x8d, 0x09, 0xd9, 0x7c, 0xd4, 0x0b, 0xf2, 0x28, 0x6f, + 0x05, 0x8d, 0xab, 0xcd, 0xd2, 0xfb, 0x9f, 0x30, 0x1a, 0xca, 0x65, 0x43, 0x26, 0xb3, 0xa2, 0x83, 0xe6, 0xab, 0x65, + 0x6c, 0x0e, 0x2a, 0xc8, 0x31, 0x27, 0x01, 0x7a, 0x5c, 0x81, 0xe7, 0x96, 0x45, 0xbd, 0x49, 0xf5, 0x67, 0xc5, 0x0b, + 0x5d, 0x83, 0xdd, 0xd7, 0x0e, 0x62, 0xc7, 0x26, 0x53, 0xbb, 0x58, 0x05, 0x4a, 0xe2, 0x88, 0x6e, 0x85, 0x3e, 0x85, + 0x2a, 0x77, 0xa4, 0x10, 0xc3, 0x3a, 0xc0, 0xc2, 0x59, 0xc9, 0x4c, 0xd8, 0x3e, 0xcc, 0xe7, 0x8f, 0x51, 0x6b, 0x01, + 0xd3, 0x43, 0x08, 0xf5, 0xdd, 0x1d, 0xee, 0x28, 0x3a, 0x3a, 0x93, 0xc9, 0x5d, 0x56, 0xc8, 0xa0, 0x5f, 0xf8, 0x58, + 0xc0, 0x05, 0x57, 0xe4, 0x92, 0xb1, 0xa0, 0xe9, 0x14, 0x4c, 0xcb, 0xd4, 0xb9, 0xfc, 0xdd, 0xfb, 0x98, 0x40, 0x2d, + 0x88, 0x45, 0xd3, 0x84, 0x13, 0xd4, 0xd0, 0x1d, 0x44, 0x6b, 0xda, 0x93, 0xc7, 0x8b, 0xec, 0x19, 0xc6, 0xca, 0x09, + 0xfe, 0xd4, 0xe5, 0xba, 0xfa, 0xf2, 0x5d, 0x90, 0x4a, 0xef, 0x8d, 0x4e, 0x4b, 0xd2, 0x3b, 0xca, 0x11, 0xd1, 0xa4, + 0xe3, 0x6f, 0x1f, 0x91, 0xb7, 0x20, 0x13, 0x1b, 0x3e, 0x5c, 0xd6, 0x9a, 0xf7, 0x5f, 0x51, 0xb0, 0x4a, 0x11, 0xce, + 0x7e, 0xa2, 0x49, 0x1c, 0xb2, 0x15, 0x21, 0xed, 0x8b, 0x60, 0xa4, 0xa3, 0x82, 0xd8, 0x8a, 0xed, 0x6a, 0x6d, 0xb9, + 0x87, 0x40, 0xc4, 0x39, 0xb8, 0x42, 0x66, 0x19, 0x9c, 0x63, 0xaf, 0x7e, 0x79, 0x80, 0xe0, 0xf2, 0x14, 0xf5, 0xbf, + 0x5e, 0x16, 0x7e, 0xf4, 0x70, 0xa0, 0x75, 0x64, 0x65, 0x65, 0x4e, 0xbd, 0x54, 0x1f, 0xcb, 0x3a, 0x1e, 0xad, 0xfa, + 0x9a, 0x7e, 0xa3, 0x94, 0x46, 0x9b, 0x41, 0x8b, 0xdb, 0x94, 0x95, 0x1a, 0xc3, 0x9f, 0x59, 0x2d, 0xea, 0xa1, 0xc2, + 0x1d, 0xae, 0x0d, 0xde, 0xb3, 0x77, 0x30, 0x91, 0x22, 0xef, 0xdb, 0x3f, 0x35, 0xb8, 0x21, 0x61, 0x3a, 0xe1, 0x90, + 0x3b, 0x70, 0x05, 0xd3, 0x93, 0x4e, 0xdd, 0x35, 0xc4, 0xd7, 0x22, 0xc9, 0x8e, 0xfe, 0x1b, 0x05, 0xcf, 0x17, 0x32, + 0xd6, 0x84, 0x8c, 0x6e, 0x0b, 0x6b, 0x11, 0x69, 0xa5, 0xc1, 0xc4, 0x18, 0xc5, 0x7c, 0x4a, 0x94, 0x88, 0x65, 0xb7, + 0x25, 0x23, 0xb1, 0xcf, 0xd6, 0x96, 0xbd, 0xd5, 0x4d, 0x4b, 0x82, 0x96, 0xa5, 0x20, 0x5e, 0x2e, 0xcf, 0x44, 0x15, + 0xd0, 0xb5, 0x71, 0x03, 0x22, 0x4e, 0xef, 0xac, 0xf6, 0x16, 0x04, 0xd0, 0x3e, 0xff, 0xfb, 0x4a, 0xe9, 0xe2, 0x56, + 0x85, 0x12, 0x82, 0x1f, 0xb2, 0x4c, 0x96, 0x40, 0x19, 0xe4, 0x63, 0xcb, 0x07, 0xf7, 0x15, 0x56, 0xeb, 0xbb, 0xf5, + 0x10, 0xb1, 0x79, 0x3e, 0x84, 0xb4, 0x83, 0xe1, 0x99, 0x02, 0x4f, 0xf6, 0x2f, 0xdb, 0x87, 0x0d, 0xd0, 0xba, 0xc9, + 0x50, 0x7e, 0x57, 0xaa, 0x89, 0x32, 0x82, 0x8f, 0x5f, 0xed, 0x70, 0x61, 0x43, 0xed, 0xc0, 0x68, 0x1a, 0x76, 0xcb, + 0x3f, 0x20, 0x56, 0x48, 0xe8, 0xea, 0x08, 0x60, 0xeb, 0x32, 0x26, 0x7c, 0xc9, 0xbe, 0x41, 0x18, 0x00, 0x89, 0xdf, + 0xfe, 0xaa, 0x1d, 0x9f, 0x98, 0xeb, 0xf2, 0xfb, 0xb6, 0xbd, 0x4a, 0x44, 0xef, 0x63, 0x27, 0x66, 0x3b, 0xf6, 0x01, + 0x2b, 0x1e, 0x56, 0x8d, 0xe8, 0xd8, 0xf3, 0xa1, 0x70, 0x9f, 0xe2, 0xd1, 0xd6, 0x21, 0xfa, 0x9d, 0x28, 0xb2, 0xc5, + 0x76, 0xc9, 0xfe, 0x42, 0x4b, 0xe7, 0xd3, 0x07, 0x9a, 0x41, 0xdd, 0x1e, 0x23, 0xaf, 0x22, 0x80, 0x78, 0x0c, 0x76, + 0xe1, 0xeb, 0x32, 0xef, 0x99, 0xbc, 0x02, 0xfc, 0x9c, 0x72, 0xf2, 0x97, 0xe7, 0x8b, 0x26, 0x22, 0xe8, 0xb3, 0x2e, + 0x49, 0x02, 0x22, 0xe2, 0x71, 0x3a, 0x3b, 0x36, 0x4d, 0x7a, 0x19, 0x39, 0x3c, 0x62, 0x33, 0x2b, 0xdf, 0xb1, 0xaa, + 0x8b, 0xb3, 0x5b, 0x3e, 0xda, 0x5f, 0xe8, 0x41, 0x67, 0x90, 0xa8, 0x5d, 0x9c, 0xc9, 0x68, 0x76, 0x64, 0x1a, 0x63, + 0x43, 0xb4, 0x97, 0x8a, 0x29, 0x19, 0x66, 0x39, 0x46, 0x1d, 0xd7, 0x46, 0x4e, 0x97, 0x93, 0x25, 0x0e, 0xc3, 0x12, + 0xe3, 0x7d, 0x1a, 0x10, 0xf4, 0x72, 0x05, 0x1d, 0xec, 0xe2, 0x5c, 0x6f, 0x87, 0x1c, 0x1a, 0x10, 0x97, 0x1a, 0xef, + 0xe2, 0x5c, 0xf7, 0xa0, 0xca, 0x53, 0x64, 0xc5, 0xc3, 0x9f, 0x52, 0xbf, 0x54, 0x8e, 0xf1, 0x9e, 0x81, 0xc4, 0xd8, + 0x6f, 0x6c, 0xcf, 0xfd, 0x26, 0x28, 0x66, 0x99, 0xa2, 0x91, 0x9e, 0x17, 0xee, 0xc1, 0x6c, 0x4f, 0xdb, 0xab, 0xd1, + 0x54, 0xc1, 0xcc, 0xa2, 0x13, 0xc0, 0xe6, 0x0f, 0xc4, 0x54, 0x45, 0x57, 0x3c, 0x52, 0x08, 0xc2, 0x70, 0xb5, 0xde, + 0x91, 0xed, 0xb3, 0x42, 0x68, 0xb9, 0x63, 0x26, 0x19, 0xf8, 0xb9, 0xf1, 0x61, 0xd6, 0x35, 0xbe, 0xa8, 0x27, 0x40, + 0x33, 0x71, 0xe5, 0xc3, 0xc7, 0xc9, 0x42, 0x61, 0x82, 0x92, 0xd1, 0x4f, 0xae, 0xa6, 0x5a, 0xd2, 0x9d, 0x74, 0xd8, + 0x9b, 0x2d, 0x5f, 0x27, 0x65, 0x1d, 0x76, 0x29, 0xfb, 0x58, 0xca, 0x03, 0xed, 0x76, 0x33, 0xdb, 0xc3, 0xdf, 0x70, + 0xf3, 0x01, 0xa0, 0x8b, 0x84, 0x95, 0x49, 0x6e, 0xd1, 0x80, 0x5f, 0x7c, 0x30, 0x38, 0x19, 0xc3, 0xf6, 0xe0, 0xc5, + 0xdc, 0x61, 0x9d, 0x63, 0xff, 0xd6, 0x91, 0x9b, 0x38, 0x0a, 0xa4, 0xe4, 0xab, 0x85, 0x45, 0x15, 0xa2, 0xc3, 0x40, + 0xe3, 0xaa, 0xcf, 0x13, 0xb0, 0x90, 0x33, 0xb5, 0x26, 0xd9, 0xfc, 0x53, 0x05, 0xc4, 0xf3, 0xd9, 0x72, 0x08, 0x24, + 0xc8, 0xb7, 0xb2, 0x5a, 0x16, 0xaf, 0x09, 0x27, 0xb0, 0x3d, 0x82, 0x45, 0x63, 0x77, 0x04, 0x00, 0x5a, 0xe8, 0x20, + 0xa4, 0xd4, 0x85, 0x0b, 0x65, 0x2f, 0xd7, 0xc8, 0x86, 0xa9, 0x6b, 0x81, 0x17, 0xdf, 0x4e, 0x38, 0xfa, 0xf7, 0x47, + 0x43, 0xb2, 0x8e, 0x00, 0x2e, 0x27, 0x78, 0x1f, 0x36, 0x8d, 0x3d, 0x03, 0xce, 0x48, 0xfb, 0xa2, 0x70, 0x45, 0x3f, + 0x0c, 0xac, 0x0b, 0xf1, 0x2c, 0x38, 0x47, 0x26, 0xbb, 0x12, 0xfa, 0x45, 0xd1, 0x0c, 0x09, 0x5e, 0x30, 0x8e, 0x6d, + 0xe0, 0x73, 0x07, 0xf4, 0xd3, 0x98, 0x8b, 0xb6, 0x05, 0x1e, 0x2b, 0xaa, 0xcc, 0x29, 0x87, 0x6e, 0x10, 0xad, 0xbd, + 0xfa, 0x5c, 0xea, 0x3b, 0x9c, 0x95, 0xce, 0x8a, 0x7b, 0x97, 0x55, 0x0f, 0x05, 0x9f, 0x20, 0xc7, 0xfb, 0x57, 0x14, + 0xfb, 0x9f, 0x36, 0xe2, 0x68, 0xc1, 0xa6, 0x00, 0x0c, 0x20, 0x21, 0xd3, 0x08, 0xdb, 0x3a, 0x09, 0x3a, 0x7e, 0x28, + 0x3d, 0x46, 0x1c, 0x4a, 0x5a, 0x61, 0x70, 0x98, 0xaa, 0x6f, 0x83, 0x0c, 0x29, 0x79, 0xb9, 0x94, 0x1e, 0x86, 0x18, + 0x39, 0x20, 0x95, 0xb9, 0xf2, 0x3d, 0x7b, 0x55, 0x3c, 0x51, 0xea, 0xc4, 0x07, 0x10, 0x8b, 0xa1, 0x47, 0x46, 0x7d, + 0x20, 0x53, 0x5d, 0x80, 0x26, 0x86, 0x90, 0x51, 0x02, 0x88, 0x8d, 0xa1, 0x11, 0x02, 0x25, 0xe4, 0xd8, 0xfa, 0xc5, + 0xac, 0x0a, 0x12, 0xa1, 0x88, 0x45, 0x4b, 0xb4, 0x38, 0x62, 0x14, 0x60, 0x86, 0x34, 0xd0, 0x63, 0xee, 0x9a, 0x0e, + 0x8c, 0x0b, 0x30, 0xa6, 0xe2, 0x1e, 0x40, 0x7e, 0x33, 0x86, 0xb1, 0x88, 0xe0, 0xe5, 0xae, 0x3c, 0x4f, 0x1a, 0x35, + 0x58, 0xc3, 0x5a, 0x34, 0x17, 0xab, 0xb7, 0x81, 0x99, 0x72, 0x0c, 0xc9, 0x55, 0xab, 0x52, 0xd8, 0xe9, 0xcd, 0x7e, + 0x1f, 0xf2, 0xb9, 0x83, 0xd0, 0xd6, 0xc1, 0x99, 0x25, 0x28, 0x33, 0x12, 0xdb, 0x98, 0x50, 0x40, 0x32, 0xd0, 0x81, + 0xd4, 0x15, 0x88, 0x90, 0x90, 0x64, 0x92, 0x84, 0xe6, 0x64, 0x8a, 0x44, 0x7c, 0x71, 0xc2, 0x5c, 0x1f, 0xc4, 0xc9, + 0x12, 0xd9, 0xbc, 0x6f, 0x97, 0xc0, 0xfc, 0x81, 0x91, 0x59, 0x91, 0xab, 0xaa, 0xa0, 0x01, 0x12, 0x09, 0xa3, 0xd5, + 0x09, 0x43, 0xe7, 0xf5, 0xd9, 0xdf, 0x07, 0x8c, 0x2d, 0x4c, 0xe8, 0x40, 0x30, 0x0c, 0x65, 0x51, 0xa8, 0xe4, 0x4f, + 0x0a, 0x1c, 0x56, 0x68, 0x78, 0x7f, 0x16, 0x7c, 0xf1, 0xd4, 0x62, 0x61, 0x15, 0x1e, 0x09, 0xb9, 0x1f, 0x6a, 0x89, + 0xb3, 0x02, 0x92, 0x13, 0x84, 0x56, 0xf7, 0xef, 0x7f, 0x77, 0x54, 0x12, 0xe6, 0x45, 0x8b, 0xd2, 0xab, 0x23, 0x6e, + 0x73, 0xb5, 0xc0, 0xd0, 0xa4, 0xd9, 0x21, 0xdf, 0x3e, 0x55, 0x22, 0x6e, 0x14, 0x5c, 0xee, 0x42, 0x2c, 0x01, 0x69, + 0x33, 0x18, 0x7c, 0x69, 0x3d, 0xa5, 0x1f, 0x20, 0xf4, 0x8d, 0x7b, 0x76, 0xfa, 0x38, 0x46, 0x32, 0x26, 0x17, 0xd6, + 0xcf, 0xac, 0x6a, 0x35, 0x71, 0x44, 0x42, 0xce, 0x59, 0xe8, 0x50, 0xec, 0xab, 0x61, 0x39, 0x73, 0xc5, 0xd9, 0xc3, + 0xc3, 0x68, 0x05, 0x24, 0x1d, 0x69, 0xb8, 0x21, 0xc7, 0xb3, 0x0f, 0x50, 0xe7, 0x51, 0x30, 0x92, 0x4a, 0xe6, 0xbd, + 0x62, 0x38, 0x6f, 0x88, 0xb6, 0xd4, 0xb3, 0xd6, 0x20, 0x70, 0x4e, 0x16, 0x49, 0xc9, 0x9b, 0x20, 0xb5, 0xf2, 0xf2, + 0x64, 0x1e, 0x31, 0xc5, 0xe9, 0x54, 0x59, 0x61, 0x74, 0x72, 0xd1, 0x73, 0x64, 0x94, 0x5d, 0xb0, 0xa1, 0x9a, 0x4f, + 0x4b, 0x53, 0xee, 0x2b, 0xac, 0x94, 0xae, 0xb4, 0xc0, 0x74, 0x24, 0xc6, 0xea, 0x66, 0x8e, 0xea, 0x81, 0x41, 0xc4, + 0x7a, 0xf9, 0x06, 0x91, 0x87, 0x34, 0xbf, 0x70, 0xa4, 0x22, 0x6d, 0x09, 0xcf, 0x4a, 0x3e, 0x60, 0x36, 0x03, 0xd2, + 0xca, 0xfb, 0x04, 0x5c, 0xf9, 0x4d, 0x81, 0x82, 0xe4, 0x8b, 0xf3, 0x04, 0xcd, 0x20, 0x7e, 0x1d, 0x64, 0xb3, 0xb1, + 0x11, 0xe3, 0xf9, 0xd6, 0xe0, 0xd5, 0x10, 0x39, 0x58, 0x1d, 0xfd, 0xba, 0x1b, 0xb0, 0x75, 0xb8, 0x4d, 0xa7, 0x67, + 0x5f, 0x6a, 0x81, 0x16, 0x83, 0xe3, 0xa9, 0x98, 0xe2, 0xa4, 0x7a, 0x44, 0x2c, 0x53, 0x61, 0x1a, 0x13, 0x5d, 0x21, + 0x6b, 0x6c, 0x29, 0xd8, 0x7c, 0xcb, 0x7b, 0x5e, 0x64, 0x48, 0xb8, 0x6b, 0x44, 0x17, 0xc3, 0x18, 0x04, 0x2f, 0x2f, + 0xa5, 0x73, 0x5f, 0x1b, 0x25, 0x56, 0xcc, 0x13, 0x1f, 0x5e, 0x37, 0x49, 0xf2, 0x82, 0xb4, 0x66, 0xcf, 0x6a, 0x2c, + 0x7f, 0x78, 0xf3, 0x83, 0xa9, 0x4a, 0xac, 0xd9, 0xc9, 0x4f, 0x52, 0xb6, 0xef, 0x87, 0xa6, 0x41, 0xde, 0x56, 0x2c, + 0x7e, 0x69, 0xf2, 0x0d, 0xa2, 0x0b, 0x46, 0xc9, 0x4e, 0x17, 0x8b, 0x75, 0x03, 0xf7, 0xeb, 0x25, 0xe8, 0xca, 0x0c, + 0x83, 0x76, 0xef, 0x6b, 0xdd, 0x2f, 0x8a, 0x48, 0x8f, 0xb1, 0x0f, 0x19, 0x29, 0x5a, 0x89, 0x5a, 0xcb, 0xfc, 0x6c, + 0x5b, 0xeb, 0x08, 0x09, 0x33, 0xd1, 0x4b, 0x73, 0xb4, 0x43, 0x22, 0x56, 0x33, 0x13, 0xa1, 0xc1, 0xba, 0x19, 0x79, + 0x57, 0x53, 0xfe, 0xb4, 0x84, 0x0e, 0x8f, 0xb5, 0xae, 0xda, 0xdc, 0xcb, 0x68, 0x3a, 0x23, 0xae, 0xe7, 0x69, 0xea, + 0x9a, 0xd2, 0xd3, 0xa0, 0xc3, 0x9d, 0x14, 0xb1, 0xc5, 0xad, 0xff, 0xc0, 0x4c, 0x8b, 0x42, 0x42, 0x35, 0x94, 0xb9, + 0xbd, 0xae, 0x1e, 0x4b, 0xd5, 0x53, 0xb2, 0xfb, 0x9e, 0xe8, 0x6b, 0xac, 0xd2, 0xbe, 0x46, 0xb2, 0x6a, 0x85, 0xc7, + 0xc6, 0xb8, 0x0e, 0x9e, 0xf5, 0x1b, 0xdc, 0x24, 0x8a, 0x10, 0xc3, 0xb8, 0xf4, 0x0b, 0x1f, 0xe1, 0x5c, 0xe0, 0xf5, + 0x30, 0x6d, 0xdd, 0x0e, 0xa9, 0xa6, 0x20, 0x8e, 0xdd, 0x16, 0xce, 0xd9, 0xad, 0x39, 0x78, 0xe8, 0x8e, 0xa3, 0xbc, + 0x50, 0x8f, 0xf3, 0x0e, 0x85, 0x76, 0x28, 0x69, 0x78, 0x5c, 0xb7, 0xa3, 0xc9, 0x83, 0x23, 0x9a, 0xb8, 0x5d, 0x6e, + 0x7f, 0x26, 0x94, 0x79, 0x1a, 0x20, 0xa2, 0x31, 0xfc, 0xfb, 0x92, 0x3d, 0x19, 0xd3, 0x09, 0x49, 0x64, 0x43, 0x66, + 0x1b, 0x30, 0xf6, 0x90, 0x48, 0x8f, 0xbf, 0x22, 0xf7, 0x6f, 0x8d, 0x82, 0xe3, 0xa5, 0xb8, 0xa1, 0xa4, 0x3f, 0x2c, + 0xc2, 0x4c, 0x27, 0x31, 0x4d, 0x3c, 0x90, 0xc5, 0x55, 0x00, 0x2e, 0xd3, 0xae, 0xb0, 0x40, 0x96, 0x0b, 0x2c, 0x90, + 0xb2, 0xfa, 0x1c, 0x25, 0x91, 0xb8, 0x47, 0x42, 0x76, 0x3a, 0x79, 0x2f, 0x8e, 0x71, 0xc1, 0x73, 0x35, 0x39, 0xba, + 0xe0, 0xc5, 0x4c, 0x10, 0xb5, 0x3b, 0x8d, 0xf4, 0x22, 0x34, 0xef, 0xe5, 0xea, 0x3a, 0xd2, 0xa7, 0xd0, 0x82, 0x0a, + 0xf5, 0x0b, 0x69, 0xbf, 0x7f, 0x9d, 0xc8, 0x80, 0xa3, 0x41, 0x93, 0x0d, 0x3b, 0x24, 0xac, 0x90, 0xd7, 0x2e, 0xbe, + 0x10, 0x3a, 0x22, 0x33, 0x7a, 0x94, 0x61, 0x7a, 0x99, 0x8f, 0xd1, 0xce, 0x5b, 0x39, 0x9a, 0x2e, 0x1c, 0xfc, 0xe7, + 0xb0, 0xb7, 0x40, 0x87, 0xab, 0xe3, 0x22, 0xdd, 0x4f, 0xce, 0x5c, 0xfc, 0x0f, 0xa6, 0xab, 0xae, 0x7d, 0x36, 0x13, + 0x5f, 0xc9, 0x63, 0x44, 0x7d, 0xd5, 0x0b, 0xa7, 0x34, 0x1b, 0xd5, 0x4c, 0x1f, 0x45, 0xe4, 0x79, 0xa8, 0x72, 0x5b, + 0x30, 0x9e, 0xd6, 0x60, 0xf8, 0xe8, 0x28, 0xe1, 0x10, 0x34, 0xc1, 0x99, 0xb9, 0x1f, 0x51, 0x65, 0x64, 0x09, 0xe3, + 0xc6, 0x02, 0xcb, 0x9b, 0xe9, 0x3c, 0x8e, 0x4b, 0xa1, 0xe5, 0x33, 0xc6, 0xdf, 0xdf, 0xa2, 0xcf, 0x4f, 0x85, 0xcd, + 0x12, 0x17, 0x3f, 0xe8, 0xc4, 0x51, 0x2f, 0x5c, 0x69, 0xeb, 0x14, 0xab, 0x52, 0xd9, 0x4d, 0xed, 0x7c, 0x6c, 0x5b, + 0x5e, 0x4a, 0xc6, 0xa7, 0x14, 0xe5, 0x24, 0xd7, 0x14, 0x8a, 0xc1, 0xc0, 0x1b, 0x59, 0xf5, 0xe7, 0x0b, 0x98, 0xc9, + 0x0d, 0x78, 0xa6, 0xaf, 0x63, 0xbd, 0x03, 0x3c, 0xd8, 0x73, 0x0b, 0x33, 0x57, 0x90, 0xc8, 0xe3, 0xf1, 0x1c, 0x8f, + 0x75, 0xc0, 0xf9, 0x83, 0xdc, 0x3b, 0x0a, 0xf8, 0x6e, 0x00, 0x62, 0x76, 0xde, 0x08, 0xf0, 0x0b, 0xec, 0x70, 0xb6, + 0xc4, 0x12, 0x54, 0x29, 0xd4, 0x82, 0x1d, 0x19, 0x7c, 0x96, 0x60, 0x35, 0x13, 0x70, 0x96, 0x20, 0x28, 0xca, 0x62, + 0xbe, 0x20, 0x28, 0x71, 0x14, 0x4a, 0x66, 0x2e, 0x3f, 0x35, 0x9b, 0xa2, 0x28, 0x12, 0xe1, 0xa7, 0x76, 0x70, 0x9e, + 0x11, 0x2e, 0xf1, 0xb5, 0xa2, 0xca, 0x07, 0x06, 0x5f, 0x10, 0x68, 0x80, 0xfe, 0xcd, 0x54, 0x44, 0xfb, 0x73, 0xd2, + 0x28, 0x29, 0xdc, 0xb3, 0xb0, 0x18, 0x67, 0x9d, 0x59, 0xd2, 0x6f, 0xb2, 0xcc, 0x6b, 0xd1, 0xcc, 0xaf, 0x6c, 0xc8, + 0x5a, 0xe7, 0xbb, 0x9f, 0xf7, 0x03, 0xa5, 0x9d, 0xf5, 0xcc, 0x92, 0x7d, 0xb4, 0x67, 0x9a, 0x36, 0x0b, 0x87, 0x9e, + 0xc5, 0xd5, 0x0d, 0x53, 0x10, 0x07, 0x5e, 0x9e, 0x46, 0x2a, 0x03, 0x7f, 0x2a, 0x0a, 0x38, 0x52, 0x4e, 0xf1, 0x5b, + 0x4a, 0x78, 0x37, 0xbf, 0x20, 0x8e, 0xdd, 0x5d, 0xfd, 0x0a, 0x90, 0xb5, 0x85, 0xd5, 0xc1, 0x4d, 0x8e, 0x9b, 0xa8, + 0x21, 0xca, 0xc1, 0xdb, 0x40, 0xbe, 0x34, 0x4f, 0x5a, 0xe2, 0xa8, 0x97, 0x45, 0xab, 0xcf, 0xd3, 0xdc, 0x10, 0xf8, + 0xa9, 0x0b, 0xc7, 0xe3, 0x3c, 0xfa, 0xe6, 0xd0, 0x34, 0xf2, 0x63, 0xd2, 0xf6, 0x80, 0x81, 0xa4, 0x99, 0x68, 0xe3, + 0x23, 0x5b, 0x4e, 0x77, 0x3b, 0x0b, 0xe9, 0x7a, 0x3d, 0x0d, 0xa5, 0xb0, 0x58, 0xb8, 0x70, 0x34, 0x66, 0x9f, 0xd0, + 0xe9, 0xd6, 0x6c, 0x48, 0x74, 0x07, 0xc3, 0x95, 0x18, 0xb9, 0x0e, 0xe3, 0x9c, 0xd9, 0x70, 0x84, 0x95, 0xea, 0xb1, + 0x37, 0x6e, 0x1b, 0x12, 0x3c, 0xa1, 0xe2, 0xc8, 0x03, 0x8f, 0xf0, 0x59, 0x1d, 0x74, 0x78, 0x98, 0x07, 0x2e, 0xf9, + 0x06, 0x73, 0x75, 0x04, 0x03, 0xe5, 0x08, 0x42, 0x11, 0xf9, 0xfe, 0x0e, 0x73, 0xe1, 0xb1, 0x7c, 0x83, 0x99, 0x5a, + 0x79, 0xe1, 0x73, 0xbd, 0xe4, 0x76, 0xc0, 0xf3, 0xf6, 0x13, 0x2f, 0xe9, 0x1a, 0xc1, 0xe1, 0x47, 0x7e, 0xd5, 0x62, + 0xfd, 0x75, 0x1f, 0xf3, 0xe7, 0x41, 0xaa, 0x4b, 0xb8, 0x2a, 0x0c, 0x80, 0x3f, 0xba, 0x32, 0xee, 0x06, 0x0c, 0xeb, + 0x23, 0x44, 0x8d, 0xf0, 0x88, 0xfd, 0xe1, 0xa9, 0x17, 0x00, 0xca, 0x9d, 0x9b, 0x81, 0xc8, 0x42, 0x34, 0x3f, 0x2f, + 0x57, 0xdb, 0xe6, 0x65, 0x68, 0x4b, 0x4b, 0x37, 0x8f, 0x13, 0x49, 0xd8, 0x4c, 0x9c, 0x5a, 0xa8, 0x5e, 0x11, 0x31, + 0x45, 0xcc, 0x02, 0xad, 0x97, 0xf1, 0x7b, 0x7c, 0x67, 0x08, 0xa3, 0x36, 0x6c, 0x84, 0xd7, 0xed, 0x68, 0x6d, 0xf0, + 0x7e, 0xbf, 0xd6, 0x46, 0x21, 0xd8, 0xb7, 0xf4, 0x0b, 0x14, 0x69, 0xd8, 0xd2, 0x8e, 0xff, 0x79, 0xc0, 0x17, 0xfd, + 0x43, 0x08, 0x9b, 0xc4, 0x06, 0x05, 0x85, 0x97, 0xda, 0x64, 0x6f, 0x03, 0x25, 0x4c, 0x62, 0xad, 0xd6, 0x13, 0xf0, + 0xa2, 0x0d, 0x20, 0x15, 0xba, 0x67, 0xcc, 0xaf, 0xc8, 0xe4, 0xf9, 0x13, 0xd2, 0xb2, 0x85, 0x71, 0xca, 0x27, 0xd1, + 0x8e, 0x04, 0x3b, 0x3f, 0x45, 0x91, 0xbc, 0xe2, 0xbb, 0x44, 0x92, 0xaf, 0x4f, 0xbb, 0xf9, 0xcb, 0xdd, 0x83, 0x26, + 0x85, 0x40, 0x07, 0x8f, 0xee, 0x08, 0x19, 0x6a, 0xb5, 0x8c, 0xea, 0xf0, 0x18, 0x8b, 0x4c, 0xcf, 0x1f, 0xce, 0xea, + 0x8b, 0x0c, 0x03, 0x27, 0x96, 0xc0, 0x28, 0x95, 0x5d, 0x6e, 0xd9, 0xd8, 0x9f, 0xf4, 0xde, 0x78, 0x89, 0x52, 0x75, + 0x3c, 0xc7, 0xad, 0x1a, 0xba, 0x43, 0x57, 0xc4, 0x1b, 0x3e, 0xf0, 0xd8, 0xbf, 0xba, 0x31, 0xa8, 0x63, 0x4d, 0x9b, + 0x08, 0x5e, 0x07, 0xfd, 0xcc, 0x14, 0x9c, 0x6c, 0x7c, 0x4a, 0x74, 0x0a, 0x83, 0x04, 0x0a, 0x66, 0x28, 0xf6, 0x99, + 0x96, 0x8f, 0x4b, 0xe9, 0xce, 0x5a, 0x2a, 0xea, 0xd8, 0x38, 0x33, 0xca, 0xfa, 0xe5, 0x72, 0x69, 0xe3, 0x6d, 0x04, + 0xf4, 0x92, 0x7b, 0x79, 0x7f, 0xc5, 0x49, 0xe3, 0x18, 0x91, 0x2c, 0x38, 0x1e, 0x1e, 0xc7, 0x1c, 0xf2, 0xc6, 0xad, + 0x05, 0x1d, 0x26, 0xb4, 0x06, 0x36, 0x3b, 0x67, 0x39, 0xe5, 0x6b, 0x11, 0xce, 0xb2, 0xcb, 0x6f, 0x36, 0x40, 0x04, + 0x84, 0x9e, 0x16, 0x91, 0x04, 0x3e, 0x2b, 0x90, 0x31, 0x47, 0x4e, 0x72, 0x64, 0x79, 0xad, 0xe4, 0x11, 0x48, 0x26, + 0x46, 0x8a, 0xb7, 0xe1, 0xa6, 0x9f, 0xa2, 0x4b, 0x76, 0xb0, 0x51, 0x37, 0x08, 0xa2, 0x04, 0x3b, 0xc0, 0x5f, 0xf8, + 0xf3, 0xa1, 0xef, 0xfc, 0xe9, 0xb7, 0x5b, 0x87, 0xff, 0x27, 0xb8, 0xb4, 0x8f, 0x18, 0x3b, 0xfd, 0x25, 0x56, 0x7d, + 0xf5, 0x7f, 0x73, 0xd7, 0xd0, 0x3a, 0xf0, 0xe1, 0x03, 0x17, 0x1e, 0x7f, 0x1b, 0x96, 0xd0, 0x6a, 0x6b, 0x77, 0x58, + 0x52, 0x88, 0x13, 0xe5, 0xc4, 0x8e, 0xea, 0x3d, 0x8a, 0xf6, 0xc5, 0xd3, 0xfb, 0x23, 0x01, 0xac, 0xbf, 0x7f, 0xe3, + 0x51, 0x69, 0xa4, 0xbb, 0x5f, 0x82, 0x4c, 0x6c, 0xad, 0x4d, 0x90, 0xab, 0xd4, 0x7e, 0x7e, 0xee, 0x5b, 0xeb, 0xa8, + 0xa5, 0xab, 0x6c, 0x70, 0x7f, 0xd1, 0x55, 0x7b, 0xb0, 0xc9, 0xf2, 0x61, 0xbb, 0xb9, 0xb5, 0x4f, 0x2b, 0x57, 0x19, + 0xe1, 0x43, 0x01, 0x02, 0xec, 0x54, 0x99, 0x9c, 0x3c, 0xe3, 0xb7, 0x52, 0xf0, 0x8e, 0xa5, 0x9e, 0xf6, 0x37, 0x9b, + 0xe0, 0xef, 0x0d, 0x6b, 0xbb, 0xab, 0x47, 0xeb, 0x03, 0x08, 0xca, 0xa5, 0xd7, 0x50, 0xc1, 0x21, 0xc4, 0x4b, 0x0a, + 0x12, 0x72, 0x18, 0xce, 0x5c, 0x74, 0x92, 0x43, 0x4c, 0x1b, 0x31, 0xac, 0xab, 0xb4, 0x55, 0x71, 0xe2, 0xb5, 0x3c, + 0xb0, 0x5b, 0x18, 0xb7, 0x60, 0x61, 0x58, 0x64, 0x30, 0xf2, 0x0c, 0xec, 0x70, 0x2e, 0x1e, 0x7a, 0x35, 0x0b, 0x5e, + 0x90, 0x26, 0x5c, 0x96, 0xfa, 0x7d, 0xb0, 0x38, 0x66, 0xf5, 0x55, 0x0b, 0x7e, 0xcd, 0xc1, 0xa9, 0x29, 0x6a, 0x43, + 0x7e, 0xb5, 0x6f, 0x66, 0x84, 0xcb, 0x0b, 0xb9, 0xc7, 0x42, 0x10, 0x2a, 0xdb, 0xb8, 0x65, 0xd2, 0xc1, 0xc9, 0x50, + 0xdf, 0xa7, 0x0d, 0x61, 0x84, 0x17, 0x04, 0x32, 0x4d, 0x51, 0xca, 0xf0, 0x5b, 0xb8, 0xaf, 0x1d, 0xca, 0x06, 0xb9, + 0x99, 0x0e, 0x23, 0xe1, 0x8a, 0xec, 0x38, 0xf0, 0x2c, 0xcd, 0xa7, 0x6a, 0x7f, 0x6c, 0x5d, 0x07, 0xfd, 0xce, 0x25, + 0x44, 0xed, 0x91, 0x9a, 0xf1, 0x31, 0x9b, 0x76, 0x0a, 0xfe, 0xe6, 0x73, 0x29, 0x36, 0x10, 0x1f, 0x69, 0xb9, 0x4b, + 0xa9, 0x89, 0x63, 0xb9, 0xb4, 0xca, 0x38, 0xd4, 0xd0, 0x29, 0x0b, 0x6d, 0x23, 0x97, 0x19, 0x44, 0xda, 0x2e, 0x4e, + 0x49, 0x95, 0x49, 0x1e, 0x8b, 0x13, 0x62, 0xc8, 0x42, 0xbf, 0xc0, 0xda, 0xfe, 0x72, 0xf3, 0x4b, 0x32, 0x54, 0x21, + 0x76, 0xee, 0x10, 0xfa, 0xb0, 0xc0, 0xe6, 0xa5, 0xb4, 0x14, 0x46, 0x15, 0xa6, 0xae, 0xda, 0xea, 0xb9, 0xa5, 0x6d, + 0x48, 0x32, 0x90, 0xcc, 0xb2, 0x84, 0x8f, 0xb2, 0x81, 0x41, 0x8e, 0xff, 0x6d, 0x00, 0xd9, 0xf6, 0x20, 0xd8, 0xde, + 0x32, 0x65, 0xa9, 0xef, 0x2d, 0x7e, 0x9a, 0x84, 0x4f, 0x4c, 0x08, 0x5c, 0x06, 0x5c, 0x75, 0xfe, 0x6c, 0x76, 0x8d, + 0xff, 0x10, 0x06, 0xfe, 0x1b, 0x6e, 0xf4, 0x0d, 0xbe, 0x4a, 0x3f, 0x77, 0xc9, 0xfd, 0xc8, 0xfb, 0x91, 0x3c, 0xdb, + 0x96, 0xc6, 0x4f, 0x5c, 0xac, 0x78, 0x53, 0x7e, 0x0a, 0x7f, 0x33, 0x9a, 0xef, 0xcb, 0xfa, 0xce, 0xb6, 0xd3, 0x47, + 0x60, 0x33, 0xd8, 0x23, 0x3b, 0x74, 0xd7, 0x47, 0xa3, 0x54, 0xcc, 0x1c, 0xf1, 0xed, 0xc3, 0x9f, 0xdb, 0xda, 0x2f, + 0xce, 0x86, 0xe8, 0x3a, 0x30, 0x85, 0xd3, 0xd7, 0x01, 0xca, 0x0e, 0x59, 0x62, 0xda, 0x81, 0x4a, 0x14, 0x1d, 0x74, + 0x66, 0x5d, 0x0a, 0xb0, 0x7c, 0xe3, 0xe8, 0x67, 0x0d, 0xae, 0x95, 0xa4, 0xc3, 0x50, 0x6b, 0x11, 0x9f, 0x4d, 0xa7, + 0xf7, 0xa3, 0x58, 0x51, 0xc0, 0x02, 0xe6, 0xeb, 0x04, 0x76, 0x91, 0xde, 0xbc, 0x3c, 0x92, 0xe0, 0x9c, 0x70, 0x38, + 0x72, 0x81, 0x00, 0x2a, 0xb4, 0x5d, 0x48, 0x13, 0x7e, 0x9d, 0x3b, 0xba, 0xb6, 0x9f, 0x90, 0x5a, 0xb2, 0x1c, 0xe8, + 0xa5, 0xfa, 0xbf, 0xee, 0xee, 0x7e, 0x51, 0x1e, 0x2f, 0xec, 0xed, 0x89, 0x70, 0xcb, 0xb3, 0xaf, 0xac, 0xb0, 0xea, + 0x15, 0xf7, 0xfb, 0x24, 0x13, 0xad, 0xdd, 0x5c, 0x1f, 0xac, 0x4e, 0xd4, 0x2a, 0x78, 0xe8, 0xab, 0xf4, 0x3f, 0x33, + 0xbd, 0xdc, 0x73, 0x53, 0x1e, 0x4a, 0x84, 0x03, 0x5f, 0x34, 0x34, 0x3e, 0x43, 0x35, 0x44, 0xf1, 0x58, 0x0d, 0x38, + 0x8c, 0x49, 0x73, 0xdc, 0x27, 0x58, 0xc9, 0xd4, 0x89, 0x51, 0xb5, 0x11, 0x05, 0x24, 0x98, 0x82, 0xce, 0xa5, 0x2d, + 0xa1, 0x40, 0x05, 0xcd, 0xa2, 0x84, 0x46, 0xdf, 0xf3, 0x61, 0x45, 0x1a, 0x1d, 0xdc, 0x13, 0xc8, 0x08, 0x82, 0xca, + 0xb2, 0xf9, 0xcd, 0x76, 0x35, 0x8a, 0xc2, 0xa9, 0xef, 0x13, 0x0a, 0xca, 0x7f, 0x9c, 0xf9, 0xd2, 0x66, 0xc7, 0xdd, + 0xa3, 0x81, 0x50, 0x54, 0xeb, 0x12, 0x2f, 0x5b, 0x6d, 0xe4, 0x26, 0x37, 0x45, 0xa4, 0x09, 0xc4, 0x1e, 0xfe, 0x04, + 0x4d, 0x52, 0xc4, 0x74, 0x11, 0x37, 0x97, 0xe6, 0xe2, 0xe0, 0x4a, 0xe9, 0xea, 0x81, 0xdb, 0xd0, 0xc8, 0xab, 0x89, + 0x5e, 0xed, 0xe2, 0x0f, 0x02, 0xd1, 0x09, 0x4b, 0x26, 0xf2, 0x8a, 0x81, 0x48, 0x82, 0x81, 0x02, 0x45, 0xdb, 0x82, + 0x29, 0x0a, 0xbd, 0x6e, 0xeb, 0xc5, 0x71, 0x7e, 0x21, 0x53, 0x11, 0x64, 0x2a, 0x6d, 0x6e, 0x80, 0xab, 0x9f, 0xb6, + 0xec, 0x07, 0x1a, 0xff, 0x93, 0x9c, 0x70, 0xd3, 0x43, 0xcf, 0x42, 0x7c, 0xea, 0x3e, 0xb6, 0xde, 0x55, 0xa0, 0x30, + 0xbd, 0x78, 0x11, 0x2d, 0x90, 0xa2, 0x6e, 0xcc, 0x89, 0x25, 0x9f, 0xab, 0x16, 0xdf, 0x57, 0xe5, 0x97, 0x54, 0x50, + 0x43, 0x40, 0x98, 0x09, 0x20, 0x2b, 0xb1, 0x92, 0xcd, 0x2b, 0x72, 0xee, 0x4b, 0xb6, 0x61, 0x27, 0x78, 0x53, 0x6b, + 0x6e, 0x77, 0x46, 0x8c, 0xe0, 0xfd, 0x10, 0x01, 0x21, 0xaa, 0x15, 0x99, 0x25, 0xbf, 0x2a, 0x45, 0x9b, 0x01, 0x0f, + 0xa1, 0x20, 0x2c, 0xce, 0x5e, 0x21, 0xf3, 0x58, 0x2c, 0xf4, 0x03, 0x72, 0x8d, 0xb8, 0x87, 0x43, 0x04, 0x60, 0xd8, + 0xef, 0xee, 0x11, 0x31, 0xd2, 0xe1, 0xc2, 0x44, 0x0c, 0x03, 0x48, 0xd8, 0x06, 0x2e, 0xb3, 0xf3, 0xf1, 0xbe, 0x7b, + 0xff, 0xc7, 0x18, 0xce, 0x0d, 0xd6, 0x4a, 0xb8, 0x75, 0x74, 0xd5, 0x09, 0xf2, 0xf2, 0x3e, 0xe2, 0xd3, 0xdc, 0x8e, + 0xa8, 0x97, 0x03, 0x51, 0x69, 0x35, 0x9e, 0x6d, 0x84, 0x87, 0x65, 0x0a, 0x8f, 0x7d, 0x2e, 0x28, 0x9d, 0x79, 0x09, + 0x2e, 0x01, 0xd5, 0x07, 0x19, 0x5f, 0x79, 0x23, 0xd1, 0xab, 0xcc, 0xc6, 0x9f, 0xc7, 0xf3, 0x3d, 0x6c, 0xd3, 0x45, + 0x1b, 0xd7, 0xd3, 0xe9, 0x1d, 0x4a, 0x32, 0xc1, 0xb4, 0xbb, 0x49, 0x36, 0xec, 0xfa, 0x89, 0xc9, 0x37, 0x2a, 0xe2, + 0x06, 0xa4, 0xf6, 0xdd, 0x38, 0xd0, 0x54, 0xb0, 0xde, 0x7c, 0x4a, 0xa2, 0x81, 0xe9, 0x11, 0xc9, 0xdc, 0xac, 0xd7, + 0xf6, 0x66, 0x0d, 0x01, 0x20, 0x05, 0x8b, 0x96, 0xe0, 0xbd, 0x2b, 0x67, 0x4d, 0x93, 0x12, 0x5b, 0x00, 0x31, 0xdd, + 0x40, 0xe2, 0x38, 0xa2, 0x5a, 0xe3, 0xee, 0x9b, 0xa5, 0x87, 0xf7, 0x3b, 0x62, 0xf7, 0xee, 0x48, 0x6a, 0x7a, 0xe5, + 0x84, 0xed, 0xde, 0x91, 0x53, 0xa3, 0x1c, 0x1f, 0xd5, 0xb3, 0x1b, 0xb6, 0xb4, 0x8e, 0xe5, 0xc9, 0x8c, 0x1e, 0x05, + 0xbe, 0x64, 0xde, 0xbb, 0x7a, 0x50, 0x92, 0x70, 0xf6, 0x0b, 0x01, 0xe2, 0x68, 0xfd, 0x4b, 0xad, 0xd2, 0xa5, 0xe6, + 0x94, 0xfb, 0xbd, 0x0d, 0xfb, 0xaa, 0xb0, 0x72, 0x49, 0x2d, 0x7a, 0x39, 0x99, 0xaa, 0x9e, 0xca, 0xd7, 0x5e, 0xcb, + 0x35, 0xce, 0x86, 0x1a, 0xda, 0x43, 0xef, 0x35, 0x4d, 0xd5, 0xb2, 0x15, 0xce, 0xa2, 0x98, 0xb6, 0x77, 0xd1, 0x9d, + 0x42, 0x63, 0x1f, 0x39, 0x91, 0x38, 0x61, 0x6e, 0xfd, 0x55, 0x1e, 0x89, 0x1d, 0x1e, 0xc1, 0x16, 0xbe, 0x91, 0x74, + 0x48, 0xca, 0x41, 0xc7, 0x09, 0xb8, 0xad, 0x0c, 0x4f, 0x33, 0x10, 0xb1, 0x5a, 0x44, 0x9a, 0xcc, 0x00, 0xc6, 0x31, + 0x45, 0x5c, 0xab, 0x60, 0xa8, 0x41, 0x72, 0xae, 0x06, 0xc1, 0x4c, 0xc7, 0x82, 0x9d, 0xf9, 0x28, 0x3f, 0x41, 0x5b, + 0x1b, 0xb3, 0xb0, 0xd0, 0xb3, 0x31, 0x35, 0xbb, 0x29, 0x01, 0xac, 0x11, 0x74, 0x7b, 0x49, 0x77, 0xcf, 0x0d, 0xc2, + 0xfb, 0xe5, 0xc8, 0xe5, 0x8c, 0xc1, 0x7a, 0xec, 0xa3, 0x6c, 0x71, 0xea, 0xc1, 0x83, 0x00, 0x33, 0x82, 0xc3, 0x56, + 0xb9, 0x81, 0xf6, 0x6c, 0xe8, 0x3f, 0xf0, 0x4d, 0x34, 0xfb, 0xa2, 0xc6, 0x82, 0x83, 0x33, 0xeb, 0xb3, 0x78, 0x57, + 0xc5, 0x04, 0x59, 0xc4, 0x90, 0x24, 0x67, 0x4d, 0x31, 0x37, 0xeb, 0x62, 0x3d, 0x83, 0x40, 0xb0, 0x7c, 0x85, 0xc9, + 0x00, 0xe1, 0x60, 0x76, 0xa3, 0x21, 0x26, 0xd6, 0x93, 0x77, 0xfd, 0x08, 0x80, 0xc0, 0x00, 0xdc, 0xc5, 0xb9, 0xd0, + 0x26, 0x3a, 0x80, 0x22, 0xbf, 0x07, 0x07, 0x40, 0x12, 0x98, 0xa1, 0x48, 0x50, 0xd0, 0xab, 0xd6, 0xbe, 0xe6, 0xc5, + 0x18, 0x0a, 0x2d, 0x24, 0x04, 0xc1, 0x56, 0xee, 0x92, 0x35, 0x2a, 0xb3, 0x75, 0xd0, 0x90, 0xf0, 0xed, 0x59, 0x51, + 0x49, 0x8a, 0x90, 0x5f, 0xe7, 0x81, 0xf4, 0x4f, 0x07, 0x34, 0xf6, 0x1c, 0x25, 0xa7, 0x9b, 0x4c, 0xcc, 0x1a, 0xe2, + 0xe5, 0x69, 0x3d, 0x5b, 0x84, 0x62, 0x0f, 0xdd, 0xa0, 0xcc, 0xc9, 0xd8, 0x89, 0x2f, 0xa8, 0x11, 0x49, 0xfd, 0xe3, + 0x14, 0xd5, 0x83, 0x7a, 0x14, 0x23, 0x93, 0x71, 0x3d, 0xa1, 0x96, 0xaf, 0xb5, 0x1b, 0x81, 0x36, 0x29, 0xcf, 0xb8, + 0xc9, 0xd8, 0x52, 0xbf, 0x54, 0xa8, 0x65, 0xa7, 0xa6, 0x14, 0xec, 0xe4, 0x3c, 0x2f, 0x38, 0x7a, 0x2a, 0x76, 0xc2, + 0x38, 0x08, 0xf6, 0xa7, 0xd3, 0x6e, 0x8d, 0xf7, 0x7c, 0x82, 0x78, 0xbc, 0xea, 0xdc, 0x3e, 0x64, 0x6a, 0xd5, 0xd4, + 0x14, 0x68, 0xc6, 0xd3, 0xf4, 0xfe, 0x3f, 0x80, 0x3e, 0x0f, 0xc1, 0x9e, 0xe9, 0xa3, 0x10, 0xb7, 0x83, 0x18, 0x7f, + 0xd0, 0xc2, 0x4f, 0xf8, 0x1a, 0x25, 0x5c, 0xff, 0x2d, 0x09, 0xd0, 0xf1, 0x83, 0x56, 0x82, 0x2d, 0x49, 0x9c, 0xce, + 0x45, 0xaa, 0x3b, 0xc7, 0x0c, 0xab, 0x20, 0x17, 0x44, 0x8e, 0xe7, 0x3a, 0x8d, 0xca, 0x42, 0x96, 0x22, 0xe1, 0xc6, + 0x2f, 0x7e, 0xcd, 0x96, 0x0a, 0x3f, 0x06, 0x0e, 0x02, 0x51, 0x01, 0x24, 0xec, 0xa7, 0x97, 0xda, 0x73, 0x66, 0xe7, + 0x01, 0x43, 0x16, 0x48, 0x4b, 0x1d, 0xfb, 0x0a, 0x9d, 0x04, 0x00, 0x44, 0xc7, 0xc4, 0x18, 0xc8, 0xab, 0x1d, 0x55, + 0x7f, 0x80, 0x43, 0xef, 0xa4, 0x63, 0x6d, 0xee, 0x26, 0x10, 0x45, 0x08, 0x08, 0x90, 0x58, 0x1b, 0x0a, 0x22, 0x6b, + 0x39, 0x88, 0xa0, 0x4a, 0xec, 0x04, 0x8e, 0xd2, 0x66, 0xc1, 0x8d, 0x78, 0x44, 0x1a, 0x01, 0xf4, 0x0a, 0x2e, 0xc4, + 0x8c, 0xc0, 0x28, 0xcb, 0x48, 0xe3, 0x17, 0x58, 0x68, 0x5c, 0x04, 0xc1, 0xe7, 0x94, 0xb5, 0xde, 0x83, 0x78, 0x3e, + 0xb7, 0x8a, 0xe6, 0x63, 0x42, 0x88, 0x35, 0x00, 0x6b, 0x28, 0xf3, 0xdf, 0xb2, 0x18, 0x30, 0x1a, 0x28, 0xd9, 0xde, + 0xe3, 0xcc, 0x54, 0x2f, 0x2d, 0x57, 0x55, 0x98, 0x32, 0x8f, 0xc8, 0xa5, 0xf3, 0xae, 0x3f, 0x85, 0xf5, 0xa2, 0x76, + 0x41, 0xd3, 0x84, 0xc7, 0xea, 0xa5, 0x7a, 0xd6, 0xc8, 0x0d, 0xc5, 0x7f, 0x52, 0x9a, 0x1b, 0xe3, 0xa8, 0xfc, 0x62, + 0x5a, 0xf5, 0xc9, 0xe8, 0xb0, 0xde, 0x45, 0x76, 0xa7, 0xa2, 0x02, 0xe0, 0xb4, 0x5b, 0x61, 0x9c, 0xd3, 0x2b, 0x7f, + 0xb5, 0xc3, 0x47, 0xab, 0xcc, 0xdc, 0xa2, 0x2e, 0xb3, 0x86, 0x82, 0xf2, 0xd1, 0x54, 0x7e, 0x87, 0xab, 0xbb, 0x3c, + 0x61, 0xf4, 0xa9, 0x2c, 0x8a, 0x53, 0x77, 0x0f, 0x47, 0xfe, 0x75, 0xd8, 0x12, 0x62, 0xa7, 0xba, 0xf5, 0x17, 0x17, + 0x1e, 0x4c, 0x7d, 0xe2, 0x15, 0x6e, 0xdc, 0x42, 0x9f, 0xb1, 0xd7, 0x8c, 0xa1, 0x13, 0x02, 0xc0, 0x3b, 0x4b, 0x14, + 0x65, 0x41, 0xf8, 0xf7, 0x47, 0x9b, 0xa7, 0x45, 0x34, 0x4f, 0xfa, 0x36, 0xde, 0x4e, 0x40, 0x53, 0x60, 0x83, 0x75, + 0x20, 0x30, 0x1f, 0xd0, 0xbf, 0x19, 0x6c, 0xa3, 0xc6, 0xf7, 0xad, 0x2e, 0x8a, 0x10, 0x5b, 0x18, 0x7c, 0x69, 0xfd, + 0xa5, 0x20, 0xb2, 0x3e, 0xa9, 0x01, 0x6d, 0x3f, 0x4d, 0xd6, 0x5d, 0x61, 0x28, 0x79, 0xda, 0xad, 0x87, 0x11, 0x3b, + 0x68, 0x96, 0xf4, 0x86, 0xc9, 0x1f, 0xd2, 0x41, 0xe1, 0x26, 0x26, 0x8b, 0x44, 0xf9, 0xbb, 0x1f, 0x53, 0x92, 0xdc, + 0xf5, 0x0e, 0x67, 0x29, 0xea, 0x2a, 0x4c, 0xfd, 0x59, 0x79, 0xbf, 0x52, 0xff, 0x96, 0xde, 0xd8, 0x42, 0xc3, 0x91, + 0xb5, 0x20, 0x91, 0xd3, 0x30, 0xe4, 0x5a, 0x1d, 0xce, 0x9c, 0xb8, 0xb5, 0xce, 0x76, 0x84, 0x04, 0x1e, 0x96, 0x9c, + 0x25, 0x4c, 0xd5, 0x9b, 0x5a, 0x10, 0x1c, 0x26, 0x82, 0xc2, 0x74, 0x51, 0x9c, 0x22, 0x61, 0xf1, 0x66, 0x87, 0x16, + 0xa7, 0xcb, 0x60, 0xe7, 0xab, 0xfd, 0x44, 0x85, 0x67, 0x6c, 0x16, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x78, 0x31, 0xc0, + 0xee, 0x9f, 0xf0, 0xb1, 0x74, 0x12, 0xb6, 0x1e, 0x74, 0x4d, 0x6a, 0xb9, 0x54, 0x6a, 0x54, 0x5b, 0xc6, 0x35, 0xd7, + 0x50, 0x71, 0xed, 0xf0, 0xd0, 0x76, 0xf8, 0xee, 0x83, 0xf7, 0x45, 0xe2, 0x19, 0x4c, 0xe5, 0x91, 0x43, 0x10, 0x2d, + 0x6e, 0x59, 0xb7, 0x3e, 0x0c, 0x35, 0x97, 0xa7, 0xb0, 0x8f, 0x86, 0x72, 0xba, 0x88, 0x97, 0x24, 0xdf, 0x41, 0x1d, + 0x48, 0x0f, 0x1d, 0x26, 0x7a, 0x7b, 0x5f, 0x35, 0xeb, 0x0e, 0x34, 0xdf, 0xf4, 0x88, 0x40, 0x9b, 0xbb, 0x6a, 0x31, + 0xaf, 0x98, 0xba, 0x44, 0xb7, 0xa4, 0x96, 0x20, 0xee, 0xba, 0x3c, 0x6e, 0x2d, 0x5f, 0x02, 0x29, 0xa5, 0x84, 0x43, + 0xcb, 0xa5, 0xe6, 0xae, 0xf7, 0x1d, 0x87, 0x84, 0xad, 0xd0, 0x92, 0x75, 0xeb, 0x70, 0x1b, 0x6b, 0xfd, 0x29, 0x30, + 0xa9, 0x7f, 0x69, 0x45, 0x38, 0x78, 0x75, 0xc1, 0xba, 0x2d, 0x3e, 0x78, 0x61, 0x5d, 0x83, 0xae, 0x3d, 0xac, 0x44, + 0x87, 0x1d, 0x56, 0xa1, 0xd5, 0x66, 0x2d, 0x71, 0xb5, 0x12, 0xe3, 0x1b, 0xfa, 0xc3, 0x05, 0x27, 0x96, 0x9d, 0x65, + 0x48, 0xe3, 0x91, 0x93, 0xde, 0x8a, 0x3c, 0x55, 0x64, 0xbf, 0x62, 0x46, 0xc5, 0x4f, 0xd7, 0x91, 0xd6, 0x0b, 0x38, + 0x23, 0x94, 0xbd, 0xfc, 0x80, 0x8d, 0x63, 0x0e, 0xb6, 0x65, 0xd6, 0xde, 0xbb, 0x90, 0x56, 0x62, 0x87, 0x08, 0x5e, + 0x71, 0x17, 0xc3, 0x03, 0xcd, 0x0a, 0xc8, 0x98, 0x82, 0x98, 0x50, 0xf0, 0xf7, 0xba, 0x22, 0x64, 0xec, 0xf0, 0xa4, + 0x73, 0x6c, 0xd9, 0xf1, 0x09, 0x0a, 0x70, 0x64, 0x19, 0x18, 0x8f, 0x51, 0xa5, 0xa2, 0x3d, 0x9d, 0xe1, 0x18, 0xd5, + 0x2c, 0xad, 0x98, 0x5f, 0xc5, 0x02, 0x59, 0x01, 0xbb, 0x71, 0xd6, 0xb2, 0xd7, 0x16, 0xb9, 0x44, 0xf1, 0x86, 0xec, + 0x4e, 0x15, 0x99, 0x85, 0xb1, 0x4e, 0x95, 0x2c, 0xb0, 0xf4, 0xb8, 0x26, 0x94, 0xf1, 0x3f, 0x4d, 0x09, 0xca, 0xb7, + 0xfb, 0x9a, 0x4e, 0x2a, 0x34, 0x0a, 0xd7, 0x64, 0x7d, 0x9a, 0x5f, 0xd1, 0x13, 0xb9, 0xc0, 0xba, 0x24, 0x09, 0xe3, + 0x06, 0x31, 0xaa, 0xda, 0x84, 0x80, 0x6e, 0x08, 0xc5, 0x9b, 0x82, 0xd0, 0x94, 0x21, 0xb4, 0x9c, 0xe4, 0xa8, 0x1e, + 0x70, 0x96, 0xc8, 0xcd, 0xc1, 0x6b, 0x04, 0x57, 0xd1, 0x0e, 0x52, 0x54, 0x61, 0xb8, 0x8b, 0x6a, 0x90, 0xe6, 0xda, + 0x23, 0xa5, 0xe0, 0xaf, 0x09, 0xd0, 0x01, 0x08, 0xc3, 0xca, 0xdf, 0xdc, 0xa8, 0xe0, 0x15, 0xca, 0x4a, 0xe9, 0x54, + 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x46, 0x3a, 0xe1, 0x07, 0xaf, 0x11, 0xe7, 0x82, 0xa0, 0xb6, 0xab, 0xc5, 0x6a, + 0x30, 0x4c, 0xea, 0xa4, 0x2b, 0x40, 0x3e, 0x6a, 0x1a, 0x4c, 0x68, 0xb7, 0x94, 0xe8, 0x45, 0xd8, 0x2b, 0xb0, 0x9c, + 0x76, 0xb3, 0x5d, 0x03, 0x88, 0xd5, 0x5a, 0xd8, 0x41, 0x06, 0xc6, 0x32, 0xfe, 0x08, 0xc8, 0x03, 0x9f, 0x3e, 0x2f, + 0xad, 0x78, 0x64, 0xbd, 0x72, 0xf8, 0xe1, 0xe3, 0xaf, 0x29, 0x18, 0x2c, 0x15, 0x0d, 0x39, 0xbd, 0xd7, 0xe7, 0xf4, + 0x9d, 0x6c, 0x30, 0xd6, 0xa2, 0x73, 0x10, 0xf9, 0x2e, 0xb4, 0x23, 0xdd, 0x95, 0x75, 0x99, 0x91, 0xed, 0xeb, 0x81, + 0x2c, 0xf4, 0x5c, 0x5f, 0x8a, 0x20, 0xd5, 0x82, 0xc2, 0xdf, 0x01, 0x8a, 0x4b, 0x43, 0x28, 0x0d, 0xe5, 0xa0, 0x8c, + 0x14, 0x8e, 0x32, 0x19, 0xee, 0x34, 0x90, 0x02, 0x32, 0x22, 0x10, 0xcc, 0x99, 0x65, 0xed, 0x2d, 0x16, 0xd8, 0x92, + 0x9d, 0xa9, 0x5b, 0xb5, 0x6b, 0x4c, 0x98, 0x97, 0x39, 0x34, 0x7a, 0xe0, 0xd4, 0x96, 0xd3, 0xa3, 0x68, 0xa9, 0x9e, + 0x4e, 0x86, 0xa2, 0x99, 0x95, 0xa4, 0xb3, 0x97, 0xcf, 0xab, 0x86, 0x56, 0x92, 0x7e, 0x67, 0xa1, 0x06, 0xa4, 0x38, + 0x81, 0x3f, 0xbe, 0x08, 0x21, 0x5f, 0x72, 0x1f, 0xee, 0xe9, 0x2f, 0x3b, 0x0b, 0x4e, 0x2f, 0x51, 0x83, 0x9a, 0xbf, + 0x2c, 0x9c, 0xe9, 0x8d, 0x29, 0x1d, 0x94, 0x38, 0x16, 0x84, 0x3d, 0xbc, 0x97, 0xbe, 0xa8, 0x46, 0xdb, 0x45, 0x45, + 0xc1, 0x74, 0x00, 0xa8, 0x68, 0x1a, 0x0e, 0x1d, 0xd7, 0x9a, 0xa4, 0xac, 0xa4, 0xe2, 0xda, 0xcd, 0x15, 0x9f, 0x3e, + 0x76, 0x8c, 0xd4, 0xba, 0x03, 0x93, 0x78, 0x00, 0xcb, 0x3f, 0x07, 0xde, 0x8f, 0x09, 0x20, 0x5c, 0x4a, 0x79, 0x7e, + 0x71, 0x36, 0xe8, 0xf1, 0xdb, 0xad, 0xb8, 0x17, 0xde, 0xab, 0x8e, 0x31, 0x22, 0x66, 0x0b, 0x21, 0x79, 0xc8, 0x96, + 0x48, 0x6c, 0x36, 0x37, 0x4e, 0xba, 0xdb, 0x1c, 0x75, 0x78, 0x7f, 0xf0, 0x7a, 0xc9, 0x3b, 0x76, 0xa7, 0x69, 0xf0, + 0x41, 0xab, 0x53, 0x23, 0xad, 0xe9, 0x3f, 0xf8, 0xb7, 0x72, 0x91, 0x4e, 0xea, 0x1a, 0x90, 0xe8, 0x7c, 0x09, 0x09, + 0xf6, 0x07, 0x49, 0x91, 0x15, 0x5d, 0x2a, 0x65, 0x1b, 0x15, 0xeb, 0x97, 0x66, 0x39, 0x0b, 0xd7, 0x9b, 0x92, 0x7e, + 0xd9, 0xa5, 0x9b, 0x9c, 0x81, 0x75, 0xc1, 0xaa, 0xec, 0x39, 0xc7, 0xe2, 0x19, 0x32, 0xb1, 0xb0, 0xd7, 0x25, 0xca, + 0x52, 0x17, 0x36, 0x90, 0x64, 0xc7, 0xf0, 0x96, 0xf1, 0xe8, 0x4f, 0x9b, 0xc3, 0xbb, 0x9f, 0xf6, 0xed, 0x83, 0xfc, + 0x79, 0x1d, 0xed, 0x0c, 0x0a, 0x71, 0x29, 0xe9, 0xc2, 0xc3, 0x45, 0x0d, 0x2e, 0x09, 0x2d, 0xbc, 0x2d, 0x21, 0x2e, + 0x1e, 0xc3, 0x79, 0xfb, 0x0e, 0x41, 0xad, 0xac, 0xd8, 0xde, 0x71, 0xc4, 0x42, 0x3a, 0xeb, 0x95, 0x00, 0xfa, 0x2d, + 0x95, 0xb5, 0xb8, 0x23, 0xa7, 0x05, 0x94, 0x44, 0xca, 0x2e, 0xd1, 0xd3, 0xd1, 0xa9, 0xad, 0x3d, 0x9b, 0x0f, 0x6b, + 0x4b, 0xd1, 0x36, 0x12, 0x55, 0x9c, 0x43, 0x1c, 0xa3, 0x61, 0x68, 0x73, 0x6d, 0x6d, 0x8b, 0x3a, 0xcc, 0x50, 0x1d, + 0x6b, 0x08, 0x9b, 0x6e, 0x29, 0xe6, 0x5f, 0xaa, 0x1d, 0x97, 0x6e, 0x0d, 0x86, 0x09, 0xc9, 0x83, 0xa0, 0x4c, 0xc2, + 0xa5, 0xbc, 0xbd, 0xf0, 0x21, 0xdd, 0xd7, 0xeb, 0x77, 0x28, 0xff, 0x6e, 0x41, 0x5b, 0x8b, 0x6f, 0x9a, 0xff, 0x20, + 0xff, 0x2f, 0x1b, 0x30, 0x34, 0xe6, 0xf1, 0xe1, 0x58, 0xd2, 0x46, 0x19, 0x2d, 0xe5, 0x14, 0x1e, 0x3b, 0xd3, 0xf4, + 0x12, 0x4b, 0x87, 0x70, 0x77, 0x27, 0x99, 0x05, 0x87, 0x2d, 0x9b, 0x03, 0x24, 0x28, 0xc1, 0xe4, 0xcd, 0xc5, 0x68, + 0xd3, 0x63, 0xba, 0xc2, 0xe1, 0xbb, 0x15, 0x49, 0x36, 0x7b, 0x8d, 0x8b, 0x18, 0x20, 0x3d, 0x57, 0x30, 0x81, 0x02, + 0xfe, 0x30, 0x43, 0x51, 0x77, 0xe3, 0x5a, 0x4a, 0x31, 0x65, 0x8d, 0x20, 0x98, 0xe5, 0x2d, 0x9e, 0x63, 0xc8, 0xb4, + 0xad, 0x9e, 0xbb, 0x4f, 0x7a, 0xc0, 0x80, 0x13, 0x39, 0xfb, 0xd5, 0x62, 0x43, 0xa8, 0x6a, 0xdd, 0xae, 0xbd, 0x26, + 0xba, 0x42, 0x24, 0x7a, 0x72, 0xd2, 0x69, 0x40, 0x6c, 0x8b, 0x30, 0xe4, 0x50, 0xc8, 0xf8, 0xb8, 0x15, 0x39, 0x93, + 0xf0, 0x19, 0xdf, 0xb2, 0x4b, 0x16, 0x77, 0xa2, 0x99, 0x63, 0xc8, 0x67, 0x26, 0x41, 0xc4, 0xe8, 0x5a, 0x2a, 0xe7, + 0x84, 0x14, 0x5d, 0xa9, 0x47, 0xdf, 0x0f, 0xc8, 0xd2, 0x48, 0x82, 0x38, 0x3a, 0x55, 0x63, 0x9e, 0xff, 0x9d, 0x59, + 0x44, 0x67, 0xf0, 0x0f, 0xe3, 0xcc, 0xb3, 0xaf, 0x88, 0x7d, 0x96, 0x70, 0x32, 0xe9, 0xd5, 0xd6, 0x7a, 0x18, 0x44, + 0x20, 0xe0, 0xf3, 0xdd, 0xe8, 0xcd, 0x46, 0x5b, 0x37, 0x68, 0xbc, 0xa3, 0x79, 0x3a, 0xec, 0xcf, 0xc8, 0xdd, 0xa0, + 0x99, 0xd6, 0x6a, 0x53, 0xe2, 0x33, 0x08, 0x9c, 0xcb, 0x48, 0x35, 0x67, 0x19, 0x98, 0x60, 0xbf, 0x5f, 0x6c, 0x7d, + 0x01, 0xd5, 0x99, 0x11, 0x48, 0xfd, 0xae, 0x7a, 0xa9, 0x55, 0x9a, 0x31, 0xa6, 0xd3, 0x45, 0x6d, 0xaf, 0x0d, 0x1c, + 0xf8, 0x3e, 0xd9, 0xc4, 0xa4, 0xad, 0x5e, 0xe2, 0x04, 0x45, 0x77, 0x68, 0xd1, 0xf9, 0x5e, 0x35, 0xd1, 0x54, 0x66, + 0xec, 0xc9, 0xb8, 0x90, 0xed, 0xeb, 0xed, 0x7e, 0x43, 0xe6, 0xe8, 0x5a, 0xc7, 0x48, 0xc9, 0x45, 0x7d, 0x8e, 0xb8, + 0xca, 0x90, 0x7f, 0x5e, 0xc8, 0x62, 0x47, 0x1c, 0x6e, 0x7f, 0x87, 0x87, 0xd5, 0xa2, 0x2e, 0x66, 0xc7, 0x81, 0x38, + 0x46, 0xfe, 0x21, 0x72, 0x7e, 0x14, 0xb0, 0x19, 0x7e, 0x9a, 0xe1, 0x33, 0x68, 0xb3, 0x37, 0xfb, 0xc9, 0x36, 0xbf, + 0xf5, 0xd8, 0xf5, 0xef, 0x1a, 0x5e, 0xf9, 0xc6, 0x2a, 0x1c, 0x76, 0xdf, 0x76, 0x62, 0xcc, 0xfb, 0xf3, 0xd3, 0xaf, + 0x35, 0x46, 0xde, 0x10, 0xb0, 0xd9, 0xc1, 0xfb, 0x38, 0x67, 0xbf, 0xa5, 0xc3, 0x42, 0x2f, 0x6a, 0x15, 0x90, 0x51, + 0xe7, 0x3e, 0x71, 0x7d, 0x0b, 0x90, 0x56, 0x68, 0xa1, 0xd5, 0xa3, 0x5b, 0x42, 0xf7, 0x12, 0x21, 0xeb, 0x9b, 0x4b, + 0xb1, 0xe9, 0xb4, 0x67, 0x4d, 0x25, 0x25, 0x4d, 0xf1, 0x96, 0x14, 0x8a, 0xdf, 0xcf, 0xa8, 0x93, 0x07, 0xb8, 0xcf, + 0xa7, 0x8d, 0x64, 0xa6, 0xee, 0x26, 0xeb, 0xf9, 0x93, 0xd9, 0x13, 0x4a, 0xdb, 0x30, 0x9a, 0x43, 0x7e, 0xd3, 0x68, + 0x40, 0x8f, 0x47, 0x8b, 0x89, 0xd8, 0x0f, 0x02, 0x14, 0x7c, 0x1a, 0x2a, 0xa0, 0x7a, 0xa0, 0xdf, 0xf6, 0xd7, 0x01, + 0x27, 0x15, 0x31, 0x06, 0x7b, 0x03, 0x50, 0x30, 0x44, 0xb6, 0x91, 0xc5, 0x7b, 0xa1, 0x43, 0xd1, 0x27, 0x09, 0x9d, + 0xe9, 0x85, 0x12, 0x91, 0xd0, 0x23, 0x88, 0xce, 0xe9, 0xae, 0xf8, 0xc6, 0xe6, 0xc3, 0xeb, 0x58, 0xec, 0x59, 0x26, + 0xdf, 0x61, 0xb3, 0xb2, 0x0e, 0xf5, 0x35, 0x93, 0x86, 0xee, 0x45, 0xfb, 0xa8, 0x71, 0xeb, 0x45, 0x42, 0xc7, 0x5f, + 0xce, 0xeb, 0x91, 0x55, 0x6f, 0x89, 0x18, 0xa6, 0x98, 0x79, 0xcf, 0xa2, 0xde, 0xba, 0x68, 0x09, 0xd7, 0xac, 0xab, + 0x0e, 0x82, 0xa6, 0xc4, 0xd3, 0x7a, 0x70, 0x9d, 0x0b, 0xb1, 0xf8, 0xc9, 0x24, 0x5a, 0x3f, 0xf9, 0x6d, 0xdc, 0xa0, + 0xe4, 0x5c, 0x68, 0xd0, 0x85, 0x02, 0xa1, 0xf7, 0xde, 0x7b, 0x9b, 0x8f, 0xf6, 0x36, 0x35, 0xfd, 0x85, 0x79, 0xf1, + 0x47, 0x72, 0xd6, 0x6f, 0x76, 0x39, 0x70, 0x10, 0x4a, 0x9c, 0x30, 0x22, 0x5c, 0xd8, 0x34, 0x97, 0xbc, 0x94, 0x59, + 0xb9, 0x70, 0x86, 0x03, 0xd1, 0x19, 0xf1, 0x0d, 0x3f, 0xd8, 0xb6, 0x40, 0x20, 0x6e, 0xb5, 0x4c, 0x14, 0xcf, 0x88, + 0x38, 0x91, 0x65, 0x0e, 0x93, 0x9a, 0xe6, 0x72, 0xa6, 0x15, 0xbb, 0x6d, 0x05, 0x8d, 0x6f, 0x8c, 0x73, 0x2c, 0x81, + 0xde, 0xac, 0xd0, 0xce, 0xa5, 0x92, 0x8f, 0xfd, 0x8e, 0xaa, 0x9d, 0xeb, 0x2f, 0xaf, 0x65, 0x5e, 0xee, 0x3c, 0xbb, + 0x36, 0xcd, 0xcb, 0x35, 0x86, 0xce, 0x40, 0x66, 0x47, 0x75, 0x95, 0xa9, 0xbb, 0xd8, 0xe0, 0x8e, 0x42, 0x75, 0xb5, + 0x20, 0x1c, 0x80, 0x22, 0x9a, 0xe6, 0x98, 0x1b, 0xcc, 0xa2, 0xaf, 0xae, 0xf0, 0x4e, 0x07, 0x6d, 0xb5, 0xb4, 0x01, + 0x25, 0x20, 0x9c, 0x74, 0xd1, 0x61, 0x89, 0x07, 0x77, 0xa7, 0xee, 0x54, 0xd2, 0x60, 0x5c, 0x2c, 0xce, 0xc3, 0xb3, + 0x28, 0xee, 0x0a, 0xd3, 0xcc, 0x68, 0xf4, 0x03, 0x4d, 0xb4, 0xe7, 0x9b, 0xa5, 0xc4, 0x92, 0x0b, 0x76, 0xb9, 0xc7, + 0xf6, 0x03, 0x45, 0xe2, 0xa5, 0x3c, 0x56, 0x3a, 0xa5, 0xc4, 0x4e, 0x4d, 0x3b, 0x2b, 0xd3, 0x1c, 0x7a, 0x96, 0x65, + 0xe2, 0xb9, 0xf4, 0x3b, 0xaa, 0x67, 0x5b, 0x66, 0x7d, 0x53, 0xb8, 0xdb, 0x3b, 0x91, 0x12, 0x3f, 0x38, 0xd6, 0xf0, + 0xb6, 0xe8, 0x76, 0x9a, 0xbe, 0x2d, 0xdc, 0xfa, 0x05, 0x63, 0x0f, 0x8b, 0x55, 0xac, 0xbe, 0x28, 0x8e, 0x26, 0x14, + 0xd8, 0xea, 0xdf, 0xe4, 0x24, 0x4d, 0xdc, 0x4a, 0xe3, 0xaf, 0x69, 0x09, 0x53, 0x75, 0xaa, 0x7b, 0x2f, 0xb1, 0x8a, + 0xb0, 0x70, 0xff, 0x7d, 0xf5, 0x70, 0x28, 0x64, 0xb6, 0x79, 0xd6, 0x3c, 0x42, 0xba, 0x92, 0x7b, 0xc8, 0xa7, 0x4a, + 0xa6, 0xe6, 0x93, 0x93, 0xec, 0x86, 0xbb, 0x56, 0xab, 0x56, 0xc2, 0x9b, 0x66, 0xab, 0xc3, 0x75, 0xae, 0xd8, 0x68, + 0x99, 0x4d, 0x6a, 0xbb, 0x82, 0xe9, 0xdc, 0x3a, 0xf1, 0x38, 0x44, 0x22, 0x94, 0xb1, 0xbb, 0xbd, 0x51, 0x07, 0x17, + 0xb0, 0x29, 0xc1, 0x5d, 0x29, 0x38, 0x37, 0xd9, 0xe0, 0x2e, 0x88, 0xd4, 0x28, 0xae, 0x74, 0xdc, 0xdb, 0x86, 0x48, + 0xc1, 0x4e, 0x7a, 0xa4, 0x88, 0xc5, 0x69, 0xba, 0xf0, 0x34, 0xbe, 0xf2, 0x66, 0xd7, 0x34, 0x53, 0xdf, 0xa1, 0x46, + 0x8e, 0x68, 0x54, 0xee, 0x65, 0x48, 0x4c, 0x81, 0x87, 0x56, 0xe3, 0x59, 0xaa, 0x42, 0x6e, 0x30, 0xa3, 0x5b, 0xae, + 0xdb, 0xfd, 0xe2, 0xe3, 0x71, 0x39, 0x13, 0xd1, 0x85, 0xf1, 0x95, 0x1a, 0x92, 0x95, 0xec, 0x27, 0x22, 0x2f, 0x38, + 0xa6, 0xb3, 0x37, 0x45, 0x02, 0x6e, 0xe9, 0x8d, 0x8b, 0xb4, 0xa1, 0x5c, 0xcb, 0x06, 0x9d, 0x26, 0x39, 0x15, 0x54, + 0x88, 0x99, 0xb1, 0x66, 0xf1, 0xbe, 0x04, 0x09, 0x87, 0x3d, 0x85, 0x03, 0xd9, 0xd4, 0xcc, 0x6d, 0x87, 0x32, 0xd7, + 0xa1, 0x1a, 0x47, 0x62, 0xa3, 0x72, 0x08, 0x8e, 0xce, 0xdc, 0xee, 0xb1, 0xb0, 0xae, 0x60, 0x4e, 0x15, 0x59, 0x1e, + 0x9c, 0xae, 0xf6, 0x5f, 0xb8, 0x23, 0xfa, 0x62, 0x20, 0xfa, 0x9d, 0x56, 0x4d, 0xb4, 0xc0, 0x43, 0x8b, 0xeb, 0xda, + 0x42, 0x63, 0x0a, 0xe2, 0x80, 0xf4, 0x66, 0x82, 0xa2, 0xe1, 0x93, 0x66, 0x98, 0x83, 0x9e, 0xea, 0x9b, 0x9f, 0x3b, + 0x75, 0xf6, 0x65, 0x9a, 0x5e, 0x18, 0x66, 0x97, 0x06, 0xee, 0x8c, 0xa3, 0xa6, 0x18, 0x36, 0x5f, 0x8c, 0xbe, 0x89, + 0x5c, 0x9e, 0x7b, 0x56, 0x33, 0xc1, 0x34, 0x1d, 0x73, 0xe4, 0xbf, 0xc6, 0xf3, 0x7e, 0xc1, 0x71, 0x8c, 0x4a, 0x2f, + 0xbf, 0x28, 0x73, 0xa6, 0x25, 0x1b, 0xef, 0xab, 0x0b, 0xb8, 0x9e, 0x8c, 0x72, 0x24, 0x1e, 0x96, 0x59, 0x2c, 0x3f, + 0x80, 0x6f, 0x46, 0x2e, 0x41, 0x1b, 0xbb, 0x97, 0x89, 0x01, 0xc0, 0xb2, 0x5d, 0x73, 0x52, 0xbb, 0x46, 0xbe, 0x0a, + 0xb5, 0x55, 0xd7, 0xee, 0x24, 0xf3, 0x95, 0x08, 0xf6, 0x55, 0xfa, 0xe3, 0xa7, 0xa8, 0x07, 0xb5, 0xb7, 0x43, 0x92, + 0xab, 0x4d, 0xc2, 0xbe, 0x5f, 0x56, 0xa7, 0x27, 0xde, 0xbf, 0xc2, 0xe3, 0xe0, 0x02, 0x36, 0x3d, 0xf4, 0xf5, 0xb6, + 0x19, 0x89, 0x51, 0x77, 0x0d, 0xfe, 0xa0, 0xea, 0x21, 0x99, 0x1e, 0x74, 0x92, 0x47, 0x22, 0x30, 0xeb, 0xa9, 0x8e, + 0x89, 0xfc, 0x93, 0xf0, 0x73, 0xb5, 0xe7, 0xff, 0xf2, 0xf5, 0xd2, 0xcc, 0x9e, 0x21, 0xbc, 0x3b, 0xbc, 0xf9, 0xaa, + 0xd0, 0x75, 0xc6, 0xe5, 0xb1, 0x08, 0xe7, 0xce, 0xdf, 0x03, 0x70, 0xe5, 0x75, 0x79, 0xbb, 0x98, 0xef, 0x38, 0xed, + 0x2e, 0x6d, 0xde, 0xad, 0xa3, 0x86, 0x9f, 0x7f, 0xb0, 0x8d, 0x8a, 0x1f, 0xa9, 0x22, 0xfa, 0x75, 0x93, 0x05, 0x45, + 0x20, 0xe4, 0xe9, 0xeb, 0x84, 0x18, 0xff, 0x0c, 0x68, 0xfa, 0xa6, 0x50, 0xd9, 0x7f, 0xc3, 0x15, 0xa6, 0x0e, 0xe1, + 0x8f, 0xcc, 0xea, 0x60, 0x40, 0x73, 0x5b, 0xb8, 0x27, 0xfd, 0x17, 0x88, 0x35, 0x77, 0x10, 0xe0, 0x44, 0x91, 0xa4, + 0xe2, 0x87, 0x3e, 0xbc, 0x82, 0x26, 0xf7, 0x89, 0x14, 0xd4, 0x0c, 0xc5, 0x6d, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x47, + 0x87, 0xa8, 0x73, 0xf4, 0x88, 0xdd, 0x5f, 0xda, 0x9d, 0xc9, 0xc3, 0x37, 0x94, 0xac, 0x89, 0x50, 0x31, 0x98, 0x50, + 0xfe, 0x5c, 0xf7, 0x4b, 0xde, 0xb3, 0xf2, 0x95, 0xb1, 0x28, 0xb8, 0xd8, 0x1b, 0x54, 0xfd, 0x00, 0x16, 0xd0, 0x59, + 0x24, 0xa0, 0x62, 0xb7, 0x13, 0xd6, 0xa9, 0xc6, 0xf1, 0x93, 0x58, 0x36, 0xf1, 0xc3, 0xf2, 0x0d, 0xff, 0xa5, 0x21, + 0x24, 0xa1, 0x88, 0x39, 0xa9, 0xc3, 0x60, 0x47, 0x2c, 0x6e, 0x63, 0x36, 0x0f, 0xa5, 0xe6, 0x61, 0x39, 0x71, 0xde, + 0x41, 0x0b, 0x10, 0x97, 0xa3, 0xee, 0xaa, 0xb5, 0x4b, 0xa7, 0x6b, 0x1d, 0x86, 0x93, 0xd8, 0x29, 0x56, 0x78, 0x18, + 0x5b, 0x8f, 0x1c, 0x23, 0xfc, 0x77, 0x20, 0x8f, 0x2f, 0x69, 0x7e, 0x78, 0x7b, 0x47, 0x83, 0x24, 0x1a, 0x2b, 0x15, + 0xa9, 0x78, 0x4a, 0x0f, 0x2b, 0x92, 0x21, 0x4d, 0x24, 0x7a, 0x78, 0x2f, 0xdf, 0xd2, 0x78, 0x58, 0xa5, 0x62, 0x43, + 0xc7, 0xcd, 0x56, 0x07, 0x92, 0x8f, 0xb2, 0xdd, 0x5f, 0x2f, 0xbd, 0x15, 0x9a, 0x75, 0x0a, 0x9b, 0x97, 0x1e, 0xb7, + 0xd8, 0xbb, 0x67, 0x31, 0xf5, 0x53, 0xa0, 0xc6, 0x91, 0x1c, 0x88, 0x89, 0xb1, 0xa9, 0x80, 0x3c, 0xf3, 0xe4, 0xe4, + 0xfd, 0xe0, 0xf5, 0x87, 0x63, 0x1f, 0x4f, 0xa4, 0x7c, 0xcc, 0xce, 0x70, 0xcf, 0xa7, 0x5e, 0x7e, 0xa6, 0x59, 0x1e, + 0x88, 0x9d, 0x8e, 0xe2, 0x21, 0x1f, 0xdd, 0x89, 0x50, 0x23, 0x2c, 0x27, 0x6b, 0xd5, 0x4a, 0x6b, 0x0c, 0x6a, 0x85, + 0x32, 0x97, 0xfb, 0x58, 0xdc, 0xda, 0xfd, 0x68, 0x93, 0xef, 0x7e, 0xa6, 0x88, 0xe7, 0x24, 0x02, 0xb9, 0xfe, 0x61, + 0x90, 0x96, 0x82, 0x79, 0x69, 0xa4, 0x95, 0xfa, 0x13, 0x4a, 0x39, 0xf0, 0x10, 0xf0, 0x25, 0x11, 0x97, 0x86, 0xb6, + 0xfe, 0x07, 0x4c, 0x5e, 0xd7, 0xbd, 0x6f, 0x25, 0xce, 0x9a, 0x70, 0x6e, 0x89, 0x7b, 0xac, 0xe5, 0x27, 0xb5, 0x24, + 0x0f, 0x0a, 0xa3, 0xbd, 0x9d, 0x1e, 0x1a, 0xa6, 0xc5, 0x2b, 0x16, 0xc5, 0x27, 0x7d, 0x2a, 0xbf, 0x07, 0xb5, 0xeb, + 0x2c, 0x75, 0xd9, 0x0b, 0xe5, 0x4c, 0xa9, 0xce, 0x0a, 0xbf, 0x76, 0x18, 0x5a, 0xe9, 0x48, 0x9a, 0x25, 0xce, 0xd5, + 0x7b, 0xec, 0x26, 0x4e, 0xb8, 0x21, 0x0d, 0x14, 0xa8, 0x64, 0x36, 0x1c, 0xd1, 0x53, 0x18, 0xdb, 0xfa, 0x32, 0xc3, + 0xed, 0x87, 0x32, 0xee, 0xe0, 0x68, 0xb2, 0x9a, 0x22, 0x5f, 0x27, 0x45, 0x2c, 0x14, 0x49, 0xd8, 0x85, 0x4b, 0x3b, + 0xbf, 0xc1, 0x5a, 0x69, 0x7e, 0x31, 0x5e, 0x30, 0xde, 0x65, 0x5d, 0xc9, 0x87, 0xcf, 0xba, 0x3b, 0x47, 0x04, 0xc8, + 0xa3, 0x9c, 0xd4, 0x3c, 0x82, 0xdb, 0x84, 0xa8, 0xb7, 0xb7, 0x3d, 0xb9, 0xe1, 0xcc, 0xb6, 0x45, 0x8b, 0x55, 0x2f, + 0x57, 0xb2, 0xdf, 0x9e, 0x95, 0x85, 0x82, 0xec, 0x6e, 0xe0, 0xc8, 0x9d, 0xe9, 0xc4, 0x6f, 0x18, 0x48, 0xef, 0x41, + 0x2d, 0x38, 0xba, 0x6e, 0x01, 0xa8, 0x35, 0xb4, 0x91, 0x4e, 0x5f, 0x23, 0xdb, 0xc8, 0xb8, 0xbc, 0x77, 0x1c, 0x41, + 0x71, 0xc0, 0xf8, 0xfa, 0xde, 0x31, 0x9d, 0x96, 0x80, 0xa4, 0x8f, 0x98, 0x0f, 0x03, 0x8c, 0x82, 0x18, 0x03, 0xd5, + 0xea, 0xf1, 0x01, 0x4f, 0x40, 0xc4, 0x91, 0xad, 0x0e, 0x6e, 0xdc, 0x20, 0x6f, 0x1d, 0x19, 0x07, 0x9f, 0x90, 0x6e, + 0x28, 0x61, 0x30, 0x5e, 0xfe, 0xc8, 0x40, 0x75, 0xa1, 0x8e, 0x0d, 0xae, 0x6d, 0x14, 0x34, 0xce, 0x0c, 0x10, 0x08, + 0x3e, 0xbd, 0x5d, 0xe9, 0xaf, 0xe3, 0x0f, 0x3a, 0xab, 0x37, 0x05, 0xa9, 0x95, 0xd3, 0xa3, 0x36, 0x5b, 0xe8, 0x2a, + 0xa0, 0x70, 0xa6, 0x7a, 0xc2, 0x80, 0xeb, 0x0f, 0x1b, 0x06, 0xe6, 0x3d, 0x27, 0x94, 0xd9, 0x1c, 0x09, 0x7f, 0x49, + 0xb3, 0x6f, 0xd6, 0x30, 0xcf, 0xe5, 0xd8, 0x83, 0x1d, 0x02, 0xb9, 0x7a, 0x18, 0xfb, 0x2d, 0xb6, 0x4d, 0x10, 0xe6, + 0xb0, 0xfc, 0xf8, 0x9f, 0x0a, 0xb5, 0x15, 0x4a, 0xed, 0xcd, 0x8f, 0x1c, 0xd6, 0xce, 0x73, 0x79, 0xfc, 0x4f, 0x28, + 0xf2, 0xd9, 0x3c, 0xe4, 0x79, 0xb2, 0xd8, 0x36, 0x88, 0x3f, 0x3d, 0xb2, 0x77, 0x36, 0xbb, 0xd6, 0x3e, 0xc8, 0xcf, + 0x60, 0x97, 0x7f, 0x0f, 0x09, 0xd5, 0xb0, 0x65, 0x05, 0x3f, 0x8c, 0x47, 0x04, 0x80, 0x85, 0x5e, 0xbf, 0xd9, 0x37, + 0xe4, 0x66, 0x1f, 0x90, 0x19, 0xf4, 0x39, 0xa2, 0x91, 0x67, 0xc6, 0x35, 0xec, 0xcc, 0x73, 0x3e, 0xf7, 0x0c, 0xe7, + 0x07, 0xca, 0x7a, 0xca, 0x9c, 0xe7, 0x25, 0x1b, 0xf7, 0xb6, 0x70, 0x06, 0xba, 0xd5, 0x8c, 0x5d, 0xd8, 0x82, 0xe5, + 0x3b, 0x6b, 0xc1, 0xa9, 0x1b, 0x30, 0x7b, 0x7b, 0xee, 0x4f, 0x74, 0xe0, 0xcf, 0x50, 0xde, 0xc9, 0xa8, 0xd5, 0x6f, + 0xbe, 0x75, 0x3b, 0x8d, 0x01, 0x6f, 0x84, 0xa7, 0x8a, 0xea, 0xcc, 0x39, 0x7b, 0x0a, 0x72, 0x21, 0xfe, 0xa2, 0x1b, + 0x7c, 0x42, 0xb7, 0x2a, 0x0a, 0x01, 0x5f, 0xda, 0x62, 0x44, 0xc8, 0x3a, 0xb4, 0xa4, 0x94, 0x27, 0x6d, 0x3e, 0x51, + 0x73, 0xa7, 0xe8, 0x34, 0xb7, 0x32, 0x3f, 0x9c, 0x39, 0x81, 0x0d, 0x02, 0x49, 0x48, 0x11, 0xc2, 0x3f, 0xc5, 0x8e, + 0x7b, 0x67, 0x6c, 0xb9, 0x91, 0xd0, 0xa0, 0x5d, 0x94, 0x8a, 0x18, 0x1f, 0x95, 0x4e, 0x23, 0xae, 0x7b, 0x8f, 0xf0, + 0x0f, 0xf6, 0x3f, 0xd3, 0xa8, 0x4c, 0xff, 0x9d, 0x46, 0x61, 0xfa, 0xcf, 0x69, 0x08, 0xa6, 0xff, 0x9e, 0x06, 0xbb, + 0x4b, 0xad, 0x0e, 0xec, 0xab, 0x23, 0xfb, 0xea, 0xce, 0x1e, 0xa7, 0xd9, 0x1e, 0x5a, 0x7b, 0x5f, 0x83, 0x76, 0x6c, + 0x3f, 0xf1, 0x2d, 0x39, 0xe0, 0xad, 0x63, 0x59, 0xb2, 0xf1, 0x76, 0x8a, 0xbd, 0xcf, 0xe9, 0xd2, 0xe5, 0x71, 0x1f, + 0xc5, 0x53, 0x1e, 0x87, 0xd5, 0x74, 0x56, 0x51, 0x67, 0x5a, 0xa6, 0x91, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x6a, 0x3e, + 0x42, 0xde, 0xad, 0x25, 0x9c, 0x81, 0xd2, 0x04, 0xf9, 0xad, 0xe7, 0x8f, 0x8d, 0x62, 0x2f, 0x1a, 0x6f, 0xbb, 0xfb, + 0x99, 0x21, 0xce, 0x5f, 0x0c, 0x91, 0x54, 0xa6, 0x15, 0x26, 0xda, 0xc1, 0xd4, 0x6d, 0xcd, 0x5a, 0xac, 0x29, 0x20, + 0xb3, 0x3d, 0x8f, 0xb2, 0x25, 0x08, 0xe1, 0xb9, 0x6d, 0xe1, 0x3f, 0x0b, 0x58, 0x75, 0xb1, 0x85, 0x5e, 0x73, 0x39, + 0xe8, 0xb4, 0x52, 0xe9, 0x3e, 0x6b, 0x10, 0xbb, 0xa1, 0x4c, 0x77, 0x84, 0x8c, 0xe1, 0x05, 0x8b, 0x2b, 0x28, 0xea, + 0x17, 0x62, 0x71, 0x17, 0xb3, 0x87, 0xe7, 0x27, 0x65, 0x1a, 0xfc, 0xbf, 0x16, 0xdb, 0x41, 0x77, 0x42, 0x53, 0xe3, + 0x92, 0x4b, 0x2a, 0xec, 0x17, 0x62, 0xdc, 0x9e, 0xdb, 0x45, 0xd7, 0xb7, 0x4e, 0x19, 0x89, 0xcf, 0xf9, 0x0c, 0xe4, + 0x7a, 0xe9, 0xa7, 0xfa, 0xf4, 0x88, 0x0b, 0xb2, 0xa8, 0xa7, 0x39, 0xc1, 0xaa, 0x10, 0x33, 0x52, 0x87, 0x9a, 0x12, + 0x9f, 0xbf, 0xfa, 0x9f, 0xf6, 0x6b, 0x49, 0x3c, 0x68, 0xa7, 0x5f, 0xf9, 0xf5, 0xb1, 0x10, 0x97, 0xf6, 0x33, 0xf1, + 0xe3, 0xad, 0x62, 0xed, 0x0f, 0xa8, 0x7a, 0x9c, 0xaa, 0xff, 0x3d, 0x6a, 0xd1, 0xaf, 0xc3, 0x65, 0xd3, 0x7f, 0x2d, + 0x89, 0x07, 0xec, 0xf5, 0xeb, 0xf3, 0x3b, 0x18, 0xfc, 0x13, 0x43, 0xf2, 0xc8, 0x76, 0x02, 0x94, 0xe3, 0x47, 0xd1, + 0xe4, 0x38, 0xe4, 0x4c, 0x53, 0xae, 0x2b, 0x3c, 0xbd, 0xea, 0x68, 0x4c, 0x95, 0x8b, 0x23, 0xe9, 0xf4, 0x7c, 0x02, + 0x13, 0xd9, 0xf0, 0x96, 0xd9, 0xa5, 0xc8, 0xde, 0xc3, 0x11, 0x64, 0xb7, 0xcd, 0x27, 0x31, 0xcb, 0x67, 0x11, 0x2d, + 0xdb, 0x35, 0xd8, 0xe8, 0x94, 0xc3, 0x54, 0x5c, 0x38, 0xc0, 0xbe, 0xb7, 0x5c, 0x18, 0xec, 0x46, 0x6a, 0x1f, 0xa2, + 0x72, 0x7a, 0x1b, 0xd1, 0x6f, 0xca, 0x71, 0xf4, 0x7e, 0x1b, 0xac, 0x96, 0xc2, 0xc3, 0x43, 0x83, 0x58, 0xb5, 0xc3, + 0x2b, 0x46, 0xfd, 0xe2, 0x3a, 0xd4, 0x6e, 0x00, 0x4e, 0x9c, 0x69, 0xd3, 0xf5, 0xe3, 0xfc, 0xc2, 0x9f, 0xea, 0xd3, + 0x95, 0xd5, 0x53, 0x0f, 0x5d, 0xc4, 0xd1, 0x19, 0x97, 0x9d, 0x83, 0x12, 0x23, 0x8c, 0x19, 0x9e, 0xbf, 0x37, 0x2b, + 0x4b, 0x28, 0x48, 0x0b, 0xbd, 0x16, 0x54, 0x19, 0xfd, 0xfb, 0x03, 0xc5, 0xb9, 0xbc, 0x7f, 0xae, 0x7b, 0xff, 0x1e, + 0x33, 0xb4, 0xcd, 0x8c, 0x7a, 0xab, 0xe0, 0x3e, 0x9f, 0x24, 0xb0, 0x48, 0x96, 0x58, 0xdb, 0xe2, 0xff, 0xea, 0x12, + 0xeb, 0x34, 0xaa, 0xbd, 0xc2, 0xd5, 0x99, 0xb6, 0xe6, 0xab, 0xfa, 0x52, 0x73, 0xaf, 0xee, 0x47, 0x3f, 0xd8, 0x30, + 0x8d, 0x4b, 0x7b, 0x5a, 0x90, 0x9b, 0x64, 0xcf, 0xa2, 0xc7, 0xe6, 0x64, 0x1c, 0x5a, 0xf5, 0x43, 0x93, 0x00, 0x51, + 0xc6, 0xa9, 0x47, 0x9a, 0xf2, 0x59, 0xee, 0xc3, 0x12, 0x2f, 0xb8, 0x10, 0xd7, 0xc3, 0xed, 0xee, 0x9e, 0x91, 0x1d, + 0xa8, 0xf2, 0x9b, 0x77, 0x87, 0xf7, 0x7d, 0xa4, 0xfc, 0x0e, 0x54, 0xb3, 0xbe, 0x59, 0xa9, 0x08, 0xd4, 0x15, 0x28, + 0x02, 0x5c, 0xbe, 0x67, 0x95, 0xe0, 0xae, 0xe6, 0x79, 0x18, 0xb1, 0x92, 0x84, 0x9a, 0x2b, 0x05, 0x87, 0xc5, 0xa6, + 0x29, 0x45, 0x61, 0xb1, 0x26, 0xfa, 0x75, 0xcd, 0xa6, 0xd3, 0x45, 0x0d, 0x9c, 0x1b, 0x98, 0xa5, 0x9b, 0x35, 0xa2, + 0x1f, 0x12, 0xf2, 0x0e, 0x9e, 0x66, 0x8b, 0x6d, 0x20, 0x86, 0x5a, 0x5c, 0x63, 0x60, 0x7b, 0xf8, 0x90, 0x07, 0xf4, + 0xa4, 0xff, 0x74, 0x0d, 0xd1, 0x23, 0xdb, 0x80, 0xc5, 0x6f, 0x26, 0x75, 0x78, 0xf7, 0x30, 0x3d, 0xe3, 0xa5, 0x4f, + 0xc6, 0x2f, 0x0e, 0x6d, 0x86, 0x9f, 0x1e, 0x51, 0x54, 0x24, 0x2a, 0x77, 0x76, 0xd9, 0xcf, 0x86, 0x4c, 0xed, 0xe9, + 0x78, 0xb2, 0xbf, 0x60, 0x6e, 0xfd, 0x60, 0x7f, 0x18, 0xc7, 0x83, 0x04, 0x35, 0x14, 0x1b, 0xfe, 0x71, 0xa3, 0x58, + 0x24, 0x3d, 0x5b, 0x6f, 0xfb, 0xe0, 0x95, 0x50, 0xce, 0x2b, 0xd7, 0x32, 0x3d, 0xd3, 0xb1, 0x83, 0x67, 0xfa, 0xc1, + 0xea, 0x32, 0x01, 0x95, 0xdf, 0x85, 0x89, 0x81, 0x73, 0x24, 0xca, 0x11, 0x19, 0xf1, 0xa2, 0xe8, 0x4b, 0x36, 0x87, + 0x56, 0x58, 0x0d, 0xba, 0xa5, 0xe8, 0xaf, 0x57, 0x76, 0x97, 0xfa, 0xae, 0xcf, 0x5e, 0xe4, 0xf6, 0xe6, 0x63, 0x19, + 0x3a, 0x14, 0x29, 0x25, 0xa7, 0xfe, 0x64, 0x0c, 0x79, 0x7d, 0x3d, 0x75, 0xa6, 0xf8, 0xcf, 0x6c, 0x90, 0xc4, 0x6c, + 0x00, 0x0a, 0x59, 0x34, 0x8f, 0x00, 0x60, 0x49, 0x5f, 0x24, 0x81, 0x37, 0xfc, 0x43, 0xac, 0x59, 0x37, 0x44, 0xcc, + 0x57, 0xfb, 0xe6, 0xe2, 0x32, 0x0b, 0x77, 0x76, 0xec, 0xd1, 0x3d, 0x79, 0x10, 0x95, 0x25, 0x99, 0x4d, 0x67, 0xed, + 0x3d, 0xa4, 0xaf, 0x0c, 0x79, 0x06, 0x99, 0x32, 0x40, 0x02, 0xa6, 0x23, 0xac, 0x33, 0x3c, 0xb9, 0xe6, 0xdc, 0x6a, + 0xb2, 0x50, 0x82, 0x43, 0x74, 0x1c, 0xdd, 0x0a, 0x49, 0xd6, 0xdc, 0x6b, 0xbe, 0xd4, 0x0f, 0x52, 0x4e, 0x3e, 0xad, + 0x98, 0x27, 0x8e, 0xe3, 0x37, 0x24, 0xa2, 0x27, 0x11, 0xe5, 0x69, 0xd7, 0x39, 0xe4, 0xb7, 0xac, 0x54, 0xcc, 0x0c, + 0x54, 0x3d, 0xf2, 0x54, 0x13, 0xac, 0xbb, 0xc5, 0x1d, 0x88, 0xa7, 0x0f, 0x44, 0x13, 0x8a, 0x93, 0xac, 0xf2, 0x5a, + 0x0f, 0xb3, 0xe1, 0x2b, 0x62, 0x73, 0x35, 0xda, 0xec, 0x58, 0xcc, 0xd8, 0x0a, 0x9a, 0x60, 0x40, 0x9d, 0x11, 0x4e, + 0xbb, 0x76, 0xf7, 0x28, 0x30, 0xb2, 0xe9, 0x94, 0x7e, 0x8c, 0xa8, 0xd0, 0x6d, 0xbe, 0x8c, 0x0a, 0x71, 0x54, 0x84, + 0x9e, 0x87, 0xa1, 0x50, 0xfa, 0x69, 0x59, 0x14, 0xf1, 0x59, 0x3f, 0xe7, 0xae, 0xc6, 0x18, 0x53, 0x34, 0x95, 0x65, + 0xd7, 0x15, 0xc8, 0x1b, 0xb1, 0x35, 0x44, 0x80, 0x3c, 0x5f, 0x35, 0xed, 0xea, 0xd7, 0x9b, 0xa8, 0xfc, 0x3b, 0x36, + 0xba, 0x8d, 0x76, 0x13, 0x78, 0x56, 0x9c, 0xb9, 0x2d, 0x80, 0x35, 0x3a, 0xd7, 0x25, 0x71, 0xe4, 0xe8, 0x71, 0xbd, + 0x1f, 0xcc, 0xfe, 0xa4, 0xb5, 0x78, 0x90, 0x6f, 0x91, 0xa9, 0x95, 0x52, 0x17, 0xea, 0xb5, 0x65, 0x1a, 0xcf, 0x07, + 0x99, 0x49, 0xf9, 0x84, 0xd1, 0xf9, 0xd2, 0x4d, 0xf3, 0xc2, 0x66, 0x81, 0xc9, 0x44, 0x25, 0x4e, 0x61, 0x3a, 0xb7, + 0x4b, 0x84, 0xa4, 0x3b, 0x82, 0x53, 0x59, 0x56, 0x14, 0x77, 0xb7, 0xad, 0xd9, 0x37, 0x93, 0xbf, 0x26, 0x3d, 0x1c, + 0xe3, 0x2e, 0xe8, 0xd8, 0x28, 0x6f, 0x26, 0xdb, 0x83, 0xc9, 0xc3, 0xea, 0x42, 0xe9, 0xb4, 0x9a, 0x6e, 0xea, 0x19, + 0xb9, 0xb9, 0x71, 0xea, 0x6a, 0xa2, 0xeb, 0x12, 0x30, 0x9e, 0x8d, 0xe2, 0x1e, 0x5b, 0xe4, 0x1a, 0x79, 0x6d, 0x2d, + 0x41, 0xb7, 0x2c, 0x14, 0x8b, 0xd1, 0xd4, 0xc0, 0x18, 0x61, 0x52, 0x11, 0x83, 0xd7, 0xe7, 0xb0, 0xc9, 0x13, 0x13, + 0xa8, 0xea, 0xdf, 0x94, 0x93, 0x25, 0xbb, 0x98, 0xa5, 0x91, 0x0c, 0xcb, 0x41, 0xd9, 0x7b, 0xa2, 0xa5, 0x8f, 0x78, + 0x2e, 0x70, 0x6d, 0xdb, 0xf6, 0x61, 0x6d, 0x6b, 0xc0, 0xc0, 0xfb, 0xa6, 0x7d, 0x07, 0xc1, 0x15, 0xbb, 0xd5, 0x9c, + 0x67, 0xf0, 0x78, 0xc0, 0xec, 0x5b, 0xf2, 0x7c, 0x5e, 0xa8, 0xb2, 0x7d, 0xa2, 0xb3, 0xfb, 0x02, 0x42, 0x31, 0xbb, + 0xd1, 0xe5, 0xd9, 0x6e, 0xbb, 0x87, 0x0c, 0x59, 0x90, 0xb1, 0x24, 0x29, 0x3c, 0xf2, 0x9d, 0x5e, 0x6d, 0x19, 0x6b, + 0x3e, 0x73, 0x19, 0xb7, 0xa4, 0x16, 0x94, 0x6a, 0x0f, 0x6d, 0x8a, 0xf2, 0x5a, 0x84, 0x49, 0x15, 0xd6, 0x6e, 0xf3, + 0x99, 0xca, 0xd1, 0x16, 0x91, 0x09, 0x1e, 0x17, 0x12, 0x3b, 0x83, 0x25, 0x82, 0x0c, 0x9d, 0x26, 0x68, 0x6a, 0x9f, + 0x44, 0xb3, 0xb8, 0xe6, 0xc1, 0xa8, 0xa6, 0xca, 0xe1, 0x75, 0x13, 0x26, 0xcc, 0xe3, 0x42, 0xda, 0x76, 0xc4, 0x24, + 0x5d, 0xc7, 0xf9, 0x6a, 0x25, 0xeb, 0x51, 0x8e, 0xcc, 0x73, 0xa5, 0xb3, 0x95, 0x2e, 0xe6, 0x41, 0x29, 0xca, 0xcb, + 0x50, 0x20, 0x91, 0x93, 0xad, 0x66, 0x6f, 0x2f, 0x8d, 0xd5, 0x40, 0xa4, 0x57, 0xd6, 0xc7, 0x23, 0x58, 0x4c, 0x17, + 0x29, 0xa5, 0x60, 0x03, 0x85, 0xb0, 0xd1, 0xd8, 0xb3, 0x56, 0xfe, 0xf9, 0xb9, 0xa6, 0x5a, 0xf5, 0x67, 0x84, 0x6d, + 0xf6, 0x8b, 0xf7, 0xe5, 0x58, 0x05, 0x18, 0x75, 0x2f, 0xb2, 0x22, 0x79, 0xab, 0xcb, 0x5b, 0x24, 0x6f, 0xbe, 0xbc, + 0x32, 0x71, 0xc2, 0xf3, 0xb5, 0xd6, 0x86, 0x09, 0x77, 0x6e, 0x55, 0xeb, 0x88, 0x2b, 0x31, 0xd7, 0x7e, 0xdf, 0xa0, + 0x9f, 0x26, 0xa2, 0xec, 0x5f, 0xcd, 0xa8, 0x90, 0x4d, 0x9f, 0x12, 0xaa, 0xcd, 0xbc, 0x8c, 0x90, 0xbb, 0x17, 0x83, + 0x49, 0xa9, 0x4e, 0x5d, 0xdd, 0xe6, 0xe3, 0x8b, 0x31, 0xb1, 0x7e, 0xf9, 0xd7, 0xb8, 0x38, 0x5f, 0x30, 0x1c, 0xba, + 0xe2, 0xce, 0x7b, 0xd6, 0x0a, 0xe5, 0x0a, 0x73, 0xc0, 0x39, 0x5a, 0xaa, 0x2a, 0x63, 0xd4, 0xb6, 0xea, 0xdc, 0x01, + 0x8f, 0x23, 0x08, 0xfc, 0x8e, 0xae, 0x1a, 0x49, 0x46, 0xa9, 0xef, 0xea, 0x18, 0xfc, 0x65, 0xa4, 0xf1, 0xe1, 0xf7, + 0x05, 0x11, 0xf4, 0xd2, 0x55, 0xe5, 0xda, 0xa3, 0x2a, 0xa2, 0xac, 0x82, 0x24, 0xe6, 0x64, 0xb9, 0x0b, 0x47, 0xb9, + 0xf1, 0xe7, 0x93, 0x5d, 0xad, 0x0d, 0x42, 0xcc, 0x62, 0xcc, 0xd9, 0x52, 0xcc, 0x59, 0x11, 0xbe, 0x7d, 0x1e, 0xfd, + 0xce, 0x55, 0x25, 0x10, 0xf9, 0x68, 0xe3, 0x51, 0x7c, 0xf9, 0x22, 0xe0, 0x69, 0x55, 0x7d, 0x20, 0x24, 0xbe, 0xb3, + 0xd3, 0x2e, 0xf9, 0x6b, 0x7f, 0xa6, 0x44, 0x32, 0x69, 0x89, 0x21, 0x70, 0x47, 0xfc, 0xce, 0x75, 0x03, 0x19, 0x80, + 0x9c, 0xd1, 0xae, 0x01, 0x73, 0x12, 0x4d, 0x43, 0x42, 0xd5, 0xb4, 0x96, 0x77, 0xf3, 0x0a, 0x7d, 0x22, 0x89, 0x7e, + 0x97, 0x37, 0xc3, 0xaf, 0xb4, 0x48, 0xe5, 0x9c, 0xbf, 0xef, 0xe2, 0x57, 0x75, 0x64, 0xe7, 0x4c, 0x63, 0xa5, 0xc0, + 0x97, 0x01, 0xb8, 0x81, 0x76, 0xc5, 0x8d, 0x38, 0xce, 0x92, 0x1e, 0xd9, 0x19, 0x3d, 0x50, 0xdb, 0x57, 0xb2, 0x68, + 0x29, 0x5e, 0x98, 0xa6, 0x10, 0xca, 0xe0, 0x22, 0x3e, 0x91, 0xb9, 0xa8, 0xb2, 0xe6, 0x55, 0x5f, 0xe0, 0x36, 0x22, + 0x66, 0x44, 0x79, 0x22, 0x92, 0x9c, 0x95, 0xba, 0xa1, 0xc1, 0xe2, 0xe8, 0xd2, 0x62, 0x4d, 0x4e, 0x90, 0xcc, 0x97, + 0x88, 0xe0, 0x5f, 0x2e, 0xd5, 0xb3, 0xfb, 0x9b, 0xb5, 0x67, 0x85, 0xb6, 0x46, 0x60, 0xb2, 0x8b, 0x5e, 0xbd, 0xe8, + 0x35, 0xb7, 0x86, 0xf2, 0x21, 0x51, 0xc8, 0xef, 0x49, 0xdd, 0x1a, 0xd6, 0x4c, 0x52, 0x30, 0xdf, 0x17, 0xb5, 0x45, + 0xeb, 0xce, 0xb1, 0x97, 0x3f, 0xea, 0x71, 0xf7, 0x54, 0x82, 0x82, 0xd0, 0x6d, 0x26, 0xb5, 0x40, 0x24, 0x59, 0x63, + 0x8b, 0x7d, 0x22, 0x7a, 0xc7, 0x74, 0xa5, 0x74, 0x71, 0x64, 0xfb, 0xe5, 0x1d, 0x32, 0x93, 0x9c, 0x5d, 0x2a, 0x31, + 0xe5, 0x3f, 0x47, 0xd9, 0xe4, 0x62, 0x67, 0x8b, 0x3e, 0x73, 0x90, 0x36, 0x53, 0x13, 0x61, 0x0a, 0xf6, 0xce, 0xcc, + 0x46, 0x08, 0x8f, 0x24, 0x93, 0xc2, 0x28, 0xb1, 0x97, 0x7c, 0x8a, 0xa7, 0x90, 0xdf, 0x2a, 0x34, 0xb4, 0xe4, 0x99, + 0xfe, 0x07, 0xeb, 0x08, 0xdf, 0x4a, 0xe0, 0x20, 0xc9, 0x3f, 0x60, 0xc1, 0x6d, 0xe9, 0x7a, 0xc7, 0x6c, 0x90, 0x84, + 0xfb, 0x67, 0x96, 0xcf, 0x76, 0x7b, 0x10, 0xbf, 0x29, 0x12, 0x82, 0x2f, 0x3a, 0xaa, 0x5d, 0xb2, 0x8c, 0x4a, 0xaa, + 0x45, 0xe5, 0x7e, 0x7c, 0xcc, 0xcb, 0x23, 0x2a, 0x2f, 0xe0, 0x97, 0xef, 0xd6, 0x1c, 0x98, 0x81, 0xaf, 0xb4, 0xd5, + 0x44, 0xc2, 0x5e, 0x18, 0xec, 0x29, 0x94, 0x2c, 0xe2, 0xc0, 0x6e, 0x36, 0xc4, 0x5c, 0xe8, 0x5a, 0x9b, 0xed, 0xc3, + 0x18, 0x6a, 0x75, 0xca, 0xf4, 0x26, 0xae, 0x6a, 0x84, 0xb9, 0x4d, 0x23, 0x8e, 0x4a, 0x66, 0xda, 0x97, 0x1b, 0x4c, + 0xd3, 0x21, 0x7b, 0x1b, 0x68, 0x2d, 0xdf, 0x1c, 0xeb, 0xca, 0x9b, 0x69, 0x8f, 0x42, 0xc0, 0x18, 0xb1, 0xe6, 0x8a, + 0x5e, 0x6b, 0x65, 0x3f, 0x48, 0xb1, 0x3f, 0xaa, 0x05, 0x22, 0xaa, 0x22, 0xa9, 0xd9, 0xb0, 0xcb, 0x5e, 0xad, 0xbd, + 0xac, 0x0b, 0xb0, 0x74, 0x6a, 0x39, 0xd6, 0xbc, 0x60, 0x30, 0x94, 0xa9, 0x5a, 0x2d, 0x73, 0x87, 0xab, 0xec, 0xa9, + 0x96, 0x97, 0xb2, 0x20, 0x61, 0x2f, 0x81, 0xe8, 0xc4, 0xf7, 0x74, 0x4f, 0x22, 0xdf, 0x99, 0xd3, 0x37, 0x66, 0x32, + 0xc4, 0xe8, 0xac, 0x58, 0x81, 0x55, 0xbd, 0x0d, 0x0c, 0x15, 0xb5, 0xc6, 0x86, 0xee, 0xf2, 0x98, 0x7d, 0x8e, 0xc3, + 0x7d, 0x61, 0xbf, 0x2d, 0xc8, 0x7d, 0xf8, 0xef, 0x59, 0x7e, 0xdb, 0xd8, 0x2c, 0xcc, 0xb2, 0xde, 0x3c, 0x46, 0x8e, + 0xf0, 0x7a, 0x4b, 0xa5, 0xca, 0x16, 0x0c, 0xd9, 0x6b, 0x58, 0xf7, 0xab, 0x99, 0xba, 0x90, 0x6e, 0x62, 0x46, 0x8c, + 0xda, 0x9d, 0x48, 0x12, 0xf4, 0x14, 0x33, 0x28, 0xa1, 0x79, 0x91, 0xd6, 0x66, 0x23, 0xf7, 0x60, 0x9d, 0x8e, 0x4c, + 0x44, 0x97, 0x60, 0x8a, 0x73, 0x36, 0xdf, 0xdf, 0x61, 0xc8, 0x61, 0x8f, 0x25, 0xaa, 0xe4, 0x41, 0xbd, 0x6f, 0x65, + 0xa5, 0xa6, 0xd8, 0x74, 0x2c, 0x23, 0x2e, 0x37, 0x80, 0x83, 0x1d, 0x6d, 0xa7, 0x86, 0x39, 0xb5, 0x73, 0x09, 0x76, + 0x72, 0x53, 0x7b, 0xb7, 0x22, 0x03, 0x4b, 0x1e, 0x08, 0x55, 0x18, 0xf0, 0x69, 0x5f, 0x11, 0x00, 0x9a, 0xe3, 0x14, + 0x89, 0x3f, 0x8c, 0xe4, 0xef, 0x77, 0x24, 0x9d, 0x84, 0xe3, 0x6e, 0x24, 0x70, 0x7a, 0x1c, 0xc0, 0x28, 0xf5, 0x64, + 0xf3, 0x03, 0x10, 0xe5, 0x22, 0x7f, 0x95, 0x18, 0x1d, 0x31, 0x44, 0x38, 0xf0, 0x53, 0x71, 0x21, 0x6d, 0xbd, 0x59, + 0x2e, 0x8e, 0x46, 0x41, 0xd7, 0xd5, 0x01, 0xf7, 0x91, 0x0a, 0x00, 0x6d, 0x36, 0xe4, 0xba, 0xbe, 0x77, 0x88, 0xd8, + 0x7d, 0x5a, 0xb8, 0x41, 0x04, 0x7e, 0x5c, 0xa6, 0xe6, 0x5b, 0x38, 0x5c, 0xd3, 0x4c, 0xbd, 0x95, 0xc7, 0xd3, 0x7d, + 0xdd, 0xed, 0x0c, 0xf0, 0x2f, 0x97, 0x38, 0x60, 0xfe, 0x3b, 0xa9, 0xe2, 0x60, 0xc4, 0x1c, 0x1d, 0xe3, 0x92, 0x66, + 0x66, 0x6a, 0xc8, 0x73, 0x73, 0xe5, 0x29, 0xca, 0x81, 0xcc, 0x27, 0xd3, 0x43, 0x76, 0x13, 0xf8, 0x35, 0x40, 0x5d, + 0x3c, 0x24, 0x54, 0x80, 0x7a, 0x82, 0xc0, 0xd5, 0x04, 0xc2, 0xb2, 0xf9, 0x73, 0x6c, 0xee, 0x99, 0x68, 0x02, 0x1a, + 0x3a, 0x50, 0xe9, 0xf4, 0xa4, 0x2c, 0x80, 0x7a, 0xa8, 0xfd, 0x10, 0x09, 0x0f, 0x7a, 0xd9, 0x74, 0xd0, 0xb8, 0x8e, + 0x46, 0x48, 0x9a, 0x50, 0x90, 0xb8, 0xc0, 0x29, 0xfa, 0x6a, 0xc9, 0xfc, 0x55, 0x22, 0xdf, 0xa8, 0x72, 0xd1, 0xe0, + 0x5f, 0xa2, 0x45, 0x56, 0xcf, 0x18, 0x99, 0x1d, 0x6d, 0xca, 0x4a, 0x65, 0xbc, 0x00, 0xf0, 0xe1, 0x10, 0x1c, 0x49, + 0x44, 0x2c, 0x93, 0x68, 0x22, 0x1b, 0x87, 0xf2, 0xa7, 0x97, 0x77, 0x0a, 0xe0, 0x7a, 0x1e, 0x09, 0x9a, 0x08, 0x7c, + 0x6c, 0x09, 0x38, 0x33, 0x83, 0x00, 0x67, 0xab, 0x4d, 0x23, 0x30, 0x11, 0x5a, 0x79, 0x6a, 0xd8, 0xc7, 0x48, 0x94, + 0xe3, 0x12, 0x61, 0xe4, 0x76, 0x4d, 0x19, 0xb9, 0x44, 0x24, 0x36, 0xe6, 0xc8, 0x73, 0xfd, 0x51, 0x0a, 0xfd, 0xcb, + 0x2c, 0x7c, 0x52, 0xa2, 0xfa, 0xd2, 0xa0, 0x78, 0xd3, 0xc6, 0x07, 0x3b, 0x18, 0xd7, 0x52, 0xcb, 0x61, 0xc2, 0x60, + 0xbe, 0xf6, 0xff, 0xc6, 0xd7, 0x4a, 0xf5, 0x95, 0xf3, 0x11, 0x5d, 0xf1, 0x18, 0x1c, 0xd6, 0x89, 0x9c, 0x5f, 0x37, + 0x4d, 0xe4, 0xf8, 0x73, 0x79, 0xb7, 0x37, 0x9e, 0xee, 0x36, 0x82, 0xca, 0xa5, 0x34, 0x67, 0x9e, 0x11, 0x7d, 0x18, + 0x58, 0xbe, 0x58, 0xa3, 0xca, 0x34, 0xbe, 0x74, 0x40, 0xb9, 0xe2, 0xf0, 0xf4, 0x24, 0x10, 0x2f, 0x07, 0x7b, 0x8a, + 0x03, 0x62, 0x45, 0x89, 0xb2, 0x67, 0x2a, 0x22, 0x8d, 0x43, 0x60, 0xbd, 0x11, 0x19, 0x19, 0x02, 0x52, 0x86, 0xed, + 0x9a, 0xf5, 0xaf, 0x58, 0x51, 0x7c, 0x0e, 0xc9, 0x26, 0xcb, 0x66, 0x7c, 0x8a, 0x1d, 0x8d, 0x57, 0x22, 0xa9, 0x68, + 0xd9, 0xf4, 0xa7, 0x6d, 0x47, 0xf6, 0x5e, 0x82, 0x43, 0xe2, 0x00, 0xa7, 0xf4, 0xce, 0x9f, 0xcb, 0x3b, 0xab, 0x23, + 0xdf, 0x83, 0xfe, 0x95, 0x97, 0xfc, 0x95, 0xef, 0xc1, 0x9e, 0xf2, 0x92, 0xa7, 0x7c, 0x0f, 0xf8, 0x94, 0x17, 0x89, + 0xe2, 0x34, 0x7d, 0xe5, 0x70, 0x1e, 0x8c, 0x11, 0x43, 0xb9, 0x3c, 0x91, 0xad, 0xe4, 0xe0, 0x17, 0xef, 0x13, 0xee, + 0xb3, 0x81, 0x94, 0x3c, 0x66, 0xa6, 0x58, 0x89, 0x4a, 0x56, 0x96, 0x49, 0x01, 0x7c, 0xea, 0xdb, 0xc5, 0x99, 0xed, + 0x17, 0xfc, 0xe1, 0x97, 0x48, 0x1a, 0x03, 0x71, 0xa7, 0x04, 0x5d, 0xbb, 0xd3, 0xd7, 0x9e, 0xdb, 0x8a, 0x08, 0xca, + 0x72, 0xc4, 0xe8, 0x44, 0xa5, 0x1d, 0x67, 0x89, 0xde, 0xbd, 0x55, 0x18, 0x08, 0xfa, 0x76, 0xa1, 0x8f, 0xc8, 0x61, + 0xfd, 0xfd, 0x17, 0x20, 0x64, 0x5c, 0x12, 0x88, 0xc0, 0x3e, 0xf6, 0xea, 0x39, 0xd4, 0xda, 0xf3, 0xa4, 0x8a, 0x06, + 0x5c, 0x93, 0x83, 0x71, 0x8b, 0x90, 0xa4, 0xa7, 0xff, 0x88, 0x1f, 0x92, 0xb3, 0x74, 0xd1, 0x3c, 0x0b, 0xf7, 0x18, + 0x2d, 0x07, 0x34, 0x27, 0x41, 0xd5, 0xcc, 0x72, 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xe0, 0x64, 0xa9, 0xb6, 0xae, + 0xc2, 0x9d, 0xf7, 0xf8, 0x19, 0x9f, 0xd1, 0x71, 0x9a, 0x1e, 0x19, 0xb0, 0x2f, 0x72, 0x7a, 0x1f, 0x5c, 0xe1, 0x58, + 0x6b, 0x30, 0x3d, 0x91, 0x6c, 0x2d, 0xae, 0xaf, 0xc6, 0xf8, 0x82, 0xb4, 0xca, 0xfb, 0x52, 0x44, 0xc3, 0x4f, 0xc9, + 0xc4, 0x66, 0xa4, 0xa5, 0x21, 0x5f, 0x5b, 0x6a, 0xb4, 0x59, 0xb1, 0x04, 0x4b, 0x6e, 0xbf, 0x75, 0x85, 0x4d, 0xdf, + 0x64, 0x2e, 0x92, 0x6c, 0x54, 0xdd, 0x14, 0x69, 0x53, 0xe0, 0x53, 0x92, 0x15, 0xc1, 0x23, 0x50, 0x64, 0xee, 0x48, + 0x72, 0xbc, 0x74, 0xd4, 0x72, 0xaa, 0x4a, 0x88, 0xc2, 0x67, 0x15, 0x56, 0xb5, 0x14, 0x1d, 0x2f, 0x0e, 0x44, 0x08, + 0x39, 0x8c, 0x4b, 0xa7, 0xa6, 0xd1, 0x75, 0xad, 0xf6, 0x16, 0xf2, 0x1c, 0x7c, 0xf9, 0x69, 0x88, 0x25, 0x2c, 0x59, + 0x8d, 0x31, 0xe0, 0xcc, 0xb3, 0x1b, 0x7a, 0xe4, 0xb9, 0xbc, 0x1f, 0x80, 0xa3, 0x17, 0xbb, 0x16, 0x8a, 0xb9, 0xeb, + 0x33, 0x12, 0x09, 0x24, 0x32, 0x5f, 0x00, 0x70, 0x00, 0xc0, 0x55, 0x2f, 0xab, 0x3a, 0x80, 0x41, 0x2b, 0x55, 0xa0, + 0x67, 0x0a, 0x6e, 0x81, 0xcc, 0xd0, 0x72, 0x50, 0xf9, 0x23, 0x0a, 0x7c, 0xed, 0x90, 0x2c, 0x26, 0xb2, 0x34, 0x94, + 0xac, 0x63, 0x42, 0x3b, 0x1f, 0xc6, 0xd3, 0x4b, 0x14, 0xee, 0x22, 0xa5, 0xa3, 0xb6, 0xe8, 0xa7, 0x67, 0x8f, 0x7a, + 0x5a, 0x38, 0x2d, 0x22, 0x2f, 0xc7, 0xc6, 0xbf, 0xe5, 0xed, 0xba, 0x5c, 0x7f, 0x64, 0x2b, 0x9a, 0x82, 0x36, 0x04, + 0x9f, 0x3d, 0x5b, 0xf5, 0x8c, 0xbe, 0x42, 0x4e, 0x8b, 0xe5, 0xd0, 0xeb, 0xb7, 0x59, 0x6d, 0x0e, 0x1f, 0x9e, 0xd1, + 0x03, 0xd1, 0xa5, 0xbb, 0xd7, 0x48, 0xa0, 0xb9, 0x44, 0xb0, 0x18, 0x9e, 0xe3, 0xd2, 0x6e, 0x72, 0x28, 0x29, 0x0a, + 0x62, 0x15, 0xf8, 0x80, 0xde, 0xde, 0xc1, 0x90, 0xc1, 0xae, 0xdb, 0x18, 0xc0, 0xd5, 0x40, 0xf3, 0xac, 0xc5, 0x61, + 0xaf, 0x4f, 0xc0, 0xc6, 0xd2, 0xf9, 0x6a, 0xdb, 0x45, 0xb1, 0xd7, 0x5c, 0x91, 0xee, 0xda, 0x0a, 0x81, 0x3f, 0x17, + 0x9f, 0xfc, 0xed, 0x79, 0xd1, 0xfe, 0xd6, 0x7f, 0x29, 0xbd, 0x77, 0xaa, 0xf6, 0x7b, 0xa3, 0x01, 0xf5, 0xc7, 0xa9, + 0x65, 0xa9, 0x2c, 0x87, 0x59, 0xe9, 0xf9, 0x68, 0x54, 0x8b, 0xdb, 0x6b, 0x8a, 0x88, 0x8f, 0x92, 0xe0, 0x66, 0x53, + 0x2b, 0x0f, 0xee, 0x9d, 0xed, 0x85, 0xbe, 0x87, 0x81, 0xea, 0x5e, 0x0b, 0x4d, 0x77, 0x2e, 0x25, 0xa8, 0xc9, 0xc8, + 0x68, 0xa6, 0xd9, 0x98, 0xb7, 0xbe, 0xf9, 0x61, 0xaa, 0x5f, 0xd0, 0xa7, 0x52, 0x72, 0x20, 0x3b, 0xab, 0x8b, 0x52, + 0xb1, 0x2a, 0x09, 0xc1, 0xe2, 0xfa, 0xbb, 0x38, 0x24, 0x30, 0x70, 0xad, 0xba, 0x0c, 0x18, 0x89, 0x7d, 0xb1, 0xf8, + 0xa8, 0xe8, 0xf8, 0xad, 0x1d, 0x64, 0x70, 0xb3, 0xcb, 0xbc, 0x0c, 0x33, 0xfc, 0x20, 0xac, 0xd3, 0x9a, 0x82, 0x40, + 0x4d, 0x9d, 0xbc, 0x4a, 0x82, 0x62, 0xf9, 0x66, 0x4f, 0x1b, 0x7b, 0x61, 0x6c, 0x03, 0xe8, 0xd9, 0xa6, 0x91, 0x18, + 0x4c, 0xfc, 0x93, 0x63, 0xf7, 0x57, 0xa1, 0xd2, 0xaa, 0x6b, 0x51, 0x7b, 0x51, 0x1e, 0x84, 0x0e, 0xa1, 0x43, 0x51, + 0x2b, 0xb7, 0x75, 0x58, 0x9f, 0xd7, 0xb2, 0x3c, 0xe9, 0x9f, 0x78, 0xbb, 0x48, 0xd7, 0xc5, 0x1d, 0x0c, 0x35, 0x12, + 0xc8, 0x8e, 0x2a, 0x36, 0x69, 0xdc, 0x51, 0xa9, 0xb2, 0xdc, 0x7d, 0xd8, 0xa0, 0x5e, 0x5b, 0x44, 0x90, 0xa9, 0x3e, + 0xae, 0x08, 0x35, 0x86, 0x3d, 0xa1, 0x34, 0x05, 0x4c, 0x65, 0x95, 0xc5, 0x53, 0x73, 0x77, 0x7e, 0xc8, 0x99, 0xd2, + 0x70, 0xc0, 0xc7, 0xb0, 0x98, 0x0d, 0xfc, 0xfb, 0x21, 0xd2, 0xc0, 0x4d, 0xad, 0x67, 0xa1, 0x4c, 0x20, 0xad, 0x50, + 0xcc, 0x47, 0x32, 0x0a, 0x13, 0x7c, 0xcf, 0x19, 0x14, 0x39, 0x29, 0xd9, 0x68, 0xfc, 0x66, 0xdd, 0x63, 0xe8, 0x38, + 0x33, 0x3e, 0xcc, 0xd3, 0x15, 0x7b, 0xa5, 0xc0, 0xd5, 0x21, 0x14, 0x5c, 0x8e, 0xa3, 0x1a, 0xd7, 0x05, 0xd9, 0x40, + 0x49, 0x5e, 0x78, 0x8f, 0x24, 0xa4, 0x2e, 0xf4, 0x94, 0x6a, 0x47, 0x21, 0x19, 0x96, 0x60, 0x7a, 0xdc, 0x9d, 0xb1, + 0x8d, 0x2b, 0x69, 0xdb, 0xd9, 0x69, 0xa1, 0x6e, 0xcf, 0xc0, 0x83, 0x5d, 0xd5, 0x3b, 0x28, 0x47, 0x56, 0x06, 0x1a, + 0x8c, 0x80, 0xb6, 0x2c, 0x49, 0xaa, 0x89, 0xd8, 0x68, 0x14, 0x46, 0x0d, 0xa5, 0xb5, 0x92, 0x9d, 0x9c, 0xdf, 0xeb, + 0xaa, 0x98, 0x26, 0xeb, 0x50, 0x1c, 0xf4, 0xc4, 0x24, 0xa5, 0x79, 0x5d, 0xb6, 0x78, 0x7f, 0xa0, 0xf6, 0x8b, 0x54, + 0x7b, 0x62, 0x6f, 0x6e, 0x24, 0x4a, 0xb3, 0xef, 0x29, 0x94, 0x87, 0x46, 0xe7, 0xb5, 0xd1, 0x79, 0x79, 0x1d, 0xa5, + 0xff, 0x9b, 0xa8, 0x65, 0xca, 0xc6, 0x98, 0xa2, 0x0e, 0x68, 0x3e, 0x31, 0x82, 0xf6, 0xfd, 0x4b, 0xa1, 0x8e, 0x50, + 0x34, 0x4c, 0x3d, 0xce, 0xb0, 0x18, 0xe9, 0x06, 0xcf, 0x97, 0x84, 0x04, 0xf7, 0xee, 0xc0, 0xc0, 0x23, 0xc2, 0x3c, + 0x91, 0x31, 0x9d, 0x20, 0x0c, 0x51, 0x59, 0x27, 0x67, 0xde, 0xe7, 0xe6, 0xdf, 0x6e, 0x4a, 0xdb, 0x6e, 0xfa, 0x0d, + 0x26, 0xe7, 0xfd, 0x94, 0xde, 0x7b, 0x79, 0xb4, 0x69, 0x7f, 0x31, 0xb2, 0x5b, 0xf0, 0xc2, 0xe2, 0x3d, 0x16, 0xf6, + 0x2f, 0x65, 0x3e, 0x73, 0xac, 0xf4, 0x36, 0x63, 0x20, 0x83, 0x67, 0xd6, 0x58, 0xfe, 0x4a, 0xd0, 0x8e, 0x42, 0xa0, + 0x9d, 0xd8, 0x09, 0x59, 0x05, 0x09, 0x88, 0xc4, 0x58, 0xdb, 0xce, 0xc1, 0x40, 0x3b, 0xd6, 0x99, 0x5b, 0xb4, 0xf4, + 0xdd, 0x53, 0x4e, 0x4a, 0x00, 0xca, 0x4b, 0xe5, 0x9f, 0x5d, 0x9c, 0x1a, 0xfb, 0x38, 0xc1, 0xd8, 0x0a, 0xec, 0x43, + 0x02, 0xa9, 0x2a, 0x26, 0x74, 0x9a, 0x22, 0xa0, 0x8b, 0x63, 0x13, 0x7f, 0x6e, 0xdc, 0x9d, 0xc1, 0xea, 0x69, 0xbe, + 0x64, 0x9b, 0xdd, 0x4b, 0x8c, 0xa9, 0xcd, 0x3a, 0xdb, 0x16, 0xf3, 0x8c, 0xdc, 0x95, 0xc5, 0xda, 0x04, 0x52, 0xb6, + 0xe4, 0xca, 0xb5, 0x45, 0xc8, 0x84, 0x21, 0xeb, 0x1a, 0x42, 0x52, 0x20, 0xf8, 0x2d, 0x25, 0x81, 0xd5, 0xfb, 0xa5, + 0xae, 0xd4, 0xb3, 0x88, 0x76, 0x99, 0xa0, 0x1d, 0x1c, 0x39, 0xd2, 0x79, 0xe1, 0xff, 0xb7, 0x12, 0x42, 0x38, 0xd3, + 0x86, 0x6e, 0x4b, 0x68, 0x92, 0xe2, 0xe8, 0x2a, 0x5a, 0x40, 0xbe, 0xeb, 0xf5, 0x2f, 0x8d, 0xcd, 0xfb, 0x0e, 0x9e, + 0x0d, 0x22, 0x81, 0x8d, 0xa8, 0xa9, 0x51, 0x0d, 0xab, 0xad, 0x6e, 0xda, 0x6e, 0x1e, 0xdd, 0xde, 0xc8, 0xc7, 0x50, + 0xe1, 0xe8, 0xe7, 0x40, 0x89, 0xe3, 0xde, 0x34, 0xa5, 0x4d, 0x54, 0xfe, 0x17, 0xaa, 0x05, 0x4e, 0xe1, 0x93, 0x1b, + 0x9c, 0x0a, 0x4e, 0xbb, 0xa7, 0x86, 0xe2, 0x7e, 0xbf, 0x54, 0xd1, 0xf5, 0x71, 0x73, 0x95, 0x01, 0x9a, 0xf0, 0x08, + 0x72, 0x39, 0xf2, 0xfd, 0xbc, 0xae, 0xfc, 0x22, 0xbf, 0xf4, 0xed, 0x6b, 0x47, 0xd8, 0x42, 0x8d, 0xb4, 0xd0, 0xe3, + 0x24, 0xbf, 0x2c, 0x6f, 0x92, 0xee, 0x90, 0x81, 0xeb, 0x2f, 0x6b, 0xec, 0x1d, 0xaa, 0xf2, 0xd8, 0x6d, 0x8f, 0x14, + 0x08, 0xd3, 0x49, 0x97, 0xca, 0x5d, 0x29, 0x25, 0x62, 0xd4, 0x86, 0xb3, 0x4e, 0xd5, 0xa2, 0xb6, 0xb0, 0x9e, 0x2d, + 0x74, 0x93, 0x0a, 0x08, 0xd5, 0xf7, 0x94, 0x87, 0x63, 0x60, 0xd8, 0x3b, 0x5f, 0x1e, 0x27, 0x0b, 0xe7, 0x53, 0x5d, + 0x2b, 0xe7, 0xa9, 0xb6, 0xeb, 0xbe, 0xce, 0x50, 0x60, 0x6c, 0xe9, 0x1d, 0xbb, 0x0c, 0xe7, 0xb7, 0xea, 0x0a, 0x4f, + 0x96, 0x11, 0x3c, 0x4b, 0x7d, 0x42, 0xf0, 0x55, 0xf2, 0x48, 0xe1, 0xc1, 0xd1, 0xcd, 0x59, 0x40, 0x07, 0xd3, 0x49, + 0xe0, 0xc1, 0xf1, 0xb6, 0x56, 0xc9, 0xfa, 0xe0, 0xe5, 0x98, 0x10, 0x06, 0x94, 0xac, 0x0f, 0xb6, 0xdd, 0x58, 0xb9, + 0x44, 0xe3, 0xf5, 0x23, 0x0b, 0x2d, 0xba, 0x7e, 0xd0, 0xa6, 0xe7, 0x01, 0x53, 0x39, 0xaa, 0xae, 0xe7, 0x29, 0x67, + 0x87, 0x98, 0x27, 0x8c, 0x74, 0x62, 0xd0, 0xc8, 0x0e, 0x98, 0x47, 0xa9, 0xf9, 0xa9, 0x75, 0x9b, 0x6f, 0xf6, 0xe1, + 0x33, 0x61, 0xac, 0xd5, 0x46, 0x91, 0xcf, 0x53, 0x68, 0xcf, 0x8e, 0xbc, 0xdf, 0xa8, 0x21, 0x23, 0x6b, 0xd3, 0x15, + 0x90, 0x8c, 0x05, 0x7f, 0x36, 0x43, 0x58, 0xd4, 0x4a, 0xc6, 0x69, 0x62, 0x9f, 0x4d, 0x37, 0x91, 0xae, 0xf2, 0x55, + 0x04, 0x78, 0xbf, 0xe1, 0x4c, 0x9a, 0xc7, 0x96, 0x5b, 0x8c, 0x98, 0xbc, 0xd4, 0x84, 0xda, 0xa2, 0x89, 0x28, 0x01, + 0xa0, 0xd7, 0xc3, 0x3e, 0x02, 0x95, 0xbe, 0x43, 0x38, 0x37, 0x4f, 0x6c, 0x69, 0x93, 0x9a, 0x0b, 0x0a, 0xc3, 0x1d, + 0x3b, 0xd9, 0x8b, 0x4d, 0x26, 0xf6, 0x0c, 0xe6, 0xa1, 0xc5, 0x5a, 0x76, 0xf3, 0x47, 0xb1, 0xe3, 0x07, 0x34, 0x90, + 0xf9, 0x01, 0x0b, 0x92, 0x3f, 0x96, 0x0e, 0x71, 0x2e, 0x04, 0xc5, 0x43, 0x5a, 0xc9, 0x22, 0x16, 0xa4, 0xdb, 0xf1, + 0x22, 0xce, 0x65, 0x4e, 0x6e, 0x01, 0x41, 0x75, 0x20, 0x16, 0xb2, 0xdc, 0x40, 0x1a, 0x6f, 0x70, 0xe1, 0xbc, 0xc9, + 0x89, 0x24, 0xb0, 0xf5, 0x4c, 0x24, 0x93, 0x45, 0x39, 0x16, 0x81, 0xdf, 0x7c, 0xec, 0xfe, 0x66, 0x3e, 0x36, 0x1b, + 0x7b, 0xda, 0x2c, 0xdf, 0x2c, 0xc2, 0xcc, 0xda, 0xaa, 0xc2, 0x84, 0x25, 0x92, 0x71, 0xc2, 0x5b, 0x7b, 0xf8, 0xca, + 0xad, 0xe1, 0x33, 0xf8, 0xdd, 0xcc, 0x16, 0x73, 0x69, 0x3b, 0x5b, 0x24, 0xe9, 0x20, 0x4c, 0x37, 0xe1, 0x1f, 0x62, + 0x64, 0xba, 0xd8, 0xac, 0xe8, 0x47, 0x83, 0x44, 0xf1, 0x76, 0xe3, 0xe5, 0xe1, 0xb7, 0x08, 0x0e, 0x76, 0x0b, 0xb2, + 0xb9, 0xfb, 0x72, 0xa4, 0xe2, 0x21, 0x2b, 0xaa, 0x1a, 0x63, 0x84, 0x52, 0x88, 0x63, 0x88, 0xba, 0xdc, 0xbe, 0x6a, + 0xcb, 0x43, 0xba, 0xfa, 0x5a, 0x64, 0x14, 0xde, 0xca, 0x7f, 0x63, 0xbe, 0xe3, 0x9f, 0x31, 0x95, 0xd4, 0x79, 0x0e, + 0xf0, 0xb5, 0xdf, 0xc1, 0x20, 0x21, 0x2a, 0x22, 0x7f, 0x2d, 0x11, 0x20, 0x66, 0xbd, 0xc4, 0x00, 0xee, 0xbc, 0xba, + 0x95, 0x93, 0x90, 0xbe, 0x60, 0xe8, 0x6d, 0x8b, 0x85, 0x79, 0x3c, 0x92, 0x7c, 0x87, 0xb1, 0x88, 0x9d, 0xf5, 0xc1, + 0x8c, 0x9d, 0xba, 0xe6, 0xc3, 0x74, 0xf6, 0x1f, 0x23, 0x2c, 0x70, 0x04, 0x43, 0xad, 0x85, 0x9f, 0xae, 0x02, 0xb8, + 0xd3, 0x7f, 0x08, 0x52, 0xe0, 0x36, 0x7a, 0xe2, 0x67, 0xba, 0x17, 0xd8, 0x04, 0xa7, 0x62, 0xaf, 0x88, 0xed, 0x39, + 0xd0, 0xab, 0x55, 0x0d, 0xa5, 0xbb, 0x73, 0x3a, 0x08, 0x53, 0x2c, 0x0a, 0x63, 0xbd, 0x8e, 0x12, 0x9b, 0x55, 0xcb, + 0x69, 0xc2, 0x90, 0xed, 0x2a, 0xd4, 0x9e, 0xe4, 0xc2, 0xa2, 0x84, 0x23, 0x37, 0x89, 0x37, 0xd5, 0x3a, 0xa0, 0x7e, + 0xeb, 0xd7, 0x26, 0xb8, 0xf5, 0x82, 0xa5, 0x63, 0x41, 0xa1, 0xa5, 0x88, 0xc1, 0x23, 0x44, 0x06, 0xaf, 0xcb, 0x15, + 0xe2, 0xf4, 0x22, 0xfd, 0xbe, 0x75, 0x57, 0x4a, 0x4b, 0x77, 0xb3, 0x88, 0xd9, 0xcf, 0xe9, 0xaf, 0x86, 0x97, 0xd7, + 0x9c, 0x91, 0x71, 0xd1, 0xb4, 0xe8, 0xa9, 0xd7, 0xb8, 0xdc, 0x80, 0xd9, 0x43, 0xab, 0x63, 0x86, 0xfd, 0x33, 0x2d, + 0x2d, 0xc6, 0xf8, 0x9d, 0x28, 0xa6, 0xdd, 0xef, 0x3e, 0x75, 0xe2, 0x9e, 0x5e, 0xe8, 0xa0, 0xf7, 0x96, 0x78, 0xdb, + 0xe9, 0x9d, 0xae, 0x3e, 0x9b, 0x8e, 0x41, 0xf4, 0x8d, 0x32, 0x7d, 0x37, 0x0b, 0x5d, 0x2e, 0x63, 0xd6, 0x68, 0x93, + 0xf6, 0xe5, 0x72, 0xfa, 0xa5, 0x97, 0xb9, 0xf1, 0x6f, 0xe1, 0x7a, 0x32, 0x24, 0x92, 0x96, 0x2a, 0x95, 0x2a, 0x9c, + 0x74, 0x81, 0xc4, 0x9a, 0x89, 0x5a, 0xae, 0x51, 0x67, 0x1c, 0x0f, 0x97, 0x0e, 0xcb, 0xef, 0x9b, 0x0f, 0x2a, 0xbd, + 0x7c, 0x1f, 0x88, 0x7d, 0x76, 0x25, 0x19, 0x50, 0x4e, 0xe1, 0x8c, 0xec, 0xfe, 0x73, 0x58, 0xed, 0x0a, 0xa0, 0x66, + 0x18, 0xbd, 0x5c, 0x1a, 0x76, 0x50, 0x94, 0x7e, 0x3a, 0xe9, 0xa6, 0x20, 0xac, 0xaf, 0xce, 0xc2, 0xeb, 0x5a, 0x92, + 0xe8, 0x12, 0x7f, 0x25, 0xdd, 0x4f, 0x38, 0xc9, 0xbe, 0x43, 0x7d, 0x55, 0x97, 0x00, 0xd0, 0x21, 0x5e, 0xa9, 0x40, + 0x9a, 0x79, 0x4b, 0xba, 0x4a, 0x64, 0x5d, 0x7c, 0x48, 0x01, 0x5c, 0x59, 0x6f, 0x9f, 0x66, 0x21, 0x5d, 0x6b, 0x89, + 0x9d, 0x84, 0x6e, 0xb8, 0x9f, 0x30, 0x02, 0x24, 0xd8, 0xf1, 0x00, 0x9a, 0xbc, 0x13, 0x9e, 0x63, 0xbd, 0x9a, 0x58, + 0x83, 0x20, 0xa2, 0x7b, 0x2f, 0xc1, 0x6e, 0x4e, 0xf3, 0xac, 0xb0, 0x09, 0xd1, 0xec, 0xc8, 0x7d, 0x3f, 0x39, 0xf0, + 0x7a, 0x61, 0x53, 0xb1, 0x51, 0x99, 0x3a, 0xb9, 0xc5, 0x38, 0xc0, 0x3e, 0x2d, 0x05, 0xd4, 0x70, 0x15, 0xa5, 0x2c, + 0xa7, 0x29, 0xa1, 0xc5, 0x38, 0xe0, 0xf4, 0x25, 0x07, 0xff, 0x27, 0x82, 0x26, 0x64, 0x1d, 0x7e, 0xfc, 0xb1, 0x05, + 0x7f, 0x24, 0xad, 0x69, 0x56, 0x44, 0xab, 0x3d, 0xc5, 0x1a, 0x34, 0x2f, 0x93, 0x8f, 0x0d, 0x03, 0xd8, 0xbc, 0x16, + 0xb2, 0xfa, 0x89, 0x9b, 0x56, 0x3c, 0x50, 0x7e, 0xca, 0x41, 0xed, 0xa9, 0x35, 0xf6, 0x42, 0xb2, 0xd3, 0xac, 0xa8, + 0x88, 0xe2, 0x7a, 0xb2, 0x5d, 0x17, 0xef, 0xbe, 0x48, 0x54, 0xfc, 0xe9, 0x06, 0x62, 0x48, 0x40, 0x02, 0x83, 0x15, + 0xd4, 0x90, 0xd0, 0x51, 0x5f, 0x6f, 0xbe, 0xbc, 0xd5, 0x20, 0xd0, 0x7c, 0xe9, 0x14, 0x10, 0x33, 0x15, 0xb3, 0xf3, + 0x21, 0xa0, 0x8a, 0xf7, 0x6f, 0x30, 0x69, 0x36, 0x7e, 0xb7, 0x8e, 0x6b, 0x5d, 0x38, 0xff, 0x51, 0xab, 0x66, 0xc0, + 0x86, 0xb8, 0xa0, 0x4a, 0xd1, 0xb0, 0xca, 0x58, 0x20, 0x1a, 0x3d, 0x7d, 0x1c, 0x59, 0x0a, 0xfb, 0xe7, 0xe6, 0xcb, + 0x67, 0xad, 0x4e, 0x6d, 0x5e, 0xcd, 0x5c, 0x4a, 0xa2, 0xe0, 0x32, 0x7d, 0xc3, 0x57, 0x00, 0x20, 0x33, 0x6b, 0x10, + 0x14, 0x34, 0xf8, 0x1a, 0x7c, 0x6e, 0x45, 0xc8, 0x38, 0xd0, 0xfd, 0x90, 0xf1, 0x87, 0x9b, 0xf6, 0x8a, 0xde, 0xd2, + 0xca, 0x7c, 0x4b, 0xaf, 0xf7, 0xb4, 0xd5, 0xf5, 0x4b, 0x8b, 0x19, 0x75, 0xa9, 0x5a, 0x9e, 0x7e, 0xde, 0xee, 0x7b, + 0xe2, 0xd6, 0xda, 0x9f, 0x8a, 0x32, 0xb6, 0x27, 0xe5, 0xa0, 0x31, 0x37, 0xfe, 0x05, 0xea, 0x35, 0x0d, 0x8d, 0x8a, + 0x42, 0x79, 0x5b, 0xf7, 0xad, 0x50, 0xe6, 0xed, 0x89, 0x8c, 0x23, 0xa9, 0x3b, 0x86, 0xbc, 0x2f, 0x6d, 0xe3, 0xf3, + 0x9a, 0x22, 0x50, 0xf8, 0x95, 0xe9, 0x94, 0x02, 0x5d, 0x13, 0x2e, 0x11, 0x3c, 0xb4, 0xbc, 0x2e, 0xdd, 0x98, 0x41, + 0xe5, 0xe8, 0x03, 0xbd, 0xa5, 0x0d, 0xc1, 0x8f, 0x8b, 0xf0, 0x8b, 0x9d, 0xd0, 0x4c, 0xae, 0x02, 0x35, 0x13, 0x55, + 0xf6, 0x90, 0xac, 0x0c, 0x96, 0x13, 0xa9, 0x49, 0xdf, 0xd4, 0x99, 0x40, 0x83, 0xa9, 0x57, 0x3e, 0xeb, 0x82, 0xa1, + 0x8b, 0x5d, 0x69, 0x61, 0x60, 0x11, 0x26, 0x5f, 0x84, 0x5f, 0x1f, 0x7d, 0x2d, 0x8d, 0x16, 0x18, 0x02, 0x84, 0xe6, + 0x5e, 0x5e, 0x34, 0x0a, 0xb6, 0xbf, 0xbb, 0x69, 0xaf, 0x57, 0x78, 0xf0, 0xed, 0x83, 0x79, 0x89, 0xc5, 0x81, 0x9e, + 0x9b, 0xfc, 0x71, 0x27, 0xed, 0x44, 0x41, 0x48, 0x6d, 0x2e, 0x70, 0x08, 0x50, 0xd5, 0xec, 0x21, 0xce, 0x56, 0x29, + 0x3b, 0x71, 0x04, 0x64, 0xf9, 0x6d, 0x04, 0xbe, 0x7c, 0xb7, 0xc6, 0xde, 0x63, 0x91, 0xb9, 0x28, 0xed, 0xf1, 0xb7, + 0xbb, 0x0b, 0xab, 0xbb, 0x79, 0x78, 0x2c, 0x28, 0xec, 0xfc, 0xe1, 0x3c, 0xee, 0xeb, 0xba, 0x7b, 0x00, 0x98, 0x81, + 0xf0, 0x71, 0x21, 0x1c, 0x02, 0xd1, 0x4c, 0x37, 0xeb, 0xf6, 0xa3, 0x4a, 0xaa, 0x8a, 0xa7, 0x00, 0x27, 0x1c, 0x02, + 0xef, 0x4c, 0x3d, 0x36, 0x4b, 0xb0, 0xd9, 0x0e, 0xc0, 0x10, 0x4a, 0xd3, 0x1c, 0x37, 0xe5, 0x06, 0xc8, 0x77, 0x11, + 0xc3, 0x14, 0xf7, 0x62, 0x8f, 0x86, 0x0f, 0x28, 0x8a, 0x68, 0xe9, 0xbc, 0x20, 0xdf, 0x76, 0x11, 0xcb, 0x9d, 0x27, + 0xa3, 0x0c, 0x3e, 0x11, 0xf9, 0x16, 0x29, 0x64, 0xee, 0x47, 0x9a, 0xc2, 0x6a, 0x9b, 0xd6, 0x8f, 0x01, 0x91, 0x5b, + 0x5a, 0x37, 0x26, 0x5a, 0x03, 0x17, 0x7a, 0x13, 0xf9, 0x02, 0x5a, 0xdb, 0x2a, 0x76, 0x9f, 0x5f, 0x89, 0x64, 0xf0, + 0x40, 0x98, 0x7f, 0xe3, 0xe1, 0xad, 0xd1, 0x31, 0xa5, 0x66, 0x76, 0x49, 0xfb, 0xe3, 0xbd, 0xb5, 0x97, 0xad, 0xfb, + 0xd6, 0xbb, 0x6a, 0x4d, 0x9e, 0xd3, 0x21, 0x95, 0xd8, 0x49, 0x05, 0x50, 0x04, 0x1f, 0x5b, 0x3e, 0x3f, 0x07, 0xa8, + 0x13, 0x05, 0x5c, 0xa8, 0x72, 0xe2, 0xcc, 0x38, 0xcc, 0xf2, 0x2b, 0x69, 0x73, 0x70, 0xfb, 0x79, 0x93, 0x62, 0x20, + 0x84, 0x42, 0x07, 0x64, 0xea, 0x0d, 0x4e, 0x6a, 0x6b, 0xda, 0x02, 0x8b, 0x39, 0x2c, 0x10, 0x39, 0x82, 0x00, 0xe4, + 0x10, 0xe9, 0x5a, 0xa5, 0xfb, 0x78, 0xd0, 0x0d, 0x28, 0x6f, 0x04, 0x66, 0xa4, 0x3f, 0x80, 0xd8, 0xb1, 0xb6, 0x73, + 0x95, 0x88, 0x30, 0x89, 0x34, 0x16, 0x1e, 0xfe, 0x25, 0x53, 0x52, 0x3e, 0x62, 0xb1, 0x1b, 0x82, 0x69, 0x31, 0xaf, + 0x48, 0x0e, 0x29, 0x48, 0x17, 0xea, 0xea, 0x5b, 0x8e, 0xc9, 0x39, 0xcd, 0x32, 0x14, 0xa6, 0x48, 0x18, 0x39, 0x9b, + 0x36, 0x13, 0x59, 0x40, 0x33, 0x56, 0x45, 0xa0, 0x5c, 0x91, 0xf5, 0xa8, 0x92, 0x3f, 0x72, 0xfe, 0x4d, 0x58, 0x05, + 0x97, 0x63, 0xc7, 0xba, 0x61, 0x9d, 0x9d, 0x17, 0x95, 0x69, 0x99, 0x7c, 0x5b, 0x96, 0x24, 0x5e, 0xc2, 0x63, 0x21, + 0xde, 0x2f, 0xfa, 0x6d, 0xf5, 0x14, 0xfa, 0xe5, 0xae, 0x1d, 0x42, 0x85, 0x54, 0x0c, 0x6a, 0x09, 0x13, 0x45, 0x8b, + 0xd2, 0xf8, 0xbd, 0x00, 0x5b, 0x1e, 0x03, 0xda, 0x58, 0xfa, 0xc1, 0x4a, 0x5c, 0x95, 0x23, 0x6a, 0x59, 0xbd, 0x95, + 0xa2, 0x93, 0xcb, 0xca, 0x32, 0xda, 0x22, 0x92, 0x80, 0x00, 0xe7, 0x2b, 0x65, 0x35, 0xbf, 0xe4, 0x3a, 0xac, 0x5b, + 0xbf, 0xb2, 0x54, 0x2a, 0x4c, 0xd1, 0x62, 0xb0, 0x8c, 0x08, 0xe3, 0x36, 0xd7, 0xba, 0x38, 0x7e, 0xd7, 0xfc, 0x0d, + 0xe8, 0xb7, 0x70, 0x97, 0xbb, 0x6a, 0x05, 0x6e, 0x5e, 0x44, 0x74, 0x41, 0x2e, 0x03, 0xb9, 0x0b, 0xaa, 0x37, 0x68, + 0xc1, 0x96, 0xac, 0xb7, 0xe6, 0x32, 0x2f, 0x0f, 0x7d, 0x15, 0x83, 0x3c, 0x7d, 0xa8, 0x68, 0x75, 0xa8, 0xf5, 0x71, + 0x6f, 0xff, 0x69, 0xaf, 0xda, 0x69, 0x40, 0x07, 0xe4, 0xbe, 0xd6, 0xf1, 0x75, 0x97, 0xff, 0xf9, 0x87, 0xdb, 0x22, + 0x91, 0xfb, 0x25, 0x75, 0x03, 0x1d, 0x82, 0xd2, 0x81, 0x60, 0x3b, 0x5e, 0x5a, 0x7e, 0x72, 0xd0, 0x0b, 0x6b, 0x42, + 0x2d, 0xbc, 0x29, 0x4f, 0x83, 0x11, 0x21, 0x94, 0x92, 0x58, 0xe7, 0xb4, 0xd9, 0xc3, 0x82, 0x3e, 0xdc, 0xe1, 0xac, + 0x36, 0xa6, 0x3f, 0x21, 0xaa, 0x4c, 0xb4, 0x07, 0x76, 0x17, 0x4d, 0x6c, 0x78, 0xd8, 0x0f, 0x4a, 0x52, 0x42, 0xb5, + 0xaf, 0xe8, 0x03, 0x65, 0x62, 0x8e, 0x2f, 0x3b, 0x14, 0xfc, 0x55, 0x6a, 0x89, 0x4d, 0x0c, 0xf6, 0x1d, 0x87, 0x25, + 0x51, 0x31, 0x80, 0xcd, 0x65, 0x8c, 0x59, 0x5f, 0x60, 0x8b, 0xd8, 0x9f, 0x56, 0x03, 0x65, 0xbf, 0x5b, 0xf7, 0x7d, + 0x67, 0x05, 0x50, 0xe6, 0x9a, 0x9f, 0xf4, 0x7b, 0xe4, 0x7b, 0xb0, 0xa8, 0x5f, 0x87, 0xa0, 0x45, 0xd7, 0xb5, 0x35, + 0x71, 0xe6, 0xb3, 0x74, 0xcf, 0x0d, 0x17, 0xfe, 0xbe, 0x2a, 0x90, 0x09, 0xd2, 0x74, 0xa8, 0x62, 0x33, 0x2e, 0xca, + 0x28, 0xb6, 0x0c, 0xf7, 0xc2, 0xef, 0xa4, 0x20, 0x42, 0x84, 0x8c, 0x61, 0x5a, 0x22, 0xe8, 0xd4, 0x7c, 0x9e, 0x36, + 0x02, 0xd5, 0x35, 0x29, 0x73, 0x4f, 0x97, 0x3b, 0xe2, 0x41, 0x89, 0x1e, 0x59, 0x02, 0xf4, 0x7f, 0xab, 0xe7, 0x1a, + 0xb7, 0x9c, 0x11, 0xa4, 0x59, 0x10, 0x19, 0x9c, 0xc1, 0x71, 0x8e, 0x1b, 0x2d, 0x24, 0x48, 0x14, 0x77, 0x27, 0xa1, + 0x4f, 0xda, 0x38, 0x35, 0xf8, 0x05, 0xb9, 0x28, 0x37, 0x2a, 0x00, 0xb5, 0x7b, 0x88, 0x16, 0x05, 0x73, 0x66, 0xc8, + 0x8e, 0xbc, 0x87, 0x18, 0x1e, 0xda, 0x52, 0x69, 0x1e, 0x73, 0x72, 0x02, 0x51, 0x73, 0x99, 0x27, 0x35, 0xf6, 0x0a, + 0xfa, 0x06, 0x14, 0xa7, 0xd0, 0xc6, 0x98, 0x38, 0x5d, 0x9e, 0xfa, 0x54, 0x0d, 0x44, 0xe9, 0xd9, 0x7c, 0x5d, 0xac, + 0x23, 0x76, 0xc0, 0x2e, 0x34, 0x63, 0x0c, 0x7e, 0x23, 0x94, 0x02, 0x0e, 0x32, 0x9f, 0x08, 0x3a, 0xf2, 0x83, 0x81, + 0x93, 0x19, 0xe3, 0x5d, 0xd6, 0x84, 0x03, 0x3d, 0x94, 0x52, 0x7d, 0x01, 0x9b, 0x21, 0x04, 0xe8, 0xaf, 0xc4, 0x7b, + 0x67, 0xad, 0x9e, 0x51, 0x89, 0x17, 0x13, 0x39, 0x28, 0xc2, 0x84, 0x87, 0x48, 0x8d, 0x28, 0x74, 0x24, 0xda, 0x43, + 0x05, 0xb3, 0xec, 0x6c, 0x5b, 0x53, 0xde, 0x17, 0x75, 0xea, 0x34, 0x07, 0xbf, 0xbe, 0x17, 0x6f, 0xe4, 0xea, 0x31, + 0xa0, 0xc7, 0xbe, 0x6e, 0x09, 0xd9, 0xbd, 0x53, 0x40, 0x80, 0x7c, 0xb1, 0x43, 0xc6, 0x84, 0xe8, 0x58, 0xd3, 0x92, + 0xaa, 0xd9, 0x47, 0x8b, 0xd0, 0x5f, 0xae, 0x8f, 0x33, 0x2c, 0x13, 0x42, 0x6d, 0x61, 0x02, 0x88, 0xd0, 0x93, 0x4e, + 0x09, 0x96, 0xe4, 0x3e, 0x78, 0xd9, 0xb0, 0xc3, 0xc1, 0x76, 0x55, 0x0c, 0x4f, 0x0e, 0x3f, 0x0f, 0x81, 0xed, 0x98, + 0x80, 0x4e, 0xb3, 0x14, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x33, 0x49, 0x05, 0x31, 0x4d, 0x54, 0x3e, 0xe0, 0x0f, 0x6a, + 0x23, 0x6e, 0xd2, 0x8e, 0xe2, 0xdd, 0x08, 0x7b, 0x89, 0x43, 0x37, 0x84, 0xeb, 0x80, 0xa8, 0xd1, 0x3e, 0x97, 0x35, + 0x37, 0xa2, 0xcd, 0x33, 0x32, 0x70, 0x89, 0xd4, 0x5f, 0xa1, 0x75, 0x50, 0x69, 0x41, 0x3d, 0x8b, 0xdf, 0x02, 0x3c, + 0xb7, 0x86, 0x96, 0xfb, 0x15, 0x92, 0xb8, 0x53, 0x8c, 0x66, 0xb4, 0x47, 0x78, 0x99, 0xee, 0x10, 0xe0, 0xde, 0x6a, + 0xdd, 0x69, 0xba, 0x1e, 0xa0, 0x8c, 0x9d, 0xb8, 0xe9, 0xb6, 0xca, 0x49, 0x1a, 0x03, 0x6a, 0xcc, 0xbf, 0x47, 0xef, + 0x07, 0xdf, 0x73, 0xa4, 0xe3, 0x76, 0x59, 0xe8, 0x5a, 0xa1, 0xf9, 0xf4, 0x39, 0xd9, 0x69, 0xe9, 0x16, 0xf7, 0x26, + 0x11, 0xea, 0xf0, 0x11, 0x5e, 0x30, 0x17, 0x4a, 0x77, 0x5c, 0xd4, 0xbd, 0xf9, 0xc9, 0xc2, 0x4d, 0x51, 0x53, 0x98, + 0x42, 0xc9, 0x66, 0xc3, 0x2b, 0x89, 0x59, 0xa0, 0xb9, 0x5c, 0x29, 0x84, 0x96, 0xf7, 0x40, 0xed, 0x35, 0x24, 0x6e, + 0xad, 0xd7, 0x16, 0x6e, 0xd3, 0x45, 0x6b, 0x35, 0x59, 0xd0, 0xc6, 0x48, 0xca, 0x98, 0x39, 0x74, 0x56, 0x64, 0xba, + 0x2a, 0x0a, 0x86, 0x35, 0xb5, 0x5e, 0x5d, 0x3b, 0x7e, 0x7e, 0x69, 0x7a, 0x08, 0x13, 0x0e, 0xac, 0x56, 0xd0, 0x3b, + 0xec, 0x34, 0x7f, 0x7a, 0xe1, 0x6a, 0x0b, 0x83, 0x44, 0x01, 0x01, 0x5d, 0x72, 0xf4, 0x3e, 0x96, 0x9e, 0xa2, 0x20, + 0x52, 0xa7, 0xab, 0xae, 0x32, 0x12, 0x82, 0x95, 0x8a, 0xff, 0x76, 0x60, 0x42, 0x8e, 0x70, 0x8e, 0xc8, 0xed, 0x75, + 0x25, 0xe7, 0xc7, 0x03, 0xd2, 0xd3, 0x11, 0x91, 0xd0, 0xd3, 0x1b, 0x43, 0x70, 0x39, 0x68, 0xec, 0xef, 0x02, 0xae, + 0xf0, 0x01, 0x86, 0xaf, 0x87, 0xae, 0x94, 0x1b, 0x2c, 0xec, 0xfb, 0x02, 0x69, 0xca, 0x45, 0x04, 0x07, 0xaa, 0x1d, + 0xf9, 0x9c, 0x1d, 0xf9, 0xad, 0x79, 0x15, 0x38, 0x37, 0x27, 0xbb, 0x46, 0x11, 0xca, 0x14, 0xbb, 0xb7, 0x03, 0x23, + 0x51, 0x92, 0xf0, 0xbb, 0x43, 0x42, 0x6b, 0xad, 0xf3, 0x3b, 0xee, 0x07, 0xbc, 0x28, 0x22, 0xf9, 0x07, 0xb1, 0x79, + 0x4f, 0x93, 0xf3, 0xf2, 0x1a, 0x5b, 0xb7, 0x15, 0x23, 0x00, 0xcd, 0x4d, 0xe6, 0x6d, 0x95, 0xc1, 0x0d, 0x56, 0x06, + 0x79, 0xb2, 0x24, 0x18, 0xcf, 0x52, 0x0d, 0xe6, 0xd9, 0xb1, 0x93, 0x96, 0x05, 0x0b, 0x81, 0x22, 0xd7, 0xd4, 0x66, + 0x75, 0x12, 0x57, 0xb4, 0x63, 0xf7, 0x5b, 0xb6, 0xc0, 0x09, 0x48, 0x3d, 0x71, 0xb2, 0xb4, 0x0d, 0x3e, 0x50, 0x48, + 0x76, 0x67, 0x19, 0x06, 0xd9, 0x85, 0xff, 0x2a, 0xe8, 0x07, 0x54, 0x57, 0x21, 0x54, 0xa4, 0x4d, 0x6c, 0x95, 0x94, + 0x22, 0x6b, 0x84, 0xd6, 0xd9, 0x16, 0x64, 0xc5, 0xd9, 0x1e, 0xf1, 0xa8, 0x99, 0xc0, 0x83, 0xc9, 0x6d, 0x91, 0xcd, + 0x19, 0xee, 0x89, 0x40, 0xc7, 0xa6, 0x50, 0x66, 0xda, 0x84, 0x6d, 0xdc, 0x93, 0xcd, 0xda, 0xbb, 0xad, 0xa8, 0x19, + 0x34, 0xa2, 0x6f, 0x69, 0x9a, 0xfd, 0x7b, 0x7d, 0xf0, 0x59, 0x89, 0xbe, 0x91, 0x43, 0x4c, 0xd7, 0x6d, 0xa4, 0x49, + 0x95, 0x5a, 0xe2, 0xd7, 0x6d, 0x3e, 0xbd, 0xa7, 0xa1, 0x1c, 0x52, 0x00, 0x27, 0x94, 0x02, 0x33, 0xe4, 0x73, 0x0c, + 0xc1, 0x9d, 0x82, 0x6d, 0x24, 0xcb, 0xad, 0xc8, 0x65, 0xd6, 0x58, 0xdd, 0xf1, 0x0f, 0x16, 0x80, 0x42, 0x5f, 0xde, + 0xa1, 0xa0, 0x1f, 0x6b, 0xbd, 0x4f, 0xd4, 0x91, 0x12, 0x93, 0xe2, 0xd3, 0xa5, 0x9b, 0xac, 0x02, 0x6a, 0xae, 0x5e, + 0x17, 0x0d, 0xe8, 0x35, 0x61, 0x00, 0xa1, 0x47, 0x74, 0xd8, 0x42, 0x18, 0xfd, 0xd1, 0x14, 0xc2, 0x7a, 0x5f, 0xc5, + 0x6d, 0xb7, 0x29, 0xba, 0xa7, 0xb3, 0x3b, 0x46, 0x6a, 0x90, 0x99, 0x56, 0x34, 0xc7, 0x70, 0x7a, 0xc0, 0x9d, 0xe2, + 0xb1, 0x63, 0x81, 0xcd, 0x26, 0xd5, 0x63, 0x8c, 0x01, 0x8e, 0xcc, 0x58, 0x6c, 0x53, 0x69, 0xad, 0x8c, 0x91, 0xda, + 0x16, 0xfd, 0xb2, 0xe6, 0x4e, 0x51, 0xdc, 0xfe, 0x08, 0x80, 0x79, 0x6e, 0x32, 0xad, 0xa3, 0x98, 0xa2, 0x46, 0x49, + 0xdb, 0xc5, 0xf1, 0x52, 0x54, 0x5e, 0x7c, 0x22, 0x70, 0x6f, 0x84, 0xca, 0x95, 0xa3, 0x03, 0xab, 0x33, 0xa5, 0x1f, + 0x6e, 0xf1, 0x98, 0x39, 0x89, 0x78, 0x01, 0xa3, 0xcf, 0x98, 0x0d, 0xe7, 0x0b, 0xef, 0x88, 0xb9, 0x45, 0x4e, 0xe1, + 0x5d, 0xf1, 0x56, 0xf8, 0xa5, 0x0b, 0xa8, 0xee, 0x41, 0x9c, 0xee, 0x54, 0xd6, 0x7a, 0x9d, 0x11, 0x21, 0xe1, 0x3b, + 0x92, 0xec, 0x95, 0x8c, 0x9d, 0xf8, 0x2c, 0x32, 0x3d, 0x38, 0x86, 0x85, 0x67, 0x8c, 0xe4, 0xf6, 0x99, 0x3a, 0x9a, + 0xb3, 0xc7, 0x3a, 0xd7, 0x45, 0x77, 0x5e, 0x7b, 0x6f, 0x2b, 0xd2, 0x53, 0x33, 0x9b, 0x4e, 0xbc, 0x69, 0x80, 0x3a, + 0x1f, 0xbc, 0xf6, 0x48, 0xe7, 0x7c, 0x07, 0x47, 0x71, 0x28, 0x5c, 0xb7, 0x6a, 0xf4, 0xd9, 0xf5, 0x1e, 0x72, 0x35, + 0x6c, 0xba, 0x8b, 0xc7, 0x65, 0x8f, 0x26, 0x7f, 0xb1, 0x22, 0x10, 0xfb, 0x18, 0x1e, 0x9f, 0xd3, 0xe0, 0xd6, 0xda, + 0xce, 0xb4, 0xd5, 0x36, 0x02, 0xd5, 0xa6, 0xa9, 0x05, 0x7e, 0xd2, 0xd5, 0x71, 0x3e, 0x71, 0xbc, 0xbc, 0x6b, 0xe0, + 0x4b, 0xfc, 0x02, 0x84, 0x55, 0xe9, 0xf5, 0xee, 0xf1, 0x1d, 0x67, 0x99, 0x2d, 0x73, 0xaf, 0x01, 0x59, 0x0e, 0x73, + 0x9d, 0xc5, 0xf1, 0xae, 0x3a, 0x22, 0x95, 0xda, 0xbe, 0xf2, 0xbf, 0x33, 0xe3, 0x42, 0x97, 0x1d, 0x41, 0x1c, 0xc8, + 0x15, 0x39, 0x53, 0x2a, 0xac, 0xc2, 0x69, 0x69, 0x4d, 0x43, 0xe3, 0x3a, 0x14, 0x04, 0x64, 0xf8, 0x7f, 0x20, 0x1c, + 0x44, 0xe6, 0xad, 0x13, 0x92, 0xaa, 0x6a, 0x03, 0x6b, 0xb4, 0x17, 0x7b, 0x01, 0x52, 0x78, 0x28, 0x92, 0xad, 0x2f, + 0xda, 0xaf, 0x4b, 0x64, 0x21, 0x03, 0xc1, 0x28, 0x93, 0x24, 0xc0, 0xd6, 0xd1, 0xad, 0x9e, 0xee, 0x92, 0x5e, 0x26, + 0xa0, 0xef, 0xf4, 0x3c, 0xfe, 0x10, 0x87, 0xa2, 0xac, 0x39, 0x7f, 0x6e, 0x49, 0xb6, 0xf3, 0xe8, 0xae, 0x6a, 0xac, + 0x43, 0x2c, 0x36, 0x97, 0x1c, 0x1d, 0xe7, 0x45, 0x81, 0xb3, 0x0c, 0x7d, 0x07, 0x8c, 0x85, 0x77, 0x36, 0x0c, 0xd5, + 0x5c, 0x48, 0x35, 0x7d, 0xc5, 0xa7, 0x70, 0x1d, 0x1e, 0x52, 0x4a, 0xdb, 0x16, 0xeb, 0xc1, 0x72, 0x88, 0x97, 0xdc, + 0x50, 0xa1, 0x71, 0xb5, 0x34, 0x9b, 0xd4, 0x73, 0x98, 0xc6, 0x8a, 0x2f, 0xd0, 0xa4, 0xdc, 0x45, 0xc5, 0x53, 0x07, + 0x53, 0x87, 0x6e, 0x52, 0x88, 0x7e, 0x3a, 0x32, 0x27, 0x92, 0x34, 0xe9, 0xc7, 0xb6, 0x51, 0x05, 0x01, 0xd0, 0xd1, + 0x5a, 0x16, 0xb4, 0xfb, 0xde, 0xaf, 0x7e, 0x65, 0xa3, 0x4d, 0x8f, 0x1a, 0x92, 0xb9, 0xd6, 0xe1, 0xd6, 0xd7, 0x72, + 0x7c, 0x77, 0x45, 0x18, 0xcd, 0xdb, 0x03, 0xab, 0xc2, 0xb9, 0x88, 0x14, 0xe3, 0x16, 0xad, 0x20, 0x61, 0x1e, 0x20, + 0xc7, 0xbb, 0x61, 0xda, 0x9f, 0x2b, 0x93, 0xa3, 0xf3, 0x3c, 0x3c, 0x6f, 0xae, 0x58, 0x68, 0x45, 0x2f, 0xce, 0xb1, + 0xdf, 0xb8, 0xf7, 0xbd, 0x8c, 0xa9, 0xe7, 0x61, 0xe3, 0xdd, 0x28, 0x4f, 0x4f, 0x30, 0x3a, 0x3f, 0x44, 0x37, 0x77, + 0xa4, 0xaf, 0xec, 0x02, 0xf4, 0x7a, 0x4f, 0x8e, 0xef, 0x67, 0xdf, 0x8b, 0x8e, 0x33, 0xb8, 0x30, 0xd2, 0x28, 0xce, + 0x17, 0x84, 0x96, 0x98, 0xa3, 0x34, 0xe3, 0x45, 0x3d, 0x11, 0x8e, 0x78, 0x79, 0x0a, 0x76, 0x2c, 0xec, 0xa6, 0x3f, + 0x17, 0xbe, 0xb0, 0xf0, 0xd7, 0xe9, 0x4c, 0xe0, 0x71, 0xff, 0x6f, 0x93, 0xfd, 0x82, 0x44, 0x22, 0x7a, 0x18, 0x47, + 0x7a, 0x6c, 0xcb, 0x42, 0xef, 0x99, 0xd8, 0x22, 0xf5, 0xfa, 0xfd, 0x84, 0x50, 0xea, 0x86, 0x52, 0xea, 0x0e, 0xca, + 0x64, 0x59, 0x02, 0x1b, 0x37, 0x85, 0x10, 0x72, 0xfc, 0x33, 0x6e, 0x9e, 0x22, 0x7c, 0xd6, 0x88, 0xd2, 0xac, 0xa6, + 0xa6, 0xe0, 0xce, 0x60, 0x00, 0x56, 0xe2, 0x04, 0x07, 0x88, 0xf2, 0xa1, 0x2e, 0xbc, 0xc2, 0xc4, 0x6a, 0x55, 0x56, + 0x02, 0xb5, 0xc2, 0x50, 0x82, 0x08, 0x4e, 0x68, 0x2f, 0x22, 0xac, 0xeb, 0x98, 0x94, 0x7b, 0xb0, 0x45, 0x3b, 0xb7, + 0xf0, 0xba, 0xdb, 0xc2, 0xca, 0xc3, 0x7b, 0x35, 0xeb, 0xb1, 0x2b, 0xbb, 0xe3, 0x01, 0x72, 0x94, 0x9c, 0xfd, 0x04, + 0x88, 0xe0, 0x41, 0x12, 0xd8, 0xea, 0xad, 0x3d, 0x6c, 0xed, 0x0e, 0xa1, 0xdf, 0x16, 0xf8, 0x74, 0x07, 0xcc, 0x46, + 0x69, 0x37, 0xfb, 0xfc, 0xa7, 0x0e, 0x0e, 0x4b, 0x6f, 0x02, 0x7c, 0x9d, 0xea, 0x4e, 0xd6, 0x74, 0x1b, 0xb8, 0xc7, + 0x3f, 0x7b, 0xe8, 0x8a, 0x44, 0x3a, 0x62, 0x16, 0xb7, 0x38, 0xaa, 0xcb, 0xce, 0xea, 0xae, 0x91, 0x73, 0x5b, 0x12, + 0x57, 0xa5, 0x84, 0xec, 0x72, 0x44, 0xa5, 0x24, 0x7b, 0x44, 0x19, 0x9c, 0xf6, 0xf6, 0xf2, 0xdc, 0x98, 0x7b, 0x18, + 0x67, 0x01, 0xa8, 0x09, 0x58, 0x2e, 0xc8, 0xc6, 0x3b, 0x01, 0x80, 0x51, 0x5a, 0x35, 0x75, 0x46, 0xef, 0xe2, 0x56, + 0x5d, 0x6f, 0x1e, 0x64, 0x46, 0x33, 0x51, 0x33, 0xb9, 0x3b, 0xa0, 0x8a, 0xd1, 0xc2, 0x20, 0xfb, 0xa5, 0x54, 0x7c, + 0x5a, 0x95, 0x68, 0xa5, 0x43, 0xcd, 0x68, 0xbf, 0xfb, 0x34, 0xd0, 0x51, 0x22, 0xb6, 0x5c, 0x4c, 0xbb, 0xf2, 0x76, + 0x98, 0x78, 0x1a, 0xd8, 0x2a, 0x33, 0x22, 0x4d, 0xd9, 0xc2, 0xcb, 0x11, 0x49, 0x7e, 0xd4, 0x5d, 0xb3, 0x6a, 0x52, + 0x1b, 0x67, 0x2d, 0x3c, 0xdd, 0x52, 0xe4, 0x14, 0x0a, 0x2e, 0xda, 0xee, 0x83, 0x0c, 0x82, 0x69, 0xd3, 0xc6, 0x59, + 0x6f, 0xbb, 0x2f, 0xa2, 0x8e, 0x57, 0x74, 0x5c, 0x24, 0x6c, 0x6e, 0xf7, 0x14, 0x65, 0x07, 0x89, 0xf2, 0x24, 0x26, + 0xd3, 0x91, 0x03, 0x95, 0xb4, 0xa1, 0xd4, 0xd2, 0x7b, 0xc9, 0x8a, 0x8b, 0xb8, 0xf8, 0xbf, 0xca, 0xb2, 0xad, 0x2f, + 0xbe, 0x48, 0xb0, 0xa0, 0x83, 0x39, 0xa2, 0xc0, 0x3c, 0x97, 0xd2, 0x41, 0x89, 0x44, 0x11, 0xf9, 0x49, 0xc1, 0xec, + 0xaa, 0x64, 0x0d, 0x3e, 0x68, 0xa5, 0x3b, 0x93, 0x49, 0x43, 0x22, 0xe5, 0x9a, 0xd4, 0xda, 0x16, 0x1b, 0x19, 0xf1, + 0xcc, 0x0f, 0x56, 0x89, 0x30, 0x12, 0x0f, 0x32, 0x25, 0x96, 0xc2, 0xb3, 0x85, 0x94, 0xf8, 0x22, 0x67, 0x9f, 0xeb, + 0xc5, 0x6e, 0xb4, 0xc8, 0x62, 0x7e, 0x98, 0xf9, 0xe5, 0x70, 0xb3, 0x5b, 0x11, 0xa3, 0xde, 0x9a, 0xb3, 0x3c, 0x2b, + 0x99, 0x8d, 0x6b, 0x47, 0x8e, 0xb9, 0x04, 0x1a, 0x29, 0x04, 0x0a, 0xe9, 0x93, 0x81, 0x53, 0x8b, 0xcb, 0x81, 0x0d, + 0x1a, 0xdf, 0xf1, 0xc9, 0xb3, 0xa5, 0xbb, 0x8b, 0xa1, 0x61, 0xdb, 0x21, 0x11, 0x44, 0x68, 0xbc, 0x21, 0xd1, 0x32, + 0x34, 0x3f, 0x78, 0x3a, 0xef, 0xcc, 0xf4, 0xea, 0x8e, 0xa4, 0x67, 0x69, 0xe1, 0x11, 0xe0, 0x7c, 0x52, 0x91, 0xe6, + 0xd6, 0x3e, 0xc9, 0x21, 0xeb, 0xfe, 0x45, 0xb3, 0x7e, 0x45, 0x00, 0x77, 0x92, 0x80, 0x10, 0xa0, 0xe1, 0x75, 0x6b, + 0x21, 0x8c, 0x25, 0xcc, 0x38, 0x84, 0xee, 0x2a, 0xf8, 0x6f, 0x12, 0xa6, 0xe7, 0xa5, 0x09, 0x8d, 0x2f, 0x4a, 0xc5, + 0x60, 0x27, 0x0b, 0x84, 0x5b, 0x40, 0x14, 0x04, 0x81, 0x20, 0x63, 0x16, 0x8a, 0xa9, 0x84, 0x76, 0xa0, 0x15, 0x14, + 0x48, 0x80, 0x89, 0x37, 0x4e, 0x85, 0x41, 0x55, 0x6d, 0xc5, 0xd3, 0x1c, 0xb3, 0xe1, 0xa4, 0x61, 0x50, 0x58, 0x7f, + 0x02, 0x5d, 0x9c, 0x62, 0x92, 0x0c, 0xfb, 0xbb, 0x78, 0xe3, 0xc9, 0xba, 0x9d, 0x89, 0x52, 0x29, 0xf6, 0x59, 0x93, + 0x27, 0x34, 0xc3, 0x79, 0x21, 0xea, 0xcb, 0xba, 0xb4, 0xee, 0x83, 0xd5, 0x74, 0x07, 0x4f, 0x9e, 0x75, 0xa4, 0xb7, + 0x71, 0x60, 0xb9, 0x83, 0x44, 0x80, 0x45, 0xda, 0x03, 0xcd, 0xc8, 0x32, 0x64, 0xa8, 0x02, 0xac, 0x35, 0xe6, 0x4e, + 0x0d, 0x6d, 0x0f, 0xe5, 0x46, 0x72, 0x6d, 0x12, 0xac, 0x1e, 0x96, 0xbe, 0xbc, 0xba, 0x6e, 0x73, 0x63, 0x00, 0xbb, + 0xef, 0xd8, 0xb2, 0xa0, 0xcb, 0x11, 0x19, 0x8e, 0x27, 0xb7, 0x09, 0xd5, 0x03, 0x14, 0x8a, 0x6a, 0xaa, 0x69, 0xed, + 0x1f, 0x7e, 0xe6, 0x9d, 0x38, 0xd4, 0x39, 0x21, 0x36, 0x2a, 0x8f, 0xd0, 0x31, 0x8f, 0x7d, 0xa2, 0xcf, 0x25, 0xef, + 0x69, 0xbe, 0x41, 0xea, 0xc8, 0xc5, 0xd5, 0x79, 0x92, 0xa8, 0x1b, 0x63, 0xb5, 0x15, 0x5b, 0x84, 0x01, 0x16, 0x73, + 0x0c, 0x87, 0xe8, 0x54, 0x70, 0xb4, 0x24, 0xbd, 0x8d, 0xa5, 0xea, 0xe5, 0xf6, 0xdb, 0xaa, 0x4b, 0x6b, 0xa7, 0x09, + 0x83, 0xe8, 0xf4, 0x90, 0x01, 0x07, 0x42, 0xc6, 0xda, 0x3e, 0x58, 0xc6, 0x71, 0x46, 0xeb, 0x32, 0x68, 0x04, 0x63, + 0xe8, 0x00, 0xe5, 0xac, 0x7a, 0x1c, 0xec, 0x04, 0x62, 0x79, 0x48, 0x6f, 0x9a, 0xcc, 0x00, 0xd9, 0x22, 0x97, 0x5f, + 0x6a, 0xa2, 0x9d, 0x85, 0x8e, 0x2d, 0xfb, 0x1e, 0xd0, 0xae, 0x03, 0x47, 0x5f, 0x07, 0x1c, 0x75, 0xe2, 0x45, 0x2d, + 0x85, 0x36, 0xc7, 0xc0, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x68, 0xc7, 0xbd, 0x03, 0xbc, 0x98, 0xd2, 0xf5, 0x02, + 0xfc, 0x76, 0x70, 0x19, 0xf8, 0xc4, 0x83, 0xdb, 0xea, 0xb0, 0x63, 0x67, 0x92, 0xc6, 0x79, 0x34, 0x75, 0x73, 0xce, + 0xb9, 0xd0, 0xe5, 0xdc, 0xff, 0x9e, 0x6e, 0xfd, 0xfe, 0x8a, 0xf1, 0x69, 0xad, 0x3d, 0x61, 0xb9, 0xca, 0x69, 0x97, + 0x45, 0x2c, 0x59, 0x71, 0x8e, 0xbe, 0x10, 0xc8, 0xd7, 0xeb, 0xfc, 0x7e, 0xa1, 0x41, 0xe7, 0xd4, 0x41, 0x74, 0x8e, + 0x71, 0xb2, 0xd3, 0x83, 0xc9, 0x7b, 0x65, 0x71, 0x68, 0xac, 0x52, 0x66, 0xf1, 0x7d, 0xe3, 0x96, 0xde, 0x9e, 0x50, + 0x76, 0x29, 0x85, 0x14, 0xca, 0xb2, 0xe1, 0xb6, 0xc7, 0x81, 0xa6, 0xed, 0x36, 0x92, 0xdd, 0xd6, 0xb7, 0xef, 0x34, + 0x89, 0x48, 0xd2, 0xdd, 0x05, 0x51, 0x78, 0x86, 0xd0, 0x18, 0x50, 0xb0, 0x37, 0xa7, 0xd6, 0xe5, 0x6b, 0x2f, 0x2b, + 0xf1, 0x8a, 0x78, 0x57, 0x0c, 0xc6, 0xca, 0x09, 0x1d, 0x2c, 0xd2, 0x34, 0x50, 0xc7, 0x4e, 0x92, 0xb8, 0x55, 0x49, + 0xfc, 0xd0, 0xf2, 0x2f, 0xa4, 0xb9, 0x51, 0x79, 0x2a, 0xe2, 0xeb, 0x10, 0x7d, 0xe6, 0xb8, 0x54, 0xf7, 0x46, 0x35, + 0x83, 0x72, 0xcc, 0x93, 0x79, 0xc3, 0x5c, 0xa6, 0xdb, 0x29, 0x32, 0x4f, 0xf6, 0xbc, 0xb9, 0x99, 0x51, 0xa2, 0x44, + 0xa4, 0x2e, 0xf4, 0x32, 0xd7, 0x56, 0xa1, 0x23, 0x8d, 0xd8, 0xb4, 0x56, 0xb3, 0x89, 0x3d, 0x0e, 0x67, 0x3f, 0x59, + 0xd9, 0x13, 0xbc, 0xeb, 0x3d, 0xef, 0xec, 0xc3, 0xe6, 0x82, 0xeb, 0xd0, 0x88, 0x21, 0x33, 0x60, 0xa6, 0x59, 0x3a, + 0x53, 0x20, 0x8b, 0xb8, 0xaf, 0xee, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0x75, 0x7d, 0xad, 0x54, 0x1d, 0x93, 0x1f, + 0xbe, 0xa3, 0x6b, 0x38, 0x77, 0x50, 0x94, 0x18, 0x4e, 0x34, 0xed, 0xe6, 0x52, 0x03, 0x10, 0x7e, 0x67, 0x87, 0x51, + 0x58, 0xc1, 0xb6, 0xa8, 0xb7, 0xea, 0x2a, 0x60, 0xa0, 0x86, 0x79, 0x32, 0xf6, 0x46, 0x11, 0x19, 0xf5, 0x1b, 0x76, + 0x23, 0xaf, 0x2c, 0xba, 0x65, 0x8d, 0xcf, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x0e, 0x0b, 0xe4, 0x86, 0xeb, + 0x42, 0x21, 0xa9, 0x37, 0x1c, 0x9b, 0x6d, 0x6b, 0xe6, 0x99, 0x06, 0xba, 0x6d, 0x4d, 0xef, 0x13, 0x3b, 0x70, 0xc3, + 0x6d, 0xdd, 0x30, 0x55, 0x6d, 0x3b, 0x8f, 0x5f, 0xef, 0xd3, 0x22, 0xac, 0x09, 0x6d, 0x18, 0xc6, 0x1a, 0xd8, 0xb6, + 0x45, 0x31, 0x17, 0x83, 0x98, 0xf6, 0xd8, 0x62, 0xdf, 0x81, 0x6c, 0xdf, 0xfd, 0xb5, 0x4a, 0x42, 0x4e, 0xae, 0xd2, + 0xf9, 0x35, 0xf9, 0x49, 0x27, 0x8b, 0x44, 0x66, 0x76, 0x91, 0xbf, 0xc6, 0x95, 0xfd, 0xa3, 0x95, 0xdd, 0xab, 0x95, + 0x2e, 0x52, 0x40, 0x14, 0xa6, 0xc2, 0x73, 0x08, 0x4c, 0x97, 0xac, 0xfc, 0x1f, 0xe8, 0x38, 0x27, 0x63, 0x4a, 0x68, + 0x6f, 0x34, 0x9a, 0x40, 0x37, 0x24, 0x14, 0x43, 0x0b, 0xcb, 0xe9, 0x79, 0xa9, 0x41, 0x57, 0x3b, 0x5c, 0x47, 0x96, + 0xfb, 0x22, 0xc0, 0x4f, 0x14, 0x50, 0x67, 0x6a, 0x82, 0xdd, 0x4f, 0x02, 0x63, 0x69, 0xd6, 0x59, 0xfa, 0x45, 0x87, + 0xd3, 0x15, 0x75, 0xf7, 0xf4, 0x2b, 0x86, 0x44, 0x77, 0xf8, 0x95, 0x42, 0xeb, 0x13, 0x33, 0x73, 0x81, 0x46, 0x3a, + 0x6e, 0x60, 0x10, 0x2e, 0x6a, 0x0b, 0xfe, 0x80, 0x5c, 0xc5, 0x4d, 0xe1, 0x6e, 0x72, 0x00, 0x97, 0xca, 0x6d, 0xcb, + 0xb3, 0x4a, 0x13, 0x98, 0x7d, 0x92, 0x32, 0x3a, 0x71, 0x8c, 0xba, 0x6f, 0x77, 0x3f, 0x4a, 0x52, 0xde, 0x3e, 0x7d, + 0xf3, 0x7a, 0x95, 0x35, 0xca, 0xde, 0x33, 0xb3, 0xd4, 0x55, 0xfc, 0xa9, 0x49, 0xee, 0x6a, 0xee, 0x3b, 0xe9, 0x56, + 0x20, 0x30, 0xca, 0x79, 0x85, 0xe5, 0xce, 0xb2, 0x90, 0xc3, 0xe6, 0x5e, 0xba, 0x4f, 0x4b, 0x9a, 0xec, 0x44, 0x55, + 0x62, 0x8c, 0x49, 0xa1, 0xfd, 0xf2, 0x74, 0xee, 0x8f, 0x0e, 0xdf, 0xa3, 0xa3, 0xbe, 0x4b, 0xd3, 0x72, 0xda, 0x8a, + 0xed, 0xf2, 0xc4, 0x0e, 0xa6, 0xe1, 0x9a, 0x30, 0x2d, 0x03, 0x84, 0xee, 0xea, 0x03, 0xe8, 0x5f, 0xe2, 0x1f, 0xfa, + 0xf1, 0x9c, 0xa2, 0x0f, 0xd0, 0x83, 0xd9, 0x9a, 0xca, 0x25, 0x6a, 0x50, 0x22, 0xb2, 0x4d, 0xbb, 0x34, 0x01, 0x53, + 0xe4, 0x20, 0xdd, 0x42, 0x06, 0xa2, 0x64, 0x21, 0x98, 0x41, 0xe5, 0x17, 0xf1, 0x3a, 0xf1, 0x75, 0xbe, 0x5a, 0xf0, + 0x92, 0x9e, 0x70, 0x55, 0xc8, 0xd5, 0x0d, 0xa3, 0xc5, 0xbc, 0x3a, 0xed, 0xa4, 0xda, 0x38, 0x34, 0xa8, 0x51, 0x87, + 0x48, 0xd7, 0xf1, 0xfe, 0x6f, 0x36, 0x52, 0x37, 0x18, 0xfd, 0xe4, 0x24, 0xe0, 0xfb, 0xc6, 0x48, 0xa5, 0xb3, 0x87, + 0x38, 0xb5, 0x16, 0x3c, 0x5e, 0x28, 0x7b, 0x34, 0xea, 0x11, 0xb5, 0xc6, 0x5e, 0x0e, 0x32, 0xad, 0x0d, 0x27, 0x85, + 0xd2, 0x79, 0xb8, 0x94, 0x77, 0x49, 0xe1, 0xd2, 0x1b, 0x95, 0x88, 0xf2, 0x00, 0x76, 0xc2, 0x96, 0x8a, 0x1b, 0x95, + 0xb4, 0x80, 0xea, 0x99, 0x9e, 0x0c, 0x89, 0xe9, 0x9c, 0x44, 0x8c, 0x19, 0x9e, 0xd2, 0xcd, 0x38, 0x44, 0x6b, 0x68, + 0x86, 0x3d, 0xbd, 0x8f, 0xd5, 0x13, 0xe4, 0x80, 0x9d, 0x8d, 0xeb, 0x0c, 0x21, 0x76, 0x52, 0xe1, 0x67, 0x6a, 0x55, + 0x6c, 0x99, 0x7f, 0x24, 0xa8, 0x6d, 0xf3, 0xb6, 0x8f, 0x88, 0xf2, 0xd6, 0xd2, 0x37, 0xb9, 0xbf, 0xe2, 0xca, 0x78, + 0x25, 0x81, 0x66, 0x96, 0x97, 0xfc, 0x1c, 0xe6, 0x67, 0xbf, 0xb1, 0x03, 0x13, 0x88, 0x38, 0xdb, 0x68, 0xd4, 0x53, + 0x72, 0x34, 0xd7, 0x39, 0xef, 0x5b, 0x70, 0x46, 0xc9, 0x34, 0x10, 0x62, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, 0x71, + 0x56, 0x38, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7a, 0x6f, 0x22, 0xf7, 0x45, 0x4d, 0x7a, 0x06, 0xfe, 0xd8, 0x51, 0x63, + 0x31, 0x8a, 0x6e, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0x43, 0xbd, 0xf4, 0x66, 0xae, 0xfd, 0xd2, 0xd3, 0x5a, 0xaa, + 0x0b, 0x74, 0x71, 0xe8, 0x31, 0x6a, 0x51, 0x5e, 0x41, 0x1a, 0x4c, 0x7b, 0xa0, 0xec, 0x35, 0x4c, 0xe8, 0x01, 0xbf, + 0x54, 0x82, 0x8c, 0x06, 0xef, 0x7c, 0xb4, 0xc5, 0xc5, 0x74, 0x92, 0xf3, 0x66, 0x01, 0x05, 0xb7, 0xeb, 0x2d, 0xa9, + 0x89, 0xd0, 0x1a, 0x37, 0x28, 0x6c, 0x91, 0xf0, 0x4f, 0x34, 0x87, 0xb3, 0x2b, 0x24, 0x75, 0x88, 0x4d, 0x31, 0xc2, + 0x04, 0xb4, 0x66, 0x5c, 0x6c, 0x68, 0x61, 0x37, 0xd1, 0x03, 0x6b, 0xf3, 0x20, 0x19, 0x87, 0x3b, 0x9a, 0x69, 0x33, + 0x90, 0x6b, 0x09, 0xfe, 0x2c, 0x11, 0xbd, 0xc3, 0xae, 0x0f, 0x77, 0x64, 0xd8, 0xdc, 0x12, 0xb2, 0x52, 0x66, 0x7a, + 0x78, 0x09, 0xb4, 0xeb, 0xb7, 0x8a, 0xed, 0x50, 0xc1, 0x9f, 0x22, 0x87, 0xa4, 0x98, 0x7e, 0x9f, 0xbd, 0x3a, 0x80, + 0x18, 0xc4, 0xa9, 0xd3, 0x7d, 0x53, 0x60, 0x9d, 0x43, 0x49, 0xb1, 0x21, 0x8c, 0x71, 0xc6, 0x51, 0xbb, 0xdb, 0xd1, + 0xc6, 0x7e, 0x24, 0x86, 0x40, 0xe9, 0xf0, 0xe5, 0x8e, 0x56, 0x5e, 0xb7, 0xb3, 0x75, 0xdb, 0x6b, 0xda, 0x91, 0x0f, + 0xc9, 0x11, 0x4c, 0x8a, 0x48, 0x5a, 0x36, 0x10, 0x9a, 0x31, 0x78, 0x8b, 0xb4, 0x60, 0x6d, 0xcf, 0x80, 0x96, 0xb9, + 0x5e, 0x28, 0xb4, 0xc0, 0xb3, 0x66, 0x0c, 0x4c, 0x0a, 0x8b, 0x0e, 0x2e, 0x69, 0xef, 0x74, 0x82, 0xd9, 0x40, 0xb5, + 0x5a, 0xdb, 0x6d, 0x59, 0xdf, 0x34, 0x0a, 0x84, 0xed, 0xbb, 0x72, 0x33, 0xfd, 0xc8, 0xcf, 0xac, 0x05, 0xf0, 0x55, + 0x6c, 0xbb, 0xce, 0x83, 0x76, 0x5f, 0x5b, 0xe5, 0xde, 0xc7, 0xfe, 0x5a, 0xe2, 0xc7, 0x50, 0xc3, 0xb2, 0x74, 0xc2, + 0x74, 0x65, 0x50, 0xbc, 0xe5, 0x9a, 0xfb, 0xc2, 0xc6, 0x64, 0x7a, 0x87, 0x12, 0x9b, 0xf8, 0xba, 0xb3, 0x1b, 0xcc, + 0x2d, 0x23, 0x7a, 0x59, 0xbf, 0xd3, 0xb7, 0xb2, 0xb5, 0xeb, 0x01, 0x88, 0xa9, 0x57, 0x96, 0x8c, 0x87, 0x19, 0x5d, + 0x3c, 0x04, 0xa5, 0xc9, 0x6b, 0x54, 0x92, 0xc1, 0x67, 0xf5, 0xae, 0x85, 0x44, 0xe4, 0xdb, 0x7a, 0x95, 0x27, 0xb3, + 0x91, 0x0d, 0xc7, 0xae, 0xa7, 0xe5, 0x81, 0x90, 0x32, 0x9a, 0xfd, 0x6d, 0x93, 0xd6, 0x5c, 0x4b, 0xc3, 0x2f, 0x91, + 0xe2, 0xa2, 0xd9, 0x38, 0xca, 0x36, 0x12, 0x04, 0x5d, 0xd5, 0x42, 0xb2, 0x58, 0x78, 0x58, 0xc8, 0x50, 0xbe, 0xac, + 0x84, 0x65, 0x2f, 0xee, 0xa6, 0x13, 0xf9, 0xe6, 0xc6, 0xcd, 0x8f, 0x42, 0xdb, 0xad, 0xaf, 0xdd, 0xf5, 0x43, 0x1b, + 0x51, 0x56, 0xbf, 0xe8, 0xc1, 0x57, 0xaa, 0xb1, 0x3e, 0xb2, 0xfe, 0xff, 0xa1, 0x9f, 0xd4, 0x89, 0xe4, 0xcc, 0x69, + 0x3b, 0x60, 0x7b, 0xa6, 0x80, 0xad, 0xd0, 0xf6, 0xb0, 0xa9, 0xf4, 0xfe, 0xce, 0x25, 0x81, 0x5c, 0x88, 0xf8, 0x84, + 0x85, 0x40, 0x92, 0xe2, 0x91, 0x4e, 0x03, 0x4c, 0x2d, 0x03, 0xea, 0x11, 0xec, 0xfb, 0xc1, 0x8e, 0x7c, 0xf3, 0x92, + 0xed, 0xf2, 0xb6, 0xee, 0x27, 0x28, 0xeb, 0x3e, 0x0f, 0x81, 0x8d, 0xdb, 0xd2, 0xe5, 0x80, 0x49, 0x1c, 0xc8, 0xc4, + 0x4c, 0xfb, 0x65, 0x6a, 0x2f, 0xdf, 0x2a, 0x67, 0x9c, 0xa0, 0x5b, 0x8a, 0x5a, 0x0e, 0x29, 0x71, 0x48, 0x5b, 0x79, + 0xe7, 0x86, 0xbd, 0x91, 0x7e, 0x88, 0x73, 0x8b, 0x1e, 0x07, 0x46, 0xd4, 0x69, 0xce, 0x66, 0x21, 0x42, 0x4d, 0xae, + 0x1a, 0xe5, 0xf1, 0x03, 0x57, 0xe9, 0x5a, 0xaa, 0xee, 0x2b, 0x94, 0xcc, 0x9e, 0x08, 0x93, 0x39, 0xb4, 0x3b, 0x64, + 0x49, 0x89, 0x66, 0x1f, 0xbb, 0x75, 0x40, 0x60, 0x27, 0x60, 0x9e, 0x96, 0xc8, 0xeb, 0x94, 0x4c, 0xfc, 0xf6, 0xed, + 0x3f, 0xca, 0xeb, 0x08, 0x86, 0xbd, 0xe4, 0x30, 0xa7, 0x02, 0x11, 0xc7, 0x71, 0xfe, 0xbc, 0x91, 0x0b, 0x12, 0x63, + 0xfd, 0xf9, 0x6b, 0xac, 0x5c, 0x23, 0x81, 0x56, 0x49, 0x43, 0xe1, 0x99, 0x1b, 0x67, 0xae, 0xec, 0xd4, 0xb3, 0x8c, + 0x2b, 0x76, 0x5b, 0xf4, 0x93, 0xc8, 0xa3, 0x16, 0xcd, 0x94, 0x1e, 0xa9, 0x72, 0x91, 0x94, 0xb4, 0xca, 0xa1, 0x96, + 0x6c, 0x05, 0xca, 0x61, 0x72, 0x2c, 0xe3, 0x3a, 0x73, 0x1a, 0x9a, 0xb3, 0x2c, 0x01, 0x72, 0x8b, 0x25, 0x38, 0xc7, + 0x4c, 0x2e, 0xc3, 0x4a, 0x2a, 0x24, 0x60, 0x1c, 0x84, 0xc2, 0x4f, 0xfe, 0xb1, 0xd2, 0xfe, 0x4e, 0x86, 0x5c, 0x62, + 0xf8, 0x0b, 0x1f, 0x93, 0x9e, 0x2b, 0x1f, 0x0a, 0x66, 0xb0, 0x18, 0xa2, 0xb7, 0x8c, 0x60, 0x5b, 0xee, 0xc4, 0x5b, + 0x34, 0xcb, 0xd2, 0xb9, 0x7f, 0x81, 0x66, 0xdd, 0xac, 0xd5, 0x7d, 0x8b, 0x22, 0xaf, 0x67, 0x4c, 0x9a, 0x70, 0xd2, + 0x4a, 0xa9, 0x94, 0xa6, 0xa0, 0x23, 0x4a, 0x32, 0x01, 0xcc, 0x0c, 0x50, 0xb2, 0x93, 0x8c, 0x4a, 0x0f, 0xca, 0xc9, + 0x70, 0x62, 0x31, 0xd3, 0xe8, 0x2c, 0x06, 0xac, 0x5e, 0x35, 0x3e, 0xce, 0x27, 0x1d, 0xff, 0x03, 0x40, 0xf5, 0xb5, + 0xd7, 0x82, 0xd7, 0x3c, 0x97, 0x93, 0xae, 0xe9, 0xba, 0x3a, 0xf6, 0x3f, 0xee, 0x45, 0x57, 0x50, 0x35, 0x66, 0xbf, + 0xd8, 0x5f, 0xd2, 0x38, 0x0c, 0x13, 0x62, 0x7c, 0x70, 0x1f, 0x70, 0xd4, 0x01, 0x5b, 0xac, 0x7a, 0x72, 0x91, 0x64, + 0x96, 0xa4, 0xb7, 0xb9, 0xe8, 0x3a, 0x7e, 0x70, 0x60, 0xa8, 0x2e, 0x6d, 0xba, 0xe7, 0x91, 0x15, 0x6f, 0x8d, 0x25, + 0xc0, 0x52, 0xcc, 0x81, 0x2e, 0x18, 0x1d, 0xaf, 0x08, 0xce, 0xb6, 0x13, 0x20, 0x0a, 0x63, 0x2d, 0x8a, 0x2c, 0x4e, + 0xf8, 0x5b, 0xd2, 0x26, 0x60, 0x4b, 0xc6, 0x28, 0x8d, 0x7d, 0x0e, 0xce, 0x95, 0xf9, 0xe0, 0xb1, 0xea, 0x17, 0x75, + 0xba, 0xba, 0x0c, 0xb1, 0xcf, 0x4f, 0x72, 0x79, 0xfd, 0x1d, 0xea, 0x4b, 0xbf, 0x8d, 0xd2, 0x17, 0x78, 0x67, 0x09, + 0x39, 0xef, 0x5e, 0xff, 0x54, 0xb4, 0x38, 0x30, 0x0b, 0x5d, 0xc5, 0x16, 0xb5, 0xe0, 0xfc, 0xe9, 0x85, 0x44, 0x14, + 0x65, 0x8f, 0x09, 0x90, 0xa9, 0xa6, 0xac, 0x7e, 0x53, 0xa4, 0x40, 0xc6, 0x45, 0x55, 0x9c, 0x3c, 0x06, 0xdf, 0xce, + 0x37, 0x77, 0x94, 0xc1, 0x68, 0xc8, 0xba, 0x5f, 0xef, 0xd8, 0xc4, 0x6f, 0xc4, 0xfc, 0x8f, 0x09, 0x27, 0xbd, 0x7a, + 0x4a, 0x80, 0x4a, 0xda, 0x49, 0x2a, 0x7d, 0x50, 0xe0, 0x85, 0x89, 0x26, 0x67, 0xa8, 0x41, 0x56, 0x78, 0x02, 0x9d, + 0x01, 0xcb, 0xd8, 0x62, 0x4a, 0xd9, 0x6d, 0x9b, 0xf8, 0x19, 0x85, 0x37, 0xb6, 0xb5, 0xd5, 0x18, 0xa4, 0xa7, 0x0a, + 0xd0, 0xf6, 0x38, 0x53, 0x85, 0x67, 0xd1, 0x85, 0x73, 0x6e, 0xde, 0x39, 0x70, 0x3e, 0xac, 0xcd, 0xc3, 0x97, 0xbf, + 0x20, 0x07, 0x85, 0x5d, 0x93, 0x3a, 0xa8, 0xea, 0x9a, 0x97, 0x74, 0xc2, 0x3f, 0x61, 0x7b, 0x89, 0xc5, 0x4c, 0x5e, + 0xd2, 0x7e, 0x0a, 0x1d, 0x21, 0x6d, 0x1e, 0x3a, 0xcd, 0xf6, 0x6f, 0x8a, 0x99, 0x1c, 0x2f, 0xb6, 0x9a, 0xfd, 0xb2, + 0x31, 0xfe, 0x2d, 0x92, 0x02, 0xee, 0x2b, 0xe7, 0xc3, 0x2a, 0x32, 0x89, 0x3a, 0xae, 0x8d, 0x17, 0x94, 0x3e, 0x86, + 0xe9, 0x68, 0xb1, 0xea, 0xb2, 0x8c, 0x7b, 0xa5, 0xcc, 0x91, 0x51, 0x82, 0xc3, 0x53, 0x55, 0x44, 0x15, 0x3a, 0xaf, + 0x21, 0x2f, 0xcd, 0xfc, 0xba, 0x4a, 0x45, 0xe8, 0x43, 0x99, 0x73, 0xce, 0x5b, 0xa2, 0xee, 0x7a, 0xa2, 0xf8, 0x71, + 0x81, 0x42, 0x5b, 0x22, 0x8c, 0x7c, 0x70, 0x06, 0xa7, 0x49, 0x82, 0x47, 0x26, 0x22, 0x8f, 0x3c, 0xc5, 0xf5, 0x8b, + 0x51, 0x49, 0x2f, 0x2f, 0xe1, 0x91, 0x73, 0x97, 0xc5, 0xdd, 0x47, 0xfc, 0x5a, 0x7d, 0x89, 0x3e, 0x2c, 0xe1, 0x28, + 0x88, 0x95, 0x76, 0xbf, 0x0c, 0x9f, 0xd4, 0x81, 0xca, 0xf9, 0x3f, 0xa8, 0xbf, 0x86, 0x2c, 0xb2, 0x88, 0x26, 0xeb, + 0x0a, 0x73, 0x70, 0xd4, 0x0f, 0x8b, 0x10, 0xf9, 0x22, 0x43, 0x48, 0x16, 0xdd, 0xea, 0xe5, 0x21, 0xb4, 0x9e, 0xfc, + 0xdd, 0x32, 0xf7, 0xfb, 0xbb, 0x6a, 0x7a, 0x38, 0x8d, 0x14, 0xfc, 0x48, 0x45, 0x5f, 0x76, 0x75, 0x7b, 0x12, 0xdf, + 0xf5, 0x7c, 0x0f, 0x01, 0xb3, 0x8f, 0x34, 0x44, 0xf2, 0x66, 0xd9, 0x3a, 0xf4, 0x4d, 0x6c, 0x71, 0x45, 0x6b, 0xd0, + 0xa5, 0xd4, 0xf4, 0x51, 0x81, 0x33, 0xbc, 0x12, 0x74, 0x90, 0xe1, 0x68, 0xb9, 0xf2, 0xa6, 0x42, 0xb0, 0x38, 0xa9, + 0xda, 0x6e, 0x8b, 0x32, 0xdb, 0x33, 0x38, 0x89, 0x16, 0x51, 0x93, 0x99, 0xfc, 0x3e, 0x7d, 0x14, 0xab, 0xdc, 0x28, + 0x82, 0x3b, 0xfa, 0xc2, 0x2a, 0xad, 0xbd, 0x34, 0xe4, 0x97, 0x5a, 0xb2, 0x85, 0x06, 0x54, 0x4a, 0x79, 0xa1, 0x6a, + 0x5c, 0x2e, 0x85, 0x2b, 0x63, 0x6b, 0xf4, 0x30, 0xd3, 0xaa, 0x78, 0x15, 0x57, 0x48, 0xc7, 0xd7, 0x88, 0x45, 0xe8, + 0xb2, 0x0c, 0x12, 0x1e, 0xce, 0x72, 0x2e, 0x79, 0x72, 0x0d, 0x56, 0x3c, 0xb7, 0x60, 0x0e, 0x66, 0x5d, 0xab, 0x27, + 0xd5, 0xd8, 0x80, 0x91, 0x14, 0xf9, 0x2a, 0xa6, 0x73, 0xd5, 0x01, 0x75, 0x5c, 0x43, 0x60, 0x16, 0xee, 0x23, 0x3f, + 0x4a, 0x49, 0xaf, 0x94, 0x91, 0x33, 0xdc, 0x56, 0x49, 0x36, 0xe3, 0x64, 0x24, 0xdc, 0xd1, 0xc6, 0xce, 0x45, 0x01, + 0x3f, 0x0a, 0x39, 0x53, 0x02, 0x1a, 0xd2, 0x10, 0x49, 0x2e, 0x76, 0xcf, 0x13, 0xab, 0x21, 0xd2, 0x93, 0x05, 0x05, + 0x10, 0x79, 0x58, 0xfb, 0x60, 0x49, 0x79, 0x34, 0xb5, 0x80, 0x89, 0x79, 0xae, 0xfc, 0xa8, 0xbd, 0x85, 0xaf, 0xd6, + 0xa1, 0x04, 0xcc, 0xe1, 0xcb, 0x24, 0xd6, 0x4a, 0x9b, 0xf1, 0xb8, 0x2c, 0x8f, 0xca, 0x5b, 0xcb, 0x6a, 0xba, 0xa2, + 0x7a, 0xd0, 0x98, 0x1e, 0xae, 0x53, 0x62, 0x6c, 0x2c, 0xb3, 0x4e, 0x5c, 0x2a, 0xe6, 0xbf, 0x4f, 0x5f, 0xaa, 0x8b, + 0xaa, 0x96, 0x6f, 0x23, 0xae, 0x67, 0x8c, 0x6a, 0x51, 0xc3, 0x03, 0xe6, 0x5f, 0x96, 0x31, 0x2c, 0xd7, 0x04, 0xb3, + 0x5c, 0x13, 0xbd, 0xad, 0x86, 0xa0, 0xed, 0x78, 0x14, 0x95, 0xa0, 0x1b, 0x31, 0xa0, 0x91, 0x52, 0x23, 0x60, 0x9b, + 0x14, 0x62, 0xf0, 0x1b, 0xb0, 0x3f, 0x76, 0x08, 0x48, 0x05, 0x47, 0xf0, 0x80, 0x70, 0xc9, 0x71, 0xf9, 0x61, 0xd2, + 0xdd, 0x42, 0x02, 0xa9, 0x78, 0x39, 0x2b, 0x9f, 0x96, 0x08, 0x46, 0x31, 0x28, 0x8b, 0xd0, 0x0c, 0x91, 0x52, 0x37, + 0x2b, 0x32, 0xea, 0xe0, 0x8d, 0xc1, 0x37, 0x22, 0x06, 0xbc, 0x52, 0x50, 0xc8, 0x63, 0x4e, 0x4e, 0x96, 0xcb, 0xd7, + 0xb9, 0x4b, 0x7f, 0x47, 0x4f, 0xe5, 0x38, 0x75, 0x47, 0xd0, 0xa6, 0x8f, 0x62, 0x9c, 0x8b, 0x4a, 0x82, 0xeb, 0xe5, + 0xb4, 0xf7, 0x98, 0xd1, 0x7c, 0xe1, 0xea, 0x69, 0x3c, 0x68, 0x8b, 0xdf, 0x8f, 0x39, 0xfb, 0xf0, 0x29, 0x35, 0xba, + 0x80, 0x02, 0x0f, 0x3b, 0x75, 0xdb, 0xc8, 0x29, 0x46, 0x80, 0xbf, 0xad, 0xaf, 0xc7, 0xa3, 0xcd, 0x96, 0xb9, 0x20, + 0x35, 0xec, 0x1b, 0x7c, 0x39, 0x18, 0x7f, 0x45, 0xb4, 0xc3, 0xd7, 0x64, 0xdd, 0x43, 0x83, 0xee, 0x5e, 0xd6, 0xf0, + 0x05, 0x0b, 0x74, 0x7e, 0x89, 0x21, 0x6f, 0xd9, 0x81, 0xe5, 0x3e, 0xcf, 0xf5, 0x04, 0x99, 0xc6, 0xc3, 0x78, 0x0d, + 0xc8, 0x35, 0x9e, 0xe5, 0xbd, 0x1b, 0xf5, 0x7b, 0xb6, 0x9c, 0x77, 0xc4, 0xd6, 0xd4, 0xbb, 0x6c, 0x03, 0x8c, 0xa3, + 0xea, 0x7f, 0xdf, 0x54, 0x22, 0x18, 0x99, 0xa1, 0x7d, 0x5a, 0xeb, 0xa3, 0xca, 0xd3, 0xff, 0x37, 0xb3, 0x75, 0x61, + 0x65, 0x98, 0x43, 0x30, 0xe3, 0x2b, 0x7c, 0x9a, 0x71, 0x1e, 0x44, 0x78, 0x20, 0xed, 0x5e, 0x66, 0x37, 0xd6, 0x9c, + 0xd1, 0x8f, 0xd0, 0x9d, 0x92, 0xec, 0x02, 0xc7, 0xf1, 0x6f, 0x83, 0x9e, 0x0a, 0xb5, 0x1f, 0xd5, 0x81, 0xc5, 0xdf, + 0x05, 0xa9, 0x09, 0xc9, 0x50, 0x80, 0x03, 0xb9, 0x6a, 0xd9, 0x7b, 0xba, 0x9d, 0x5d, 0x4c, 0x13, 0xc4, 0xa5, 0xb3, + 0xd5, 0x97, 0xd7, 0xad, 0x17, 0x68, 0xdf, 0xec, 0xfd, 0x68, 0x63, 0xa6, 0x98, 0xc7, 0xeb, 0xbb, 0xa6, 0xe3, 0x37, + 0x14, 0x86, 0xd6, 0xf8, 0x2a, 0x62, 0xba, 0x6f, 0x68, 0xde, 0xcb, 0xb5, 0x37, 0xed, 0x3d, 0x7e, 0xb1, 0xd7, 0xea, + 0x2c, 0xb0, 0xf1, 0x46, 0x01, 0x57, 0x26, 0x2e, 0x67, 0x94, 0xe4, 0xc3, 0x0d, 0x82, 0xeb, 0xf8, 0xd1, 0xaa, 0x19, + 0xee, 0x7a, 0x7c, 0xa3, 0x13, 0x96, 0x61, 0x60, 0xba, 0x85, 0xeb, 0x40, 0x8c, 0x61, 0x6c, 0x11, 0x42, 0x91, 0xfa, + 0x91, 0xc6, 0x30, 0x0a, 0xc6, 0xcf, 0x4f, 0xd6, 0x98, 0xd9, 0xf1, 0x1f, 0x51, 0x00, 0xae, 0x5d, 0x84, 0x23, 0x30, + 0xcc, 0x2c, 0xa8, 0x50, 0xe1, 0x42, 0x1f, 0x89, 0x2b, 0x9b, 0xb2, 0xa7, 0xf0, 0x02, 0xf2, 0x25, 0xa6, 0xfd, 0x51, + 0xd7, 0xf9, 0x83, 0x13, 0xf9, 0x49, 0xed, 0xee, 0xf7, 0x4a, 0xb7, 0x17, 0xe1, 0x32, 0xd3, 0x75, 0xc4, 0x00, 0xc9, + 0x63, 0x30, 0xc1, 0x68, 0x31, 0x64, 0xc7, 0x4d, 0xed, 0x59, 0x9d, 0xce, 0xc9, 0xf1, 0xe0, 0x7f, 0xad, 0x82, 0xd9, + 0xf8, 0x28, 0xde, 0x56, 0x8d, 0x9c, 0xed, 0x49, 0xba, 0xf9, 0x63, 0xa5, 0xc9, 0xec, 0xff, 0x61, 0x7e, 0x9d, 0x05, + 0x0b, 0xe6, 0x8b, 0x45, 0x8b, 0xac, 0x21, 0x6a, 0x80, 0x1f, 0xee, 0x34, 0xa6, 0x7c, 0x46, 0x19, 0x61, 0xab, 0x5a, + 0x2b, 0x6d, 0x68, 0x80, 0xe6, 0x94, 0x9d, 0x20, 0x45, 0x09, 0x24, 0xef, 0x58, 0x85, 0x91, 0xf9, 0xc0, 0x30, 0x78, + 0xec, 0x7d, 0x6a, 0xdd, 0x9a, 0xa2, 0xae, 0xf0, 0x3e, 0xd1, 0xd8, 0x8d, 0x59, 0x29, 0xf5, 0x73, 0x2b, 0xf4, 0x1f, + 0xd1, 0x0b, 0x11, 0x58, 0x22, 0x3f, 0x04, 0xf5, 0x93, 0xa0, 0x96, 0xf5, 0x27, 0x95, 0xb7, 0x7c, 0x6e, 0xcf, 0x2e, + 0xb6, 0xe5, 0xd3, 0x5c, 0x67, 0x20, 0xb1, 0x33, 0xbe, 0xa9, 0x2f, 0xbe, 0x48, 0xb5, 0x96, 0x5b, 0xba, 0xe5, 0xd1, + 0x34, 0xc4, 0xe8, 0x00, 0x80, 0x94, 0x01, 0xe3, 0x27, 0xf8, 0x81, 0x3a, 0xe3, 0x9f, 0xcf, 0x6f, 0xea, 0x9c, 0xea, + 0xaf, 0xde, 0x48, 0xe8, 0x2d, 0x2d, 0x01, 0xdf, 0x85, 0xfc, 0xdf, 0xfe, 0x95, 0x6e, 0x1d, 0x63, 0x45, 0x60, 0x76, + 0x70, 0x75, 0x92, 0x9d, 0xe9, 0x69, 0x6b, 0xe2, 0x2a, 0x06, 0xef, 0x87, 0x68, 0x9d, 0xfb, 0x91, 0xc0, 0x68, 0x0a, + 0x6f, 0xb3, 0xd8, 0xb4, 0x55, 0xae, 0x57, 0x33, 0x61, 0xb6, 0x8d, 0x2e, 0x91, 0x1a, 0x82, 0xeb, 0x7d, 0x2c, 0xa3, + 0x8b, 0x27, 0x83, 0xb3, 0xba, 0xbe, 0x64, 0x2a, 0xc0, 0x85, 0x14, 0xf5, 0x27, 0xca, 0xb2, 0xdd, 0xa3, 0x2e, 0x35, + 0xdd, 0x1f, 0xb4, 0x76, 0xcf, 0xa5, 0xc5, 0x36, 0x5d, 0x36, 0x7d, 0x6a, 0x3d, 0x10, 0xc1, 0xbe, 0xa5, 0x1b, 0xf6, + 0x02, 0x00, 0x1d, 0xe0, 0x85, 0x6a, 0x13, 0x5d, 0x57, 0xfd, 0x63, 0x0f, 0x48, 0x6b, 0x7c, 0x8f, 0x4d, 0xaa, 0xdc, + 0xc8, 0xa4, 0xda, 0x45, 0x82, 0xb2, 0xc3, 0xf8, 0xf8, 0x0e, 0x7b, 0xad, 0x87, 0x17, 0x6a, 0x55, 0x0a, 0x6b, 0xcb, + 0xdc, 0x9b, 0x31, 0xa9, 0x69, 0xeb, 0x0f, 0x5e, 0x0b, 0xeb, 0x86, 0x2e, 0x85, 0xcb, 0xe2, 0x51, 0xab, 0x03, 0x90, + 0x93, 0x0d, 0x84, 0x70, 0xc4, 0xd3, 0x3f, 0x92, 0x9c, 0x02, 0xbc, 0x0e, 0xdc, 0x15, 0xc7, 0xec, 0xb2, 0x1d, 0x77, + 0xc3, 0x96, 0x5b, 0xf8, 0xb3, 0x5b, 0x20, 0xc5, 0xba, 0xea, 0xdc, 0xb0, 0x83, 0xd7, 0x65, 0x8a, 0xa0, 0x54, 0x48, + 0x40, 0x38, 0x5c, 0xce, 0x2e, 0x05, 0xa1, 0x24, 0x60, 0xac, 0x0a, 0xf7, 0x87, 0xb2, 0xb7, 0xdd, 0x6e, 0xd8, 0x92, + 0x47, 0x92, 0x61, 0xa0, 0x6a, 0x3d, 0xa6, 0xf5, 0xaf, 0x76, 0x3a, 0x81, 0x4a, 0xd6, 0x6c, 0x7a, 0xa4, 0x7f, 0x58, + 0x8f, 0xf4, 0x52, 0xf0, 0x48, 0xc4, 0xe2, 0x1d, 0x19, 0xa3, 0xab, 0x1f, 0x2f, 0x90, 0xd9, 0x3b, 0x2e, 0x7e, 0x98, + 0xc3, 0xda, 0xb0, 0xcb, 0x80, 0x27, 0x98, 0x49, 0x83, 0x7a, 0xd5, 0x55, 0xf4, 0x54, 0x90, 0x0e, 0x8b, 0x86, 0x81, + 0x85, 0x53, 0xea, 0x57, 0xe9, 0x2d, 0x6f, 0x74, 0x16, 0x34, 0x86, 0x12, 0x2d, 0x65, 0xa1, 0x2c, 0x37, 0x93, 0x87, + 0x0d, 0x25, 0x2b, 0xae, 0xa9, 0x6d, 0x67, 0xab, 0x68, 0xd1, 0x0a, 0xc2, 0x1f, 0xd7, 0x30, 0x23, 0xea, 0x2f, 0x64, + 0x9a, 0x75, 0x3b, 0xfc, 0x0c, 0x69, 0xb5, 0xa4, 0x76, 0x6e, 0x81, 0xf6, 0x82, 0x06, 0xfc, 0x1a, 0x82, 0xd6, 0x92, + 0x52, 0x13, 0x9f, 0xd6, 0xb9, 0xe0, 0xf1, 0x86, 0xe1, 0xd3, 0x26, 0xa9, 0x97, 0xd9, 0xc6, 0xd5, 0x0d, 0x4f, 0x73, + 0x29, 0x3a, 0x18, 0x74, 0x90, 0x90, 0x52, 0x73, 0xa8, 0xc8, 0xdf, 0x5d, 0xac, 0x0b, 0xa7, 0x09, 0xc9, 0x66, 0x2a, + 0x59, 0x4e, 0x4a, 0xf6, 0x8c, 0x10, 0x47, 0x3f, 0x20, 0x65, 0xf2, 0x08, 0x35, 0xc9, 0xab, 0x17, 0x90, 0xc9, 0xeb, + 0x51, 0x4b, 0x8a, 0x0b, 0x6d, 0x32, 0xb1, 0x14, 0x70, 0x32, 0x8e, 0x20, 0x13, 0xac, 0xa7, 0x64, 0x75, 0x0d, 0x90, + 0xf4, 0x92, 0x3c, 0x35, 0xb0, 0x60, 0x6a, 0xef, 0x94, 0x02, 0x8b, 0x14, 0x80, 0xa1, 0x9d, 0x34, 0x2a, 0x4b, 0xf2, + 0x58, 0x76, 0xdf, 0x96, 0x65, 0x4f, 0xa1, 0xa0, 0x60, 0xc4, 0xd9, 0x63, 0x9f, 0x9d, 0x05, 0x82, 0xf2, 0x70, 0x06, + 0x65, 0xfa, 0x9c, 0x60, 0x23, 0xcf, 0x11, 0x2c, 0xf2, 0x62, 0x40, 0x8e, 0x2a, 0x5e, 0xd6, 0x08, 0xff, 0xd5, 0x02, + 0xb9, 0xc0, 0xe0, 0xe1, 0x9e, 0x74, 0x7a, 0xad, 0xdf, 0x94, 0x53, 0x50, 0x30, 0xfa, 0x94, 0xd5, 0xcd, 0x38, 0x37, + 0xd4, 0x32, 0x9a, 0x31, 0xf5, 0x67, 0xee, 0xe2, 0x49, 0xbe, 0x55, 0x32, 0xa3, 0x22, 0x93, 0x89, 0x17, 0x7e, 0x00, + 0x3b, 0x3f, 0x2f, 0x26, 0x06, 0x85, 0x27, 0x2e, 0xea, 0x98, 0x11, 0x87, 0xb8, 0x2a, 0x27, 0xbf, 0x2d, 0xc0, 0xa8, + 0xc1, 0x60, 0x72, 0x8b, 0x7a, 0x4d, 0xa9, 0xf7, 0x50, 0x9f, 0x19, 0x0c, 0xb5, 0x71, 0xac, 0x57, 0x56, 0x82, 0x0d, + 0x0d, 0x2f, 0xf9, 0x54, 0xcd, 0x3a, 0x8c, 0x15, 0x7e, 0xa5, 0x02, 0xcc, 0x05, 0xa6, 0x79, 0x1a, 0x87, 0x80, 0x95, + 0x96, 0x6a, 0x18, 0x7d, 0x75, 0xee, 0x10, 0x4a, 0xdd, 0xe8, 0x05, 0x6c, 0x00, 0xc3, 0x21, 0xa2, 0x2d, 0x7a, 0x79, + 0xe1, 0x2b, 0x0d, 0x52, 0xb5, 0x23, 0x4b, 0x5e, 0x1d, 0x72, 0x22, 0x8f, 0x27, 0xe2, 0x7f, 0x26, 0x0c, 0x49, 0x9b, + 0x1b, 0x88, 0xb7, 0x94, 0xdd, 0xd4, 0x71, 0x9a, 0x39, 0x48, 0xef, 0xe9, 0x60, 0xaf, 0x95, 0xaf, 0x6c, 0x93, 0x19, + 0x7a, 0x35, 0x1a, 0x87, 0x82, 0xb4, 0xbc, 0x98, 0x2d, 0x32, 0x69, 0x12, 0xdd, 0x96, 0x16, 0x03, 0x7a, 0x88, 0xec, + 0xcc, 0x43, 0xb1, 0xe2, 0x7d, 0x3d, 0x99, 0x16, 0x14, 0x1d, 0xc2, 0x2d, 0xe4, 0x26, 0x1a, 0xf5, 0x13, 0x5d, 0xb5, + 0x2b, 0x94, 0xd9, 0x7e, 0x26, 0x74, 0x80, 0x97, 0x16, 0x27, 0x00, 0xec, 0xd1, 0x34, 0x2e, 0xb8, 0x6d, 0x09, 0xc3, + 0xd4, 0x86, 0x6a, 0x2e, 0x3b, 0xdd, 0xd6, 0x99, 0x5c, 0x0b, 0x14, 0x83, 0x00, 0x3a, 0xcf, 0x37, 0xef, 0x4f, 0x5e, + 0xfe, 0x0c, 0xc7, 0xb1, 0x83, 0xd1, 0xc9, 0x8c, 0xaa, 0xb8, 0x4d, 0xa2, 0xde, 0x6f, 0xe9, 0xa6, 0x81, 0xbc, 0xef, + 0x41, 0x35, 0x7b, 0xd6, 0xef, 0x4e, 0xd7, 0xc6, 0x3b, 0xf5, 0x9b, 0xd9, 0x00, 0xa0, 0xbc, 0x48, 0x9a, 0x0f, 0x70, + 0xdc, 0xe0, 0xe7, 0x19, 0xab, 0x15, 0x6a, 0x24, 0x22, 0x88, 0x02, 0x12, 0xa6, 0xfe, 0x59, 0x38, 0xbc, 0xc7, 0x77, + 0x2c, 0x3b, 0x51, 0x70, 0x48, 0xea, 0xab, 0xc1, 0xd1, 0x83, 0x6e, 0x4c, 0x05, 0xc3, 0x1a, 0xe3, 0x84, 0x9b, 0x6f, + 0xb1, 0xef, 0x5a, 0x2b, 0x8a, 0xeb, 0xc2, 0x3e, 0xf7, 0x9d, 0xa2, 0x9e, 0x7d, 0x76, 0x43, 0x8f, 0xf3, 0xe0, 0x15, + 0x53, 0x56, 0x29, 0xd6, 0x5d, 0x8e, 0x3c, 0x3e, 0x01, 0x52, 0xf3, 0x5d, 0xc9, 0xdf, 0x60, 0xac, 0x20, 0x0a, 0xbc, + 0x5f, 0x6d, 0x8a, 0x74, 0x39, 0xb1, 0x22, 0x0a, 0x83, 0x20, 0xf3, 0x2a, 0x42, 0xbc, 0xa2, 0x92, 0xdf, 0xb7, 0x03, + 0x38, 0x81, 0x3c, 0x1c, 0xb6, 0x09, 0xbe, 0xdf, 0xd1, 0x40, 0xa8, 0x18, 0x37, 0xd2, 0x76, 0x4b, 0x4e, 0x37, 0x8c, + 0x7b, 0x3a, 0x69, 0xf6, 0x26, 0x91, 0x9b, 0x44, 0x0d, 0x47, 0x11, 0xcb, 0xd7, 0x64, 0x77, 0x45, 0x81, 0x42, 0x80, + 0xc8, 0x2e, 0xf9, 0x1c, 0x96, 0x9a, 0xca, 0xf5, 0xb5, 0xe4, 0x17, 0x48, 0x82, 0x8c, 0xdb, 0x40, 0xea, 0x9f, 0x14, + 0xa1, 0xec, 0x1c, 0xb5, 0x61, 0xc7, 0x8f, 0x26, 0xaa, 0x0e, 0x76, 0xa7, 0x55, 0x9b, 0x1d, 0x8d, 0x60, 0xdf, 0x6b, + 0x85, 0x96, 0x83, 0xd6, 0x59, 0x9f, 0x9a, 0xdc, 0x10, 0x3f, 0x3e, 0xe7, 0x72, 0x80, 0x00, 0x3a, 0x59, 0xa0, 0xc2, + 0xfd, 0xd0, 0x51, 0xdf, 0xae, 0x0e, 0x69, 0x02, 0x45, 0xe5, 0xa0, 0xb8, 0xe3, 0x38, 0x85, 0x5d, 0x91, 0x1d, 0xfd, + 0x42, 0x34, 0x4e, 0xd8, 0xe1, 0x23, 0x6b, 0x9a, 0x3f, 0xc4, 0x09, 0xca, 0x17, 0xf3, 0x50, 0x70, 0x89, 0x3a, 0x1b, + 0x52, 0x46, 0x00, 0x74, 0x47, 0xbb, 0xf5, 0x90, 0x7e, 0x5c, 0xdb, 0x14, 0x7b, 0xee, 0x09, 0xfa, 0xbc, 0x6f, 0x60, + 0xdc, 0x11, 0xd8, 0xd1, 0x40, 0x12, 0xda, 0x47, 0x95, 0xfa, 0x33, 0x8f, 0xc5, 0x98, 0xd9, 0xa7, 0xdb, 0x66, 0x82, + 0xca, 0x9d, 0xec, 0x52, 0x09, 0xd2, 0xe0, 0x0d, 0xf2, 0x70, 0xd8, 0xd7, 0xfd, 0x5e, 0x6a, 0xda, 0xe6, 0xc9, 0xed, + 0x2b, 0xab, 0xd5, 0x94, 0xef, 0x76, 0x99, 0x40, 0x7c, 0x71, 0x0e, 0x65, 0xbc, 0xe7, 0x81, 0xaa, 0xef, 0x1b, 0x59, + 0x43, 0xc0, 0x7d, 0xb3, 0x30, 0xcc, 0x09, 0x3a, 0xc2, 0x20, 0x69, 0xe6, 0xc1, 0x9f, 0x00, 0x6d, 0xde, 0xcb, 0xeb, + 0x55, 0x88, 0x73, 0x40, 0x77, 0xf8, 0xf2, 0x84, 0xb5, 0x8e, 0xd8, 0xe3, 0x83, 0x79, 0xc6, 0x28, 0x37, 0xbc, 0x44, + 0xc7, 0x88, 0xdb, 0xde, 0x95, 0x17, 0x32, 0x5d, 0x3e, 0xfb, 0x96, 0x04, 0xbe, 0x31, 0x52, 0x81, 0x14, 0x68, 0xc4, + 0xb1, 0x0f, 0x36, 0xdf, 0x87, 0x43, 0xb3, 0x5f, 0xe8, 0x8d, 0xc2, 0xf4, 0x72, 0xfc, 0xe5, 0xc6, 0xfc, 0x16, 0x8e, + 0xb8, 0xda, 0x2a, 0xc4, 0xc3, 0x5e, 0x8e, 0xb9, 0xd0, 0x9a, 0x07, 0xbf, 0x30, 0x27, 0xcb, 0x42, 0xe2, 0xdd, 0x45, + 0x7d, 0xc3, 0x7a, 0xcd, 0x96, 0x3d, 0x93, 0x59, 0x13, 0x0f, 0x92, 0xf5, 0xb4, 0xf2, 0x70, 0x7a, 0x2a, 0xcf, 0xb1, + 0xd9, 0x0b, 0x0b, 0xb2, 0xa1, 0xab, 0xa7, 0xb6, 0x5c, 0xf7, 0xd6, 0x34, 0x24, 0x2f, 0xf1, 0x8b, 0xab, 0x68, 0x01, + 0x4a, 0x4c, 0xd4, 0xce, 0xac, 0x5d, 0x90, 0x0a, 0xf6, 0x7a, 0x59, 0x40, 0x83, 0x63, 0xe5, 0xd8, 0x96, 0xd0, 0x53, + 0x91, 0x19, 0x9f, 0x55, 0x29, 0x20, 0x7d, 0x4d, 0xd4, 0xed, 0x45, 0x54, 0x5a, 0x42, 0x82, 0xc0, 0xc7, 0x4f, 0x92, + 0x52, 0xec, 0xcb, 0x0d, 0x20, 0x30, 0x54, 0xbc, 0xef, 0x02, 0xbe, 0xbf, 0xa9, 0x48, 0x64, 0x72, 0xb0, 0x92, 0xf7, + 0x44, 0x97, 0x14, 0xf8, 0x9f, 0x9f, 0xef, 0xac, 0x54, 0x2a, 0x72, 0x39, 0x86, 0x11, 0xc5, 0x5e, 0x33, 0x45, 0x61, + 0x6e, 0x1a, 0xa1, 0x20, 0x50, 0xcb, 0x3f, 0x5c, 0x7f, 0xa1, 0xbf, 0xa4, 0x04, 0xa7, 0x96, 0x40, 0x5c, 0x5e, 0x9d, + 0x87, 0x04, 0x67, 0xf5, 0x16, 0x79, 0xac, 0x20, 0xd8, 0x63, 0xae, 0x35, 0x3b, 0xcc, 0x81, 0x64, 0x57, 0x0b, 0x8c, + 0xb6, 0x44, 0x29, 0xf5, 0x02, 0x62, 0x97, 0x4c, 0xf7, 0x75, 0x45, 0x91, 0xee, 0x51, 0xf4, 0x98, 0xca, 0x68, 0x39, + 0x3e, 0xd1, 0xd8, 0xdf, 0x18, 0xaa, 0x96, 0xfa, 0x2a, 0x7b, 0xc2, 0xd7, 0xbb, 0xc3, 0x17, 0x1b, 0x3f, 0x12, 0xfe, + 0x3e, 0x57, 0x4c, 0x3f, 0x67, 0xf7, 0xa3, 0x5d, 0xc2, 0x68, 0xa0, 0x7a, 0xae, 0x39, 0x6e, 0x2c, 0x37, 0x5e, 0x6e, + 0x5f, 0x74, 0xc5, 0x56, 0x99, 0x9f, 0xbb, 0x05, 0xb9, 0x26, 0xdd, 0x6b, 0x32, 0xcf, 0x49, 0x6e, 0xf0, 0xce, 0xf4, + 0x20, 0x9d, 0x08, 0xae, 0xfd, 0xcb, 0xf3, 0xaf, 0x3b, 0x5c, 0x85, 0x6d, 0x5b, 0x91, 0x57, 0x66, 0x40, 0x39, 0xb4, + 0xdb, 0x04, 0xd4, 0x97, 0x6e, 0xd2, 0x1d, 0xd1, 0x36, 0xb6, 0xf0, 0x12, 0xe2, 0x35, 0x50, 0xdc, 0xd2, 0xc4, 0x57, + 0x67, 0xa3, 0x90, 0xa6, 0x64, 0xb2, 0x07, 0x84, 0x62, 0xc2, 0x02, 0xfd, 0xd3, 0x71, 0xd2, 0xac, 0x0a, 0x5a, 0xef, + 0x95, 0xaa, 0x8e, 0x95, 0xd3, 0xd5, 0x57, 0x61, 0x66, 0xa3, 0x19, 0xf1, 0x20, 0x27, 0x1b, 0x87, 0x28, 0x77, 0x9d, + 0xe9, 0xe8, 0x50, 0x3c, 0xa6, 0xdc, 0x49, 0x9d, 0x5c, 0x9c, 0xb3, 0x23, 0x09, 0xc5, 0x7f, 0xeb, 0x9c, 0x08, 0x85, + 0x6f, 0x61, 0x2b, 0x02, 0xf9, 0xda, 0xb4, 0xfc, 0xaf, 0x1d, 0xf5, 0x39, 0xe1, 0x8e, 0x76, 0xe5, 0x6a, 0xc6, 0x29, + 0xb2, 0xe1, 0x40, 0xe6, 0xe3, 0x46, 0x05, 0xaf, 0x3c, 0x55, 0x65, 0xbf, 0x8d, 0x98, 0xf4, 0x89, 0x3d, 0x9b, 0x1c, + 0x26, 0xa5, 0xa3, 0xf6, 0x13, 0x5c, 0x16, 0x1d, 0x4c, 0xc3, 0xa2, 0x0d, 0x11, 0x20, 0x6a, 0xb5, 0xd1, 0x0e, 0x8b, + 0x88, 0x04, 0x8d, 0x2f, 0x56, 0x2f, 0xe3, 0x81, 0x8f, 0xe6, 0x18, 0xc5, 0x3e, 0x6d, 0x6b, 0x49, 0xf6, 0xbd, 0x31, + 0x46, 0xca, 0x40, 0x7d, 0xa2, 0x73, 0xa0, 0x4c, 0x2c, 0xf2, 0x31, 0xc9, 0x4b, 0x2d, 0x56, 0xb8, 0x4b, 0x5e, 0x47, + 0x25, 0x60, 0x45, 0xf2, 0x57, 0x70, 0x19, 0x25, 0x08, 0x46, 0x8f, 0xa2, 0x2f, 0xfd, 0x12, 0xdc, 0x72, 0xdf, 0x1f, + 0x32, 0x05, 0x76, 0x8a, 0xb1, 0x8f, 0x18, 0xbd, 0x94, 0x22, 0xf3, 0x21, 0x12, 0x8f, 0xdf, 0xb3, 0x04, 0x29, 0x28, + 0x7d, 0x69, 0x1b, 0x60, 0x70, 0x13, 0xe8, 0xb2, 0x6e, 0x6a, 0x9c, 0x01, 0x72, 0x22, 0x57, 0xd4, 0x76, 0xdc, 0xf3, + 0xc9, 0x0e, 0x05, 0x6d, 0x0d, 0x32, 0x66, 0x7a, 0xa1, 0x59, 0xa2, 0xc0, 0xf0, 0xfd, 0x56, 0xe3, 0x28, 0x18, 0xb0, + 0x6b, 0xac, 0x47, 0xbf, 0x52, 0xd2, 0x21, 0x53, 0xfa, 0x91, 0x16, 0xce, 0xe5, 0x4c, 0xa6, 0x7a, 0xf3, 0x7b, 0x21, + 0x05, 0x10, 0x17, 0x6f, 0x25, 0xa2, 0xb7, 0x64, 0x7f, 0x1d, 0x14, 0xa0, 0x60, 0x1a, 0x19, 0x23, 0xfd, 0x5f, 0x2c, + 0x0b, 0x72, 0x3b, 0x0a, 0x6b, 0x86, 0x04, 0x06, 0x15, 0x1f, 0x77, 0x68, 0x8e, 0xbf, 0x0e, 0xff, 0x6b, 0x03, 0x50, + 0x57, 0xee, 0xbc, 0xa1, 0xac, 0xf9, 0x01, 0x29, 0x45, 0x66, 0x2f, 0xdf, 0xbd, 0x6a, 0x85, 0x3a, 0x68, 0xb1, 0xcd, + 0x75, 0x9e, 0xd7, 0x16, 0xbf, 0x9e, 0x42, 0xb7, 0x37, 0xf9, 0xcd, 0x6c, 0x57, 0x5d, 0x3d, 0x36, 0x6a, 0xd4, 0x1b, + 0x04, 0xa3, 0xb7, 0x37, 0xc3, 0x6e, 0x9d, 0x0f, 0x67, 0x25, 0xa0, 0x95, 0xcd, 0x5e, 0xfd, 0x9b, 0x08, 0x0a, 0x7d, + 0xad, 0x9f, 0x47, 0xba, 0xca, 0xb8, 0x7c, 0x96, 0x80, 0x97, 0xc6, 0x87, 0x46, 0x95, 0x6a, 0x59, 0x58, 0xb2, 0x26, + 0x11, 0x08, 0x0e, 0x7f, 0xd0, 0xac, 0x67, 0xda, 0x8f, 0xea, 0x36, 0xdf, 0xd4, 0x75, 0x15, 0x41, 0xfb, 0x11, 0xd6, + 0x74, 0xa5, 0xff, 0x37, 0x71, 0x78, 0x38, 0x45, 0xff, 0xa3, 0xf9, 0x83, 0x82, 0xed, 0xdd, 0x66, 0x53, 0x42, 0x85, + 0x6b, 0xe6, 0x5e, 0x3d, 0xc5, 0x33, 0x45, 0x62, 0x17, 0xa5, 0x67, 0x55, 0xdb, 0xc1, 0xb2, 0xa1, 0xb6, 0xd7, 0x90, + 0xb0, 0x45, 0x90, 0x6a, 0x0a, 0xc6, 0xcd, 0xd3, 0x3b, 0xdc, 0x1d, 0x71, 0xcc, 0xa0, 0x1c, 0x1a, 0x45, 0x99, 0xdf, + 0x0e, 0x93, 0xe6, 0x54, 0x6d, 0x6f, 0x51, 0xe0, 0x47, 0x00, 0x9f, 0x2b, 0x6a, 0x07, 0xf2, 0xf4, 0x61, 0x94, 0xaf, + 0x27, 0xb9, 0xef, 0xc4, 0x11, 0x09, 0xd6, 0x0e, 0x6c, 0x79, 0xc9, 0xab, 0xd3, 0x95, 0xd5, 0x3d, 0x89, 0xaf, 0x3b, + 0xc6, 0xf9, 0x21, 0x71, 0xed, 0x47, 0x4f, 0x53, 0x0e, 0xdb, 0xa2, 0x9e, 0xe0, 0xb0, 0x38, 0xb4, 0xdd, 0x10, 0xdd, + 0x76, 0x96, 0x46, 0xef, 0x00, 0x6d, 0xb1, 0xc9, 0x8b, 0x27, 0x9d, 0x63, 0x5c, 0x1f, 0x2e, 0x27, 0x69, 0xd9, 0x3f, + 0x95, 0x1a, 0xa2, 0xbe, 0xa5, 0x74, 0x8f, 0xd4, 0x1d, 0x1d, 0x6c, 0xcd, 0xde, 0x3f, 0x16, 0xcd, 0x43, 0xe4, 0xb5, + 0x1c, 0x36, 0x6d, 0x52, 0xce, 0x87, 0x2f, 0x1b, 0x7d, 0x59, 0x5e, 0x6d, 0x4a, 0xb6, 0x41, 0xea, 0x4c, 0xb4, 0x79, + 0x0c, 0xa8, 0x6f, 0x0d, 0xbd, 0x0a, 0xbe, 0x60, 0xcd, 0x16, 0xfa, 0xe6, 0xbc, 0x5b, 0x60, 0x2c, 0xc1, 0x67, 0x0c, + 0x6d, 0x73, 0xee, 0xbe, 0x93, 0xee, 0xb3, 0x1c, 0xa6, 0x5c, 0x54, 0x4e, 0x51, 0x22, 0x89, 0xba, 0xff, 0x2f, 0xaf, + 0xf7, 0x52, 0x46, 0x7a, 0x79, 0x42, 0x87, 0x9d, 0xc2, 0xc3, 0x25, 0xab, 0x80, 0x62, 0xac, 0xad, 0xf4, 0xbc, 0x72, + 0x0a, 0x52, 0xa3, 0xa3, 0xb8, 0xd0, 0x7f, 0xf8, 0xca, 0x5d, 0xef, 0x36, 0xd6, 0xf4, 0x63, 0xca, 0x92, 0xbf, 0xf6, + 0x8d, 0x04, 0x6d, 0x5d, 0x11, 0x99, 0xfc, 0x9f, 0x48, 0x4c, 0x8e, 0x2c, 0xc4, 0xa3, 0x03, 0x68, 0x60, 0xa7, 0x4e, + 0xb6, 0xa0, 0xc5, 0x24, 0x09, 0x88, 0x2e, 0xd1, 0x1c, 0x4e, 0x00, 0x6d, 0xd2, 0x12, 0x4c, 0xc8, 0x6f, 0xf4, 0xbe, + 0xcb, 0x98, 0x27, 0xfc, 0x65, 0x1e, 0x4e, 0xa0, 0xfb, 0xe0, 0xd0, 0xa2, 0x09, 0x58, 0x45, 0x92, 0x86, 0xb5, 0xb6, + 0x9d, 0x0f, 0x27, 0xdb, 0x09, 0x49, 0xaa, 0xf7, 0xfb, 0xdc, 0x90, 0x42, 0xc8, 0xed, 0x28, 0x45, 0x4d, 0xe7, 0x7c, + 0xd5, 0xea, 0xcd, 0x21, 0xd6, 0xc5, 0x0c, 0x75, 0xcf, 0x40, 0x49, 0xdb, 0xce, 0x16, 0xe8, 0xf6, 0x09, 0xff, 0xf8, + 0xcb, 0x40, 0x13, 0x14, 0xcd, 0x1a, 0xb0, 0xa4, 0x00, 0xdc, 0xc6, 0x9c, 0xef, 0x35, 0x4f, 0xa9, 0xa2, 0xba, 0x83, + 0x30, 0x77, 0xd8, 0x90, 0x62, 0x54, 0xf7, 0xe1, 0x84, 0x05, 0x41, 0xbc, 0xf6, 0x44, 0x0e, 0x22, 0x3d, 0xa8, 0x4f, + 0x3a, 0x10, 0x32, 0xeb, 0x81, 0xb3, 0x86, 0x55, 0xd2, 0xad, 0xae, 0x59, 0xd7, 0x19, 0x7f, 0xf2, 0x43, 0xd6, 0xd9, + 0x40, 0xff, 0x64, 0xa3, 0xa4, 0x73, 0x5d, 0x44, 0x04, 0x4f, 0xe2, 0x65, 0x0e, 0x94, 0xe7, 0x3d, 0x4d, 0x39, 0xb5, + 0xfc, 0xf8, 0xef, 0x5b, 0x32, 0x87, 0xfa, 0x92, 0x35, 0xf9, 0x7b, 0xa7, 0x3f, 0x59, 0x44, 0x5e, 0x31, 0x35, 0x5f, + 0x2d, 0x26, 0x2b, 0x2f, 0x32, 0xce, 0x29, 0x91, 0x0a, 0x4e, 0xad, 0xe8, 0x7c, 0x22, 0x97, 0xd8, 0xc6, 0x1f, 0x04, + 0x32, 0x67, 0x8f, 0xec, 0x3d, 0x3b, 0xa8, 0x18, 0x2d, 0xa1, 0x20, 0x66, 0x51, 0x35, 0xf0, 0xed, 0xc1, 0x9b, 0x31, + 0xb3, 0xe7, 0xa4, 0x40, 0x8b, 0x51, 0x60, 0xcb, 0x85, 0x18, 0x0d, 0xf1, 0xaa, 0x64, 0xae, 0x24, 0xe1, 0xcf, 0x96, + 0x99, 0x12, 0x3f, 0x64, 0xa5, 0x0e, 0xee, 0xbc, 0x58, 0xb9, 0x64, 0xb9, 0x7c, 0x7e, 0xfd, 0x08, 0xec, 0x7a, 0xef, + 0x11, 0x31, 0xe3, 0xf5, 0x93, 0x05, 0xbb, 0x56, 0x80, 0x12, 0x19, 0xdd, 0x30, 0xee, 0x22, 0xa1, 0x46, 0xd9, 0x61, + 0x74, 0x05, 0x2a, 0x8e, 0x75, 0x2a, 0x0a, 0x00, 0xfe, 0x78, 0x3d, 0x54, 0x2e, 0x70, 0x7f, 0x3c, 0x11, 0x80, 0x32, + 0xca, 0xf4, 0x9d, 0xc9, 0x18, 0x10, 0x1d, 0x35, 0x13, 0xf8, 0x37, 0x61, 0xac, 0x9e, 0xfb, 0xec, 0xf8, 0x28, 0xee, + 0x65, 0x23, 0x0c, 0x34, 0x96, 0x65, 0x93, 0xcd, 0xba, 0x75, 0x5b, 0xe1, 0x4f, 0xc5, 0x0a, 0xa4, 0x29, 0x40, 0xf3, + 0x31, 0x6d, 0x04, 0x9c, 0x81, 0x31, 0xfb, 0x32, 0x81, 0x9a, 0x2a, 0x18, 0x47, 0x5f, 0x5b, 0x36, 0x3c, 0x1f, 0xd5, + 0xdd, 0x0f, 0x2e, 0x73, 0x81, 0x50, 0x16, 0x0b, 0x6c, 0x7b, 0xa1, 0x4e, 0xfc, 0x56, 0x90, 0x79, 0x7c, 0x5f, 0x0d, + 0x8b, 0x36, 0x1d, 0x2d, 0x2b, 0x2b, 0xac, 0x0f, 0x7a, 0xb4, 0x47, 0xb0, 0x1a, 0x29, 0x5a, 0xcf, 0x71, 0xb7, 0x02, + 0x1b, 0xd1, 0xe3, 0xd4, 0x60, 0xf5, 0x83, 0x49, 0x81, 0xe4, 0x60, 0xc8, 0xb6, 0x23, 0x96, 0x1a, 0x18, 0x82, 0x9a, + 0x97, 0xa7, 0x00, 0x6b, 0xa4, 0x76, 0xd3, 0xd2, 0x68, 0xf2, 0xaf, 0xda, 0xa2, 0xdf, 0xfa, 0x37, 0xb3, 0xde, 0x35, + 0x42, 0x24, 0xdb, 0xc3, 0xf9, 0xec, 0x0c, 0x2d, 0x98, 0x41, 0xa3, 0x22, 0xb4, 0x87, 0x50, 0x6a, 0x4e, 0x23, 0x31, + 0xa8, 0x85, 0x10, 0xd9, 0x9f, 0xb8, 0xb7, 0x9c, 0xf0, 0x3c, 0xe0, 0x1e, 0x9e, 0x95, 0x34, 0xe9, 0x34, 0x5f, 0x2a, + 0x23, 0xb8, 0x2b, 0x70, 0x8a, 0x12, 0xcc, 0x16, 0xf4, 0x4f, 0x7e, 0x7b, 0x57, 0x8a, 0x18, 0xae, 0x0b, 0x08, 0xa5, + 0xcf, 0x9e, 0x11, 0x45, 0xbb, 0xc8, 0x88, 0x56, 0x25, 0x4b, 0x70, 0x81, 0xec, 0x23, 0xdb, 0xcf, 0x46, 0x16, 0xcc, + 0x1a, 0xf6, 0x53, 0xdd, 0x88, 0xf6, 0x21, 0x30, 0x23, 0x36, 0xc7, 0x5e, 0x4f, 0x9e, 0x40, 0x43, 0xf4, 0xb0, 0x64, + 0x5a, 0x17, 0xb4, 0x74, 0x95, 0x62, 0xa5, 0x42, 0x37, 0xf1, 0xa8, 0x1f, 0xa9, 0x51, 0xab, 0xe5, 0xed, 0x10, 0x7d, + 0x04, 0x6b, 0x5e, 0xef, 0x9f, 0xe2, 0x5d, 0x43, 0x81, 0x98, 0x85, 0x3b, 0x56, 0xd6, 0x58, 0xd9, 0x63, 0x61, 0xe2, + 0xf0, 0x8d, 0x10, 0x0b, 0x4f, 0x85, 0xde, 0x4f, 0xf3, 0xbf, 0x36, 0x78, 0xf5, 0xb5, 0x50, 0xd6, 0x04, 0xe5, 0x87, + 0xc1, 0xc2, 0x99, 0x0b, 0x7c, 0x8c, 0xb1, 0xd3, 0xe1, 0x37, 0x8a, 0x68, 0x83, 0x44, 0x4b, 0x8a, 0x61, 0x0b, 0xb7, + 0x57, 0x12, 0x57, 0x49, 0x15, 0x1c, 0x45, 0x18, 0x5f, 0x70, 0xeb, 0xf1, 0x4b, 0xd6, 0x18, 0x13, 0x8e, 0xce, 0x39, + 0x28, 0x5b, 0x11, 0x12, 0xcc, 0x02, 0x9b, 0xf4, 0x70, 0x83, 0x65, 0x5a, 0x21, 0x25, 0x08, 0x31, 0xc9, 0x74, 0x3f, + 0x86, 0xa1, 0x12, 0x5b, 0x05, 0x41, 0x46, 0x65, 0x76, 0xe8, 0xc4, 0x19, 0x6d, 0x71, 0x98, 0x62, 0x8d, 0xf0, 0xa9, + 0xa6, 0x17, 0x21, 0x4a, 0x22, 0xef, 0x99, 0x5d, 0x63, 0x98, 0x40, 0x2b, 0x32, 0x55, 0x32, 0xfa, 0x2a, 0x06, 0xdc, + 0xfa, 0x6b, 0xed, 0x43, 0xc1, 0x3a, 0xb8, 0x86, 0x5e, 0xaa, 0xe2, 0xaf, 0x4e, 0xa1, 0x55, 0xea, 0x92, 0x54, 0x49, + 0x4f, 0xa6, 0x90, 0xe6, 0xbc, 0x82, 0x1e, 0xce, 0x79, 0x88, 0xb7, 0x02, 0xde, 0x2a, 0xf8, 0x04, 0x5a, 0xd2, 0x08, + 0xf7, 0x2d, 0xbb, 0xda, 0x3e, 0x2b, 0x91, 0xed, 0xe7, 0xe6, 0x64, 0xc4, 0xb9, 0x0e, 0x34, 0x7a, 0x0e, 0x0b, 0x2f, + 0x83, 0x16, 0x7d, 0xa7, 0x06, 0xee, 0x4a, 0x44, 0xdf, 0xfa, 0x43, 0x0b, 0x8a, 0x35, 0xab, 0x54, 0xc0, 0x9e, 0xa9, + 0xf7, 0x23, 0x21, 0xf1, 0x58, 0xfe, 0xb1, 0xa7, 0xc7, 0x24, 0x51, 0xb5, 0x3c, 0x81, 0x91, 0x08, 0x51, 0x93, 0x41, + 0xd6, 0xfa, 0x04, 0x83, 0xae, 0x59, 0xae, 0x52, 0x73, 0x85, 0x30, 0x87, 0x32, 0xdd, 0xd5, 0xda, 0x2e, 0x00, 0x4e, + 0x5f, 0xad, 0xe7, 0x2b, 0xd0, 0x69, 0x61, 0x06, 0x28, 0x71, 0xa6, 0x47, 0x75, 0xc6, 0xc1, 0xa9, 0x6e, 0x11, 0xff, + 0xeb, 0x95, 0x4a, 0x58, 0x7b, 0xf0, 0x70, 0x50, 0xf1, 0xa4, 0x82, 0xfc, 0x6c, 0xa0, 0x29, 0x0d, 0x03, 0x52, 0x70, + 0x4e, 0x62, 0x57, 0x2c, 0xa7, 0x8b, 0x47, 0x5e, 0x19, 0x23, 0x9c, 0xc0, 0xba, 0xd3, 0xa7, 0xd3, 0x41, 0x31, 0x2e, + 0xd1, 0x52, 0x17, 0x35, 0xe7, 0xd6, 0x49, 0x5a, 0xee, 0x40, 0xf1, 0x57, 0x96, 0xa8, 0x6b, 0x91, 0x4e, 0x96, 0x2d, + 0xae, 0xea, 0xab, 0x31, 0xed, 0x82, 0x08, 0x2b, 0x6a, 0xe4, 0xd6, 0x42, 0x9d, 0xed, 0x77, 0x5e, 0xde, 0x50, 0x8c, + 0xe3, 0x39, 0xbf, 0xd6, 0xca, 0xc3, 0xb3, 0x96, 0x52, 0x2f, 0xde, 0x32, 0x47, 0xd3, 0x89, 0x35, 0x5f, 0x6a, 0x84, + 0x67, 0xe2, 0x2e, 0x22, 0xc3, 0x68, 0x80, 0xe9, 0xdb, 0xaa, 0x45, 0x2c, 0xa4, 0x1d, 0x40, 0x3f, 0x17, 0xd4, 0x39, + 0x00, 0x0c, 0x45, 0x28, 0x3b, 0x00, 0xae, 0x42, 0xb5, 0x5e, 0xcf, 0x2b, 0x6d, 0x6c, 0xf6, 0x27, 0x72, 0x42, 0x10, + 0x56, 0xbc, 0xa4, 0x50, 0x0a, 0x99, 0x40, 0x5e, 0xe2, 0x52, 0x95, 0xdc, 0x4e, 0xcb, 0x66, 0xd3, 0xb9, 0xc3, 0x37, + 0xd2, 0x00, 0x44, 0x4d, 0x5a, 0x66, 0xb2, 0x81, 0x0d, 0x55, 0xca, 0x94, 0xa7, 0x49, 0xad, 0x06, 0x5c, 0xf3, 0xc1, + 0x35, 0x70, 0x24, 0xe0, 0xec, 0xc0, 0xb5, 0x20, 0x0e, 0xbb, 0x66, 0xc8, 0x35, 0x75, 0x4e, 0x79, 0x8c, 0xfe, 0x6b, + 0xab, 0x35, 0xb6, 0x5f, 0x7d, 0x2d, 0x4d, 0xde, 0x4f, 0xc7, 0x48, 0x2b, 0x03, 0x52, 0x3b, 0xf9, 0xbf, 0x36, 0xa4, + 0x9c, 0xfd, 0x58, 0x88, 0xb5, 0xff, 0x9b, 0x91, 0x39, 0x9f, 0x57, 0xcf, 0x0e, 0x13, 0x37, 0x18, 0x53, 0x21, 0x8e, + 0x71, 0x12, 0x5e, 0x6c, 0x87, 0x57, 0x8d, 0x41, 0xed, 0xd7, 0x0b, 0x18, 0x72, 0xdc, 0xb1, 0xf7, 0x1e, 0x18, 0xce, + 0xbe, 0xd8, 0x5b, 0x34, 0x56, 0x87, 0xb4, 0x28, 0x96, 0x7d, 0x00, 0xe9, 0x67, 0xf9, 0xfe, 0x7f, 0xdc, 0xdc, 0xa5, + 0x41, 0x2d, 0x23, 0x2f, 0x71, 0xc9, 0x42, 0xb3, 0xfc, 0x5e, 0x52, 0xac, 0x4f, 0x1b, 0xe1, 0x12, 0xcd, 0x95, 0xd5, + 0xff, 0x82, 0x65, 0xcb, 0xea, 0x2e, 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8d, 0x6f, 0x6e, 0x7c, 0x4c, 0x9d, 0x35, 0x95, + 0x6e, 0xc6, 0xbb, 0x38, 0xc4, 0xae, 0xb7, 0x8d, 0x2a, 0xb6, 0x8b, 0x8c, 0xa9, 0x68, 0x6a, 0xf5, 0xd1, 0x0c, 0x22, + 0x37, 0xb4, 0xa0, 0xfd, 0x5b, 0x4c, 0x3a, 0x58, 0x3c, 0x28, 0xc3, 0xa5, 0xd1, 0xf2, 0xba, 0x10, 0x3b, 0x0a, 0x2e, + 0xc9, 0x48, 0x4a, 0x12, 0x64, 0x48, 0xf7, 0x1d, 0x17, 0x0f, 0x9a, 0x42, 0xd5, 0x88, 0xdb, 0x95, 0x64, 0xbf, 0xe2, + 0xfe, 0xa5, 0x7e, 0xdc, 0x30, 0xea, 0xca, 0x39, 0x50, 0x89, 0xcf, 0x9a, 0x6c, 0x4e, 0x88, 0x8e, 0xda, 0x36, 0xeb, + 0x28, 0xca, 0x91, 0x5f, 0x29, 0x25, 0xea, 0x5f, 0xd1, 0x1b, 0x48, 0xb6, 0x08, 0x60, 0x60, 0x1b, 0x80, 0xd5, 0x6f, + 0xd6, 0x2c, 0xd5, 0x32, 0x40, 0xe3, 0x57, 0xb0, 0x6b, 0x3e, 0x3e, 0x75, 0x37, 0xfa, 0x05, 0xd1, 0xd8, 0x5a, 0xd1, + 0x04, 0x97, 0xdd, 0x0b, 0xab, 0x37, 0xe2, 0xf7, 0xd4, 0xdb, 0x23, 0x88, 0x0d, 0xe4, 0xd3, 0x74, 0xbf, 0x4b, 0x4d, + 0x1f, 0x90, 0xf4, 0x3d, 0x18, 0x63, 0x1f, 0x83, 0x5d, 0x51, 0x4f, 0xad, 0xde, 0x54, 0x95, 0x43, 0x20, 0xf7, 0x74, + 0x35, 0x2a, 0xe6, 0xf1, 0x57, 0xb4, 0x5b, 0x6b, 0xd9, 0x61, 0x78, 0x95, 0x2f, 0xa0, 0x6c, 0xd1, 0xae, 0x29, 0x22, + 0xc9, 0x65, 0x8c, 0x4b, 0x15, 0x80, 0x12, 0x58, 0x90, 0x93, 0x1a, 0xbb, 0x3a, 0xdd, 0xb2, 0x79, 0xf9, 0x3a, 0x9a, + 0x90, 0x6f, 0xfd, 0xb4, 0xf2, 0xb9, 0x19, 0x1c, 0x55, 0xd4, 0x21, 0x02, 0xd3, 0x40, 0x1d, 0x16, 0x70, 0x18, 0xa9, + 0xf3, 0x52, 0x04, 0x0e, 0x78, 0x37, 0xe8, 0x73, 0xcd, 0x40, 0x51, 0x70, 0x88, 0xbc, 0x8b, 0x1a, 0x2c, 0xf0, 0x1c, + 0x3c, 0x49, 0xb4, 0x71, 0x74, 0xf8, 0xef, 0x82, 0x8e, 0xa2, 0x43, 0xb2, 0x94, 0xf5, 0xbd, 0x32, 0x15, 0xc9, 0x49, + 0xea, 0x22, 0xe9, 0xfc, 0x54, 0x9e, 0xa9, 0x4d, 0x6e, 0xcd, 0x5f, 0x24, 0x9f, 0xc6, 0xc9, 0xd8, 0x0b, 0xd8, 0xaf, + 0x61, 0xc4, 0xae, 0xf3, 0x17, 0x36, 0x9f, 0xf6, 0xcc, 0xb2, 0x46, 0xab, 0x33, 0xe0, 0x81, 0xa4, 0x13, 0x61, 0x29, + 0xbb, 0x64, 0x2e, 0x65, 0x00, 0x28, 0xd7, 0xc6, 0xcb, 0xbb, 0x21, 0xc4, 0xe7, 0xe2, 0xfa, 0x8e, 0x48, 0xa8, 0x4c, + 0x35, 0x33, 0xe3, 0xb9, 0x47, 0x11, 0x21, 0x2c, 0xd5, 0xce, 0x2c, 0x6e, 0xb3, 0xed, 0xed, 0x6c, 0x78, 0x5e, 0xb3, + 0xfd, 0xb1, 0xc0, 0x14, 0xf5, 0xa0, 0xbf, 0x8b, 0x8b, 0xa4, 0xca, 0x20, 0x44, 0xcc, 0xe0, 0x03, 0xae, 0x86, 0xb0, + 0x4b, 0xa5, 0xa2, 0x3f, 0xdb, 0x25, 0x8a, 0x9f, 0x5e, 0xa5, 0xaa, 0xc2, 0xe5, 0x48, 0xc8, 0xc4, 0x96, 0xda, 0x80, + 0x25, 0x02, 0x3c, 0xf2, 0xe4, 0x16, 0xb7, 0x65, 0xb9, 0x1b, 0x11, 0x9c, 0x16, 0x2d, 0x9d, 0x9c, 0xb0, 0x4c, 0xe8, + 0x3b, 0xd9, 0xf5, 0xae, 0x29, 0xc2, 0xec, 0x7e, 0x93, 0x6e, 0x7f, 0x94, 0xd2, 0x57, 0x95, 0xc6, 0x1d, 0xb8, 0xc6, + 0x12, 0xb8, 0xf0, 0x18, 0xd1, 0x6a, 0x68, 0x54, 0x9f, 0x7a, 0x44, 0xf1, 0xa8, 0xd6, 0x24, 0xc7, 0x41, 0xeb, 0x30, + 0x71, 0xa5, 0xa5, 0x81, 0xe2, 0x42, 0xec, 0xac, 0x43, 0x76, 0x3a, 0x0b, 0xf9, 0x92, 0x73, 0xb3, 0x75, 0x92, 0xc8, + 0x17, 0xb5, 0x0f, 0x45, 0x33, 0x12, 0x73, 0xf5, 0x5d, 0x7e, 0xce, 0xd1, 0x8f, 0x77, 0x57, 0xf9, 0x8a, 0xb7, 0x8e, + 0x73, 0x92, 0xcc, 0x27, 0xf1, 0xa2, 0xe5, 0x9f, 0xcb, 0xd2, 0x46, 0x0b, 0x4f, 0xe2, 0xd1, 0x0f, 0xa7, 0x8a, 0xfa, + 0x35, 0x12, 0x9a, 0x75, 0x52, 0xeb, 0x59, 0x79, 0x25, 0xe5, 0x7c, 0xb7, 0x47, 0x8a, 0x25, 0x62, 0x8e, 0x71, 0xb9, + 0xe4, 0x69, 0x55, 0x2d, 0x1d, 0x7d, 0x7f, 0x86, 0xe7, 0x52, 0x76, 0x02, 0x60, 0x22, 0xa9, 0x8f, 0xb0, 0xa2, 0xbd, + 0x8c, 0x1a, 0x21, 0xf6, 0x82, 0xd1, 0xb2, 0x84, 0x17, 0xfb, 0xcd, 0xad, 0x07, 0x21, 0x5b, 0x92, 0xee, 0xee, 0x2d, + 0x08, 0x5f, 0xf0, 0xd3, 0x03, 0xa7, 0x75, 0xa4, 0x26, 0x2f, 0xce, 0x42, 0x94, 0x78, 0x89, 0x74, 0x18, 0xb5, 0xb5, + 0x9c, 0x9b, 0xb0, 0x92, 0x34, 0x86, 0xdc, 0x1a, 0x65, 0xd5, 0xb0, 0xa5, 0x18, 0x73, 0x20, 0xe3, 0x91, 0x79, 0x06, + 0xfa, 0x1e, 0xe0, 0x4d, 0x6e, 0x6d, 0x49, 0xb2, 0xee, 0x9e, 0xca, 0xc8, 0xbc, 0xe8, 0xb3, 0xe4, 0xfc, 0xb8, 0x95, + 0xd8, 0x50, 0xdc, 0x49, 0xb9, 0x62, 0x3d, 0x71, 0x90, 0x5d, 0x9a, 0xbc, 0x2f, 0x51, 0x44, 0xc9, 0x4a, 0xa7, 0xff, + 0x39, 0x37, 0x1c, 0x77, 0x3a, 0x34, 0xd1, 0xea, 0xd8, 0x76, 0x68, 0x25, 0xe6, 0xe1, 0xd7, 0xe5, 0x9a, 0xaa, 0x05, + 0xb4, 0x80, 0x39, 0x22, 0x4a, 0xdd, 0x0c, 0x71, 0x93, 0xa4, 0xe3, 0x05, 0xc2, 0xdf, 0x6e, 0x33, 0x13, 0x5f, 0x76, + 0x7f, 0x97, 0x23, 0x34, 0x35, 0x94, 0xe4, 0x01, 0x14, 0x97, 0x6f, 0xc2, 0x9b, 0x31, 0x15, 0xf1, 0x0d, 0xfb, 0xcc, + 0x59, 0x6a, 0x0f, 0x5e, 0xa0, 0x4d, 0x4f, 0x82, 0xd5, 0x89, 0x1b, 0x40, 0x89, 0x4c, 0x10, 0x20, 0xbb, 0xc7, 0x00, + 0x96, 0x06, 0xd9, 0x8b, 0x26, 0xd3, 0x00, 0x22, 0x5b, 0x8c, 0xad, 0x61, 0x8e, 0xcd, 0x15, 0xa0, 0x05, 0x3b, 0xf3, + 0x4b, 0xa0, 0x6c, 0x60, 0x87, 0x77, 0xf4, 0x3f, 0x79, 0x43, 0x0c, 0x31, 0xa6, 0xa9, 0x4d, 0x3b, 0xeb, 0x55, 0x90, + 0xbd, 0xeb, 0x63, 0x16, 0x07, 0xe4, 0xc0, 0x75, 0x43, 0x69, 0xec, 0x8c, 0xd5, 0x35, 0x0d, 0x68, 0xa5, 0xa8, 0xae, + 0x08, 0x84, 0x24, 0x10, 0xf3, 0xf2, 0x50, 0x48, 0x4d, 0x42, 0xb5, 0x74, 0xd3, 0xa9, 0x6d, 0x82, 0xc2, 0xec, 0x78, + 0x6a, 0xf2, 0xd0, 0x4b, 0xe0, 0xed, 0xdb, 0x5b, 0x8b, 0x01, 0x47, 0xe1, 0x4a, 0x96, 0x32, 0xea, 0x57, 0xe6, 0xcd, + 0x7a, 0x58, 0xcb, 0x5f, 0x1c, 0xd0, 0x6e, 0x57, 0x8e, 0x19, 0xd5, 0x4e, 0xf5, 0x42, 0x70, 0x7a, 0x67, 0x80, 0x46, + 0x44, 0x02, 0x6c, 0xe0, 0x47, 0xfd, 0x8e, 0x54, 0x2c, 0x51, 0xd6, 0x56, 0x5e, 0xcd, 0xfa, 0x03, 0x16, 0x22, 0x8d, + 0x2b, 0x6c, 0x9c, 0xb3, 0x68, 0x55, 0x23, 0x99, 0x90, 0xa0, 0x07, 0x32, 0xb2, 0x73, 0x56, 0x93, 0xe0, 0xeb, 0x94, + 0x06, 0x5f, 0x70, 0x7a, 0xfc, 0xb5, 0x0e, 0x50, 0x8e, 0x7f, 0x71, 0xf6, 0xba, 0x57, 0xe1, 0x88, 0xeb, 0x11, 0xf3, + 0x45, 0x9d, 0x97, 0x3f, 0xdc, 0x19, 0x39, 0xfd, 0x7b, 0xcb, 0x0c, 0x40, 0x95, 0xbf, 0x58, 0x26, 0x80, 0x54, 0x1e, + 0xdc, 0x79, 0x23, 0x3a, 0x4b, 0x76, 0x14, 0x8d, 0x59, 0x3b, 0x69, 0x09, 0x3b, 0x98, 0x15, 0x47, 0x10, 0x2a, 0xfe, + 0xc5, 0x08, 0x20, 0x71, 0x14, 0xb4, 0xec, 0x68, 0xd0, 0x8a, 0xf6, 0x40, 0x9d, 0x93, 0x12, 0x61, 0x63, 0x5e, 0x88, + 0x0d, 0xf9, 0xfa, 0xe6, 0x04, 0x07, 0x59, 0x43, 0x12, 0x3c, 0xa8, 0xb7, 0x6f, 0x8a, 0x6c, 0x97, 0x1d, 0xa6, 0xde, + 0xf4, 0xf8, 0x3d, 0x97, 0x80, 0x90, 0x16, 0x0f, 0x91, 0x8f, 0xdd, 0x48, 0xcc, 0x6e, 0x3d, 0xde, 0x76, 0xc4, 0xa2, + 0x6f, 0x27, 0xa2, 0x54, 0xea, 0xb8, 0x36, 0x0f, 0x51, 0x10, 0x56, 0x18, 0x4a, 0x70, 0xf9, 0x55, 0x40, 0x6c, 0xa2, + 0xa0, 0xb1, 0x8f, 0xe5, 0x4c, 0x39, 0x6c, 0xb2, 0x0f, 0xe7, 0x2f, 0x75, 0xad, 0xff, 0x08, 0xb5, 0xce, 0x9e, 0xc0, + 0xaf, 0x18, 0xd8, 0x7b, 0x28, 0x83, 0x75, 0x4a, 0xdc, 0xb5, 0xe0, 0xa1, 0x0c, 0xca, 0x7d, 0x18, 0x48, 0x08, 0xc5, + 0xf5, 0x71, 0xd8, 0x14, 0xbb, 0x96, 0x18, 0x01, 0x3e, 0x4a, 0x66, 0xa5, 0x36, 0x1d, 0xc3, 0x95, 0x30, 0xe0, 0xf2, + 0x52, 0x8f, 0xe7, 0xa3, 0x9b, 0xdd, 0x95, 0x46, 0x1a, 0xfa, 0x6e, 0xe0, 0x78, 0xb9, 0x39, 0x4c, 0x95, 0x45, 0x5b, + 0x37, 0x25, 0x2c, 0x75, 0x81, 0xc8, 0x8c, 0x10, 0x31, 0xb7, 0x6c, 0xd2, 0x90, 0x38, 0xdb, 0xe9, 0x04, 0x7d, 0x6c, + 0x60, 0x38, 0x83, 0xd9, 0x54, 0xb5, 0xb5, 0x7b, 0x53, 0x58, 0xff, 0xcc, 0xb2, 0x0d, 0xfc, 0x7c, 0x39, 0x23, 0x21, + 0xa0, 0x61, 0xa1, 0x17, 0x11, 0xc2, 0x7a, 0x38, 0xca, 0xb3, 0x97, 0xd8, 0x70, 0x21, 0x43, 0x87, 0xe3, 0x87, 0x63, + 0xb3, 0x17, 0x34, 0xc7, 0xcf, 0xa7, 0xc7, 0xc6, 0xbe, 0x56, 0xd3, 0x24, 0x0b, 0x2e, 0x65, 0xe1, 0x74, 0xfd, 0xc8, + 0x11, 0xc5, 0x67, 0xda, 0x75, 0xdf, 0xc1, 0xe6, 0x33, 0x29, 0x73, 0x52, 0xe9, 0x26, 0x02, 0x95, 0x81, 0x4c, 0xde, + 0xed, 0x05, 0xc0, 0xb6, 0x01, 0xfa, 0xa2, 0xb9, 0xc8, 0x4c, 0x65, 0x9f, 0x74, 0x5e, 0x1e, 0x22, 0x65, 0x7b, 0x78, + 0x73, 0x58, 0x86, 0x80, 0xd7, 0xa7, 0x35, 0xfb, 0x37, 0x3c, 0x0d, 0xd2, 0x75, 0xb4, 0x31, 0x2a, 0x92, 0xe6, 0x82, + 0xc9, 0x35, 0x2a, 0xa6, 0xc1, 0x43, 0x38, 0x69, 0xc0, 0xa9, 0x52, 0x4e, 0xb8, 0x20, 0x79, 0x81, 0x49, 0x2a, 0xf6, + 0x04, 0x5a, 0xdb, 0x40, 0x44, 0x45, 0x0d, 0x3f, 0xba, 0x8c, 0x8b, 0x47, 0x69, 0x67, 0x4f, 0xa2, 0xa2, 0xfe, 0xda, + 0x7b, 0xd2, 0x0a, 0x61, 0x9f, 0x53, 0xdd, 0xf5, 0x1a, 0x8f, 0xcd, 0x08, 0x8a, 0x5e, 0xd3, 0xd4, 0xff, 0x65, 0x18, + 0x84, 0xbb, 0xcb, 0x76, 0x0e, 0x82, 0x82, 0x1c, 0x21, 0xc0, 0x4f, 0x5e, 0xd0, 0x97, 0x00, 0x6b, 0xe8, 0x88, 0x03, + 0x79, 0x7e, 0x6d, 0x8f, 0xa4, 0x73, 0xf5, 0xd5, 0xb9, 0xef, 0x7f, 0xc5, 0xd1, 0x1a, 0xef, 0x9f, 0x61, 0xec, 0x1f, + 0x9f, 0x29, 0x6d, 0xce, 0x1e, 0x33, 0xf1, 0xe8, 0x44, 0xf6, 0xb7, 0x8d, 0x49, 0x8a, 0xb7, 0xc7, 0x4a, 0x81, 0x7f, + 0xf8, 0x40, 0xf2, 0x36, 0x0b, 0xe7, 0x46, 0x12, 0xf3, 0xdb, 0xd9, 0xaa, 0x93, 0x9f, 0x1c, 0xd7, 0xca, 0x7d, 0xd6, + 0x24, 0x7f, 0xcc, 0xa5, 0x1d, 0xf0, 0x9d, 0xab, 0xce, 0xce, 0xad, 0xe4, 0xd6, 0x38, 0xe7, 0xf8, 0xcd, 0xb7, 0xbb, + 0x55, 0xea, 0xcd, 0xff, 0x95, 0xd5, 0xe2, 0x3a, 0x75, 0xc3, 0x25, 0xde, 0x40, 0x41, 0x50, 0xb8, 0xc3, 0x3a, 0xbd, + 0xcc, 0x5d, 0xe3, 0x0e, 0xa3, 0xc1, 0xda, 0xfa, 0xaa, 0xc8, 0x3c, 0x32, 0x17, 0x31, 0xce, 0x67, 0xe2, 0x65, 0x35, + 0x65, 0xdb, 0xa0, 0xdf, 0x35, 0x15, 0xe6, 0x3f, 0xbf, 0x86, 0x3a, 0xdb, 0xb1, 0xf9, 0x53, 0xe5, 0xdf, 0x80, 0x6b, + 0xe8, 0x50, 0x8e, 0xa2, 0xe0, 0xc4, 0x75, 0xcd, 0xb4, 0x4d, 0xce, 0xb5, 0x70, 0x5c, 0xbb, 0x1c, 0x78, 0xb5, 0x49, + 0x9c, 0x41, 0x94, 0x56, 0xc6, 0x3d, 0xa7, 0x4f, 0xbb, 0xfc, 0xce, 0xb8, 0x63, 0xd8, 0x75, 0x30, 0x0a, 0x82, 0x01, + 0x25, 0x16, 0x6d, 0x50, 0x77, 0x32, 0xba, 0x9a, 0xd8, 0xb3, 0x06, 0x62, 0x09, 0xac, 0x68, 0x7e, 0xab, 0x04, 0xa0, + 0xa5, 0x1d, 0x78, 0x59, 0xaf, 0x12, 0xc9, 0x92, 0xd5, 0x37, 0x0e, 0xe6, 0x7f, 0x88, 0x50, 0x04, 0xe7, 0xdb, 0x38, + 0xc4, 0x8b, 0x4a, 0x91, 0x98, 0x53, 0xec, 0xd1, 0x9b, 0xec, 0xa3, 0x5e, 0x82, 0x34, 0xff, 0x06, 0x18, 0x20, 0x60, + 0xc3, 0x71, 0x2c, 0x10, 0x94, 0xcc, 0xcf, 0xf1, 0xe5, 0xce, 0x5e, 0xbe, 0xf9, 0x04, 0x53, 0xfb, 0x37, 0x9e, 0xdb, + 0xc8, 0xfd, 0xdb, 0x50, 0xc9, 0xed, 0xcf, 0x2c, 0xee, 0xff, 0x2c, 0x9e, 0xdd, 0xbf, 0xe5, 0x1f, 0xbf, 0x6e, 0x5a, + 0xe0, 0x9d, 0xce, 0xfb, 0x48, 0x02, 0x35, 0x3f, 0x5f, 0x67, 0xa4, 0x60, 0x18, 0x11, 0x7c, 0xed, 0xf8, 0x30, 0xa2, + 0xfb, 0xad, 0x67, 0x03, 0x6b, 0x62, 0x1f, 0xe3, 0x16, 0xd5, 0xeb, 0x79, 0x81, 0xed, 0x6a, 0x5c, 0xcb, 0xf4, 0xb2, + 0xd0, 0x9a, 0xa7, 0xca, 0x2e, 0x15, 0x1a, 0x09, 0x07, 0x5b, 0xc0, 0x3b, 0xb8, 0xeb, 0xca, 0x9d, 0xbd, 0xb4, 0x66, + 0x36, 0xe5, 0x49, 0x82, 0x9c, 0x0e, 0x5c, 0x34, 0x7d, 0xf5, 0xd4, 0xb6, 0xc4, 0x18, 0xfe, 0x9c, 0x37, 0xd5, 0x18, + 0x15, 0x3d, 0x46, 0x23, 0x19, 0xb1, 0x72, 0x56, 0x46, 0xcb, 0x8b, 0x61, 0x68, 0x4b, 0xc6, 0xc5, 0xac, 0xb2, 0xa0, + 0x0c, 0xb8, 0x07, 0x42, 0xd6, 0x0b, 0xfa, 0xd6, 0x4e, 0x91, 0x0f, 0xd5, 0x27, 0x1c, 0xb0, 0x79, 0x3c, 0xc1, 0x71, + 0xe9, 0xa3, 0x7a, 0x40, 0x9a, 0xc4, 0x55, 0xb8, 0x86, 0xb3, 0xc9, 0xaa, 0x8a, 0xe7, 0xcd, 0x4f, 0xdb, 0x00, 0x73, + 0x5a, 0xb0, 0x7f, 0x73, 0x5b, 0xa2, 0xdc, 0x4f, 0x82, 0xda, 0x2e, 0x1a, 0x55, 0x8d, 0xb2, 0x00, 0xa2, 0x4c, 0x9f, + 0xde, 0x40, 0x02, 0xd1, 0x39, 0xd5, 0x8b, 0xe6, 0xdb, 0xd4, 0x76, 0x38, 0x37, 0x45, 0xa0, 0x16, 0x2e, 0x8d, 0xd1, + 0x6c, 0xa6, 0x70, 0xc2, 0x7b, 0x97, 0xf6, 0x3c, 0x5d, 0x20, 0x4f, 0xb6, 0x80, 0x49, 0xdf, 0x0b, 0x3c, 0x6b, 0x00, + 0x0f, 0x08, 0xf4, 0x28, 0xaa, 0xd0, 0xc0, 0x9a, 0x82, 0x1d, 0x8c, 0x8a, 0x34, 0x0e, 0x80, 0x64, 0x9f, 0x46, 0xdc, + 0x80, 0x83, 0x73, 0x34, 0x86, 0x8e, 0x6d, 0xcf, 0xe4, 0x95, 0x14, 0x82, 0xa0, 0xca, 0x66, 0x89, 0xcd, 0x68, 0xb2, + 0x17, 0x95, 0x6f, 0x70, 0xb3, 0x73, 0x27, 0x18, 0xfb, 0x9d, 0xce, 0x00, 0xa6, 0xac, 0xa2, 0x77, 0x48, 0xcd, 0x88, + 0x17, 0x3a, 0x29, 0x9a, 0x1c, 0x88, 0x48, 0x46, 0xcc, 0x75, 0xe3, 0xb7, 0x7f, 0x1e, 0xe5, 0x66, 0x63, 0x5b, 0x6c, + 0x56, 0x3c, 0x23, 0x58, 0xef, 0xe0, 0xea, 0x2c, 0xbc, 0xd6, 0x33, 0xb2, 0x50, 0xf8, 0xc7, 0x30, 0xb9, 0x53, 0xdf, + 0xf7, 0xc4, 0x88, 0xe6, 0xf2, 0x7f, 0x97, 0xb1, 0xab, 0xca, 0x69, 0x34, 0x86, 0x86, 0x48, 0x46, 0x36, 0x01, 0x48, + 0xe6, 0x59, 0xd3, 0x31, 0x9a, 0x8d, 0xd5, 0xb6, 0x73, 0x9a, 0x66, 0x3f, 0x7e, 0xe5, 0xf4, 0xd7, 0x06, 0xc7, 0x03, + 0xe4, 0xe7, 0xce, 0x8d, 0x72, 0xf6, 0x03, 0x5b, 0xcc, 0xa1, 0xc7, 0xb9, 0x5c, 0xd5, 0x37, 0x8a, 0x5c, 0x8d, 0x90, + 0x8b, 0x41, 0xdf, 0x0d, 0x2a, 0x1e, 0x10, 0x40, 0x7f, 0x02, 0x5f, 0x79, 0x79, 0xfe, 0x5f, 0xa3, 0xb9, 0xe3, 0x91, + 0x60, 0x63, 0xe5, 0x32, 0x9c, 0xc4, 0xcb, 0x61, 0x3c, 0xe0, 0xe8, 0x39, 0x91, 0xf8, 0xb4, 0x22, 0xe9, 0x11, 0x89, + 0x0c, 0xe3, 0x91, 0x59, 0x1a, 0x52, 0x9c, 0x61, 0x84, 0xe2, 0x2f, 0xab, 0xdf, 0xae, 0xbb, 0x6f, 0x20, 0xc5, 0xbf, + 0x71, 0x5d, 0x1d, 0xcf, 0x8d, 0x2a, 0x33, 0xe9, 0x65, 0x73, 0xdc, 0x92, 0xb3, 0x9a, 0x56, 0x33, 0x9f, 0xb5, 0x4b, + 0xa6, 0xed, 0xe6, 0xb1, 0x9c, 0x19, 0x3f, 0x4f, 0x13, 0xc9, 0xe0, 0x6f, 0xce, 0x61, 0x80, 0x16, 0x06, 0xda, 0x4b, + 0xec, 0xd4, 0xa0, 0xd3, 0xd5, 0x9b, 0x0d, 0x31, 0xda, 0xae, 0xd6, 0xe9, 0x07, 0x5c, 0x2f, 0xe8, 0x18, 0x76, 0xd6, + 0x74, 0xf2, 0x9c, 0x10, 0xbb, 0x28, 0xf8, 0xf1, 0xfb, 0xae, 0xa0, 0xd4, 0x34, 0xa0, 0x5f, 0xe7, 0xe5, 0xe5, 0xae, + 0x76, 0x91, 0x81, 0x9a, 0x09, 0xe8, 0x90, 0xdd, 0x30, 0xe6, 0x58, 0x17, 0x63, 0x0f, 0xd2, 0x85, 0x71, 0x6b, 0xf6, + 0x41, 0x68, 0x8c, 0xb2, 0x70, 0x65, 0x4c, 0x2e, 0x0a, 0x5f, 0x93, 0x93, 0x6b, 0xb8, 0xa0, 0x25, 0xb4, 0xcf, 0xbd, + 0x77, 0x0e, 0xd3, 0x3d, 0xc2, 0x51, 0x5b, 0x7a, 0x91, 0x16, 0xea, 0xcd, 0x42, 0x79, 0x56, 0x80, 0x16, 0x2c, 0x52, + 0x4f, 0xab, 0xe5, 0xc8, 0xe5, 0x5d, 0x3f, 0x3a, 0x3d, 0x75, 0xab, 0xb5, 0xdc, 0x63, 0x4a, 0x03, 0xe1, 0x1d, 0xad, + 0xec, 0xbf, 0xe2, 0x25, 0x47, 0x2a, 0x6c, 0xd5, 0x2c, 0x93, 0xaf, 0xc8, 0xf5, 0x3f, 0x6a, 0x7a, 0x13, 0xef, 0x13, + 0xae, 0x0a, 0x84, 0x3b, 0x12, 0xa1, 0x33, 0x9e, 0x32, 0xeb, 0x68, 0x1d, 0xaf, 0xa9, 0x13, 0x3b, 0x1e, 0x1e, 0x17, + 0x28, 0x86, 0xdf, 0x9a, 0xd1, 0x80, 0xe7, 0xbe, 0x78, 0x11, 0xec, 0x5e, 0xfb, 0x2e, 0x39, 0x33, 0x8b, 0x6c, 0x7f, + 0xd5, 0x6a, 0xdc, 0x85, 0xd8, 0xb4, 0xca, 0xdc, 0x15, 0xfb, 0xec, 0x30, 0x9c, 0x6b, 0xc6, 0x17, 0x07, 0xb7, 0x7b, + 0x23, 0x77, 0x07, 0x6f, 0x9e, 0x12, 0x47, 0xd7, 0x02, 0x1e, 0x97, 0x9b, 0xbc, 0x5b, 0x55, 0xba, 0x5f, 0x1b, 0xf5, + 0x6a, 0x5f, 0x23, 0xfb, 0x92, 0x80, 0xe4, 0x71, 0x3d, 0xa4, 0x88, 0xe3, 0xa9, 0xc8, 0xd6, 0x84, 0xb1, 0x0e, 0x0a, + 0x1e, 0x6a, 0x3d, 0xb7, 0xed, 0xa4, 0xf6, 0x83, 0x72, 0xb7, 0x2e, 0xca, 0xca, 0xc3, 0xe1, 0xb7, 0xcd, 0x8f, 0x07, + 0xee, 0x25, 0x85, 0xe2, 0xa1, 0xfa, 0x2a, 0x02, 0x03, 0xee, 0x57, 0xd4, 0x9a, 0xcc, 0x8a, 0xe3, 0x27, 0xec, 0x94, + 0xca, 0x14, 0xa3, 0x83, 0x9b, 0xb6, 0x3b, 0x4d, 0x03, 0x18, 0x1d, 0xd3, 0x75, 0xb2, 0x33, 0xf5, 0xf8, 0x84, 0x88, + 0x1c, 0x53, 0xfb, 0x9f, 0xca, 0x8b, 0xd3, 0x01, 0xde, 0x07, 0xfb, 0xaf, 0x98, 0x40, 0x6c, 0xad, 0xbb, 0x49, 0x9d, + 0x86, 0x48, 0xc1, 0x87, 0x35, 0x6d, 0xfc, 0x5f, 0x7c, 0x2e, 0x8c, 0x26, 0xa2, 0x77, 0xea, 0xad, 0x2b, 0x25, 0xb0, + 0x5d, 0xed, 0x52, 0xe8, 0xb6, 0xb7, 0xba, 0x89, 0x71, 0x59, 0xf0, 0x86, 0x4e, 0xef, 0xc8, 0xfa, 0x49, 0xd0, 0x86, + 0xdc, 0x3b, 0x75, 0x19, 0x71, 0x88, 0x91, 0x94, 0xb3, 0x8b, 0xb1, 0xd4, 0x86, 0xd0, 0xc5, 0x16, 0x65, 0x4d, 0xee, + 0xfa, 0xfb, 0x53, 0x74, 0x18, 0x5a, 0x22, 0x8d, 0xf2, 0xbc, 0x03, 0xb6, 0x5e, 0xdd, 0x29, 0xaa, 0xb8, 0x1d, 0xae, + 0x6c, 0x5d, 0x02, 0xbd, 0x4e, 0x0c, 0xbe, 0xd8, 0x51, 0x83, 0x02, 0xde, 0x08, 0xdd, 0x64, 0xd2, 0x35, 0xc4, 0x70, + 0x36, 0xce, 0x3e, 0xa6, 0x1c, 0xf3, 0x73, 0xbf, 0x34, 0x5f, 0x56, 0x52, 0x3b, 0x41, 0x4c, 0x18, 0x90, 0xeb, 0x59, + 0x71, 0xa4, 0xfa, 0xf6, 0xf4, 0xaf, 0x4d, 0xe1, 0xff, 0x8e, 0x0d, 0xdf, 0xea, 0x30, 0x22, 0x19, 0xf5, 0x0a, 0x3b, + 0x04, 0x3a, 0x83, 0xba, 0xa4, 0x30, 0xe9, 0x43, 0x40, 0x9d, 0xb8, 0xc6, 0xf5, 0x54, 0x1e, 0x21, 0xf4, 0x4d, 0x1a, + 0x54, 0xce, 0x6d, 0x3b, 0xd4, 0x5b, 0xdf, 0x13, 0x51, 0x02, 0x84, 0x47, 0xa3, 0x00, 0x5a, 0x64, 0x32, 0xb8, 0x37, + 0x38, 0x80, 0xb0, 0x2e, 0xa5, 0x9c, 0xd1, 0x5a, 0xd2, 0x75, 0x68, 0x3e, 0x6e, 0xb1, 0xbe, 0xd5, 0x09, 0x39, 0x82, + 0x54, 0xea, 0xe9, 0x53, 0x35, 0x5d, 0xa4, 0x97, 0x98, 0x2d, 0x9d, 0xf2, 0x79, 0x80, 0xd8, 0x86, 0x5e, 0x58, 0x74, + 0x9f, 0xcf, 0xe5, 0x21, 0x40, 0xa6, 0xb9, 0x04, 0x24, 0x5c, 0x52, 0x50, 0x3f, 0x02, 0x93, 0x72, 0xf9, 0x1f, 0x15, + 0xd2, 0xeb, 0xdc, 0x1d, 0xbe, 0x7a, 0xbd, 0x58, 0xd5, 0x1a, 0x59, 0xbf, 0xf1, 0x03, 0x5d, 0xe5, 0xf5, 0xaa, 0xd6, + 0x9e, 0x2f, 0xd8, 0x8c, 0x0e, 0xd2, 0x8d, 0xf4, 0x3f, 0xf9, 0x07, 0x63, 0xa9, 0xb3, 0x23, 0xfa, 0x16, 0x57, 0xe2, + 0xba, 0xaf, 0xa7, 0xf7, 0x50, 0x5e, 0x3c, 0x49, 0x93, 0x65, 0xca, 0x6a, 0xd3, 0xfa, 0xb0, 0x53, 0x04, 0x42, 0xd4, + 0xd1, 0xcb, 0xb8, 0xe4, 0xc0, 0x45, 0x59, 0xba, 0x5e, 0x80, 0x7f, 0xf6, 0x0f, 0xa3, 0x13, 0x68, 0xa0, 0xd8, 0xb0, + 0xfb, 0x7e, 0x47, 0x65, 0xe7, 0x42, 0x0e, 0x4d, 0xf4, 0xbe, 0xda, 0x29, 0x93, 0x33, 0x75, 0x67, 0x9f, 0x93, 0xe8, + 0x86, 0x3a, 0x90, 0x57, 0x06, 0x1c, 0xa7, 0x5e, 0xec, 0xf7, 0x60, 0x98, 0x15, 0xbe, 0xec, 0x59, 0xb7, 0xfd, 0x09, + 0x83, 0x29, 0xc8, 0x5a, 0xee, 0x2c, 0x8a, 0xe5, 0x5d, 0xc8, 0xab, 0xa8, 0xb1, 0x5c, 0x4c, 0xac, 0x10, 0xca, 0x02, + 0xb6, 0x9c, 0xdc, 0x8f, 0x42, 0x90, 0x7b, 0x9c, 0xe3, 0xcd, 0xce, 0x39, 0x52, 0xee, 0x12, 0xcc, 0xee, 0xb0, 0xc5, + 0x69, 0x22, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x4a, 0x54, 0x51, 0xe4, 0xa6, 0x98, 0xa8, 0xe2, 0xa8, 0x6b, 0x7b, + 0xa3, 0x6d, 0x23, 0x65, 0x90, 0xc8, 0x30, 0x23, 0xa4, 0xa7, 0xf9, 0xe1, 0xee, 0xcd, 0x3e, 0x99, 0x32, 0x06, 0x11, + 0xd0, 0xa8, 0x7a, 0x06, 0x10, 0x7a, 0xbe, 0xac, 0x5d, 0xf2, 0x58, 0x56, 0x30, 0x92, 0xbe, 0x02, 0x1a, 0x2e, 0x9a, + 0x74, 0xc3, 0x2f, 0xc1, 0x49, 0xac, 0x78, 0x9a, 0x00, 0x45, 0xa3, 0xad, 0xf2, 0x6c, 0x88, 0xaf, 0x3c, 0x0e, 0x3a, + 0x51, 0x4f, 0x1a, 0x14, 0xc1, 0x60, 0x9a, 0x8d, 0x24, 0xdc, 0x52, 0x93, 0x41, 0xac, 0x0c, 0xc4, 0xd1, 0xbf, 0xb4, + 0x52, 0xa6, 0x54, 0xbb, 0x5a, 0x30, 0x32, 0xa3, 0x07, 0xd3, 0xdf, 0x85, 0xa8, 0x61, 0xd5, 0x08, 0xfd, 0x45, 0xa6, + 0x4e, 0x75, 0xca, 0xc8, 0x4b, 0x8c, 0xd3, 0xc4, 0xc0, 0x18, 0x72, 0xa0, 0x71, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, + 0xb6, 0x8c, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, 0x6e, 0xe9, 0xfa, 0xcf, 0x65, 0xb6, 0x61, 0xc7, 0x9c, 0xbf, + 0xf4, 0xd3, 0x6e, 0xfa, 0x30, 0xc6, 0xbc, 0x19, 0x07, 0xc3, 0x0c, 0xae, 0xbf, 0x48, 0x8b, 0x47, 0x45, 0x83, 0x2c, + 0x5f, 0x6a, 0x8c, 0x23, 0xed, 0xef, 0x07, 0xaa, 0xb7, 0xbb, 0x8d, 0x49, 0xd2, 0x00, 0x28, 0x47, 0x68, 0x44, 0x70, + 0xec, 0x8a, 0xff, 0x38, 0xaa, 0xfc, 0xef, 0xee, 0x7a, 0x8b, 0x1e, 0x84, 0x2f, 0xf6, 0xa6, 0x4f, 0xa3, 0x80, 0x39, + 0x6b, 0xdd, 0xae, 0x3e, 0x8d, 0xa9, 0x21, 0xfd, 0x35, 0x01, 0xe3, 0xc6, 0xb1, 0xfa, 0xc7, 0x34, 0x25, 0xbf, 0xd7, + 0x63, 0x12, 0x5f, 0x2c, 0xfa, 0xca, 0x1a, 0x55, 0xea, 0xd1, 0x65, 0x38, 0x6d, 0xc9, 0x68, 0x4f, 0xca, 0xb7, 0xba, + 0xc3, 0xd3, 0xb6, 0x4b, 0x6a, 0x36, 0xef, 0x89, 0xf9, 0xec, 0xba, 0xda, 0x56, 0xe2, 0x88, 0xf4, 0x20, 0x5f, 0x4f, + 0x19, 0xa5, 0xa3, 0x4f, 0xd1, 0xde, 0xef, 0x8e, 0x03, 0x99, 0xa7, 0xc7, 0xa1, 0x56, 0xd7, 0xae, 0xec, 0xf8, 0x56, + 0x9c, 0x98, 0xd4, 0x58, 0x86, 0xec, 0xd7, 0xb8, 0x11, 0x0d, 0x3a, 0xee, 0x7d, 0xd5, 0x7a, 0xdd, 0xd4, 0x98, 0x0e, + 0x4e, 0x31, 0x04, 0xcd, 0x57, 0x5d, 0x12, 0x55, 0xc4, 0x82, 0x37, 0xc4, 0x07, 0x71, 0x01, 0x80, 0x9c, 0x93, 0x16, + 0xb5, 0xec, 0x18, 0x4b, 0xa2, 0x7c, 0x57, 0x81, 0x5a, 0xf2, 0xec, 0xa2, 0xa2, 0x53, 0x77, 0xa2, 0x57, 0xa7, 0x5e, + 0xa5, 0x39, 0x8d, 0xd0, 0xf5, 0xf0, 0x99, 0xe7, 0xa8, 0x64, 0x59, 0xf7, 0xae, 0x42, 0x5f, 0xb1, 0xd7, 0x5e, 0x49, + 0xc9, 0x3b, 0x52, 0x1a, 0x0a, 0x19, 0xc5, 0x1a, 0x34, 0xb6, 0xce, 0x5d, 0x62, 0x49, 0x27, 0xcb, 0xa3, 0x86, 0xc2, + 0x17, 0x73, 0x1f, 0xb7, 0xc6, 0x51, 0x39, 0xe6, 0x1c, 0xc0, 0x9e, 0x54, 0xe9, 0x64, 0xaa, 0x1c, 0xc0, 0xaf, 0x69, + 0x16, 0x11, 0x83, 0x94, 0xda, 0xe9, 0xb8, 0x8b, 0xb3, 0x64, 0x3b, 0x61, 0xd0, 0xb1, 0xe8, 0x39, 0x7a, 0x20, 0xd2, + 0x79, 0x1c, 0x44, 0xf7, 0x91, 0xc7, 0x0d, 0x32, 0x0c, 0xb6, 0x67, 0x2d, 0x79, 0x94, 0xb9, 0xe2, 0x28, 0xbb, 0x12, + 0x53, 0xcb, 0xb3, 0xa9, 0xdb, 0x33, 0xba, 0x62, 0xad, 0xac, 0xe9, 0xee, 0x88, 0x4c, 0x05, 0xf7, 0x7d, 0x7b, 0x86, + 0x4f, 0x47, 0x46, 0x8e, 0x33, 0x89, 0xa3, 0x3a, 0x84, 0xb9, 0x71, 0x22, 0x78, 0x82, 0xd1, 0xb2, 0x25, 0xf3, 0x94, + 0x53, 0x0a, 0xb5, 0xf7, 0xbf, 0x34, 0x1e, 0xa1, 0x6a, 0xae, 0x61, 0x7a, 0xcb, 0xd0, 0x1d, 0xc2, 0x76, 0xfd, 0x43, + 0x74, 0x32, 0xa2, 0x05, 0xef, 0x2f, 0x92, 0x0a, 0xc6, 0x5a, 0x5a, 0x95, 0xb6, 0xbe, 0xdd, 0x43, 0x02, 0x96, 0xa7, + 0x56, 0x9d, 0xa1, 0x80, 0x15, 0xa6, 0xcf, 0xf9, 0x9b, 0xb9, 0xc6, 0x21, 0x77, 0x2d, 0x11, 0x10, 0x1b, 0x81, 0xdd, + 0xd0, 0x09, 0x12, 0x18, 0xaa, 0x10, 0xfb, 0xac, 0x55, 0xf1, 0x9c, 0x37, 0x85, 0x1e, 0xf0, 0x23, 0x9f, 0xc4, 0x92, + 0xfa, 0x09, 0x92, 0xfc, 0x09, 0x97, 0x84, 0xd0, 0xa7, 0xfc, 0x22, 0xf6, 0xaa, 0xc9, 0x4d, 0xad, 0x34, 0xdb, 0x0e, + 0xc5, 0xcf, 0xfc, 0x62, 0xdc, 0xdd, 0x68, 0x88, 0x21, 0x62, 0x85, 0x11, 0x0a, 0xc6, 0x9c, 0xa0, 0x6e, 0xf2, 0x57, + 0xa4, 0xf8, 0x74, 0xce, 0xe6, 0x5b, 0xf8, 0x4e, 0xdb, 0xe9, 0x1d, 0x14, 0x0a, 0x31, 0xea, 0x0c, 0x2d, 0x61, 0xd8, + 0xc3, 0x93, 0xf9, 0xec, 0xc2, 0x9c, 0x84, 0x24, 0x15, 0x2d, 0x4a, 0x38, 0x43, 0xfc, 0x06, 0xc0, 0x04, 0x9a, 0xac, + 0x44, 0xa9, 0xa8, 0x81, 0x3d, 0x82, 0x5f, 0xb8, 0xd9, 0xe6, 0xf3, 0x56, 0xe4, 0xe1, 0x40, 0x1a, 0xe5, 0x0a, 0x6d, + 0x20, 0xa6, 0x7a, 0x6e, 0x23, 0xb1, 0x18, 0x19, 0x45, 0x6b, 0xc9, 0x97, 0x5a, 0x42, 0x5d, 0xec, 0x3c, 0x08, 0xd6, + 0x55, 0x77, 0x95, 0x9d, 0xa1, 0x59, 0x31, 0x83, 0x03, 0x39, 0x2e, 0xd0, 0x30, 0x44, 0xba, 0x31, 0xd9, 0xa6, 0x98, + 0x65, 0x23, 0x7c, 0x5f, 0xc5, 0xbc, 0xc9, 0x6b, 0x21, 0xf2, 0x5a, 0x9d, 0x49, 0xb0, 0x86, 0x09, 0x79, 0x6a, 0x60, + 0x96, 0x24, 0xa4, 0x61, 0x09, 0xcb, 0x13, 0x3e, 0x43, 0xbd, 0x64, 0x98, 0x66, 0x64, 0xfa, 0xe0, 0x49, 0xbf, 0x65, + 0xfd, 0x89, 0x37, 0xf2, 0xf3, 0x46, 0x13, 0x78, 0x51, 0x09, 0x55, 0x2e, 0xb6, 0x19, 0x22, 0xba, 0xd5, 0x52, 0xc3, + 0x73, 0xea, 0x96, 0x27, 0x40, 0xe2, 0x49, 0x9f, 0x19, 0x7e, 0xb4, 0xcd, 0x08, 0x81, 0x54, 0xe9, 0xad, 0x8b, 0x90, + 0xd9, 0x27, 0x65, 0xe5, 0xe1, 0xf0, 0xe4, 0xd2, 0x69, 0x09, 0x95, 0xc0, 0xf5, 0x9b, 0xd7, 0x05, 0x54, 0x81, 0x99, + 0xa1, 0x58, 0x63, 0x53, 0x3d, 0x1b, 0x6f, 0x90, 0x66, 0x30, 0x2e, 0x22, 0xa1, 0x42, 0xe6, 0xce, 0x25, 0x9a, 0xba, + 0x5e, 0xcc, 0x19, 0xcb, 0xcb, 0x3e, 0xec, 0xf9, 0xd2, 0x53, 0xcc, 0x2e, 0xbc, 0xd6, 0x2f, 0x99, 0xe3, 0xf6, 0x59, + 0x48, 0xb3, 0xdc, 0x9d, 0x22, 0x35, 0x7b, 0xac, 0x92, 0x9a, 0x07, 0xb0, 0xae, 0xb3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, + 0x61, 0x7f, 0x82, 0x3b, 0x80, 0x63, 0x04, 0x43, 0x12, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0x30, 0xf2, 0xcd, 0xc7, 0x41, + 0x1b, 0x82, 0xc8, 0x04, 0x89, 0x10, 0x31, 0x91, 0xc7, 0xf0, 0xf3, 0x01, 0xce, 0xbe, 0xba, 0x4c, 0x34, 0x51, 0xbc, + 0x11, 0x8a, 0x69, 0x78, 0x0d, 0x77, 0xeb, 0xc0, 0x8c, 0xce, 0x7b, 0x3a, 0x45, 0x57, 0xd0, 0x24, 0xa6, 0x56, 0x4f, + 0x9b, 0xf7, 0xdc, 0x23, 0xc2, 0x2f, 0x74, 0x51, 0xdc, 0xdd, 0xc1, 0x7a, 0xbd, 0x80, 0x25, 0x13, 0xf9, 0x96, 0x33, + 0xf3, 0x66, 0xca, 0x1e, 0x92, 0x63, 0x9f, 0x3e, 0x3c, 0x6e, 0x17, 0xfb, 0xe4, 0x39, 0x2e, 0xb2, 0x5e, 0x52, 0x85, + 0x3d, 0x29, 0xff, 0x9b, 0x32, 0xe6, 0x44, 0x04, 0x35, 0x95, 0xe9, 0xda, 0xa2, 0xe3, 0xcf, 0x2a, 0x9a, 0x2c, 0x8d, + 0x60, 0x6b, 0x54, 0x91, 0x7e, 0x69, 0x94, 0x52, 0x1d, 0x51, 0x0f, 0x43, 0x9b, 0x48, 0xb1, 0xd0, 0x28, 0x70, 0x74, + 0xa9, 0x4d, 0xf0, 0x6c, 0x15, 0xf4, 0x48, 0x7c, 0xa4, 0x9d, 0xd8, 0xe6, 0xfc, 0x7c, 0x4f, 0xf1, 0x4d, 0xf2, 0x5b, + 0xfa, 0x5b, 0x70, 0x93, 0x42, 0x93, 0xc5, 0xb5, 0xbc, 0xb5, 0x72, 0x8b, 0xdf, 0xe5, 0x63, 0x5f, 0xa3, 0x8b, 0x83, + 0x51, 0x3a, 0x99, 0xf3, 0x5e, 0x78, 0xc8, 0xb5, 0x93, 0x57, 0x62, 0xaf, 0x66, 0x2b, 0xc5, 0x95, 0x60, 0xe1, 0xc1, + 0xa9, 0x2b, 0x99, 0x8a, 0x56, 0x10, 0xc8, 0xbc, 0x71, 0xdb, 0xaf, 0x7f, 0x20, 0xa3, 0x6d, 0x08, 0x19, 0xcc, 0xda, + 0xea, 0x25, 0xa6, 0xf3, 0xbe, 0x45, 0xbe, 0x64, 0x6f, 0x6c, 0x59, 0xf7, 0x10, 0x88, 0xfe, 0xe4, 0x78, 0x37, 0x64, + 0x05, 0x16, 0x0a, 0xfb, 0x12, 0xd0, 0x93, 0xa8, 0xaa, 0xd4, 0x5e, 0xea, 0x50, 0xae, 0xab, 0x19, 0x2a, 0x54, 0xcb, + 0xeb, 0x1f, 0x40, 0x22, 0x8e, 0x52, 0x06, 0xed, 0xe9, 0xa2, 0x2a, 0x23, 0x82, 0xc0, 0xb8, 0x08, 0x0d, 0x2b, 0xc4, + 0x14, 0x76, 0x59, 0xc5, 0x38, 0x4e, 0x57, 0xf7, 0xf5, 0x8b, 0x53, 0x88, 0xbd, 0xee, 0x86, 0xac, 0x12, 0x74, 0xee, + 0xba, 0xec, 0xd3, 0x1c, 0xfa, 0x99, 0xae, 0x7f, 0x04, 0x37, 0x39, 0x87, 0x35, 0x29, 0x38, 0x35, 0xf5, 0x39, 0x8b, + 0x25, 0xdf, 0x08, 0x15, 0x4e, 0x5b, 0x32, 0xda, 0xb1, 0x63, 0x56, 0xe5, 0xc7, 0x2e, 0x4b, 0x69, 0x60, 0x48, 0xa2, + 0xba, 0x36, 0xe8, 0x18, 0xb4, 0x24, 0x72, 0xf3, 0xea, 0x70, 0x49, 0x7b, 0x43, 0xc8, 0x0f, 0x37, 0xa7, 0xfb, 0x94, + 0xd0, 0xc6, 0x6a, 0xf1, 0xca, 0xc5, 0x97, 0x44, 0xa4, 0xbc, 0xe0, 0x1e, 0x01, 0xeb, 0x77, 0x22, 0xfc, 0xbb, 0xe8, + 0xc1, 0x81, 0x47, 0x00, 0x8b, 0xf0, 0x56, 0xdc, 0x57, 0xde, 0x26, 0x94, 0x56, 0xa0, 0x2e, 0xd7, 0xa6, 0x51, 0x82, + 0x37, 0xa4, 0xff, 0xf0, 0xc8, 0xbe, 0xcc, 0x13, 0xb6, 0x51, 0x21, 0xf1, 0x0e, 0xbf, 0xf3, 0x77, 0x4f, 0xc7, 0x9c, + 0x00, 0xbb, 0xa5, 0xd3, 0xbc, 0x6a, 0x0b, 0x90, 0x16, 0x5d, 0x0c, 0x62, 0x9c, 0x82, 0xe5, 0x95, 0x00, 0xe9, 0x87, + 0x57, 0x61, 0xa1, 0xeb, 0xf9, 0x7b, 0x4d, 0xf7, 0xca, 0x5e, 0x87, 0x69, 0xf2, 0x65, 0xef, 0x88, 0x46, 0xd0, 0xcb, + 0xd5, 0xc9, 0xe5, 0xfb, 0x94, 0x72, 0xe1, 0x5f, 0xd2, 0xd5, 0xcf, 0x54, 0x89, 0xe6, 0xaa, 0x6f, 0xaa, 0xf8, 0x94, + 0xab, 0xf1, 0x09, 0xa4, 0xda, 0x9c, 0x57, 0x13, 0xe6, 0xca, 0x55, 0x9f, 0xdc, 0x77, 0x17, 0x98, 0x56, 0x6f, 0xfd, + 0xdb, 0xfd, 0x30, 0xd0, 0x9f, 0xdd, 0xdf, 0x1c, 0x7c, 0x9d, 0x5d, 0x74, 0x76, 0x3a, 0xf6, 0x2f, 0xe4, 0xc7, 0x11, + 0xba, 0xac, 0x87, 0xa2, 0x26, 0x72, 0xc2, 0x7b, 0xea, 0xa8, 0x61, 0x2f, 0xb7, 0x94, 0x79, 0x31, 0x7d, 0x2f, 0x59, + 0x05, 0x94, 0xdf, 0xb7, 0xd9, 0xa5, 0xd5, 0x84, 0xe2, 0x02, 0x92, 0x2e, 0x73, 0x9a, 0x95, 0x6e, 0xa4, 0x50, 0xb3, + 0xc9, 0x5e, 0x46, 0x56, 0xe9, 0xb5, 0x12, 0xec, 0x57, 0x8b, 0x60, 0x58, 0x56, 0xe9, 0x2a, 0x8f, 0x3a, 0x6c, 0xd6, + 0xae, 0xad, 0xd3, 0x7f, 0xb9, 0xb9, 0x9c, 0x09, 0xa2, 0xec, 0xa0, 0x56, 0xf2, 0x8c, 0x2b, 0x7d, 0xce, 0xb5, 0x52, + 0x77, 0x3a, 0xde, 0xab, 0x3f, 0x57, 0xcd, 0x27, 0x4b, 0x4b, 0xf7, 0xbd, 0x0e, 0xff, 0xd9, 0x95, 0xb5, 0x14, 0x41, + 0x16, 0x43, 0xea, 0x3d, 0x63, 0x67, 0x25, 0x53, 0x42, 0x01, 0xc4, 0x2f, 0x3c, 0xae, 0x5d, 0x07, 0xcd, 0xbb, 0xd2, + 0xed, 0xa7, 0xab, 0xd6, 0xaa, 0x90, 0xf2, 0x78, 0x63, 0x19, 0x51, 0x98, 0xb8, 0xaa, 0x95, 0x61, 0x9a, 0x37, 0x7f, + 0xef, 0x9e, 0xf4, 0x57, 0xc5, 0xcb, 0x6a, 0x22, 0x8a, 0x98, 0xae, 0x79, 0xbc, 0xb1, 0x7a, 0x37, 0x87, 0xb5, 0x79, + 0xf1, 0x5c, 0x8d, 0x2f, 0x5a, 0xff, 0x5c, 0x75, 0x6c, 0x0d, 0x63, 0x52, 0x39, 0xcf, 0x3b, 0xbf, 0x29, 0x29, 0x8d, + 0xb4, 0x8c, 0x36, 0x4e, 0x8a, 0x99, 0x0a, 0x2f, 0x57, 0xef, 0x54, 0x27, 0xaa, 0x10, 0x19, 0x1c, 0x3c, 0x23, 0xb8, + 0xbf, 0xfd, 0xf3, 0x51, 0x59, 0xb7, 0xb6, 0x8d, 0xe5, 0x8d, 0xbc, 0x92, 0x68, 0xfc, 0x2e, 0x96, 0xcb, 0x16, 0xe6, + 0x5b, 0xfb, 0xa6, 0x29, 0x97, 0xb5, 0x89, 0xa4, 0x8e, 0xd2, 0x27, 0xc5, 0x65, 0xa4, 0x2a, 0xbd, 0x4f, 0x40, 0xa2, + 0x97, 0x46, 0xfa, 0x0c, 0x23, 0xa5, 0x1e, 0xc9, 0x8e, 0x10, 0x21, 0x40, 0x80, 0x66, 0xe7, 0xaa, 0xbd, 0x4c, 0x97, + 0x0c, 0xce, 0xc8, 0xa4, 0x40, 0x9f, 0x61, 0x76, 0x35, 0x17, 0x09, 0xc1, 0x19, 0xa1, 0x03, 0xe9, 0x26, 0x63, 0x25, + 0xf8, 0x67, 0xa4, 0x1a, 0x35, 0x6d, 0xa6, 0xae, 0xb1, 0xf3, 0xb5, 0xb0, 0xe6, 0x87, 0x0e, 0xd9, 0xc5, 0x89, 0x45, + 0x89, 0xbe, 0x70, 0x24, 0x66, 0xe9, 0x49, 0x5d, 0x69, 0x0d, 0xdd, 0x85, 0x5b, 0x5c, 0xef, 0x5c, 0x76, 0xc9, 0x2f, + 0xe3, 0x4d, 0x2b, 0xd2, 0x1c, 0x53, 0x74, 0xf9, 0x26, 0x58, 0x0b, 0x70, 0xa0, 0xcc, 0xcb, 0x57, 0x3d, 0x02, 0x57, + 0x7e, 0x80, 0x8b, 0xe8, 0x65, 0x3e, 0x82, 0x08, 0xce, 0x4d, 0x95, 0x16, 0x5a, 0x98, 0x3d, 0x02, 0x3c, 0xd6, 0x6b, + 0xfe, 0x14, 0xfa, 0x99, 0x29, 0x5e, 0x0a, 0x27, 0xcf, 0x5a, 0xa3, 0x76, 0x0f, 0x31, 0xf8, 0x94, 0xac, 0xd6, 0xc4, + 0x22, 0xa7, 0x71, 0x9d, 0x53, 0x8f, 0x8f, 0x66, 0xcb, 0x7c, 0x90, 0x98, 0x15, 0xc0, 0xe4, 0x34, 0xae, 0x51, 0xe2, + 0x6d, 0xa6, 0xaa, 0x76, 0x46, 0x39, 0x8d, 0x2f, 0xc4, 0x90, 0x4c, 0x52, 0x31, 0xdf, 0x3e, 0x90, 0x51, 0x86, 0xc4, + 0x45, 0xc9, 0xad, 0xd5, 0x14, 0xa7, 0xad, 0x79, 0x43, 0x52, 0x7e, 0xc1, 0x28, 0xeb, 0xe6, 0xef, 0x52, 0x5f, 0xef, + 0xfe, 0x28, 0xa6, 0x4b, 0x8f, 0xab, 0xc3, 0x9b, 0x79, 0x75, 0x34, 0x91, 0x9e, 0xe6, 0xd4, 0x20, 0xf1, 0x5b, 0x0b, + 0xfe, 0x98, 0x1f, 0x2f, 0x35, 0xa6, 0x1a, 0x9a, 0xf8, 0xc8, 0x66, 0x8b, 0x2e, 0x2b, 0xbc, 0x71, 0x6e, 0x85, 0x2f, + 0xb5, 0x29, 0x16, 0xe3, 0xb3, 0xcf, 0x3b, 0x0d, 0xae, 0xa3, 0x78, 0x0f, 0x87, 0xd4, 0xd5, 0x8b, 0xa2, 0xa5, 0x3f, + 0x36, 0xfb, 0x3c, 0x8e, 0xf8, 0xc3, 0x9b, 0xfd, 0xb0, 0x04, 0xe6, 0xee, 0xd0, 0x4a, 0x8b, 0x03, 0x69, 0x2b, 0x39, + 0x5a, 0xef, 0xda, 0x7e, 0x8a, 0xd6, 0x44, 0x56, 0x63, 0x53, 0x41, 0xa9, 0x5e, 0x90, 0xff, 0xef, 0x6d, 0x6c, 0x55, + 0x32, 0x55, 0x3a, 0xe8, 0x3d, 0x24, 0xbd, 0x34, 0xf4, 0x15, 0x7d, 0xee, 0xe9, 0xb1, 0xde, 0xa9, 0x44, 0xbc, 0x8b, + 0xcb, 0x9c, 0x61, 0x36, 0x1b, 0xe6, 0xe6, 0x11, 0xbd, 0x95, 0x5e, 0xb1, 0xdb, 0x98, 0xf4, 0x34, 0x88, 0x65, 0x79, + 0x99, 0x53, 0xf7, 0x39, 0x09, 0x24, 0xfe, 0x39, 0x3c, 0x00, 0xff, 0xa4, 0x6b, 0xd0, 0x1c, 0x49, 0xe5, 0x72, 0x53, + 0xaf, 0x43, 0xbc, 0x6b, 0x77, 0x3c, 0x16, 0xe9, 0xeb, 0x26, 0x1a, 0xdf, 0xd0, 0x0d, 0xa5, 0xa8, 0xa9, 0x8c, 0x3a, + 0x8e, 0x0c, 0x97, 0x8c, 0xbc, 0x59, 0x91, 0x6b, 0xbf, 0x02, 0x79, 0x55, 0x00, 0x21, 0x48, 0x6b, 0x11, 0x4d, 0x4c, + 0xf6, 0x57, 0x43, 0xcd, 0x51, 0x9a, 0xd9, 0x26, 0x7f, 0xda, 0xc4, 0xee, 0xba, 0x05, 0xdc, 0xad, 0x1c, 0xa2, 0x8b, + 0xed, 0x31, 0x0f, 0x79, 0x04, 0xa3, 0x2d, 0x24, 0x0a, 0x59, 0x15, 0xa2, 0x85, 0xd3, 0xfc, 0x49, 0x3e, 0x55, 0x9e, + 0x02, 0x3c, 0x44, 0x41, 0x13, 0x96, 0xb2, 0x9b, 0xee, 0x4b, 0xb2, 0x74, 0xf4, 0x3c, 0x82, 0x0f, 0x50, 0x09, 0x0e, + 0xd0, 0x45, 0xce, 0xeb, 0xee, 0xc5, 0xb6, 0x11, 0xd9, 0xc8, 0xd6, 0x75, 0x4f, 0x07, 0x59, 0x6e, 0x2d, 0x2d, 0xfc, + 0xef, 0x8f, 0xbd, 0xaf, 0xee, 0x82, 0x1d, 0x60, 0x28, 0xef, 0x3e, 0x84, 0x16, 0xee, 0x38, 0xd4, 0xea, 0xc5, 0x8a, + 0x12, 0x05, 0x4f, 0x22, 0xf3, 0xc7, 0x4a, 0x76, 0xba, 0xc7, 0x56, 0x24, 0xde, 0x53, 0x37, 0xa8, 0xdb, 0xe5, 0x56, + 0x5d, 0x35, 0x7b, 0xb9, 0x2a, 0xec, 0x3f, 0x1b, 0xfa, 0xd1, 0x54, 0xc1, 0x07, 0x4c, 0x2f, 0x6e, 0x23, 0x2e, 0x0a, + 0x85, 0x35, 0x72, 0xfe, 0x01, 0x8c, 0xca, 0x9a, 0x17, 0x6e, 0x52, 0x2c, 0x83, 0xcb, 0xd0, 0x28, 0xee, 0xc4, 0x2d, + 0x86, 0x1a, 0x0f, 0x06, 0x3d, 0x0b, 0x4b, 0x90, 0x46, 0xf7, 0xe9, 0x3d, 0xce, 0x70, 0x12, 0xa4, 0xd5, 0xe7, 0xcd, + 0x09, 0x72, 0x8d, 0x77, 0x52, 0x6b, 0x44, 0x22, 0xcd, 0x1e, 0x47, 0x65, 0x6d, 0xf8, 0x18, 0xa6, 0xd1, 0x39, 0xa0, + 0xa8, 0x4d, 0x85, 0xad, 0x76, 0x8a, 0x50, 0xaa, 0xe3, 0x20, 0xb0, 0x69, 0xe9, 0xe3, 0x24, 0x2d, 0xe2, 0x40, 0x4f, + 0x25, 0x78, 0x5e, 0xd2, 0xfc, 0x96, 0x8a, 0xbc, 0x9f, 0x77, 0x82, 0x66, 0xfa, 0xbd, 0x82, 0x48, 0x79, 0xac, 0x44, + 0x1a, 0x46, 0x1d, 0x0c, 0x76, 0x6c, 0xc3, 0xab, 0x03, 0x18, 0xcf, 0x91, 0x4a, 0x46, 0x0d, 0x5c, 0xb9, 0xe2, 0xee, + 0x4b, 0x9b, 0x32, 0xe5, 0xda, 0x2a, 0xfc, 0xc8, 0x7c, 0xc9, 0x10, 0x2b, 0x5f, 0x35, 0x43, 0x89, 0xab, 0xd4, 0xb0, + 0xf6, 0x8b, 0xa9, 0x9b, 0x58, 0x5b, 0xc8, 0xe7, 0x8b, 0xbf, 0x46, 0x87, 0xb0, 0x0f, 0x20, 0xab, 0x9f, 0x2e, 0xc4, + 0x94, 0x5c, 0xc2, 0x04, 0x39, 0x57, 0x8c, 0x89, 0x77, 0x93, 0xc9, 0xa5, 0x3f, 0xcd, 0x16, 0xd8, 0x67, 0xd3, 0x4a, + 0xba, 0x5f, 0x92, 0x42, 0xfc, 0x1e, 0x0f, 0x1a, 0xd2, 0x13, 0x84, 0x98, 0x3d, 0x05, 0x8f, 0x6e, 0x56, 0x6e, 0xd4, + 0x1b, 0x49, 0xd0, 0x8e, 0xad, 0xd8, 0x02, 0x24, 0x38, 0xa0, 0x9e, 0xa8, 0xf1, 0x7d, 0xf0, 0x52, 0xe5, 0x97, 0x2f, + 0x0f, 0x11, 0x6a, 0x06, 0xe3, 0x89, 0xa4, 0x19, 0x3b, 0x54, 0x24, 0xf3, 0x15, 0x34, 0xf3, 0xe1, 0xae, 0xa7, 0x23, + 0xde, 0xec, 0xd0, 0x2b, 0x6d, 0xdc, 0xba, 0x27, 0xba, 0xb8, 0x22, 0x61, 0x68, 0xf5, 0xf1, 0xa0, 0xf2, 0xfe, 0x7c, + 0x39, 0x94, 0x57, 0xb6, 0xf2, 0x83, 0x70, 0x98, 0xb5, 0x3b, 0x78, 0xbe, 0x8e, 0x8c, 0x0f, 0x33, 0x92, 0xb3, 0x0c, + 0x16, 0x81, 0x07, 0x73, 0x96, 0xa2, 0x85, 0x6f, 0xca, 0x32, 0x1b, 0x64, 0x6a, 0xb4, 0x80, 0xc5, 0x8b, 0xfc, 0x1b, + 0x1b, 0x5f, 0x96, 0xd9, 0x58, 0xc1, 0xec, 0x75, 0x20, 0x3b, 0x25, 0x90, 0x98, 0xa3, 0xda, 0x9d, 0x0d, 0xa8, 0xa2, + 0x87, 0x27, 0x00, 0x57, 0xf0, 0x87, 0xc7, 0x2c, 0xd0, 0x39, 0x35, 0xce, 0xd7, 0xb0, 0x56, 0x1e, 0x35, 0x36, 0x59, + 0xd7, 0x44, 0x50, 0xa4, 0x16, 0xab, 0xd0, 0x4b, 0x92, 0x48, 0x1d, 0xaa, 0xfc, 0x8f, 0x2f, 0x9c, 0x53, 0x73, 0xef, + 0x68, 0xeb, 0x31, 0xd7, 0x13, 0xd2, 0x56, 0x51, 0x93, 0x33, 0x3d, 0x2e, 0xa1, 0xa0, 0xfc, 0x9c, 0x0a, 0x95, 0xe2, + 0xcb, 0x74, 0xe7, 0x66, 0x55, 0xc1, 0x00, 0x6a, 0x06, 0x30, 0xfa, 0x51, 0x40, 0x46, 0x6a, 0xfc, 0x78, 0xa2, 0x5e, + 0xf7, 0x31, 0x37, 0x74, 0xd0, 0xe2, 0x4c, 0x37, 0xb0, 0x47, 0xb2, 0x1d, 0x8e, 0x6a, 0x80, 0xf2, 0x21, 0x9e, 0x04, + 0x9e, 0x22, 0x9a, 0xa4, 0x59, 0x5f, 0xf1, 0xb7, 0xe9, 0xdc, 0xf6, 0x64, 0x1d, 0x00, 0x2d, 0x2c, 0x98, 0x41, 0xb3, + 0x49, 0xdf, 0x4b, 0xd0, 0x80, 0x1f, 0xc6, 0xce, 0x30, 0xdf, 0x3b, 0xa1, 0xf6, 0xce, 0x0e, 0xbd, 0x9e, 0x7d, 0xe5, + 0x9c, 0x70, 0x3e, 0x53, 0x2f, 0xc6, 0x51, 0xd8, 0x45, 0x9d, 0xc5, 0x93, 0x3f, 0x7c, 0xa6, 0xc2, 0x78, 0x4c, 0xc4, + 0x45, 0x2c, 0x35, 0xb8, 0x20, 0x89, 0x2d, 0x9b, 0xcd, 0x32, 0x0e, 0x7e, 0x26, 0xc3, 0x41, 0xc6, 0x04, 0x2f, 0x27, + 0xf4, 0xfe, 0x96, 0x48, 0x08, 0xb2, 0x21, 0x94, 0x4c, 0xd3, 0x90, 0x1a, 0xaf, 0x36, 0x97, 0x71, 0x99, 0xd1, 0x25, + 0xe3, 0xff, 0x66, 0x17, 0x14, 0xea, 0xb5, 0xa2, 0xe0, 0xfb, 0x2d, 0xdc, 0xf6, 0x1a, 0x9d, 0xb1, 0x67, 0xc8, 0xf4, + 0xa1, 0x39, 0x4c, 0x19, 0x29, 0x0c, 0x77, 0xed, 0x29, 0x48, 0x90, 0x99, 0x97, 0xe1, 0xfd, 0x86, 0xfd, 0x36, 0x60, + 0x0a, 0x1e, 0xdf, 0xfb, 0x66, 0x05, 0xd8, 0x1c, 0x69, 0xa8, 0x7b, 0xee, 0x29, 0xa0, 0x1c, 0xe6, 0xc2, 0xc3, 0x1c, + 0xba, 0x42, 0xb5, 0x0f, 0xb9, 0xab, 0xa7, 0x7a, 0x15, 0x0b, 0xcb, 0xc1, 0xa6, 0x6e, 0x54, 0x9b, 0x84, 0xea, 0xb8, + 0x5c, 0x03, 0xd2, 0x9e, 0xd0, 0x0c, 0xb4, 0x1e, 0x46, 0x54, 0xeb, 0x64, 0x97, 0xde, 0x4a, 0x30, 0xba, 0x24, 0x91, + 0x06, 0x26, 0xcb, 0x9c, 0xd4, 0x00, 0xa6, 0x45, 0x98, 0x03, 0xbf, 0x23, 0x39, 0xae, 0x91, 0x80, 0xce, 0x71, 0xd8, + 0x35, 0xac, 0x26, 0xa5, 0xf3, 0x5c, 0xb5, 0x24, 0x15, 0xa4, 0x22, 0x42, 0x25, 0x53, 0x25, 0xa5, 0x63, 0xc2, 0x39, + 0xae, 0x06, 0x24, 0xc3, 0x94, 0x0a, 0x6a, 0x6f, 0xa3, 0x52, 0x1a, 0xcb, 0x59, 0x18, 0x3e, 0x71, 0xf9, 0x33, 0xaa, + 0xf9, 0xb2, 0x65, 0x23, 0x89, 0xec, 0x35, 0xd3, 0xc5, 0x82, 0x3b, 0xf3, 0x27, 0x70, 0x07, 0xbe, 0xfb, 0x8a, 0x9a, + 0xf2, 0xbe, 0x3c, 0x18, 0x25, 0x26, 0x32, 0x7e, 0x4d, 0xf5, 0x15, 0xcc, 0x65, 0x3e, 0x43, 0x28, 0xd3, 0x6f, 0x3d, + 0x56, 0x67, 0x0b, 0x61, 0x53, 0x49, 0xec, 0xfe, 0xfd, 0xe4, 0x87, 0x02, 0x5e, 0xf0, 0x43, 0x8f, 0xcf, 0x56, 0x13, + 0x04, 0x89, 0x45, 0xb3, 0x0a, 0x7b, 0x8b, 0x9c, 0x18, 0x40, 0x54, 0xf6, 0x68, 0x6e, 0x2f, 0xa9, 0xa1, 0x23, 0x52, + 0x8f, 0x3b, 0x27, 0xac, 0xec, 0x6d, 0x4b, 0x9e, 0xbd, 0x5a, 0xd5, 0x53, 0xaa, 0x63, 0xc2, 0x80, 0x9b, 0xbf, 0xf1, + 0x75, 0x6e, 0xeb, 0xbb, 0x1b, 0x30, 0xd8, 0x12, 0xed, 0xc7, 0x91, 0x22, 0x80, 0x9d, 0x60, 0x8a, 0x43, 0xce, 0xf9, + 0xf1, 0xa6, 0x7a, 0xf9, 0xbf, 0x27, 0x47, 0x15, 0xae, 0xcf, 0x11, 0xb8, 0xc4, 0xe8, 0x74, 0x33, 0x76, 0xee, 0xee, + 0xa8, 0xf4, 0x0d, 0x1f, 0x80, 0x5d, 0x67, 0x10, 0xf4, 0x90, 0x7b, 0x12, 0xde, 0x52, 0x2a, 0x9c, 0xf6, 0x4d, 0x67, + 0xa4, 0xc7, 0xa2, 0xe5, 0x43, 0x78, 0x6c, 0x77, 0x10, 0xac, 0x67, 0xcb, 0xb2, 0xa0, 0xa9, 0x04, 0x68, 0xa6, 0x18, + 0xe0, 0xc8, 0x43, 0xec, 0x1c, 0xc9, 0xac, 0x1c, 0xe3, 0x6e, 0x8e, 0xf7, 0x32, 0x88, 0x0e, 0xd1, 0x11, 0x4f, 0xa5, + 0x25, 0xb2, 0x8c, 0x6d, 0xa9, 0xc2, 0xb5, 0x4f, 0x71, 0x5a, 0xd8, 0xa2, 0xab, 0xca, 0x44, 0xbf, 0xfc, 0x08, 0xc4, + 0xd3, 0x37, 0x7a, 0x5e, 0xbb, 0xd9, 0x24, 0xb2, 0x37, 0x74, 0xb5, 0xfc, 0x92, 0x5b, 0x94, 0x56, 0xae, 0xc6, 0x00, + 0x2b, 0xf6, 0x3a, 0xef, 0x09, 0x84, 0x33, 0x25, 0x0e, 0xb7, 0xf9, 0x9d, 0x61, 0xb6, 0xb4, 0xb1, 0xba, 0x19, 0x9d, + 0x62, 0xdc, 0xd6, 0xdb, 0xfd, 0x40, 0x67, 0x37, 0x24, 0x7c, 0x78, 0xe3, 0xfb, 0xd0, 0x03, 0xa9, 0x24, 0xb8, 0xe2, + 0xee, 0xca, 0x7b, 0x0b, 0xc2, 0xec, 0x81, 0x9c, 0x3e, 0x7a, 0x42, 0x82, 0x5e, 0xc0, 0xfe, 0x7c, 0x1e, 0x1e, 0xf3, + 0x92, 0x38, 0x36, 0xca, 0xc7, 0x1f, 0xd6, 0x58, 0xe1, 0x96, 0xe8, 0x70, 0x89, 0x48, 0xdf, 0xc3, 0xe0, 0xc5, 0x13, + 0x86, 0xa4, 0xea, 0x7f, 0xbc, 0x91, 0x50, 0xc5, 0x33, 0x85, 0xce, 0xed, 0xb4, 0x39, 0x27, 0x88, 0xe5, 0xce, 0x55, + 0x66, 0xaf, 0x1d, 0x85, 0xbd, 0xe3, 0xea, 0x96, 0x74, 0x5f, 0xf6, 0x95, 0x9a, 0x5b, 0x8d, 0x48, 0xb0, 0x91, 0xe1, + 0x79, 0x6e, 0xf5, 0x22, 0xb3, 0x43, 0xd6, 0x45, 0x0e, 0xb0, 0xe9, 0x4c, 0x16, 0x47, 0xed, 0xcd, 0xe8, 0x8b, 0xea, + 0x8a, 0xed, 0xaa, 0x6a, 0x95, 0xc6, 0x25, 0x1d, 0xb4, 0xe6, 0x54, 0xc9, 0x0f, 0xc0, 0x36, 0x22, 0x7f, 0xa7, 0x47, + 0x9d, 0xa9, 0x87, 0x4a, 0x39, 0xad, 0x75, 0x20, 0x8c, 0x87, 0x91, 0xde, 0xcf, 0xc0, 0x40, 0x51, 0x09, 0x6c, 0xb7, + 0x43, 0xe7, 0xa7, 0x5b, 0x93, 0x92, 0x91, 0x53, 0x50, 0x52, 0x56, 0x03, 0xd3, 0x44, 0x91, 0x75, 0x9e, 0x63, 0xf6, + 0x77, 0xc7, 0xd3, 0x9f, 0x3b, 0x0e, 0x1a, 0x31, 0xb3, 0x0b, 0x63, 0xff, 0xb8, 0x77, 0x4d, 0x36, 0xa4, 0x70, 0xea, + 0xc0, 0x24, 0xce, 0x92, 0xb4, 0xfe, 0x7d, 0xad, 0x99, 0xfe, 0xba, 0xe9, 0x7a, 0x09, 0x1f, 0xe8, 0xe1, 0xd8, 0x6e, + 0xb5, 0xf9, 0xa1, 0x7c, 0x60, 0x25, 0xbe, 0xf0, 0xdb, 0x35, 0x1d, 0xbe, 0x0c, 0x3d, 0xf7, 0x39, 0xcc, 0x61, 0x6d, + 0xc5, 0xde, 0x48, 0xa6, 0x05, 0x81, 0xde, 0x6e, 0x77, 0x12, 0xc6, 0x80, 0xfb, 0x7a, 0x8e, 0xa8, 0x7c, 0xe6, 0x72, + 0xf4, 0x4c, 0xa2, 0x04, 0xa6, 0xa3, 0xc1, 0xa3, 0x16, 0xa0, 0xe2, 0x13, 0x8b, 0xd3, 0xe1, 0x01, 0x36, 0x38, 0xb8, + 0x3b, 0x8c, 0xd1, 0x8f, 0x75, 0xf7, 0x6d, 0xea, 0xb3, 0x6c, 0xf8, 0x1a, 0x8e, 0x45, 0x5d, 0xfe, 0x70, 0x55, 0x1b, + 0xc7, 0xa2, 0xc7, 0xea, 0x2a, 0x3e, 0x1a, 0x17, 0xf5, 0x06, 0x43, 0xac, 0xce, 0x03, 0x1c, 0x55, 0xa4, 0x6c, 0xce, + 0x6c, 0xa1, 0x24, 0x81, 0xea, 0xad, 0xd5, 0xfc, 0x32, 0xb0, 0x5b, 0x83, 0x0d, 0xd1, 0xfc, 0x6c, 0xbd, 0x87, 0xef, + 0xe2, 0x27, 0x9f, 0x6d, 0xc9, 0x7c, 0x9b, 0x9d, 0x00, 0x77, 0x96, 0x5d, 0x79, 0x92, 0xd5, 0x8a, 0x77, 0x5b, 0x5f, + 0xbc, 0xef, 0x5f, 0x58, 0x2f, 0x84, 0x84, 0xf3, 0x4b, 0x7a, 0xbb, 0x96, 0x43, 0x1a, 0xc4, 0xf6, 0xaf, 0x26, 0x90, + 0x7f, 0x4a, 0x33, 0x77, 0xfe, 0x58, 0x19, 0x82, 0x63, 0x84, 0x1a, 0x6f, 0x09, 0x16, 0x5c, 0x7a, 0x45, 0x4a, 0xb1, + 0xcd, 0x6a, 0xa7, 0x95, 0x8c, 0xb5, 0xe6, 0xbe, 0xd2, 0x96, 0xb4, 0xca, 0x9d, 0x55, 0x40, 0x5c, 0x5d, 0x9a, 0xf8, + 0x50, 0x60, 0x35, 0x7b, 0x52, 0x96, 0xa4, 0x50, 0x1a, 0x2f, 0xfe, 0x91, 0x78, 0x47, 0x40, 0xe5, 0xea, 0x25, 0x42, + 0x30, 0xae, 0xbf, 0xef, 0xec, 0x2c, 0x3b, 0xcd, 0x1e, 0x32, 0xd5, 0x23, 0x2f, 0x2f, 0xc3, 0x39, 0x8a, 0x52, 0xa5, + 0xf1, 0x1d, 0x9c, 0x71, 0x23, 0x46, 0xbd, 0x7b, 0xf6, 0x14, 0x21, 0xef, 0xc8, 0x6f, 0x64, 0x92, 0xc3, 0x30, 0xef, + 0xbe, 0x3a, 0x19, 0x91, 0xe6, 0xf6, 0x0e, 0xe8, 0x62, 0x93, 0x29, 0xeb, 0x2c, 0xd8, 0x92, 0x0a, 0x12, 0x09, 0xd1, + 0xed, 0x90, 0x90, 0xbd, 0xb4, 0x6f, 0x48, 0x51, 0x54, 0xa7, 0x7a, 0xc8, 0x50, 0x4f, 0x3b, 0x7e, 0x5c, 0x47, 0x4c, + 0xc7, 0xda, 0x22, 0x1d, 0x91, 0x0c, 0x20, 0x18, 0x33, 0x5e, 0x42, 0xa6, 0x5a, 0x33, 0xbc, 0x56, 0x13, 0x4f, 0x19, + 0xdd, 0x59, 0x0f, 0x0c, 0x13, 0xa9, 0x20, 0x76, 0xde, 0xd7, 0x24, 0x52, 0x76, 0xeb, 0xc5, 0x67, 0xa5, 0x0c, 0xcb, + 0x7b, 0x78, 0xd6, 0xb5, 0xa7, 0x6c, 0x52, 0x06, 0x24, 0x96, 0xfb, 0x95, 0x8d, 0x5f, 0xeb, 0xe8, 0x4a, 0x9e, 0xd1, + 0xce, 0x03, 0x00, 0xa6, 0x96, 0xf8, 0x7d, 0xea, 0x32, 0x5f, 0xba, 0xd5, 0x8b, 0xed, 0x35, 0xba, 0x05, 0xb8, 0xf6, + 0xa8, 0x66, 0x9e, 0xf6, 0x16, 0xbb, 0xa7, 0x42, 0x07, 0x74, 0xd5, 0x30, 0x5b, 0xfc, 0xe5, 0x8d, 0x0f, 0xb7, 0xc4, + 0xbd, 0x3a, 0x95, 0xe8, 0x63, 0x7e, 0x2d, 0x2e, 0xfc, 0xa7, 0xdc, 0x91, 0x80, 0xd1, 0x31, 0x3e, 0x29, 0xa4, 0x0d, + 0xab, 0x22, 0x64, 0x42, 0x75, 0xbf, 0x38, 0x4d, 0xe0, 0x00, 0x03, 0xd3, 0xb9, 0xc9, 0x62, 0x96, 0xee, 0xae, 0x9c, + 0xea, 0x3e, 0x18, 0xc0, 0xaa, 0x76, 0xda, 0x9c, 0x7a, 0xea, 0x6e, 0x43, 0xeb, 0x18, 0x17, 0xdf, 0x42, 0x4d, 0x86, + 0xb0, 0xb5, 0x5e, 0xa8, 0x48, 0xd3, 0xbc, 0xc5, 0xca, 0x9f, 0x64, 0xdb, 0x1b, 0x60, 0xe8, 0x42, 0x62, 0x6b, 0x3e, + 0x28, 0x41, 0x7c, 0x50, 0x17, 0xc2, 0xbe, 0xa3, 0x81, 0x68, 0x71, 0x86, 0x75, 0x93, 0x2a, 0xd3, 0x7e, 0x46, 0x8e, + 0x26, 0xd4, 0xfa, 0x3e, 0xf6, 0xcf, 0xba, 0x73, 0xfa, 0x57, 0x24, 0xb5, 0x4c, 0xd3, 0x1c, 0xc9, 0xe8, 0x44, 0xd8, + 0xd8, 0x60, 0x20, 0x8d, 0x11, 0x2f, 0x3d, 0xfd, 0x9c, 0xbb, 0x75, 0xcd, 0x28, 0xb0, 0x7e, 0x83, 0xf1, 0x7a, 0xe0, + 0xe4, 0x9a, 0x5c, 0x04, 0x7a, 0x26, 0x46, 0x59, 0x0f, 0xa9, 0x67, 0x5e, 0x2f, 0xd5, 0xfb, 0x9c, 0x8b, 0x09, 0x42, + 0x85, 0xd7, 0x1c, 0x87, 0xf4, 0x13, 0xc0, 0xe3, 0x26, 0x5b, 0x24, 0x3f, 0x6a, 0x70, 0x1e, 0xf6, 0x49, 0xac, 0x2c, + 0x0e, 0x2f, 0x68, 0x7a, 0xf6, 0xbc, 0x0a, 0xf3, 0x03, 0xf9, 0xd3, 0xb9, 0x32, 0xc0, 0x18, 0xc9, 0xdd, 0xc4, 0xae, + 0x08, 0x4d, 0x01, 0x1c, 0x2a, 0xb5, 0x8e, 0x83, 0x68, 0x80, 0x39, 0xec, 0xfb, 0x72, 0x4b, 0x94, 0x91, 0x02, 0x58, + 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x25, 0xd9, 0x31, 0xd6, 0x62, 0x64, 0x01, 0x8f, 0x86, 0xab, 0x89, 0xd3, 0xa2, 0xda, + 0x8b, 0x8b, 0x31, 0x31, 0xf0, 0x18, 0xd1, 0x32, 0x69, 0xdc, 0x0c, 0xa6, 0xb9, 0x21, 0xe8, 0x66, 0x87, 0xce, 0xdc, + 0xdc, 0xb6, 0xb3, 0x08, 0x4e, 0x6f, 0x7f, 0x06, 0xce, 0x0f, 0xe2, 0xbe, 0x76, 0x45, 0xc4, 0xfd, 0x2b, 0x19, 0x70, + 0x25, 0x85, 0xe7, 0x6c, 0x82, 0xa0, 0x1f, 0xad, 0x7d, 0xa6, 0x41, 0x3c, 0x63, 0xcf, 0xa5, 0x4e, 0x05, 0x0c, 0xfe, + 0xa2, 0x11, 0xaf, 0x53, 0x4f, 0x4c, 0x87, 0x45, 0xf4, 0x3d, 0xd1, 0x6c, 0xa0, 0x31, 0x32, 0xdd, 0x6d, 0xef, 0x9a, + 0x21, 0x44, 0x9f, 0x98, 0x52, 0x96, 0x08, 0x80, 0xf3, 0x2f, 0x2b, 0x84, 0xfb, 0xb7, 0x82, 0x84, 0x05, 0x92, 0xe7, + 0x6a, 0xd7, 0xc4, 0x0d, 0xb0, 0x56, 0xcb, 0x19, 0x77, 0x24, 0x82, 0xd9, 0x98, 0xcb, 0x4c, 0xf4, 0x48, 0x12, 0x67, + 0x90, 0xca, 0x66, 0x5b, 0xc3, 0xdc, 0xdb, 0x06, 0x33, 0x21, 0xca, 0x11, 0x0c, 0xde, 0xbd, 0x85, 0x0d, 0x26, 0xb5, + 0x29, 0x25, 0x4e, 0x43, 0x35, 0x24, 0xf9, 0xb2, 0x17, 0xdb, 0xd5, 0x9d, 0x74, 0x1b, 0x68, 0x32, 0x7f, 0xf7, 0xc5, + 0xc1, 0x7d, 0x64, 0xfb, 0xbc, 0x55, 0xec, 0x85, 0x49, 0xb5, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, 0xb8, 0x46, 0x2f, + 0x4d, 0x5f, 0xb5, 0xdf, 0x58, 0x9f, 0xe7, 0x20, 0x47, 0x45, 0x9f, 0xf7, 0x97, 0x0b, 0x08, 0x9a, 0xba, 0x8c, 0x3b, + 0x01, 0x2e, 0x18, 0x51, 0x7a, 0xae, 0x33, 0x02, 0x5b, 0xc2, 0x3c, 0x2d, 0x9b, 0x2b, 0xbc, 0x3c, 0x3f, 0x38, 0x4d, + 0xa8, 0x54, 0xe8, 0x35, 0xbf, 0xaf, 0xde, 0xab, 0xb5, 0xc7, 0xe5, 0x61, 0xff, 0xbd, 0x48, 0xce, 0x40, 0x91, 0x76, + 0x46, 0x7e, 0xb4, 0xac, 0x83, 0x78, 0xdb, 0x9a, 0xbe, 0xbd, 0x96, 0x3f, 0x4c, 0x48, 0xa6, 0xca, 0x6d, 0x08, 0x16, + 0x93, 0xbe, 0xdf, 0x65, 0xf0, 0x93, 0x6c, 0x45, 0x4a, 0x0c, 0x34, 0x8a, 0x5d, 0xc6, 0x3c, 0xd9, 0xa4, 0x5e, 0x37, + 0x15, 0xdd, 0xf8, 0x50, 0xcf, 0x76, 0x18, 0x6f, 0xe0, 0xb1, 0x9e, 0x7c, 0x34, 0x77, 0xaa, 0xee, 0x5a, 0xf8, 0xba, + 0xba, 0x13, 0xda, 0xed, 0xed, 0xeb, 0x45, 0x69, 0x5e, 0x77, 0x27, 0xda, 0x3a, 0x45, 0xcf, 0xeb, 0xff, 0xeb, 0x39, + 0xe3, 0xe0, 0x6d, 0x0a, 0xef, 0x05, 0xf8, 0x76, 0x7c, 0xf6, 0x3c, 0x03, 0x8a, 0x96, 0x59, 0xb4, 0x32, 0xb9, 0xc6, + 0x39, 0x0e, 0x18, 0x55, 0xa8, 0xf3, 0x9a, 0xa9, 0x36, 0x4e, 0x6c, 0x58, 0xef, 0x78, 0x79, 0x55, 0x00, 0x71, 0x87, + 0x6b, 0x59, 0x6e, 0xe2, 0xc2, 0xfc, 0xe6, 0x99, 0x12, 0x92, 0xcd, 0x63, 0x6d, 0xd5, 0xe9, 0x77, 0x49, 0x49, 0x0e, + 0x03, 0x6e, 0x73, 0xe9, 0xc3, 0x4d, 0xe5, 0xa1, 0x0b, 0xdd, 0x2e, 0xca, 0x09, 0x22, 0x95, 0xba, 0x13, 0xa8, 0x70, + 0x6c, 0x8b, 0x15, 0x75, 0xa9, 0xed, 0x1b, 0xdf, 0x17, 0xfc, 0xb2, 0x10, 0x7c, 0x63, 0x27, 0x36, 0x31, 0x5b, 0xa9, + 0x66, 0x24, 0xe1, 0x67, 0x10, 0xcc, 0x71, 0xe5, 0x99, 0xda, 0xed, 0xf0, 0x7f, 0x14, 0x4d, 0x45, 0x0a, 0xe8, 0x12, + 0x87, 0x08, 0x99, 0x99, 0x63, 0x8a, 0x1e, 0xac, 0x10, 0x3a, 0x8b, 0x94, 0x0f, 0x76, 0x73, 0xf0, 0x7d, 0xeb, 0xe7, + 0xb6, 0xae, 0xda, 0xe5, 0x5e, 0xd1, 0xd3, 0x34, 0x25, 0x5a, 0x52, 0xa8, 0xa4, 0x91, 0xb5, 0x43, 0x7d, 0xad, 0xaf, + 0xdd, 0x48, 0x41, 0x2d, 0xb2, 0x20, 0x7a, 0x9d, 0xaf, 0x0d, 0x20, 0x4d, 0x2a, 0xfe, 0xc2, 0xbf, 0x7f, 0x16, 0x89, + 0x37, 0xb5, 0x88, 0x86, 0xfa, 0x3a, 0x6d, 0x5d, 0x7d, 0x15, 0x8f, 0x0d, 0xd7, 0x56, 0xfd, 0x18, 0xe5, 0xe6, 0x46, + 0xca, 0xfb, 0x89, 0xf9, 0xf3, 0xaf, 0x36, 0x0d, 0x8d, 0xc0, 0x49, 0xf3, 0xe6, 0x76, 0xee, 0x30, 0xe7, 0x9e, 0x23, + 0x35, 0x1c, 0xb2, 0x6f, 0x40, 0x6e, 0x91, 0x2f, 0xb5, 0x6b, 0x22, 0x71, 0x81, 0xb0, 0x89, 0x60, 0x43, 0xdc, 0x47, + 0xc6, 0x8c, 0x6e, 0x5d, 0xe3, 0xe0, 0xdd, 0xa5, 0x4c, 0x9d, 0x96, 0x6a, 0x2e, 0xa7, 0x42, 0x99, 0x49, 0x2a, 0xfa, + 0xd5, 0x46, 0x7f, 0x76, 0xe5, 0x94, 0xb8, 0x0e, 0x2a, 0xbf, 0x8d, 0x38, 0x75, 0x1b, 0xcd, 0xb4, 0xbf, 0x95, 0xaf, + 0x7a, 0x5c, 0xd4, 0x5f, 0xd2, 0xe3, 0xbd, 0xb5, 0x47, 0x6e, 0x4d, 0x2d, 0x3d, 0xe2, 0xfe, 0x6a, 0xbb, 0xaf, 0xf2, + 0x39, 0x0e, 0x22, 0x54, 0x3b, 0x21, 0xc6, 0xa5, 0x88, 0x02, 0x0e, 0xe0, 0x15, 0xf1, 0x5f, 0x90, 0xeb, 0xf1, 0xac, + 0x4e, 0xd1, 0x8f, 0x3d, 0xd0, 0xde, 0x6d, 0x9e, 0x03, 0x4e, 0xa9, 0x72, 0xca, 0xbe, 0x23, 0x6b, 0xb3, 0x2c, 0xd2, + 0xae, 0x77, 0x66, 0xb3, 0xa8, 0x58, 0x11, 0x00, 0xc8, 0xde, 0xe9, 0x53, 0x97, 0x75, 0x28, 0xb7, 0x1b, 0x08, 0xb7, + 0x4a, 0x66, 0xc2, 0x4c, 0x14, 0xfe, 0xba, 0x63, 0xc0, 0x0b, 0x21, 0xce, 0x0d, 0x5f, 0x79, 0x49, 0xe3, 0x44, 0x45, + 0x6c, 0x88, 0x1f, 0x94, 0x07, 0xc7, 0xe1, 0xd6, 0xfe, 0xb0, 0x6d, 0x64, 0x22, 0x87, 0xe8, 0x60, 0x35, 0x4a, 0xf7, + 0xc6, 0x77, 0x44, 0x76, 0x3f, 0xde, 0x5f, 0x6b, 0x89, 0x40, 0x4b, 0xcb, 0xf7, 0x6a, 0x57, 0x13, 0xce, 0x9f, 0xde, + 0x76, 0x15, 0x9b, 0x94, 0x19, 0xc5, 0xb7, 0x54, 0xb6, 0xaf, 0xbe, 0xff, 0x8a, 0x7e, 0x16, 0x25, 0x99, 0xc2, 0xd7, + 0xb2, 0x85, 0xe7, 0xd6, 0x32, 0x23, 0x0d, 0x00, 0x55, 0x24, 0x46, 0x73, 0xc9, 0xd3, 0x2e, 0xe9, 0x30, 0x10, 0x6d, + 0xfc, 0x58, 0x6c, 0x9a, 0x45, 0xa8, 0x28, 0x7b, 0xc0, 0x66, 0xa3, 0x1b, 0x32, 0x08, 0x4f, 0xd0, 0x8b, 0x7f, 0xa5, + 0x03, 0x2f, 0x2a, 0xe7, 0xca, 0xd2, 0xad, 0x2f, 0x6f, 0xeb, 0x6f, 0xd2, 0xf5, 0xa4, 0xd6, 0xbb, 0x32, 0x5c, 0x2c, + 0x68, 0x46, 0xbe, 0xf2, 0x5f, 0x0d, 0xe0, 0x75, 0x48, 0xd3, 0x19, 0x0b, 0x7f, 0x62, 0xea, 0x1e, 0x79, 0x5b, 0x99, + 0xf7, 0xdb, 0x65, 0x73, 0x3e, 0x68, 0x1f, 0xbc, 0xa4, 0xaa, 0x3f, 0xe0, 0xf8, 0xc8, 0x79, 0xb8, 0xbf, 0x8a, 0x69, + 0x6e, 0x45, 0xc1, 0x80, 0xe7, 0xa3, 0x15, 0x4d, 0xba, 0xab, 0x47, 0x2b, 0x22, 0x8c, 0x25, 0x4e, 0x2d, 0x6e, 0x75, + 0x21, 0x93, 0xa3, 0xdc, 0x42, 0xdf, 0xc9, 0xcb, 0xdc, 0xe2, 0x3a, 0xda, 0xcb, 0xcc, 0xf4, 0x94, 0x55, 0xf7, 0x1b, + 0xc2, 0xa8, 0x8f, 0xcc, 0x2e, 0x5a, 0x05, 0xa7, 0x95, 0x46, 0xb8, 0xa1, 0x5e, 0x6b, 0x8a, 0x05, 0xce, 0x8d, 0x82, + 0x5a, 0xd5, 0x3b, 0x4f, 0xbb, 0xc6, 0x41, 0xb6, 0x99, 0xd3, 0x8a, 0xd0, 0xed, 0x57, 0xb8, 0xa7, 0xb0, 0xae, 0xf3, + 0xe0, 0x6a, 0x4e, 0x34, 0x38, 0x8d, 0xdb, 0x6d, 0xb3, 0x88, 0x16, 0xb2, 0x8b, 0x15, 0xfd, 0x7a, 0x00, 0xfe, 0x8b, + 0x1d, 0x8a, 0x0f, 0x5b, 0xa9, 0xb1, 0x15, 0x23, 0x2b, 0x34, 0xf5, 0x76, 0x8e, 0x08, 0xff, 0xc2, 0xb7, 0xe4, 0x76, + 0x5b, 0xaa, 0x08, 0x35, 0x75, 0xb3, 0x6a, 0x7b, 0xed, 0x64, 0xbf, 0x34, 0x49, 0xfb, 0x61, 0x9e, 0x9e, 0x10, 0x2a, + 0x51, 0x7b, 0x73, 0x68, 0x88, 0x25, 0xd7, 0x46, 0x9c, 0x1b, 0x4c, 0x48, 0xe3, 0xbf, 0xbf, 0x11, 0x90, 0x13, 0x29, + 0xe9, 0x70, 0x39, 0xf6, 0x2c, 0xc5, 0x48, 0xa2, 0xf9, 0xc8, 0xe0, 0x75, 0x0a, 0x8b, 0xb4, 0x95, 0x27, 0xd7, 0x2d, + 0x75, 0x43, 0xdd, 0x35, 0x7d, 0x92, 0xaa, 0xe3, 0xbc, 0x38, 0xc2, 0xdd, 0xa9, 0x82, 0x46, 0xf5, 0xe6, 0xe4, 0x0c, + 0x49, 0xdb, 0x99, 0x17, 0x42, 0xf2, 0x41, 0xbc, 0x96, 0x44, 0x8a, 0xed, 0x27, 0x59, 0xea, 0x3e, 0xbe, 0x39, 0x88, + 0x0a, 0x84, 0x8b, 0x70, 0x8c, 0xc4, 0xfe, 0x14, 0x63, 0x8a, 0xee, 0x2c, 0x4a, 0x82, 0x4d, 0xd5, 0xc9, 0x19, 0x3a, + 0xd3, 0x7c, 0x02, 0x81, 0x65, 0x37, 0xc8, 0xe8, 0xa0, 0x2e, 0x62, 0x7e, 0xf4, 0xed, 0x10, 0x37, 0xbf, 0xe5, 0xe0, + 0x1a, 0x6d, 0xcf, 0x8c, 0x33, 0xa5, 0xb6, 0xf8, 0xa7, 0x39, 0x5c, 0x9f, 0xc0, 0xec, 0xee, 0x50, 0xc2, 0x89, 0x38, + 0x92, 0x50, 0xaf, 0x3f, 0x57, 0x3f, 0x6c, 0x22, 0x85, 0xce, 0x09, 0xad, 0x0d, 0xb4, 0xf8, 0x34, 0xa7, 0xab, 0x05, + 0x1f, 0xc6, 0x61, 0xc7, 0x90, 0xa9, 0x92, 0xfc, 0x2e, 0xfa, 0xdc, 0xcf, 0x05, 0x18, 0xde, 0x43, 0x5c, 0xe7, 0x7b, + 0x67, 0x47, 0xcd, 0xc2, 0x2d, 0x84, 0xed, 0x4f, 0xa3, 0x84, 0x1c, 0xf4, 0x6b, 0xe5, 0xe7, 0x88, 0x5f, 0x7d, 0xa4, + 0x67, 0xb2, 0xe1, 0x87, 0x43, 0xb4, 0xb8, 0x96, 0xb0, 0x24, 0xc3, 0xe8, 0xfd, 0x8b, 0x57, 0x18, 0xf6, 0x12, 0x18, + 0x3c, 0x83, 0xbd, 0x05, 0x02, 0xe0, 0xf6, 0xe8, 0x27, 0x0c, 0xb5, 0x54, 0x0a, 0xc2, 0xb9, 0xe4, 0x21, 0x41, 0x62, + 0x5c, 0xca, 0xd5, 0xda, 0xa4, 0x4f, 0xc0, 0x5a, 0x3b, 0x4e, 0x1d, 0x34, 0x26, 0x3d, 0xcf, 0x92, 0xe6, 0xcb, 0x98, + 0x3f, 0x0b, 0x14, 0x2c, 0x3f, 0x34, 0x35, 0xdd, 0x83, 0xa0, 0xea, 0xca, 0x18, 0x6b, 0xba, 0xa3, 0x1d, 0x04, 0xef, + 0xaf, 0xd5, 0x33, 0xa2, 0xfc, 0xdd, 0x1a, 0x93, 0x1d, 0x04, 0x85, 0x82, 0x2d, 0x6e, 0xc8, 0xa1, 0x10, 0x62, 0x57, + 0xe3, 0xce, 0xbe, 0x8b, 0x4e, 0x65, 0xa9, 0x99, 0xdc, 0x6e, 0x94, 0x4d, 0x33, 0x4c, 0x98, 0x62, 0x87, 0x56, 0xf2, + 0x05, 0x45, 0x89, 0x5d, 0xbb, 0x5a, 0x94, 0x33, 0xbf, 0xdb, 0xfa, 0x38, 0xb6, 0x50, 0x58, 0xf5, 0x39, 0x98, 0xe5, + 0xc4, 0xb4, 0x6d, 0x97, 0x81, 0xdc, 0xd9, 0x1b, 0x64, 0xaa, 0x29, 0x1b, 0x43, 0x98, 0x77, 0xcc, 0x47, 0xe6, 0xf0, + 0x3d, 0xb2, 0x3b, 0x0f, 0x99, 0xbb, 0xc9, 0x65, 0x2f, 0x3f, 0xeb, 0xf5, 0xcf, 0x1c, 0xa0, 0x90, 0xc6, 0xc0, 0xb1, + 0x79, 0xde, 0x10, 0x6b, 0x99, 0x98, 0x2e, 0x3b, 0x56, 0xba, 0x83, 0x41, 0xc1, 0xeb, 0x1c, 0x28, 0x54, 0xd2, 0x94, + 0x38, 0x71, 0x3d, 0x84, 0x35, 0xa2, 0x1c, 0xde, 0x3b, 0x31, 0xd7, 0xc9, 0x44, 0xb2, 0xf1, 0xaf, 0xf6, 0x3e, 0x5c, + 0xb4, 0x01, 0xfa, 0x78, 0x66, 0xa3, 0x16, 0x16, 0x89, 0x38, 0x85, 0x21, 0x3f, 0xaa, 0x79, 0xac, 0x49, 0xe8, 0x03, + 0x27, 0x03, 0xa9, 0xa0, 0x97, 0x0a, 0xfc, 0x6f, 0x91, 0x9c, 0xb1, 0x72, 0x4a, 0x01, 0x2a, 0xa2, 0xb5, 0x6b, 0xfe, + 0x75, 0xef, 0x7a, 0x4c, 0x82, 0x7a, 0xb5, 0x00, 0x6e, 0x2d, 0x25, 0x92, 0x9f, 0xfb, 0xdb, 0x30, 0x3a, 0xcc, 0x8c, + 0x93, 0xce, 0xf3, 0xea, 0x57, 0x4f, 0x2e, 0x22, 0x99, 0xa2, 0x2d, 0x04, 0x4f, 0x5d, 0x0c, 0x4c, 0xe4, 0x21, 0x9e, + 0x9b, 0x76, 0xd0, 0xa5, 0xc6, 0xa1, 0xfc, 0xcb, 0xae, 0xe3, 0x68, 0x6c, 0x16, 0xe3, 0x04, 0x42, 0x95, 0xea, 0xf2, + 0x3c, 0x73, 0x5d, 0xd6, 0x8b, 0x3d, 0x69, 0xa2, 0xae, 0xac, 0xf4, 0x5b, 0xa8, 0x98, 0x37, 0xba, 0x3a, 0x45, 0x6d, + 0x31, 0xad, 0x93, 0x97, 0x6d, 0x56, 0x66, 0xd5, 0x04, 0x6f, 0x43, 0xb6, 0x11, 0x4e, 0x76, 0xc1, 0x7e, 0x3a, 0xc7, + 0x4b, 0x77, 0x0d, 0x8d, 0x12, 0xbc, 0x84, 0x54, 0xd1, 0xdf, 0x99, 0x16, 0x0e, 0x24, 0x5a, 0x51, 0xb2, 0xf6, 0xa5, + 0xff, 0x66, 0x37, 0x9c, 0xe4, 0x5c, 0x47, 0xef, 0x50, 0x7b, 0x1c, 0x8a, 0x66, 0x3c, 0x26, 0x6b, 0x9c, 0xe7, 0x74, + 0x29, 0x70, 0xc9, 0x92, 0x72, 0xee, 0x05, 0xbb, 0x2b, 0x90, 0xf2, 0xfa, 0xcb, 0x16, 0x09, 0x99, 0x70, 0xfb, 0x3c, + 0x19, 0xb8, 0x8c, 0x09, 0xd2, 0x83, 0xde, 0xf5, 0x03, 0xd5, 0x58, 0xe0, 0xee, 0x97, 0x39, 0xe7, 0x7f, 0xae, 0x48, + 0x92, 0x86, 0x78, 0x68, 0x11, 0x1c, 0xa6, 0xda, 0xaf, 0xc0, 0xad, 0x63, 0xc0, 0xb5, 0x59, 0x99, 0x3e, 0xf8, 0xf5, + 0xf8, 0x40, 0x34, 0x02, 0xff, 0xf9, 0xf8, 0x2b, 0xe2, 0xd0, 0x83, 0x67, 0x2b, 0x42, 0xb2, 0xae, 0x87, 0x8b, 0x34, + 0xff, 0xd5, 0xee, 0x13, 0x80, 0x45, 0xb8, 0x91, 0x74, 0x2c, 0x01, 0x1d, 0xdf, 0x0d, 0x0b, 0xcc, 0x53, 0x60, 0x97, + 0xd1, 0x1f, 0xb3, 0x87, 0x95, 0x6b, 0x1c, 0x2a, 0x4e, 0xb4, 0x85, 0x71, 0xb8, 0x24, 0x58, 0xde, 0xd2, 0xb9, 0x8a, + 0x40, 0x06, 0x07, 0xa4, 0x5e, 0xde, 0x19, 0xc7, 0x23, 0xf7, 0x91, 0x15, 0x1c, 0xf8, 0x66, 0x58, 0xb6, 0x47, 0x06, + 0x1c, 0xea, 0x88, 0x1e, 0xd0, 0xe1, 0xd6, 0x20, 0x43, 0x4d, 0x14, 0x63, 0x0b, 0x3e, 0x3e, 0xaa, 0xc7, 0x0c, 0xf2, + 0x5c, 0x0e, 0xf8, 0xfa, 0xc0, 0xa0, 0xe2, 0x30, 0x81, 0xfc, 0x5d, 0x08, 0x83, 0x3a, 0xec, 0xad, 0x05, 0x80, 0xd2, + 0x27, 0x88, 0xa1, 0x13, 0x87, 0xd4, 0x1b, 0xd0, 0xe4, 0x7b, 0x90, 0xd2, 0x08, 0xfe, 0xa2, 0x22, 0x33, 0x1a, 0x3d, + 0x15, 0xb3, 0x50, 0x18, 0x45, 0x2b, 0x64, 0xa8, 0x4d, 0x88, 0x34, 0x75, 0xf7, 0x96, 0x11, 0xf9, 0xb1, 0x3d, 0xf0, + 0x65, 0x69, 0xaf, 0x45, 0x22, 0x55, 0xce, 0x78, 0x1f, 0x40, 0xa9, 0x39, 0xb8, 0x0a, 0xd4, 0x3d, 0x53, 0x7d, 0x4e, + 0xc5, 0xda, 0xcc, 0xb2, 0x58, 0x78, 0x20, 0x1f, 0xe2, 0x62, 0x7c, 0x15, 0x5d, 0xbe, 0xad, 0x28, 0x9e, 0xc5, 0xdf, + 0xfd, 0xba, 0xe9, 0x43, 0x0a, 0xff, 0x52, 0xf0, 0xd5, 0x59, 0x73, 0xe5, 0x84, 0x75, 0x9e, 0x20, 0x5d, 0x37, 0x18, + 0x74, 0x5b, 0x4b, 0x2c, 0x4f, 0xce, 0xf4, 0xeb, 0x76, 0x31, 0xa5, 0x6a, 0xaa, 0xde, 0xce, 0x03, 0x08, 0xa4, 0xf6, + 0x9d, 0x49, 0x67, 0xd0, 0x2c, 0x24, 0xcb, 0x0c, 0x13, 0xfc, 0xb9, 0xc3, 0x6e, 0x50, 0x91, 0x06, 0x5e, 0xb6, 0x96, + 0x5e, 0xe1, 0x73, 0x3c, 0xae, 0xe8, 0x25, 0xa7, 0xf1, 0xb7, 0x77, 0xa4, 0x3c, 0x6d, 0xfd, 0x54, 0x2e, 0xe7, 0x65, + 0xd1, 0x97, 0xa6, 0x5f, 0xd1, 0x6f, 0x52, 0xb7, 0x3c, 0xee, 0x22, 0x02, 0xe9, 0xff, 0x2a, 0xd7, 0x35, 0x8d, 0xbe, + 0x0a, 0x7b, 0xb1, 0x8b, 0x60, 0xf4, 0xec, 0xb6, 0x6e, 0x0e, 0x39, 0x53, 0x5a, 0x94, 0x1a, 0x0c, 0x4d, 0x3a, 0xfe, + 0x32, 0x0a, 0x4b, 0xd7, 0x94, 0x76, 0xee, 0xa7, 0x3b, 0xbd, 0x54, 0x47, 0x26, 0xfe, 0x6d, 0x2f, 0x7f, 0xc8, 0x3a, + 0x6a, 0x44, 0x17, 0xfe, 0x0f, 0xfe, 0x3c, 0xa2, 0x9c, 0x2f, 0x75, 0x4a, 0xa5, 0x1d, 0xd4, 0x47, 0x55, 0x72, 0x3c, + 0x1d, 0x07, 0xca, 0x68, 0x14, 0xcf, 0xd4, 0xf1, 0xcc, 0x69, 0x26, 0xe8, 0x89, 0x6e, 0x90, 0xac, 0xe5, 0x00, 0x2d, + 0x80, 0x9a, 0x92, 0x11, 0xa7, 0xea, 0x04, 0x37, 0x13, 0xa7, 0xd7, 0x45, 0x27, 0x48, 0x4e, 0x0b, 0xc7, 0xe8, 0x73, + 0x59, 0x0c, 0x51, 0x29, 0xeb, 0xdb, 0xab, 0x23, 0xaa, 0x1e, 0x65, 0xdb, 0xd2, 0xb7, 0x8a, 0x8d, 0x76, 0xa8, 0x83, + 0x15, 0x73, 0x60, 0x97, 0x97, 0xcc, 0xd4, 0x72, 0xe6, 0x60, 0xe6, 0xa7, 0x67, 0xc0, 0x9e, 0x03, 0x66, 0xe7, 0x0c, + 0x31, 0x47, 0x11, 0xaa, 0xc4, 0xd2, 0x18, 0x14, 0x17, 0x76, 0x92, 0x48, 0x7d, 0x3e, 0xef, 0x8e, 0x52, 0x15, 0x73, + 0x6a, 0x2a, 0xaf, 0x07, 0xb0, 0x2d, 0xb1, 0xf2, 0x57, 0x34, 0xa1, 0x1f, 0xe9, 0x16, 0x23, 0xfc, 0x8d, 0x8a, 0xe3, + 0xfc, 0x7e, 0x7e, 0x9b, 0x9a, 0x29, 0x01, 0x13, 0x43, 0x4e, 0x5d, 0x9d, 0x60, 0x5d, 0xa5, 0x98, 0x96, 0xc5, 0x99, + 0x96, 0xe7, 0x7c, 0x36, 0xb6, 0x25, 0xd6, 0x42, 0x38, 0x5b, 0xde, 0xf6, 0xc6, 0x5d, 0x5e, 0x30, 0x26, 0x92, 0x24, + 0x96, 0x6d, 0x5e, 0x4d, 0x07, 0x20, 0xc1, 0x1d, 0x62, 0x9b, 0x7e, 0xc1, 0xb7, 0xa2, 0x88, 0x07, 0xb0, 0x9b, 0xcc, + 0xce, 0x62, 0xab, 0x4c, 0x07, 0xe3, 0xe0, 0x96, 0xff, 0xd5, 0xb6, 0x86, 0x02, 0x21, 0x11, 0x9f, 0x08, 0x70, 0x49, + 0x74, 0x36, 0x83, 0x3a, 0x85, 0x0c, 0x37, 0xf1, 0x9d, 0xa2, 0xc9, 0x77, 0xb4, 0xfa, 0x8e, 0x88, 0xec, 0xdb, 0xab, + 0x88, 0x28, 0x4a, 0xb9, 0x3c, 0x6a, 0xc5, 0x49, 0x8e, 0x68, 0x4e, 0xc6, 0x97, 0x8e, 0xa4, 0x9d, 0x34, 0xe3, 0x4a, + 0x4d, 0x6f, 0x8f, 0xdf, 0x65, 0x10, 0xe9, 0x57, 0xe7, 0xb9, 0x15, 0xc7, 0x79, 0x21, 0x0a, 0xca, 0x07, 0xdc, 0x86, + 0x51, 0x8d, 0x56, 0xbe, 0x99, 0xf3, 0x80, 0x76, 0x66, 0x78, 0x38, 0x9d, 0xb5, 0x6f, 0xb6, 0x2d, 0xf8, 0x72, 0x1c, + 0x0e, 0x63, 0xd3, 0xbe, 0x7f, 0xfe, 0xae, 0x7e, 0x6f, 0xc6, 0x87, 0x57, 0xde, 0x49, 0xea, 0x1d, 0x0f, 0x60, 0xea, + 0xda, 0x98, 0xad, 0x73, 0x70, 0x9e, 0xc6, 0xd8, 0x22, 0xfa, 0x5f, 0xda, 0xc6, 0x67, 0xa5, 0x7f, 0x02, 0xee, 0xc1, + 0x9d, 0x64, 0x59, 0xfa, 0xc5, 0x99, 0x46, 0x8b, 0xfc, 0x89, 0xe5, 0x49, 0xad, 0x1e, 0x74, 0x5c, 0x9a, 0x5c, 0xbc, + 0x42, 0xba, 0x3c, 0x4b, 0xbf, 0x9c, 0x2d, 0xf4, 0x8f, 0xd3, 0x55, 0x00, 0xff, 0x8f, 0x73, 0xa4, 0xb8, 0x3f, 0xa6, + 0xd9, 0x8b, 0x74, 0xe3, 0xfb, 0xb3, 0x9b, 0xd5, 0xeb, 0x82, 0x3d, 0x3a, 0x4f, 0xb6, 0x6c, 0x5d, 0x0b, 0xad, 0xa9, + 0x1b, 0x17, 0xd4, 0x9d, 0xdd, 0x66, 0xed, 0x1b, 0xeb, 0x53, 0x6b, 0xe8, 0xbb, 0x98, 0x48, 0x3f, 0x7f, 0x44, 0x3f, + 0x5d, 0x7b, 0x8a, 0x0b, 0xc3, 0x7e, 0xa7, 0xba, 0x1e, 0x35, 0x33, 0x9d, 0x0a, 0x12, 0x9a, 0x97, 0x3c, 0xdd, 0x37, + 0x39, 0xaf, 0xe5, 0xf8, 0x72, 0xf4, 0x34, 0xa2, 0xa6, 0x7d, 0x47, 0x19, 0xdd, 0x4b, 0x82, 0x31, 0xea, 0x2a, 0x35, + 0x30, 0xfa, 0xe2, 0x55, 0x05, 0x06, 0x01, 0xaa, 0xf3, 0xfa, 0x40, 0x8a, 0xc0, 0xe0, 0xc3, 0x21, 0x8f, 0xe5, 0x06, + 0x03, 0x27, 0x4b, 0xeb, 0x20, 0xf5, 0xf2, 0x20, 0x1c, 0xa9, 0xea, 0xe2, 0x6d, 0x26, 0xa0, 0xc0, 0xeb, 0xa9, 0xfe, + 0x1b, 0xdd, 0x9c, 0x1b, 0xe7, 0x69, 0xc6, 0x87, 0x73, 0x43, 0xe9, 0x52, 0x71, 0xf1, 0xda, 0xae, 0x62, 0x1c, 0x16, + 0xd5, 0x56, 0x25, 0x53, 0x32, 0x65, 0x0e, 0x13, 0xf3, 0x33, 0x41, 0x7a, 0xde, 0xa8, 0x43, 0xee, 0x97, 0x4f, 0xf2, + 0x9a, 0x2e, 0x71, 0x65, 0x92, 0x8d, 0x42, 0xf8, 0x3f, 0x34, 0x55, 0x6b, 0x0e, 0xa4, 0x46, 0xe0, 0x72, 0x70, 0xb5, + 0x54, 0xde, 0xb6, 0xb4, 0x9f, 0x3f, 0x2e, 0xdf, 0xa7, 0xb7, 0x95, 0x24, 0xf9, 0x2f, 0x4d, 0xd8, 0x98, 0xf3, 0xc9, + 0x28, 0xb4, 0x29, 0xc4, 0x0d, 0x4c, 0x45, 0x3b, 0xc6, 0x4f, 0x0a, 0x2f, 0x08, 0xea, 0xf3, 0x0e, 0x45, 0x03, 0xb0, + 0x79, 0x95, 0x8a, 0xdc, 0x19, 0x68, 0x59, 0xa2, 0x6c, 0xdd, 0xe8, 0x6b, 0xc3, 0xf7, 0x38, 0x78, 0xd5, 0x70, 0xeb, + 0xde, 0xcb, 0xa6, 0x0a, 0x94, 0x4d, 0x5b, 0x59, 0xbc, 0x0a, 0x25, 0xcf, 0xd4, 0x4b, 0x9d, 0x2b, 0x69, 0x17, 0x0e, + 0x7e, 0xa6, 0xe2, 0xe8, 0x57, 0x12, 0x81, 0x5d, 0x39, 0xc8, 0x00, 0xc7, 0xed, 0x36, 0xc7, 0x19, 0x02, 0x11, 0x94, + 0x85, 0x56, 0x20, 0xd4, 0x22, 0x55, 0xa7, 0xbe, 0x33, 0x62, 0x35, 0x01, 0xe4, 0x8a, 0xbd, 0x8b, 0x56, 0xc8, 0x9f, + 0x65, 0x06, 0x3a, 0xb0, 0xa3, 0x3d, 0x37, 0x2e, 0xbe, 0x3e, 0x25, 0xe8, 0xd7, 0x12, 0x7b, 0x67, 0x54, 0xc7, 0xc8, + 0x69, 0x3e, 0x3f, 0x58, 0x26, 0xc6, 0x6d, 0x31, 0xde, 0xb6, 0x91, 0x39, 0x81, 0x29, 0x50, 0x89, 0x99, 0xd6, 0xaa, + 0x65, 0x04, 0x39, 0x4c, 0xb2, 0x13, 0x8f, 0x34, 0x19, 0x2b, 0x96, 0xf7, 0x40, 0x60, 0xce, 0x30, 0x6e, 0xd3, 0x98, + 0x55, 0x2b, 0xa4, 0x60, 0x04, 0xc3, 0xd0, 0xf8, 0x60, 0x31, 0x12, 0xe6, 0x95, 0x80, 0x0c, 0x1c, 0x29, 0x52, 0x10, + 0xdf, 0xed, 0x68, 0x7e, 0x30, 0xa5, 0x47, 0x9c, 0xa8, 0x70, 0x8f, 0xca, 0x29, 0xdd, 0x60, 0xa8, 0xe7, 0x82, 0x05, + 0x4c, 0x31, 0xc5, 0x46, 0x72, 0xa0, 0x32, 0xdc, 0xaa, 0x90, 0xb1, 0x5c, 0xf7, 0xb6, 0x3f, 0xbd, 0x97, 0x34, 0x6c, + 0xfa, 0x4a, 0x48, 0x1a, 0xd4, 0x5a, 0x71, 0xe1, 0x03, 0x76, 0xd1, 0xb3, 0xf7, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, + 0xda, 0x4b, 0xa2, 0x7c, 0x69, 0x7f, 0xac, 0x15, 0x5b, 0x63, 0x80, 0xab, 0xde, 0xe9, 0xfa, 0x84, 0x9c, 0xf2, 0x4e, + 0x8b, 0x82, 0x0c, 0x32, 0x2c, 0x23, 0xfa, 0xf0, 0x9f, 0x2e, 0xf2, 0xcd, 0x58, 0x3f, 0x4b, 0xa8, 0x53, 0x93, 0xd6, + 0x2f, 0x7a, 0xb3, 0xcd, 0xce, 0xc9, 0x6c, 0x01, 0xa0, 0xf0, 0x5f, 0xad, 0x3f, 0xb1, 0x35, 0x22, 0xd4, 0x50, 0x04, + 0x2f, 0x01, 0x57, 0x1c, 0xf0, 0xa8, 0xf6, 0x34, 0x42, 0xe1, 0x20, 0x09, 0x4d, 0x99, 0xb3, 0xdd, 0xdf, 0x10, 0xb4, + 0x71, 0x4d, 0x41, 0x87, 0x3e, 0x85, 0xa6, 0xff, 0xea, 0xb3, 0x5f, 0xa0, 0x5a, 0x45, 0xd1, 0x26, 0x76, 0x4d, 0xb1, + 0x38, 0xa4, 0x70, 0x93, 0x6b, 0x87, 0x77, 0x89, 0x10, 0xe0, 0xec, 0x5f, 0xcc, 0x29, 0x4e, 0x16, 0xd6, 0x9d, 0x4d, + 0x08, 0x96, 0x0a, 0x46, 0x52, 0xa2, 0x43, 0x19, 0x73, 0x9d, 0x39, 0x1e, 0x56, 0xe3, 0x97, 0x2e, 0xe8, 0xe1, 0x10, + 0x5e, 0xc7, 0xf8, 0xfc, 0xe1, 0x79, 0xc7, 0x3b, 0x56, 0x68, 0x99, 0xb5, 0x84, 0x29, 0xa4, 0x87, 0x7c, 0x0f, 0x83, + 0xca, 0x63, 0xcf, 0x05, 0xd3, 0xea, 0xfe, 0xa1, 0x54, 0x68, 0xe7, 0x39, 0xa8, 0xa9, 0x17, 0xc0, 0xc4, 0xc2, 0x4d, + 0x29, 0x0d, 0xbb, 0x92, 0x40, 0x6a, 0x53, 0x04, 0x30, 0xfe, 0xe4, 0x13, 0x22, 0x1e, 0xc4, 0x41, 0xa9, 0x96, 0xd0, + 0xf1, 0xe6, 0x68, 0xa3, 0x56, 0x77, 0xb1, 0x30, 0xbe, 0x05, 0x2b, 0x80, 0xb6, 0xc4, 0x86, 0xe1, 0x61, 0xf1, 0xa9, + 0x94, 0x37, 0x21, 0x01, 0xb5, 0xab, 0x20, 0x85, 0x95, 0x83, 0xb5, 0x1f, 0x4c, 0x80, 0xaa, 0x5d, 0x93, 0x28, 0xfd, + 0xb6, 0x52, 0x44, 0x0a, 0x8b, 0x42, 0x35, 0x8f, 0xec, 0xde, 0x96, 0x75, 0xda, 0x50, 0x35, 0x4f, 0x91, 0x2e, 0x95, + 0xda, 0x2e, 0x71, 0x6d, 0xff, 0xa7, 0x99, 0x42, 0xe6, 0x3e, 0x3b, 0x61, 0xf5, 0xb6, 0xf6, 0x14, 0xea, 0x64, 0x54, + 0x4f, 0xf1, 0xf2, 0x51, 0xb5, 0xc2, 0xdf, 0x56, 0xe6, 0xa0, 0x01, 0x0f, 0xc6, 0x45, 0xfa, 0x67, 0xef, 0xc3, 0x35, + 0xe4, 0x9e, 0xbc, 0x6f, 0x55, 0xa1, 0x48, 0x8e, 0x07, 0x33, 0xec, 0x2f, 0x3a, 0x81, 0xe3, 0x09, 0xdb, 0x36, 0x09, + 0x58, 0xeb, 0xf8, 0x1e, 0x49, 0x41, 0x8a, 0xfc, 0x36, 0xd6, 0x86, 0xc4, 0xdc, 0xf0, 0xa3, 0x44, 0x71, 0x4b, 0x29, + 0x5d, 0x25, 0x4f, 0x4e, 0x6d, 0xbb, 0x82, 0x52, 0x13, 0x47, 0xe0, 0xd8, 0xfa, 0xca, 0x11, 0xff, 0x6c, 0xfb, 0x6a, + 0x97, 0x2b, 0x89, 0x43, 0xb1, 0xc8, 0x4f, 0x75, 0x3f, 0x29, 0x0f, 0x93, 0x01, 0xac, 0x26, 0xd4, 0x19, 0x0b, 0x47, + 0x95, 0x24, 0x80, 0xc0, 0x04, 0xa8, 0x25, 0x3c, 0x17, 0x6a, 0x91, 0xdb, 0x30, 0xa9, 0xd9, 0x56, 0xce, 0x55, 0xfb, + 0x64, 0x6b, 0x6a, 0xcd, 0xc0, 0xcd, 0xc5, 0xc6, 0x71, 0x75, 0x67, 0x07, 0xb2, 0xd2, 0x43, 0x02, 0x9d, 0x7b, 0x53, + 0x62, 0x41, 0x53, 0xe0, 0xc3, 0xd1, 0xee, 0xbe, 0x03, 0x10, 0x45, 0x23, 0x46, 0xff, 0x59, 0xc1, 0xe4, 0xa4, 0xdf, + 0xe8, 0x06, 0x7c, 0x4b, 0x95, 0x79, 0x41, 0xd9, 0xe0, 0x72, 0x77, 0x7e, 0x63, 0xd5, 0x03, 0xcf, 0x4c, 0x98, 0x93, + 0x72, 0xed, 0xc1, 0x46, 0x66, 0x89, 0x9a, 0x70, 0xfd, 0x7f, 0x35, 0xd7, 0x90, 0x1c, 0x80, 0x5c, 0x8c, 0x7d, 0xab, + 0xac, 0xc0, 0xd5, 0x2c, 0x74, 0x40, 0x61, 0x1f, 0x0c, 0x9c, 0x0a, 0x1b, 0x76, 0x03, 0x6e, 0x7e, 0x90, 0xa6, 0x95, + 0xef, 0x12, 0xe8, 0xfe, 0xa7, 0x58, 0x63, 0xdf, 0xbb, 0x25, 0x6b, 0xd8, 0xe8, 0x4d, 0x41, 0xd3, 0xe8, 0x5e, 0x33, + 0x59, 0xd3, 0xd9, 0xca, 0x0c, 0x55, 0x23, 0xaf, 0xd6, 0x8f, 0x45, 0xdc, 0x1a, 0x9e, 0x9f, 0xc9, 0x79, 0xbd, 0x8f, + 0xe9, 0xa5, 0x6e, 0x3c, 0xf6, 0x45, 0xdd, 0xe1, 0xab, 0x1b, 0xd1, 0x86, 0xb3, 0xa2, 0x88, 0x9d, 0x0f, 0xeb, 0x9e, + 0x8a, 0xb4, 0x5b, 0x47, 0xbb, 0x78, 0x5b, 0x30, 0xa7, 0x64, 0x54, 0x67, 0xd0, 0x14, 0xba, 0x0a, 0xc7, 0xba, 0x7e, + 0xbe, 0xb8, 0x02, 0xeb, 0x8e, 0x96, 0x55, 0x82, 0x37, 0x26, 0x5d, 0xd4, 0x61, 0xd7, 0xf7, 0x8c, 0x0f, 0x89, 0xaa, + 0x8f, 0x46, 0xeb, 0x34, 0xf7, 0x05, 0x34, 0xa0, 0xe5, 0x0b, 0x3a, 0xb4, 0x21, 0xab, 0xd1, 0x5d, 0x69, 0xf2, 0xa4, + 0x56, 0xd5, 0x6f, 0x79, 0x0c, 0xde, 0xb1, 0x7c, 0x35, 0x56, 0x9d, 0x8e, 0x7f, 0x19, 0xbe, 0xbc, 0xac, 0xee, 0x90, + 0xf4, 0xb9, 0x97, 0x01, 0x60, 0xda, 0xe6, 0x93, 0x41, 0xbf, 0x2f, 0x02, 0x91, 0x91, 0xdf, 0x62, 0x3c, 0x7b, 0x29, + 0x4b, 0x00, 0x1d, 0x57, 0x05, 0xbd, 0x33, 0x4d, 0x7a, 0x79, 0x4f, 0x24, 0xe2, 0xc6, 0xc0, 0x78, 0x83, 0x42, 0x15, + 0x52, 0xef, 0x34, 0x81, 0xb8, 0x47, 0x1d, 0x13, 0xe9, 0x45, 0xd5, 0xf7, 0xab, 0x04, 0x07, 0xcf, 0xa2, 0xd5, 0x6e, + 0xff, 0xb3, 0x68, 0x0a, 0xe4, 0xc4, 0xc1, 0x44, 0x5d, 0xe1, 0x84, 0xc7, 0x3f, 0x9e, 0x68, 0xbf, 0x64, 0x47, 0xaa, + 0xe9, 0x30, 0x5f, 0xc5, 0x57, 0x76, 0xaa, 0x5a, 0xf1, 0xcb, 0xbc, 0xef, 0x67, 0x8b, 0xb4, 0xf1, 0x32, 0xd2, 0xab, + 0xd9, 0x5e, 0xed, 0x6c, 0xa2, 0xba, 0x53, 0x58, 0x1e, 0x35, 0x59, 0x51, 0x1d, 0x13, 0xab, 0x56, 0x5f, 0x1d, 0x7a, + 0xe5, 0xed, 0x65, 0xf6, 0x9b, 0x25, 0x61, 0xe6, 0xec, 0x69, 0xe1, 0xde, 0xec, 0x6c, 0xc9, 0x83, 0xee, 0xe7, 0xe0, + 0xbf, 0xc7, 0x46, 0x8a, 0x2d, 0x53, 0xbb, 0x28, 0x47, 0x02, 0x00, 0x0e, 0x12, 0xbf, 0x3a, 0xbd, 0xf9, 0x7b, 0x2d, + 0x2a, 0x75, 0xb3, 0xda, 0x69, 0x71, 0xe9, 0x1f, 0x23, 0x4a, 0x4b, 0xe3, 0x38, 0xe5, 0x08, 0xa2, 0x71, 0x6d, 0x7e, + 0xc1, 0x24, 0x73, 0xdf, 0x62, 0xb5, 0x12, 0x6b, 0xc9, 0x09, 0x14, 0x18, 0xb9, 0xd7, 0x35, 0xcf, 0x5d, 0xab, 0x53, + 0x58, 0xa6, 0xb6, 0xe6, 0xb0, 0xb5, 0xc3, 0xbe, 0x83, 0xaa, 0xaf, 0xa9, 0xc3, 0x55, 0x16, 0xbe, 0xad, 0x78, 0x21, + 0x5f, 0x4a, 0x79, 0x72, 0xea, 0xe6, 0x8d, 0x60, 0x29, 0x3e, 0x0a, 0x54, 0x73, 0x46, 0xf0, 0xa2, 0x56, 0x5f, 0x59, + 0xc4, 0x4a, 0x7e, 0x28, 0x09, 0xbd, 0xd8, 0x3d, 0x17, 0xd9, 0x80, 0xab, 0xb2, 0xfe, 0xbe, 0xfa, 0xdc, 0x23, 0x95, + 0x7d, 0x74, 0x61, 0x95, 0xda, 0x8e, 0x63, 0x6e, 0xa3, 0xa6, 0x2a, 0x78, 0xf3, 0xde, 0x35, 0xd8, 0x35, 0xb0, 0x3c, + 0x19, 0xcb, 0x25, 0x46, 0x06, 0x3e, 0xd6, 0xd6, 0x53, 0x7d, 0x65, 0x5e, 0x3d, 0x5a, 0xc9, 0x58, 0x48, 0xca, 0x2b, + 0x04, 0xa2, 0xd7, 0x7f, 0x96, 0x2b, 0x35, 0xac, 0xd5, 0xd9, 0x0a, 0x25, 0x1a, 0x31, 0xda, 0xbb, 0x54, 0x4e, 0x76, + 0x4d, 0x8f, 0x8c, 0xe9, 0xf3, 0xee, 0x47, 0xd5, 0xd2, 0x92, 0xd9, 0x86, 0x16, 0xff, 0x54, 0x64, 0x2c, 0xa9, 0x88, + 0x6d, 0xc5, 0x16, 0x7b, 0x16, 0x77, 0x01, 0x4c, 0x3e, 0x5d, 0x30, 0x77, 0x9f, 0x50, 0x0e, 0xc6, 0xea, 0x57, 0xaa, + 0x2a, 0x37, 0x3e, 0x4f, 0xbc, 0xbe, 0x6f, 0x60, 0x26, 0x91, 0x45, 0x1e, 0x05, 0x36, 0x2b, 0xeb, 0x69, 0x4f, 0x6f, + 0x73, 0x52, 0xa3, 0x5f, 0x18, 0x85, 0x56, 0x79, 0xc0, 0xe7, 0x9a, 0x79, 0xf2, 0xe6, 0x7d, 0xa7, 0x1b, 0x41, 0x86, + 0xa3, 0x8d, 0xb4, 0x41, 0xdb, 0x6d, 0x48, 0x7a, 0x8b, 0xf8, 0x0f, 0x29, 0xd3, 0x5f, 0x94, 0xf9, 0xea, 0xfb, 0xe1, + 0x7c, 0x5d, 0x4e, 0x50, 0x35, 0x7b, 0xc0, 0xe1, 0xd1, 0x58, 0x02, 0x2c, 0x20, 0x8e, 0x3e, 0x12, 0xb2, 0xb6, 0x26, + 0x28, 0x27, 0x3c, 0x52, 0xe5, 0x6c, 0x94, 0x77, 0x26, 0x7a, 0x42, 0xab, 0xca, 0xd9, 0x00, 0x5b, 0xd0, 0x8d, 0x5d, + 0xf2, 0x6d, 0x2c, 0x3c, 0x5d, 0xee, 0x77, 0x8e, 0xed, 0x81, 0x2b, 0xd7, 0x5c, 0xc0, 0x17, 0xde, 0x03, 0x77, 0xa1, + 0x5a, 0x40, 0x6b, 0x10, 0xff, 0x51, 0x54, 0xd9, 0xdd, 0xe6, 0xdc, 0x48, 0x24, 0x59, 0x28, 0x13, 0x2a, 0x6b, 0xf1, + 0x73, 0x83, 0x9c, 0xeb, 0x71, 0xe0, 0x1c, 0x29, 0x01, 0x82, 0x63, 0xc4, 0x24, 0xf6, 0xa6, 0x34, 0x54, 0x70, 0x8e, + 0x3e, 0x79, 0x2d, 0xbf, 0x60, 0xca, 0xd0, 0x05, 0x3a, 0x3d, 0xcf, 0x42, 0xc1, 0x7e, 0x60, 0x5d, 0x38, 0x3a, 0x69, + 0x39, 0xeb, 0x9f, 0x1d, 0x18, 0x01, 0xf2, 0x58, 0x79, 0x99, 0x24, 0x6c, 0x2d, 0x5a, 0xbd, 0xc9, 0xfb, 0x71, 0xa5, + 0x10, 0x2d, 0x16, 0xa8, 0xba, 0xfd, 0x02, 0x17, 0xa7, 0x25, 0x95, 0xac, 0x14, 0xb7, 0x0a, 0x15, 0x88, 0xd6, 0x9b, + 0x50, 0xf5, 0x3a, 0x7d, 0x6d, 0xdb, 0x51, 0x79, 0x69, 0x28, 0x36, 0x31, 0x04, 0x86, 0x58, 0x1f, 0x7e, 0xaa, 0xb6, + 0xe1, 0xb6, 0xb3, 0x2e, 0xee, 0x73, 0xdb, 0x7e, 0x0d, 0x5f, 0x8f, 0xc4, 0x9b, 0xca, 0xdb, 0xa6, 0x78, 0x58, 0x20, + 0xe2, 0x44, 0xd7, 0x6b, 0x0d, 0x9b, 0x93, 0x4f, 0x7f, 0x55, 0xa7, 0x4c, 0x8e, 0xe8, 0x63, 0x0f, 0x21, 0xe6, 0x42, + 0x44, 0x85, 0x48, 0xbf, 0x6f, 0x47, 0xe7, 0xca, 0x3d, 0x23, 0x44, 0xe7, 0xd8, 0x88, 0x75, 0x6c, 0x27, 0x81, 0xa7, + 0xb6, 0x14, 0xc4, 0x09, 0xdc, 0x7d, 0x27, 0x16, 0x7c, 0xf2, 0x85, 0x34, 0xe7, 0xe1, 0xf9, 0xcb, 0xdf, 0xfe, 0x4a, + 0x56, 0xea, 0xb9, 0xee, 0x2c, 0xba, 0xa6, 0xbb, 0xa4, 0x52, 0x97, 0xcf, 0x71, 0x17, 0xb3, 0xf0, 0x26, 0x6b, 0xff, + 0x7a, 0x78, 0x4b, 0x37, 0x6d, 0x48, 0x91, 0x4c, 0x51, 0xee, 0xfe, 0x4d, 0x3c, 0x35, 0x22, 0xc3, 0x5f, 0xf0, 0x8c, + 0xb1, 0xee, 0xcb, 0xaa, 0xf9, 0x60, 0xac, 0x04, 0xec, 0x3d, 0x27, 0x23, 0x73, 0x51, 0x70, 0xa3, 0x28, 0x44, 0x2b, + 0xd6, 0x83, 0xed, 0x40, 0x53, 0xf9, 0x80, 0xf1, 0x0f, 0x53, 0x6a, 0xb9, 0x8b, 0xcd, 0xf5, 0xfd, 0xd8, 0xf4, 0x38, + 0x26, 0x25, 0x23, 0x9d, 0x39, 0x1a, 0xa8, 0x15, 0xd8, 0xf6, 0x58, 0x7e, 0x39, 0x44, 0xe7, 0xb4, 0x2d, 0xb0, 0x4d, + 0xcb, 0xc7, 0x37, 0x87, 0x6c, 0x2e, 0x5f, 0x9a, 0xf1, 0x5e, 0xba, 0x79, 0xf2, 0x62, 0x99, 0xde, 0x0a, 0x7b, 0xc2, + 0x40, 0x14, 0x51, 0x05, 0x9d, 0x84, 0x22, 0xec, 0xb4, 0x5b, 0x7b, 0x82, 0x94, 0x16, 0x83, 0xf0, 0x13, 0x5c, 0x9f, + 0xb4, 0xaf, 0x45, 0x6d, 0x6a, 0x1d, 0x35, 0x41, 0xed, 0x72, 0x9e, 0x06, 0x48, 0x47, 0xc5, 0x73, 0x0b, 0xa1, 0xcf, + 0x28, 0xd0, 0x16, 0x34, 0x59, 0x29, 0xd2, 0x08, 0x43, 0x91, 0x73, 0x63, 0xaa, 0x26, 0x73, 0xb1, 0x5c, 0xf8, 0xb3, + 0x46, 0x9b, 0x34, 0xc4, 0x24, 0xe4, 0xda, 0x96, 0x5d, 0xe6, 0xeb, 0x04, 0xeb, 0x2b, 0x6b, 0x7f, 0x3d, 0xf9, 0x5b, + 0x41, 0x32, 0x05, 0xec, 0x47, 0x16, 0xaf, 0xdb, 0x97, 0xb8, 0x02, 0xde, 0xd4, 0x40, 0x51, 0x03, 0xca, 0xac, 0x3a, + 0xad, 0xdb, 0xf0, 0x80, 0x32, 0xfb, 0xcd, 0x40, 0x95, 0x9a, 0x5c, 0x59, 0xc5, 0xb7, 0xba, 0x8d, 0xb8, 0x5e, 0xb2, + 0x81, 0xb4, 0xf1, 0x76, 0xca, 0xad, 0xd3, 0x54, 0xb9, 0x12, 0xe7, 0x41, 0x25, 0xa9, 0x71, 0x0f, 0x30, 0x98, 0xe6, + 0xe9, 0x3b, 0x34, 0xe6, 0xdf, 0x8a, 0x83, 0x49, 0x5f, 0x18, 0x24, 0xab, 0xb4, 0x63, 0x01, 0x20, 0x40, 0xb7, 0x5d, + 0x72, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x88, 0xec, 0x1d, 0xd8, 0x9d, 0xe9, 0xc3, 0xc0, 0xcc, + 0xbb, 0x9a, 0x92, 0x5d, 0x8a, 0xc2, 0x37, 0xd1, 0x37, 0xdb, 0xc5, 0x4a, 0x00, 0xdc, 0x30, 0xbb, 0xcc, 0x17, 0xaa, + 0x4c, 0xe6, 0x62, 0xab, 0xf2, 0x90, 0x9b, 0xa9, 0x4c, 0x71, 0x55, 0x13, 0x3c, 0x08, 0x82, 0x80, 0x82, 0xbc, 0x81, + 0x5c, 0xc7, 0x17, 0x0d, 0x20, 0xe8, 0x41, 0x58, 0x0c, 0x13, 0xcf, 0x8d, 0xb2, 0xbb, 0x3e, 0xaa, 0x98, 0xc2, 0xf8, + 0x54, 0x4a, 0x72, 0x72, 0xee, 0xf5, 0xc9, 0x64, 0xd8, 0x6a, 0x36, 0xec, 0xe4, 0x24, 0x21, 0xb4, 0x24, 0xb6, 0x90, + 0x53, 0xea, 0xf6, 0xae, 0x0e, 0xbd, 0x3c, 0x96, 0x05, 0x8c, 0xb6, 0x11, 0xac, 0x3b, 0x1c, 0xed, 0x3d, 0x25, 0xc2, + 0x8b, 0x65, 0x63, 0xbe, 0x13, 0xf1, 0x45, 0xaa, 0x8f, 0x81, 0x06, 0xcc, 0x9b, 0x3f, 0x07, 0xb2, 0x9a, 0xe0, 0x6f, + 0xc2, 0x8b, 0x65, 0x71, 0x9f, 0x39, 0x21, 0x2a, 0x36, 0x8b, 0xfb, 0x67, 0x1b, 0x14, 0x98, 0xae, 0x09, 0xdd, 0x40, + 0xaa, 0x81, 0x45, 0xc3, 0x1d, 0x3d, 0x58, 0xb4, 0x3f, 0xa2, 0xab, 0x62, 0x59, 0x61, 0xf4, 0xe8, 0xc1, 0x51, 0x3d, + 0x95, 0x1d, 0x4b, 0x6b, 0xa4, 0x39, 0xe2, 0x37, 0xcf, 0x11, 0x2d, 0xea, 0x36, 0xc6, 0x44, 0x63, 0x69, 0xe6, 0x1f, + 0x44, 0x79, 0xb4, 0xaf, 0x41, 0xd8, 0x3f, 0x83, 0x4d, 0xe2, 0x63, 0xc6, 0x20, 0x6f, 0x8e, 0x06, 0xf6, 0x72, 0x40, + 0x1d, 0x07, 0xcb, 0x93, 0x92, 0x82, 0x9b, 0x8b, 0x95, 0x2a, 0xcd, 0x32, 0x8a, 0x3d, 0xaf, 0x13, 0x59, 0xcb, 0x1e, + 0xe1, 0x24, 0x23, 0x26, 0xfa, 0x3c, 0x50, 0x90, 0x77, 0x5a, 0x2f, 0xff, 0xd3, 0x0a, 0xcc, 0x3a, 0x74, 0x32, 0xd6, + 0x64, 0x94, 0x2c, 0x84, 0x08, 0x6d, 0x08, 0xb7, 0x36, 0x24, 0xd7, 0x22, 0xb4, 0x1d, 0x99, 0x43, 0x1f, 0xe6, 0x4b, + 0xc1, 0x19, 0x5e, 0x82, 0x9e, 0x76, 0xb9, 0x7d, 0x71, 0xfa, 0xcd, 0x85, 0x72, 0x67, 0x83, 0x83, 0x08, 0xa4, 0xe8, + 0x5c, 0x9f, 0x1e, 0x8a, 0x17, 0x85, 0x83, 0x88, 0xb8, 0x39, 0xbc, 0x1e, 0xac, 0x3e, 0x26, 0x74, 0x56, 0x75, 0x4f, + 0x7b, 0xff, 0x85, 0x0b, 0xdf, 0xb5, 0xb5, 0x22, 0x8a, 0xd3, 0x1b, 0xb6, 0x1e, 0xa5, 0x79, 0x26, 0xad, 0x1e, 0xbb, + 0x62, 0xe0, 0x51, 0xa6, 0x22, 0xc7, 0x6f, 0xd6, 0x63, 0x8c, 0x6d, 0x08, 0x28, 0x43, 0xaa, 0xb7, 0x18, 0x02, 0x20, + 0x63, 0x9e, 0x8e, 0xfd, 0x71, 0xce, 0x26, 0xc8, 0x7b, 0x8d, 0x31, 0x17, 0xf1, 0x76, 0xed, 0x4f, 0xe0, 0xa1, 0x50, + 0x36, 0x12, 0xd7, 0xf2, 0x28, 0xc5, 0xb9, 0x07, 0x15, 0x9f, 0x46, 0xc4, 0xd6, 0x61, 0xea, 0x7c, 0x42, 0x18, 0xb2, + 0x07, 0x31, 0x66, 0x17, 0x26, 0x74, 0x7a, 0x89, 0xbe, 0x32, 0xbd, 0x0d, 0xa8, 0xbe, 0x15, 0x5b, 0x24, 0x9a, 0x97, + 0x44, 0xa2, 0xe8, 0xec, 0x84, 0xd8, 0x6c, 0x45, 0x8e, 0x1a, 0xab, 0xbd, 0x83, 0xc1, 0xe5, 0x33, 0x4e, 0x6b, 0xeb, + 0x0a, 0x30, 0xf9, 0x63, 0x98, 0x0a, 0x06, 0x9c, 0x1b, 0x4e, 0x2c, 0x79, 0x37, 0xa2, 0x1f, 0x7d, 0x20, 0xe3, 0xb7, + 0xd2, 0x22, 0xd8, 0xa3, 0x81, 0x18, 0xa9, 0x8a, 0x61, 0x05, 0xd3, 0x47, 0x21, 0xc1, 0x53, 0x17, 0x8e, 0xaa, 0x3a, + 0xf4, 0x0b, 0x22, 0xaa, 0x9d, 0x0b, 0xbb, 0x56, 0x0c, 0x98, 0x68, 0xcc, 0x1c, 0x1a, 0x2d, 0x5c, 0xc0, 0xf3, 0x74, + 0xfc, 0x7e, 0xe2, 0x7e, 0x76, 0xfe, 0xa0, 0x19, 0xf4, 0xbf, 0x26, 0xa3, 0xce, 0xf1, 0xd3, 0xfb, 0xdb, 0xf6, 0x69, + 0xbf, 0xb6, 0x33, 0xf7, 0x07, 0xea, 0xfb, 0x4f, 0xfc, 0xcb, 0x24, 0x80, 0xfc, 0x52, 0xc7, 0x6e, 0xc3, 0xf5, 0x53, + 0xe2, 0x35, 0x78, 0xb8, 0x7e, 0x72, 0x89, 0x50, 0xef, 0x00, 0xed, 0x8d, 0x4a, 0xdb, 0x86, 0x4b, 0x4c, 0xe2, 0x91, + 0xf2, 0x64, 0x35, 0x56, 0x64, 0x49, 0xad, 0x60, 0x65, 0x92, 0x6f, 0xe4, 0xae, 0xcf, 0x2e, 0xc1, 0x3d, 0xbe, 0x15, + 0xd9, 0x53, 0xae, 0x3e, 0x00, 0x17, 0xa5, 0xf3, 0x57, 0xcc, 0x3b, 0xff, 0x13, 0x55, 0xd6, 0x1d, 0xd4, 0x0c, 0xb5, + 0x96, 0x44, 0xad, 0x9a, 0x59, 0x5d, 0xb0, 0xb7, 0x04, 0xb4, 0xa6, 0x56, 0x1f, 0xca, 0xcd, 0x21, 0x7f, 0x6c, 0xb1, + 0x2e, 0x8c, 0x13, 0x4d, 0x93, 0x01, 0x79, 0x6a, 0x7e, 0xe9, 0x12, 0x43, 0x92, 0x41, 0xfd, 0xbf, 0xbe, 0x7b, 0x77, + 0x74, 0xd0, 0x4c, 0x5a, 0xde, 0x85, 0x3d, 0xde, 0xab, 0xa2, 0x62, 0x49, 0xe7, 0x1b, 0x7d, 0x7c, 0x90, 0x3c, 0xc9, + 0xc3, 0xf6, 0x79, 0xea, 0xcf, 0x0e, 0xfc, 0xd8, 0x80, 0xbe, 0xe3, 0x6d, 0xd3, 0x8e, 0xd2, 0xc7, 0x21, 0x04, 0x2c, + 0xd5, 0x2e, 0x68, 0x56, 0xc3, 0x23, 0x34, 0x58, 0xb7, 0x49, 0x55, 0x38, 0x8a, 0xa7, 0x1c, 0x1f, 0xfe, 0x03, 0xd0, + 0x41, 0x02, 0x3c, 0x6a, 0x2e, 0xcb, 0xc3, 0xb4, 0x03, 0x6b, 0x23, 0x6c, 0xf7, 0x26, 0x44, 0x2f, 0x16, 0x47, 0x6b, + 0xa7, 0x36, 0x61, 0x11, 0x69, 0xbc, 0x2b, 0x09, 0x5d, 0xdd, 0x07, 0xbd, 0x1e, 0x75, 0x9a, 0x35, 0x09, 0xa1, 0x9d, + 0x6c, 0xeb, 0xb8, 0x7a, 0xd0, 0xab, 0xac, 0xcf, 0x5f, 0x30, 0xfd, 0x58, 0xdf, 0xe3, 0x23, 0x86, 0xf5, 0x1b, 0xde, + 0x1f, 0x5c, 0x4a, 0x70, 0xb1, 0x69, 0xec, 0x7c, 0x33, 0x27, 0x0e, 0xbb, 0x59, 0x0a, 0x0b, 0x09, 0xa6, 0x97, 0x48, + 0x1b, 0xc6, 0x6a, 0x70, 0x7c, 0x11, 0x1f, 0xeb, 0xf9, 0x62, 0x40, 0x20, 0x52, 0xd9, 0x29, 0xf2, 0xc2, 0x00, 0x13, + 0xf5, 0xed, 0xcd, 0x87, 0xd4, 0xff, 0x10, 0xdf, 0xec, 0x03, 0xa9, 0x93, 0xe4, 0xd1, 0x8b, 0x45, 0x51, 0x24, 0x54, + 0xf4, 0x14, 0xff, 0xe2, 0x10, 0xca, 0xf0, 0x32, 0xd1, 0xd9, 0xa4, 0xe8, 0xf6, 0xce, 0x2d, 0x5f, 0x24, 0xbc, 0x71, + 0xe5, 0x72, 0xe9, 0x61, 0x60, 0xda, 0x02, 0x36, 0x50, 0x41, 0xc6, 0x31, 0x4b, 0xf1, 0x63, 0xe4, 0x2a, 0x43, 0x94, + 0xdd, 0xea, 0x31, 0xd4, 0x70, 0x11, 0x98, 0x3b, 0x94, 0x49, 0xc2, 0x68, 0xa1, 0x9e, 0xdb, 0xc0, 0xd3, 0x73, 0x66, + 0xe7, 0xe9, 0xdc, 0xde, 0xab, 0x62, 0xc7, 0x84, 0x89, 0x0c, 0x8a, 0xe8, 0xb1, 0xc2, 0x86, 0x5a, 0xcd, 0x97, 0x99, + 0x53, 0x6c, 0x7a, 0xe4, 0x0f, 0x43, 0x2d, 0x37, 0xe9, 0x96, 0x1d, 0xbd, 0xd2, 0x47, 0xfd, 0xd1, 0xa2, 0x13, 0x0c, + 0xd1, 0xe2, 0xee, 0xac, 0x8d, 0x72, 0xc4, 0x28, 0x6c, 0xde, 0x17, 0x80, 0xd9, 0xb7, 0x6e, 0x4b, 0xba, 0xfa, 0xc4, + 0xd5, 0xf7, 0xc2, 0xdc, 0xf3, 0x00, 0x62, 0x24, 0xcf, 0xe5, 0xc8, 0x45, 0x91, 0x03, 0x92, 0xbc, 0xab, 0x23, 0x2d, + 0x91, 0x8a, 0x10, 0x4e, 0x67, 0x1c, 0x0c, 0x8b, 0xd3, 0xb9, 0x6a, 0xea, 0xbb, 0x2c, 0x10, 0x09, 0x65, 0xb2, 0x9f, + 0xa2, 0x67, 0x7b, 0xa3, 0x71, 0x47, 0x87, 0xb5, 0x76, 0xeb, 0x20, 0x14, 0xae, 0x4c, 0xb5, 0x99, 0x70, 0xf7, 0x8c, + 0xfe, 0xeb, 0x8d, 0x97, 0x14, 0xab, 0x8e, 0x7b, 0xef, 0x53, 0x7d, 0xf9, 0x6b, 0x5e, 0x00, 0xf5, 0xfb, 0x81, 0xb3, + 0x21, 0x7f, 0xcb, 0x7d, 0xb0, 0x98, 0x32, 0x40, 0x80, 0x8f, 0x68, 0x86, 0x3a, 0xed, 0xab, 0xd9, 0x8d, 0x6f, 0x88, + 0xd9, 0xb3, 0xda, 0xd0, 0x77, 0x7e, 0xf8, 0xae, 0xae, 0xa0, 0xc1, 0x45, 0x65, 0xf4, 0x7f, 0x9e, 0x2a, 0x20, 0x98, + 0x0a, 0xfe, 0x3e, 0x6e, 0x87, 0xe3, 0x5b, 0xf0, 0x1c, 0x46, 0x7d, 0x1c, 0x69, 0xa2, 0x7b, 0x27, 0xee, 0x52, 0xaf, + 0x32, 0x4d, 0x32, 0xaf, 0x68, 0x97, 0x35, 0x2e, 0x58, 0xd6, 0x35, 0x5d, 0x5b, 0x76, 0xb0, 0x66, 0x5f, 0x02, 0x20, + 0x23, 0xdb, 0x9b, 0xaa, 0xa6, 0xf0, 0xeb, 0x4b, 0xb1, 0x08, 0x24, 0xf0, 0x9d, 0xb2, 0xbf, 0xba, 0x76, 0x7d, 0xd3, + 0xae, 0x16, 0xf1, 0xc1, 0xc0, 0x81, 0x50, 0xae, 0xf3, 0x86, 0x7b, 0x59, 0xa1, 0xcd, 0xf3, 0x25, 0xe7, 0xc6, 0xcb, + 0x88, 0x4a, 0x43, 0x21, 0x89, 0xda, 0x40, 0x9f, 0x8e, 0x3d, 0x0d, 0x10, 0x1e, 0x12, 0x4b, 0x1d, 0x64, 0x65, 0xfa, + 0x47, 0xd2, 0xde, 0x9b, 0x1b, 0xc3, 0xeb, 0xe1, 0x16, 0x97, 0x19, 0x45, 0x14, 0x76, 0x0c, 0x3c, 0x72, 0x2b, 0x56, + 0x7b, 0xb7, 0xfe, 0xe1, 0xc1, 0xd3, 0xbb, 0xab, 0x8f, 0x9f, 0x16, 0xb7, 0x43, 0xaa, 0xd5, 0x4f, 0xa7, 0xd6, 0xb2, + 0xe6, 0x93, 0x76, 0x98, 0xf7, 0x8e, 0x15, 0xbb, 0x84, 0x13, 0x69, 0x07, 0x31, 0x56, 0x6e, 0x26, 0x55, 0xa7, 0x09, + 0x70, 0x20, 0x35, 0x75, 0x9f, 0x3d, 0x73, 0xcd, 0x94, 0x3c, 0x36, 0xe8, 0x25, 0x51, 0x57, 0xa5, 0x11, 0x58, 0xa6, + 0xfd, 0xe3, 0xf1, 0xd2, 0x4b, 0x3d, 0x4d, 0xb0, 0x89, 0x6e, 0x18, 0x88, 0xc3, 0xdf, 0xb1, 0xc1, 0xaf, 0x67, 0xf7, + 0x64, 0x49, 0xa0, 0x70, 0x69, 0xeb, 0x86, 0x32, 0x0d, 0xda, 0x52, 0x21, 0x38, 0x2e, 0x5e, 0xdc, 0x2a, 0xc6, 0x93, + 0xac, 0xa9, 0x16, 0xc5, 0x43, 0x24, 0x1a, 0x70, 0x19, 0x5b, 0xca, 0x4d, 0xbe, 0x8d, 0x01, 0x0e, 0xd2, 0x11, 0xca, + 0xf5, 0xb2, 0x0a, 0xb0, 0xdb, 0xf0, 0xd7, 0xe3, 0x69, 0x1e, 0x80, 0x98, 0x1e, 0x1b, 0xf6, 0x74, 0x6f, 0xa3, 0xc9, + 0xad, 0xb9, 0x93, 0x12, 0x3f, 0x4a, 0xd9, 0x62, 0x4b, 0x0c, 0x83, 0x73, 0xa5, 0x13, 0x20, 0xa0, 0xe5, 0x6e, 0x09, + 0x20, 0xb5, 0x2c, 0x39, 0x89, 0x83, 0x85, 0x13, 0xd9, 0xde, 0x62, 0xbc, 0xdd, 0x93, 0x9e, 0x1a, 0xcf, 0xdc, 0x46, + 0xc6, 0xa4, 0xac, 0x7c, 0xbf, 0x20, 0x93, 0xf7, 0x79, 0x06, 0x16, 0xcd, 0x65, 0xf4, 0xf4, 0x5d, 0x71, 0x2a, 0x7e, + 0x98, 0x45, 0xe7, 0xe1, 0x69, 0xd4, 0xcd, 0x61, 0x96, 0x78, 0xc0, 0x4e, 0x38, 0xd3, 0x6a, 0x60, 0xac, 0x5d, 0xda, + 0x8e, 0xb4, 0x3b, 0xfb, 0x02, 0x29, 0x61, 0xcd, 0x6e, 0x76, 0x82, 0x63, 0x46, 0x5c, 0x0e, 0xba, 0xd7, 0x1b, 0x30, + 0xac, 0x6c, 0x17, 0x73, 0x73, 0x4f, 0xee, 0xa4, 0xd5, 0x53, 0x81, 0x9c, 0x81, 0x2c, 0x59, 0xd7, 0xf0, 0xbe, 0x40, + 0xb5, 0xbe, 0x78, 0x70, 0xf0, 0x76, 0x6f, 0x19, 0x77, 0x4d, 0x19, 0x65, 0x3b, 0xa2, 0x08, 0x7e, 0x65, 0x40, 0xba, + 0x56, 0xf6, 0x23, 0x77, 0x37, 0x4b, 0x1d, 0xa4, 0x14, 0xfa, 0x74, 0x3d, 0x5d, 0x1b, 0x09, 0x6f, 0x66, 0xaa, 0xe3, + 0x08, 0xf9, 0x44, 0x87, 0x41, 0x59, 0x49, 0x8a, 0xfe, 0x9f, 0xb1, 0xdf, 0x81, 0x82, 0x7a, 0xe0, 0xd7, 0xbf, 0x0b, + 0x12, 0x1c, 0xd8, 0x9d, 0xa0, 0xb5, 0xe2, 0x63, 0x09, 0xb2, 0x5b, 0x85, 0xb9, 0xa0, 0x44, 0xad, 0x7f, 0xcf, 0xcd, + 0xf5, 0xfa, 0xfb, 0x4b, 0x56, 0xaa, 0x75, 0x27, 0xdb, 0xb6, 0xf5, 0x4d, 0xae, 0x19, 0x3b, 0x62, 0x5f, 0x0e, 0x7c, + 0x70, 0x9a, 0xc9, 0xb5, 0x80, 0xa4, 0x21, 0xd3, 0xe7, 0x6e, 0x8d, 0xba, 0x91, 0x8c, 0xdc, 0x01, 0x09, 0x44, 0x08, + 0x34, 0x18, 0x94, 0x75, 0xbb, 0x2f, 0xc6, 0xe1, 0xbc, 0xb3, 0x78, 0xff, 0x73, 0x41, 0x97, 0xe8, 0xb0, 0xae, 0xce, + 0x62, 0xc9, 0x7f, 0xbf, 0x53, 0x8c, 0x64, 0x7b, 0xb4, 0xbd, 0x7f, 0x31, 0x9a, 0xe2, 0x4a, 0xa6, 0xfd, 0x83, 0xbf, + 0xbf, 0xe8, 0x2d, 0xbc, 0xd9, 0xd1, 0xc1, 0xea, 0x3e, 0x4f, 0xb9, 0x79, 0xd2, 0x17, 0x33, 0xf9, 0xae, 0x8c, 0x4c, + 0x6e, 0x10, 0x18, 0x75, 0x67, 0x75, 0xa9, 0xcb, 0xc3, 0xc8, 0xc5, 0x7a, 0xb8, 0x19, 0x4e, 0xe1, 0x36, 0x13, 0x59, + 0xb5, 0x50, 0x05, 0xe0, 0x11, 0x3a, 0x29, 0x51, 0x24, 0x49, 0x62, 0x80, 0xe8, 0xde, 0xc6, 0x3c, 0x80, 0x17, 0x35, + 0x9f, 0x35, 0xd4, 0x76, 0x46, 0x36, 0xc7, 0x01, 0xad, 0xcd, 0x1c, 0xd3, 0xb2, 0x29, 0x41, 0xe7, 0xee, 0x74, 0x84, + 0x0e, 0xbd, 0xa5, 0xf5, 0x54, 0x97, 0x8a, 0x7d, 0xd3, 0xb3, 0xb6, 0x8e, 0xc8, 0x27, 0x71, 0x6b, 0x75, 0x90, 0xe6, + 0x2a, 0xa7, 0xe2, 0x66, 0xaa, 0x9e, 0xa3, 0x77, 0x16, 0x8e, 0x40, 0xdf, 0x5a, 0x1e, 0xac, 0x71, 0x11, 0x6c, 0x8a, + 0xee, 0x2c, 0x15, 0x55, 0xc5, 0x96, 0xfb, 0x9d, 0x4c, 0xa7, 0xed, 0x9d, 0x01, 0xb2, 0x4e, 0x98, 0xee, 0x1e, 0x12, + 0x48, 0x3c, 0x7a, 0x17, 0x60, 0xb0, 0x67, 0x52, 0x4c, 0xab, 0xea, 0xbc, 0x62, 0x82, 0x87, 0xa5, 0x3c, 0xf3, 0xbd, + 0xd9, 0xb3, 0xc3, 0xa8, 0x61, 0x3c, 0x76, 0xf8, 0x05, 0x25, 0x05, 0xb3, 0x37, 0xd1, 0xcd, 0xdf, 0xcb, 0xd7, 0xf5, + 0x09, 0xb7, 0x46, 0x0e, 0xb9, 0x75, 0x07, 0xd7, 0xef, 0xf4, 0x7d, 0xe6, 0x62, 0x56, 0xdf, 0x7e, 0x36, 0x2e, 0x66, + 0x46, 0xc9, 0x77, 0x6a, 0xa4, 0x3d, 0x24, 0xde, 0x6b, 0x00, 0xb6, 0x00, 0xca, 0x92, 0x09, 0xe8, 0x60, 0xb5, 0x2e, + 0x97, 0x4e, 0xd7, 0x29, 0x69, 0xaa, 0x3d, 0xf3, 0x6a, 0xbb, 0xb1, 0xcd, 0x85, 0x67, 0x4c, 0xb6, 0x58, 0x9b, 0x4e, + 0x5b, 0xc2, 0xe4, 0xb5, 0xae, 0xdf, 0xe8, 0xfa, 0x97, 0x15, 0x81, 0x9a, 0xa9, 0x5c, 0x71, 0x5f, 0x2b, 0x6b, 0x08, + 0x3e, 0x85, 0x45, 0x98, 0x0a, 0xf0, 0xac, 0x3a, 0x81, 0xaa, 0xf5, 0x43, 0xdb, 0xfb, 0x1b, 0x16, 0xdb, 0xb3, 0x9d, + 0x76, 0x01, 0x14, 0x9e, 0x25, 0xee, 0x9c, 0x2b, 0x77, 0x74, 0xe3, 0x74, 0x13, 0x53, 0xf6, 0xe3, 0x17, 0xa8, 0x93, + 0x83, 0x99, 0xdb, 0x0b, 0x1a, 0x4b, 0xc0, 0x93, 0x22, 0x13, 0xc4, 0xe4, 0xe7, 0x40, 0x08, 0x6d, 0xa4, 0xd2, 0x99, + 0x86, 0xc7, 0x68, 0xf7, 0x5a, 0x29, 0x0b, 0xa6, 0x76, 0xef, 0xc9, 0x6d, 0xd8, 0x74, 0x04, 0xaa, 0xb3, 0xef, 0xa4, + 0xdc, 0xa8, 0x97, 0x30, 0x02, 0x3a, 0xdd, 0x6b, 0xf5, 0xe3, 0x9f, 0x93, 0xb9, 0x86, 0x7d, 0x64, 0xc7, 0x1b, 0xd1, + 0x0d, 0x40, 0x0e, 0x87, 0x4b, 0x28, 0x65, 0xed, 0x93, 0xea, 0xdf, 0xfb, 0xb2, 0xd1, 0xf0, 0x09, 0xc3, 0x38, 0x49, + 0x54, 0x71, 0xda, 0xe6, 0xd6, 0x40, 0xe9, 0x4f, 0xee, 0x9d, 0x12, 0xa6, 0x20, 0x10, 0x4d, 0xb2, 0x72, 0x3e, 0x05, + 0x2c, 0x3c, 0xe5, 0x81, 0x4a, 0x98, 0x46, 0x2c, 0xd1, 0x0e, 0xad, 0x34, 0x1b, 0x5d, 0x82, 0x19, 0x06, 0x5c, 0xfb, + 0x0b, 0x8d, 0xd6, 0x9d, 0xec, 0xad, 0xa3, 0x06, 0x6f, 0xd0, 0xd2, 0xe8, 0x77, 0x43, 0x93, 0x00, 0x84, 0x9c, 0x1e, + 0xdc, 0xf7, 0x2c, 0x46, 0xc7, 0x15, 0x9d, 0x47, 0x0f, 0x64, 0x22, 0xd4, 0x94, 0xeb, 0x4e, 0x0e, 0x80, 0x39, 0xdd, + 0x72, 0x69, 0xa8, 0xc7, 0x60, 0x9a, 0x5e, 0x40, 0x54, 0xc0, 0x8a, 0x0e, 0xa0, 0xd3, 0xd8, 0x0d, 0x65, 0x79, 0xc3, + 0x0c, 0x05, 0x08, 0x82, 0xec, 0x1b, 0x84, 0xfd, 0xa9, 0x3a, 0xe6, 0x6a, 0x86, 0x5d, 0x86, 0x19, 0x1c, 0x87, 0x86, + 0xf6, 0x14, 0xfc, 0x04, 0x6c, 0xa2, 0x09, 0x08, 0x50, 0x6e, 0x12, 0x62, 0x0f, 0x6a, 0xfe, 0x2b, 0x0f, 0x49, 0x7b, + 0xdd, 0x34, 0xf5, 0x09, 0xa6, 0x38, 0x2c, 0x83, 0x75, 0x5b, 0xb6, 0x57, 0xb7, 0xaa, 0x8c, 0xe3, 0x1a, 0x60, 0x6c, + 0xe9, 0x1c, 0x47, 0x61, 0x1a, 0xe2, 0x7f, 0x0d, 0xa8, 0x0b, 0x73, 0xab, 0x76, 0x13, 0xfa, 0x66, 0x49, 0x53, 0x3e, + 0x9a, 0xdc, 0x1f, 0x1b, 0x9a, 0x13, 0xfd, 0xbe, 0xc0, 0x8c, 0x6b, 0x89, 0x4b, 0x16, 0x7a, 0xda, 0x06, 0x65, 0xa7, + 0x6b, 0x5c, 0x65, 0xfc, 0x6a, 0xf4, 0xcb, 0xb7, 0xab, 0x57, 0x31, 0xc4, 0x8c, 0x28, 0x60, 0x6b, 0xde, 0x59, 0xc7, + 0x27, 0xda, 0x7d, 0x37, 0xe6, 0x97, 0xa7, 0xa8, 0x71, 0xa3, 0x94, 0x58, 0x2c, 0x92, 0xf7, 0x15, 0x6e, 0x6b, 0x3e, + 0xd8, 0x5e, 0xf9, 0xf8, 0xeb, 0x79, 0x28, 0x04, 0x4f, 0xa8, 0x92, 0x20, 0xd1, 0x40, 0x37, 0xad, 0xd7, 0x82, 0x96, + 0xde, 0x97, 0x94, 0x66, 0x9e, 0xfb, 0xcb, 0xa6, 0x5d, 0x02, 0x42, 0x55, 0x03, 0x39, 0x3f, 0x45, 0x93, 0x2f, 0xa6, + 0xd3, 0x31, 0x82, 0x4f, 0x9a, 0x9c, 0x23, 0x0c, 0xa7, 0xdd, 0x7e, 0x97, 0x9f, 0xfe, 0x26, 0x47, 0x07, 0x9e, 0xfb, + 0x49, 0xea, 0xdb, 0xa1, 0xf0, 0xe9, 0x77, 0xbd, 0x18, 0x7d, 0xf5, 0x8d, 0x90, 0xbe, 0xed, 0xc4, 0xc6, 0x41, 0x90, + 0x37, 0xf2, 0x42, 0x84, 0x08, 0x76, 0x49, 0x20, 0xcc, 0x65, 0xfd, 0x46, 0xbc, 0x85, 0xaf, 0xe8, 0x2d, 0x35, 0x47, + 0x4f, 0xa3, 0x03, 0x3d, 0x9c, 0xb0, 0xbe, 0x8b, 0x0f, 0xa3, 0x2f, 0xb0, 0xe6, 0xe1, 0xb3, 0x00, 0x90, 0x8e, 0x61, + 0x15, 0xc0, 0xda, 0x60, 0xee, 0x18, 0x6e, 0xeb, 0xf4, 0xc4, 0x5a, 0xe6, 0x00, 0xbb, 0xdc, 0xc9, 0x71, 0x43, 0x77, + 0x0e, 0x41, 0xc1, 0xbc, 0x1d, 0x58, 0x23, 0xff, 0xcf, 0xb4, 0xa1, 0x3b, 0xab, 0x98, 0x58, 0x06, 0x22, 0xcd, 0x11, + 0x09, 0x0d, 0x5f, 0x77, 0x2f, 0x02, 0x07, 0xf0, 0x11, 0x83, 0xaf, 0x41, 0xc5, 0xf3, 0xdc, 0xe4, 0x57, 0xf5, 0xf3, + 0x4b, 0xc4, 0xde, 0x14, 0xaf, 0xeb, 0xa9, 0xbb, 0x2b, 0x0f, 0x7f, 0xa7, 0x14, 0x00, 0xbd, 0x54, 0x76, 0x15, 0x98, + 0xc9, 0xc1, 0x26, 0x32, 0xfc, 0x5c, 0x2f, 0xa1, 0x32, 0x6d, 0xf6, 0x84, 0x10, 0x2e, 0x48, 0x39, 0xb9, 0x1e, 0x2f, + 0x46, 0x7e, 0x02, 0x2a, 0x02, 0x6d, 0x02, 0xc8, 0xb2, 0x3f, 0x82, 0x45, 0xca, 0x01, 0x81, 0x78, 0x17, 0x17, 0x7d, + 0xea, 0x2d, 0x0d, 0x92, 0x98, 0xdd, 0x4b, 0x11, 0x30, 0x88, 0xcb, 0x84, 0x12, 0x34, 0x6c, 0x4d, 0xd9, 0xb7, 0x10, + 0xb9, 0x23, 0x74, 0xd8, 0x11, 0x66, 0x06, 0x5d, 0x25, 0xf2, 0x1f, 0x1d, 0x2d, 0xa9, 0x82, 0x87, 0xe9, 0xc9, 0xb3, + 0x15, 0xcd, 0x86, 0x93, 0x06, 0x12, 0x12, 0xf8, 0x50, 0x88, 0x03, 0x1b, 0x6f, 0x48, 0xa2, 0x60, 0x3d, 0x48, 0xfe, + 0x74, 0xd9, 0xf2, 0xba, 0xf3, 0x2c, 0x3b, 0xbe, 0x63, 0x68, 0x0e, 0x79, 0x8c, 0x44, 0x11, 0x94, 0xc2, 0xef, 0xa0, + 0xa4, 0x45, 0xa6, 0x12, 0x50, 0xae, 0x15, 0xd9, 0xe1, 0xa9, 0x2a, 0x31, 0x01, 0x5a, 0xa0, 0x07, 0xd1, 0xbd, 0xcb, + 0x42, 0xd3, 0x74, 0xf0, 0xda, 0xa1, 0x61, 0x2c, 0x83, 0xa9, 0x0e, 0x2e, 0x5b, 0xa1, 0x38, 0x32, 0xe9, 0x90, 0x51, + 0x70, 0x72, 0xeb, 0xac, 0xcb, 0x26, 0x37, 0xbf, 0xbd, 0x57, 0x74, 0x74, 0x0c, 0x64, 0x75, 0x9e, 0xde, 0x3c, 0xcf, + 0x66, 0x08, 0x06, 0xe9, 0xe3, 0x69, 0x57, 0xf1, 0x72, 0x9a, 0x81, 0x69, 0xd5, 0xf6, 0x6d, 0x19, 0x2e, 0x37, 0xb1, + 0xe4, 0xaa, 0xdb, 0x87, 0xb9, 0xcc, 0x67, 0xa7, 0x93, 0xec, 0xb7, 0xd6, 0xe0, 0xc8, 0x69, 0x66, 0xfd, 0x46, 0xf9, + 0x3c, 0x3f, 0x32, 0x95, 0x6f, 0x0e, 0x93, 0x44, 0x6a, 0xd7, 0x50, 0xad, 0xc2, 0x0c, 0x3f, 0x19, 0x44, 0xbd, 0x06, + 0x54, 0x1b, 0xad, 0x18, 0x6e, 0xe0, 0xc5, 0xe6, 0xc9, 0xd2, 0x75, 0xcc, 0x8c, 0xab, 0xc0, 0x2c, 0x26, 0x95, 0x18, + 0xdf, 0x8b, 0x04, 0x19, 0xb4, 0xa7, 0xfb, 0x54, 0x34, 0xd6, 0x97, 0x40, 0x27, 0x8b, 0x68, 0x03, 0x06, 0xe6, 0x10, + 0xea, 0x58, 0xa0, 0xb1, 0x71, 0x98, 0x45, 0x6d, 0x2b, 0x33, 0x9a, 0x2a, 0x83, 0x61, 0x0c, 0xb5, 0x01, 0x5c, 0xdd, + 0xaa, 0x85, 0x94, 0x8c, 0xb2, 0xee, 0x32, 0x1a, 0x28, 0xa1, 0x63, 0x19, 0x2b, 0x3c, 0x52, 0x32, 0x5c, 0x19, 0x71, + 0x1a, 0xe0, 0xcb, 0xd3, 0xff, 0xf7, 0x27, 0x32, 0x6a, 0xe9, 0xee, 0x48, 0xde, 0xb9, 0xec, 0xe8, 0x4a, 0x33, 0x9e, + 0xa7, 0xcb, 0xe9, 0x8b, 0xd4, 0x6d, 0xa9, 0x96, 0xf9, 0xc3, 0xe8, 0x18, 0x85, 0xaf, 0xed, 0xdb, 0x6d, 0x25, 0x1a, + 0xce, 0x30, 0x62, 0xae, 0x7c, 0xe3, 0x16, 0xf5, 0x5a, 0x8a, 0xee, 0xb7, 0x8c, 0x9c, 0x4a, 0x75, 0xc7, 0x1b, 0x97, + 0x1a, 0x5e, 0x29, 0xfd, 0x87, 0x79, 0x5e, 0xcc, 0xb1, 0xdd, 0xf6, 0x71, 0xb5, 0xb2, 0xcb, 0x89, 0xce, 0x9b, 0xe7, + 0x24, 0xe1, 0x6d, 0x8f, 0x63, 0x2b, 0x91, 0xe2, 0xb1, 0x34, 0x7f, 0x57, 0x4d, 0xb6, 0x9b, 0x5f, 0x7d, 0x2e, 0xc8, + 0x5a, 0x4c, 0xba, 0xd5, 0x56, 0xa5, 0x35, 0xf3, 0xe0, 0xdd, 0x9e, 0x39, 0xd2, 0x53, 0x12, 0x34, 0xdc, 0x2e, 0xe4, + 0xd3, 0x20, 0xd2, 0x5b, 0x66, 0x74, 0x58, 0x93, 0x57, 0xbe, 0xb1, 0x09, 0x0e, 0xe1, 0x78, 0x6b, 0x34, 0x0f, 0x93, + 0x9d, 0x4e, 0xea, 0xc5, 0xff, 0x33, 0x5b, 0xf8, 0x36, 0x75, 0xf2, 0x57, 0x5c, 0xe9, 0x20, 0xc5, 0xc5, 0x14, 0x1f, + 0x8e, 0x11, 0xcc, 0x97, 0xf4, 0x1d, 0x0a, 0x8f, 0xa6, 0x9c, 0x06, 0x06, 0x21, 0x66, 0xcf, 0xbe, 0x73, 0xf7, 0x76, + 0xbc, 0x25, 0xce, 0xa8, 0x2c, 0x6b, 0x8a, 0x25, 0x18, 0xa4, 0x79, 0x1d, 0x10, 0x00, 0x57, 0x2e, 0x88, 0x5d, 0x81, + 0xc8, 0x96, 0x17, 0xd1, 0xe2, 0xdd, 0x2f, 0x4b, 0xa3, 0xb8, 0x29, 0xf1, 0x99, 0xec, 0xf6, 0x44, 0x30, 0xc0, 0x2d, + 0xc8, 0x0e, 0xc7, 0x0e, 0x16, 0xc4, 0x1c, 0x09, 0xde, 0x15, 0x65, 0x58, 0x92, 0x3a, 0x50, 0x2c, 0x5a, 0xd4, 0x05, + 0x13, 0x13, 0x29, 0x64, 0x6b, 0xab, 0x84, 0x00, 0x69, 0xa2, 0xf6, 0x12, 0x58, 0xd4, 0x34, 0x7b, 0xa2, 0xea, 0x62, + 0x92, 0xbb, 0x21, 0xf7, 0x34, 0x1e, 0xfc, 0x3c, 0x94, 0xcc, 0xb1, 0x37, 0x89, 0x90, 0x7f, 0xbd, 0xd9, 0xfa, 0x05, + 0xf6, 0x0e, 0x7e, 0xd1, 0x10, 0xbe, 0x9a, 0xc2, 0x1a, 0x92, 0x30, 0xab, 0x5c, 0x78, 0xab, 0x24, 0x40, 0x81, 0xb2, + 0xac, 0x4f, 0x8b, 0x03, 0x46, 0x1f, 0x0a, 0xca, 0x16, 0xcb, 0x39, 0x89, 0xd9, 0x71, 0x11, 0x5b, 0x72, 0x2f, 0xfa, + 0xfc, 0xfc, 0x65, 0x1c, 0xef, 0x11, 0x81, 0xca, 0xad, 0xf2, 0xfe, 0x48, 0xc9, 0x01, 0x03, 0x33, 0xfd, 0x29, 0x8d, + 0xe8, 0xdc, 0x7f, 0x3f, 0xd5, 0x0f, 0x39, 0xf0, 0x4b, 0xe0, 0x38, 0xd0, 0xa7, 0x2c, 0x5a, 0xce, 0x06, 0xaa, 0x7b, + 0x9c, 0x53, 0xfb, 0x58, 0x5c, 0x22, 0xae, 0x4c, 0x42, 0xa0, 0xbb, 0x5c, 0x48, 0x82, 0xc5, 0xa7, 0x60, 0x48, 0x36, + 0x01, 0xd3, 0x58, 0x61, 0x73, 0xad, 0x79, 0x77, 0x80, 0x2e, 0x36, 0x58, 0xc1, 0x2b, 0x1c, 0x0c, 0xbd, 0xb6, 0x66, + 0x4e, 0x6b, 0x35, 0xbd, 0x13, 0x25, 0x89, 0x6c, 0xb2, 0xdb, 0x8f, 0x23, 0x7b, 0x43, 0x1a, 0x22, 0xfc, 0xb9, 0x51, + 0x5a, 0x14, 0x8a, 0xe6, 0x6a, 0x85, 0x88, 0x7d, 0xaf, 0x52, 0x4e, 0x32, 0xa9, 0x5a, 0x6a, 0x72, 0x5b, 0x29, 0x21, + 0xd6, 0x85, 0x7f, 0x14, 0xd4, 0xcd, 0xa8, 0x3f, 0x25, 0x37, 0xd0, 0x37, 0xe2, 0x4d, 0x02, 0x6f, 0xac, 0xf5, 0x21, + 0x28, 0x9a, 0x68, 0xfc, 0x08, 0x8a, 0xc5, 0xc1, 0x04, 0x4f, 0x3c, 0x97, 0x61, 0x09, 0x48, 0xa7, 0x78, 0xe8, 0xc5, + 0x84, 0x8b, 0x40, 0x0b, 0xce, 0x59, 0xbe, 0x7b, 0xa7, 0x79, 0xa0, 0xd3, 0x7a, 0x21, 0x89, 0xd9, 0x5e, 0x75, 0xba, + 0xf4, 0x8a, 0x81, 0xf3, 0xeb, 0x4c, 0x59, 0x22, 0xee, 0x49, 0x5e, 0x6e, 0x37, 0x96, 0xd1, 0xc6, 0x22, 0xe6, 0x74, + 0xa6, 0x82, 0x3f, 0x9b, 0x7a, 0x5b, 0x27, 0x16, 0xbf, 0x1d, 0x4f, 0xad, 0x8c, 0xd7, 0x01, 0xee, 0x12, 0x6f, 0xca, + 0xa0, 0x54, 0xc4, 0xeb, 0x41, 0x84, 0x48, 0x90, 0x12, 0x9d, 0x46, 0x86, 0xd2, 0x63, 0x3f, 0x48, 0xcc, 0x06, 0xd4, + 0x88, 0x1d, 0xd8, 0x39, 0xca, 0x6e, 0x85, 0x9f, 0xfb, 0xbb, 0xf5, 0xf0, 0x7b, 0x95, 0x3e, 0xe9, 0x2d, 0xcc, 0x4a, + 0xf3, 0xa4, 0x1a, 0x56, 0x60, 0xd9, 0x71, 0xfb, 0x97, 0x67, 0xae, 0xc2, 0xe0, 0xdc, 0x56, 0xc3, 0x9d, 0x3e, 0x97, + 0xef, 0x2f, 0xe0, 0xef, 0x4f, 0xbf, 0xaf, 0xf9, 0x02, 0xb3, 0x8e, 0x94, 0x50, 0xd7, 0x6e, 0x23, 0x22, 0xee, 0xc5, + 0xab, 0xab, 0x14, 0x5a, 0x80, 0x2c, 0xbf, 0x80, 0x67, 0xc7, 0xb7, 0x46, 0xba, 0x4f, 0x8e, 0x54, 0x20, 0x11, 0xf2, + 0x56, 0x41, 0x58, 0x09, 0x38, 0x52, 0xd8, 0x2c, 0xb2, 0xa0, 0x4f, 0x25, 0x74, 0x0d, 0x3f, 0x25, 0xbe, 0xbc, 0x9a, + 0x2b, 0x7e, 0x0c, 0xe9, 0x04, 0x74, 0xd8, 0x9d, 0x0f, 0x22, 0xb0, 0x41, 0xce, 0x7a, 0xc9, 0x68, 0xde, 0xc9, 0x67, + 0xa3, 0xc8, 0xb4, 0x63, 0xa5, 0xfd, 0xda, 0xa8, 0xdb, 0x3e, 0x1e, 0xdf, 0x29, 0x06, 0x3c, 0x38, 0x6c, 0x6e, 0x37, + 0x69, 0x20, 0x6f, 0xd5, 0xde, 0xfb, 0x7a, 0xc7, 0xb5, 0x5d, 0x90, 0x7c, 0xb2, 0xb4, 0x83, 0x28, 0xa4, 0xdb, 0x8d, + 0x9c, 0x2a, 0xea, 0x17, 0x45, 0xfb, 0x22, 0x2d, 0xef, 0xee, 0x12, 0x8f, 0x7b, 0xf5, 0x24, 0x4e, 0x2e, 0x8e, 0x73, + 0x4d, 0x25, 0xe2, 0xc8, 0x97, 0xa8, 0x2f, 0x4f, 0xd1, 0x66, 0x5a, 0x53, 0x83, 0xab, 0x5c, 0xab, 0xa6, 0x44, 0x5e, + 0x8a, 0x9e, 0xd9, 0xcd, 0xe2, 0xaf, 0xb8, 0xa6, 0x42, 0x33, 0xe0, 0xfc, 0x59, 0xfb, 0xe6, 0xcf, 0x04, 0x0f, 0x2e, + 0x8b, 0x7f, 0x94, 0xfe, 0x97, 0x53, 0x4f, 0x64, 0xf9, 0x05, 0xfe, 0x6a, 0xbc, 0x59, 0xbc, 0xf9, 0xef, 0x2e, 0x72, + 0x9f, 0x2f, 0xd8, 0x51, 0xb0, 0xde, 0x5e, 0x8e, 0x2f, 0x72, 0x7d, 0x39, 0x49, 0x7c, 0x83, 0x30, 0x80, 0xd3, 0x21, + 0x2d, 0xeb, 0x9d, 0xd6, 0x04, 0x9f, 0x81, 0x80, 0x90, 0x6c, 0xe7, 0xec, 0xc4, 0xd6, 0x1f, 0x49, 0xb4, 0x19, 0xcc, + 0xe4, 0x65, 0x90, 0xec, 0x6b, 0x24, 0x00, 0x72, 0x6a, 0x33, 0xd2, 0x71, 0x3e, 0x6d, 0x02, 0x6d, 0x32, 0x49, 0xdd, + 0x6e, 0x01, 0x5c, 0x80, 0x54, 0x94, 0xaf, 0xd6, 0x4d, 0x14, 0x35, 0xf3, 0x2a, 0x14, 0x5f, 0xed, 0xf5, 0x0b, 0xb4, + 0x53, 0x4d, 0x7b, 0x35, 0xd7, 0x81, 0xc0, 0x7a, 0xd5, 0x21, 0x42, 0x4b, 0xb6, 0x82, 0x1e, 0x7f, 0x4f, 0x7c, 0xb7, + 0xf9, 0x80, 0x7a, 0x83, 0xe5, 0x6e, 0xaf, 0x39, 0x9d, 0xda, 0xcd, 0x90, 0x1a, 0xf4, 0x19, 0x54, 0x51, 0xb0, 0x04, + 0xbc, 0xfd, 0xcc, 0xee, 0x66, 0x4b, 0x45, 0x36, 0xb7, 0xf8, 0xe2, 0x60, 0x5b, 0x24, 0x90, 0x8e, 0x23, 0x60, 0x4d, + 0x66, 0xa4, 0x24, 0xb3, 0x53, 0x9a, 0x32, 0x0a, 0x40, 0x06, 0xf0, 0x62, 0x12, 0xf6, 0x98, 0xf4, 0xdf, 0x87, 0x57, + 0x69, 0xfd, 0xd5, 0xfb, 0x62, 0xe4, 0x3d, 0xff, 0x68, 0x7a, 0xe0, 0xf4, 0x7b, 0x6b, 0x97, 0xb3, 0xd7, 0xa9, 0x47, + 0x8d, 0x25, 0xdf, 0x38, 0x80, 0xff, 0x84, 0xa7, 0xce, 0xea, 0x30, 0xdf, 0x8e, 0x9c, 0x52, 0xe5, 0xca, 0xbd, 0x0a, + 0xee, 0xf7, 0x07, 0xe1, 0xfe, 0xff, 0x55, 0xed, 0x66, 0xf8, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, 0x75, 0x58, 0x6b, + 0xee, 0x7f, 0x6b, 0x70, 0xe9, 0x77, 0x14, 0xd4, 0x75, 0xed, 0xdf, 0x79, 0x10, 0x68, 0x05, 0x5e, 0x17, 0x77, 0x26, + 0x2b, 0x3d, 0x4d, 0xe9, 0xc1, 0x20, 0x3a, 0xf8, 0xff, 0xb3, 0x6c, 0x8e, 0xbd, 0x38, 0x61, 0xb2, 0xb2, 0xfd, 0x7e, + 0x1a, 0x0b, 0xb0, 0x9c, 0x44, 0x69, 0xe3, 0x80, 0xf7, 0x95, 0x1f, 0xd7, 0xe8, 0xe7, 0x80, 0x4e, 0xac, 0x53, 0x40, + 0xdf, 0xd5, 0xf4, 0x09, 0xe2, 0xb1, 0x87, 0xd7, 0x90, 0x7b, 0x47, 0x70, 0x5f, 0x6b, 0x1c, 0x2e, 0x28, 0x3f, 0x14, + 0x77, 0x72, 0x31, 0x95, 0xfc, 0x52, 0xfa, 0xbd, 0x66, 0xf7, 0x45, 0x29, 0x37, 0xc4, 0x50, 0x93, 0x5b, 0x7f, 0x13, + 0x21, 0xdd, 0x2b, 0x92, 0xc8, 0x6a, 0x51, 0x77, 0xae, 0x92, 0x4e, 0x9c, 0xdd, 0xb3, 0xad, 0xca, 0x0c, 0xc0, 0x8b, + 0x2a, 0x97, 0x92, 0xb7, 0xeb, 0x40, 0x19, 0xd3, 0x7b, 0xec, 0x7c, 0x1d, 0x0d, 0xa8, 0xa5, 0xf4, 0x55, 0xde, 0xf0, + 0xef, 0xfc, 0x02, 0xf3, 0xae, 0xc6, 0xba, 0xf1, 0xc4, 0x3e, 0x1a, 0xda, 0x4d, 0xe3, 0x3e, 0x42, 0x40, 0x1d, 0x6e, + 0xc8, 0xa9, 0x46, 0xa2, 0x6b, 0x3e, 0xcb, 0xc3, 0x88, 0xb2, 0x91, 0xb7, 0xe0, 0x4c, 0x9c, 0xb3, 0x4e, 0x41, 0x86, + 0x99, 0xa1, 0x61, 0x05, 0x4d, 0x6f, 0x31, 0xc6, 0xf6, 0xf2, 0x8e, 0xef, 0x8e, 0xb2, 0xb5, 0xfd, 0xfa, 0xcb, 0x02, + 0x81, 0x74, 0x5c, 0x04, 0xef, 0x14, 0x5f, 0xe0, 0x91, 0x34, 0x32, 0xf5, 0x60, 0xdf, 0x5f, 0xd2, 0x8b, 0xb0, 0xff, + 0xd6, 0x9c, 0x26, 0x97, 0x2f, 0xe7, 0x4c, 0x69, 0x51, 0xe7, 0x6c, 0xf1, 0xe2, 0xb6, 0x71, 0xff, 0xd3, 0xe4, 0xda, + 0x98, 0xf5, 0xe7, 0x9c, 0x14, 0x15, 0x4e, 0xb4, 0xce, 0xe6, 0x62, 0xef, 0xbd, 0xe7, 0xbc, 0x1e, 0x2c, 0xbb, 0x07, + 0x67, 0x32, 0x62, 0xeb, 0xad, 0x2e, 0xbc, 0x64, 0xdf, 0x26, 0x6e, 0x9b, 0x0a, 0xae, 0x29, 0x1e, 0xbc, 0x7a, 0x99, + 0xde, 0x5d, 0x9d, 0x2c, 0x59, 0xac, 0x59, 0x7e, 0x34, 0xa0, 0x9b, 0x7d, 0x58, 0xb7, 0x8d, 0xc6, 0xf1, 0x9a, 0x4a, + 0x6c, 0x9b, 0x58, 0xc6, 0xac, 0xa6, 0x13, 0xc1, 0xfd, 0x5f, 0x36, 0xb8, 0x76, 0xa6, 0x0e, 0xc5, 0xb5, 0x19, 0x85, + 0x52, 0xf0, 0xa3, 0x04, 0x24, 0x5c, 0x32, 0x96, 0x0c, 0x9c, 0xe0, 0xdb, 0x39, 0x9d, 0x4c, 0x99, 0xa6, 0xe1, 0x74, + 0xf3, 0xc3, 0x69, 0x07, 0xdf, 0x76, 0x12, 0x23, 0x20, 0xb9, 0x1f, 0x19, 0xb9, 0xc1, 0x64, 0x49, 0xa8, 0x11, 0x77, + 0xeb, 0xe4, 0x17, 0x74, 0xcc, 0x64, 0x89, 0xa7, 0x52, 0x93, 0x87, 0xf3, 0xf1, 0x09, 0xfb, 0xf9, 0x67, 0xeb, 0x6f, + 0xd6, 0x37, 0xed, 0x2a, 0xdc, 0x28, 0xeb, 0xd4, 0x7e, 0x86, 0x3d, 0xab, 0x12, 0x42, 0xde, 0x94, 0xf7, 0xf6, 0x96, + 0xda, 0xa7, 0xdf, 0x37, 0x22, 0xb8, 0xfa, 0xce, 0xd0, 0xea, 0xcf, 0x29, 0x82, 0xe5, 0x6e, 0xd7, 0x4a, 0xa5, 0xc9, + 0xea, 0x89, 0xef, 0xfd, 0x1a, 0x6f, 0x45, 0xce, 0x83, 0x97, 0xec, 0x8d, 0x38, 0x7f, 0x2c, 0x8a, 0xef, 0x9e, 0x3f, + 0x22, 0x16, 0x97, 0x77, 0x73, 0x0c, 0xb1, 0xc9, 0xe5, 0x21, 0x95, 0xc4, 0x34, 0xf8, 0x04, 0x6a, 0x3b, 0xab, 0xa1, + 0x44, 0x57, 0x52, 0xab, 0x2b, 0xbe, 0x94, 0x02, 0x96, 0xca, 0xa8, 0x92, 0xa1, 0xae, 0x0e, 0xa7, 0x8e, 0xd2, 0xf2, + 0xc3, 0xab, 0x0a, 0x2e, 0x95, 0x79, 0x68, 0x69, 0x0c, 0xbf, 0xf4, 0xe9, 0x05, 0x63, 0x18, 0xd9, 0x66, 0x03, 0x97, + 0xa7, 0xe8, 0x44, 0xef, 0xe0, 0x0b, 0xa1, 0xe3, 0x43, 0x33, 0xf9, 0x02, 0x8d, 0xd7, 0x50, 0x92, 0xe1, 0x90, 0x73, + 0x55, 0xdc, 0xa2, 0x96, 0xb8, 0x7f, 0x45, 0xd6, 0x53, 0x4d, 0x69, 0xd1, 0x9e, 0x96, 0xa1, 0xa0, 0xb4, 0x4e, 0x72, + 0x5d, 0x61, 0x7a, 0x99, 0x74, 0x52, 0x4f, 0x6b, 0x70, 0x2b, 0x77, 0x8e, 0x44, 0x66, 0xf7, 0x4d, 0xd3, 0x91, 0x42, + 0x6e, 0x57, 0x40, 0xd2, 0xae, 0x3f, 0x8f, 0x55, 0xc8, 0x3e, 0x24, 0x4d, 0x2d, 0xe9, 0xfe, 0xcc, 0x0e, 0x84, 0x96, + 0xf7, 0xdd, 0xd8, 0xa9, 0x23, 0xdd, 0x83, 0x60, 0xec, 0xfc, 0x56, 0x69, 0x37, 0xcd, 0x49, 0xbc, 0x71, 0xf1, 0x6b, + 0x8f, 0x02, 0xb2, 0xa5, 0x19, 0x7c, 0x6d, 0x4d, 0x40, 0xbb, 0x7c, 0x03, 0x6b, 0x2d, 0x76, 0x30, 0xde, 0xe7, 0x6d, + 0xe8, 0xa1, 0x0f, 0x6c, 0x94, 0x6a, 0x1e, 0x7e, 0xa3, 0x54, 0xfd, 0x8e, 0x9c, 0x42, 0xd5, 0x73, 0xfe, 0xba, 0x24, + 0x8e, 0x8d, 0xac, 0xb6, 0x8b, 0x23, 0x06, 0x1b, 0x18, 0xe3, 0x50, 0x5f, 0x20, 0x62, 0xde, 0x31, 0x32, 0x40, 0x87, + 0xa4, 0x43, 0x59, 0x27, 0xd3, 0x44, 0x42, 0xcc, 0x03, 0x12, 0xec, 0x1d, 0x40, 0x3d, 0x80, 0xff, 0xc9, 0xa4, 0x45, + 0xfe, 0xa9, 0x5d, 0xe5, 0xdc, 0x31, 0xc7, 0x5f, 0x6a, 0x76, 0xcd, 0x46, 0x99, 0xd5, 0xd4, 0xe0, 0x7e, 0xd1, 0x14, + 0x11, 0xd5, 0xf2, 0x5a, 0x36, 0x4a, 0x67, 0x8e, 0xa4, 0xf8, 0x8b, 0xd9, 0xd2, 0x93, 0xfe, 0xf6, 0xbe, 0x94, 0x3e, + 0x7b, 0xf7, 0xfc, 0xce, 0x22, 0x67, 0xaa, 0xdd, 0xfd, 0x14, 0x87, 0x4f, 0x7d, 0xb2, 0xe4, 0x5f, 0x3f, 0xfe, 0x8b, + 0x7f, 0x41, 0x6f, 0xf8, 0x0b, 0xd6, 0xa5, 0x11, 0xac, 0x5d, 0xf6, 0xf5, 0x25, 0xd8, 0xf1, 0xa1, 0xd1, 0xa7, 0x0c, + 0x2c, 0x05, 0x77, 0x41, 0x4b, 0xf0, 0x10, 0x60, 0xb2, 0xd5, 0x6a, 0xfd, 0x40, 0xdc, 0x3f, 0xbb, 0xae, 0x2b, 0x5f, + 0x2c, 0xdc, 0x57, 0xdb, 0xf7, 0x45, 0xaa, 0xd5, 0xe7, 0xdd, 0x4e, 0x26, 0xc7, 0xbb, 0xff, 0x42, 0x0d, 0xfa, 0x46, + 0x84, 0xc2, 0x33, 0x3b, 0x3d, 0x5d, 0x0d, 0x8b, 0xd7, 0x55, 0xbf, 0x98, 0xaa, 0xb6, 0xb8, 0xa9, 0xa6, 0xc5, 0x8b, + 0xea, 0xf4, 0xe0, 0xff, 0xae, 0x78, 0xc9, 0x33, 0x61, 0x98, 0x0f, 0x34, 0xc8, 0xd9, 0xe3, 0x97, 0xa1, 0x96, 0x1b, + 0x1f, 0x28, 0x76, 0xab, 0xa2, 0x70, 0xda, 0xa5, 0xef, 0x7f, 0xdc, 0x67, 0xf0, 0x46, 0x0a, 0x7a, 0x19, 0xd3, 0x1e, + 0x2d, 0x69, 0xd0, 0x4c, 0x22, 0x48, 0xec, 0xeb, 0x4e, 0x7b, 0x27, 0x1d, 0x48, 0x18, 0xf4, 0xeb, 0x6d, 0xcb, 0x35, + 0x1e, 0x45, 0x98, 0x30, 0x79, 0xcb, 0x40, 0x1c, 0x0a, 0xbe, 0x42, 0x35, 0x22, 0xda, 0x3b, 0x61, 0x9b, 0x24, 0x82, + 0x20, 0x86, 0x2e, 0x75, 0x52, 0x07, 0xbb, 0x4c, 0x73, 0xeb, 0x3c, 0x96, 0x00, 0x69, 0xc5, 0x9a, 0xf2, 0x53, 0x5f, + 0xb4, 0x62, 0x92, 0x8a, 0xda, 0x5c, 0x98, 0x2a, 0xa1, 0x9b, 0x11, 0x62, 0x7d, 0xcb, 0x05, 0xdf, 0xe6, 0x75, 0x2d, + 0x02, 0x2d, 0x37, 0x6b, 0x06, 0xe4, 0x8c, 0x2e, 0xe4, 0x8d, 0xb9, 0x90, 0x2d, 0x96, 0x69, 0xbd, 0x30, 0x4e, 0x35, + 0x6d, 0xda, 0x88, 0xc8, 0x5e, 0xfd, 0xfa, 0x16, 0x88, 0xec, 0x43, 0x5f, 0xd4, 0x99, 0xde, 0xd4, 0xad, 0xb0, 0x89, + 0x41, 0xa6, 0xa1, 0x2a, 0x51, 0x1a, 0xa2, 0x11, 0x17, 0xf1, 0x68, 0x57, 0x89, 0xb0, 0xf1, 0x93, 0xfc, 0x9a, 0x49, + 0x0a, 0x3a, 0x80, 0x58, 0xa0, 0xe2, 0xba, 0xf6, 0x02, 0xe2, 0x90, 0x95, 0xde, 0x37, 0xfd, 0x53, 0x6e, 0xee, 0x8c, + 0x72, 0x33, 0xf4, 0x93, 0x26, 0x57, 0x70, 0x09, 0x31, 0xea, 0x21, 0x8a, 0xc8, 0x47, 0xb1, 0xef, 0x50, 0x27, 0x90, + 0x02, 0x4e, 0x14, 0x67, 0xd0, 0x38, 0x53, 0x81, 0x03, 0xf6, 0x81, 0x16, 0x71, 0x0c, 0x45, 0xf6, 0xa3, 0xae, 0x3a, + 0xd7, 0x23, 0x93, 0x54, 0x77, 0xd2, 0x6f, 0xfe, 0x73, 0x55, 0x65, 0xb0, 0x97, 0x57, 0xab, 0x6c, 0x3e, 0x28, 0xf9, + 0x07, 0xf6, 0x37, 0x73, 0x85, 0x8a, 0xb5, 0xf3, 0x36, 0x9c, 0xd1, 0xe6, 0x88, 0xb1, 0x85, 0xe5, 0x71, 0x6e, 0xa9, + 0x27, 0x70, 0xad, 0xbf, 0x03, 0xcf, 0x70, 0xf6, 0x2d, 0x61, 0x64, 0x5e, 0x4e, 0x26, 0x0b, 0xdd, 0xcc, 0x6e, 0x77, + 0x79, 0xe4, 0x6c, 0x98, 0xd4, 0x9e, 0x2c, 0xea, 0xd7, 0x00, 0xe3, 0x47, 0xbc, 0xe6, 0xc1, 0x9e, 0x81, 0xeb, 0x91, + 0x48, 0xc1, 0x66, 0x80, 0x77, 0x32, 0x76, 0xc4, 0xca, 0x89, 0xb3, 0x34, 0x06, 0x9d, 0x0b, 0x57, 0xa5, 0xe9, 0xef, + 0x2d, 0x51, 0x4a, 0x00, 0x98, 0x41, 0xe8, 0xfd, 0xdc, 0x36, 0xf7, 0xad, 0xa8, 0x4d, 0x49, 0x1a, 0xe2, 0x0c, 0xa2, + 0x72, 0xa0, 0x62, 0x17, 0x34, 0x1d, 0xed, 0x5b, 0x2a, 0xc7, 0xc9, 0x0c, 0x12, 0xa6, 0x5e, 0x19, 0x77, 0xc5, 0x5f, + 0xfa, 0xac, 0x56, 0xff, 0xfc, 0xc8, 0xf4, 0x54, 0xff, 0x88, 0xec, 0xf6, 0x55, 0xf1, 0x3c, 0x57, 0x7e, 0x62, 0x4a, + 0xcd, 0xd5, 0x76, 0x27, 0x43, 0xbc, 0xb1, 0xf4, 0x56, 0xcc, 0x1c, 0xb0, 0xde, 0x1a, 0x9e, 0xd7, 0xbb, 0x5e, 0xcc, + 0x1d, 0xf5, 0x4b, 0xba, 0xaf, 0xcf, 0xff, 0x26, 0x03, 0xfb, 0x0d, 0x93, 0x9c, 0xfb, 0x9a, 0xf6, 0x3c, 0xa1, 0xaf, + 0x16, 0xf3, 0x9a, 0x26, 0x36, 0xf6, 0x99, 0x67, 0xde, 0xd2, 0x34, 0xc8, 0x9e, 0xee, 0xeb, 0x95, 0xd6, 0x99, 0x39, + 0xc7, 0x87, 0x83, 0xe6, 0xf3, 0x27, 0xdd, 0x1b, 0x07, 0xdd, 0x15, 0x28, 0x2e, 0xdd, 0x27, 0xdf, 0x51, 0xf8, 0xc2, + 0x5c, 0x30, 0xed, 0x5c, 0x22, 0xe4, 0xc1, 0xcd, 0xf2, 0x04, 0xa4, 0xbc, 0xcc, 0x27, 0x90, 0x34, 0xcf, 0xcf, 0x97, + 0x98, 0x95, 0x22, 0xc1, 0xcd, 0x84, 0x59, 0x4f, 0x9b, 0x81, 0xe9, 0x66, 0x37, 0x9b, 0x77, 0xf5, 0xe4, 0x49, 0xe7, + 0xb5, 0x83, 0xa6, 0xce, 0xbf, 0xb2, 0xd9, 0xa7, 0x2f, 0x2a, 0xf5, 0x34, 0xad, 0xdc, 0xf5, 0x24, 0x7f, 0xaf, 0x44, + 0x99, 0x05, 0xf0, 0x5e, 0x4a, 0xe4, 0x29, 0x9e, 0xee, 0xe4, 0xa4, 0x89, 0x6a, 0x80, 0x14, 0xab, 0xbb, 0x13, 0xc3, + 0x46, 0xd5, 0x42, 0xa7, 0x1c, 0x3d, 0xe3, 0xd5, 0xcf, 0xd8, 0x23, 0xbe, 0x88, 0xd8, 0x89, 0x8d, 0xc2, 0x8f, 0x8a, + 0xa1, 0xc2, 0xfa, 0xb4, 0x2e, 0x83, 0x57, 0x86, 0xd5, 0x65, 0x2c, 0x06, 0xe4, 0xe7, 0xa6, 0x5c, 0x48, 0xa1, 0xe5, + 0xe7, 0xe8, 0x3e, 0x34, 0x35, 0x50, 0x6f, 0x7c, 0x1e, 0xef, 0xf2, 0xd9, 0xa4, 0xfe, 0x0d, 0x04, 0x7c, 0x90, 0x01, + 0xb5, 0x2c, 0x74, 0x5a, 0xcf, 0x9e, 0xe2, 0xc7, 0x4f, 0xfb, 0xdf, 0x58, 0xf2, 0xf1, 0xc7, 0xff, 0x14, 0xcf, 0x1e, + 0xfb, 0xa8, 0x52, 0x68, 0x12, 0xbc, 0xa7, 0xb0, 0x6f, 0xb3, 0xff, 0xef, 0x91, 0x67, 0xd1, 0xc4, 0x8b, 0xe1, 0x51, + 0x9d, 0x5d, 0x20, 0x4a, 0x6a, 0x7d, 0xe8, 0x8b, 0xd8, 0x71, 0xdf, 0xf7, 0x60, 0x59, 0xba, 0x47, 0xdc, 0xe4, 0xc1, + 0xf5, 0x49, 0xec, 0xf6, 0x95, 0x89, 0x54, 0x6a, 0xfc, 0x8c, 0x5c, 0xc0, 0x58, 0x27, 0xed, 0x31, 0x5c, 0xda, 0xd2, + 0x48, 0xc1, 0xa6, 0x14, 0x67, 0x52, 0x80, 0xfb, 0x4c, 0x94, 0xbe, 0xb3, 0x8f, 0x20, 0xa9, 0xf7, 0x2f, 0x4d, 0x60, + 0x49, 0x5e, 0x97, 0x05, 0x12, 0x9f, 0x8f, 0x2b, 0xf7, 0xf9, 0x24, 0x20, 0x2e, 0x8a, 0x0b, 0x68, 0x0b, 0xc4, 0x18, + 0x15, 0xb9, 0x14, 0x3d, 0x64, 0x69, 0x2a, 0x26, 0xaa, 0x43, 0x7a, 0xc1, 0x6e, 0xdf, 0x0d, 0x94, 0x32, 0x2d, 0x74, + 0xfc, 0xd5, 0x89, 0x18, 0x28, 0x5d, 0x9e, 0xed, 0x6d, 0x61, 0x40, 0x2e, 0x17, 0x13, 0x82, 0x34, 0xbe, 0x9e, 0xc2, + 0xb2, 0xf3, 0x11, 0x5d, 0x25, 0x00, 0x29, 0xbc, 0x5b, 0xc4, 0xcd, 0xa0, 0xa0, 0xa4, 0x81, 0xaa, 0xa9, 0x8d, 0x1e, + 0x08, 0xb1, 0xec, 0x4c, 0xa9, 0xdc, 0x8a, 0x0a, 0x04, 0x01, 0x22, 0x1b, 0x7b, 0x90, 0xc8, 0xe9, 0x61, 0x7a, 0xb8, + 0xa3, 0x2d, 0x4a, 0xa6, 0x68, 0x04, 0x35, 0xda, 0xf4, 0x90, 0xa4, 0x07, 0xaf, 0x9b, 0x89, 0xc1, 0x89, 0xb3, 0xe1, + 0x17, 0xbc, 0xd7, 0x93, 0x7b, 0xbb, 0x36, 0xb2, 0xcf, 0x25, 0xe9, 0x10, 0x73, 0x78, 0xd8, 0xd5, 0xd3, 0xcd, 0x71, + 0xbb, 0xa7, 0x9c, 0x7b, 0x89, 0x9d, 0x80, 0xf6, 0xf6, 0xd4, 0x7d, 0x67, 0x25, 0x6a, 0x5d, 0xf0, 0x08, 0x29, 0xd7, + 0x49, 0xd7, 0x93, 0xef, 0x2f, 0xef, 0x6a, 0x53, 0x2a, 0x9b, 0x88, 0x54, 0x34, 0x99, 0x2a, 0x10, 0x53, 0x82, 0x34, + 0x96, 0x51, 0x2f, 0xb7, 0x73, 0xc4, 0x9e, 0x0e, 0xa3, 0xb8, 0x85, 0x37, 0xb3, 0x55, 0xf6, 0x26, 0xad, 0xaf, 0xb0, + 0x82, 0x69, 0x8a, 0x6a, 0xfe, 0xfb, 0x59, 0x56, 0xb4, 0x33, 0x10, 0x41, 0xa8, 0xe7, 0xb6, 0x25, 0xbb, 0x80, 0x46, + 0x39, 0x7f, 0xdb, 0x40, 0x9b, 0x0e, 0xfb, 0x20, 0xe4, 0x39, 0x32, 0xef, 0xe5, 0x5b, 0x22, 0xc4, 0x40, 0x4a, 0x90, + 0x81, 0xaf, 0x5d, 0x44, 0xd4, 0x1c, 0x16, 0xcd, 0x6d, 0xe0, 0xf0, 0x21, 0x5c, 0x91, 0x99, 0x60, 0x32, 0xc5, 0xdd, + 0x85, 0x38, 0xed, 0xb8, 0xc3, 0x3d, 0x3b, 0xea, 0x59, 0x93, 0x3b, 0x65, 0x1a, 0x69, 0x26, 0x79, 0x7a, 0xb7, 0x4a, + 0xa3, 0x6c, 0xe9, 0xc8, 0xc5, 0x26, 0x92, 0x4b, 0xb9, 0x85, 0x88, 0xdb, 0xb2, 0x76, 0xfa, 0xf6, 0xfb, 0xb2, 0x79, + 0x74, 0x2f, 0xbe, 0xf5, 0x3e, 0xec, 0xdc, 0xaa, 0xb7, 0x35, 0xdb, 0xd6, 0x4f, 0x4b, 0x81, 0x52, 0x06, 0xdc, 0x99, + 0xae, 0x64, 0x26, 0x55, 0x57, 0xbe, 0x68, 0xdb, 0x21, 0x5f, 0x98, 0xc0, 0xf4, 0x34, 0xbc, 0xcd, 0x6a, 0x9d, 0x50, + 0x94, 0xd2, 0x07, 0x62, 0x91, 0xf8, 0x30, 0x00, 0xc6, 0x07, 0xaf, 0x89, 0x5c, 0xf0, 0x33, 0xfc, 0x5c, 0x2a, 0xfd, + 0xae, 0xc9, 0x52, 0x14, 0x80, 0x3e, 0x88, 0xf6, 0xec, 0x34, 0xaa, 0xf9, 0x2a, 0x9b, 0xe9, 0xe4, 0x20, 0xa6, 0x7f, + 0xfc, 0xff, 0x5c, 0x05, 0xea, 0xb7, 0x23, 0x3d, 0x84, 0xf7, 0x9b, 0x04, 0xae, 0xd5, 0xc2, 0x98, 0x9e, 0xc4, 0xa8, + 0x7b, 0x58, 0x12, 0xe1, 0x40, 0x00, 0x5f, 0x45, 0x4d, 0xdc, 0x48, 0xe3, 0xad, 0xa2, 0xa7, 0xa8, 0x6f, 0xc3, 0x5b, + 0x77, 0xb2, 0x4f, 0xc6, 0xe1, 0x7e, 0x8e, 0xb9, 0x17, 0x25, 0xcb, 0x32, 0x88, 0x86, 0x41, 0xd1, 0x2d, 0x0c, 0xac, + 0x90, 0x9f, 0x2f, 0xe0, 0xcb, 0x30, 0xe7, 0x33, 0xa3, 0x64, 0xb4, 0x42, 0xf4, 0x2a, 0xa4, 0x0e, 0x12, 0xef, 0x66, + 0x98, 0x0d, 0x7a, 0x06, 0xc5, 0xfe, 0x60, 0xea, 0x54, 0x2a, 0x68, 0xaf, 0xaa, 0xd2, 0x64, 0x57, 0x92, 0x5b, 0x7b, + 0x15, 0x1d, 0xfd, 0x14, 0x44, 0x8e, 0x97, 0xa2, 0xc5, 0x17, 0x1e, 0x0b, 0xfb, 0x5d, 0xdc, 0x1c, 0xc7, 0x00, 0x3c, + 0x7f, 0xfa, 0xa9, 0x17, 0xb7, 0x22, 0x3b, 0xfd, 0x5b, 0xe2, 0xd2, 0x77, 0x8f, 0xa6, 0xf1, 0xff, 0x29, 0x64, 0x7f, + 0xe0, 0xb7, 0x08, 0xac, 0x3f, 0xed, 0x31, 0x38, 0xb8, 0x84, 0xeb, 0x2d, 0x62, 0xf3, 0x05, 0x2c, 0xcb, 0xdb, 0xad, + 0x79, 0x20, 0x24, 0xee, 0x0b, 0x63, 0x66, 0x4f, 0xca, 0x6a, 0x94, 0x08, 0xff, 0xba, 0x8f, 0x61, 0xff, 0x35, 0x71, + 0x09, 0xc2, 0x70, 0x6e, 0x5c, 0xe8, 0xef, 0xb4, 0xce, 0x9e, 0xe2, 0xfb, 0xa7, 0xfe, 0x66, 0xc9, 0xfb, 0x1f, 0xff, + 0x53, 0x9c, 0x79, 0x67, 0x5c, 0xa3, 0xb7, 0x4f, 0x6f, 0x6e, 0x22, 0x46, 0x4d, 0x5e, 0xcb, 0x0a, 0x67, 0x3f, 0x8b, + 0x9c, 0xcd, 0x84, 0x57, 0x27, 0x72, 0x81, 0x86, 0x91, 0x8f, 0x7b, 0x5e, 0xa2, 0x17, 0xec, 0xba, 0xa3, 0x58, 0x9a, + 0x68, 0xcb, 0x22, 0x54, 0xe8, 0xa7, 0x06, 0x49, 0x82, 0xf9, 0xfe, 0x27, 0x31, 0x3b, 0x6a, 0xab, 0x61, 0x66, 0x15, + 0x0f, 0xf1, 0x5d, 0x5a, 0x99, 0xa4, 0x9c, 0x57, 0xf5, 0x4e, 0x25, 0xca, 0xe6, 0x47, 0x64, 0x87, 0xc5, 0x60, 0xcc, + 0x4a, 0x08, 0xfb, 0x9d, 0x21, 0x32, 0x72, 0xd4, 0x97, 0x38, 0x49, 0xfc, 0x56, 0x47, 0x48, 0xbc, 0xb3, 0x34, 0x48, + 0x5f, 0x4b, 0x80, 0x7c, 0x2d, 0xbb, 0x3e, 0xf6, 0x62, 0x4a, 0x27, 0x1c, 0xee, 0x24, 0x7d, 0xeb, 0x3d, 0xf2, 0x8d, + 0x30, 0x6f, 0x95, 0xc6, 0x31, 0x20, 0xec, 0x5c, 0x03, 0x46, 0x46, 0xec, 0x40, 0x0e, 0x31, 0x17, 0x3b, 0x40, 0x30, + 0xeb, 0x6a, 0x9c, 0x03, 0xbf, 0xf7, 0x0e, 0xa5, 0xf4, 0x62, 0x2d, 0xb5, 0x4f, 0x72, 0x7e, 0x90, 0xc3, 0x31, 0x27, + 0x30, 0xde, 0x93, 0x39, 0x1d, 0x68, 0x1e, 0x93, 0x52, 0x2b, 0x91, 0x8a, 0x06, 0xe4, 0x57, 0xc9, 0xe0, 0x9e, 0xed, + 0xc9, 0x88, 0x93, 0x7f, 0xa1, 0x94, 0xfc, 0xe1, 0xc6, 0x3d, 0x9a, 0x09, 0xce, 0xcb, 0x03, 0x76, 0xb1, 0x59, 0x94, + 0x40, 0x3b, 0x53, 0xcd, 0x93, 0xb3, 0x05, 0x73, 0x69, 0x49, 0x49, 0xcb, 0xc2, 0x27, 0x64, 0x46, 0x6e, 0xfe, 0xc5, + 0xeb, 0x9b, 0xfe, 0x91, 0x61, 0x05, 0xc1, 0x5e, 0xeb, 0xaf, 0xf5, 0x7e, 0x4f, 0xa7, 0x83, 0x43, 0xd0, 0x9d, 0x03, + 0xb4, 0x4a, 0xe3, 0x61, 0x7f, 0xc6, 0x26, 0x80, 0x4c, 0x10, 0x3f, 0xdc, 0xb0, 0xee, 0xee, 0x07, 0x04, 0x66, 0x3f, + 0xf1, 0x8b, 0xe3, 0x94, 0x11, 0xf0, 0xad, 0xdd, 0xa2, 0x12, 0x22, 0x87, 0xff, 0xe7, 0xbe, 0x92, 0xc5, 0xea, 0x36, + 0x39, 0xd2, 0xec, 0xd7, 0xad, 0x33, 0xc0, 0x38, 0xfa, 0xe5, 0x3a, 0xa1, 0x12, 0x46, 0x66, 0x87, 0xa6, 0xd8, 0x15, + 0xce, 0x1e, 0xe1, 0x64, 0xc6, 0x7e, 0x0a, 0x8d, 0x48, 0xe3, 0x60, 0x25, 0x47, 0x5a, 0x80, 0x8b, 0xe5, 0x70, 0x68, + 0x98, 0x84, 0x0e, 0xb0, 0xc5, 0x45, 0x8e, 0xfb, 0xe1, 0xf9, 0x4c, 0xb2, 0xc3, 0x4b, 0x02, 0xe8, 0xc0, 0xb9, 0x88, + 0x89, 0x20, 0x07, 0x2d, 0x06, 0xa1, 0x1b, 0x72, 0xb0, 0x16, 0xaa, 0x61, 0x72, 0x04, 0xcf, 0xbe, 0xfe, 0x31, 0xfa, + 0x49, 0xc3, 0xe0, 0x25, 0x24, 0xc3, 0x28, 0x01, 0xe4, 0x98, 0xac, 0xf4, 0x1b, 0xf7, 0x76, 0x7b, 0xeb, 0xae, 0x0b, + 0x89, 0x3b, 0xfb, 0x69, 0xd7, 0x72, 0x31, 0x91, 0x7a, 0xf5, 0xd1, 0xc0, 0xb0, 0x73, 0xc0, 0x16, 0x78, 0x15, 0x44, + 0x67, 0xa2, 0xc7, 0x3d, 0xdc, 0x9f, 0x42, 0xaf, 0x30, 0x47, 0x60, 0x02, 0x7c, 0x63, 0xb2, 0x3b, 0x79, 0x84, 0xab, + 0xdb, 0x7d, 0xb4, 0xe7, 0xb1, 0x35, 0x8e, 0x0a, 0xa1, 0x34, 0xe2, 0x2d, 0xd3, 0x9d, 0x64, 0xc2, 0x3a, 0xac, 0xfe, + 0xa1, 0x29, 0xae, 0xd2, 0x77, 0xd2, 0x34, 0x82, 0x13, 0xb1, 0xfb, 0x36, 0xdc, 0x6a, 0xe0, 0x04, 0x47, 0x2e, 0x7a, + 0xf8, 0x8e, 0x08, 0x43, 0x0b, 0x7c, 0xc0, 0x49, 0xc5, 0x6c, 0x3c, 0x26, 0x06, 0x4e, 0xe3, 0x24, 0x57, 0x66, 0x39, + 0x37, 0x39, 0x24, 0xae, 0x58, 0xae, 0xb0, 0x9e, 0x5e, 0xb3, 0x6c, 0x93, 0x09, 0xf0, 0xde, 0x4f, 0xdd, 0x7b, 0x26, + 0xa4, 0x5c, 0x35, 0x6a, 0xcb, 0xdd, 0x59, 0xf1, 0x69, 0xb4, 0x92, 0xc9, 0xc9, 0x26, 0xfe, 0x30, 0xc0, 0x9d, 0xdd, + 0x12, 0xdd, 0xa9, 0xee, 0x2e, 0xb9, 0x0b, 0x8d, 0x27, 0xcc, 0x9c, 0xc2, 0x3e, 0x58, 0x4b, 0x75, 0x1e, 0x86, 0xd6, + 0xe3, 0xef, 0x9a, 0x99, 0x80, 0xc8, 0x4e, 0xa6, 0xb3, 0xf8, 0xa1, 0x1b, 0x90, 0xd2, 0x12, 0x47, 0x17, 0x25, 0xab, + 0x3f, 0xad, 0x7b, 0x93, 0x2a, 0xee, 0xd0, 0xf6, 0xf5, 0x8d, 0x1c, 0xef, 0x24, 0x2b, 0xb1, 0x04, 0xd5, 0x48, 0x7e, + 0x91, 0xa4, 0x81, 0x1d, 0x90, 0x0e, 0xb9, 0x46, 0xc3, 0x4c, 0x3d, 0x9b, 0x07, 0xaf, 0x23, 0xdd, 0x06, 0xab, 0x74, + 0x66, 0xf7, 0xf2, 0x03, 0x69, 0x85, 0xa6, 0x8c, 0x49, 0x31, 0xc9, 0xc7, 0x8b, 0x2e, 0x4e, 0x9c, 0xa2, 0x96, 0x7c, + 0x72, 0xe5, 0xa4, 0xe7, 0xb5, 0x3a, 0xe4, 0xea, 0x65, 0x0f, 0x31, 0x90, 0x24, 0xb3, 0x78, 0xa1, 0x7a, 0x72, 0x43, + 0xbc, 0x46, 0x03, 0x9c, 0xb6, 0xc7, 0xee, 0x2e, 0x1e, 0xe5, 0xad, 0x7f, 0xaa, 0xb7, 0x15, 0x5a, 0xfe, 0x94, 0x97, + 0xf7, 0x6a, 0xfd, 0x6d, 0x14, 0x21, 0xbf, 0x8b, 0x1f, 0x76, 0xeb, 0x9f, 0xb6, 0xab, 0x52, 0xa1, 0x53, 0xf9, 0x35, + 0x69, 0x8b, 0x05, 0xc0, 0x9f, 0xd7, 0xa6, 0x29, 0x24, 0x23, 0x8c, 0xa8, 0x4f, 0x10, 0x61, 0xaa, 0x13, 0xc6, 0xb7, + 0xa2, 0x86, 0xbc, 0x15, 0xad, 0x48, 0xaf, 0x19, 0x4d, 0xe3, 0xec, 0xe7, 0x8e, 0x11, 0x76, 0x32, 0x1c, 0xb1, 0x5b, + 0x92, 0x72, 0xfd, 0x14, 0xe9, 0x29, 0x24, 0x8e, 0x45, 0x70, 0x99, 0x50, 0x69, 0x29, 0xc7, 0x04, 0xd0, 0xad, 0xb6, + 0x86, 0x2c, 0x86, 0xd4, 0xa0, 0x8c, 0x59, 0xdd, 0x3c, 0x22, 0x70, 0xd4, 0xa0, 0x87, 0x8e, 0xa4, 0x70, 0x42, 0xb3, + 0x9d, 0x3e, 0x3e, 0x7f, 0xc6, 0xb4, 0x55, 0xdb, 0x20, 0x12, 0x03, 0xd0, 0xed, 0xee, 0x48, 0x0c, 0x41, 0xda, 0xdf, + 0x11, 0xd9, 0x5a, 0x2d, 0xca, 0xe8, 0xc8, 0x86, 0x6e, 0xa7, 0xc8, 0xfc, 0x5a, 0xcd, 0x15, 0xd9, 0xd4, 0xed, 0x06, + 0x65, 0x14, 0x19, 0xa4, 0xbc, 0xa3, 0xb4, 0xe5, 0x62, 0x19, 0x1d, 0xdd, 0xa2, 0x88, 0x50, 0x71, 0x1b, 0x14, 0x69, + 0xfa, 0x83, 0x14, 0x39, 0x0d, 0x11, 0xa7, 0x00, 0xef, 0x4e, 0x2d, 0x89, 0xda, 0x2d, 0x15, 0x0d, 0x9e, 0x42, 0x2f, + 0x83, 0x79, 0x77, 0xe1, 0x40, 0x42, 0x68, 0x73, 0x83, 0x53, 0x10, 0x6d, 0x41, 0xa7, 0x22, 0xbc, 0x15, 0xe9, 0x41, + 0x6a, 0x20, 0x00, 0xaf, 0xce, 0x7d, 0x1c, 0x1c, 0x00, 0xf4, 0xc9, 0x2a, 0xe8, 0x7c, 0x7f, 0xb4, 0xc8, 0x21, 0x96, + 0x66, 0x47, 0xea, 0x29, 0xe2, 0x52, 0x9a, 0x4f, 0xc4, 0xed, 0x82, 0x1c, 0x44, 0x9a, 0x56, 0xfc, 0x87, 0x5c, 0xd8, + 0xa4, 0x9d, 0x0f, 0x33, 0x04, 0x5f, 0x6a, 0xe2, 0x89, 0xd4, 0x7d, 0x8e, 0xc5, 0x94, 0x91, 0xc9, 0xd7, 0xba, 0x0b, + 0xab, 0x1d, 0xcc, 0x01, 0x31, 0x9e, 0x54, 0xf2, 0xd3, 0x29, 0xb2, 0xb3, 0xc9, 0x62, 0xa5, 0xa1, 0x02, 0x5a, 0x3a, + 0xa4, 0xcb, 0x65, 0xab, 0xc7, 0x01, 0x77, 0xfc, 0xa8, 0x09, 0x1f, 0x0d, 0x71, 0x5d, 0xfa, 0xf4, 0x2a, 0x48, 0x43, + 0xf8, 0x60, 0x29, 0xa4, 0x65, 0xd5, 0xb8, 0xf7, 0x66, 0x92, 0xda, 0xbf, 0xdb, 0x2c, 0xad, 0x69, 0xb0, 0xc3, 0xb6, + 0xe8, 0x19, 0x44, 0xe1, 0xeb, 0xaf, 0xa7, 0xd5, 0x47, 0xe7, 0x36, 0x2d, 0x88, 0xd0, 0x57, 0x05, 0x4e, 0x2c, 0xa7, + 0xbf, 0x2c, 0xe9, 0xe6, 0x96, 0xd0, 0x47, 0x2c, 0x7f, 0x94, 0x29, 0xc7, 0x67, 0x86, 0x17, 0x6b, 0xe8, 0x7e, 0x07, + 0x5a, 0x44, 0x8d, 0xb3, 0x59, 0x16, 0x8d, 0x6c, 0x09, 0xaf, 0xa9, 0x98, 0x98, 0xab, 0x1f, 0x0d, 0x19, 0x6b, 0x64, + 0x82, 0xc8, 0xa2, 0x1f, 0x3f, 0xea, 0xd2, 0x11, 0xe7, 0x61, 0x10, 0x27, 0x20, 0xcd, 0xbc, 0x64, 0xe4, 0x4d, 0x14, + 0xfc, 0xd6, 0x73, 0x60, 0x9b, 0xf7, 0x5b, 0xfb, 0xcc, 0x6e, 0xc4, 0x47, 0xfa, 0xda, 0xeb, 0x1d, 0x08, 0x25, 0x21, + 0x46, 0xe5, 0x9e, 0x8f, 0x8b, 0x25, 0x7b, 0x1a, 0x78, 0x53, 0x96, 0x2b, 0x06, 0xb7, 0xf8, 0x0d, 0xe8, 0x41, 0x0d, + 0xef, 0x20, 0xb4, 0x8f, 0x9c, 0x76, 0x84, 0x07, 0x68, 0x54, 0x0f, 0xd7, 0x72, 0x44, 0x17, 0x10, 0x64, 0x4e, 0xd0, + 0xa3, 0x81, 0x32, 0x50, 0xf0, 0x95, 0x64, 0xd0, 0x55, 0x66, 0xbb, 0xcc, 0xd6, 0xd0, 0x8c, 0x09, 0x10, 0xa9, 0xce, + 0x9f, 0x46, 0x70, 0x09, 0x5d, 0xc2, 0xa5, 0xa2, 0x0e, 0x64, 0xd4, 0xca, 0x70, 0x30, 0x0a, 0x68, 0xfa, 0x54, 0x1a, + 0xbf, 0x1a, 0x5d, 0x0a, 0xc0, 0xb1, 0xc6, 0xe7, 0x49, 0x06, 0x9f, 0x6d, 0x5c, 0xb1, 0xb8, 0x0c, 0x9a, 0x03, 0x83, + 0x6b, 0x5f, 0xdb, 0xab, 0xae, 0xc1, 0xce, 0xeb, 0xef, 0xa2, 0x33, 0x86, 0x3d, 0xa3, 0x10, 0x2b, 0x80, 0x0e, 0x90, + 0x28, 0xd7, 0xc0, 0xd9, 0x7b, 0xee, 0x7c, 0x6c, 0x23, 0x57, 0xd0, 0x85, 0x0e, 0x08, 0xae, 0x35, 0xb8, 0xdc, 0x3f, + 0x02, 0x5c, 0x68, 0x68, 0xe7, 0x59, 0x60, 0x45, 0x2e, 0x33, 0x50, 0x23, 0xfe, 0x4d, 0xee, 0x60, 0x59, 0x8d, 0x74, + 0x11, 0x8f, 0x15, 0xb5, 0xed, 0x64, 0x81, 0x4e, 0xb0, 0x4d, 0x0d, 0xb1, 0x03, 0x14, 0xbc, 0x50, 0x7e, 0xc2, 0xa9, + 0x47, 0x4b, 0x37, 0xa8, 0x2c, 0xf8, 0x1c, 0x98, 0xc5, 0xef, 0xa4, 0xde, 0xc2, 0xfd, 0x27, 0x47, 0x76, 0x10, 0x40, + 0xbc, 0x35, 0x2b, 0x84, 0x30, 0xf1, 0x72, 0x6c, 0x13, 0x76, 0x94, 0x81, 0x60, 0x37, 0x9a, 0x08, 0xd9, 0x08, 0x73, + 0x1b, 0xef, 0xa2, 0xf5, 0x7a, 0x1f, 0xbb, 0xbf, 0x18, 0x85, 0xc1, 0x76, 0x81, 0x61, 0xfc, 0x58, 0x8c, 0x22, 0xd4, + 0xf6, 0xf2, 0x5b, 0x91, 0x8c, 0xe4, 0x67, 0x15, 0xcc, 0x45, 0xdc, 0x0e, 0x6c, 0x5d, 0x99, 0x5a, 0x3f, 0x20, 0x2a, + 0xef, 0xf7, 0x92, 0x41, 0xbb, 0x85, 0x8f, 0x6f, 0x46, 0x76, 0xe2, 0x2b, 0xc7, 0xf5, 0xac, 0xfa, 0xfc, 0xfe, 0x39, + 0x22, 0x6b, 0x1e, 0x6f, 0xdd, 0x19, 0x8d, 0xce, 0x6a, 0x2d, 0x87, 0x8d, 0xda, 0xc0, 0x30, 0x21, 0xac, 0xf0, 0xfd, + 0xbc, 0x5c, 0xfb, 0x80, 0x30, 0xfc, 0xba, 0xe1, 0x37, 0x9e, 0x2d, 0xb0, 0x97, 0x1e, 0x1c, 0x2d, 0x6f, 0x5d, 0x57, + 0xd7, 0xd3, 0x4a, 0x34, 0x1e, 0x61, 0x12, 0xe2, 0x75, 0xde, 0x30, 0xa5, 0x03, 0x99, 0xe5, 0xf0, 0xa4, 0x7f, 0x70, + 0x4d, 0x67, 0x3e, 0xc4, 0x88, 0xf6, 0x17, 0x80, 0x7c, 0xd1, 0x94, 0x8f, 0x48, 0x9e, 0xd1, 0xe4, 0x06, 0x9b, 0x46, + 0xfa, 0x85, 0x33, 0xa5, 0x3a, 0x10, 0xdc, 0x77, 0x00, 0x00, 0x03, 0x75, 0x58, 0xf0, 0xfb, 0xd8, 0x56, 0xe2, 0xba, + 0x06, 0x63, 0x30, 0x30, 0xfd, 0x47, 0xbf, 0xa8, 0xf3, 0xa3, 0xcf, 0x50, 0x4d, 0xac, 0xf9, 0x52, 0x23, 0x32, 0xbb, + 0x92, 0x15, 0xd9, 0x4d, 0x90, 0x1f, 0xe7, 0xcb, 0x82, 0xdc, 0x84, 0xb8, 0x09, 0x41, 0xc5, 0x3d, 0xf1, 0xb5, 0xa8, + 0x02, 0x7d, 0x03, 0x94, 0x7f, 0x38, 0xeb, 0x40, 0xd0, 0x5f, 0x04, 0xc6, 0x9a, 0x1c, 0x84, 0xf3, 0xcf, 0x2d, 0x33, + 0x91, 0x3f, 0x8f, 0xc2, 0x65, 0xc9, 0x5f, 0xdd, 0xb2, 0x8d, 0xcc, 0xb8, 0xf1, 0x6d, 0x54, 0x99, 0x14, 0xf2, 0xba, + 0xf6, 0xac, 0x33, 0xbe, 0x90, 0x6a, 0x15, 0xc8, 0xd5, 0x45, 0xcc, 0x8c, 0x69, 0x0b, 0x39, 0xfd, 0x59, 0xfb, 0x5a, + 0xe5, 0x7f, 0xc6, 0x1d, 0x1c, 0xb3, 0xf0, 0xcf, 0xc7, 0x6d, 0x63, 0x0a, 0x88, 0xca, 0x1e, 0xf6, 0x45, 0xe5, 0x59, + 0xa7, 0xcb, 0x02, 0xd8, 0x26, 0x88, 0x2b, 0x19, 0xa1, 0xcc, 0x61, 0xa3, 0xf6, 0xfe, 0xbb, 0x7d, 0x1d, 0xcf, 0xac, + 0xb6, 0x1f, 0xd1, 0x4f, 0xfc, 0x11, 0xf3, 0x6f, 0x17, 0xf6, 0x65, 0x62, 0x9c, 0xbe, 0xce, 0x33, 0xd5, 0x9f, 0xba, + 0x49, 0x5d, 0xf0, 0xac, 0x4e, 0x40, 0x05, 0x09, 0xab, 0xe0, 0x67, 0xb0, 0x67, 0xff, 0xa3, 0xc2, 0xd5, 0x90, 0x4f, + 0xcb, 0x67, 0x67, 0xf6, 0x1a, 0xba, 0x56, 0x50, 0x75, 0xb8, 0x01, 0x22, 0x87, 0xc5, 0xad, 0xea, 0x62, 0xc7, 0x99, + 0xf9, 0x2f, 0x0b, 0xd8, 0xf8, 0x5a, 0x08, 0x4e, 0xd7, 0x1f, 0x5d, 0xbe, 0x44, 0xdb, 0x93, 0xb3, 0x89, 0x19, 0xc6, + 0x97, 0x34, 0xc4, 0x83, 0x7b, 0x4a, 0x87, 0x1f, 0x19, 0x93, 0x4f, 0xf1, 0xc7, 0xa7, 0xfd, 0x64, 0x2e, 0xf9, 0xf1, + 0xe3, 0x5f, 0xfa, 0xab, 0x7e, 0xcd, 0x33, 0xbf, 0x50, 0x67, 0xb2, 0xc3, 0x7b, 0x45, 0xd1, 0xf3, 0x8b, 0xb9, 0x18, + 0x11, 0x5b, 0x31, 0xfe, 0x30, 0x0b, 0x7d, 0xfa, 0xed, 0xed, 0xc3, 0x3d, 0x78, 0x33, 0x28, 0x69, 0xc6, 0x41, 0x9d, + 0x9b, 0xeb, 0x1c, 0x5b, 0x69, 0xca, 0x60, 0x12, 0xec, 0x0d, 0x2c, 0x91, 0x41, 0xda, 0x9d, 0x08, 0x11, 0xa8, 0x0c, + 0x4a, 0x05, 0x43, 0x69, 0x8e, 0xa3, 0xae, 0x83, 0x70, 0x20, 0x28, 0x97, 0x11, 0x5d, 0xd5, 0x2a, 0xce, 0x46, 0x07, + 0x0b, 0x01, 0x67, 0x10, 0x61, 0x08, 0xf0, 0xbd, 0x9a, 0x28, 0x81, 0x29, 0x24, 0x0d, 0x21, 0xfe, 0x54, 0x3a, 0x8e, + 0xa2, 0xb8, 0xae, 0xc2, 0xd7, 0xfb, 0x17, 0xd9, 0x38, 0xf9, 0x28, 0x81, 0xa2, 0xbc, 0x03, 0x81, 0x9a, 0x22, 0x05, + 0x9b, 0x8b, 0xcc, 0xe5, 0x88, 0x85, 0xf3, 0xa1, 0xa0, 0x17, 0x12, 0x56, 0x4b, 0x07, 0x3a, 0x1d, 0x7b, 0x38, 0x24, + 0xb4, 0x2a, 0xd8, 0x84, 0xa1, 0xc9, 0x6d, 0x7e, 0xad, 0x02, 0xca, 0xc9, 0x64, 0x17, 0xb7, 0xc0, 0x37, 0xbf, 0x3e, + 0x47, 0x77, 0x2d, 0x74, 0x9e, 0xf9, 0x9e, 0xf1, 0xf7, 0xef, 0x6f, 0x8e, 0xbf, 0xc2, 0xa3, 0x19, 0xab, 0x26, 0xac, + 0xff, 0xf5, 0x4d, 0x48, 0x08, 0xa5, 0x40, 0x15, 0x01, 0x42, 0xa9, 0xac, 0x81, 0x75, 0x1d, 0x32, 0x73, 0x68, 0xe8, + 0xfa, 0x47, 0x06, 0x39, 0x82, 0x1d, 0x36, 0xf6, 0x6d, 0x58, 0xf8, 0x5a, 0xa9, 0x83, 0xbd, 0x81, 0xa9, 0xb5, 0xb0, + 0x4f, 0x5b, 0xa0, 0xce, 0xe6, 0x9c, 0x39, 0x82, 0xa0, 0x5b, 0x66, 0x66, 0xaa, 0xd2, 0x59, 0x9e, 0x69, 0x7e, 0x46, + 0x7b, 0xc5, 0x7e, 0x5d, 0x02, 0x17, 0x64, 0xe9, 0x6c, 0x6e, 0x6d, 0x45, 0x81, 0xbb, 0x92, 0x2a, 0x9f, 0xb1, 0x75, + 0x3c, 0x04, 0xc2, 0xcf, 0x13, 0x63, 0xbb, 0xc6, 0xe7, 0xc1, 0xd6, 0x27, 0xf9, 0x80, 0x96, 0xae, 0x0f, 0x5d, 0x72, + 0xad, 0x8f, 0x11, 0xcc, 0x88, 0xa9, 0xfc, 0xf0, 0x86, 0xfa, 0x6e, 0x38, 0x70, 0x74, 0x9f, 0xe2, 0xa7, 0x4f, 0x3b, + 0xe9, 0x92, 0x4f, 0x3f, 0xfe, 0x4b, 0x5e, 0xd9, 0x75, 0x08, 0x55, 0x2e, 0x53, 0xf0, 0x63, 0x9f, 0xaf, 0xab, 0xc9, + 0xf6, 0xa6, 0xe2, 0x38, 0x10, 0x3f, 0xaa, 0x34, 0x99, 0xe8, 0x17, 0x77, 0x99, 0xc1, 0xf1, 0x3c, 0x44, 0x56, 0x7b, + 0xe2, 0x5c, 0xd7, 0x93, 0x39, 0x97, 0x6d, 0x70, 0xa1, 0x11, 0x32, 0x75, 0x79, 0xe6, 0x65, 0x9f, 0x13, 0x58, 0xd4, + 0x4c, 0xca, 0xee, 0x6b, 0x8c, 0xc7, 0xd7, 0x96, 0xd3, 0xf4, 0x2c, 0xa4, 0x50, 0x37, 0x1d, 0x2e, 0x68, 0x08, 0x15, + 0xd0, 0xe0, 0xe7, 0x6f, 0x4a, 0xd9, 0x98, 0xb8, 0x19, 0xc9, 0x7f, 0xf0, 0xc8, 0xa4, 0x99, 0x32, 0x1e, 0xe9, 0xb3, + 0x5a, 0xb3, 0x3c, 0xe8, 0x88, 0x2d, 0x65, 0xd9, 0xc7, 0xf8, 0x3a, 0xb5, 0x90, 0xfd, 0x35, 0xfd, 0x3e, 0xdd, 0x62, + 0x94, 0x5a, 0xca, 0x93, 0x8e, 0x84, 0xda, 0xfa, 0xb2, 0x1f, 0x44, 0xa4, 0x2e, 0xf0, 0x50, 0x13, 0xb1, 0x5e, 0xc6, + 0x74, 0x30, 0x98, 0x2a, 0xda, 0x6f, 0x4f, 0x77, 0xab, 0xd3, 0x37, 0x9b, 0x6a, 0x11, 0xe2, 0xfa, 0x40, 0xea, 0x63, + 0x58, 0x4d, 0x94, 0x9d, 0x1d, 0x7a, 0x09, 0x07, 0xc1, 0x03, 0xa3, 0x73, 0x05, 0x37, 0x19, 0x2e, 0x62, 0xd6, 0x99, + 0x07, 0xdc, 0x25, 0xe5, 0x70, 0x82, 0x38, 0xaf, 0xd0, 0xd5, 0xba, 0x0b, 0xe3, 0x5a, 0xbe, 0xc9, 0xbb, 0xd3, 0xa9, + 0xa4, 0x4e, 0x79, 0xb8, 0x01, 0x6d, 0xa4, 0x36, 0xbd, 0x53, 0x6c, 0x1f, 0xb8, 0x55, 0xfb, 0xef, 0x37, 0x20, 0x93, + 0xbd, 0xcf, 0x1f, 0x38, 0xa0, 0x21, 0x08, 0xd9, 0xe3, 0xe5, 0xf8, 0x02, 0x9d, 0x45, 0xdd, 0x5a, 0x77, 0x75, 0xda, + 0x5d, 0x6f, 0xa1, 0x2a, 0xeb, 0x23, 0x2e, 0x98, 0x9c, 0xa1, 0xc3, 0xb6, 0x95, 0x42, 0x3f, 0x86, 0x9e, 0xc4, 0xbc, + 0xbc, 0xb2, 0x36, 0xac, 0x93, 0x13, 0x7b, 0xc1, 0xd5, 0xbe, 0xf9, 0x83, 0xf8, 0x0c, 0x30, 0x8b, 0xb9, 0xe9, 0xcd, + 0xb3, 0xea, 0x0b, 0x31, 0x44, 0xc6, 0x35, 0x1c, 0x61, 0x02, 0x3e, 0xa0, 0xfa, 0x0f, 0x0e, 0x2d, 0x86, 0xab, 0xe3, + 0x52, 0x83, 0xe9, 0xf8, 0xc1, 0x17, 0xd5, 0x11, 0x12, 0xd3, 0x8e, 0xc7, 0x06, 0xac, 0x31, 0xd4, 0xa0, 0x83, 0x5b, + 0xd3, 0x28, 0x40, 0x10, 0xdb, 0xd7, 0xcf, 0x0d, 0x6e, 0xbf, 0x7b, 0xd7, 0xbb, 0x22, 0xe1, 0xdc, 0xbe, 0x6c, 0x80, + 0x39, 0x61, 0x30, 0x3a, 0x9d, 0xad, 0x6b, 0xa2, 0x2f, 0xea, 0xf7, 0x85, 0x2d, 0xf4, 0x40, 0x6e, 0x4c, 0x78, 0x04, + 0x0b, 0x15, 0x77, 0x90, 0x33, 0xa8, 0x80, 0xfb, 0x0b, 0x7a, 0xc0, 0x82, 0x94, 0xf1, 0x89, 0x78, 0x87, 0xd6, 0x31, + 0x42, 0x0d, 0x2c, 0x38, 0x56, 0x1a, 0x86, 0x03, 0x06, 0xc1, 0xf1, 0x59, 0xd6, 0x88, 0xbc, 0x53, 0x23, 0xf8, 0x2b, + 0x1a, 0x45, 0xeb, 0x58, 0x4a, 0x0a, 0x15, 0xac, 0xe9, 0xec, 0x6b, 0x45, 0xc4, 0xab, 0x29, 0xe8, 0x04, 0x18, 0xd2, + 0x9e, 0x38, 0xfb, 0x74, 0x17, 0xc9, 0xa2, 0x7a, 0xcf, 0x2e, 0x12, 0xe1, 0x2e, 0x03, 0x52, 0xc4, 0x81, 0x4f, 0x87, + 0xd5, 0x74, 0x55, 0x6e, 0xee, 0xa1, 0xad, 0xbd, 0x8b, 0x1d, 0x9d, 0x06, 0xc1, 0xe4, 0xd8, 0xb3, 0xe1, 0x46, 0x2f, + 0x0a, 0x0e, 0x5b, 0x49, 0xd9, 0xaf, 0x22, 0x9c, 0x70, 0xeb, 0xb9, 0x16, 0x2a, 0x1d, 0x34, 0x17, 0x7f, 0xba, 0x42, + 0x2f, 0x21, 0xd4, 0xf6, 0x4c, 0x23, 0x4e, 0x2f, 0xc1, 0xd8, 0x6e, 0xfe, 0x53, 0xb7, 0x0c, 0xda, 0xdc, 0xda, 0xbb, + 0xf4, 0xd6, 0x86, 0xb3, 0x49, 0x65, 0x56, 0x0e, 0xba, 0x17, 0xa5, 0xbb, 0x1c, 0xe3, 0x0c, 0x46, 0xf1, 0x49, 0x3e, + 0xd3, 0xaa, 0xf4, 0xd8, 0xef, 0x36, 0x78, 0xc4, 0x3e, 0xda, 0xc6, 0xd8, 0x21, 0x16, 0x58, 0xe4, 0x78, 0x76, 0x02, + 0x35, 0x0e, 0x8d, 0x78, 0x4d, 0x11, 0x5a, 0x52, 0x7b, 0x87, 0x8f, 0x3e, 0xf6, 0xd6, 0xca, 0x77, 0xe4, 0xc5, 0x5a, + 0x04, 0x50, 0x83, 0x9a, 0x56, 0x09, 0xdd, 0xa5, 0x9b, 0x67, 0xbc, 0x06, 0x2c, 0x3a, 0x0a, 0x87, 0x28, 0xdf, 0x39, + 0x57, 0xd0, 0x8e, 0xb6, 0x48, 0x64, 0x1d, 0xa3, 0xa9, 0x14, 0xb9, 0xfe, 0xc3, 0x32, 0x0d, 0x9a, 0x1f, 0xdb, 0x57, + 0x90, 0xbd, 0x39, 0x1f, 0xf3, 0x3f, 0x9e, 0xb3, 0x2f, 0xd9, 0x5e, 0x17, 0x00, 0xae, 0x9f, 0xfd, 0x63, 0x62, 0xf2, + 0x67, 0x16, 0x86, 0xf9, 0x0f, 0xf5, 0x09, 0x6f, 0x02, 0xff, 0x04, 0xcf, 0x59, 0x62, 0xbc, 0x97, 0xe2, 0x3c, 0xc5, + 0x33, 0x97, 0x40, 0x6f, 0x4b, 0xbe, 0x6c, 0x01, 0xbc, 0xb8, 0xd4, 0xbc, 0x5d, 0x70, 0x36, 0x46, 0x14, 0xa8, 0xbe, + 0xd5, 0x93, 0x5c, 0x0e, 0xba, 0x51, 0x8a, 0xb8, 0xe9, 0xb7, 0x0a, 0x34, 0xa3, 0x55, 0x62, 0x76, 0x19, 0x7a, 0xb1, + 0x74, 0x9c, 0xab, 0xf0, 0x33, 0x19, 0x6c, 0x83, 0x7d, 0x22, 0xc2, 0x65, 0xd2, 0x63, 0x84, 0xbf, 0x4d, 0x91, 0x7c, + 0xab, 0xc3, 0xf5, 0x83, 0xc6, 0xbf, 0xee, 0xfd, 0xfa, 0xd5, 0xe3, 0x8b, 0x9b, 0x86, 0xb0, 0x7a, 0xa0, 0x7c, 0x72, + 0xb6, 0xde, 0xed, 0x4c, 0x0f, 0x03, 0xc5, 0x43, 0x61, 0x34, 0x3a, 0xc6, 0x49, 0x61, 0x36, 0x9b, 0x75, 0xfd, 0xd0, + 0xf5, 0x1f, 0x39, 0x1d, 0x48, 0xb0, 0x0c, 0xe5, 0xde, 0x9d, 0x81, 0x79, 0xbd, 0x35, 0x90, 0xb5, 0x5c, 0xe5, 0xc0, + 0x9d, 0x9e, 0xa9, 0xde, 0x8e, 0x14, 0x8e, 0x78, 0xa4, 0x15, 0xee, 0xcc, 0x5e, 0x66, 0x03, 0xba, 0x8b, 0x73, 0x45, + 0x77, 0xce, 0x29, 0x59, 0x44, 0x96, 0x9f, 0xf4, 0x8e, 0xde, 0xec, 0xf8, 0xd8, 0xbd, 0x2b, 0x09, 0x2c, 0xff, 0x6f, + 0xd4, 0xa1, 0x7a, 0x48, 0x8c, 0x14, 0x9e, 0x45, 0xb1, 0xb1, 0x2a, 0x86, 0xef, 0xf0, 0x5b, 0xc9, 0x53, 0xed, 0x15, + 0xc3, 0x02, 0xdf, 0x35, 0xcc, 0xdd, 0x3a, 0x12, 0xbc, 0x4c, 0xc7, 0x80, 0x47, 0x62, 0xc0, 0x6f, 0x36, 0x8f, 0x08, + 0x5d, 0x27, 0x7b, 0x1c, 0x3f, 0x05, 0xe1, 0xc6, 0x15, 0x94, 0x33, 0x23, 0x7c, 0x83, 0x91, 0x83, 0xa7, 0x98, 0x3f, + 0xde, 0xdc, 0x41, 0xf5, 0xf1, 0xc3, 0xbe, 0x58, 0x7b, 0xf0, 0xd7, 0x02, 0xac, 0x81, 0x3c, 0xda, 0x50, 0x3d, 0x4b, + 0xf5, 0xce, 0xfd, 0x35, 0x4f, 0x0b, 0x7e, 0x46, 0x6e, 0x74, 0x5b, 0x9c, 0x23, 0x5f, 0xe2, 0xed, 0xb6, 0x13, 0x6f, + 0x77, 0x7d, 0x6b, 0x7e, 0xd4, 0x08, 0x10, 0x36, 0xbf, 0x2d, 0xdb, 0xfa, 0xc3, 0xc5, 0xed, 0x97, 0xf6, 0xce, 0x60, + 0x07, 0xb8, 0xc4, 0x80, 0x8d, 0xae, 0x8b, 0xd8, 0xe6, 0x8c, 0x1b, 0x63, 0x17, 0x71, 0xd8, 0x00, 0xa4, 0x8a, 0x98, + 0x08, 0x4d, 0xe5, 0x28, 0x04, 0x83, 0xa1, 0x37, 0x7d, 0x1f, 0xef, 0x33, 0x0f, 0xb0, 0x01, 0x9b, 0x4c, 0x6d, 0x42, + 0xd8, 0x98, 0x54, 0xb7, 0x7e, 0x1d, 0xa1, 0x2c, 0xc6, 0xc6, 0xd2, 0x9a, 0x2b, 0x0b, 0x42, 0x9f, 0xb7, 0xfe, 0x56, + 0xc3, 0x36, 0xd7, 0xf8, 0xb7, 0x58, 0x44, 0xfc, 0x98, 0x72, 0xd8, 0x5f, 0xc2, 0xa7, 0x0b, 0xc7, 0xe8, 0xe8, 0x93, + 0xc6, 0x99, 0x71, 0xaa, 0xae, 0x95, 0xfe, 0x56, 0xc6, 0x43, 0x1f, 0xdf, 0xdd, 0x98, 0x2a, 0x3b, 0xf4, 0x12, 0x2c, + 0x3a, 0x0a, 0xe3, 0x21, 0x9e, 0x06, 0x75, 0x1d, 0x47, 0x32, 0x98, 0xba, 0xc7, 0x99, 0xbe, 0xda, 0xce, 0xa2, 0xb8, + 0x8c, 0xd8, 0x79, 0x5f, 0x5a, 0x2d, 0xe3, 0xa0, 0x5a, 0xb8, 0x88, 0x8e, 0x19, 0xd4, 0x22, 0xe2, 0x9d, 0x7a, 0xf1, + 0x24, 0xf9, 0x98, 0xd3, 0x71, 0xa0, 0x74, 0x2d, 0x69, 0x8f, 0x05, 0x34, 0x44, 0x66, 0x14, 0x5e, 0xfa, 0xa9, 0x9b, + 0xfd, 0xd3, 0xf8, 0x7f, 0x5d, 0x6e, 0xb6, 0xdb, 0x63, 0xbb, 0x12, 0x85, 0x39, 0x4d, 0x0e, 0x81, 0xb6, 0xe0, 0x3b, + 0x6e, 0xf5, 0x31, 0x47, 0xc6, 0x78, 0xad, 0x4b, 0xfa, 0xa5, 0xad, 0x3a, 0x8f, 0xda, 0x35, 0x5a, 0xbf, 0xc0, 0x51, + 0x21, 0xb4, 0xd3, 0x6c, 0xb4, 0x8b, 0x0f, 0x7c, 0xde, 0x3c, 0x98, 0x86, 0x26, 0x14, 0x53, 0x4b, 0xf5, 0x90, 0x39, + 0x2a, 0x9f, 0xe3, 0xf4, 0x1e, 0x80, 0x8a, 0x48, 0x7b, 0xf7, 0x7e, 0xa6, 0xde, 0x5f, 0x6b, 0x86, 0xee, 0xa3, 0x56, + 0xca, 0x48, 0xf8, 0x6d, 0x87, 0x90, 0xb0, 0x0a, 0x49, 0x18, 0x3b, 0x27, 0xca, 0x59, 0xd6, 0x36, 0x86, 0x96, 0xf7, + 0x87, 0x83, 0xe7, 0x89, 0x56, 0xcb, 0xb8, 0xc5, 0x23, 0x72, 0xbb, 0xf7, 0x99, 0x48, 0xf5, 0xa2, 0xea, 0xf2, 0x08, + 0x82, 0x45, 0x27, 0x32, 0xd2, 0x5f, 0x8c, 0xda, 0x71, 0x02, 0xfd, 0x7b, 0xf9, 0x53, 0x50, 0x52, 0xd4, 0x0a, 0xa7, + 0x8c, 0x75, 0x13, 0x9d, 0x68, 0x29, 0xc2, 0xc8, 0xa6, 0xaf, 0x82, 0xff, 0x04, 0x37, 0x58, 0x79, 0x77, 0xcf, 0x33, + 0xa2, 0x6a, 0xe1, 0x11, 0x45, 0x32, 0x26, 0xee, 0x7e, 0x0e, 0xb3, 0x84, 0x5e, 0x7a, 0x77, 0xad, 0x75, 0xea, 0x9c, + 0x2e, 0xde, 0x04, 0x51, 0x0a, 0xa2, 0xbb, 0xcf, 0xf1, 0x13, 0xe3, 0x00, 0xe9, 0x06, 0xf8, 0xe7, 0x04, 0xc9, 0x29, + 0x4f, 0x54, 0x5e, 0x06, 0xd3, 0x36, 0xa4, 0x60, 0xf8, 0x58, 0xef, 0xc1, 0x8d, 0x37, 0x7c, 0xb9, 0x9c, 0xfa, 0xe6, + 0xcd, 0x23, 0x57, 0x3d, 0xc4, 0xd3, 0x38, 0xef, 0x6c, 0x5a, 0x26, 0xf8, 0x48, 0x12, 0xff, 0xac, 0x4d, 0xec, 0xb6, + 0x6c, 0xd2, 0xf3, 0xa6, 0xdb, 0xc2, 0xd9, 0xbd, 0x65, 0x0e, 0xb2, 0xd8, 0xf4, 0x05, 0x20, 0xe5, 0x80, 0xd6, 0xc5, + 0x2e, 0x0a, 0x05, 0x71, 0x1a, 0xe0, 0x02, 0x30, 0x42, 0x4b, 0x2c, 0x56, 0xe0, 0x89, 0xc6, 0xd3, 0x2c, 0xa7, 0xc5, + 0x36, 0x78, 0x37, 0x82, 0x67, 0x89, 0x5c, 0x4a, 0xd3, 0x90, 0x36, 0xb5, 0x94, 0xf0, 0xcc, 0xa9, 0xf5, 0x6d, 0x9a, + 0x6e, 0x6a, 0x93, 0xd9, 0x7c, 0xec, 0x8a, 0x15, 0x6d, 0xe8, 0xe0, 0x0e, 0x26, 0xd1, 0x16, 0x42, 0x36, 0x6a, 0x20, + 0xdb, 0xec, 0x4f, 0x59, 0xb2, 0xd3, 0x54, 0xa1, 0x27, 0xb5, 0x6e, 0x89, 0x16, 0x47, 0xa6, 0xde, 0xcd, 0x02, 0x49, + 0xb0, 0x85, 0x86, 0x63, 0x61, 0x45, 0xd3, 0xe3, 0x7b, 0xee, 0xa3, 0x63, 0x60, 0xa1, 0x96, 0x9e, 0xc6, 0x1c, 0xbd, + 0x33, 0x88, 0x69, 0xd6, 0x32, 0xb2, 0x65, 0xe3, 0xf3, 0x1e}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From a68506f9244a0e831c2c5046a6b0c126c3aaa65f Mon Sep 17 00:00:00 2001 From: Cody Cutrer Date: Wed, 28 Jan 2026 09:04:43 -0700 Subject: [PATCH 0427/2030] [ld2450] preserve precision of angle (#13600) --- esphome/components/ld2450/ld2450.cpp | 2 +- esphome/components/ld2450/sensor.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 58d469b2a7..512683bbce 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -451,7 +451,7 @@ void LD2450Component::handle_periodic_data_() { int16_t ty = 0; int16_t td = 0; int16_t ts = 0; - int16_t angle = 0; + float angle = 0; uint8_t index = 0; Direction direction{DIRECTION_UNDEFINED}; bool is_moving = false; diff --git a/esphome/components/ld2450/sensor.py b/esphome/components/ld2450/sensor.py index 3dee8bf470..ce58cedf11 100644 --- a/esphome/components/ld2450/sensor.py +++ b/esphome/components/ld2450/sensor.py @@ -143,6 +143,7 @@ CONFIG_SCHEMA = CONFIG_SCHEMA.extend( ], icon=ICON_FORMAT_TEXT_ROTATION_ANGLE_UP, unit_of_measurement=UNIT_DEGREES, + accuracy_decimals=1, ), cv.Optional(CONF_DISTANCE): sensor.sensor_schema( device_class=DEVICE_CLASS_DISTANCE, From 6c84f2049114a921eb7eeac3726ccaa5db164270 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 09:40:00 -1000 Subject: [PATCH 0428/2030] [wifi] Fix ESP8266 yield panic when WiFi scan fails (#13603) --- esphome/components/wifi/wifi_component_esp8266.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 4c204f7cf3..59101439c2 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -756,7 +756,10 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { if (status != OK) { ESP_LOGV(TAG, "Scan failed: %d", status); - this->retry_connect(); + // Don't call retry_connect() here - this callback runs in SDK system context + // where yield() cannot be called. Instead, just set scan_done_ and let + // check_scanning_finished() handle the empty scan_result_ from loop context. + this->scan_done_ = true; return; } From 50e739ee8eeefc3a76e86e6d596c714294f9472e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 28 Jan 2026 09:41:42 -1000 Subject: [PATCH 0429/2030] [http_request] Fix empty body for chunked transfer encoding responses (#13599) --- .../http_request/http_request_arduino.cpp | 18 +++++++++++---- .../http_request/http_request_idf.cpp | 22 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 8ec4d2bc4b..82538b2cb3 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -131,6 +131,10 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur } } + // HTTPClient::getSize() returns -1 for chunked transfer encoding (no Content-Length). + // When cast to size_t, -1 becomes SIZE_MAX (4294967295 on 32-bit). + // The read() method handles this: bytes_read_ can never reach SIZE_MAX, so the + // early return check (bytes_read_ >= content_length) will never trigger. int content_length = container->client_.getSize(); ESP_LOGD(TAG, "Content-Length: %d", content_length); container->content_length = (size_t) content_length; @@ -167,17 +171,23 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { } int available_data = stream_ptr->available(); - int bufsize = std::min(max_len, std::min(this->content_length - this->bytes_read_, (size_t) available_data)); + // For chunked transfer encoding, HTTPClient::getSize() returns -1, which becomes SIZE_MAX when + // cast to size_t. SIZE_MAX - bytes_read_ is still huge, so it won't limit the read. + size_t remaining = (this->content_length > 0) ? (this->content_length - this->bytes_read_) : max_len; + int bufsize = std::min(max_len, std::min(remaining, (size_t) available_data)); if (bufsize == 0) { this->duration_ms += (millis() - start); - // Check if we've read all expected content - if (this->bytes_read_ >= this->content_length) { + // Check if we've read all expected content (only valid when content_length is known and not SIZE_MAX) + // For chunked encoding (content_length == SIZE_MAX), we can't use this check + if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { return 0; // All content read successfully } // No data available - check if connection is still open + // For chunked encoding, !connected() after reading means EOF (all chunks received) + // For known content_length with bytes_read_ < content_length, it means connection dropped if (!stream_ptr->connected()) { - return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed prematurely + return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed or EOF for chunked } return 0; // No data yet, caller should retry } diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index b6fb7f7ea9..95c59aa04c 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -152,6 +152,8 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c } container->feed_wdt(); + // esp_http_client_fetch_headers() returns 0 for chunked transfer encoding (no Content-Length header). + // The read() method handles content_length == 0 specially to support chunked responses. container->content_length = esp_http_client_fetch_headers(client); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); @@ -220,14 +222,22 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c // // We normalize to HttpContainer::read() contract: // > 0: bytes read -// 0: no data yet / all content read (caller should check bytes_read vs content_length) +// 0: all content read (only returned when content_length is known and fully read) // < 0: error/connection closed +// +// Note on chunked transfer encoding: +// esp_http_client_fetch_headers() returns 0 for chunked responses (no Content-Length header). +// We handle this by skipping the content_length check when content_length is 0, +// allowing esp_http_client_read() to handle chunked decoding internally and signal EOF +// by returning 0. int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); // Check if we've already read all expected content - if (this->bytes_read_ >= this->content_length) { + // Skip this check when content_length is 0 (chunked transfer encoding or unknown length) + // For chunked responses, esp_http_client_read() will return 0 when all data is received + if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { return 0; // All content read successfully } @@ -242,7 +252,13 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { return read_len_or_error; } - // Connection closed by server before all content received + // esp_http_client_read() returns 0 in two cases: + // 1. Known content_length: connection closed before all data received (error) + // 2. Chunked encoding (content_length == 0): end of stream reached (EOF) + // For case 1, returning HTTP_ERROR_CONNECTION_CLOSED is correct. + // For case 2, 0 indicates that all chunked data has already been delivered + // in previous successful read() calls, so treating this as a closed + // connection does not cause any loss of response data. if (read_len_or_error == 0) { return HTTP_ERROR_CONNECTION_CLOSED; } From 0a63fc6f05b5d6ce053da91c665925f9bec48547 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 29 Jan 2026 21:11:09 -0500 Subject: [PATCH 0430/2030] Bump version to 2026.1.3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 7fcf0f92f1..f9ffa9e25a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.2 +PROJECT_NUMBER = 2026.1.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 36adcbf500..1ce6eb4ba3 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.2" +__version__ = "2026.1.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 9a8c71a58ba6e62976768d0b2721a53352f7ecb1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 29 Jan 2026 17:31:01 -1000 Subject: [PATCH 0431/2030] [logger] Fix USB Serial JTAG VFS linker errors when using UART on IDF (#13628) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 27 ++++++++++++++++++++++----- esphome/components/logger/__init__.py | 8 ++++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 1d7ea5395f..a3154f9933 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -739,9 +739,10 @@ CONF_DISABLE_REGI2C_IN_IRAM = "disable_regi2c_in_iram" CONF_DISABLE_FATFS = "disable_fatfs" # VFS requirement tracking -# Components that need VFS features can call require_vfs_select() or require_vfs_dir() +# Components that need VFS features can call require_vfs_*() functions KEY_VFS_SELECT_REQUIRED = "vfs_select_required" KEY_VFS_DIR_REQUIRED = "vfs_dir_required" +KEY_VFS_TERMIOS_REQUIRED = "vfs_termios_required" # Feature requirement tracking - components can call require_* functions to re-enable # These are stored in CORE.data[KEY_ESP32] dict KEY_USB_SERIAL_JTAG_SECONDARY_REQUIRED = "usb_serial_jtag_secondary_required" @@ -768,6 +769,15 @@ def require_vfs_dir() -> None: CORE.data[KEY_VFS_DIR_REQUIRED] = True +def require_vfs_termios() -> None: + """Mark that VFS termios support is required by a component. + + Call this from components that use terminal I/O functions (usb_serial_jtag_vfs_*, etc.). + This prevents CONFIG_VFS_SUPPORT_TERMIOS from being disabled. + """ + CORE.data[KEY_VFS_TERMIOS_REQUIRED] = True + + def require_full_certificate_bundle() -> None: """Request the full certificate bundle instead of the common-CAs-only bundle. @@ -1372,11 +1382,18 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_LIBC_LOCKS_PLACE_IN_IRAM", False) # Disable VFS support for termios (terminal I/O functions) - # ESPHome doesn't use termios functions on ESP32 (only used in host UART driver). + # USB Serial JTAG VFS functions require termios support. + # Components that need it (e.g., logger when USB_SERIAL_JTAG is supported but not selected + # as the logger output) call require_vfs_termios(). # Saves approximately 1.8KB of flash when disabled (default). - add_idf_sdkconfig_option( - "CONFIG_VFS_SUPPORT_TERMIOS", not advanced[CONF_DISABLE_VFS_SUPPORT_TERMIOS] - ) + if CORE.data.get(KEY_VFS_TERMIOS_REQUIRED, False): + # Component requires VFS termios - force enable regardless of user setting + add_idf_sdkconfig_option("CONFIG_VFS_SUPPORT_TERMIOS", True) + else: + # No component needs it - allow user to control (default: disabled) + add_idf_sdkconfig_option( + "CONFIG_VFS_SUPPORT_TERMIOS", not advanced[CONF_DISABLE_VFS_SUPPORT_TERMIOS] + ) # Disable VFS support for select() with file descriptors # ESPHome only uses select() with sockets via lwip_select(), which still works. diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index cadd0a14ae..40ceaec7dc 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -16,6 +16,8 @@ from esphome.components.esp32 import ( VARIANT_ESP32S3, add_idf_sdkconfig_option, get_esp32_variant, + require_usb_serial_jtag_secondary, + require_vfs_termios, ) from esphome.components.libretiny import get_libretiny_component, get_libretiny_family from esphome.components.libretiny.const import ( @@ -397,9 +399,15 @@ async def to_code(config): elif config[CONF_HARDWARE_UART] == USB_SERIAL_JTAG: add_idf_sdkconfig_option("CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG", True) cg.add_define("USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG") + # Define platform support flags for components that need auto-detection try: uart_selection(USB_SERIAL_JTAG) cg.add_define("USE_LOGGER_USB_SERIAL_JTAG") + # USB Serial JTAG code is compiled when platform supports it. + # Enable secondary USB serial JTAG console so the VFS functions are available. + if CORE.is_esp32 and config[CONF_HARDWARE_UART] != USB_SERIAL_JTAG: + require_usb_serial_jtag_secondary() + require_vfs_termios() except cv.Invalid: pass try: From 20edd11ca758b498792f7860468bcc034103bc77 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht Date: Fri, 30 Jan 2026 04:48:16 +0100 Subject: [PATCH 0432/2030] [pmsx003] Improvements (#13626) --- esphome/components/pmsx003/pmsx003.cpp | 81 +++++++++++++------------- esphome/components/pmsx003/pmsx003.h | 43 +++++++------- esphome/components/pmsx003/sensor.py | 38 ++++++------ tests/components/pmsx003/common.yaml | 6 +- 4 files changed, 82 insertions(+), 86 deletions(-) diff --git a/esphome/components/pmsx003/pmsx003.cpp b/esphome/components/pmsx003/pmsx003.cpp index bb167033d1..b0920de062 100644 --- a/esphome/components/pmsx003/pmsx003.cpp +++ b/esphome/components/pmsx003/pmsx003.cpp @@ -2,21 +2,20 @@ #include "esphome/core/log.h" #include "esphome/core/application.h" -namespace esphome { -namespace pmsx003 { +namespace esphome::pmsx003 { static const char *const TAG = "pmsx003"; static const uint8_t START_CHARACTER_1 = 0x42; static const uint8_t START_CHARACTER_2 = 0x4D; -static const uint16_t PMS_STABILISING_MS = 30000; // time taken for the sensor to become stable after power on in ms +static const uint16_t STABILISING_MS = 30000; // time taken for the sensor to become stable after power on in ms -static const uint16_t PMS_CMD_MEASUREMENT_MODE_PASSIVE = - 0x0000; // use `PMS_CMD_MANUAL_MEASUREMENT` to trigger a measurement -static const uint16_t PMS_CMD_MEASUREMENT_MODE_ACTIVE = 0x0001; // automatically perform measurements -static const uint16_t PMS_CMD_SLEEP_MODE_SLEEP = 0x0000; // go to sleep mode -static const uint16_t PMS_CMD_SLEEP_MODE_WAKEUP = 0x0001; // wake up from sleep mode +static const uint16_t CMD_MEASUREMENT_MODE_PASSIVE = + 0x0000; // use `Command::MANUAL_MEASUREMENT` to trigger a measurement +static const uint16_t CMD_MEASUREMENT_MODE_ACTIVE = 0x0001; // automatically perform measurements +static const uint16_t CMD_SLEEP_MODE_SLEEP = 0x0000; // go to sleep mode +static const uint16_t CMD_SLEEP_MODE_WAKEUP = 0x0001; // wake up from sleep mode void PMSX003Component::setup() {} @@ -42,7 +41,7 @@ void PMSX003Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); - if (this->update_interval_ <= PMS_STABILISING_MS) { + if (this->update_interval_ <= STABILISING_MS) { ESP_LOGCONFIG(TAG, " Mode: active continuous (sensor default)"); } else { ESP_LOGCONFIG(TAG, " Mode: passive with sleep/wake cycles"); @@ -55,44 +54,44 @@ void PMSX003Component::loop() { const uint32_t now = App.get_loop_component_start_time(); // Initialize sensor mode on first loop - if (this->initialised_ == 0) { - if (this->update_interval_ > PMS_STABILISING_MS) { + if (!this->initialised_) { + if (this->update_interval_ > STABILISING_MS) { // Long update interval: use passive mode with sleep/wake cycles - this->send_command_(PMS_CMD_MEASUREMENT_MODE, PMS_CMD_MEASUREMENT_MODE_PASSIVE); - this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_WAKEUP); + this->send_command_(Command::MEASUREMENT_MODE, CMD_MEASUREMENT_MODE_PASSIVE); + this->send_command_(Command::SLEEP_MODE, CMD_SLEEP_MODE_WAKEUP); } else { // Short/zero update interval: use active continuous mode - this->send_command_(PMS_CMD_MEASUREMENT_MODE, PMS_CMD_MEASUREMENT_MODE_ACTIVE); + this->send_command_(Command::MEASUREMENT_MODE, CMD_MEASUREMENT_MODE_ACTIVE); } - this->initialised_ = 1; + this->initialised_ = true; } // If we update less often than it takes the device to stabilise, spin the fan down // rather than running it constantly. It does take some time to stabilise, so we // need to keep track of what state we're in. - if (this->update_interval_ > PMS_STABILISING_MS) { + if (this->update_interval_ > STABILISING_MS) { switch (this->state_) { - case PMSX003_STATE_IDLE: + case State::IDLE: // Power on the sensor now so it'll be ready when we hit the update time - if (now - this->last_update_ < (this->update_interval_ - PMS_STABILISING_MS)) + if (now - this->last_update_ < (this->update_interval_ - STABILISING_MS)) return; - this->state_ = PMSX003_STATE_STABILISING; - this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_WAKEUP); + this->state_ = State::STABILISING; + this->send_command_(Command::SLEEP_MODE, CMD_SLEEP_MODE_WAKEUP); this->fan_on_time_ = now; return; - case PMSX003_STATE_STABILISING: + case State::STABILISING: // wait for the sensor to be stable - if (now - this->fan_on_time_ < PMS_STABILISING_MS) + if (now - this->fan_on_time_ < STABILISING_MS) return; // consume any command responses that are in the serial buffer while (this->available()) this->read_byte(&this->data_[0]); // Trigger a new read - this->send_command_(PMS_CMD_MANUAL_MEASUREMENT, 0); - this->state_ = PMSX003_STATE_WAITING; + this->send_command_(Command::MANUAL_MEASUREMENT, 0); + this->state_ = State::WAITING; break; - case PMSX003_STATE_WAITING: + case State::WAITING: // Just go ahead and read stuff break; } @@ -180,27 +179,28 @@ optional PMSX003Component::check_byte_() { } bool PMSX003Component::check_payload_length_(uint16_t payload_length) { + // https://avaldebe.github.io/PyPMS/sensors/Plantower/ switch (this->type_) { - case PMSX003_TYPE_X003: + case Type::PMSX003: // The expected payload length is typically 28 bytes. // However, a 20-byte payload check was already present in the code. // No official documentation was found confirming this. // Retaining this check to avoid breaking existing behavior. return payload_length == 28 || payload_length == 20; // 2*13+2 - case PMSX003_TYPE_5003T: - case PMSX003_TYPE_5003S: + case Type::PMS5003S: + case Type::PMS5003T: return payload_length == 28; // 2*13+2 (Data 13 not set/reserved) - case PMSX003_TYPE_5003ST: + case Type::PMS5003ST: return payload_length == 36; // 2*17+2 (Data 16 not set/reserved) } return false; } -void PMSX003Component::send_command_(PMSX0003Command cmd, uint16_t data) { +void PMSX003Component::send_command_(Command cmd, uint16_t data) { uint8_t send_data[7] = { START_CHARACTER_1, // Start Byte 1 START_CHARACTER_2, // Start Byte 2 - cmd, // Command + static_cast(cmd), // Command uint8_t((data >> 8) & 0xFF), // Data 1 uint8_t((data >> 0) & 0xFF), // Data 2 0, // Verify Byte 1 @@ -265,7 +265,7 @@ void PMSX003Component::parse_data_() { if (this->pm_particles_25um_sensor_ != nullptr) this->pm_particles_25um_sensor_->publish_state(pm_particles_25um); - if (this->type_ == PMSX003_TYPE_5003T) { + if (this->type_ == Type::PMS5003T) { ESP_LOGD(TAG, "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, " "PM2.5 Particles %u Count/0.1L", @@ -289,7 +289,7 @@ void PMSX003Component::parse_data_() { } // Formaldehyde - if (this->type_ == PMSX003_TYPE_5003ST || this->type_ == PMSX003_TYPE_5003S) { + if (this->type_ == Type::PMS5003S || this->type_ == Type::PMS5003ST) { const uint16_t formaldehyde = this->get_16_bit_uint_(28); ESP_LOGD(TAG, "Got Formaldehyde: %u µg/m^3", formaldehyde); @@ -299,8 +299,8 @@ void PMSX003Component::parse_data_() { } // Temperature and Humidity - if (this->type_ == PMSX003_TYPE_5003ST || this->type_ == PMSX003_TYPE_5003T) { - const uint8_t temperature_offset = (this->type_ == PMSX003_TYPE_5003T) ? 24 : 30; + if (this->type_ == Type::PMS5003T || this->type_ == Type::PMS5003ST) { + const uint8_t temperature_offset = (this->type_ == Type::PMS5003T) ? 24 : 30; const float temperature = static_cast(this->get_16_bit_uint_(temperature_offset)) / 10.0f; const float humidity = this->get_16_bit_uint_(temperature_offset + 2) / 10.0f; @@ -314,7 +314,7 @@ void PMSX003Component::parse_data_() { } // Firmware Version and Error Code - if (this->type_ == PMSX003_TYPE_5003ST) { + if (this->type_ == Type::PMS5003ST) { const uint8_t firmware_version = this->data_[36]; const uint8_t error_code = this->data_[37]; @@ -323,13 +323,12 @@ void PMSX003Component::parse_data_() { // Spin down the sensor again if we aren't going to need it until more time has // passed than it takes to stabilise - if (this->update_interval_ > PMS_STABILISING_MS) { - this->send_command_(PMS_CMD_SLEEP_MODE, PMS_CMD_SLEEP_MODE_SLEEP); - this->state_ = PMSX003_STATE_IDLE; + if (this->update_interval_ > STABILISING_MS) { + this->send_command_(Command::SLEEP_MODE, CMD_SLEEP_MODE_SLEEP); + this->state_ = State::IDLE; } this->status_clear_warning(); } -} // namespace pmsx003 -} // namespace esphome +} // namespace esphome::pmsx003 diff --git a/esphome/components/pmsx003/pmsx003.h b/esphome/components/pmsx003/pmsx003.h index f48121800e..f2d4e68db7 100644 --- a/esphome/components/pmsx003/pmsx003.h +++ b/esphome/components/pmsx003/pmsx003.h @@ -5,27 +5,25 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/uart/uart.h" -namespace esphome { -namespace pmsx003 { +namespace esphome::pmsx003 { -enum PMSX0003Command : uint8_t { - PMS_CMD_MEASUREMENT_MODE = - 0xE1, // Data Options: `PMS_CMD_MEASUREMENT_MODE_PASSIVE`, `PMS_CMD_MEASUREMENT_MODE_ACTIVE` - PMS_CMD_MANUAL_MEASUREMENT = 0xE2, - PMS_CMD_SLEEP_MODE = 0xE4, // Data Options: `PMS_CMD_SLEEP_MODE_SLEEP`, `PMS_CMD_SLEEP_MODE_WAKEUP` +enum class Type : uint8_t { + PMSX003 = 0, + PMS5003S, + PMS5003T, + PMS5003ST, }; -enum PMSX003Type { - PMSX003_TYPE_X003 = 0, - PMSX003_TYPE_5003T, - PMSX003_TYPE_5003ST, - PMSX003_TYPE_5003S, +enum class Command : uint8_t { + MEASUREMENT_MODE = 0xE1, // Data Options: `CMD_MEASUREMENT_MODE_PASSIVE`, `CMD_MEASUREMENT_MODE_ACTIVE` + MANUAL_MEASUREMENT = 0xE2, + SLEEP_MODE = 0xE4, // Data Options: `CMD_SLEEP_MODE_SLEEP`, `CMD_SLEEP_MODE_WAKEUP` }; -enum PMSX003State { - PMSX003_STATE_IDLE = 0, - PMSX003_STATE_STABILISING, - PMSX003_STATE_WAITING, +enum class State : uint8_t { + IDLE = 0, + STABILISING, + WAITING, }; class PMSX003Component : public uart::UARTDevice, public Component { @@ -37,7 +35,7 @@ class PMSX003Component : public uart::UARTDevice, public Component { void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } - void set_type(PMSX003Type type) { this->type_ = type; } + void set_type(Type type) { this->type_ = type; } void set_pm_1_0_std_sensor(sensor::Sensor *pm_1_0_std_sensor) { this->pm_1_0_std_sensor_ = pm_1_0_std_sensor; } void set_pm_2_5_std_sensor(sensor::Sensor *pm_2_5_std_sensor) { this->pm_2_5_std_sensor_ = pm_2_5_std_sensor; } @@ -77,20 +75,20 @@ class PMSX003Component : public uart::UARTDevice, public Component { optional check_byte_(); void parse_data_(); bool check_payload_length_(uint16_t payload_length); - void send_command_(PMSX0003Command cmd, uint16_t data); + void send_command_(Command cmd, uint16_t data); uint16_t get_16_bit_uint_(uint8_t start_index) const { return encode_uint16(this->data_[start_index], this->data_[start_index + 1]); } + Type type_; + State state_{State::IDLE}; + bool initialised_{false}; uint8_t data_[64]; uint8_t data_index_{0}; - uint8_t initialised_{0}; uint32_t fan_on_time_{0}; uint32_t last_update_{0}; uint32_t last_transmission_{0}; uint32_t update_interval_{0}; - PMSX003State state_{PMSX003_STATE_IDLE}; - PMSX003Type type_; // "Standard Particle" sensor::Sensor *pm_1_0_std_sensor_{nullptr}; @@ -118,5 +116,4 @@ class PMSX003Component : public uart::UARTDevice, public Component { sensor::Sensor *humidity_sensor_{nullptr}; }; -} // namespace pmsx003 -} // namespace esphome +} // namespace esphome::pmsx003 diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index bebd3a01ee..4f95b1dcdb 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -41,33 +41,33 @@ PMSX003Component = pmsx003_ns.class_("PMSX003Component", uart.UARTDevice, cg.Com PMSX003Sensor = pmsx003_ns.class_("PMSX003Sensor", sensor.Sensor) TYPE_PMSX003 = "PMSX003" +TYPE_PMS5003S = "PMS5003S" TYPE_PMS5003T = "PMS5003T" TYPE_PMS5003ST = "PMS5003ST" -TYPE_PMS5003S = "PMS5003S" -PMSX003Type = pmsx003_ns.enum("PMSX003Type") +Type = pmsx003_ns.enum("Type", is_class=True) PMSX003_TYPES = { - TYPE_PMSX003: PMSX003Type.PMSX003_TYPE_X003, - TYPE_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T, - TYPE_PMS5003ST: PMSX003Type.PMSX003_TYPE_5003ST, - TYPE_PMS5003S: PMSX003Type.PMSX003_TYPE_5003S, + TYPE_PMSX003: Type.PMSX003, + TYPE_PMS5003S: Type.PMS5003S, + TYPE_PMS5003T: Type.PMS5003T, + TYPE_PMS5003ST: Type.PMS5003ST, } SENSORS_TO_TYPE = { - CONF_PM_1_0: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_2_5: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_10_0: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_1_0_STD: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_2_5_STD: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_10_0_STD: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_0_3UM: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_0_5UM: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_1_0UM: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_2_5UM: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_5_0UM: [TYPE_PMSX003, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_PM_10_0UM: [TYPE_PMSX003, TYPE_PMS5003ST, TYPE_PMS5003S], - CONF_FORMALDEHYDE: [TYPE_PMS5003ST, TYPE_PMS5003S], + CONF_PM_1_0_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_2_5_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_10_0_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_1_0: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_2_5: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_10_0: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_0_3UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_0_5UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_1_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_2_5UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], + CONF_PM_5_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003ST], + CONF_PM_10_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003ST], + CONF_FORMALDEHYDE: [TYPE_PMS5003S, TYPE_PMS5003ST], CONF_TEMPERATURE: [TYPE_PMS5003T, TYPE_PMS5003ST], CONF_HUMIDITY: [TYPE_PMS5003T, TYPE_PMS5003ST], } diff --git a/tests/components/pmsx003/common.yaml b/tests/components/pmsx003/common.yaml index 3c60995804..eaa3cbc3e9 100644 --- a/tests/components/pmsx003/common.yaml +++ b/tests/components/pmsx003/common.yaml @@ -8,11 +8,11 @@ sensor: pm_10_0: name: PM 10.0 Concentration pm_1_0_std: - name: PM 1.0 Standard Atmospher Concentration + name: PM 1.0 Standard Atmospheric Concentration pm_2_5_std: - name: PM 2.5 Standard Atmospher Concentration + name: PM 2.5 Standard Atmospheric Concentration pm_10_0_std: - name: PM 10.0 Standard Atmospher Concentration + name: PM 10.0 Standard Atmospheric Concentration pm_0_3um: name: Particulate Count >0.3um pm_0_5um: From 898c8a583692658fdfd4225490d60eac0339a46c Mon Sep 17 00:00:00 2001 From: Shivam Maurya <54358380+shvmm@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:31:00 +0530 Subject: [PATCH 0433/2030] [core] ESP32 chip revision text (#13647) --- esphome/core/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 55eb25ce09..0e77be9ee4 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -210,7 +210,7 @@ void Application::loop() { #ifdef USE_ESP32 esp_chip_info_t chip_info; esp_chip_info(&chip_info); - ESP_LOGI(TAG, "ESP32 Chip: %s r%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100, + ESP_LOGI(TAG, "ESP32 Chip: %s rev%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100, chip_info.revision % 100, chip_info.cores); #if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET) // Suggest optimization for chips that don't need the PSRAM cache workaround From a1a60c44da41c01be280d0eac59a27d7be2a2723 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 30 Jan 2026 12:48:34 -0600 Subject: [PATCH 0434/2030] [web_server_base] Update ESPAsyncWebServer to 3.9.6 (#13639) --- .clang-tidy.hash | 2 +- esphome/components/web_server_base/__init__.py | 2 +- platformio.ini | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 1cb5f98c28..ab354259e3 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -cf3d341206b4184ec8b7fe85141aef4fe4696aa720c3f8a06d4e57930574bdab +069fa9526c52f7c580a9ec17c7678d12f142221387e9b561c18f95394d4629a3 diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 6c756575d4..6326b4d6ff 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -53,4 +53,4 @@ async def to_code(config): "lib_ignore", ["ESPAsyncTCP", "AsyncTCP", "AsyncTCP_RP2040W"] ) # https://github.com/ESP32Async/ESPAsyncWebServer/blob/main/library.json - cg.add_library("ESP32Async/ESPAsyncWebServer", "3.9.5") + cg.add_library("ESP32Async/ESPAsyncWebServer", "3.9.6") diff --git a/platformio.ini b/platformio.ini index 0f5bf2f8fb..bb0de3c2b1 100644 --- a/platformio.ini +++ b/platformio.ini @@ -114,7 +114,7 @@ lib_deps = ESP8266WiFi ; wifi (Arduino built-in) Update ; ota (Arduino built-in) ESP32Async/ESPAsyncTCP@2.0.0 ; async_tcp - ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base makuna/NeoPixelBus@2.7.3 ; neopixelbus ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) @@ -202,7 +202,7 @@ lib_deps = ${common:arduino.lib_deps} ayushsharma82/RPAsyncTCP@1.3.2 ; async_tcp bblanchon/ArduinoJson@7.4.2 ; json - ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base build_flags = ${common:arduino.build_flags} -DUSE_RP2040 @@ -218,7 +218,7 @@ framework = arduino lib_compat_mode = soft lib_deps = bblanchon/ArduinoJson@7.4.2 ; json - ESP32Async/ESPAsyncWebServer@3.9.5 ; web_server_base + ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base droscy/esp_wireguard@0.4.2 ; wireguard build_flags = ${common:arduino.build_flags} From 4e96b20b46f0ff59c75d549e0ad11f0d9fb287f6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 30 Jan 2026 12:49:14 -0600 Subject: [PATCH 0435/2030] [mqtt] Restore ESP8266 on_message defer to prevent stack overflow (#13648) --- esphome/components/mqtt/mqtt_client.cpp | 32 +++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index e7364f3406..a284b162dd 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -643,10 +643,34 @@ static bool topic_match(const char *message, const char *subscription) { } void MQTTClientComponent::on_message(const std::string &topic, const std::string &payload) { - for (auto &subscription : this->subscriptions_) { - if (topic_match(topic.c_str(), subscription.topic.c_str())) - subscription.callback(topic, payload); - } +#ifdef USE_ESP8266 + // IMPORTANT: This defer is REQUIRED to prevent stack overflow crashes on ESP8266. + // + // On ESP8266, this callback is invoked directly from the lwIP/AsyncTCP network stack + // which runs in the "sys" context with a very limited stack (~4KB). By the time we + // reach this function, the stack is already partially consumed by the network + // processing chain: tcp_input -> AsyncClient::_recv -> AsyncMqttClient::_onMessage -> here. + // + // MQTT subscription callbacks can trigger arbitrary user actions (automations, HTTP + // requests, sensor updates, etc.) which may have deep call stacks of their own. + // For example, an HTTP request action requires: DNS lookup -> TCP connect -> TLS + // handshake (if HTTPS) -> request formatting. This easily overflows the remaining + // system stack space, causing a LoadStoreAlignmentCause exception or silent corruption. + // + // By deferring to the main loop, we ensure callbacks execute with a fresh, full-size + // stack in the normal application context rather than the constrained network task. + // + // DO NOT REMOVE THIS DEFER without understanding the above. It may appear to work + // in simple tests but will cause crashes with complex automations. + this->defer([this, topic, payload]() { +#endif + for (auto &subscription : this->subscriptions_) { + if (topic_match(topic.c_str(), subscription.topic.c_str())) + subscription.callback(topic, payload); + } +#ifdef USE_ESP8266 + }); +#endif } // Setters From ca9ed369f97d792757cdd79d48841accb1a63226 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht Date: Fri, 30 Jan 2026 20:59:47 +0100 Subject: [PATCH 0436/2030] [pmsx003] support device-types `PMS1003`, `PMS3003`, `PMS9003M` (#13640) --- esphome/components/pmsx003/pmsx003.cpp | 28 +++--- esphome/components/pmsx003/pmsx003.h | 5 +- esphome/components/pmsx003/sensor.py | 120 ++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 26 deletions(-) diff --git a/esphome/components/pmsx003/pmsx003.cpp b/esphome/components/pmsx003/pmsx003.cpp index b0920de062..114ecf435e 100644 --- a/esphome/components/pmsx003/pmsx003.cpp +++ b/esphome/components/pmsx003/pmsx003.cpp @@ -181,17 +181,20 @@ optional PMSX003Component::check_byte_() { bool PMSX003Component::check_payload_length_(uint16_t payload_length) { // https://avaldebe.github.io/PyPMS/sensors/Plantower/ switch (this->type_) { - case Type::PMSX003: - // The expected payload length is typically 28 bytes. - // However, a 20-byte payload check was already present in the code. - // No official documentation was found confirming this. - // Retaining this check to avoid breaking existing behavior. + case Type::PMS1003: + return payload_length == 28; // 2*13+2 + case Type::PMS3003: // Data 7/8/9 not set/reserved + return payload_length == 20; // 2*9+2 + case Type::PMSX003: // Data 13 not set/reserved + // Deprecated: Length 20 is for PMS3003 backwards compatibility return payload_length == 28 || payload_length == 20; // 2*13+2 case Type::PMS5003S: - case Type::PMS5003T: - return payload_length == 28; // 2*13+2 (Data 13 not set/reserved) - case Type::PMS5003ST: - return payload_length == 36; // 2*17+2 (Data 16 not set/reserved) + case Type::PMS5003T: // Data 13 not set/reserved + return payload_length == 28; // 2*13+2 + case Type::PMS5003ST: // Data 16 not set/reserved + return payload_length == 36; // 2*17+2 + case Type::PMS9003M: + return payload_length == 28; // 2*13+2 } return false; } @@ -314,9 +317,10 @@ void PMSX003Component::parse_data_() { } // Firmware Version and Error Code - if (this->type_ == Type::PMS5003ST) { - const uint8_t firmware_version = this->data_[36]; - const uint8_t error_code = this->data_[37]; + if (this->type_ == Type::PMS1003 || this->type_ == Type::PMS5003ST || this->type_ == Type::PMS9003M) { + const uint8_t firmware_error_code_offset = (this->type_ == Type::PMS5003ST) ? 36 : 28; + const uint8_t firmware_version = this->data_[firmware_error_code_offset]; + const uint8_t error_code = this->data_[firmware_error_code_offset + 1]; ESP_LOGD(TAG, "Got Firmware Version: 0x%02X, Error Code: 0x%02X", firmware_version, error_code); } diff --git a/esphome/components/pmsx003/pmsx003.h b/esphome/components/pmsx003/pmsx003.h index f2d4e68db7..d559f2dec0 100644 --- a/esphome/components/pmsx003/pmsx003.h +++ b/esphome/components/pmsx003/pmsx003.h @@ -8,10 +8,13 @@ namespace esphome::pmsx003 { enum class Type : uint8_t { - PMSX003 = 0, + PMS1003 = 0, + PMS3003, + PMSX003, // PMS5003, PMS6003, PMS7003, PMSA003 (NOT PMSA003I - see `pmsa003i` component) PMS5003S, PMS5003T, PMS5003ST, + PMS9003M, }; enum class Command : uint8_t { diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index 4f95b1dcdb..cdcedc85ac 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -40,33 +40,127 @@ pmsx003_ns = cg.esphome_ns.namespace("pmsx003") PMSX003Component = pmsx003_ns.class_("PMSX003Component", uart.UARTDevice, cg.Component) PMSX003Sensor = pmsx003_ns.class_("PMSX003Sensor", sensor.Sensor) -TYPE_PMSX003 = "PMSX003" +TYPE_PMS1003 = "PMS1003" +TYPE_PMS3003 = "PMS3003" +TYPE_PMSX003 = "PMSX003" # PMS5003, PMS6003, PMS7003, PMSA003 (NOT PMSA003I - see `pmsa003i` component) TYPE_PMS5003S = "PMS5003S" TYPE_PMS5003T = "PMS5003T" TYPE_PMS5003ST = "PMS5003ST" +TYPE_PMS9003M = "PMS9003M" Type = pmsx003_ns.enum("Type", is_class=True) PMSX003_TYPES = { + TYPE_PMS1003: Type.PMS1003, + TYPE_PMS3003: Type.PMS3003, TYPE_PMSX003: Type.PMSX003, TYPE_PMS5003S: Type.PMS5003S, TYPE_PMS5003T: Type.PMS5003T, TYPE_PMS5003ST: Type.PMS5003ST, + TYPE_PMS9003M: Type.PMS9003M, } SENSORS_TO_TYPE = { - CONF_PM_1_0_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_2_5_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_10_0_STD: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_1_0: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_2_5: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_10_0: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_0_3UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_0_5UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_1_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_2_5UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003T, TYPE_PMS5003ST], - CONF_PM_5_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003ST], - CONF_PM_10_0UM: [TYPE_PMSX003, TYPE_PMS5003S, TYPE_PMS5003ST], + CONF_PM_1_0_STD: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_2_5_STD: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_10_0_STD: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_1_0: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_2_5: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_10_0: [ + TYPE_PMS1003, + TYPE_PMS3003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_0_3UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_0_5UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_1_0UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_2_5UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003T, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_5_0UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], + CONF_PM_10_0UM: [ + TYPE_PMS1003, + TYPE_PMSX003, + TYPE_PMS5003S, + TYPE_PMS5003ST, + TYPE_PMS9003M, + ], CONF_FORMALDEHYDE: [TYPE_PMS5003S, TYPE_PMS5003ST], CONF_TEMPERATURE: [TYPE_PMS5003T, TYPE_PMS5003ST], CONF_HUMIDITY: [TYPE_PMS5003T, TYPE_PMS5003ST], From 5e3561d60bddad69629e2f558676687ac5259847 Mon Sep 17 00:00:00 2001 From: J0k3r2k1 <60352302+J0k3r2k1@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:33:45 +0100 Subject: [PATCH 0437/2030] [mipi_spi] Fix log_pin() FlashStringHelper compatibility (#13624) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/mipi_spi/mipi_spi.cpp | 39 +++++++++++++++++-- esphome/components/mipi_spi/mipi_spi.h | 39 ++++--------------- .../components/mipi_spi/test.esp8266-ard.yaml | 10 +++++ 3 files changed, 54 insertions(+), 34 deletions(-) create mode 100644 tests/components/mipi_spi/test.esp8266-ard.yaml diff --git a/esphome/components/mipi_spi/mipi_spi.cpp b/esphome/components/mipi_spi/mipi_spi.cpp index 272915b4e1..90f6324511 100644 --- a/esphome/components/mipi_spi/mipi_spi.cpp +++ b/esphome/components/mipi_spi/mipi_spi.cpp @@ -1,6 +1,39 @@ #include "mipi_spi.h" #include "esphome/core/log.h" -namespace esphome { -namespace mipi_spi {} // namespace mipi_spi -} // namespace esphome +namespace esphome::mipi_spi { + +void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, + bool invert_colors, int display_bits, bool is_big_endian, const optional &brightness, + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width) { + ESP_LOGCONFIG(TAG, + "MIPI_SPI Display\n" + " Model: %s\n" + " Width: %d\n" + " Height: %d\n" + " Swap X/Y: %s\n" + " Mirror X: %s\n" + " Mirror Y: %s\n" + " Invert colors: %s\n" + " Color order: %s\n" + " Display pixels: %d bits\n" + " Endianness: %s\n" + " SPI Mode: %d\n" + " SPI Data rate: %uMHz\n" + " SPI Bus width: %d", + model, width, height, YESNO(madctl & MADCTL_MV), YESNO(madctl & (MADCTL_MX | MADCTL_XFLIP)), + YESNO(madctl & (MADCTL_MY | MADCTL_YFLIP)), YESNO(invert_colors), (madctl & MADCTL_BGR) ? "BGR" : "RGB", + display_bits, is_big_endian ? "Big" : "Little", spi_mode, static_cast(data_rate / 1000000), + bus_width); + LOG_PIN(" CS Pin: ", cs); + LOG_PIN(" Reset Pin: ", reset); + LOG_PIN(" DC Pin: ", dc); + if (offset_width != 0) + ESP_LOGCONFIG(TAG, " Offset width: %d", offset_width); + if (offset_height != 0) + ESP_LOGCONFIG(TAG, " Offset height: %d", offset_height); + if (brightness.has_value()) + ESP_LOGCONFIG(TAG, " Brightness: %u", brightness.value()); +} + +} // namespace esphome::mipi_spi diff --git a/esphome/components/mipi_spi/mipi_spi.h b/esphome/components/mipi_spi/mipi_spi.h index fd5bc97596..083ff9507f 100644 --- a/esphome/components/mipi_spi/mipi_spi.h +++ b/esphome/components/mipi_spi/mipi_spi.h @@ -63,6 +63,11 @@ enum BusType { BUS_TYPE_SINGLE_16 = 16, // Single bit bus, but 16 bits per transfer }; +// Helper function for dump_config - defined in mipi_spi.cpp to allow use of LOG_PIN macro +void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, + bool invert_colors, int display_bits, bool is_big_endian, const optional &brightness, + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width); + /** * Base class for MIPI SPI displays. * All the methods are defined here in the header file, as it is not possible to define templated methods in a cpp file. @@ -201,37 +206,9 @@ class MipiSpi : public display::Display, } void dump_config() override { - esph_log_config(TAG, - "MIPI_SPI Display\n" - " Model: %s\n" - " Width: %u\n" - " Height: %u", - this->model_, WIDTH, HEIGHT); - if constexpr (OFFSET_WIDTH != 0) - esph_log_config(TAG, " Offset width: %u", OFFSET_WIDTH); - if constexpr (OFFSET_HEIGHT != 0) - esph_log_config(TAG, " Offset height: %u", OFFSET_HEIGHT); - esph_log_config(TAG, - " Swap X/Y: %s\n" - " Mirror X: %s\n" - " Mirror Y: %s\n" - " Invert colors: %s\n" - " Color order: %s\n" - " Display pixels: %d bits\n" - " Endianness: %s\n", - YESNO(this->madctl_ & MADCTL_MV), YESNO(this->madctl_ & (MADCTL_MX | MADCTL_XFLIP)), - YESNO(this->madctl_ & (MADCTL_MY | MADCTL_YFLIP)), YESNO(this->invert_colors_), - this->madctl_ & MADCTL_BGR ? "BGR" : "RGB", DISPLAYPIXEL * 8, IS_BIG_ENDIAN ? "Big" : "Little"); - if (this->brightness_.has_value()) - esph_log_config(TAG, " Brightness: %u", this->brightness_.value()); - log_pin(TAG, " CS Pin: ", this->cs_); - log_pin(TAG, " Reset Pin: ", this->reset_pin_); - log_pin(TAG, " DC Pin: ", this->dc_pin_); - esph_log_config(TAG, - " SPI Mode: %d\n" - " SPI Data rate: %dMHz\n" - " SPI Bus width: %d", - this->mode_, static_cast(this->data_rate_ / 1000000), BUS_TYPE); + internal_dump_config(this->model_, WIDTH, HEIGHT, OFFSET_WIDTH, OFFSET_HEIGHT, this->madctl_, this->invert_colors_, + DISPLAYPIXEL * 8, IS_BIG_ENDIAN, this->brightness_, this->cs_, this->reset_pin_, this->dc_pin_, + this->mode_, this->data_rate_, BUS_TYPE); } protected: diff --git a/tests/components/mipi_spi/test.esp8266-ard.yaml b/tests/components/mipi_spi/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ef6197d852 --- /dev/null +++ b/tests/components/mipi_spi/test.esp8266-ard.yaml @@ -0,0 +1,10 @@ +substitutions: + dc_pin: GPIO15 + cs_pin: GPIO5 + enable_pin: GPIO4 + reset_pin: GPIO16 + +packages: + spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml + +<<: !include common.yaml From 9dcb469460e1dddc6988bddb001fc0c60c17aa0f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 31 Jan 2026 12:18:30 +1100 Subject: [PATCH 0438/2030] [core] Simplify generation of Lambda during `to_code()` (#13533) --- esphome/components/udp/__init__.py | 17 +- esphome/core/__init__.py | 4 + esphome/cpp_generator.py | 20 +- tests/unit_tests/test_cpp_generator.py | 277 +++++++++++++++++++++++++ 4 files changed, 310 insertions(+), 8 deletions(-) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 9be196d420..8252e35023 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -12,8 +12,8 @@ from esphome.components.packet_transport import ( ) import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID -from esphome.core import ID, Lambda -from esphome.cpp_generator import ExpressionStatement, MockObj +from esphome.core import ID +from esphome.cpp_generator import literal CODEOWNERS = ["@clydebarrow"] DEPENDENCIES = ["network"] @@ -24,6 +24,8 @@ udp_ns = cg.esphome_ns.namespace("udp") UDPComponent = udp_ns.class_("UDPComponent", cg.Component) UDPWriteAction = udp_ns.class_("UDPWriteAction", automation.Action) trigger_args = cg.std_vector.template(cg.uint8) +trigger_argname = "data" +trigger_argtype = [(trigger_args, trigger_argname)] CONF_ADDRESSES = "addresses" CONF_LISTEN_ADDRESS = "listen_address" @@ -111,13 +113,14 @@ async def to_code(config): cg.add(var.set_addresses([str(addr) for addr in config[CONF_ADDRESSES]])) if on_receive := config.get(CONF_ON_RECEIVE): on_receive = on_receive[0] - trigger = cg.new_Pvariable(on_receive[CONF_TRIGGER_ID]) + trigger_id = cg.new_Pvariable(on_receive[CONF_TRIGGER_ID]) trigger = await automation.build_automation( - trigger, [(trigger_args, "data")], on_receive + trigger_id, trigger_argtype, on_receive ) - trigger = Lambda(str(ExpressionStatement(trigger.trigger(MockObj("data"))))) - trigger = await cg.process_lambda(trigger, [(trigger_args, "data")]) - cg.add(var.add_listener(trigger)) + trigger_lambda = await cg.process_lambda( + trigger.trigger(literal(trigger_argname)), trigger_argtype + ) + cg.add(var.add_listener(trigger_lambda)) cg.add(var.set_should_listen()) diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 9a7dd49609..5308ad241e 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -278,9 +278,13 @@ LAMBDA_PROG = re.compile(r"\bid\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)(\.?)") class Lambda: def __init__(self, value): + from esphome.cpp_generator import Expression, statement + # pylint: disable=protected-access if isinstance(value, Lambda): self._value = value._value + elif isinstance(value, Expression): + self._value = str(statement(value)) else: self._value = value self._parts = None diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index cff0748c95..83f2d6cf81 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -462,6 +462,16 @@ def statement(expression: Expression | Statement) -> Statement: return ExpressionStatement(expression) +def literal(name: str) -> "MockObj": + """Create a literal name that will appear in the generated code + not surrounded by quotes. + + :param name: The name of the literal. + :return: The literal as a MockObj. + """ + return MockObj(name, "") + + def variable( id_: ID, rhs: SafeExpType, type_: "MockObj" = None, register=True ) -> "MockObj": @@ -665,7 +675,7 @@ async def get_variable_with_full_id(id_: ID) -> tuple[ID, "MockObj"]: async def process_lambda( - value: Lambda, + value: Lambda | Expression, parameters: TemplateArgsType, capture: str = "", return_type: SafeExpType = None, @@ -689,6 +699,14 @@ async def process_lambda( if value is None: return None + # Inadvertently passing a malformed parameters value will lead to the build process mysteriously hanging at the + # "Generating C++ source..." stage, so check here to save the developer's hair. + assert isinstance(parameters, list) and all( + isinstance(p, tuple) and len(p) == 2 for p in parameters + ) + if isinstance(value, Expression): + value = Lambda(value) + parts = value.parts[:] for i, id in enumerate(value.requires_ids): full_id, var = await get_variable_with_full_id(id) diff --git a/tests/unit_tests/test_cpp_generator.py b/tests/unit_tests/test_cpp_generator.py index 2c9f760c8e..8755e6e2a1 100644 --- a/tests/unit_tests/test_cpp_generator.py +++ b/tests/unit_tests/test_cpp_generator.py @@ -347,3 +347,280 @@ class TestMockObj: assert isinstance(actual, cg.MockObj) assert actual.base == "foo.eek" assert actual.op == "." + + +class TestStatementFunction: + """Tests for the statement() function.""" + + def test_statement__expression_converted_to_statement(self): + """Test that expressions are converted to ExpressionStatement.""" + expr = cg.RawExpression("foo()") + result = cg.statement(expr) + + assert isinstance(result, cg.ExpressionStatement) + assert str(result) == "foo();" + + def test_statement__statement_unchanged(self): + """Test that statements are returned unchanged.""" + stmt = cg.RawStatement("foo()") + result = cg.statement(stmt) + + assert result is stmt + assert str(result) == "foo()" + + def test_statement__expression_statement_unchanged(self): + """Test that ExpressionStatement is returned unchanged.""" + stmt = cg.ExpressionStatement(42) + result = cg.statement(stmt) + + assert result is stmt + assert str(result) == "42;" + + def test_statement__line_comment_unchanged(self): + """Test that LineComment is returned unchanged.""" + stmt = cg.LineComment("This is a comment") + result = cg.statement(stmt) + + assert result is stmt + assert str(result) == "// This is a comment" + + +class TestLiteralFunction: + """Tests for the literal() function.""" + + def test_literal__creates_mockobj(self): + """Test that literal() creates a MockObj.""" + result = cg.literal("MY_CONSTANT") + + assert isinstance(result, cg.MockObj) + assert result.base == "MY_CONSTANT" + assert result.op == "" + + def test_literal__string_representation(self): + """Test that literal names appear unquoted in generated code.""" + result = cg.literal("nullptr") + + assert str(result) == "nullptr" + + def test_literal__can_be_used_in_expressions(self): + """Test that literals can be used as part of larger expressions.""" + null_lit = cg.literal("nullptr") + expr = cg.CallExpression(cg.RawExpression("my_func"), null_lit) + + assert str(expr) == "my_func(nullptr)" + + def test_literal__common_cpp_literals(self): + """Test common C++ literal values.""" + test_cases = [ + ("nullptr", "nullptr"), + ("true", "true"), + ("false", "false"), + ("NULL", "NULL"), + ("NAN", "NAN"), + ] + + for name, expected in test_cases: + result = cg.literal(name) + assert str(result) == expected + + +class TestLambdaConstructor: + """Tests for the Lambda class constructor in core/__init__.py.""" + + def test_lambda__from_string(self): + """Test Lambda constructor with string argument.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x + 1;") + + assert lambda_obj.value == "return x + 1;" + assert str(lambda_obj) == "return x + 1;" + + def test_lambda__from_expression(self): + """Test Lambda constructor with Expression argument.""" + from esphome.core import Lambda + + expr = cg.RawExpression("x + 1") + lambda_obj = Lambda(expr) + + # Expression should be converted to statement (with semicolon) + assert lambda_obj.value == "x + 1;" + + def test_lambda__from_lambda(self): + """Test Lambda constructor with another Lambda argument.""" + from esphome.core import Lambda + + original = Lambda("return x + 1;") + copy = Lambda(original) + + assert copy.value == original.value + assert copy.value == "return x + 1;" + + def test_lambda__parts_parsing(self): + """Test that Lambda correctly parses parts with id() references.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return id(my_sensor).state;") + parts = lambda_obj.parts + + # Parts should be split by LAMBDA_PROG regex: text, id, op, text + assert len(parts) == 4 + assert parts[0] == "return " + assert parts[1] == "my_sensor" + assert parts[2] == "." + assert parts[3] == "state;" + + def test_lambda__requires_ids(self): + """Test that Lambda correctly extracts required IDs.""" + from esphome.core import ID, Lambda + + lambda_obj = Lambda("return id(sensor1).state + id(sensor2).value;") + ids = lambda_obj.requires_ids + + assert len(ids) == 2 + assert all(isinstance(id_obj, ID) for id_obj in ids) + assert ids[0].id == "sensor1" + assert ids[1].id == "sensor2" + + def test_lambda__no_ids(self): + """Test Lambda with no id() references.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return 42;") + ids = lambda_obj.requires_ids + + assert len(ids) == 0 + + def test_lambda__comment_removal(self): + """Test that comments are removed when parsing parts.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return id(sensor).state; // Get sensor state") + parts = lambda_obj.parts + + # Comment should be replaced with space, not affect parsing + assert "my_sensor" not in str(parts) + + def test_lambda__multiline_string(self): + """Test Lambda with multiline string.""" + from esphome.core import Lambda + + code = """if (id(sensor).state > 0) { + return true; +} +return false;""" + lambda_obj = Lambda(code) + + assert lambda_obj.value == code + assert "sensor" in [id_obj.id for id_obj in lambda_obj.requires_ids] + + +@pytest.mark.asyncio +class TestProcessLambda: + """Tests for the process_lambda() async function.""" + + async def test_process_lambda__none_value(self): + """Test that None returns None.""" + result = await cg.process_lambda(None, []) + + assert result is None + + async def test_process_lambda__with_expression(self): + """Test process_lambda with Expression argument.""" + + expr = cg.RawExpression("return x + 1") + result = await cg.process_lambda(expr, [(int, "x")]) + + assert isinstance(result, cg.LambdaExpression) + assert "x + 1" in str(result) + + async def test_process_lambda__simple_lambda_no_ids(self): + """Test process_lambda with simple Lambda without id() references.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x + 1;") + result = await cg.process_lambda(lambda_obj, [(int, "x")]) + + assert isinstance(result, cg.LambdaExpression) + # Should have parameter + lambda_str = str(result) + assert "int32_t x" in lambda_str + assert "return x + 1;" in lambda_str + + async def test_process_lambda__with_return_type(self): + """Test process_lambda with return type specified.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x > 0;") + result = await cg.process_lambda(lambda_obj, [(int, "x")], return_type=bool) + + assert isinstance(result, cg.LambdaExpression) + lambda_str = str(result) + assert "-> bool" in lambda_str + + async def test_process_lambda__with_capture(self): + """Test process_lambda with capture specified.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return captured + x;") + result = await cg.process_lambda(lambda_obj, [(int, "x")], capture="captured") + + assert isinstance(result, cg.LambdaExpression) + lambda_str = str(result) + assert "[captured]" in lambda_str + + async def test_process_lambda__empty_capture(self): + """Test process_lambda with empty capture (stateless lambda).""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x + 1;") + result = await cg.process_lambda(lambda_obj, [(int, "x")], capture="") + + assert isinstance(result, cg.LambdaExpression) + lambda_str = str(result) + assert "[]" in lambda_str + + async def test_process_lambda__no_parameters(self): + """Test process_lambda with no parameters.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return 42;") + result = await cg.process_lambda(lambda_obj, []) + + assert isinstance(result, cg.LambdaExpression) + lambda_str = str(result) + # Should have empty parameter list + assert "()" in lambda_str + + async def test_process_lambda__multiple_parameters(self): + """Test process_lambda with multiple parameters.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x + y + z;") + result = await cg.process_lambda( + lambda_obj, [(int, "x"), (float, "y"), (bool, "z")] + ) + + assert isinstance(result, cg.LambdaExpression) + lambda_str = str(result) + assert "int32_t x" in lambda_str + assert "float y" in lambda_str + assert "bool z" in lambda_str + + async def test_process_lambda__parameter_validation(self): + """Test that malformed parameters raise assertion error.""" + from esphome.core import Lambda + + lambda_obj = Lambda("return x;") + + # Test invalid parameter format (not list of tuples) + with pytest.raises(AssertionError): + await cg.process_lambda(lambda_obj, "invalid") + + # Test invalid tuple format (not 2-element tuples) + with pytest.raises(AssertionError): + await cg.process_lambda(lambda_obj, [(int, "x", "extra")]) + + # Test invalid tuple format (single element) + with pytest.raises(AssertionError): + await cg.process_lambda(lambda_obj, [(int,)]) From 0fd50b2381e6a137243d9a96ae493ba5d2c8f10c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 31 Jan 2026 01:21:52 -0600 Subject: [PATCH 0439/2030] [esp32] Disable unused per-tag log filtering, saving ~536 bytes RAM (#13662) --- esphome/components/esp32/__init__.py | 4 ++++ esphome/components/i2c/i2c.cpp | 9 --------- esphome/components/logger/logger_esp32.cpp | 3 --- esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp | 5 +++-- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index a3154f9933..aed4ecad90 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1329,6 +1329,10 @@ async def to_code(config): # Disable dynamic log level control to save memory add_idf_sdkconfig_option("CONFIG_LOG_DYNAMIC_LEVEL_CONTROL", False) + # Disable per-tag log level filtering since dynamic level control is disabled above + # This saves ~250 bytes of RAM (tag cache) and associated code + add_idf_sdkconfig_option("CONFIG_LOG_TAG_LEVEL_IMPL_NONE", True) + # Reduce PHY TX power in the event of a brownout add_idf_sdkconfig_option("CONFIG_ESP_PHY_REDUCE_TX_POWER", True) diff --git a/esphome/components/i2c/i2c.cpp b/esphome/components/i2c/i2c.cpp index c1e7336ce4..b9b5d79428 100644 --- a/esphome/components/i2c/i2c.cpp +++ b/esphome/components/i2c/i2c.cpp @@ -11,12 +11,6 @@ namespace i2c { static const char *const TAG = "i2c"; void I2CBus::i2c_scan_() { - // suppress logs from the IDF I2C library during the scan -#if defined(USE_ESP32) && defined(USE_LOGGER) - auto previous = esp_log_level_get("*"); - esp_log_level_set("*", ESP_LOG_NONE); -#endif - for (uint8_t address = 8; address != 120; address++) { auto err = write_readv(address, nullptr, 0, nullptr, 0); if (err == ERROR_OK) { @@ -27,9 +21,6 @@ void I2CBus::i2c_scan_() { // it takes 16sec to scan on nrf52. It prevents board reset. arch_feed_wdt(); } -#if defined(USE_ESP32) && defined(USE_LOGGER) - esp_log_level_set("*", previous); -#endif } ErrorCode I2CDevice::read_register(uint8_t a_register, uint8_t *data, size_t len) { diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 32ef752462..9defb6c166 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -114,9 +114,6 @@ void Logger::pre_setup() { global_logger = this; esp_log_set_vprintf(esp_idf_log_vprintf_); - if (ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE) { - esp_log_level_set("*", ESP_LOG_VERBOSE); - } ESP_LOGI(TAG, "Log initialized"); } diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index 5c91150f30..224d6e3ab1 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -155,8 +155,9 @@ void USBCDCACMInstance::setup() { return; } - // Use a larger stack size for (very) verbose logging - const size_t stack_size = esp_log_level_get(TAG) > ESP_LOG_DEBUG ? USB_TX_TASK_STACK_SIZE_VV : USB_TX_TASK_STACK_SIZE; + // Use a larger stack size for very verbose logging + constexpr size_t stack_size = + ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE ? USB_TX_TASK_STACK_SIZE_VV : USB_TX_TASK_STACK_SIZE; // Create a simple, unique task name per interface char task_name[] = "usb_tx_0"; From 891382a32ee35578571186c8407ce8cabe7deccd Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 31 Jan 2026 09:59:13 -0500 Subject: [PATCH 0440/2030] [max7219] Allocate buffer in constructor (#13660) Co-authored-by: Claude Opus 4.5 --- esphome/components/max7219/display.py | 3 +-- esphome/components/max7219/max7219.cpp | 17 ++++++++--------- esphome/components/max7219/max7219.h | 11 +++++------ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/esphome/components/max7219/display.py b/esphome/components/max7219/display.py index a434125148..abb20702bd 100644 --- a/esphome/components/max7219/display.py +++ b/esphome/components/max7219/display.py @@ -28,11 +28,10 @@ CONFIG_SCHEMA = ( async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + var = cg.new_Pvariable(config[CONF_ID], config[CONF_NUM_CHIPS]) await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) - cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) cg.add(var.set_intensity(config[CONF_INTENSITY])) cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE])) diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index 157b317c02..d701e6fc86 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -3,8 +3,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace max7219 { +namespace esphome::max7219 { static const char *const TAG = "max7219"; @@ -115,12 +114,14 @@ const uint8_t MAX7219_ASCII_TO_RAW[95] PROGMEM = { }; float MAX7219Component::get_setup_priority() const { return setup_priority::PROCESSOR; } + +MAX7219Component::MAX7219Component(uint8_t num_chips) : num_chips_(num_chips) { + this->buffer_ = new uint8_t[this->num_chips_ * 8]; // NOLINT + memset(this->buffer_, 0, this->num_chips_ * 8); +} + void MAX7219Component::setup() { this->spi_setup(); - this->buffer_ = new uint8_t[this->num_chips_ * 8]; // NOLINT - for (uint8_t i = 0; i < this->num_chips_ * 8; i++) - this->buffer_[i] = 0; - // let's assume the user has all 8 digits connected, only important in daisy chained setups anyway this->send_to_all_(MAX7219_REGISTER_SCAN_LIMIT, 7); // let's use our own ASCII -> led pattern encoding @@ -229,7 +230,6 @@ void MAX7219Component::set_intensity(uint8_t intensity) { this->intensity_ = intensity; } } -void MAX7219Component::set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; } uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time) { char buffer[64]; @@ -240,5 +240,4 @@ uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time } uint8_t MAX7219Component::strftime(const char *format, ESPTime time) { return this->strftime(0, format, time); } -} // namespace max7219 -} // namespace esphome +} // namespace esphome::max7219 diff --git a/esphome/components/max7219/max7219.h b/esphome/components/max7219/max7219.h index 58d871d54c..ef38628f28 100644 --- a/esphome/components/max7219/max7219.h +++ b/esphome/components/max7219/max7219.h @@ -6,8 +6,7 @@ #include "esphome/components/spi/spi.h" #include "esphome/components/display/display.h" -namespace esphome { -namespace max7219 { +namespace esphome::max7219 { class MAX7219Component; @@ -17,6 +16,8 @@ class MAX7219Component : public PollingComponent, public spi::SPIDevice { public: + explicit MAX7219Component(uint8_t num_chips); + void set_writer(max7219_writer_t &&writer); void setup() override; @@ -30,7 +31,6 @@ class MAX7219Component : public PollingComponent, void display(); void set_intensity(uint8_t intensity); - void set_num_chips(uint8_t num_chips); void set_reverse(bool reverse) { this->reverse_ = reverse; }; /// Evaluate the printf-format and print the result at the given position. @@ -56,10 +56,9 @@ class MAX7219Component : public PollingComponent, uint8_t intensity_{15}; // Intensity of the display from 0 to 15 (most) bool intensity_changed_{}; // True if we need to re-send the intensity uint8_t num_chips_{1}; - uint8_t *buffer_; + uint8_t *buffer_{nullptr}; bool reverse_{false}; max7219_writer_t writer_{}; }; -} // namespace max7219 -} // namespace esphome +} // namespace esphome::max7219 From 1ff2f3b6a38386af88b61758fb904808ce4c2c0d Mon Sep 17 00:00:00 2001 From: Simon Fischer Date: Sat, 31 Jan 2026 16:48:27 +0100 Subject: [PATCH 0441/2030] [dlms_meter] Add dlms smart meter component (#8009) Co-authored-by: Thomas Rupprecht Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 --- CODEOWNERS | 1 + esphome/components/dlms_meter/__init__.py | 57 +++ esphome/components/dlms_meter/dlms.h | 71 +++ esphome/components/dlms_meter/dlms_meter.cpp | 468 ++++++++++++++++++ esphome/components/dlms_meter/dlms_meter.h | 96 ++++ esphome/components/dlms_meter/mbus.h | 69 +++ esphome/components/dlms_meter/obis.h | 94 ++++ .../components/dlms_meter/sensor/__init__.py | 124 +++++ .../dlms_meter/text_sensor/__init__.py | 37 ++ .../components/dlms_meter/common-generic.yaml | 11 + .../components/dlms_meter/common-netznoe.yaml | 17 + tests/components/dlms_meter/common.yaml | 27 + .../components/dlms_meter/test.esp32-ard.yaml | 4 + .../components/dlms_meter/test.esp32-idf.yaml | 4 + .../dlms_meter/test.esp8266-ard.yaml | 4 + .../common/uart_2400/esp32-ard.yaml | 11 + .../common/uart_2400/esp32-idf.yaml | 11 + .../common/uart_2400/esp8266-ard.yaml | 11 + 18 files changed, 1117 insertions(+) create mode 100644 esphome/components/dlms_meter/__init__.py create mode 100644 esphome/components/dlms_meter/dlms.h create mode 100644 esphome/components/dlms_meter/dlms_meter.cpp create mode 100644 esphome/components/dlms_meter/dlms_meter.h create mode 100644 esphome/components/dlms_meter/mbus.h create mode 100644 esphome/components/dlms_meter/obis.h create mode 100644 esphome/components/dlms_meter/sensor/__init__.py create mode 100644 esphome/components/dlms_meter/text_sensor/__init__.py create mode 100644 tests/components/dlms_meter/common-generic.yaml create mode 100644 tests/components/dlms_meter/common-netznoe.yaml create mode 100644 tests/components/dlms_meter/common.yaml create mode 100644 tests/components/dlms_meter/test.esp32-ard.yaml create mode 100644 tests/components/dlms_meter/test.esp32-idf.yaml create mode 100644 tests/components/dlms_meter/test.esp8266-ard.yaml create mode 100644 tests/test_build_components/common/uart_2400/esp32-ard.yaml create mode 100644 tests/test_build_components/common/uart_2400/esp32-idf.yaml create mode 100644 tests/test_build_components/common/uart_2400/esp8266-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index b7675f9406..1d165a6f57 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -134,6 +134,7 @@ esphome/components/dfplayer/* @glmnet esphome/components/dfrobot_sen0395/* @niklasweber esphome/components/dht/* @OttoWinter esphome/components/display_menu_base/* @numo68 +esphome/components/dlms_meter/* @SimonFischer04 esphome/components/dps310/* @kbx81 esphome/components/ds1307/* @badbadc0ffee esphome/components/ds2484/* @mrk-its diff --git a/esphome/components/dlms_meter/__init__.py b/esphome/components/dlms_meter/__init__.py new file mode 100644 index 0000000000..c22ab7b552 --- /dev/null +++ b/esphome/components/dlms_meter/__init__.py @@ -0,0 +1,57 @@ +import esphome.codegen as cg +from esphome.components import uart +import esphome.config_validation as cv +from esphome.const import CONF_ID, PLATFORM_ESP32, PLATFORM_ESP8266 + +CODEOWNERS = ["@SimonFischer04"] +DEPENDENCIES = ["uart"] + +CONF_DLMS_METER_ID = "dlms_meter_id" +CONF_DECRYPTION_KEY = "decryption_key" +CONF_PROVIDER = "provider" + +PROVIDERS = {"generic": 0, "netznoe": 1} + +dlms_meter_component_ns = cg.esphome_ns.namespace("dlms_meter") +DlmsMeterComponent = dlms_meter_component_ns.class_( + "DlmsMeterComponent", cg.Component, uart.UARTDevice +) + + +def validate_key(value): + value = cv.string_strict(value) + if len(value) != 32: + raise cv.Invalid("Decryption key must be 32 hex characters (16 bytes)") + try: + return [int(value[i : i + 2], 16) for i in range(0, 32, 2)] + except ValueError as exc: + raise cv.Invalid("Decryption key must be hex values from 00 to FF") from exc + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(DlmsMeterComponent), + cv.Required(CONF_DECRYPTION_KEY): validate_key, + cv.Optional(CONF_PROVIDER, default="generic"): cv.enum( + PROVIDERS, lower=True + ), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), + cv.only_on([PLATFORM_ESP8266, PLATFORM_ESP32]), +) + +FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( + "dlms_meter", baud_rate=2400, require_rx=True +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) + key = ", ".join(str(b) for b in config[CONF_DECRYPTION_KEY]) + cg.add(var.set_decryption_key(cg.RawExpression(f"{{{key}}}"))) + cg.add(var.set_provider(PROVIDERS[config[CONF_PROVIDER]])) diff --git a/esphome/components/dlms_meter/dlms.h b/esphome/components/dlms_meter/dlms.h new file mode 100644 index 0000000000..a3d8f62ce6 --- /dev/null +++ b/esphome/components/dlms_meter/dlms.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +namespace esphome::dlms_meter { + +/* ++-------------------------------+ +| Ciphering Service | ++-------------------------------+ +| System Title Length | ++-------------------------------+ +| | +| | +| | +| System | +| Title | +| | +| | +| | ++-------------------------------+ +| Length | (1 or 3 Bytes) ++-------------------------------+ +| Security Control Byte | ++-------------------------------+ +| | +| Frame | +| Counter | +| | ++-------------------------------+ +| | +~ ~ + Encrypted Payload +~ ~ +| | ++-------------------------------+ + +Ciphering Service: 0xDB (General-Glo-Ciphering) +System Title Length: 0x08 +System Title: Unique ID of meter +Length: 1 Byte=Length <= 127, 3 Bytes=Length > 127 (0x82 & 2 Bytes length) +Security Control Byte: +- Bit 3…0: Security_Suite_Id +- Bit 4: "A" subfield: indicates that authentication is applied +- Bit 5: "E" subfield: indicates that encryption is applied +- Bit 6: Key_Set subfield: 0 = Unicast, 1 = Broadcast +- Bit 7: Indicates the use of compression. + */ + +static constexpr uint8_t DLMS_HEADER_LENGTH = 16; +static constexpr uint8_t DLMS_HEADER_EXT_OFFSET = 2; // Extra offset for extended length header +static constexpr uint8_t DLMS_CIPHER_OFFSET = 0; +static constexpr uint8_t DLMS_SYST_OFFSET = 1; +static constexpr uint8_t DLMS_LENGTH_OFFSET = 10; +static constexpr uint8_t TWO_BYTE_LENGTH = 0x82; +static constexpr uint8_t DLMS_LENGTH_CORRECTION = 5; // Header bytes included in length field +static constexpr uint8_t DLMS_SECBYTE_OFFSET = 11; +static constexpr uint8_t DLMS_FRAMECOUNTER_OFFSET = 12; +static constexpr uint8_t DLMS_FRAMECOUNTER_LENGTH = 4; +static constexpr uint8_t DLMS_PAYLOAD_OFFSET = 16; +static constexpr uint8_t GLO_CIPHERING = 0xDB; +static constexpr uint8_t DATA_NOTIFICATION = 0x0F; +static constexpr uint8_t TIMESTAMP_DATETIME = 0x0C; +static constexpr uint16_t MAX_MESSAGE_LENGTH = 512; // Maximum size of message (when having 2 bytes length in header). + +// Provider specific quirks +static constexpr uint8_t NETZ_NOE_MAGIC_BYTE = 0x81; // Magic length byte used by Netz NOE +static constexpr uint8_t NETZ_NOE_EXPECTED_MESSAGE_LENGTH = 0xF8; +static constexpr uint8_t NETZ_NOE_EXPECTED_SECURITY_CONTROL_BYTE = 0x20; + +} // namespace esphome::dlms_meter diff --git a/esphome/components/dlms_meter/dlms_meter.cpp b/esphome/components/dlms_meter/dlms_meter.cpp new file mode 100644 index 0000000000..6aa465143e --- /dev/null +++ b/esphome/components/dlms_meter/dlms_meter.cpp @@ -0,0 +1,468 @@ +#include "dlms_meter.h" + +#include + +#if defined(USE_ESP8266_FRAMEWORK_ARDUINO) +#include +#elif defined(USE_ESP32) +#include "mbedtls/esp_config.h" +#include "mbedtls/gcm.h" +#endif + +namespace esphome::dlms_meter { + +static constexpr const char *TAG = "dlms_meter"; + +void DlmsMeterComponent::dump_config() { + const char *provider_name = this->provider_ == PROVIDER_NETZNOE ? "Netz NOE" : "Generic"; + ESP_LOGCONFIG(TAG, + "DLMS Meter:\n" + " Provider: %s\n" + " Read Timeout: %u ms", + provider_name, this->read_timeout_); +#define DLMS_METER_LOG_SENSOR(s) LOG_SENSOR(" ", #s, this->s##_sensor_); + DLMS_METER_SENSOR_LIST(DLMS_METER_LOG_SENSOR, ) +#define DLMS_METER_LOG_TEXT_SENSOR(s) LOG_TEXT_SENSOR(" ", #s, this->s##_text_sensor_); + DLMS_METER_TEXT_SENSOR_LIST(DLMS_METER_LOG_TEXT_SENSOR, ) +} + +void DlmsMeterComponent::loop() { + // Read while data is available, netznoe uses two frames so allow 2x max frame length + while (this->available()) { + if (this->receive_buffer_.size() >= MBUS_MAX_FRAME_LENGTH * 2) { + ESP_LOGW(TAG, "Receive buffer full, dropping remaining bytes"); + break; + } + uint8_t c; + this->read_byte(&c); + this->receive_buffer_.push_back(c); + this->last_read_ = millis(); + } + + if (!this->receive_buffer_.empty() && millis() - this->last_read_ > this->read_timeout_) { + this->mbus_payload_.clear(); + if (!this->parse_mbus_(this->mbus_payload_)) + return; + + uint16_t message_length; + uint8_t systitle_length; + uint16_t header_offset; + if (!this->parse_dlms_(this->mbus_payload_, message_length, systitle_length, header_offset)) + return; + + if (message_length < DECODER_START_OFFSET || message_length > MAX_MESSAGE_LENGTH) { + ESP_LOGE(TAG, "DLMS: Message length invalid: %u", message_length); + this->receive_buffer_.clear(); + return; + } + + // Decrypt in place and then decode the OBIS codes + if (!this->decrypt_(this->mbus_payload_, message_length, systitle_length, header_offset)) + return; + this->decode_obis_(&this->mbus_payload_[header_offset + DLMS_PAYLOAD_OFFSET], message_length); + } +} + +bool DlmsMeterComponent::parse_mbus_(std::vector &mbus_payload) { + ESP_LOGV(TAG, "Parsing M-Bus frames"); + uint16_t frame_offset = 0; // Offset is used if the M-Bus message is split into multiple frames + + while (frame_offset < this->receive_buffer_.size()) { + // Ensure enough bytes remain for the minimal intro header before accessing indices + if (this->receive_buffer_.size() - frame_offset < MBUS_HEADER_INTRO_LENGTH) { + ESP_LOGE(TAG, "MBUS: Not enough data for frame header (need %d, have %d)", MBUS_HEADER_INTRO_LENGTH, + (this->receive_buffer_.size() - frame_offset)); + this->receive_buffer_.clear(); + return false; + } + + // Check start bytes + if (this->receive_buffer_[frame_offset + MBUS_START1_OFFSET] != START_BYTE_LONG_FRAME || + this->receive_buffer_[frame_offset + MBUS_START2_OFFSET] != START_BYTE_LONG_FRAME) { + ESP_LOGE(TAG, "MBUS: Start bytes do not match"); + this->receive_buffer_.clear(); + return false; + } + + // Both length bytes must be identical + if (this->receive_buffer_[frame_offset + MBUS_LENGTH1_OFFSET] != + this->receive_buffer_[frame_offset + MBUS_LENGTH2_OFFSET]) { + ESP_LOGE(TAG, "MBUS: Length bytes do not match"); + this->receive_buffer_.clear(); + return false; + } + + uint8_t frame_length = this->receive_buffer_[frame_offset + MBUS_LENGTH1_OFFSET]; // Get length of this frame + + // Check if received data is enough for the given frame length + if (this->receive_buffer_.size() - frame_offset < + frame_length + 3) { // length field inside packet does not account for second start- + checksum- + stop- byte + ESP_LOGE(TAG, "MBUS: Frame too big for received data"); + this->receive_buffer_.clear(); + return false; + } + + // Ensure we have full frame (header + payload + checksum + stop byte) before accessing stop byte + size_t required_total = + frame_length + MBUS_HEADER_INTRO_LENGTH + MBUS_FOOTER_LENGTH; // payload + header + 2 footer bytes + if (this->receive_buffer_.size() - frame_offset < required_total) { + ESP_LOGE(TAG, "MBUS: Incomplete frame (need %d, have %d)", (unsigned int) required_total, + this->receive_buffer_.size() - frame_offset); + this->receive_buffer_.clear(); + return false; + } + + if (this->receive_buffer_[frame_offset + frame_length + MBUS_HEADER_INTRO_LENGTH + MBUS_FOOTER_LENGTH - 1] != + STOP_BYTE) { + ESP_LOGE(TAG, "MBUS: Invalid stop byte"); + this->receive_buffer_.clear(); + return false; + } + + // Verify checksum: sum of all bytes starting at MBUS_HEADER_INTRO_LENGTH, take last byte + uint8_t checksum = 0; // use uint8_t so only the 8 least significant bits are stored + for (uint16_t i = 0; i < frame_length; i++) { + checksum += this->receive_buffer_[frame_offset + MBUS_HEADER_INTRO_LENGTH + i]; + } + if (checksum != this->receive_buffer_[frame_offset + frame_length + MBUS_HEADER_INTRO_LENGTH]) { + ESP_LOGE(TAG, "MBUS: Invalid checksum: %x != %x", checksum, + this->receive_buffer_[frame_offset + frame_length + MBUS_HEADER_INTRO_LENGTH]); + this->receive_buffer_.clear(); + return false; + } + + mbus_payload.insert(mbus_payload.end(), &this->receive_buffer_[frame_offset + MBUS_FULL_HEADER_LENGTH], + &this->receive_buffer_[frame_offset + MBUS_HEADER_INTRO_LENGTH + frame_length]); + + frame_offset += MBUS_HEADER_INTRO_LENGTH + frame_length + MBUS_FOOTER_LENGTH; + } + return true; +} + +bool DlmsMeterComponent::parse_dlms_(const std::vector &mbus_payload, uint16_t &message_length, + uint8_t &systitle_length, uint16_t &header_offset) { + ESP_LOGV(TAG, "Parsing DLMS header"); + if (mbus_payload.size() < DLMS_HEADER_LENGTH + DLMS_HEADER_EXT_OFFSET) { + ESP_LOGE(TAG, "DLMS: Payload too short"); + this->receive_buffer_.clear(); + return false; + } + + if (mbus_payload[DLMS_CIPHER_OFFSET] != GLO_CIPHERING) { // Only general-glo-ciphering is supported (0xDB) + ESP_LOGE(TAG, "DLMS: Unsupported cipher"); + this->receive_buffer_.clear(); + return false; + } + + systitle_length = mbus_payload[DLMS_SYST_OFFSET]; + + if (systitle_length != 0x08) { // Only system titles with length of 8 are supported + ESP_LOGE(TAG, "DLMS: Unsupported system title length"); + this->receive_buffer_.clear(); + return false; + } + + message_length = mbus_payload[DLMS_LENGTH_OFFSET]; + header_offset = 0; + + if (this->provider_ == PROVIDER_NETZNOE) { + // for some reason EVN seems to set the standard "length" field to 0x81 and then the actual length is in the next + // byte. Check some bytes to see if received data still matches expectation + if (message_length == NETZ_NOE_MAGIC_BYTE && + mbus_payload[DLMS_LENGTH_OFFSET + 1] == NETZ_NOE_EXPECTED_MESSAGE_LENGTH && + mbus_payload[DLMS_LENGTH_OFFSET + 2] == NETZ_NOE_EXPECTED_SECURITY_CONTROL_BYTE) { + message_length = mbus_payload[DLMS_LENGTH_OFFSET + 1]; + header_offset = 1; + } else { + ESP_LOGE(TAG, "Wrong Length - Security Control Byte sequence detected for provider EVN"); + } + } else { + if (message_length == TWO_BYTE_LENGTH) { + message_length = encode_uint16(mbus_payload[DLMS_LENGTH_OFFSET + 1], mbus_payload[DLMS_LENGTH_OFFSET + 2]); + header_offset = DLMS_HEADER_EXT_OFFSET; + } + } + if (message_length < DLMS_LENGTH_CORRECTION) { + ESP_LOGE(TAG, "DLMS: Message length too short: %u", message_length); + this->receive_buffer_.clear(); + return false; + } + message_length -= DLMS_LENGTH_CORRECTION; // Correct message length due to part of header being included in length + + if (mbus_payload.size() - DLMS_HEADER_LENGTH - header_offset != message_length) { + ESP_LOGV(TAG, "DLMS: Length mismatch - payload=%d, header=%d, offset=%d, message=%d", mbus_payload.size(), + DLMS_HEADER_LENGTH, header_offset, message_length); + ESP_LOGE(TAG, "DLMS: Message has invalid length"); + this->receive_buffer_.clear(); + return false; + } + + if (mbus_payload[header_offset + DLMS_SECBYTE_OFFSET] != 0x21 && + mbus_payload[header_offset + DLMS_SECBYTE_OFFSET] != + 0x20) { // Only certain security suite is supported (0x21 || 0x20) + ESP_LOGE(TAG, "DLMS: Unsupported security control byte"); + this->receive_buffer_.clear(); + return false; + } + + return true; +} + +bool DlmsMeterComponent::decrypt_(std::vector &mbus_payload, uint16_t message_length, uint8_t systitle_length, + uint16_t header_offset) { + ESP_LOGV(TAG, "Decrypting payload"); + uint8_t iv[12]; // Reserve space for the IV, always 12 bytes + // Copy system title to IV (System title is before length; no header offset needed!) + // Add 1 to the offset in order to skip the system title length byte + memcpy(&iv[0], &mbus_payload[DLMS_SYST_OFFSET + 1], systitle_length); + memcpy(&iv[8], &mbus_payload[header_offset + DLMS_FRAMECOUNTER_OFFSET], + DLMS_FRAMECOUNTER_LENGTH); // Copy frame counter to IV + + uint8_t *payload_ptr = &mbus_payload[header_offset + DLMS_PAYLOAD_OFFSET]; + +#if defined(USE_ESP8266_FRAMEWORK_ARDUINO) + br_gcm_context gcm_ctx; + br_aes_ct_ctr_keys bc; + br_aes_ct_ctr_init(&bc, this->decryption_key_.data(), this->decryption_key_.size()); + br_gcm_init(&gcm_ctx, &bc.vtable, br_ghash_ctmul32); + br_gcm_reset(&gcm_ctx, iv, sizeof(iv)); + br_gcm_flip(&gcm_ctx); + br_gcm_run(&gcm_ctx, 0, payload_ptr, message_length); +#elif defined(USE_ESP32) + size_t outlen = 0; + mbedtls_gcm_context gcm_ctx; + mbedtls_gcm_init(&gcm_ctx); + mbedtls_gcm_setkey(&gcm_ctx, MBEDTLS_CIPHER_ID_AES, this->decryption_key_.data(), this->decryption_key_.size() * 8); + mbedtls_gcm_starts(&gcm_ctx, MBEDTLS_GCM_DECRYPT, iv, sizeof(iv)); + auto ret = mbedtls_gcm_update(&gcm_ctx, payload_ptr, message_length, payload_ptr, message_length, &outlen); + mbedtls_gcm_free(&gcm_ctx); + if (ret != 0) { + ESP_LOGE(TAG, "Decryption failed with error: %d", ret); + this->receive_buffer_.clear(); + return false; + } +#else +#error "Invalid Platform" +#endif + + if (payload_ptr[0] != DATA_NOTIFICATION || payload_ptr[5] != TIMESTAMP_DATETIME) { + ESP_LOGE(TAG, "OBIS: Packet was decrypted but data is invalid"); + this->receive_buffer_.clear(); + return false; + } + ESP_LOGV(TAG, "Decrypted payload: %d bytes", message_length); + return true; +} + +void DlmsMeterComponent::decode_obis_(uint8_t *plaintext, uint16_t message_length) { + ESP_LOGV(TAG, "Decoding payload"); + MeterData data{}; + uint16_t current_position = DECODER_START_OFFSET; + bool power_factor_found = false; + + while (current_position + OBIS_CODE_OFFSET <= message_length) { + if (plaintext[current_position + OBIS_TYPE_OFFSET] != DataType::OCTET_STRING) { + ESP_LOGE(TAG, "OBIS: Unsupported OBIS header type: %x", plaintext[current_position + OBIS_TYPE_OFFSET]); + this->receive_buffer_.clear(); + return; + } + + uint8_t obis_code_length = plaintext[current_position + OBIS_LENGTH_OFFSET]; + if (obis_code_length != OBIS_CODE_LENGTH_STANDARD && obis_code_length != OBIS_CODE_LENGTH_EXTENDED) { + ESP_LOGE(TAG, "OBIS: Unsupported OBIS header length: %x", obis_code_length); + this->receive_buffer_.clear(); + return; + } + if (current_position + OBIS_CODE_OFFSET + obis_code_length > message_length) { + ESP_LOGE(TAG, "OBIS: Buffer too short for OBIS code"); + this->receive_buffer_.clear(); + return; + } + + uint8_t *obis_code = &plaintext[current_position + OBIS_CODE_OFFSET]; + uint8_t obis_medium = obis_code[OBIS_A]; + uint16_t obis_cd = encode_uint16(obis_code[OBIS_C], obis_code[OBIS_D]); + + bool timestamp_found = false; + bool meter_number_found = false; + if (this->provider_ == PROVIDER_NETZNOE) { + // Do not advance Position when reading the Timestamp at DECODER_START_OFFSET + if ((obis_code_length == OBIS_CODE_LENGTH_EXTENDED) && (current_position == DECODER_START_OFFSET)) { + timestamp_found = true; + } else if (power_factor_found) { + meter_number_found = true; + power_factor_found = false; + } else { + current_position += obis_code_length + OBIS_CODE_OFFSET; // Advance past code and position + } + } else { + current_position += obis_code_length + OBIS_CODE_OFFSET; // Advance past code, position and type + } + if (!timestamp_found && !meter_number_found && obis_medium != Medium::ELECTRICITY && + obis_medium != Medium::ABSTRACT) { + ESP_LOGE(TAG, "OBIS: Unsupported OBIS medium: %x", obis_medium); + this->receive_buffer_.clear(); + return; + } + + if (current_position >= message_length) { + ESP_LOGE(TAG, "OBIS: Buffer too short for data type"); + this->receive_buffer_.clear(); + return; + } + + float value = 0.0f; + uint8_t value_size = 0; + uint8_t data_type = plaintext[current_position]; + current_position++; + + switch (data_type) { + case DataType::DOUBLE_LONG_UNSIGNED: { + value_size = 4; + if (current_position + value_size > message_length) { + ESP_LOGE(TAG, "OBIS: Buffer too short for DOUBLE_LONG_UNSIGNED"); + this->receive_buffer_.clear(); + return; + } + value = encode_uint32(plaintext[current_position + 0], plaintext[current_position + 1], + plaintext[current_position + 2], plaintext[current_position + 3]); + current_position += value_size; + break; + } + case DataType::LONG_UNSIGNED: { + value_size = 2; + if (current_position + value_size > message_length) { + ESP_LOGE(TAG, "OBIS: Buffer too short for LONG_UNSIGNED"); + this->receive_buffer_.clear(); + return; + } + value = encode_uint16(plaintext[current_position + 0], plaintext[current_position + 1]); + current_position += value_size; + break; + } + case DataType::OCTET_STRING: { + uint8_t data_length = plaintext[current_position]; + current_position++; // Advance past string length + if (current_position + data_length > message_length) { + ESP_LOGE(TAG, "OBIS: Buffer too short for OCTET_STRING"); + this->receive_buffer_.clear(); + return; + } + // Handle timestamp (normal OBIS code or NETZNOE special case) + if (obis_cd == OBIS_TIMESTAMP || timestamp_found) { + if (data_length < 8) { + ESP_LOGE(TAG, "OBIS: Timestamp data too short: %u", data_length); + this->receive_buffer_.clear(); + return; + } + uint16_t year = encode_uint16(plaintext[current_position + 0], plaintext[current_position + 1]); + uint8_t month = plaintext[current_position + 2]; + uint8_t day = plaintext[current_position + 3]; + uint8_t hour = plaintext[current_position + 5]; + uint8_t minute = plaintext[current_position + 6]; + uint8_t second = plaintext[current_position + 7]; + if (year > 9999 || month > 12 || day > 31 || hour > 23 || minute > 59 || second > 59) { + ESP_LOGE(TAG, "Invalid timestamp values: %04u-%02u-%02uT%02u:%02u:%02uZ", year, month, day, hour, minute, + second); + this->receive_buffer_.clear(); + return; + } + snprintf(data.timestamp, sizeof(data.timestamp), "%04u-%02u-%02uT%02u:%02u:%02uZ", year, month, day, hour, + minute, second); + } else if (meter_number_found) { + snprintf(data.meternumber, sizeof(data.meternumber), "%.*s", data_length, &plaintext[current_position]); + } + current_position += data_length; + break; + } + default: + ESP_LOGE(TAG, "OBIS: Unsupported OBIS data type: %x", data_type); + this->receive_buffer_.clear(); + return; + } + + // Skip break after data + if (this->provider_ == PROVIDER_NETZNOE) { + // Don't skip the break on the first timestamp, as there's none + if (!timestamp_found) { + current_position += 2; + } + } else { + current_position += 2; + } + + // Check for additional data (scaler-unit structure) + if (current_position < message_length && plaintext[current_position] == DataType::INTEGER) { + // Apply scaler: real_value = raw_value × 10^scaler + if (current_position + 1 < message_length) { + int8_t scaler = static_cast(plaintext[current_position + 1]); + if (scaler != 0) { + value *= powf(10.0f, scaler); + } + } + + // on EVN Meters there is no additional break + if (this->provider_ == PROVIDER_NETZNOE) { + current_position += 4; + } else { + current_position += 6; + } + } + + // Handle numeric values (LONG_UNSIGNED and DOUBLE_LONG_UNSIGNED) + if (value_size > 0) { + switch (obis_cd) { + case OBIS_VOLTAGE_L1: + data.voltage_l1 = value; + break; + case OBIS_VOLTAGE_L2: + data.voltage_l2 = value; + break; + case OBIS_VOLTAGE_L3: + data.voltage_l3 = value; + break; + case OBIS_CURRENT_L1: + data.current_l1 = value; + break; + case OBIS_CURRENT_L2: + data.current_l2 = value; + break; + case OBIS_CURRENT_L3: + data.current_l3 = value; + break; + case OBIS_ACTIVE_POWER_PLUS: + data.active_power_plus = value; + break; + case OBIS_ACTIVE_POWER_MINUS: + data.active_power_minus = value; + break; + case OBIS_ACTIVE_ENERGY_PLUS: + data.active_energy_plus = value; + break; + case OBIS_ACTIVE_ENERGY_MINUS: + data.active_energy_minus = value; + break; + case OBIS_REACTIVE_ENERGY_PLUS: + data.reactive_energy_plus = value; + break; + case OBIS_REACTIVE_ENERGY_MINUS: + data.reactive_energy_minus = value; + break; + case OBIS_POWER_FACTOR: + data.power_factor = value; + power_factor_found = true; + break; + default: + ESP_LOGW(TAG, "Unsupported OBIS code 0x%04X", obis_cd); + } + } + } + + this->receive_buffer_.clear(); + + ESP_LOGI(TAG, "Received valid data"); + this->publish_sensors(data); + this->status_clear_warning(); +} + +} // namespace esphome::dlms_meter diff --git a/esphome/components/dlms_meter/dlms_meter.h b/esphome/components/dlms_meter/dlms_meter.h new file mode 100644 index 0000000000..c50e6f6b4d --- /dev/null +++ b/esphome/components/dlms_meter/dlms_meter.h @@ -0,0 +1,96 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/log.h" +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif +#ifdef USE_TEXT_SENSOR +#include "esphome/components/text_sensor/text_sensor.h" +#endif +#include "esphome/components/uart/uart.h" + +#include "mbus.h" +#include "dlms.h" +#include "obis.h" + +#include +#include + +namespace esphome::dlms_meter { + +#ifndef DLMS_METER_SENSOR_LIST +#define DLMS_METER_SENSOR_LIST(F, SEP) +#endif + +#ifndef DLMS_METER_TEXT_SENSOR_LIST +#define DLMS_METER_TEXT_SENSOR_LIST(F, SEP) +#endif + +struct MeterData { + float voltage_l1 = 0.0f; // Voltage L1 + float voltage_l2 = 0.0f; // Voltage L2 + float voltage_l3 = 0.0f; // Voltage L3 + float current_l1 = 0.0f; // Current L1 + float current_l2 = 0.0f; // Current L2 + float current_l3 = 0.0f; // Current L3 + float active_power_plus = 0.0f; // Active power taken from grid + float active_power_minus = 0.0f; // Active power put into grid + float active_energy_plus = 0.0f; // Active energy taken from grid + float active_energy_minus = 0.0f; // Active energy put into grid + float reactive_energy_plus = 0.0f; // Reactive energy taken from grid + float reactive_energy_minus = 0.0f; // Reactive energy put into grid + char timestamp[27]{}; // Text sensor for the timestamp value + + // Netz NOE + float power_factor = 0.0f; // Power Factor + char meternumber[13]{}; // Text sensor for the meterNumber value +}; + +// Provider constants +enum Providers : uint32_t { PROVIDER_GENERIC = 0x00, PROVIDER_NETZNOE = 0x01 }; + +class DlmsMeterComponent : public Component, public uart::UARTDevice { + public: + DlmsMeterComponent() = default; + + void dump_config() override; + void loop() override; + + void set_decryption_key(const std::array &key) { this->decryption_key_ = key; } + void set_provider(uint32_t provider) { this->provider_ = provider; } + + void publish_sensors(MeterData &data) { +#define DLMS_METER_PUBLISH_SENSOR(s) \ + if (this->s##_sensor_ != nullptr) \ + s##_sensor_->publish_state(data.s); + DLMS_METER_SENSOR_LIST(DLMS_METER_PUBLISH_SENSOR, ) + +#define DLMS_METER_PUBLISH_TEXT_SENSOR(s) \ + if (this->s##_text_sensor_ != nullptr) \ + s##_text_sensor_->publish_state(data.s); + DLMS_METER_TEXT_SENSOR_LIST(DLMS_METER_PUBLISH_TEXT_SENSOR, ) + } + + DLMS_METER_SENSOR_LIST(SUB_SENSOR, ) + DLMS_METER_TEXT_SENSOR_LIST(SUB_TEXT_SENSOR, ) + + protected: + bool parse_mbus_(std::vector &mbus_payload); + bool parse_dlms_(const std::vector &mbus_payload, uint16_t &message_length, uint8_t &systitle_length, + uint16_t &header_offset); + bool decrypt_(std::vector &mbus_payload, uint16_t message_length, uint8_t systitle_length, + uint16_t header_offset); + void decode_obis_(uint8_t *plaintext, uint16_t message_length); + + std::vector receive_buffer_; // Stores the packet currently being received + std::vector mbus_payload_; // Parsed M-Bus payload, reused to avoid heap churn + uint32_t last_read_ = 0; // Timestamp when data was last read + uint32_t read_timeout_ = 1000; // Time to wait after last byte before considering data complete + + uint32_t provider_ = PROVIDER_GENERIC; // Provider of the meter / your grid operator + std::array decryption_key_; +}; + +} // namespace esphome::dlms_meter diff --git a/esphome/components/dlms_meter/mbus.h b/esphome/components/dlms_meter/mbus.h new file mode 100644 index 0000000000..293d43a55b --- /dev/null +++ b/esphome/components/dlms_meter/mbus.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +namespace esphome::dlms_meter { + +/* ++----------------------------------------------------+ - +| Start Character [0x68] | \ ++----------------------------------------------------+ | +| Data Length (L) | | ++----------------------------------------------------+ | +| Data Length Repeat (L) | | ++----------------------------------------------------+ > M-Bus Data link layer +| Start Character Repeat [0x68] | | ++----------------------------------------------------+ | +| Control/Function Field (C) | | ++----------------------------------------------------+ | +| Address Field (A) | / ++----------------------------------------------------+ - +| Control Information Field (CI) | \ ++----------------------------------------------------+ | +| Source Transport Service Access Point (STSAP) | > DLMS/COSEM M-Bus transport layer ++----------------------------------------------------+ | +| Destination Transport Service Access Point (DTSAP) | / ++----------------------------------------------------+ - +| | \ +~ ~ | + Data > DLMS/COSEM Application Layer +~ ~ | +| | / ++----------------------------------------------------+ - +| Checksum | \ ++----------------------------------------------------+ > M-Bus Data link layer +| Stop Character [0x16] | / ++----------------------------------------------------+ - + +Data_Length = L - C - A - CI +Each line (except Data) is one Byte + +Possible Values found in publicly available docs: +- C: 0x53/0x73 (SND_UD) +- A: FF (Broadcast) +- CI: 0x00-0x1F/0x60/0x61/0x7C/0x7D +- STSAP: 0x01 (Management Logical Device ID 1 of the meter) +- DTSAP: 0x67 (Consumer Information Push Client ID 103) + */ + +// MBUS start bytes for different telegram formats: +// - Single Character: 0xE5 (length=1) +// - Short Frame: 0x10 (length=5) +// - Control Frame: 0x68 (length=9) +// - Long Frame: 0x68 (length=9+data_length) +// This component currently only uses Long Frame. +static constexpr uint8_t START_BYTE_SINGLE_CHARACTER = 0xE5; +static constexpr uint8_t START_BYTE_SHORT_FRAME = 0x10; +static constexpr uint8_t START_BYTE_CONTROL_FRAME = 0x68; +static constexpr uint8_t START_BYTE_LONG_FRAME = 0x68; +static constexpr uint8_t MBUS_HEADER_INTRO_LENGTH = 4; // Header length for the intro (0x68, length, length, 0x68) +static constexpr uint8_t MBUS_FULL_HEADER_LENGTH = 9; // Total header length +static constexpr uint8_t MBUS_FOOTER_LENGTH = 2; // Footer after frame +static constexpr uint8_t MBUS_MAX_FRAME_LENGTH = 250; // Maximum size of frame +static constexpr uint8_t MBUS_START1_OFFSET = 0; // Offset of first start byte +static constexpr uint8_t MBUS_LENGTH1_OFFSET = 1; // Offset of first length byte +static constexpr uint8_t MBUS_LENGTH2_OFFSET = 2; // Offset of (duplicated) second length byte +static constexpr uint8_t MBUS_START2_OFFSET = 3; // Offset of (duplicated) second start byte +static constexpr uint8_t STOP_BYTE = 0x16; + +} // namespace esphome::dlms_meter diff --git a/esphome/components/dlms_meter/obis.h b/esphome/components/dlms_meter/obis.h new file mode 100644 index 0000000000..1bb960e61e --- /dev/null +++ b/esphome/components/dlms_meter/obis.h @@ -0,0 +1,94 @@ +#pragma once + +#include + +namespace esphome::dlms_meter { + +// Data types as per specification +enum DataType { + NULL_DATA = 0x00, + BOOLEAN = 0x03, + BIT_STRING = 0x04, + DOUBLE_LONG = 0x05, + DOUBLE_LONG_UNSIGNED = 0x06, + OCTET_STRING = 0x09, + VISIBLE_STRING = 0x0A, + UTF8_STRING = 0x0C, + BINARY_CODED_DECIMAL = 0x0D, + INTEGER = 0x0F, + LONG = 0x10, + UNSIGNED = 0x11, + LONG_UNSIGNED = 0x12, + LONG64 = 0x14, + LONG64_UNSIGNED = 0x15, + ENUM = 0x16, + FLOAT32 = 0x17, + FLOAT64 = 0x18, + DATE_TIME = 0x19, + DATE = 0x1A, + TIME = 0x1B, + + ARRAY = 0x01, + STRUCTURE = 0x02, + COMPACT_ARRAY = 0x13 +}; + +enum Medium { + ABSTRACT = 0x00, + ELECTRICITY = 0x01, + HEAT_COST_ALLOCATOR = 0x04, + COOLING = 0x05, + HEAT = 0x06, + GAS = 0x07, + COLD_WATER = 0x08, + HOT_WATER = 0x09, + OIL = 0x10, + COMPRESSED_AIR = 0x11, + NITROGEN = 0x12 +}; + +// Data structure +static constexpr uint8_t DECODER_START_OFFSET = 20; // Skip header, timestamp and break block +static constexpr uint8_t OBIS_TYPE_OFFSET = 0; +static constexpr uint8_t OBIS_LENGTH_OFFSET = 1; +static constexpr uint8_t OBIS_CODE_OFFSET = 2; +static constexpr uint8_t OBIS_CODE_LENGTH_STANDARD = 0x06; // 6-byte OBIS code (A.B.C.D.E.F) +static constexpr uint8_t OBIS_CODE_LENGTH_EXTENDED = 0x0C; // 12-byte extended OBIS code +static constexpr uint8_t OBIS_A = 0; +static constexpr uint8_t OBIS_B = 1; +static constexpr uint8_t OBIS_C = 2; +static constexpr uint8_t OBIS_D = 3; +static constexpr uint8_t OBIS_E = 4; +static constexpr uint8_t OBIS_F = 5; + +// Metadata +static constexpr uint16_t OBIS_TIMESTAMP = 0x0100; +static constexpr uint16_t OBIS_SERIAL_NUMBER = 0x6001; +static constexpr uint16_t OBIS_DEVICE_NAME = 0x2A00; + +// Voltage +static constexpr uint16_t OBIS_VOLTAGE_L1 = 0x2007; +static constexpr uint16_t OBIS_VOLTAGE_L2 = 0x3407; +static constexpr uint16_t OBIS_VOLTAGE_L3 = 0x4807; + +// Current +static constexpr uint16_t OBIS_CURRENT_L1 = 0x1F07; +static constexpr uint16_t OBIS_CURRENT_L2 = 0x3307; +static constexpr uint16_t OBIS_CURRENT_L3 = 0x4707; + +// Power +static constexpr uint16_t OBIS_ACTIVE_POWER_PLUS = 0x0107; +static constexpr uint16_t OBIS_ACTIVE_POWER_MINUS = 0x0207; + +// Active energy +static constexpr uint16_t OBIS_ACTIVE_ENERGY_PLUS = 0x0108; +static constexpr uint16_t OBIS_ACTIVE_ENERGY_MINUS = 0x0208; + +// Reactive energy +static constexpr uint16_t OBIS_REACTIVE_ENERGY_PLUS = 0x0308; +static constexpr uint16_t OBIS_REACTIVE_ENERGY_MINUS = 0x0408; + +// Netz NOE specific +static constexpr uint16_t OBIS_POWER_FACTOR = 0x0D07; + +} // namespace esphome::dlms_meter diff --git a/esphome/components/dlms_meter/sensor/__init__.py b/esphome/components/dlms_meter/sensor/__init__.py new file mode 100644 index 0000000000..27fd44f008 --- /dev/null +++ b/esphome/components/dlms_meter/sensor/__init__.py @@ -0,0 +1,124 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + UNIT_AMPERE, + UNIT_VOLT, + UNIT_WATT, + UNIT_WATT_HOURS, +) + +from .. import CONF_DLMS_METER_ID, DlmsMeterComponent + +AUTO_LOAD = ["dlms_meter"] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_DLMS_METER_ID): cv.use_id(DlmsMeterComponent), + cv.Optional("voltage_l1"): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("voltage_l2"): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("voltage_l3"): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("current_l1"): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("current_l2"): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("current_l3"): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("active_power_plus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("active_power_minus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional("active_energy_plus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional("active_energy_minus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional("reactive_energy_plus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional("reactive_energy_minus"): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + # Netz NOE + cv.Optional("power_factor"): sensor.sensor_schema( + accuracy_decimals=3, + device_class=DEVICE_CLASS_POWER_FACTOR, + state_class=STATE_CLASS_MEASUREMENT, + ), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_DLMS_METER_ID]) + + sensors = [] + for key, conf in config.items(): + if not isinstance(conf, dict): + continue + id = conf[CONF_ID] + if id and id.type == sensor.Sensor: + sens = await sensor.new_sensor(conf) + cg.add(getattr(hub, f"set_{key}_sensor")(sens)) + sensors.append(f"F({key})") + + if sensors: + cg.add_define( + "DLMS_METER_SENSOR_LIST(F, sep)", cg.RawExpression(" sep ".join(sensors)) + ) diff --git a/esphome/components/dlms_meter/text_sensor/__init__.py b/esphome/components/dlms_meter/text_sensor/__init__.py new file mode 100644 index 0000000000..4d2373f4f9 --- /dev/null +++ b/esphome/components/dlms_meter/text_sensor/__init__.py @@ -0,0 +1,37 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import CONF_ID + +from .. import CONF_DLMS_METER_ID, DlmsMeterComponent + +AUTO_LOAD = ["dlms_meter"] + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_DLMS_METER_ID): cv.use_id(DlmsMeterComponent), + cv.Optional("timestamp"): text_sensor.text_sensor_schema(), + # Netz NOE + cv.Optional("meternumber"): text_sensor.text_sensor_schema(), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + hub = await cg.get_variable(config[CONF_DLMS_METER_ID]) + + text_sensors = [] + for key, conf in config.items(): + if not isinstance(conf, dict): + continue + id = conf[CONF_ID] + if id and id.type == text_sensor.TextSensor: + sens = await text_sensor.new_text_sensor(conf) + cg.add(getattr(hub, f"set_{key}_text_sensor")(sens)) + text_sensors.append(f"F({key})") + + if text_sensors: + cg.add_define( + "DLMS_METER_TEXT_SENSOR_LIST(F, sep)", + cg.RawExpression(" sep ".join(text_sensors)), + ) diff --git a/tests/components/dlms_meter/common-generic.yaml b/tests/components/dlms_meter/common-generic.yaml new file mode 100644 index 0000000000..edb1c66f0f --- /dev/null +++ b/tests/components/dlms_meter/common-generic.yaml @@ -0,0 +1,11 @@ +dlms_meter: + decryption_key: "36C66639E48A8CA4D6BC8B282A793BBB" # change this to your decryption key! + +sensor: + - platform: dlms_meter + reactive_energy_plus: + name: "Reactive energy taken from grid" + reactive_energy_minus: + name: "Reactive energy put into grid" + +<<: !include common.yaml diff --git a/tests/components/dlms_meter/common-netznoe.yaml b/tests/components/dlms_meter/common-netznoe.yaml new file mode 100644 index 0000000000..db064b64f9 --- /dev/null +++ b/tests/components/dlms_meter/common-netznoe.yaml @@ -0,0 +1,17 @@ +dlms_meter: + decryption_key: "36C66639E48A8CA4D6BC8B282A793BBB" # change this to your decryption key! + provider: netznoe # (optional) key - only set if using evn + +sensor: + - platform: dlms_meter + # EVN + power_factor: + name: "Power Factor" + +text_sensor: + - platform: dlms_meter + # EVN + meternumber: + name: "meterNumber" + +<<: !include common.yaml diff --git a/tests/components/dlms_meter/common.yaml b/tests/components/dlms_meter/common.yaml new file mode 100644 index 0000000000..6aa4e1b0ff --- /dev/null +++ b/tests/components/dlms_meter/common.yaml @@ -0,0 +1,27 @@ +sensor: + - platform: dlms_meter + voltage_l1: + name: "Voltage L1" + voltage_l2: + name: "Voltage L2" + voltage_l3: + name: "Voltage L3" + current_l1: + name: "Current L1" + current_l2: + name: "Current L2" + current_l3: + name: "Current L3" + active_power_plus: + name: "Active power taken from grid" + active_power_minus: + name: "Active power put into grid" + active_energy_plus: + name: "Active energy taken from grid" + active_energy_minus: + name: "Active energy put into grid" + +text_sensor: + - platform: dlms_meter + timestamp: + name: "timestamp" diff --git a/tests/components/dlms_meter/test.esp32-ard.yaml b/tests/components/dlms_meter/test.esp32-ard.yaml new file mode 100644 index 0000000000..4f8a06c31b --- /dev/null +++ b/tests/components/dlms_meter/test.esp32-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_2400/esp32-ard.yaml + +<<: !include common-generic.yaml diff --git a/tests/components/dlms_meter/test.esp32-idf.yaml b/tests/components/dlms_meter/test.esp32-idf.yaml new file mode 100644 index 0000000000..f993515fce --- /dev/null +++ b/tests/components/dlms_meter/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_2400/esp32-idf.yaml + +<<: !include common-netznoe.yaml diff --git a/tests/components/dlms_meter/test.esp8266-ard.yaml b/tests/components/dlms_meter/test.esp8266-ard.yaml new file mode 100644 index 0000000000..2ce7955c9f --- /dev/null +++ b/tests/components/dlms_meter/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_2400/esp8266-ard.yaml + +<<: !include common-generic.yaml diff --git a/tests/test_build_components/common/uart_2400/esp32-ard.yaml b/tests/test_build_components/common/uart_2400/esp32-ard.yaml new file mode 100644 index 0000000000..e0b6571104 --- /dev/null +++ b/tests/test_build_components/common/uart_2400/esp32-ard.yaml @@ -0,0 +1,11 @@ +# Common UART configuration for ESP32 Arduino tests - 2400 baud + +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 + +uart: + - id: uart_bus + tx_pin: ${tx_pin} + rx_pin: ${rx_pin} + baud_rate: 2400 diff --git a/tests/test_build_components/common/uart_2400/esp32-idf.yaml b/tests/test_build_components/common/uart_2400/esp32-idf.yaml new file mode 100644 index 0000000000..7bded8c91d --- /dev/null +++ b/tests/test_build_components/common/uart_2400/esp32-idf.yaml @@ -0,0 +1,11 @@ +# Common UART configuration for ESP32 IDF tests - 2400 baud + +substitutions: + tx_pin: GPIO17 + rx_pin: GPIO16 + +uart: + - id: uart_bus + tx_pin: ${tx_pin} + rx_pin: ${rx_pin} + baud_rate: 2400 diff --git a/tests/test_build_components/common/uart_2400/esp8266-ard.yaml b/tests/test_build_components/common/uart_2400/esp8266-ard.yaml new file mode 100644 index 0000000000..6c9a4a558d --- /dev/null +++ b/tests/test_build_components/common/uart_2400/esp8266-ard.yaml @@ -0,0 +1,11 @@ +# Common UART configuration for ESP8266 Arduino tests - 2400 baud + +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +uart: + - id: uart_bus + tx_pin: ${tx_pin} + rx_pin: ${rx_pin} + baud_rate: 2400 From 29f8d70b35d16cb8296d1a0496e4b4ce0679008f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:41:08 +0100 Subject: [PATCH 0442/2030] [thermostat] Avoid heap allocation for triggers (#13692) --- .../thermostat/thermostat_climate.cpp | 220 +++++++----------- .../thermostat/thermostat_climate.h | 212 +++++++---------- 2 files changed, 170 insertions(+), 262 deletions(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 44087969b5..02e01db549 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -499,7 +499,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } bool action_ready = false; - Trigger<> *trig = this->idle_action_trigger_, *trig_fan = nullptr; + Trigger<> *trig = &this->idle_action_trigger_, *trig_fan = nullptr; switch (action) { case climate::CLIMATE_ACTION_OFF: case climate::CLIMATE_ACTION_IDLE: @@ -529,10 +529,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); if (this->supports_fan_with_cooling_) { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig_fan = this->fan_only_action_trigger_; + trig_fan = &this->fan_only_action_trigger_; } this->cooling_max_runtime_exceeded_ = false; - trig = this->cool_action_trigger_; + trig = &this->cool_action_trigger_; ESP_LOGVV(TAG, "Switching to COOLING action"); action_ready = true; } @@ -543,10 +543,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); if (this->supports_fan_with_heating_) { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig_fan = this->fan_only_action_trigger_; + trig_fan = &this->fan_only_action_trigger_; } this->heating_max_runtime_exceeded_ = false; - trig = this->heat_action_trigger_; + trig = &this->heat_action_trigger_; ESP_LOGVV(TAG, "Switching to HEATING action"); action_ready = true; } @@ -558,7 +558,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } else { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); } - trig = this->fan_only_action_trigger_; + trig = &this->fan_only_action_trigger_; ESP_LOGVV(TAG, "Switching to FAN_ONLY action"); action_ready = true; } @@ -567,7 +567,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu if (this->drying_action_ready_()) { this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_ON); this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig = this->dry_action_trigger_; + trig = &this->dry_action_trigger_; ESP_LOGVV(TAG, "Switching to DRYING action"); action_ready = true; } @@ -634,14 +634,14 @@ void ThermostatClimate::trigger_supplemental_action_() { if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME)) { this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); } - trig = this->supplemental_cool_action_trigger_; + trig = &this->supplemental_cool_action_trigger_; ESP_LOGVV(TAG, "Calling supplemental COOLING action"); break; case climate::CLIMATE_ACTION_HEATING: if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME)) { this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); } - trig = this->supplemental_heat_action_trigger_; + trig = &this->supplemental_heat_action_trigger_; ESP_LOGVV(TAG, "Calling supplemental HEATING action"); break; default: @@ -660,24 +660,24 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction return; } - Trigger<> *trig = this->humidity_control_off_action_trigger_; + Trigger<> *trig = &this->humidity_control_off_action_trigger_; switch (action) { case THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF: - // trig = this->humidity_control_off_action_trigger_; + // trig = &this->humidity_control_off_action_trigger_; ESP_LOGVV(TAG, "Switching to HUMIDIFICATION_OFF action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_DEHUMIDIFY: - trig = this->humidity_control_dehumidify_action_trigger_; + trig = &this->humidity_control_dehumidify_action_trigger_; ESP_LOGVV(TAG, "Switching to DEHUMIDIFY action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_HUMIDIFY: - trig = this->humidity_control_humidify_action_trigger_; + trig = &this->humidity_control_humidify_action_trigger_; ESP_LOGVV(TAG, "Switching to HUMIDIFY action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_NONE: default: action = THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF; - // trig = this->humidity_control_off_action_trigger_; + // trig = &this->humidity_control_off_action_trigger_; } if (this->prev_humidity_control_trigger_ != nullptr) { @@ -703,53 +703,53 @@ void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bo this->publish_state(); if (this->fan_mode_ready_()) { - Trigger<> *trig = this->fan_mode_auto_trigger_; + Trigger<> *trig = &this->fan_mode_auto_trigger_; switch (fan_mode) { case climate::CLIMATE_FAN_ON: - trig = this->fan_mode_on_trigger_; + trig = &this->fan_mode_on_trigger_; ESP_LOGVV(TAG, "Switching to FAN_ON mode"); break; case climate::CLIMATE_FAN_OFF: - trig = this->fan_mode_off_trigger_; + trig = &this->fan_mode_off_trigger_; ESP_LOGVV(TAG, "Switching to FAN_OFF mode"); break; case climate::CLIMATE_FAN_AUTO: - // trig = this->fan_mode_auto_trigger_; + // trig = &this->fan_mode_auto_trigger_; ESP_LOGVV(TAG, "Switching to FAN_AUTO mode"); break; case climate::CLIMATE_FAN_LOW: - trig = this->fan_mode_low_trigger_; + trig = &this->fan_mode_low_trigger_; ESP_LOGVV(TAG, "Switching to FAN_LOW mode"); break; case climate::CLIMATE_FAN_MEDIUM: - trig = this->fan_mode_medium_trigger_; + trig = &this->fan_mode_medium_trigger_; ESP_LOGVV(TAG, "Switching to FAN_MEDIUM mode"); break; case climate::CLIMATE_FAN_HIGH: - trig = this->fan_mode_high_trigger_; + trig = &this->fan_mode_high_trigger_; ESP_LOGVV(TAG, "Switching to FAN_HIGH mode"); break; case climate::CLIMATE_FAN_MIDDLE: - trig = this->fan_mode_middle_trigger_; + trig = &this->fan_mode_middle_trigger_; ESP_LOGVV(TAG, "Switching to FAN_MIDDLE mode"); break; case climate::CLIMATE_FAN_FOCUS: - trig = this->fan_mode_focus_trigger_; + trig = &this->fan_mode_focus_trigger_; ESP_LOGVV(TAG, "Switching to FAN_FOCUS mode"); break; case climate::CLIMATE_FAN_DIFFUSE: - trig = this->fan_mode_diffuse_trigger_; + trig = &this->fan_mode_diffuse_trigger_; ESP_LOGVV(TAG, "Switching to FAN_DIFFUSE mode"); break; case climate::CLIMATE_FAN_QUIET: - trig = this->fan_mode_quiet_trigger_; + trig = &this->fan_mode_quiet_trigger_; ESP_LOGVV(TAG, "Switching to FAN_QUIET mode"); break; default: // we cannot report an invalid mode back to HA (even if it asked for one) // and must assume some valid value fan_mode = climate::CLIMATE_FAN_AUTO; - // trig = this->fan_mode_auto_trigger_; + // trig = &this->fan_mode_auto_trigger_; } if (this->prev_fan_mode_trigger_ != nullptr) { this->prev_fan_mode_trigger_->stop_action(); @@ -775,25 +775,25 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_ this->prev_mode_trigger_->stop_action(); this->prev_mode_trigger_ = nullptr; } - Trigger<> *trig = this->off_mode_trigger_; + Trigger<> *trig = &this->off_mode_trigger_; switch (mode) { case climate::CLIMATE_MODE_AUTO: - trig = this->auto_mode_trigger_; + trig = &this->auto_mode_trigger_; break; case climate::CLIMATE_MODE_HEAT_COOL: - trig = this->heat_cool_mode_trigger_; + trig = &this->heat_cool_mode_trigger_; break; case climate::CLIMATE_MODE_COOL: - trig = this->cool_mode_trigger_; + trig = &this->cool_mode_trigger_; break; case climate::CLIMATE_MODE_HEAT: - trig = this->heat_mode_trigger_; + trig = &this->heat_mode_trigger_; break; case climate::CLIMATE_MODE_FAN_ONLY: - trig = this->fan_only_mode_trigger_; + trig = &this->fan_only_mode_trigger_; break; case climate::CLIMATE_MODE_DRY: - trig = this->dry_mode_trigger_; + trig = &this->dry_mode_trigger_; break; case climate::CLIMATE_MODE_OFF: default: @@ -824,25 +824,25 @@ void ThermostatClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mo this->prev_swing_mode_trigger_->stop_action(); this->prev_swing_mode_trigger_ = nullptr; } - Trigger<> *trig = this->swing_mode_off_trigger_; + Trigger<> *trig = &this->swing_mode_off_trigger_; switch (swing_mode) { case climate::CLIMATE_SWING_BOTH: - trig = this->swing_mode_both_trigger_; + trig = &this->swing_mode_both_trigger_; break; case climate::CLIMATE_SWING_HORIZONTAL: - trig = this->swing_mode_horizontal_trigger_; + trig = &this->swing_mode_horizontal_trigger_; break; case climate::CLIMATE_SWING_OFF: - // trig = this->swing_mode_off_trigger_; + // trig = &this->swing_mode_off_trigger_; break; case climate::CLIMATE_SWING_VERTICAL: - trig = this->swing_mode_vertical_trigger_; + trig = &this->swing_mode_vertical_trigger_; break; default: // we cannot report an invalid mode back to HA (even if it asked for one) // and must assume some valid value swing_mode = climate::CLIMATE_SWING_OFF; - // trig = this->swing_mode_off_trigger_; + // trig = &this->swing_mode_off_trigger_; } if (trig != nullptr) { trig->trigger(); @@ -1024,10 +1024,8 @@ void ThermostatClimate::check_humidity_change_trigger_() { this->prev_target_humidity_ = this->target_humidity; } // trigger the action - Trigger<> *trig = this->humidity_change_trigger_; - if (trig != nullptr) { - trig->trigger(); - } + Trigger<> *trig = &this->humidity_change_trigger_; + trig->trigger(); } void ThermostatClimate::check_temperature_change_trigger_() { @@ -1050,10 +1048,8 @@ void ThermostatClimate::check_temperature_change_trigger_() { } } // trigger the action - Trigger<> *trig = this->temperature_change_trigger_; - if (trig != nullptr) { - trig->trigger(); - } + Trigger<> *trig = &this->temperature_change_trigger_; + trig->trigger(); } bool ThermostatClimate::cooling_required_() { @@ -1202,12 +1198,10 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { if (config != nullptr) { ESP_LOGV(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset))); if (this->change_preset_internal_(*config) || (!this->preset.has_value()) || this->preset.value() != preset) { - // Fire any preset changed trigger if defined - Trigger<> *trig = this->preset_change_trigger_; + // Fire preset changed trigger + Trigger<> *trig = &this->preset_change_trigger_; this->set_preset_(preset); - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->refresh(); ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset))); @@ -1234,13 +1228,11 @@ void ThermostatClimate::change_custom_preset_(const char *custom_preset, size_t ESP_LOGV(TAG, "Custom preset %s requested", custom_preset); if (this->change_preset_internal_(*config) || !this->has_custom_preset() || this->get_custom_preset() != custom_preset) { - // Fire any preset changed trigger if defined - Trigger<> *trig = this->preset_change_trigger_; + // Fire preset changed trigger + Trigger<> *trig = &this->preset_change_trigger_; // Use the base class method which handles pointer lookup and preset reset internally this->set_custom_preset_(custom_preset); - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->refresh(); ESP_LOGI(TAG, "Custom preset %s applied", custom_preset); @@ -1305,41 +1297,7 @@ void ThermostatClimate::set_custom_preset_config(std::initializer_listcustom_preset_config_ = presets; } -ThermostatClimate::ThermostatClimate() - : cool_action_trigger_(new Trigger<>()), - supplemental_cool_action_trigger_(new Trigger<>()), - cool_mode_trigger_(new Trigger<>()), - dry_action_trigger_(new Trigger<>()), - dry_mode_trigger_(new Trigger<>()), - heat_action_trigger_(new Trigger<>()), - supplemental_heat_action_trigger_(new Trigger<>()), - heat_mode_trigger_(new Trigger<>()), - heat_cool_mode_trigger_(new Trigger<>()), - auto_mode_trigger_(new Trigger<>()), - idle_action_trigger_(new Trigger<>()), - off_mode_trigger_(new Trigger<>()), - fan_only_action_trigger_(new Trigger<>()), - fan_only_mode_trigger_(new Trigger<>()), - fan_mode_on_trigger_(new Trigger<>()), - fan_mode_off_trigger_(new Trigger<>()), - fan_mode_auto_trigger_(new Trigger<>()), - fan_mode_low_trigger_(new Trigger<>()), - fan_mode_medium_trigger_(new Trigger<>()), - fan_mode_high_trigger_(new Trigger<>()), - fan_mode_middle_trigger_(new Trigger<>()), - fan_mode_focus_trigger_(new Trigger<>()), - fan_mode_diffuse_trigger_(new Trigger<>()), - fan_mode_quiet_trigger_(new Trigger<>()), - swing_mode_both_trigger_(new Trigger<>()), - swing_mode_off_trigger_(new Trigger<>()), - swing_mode_horizontal_trigger_(new Trigger<>()), - swing_mode_vertical_trigger_(new Trigger<>()), - humidity_change_trigger_(new Trigger<>()), - temperature_change_trigger_(new Trigger<>()), - preset_change_trigger_(new Trigger<>()), - humidity_control_dehumidify_action_trigger_(new Trigger<>()), - humidity_control_humidify_action_trigger_(new Trigger<>()), - humidity_control_off_action_trigger_(new Trigger<>()) {} +ThermostatClimate::ThermostatClimate() = default; void ThermostatClimate::set_default_preset(const char *custom_preset) { // Find the preset in custom_preset_config_ and store pointer from there @@ -1513,49 +1471,49 @@ void ThermostatClimate::set_supports_humidification(bool supports_humidification } } -Trigger<> *ThermostatClimate::get_cool_action_trigger() const { return this->cool_action_trigger_; } -Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() const { - return this->supplemental_cool_action_trigger_; +Trigger<> *ThermostatClimate::get_cool_action_trigger() { return &this->cool_action_trigger_; } +Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() { + return &this->supplemental_cool_action_trigger_; } -Trigger<> *ThermostatClimate::get_dry_action_trigger() const { return this->dry_action_trigger_; } -Trigger<> *ThermostatClimate::get_fan_only_action_trigger() const { return this->fan_only_action_trigger_; } -Trigger<> *ThermostatClimate::get_heat_action_trigger() const { return this->heat_action_trigger_; } -Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() const { - return this->supplemental_heat_action_trigger_; +Trigger<> *ThermostatClimate::get_dry_action_trigger() { return &this->dry_action_trigger_; } +Trigger<> *ThermostatClimate::get_fan_only_action_trigger() { return &this->fan_only_action_trigger_; } +Trigger<> *ThermostatClimate::get_heat_action_trigger() { return &this->heat_action_trigger_; } +Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() { + return &this->supplemental_heat_action_trigger_; } -Trigger<> *ThermostatClimate::get_idle_action_trigger() const { return this->idle_action_trigger_; } -Trigger<> *ThermostatClimate::get_auto_mode_trigger() const { return this->auto_mode_trigger_; } -Trigger<> *ThermostatClimate::get_cool_mode_trigger() const { return this->cool_mode_trigger_; } -Trigger<> *ThermostatClimate::get_dry_mode_trigger() const { return this->dry_mode_trigger_; } -Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() const { return this->fan_only_mode_trigger_; } -Trigger<> *ThermostatClimate::get_heat_mode_trigger() const { return this->heat_mode_trigger_; } -Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() const { return this->heat_cool_mode_trigger_; } -Trigger<> *ThermostatClimate::get_off_mode_trigger() const { return this->off_mode_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() const { return this->fan_mode_on_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() const { return this->fan_mode_off_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() const { return this->fan_mode_auto_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() const { return this->fan_mode_low_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() const { return this->fan_mode_medium_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() const { return this->fan_mode_high_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() const { return this->fan_mode_middle_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() const { return this->fan_mode_focus_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() const { return this->fan_mode_diffuse_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() const { return this->fan_mode_quiet_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() const { return this->swing_mode_both_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() const { return this->swing_mode_off_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() const { return this->swing_mode_horizontal_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() const { return this->swing_mode_vertical_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_change_trigger() const { return this->humidity_change_trigger_; } -Trigger<> *ThermostatClimate::get_temperature_change_trigger() const { return this->temperature_change_trigger_; } -Trigger<> *ThermostatClimate::get_preset_change_trigger() const { return this->preset_change_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() const { - return this->humidity_control_dehumidify_action_trigger_; +Trigger<> *ThermostatClimate::get_idle_action_trigger() { return &this->idle_action_trigger_; } +Trigger<> *ThermostatClimate::get_auto_mode_trigger() { return &this->auto_mode_trigger_; } +Trigger<> *ThermostatClimate::get_cool_mode_trigger() { return &this->cool_mode_trigger_; } +Trigger<> *ThermostatClimate::get_dry_mode_trigger() { return &this->dry_mode_trigger_; } +Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() { return &this->fan_only_mode_trigger_; } +Trigger<> *ThermostatClimate::get_heat_mode_trigger() { return &this->heat_mode_trigger_; } +Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() { return &this->heat_cool_mode_trigger_; } +Trigger<> *ThermostatClimate::get_off_mode_trigger() { return &this->off_mode_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() { return &this->fan_mode_on_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() { return &this->fan_mode_off_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() { return &this->fan_mode_auto_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() { return &this->fan_mode_low_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() { return &this->fan_mode_medium_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() { return &this->fan_mode_high_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() { return &this->fan_mode_middle_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() { return &this->fan_mode_focus_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() { return &this->fan_mode_diffuse_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() { return &this->fan_mode_quiet_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() { return &this->swing_mode_both_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() { return &this->swing_mode_off_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() { return &this->swing_mode_horizontal_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() { return &this->swing_mode_vertical_trigger_; } +Trigger<> *ThermostatClimate::get_humidity_change_trigger() { return &this->humidity_change_trigger_; } +Trigger<> *ThermostatClimate::get_temperature_change_trigger() { return &this->temperature_change_trigger_; } +Trigger<> *ThermostatClimate::get_preset_change_trigger() { return &this->preset_change_trigger_; } +Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() { + return &this->humidity_control_dehumidify_action_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() const { - return this->humidity_control_humidify_action_trigger_; +Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() { + return &this->humidity_control_humidify_action_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() const { - return this->humidity_control_off_action_trigger_; +Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() { + return &this->humidity_control_off_action_trigger_; } void ThermostatClimate::dump_config() { diff --git a/esphome/components/thermostat/thermostat_climate.h b/esphome/components/thermostat/thermostat_climate.h index d37c9a68a6..4268d5c582 100644 --- a/esphome/components/thermostat/thermostat_climate.h +++ b/esphome/components/thermostat/thermostat_climate.h @@ -146,40 +146,40 @@ class ThermostatClimate : public climate::Climate, public Component { void set_preset_config(std::initializer_list presets); void set_custom_preset_config(std::initializer_list presets); - Trigger<> *get_cool_action_trigger() const; - Trigger<> *get_supplemental_cool_action_trigger() const; - Trigger<> *get_dry_action_trigger() const; - Trigger<> *get_fan_only_action_trigger() const; - Trigger<> *get_heat_action_trigger() const; - Trigger<> *get_supplemental_heat_action_trigger() const; - Trigger<> *get_idle_action_trigger() const; - Trigger<> *get_auto_mode_trigger() const; - Trigger<> *get_cool_mode_trigger() const; - Trigger<> *get_dry_mode_trigger() const; - Trigger<> *get_fan_only_mode_trigger() const; - Trigger<> *get_heat_mode_trigger() const; - Trigger<> *get_heat_cool_mode_trigger() const; - Trigger<> *get_off_mode_trigger() const; - Trigger<> *get_fan_mode_on_trigger() const; - Trigger<> *get_fan_mode_off_trigger() const; - Trigger<> *get_fan_mode_auto_trigger() const; - Trigger<> *get_fan_mode_low_trigger() const; - Trigger<> *get_fan_mode_medium_trigger() const; - Trigger<> *get_fan_mode_high_trigger() const; - Trigger<> *get_fan_mode_middle_trigger() const; - Trigger<> *get_fan_mode_focus_trigger() const; - Trigger<> *get_fan_mode_diffuse_trigger() const; - Trigger<> *get_fan_mode_quiet_trigger() const; - Trigger<> *get_swing_mode_both_trigger() const; - Trigger<> *get_swing_mode_horizontal_trigger() const; - Trigger<> *get_swing_mode_off_trigger() const; - Trigger<> *get_swing_mode_vertical_trigger() const; - Trigger<> *get_humidity_change_trigger() const; - Trigger<> *get_temperature_change_trigger() const; - Trigger<> *get_preset_change_trigger() const; - Trigger<> *get_humidity_control_dehumidify_action_trigger() const; - Trigger<> *get_humidity_control_humidify_action_trigger() const; - Trigger<> *get_humidity_control_off_action_trigger() const; + Trigger<> *get_cool_action_trigger(); + Trigger<> *get_supplemental_cool_action_trigger(); + Trigger<> *get_dry_action_trigger(); + Trigger<> *get_fan_only_action_trigger(); + Trigger<> *get_heat_action_trigger(); + Trigger<> *get_supplemental_heat_action_trigger(); + Trigger<> *get_idle_action_trigger(); + Trigger<> *get_auto_mode_trigger(); + Trigger<> *get_cool_mode_trigger(); + Trigger<> *get_dry_mode_trigger(); + Trigger<> *get_fan_only_mode_trigger(); + Trigger<> *get_heat_mode_trigger(); + Trigger<> *get_heat_cool_mode_trigger(); + Trigger<> *get_off_mode_trigger(); + Trigger<> *get_fan_mode_on_trigger(); + Trigger<> *get_fan_mode_off_trigger(); + Trigger<> *get_fan_mode_auto_trigger(); + Trigger<> *get_fan_mode_low_trigger(); + Trigger<> *get_fan_mode_medium_trigger(); + Trigger<> *get_fan_mode_high_trigger(); + Trigger<> *get_fan_mode_middle_trigger(); + Trigger<> *get_fan_mode_focus_trigger(); + Trigger<> *get_fan_mode_diffuse_trigger(); + Trigger<> *get_fan_mode_quiet_trigger(); + Trigger<> *get_swing_mode_both_trigger(); + Trigger<> *get_swing_mode_horizontal_trigger(); + Trigger<> *get_swing_mode_off_trigger(); + Trigger<> *get_swing_mode_vertical_trigger(); + Trigger<> *get_humidity_change_trigger(); + Trigger<> *get_temperature_change_trigger(); + Trigger<> *get_preset_change_trigger(); + Trigger<> *get_humidity_control_dehumidify_action_trigger(); + Trigger<> *get_humidity_control_humidify_action_trigger(); + Trigger<> *get_humidity_control_off_action_trigger(); /// Get current hysteresis values float cool_deadband(); float cool_overrun(); @@ -417,115 +417,65 @@ class ThermostatClimate : public climate::Climate, public Component { /// The sensor used for getting the current humidity sensor::Sensor *humidity_sensor_{nullptr}; - /// The trigger to call when the controller should switch to cooling action/mode. - /// - /// A null value for this attribute means that the controller has no cooling action - /// For example electric heat, where only heating (power on) and not-heating - /// (power off) is possible. - Trigger<> *cool_action_trigger_{nullptr}; - Trigger<> *supplemental_cool_action_trigger_{nullptr}; - Trigger<> *cool_mode_trigger_{nullptr}; + /// Trigger for cooling action/mode + Trigger<> cool_action_trigger_; + Trigger<> supplemental_cool_action_trigger_; + Trigger<> cool_mode_trigger_; - /// The trigger to call when the controller should switch to dry (dehumidification) mode. - /// - /// In dry mode, the controller is assumed to have both heating and cooling disabled, - /// although the system may use its cooling mechanism to achieve drying. - Trigger<> *dry_action_trigger_{nullptr}; - Trigger<> *dry_mode_trigger_{nullptr}; + /// Trigger for dry (dehumidification) mode + Trigger<> dry_action_trigger_; + Trigger<> dry_mode_trigger_; - /// The trigger to call when the controller should switch to heating action/mode. - /// - /// A null value for this attribute means that the controller has no heating action - /// For example window blinds, where only cooling (blinds closed) and not-cooling - /// (blinds open) is possible. - Trigger<> *heat_action_trigger_{nullptr}; - Trigger<> *supplemental_heat_action_trigger_{nullptr}; - Trigger<> *heat_mode_trigger_{nullptr}; + /// Trigger for heating action/mode + Trigger<> heat_action_trigger_; + Trigger<> supplemental_heat_action_trigger_; + Trigger<> heat_mode_trigger_; - /// The trigger to call when the controller should switch to heat/cool mode. - /// - /// In heat/cool mode, the controller will enable heating/cooling as necessary and switch - /// to idle when the temperature is within the thresholds/set points. - Trigger<> *heat_cool_mode_trigger_{nullptr}; + /// Trigger for heat/cool mode + Trigger<> heat_cool_mode_trigger_; - /// The trigger to call when the controller should switch to auto mode. - /// - /// In auto mode, the controller will enable heating/cooling as supported/necessary and switch - /// to idle when the temperature is within the thresholds/set points. - Trigger<> *auto_mode_trigger_{nullptr}; + /// Trigger for auto mode + Trigger<> auto_mode_trigger_; - /// The trigger to call when the controller should switch to idle action/off mode. - /// - /// In these actions/modes, the controller is assumed to have both heating and cooling disabled. - Trigger<> *idle_action_trigger_{nullptr}; - Trigger<> *off_mode_trigger_{nullptr}; + /// Trigger for idle action/off mode + Trigger<> idle_action_trigger_; + Trigger<> off_mode_trigger_; - /// The trigger to call when the controller should switch to fan-only action/mode. - /// - /// In fan-only mode, the controller is assumed to have both heating and cooling disabled. - /// The system should activate the fan only. - Trigger<> *fan_only_action_trigger_{nullptr}; - Trigger<> *fan_only_mode_trigger_{nullptr}; + /// Trigger for fan-only action/mode + Trigger<> fan_only_action_trigger_; + Trigger<> fan_only_mode_trigger_; - /// The trigger to call when the controller should switch on the fan. - Trigger<> *fan_mode_on_trigger_{nullptr}; + /// Fan mode triggers + Trigger<> fan_mode_on_trigger_; + Trigger<> fan_mode_off_trigger_; + Trigger<> fan_mode_auto_trigger_; + Trigger<> fan_mode_low_trigger_; + Trigger<> fan_mode_medium_trigger_; + Trigger<> fan_mode_high_trigger_; + Trigger<> fan_mode_middle_trigger_; + Trigger<> fan_mode_focus_trigger_; + Trigger<> fan_mode_diffuse_trigger_; + Trigger<> fan_mode_quiet_trigger_; - /// The trigger to call when the controller should switch off the fan. - Trigger<> *fan_mode_off_trigger_{nullptr}; + /// Swing mode triggers + Trigger<> swing_mode_both_trigger_; + Trigger<> swing_mode_off_trigger_; + Trigger<> swing_mode_horizontal_trigger_; + Trigger<> swing_mode_vertical_trigger_; - /// The trigger to call when the controller should switch the fan to "auto" mode. - Trigger<> *fan_mode_auto_trigger_{nullptr}; + /// Trigger for target humidity changes + Trigger<> humidity_change_trigger_; - /// The trigger to call when the controller should switch the fan to "low" speed. - Trigger<> *fan_mode_low_trigger_{nullptr}; + /// Trigger for target temperature changes + Trigger<> temperature_change_trigger_; - /// The trigger to call when the controller should switch the fan to "medium" speed. - Trigger<> *fan_mode_medium_trigger_{nullptr}; + /// Trigger for preset mode changes + Trigger<> preset_change_trigger_; - /// The trigger to call when the controller should switch the fan to "high" speed. - Trigger<> *fan_mode_high_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "middle" position. - Trigger<> *fan_mode_middle_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "focus" position. - Trigger<> *fan_mode_focus_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "diffuse" position. - Trigger<> *fan_mode_diffuse_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "quiet" position. - Trigger<> *fan_mode_quiet_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "both". - Trigger<> *swing_mode_both_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "off". - Trigger<> *swing_mode_off_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "horizontal". - Trigger<> *swing_mode_horizontal_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "vertical". - Trigger<> *swing_mode_vertical_trigger_{nullptr}; - - /// The trigger to call when the target humidity changes. - Trigger<> *humidity_change_trigger_{nullptr}; - - /// The trigger to call when the target temperature(s) change(es). - Trigger<> *temperature_change_trigger_{nullptr}; - - /// The trigger to call when the preset mode changes - Trigger<> *preset_change_trigger_{nullptr}; - - /// The trigger to call when dehumidification is required - Trigger<> *humidity_control_dehumidify_action_trigger_{nullptr}; - - /// The trigger to call when humidification is required - Trigger<> *humidity_control_humidify_action_trigger_{nullptr}; - - /// The trigger to call when (de)humidification should stop - Trigger<> *humidity_control_off_action_trigger_{nullptr}; + /// Humidity control triggers + Trigger<> humidity_control_dehumidify_action_trigger_; + Trigger<> humidity_control_humidify_action_trigger_; + Trigger<> humidity_control_off_action_trigger_; /// A reference to the trigger that was previously active. /// From bfeb4471784983af79c076d953ed6382df870176 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:16 +0100 Subject: [PATCH 0443/2030] [sx127x] Avoid heap allocation for packet trigger (#13698) --- esphome/components/sx127x/sx127x.cpp | 2 +- esphome/components/sx127x/sx127x.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index 3185574b1a..caf68b6d51 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -300,7 +300,7 @@ void SX127x::call_listeners_(const std::vector &packet, float rssi, flo for (auto &listener : this->listeners_) { listener->on_packet(packet, rssi, snr); } - this->packet_trigger_->trigger(packet, rssi, snr); + this->packet_trigger_.trigger(packet, rssi, snr); } void SX127x::loop() { diff --git a/esphome/components/sx127x/sx127x.h b/esphome/components/sx127x/sx127x.h index 0600b51201..be7b6d8d9f 100644 --- a/esphome/components/sx127x/sx127x.h +++ b/esphome/components/sx127x/sx127x.h @@ -83,7 +83,7 @@ class SX127x : public Component, void configure(); SX127xError transmit_packet(const std::vector &packet); void register_listener(SX127xListener *listener) { this->listeners_.push_back(listener); } - Trigger, float, float> *get_packet_trigger() const { return this->packet_trigger_; }; + Trigger, float, float> *get_packet_trigger() { return &this->packet_trigger_; } protected: void configure_fsk_ook_(); @@ -94,7 +94,7 @@ class SX127x : public Component, void write_register_(uint8_t reg, uint8_t value); void call_listeners_(const std::vector &packet, float rssi, float snr); uint8_t read_register_(uint8_t reg); - Trigger, float, float> *packet_trigger_{new Trigger, float, float>()}; + Trigger, float, float> packet_trigger_; std::vector listeners_; std::vector packet_; std::vector sync_value_; From 75ee9a718ac7dd02b445648847229bfcbffe6642 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:30 +0100 Subject: [PATCH 0444/2030] [sx126x] Avoid heap allocation for packet trigger (#13699) --- esphome/components/sx126x/sx126x.cpp | 2 +- esphome/components/sx126x/sx126x.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/sx126x/sx126x.cpp b/esphome/components/sx126x/sx126x.cpp index 707d6f1fbf..64cd24b171 100644 --- a/esphome/components/sx126x/sx126x.cpp +++ b/esphome/components/sx126x/sx126x.cpp @@ -343,7 +343,7 @@ void SX126x::call_listeners_(const std::vector &packet, float rssi, flo for (auto &listener : this->listeners_) { listener->on_packet(packet, rssi, snr); } - this->packet_trigger_->trigger(packet, rssi, snr); + this->packet_trigger_.trigger(packet, rssi, snr); } void SX126x::loop() { diff --git a/esphome/components/sx126x/sx126x.h b/esphome/components/sx126x/sx126x.h index 850d7d4c77..a758d63795 100644 --- a/esphome/components/sx126x/sx126x.h +++ b/esphome/components/sx126x/sx126x.h @@ -97,7 +97,7 @@ class SX126x : public Component, void configure(); SX126xError transmit_packet(const std::vector &packet); void register_listener(SX126xListener *listener) { this->listeners_.push_back(listener); } - Trigger, float, float> *get_packet_trigger() const { return this->packet_trigger_; }; + Trigger, float, float> *get_packet_trigger() { return &this->packet_trigger_; } protected: void configure_fsk_ook_(); @@ -111,7 +111,7 @@ class SX126x : public Component, void read_register_(uint16_t reg, uint8_t *data, uint8_t size); void call_listeners_(const std::vector &packet, float rssi, float snr); void wait_busy_(); - Trigger, float, float> *packet_trigger_{new Trigger, float, float>()}; + Trigger, float, float> packet_trigger_; std::vector listeners_; std::vector packet_; std::vector sync_value_; From 78ed898f0bf521a2bea95461640c167aa6ac5715 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:52 +0100 Subject: [PATCH 0445/2030] [current_based] Avoid heap allocation for cover triggers (#13700) --- .../current_based/current_based_cover.cpp | 10 +++++----- .../current_based/current_based_cover.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index cb3f65c9cd..402cf9fee7 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -66,7 +66,7 @@ void CurrentBasedCover::loop() { if (this->current_operation == COVER_OPERATION_OPENING) { if (this->malfunction_detection_ && this->is_closing_()) { // Malfunction this->direction_idle_(); - this->malfunction_trigger_->trigger(); + this->malfunction_trigger_.trigger(); ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit", this->name_.c_str()); } else if (this->is_opening_blocked_()) { // Blocked @@ -87,7 +87,7 @@ void CurrentBasedCover::loop() { } else if (this->current_operation == COVER_OPERATION_CLOSING) { if (this->malfunction_detection_ && this->is_opening_()) { // Malfunction this->direction_idle_(); - this->malfunction_trigger_->trigger(); + this->malfunction_trigger_.trigger(); ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit", this->name_.c_str()); } else if (this->is_closing_blocked_()) { // Blocked @@ -221,15 +221,15 @@ void CurrentBasedCover::start_direction_(CoverOperation dir) { Trigger<> *trig; switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; break; default: return; diff --git a/esphome/components/current_based/current_based_cover.h b/esphome/components/current_based/current_based_cover.h index b172e762b0..f7993f1550 100644 --- a/esphome/components/current_based/current_based_cover.h +++ b/esphome/components/current_based/current_based_cover.h @@ -16,9 +16,9 @@ class CurrentBasedCover : public cover::Cover, public Component { void dump_config() override; float get_setup_priority() const override; - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } - Trigger<> *get_open_trigger() const { return this->open_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } void set_open_sensor(sensor::Sensor *open_sensor) { this->open_sensor_ = open_sensor; } void set_open_moving_current_threshold(float open_moving_current_threshold) { this->open_moving_current_threshold_ = open_moving_current_threshold; @@ -28,7 +28,7 @@ class CurrentBasedCover : public cover::Cover, public Component { } void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } void set_close_sensor(sensor::Sensor *close_sensor) { this->close_sensor_ = close_sensor; } void set_close_moving_current_threshold(float close_moving_current_threshold) { this->close_moving_current_threshold_ = close_moving_current_threshold; @@ -44,7 +44,7 @@ class CurrentBasedCover : public cover::Cover, public Component { void set_malfunction_detection(bool malfunction_detection) { this->malfunction_detection_ = malfunction_detection; } void set_start_sensing_delay(uint32_t start_sensing_delay) { this->start_sensing_delay_ = start_sensing_delay; } - Trigger<> *get_malfunction_trigger() const { return this->malfunction_trigger_; } + Trigger<> *get_malfunction_trigger() { return &this->malfunction_trigger_; } cover::CoverTraits get_traits() override; @@ -64,23 +64,23 @@ class CurrentBasedCover : public cover::Cover, public Component { void recompute_position_(); - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> stop_trigger_; sensor::Sensor *open_sensor_{nullptr}; - Trigger<> *open_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; float open_moving_current_threshold_; float open_obstacle_current_threshold_{FLT_MAX}; uint32_t open_duration_; sensor::Sensor *close_sensor_{nullptr}; - Trigger<> *close_trigger_{new Trigger<>()}; + Trigger<> close_trigger_; float close_moving_current_threshold_; float close_obstacle_current_threshold_{FLT_MAX}; uint32_t close_duration_; uint32_t max_duration_{UINT32_MAX}; bool malfunction_detection_{true}; - Trigger<> *malfunction_trigger_{new Trigger<>()}; + Trigger<> malfunction_trigger_; uint32_t start_sensing_delay_; float obstacle_rollback_; From 01ffeba2c2930e633c6faf14d993cb040db97e85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:44:08 +0100 Subject: [PATCH 0446/2030] [api] Avoid heap allocation for homeassistant action triggers (#13695) --- .../components/api/homeassistant_service.h | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 9bffe18764..8ee23c75fe 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -136,12 +136,10 @@ template class HomeAssistantServiceCallAction : public Actionflags_.wants_response = true; } #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - Trigger *get_success_trigger_with_response() const { - return this->success_trigger_with_response_; - } + Trigger *get_success_trigger_with_response() { return &this->success_trigger_with_response_; } #endif - Trigger *get_success_trigger() const { return this->success_trigger_; } - Trigger *get_error_trigger() const { return this->error_trigger_; } + Trigger *get_success_trigger() { return &this->success_trigger_; } + Trigger *get_error_trigger() { return &this->error_trigger_; } #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES void play(const Ts &...x) override { @@ -187,14 +185,14 @@ template class HomeAssistantServiceCallAction : public Actionflags_.wants_response) { - this->success_trigger_with_response_->trigger(response.get_json(), args...); + this->success_trigger_with_response_.trigger(response.get_json(), args...); } else #endif { - this->success_trigger_->trigger(args...); + this->success_trigger_.trigger(args...); } } else { - this->error_trigger_->trigger(response.get_error_message(), args...); + this->error_trigger_.trigger(response.get_error_message(), args...); } }, captured_args); @@ -251,10 +249,10 @@ template class HomeAssistantServiceCallAction : public Action response_template_{""}; - Trigger *success_trigger_with_response_ = new Trigger(); + Trigger success_trigger_with_response_; #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - Trigger *success_trigger_ = new Trigger(); - Trigger *error_trigger_ = new Trigger(); + Trigger success_trigger_; + Trigger error_trigger_; #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES struct Flags { From 8a8c1290dbfc87639bc4c297b94377857aa2d077 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:45:01 +0100 Subject: [PATCH 0447/2030] [endstop] Avoid heap allocation for cover triggers (#13702) --- esphome/components/endstop/endstop_cover.cpp | 6 +++--- esphome/components/endstop/endstop_cover.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/endstop/endstop_cover.cpp b/esphome/components/endstop/endstop_cover.cpp index 2c281ea2e6..e28f024136 100644 --- a/esphome/components/endstop/endstop_cover.cpp +++ b/esphome/components/endstop/endstop_cover.cpp @@ -141,15 +141,15 @@ void EndstopCover::start_direction_(CoverOperation dir) { Trigger<> *trig; switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; break; default: return; diff --git a/esphome/components/endstop/endstop_cover.h b/esphome/components/endstop/endstop_cover.h index 6ae15de8c1..6f72b2b805 100644 --- a/esphome/components/endstop/endstop_cover.h +++ b/esphome/components/endstop/endstop_cover.h @@ -15,9 +15,9 @@ class EndstopCover : public cover::Cover, public Component { void dump_config() override; float get_setup_priority() const override; - Trigger<> *get_open_trigger() const { return this->open_trigger_; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } void set_open_endstop(binary_sensor::BinarySensor *open_endstop) { this->open_endstop_ = open_endstop; } void set_close_endstop(binary_sensor::BinarySensor *close_endstop) { this->close_endstop_ = close_endstop; } void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } @@ -39,11 +39,11 @@ class EndstopCover : public cover::Cover, public Component { binary_sensor::BinarySensor *open_endstop_; binary_sensor::BinarySensor *close_endstop_; - Trigger<> *open_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; uint32_t open_duration_; - Trigger<> *close_trigger_{new Trigger<>()}; + Trigger<> close_trigger_; uint32_t close_duration_; - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> stop_trigger_; uint32_t max_duration_{UINT32_MAX}; Trigger<> *prev_command_trigger_{nullptr}; From d49d8095dfdb24c8e54a3e7f12e1a7e6ffe0f8b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:46:41 +0100 Subject: [PATCH 0448/2030] [template] Avoid heap allocation for valve triggers (#13697) --- .../template/valve/template_valve.cpp | 35 ++++++++----------- .../template/valve/template_valve.h | 20 +++++------ 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/esphome/components/template/valve/template_valve.cpp b/esphome/components/template/valve/template_valve.cpp index 4e772f9253..2817e1a132 100644 --- a/esphome/components/template/valve/template_valve.cpp +++ b/esphome/components/template/valve/template_valve.cpp @@ -7,12 +7,7 @@ using namespace esphome::valve; static const char *const TAG = "template.valve"; -TemplateValve::TemplateValve() - : open_trigger_(new Trigger<>()), - close_trigger_(new Trigger<>), - stop_trigger_(new Trigger<>()), - toggle_trigger_(new Trigger<>()), - position_trigger_(new Trigger()) {} +TemplateValve::TemplateValve() = default; void TemplateValve::setup() { switch (this->restore_mode_) { @@ -56,10 +51,10 @@ void TemplateValve::set_optimistic(bool optimistic) { this->optimistic_ = optimi void TemplateValve::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } float TemplateValve::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *TemplateValve::get_open_trigger() const { return this->open_trigger_; } -Trigger<> *TemplateValve::get_close_trigger() const { return this->close_trigger_; } -Trigger<> *TemplateValve::get_stop_trigger() const { return this->stop_trigger_; } -Trigger<> *TemplateValve::get_toggle_trigger() const { return this->toggle_trigger_; } +Trigger<> *TemplateValve::get_open_trigger() { return &this->open_trigger_; } +Trigger<> *TemplateValve::get_close_trigger() { return &this->close_trigger_; } +Trigger<> *TemplateValve::get_stop_trigger() { return &this->stop_trigger_; } +Trigger<> *TemplateValve::get_toggle_trigger() { return &this->toggle_trigger_; } void TemplateValve::dump_config() { LOG_VALVE("", "Template Valve", this); @@ -72,14 +67,14 @@ void TemplateValve::dump_config() { void TemplateValve::control(const ValveCall &call) { if (call.get_stop()) { this->stop_prev_trigger_(); - this->stop_trigger_->trigger(); - this->prev_command_trigger_ = this->stop_trigger_; + this->stop_trigger_.trigger(); + this->prev_command_trigger_ = &this->stop_trigger_; this->publish_state(); } if (call.get_toggle().has_value()) { this->stop_prev_trigger_(); - this->toggle_trigger_->trigger(); - this->prev_command_trigger_ = this->toggle_trigger_; + this->toggle_trigger_.trigger(); + this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } if (call.get_position().has_value()) { @@ -87,13 +82,13 @@ void TemplateValve::control(const ValveCall &call) { this->stop_prev_trigger_(); if (pos == VALVE_OPEN) { - this->open_trigger_->trigger(); - this->prev_command_trigger_ = this->open_trigger_; + this->open_trigger_.trigger(); + this->prev_command_trigger_ = &this->open_trigger_; } else if (pos == VALVE_CLOSED) { - this->close_trigger_->trigger(); - this->prev_command_trigger_ = this->close_trigger_; + this->close_trigger_.trigger(); + this->prev_command_trigger_ = &this->close_trigger_; } else { - this->position_trigger_->trigger(pos); + this->position_trigger_.trigger(pos); } if (this->optimistic_) { @@ -113,7 +108,7 @@ ValveTraits TemplateValve::get_traits() { return traits; } -Trigger *TemplateValve::get_position_trigger() const { return this->position_trigger_; } +Trigger *TemplateValve::get_position_trigger() { return &this->position_trigger_; } void TemplateValve::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } void TemplateValve::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 4205682a2a..76c4630aa0 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -18,11 +18,11 @@ class TemplateValve final : public valve::Valve, public Component { TemplateValve(); template void set_state_lambda(F &&f) { this->state_f_.set(std::forward(f)); } - Trigger<> *get_open_trigger() const; - Trigger<> *get_close_trigger() const; - Trigger<> *get_stop_trigger() const; - Trigger<> *get_toggle_trigger() const; - Trigger *get_position_trigger() const; + Trigger<> *get_open_trigger(); + Trigger<> *get_close_trigger(); + Trigger<> *get_stop_trigger(); + Trigger<> *get_toggle_trigger(); + Trigger *get_position_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void set_has_stop(bool has_stop); @@ -45,14 +45,14 @@ class TemplateValve final : public valve::Valve, public Component { TemplateLambda state_f_; bool assumed_state_{false}; bool optimistic_{false}; - Trigger<> *open_trigger_; - Trigger<> *close_trigger_; + Trigger<> open_trigger_; + Trigger<> close_trigger_; bool has_stop_{false}; bool has_toggle_{false}; - Trigger<> *stop_trigger_; - Trigger<> *toggle_trigger_; + Trigger<> stop_trigger_; + Trigger<> toggle_trigger_; Trigger<> *prev_command_trigger_{nullptr}; - Trigger *position_trigger_; + Trigger position_trigger_; bool has_position_{false}; }; From 2f0abd5c3f5e9b1ae8bffe62a8ad320b7ad32a2c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:46:55 +0100 Subject: [PATCH 0449/2030] [template] Avoid heap allocation for cover triggers (#13696) --- .../template/cover/template_cover.cpp | 40 ++++++++----------- .../template/cover/template_cover.h | 24 +++++------ 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/esphome/components/template/cover/template_cover.cpp b/esphome/components/template/cover/template_cover.cpp index 9c8a8fc9bc..7f5d68623f 100644 --- a/esphome/components/template/cover/template_cover.cpp +++ b/esphome/components/template/cover/template_cover.cpp @@ -7,13 +7,7 @@ using namespace esphome::cover; static const char *const TAG = "template.cover"; -TemplateCover::TemplateCover() - : open_trigger_(new Trigger<>()), - close_trigger_(new Trigger<>), - stop_trigger_(new Trigger<>()), - toggle_trigger_(new Trigger<>()), - position_trigger_(new Trigger()), - tilt_trigger_(new Trigger()) {} +TemplateCover::TemplateCover() = default; void TemplateCover::setup() { switch (this->restore_mode_) { case COVER_NO_RESTORE: @@ -62,22 +56,22 @@ void TemplateCover::loop() { void TemplateCover::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void TemplateCover::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } float TemplateCover::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *TemplateCover::get_open_trigger() const { return this->open_trigger_; } -Trigger<> *TemplateCover::get_close_trigger() const { return this->close_trigger_; } -Trigger<> *TemplateCover::get_stop_trigger() const { return this->stop_trigger_; } -Trigger<> *TemplateCover::get_toggle_trigger() const { return this->toggle_trigger_; } +Trigger<> *TemplateCover::get_open_trigger() { return &this->open_trigger_; } +Trigger<> *TemplateCover::get_close_trigger() { return &this->close_trigger_; } +Trigger<> *TemplateCover::get_stop_trigger() { return &this->stop_trigger_; } +Trigger<> *TemplateCover::get_toggle_trigger() { return &this->toggle_trigger_; } void TemplateCover::dump_config() { LOG_COVER("", "Template Cover", this); } void TemplateCover::control(const CoverCall &call) { if (call.get_stop()) { this->stop_prev_trigger_(); - this->stop_trigger_->trigger(); - this->prev_command_trigger_ = this->stop_trigger_; + this->stop_trigger_.trigger(); + this->prev_command_trigger_ = &this->stop_trigger_; this->publish_state(); } if (call.get_toggle().has_value()) { this->stop_prev_trigger_(); - this->toggle_trigger_->trigger(); - this->prev_command_trigger_ = this->toggle_trigger_; + this->toggle_trigger_.trigger(); + this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } if (call.get_position().has_value()) { @@ -85,13 +79,13 @@ void TemplateCover::control(const CoverCall &call) { this->stop_prev_trigger_(); if (pos == COVER_OPEN) { - this->open_trigger_->trigger(); - this->prev_command_trigger_ = this->open_trigger_; + this->open_trigger_.trigger(); + this->prev_command_trigger_ = &this->open_trigger_; } else if (pos == COVER_CLOSED) { - this->close_trigger_->trigger(); - this->prev_command_trigger_ = this->close_trigger_; + this->close_trigger_.trigger(); + this->prev_command_trigger_ = &this->close_trigger_; } else { - this->position_trigger_->trigger(pos); + this->position_trigger_.trigger(pos); } if (this->optimistic_) { @@ -101,7 +95,7 @@ void TemplateCover::control(const CoverCall &call) { if (call.get_tilt().has_value()) { auto tilt = *call.get_tilt(); - this->tilt_trigger_->trigger(tilt); + this->tilt_trigger_.trigger(tilt); if (this->optimistic_) { this->tilt = tilt; @@ -119,8 +113,8 @@ CoverTraits TemplateCover::get_traits() { traits.set_supports_tilt(this->has_tilt_); return traits; } -Trigger *TemplateCover::get_position_trigger() const { return this->position_trigger_; } -Trigger *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; } +Trigger *TemplateCover::get_position_trigger() { return &this->position_trigger_; } +Trigger *TemplateCover::get_tilt_trigger() { return &this->tilt_trigger_; } void TemplateCover::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } void TemplateCover::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } void TemplateCover::set_has_position(bool has_position) { this->has_position_ = has_position; } diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 9c4a787283..20c092cda7 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -19,12 +19,12 @@ class TemplateCover final : public cover::Cover, public Component { template void set_state_lambda(F &&f) { this->state_f_.set(std::forward(f)); } template void set_tilt_lambda(F &&f) { this->tilt_f_.set(std::forward(f)); } - Trigger<> *get_open_trigger() const; - Trigger<> *get_close_trigger() const; - Trigger<> *get_stop_trigger() const; - Trigger<> *get_toggle_trigger() const; - Trigger *get_position_trigger() const; - Trigger *get_tilt_trigger() const; + Trigger<> *get_open_trigger(); + Trigger<> *get_close_trigger(); + Trigger<> *get_stop_trigger(); + Trigger<> *get_toggle_trigger(); + Trigger *get_position_trigger(); + Trigger *get_tilt_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void set_has_stop(bool has_stop); @@ -49,16 +49,16 @@ class TemplateCover final : public cover::Cover, public Component { TemplateLambda tilt_f_; bool assumed_state_{false}; bool optimistic_{false}; - Trigger<> *open_trigger_; - Trigger<> *close_trigger_; + Trigger<> open_trigger_; + Trigger<> close_trigger_; bool has_stop_{false}; bool has_toggle_{false}; - Trigger<> *stop_trigger_; - Trigger<> *toggle_trigger_; + Trigger<> stop_trigger_; + Trigger<> toggle_trigger_; Trigger<> *prev_command_trigger_{nullptr}; - Trigger *position_trigger_; + Trigger position_trigger_; bool has_position_{false}; - Trigger *tilt_trigger_; + Trigger tilt_trigger_; bool has_tilt_{false}; }; From 7d717a78dc0f68cfd6d47135dfa896ec65021e86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:21 +0100 Subject: [PATCH 0450/2030] [template] Avoid heap allocation for number set trigger (#13694) --- esphome/components/template/number/template_number.cpp | 2 +- esphome/components/template/number/template_number.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/template/number/template_number.cpp b/esphome/components/template/number/template_number.cpp index 885265cf5d..64c2deb281 100644 --- a/esphome/components/template/number/template_number.cpp +++ b/esphome/components/template/number/template_number.cpp @@ -36,7 +36,7 @@ void TemplateNumber::update() { } void TemplateNumber::control(float value) { - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) this->publish_state(value); diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index 42c27fc3ca..e51e858ccf 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -17,7 +17,7 @@ class TemplateNumber final : public number::Number, public PollingComponent { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { optimistic_ = optimistic; } void set_initial_value(float initial_value) { initial_value_ = initial_value; } void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } @@ -27,7 +27,7 @@ class TemplateNumber final : public number::Number, public PollingComponent { bool optimistic_{false}; float initial_value_{NAN}; bool restore_value_{false}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_; ESPPreferenceObject pref_; From e420964b939b78edd7475d7ad89eaeef37f22020 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:34 +0100 Subject: [PATCH 0451/2030] [template.switch] Avoid heap allocation for triggers (#13691) --- .../components/template/switch/template_switch.cpp | 14 +++++++------- .../components/template/switch/template_switch.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/esphome/components/template/switch/template_switch.cpp b/esphome/components/template/switch/template_switch.cpp index cfa8798e75..05288b2d4e 100644 --- a/esphome/components/template/switch/template_switch.cpp +++ b/esphome/components/template/switch/template_switch.cpp @@ -5,7 +5,7 @@ namespace esphome::template_ { static const char *const TAG = "template.switch"; -TemplateSwitch::TemplateSwitch() : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {} +TemplateSwitch::TemplateSwitch() = default; void TemplateSwitch::loop() { auto s = this->f_(); @@ -19,11 +19,11 @@ void TemplateSwitch::write_state(bool state) { } if (state) { - this->prev_trigger_ = this->turn_on_trigger_; - this->turn_on_trigger_->trigger(); + this->prev_trigger_ = &this->turn_on_trigger_; + this->turn_on_trigger_.trigger(); } else { - this->prev_trigger_ = this->turn_off_trigger_; - this->turn_off_trigger_->trigger(); + this->prev_trigger_ = &this->turn_off_trigger_; + this->turn_off_trigger_.trigger(); } if (this->optimistic_) @@ -32,8 +32,8 @@ void TemplateSwitch::write_state(bool state) { void TemplateSwitch::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } bool TemplateSwitch::assumed_state() { return this->assumed_state_; } float TemplateSwitch::get_setup_priority() const { return setup_priority::HARDWARE - 2.0f; } -Trigger<> *TemplateSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; } -Trigger<> *TemplateSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; } +Trigger<> *TemplateSwitch::get_turn_on_trigger() { return &this->turn_on_trigger_; } +Trigger<> *TemplateSwitch::get_turn_off_trigger() { return &this->turn_off_trigger_; } void TemplateSwitch::setup() { if (!this->f_.has_value()) this->disable_loop(); diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index 91b7b396f6..1714b4f72b 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -15,8 +15,8 @@ class TemplateSwitch final : public switch_::Switch, public Component { void dump_config() override; template void set_state_lambda(F &&f) { this->f_.set(std::forward(f)); } - Trigger<> *get_turn_on_trigger() const; - Trigger<> *get_turn_off_trigger() const; + Trigger<> *get_turn_on_trigger(); + Trigger<> *get_turn_off_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void loop() override; @@ -31,9 +31,9 @@ class TemplateSwitch final : public switch_::Switch, public Component { TemplateLambda f_; bool optimistic_{false}; bool assumed_state_{false}; - Trigger<> *turn_on_trigger_; - Trigger<> *turn_off_trigger_; - Trigger<> *prev_trigger_{nullptr}; + Trigger<> turn_on_trigger_; + Trigger<> turn_off_trigger_; + Trigger<> *prev_trigger_{nullptr}; // Points to one of the above }; } // namespace esphome::template_ From 4ab552d7504fb2070b3b7eb58ae9eafe7e8c32ec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:49 +0100 Subject: [PATCH 0452/2030] [http_request] Avoid heap allocation for triggers (#13690) --- .../components/http_request/http_request.h | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index fb39ca504c..79098a6b72 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -332,13 +332,13 @@ template class HttpRequestSendAction : public Action { void set_json(std::function json_func) { this->json_func_ = json_func; } #ifdef USE_HTTP_REQUEST_RESPONSE - Trigger, std::string &, Ts...> *get_success_trigger_with_response() const { - return this->success_trigger_with_response_; + Trigger, std::string &, Ts...> *get_success_trigger_with_response() { + return &this->success_trigger_with_response_; } #endif - Trigger, Ts...> *get_success_trigger() const { return this->success_trigger_; } + Trigger, Ts...> *get_success_trigger() { return &this->success_trigger_; } - Trigger *get_error_trigger() const { return this->error_trigger_; } + Trigger *get_error_trigger() { return &this->error_trigger_; } void set_max_response_buffer_size(size_t max_response_buffer_size) { this->max_response_buffer_size_ = max_response_buffer_size; @@ -372,7 +372,7 @@ template class HttpRequestSendAction : public Action { auto captured_args = std::make_tuple(x...); if (container == nullptr) { - std::apply([this](Ts... captured_args_inner) { this->error_trigger_->trigger(captured_args_inner...); }, + std::apply([this](Ts... captured_args_inner) { this->error_trigger_.trigger(captured_args_inner...); }, captured_args); return; } @@ -406,14 +406,14 @@ template class HttpRequestSendAction : public Action { } std::apply( [this, &container, &response_body](Ts... captured_args_inner) { - this->success_trigger_with_response_->trigger(container, response_body, captured_args_inner...); + this->success_trigger_with_response_.trigger(container, response_body, captured_args_inner...); }, captured_args); } else #endif { std::apply([this, &container]( - Ts... captured_args_inner) { this->success_trigger_->trigger(container, captured_args_inner...); }, + Ts... captured_args_inner) { this->success_trigger_.trigger(container, captured_args_inner...); }, captured_args); } container->end(); @@ -433,12 +433,10 @@ template class HttpRequestSendAction : public Action { std::map> json_{}; std::function json_func_{nullptr}; #ifdef USE_HTTP_REQUEST_RESPONSE - Trigger, std::string &, Ts...> *success_trigger_with_response_ = - new Trigger, std::string &, Ts...>(); + Trigger, std::string &, Ts...> success_trigger_with_response_; #endif - Trigger, Ts...> *success_trigger_ = - new Trigger, Ts...>(); - Trigger *error_trigger_ = new Trigger(); + Trigger, Ts...> success_trigger_; + Trigger error_trigger_; size_t max_response_buffer_size_{SIZE_MAX}; }; From 652c02b9abfacf6b1ad3d161948e8b9ccaf57ae1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:49:46 +0100 Subject: [PATCH 0453/2030] [bang_bang] Avoid heap allocation for climate triggers (#13701) --- .../components/bang_bang/bang_bang_climate.cpp | 15 +++++++-------- esphome/components/bang_bang/bang_bang_climate.h | 16 ++++++---------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/esphome/components/bang_bang/bang_bang_climate.cpp b/esphome/components/bang_bang/bang_bang_climate.cpp index f26377a38a..6871e9df5d 100644 --- a/esphome/components/bang_bang/bang_bang_climate.cpp +++ b/esphome/components/bang_bang/bang_bang_climate.cpp @@ -6,8 +6,7 @@ namespace bang_bang { static const char *const TAG = "bang_bang.climate"; -BangBangClimate::BangBangClimate() - : idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {} +BangBangClimate::BangBangClimate() = default; void BangBangClimate::setup() { this->sensor_->add_on_state_callback([this](float state) { @@ -160,13 +159,13 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) { switch (action) { case climate::CLIMATE_ACTION_OFF: case climate::CLIMATE_ACTION_IDLE: - trig = this->idle_trigger_; + trig = &this->idle_trigger_; break; case climate::CLIMATE_ACTION_COOLING: - trig = this->cool_trigger_; + trig = &this->cool_trigger_; break; case climate::CLIMATE_ACTION_HEATING: - trig = this->heat_trigger_; + trig = &this->heat_trigger_; break; default: trig = nullptr; @@ -204,9 +203,9 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; } void BangBangClimate::set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } -Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; } -Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; } -Trigger<> *BangBangClimate::get_heat_trigger() const { return this->heat_trigger_; } +Trigger<> *BangBangClimate::get_idle_trigger() { return &this->idle_trigger_; } +Trigger<> *BangBangClimate::get_cool_trigger() { return &this->cool_trigger_; } +Trigger<> *BangBangClimate::get_heat_trigger() { return &this->heat_trigger_; } void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; } void BangBangClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; } diff --git a/esphome/components/bang_bang/bang_bang_climate.h b/esphome/components/bang_bang/bang_bang_climate.h index 2e7da93a07..d0ddef2848 100644 --- a/esphome/components/bang_bang/bang_bang_climate.h +++ b/esphome/components/bang_bang/bang_bang_climate.h @@ -30,9 +30,9 @@ class BangBangClimate : public climate::Climate, public Component { void set_normal_config(const BangBangClimateTargetTempConfig &normal_config); void set_away_config(const BangBangClimateTargetTempConfig &away_config); - Trigger<> *get_idle_trigger() const; - Trigger<> *get_cool_trigger() const; - Trigger<> *get_heat_trigger() const; + Trigger<> *get_idle_trigger(); + Trigger<> *get_cool_trigger(); + Trigger<> *get_heat_trigger(); protected: /// Override control to change settings of the climate device. @@ -57,17 +57,13 @@ class BangBangClimate : public climate::Climate, public Component { * * In idle mode, the controller is assumed to have both heating and cooling disabled. */ - Trigger<> *idle_trigger_{nullptr}; + Trigger<> idle_trigger_; /** The trigger to call when the controller should switch to cooling mode. */ - Trigger<> *cool_trigger_{nullptr}; + Trigger<> cool_trigger_; /** The trigger to call when the controller should switch to heating mode. - * - * A null value for this attribute means that the controller has no heating action - * For example window blinds, where only cooling (blinds closed) and not-cooling - * (blinds open) is possible. */ - Trigger<> *heat_trigger_{nullptr}; + Trigger<> heat_trigger_; /** A reference to the trigger that was previously active. * * This is so that the previous trigger can be stopped before enabling a new one. From 8791c24072da87ac2067f3b68e489cd8e83ed0f9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:50:01 +0100 Subject: [PATCH 0454/2030] [api] Avoid heap allocation for client connected/disconnected triggers (#13688) --- esphome/components/api/api_server.cpp | 2 +- esphome/components/api/api_server.h | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index ed97c3b9a2..c56449455d 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -211,7 +211,7 @@ void APIServer::loop() { #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER // Fire trigger after client is removed so api.connected reflects the true state - this->client_disconnected_trigger_->trigger(client_name, client_peername); + this->client_disconnected_trigger_.trigger(client_name, client_peername); #endif // Don't increment client_index since we need to process the swapped element } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 93421ef801..6ab3cdc576 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -227,12 +227,10 @@ class APIServer : public Component, #endif #ifdef USE_API_CLIENT_CONNECTED_TRIGGER - Trigger *get_client_connected_trigger() const { return this->client_connected_trigger_; } + Trigger *get_client_connected_trigger() { return &this->client_connected_trigger_; } #endif #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - Trigger *get_client_disconnected_trigger() const { - return this->client_disconnected_trigger_; - } + Trigger *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; } #endif protected: @@ -253,10 +251,10 @@ class APIServer : public Component, // Pointers and pointer-like types first (4 bytes each) std::unique_ptr socket_ = nullptr; #ifdef USE_API_CLIENT_CONNECTED_TRIGGER - Trigger *client_connected_trigger_ = new Trigger(); + Trigger client_connected_trigger_; #endif #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - Trigger *client_disconnected_trigger_ = new Trigger(); + Trigger client_disconnected_trigger_; #endif // 4-byte aligned types From 09b76d5e4a4405dbf9fe2f7ffb0a93af544dcc83 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:50:16 +0100 Subject: [PATCH 0455/2030] [voice_assistant] Avoid heap allocation for triggers (#13689) --- .../voice_assistant/voice_assistant.cpp | 58 ++++++------ .../voice_assistant/voice_assistant.h | 92 +++++++++---------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index e2516d5fb8..7f5fbe62e1 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -197,7 +197,7 @@ void VoiceAssistant::loop() { switch (this->state_) { case State::IDLE: { if (this->continuous_ && this->desired_state_ == State::IDLE) { - this->idle_trigger_->trigger(); + this->idle_trigger_.trigger(); this->set_state_(State::START_MICROPHONE, State::START_PIPELINE); } else { this->deallocate_buffers_(); @@ -254,7 +254,7 @@ void VoiceAssistant::loop() { if (this->api_client_ == nullptr || !this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) { ESP_LOGW(TAG, "Could not request start"); - this->error_trigger_->trigger("not-connected", "Could not request start"); + this->error_trigger_.trigger("not-connected", "Could not request start"); this->continuous_ = false; this->set_state_(State::IDLE, State::IDLE); break; @@ -384,7 +384,7 @@ void VoiceAssistant::loop() { this->wait_for_stream_end_ = false; this->stream_ended_ = false; - this->tts_stream_end_trigger_->trigger(); + this->tts_stream_end_trigger_.trigger(); } #endif if (this->continue_conversation_) { @@ -425,7 +425,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr return; } this->api_client_ = nullptr; - this->client_disconnected_trigger_->trigger(); + this->client_disconnected_trigger_.trigger(); return; } @@ -440,7 +440,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr } this->api_client_ = client; - this->client_connected_trigger_->trigger(); + this->client_connected_trigger_.trigger(); } static const LogString *voice_assistant_state_to_string(State state) { @@ -491,7 +491,7 @@ void VoiceAssistant::set_state_(State state, State desired_state) { void VoiceAssistant::failed_to_start() { ESP_LOGE(TAG, "Failed to start server. See Home Assistant logs for more details."); - this->error_trigger_->trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details."); + this->error_trigger_.trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details."); this->set_state_(State::STOP_MICROPHONE, State::IDLE); } @@ -637,18 +637,18 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } } #endif - this->defer([this]() { this->start_trigger_->trigger(); }); + this->defer([this]() { this->start_trigger_.trigger(); }); break; case api::enums::VOICE_ASSISTANT_WAKE_WORD_START: break; case api::enums::VOICE_ASSISTANT_WAKE_WORD_END: { ESP_LOGD(TAG, "Wake word detected"); - this->defer([this]() { this->wake_word_detected_trigger_->trigger(); }); + this->defer([this]() { this->wake_word_detected_trigger_.trigger(); }); break; } case api::enums::VOICE_ASSISTANT_STT_START: ESP_LOGD(TAG, "STT started"); - this->defer([this]() { this->listening_trigger_->trigger(); }); + this->defer([this]() { this->listening_trigger_.trigger(); }); break; case api::enums::VOICE_ASSISTANT_STT_END: { std::string text; @@ -665,12 +665,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { text += "..."; } ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str()); - this->defer([this, text]() { this->stt_end_trigger_->trigger(text); }); + this->defer([this, text]() { this->stt_end_trigger_.trigger(text); }); break; } case api::enums::VOICE_ASSISTANT_INTENT_START: ESP_LOGD(TAG, "Intent started"); - this->defer([this]() { this->intent_start_trigger_->trigger(); }); + this->defer([this]() { this->intent_start_trigger_.trigger(); }); break; case api::enums::VOICE_ASSISTANT_INTENT_PROGRESS: { ESP_LOGD(TAG, "Intent progress"); @@ -693,7 +693,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } } #endif - this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_->trigger(tts_url_for_trigger); }); + this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_.trigger(tts_url_for_trigger); }); break; } case api::enums::VOICE_ASSISTANT_INTENT_END: { @@ -704,7 +704,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->continue_conversation_ = (arg.value == "1"); } } - this->defer([this]() { this->intent_end_trigger_->trigger(); }); + this->defer([this]() { this->intent_end_trigger_.trigger(); }); break; } case api::enums::VOICE_ASSISTANT_TTS_START: { @@ -724,7 +724,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } ESP_LOGD(TAG, "Response: \"%s\"", text.c_str()); this->defer([this, text]() { - this->tts_start_trigger_->trigger(text); + this->tts_start_trigger_.trigger(text); #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { this->speaker_->start(); @@ -756,7 +756,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } this->started_streaming_tts_ = false; // Helps indicate reaching the TTS_END stage #endif - this->tts_end_trigger_->trigger(url); + this->tts_end_trigger_.trigger(url); }); State new_state = this->local_output_ ? State::STREAMING_RESPONSE : State::IDLE; if (new_state != this->state_) { @@ -776,7 +776,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { // No TTS start event ("nevermind") this->set_state_(State::IDLE, State::IDLE); } - this->defer([this]() { this->end_trigger_->trigger(); }); + this->defer([this]() { this->end_trigger_.trigger(); }); break; } case api::enums::VOICE_ASSISTANT_ERROR: { @@ -796,7 +796,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { // Wake word is not set up or not ready on Home Assistant so stop and do not retry until user starts again. this->defer([this, code, message]() { this->request_stop(); - this->error_trigger_->trigger(code, message); + this->error_trigger_.trigger(code, message); }); return; } @@ -805,7 +805,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { this->signal_stop_(); this->set_state_(State::STOP_MICROPHONE, State::IDLE); } - this->defer([this, code, message]() { this->error_trigger_->trigger(code, message); }); + this->defer([this, code, message]() { this->error_trigger_.trigger(code, message); }); break; } case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: { @@ -813,7 +813,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { if (this->speaker_ != nullptr) { this->wait_for_stream_end_ = true; ESP_LOGD(TAG, "TTS stream start"); - this->defer([this] { this->tts_stream_start_trigger_->trigger(); }); + this->defer([this] { this->tts_stream_start_trigger_.trigger(); }); } #endif break; @@ -829,12 +829,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) { } case api::enums::VOICE_ASSISTANT_STT_VAD_START: ESP_LOGD(TAG, "Starting STT by VAD"); - this->defer([this]() { this->stt_vad_start_trigger_->trigger(); }); + this->defer([this]() { this->stt_vad_start_trigger_.trigger(); }); break; case api::enums::VOICE_ASSISTANT_STT_VAD_END: ESP_LOGD(TAG, "STT by VAD end"); this->set_state_(State::STOP_MICROPHONE, State::AWAITING_RESPONSE); - this->defer([this]() { this->stt_vad_end_trigger_->trigger(); }); + this->defer([this]() { this->stt_vad_end_trigger_.trigger(); }); break; default: ESP_LOGD(TAG, "Unhandled event type: %" PRId32, msg.event_type); @@ -876,17 +876,17 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_TIMER_STARTED: - this->timer_started_trigger_->trigger(timer); + this->timer_started_trigger_.trigger(timer); break; case api::enums::VOICE_ASSISTANT_TIMER_UPDATED: - this->timer_updated_trigger_->trigger(timer); + this->timer_updated_trigger_.trigger(timer); break; case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED: - this->timer_cancelled_trigger_->trigger(timer); + this->timer_cancelled_trigger_.trigger(timer); this->timers_.erase(timer.id); break; case api::enums::VOICE_ASSISTANT_TIMER_FINISHED: - this->timer_finished_trigger_->trigger(timer); + this->timer_finished_trigger_.trigger(timer); this->timers_.erase(timer.id); break; } @@ -910,13 +910,13 @@ void VoiceAssistant::timer_tick_() { } res.push_back(timer); } - this->timer_tick_trigger_->trigger(res); + this->timer_tick_trigger_.trigger(res); } void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) { #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - this->tts_start_trigger_->trigger(msg.text); + this->tts_start_trigger_.trigger(msg.text); this->media_player_response_state_ = MediaPlayerResponseState::URL_SENT; @@ -939,8 +939,8 @@ void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE); } - this->tts_end_trigger_->trigger(msg.media_id); - this->end_trigger_->trigger(); + this->tts_end_trigger_.trigger(msg.media_id); + this->end_trigger_.trigger(); } #endif } diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index d61a8fbbc1..2a5f3a55a7 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -195,38 +195,38 @@ class VoiceAssistant : public Component { void set_conversation_timeout(uint32_t conversation_timeout) { this->conversation_timeout_ = conversation_timeout; } void reset_conversation_id(); - Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; } - Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; } - Trigger *get_intent_progress_trigger() const { return this->intent_progress_trigger_; } - Trigger<> *get_listening_trigger() const { return this->listening_trigger_; } - Trigger<> *get_end_trigger() const { return this->end_trigger_; } - Trigger<> *get_start_trigger() const { return this->start_trigger_; } - Trigger<> *get_stt_vad_end_trigger() const { return this->stt_vad_end_trigger_; } - Trigger<> *get_stt_vad_start_trigger() const { return this->stt_vad_start_trigger_; } + Trigger<> *get_intent_end_trigger() { return &this->intent_end_trigger_; } + Trigger<> *get_intent_start_trigger() { return &this->intent_start_trigger_; } + Trigger *get_intent_progress_trigger() { return &this->intent_progress_trigger_; } + Trigger<> *get_listening_trigger() { return &this->listening_trigger_; } + Trigger<> *get_end_trigger() { return &this->end_trigger_; } + Trigger<> *get_start_trigger() { return &this->start_trigger_; } + Trigger<> *get_stt_vad_end_trigger() { return &this->stt_vad_end_trigger_; } + Trigger<> *get_stt_vad_start_trigger() { return &this->stt_vad_start_trigger_; } #ifdef USE_SPEAKER - Trigger<> *get_tts_stream_start_trigger() const { return this->tts_stream_start_trigger_; } - Trigger<> *get_tts_stream_end_trigger() const { return this->tts_stream_end_trigger_; } + Trigger<> *get_tts_stream_start_trigger() { return &this->tts_stream_start_trigger_; } + Trigger<> *get_tts_stream_end_trigger() { return &this->tts_stream_end_trigger_; } #endif - Trigger<> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; } - Trigger *get_stt_end_trigger() const { return this->stt_end_trigger_; } - Trigger *get_tts_end_trigger() const { return this->tts_end_trigger_; } - Trigger *get_tts_start_trigger() const { return this->tts_start_trigger_; } - Trigger *get_error_trigger() const { return this->error_trigger_; } - Trigger<> *get_idle_trigger() const { return this->idle_trigger_; } + Trigger<> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; } + Trigger *get_stt_end_trigger() { return &this->stt_end_trigger_; } + Trigger *get_tts_end_trigger() { return &this->tts_end_trigger_; } + Trigger *get_tts_start_trigger() { return &this->tts_start_trigger_; } + Trigger *get_error_trigger() { return &this->error_trigger_; } + Trigger<> *get_idle_trigger() { return &this->idle_trigger_; } - Trigger<> *get_client_connected_trigger() const { return this->client_connected_trigger_; } - Trigger<> *get_client_disconnected_trigger() const { return this->client_disconnected_trigger_; } + Trigger<> *get_client_connected_trigger() { return &this->client_connected_trigger_; } + Trigger<> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; } void client_subscription(api::APIConnection *client, bool subscribe); api::APIConnection *get_api_connection() const { return this->api_client_; } void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; } - Trigger *get_timer_started_trigger() const { return this->timer_started_trigger_; } - Trigger *get_timer_updated_trigger() const { return this->timer_updated_trigger_; } - Trigger *get_timer_cancelled_trigger() const { return this->timer_cancelled_trigger_; } - Trigger *get_timer_finished_trigger() const { return this->timer_finished_trigger_; } - Trigger> *get_timer_tick_trigger() const { return this->timer_tick_trigger_; } + Trigger *get_timer_started_trigger() { return &this->timer_started_trigger_; } + Trigger *get_timer_updated_trigger() { return &this->timer_updated_trigger_; } + Trigger *get_timer_cancelled_trigger() { return &this->timer_cancelled_trigger_; } + Trigger *get_timer_finished_trigger() { return &this->timer_finished_trigger_; } + Trigger> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; } void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; } const std::unordered_map &get_timers() const { return this->timers_; } @@ -243,37 +243,37 @@ class VoiceAssistant : public Component { std::unique_ptr socket_ = nullptr; struct sockaddr_storage dest_addr_; - Trigger<> *intent_end_trigger_ = new Trigger<>(); - Trigger<> *intent_start_trigger_ = new Trigger<>(); - Trigger<> *listening_trigger_ = new Trigger<>(); - Trigger<> *end_trigger_ = new Trigger<>(); - Trigger<> *start_trigger_ = new Trigger<>(); - Trigger<> *stt_vad_start_trigger_ = new Trigger<>(); - Trigger<> *stt_vad_end_trigger_ = new Trigger<>(); + Trigger<> intent_end_trigger_; + Trigger<> intent_start_trigger_; + Trigger<> listening_trigger_; + Trigger<> end_trigger_; + Trigger<> start_trigger_; + Trigger<> stt_vad_start_trigger_; + Trigger<> stt_vad_end_trigger_; #ifdef USE_SPEAKER - Trigger<> *tts_stream_start_trigger_ = new Trigger<>(); - Trigger<> *tts_stream_end_trigger_ = new Trigger<>(); + Trigger<> tts_stream_start_trigger_; + Trigger<> tts_stream_end_trigger_; #endif - Trigger *intent_progress_trigger_ = new Trigger(); - Trigger<> *wake_word_detected_trigger_ = new Trigger<>(); - Trigger *stt_end_trigger_ = new Trigger(); - Trigger *tts_end_trigger_ = new Trigger(); - Trigger *tts_start_trigger_ = new Trigger(); - Trigger *error_trigger_ = new Trigger(); - Trigger<> *idle_trigger_ = new Trigger<>(); + Trigger intent_progress_trigger_; + Trigger<> wake_word_detected_trigger_; + Trigger stt_end_trigger_; + Trigger tts_end_trigger_; + Trigger tts_start_trigger_; + Trigger error_trigger_; + Trigger<> idle_trigger_; - Trigger<> *client_connected_trigger_ = new Trigger<>(); - Trigger<> *client_disconnected_trigger_ = new Trigger<>(); + Trigger<> client_connected_trigger_; + Trigger<> client_disconnected_trigger_; api::APIConnection *api_client_{nullptr}; std::unordered_map timers_; void timer_tick_(); - Trigger *timer_started_trigger_ = new Trigger(); - Trigger *timer_finished_trigger_ = new Trigger(); - Trigger *timer_updated_trigger_ = new Trigger(); - Trigger *timer_cancelled_trigger_ = new Trigger(); - Trigger> *timer_tick_trigger_ = new Trigger>(); + Trigger timer_started_trigger_; + Trigger timer_finished_trigger_; + Trigger timer_updated_trigger_; + Trigger timer_cancelled_trigger_; + Trigger> timer_tick_trigger_; bool has_timers_{false}; bool timer_tick_running_{false}; From 18c152723c1b607fba022b0b0d1d702cdf5020cf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:53:46 +0100 Subject: [PATCH 0456/2030] [sprinkler] Avoid heap allocation for triggers (#13705) --- esphome/components/sprinkler/sprinkler.cpp | 16 ++++++---------- esphome/components/sprinkler/sprinkler.h | 12 ++++++------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 2a60eb042b..eae6ecbf31 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -29,7 +29,7 @@ void SprinklerControllerNumber::setup() { } void SprinklerControllerNumber::control(float value) { - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); this->publish_state(value); @@ -39,8 +39,7 @@ void SprinklerControllerNumber::control(float value) { void SprinklerControllerNumber::dump_config() { LOG_NUMBER("", "Sprinkler Controller Number", this); } -SprinklerControllerSwitch::SprinklerControllerSwitch() - : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {} +SprinklerControllerSwitch::SprinklerControllerSwitch() = default; void SprinklerControllerSwitch::loop() { // Loop is only enabled when f_ has a value (see setup()) @@ -56,11 +55,11 @@ void SprinklerControllerSwitch::write_state(bool state) { } if (state) { - this->prev_trigger_ = this->turn_on_trigger_; - this->turn_on_trigger_->trigger(); + this->prev_trigger_ = &this->turn_on_trigger_; + this->turn_on_trigger_.trigger(); } else { - this->prev_trigger_ = this->turn_off_trigger_; - this->turn_off_trigger_->trigger(); + this->prev_trigger_ = &this->turn_off_trigger_; + this->turn_off_trigger_.trigger(); } this->publish_state(state); @@ -69,9 +68,6 @@ void SprinklerControllerSwitch::write_state(bool state) { void SprinklerControllerSwitch::set_state_lambda(std::function()> &&f) { this->f_ = f; } float SprinklerControllerSwitch::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *SprinklerControllerSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; } -Trigger<> *SprinklerControllerSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; } - void SprinklerControllerSwitch::setup() { this->state = this->get_initial_state_with_restore_mode().value_or(false); // Disable loop if no state lambda is set - nothing to poll diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index 04efa28031..a3cdef5b1a 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -76,7 +76,7 @@ class SprinklerControllerNumber : public number::Number, public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::PROCESSOR; } - Trigger *get_set_trigger() const { return set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_initial_value(float initial_value) { initial_value_ = initial_value; } void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } @@ -84,7 +84,7 @@ class SprinklerControllerNumber : public number::Number, public Component { void control(float value) override; float initial_value_{NAN}; bool restore_value_{true}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; ESPPreferenceObject pref_; }; @@ -97,8 +97,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component { void dump_config() override; void set_state_lambda(std::function()> &&f); - Trigger<> *get_turn_on_trigger() const; - Trigger<> *get_turn_off_trigger() const; + Trigger<> *get_turn_on_trigger() { return &this->turn_on_trigger_; } + Trigger<> *get_turn_off_trigger() { return &this->turn_off_trigger_; } void loop() override; float get_setup_priority() const override; @@ -107,8 +107,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component { void write_state(bool state) override; optional()>> f_; - Trigger<> *turn_on_trigger_; - Trigger<> *turn_off_trigger_; + Trigger<> turn_on_trigger_; + Trigger<> turn_off_trigger_; Trigger<> *prev_trigger_{nullptr}; }; From 379652f63107cc8b14e6994788e78d0582944b53 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:10:08 +0100 Subject: [PATCH 0457/2030] [thermostat] Remove dead null checks for triggers (#13706) --- .../thermostat/thermostat_climate.cpp | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 02e01db549..c666419701 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -586,9 +586,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } this->action = action; this->prev_action_trigger_ = trig; - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); // if enabled, call the fan_only action with cooling/heating actions if (trig_fan != nullptr) { ESP_LOGVV(TAG, "Calling FAN_ONLY action with HEATING/COOLING action"); @@ -686,9 +684,7 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction } this->humidification_action = action; this->prev_humidity_control_trigger_ = trig; - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); } void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bool publish_state) { @@ -756,9 +752,7 @@ void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bo this->prev_fan_mode_trigger_ = nullptr; } this->start_timer_(thermostat::THERMOSTAT_TIMER_FAN_MODE); - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->prev_fan_mode_ = fan_mode; this->prev_fan_mode_trigger_ = trig; } @@ -802,9 +796,7 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_ mode = climate::CLIMATE_MODE_OFF; // trig = this->off_mode_trigger_; } - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->mode = mode; this->prev_mode_ = mode; this->prev_mode_trigger_ = trig; @@ -844,9 +836,7 @@ void ThermostatClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mo swing_mode = climate::CLIMATE_SWING_OFF; // trig = &this->swing_mode_off_trigger_; } - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->swing_mode = swing_mode; this->prev_swing_mode_ = swing_mode; this->prev_swing_mode_trigger_ = trig; From f0801ecac01779cc78000fdb144e7bfd82623c40 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:14:11 +0100 Subject: [PATCH 0458/2030] [template.lock] Avoid heap allocation for triggers (#13704) --- .../components/template/lock/template_lock.cpp | 18 +++++++----------- .../components/template/lock/template_lock.h | 12 ++++++------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/esphome/components/template/lock/template_lock.cpp b/esphome/components/template/lock/template_lock.cpp index de8f9b762c..dbc4501ce7 100644 --- a/esphome/components/template/lock/template_lock.cpp +++ b/esphome/components/template/lock/template_lock.cpp @@ -7,8 +7,7 @@ using namespace esphome::lock; static const char *const TAG = "template.lock"; -TemplateLock::TemplateLock() - : lock_trigger_(new Trigger<>()), unlock_trigger_(new Trigger<>()), open_trigger_(new Trigger<>()) {} +TemplateLock::TemplateLock() = default; void TemplateLock::setup() { if (!this->f_.has_value()) @@ -28,11 +27,11 @@ void TemplateLock::control(const lock::LockCall &call) { auto state = *call.get_state(); if (state == LOCK_STATE_LOCKED) { - this->prev_trigger_ = this->lock_trigger_; - this->lock_trigger_->trigger(); + this->prev_trigger_ = &this->lock_trigger_; + this->lock_trigger_.trigger(); } else if (state == LOCK_STATE_UNLOCKED) { - this->prev_trigger_ = this->unlock_trigger_; - this->unlock_trigger_->trigger(); + this->prev_trigger_ = &this->unlock_trigger_; + this->unlock_trigger_.trigger(); } if (this->optimistic_) @@ -42,14 +41,11 @@ void TemplateLock::open_latch() { if (this->prev_trigger_ != nullptr) { this->prev_trigger_->stop_action(); } - this->prev_trigger_ = this->open_trigger_; - this->open_trigger_->trigger(); + this->prev_trigger_ = &this->open_trigger_; + this->open_trigger_.trigger(); } void TemplateLock::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } float TemplateLock::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *TemplateLock::get_lock_trigger() const { return this->lock_trigger_; } -Trigger<> *TemplateLock::get_unlock_trigger() const { return this->unlock_trigger_; } -Trigger<> *TemplateLock::get_open_trigger() const { return this->open_trigger_; } void TemplateLock::dump_config() { LOG_LOCK("", "Template Lock", this); ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_)); diff --git a/esphome/components/template/lock/template_lock.h b/esphome/components/template/lock/template_lock.h index f4396c2c5d..03e3e86d88 100644 --- a/esphome/components/template/lock/template_lock.h +++ b/esphome/components/template/lock/template_lock.h @@ -15,9 +15,9 @@ class TemplateLock final : public lock::Lock, public Component { void dump_config() override; template void set_state_lambda(F &&f) { this->f_.set(std::forward(f)); } - Trigger<> *get_lock_trigger() const; - Trigger<> *get_unlock_trigger() const; - Trigger<> *get_open_trigger() const; + Trigger<> *get_lock_trigger() { return &this->lock_trigger_; } + Trigger<> *get_unlock_trigger() { return &this->unlock_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } void set_optimistic(bool optimistic); void loop() override; @@ -29,9 +29,9 @@ class TemplateLock final : public lock::Lock, public Component { TemplateLambda f_; bool optimistic_{false}; - Trigger<> *lock_trigger_; - Trigger<> *unlock_trigger_; - Trigger<> *open_trigger_; + Trigger<> lock_trigger_; + Trigger<> unlock_trigger_; + Trigger<> open_trigger_; Trigger<> *prev_trigger_{nullptr}; }; From dbd740172192f2d2acefb9cf883f2e544e174abe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:15:13 +0100 Subject: [PATCH 0459/2030] [feedback] Avoid heap allocation for cover triggers (#13693) --- esphome/components/feedback/feedback_cover.cpp | 6 +++--- esphome/components/feedback/feedback_cover.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/feedback/feedback_cover.cpp b/esphome/components/feedback/feedback_cover.cpp index e419ee6229..ffb19fa091 100644 --- a/esphome/components/feedback/feedback_cover.cpp +++ b/esphome/components/feedback/feedback_cover.cpp @@ -335,18 +335,18 @@ void FeedbackCover::start_direction_(CoverOperation dir) { switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; #ifdef USE_BINARY_SENSOR obstacle = this->open_obstacle_; #endif break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; #ifdef USE_BINARY_SENSOR obstacle = this->close_obstacle_; #endif diff --git a/esphome/components/feedback/feedback_cover.h b/esphome/components/feedback/feedback_cover.h index 199d3b520a..6be8939413 100644 --- a/esphome/components/feedback/feedback_cover.h +++ b/esphome/components/feedback/feedback_cover.h @@ -17,9 +17,9 @@ class FeedbackCover : public cover::Cover, public Component { void loop() override; void dump_config() override; - Trigger<> *get_open_trigger() const { return this->open_trigger_; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } #ifdef USE_BINARY_SENSOR void set_open_endstop(binary_sensor::BinarySensor *open_endstop); @@ -61,9 +61,9 @@ class FeedbackCover : public cover::Cover, public Component { binary_sensor::BinarySensor *close_obstacle_{nullptr}; #endif - Trigger<> *open_trigger_{new Trigger<>()}; - Trigger<> *close_trigger_{new Trigger<>()}; - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; + Trigger<> close_trigger_; + Trigger<> stop_trigger_; uint32_t open_duration_{0}; uint32_t close_duration_{0}; From 1362ff6cba18351ac7fd89899168e00cb233c700 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:15:33 +0100 Subject: [PATCH 0460/2030] [speaker.media_player] Avoid heap allocation for triggers (#13707) --- esphome/components/mixer/speaker/automation.h | 1 + .../speaker/media_player/speaker_media_player.cpp | 6 +++--- .../speaker/media_player/speaker_media_player.h | 12 ++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/components/mixer/speaker/automation.h b/esphome/components/mixer/speaker/automation.h index 2234936628..2fb2f49373 100644 --- a/esphome/components/mixer/speaker/automation.h +++ b/esphome/components/mixer/speaker/automation.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/automation.h" #include "mixer_speaker.h" #ifdef USE_ESP32 diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 172bc980a8..94f555c26e 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -519,9 +519,9 @@ void SpeakerMediaPlayer::set_mute_state_(bool mute_state) { if (old_mute_state != mute_state) { if (mute_state) { - this->defer([this]() { this->mute_trigger_->trigger(); }); + this->defer([this]() { this->mute_trigger_.trigger(); }); } else { - this->defer([this]() { this->unmute_trigger_->trigger(); }); + this->defer([this]() { this->unmute_trigger_.trigger(); }); } } } @@ -550,7 +550,7 @@ void SpeakerMediaPlayer::set_volume_(float volume, bool publish) { this->set_mute_state_(false); } - this->defer([this, volume]() { this->volume_trigger_->trigger(volume); }); + this->defer([this, volume]() { this->volume_trigger_.trigger(volume); }); } } // namespace speaker diff --git a/esphome/components/speaker/media_player/speaker_media_player.h b/esphome/components/speaker/media_player/speaker_media_player.h index 065926d0cf..722f98ceea 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.h +++ b/esphome/components/speaker/media_player/speaker_media_player.h @@ -84,9 +84,9 @@ class SpeakerMediaPlayer : public Component, this->media_format_ = media_format; } - Trigger<> *get_mute_trigger() const { return this->mute_trigger_; } - Trigger<> *get_unmute_trigger() const { return this->unmute_trigger_; } - Trigger *get_volume_trigger() const { return this->volume_trigger_; } + Trigger<> *get_mute_trigger() { return &this->mute_trigger_; } + Trigger<> *get_unmute_trigger() { return &this->unmute_trigger_; } + Trigger *get_volume_trigger() { return &this->volume_trigger_; } void play_file(audio::AudioFile *media_file, bool announcement, bool enqueue); @@ -154,9 +154,9 @@ class SpeakerMediaPlayer : public Component, // Used to save volume/mute state for restoration on reboot ESPPreferenceObject pref_; - Trigger<> *mute_trigger_ = new Trigger<>(); - Trigger<> *unmute_trigger_ = new Trigger<>(); - Trigger *volume_trigger_ = new Trigger(); + Trigger<> mute_trigger_; + Trigger<> unmute_trigger_; + Trigger volume_trigger_; }; } // namespace speaker From 56110d4495055523d8a837d7d68ea71285109a9c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:15:50 +0100 Subject: [PATCH 0461/2030] [time_based] Avoid heap allocation for cover triggers (#13703) --- esphome/components/time_based/time_based_cover.cpp | 6 +++--- esphome/components/time_based/time_based_cover.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/time_based_cover.cpp index 1eb591fe6e..0aef4b8e85 100644 --- a/esphome/components/time_based/time_based_cover.cpp +++ b/esphome/components/time_based/time_based_cover.cpp @@ -132,15 +132,15 @@ void TimeBasedCover::start_direction_(CoverOperation dir) { Trigger<> *trig; switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; break; default: return; diff --git a/esphome/components/time_based/time_based_cover.h b/esphome/components/time_based/time_based_cover.h index 42cf66c2ab..d2457cae7a 100644 --- a/esphome/components/time_based/time_based_cover.h +++ b/esphome/components/time_based/time_based_cover.h @@ -14,9 +14,9 @@ class TimeBasedCover : public cover::Cover, public Component { void dump_config() override; float get_setup_priority() const override; - Trigger<> *get_open_trigger() const { return this->open_trigger_; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } void set_close_duration(uint32_t close_duration) { this->close_duration_ = close_duration; } cover::CoverTraits get_traits() override; @@ -34,11 +34,11 @@ class TimeBasedCover : public cover::Cover, public Component { void recompute_position_(); - Trigger<> *open_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; uint32_t open_duration_; - Trigger<> *close_trigger_{new Trigger<>()}; + Trigger<> close_trigger_; uint32_t close_duration_; - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> stop_trigger_; Trigger<> *prev_command_trigger_{nullptr}; uint32_t last_recompute_time_{0}; From 6727fe9040a1ce760ebcb86c54e1ae8686b06df9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:18:17 +0100 Subject: [PATCH 0462/2030] [remote_transmitter] Avoid heap allocation for triggers (#13708) --- .../components/remote_transmitter/remote_transmitter.cpp | 4 ++-- .../components/remote_transmitter/remote_transmitter.h | 8 ++++---- .../remote_transmitter/remote_transmitter_esp32.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/remote_transmitter/remote_transmitter.cpp b/esphome/components/remote_transmitter/remote_transmitter.cpp index f20789fb9f..d35541e2e1 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter.cpp @@ -83,7 +83,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen uint32_t on_time, off_time; this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time); this->target_time_ = 0; - this->transmit_trigger_->trigger(); + this->transmit_trigger_.trigger(); for (uint32_t i = 0; i < send_times; i++) { InterruptLock lock; for (int32_t item : this->temp_.get_data()) { @@ -102,7 +102,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) this->target_time_ += send_wait; } - this->complete_trigger_->trigger(); + this->complete_trigger_.trigger(); } } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index dd6a849e4c..65bd2ac8b2 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -57,8 +57,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void set_non_blocking(bool non_blocking) { this->non_blocking_ = non_blocking; } #endif - Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; }; - Trigger<> *get_complete_trigger() const { return this->complete_trigger_; }; + Trigger<> *get_transmit_trigger() { return &this->transmit_trigger_; } + Trigger<> *get_complete_trigger() { return &this->complete_trigger_; } protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; @@ -96,8 +96,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, #endif uint8_t carrier_duty_percent_; - Trigger<> *transmit_trigger_{new Trigger<>()}; - Trigger<> *complete_trigger_{new Trigger<>()}; + Trigger<> transmit_trigger_; + Trigger<> complete_trigger_; }; } // namespace remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index 59c85c99a8..89d97895b2 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -203,7 +203,7 @@ void RemoteTransmitterComponent::wait_for_rmt_() { this->status_set_warning(); } - this->complete_trigger_->trigger(); + this->complete_trigger_.trigger(); } #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1) @@ -264,7 +264,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen return; } - this->transmit_trigger_->trigger(); + this->transmit_trigger_.trigger(); rmt_transmit_config_t config; memset(&config, 0, sizeof(config)); @@ -333,7 +333,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen ESP_LOGE(TAG, "Empty data"); return; } - this->transmit_trigger_->trigger(); + this->transmit_trigger_.trigger(); for (uint32_t i = 0; i < send_times; i++) { rmt_transmit_config_t config; memset(&config, 0, sizeof(config)); @@ -354,7 +354,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen if (i + 1 < send_times) delayMicroseconds(send_wait); } - this->complete_trigger_->trigger(); + this->complete_trigger_.trigger(); } #endif From bc9fc6622553f0e58bcf5f8301fa2dd43da72f7a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 05:30:46 +0100 Subject: [PATCH 0463/2030] [template.datetime] Avoid heap allocation for triggers (#13710) --- esphome/components/template/datetime/template_date.cpp | 2 +- esphome/components/template/datetime/template_date.h | 4 ++-- esphome/components/template/datetime/template_datetime.cpp | 2 +- esphome/components/template/datetime/template_datetime.h | 4 ++-- esphome/components/template/datetime/template_time.cpp | 2 +- esphome/components/template/datetime/template_time.h | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/template/datetime/template_date.cpp b/esphome/components/template/datetime/template_date.cpp index be1d875a7e..8a5f11b876 100644 --- a/esphome/components/template/datetime/template_date.cpp +++ b/esphome/components/template/datetime/template_date.cpp @@ -62,7 +62,7 @@ void TemplateDate::control(const datetime::DateCall &call) { if (has_day) value.day_of_month = *call.get_day(); - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_year) diff --git a/esphome/components/template/datetime/template_date.h b/esphome/components/template/datetime/template_date.h index 0379a9bc67..acf823a34d 100644 --- a/esphome/components/template/datetime/template_date.h +++ b/esphome/components/template/datetime/template_date.h @@ -22,7 +22,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; } @@ -34,7 +34,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent bool optimistic_{false}; ESPTime initial_value_{}; bool restore_value_{false}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_; ESPPreferenceObject pref_; diff --git a/esphome/components/template/datetime/template_datetime.cpp b/esphome/components/template/datetime/template_datetime.cpp index e134f2b654..269a1d06ca 100644 --- a/esphome/components/template/datetime/template_datetime.cpp +++ b/esphome/components/template/datetime/template_datetime.cpp @@ -80,7 +80,7 @@ void TemplateDateTime::control(const datetime::DateTimeCall &call) { if (has_second) value.second = *call.get_second(); - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_year) diff --git a/esphome/components/template/datetime/template_datetime.h b/esphome/components/template/datetime/template_datetime.h index b7eb490933..575065a3dd 100644 --- a/esphome/components/template/datetime/template_datetime.h +++ b/esphome/components/template/datetime/template_datetime.h @@ -22,7 +22,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; } @@ -34,7 +34,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo bool optimistic_{false}; ESPTime initial_value_{}; bool restore_value_{false}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_; ESPPreferenceObject pref_; diff --git a/esphome/components/template/datetime/template_time.cpp b/esphome/components/template/datetime/template_time.cpp index 586e126e3b..9c81687116 100644 --- a/esphome/components/template/datetime/template_time.cpp +++ b/esphome/components/template/datetime/template_time.cpp @@ -62,7 +62,7 @@ void TemplateTime::control(const datetime::TimeCall &call) { if (has_second) value.second = *call.get_second(); - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_hour) diff --git a/esphome/components/template/datetime/template_time.h b/esphome/components/template/datetime/template_time.h index cb83b1b3e5..924b53cc71 100644 --- a/esphome/components/template/datetime/template_time.h +++ b/esphome/components/template/datetime/template_time.h @@ -22,7 +22,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; } @@ -34,7 +34,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent bool optimistic_{false}; ESPTime initial_value_{}; bool restore_value_{false}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_; ESPPreferenceObject pref_; From b5b9a895619e10dfe7784874133c7a8ebd444af6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:34:34 +0100 Subject: [PATCH 0464/2030] [light] Avoid heap allocation for AutomationLightEffect trigger (#13713) --- esphome/components/light/base_light_effects.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/light/base_light_effects.h b/esphome/components/light/base_light_effects.h index 2eeae574e7..cdb9f1f666 100644 --- a/esphome/components/light/base_light_effects.h +++ b/esphome/components/light/base_light_effects.h @@ -138,20 +138,20 @@ class LambdaLightEffect : public LightEffect { class AutomationLightEffect : public LightEffect { public: AutomationLightEffect(const char *name) : LightEffect(name) {} - void stop() override { this->trig_->stop_action(); } + void stop() override { this->trig_.stop_action(); } void apply() override { - if (!this->trig_->is_action_running()) { - this->trig_->trigger(); + if (!this->trig_.is_action_running()) { + this->trig_.trigger(); } } - Trigger<> *get_trig() const { return trig_; } + Trigger<> *get_trig() { return &this->trig_; } /// Get the current effect index for use in automations. /// Useful for automations that need to know which effect is running. uint32_t get_current_index() const { return this->get_index(); } protected: - Trigger<> *trig_{new Trigger<>}; + Trigger<> trig_; }; struct StrobeLightEffectColor { From 61e33217cd1995ae9fca8caba309268dd5b36a09 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:34:50 +0100 Subject: [PATCH 0465/2030] [cc1101] Avoid heap allocation for trigger (#13715) --- esphome/components/cc1101/cc1101.cpp | 2 +- esphome/components/cc1101/cc1101.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/cc1101/cc1101.cpp b/esphome/components/cc1101/cc1101.cpp index 46cd89e0e8..b6973da78d 100644 --- a/esphome/components/cc1101/cc1101.cpp +++ b/esphome/components/cc1101/cc1101.cpp @@ -156,7 +156,7 @@ void CC1101Component::call_listeners_(const std::vector &packet, float for (auto &listener : this->listeners_) { listener->on_packet(packet, freq_offset, rssi, lqi); } - this->packet_trigger_->trigger(packet, freq_offset, rssi, lqi); + this->packet_trigger_.trigger(packet, freq_offset, rssi, lqi); } void CC1101Component::loop() { diff --git a/esphome/components/cc1101/cc1101.h b/esphome/components/cc1101/cc1101.h index 6e3f01af90..e55071e7e3 100644 --- a/esphome/components/cc1101/cc1101.h +++ b/esphome/components/cc1101/cc1101.h @@ -79,7 +79,7 @@ class CC1101Component : public Component, // Packet mode operations CC1101Error transmit_packet(const std::vector &packet); void register_listener(CC1101Listener *listener) { this->listeners_.push_back(listener); } - Trigger, float, float, uint8_t> *get_packet_trigger() const { return this->packet_trigger_; } + Trigger, float, float, uint8_t> *get_packet_trigger() { return &this->packet_trigger_; } protected: uint16_t chip_id_{0}; @@ -96,8 +96,7 @@ class CC1101Component : public Component, // Packet handling void call_listeners_(const std::vector &packet, float freq_offset, float rssi, uint8_t lqi); - Trigger, float, float, uint8_t> *packet_trigger_{ - new Trigger, float, float, uint8_t>()}; + Trigger, float, float, uint8_t> packet_trigger_; std::vector packet_; std::vector listeners_; From 420de987bcd19edd991592632da82784c371ddc5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:35:03 +0100 Subject: [PATCH 0466/2030] [micro_wake_word] Avoid heap allocation for trigger (#13714) --- esphome/components/micro_wake_word/micro_wake_word.cpp | 2 +- esphome/components/micro_wake_word/micro_wake_word.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index d7e80efc84..b93bf1b556 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -325,7 +325,7 @@ void MicroWakeWord::loop() { ESP_LOGD(TAG, "Detected '%s' with sliding average probability is %.2f and max probability is %.2f", detection_event.wake_word->c_str(), (detection_event.average_probability / uint8_to_float_divisor), (detection_event.max_probability / uint8_to_float_divisor)); - this->wake_word_detected_trigger_->trigger(*detection_event.wake_word); + this->wake_word_detected_trigger_.trigger(*detection_event.wake_word); if (this->stop_after_detection_) { this->stop(); } diff --git a/esphome/components/micro_wake_word/micro_wake_word.h b/esphome/components/micro_wake_word/micro_wake_word.h index b427e4dfcb..44d5d89372 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.h +++ b/esphome/components/micro_wake_word/micro_wake_word.h @@ -60,7 +60,7 @@ class MicroWakeWord : public Component void set_stop_after_detection(bool stop_after_detection) { this->stop_after_detection_ = stop_after_detection; } - Trigger *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; } + Trigger *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; } void add_wake_word_model(WakeWordModel *model); @@ -78,7 +78,7 @@ class MicroWakeWord : public Component protected: microphone::MicrophoneSource *microphone_source_{nullptr}; - Trigger *wake_word_detected_trigger_ = new Trigger(); + Trigger wake_word_detected_trigger_; State state_{State::STOPPED}; std::weak_ptr ring_buffer_; From c0e5ae4298162b1c971121255de9bf5358be93d0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:35:21 +0100 Subject: [PATCH 0467/2030] [template.text] Avoid heap allocation for trigger (#13711) --- esphome/components/template/text/template_text.cpp | 2 +- esphome/components/template/text/template_text.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/template/text/template_text.cpp b/esphome/components/template/text/template_text.cpp index 70b8dce312..af134e6ed4 100644 --- a/esphome/components/template/text/template_text.cpp +++ b/esphome/components/template/text/template_text.cpp @@ -47,7 +47,7 @@ void TemplateText::update() { } void TemplateText::control(const std::string &value) { - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) this->publish_state(value); diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index e5e5e4f4a8..88c6afdf2c 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -68,7 +68,7 @@ class TemplateText final : public text::Text, public PollingComponent { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_initial_value(const char *initial_value) { this->initial_value_ = initial_value; } /// Prevent accidental use of std::string which would dangle @@ -79,7 +79,7 @@ class TemplateText final : public text::Text, public PollingComponent { void control(const std::string &value) override; bool optimistic_ = false; const char *initial_value_{nullptr}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_{}; TemplateTextSaverBase *pref_ = nullptr; From 61140059524d837dc9ac40bc0dfe6acc7a027216 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:36:08 +0100 Subject: [PATCH 0468/2030] [template.water_heater] Avoid heap allocation for trigger (#13712) --- .../template/water_heater/template_water_heater.cpp | 4 ++-- .../components/template/water_heater/template_water_heater.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index e89c96ca48..f888edb1df 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -5,7 +5,7 @@ namespace esphome::template_ { static const char *const TAG = "template.water_heater"; -TemplateWaterHeater::TemplateWaterHeater() : set_trigger_(new Trigger<>()) {} +TemplateWaterHeater::TemplateWaterHeater() = default; void TemplateWaterHeater::setup() { if (this->restore_mode_ == TemplateWaterHeaterRestoreMode::WATER_HEATER_RESTORE || @@ -78,7 +78,7 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) { } } - this->set_trigger_->trigger(); + this->set_trigger_.trigger(); if (this->optimistic_) { this->publish_state(); diff --git a/esphome/components/template/water_heater/template_water_heater.h b/esphome/components/template/water_heater/template_water_heater.h index c2a2dcbb23..f1cf00a115 100644 --- a/esphome/components/template/water_heater/template_water_heater.h +++ b/esphome/components/template/water_heater/template_water_heater.h @@ -28,7 +28,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { this->supported_modes_ = modes; } - Trigger<> *get_set_trigger() const { return this->set_trigger_; } + Trigger<> *get_set_trigger() { return &this->set_trigger_; } void setup() override; void loop() override; @@ -42,7 +42,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { water_heater::WaterHeaterTraits traits() override; // Ordered to minimize padding on 32-bit: 4-byte members first, then smaller - Trigger<> *set_trigger_; + Trigger<> set_trigger_; TemplateLambda current_temperature_f_; TemplateLambda mode_f_; TemplateWaterHeaterRestoreMode restore_mode_{WATER_HEATER_NO_RESTORE}; From 62f34bea83c1423a8b894cebf04c3cc40bfc78f2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 07:36:27 +0100 Subject: [PATCH 0469/2030] [template.output] Avoid heap allocation for triggers (#13709) --- esphome/components/template/output/template_output.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/template/output/template_output.h b/esphome/components/template/output/template_output.h index e536660b02..6fe8e53855 100644 --- a/esphome/components/template/output/template_output.h +++ b/esphome/components/template/output/template_output.h @@ -8,22 +8,22 @@ namespace esphome::template_ { class TemplateBinaryOutput final : public output::BinaryOutput { public: - Trigger *get_trigger() const { return trigger_; } + Trigger *get_trigger() { return &this->trigger_; } protected: - void write_state(bool state) override { this->trigger_->trigger(state); } + void write_state(bool state) override { this->trigger_.trigger(state); } - Trigger *trigger_ = new Trigger(); + Trigger trigger_; }; class TemplateFloatOutput final : public output::FloatOutput { public: - Trigger *get_trigger() const { return trigger_; } + Trigger *get_trigger() { return &this->trigger_; } protected: - void write_state(float state) override { this->trigger_->trigger(state); } + void write_state(float state) override { this->trigger_.trigger(state); } - Trigger *trigger_ = new Trigger(); + Trigger trigger_; }; } // namespace esphome::template_ From 18991686ab389d153c2af110daee17d8124fcf31 Mon Sep 17 00:00:00 2001 From: rwrozelle Date: Mon, 2 Feb 2026 10:48:08 -0500 Subject: [PATCH 0470/2030] [mqtt] resolve warnings related to use of ip.str() (#13719) --- esphome/components/mqtt/mqtt_backend_esp32.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index bd2d2a67b2..adba0cf004 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -139,7 +139,8 @@ class MQTTBackendESP32 final : public MQTTBackend { this->lwt_retain_ = retain; } void set_server(network::IPAddress ip, uint16_t port) final { - this->host_ = ip.str(); + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + this->host_ = ip.str_to(ip_buf); this->port_ = port; } void set_server(const char *host, uint16_t port) final { From aa8ccfc32b0e2f7c347911f27dc8dce922f2b16b Mon Sep 17 00:00:00 2001 From: Roger Fachini Date: Mon, 2 Feb 2026 08:00:11 -0800 Subject: [PATCH 0471/2030] [ethernet] Add on_connect and on_disconnect triggers (#13677) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/ethernet/__init__.py | 18 +++++++++++++++++- .../components/ethernet/ethernet_component.cpp | 9 +++++++++ .../components/ethernet/ethernet_component.h | 13 +++++++++++++ esphome/core/defines.h | 2 ++ tests/components/ethernet/common-dm9051.yaml | 4 ++++ tests/components/ethernet/common-dp83848.yaml | 4 ++++ tests/components/ethernet/common-ip101.yaml | 4 ++++ tests/components/ethernet/common-jl1101.yaml | 4 ++++ tests/components/ethernet/common-ksz8081.yaml | 4 ++++ .../components/ethernet/common-ksz8081rna.yaml | 4 ++++ tests/components/ethernet/common-lan8670.yaml | 4 ++++ tests/components/ethernet/common-lan8720.yaml | 4 ++++ tests/components/ethernet/common-openeth.yaml | 4 ++++ tests/components/ethernet/common-rtl8201.yaml | 4 ++++ tests/components/ethernet/common-w5500.yaml | 4 ++++ 15 files changed, 85 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 8d4a1aaf8e..23436cc5be 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -1,6 +1,6 @@ import logging -from esphome import pins +from esphome import automation, pins import esphome.codegen as cg from esphome.components.esp32 import ( VARIANT_ESP32, @@ -35,6 +35,8 @@ from esphome.const import ( CONF_MODE, CONF_MOSI_PIN, CONF_NUMBER, + CONF_ON_CONNECT, + CONF_ON_DISCONNECT, CONF_PAGE_ID, CONF_PIN, CONF_POLLING_INTERVAL, @@ -237,6 +239,8 @@ BASE_SCHEMA = cv.Schema( cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name, cv.Optional(CONF_USE_ADDRESS): cv.string_strict, cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_ON_CONNECT): automation.validate_automation(single=True), + cv.Optional(CONF_ON_DISCONNECT): automation.validate_automation(single=True), } ).extend(cv.COMPONENT_SCHEMA) @@ -430,6 +434,18 @@ async def to_code(config): if CORE.using_arduino: cg.add_library("WiFi", None) + if on_connect_config := config.get(CONF_ON_CONNECT): + cg.add_define("USE_ETHERNET_CONNECT_TRIGGER") + await automation.build_automation( + var.get_connect_trigger(), [], on_connect_config + ) + + if on_disconnect_config := config.get(CONF_ON_DISCONNECT): + cg.add_define("USE_ETHERNET_DISCONNECT_TRIGGER") + await automation.build_automation( + var.get_disconnect_trigger(), [], on_disconnect_config + ) + CORE.add_job(final_step) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 70f8ce1204..af7fed608b 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -309,6 +309,9 @@ void EthernetComponent::loop() { this->dump_connect_params_(); this->status_clear_warning(); +#ifdef USE_ETHERNET_CONNECT_TRIGGER + this->connect_trigger_.trigger(); +#endif } else if (now - this->connect_begin_ > 15000) { ESP_LOGW(TAG, "Connecting failed; reconnecting"); this->start_connect_(); @@ -318,10 +321,16 @@ void EthernetComponent::loop() { if (!this->started_) { ESP_LOGI(TAG, "Stopped connection"); this->state_ = EthernetComponentState::STOPPED; +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif } else if (!this->connected_) { ESP_LOGW(TAG, "Connection lost; reconnecting"); this->state_ = EthernetComponentState::CONNECTING; this->start_connect_(); +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif } else { this->finish_connect_(); // When connected and stable, disable the loop to save CPU cycles diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 34380047d1..5a2869c5a7 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -4,6 +4,7 @@ #include "esphome/core/defines.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" +#include "esphome/core/automation.h" #include "esphome/components/network/ip_address.h" #ifdef USE_ESP32 @@ -119,6 +120,12 @@ class EthernetComponent : public Component { void add_ip_state_listener(EthernetIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); } #endif +#ifdef USE_ETHERNET_CONNECT_TRIGGER + Trigger<> *get_connect_trigger() { return &this->connect_trigger_; } +#endif +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + Trigger<> *get_disconnect_trigger() { return &this->disconnect_trigger_; } +#endif protected: static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); @@ -190,6 +197,12 @@ class EthernetComponent : public Component { StaticVector ip_state_listeners_; #endif +#ifdef USE_ETHERNET_CONNECT_TRIGGER + Trigger<> connect_trigger_; +#endif +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + Trigger<> disconnect_trigger_; +#endif private: // Stores a pointer to a string literal (static storage duration). // ONLY set from Python-generated code with string literals - never dynamic strings. diff --git a/esphome/core/defines.h b/esphome/core/defines.h index e98cdd0ba0..1edc648084 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -240,6 +240,8 @@ #define USE_ETHERNET_KSZ8081 #define USE_ETHERNET_MANUAL_IP #define USE_ETHERNET_IP_STATE_LISTENERS +#define USE_ETHERNET_CONNECT_TRIGGER +#define USE_ETHERNET_DISCONNECT_TRIGGER #define ESPHOME_ETHERNET_IP_STATE_LISTENERS 2 #endif diff --git a/tests/components/ethernet/common-dm9051.yaml b/tests/components/ethernet/common-dm9051.yaml index 4526e7732d..bb8c74b820 100644 --- a/tests/components/ethernet/common-dm9051.yaml +++ b/tests/components/ethernet/common-dm9051.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-dp83848.yaml b/tests/components/ethernet/common-dp83848.yaml index f9069c5fb9..809613c79d 100644 --- a/tests/components/ethernet/common-dp83848.yaml +++ b/tests/components/ethernet/common-dp83848.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-ip101.yaml b/tests/components/ethernet/common-ip101.yaml index cea7a5cc35..41716a7850 100644 --- a/tests/components/ethernet/common-ip101.yaml +++ b/tests/components/ethernet/common-ip101.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-jl1101.yaml b/tests/components/ethernet/common-jl1101.yaml index 7b0a2dfdc4..d70a576c81 100644 --- a/tests/components/ethernet/common-jl1101.yaml +++ b/tests/components/ethernet/common-jl1101.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-ksz8081.yaml b/tests/components/ethernet/common-ksz8081.yaml index 65541832c2..e2add8d370 100644 --- a/tests/components/ethernet/common-ksz8081.yaml +++ b/tests/components/ethernet/common-ksz8081.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-ksz8081rna.yaml b/tests/components/ethernet/common-ksz8081rna.yaml index f04cba15b2..1bb404f720 100644 --- a/tests/components/ethernet/common-ksz8081rna.yaml +++ b/tests/components/ethernet/common-ksz8081rna.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-lan8670.yaml b/tests/components/ethernet/common-lan8670.yaml index fb751ebd23..ae4953974c 100644 --- a/tests/components/ethernet/common-lan8670.yaml +++ b/tests/components/ethernet/common-lan8670.yaml @@ -12,3 +12,7 @@ ethernet: gateway: 192.168.178.1 subnet: 255.255.255.0 domain: .local + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-lan8720.yaml b/tests/components/ethernet/common-lan8720.yaml index 838d57df28..742800fdf4 100644 --- a/tests/components/ethernet/common-lan8720.yaml +++ b/tests/components/ethernet/common-lan8720.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-openeth.yaml b/tests/components/ethernet/common-openeth.yaml index fbb7579598..26595dbc52 100644 --- a/tests/components/ethernet/common-openeth.yaml +++ b/tests/components/ethernet/common-openeth.yaml @@ -1,2 +1,6 @@ ethernet: type: OPENETH + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-rtl8201.yaml b/tests/components/ethernet/common-rtl8201.yaml index 0e7cbe73c6..d5a60f6e98 100644 --- a/tests/components/ethernet/common-rtl8201.yaml +++ b/tests/components/ethernet/common-rtl8201.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-w5500.yaml b/tests/components/ethernet/common-w5500.yaml index b3e96f000d..1f8b8650dd 100644 --- a/tests/components/ethernet/common-w5500.yaml +++ b/tests/components/ethernet/common-w5500.yaml @@ -13,3 +13,7 @@ ethernet: subnet: 255.255.255.0 domain: .local mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" From 6892805094426d903b0dd2650ef8531e861f0271 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:00:46 +0100 Subject: [PATCH 0472/2030] [api] Align water_heater_command with standard entity command pattern (#13655) --- esphome/components/api/api.proto | 1 + esphome/components/api/api_connection.cpp | 2 +- esphome/components/api/api_connection.h | 2 +- esphome/components/api/api_pb2_service.cpp | 5 +++++ esphome/components/api/api_pb2_service.h | 6 ++++++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 597da25883..d25934c60b 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -45,6 +45,7 @@ service APIConnection { rpc time_command (TimeCommandRequest) returns (void) {} rpc update_command (UpdateCommandRequest) returns (void) {} rpc valve_command (ValveCommandRequest) returns (void) {} + rpc water_heater_command (WaterHeaterCommandRequest) returns (void) {} rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {} diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 1626f395e6..839de29de7 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1385,7 +1385,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec is_single); } -void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) { +void APIConnection::water_heater_command(const WaterHeaterCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(water_heater::WaterHeater, water_heater, water_heater) if (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_MODE) call.set_mode(static_cast(msg.mode)); diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 21bf4c4073..b839a2a97b 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -170,7 +170,7 @@ class APIConnection final : public APIServerConnection { #ifdef USE_WATER_HEATER bool send_water_heater_state(water_heater::WaterHeater *water_heater); - void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; + void water_heater_command(const WaterHeaterCommandRequest &msg) override; #endif #ifdef USE_IR_RF diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 4b7148e6c0..af0a2d0ca2 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -746,6 +746,11 @@ void APIServerConnection::on_update_command_request(const UpdateCommandRequest & #ifdef USE_VALVE void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) { this->valve_command(msg); } #endif +#ifdef USE_WATER_HEATER +void APIServerConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) { + this->water_heater_command(msg); +} +#endif #ifdef USE_BLUETOOTH_PROXY void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request( const SubscribeBluetoothLEAdvertisementsRequest &msg) { diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 200991c282..80a61c1041 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -303,6 +303,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_VALVE virtual void valve_command(const ValveCommandRequest &msg) = 0; #endif +#ifdef USE_WATER_HEATER + virtual void water_heater_command(const WaterHeaterCommandRequest &msg) = 0; +#endif #ifdef USE_BLUETOOTH_PROXY virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0; #endif @@ -432,6 +435,9 @@ class APIServerConnection : public APIServerConnectionBase { #ifdef USE_VALVE void on_valve_command_request(const ValveCommandRequest &msg) override; #endif +#ifdef USE_WATER_HEATER + void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; +#endif #ifdef USE_BLUETOOTH_PROXY void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; #endif From 848c2371590f1839704f1ddeeeda65b539c7506e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:05:27 +0100 Subject: [PATCH 0473/2030] [time] Use lazy callback for time sync to save 8 bytes (#13652) --- esphome/components/time/real_time_clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index 70469e11b0..19aa1a4f4a 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -62,7 +62,7 @@ class RealTimeClock : public PollingComponent { void apply_timezone_(); #endif - CallbackManager time_sync_callback_; + LazyCallbackManager time_sync_callback_; }; template class TimeHasTimeCondition : public Condition { From 4f0894e970468d1ecf375866d25d46977903e13c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:05:39 +0100 Subject: [PATCH 0474/2030] [analyze-memory] Add top 30 largest symbols to report (#13673) --- esphome/analyze_memory/cli.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/esphome/analyze_memory/cli.py b/esphome/analyze_memory/cli.py index a77e17afce..72a73dbdd4 100644 --- a/esphome/analyze_memory/cli.py +++ b/esphome/analyze_memory/cli.py @@ -4,6 +4,8 @@ from __future__ import annotations from collections import defaultdict from collections.abc import Callable +import heapq +from operator import itemgetter import sys from typing import TYPE_CHECKING @@ -29,6 +31,10 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): ) # Lower threshold for RAM symbols (RAM is more constrained) RAM_SYMBOL_SIZE_THRESHOLD: int = 24 + # Number of top symbols to show in the largest symbols report + TOP_SYMBOLS_LIMIT: int = 30 + # Width for symbol name display in top symbols report + COL_TOP_SYMBOL_NAME: int = 55 # Column width constants COL_COMPONENT: int = 29 @@ -147,6 +153,37 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): section_label = f" [{section[1:]}]" # .data -> [data], .bss -> [bss] return f"{demangled} ({size:,} B){section_label}" + def _add_top_symbols(self, lines: list[str]) -> None: + """Add a section showing the top largest symbols in the binary.""" + # Collect all symbols from all components: (symbol, demangled, size, section, component) + all_symbols = [ + (symbol, demangled, size, section, component) + for component, symbols in self._component_symbols.items() + for symbol, demangled, size, section in symbols + ] + + # Get top N symbols by size using heapq for efficiency + top_symbols = heapq.nlargest( + self.TOP_SYMBOLS_LIMIT, all_symbols, key=itemgetter(2) + ) + + lines.append("") + lines.append(f"Top {self.TOP_SYMBOLS_LIMIT} Largest Symbols:") + # Calculate truncation limit from column width (leaving room for "...") + truncate_limit = self.COL_TOP_SYMBOL_NAME - 3 + for i, (_, demangled, size, section, component) in enumerate(top_symbols): + # Format section label + section_label = f"[{section[1:]}]" if section else "" + # Truncate demangled name if too long + demangled_display = ( + f"{demangled[:truncate_limit]}..." + if len(demangled) > self.COL_TOP_SYMBOL_NAME + else demangled + ) + lines.append( + f"{i + 1:>2}. {size:>7,} B {section_label:<8} {demangled_display:<{self.COL_TOP_SYMBOL_NAME}} {component}" + ) + def generate_report(self, detailed: bool = False) -> str: """Generate a formatted memory report.""" components = sorted( @@ -248,6 +285,9 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): "RAM", ) + # Top largest symbols in the binary + self._add_top_symbols(lines) + # Add ESPHome core detailed analysis if there are core symbols if self._esphome_core_symbols: self._add_section_header(lines, f"{_COMPONENT_CORE} Detailed Analysis") From c089d9aeac70588cf56b20fa9c353cc081060839 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:21:52 +0100 Subject: [PATCH 0475/2030] [esp32_hosted] Replace sscanf with strtol for version parsing (#13658) --- .../update/esp32_hosted_update.cpp | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index ebcdd5f36e..dac2b01425 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -34,14 +34,29 @@ static const char *const ESP_HOSTED_VERSION_STR = STRINGIFY(ESP_HOSTED_VERSION_M ESP_HOSTED_VERSION_MINOR_1) "." STRINGIFY(ESP_HOSTED_VERSION_PATCH_1); #ifdef USE_ESP32_HOSTED_HTTP_UPDATE +// Parse an integer from str, advancing ptr past the number +// Returns false if no digits were parsed +static bool parse_int(const char *&ptr, int &value) { + char *end; + value = static_cast(strtol(ptr, &end, 10)); + if (end == ptr) + return false; + ptr = end; + return true; +} + // Parse version string "major.minor.patch" into components -// Returns true if parsing succeeded +// Returns true if at least major.minor was parsed static bool parse_version(const std::string &version_str, int &major, int &minor, int &patch) { major = minor = patch = 0; - if (sscanf(version_str.c_str(), "%d.%d.%d", &major, &minor, &patch) >= 2) { - return true; - } - return false; + const char *ptr = version_str.c_str(); + + if (!parse_int(ptr, major) || *ptr++ != '.' || !parse_int(ptr, minor)) + return false; + if (*ptr == '.') + parse_int(++ptr, patch); + + return true; } // Compare two versions, returns: From 1119003eb5208206eae7526246968dd703ca1dd2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:22:11 +0100 Subject: [PATCH 0476/2030] [core] Add missing uint32_t ID overloads for defer() and cancel_defer() (#13720) --- esphome/core/component.cpp | 4 ++ esphome/core/component.h | 4 ++ .../fixtures/scheduler_numeric_id_test.yaml | 45 ++++++++++++++++++- .../test_scheduler_numeric_id_test.py | 38 +++++++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 98e8c02d07..f09a39d2bb 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -359,6 +359,10 @@ void Component::defer(const std::string &name, std::function &&f) { // void Component::defer(const char *name, std::function &&f) { // NOLINT App.scheduler.set_timeout(this, name, 0, std::move(f)); } +void Component::defer(uint32_t id, std::function &&f) { // NOLINT + App.scheduler.set_timeout(this, id, 0, std::move(f)); +} +bool Component::cancel_defer(uint32_t id) { return App.scheduler.cancel_timeout(this, id); } void Component::set_timeout(uint32_t timeout, std::function &&f) { // NOLINT App.scheduler.set_timeout(this, static_cast(nullptr), timeout, std::move(f)); } diff --git a/esphome/core/component.h b/esphome/core/component.h index 49349d4199..97f2afe1a4 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -494,11 +494,15 @@ class Component { /// Defer a callback to the next loop() call. void defer(std::function &&f); // NOLINT + /// Defer a callback with a numeric ID (zero heap allocation) + void defer(uint32_t id, std::function &&f); // NOLINT + /// Cancel a defer callback using the specified name, name must not be empty. // Remove before 2026.7.0 ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_defer(const std::string &name); // NOLINT bool cancel_defer(const char *name); // NOLINT + bool cancel_defer(uint32_t id); // NOLINT // Ordered for optimal packing on 32-bit systems const LogString *component_source_{nullptr}; diff --git a/tests/integration/fixtures/scheduler_numeric_id_test.yaml b/tests/integration/fixtures/scheduler_numeric_id_test.yaml index bf60f2fda9..1669f026f5 100644 --- a/tests/integration/fixtures/scheduler_numeric_id_test.yaml +++ b/tests/integration/fixtures/scheduler_numeric_id_test.yaml @@ -20,6 +20,9 @@ globals: - id: retry_counter type: int initial_value: '0' + - id: defer_counter + type: int + initial_value: '0' - id: tests_done type: bool initial_value: 'false' @@ -136,11 +139,49 @@ script: App.scheduler.cancel_retry(component1, 6002U); ESP_LOGI("test", "Cancelled numeric retry 6002"); + // Test 12: defer with numeric ID (Component method) + class TestDeferComponent : public Component { + public: + void test_defer_methods() { + // Test defer with uint32_t ID - should execute on next loop + this->defer(7001U, []() { + ESP_LOGI("test", "Component numeric defer 7001 fired"); + id(defer_counter) += 1; + }); + + // Test another defer with numeric ID + this->defer(7002U, []() { + ESP_LOGI("test", "Component numeric defer 7002 fired"); + id(defer_counter) += 1; + }); + } + }; + + static TestDeferComponent test_defer_component; + test_defer_component.test_defer_methods(); + + // Test 13: cancel_defer with numeric ID (Component method) + class TestCancelDeferComponent : public Component { + public: + void test_cancel_defer() { + // Set a defer that should be cancelled + this->defer(8001U, []() { + ESP_LOGE("test", "ERROR: Numeric defer 8001 should have been cancelled"); + }); + // Cancel it immediately + bool cancelled = this->cancel_defer(8001U); + ESP_LOGI("test", "Cancelled numeric defer 8001: %s", cancelled ? "true" : "false"); + } + }; + + static TestCancelDeferComponent test_cancel_defer_component; + test_cancel_defer_component.test_cancel_defer(); + - id: report_results then: - lambda: |- - ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d", - id(timeout_counter), id(interval_counter), id(retry_counter)); + ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d, Defers: %d", + id(timeout_counter), id(interval_counter), id(retry_counter), id(defer_counter)); sensor: - platform: template diff --git a/tests/integration/test_scheduler_numeric_id_test.py b/tests/integration/test_scheduler_numeric_id_test.py index 510256b9a4..c1958db685 100644 --- a/tests/integration/test_scheduler_numeric_id_test.py +++ b/tests/integration/test_scheduler_numeric_id_test.py @@ -19,6 +19,7 @@ async def test_scheduler_numeric_id_test( timeout_count = 0 interval_count = 0 retry_count = 0 + defer_count = 0 # Events for each test completion numeric_timeout_1001_fired = asyncio.Event() @@ -33,6 +34,9 @@ async def test_scheduler_numeric_id_test( max_id_timeout_fired = asyncio.Event() numeric_retry_done = asyncio.Event() numeric_retry_cancelled = asyncio.Event() + numeric_defer_7001_fired = asyncio.Event() + numeric_defer_7002_fired = asyncio.Event() + numeric_defer_cancelled = asyncio.Event() final_results_logged = asyncio.Event() # Track interval counts @@ -40,7 +44,7 @@ async def test_scheduler_numeric_id_test( numeric_retry_count = 0 def on_log_line(line: str) -> None: - nonlocal timeout_count, interval_count, retry_count + nonlocal timeout_count, interval_count, retry_count, defer_count nonlocal numeric_interval_count, numeric_retry_count # Strip ANSI color codes @@ -105,15 +109,27 @@ async def test_scheduler_numeric_id_test( elif "Cancelled numeric retry 6002" in clean_line: numeric_retry_cancelled.set() + # Check for numeric defer tests + elif "Component numeric defer 7001 fired" in clean_line: + numeric_defer_7001_fired.set() + + elif "Component numeric defer 7002 fired" in clean_line: + numeric_defer_7002_fired.set() + + elif "Cancelled numeric defer 8001: true" in clean_line: + numeric_defer_cancelled.set() + # Check for final results elif "Final results" in clean_line: match = re.search( - r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+)", clean_line + r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+), Defers: (\d+)", + clean_line, ) if match: timeout_count = int(match.group(1)) interval_count = int(match.group(2)) retry_count = int(match.group(3)) + defer_count = int(match.group(4)) final_results_logged.set() async with ( @@ -201,6 +217,23 @@ async def test_scheduler_numeric_id_test( "Numeric retry 6002 should have been cancelled" ) + # Wait for numeric defer tests + try: + await asyncio.wait_for(numeric_defer_7001_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 7001 did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(numeric_defer_7002_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 7002 did not fire within 0.5 seconds") + + # Verify numeric defer was cancelled + try: + await asyncio.wait_for(numeric_defer_cancelled.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 8001 cancel confirmation not received") + # Wait for final results try: await asyncio.wait_for(final_results_logged.wait(), timeout=3.0) @@ -215,3 +248,4 @@ async def test_scheduler_numeric_id_test( assert retry_count >= 2, ( f"Expected at least 2 retry attempts, got {retry_count}" ) + assert defer_count >= 2, f"Expected at least 2 defer fires, got {defer_count}" From da947d060f9e14b9f8b241290e80b5cf2d405aae Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 2 Feb 2026 19:20:24 -0500 Subject: [PATCH 0477/2030] [wizard] Use API encryption key instead of deprecated password (#13634) Co-authored-by: Claude Opus 4.5 --- esphome/wizard.py | 66 +++++++++++++++++--------- tests/unit_tests/test_wizard.py | 84 +++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 25 deletions(-) diff --git a/esphome/wizard.py b/esphome/wizard.py index d77450b04d..f5e8a1e462 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -1,5 +1,7 @@ +import base64 from pathlib import Path import random +import secrets import string from typing import Literal, NotRequired, TypedDict, Unpack import unicodedata @@ -116,7 +118,6 @@ class WizardFileKwargs(TypedDict): board: str ssid: NotRequired[str] psk: NotRequired[str] - password: NotRequired[str] ota_password: NotRequired[str] api_encryption_key: NotRequired[str] friendly_name: NotRequired[str] @@ -144,9 +145,7 @@ def wizard_file(**kwargs: Unpack[WizardFileKwargs]) -> str: config += API_CONFIG - # Configure API - if "password" in kwargs: - config += f' password: "{kwargs["password"]}"\n' + # Configure API encryption if "api_encryption_key" in kwargs: config += f' encryption:\n key: "{kwargs["api_encryption_key"]}"\n' @@ -155,8 +154,6 @@ def wizard_file(**kwargs: Unpack[WizardFileKwargs]) -> str: config += " - platform: esphome\n" if "ota_password" in kwargs: config += f' password: "{kwargs["ota_password"]}"' - elif "password" in kwargs: - config += f' password: "{kwargs["password"]}"' # Configuring wifi config += "\n\nwifi:\n" @@ -205,7 +202,6 @@ class WizardWriteKwargs(TypedDict): platform: NotRequired[str] ssid: NotRequired[str] psk: NotRequired[str] - password: NotRequired[str] ota_password: NotRequired[str] api_encryption_key: NotRequired[str] friendly_name: NotRequired[str] @@ -232,7 +228,7 @@ def wizard_write(path: Path, **kwargs: Unpack[WizardWriteKwargs]) -> bool: else: # "basic" board = kwargs["board"] - for key in ("ssid", "psk", "password", "ota_password"): + for key in ("ssid", "psk", "ota_password"): if key in kwargs: kwargs[key] = sanitize_double_quotes(kwargs[key]) if "platform" not in kwargs: @@ -522,26 +518,54 @@ def wizard(path: Path) -> int: "Almost there! ESPHome can automatically upload custom firmwares over WiFi " "(over the air) and integrates into Home Assistant with a native API." ) + safe_print() + sleep(0.5) + + # Generate encryption key (32 bytes, base64 encoded) for secure API communication + noise_psk = secrets.token_bytes(32) + api_encryption_key = base64.b64encode(noise_psk).decode() + safe_print( - f"This can be insecure if you do not trust the WiFi network. Do you want to set a {color(AnsiFore.GREEN, 'password')} for connecting to this ESP?" + "For secure API communication, I've generated a random encryption key." + ) + safe_print() + safe_print( + f"Your {color(AnsiFore.GREEN, 'API encryption key')} is: " + f"{color(AnsiFore.BOLD_WHITE, api_encryption_key)}" + ) + safe_print() + safe_print("You'll need this key when adding the device to Home Assistant.") + sleep(1) + + safe_print() + safe_print( + f"Do you want to set a {color(AnsiFore.GREEN, 'password')} for OTA updates? " + "This can be insecure if you do not trust the WiFi network." ) safe_print() sleep(0.25) safe_print("Press ENTER for no password") - password = safe_input(color(AnsiFore.BOLD_WHITE, "(password): ")) + ota_password = safe_input(color(AnsiFore.BOLD_WHITE, "(password): ")) else: - ssid, password, psk = "", "", "" + ssid, psk = "", "" + api_encryption_key = None + ota_password = "" - if not wizard_write( - path=path, - name=name, - platform=platform, - board=board, - ssid=ssid, - psk=psk, - password=password, - type="basic", - ): + kwargs = { + "path": path, + "name": name, + "platform": platform, + "board": board, + "ssid": ssid, + "psk": psk, + "type": "basic", + } + if api_encryption_key: + kwargs["api_encryption_key"] = api_encryption_key + if ota_password: + kwargs["ota_password"] = ota_password + + if not wizard_write(**kwargs): return 1 safe_print() diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index fd53a0b0b7..eb44c1c20f 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -25,7 +25,6 @@ def default_config() -> dict[str, Any]: "board": "esp01_1m", "ssid": "test_ssid", "psk": "test_psk", - "password": "", } @@ -37,7 +36,7 @@ def wizard_answers() -> list[str]: "nodemcuv2", # board "SSID", # ssid "psk", # wifi password - "ota_pass", # ota password + "", # ota password (empty for no password) ] @@ -105,16 +104,35 @@ def test_config_file_should_include_ota_when_password_set( default_config: dict[str, Any], ): """ - The Over-The-Air update should be enabled when a password is set + The Over-The-Air update should be enabled when an OTA password is set """ # Given - default_config["password"] = "foo" + default_config["ota_password"] = "foo" # When config = wz.wizard_file(**default_config) # Then assert "ota:" in config + assert 'password: "foo"' in config + + +def test_config_file_should_include_api_encryption_key( + default_config: dict[str, Any], +): + """ + The API encryption key should be included when set + """ + # Given + default_config["api_encryption_key"] = "test_encryption_key_base64==" + + # When + config = wz.wizard_file(**default_config) + + # Then + assert "api:" in config + assert "encryption:" in config + assert 'key: "test_encryption_key_base64=="' in config def test_wizard_write_sets_platform( @@ -556,3 +574,61 @@ def test_wizard_write_protects_existing_config( # Then assert result is False # Should return False when file exists assert config_file.read_text() == original_content + + +def test_wizard_accepts_ota_password( + tmp_path: Path, monkeypatch: MonkeyPatch, wizard_answers: list[str] +): + """ + The wizard should pass ota_password to wizard_write when the user provides one + """ + + # Given + wizard_answers[5] = "my_ota_password" # Set OTA password + config_file = tmp_path / "test.yaml" + input_mock = MagicMock(side_effect=wizard_answers) + monkeypatch.setattr("builtins.input", input_mock) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) + monkeypatch.setattr(wz, "sleep", lambda _: 0) + wizard_write_mock = MagicMock(return_value=True) + monkeypatch.setattr(wz, "wizard_write", wizard_write_mock) + + # When + retval = wz.wizard(config_file) + + # Then + assert retval == 0 + call_kwargs = wizard_write_mock.call_args.kwargs + assert "ota_password" in call_kwargs + assert call_kwargs["ota_password"] == "my_ota_password" + + +def test_wizard_accepts_rpipico_board(tmp_path: Path, monkeypatch: MonkeyPatch): + """ + The wizard should handle rpipico board which doesn't support WiFi. + This tests the branch where api_encryption_key is None. + """ + + # Given + wizard_answers_rp2040 = [ + "test-node", # Name of the node + "RP2040", # platform + "rpipico", # board (no WiFi support) + ] + config_file = tmp_path / "test.yaml" + input_mock = MagicMock(side_effect=wizard_answers_rp2040) + monkeypatch.setattr("builtins.input", input_mock) + monkeypatch.setattr(wz, "safe_print", lambda t=None, end=None: 0) + monkeypatch.setattr(wz, "sleep", lambda _: 0) + wizard_write_mock = MagicMock(return_value=True) + monkeypatch.setattr(wz, "wizard_write", wizard_write_mock) + + # When + retval = wz.wizard(config_file) + + # Then + assert retval == 0 + call_kwargs = wizard_write_mock.call_args.kwargs + # rpipico doesn't support WiFi, so no api_encryption_key or ota_password + assert "api_encryption_key" not in call_kwargs + assert "ota_password" not in call_kwargs From a6543d32bd23ae18f2ae49cd6023281e2c912aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kundr=C3=A1t?= Date: Tue, 3 Feb 2026 02:15:18 +0100 Subject: [PATCH 0478/2030] [sx126x] fix maximal payload_length (#13723) --- esphome/components/sx126x/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/sx126x/__init__.py b/esphome/components/sx126x/__init__.py index ed878ed0d4..413eb139d6 100644 --- a/esphome/components/sx126x/__init__.py +++ b/esphome/components/sx126x/__init__.py @@ -213,7 +213,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_ON_PACKET): automation.validate_automation(single=True), cv.Optional(CONF_PA_POWER, default=17): cv.int_range(min=-3, max=22), cv.Optional(CONF_PA_RAMP, default="40us"): cv.enum(RAMP), - cv.Optional(CONF_PAYLOAD_LENGTH, default=0): cv.int_range(min=0, max=256), + cv.Optional(CONF_PAYLOAD_LENGTH, default=0): cv.int_range(min=0, max=255), cv.Optional(CONF_PREAMBLE_DETECT, default=2): cv.int_range(min=0, max=4), cv.Optional(CONF_PREAMBLE_SIZE, default=8): cv.int_range(min=1, max=65535), cv.Required(CONF_RST_PIN): pins.gpio_output_pin_schema, From 26e4cda610d32c21c980c1fe96eda4b70551d8b8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 02:25:54 +0100 Subject: [PATCH 0479/2030] [logger] Use vsnprintf_P directly for ESP8266 flash format strings (#13716) --- esphome/components/logger/logger.cpp | 51 +++++++--------------------- esphome/components/logger/logger.h | 45 ++++++++++++++---------- 2 files changed, 40 insertions(+), 56 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 3a726d4046..25243ff3f6 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -128,22 +128,7 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch // Note: USE_STORE_LOG_STR_IN_FLASH is only defined for ESP8266. // // This function handles format strings stored in flash memory (PROGMEM) to save RAM. -// The buffer is used in a special way to avoid allocating extra memory: -// -// Memory layout during execution: -// Step 1: Copy format string from flash to buffer -// tx_buffer_: [format_string][null][.....................] -// tx_buffer_at_: ------------------^ -// msg_start: saved here -----------^ -// -// Step 2: format_log_to_buffer_with_terminator_ reads format string from beginning -// and writes formatted output starting at msg_start position -// tx_buffer_: [format_string][null][formatted_message][null] -// tx_buffer_at_: -------------------------------------^ -// -// Step 3: Output the formatted message (starting at msg_start) -// write_msg_ and callbacks receive: this->tx_buffer_ + msg_start -// which points to: [formatted_message][null] +// Uses vsnprintf_P to read the format string directly from flash without copying to RAM. // void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __FlashStringHelper *format, va_list args) { // NOLINT @@ -153,35 +138,25 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas RecursionGuard guard(global_recursion_guard_); this->tx_buffer_at_ = 0; - // Copy format string from progmem - auto *format_pgm_p = reinterpret_cast(format); - char ch = '.'; - while (this->tx_buffer_at_ < this->tx_buffer_size_ && ch != '\0') { - this->tx_buffer_[this->tx_buffer_at_++] = ch = (char) progmem_read_byte(format_pgm_p++); - } + // Write header, format body directly from flash, and write footer + this->write_header_to_buffer_(level, tag, line, nullptr, this->tx_buffer_, &this->tx_buffer_at_, + this->tx_buffer_size_); + this->format_body_to_buffer_P_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_, + reinterpret_cast(format), args); + this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); - // Buffer full from copying format - RAII guard handles cleanup on return - if (this->tx_buffer_at_ >= this->tx_buffer_size_) { - return; - } - - // Save the offset before calling format_log_to_buffer_with_terminator_ - // since it will increment tx_buffer_at_ to the end of the formatted string - uint16_t msg_start = this->tx_buffer_at_; - this->format_log_to_buffer_with_terminator_(level, tag, line, this->tx_buffer_, args, this->tx_buffer_, - &this->tx_buffer_at_, this->tx_buffer_size_); - - uint16_t msg_length = - this->tx_buffer_at_ - msg_start; // Don't subtract 1 - tx_buffer_at_ is already at the null terminator position + // Ensure null termination + uint16_t null_pos = this->tx_buffer_at_ >= this->tx_buffer_size_ ? this->tx_buffer_size_ - 1 : this->tx_buffer_at_; + this->tx_buffer_[null_pos] = '\0'; // Listeners get message first (before console write) #ifdef USE_LOG_LISTENERS for (auto *listener : this->log_listeners_) - listener->on_log(level, tag, this->tx_buffer_ + msg_start, msg_length); + listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); #endif - // Write to console starting at the msg_start - this->write_tx_buffer_to_console_(msg_start, &msg_length); + // Write to console + this->write_tx_buffer_to_console_(); } #endif // USE_STORE_LOG_STR_IN_FLASH diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index fe9cab4993..40ac9a38aa 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -597,31 +597,40 @@ class Logger : public Component { *buffer_at = pos; } + // Helper to process vsnprintf return value and strip trailing newlines. + // Updates buffer_at with the formatted length, handling truncation: + // - When vsnprintf truncates (ret >= remaining), it writes (remaining - 1) chars + null terminator + // - When it doesn't truncate (ret < remaining), it writes ret chars + null terminator + __attribute__((always_inline)) static inline void process_vsnprintf_result(const char *buffer, uint16_t *buffer_at, + uint16_t remaining, int ret) { + if (ret < 0) + return; // Encoding error, do not increment buffer_at + *buffer_at += (ret >= remaining) ? (remaining - 1) : static_cast(ret); + // Remove all trailing newlines right after formatting + while (*buffer_at > 0 && buffer[*buffer_at - 1] == '\n') + (*buffer_at)--; + } + inline void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format, va_list args) { - // Get remaining capacity in the buffer + // Check remaining capacity in the buffer if (*buffer_at >= buffer_size) return; const uint16_t remaining = buffer_size - *buffer_at; - - const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args); - - if (ret < 0) { - return; // Encoding error, do not increment buffer_at - } - - // Update buffer_at with the formatted length (handle truncation) - // When vsnprintf truncates (ret >= remaining), it writes (remaining - 1) chars + null terminator - // When it doesn't truncate (ret < remaining), it writes ret chars + null terminator - uint16_t formatted_len = (ret >= remaining) ? (remaining - 1) : ret; - *buffer_at += formatted_len; - - // Remove all trailing newlines right after formatting - while (*buffer_at > 0 && buffer[*buffer_at - 1] == '\n') { - (*buffer_at)--; - } + process_vsnprintf_result(buffer, buffer_at, remaining, vsnprintf(buffer + *buffer_at, remaining, format, args)); } +#ifdef USE_STORE_LOG_STR_IN_FLASH + // ESP8266 variant that reads format string directly from flash using vsnprintf_P + inline void HOT format_body_to_buffer_P_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, PGM_P format, + va_list args) { + if (*buffer_at >= buffer_size) + return; + const uint16_t remaining = buffer_size - *buffer_at; + process_vsnprintf_result(buffer, buffer_at, remaining, vsnprintf_P(buffer + *buffer_at, remaining, format, args)); + } +#endif + inline void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) { static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size); From efecea9450462e3cb65d1c361e57aa5b9d0463ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 02:27:34 +0100 Subject: [PATCH 0480/2030] Bump github/codeql-action from 4.32.0 to 4.32.1 (#13726) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index be761cee3d..817ea1d2be 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/init@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0 + uses: github/codeql-action/analyze@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1 with: category: "/language:${{matrix.language}}" From ccf5c1f7e9103a470f9167105ae266af760dd7e0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 03:12:12 +0100 Subject: [PATCH 0481/2030] [esp32] Exclude additional unused IDF components (driver, dac, mcpwm, twai, openthread, ulp) (#13664) --- esphome/components/esp32/__init__.py | 6 ++++++ esphome/components/esp32_can/canbus.py | 5 +++++ esphome/components/esp32_dac/output.py | 8 +++++++- esphome/components/esp32_touch/__init__.py | 2 ++ esphome/components/openthread/__init__.py | 4 ++++ 5 files changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index aed4ecad90..4c53b42e6f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -124,10 +124,14 @@ COMPILER_OPTIMIZATIONS = { # - "sdmmc": driver -> esp_driver_sdmmc -> sdmmc dependency chain DEFAULT_EXCLUDED_IDF_COMPONENTS = ( "cmock", # Unit testing mock framework - ESPHome doesn't use IDF's testing + "driver", # Legacy driver shim - only needed by esp32_touch, esp32_can for legacy headers "esp_adc", # ADC driver - only needed by adc component + "esp_driver_dac", # DAC driver - only needed by esp32_dac component "esp_driver_i2s", # I2S driver - only needed by i2s_audio component + "esp_driver_mcpwm", # MCPWM driver - ESPHome doesn't use motor control PWM "esp_driver_rmt", # RMT driver - only needed by remote_transmitter/receiver, neopixelbus "esp_driver_touch_sens", # Touch sensor driver - only needed by esp32_touch + "esp_driver_twai", # TWAI/CAN driver - only needed by esp32_can component "esp_eth", # Ethernet driver - only needed by ethernet component "esp_hid", # HID host/device support - ESPHome doesn't implement HID functionality "esp_http_client", # HTTP client - only needed by http_request component @@ -138,9 +142,11 @@ DEFAULT_EXCLUDED_IDF_COMPONENTS = ( "espcoredump", # Core dump support - ESPHome has its own debug component "fatfs", # FAT filesystem - ESPHome doesn't use filesystem storage "mqtt", # ESP-IDF MQTT library - ESPHome has its own MQTT implementation + "openthread", # Thread protocol - only needed by openthread component "perfmon", # Xtensa performance monitor - ESPHome has its own debug component "protocomm", # Protocol communication for provisioning - unused by ESPHome "spiffs", # SPIFFS filesystem - ESPHome doesn't use filesystem storage (IDF only) + "ulp", # ULP coprocessor - not currently used by any ESPHome component "unity", # Unit testing framework - ESPHome doesn't use IDF's testing "wear_levelling", # Flash wear levelling for fatfs - unused since fatfs unused "wifi_provisioning", # WiFi provisioning - ESPHome uses its own improv implementation diff --git a/esphome/components/esp32_can/canbus.py b/esphome/components/esp32_can/canbus.py index 0768b35507..7245ba7513 100644 --- a/esphome/components/esp32_can/canbus.py +++ b/esphome/components/esp32_can/canbus.py @@ -15,6 +15,7 @@ from esphome.components.esp32 import ( VARIANT_ESP32S2, VARIANT_ESP32S3, get_esp32_variant, + include_builtin_idf_component, ) import esphome.config_validation as cv from esphome.const import ( @@ -121,6 +122,10 @@ def get_default_tx_enqueue_timeout(bit_rate): async def to_code(config): + # Legacy driver component provides driver/twai.h header + include_builtin_idf_component("driver") + # Also enable esp_driver_twai for future migration to new API + include_builtin_idf_component("esp_driver_twai") var = cg.new_Pvariable(config[CONF_ID]) await canbus.register_canbus(var, config) diff --git a/esphome/components/esp32_dac/output.py b/esphome/components/esp32_dac/output.py index daace596d3..7c63d7bd11 100644 --- a/esphome/components/esp32_dac/output.py +++ b/esphome/components/esp32_dac/output.py @@ -1,7 +1,12 @@ from esphome import pins import esphome.codegen as cg from esphome.components import output -from esphome.components.esp32 import VARIANT_ESP32, VARIANT_ESP32S2, get_esp32_variant +from esphome.components.esp32 import ( + VARIANT_ESP32, + VARIANT_ESP32S2, + get_esp32_variant, + include_builtin_idf_component, +) import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_NUMBER, CONF_PIN @@ -38,6 +43,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( async def to_code(config): + include_builtin_idf_component("esp_driver_dac") var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await output.register_output(var, config) diff --git a/esphome/components/esp32_touch/__init__.py b/esphome/components/esp32_touch/__init__.py index 6accb89c35..a02370a343 100644 --- a/esphome/components/esp32_touch/__init__.py +++ b/esphome/components/esp32_touch/__init__.py @@ -269,6 +269,8 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): # Re-enable ESP-IDF's touch sensor driver (excluded by default to save compile time) include_builtin_idf_component("esp_driver_touch_sens") + # Legacy driver component provides driver/touch_sensor.h header + include_builtin_idf_component("driver") touch = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(touch, config) diff --git a/esphome/components/openthread/__init__.py b/esphome/components/openthread/__init__.py index 26c05a0a86..89d335c574 100644 --- a/esphome/components/openthread/__init__.py +++ b/esphome/components/openthread/__init__.py @@ -4,6 +4,7 @@ from esphome.components.esp32 import ( VARIANT_ESP32C6, VARIANT_ESP32H2, add_idf_sdkconfig_option, + include_builtin_idf_component, only_on_variant, require_vfs_select, ) @@ -172,6 +173,9 @@ FINAL_VALIDATE_SCHEMA = _final_validate async def to_code(config): + # Re-enable openthread IDF component (excluded by default) + include_builtin_idf_component("openthread") + cg.add_define("USE_OPENTHREAD") # OpenThread SRP needs access to mDNS services after setup From ae71f07abb34b9b053eb5233f1ee39fd1936de7b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 03:19:38 +0100 Subject: [PATCH 0482/2030] [http_request] Fix requests taking full timeout when response is already complete (#13649) --- .../update/esp32_hosted_update.cpp | 14 ++++- .../components/http_request/http_request.h | 55 ++++++++++++++----- .../http_request/http_request_arduino.cpp | 20 ++++++- .../http_request/http_request_idf.cpp | 9 +-- .../http_request/ota/ota_http_request.cpp | 6 +- 5 files changed, 78 insertions(+), 26 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index dac2b01425..a7d5f7e3d5 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -211,11 +211,14 @@ bool Esp32HostedUpdate::fetch_manifest_() { int read_or_error = container->read(buf, sizeof(buf)); App.feed_wdt(); yield(); - auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == http_request::HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added in the future. if (result != http_request::HttpReadLoopResult::DATA) - break; // ERROR or TIMEOUT + break; // COMPLETE, ERROR, or TIMEOUT json_str.append(reinterpret_cast(buf), read_or_error); } container->end(); @@ -336,9 +339,14 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { App.feed_wdt(); yield(); - auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == http_request::HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added in the future. + if (result == http_request::HttpReadLoopResult::COMPLETE) + break; if (result != http_request::HttpReadLoopResult::DATA) { if (result == http_request::HttpReadLoopResult::TIMEOUT) { ESP_LOGE(TAG, "Timeout reading firmware data"); diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 79098a6b72..c88360ca78 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -26,6 +26,7 @@ struct Header { enum HttpStatus { HTTP_STATUS_OK = 200, HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_RESET_CONTENT = 205, HTTP_STATUS_PARTIAL_CONTENT = 206, /* 3xx - Redirection */ @@ -126,19 +127,21 @@ struct HttpReadResult { /// Result of processing a non-blocking read with timeout (for manual loops) enum class HttpReadLoopResult : uint8_t { - DATA, ///< Data was read, process it - RETRY, ///< No data yet, already delayed, caller should continue loop - ERROR, ///< Read error, caller should exit loop - TIMEOUT, ///< Timeout waiting for data, caller should exit loop + DATA, ///< Data was read, process it + COMPLETE, ///< All content has been read, caller should exit loop + RETRY, ///< No data yet, already delayed, caller should continue loop + ERROR, ///< Read error, caller should exit loop + TIMEOUT, ///< Timeout waiting for data, caller should exit loop }; /// Process a read result with timeout tracking and delay handling /// @param bytes_read_or_error Return value from read() - positive for bytes read, negative for error /// @param last_data_time Time of last successful read, updated when data received /// @param timeout_ms Maximum time to wait for data -/// @return DATA if data received, RETRY if should continue loop, ERROR/TIMEOUT if should exit -inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, - uint32_t timeout_ms) { +/// @param is_read_complete Whether all expected content has been read (from HttpContainer::is_read_complete()) +/// @return How the caller should proceed - see HttpReadLoopResult enum +inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, uint32_t timeout_ms, + bool is_read_complete) { if (bytes_read_or_error > 0) { last_data_time = millis(); return HttpReadLoopResult::DATA; @@ -146,7 +149,10 @@ inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_ if (bytes_read_or_error < 0) { return HttpReadLoopResult::ERROR; } - // bytes_read_or_error == 0: no data available yet + // bytes_read_or_error == 0: either "no data yet" or "all content read" + if (is_read_complete) { + return HttpReadLoopResult::COMPLETE; + } if (millis() - last_data_time >= timeout_ms) { return HttpReadLoopResult::TIMEOUT; } @@ -159,9 +165,9 @@ class HttpRequestComponent; class HttpContainer : public Parented { public: virtual ~HttpContainer() = default; - size_t content_length; - int status_code; - uint32_t duration_ms; + size_t content_length{0}; + int status_code{-1}; ///< -1 indicates no response received yet + uint32_t duration_ms{0}; /** * @brief Read data from the HTTP response body. @@ -194,9 +200,24 @@ class HttpContainer : public Parented { virtual void end() = 0; void set_secure(bool secure) { this->secure_ = secure; } + void set_chunked(bool chunked) { this->is_chunked_ = chunked; } size_t get_bytes_read() const { return this->bytes_read_; } + /// Check if all expected content has been read + /// For chunked responses, returns false (completion detected via read() returning error/EOF) + bool is_read_complete() const { + // Per RFC 9112, these responses have no body: + // - 1xx (Informational), 204 No Content, 205 Reset Content, 304 Not Modified + if ((this->status_code >= 100 && this->status_code < 200) || this->status_code == HTTP_STATUS_NO_CONTENT || + this->status_code == HTTP_STATUS_RESET_CONTENT || this->status_code == HTTP_STATUS_NOT_MODIFIED) { + return true; + } + // For non-chunked responses, complete when bytes_read >= content_length + // This handles both Content-Length: 0 and Content-Length: N cases + return !this->is_chunked_ && this->bytes_read_ >= this->content_length; + } + /** * @brief Get response headers. * @@ -209,6 +230,7 @@ class HttpContainer : public Parented { protected: size_t bytes_read_{0}; bool secure_{false}; + bool is_chunked_{false}; ///< True if response uses chunked transfer encoding std::map> response_headers_{}; }; @@ -219,7 +241,7 @@ class HttpContainer : public Parented { /// @param total_size Total bytes to read /// @param chunk_size Maximum bytes per read call /// @param timeout_ms Read timeout in milliseconds -/// @return HttpReadResult with status and error_code on failure +/// @return HttpReadResult with status and error_code on failure; use container->get_bytes_read() for total bytes read inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, size_t total_size, size_t chunk_size, uint32_t timeout_ms) { size_t read_index = 0; @@ -231,9 +253,11 @@ inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, App.feed_wdt(); yield(); - auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms); + auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; + if (result == HttpReadLoopResult::COMPLETE) + break; // Server sent less data than requested, but transfer is complete if (result == HttpReadLoopResult::ERROR) return {HttpReadStatus::ERROR, read_bytes_or_error}; if (result == HttpReadLoopResult::TIMEOUT) @@ -393,11 +417,12 @@ template class HttpRequestSendAction : public Action { int read_or_error = container->read(buf + read_index, std::min(max_length - read_index, 512)); App.feed_wdt(); yield(); - auto result = http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; if (result != HttpReadLoopResult::DATA) - break; // ERROR or TIMEOUT + break; // COMPLETE, ERROR, or TIMEOUT read_index += read_or_error; } response_body.reserve(read_index); diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 82538b2cb3..2f12b58766 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -135,9 +135,23 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur // When cast to size_t, -1 becomes SIZE_MAX (4294967295 on 32-bit). // The read() method handles this: bytes_read_ can never reach SIZE_MAX, so the // early return check (bytes_read_ >= content_length) will never trigger. + // + // TODO: Chunked transfer encoding is NOT properly supported on Arduino. + // The implementation in #7884 was incomplete - it only works correctly on ESP-IDF where + // esp_http_client_read() decodes chunks internally. On Arduino, using getStreamPtr() + // returns raw TCP data with chunk framing (e.g., "12a\r\n{json}\r\n0\r\n\r\n") instead + // of decoded content. This wasn't noticed because requests would complete and payloads + // were only examined on IDF. The long transfer times were also masked by the misleading + // "HTTP on Arduino version >= 3.1 is **very** slow" warning above. This causes two issues: + // 1. Response body is corrupted - contains chunk size headers mixed with data + // 2. Cannot detect end of transfer - connection stays open (keep-alive), causing timeout + // The proper fix would be to use getString() for chunked responses, which decodes chunks + // internally, but this buffers the entire response in memory. int content_length = container->client_.getSize(); ESP_LOGD(TAG, "Content-Length: %d", content_length); container->content_length = (size_t) content_length; + // -1 (SIZE_MAX when cast to size_t) means chunked transfer encoding + container->set_chunked(content_length == -1); container->duration_ms = millis() - start; return container; @@ -178,9 +192,9 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { if (bufsize == 0) { this->duration_ms += (millis() - start); - // Check if we've read all expected content (only valid when content_length is known and not SIZE_MAX) - // For chunked encoding (content_length == SIZE_MAX), we can't use this check - if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { + // Check if we've read all expected content (non-chunked only) + // For chunked encoding (content_length == SIZE_MAX), is_read_complete() returns false + if (this->is_read_complete()) { return 0; // All content read successfully } // No data available - check if connection is still open diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 2b4dee953a..bd12b7d123 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -160,6 +160,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c // esp_http_client_fetch_headers() returns 0 for chunked transfer encoding (no Content-Length header). // The read() method handles content_length == 0 specially to support chunked responses. container->content_length = esp_http_client_fetch_headers(client); + container->set_chunked(esp_http_client_is_chunked_response(client)); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); container->feed_wdt(); @@ -195,6 +196,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c container->feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); + container->set_chunked(esp_http_client_is_chunked_response(client)); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); container->feed_wdt(); @@ -239,10 +241,9 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); - // Check if we've already read all expected content - // Skip this check when content_length is 0 (chunked transfer encoding or unknown length) - // For chunked responses, esp_http_client_read() will return 0 when all data is received - if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { + // Check if we've already read all expected content (non-chunked only) + // For chunked responses (content_length == 0), esp_http_client_read() handles EOF + if (this->is_read_complete()) { return 0; // All content read successfully } diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 8a4b3684cf..8f4ecfab2d 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -130,9 +130,13 @@ uint8_t OtaHttpRequestComponent::do_ota_() { App.feed_wdt(); yield(); - auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout); + auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added for OTA in the future. + if (result == HttpReadLoopResult::COMPLETE) + break; if (result != HttpReadLoopResult::DATA) { if (result == HttpReadLoopResult::TIMEOUT) { ESP_LOGE(TAG, "Timeout reading data"); From 9f1a427ce235aa6ab3f1206cfd7940fa7f338b04 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 04:03:52 +0100 Subject: [PATCH 0483/2030] [preferences] Use static storage for singletons and flash buffer (#13727) --- esphome/components/esp32/preferences.cpp | 7 ++++--- esphome/components/esp8266/preferences.cpp | 17 +++++++++-------- esphome/components/host/preferences.cpp | 7 ++++--- esphome/components/libretiny/preferences.cpp | 7 ++++--- esphome/components/rp2040/preferences.cpp | 17 +++++++++-------- esphome/components/zephyr/preferences.cpp | 7 ++++--- 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index 4e0bb68133..7d5af023b4 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -203,10 +203,11 @@ class ESP32Preferences : public ESPPreferences { } }; +static ESP32Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *prefs = new ESP32Preferences(); // NOLINT(cppcoreguidelines-owning-memory) - prefs->open(); - global_preferences = prefs; + s_preferences.open(); + global_preferences = &s_preferences; } } // namespace esp32 diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index 35d1cd07f7..f037b881a8 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -17,10 +17,6 @@ namespace esphome::esp8266 { static const char *const TAG = "esp8266.preferences"; -static uint32_t *s_flash_storage = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - static constexpr uint32_t ESP_RTC_USER_MEM_START = 0x60001200; static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_WORDS = 128; static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_BYTES = ESP_RTC_USER_MEM_SIZE_WORDS * 4; @@ -43,6 +39,11 @@ static constexpr uint32_t ESP8266_FLASH_STORAGE_SIZE = 128; static constexpr uint32_t ESP8266_FLASH_STORAGE_SIZE = 64; #endif +static uint32_t + s_flash_storage[ESP8266_FLASH_STORAGE_SIZE]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) { if (index >= ESP_RTC_USER_MEM_SIZE_WORDS) { return false; @@ -180,7 +181,6 @@ class ESP8266Preferences : public ESPPreferences { uint32_t current_flash_offset = 0; // in words void setup() { - s_flash_storage = new uint32_t[ESP8266_FLASH_STORAGE_SIZE]; // NOLINT ESP_LOGVV(TAG, "Loading preferences from flash"); { @@ -283,10 +283,11 @@ class ESP8266Preferences : public ESPPreferences { } }; +static ESP8266Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *pref = new ESP8266Preferences(); // NOLINT(cppcoreguidelines-owning-memory) - pref->setup(); - global_preferences = pref; + s_preferences.setup(); + global_preferences = &s_preferences; } void preferences_prevent_write(bool prevent) { s_prevent_write = prevent; } diff --git a/esphome/components/host/preferences.cpp b/esphome/components/host/preferences.cpp index 7b939cdebb..5ad87c1f2a 100644 --- a/esphome/components/host/preferences.cpp +++ b/esphome/components/host/preferences.cpp @@ -66,10 +66,11 @@ ESPPreferenceObject HostPreferences::make_preference(size_t length, uint32_t typ return ESPPreferenceObject(backend); }; +static HostPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *pref = new HostPreferences(); // NOLINT(cppcoreguidelines-owning-memory) - host_preferences = pref; - global_preferences = pref; + host_preferences = &s_preferences; + global_preferences = &s_preferences; } bool HostPreferenceBackend::save(const uint8_t *data, size_t len) { diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 978dcce3fa..5a60b535da 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -189,10 +189,11 @@ class LibreTinyPreferences : public ESPPreferences { } }; +static LibreTinyPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *prefs = new LibreTinyPreferences(); // NOLINT(cppcoreguidelines-owning-memory) - prefs->open(); - global_preferences = prefs; + s_preferences.open(); + global_preferences = &s_preferences; } } // namespace libretiny diff --git a/esphome/components/rp2040/preferences.cpp b/esphome/components/rp2040/preferences.cpp index e84033bc52..172da32adc 100644 --- a/esphome/components/rp2040/preferences.cpp +++ b/esphome/components/rp2040/preferences.cpp @@ -18,11 +18,12 @@ namespace rp2040 { static const char *const TAG = "rp2040.preferences"; -static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static uint8_t *s_flash_storage = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static constexpr uint32_t RP2040_FLASH_STORAGE_SIZE = 512; -static const uint32_t RP2040_FLASH_STORAGE_SIZE = 512; +static bool s_prevent_write = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static uint8_t + s_flash_storage[RP2040_FLASH_STORAGE_SIZE]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) // Stack buffer size for preferences - covers virtually all real-world preferences without heap allocation static constexpr size_t PREF_BUFFER_SIZE = 64; @@ -91,7 +92,6 @@ class RP2040Preferences : public ESPPreferences { RP2040Preferences() : eeprom_sector_(&_EEPROM_start) {} void setup() { - s_flash_storage = new uint8_t[RP2040_FLASH_STORAGE_SIZE]; // NOLINT ESP_LOGVV(TAG, "Loading preferences from flash"); memcpy(s_flash_storage, this->eeprom_sector_, RP2040_FLASH_STORAGE_SIZE); } @@ -149,10 +149,11 @@ class RP2040Preferences : public ESPPreferences { uint8_t *eeprom_sector_; }; +static RP2040Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *prefs = new RP2040Preferences(); // NOLINT(cppcoreguidelines-owning-memory) - prefs->setup(); - global_preferences = prefs; + s_preferences.setup(); + global_preferences = &s_preferences; } void preferences_prevent_write(bool prevent) { s_prevent_write = prevent; } diff --git a/esphome/components/zephyr/preferences.cpp b/esphome/components/zephyr/preferences.cpp index 311133a813..f02fa16326 100644 --- a/esphome/components/zephyr/preferences.cpp +++ b/esphome/components/zephyr/preferences.cpp @@ -152,10 +152,11 @@ class ZephyrPreferences : public ESPPreferences { } }; +static ZephyrPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + void setup_preferences() { - auto *prefs = new ZephyrPreferences(); // NOLINT(cppcoreguidelines-owning-memory) - global_preferences = prefs; - prefs->open(); + global_preferences = &s_preferences; + s_preferences.open(); } } // namespace zephyr From d41c84d624165984d1e1eaf6cde6312b4bb6f9a9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 04:29:18 +0100 Subject: [PATCH 0484/2030] [wifi] Conditionally compile on_connect/on_disconnect triggers (#13684) --- esphome/components/wifi/__init__.py | 2 ++ esphome/components/wifi/automation.h | 16 ++++++++-------- esphome/components/wifi/wifi_component.cpp | 13 ++++++++++--- esphome/components/wifi/wifi_component.h | 19 ++++++++++++++----- esphome/core/defines.h | 2 ++ tests/components/wifi/common.yaml | 4 ++++ 6 files changed, 40 insertions(+), 16 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 98266eb589..6863e6fb62 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -585,11 +585,13 @@ async def to_code(config): await cg.past_safe_mode() if on_connect_config := config.get(CONF_ON_CONNECT): + cg.add_define("USE_WIFI_CONNECT_TRIGGER") await automation.build_automation( var.get_connect_trigger(), [], on_connect_config ) if on_disconnect_config := config.get(CONF_ON_DISCONNECT): + cg.add_define("USE_WIFI_DISCONNECT_TRIGGER") await automation.build_automation( var.get_disconnect_trigger(), [], on_disconnect_config ) diff --git a/esphome/components/wifi/automation.h b/esphome/components/wifi/automation.h index fb0e71bcf6..1ad69b3992 100644 --- a/esphome/components/wifi/automation.h +++ b/esphome/components/wifi/automation.h @@ -48,7 +48,7 @@ template class WiFiConfigureAction : public Action, publi char ssid_buf[SSID_BUFFER_SIZE]; if (strcmp(global_wifi_component->wifi_ssid_to(ssid_buf), ssid.c_str()) == 0) { // Callback to notify the user that the connection was successful - this->connect_trigger_->trigger(); + this->connect_trigger_.trigger(); return; } // Create a new WiFiAP object with the new SSID and password @@ -79,13 +79,13 @@ template class WiFiConfigureAction : public Action, publi // Start a timeout for the fallback if the connection to the old AP fails this->set_timeout("wifi-fallback-timeout", this->connection_timeout_.value(x...), [this]() { this->connecting_ = false; - this->error_trigger_->trigger(); + this->error_trigger_.trigger(); }); }); } - Trigger<> *get_connect_trigger() const { return this->connect_trigger_; } - Trigger<> *get_error_trigger() const { return this->error_trigger_; } + Trigger<> *get_connect_trigger() { return &this->connect_trigger_; } + Trigger<> *get_error_trigger() { return &this->error_trigger_; } void loop() override { if (!this->connecting_) @@ -98,10 +98,10 @@ template class WiFiConfigureAction : public Action, publi char ssid_buf[SSID_BUFFER_SIZE]; if (strcmp(global_wifi_component->wifi_ssid_to(ssid_buf), this->new_sta_.get_ssid().c_str()) == 0) { // Callback to notify the user that the connection was successful - this->connect_trigger_->trigger(); + this->connect_trigger_.trigger(); } else { // Callback to notify the user that the connection failed - this->error_trigger_->trigger(); + this->error_trigger_.trigger(); } } } @@ -110,8 +110,8 @@ template class WiFiConfigureAction : public Action, publi bool connecting_{false}; WiFiAP new_sta_; WiFiAP old_sta_; - Trigger<> *connect_trigger_{new Trigger<>()}; - Trigger<> *error_trigger_{new Trigger<>()}; + Trigger<> connect_trigger_; + Trigger<> error_trigger_; }; } // namespace esphome::wifi diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 65c653a62a..c4bfdf3c42 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -651,14 +651,21 @@ void WiFiComponent::loop() { const uint32_t now = App.get_loop_component_start_time(); if (this->has_sta()) { +#if defined(USE_WIFI_CONNECT_TRIGGER) || defined(USE_WIFI_DISCONNECT_TRIGGER) if (this->is_connected() != this->handled_connected_state_) { +#ifdef USE_WIFI_DISCONNECT_TRIGGER if (this->handled_connected_state_) { - this->disconnect_trigger_->trigger(); - } else { - this->connect_trigger_->trigger(); + this->disconnect_trigger_.trigger(); } +#endif +#ifdef USE_WIFI_CONNECT_TRIGGER + if (!this->handled_connected_state_) { + this->connect_trigger_.trigger(); + } +#endif this->handled_connected_state_ = this->is_connected(); } +#endif // USE_WIFI_CONNECT_TRIGGER || USE_WIFI_DISCONNECT_TRIGGER switch (this->state_) { case WIFI_COMPONENT_STATE_COOLDOWN: { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index f27c522a1b..4bdc253f66 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -454,8 +454,12 @@ class WiFiComponent : public Component { void set_keep_scan_results(bool keep_scan_results) { this->keep_scan_results_ = keep_scan_results; } void set_post_connect_roaming(bool enabled) { this->post_connect_roaming_ = enabled; } - Trigger<> *get_connect_trigger() const { return this->connect_trigger_; }; - Trigger<> *get_disconnect_trigger() const { return this->disconnect_trigger_; }; +#ifdef USE_WIFI_CONNECT_TRIGGER + Trigger<> *get_connect_trigger() { return &this->connect_trigger_; } +#endif +#ifdef USE_WIFI_DISCONNECT_TRIGGER + Trigger<> *get_disconnect_trigger() { return &this->disconnect_trigger_; } +#endif int32_t get_wifi_channel(); @@ -706,7 +710,9 @@ class WiFiComponent : public Component { // Group all boolean values together bool has_ap_{false}; +#if defined(USE_WIFI_CONNECT_TRIGGER) || defined(USE_WIFI_DISCONNECT_TRIGGER) bool handled_connected_state_{false}; +#endif bool error_from_callback_{false}; bool scan_done_{false}; bool ap_setup_{false}; @@ -733,9 +739,12 @@ class WiFiComponent : public Component { SemaphoreHandle_t high_performance_semaphore_{nullptr}; #endif - // Pointers at the end (naturally aligned) - Trigger<> *connect_trigger_{new Trigger<>()}; - Trigger<> *disconnect_trigger_{new Trigger<>()}; +#ifdef USE_WIFI_CONNECT_TRIGGER + Trigger<> connect_trigger_; +#endif +#ifdef USE_WIFI_DISCONNECT_TRIGGER + Trigger<> disconnect_trigger_; +#endif private: // Stores a pointer to a string literal (static storage duration). diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1edc648084..ee865a7e65 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -227,6 +227,8 @@ #define USE_WIFI_SCAN_RESULTS_LISTENERS #define USE_WIFI_CONNECT_STATE_LISTENERS #define USE_WIFI_POWER_SAVE_LISTENERS +#define USE_WIFI_CONNECT_TRIGGER +#define USE_WIFI_DISCONNECT_TRIGGER #define ESPHOME_WIFI_IP_STATE_LISTENERS 2 #define ESPHOME_WIFI_SCAN_RESULTS_LISTENERS 2 #define ESPHOME_WIFI_CONNECT_STATE_LISTENERS 2 diff --git a/tests/components/wifi/common.yaml b/tests/components/wifi/common.yaml index 7ce74ab00d..10b68347eb 100644 --- a/tests/components/wifi/common.yaml +++ b/tests/components/wifi/common.yaml @@ -26,3 +26,7 @@ wifi: - ssid: MySSID3 password: password3 priority: 0 + on_connect: + - logger.log: "WiFi connected!" + on_disconnect: + - logger.log: "WiFi disconnected!" From 8cb701e4128abdf0508ad90e97bffda0263accda Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 04:29:31 +0100 Subject: [PATCH 0485/2030] [water_heater] Store mode strings in flash and avoid heap allocation in set_mode (#13728) --- .../components/water_heater/water_heater.cpp | 19 ++++++++++--------- .../components/water_heater/water_heater.h | 3 ++- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 7266294d84..286addf7db 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -2,6 +2,7 @@ #include "esphome/core/log.h" #include "esphome/core/application.h" #include "esphome/core/controller_registry.h" +#include "esphome/core/progmem.h" #include @@ -22,23 +23,23 @@ WaterHeaterCall &WaterHeaterCall::set_mode(WaterHeaterMode mode) { return *this; } -WaterHeaterCall &WaterHeaterCall::set_mode(const std::string &mode) { - if (str_equals_case_insensitive(mode, "OFF")) { +WaterHeaterCall &WaterHeaterCall::set_mode(const char *mode) { + if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("OFF")) == 0) { this->set_mode(WATER_HEATER_MODE_OFF); - } else if (str_equals_case_insensitive(mode, "ECO")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("ECO")) == 0) { this->set_mode(WATER_HEATER_MODE_ECO); - } else if (str_equals_case_insensitive(mode, "ELECTRIC")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("ELECTRIC")) == 0) { this->set_mode(WATER_HEATER_MODE_ELECTRIC); - } else if (str_equals_case_insensitive(mode, "PERFORMANCE")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("PERFORMANCE")) == 0) { this->set_mode(WATER_HEATER_MODE_PERFORMANCE); - } else if (str_equals_case_insensitive(mode, "HIGH_DEMAND")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("HIGH_DEMAND")) == 0) { this->set_mode(WATER_HEATER_MODE_HIGH_DEMAND); - } else if (str_equals_case_insensitive(mode, "HEAT_PUMP")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("HEAT_PUMP")) == 0) { this->set_mode(WATER_HEATER_MODE_HEAT_PUMP); - } else if (str_equals_case_insensitive(mode, "GAS")) { + } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("GAS")) == 0) { this->set_mode(WATER_HEATER_MODE_GAS); } else { - ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode.c_str()); + ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode); } return *this; } diff --git a/esphome/components/water_heater/water_heater.h b/esphome/components/water_heater/water_heater.h index 84fc46d208..7bd05ba7f5 100644 --- a/esphome/components/water_heater/water_heater.h +++ b/esphome/components/water_heater/water_heater.h @@ -75,7 +75,8 @@ class WaterHeaterCall { WaterHeaterCall(WaterHeater *parent); WaterHeaterCall &set_mode(WaterHeaterMode mode); - WaterHeaterCall &set_mode(const std::string &mode); + WaterHeaterCall &set_mode(const char *mode); + WaterHeaterCall &set_mode(const std::string &mode) { return this->set_mode(mode.c_str()); } WaterHeaterCall &set_target_temperature(float temperature); WaterHeaterCall &set_target_temperature_low(float temperature); WaterHeaterCall &set_target_temperature_high(float temperature); From 9d63642bdb16598ab8c0ec3eafbb00178df96955 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 04:29:43 +0100 Subject: [PATCH 0486/2030] [media_player] Store command strings in flash and avoid heap allocation in set_command (#13731) --- .../components/media_player/media_player.cpp | 21 ++++++++++--------- .../components/media_player/media_player.h | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index b46ec39d30..17d9b054da 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace media_player { @@ -107,25 +108,25 @@ MediaPlayerCall &MediaPlayerCall::set_command(optional comma this->command_ = command; return *this; } -MediaPlayerCall &MediaPlayerCall::set_command(const std::string &command) { - if (str_equals_case_insensitive(command, "PLAY")) { +MediaPlayerCall &MediaPlayerCall::set_command(const char *command) { + if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("PLAY")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_PLAY); - } else if (str_equals_case_insensitive(command, "PAUSE")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("PAUSE")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_PAUSE); - } else if (str_equals_case_insensitive(command, "STOP")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("STOP")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_STOP); - } else if (str_equals_case_insensitive(command, "MUTE")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("MUTE")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_MUTE); - } else if (str_equals_case_insensitive(command, "UNMUTE")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("UNMUTE")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_UNMUTE); - } else if (str_equals_case_insensitive(command, "TOGGLE")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_TOGGLE); - } else if (str_equals_case_insensitive(command, "TURN_ON")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TURN_ON")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_TURN_ON); - } else if (str_equals_case_insensitive(command, "TURN_OFF")) { + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TURN_OFF")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_TURN_OFF); } else { - ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command.c_str()); + ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command); } return *this; } diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index b753e2d088..f75a68dd85 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -114,7 +114,8 @@ class MediaPlayerCall { MediaPlayerCall &set_command(MediaPlayerCommand command); MediaPlayerCall &set_command(optional command); - MediaPlayerCall &set_command(const std::string &command); + MediaPlayerCall &set_command(const char *command); + MediaPlayerCall &set_command(const std::string &command) { return this->set_command(command.c_str()); } MediaPlayerCall &set_media_url(const std::string &url); From fbeb0e8e542af3b8b4f2f86a1fc8d46e2bb915ac Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 04:40:44 +0100 Subject: [PATCH 0487/2030] [opentherm] Fix ESP-IDF build by re-enabling legacy driver component (#13732) --- esphome/components/opentherm/__init__.py | 8 ++++++++ esphome/components/opentherm/opentherm.cpp | 2 ++ esphome/components/opentherm/opentherm.h | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/esphome/components/opentherm/__init__.py b/esphome/components/opentherm/__init__.py index 8cbee1eed2..dddb9dc891 100644 --- a/esphome/components/opentherm/__init__.py +++ b/esphome/components/opentherm/__init__.py @@ -4,8 +4,10 @@ from typing import Any from esphome import automation, pins import esphome.codegen as cg from esphome.components import sensor +from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_TRIGGER_ID, PLATFORM_ESP32, PLATFORM_ESP8266 +from esphome.core import CORE from . import const, generate, schema, validate @@ -83,6 +85,12 @@ CONFIG_SCHEMA = cv.All( async def to_code(config: dict[str, Any]) -> None: + if CORE.is_esp32: + # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) + # Provides driver/timer.h header for hardware timer API + # TODO: Remove this once opentherm migrates to GPTimer API (driver/gptimer.h) + include_builtin_idf_component("driver") + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/opentherm/opentherm.cpp b/esphome/components/opentherm/opentherm.cpp index 2bf438a52f..cdf89207bc 100644 --- a/esphome/components/opentherm/opentherm.cpp +++ b/esphome/components/opentherm/opentherm.cpp @@ -8,6 +8,8 @@ #include "opentherm.h" #include "esphome/core/helpers.h" #include +// TODO: Migrate from legacy timer API (driver/timer.h) to GPTimer API (driver/gptimer.h) +// The legacy timer API is deprecated in ESP-IDF 5.x. See opentherm.h for details. #ifdef USE_ESP32 #include "driver/timer.h" #include "esp_err.h" diff --git a/esphome/components/opentherm/opentherm.h b/esphome/components/opentherm/opentherm.h index 3996481760..a2c347d0d8 100644 --- a/esphome/components/opentherm/opentherm.h +++ b/esphome/components/opentherm/opentherm.h @@ -12,6 +12,10 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +// TODO: Migrate from legacy timer API (driver/timer.h) to GPTimer API (driver/gptimer.h) +// The legacy timer API is deprecated in ESP-IDF 5.x. Migration would allow removing the +// "driver" IDF component dependency. See: +// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/peripherals.html#id4 #ifdef USE_ESP32 #include "driver/timer.h" #endif From a430b3a42606696bda318af4314c1be26103a0b5 Mon Sep 17 00:00:00 2001 From: Roger Fachini Date: Mon, 2 Feb 2026 19:46:46 -0800 Subject: [PATCH 0488/2030] [speaker.media_player]: Add verbose error message for puremagic parsing (#13725) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/speaker/media_player/__init__.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/speaker/media_player/__init__.py b/esphome/components/speaker/media_player/__init__.py index 370b4576a7..034312236c 100644 --- a/esphome/components/speaker/media_player/__init__.py +++ b/esphome/components/speaker/media_player/__init__.py @@ -157,8 +157,14 @@ def _read_audio_file_and_type(file_config): import puremagic - file_type: str = puremagic.from_string(data) - file_type = file_type.removeprefix(".") + try: + file_type: str = puremagic.from_string(data) + file_type = file_type.removeprefix(".") + except puremagic.PureError as e: + raise cv.Invalid( + f"Unable to determine audio file type of '{path}'. " + f"Try re-encoding the file into a supported format. Details: {e}" + ) media_file_type = audio.AUDIO_FILE_TYPE_ENUM["NONE"] if file_type in ("wav"): From ff6f7d3248926c7594a2de969b3fc2f6d93b3550 Mon Sep 17 00:00:00 2001 From: Andrew Gillis Date: Mon, 2 Feb 2026 22:59:51 -0500 Subject: [PATCH 0489/2030] [mipi_dsi] Add WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B (#13608) --- .../components/mipi_dsi/models/waveshare.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/esphome/components/mipi_dsi/models/waveshare.py b/esphome/components/mipi_dsi/models/waveshare.py index c3d080f8b2..f83cacc5a3 100644 --- a/esphome/components/mipi_dsi/models/waveshare.py +++ b/esphome/components/mipi_dsi/models/waveshare.py @@ -94,3 +94,29 @@ DriverChip( (0x29, 0x00), ], ) + +DriverChip( + "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B", + height=600, + width=1024, + hsync_back_porch=160, + hsync_pulse_width=10, + hsync_front_porch=160, + vsync_back_porch=23, + vsync_pulse_width=1, + vsync_front_porch=12, + pclk_frequency="52MHz", + lane_bit_rate="900Mbps", + no_transform=True, + color_order="RGB", + initsequence=[ + (0x80, 0x8B), + (0x81, 0x78), + (0x82, 0x84), + (0x83, 0x88), + (0x84, 0xA8), + (0x85, 0xE3), + (0x86, 0x88), + (0xB2, 0x10), + ], +) From d4110bf6507be83235a5c397dd442574519cf99d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 05:29:24 +0100 Subject: [PATCH 0490/2030] [lock] Store state strings in flash and avoid heap allocation in set_state (#13729) --- esphome/components/lock/lock.cpp | 17 +++++++++-------- esphome/components/lock/lock.h | 3 ++- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 9fa1ba3600..4c61418256 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome::lock { @@ -84,21 +85,21 @@ LockCall &LockCall::set_state(optional state) { this->state_ = state; return *this; } -LockCall &LockCall::set_state(const std::string &state) { - if (str_equals_case_insensitive(state, "LOCKED")) { +LockCall &LockCall::set_state(const char *state) { + if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("LOCKED")) == 0) { this->set_state(LOCK_STATE_LOCKED); - } else if (str_equals_case_insensitive(state, "UNLOCKED")) { + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("UNLOCKED")) == 0) { this->set_state(LOCK_STATE_UNLOCKED); - } else if (str_equals_case_insensitive(state, "JAMMED")) { + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("JAMMED")) == 0) { this->set_state(LOCK_STATE_JAMMED); - } else if (str_equals_case_insensitive(state, "LOCKING")) { + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("LOCKING")) == 0) { this->set_state(LOCK_STATE_LOCKING); - } else if (str_equals_case_insensitive(state, "UNLOCKING")) { + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("UNLOCKING")) == 0) { this->set_state(LOCK_STATE_UNLOCKING); - } else if (str_equals_case_insensitive(state, "NONE")) { + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("NONE")) == 0) { this->set_state(LOCK_STATE_NONE); } else { - ESP_LOGW(TAG, "'%s' - Unrecognized state %s", this->parent_->get_name().c_str(), state.c_str()); + ESP_LOGW(TAG, "'%s' - Unrecognized state %s", this->parent_->get_name().c_str(), state); } return *this; } diff --git a/esphome/components/lock/lock.h b/esphome/components/lock/lock.h index 69fc405713..bebd296eac 100644 --- a/esphome/components/lock/lock.h +++ b/esphome/components/lock/lock.h @@ -83,7 +83,8 @@ class LockCall { /// Set the state of the lock device. LockCall &set_state(optional state); /// Set the state of the lock device based on a string. - LockCall &set_state(const std::string &state); + LockCall &set_state(const char *state); + LockCall &set_state(const std::string &state) { return this->set_state(state.c_str()); } void perform(); From b3e09e5c68b4734bb8cd896ce8aedd00523e1a02 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 3 Feb 2026 21:14:09 +1100 Subject: [PATCH 0491/2030] [key_collector] Add text sensor and allow multiple callbacks (#13617) --- esphome/components/key_collector/__init__.py | 91 +++++++++++++------ .../key_collector/key_collector.cpp | 45 +++++---- .../components/key_collector/key_collector.h | 36 ++++---- .../key_collector/text_sensor/__init__.py | 28 ++++++ tests/components/key_collector/common.yaml | 14 +++ 5 files changed, 146 insertions(+), 68 deletions(-) create mode 100644 esphome/components/key_collector/text_sensor/__init__.py diff --git a/esphome/components/key_collector/__init__.py b/esphome/components/key_collector/__init__.py index 17af40da1a..badb28c32c 100644 --- a/esphome/components/key_collector/__init__.py +++ b/esphome/components/key_collector/__init__.py @@ -1,4 +1,7 @@ +from dataclasses import dataclass + from esphome import automation +from esphome.automation import Trigger import esphome.codegen as cg from esphome.components import key_provider import esphome.config_validation as cv @@ -10,7 +13,10 @@ from esphome.const import ( CONF_ON_TIMEOUT, CONF_SOURCE_ID, CONF_TIMEOUT, + CONF_TRIGGER_ID, ) +from esphome.cpp_generator import MockObj, literal +from esphome.types import TemplateArgsType CODEOWNERS = ["@ssieb"] @@ -32,22 +38,50 @@ KeyCollector = key_collector_ns.class_("KeyCollector", cg.Component) EnableAction = key_collector_ns.class_("EnableAction", automation.Action) DisableAction = key_collector_ns.class_("DisableAction", automation.Action) +X_TYPE = cg.std_string_ref.operator("const") + + +@dataclass +class Argument: + type: MockObj + name: str + + +TRIGGER_TYPES = { + CONF_ON_PROGRESS: [Argument(X_TYPE, "x"), Argument(cg.uint8, "start")], + CONF_ON_RESULT: [ + Argument(X_TYPE, "x"), + Argument(cg.uint8, "start"), + Argument(cg.uint8, "end"), + ], + CONF_ON_TIMEOUT: [Argument(X_TYPE, "x"), Argument(cg.uint8, "start")], +} + CONFIG_SCHEMA = cv.All( cv.COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(KeyCollector), - cv.Optional(CONF_SOURCE_ID): cv.use_id(key_provider.KeyProvider), - cv.Optional(CONF_MIN_LENGTH): cv.int_, - cv.Optional(CONF_MAX_LENGTH): cv.int_, + cv.Optional(CONF_SOURCE_ID): cv.ensure_list( + cv.use_id(key_provider.KeyProvider) + ), + cv.Optional(CONF_MIN_LENGTH): cv.uint16_t, + cv.Optional(CONF_MAX_LENGTH): cv.uint16_t, cv.Optional(CONF_START_KEYS): cv.string, cv.Optional(CONF_END_KEYS): cv.string, cv.Optional(CONF_END_KEY_REQUIRED): cv.boolean, cv.Optional(CONF_BACK_KEYS): cv.string, cv.Optional(CONF_CLEAR_KEYS): cv.string, cv.Optional(CONF_ALLOWED_KEYS): cv.string, - cv.Optional(CONF_ON_PROGRESS): automation.validate_automation(single=True), - cv.Optional(CONF_ON_RESULT): automation.validate_automation(single=True), - cv.Optional(CONF_ON_TIMEOUT): automation.validate_automation(single=True), + **{ + cv.Optional(trigger_type): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + Trigger.template(*[arg.type for arg in args]) + ), + } + ) + for trigger_type, args in TRIGGER_TYPES.items() + }, cv.Optional(CONF_TIMEOUT): cv.positive_time_period_milliseconds, cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, } @@ -59,9 +93,9 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - if CONF_SOURCE_ID in config: - source = await cg.get_variable(config[CONF_SOURCE_ID]) - cg.add(var.set_provider(source)) + for source_conf in config.get(CONF_SOURCE_ID, ()): + source = await cg.get_variable(source_conf) + cg.add(var.add_provider(source)) if CONF_MIN_LENGTH in config: cg.add(var.set_min_length(config[CONF_MIN_LENGTH])) if CONF_MAX_LENGTH in config: @@ -78,26 +112,25 @@ async def to_code(config): cg.add(var.set_clear_keys(config[CONF_CLEAR_KEYS])) if CONF_ALLOWED_KEYS in config: cg.add(var.set_allowed_keys(config[CONF_ALLOWED_KEYS])) - if CONF_ON_PROGRESS in config: - await automation.build_automation( - var.get_progress_trigger(), - [(cg.std_string, "x"), (cg.uint8, "start")], - config[CONF_ON_PROGRESS], - ) - if CONF_ON_RESULT in config: - await automation.build_automation( - var.get_result_trigger(), - [(cg.std_string, "x"), (cg.uint8, "start"), (cg.uint8, "end")], - config[CONF_ON_RESULT], - ) - if CONF_ON_TIMEOUT in config: - await automation.build_automation( - var.get_timeout_trigger(), - [(cg.std_string, "x"), (cg.uint8, "start")], - config[CONF_ON_TIMEOUT], - ) - if CONF_TIMEOUT in config: - cg.add(var.set_timeout(config[CONF_TIMEOUT])) + + for trigger_name, args in TRIGGER_TYPES.items(): + arglist: TemplateArgsType = [(arg.type, arg.name) for arg in args] + for conf in config.get(trigger_name, ()): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) + add_trig = getattr( + var, + f"add_on_{trigger_name.rsplit('_', maxsplit=1)[-1].lower()}_callback", + ) + await automation.build_automation( + trigger, + arglist, + conf, + ) + lamb = trigger.trigger(*[literal(arg.name) for arg in args]) + cg.add(add_trig(await cg.process_lambda(lamb, arglist))) + + if timeout := config.get(CONF_TIMEOUT): + cg.add(var.set_timeout(timeout)) cg.add(var.set_enabled(config[CONF_ENABLE_ON_BOOT])) diff --git a/esphome/components/key_collector/key_collector.cpp b/esphome/components/key_collector/key_collector.cpp index 9cfc74f50e..68d1c60bf9 100644 --- a/esphome/components/key_collector/key_collector.cpp +++ b/esphome/components/key_collector/key_collector.cpp @@ -7,15 +7,10 @@ namespace key_collector { static const char *const TAG = "key_collector"; -KeyCollector::KeyCollector() - : progress_trigger_(new Trigger()), - result_trigger_(new Trigger()), - timeout_trigger_(new Trigger()) {} - void KeyCollector::loop() { if ((this->timeout_ == 0) || this->result_.empty() || (millis() - this->last_key_time_ < this->timeout_)) return; - this->timeout_trigger_->trigger(this->result_, this->start_key_); + this->timeout_callbacks_.call(this->result_, this->start_key_); this->clear(); } @@ -43,64 +38,68 @@ void KeyCollector::dump_config() { ESP_LOGCONFIG(TAG, " entry timeout: %0.1f", this->timeout_ / 1000.0); } -void KeyCollector::set_provider(key_provider::KeyProvider *provider) { - provider->add_on_key_callback([this](uint8_t key) { this->key_pressed_(key); }); +void KeyCollector::add_provider(key_provider::KeyProvider *provider) { + provider->add_on_key_callback([this](uint8_t key) { this->send_key(key); }); } void KeyCollector::set_enabled(bool enabled) { this->enabled_ = enabled; - if (!enabled) + if (!enabled) { this->clear(false); + } } void KeyCollector::clear(bool progress_update) { + auto had_state = !this->result_.empty() || this->start_key_ != 0; this->result_.clear(); this->start_key_ = 0; - if (progress_update) - this->progress_trigger_->trigger(this->result_, 0); + if (progress_update && had_state) { + this->progress_callbacks_.call(this->result_, 0); + } + this->disable_loop(); } -void KeyCollector::send_key(uint8_t key) { this->key_pressed_(key); } - -void KeyCollector::key_pressed_(uint8_t key) { +void KeyCollector::send_key(uint8_t key) { if (!this->enabled_) return; this->last_key_time_ = millis(); if (!this->start_keys_.empty() && !this->start_key_) { if (this->start_keys_.find(key) != std::string::npos) { this->start_key_ = key; - this->progress_trigger_->trigger(this->result_, this->start_key_); + this->progress_callbacks_.call(this->result_, this->start_key_); } return; } if (this->back_keys_.find(key) != std::string::npos) { if (!this->result_.empty()) { this->result_.pop_back(); - this->progress_trigger_->trigger(this->result_, this->start_key_); + this->progress_callbacks_.call(this->result_, this->start_key_); } return; } if (this->clear_keys_.find(key) != std::string::npos) { - if (!this->result_.empty()) - this->clear(); + this->clear(); return; } if (this->end_keys_.find(key) != std::string::npos) { if ((this->min_length_ == 0) || (this->result_.size() >= this->min_length_)) { - this->result_trigger_->trigger(this->result_, this->start_key_, key); + this->result_callbacks_.call(this->result_, this->start_key_, key); this->clear(); } return; } - if (!this->allowed_keys_.empty() && (this->allowed_keys_.find(key) == std::string::npos)) + if (!this->allowed_keys_.empty() && this->allowed_keys_.find(key) == std::string::npos) return; - if ((this->max_length_ == 0) || (this->result_.size() < this->max_length_)) + if ((this->max_length_ == 0) || (this->result_.size() < this->max_length_)) { + if (this->result_.empty()) + this->enable_loop(); this->result_.push_back(key); + } if ((this->max_length_ > 0) && (this->result_.size() == this->max_length_) && (!this->end_key_required_)) { - this->result_trigger_->trigger(this->result_, this->start_key_, 0); + this->result_callbacks_.call(this->result_, this->start_key_, 0); this->clear(false); } - this->progress_trigger_->trigger(this->result_, this->start_key_); + this->progress_callbacks_.call(this->result_, this->start_key_); } } // namespace key_collector diff --git a/esphome/components/key_collector/key_collector.h b/esphome/components/key_collector/key_collector.h index 735f396809..8e30c333df 100644 --- a/esphome/components/key_collector/key_collector.h +++ b/esphome/components/key_collector/key_collector.h @@ -3,27 +3,33 @@ #include #include "esphome/components/key_provider/key_provider.h" #include "esphome/core/automation.h" +#include "esphome/core/helpers.h" namespace esphome { namespace key_collector { class KeyCollector : public Component { public: - KeyCollector(); void loop() override; void dump_config() override; - void set_provider(key_provider::KeyProvider *provider); - void set_min_length(uint32_t min_length) { this->min_length_ = min_length; }; - void set_max_length(uint32_t max_length) { this->max_length_ = max_length; }; + void add_provider(key_provider::KeyProvider *provider); + void set_min_length(uint16_t min_length) { this->min_length_ = min_length; }; + void set_max_length(uint16_t max_length) { this->max_length_ = max_length; }; void set_start_keys(std::string start_keys) { this->start_keys_ = std::move(start_keys); }; void set_end_keys(std::string end_keys) { this->end_keys_ = std::move(end_keys); }; void set_end_key_required(bool end_key_required) { this->end_key_required_ = end_key_required; }; void set_back_keys(std::string back_keys) { this->back_keys_ = std::move(back_keys); }; void set_clear_keys(std::string clear_keys) { this->clear_keys_ = std::move(clear_keys); }; void set_allowed_keys(std::string allowed_keys) { this->allowed_keys_ = std::move(allowed_keys); }; - Trigger *get_progress_trigger() const { return this->progress_trigger_; }; - Trigger *get_result_trigger() const { return this->result_trigger_; }; - Trigger *get_timeout_trigger() const { return this->timeout_trigger_; }; + void add_on_progress_callback(std::function &&callback) { + this->progress_callbacks_.add(std::move(callback)); + } + void add_on_result_callback(std::function &&callback) { + this->result_callbacks_.add(std::move(callback)); + } + void add_on_timeout_callback(std::function &&callback) { + this->timeout_callbacks_.add(std::move(callback)); + } void set_timeout(int timeout) { this->timeout_ = timeout; }; void set_enabled(bool enabled); @@ -31,10 +37,8 @@ class KeyCollector : public Component { void send_key(uint8_t key); protected: - void key_pressed_(uint8_t key); - - uint32_t min_length_{0}; - uint32_t max_length_{0}; + uint16_t min_length_{0}; + uint16_t max_length_{0}; std::string start_keys_; std::string end_keys_; bool end_key_required_{false}; @@ -43,12 +47,12 @@ class KeyCollector : public Component { std::string allowed_keys_; std::string result_; uint8_t start_key_{0}; - Trigger *progress_trigger_; - Trigger *result_trigger_; - Trigger *timeout_trigger_; - uint32_t last_key_time_; + LazyCallbackManager progress_callbacks_; + LazyCallbackManager result_callbacks_; + LazyCallbackManager timeout_callbacks_; + uint32_t last_key_time_{}; uint32_t timeout_{0}; - bool enabled_; + bool enabled_{}; }; template class EnableAction : public Action, public Parented { diff --git a/esphome/components/key_collector/text_sensor/__init__.py b/esphome/components/key_collector/text_sensor/__init__.py new file mode 100644 index 0000000000..1676cf7bdf --- /dev/null +++ b/esphome/components/key_collector/text_sensor/__init__.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +from esphome.components.text_sensor import TextSensor +import esphome.config_validation as cv +from esphome.const import CONF_ID +from esphome.cpp_generator import literal +from esphome.types import TemplateArgsType + +from .. import CONF_ON_RESULT, CONF_SOURCE_ID, TRIGGER_TYPES, KeyCollector + +CONFIG_SCHEMA = text_sensor.text_sensor_schema(TextSensor).extend( + { + cv.GenerateID(CONF_SOURCE_ID): cv.use_id(KeyCollector), + } +) + + +async def to_code(config): + parent = await cg.get_variable(config[CONF_SOURCE_ID]) + var = cg.new_Pvariable(config[CONF_ID]) + await text_sensor.register_text_sensor(var, config) + args = TRIGGER_TYPES[CONF_ON_RESULT] + arglist: TemplateArgsType = [(arg.type, arg.name) for arg in args] + cg.add( + parent.add_on_result_callback( + await cg.process_lambda(var.publish_state(literal(args[0].name)), arglist) + ) + ) diff --git a/tests/components/key_collector/common.yaml b/tests/components/key_collector/common.yaml index 12e541c865..43a0478a18 100644 --- a/tests/components/key_collector/common.yaml +++ b/tests/components/key_collector/common.yaml @@ -18,14 +18,23 @@ key_collector: - logger.log: format: "input progress: '%s', started by '%c'" args: ['x.c_str()', "(start == 0 ? '~' : start)"] + - logger.log: + format: "second listener - progress: '%s'" + args: ['x.c_str()'] on_result: - logger.log: format: "input result: '%s', started by '%c', ended by '%c'" args: ['x.c_str()', "(start == 0 ? '~' : start)", "(end == 0 ? '~' : end)"] + - logger.log: + format: "second listener - result: '%s'" + args: ['x.c_str()'] on_timeout: - logger.log: format: "input timeout: '%s', started by '%c'" args: ['x.c_str()', "(start == 0 ? '~' : start)"] + - logger.log: + format: "second listener - timeout: '%s'" + args: ['x.c_str()'] enable_on_boot: false button: @@ -34,3 +43,8 @@ button: on_press: - key_collector.enable: - key_collector.disable: + +text_sensor: + - platform: key_collector + id: collected_keys + source_id: reader From c027d9116febad4cd55d647b2090f22b4f3467e2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 12:13:03 +0100 Subject: [PATCH 0492/2030] [template] Add additional tests for template select (#13741) --- tests/components/template/common-base.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index 9dc65fbab8..9dece7c3a5 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -296,6 +296,16 @@ select: // Migration guide: Store in std::string std::string stored_option(id(template_select).current_option()); ESP_LOGI("test", "Stored: %s", stored_option.c_str()); + - platform: template + id: template_select_with_action + name: "Template select with action" + options: + - option_a + - option_b + set_action: + - logger.log: + format: "Selected: %s" + args: ["x.c_str()"] lock: - platform: template From f4d7d06c41a5347ae94bd857e8cfe62f1da5b8ab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 12:23:05 +0100 Subject: [PATCH 0493/2030] [dlms_meter] Rename test UART package key to match directory name (#13743) --- tests/components/dlms_meter/test.esp32-ard.yaml | 2 +- tests/components/dlms_meter/test.esp32-idf.yaml | 2 +- tests/components/dlms_meter/test.esp8266-ard.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/components/dlms_meter/test.esp32-ard.yaml b/tests/components/dlms_meter/test.esp32-ard.yaml index 4f8a06c31b..c9910aa600 100644 --- a/tests/components/dlms_meter/test.esp32-ard.yaml +++ b/tests/components/dlms_meter/test.esp32-ard.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_2400/esp32-ard.yaml + uart_2400: !include ../../test_build_components/common/uart_2400/esp32-ard.yaml <<: !include common-generic.yaml diff --git a/tests/components/dlms_meter/test.esp32-idf.yaml b/tests/components/dlms_meter/test.esp32-idf.yaml index f993515fce..1547532f1e 100644 --- a/tests/components/dlms_meter/test.esp32-idf.yaml +++ b/tests/components/dlms_meter/test.esp32-idf.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_2400/esp32-idf.yaml + uart_2400: !include ../../test_build_components/common/uart_2400/esp32-idf.yaml <<: !include common-netznoe.yaml diff --git a/tests/components/dlms_meter/test.esp8266-ard.yaml b/tests/components/dlms_meter/test.esp8266-ard.yaml index 2ce7955c9f..119a1978de 100644 --- a/tests/components/dlms_meter/test.esp8266-ard.yaml +++ b/tests/components/dlms_meter/test.esp8266-ard.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_2400/esp8266-ard.yaml + uart_2400: !include ../../test_build_components/common/uart_2400/esp8266-ard.yaml <<: !include common-generic.yaml From d0017ded5bc0cb62204892802986198694624ab2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 12:48:31 +0100 Subject: [PATCH 0494/2030] [template] Split TemplateSelect into TemplateSelectWithSetAction to save RAM (#13685) Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- .../components/template/select/__init__.py | 87 +++++++++++++------ .../template/select/template_select.cpp | 73 ++++++---------- .../template/select/template_select.h | 78 +++++++++++++---- .../fixtures/select_stringref_trigger.yaml | 16 +++- .../test_select_stringref_trigger.py | 24 +++-- 5 files changed, 180 insertions(+), 98 deletions(-) diff --git a/esphome/components/template/select/__init__.py b/esphome/components/template/select/__init__.py index 574f1f5fb7..8de0b65c2d 100644 --- a/esphome/components/template/select/__init__.py +++ b/esphome/components/template/select/__init__.py @@ -10,35 +10,65 @@ from esphome.const import ( CONF_OPTIONS, CONF_RESTORE_VALUE, CONF_SET_ACTION, + CONF_UPDATE_INTERVAL, + SCHEDULER_DONT_RUN, ) +from esphome.core import TimePeriodMilliseconds +from esphome.cpp_generator import TemplateArguments from .. import template_ns TemplateSelect = template_ns.class_( "TemplateSelect", select.Select, cg.PollingComponent ) +TemplateSelectWithSetAction = template_ns.class_( + "TemplateSelectWithSetAction", TemplateSelect +) def validate(config): + errors = [] if CONF_LAMBDA in config: if config[CONF_OPTIMISTIC]: - raise cv.Invalid("optimistic cannot be used with lambda") + errors.append( + cv.Invalid( + "optimistic cannot be used with lambda", path=[CONF_OPTIMISTIC] + ) + ) if CONF_INITIAL_OPTION in config: - raise cv.Invalid("initial_value cannot be used with lambda") + errors.append( + cv.Invalid( + "initial_value cannot be used with lambda", + path=[CONF_INITIAL_OPTION], + ) + ) if CONF_RESTORE_VALUE in config: - raise cv.Invalid("restore_value cannot be used with lambda") + errors.append( + cv.Invalid( + "restore_value cannot be used with lambda", + path=[CONF_RESTORE_VALUE], + ) + ) elif CONF_INITIAL_OPTION in config: if config[CONF_INITIAL_OPTION] not in config[CONF_OPTIONS]: - raise cv.Invalid( - f"initial_option '{config[CONF_INITIAL_OPTION]}' is not a valid option [{', '.join(config[CONF_OPTIONS])}]" + errors.append( + cv.Invalid( + f"initial_option '{config[CONF_INITIAL_OPTION]}' is not a valid option [{', '.join(config[CONF_OPTIONS])}]", + path=[CONF_INITIAL_OPTION], + ) ) else: config[CONF_INITIAL_OPTION] = config[CONF_OPTIONS][0] if not config[CONF_OPTIMISTIC] and CONF_SET_ACTION not in config: - raise cv.Invalid( - "Either optimistic mode must be enabled, or set_action must be set, to handle the option being set." + errors.append( + cv.Invalid( + "Either optimistic mode must be enabled, or set_action must be set, to handle the option being set." + ) ) + if errors: + raise cv.MultipleInvalid(errors) + return config @@ -62,29 +92,34 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) - await select.register_select(var, config, options=config[CONF_OPTIONS]) + var_id = config[CONF_ID] + if CONF_SET_ACTION in config: + var_id.type = TemplateSelectWithSetAction + has_lambda = CONF_LAMBDA in config + optimistic = config.get(CONF_OPTIMISTIC, False) + restore_value = config.get(CONF_RESTORE_VALUE, False) + options = config[CONF_OPTIONS] + initial_option = config.get(CONF_INITIAL_OPTION, 0) + initial_option_index = options.index(initial_option) if not has_lambda else 0 + + var = cg.new_Pvariable( + var_id, + TemplateArguments(has_lambda, optimistic, restore_value, initial_option_index), + ) + component_config = config.copy() + if not has_lambda: + # No point in polling if not using a lambda + component_config[CONF_UPDATE_INTERVAL] = TimePeriodMilliseconds( + milliseconds=SCHEDULER_DONT_RUN + ) + await cg.register_component(var, component_config) + await select.register_select(var, config, options=options) if CONF_LAMBDA in config: - template_ = await cg.process_lambda( + lambda_ = await cg.process_lambda( config[CONF_LAMBDA], [], return_type=cg.optional.template(cg.std_string) ) - cg.add(var.set_template(template_)) - - else: - # Only set if non-default to avoid bloating setup() function - if config[CONF_OPTIMISTIC]: - cg.add(var.set_optimistic(True)) - initial_option_index = config[CONF_OPTIONS].index(config[CONF_INITIAL_OPTION]) - # Only set if non-zero to avoid bloating setup() function - # (initial_option_index_ is zero-initialized in the header) - if initial_option_index != 0: - cg.add(var.set_initial_option_index(initial_option_index)) - - # Only set if True (default is False) - if config.get(CONF_RESTORE_VALUE): - cg.add(var.set_restore_value(True)) + cg.add(var.set_lambda(lambda_)) if CONF_SET_ACTION in config: await automation.build_automation( diff --git a/esphome/components/template/select/template_select.cpp b/esphome/components/template/select/template_select.cpp index fa34aa9fa7..e68729c2d4 100644 --- a/esphome/components/template/select/template_select.cpp +++ b/esphome/components/template/select/template_select.cpp @@ -5,61 +5,44 @@ namespace esphome::template_ { static const char *const TAG = "template.select"; -void TemplateSelect::setup() { - if (this->f_.has_value()) - return; - - size_t index = this->initial_option_index_; - if (this->restore_value_) { - this->pref_ = this->make_entity_preference(); - size_t restored_index; - if (this->pref_.load(&restored_index) && this->has_index(restored_index)) { - index = restored_index; - ESP_LOGD(TAG, "State from restore: %s", this->option_at(index)); - } else { - ESP_LOGD(TAG, "State from initial (could not load or invalid stored index): %s", this->option_at(index)); - } +void dump_config_helper(BaseTemplateSelect *sel_comp, bool optimistic, bool has_lambda, + const size_t initial_option_index, bool restore_value) { + LOG_SELECT("", "Template Select", sel_comp); + if (has_lambda) { + LOG_UPDATE_INTERVAL(sel_comp); } else { - ESP_LOGD(TAG, "State from initial: %s", this->option_at(index)); + ESP_LOGCONFIG(TAG, + " Optimistic: %s\n" + " Initial Option: %s\n" + " Restore Value: %s", + YESNO(optimistic), sel_comp->option_at(initial_option_index), YESNO(restore_value)); } - - this->publish_state(index); } -void TemplateSelect::update() { - if (!this->f_.has_value()) - return; +void setup_initial(BaseTemplateSelect *sel_comp, size_t initial_index) { + ESP_LOGD(TAG, "State from initial: %s", sel_comp->option_at(initial_index)); + sel_comp->publish_state(initial_index); +} - auto val = this->f_(); +void setup_with_restore(BaseTemplateSelect *sel_comp, ESPPreferenceObject &pref, size_t initial_index) { + size_t index = initial_index; + if (pref.load(&index) && sel_comp->has_index(index)) { + ESP_LOGD(TAG, "State from restore: %s", sel_comp->option_at(index)); + } else { + index = initial_index; + ESP_LOGD(TAG, "State from initial (no valid stored index): %s", sel_comp->option_at(initial_index)); + } + sel_comp->publish_state(index); +} + +void update_lambda(BaseTemplateSelect *sel_comp, const optional &val) { if (val.has_value()) { - if (!this->has_option(*val)) { + if (!sel_comp->has_option(*val)) { ESP_LOGE(TAG, "Lambda returned an invalid option: %s", (*val).c_str()); return; } - this->publish_state(*val); + sel_comp->publish_state(*val); } } -void TemplateSelect::control(size_t index) { - this->set_trigger_->trigger(StringRef(this->option_at(index))); - - if (this->optimistic_) - this->publish_state(index); - - if (this->restore_value_) - this->pref_.save(&index); -} - -void TemplateSelect::dump_config() { - LOG_SELECT("", "Template Select", this); - LOG_UPDATE_INTERVAL(this); - if (this->f_.has_value()) - return; - ESP_LOGCONFIG(TAG, - " Optimistic: %s\n" - " Initial Option: %s\n" - " Restore Value: %s", - YESNO(this->optimistic_), this->option_at(this->initial_option_index_), YESNO(this->restore_value_)); -} - } // namespace esphome::template_ diff --git a/esphome/components/template/select/template_select.h b/esphome/components/template/select/template_select.h index 114d25b9ce..5da6d732bd 100644 --- a/esphome/components/template/select/template_select.h +++ b/esphome/components/template/select/template_select.h @@ -9,29 +9,71 @@ namespace esphome::template_ { -class TemplateSelect final : public select::Select, public PollingComponent { - public: - template void set_template(F &&f) { this->f_.set(std::forward(f)); } +struct Empty {}; +class BaseTemplateSelect : public select::Select, public PollingComponent {}; - void setup() override; - void update() override; - void dump_config() override; +void dump_config_helper(BaseTemplateSelect *sel_comp, bool optimistic, bool has_lambda, size_t initial_option_index, + bool restore_value); +void setup_initial(BaseTemplateSelect *sel_comp, size_t initial_index); +void setup_with_restore(BaseTemplateSelect *sel_comp, ESPPreferenceObject &pref, size_t initial_index); +void update_lambda(BaseTemplateSelect *sel_comp, const optional &val); + +/// Base template select class - used when no set_action is configured + +template +class TemplateSelect : public BaseTemplateSelect { + public: + template void set_lambda(F &&f) { + if constexpr (HAS_LAMBDA) { + this->f_.set(std::forward(f)); + } + } + + void setup() override { + if constexpr (!HAS_LAMBDA) { + if constexpr (RESTORE_VALUE) { + this->pref_ = this->template make_entity_preference(); + setup_with_restore(this, this->pref_, INITIAL_OPTION_INDEX); + } else { + setup_initial(this, INITIAL_OPTION_INDEX); + } + } + } + + void update() override { + if constexpr (HAS_LAMBDA) { + update_lambda(this, this->f_()); + } + } + void dump_config() override { + dump_config_helper(this, OPTIMISTIC, HAS_LAMBDA, INITIAL_OPTION_INDEX, RESTORE_VALUE); + }; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return this->set_trigger_; } - void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } - void set_initial_option_index(size_t initial_option_index) { this->initial_option_index_ = initial_option_index; } - void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } + protected: + void control(size_t index) override { + if constexpr (OPTIMISTIC) + this->publish_state(index); + if constexpr (RESTORE_VALUE) + this->pref_.save(&index); + } + [[no_unique_address]] std::conditional_t, Empty> f_{}; + [[no_unique_address]] std::conditional_t pref_{}; +}; + +/// Template select with set_action trigger - only instantiated when set_action is configured +template +class TemplateSelectWithSetAction final + : public TemplateSelect { + public: + Trigger *get_set_trigger() { return &this->set_trigger_; } protected: - void control(size_t index) override; - bool optimistic_ = false; - size_t initial_option_index_{0}; - bool restore_value_ = false; - Trigger *set_trigger_ = new Trigger(); - TemplateLambda f_; - - ESPPreferenceObject pref_; + void control(size_t index) override { + this->set_trigger_.trigger(StringRef(this->option_at(index))); + TemplateSelect::control(index); + } + Trigger set_trigger_; }; } // namespace esphome::template_ diff --git a/tests/integration/fixtures/select_stringref_trigger.yaml b/tests/integration/fixtures/select_stringref_trigger.yaml index bb1e1fd843..5858e2f529 100644 --- a/tests/integration/fixtures/select_stringref_trigger.yaml +++ b/tests/integration/fixtures/select_stringref_trigger.yaml @@ -56,7 +56,21 @@ select: std::string prefix = x.substr(0, 6); ESP_LOGI("test", "Substr prefix: %s", prefix.c_str()); - # Second select with numeric options to test ADL functions + # Second select with set_action trigger (uses TemplateSelectWithSetAction subclass) + - platform: template + name: "Action Select" + id: action_select + options: + - "Action A" + - "Action B" + set_action: + then: + # Test: set_action trigger receives StringRef + - logger.log: + format: "set_action triggered: %s" + args: ['x.c_str()'] + + # Third select with numeric options to test ADL functions - platform: template name: "Baud Rate" id: baud_select diff --git a/tests/integration/test_select_stringref_trigger.py b/tests/integration/test_select_stringref_trigger.py index 7fc72a2290..5baba9c7f5 100644 --- a/tests/integration/test_select_stringref_trigger.py +++ b/tests/integration/test_select_stringref_trigger.py @@ -28,6 +28,8 @@ async def test_select_stringref_trigger( find_substr_future = loop.create_future() find_char_future = loop.create_future() substr_future = loop.create_future() + # set_action trigger (TemplateSelectWithSetAction subclass) + set_action_future = loop.create_future() # ADL functions stoi_future = loop.create_future() stol_future = loop.create_future() @@ -43,6 +45,8 @@ async def test_select_stringref_trigger( find_substr_pattern = re.compile(r"Found 'Option' in value") find_char_pattern = re.compile(r"Space at position: 6") # space at index 6 substr_pattern = re.compile(r"Substr prefix: Option") + # set_action trigger pattern (TemplateSelectWithSetAction subclass) + set_action_pattern = re.compile(r"set_action triggered: Action B") # ADL function patterns (115200 from baud rate select) stoi_pattern = re.compile(r"stoi result: 115200") stol_pattern = re.compile(r"stol result: 115200") @@ -67,6 +71,9 @@ async def test_select_stringref_trigger( find_char_future.set_result(True) if not substr_future.done() and substr_pattern.search(line): substr_future.set_result(True) + # set_action trigger + if not set_action_future.done() and set_action_pattern.search(line): + set_action_future.set_result(True) # ADL functions if not stoi_future.done() and stoi_pattern.search(line): stoi_future.set_result(True) @@ -89,22 +96,21 @@ async def test_select_stringref_trigger( # List entities to find our select entities, _ = await client.list_entities_services() - select_entity = next( - (e for e in entities if hasattr(e, "options") and e.name == "Test Select"), - None, - ) + select_entity = next((e for e in entities if e.name == "Test Select"), None) assert select_entity is not None, "Test Select entity not found" - baud_entity = next( - (e for e in entities if hasattr(e, "options") and e.name == "Baud Rate"), - None, - ) + baud_entity = next((e for e in entities if e.name == "Baud Rate"), None) assert baud_entity is not None, "Baud Rate entity not found" + action_entity = next((e for e in entities if e.name == "Action Select"), None) + assert action_entity is not None, "Action Select entity not found" + # Change select to Option B - this should trigger on_value with StringRef client.select_command(select_entity.key, "Option B") # Change baud to 115200 - this tests ADL functions (stoi, stol, stof, stod) client.select_command(baud_entity.key, "115200") + # Change action select - tests set_action trigger (TemplateSelectWithSetAction) + client.select_command(action_entity.key, "Action B") # Wait for all log messages confirming StringRef operations work try: @@ -118,6 +124,7 @@ async def test_select_stringref_trigger( find_substr_future, find_char_future, substr_future, + set_action_future, stoi_future, stol_future, stof_future, @@ -135,6 +142,7 @@ async def test_select_stringref_trigger( "find_substr": find_substr_future.done(), "find_char": find_char_future.done(), "substr": substr_future.done(), + "set_action": set_action_future.done(), "stoi": stoi_future.done(), "stol": stol_future.done(), "stof": stof_future.done(), From 21bd0ff6aaa23bc32e4ff52f850da33bd4cfc5f2 Mon Sep 17 00:00:00 2001 From: Tomer Shalev Date: Tue, 3 Feb 2026 15:37:27 +0200 Subject: [PATCH 0495/2030] [mqtt] Stop sending deprecated color_mode and brightness in light discovery (fixes #13666) (#13667) --- esphome/components/mqtt/mqtt_light.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/esphome/components/mqtt/mqtt_light.cpp b/esphome/components/mqtt/mqtt_light.cpp index 3e3537fa5c..aa47bdf996 100644 --- a/esphome/components/mqtt/mqtt_light.cpp +++ b/esphome/components/mqtt/mqtt_light.cpp @@ -47,7 +47,6 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery root[ESPHOME_F("schema")] = ESPHOME_F("json"); auto traits = this->state_->get_traits(); - root[MQTT_COLOR_MODE] = true; // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson JsonArray color_modes = root[ESPHOME_F("supported_color_modes")].to(); if (traits.supports_color_mode(ColorMode::ON_OFF)) @@ -68,10 +67,6 @@ void MQTTJSONLightComponent::send_discovery(JsonObject root, mqtt::SendDiscovery if (traits.supports_color_mode(ColorMode::RGB_COLD_WARM_WHITE)) color_modes.add(ESPHOME_F("rgbww")); - // legacy API - if (traits.supports_color_capability(ColorCapability::BRIGHTNESS)) - root[ESPHOME_F("brightness")] = true; - if (traits.supports_color_mode(ColorMode::COLOR_TEMPERATURE) || traits.supports_color_mode(ColorMode::COLD_WARM_WHITE)) { root[MQTT_MIN_MIREDS] = traits.get_min_mireds(); From 8d0ce49eb4b6d25761d59442f890e95705641527 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 16:34:15 +0100 Subject: [PATCH 0496/2030] [api] Eliminate intermediate buffers in protobuf dump helpers (#13742) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_pb2_dump.cpp | 27 ++++++------------------- esphome/components/api/proto.h | 14 +++++++++++++ script/api_protobuf/api_protobuf.py | 27 ++++++------------------- 3 files changed, 26 insertions(+), 42 deletions(-) diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 29121f05e0..e9db36ae21 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -23,15 +23,8 @@ static inline void append_field_prefix(DumpBuffer &out, const char *field_name, out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(DumpBuffer &out, const char *str) { - out.append(str); - out.append("\n"); -} - static inline void append_uint(DumpBuffer &out, uint32_t value) { - char buf[16]; - snprintf(buf, sizeof(buf), "%" PRIu32, value); - out.append(buf); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32, value)); } // RAII helper for message dump formatting @@ -49,31 +42,23 @@ class MessageDumpHelper { // Helper functions to reduce code duplication in dump methods static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRId32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%g", value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%g\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu64, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu64 "\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { @@ -112,7 +97,7 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); - append_with_newline(out, hex_buf); + out.append(hex_buf).append("\n"); } template<> const char *proto_enum_to_string(enums::EntityCategory value) { diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 2e0df297c3..552b4a4625 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -402,6 +402,20 @@ class DumpBuffer { const char *c_str() const { return buf_; } size_t size() const { return pos_; } + /// Get writable buffer pointer for use with buf_append_printf + char *data() { return buf_; } + /// Get current position for use with buf_append_printf + size_t pos() const { return pos_; } + /// Update position after buf_append_printf call + void set_pos(size_t pos) { + if (pos >= CAPACITY) { + pos_ = CAPACITY - 1; + } else { + pos_ = pos; + } + buf_[pos_] = '\0'; + } + private: void append_impl_(const char *str, size_t len) { size_t space = CAPACITY - 1 - pos_; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 7625458f9f..72103285e8 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2599,15 +2599,8 @@ static inline void append_field_prefix(DumpBuffer &out, const char *field_name, out.append(indent, ' ').append(field_name).append(": "); } -static inline void append_with_newline(DumpBuffer &out, const char *str) { - out.append(str); - out.append("\\n"); -} - static inline void append_uint(DumpBuffer &out, uint32_t value) { - char buf[16]; - snprintf(buf, sizeof(buf), "%" PRIu32, value); - out.append(buf); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32, value)); } // RAII helper for message dump formatting @@ -2625,31 +2618,23 @@ class MessageDumpHelper { // Helper functions to reduce code duplication in dump methods static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRId32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint32_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu32, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu32 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, float value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%g", value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%g\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, uint64_t value, int indent = 2) { - char buffer[64]; append_field_prefix(out, field_name, indent); - snprintf(buffer, 64, "%" PRIu64, value); - append_with_newline(out, buffer); + out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRIu64 "\\n", value)); } static void dump_field(DumpBuffer &out, const char *field_name, bool value, int indent = 2) { @@ -2689,7 +2674,7 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); - append_with_newline(out, hex_buf); + out.append(hex_buf).append("\\n"); } """ From 18f7e0e6b33526821b99cefd0b9575dbe68eee6f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 16:42:45 +0100 Subject: [PATCH 0497/2030] [pulse_counter][hlw8012] Fix ESP-IDF build by re-enabling legacy driver component (#13747) --- esphome/components/hlw8012/sensor.py | 8 ++++++++ .../components/pulse_counter/pulse_counter_sensor.h | 4 ++++ esphome/components/pulse_counter/sensor.py | 10 +++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/esphome/components/hlw8012/sensor.py b/esphome/components/hlw8012/sensor.py index 201ea4451f..4727877633 100644 --- a/esphome/components/hlw8012/sensor.py +++ b/esphome/components/hlw8012/sensor.py @@ -1,6 +1,7 @@ from esphome import pins import esphome.codegen as cg from esphome.components import sensor +from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv from esphome.const import ( CONF_CHANGE_MODE_EVERY, @@ -25,6 +26,7 @@ from esphome.const import ( UNIT_WATT, UNIT_WATT_HOURS, ) +from esphome.core import CORE AUTO_LOAD = ["pulse_counter"] @@ -91,6 +93,12 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): + if CORE.is_esp32: + # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) + # HLW8012 uses pulse_counter's PCNT storage which requires driver/pcnt.h + # TODO: Remove this once pulse_counter migrates to new PCNT API (driver/pulse_cnt.h) + include_builtin_idf_component("driver") + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index 5ba59cca2a..f906e9e5cb 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -6,6 +6,10 @@ #include +// TODO: Migrate from legacy PCNT API (driver/pcnt.h) to new PCNT API (driver/pulse_cnt.h) +// The legacy PCNT API is deprecated in ESP-IDF 5.x. Migration would allow removing the +// "driver" IDF component dependency. See: +// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/peripherals.html#id6 #if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) #include #define HAS_PCNT diff --git a/esphome/components/pulse_counter/sensor.py b/esphome/components/pulse_counter/sensor.py index dbf67fd2ad..65be5ee793 100644 --- a/esphome/components/pulse_counter/sensor.py +++ b/esphome/components/pulse_counter/sensor.py @@ -1,6 +1,7 @@ from esphome import automation, pins import esphome.codegen as cg from esphome.components import sensor +from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv from esphome.const import ( CONF_COUNT_MODE, @@ -126,7 +127,14 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): - var = await sensor.new_sensor(config, config.get(CONF_USE_PCNT)) + use_pcnt = config.get(CONF_USE_PCNT) + if CORE.is_esp32 and use_pcnt: + # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) + # Provides driver/pcnt.h header for hardware pulse counter API + # TODO: Remove this once pulse_counter migrates to new PCNT API (driver/pulse_cnt.h) + include_builtin_idf_component("driver") + + var = await sensor.new_sensor(config, use_pcnt) await cg.register_component(var, config) pin = await cg.gpio_pin_expression(config[CONF_PIN]) From b8b072cf8643dd8f0741d6657a92c99f7fcf2e92 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 16:43:27 +0100 Subject: [PATCH 0498/2030] [web_server_idf] Add const char* overloads for getParam/hasParam to avoid temporary string allocations (#13746) --- esphome/components/web_server_idf/utils.cpp | 13 +++++-------- esphome/components/web_server_idf/utils.h | 5 ++++- .../components/web_server_idf/web_server_idf.cpp | 6 +++--- esphome/components/web_server_idf/web_server_idf.h | 11 ++++++++--- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/esphome/components/web_server_idf/utils.cpp b/esphome/components/web_server_idf/utils.cpp index f27814062c..d3c3c3dc55 100644 --- a/esphome/components/web_server_idf/utils.cpp +++ b/esphome/components/web_server_idf/utils.cpp @@ -73,18 +73,15 @@ optional request_get_url_query(httpd_req_t *req) { return {str}; } -optional query_key_value(const std::string &query_url, const std::string &key) { - if (query_url.empty()) { +optional query_key_value(const char *query_url, size_t query_len, const char *key) { + if (query_url == nullptr || query_len == 0) { return {}; } - auto val = std::unique_ptr(new char[query_url.size()]); - if (!val) { - ESP_LOGE(TAG, "Not enough memory to the query key value"); - return {}; - } + // Use stack buffer for typical query strings, heap fallback for large ones + SmallBufferWithHeapFallback<256, char> val(query_len); - if (httpd_query_key_value(query_url.c_str(), key.c_str(), val.get(), query_url.size()) != ESP_OK) { + if (httpd_query_key_value(query_url, key, val.get(), query_len) != ESP_OK) { return {}; } diff --git a/esphome/components/web_server_idf/utils.h b/esphome/components/web_server_idf/utils.h index 3a86aec7ac..ae58f82398 100644 --- a/esphome/components/web_server_idf/utils.h +++ b/esphome/components/web_server_idf/utils.h @@ -15,7 +15,10 @@ size_t url_decode(char *str); bool request_has_header(httpd_req_t *req, const char *name); optional request_get_header(httpd_req_t *req, const char *name); optional request_get_url_query(httpd_req_t *req); -optional query_key_value(const std::string &query_url, const std::string &key); +optional query_key_value(const char *query_url, size_t query_len, const char *key); +inline optional query_key_value(const std::string &query_url, const std::string &key) { + return query_key_value(query_url.c_str(), query_url.size(), key.c_str()); +} // Helper function for case-insensitive character comparison inline bool char_equals_ci(char a, char b) { return ::tolower(a) == ::tolower(b); } diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 2e5a74cbef..9860810452 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -366,7 +366,7 @@ void AsyncWebServerRequest::requestAuthentication(const char *realm) const { } #endif -AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) { +AsyncWebParameter *AsyncWebServerRequest::getParam(const char *name) { // Check cache first - only successful lookups are cached for (auto *param : this->params_) { if (param->name() == name) { @@ -375,11 +375,11 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const std::string &name) { } // Look up value from query strings - optional val = query_key_value(this->post_query_, name); + optional val = query_key_value(this->post_query_.c_str(), this->post_query_.size(), name); if (!val.has_value()) { auto url_query = request_get_url_query(*this); if (url_query.has_value()) { - val = query_key_value(url_query.value(), name); + val = query_key_value(url_query.value().c_str(), url_query.value().size(), name); } } diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index e38913ef4a..817f47da79 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -162,19 +162,24 @@ class AsyncWebServerRequest { } // NOLINTNEXTLINE(readability-identifier-naming) - bool hasParam(const std::string &name) { return this->getParam(name) != nullptr; } + bool hasParam(const char *name) { return this->getParam(name) != nullptr; } // NOLINTNEXTLINE(readability-identifier-naming) - AsyncWebParameter *getParam(const std::string &name); + bool hasParam(const std::string &name) { return this->getParam(name.c_str()) != nullptr; } + // NOLINTNEXTLINE(readability-identifier-naming) + AsyncWebParameter *getParam(const char *name); + // NOLINTNEXTLINE(readability-identifier-naming) + AsyncWebParameter *getParam(const std::string &name) { return this->getParam(name.c_str()); } // NOLINTNEXTLINE(readability-identifier-naming) bool hasArg(const char *name) { return this->hasParam(name); } - std::string arg(const std::string &name) { + std::string arg(const char *name) { auto *param = this->getParam(name); if (param) { return param->value(); } return {}; } + std::string arg(const std::string &name) { return this->arg(name.c_str()); } operator httpd_req_t *() const { return this->req_; } optional get_header(const char *name) const; From 5d4bde98dcd251fc2762ca14356977bba0310fa1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 16:56:48 +0100 Subject: [PATCH 0499/2030] [mqtt] Refactor state publishing with dedicated enum-to-string helpers (#13544) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../mqtt/mqtt_alarm_control_panel.cpp | 65 ++--- esphome/components/mqtt/mqtt_climate.cpp | 269 ++++++++---------- esphome/components/mqtt/mqtt_component.cpp | 17 ++ esphome/components/mqtt/mqtt_component.h | 33 +++ esphome/components/mqtt/mqtt_cover.cpp | 25 +- esphome/components/mqtt/mqtt_fan.cpp | 16 +- esphome/components/mqtt/mqtt_valve.cpp | 25 +- 7 files changed, 253 insertions(+), 197 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index 263e554778..dc8f75d8f5 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -13,6 +13,33 @@ static const char *const TAG = "mqtt.alarm_control_panel"; using namespace esphome::alarm_control_panel; +static ProgmemStr alarm_state_to_mqtt_str(AlarmControlPanelState state) { + switch (state) { + case ACP_STATE_DISARMED: + return ESPHOME_F("disarmed"); + case ACP_STATE_ARMED_HOME: + return ESPHOME_F("armed_home"); + case ACP_STATE_ARMED_AWAY: + return ESPHOME_F("armed_away"); + case ACP_STATE_ARMED_NIGHT: + return ESPHOME_F("armed_night"); + case ACP_STATE_ARMED_VACATION: + return ESPHOME_F("armed_vacation"); + case ACP_STATE_ARMED_CUSTOM_BYPASS: + return ESPHOME_F("armed_custom_bypass"); + case ACP_STATE_PENDING: + return ESPHOME_F("pending"); + case ACP_STATE_ARMING: + return ESPHOME_F("arming"); + case ACP_STATE_DISARMING: + return ESPHOME_F("disarming"); + case ACP_STATE_TRIGGERED: + return ESPHOME_F("triggered"); + default: + return ESPHOME_F("unknown"); + } +} + MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel) : alarm_control_panel_(alarm_control_panel) {} void MQTTAlarmControlPanelComponent::setup() { @@ -85,43 +112,9 @@ const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return th bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } bool MQTTAlarmControlPanelComponent::publish_state() { - const char *state_s; - switch (this->alarm_control_panel_->get_state()) { - case ACP_STATE_DISARMED: - state_s = "disarmed"; - break; - case ACP_STATE_ARMED_HOME: - state_s = "armed_home"; - break; - case ACP_STATE_ARMED_AWAY: - state_s = "armed_away"; - break; - case ACP_STATE_ARMED_NIGHT: - state_s = "armed_night"; - break; - case ACP_STATE_ARMED_VACATION: - state_s = "armed_vacation"; - break; - case ACP_STATE_ARMED_CUSTOM_BYPASS: - state_s = "armed_custom_bypass"; - break; - case ACP_STATE_PENDING: - state_s = "pending"; - break; - case ACP_STATE_ARMING: - state_s = "arming"; - break; - case ACP_STATE_DISARMING: - state_s = "disarming"; - break; - case ACP_STATE_TRIGGERED: - state_s = "triggered"; - break; - default: - state_s = "unknown"; - } char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; - return this->publish(this->get_state_topic_to_(topic_buf), state_s); + return this->publish(this->get_state_topic_to_(topic_buf), + alarm_state_to_mqtt_str(this->alarm_control_panel_->get_state())); } } // namespace esphome::mqtt diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 37d643f9e7..673593ef84 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -1,5 +1,6 @@ #include "mqtt_climate.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,111 @@ static const char *const TAG = "mqtt.climate"; using namespace esphome::climate; +static ProgmemStr climate_mode_to_mqtt_str(ClimateMode mode) { + switch (mode) { + case CLIMATE_MODE_OFF: + return ESPHOME_F("off"); + case CLIMATE_MODE_HEAT_COOL: + return ESPHOME_F("heat_cool"); + case CLIMATE_MODE_AUTO: + return ESPHOME_F("auto"); + case CLIMATE_MODE_COOL: + return ESPHOME_F("cool"); + case CLIMATE_MODE_HEAT: + return ESPHOME_F("heat"); + case CLIMATE_MODE_FAN_ONLY: + return ESPHOME_F("fan_only"); + case CLIMATE_MODE_DRY: + return ESPHOME_F("dry"); + default: + return ESPHOME_F("unknown"); + } +} + +static ProgmemStr climate_action_to_mqtt_str(ClimateAction action) { + switch (action) { + case CLIMATE_ACTION_OFF: + return ESPHOME_F("off"); + case CLIMATE_ACTION_COOLING: + return ESPHOME_F("cooling"); + case CLIMATE_ACTION_HEATING: + return ESPHOME_F("heating"); + case CLIMATE_ACTION_IDLE: + return ESPHOME_F("idle"); + case CLIMATE_ACTION_DRYING: + return ESPHOME_F("drying"); + case CLIMATE_ACTION_FAN: + return ESPHOME_F("fan"); + default: + return ESPHOME_F("unknown"); + } +} + +static ProgmemStr climate_fan_mode_to_mqtt_str(ClimateFanMode fan_mode) { + switch (fan_mode) { + case CLIMATE_FAN_ON: + return ESPHOME_F("on"); + case CLIMATE_FAN_OFF: + return ESPHOME_F("off"); + case CLIMATE_FAN_AUTO: + return ESPHOME_F("auto"); + case CLIMATE_FAN_LOW: + return ESPHOME_F("low"); + case CLIMATE_FAN_MEDIUM: + return ESPHOME_F("medium"); + case CLIMATE_FAN_HIGH: + return ESPHOME_F("high"); + case CLIMATE_FAN_MIDDLE: + return ESPHOME_F("middle"); + case CLIMATE_FAN_FOCUS: + return ESPHOME_F("focus"); + case CLIMATE_FAN_DIFFUSE: + return ESPHOME_F("diffuse"); + case CLIMATE_FAN_QUIET: + return ESPHOME_F("quiet"); + default: + return ESPHOME_F("unknown"); + } +} + +static ProgmemStr climate_swing_mode_to_mqtt_str(ClimateSwingMode swing_mode) { + switch (swing_mode) { + case CLIMATE_SWING_OFF: + return ESPHOME_F("off"); + case CLIMATE_SWING_BOTH: + return ESPHOME_F("both"); + case CLIMATE_SWING_VERTICAL: + return ESPHOME_F("vertical"); + case CLIMATE_SWING_HORIZONTAL: + return ESPHOME_F("horizontal"); + default: + return ESPHOME_F("unknown"); + } +} + +static ProgmemStr climate_preset_to_mqtt_str(ClimatePreset preset) { + switch (preset) { + case CLIMATE_PRESET_NONE: + return ESPHOME_F("none"); + case CLIMATE_PRESET_HOME: + return ESPHOME_F("home"); + case CLIMATE_PRESET_ECO: + return ESPHOME_F("eco"); + case CLIMATE_PRESET_AWAY: + return ESPHOME_F("away"); + case CLIMATE_PRESET_BOOST: + return ESPHOME_F("boost"); + case CLIMATE_PRESET_COMFORT: + return ESPHOME_F("comfort"); + case CLIMATE_PRESET_SLEEP: + return ESPHOME_F("sleep"); + case CLIMATE_PRESET_ACTIVITY: + return ESPHOME_F("activity"); + default: + return ESPHOME_F("unknown"); + } +} + void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson auto traits = this->device_->get_traits(); @@ -260,34 +366,8 @@ const EntityBase *MQTTClimateComponent::get_entity() const { return this->device bool MQTTClimateComponent::publish_state_() { auto traits = this->device_->get_traits(); // mode - const char *mode_s; - switch (this->device_->mode) { - case CLIMATE_MODE_OFF: - mode_s = "off"; - break; - case CLIMATE_MODE_AUTO: - mode_s = "auto"; - break; - case CLIMATE_MODE_COOL: - mode_s = "cool"; - break; - case CLIMATE_MODE_HEAT: - mode_s = "heat"; - break; - case CLIMATE_MODE_FAN_ONLY: - mode_s = "fan_only"; - break; - case CLIMATE_MODE_DRY: - mode_s = "dry"; - break; - case CLIMATE_MODE_HEAT_COOL: - mode_s = "heat_cool"; - break; - default: - mode_s = "unknown"; - } bool success = true; - if (!this->publish(this->get_mode_state_topic(), mode_s)) + if (!this->publish(this->get_mode_state_topic(), climate_mode_to_mqtt_str(this->device_->mode))) success = false; int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); @@ -327,134 +407,37 @@ bool MQTTClimateComponent::publish_state_() { } if (traits.get_supports_presets() || !traits.get_supported_custom_presets().empty()) { - std::string payload; - if (this->device_->preset.has_value()) { - switch (this->device_->preset.value()) { - case CLIMATE_PRESET_NONE: - payload = "none"; - break; - case CLIMATE_PRESET_HOME: - payload = "home"; - break; - case CLIMATE_PRESET_AWAY: - payload = "away"; - break; - case CLIMATE_PRESET_BOOST: - payload = "boost"; - break; - case CLIMATE_PRESET_COMFORT: - payload = "comfort"; - break; - case CLIMATE_PRESET_ECO: - payload = "eco"; - break; - case CLIMATE_PRESET_SLEEP: - payload = "sleep"; - break; - case CLIMATE_PRESET_ACTIVITY: - payload = "activity"; - break; - default: - payload = "unknown"; - } - } - if (this->device_->has_custom_preset()) - payload = this->device_->get_custom_preset().c_str(); - if (!this->publish(this->get_preset_state_topic(), payload)) + if (this->device_->has_custom_preset()) { + if (!this->publish(this->get_preset_state_topic(), this->device_->get_custom_preset())) + success = false; + } else if (this->device_->preset.has_value()) { + if (!this->publish(this->get_preset_state_topic(), climate_preset_to_mqtt_str(this->device_->preset.value()))) + success = false; + } else if (!this->publish(this->get_preset_state_topic(), "")) { success = false; + } } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { - const char *payload; - switch (this->device_->action) { - case CLIMATE_ACTION_OFF: - payload = "off"; - break; - case CLIMATE_ACTION_COOLING: - payload = "cooling"; - break; - case CLIMATE_ACTION_HEATING: - payload = "heating"; - break; - case CLIMATE_ACTION_IDLE: - payload = "idle"; - break; - case CLIMATE_ACTION_DRYING: - payload = "drying"; - break; - case CLIMATE_ACTION_FAN: - payload = "fan"; - break; - default: - payload = "unknown"; - } - if (!this->publish(this->get_action_state_topic(), payload)) + if (!this->publish(this->get_action_state_topic(), climate_action_to_mqtt_str(this->device_->action))) success = false; } if (traits.get_supports_fan_modes()) { - std::string payload; - if (this->device_->fan_mode.has_value()) { - switch (this->device_->fan_mode.value()) { - case CLIMATE_FAN_ON: - payload = "on"; - break; - case CLIMATE_FAN_OFF: - payload = "off"; - break; - case CLIMATE_FAN_AUTO: - payload = "auto"; - break; - case CLIMATE_FAN_LOW: - payload = "low"; - break; - case CLIMATE_FAN_MEDIUM: - payload = "medium"; - break; - case CLIMATE_FAN_HIGH: - payload = "high"; - break; - case CLIMATE_FAN_MIDDLE: - payload = "middle"; - break; - case CLIMATE_FAN_FOCUS: - payload = "focus"; - break; - case CLIMATE_FAN_DIFFUSE: - payload = "diffuse"; - break; - case CLIMATE_FAN_QUIET: - payload = "quiet"; - break; - default: - payload = "unknown"; - } - } - if (this->device_->has_custom_fan_mode()) - payload = this->device_->get_custom_fan_mode().c_str(); - if (!this->publish(this->get_fan_mode_state_topic(), payload)) + if (this->device_->has_custom_fan_mode()) { + if (!this->publish(this->get_fan_mode_state_topic(), this->device_->get_custom_fan_mode())) + success = false; + } else if (this->device_->fan_mode.has_value()) { + if (!this->publish(this->get_fan_mode_state_topic(), + climate_fan_mode_to_mqtt_str(this->device_->fan_mode.value()))) + success = false; + } else if (!this->publish(this->get_fan_mode_state_topic(), "")) { success = false; + } } if (traits.get_supports_swing_modes()) { - const char *payload; - switch (this->device_->swing_mode) { - case CLIMATE_SWING_OFF: - payload = "off"; - break; - case CLIMATE_SWING_BOTH: - payload = "both"; - break; - case CLIMATE_SWING_VERTICAL: - payload = "vertical"; - break; - case CLIMATE_SWING_HORIZONTAL: - payload = "horizontal"; - break; - default: - payload = "unknown"; - } - if (!this->publish(this->get_swing_mode_state_topic(), payload)) + if (!this->publish(this->get_swing_mode_state_topic(), climate_swing_mode_to_mqtt_str(this->device_->swing_mode))) success = false; } diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index aec6140e3f..a77afd3f4e 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -5,6 +5,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "esphome/core/version.h" #include "mqtt_const.h" @@ -149,6 +150,22 @@ bool MQTTComponent::publish(const char *topic, const char *payload) { return this->publish(topic, payload, strlen(payload)); } +#ifdef USE_ESP8266 +bool MQTTComponent::publish(const std::string &topic, ProgmemStr payload) { + return this->publish(topic.c_str(), payload); +} + +bool MQTTComponent::publish(const char *topic, ProgmemStr payload) { + if (topic[0] == '\0') + return false; + // On ESP8266, ProgmemStr is __FlashStringHelper* - need to copy from flash + char buf[64]; + strncpy_P(buf, reinterpret_cast(payload), sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + return global_mqtt_client->publish(topic, buf, strlen(buf), this->qos_, this->retain_); +} +#endif + bool MQTTComponent::publish_json(const std::string &topic, const json::json_build_t &f) { return this->publish_json(topic.c_str(), f); } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 304a2c0d0e..2cec6fda7e 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -9,6 +9,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/entity_base.h" +#include "esphome/core/progmem.h" #include "esphome/core/string_ref.h" #include "mqtt_client.h" @@ -157,6 +158,15 @@ class MQTTComponent : public Component { */ bool publish(const std::string &topic, const char *payload, size_t payload_length); + /** Send a MQTT message. + * + * @param topic The topic. + * @param payload The null-terminated payload. + */ + bool publish(const std::string &topic, const char *payload) { + return this->publish(topic.c_str(), payload, strlen(payload)); + } + /** Send a MQTT message (no heap allocation for topic). * * @param topic The topic as C string. @@ -189,6 +199,29 @@ class MQTTComponent : public Component { */ bool publish(StringRef topic, const char *payload) { return this->publish(topic.c_str(), payload); } +#ifdef USE_ESP8266 + /** Send a MQTT message with a PROGMEM string payload. + * + * @param topic The topic. + * @param payload The payload (ProgmemStr - stored in flash on ESP8266). + */ + bool publish(const std::string &topic, ProgmemStr payload); + + /** Send a MQTT message with a PROGMEM string payload (no heap allocation for topic). + * + * @param topic The topic as C string. + * @param payload The payload (ProgmemStr - stored in flash on ESP8266). + */ + bool publish(const char *topic, ProgmemStr payload); + + /** Send a MQTT message with a PROGMEM string payload (no heap allocation for topic). + * + * @param topic The topic as StringRef (for use with get_state_topic_to_()). + * @param payload The payload (ProgmemStr - stored in flash on ESP8266). + */ + bool publish(StringRef topic, ProgmemStr payload) { return this->publish(topic.c_str(), payload); } +#endif + /** Construct and send a JSON MQTT message. * * @param topic The topic. diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index d5bd13869a..50e68ecbcc 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -1,5 +1,6 @@ #include "mqtt_cover.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,20 @@ static const char *const TAG = "mqtt.cover"; using namespace esphome::cover; +static ProgmemStr cover_state_to_mqtt_str(CoverOperation operation, float position, bool supports_position) { + if (operation == COVER_OPERATION_OPENING) + return ESPHOME_F("opening"); + if (operation == COVER_OPERATION_CLOSING) + return ESPHOME_F("closing"); + if (position == COVER_CLOSED) + return ESPHOME_F("closed"); + if (position == COVER_OPEN) + return ESPHOME_F("open"); + if (supports_position) + return ESPHOME_F("open"); + return ESPHOME_F("unknown"); +} + MQTTCoverComponent::MQTTCoverComponent(Cover *cover) : cover_(cover) {} void MQTTCoverComponent::setup() { auto traits = this->cover_->get_traits(); @@ -109,14 +124,10 @@ bool MQTTCoverComponent::publish_state() { if (!this->publish(this->get_tilt_state_topic(), pos, len)) success = false; } - const char *state_s = this->cover_->current_operation == COVER_OPERATION_OPENING ? "opening" - : this->cover_->current_operation == COVER_OPERATION_CLOSING ? "closing" - : this->cover_->position == COVER_CLOSED ? "closed" - : this->cover_->position == COVER_OPEN ? "open" - : traits.get_supports_position() ? "open" - : "unknown"; char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; - if (!this->publish(this->get_state_topic_to_(topic_buf), state_s)) + if (!this->publish(this->get_state_topic_to_(topic_buf), + cover_state_to_mqtt_str(this->cover_->current_operation, this->cover_->position, + traits.get_supports_position()))) success = false; return success; } diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index c9791fb0f1..84d51895c5 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -1,5 +1,6 @@ #include "mqtt_fan.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,14 @@ static const char *const TAG = "mqtt.fan"; using namespace esphome::fan; +static ProgmemStr fan_direction_to_mqtt_str(FanDirection direction) { + return direction == FanDirection::FORWARD ? ESPHOME_F("forward") : ESPHOME_F("reverse"); +} + +static ProgmemStr fan_oscillation_to_mqtt_str(bool oscillating) { + return oscillating ? ESPHOME_F("oscillate_on") : ESPHOME_F("oscillate_off"); +} + MQTTFanComponent::MQTTFanComponent(Fan *state) : state_(state) {} Fan *MQTTFanComponent::get_state() const { return this->state_; } @@ -164,13 +173,12 @@ bool MQTTFanComponent::publish_state() { this->publish(this->get_state_topic_to_(topic_buf), state_s); bool failed = false; if (this->state_->get_traits().supports_direction()) { - bool success = this->publish(this->get_direction_state_topic(), - this->state_->direction == fan::FanDirection::FORWARD ? "forward" : "reverse"); + bool success = this->publish(this->get_direction_state_topic(), fan_direction_to_mqtt_str(this->state_->direction)); failed = failed || !success; } if (this->state_->get_traits().supports_oscillation()) { - bool success = this->publish(this->get_oscillation_state_topic(), - this->state_->oscillating ? "oscillate_on" : "oscillate_off"); + bool success = + this->publish(this->get_oscillation_state_topic(), fan_oscillation_to_mqtt_str(this->state_->oscillating)); failed = failed || !success; } auto traits = this->state_->get_traits(); diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 2e100823bf..16e25f6a8a 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -1,5 +1,6 @@ #include "mqtt_valve.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,20 @@ static const char *const TAG = "mqtt.valve"; using namespace esphome::valve; +static ProgmemStr valve_state_to_mqtt_str(ValveOperation operation, float position, bool supports_position) { + if (operation == VALVE_OPERATION_OPENING) + return ESPHOME_F("opening"); + if (operation == VALVE_OPERATION_CLOSING) + return ESPHOME_F("closing"); + if (position == VALVE_CLOSED) + return ESPHOME_F("closed"); + if (position == VALVE_OPEN) + return ESPHOME_F("open"); + if (supports_position) + return ESPHOME_F("open"); + return ESPHOME_F("unknown"); +} + MQTTValveComponent::MQTTValveComponent(Valve *valve) : valve_(valve) {} void MQTTValveComponent::setup() { auto traits = this->valve_->get_traits(); @@ -78,14 +93,10 @@ bool MQTTValveComponent::publish_state() { if (!this->publish(this->get_position_state_topic(), pos, len)) success = false; } - const char *state_s = this->valve_->current_operation == VALVE_OPERATION_OPENING ? "opening" - : this->valve_->current_operation == VALVE_OPERATION_CLOSING ? "closing" - : this->valve_->position == VALVE_CLOSED ? "closed" - : this->valve_->position == VALVE_OPEN ? "open" - : traits.get_supports_position() ? "open" - : "unknown"; char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; - if (!this->publish(this->get_state_topic_to_(topic_buf), state_s)) + if (!this->publish(this->get_state_topic_to_(topic_buf), + valve_state_to_mqtt_str(this->valve_->current_operation, this->valve_->position, + traits.get_supports_position()))) success = false; return success; } From f11b8615dab566c1e6e84264b84aaf618ff8c787 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 17:03:02 +0100 Subject: [PATCH 0500/2030] [cse7766] Fix power reading stuck when load switches off (#13734) --- esphome/components/cse7766/cse7766.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 4432195365..c36e57c929 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -152,6 +152,10 @@ void CSE7766Component::parse_data_() { if (this->power_sensor_ != nullptr) { this->power_sensor_->publish_state(power); } + } else if (this->power_sensor_ != nullptr) { + // No valid power measurement from chip - publish 0W to avoid stale readings + // This typically happens when current is below the measurable threshold (~50mA) + this->power_sensor_->publish_state(0.0f); } float current = 0.0f; From e6bae1a97e863abd4fe82e4901b52daa431b154c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 3 Feb 2026 11:16:13 -0500 Subject: [PATCH 0501/2030] [adc] Add ESP32-C2 support for curve fitting calibration (#13749) Co-authored-by: Claude Opus 4.5 --- esphome/components/adc/adc_sensor_esp32.cpp | 42 ++++++++++++--------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/esphome/components/adc/adc_sensor_esp32.cpp b/esphome/components/adc/adc_sensor_esp32.cpp index ea1263db5f..ece45f3746 100644 --- a/esphome/components/adc/adc_sensor_esp32.cpp +++ b/esphome/components/adc/adc_sensor_esp32.cpp @@ -42,11 +42,11 @@ void ADCSensor::setup() { adc_oneshot_unit_init_cfg_t init_config = {}; // Zero initialize init_config.unit_id = this->adc_unit_; init_config.ulp_mode = ADC_ULP_MODE_DISABLE; -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 init_config.clk_src = ADC_DIGI_CLK_SRC_DEFAULT; -#endif // USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || - // USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 +#endif // USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || + // USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 esp_err_t err = adc_oneshot_new_unit(&init_config, &ADCSensor::shared_adc_handles[this->adc_unit_]); if (err != ESP_OK) { ESP_LOGE(TAG, "Error initializing %s: %d", LOG_STR_ARG(adc_unit_to_str(this->adc_unit_)), err); @@ -74,8 +74,9 @@ void ADCSensor::setup() { if (this->calibration_handle_ == nullptr) { adc_cali_handle_t handle = nullptr; -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 // RISC-V variants and S3 use curve fitting calibration adc_cali_curve_fitting_config_t cali_config = {}; // Zero initialize first #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) @@ -112,7 +113,7 @@ void ADCSensor::setup() { ESP_LOGW(TAG, "Line fitting calibration failed with error %d, will use uncalibrated readings", err); this->setup_flags_.calibration_complete = false; } -#endif // USE_ESP32_VARIANT_ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 +#endif // USE_ESP32_VARIANT_ESP32C2 || ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 } this->setup_flags_.init_complete = true; @@ -184,12 +185,13 @@ float ADCSensor::sample_fixed_attenuation_() { } else { ESP_LOGW(TAG, "ADC calibration conversion failed with error %d, disabling calibration", err); if (this->calibration_handle_ != nullptr) { -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else // Other ESP32 variants use line fitting calibration adc_cali_delete_scheme_line_fitting(this->calibration_handle_); -#endif // USE_ESP32_VARIANT_ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 +#endif // USE_ESP32_VARIANT_ESP32C2 || ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 this->calibration_handle_ = nullptr; } } @@ -217,8 +219,9 @@ float ADCSensor::sample_autorange_() { // Need to recalibrate for the new attenuation if (this->calibration_handle_ != nullptr) { // Delete old calibration handle -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else adc_cali_delete_scheme_line_fitting(this->calibration_handle_); @@ -229,8 +232,9 @@ float ADCSensor::sample_autorange_() { // Create new calibration handle for this attenuation adc_cali_handle_t handle = nullptr; -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_curve_fitting_config_t cali_config = {}; #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) cali_config.chan = this->channel_; @@ -264,8 +268,9 @@ float ADCSensor::sample_autorange_() { if (err != ESP_OK) { ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err); if (handle != nullptr) { -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); @@ -286,8 +291,9 @@ float ADCSensor::sample_autorange_() { ESP_LOGVV(TAG, "Autorange atten=%d: UNCALIBRATED FALLBACK - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage); } // Clean up calibration handle -#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ - USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ + USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ + USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); From 95f39149d76023fee4317fdc416efa6994ef214f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:28:59 -0500 Subject: [PATCH 0502/2030] [rtttl] Fix dotted note parsing order to match RTTTL spec (#13722) Co-authored-by: Claude Opus 4.5 --- esphome/components/rtttl/rtttl.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 65fcc207d4..c179282c50 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -290,25 +290,26 @@ void Rtttl::loop() { this->position_++; } - // now, get optional '.' dotted note - if (this->rtttl_[this->position_] == '.') { - this->note_duration_ += this->note_duration_ / 2; - this->position_++; - } - // now, get scale uint8_t scale = get_integer_(); - if (scale == 0) + if (scale == 0) { scale = this->default_octave_; + } if (scale < 4 || scale > 7) { ESP_LOGE(TAG, "Octave must be between 4 and 7 (it is %d)", scale); this->finish_(); return; } - bool need_note_gap = false; + + // now, get optional '.' dotted note + if (this->rtttl_[this->position_] == '.') { + this->note_duration_ += this->note_duration_ / 2; + this->position_++; + } // Now play the note + bool need_note_gap = false; if (note) { auto note_index = (scale - 4) * 12 + note; if (note_index < 0 || note_index >= (int) sizeof(NOTES)) { From 2541ec15656e79d44501605be72c18edac66e78f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 4 Feb 2026 09:42:13 +0100 Subject: [PATCH 0503/2030] [wifi] Fix wifi.connected condition returning false in connect state listener automations (#13733) --- esphome/components/wifi/wifi_component.cpp | 21 +++++++++++++++++++ esphome/components/wifi/wifi_component.h | 15 +++++++++++++ .../wifi/wifi_component_esp8266.cpp | 10 ++++++--- .../wifi/wifi_component_esp_idf.cpp | 9 +++++--- .../wifi/wifi_component_libretiny.cpp | 11 ++++++---- .../components/wifi/wifi_component_pico_w.cpp | 12 ++++++----- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index c4bfdf3c42..e9b78c9225 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1464,6 +1464,12 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { this->release_scan_results_(); +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + // Notify listeners now that state machine has reached STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->notify_connect_state_listeners_(); +#endif + return; } @@ -2183,6 +2189,21 @@ void WiFiComponent::release_scan_results_() { } } +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS +void WiFiComponent::notify_connect_state_listeners_() { + if (!this->pending_.connect_state) + return; + this->pending_.connect_state = false; + // Get current SSID and BSSID from the WiFi driver + char ssid_buf[SSID_BUFFER_SIZE]; + const char *ssid = this->wifi_ssid_to(ssid_buf); + bssid_t bssid = this->wifi_bssid(); + for (auto *listener : this->connect_state_listeners_) { + listener->on_wifi_connect_state(StringRef(ssid, strlen(ssid)), bssid); + } +} +#endif // USE_WIFI_CONNECT_STATE_LISTENERS + void WiFiComponent::check_roaming_(uint32_t now) { // Guard: not for hidden networks (may not appear in scan) const WiFiAP *selected = this->get_selected_sta_(); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 4bdc253f66..98f339809a 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -632,6 +632,11 @@ class WiFiComponent : public Component { /// Free scan results memory unless a component needs them void release_scan_results_(); +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + /// Notify connect state listeners (called after state machine reaches STA_CONNECTED) + void notify_connect_state_listeners_(); +#endif + #ifdef USE_ESP8266 static void wifi_event_callback(System_Event_t *event); void wifi_scan_done_callback_(void *arg, STATUS status); @@ -739,6 +744,16 @@ class WiFiComponent : public Component { SemaphoreHandle_t high_performance_semaphore_{nullptr}; #endif +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + // Pending listener notifications deferred until state machine reaches appropriate state. + // Listeners are notified after state transitions complete so conditions like + // wifi.connected return correct values in automations. + // Uses bitfields to minimize memory; more flags may be added as needed. + struct { + bool connect_state : 1; // Notify connect state listeners after STA_CONNECTED + } pending_{}; +#endif + #ifdef USE_WIFI_CONNECT_TRIGGER Trigger<> connect_trigger_; #endif diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index c714afaad3..c6bd40037d 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -500,6 +500,10 @@ const LogString *get_disconnect_reason_str(uint8_t reason) { } } +// TODO: This callback runs in ESP8266 system context with limited stack (~2KB). +// All listener notifications should be deferred to wifi_loop_() via pending_ flags +// to avoid stack overflow. Currently only connect_state is deferred; disconnect, +// IP, and scan listeners still run in this context and should be migrated. void WiFiComponent::wifi_event_callback(System_Event_t *event) { switch (event->event) { case EVENT_STAMODE_CONNECTED: { @@ -512,9 +516,9 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { #endif s_sta_connected = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : global_wifi_component->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + global_wifi_component->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index a32232a758..22bf4be483 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -710,6 +710,9 @@ void WiFiComponent::wifi_loop_() { delete data; // NOLINT(cppcoreguidelines-owning-memory) } } +// Events are processed from queue in main loop context, but listener notifications +// must be deferred until after the state machine transitions (in check_connecting_finished) +// so that conditions like wifi.connected return correct values in automations. void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { esp_err_t err; if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_START) { @@ -743,9 +746,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { #endif s_sta_connected = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index af2b82c3c6..285a520ef5 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -423,7 +423,10 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } } -// Process a single event from the queue - runs in main loop context +// Process a single event from the queue - runs in main loop context. +// Listener notifications must be deferred until after the state machine transitions +// (in check_connecting_finished) so that conditions like wifi.connected return +// correct values in automations. void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { switch (event->event_id) { case ESPHOME_EVENT_ID_WIFI_READY: { @@ -456,9 +459,9 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // This matches ESP32 IDF behavior where s_sta_connected is set but // wifi_sta_connect_status_() also checks got_ipv4_address_ #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so set connected state here #ifdef USE_WIFI_MANUAL_IP diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 84c10d5d43..1ce36c2d93 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -252,6 +252,10 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(dns_ip); } +// Pico W uses polling for connection state detection. +// Connect state listener notifications are deferred until after the state machine +// transitions (in check_connecting_finished) so that conditions like wifi.connected +// return correct values in automations. void WiFiComponent::wifi_loop_() { // Handle scan completion if (this->state_ == WIFI_COMPONENT_STATE_STA_SCANNING && !cyw43_wifi_scan_active(&cyw43_state)) { @@ -278,11 +282,9 @@ void WiFiComponent::wifi_loop_() { s_sta_was_connected = true; ESP_LOGV(TAG, "Connected"); #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - String ssid = WiFi.SSID(); - bssid_t bssid = this->wifi_bssid(); - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(ssid.c_str(), ssid.length()), bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, notify IP listeners immediately as the IP is already configured #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) From 4d05cd30592ab23208953ad8a1c6c277dab34cc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 09:24:05 +0000 Subject: [PATCH 0504/2030] Bump ruff from 0.14.14 to 0.15.0 (#13752) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston --- .pre-commit-config.yaml | 2 +- esphome/components/i2c/__init__.py | 2 +- esphome/components/lvgl/automation.py | 8 ++---- esphome/components/opentherm/generate.py | 4 ++- esphome/components/zephyr/__init__.py | 7 +++-- esphome/config_validation.py | 2 +- esphome/enum.py | 18 ++---------- esphome/wizard.py | 2 +- requirements_test.txt | 2 +- script/api_protobuf/api_protobuf.py | 2 +- script/merge_component_configs.py | 2 +- tests/integration/test_script_queued.py | 8 ++++-- tests/script/test_helpers.py | 4 +-- tests/unit_tests/core/test_config.py | 26 ++++++++++------- tests/unit_tests/test_writer.py | 36 ++++++++++++------------ 15 files changed, 60 insertions(+), 65 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b068673ecf..991e053d5a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.14.14 + rev: v0.15.0 hooks: # Run the linter. - id: ruff diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index 19efda0b49..de3f2be674 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -183,7 +183,7 @@ async def to_code(config): if CORE.using_zephyr: zephyr_add_prj_conf("I2C", True) i2c = "i2c0" - if zephyr_data()[KEY_BOARD] in ["xiao_ble"]: + if zephyr_data()[KEY_BOARD] == "xiao_ble": i2c = "i2c1" zephyr_add_overlay( f""" diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 9b58727f2a..b589e42f3b 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -272,9 +272,7 @@ async def obj_hide_to_code(config, action_id, template_arg, args): async def do_hide(widget: Widget): widget.add_flag("LV_OBJ_FLAG_HIDDEN") - widgets = [ - widget.outer if widget.outer else widget for widget in await get_widgets(config) - ] + widgets = [widget.outer or widget for widget in await get_widgets(config)] return await action_to_code(widgets, do_hide, action_id, template_arg, args) @@ -285,9 +283,7 @@ async def obj_show_to_code(config, action_id, template_arg, args): if widget.move_to_foreground: lv_obj.move_foreground(widget.obj) - widgets = [ - widget.outer if widget.outer else widget for widget in await get_widgets(config) - ] + widgets = [widget.outer or widget for widget in await get_widgets(config)] return await action_to_code(widgets, do_show, action_id, template_arg, args) diff --git a/esphome/components/opentherm/generate.py b/esphome/components/opentherm/generate.py index 4e6f3b0a12..0b39895798 100644 --- a/esphome/components/opentherm/generate.py +++ b/esphome/components/opentherm/generate.py @@ -31,7 +31,9 @@ def define_has_settings(keys: list[str], schemas: dict[str, SettingSchema]) -> N cg.RawExpression( " sep ".join( map( - lambda key: f"F({schemas[key].backing_type}, {key}_setting, {schemas[key].default_value})", + lambda key: ( + f"F({schemas[key].backing_type}, {key}_setting, {schemas[key].default_value})" + ), keys, ) ) diff --git a/esphome/components/zephyr/__init__.py b/esphome/components/zephyr/__init__.py index 8e3ae86bbe..43d5cebebb 100644 --- a/esphome/components/zephyr/__init__.py +++ b/esphome/components/zephyr/__init__.py @@ -213,9 +213,10 @@ def copy_files(): zephyr_data()[KEY_OVERLAY], ) - if zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT or zephyr_data()[ - KEY_BOARD - ] in ["xiao_ble"]: + if ( + zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT + or zephyr_data()[KEY_BOARD] == "xiao_ble" + ): fake_board_manifest = """ { "frameworks": [ diff --git a/esphome/config_validation.py b/esphome/config_validation.py index b7ab02013d..55e13a7050 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -682,7 +682,7 @@ def only_with_framework( def validator_(obj): if CORE.target_framework not in frameworks: err_str = f"This feature is only available with framework(s) {', '.join([framework.value for framework in frameworks])}" - if suggestion := suggestions.get(CORE.target_framework, None): + if suggestion := suggestions.get(CORE.target_framework): (component, docs_path) = suggestion err_str += f"\nPlease use '{component}'" if docs_path: diff --git a/esphome/enum.py b/esphome/enum.py index 0fe30cf92a..cf0d8b645b 100644 --- a/esphome/enum.py +++ b/esphome/enum.py @@ -2,19 +2,7 @@ from __future__ import annotations -from enum import Enum -from typing import Any +from enum import StrEnum as _StrEnum - -class StrEnum(str, Enum): - """Partial backport of Python 3.11's StrEnum for our basic use cases.""" - - def __new__(cls, value: str, *args: Any, **kwargs: Any) -> StrEnum: - """Create a new StrEnum instance.""" - if not isinstance(value, str): - raise TypeError(f"{value!r} is not a string") - return super().__new__(cls, value, *args, **kwargs) - - def __str__(self) -> str: - """Return self.value.""" - return str(self.value) +# Re-export StrEnum from standard library for backwards compatibility +StrEnum = _StrEnum diff --git a/esphome/wizard.py b/esphome/wizard.py index f5e8a1e462..4b74847996 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -470,7 +470,7 @@ def wizard(path: Path) -> int: sleep(1) # Do not create wifi if the board does not support it - if board not in ["rpipico"]: + if board != "rpipico": safe_print_step(3, WIFI_BIG) safe_print("In this step, I'm going to create the configuration for WiFi.") safe_print() diff --git a/requirements_test.txt b/requirements_test.txt index 5d90764021..2cf6f6456e 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.14.14 # also change in .pre-commit-config.yaml when updating +ruff==0.15.0 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 72103285e8..8baf6acf11 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -280,7 +280,7 @@ class TypeInfo(ABC): """ field_id_size = self.calculate_field_id_size() method = f"{base_method}_force" if force else base_method - value = value_expr if value_expr else name + value = value_expr or name return f"size.{method}({field_id_size}, {value});" @abstractmethod diff --git a/script/merge_component_configs.py b/script/merge_component_configs.py index 59774edba9..5e98f1fef5 100755 --- a/script/merge_component_configs.py +++ b/script/merge_component_configs.py @@ -249,7 +249,7 @@ def merge_component_configs( if all_packages is None: # First component - initialize package dict - all_packages = comp_packages if comp_packages else {} + all_packages = comp_packages or {} elif comp_packages: # Merge packages - combine all unique package types # If both have the same package type, verify they're identical diff --git a/tests/integration/test_script_queued.py b/tests/integration/test_script_queued.py index c86c289719..84c7f950b6 100644 --- a/tests/integration/test_script_queued.py +++ b/tests/integration/test_script_queued.py @@ -98,9 +98,11 @@ async def test_script_queued( if not test3_complete.done(): loop.call_later( 0.3, - lambda: test3_complete.set_result(True) - if not test3_complete.done() - else None, + lambda: ( + test3_complete.set_result(True) + if not test3_complete.done() + else None + ), ) # Test 4: Rejection diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index c51273f298..7e60ba41fc 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -1011,8 +1011,8 @@ def test_get_all_dependencies_handles_missing_components() -> None: comp.dependencies = ["missing_comp"] comp.auto_load = [] - mock_get_component.side_effect = ( - lambda name: comp if name == "existing" else None + mock_get_component.side_effect = lambda name: ( + comp if name == "existing" else None ) result = helpers.get_all_dependencies({"existing", "nonexistent"}) diff --git a/tests/unit_tests/core/test_config.py b/tests/unit_tests/core/test_config.py index ab7bdbb98c..88801a9ca0 100644 --- a/tests/unit_tests/core/test_config.py +++ b/tests/unit_tests/core/test_config.py @@ -453,11 +453,14 @@ def test_preload_core_config_no_platform(setup_core: Path) -> None: # Mock _is_target_platform to avoid expensive component loading with patch("esphome.core.config._is_target_platform") as mock_is_platform: # Return True for known platforms - mock_is_platform.side_effect = lambda name: name in [ - "esp32", - "esp8266", - "rp2040", - ] + mock_is_platform.side_effect = lambda name: ( + name + in [ + "esp32", + "esp8266", + "rp2040", + ] + ) with pytest.raises(cv.Invalid, match="Platform missing"): preload_core_config(config, result) @@ -477,11 +480,14 @@ def test_preload_core_config_multiple_platforms(setup_core: Path) -> None: # Mock _is_target_platform to avoid expensive component loading with patch("esphome.core.config._is_target_platform") as mock_is_platform: # Return True for known platforms - mock_is_platform.side_effect = lambda name: name in [ - "esp32", - "esp8266", - "rp2040", - ] + mock_is_platform.side_effect = lambda name: ( + name + in [ + "esp32", + "esp8266", + "rp2040", + ] + ) with pytest.raises(cv.Invalid, match="Found multiple target platform blocks"): preload_core_config(config, result) diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index ac05e0d31b..134b63df4a 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -466,8 +466,8 @@ def test_clean_build( ) as mock_get_instance: mock_config = MagicMock() mock_get_instance.return_value = mock_config - mock_config.get.side_effect = ( - lambda section, option: str(platformio_cache_dir) + mock_config.get.side_effect = lambda section, option: ( + str(platformio_cache_dir) if (section, option) == ("platformio", "cache_dir") else "" ) @@ -630,8 +630,8 @@ def test_clean_build_empty_cache_dir( ) as mock_get_instance: mock_config = MagicMock() mock_get_instance.return_value = mock_config - mock_config.get.side_effect = ( - lambda section, option: " " # Whitespace only + mock_config.get.side_effect = lambda section, option: ( + " " # Whitespace only if (section, option) == ("platformio", "cache_dir") else "" ) @@ -1574,8 +1574,8 @@ def test_copy_src_tree_writes_build_info_files( mock_component.resources = mock_resources # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "Test comment" @@ -1649,8 +1649,8 @@ def test_copy_src_tree_detects_config_hash_change( build_info_h_path.write_text("// old build_info_data.h") # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF # Different from existing mock_core.comment = "" @@ -1711,8 +1711,8 @@ def test_copy_src_tree_detects_version_change( build_info_h_path.write_text("// old build_info_data.h") # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "" @@ -1761,8 +1761,8 @@ def test_copy_src_tree_handles_invalid_build_info_json( build_info_h_path.write_text("// old build_info_data.h") # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "" @@ -1835,8 +1835,8 @@ def test_copy_src_tree_build_info_timestamp_behavior( mock_component.resources = mock_resources # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "" @@ -1930,8 +1930,8 @@ def test_copy_src_tree_detects_removed_source_file( existing_file.write_text("// test file") # Setup mocks - no components, so the file should be removed - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "" @@ -1992,8 +1992,8 @@ def test_copy_src_tree_ignores_removed_generated_file( build_info_h.write_text("// old generated file") # Setup mocks - mock_core.relative_src_path.side_effect = lambda *args: src_path.joinpath(*args) - mock_core.relative_build_path.side_effect = lambda *args: build_path.joinpath(*args) + mock_core.relative_src_path.side_effect = src_path.joinpath + mock_core.relative_build_path.side_effect = build_path.joinpath mock_core.defines = [] mock_core.config_hash = 0xDEADBEEF mock_core.comment = "" From 5dc8bfe95efe0a6efd21cbed855b724d05b469ef Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 4 Feb 2026 01:29:27 -0800 Subject: [PATCH 0505/2030] [ultrasonic] adjust timeouts and bring the parameter back (#13738) Co-authored-by: Samuel Sieb --- CODEOWNERS | 2 +- esphome/components/ultrasonic/__init__.py | 2 +- esphome/components/ultrasonic/sensor.py | 11 +--- .../ultrasonic/ultrasonic_sensor.cpp | 56 ++++++++++++++----- .../components/ultrasonic/ultrasonic_sensor.h | 5 ++ 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 1d165a6f57..25e6dc1b29 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -532,7 +532,7 @@ esphome/components/uart/packet_transport/* @clydebarrow esphome/components/udp/* @clydebarrow esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli -esphome/components/ultrasonic/* @OttoWinter +esphome/components/ultrasonic/* @ssieb @swoboda1337 esphome/components/update/* @jesserockz esphome/components/uponor_smatrix/* @kroimon esphome/components/usb_cdc_acm/* @kbx81 diff --git a/esphome/components/ultrasonic/__init__.py b/esphome/components/ultrasonic/__init__.py index 71a87b6ae5..3bca12bffc 100644 --- a/esphome/components/ultrasonic/__init__.py +++ b/esphome/components/ultrasonic/__init__.py @@ -1 +1 @@ -CODEOWNERS = ["@OttoWinter"] +CODEOWNERS = ["@swoboda1337", "@ssieb"] diff --git a/esphome/components/ultrasonic/sensor.py b/esphome/components/ultrasonic/sensor.py index 4b04ee7578..fad4e6b11d 100644 --- a/esphome/components/ultrasonic/sensor.py +++ b/esphome/components/ultrasonic/sensor.py @@ -34,7 +34,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_TRIGGER_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema, - cv.Optional(CONF_TIMEOUT): cv.distance, + cv.Optional(CONF_TIMEOUT, default="2m"): cv.distance, cv.Optional( CONF_PULSE_TIME, default="10us" ): cv.positive_time_period_microseconds, @@ -52,12 +52,5 @@ async def to_code(config): cg.add(var.set_trigger_pin(trigger)) echo = await cg.gpio_pin_expression(config[CONF_ECHO_PIN]) cg.add(var.set_echo_pin(echo)) - - # Remove before 2026.8.0 - if CONF_TIMEOUT in config: - _LOGGER.warning( - "'timeout' option is deprecated and will be removed in 2026.8.0. " - "The option has no effect and can be safely removed." - ) - + cg.add(var.set_timeout_us(config[CONF_TIMEOUT] / (0.000343 / 2))) cg.add(var.set_pulse_time_us(config[CONF_PULSE_TIME])) diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index 369a10edbd..d3f7e69444 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -6,12 +6,11 @@ namespace esphome::ultrasonic { static const char *const TAG = "ultrasonic.sensor"; -static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us (noise filtering) -static constexpr uint32_t MEASUREMENT_TIMEOUT_US = 80000; // Maximum time to wait for measurement completion +static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { uint32_t now = micros(); - if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) { + if (arg->echo_pin_isr.digital_read()) { arg->echo_start_us = now; arg->echo_start = true; } else { @@ -38,6 +37,7 @@ void UltrasonicSensorComponent::setup() { this->trigger_pin_->digital_write(false); this->trigger_pin_isr_ = this->trigger_pin_->to_isr(); this->echo_pin_->setup(); + this->store_.echo_pin_isr = this->echo_pin_->to_isr(); this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE); } @@ -53,29 +53,55 @@ void UltrasonicSensorComponent::loop() { return; } + if (!this->store_.echo_start) { + uint32_t elapsed = micros() - this->measurement_start_us_; + if (elapsed >= START_TIMEOUT_US) { + ESP_LOGW(TAG, "'%s' - Measurement start timed out", this->name_.c_str()); + this->publish_state(NAN); + this->measurement_pending_ = false; + return; + } + } else { + uint32_t elapsed; + if (this->store_.echo_end) { + elapsed = this->store_.echo_end_us - this->store_.echo_start_us; + } else { + elapsed = micros() - this->store_.echo_start_us; + } + if (elapsed >= this->timeout_us_) { + ESP_LOGD(TAG, "'%s' - Measurement pulse timed out after %" PRIu32 "us", this->name_.c_str(), elapsed); + this->publish_state(NAN); + this->measurement_pending_ = false; + return; + } + } + if (this->store_.echo_end) { - uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; - ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration); - float result = UltrasonicSensorComponent::us_to_m(pulse_duration); - ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); + float result; + if (this->store_.echo_start) { + uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; + ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us", + this->store_.echo_start_us - this->measurement_start_us_, pulse_duration); + result = UltrasonicSensorComponent::us_to_m(pulse_duration); + ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); + } else { + ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str()); + result = NAN; + } this->publish_state(result); this->measurement_pending_ = false; return; } - - uint32_t elapsed = micros() - this->measurement_start_us_; - if (elapsed >= MEASUREMENT_TIMEOUT_US) { - ESP_LOGD(TAG, "'%s' - Measurement timed out after %" PRIu32 "us", this->name_.c_str(), elapsed); - this->publish_state(NAN); - this->measurement_pending_ = false; - } } void UltrasonicSensorComponent::dump_config() { LOG_SENSOR("", "Ultrasonic Sensor", this); LOG_PIN(" Echo Pin: ", this->echo_pin_); LOG_PIN(" Trigger Pin: ", this->trigger_pin_); - ESP_LOGCONFIG(TAG, " Pulse time: %" PRIu32 " us", this->pulse_time_us_); + ESP_LOGCONFIG(TAG, + " Pulse time: %" PRIu32 " µs\n" + " Timeout: %" PRIu32 " µs", + this->pulse_time_us_, this->timeout_us_); LOG_UPDATE_INTERVAL(this); } diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index b0c00e51f0..a38737aff5 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -11,6 +11,8 @@ namespace esphome::ultrasonic { struct UltrasonicSensorStore { static void gpio_intr(UltrasonicSensorStore *arg); + ISRInternalGPIOPin echo_pin_isr; + volatile uint32_t wait_start_us{0}; volatile uint32_t echo_start_us{0}; volatile uint32_t echo_end_us{0}; volatile bool echo_start{false}; @@ -29,6 +31,8 @@ class UltrasonicSensorComponent : public sensor::Sensor, public PollingComponent float get_setup_priority() const override { return setup_priority::DATA; } + /// Set the maximum time in µs to wait for the echo to return + void set_timeout_us(uint32_t timeout_us) { this->timeout_us_ = timeout_us; } /// Set the time in µs the trigger pin should be enabled for in µs, defaults to 10µs (for HC-SR04) void set_pulse_time_us(uint32_t pulse_time_us) { this->pulse_time_us_ = pulse_time_us; } @@ -41,6 +45,7 @@ class UltrasonicSensorComponent : public sensor::Sensor, public PollingComponent ISRInternalGPIOPin trigger_pin_isr_; InternalGPIOPin *echo_pin_; UltrasonicSensorStore store_; + uint32_t timeout_us_{}; uint32_t pulse_time_us_{}; uint32_t measurement_start_us_{0}; From 5544f0d346a4d689dfe78b9d7ed5e83b1f45ad7e Mon Sep 17 00:00:00 2001 From: J0k3r2k1 <60352302+J0k3r2k1@users.noreply.github.com> Date: Fri, 30 Jan 2026 21:33:45 +0100 Subject: [PATCH 0506/2030] [mipi_spi] Fix log_pin() FlashStringHelper compatibility (#13624) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: J. Nick Koston --- esphome/components/mipi_spi/mipi_spi.cpp | 39 +++++++++++++++-- esphome/components/mipi_spi/mipi_spi.h | 42 ++++--------------- .../components/mipi_spi/test.esp8266-ard.yaml | 10 +++++ 3 files changed, 54 insertions(+), 37 deletions(-) create mode 100644 tests/components/mipi_spi/test.esp8266-ard.yaml diff --git a/esphome/components/mipi_spi/mipi_spi.cpp b/esphome/components/mipi_spi/mipi_spi.cpp index 272915b4e1..90f6324511 100644 --- a/esphome/components/mipi_spi/mipi_spi.cpp +++ b/esphome/components/mipi_spi/mipi_spi.cpp @@ -1,6 +1,39 @@ #include "mipi_spi.h" #include "esphome/core/log.h" -namespace esphome { -namespace mipi_spi {} // namespace mipi_spi -} // namespace esphome +namespace esphome::mipi_spi { + +void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, + bool invert_colors, int display_bits, bool is_big_endian, const optional &brightness, + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width) { + ESP_LOGCONFIG(TAG, + "MIPI_SPI Display\n" + " Model: %s\n" + " Width: %d\n" + " Height: %d\n" + " Swap X/Y: %s\n" + " Mirror X: %s\n" + " Mirror Y: %s\n" + " Invert colors: %s\n" + " Color order: %s\n" + " Display pixels: %d bits\n" + " Endianness: %s\n" + " SPI Mode: %d\n" + " SPI Data rate: %uMHz\n" + " SPI Bus width: %d", + model, width, height, YESNO(madctl & MADCTL_MV), YESNO(madctl & (MADCTL_MX | MADCTL_XFLIP)), + YESNO(madctl & (MADCTL_MY | MADCTL_YFLIP)), YESNO(invert_colors), (madctl & MADCTL_BGR) ? "BGR" : "RGB", + display_bits, is_big_endian ? "Big" : "Little", spi_mode, static_cast(data_rate / 1000000), + bus_width); + LOG_PIN(" CS Pin: ", cs); + LOG_PIN(" Reset Pin: ", reset); + LOG_PIN(" DC Pin: ", dc); + if (offset_width != 0) + ESP_LOGCONFIG(TAG, " Offset width: %d", offset_width); + if (offset_height != 0) + ESP_LOGCONFIG(TAG, " Offset height: %d", offset_height); + if (brightness.has_value()) + ESP_LOGCONFIG(TAG, " Brightness: %u", brightness.value()); +} + +} // namespace esphome::mipi_spi diff --git a/esphome/components/mipi_spi/mipi_spi.h b/esphome/components/mipi_spi/mipi_spi.h index a59cb8104b..083ff9507f 100644 --- a/esphome/components/mipi_spi/mipi_spi.h +++ b/esphome/components/mipi_spi/mipi_spi.h @@ -63,6 +63,11 @@ enum BusType { BUS_TYPE_SINGLE_16 = 16, // Single bit bus, but 16 bits per transfer }; +// Helper function for dump_config - defined in mipi_spi.cpp to allow use of LOG_PIN macro +void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, + bool invert_colors, int display_bits, bool is_big_endian, const optional &brightness, + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width); + /** * Base class for MIPI SPI displays. * All the methods are defined here in the header file, as it is not possible to define templated methods in a cpp file. @@ -201,40 +206,9 @@ class MipiSpi : public display::Display, } void dump_config() override { - esph_log_config(TAG, - "MIPI_SPI Display\n" - " Model: %s\n" - " Width: %u\n" - " Height: %u", - this->model_, WIDTH, HEIGHT); - if constexpr (OFFSET_WIDTH != 0) - esph_log_config(TAG, " Offset width: %u", OFFSET_WIDTH); - if constexpr (OFFSET_HEIGHT != 0) - esph_log_config(TAG, " Offset height: %u", OFFSET_HEIGHT); - esph_log_config(TAG, - " Swap X/Y: %s\n" - " Mirror X: %s\n" - " Mirror Y: %s\n" - " Invert colors: %s\n" - " Color order: %s\n" - " Display pixels: %d bits\n" - " Endianness: %s\n", - YESNO(this->madctl_ & MADCTL_MV), YESNO(this->madctl_ & (MADCTL_MX | MADCTL_XFLIP)), - YESNO(this->madctl_ & (MADCTL_MY | MADCTL_YFLIP)), YESNO(this->invert_colors_), - this->madctl_ & MADCTL_BGR ? "BGR" : "RGB", DISPLAYPIXEL * 8, IS_BIG_ENDIAN ? "Big" : "Little"); - if (this->brightness_.has_value()) - esph_log_config(TAG, " Brightness: %u", this->brightness_.value()); - if (this->cs_ != nullptr) - esph_log_config(TAG, " CS Pin: %s", this->cs_->dump_summary().c_str()); - if (this->reset_pin_ != nullptr) - esph_log_config(TAG, " Reset Pin: %s", this->reset_pin_->dump_summary().c_str()); - if (this->dc_pin_ != nullptr) - esph_log_config(TAG, " DC Pin: %s", this->dc_pin_->dump_summary().c_str()); - esph_log_config(TAG, - " SPI Mode: %d\n" - " SPI Data rate: %dMHz\n" - " SPI Bus width: %d", - this->mode_, static_cast(this->data_rate_ / 1000000), BUS_TYPE); + internal_dump_config(this->model_, WIDTH, HEIGHT, OFFSET_WIDTH, OFFSET_HEIGHT, this->madctl_, this->invert_colors_, + DISPLAYPIXEL * 8, IS_BIG_ENDIAN, this->brightness_, this->cs_, this->reset_pin_, this->dc_pin_, + this->mode_, this->data_rate_, BUS_TYPE); } protected: diff --git a/tests/components/mipi_spi/test.esp8266-ard.yaml b/tests/components/mipi_spi/test.esp8266-ard.yaml new file mode 100644 index 0000000000..ef6197d852 --- /dev/null +++ b/tests/components/mipi_spi/test.esp8266-ard.yaml @@ -0,0 +1,10 @@ +substitutions: + dc_pin: GPIO15 + cs_pin: GPIO5 + enable_pin: GPIO4 + reset_pin: GPIO16 + +packages: + spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml + +<<: !include common.yaml From 8314ad9ca01b8bdf5d91f0da768836d236f87595 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 31 Jan 2026 09:59:13 -0500 Subject: [PATCH 0507/2030] [max7219] Allocate buffer in constructor (#13660) Co-authored-by: Claude Opus 4.5 --- esphome/components/max7219/display.py | 3 +-- esphome/components/max7219/max7219.cpp | 17 ++++++++--------- esphome/components/max7219/max7219.h | 11 +++++------ 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/esphome/components/max7219/display.py b/esphome/components/max7219/display.py index a434125148..abb20702bd 100644 --- a/esphome/components/max7219/display.py +++ b/esphome/components/max7219/display.py @@ -28,11 +28,10 @@ CONFIG_SCHEMA = ( async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + var = cg.new_Pvariable(config[CONF_ID], config[CONF_NUM_CHIPS]) await spi.register_spi_device(var, config, write_only=True) await display.register_display(var, config) - cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) cg.add(var.set_intensity(config[CONF_INTENSITY])) cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE])) diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index 157b317c02..d701e6fc86 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -3,8 +3,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace max7219 { +namespace esphome::max7219 { static const char *const TAG = "max7219"; @@ -115,12 +114,14 @@ const uint8_t MAX7219_ASCII_TO_RAW[95] PROGMEM = { }; float MAX7219Component::get_setup_priority() const { return setup_priority::PROCESSOR; } + +MAX7219Component::MAX7219Component(uint8_t num_chips) : num_chips_(num_chips) { + this->buffer_ = new uint8_t[this->num_chips_ * 8]; // NOLINT + memset(this->buffer_, 0, this->num_chips_ * 8); +} + void MAX7219Component::setup() { this->spi_setup(); - this->buffer_ = new uint8_t[this->num_chips_ * 8]; // NOLINT - for (uint8_t i = 0; i < this->num_chips_ * 8; i++) - this->buffer_[i] = 0; - // let's assume the user has all 8 digits connected, only important in daisy chained setups anyway this->send_to_all_(MAX7219_REGISTER_SCAN_LIMIT, 7); // let's use our own ASCII -> led pattern encoding @@ -229,7 +230,6 @@ void MAX7219Component::set_intensity(uint8_t intensity) { this->intensity_ = intensity; } } -void MAX7219Component::set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; } uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time) { char buffer[64]; @@ -240,5 +240,4 @@ uint8_t MAX7219Component::strftime(uint8_t pos, const char *format, ESPTime time } uint8_t MAX7219Component::strftime(const char *format, ESPTime time) { return this->strftime(0, format, time); } -} // namespace max7219 -} // namespace esphome +} // namespace esphome::max7219 diff --git a/esphome/components/max7219/max7219.h b/esphome/components/max7219/max7219.h index 58d871d54c..ef38628f28 100644 --- a/esphome/components/max7219/max7219.h +++ b/esphome/components/max7219/max7219.h @@ -6,8 +6,7 @@ #include "esphome/components/spi/spi.h" #include "esphome/components/display/display.h" -namespace esphome { -namespace max7219 { +namespace esphome::max7219 { class MAX7219Component; @@ -17,6 +16,8 @@ class MAX7219Component : public PollingComponent, public spi::SPIDevice { public: + explicit MAX7219Component(uint8_t num_chips); + void set_writer(max7219_writer_t &&writer); void setup() override; @@ -30,7 +31,6 @@ class MAX7219Component : public PollingComponent, void display(); void set_intensity(uint8_t intensity); - void set_num_chips(uint8_t num_chips); void set_reverse(bool reverse) { this->reverse_ = reverse; }; /// Evaluate the printf-format and print the result at the given position. @@ -56,10 +56,9 @@ class MAX7219Component : public PollingComponent, uint8_t intensity_{15}; // Intensity of the display from 0 to 15 (most) bool intensity_changed_{}; // True if we need to re-send the intensity uint8_t num_chips_{1}; - uint8_t *buffer_; + uint8_t *buffer_{nullptr}; bool reverse_{false}; max7219_writer_t writer_{}; }; -} // namespace max7219 -} // namespace esphome +} // namespace esphome::max7219 From 49ef4e00df263618ece4ee5ffa52ca02d432c3e9 Mon Sep 17 00:00:00 2001 From: rwrozelle Date: Mon, 2 Feb 2026 10:48:08 -0500 Subject: [PATCH 0508/2030] [mqtt] resolve warnings related to use of ip.str() (#13719) --- esphome/components/mqtt/mqtt_backend_esp32.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index bd2d2a67b2..adba0cf004 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -139,7 +139,8 @@ class MQTTBackendESP32 final : public MQTTBackend { this->lwt_retain_ = retain; } void set_server(network::IPAddress ip, uint16_t port) final { - this->host_ = ip.str(); + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + this->host_ = ip.str_to(ip_buf); this->port_ = port; } void set_server(const char *host, uint16_t port) final { From b085585461120df1b375bf14ce283c929fcd1c4e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 22:22:11 +0100 Subject: [PATCH 0509/2030] [core] Add missing uint32_t ID overloads for defer() and cancel_defer() (#13720) --- esphome/core/component.cpp | 4 ++ esphome/core/component.h | 4 ++ .../fixtures/scheduler_numeric_id_test.yaml | 45 ++++++++++++++++++- .../test_scheduler_numeric_id_test.py | 38 +++++++++++++++- 4 files changed, 87 insertions(+), 4 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 2f61f7d195..1c398d9ac0 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -356,6 +356,10 @@ void Component::defer(const std::string &name, std::function &&f) { // void Component::defer(const char *name, std::function &&f) { // NOLINT App.scheduler.set_timeout(this, name, 0, std::move(f)); } +void Component::defer(uint32_t id, std::function &&f) { // NOLINT + App.scheduler.set_timeout(this, id, 0, std::move(f)); +} +bool Component::cancel_defer(uint32_t id) { return App.scheduler.cancel_timeout(this, id); } void Component::set_timeout(uint32_t timeout, std::function &&f) { // NOLINT App.scheduler.set_timeout(this, static_cast(nullptr), timeout, std::move(f)); } diff --git a/esphome/core/component.h b/esphome/core/component.h index 49349d4199..97f2afe1a4 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -494,11 +494,15 @@ class Component { /// Defer a callback to the next loop() call. void defer(std::function &&f); // NOLINT + /// Defer a callback with a numeric ID (zero heap allocation) + void defer(uint32_t id, std::function &&f); // NOLINT + /// Cancel a defer callback using the specified name, name must not be empty. // Remove before 2026.7.0 ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_defer(const std::string &name); // NOLINT bool cancel_defer(const char *name); // NOLINT + bool cancel_defer(uint32_t id); // NOLINT // Ordered for optimal packing on 32-bit systems const LogString *component_source_{nullptr}; diff --git a/tests/integration/fixtures/scheduler_numeric_id_test.yaml b/tests/integration/fixtures/scheduler_numeric_id_test.yaml index bf60f2fda9..1669f026f5 100644 --- a/tests/integration/fixtures/scheduler_numeric_id_test.yaml +++ b/tests/integration/fixtures/scheduler_numeric_id_test.yaml @@ -20,6 +20,9 @@ globals: - id: retry_counter type: int initial_value: '0' + - id: defer_counter + type: int + initial_value: '0' - id: tests_done type: bool initial_value: 'false' @@ -136,11 +139,49 @@ script: App.scheduler.cancel_retry(component1, 6002U); ESP_LOGI("test", "Cancelled numeric retry 6002"); + // Test 12: defer with numeric ID (Component method) + class TestDeferComponent : public Component { + public: + void test_defer_methods() { + // Test defer with uint32_t ID - should execute on next loop + this->defer(7001U, []() { + ESP_LOGI("test", "Component numeric defer 7001 fired"); + id(defer_counter) += 1; + }); + + // Test another defer with numeric ID + this->defer(7002U, []() { + ESP_LOGI("test", "Component numeric defer 7002 fired"); + id(defer_counter) += 1; + }); + } + }; + + static TestDeferComponent test_defer_component; + test_defer_component.test_defer_methods(); + + // Test 13: cancel_defer with numeric ID (Component method) + class TestCancelDeferComponent : public Component { + public: + void test_cancel_defer() { + // Set a defer that should be cancelled + this->defer(8001U, []() { + ESP_LOGE("test", "ERROR: Numeric defer 8001 should have been cancelled"); + }); + // Cancel it immediately + bool cancelled = this->cancel_defer(8001U); + ESP_LOGI("test", "Cancelled numeric defer 8001: %s", cancelled ? "true" : "false"); + } + }; + + static TestCancelDeferComponent test_cancel_defer_component; + test_cancel_defer_component.test_cancel_defer(); + - id: report_results then: - lambda: |- - ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d", - id(timeout_counter), id(interval_counter), id(retry_counter)); + ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d, Defers: %d", + id(timeout_counter), id(interval_counter), id(retry_counter), id(defer_counter)); sensor: - platform: template diff --git a/tests/integration/test_scheduler_numeric_id_test.py b/tests/integration/test_scheduler_numeric_id_test.py index 510256b9a4..c1958db685 100644 --- a/tests/integration/test_scheduler_numeric_id_test.py +++ b/tests/integration/test_scheduler_numeric_id_test.py @@ -19,6 +19,7 @@ async def test_scheduler_numeric_id_test( timeout_count = 0 interval_count = 0 retry_count = 0 + defer_count = 0 # Events for each test completion numeric_timeout_1001_fired = asyncio.Event() @@ -33,6 +34,9 @@ async def test_scheduler_numeric_id_test( max_id_timeout_fired = asyncio.Event() numeric_retry_done = asyncio.Event() numeric_retry_cancelled = asyncio.Event() + numeric_defer_7001_fired = asyncio.Event() + numeric_defer_7002_fired = asyncio.Event() + numeric_defer_cancelled = asyncio.Event() final_results_logged = asyncio.Event() # Track interval counts @@ -40,7 +44,7 @@ async def test_scheduler_numeric_id_test( numeric_retry_count = 0 def on_log_line(line: str) -> None: - nonlocal timeout_count, interval_count, retry_count + nonlocal timeout_count, interval_count, retry_count, defer_count nonlocal numeric_interval_count, numeric_retry_count # Strip ANSI color codes @@ -105,15 +109,27 @@ async def test_scheduler_numeric_id_test( elif "Cancelled numeric retry 6002" in clean_line: numeric_retry_cancelled.set() + # Check for numeric defer tests + elif "Component numeric defer 7001 fired" in clean_line: + numeric_defer_7001_fired.set() + + elif "Component numeric defer 7002 fired" in clean_line: + numeric_defer_7002_fired.set() + + elif "Cancelled numeric defer 8001: true" in clean_line: + numeric_defer_cancelled.set() + # Check for final results elif "Final results" in clean_line: match = re.search( - r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+)", clean_line + r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+), Defers: (\d+)", + clean_line, ) if match: timeout_count = int(match.group(1)) interval_count = int(match.group(2)) retry_count = int(match.group(3)) + defer_count = int(match.group(4)) final_results_logged.set() async with ( @@ -201,6 +217,23 @@ async def test_scheduler_numeric_id_test( "Numeric retry 6002 should have been cancelled" ) + # Wait for numeric defer tests + try: + await asyncio.wait_for(numeric_defer_7001_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 7001 did not fire within 0.5 seconds") + + try: + await asyncio.wait_for(numeric_defer_7002_fired.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 7002 did not fire within 0.5 seconds") + + # Verify numeric defer was cancelled + try: + await asyncio.wait_for(numeric_defer_cancelled.wait(), timeout=0.5) + except TimeoutError: + pytest.fail("Numeric defer 8001 cancel confirmation not received") + # Wait for final results try: await asyncio.wait_for(final_results_logged.wait(), timeout=3.0) @@ -215,3 +248,4 @@ async def test_scheduler_numeric_id_test( assert retry_count >= 2, ( f"Expected at least 2 retry attempts, got {retry_count}" ) + assert defer_count >= 2, f"Expected at least 2 defer fires, got {defer_count}" From 094d64f872f9bf3856ba6fec8eb8dabf2f5114c7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 03:19:38 +0100 Subject: [PATCH 0510/2030] [http_request] Fix requests taking full timeout when response is already complete (#13649) --- .../update/esp32_hosted_update.cpp | 14 ++++- .../components/http_request/http_request.h | 55 ++++++++++++++----- .../http_request/http_request_arduino.cpp | 20 ++++++- .../http_request/http_request_idf.cpp | 9 +-- .../http_request/ota/ota_http_request.cpp | 6 +- 5 files changed, 78 insertions(+), 26 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index 0e0778dd23..7ffa61fc97 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -193,11 +193,14 @@ bool Esp32HostedUpdate::fetch_manifest_() { int read_or_error = container->read(buf, sizeof(buf)); App.feed_wdt(); yield(); - auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == http_request::HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added in the future. if (result != http_request::HttpReadLoopResult::DATA) - break; // ERROR or TIMEOUT + break; // COMPLETE, ERROR, or TIMEOUT json_str.append(reinterpret_cast(buf), read_or_error); } container->end(); @@ -318,9 +321,14 @@ bool Esp32HostedUpdate::stream_firmware_to_coprocessor_() { App.feed_wdt(); yield(); - auto result = http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_request::http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == http_request::HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added in the future. + if (result == http_request::HttpReadLoopResult::COMPLETE) + break; if (result != http_request::HttpReadLoopResult::DATA) { if (result == http_request::HttpReadLoopResult::TIMEOUT) { ESP_LOGE(TAG, "Timeout reading firmware data"); diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index fb39ca504c..f3c99c6de4 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -26,6 +26,7 @@ struct Header { enum HttpStatus { HTTP_STATUS_OK = 200, HTTP_STATUS_NO_CONTENT = 204, + HTTP_STATUS_RESET_CONTENT = 205, HTTP_STATUS_PARTIAL_CONTENT = 206, /* 3xx - Redirection */ @@ -126,19 +127,21 @@ struct HttpReadResult { /// Result of processing a non-blocking read with timeout (for manual loops) enum class HttpReadLoopResult : uint8_t { - DATA, ///< Data was read, process it - RETRY, ///< No data yet, already delayed, caller should continue loop - ERROR, ///< Read error, caller should exit loop - TIMEOUT, ///< Timeout waiting for data, caller should exit loop + DATA, ///< Data was read, process it + COMPLETE, ///< All content has been read, caller should exit loop + RETRY, ///< No data yet, already delayed, caller should continue loop + ERROR, ///< Read error, caller should exit loop + TIMEOUT, ///< Timeout waiting for data, caller should exit loop }; /// Process a read result with timeout tracking and delay handling /// @param bytes_read_or_error Return value from read() - positive for bytes read, negative for error /// @param last_data_time Time of last successful read, updated when data received /// @param timeout_ms Maximum time to wait for data -/// @return DATA if data received, RETRY if should continue loop, ERROR/TIMEOUT if should exit -inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, - uint32_t timeout_ms) { +/// @param is_read_complete Whether all expected content has been read (from HttpContainer::is_read_complete()) +/// @return How the caller should proceed - see HttpReadLoopResult enum +inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_t &last_data_time, uint32_t timeout_ms, + bool is_read_complete) { if (bytes_read_or_error > 0) { last_data_time = millis(); return HttpReadLoopResult::DATA; @@ -146,7 +149,10 @@ inline HttpReadLoopResult http_read_loop_result(int bytes_read_or_error, uint32_ if (bytes_read_or_error < 0) { return HttpReadLoopResult::ERROR; } - // bytes_read_or_error == 0: no data available yet + // bytes_read_or_error == 0: either "no data yet" or "all content read" + if (is_read_complete) { + return HttpReadLoopResult::COMPLETE; + } if (millis() - last_data_time >= timeout_ms) { return HttpReadLoopResult::TIMEOUT; } @@ -159,9 +165,9 @@ class HttpRequestComponent; class HttpContainer : public Parented { public: virtual ~HttpContainer() = default; - size_t content_length; - int status_code; - uint32_t duration_ms; + size_t content_length{0}; + int status_code{-1}; ///< -1 indicates no response received yet + uint32_t duration_ms{0}; /** * @brief Read data from the HTTP response body. @@ -194,9 +200,24 @@ class HttpContainer : public Parented { virtual void end() = 0; void set_secure(bool secure) { this->secure_ = secure; } + void set_chunked(bool chunked) { this->is_chunked_ = chunked; } size_t get_bytes_read() const { return this->bytes_read_; } + /// Check if all expected content has been read + /// For chunked responses, returns false (completion detected via read() returning error/EOF) + bool is_read_complete() const { + // Per RFC 9112, these responses have no body: + // - 1xx (Informational), 204 No Content, 205 Reset Content, 304 Not Modified + if ((this->status_code >= 100 && this->status_code < 200) || this->status_code == HTTP_STATUS_NO_CONTENT || + this->status_code == HTTP_STATUS_RESET_CONTENT || this->status_code == HTTP_STATUS_NOT_MODIFIED) { + return true; + } + // For non-chunked responses, complete when bytes_read >= content_length + // This handles both Content-Length: 0 and Content-Length: N cases + return !this->is_chunked_ && this->bytes_read_ >= this->content_length; + } + /** * @brief Get response headers. * @@ -209,6 +230,7 @@ class HttpContainer : public Parented { protected: size_t bytes_read_{0}; bool secure_{false}; + bool is_chunked_{false}; ///< True if response uses chunked transfer encoding std::map> response_headers_{}; }; @@ -219,7 +241,7 @@ class HttpContainer : public Parented { /// @param total_size Total bytes to read /// @param chunk_size Maximum bytes per read call /// @param timeout_ms Read timeout in milliseconds -/// @return HttpReadResult with status and error_code on failure +/// @return HttpReadResult with status and error_code on failure; use container->get_bytes_read() for total bytes read inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, size_t total_size, size_t chunk_size, uint32_t timeout_ms) { size_t read_index = 0; @@ -231,9 +253,11 @@ inline HttpReadResult http_read_fully(HttpContainer *container, uint8_t *buffer, App.feed_wdt(); yield(); - auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms); + auto result = http_read_loop_result(read_bytes_or_error, last_data_time, timeout_ms, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; + if (result == HttpReadLoopResult::COMPLETE) + break; // Server sent less data than requested, but transfer is complete if (result == HttpReadLoopResult::ERROR) return {HttpReadStatus::ERROR, read_bytes_or_error}; if (result == HttpReadLoopResult::TIMEOUT) @@ -393,11 +417,12 @@ template class HttpRequestSendAction : public Action { int read_or_error = container->read(buf + read_index, std::min(max_length - read_index, 512)); App.feed_wdt(); yield(); - auto result = http_read_loop_result(read_or_error, last_data_time, read_timeout); + auto result = + http_read_loop_result(read_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; if (result != HttpReadLoopResult::DATA) - break; // ERROR or TIMEOUT + break; // COMPLETE, ERROR, or TIMEOUT read_index += read_or_error; } response_body.reserve(read_index); diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 82538b2cb3..2f12b58766 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -135,9 +135,23 @@ std::shared_ptr HttpRequestArduino::perform(const std::string &ur // When cast to size_t, -1 becomes SIZE_MAX (4294967295 on 32-bit). // The read() method handles this: bytes_read_ can never reach SIZE_MAX, so the // early return check (bytes_read_ >= content_length) will never trigger. + // + // TODO: Chunked transfer encoding is NOT properly supported on Arduino. + // The implementation in #7884 was incomplete - it only works correctly on ESP-IDF where + // esp_http_client_read() decodes chunks internally. On Arduino, using getStreamPtr() + // returns raw TCP data with chunk framing (e.g., "12a\r\n{json}\r\n0\r\n\r\n") instead + // of decoded content. This wasn't noticed because requests would complete and payloads + // were only examined on IDF. The long transfer times were also masked by the misleading + // "HTTP on Arduino version >= 3.1 is **very** slow" warning above. This causes two issues: + // 1. Response body is corrupted - contains chunk size headers mixed with data + // 2. Cannot detect end of transfer - connection stays open (keep-alive), causing timeout + // The proper fix would be to use getString() for chunked responses, which decodes chunks + // internally, but this buffers the entire response in memory. int content_length = container->client_.getSize(); ESP_LOGD(TAG, "Content-Length: %d", content_length); container->content_length = (size_t) content_length; + // -1 (SIZE_MAX when cast to size_t) means chunked transfer encoding + container->set_chunked(content_length == -1); container->duration_ms = millis() - start; return container; @@ -178,9 +192,9 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { if (bufsize == 0) { this->duration_ms += (millis() - start); - // Check if we've read all expected content (only valid when content_length is known and not SIZE_MAX) - // For chunked encoding (content_length == SIZE_MAX), we can't use this check - if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { + // Check if we've read all expected content (non-chunked only) + // For chunked encoding (content_length == SIZE_MAX), is_read_complete() returns false + if (this->is_read_complete()) { return 0; // All content read successfully } // No data available - check if connection is still open diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 95c59aa04c..9cfa825e17 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -155,6 +155,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c // esp_http_client_fetch_headers() returns 0 for chunked transfer encoding (no Content-Length header). // The read() method handles content_length == 0 specially to support chunked responses. container->content_length = esp_http_client_fetch_headers(client); + container->set_chunked(esp_http_client_is_chunked_response(client)); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); container->feed_wdt(); @@ -190,6 +191,7 @@ std::shared_ptr HttpRequestIDF::perform(const std::string &url, c container->feed_wdt(); container->content_length = esp_http_client_fetch_headers(client); + container->set_chunked(esp_http_client_is_chunked_response(client)); container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); container->feed_wdt(); @@ -234,10 +236,9 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); - // Check if we've already read all expected content - // Skip this check when content_length is 0 (chunked transfer encoding or unknown length) - // For chunked responses, esp_http_client_read() will return 0 when all data is received - if (this->content_length > 0 && this->bytes_read_ >= this->content_length) { + // Check if we've already read all expected content (non-chunked only) + // For chunked responses (content_length == 0), esp_http_client_read() handles EOF + if (this->is_read_complete()) { return 0; // All content read successfully } diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 6c77e75d8c..d073644a37 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -130,9 +130,13 @@ uint8_t OtaHttpRequestComponent::do_ota_() { App.feed_wdt(); yield(); - auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout); + auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; + // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, + // but this is defensive code in case chunked transfer encoding support is added for OTA in the future. + if (result == HttpReadLoopResult::COMPLETE) + break; if (result != HttpReadLoopResult::DATA) { if (result == HttpReadLoopResult::TIMEOUT) { ESP_LOGE(TAG, "Timeout reading data"); From bc41d25657236e32b04465ae05040b8928f0448c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 3 Feb 2026 17:03:02 +0100 Subject: [PATCH 0511/2030] [cse7766] Fix power reading stuck when load switches off (#13734) --- esphome/components/cse7766/cse7766.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 71fe15f0ae..e7bcb64f8c 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -152,6 +152,10 @@ void CSE7766Component::parse_data_() { if (this->power_sensor_ != nullptr) { this->power_sensor_->publish_state(power); } + } else if (this->power_sensor_ != nullptr) { + // No valid power measurement from chip - publish 0W to avoid stale readings + // This typically happens when current is below the measurable threshold (~50mA) + this->power_sensor_->publish_state(0.0f); } float current = 0.0f; From 900aab45f12b7b6d590d97c7ad086743c36de078 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 4 Feb 2026 09:42:13 +0100 Subject: [PATCH 0512/2030] [wifi] Fix wifi.connected condition returning false in connect state listener automations (#13733) --- esphome/components/wifi/wifi_component.cpp | 21 +++++++++++++++++++ esphome/components/wifi/wifi_component.h | 15 +++++++++++++ .../wifi/wifi_component_esp8266.cpp | 10 ++++++--- .../wifi/wifi_component_esp_idf.cpp | 9 +++++--- .../wifi/wifi_component_libretiny.cpp | 11 ++++++---- .../components/wifi/wifi_component_pico_w.cpp | 12 ++++++----- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 52d9b2b442..fd7e2c6ee6 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1383,6 +1383,12 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { this->release_scan_results_(); +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + // Notify listeners now that state machine has reached STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->notify_connect_state_listeners_(); +#endif + return; } @@ -2090,6 +2096,21 @@ void WiFiComponent::release_scan_results_() { } } +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS +void WiFiComponent::notify_connect_state_listeners_() { + if (!this->pending_.connect_state) + return; + this->pending_.connect_state = false; + // Get current SSID and BSSID from the WiFi driver + char ssid_buf[SSID_BUFFER_SIZE]; + const char *ssid = this->wifi_ssid_to(ssid_buf); + bssid_t bssid = this->wifi_bssid(); + for (auto *listener : this->connect_state_listeners_) { + listener->on_wifi_connect_state(StringRef(ssid, strlen(ssid)), bssid); + } +} +#endif // USE_WIFI_CONNECT_STATE_LISTENERS + void WiFiComponent::check_roaming_(uint32_t now) { // Guard: not for hidden networks (may not appear in scan) const WiFiAP *selected = this->get_selected_sta_(); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index dfc91fb5da..28db486b88 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -618,6 +618,11 @@ class WiFiComponent : public Component { /// Free scan results memory unless a component needs them void release_scan_results_(); +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + /// Notify connect state listeners (called after state machine reaches STA_CONNECTED) + void notify_connect_state_listeners_(); +#endif + #ifdef USE_ESP8266 static void wifi_event_callback(System_Event_t *event); void wifi_scan_done_callback_(void *arg, STATUS status); @@ -721,6 +726,16 @@ class WiFiComponent : public Component { SemaphoreHandle_t high_performance_semaphore_{nullptr}; #endif +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + // Pending listener notifications deferred until state machine reaches appropriate state. + // Listeners are notified after state transitions complete so conditions like + // wifi.connected return correct values in automations. + // Uses bitfields to minimize memory; more flags may be added as needed. + struct { + bool connect_state : 1; // Notify connect state listeners after STA_CONNECTED + } pending_{}; +#endif + // Pointers at the end (naturally aligned) Trigger<> *connect_trigger_{new Trigger<>()}; Trigger<> *disconnect_trigger_{new Trigger<>()}; diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 59101439c2..41033cca19 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -500,6 +500,10 @@ const LogString *get_disconnect_reason_str(uint8_t reason) { } } +// TODO: This callback runs in ESP8266 system context with limited stack (~2KB). +// All listener notifications should be deferred to wifi_loop_() via pending_ flags +// to avoid stack overflow. Currently only connect_state is deferred; disconnect, +// IP, and scan listeners still run in this context and should be migrated. void WiFiComponent::wifi_event_callback(System_Event_t *event) { switch (event->event) { case EVENT_STAMODE_CONNECTED: { @@ -512,9 +516,9 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { #endif s_sta_connected = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : global_wifi_component->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + global_wifi_component->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 15fd407e3c..711d88bd68 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -710,6 +710,9 @@ void WiFiComponent::wifi_loop_() { delete data; // NOLINT(cppcoreguidelines-owning-memory) } } +// Events are processed from queue in main loop context, but listener notifications +// must be deferred until after the state machine transitions (in check_connecting_finished) +// so that conditions like wifi.connected return correct values in automations. void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { esp_err_t err; if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_START) { @@ -743,9 +746,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { #endif s_sta_connected = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 20cd32fa8f..cddca2aa91 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -423,7 +423,10 @@ void WiFiComponent::wifi_event_callback_(esphome_wifi_event_id_t event, esphome_ } } -// Process a single event from the queue - runs in main loop context +// Process a single event from the queue - runs in main loop context. +// Listener notifications must be deferred until after the state machine transitions +// (in check_connecting_finished) so that conditions like wifi.connected return +// correct values in automations. void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { switch (event->event_id) { case ESPHOME_EVENT_ID_WIFI_READY: { @@ -456,9 +459,9 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // This matches ESP32 IDF behavior where s_sta_connected is set but // wifi_sta_connect_status_() also checks got_ipv4_address_ #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(it.ssid, it.ssid_len), it.bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, GOT_IP event may not fire, so set connected state here #ifdef USE_WIFI_MANUAL_IP diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 29ac096d94..c55aeef5a4 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -240,6 +240,10 @@ network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(dns_ip); } +// Pico W uses polling for connection state detection. +// Connect state listener notifications are deferred until after the state machine +// transitions (in check_connecting_finished) so that conditions like wifi.connected +// return correct values in automations. void WiFiComponent::wifi_loop_() { // Handle scan completion if (this->state_ == WIFI_COMPONENT_STATE_STA_SCANNING && !cyw43_wifi_scan_active(&cyw43_state)) { @@ -264,11 +268,9 @@ void WiFiComponent::wifi_loop_() { s_sta_was_connected = true; ESP_LOGV(TAG, "Connected"); #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - String ssid = WiFi.SSID(); - bssid_t bssid = this->wifi_bssid(); - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(ssid.c_str(), ssid.length()), bssid); - } + // Defer listener notification until state machine reaches STA_CONNECTED + // This ensures wifi.connected condition returns true in listener automations + this->pending_.connect_state = true; #endif // For static IP configurations, notify IP listeners immediately as the IP is already configured #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) From bafbd4235a5ac9d631b79d64ce1a1a796fbc3d18 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Wed, 4 Feb 2026 01:29:27 -0800 Subject: [PATCH 0513/2030] [ultrasonic] adjust timeouts and bring the parameter back (#13738) Co-authored-by: Samuel Sieb --- CODEOWNERS | 2 +- esphome/components/ultrasonic/__init__.py | 2 +- esphome/components/ultrasonic/sensor.py | 11 +--- .../ultrasonic/ultrasonic_sensor.cpp | 56 ++++++++++++++----- .../components/ultrasonic/ultrasonic_sensor.h | 5 ++ 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 8a37aeb29f..136152e6ff 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -528,7 +528,7 @@ esphome/components/uart/packet_transport/* @clydebarrow esphome/components/udp/* @clydebarrow esphome/components/ufire_ec/* @pvizeli esphome/components/ufire_ise/* @pvizeli -esphome/components/ultrasonic/* @OttoWinter +esphome/components/ultrasonic/* @ssieb @swoboda1337 esphome/components/update/* @jesserockz esphome/components/uponor_smatrix/* @kroimon esphome/components/usb_cdc_acm/* @kbx81 diff --git a/esphome/components/ultrasonic/__init__.py b/esphome/components/ultrasonic/__init__.py index 71a87b6ae5..3bca12bffc 100644 --- a/esphome/components/ultrasonic/__init__.py +++ b/esphome/components/ultrasonic/__init__.py @@ -1 +1 @@ -CODEOWNERS = ["@OttoWinter"] +CODEOWNERS = ["@swoboda1337", "@ssieb"] diff --git a/esphome/components/ultrasonic/sensor.py b/esphome/components/ultrasonic/sensor.py index 4b04ee7578..fad4e6b11d 100644 --- a/esphome/components/ultrasonic/sensor.py +++ b/esphome/components/ultrasonic/sensor.py @@ -34,7 +34,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_TRIGGER_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema, - cv.Optional(CONF_TIMEOUT): cv.distance, + cv.Optional(CONF_TIMEOUT, default="2m"): cv.distance, cv.Optional( CONF_PULSE_TIME, default="10us" ): cv.positive_time_period_microseconds, @@ -52,12 +52,5 @@ async def to_code(config): cg.add(var.set_trigger_pin(trigger)) echo = await cg.gpio_pin_expression(config[CONF_ECHO_PIN]) cg.add(var.set_echo_pin(echo)) - - # Remove before 2026.8.0 - if CONF_TIMEOUT in config: - _LOGGER.warning( - "'timeout' option is deprecated and will be removed in 2026.8.0. " - "The option has no effect and can be safely removed." - ) - + cg.add(var.set_timeout_us(config[CONF_TIMEOUT] / (0.000343 / 2))) cg.add(var.set_pulse_time_us(config[CONF_PULSE_TIME])) diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index 369a10edbd..d3f7e69444 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -6,12 +6,11 @@ namespace esphome::ultrasonic { static const char *const TAG = "ultrasonic.sensor"; -static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us (noise filtering) -static constexpr uint32_t MEASUREMENT_TIMEOUT_US = 80000; // Maximum time to wait for measurement completion +static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { uint32_t now = micros(); - if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) { + if (arg->echo_pin_isr.digital_read()) { arg->echo_start_us = now; arg->echo_start = true; } else { @@ -38,6 +37,7 @@ void UltrasonicSensorComponent::setup() { this->trigger_pin_->digital_write(false); this->trigger_pin_isr_ = this->trigger_pin_->to_isr(); this->echo_pin_->setup(); + this->store_.echo_pin_isr = this->echo_pin_->to_isr(); this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE); } @@ -53,29 +53,55 @@ void UltrasonicSensorComponent::loop() { return; } + if (!this->store_.echo_start) { + uint32_t elapsed = micros() - this->measurement_start_us_; + if (elapsed >= START_TIMEOUT_US) { + ESP_LOGW(TAG, "'%s' - Measurement start timed out", this->name_.c_str()); + this->publish_state(NAN); + this->measurement_pending_ = false; + return; + } + } else { + uint32_t elapsed; + if (this->store_.echo_end) { + elapsed = this->store_.echo_end_us - this->store_.echo_start_us; + } else { + elapsed = micros() - this->store_.echo_start_us; + } + if (elapsed >= this->timeout_us_) { + ESP_LOGD(TAG, "'%s' - Measurement pulse timed out after %" PRIu32 "us", this->name_.c_str(), elapsed); + this->publish_state(NAN); + this->measurement_pending_ = false; + return; + } + } + if (this->store_.echo_end) { - uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; - ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration); - float result = UltrasonicSensorComponent::us_to_m(pulse_duration); - ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); + float result; + if (this->store_.echo_start) { + uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; + ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us", + this->store_.echo_start_us - this->measurement_start_us_, pulse_duration); + result = UltrasonicSensorComponent::us_to_m(pulse_duration); + ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); + } else { + ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str()); + result = NAN; + } this->publish_state(result); this->measurement_pending_ = false; return; } - - uint32_t elapsed = micros() - this->measurement_start_us_; - if (elapsed >= MEASUREMENT_TIMEOUT_US) { - ESP_LOGD(TAG, "'%s' - Measurement timed out after %" PRIu32 "us", this->name_.c_str(), elapsed); - this->publish_state(NAN); - this->measurement_pending_ = false; - } } void UltrasonicSensorComponent::dump_config() { LOG_SENSOR("", "Ultrasonic Sensor", this); LOG_PIN(" Echo Pin: ", this->echo_pin_); LOG_PIN(" Trigger Pin: ", this->trigger_pin_); - ESP_LOGCONFIG(TAG, " Pulse time: %" PRIu32 " us", this->pulse_time_us_); + ESP_LOGCONFIG(TAG, + " Pulse time: %" PRIu32 " µs\n" + " Timeout: %" PRIu32 " µs", + this->pulse_time_us_, this->timeout_us_); LOG_UPDATE_INTERVAL(this); } diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index b0c00e51f0..a38737aff5 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -11,6 +11,8 @@ namespace esphome::ultrasonic { struct UltrasonicSensorStore { static void gpio_intr(UltrasonicSensorStore *arg); + ISRInternalGPIOPin echo_pin_isr; + volatile uint32_t wait_start_us{0}; volatile uint32_t echo_start_us{0}; volatile uint32_t echo_end_us{0}; volatile bool echo_start{false}; @@ -29,6 +31,8 @@ class UltrasonicSensorComponent : public sensor::Sensor, public PollingComponent float get_setup_priority() const override { return setup_priority::DATA; } + /// Set the maximum time in µs to wait for the echo to return + void set_timeout_us(uint32_t timeout_us) { this->timeout_us_ = timeout_us; } /// Set the time in µs the trigger pin should be enabled for in µs, defaults to 10µs (for HC-SR04) void set_pulse_time_us(uint32_t pulse_time_us) { this->pulse_time_us_ = pulse_time_us; } @@ -41,6 +45,7 @@ class UltrasonicSensorComponent : public sensor::Sensor, public PollingComponent ISRInternalGPIOPin trigger_pin_isr_; InternalGPIOPin *echo_pin_; UltrasonicSensorStore store_; + uint32_t timeout_us_{}; uint32_t pulse_time_us_{}; uint32_t measurement_start_us_{0}; From 1b3c9aa98efba2235f5a406ca0752faba7c160bf Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:01:32 +0100 Subject: [PATCH 0514/2030] Bump version to 2026.1.4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index f9ffa9e25a..140ac06565 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.3 +PROJECT_NUMBER = 2026.1.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 1ce6eb4ba3..862c7e37e6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.3" +__version__ = "2026.1.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From ba18a8b3e33cabbc40772a49348423f3d73ee987 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Feb 2026 06:44:17 -0500 Subject: [PATCH 0515/2030] [adc] Fix ESP32-C2 ADC calibration to use line fitting (#13756) Co-authored-by: Claude Opus 4.5 --- esphome/components/adc/adc_sensor_esp32.cpp | 44 ++++++++----------- tests/components/adc/test.esp32-c2-idf.yaml | 12 +++++ .../build_components_base.esp32-c2-idf.yaml | 20 +++++++++ 3 files changed, 51 insertions(+), 25 deletions(-) create mode 100644 tests/components/adc/test.esp32-c2-idf.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-c2-idf.yaml diff --git a/esphome/components/adc/adc_sensor_esp32.cpp b/esphome/components/adc/adc_sensor_esp32.cpp index ece45f3746..1d3138623e 100644 --- a/esphome/components/adc/adc_sensor_esp32.cpp +++ b/esphome/components/adc/adc_sensor_esp32.cpp @@ -74,10 +74,9 @@ void ADCSensor::setup() { if (this->calibration_handle_ == nullptr) { adc_cali_handle_t handle = nullptr; -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 - // RISC-V variants and S3 use curve fitting calibration +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 + // RISC-V variants (except C2) and S3 use curve fitting calibration adc_cali_curve_fitting_config_t cali_config = {}; // Zero initialize first #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) cali_config.chan = this->channel_; @@ -95,14 +94,14 @@ void ADCSensor::setup() { ESP_LOGW(TAG, "Curve fitting calibration failed with error %d, will use uncalibrated readings", err); this->setup_flags_.calibration_complete = false; } -#else // Other ESP32 variants use line fitting calibration +#else // ESP32, ESP32-S2, and ESP32-C2 use line fitting calibration adc_cali_line_fitting_config_t cali_config = { .unit_id = this->adc_unit_, .atten = this->attenuation_, .bitwidth = ADC_BITWIDTH_DEFAULT, -#if !defined(USE_ESP32_VARIANT_ESP32S2) +#if !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32C2) .default_vref = 1100, // Default reference voltage in mV -#endif // !defined(USE_ESP32_VARIANT_ESP32S2) +#endif // !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32C2) }; err = adc_cali_create_scheme_line_fitting(&cali_config, &handle); if (err == ESP_OK) { @@ -113,7 +112,7 @@ void ADCSensor::setup() { ESP_LOGW(TAG, "Line fitting calibration failed with error %d, will use uncalibrated readings", err); this->setup_flags_.calibration_complete = false; } -#endif // USE_ESP32_VARIANT_ESP32C2 || ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 +#endif // ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 } this->setup_flags_.init_complete = true; @@ -185,13 +184,12 @@ float ADCSensor::sample_fixed_attenuation_() { } else { ESP_LOGW(TAG, "ADC calibration conversion failed with error %d, disabling calibration", err); if (this->calibration_handle_ != nullptr) { -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else // Other ESP32 variants use line fitting calibration adc_cali_delete_scheme_line_fitting(this->calibration_handle_); -#endif // USE_ESP32_VARIANT_ESP32C2 || ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 +#endif // ESP32C3 || ESP32C5 || ESP32C6 || ESP32C61 || ESP32H2 || ESP32P4 || ESP32S3 this->calibration_handle_ = nullptr; } } @@ -219,9 +217,8 @@ float ADCSensor::sample_autorange_() { // Need to recalibrate for the new attenuation if (this->calibration_handle_ != nullptr) { // Delete old calibration handle -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(this->calibration_handle_); #else adc_cali_delete_scheme_line_fitting(this->calibration_handle_); @@ -232,9 +229,8 @@ float ADCSensor::sample_autorange_() { // Create new calibration handle for this attenuation adc_cali_handle_t handle = nullptr; -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_curve_fitting_config_t cali_config = {}; #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) cali_config.chan = this->channel_; @@ -251,7 +247,7 @@ float ADCSensor::sample_autorange_() { .unit_id = this->adc_unit_, .atten = atten, .bitwidth = ADC_BITWIDTH_DEFAULT, -#if !defined(USE_ESP32_VARIANT_ESP32S2) +#if !defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32C2) .default_vref = 1100, #endif }; @@ -268,9 +264,8 @@ float ADCSensor::sample_autorange_() { if (err != ESP_OK) { ESP_LOGW(TAG, "ADC read failed in autorange with error %d", err); if (handle != nullptr) { -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); @@ -291,9 +286,8 @@ float ADCSensor::sample_autorange_() { ESP_LOGVV(TAG, "Autorange atten=%d: UNCALIBRATED FALLBACK - raw=%d -> %.6fV (3.3V ref)", atten, raw, voltage); } // Clean up calibration handle -#if USE_ESP32_VARIANT_ESP32C2 || USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || \ - USE_ESP32_VARIANT_ESP32C6 || USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || \ - USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 +#if USE_ESP32_VARIANT_ESP32C3 || USE_ESP32_VARIANT_ESP32C5 || USE_ESP32_VARIANT_ESP32C6 || \ + USE_ESP32_VARIANT_ESP32C61 || USE_ESP32_VARIANT_ESP32H2 || USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S3 adc_cali_delete_scheme_curve_fitting(handle); #else adc_cali_delete_scheme_line_fitting(handle); diff --git a/tests/components/adc/test.esp32-c2-idf.yaml b/tests/components/adc/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..e764f0fe21 --- /dev/null +++ b/tests/components/adc/test.esp32-c2-idf.yaml @@ -0,0 +1,12 @@ +sensor: + - id: my_sensor + platform: adc + pin: GPIO1 + name: ADC Test sensor + update_interval: "1:01" + attenuation: 2.5db + unit_of_measurement: "°C" + icon: "mdi:water-percent" + accuracy_decimals: 5 + setup_priority: -100 + force_update: true diff --git a/tests/test_build_components/build_components_base.esp32-c2-idf.yaml b/tests/test_build_components/build_components_base.esp32-c2-idf.yaml new file mode 100644 index 0000000000..59691be7aa --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-c2-idf.yaml @@ -0,0 +1,20 @@ +esphome: + name: componenttestesp32c2idf + friendly_name: $component_name + +esp32: + board: esp32-c2-devkitm-1 + framework: + type: esp-idf + # Use custom partition table with larger app partition (3MB) + # Default IDF partitions only allow 1.75MB which is too small for grouped tests + partitions: ../partitions_testing.csv + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_test_file: $component_test_file From 36f2654fa67cdfc76741b6329e76f789671ed775 Mon Sep 17 00:00:00 2001 From: functionpointer Date: Wed, 4 Feb 2026 17:06:59 +0100 Subject: [PATCH 0516/2030] [pylontech] Refactor parser to support new firmware version and SysError (#12300) --- esphome/components/pylontech/pylontech.cpp | 138 ++++++++++++++++++--- esphome/components/pylontech/pylontech.h | 7 +- 2 files changed, 122 insertions(+), 23 deletions(-) diff --git a/esphome/components/pylontech/pylontech.cpp b/esphome/components/pylontech/pylontech.cpp index 74b7caefb2..61b5356c90 100644 --- a/esphome/components/pylontech/pylontech.cpp +++ b/esphome/components/pylontech/pylontech.cpp @@ -2,6 +2,28 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +// Helper macros +#define PARSE_INT(field, field_name) \ + { \ + get_token(token_buf); \ + auto val = parse_number(token_buf); \ + if (val.has_value()) { \ + (field) = val.value(); \ + } else { \ + ESP_LOGD(TAG, "invalid " field_name " in line %s", buffer.substr(0, buffer.size() - 2).c_str()); \ + return; \ + } \ + } + +#define PARSE_STR(field, field_name) \ + { \ + get_token(field); \ + if (strlen(field) < 2) { \ + ESP_LOGD(TAG, "too short " field_name " in line %s", buffer.substr(0, buffer.size() - 2).c_str()); \ + return; \ + } \ + } + namespace esphome { namespace pylontech { @@ -64,33 +86,106 @@ void PylontechComponent::loop() { void PylontechComponent::process_line_(std::string &buffer) { ESP_LOGV(TAG, "Read from serial: %s", buffer.substr(0, buffer.size() - 2).c_str()); // clang-format off - // example line to parse: - // Power Volt Curr Tempr Tlow Thigh Vlow Vhigh Base.St Volt.St Curr.St Temp.St Coulomb Time B.V.St B.T.St MosTempr M.T.St - // 1 50548 8910 25000 24200 25000 3368 3371 Charge Normal Normal Normal 97% 2021-06-30 20:49:45 Normal Normal 22700 Normal + // example lines to parse: + // Power Volt Curr Tempr Tlow Thigh Vlow Vhigh Base.St Volt.St Curr.St Temp.St Coulomb Time B.V.St B.T.St MosTempr M.T.St + // 1 50548 8910 25000 24200 25000 3368 3371 Charge Normal Normal Normal 97% 2021-06-30 20:49:45 Normal Normal 22700 Normal + // 1 46012 1255 9100 5300 5500 3047 3091 SysError Low Normal Normal 4% 2025-11-28 17:56:33 Low Normal 7800 Normal + // newer firmware example: + // Power Volt Curr Tempr Tlow Tlow.Id Thigh Thigh.Id Vlow Vlow.Id Vhigh Vhigh.Id Base.St Volt.St Curr.St Temp.St Coulomb Time B.V.St B.T.St MosTempr M.T.St SysAlarm.St + // 1 49405 0 17600 13700 8 14500 0 3293 2 3294 0 Idle Normal Normal Normal 60% 2025-12-05 00:53:41 Normal Normal 16600 Normal Normal // clang-format on PylontechListener::LineContents l{}; - char mostempr_s[6]; - const int parsed = sscanf( // NOLINT - buffer.c_str(), "%d %d %d %d %d %d %d %d %7s %7s %7s %7s %d%% %*d-%*d-%*d %*d:%*d:%*d %*s %*s %5s %*s", // NOLINT - &l.bat_num, &l.volt, &l.curr, &l.tempr, &l.tlow, &l.thigh, &l.vlow, &l.vhigh, l.base_st, l.volt_st, // NOLINT - l.curr_st, l.temp_st, &l.coulomb, mostempr_s); // NOLINT - if (l.bat_num <= 0) { - ESP_LOGD(TAG, "invalid bat_num in line %s", buffer.substr(0, buffer.size() - 2).c_str()); - return; + const char *cursor = buffer.c_str(); + char token_buf[TEXT_SENSOR_MAX_LEN] = {0}; + + // Helper Lambda to extract tokens + auto get_token = [&](char *token_buf) -> void { + // Skip leading whitespace + while (*cursor == ' ' || *cursor == '\t') { + cursor++; + } + + if (*cursor == '\0') { + token_buf[0] = 0; + return; + } + + const char *start = cursor; + + // Find end of field + while (*cursor != '\0' && *cursor != ' ' && *cursor != '\t' && *cursor != '\r') { + cursor++; + } + + size_t token_len = std::min(static_cast(cursor - start), static_cast(TEXT_SENSOR_MAX_LEN - 1)); + memcpy(token_buf, start, token_len); + token_buf[token_len] = 0; + }; + + { + get_token(token_buf); + auto val = parse_number(token_buf); + if (val.has_value() && val.value() > 0) { + l.bat_num = val.value(); + } else if (strcmp(token_buf, "Power") == 0) { + // header line i.e. "Power Volt Curr" and so on + this->has_tlow_id_ = buffer.find("Tlow.Id") != std::string::npos; + ESP_LOGD(TAG, "header line %s Tlow.Id: %s", this->has_tlow_id_ ? "with" : "without", + buffer.substr(0, buffer.size() - 2).c_str()); + return; + } else { + ESP_LOGD(TAG, "unknown line %s", buffer.substr(0, buffer.size() - 2).c_str()); + return; + } } - if (parsed != 14) { - ESP_LOGW(TAG, "invalid line: found only %d items in %s", parsed, buffer.substr(0, buffer.size() - 2).c_str()); - return; + PARSE_INT(l.volt, "Volt"); + PARSE_INT(l.curr, "Curr"); + PARSE_INT(l.tempr, "Tempr"); + PARSE_INT(l.tlow, "Tlow"); + if (this->has_tlow_id_) { + get_token(token_buf); // Skip Tlow.Id } - auto mostempr_parsed = parse_number(mostempr_s); - if (mostempr_parsed.has_value()) { - l.mostempr = mostempr_parsed.value(); - } else { - l.mostempr = -300; - ESP_LOGW(TAG, "bat_num %d: received no mostempr", l.bat_num); + PARSE_INT(l.thigh, "Thigh"); + if (this->has_tlow_id_) { + get_token(token_buf); // Skip Thigh.Id } + PARSE_INT(l.vlow, "Vlow"); + if (this->has_tlow_id_) { + get_token(token_buf); // Skip Vlow.Id + } + PARSE_INT(l.vhigh, "Vhigh"); + if (this->has_tlow_id_) { + get_token(token_buf); // Skip Vhigh.Id + } + PARSE_STR(l.base_st, "Base.St"); + PARSE_STR(l.volt_st, "Volt.St"); + PARSE_STR(l.curr_st, "Curr.St"); + PARSE_STR(l.temp_st, "Temp.St"); + { + get_token(token_buf); + for (char &i : token_buf) { + if (i == '%') { + i = 0; + break; + } + } + auto coul_val = parse_number(token_buf); + if (coul_val.has_value()) { + l.coulomb = coul_val.value(); + } else { + ESP_LOGD(TAG, "invalid Coulomb in line %s", buffer.substr(0, buffer.size() - 2).c_str()); + return; + } + } + get_token(token_buf); // Skip Date + get_token(token_buf); // Skip Time + get_token(token_buf); // Skip B.V.St + get_token(token_buf); // Skip B.T.St + PARSE_INT(l.mostempr, "Mostempr"); + + ESP_LOGD(TAG, "successful line %s", buffer.substr(0, buffer.size() - 2).c_str()); for (PylontechListener *listener : this->listeners_) { listener->on_line_read(&l); @@ -101,3 +196,6 @@ float PylontechComponent::get_setup_priority() const { return setup_priority::DA } // namespace pylontech } // namespace esphome + +#undef PARSE_INT +#undef PARSE_STR diff --git a/esphome/components/pylontech/pylontech.h b/esphome/components/pylontech/pylontech.h index 3282cb4d9f..10c669ad9a 100644 --- a/esphome/components/pylontech/pylontech.h +++ b/esphome/components/pylontech/pylontech.h @@ -8,14 +8,14 @@ namespace esphome { namespace pylontech { static const uint8_t NUM_BUFFERS = 20; -static const uint8_t TEXT_SENSOR_MAX_LEN = 8; +static const uint8_t TEXT_SENSOR_MAX_LEN = 14; class PylontechListener { public: struct LineContents { int bat_num = 0, volt, curr, tempr, tlow, thigh, vlow, vhigh, coulomb, mostempr; - char base_st[TEXT_SENSOR_MAX_LEN], volt_st[TEXT_SENSOR_MAX_LEN], curr_st[TEXT_SENSOR_MAX_LEN], - temp_st[TEXT_SENSOR_MAX_LEN]; + char base_st[TEXT_SENSOR_MAX_LEN] = {0}, volt_st[TEXT_SENSOR_MAX_LEN] = {0}, curr_st[TEXT_SENSOR_MAX_LEN] = {0}, + temp_st[TEXT_SENSOR_MAX_LEN] = {0}; }; virtual void on_line_read(LineContents *line); @@ -45,6 +45,7 @@ class PylontechComponent : public PollingComponent, public uart::UARTDevice { std::string buffer_[NUM_BUFFERS]; int buffer_index_write_ = 0; int buffer_index_read_ = 0; + bool has_tlow_id_ = false; std::vector listeners_{}; }; From becb6559f143fc5c361065785fc8260bfe51bd26 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 4 Feb 2026 17:48:41 +0100 Subject: [PATCH 0517/2030] [components] Remove redundant setup priority overrides that duplicate default (#13745) --- esphome/components/absolute_humidity/absolute_humidity.cpp | 2 -- esphome/components/absolute_humidity/absolute_humidity.h | 1 - esphome/components/adc/adc_sensor.h | 5 ----- esphome/components/adc/adc_sensor_common.cpp | 2 -- esphome/components/adc128s102/sensor/adc128s102_sensor.cpp | 2 -- esphome/components/adc128s102/sensor/adc128s102_sensor.h | 1 - esphome/components/aht10/aht10.cpp | 2 -- esphome/components/aht10/aht10.h | 1 - esphome/components/am2315c/am2315c.cpp | 2 -- esphome/components/am2315c/am2315c.h | 1 - esphome/components/am2320/am2320.cpp | 1 - esphome/components/am2320/am2320.h | 1 - esphome/components/apds9960/apds9960.cpp | 1 - esphome/components/apds9960/apds9960.h | 1 - esphome/components/aqi/aqi_sensor.h | 1 - esphome/components/as3935/as3935.cpp | 2 -- esphome/components/as3935/as3935.h | 1 - esphome/components/as5600/sensor/as5600_sensor.cpp | 2 -- esphome/components/as5600/sensor/as5600_sensor.h | 1 - esphome/components/as7341/as7341.cpp | 2 -- esphome/components/as7341/as7341.h | 1 - esphome/components/atm90e26/atm90e26.cpp | 1 - esphome/components/atm90e26/atm90e26.h | 1 - esphome/components/bh1750/bh1750.cpp | 2 -- esphome/components/bh1750/bh1750.h | 1 - esphome/components/bme280_base/bme280_base.cpp | 1 - esphome/components/bme280_base/bme280_base.h | 1 - esphome/components/bme680/bme680.cpp | 2 -- esphome/components/bme680/bme680.h | 1 - esphome/components/bme680_bsec/bme680_bsec.cpp | 2 -- esphome/components/bme680_bsec/bme680_bsec.h | 1 - esphome/components/bme68x_bsec2/bme68x_bsec2.cpp | 2 -- esphome/components/bme68x_bsec2/bme68x_bsec2.h | 1 - esphome/components/bmi160/bmi160.cpp | 1 - esphome/components/bmi160/bmi160.h | 2 -- esphome/components/bmp085/bmp085.cpp | 1 - esphome/components/bmp085/bmp085.h | 2 -- esphome/components/bmp280_base/bmp280_base.cpp | 1 - esphome/components/bmp280_base/bmp280_base.h | 1 - esphome/components/bmp3xx_base/bmp3xx_base.cpp | 1 - esphome/components/bmp3xx_base/bmp3xx_base.h | 1 - esphome/components/cd74hc4067/cd74hc4067.cpp | 2 -- esphome/components/cd74hc4067/cd74hc4067.h | 1 - esphome/components/cm1106/cm1106.h | 2 -- esphome/components/combination/combination.h | 2 -- esphome/components/cse7761/cse7761.cpp | 2 -- esphome/components/cse7761/cse7761.h | 1 - esphome/components/cse7766/cse7766.cpp | 1 - esphome/components/cse7766/cse7766.h | 1 - esphome/components/current_based/current_based_cover.cpp | 1 - esphome/components/current_based/current_based_cover.h | 1 - esphome/components/daly_bms/daly_bms.cpp | 2 -- esphome/components/daly_bms/daly_bms.h | 1 - esphome/components/dht/dht.cpp | 2 -- esphome/components/dht/dht.h | 2 -- esphome/components/dht12/dht12.cpp | 2 +- esphome/components/dht12/dht12.h | 1 - esphome/components/dps310/dps310.cpp | 2 -- esphome/components/dps310/dps310.h | 1 - esphome/components/ds1307/ds1307.cpp | 2 -- esphome/components/ds1307/ds1307.h | 1 - esphome/components/duty_cycle/duty_cycle_sensor.cpp | 2 -- esphome/components/duty_cycle/duty_cycle_sensor.h | 1 - esphome/components/ee895/ee895.cpp | 2 -- esphome/components/ee895/ee895.h | 1 - esphome/components/emc2101/sensor/emc2101_sensor.cpp | 2 -- esphome/components/emc2101/sensor/emc2101_sensor.h | 2 -- esphome/components/endstop/endstop_cover.cpp | 2 +- esphome/components/endstop/endstop_cover.h | 1 - esphome/components/ens210/ens210.cpp | 2 -- esphome/components/ens210/ens210.h | 1 - esphome/components/esp32_camera/esp32_camera.cpp | 2 -- esphome/components/esp32_camera/esp32_camera.h | 1 - esphome/components/esp32_touch/esp32_touch.h | 1 - esphome/components/gdk101/gdk101.cpp | 2 -- esphome/components/gdk101/gdk101.h | 1 - esphome/components/gp8403/gp8403.h | 1 - esphome/components/hc8/hc8.cpp | 2 -- esphome/components/hc8/hc8.h | 2 -- esphome/components/hdc1080/hdc1080.h | 2 -- esphome/components/hlw8012/hlw8012.cpp | 1 - esphome/components/hlw8012/hlw8012.h | 1 - esphome/components/hm3301/hm3301.cpp | 2 -- esphome/components/hm3301/hm3301.h | 1 - esphome/components/hmc5883l/hmc5883l.cpp | 1 - esphome/components/hmc5883l/hmc5883l.h | 1 - .../components/homeassistant/time/homeassistant_time.cpp | 2 -- esphome/components/homeassistant/time/homeassistant_time.h | 1 - esphome/components/honeywell_hih_i2c/honeywell_hih.cpp | 2 -- esphome/components/honeywell_hih_i2c/honeywell_hih.h | 1 - esphome/components/hte501/hte501.cpp | 1 - esphome/components/hte501/hte501.h | 1 - esphome/components/htu21d/htu21d.cpp | 2 -- esphome/components/htu21d/htu21d.h | 2 -- esphome/components/htu31d/htu31d.cpp | 6 ------ esphome/components/htu31d/htu31d.h | 2 -- esphome/components/hx711/hx711.cpp | 1 - esphome/components/hx711/hx711.h | 1 - esphome/components/hydreon_rgxx/hydreon_rgxx.cpp | 2 -- esphome/components/hydreon_rgxx/hydreon_rgxx.h | 2 -- esphome/components/hyt271/hyt271.cpp | 2 -- esphome/components/hyt271/hyt271.h | 2 -- esphome/components/ina219/ina219.cpp | 2 -- esphome/components/ina219/ina219.h | 1 - esphome/components/ina226/ina226.cpp | 2 -- esphome/components/ina226/ina226.h | 1 - esphome/components/ina2xx_base/ina2xx_base.cpp | 2 -- esphome/components/ina2xx_base/ina2xx_base.h | 1 - esphome/components/ina3221/ina3221.cpp | 1 - esphome/components/ina3221/ina3221.h | 1 - esphome/components/kamstrup_kmp/kamstrup_kmp.cpp | 2 -- esphome/components/kamstrup_kmp/kamstrup_kmp.h | 1 - esphome/components/kmeteriso/kmeteriso.cpp | 2 -- esphome/components/kmeteriso/kmeteriso.h | 1 - esphome/components/m5stack_8angle/m5stack_8angle.cpp | 2 -- esphome/components/m5stack_8angle/m5stack_8angle.h | 1 - esphome/components/max17043/max17043.cpp | 2 -- esphome/components/max17043/max17043.h | 1 - esphome/components/max31855/max31855.cpp | 1 - esphome/components/max31855/max31855.h | 1 - esphome/components/max31856/max31856.cpp | 2 -- esphome/components/max31856/max31856.h | 1 - esphome/components/max31865/max31865.cpp | 2 -- esphome/components/max31865/max31865.h | 1 - esphome/components/max44009/max44009.cpp | 2 -- esphome/components/max44009/max44009.h | 1 - esphome/components/max6675/max6675.cpp | 1 - esphome/components/max6675/max6675.h | 1 - esphome/components/mcp3008/sensor/mcp3008_sensor.cpp | 2 -- esphome/components/mcp3008/sensor/mcp3008_sensor.h | 1 - esphome/components/mcp3204/sensor/mcp3204_sensor.cpp | 2 -- esphome/components/mcp3204/sensor/mcp3204_sensor.h | 1 - esphome/components/mcp9808/mcp9808.cpp | 1 - esphome/components/mcp9808/mcp9808.h | 1 - esphome/components/mhz19/mhz19.cpp | 2 -- esphome/components/mhz19/mhz19.h | 2 -- esphome/components/mics_4514/mics_4514.cpp | 1 - esphome/components/mics_4514/mics_4514.h | 1 - esphome/components/mlx90393/sensor_mlx90393.cpp | 2 -- esphome/components/mlx90393/sensor_mlx90393.h | 1 - esphome/components/mlx90614/mlx90614.cpp | 2 -- esphome/components/mlx90614/mlx90614.h | 1 - esphome/components/mmc5603/mmc5603.cpp | 2 -- esphome/components/mmc5603/mmc5603.h | 1 - esphome/components/mmc5983/mmc5983.cpp | 2 -- esphome/components/mmc5983/mmc5983.h | 1 - esphome/components/mpu6050/mpu6050.cpp | 1 - esphome/components/mpu6050/mpu6050.h | 2 -- esphome/components/mpu6886/mpu6886.cpp | 2 -- esphome/components/mpu6886/mpu6886.h | 2 -- esphome/components/ms5611/ms5611.cpp | 1 - esphome/components/ms5611/ms5611.h | 1 - esphome/components/msa3xx/msa3xx.cpp | 1 - esphome/components/msa3xx/msa3xx.h | 2 -- esphome/components/nau7802/nau7802.cpp | 2 -- esphome/components/nau7802/nau7802.h | 1 - esphome/components/nextion/nextion.cpp | 1 - esphome/components/nextion/nextion.h | 1 - esphome/components/npi19/npi19.cpp | 2 -- esphome/components/npi19/npi19.h | 1 - esphome/components/ntc/ntc.cpp | 1 - esphome/components/ntc/ntc.h | 1 - esphome/components/opt3001/opt3001.cpp | 2 -- esphome/components/opt3001/opt3001.h | 1 - esphome/components/pcf85063/pcf85063.cpp | 2 -- esphome/components/pcf85063/pcf85063.h | 1 - esphome/components/pcf8563/pcf8563.cpp | 2 -- esphome/components/pcf8563/pcf8563.h | 1 - esphome/components/pm1006/pm1006.cpp | 2 -- esphome/components/pm1006/pm1006.h | 2 -- esphome/components/pm2005/pm2005.h | 2 -- esphome/components/pmwcs3/pmwcs3.cpp | 2 -- esphome/components/pmwcs3/pmwcs3.h | 1 - esphome/components/pn532/pn532.cpp | 2 -- esphome/components/pn532/pn532.h | 1 - esphome/components/pulse_meter/pulse_meter_sensor.cpp | 2 -- esphome/components/pulse_meter/pulse_meter_sensor.h | 1 - esphome/components/pylontech/pylontech.cpp | 2 -- esphome/components/pylontech/pylontech.h | 2 -- esphome/components/qmc5883l/qmc5883l.cpp | 2 -- esphome/components/qmc5883l/qmc5883l.h | 1 - esphome/components/rd03d/rd03d.h | 1 - esphome/components/resampler/speaker/resampler_speaker.h | 1 - esphome/components/rotary_encoder/rotary_encoder.cpp | 1 - esphome/components/rotary_encoder/rotary_encoder.h | 2 -- esphome/components/rx8130/rx8130.h | 2 -- esphome/components/sdp3x/sdp3x.cpp | 2 -- esphome/components/sdp3x/sdp3x.h | 1 - esphome/components/sds011/sds011.cpp | 2 -- esphome/components/sds011/sds011.h | 2 -- esphome/components/sht3xd/sht3xd.cpp | 2 -- esphome/components/sht3xd/sht3xd.h | 1 - esphome/components/shtcx/shtcx.cpp | 2 -- esphome/components/shtcx/shtcx.h | 1 - esphome/components/smt100/smt100.cpp | 2 -- esphome/components/smt100/smt100.h | 2 -- esphome/components/sonoff_d1/sonoff_d1.h | 1 - esphome/components/spi_device/spi_device.cpp | 2 -- esphome/components/spi_device/spi_device.h | 2 -- esphome/components/sts3x/sts3x.cpp | 2 +- esphome/components/sts3x/sts3x.h | 1 - esphome/components/sy6970/sy6970.h | 1 - esphome/components/t6615/t6615.cpp | 1 - esphome/components/t6615/t6615.h | 2 -- esphome/components/tc74/tc74.cpp | 2 -- esphome/components/tc74/tc74.h | 2 -- esphome/components/tcs34725/tcs34725.cpp | 1 - esphome/components/tcs34725/tcs34725.h | 1 - esphome/components/tee501/tee501.cpp | 1 - esphome/components/tee501/tee501.h | 1 - esphome/components/tem3200/tem3200.cpp | 2 -- esphome/components/tem3200/tem3200.h | 1 - esphome/components/time_based/time_based_cover.cpp | 2 +- esphome/components/time_based/time_based_cover.h | 1 - esphome/components/tmp102/tmp102.cpp | 2 -- esphome/components/tmp102/tmp102.h | 2 -- esphome/components/tmp117/tmp117.cpp | 2 +- esphome/components/tmp117/tmp117.h | 1 - esphome/components/tsl2561/tsl2561.cpp | 2 +- esphome/components/tsl2561/tsl2561.h | 1 - esphome/components/tsl2591/tsl2591.cpp | 2 -- esphome/components/tsl2591/tsl2591.h | 2 -- esphome/components/tx20/tx20.cpp | 2 -- esphome/components/tx20/tx20.h | 1 - esphome/components/ultrasonic/ultrasonic_sensor.h | 2 -- esphome/components/version/version_text_sensor.cpp | 1 - esphome/components/version/version_text_sensor.h | 1 - esphome/components/wts01/wts01.h | 1 - 228 files changed, 6 insertions(+), 337 deletions(-) diff --git a/esphome/components/absolute_humidity/absolute_humidity.cpp b/esphome/components/absolute_humidity/absolute_humidity.cpp index b13fcd519a..9c66531d05 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.cpp +++ b/esphome/components/absolute_humidity/absolute_humidity.cpp @@ -45,8 +45,6 @@ void AbsoluteHumidityComponent::dump_config() { this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str()); } -float AbsoluteHumidityComponent::get_setup_priority() const { return setup_priority::DATA; } - void AbsoluteHumidityComponent::loop() { if (!this->next_update_) { return; diff --git a/esphome/components/absolute_humidity/absolute_humidity.h b/esphome/components/absolute_humidity/absolute_humidity.h index 9f3b9eab8b..71feee2c42 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.h +++ b/esphome/components/absolute_humidity/absolute_humidity.h @@ -24,7 +24,6 @@ class AbsoluteHumidityComponent : public sensor::Sensor, public Component { void setup() override; void dump_config() override; - float get_setup_priority() const override; void loop() override; protected: diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index 526dd57fd5..91cf4eaafc 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -68,11 +68,6 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage /// This method is called during the ESPHome setup process to log the configuration. void dump_config() override; - /// Return the setup priority for this component. - /// Components with higher priority are initialized earlier during setup. - /// @return A float representing the setup priority. - float get_setup_priority() const override; - #ifdef USE_ZEPHYR /// Set the ADC channel to be used by the ADC sensor. /// @param channel Pointer to an adc_dt_spec structure representing the ADC channel. diff --git a/esphome/components/adc/adc_sensor_common.cpp b/esphome/components/adc/adc_sensor_common.cpp index 748c8634b7..c779fd5893 100644 --- a/esphome/components/adc/adc_sensor_common.cpp +++ b/esphome/components/adc/adc_sensor_common.cpp @@ -79,7 +79,5 @@ void ADCSensor::set_sample_count(uint8_t sample_count) { void ADCSensor::set_sampling_mode(SamplingMode sampling_mode) { this->sampling_mode_ = sampling_mode; } -float ADCSensor::get_setup_priority() const { return setup_priority::DATA; } - } // namespace adc } // namespace esphome diff --git a/esphome/components/adc128s102/sensor/adc128s102_sensor.cpp b/esphome/components/adc128s102/sensor/adc128s102_sensor.cpp index 03ce31d3cb..800b2d5261 100644 --- a/esphome/components/adc128s102/sensor/adc128s102_sensor.cpp +++ b/esphome/components/adc128s102/sensor/adc128s102_sensor.cpp @@ -9,8 +9,6 @@ static const char *const TAG = "adc128s102.sensor"; ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {} -float ADC128S102Sensor::get_setup_priority() const { return setup_priority::DATA; } - void ADC128S102Sensor::dump_config() { LOG_SENSOR("", "ADC128S102 Sensor", this); ESP_LOGCONFIG(TAG, " Pin: %u", this->channel_); diff --git a/esphome/components/adc128s102/sensor/adc128s102_sensor.h b/esphome/components/adc128s102/sensor/adc128s102_sensor.h index 234500c2f4..5e6fc74e9c 100644 --- a/esphome/components/adc128s102/sensor/adc128s102_sensor.h +++ b/esphome/components/adc128s102/sensor/adc128s102_sensor.h @@ -19,7 +19,6 @@ class ADC128S102Sensor : public PollingComponent, void update() override; void dump_config() override; - float get_setup_priority() const override; float sample() override; protected: diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 03d9d9cd9e..1b1f8335cc 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -150,8 +150,6 @@ void AHT10Component::update() { this->restart_read_(); } -float AHT10Component::get_setup_priority() const { return setup_priority::DATA; } - void AHT10Component::dump_config() { ESP_LOGCONFIG(TAG, "AHT10:"); LOG_I2C_DEVICE(this); diff --git a/esphome/components/aht10/aht10.h b/esphome/components/aht10/aht10.h index a3320c77e0..ce9cd963ad 100644 --- a/esphome/components/aht10/aht10.h +++ b/esphome/components/aht10/aht10.h @@ -16,7 +16,6 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void update() override; void dump_config() override; - float get_setup_priority() const override; void set_variant(AHT10Variant variant) { this->variant_ = variant; } void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/am2315c/am2315c.cpp b/esphome/components/am2315c/am2315c.cpp index b20a8c6cbb..1390b74975 100644 --- a/esphome/components/am2315c/am2315c.cpp +++ b/esphome/components/am2315c/am2315c.cpp @@ -176,7 +176,5 @@ void AM2315C::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float AM2315C::get_setup_priority() const { return setup_priority::DATA; } - } // namespace am2315c } // namespace esphome diff --git a/esphome/components/am2315c/am2315c.h b/esphome/components/am2315c/am2315c.h index c8d01beeaa..d7baf01cae 100644 --- a/esphome/components/am2315c/am2315c.h +++ b/esphome/components/am2315c/am2315c.h @@ -33,7 +33,6 @@ class AM2315C : public PollingComponent, public i2c::I2CDevice { void dump_config() override; void update() override; void setup() override; - float get_setup_priority() const override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } diff --git a/esphome/components/am2320/am2320.cpp b/esphome/components/am2320/am2320.cpp index 055be2aeee..7fef3bb3a6 100644 --- a/esphome/components/am2320/am2320.cpp +++ b/esphome/components/am2320/am2320.cpp @@ -51,7 +51,6 @@ void AM2320Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float AM2320Component::get_setup_priority() const { return setup_priority::DATA; } bool AM2320Component::read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion) { if (!this->write_bytes(a_register, data, 2)) { diff --git a/esphome/components/am2320/am2320.h b/esphome/components/am2320/am2320.h index da1e87cf65..708dbb632e 100644 --- a/esphome/components/am2320/am2320.h +++ b/esphome/components/am2320/am2320.h @@ -11,7 +11,6 @@ class AM2320Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/apds9960/apds9960.cpp b/esphome/components/apds9960/apds9960.cpp index 93038d3160..260de82d14 100644 --- a/esphome/components/apds9960/apds9960.cpp +++ b/esphome/components/apds9960/apds9960.cpp @@ -384,7 +384,6 @@ void APDS9960::process_dataset_(int up, int down, int left, int right) { } } } -float APDS9960::get_setup_priority() const { return setup_priority::DATA; } bool APDS9960::is_proximity_enabled_() const { return #ifdef USE_SENSOR diff --git a/esphome/components/apds9960/apds9960.h b/esphome/components/apds9960/apds9960.h index 2a0fbb5c19..4574b70a42 100644 --- a/esphome/components/apds9960/apds9960.h +++ b/esphome/components/apds9960/apds9960.h @@ -32,7 +32,6 @@ class APDS9960 : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void loop() override; diff --git a/esphome/components/aqi/aqi_sensor.h b/esphome/components/aqi/aqi_sensor.h index a990f815fe..2e526ca825 100644 --- a/esphome/components/aqi/aqi_sensor.h +++ b/esphome/components/aqi/aqi_sensor.h @@ -10,7 +10,6 @@ class AQISensor : public sensor::Sensor, public Component { public: void setup() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } void set_pm_2_5_sensor(sensor::Sensor *sensor) { this->pm_2_5_sensor_ = sensor; } void set_pm_10_0_sensor(sensor::Sensor *sensor) { this->pm_10_0_sensor_ = sensor; } diff --git a/esphome/components/as3935/as3935.cpp b/esphome/components/as3935/as3935.cpp index 93a0bff5b3..dd0ab714f7 100644 --- a/esphome/components/as3935/as3935.cpp +++ b/esphome/components/as3935/as3935.cpp @@ -41,8 +41,6 @@ void AS3935Component::dump_config() { #endif } -float AS3935Component::get_setup_priority() const { return setup_priority::DATA; } - void AS3935Component::loop() { if (!this->irq_pin_->digital_read()) return; diff --git a/esphome/components/as3935/as3935.h b/esphome/components/as3935/as3935.h index dc590c268e..5dff1cb0ae 100644 --- a/esphome/components/as3935/as3935.h +++ b/esphome/components/as3935/as3935.h @@ -74,7 +74,6 @@ class AS3935Component : public Component { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void loop() override; void set_irq_pin(GPIOPin *irq_pin) { irq_pin_ = irq_pin; } diff --git a/esphome/components/as5600/sensor/as5600_sensor.cpp b/esphome/components/as5600/sensor/as5600_sensor.cpp index feb8f6cebf..1c0f4bad2c 100644 --- a/esphome/components/as5600/sensor/as5600_sensor.cpp +++ b/esphome/components/as5600/sensor/as5600_sensor.cpp @@ -22,8 +22,6 @@ static const uint8_t REGISTER_STATUS = 0x0B; // 8 bytes / R static const uint8_t REGISTER_AGC = 0x1A; // 8 bytes / R static const uint8_t REGISTER_MAGNITUDE = 0x1B; // 16 bytes / R -float AS5600Sensor::get_setup_priority() const { return setup_priority::DATA; } - void AS5600Sensor::dump_config() { LOG_SENSOR("", "AS5600 Sensor", this); ESP_LOGCONFIG(TAG, " Out of Range Mode: %u", this->out_of_range_mode_); diff --git a/esphome/components/as5600/sensor/as5600_sensor.h b/esphome/components/as5600/sensor/as5600_sensor.h index 0af9b01ae5..d471be49b5 100644 --- a/esphome/components/as5600/sensor/as5600_sensor.h +++ b/esphome/components/as5600/sensor/as5600_sensor.h @@ -14,7 +14,6 @@ class AS5600Sensor : public PollingComponent, public Parented, public: void update() override; void dump_config() override; - float get_setup_priority() const override; void set_angle_sensor(sensor::Sensor *angle_sensor) { this->angle_sensor_ = angle_sensor; } void set_raw_angle_sensor(sensor::Sensor *raw_angle_sensor) { this->raw_angle_sensor_ = raw_angle_sensor; } diff --git a/esphome/components/as7341/as7341.cpp b/esphome/components/as7341/as7341.cpp index 893eaa850f..1e78d814c8 100644 --- a/esphome/components/as7341/as7341.cpp +++ b/esphome/components/as7341/as7341.cpp @@ -58,8 +58,6 @@ void AS7341Component::dump_config() { LOG_SENSOR(" ", "NIR", this->nir_); } -float AS7341Component::get_setup_priority() const { return setup_priority::DATA; } - void AS7341Component::update() { this->read_channels(this->channel_readings_); diff --git a/esphome/components/as7341/as7341.h b/esphome/components/as7341/as7341.h index aed7996cef..3ede9d4aa4 100644 --- a/esphome/components/as7341/as7341.h +++ b/esphome/components/as7341/as7341.h @@ -78,7 +78,6 @@ class AS7341Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_f1_sensor(sensor::Sensor *f1_sensor) { this->f1_ = f1_sensor; } diff --git a/esphome/components/atm90e26/atm90e26.cpp b/esphome/components/atm90e26/atm90e26.cpp index cadc06ac6b..2203dd0d71 100644 --- a/esphome/components/atm90e26/atm90e26.cpp +++ b/esphome/components/atm90e26/atm90e26.cpp @@ -146,7 +146,6 @@ void ATM90E26Component::dump_config() { LOG_SENSOR(" ", "Active Reverse Energy A", this->reverse_active_energy_sensor_); LOG_SENSOR(" ", "Frequency", this->freq_sensor_); } -float ATM90E26Component::get_setup_priority() const { return setup_priority::DATA; } uint16_t ATM90E26Component::read16_(uint8_t a_register) { uint8_t data[2]; diff --git a/esphome/components/atm90e26/atm90e26.h b/esphome/components/atm90e26/atm90e26.h index 3c098d7e91..d15a53ea43 100644 --- a/esphome/components/atm90e26/atm90e26.h +++ b/esphome/components/atm90e26/atm90e26.h @@ -13,7 +13,6 @@ class ATM90E26Component : public PollingComponent, public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_voltage_sensor(sensor::Sensor *obj) { this->voltage_sensor_ = obj; } diff --git a/esphome/components/bh1750/bh1750.cpp b/esphome/components/bh1750/bh1750.cpp index bd7c667c25..045fb7cf45 100644 --- a/esphome/components/bh1750/bh1750.cpp +++ b/esphome/components/bh1750/bh1750.cpp @@ -265,6 +265,4 @@ void BH1750Sensor::fail_and_reset_() { this->state_ = IDLE; } -float BH1750Sensor::get_setup_priority() const { return setup_priority::DATA; } - } // namespace esphome::bh1750 diff --git a/esphome/components/bh1750/bh1750.h b/esphome/components/bh1750/bh1750.h index 0460427954..39dbd1d6a9 100644 --- a/esphome/components/bh1750/bh1750.h +++ b/esphome/components/bh1750/bh1750.h @@ -21,7 +21,6 @@ class BH1750Sensor : public sensor::Sensor, public PollingComponent, public i2c: void dump_config() override; void update() override; void loop() override; - float get_setup_priority() const override; protected: // State machine states diff --git a/esphome/components/bme280_base/bme280_base.cpp b/esphome/components/bme280_base/bme280_base.cpp index c5d4c9c0a5..f396888fd1 100644 --- a/esphome/components/bme280_base/bme280_base.cpp +++ b/esphome/components/bme280_base/bme280_base.cpp @@ -199,7 +199,6 @@ void BME280Component::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); ESP_LOGCONFIG(TAG, " Oversampling: %s", oversampling_to_str(this->humidity_oversampling_)); } -float BME280Component::get_setup_priority() const { return setup_priority::DATA; } inline uint8_t oversampling_to_time(BME280Oversampling over_sampling) { return (1 << uint8_t(over_sampling)) >> 1; } diff --git a/esphome/components/bme280_base/bme280_base.h b/esphome/components/bme280_base/bme280_base.h index 0f55ad0101..00781d05b2 100644 --- a/esphome/components/bme280_base/bme280_base.h +++ b/esphome/components/bme280_base/bme280_base.h @@ -76,7 +76,6 @@ class BME280Component : public PollingComponent { // (In most use cases you won't need these) void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/bme680/bme680.cpp b/esphome/components/bme680/bme680.cpp index 16435ccfee..5e52c84b3d 100644 --- a/esphome/components/bme680/bme680.cpp +++ b/esphome/components/bme680/bme680.cpp @@ -233,8 +233,6 @@ void BME680Component::dump_config() { } } -float BME680Component::get_setup_priority() const { return setup_priority::DATA; } - void BME680Component::update() { uint8_t meas_control = 0; // No need to fetch, we're setting all fields meas_control |= (this->temperature_oversampling_ & 0b111) << 5; diff --git a/esphome/components/bme680/bme680.h b/esphome/components/bme680/bme680.h index cfa7aaca20..d48a42823b 100644 --- a/esphome/components/bme680/bme680.h +++ b/esphome/components/bme680/bme680.h @@ -99,7 +99,6 @@ class BME680Component : public PollingComponent, public i2c::I2CDevice { // (In most use cases you won't need these) void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/bme680_bsec/bme680_bsec.cpp b/esphome/components/bme680_bsec/bme680_bsec.cpp index d969c8fd98..392d071b31 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.cpp +++ b/esphome/components/bme680_bsec/bme680_bsec.cpp @@ -181,8 +181,6 @@ void BME680BSECComponent::dump_config() { LOG_SENSOR(" ", "Breath VOC Equivalent", this->breath_voc_equivalent_sensor_); } -float BME680BSECComponent::get_setup_priority() const { return setup_priority::DATA; } - void BME680BSECComponent::loop() { this->run_(); diff --git a/esphome/components/bme680_bsec/bme680_bsec.h b/esphome/components/bme680_bsec/bme680_bsec.h index e52dbe964b..ec919f31df 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.h +++ b/esphome/components/bme680_bsec/bme680_bsec.h @@ -64,7 +64,6 @@ class BME680BSECComponent : public Component, public i2c::I2CDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override; void loop() override; protected: diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index 91383c8d45..1a42c9d54b 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -106,8 +106,6 @@ void BME68xBSEC2Component::dump_config() { #endif } -float BME68xBSEC2Component::get_setup_priority() const { return setup_priority::DATA; } - void BME68xBSEC2Component::loop() { this->run_(); diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.h b/esphome/components/bme68x_bsec2/bme68x_bsec2.h index 86d3e5dfbf..8f4d8f61c2 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.h +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.h @@ -48,7 +48,6 @@ class BME68xBSEC2Component : public Component { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void loop() override; void set_algorithm_output(AlgorithmOutput algorithm_output) { this->algorithm_output_ = algorithm_output; } diff --git a/esphome/components/bmi160/bmi160.cpp b/esphome/components/bmi160/bmi160.cpp index 4fcc3edb82..1e8c91d7b7 100644 --- a/esphome/components/bmi160/bmi160.cpp +++ b/esphome/components/bmi160/bmi160.cpp @@ -263,7 +263,6 @@ void BMI160Component::update() { this->status_clear_warning(); } -float BMI160Component::get_setup_priority() const { return setup_priority::DATA; } } // namespace bmi160 } // namespace esphome diff --git a/esphome/components/bmi160/bmi160.h b/esphome/components/bmi160/bmi160.h index 47691a4de9..16cab69733 100644 --- a/esphome/components/bmi160/bmi160.h +++ b/esphome/components/bmi160/bmi160.h @@ -14,8 +14,6 @@ class BMI160Component : public PollingComponent, public i2c::I2CDevice { void update() override; - float get_setup_priority() const override; - void set_accel_x_sensor(sensor::Sensor *accel_x_sensor) { accel_x_sensor_ = accel_x_sensor; } void set_accel_y_sensor(sensor::Sensor *accel_y_sensor) { accel_y_sensor_ = accel_y_sensor; } void set_accel_z_sensor(sensor::Sensor *accel_z_sensor) { accel_z_sensor_ = accel_z_sensor; } diff --git a/esphome/components/bmp085/bmp085.cpp b/esphome/components/bmp085/bmp085.cpp index 657da34f9b..9a383b2654 100644 --- a/esphome/components/bmp085/bmp085.cpp +++ b/esphome/components/bmp085/bmp085.cpp @@ -131,7 +131,6 @@ bool BMP085Component::set_mode_(uint8_t mode) { ESP_LOGV(TAG, "Setting mode to 0x%02X", mode); return this->write_byte(BMP085_REGISTER_CONTROL, mode); } -float BMP085Component::get_setup_priority() const { return setup_priority::DATA; } } // namespace bmp085 } // namespace esphome diff --git a/esphome/components/bmp085/bmp085.h b/esphome/components/bmp085/bmp085.h index d84b4d43ef..c7315827e0 100644 --- a/esphome/components/bmp085/bmp085.h +++ b/esphome/components/bmp085/bmp085.h @@ -18,8 +18,6 @@ class BMP085Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override; - protected: struct CalibrationData { int16_t ac1, ac2, ac3; diff --git a/esphome/components/bmp280_base/bmp280_base.cpp b/esphome/components/bmp280_base/bmp280_base.cpp index 728eead521..de685e7c27 100644 --- a/esphome/components/bmp280_base/bmp280_base.cpp +++ b/esphome/components/bmp280_base/bmp280_base.cpp @@ -148,7 +148,6 @@ void BMP280Component::dump_config() { LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); ESP_LOGCONFIG(TAG, " Oversampling: %s", oversampling_to_str(this->pressure_oversampling_)); } -float BMP280Component::get_setup_priority() const { return setup_priority::DATA; } inline uint8_t oversampling_to_time(BMP280Oversampling over_sampling) { return (1 << uint8_t(over_sampling)) >> 1; } diff --git a/esphome/components/bmp280_base/bmp280_base.h b/esphome/components/bmp280_base/bmp280_base.h index a47a794e96..836eafaf8b 100644 --- a/esphome/components/bmp280_base/bmp280_base.h +++ b/esphome/components/bmp280_base/bmp280_base.h @@ -64,7 +64,6 @@ class BMP280Component : public PollingComponent { void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/bmp3xx_base/bmp3xx_base.cpp b/esphome/components/bmp3xx_base/bmp3xx_base.cpp index acc28d4e85..d7d9972170 100644 --- a/esphome/components/bmp3xx_base/bmp3xx_base.cpp +++ b/esphome/components/bmp3xx_base/bmp3xx_base.cpp @@ -179,7 +179,6 @@ void BMP3XXComponent::dump_config() { ESP_LOGCONFIG(TAG, " Oversampling: %s", LOG_STR_ARG(oversampling_to_str(this->pressure_oversampling_))); } } -float BMP3XXComponent::get_setup_priority() const { return setup_priority::DATA; } inline uint8_t oversampling_to_time(Oversampling over_sampling) { return (1 << uint8_t(over_sampling)); } diff --git a/esphome/components/bmp3xx_base/bmp3xx_base.h b/esphome/components/bmp3xx_base/bmp3xx_base.h index 50f92e04c1..8d2312231b 100644 --- a/esphome/components/bmp3xx_base/bmp3xx_base.h +++ b/esphome/components/bmp3xx_base/bmp3xx_base.h @@ -73,7 +73,6 @@ class BMP3XXComponent : public PollingComponent { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/cd74hc4067/cd74hc4067.cpp b/esphome/components/cd74hc4067/cd74hc4067.cpp index 4293d7af07..302c83d7d3 100644 --- a/esphome/components/cd74hc4067/cd74hc4067.cpp +++ b/esphome/components/cd74hc4067/cd74hc4067.cpp @@ -7,8 +7,6 @@ namespace cd74hc4067 { static const char *const TAG = "cd74hc4067"; -float CD74HC4067Component::get_setup_priority() const { return setup_priority::DATA; } - void CD74HC4067Component::setup() { this->pin_s0_->setup(); this->pin_s1_->setup(); diff --git a/esphome/components/cd74hc4067/cd74hc4067.h b/esphome/components/cd74hc4067/cd74hc4067.h index 6193513575..76ebc1ebbe 100644 --- a/esphome/components/cd74hc4067/cd74hc4067.h +++ b/esphome/components/cd74hc4067/cd74hc4067.h @@ -13,7 +13,6 @@ class CD74HC4067Component : public Component { /// Set up the internal sensor array. void setup() override; void dump_config() override; - float get_setup_priority() const override; /// setting pin active by setting the right combination of the four multiplexer input pins void activate_pin(uint8_t pin); diff --git a/esphome/components/cm1106/cm1106.h b/esphome/components/cm1106/cm1106.h index ad089bbe7d..8c33e56457 100644 --- a/esphome/components/cm1106/cm1106.h +++ b/esphome/components/cm1106/cm1106.h @@ -10,8 +10,6 @@ namespace cm1106 { class CM1106Component : public PollingComponent, public uart::UARTDevice { public: - float get_setup_priority() const override { return esphome::setup_priority::DATA; } - void setup() override; void update() override; void dump_config() override; diff --git a/esphome/components/combination/combination.h b/esphome/components/combination/combination.h index 901aeaf259..fb5e156da9 100644 --- a/esphome/components/combination/combination.h +++ b/esphome/components/combination/combination.h @@ -10,8 +10,6 @@ namespace combination { class CombinationComponent : public Component, public sensor::Sensor { public: - float get_setup_priority() const override { return esphome::setup_priority::DATA; } - /// @brief Logs all source sensor's names virtual void log_source_sensors() = 0; diff --git a/esphome/components/cse7761/cse7761.cpp b/esphome/components/cse7761/cse7761.cpp index 482636dd81..7c5ee833a4 100644 --- a/esphome/components/cse7761/cse7761.cpp +++ b/esphome/components/cse7761/cse7761.cpp @@ -62,8 +62,6 @@ void CSE7761Component::dump_config() { this->check_uart_settings(38400, 1, uart::UART_CONFIG_PARITY_EVEN, 8); } -float CSE7761Component::get_setup_priority() const { return setup_priority::DATA; } - void CSE7761Component::update() { if (this->data_.ready) { this->get_data_(); diff --git a/esphome/components/cse7761/cse7761.h b/esphome/components/cse7761/cse7761.h index 71846cdcab..289c5e7e19 100644 --- a/esphome/components/cse7761/cse7761.h +++ b/esphome/components/cse7761/cse7761.h @@ -28,7 +28,6 @@ class CSE7761Component : public PollingComponent, public uart::UARTDevice { void set_current_2_sensor(sensor::Sensor *current_sensor_2) { current_sensor_2_ = current_sensor_2; } void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index c36e57c929..df4872deac 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -37,7 +37,6 @@ void CSE7766Component::loop() { this->raw_data_index_ = (this->raw_data_index_ + 1) % 24; } } -float CSE7766Component::get_setup_priority() const { return setup_priority::DATA; } bool CSE7766Component::check_byte_() { uint8_t index = this->raw_data_index_; diff --git a/esphome/components/cse7766/cse7766.h b/esphome/components/cse7766/cse7766.h index 8902eafe3c..efddccd3c5 100644 --- a/esphome/components/cse7766/cse7766.h +++ b/esphome/components/cse7766/cse7766.h @@ -23,7 +23,6 @@ class CSE7766Component : public Component, public uart::UARTDevice { void set_power_factor_sensor(sensor::Sensor *power_factor_sensor) { power_factor_sensor_ = power_factor_sensor; } void loop() override; - float get_setup_priority() const override; void dump_config() override; protected: diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index 402cf9fee7..5dfaeeff39 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -159,7 +159,6 @@ void CurrentBasedCover::dump_config() { this->start_sensing_delay_ / 1e3f, YESNO(this->malfunction_detection_)); } -float CurrentBasedCover::get_setup_priority() const { return setup_priority::DATA; } void CurrentBasedCover::stop_prev_trigger_() { if (this->prev_command_trigger_ != nullptr) { this->prev_command_trigger_->stop_action(); diff --git a/esphome/components/current_based/current_based_cover.h b/esphome/components/current_based/current_based_cover.h index f7993f1550..76bd85cdf7 100644 --- a/esphome/components/current_based/current_based_cover.h +++ b/esphome/components/current_based/current_based_cover.h @@ -14,7 +14,6 @@ class CurrentBasedCover : public cover::Cover, public Component { void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override; Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } diff --git a/esphome/components/daly_bms/daly_bms.cpp b/esphome/components/daly_bms/daly_bms.cpp index 2d270cc56e..90ccee78f8 100644 --- a/esphome/components/daly_bms/daly_bms.cpp +++ b/esphome/components/daly_bms/daly_bms.cpp @@ -104,8 +104,6 @@ void DalyBmsComponent::loop() { } } -float DalyBmsComponent::get_setup_priority() const { return setup_priority::DATA; } - void DalyBmsComponent::request_data_(uint8_t data_id) { uint8_t request_message[DALY_FRAME_SIZE]; diff --git a/esphome/components/daly_bms/daly_bms.h b/esphome/components/daly_bms/daly_bms.h index e6d476bcdd..1983ba0ef1 100644 --- a/esphome/components/daly_bms/daly_bms.h +++ b/esphome/components/daly_bms/daly_bms.h @@ -72,7 +72,6 @@ class DalyBmsComponent : public PollingComponent, public uart::UARTDevice { void update() override; void loop() override; - float get_setup_priority() const override; void set_address(uint8_t address) { this->addr_ = address; } protected: diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index 276ea24717..fef247f168 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -63,8 +63,6 @@ void DHT::update() { } } -float DHT::get_setup_priority() const { return setup_priority::DATA; } - void DHT::set_dht_model(DHTModel model) { this->model_ = model; this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT; diff --git a/esphome/components/dht/dht.h b/esphome/components/dht/dht.h index 9047dd2c96..4671ee6f27 100644 --- a/esphome/components/dht/dht.h +++ b/esphome/components/dht/dht.h @@ -51,8 +51,6 @@ class DHT : public PollingComponent { void dump_config() override; /// Update sensor values and push them to the frontend. void update() override; - /// HARDWARE_LATE setup priority. - float get_setup_priority() const override; protected: bool read_sensor_(float *temperature, float *humidity, bool report_errors); diff --git a/esphome/components/dht12/dht12.cpp b/esphome/components/dht12/dht12.cpp index 445d150be0..1d884daad6 100644 --- a/esphome/components/dht12/dht12.cpp +++ b/esphome/components/dht12/dht12.cpp @@ -49,7 +49,7 @@ void DHT12Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float DHT12Component::get_setup_priority() const { return setup_priority::DATA; } + bool DHT12Component::read_data_(uint8_t *data) { if (!this->read_bytes(0, data, 5)) { ESP_LOGW(TAG, "Updating DHT12 failed!"); diff --git a/esphome/components/dht12/dht12.h b/esphome/components/dht12/dht12.h index 2a706039ba..ab19d7c723 100644 --- a/esphome/components/dht12/dht12.h +++ b/esphome/components/dht12/dht12.h @@ -11,7 +11,6 @@ class DHT12Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/dps310/dps310.cpp b/esphome/components/dps310/dps310.cpp index 6b6f9622fa..aa0a77cdd8 100644 --- a/esphome/components/dps310/dps310.cpp +++ b/esphome/components/dps310/dps310.cpp @@ -98,8 +98,6 @@ void DPS310Component::dump_config() { LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); } -float DPS310Component::get_setup_priority() const { return setup_priority::DATA; } - void DPS310Component::update() { if (!this->update_in_progress_) { this->update_in_progress_ = true; diff --git a/esphome/components/dps310/dps310.h b/esphome/components/dps310/dps310.h index 50e7d93c8a..dce220d44b 100644 --- a/esphome/components/dps310/dps310.h +++ b/esphome/components/dps310/dps310.h @@ -40,7 +40,6 @@ class DPS310Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp index adbd7b5487..5c0e98290b 100644 --- a/esphome/components/ds1307/ds1307.cpp +++ b/esphome/components/ds1307/ds1307.cpp @@ -26,8 +26,6 @@ void DS1307Component::dump_config() { RealTimeClock::dump_config(); } -float DS1307Component::get_setup_priority() const { return setup_priority::DATA; } - void DS1307Component::read_time() { if (!this->read_rtc_()) { return; diff --git a/esphome/components/ds1307/ds1307.h b/esphome/components/ds1307/ds1307.h index f7f06253b7..1712056006 100644 --- a/esphome/components/ds1307/ds1307.h +++ b/esphome/components/ds1307/ds1307.h @@ -12,7 +12,6 @@ class DS1307Component : public time::RealTimeClock, public i2c::I2CDevice { void setup() override; void update() override; void dump_config() override; - float get_setup_priority() const override; void read_time(); void write_time(); diff --git a/esphome/components/duty_cycle/duty_cycle_sensor.cpp b/esphome/components/duty_cycle/duty_cycle_sensor.cpp index 40a728d025..f801769d27 100644 --- a/esphome/components/duty_cycle/duty_cycle_sensor.cpp +++ b/esphome/components/duty_cycle/duty_cycle_sensor.cpp @@ -43,8 +43,6 @@ void DutyCycleSensor::update() { this->last_update_ = now; } -float DutyCycleSensor::get_setup_priority() const { return setup_priority::DATA; } - void IRAM_ATTR DutyCycleSensorStore::gpio_intr(DutyCycleSensorStore *arg) { const bool new_level = arg->pin.digital_read(); if (new_level == arg->last_level) diff --git a/esphome/components/duty_cycle/duty_cycle_sensor.h b/esphome/components/duty_cycle/duty_cycle_sensor.h index ffb1802e14..ffb8e3b622 100644 --- a/esphome/components/duty_cycle/duty_cycle_sensor.h +++ b/esphome/components/duty_cycle/duty_cycle_sensor.h @@ -22,7 +22,6 @@ class DutyCycleSensor : public sensor::Sensor, public PollingComponent { void set_pin(InternalGPIOPin *pin) { pin_ = pin; } void setup() override; - float get_setup_priority() const override; void dump_config() override; void update() override; diff --git a/esphome/components/ee895/ee895.cpp b/esphome/components/ee895/ee895.cpp index 602e31db14..22f28be9bc 100644 --- a/esphome/components/ee895/ee895.cpp +++ b/esphome/components/ee895/ee895.cpp @@ -55,8 +55,6 @@ void EE895Component::dump_config() { LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); } -float EE895Component::get_setup_priority() const { return setup_priority::DATA; } - void EE895Component::update() { write_command_(TEMPERATURE_ADDRESS, 2); this->set_timeout(50, [this]() { diff --git a/esphome/components/ee895/ee895.h b/esphome/components/ee895/ee895.h index 83bd7c6e82..259b7c524b 100644 --- a/esphome/components/ee895/ee895.h +++ b/esphome/components/ee895/ee895.h @@ -14,7 +14,6 @@ class EE895Component : public PollingComponent, public i2c::I2CDevice { void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } - float get_setup_priority() const override; void setup() override; void dump_config() override; void update() override; diff --git a/esphome/components/emc2101/sensor/emc2101_sensor.cpp b/esphome/components/emc2101/sensor/emc2101_sensor.cpp index 2a199f48e9..3014c7da07 100644 --- a/esphome/components/emc2101/sensor/emc2101_sensor.cpp +++ b/esphome/components/emc2101/sensor/emc2101_sensor.cpp @@ -7,8 +7,6 @@ namespace emc2101 { static const char *const TAG = "EMC2101.sensor"; -float EMC2101Sensor::get_setup_priority() const { return setup_priority::DATA; } - void EMC2101Sensor::dump_config() { ESP_LOGCONFIG(TAG, "Emc2101 sensor:"); LOG_SENSOR(" ", "Internal temperature", this->internal_temperature_sensor_); diff --git a/esphome/components/emc2101/sensor/emc2101_sensor.h b/esphome/components/emc2101/sensor/emc2101_sensor.h index 3e8dcebc8e..3e033f58a7 100644 --- a/esphome/components/emc2101/sensor/emc2101_sensor.h +++ b/esphome/components/emc2101/sensor/emc2101_sensor.h @@ -15,8 +15,6 @@ class EMC2101Sensor : public PollingComponent { void dump_config() override; /** Used by ESPHome framework. */ void update() override; - /** Used by ESPHome framework. */ - float get_setup_priority() const override; /** Used by ESPHome framework. */ void set_internal_temperature_sensor(sensor::Sensor *sensor) { this->internal_temperature_sensor_ = sensor; } diff --git a/esphome/components/endstop/endstop_cover.cpp b/esphome/components/endstop/endstop_cover.cpp index e28f024136..ea8a5ec186 100644 --- a/esphome/components/endstop/endstop_cover.cpp +++ b/esphome/components/endstop/endstop_cover.cpp @@ -111,7 +111,7 @@ void EndstopCover::dump_config() { LOG_BINARY_SENSOR(" ", "Open Endstop", this->open_endstop_); LOG_BINARY_SENSOR(" ", "Close Endstop", this->close_endstop_); } -float EndstopCover::get_setup_priority() const { return setup_priority::DATA; } + void EndstopCover::stop_prev_trigger_() { if (this->prev_command_trigger_ != nullptr) { this->prev_command_trigger_->stop_action(); diff --git a/esphome/components/endstop/endstop_cover.h b/esphome/components/endstop/endstop_cover.h index 6f72b2b805..32ede12335 100644 --- a/esphome/components/endstop/endstop_cover.h +++ b/esphome/components/endstop/endstop_cover.h @@ -13,7 +13,6 @@ class EndstopCover : public cover::Cover, public Component { void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override; Trigger<> *get_open_trigger() { return &this->open_trigger_; } Trigger<> *get_close_trigger() { return &this->close_trigger_; } diff --git a/esphome/components/ens210/ens210.cpp b/esphome/components/ens210/ens210.cpp index 98a300f5d7..8bee9bfb18 100644 --- a/esphome/components/ens210/ens210.cpp +++ b/esphome/components/ens210/ens210.cpp @@ -136,8 +136,6 @@ void ENS210Component::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float ENS210Component::get_setup_priority() const { return setup_priority::DATA; } - void ENS210Component::update() { // Execute a single measurement if (!this->write_byte(ENS210_REGISTER_SENS_RUN, 0x00)) { diff --git a/esphome/components/ens210/ens210.h b/esphome/components/ens210/ens210.h index 0fb6ff634d..ae2bf81b5f 100644 --- a/esphome/components/ens210/ens210.h +++ b/esphome/components/ens210/ens210.h @@ -10,7 +10,6 @@ namespace ens210 { /// This class implements support for the ENS210 relative humidity and temperature i2c sensor. class ENS210Component : public PollingComponent, public i2c::I2CDevice { public: - float get_setup_priority() const override; void dump_config() override; void setup() override; void update() override; diff --git a/esphome/components/esp32_camera/esp32_camera.cpp b/esphome/components/esp32_camera/esp32_camera.cpp index 5466d2e7ef..cfe06b1673 100644 --- a/esphome/components/esp32_camera/esp32_camera.cpp +++ b/esphome/components/esp32_camera/esp32_camera.cpp @@ -235,8 +235,6 @@ void ESP32Camera::loop() { this->single_requesters_ = 0; } -float ESP32Camera::get_setup_priority() const { return setup_priority::DATA; } - /* ---------------- constructors ---------------- */ ESP32Camera::ESP32Camera() { this->config_.pin_pwdn = -1; diff --git a/esphome/components/esp32_camera/esp32_camera.h b/esphome/components/esp32_camera/esp32_camera.h index e97eb27c70..eea93b7e01 100644 --- a/esphome/components/esp32_camera/esp32_camera.h +++ b/esphome/components/esp32_camera/esp32_camera.h @@ -159,7 +159,6 @@ class ESP32Camera : public camera::Camera { void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override; /* public API (specific) */ void start_stream(camera::CameraRequester requester) override; void stop_stream(camera::CameraRequester requester) override; diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 812c746301..7f45f2ccb4 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -51,7 +51,6 @@ class ESP32TouchComponent : public Component { void setup() override; void dump_config() override; void loop() override; - float get_setup_priority() const override { return setup_priority::DATA; } void on_shutdown() override; diff --git a/esphome/components/gdk101/gdk101.cpp b/esphome/components/gdk101/gdk101.cpp index ddf38f2f55..8b381564b2 100644 --- a/esphome/components/gdk101/gdk101.cpp +++ b/esphome/components/gdk101/gdk101.cpp @@ -77,8 +77,6 @@ void GDK101Component::dump_config() { #endif // USE_TEXT_SENSOR } -float GDK101Component::get_setup_priority() const { return setup_priority::DATA; } - bool GDK101Component::read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len) { uint8_t retry = NUMBER_OF_READ_RETRIES; bool status = false; diff --git a/esphome/components/gdk101/gdk101.h b/esphome/components/gdk101/gdk101.h index f250a42a54..abe417e0f9 100644 --- a/esphome/components/gdk101/gdk101.h +++ b/esphome/components/gdk101/gdk101.h @@ -40,7 +40,6 @@ class GDK101Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/gp8403/gp8403.h b/esphome/components/gp8403/gp8403.h index 6613187b20..972f2ce60c 100644 --- a/esphome/components/gp8403/gp8403.h +++ b/esphome/components/gp8403/gp8403.h @@ -20,7 +20,6 @@ class GP8403Component : public Component, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } void set_model(GP8403Model model) { this->model_ = model; } void set_voltage(gp8403::GP8403Voltage voltage) { this->voltage_ = voltage; } diff --git a/esphome/components/hc8/hc8.cpp b/esphome/components/hc8/hc8.cpp index 4d0f77df1b..4c2d367b24 100644 --- a/esphome/components/hc8/hc8.cpp +++ b/esphome/components/hc8/hc8.cpp @@ -86,8 +86,6 @@ void HC8Component::calibrate(uint16_t baseline) { this->flush(); } -float HC8Component::get_setup_priority() const { return setup_priority::DATA; } - void HC8Component::dump_config() { ESP_LOGCONFIG(TAG, "HC8:\n" diff --git a/esphome/components/hc8/hc8.h b/esphome/components/hc8/hc8.h index 7711fb8c97..74257fab14 100644 --- a/esphome/components/hc8/hc8.h +++ b/esphome/components/hc8/hc8.h @@ -11,8 +11,6 @@ namespace esphome::hc8 { class HC8Component : public PollingComponent, public uart::UARTDevice { public: - float get_setup_priority() const override; - void setup() override; void update() override; void dump_config() override; diff --git a/esphome/components/hdc1080/hdc1080.h b/esphome/components/hdc1080/hdc1080.h index 7ad0764f1f..a5bece82c4 100644 --- a/esphome/components/hdc1080/hdc1080.h +++ b/esphome/components/hdc1080/hdc1080.h @@ -16,8 +16,6 @@ class HDC1080Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; void update() override; - float get_setup_priority() const override { return setup_priority::DATA; } - protected: sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; diff --git a/esphome/components/hlw8012/hlw8012.cpp b/esphome/components/hlw8012/hlw8012.cpp index f037ee9d8b..d0fd697d8f 100644 --- a/esphome/components/hlw8012/hlw8012.cpp +++ b/esphome/components/hlw8012/hlw8012.cpp @@ -48,7 +48,6 @@ void HLW8012Component::dump_config() { LOG_SENSOR(" ", "Power", this->power_sensor_); LOG_SENSOR(" ", "Energy", this->energy_sensor_); } -float HLW8012Component::get_setup_priority() const { return setup_priority::DATA; } void HLW8012Component::update() { // HLW8012 has 50% duty cycle pulse_counter::pulse_counter_t raw_cf = this->cf_store_.read_raw_value(); diff --git a/esphome/components/hlw8012/hlw8012.h b/esphome/components/hlw8012/hlw8012.h index 312391f533..8a13ec07d8 100644 --- a/esphome/components/hlw8012/hlw8012.h +++ b/esphome/components/hlw8012/hlw8012.h @@ -31,7 +31,6 @@ class HLW8012Component : public PollingComponent { void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_initial_mode(HLW8012InitialMode initial_mode) { diff --git a/esphome/components/hm3301/hm3301.cpp b/esphome/components/hm3301/hm3301.cpp index 00fb85397c..9343b47823 100644 --- a/esphome/components/hm3301/hm3301.cpp +++ b/esphome/components/hm3301/hm3301.cpp @@ -31,8 +31,6 @@ void HM3301Component::dump_config() { LOG_SENSOR(" ", "AQI", this->aqi_sensor_); } -float HM3301Component::get_setup_priority() const { return setup_priority::DATA; } - void HM3301Component::update() { if (this->read(data_buffer_, 29) != i2c::ERROR_OK) { ESP_LOGW(TAG, "Read result failed"); diff --git a/esphome/components/hm3301/hm3301.h b/esphome/components/hm3301/hm3301.h index e155ed6b4b..6b10a5e237 100644 --- a/esphome/components/hm3301/hm3301.h +++ b/esphome/components/hm3301/hm3301.h @@ -23,7 +23,6 @@ class HM3301Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/hmc5883l/hmc5883l.cpp b/esphome/components/hmc5883l/hmc5883l.cpp index 101493ad91..b62381a287 100644 --- a/esphome/components/hmc5883l/hmc5883l.cpp +++ b/esphome/components/hmc5883l/hmc5883l.cpp @@ -83,7 +83,6 @@ void HMC5883LComponent::dump_config() { LOG_SENSOR(" ", "Z Axis", this->z_sensor_); LOG_SENSOR(" ", "Heading", this->heading_sensor_); } -float HMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } void HMC5883LComponent::update() { uint16_t raw_x, raw_y, raw_z; if (!this->read_byte_16(HMC5883L_REGISTER_DATA_X_MSB, &raw_x) || diff --git a/esphome/components/hmc5883l/hmc5883l.h b/esphome/components/hmc5883l/hmc5883l.h index 06fba2af9d..8eae0f7a50 100644 --- a/esphome/components/hmc5883l/hmc5883l.h +++ b/esphome/components/hmc5883l/hmc5883l.h @@ -39,7 +39,6 @@ class HMC5883LComponent : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_oversampling(HMC5883LOversampling oversampling) { oversampling_ = oversampling; } diff --git a/esphome/components/homeassistant/time/homeassistant_time.cpp b/esphome/components/homeassistant/time/homeassistant_time.cpp index e72c5a21f5..d039892073 100644 --- a/esphome/components/homeassistant/time/homeassistant_time.cpp +++ b/esphome/components/homeassistant/time/homeassistant_time.cpp @@ -11,8 +11,6 @@ void HomeassistantTime::dump_config() { RealTimeClock::dump_config(); } -float HomeassistantTime::get_setup_priority() const { return setup_priority::DATA; } - void HomeassistantTime::setup() { global_homeassistant_time = this; } void HomeassistantTime::update() { api::global_api_server->request_time(); } diff --git a/esphome/components/homeassistant/time/homeassistant_time.h b/esphome/components/homeassistant/time/homeassistant_time.h index 36e28ea16b..7b5842fefd 100644 --- a/esphome/components/homeassistant/time/homeassistant_time.h +++ b/esphome/components/homeassistant/time/homeassistant_time.h @@ -13,7 +13,6 @@ class HomeassistantTime : public time::RealTimeClock { void update() override; void dump_config() override; void set_epoch_time(uint32_t epoch) { this->synchronize_epoch_(epoch); } - float get_setup_priority() const override; }; extern HomeassistantTime *global_homeassistant_time; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/honeywell_hih_i2c/honeywell_hih.cpp b/esphome/components/honeywell_hih_i2c/honeywell_hih.cpp index 5f2b009972..904672d136 100644 --- a/esphome/components/honeywell_hih_i2c/honeywell_hih.cpp +++ b/esphome/components/honeywell_hih_i2c/honeywell_hih.cpp @@ -91,7 +91,5 @@ void HoneywellHIComponent::dump_config() { LOG_UPDATE_INTERVAL(this); } -float HoneywellHIComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace honeywell_hih_i2c } // namespace esphome diff --git a/esphome/components/honeywell_hih_i2c/honeywell_hih.h b/esphome/components/honeywell_hih_i2c/honeywell_hih.h index 4457eab1da..79140f7399 100644 --- a/esphome/components/honeywell_hih_i2c/honeywell_hih.h +++ b/esphome/components/honeywell_hih_i2c/honeywell_hih.h @@ -11,7 +11,6 @@ namespace honeywell_hih_i2c { class HoneywellHIComponent : public PollingComponent, public i2c::I2CDevice { public: void dump_config() override; - float get_setup_priority() const override; void loop() override; void update() override; diff --git a/esphome/components/hte501/hte501.cpp b/esphome/components/hte501/hte501.cpp index cde6886109..972e72c170 100644 --- a/esphome/components/hte501/hte501.cpp +++ b/esphome/components/hte501/hte501.cpp @@ -43,7 +43,6 @@ void HTE501Component::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float HTE501Component::get_setup_priority() const { return setup_priority::DATA; } void HTE501Component::update() { uint8_t address_1[] = {0x2C, 0x1B}; this->write(address_1, 2); diff --git a/esphome/components/hte501/hte501.h b/esphome/components/hte501/hte501.h index a7072d5bdb..b47daf9157 100644 --- a/esphome/components/hte501/hte501.h +++ b/esphome/components/hte501/hte501.h @@ -13,7 +13,6 @@ class HTE501Component : public PollingComponent, public i2c::I2CDevice { void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } - float get_setup_priority() const override; void setup() override; void dump_config() override; void update() override; diff --git a/esphome/components/htu21d/htu21d.cpp b/esphome/components/htu21d/htu21d.cpp index c5d91d3dd0..58a28b213f 100644 --- a/esphome/components/htu21d/htu21d.cpp +++ b/esphome/components/htu21d/htu21d.cpp @@ -143,7 +143,5 @@ uint8_t HTU21DComponent::get_heater_level() { return raw_heater & 0xF; } -float HTU21DComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace htu21d } // namespace esphome diff --git a/esphome/components/htu21d/htu21d.h b/esphome/components/htu21d/htu21d.h index 277c6ca3e5..594be78326 100644 --- a/esphome/components/htu21d/htu21d.h +++ b/esphome/components/htu21d/htu21d.h @@ -28,8 +28,6 @@ class HTU21DComponent : public PollingComponent, public i2c::I2CDevice { void set_heater_level(uint8_t level); uint8_t get_heater_level(); - float get_setup_priority() const override; - protected: sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; diff --git a/esphome/components/htu31d/htu31d.cpp b/esphome/components/htu31d/htu31d.cpp index 562078aacb..4bb38a11a2 100644 --- a/esphome/components/htu31d/htu31d.cpp +++ b/esphome/components/htu31d/htu31d.cpp @@ -259,11 +259,5 @@ void HTU31DComponent::set_heater_state(bool desired) { } } -/** - * Sets the startup priority for this component. - * - * @returns The startup priority - */ -float HTU31DComponent::get_setup_priority() const { return setup_priority::DATA; } } // namespace htu31d } // namespace esphome diff --git a/esphome/components/htu31d/htu31d.h b/esphome/components/htu31d/htu31d.h index 9462133ced..24d85243cc 100644 --- a/esphome/components/htu31d/htu31d.h +++ b/esphome/components/htu31d/htu31d.h @@ -20,8 +20,6 @@ class HTU31DComponent : public PollingComponent, public i2c::I2CDevice { void set_heater_state(bool desired); bool is_heater_enabled(); - float get_setup_priority() const override; - protected: bool reset_(); uint32_t read_serial_num_(); diff --git a/esphome/components/hx711/hx711.cpp b/esphome/components/hx711/hx711.cpp index 67ec4549df..f2e3234127 100644 --- a/esphome/components/hx711/hx711.cpp +++ b/esphome/components/hx711/hx711.cpp @@ -22,7 +22,6 @@ void HX711Sensor::dump_config() { LOG_PIN(" SCK Pin: ", this->sck_pin_); LOG_UPDATE_INTERVAL(this); } -float HX711Sensor::get_setup_priority() const { return setup_priority::DATA; } void HX711Sensor::update() { uint32_t result; if (this->read_sensor_(&result)) { diff --git a/esphome/components/hx711/hx711.h b/esphome/components/hx711/hx711.h index a92bb9945d..37723ee81f 100644 --- a/esphome/components/hx711/hx711.h +++ b/esphome/components/hx711/hx711.h @@ -23,7 +23,6 @@ class HX711Sensor : public sensor::Sensor, public PollingComponent { void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp index 4872d68610..983a0a6649 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.cpp @@ -284,7 +284,5 @@ void HydreonRGxxComponent::process_line_() { } } -float HydreonRGxxComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace hydreon_rgxx } // namespace esphome diff --git a/esphome/components/hydreon_rgxx/hydreon_rgxx.h b/esphome/components/hydreon_rgxx/hydreon_rgxx.h index 76b0985a24..e3f9798a93 100644 --- a/esphome/components/hydreon_rgxx/hydreon_rgxx.h +++ b/esphome/components/hydreon_rgxx/hydreon_rgxx.h @@ -53,8 +53,6 @@ class HydreonRGxxComponent : public PollingComponent, public uart::UARTDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override; - void set_disable_led(bool disable_led) { this->disable_led_ = disable_led; } protected: diff --git a/esphome/components/hyt271/hyt271.cpp b/esphome/components/hyt271/hyt271.cpp index f187e054a8..4c0e3cd96e 100644 --- a/esphome/components/hyt271/hyt271.cpp +++ b/esphome/components/hyt271/hyt271.cpp @@ -46,7 +46,5 @@ void HYT271Component::update() { this->status_clear_warning(); }); } -float HYT271Component::get_setup_priority() const { return setup_priority::DATA; } - } // namespace hyt271 } // namespace esphome diff --git a/esphome/components/hyt271/hyt271.h b/esphome/components/hyt271/hyt271.h index 64f32a651c..19409d830c 100644 --- a/esphome/components/hyt271/hyt271.h +++ b/esphome/components/hyt271/hyt271.h @@ -16,8 +16,6 @@ class HYT271Component : public PollingComponent, public i2c::I2CDevice { /// Update the sensor values (temperature+humidity). void update() override; - float get_setup_priority() const override; - protected: sensor::Sensor *temperature_{nullptr}; sensor::Sensor *humidity_{nullptr}; diff --git a/esphome/components/ina219/ina219.cpp b/esphome/components/ina219/ina219.cpp index ea8c5cea9d..278017651b 100644 --- a/esphome/components/ina219/ina219.cpp +++ b/esphome/components/ina219/ina219.cpp @@ -151,8 +151,6 @@ void INA219Component::dump_config() { LOG_SENSOR(" ", "Power", this->power_sensor_); } -float INA219Component::get_setup_priority() const { return setup_priority::DATA; } - void INA219Component::update() { if (this->bus_voltage_sensor_ != nullptr) { uint16_t raw_bus_voltage; diff --git a/esphome/components/ina219/ina219.h b/esphome/components/ina219/ina219.h index 115fa886e0..bcadb65e36 100644 --- a/esphome/components/ina219/ina219.h +++ b/esphome/components/ina219/ina219.h @@ -13,7 +13,6 @@ class INA219Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void on_powerdown() override; diff --git a/esphome/components/ina226/ina226.cpp b/esphome/components/ina226/ina226.cpp index c4d4fb896e..cbc44c9a1a 100644 --- a/esphome/components/ina226/ina226.cpp +++ b/esphome/components/ina226/ina226.cpp @@ -104,8 +104,6 @@ void INA226Component::dump_config() { LOG_SENSOR(" ", "Power", this->power_sensor_); } -float INA226Component::get_setup_priority() const { return setup_priority::DATA; } - void INA226Component::update() { if (this->bus_voltage_sensor_ != nullptr) { uint16_t raw_bus_voltage; diff --git a/esphome/components/ina226/ina226.h b/esphome/components/ina226/ina226.h index 61214fea0e..0aa66ff765 100644 --- a/esphome/components/ina226/ina226.h +++ b/esphome/components/ina226/ina226.h @@ -45,7 +45,6 @@ class INA226Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_shunt_resistance_ohm(float shunt_resistance_ohm) { shunt_resistance_ohm_ = shunt_resistance_ohm; } diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index 7185d21810..de01c99a19 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -79,8 +79,6 @@ void INA2XX::setup() { this->state_ = State::IDLE; } -float INA2XX::get_setup_priority() const { return setup_priority::DATA; } - void INA2XX::update() { ESP_LOGD(TAG, "Updating"); if (this->is_ready() && this->state_ == State::IDLE) { diff --git a/esphome/components/ina2xx_base/ina2xx_base.h b/esphome/components/ina2xx_base/ina2xx_base.h index ba0999b28e..104c384a0d 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.h +++ b/esphome/components/ina2xx_base/ina2xx_base.h @@ -114,7 +114,6 @@ enum INAModel : uint8_t { INA_UNKNOWN = 0, INA_228, INA_229, INA_238, INA_239, I class INA2XX : public PollingComponent { public: void setup() override; - float get_setup_priority() const override; void update() override; void loop() override; void dump_config() override; diff --git a/esphome/components/ina3221/ina3221.cpp b/esphome/components/ina3221/ina3221.cpp index 8243764147..d03183e002 100644 --- a/esphome/components/ina3221/ina3221.cpp +++ b/esphome/components/ina3221/ina3221.cpp @@ -113,7 +113,6 @@ void INA3221Component::update() { } } -float INA3221Component::get_setup_priority() const { return setup_priority::DATA; } void INA3221Component::set_shunt_resistance(int channel, float resistance_ohm) { this->channels_[channel].shunt_resistance_ = resistance_ohm; } diff --git a/esphome/components/ina3221/ina3221.h b/esphome/components/ina3221/ina3221.h index f593badc09..3769df77aa 100644 --- a/esphome/components/ina3221/ina3221.h +++ b/esphome/components/ina3221/ina3221.h @@ -12,7 +12,6 @@ class INA3221Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void dump_config() override; void update() override; - float get_setup_priority() const override; void set_bus_voltage_sensor(int channel, sensor::Sensor *obj) { this->channels_[channel].bus_voltage_sensor_ = obj; } void set_shunt_voltage_sensor(int channel, sensor::Sensor *obj) { diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp index e5fa035682..534939f9af 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -30,8 +30,6 @@ void KamstrupKMPComponent::dump_config() { this->check_uart_settings(1200, 2, uart::UART_CONFIG_PARITY_NONE, 8); } -float KamstrupKMPComponent::get_setup_priority() const { return setup_priority::DATA; } - void KamstrupKMPComponent::update() { if (this->heat_energy_sensor_ != nullptr) { this->command_queue_.push(CMD_HEAT_ENERGY); diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.h b/esphome/components/kamstrup_kmp/kamstrup_kmp.h index c9cc9c5a39..f84e360132 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.h +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.h @@ -83,7 +83,6 @@ class KamstrupKMPComponent : public PollingComponent, public uart::UARTDevice { void set_flow_sensor(sensor::Sensor *sensor) { this->flow_sensor_ = sensor; } void set_volume_sensor(sensor::Sensor *sensor) { this->volume_sensor_ = sensor; } void dump_config() override; - float get_setup_priority() const override; void update() override; void loop() override; void add_custom_sensor(sensor::Sensor *sensor, uint16_t command) { diff --git a/esphome/components/kmeteriso/kmeteriso.cpp b/esphome/components/kmeteriso/kmeteriso.cpp index 36f6d74ba0..186686e472 100644 --- a/esphome/components/kmeteriso/kmeteriso.cpp +++ b/esphome/components/kmeteriso/kmeteriso.cpp @@ -47,8 +47,6 @@ void KMeterISOComponent::setup() { } } -float KMeterISOComponent::get_setup_priority() const { return setup_priority::DATA; } - void KMeterISOComponent::update() { uint8_t read_buf[4]; diff --git a/esphome/components/kmeteriso/kmeteriso.h b/esphome/components/kmeteriso/kmeteriso.h index c8bed662b0..6f1978105f 100644 --- a/esphome/components/kmeteriso/kmeteriso.h +++ b/esphome/components/kmeteriso/kmeteriso.h @@ -17,7 +17,6 @@ class KMeterISOComponent : public PollingComponent, public i2c::I2CDevice { // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) void setup() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/m5stack_8angle/m5stack_8angle.cpp b/esphome/components/m5stack_8angle/m5stack_8angle.cpp index 5a9a5e8c9d..2de900c21d 100644 --- a/esphome/components/m5stack_8angle/m5stack_8angle.cpp +++ b/esphome/components/m5stack_8angle/m5stack_8angle.cpp @@ -69,7 +69,5 @@ int8_t M5Stack8AngleComponent::read_switch() { } } -float M5Stack8AngleComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace m5stack_8angle } // namespace esphome diff --git a/esphome/components/m5stack_8angle/m5stack_8angle.h b/esphome/components/m5stack_8angle/m5stack_8angle.h index 831b1422fd..4942518054 100644 --- a/esphome/components/m5stack_8angle/m5stack_8angle.h +++ b/esphome/components/m5stack_8angle/m5stack_8angle.h @@ -21,7 +21,6 @@ class M5Stack8AngleComponent : public i2c::I2CDevice, public Component { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; float read_knob_pos(uint8_t channel, AnalogBits bits = AnalogBits::BITS_8); int32_t read_knob_pos_raw(uint8_t channel, AnalogBits bits = AnalogBits::BITS_8); int8_t read_switch(); diff --git a/esphome/components/max17043/max17043.cpp b/esphome/components/max17043/max17043.cpp index e8cf4d5ab1..dfd59f1e7d 100644 --- a/esphome/components/max17043/max17043.cpp +++ b/esphome/components/max17043/max17043.cpp @@ -81,8 +81,6 @@ void MAX17043Component::dump_config() { LOG_SENSOR(" ", "Battery Level", this->battery_remaining_sensor_); } -float MAX17043Component::get_setup_priority() const { return setup_priority::DATA; } - void MAX17043Component::sleep_mode() { if (!this->is_failed()) { if (!this->write_byte_16(MAX17043_CONFIG, MAX17043_CONFIG_POWER_UP_DEFAULT | MAX17043_CONFIG_SLEEP_MASK)) { diff --git a/esphome/components/max17043/max17043.h b/esphome/components/max17043/max17043.h index 540b977789..f477ce5948 100644 --- a/esphome/components/max17043/max17043.h +++ b/esphome/components/max17043/max17043.h @@ -11,7 +11,6 @@ class MAX17043Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void sleep_mode(); diff --git a/esphome/components/max31855/max31855.cpp b/esphome/components/max31855/max31855.cpp index b5be3106cf..99129880f4 100644 --- a/esphome/components/max31855/max31855.cpp +++ b/esphome/components/max31855/max31855.cpp @@ -31,7 +31,6 @@ void MAX31855Sensor::dump_config() { ESP_LOGCONFIG(TAG, " Reference temperature disabled."); } } -float MAX31855Sensor::get_setup_priority() const { return setup_priority::DATA; } void MAX31855Sensor::read_data_() { this->enable(); delay(1); diff --git a/esphome/components/max31855/max31855.h b/esphome/components/max31855/max31855.h index 822e256587..b755d240f2 100644 --- a/esphome/components/max31855/max31855.h +++ b/esphome/components/max31855/max31855.h @@ -18,7 +18,6 @@ class MAX31855Sensor : public sensor::Sensor, void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; diff --git a/esphome/components/max31856/max31856.cpp b/esphome/components/max31856/max31856.cpp index cc573cbc53..ff65c8c5c9 100644 --- a/esphome/components/max31856/max31856.cpp +++ b/esphome/components/max31856/max31856.cpp @@ -197,7 +197,5 @@ uint32_t MAX31856Sensor::read_register24_(uint8_t reg) { return value; } -float MAX31856Sensor::get_setup_priority() const { return setup_priority::DATA; } - } // namespace max31856 } // namespace esphome diff --git a/esphome/components/max31856/max31856.h b/esphome/components/max31856/max31856.h index 8d64cfe8bc..a27ababa2e 100644 --- a/esphome/components/max31856/max31856.h +++ b/esphome/components/max31856/max31856.h @@ -76,7 +76,6 @@ class MAX31856Sensor : public sensor::Sensor, public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void set_filter(MAX31856ConfigFilter filter) { this->filter_ = filter; } void set_thermocouple_type(MAX31856ThermocoupleType thermocouple_type) { this->thermocouple_type_ = thermocouple_type; diff --git a/esphome/components/max31865/max31865.cpp b/esphome/components/max31865/max31865.cpp index a9c5204cf5..09b8368d07 100644 --- a/esphome/components/max31865/max31865.cpp +++ b/esphome/components/max31865/max31865.cpp @@ -90,8 +90,6 @@ void MAX31865Sensor::dump_config() { (filter_ == FILTER_60HZ ? "60 Hz" : (filter_ == FILTER_50HZ ? "50 Hz" : "Unknown!"))); } -float MAX31865Sensor::get_setup_priority() const { return setup_priority::DATA; } - void MAX31865Sensor::read_data_() { // Read temperature, disable V_BIAS (save power) const uint16_t rtd_resistance_register = this->read_register_16_(RTD_RESISTANCE_MSB_REG); diff --git a/esphome/components/max31865/max31865.h b/esphome/components/max31865/max31865.h index b83753a678..440c6523a6 100644 --- a/esphome/components/max31865/max31865.h +++ b/esphome/components/max31865/max31865.h @@ -34,7 +34,6 @@ class MAX31865Sensor : public sensor::Sensor, void set_num_rtd_wires(uint8_t rtd_wires) { rtd_wires_ = rtd_wires; } void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; diff --git a/esphome/components/max44009/max44009.cpp b/esphome/components/max44009/max44009.cpp index 928fc47696..8b8e38c1ea 100644 --- a/esphome/components/max44009/max44009.cpp +++ b/esphome/components/max44009/max44009.cpp @@ -51,8 +51,6 @@ void MAX44009Sensor::dump_config() { } } -float MAX44009Sensor::get_setup_priority() const { return setup_priority::DATA; } - void MAX44009Sensor::update() { // update sensor illuminance value float lux = this->read_illuminance_(); diff --git a/esphome/components/max44009/max44009.h b/esphome/components/max44009/max44009.h index c85d1c1028..59eea66ed9 100644 --- a/esphome/components/max44009/max44009.h +++ b/esphome/components/max44009/max44009.h @@ -16,7 +16,6 @@ class MAX44009Sensor : public sensor::Sensor, public PollingComponent, public i2 void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_mode(MAX44009Mode mode); bool set_continuous_mode(); diff --git a/esphome/components/max6675/max6675.cpp b/esphome/components/max6675/max6675.cpp index 54e0330ff7..c329cdfd42 100644 --- a/esphome/components/max6675/max6675.cpp +++ b/esphome/components/max6675/max6675.cpp @@ -23,7 +23,6 @@ void MAX6675Sensor::dump_config() { LOG_PIN(" CS Pin: ", this->cs_); LOG_UPDATE_INTERVAL(this); } -float MAX6675Sensor::get_setup_priority() const { return setup_priority::DATA; } void MAX6675Sensor::read_data_() { this->enable(); delay(1); diff --git a/esphome/components/max6675/max6675.h b/esphome/components/max6675/max6675.h index ab0f06b041..f0db4a6c26 100644 --- a/esphome/components/max6675/max6675.h +++ b/esphome/components/max6675/max6675.h @@ -14,7 +14,6 @@ class MAX6675Sensor : public sensor::Sensor, public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; diff --git a/esphome/components/mcp3008/sensor/mcp3008_sensor.cpp b/esphome/components/mcp3008/sensor/mcp3008_sensor.cpp index 81eb0a812f..ee052e9fb7 100644 --- a/esphome/components/mcp3008/sensor/mcp3008_sensor.cpp +++ b/esphome/components/mcp3008/sensor/mcp3008_sensor.cpp @@ -7,8 +7,6 @@ namespace mcp3008 { static const char *const TAG = "mcp3008.sensor"; -float MCP3008Sensor::get_setup_priority() const { return setup_priority::DATA; } - void MCP3008Sensor::dump_config() { ESP_LOGCONFIG(TAG, "MCP3008Sensor:\n" diff --git a/esphome/components/mcp3008/sensor/mcp3008_sensor.h b/esphome/components/mcp3008/sensor/mcp3008_sensor.h index ebaeab966f..9478d38e74 100644 --- a/esphome/components/mcp3008/sensor/mcp3008_sensor.h +++ b/esphome/components/mcp3008/sensor/mcp3008_sensor.h @@ -19,7 +19,6 @@ class MCP3008Sensor : public PollingComponent, void update() override; void dump_config() override; - float get_setup_priority() const override; float sample() override; protected: diff --git a/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp b/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp index e673537be1..711448cf44 100644 --- a/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp +++ b/esphome/components/mcp3204/sensor/mcp3204_sensor.cpp @@ -7,8 +7,6 @@ namespace mcp3204 { static const char *const TAG = "mcp3204.sensor"; -float MCP3204Sensor::get_setup_priority() const { return setup_priority::DATA; } - void MCP3204Sensor::dump_config() { LOG_SENSOR("", "MCP3204 Sensor", this); ESP_LOGCONFIG(TAG, diff --git a/esphome/components/mcp3204/sensor/mcp3204_sensor.h b/esphome/components/mcp3204/sensor/mcp3204_sensor.h index 5665b80b98..2bf75a9c1e 100644 --- a/esphome/components/mcp3204/sensor/mcp3204_sensor.h +++ b/esphome/components/mcp3204/sensor/mcp3204_sensor.h @@ -19,7 +19,6 @@ class MCP3204Sensor : public PollingComponent, void update() override; void dump_config() override; - float get_setup_priority() const override; float sample() override; protected: diff --git a/esphome/components/mcp9808/mcp9808.cpp b/esphome/components/mcp9808/mcp9808.cpp index 088d33887f..ed12e52239 100644 --- a/esphome/components/mcp9808/mcp9808.cpp +++ b/esphome/components/mcp9808/mcp9808.cpp @@ -73,7 +73,6 @@ void MCP9808Sensor::update() { this->publish_state(temp); this->status_clear_warning(); } -float MCP9808Sensor::get_setup_priority() const { return setup_priority::DATA; } } // namespace mcp9808 } // namespace esphome diff --git a/esphome/components/mcp9808/mcp9808.h b/esphome/components/mcp9808/mcp9808.h index 19aa3117c3..894e4599d0 100644 --- a/esphome/components/mcp9808/mcp9808.h +++ b/esphome/components/mcp9808/mcp9808.h @@ -11,7 +11,6 @@ class MCP9808Sensor : public sensor::Sensor, public PollingComponent, public i2c public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; }; diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index b6b4031e16..bccea7d423 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -137,8 +137,6 @@ bool MHZ19Component::mhz19_write_command_(const uint8_t *command, uint8_t *respo return this->read_array(response, MHZ19_RESPONSE_LENGTH); } -float MHZ19Component::get_setup_priority() const { return setup_priority::DATA; } - void MHZ19Component::dump_config() { ESP_LOGCONFIG(TAG, "MH-Z19:"); LOG_SENSOR(" ", "CO2", this->co2_sensor_); diff --git a/esphome/components/mhz19/mhz19.h b/esphome/components/mhz19/mhz19.h index a27f1c31eb..e577b98537 100644 --- a/esphome/components/mhz19/mhz19.h +++ b/esphome/components/mhz19/mhz19.h @@ -22,8 +22,6 @@ enum MHZ19DetectionRange { class MHZ19Component : public PollingComponent, public uart::UARTDevice { public: - float get_setup_priority() const override; - void setup() override; void update() override; void dump_config() override; diff --git a/esphome/components/mics_4514/mics_4514.cpp b/esphome/components/mics_4514/mics_4514.cpp index 8181ece94c..60413b32d7 100644 --- a/esphome/components/mics_4514/mics_4514.cpp +++ b/esphome/components/mics_4514/mics_4514.cpp @@ -37,7 +37,6 @@ void MICS4514Component::dump_config() { LOG_SENSOR(" ", "Hydrogen", this->hydrogen_sensor_); LOG_SENSOR(" ", "Ammonia", this->ammonia_sensor_); } -float MICS4514Component::get_setup_priority() const { return setup_priority::DATA; } void MICS4514Component::update() { if (!this->warmed_up_) { return; diff --git a/esphome/components/mics_4514/mics_4514.h b/esphome/components/mics_4514/mics_4514.h index d2fefc3630..e7271314c8 100644 --- a/esphome/components/mics_4514/mics_4514.h +++ b/esphome/components/mics_4514/mics_4514.h @@ -19,7 +19,6 @@ class MICS4514Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/mlx90393/sensor_mlx90393.cpp b/esphome/components/mlx90393/sensor_mlx90393.cpp index 21a5b3a829..ee52f9b9ab 100644 --- a/esphome/components/mlx90393/sensor_mlx90393.cpp +++ b/esphome/components/mlx90393/sensor_mlx90393.cpp @@ -132,8 +132,6 @@ void MLX90393Cls::dump_config() { LOG_SENSOR(" ", "Temperature", this->t_sensor_); } -float MLX90393Cls::get_setup_priority() const { return setup_priority::DATA; } - void MLX90393Cls::update() { MLX90393::txyz data; diff --git a/esphome/components/mlx90393/sensor_mlx90393.h b/esphome/components/mlx90393/sensor_mlx90393.h index 8a6f3321f9..845ae87e09 100644 --- a/esphome/components/mlx90393/sensor_mlx90393.h +++ b/esphome/components/mlx90393/sensor_mlx90393.h @@ -25,7 +25,6 @@ class MLX90393Cls : public PollingComponent, public i2c::I2CDevice, public MLX90 public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_drdy_gpio(GPIOPin *pin) { drdy_pin_ = pin; } diff --git a/esphome/components/mlx90614/mlx90614.cpp b/esphome/components/mlx90614/mlx90614.cpp index 8e53b9e3c3..8a514cbc26 100644 --- a/esphome/components/mlx90614/mlx90614.cpp +++ b/esphome/components/mlx90614/mlx90614.cpp @@ -71,8 +71,6 @@ void MLX90614Component::dump_config() { LOG_SENSOR(" ", "Object", this->object_sensor_); } -float MLX90614Component::get_setup_priority() const { return setup_priority::DATA; } - void MLX90614Component::update() { uint8_t emissivity[3]; if (this->read_register(MLX90614_EMISSIVITY, emissivity, 3) != i2c::ERROR_OK) { diff --git a/esphome/components/mlx90614/mlx90614.h b/esphome/components/mlx90614/mlx90614.h index fa6fb523bb..bf081c3e90 100644 --- a/esphome/components/mlx90614/mlx90614.h +++ b/esphome/components/mlx90614/mlx90614.h @@ -12,7 +12,6 @@ class MLX90614Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void dump_config() override; void update() override; - float get_setup_priority() const override; void set_ambient_sensor(sensor::Sensor *ambient_sensor) { ambient_sensor_ = ambient_sensor; } void set_object_sensor(sensor::Sensor *object_sensor) { object_sensor_ = object_sensor; } diff --git a/esphome/components/mmc5603/mmc5603.cpp b/esphome/components/mmc5603/mmc5603.cpp index d6321eae8f..1cbc84191f 100644 --- a/esphome/components/mmc5603/mmc5603.cpp +++ b/esphome/components/mmc5603/mmc5603.cpp @@ -91,8 +91,6 @@ void MMC5603Component::dump_config() { LOG_SENSOR(" ", "Heading", this->heading_sensor_); } -float MMC5603Component::get_setup_priority() const { return setup_priority::DATA; } - void MMC5603Component::update() { uint8_t ctrl0 = (this->auto_set_reset_) ? 0x21 : 0x01; if (!this->write_byte(MMC56X3_CTRL0_REG, ctrl0)) { diff --git a/esphome/components/mmc5603/mmc5603.h b/esphome/components/mmc5603/mmc5603.h index 09718bd3b7..f827e27e04 100644 --- a/esphome/components/mmc5603/mmc5603.h +++ b/esphome/components/mmc5603/mmc5603.h @@ -17,7 +17,6 @@ class MMC5603Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_datarate(MMC5603Datarate datarate) { datarate_ = datarate; } diff --git a/esphome/components/mmc5983/mmc5983.cpp b/esphome/components/mmc5983/mmc5983.cpp index 1e0065020c..b038084a72 100644 --- a/esphome/components/mmc5983/mmc5983.cpp +++ b/esphome/components/mmc5983/mmc5983.cpp @@ -133,7 +133,5 @@ void MMC5983Component::dump_config() { LOG_SENSOR(" ", "Z", this->z_sensor_); } -float MMC5983Component::get_setup_priority() const { return setup_priority::DATA; } - } // namespace mmc5983 } // namespace esphome diff --git a/esphome/components/mmc5983/mmc5983.h b/esphome/components/mmc5983/mmc5983.h index d425418904..3e87e54daa 100644 --- a/esphome/components/mmc5983/mmc5983.h +++ b/esphome/components/mmc5983/mmc5983.h @@ -12,7 +12,6 @@ class MMC5983Component : public PollingComponent, public i2c::I2CDevice { void update() override; void setup() override; void dump_config() override; - float get_setup_priority() const override; void set_x_sensor(sensor::Sensor *x_sensor) { x_sensor_ = x_sensor; } void set_y_sensor(sensor::Sensor *y_sensor) { y_sensor_ = y_sensor; } diff --git a/esphome/components/mpu6050/mpu6050.cpp b/esphome/components/mpu6050/mpu6050.cpp index ecbee11c48..91a84d061a 100644 --- a/esphome/components/mpu6050/mpu6050.cpp +++ b/esphome/components/mpu6050/mpu6050.cpp @@ -140,7 +140,6 @@ void MPU6050Component::update() { this->status_clear_warning(); } -float MPU6050Component::get_setup_priority() const { return setup_priority::DATA; } } // namespace mpu6050 } // namespace esphome diff --git a/esphome/components/mpu6050/mpu6050.h b/esphome/components/mpu6050/mpu6050.h index ab410105c0..cc7c3620df 100644 --- a/esphome/components/mpu6050/mpu6050.h +++ b/esphome/components/mpu6050/mpu6050.h @@ -14,8 +14,6 @@ class MPU6050Component : public PollingComponent, public i2c::I2CDevice { void update() override; - float get_setup_priority() const override; - void set_accel_x_sensor(sensor::Sensor *accel_x_sensor) { accel_x_sensor_ = accel_x_sensor; } void set_accel_y_sensor(sensor::Sensor *accel_y_sensor) { accel_y_sensor_ = accel_y_sensor; } void set_accel_z_sensor(sensor::Sensor *accel_z_sensor) { accel_z_sensor_ = accel_z_sensor; } diff --git a/esphome/components/mpu6886/mpu6886.cpp b/esphome/components/mpu6886/mpu6886.cpp index 6fdf7b8684..68b77b59c9 100644 --- a/esphome/components/mpu6886/mpu6886.cpp +++ b/esphome/components/mpu6886/mpu6886.cpp @@ -146,7 +146,5 @@ void MPU6886Component::update() { this->status_clear_warning(); } -float MPU6886Component::get_setup_priority() const { return setup_priority::DATA; } - } // namespace mpu6886 } // namespace esphome diff --git a/esphome/components/mpu6886/mpu6886.h b/esphome/components/mpu6886/mpu6886.h index 04551ae56d..96e2bf61a1 100644 --- a/esphome/components/mpu6886/mpu6886.h +++ b/esphome/components/mpu6886/mpu6886.h @@ -14,8 +14,6 @@ class MPU6886Component : public PollingComponent, public i2c::I2CDevice { void update() override; - float get_setup_priority() const override; - void set_accel_x_sensor(sensor::Sensor *accel_x_sensor) { accel_x_sensor_ = accel_x_sensor; } void set_accel_y_sensor(sensor::Sensor *accel_y_sensor) { accel_y_sensor_ = accel_y_sensor; } void set_accel_z_sensor(sensor::Sensor *accel_z_sensor) { accel_z_sensor_ = accel_z_sensor; } diff --git a/esphome/components/ms5611/ms5611.cpp b/esphome/components/ms5611/ms5611.cpp index 5a7622e783..7ed73400c8 100644 --- a/esphome/components/ms5611/ms5611.cpp +++ b/esphome/components/ms5611/ms5611.cpp @@ -38,7 +38,6 @@ void MS5611Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); } -float MS5611Component::get_setup_priority() const { return setup_priority::DATA; } void MS5611Component::update() { // request temperature reading if (!this->write_bytes(MS5611_CMD_CONV_D2 + 0x08, nullptr, 0)) { diff --git a/esphome/components/ms5611/ms5611.h b/esphome/components/ms5611/ms5611.h index 476db79612..7e4806f319 100644 --- a/esphome/components/ms5611/ms5611.h +++ b/esphome/components/ms5611/ms5611.h @@ -11,7 +11,6 @@ class MS5611Component : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } diff --git a/esphome/components/msa3xx/msa3xx.cpp b/esphome/components/msa3xx/msa3xx.cpp index 56dc919968..e46bfed193 100644 --- a/esphome/components/msa3xx/msa3xx.cpp +++ b/esphome/components/msa3xx/msa3xx.cpp @@ -287,7 +287,6 @@ void MSA3xxComponent::update() { this->status_.never_published = false; this->status_clear_warning(); } -float MSA3xxComponent::get_setup_priority() const { return setup_priority::DATA; } void MSA3xxComponent::set_offset(float offset_x, float offset_y, float offset_z) { this->offset_x_ = offset_x; diff --git a/esphome/components/msa3xx/msa3xx.h b/esphome/components/msa3xx/msa3xx.h index 644109dab0..439d3b5f4d 100644 --- a/esphome/components/msa3xx/msa3xx.h +++ b/esphome/components/msa3xx/msa3xx.h @@ -220,8 +220,6 @@ class MSA3xxComponent : public PollingComponent, public i2c::I2CDevice { void loop() override; void update() override; - float get_setup_priority() const override; - void set_model(Model model) { this->model_ = model; } void set_offset(float offset_x, float offset_y, float offset_z); void set_range(Range range) { this->range_ = range; } diff --git a/esphome/components/nau7802/nau7802.cpp b/esphome/components/nau7802/nau7802.cpp index 5edbc79862..937239b98d 100644 --- a/esphome/components/nau7802/nau7802.cpp +++ b/esphome/components/nau7802/nau7802.cpp @@ -296,8 +296,6 @@ void NAU7802Sensor::loop() { } } -float NAU7802Sensor::get_setup_priority() const { return setup_priority::DATA; } - void NAU7802Sensor::update() { if (!this->is_data_ready_()) { ESP_LOGW(TAG, "No measurements ready!"); diff --git a/esphome/components/nau7802/nau7802.h b/esphome/components/nau7802/nau7802.h index 05452851ca..ae39e167a4 100644 --- a/esphome/components/nau7802/nau7802.h +++ b/esphome/components/nau7802/nau7802.h @@ -62,7 +62,6 @@ class NAU7802Sensor : public sensor::Sensor, public PollingComponent, public i2c void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index e57a258edb..fd6ce0a24b 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -193,7 +193,6 @@ void Nextion::dump_config() { #endif } -float Nextion::get_setup_priority() const { return setup_priority::DATA; } void Nextion::update() { if (!this->is_setup()) { return; diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index c543e14bfe..c42ddba9b5 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1048,7 +1048,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void setup() override; void set_brightness(float brightness) { this->brightness_ = brightness; } - float get_setup_priority() const override; void update() override; void loop() override; void set_writer(const nextion_writer_t &writer); diff --git a/esphome/components/npi19/npi19.cpp b/esphome/components/npi19/npi19.cpp index c531d2ec8f..995abdff37 100644 --- a/esphome/components/npi19/npi19.cpp +++ b/esphome/components/npi19/npi19.cpp @@ -29,8 +29,6 @@ void NPI19Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); } -float NPI19Component::get_setup_priority() const { return setup_priority::DATA; } - i2c::ErrorCode NPI19Component::read_(uint16_t &raw_temperature, uint16_t &raw_pressure) { // initiate data read from device i2c::ErrorCode w_err = write(&READ_COMMAND, sizeof(READ_COMMAND)); diff --git a/esphome/components/npi19/npi19.h b/esphome/components/npi19/npi19.h index df289dffc1..8e6a8e3bfa 100644 --- a/esphome/components/npi19/npi19.h +++ b/esphome/components/npi19/npi19.h @@ -15,7 +15,6 @@ class NPI19Component : public PollingComponent, public i2c::I2CDevice { this->raw_pressure_sensor_ = raw_pressure_sensor; } - float get_setup_priority() const override; void setup() override; void dump_config() override; void update() override; diff --git a/esphome/components/ntc/ntc.cpp b/esphome/components/ntc/ntc.cpp index cc500ba429..e2097bdd77 100644 --- a/esphome/components/ntc/ntc.cpp +++ b/esphome/components/ntc/ntc.cpp @@ -12,7 +12,6 @@ void NTC::setup() { this->process_(this->sensor_->state); } void NTC::dump_config() { LOG_SENSOR("", "NTC Sensor", this); } -float NTC::get_setup_priority() const { return setup_priority::DATA; } void NTC::process_(float value) { if (std::isnan(value)) { this->publish_state(NAN); diff --git a/esphome/components/ntc/ntc.h b/esphome/components/ntc/ntc.h index c8592e0fe8..a0c72340de 100644 --- a/esphome/components/ntc/ntc.h +++ b/esphome/components/ntc/ntc.h @@ -14,7 +14,6 @@ class NTC : public Component, public sensor::Sensor { void set_c(double c) { c_ = c; } void setup() override; void dump_config() override; - float get_setup_priority() const override; protected: void process_(float value); diff --git a/esphome/components/opt3001/opt3001.cpp b/esphome/components/opt3001/opt3001.cpp index f5f7ab9412..a942e45035 100644 --- a/esphome/components/opt3001/opt3001.cpp +++ b/esphome/components/opt3001/opt3001.cpp @@ -116,7 +116,5 @@ void OPT3001Sensor::update() { }); } -float OPT3001Sensor::get_setup_priority() const { return setup_priority::DATA; } - } // namespace opt3001 } // namespace esphome diff --git a/esphome/components/opt3001/opt3001.h b/esphome/components/opt3001/opt3001.h index ae3fde5c54..3bce9f0aeb 100644 --- a/esphome/components/opt3001/opt3001.h +++ b/esphome/components/opt3001/opt3001.h @@ -12,7 +12,6 @@ class OPT3001Sensor : public sensor::Sensor, public PollingComponent, public i2c public: void dump_config() override; void update() override; - float get_setup_priority() const override; protected: // checks if one-shot is complete before reading the result and returning it diff --git a/esphome/components/pcf85063/pcf85063.cpp b/esphome/components/pcf85063/pcf85063.cpp index f38b60b55d..03ed78654f 100644 --- a/esphome/components/pcf85063/pcf85063.cpp +++ b/esphome/components/pcf85063/pcf85063.cpp @@ -26,8 +26,6 @@ void PCF85063Component::dump_config() { RealTimeClock::dump_config(); } -float PCF85063Component::get_setup_priority() const { return setup_priority::DATA; } - void PCF85063Component::read_time() { if (!this->read_rtc_()) { return; diff --git a/esphome/components/pcf85063/pcf85063.h b/esphome/components/pcf85063/pcf85063.h index b7034d4f00..697837f223 100644 --- a/esphome/components/pcf85063/pcf85063.h +++ b/esphome/components/pcf85063/pcf85063.h @@ -12,7 +12,6 @@ class PCF85063Component : public time::RealTimeClock, public i2c::I2CDevice { void setup() override; void update() override; void dump_config() override; - float get_setup_priority() const override; void read_time(); void write_time(); diff --git a/esphome/components/pcf8563/pcf8563.cpp b/esphome/components/pcf8563/pcf8563.cpp index 2090936bb6..dc68807aef 100644 --- a/esphome/components/pcf8563/pcf8563.cpp +++ b/esphome/components/pcf8563/pcf8563.cpp @@ -26,8 +26,6 @@ void PCF8563Component::dump_config() { RealTimeClock::dump_config(); } -float PCF8563Component::get_setup_priority() const { return setup_priority::DATA; } - void PCF8563Component::read_time() { if (!this->read_rtc_()) { return; diff --git a/esphome/components/pcf8563/pcf8563.h b/esphome/components/pcf8563/pcf8563.h index 81aa816b42..cd37d05816 100644 --- a/esphome/components/pcf8563/pcf8563.h +++ b/esphome/components/pcf8563/pcf8563.h @@ -12,7 +12,6 @@ class PCF8563Component : public time::RealTimeClock, public i2c::I2CDevice { void setup() override; void update() override; void dump_config() override; - float get_setup_priority() const override; void read_time(); void write_time(); diff --git a/esphome/components/pm1006/pm1006.cpp b/esphome/components/pm1006/pm1006.cpp index c466c4bb25..fe8890e777 100644 --- a/esphome/components/pm1006/pm1006.cpp +++ b/esphome/components/pm1006/pm1006.cpp @@ -44,8 +44,6 @@ void PM1006Component::loop() { } } -float PM1006Component::get_setup_priority() const { return setup_priority::DATA; } - uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const { uint8_t sum = 0; for (uint8_t i = 0; i < length; i++) { diff --git a/esphome/components/pm1006/pm1006.h b/esphome/components/pm1006/pm1006.h index 98637dad71..6b6332e1e3 100644 --- a/esphome/components/pm1006/pm1006.h +++ b/esphome/components/pm1006/pm1006.h @@ -18,8 +18,6 @@ class PM1006Component : public PollingComponent, public uart::UARTDevice { void loop() override; void update() override; - float get_setup_priority() const override; - protected: optional check_byte_() const; void parse_data_(); diff --git a/esphome/components/pm2005/pm2005.h b/esphome/components/pm2005/pm2005.h index 219fbae5cb..e788569b7e 100644 --- a/esphome/components/pm2005/pm2005.h +++ b/esphome/components/pm2005/pm2005.h @@ -14,8 +14,6 @@ enum SensorType { class PM2005Component : public PollingComponent, public i2c::I2CDevice { public: - float get_setup_priority() const override { return esphome::setup_priority::DATA; } - void set_sensor_type(SensorType sensor_type) { this->sensor_type_ = sensor_type; } void set_pm_1_0_sensor(sensor::Sensor *pm_1_0_sensor) { this->pm_1_0_sensor_ = pm_1_0_sensor; } diff --git a/esphome/components/pmwcs3/pmwcs3.cpp b/esphome/components/pmwcs3/pmwcs3.cpp index 95638851b5..2ed7789c53 100644 --- a/esphome/components/pmwcs3/pmwcs3.cpp +++ b/esphome/components/pmwcs3/pmwcs3.cpp @@ -53,8 +53,6 @@ void PMWCS3Component::water_calibration() { void PMWCS3Component::update() { this->read_data_(); } -float PMWCS3Component::get_setup_priority() const { return setup_priority::DATA; } - void PMWCS3Component::dump_config() { ESP_LOGCONFIG(TAG, "PMWCS3"); LOG_I2C_DEVICE(this); diff --git a/esphome/components/pmwcs3/pmwcs3.h b/esphome/components/pmwcs3/pmwcs3.h index d63c516586..b1e26eec4f 100644 --- a/esphome/components/pmwcs3/pmwcs3.h +++ b/esphome/components/pmwcs3/pmwcs3.h @@ -14,7 +14,6 @@ class PMWCS3Component : public PollingComponent, public i2c::I2CDevice { public: void update() override; void dump_config() override; - float get_setup_priority() const override; void set_e25_sensor(sensor::Sensor *e25_sensor) { e25_sensor_ = e25_sensor; } void set_ec_sensor(sensor::Sensor *ec_sensor) { ec_sensor_ = ec_sensor; } diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index 733810c242..5366aab54e 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -426,8 +426,6 @@ bool PN532::write_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message) { return false; } -float PN532::get_setup_priority() const { return setup_priority::DATA; } - void PN532::dump_config() { ESP_LOGCONFIG(TAG, "PN532:"); switch (this->error_code_) { diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index 488ec4af3b..73a6c15164 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -35,7 +35,6 @@ class PN532 : public PollingComponent { void dump_config() override; void update() override; - float get_setup_priority() const override; void loop() override; void on_powerdown() override { powerdown(); } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 9a7630a7be..007deb66e5 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -125,8 +125,6 @@ void PulseMeterSensor::loop() { } } -float PulseMeterSensor::get_setup_priority() const { return setup_priority::DATA; } - void PulseMeterSensor::dump_config() { LOG_SENSOR("", "Pulse Meter", this); LOG_PIN(" Pin: ", this->pin_); diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index 748bab29ac..5800c4ec42 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -27,7 +27,6 @@ class PulseMeterSensor : public sensor::Sensor, public Component { void setup() override; void loop() override; - float get_setup_priority() const override; void dump_config() override; protected: diff --git a/esphome/components/pylontech/pylontech.cpp b/esphome/components/pylontech/pylontech.cpp index 61b5356c90..1dc7caaf16 100644 --- a/esphome/components/pylontech/pylontech.cpp +++ b/esphome/components/pylontech/pylontech.cpp @@ -192,8 +192,6 @@ void PylontechComponent::process_line_(std::string &buffer) { } } -float PylontechComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace pylontech } // namespace esphome diff --git a/esphome/components/pylontech/pylontech.h b/esphome/components/pylontech/pylontech.h index 10c669ad9a..5727928a60 100644 --- a/esphome/components/pylontech/pylontech.h +++ b/esphome/components/pylontech/pylontech.h @@ -34,8 +34,6 @@ class PylontechComponent : public PollingComponent, public uart::UARTDevice { void setup() override; void dump_config() override; - float get_setup_priority() const override; - void register_listener(PylontechListener *listener) { this->listeners_.push_back(listener); } protected: diff --git a/esphome/components/qmc5883l/qmc5883l.cpp b/esphome/components/qmc5883l/qmc5883l.cpp index 693614581c..bc2adb5cfe 100644 --- a/esphome/components/qmc5883l/qmc5883l.cpp +++ b/esphome/components/qmc5883l/qmc5883l.cpp @@ -86,8 +86,6 @@ void QMC5883LComponent::dump_config() { LOG_PIN(" DRDY Pin: ", this->drdy_pin_); } -float QMC5883LComponent::get_setup_priority() const { return setup_priority::DATA; } - void QMC5883LComponent::update() { i2c::ErrorCode err; uint8_t status = false; diff --git a/esphome/components/qmc5883l/qmc5883l.h b/esphome/components/qmc5883l/qmc5883l.h index 5ba7180e23..21ef9c2a17 100644 --- a/esphome/components/qmc5883l/qmc5883l.h +++ b/esphome/components/qmc5883l/qmc5883l.h @@ -31,7 +31,6 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice { public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_drdy_pin(GPIOPin *pin) { drdy_pin_ = pin; } diff --git a/esphome/components/rd03d/rd03d.h b/esphome/components/rd03d/rd03d.h index 7413fe38f2..8bf7b423be 100644 --- a/esphome/components/rd03d/rd03d.h +++ b/esphome/components/rd03d/rd03d.h @@ -42,7 +42,6 @@ class RD03DComponent : public Component, public uart::UARTDevice { void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } #ifdef USE_SENSOR void set_target_count_sensor(sensor::Sensor *sensor) { this->target_count_sensor_ = sensor; } diff --git a/esphome/components/resampler/speaker/resampler_speaker.h b/esphome/components/resampler/speaker/resampler_speaker.h index 51790069d2..810087ab7f 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.h +++ b/esphome/components/resampler/speaker/resampler_speaker.h @@ -16,7 +16,6 @@ namespace resampler { class ResamplerSpeaker : public Component, public speaker::Speaker { public: - float get_setup_priority() const override { return esphome::setup_priority::DATA; } void setup() override; void loop() override; diff --git a/esphome/components/rotary_encoder/rotary_encoder.cpp b/esphome/components/rotary_encoder/rotary_encoder.cpp index c652944120..38fd14375d 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.cpp +++ b/esphome/components/rotary_encoder/rotary_encoder.cpp @@ -235,7 +235,6 @@ void RotaryEncoderSensor::loop() { } } -float RotaryEncoderSensor::get_setup_priority() const { return setup_priority::DATA; } void RotaryEncoderSensor::set_restore_mode(RotaryEncoderRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } diff --git a/esphome/components/rotary_encoder/rotary_encoder.h b/esphome/components/rotary_encoder/rotary_encoder.h index 14442f0565..865554cd4d 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.h +++ b/esphome/components/rotary_encoder/rotary_encoder.h @@ -82,8 +82,6 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { void dump_config() override; void loop() override; - float get_setup_priority() const override; - void add_on_clockwise_callback(std::function callback) { this->on_clockwise_callback_.add(std::move(callback)); } diff --git a/esphome/components/rx8130/rx8130.h b/esphome/components/rx8130/rx8130.h index 6694c763cd..979da3e19c 100644 --- a/esphome/components/rx8130/rx8130.h +++ b/esphome/components/rx8130/rx8130.h @@ -14,8 +14,6 @@ class RX8130Component : public time::RealTimeClock, public i2c::I2CDevice { void dump_config() override; void read_time(); void write_time(); - /// Ensure RTC is initialized at the correct time in the setup sequence - float get_setup_priority() const override { return setup_priority::DATA; } protected: void stop_(bool stop); diff --git a/esphome/components/sdp3x/sdp3x.cpp b/esphome/components/sdp3x/sdp3x.cpp index d4ab04e7cd..6f6cc1ebd8 100644 --- a/esphome/components/sdp3x/sdp3x.cpp +++ b/esphome/components/sdp3x/sdp3x.cpp @@ -114,7 +114,5 @@ void SDP3XComponent::read_pressure_() { this->status_clear_warning(); } -float SDP3XComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace sdp3x } // namespace esphome diff --git a/esphome/components/sdp3x/sdp3x.h b/esphome/components/sdp3x/sdp3x.h index e3d3533c74..afb58d47c8 100644 --- a/esphome/components/sdp3x/sdp3x.h +++ b/esphome/components/sdp3x/sdp3x.h @@ -17,7 +17,6 @@ class SDP3XComponent : public PollingComponent, public sensirion_common::Sensiri void setup() override; void dump_config() override; - float get_setup_priority() const override; void set_measurement_mode(MeasurementMode mode) { measurement_mode_ = mode; } protected: diff --git a/esphome/components/sds011/sds011.cpp b/esphome/components/sds011/sds011.cpp index 4e12c0e322..cdfd7544ad 100644 --- a/esphome/components/sds011/sds011.cpp +++ b/esphome/components/sds011/sds011.cpp @@ -108,8 +108,6 @@ void SDS011Component::loop() { } } -float SDS011Component::get_setup_priority() const { return setup_priority::DATA; } - void SDS011Component::set_rx_mode_only(bool rx_mode_only) { this->rx_mode_only_ = rx_mode_only; } void SDS011Component::sds011_write_command_(const uint8_t *command_data) { diff --git a/esphome/components/sds011/sds011.h b/esphome/components/sds011/sds011.h index 1f404601b1..3be74e66d1 100644 --- a/esphome/components/sds011/sds011.h +++ b/esphome/components/sds011/sds011.h @@ -21,8 +21,6 @@ class SDS011Component : public Component, public uart::UARTDevice { void dump_config() override; void loop() override; - float get_setup_priority() const override; - void set_update_interval(uint32_t val) { /* ignore */ } void set_update_interval_min(uint8_t update_interval_min); diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index d473df43c7..bd3dec6fb8 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -72,8 +72,6 @@ void SHT3XDComponent::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float SHT3XDComponent::get_setup_priority() const { return setup_priority::DATA; } - void SHT3XDComponent::update() { if (this->status_has_warning()) { ESP_LOGD(TAG, "Retrying to reconnect the sensor."); diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index 74f155121b..43f1a4d8e2 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -17,7 +17,6 @@ class SHT3XDComponent : public PollingComponent, public sensirion_common::Sensir void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_heater_enabled(bool heater_enabled) { heater_enabled_ = heater_enabled; } diff --git a/esphome/components/shtcx/shtcx.cpp b/esphome/components/shtcx/shtcx.cpp index aca305b88d..ec12a5babd 100644 --- a/esphome/components/shtcx/shtcx.cpp +++ b/esphome/components/shtcx/shtcx.cpp @@ -63,8 +63,6 @@ void SHTCXComponent::dump_config() { LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } -float SHTCXComponent::get_setup_priority() const { return setup_priority::DATA; } - void SHTCXComponent::update() { if (this->status_has_warning()) { ESP_LOGW(TAG, "Retrying communication"); diff --git a/esphome/components/shtcx/shtcx.h b/esphome/components/shtcx/shtcx.h index 084d3bfc35..f9778dce8d 100644 --- a/esphome/components/shtcx/shtcx.h +++ b/esphome/components/shtcx/shtcx.h @@ -17,7 +17,6 @@ class SHTCXComponent : public PollingComponent, public sensirion_common::Sensiri void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void soft_reset(); void sleep(); diff --git a/esphome/components/smt100/smt100.cpp b/esphome/components/smt100/smt100.cpp index c8dfb4c7bd..1bcb964264 100644 --- a/esphome/components/smt100/smt100.cpp +++ b/esphome/components/smt100/smt100.cpp @@ -44,8 +44,6 @@ void SMT100Component::loop() { } } -float SMT100Component::get_setup_priority() const { return setup_priority::DATA; } - void SMT100Component::dump_config() { ESP_LOGCONFIG(TAG, "SMT100:"); diff --git a/esphome/components/smt100/smt100.h b/esphome/components/smt100/smt100.h index 86827607dc..df8803e1c6 100644 --- a/esphome/components/smt100/smt100.h +++ b/esphome/components/smt100/smt100.h @@ -17,8 +17,6 @@ class SMT100Component : public PollingComponent, public uart::UARTDevice { void loop() override; void update() override; - float get_setup_priority() const override; - void set_counts_sensor(sensor::Sensor *counts_sensor) { this->counts_sensor_ = counts_sensor; } void set_permittivity_sensor(sensor::Sensor *permittivity_sensor) { this->permittivity_sensor_ = permittivity_sensor; diff --git a/esphome/components/sonoff_d1/sonoff_d1.h b/esphome/components/sonoff_d1/sonoff_d1.h index 19ff83f378..20bea23287 100644 --- a/esphome/components/sonoff_d1/sonoff_d1.h +++ b/esphome/components/sonoff_d1/sonoff_d1.h @@ -53,7 +53,6 @@ class SonoffD1Output : public light::LightOutput, public uart::UARTDevice, publi void setup() override{}; void loop() override; void dump_config() override; - float get_setup_priority() const override { return esphome::setup_priority::DATA; } // Custom methods void set_use_rm433_remote(const bool use_rm433_remote) { this->use_rm433_remote_ = use_rm433_remote; } diff --git a/esphome/components/spi_device/spi_device.cpp b/esphome/components/spi_device/spi_device.cpp index 4cc7286ba9..34f83027db 100644 --- a/esphome/components/spi_device/spi_device.cpp +++ b/esphome/components/spi_device/spi_device.cpp @@ -23,7 +23,5 @@ void SPIDeviceComponent::dump_config() { } } -float SPIDeviceComponent::get_setup_priority() const { return setup_priority::DATA; } - } // namespace spi_device } // namespace esphome diff --git a/esphome/components/spi_device/spi_device.h b/esphome/components/spi_device/spi_device.h index d8aef440a7..e3aa74aaf0 100644 --- a/esphome/components/spi_device/spi_device.h +++ b/esphome/components/spi_device/spi_device.h @@ -13,8 +13,6 @@ class SPIDeviceComponent : public Component, void setup() override; void dump_config() override; - float get_setup_priority() const override; - protected: }; diff --git a/esphome/components/sts3x/sts3x.cpp b/esphome/components/sts3x/sts3x.cpp index eee2aca73e..8713b0b6b8 100644 --- a/esphome/components/sts3x/sts3x.cpp +++ b/esphome/components/sts3x/sts3x.cpp @@ -41,7 +41,7 @@ void STS3XComponent::dump_config() { LOG_SENSOR(" ", "STS3x", this); } -float STS3XComponent::get_setup_priority() const { return setup_priority::DATA; } + void STS3XComponent::update() { if (this->status_has_warning()) { ESP_LOGD(TAG, "Retrying to reconnect the sensor."); diff --git a/esphome/components/sts3x/sts3x.h b/esphome/components/sts3x/sts3x.h index 8f806a3471..6c1dd2b244 100644 --- a/esphome/components/sts3x/sts3x.h +++ b/esphome/components/sts3x/sts3x.h @@ -14,7 +14,6 @@ class STS3XComponent : public sensor::Sensor, public PollingComponent, public se public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; }; diff --git a/esphome/components/sy6970/sy6970.h b/esphome/components/sy6970/sy6970.h index bacc072f9b..2225dd781b 100644 --- a/esphome/components/sy6970/sy6970.h +++ b/esphome/components/sy6970/sy6970.h @@ -87,7 +87,6 @@ class SY6970Component : public PollingComponent, public i2c::I2CDevice { void setup() override; void dump_config() override; void update() override; - float get_setup_priority() const override { return setup_priority::DATA; } // Listener registration void add_listener(SY6970Listener *listener) { this->listeners_.push_back(listener); } diff --git a/esphome/components/t6615/t6615.cpp b/esphome/components/t6615/t6615.cpp index c2ac88ee2e..75f9ed108e 100644 --- a/esphome/components/t6615/t6615.cpp +++ b/esphome/components/t6615/t6615.cpp @@ -86,7 +86,6 @@ void T6615Component::query_ppm_() { this->send_ppm_command_(); } -float T6615Component::get_setup_priority() const { return setup_priority::DATA; } void T6615Component::dump_config() { ESP_LOGCONFIG(TAG, "T6615:"); LOG_SENSOR(" ", "CO2", this->co2_sensor_); diff --git a/esphome/components/t6615/t6615.h b/esphome/components/t6615/t6615.h index fb53032e8d..69c406a5ba 100644 --- a/esphome/components/t6615/t6615.h +++ b/esphome/components/t6615/t6615.h @@ -22,8 +22,6 @@ enum class T6615Command : uint8_t { class T6615Component : public PollingComponent, public uart::UARTDevice { public: - float get_setup_priority() const override; - void loop() override; void update() override; void dump_config() override; diff --git a/esphome/components/tc74/tc74.cpp b/esphome/components/tc74/tc74.cpp index abf3839e00..969ef3671e 100644 --- a/esphome/components/tc74/tc74.cpp +++ b/esphome/components/tc74/tc74.cpp @@ -61,7 +61,5 @@ void TC74Component::read_temperature_() { this->status_clear_warning(); } -float TC74Component::get_setup_priority() const { return setup_priority::DATA; } - } // namespace tc74 } // namespace esphome diff --git a/esphome/components/tc74/tc74.h b/esphome/components/tc74/tc74.h index 5d70c05420..f3ce225ff4 100644 --- a/esphome/components/tc74/tc74.h +++ b/esphome/components/tc74/tc74.h @@ -15,8 +15,6 @@ class TC74Component : public PollingComponent, public i2c::I2CDevice, public sen /// Update the sensor value (temperature). void update() override; - float get_setup_priority() const override; - protected: /// Internal method to read the temperature from the component after it has been scheduled. void read_temperature_(); diff --git a/esphome/components/tcs34725/tcs34725.cpp b/esphome/components/tcs34725/tcs34725.cpp index e4e5547595..4fe87de0ca 100644 --- a/esphome/components/tcs34725/tcs34725.cpp +++ b/esphome/components/tcs34725/tcs34725.cpp @@ -56,7 +56,6 @@ void TCS34725Component::dump_config() { LOG_SENSOR(" ", "Illuminance", this->illuminance_sensor_); LOG_SENSOR(" ", "Color Temperature", this->color_temperature_sensor_); } -float TCS34725Component::get_setup_priority() const { return setup_priority::DATA; } /*! * @brief Converts the raw R/G/B values to color temperature in degrees diff --git a/esphome/components/tcs34725/tcs34725.h b/esphome/components/tcs34725/tcs34725.h index 23985e8221..85bb383e4b 100644 --- a/esphome/components/tcs34725/tcs34725.h +++ b/esphome/components/tcs34725/tcs34725.h @@ -52,7 +52,6 @@ class TCS34725Component : public PollingComponent, public i2c::I2CDevice { } void setup() override; - float get_setup_priority() const override; void update() override; void dump_config() override; diff --git a/esphome/components/tee501/tee501.cpp b/esphome/components/tee501/tee501.cpp index 06481b628b..00a62247f9 100644 --- a/esphome/components/tee501/tee501.cpp +++ b/esphome/components/tee501/tee501.cpp @@ -43,7 +43,6 @@ void TEE501Component::dump_config() { LOG_SENSOR(" ", "TEE501", this); } -float TEE501Component::get_setup_priority() const { return setup_priority::DATA; } void TEE501Component::update() { uint8_t address_1[] = {0x2C, 0x1B}; this->write(address_1, 2); diff --git a/esphome/components/tee501/tee501.h b/esphome/components/tee501/tee501.h index 2437ac92eb..62a6f1c944 100644 --- a/esphome/components/tee501/tee501.h +++ b/esphome/components/tee501/tee501.h @@ -12,7 +12,6 @@ class TEE501Component : public sensor::Sensor, public PollingComponent, public i public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; protected: diff --git a/esphome/components/tem3200/tem3200.cpp b/esphome/components/tem3200/tem3200.cpp index b31496142c..9c305f8f6f 100644 --- a/esphome/components/tem3200/tem3200.cpp +++ b/esphome/components/tem3200/tem3200.cpp @@ -51,8 +51,6 @@ void TEM3200Component::dump_config() { LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); } -float TEM3200Component::get_setup_priority() const { return setup_priority::DATA; } - i2c::ErrorCode TEM3200Component::read_(uint8_t &status, uint16_t &raw_temperature, uint16_t &raw_pressure) { uint8_t response[4] = {0x00, 0x00, 0x00, 0x00}; diff --git a/esphome/components/tem3200/tem3200.h b/esphome/components/tem3200/tem3200.h index c84a2aba21..37589b2a06 100644 --- a/esphome/components/tem3200/tem3200.h +++ b/esphome/components/tem3200/tem3200.h @@ -15,7 +15,6 @@ class TEM3200Component : public PollingComponent, public i2c::I2CDevice { this->raw_pressure_sensor_ = raw_pressure_sensor; } - float get_setup_priority() const override; void setup() override; void dump_config() override; void update() override; diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/time_based_cover.cpp index 0aef4b8e85..f6a3048bd4 100644 --- a/esphome/components/time_based/time_based_cover.cpp +++ b/esphome/components/time_based/time_based_cover.cpp @@ -51,7 +51,7 @@ void TimeBasedCover::loop() { this->last_publish_time_ = now; } } -float TimeBasedCover::get_setup_priority() const { return setup_priority::DATA; } + CoverTraits TimeBasedCover::get_traits() { auto traits = CoverTraits(); traits.set_supports_stop(true); diff --git a/esphome/components/time_based/time_based_cover.h b/esphome/components/time_based/time_based_cover.h index d2457cae7a..0adc5cb370 100644 --- a/esphome/components/time_based/time_based_cover.h +++ b/esphome/components/time_based/time_based_cover.h @@ -12,7 +12,6 @@ class TimeBasedCover : public cover::Cover, public Component { void setup() override; void loop() override; void dump_config() override; - float get_setup_priority() const override; Trigger<> *get_open_trigger() { return &this->open_trigger_; } Trigger<> *get_close_trigger() { return &this->close_trigger_; } diff --git a/esphome/components/tmp102/tmp102.cpp b/esphome/components/tmp102/tmp102.cpp index 7390d9fcc9..99f6753ddc 100644 --- a/esphome/components/tmp102/tmp102.cpp +++ b/esphome/components/tmp102/tmp102.cpp @@ -46,7 +46,5 @@ void TMP102Component::update() { }); } -float TMP102Component::get_setup_priority() const { return setup_priority::DATA; } - } // namespace tmp102 } // namespace esphome diff --git a/esphome/components/tmp102/tmp102.h b/esphome/components/tmp102/tmp102.h index 657b48c7cf..fe860a3819 100644 --- a/esphome/components/tmp102/tmp102.h +++ b/esphome/components/tmp102/tmp102.h @@ -11,8 +11,6 @@ class TMP102Component : public PollingComponent, public i2c::I2CDevice, public s public: void dump_config() override; void update() override; - - float get_setup_priority() const override; }; } // namespace tmp102 diff --git a/esphome/components/tmp117/tmp117.cpp b/esphome/components/tmp117/tmp117.cpp index c9eff41399..f8f52266e0 100644 --- a/esphome/components/tmp117/tmp117.cpp +++ b/esphome/components/tmp117/tmp117.cpp @@ -45,7 +45,7 @@ void TMP117Component::dump_config() { } LOG_SENSOR(" ", "Temperature", this); } -float TMP117Component::get_setup_priority() const { return setup_priority::DATA; } + bool TMP117Component::read_data_(int16_t *data) { if (!this->read_byte_16(0, (uint16_t *) data)) { ESP_LOGW(TAG, "Updating TMP117 failed!"); diff --git a/esphome/components/tmp117/tmp117.h b/esphome/components/tmp117/tmp117.h index 162dbb64db..f501ee270c 100644 --- a/esphome/components/tmp117/tmp117.h +++ b/esphome/components/tmp117/tmp117.h @@ -11,7 +11,6 @@ class TMP117Component : public PollingComponent, public i2c::I2CDevice, public s public: void setup() override; void dump_config() override; - float get_setup_priority() const override; void update() override; void set_config(uint16_t config) { config_ = config; }; diff --git a/esphome/components/tsl2561/tsl2561.cpp b/esphome/components/tsl2561/tsl2561.cpp index 1442dd176c..cb4c38a83c 100644 --- a/esphome/components/tsl2561/tsl2561.cpp +++ b/esphome/components/tsl2561/tsl2561.cpp @@ -144,7 +144,7 @@ void TSL2561Sensor::set_integration_time(TSL2561IntegrationTime integration_time } void TSL2561Sensor::set_gain(TSL2561Gain gain) { this->gain_ = gain; } void TSL2561Sensor::set_is_cs_package(bool package_cs) { this->package_cs_ = package_cs; } -float TSL2561Sensor::get_setup_priority() const { return setup_priority::DATA; } + bool TSL2561Sensor::tsl2561_write_byte(uint8_t a_register, uint8_t value) { return this->write_byte(a_register | TSL2561_COMMAND_BIT, value); } diff --git a/esphome/components/tsl2561/tsl2561.h b/esphome/components/tsl2561/tsl2561.h index c54f41fb81..a8f0aef90f 100644 --- a/esphome/components/tsl2561/tsl2561.h +++ b/esphome/components/tsl2561/tsl2561.h @@ -67,7 +67,6 @@ class TSL2561Sensor : public sensor::Sensor, public PollingComponent, public i2c void setup() override; void dump_config() override; void update() override; - float get_setup_priority() const override; bool tsl2561_read_byte(uint8_t a_register, uint8_t *value); bool tsl2561_read_uint(uint8_t a_register, uint16_t *value); diff --git a/esphome/components/tsl2591/tsl2591.cpp b/esphome/components/tsl2591/tsl2591.cpp index 999e42e949..42c524a074 100644 --- a/esphome/components/tsl2591/tsl2591.cpp +++ b/esphome/components/tsl2591/tsl2591.cpp @@ -247,8 +247,6 @@ void TSL2591Component::set_power_save_mode(bool enable) { this->power_save_mode_ void TSL2591Component::set_name(const char *name) { this->name_ = name; } -float TSL2591Component::get_setup_priority() const { return setup_priority::DATA; } - bool TSL2591Component::is_adc_valid() { uint8_t status; if (!this->read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_STATUS, &status)) { diff --git a/esphome/components/tsl2591/tsl2591.h b/esphome/components/tsl2591/tsl2591.h index fa302b14b0..84c92b6ba9 100644 --- a/esphome/components/tsl2591/tsl2591.h +++ b/esphome/components/tsl2591/tsl2591.h @@ -249,8 +249,6 @@ class TSL2591Component : public PollingComponent, public i2c::I2CDevice { void dump_config() override; /** Used by ESPHome framework. */ void update() override; - /** Used by ESPHome framework. */ - float get_setup_priority() const override; protected: const char *name_; diff --git a/esphome/components/tx20/tx20.cpp b/esphome/components/tx20/tx20.cpp index a6df61c053..6bc5f0bb51 100644 --- a/esphome/components/tx20/tx20.cpp +++ b/esphome/components/tx20/tx20.cpp @@ -38,8 +38,6 @@ void Tx20Component::loop() { } } -float Tx20Component::get_setup_priority() const { return setup_priority::DATA; } - std::string Tx20Component::get_wind_cardinal_direction() const { return this->wind_cardinal_direction_; } void Tx20Component::decode_and_publish_() { diff --git a/esphome/components/tx20/tx20.h b/esphome/components/tx20/tx20.h index 95a9517227..d1673f99f2 100644 --- a/esphome/components/tx20/tx20.h +++ b/esphome/components/tx20/tx20.h @@ -35,7 +35,6 @@ class Tx20Component : public Component { void setup() override; void dump_config() override; - float get_setup_priority() const override; void loop() override; protected: diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index a38737aff5..541f7d2b70 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -29,8 +29,6 @@ class UltrasonicSensorComponent : public sensor::Sensor, public PollingComponent void dump_config() override; void update() override; - float get_setup_priority() const override { return setup_priority::DATA; } - /// Set the maximum time in µs to wait for the echo to return void set_timeout_us(uint32_t timeout_us) { this->timeout_us_ = timeout_us; } /// Set the time in µs the trigger pin should be enabled for in µs, defaults to 10µs (for HC-SR04) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 584b8abfb2..2e5686008b 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -32,7 +32,6 @@ void VersionTextSensor::setup() { version_str[sizeof(version_str) - 1] = '\0'; this->publish_state(version_str); } -float VersionTextSensor::get_setup_priority() const { return setup_priority::DATA; } void VersionTextSensor::set_hide_timestamp(bool hide_timestamp) { this->hide_timestamp_ = hide_timestamp; } void VersionTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Version Text Sensor", this); } diff --git a/esphome/components/version/version_text_sensor.h b/esphome/components/version/version_text_sensor.h index 6813da7830..b7d8001120 100644 --- a/esphome/components/version/version_text_sensor.h +++ b/esphome/components/version/version_text_sensor.h @@ -11,7 +11,6 @@ class VersionTextSensor : public text_sensor::TextSensor, public Component { void set_hide_timestamp(bool hide_timestamp); void setup() override; void dump_config() override; - float get_setup_priority() const override; protected: bool hide_timestamp_{false}; diff --git a/esphome/components/wts01/wts01.h b/esphome/components/wts01/wts01.h index 298595a5d6..aae90c2c77 100644 --- a/esphome/components/wts01/wts01.h +++ b/esphome/components/wts01/wts01.h @@ -13,7 +13,6 @@ class WTS01Sensor : public sensor::Sensor, public uart::UARTDevice, public Compo public: void loop() override; void dump_config() override; - float get_setup_priority() const override { return setup_priority::DATA; } protected: uint8_t buffer_[PACKET_SIZE]; From 4a579700a014f7beb2caebb93a21e64da23d5ff1 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 5 Feb 2026 06:52:14 +1100 Subject: [PATCH 0518/2030] [cover] Add operation-based triggers and fix repeated trigger firing (#13471) --- esphome/components/cover/__init__.py | 83 ++++++++++++++++------ esphome/components/cover/automation.h | 53 ++++++++------ esphome/components/cover/cover.cpp | 3 - esphome/components/cover/cover.h | 4 +- tests/components/template/common-base.yaml | 38 ++++++++++ 5 files changed, 133 insertions(+), 48 deletions(-) diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 383daee083..41774f3d71 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -1,3 +1,5 @@ +import logging + from esphome import automation from esphome.automation import Condition, maybe_simple_id import esphome.codegen as cg @@ -9,6 +11,7 @@ from esphome.const import ( CONF_ICON, CONF_ID, CONF_MQTT_ID, + CONF_ON_IDLE, CONF_ON_OPEN, CONF_POSITION, CONF_POSITION_COMMAND_TOPIC, @@ -32,9 +35,10 @@ from esphome.const import ( DEVICE_CLASS_SHUTTER, DEVICE_CLASS_WINDOW, ) -from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity -from esphome.cpp_generator import MockObjClass +from esphome.cpp_generator import MockObj, MockObjClass +from esphome.types import ConfigType, TemplateArgsType IS_PLATFORM_COMPONENT = True @@ -53,6 +57,8 @@ DEVICE_CLASSES = [ DEVICE_CLASS_WINDOW, ] +_LOGGER = logging.getLogger(__name__) + cover_ns = cg.esphome_ns.namespace("cover") Cover = cover_ns.class_("Cover", cg.EntityBase) @@ -83,14 +89,29 @@ ControlAction = cover_ns.class_("ControlAction", automation.Action) CoverPublishAction = cover_ns.class_("CoverPublishAction", automation.Action) CoverIsOpenCondition = cover_ns.class_("CoverIsOpenCondition", Condition) CoverIsClosedCondition = cover_ns.class_("CoverIsClosedCondition", Condition) - -# Triggers -CoverOpenTrigger = cover_ns.class_("CoverOpenTrigger", automation.Trigger.template()) +CoverOpenedTrigger = cover_ns.class_( + "CoverOpenedTrigger", automation.Trigger.template() +) CoverClosedTrigger = cover_ns.class_( "CoverClosedTrigger", automation.Trigger.template() ) +CoverTrigger = cover_ns.class_("CoverTrigger", automation.Trigger.template()) +# Cover-specific constants CONF_ON_CLOSED = "on_closed" +CONF_ON_OPENED = "on_opened" +CONF_ON_OPENING = "on_opening" +CONF_ON_CLOSING = "on_closing" + +TRIGGERS = { + CONF_ON_OPEN: CoverOpenedTrigger, # Deprecated, use on_opened + CONF_ON_OPENED: CoverOpenedTrigger, + CONF_ON_CLOSED: CoverClosedTrigger, + CONF_ON_CLOSING: CoverTrigger.template(CoverOperation.COVER_OPERATION_CLOSING), + CONF_ON_OPENING: CoverTrigger.template(CoverOperation.COVER_OPERATION_OPENING), + CONF_ON_IDLE: CoverTrigger.template(CoverOperation.COVER_OPERATION_IDLE), +} + _COVER_SCHEMA = ( cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) @@ -111,16 +132,14 @@ _COVER_SCHEMA = ( cv.Optional(CONF_TILT_STATE_TOPIC): cv.All( cv.requires_component("mqtt"), cv.subscribe_topic ), - cv.Optional(CONF_ON_OPEN): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenTrigger), - } - ), - cv.Optional(CONF_ON_CLOSED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverClosedTrigger), - } - ), + **{ + cv.Optional(conf): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(trigger_class), + } + ) + for conf, trigger_class in TRIGGERS.items() + }, } ) ) @@ -157,12 +176,14 @@ async def setup_cover_core_(var, config): if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: cg.add(var.set_device_class(device_class)) - for conf in config.get(CONF_ON_OPEN, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_CLOSED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + if CONF_ON_OPEN in config: + _LOGGER.warning( + "'on_open' is deprecated, use 'on_opened'. Will be removed in 2026.8.0" + ) + for trigger_conf in TRIGGERS: + for conf in config.get(trigger_conf, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) @@ -258,6 +279,26 @@ async def cover_control_to_code(config, action_id, template_arg, args): return var +COVER_CONDITION_SCHEMA = cv.maybe_simple_value( + {cv.Required(CONF_ID): cv.use_id(Cover)}, key=CONF_ID +) + + +async def cover_condition_to_code( + config: ConfigType, condition_id: ID, template_arg: MockObj, args: TemplateArgsType +) -> MockObj: + paren = await cg.get_variable(config[CONF_ID]) + return cg.new_Pvariable(condition_id, template_arg, paren) + + +automation.register_condition( + "cover.is_open", CoverIsOpenCondition, COVER_CONDITION_SCHEMA +)(cover_condition_to_code) +automation.register_condition( + "cover.is_closed", CoverIsClosedCondition, COVER_CONDITION_SCHEMA +)(cover_condition_to_code) + + @coroutine_with_priority(CoroPriority.CORE) async def to_code(config): cg.add_global(cover_ns.using) diff --git a/esphome/components/cover/automation.h b/esphome/components/cover/automation.h index c0345a7cc6..12ec46725d 100644 --- a/esphome/components/cover/automation.h +++ b/esphome/components/cover/automation.h @@ -90,44 +90,53 @@ template class CoverPublishAction : public Action { Cover *cover_; }; -template class CoverIsOpenCondition : public Condition { +template class CoverPositionCondition : public Condition { public: - CoverIsOpenCondition(Cover *cover) : cover_(cover) {} - bool check(const Ts &...x) override { return this->cover_->is_fully_open(); } + CoverPositionCondition(Cover *cover) : cover_(cover) {} + + bool check(const Ts &...x) override { return this->cover_->position == (OPEN ? COVER_OPEN : COVER_CLOSED); } protected: Cover *cover_; }; -template class CoverIsClosedCondition : public Condition { +template using CoverIsOpenCondition = CoverPositionCondition; +template using CoverIsClosedCondition = CoverPositionCondition; + +template class CoverPositionTrigger : public Trigger<> { public: - CoverIsClosedCondition(Cover *cover) : cover_(cover) {} - bool check(const Ts &...x) override { return this->cover_->is_fully_closed(); } + CoverPositionTrigger(Cover *a_cover) { + a_cover->add_on_state_callback([this, a_cover]() { + if (a_cover->position != this->last_position_) { + this->last_position_ = a_cover->position; + if (a_cover->position == (OPEN ? COVER_OPEN : COVER_CLOSED)) + this->trigger(); + } + }); + } protected: - Cover *cover_; + float last_position_{NAN}; }; -class CoverOpenTrigger : public Trigger<> { +using CoverOpenedTrigger = CoverPositionTrigger; +using CoverClosedTrigger = CoverPositionTrigger; + +template class CoverTrigger : public Trigger<> { public: - CoverOpenTrigger(Cover *a_cover) { + CoverTrigger(Cover *a_cover) { a_cover->add_on_state_callback([this, a_cover]() { - if (a_cover->is_fully_open()) { - this->trigger(); + auto current_op = a_cover->current_operation; + if (current_op == OP) { + if (!this->last_operation_.has_value() || this->last_operation_.value() != OP) { + this->trigger(); + } } + this->last_operation_ = current_op; }); } -}; -class CoverClosedTrigger : public Trigger<> { - public: - CoverClosedTrigger(Cover *a_cover) { - a_cover->add_on_state_callback([this, a_cover]() { - if (a_cover->is_fully_closed()) { - this->trigger(); - } - }); - } + protected: + optional last_operation_{}; }; - } // namespace esphome::cover diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index 0d9e7e8ffb..37cb908d9f 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -10,9 +10,6 @@ namespace esphome::cover { static const char *const TAG = "cover"; -const float COVER_OPEN = 1.0f; -const float COVER_CLOSED = 0.0f; - const LogString *cover_command_to_str(float pos) { if (pos == COVER_OPEN) { return LOG_STR("OPEN"); diff --git a/esphome/components/cover/cover.h b/esphome/components/cover/cover.h index e5427ceaa8..0af48f75de 100644 --- a/esphome/components/cover/cover.h +++ b/esphome/components/cover/cover.h @@ -10,8 +10,8 @@ namespace esphome::cover { -const extern float COVER_OPEN; -const extern float COVER_CLOSED; +static constexpr float COVER_OPEN = 1.0f; +static constexpr float COVER_CLOSED = 0.0f; #define LOG_COVER(prefix, type, obj) \ if ((obj) != nullptr) { \ diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index 9dece7c3a5..d1849efaf7 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -245,6 +245,44 @@ cover: stop_action: - logger.log: stop_action optimistic: true + - platform: template + name: "Template Cover with Triggers" + id: template_cover_with_triggers + lambda: |- + if (id(some_binary_sensor).state) { + return COVER_OPEN; + } + return COVER_CLOSED; + open_action: + - logger.log: open_action + close_action: + - logger.log: close_action + stop_action: + - logger.log: stop_action + optimistic: true + on_open: + - logger.log: "Cover on_open (deprecated)" + on_opened: + - logger.log: "Cover fully opened" + on_closed: + - logger.log: "Cover fully closed" + on_opening: + - logger.log: "Cover started opening" + on_closing: + - logger.log: "Cover started closing" + on_idle: + - logger.log: "Cover stopped moving" + - logger.log: "Cover stopped moving" + - if: + condition: + cover.is_open: template_cover_with_triggers + then: + logger.log: Cover is open + - if: + condition: + cover.is_closed: template_cover_with_triggers + then: + logger.log: Cover is closed number: - platform: template From 43d9d6fe641e2d9651f25429b1a147b2c811fe20 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Feb 2026 15:12:42 -0500 Subject: [PATCH 0519/2030] [esp32] Restore develop branch for dev platform version, bump platformio (#13759) Co-authored-by: Claude --- esphome/components/esp32/__init__.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 4c53b42e6f..77753e277f 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -517,7 +517,7 @@ ESP_IDF_PLATFORM_VERSION_LOOKUP = { PLATFORM_VERSION_LOOKUP = { "recommended": cv.Version(55, 3, 36), "latest": cv.Version(55, 3, 36), - "dev": cv.Version(55, 3, 36), + "dev": "https://github.com/pioarduino/platform-espressif32.git#develop", } diff --git a/requirements.txt b/requirements.txt index 821324262b..bb118c5f9a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,7 +8,7 @@ tornado==6.5.4 tzlocal==5.3.1 # from time tzdata>=2021.1 # from time pyserial==3.5 -platformio==6.1.18 # When updating platformio, also update /docker/Dockerfile +platformio==6.1.19 esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 From 13ddf267bbb6e15e1d30c43f9a4511c964972d9f Mon Sep 17 00:00:00 2001 From: tomaszduda23 Date: Wed, 4 Feb 2026 21:18:24 +0100 Subject: [PATCH 0520/2030] [nrf52,zigbee] update warnings (#13761) --- esphome/components/zigbee/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index c044148b32..7e917a9d70 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -84,8 +84,8 @@ def validate_number_of_ep(config: ConfigType) -> None: raise cv.Invalid("At least one zigbee device need to be included") count = len(CORE.data[KEY_ZIGBEE][KEY_EP_NUMBER]) if count == 1: - raise cv.Invalid( - "Single endpoint is not supported https://github.com/Koenkk/zigbee2mqtt/issues/29888" + _LOGGER.warning( + "Single endpoint requires ZHA or at leatst Zigbee2MQTT 2.8.0. For older versions of Zigbee2MQTT use multiple endpoints" ) if count > CONF_MAX_EP_NUMBER and not CORE.testing_mode: raise cv.Invalid(f"Maximum number of end points is {CONF_MAX_EP_NUMBER}") @@ -151,7 +151,7 @@ def consume_endpoint(config: ConfigType) -> ConfigType: return config if CONF_NAME in config and " " in config[CONF_NAME]: _LOGGER.warning( - "Spaces in '%s' work with ZHA but not Zigbee2MQTT. For Zigbee2MQTT use '%s'", + "Spaces in '%s' requires ZHA or at least Zigbee2MQTT 2.8.0. For older version of Zigbee2MQTT use '%s'", config[CONF_NAME], config[CONF_NAME].replace(" ", "_"), ) From 67dfa5e2bc837f98d8f58d613073881d96c0d7fd Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Thu, 5 Feb 2026 00:39:03 +0100 Subject: [PATCH 0521/2030] [epaper_spi] Validate BUSY pin as input instead of output (#13764) --- esphome/components/epaper_spi/display.py | 78 +++++++++---------- tests/component_tests/epaper_spi/test_init.py | 53 +++++++++++++ 2 files changed, 88 insertions(+), 43 deletions(-) diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index 8cc7b2663c..13f66691b2 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -76,50 +76,42 @@ def model_schema(config): model.get_default(CONF_MINIMUM_UPDATE_INTERVAL, "1s") ) cv_dimensions = cv.Optional if model.get_default(CONF_WIDTH) else cv.Required - return ( - display.FULL_DISPLAY_SCHEMA.extend( - spi.spi_device_schema( - cs_pin_required=False, - default_mode="MODE0", - default_data_rate=model.get_default(CONF_DATA_RATE, 10_000_000), - ) - ) - .extend( - { - model.option(pin): pins.gpio_output_pin_schema - for pin in (CONF_RESET_PIN, CONF_CS_PIN, CONF_BUSY_PIN) - } - ) - .extend( - { - cv.Optional(CONF_ROTATION, default=0): validate_rotation, - cv.Required(CONF_MODEL): cv.one_of(model.name, upper=True), - cv.Optional(CONF_UPDATE_INTERVAL, default=cv.UNDEFINED): cv.All( - update_interval, cv.Range(min=minimum_update_interval) - ), - cv.Optional(CONF_TRANSFORM): cv.Schema( - { - cv.Required(CONF_MIRROR_X): cv.boolean, - cv.Required(CONF_MIRROR_Y): cv.boolean, - } - ), - cv.Optional(CONF_FULL_UPDATE_EVERY, default=1): cv.int_range(1, 255), - model.option(CONF_DC_PIN, fallback=None): pins.gpio_output_pin_schema, - cv.GenerateID(): cv.declare_id(class_name), - cv.GenerateID(CONF_INIT_SEQUENCE_ID): cv.declare_id(cg.uint8), - cv_dimensions(CONF_DIMENSIONS): DIMENSION_SCHEMA, - model.option(CONF_ENABLE_PIN): cv.ensure_list( - pins.gpio_output_pin_schema - ), - model.option(CONF_INIT_SEQUENCE, cv.UNDEFINED): cv.ensure_list( - map_sequence - ), - model.option(CONF_RESET_DURATION, cv.UNDEFINED): cv.All( - cv.positive_time_period_milliseconds, - cv.Range(max=core.TimePeriod(milliseconds=500)), - ), - } + return display.FULL_DISPLAY_SCHEMA.extend( + spi.spi_device_schema( + cs_pin_required=False, + default_mode="MODE0", + default_data_rate=model.get_default(CONF_DATA_RATE, 10_000_000), ) + ).extend( + { + cv.Optional(CONF_ROTATION, default=0): validate_rotation, + cv.Required(CONF_MODEL): cv.one_of(model.name, upper=True), + cv.Optional(CONF_UPDATE_INTERVAL, default=cv.UNDEFINED): cv.All( + update_interval, cv.Range(min=minimum_update_interval) + ), + cv.Optional(CONF_TRANSFORM): cv.Schema( + { + cv.Required(CONF_MIRROR_X): cv.boolean, + cv.Required(CONF_MIRROR_Y): cv.boolean, + } + ), + cv.Optional(CONF_FULL_UPDATE_EVERY, default=1): cv.int_range(1, 255), + model.option(CONF_BUSY_PIN): pins.gpio_input_pin_schema, + model.option(CONF_CS_PIN): pins.gpio_output_pin_schema, + model.option(CONF_DC_PIN, fallback=None): pins.gpio_output_pin_schema, + model.option(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.GenerateID(): cv.declare_id(class_name), + cv.GenerateID(CONF_INIT_SEQUENCE_ID): cv.declare_id(cg.uint8), + cv_dimensions(CONF_DIMENSIONS): DIMENSION_SCHEMA, + model.option(CONF_ENABLE_PIN): cv.ensure_list(pins.gpio_output_pin_schema), + model.option(CONF_INIT_SEQUENCE, cv.UNDEFINED): cv.ensure_list( + map_sequence + ), + model.option(CONF_RESET_DURATION, cv.UNDEFINED): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(max=core.TimePeriod(milliseconds=500)), + ), + } ) diff --git a/tests/component_tests/epaper_spi/test_init.py b/tests/component_tests/epaper_spi/test_init.py index 71e66cd043..a9f5735fca 100644 --- a/tests/component_tests/epaper_spi/test_init.py +++ b/tests/component_tests/epaper_spi/test_init.py @@ -289,3 +289,56 @@ def test_model_with_full_update_every( "full_update_every": 10, } ) + + +def test_busy_pin_input_mode_ssd1677( + set_core_config: SetCoreConfigCallable, + set_component_config: Callable[[str, Any], None], +) -> None: + """Test that busy_pin has input mode and cs/dc/reset pins have output mode for ssd1677.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + + # Configure SPI component which is required by epaper_spi + set_component_config("spi", {"id": "spi_bus", "clk_pin": 18, "mosi_pin": 19}) + + result = run_schema_validation( + { + "id": "test_display", + "model": "ssd1677", + "dc_pin": 21, + "busy_pin": 22, + "reset_pin": 23, + "cs_pin": 5, + "dimensions": { + "width": 200, + "height": 200, + }, + } + ) + + # Verify that busy_pin has input mode set + assert CONF_BUSY_PIN in result + busy_pin_config = result[CONF_BUSY_PIN] + assert "mode" in busy_pin_config + assert busy_pin_config["mode"]["input"] is True + + # Verify that cs_pin has output mode set + assert CONF_CS_PIN in result + cs_pin_config = result[CONF_CS_PIN] + assert "mode" in cs_pin_config + assert cs_pin_config["mode"]["output"] is True + + # Verify that dc_pin has output mode set + assert CONF_DC_PIN in result + dc_pin_config = result[CONF_DC_PIN] + assert "mode" in dc_pin_config + assert dc_pin_config["mode"]["output"] is True + + # Verify that reset_pin has output mode set + assert CONF_RESET_PIN in result + reset_pin_config = result[CONF_RESET_PIN] + assert "mode" in reset_pin_config + assert reset_pin_config["mode"]["output"] is True From 89fc5ebc978325698052579a49c5af780f758b1f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 5 Feb 2026 06:18:03 +0100 Subject: [PATCH 0522/2030] Fix bare hostname ping fallback in dashboard (#13760) --- esphome/dashboard/dns.py | 21 +++++++- tests/dashboard/status/test_dns.py | 82 +++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/esphome/dashboard/dns.py b/esphome/dashboard/dns.py index 58867f7bc1..eb4a87dbfb 100644 --- a/esphome/dashboard/dns.py +++ b/esphome/dashboard/dns.py @@ -3,11 +3,16 @@ from __future__ import annotations import asyncio from contextlib import suppress from ipaddress import ip_address +import logging from icmplib import NameLookupError, async_resolve RESOLVE_TIMEOUT = 3.0 +_LOGGER = logging.getLogger(__name__) + +_RESOLVE_EXCEPTIONS = (TimeoutError, NameLookupError, UnicodeError) + async def _async_resolve_wrapper(hostname: str) -> list[str] | Exception: """Wrap the icmplib async_resolve function.""" @@ -16,7 +21,21 @@ async def _async_resolve_wrapper(hostname: str) -> list[str] | Exception: try: async with asyncio.timeout(RESOLVE_TIMEOUT): return await async_resolve(hostname) - except (TimeoutError, NameLookupError, UnicodeError) as ex: + except _RESOLVE_EXCEPTIONS as ex: + # If the hostname ends with .local and resolution failed, + # try the bare hostname as a fallback since mDNS may not be + # working on the system but unicast DNS might resolve it + if hostname.endswith(".local"): + bare_hostname = hostname[:-6] # Remove ".local" + try: + async with asyncio.timeout(RESOLVE_TIMEOUT): + result = await async_resolve(bare_hostname) + _LOGGER.debug( + "Bare hostname %s resolved to %s", bare_hostname, result + ) + return result + except _RESOLVE_EXCEPTIONS: + _LOGGER.debug("Bare hostname %s also failed to resolve", bare_hostname) return ex diff --git a/tests/dashboard/status/test_dns.py b/tests/dashboard/status/test_dns.py index 9ca48ba2d8..f7c4992079 100644 --- a/tests/dashboard/status/test_dns.py +++ b/tests/dashboard/status/test_dns.py @@ -3,11 +3,12 @@ from __future__ import annotations import time -from unittest.mock import patch +from unittest.mock import AsyncMock, patch +from icmplib import NameLookupError import pytest -from esphome.dashboard.dns import DNSCache +from esphome.dashboard.dns import DNSCache, _async_resolve_wrapper @pytest.fixture @@ -119,3 +120,80 @@ def test_async_resolve_not_called(dns_cache_fixture: DNSCache) -> None: result = dns_cache_fixture.get_cached_addresses("valid.com", now) assert result == ["192.168.1.10"] mock_resolve.assert_not_called() + + +@pytest.mark.asyncio +async def test_async_resolve_wrapper_ip_address() -> None: + """Test _async_resolve_wrapper returns IP address directly.""" + result = await _async_resolve_wrapper("192.168.1.10") + assert result == ["192.168.1.10"] + + result = await _async_resolve_wrapper("2001:db8::1") + assert result == ["2001:db8::1"] + + +@pytest.mark.asyncio +async def test_async_resolve_wrapper_local_fallback_success() -> None: + """Test _async_resolve_wrapper falls back to bare hostname for .local.""" + mock_resolve = AsyncMock() + # First call (device.local) fails, second call (device) succeeds + mock_resolve.side_effect = [ + NameLookupError("device.local"), + ["192.168.1.50"], + ] + + with patch("esphome.dashboard.dns.async_resolve", mock_resolve): + result = await _async_resolve_wrapper("device.local") + + assert result == ["192.168.1.50"] + assert mock_resolve.call_count == 2 + mock_resolve.assert_any_call("device.local") + mock_resolve.assert_any_call("device") + + +@pytest.mark.asyncio +async def test_async_resolve_wrapper_local_fallback_both_fail() -> None: + """Test _async_resolve_wrapper returns exception when both fail.""" + mock_resolve = AsyncMock() + original_exception = NameLookupError("device.local") + mock_resolve.side_effect = [ + original_exception, + NameLookupError("device"), + ] + + with patch("esphome.dashboard.dns.async_resolve", mock_resolve): + result = await _async_resolve_wrapper("device.local") + + # Should return the original exception, not the fallback exception + assert result is original_exception + assert mock_resolve.call_count == 2 + + +@pytest.mark.asyncio +async def test_async_resolve_wrapper_non_local_no_fallback() -> None: + """Test _async_resolve_wrapper doesn't fallback for non-.local hostnames.""" + mock_resolve = AsyncMock() + original_exception = NameLookupError("device.example.com") + mock_resolve.side_effect = original_exception + + with patch("esphome.dashboard.dns.async_resolve", mock_resolve): + result = await _async_resolve_wrapper("device.example.com") + + assert result is original_exception + # Should only try the original hostname, no fallback + assert mock_resolve.call_count == 1 + mock_resolve.assert_called_once_with("device.example.com") + + +@pytest.mark.asyncio +async def test_async_resolve_wrapper_local_success_no_fallback() -> None: + """Test _async_resolve_wrapper doesn't fallback when .local succeeds.""" + mock_resolve = AsyncMock(return_value=["192.168.1.50"]) + + with patch("esphome.dashboard.dns.async_resolve", mock_resolve): + result = await _async_resolve_wrapper("device.local") + + assert result == ["192.168.1.50"] + # Should only try once since it succeeded + assert mock_resolve.call_count == 1 + mock_resolve.assert_called_once_with("device.local") From a5568248753345080b8e5524f7f886ddbaf9d8dc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 5 Feb 2026 06:19:13 +0100 Subject: [PATCH 0523/2030] [logger] Refactor to reduce code duplication and flash size (#13750) --- esphome/components/logger/logger.cpp | 55 +-- esphome/components/logger/logger.h | 407 +++++++++--------- esphome/components/logger/logger_esp32.cpp | 4 +- esphome/components/logger/logger_esp8266.cpp | 2 +- esphome/components/logger/logger_host.cpp | 4 +- .../components/logger/logger_libretiny.cpp | 2 +- esphome/components/logger/logger_rp2040.cpp | 2 +- esphome/components/logger/logger_zephyr.cpp | 4 +- 8 files changed, 234 insertions(+), 246 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 25243ff3f6..54b5670016 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -36,9 +36,7 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch // Fast path: main thread, no recursion (99.9% of all logs) if (is_main_task && !this->main_task_recursion_guard_) [[likely]] { - RecursionGuard guard(this->main_task_recursion_guard_); - // Format and send to both console and callbacks - this->log_message_to_buffer_and_send_(level, tag, line, format, args); + this->log_message_to_buffer_and_send_(this->main_task_recursion_guard_, level, tag, line, format, args); return; } @@ -101,12 +99,9 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144; #endif char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE]; // MUST be stack allocated for thread safety - uint16_t buffer_at = 0; // Initialize buffer position - this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, console_buffer, &buffer_at, - MAX_CONSOLE_LOG_MSG_SIZE); - // Add newline before writing to console - this->add_newline_to_buffer_(console_buffer, &buffer_at, MAX_CONSOLE_LOG_MSG_SIZE); - this->write_msg_(console_buffer, buffer_at); + LogBuffer buf{console_buffer, MAX_CONSOLE_LOG_MSG_SIZE}; + this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf); + this->write_to_console_(buf); } // RAII guard automatically resets on return @@ -117,9 +112,7 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch if (level > this->level_for(tag) || global_recursion_guard_) return; - RecursionGuard guard(global_recursion_guard_); - // Format and send to both console and callbacks - this->log_message_to_buffer_and_send_(level, tag, line, format, args); + this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args); } #endif // USE_ESP32 / USE_HOST / USE_LIBRETINY @@ -135,28 +128,7 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas if (level > this->level_for(tag) || global_recursion_guard_) return; - RecursionGuard guard(global_recursion_guard_); - this->tx_buffer_at_ = 0; - - // Write header, format body directly from flash, and write footer - this->write_header_to_buffer_(level, tag, line, nullptr, this->tx_buffer_, &this->tx_buffer_at_, - this->tx_buffer_size_); - this->format_body_to_buffer_P_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_, - reinterpret_cast(format), args); - this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); - - // Ensure null termination - uint16_t null_pos = this->tx_buffer_at_ >= this->tx_buffer_size_ ? this->tx_buffer_size_ - 1 : this->tx_buffer_at_; - this->tx_buffer_[null_pos] = '\0'; - - // Listeners get message first (before console write) -#ifdef USE_LOG_LISTENERS - for (auto *listener : this->log_listeners_) - listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); -#endif - - // Write to console - this->write_tx_buffer_to_console_(); + this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args); } #endif // USE_STORE_LOG_STR_IN_FLASH @@ -215,10 +187,11 @@ void Logger::process_messages_() { logger::TaskLogBufferHost::LogMessage *message; while (this->log_buffer_->get_message_main_loop(&message)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; + LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, message->text, - message->text_length); + message->text_length, buf); this->log_buffer_->release_message_main_loop(); - this->write_tx_buffer_to_console_(); + this->write_log_buffer_to_console_(buf); } #elif defined(USE_ESP32) logger::TaskLogBuffer::LogMessage *message; @@ -226,22 +199,24 @@ void Logger::process_messages_() { void *received_token; while (this->log_buffer_->borrow_message_main_loop(&message, &text, &received_token)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; + LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, text, - message->text_length); + message->text_length, buf); // Release the message to allow other tasks to use it as soon as possible this->log_buffer_->release_message_main_loop(received_token); - this->write_tx_buffer_to_console_(); + this->write_log_buffer_to_console_(buf); } #elif defined(USE_LIBRETINY) logger::TaskLogBufferLibreTiny::LogMessage *message; const char *text; while (this->log_buffer_->borrow_message_main_loop(&message, &text)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; + LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, text, - message->text_length); + message->text_length, buf); // Release the message to allow other tasks to use it as soon as possible this->log_buffer_->release_message_main_loop(); - this->write_tx_buffer_to_console_(); + this->write_log_buffer_to_console_(buf); } #endif } diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 40ac9a38aa..1678fed5f5 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -2,6 +2,7 @@ #include #include +#include #if defined(USE_ESP32) || defined(USE_HOST) #include #endif @@ -123,6 +124,163 @@ static constexpr uint16_t MAX_HEADER_SIZE = 128; // "0x" + 2 hex digits per byte + '\0' static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1; +// Buffer wrapper for log formatting functions +struct LogBuffer { + char *data; + uint16_t size; + uint16_t pos{0}; + // Replaces the null terminator with a newline for console output. + // Must be called after notify_listeners_() since listeners need null-terminated strings. + // Console output uses length-based writes (buf.pos), so null terminator is not needed. + void terminate_with_newline() { + if (this->pos < this->size) { + this->data[this->pos++] = '\n'; + } else if (this->size > 0) { + // Buffer was full - replace last char with newline to ensure it's visible + this->data[this->size - 1] = '\n'; + this->pos = this->size; + } + } + void HOT write_header(uint8_t level, const char *tag, int line, const char *thread_name) { + // Early return if insufficient space - intentionally don't update pos to prevent partial writes + if (this->pos + MAX_HEADER_SIZE > this->size) + return; + + char *p = this->current_(); + + // Write ANSI color + this->write_ansi_color_(p, level); + + // Construct: [LEVEL][tag:line] + *p++ = '['; + if (level != 0) { + if (level >= 7) { + *p++ = 'V'; // VERY_VERBOSE = "VV" + *p++ = 'V'; + } else { + *p++ = LOG_LEVEL_LETTER_CHARS[level]; + } + } + *p++ = ']'; + *p++ = '['; + + // Copy tag + this->copy_string_(p, tag); + + *p++ = ':'; + + // Format line number without modulo operations + if (line > 999) [[unlikely]] { + int thousands = line / 1000; + *p++ = '0' + thousands; + line -= thousands * 1000; + } + int hundreds = line / 100; + int remainder = line - hundreds * 100; + int tens = remainder / 10; + *p++ = '0' + hundreds; + *p++ = '0' + tens; + *p++ = '0' + (remainder - tens * 10); + *p++ = ']'; + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST) + // Write thread name with bold red color + if (thread_name != nullptr) { + this->write_ansi_color_(p, 1); // Bold red for thread name + *p++ = '['; + this->copy_string_(p, thread_name); + *p++ = ']'; + this->write_ansi_color_(p, level); // Restore original color + } +#endif + + *p++ = ':'; + *p++ = ' '; + + this->pos = p - this->data; + } + void HOT format_body(const char *format, va_list args) { + this->format_vsnprintf_(format, args); + this->finalize_(); + } +#ifdef USE_STORE_LOG_STR_IN_FLASH + void HOT format_body_P(PGM_P format, va_list args) { + this->format_vsnprintf_P_(format, args); + this->finalize_(); + } +#endif + void write_body(const char *text, uint16_t text_length) { + this->write_(text, text_length); + this->finalize_(); + } + + private: + bool full_() const { return this->pos >= this->size; } + uint16_t remaining_() const { return this->size - this->pos; } + char *current_() { return this->data + this->pos; } + void write_(const char *value, uint16_t length) { + const uint16_t available = this->remaining_(); + const uint16_t copy_len = (length < available) ? length : available; + if (copy_len > 0) { + memcpy(this->current_(), value, copy_len); + this->pos += copy_len; + } + } + void finalize_() { + // Write color reset sequence + static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; + this->write_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN); + // Null terminate + this->data[this->full_() ? this->size - 1 : this->pos] = '\0'; + } + void strip_trailing_newlines_() { + while (this->pos > 0 && this->data[this->pos - 1] == '\n') + this->pos--; + } + void process_vsnprintf_result_(int ret) { + if (ret < 0) + return; + const uint16_t rem = this->remaining_(); + this->pos += (ret >= rem) ? (rem - 1) : static_cast(ret); + this->strip_trailing_newlines_(); + } + void format_vsnprintf_(const char *format, va_list args) { + if (this->full_()) + return; + this->process_vsnprintf_result_(vsnprintf(this->current_(), this->remaining_(), format, args)); + } +#ifdef USE_STORE_LOG_STR_IN_FLASH + void format_vsnprintf_P_(PGM_P format, va_list args) { + if (this->full_()) + return; + this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(), format, args)); + } +#endif + // Write ANSI color escape sequence to buffer, updates pointer in place + // Caller is responsible for ensuring buffer has sufficient space + void write_ansi_color_(char *&p, uint8_t level) { + if (level == 0) + return; + // Direct buffer fill: "\033[{bold};3{color}m" (7 bytes) + *p++ = '\033'; + *p++ = '['; + *p++ = (level == 1) ? '1' : '0'; // Only ERROR is bold + *p++ = ';'; + *p++ = '3'; + *p++ = LOG_LEVEL_COLOR_DIGIT[level]; + *p++ = 'm'; + } + // Copy string without null terminator, updates pointer in place + // Caller is responsible for ensuring buffer has sufficient space + void copy_string_(char *&p, const char *str) { + const size_t len = strlen(str); + // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - intentionally no null terminator, building string piece by + // piece + memcpy(p, str, len); + p += len; + } +}; + #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) /** Enum for logging UART selection * @@ -260,114 +418,83 @@ class Logger : public Component { #endif #endif void process_messages_(); - void write_msg_(const char *msg, size_t len); + void write_msg_(const char *msg, uint16_t len); // Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator - // It's the caller's responsibility to initialize buffer_at (typically to 0) inline void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format, - va_list args, char *buffer, uint16_t *buffer_at, - uint16_t buffer_size) { + va_list args, LogBuffer &buf) { #if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_HOST) - this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size); + buf.write_header(level, tag, line, this->get_thread_name_()); #elif defined(USE_ZEPHYR) - char buff[MAX_POINTER_REPRESENTATION]; - this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(buff), buffer, buffer_at, buffer_size); + char tmp[MAX_POINTER_REPRESENTATION]; + buf.write_header(level, tag, line, this->get_thread_name_(tmp)); #else - this->write_header_to_buffer_(level, tag, line, nullptr, buffer, buffer_at, buffer_size); + buf.write_header(level, tag, line, nullptr); #endif - this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, args); - this->write_footer_to_buffer_(buffer, buffer_at, buffer_size); - - // Always ensure the buffer has a null terminator, even if we need to - // overwrite the last character of the actual content - if (*buffer_at >= buffer_size) { - buffer[buffer_size - 1] = '\0'; // Truncate and ensure null termination - } else { - buffer[*buffer_at] = '\0'; // Normal case, append null terminator - } + buf.format_body(format, args); } - // Helper to add newline to buffer before writing to console - // Modifies buffer_at to include the newline - inline void HOT add_newline_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) { - // Add newline - don't need to maintain null termination - // write_msg_ receives explicit length, so we can safely overwrite the null terminator - // This is safe because: - // 1. Callbacks already received the message (before we add newline) - // 2. write_msg_ receives the length explicitly (doesn't need null terminator) - if (*buffer_at < buffer_size) { - buffer[(*buffer_at)++] = '\n'; - } else if (buffer_size > 0) { - // Buffer was full - replace last char with newline to ensure it's visible - buffer[buffer_size - 1] = '\n'; - *buffer_at = buffer_size; - } +#ifdef USE_STORE_LOG_STR_IN_FLASH + // Format a log message with flash string format and write it to a buffer with header, footer, and null terminator + inline void HOT format_log_to_buffer_with_terminator_P_(uint8_t level, const char *tag, int line, + const __FlashStringHelper *format, va_list args, + LogBuffer &buf) { + buf.write_header(level, tag, line, nullptr); + buf.format_body_P(reinterpret_cast(format), args); + } +#endif + + // Helper to notify log listeners + inline void HOT notify_listeners_(uint8_t level, const char *tag, const LogBuffer &buf) { +#ifdef USE_LOG_LISTENERS + for (auto *listener : this->log_listeners_) + listener->on_log(level, tag, buf.data, buf.pos); +#endif } - // Helper to write tx_buffer_ to console if logging is enabled - // INTERNAL USE ONLY - offset > 0 requires length parameter to be non-null - inline void HOT write_tx_buffer_to_console_(uint16_t offset = 0, uint16_t *length = nullptr) { - if (this->baud_rate_ > 0) { - uint16_t *len_ptr = length ? length : &this->tx_buffer_at_; - this->add_newline_to_buffer_(this->tx_buffer_ + offset, len_ptr, this->tx_buffer_size_ - offset); - this->write_msg_(this->tx_buffer_ + offset, *len_ptr); - } + // Helper to write log buffer to console (replaces null terminator with newline and writes) + inline void HOT write_to_console_(LogBuffer &buf) { + buf.terminate_with_newline(); + this->write_msg_(buf.data, buf.pos); + } + + // Helper to write log buffer to console if logging is enabled + inline void HOT write_log_buffer_to_console_(LogBuffer &buf) { + if (this->baud_rate_ > 0) + this->write_to_console_(buf); } // Helper to format and send a log message to both console and listeners - inline void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format, - va_list args) { - // Format to tx_buffer and prepare for output - this->tx_buffer_at_ = 0; // Initialize buffer position - this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, this->tx_buffer_, &this->tx_buffer_at_, - this->tx_buffer_size_); - - // Listeners get message WITHOUT newline (for API/MQTT/syslog) -#ifdef USE_LOG_LISTENERS - for (auto *listener : this->log_listeners_) - listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); + // Template handles both const char* (RAM) and __FlashStringHelper* (flash) format strings + template + inline void HOT log_message_to_buffer_and_send_(bool &recursion_guard, uint8_t level, const char *tag, int line, + FormatType format, va_list args) { + RecursionGuard guard(recursion_guard); + LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; +#ifdef USE_STORE_LOG_STR_IN_FLASH + if constexpr (std::is_same_v) { + this->format_log_to_buffer_with_terminator_P_(level, tag, line, format, args, buf); + } else #endif - - // Console gets message WITH newline (if platform needs it) - this->write_tx_buffer_to_console_(); + { + this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf); + } + this->notify_listeners_(level, tag, buf); + this->write_log_buffer_to_console_(buf); } #ifdef USE_ESPHOME_TASK_LOG_BUFFER // Helper to format a pre-formatted message from the task log buffer and notify listeners // Used by process_messages_ to avoid code duplication between ESP32 and host platforms inline void HOT format_buffered_message_and_notify_(uint8_t level, const char *tag, uint16_t line, - const char *thread_name, const char *text, size_t text_length) { - this->tx_buffer_at_ = 0; - this->write_header_to_buffer_(level, tag, line, thread_name, this->tx_buffer_, &this->tx_buffer_at_, - this->tx_buffer_size_); - this->write_body_to_buffer_(text, text_length, this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); - this->write_footer_to_buffer_(this->tx_buffer_, &this->tx_buffer_at_, this->tx_buffer_size_); - this->tx_buffer_[this->tx_buffer_at_] = '\0'; -#ifdef USE_LOG_LISTENERS - for (auto *listener : this->log_listeners_) - listener->on_log(level, tag, this->tx_buffer_, this->tx_buffer_at_); -#endif + const char *thread_name, const char *text, uint16_t text_length, + LogBuffer &buf) { + buf.write_header(level, tag, line, thread_name); + buf.write_body(text, text_length); + this->notify_listeners_(level, tag, buf); } #endif - // Write the body of the log message to the buffer - inline void write_body_to_buffer_(const char *value, size_t length, char *buffer, uint16_t *buffer_at, - uint16_t buffer_size) { - // Calculate available space - if (*buffer_at >= buffer_size) - return; - const uint16_t available = buffer_size - *buffer_at; - - // Determine copy length (minimum of remaining capacity and string length) - const size_t copy_len = (length < static_cast(available)) ? length : available; - - // Copy the data - if (copy_len > 0) { - memcpy(buffer + *buffer_at, value, copy_len); - *buffer_at += copy_len; - } - } - #ifndef USE_HOST const LogString *get_uart_selection_(); #endif @@ -421,7 +548,6 @@ class Logger : public Component { #endif // Group smaller types together at the end - uint16_t tx_buffer_at_{0}; uint16_t tx_buffer_size_{0}; uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE}; #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR) @@ -525,117 +651,6 @@ class Logger : public Component { } #endif - static inline void copy_string(char *buffer, uint16_t &pos, const char *str) { - const size_t len = strlen(str); - // Intentionally no null terminator, building larger string - memcpy(buffer + pos, str, len); // NOLINT(bugprone-not-null-terminated-result) - pos += len; - } - - static inline void write_ansi_color_for_level(char *buffer, uint16_t &pos, uint8_t level) { - if (level == 0) - return; - // Construct ANSI escape sequence: "\033[{bold};3{color}m" - // Example: "\033[1;31m" for ERROR (bold red) - buffer[pos++] = '\033'; - buffer[pos++] = '['; - buffer[pos++] = (level == 1) ? '1' : '0'; // Only ERROR is bold - buffer[pos++] = ';'; - buffer[pos++] = '3'; - buffer[pos++] = LOG_LEVEL_COLOR_DIGIT[level]; - buffer[pos++] = 'm'; - } - - inline void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name, - char *buffer, uint16_t *buffer_at, uint16_t buffer_size) { - uint16_t pos = *buffer_at; - // Early return if insufficient space - intentionally don't update buffer_at to prevent partial writes - if (pos + MAX_HEADER_SIZE > buffer_size) - return; - - // Construct: [LEVEL][tag:line]: - write_ansi_color_for_level(buffer, pos, level); - buffer[pos++] = '['; - if (level != 0) { - if (level >= 7) { - buffer[pos++] = 'V'; // VERY_VERBOSE = "VV" - buffer[pos++] = 'V'; - } else { - buffer[pos++] = LOG_LEVEL_LETTER_CHARS[level]; - } - } - buffer[pos++] = ']'; - buffer[pos++] = '['; - copy_string(buffer, pos, tag); - buffer[pos++] = ':'; - // Format line number without modulo operations (passed by value, safe to mutate) - if (line > 999) [[unlikely]] { - int thousands = line / 1000; - buffer[pos++] = '0' + thousands; - line -= thousands * 1000; - } - int hundreds = line / 100; - int remainder = line - hundreds * 100; - int tens = remainder / 10; - buffer[pos++] = '0' + hundreds; - buffer[pos++] = '0' + tens; - buffer[pos++] = '0' + (remainder - tens * 10); - buffer[pos++] = ']'; - -#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST) - if (thread_name != nullptr) { - write_ansi_color_for_level(buffer, pos, 1); // Always use bold red for thread name - buffer[pos++] = '['; - copy_string(buffer, pos, thread_name); - buffer[pos++] = ']'; - write_ansi_color_for_level(buffer, pos, level); // Restore original color - } -#endif - - buffer[pos++] = ':'; - buffer[pos++] = ' '; - *buffer_at = pos; - } - - // Helper to process vsnprintf return value and strip trailing newlines. - // Updates buffer_at with the formatted length, handling truncation: - // - When vsnprintf truncates (ret >= remaining), it writes (remaining - 1) chars + null terminator - // - When it doesn't truncate (ret < remaining), it writes ret chars + null terminator - __attribute__((always_inline)) static inline void process_vsnprintf_result(const char *buffer, uint16_t *buffer_at, - uint16_t remaining, int ret) { - if (ret < 0) - return; // Encoding error, do not increment buffer_at - *buffer_at += (ret >= remaining) ? (remaining - 1) : static_cast(ret); - // Remove all trailing newlines right after formatting - while (*buffer_at > 0 && buffer[*buffer_at - 1] == '\n') - (*buffer_at)--; - } - - inline void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format, - va_list args) { - // Check remaining capacity in the buffer - if (*buffer_at >= buffer_size) - return; - const uint16_t remaining = buffer_size - *buffer_at; - process_vsnprintf_result(buffer, buffer_at, remaining, vsnprintf(buffer + *buffer_at, remaining, format, args)); - } - -#ifdef USE_STORE_LOG_STR_IN_FLASH - // ESP8266 variant that reads format string directly from flash using vsnprintf_P - inline void HOT format_body_to_buffer_P_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, PGM_P format, - va_list args) { - if (*buffer_at >= buffer_size) - return; - const uint16_t remaining = buffer_size - *buffer_at; - process_vsnprintf_result(buffer, buffer_at, remaining, vsnprintf_P(buffer + *buffer_at, remaining, format, args)); - } -#endif - - inline void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) { - static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; - this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size); - } - #if defined(USE_ESP32) || defined(USE_LIBRETINY) // Disable loop when task buffer is empty (with USB CDC check on ESP32) inline void disable_loop_when_buffer_empty_() { diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 9defb6c166..dfa643d5e9 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -118,9 +118,7 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, size_t len) { - // Length is now always passed explicitly - no strlen() fallback needed - +void HOT Logger::write_msg_(const char *msg, uint16_t len) { #if defined(USE_LOGGER_UART_SELECTION_USB_CDC) || defined(USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG) // USB CDC/JTAG - single write including newline (already in buffer) // Use fwrite to stdout which goes through VFS to USB console diff --git a/esphome/components/logger/logger_esp8266.cpp b/esphome/components/logger/logger_esp8266.cpp index 6cee1baca5..0a3433d132 100644 --- a/esphome/components/logger/logger_esp8266.cpp +++ b/esphome/components/logger/logger_esp8266.cpp @@ -28,7 +28,7 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, size_t len) { +void HOT Logger::write_msg_(const char *msg, uint16_t len) { // Single write with newline already in buffer (added by caller) this->hw_serial_->write(msg, len); } diff --git a/esphome/components/logger/logger_host.cpp b/esphome/components/logger/logger_host.cpp index 874cdabd22..be12b6df6a 100644 --- a/esphome/components/logger/logger_host.cpp +++ b/esphome/components/logger/logger_host.cpp @@ -3,7 +3,7 @@ namespace esphome::logger { -void HOT Logger::write_msg_(const char *msg, size_t len) { +void HOT Logger::write_msg_(const char *msg, uint16_t len) { static constexpr size_t TIMESTAMP_LEN = 10; // "[HH:MM:SS]" // tx_buffer_size_ defaults to 512, so 768 covers default + headroom char buffer[TIMESTAMP_LEN + 768]; @@ -15,7 +15,7 @@ void HOT Logger::write_msg_(const char *msg, size_t len) { size_t pos = strftime(buffer, TIMESTAMP_LEN + 1, "[%H:%M:%S]", &timeinfo); // Copy message (with newline already included by caller) - size_t copy_len = std::min(len, sizeof(buffer) - pos); + size_t copy_len = std::min(static_cast(len), sizeof(buffer) - pos); memcpy(buffer + pos, msg, copy_len); pos += copy_len; diff --git a/esphome/components/logger/logger_libretiny.cpp b/esphome/components/logger/logger_libretiny.cpp index cdf55e710c..aab8a97abf 100644 --- a/esphome/components/logger/logger_libretiny.cpp +++ b/esphome/components/logger/logger_libretiny.cpp @@ -49,7 +49,7 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, size_t len) { this->hw_serial_->write(msg, len); } +void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); } const LogString *Logger::get_uart_selection_() { switch (this->uart_) { diff --git a/esphome/components/logger/logger_rp2040.cpp b/esphome/components/logger/logger_rp2040.cpp index be8252f56a..1f435031f6 100644 --- a/esphome/components/logger/logger_rp2040.cpp +++ b/esphome/components/logger/logger_rp2040.cpp @@ -27,7 +27,7 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, size_t len) { +void HOT Logger::write_msg_(const char *msg, uint16_t len) { // Single write with newline already in buffer (added by caller) this->hw_serial_->write(msg, len); } diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index 41f53beec0..ef1702c5c1 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -63,7 +63,7 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, size_t len) { +void HOT Logger::write_msg_(const char *msg, uint16_t len) { // Single write with newline already in buffer (added by caller) #ifdef CONFIG_PRINTK // Requires the debug component and an active SWD connection. @@ -73,7 +73,7 @@ void HOT Logger::write_msg_(const char *msg, size_t len) { if (this->uart_dev_ == nullptr) { return; } - for (size_t i = 0; i < len; ++i) { + for (uint16_t i = 0; i < len; ++i) { uart_poll_out(this->uart_dev_, msg[i]); } } From 25c0073b2d60e99012264a2149696cd50970af44 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 5 Feb 2026 06:20:04 +0100 Subject: [PATCH 0524/2030] [web_server] Fix ESP8266 watchdog panic by deferring actions to main loop (#13765) --- esphome/components/web_server/web_server.cpp | 15 +-------------- esphome/components/web_server/web_server.h | 11 +++++------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index d30cb524f4..a3bf1e6b02 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -721,11 +721,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM } if (action != SWITCH_ACTION_NONE) { -#ifdef USE_ESP8266 - execute_switch_action(obj, action); -#else this->defer([obj, action]() { execute_switch_action(obj, action); }); -#endif request->send(200); } else { request->send(404); @@ -1645,11 +1641,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat } if (action != LOCK_ACTION_NONE) { -#ifdef USE_ESP8266 - execute_lock_action(obj, action); -#else this->defer([obj, action]() { execute_lock_action(obj, action); }); -#endif request->send(200); } else { request->send(404); @@ -2015,19 +2007,14 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur return; } -#ifdef USE_ESP8266 - // ESP8266 is single-threaded, call directly - call.set_raw_timings_base64url(encoded); - call.perform(); -#else // Defer to main loop for thread safety. Move encoded string into lambda to ensure // it outlives the call - set_raw_timings_base64url stores a pointer, so the string // must remain valid until perform() completes. + // ESP8266 also needs this because ESPAsyncWebServer callbacks run in "sys" context. this->defer([call, encoded = std::move(encoded)]() mutable { call.set_raw_timings_base64url(encoded); call.perform(); }); -#endif request->send(200); return; diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 92a5c7edee..224c051ece 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -42,13 +42,12 @@ using ParamNameType = const __FlashStringHelper *; using ParamNameType = const char *; #endif -// ESP8266 is single-threaded, so actions can execute directly in request context. -// Multi-core platforms need to defer to main loop thread for thread safety. -#ifdef USE_ESP8266 -#define DEFER_ACTION(capture, action) action -#else +// All platforms need to defer actions to main loop thread. +// Multi-core platforms need this for thread safety. +// ESP8266 needs this because ESPAsyncWebServer callbacks run in "sys" context +// (SDK system context), not "cont" context (continuation/main loop). Calling +// yield() from sys context causes a panic in the Arduino core. #define DEFER_ACTION(capture, action) this->defer([capture]() mutable { action; }) -#endif /// Result of matching a URL against an entity struct EntityMatchResult { From c27870b15d076e61632efc1637629104817d1064 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 5 Feb 2026 06:36:40 +0100 Subject: [PATCH 0525/2030] [web_server] Add some more missing ESPHOME_F macros (#13748) --- esphome/components/web_server/web_server.cpp | 10 +++++----- esphome/components/web_server/web_server_v1.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index a3bf1e6b02..42219f3aac 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -454,7 +454,7 @@ void WebServer::handle_index_request(AsyncWebServerRequest *request) { #ifdef USE_WEBSERVER_PRIVATE_NETWORK_ACCESS void WebServer::handle_pna_cors_request(AsyncWebServerRequest *request) { - AsyncWebServerResponse *response = request->beginResponse(200, ""); + AsyncWebServerResponse *response = request->beginResponse(200, ESPHOME_F("")); response->addHeader(ESPHOME_F("Access-Control-Allow-Private-Network"), ESPHOME_F("true")); response->addHeader(ESPHOME_F("Private-Network-Access-Name"), App.get_name().c_str()); char mac_s[18]; @@ -1967,7 +1967,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur // Only allow transmit if the device supports it if (!obj->has_transmitter()) { - request->send(400, ESPHOME_F("text/plain"), "Device does not support transmission"); + request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Device does not support transmission")); return; } @@ -1993,7 +1993,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur // Parse base64url-encoded raw timings (required) // Base64url is URL-safe: uses A-Za-z0-9-_ (no special characters needing escaping) if (!request->hasParam(ESPHOME_F("data"))) { - request->send(400, ESPHOME_F("text/plain"), "Missing 'data' parameter"); + request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Missing 'data' parameter")); return; } @@ -2003,7 +2003,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur // Validate base64url is not empty if (encoded.empty()) { - request->send(400, ESPHOME_F("text/plain"), "Empty 'data' parameter"); + request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Empty 'data' parameter")); return; } @@ -2472,7 +2472,7 @@ void WebServer::handleRequest(AsyncWebServerRequest *request) { else { // No matching handler found - send 404 ESP_LOGV(TAG, "Request for unknown URL: %s", url.c_str()); - request->send(404, "text/plain", "Not Found"); + request->send(404, ESPHOME_F("text/plain"), ESPHOME_F("Not Found")); } } diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp index ae4bbfa557..f7b90018dc 100644 --- a/esphome/components/web_server/web_server_v1.cpp +++ b/esphome/components/web_server/web_server_v1.cpp @@ -74,7 +74,7 @@ void WebServer::set_css_url(const char *css_url) { this->css_url_ = css_url; } void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; } void WebServer::handle_index_request(AsyncWebServerRequest *request) { - AsyncResponseStream *stream = request->beginResponseStream("text/html"); + AsyncResponseStream *stream = request->beginResponseStream(ESPHOME_F("text/html")); const std::string &title = App.get_name(); stream->print(ESPHOME_F("")); From 7bd8b08e16493259df06d0c3d5e4ac035bb44e25 Mon Sep 17 00:00:00 2001 From: Jas Strong <jasmine@electronpusher.org> Date: Thu, 5 Feb 2026 00:06:52 -0800 Subject: [PATCH 0526/2030] [rd03d] Revert incorrect field order swap (#13769) Co-authored-by: jas <jas@asspa.in> --- esphome/components/rd03d/rd03d.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index ba05abe8e0..090e4dcf32 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -132,18 +132,15 @@ void RD03DComponent::process_frame_() { // Header is 4 bytes, each target is 8 bytes uint8_t offset = FRAME_HEADER_SIZE + (i * TARGET_DATA_SIZE); - // Extract raw bytes for this target - // Note: Despite datasheet Table 5-2 showing order as X, Y, Speed, Resolution, - // actual radar output has Resolution before Speed (verified empirically - - // stationary targets were showing non-zero speed with original field order) + // Extract raw bytes for this target (per datasheet Table 5-2: X, Y, Speed, Resolution) uint8_t x_low = this->buffer_[offset + 0]; uint8_t x_high = this->buffer_[offset + 1]; uint8_t y_low = this->buffer_[offset + 2]; uint8_t y_high = this->buffer_[offset + 3]; - uint8_t res_low = this->buffer_[offset + 4]; - uint8_t res_high = this->buffer_[offset + 5]; - uint8_t speed_low = this->buffer_[offset + 6]; - uint8_t speed_high = this->buffer_[offset + 7]; + uint8_t speed_low = this->buffer_[offset + 4]; + uint8_t speed_high = this->buffer_[offset + 5]; + uint8_t res_low = this->buffer_[offset + 6]; + uint8_t res_high = this->buffer_[offset + 7]; // Decode values per RD-03D format int16_t x = decode_value(x_low, x_high); From be44d4801f578aeb4d6561f3a075872f4241724a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Feb 2026 10:52:43 +0100 Subject: [PATCH 0527/2030] [esp32] Reduce Arduino build size by 44% and build time by 36% (#13623) --- esphome/components/bme680_bsec/__init__.py | 3 +- esphome/components/esp32/__init__.py | 266 +++++++++++++++++- esphome/components/esp32/const.py | 1 + esphome/components/espnow/__init__.py | 5 +- esphome/components/ethernet/__init__.py | 3 - .../i2s_audio/media_player/__init__.py | 1 + esphome/components/midea/climate.py | 5 +- esphome/components/network/__init__.py | 3 +- .../components/web_server_base/__init__.py | 5 +- esphome/components/wled/__init__.py | 3 + esphome/core/__init__.py | 10 + esphome/writer.py | 15 +- .../components/i2s_audio/test.esp32-ard.yaml | 16 ++ tests/unit_tests/test_core.py | 75 +++++ 14 files changed, 384 insertions(+), 27 deletions(-) create mode 100644 tests/components/i2s_audio/test.esp32-ard.yaml diff --git a/esphome/components/bme680_bsec/__init__.py b/esphome/components/bme680_bsec/__init__.py index 06e641d34d..a86e061cd4 100644 --- a/esphome/components/bme680_bsec/__init__.py +++ b/esphome/components/bme680_bsec/__init__.py @@ -89,8 +89,9 @@ async def to_code(config): var.set_state_save_interval(config[CONF_STATE_SAVE_INTERVAL].total_milliseconds) ) - # Although this component does not use SPI, the BSEC library requires the SPI library + # Although this component does not use SPI/Wire directly, the BSEC library requires them cg.add_library("SPI", None) + cg.add_library("Wire", None) cg.add_define("USE_BSEC") cg.add_library("boschsensortec/BSEC Software Library", "1.6.1480") diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 77753e277f..e1e3164b68 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -46,10 +46,11 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache +from esphome.writer import clean_cmake_cache, rmtree from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa + KEY_ARDUINO_LIBRARIES, KEY_BOARD, KEY_COMPONENTS, KEY_ESP32, @@ -152,6 +153,168 @@ DEFAULT_EXCLUDED_IDF_COMPONENTS = ( "wifi_provisioning", # WiFi provisioning - ESPHome uses its own improv implementation ) +# Additional IDF managed components to exclude for Arduino framework builds +# These are pulled in by the Arduino framework's idf_component.yml but not used by ESPHome +# Note: Component names include the namespace prefix (e.g., "espressif__cbor") because +# that's how managed components are registered in the IDF build system +# List includes direct dependencies from arduino-esp32/idf_component.yml +# plus transitive dependencies from RainMaker/Insights (except espressif/mdns which we need) +ARDUINO_EXCLUDED_IDF_COMPONENTS = ( + "chmorgan__esp-libhelix-mp3", # MP3 decoder - not used + "espressif__cbor", # CBOR library - only used by RainMaker/Insights + "espressif__esp-dsp", # DSP library - not used + "espressif__esp-modbus", # Modbus - ESPHome has its own + "espressif__esp-sr", # Speech recognition - not used + "espressif__esp-zboss-lib", # Zigbee ZBOSS library - not used + "espressif__esp-zigbee-lib", # Zigbee library - not used + "espressif__esp_diag_data_store", # Diagnostics - not used + "espressif__esp_diagnostics", # Diagnostics - not used + "espressif__esp_hosted", # ESP hosted - only for ESP32-P4 + "espressif__esp_insights", # ESP Insights - not used + "espressif__esp_modem", # Modem library - not used + "espressif__esp_rainmaker", # RainMaker - not used + "espressif__esp_rcp_update", # RCP update - RainMaker transitive dep + "espressif__esp_schedule", # Schedule - RainMaker transitive dep + "espressif__esp_secure_cert_mgr", # Secure cert - RainMaker transitive dep + "espressif__esp_wifi_remote", # WiFi remote - only for ESP32-P4 + "espressif__json_generator", # JSON generator - RainMaker transitive dep + "espressif__json_parser", # JSON parser - RainMaker transitive dep + "espressif__lan867x", # Ethernet PHY - ESPHome uses ESP-IDF ethernet directly + "espressif__libsodium", # Crypto - ESPHome uses its own noise-c library + "espressif__network_provisioning", # Network provisioning - not used + "espressif__qrcode", # QR code - not used + "espressif__rmaker_common", # RainMaker common - not used + "joltwallet__littlefs", # LittleFS - ESPHome doesn't use filesystem +) + +# Mapping of Arduino libraries to IDF managed components they require +# When an Arduino library is enabled via cg.add_library(), these components +# are automatically un-stubbed from ARDUINO_EXCLUDED_IDF_COMPONENTS. +# +# Note: Some libraries (Matter, LittleFS, ESP_SR, WiFiProv, ArduinoOTA) already have +# conditional maybe_add_component() calls in arduino-esp32/CMakeLists.txt that handle +# their managed component dependencies. Our mapping is primarily needed for libraries +# that don't have such conditionals (Ethernet, PPP, Zigbee, RainMaker, Insights, etc.) +# and to ensure the stubs are removed from our idf_component.yml overrides. +ARDUINO_LIBRARY_IDF_COMPONENTS: dict[str, tuple[str, ...]] = { + "BLE": ("esp_driver_gptimer",), + "BluetoothSerial": ("esp_driver_gptimer",), + "ESP_HostedOTA": ("espressif__esp_hosted", "espressif__esp_wifi_remote"), + "ESP_SR": ("espressif__esp-sr",), + "Ethernet": ("espressif__lan867x",), + "FFat": ("fatfs",), + "Insights": ( + "espressif__cbor", + "espressif__esp_insights", + "espressif__esp_diagnostics", + "espressif__esp_diag_data_store", + "espressif__rmaker_common", # Transitive dep from esp_insights + ), + "LittleFS": ("joltwallet__littlefs",), + "Matter": ("espressif__esp_matter",), + "PPP": ("espressif__esp_modem",), + "RainMaker": ( + # Direct deps from idf_component.yml + "espressif__cbor", + "espressif__esp_rainmaker", + "espressif__esp_insights", + "espressif__esp_diagnostics", + "espressif__esp_diag_data_store", + "espressif__rmaker_common", + "espressif__qrcode", + # Transitive deps from esp_rainmaker + "espressif__esp_rcp_update", + "espressif__esp_schedule", + "espressif__esp_secure_cert_mgr", + "espressif__json_generator", + "espressif__json_parser", + "espressif__network_provisioning", + ), + "SD": ("fatfs",), + "SD_MMC": ("fatfs",), + "SPIFFS": ("spiffs",), + "WiFiProv": ("espressif__network_provisioning", "espressif__qrcode"), + "Zigbee": ("espressif__esp-zigbee-lib", "espressif__esp-zboss-lib"), +} + +# Arduino library to Arduino library dependencies +# When enabling one library, also enable its dependencies +# Kconfig "select" statements don't work with CONFIG_ARDUINO_SELECTIVE_COMPILATION +ARDUINO_LIBRARY_DEPENDENCIES: dict[str, tuple[str, ...]] = { + "Ethernet": ("Network",), + "WiFi": ("Network",), +} + + +def _idf_component_stub_name(component: str) -> str: + """Get stub directory name from IDF component name. + + Component names are typically namespace__name (e.g., espressif__cbor). + Returns just the name part (e.g., cbor). If no namespace is present, + returns the original component name. + """ + _prefix, sep, suffix = component.partition("__") + return suffix if sep else component + + +def _idf_component_dep_name(component: str) -> str: + """Convert IDF component name to dependency format. + + Converts espressif__cbor to espressif/cbor. + """ + return component.replace("__", "/") + + +# Arduino libraries to disable by default when using Arduino framework +# ESPHome uses ESP-IDF APIs directly; we only need the Arduino core +# (HardwareSerial, Print, Stream, GPIO functions which are always compiled) +# Components use cg.add_library() which auto-enables any they need +# This list must match ARDUINO_ALL_LIBRARIES from arduino-esp32/CMakeLists.txt +ARDUINO_DISABLED_LIBRARIES: frozenset[str] = frozenset( + { + "ArduinoOTA", + "AsyncUDP", + "BLE", + "BluetoothSerial", + "DNSServer", + "EEPROM", + "ESP_HostedOTA", + "ESP_I2S", + "ESP_NOW", + "ESP_SR", + "ESPmDNS", + "Ethernet", + "FFat", + "FS", + "Hash", + "HTTPClient", + "HTTPUpdate", + "Insights", + "LittleFS", + "Matter", + "NetBIOS", + "Network", + "NetworkClientSecure", + "OpenThread", + "PPP", + "Preferences", + "RainMaker", + "SD", + "SD_MMC", + "SimpleBLE", + "SPI", + "SPIFFS", + "Ticker", + "Update", + "USB", + "WebServer", + "WiFi", + "WiFiProv", + "Wire", + "Zigbee", + } +) + # ESP32 (original) chip revision options # Setting minimum revision to 3.0 or higher: # - Reduces flash size by excluding workaround code for older chip bugs @@ -243,7 +406,13 @@ def set_core_data(config): CORE.data[KEY_ESP32][KEY_COMPONENTS] = {} # Initialize with default exclusions - components can call include_builtin_idf_component() # to re-enable any they need - CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = set(DEFAULT_EXCLUDED_IDF_COMPONENTS) + excluded = set(DEFAULT_EXCLUDED_IDF_COMPONENTS) + # Add Arduino-specific managed component exclusions when using Arduino framework + if conf[CONF_TYPE] == FRAMEWORK_ARDUINO: + excluded.update(ARDUINO_EXCLUDED_IDF_COMPONENTS) + CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = excluded + # Initialize Arduino library tracking - cg.add_library() auto-enables libraries + CORE.data[KEY_ESP32][KEY_ARDUINO_LIBRARIES] = set() CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( config[CONF_FRAMEWORK][CONF_VERSION] ) @@ -391,6 +560,26 @@ def include_builtin_idf_component(name: str) -> None: CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS].discard(name) +def _enable_arduino_library(name: str) -> None: + """Enable an Arduino library that is disabled by default. + + This is called automatically by CORE.add_library() when a component adds + an Arduino library via cg.add_library(). Components should not call this + directly - just use cg.add_library("LibName", None). + + Args: + name: The library name (e.g., "Wire", "SPI", "WiFi") + """ + enabled_libs: set[str] = CORE.data[KEY_ESP32][KEY_ARDUINO_LIBRARIES] + enabled_libs.add(name) + # Also enable any required Arduino library dependencies + for dep_lib in ARDUINO_LIBRARY_DEPENDENCIES.get(name, ()): + enabled_libs.add(dep_lib) + # Also enable any required IDF components + for idf_component in ARDUINO_LIBRARY_IDF_COMPONENTS.get(name, ()): + include_builtin_idf_component(idf_component) + + def add_extra_script(stage: str, filename: str, path: Path): """Add an extra script to the project.""" key = f"{stage}:{filename}" @@ -1132,6 +1321,27 @@ async def _write_exclude_components() -> None: ) +@coroutine_with_priority(CoroPriority.FINAL) +async def _write_arduino_libraries_sdkconfig() -> None: + """Write Arduino selective compilation sdkconfig after all components have added libraries. + + This must run at FINAL priority so that all components have had a chance to call + cg.add_library() which auto-enables Arduino libraries via _enable_arduino_library(). + """ + if KEY_ESP32 not in CORE.data: + return + # Enable Arduino selective compilation to disable unused Arduino libraries + # ESPHome uses ESP-IDF APIs directly; we only need the Arduino core + # (HardwareSerial, Print, Stream, GPIO functions which are always compiled) + # cg.add_library() auto-enables needed libraries; users can also add + # libraries via esphome: libraries: config which calls cg.add_library() + add_idf_sdkconfig_option("CONFIG_ARDUINO_SELECTIVE_COMPILATION", True) + enabled_libs = CORE.data[KEY_ESP32].get(KEY_ARDUINO_LIBRARIES, set()) + for lib in ARDUINO_DISABLED_LIBRARIES: + # Enable if explicitly requested, disable otherwise + add_idf_sdkconfig_option(f"CONFIG_ARDUINO_SELECTIVE_{lib}", lib in enabled_libs) + + @coroutine_with_priority(CoroPriority.FINAL) async def _add_yaml_idf_components(components: list[ConfigType]): """Add IDF components from YAML config with final priority to override code-added components.""" @@ -1550,6 +1760,11 @@ async def to_code(config): # Default exclusions are added in set_core_data() during config validation. CORE.add_job(_write_exclude_components) + # Write Arduino selective compilation sdkconfig at FINAL priority after all + # components have had a chance to call cg.add_library() to enable libraries they need. + if conf[CONF_TYPE] == FRAMEWORK_ARDUINO: + CORE.add_job(_write_arduino_libraries_sdkconfig) + APP_PARTITION_SIZES = { "2MB": 0x0C0000, # 768 KB @@ -1630,11 +1845,49 @@ def _write_sdkconfig(): def _write_idf_component_yml(): yml_path = CORE.relative_build_path("src/idf_component.yml") + dependencies: dict[str, dict] = {} + + # For Arduino builds, override unused managed components from the Arduino framework + # by pointing them to empty stub directories using override_path + # This prevents the IDF component manager from downloading the real components + if CORE.using_arduino: + # Determine which IDF components are needed by enabled Arduino libraries + enabled_libs = CORE.data[KEY_ESP32].get(KEY_ARDUINO_LIBRARIES, set()) + required_idf_components = { + comp + for lib in enabled_libs + for comp in ARDUINO_LIBRARY_IDF_COMPONENTS.get(lib, ()) + } + + # Only stub components that are not required by any enabled Arduino library + components_to_stub = ( + set(ARDUINO_EXCLUDED_IDF_COMPONENTS) - required_idf_components + ) + + stubs_dir = CORE.relative_build_path("component_stubs") + stubs_dir.mkdir(exist_ok=True) + for component_name in components_to_stub: + # Create stub directory with minimal CMakeLists.txt + stub_path = stubs_dir / _idf_component_stub_name(component_name) + stub_path.mkdir(exist_ok=True) + stub_cmake = stub_path / "CMakeLists.txt" + if not stub_cmake.exists(): + stub_cmake.write_text("idf_component_register()\n") + dependencies[_idf_component_dep_name(component_name)] = { + "version": "*", + "override_path": str(stub_path), + } + + # Remove stubs for components that are now required by enabled libraries + for component_name in required_idf_components: + stub_path = stubs_dir / _idf_component_stub_name(component_name) + if stub_path.exists(): + rmtree(stub_path) + if CORE.data[KEY_ESP32][KEY_COMPONENTS]: components: dict = CORE.data[KEY_ESP32][KEY_COMPONENTS] - dependencies = {} for name, component in components.items(): - dependency = {} + dependency: dict[str, str] = {} if component[KEY_REF]: dependency["version"] = component[KEY_REF] if component[KEY_REPO]: @@ -1642,9 +1895,8 @@ def _write_idf_component_yml(): if component[KEY_PATH]: dependency["path"] = component[KEY_PATH] dependencies[name] = dependency - contents = yaml_util.dump({"dependencies": dependencies}) - else: - contents = "" + + contents = yaml_util.dump({"dependencies": dependencies}) if dependencies else "" if write_file_if_changed(yml_path, contents): dependencies_lock = CORE.relative_build_path("dependencies.lock") if dependencies_lock.is_file(): diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index db3eddebd5..7874c1c759 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -7,6 +7,7 @@ KEY_VARIANT = "variant" KEY_SDKCONFIG_OPTIONS = "sdkconfig_options" KEY_COMPONENTS = "components" KEY_EXCLUDE_COMPONENTS = "exclude_components" +KEY_ARDUINO_LIBRARIES = "arduino_libraries" KEY_REPO = "repo" KEY_REF = "ref" KEY_REFRESH = "refresh" diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 1f5ca1104a..faeccd910e 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -13,7 +13,7 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_WIFI, ) -from esphome.core import CORE, HexInt +from esphome.core import HexInt from esphome.types import ConfigType CODEOWNERS = ["@jesserockz"] @@ -124,9 +124,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - if CORE.using_arduino: - cg.add_library("WiFi", None) - # ESP-NOW uses wake_loop_threadsafe() to wake the main loop from ESP-NOW callbacks # This enables low-latency event processing instead of waiting for select() timeout socket.require_wake_loop_threadsafe() diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 23436cc5be..38489ceb2b 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -431,9 +431,6 @@ async def to_code(config): # Add LAN867x 10BASE-T1S PHY support component add_idf_component(name="espressif/lan867x", ref="2.0.0") - if CORE.using_arduino: - cg.add_library("WiFi", None) - if on_connect_config := config.get(CONF_ON_CONNECT): cg.add_define("USE_ETHERNET_CONNECT_TRIGGER") await automation.build_automation( diff --git a/esphome/components/i2s_audio/media_player/__init__.py b/esphome/components/i2s_audio/media_player/__init__.py index 35c42e1b06..426b211f47 100644 --- a/esphome/components/i2s_audio/media_player/__init__.py +++ b/esphome/components/i2s_audio/media_player/__init__.py @@ -114,6 +114,7 @@ async def to_code(config): cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1)) cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb")) + cg.add_library("WiFi", None) cg.add_library("NetworkClientSecure", None) cg.add_library("HTTPClient", None) cg.add_library("esphome/ESP32-audioI2S", "2.3.0") diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index b08a47afa9..8a3d4f22ba 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -30,7 +30,7 @@ from esphome.const import ( UNIT_PERCENT, UNIT_WATT, ) -from esphome.core import coroutine +from esphome.core import CORE, coroutine CODEOWNERS = ["@dudanov"] DEPENDENCIES = ["climate", "uart"] @@ -290,4 +290,7 @@ async def to_code(config): if CONF_HUMIDITY_SETPOINT in config: sens = await sensor.new_sensor(config[CONF_HUMIDITY_SETPOINT]) cg.add(var.set_humidity_setpoint_sensor(sens)) + # MideaUART library requires WiFi (WiFi auto-enables Network via dependency mapping) + if CORE.is_esp32: + cg.add_library("WiFi", None) cg.add_library("dudanov/MideaUART", "1.1.9") diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index 5b63bbfce9..1f75b12178 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -137,8 +137,7 @@ CONFIG_SCHEMA = cv.Schema( @coroutine_with_priority(CoroPriority.NETWORK) async def to_code(config): cg.add_define("USE_NETWORK") - if CORE.using_arduino and CORE.is_esp32: - cg.add_library("Networking", None) + # ESP32 with Arduino uses ESP-IDF network APIs directly, no Arduino Network library needed # Apply high performance networking settings # Config can explicitly enable/disable, or default to component-driven behavior diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 6326b4d6ff..11408ae260 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -38,11 +38,8 @@ async def to_code(config): cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1) return + # ESP32 uses IDF web server (early return above), so this is for other Arduino platforms if CORE.using_arduino: - if CORE.is_esp32: - cg.add_library("WiFi", None) - cg.add_library("FS", None) - cg.add_library("Update", None) if CORE.is_esp8266: cg.add_library("ESP8266WiFi", None) if CORE.is_libretiny: diff --git a/esphome/components/wled/__init__.py b/esphome/components/wled/__init__.py index fb20a03010..49eb15dad6 100644 --- a/esphome/components/wled/__init__.py +++ b/esphome/components/wled/__init__.py @@ -3,6 +3,7 @@ from esphome.components.light.effects import register_addressable_effect from esphome.components.light.types import AddressableLightEffect import esphome.config_validation as cv from esphome.const import CONF_NAME, CONF_PORT +from esphome.core import CORE wled_ns = cg.esphome_ns.namespace("wled") WLEDLightEffect = wled_ns.class_("WLEDLightEffect", AddressableLightEffect) @@ -27,4 +28,6 @@ async def wled_light_effect_to_code(config, effect_id): cg.add(effect.set_port(config[CONF_PORT])) cg.add(effect.set_sync_group_mask(config[CONF_SYNC_GROUP_MASK])) cg.add(effect.set_blank_on_start(config[CONF_BLANK_ON_START])) + if CORE.is_esp32: + cg.add_library("WiFi", None) return effect diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 5308ad241e..484f679369 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -892,6 +892,16 @@ class EsphomeCore: library.name if "/" not in library.name else library.name.split("/")[-1] ) + # Auto-enable Arduino libraries on ESP32 Arduino builds + if self.is_esp32 and self.using_arduino: + from esphome.components.esp32 import ( + ARDUINO_DISABLED_LIBRARIES, + _enable_arduino_library, + ) + + if short_name in ARDUINO_DISABLED_LIBRARIES: + _enable_arduino_library(short_name) + if short_name not in self.platformio_libraries: _LOGGER.debug("Adding library: %s", library) self.platformio_libraries[short_name] = library diff --git a/esphome/writer.py b/esphome/writer.py index cb9c921693..661118e518 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -421,6 +421,11 @@ def _rmtree_error_handler( func(path) +def rmtree(path: Path | str) -> None: + """Remove a directory tree, handling read-only files on Windows.""" + shutil.rmtree(path, onerror=_rmtree_error_handler) + + def clean_build(clear_pio_cache: bool = True): # Allow skipping cache cleaning for integration tests if os.environ.get("ESPHOME_SKIP_CLEAN_BUILD"): @@ -430,11 +435,11 @@ def clean_build(clear_pio_cache: bool = True): pioenvs = CORE.relative_pioenvs_path() if pioenvs.is_dir(): _LOGGER.info("Deleting %s", pioenvs) - shutil.rmtree(pioenvs, onerror=_rmtree_error_handler) + rmtree(pioenvs) piolibdeps = CORE.relative_piolibdeps_path() if piolibdeps.is_dir(): _LOGGER.info("Deleting %s", piolibdeps) - shutil.rmtree(piolibdeps, onerror=_rmtree_error_handler) + rmtree(piolibdeps) dependencies_lock = CORE.relative_build_path("dependencies.lock") if dependencies_lock.is_file(): _LOGGER.info("Deleting %s", dependencies_lock) @@ -455,7 +460,7 @@ def clean_build(clear_pio_cache: bool = True): cache_dir = Path(config.get("platformio", "cache_dir")) if cache_dir.is_dir(): _LOGGER.info("Deleting PlatformIO cache %s", cache_dir) - shutil.rmtree(cache_dir, onerror=_rmtree_error_handler) + rmtree(cache_dir) def clean_all(configuration: list[str]): @@ -480,7 +485,7 @@ def clean_all(configuration: list[str]): if item.is_file() and not item.name.endswith(".json"): item.unlink() elif item.is_dir() and item.name != "storage": - shutil.rmtree(item, onerror=_rmtree_error_handler) + rmtree(item) # Clean PlatformIO project files try: @@ -494,7 +499,7 @@ def clean_all(configuration: list[str]): path = Path(config.get("platformio", pio_dir)) if path.is_dir(): _LOGGER.info("Deleting PlatformIO %s %s", pio_dir, path) - shutil.rmtree(path, onerror=_rmtree_error_handler) + rmtree(path) GITIGNORE_CONTENT = """# Gitignore settings for ESPHome diff --git a/tests/components/i2s_audio/test.esp32-ard.yaml b/tests/components/i2s_audio/test.esp32-ard.yaml new file mode 100644 index 0000000000..4276b4f922 --- /dev/null +++ b/tests/components/i2s_audio/test.esp32-ard.yaml @@ -0,0 +1,16 @@ +substitutions: + i2s_bclk_pin: GPIO15 + i2s_lrclk_pin: GPIO4 + i2s_mclk_pin: GPIO5 + +<<: !include common.yaml + +wifi: + ssid: test + password: test1234 + +media_player: + - platform: i2s_audio + name: Test Media Player + dac_type: internal + mode: stereo diff --git a/tests/unit_tests/test_core.py b/tests/unit_tests/test_core.py index 1fc8dab358..174b3fec85 100644 --- a/tests/unit_tests/test_core.py +++ b/tests/unit_tests/test_core.py @@ -780,3 +780,78 @@ class TestEsphomeCore: target.config = {const.CONF_ESPHOME: {"name": "test"}, "logger": {}} assert target.has_networking is False + + def test_add_library__esp32_arduino_enables_disabled_library(self, target): + """Test add_library auto-enables Arduino libraries on ESP32 Arduino builds.""" + target.data[const.KEY_CORE] = { + const.KEY_TARGET_PLATFORM: "esp32", + const.KEY_TARGET_FRAMEWORK: "arduino", + } + + library = core.Library("WiFi", None) + + with patch("esphome.components.esp32._enable_arduino_library") as mock_enable: + target.add_library(library) + mock_enable.assert_called_once_with("WiFi") + + assert "WiFi" in target.platformio_libraries + + def test_add_library__esp32_arduino_ignores_non_arduino_library(self, target): + """Test add_library doesn't enable libraries not in ARDUINO_DISABLED_LIBRARIES.""" + target.data[const.KEY_CORE] = { + const.KEY_TARGET_PLATFORM: "esp32", + const.KEY_TARGET_FRAMEWORK: "arduino", + } + + library = core.Library("SomeOtherLib", "1.0.0") + + with patch("esphome.components.esp32._enable_arduino_library") as mock_enable: + target.add_library(library) + mock_enable.assert_not_called() + + assert "SomeOtherLib" in target.platformio_libraries + + def test_add_library__esp32_idf_does_not_enable_arduino_library(self, target): + """Test add_library doesn't auto-enable Arduino libraries on ESP32 IDF builds.""" + target.data[const.KEY_CORE] = { + const.KEY_TARGET_PLATFORM: "esp32", + const.KEY_TARGET_FRAMEWORK: "esp-idf", + } + + library = core.Library("WiFi", None) + + with patch("esphome.components.esp32._enable_arduino_library") as mock_enable: + target.add_library(library) + mock_enable.assert_not_called() + + assert "WiFi" in target.platformio_libraries + + def test_add_library__esp8266_does_not_enable_arduino_library(self, target): + """Test add_library doesn't auto-enable Arduino libraries on ESP8266.""" + target.data[const.KEY_CORE] = { + const.KEY_TARGET_PLATFORM: "esp8266", + const.KEY_TARGET_FRAMEWORK: "arduino", + } + + library = core.Library("WiFi", None) + + with patch("esphome.components.esp32._enable_arduino_library") as mock_enable: + target.add_library(library) + mock_enable.assert_not_called() + + assert "WiFi" in target.platformio_libraries + + def test_add_library__extracts_short_name_from_path(self, target): + """Test add_library extracts short name from library paths like owner/lib.""" + target.data[const.KEY_CORE] = { + const.KEY_TARGET_PLATFORM: "esp32", + const.KEY_TARGET_FRAMEWORK: "arduino", + } + + library = core.Library("arduino/Wire", None) + + with patch("esphome.components.esp32._enable_arduino_library") as mock_enable: + target.add_library(library) + mock_enable.assert_called_once_with("Wire") + + assert "Wire" in target.platformio_libraries From ed8c0dc99d519f492e51d1f054f5ea9d5e07fe5b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Feb 2026 05:55:08 -0500 Subject: [PATCH 0528/2030] [esp32] Skip downloading precompiled Arduino libs (#13775) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 33 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index e1e3164b68..f5a8bc8994 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -95,6 +95,11 @@ CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision" CONF_RELEASE = "release" +ARDUINO_FRAMEWORK_NAME = "framework-arduinoespressif32" +ARDUINO_FRAMEWORK_PKG = f"pioarduino/{ARDUINO_FRAMEWORK_NAME}" +ARDUINO_LIBS_NAME = f"{ARDUINO_FRAMEWORK_NAME}-libs" +ARDUINO_LIBS_PKG = f"pioarduino/{ARDUINO_LIBS_NAME}" + LOG_LEVELS_IDF = [ "NONE", "ERROR", @@ -599,14 +604,12 @@ def add_extra_build_file(filename: str, path: Path) -> bool: def _format_framework_arduino_version(ver: cv.Version) -> str: - # format the given arduino (https://github.com/espressif/arduino-esp32/releases) version to - # a PIO pioarduino/framework-arduinoespressif32 value # 3.3.6+ changed filename from esp32-{ver}.zip to esp32-core-{ver}.tar.xz if ver >= cv.Version(3, 3, 6): filename = f"esp32-core-{ver}.tar.xz" else: filename = f"esp32-{ver}.zip" - return f"pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/{ver}/{filename}" + return f"{ARDUINO_FRAMEWORK_PKG}@https://github.com/espressif/arduino-esp32/releases/download/{ver}/{filename}" def _format_framework_espidf_version(ver: cv.Version, release: str) -> str: @@ -741,9 +744,7 @@ def _check_versions(config): CONF_SOURCE, _format_framework_arduino_version(version) ) if _is_framework_url(value[CONF_SOURCE]): - value[CONF_SOURCE] = ( - f"pioarduino/framework-arduinoespressif32@{value[CONF_SOURCE]}" - ) + value[CONF_SOURCE] = f"{ARDUINO_FRAMEWORK_PKG}@{value[CONF_SOURCE]}" else: if version < cv.Version(5, 0, 0): raise cv.Invalid("Only ESP-IDF 5.0+ is supported.") @@ -1321,6 +1322,20 @@ async def _write_exclude_components() -> None: ) +@coroutine_with_priority(CoroPriority.FINAL) +async def _write_arduino_libs_stub(stubs_dir: Path, idf_ver: cv.Version) -> None: + """Write stub package to skip downloading precompiled Arduino libs.""" + stubs_dir.mkdir(parents=True, exist_ok=True) + write_file_if_changed( + stubs_dir / "package.json", + f'{{"name":"{ARDUINO_LIBS_NAME}","version":"{idf_ver.major}.{idf_ver.minor}.{idf_ver.patch}"}}', + ) + write_file_if_changed( + stubs_dir / "tools.json", + '{"packages":[{"platforms":[{"toolsDependencies":[]}],"tools":[]}]}', + ) + + @coroutine_with_priority(CoroPriority.FINAL) async def _write_arduino_libraries_sdkconfig() -> None: """Write Arduino selective compilation sdkconfig after all components have added libraries. @@ -1451,6 +1466,12 @@ async def to_code(config): "platform_packages", [_format_framework_espidf_version(idf_ver, None)], ) + # Use stub package to skip downloading precompiled libs + stubs_dir = CORE.relative_build_path("arduino-libs-stub") + cg.add_platformio_option( + "platform_packages", [f"{ARDUINO_LIBS_PKG}@file://{stubs_dir}"] + ) + CORE.add_job(_write_arduino_libs_stub, stubs_dir, idf_ver) # ESP32-S2 Arduino: Disable USB Serial on boot to avoid TinyUSB dependency if get_esp32_variant() == VARIANT_ESP32S2: From 9ea846144008ff78f082e0987132047b7092a726 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Feb 2026 06:41:17 -0500 Subject: [PATCH 0529/2030] [esp32] Remove specific claims from framework migration message (#13777) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index f5a8bc8994..0c02f6fbee 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1169,8 +1169,8 @@ def _show_framework_migration_message(name: str, variant: str) -> None: + "(We've been warning about this change since ESPHome 2025.8.0)\n" + "\n" + "Why we made this change:\n" - + color(AnsiFore.GREEN, " ✨ Up to 40% smaller firmware binaries\n") - + color(AnsiFore.GREEN, " ⚡ 2-3x faster compile times\n") + + color(AnsiFore.GREEN, " ✨ Smaller firmware binaries\n") + + color(AnsiFore.GREEN, " ⚡ Faster compile times\n") + color(AnsiFore.GREEN, " 🚀 Better performance and newer features\n") + color(AnsiFore.GREEN, " 🔧 More actively maintained by ESPHome\n") + "\n" From bbdb202e2c53358dbd20076a748bc743500371e6 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:26:47 +0100 Subject: [PATCH 0530/2030] [epaper_spi] Refactor initialise for future use (#13774) --- esphome/components/epaper_spi/epaper_spi.cpp | 13 +++++++++---- esphome/components/epaper_spi/epaper_spi.h | 3 ++- esphome/components/epaper_spi/epaper_waveshare.cpp | 3 ++- esphome/components/epaper_spi/epaper_waveshare.h | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/esphome/components/epaper_spi/epaper_spi.cpp b/esphome/components/epaper_spi/epaper_spi.cpp index db803305a5..ae1923a916 100644 --- a/esphome/components/epaper_spi/epaper_spi.cpp +++ b/esphome/components/epaper_spi/epaper_spi.cpp @@ -182,7 +182,9 @@ void EPaperBase::process_state_() { this->set_state_(EPaperState::RESET); break; case EPaperState::INITIALISE: - this->initialise(this->update_count_ != 0); + if (!this->initialise(this->update_count_ != 0)) { + return; // Not done yet, come back next loop + } this->set_state_(EPaperState::TRANSFER_DATA); break; case EPaperState::TRANSFER_DATA: @@ -239,11 +241,9 @@ void EPaperBase::start_data_() { void EPaperBase::on_safe_shutdown() { this->deep_sleep(); } -void EPaperBase::initialise(bool partial) { +void EPaperBase::send_init_sequence_(const uint8_t *sequence, size_t length) { size_t index = 0; - auto *sequence = this->init_sequence_; - auto length = this->init_sequence_length_; while (index != length) { if (length - index < 2) { this->mark_failed(LOG_STR("Malformed init sequence")); @@ -266,6 +266,11 @@ void EPaperBase::initialise(bool partial) { } } +bool EPaperBase::initialise(bool partial) { + this->send_init_sequence_(this->init_sequence_, this->init_sequence_length_); + return true; +} + /** * Check and rotate coordinates based on the transform flags. * @param x diff --git a/esphome/components/epaper_spi/epaper_spi.h b/esphome/components/epaper_spi/epaper_spi.h index 521543f026..a8c2fe9b56 100644 --- a/esphome/components/epaper_spi/epaper_spi.h +++ b/esphome/components/epaper_spi/epaper_spi.h @@ -115,7 +115,8 @@ class EPaperBase : public Display, bool is_idle_() const; void setup_pins_() const; virtual bool reset(); - virtual void initialise(bool partial); + virtual bool initialise(bool partial); + void send_init_sequence_(const uint8_t *sequence, size_t length); void wait_for_idle_(bool should_wait); bool init_buffer_(size_t buffer_length); bool rotate_coordinates_(int &x, int &y); diff --git a/esphome/components/epaper_spi/epaper_waveshare.cpp b/esphome/components/epaper_spi/epaper_waveshare.cpp index 8d382d86e7..7a7b4e22d3 100644 --- a/esphome/components/epaper_spi/epaper_waveshare.cpp +++ b/esphome/components/epaper_spi/epaper_waveshare.cpp @@ -4,7 +4,7 @@ namespace esphome::epaper_spi { static const char *const TAG = "epaper_spi.waveshare"; -void EpaperWaveshare::initialise(bool partial) { +bool EpaperWaveshare::initialise(bool partial) { EPaperBase::initialise(partial); if (partial) { this->cmd_data(0x32, this->partial_lut_, this->partial_lut_length_); @@ -17,6 +17,7 @@ void EpaperWaveshare::initialise(bool partial) { this->cmd_data(0x3C, {0x05}); } this->send_red_ = true; + return true; } void EpaperWaveshare::set_window() { diff --git a/esphome/components/epaper_spi/epaper_waveshare.h b/esphome/components/epaper_spi/epaper_waveshare.h index 6b894cfd09..15fb575ca0 100644 --- a/esphome/components/epaper_spi/epaper_waveshare.h +++ b/esphome/components/epaper_spi/epaper_waveshare.h @@ -18,7 +18,7 @@ class EpaperWaveshare : public EPaperMono { partial_lut_length_(partial_lut_length) {} protected: - void initialise(bool partial) override; + bool initialise(bool partial) override; void set_window() override; void refresh_screen(bool partial) override; void deep_sleep() override; From f4e410f47f92199def4494525d121528b4504bc0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Feb 2026 14:56:43 +0100 Subject: [PATCH 0531/2030] [ci] Block new scanf() usage to prevent ~9.8KB flash bloat (#13657) --- script/ci-custom.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/script/ci-custom.py b/script/ci-custom.py index b146c9867e..b5bec74fa7 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -756,6 +756,28 @@ def lint_no_sprintf(fname, match): ) +@lint_re_check( + # Match scanf family functions: scanf, sscanf, fscanf, vscanf, vsscanf, vfscanf + # Also match std:: prefixed versions + # [^\w] ensures we match function calls, not substrings + r"[^\w]((?:std::)?v?[fs]?scanf)\s*\(" + CPP_RE_EOL, + include=cpp_include, +) +def lint_no_scanf(fname, match): + func = match.group(1) + return ( + f"{highlight(func + '()')} is not allowed in new ESPHome code. The scanf family " + f"pulls in ~7KB flash on ESP8266 and ~9KB on ESP32, and ESPHome doesn't otherwise " + f"need this code.\n" + f"Please use alternatives:\n" + f" - {highlight('parse_number<T>(str)')} for parsing integers/floats from strings\n" + f" - {highlight('strtol()/strtof()')} for C-style number parsing with error checking\n" + f" - {highlight('parse_hex()')} for hex string parsing\n" + f" - Manual parsing for simple fixed formats\n" + f"(If strictly necessary, add `// NOLINT` to the end of the line)" + ) + + @lint_content_find_check( "ESP_LOG", include=["*.h", "*.tcc"], From 081f953dc330cdf22e09c3286b9d957477f68c95 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Feb 2026 09:00:16 -0500 Subject: [PATCH 0532/2030] [core] Add capacity check to register_component_ (#13778) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/core/application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 0e77be9ee4..0daabc0282 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -81,6 +81,10 @@ void Application::register_component_(Component *comp) { return; } } + if (this->components_.size() >= ESPHOME_COMPONENT_COUNT) { + ESP_LOGE(TAG, "Cannot register component %s - at capacity!", LOG_STR_ARG(comp->get_component_log_str())); + return; + } this->components_.push_back(comp); } void Application::setup() { From 55ef8393afd40baf100424c0ef0a01efa25ffc08 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Feb 2026 15:19:03 +0100 Subject: [PATCH 0533/2030] [api] Remove is_single parameter and fix batch buffer preparation (#13773) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_connection.cpp | 354 +++++++++------------- esphome/components/api/api_connection.h | 176 ++++------- esphome/components/api/api_pb2_service.h | 2 +- esphome/components/api/proto.h | 32 +- script/api_protobuf/api_protobuf.py | 2 +- 5 files changed, 221 insertions(+), 345 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 839de29de7..2aa5956f24 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -300,7 +300,7 @@ void APIConnection::on_disconnect_response(const DisconnectResponse &value) { // Encodes a message to the buffer and returns the total number of bytes used, // including header and footer overhead. Returns 0 if the message doesn't fit. uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, - uint32_t remaining_size, bool is_single) { + uint32_t remaining_size) { #ifdef HAS_PROTO_MESSAGE_DUMP // If in log-only mode, just log and return if (conn->flags_.log_only_mode) { @@ -330,12 +330,9 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess // Get buffer size after allocation (which includes header padding) std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); - if (is_single || conn->flags_.batch_first_message) { - // Single message or first batch message - conn->prepare_first_message_buffer(shared_buf, header_padding, total_calculated_size); - if (conn->flags_.batch_first_message) { - conn->flags_.batch_first_message = false; - } + if (conn->flags_.batch_first_message) { + // First message - buffer already prepared by caller, just clear flag + conn->flags_.batch_first_message = false; } else { // Batch message second or later // Add padding for previous message footer + this message header @@ -365,24 +362,22 @@ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary BinarySensorStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); BinarySensorStateResponse resp; resp.state = binary_sensor->state; resp.missing_state = !binary_sensor->has_state(); return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn, - remaining_size, is_single); + remaining_size); } -uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); ListEntitiesBinarySensorResponse msg; msg.device_class = binary_sensor->get_device_class_ref(); msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor(); return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, - remaining_size, is_single); + remaining_size); } #endif @@ -390,8 +385,7 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne bool APIConnection::send_cover_state(cover::Cover *cover) { return this->send_message_smart_(cover, CoverStateResponse::MESSAGE_TYPE, CoverStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *cover = static_cast<cover::Cover *>(entity); CoverStateResponse msg; auto traits = cover->get_traits(); @@ -399,10 +393,9 @@ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection * if (traits.get_supports_tilt()) msg.tilt = cover->tilt; msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation); - return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *cover = static_cast<cover::Cover *>(entity); ListEntitiesCoverResponse msg; auto traits = cover->get_traits(); @@ -411,8 +404,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c msg.supports_tilt = traits.get_supports_tilt(); msg.supports_stop = traits.get_supports_stop(); msg.device_class = cover->get_device_class_ref(); - return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::cover_command(const CoverCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover) @@ -430,8 +422,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) { bool APIConnection::send_fan_state(fan::Fan *fan) { return this->send_message_smart_(fan, FanStateResponse::MESSAGE_TYPE, FanStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *fan = static_cast<fan::Fan *>(entity); FanStateResponse msg; auto traits = fan->get_traits(); @@ -445,10 +436,9 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co msg.direction = static_cast<enums::FanDirection>(fan->direction); if (traits.supports_preset_modes() && fan->has_preset_mode()) msg.preset_mode = fan->get_preset_mode(); - return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *fan = static_cast<fan::Fan *>(entity); ListEntitiesFanResponse msg; auto traits = fan->get_traits(); @@ -457,7 +447,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con msg.supports_direction = traits.supports_direction(); msg.supported_speed_count = traits.supported_speed_count(); msg.supported_preset_modes = &traits.supported_preset_modes(); - return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::fan_command(const FanCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan) @@ -481,8 +471,7 @@ void APIConnection::fan_command(const FanCommandRequest &msg) { bool APIConnection::send_light_state(light::LightState *light) { return this->send_message_smart_(light, LightStateResponse::MESSAGE_TYPE, LightStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *light = static_cast<light::LightState *>(entity); LightStateResponse resp; auto values = light->remote_values; @@ -501,10 +490,9 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection * if (light->supports_effects()) { resp.effect = light->get_effect_name(); } - return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *light = static_cast<light::LightState *>(entity); ListEntitiesLightResponse msg; auto traits = light->get_traits(); @@ -527,8 +515,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c } } msg.effects = &effects_list; - return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::light_command(const LightCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light) @@ -568,17 +555,15 @@ bool APIConnection::send_sensor_state(sensor::Sensor *sensor) { return this->send_message_smart_(sensor, SensorStateResponse::MESSAGE_TYPE, SensorStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *sensor = static_cast<sensor::Sensor *>(entity); SensorStateResponse resp; resp.state = sensor->state; resp.missing_state = !sensor->has_state(); - return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *sensor = static_cast<sensor::Sensor *>(entity); ListEntitiesSensorResponse msg; msg.unit_of_measurement = sensor->get_unit_of_measurement_ref(); @@ -586,8 +571,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection * msg.force_update = sensor->get_force_update(); msg.device_class = sensor->get_device_class_ref(); msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class()); - return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -596,23 +580,19 @@ bool APIConnection::send_switch_state(switch_::Switch *a_switch) { return this->send_message_smart_(a_switch, SwitchStateResponse::MESSAGE_TYPE, SwitchStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *a_switch = static_cast<switch_::Switch *>(entity); SwitchStateResponse resp; resp.state = a_switch->state; - return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *a_switch = static_cast<switch_::Switch *>(entity); ListEntitiesSwitchResponse msg; msg.assumed_state = a_switch->assumed_state(); msg.device_class = a_switch->get_device_class_ref(); - return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::switch_command(const SwitchCommandRequest &msg) { ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch) @@ -631,22 +611,19 @@ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) TextSensorStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); TextSensorStateResponse resp; resp.state = StringRef(text_sensor->state); resp.missing_state = !text_sensor->has_state(); - return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); ListEntitiesTextSensorResponse msg; msg.device_class = text_sensor->get_device_class_ref(); return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, - remaining_size, is_single); + remaining_size); } #endif @@ -654,8 +631,7 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect bool APIConnection::send_climate_state(climate::Climate *climate) { return this->send_message_smart_(climate, ClimateStateResponse::MESSAGE_TYPE, ClimateStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *climate = static_cast<climate::Climate *>(entity); ClimateStateResponse resp; auto traits = climate->get_traits(); @@ -687,11 +663,9 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection resp.current_humidity = climate->current_humidity; if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) resp.target_humidity = climate->target_humidity; - return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *climate = static_cast<climate::Climate *>(entity); ListEntitiesClimateResponse msg; auto traits = climate->get_traits(); @@ -716,8 +690,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection msg.supported_presets = &traits.get_supported_presets(); msg.supported_custom_presets = &traits.get_supported_custom_presets(); msg.supported_swing_modes = &traits.get_supported_swing_modes(); - return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::climate_command(const ClimateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate) @@ -750,17 +723,15 @@ bool APIConnection::send_number_state(number::Number *number) { return this->send_message_smart_(number, NumberStateResponse::MESSAGE_TYPE, NumberStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *number = static_cast<number::Number *>(entity); NumberStateResponse resp; resp.state = number->state; resp.missing_state = !number->has_state(); - return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *number = static_cast<number::Number *>(entity); ListEntitiesNumberResponse msg; msg.unit_of_measurement = number->traits.get_unit_of_measurement_ref(); @@ -769,8 +740,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection * msg.min_value = number->traits.get_min_value(); msg.max_value = number->traits.get_max_value(); msg.step = number->traits.get_step(); - return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::number_command(const NumberCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(number::Number, number, number) @@ -783,22 +753,19 @@ void APIConnection::number_command(const NumberCommandRequest &msg) { bool APIConnection::send_date_state(datetime::DateEntity *date) { return this->send_message_smart_(date, DateStateResponse::MESSAGE_TYPE, DateStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *date = static_cast<datetime::DateEntity *>(entity); DateStateResponse resp; resp.missing_state = !date->has_state(); resp.year = date->year; resp.month = date->month; resp.day = date->day; - return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *date = static_cast<datetime::DateEntity *>(entity); ListEntitiesDateResponse msg; - return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::date_command(const DateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date) @@ -811,22 +778,19 @@ void APIConnection::date_command(const DateCommandRequest &msg) { bool APIConnection::send_time_state(datetime::TimeEntity *time) { return this->send_message_smart_(time, TimeStateResponse::MESSAGE_TYPE, TimeStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *time = static_cast<datetime::TimeEntity *>(entity); TimeStateResponse resp; resp.missing_state = !time->has_state(); resp.hour = time->hour; resp.minute = time->minute; resp.second = time->second; - return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *time = static_cast<datetime::TimeEntity *>(entity); ListEntitiesTimeResponse msg; - return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::time_command(const TimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time) @@ -840,8 +804,7 @@ bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) { return this->send_message_smart_(datetime, DateTimeStateResponse::MESSAGE_TYPE, DateTimeStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *datetime = static_cast<datetime::DateTimeEntity *>(entity); DateTimeStateResponse resp; resp.missing_state = !datetime->has_state(); @@ -849,15 +812,12 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio ESPTime state = datetime->state_as_esptime(); resp.epoch_seconds = state.timestamp; } - return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *datetime = static_cast<datetime::DateTimeEntity *>(entity); ListEntitiesDateTimeResponse msg; - return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime) @@ -871,25 +831,22 @@ bool APIConnection::send_text_state(text::Text *text) { return this->send_message_smart_(text, TextStateResponse::MESSAGE_TYPE, TextStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text = static_cast<text::Text *>(entity); TextStateResponse resp; resp.state = StringRef(text->state); resp.missing_state = !text->has_state(); - return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text = static_cast<text::Text *>(entity); ListEntitiesTextResponse msg; msg.mode = static_cast<enums::TextMode>(text->traits.get_mode()); msg.min_length = text->traits.get_min_length(); msg.max_length = text->traits.get_max_length(); msg.pattern = text->traits.get_pattern_ref(); - return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::text_command(const TextCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(text::Text, text, text) @@ -903,22 +860,19 @@ bool APIConnection::send_select_state(select::Select *select) { return this->send_message_smart_(select, SelectStateResponse::MESSAGE_TYPE, SelectStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *select = static_cast<select::Select *>(entity); SelectStateResponse resp; resp.state = select->current_option(); resp.missing_state = !select->has_state(); - return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *select = static_cast<select::Select *>(entity); ListEntitiesSelectResponse msg; msg.options = &select->traits.get_options(); - return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::select_command(const SelectCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(select::Select, select, select) @@ -928,13 +882,11 @@ void APIConnection::select_command(const SelectCommandRequest &msg) { #endif #ifdef USE_BUTTON -uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *button = static_cast<button::Button *>(entity); ListEntitiesButtonResponse msg; msg.device_class = button->get_device_class_ref(); - return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size); } void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) { ENTITY_COMMAND_GET(button::Button, button, button) @@ -947,23 +899,20 @@ bool APIConnection::send_lock_state(lock::Lock *a_lock) { return this->send_message_smart_(a_lock, LockStateResponse::MESSAGE_TYPE, LockStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *a_lock = static_cast<lock::Lock *>(entity); LockStateResponse resp; resp.state = static_cast<enums::LockState>(a_lock->state); - return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *a_lock = static_cast<lock::Lock *>(entity); ListEntitiesLockResponse msg; msg.assumed_state = a_lock->traits.get_assumed_state(); msg.supports_open = a_lock->traits.get_supports_open(); msg.requires_code = a_lock->traits.get_requires_code(); - return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::lock_command(const LockCommandRequest &msg) { ENTITY_COMMAND_GET(lock::Lock, a_lock, lock) @@ -986,16 +935,14 @@ void APIConnection::lock_command(const LockCommandRequest &msg) { bool APIConnection::send_valve_state(valve::Valve *valve) { return this->send_message_smart_(valve, ValveStateResponse::MESSAGE_TYPE, ValveStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *valve = static_cast<valve::Valve *>(entity); ValveStateResponse resp; resp.position = valve->position; resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation); - return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *valve = static_cast<valve::Valve *>(entity); ListEntitiesValveResponse msg; auto traits = valve->get_traits(); @@ -1003,8 +950,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c msg.assumed_state = traits.get_is_assumed_state(); msg.supports_position = traits.get_supports_position(); msg.supports_stop = traits.get_supports_stop(); - return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::valve_command(const ValveCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve) @@ -1021,8 +967,7 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla return this->send_message_smart_(media_player, MediaPlayerStateResponse::MESSAGE_TYPE, MediaPlayerStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *media_player = static_cast<media_player::MediaPlayer *>(entity); MediaPlayerStateResponse resp; media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING @@ -1031,11 +976,9 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne resp.state = static_cast<enums::MediaPlayerState>(report_state); resp.volume = media_player->volume; resp.muted = media_player->is_muted(); - return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *media_player = static_cast<media_player::MediaPlayer *>(entity); ListEntitiesMediaPlayerResponse msg; auto traits = media_player->get_traits(); @@ -1051,7 +994,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec media_format.sample_bytes = supported_format.sample_bytes; } return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, - remaining_size, is_single); + remaining_size); } void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player) @@ -1092,7 +1035,7 @@ void APIConnection::try_send_camera_image_() { msg.device_id = camera::Camera::instance()->get_device_id(); #endif - if (!this->send_message_(msg, CameraImageResponse::MESSAGE_TYPE)) { + if (!this->send_message_impl(msg, CameraImageResponse::MESSAGE_TYPE)) { return; // Send failed, try again later } this->image_reader_->consume_data(to_send); @@ -1115,12 +1058,10 @@ void APIConnection::set_camera_state(std::shared_ptr<camera::CameraImage> image) this->try_send_camera_image_(); } } -uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *camera = static_cast<camera::Camera *>(entity); ListEntitiesCameraResponse msg; - return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::camera_image(const CameraImageRequest &msg) { if (camera::Camera::instance() == nullptr) @@ -1305,22 +1246,22 @@ bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmCon AlarmControlPanelStateResponse::ESTIMATED_SIZE); } uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, - uint32_t remaining_size, bool is_single) { + uint32_t remaining_size) { auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity); AlarmControlPanelStateResponse resp; resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state()); return fill_and_encode_entity_state(a_alarm_control_panel, resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn, - remaining_size, is_single); + remaining_size); } uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, - uint32_t remaining_size, bool is_single) { + uint32_t remaining_size) { auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity); ListEntitiesAlarmControlPanelResponse msg; msg.supported_features = a_alarm_control_panel->get_supported_features(); msg.requires_code = a_alarm_control_panel->get_requires_code(); msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm(); return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, - conn, remaining_size, is_single); + conn, remaining_size); } void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel) @@ -1357,8 +1298,7 @@ bool APIConnection::send_water_heater_state(water_heater::WaterHeater *water_hea return this->send_message_smart_(water_heater, WaterHeaterStateResponse::MESSAGE_TYPE, WaterHeaterStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *wh = static_cast<water_heater::WaterHeater *>(entity); WaterHeaterStateResponse resp; resp.mode = static_cast<enums::WaterHeaterMode>(wh->get_mode()); @@ -1369,10 +1309,9 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne resp.state = wh->get_state(); resp.key = wh->get_object_id_hash(); - return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *wh = static_cast<water_heater::WaterHeater *>(entity); ListEntitiesWaterHeaterResponse msg; auto traits = wh->get_traits(); @@ -1381,8 +1320,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec msg.target_temperature_step = traits.get_target_temperature_step(); msg.supported_modes = &traits.get_supported_modes(); msg.supported_features = traits.get_feature_flags(); - return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::water_heater_command(const WaterHeaterCommandRequest &msg) { @@ -1411,20 +1349,18 @@ void APIConnection::send_event(event::Event *event) { event->get_last_event_type_index()); } uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, - uint32_t remaining_size, bool is_single) { + uint32_t remaining_size) { EventResponse resp; resp.event_type = event_type; - return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *event = static_cast<event::Event *>(entity); ListEntitiesEventResponse msg; msg.device_class = event->get_device_class_ref(); msg.event_types = &event->get_event_types(); - return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -1447,13 +1383,11 @@ void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent #endif #ifdef USE_INFRARED -uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *infrared = static_cast<infrared::Infrared *>(entity); ListEntitiesInfraredResponse msg; msg.capabilities = infrared->get_capability_flags(); - return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -1461,8 +1395,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection bool APIConnection::send_update_state(update::UpdateEntity *update) { return this->send_message_smart_(update, UpdateStateResponse::MESSAGE_TYPE, UpdateStateResponse::ESTIMATED_SIZE); } -uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *update = static_cast<update::UpdateEntity *>(entity); UpdateStateResponse resp; resp.missing_state = !update->has_state(); @@ -1478,15 +1411,13 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection resp.release_summary = StringRef(update->update_info.summary); resp.release_url = StringRef(update->update_info.release_url); } - return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *update = static_cast<update::UpdateEntity *>(entity); ListEntitiesUpdateResponse msg; msg.device_class = update->get_device_class_ref(); - return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size, - is_single); + return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::update_command(const UpdateCommandRequest &msg) { ENTITY_COMMAND_GET(update::UpdateEntity, update, update) @@ -1512,7 +1443,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char SubscribeLogsResponse msg; msg.level = static_cast<enums::LogLevel>(level); msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len); - return this->send_message_(msg, SubscribeLogsResponse::MESSAGE_TYPE); + return this->send_message_impl(msg, SubscribeLogsResponse::MESSAGE_TYPE); } void APIConnection::complete_authentication_() { @@ -1837,6 +1768,14 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { } return false; } +bool APIConnection::send_message_impl(const ProtoMessage &msg, uint8_t message_type) { + ProtoSize size; + msg.calculate_size(size); + std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref(); + this->prepare_first_message_buffer(shared_buf, size.get_size()); + msg.encode({&shared_buf}); + return this->send_buffer({&shared_buf}, message_type); +} bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); @@ -1897,6 +1836,23 @@ void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t me } } +bool APIConnection::send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, + uint8_t aux_data_index) { + if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) { + auto &shared_buf = this->parent_->get_shared_buffer_ref(); + this->prepare_first_message_buffer(shared_buf, estimated_size); + DeferredBatch::BatchItem item{entity, message_type, estimated_size, aux_data_index}; + if (this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true) && + this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type)) { +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_batch_item_(item); +#endif + return true; + } + } + return this->schedule_message_(entity, message_type, estimated_size, aux_data_index); +} + bool APIConnection::schedule_batch_() { if (!this->flags_.batch_scheduled) { this->flags_.batch_scheduled = true; @@ -1925,10 +1881,21 @@ void APIConnection::process_batch_() { auto &shared_buf = this->parent_->get_shared_buffer_ref(); size_t num_items = this->deferred_batch_.size(); - // Fast path for single message - allocate exact size needed + // Cache these values to avoid repeated virtual calls + const uint8_t header_padding = this->helper_->frame_header_padding(); + const uint8_t footer_size = this->helper_->frame_footer_size(); + + // Pre-calculate exact buffer size needed based on message types + uint32_t total_estimated_size = num_items * (header_padding + footer_size); + for (size_t i = 0; i < num_items; i++) { + total_estimated_size += this->deferred_batch_[i].estimated_size; + } + + this->prepare_first_message_buffer(shared_buf, header_padding, total_estimated_size); + + // Fast path for single message - buffer already allocated above if (num_items == 1) { const auto &item = this->deferred_batch_[0]; - // Let dispatch_message_ calculate size and encode if it fits uint16_t payload_size = this->dispatch_message_(item, std::numeric_limits<uint16_t>::max(), true); @@ -1951,30 +1918,8 @@ void APIConnection::process_batch_() { // Stack-allocated array for message info alignas(MessageInfo) char message_info_storage[MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo)]; MessageInfo *message_info = reinterpret_cast<MessageInfo *>(message_info_storage); - size_t message_count = 0; - - // Cache these values to avoid repeated virtual calls - const uint8_t header_padding = this->helper_->frame_header_padding(); - const uint8_t footer_size = this->helper_->frame_footer_size(); - - // Initialize buffer and tracking variables - shared_buf.clear(); - - // Pre-calculate exact buffer size needed based on message types - uint32_t total_estimated_size = num_items * (header_padding + footer_size); - for (size_t i = 0; i < this->deferred_batch_.size(); i++) { - const auto &item = this->deferred_batch_[i]; - total_estimated_size += item.estimated_size; - } - - // Calculate total overhead for all messages - // Reserve based on estimated size (much more accurate than 24-byte worst-case) - shared_buf.reserve(total_estimated_size); - this->flags_.batch_first_message = true; - size_t items_processed = 0; uint16_t remaining_size = std::numeric_limits<uint16_t>::max(); - // Track where each message's header padding begins in the buffer // For plaintext: this is where the 6-byte header padding starts // For noise: this is where the 7-byte header padding starts @@ -1986,7 +1931,7 @@ void APIConnection::process_batch_() { const auto &item = this->deferred_batch_[i]; // Try to encode message via dispatch // The dispatch function calculates overhead to determine if the message fits - uint16_t payload_size = this->dispatch_message_(item, remaining_size, false); + uint16_t payload_size = this->dispatch_message_(item, remaining_size, i == 0); if (payload_size == 0) { // Message won't fit, stop processing @@ -2000,10 +1945,7 @@ void APIConnection::process_batch_() { // This avoids default-constructing all MAX_MESSAGES_PER_BATCH elements // Explicit destruction is not needed because MessageInfo is trivially destructible, // as ensured by the static_assert in its definition. - new (&message_info[message_count++]) MessageInfo(item.message_type, current_offset, proto_payload_size); - - // Update tracking variables - items_processed++; + new (&message_info[items_processed++]) MessageInfo(item.message_type, current_offset, proto_payload_size); // After first message, set remaining size to MAX_BATCH_PACKET_SIZE to avoid fragmentation if (items_processed == 1) { remaining_size = MAX_BATCH_PACKET_SIZE; @@ -2026,7 +1968,7 @@ void APIConnection::process_batch_() { // Send all collected messages APIError err = this->helper_->write_protobuf_messages(ProtoWriteBuffer{&shared_buf}, - std::span<const MessageInfo>(message_info, message_count)); + std::span<const MessageInfo>(message_info, items_processed)); if (err != APIError::OK && err != APIError::WOULD_BLOCK) { this->fatal_error_with_log_(LOG_STR("Batch write failed"), err); } @@ -2055,7 +1997,8 @@ void APIConnection::process_batch_() { // Dispatch message encoding based on message_type // Switch assigns function pointer, single call site for smaller code size uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, - bool is_single) { + bool batch_first) { + this->flags_.batch_first_message = batch_first; #ifdef USE_EVENT // Events need aux_data_index to look up event type from entity if (item.message_type == EventResponse::MESSAGE_TYPE) { @@ -2064,7 +2007,7 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, return 0; auto *event = static_cast<event::Event *>(item.entity); return try_send_event_response(event, StringRef::from_maybe_nullptr(event->get_event_type(item.aux_data_index)), - this, remaining_size, is_single); + this, remaining_size); } #endif @@ -2174,25 +2117,22 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, #undef CASE_STATE_INFO #undef CASE_INFO_ONLY - return func(item.entity, this, remaining_size, is_single); + return func(item.entity, this, remaining_size); } -uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { ListEntitiesDoneResponse resp; - return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size, is_single); + return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { DisconnectRequest req; - return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size, is_single); + return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size); } -uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single) { +uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { PingRequest req; - return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size, is_single); + return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size); } #ifdef USE_API_HOMEASSISTANT_STATES diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index b839a2a97b..40e4fd61c1 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -255,17 +255,7 @@ class APIConnection final : public APIServerConnection { void on_fatal_error() override; void on_no_setup_connection() override; - ProtoWriteBuffer create_buffer(uint32_t reserve_size) override { - // FIXME: ensure no recursive writes can happen - - // Get header padding size - used for both reserve and insert - uint8_t header_padding = this->helper_->frame_header_padding(); - // Get shared buffer from parent server - std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref(); - this->prepare_first_message_buffer(shared_buf, header_padding, - reserve_size + header_padding + this->helper_->frame_footer_size()); - return {&shared_buf}; - } + bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) override; void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) { shared_buf.clear(); @@ -277,6 +267,13 @@ class APIConnection final : public APIServerConnection { shared_buf.resize(header_padding); } + // Convenience overload - computes frame overhead internally + void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t payload_size) { + const uint8_t header_padding = this->helper_->frame_header_padding(); + const uint8_t footer_size = this->helper_->frame_footer_size(); + this->prepare_first_message_buffer(shared_buf, header_padding, payload_size + header_padding + footer_size); + } + bool try_to_clear_buffer(bool log_out_of_space); bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; @@ -298,21 +295,21 @@ class APIConnection final : public APIServerConnection { // Non-template helper to encode any ProtoMessage static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, - uint32_t remaining_size, bool is_single); + uint32_t remaining_size); // Helper to fill entity state base and encode message static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size, bool is_single) { + APIConnection *conn, uint32_t remaining_size) { msg.key = entity->get_object_id_hash(); #ifdef USE_DEVICES msg.device_id = entity->get_device_id(); #endif - return encode_message_to_buffer(msg, message_type, conn, remaining_size, is_single); + return encode_message_to_buffer(msg, message_type, conn, remaining_size); } // Helper to fill entity info base and encode message static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size, bool is_single) { + APIConnection *conn, uint32_t remaining_size) { // Set common fields that are shared by all entity types msg.key = entity->get_object_id_hash(); @@ -339,7 +336,7 @@ class APIConnection final : public APIServerConnection { #ifdef USE_DEVICES msg.device_id = entity->get_device_id(); #endif - return encode_message_to_buffer(msg, message_type, conn, remaining_size, is_single); + return encode_message_to_buffer(msg, message_type, conn, remaining_size); } #ifdef USE_VOICE_ASSISTANT @@ -370,141 +367,108 @@ class APIConnection final : public APIServerConnection { } #ifdef USE_BINARY_SENSOR - static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_COVER - static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_FAN - static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); - static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_LIGHT - static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_SENSOR - static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_SWITCH - static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_TEXT_SENSOR - static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_CLIMATE - static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_NUMBER - static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_DATETIME_DATE - static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); - static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_DATETIME_TIME - static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); - static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_DATETIME_DATETIME - static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_TEXT - static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); - static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_SELECT - static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_BUTTON - static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_LOCK - static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); - static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_VALVE - static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_MEDIA_PLAYER - static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_ALARM_CONTROL_PANEL - static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_WATER_HEATER - static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_water_heater_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_INFRARED - static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_EVENT static uint16_t try_send_event_response(event::Event *event, StringRef event_type, APIConnection *conn, - uint32_t remaining_size, bool is_single); - static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single); + uint32_t remaining_size); + static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_UPDATE - static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); - static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); + static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif #ifdef USE_CAMERA - static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); #endif // Method for ListEntitiesDone batching - static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); // Method for DisconnectRequest batching - static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); // Batch message method for ping requests - static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, - bool is_single); + static uint16_t try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); // === Optimal member ordering for 32-bit systems === @@ -539,7 +503,7 @@ class APIConnection final : public APIServerConnection { #endif // Function pointer type for message encoding - using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single); + using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size); // Generic batching mechanism for both state updates and entity info struct DeferredBatch { @@ -652,7 +616,7 @@ class APIConnection final : public APIServerConnection { // Dispatch message encoding based on message_type - replaces function pointer storage // Switch assigns pointer, single call site for smaller code size - uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool is_single); + uint16_t dispatch_message_(const DeferredBatch::BatchItem &item, uint32_t remaining_size, bool batch_first); #ifdef HAS_PROTO_MESSAGE_DUMP void log_batch_item_(const DeferredBatch::BatchItem &item) { @@ -684,19 +648,7 @@ class APIConnection final : public APIServerConnection { // Tries immediate send if should_send_immediately_() returns true and buffer has space // Falls back to batching if immediate send fails or isn't applicable bool send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, - uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED) { - if (this->should_send_immediately_(message_type) && this->helper_->can_write_without_blocking()) { - DeferredBatch::BatchItem item{entity, message_type, estimated_size, aux_data_index}; - if (this->dispatch_message_(item, MAX_BATCH_PACKET_SIZE, true) && - this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) { -#ifdef HAS_PROTO_MESSAGE_DUMP - this->log_batch_item_(item); -#endif - return true; - } - } - return this->schedule_message_(entity, message_type, estimated_size, aux_data_index); - } + uint8_t aux_data_index = DeferredBatch::AUX_DATA_UNUSED); // Helper function to schedule a deferred message with known message type bool schedule_message_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 80a61c1041..e2bc1609ed 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -23,7 +23,7 @@ class APIServerConnectionBase : public ProtoService { DumpBuffer dump_buf; this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); #endif - return this->send_message_(msg, message_type); + return this->send_message_impl(msg, message_type); } virtual void on_hello_request(const HelloRequest &value){}; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 552b4a4625..92978f765f 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -957,32 +957,16 @@ class ProtoService { virtual bool is_connection_setup() = 0; virtual void on_fatal_error() = 0; virtual void on_no_setup_connection() = 0; - /** - * Create a buffer with a reserved size. - * @param reserve_size The number of bytes to pre-allocate in the buffer. This is a hint - * to optimize memory usage and avoid reallocations during encoding. - * Implementations should aim to allocate at least this size. - * @return A ProtoWriteBuffer object with the reserved size. - */ - virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0; virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0; virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0; - - // Optimized method that pre-allocates buffer based on message size - bool send_message_(const ProtoMessage &msg, uint8_t message_type) { - ProtoSize size; - msg.calculate_size(size); - uint32_t msg_size = size.get_size(); - - // Create a pre-sized buffer - auto buffer = this->create_buffer(msg_size); - - // Encode message into the buffer - msg.encode(buffer); - - // Send the buffer - return this->send_buffer(buffer, message_type); - } + /** + * Send a protobuf message by calculating its size, allocating a buffer, encoding, and sending. + * This is the implementation method - callers should use send_message() which adds logging. + * @param msg The protobuf message to send. + * @param message_type The message type identifier. + * @return True if the message was sent successfully, false otherwise. + */ + virtual bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) = 0; // Authentication helper methods inline bool check_connection_setup_() { diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 8baf6acf11..4021a062ca 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2848,7 +2848,7 @@ static const char *const TAG = "api.service"; hpp += " DumpBuffer dump_buf;\n" hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n" hpp += "#endif\n" - hpp += " return this->send_message_(msg, message_type);\n" + hpp += " return this->send_message_impl(msg, message_type);\n" hpp += " }\n\n" # Add logging helper method implementations to cpp From ed4f00d4a3c80c54f6084305a640377f4f575105 Mon Sep 17 00:00:00 2001 From: Marek Beran <95686867+Bercek71@users.noreply.github.com> Date: Fri, 6 Feb 2026 08:11:14 +0100 Subject: [PATCH 0534/2030] [vbus] Add DeltaSol BS/2 support with sensors and binary sensors (#13762) --- esphome/components/vbus/__init__.py | 1 + .../components/vbus/binary_sensor/__init__.py | 41 +++++++ .../vbus/binary_sensor/vbus_binary_sensor.cpp | 19 +++ .../vbus/binary_sensor/vbus_binary_sensor.h | 17 +++ esphome/components/vbus/sensor/__init__.py | 110 ++++++++++++++++++ .../components/vbus/sensor/vbus_sensor.cpp | 39 +++++++ esphome/components/vbus/sensor/vbus_sensor.h | 30 +++++ tests/components/vbus/common.yaml | 50 ++++++-- 8 files changed, 298 insertions(+), 9 deletions(-) diff --git a/esphome/components/vbus/__init__.py b/esphome/components/vbus/__init__.py index d916d7c064..5790a9cce0 100644 --- a/esphome/components/vbus/__init__.py +++ b/esphome/components/vbus/__init__.py @@ -16,6 +16,7 @@ CONF_VBUS_ID = "vbus_id" CONF_DELTASOL_BS_PLUS = "deltasol_bs_plus" CONF_DELTASOL_BS_2009 = "deltasol_bs_2009" +CONF_DELTASOL_BS2 = "deltasol_bs2" CONF_DELTASOL_C = "deltasol_c" CONF_DELTASOL_CS2 = "deltasol_cs2" CONF_DELTASOL_CS_PLUS = "deltasol_cs_plus" diff --git a/esphome/components/vbus/binary_sensor/__init__.py b/esphome/components/vbus/binary_sensor/__init__.py index ae927656c0..70dda94300 100644 --- a/esphome/components/vbus/binary_sensor/__init__.py +++ b/esphome/components/vbus/binary_sensor/__init__.py @@ -15,6 +15,7 @@ from esphome.const import ( ) from .. import ( + CONF_DELTASOL_BS2, CONF_DELTASOL_BS_2009, CONF_DELTASOL_BS_PLUS, CONF_DELTASOL_C, @@ -27,6 +28,7 @@ from .. import ( DeltaSol_BS_Plus = vbus_ns.class_("DeltaSolBSPlusBSensor", cg.Component) DeltaSol_BS_2009 = vbus_ns.class_("DeltaSolBS2009BSensor", cg.Component) +DeltaSol_BS2 = vbus_ns.class_("DeltaSolBS2BSensor", cg.Component) DeltaSol_C = vbus_ns.class_("DeltaSolCBSensor", cg.Component) DeltaSol_CS2 = vbus_ns.class_("DeltaSolCS2BSensor", cg.Component) DeltaSol_CS_Plus = vbus_ns.class_("DeltaSolCSPlusBSensor", cg.Component) @@ -118,6 +120,28 @@ CONFIG_SCHEMA = cv.typed_schema( ), } ), + CONF_DELTASOL_BS2: cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(DeltaSol_BS2), + cv.GenerateID(CONF_VBUS_ID): cv.use_id(VBus), + cv.Optional(CONF_SENSOR1_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR2_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR3_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR4_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ), CONF_DELTASOL_C: cv.COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(DeltaSol_C), @@ -275,6 +299,23 @@ async def to_code(config): ) cg.add(var.set_frost_protection_active_bsensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_BS2: + cg.add(var.set_command(0x0100)) + cg.add(var.set_source(0x4278)) + cg.add(var.set_dest(0x0010)) + if CONF_SENSOR1_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR1_ERROR]) + cg.add(var.set_s1_error_bsensor(sens)) + if CONF_SENSOR2_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR2_ERROR]) + cg.add(var.set_s2_error_bsensor(sens)) + if CONF_SENSOR3_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR3_ERROR]) + cg.add(var.set_s3_error_bsensor(sens)) + if CONF_SENSOR4_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR4_ERROR]) + cg.add(var.set_s4_error_bsensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_C: cg.add(var.set_command(0x0100)) cg.add(var.set_source(0x4212)) diff --git a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp index 4ccd149935..c1d7bc1b18 100644 --- a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp +++ b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp @@ -129,6 +129,25 @@ void DeltaSolCSPlusBSensor::handle_message(std::vector<uint8_t> &message) { this->s4_error_bsensor_->publish_state(message[20] & 8); } +void DeltaSolBS2BSensor::dump_config() { + ESP_LOGCONFIG(TAG, "DeltaSol BS/2 (DrainBack):"); + LOG_BINARY_SENSOR(" ", "Sensor 1 Error", this->s1_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 2 Error", this->s2_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 3 Error", this->s3_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 4 Error", this->s4_error_bsensor_); +} + +void DeltaSolBS2BSensor::handle_message(std::vector<uint8_t> &message) { + if (this->s1_error_bsensor_ != nullptr) + this->s1_error_bsensor_->publish_state(message[10] & 1); + if (this->s2_error_bsensor_ != nullptr) + this->s2_error_bsensor_->publish_state(message[10] & 2); + if (this->s3_error_bsensor_ != nullptr) + this->s3_error_bsensor_->publish_state(message[10] & 4); + if (this->s4_error_bsensor_ != nullptr) + this->s4_error_bsensor_->publish_state(message[10] & 8); +} + void VBusCustomBSensor::dump_config() { ESP_LOGCONFIG(TAG, "VBus Custom Binary Sensor:"); if (this->source_ == 0xffff) { diff --git a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h index 146aa1b673..2decdde602 100644 --- a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h +++ b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h @@ -111,6 +111,23 @@ class DeltaSolCSPlusBSensor : public VBusListener, public Component { void handle_message(std::vector<uint8_t> &message) override; }; +class DeltaSolBS2BSensor : public VBusListener, public Component { + public: + void dump_config() override; + void set_s1_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s1_error_bsensor_ = bsensor; } + void set_s2_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s2_error_bsensor_ = bsensor; } + void set_s3_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s3_error_bsensor_ = bsensor; } + void set_s4_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s4_error_bsensor_ = bsensor; } + + protected: + binary_sensor::BinarySensor *s1_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s2_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s3_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s4_error_bsensor_{nullptr}; + + void handle_message(std::vector<uint8_t> &message) override; +}; + class VBusCustomSubBSensor; class VBusCustomBSensor : public VBusListener, public Component { diff --git a/esphome/components/vbus/sensor/__init__.py b/esphome/components/vbus/sensor/__init__.py index fcff698ac0..ff8ef98a1a 100644 --- a/esphome/components/vbus/sensor/__init__.py +++ b/esphome/components/vbus/sensor/__init__.py @@ -31,6 +31,7 @@ from esphome.const import ( ) from .. import ( + CONF_DELTASOL_BS2, CONF_DELTASOL_BS_2009, CONF_DELTASOL_BS_PLUS, CONF_DELTASOL_C, @@ -43,6 +44,7 @@ from .. import ( DeltaSol_BS_Plus = vbus_ns.class_("DeltaSolBSPlusSensor", cg.Component) DeltaSol_BS_2009 = vbus_ns.class_("DeltaSolBS2009Sensor", cg.Component) +DeltaSol_BS2 = vbus_ns.class_("DeltaSolBS2Sensor", cg.Component) DeltaSol_C = vbus_ns.class_("DeltaSolCSensor", cg.Component) DeltaSol_CS2 = vbus_ns.class_("DeltaSolCS2Sensor", cg.Component) DeltaSol_CS_Plus = vbus_ns.class_("DeltaSolCSPlusSensor", cg.Component) @@ -227,6 +229,79 @@ CONFIG_SCHEMA = cv.typed_schema( ), } ), + CONF_DELTASOL_BS2: cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(DeltaSol_BS2), + cv.GenerateID(CONF_VBUS_ID): cv.use_id(VBus), + cv.Optional(CONF_TEMPERATURE_1): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_2): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_3): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_4): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PUMP_SPEED_1): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PUMP_SPEED_2): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_OPERATING_HOURS_1): sensor.sensor_schema( + unit_of_measurement=UNIT_HOUR, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DURATION, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_OPERATING_HOURS_2): sensor.sensor_schema( + unit_of_measurement=UNIT_HOUR, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DURATION, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_HEAT_QUANTITY): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + icon=ICON_RADIATOR, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional(CONF_VERSION): sensor.sensor_schema( + accuracy_decimals=2, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ), CONF_DELTASOL_C: cv.COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(DeltaSol_C), @@ -560,6 +635,41 @@ async def to_code(config): sens = await sensor.new_sensor(config[CONF_VERSION]) cg.add(var.set_version_sensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_BS2: + cg.add(var.set_command(0x0100)) + cg.add(var.set_source(0x4278)) + cg.add(var.set_dest(0x0010)) + if CONF_TEMPERATURE_1 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_1]) + cg.add(var.set_temperature1_sensor(sens)) + if CONF_TEMPERATURE_2 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_2]) + cg.add(var.set_temperature2_sensor(sens)) + if CONF_TEMPERATURE_3 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_3]) + cg.add(var.set_temperature3_sensor(sens)) + if CONF_TEMPERATURE_4 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_4]) + cg.add(var.set_temperature4_sensor(sens)) + if CONF_PUMP_SPEED_1 in config: + sens = await sensor.new_sensor(config[CONF_PUMP_SPEED_1]) + cg.add(var.set_pump_speed1_sensor(sens)) + if CONF_PUMP_SPEED_2 in config: + sens = await sensor.new_sensor(config[CONF_PUMP_SPEED_2]) + cg.add(var.set_pump_speed2_sensor(sens)) + if CONF_OPERATING_HOURS_1 in config: + sens = await sensor.new_sensor(config[CONF_OPERATING_HOURS_1]) + cg.add(var.set_operating_hours1_sensor(sens)) + if CONF_OPERATING_HOURS_2 in config: + sens = await sensor.new_sensor(config[CONF_OPERATING_HOURS_2]) + cg.add(var.set_operating_hours2_sensor(sens)) + if CONF_HEAT_QUANTITY in config: + sens = await sensor.new_sensor(config[CONF_HEAT_QUANTITY]) + cg.add(var.set_heat_quantity_sensor(sens)) + if CONF_VERSION in config: + sens = await sensor.new_sensor(config[CONF_VERSION]) + cg.add(var.set_version_sensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_C: cg.add(var.set_command(0x0100)) cg.add(var.set_source(0x4212)) diff --git a/esphome/components/vbus/sensor/vbus_sensor.cpp b/esphome/components/vbus/sensor/vbus_sensor.cpp index e81c0486d4..75c9ea1aee 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.cpp +++ b/esphome/components/vbus/sensor/vbus_sensor.cpp @@ -214,6 +214,45 @@ void DeltaSolCSPlusSensor::handle_message(std::vector<uint8_t> &message) { this->flow_rate_sensor_->publish_state(get_u16(message, 38)); } +void DeltaSolBS2Sensor::dump_config() { + ESP_LOGCONFIG(TAG, "DeltaSol BS/2 (DrainBack):"); + LOG_SENSOR(" ", "Temperature 1", this->temperature1_sensor_); + LOG_SENSOR(" ", "Temperature 2", this->temperature2_sensor_); + LOG_SENSOR(" ", "Temperature 3", this->temperature3_sensor_); + LOG_SENSOR(" ", "Temperature 4", this->temperature4_sensor_); + LOG_SENSOR(" ", "Pump Speed 1", this->pump_speed1_sensor_); + LOG_SENSOR(" ", "Pump Speed 2", this->pump_speed2_sensor_); + LOG_SENSOR(" ", "Operating Hours 1", this->operating_hours1_sensor_); + LOG_SENSOR(" ", "Operating Hours 2", this->operating_hours2_sensor_); + LOG_SENSOR(" ", "Heat Quantity", this->heat_quantity_sensor_); + LOG_SENSOR(" ", "FW Version", this->version_sensor_); +} + +void DeltaSolBS2Sensor::handle_message(std::vector<uint8_t> &message) { + if (this->temperature1_sensor_ != nullptr) + this->temperature1_sensor_->publish_state(get_i16(message, 0) * 0.1f); + if (this->temperature2_sensor_ != nullptr) + this->temperature2_sensor_->publish_state(get_i16(message, 2) * 0.1f); + if (this->temperature3_sensor_ != nullptr) + this->temperature3_sensor_->publish_state(get_i16(message, 4) * 0.1f); + if (this->temperature4_sensor_ != nullptr) + this->temperature4_sensor_->publish_state(get_i16(message, 6) * 0.1f); + if (this->pump_speed1_sensor_ != nullptr) + this->pump_speed1_sensor_->publish_state(message[8]); + if (this->pump_speed2_sensor_ != nullptr) + this->pump_speed2_sensor_->publish_state(message[9]); + if (this->operating_hours1_sensor_ != nullptr) + this->operating_hours1_sensor_->publish_state(get_u16(message, 12)); + if (this->operating_hours2_sensor_ != nullptr) + this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); + if (this->heat_quantity_sensor_ != nullptr) { + float heat_wh = get_u16(message, 16) + get_u16(message, 18) * 1000.0f + get_u16(message, 20) * 1000000.0f; + this->heat_quantity_sensor_->publish_state(heat_wh); + } + if (this->version_sensor_ != nullptr) + this->version_sensor_->publish_state(get_u16(message, 24) * 0.01f); +} + void VBusCustomSensor::dump_config() { ESP_LOGCONFIG(TAG, "VBus Custom Sensor:"); if (this->source_ == 0xffff) { diff --git a/esphome/components/vbus/sensor/vbus_sensor.h b/esphome/components/vbus/sensor/vbus_sensor.h index d5535b2019..cea2ee1c86 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.h +++ b/esphome/components/vbus/sensor/vbus_sensor.h @@ -157,6 +157,36 @@ class DeltaSolCSPlusSensor : public VBusListener, public Component { void handle_message(std::vector<uint8_t> &message) override; }; +class DeltaSolBS2Sensor : public VBusListener, public Component { + public: + void dump_config() override; + + void set_temperature1_sensor(sensor::Sensor *sensor) { this->temperature1_sensor_ = sensor; } + void set_temperature2_sensor(sensor::Sensor *sensor) { this->temperature2_sensor_ = sensor; } + void set_temperature3_sensor(sensor::Sensor *sensor) { this->temperature3_sensor_ = sensor; } + void set_temperature4_sensor(sensor::Sensor *sensor) { this->temperature4_sensor_ = sensor; } + void set_pump_speed1_sensor(sensor::Sensor *sensor) { this->pump_speed1_sensor_ = sensor; } + void set_pump_speed2_sensor(sensor::Sensor *sensor) { this->pump_speed2_sensor_ = sensor; } + void set_operating_hours1_sensor(sensor::Sensor *sensor) { this->operating_hours1_sensor_ = sensor; } + void set_operating_hours2_sensor(sensor::Sensor *sensor) { this->operating_hours2_sensor_ = sensor; } + void set_heat_quantity_sensor(sensor::Sensor *sensor) { this->heat_quantity_sensor_ = sensor; } + void set_version_sensor(sensor::Sensor *sensor) { this->version_sensor_ = sensor; } + + protected: + sensor::Sensor *temperature1_sensor_{nullptr}; + sensor::Sensor *temperature2_sensor_{nullptr}; + sensor::Sensor *temperature3_sensor_{nullptr}; + sensor::Sensor *temperature4_sensor_{nullptr}; + sensor::Sensor *pump_speed1_sensor_{nullptr}; + sensor::Sensor *pump_speed2_sensor_{nullptr}; + sensor::Sensor *operating_hours1_sensor_{nullptr}; + sensor::Sensor *operating_hours2_sensor_{nullptr}; + sensor::Sensor *heat_quantity_sensor_{nullptr}; + sensor::Sensor *version_sensor_{nullptr}; + + void handle_message(std::vector<uint8_t> &message) override; +}; + class VBusCustomSubSensor; class VBusCustomSensor : public VBusListener, public Component { diff --git a/tests/components/vbus/common.yaml b/tests/components/vbus/common.yaml index 33d9e2935d..5c771be922 100644 --- a/tests/components/vbus/common.yaml +++ b/tests/components/vbus/common.yaml @@ -4,11 +4,21 @@ binary_sensor: - platform: vbus model: deltasol_bs_plus relay1: - name: Relay 1 On + name: BS Plus Relay 1 On relay2: - name: Relay 2 On + name: BS Plus Relay 2 On sensor1_error: - name: Sensor 1 Error + name: BS Plus Sensor 1 Error + - platform: vbus + model: deltasol_bs2 + sensor1_error: + name: BS2 Sensor 1 Error + sensor2_error: + name: BS2 Sensor 2 Error + sensor3_error: + name: BS2 Sensor 3 Error + sensor4_error: + name: BS2 Sensor 4 Error - platform: vbus model: custom command: 0x100 @@ -23,14 +33,36 @@ sensor: - platform: vbus model: deltasol c temperature_1: - name: Temperature 1 + name: DeltaSol C Temperature 1 temperature_2: - name: Temperature 2 + name: DeltaSol C Temperature 2 temperature_3: - name: Temperature 3 + name: DeltaSol C Temperature 3 operating_hours_1: - name: Operating Hours 1 + name: DeltaSol C Operating Hours 1 heat_quantity: - name: Heat Quantity + name: DeltaSol C Heat Quantity time: - name: System Time + name: DeltaSol C System Time + - platform: vbus + model: deltasol_bs2 + temperature_1: + name: BS2 Temperature 1 + temperature_2: + name: BS2 Temperature 2 + temperature_3: + name: BS2 Temperature 3 + temperature_4: + name: BS2 Temperature 4 + pump_speed_1: + name: BS2 Pump Speed 1 + pump_speed_2: + name: BS2 Pump Speed 2 + operating_hours_1: + name: BS2 Operating Hours 1 + operating_hours_2: + name: BS2 Operating Hours 2 + heat_quantity: + name: BS2 Heat Quantity + version: + name: BS2 Firmware Version From c7729cb019021d332fa414e7e6f1a183127b6f0a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Feb 2026 03:51:13 -0500 Subject: [PATCH 0535/2030] [esp32] Use underscores in arduino_libs_stub folder name (#13785) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0c02f6fbee..90f6035aba 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1467,7 +1467,7 @@ async def to_code(config): [_format_framework_espidf_version(idf_ver, None)], ) # Use stub package to skip downloading precompiled libs - stubs_dir = CORE.relative_build_path("arduino-libs-stub") + stubs_dir = CORE.relative_build_path("arduino_libs_stub") cg.add_platformio_option( "platform_packages", [f"{ARDUINO_LIBS_PKG}@file://{stubs_dir}"] ) From 6decdfad26772115bfddc4525ae9624c1ac75101 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Feb 2026 10:05:10 +0100 Subject: [PATCH 0536/2030] Bump github/codeql-action from 4.32.1 to 4.32.2 (#13781) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 817ea1d2be..51ea4085e0 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1 + uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1 + uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 with: category: "/language:${{matrix.language}}" From 8e461db301dcb00b04147c57d6a62f8639109a18 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:09:48 -0500 Subject: [PATCH 0537/2030] [ota] Fix CLI upload option shown when only http_request platform configured (#13784) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/__main__.py | 9 +++- tests/unit_tests/test_main.py | 85 ++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 55297e8d9b..c86b5604e1 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -294,8 +294,13 @@ def has_api() -> bool: def has_ota() -> bool: - """Check if OTA is available.""" - return CONF_OTA in CORE.config + """Check if OTA upload is available (requires platform: esphome).""" + if CONF_OTA not in CORE.config: + return False + return any( + ota_item.get(CONF_PLATFORM) == CONF_ESPHOME + for ota_item in CORE.config[CONF_OTA] + ) def has_mqtt_ip_lookup() -> bool: diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 3268f7ee87..c9aa446323 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -32,6 +32,7 @@ from esphome.__main__ import ( has_mqtt_ip_lookup, has_mqtt_logging, has_non_ip_address, + has_ota, has_resolvable_address, mqtt_get_ip, run_esphome, @@ -332,7 +333,9 @@ def test_choose_upload_log_host_with_mixed_hostnames_and_ips() -> None: def test_choose_upload_log_host_with_ota_list() -> None: """Test with OTA as the only item in the list.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default=["OTA"], @@ -345,7 +348,7 @@ def test_choose_upload_log_host_with_ota_list() -> None: @pytest.mark.usefixtures("mock_has_mqtt_logging") def test_choose_upload_log_host_with_ota_list_mqtt_fallback() -> None: """Test with OTA list falling back to MQTT when no address.""" - setup_core(config={CONF_OTA: {}, "mqtt": {}}) + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], "mqtt": {}}) result = choose_upload_log_host( default=["OTA"], @@ -408,7 +411,9 @@ def test_choose_upload_log_host_with_serial_device_with_ports( def test_choose_upload_log_host_with_ota_device_with_ota_config() -> None: """Test OTA device when OTA is configured.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default="OTA", @@ -475,7 +480,9 @@ def test_choose_upload_log_host_with_ota_device_no_fallback() -> None: @pytest.mark.usefixtures("mock_choose_prompt") def test_choose_upload_log_host_multiple_devices() -> None: """Test with multiple devices including special identifiers.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) mock_ports = [MockSerialPort("/dev/ttyUSB0", "USB Serial")] @@ -514,7 +521,9 @@ def test_choose_upload_log_host_no_defaults_with_serial_ports( @pytest.mark.usefixtures("mock_no_serial_ports") def test_choose_upload_log_host_no_defaults_with_ota() -> None: """Test interactive mode with OTA option.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) with patch( "esphome.__main__.choose_prompt", return_value="192.168.1.100" @@ -575,7 +584,11 @@ def test_choose_upload_log_host_no_defaults_with_all_options( ) -> None: """Test interactive mode with all options available.""" setup_core( - config={CONF_OTA: {}, CONF_API: {}, CONF_MQTT: {CONF_BROKER: "mqtt.local"}}, + config={ + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], + CONF_API: {}, + CONF_MQTT: {CONF_BROKER: "mqtt.local"}, + }, address="192.168.1.100", ) @@ -604,7 +617,11 @@ def test_choose_upload_log_host_no_defaults_with_all_options_logging( ) -> None: """Test interactive mode with all options available.""" setup_core( - config={CONF_OTA: {}, CONF_API: {}, CONF_MQTT: {CONF_BROKER: "mqtt.local"}}, + config={ + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], + CONF_API: {}, + CONF_MQTT: {CONF_BROKER: "mqtt.local"}, + }, address="192.168.1.100", ) @@ -632,7 +649,9 @@ def test_choose_upload_log_host_no_defaults_with_all_options_logging( @pytest.mark.usefixtures("mock_no_serial_ports") def test_choose_upload_log_host_check_default_matches() -> None: """Test when check_default matches an available option.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default=None, @@ -704,7 +723,10 @@ def test_choose_upload_log_host_mixed_resolved_unresolved() -> None: def test_choose_upload_log_host_ota_both_conditions() -> None: """Test OTA device when both OTA and API are configured and enabled.""" - setup_core(config={CONF_OTA: {}, CONF_API: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}}, + address="192.168.1.100", + ) result = choose_upload_log_host( default="OTA", @@ -719,7 +741,7 @@ def test_choose_upload_log_host_ota_ip_all_options() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -744,7 +766,7 @@ def test_choose_upload_log_host_ota_local_all_options() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -769,7 +791,7 @@ def test_choose_upload_log_host_ota_ip_all_options_logging() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -794,7 +816,7 @@ def test_choose_upload_log_host_ota_local_all_options_logging() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -817,7 +839,7 @@ def test_choose_upload_log_host_ota_local_all_options_logging() -> None: @pytest.mark.usefixtures("mock_no_mqtt_logging") def test_choose_upload_log_host_no_address_with_ota_config() -> None: """Test OTA device when OTA is configured but no address is set.""" - setup_core(config={CONF_OTA: {}}) + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) with pytest.raises( EsphomeError, match="All specified devices .* could not be resolved" @@ -1532,10 +1554,43 @@ def test_has_mqtt() -> None: assert has_mqtt() is False # Test with other components but no MQTT - setup_core(config={CONF_API: {}, CONF_OTA: {}}) + setup_core(config={CONF_API: {}, CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) assert has_mqtt() is False +def test_has_ota() -> None: + """Test has_ota function. + + The has_ota function should only return True when OTA is configured + with platform: esphome, not when only platform: http_request is configured. + This is because CLI OTA upload only works with the esphome platform. + """ + # Test with OTA esphome platform configured + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) + assert has_ota() is True + + # Test with OTA http_request platform only (should return False) + # This is the bug scenario from issue #13783 + setup_core(config={CONF_OTA: [{CONF_PLATFORM: "http_request"}]}) + assert has_ota() is False + + # Test without OTA configured + setup_core(config={}) + assert has_ota() is False + + # Test with multiple OTA platforms including esphome + setup_core( + config={ + CONF_OTA: [{CONF_PLATFORM: "http_request"}, {CONF_PLATFORM: CONF_ESPHOME}] + } + ) + assert has_ota() is True + + # Test with empty OTA list + setup_core(config={CONF_OTA: []}) + assert has_ota() is False + + def test_get_port_type() -> None: """Test get_port_type function.""" From fef5d3f88f3f0fff512e39ac3e956bf84c2e958f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:10:22 -0500 Subject: [PATCH 0538/2030] [rdm6300] Add ID-20LA compatibility by skipping CR/LF bytes (#13779) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/components/rdm6300/rdm6300.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/rdm6300/rdm6300.cpp b/esphome/components/rdm6300/rdm6300.cpp index f9b6126c4b..04065982f6 100644 --- a/esphome/components/rdm6300/rdm6300.cpp +++ b/esphome/components/rdm6300/rdm6300.cpp @@ -34,6 +34,8 @@ void rdm6300::RDM6300Component::loop() { this->buffer_[this->read_state_ / 2] += value; } this->read_state_++; + } else if (data == 0x0D || data == 0x0A) { + // Skip CR/LF bytes (ID-20LA compatibility) } else if (data != RDM6300_END_BYTE) { ESP_LOGW(TAG, "Invalid end byte from RDM6300!"); this->read_state_ = RDM6300_STATE_WAITING_FOR_START; From 112a2c5d9276cdf61743ccfd18c404e9c9658092 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:11:08 +1100 Subject: [PATCH 0539/2030] [const] Move some constants to common (#13788) --- esphome/components/const/__init__.py | 6 ++++++ esphome/components/daly_bms/sensor.py | 4 +--- esphome/components/ina2xx_base/__init__.py | 4 ++-- esphome/components/pipsolar/sensor/__init__.py | 4 +--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index fcfafa0c1a..3201db5dfd 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -17,3 +17,9 @@ CONF_ON_STATE_CHANGE = "on_state_change" CONF_REQUEST_HEADERS = "request_headers" CONF_ROWS = "rows" CONF_USE_PSRAM = "use_psram" + +ICON_CURRENT_DC = "mdi:current-dc" +ICON_SOLAR_PANEL = "mdi:solar-panel" +ICON_SOLAR_POWER = "mdi:solar-power" + +UNIT_AMPERE_HOUR = "Ah" diff --git a/esphome/components/daly_bms/sensor.py b/esphome/components/daly_bms/sensor.py index 560bcef64e..aa92cfa86a 100644 --- a/esphome/components/daly_bms/sensor.py +++ b/esphome/components/daly_bms/sensor.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.const import ICON_CURRENT_DC, UNIT_AMPERE_HOUR import esphome.config_validation as cv from esphome.const import ( CONF_BATTERY_LEVEL, @@ -55,14 +56,11 @@ CONF_CELL_15_VOLTAGE = "cell_15_voltage" CONF_CELL_16_VOLTAGE = "cell_16_voltage" CONF_CELL_17_VOLTAGE = "cell_17_voltage" CONF_CELL_18_VOLTAGE = "cell_18_voltage" -ICON_CURRENT_DC = "mdi:current-dc" ICON_BATTERY_OUTLINE = "mdi:battery-outline" ICON_THERMOMETER_CHEVRON_UP = "mdi:thermometer-chevron-up" ICON_THERMOMETER_CHEVRON_DOWN = "mdi:thermometer-chevron-down" ICON_CAR_BATTERY = "mdi:car-battery" -UNIT_AMPERE_HOUR = "Ah" - TYPES = [ CONF_VOLTAGE, CONF_CURRENT, diff --git a/esphome/components/ina2xx_base/__init__.py b/esphome/components/ina2xx_base/__init__.py index ce68ad2726..15e2faba07 100644 --- a/esphome/components/ina2xx_base/__init__.py +++ b/esphome/components/ina2xx_base/__init__.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.const import UNIT_AMPERE_HOUR import esphome.config_validation as cv from esphome.const import ( CONF_BUS_VOLTAGE, @@ -36,7 +37,6 @@ CONF_CHARGE_COULOMBS = "charge_coulombs" CONF_ENERGY_JOULES = "energy_joules" CONF_TEMPERATURE_COEFFICIENT = "temperature_coefficient" CONF_RESET_ON_BOOT = "reset_on_boot" -UNIT_AMPERE_HOURS = "Ah" UNIT_COULOMB = "C" UNIT_JOULE = "J" UNIT_MILLIVOLT = "mV" @@ -180,7 +180,7 @@ INA2XX_SCHEMA = cv.Schema( ), cv.Optional(CONF_CHARGE): cv.maybe_simple_value( sensor.sensor_schema( - unit_of_measurement=UNIT_AMPERE_HOURS, + unit_of_measurement=UNIT_AMPERE_HOUR, accuracy_decimals=8, state_class=STATE_CLASS_MEASUREMENT, ), diff --git a/esphome/components/pipsolar/sensor/__init__.py b/esphome/components/pipsolar/sensor/__init__.py index d08a877b55..8d3ba10d62 100644 --- a/esphome/components/pipsolar/sensor/__init__.py +++ b/esphome/components/pipsolar/sensor/__init__.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.const import ICON_CURRENT_DC, ICON_SOLAR_PANEL, ICON_SOLAR_POWER import esphome.config_validation as cv from esphome.const import ( CONF_BATTERY_VOLTAGE, @@ -29,9 +30,6 @@ from .. import CONF_PIPSOLAR_ID, PIPSOLAR_COMPONENT_SCHEMA DEPENDENCIES = ["uart"] -ICON_SOLAR_POWER = "mdi:solar-power" -ICON_SOLAR_PANEL = "mdi:solar-panel" -ICON_CURRENT_DC = "mdi:current-dc" # QPIRI sensors CONF_GRID_RATING_VOLTAGE = "grid_rating_voltage" From 7afd0eb1aa947cc5b081849eb6bc090763068127 Mon Sep 17 00:00:00 2001 From: Andrew Rankin <andrew@eiknet.com> Date: Fri, 6 Feb 2026 06:36:55 -0500 Subject: [PATCH 0540/2030] [esp32_ble] include sdkconfig.h before ESP-Hosted preprocessor guards (#13787) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- .../components/esp32_ble/ble_advertising.h | 9 ----- .../components/esp32_ble_beacon/__init__.py | 11 +++-- .../esp32_ble_beacon/esp32_ble_beacon.cpp | 10 ++++- .../esp32_ble_beacon/esp32_ble_beacon.h | 4 ++ esphome/config_validation.py | 11 +++++ .../config_validation/test_config.py | 40 ++++++++++++++++++- .../esp32_ble/test.esp32-p4-idf.yaml | 8 ++++ .../esp32_ble_beacon/test.esp32-p4-idf.yaml | 7 ++++ .../esp32_ble_client/test.esp32-p4-idf.yaml | 6 +++ .../esp32_ble_server/test.esp32-p4-idf.yaml | 4 ++ .../esp32_ble_tracker/test.esp32-p4-idf.yaml | 7 ++++ .../common/ble/esp32-p4-idf.yaml | 21 ++++++++++ 12 files changed, 124 insertions(+), 14 deletions(-) create mode 100644 tests/components/esp32_ble/test.esp32-p4-idf.yaml create mode 100644 tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml create mode 100644 tests/components/esp32_ble_client/test.esp32-p4-idf.yaml create mode 100644 tests/components/esp32_ble_server/test.esp32-p4-idf.yaml create mode 100644 tests/components/esp32_ble_tracker/test.esp32-p4-idf.yaml create mode 100644 tests/test_build_components/common/ble/esp32-p4-idf.yaml diff --git a/esphome/components/esp32_ble/ble_advertising.h b/esphome/components/esp32_ble/ble_advertising.h index d7f1eeac9d..3cfa6f548a 100644 --- a/esphome/components/esp32_ble/ble_advertising.h +++ b/esphome/components/esp32_ble/ble_advertising.h @@ -10,20 +10,11 @@ #ifdef USE_ESP32 #ifdef USE_ESP32_BLE_ADVERTISING -#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID -#include <esp_bt.h> -#endif #include <esp_gap_ble_api.h> #include <esp_gatts_api.h> namespace esphome::esp32_ble { -using raw_adv_data_t = struct { - uint8_t *data; - size_t length; - esp_power_level_t power_level; -}; - class ESPBTUUID; class BLEAdvertising { diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index ba5ae4331c..04c783980d 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -53,8 +53,10 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MEASURED_POWER, default=-59): cv.int_range( min=-128, max=0 ), - cv.Optional(CONF_TX_POWER, default="3dBm"): cv.All( - cv.decibel, cv.enum(esp32_ble.TX_POWER_LEVELS, int=True) + cv.OnlyWithout(CONF_TX_POWER, "esp32_hosted", default="3dBm"): cv.All( + cv.conflicts_with_component("esp32_hosted"), + cv.decibel, + cv.enum(esp32_ble.TX_POWER_LEVELS, int=True), ), } ).extend(cv.COMPONENT_SCHEMA), @@ -82,7 +84,10 @@ async def to_code(config): cg.add(var.set_min_interval(config[CONF_MIN_INTERVAL])) cg.add(var.set_max_interval(config[CONF_MAX_INTERVAL])) cg.add(var.set_measured_power(config[CONF_MEASURED_POWER])) - cg.add(var.set_tx_power(config[CONF_TX_POWER])) + + # TX power control only available on native Bluetooth (not ESP-Hosted) + if CONF_TX_POWER in config: + cg.add(var.set_tx_power(config[CONF_TX_POWER])) cg.add_define("USE_ESP32_BLE_ADVERTISING") diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp index f2aa7e762e..093273b399 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.cpp @@ -36,11 +36,16 @@ void ESP32BLEBeacon::dump_config() { } } *bpos = '\0'; +#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID ESP_LOGCONFIG(TAG, " UUID: %s, Major: %u, Minor: %u, Min Interval: %ums, Max Interval: %ums, Measured Power: %d" ", TX Power: %ddBm", uuid, this->major_, this->minor_, this->min_interval_, this->max_interval_, this->measured_power_, (this->tx_power_ * 3) - 12); +#else + ESP_LOGCONFIG(TAG, " UUID: %s, Major: %u, Minor: %u, Min Interval: %ums, Max Interval: %ums, Measured Power: %d", + uuid, this->major_, this->minor_, this->min_interval_, this->max_interval_, this->measured_power_); +#endif } float ESP32BLEBeacon::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH; } @@ -74,11 +79,14 @@ void ESP32BLEBeacon::on_advertise_() { ibeacon_adv_data.ibeacon_vendor.major = byteswap(this->major_); ibeacon_adv_data.ibeacon_vendor.measured_power = static_cast<uint8_t>(this->measured_power_); + esp_err_t err; +#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID ESP_LOGD(TAG, "Setting BLE TX power"); - esp_err_t err = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, this->tx_power_); + err = esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, this->tx_power_); if (err != ESP_OK) { ESP_LOGW(TAG, "esp_ble_tx_power_set failed: %s", esp_err_to_name(err)); } +#endif err = esp_ble_gap_config_adv_data_raw((uint8_t *) &ibeacon_adv_data, sizeof(ibeacon_adv_data)); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gap_config_adv_data_raw failed: %s", esp_err_to_name(err)); diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h index 05afdc7379..7a0424f3aa 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h @@ -48,7 +48,9 @@ class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented void set_min_interval(uint16_t val) { this->min_interval_ = val; } void set_max_interval(uint16_t val) { this->max_interval_ = val; } void set_measured_power(int8_t val) { this->measured_power_ = val; } +#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID void set_tx_power(esp_power_level_t val) { this->tx_power_ = val; } +#endif void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; protected: @@ -60,7 +62,9 @@ class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented uint16_t min_interval_{}; uint16_t max_interval_{}; int8_t measured_power_{}; +#ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID esp_power_level_t tx_power_{}; +#endif esp_ble_adv_params_t ble_adv_params_; bool advertising_{false}; }; diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 55e13a7050..a9d1a72e5a 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1403,6 +1403,17 @@ def requires_component(comp): return validator +def conflicts_with_component(comp): + """Validate that this option cannot be specified when the component `comp` is loaded.""" + + def validator(value): + if comp in CORE.loaded_integrations: + raise Invalid(f"This option is not compatible with component {comp}") + return value + + return validator + + uint8_t = int_range(min=0, max=255) uint16_t = int_range(min=0, max=65535) uint32_t = int_range(min=0, max=4294967295) diff --git a/tests/component_tests/config_validation/test_config.py b/tests/component_tests/config_validation/test_config.py index 1a9b9bc1f3..25d85d333b 100644 --- a/tests/component_tests/config_validation/test_config.py +++ b/tests/component_tests/config_validation/test_config.py @@ -1,10 +1,14 @@ """ -Test schema.extend functionality in esphome.config_validation. +Test config_validation functionality in esphome.config_validation. """ from typing import Any +import pytest +from voluptuous import Invalid + import esphome.config_validation as cv +from esphome.core import CORE def test_config_extend() -> None: @@ -49,3 +53,37 @@ def test_config_extend() -> None: assert validated["key2"] == "initial_value2" assert validated["extra_1"] == "value1" assert validated["extra_2"] == "value2" + + +def test_requires_component_passes_when_loaded() -> None: + """Test requires_component passes when the required component is loaded.""" + CORE.loaded_integrations.update({"wifi", "logger"}) + validator = cv.requires_component("wifi") + result = validator("test_value") + assert result == "test_value" + + +def test_requires_component_fails_when_not_loaded() -> None: + """Test requires_component raises Invalid when the required component is not loaded.""" + CORE.loaded_integrations.add("logger") + validator = cv.requires_component("wifi") + with pytest.raises(Invalid) as exc_info: + validator("test_value") + assert "requires component wifi" in str(exc_info.value) + + +def test_conflicts_with_component_passes_when_not_loaded() -> None: + """Test conflicts_with_component passes when the conflicting component is not loaded.""" + CORE.loaded_integrations.update({"wifi", "logger"}) + validator = cv.conflicts_with_component("esp32_hosted") + result = validator("test_value") + assert result == "test_value" + + +def test_conflicts_with_component_fails_when_loaded() -> None: + """Test conflicts_with_component raises Invalid when the conflicting component is loaded.""" + CORE.loaded_integrations.update({"wifi", "esp32_hosted"}) + validator = cv.conflicts_with_component("esp32_hosted") + with pytest.raises(Invalid) as exc_info: + validator("test_value") + assert "not compatible with component esp32_hosted" in str(exc_info.value) diff --git a/tests/components/esp32_ble/test.esp32-p4-idf.yaml b/tests/components/esp32_ble/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..4eeb7c2f18 --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-p4-idf.yaml @@ -0,0 +1,8 @@ +packages: + ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml + +<<: !include common.yaml + +esp32_ble: + io_capability: keyboard_only + disable_bt_logs: false diff --git a/tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml b/tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..b6e1845c50 --- /dev/null +++ b/tests/components/esp32_ble_beacon/test.esp32-p4-idf.yaml @@ -0,0 +1,7 @@ +packages: + ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml + +# tx_power is not supported on ESP-Hosted platforms +esp32_ble_beacon: + type: iBeacon + uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98' diff --git a/tests/components/esp32_ble_client/test.esp32-p4-idf.yaml b/tests/components/esp32_ble_client/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..e2496dd1ce --- /dev/null +++ b/tests/components/esp32_ble_client/test.esp32-p4-idf.yaml @@ -0,0 +1,6 @@ +packages: + ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml + +ble_client: + - mac_address: 01:02:03:04:05:06 + id: blec diff --git a/tests/components/esp32_ble_server/test.esp32-p4-idf.yaml b/tests/components/esp32_ble_server/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..f202161cf3 --- /dev/null +++ b/tests/components/esp32_ble_server/test.esp32-p4-idf.yaml @@ -0,0 +1,4 @@ +packages: + ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/esp32_ble_tracker/test.esp32-p4-idf.yaml b/tests/components/esp32_ble_tracker/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..d0f1e94a97 --- /dev/null +++ b/tests/components/esp32_ble_tracker/test.esp32-p4-idf.yaml @@ -0,0 +1,7 @@ +packages: + ble: !include ../../test_build_components/common/ble/esp32-p4-idf.yaml + +<<: !include common.yaml + +esp32_ble_tracker: + max_connections: 9 diff --git a/tests/test_build_components/common/ble/esp32-p4-idf.yaml b/tests/test_build_components/common/ble/esp32-p4-idf.yaml new file mode 100644 index 0000000000..dce923078a --- /dev/null +++ b/tests/test_build_components/common/ble/esp32-p4-idf.yaml @@ -0,0 +1,21 @@ +# Common BLE tracker configuration for ESP32-P4 IDF tests +# ESP32-P4 requires ESP-Hosted for Bluetooth via external coprocessor +# BLE client components share this tracker infrastructure +# Each component defines its own ble_client with unique MAC address + +esp32_hosted: + active_high: true + variant: ESP32C6 + reset_pin: GPIO54 + cmd_pin: GPIO19 + clk_pin: GPIO18 + d0_pin: GPIO14 + d1_pin: GPIO15 + d2_pin: GPIO16 + d3_pin: GPIO17 + +esp32_ble_tracker: + scan_parameters: + interval: 1100ms + window: 1100ms + active: true From e4ad2082bcc22d60244426e6b9fbf0dde51e73bb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 15:26:16 +0100 Subject: [PATCH 0541/2030] [core] Add PROGMEM_STRING_TABLE macro for flash-optimized string lookups (#13659) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/cover/cover.cpp | 14 +--- .../components/light/light_json_schema.cpp | 37 +++------ esphome/components/logger/logger.cpp | 34 +++----- esphome/components/sensor/sensor.cpp | 20 ++--- esphome/components/sensor/sensor.h | 1 + esphome/components/valve/valve.cpp | 14 +--- .../wifi/wifi_component_esp8266.cpp | 43 ++++------ esphome/core/progmem.h | 83 +++++++++++++++++++ 8 files changed, 137 insertions(+), 109 deletions(-) diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index 37cb908d9f..0589aa2379 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -19,17 +19,11 @@ const LogString *cover_command_to_str(float pos) { return LOG_STR("UNKNOWN"); } } +// Cover operation strings indexed by CoverOperation enum (0-2): IDLE, OPENING, CLOSING, plus UNKNOWN +PROGMEM_STRING_TABLE(CoverOperationStrings, "IDLE", "OPENING", "CLOSING", "UNKNOWN"); + const LogString *cover_operation_to_str(CoverOperation op) { - switch (op) { - case COVER_OPERATION_IDLE: - return LOG_STR("IDLE"); - case COVER_OPERATION_OPENING: - return LOG_STR("OPENING"); - case COVER_OPERATION_CLOSING: - return LOG_STR("CLOSING"); - default: - return LOG_STR("UNKNOWN"); - } + return CoverOperationStrings::get_log_str(static_cast<uint8_t>(op), CoverOperationStrings::LAST_INDEX); } Cover::Cover() : position{COVER_OPEN} {} diff --git a/esphome/components/light/light_json_schema.cpp b/esphome/components/light/light_json_schema.cpp index 631f59221f..aaa1176f9f 100644 --- a/esphome/components/light/light_json_schema.cpp +++ b/esphome/components/light/light_json_schema.cpp @@ -9,32 +9,19 @@ namespace esphome::light { // See https://www.home-assistant.io/integrations/light.mqtt/#json-schema for documentation on the schema -// Get JSON string for color mode. -// ColorMode enum values are sparse bitmasks (0, 1, 3, 7, 11, 19, 35, 39, 47, 51) which would -// generate a large jump table. Converting to bit index (0-9) allows a compact switch. +// Color mode JSON strings - packed into flash with compile-time generated offsets. +// Indexed by ColorModeBitPolicy bit index (1-9), so index 0 maps to bit 1 ("onoff"). +PROGMEM_STRING_TABLE(ColorModeStrings, "onoff", "brightness", "white", "color_temp", "cwww", "rgb", "rgbw", "rgbct", + "rgbww"); + +// Get JSON string for color mode. Returns nullptr for UNKNOWN (bit 0). +// Returns ProgmemStr so ArduinoJson knows to handle PROGMEM strings on ESP8266. static ProgmemStr get_color_mode_json_str(ColorMode mode) { - switch (ColorModeBitPolicy::to_bit(mode)) { - case 1: - return ESPHOME_F("onoff"); - case 2: - return ESPHOME_F("brightness"); - case 3: - return ESPHOME_F("white"); - case 4: - return ESPHOME_F("color_temp"); - case 5: - return ESPHOME_F("cwww"); - case 6: - return ESPHOME_F("rgb"); - case 7: - return ESPHOME_F("rgbw"); - case 8: - return ESPHOME_F("rgbct"); - case 9: - return ESPHOME_F("rgbww"); - default: - return nullptr; - } + unsigned bit = ColorModeBitPolicy::to_bit(mode); + if (bit == 0) + return nullptr; + // bit is 1-9 for valid modes, so bit-1 is always valid (0-8). LAST_INDEX fallback never used. + return ColorModeStrings::get_progmem_str(bit - 1, ColorModeStrings::LAST_INDEX); } void LightJSONSchema::dump_json(LightState &state, JsonObject root) { diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 54b5670016..4cbd4f1bf1 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -4,6 +4,7 @@ #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome::logger { @@ -241,34 +242,20 @@ UARTSelection Logger::get_uart() const { return this->uart_; } float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; } -#ifdef USE_STORE_LOG_STR_IN_FLASH -// ESP8266: PSTR() cannot be used in array initializers, so we need to declare -// each string separately as a global constant first -static const char LOG_LEVEL_NONE[] PROGMEM = "NONE"; -static const char LOG_LEVEL_ERROR[] PROGMEM = "ERROR"; -static const char LOG_LEVEL_WARN[] PROGMEM = "WARN"; -static const char LOG_LEVEL_INFO[] PROGMEM = "INFO"; -static const char LOG_LEVEL_CONFIG[] PROGMEM = "CONFIG"; -static const char LOG_LEVEL_DEBUG[] PROGMEM = "DEBUG"; -static const char LOG_LEVEL_VERBOSE[] PROGMEM = "VERBOSE"; -static const char LOG_LEVEL_VERY_VERBOSE[] PROGMEM = "VERY_VERBOSE"; +// Log level strings - packed into flash on ESP8266, indexed by log level (0-7) +PROGMEM_STRING_TABLE(LogLevelStrings, "NONE", "ERROR", "WARN", "INFO", "CONFIG", "DEBUG", "VERBOSE", "VERY_VERBOSE"); -static const LogString *const LOG_LEVELS[] = { - reinterpret_cast<const LogString *>(LOG_LEVEL_NONE), reinterpret_cast<const LogString *>(LOG_LEVEL_ERROR), - reinterpret_cast<const LogString *>(LOG_LEVEL_WARN), reinterpret_cast<const LogString *>(LOG_LEVEL_INFO), - reinterpret_cast<const LogString *>(LOG_LEVEL_CONFIG), reinterpret_cast<const LogString *>(LOG_LEVEL_DEBUG), - reinterpret_cast<const LogString *>(LOG_LEVEL_VERBOSE), reinterpret_cast<const LogString *>(LOG_LEVEL_VERY_VERBOSE), -}; -#else -static const char *const LOG_LEVELS[] = {"NONE", "ERROR", "WARN", "INFO", "CONFIG", "DEBUG", "VERBOSE", "VERY_VERBOSE"}; -#endif +static const LogString *get_log_level_str(uint8_t level) { + return LogLevelStrings::get_log_str(level, LogLevelStrings::LAST_INDEX); +} void Logger::dump_config() { ESP_LOGCONFIG(TAG, "Logger:\n" " Max Level: %s\n" " Initial Level: %s", - LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL]), LOG_STR_ARG(LOG_LEVELS[this->current_level_])); + LOG_STR_ARG(get_log_level_str(ESPHOME_LOG_LEVEL)), + LOG_STR_ARG(get_log_level_str(this->current_level_))); #ifndef USE_HOST ESP_LOGCONFIG(TAG, " Log Baud Rate: %" PRIu32 "\n" @@ -287,7 +274,7 @@ void Logger::dump_config() { #ifdef USE_LOGGER_RUNTIME_TAG_LEVELS for (auto &it : this->log_levels_) { - ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first, LOG_STR_ARG(LOG_LEVELS[it.second])); + ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first, LOG_STR_ARG(get_log_level_str(it.second))); } #endif } @@ -295,7 +282,8 @@ void Logger::dump_config() { void Logger::set_log_level(uint8_t level) { if (level > ESPHOME_LOG_LEVEL) { level = ESPHOME_LOG_LEVEL; - ESP_LOGW(TAG, "Cannot set log level higher than pre-compiled %s", LOG_STR_ARG(LOG_LEVELS[ESPHOME_LOG_LEVEL])); + ESP_LOGW(TAG, "Cannot set log level higher than pre-compiled %s", + LOG_STR_ARG(get_log_level_str(ESPHOME_LOG_LEVEL))); } this->current_level_ = level; #ifdef USE_LOGGER_LEVEL_LISTENERS diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index 3f2be02af2..ae2ee3e3d1 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome::sensor { @@ -30,20 +31,13 @@ void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *o } } +// State class strings indexed by StateClass enum (0-4): NONE, MEASUREMENT, TOTAL_INCREASING, TOTAL, MEASUREMENT_ANGLE +PROGMEM_STRING_TABLE(StateClassStrings, "", "measurement", "total_increasing", "total", "measurement_angle"); +static_assert(StateClassStrings::COUNT == STATE_CLASS_LAST + 1, "StateClassStrings must match StateClass enum"); + const LogString *state_class_to_string(StateClass state_class) { - switch (state_class) { - case STATE_CLASS_MEASUREMENT: - return LOG_STR("measurement"); - case STATE_CLASS_TOTAL_INCREASING: - return LOG_STR("total_increasing"); - case STATE_CLASS_TOTAL: - return LOG_STR("total"); - case STATE_CLASS_MEASUREMENT_ANGLE: - return LOG_STR("measurement_angle"); - case STATE_CLASS_NONE: - default: - return LOG_STR(""); - } + // Fallback to index 0 (empty string for STATE_CLASS_NONE) if out of range + return StateClassStrings::get_log_str(static_cast<uint8_t>(state_class), 0); } Sensor::Sensor() : state(NAN), raw_state(NAN) {} diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index d9046020f6..f9a45cb1d0 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -32,6 +32,7 @@ enum StateClass : uint8_t { STATE_CLASS_TOTAL = 3, STATE_CLASS_MEASUREMENT_ANGLE = 4 }; +constexpr uint8_t STATE_CLASS_LAST = static_cast<uint8_t>(STATE_CLASS_MEASUREMENT_ANGLE); const LogString *state_class_to_string(StateClass state_class); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index 607f614ef7..493ffd8da2 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -23,17 +23,11 @@ const LogString *valve_command_to_str(float pos) { return LOG_STR("UNKNOWN"); } } +// Valve operation strings indexed by ValveOperation enum (0-2): IDLE, OPENING, CLOSING, plus UNKNOWN +PROGMEM_STRING_TABLE(ValveOperationStrings, "IDLE", "OPENING", "CLOSING", "UNKNOWN"); + const LogString *valve_operation_to_str(ValveOperation op) { - switch (op) { - case VALVE_OPERATION_IDLE: - return LOG_STR("IDLE"); - case VALVE_OPERATION_OPENING: - return LOG_STR("OPENING"); - case VALVE_OPERATION_CLOSING: - return LOG_STR("CLOSING"); - default: - return LOG_STR("UNKNOWN"); - } + return ValveOperationStrings::get_log_str(static_cast<uint8_t>(op), ValveOperationStrings::LAST_INDEX); } Valve::Valve() : position{VALVE_OPEN} {} diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index c6bd40037d..0765fdc03b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -36,6 +36,7 @@ extern "C" { #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "esphome/core/util.h" namespace esphome::wifi { @@ -398,37 +399,23 @@ class WiFiMockClass : public ESP8266WiFiGenericClass { static void _event_callback(void *event) { ESP8266WiFiGenericClass::_eventCallback(event); } // NOLINT }; +// Auth mode strings indexed by AUTH_* constants (0-4), with UNKNOWN at last index +// Static asserts verify the SDK constants are contiguous as expected +static_assert(AUTH_OPEN == 0 && AUTH_WEP == 1 && AUTH_WPA_PSK == 2 && AUTH_WPA2_PSK == 3 && AUTH_WPA_WPA2_PSK == 4, + "AUTH_* constants are not contiguous"); +PROGMEM_STRING_TABLE(AuthModeStrings, "OPEN", "WEP", "WPA PSK", "WPA2 PSK", "WPA/WPA2 PSK", "UNKNOWN"); + const LogString *get_auth_mode_str(uint8_t mode) { - switch (mode) { - case AUTH_OPEN: - return LOG_STR("OPEN"); - case AUTH_WEP: - return LOG_STR("WEP"); - case AUTH_WPA_PSK: - return LOG_STR("WPA PSK"); - case AUTH_WPA2_PSK: - return LOG_STR("WPA2 PSK"); - case AUTH_WPA_WPA2_PSK: - return LOG_STR("WPA/WPA2 PSK"); - default: - return LOG_STR("UNKNOWN"); - } -} -const LogString *get_op_mode_str(uint8_t mode) { - switch (mode) { - case WIFI_OFF: - return LOG_STR("OFF"); - case WIFI_STA: - return LOG_STR("STA"); - case WIFI_AP: - return LOG_STR("AP"); - case WIFI_AP_STA: - return LOG_STR("AP+STA"); - default: - return LOG_STR("UNKNOWN"); - } + return AuthModeStrings::get_log_str(mode, AuthModeStrings::LAST_INDEX); } +// WiFi op mode strings indexed by WIFI_* constants (0-3), with UNKNOWN at last index +static_assert(WIFI_OFF == 0 && WIFI_STA == 1 && WIFI_AP == 2 && WIFI_AP_STA == 3, + "WIFI_* op mode constants are not contiguous"); +PROGMEM_STRING_TABLE(OpModeStrings, "OFF", "STA", "AP", "AP+STA", "UNKNOWN"); + +const LogString *get_op_mode_str(uint8_t mode) { return OpModeStrings::get_log_str(mode, OpModeStrings::LAST_INDEX); } + const LogString *get_disconnect_reason_str(uint8_t reason) { /* If this were one big switch statement, GCC would generate a lookup table for it. However, the values of the * REASON_* constants aren't continuous, and GCC will fill in the gap with the default value -- wasting 4 bytes of RAM diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index 4b897fb2de..6c6a5252cf 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -1,5 +1,11 @@ #pragma once +#include <array> +#include <cstddef> +#include <cstdint> + +#include "esphome/core/hal.h" // For PROGMEM definition + // Platform-agnostic macros for PROGMEM string handling // On ESP8266/Arduino: Use Arduino's F() macro for PROGMEM strings // On other platforms: Use plain strings (no PROGMEM) @@ -32,3 +38,80 @@ using ProgmemStr = const __FlashStringHelper *; // Type for pointers to strings (no PROGMEM on non-ESP8266 platforms) using ProgmemStr = const char *; #endif + +namespace esphome { + +/// Helper for C++20 string literal template arguments +template<size_t N> struct FixedString { + char data[N]{}; + constexpr FixedString(const char (&str)[N]) { + for (size_t i = 0; i < N; ++i) + data[i] = str[i]; + } + constexpr size_t size() const { return N - 1; } // exclude null terminator +}; + +/// Compile-time string table that packs strings into a single blob with offset lookup. +/// Use PROGMEM_STRING_TABLE macro to instantiate with proper flash placement on ESP8266. +/// +/// Example: +/// PROGMEM_STRING_TABLE(MyStrings, "foo", "bar", "baz"); +/// ProgmemStr str = MyStrings::get_progmem_str(idx, MyStrings::LAST_INDEX); // For ArduinoJson +/// const LogString *log_str = MyStrings::get_log_str(idx, MyStrings::LAST_INDEX); // For logging +/// +template<FixedString... Strs> struct ProgmemStringTable { + static constexpr size_t COUNT = sizeof...(Strs); + static constexpr size_t BLOB_SIZE = (0 + ... + (Strs.size() + 1)); + + /// Generate packed string blob at compile time + static constexpr auto make_blob() { + std::array<char, BLOB_SIZE> result{}; + size_t pos = 0; + auto copy = [&](const auto &str) { + for (size_t i = 0; i <= str.size(); ++i) + result[pos++] = str.data[i]; + }; + (copy(Strs), ...); + return result; + } + + /// Generate offset table at compile time (uint8_t limits blob to 255 bytes) + static constexpr auto make_offsets() { + static_assert(COUNT > 0, "PROGMEM_STRING_TABLE must contain at least one string"); + static_assert(COUNT <= 255, "PROGMEM_STRING_TABLE supports at most 255 strings with uint8_t indices"); + static_assert(BLOB_SIZE <= 255, "PROGMEM_STRING_TABLE blob exceeds 255 bytes; use fewer/shorter strings"); + std::array<uint8_t, COUNT> result{}; + size_t pos = 0, idx = 0; + ((result[idx++] = static_cast<uint8_t>(pos), pos += Strs.size() + 1), ...); + return result; + } +}; + +// Forward declaration for LogString (defined in log.h) +struct LogString; + +/// Instantiate a ProgmemStringTable with PROGMEM storage. +/// Creates: Name::get_progmem_str(idx, fallback), Name::get_log_str(idx, fallback) +/// If idx >= COUNT, returns string at fallback. Use LAST_INDEX for common patterns. +#define PROGMEM_STRING_TABLE(Name, ...) \ + struct Name { \ + using Table = ::esphome::ProgmemStringTable<__VA_ARGS__>; \ + static constexpr size_t COUNT = Table::COUNT; \ + static constexpr uint8_t LAST_INDEX = COUNT - 1; \ + static constexpr size_t BLOB_SIZE = Table::BLOB_SIZE; \ + static constexpr auto BLOB PROGMEM = Table::make_blob(); \ + static constexpr auto OFFSETS PROGMEM = Table::make_offsets(); \ + static const char *get_(uint8_t idx, uint8_t fallback) { \ + if (idx >= COUNT) \ + idx = fallback; \ + return &BLOB[::esphome::progmem_read_byte(&OFFSETS[idx])]; \ + } \ + static ::ProgmemStr get_progmem_str(uint8_t idx, uint8_t fallback) { \ + return reinterpret_cast<::ProgmemStr>(get_(idx, fallback)); \ + } \ + static const ::esphome::LogString *get_log_str(uint8_t idx, uint8_t fallback) { \ + return reinterpret_cast<const ::esphome::LogString *>(get_(idx, fallback)); \ + } \ + } + +} // namespace esphome From c3622ef7fb18aed84c1b59357a37945955bb7086 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 15:52:41 +0100 Subject: [PATCH 0542/2030] [http_request] Fix chunked transfer encoding on Arduino platforms (#13790) --- .../http_request/http_request_arduino.cpp | 193 ++++++++++++++++-- .../http_request/http_request_arduino.h | 18 ++ .../http_request/ota/ota_http_request.cpp | 6 +- esphome/core/helpers.cpp | 2 +- esphome/core/helpers.h | 5 +- 5 files changed, 198 insertions(+), 26 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 2f12b58766..aee1f651bf 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -133,20 +133,10 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur // HTTPClient::getSize() returns -1 for chunked transfer encoding (no Content-Length). // When cast to size_t, -1 becomes SIZE_MAX (4294967295 on 32-bit). - // The read() method handles this: bytes_read_ can never reach SIZE_MAX, so the - // early return check (bytes_read_ >= content_length) will never trigger. - // - // TODO: Chunked transfer encoding is NOT properly supported on Arduino. - // The implementation in #7884 was incomplete - it only works correctly on ESP-IDF where - // esp_http_client_read() decodes chunks internally. On Arduino, using getStreamPtr() - // returns raw TCP data with chunk framing (e.g., "12a\r\n{json}\r\n0\r\n\r\n") instead - // of decoded content. This wasn't noticed because requests would complete and payloads - // were only examined on IDF. The long transfer times were also masked by the misleading - // "HTTP on Arduino version >= 3.1 is **very** slow" warning above. This causes two issues: - // 1. Response body is corrupted - contains chunk size headers mixed with data - // 2. Cannot detect end of transfer - connection stays open (keep-alive), causing timeout - // The proper fix would be to use getString() for chunked responses, which decodes chunks - // internally, but this buffers the entire response in memory. + // The read() method uses a chunked transfer encoding decoder (read_chunked_) to strip + // chunk framing and deliver only decoded content. When the final 0-size chunk is received, + // is_chunked_ is cleared and content_length is set to the actual decoded size, so + // is_read_complete() returns true and callers exit their read loops correctly. int content_length = container->client_.getSize(); ESP_LOGD(TAG, "Content-Length: %d", content_length); container->content_length = (size_t) content_length; @@ -174,6 +164,10 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur // > 0: bytes read // 0: no data yet, retry <-- NOTE: 0 means retry, NOT EOF! // < 0: error/connection closed <-- connection closed returns -1, not 0 +// +// For chunked transfer encoding, read_chunked_() decodes chunk framing and delivers +// only the payload data. When the final 0-size chunk is received, it clears is_chunked_ +// and sets content_length = bytes_read_ so is_read_complete() returns true. int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); @@ -184,24 +178,42 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { return HTTP_ERROR_CONNECTION_CLOSED; } + if (this->is_chunked_) { + int result = this->read_chunked_(buf, max_len, stream_ptr); + this->duration_ms += (millis() - start); + if (result > 0) { + return result; + } + // result <= 0: check for completion or errors + if (this->is_read_complete()) { + return 0; // Chunked transfer complete (final 0-size chunk received) + } + if (result < 0) { + return result; // Stream error during chunk decoding + } + // read_chunked_ returned 0: no data was available (available() was 0). + // This happens when the TCP buffer is empty - either more data is in flight, + // or the connection dropped. Arduino's connected() returns false only when + // both the remote has closed AND the receive buffer is empty, so any buffered + // data is fully drained before we report the drop. + if (!stream_ptr->connected()) { + return HTTP_ERROR_CONNECTION_CLOSED; + } + return 0; // No data yet, caller should retry + } + + // Non-chunked path int available_data = stream_ptr->available(); - // For chunked transfer encoding, HTTPClient::getSize() returns -1, which becomes SIZE_MAX when - // cast to size_t. SIZE_MAX - bytes_read_ is still huge, so it won't limit the read. size_t remaining = (this->content_length > 0) ? (this->content_length - this->bytes_read_) : max_len; int bufsize = std::min(max_len, std::min(remaining, (size_t) available_data)); if (bufsize == 0) { this->duration_ms += (millis() - start); - // Check if we've read all expected content (non-chunked only) - // For chunked encoding (content_length == SIZE_MAX), is_read_complete() returns false if (this->is_read_complete()) { return 0; // All content read successfully } - // No data available - check if connection is still open - // For chunked encoding, !connected() after reading means EOF (all chunks received) - // For known content_length with bytes_read_ < content_length, it means connection dropped if (!stream_ptr->connected()) { - return HTTP_ERROR_CONNECTION_CLOSED; // Connection closed or EOF for chunked + return HTTP_ERROR_CONNECTION_CLOSED; } return 0; // No data yet, caller should retry } @@ -215,6 +227,143 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) { return read_len; } +void HttpContainerArduino::chunk_header_complete_() { + if (this->chunk_remaining_ == 0) { + this->chunk_state_ = ChunkedState::CHUNK_TRAILER; + this->chunk_remaining_ = 1; // repurpose as at-start-of-line flag + } else { + this->chunk_state_ = ChunkedState::CHUNK_DATA; + } +} + +// Chunked transfer encoding decoder +// +// On Arduino, getStreamPtr() returns raw TCP data. For chunked responses, this includes +// chunk framing (size headers, CRLF delimiters) mixed with payload data. This decoder +// strips the framing and delivers only decoded content to the caller. +// +// Chunk format (RFC 9112 Section 7.1): +// <hex-size>[;extension]\r\n +// <data bytes>\r\n +// ... +// 0\r\n +// [trailer-field\r\n]* +// \r\n +// +// Non-blocking: only processes bytes already in the TCP receive buffer. +// State (chunk_state_, chunk_remaining_) is preserved between calls, so partial +// chunk headers or split \r\n sequences resume correctly on the next call. +// Framing bytes (hex sizes, \r\n) may be consumed without producing output; +// the caller sees 0 and retries via the normal read timeout logic. +// +// WiFiClient::read() returns -1 on error despite available() > 0 (connection reset +// between check and read). On any stream error (c < 0 or readBytes <= 0), we return +// already-decoded data if any; otherwise HTTP_ERROR_CONNECTION_CLOSED. The error +// will surface again on the next call since the stream stays broken. +// +// Returns: > 0 decoded bytes, 0 no data available, < 0 error +int HttpContainerArduino::read_chunked_(uint8_t *buf, size_t max_len, WiFiClient *stream) { + int total_decoded = 0; + + while (total_decoded < (int) max_len && this->chunk_state_ != ChunkedState::COMPLETE) { + // Non-blocking: only process what's already buffered + if (stream->available() == 0) + break; + + // CHUNK_DATA reads multiple bytes; handle before the single-byte switch + if (this->chunk_state_ == ChunkedState::CHUNK_DATA) { + // Only read what's available, what fits in buf, and what remains in this chunk + size_t to_read = + std::min({max_len - (size_t) total_decoded, this->chunk_remaining_, (size_t) stream->available()}); + if (to_read == 0) + break; + App.feed_wdt(); + int read_len = stream->readBytes(buf + total_decoded, to_read); + if (read_len <= 0) + return total_decoded > 0 ? total_decoded : HTTP_ERROR_CONNECTION_CLOSED; + total_decoded += read_len; + this->chunk_remaining_ -= read_len; + this->bytes_read_ += read_len; + if (this->chunk_remaining_ == 0) + this->chunk_state_ = ChunkedState::CHUNK_DATA_TRAIL; + continue; + } + + // All other states consume a single byte + int c = stream->read(); + if (c < 0) + return total_decoded > 0 ? total_decoded : HTTP_ERROR_CONNECTION_CLOSED; + + switch (this->chunk_state_) { + // Parse hex chunk size, one byte at a time: "<hex>[;ext]\r\n" + // Note: if no hex digits are parsed (e.g., bare \r\n), chunk_remaining_ stays 0 + // and is treated as the final chunk. This is intentionally lenient — on embedded + // devices, rejecting malformed framing is less useful than terminating cleanly. + // Overflow of chunk_remaining_ from extremely long hex strings (>8 digits on + // 32-bit) is not checked; >4GB chunks are unrealistic on embedded targets and + // would simply cause fewer bytes to be read from that chunk. + case ChunkedState::CHUNK_HEADER: + if (c == '\n') { + // \n terminates the size line; chunk_remaining_ == 0 means last chunk + this->chunk_header_complete_(); + } else { + uint8_t hex = parse_hex_char(c); + if (hex != INVALID_HEX_CHAR) { + this->chunk_remaining_ = (this->chunk_remaining_ << 4) | hex; + } else if (c != '\r') { + this->chunk_state_ = ChunkedState::CHUNK_HEADER_EXT; // ';' starts extension, skip to \n + } + } + break; + + // Skip chunk extension bytes until \n (e.g., ";name=value\r\n") + case ChunkedState::CHUNK_HEADER_EXT: + if (c == '\n') { + this->chunk_header_complete_(); + } + break; + + // Consume \r\n trailing each chunk's data + case ChunkedState::CHUNK_DATA_TRAIL: + if (c == '\n') { + this->chunk_state_ = ChunkedState::CHUNK_HEADER; + this->chunk_remaining_ = 0; // reset for next chunk's hex accumulation + } + // else: \r is consumed silently, next iteration gets \n + break; + + // Consume optional trailer headers and terminating empty line after final chunk. + // Per RFC 9112 Section 7.1: "0\r\n" is followed by optional "field\r\n" lines + // and a final "\r\n". chunk_remaining_ is repurposed as a flag: 1 = at start + // of line (may be the empty terminator), 0 = mid-line (reading a trailer field). + case ChunkedState::CHUNK_TRAILER: + if (c == '\n') { + if (this->chunk_remaining_ != 0) { + this->chunk_state_ = ChunkedState::COMPLETE; // Empty line terminates trailers + } else { + this->chunk_remaining_ = 1; // End of trailer field, at start of next line + } + } else if (c != '\r') { + this->chunk_remaining_ = 0; // Non-CRLF char: reading a trailer field + } + // \r doesn't change the flag — it's part of \r\n line endings + break; + + default: + break; + } + + if (this->chunk_state_ == ChunkedState::COMPLETE) { + // Clear chunked flag and set content_length to actual decoded size so + // is_read_complete() returns true and callers exit their read loops + this->is_chunked_ = false; + this->content_length = this->bytes_read_; + } + } + + return total_decoded; +} + void HttpContainerArduino::end() { watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); this->client_.end(); diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h index d9b5af9d81..a1084b12d5 100644 --- a/esphome/components/http_request/http_request_arduino.h +++ b/esphome/components/http_request/http_request_arduino.h @@ -18,6 +18,17 @@ namespace esphome::http_request { class HttpRequestArduino; + +/// State machine for decoding chunked transfer encoding on Arduino +enum class ChunkedState : uint8_t { + CHUNK_HEADER, ///< Reading hex digits of chunk size + CHUNK_HEADER_EXT, ///< Skipping chunk extensions until \n + CHUNK_DATA, ///< Reading chunk data bytes + CHUNK_DATA_TRAIL, ///< Skipping \r\n after chunk data + CHUNK_TRAILER, ///< Consuming trailer headers after final 0-size chunk + COMPLETE, ///< Finished: final chunk and trailers consumed +}; + class HttpContainerArduino : public HttpContainer { public: int read(uint8_t *buf, size_t max_len) override; @@ -26,6 +37,13 @@ class HttpContainerArduino : public HttpContainer { protected: friend class HttpRequestArduino; HTTPClient client_{}; + + /// Decode chunked transfer encoding from the raw stream + int read_chunked_(uint8_t *buf, size_t max_len, WiFiClient *stream); + /// Transition from chunk header to data or trailer based on parsed size + void chunk_header_complete_(); + ChunkedState chunk_state_{ChunkedState::CHUNK_HEADER}; + size_t chunk_remaining_{0}; ///< Bytes remaining in current chunk }; class HttpRequestArduino : public HttpRequestComponent { diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 8f4ecfab2d..882def4d7f 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -133,8 +133,10 @@ uint8_t OtaHttpRequestComponent::do_ota_() { auto result = http_read_loop_result(bufsize_or_error, last_data_time, read_timeout, container->is_read_complete()); if (result == HttpReadLoopResult::RETRY) continue; - // Note: COMPLETE is currently unreachable since the loop condition checks bytes_read < content_length, - // but this is defensive code in case chunked transfer encoding support is added for OTA in the future. + // For non-chunked responses, COMPLETE is unreachable (loop condition checks bytes_read < content_length). + // For chunked responses, the decoder sets content_length = bytes_read when the final chunk arrives, + // which causes the loop condition to terminate. But COMPLETE can still be returned if the decoder + // finishes mid-read, so this is needed for correctness. if (result == HttpReadLoopResult::COMPLETE) break; if (result != HttpReadLoopResult::DATA) { diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 1a5d22f8d8..c2f7f67d9a 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -295,7 +295,7 @@ size_t parse_hex(const char *str, size_t length, uint8_t *data, size_t count) { size_t chars = std::min(length, 2 * count); for (size_t i = 2 * count - chars; i < 2 * count; i++, str++) { uint8_t val = parse_hex_char(*str); - if (val > 15) + if (val == INVALID_HEX_CHAR) return 0; data[i >> 1] = (i & 1) ? data[i >> 1] | val : val << 4; } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 9c7060cd1d..f7de34b6d5 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -874,6 +874,9 @@ template<typename T, enable_if_t<std::is_unsigned<T>::value, int> = 0> optional< } /// Parse a hex character to its nibble value (0-15), returns 255 on invalid input +/// Returned by parse_hex_char() for non-hex characters. +static constexpr uint8_t INVALID_HEX_CHAR = 255; + constexpr uint8_t parse_hex_char(char c) { if (c >= '0' && c <= '9') return c - '0'; @@ -881,7 +884,7 @@ constexpr uint8_t parse_hex_char(char c) { return c - 'A' + 10; if (c >= 'a' && c <= 'f') return c - 'a' + 10; - return 255; + return INVALID_HEX_CHAR; } /// Convert a nibble (0-15) to hex char with specified base ('a' for lowercase, 'A' for uppercase) From ec477801cab5ac6d9b91a0359af640eeeab34086 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 17:23:19 +0100 Subject: [PATCH 0543/2030] [wifi] Defer ESP8266 WiFi listener callbacks from system context to main loop (#13789) --- esphome/components/wifi/wifi_component.cpp | 35 ++++++++ esphome/components/wifi/wifi_component.h | 79 ++++++++++++------- .../wifi/wifi_component_esp8266.cpp | 60 +++++++------- .../wifi/wifi_component_esp_idf.cpp | 21 ++--- .../wifi/wifi_component_libretiny.cpp | 21 ++--- .../components/wifi/wifi_component_pico_w.cpp | 17 +--- 6 files changed, 132 insertions(+), 101 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index e9b78c9225..0fe98162f3 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1470,6 +1470,14 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { this->notify_connect_state_listeners_(); #endif +#if defined(USE_ESP8266) && defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) + // On ESP8266, GOT_IP event may not fire for static IP configurations, + // so notify IP state listeners here as a fallback. + if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { + this->notify_ip_state_listeners_(); + } +#endif + return; } @@ -1481,7 +1489,11 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { } if (this->error_from_callback_) { + // ESP8266: logging done in callback, listeners deferred via pending_.disconnect + // Other platforms: just log generic failure message +#ifndef USE_ESP8266 ESP_LOGW(TAG, "Connecting to network failed (callback)"); +#endif this->retry_connect(); return; } @@ -2202,8 +2214,31 @@ void WiFiComponent::notify_connect_state_listeners_() { listener->on_wifi_connect_state(StringRef(ssid, strlen(ssid)), bssid); } } + +void WiFiComponent::notify_disconnect_state_listeners_() { + constexpr uint8_t empty_bssid[6] = {}; + for (auto *listener : this->connect_state_listeners_) { + listener->on_wifi_connect_state(StringRef(), empty_bssid); + } +} #endif // USE_WIFI_CONNECT_STATE_LISTENERS +#ifdef USE_WIFI_IP_STATE_LISTENERS +void WiFiComponent::notify_ip_state_listeners_() { + for (auto *listener : this->ip_state_listeners_) { + listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); + } +} +#endif // USE_WIFI_IP_STATE_LISTENERS + +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS +void WiFiComponent::notify_scan_results_listeners_() { + for (auto *listener : this->scan_results_listeners_) { + listener->on_wifi_scan_results(this->scan_result_); + } +} +#endif // USE_WIFI_SCAN_RESULTS_LISTENERS + void WiFiComponent::check_roaming_(uint32_t now) { // Guard: not for hidden networks (may not appear in scan) const WiFiAP *selected = this->get_selected_sta_(); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 98f339809a..58f19c184a 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -594,6 +594,9 @@ class WiFiComponent : public Component { void connect_soon_(); void wifi_loop_(); +#ifdef USE_ESP8266 + void process_pending_callbacks_(); +#endif bool wifi_mode_(optional<bool> sta, optional<bool> ap); bool wifi_sta_pre_setup_(); bool wifi_apply_output_power_(float output_power); @@ -635,6 +638,16 @@ class WiFiComponent : public Component { #ifdef USE_WIFI_CONNECT_STATE_LISTENERS /// Notify connect state listeners (called after state machine reaches STA_CONNECTED) void notify_connect_state_listeners_(); + /// Notify connect state listeners of disconnection + void notify_disconnect_state_listeners_(); +#endif +#ifdef USE_WIFI_IP_STATE_LISTENERS + /// Notify IP state listeners with current addresses + void notify_ip_state_listeners_(); +#endif +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS + /// Notify scan results listeners with current scan results + void notify_scan_results_listeners_(); #endif #ifdef USE_ESP8266 @@ -658,13 +671,13 @@ class WiFiComponent : public Component { void wifi_scan_done_callback_(); #endif + // Large/pointer-aligned members first FixedVector<WiFiAP> sta_; std::vector<WiFiSTAPriority> sta_priorities_; wifi_scan_vector_t<WiFiScanResult> scan_result_; #ifdef USE_WIFI_AP WiFiAP ap_; #endif - float output_power_{NAN}; #ifdef USE_WIFI_IP_STATE_LISTENERS StaticVector<WiFiIPStateListener *, ESPHOME_WIFI_IP_STATE_LISTENERS> ip_state_listeners_; #endif @@ -681,6 +694,15 @@ class WiFiComponent : public Component { #ifdef USE_WIFI_FAST_CONNECT ESPPreferenceObject fast_connect_pref_; #endif +#ifdef USE_WIFI_CONNECT_TRIGGER + Trigger<> connect_trigger_; +#endif +#ifdef USE_WIFI_DISCONNECT_TRIGGER + Trigger<> disconnect_trigger_; +#endif +#if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) + SemaphoreHandle_t high_performance_semaphore_{nullptr}; +#endif // Post-connect roaming constants static constexpr uint32_t ROAMING_CHECK_INTERVAL = 5 * 60 * 1000; // 5 minutes @@ -688,7 +710,8 @@ class WiFiComponent : public Component { static constexpr int8_t ROAMING_GOOD_RSSI = -49; // Skip scan if signal is excellent static constexpr uint8_t ROAMING_MAX_ATTEMPTS = 3; - // Group all 32-bit integers together + // 4-byte members + float output_power_{NAN}; uint32_t action_started_; uint32_t last_connected_{0}; uint32_t reboot_timeout_{}; @@ -697,7 +720,7 @@ class WiFiComponent : public Component { uint32_t ap_timeout_{}; #endif - // Group all 8-bit values together + // 1-byte enums and integers WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF}; WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE}; WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2}; @@ -708,17 +731,39 @@ class WiFiComponent : public Component { // int8_t limits to 127 APs (enforced in __init__.py via MAX_WIFI_NETWORKS) int8_t selected_sta_index_{-1}; uint8_t roaming_attempts_{0}; - #if USE_NETWORK_IPV6 uint8_t num_ipv6_addresses_{0}; #endif /* USE_NETWORK_IPV6 */ + bool error_from_callback_{false}; + RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; + RoamingState roaming_state_{RoamingState::IDLE}; +#if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) + WiFiPowerSaveMode configured_power_save_{WIFI_POWER_SAVE_NONE}; +#endif - // Group all boolean values together + // Bools and bitfields + // Pending listener callbacks deferred from platform callbacks to main loop. + struct { +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + // Deferred until state machine reaches STA_CONNECTED so wifi.connected + // condition returns true in listener automations. + bool connect_state : 1; +#ifdef USE_ESP8266 + // ESP8266: also defer disconnect notification to main loop + bool disconnect : 1; +#endif +#endif +#if defined(USE_ESP8266) && defined(USE_WIFI_IP_STATE_LISTENERS) + bool got_ip : 1; +#endif +#if defined(USE_ESP8266) && defined(USE_WIFI_SCAN_RESULTS_LISTENERS) + bool scan_complete : 1; +#endif + } pending_{}; bool has_ap_{false}; #if defined(USE_WIFI_CONNECT_TRIGGER) || defined(USE_WIFI_DISCONNECT_TRIGGER) bool handled_connected_state_{false}; #endif - bool error_from_callback_{false}; bool scan_done_{false}; bool ap_setup_{false}; bool ap_started_{false}; @@ -733,32 +778,10 @@ class WiFiComponent : public Component { bool keep_scan_results_{false}; bool has_completed_scan_after_captive_portal_start_{ false}; // Tracks if we've completed a scan after captive portal started - RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; bool skip_cooldown_next_cycle_{false}; bool post_connect_roaming_{true}; // Enabled by default - RoamingState roaming_state_{RoamingState::IDLE}; #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) - WiFiPowerSaveMode configured_power_save_{WIFI_POWER_SAVE_NONE}; bool is_high_performance_mode_{false}; - - SemaphoreHandle_t high_performance_semaphore_{nullptr}; -#endif - -#ifdef USE_WIFI_CONNECT_STATE_LISTENERS - // Pending listener notifications deferred until state machine reaches appropriate state. - // Listeners are notified after state transitions complete so conditions like - // wifi.connected return correct values in automations. - // Uses bitfields to minimize memory; more flags may be added as needed. - struct { - bool connect_state : 1; // Notify connect state listeners after STA_CONNECTED - } pending_{}; -#endif - -#ifdef USE_WIFI_CONNECT_TRIGGER - Trigger<> connect_trigger_; -#endif -#ifdef USE_WIFI_DISCONNECT_TRIGGER - Trigger<> disconnect_trigger_; #endif private: diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 0765fdc03b..6e2adcbf04 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -506,16 +506,6 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { // Defer listener notification until state machine reaches STA_CONNECTED // This ensures wifi.connected condition returns true in listener automations global_wifi_component->pending_.connect_state = true; -#endif - // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) - if (const WiFiAP *config = global_wifi_component->get_selected_sta_(); - config && config->get_manual_ip().has_value()) { - for (auto *listener : global_wifi_component->ip_state_listeners_) { - listener->on_ip_state(global_wifi_component->wifi_sta_ip_addresses(), - global_wifi_component->get_dns_address(0), global_wifi_component->get_dns_address(1)); - } - } #endif break; } @@ -534,16 +524,9 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { } s_sta_connected = false; s_sta_connecting = false; - // IMPORTANT: Set error flag BEFORE notifying listeners. - // This ensures is_connected() returns false during listener callbacks, - // which is critical for proper reconnection logic (e.g., roaming). global_wifi_component->error_from_callback_ = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - // Notify listeners AFTER setting error flag so they see correct state - static constexpr uint8_t EMPTY_BSSID[6] = {}; - for (auto *listener : global_wifi_component->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); - } + global_wifi_component->pending_.disconnect = true; #endif break; } @@ -555,8 +538,6 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { // https://lbsfilm.at/blog/wpa2-authenticationmode-downgrade-in-espressif-microprocessors if (it.old_mode != AUTH_OPEN && it.new_mode == AUTH_OPEN) { ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting"); - // we can't call retry_connect() from this context, so disconnect immediately - // and notify main thread with error_from_callback_ wifi_station_disconnect(); global_wifi_component->error_from_callback_ = true; } @@ -570,10 +551,8 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { network::IPAddress(&it.gw).str_to(gw_buf), network::IPAddress(&it.mask).str_to(mask_buf)); s_sta_got_ip = true; #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : global_wifi_component->ip_state_listeners_) { - listener->on_ip_state(global_wifi_component->wifi_sta_ip_addresses(), global_wifi_component->get_dns_address(0), - global_wifi_component->get_dns_address(1)); - } + // Defer listener callbacks to main loop - system context has limited stack + global_wifi_component->pending_.got_ip = true; #endif break; } @@ -785,9 +764,7 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { needs_full ? "" : " (filtered)"); this->scan_done_ = true; #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS - for (auto *listener : global_wifi_component->scan_results_listeners_) { - listener->on_wifi_scan_results(global_wifi_component->scan_result_); - } + this->pending_.scan_complete = true; // Defer listener callbacks to main loop #endif } @@ -974,7 +951,34 @@ network::IPAddress WiFiComponent::wifi_gateway_ip_() { return network::IPAddress(&ip.gw); } network::IPAddress WiFiComponent::wifi_dns_ip_(int num) { return network::IPAddress(dns_getserver(num)); } -void WiFiComponent::wifi_loop_() {} +void WiFiComponent::wifi_loop_() { this->process_pending_callbacks_(); } + +void WiFiComponent::process_pending_callbacks_() { + // Process callbacks deferred from ESP8266 SDK system context (~2KB stack) + // to main loop context (full stack). Connect state listeners are handled + // by notify_connect_state_listeners_() in the shared state machine code. + +#ifdef USE_WIFI_CONNECT_STATE_LISTENERS + if (this->pending_.disconnect) { + this->pending_.disconnect = false; + this->notify_disconnect_state_listeners_(); + } +#endif + +#ifdef USE_WIFI_IP_STATE_LISTENERS + if (this->pending_.got_ip) { + this->pending_.got_ip = false; + this->notify_ip_state_listeners_(); + } +#endif + +#ifdef USE_WIFI_SCAN_RESULTS_LISTENERS + if (this->pending_.scan_complete) { + this->pending_.scan_complete = false; + this->notify_scan_results_listeners_(); + } +#endif +} } // namespace esphome::wifi #endif diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 22bf4be483..d74d083954 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -753,9 +753,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); } #endif @@ -779,10 +777,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { s_sta_connecting = false; error_from_callback_ = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - static constexpr uint8_t EMPTY_BSSID[6] = {}; - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); - } + this->notify_disconnect_state_listeners_(); #endif } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_STA_GOT_IP) { @@ -793,9 +788,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { ESP_LOGV(TAG, "static_ip=" IPSTR " gateway=" IPSTR, IP2STR(&it.ip_info.ip), IP2STR(&it.ip_info.gw)); this->got_ipv4_address_ = true; #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif #if USE_NETWORK_IPV6 @@ -804,9 +797,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { ESP_LOGV(TAG, "IPv6 address=" IPV6STR, IPV62STR(it.ip6_info.ip)); this->num_ipv6_addresses_++; #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif #endif /* USE_NETWORK_IPV6 */ @@ -883,9 +874,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { ESP_LOGV(TAG, "Scan complete: %u found, %zu stored%s", number, this->scan_result_.size(), needs_full ? "" : " (filtered)"); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS - for (auto *listener : this->scan_results_listeners_) { - listener->on_wifi_scan_results(this->scan_result_); - } + this->notify_scan_results_listeners_(); #endif } else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_AP_START) { diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 285a520ef5..5fd9d7663b 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -468,9 +468,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_state = LTWiFiSTAState::CONNECTED; #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif } #endif @@ -527,10 +525,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { } #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - static constexpr uint8_t EMPTY_BSSID[6] = {}; - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); - } + this->notify_disconnect_state_listeners_(); #endif break; } @@ -553,18 +548,14 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { network::IPAddress(WiFi.gatewayIP()).str_to(gw_buf)); s_sta_state = LTWiFiSTAState::CONNECTED; #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif break; } case ESPHOME_EVENT_ID_WIFI_STA_GOT_IP6: { ESP_LOGV(TAG, "Got IPv6"); #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif break; } @@ -708,9 +699,7 @@ void WiFiComponent::wifi_scan_done_callback_() { needs_full ? "" : " (filtered)"); WiFi.scanDelete(); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS - for (auto *listener : this->scan_results_listeners_) { - listener->on_wifi_scan_results(this->scan_result_); - } + this->notify_scan_results_listeners_(); #endif } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 1ce36c2d93..818ad1059c 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -264,9 +264,7 @@ void WiFiComponent::wifi_loop_() { ESP_LOGV(TAG, "Scan complete: %zu found, %zu stored%s", s_scan_result_count, this->scan_result_.size(), needs_full ? "" : " (filtered)"); #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS - for (auto *listener : this->scan_results_listeners_) { - listener->on_wifi_scan_results(this->scan_result_); - } + this->notify_scan_results_listeners_(); #endif } @@ -290,9 +288,7 @@ void WiFiComponent::wifi_loop_() { #if defined(USE_WIFI_IP_STATE_LISTENERS) && defined(USE_WIFI_MANUAL_IP) if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { s_sta_had_ip = true; - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); } #endif } else if (!is_connected && s_sta_was_connected) { @@ -301,10 +297,7 @@ void WiFiComponent::wifi_loop_() { s_sta_had_ip = false; ESP_LOGV(TAG, "Disconnected"); #ifdef USE_WIFI_CONNECT_STATE_LISTENERS - static constexpr uint8_t EMPTY_BSSID[6] = {}; - for (auto *listener : this->connect_state_listeners_) { - listener->on_wifi_connect_state(StringRef(), EMPTY_BSSID); - } + this->notify_disconnect_state_listeners_(); #endif } @@ -322,9 +315,7 @@ void WiFiComponent::wifi_loop_() { s_sta_had_ip = true; ESP_LOGV(TAG, "Got IP address"); #ifdef USE_WIFI_IP_STATE_LISTENERS - for (auto *listener : this->ip_state_listeners_) { - listener->on_ip_state(this->wifi_sta_ip_addresses(), this->get_dns_address(0), this->get_dns_address(1)); - } + this->notify_ip_state_listeners_(); #endif } } From 44f308502e130c1bc8f7c9643c4e8a3e270f17bd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 17:37:02 +0100 Subject: [PATCH 0544/2030] [gpio] Convert interrupt_type_to_string to PROGMEM_STRING_TABLE (#13795) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../gpio/binary_sensor/gpio_binary_sensor.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp index 7a35596194..38ebbc90e4 100644 --- a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +++ b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp @@ -1,5 +1,6 @@ #include "gpio_binary_sensor.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace gpio { @@ -7,17 +8,12 @@ namespace gpio { static const char *const TAG = "gpio.binary_sensor"; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG +// Interrupt type strings indexed by edge-triggered InterruptType values: +// indices 1-3: RISING_EDGE, FALLING_EDGE, ANY_EDGE; other values (e.g. level-triggered) map to UNKNOWN (index 0). +PROGMEM_STRING_TABLE(InterruptTypeStrings, "UNKNOWN", "RISING_EDGE", "FALLING_EDGE", "ANY_EDGE"); + static const LogString *interrupt_type_to_string(gpio::InterruptType type) { - switch (type) { - case gpio::INTERRUPT_RISING_EDGE: - return LOG_STR("RISING_EDGE"); - case gpio::INTERRUPT_FALLING_EDGE: - return LOG_STR("FALLING_EDGE"); - case gpio::INTERRUPT_ANY_EDGE: - return LOG_STR("ANY_EDGE"); - default: - return LOG_STR("UNKNOWN"); - } + return InterruptTypeStrings::get_log_str(static_cast<uint8_t>(type), 0); } static const LogString *gpio_mode_to_string(bool use_interrupt) { From b7dc975331f944c14452542a1ed95c019872e856 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 17:37:19 +0100 Subject: [PATCH 0545/2030] [core] Convert entity string lookups to PROGMEM_STRING_TABLE (#13794) --- .../alarm_control_panel_state.cpp | 31 ++--- esphome/components/climate/climate_mode.cpp | 115 ++++-------------- esphome/components/fan/fan.cpp | 13 +- esphome/components/lock/lock.cpp | 20 +-- .../components/water_heater/water_heater.cpp | 24 +--- 5 files changed, 48 insertions(+), 155 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_state.cpp b/esphome/components/alarm_control_panel/alarm_control_panel_state.cpp index 862c620497..b8d246c861 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_state.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel_state.cpp @@ -1,32 +1,15 @@ #include "alarm_control_panel_state.h" +#include "esphome/core/progmem.h" namespace esphome::alarm_control_panel { +// Alarm control panel state strings indexed by AlarmControlPanelState enum (0-9) +PROGMEM_STRING_TABLE(AlarmControlPanelStateStrings, "DISARMED", "ARMED_HOME", "ARMED_AWAY", "ARMED_NIGHT", + "ARMED_VACATION", "ARMED_CUSTOM_BYPASS", "PENDING", "ARMING", "DISARMING", "TRIGGERED", "UNKNOWN"); + const LogString *alarm_control_panel_state_to_string(AlarmControlPanelState state) { - switch (state) { - case ACP_STATE_DISARMED: - return LOG_STR("DISARMED"); - case ACP_STATE_ARMED_HOME: - return LOG_STR("ARMED_HOME"); - case ACP_STATE_ARMED_AWAY: - return LOG_STR("ARMED_AWAY"); - case ACP_STATE_ARMED_NIGHT: - return LOG_STR("ARMED_NIGHT"); - case ACP_STATE_ARMED_VACATION: - return LOG_STR("ARMED_VACATION"); - case ACP_STATE_ARMED_CUSTOM_BYPASS: - return LOG_STR("ARMED_CUSTOM_BYPASS"); - case ACP_STATE_PENDING: - return LOG_STR("PENDING"); - case ACP_STATE_ARMING: - return LOG_STR("ARMING"); - case ACP_STATE_DISARMING: - return LOG_STR("DISARMING"); - case ACP_STATE_TRIGGERED: - return LOG_STR("TRIGGERED"); - default: - return LOG_STR("UNKNOWN"); - } + return AlarmControlPanelStateStrings::get_log_str(static_cast<uint8_t>(state), + AlarmControlPanelStateStrings::LAST_INDEX); } } // namespace esphome::alarm_control_panel diff --git a/esphome/components/climate/climate_mode.cpp b/esphome/components/climate/climate_mode.cpp index b153ee0424..c4dd19d503 100644 --- a/esphome/components/climate/climate_mode.cpp +++ b/esphome/components/climate/climate_mode.cpp @@ -1,109 +1,44 @@ #include "climate_mode.h" +#include "esphome/core/progmem.h" namespace esphome::climate { +// Climate mode strings indexed by ClimateMode enum (0-6): OFF, HEAT_COOL, COOL, HEAT, FAN_ONLY, DRY, AUTO +PROGMEM_STRING_TABLE(ClimateModeStrings, "OFF", "HEAT_COOL", "COOL", "HEAT", "FAN_ONLY", "DRY", "AUTO", "UNKNOWN"); + const LogString *climate_mode_to_string(ClimateMode mode) { - switch (mode) { - case CLIMATE_MODE_OFF: - return LOG_STR("OFF"); - case CLIMATE_MODE_HEAT_COOL: - return LOG_STR("HEAT_COOL"); - case CLIMATE_MODE_AUTO: - return LOG_STR("AUTO"); - case CLIMATE_MODE_COOL: - return LOG_STR("COOL"); - case CLIMATE_MODE_HEAT: - return LOG_STR("HEAT"); - case CLIMATE_MODE_FAN_ONLY: - return LOG_STR("FAN_ONLY"); - case CLIMATE_MODE_DRY: - return LOG_STR("DRY"); - default: - return LOG_STR("UNKNOWN"); - } + return ClimateModeStrings::get_log_str(static_cast<uint8_t>(mode), ClimateModeStrings::LAST_INDEX); } + +// Climate action strings indexed by ClimateAction enum (0,2-6): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN +PROGMEM_STRING_TABLE(ClimateActionStrings, "OFF", "UNKNOWN", "COOLING", "HEATING", "IDLE", "DRYING", "FAN", "UNKNOWN"); + const LogString *climate_action_to_string(ClimateAction action) { - switch (action) { - case CLIMATE_ACTION_OFF: - return LOG_STR("OFF"); - case CLIMATE_ACTION_COOLING: - return LOG_STR("COOLING"); - case CLIMATE_ACTION_HEATING: - return LOG_STR("HEATING"); - case CLIMATE_ACTION_IDLE: - return LOG_STR("IDLE"); - case CLIMATE_ACTION_DRYING: - return LOG_STR("DRYING"); - case CLIMATE_ACTION_FAN: - return LOG_STR("FAN"); - default: - return LOG_STR("UNKNOWN"); - } + return ClimateActionStrings::get_log_str(static_cast<uint8_t>(action), ClimateActionStrings::LAST_INDEX); } +// Climate fan mode strings indexed by ClimateFanMode enum (0-9): ON, OFF, AUTO, LOW, MEDIUM, HIGH, MIDDLE, FOCUS, +// DIFFUSE, QUIET +PROGMEM_STRING_TABLE(ClimateFanModeStrings, "ON", "OFF", "AUTO", "LOW", "MEDIUM", "HIGH", "MIDDLE", "FOCUS", "DIFFUSE", + "QUIET", "UNKNOWN"); + const LogString *climate_fan_mode_to_string(ClimateFanMode fan_mode) { - switch (fan_mode) { - case climate::CLIMATE_FAN_ON: - return LOG_STR("ON"); - case climate::CLIMATE_FAN_OFF: - return LOG_STR("OFF"); - case climate::CLIMATE_FAN_AUTO: - return LOG_STR("AUTO"); - case climate::CLIMATE_FAN_LOW: - return LOG_STR("LOW"); - case climate::CLIMATE_FAN_MEDIUM: - return LOG_STR("MEDIUM"); - case climate::CLIMATE_FAN_HIGH: - return LOG_STR("HIGH"); - case climate::CLIMATE_FAN_MIDDLE: - return LOG_STR("MIDDLE"); - case climate::CLIMATE_FAN_FOCUS: - return LOG_STR("FOCUS"); - case climate::CLIMATE_FAN_DIFFUSE: - return LOG_STR("DIFFUSE"); - case climate::CLIMATE_FAN_QUIET: - return LOG_STR("QUIET"); - default: - return LOG_STR("UNKNOWN"); - } + return ClimateFanModeStrings::get_log_str(static_cast<uint8_t>(fan_mode), ClimateFanModeStrings::LAST_INDEX); } +// Climate swing mode strings indexed by ClimateSwingMode enum (0-3): OFF, BOTH, VERTICAL, HORIZONTAL +PROGMEM_STRING_TABLE(ClimateSwingModeStrings, "OFF", "BOTH", "VERTICAL", "HORIZONTAL", "UNKNOWN"); + const LogString *climate_swing_mode_to_string(ClimateSwingMode swing_mode) { - switch (swing_mode) { - case climate::CLIMATE_SWING_OFF: - return LOG_STR("OFF"); - case climate::CLIMATE_SWING_BOTH: - return LOG_STR("BOTH"); - case climate::CLIMATE_SWING_VERTICAL: - return LOG_STR("VERTICAL"); - case climate::CLIMATE_SWING_HORIZONTAL: - return LOG_STR("HORIZONTAL"); - default: - return LOG_STR("UNKNOWN"); - } + return ClimateSwingModeStrings::get_log_str(static_cast<uint8_t>(swing_mode), ClimateSwingModeStrings::LAST_INDEX); } +// Climate preset strings indexed by ClimatePreset enum (0-7): NONE, HOME, AWAY, BOOST, COMFORT, ECO, SLEEP, ACTIVITY +PROGMEM_STRING_TABLE(ClimatePresetStrings, "NONE", "HOME", "AWAY", "BOOST", "COMFORT", "ECO", "SLEEP", "ACTIVITY", + "UNKNOWN"); + const LogString *climate_preset_to_string(ClimatePreset preset) { - switch (preset) { - case climate::CLIMATE_PRESET_NONE: - return LOG_STR("NONE"); - case climate::CLIMATE_PRESET_HOME: - return LOG_STR("HOME"); - case climate::CLIMATE_PRESET_ECO: - return LOG_STR("ECO"); - case climate::CLIMATE_PRESET_AWAY: - return LOG_STR("AWAY"); - case climate::CLIMATE_PRESET_BOOST: - return LOG_STR("BOOST"); - case climate::CLIMATE_PRESET_COMFORT: - return LOG_STR("COMFORT"); - case climate::CLIMATE_PRESET_SLEEP: - return LOG_STR("SLEEP"); - case climate::CLIMATE_PRESET_ACTIVITY: - return LOG_STR("ACTIVITY"); - default: - return LOG_STR("UNKNOWN"); - } + return ClimatePresetStrings::get_log_str(static_cast<uint8_t>(preset), ClimatePresetStrings::LAST_INDEX); } } // namespace esphome::climate diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index a983babe1c..d70a2940bc 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -2,21 +2,18 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace fan { static const char *const TAG = "fan"; +// Fan direction strings indexed by FanDirection enum (0-1): FORWARD, REVERSE, plus UNKNOWN +PROGMEM_STRING_TABLE(FanDirectionStrings, "FORWARD", "REVERSE", "UNKNOWN"); + const LogString *fan_direction_to_string(FanDirection direction) { - switch (direction) { - case FanDirection::FORWARD: - return LOG_STR("FORWARD"); - case FanDirection::REVERSE: - return LOG_STR("REVERSE"); - default: - return LOG_STR("UNKNOWN"); - } + return FanDirectionStrings::get_log_str(static_cast<uint8_t>(direction), FanDirectionStrings::LAST_INDEX); } FanCall &FanCall::set_preset_mode(const std::string &preset_mode) { diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 4c61418256..939c84720b 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -8,22 +8,12 @@ namespace esphome::lock { static const char *const TAG = "lock"; +// Lock state strings indexed by LockState enum (0-5): NONE(UNKNOWN), LOCKED, UNLOCKED, JAMMED, LOCKING, UNLOCKING +// Index 0 is UNKNOWN (for LOCK_STATE_NONE), also used as fallback for out-of-range +PROGMEM_STRING_TABLE(LockStateStrings, "UNKNOWN", "LOCKED", "UNLOCKED", "JAMMED", "LOCKING", "UNLOCKING"); + const LogString *lock_state_to_string(LockState state) { - switch (state) { - case LOCK_STATE_LOCKED: - return LOG_STR("LOCKED"); - case LOCK_STATE_UNLOCKED: - return LOG_STR("UNLOCKED"); - case LOCK_STATE_JAMMED: - return LOG_STR("JAMMED"); - case LOCK_STATE_LOCKING: - return LOG_STR("LOCKING"); - case LOCK_STATE_UNLOCKING: - return LOG_STR("UNLOCKING"); - case LOCK_STATE_NONE: - default: - return LOG_STR("UNKNOWN"); - } + return LockStateStrings::get_log_str(static_cast<uint8_t>(state), 0); } Lock::Lock() : state(LOCK_STATE_NONE) {} diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 286addf7db..e6d1562352 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -233,25 +233,13 @@ void WaterHeater::set_visual_target_temperature_step_override(float visual_targe } #endif +// Water heater mode strings indexed by WaterHeaterMode enum (0-6): OFF, ECO, ELECTRIC, PERFORMANCE, HIGH_DEMAND, +// HEAT_PUMP, GAS +PROGMEM_STRING_TABLE(WaterHeaterModeStrings, "OFF", "ECO", "ELECTRIC", "PERFORMANCE", "HIGH_DEMAND", "HEAT_PUMP", "GAS", + "UNKNOWN"); + const LogString *water_heater_mode_to_string(WaterHeaterMode mode) { - switch (mode) { - case WATER_HEATER_MODE_OFF: - return LOG_STR("OFF"); - case WATER_HEATER_MODE_ECO: - return LOG_STR("ECO"); - case WATER_HEATER_MODE_ELECTRIC: - return LOG_STR("ELECTRIC"); - case WATER_HEATER_MODE_PERFORMANCE: - return LOG_STR("PERFORMANCE"); - case WATER_HEATER_MODE_HIGH_DEMAND: - return LOG_STR("HIGH_DEMAND"); - case WATER_HEATER_MODE_HEAT_PUMP: - return LOG_STR("HEAT_PUMP"); - case WATER_HEATER_MODE_GAS: - return LOG_STR("GAS"); - default: - return LOG_STR("UNKNOWN"); - } + return WaterHeaterModeStrings::get_log_str(static_cast<uint8_t>(mode), WaterHeaterModeStrings::LAST_INDEX); } void WaterHeater::dump_traits_(const char *tag) { From 368ef5687b95476c48659d6d3618772992d729fd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 17:37:41 +0100 Subject: [PATCH 0546/2030] [update] Move update_state_to_string to update component and convert to PROGMEM_STRING_TABLE (#13796) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/update/update_entity.cpp | 9 +++++++++ esphome/components/update/update_entity.h | 2 ++ esphome/components/web_server/web_server.cpp | 19 +++++-------------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 515e4c2c18..7edea2fe22 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -2,12 +2,21 @@ #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace update { static const char *const TAG = "update"; +// Update state strings indexed by UpdateState enum (0-3): UNKNOWN, NO UPDATE, UPDATE AVAILABLE, INSTALLING +PROGMEM_STRING_TABLE(UpdateStateStrings, "UNKNOWN", "NO UPDATE", "UPDATE AVAILABLE", "INSTALLING"); + +const LogString *update_state_to_string(UpdateState state) { + return UpdateStateStrings::get_log_str(static_cast<uint8_t>(state), + static_cast<uint8_t>(UpdateState::UPDATE_STATE_UNKNOWN)); +} + void UpdateEntity::publish_state() { ESP_LOGD(TAG, "'%s' >>\n" diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h index 8eba78b44b..405346bee4 100644 --- a/esphome/components/update/update_entity.h +++ b/esphome/components/update/update_entity.h @@ -27,6 +27,8 @@ enum UpdateState : uint8_t { UPDATE_STATE_INSTALLING, }; +const LogString *update_state_to_string(UpdateState state); + class UpdateEntity : public EntityBase, public EntityBase_DeviceClass { public: void publish_state(); diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 42219f3aac..dfd602be6b 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -29,6 +29,10 @@ #include "esphome/components/climate/climate.h" #endif +#ifdef USE_UPDATE +#include "esphome/components/update/update_entity.h" +#endif + #ifdef USE_WATER_HEATER #include "esphome/components/water_heater/water_heater.h" #endif @@ -2104,19 +2108,6 @@ std::string WebServer::event_json_(event::Event *obj, StringRef event_type, Json #endif #ifdef USE_UPDATE -static const LogString *update_state_to_string(update::UpdateState state) { - switch (state) { - case update::UPDATE_STATE_NO_UPDATE: - return LOG_STR("NO UPDATE"); - case update::UPDATE_STATE_AVAILABLE: - return LOG_STR("UPDATE AVAILABLE"); - case update::UPDATE_STATE_INSTALLING: - return LOG_STR("INSTALLING"); - default: - return LOG_STR("UNKNOWN"); - } -} - void WebServer::on_update(update::UpdateEntity *obj) { this->events_.deferrable_send_state(obj, "state", update_state_json_generator); } @@ -2158,7 +2149,7 @@ std::string WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_ JsonObject root = builder.root(); char buf[PSTR_LOCAL_SIZE]; - set_json_icon_state_value(root, obj, "update", PSTR_LOCAL(update_state_to_string(obj->state)), + set_json_icon_state_value(root, obj, "update", PSTR_LOCAL(update::update_state_to_string(obj->state)), obj->update_info.latest_version, start_config); if (start_config == DETAIL_ALL) { root[ESPHOME_F("current_version")] = obj->update_info.current_version; From c7c9ffe7e15b27a8c117ada0e8d9f3310d861b4c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 17:38:03 +0100 Subject: [PATCH 0547/2030] [light] Convert color_mode_to_human to PROGMEM_STRING_TABLE using to_bit() (#13797) --- esphome/components/light/light_call.cpp | 26 +++++++------------------ 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 6d42dd1513..f4bb0c5d11 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -4,6 +4,7 @@ #include "light_state.h" #include "esphome/core/log.h" #include "esphome/core/optional.h" +#include "esphome/core/progmem.h" namespace esphome::light { @@ -51,26 +52,13 @@ static void log_invalid_parameter(const char *name, const LogString *message) { return *this; \ } +// Color mode human-readable strings indexed by ColorModeBitPolicy::to_bit() (0-9) +// Index 0 is Unknown (for ColorMode::UNKNOWN), also used as fallback for out-of-range +PROGMEM_STRING_TABLE(ColorModeHumanStrings, "Unknown", "On/Off", "Brightness", "White", "Color temperature", + "Cold/warm white", "RGB", "RGBW", "RGB + color temperature", "RGB + cold/warm white"); + static const LogString *color_mode_to_human(ColorMode color_mode) { - if (color_mode == ColorMode::ON_OFF) - return LOG_STR("On/Off"); - if (color_mode == ColorMode::BRIGHTNESS) - return LOG_STR("Brightness"); - if (color_mode == ColorMode::WHITE) - return LOG_STR("White"); - if (color_mode == ColorMode::COLOR_TEMPERATURE) - return LOG_STR("Color temperature"); - if (color_mode == ColorMode::COLD_WARM_WHITE) - return LOG_STR("Cold/warm white"); - if (color_mode == ColorMode::RGB) - return LOG_STR("RGB"); - if (color_mode == ColorMode::RGB_WHITE) - return LOG_STR("RGBW"); - if (color_mode == ColorMode::RGB_COLD_WARM_WHITE) - return LOG_STR("RGB + cold/warm white"); - if (color_mode == ColorMode::RGB_COLOR_TEMPERATURE) - return LOG_STR("RGB + color temperature"); - return LOG_STR("Unknown"); + return ColorModeHumanStrings::get_log_str(ColorModeBitPolicy::to_bit(color_mode), 0); } // Helper to log percentage values From 2917057da81c7d815551c82c9d220f15bef4a53e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 18:08:30 +0100 Subject: [PATCH 0548/2030] [analyze-memory] Trace CSWTCH switch table symbols to source components (#13798) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/analyze_memory/__init__.py | 217 ++++++++++++++++++++++++++++- esphome/analyze_memory/cli.py | 50 +++++++ esphome/analyze_memory/const.py | 13 +- 3 files changed, 267 insertions(+), 13 deletions(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index 63ef0e74ed..d8c941e76f 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -12,7 +12,6 @@ from .const import ( CORE_SUBCATEGORY_PATTERNS, DEMANGLED_PATTERNS, ESPHOME_COMPONENT_PATTERN, - SECTION_TO_ATTR, SYMBOL_PATTERNS, ) from .demangle import batch_demangle @@ -91,6 +90,17 @@ class ComponentMemory: bss_size: int = 0 # Uninitialized data (ram only) symbol_count: int = 0 + def add_section_size(self, section_name: str, size: int) -> None: + """Add size to the appropriate attribute for a section.""" + if section_name == ".text": + self.text_size += size + elif section_name == ".rodata": + self.rodata_size += size + elif section_name == ".data": + self.data_size += size + elif section_name == ".bss": + self.bss_size += size + @property def flash_total(self) -> int: """Total flash usage (text + rodata + data).""" @@ -167,12 +177,15 @@ class MemoryAnalyzer: self._elf_symbol_names: set[str] = set() # SDK symbols not in ELF (static/local symbols from closed-source libs) self._sdk_symbols: list[SDKSymbol] = [] + # CSWTCH symbols: list of (name, size, source_file, component) + self._cswtch_symbols: list[tuple[str, int, str, str]] = [] def analyze(self) -> dict[str, ComponentMemory]: """Analyze the ELF file and return component memory usage.""" self._parse_sections() self._parse_symbols() self._categorize_symbols() + self._analyze_cswtch_symbols() self._analyze_sdk_libraries() return dict(self.components) @@ -255,8 +268,7 @@ class MemoryAnalyzer: comp_mem.symbol_count += 1 # Update the appropriate size attribute based on section - if attr_name := SECTION_TO_ATTR.get(section_name): - setattr(comp_mem, attr_name, getattr(comp_mem, attr_name) + size) + comp_mem.add_section_size(section_name, size) # Track uncategorized symbols if component == "other" and size > 0: @@ -372,6 +384,205 @@ class MemoryAnalyzer: return "Other Core" + def _find_object_files_dir(self) -> Path | None: + """Find the directory containing object files for this build. + + Returns: + Path to the directory containing .o files, or None if not found. + """ + # The ELF is typically at .pioenvs/<env>/firmware.elf + # Object files are in .pioenvs/<env>/src/ and .pioenvs/<env>/lib*/ + pioenvs_dir = self.elf_path.parent + if pioenvs_dir.exists() and any(pioenvs_dir.glob("src/*.o")): + return pioenvs_dir + return None + + def _scan_cswtch_in_objects( + self, obj_dir: Path + ) -> dict[str, list[tuple[str, int]]]: + """Scan object files for CSWTCH symbols using a single nm invocation. + + Uses ``nm --print-file-name -S`` on all ``.o`` files at once. + Output format: ``/path/to/file.o:address size type name`` + + Args: + obj_dir: Directory containing object files (.pioenvs/<env>/) + + Returns: + Dict mapping "CSWTCH$NNN:size" to list of (source_file, size) tuples. + """ + cswtch_map: dict[str, list[tuple[str, int]]] = defaultdict(list) + + if not self.nm_path: + return cswtch_map + + # Find all .o files recursively, sorted for deterministic output + obj_files = sorted(obj_dir.rglob("*.o")) + if not obj_files: + return cswtch_map + + _LOGGER.debug("Scanning %d object files for CSWTCH symbols", len(obj_files)) + + # Single nm call with --print-file-name for all object files + result = run_tool( + [self.nm_path, "--print-file-name", "-S"] + [str(f) for f in obj_files], + timeout=30, + ) + if result is None or result.returncode != 0: + return cswtch_map + + for line in result.stdout.splitlines(): + if "CSWTCH$" not in line: + continue + + # Split on last ":" that precedes a hex address. + # nm --print-file-name format: filepath:hex_addr hex_size type name + # We split from the right: find the last colon followed by hex digits. + parts_after_colon = line.rsplit(":", 1) + if len(parts_after_colon) != 2: + continue + + file_path = parts_after_colon[0] + fields = parts_after_colon[1].split() + # fields: [address, size, type, name] + if len(fields) < 4: + continue + + sym_name = fields[3] + if not sym_name.startswith("CSWTCH$"): + continue + + try: + size = int(fields[1], 16) + except ValueError: + continue + + # Get relative path from obj_dir for readability + try: + rel_path = str(Path(file_path).relative_to(obj_dir)) + except ValueError: + rel_path = file_path + + key = f"{sym_name}:{size}" + cswtch_map[key].append((rel_path, size)) + + return cswtch_map + + def _source_file_to_component(self, source_file: str) -> str: + """Map a source object file path to its component name. + + Args: + source_file: Relative path like 'src/esphome/components/wifi/wifi_component.cpp.o' + + Returns: + Component name like '[esphome]wifi' or the source file if unknown. + """ + parts = Path(source_file).parts + + # ESPHome component: src/esphome/components/<name>/... + if "components" in parts: + idx = parts.index("components") + if idx + 1 < len(parts): + component_name = parts[idx + 1] + if component_name in get_esphome_components(): + return f"{_COMPONENT_PREFIX_ESPHOME}{component_name}" + if component_name in self.external_components: + return f"{_COMPONENT_PREFIX_EXTERNAL}{component_name}" + + # ESPHome core: src/esphome/core/... or src/esphome/... + if "core" in parts and "esphome" in parts: + return _COMPONENT_CORE + if "esphome" in parts and "components" not in parts: + return _COMPONENT_CORE + + # Framework/library files - return the first path component + # e.g., lib65b/ESPAsyncTCP/... -> lib65b + # FrameworkArduino/... -> FrameworkArduino + return parts[0] if parts else source_file + + def _analyze_cswtch_symbols(self) -> None: + """Analyze CSWTCH (GCC switch table) symbols by tracing to source objects. + + CSWTCH symbols are compiler-generated lookup tables for switch statements. + They are local symbols, so the same name can appear in different object files. + This method scans .o files to attribute them to their source components. + """ + obj_dir = self._find_object_files_dir() + if obj_dir is None: + _LOGGER.debug("No object files directory found, skipping CSWTCH analysis") + return + + # Scan object files for CSWTCH symbols + cswtch_map = self._scan_cswtch_in_objects(obj_dir) + if not cswtch_map: + _LOGGER.debug("No CSWTCH symbols found in object files") + return + + # Collect CSWTCH symbols from the ELF (already parsed in sections) + # Include section_name for re-attribution of component totals + elf_cswtch = [ + (symbol_name, size, section_name) + for section_name, section in self.sections.items() + for symbol_name, size, _ in section.symbols + if symbol_name.startswith("CSWTCH$") + ] + + _LOGGER.debug( + "Found %d CSWTCH symbols in ELF, %d unique in object files", + len(elf_cswtch), + len(cswtch_map), + ) + + # Match ELF CSWTCH symbols to source files and re-attribute component totals. + # _categorize_symbols() already ran and put these into "other" since CSWTCH$ + # names don't match any component pattern. We move the bytes to the correct + # component based on the object file mapping. + other_mem = self.components.get("other") + + for sym_name, size, section_name in elf_cswtch: + key = f"{sym_name}:{size}" + sources = cswtch_map.get(key, []) + + if len(sources) == 1: + source_file = sources[0][0] + component = self._source_file_to_component(source_file) + elif len(sources) > 1: + # Ambiguous - multiple object files have same CSWTCH name+size + source_file = "ambiguous" + component = "ambiguous" + _LOGGER.debug( + "Ambiguous CSWTCH %s (%d B) found in %d files: %s", + sym_name, + size, + len(sources), + ", ".join(src for src, _ in sources), + ) + else: + source_file = "unknown" + component = "unknown" + + self._cswtch_symbols.append((sym_name, size, source_file, component)) + + # Re-attribute from "other" to the correct component + if ( + component not in ("other", "unknown", "ambiguous") + and other_mem is not None + ): + other_mem.add_section_size(section_name, -size) + if component not in self.components: + self.components[component] = ComponentMemory(component) + self.components[component].add_section_size(section_name, size) + + # Sort by size descending + self._cswtch_symbols.sort(key=lambda x: x[1], reverse=True) + + total_size = sum(size for _, size, _, _ in self._cswtch_symbols) + _LOGGER.debug( + "CSWTCH analysis: %d symbols, %d bytes total", + len(self._cswtch_symbols), + total_size, + ) + def get_unattributed_ram(self) -> tuple[int, int, int]: """Get unattributed RAM sizes (SDK/framework overhead). diff --git a/esphome/analyze_memory/cli.py b/esphome/analyze_memory/cli.py index 72a73dbdd4..bb0eb7723e 100644 --- a/esphome/analyze_memory/cli.py +++ b/esphome/analyze_memory/cli.py @@ -184,6 +184,52 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): f"{i + 1:>2}. {size:>7,} B {section_label:<8} {demangled_display:<{self.COL_TOP_SYMBOL_NAME}} {component}" ) + def _add_cswtch_analysis(self, lines: list[str]) -> None: + """Add CSWTCH (GCC switch table lookup) analysis section.""" + self._add_section_header(lines, "CSWTCH Analysis (GCC Switch Table Lookups)") + + total_size = sum(size for _, size, _, _ in self._cswtch_symbols) + lines.append( + f"Total: {len(self._cswtch_symbols)} switch table(s), {total_size:,} B" + ) + lines.append("") + + # Group by component + by_component: dict[str, list[tuple[str, int, str]]] = defaultdict(list) + for sym_name, size, source_file, component in self._cswtch_symbols: + by_component[component].append((sym_name, size, source_file)) + + # Sort components by total size descending + sorted_components = sorted( + by_component.items(), + key=lambda x: sum(s[1] for s in x[1]), + reverse=True, + ) + + for component, symbols in sorted_components: + comp_total = sum(s[1] for s in symbols) + lines.append(f"{component} ({comp_total:,} B, {len(symbols)} tables):") + + # Group by source file within component + by_file: dict[str, list[tuple[str, int]]] = defaultdict(list) + for sym_name, size, source_file in symbols: + by_file[source_file].append((sym_name, size)) + + for source_file, file_symbols in sorted( + by_file.items(), + key=lambda x: sum(s[1] for s in x[1]), + reverse=True, + ): + file_total = sum(s[1] for s in file_symbols) + lines.append( + f" {source_file} ({file_total:,} B, {len(file_symbols)} tables)" + ) + for sym_name, size in sorted( + file_symbols, key=lambda x: x[1], reverse=True + ): + lines.append(f" {size:>6,} B {sym_name}") + lines.append("") + def generate_report(self, detailed: bool = False) -> str: """Generate a formatted memory report.""" components = sorted( @@ -471,6 +517,10 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): lines.append(f" ... and {len(large_ram_syms) - 10} more") lines.append("") + # CSWTCH (GCC switch table) analysis + if self._cswtch_symbols: + self._add_cswtch_analysis(lines) + lines.append( "Note: This analysis covers symbols in the ELF file. Some runtime allocations may not be included." ) diff --git a/esphome/analyze_memory/const.py b/esphome/analyze_memory/const.py index 83547b1eb5..66866615a6 100644 --- a/esphome/analyze_memory/const.py +++ b/esphome/analyze_memory/const.py @@ -66,15 +66,6 @@ SECTION_MAPPING = { ), } -# Section to ComponentMemory attribute mapping -# Maps section names to the attribute name in ComponentMemory dataclass -SECTION_TO_ATTR = { - ".text": "text_size", - ".rodata": "rodata_size", - ".data": "data_size", - ".bss": "bss_size", -} - # Component identification rules # Symbol patterns: patterns found in raw symbol names SYMBOL_PATTERNS = { @@ -513,7 +504,9 @@ SYMBOL_PATTERNS = { "__FUNCTION__$", "DAYS_IN_MONTH", "_DAYS_BEFORE_MONTH", - "CSWTCH$", + # Note: CSWTCH$ symbols are GCC switch table lookup tables. + # They are attributed to their source object files via _analyze_cswtch_symbols() + # rather than being lumped into libc. "dst$", "sulp", "_strtol_l", # String to long with locale From f9192b5f75af343a41eb00b1cf82dd9b8380c90a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 18:20:46 +0100 Subject: [PATCH 0549/2030] [wifi] Avoid jump tables in LOG_STR switch statements to save ESP8266 RAM (#13799) --- esphome/components/wifi/wifi_component.cpp | 30 ++-- .../wifi/wifi_component_esp8266.cpp | 150 ++++++++---------- 2 files changed, 81 insertions(+), 99 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 0fe98162f3..e350f990af 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -236,25 +236,23 @@ static const char *const TAG = "wifi"; /// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ /// └──────────────────────────────────────────────────────────────────────┘ +// Use if-chain instead of switch to avoid jump table in RODATA (wastes RAM on ESP8266) static const LogString *retry_phase_to_log_string(WiFiRetryPhase phase) { - switch (phase) { - case WiFiRetryPhase::INITIAL_CONNECT: - return LOG_STR("INITIAL_CONNECT"); + if (phase == WiFiRetryPhase::INITIAL_CONNECT) + return LOG_STR("INITIAL_CONNECT"); #ifdef USE_WIFI_FAST_CONNECT - case WiFiRetryPhase::FAST_CONNECT_CYCLING_APS: - return LOG_STR("FAST_CONNECT_CYCLING"); + if (phase == WiFiRetryPhase::FAST_CONNECT_CYCLING_APS) + return LOG_STR("FAST_CONNECT_CYCLING"); #endif - case WiFiRetryPhase::EXPLICIT_HIDDEN: - return LOG_STR("EXPLICIT_HIDDEN"); - case WiFiRetryPhase::SCAN_CONNECTING: - return LOG_STR("SCAN_CONNECTING"); - case WiFiRetryPhase::RETRY_HIDDEN: - return LOG_STR("RETRY_HIDDEN"); - case WiFiRetryPhase::RESTARTING_ADAPTER: - return LOG_STR("RESTARTING"); - default: - return LOG_STR("UNKNOWN"); - } + if (phase == WiFiRetryPhase::EXPLICIT_HIDDEN) + return LOG_STR("EXPLICIT_HIDDEN"); + if (phase == WiFiRetryPhase::SCAN_CONNECTING) + return LOG_STR("SCAN_CONNECTING"); + if (phase == WiFiRetryPhase::RETRY_HIDDEN) + return LOG_STR("RETRY_HIDDEN"); + if (phase == WiFiRetryPhase::RESTARTING_ADAPTER) + return LOG_STR("RESTARTING"); + return LOG_STR("UNKNOWN"); } bool WiFiComponent::went_through_explicit_hidden_phase_() const { diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 6e2adcbf04..6488de8dae 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -416,75 +416,65 @@ PROGMEM_STRING_TABLE(OpModeStrings, "OFF", "STA", "AP", "AP+STA", "UNKNOWN"); const LogString *get_op_mode_str(uint8_t mode) { return OpModeStrings::get_log_str(mode, OpModeStrings::LAST_INDEX); } +// Use if-chain instead of switch to avoid jump tables in RODATA (wastes RAM on ESP8266). +// A single switch would generate a sparse lookup table with ~175 default entries, wasting 700 bytes of RAM. +// Even split switches still generate smaller jump tables in RODATA. const LogString *get_disconnect_reason_str(uint8_t reason) { - /* If this were one big switch statement, GCC would generate a lookup table for it. However, the values of the - * REASON_* constants aren't continuous, and GCC will fill in the gap with the default value -- wasting 4 bytes of RAM - * per entry. As there's ~175 default entries, this wastes 700 bytes of RAM. - */ - if (reason <= REASON_CIPHER_SUITE_REJECTED) { // This must be the last constant with a value <200 - switch (reason) { - case REASON_AUTH_EXPIRE: - return LOG_STR("Auth Expired"); - case REASON_AUTH_LEAVE: - return LOG_STR("Auth Leave"); - case REASON_ASSOC_EXPIRE: - return LOG_STR("Association Expired"); - case REASON_ASSOC_TOOMANY: - return LOG_STR("Too Many Associations"); - case REASON_NOT_AUTHED: - return LOG_STR("Not Authenticated"); - case REASON_NOT_ASSOCED: - return LOG_STR("Not Associated"); - case REASON_ASSOC_LEAVE: - return LOG_STR("Association Leave"); - case REASON_ASSOC_NOT_AUTHED: - return LOG_STR("Association not Authenticated"); - case REASON_DISASSOC_PWRCAP_BAD: - return LOG_STR("Disassociate Power Cap Bad"); - case REASON_DISASSOC_SUPCHAN_BAD: - return LOG_STR("Disassociate Supported Channel Bad"); - case REASON_IE_INVALID: - return LOG_STR("IE Invalid"); - case REASON_MIC_FAILURE: - return LOG_STR("Mic Failure"); - case REASON_4WAY_HANDSHAKE_TIMEOUT: - return LOG_STR("4-Way Handshake Timeout"); - case REASON_GROUP_KEY_UPDATE_TIMEOUT: - return LOG_STR("Group Key Update Timeout"); - case REASON_IE_IN_4WAY_DIFFERS: - return LOG_STR("IE In 4-Way Handshake Differs"); - case REASON_GROUP_CIPHER_INVALID: - return LOG_STR("Group Cipher Invalid"); - case REASON_PAIRWISE_CIPHER_INVALID: - return LOG_STR("Pairwise Cipher Invalid"); - case REASON_AKMP_INVALID: - return LOG_STR("AKMP Invalid"); - case REASON_UNSUPP_RSN_IE_VERSION: - return LOG_STR("Unsupported RSN IE version"); - case REASON_INVALID_RSN_IE_CAP: - return LOG_STR("Invalid RSN IE Cap"); - case REASON_802_1X_AUTH_FAILED: - return LOG_STR("802.1x Authentication Failed"); - case REASON_CIPHER_SUITE_REJECTED: - return LOG_STR("Cipher Suite Rejected"); - } - } - - switch (reason) { - case REASON_BEACON_TIMEOUT: - return LOG_STR("Beacon Timeout"); - case REASON_NO_AP_FOUND: - return LOG_STR("AP Not Found"); - case REASON_AUTH_FAIL: - return LOG_STR("Authentication Failed"); - case REASON_ASSOC_FAIL: - return LOG_STR("Association Failed"); - case REASON_HANDSHAKE_TIMEOUT: - return LOG_STR("Handshake Failed"); - case REASON_UNSPECIFIED: - default: - return LOG_STR("Unspecified"); - } + if (reason == REASON_AUTH_EXPIRE) + return LOG_STR("Auth Expired"); + if (reason == REASON_AUTH_LEAVE) + return LOG_STR("Auth Leave"); + if (reason == REASON_ASSOC_EXPIRE) + return LOG_STR("Association Expired"); + if (reason == REASON_ASSOC_TOOMANY) + return LOG_STR("Too Many Associations"); + if (reason == REASON_NOT_AUTHED) + return LOG_STR("Not Authenticated"); + if (reason == REASON_NOT_ASSOCED) + return LOG_STR("Not Associated"); + if (reason == REASON_ASSOC_LEAVE) + return LOG_STR("Association Leave"); + if (reason == REASON_ASSOC_NOT_AUTHED) + return LOG_STR("Association not Authenticated"); + if (reason == REASON_DISASSOC_PWRCAP_BAD) + return LOG_STR("Disassociate Power Cap Bad"); + if (reason == REASON_DISASSOC_SUPCHAN_BAD) + return LOG_STR("Disassociate Supported Channel Bad"); + if (reason == REASON_IE_INVALID) + return LOG_STR("IE Invalid"); + if (reason == REASON_MIC_FAILURE) + return LOG_STR("Mic Failure"); + if (reason == REASON_4WAY_HANDSHAKE_TIMEOUT) + return LOG_STR("4-Way Handshake Timeout"); + if (reason == REASON_GROUP_KEY_UPDATE_TIMEOUT) + return LOG_STR("Group Key Update Timeout"); + if (reason == REASON_IE_IN_4WAY_DIFFERS) + return LOG_STR("IE In 4-Way Handshake Differs"); + if (reason == REASON_GROUP_CIPHER_INVALID) + return LOG_STR("Group Cipher Invalid"); + if (reason == REASON_PAIRWISE_CIPHER_INVALID) + return LOG_STR("Pairwise Cipher Invalid"); + if (reason == REASON_AKMP_INVALID) + return LOG_STR("AKMP Invalid"); + if (reason == REASON_UNSUPP_RSN_IE_VERSION) + return LOG_STR("Unsupported RSN IE version"); + if (reason == REASON_INVALID_RSN_IE_CAP) + return LOG_STR("Invalid RSN IE Cap"); + if (reason == REASON_802_1X_AUTH_FAILED) + return LOG_STR("802.1x Authentication Failed"); + if (reason == REASON_CIPHER_SUITE_REJECTED) + return LOG_STR("Cipher Suite Rejected"); + if (reason == REASON_BEACON_TIMEOUT) + return LOG_STR("Beacon Timeout"); + if (reason == REASON_NO_AP_FOUND) + return LOG_STR("AP Not Found"); + if (reason == REASON_AUTH_FAIL) + return LOG_STR("Authentication Failed"); + if (reason == REASON_ASSOC_FAIL) + return LOG_STR("Association Failed"); + if (reason == REASON_HANDSHAKE_TIMEOUT) + return LOG_STR("Handshake Failed"); + return LOG_STR("Unspecified"); } // TODO: This callback runs in ESP8266 system context with limited stack (~2KB). @@ -645,21 +635,15 @@ void WiFiComponent::wifi_pre_setup_() { WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { station_status_t status = wifi_station_get_connect_status(); - switch (status) { - case STATION_GOT_IP: - return WiFiSTAConnectStatus::CONNECTED; - case STATION_NO_AP_FOUND: - return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; - ; - case STATION_CONNECT_FAIL: - case STATION_WRONG_PASSWORD: - return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; - case STATION_CONNECTING: - return WiFiSTAConnectStatus::CONNECTING; - case STATION_IDLE: - default: - return WiFiSTAConnectStatus::IDLE; - } + if (status == STATION_GOT_IP) + return WiFiSTAConnectStatus::CONNECTED; + if (status == STATION_NO_AP_FOUND) + return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; + if (status == STATION_CONNECT_FAIL || status == STATION_WRONG_PASSWORD) + return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; + if (status == STATION_CONNECTING) + return WiFiSTAConnectStatus::CONNECTING; + return WiFiSTAConnectStatus::IDLE; } bool WiFiComponent::wifi_scan_start_(bool passive) { static bool first_scan = false; From 238e40966f8a373ac634987fd30f871d55f0cf59 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 18:33:26 +0100 Subject: [PATCH 0550/2030] [light] Move CSWTCH lookup table to PROGMEM in get_suitable_color_modes_mask_ (#13801) --- esphome/components/light/light_call.cpp | 88 ++++++++++++++----------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index f4bb0c5d11..3b4e136ba5 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -445,6 +445,52 @@ ColorMode LightCall::compute_color_mode_() { LOG_STR_ARG(color_mode_to_human(color_mode))); return color_mode; } +// PROGMEM lookup table for get_suitable_color_modes_mask_(). +// Maps 4-bit key (white | ct<<1 | cwww<<2 | rgb<<3) to color mode bitmask. +// Packed into uint8_t by right-shifting by PACK_SHIFT since the lower bits +// (UNKNOWN, ON_OFF, BRIGHTNESS) are never present in suitable mode masks. +static constexpr unsigned PACK_SHIFT = ColorModeBitPolicy::to_bit(ColorMode::WHITE); +// clang-format off +static constexpr uint8_t SUITABLE_COLOR_MODES[] PROGMEM = { + // [0] none - all modes with brightness + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE, ColorMode::RGB, ColorMode::WHITE, ColorMode::COLOR_TEMPERATURE, + ColorMode::COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [1] white only + static_cast<uint8_t>(ColorModeMask({ColorMode::WHITE, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [2] ct only + static_cast<uint8_t>(ColorModeMask({ColorMode::COLOR_TEMPERATURE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [3] white + ct + static_cast<uint8_t>(ColorModeMask({ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [4] cwww only + static_cast<uint8_t>(ColorModeMask({ColorMode::COLD_WARM_WHITE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + 0, // [5] white + cwww (conflicting) + 0, // [6] ct + cwww (conflicting) + 0, // [7] white + ct + cwww (conflicting) + // [8] rgb only + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [9] rgb + white + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [10] rgb + ct + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [11] rgb + white + ct + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB_COLOR_TEMPERATURE, + ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + // [12] rgb + cwww + static_cast<uint8_t>(ColorModeMask({ColorMode::RGB_COLD_WARM_WHITE}).get_mask() >> PACK_SHIFT), + 0, // [13] rgb + white + cwww (conflicting) + 0, // [14] rgb + ct + cwww (conflicting) + 0, // [15] all (conflicting) +}; +// clang-format on + color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() { bool has_white = this->has_white() && this->white_ > 0.0f; bool has_ct = this->has_color_temperature(); @@ -454,46 +500,8 @@ color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() { (this->has_red() || this->has_green() || this->has_blue()); // Build key from flags: [rgb][cwww][ct][white] -#define KEY(white, ct, cwww, rgb) ((white) << 0 | (ct) << 1 | (cwww) << 2 | (rgb) << 3) - - uint8_t key = KEY(has_white, has_ct, has_cwww, has_rgb); - - switch (key) { - case KEY(true, false, false, false): // white only - return ColorModeMask({ColorMode::WHITE, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, - ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE}) - .get_mask(); - case KEY(false, true, false, false): // ct only - return ColorModeMask({ColorMode::COLOR_TEMPERATURE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::COLD_WARM_WHITE, - ColorMode::RGB_COLD_WARM_WHITE}) - .get_mask(); - case KEY(true, true, false, false): // white + ct - return ColorModeMask( - {ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE}) - .get_mask(); - case KEY(false, false, true, false): // cwww only - return ColorModeMask({ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE}).get_mask(); - case KEY(false, false, false, false): // none - return ColorModeMask({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE, - ColorMode::RGB, ColorMode::WHITE, ColorMode::COLOR_TEMPERATURE, ColorMode::COLD_WARM_WHITE}) - .get_mask(); - case KEY(true, false, false, true): // rgb + white - return ColorModeMask({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE}) - .get_mask(); - case KEY(false, true, false, true): // rgb + ct - case KEY(true, true, false, true): // rgb + white + ct - return ColorModeMask({ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE}).get_mask(); - case KEY(false, false, true, true): // rgb + cwww - return ColorModeMask({ColorMode::RGB_COLD_WARM_WHITE}).get_mask(); - case KEY(false, false, false, true): // rgb only - return ColorModeMask({ColorMode::RGB, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, - ColorMode::RGB_COLD_WARM_WHITE}) - .get_mask(); - default: - return 0; // conflicting flags - } - -#undef KEY + uint8_t key = has_white | (has_ct << 1) | (has_cwww << 2) | (has_rgb << 3); + return static_cast<color_mode_bitmask_t>(progmem_read_byte(&SUITABLE_COLOR_MODES[key])) << PACK_SHIFT; } LightCall &LightCall::set_effect(const char *effect, size_t len) { From 155447f541b18524ce8a9509e3614c1411c91e6e Mon Sep 17 00:00:00 2001 From: PolarGoose <35307286+PolarGoose@users.noreply.github.com> Date: Fri, 6 Feb 2026 18:53:59 +0100 Subject: [PATCH 0551/2030] [dsmr] Fix issue with parsing lines like `1-0:0.2.0((ER11))` (#13780) --- .clang-tidy.hash | 2 +- esphome/components/dsmr/__init__.py | 2 +- esphome/components/dsmr/sensor.py | 8 -------- esphome/components/dsmr/text_sensor.py | 2 ++ platformio.ini | 2 +- 5 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index ab354259e3..63ddbbac05 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -069fa9526c52f7c580a9ec17c7678d12f142221387e9b561c18f95394d4629a3 +37ec8d5a343c8d0a485fd2118cbdabcbccd7b9bca197e4a392be75087974dced diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index 386da3ce21..7d76856f28 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -66,7 +66,7 @@ async def to_code(config): cg.add_build_flag("-DDSMR_WATER_MBUS_ID=" + str(config[CONF_WATER_MBUS_ID])) # DSMR Parser - cg.add_library("esphome/dsmr_parser", "1.0.0") + cg.add_library("esphome/dsmr_parser", "1.1.0") # Crypto cg.add_library("polargoose/Crypto-no-arduino", "0.4.0") diff --git a/esphome/components/dsmr/sensor.py b/esphome/components/dsmr/sensor.py index 7d69f79530..863af42d1b 100644 --- a/esphome/components/dsmr/sensor.py +++ b/esphome/components/dsmr/sensor.py @@ -718,14 +718,6 @@ CONFIG_SCHEMA = cv.Schema( device_class=DEVICE_CLASS_POWER, state_class=STATE_CLASS_MEASUREMENT, ), - cv.Optional("fw_core_version"): sensor.sensor_schema( - accuracy_decimals=3, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional("fw_module_version"): sensor.sensor_schema( - accuracy_decimals=3, - state_class=STATE_CLASS_MEASUREMENT, - ), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/dsmr/text_sensor.py b/esphome/components/dsmr/text_sensor.py index 4c7455a38f..203c9c997e 100644 --- a/esphome/components/dsmr/text_sensor.py +++ b/esphome/components/dsmr/text_sensor.py @@ -26,7 +26,9 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional("sub_equipment_id"): text_sensor.text_sensor_schema(), cv.Optional("gas_delivered_text"): text_sensor.text_sensor_schema(), cv.Optional("fw_core_checksum"): text_sensor.text_sensor_schema(), + cv.Optional("fw_core_version"): text_sensor.text_sensor_schema(), cv.Optional("fw_module_checksum"): text_sensor.text_sensor_schema(), + cv.Optional("fw_module_version"): text_sensor.text_sensor_schema(), cv.Optional("telegram"): text_sensor.text_sensor_schema().extend( {cv.Optional(CONF_INTERNAL, default=True): cv.boolean} ), diff --git a/platformio.ini b/platformio.ini index bb0de3c2b1..d198862a25 100644 --- a/platformio.ini +++ b/platformio.ini @@ -37,7 +37,7 @@ lib_deps_base = wjtje/qr-code-generator-library@1.7.0 ; qr_code functionpointer/arduino-MLX90393@1.0.2 ; mlx90393 pavlodn/HaierProtocol@0.9.31 ; haier - esphome/dsmr_parser@1.0.0 ; dsmr + esphome/dsmr_parser@1.1.0 ; dsmr polargoose/Crypto-no-arduino@0.4.0 ; dsmr https://github.com/esphome/TinyGPSPlus.git#v1.1.0 ; gps ; This is using the repository until a new release is published to PlatformIO From 9315da79bc016c5b45ba93ca85a2c257b89d559c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Feb 2026 13:03:16 -0500 Subject: [PATCH 0552/2030] [core] Add missing requests dependency to requirements.txt (#13803) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index bb118c5f9a..1771867535 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,6 +23,7 @@ resvg-py==0.2.6 freetype-py==2.5.1 jinja2==3.1.6 bleak==2.1.1 +requests==2.32.5 # esp-idf >= 5.0 requires this pyparsing >= 3.0 From 41cecbfb0f62db7e6dffff709e34141a06e59f7f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 19:22:26 +0100 Subject: [PATCH 0553/2030] [template] Convert alarm sensor type to PROGMEM_STRING_TABLE and narrow enum to uint8_t (#13804) --- .../template_alarm_control_panel.cpp | 16 +++++----------- .../template_alarm_control_panel.h | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp index 1a5aef6b8d..09efe678ce 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp @@ -5,6 +5,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome::template_ { @@ -28,18 +29,11 @@ void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor, this->sensor_data_.push_back(sd); }; +// Alarm sensor type strings indexed by AlarmSensorType enum (0-3): DELAYED, INSTANT, DELAYED_FOLLOWER, INSTANT_ALWAYS +PROGMEM_STRING_TABLE(AlarmSensorTypeStrings, "delayed", "instant", "delayed_follower", "instant_always"); + static const LogString *sensor_type_to_string(AlarmSensorType type) { - switch (type) { - case ALARM_SENSOR_TYPE_INSTANT: - return LOG_STR("instant"); - case ALARM_SENSOR_TYPE_DELAYED_FOLLOWER: - return LOG_STR("delayed_follower"); - case ALARM_SENSOR_TYPE_INSTANT_ALWAYS: - return LOG_STR("instant_always"); - case ALARM_SENSOR_TYPE_DELAYED: - default: - return LOG_STR("delayed"); - } + return AlarmSensorTypeStrings::get_log_str(static_cast<uint8_t>(type), 0); } #endif diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h index df3b64fb6e..4f32e99fd7 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h @@ -26,7 +26,7 @@ enum BinarySensorFlags : uint16_t { BINARY_SENSOR_MODE_BYPASS_AUTO = 1 << 4, }; -enum AlarmSensorType : uint16_t { +enum AlarmSensorType : uint8_t { ALARM_SENSOR_TYPE_DELAYED = 0, ALARM_SENSOR_TYPE_INSTANT, ALARM_SENSOR_TYPE_DELAYED_FOLLOWER, From 86f91eed2f69a7cdb7789fb4927d560a7133e890 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Feb 2026 19:30:05 +0100 Subject: [PATCH 0554/2030] [mqtt] Move switch string tables to PROGMEM_STRING_TABLE (#13802) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../mqtt/mqtt_alarm_control_panel.cpp | 29 +---- esphome/components/mqtt/mqtt_client.cpp | 38 ++---- esphome/components/mqtt/mqtt_climate.cpp | 115 ++++-------------- esphome/components/mqtt/mqtt_component.cpp | 13 +- esphome/components/mqtt/mqtt_number.cpp | 17 ++- esphome/components/mqtt/mqtt_text.cpp | 14 +-- 6 files changed, 58 insertions(+), 168 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index dc8f75d8f5..a461a140ae 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -13,31 +13,12 @@ static const char *const TAG = "mqtt.alarm_control_panel"; using namespace esphome::alarm_control_panel; +// Alarm state MQTT strings indexed by AlarmControlPanelState enum (0-9) +PROGMEM_STRING_TABLE(AlarmMqttStateStrings, "disarmed", "armed_home", "armed_away", "armed_night", "armed_vacation", + "armed_custom_bypass", "pending", "arming", "disarming", "triggered", "unknown"); + static ProgmemStr alarm_state_to_mqtt_str(AlarmControlPanelState state) { - switch (state) { - case ACP_STATE_DISARMED: - return ESPHOME_F("disarmed"); - case ACP_STATE_ARMED_HOME: - return ESPHOME_F("armed_home"); - case ACP_STATE_ARMED_AWAY: - return ESPHOME_F("armed_away"); - case ACP_STATE_ARMED_NIGHT: - return ESPHOME_F("armed_night"); - case ACP_STATE_ARMED_VACATION: - return ESPHOME_F("armed_vacation"); - case ACP_STATE_ARMED_CUSTOM_BYPASS: - return ESPHOME_F("armed_custom_bypass"); - case ACP_STATE_PENDING: - return ESPHOME_F("pending"); - case ACP_STATE_ARMING: - return ESPHOME_F("arming"); - case ACP_STATE_DISARMING: - return ESPHOME_F("disarming"); - case ACP_STATE_TRIGGERED: - return ESPHOME_F("triggered"); - default: - return ESPHOME_F("unknown"); - } + return AlarmMqttStateStrings::get_progmem_str(static_cast<uint8_t>(state), AlarmMqttStateStrings::LAST_INDEX); } MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index a284b162dd..d503461257 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -8,6 +8,7 @@ #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "esphome/core/version.h" #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" @@ -27,6 +28,11 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt"; +// Disconnect reason strings indexed by MQTTClientDisconnectReason enum (0-8) +PROGMEM_STRING_TABLE(MQTTDisconnectReasonStrings, "TCP disconnected", "Unacceptable Protocol Version", + "Identifier Rejected", "Server Unavailable", "Malformed Credentials", "Not Authorized", + "Not Enough Space", "TLS Bad Fingerprint", "DNS Resolve Error", "Unknown"); + MQTTClientComponent::MQTTClientComponent() { global_mqtt_client = this; char mac_addr[MAC_ADDRESS_BUFFER_SIZE]; @@ -348,36 +354,8 @@ void MQTTClientComponent::loop() { mqtt_backend_.loop(); if (this->disconnect_reason_.has_value()) { - const LogString *reason_s; - switch (*this->disconnect_reason_) { - case MQTTClientDisconnectReason::TCP_DISCONNECTED: - reason_s = LOG_STR("TCP disconnected"); - break; - case MQTTClientDisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION: - reason_s = LOG_STR("Unacceptable Protocol Version"); - break; - case MQTTClientDisconnectReason::MQTT_IDENTIFIER_REJECTED: - reason_s = LOG_STR("Identifier Rejected"); - break; - case MQTTClientDisconnectReason::MQTT_SERVER_UNAVAILABLE: - reason_s = LOG_STR("Server Unavailable"); - break; - case MQTTClientDisconnectReason::MQTT_MALFORMED_CREDENTIALS: - reason_s = LOG_STR("Malformed Credentials"); - break; - case MQTTClientDisconnectReason::MQTT_NOT_AUTHORIZED: - reason_s = LOG_STR("Not Authorized"); - break; - case MQTTClientDisconnectReason::ESP8266_NOT_ENOUGH_SPACE: - reason_s = LOG_STR("Not Enough Space"); - break; - case MQTTClientDisconnectReason::TLS_BAD_FINGERPRINT: - reason_s = LOG_STR("TLS Bad Fingerprint"); - break; - default: - reason_s = LOG_STR("Unknown"); - break; - } + const LogString *reason_s = MQTTDisconnectReasonStrings::get_log_str( + static_cast<uint8_t>(*this->disconnect_reason_), MQTTDisconnectReasonStrings::LAST_INDEX); if (!network::is_connected()) { reason_s = LOG_STR("WiFi disconnected"); } diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 673593ef84..158cfb5552 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -13,109 +13,44 @@ static const char *const TAG = "mqtt.climate"; using namespace esphome::climate; +// Climate mode MQTT strings indexed by ClimateMode enum (0-6): OFF, HEAT_COOL, COOL, HEAT, FAN_ONLY, DRY, AUTO +PROGMEM_STRING_TABLE(ClimateMqttModeStrings, "off", "heat_cool", "cool", "heat", "fan_only", "dry", "auto", "unknown"); + static ProgmemStr climate_mode_to_mqtt_str(ClimateMode mode) { - switch (mode) { - case CLIMATE_MODE_OFF: - return ESPHOME_F("off"); - case CLIMATE_MODE_HEAT_COOL: - return ESPHOME_F("heat_cool"); - case CLIMATE_MODE_AUTO: - return ESPHOME_F("auto"); - case CLIMATE_MODE_COOL: - return ESPHOME_F("cool"); - case CLIMATE_MODE_HEAT: - return ESPHOME_F("heat"); - case CLIMATE_MODE_FAN_ONLY: - return ESPHOME_F("fan_only"); - case CLIMATE_MODE_DRY: - return ESPHOME_F("dry"); - default: - return ESPHOME_F("unknown"); - } + return ClimateMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), ClimateMqttModeStrings::LAST_INDEX); } +// Climate action MQTT strings indexed by ClimateAction enum (0,2-6): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN +PROGMEM_STRING_TABLE(ClimateMqttActionStrings, "off", "unknown", "cooling", "heating", "idle", "drying", "fan", + "unknown"); + static ProgmemStr climate_action_to_mqtt_str(ClimateAction action) { - switch (action) { - case CLIMATE_ACTION_OFF: - return ESPHOME_F("off"); - case CLIMATE_ACTION_COOLING: - return ESPHOME_F("cooling"); - case CLIMATE_ACTION_HEATING: - return ESPHOME_F("heating"); - case CLIMATE_ACTION_IDLE: - return ESPHOME_F("idle"); - case CLIMATE_ACTION_DRYING: - return ESPHOME_F("drying"); - case CLIMATE_ACTION_FAN: - return ESPHOME_F("fan"); - default: - return ESPHOME_F("unknown"); - } + return ClimateMqttActionStrings::get_progmem_str(static_cast<uint8_t>(action), ClimateMqttActionStrings::LAST_INDEX); } +// Climate fan mode MQTT strings indexed by ClimateFanMode enum (0-9) +PROGMEM_STRING_TABLE(ClimateMqttFanModeStrings, "on", "off", "auto", "low", "medium", "high", "middle", "focus", + "diffuse", "quiet", "unknown"); + static ProgmemStr climate_fan_mode_to_mqtt_str(ClimateFanMode fan_mode) { - switch (fan_mode) { - case CLIMATE_FAN_ON: - return ESPHOME_F("on"); - case CLIMATE_FAN_OFF: - return ESPHOME_F("off"); - case CLIMATE_FAN_AUTO: - return ESPHOME_F("auto"); - case CLIMATE_FAN_LOW: - return ESPHOME_F("low"); - case CLIMATE_FAN_MEDIUM: - return ESPHOME_F("medium"); - case CLIMATE_FAN_HIGH: - return ESPHOME_F("high"); - case CLIMATE_FAN_MIDDLE: - return ESPHOME_F("middle"); - case CLIMATE_FAN_FOCUS: - return ESPHOME_F("focus"); - case CLIMATE_FAN_DIFFUSE: - return ESPHOME_F("diffuse"); - case CLIMATE_FAN_QUIET: - return ESPHOME_F("quiet"); - default: - return ESPHOME_F("unknown"); - } + return ClimateMqttFanModeStrings::get_progmem_str(static_cast<uint8_t>(fan_mode), + ClimateMqttFanModeStrings::LAST_INDEX); } +// Climate swing mode MQTT strings indexed by ClimateSwingMode enum (0-3): OFF, BOTH, VERTICAL, HORIZONTAL +PROGMEM_STRING_TABLE(ClimateMqttSwingModeStrings, "off", "both", "vertical", "horizontal", "unknown"); + static ProgmemStr climate_swing_mode_to_mqtt_str(ClimateSwingMode swing_mode) { - switch (swing_mode) { - case CLIMATE_SWING_OFF: - return ESPHOME_F("off"); - case CLIMATE_SWING_BOTH: - return ESPHOME_F("both"); - case CLIMATE_SWING_VERTICAL: - return ESPHOME_F("vertical"); - case CLIMATE_SWING_HORIZONTAL: - return ESPHOME_F("horizontal"); - default: - return ESPHOME_F("unknown"); - } + return ClimateMqttSwingModeStrings::get_progmem_str(static_cast<uint8_t>(swing_mode), + ClimateMqttSwingModeStrings::LAST_INDEX); } +// Climate preset MQTT strings indexed by ClimatePreset enum (0-7) +PROGMEM_STRING_TABLE(ClimateMqttPresetStrings, "none", "home", "away", "boost", "comfort", "eco", "sleep", "activity", + "unknown"); + static ProgmemStr climate_preset_to_mqtt_str(ClimatePreset preset) { - switch (preset) { - case CLIMATE_PRESET_NONE: - return ESPHOME_F("none"); - case CLIMATE_PRESET_HOME: - return ESPHOME_F("home"); - case CLIMATE_PRESET_ECO: - return ESPHOME_F("eco"); - case CLIMATE_PRESET_AWAY: - return ESPHOME_F("away"); - case CLIMATE_PRESET_BOOST: - return ESPHOME_F("boost"); - case CLIMATE_PRESET_COMFORT: - return ESPHOME_F("comfort"); - case CLIMATE_PRESET_SLEEP: - return ESPHOME_F("sleep"); - case CLIMATE_PRESET_ACTIVITY: - return ESPHOME_F("activity"); - default: - return ESPHOME_F("unknown"); - } + return ClimateMqttPresetStrings::get_progmem_str(static_cast<uint8_t>(preset), ClimateMqttPresetStrings::LAST_INDEX); } void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index a77afd3f4e..e4b80de50a 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -14,6 +14,9 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt.component"; +// Entity category MQTT strings indexed by EntityCategory enum: NONE(0) is skipped, CONFIG(1), DIAGNOSTIC(2) +PROGMEM_STRING_TABLE(EntityCategoryMqttStrings, "", "config", "diagnostic"); + // Helper functions for building topic strings on stack inline char *append_str(char *p, const char *s, size_t len) { memcpy(p, s, len); @@ -213,13 +216,9 @@ bool MQTTComponent::send_discovery_() { // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) const auto entity_category = this->get_entity()->get_entity_category(); - switch (entity_category) { - case ENTITY_CATEGORY_NONE: - break; - case ENTITY_CATEGORY_CONFIG: - case ENTITY_CATEGORY_DIAGNOSTIC: - root[MQTT_ENTITY_CATEGORY] = entity_category == ENTITY_CATEGORY_CONFIG ? "config" : "diagnostic"; - break; + if (entity_category != ENTITY_CATEGORY_NONE) { + root[MQTT_ENTITY_CATEGORY] = EntityCategoryMqttStrings::get_progmem_str( + static_cast<uint8_t>(entity_category), static_cast<uint8_t>(ENTITY_CATEGORY_CONFIG)); } if (config.state_topic) { diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index 7dc93eee0c..fdc909fcc9 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -1,5 +1,6 @@ #include "mqtt_number.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,9 @@ static const char *const TAG = "mqtt.number"; using namespace esphome::number; +// Number mode MQTT strings indexed by NumberMode enum: AUTO(0) is skipped, BOX(1), SLIDER(2) +PROGMEM_STRING_TABLE(NumberMqttModeStrings, "", "box", "slider"); + MQTTNumberComponent::MQTTNumberComponent(Number *number) : number_(number) {} void MQTTNumberComponent::setup() { @@ -48,15 +52,10 @@ void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon if (!unit_of_measurement.empty()) { root[MQTT_UNIT_OF_MEASUREMENT] = unit_of_measurement; } - switch (this->number_->traits.get_mode()) { - case NUMBER_MODE_AUTO: - break; - case NUMBER_MODE_BOX: - root[MQTT_MODE] = "box"; - break; - case NUMBER_MODE_SLIDER: - root[MQTT_MODE] = "slider"; - break; + const auto mode = this->number_->traits.get_mode(); + if (mode != NUMBER_MODE_AUTO) { + root[MQTT_MODE] = + NumberMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), static_cast<uint8_t>(NUMBER_MODE_BOX)); } const auto device_class = this->number_->traits.get_device_class_ref(); if (!device_class.empty()) { diff --git a/esphome/components/mqtt/mqtt_text.cpp b/esphome/components/mqtt/mqtt_text.cpp index 16293c0603..200e420c9c 100644 --- a/esphome/components/mqtt/mqtt_text.cpp +++ b/esphome/components/mqtt/mqtt_text.cpp @@ -1,5 +1,6 @@ #include "mqtt_text.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "mqtt_const.h" @@ -12,6 +13,9 @@ static const char *const TAG = "mqtt.text"; using namespace esphome::text; +// Text mode MQTT strings indexed by TextMode enum (0-1): TEXT, PASSWORD +PROGMEM_STRING_TABLE(TextMqttModeStrings, "text", "password"); + MQTTTextComponent::MQTTTextComponent(Text *text) : text_(text) {} void MQTTTextComponent::setup() { @@ -34,14 +38,8 @@ const EntityBase *MQTTTextComponent::get_entity() const { return this->text_; } void MQTTTextComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - switch (this->text_->traits.get_mode()) { - case TEXT_MODE_TEXT: - root[MQTT_MODE] = "text"; - break; - case TEXT_MODE_PASSWORD: - root[MQTT_MODE] = "password"; - break; - } + root[MQTT_MODE] = TextMqttModeStrings::get_progmem_str(static_cast<uint8_t>(this->text_->traits.get_mode()), + static_cast<uint8_t>(TEXT_MODE_TEXT)); config.command_topic = true; } From eb7aa3420fcf0d649953a0ce6c8643c0a2357e31 Mon Sep 17 00:00:00 2001 From: tronikos <tronikos@users.noreply.github.com> Date: Fri, 6 Feb 2026 12:23:42 -0800 Subject: [PATCH 0555/2030] Add target_temperature to the template water heater (#13661) Co-authored-by: J. Nick Koston <nick@koston.org> --- .../components/template/water_heater/__init__.py | 9 +++++++++ .../water_heater/template_water_heater.cpp | 14 +++++++++++++- .../template/water_heater/template_water_heater.h | 4 ++++ tests/components/template/common-base.yaml | 1 + .../fixtures/water_heater_template.yaml | 1 + tests/integration/test_water_heater_template.py | 3 +++ 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/esphome/components/template/water_heater/__init__.py b/esphome/components/template/water_heater/__init__.py index bddd378b23..5f96155fbf 100644 --- a/esphome/components/template/water_heater/__init__.py +++ b/esphome/components/template/water_heater/__init__.py @@ -46,6 +46,7 @@ CONFIG_SCHEMA = ( RESTORE_MODES, upper=True ), cv.Optional(CONF_CURRENT_TEMPERATURE): cv.returning_lambda, + cv.Optional(CONF_TARGET_TEMPERATURE): cv.returning_lambda, cv.Optional(CONF_MODE): cv.returning_lambda, cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list( water_heater.validate_water_heater_mode @@ -78,6 +79,14 @@ async def to_code(config: ConfigType) -> None: ) cg.add(var.set_current_temperature_lambda(template_)) + if CONF_TARGET_TEMPERATURE in config: + template_ = await cg.process_lambda( + config[CONF_TARGET_TEMPERATURE], + [], + return_type=cg.optional.template(cg.float_), + ) + cg.add(var.set_target_temperature_lambda(template_)) + if CONF_MODE in config: template_ = await cg.process_lambda( config[CONF_MODE], diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index f888edb1df..c354deee0e 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -16,7 +16,8 @@ void TemplateWaterHeater::setup() { restore->perform(); } } - if (!this->current_temperature_f_.has_value() && !this->mode_f_.has_value()) + if (!this->current_temperature_f_.has_value() && !this->target_temperature_f_.has_value() && + !this->mode_f_.has_value()) this->disable_loop(); } @@ -28,6 +29,9 @@ water_heater::WaterHeaterTraits TemplateWaterHeater::traits() { } traits.set_supports_current_temperature(true); + if (this->target_temperature_f_.has_value()) { + traits.add_feature_flags(water_heater::WATER_HEATER_SUPPORTS_TARGET_TEMPERATURE); + } return traits; } @@ -42,6 +46,14 @@ void TemplateWaterHeater::loop() { } } + auto target_temp = this->target_temperature_f_.call(); + if (target_temp.has_value()) { + if (*target_temp != this->target_temperature_) { + this->target_temperature_ = *target_temp; + changed = true; + } + } + auto new_mode = this->mode_f_.call(); if (new_mode.has_value()) { if (*new_mode != this->mode_) { diff --git a/esphome/components/template/water_heater/template_water_heater.h b/esphome/components/template/water_heater/template_water_heater.h index f1cf00a115..22173209aa 100644 --- a/esphome/components/template/water_heater/template_water_heater.h +++ b/esphome/components/template/water_heater/template_water_heater.h @@ -20,6 +20,9 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { template<typename F> void set_current_temperature_lambda(F &&f) { this->current_temperature_f_.set(std::forward<F>(f)); } + template<typename F> void set_target_temperature_lambda(F &&f) { + this->target_temperature_f_.set(std::forward<F>(f)); + } template<typename F> void set_mode_lambda(F &&f) { this->mode_f_.set(std::forward<F>(f)); } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } @@ -44,6 +47,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { // Ordered to minimize padding on 32-bit: 4-byte members first, then smaller Trigger<> set_trigger_; TemplateLambda<float> current_temperature_f_; + TemplateLambda<float> target_temperature_f_; TemplateLambda<water_heater::WaterHeaterMode> mode_f_; TemplateWaterHeaterRestoreMode restore_mode_{WATER_HEATER_NO_RESTORE}; water_heater::WaterHeaterModeMask supported_modes_; diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index d1849efaf7..b8742f8c7b 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -412,6 +412,7 @@ water_heater: name: "Template Water Heater" optimistic: true current_temperature: !lambda "return 42.0f;" + target_temperature: !lambda "return 60.0f;" mode: !lambda "return water_heater::WATER_HEATER_MODE_ECO;" supported_modes: - "OFF" diff --git a/tests/integration/fixtures/water_heater_template.yaml b/tests/integration/fixtures/water_heater_template.yaml index b54ebed789..1aaded1991 100644 --- a/tests/integration/fixtures/water_heater_template.yaml +++ b/tests/integration/fixtures/water_heater_template.yaml @@ -10,6 +10,7 @@ water_heater: name: Test Boiler optimistic: true current_temperature: !lambda "return 45.0f;" + target_temperature: !lambda "return 60.0f;" # Note: No mode lambda - we want optimistic mode changes to stick # A mode lambda would override mode changes in loop() supported_modes: diff --git a/tests/integration/test_water_heater_template.py b/tests/integration/test_water_heater_template.py index b5f1fb64c0..6b4a685d0d 100644 --- a/tests/integration/test_water_heater_template.py +++ b/tests/integration/test_water_heater_template.py @@ -85,6 +85,9 @@ async def test_water_heater_template( assert initial_state.current_temperature == 45.0, ( f"Expected current temp 45.0, got {initial_state.current_temperature}" ) + assert initial_state.target_temperature == 60.0, ( + f"Expected target temp 60.0, got {initial_state.target_temperature}" + ) # Test changing to GAS mode client.water_heater_command(test_water_heater.key, mode=WaterHeaterMode.GAS) From 9de91539e6d1990593400db003ad05a7c55795d3 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:24:57 +0100 Subject: [PATCH 0556/2030] [epaper_spi] Add Waveshare 1.54-G (#13758) --- esphome/components/epaper_spi/colorconv.h | 67 ++++++ .../epaper_spi/epaper_spi_jd79660.cpp | 227 ++++++++++++++++++ .../epaper_spi/epaper_spi_jd79660.h | 145 +++++++++++ .../components/epaper_spi/models/jd79660.py | 86 +++++++ .../epaper_spi/test.esp32-s3-idf.yaml | 16 ++ 5 files changed, 541 insertions(+) create mode 100644 esphome/components/epaper_spi/colorconv.h create mode 100644 esphome/components/epaper_spi/epaper_spi_jd79660.cpp create mode 100644 esphome/components/epaper_spi/epaper_spi_jd79660.h create mode 100644 esphome/components/epaper_spi/models/jd79660.py diff --git a/esphome/components/epaper_spi/colorconv.h b/esphome/components/epaper_spi/colorconv.h new file mode 100644 index 0000000000..a2ea28f4b6 --- /dev/null +++ b/esphome/components/epaper_spi/colorconv.h @@ -0,0 +1,67 @@ +#pragma once + +#include <cstdint> +#include <algorithm> +#include "esphome/core/color.h" + +/* Utility for converting internal \a Color RGB representation to supported IC hardware color keys + * + * Focus in driver layer is on efficiency. + * For optimum output quality on RGB inputs consider offline color keying/dithering. + * Also see e.g. Image component. + */ + +namespace esphome::epaper_spi { + +/** Delta for when to regard as gray */ +static constexpr uint8_t COLORCONV_GRAY_THRESHOLD = 50; + +/** Map RGB color to discrete BWYR hex 4 color key + * + * @tparam NATIVE_COLOR Type of native hardware color values + * @param color RGB color to convert from + * @param hw_black Native value for black + * @param hw_white Native value for white + * @param hw_yellow Native value for yellow + * @param hw_red Native value for red + * @return Converted native hardware color value + * @internal Constexpr. Does not depend on side effects ("pure"). + */ +template<typename NATIVE_COLOR> +constexpr NATIVE_COLOR color_to_bwyr(Color color, NATIVE_COLOR hw_black, NATIVE_COLOR hw_white, NATIVE_COLOR hw_yellow, + NATIVE_COLOR hw_red) { + // --- Step 1: Check for Grayscale (Black or White) --- + // We define "grayscale" as a color where the min and max components + // are close to each other. + + const auto [min_rgb, max_rgb] = std::minmax({color.r, color.g, color.b}); + + if ((max_rgb - min_rgb) < COLORCONV_GRAY_THRESHOLD) { + // It's a shade of gray. Map to BLACK or WHITE. + // We split the luminance at the halfway point (382 = (255*3)/2) + if ((static_cast<int>(color.r) + color.g + color.b) > 382) { + return hw_white; + } + return hw_black; + } + + // --- Step 2: Check for Primary/Secondary Colors --- + // If it's not gray, it's a color. We check which components are + // "on" (over 128) vs "off". This divides the RGB cube into 8 corners. + const bool r_on = (color.r > 128); + const bool g_on = (color.g > 128); + const bool b_on = (color.b > 128); + + if (r_on) { + if (!b_on) { + return g_on ? hw_yellow : hw_red; + } + + // At least red+blue high (but not gray) -> White + return hw_white; + } else { + return (b_on && g_on) ? hw_white : hw_black; + } +} + +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/epaper_spi_jd79660.cpp b/esphome/components/epaper_spi/epaper_spi_jd79660.cpp new file mode 100644 index 0000000000..1cd1087c6b --- /dev/null +++ b/esphome/components/epaper_spi/epaper_spi_jd79660.cpp @@ -0,0 +1,227 @@ +#include "epaper_spi_jd79660.h" +#include "colorconv.h" + +#include "esphome/core/log.h" + +namespace esphome::epaper_spi { +static constexpr const char *const TAG = "epaper_spi.jd79660"; + +/** Pixel color as 2bpp. Must match IC LUT values. */ +enum JD79660Color : uint8_t { + BLACK = 0b00, + WHITE = 0b01, + YELLOW = 0b10, + RED = 0b11, +}; + +/** Map RGB color to JD79660 BWYR hex color keys */ +static JD79660Color HOT color_to_hex(Color color) { + return color_to_bwyr(color, JD79660Color::BLACK, JD79660Color::WHITE, JD79660Color::YELLOW, JD79660Color::RED); +} + +void EPaperJD79660::fill(Color color) { + // If clipping is active, fall back to base implementation + if (this->get_clipping().is_set()) { + EPaperBase::fill(color); + return; + } + + const auto pixel_color = color_to_hex(color); + + // We store 4 pixels per byte + this->buffer_.fill(pixel_color | (pixel_color << 2) | (pixel_color << 4) | (pixel_color << 6)); +} + +void HOT EPaperJD79660::draw_pixel_at(int x, int y, Color color) { + if (!this->rotate_coordinates_(x, y)) + return; + const auto pixel_bits = color_to_hex(color); + const uint32_t pixel_position = x + y * this->get_width_internal(); + // We store 4 pixels per byte at LSB offsets 6, 4, 2, 0 + const uint32_t byte_position = pixel_position / 4; + const uint32_t bit_offset = 6 - ((pixel_position % 4) * 2); + const auto original = this->buffer_[byte_position]; + + this->buffer_[byte_position] = (original & (~(0b11 << bit_offset))) | // mask old 2bpp + (pixel_bits << bit_offset); // add new 2bpp +} + +bool EPaperJD79660::reset() { + // On entry state RESET set step, next state will be RESET_END + if (this->state_ == EPaperState::RESET) { + this->step_ = FSMState::RESET_STEP0_H; + } + + switch (this->step_) { + case FSMState::RESET_STEP0_H: + // Step #0: Reset H for some settle time. + + ESP_LOGVV(TAG, "reset #0"); + this->reset_pin_->digital_write(true); + + this->reset_duration_ = SLEEP_MS_RESET0; + this->step_ = FSMState::RESET_STEP1_L; + return false; // another loop: step #1 below + + case FSMState::RESET_STEP1_L: + // Step #1: Reset L pulse for slightly >1.5ms. + // This is actual reset trigger. + + ESP_LOGVV(TAG, "reset #1"); + + // As commented on SLEEP_MS_RESET1: Reset pulse must happen within time window. + // So do not use FSM loop, and avoid other calls/logs during pulse below. + this->reset_pin_->digital_write(false); + delay(SLEEP_MS_RESET1); + this->reset_pin_->digital_write(true); + + this->reset_duration_ = SLEEP_MS_RESET2; + this->step_ = FSMState::RESET_STEP2_IDLECHECK; + return false; // another loop: step #2 below + + case FSMState::RESET_STEP2_IDLECHECK: + // Step #2: Basically finished. Check sanity, and move FSM to INITIALISE state + ESP_LOGVV(TAG, "reset #2"); + + if (!this->is_idle_()) { + // Expectation: Idle after reset + settle time. + // Improperly connected/unexpected hardware? + // Error path reproducable e.g. with disconnected VDD/... pins + // (optimally while busy_pin configured with local pulldown). + // -> Mark failed to avoid followup problems. + this->mark_failed(LOG_STR("Busy after reset")); + } + break; // End state loop below + + default: + // Unexpected step = bug? + this->mark_failed(); + } + + this->step_ = FSMState::INIT_STEP0_REGULARINIT; // reset for initialize state + return true; +} + +bool EPaperJD79660::initialise(bool partial) { + switch (this->step_) { + case FSMState::INIT_STEP0_REGULARINIT: + // Step #0: Regular init sequence + ESP_LOGVV(TAG, "init #0"); + if (!EPaperBase::initialise(partial)) { // Call parent impl + return false; // If parent should request another loop, do so + } + + // Fast init requested + supported? + if (partial && (this->fast_update_length_ > 0)) { + this->step_ = FSMState::INIT_STEP1_FASTINIT; + this->wait_for_idle_(true); // Must wait for idle before fastinit sequence in next loop + return false; // another loop: step #1 below + } + + break; // End state loop below + + case FSMState::INIT_STEP1_FASTINIT: + // Step #1: Fast init sequence + ESP_LOGVV(TAG, "init #1"); + this->write_fastinit_(); + break; // End state loop below + + default: + // Unexpected step = bug? + this->mark_failed(); + } + + this->step_ = FSMState::NONE; + return true; // Finished: State transition waits for idle +} + +bool EPaperJD79660::transfer_buffer_chunks_() { + size_t buf_idx = 0; + uint8_t bytes_to_send[MAX_TRANSFER_SIZE]; + const uint32_t start_time = App.get_loop_component_start_time(); + const auto buffer_length = this->buffer_length_; + while (this->current_data_index_ != buffer_length) { + bytes_to_send[buf_idx++] = this->buffer_[this->current_data_index_++]; + + if (buf_idx == sizeof bytes_to_send) { + this->start_data_(); + this->write_array(bytes_to_send, buf_idx); + this->disable(); + ESP_LOGVV(TAG, "Wrote %zu bytes at %ums", buf_idx, (unsigned) millis()); + buf_idx = 0; + + if (millis() - start_time > MAX_TRANSFER_TIME) { + // Let the main loop run and come back next loop + return false; + } + } + } + + // Finished the entire dataset + if (buf_idx != 0) { + this->start_data_(); + this->write_array(bytes_to_send, buf_idx); + this->disable(); + ESP_LOGVV(TAG, "Wrote %zu bytes at %ums", buf_idx, (unsigned) millis()); + } + // Cleanup for next transfer + this->current_data_index_ = 0; + + // Finished with all buffer chunks + return true; +} + +void EPaperJD79660::write_fastinit_() { + // Undocumented register sequence in vendor register range. + // Related to Fast Init/Update. + // Should likely happen after regular init seq and power on, but before refresh. + // Might only work for some models with certain factory MTP. + // Please do not change without knowledge to avoid breakage. + + this->send_init_sequence_(this->fast_update_, this->fast_update_length_); +} + +bool EPaperJD79660::transfer_data() { + // For now always send full frame buffer in chunks. + // JD79660 might support partial window transfers. But sample code missing. + // And likely minimal impact, solely on SPI transfer time into RAM. + + if (this->current_data_index_ == 0) { + this->command(CMD_TRANSFER); + } + + return this->transfer_buffer_chunks_(); +} + +void EPaperJD79660::refresh_screen([[maybe_unused]] bool partial) { + ESP_LOGV(TAG, "Refresh"); + this->cmd_data(CMD_REFRESH, {(uint8_t) 0x00}); +} + +void EPaperJD79660::power_off() { + ESP_LOGV(TAG, "Power off"); + this->cmd_data(CMD_POWEROFF, {(uint8_t) 0x00}); +} + +void EPaperJD79660::deep_sleep() { + ESP_LOGV(TAG, "Deep sleep"); + // "Deepsleep between update": Ensure EPD sleep to avoid early hardware wearout! + this->cmd_data(CMD_DEEPSLEEP, {(uint8_t) 0xA5}); + + // Notes: + // - VDD: Some boards (Waveshare) with "clever reset logic" would allow switching off + // EPD VDD by pulling reset pin low for longer time. + // However, a) not all boards have this, b) reliable sequence timing is difficult, + // c) saving is not worth it after deepsleep command above. + // If needed: Better option is to drive VDD via MOSFET with separate enable pin. + // + // - Possible safe shutdown: + // EPaperBase::on_safe_shutdown() may also trigger deep_sleep() again. + // Regularly, in IDLE state, this does not make sense for this "deepsleep between update" model, + // but SPI sequence should simply be ignored by sleeping receiver. + // But if triggering during lengthy update, this quick SPI sleep sequence may have benefit. + // Optimally, EPDs should even be set all white for longer storage. + // But full sequence (>15s) not possible w/o app logic. +} + +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/epaper_spi_jd79660.h b/esphome/components/epaper_spi/epaper_spi_jd79660.h new file mode 100644 index 0000000000..4e488fe93e --- /dev/null +++ b/esphome/components/epaper_spi/epaper_spi_jd79660.h @@ -0,0 +1,145 @@ +#pragma once + +#include "epaper_spi.h" + +namespace esphome::epaper_spi { + +/** + * JD7966x IC driver implementation + * + * Currently tested with: + * - JD79660 (max res: 200x200) + * + * May also work for other JD7966x chipset family members with minimal adaptations. + * + * Capabilities: + * - HW frame buffer layout: + * 4 colors (gray0..3, commonly BWYR). Bytes consist of 4px/2bpp. + * Width must be rounded to multiple of 4. + * - Fast init/update (shorter wave forms): Yes. Controlled by CONF_FULL_UPDATE_EVERY. + * Needs undocumented fastinit sequence, based on likely vendor specific MTP content. + * - Partial transfer (transfer only changed window): No. Maybe possible by HW. + * - Partial refresh (refresh only changed window): No. Likely HW limit. + * + * @internal \c final saves few bytes by devirtualization. Remove \c final when subclassing. + */ +class EPaperJD79660 final : public EPaperBase { + public: + EPaperJD79660(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, + size_t init_sequence_length, const uint8_t *fast_update, uint16_t fast_update_length) + : EPaperBase(name, width, height, init_sequence, init_sequence_length, DISPLAY_TYPE_COLOR), + fast_update_(fast_update), + fast_update_length_(fast_update_length) { + this->row_width_ = (width + 3) / 4; // Fix base class calc (2bpp instead of 1bpp) + this->buffer_length_ = this->row_width_ * height; + } + + void fill(Color color) override; + + protected: + /** Draw colored pixel into frame buffer */ + void draw_pixel_at(int x, int y, Color color) override; + + /** Reset (multistep sequence) + * @pre this->reset_pin_ != nullptr // cv.Required check + * @post Should be idle on successful reset. Can mark failures. + */ + bool reset() override; + + /** Initialise (multistep sequence) */ + bool initialise(bool partial) override; + + /** Buffer transfer */ + bool transfer_data() override; + + /** Power on: Already part of init sequence (likely needed there before transferring buffers). + * So nothing to do in FSM state. + */ + void power_on() override {} + + /** Refresh screen + * @param partial Ignored: Needed earlier in \a ::initialize + * @pre Must be idle. + * @post Should return to idle later after processing. + */ + void refresh_screen([[maybe_unused]] bool partial) override; + + /** Power off + * @pre Must be idle. + * @post Should return to idle later after processing. + * (latter will take long period like ~15-20s on actual refresh!) + */ + void power_off() override; + + /** Deepsleep: Must be used to avoid hardware wearout! + * @pre Must be idle. + * @post Will go busy, and not return idle till ::reset! + */ + void deep_sleep() override; + + /** Internal: Send fast init sequence via undocumented vendor registers + * @pre Must be directly after regular ::initialise sequence, before ::transfer_data + * @pre Must be idle. + * @post Should return to idle later after processing. + */ + void write_fastinit_(); + + /** Internal: Send raw buffer in chunks + * \retval true Finished + * \retval false Loop time elapsed. Need to call again next loop. + */ + bool transfer_buffer_chunks_(); + + /** @name IC commands @{ */ + static constexpr uint8_t CMD_POWEROFF = 0x02; + static constexpr uint8_t CMD_DEEPSLEEP = 0x07; + static constexpr uint8_t CMD_TRANSFER = 0x10; + static constexpr uint8_t CMD_REFRESH = 0x12; + /** @} */ + + /** State machine constants for \a step_ */ + enum class FSMState : uint8_t { + NONE = 0, //!< Initial/default value: Unused + + /* Reset state steps */ + RESET_STEP0_H, + RESET_STEP1_L, + RESET_STEP2_IDLECHECK, + + /* Init state steps */ + INIT_STEP0_REGULARINIT, + INIT_STEP1_FASTINIT, + }; + + /** Wait time (millisec) for first reset phase: High + * + * Wait via FSM loop. + */ + static constexpr uint16_t SLEEP_MS_RESET0 = 200; + + /** Wait time (millisec) for second reset phase: Low + * + * Holding Reset Low too long may trigger "clever reset" logic + * of e.g. Waveshare Rev2 boards: VDD is shut down via MOSFET, and IC + * will not report idle anymore! + * FSM loop may spuriously increase delay, e.g. >16ms. + * Therefore, sync wait below, as allowed (code rule "delays > 10ms not permitted"), + * yet only slightly exceeding known IC min req of >1.5ms. + */ + static constexpr uint16_t SLEEP_MS_RESET1 = 2; + + /** Wait time (millisec) for third reset phase: High + * + * Wait via FSM loop. + */ + static constexpr uint16_t SLEEP_MS_RESET2 = 200; + + // properties initialised in the constructor + const uint8_t *const fast_update_{}; + const uint16_t fast_update_length_{}; + + /** Counter for tracking substeps within FSM state */ + FSMState step_{FSMState::NONE}; +}; + +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/models/jd79660.py b/esphome/components/epaper_spi/models/jd79660.py new file mode 100644 index 0000000000..2d8830ebd2 --- /dev/null +++ b/esphome/components/epaper_spi/models/jd79660.py @@ -0,0 +1,86 @@ +import esphome.codegen as cg +from esphome.components.mipi import flatten_sequence +import esphome.config_validation as cv +from esphome.const import CONF_BUSY_PIN, CONF_RESET_PIN +from esphome.core import ID + +from ..display import CONF_INIT_SEQUENCE_ID +from . import EpaperModel + + +class JD79660(EpaperModel): + def __init__(self, name, class_name="EPaperJD79660", fast_update=None, **kwargs): + super().__init__(name, class_name, **kwargs) + self.fast_update = fast_update + + def option(self, name, fallback=cv.UNDEFINED) -> cv.Optional | cv.Required: + # Validate required pins, as C++ code will assume existence + if name in (CONF_RESET_PIN, CONF_BUSY_PIN): + return cv.Required(name) + + # Delegate to parent + return super().option(name, fallback) + + def get_constructor_args(self, config) -> tuple: + # Resembles init_sequence handling for fast_update config + if self.fast_update is None: + fast_update = cg.nullptr, 0 + else: + flat_fast_update = flatten_sequence(self.fast_update) + fast_update = ( + cg.static_const_array( + ID( + config[CONF_INIT_SEQUENCE_ID].id + "_fast_update", type=cg.uint8 + ), + flat_fast_update, + ), + len(flat_fast_update), + ) + return (*fast_update,) + + +jd79660 = JD79660( + "jd79660", + # Specified refresh times are ~20s (full) or ~15s (fast) due to BWRY. + # So disallow low update intervals (with safety margin), to avoid e.g. FSM update loops. + # Even less frequent intervals (min/h) highly recommended to optimize lifetime! + minimum_update_interval="30s", + # SPI rate: From spec comparisons, IC should allow SCL write cycles up to 10MHz rate. + # Existing code samples also prefer 10MHz. So justifies as default. + # Decrease value further in user config if needed (e.g. poor cabling). + data_rate="10MHz", + # No need to set optional reset_duration: + # Code requires multistep reset sequence with precise timings + # according to data sheet or samples. +) + +# Waveshare 1.54-G +# +# Device may have specific factory provisioned MTP content to facilitate vendor register features like fast init. +# Vendor specific init derived from vendor sample code +# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/1in54_e-Paper_G/ESP32/EPD_1in54g.cpp> +# Compatible MIT license, see esphome/LICENSE file. +# +# fmt: off +jd79660.extend( + "Waveshare-1.54in-G", + width=200, + height=200, + + initsequence=( + (0x4D, 0x78,), + (0x00, 0x0F, 0x29,), + (0x06, 0x0d, 0x12, 0x30, 0x20, 0x19, 0x2a, 0x22,), + (0x50, 0x37,), + (0x61, 200 // 256, 200 % 256, 200 // 256, 200 % 256,), # RES: 200x200 fixed + (0xE9, 0x01,), + (0x30, 0x08,), + # Power On (0x04): Must be early part of init seq = Disabled later! + (0x04,), + ), + fast_update=( + (0xE0, 0x02,), + (0xE6, 0x5D,), + (0xA5, 0x00,), + ), +) diff --git a/tests/components/epaper_spi/test.esp32-s3-idf.yaml b/tests/components/epaper_spi/test.esp32-s3-idf.yaml index 621a819c3c..333ab567cd 100644 --- a/tests/components/epaper_spi/test.esp32-s3-idf.yaml +++ b/tests/components/epaper_spi/test.esp32-s3-idf.yaml @@ -25,6 +25,22 @@ display: lambda: |- it.circle(64, 64, 50, Color::BLACK); + - platform: epaper_spi + spi_id: spi_bus + model: waveshare-1.54in-G + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + - platform: epaper_spi spi_id: spi_bus model: waveshare-2.13in-v3 From a43e3e59483a239467d1db8201522db25291371d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Feb 2026 22:19:20 +0100 Subject: [PATCH 0557/2030] [dashboard] Close WebSocket after process exit to prevent zombie connections (#13834) --- esphome/dashboard/web_server.py | 1 + tests/dashboard/test_web_server.py | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index f94d8eea22..da50279864 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -317,6 +317,7 @@ class EsphomeCommandWebSocket(CheckOriginMixin, tornado.websocket.WebSocketHandl # Check if the proc was not forcibly closed _LOGGER.info("Process exited with return code %s", returncode) self.write_message({"event": "exit", "code": returncode}) + self.close() def on_close(self) -> None: # Check if proc exists (if 'start' has been run) diff --git a/tests/dashboard/test_web_server.py b/tests/dashboard/test_web_server.py index 10ca6061e6..7642876ee5 100644 --- a/tests/dashboard/test_web_server.py +++ b/tests/dashboard/test_web_server.py @@ -29,7 +29,7 @@ from esphome.dashboard.entries import ( bool_to_entry_state, ) from esphome.dashboard.models import build_importable_device_dict -from esphome.dashboard.web_server import DashboardSubscriber +from esphome.dashboard.web_server import DashboardSubscriber, EsphomeCommandWebSocket from esphome.zeroconf import DiscoveredImport from .common import get_fixture_path @@ -1654,3 +1654,25 @@ async def test_websocket_check_origin_multiple_trusted_domains( assert data["event"] == "initial_state" finally: ws.close() + + +def test_proc_on_exit_calls_close() -> None: + """Test _proc_on_exit sends exit event and closes the WebSocket.""" + handler = Mock(spec=EsphomeCommandWebSocket) + handler._is_closed = False + + EsphomeCommandWebSocket._proc_on_exit(handler, 0) + + handler.write_message.assert_called_once_with({"event": "exit", "code": 0}) + handler.close.assert_called_once() + + +def test_proc_on_exit_skips_when_already_closed() -> None: + """Test _proc_on_exit does nothing when WebSocket is already closed.""" + handler = Mock(spec=EsphomeCommandWebSocket) + handler._is_closed = True + + EsphomeCommandWebSocket._proc_on_exit(handler, 0) + + handler.write_message.assert_not_called() + handler.close.assert_not_called() From 7b40e8afcb5c60ec15436da1e5b4588bd028df81 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Sun, 8 Feb 2026 02:21:37 +0100 Subject: [PATCH 0558/2030] [epaper_spi] Declare leaf classes final (#13776) --- esphome/components/epaper_spi/epaper_spi_spectra_e6.h | 2 +- esphome/components/epaper_spi/epaper_waveshare.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/epaper_spi/epaper_spi_spectra_e6.h b/esphome/components/epaper_spi/epaper_spi_spectra_e6.h index b8dbf0b0c5..9c251068af 100644 --- a/esphome/components/epaper_spi/epaper_spi_spectra_e6.h +++ b/esphome/components/epaper_spi/epaper_spi_spectra_e6.h @@ -4,7 +4,7 @@ namespace esphome::epaper_spi { -class EPaperSpectraE6 : public EPaperBase { +class EPaperSpectraE6 final : public EPaperBase { public: EPaperSpectraE6(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, size_t init_sequence_length) diff --git a/esphome/components/epaper_spi/epaper_waveshare.h b/esphome/components/epaper_spi/epaper_waveshare.h index 15fb575ca0..d3ad313d92 100644 --- a/esphome/components/epaper_spi/epaper_waveshare.h +++ b/esphome/components/epaper_spi/epaper_waveshare.h @@ -6,7 +6,7 @@ namespace esphome::epaper_spi { /** * An epaper display that needs LUTs to be sent to it. */ -class EpaperWaveshare : public EPaperMono { +class EpaperWaveshare final : public EPaperMono { public: EpaperWaveshare(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, size_t init_sequence_length, const uint8_t *lut, size_t lut_length, const uint8_t *partial_lut, From 41fedaedb3aea2a93621f7715e5d6588414eb696 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Feb 2026 08:26:47 -0600 Subject: [PATCH 0559/2030] [udp] Eliminate per-loop heap allocation using std::span (#13838) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/codegen.py | 1 + .../packet_transport/packet_transport.cpp | 4 +- .../packet_transport/packet_transport.h | 5 ++- esphome/components/udp/__init__.py | 16 ++++++-- .../udp/packet_transport/udp_transport.cpp | 2 +- esphome/components/udp/udp_component.cpp | 8 ++-- esphome/components/udp/udp_component.h | 6 ++- esphome/cpp_types.py | 1 + tests/integration/test_udp.py | 39 ++++++++++++++++--- 9 files changed, 62 insertions(+), 20 deletions(-) diff --git a/esphome/codegen.py b/esphome/codegen.py index 4a2a5975c6..c5283f4967 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -87,6 +87,7 @@ from esphome.cpp_types import ( # noqa: F401 size_t, std_ns, std_shared_ptr, + std_span, std_string, std_string_ref, std_vector, diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index cefe9a604e..365a5f2ec7 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -396,9 +396,9 @@ static bool process_rolling_code(Provider &provider, PacketDecoder &decoder) { /** * Process a received packet */ -void PacketTransport::process_(const std::vector<uint8_t> &data) { +void PacketTransport::process_(std::span<const uint8_t> data) { auto ping_key_seen = !this->ping_pong_enable_; - PacketDecoder decoder((data.data()), data.size()); + PacketDecoder decoder(data.data(), data.size()); char namebuf[256]{}; uint8_t byte; FuData rdata{}; diff --git a/esphome/components/packet_transport/packet_transport.h b/esphome/components/packet_transport/packet_transport.h index 86ec564fce..57f40874b5 100644 --- a/esphome/components/packet_transport/packet_transport.h +++ b/esphome/components/packet_transport/packet_transport.h @@ -9,8 +9,9 @@ #include "esphome/components/binary_sensor/binary_sensor.h" #endif -#include <vector> #include <map> +#include <span> +#include <vector> /** * Providing packet encoding functions for exchanging data with a remote host. @@ -113,7 +114,7 @@ class PacketTransport : public PollingComponent { virtual bool should_send() { return true; } // to be called by child classes when a data packet is received. - void process_(const std::vector<uint8_t> &data); + void process_(std::span<const uint8_t> data); void send_data_(bool all); void flush_(); void add_data_(uint8_t key, const char *id, float data); diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 8252e35023..bfaa5f2516 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -13,7 +13,7 @@ from esphome.components.packet_transport import ( import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID from esphome.core import ID -from esphome.cpp_generator import literal +from esphome.cpp_generator import MockObj CODEOWNERS = ["@clydebarrow"] DEPENDENCIES = ["network"] @@ -23,8 +23,12 @@ MULTI_CONF = True udp_ns = cg.esphome_ns.namespace("udp") UDPComponent = udp_ns.class_("UDPComponent", cg.Component) UDPWriteAction = udp_ns.class_("UDPWriteAction", automation.Action) -trigger_args = cg.std_vector.template(cg.uint8) trigger_argname = "data" +# Listener callback type (non-owning span from UDP component) +listener_args = cg.std_span.template(cg.uint8.operator("const")) +listener_argtype = [(listener_args, trigger_argname)] +# Automation/trigger type (owned vector, safe for deferred actions like delay) +trigger_args = cg.std_vector.template(cg.uint8) trigger_argtype = [(trigger_args, trigger_argname)] CONF_ADDRESSES = "addresses" @@ -118,7 +122,13 @@ async def to_code(config): trigger_id, trigger_argtype, on_receive ) trigger_lambda = await cg.process_lambda( - trigger.trigger(literal(trigger_argname)), trigger_argtype + trigger.trigger( + cg.std_vector.template(cg.uint8)( + MockObj(trigger_argname).begin(), + MockObj(trigger_argname).end(), + ) + ), + listener_argtype, ) cg.add(var.add_listener(trigger_lambda)) cg.add(var.set_should_listen()) diff --git a/esphome/components/udp/packet_transport/udp_transport.cpp b/esphome/components/udp/packet_transport/udp_transport.cpp index f3e33573a5..b5e73af777 100644 --- a/esphome/components/udp/packet_transport/udp_transport.cpp +++ b/esphome/components/udp/packet_transport/udp_transport.cpp @@ -12,7 +12,7 @@ bool UDPTransport::should_send() { return network::is_connected(); } void UDPTransport::setup() { PacketTransport::setup(); if (!this->providers_.empty() || this->is_encrypted_()) { - this->parent_->add_listener([this](std::vector<uint8_t> &buf) { this->process_(buf); }); + this->parent_->add_listener([this](std::span<const uint8_t> data) { this->process_(data); }); } } diff --git a/esphome/components/udp/udp_component.cpp b/esphome/components/udp/udp_component.cpp index 947a59dfa9..c144212ecf 100644 --- a/esphome/components/udp/udp_component.cpp +++ b/esphome/components/udp/udp_component.cpp @@ -103,8 +103,8 @@ void UDPComponent::setup() { } void UDPComponent::loop() { - auto buf = std::vector<uint8_t>(MAX_PACKET_SIZE); if (this->should_listen_) { + std::array<uint8_t, MAX_PACKET_SIZE> buf; for (;;) { #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) auto len = this->listen_socket_->read(buf.data(), buf.size()); @@ -116,9 +116,9 @@ void UDPComponent::loop() { #endif if (len <= 0) break; - buf.resize(len); - ESP_LOGV(TAG, "Received packet of length %zu", len); - this->packet_listeners_.call(buf); + size_t packet_len = static_cast<size_t>(len); + ESP_LOGV(TAG, "Received packet of length %zu", packet_len); + this->packet_listeners_.call(std::span<const uint8_t>(buf.data(), packet_len)); } } } diff --git a/esphome/components/udp/udp_component.h b/esphome/components/udp/udp_component.h index 9967e4dbbb..7fd6308065 100644 --- a/esphome/components/udp/udp_component.h +++ b/esphome/components/udp/udp_component.h @@ -10,7 +10,9 @@ #ifdef USE_SOCKET_IMPL_LWIP_TCP #include <WiFiUdp.h> #endif +#include <array> #include <initializer_list> +#include <span> #include <vector> namespace esphome::udp { @@ -26,7 +28,7 @@ class UDPComponent : public Component { void set_broadcast_port(uint16_t port) { this->broadcast_port_ = port; } void set_should_broadcast() { this->should_broadcast_ = true; } void set_should_listen() { this->should_listen_ = true; } - void add_listener(std::function<void(std::vector<uint8_t> &)> &&listener) { + void add_listener(std::function<void(std::span<const uint8_t>)> &&listener) { this->packet_listeners_.add(std::move(listener)); } void setup() override; @@ -41,7 +43,7 @@ class UDPComponent : public Component { uint16_t broadcast_port_{}; bool should_broadcast_{}; bool should_listen_{}; - CallbackManager<void(std::vector<uint8_t> &)> packet_listeners_{}; + CallbackManager<void(std::span<const uint8_t>)> packet_listeners_{}; #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) std::unique_ptr<socket::Socket> broadcast_socket_ = nullptr; diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 7001c38857..6d255bc0be 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -12,6 +12,7 @@ std_shared_ptr = std_ns.class_("shared_ptr") std_string = std_ns.class_("string") std_string_ref = std_ns.namespace("string &") std_vector = std_ns.class_("vector") +std_span = std_ns.class_("span") uint8 = global_ns.namespace("uint8_t") uint16 = global_ns.namespace("uint16_t") uint32 = global_ns.namespace("uint32_t") diff --git a/tests/integration/test_udp.py b/tests/integration/test_udp.py index 74c7ef60e3..2187d13814 100644 --- a/tests/integration/test_udp.py +++ b/tests/integration/test_udp.py @@ -93,23 +93,34 @@ async def udp_listener(port: int = 0) -> AsyncGenerator[tuple[int, UDPReceiver]] sock.close() +def _get_free_udp_port() -> int: + """Get a free UDP port by binding to port 0 and releasing.""" + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.bind(("127.0.0.1", 0)) + port = sock.getsockname()[1] + sock.close() + return port + + @pytest.mark.asyncio async def test_udp_send_receive( yaml_config: str, run_compiled: RunCompiledFunction, api_client_connected: APIClientConnectedFactory, ) -> None: - """Test UDP component can send messages with multiple addresses configured.""" - # Track log lines to verify dump_config output + """Test UDP component can send and receive messages.""" log_lines: list[str] = [] + receive_event = asyncio.Event() def on_log_line(line: str) -> None: log_lines.append(line) + if "Received UDP:" in line: + receive_event.set() - async with udp_listener() as (udp_port, receiver): - # Replace placeholders in the config - config = yaml_config.replace("UDP_LISTEN_PORT_PLACEHOLDER", str(udp_port + 1)) - config = config.replace("UDP_BROADCAST_PORT_PLACEHOLDER", str(udp_port)) + async with udp_listener() as (broadcast_port, receiver): + listen_port = _get_free_udp_port() + config = yaml_config.replace("UDP_LISTEN_PORT_PLACEHOLDER", str(listen_port)) + config = config.replace("UDP_BROADCAST_PORT_PLACEHOLDER", str(broadcast_port)) async with ( run_compiled(config, line_callback=on_log_line), @@ -169,3 +180,19 @@ async def test_udp_send_receive( assert "Address: 127.0.0.2" in log_text, ( f"Address 127.0.0.2 not found in dump_config. Log: {log_text[-2000:]}" ) + + # Test receiving a UDP packet (exercises on_receive with std::span) + test_payload = b"TEST_RECEIVE_UDP" + send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + send_sock.sendto(test_payload, ("127.0.0.1", listen_port)) + finally: + send_sock.close() + + try: + await asyncio.wait_for(receive_event.wait(), timeout=5.0) + except TimeoutError: + pytest.fail( + f"on_receive did not fire. Expected 'Received UDP:' in logs. " + f"Last log lines: {log_lines[-20:]}" + ) From 28b9487b25043dcbecb12068d617bc1909acb22f Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sun, 8 Feb 2026 18:52:05 +0100 Subject: [PATCH 0560/2030] [nrf52,logger] fix printk (#13874) --- esphome/components/logger/logger_zephyr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index ef1702c5c1..1fc0acd573 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -68,7 +68,7 @@ void HOT Logger::write_msg_(const char *msg, uint16_t len) { #ifdef CONFIG_PRINTK // Requires the debug component and an active SWD connection. // It is used for pyocd rtt -t nrf52840 - k_str_out(const_cast<char *>(msg), len); + printk("%.*s", static_cast<int>(len), msg); #endif if (this->uart_dev_ == nullptr) { return; From 756f1c6b7e8162752af7ca8191e2eff71a122e3a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:53:43 +1100 Subject: [PATCH 0561/2030] [lvgl] Fix crash with unconfigured `top_layer` (#13846) --- esphome/components/lvgl/schemas.py | 1 + tests/components/lvgl/test.host.yaml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 45d933c00e..2aeeedbd10 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -436,6 +436,7 @@ def container_schema(widget_type: WidgetType, extras=None): schema = schema.extend(widget_type.schema) def validator(value): + value = value or {} return append_layout_schema(schema, value)(value) return validator diff --git a/tests/components/lvgl/test.host.yaml b/tests/components/lvgl/test.host.yaml index 00a8cd8c01..f84156c9d8 100644 --- a/tests/components/lvgl/test.host.yaml +++ b/tests/components/lvgl/test.host.yaml @@ -20,6 +20,8 @@ lvgl: - id: lvgl_0 default_font: space16 displays: sdl0 + top_layer: + - id: lvgl_1 displays: sdl1 on_idle: From 140ec0639ca3f0e8cac0c839d5e93f67cbee2621 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:24:45 -0600 Subject: [PATCH 0562/2030] [api] Elide empty message construction in protobuf dispatch (#13871) --- esphome/components/api/api_connection.cpp | 17 ++-- esphome/components/api/api_connection.h | 24 +++-- esphome/components/api/api_pb2_service.cpp | 106 ++++++++------------- esphome/components/api/api_pb2_service.h | 62 ++++++------ script/api_protobuf/api_protobuf.py | 53 ++++++----- 5 files changed, 117 insertions(+), 145 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 2aa5956f24..efc3d210b4 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -283,7 +283,7 @@ void APIConnection::loop() { #endif } -bool APIConnection::send_disconnect_response(const DisconnectRequest &msg) { +bool APIConnection::send_disconnect_response() { // remote initiated disconnect_client // don't close yet, we still need to send the disconnect response // close will happen on next loop @@ -292,7 +292,7 @@ bool APIConnection::send_disconnect_response(const DisconnectRequest &msg) { DisconnectResponse resp; return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE); } -void APIConnection::on_disconnect_response(const DisconnectResponse &value) { +void APIConnection::on_disconnect_response() { this->helper_->close(); this->flags_.remove = true; } @@ -1095,7 +1095,7 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) { void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->subscribe_api_connection(this, msg.flags); } -void APIConnection::unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) { +void APIConnection::unsubscribe_bluetooth_le_advertisements() { bluetooth_proxy::global_bluetooth_proxy->unsubscribe_api_connection(this); } void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) { @@ -1121,8 +1121,7 @@ void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_notify(msg); } -bool APIConnection::send_subscribe_bluetooth_connections_free_response( - const SubscribeBluetoothConnectionsFreeRequest &msg) { +bool APIConnection::send_subscribe_bluetooth_connections_free_response() { bluetooth_proxy::global_bluetooth_proxy->send_connections_free(this); return true; } @@ -1491,12 +1490,12 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) { return this->send_message(resp, HelloResponse::MESSAGE_TYPE); } -bool APIConnection::send_ping_response(const PingRequest &msg) { +bool APIConnection::send_ping_response() { PingResponse resp; return this->send_message(resp, PingResponse::MESSAGE_TYPE); } -bool APIConnection::send_device_info_response(const DeviceInfoRequest &msg) { +bool APIConnection::send_device_info_response() { DeviceInfoResponse resp{}; resp.name = StringRef(App.get_name()); resp.friendly_name = StringRef(App.get_friendly_name()); @@ -1746,9 +1745,7 @@ bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryption } #endif #ifdef USE_API_HOMEASSISTANT_STATES -void APIConnection::subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) { - state_subs_at_ = 0; -} +void APIConnection::subscribe_home_assistant_states() { state_subs_at_ = 0; } #endif bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { if (this->flags_.remove) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 40e4fd61c1..935393b2da 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -127,7 +127,7 @@ class APIConnection final : public APIServerConnection { #endif // USE_API_HOMEASSISTANT_SERVICES #ifdef USE_BLUETOOTH_PROXY void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; - void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override; + void unsubscribe_bluetooth_le_advertisements() override; void bluetooth_device_request(const BluetoothDeviceRequest &msg) override; void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) override; @@ -136,7 +136,7 @@ class APIConnection final : public APIServerConnection { void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) override; void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) override; void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) override; - bool send_subscribe_bluetooth_connections_free_response(const SubscribeBluetoothConnectionsFreeRequest &msg) override; + bool send_subscribe_bluetooth_connections_free_response() override; void bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) override; #endif @@ -187,8 +187,8 @@ class APIConnection final : public APIServerConnection { void update_command(const UpdateCommandRequest &msg) override; #endif - void on_disconnect_response(const DisconnectResponse &value) override; - void on_ping_response(const PingResponse &value) override { + void on_disconnect_response() override; + void on_ping_response() override { // we initiated ping this->flags_.sent_ping = false; } @@ -199,11 +199,11 @@ class APIConnection final : public APIServerConnection { void on_get_time_response(const GetTimeResponse &value) override; #endif bool send_hello_response(const HelloRequest &msg) override; - bool send_disconnect_response(const DisconnectRequest &msg) override; - bool send_ping_response(const PingRequest &msg) override; - bool send_device_info_response(const DeviceInfoRequest &msg) override; - void list_entities(const ListEntitiesRequest &msg) override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } - void subscribe_states(const SubscribeStatesRequest &msg) override { + bool send_disconnect_response() override; + bool send_ping_response() override; + bool send_device_info_response() override; + void list_entities() override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } + void subscribe_states() override { this->flags_.state_subscription = true; // Start initial state iterator only if no iterator is active // If list_entities is running, we'll start initial_state when it completes @@ -217,12 +217,10 @@ class APIConnection final : public APIServerConnection { App.schedule_dump_config(); } #ifdef USE_API_HOMEASSISTANT_SERVICES - void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) override { - this->flags_.service_call_subscription = true; - } + void subscribe_homeassistant_services() override { this->flags_.service_call_subscription = true; } #endif #ifdef USE_API_HOMEASSISTANT_STATES - void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) override; + void subscribe_home_assistant_states() override; #endif #ifdef USE_API_USER_DEFINED_ACTIONS void execute_service(const ExecuteServiceRequest &msg) override; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index af0a2d0ca2..df66b6eb83 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -15,6 +15,9 @@ void APIServerConnectionBase::log_receive_message_(const LogString *name, const DumpBuffer dump_buf; ESP_LOGVV(TAG, "%s: %s", LOG_STR_ARG(name), msg.dump_to(dump_buf)); } +void APIServerConnectionBase::log_receive_message_(const LogString *name) { + ESP_LOGVV(TAG, "%s: {}", LOG_STR_ARG(name)); +} #endif void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { @@ -29,66 +32,52 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, break; } case DisconnectRequest::MESSAGE_TYPE: { - DisconnectRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_disconnect_request"), msg); + this->log_receive_message_(LOG_STR("on_disconnect_request")); #endif - this->on_disconnect_request(msg); + this->on_disconnect_request(); break; } case DisconnectResponse::MESSAGE_TYPE: { - DisconnectResponse msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_disconnect_response"), msg); + this->log_receive_message_(LOG_STR("on_disconnect_response")); #endif - this->on_disconnect_response(msg); + this->on_disconnect_response(); break; } case PingRequest::MESSAGE_TYPE: { - PingRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_ping_request"), msg); + this->log_receive_message_(LOG_STR("on_ping_request")); #endif - this->on_ping_request(msg); + this->on_ping_request(); break; } case PingResponse::MESSAGE_TYPE: { - PingResponse msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_ping_response"), msg); + this->log_receive_message_(LOG_STR("on_ping_response")); #endif - this->on_ping_response(msg); + this->on_ping_response(); break; } case DeviceInfoRequest::MESSAGE_TYPE: { - DeviceInfoRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_device_info_request"), msg); + this->log_receive_message_(LOG_STR("on_device_info_request")); #endif - this->on_device_info_request(msg); + this->on_device_info_request(); break; } case ListEntitiesRequest::MESSAGE_TYPE: { - ListEntitiesRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_list_entities_request"), msg); + this->log_receive_message_(LOG_STR("on_list_entities_request")); #endif - this->on_list_entities_request(msg); + this->on_list_entities_request(); break; } case SubscribeStatesRequest::MESSAGE_TYPE: { - SubscribeStatesRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_subscribe_states_request"), msg); + this->log_receive_message_(LOG_STR("on_subscribe_states_request")); #endif - this->on_subscribe_states_request(msg); + this->on_subscribe_states_request(); break; } case SubscribeLogsRequest::MESSAGE_TYPE: { @@ -146,12 +135,10 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #endif #ifdef USE_API_HOMEASSISTANT_SERVICES case SubscribeHomeassistantServicesRequest::MESSAGE_TYPE: { - SubscribeHomeassistantServicesRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_subscribe_homeassistant_services_request"), msg); + this->log_receive_message_(LOG_STR("on_subscribe_homeassistant_services_request")); #endif - this->on_subscribe_homeassistant_services_request(msg); + this->on_subscribe_homeassistant_services_request(); break; } #endif @@ -166,12 +153,10 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } #ifdef USE_API_HOMEASSISTANT_STATES case SubscribeHomeAssistantStatesRequest::MESSAGE_TYPE: { - SubscribeHomeAssistantStatesRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_subscribe_home_assistant_states_request"), msg); + this->log_receive_message_(LOG_STR("on_subscribe_home_assistant_states_request")); #endif - this->on_subscribe_home_assistant_states_request(msg); + this->on_subscribe_home_assistant_states_request(); break; } #endif @@ -375,23 +360,19 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, #endif #ifdef USE_BLUETOOTH_PROXY case SubscribeBluetoothConnectionsFreeRequest::MESSAGE_TYPE: { - SubscribeBluetoothConnectionsFreeRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_connections_free_request"), msg); + this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_connections_free_request")); #endif - this->on_subscribe_bluetooth_connections_free_request(msg); + this->on_subscribe_bluetooth_connections_free_request(); break; } #endif #ifdef USE_BLUETOOTH_PROXY case UnsubscribeBluetoothLEAdvertisementsRequest::MESSAGE_TYPE: { - UnsubscribeBluetoothLEAdvertisementsRequest msg; - // Empty message: no decode needed #ifdef HAS_PROTO_MESSAGE_DUMP - this->log_receive_message_(LOG_STR("on_unsubscribe_bluetooth_le_advertisements_request"), msg); + this->log_receive_message_(LOG_STR("on_unsubscribe_bluetooth_le_advertisements_request")); #endif - this->on_unsubscribe_bluetooth_le_advertisements_request(msg); + this->on_unsubscribe_bluetooth_le_advertisements_request(); break; } #endif @@ -647,36 +628,29 @@ void APIServerConnection::on_hello_request(const HelloRequest &msg) { this->on_fatal_error(); } } -void APIServerConnection::on_disconnect_request(const DisconnectRequest &msg) { - if (!this->send_disconnect_response(msg)) { +void APIServerConnection::on_disconnect_request() { + if (!this->send_disconnect_response()) { this->on_fatal_error(); } } -void APIServerConnection::on_ping_request(const PingRequest &msg) { - if (!this->send_ping_response(msg)) { +void APIServerConnection::on_ping_request() { + if (!this->send_ping_response()) { this->on_fatal_error(); } } -void APIServerConnection::on_device_info_request(const DeviceInfoRequest &msg) { - if (!this->send_device_info_response(msg)) { +void APIServerConnection::on_device_info_request() { + if (!this->send_device_info_response()) { this->on_fatal_error(); } } -void APIServerConnection::on_list_entities_request(const ListEntitiesRequest &msg) { this->list_entities(msg); } -void APIServerConnection::on_subscribe_states_request(const SubscribeStatesRequest &msg) { - this->subscribe_states(msg); -} +void APIServerConnection::on_list_entities_request() { this->list_entities(); } +void APIServerConnection::on_subscribe_states_request() { this->subscribe_states(); } void APIServerConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) { this->subscribe_logs(msg); } #ifdef USE_API_HOMEASSISTANT_SERVICES -void APIServerConnection::on_subscribe_homeassistant_services_request( - const SubscribeHomeassistantServicesRequest &msg) { - this->subscribe_homeassistant_services(msg); -} +void APIServerConnection::on_subscribe_homeassistant_services_request() { this->subscribe_homeassistant_services(); } #endif #ifdef USE_API_HOMEASSISTANT_STATES -void APIServerConnection::on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) { - this->subscribe_home_assistant_states(msg); -} +void APIServerConnection::on_subscribe_home_assistant_states_request() { this->subscribe_home_assistant_states(); } #endif #ifdef USE_API_USER_DEFINED_ACTIONS void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) { this->execute_service(msg); } @@ -793,17 +767,15 @@ void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNo } #endif #ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_subscribe_bluetooth_connections_free_request( - const SubscribeBluetoothConnectionsFreeRequest &msg) { - if (!this->send_subscribe_bluetooth_connections_free_response(msg)) { +void APIServerConnection::on_subscribe_bluetooth_connections_free_request() { + if (!this->send_subscribe_bluetooth_connections_free_response()) { this->on_fatal_error(); } } #endif #ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request( - const UnsubscribeBluetoothLEAdvertisementsRequest &msg) { - this->unsubscribe_bluetooth_le_advertisements(msg); +void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request() { + this->unsubscribe_bluetooth_le_advertisements(); } #endif #ifdef USE_BLUETOOTH_PROXY diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index e2bc1609ed..b8c9e4da6f 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -14,6 +14,7 @@ class APIServerConnectionBase : public ProtoService { protected: void log_send_message_(const char *name, const char *dump); void log_receive_message_(const LogString *name, const ProtoMessage &msg); + void log_receive_message_(const LogString *name); public: #endif @@ -28,15 +29,15 @@ class APIServerConnectionBase : public ProtoService { virtual void on_hello_request(const HelloRequest &value){}; - virtual void on_disconnect_request(const DisconnectRequest &value){}; - virtual void on_disconnect_response(const DisconnectResponse &value){}; - virtual void on_ping_request(const PingRequest &value){}; - virtual void on_ping_response(const PingResponse &value){}; - virtual void on_device_info_request(const DeviceInfoRequest &value){}; + virtual void on_disconnect_request(){}; + virtual void on_disconnect_response(){}; + virtual void on_ping_request(){}; + virtual void on_ping_response(){}; + virtual void on_device_info_request(){}; - virtual void on_list_entities_request(const ListEntitiesRequest &value){}; + virtual void on_list_entities_request(){}; - virtual void on_subscribe_states_request(const SubscribeStatesRequest &value){}; + virtual void on_subscribe_states_request(){}; #ifdef USE_COVER virtual void on_cover_command_request(const CoverCommandRequest &value){}; @@ -61,14 +62,14 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_API_HOMEASSISTANT_SERVICES - virtual void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &value){}; + virtual void on_subscribe_homeassistant_services_request(){}; #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES virtual void on_homeassistant_action_response(const HomeassistantActionResponse &value){}; #endif #ifdef USE_API_HOMEASSISTANT_STATES - virtual void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &value){}; + virtual void on_subscribe_home_assistant_states_request(){}; #endif #ifdef USE_API_HOMEASSISTANT_STATES @@ -147,12 +148,11 @@ class APIServerConnectionBase : public ProtoService { #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &value){}; + virtual void on_subscribe_bluetooth_connections_free_request(){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_unsubscribe_bluetooth_le_advertisements_request( - const UnsubscribeBluetoothLEAdvertisementsRequest &value){}; + virtual void on_unsubscribe_bluetooth_le_advertisements_request(){}; #endif #ifdef USE_BLUETOOTH_PROXY @@ -231,17 +231,17 @@ class APIServerConnectionBase : public ProtoService { class APIServerConnection : public APIServerConnectionBase { public: virtual bool send_hello_response(const HelloRequest &msg) = 0; - virtual bool send_disconnect_response(const DisconnectRequest &msg) = 0; - virtual bool send_ping_response(const PingRequest &msg) = 0; - virtual bool send_device_info_response(const DeviceInfoRequest &msg) = 0; - virtual void list_entities(const ListEntitiesRequest &msg) = 0; - virtual void subscribe_states(const SubscribeStatesRequest &msg) = 0; + virtual bool send_disconnect_response() = 0; + virtual bool send_ping_response() = 0; + virtual bool send_device_info_response() = 0; + virtual void list_entities() = 0; + virtual void subscribe_states() = 0; virtual void subscribe_logs(const SubscribeLogsRequest &msg) = 0; #ifdef USE_API_HOMEASSISTANT_SERVICES - virtual void subscribe_homeassistant_services(const SubscribeHomeassistantServicesRequest &msg) = 0; + virtual void subscribe_homeassistant_services() = 0; #endif #ifdef USE_API_HOMEASSISTANT_STATES - virtual void subscribe_home_assistant_states(const SubscribeHomeAssistantStatesRequest &msg) = 0; + virtual void subscribe_home_assistant_states() = 0; #endif #ifdef USE_API_USER_DEFINED_ACTIONS virtual void execute_service(const ExecuteServiceRequest &msg) = 0; @@ -331,11 +331,10 @@ class APIServerConnection : public APIServerConnectionBase { virtual void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) = 0; #endif #ifdef USE_BLUETOOTH_PROXY - virtual bool send_subscribe_bluetooth_connections_free_response( - const SubscribeBluetoothConnectionsFreeRequest &msg) = 0; + virtual bool send_subscribe_bluetooth_connections_free_response() = 0; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void unsubscribe_bluetooth_le_advertisements(const UnsubscribeBluetoothLEAdvertisementsRequest &msg) = 0; + virtual void unsubscribe_bluetooth_le_advertisements() = 0; #endif #ifdef USE_BLUETOOTH_PROXY virtual void bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) = 0; @@ -363,17 +362,17 @@ class APIServerConnection : public APIServerConnectionBase { #endif protected: void on_hello_request(const HelloRequest &msg) override; - void on_disconnect_request(const DisconnectRequest &msg) override; - void on_ping_request(const PingRequest &msg) override; - void on_device_info_request(const DeviceInfoRequest &msg) override; - void on_list_entities_request(const ListEntitiesRequest &msg) override; - void on_subscribe_states_request(const SubscribeStatesRequest &msg) override; + void on_disconnect_request() override; + void on_ping_request() override; + void on_device_info_request() override; + void on_list_entities_request() override; + void on_subscribe_states_request() override; void on_subscribe_logs_request(const SubscribeLogsRequest &msg) override; #ifdef USE_API_HOMEASSISTANT_SERVICES - void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &msg) override; + void on_subscribe_homeassistant_services_request() override; #endif #ifdef USE_API_HOMEASSISTANT_STATES - void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &msg) override; + void on_subscribe_home_assistant_states_request() override; #endif #ifdef USE_API_USER_DEFINED_ACTIONS void on_execute_service_request(const ExecuteServiceRequest &msg) override; @@ -463,11 +462,10 @@ class APIServerConnection : public APIServerConnectionBase { void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override; #endif #ifdef USE_BLUETOOTH_PROXY - void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &msg) override; + void on_subscribe_bluetooth_connections_free_request() override; #endif #ifdef USE_BLUETOOTH_PROXY - void on_unsubscribe_bluetooth_le_advertisements_request( - const UnsubscribeBluetoothLEAdvertisementsRequest &msg) override; + void on_unsubscribe_bluetooth_le_advertisements_request() override; #endif #ifdef USE_BLUETOOTH_PROXY void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 4021a062ca..5fbc1137a8 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2270,10 +2270,13 @@ SOURCE_NAMES = { SOURCE_CLIENT: "SOURCE_CLIENT", } -RECEIVE_CASES: dict[int, tuple[str, str | None]] = {} +RECEIVE_CASES: dict[int, tuple[str, str | None, str]] = {} ifdefs: dict[str, str] = {} +# Track messages with no fields (empty messages) for parameter elision +EMPTY_MESSAGES: set[str] = set() + def get_opt( desc: descriptor.DescriptorProto, @@ -2504,26 +2507,26 @@ def build_service_message_type( # Only add ifdef when we're actually generating content if ifdef is not None: hout += f"#ifdef {ifdef}\n" - # Generate receive + # Generate receive handler and switch case func = f"on_{snake}" - hout += f"virtual void {func}(const {mt.name} &value){{}};\n" - case = "" - case += f"{mt.name} msg;\n" - # Check if this message has any fields (excluding deprecated ones) has_fields = any(not field.options.deprecated for field in mt.field) - if has_fields: - # Normal case: decode the message + is_empty = not has_fields + if is_empty: + EMPTY_MESSAGES.add(mt.name) + hout += f"virtual void {func}({'' if is_empty else f'const {mt.name} &value'}){{}};\n" + case = "" + if not is_empty: + case += f"{mt.name} msg;\n" case += "msg.decode(msg_data, msg_size);\n" - else: - # Empty message optimization: skip decode since there are no fields - case += "// Empty message: no decode needed\n" if log: case += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - case += f'this->log_receive_message_(LOG_STR("{func}"), msg);\n' + if is_empty: + case += f'this->log_receive_message_(LOG_STR("{func}"));\n' + else: + case += f'this->log_receive_message_(LOG_STR("{func}"), msg);\n' case += "#endif\n" - case += f"this->{func}(msg);\n" + case += f"this->{func}({'msg' if not is_empty else ''});\n" case += "break;" - # Store the message name and ifdef with the case for later use RECEIVE_CASES[id_] = (case, ifdef, mt.name) # Only close ifdef if we opened it @@ -2839,6 +2842,7 @@ static const char *const TAG = "api.service"; hpp += ( " void log_receive_message_(const LogString *name, const ProtoMessage &msg);\n" ) + hpp += " void log_receive_message_(const LogString *name);\n" hpp += " public:\n" hpp += "#endif\n\n" @@ -2862,6 +2866,9 @@ static const char *const TAG = "api.service"; cpp += " DumpBuffer dump_buf;\n" cpp += ' ESP_LOGVV(TAG, "%s: %s", LOG_STR_ARG(name), msg.dump_to(dump_buf));\n' cpp += "}\n" + cpp += f"void {class_name}::log_receive_message_(const LogString *name) {{\n" + cpp += ' ESP_LOGVV(TAG, "%s: {}", LOG_STR_ARG(name));\n' + cpp += "}\n" cpp += "#endif\n\n" for mt in file.message_type: @@ -2929,22 +2936,22 @@ static const char *const TAG = "api.service"; hpp_protected += f"#ifdef {ifdef}\n" cpp += f"#ifdef {ifdef}\n" - hpp_protected += f" void {on_func}(const {inp} &msg) override;\n" + is_empty = inp in EMPTY_MESSAGES + param = "" if is_empty else f"const {inp} &msg" + arg = "" if is_empty else "msg" - # For non-void methods, generate a send_ method instead of return-by-value + hpp_protected += f" void {on_func}({param}) override;\n" if is_void: - hpp += f" virtual void {func}(const {inp} &msg) = 0;\n" + hpp += f" virtual void {func}({param}) = 0;\n" else: - hpp += f" virtual bool send_{func}_response(const {inp} &msg) = 0;\n" + hpp += f" virtual bool send_{func}_response({param}) = 0;\n" - cpp += f"void {class_name}::{on_func}(const {inp} &msg) {{\n" - - # No authentication check here - it's done in read_message + cpp += f"void {class_name}::{on_func}({param}) {{\n" body = "" if is_void: - body += f"this->{func}(msg);\n" + body += f"this->{func}({arg});\n" else: - body += f"if (!this->send_{func}_response(msg)) {{\n" + body += f"if (!this->send_{func}_response({arg})) {{\n" body += " this->on_fatal_error();\n" body += "}\n" From eb6a6f8d0d6a408138d0dd2fd2143a8af9b2ee8c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:25:05 -0600 Subject: [PATCH 0563/2030] [web_server_idf] Remove unused host() method (#13869) --- esphome/components/web_server_idf/web_server_idf.cpp | 2 -- esphome/components/web_server_idf/web_server_idf.h | 1 - 2 files changed, 3 deletions(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 9860810452..39e6b7a790 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -258,8 +258,6 @@ StringRef AsyncWebServerRequest::url_to(std::span<char, URL_BUF_SIZE> buffer) co return StringRef(buffer.data(), decoded_len); } -std::string AsyncWebServerRequest::host() const { return this->get_header("Host").value(); } - void AsyncWebServerRequest::send(AsyncWebServerResponse *response) { httpd_resp_send(*this, response->get_content_data(), response->get_content_size()); } diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 817f47da79..1760544963 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -121,7 +121,6 @@ class AsyncWebServerRequest { char buffer[URL_BUF_SIZE]; return std::string(this->url_to(buffer)); } - std::string host() const; // NOLINTNEXTLINE(readability-identifier-naming) size_t contentLength() const { return this->req_->content_len; } From 6ee185c58aa047dde7e933c4d5a1b47c42f6572a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:25:23 -0600 Subject: [PATCH 0564/2030] [dashboard] Use resolve/relative_to for download path validation (#13867) --- esphome/dashboard/web_server.py | 17 ++++-- tests/dashboard/test_web_server.py | 93 +++++++++++++++++++++++++----- 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index da50279864..00974bf460 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -1054,17 +1054,26 @@ class DownloadBinaryRequestHandler(BaseHandler): # fallback to type=, but prioritize file= file_name = self.get_argument("type", None) file_name = self.get_argument("file", file_name) - if file_name is None: + if file_name is None or not file_name.strip(): self.send_error(400) return - file_name = file_name.replace("..", "").lstrip("/") # get requested download name, or build it based on filename download_name = self.get_argument( "download", f"{storage_json.name}-{file_name}", ) - path = storage_json.firmware_bin_path.parent.joinpath(file_name) + if storage_json.firmware_bin_path is None: + self.send_error(404) + return + + base_dir = storage_json.firmware_bin_path.parent.resolve() + path = base_dir.joinpath(file_name).resolve() + try: + path.relative_to(base_dir) + except ValueError: + self.send_error(403) + return if not path.is_file(): args = ["esphome", "idedata", settings.rel_path(configuration)] @@ -1078,7 +1087,7 @@ class DownloadBinaryRequestHandler(BaseHandler): found = False for image in idedata.extra_flash_images: - if image.path.endswith(file_name): + if image.path.as_posix().endswith(file_name): path = image.path download_name = file_name found = True diff --git a/tests/dashboard/test_web_server.py b/tests/dashboard/test_web_server.py index 7642876ee5..9ea7a5164b 100644 --- a/tests/dashboard/test_web_server.py +++ b/tests/dashboard/test_web_server.py @@ -8,6 +8,7 @@ import gzip import json import os from pathlib import Path +import sys from unittest.mock import AsyncMock, MagicMock, Mock, patch import pytest @@ -421,7 +422,7 @@ async def test_download_binary_handler_idedata_fallback( # Mock idedata response mock_image = Mock() - mock_image.path = str(bootloader_file) + mock_image.path = bootloader_file mock_idedata_instance = Mock() mock_idedata_instance.extra_flash_images = [mock_image] mock_idedata.return_value = mock_idedata_instance @@ -528,14 +529,22 @@ async def test_download_binary_handler_subdirectory_file_url_encoded( @pytest.mark.asyncio @pytest.mark.usefixtures("mock_ext_storage_path") @pytest.mark.parametrize( - "attack_path", + ("attack_path", "expected_code"), [ - pytest.param("../../../secrets.yaml", id="basic_traversal"), - pytest.param("..%2F..%2F..%2Fsecrets.yaml", id="url_encoded"), - pytest.param("zephyr/../../../secrets.yaml", id="traversal_with_prefix"), - pytest.param("/etc/passwd", id="absolute_path"), - pytest.param("//etc/passwd", id="double_slash_absolute"), - pytest.param("....//secrets.yaml", id="multiple_dots"), + pytest.param("../../../secrets.yaml", 403, id="basic_traversal"), + pytest.param("..%2F..%2F..%2Fsecrets.yaml", 403, id="url_encoded"), + pytest.param("zephyr/../../../secrets.yaml", 403, id="traversal_with_prefix"), + pytest.param("/etc/passwd", 403, id="absolute_path"), + pytest.param("//etc/passwd", 403, id="double_slash_absolute"), + pytest.param( + "....//secrets.yaml", + # On Windows, Path.resolve() treats "..." and "...." as parent + # traversal (like ".."), so the path escapes base_dir -> 403. + # On Unix, "...." is a literal directory name that stays inside + # base_dir but doesn't exist -> 404. + 403 if sys.platform == "win32" else 404, + id="multiple_dots", + ), ], ) async def test_download_binary_handler_path_traversal_protection( @@ -543,11 +552,14 @@ async def test_download_binary_handler_path_traversal_protection( tmp_path: Path, mock_storage_json: MagicMock, attack_path: str, + expected_code: int, ) -> None: """Test that DownloadBinaryRequestHandler prevents path traversal attacks. - Verifies that attempts to use '..' in file paths are sanitized to prevent - accessing files outside the build directory. Tests multiple attack vectors. + Verifies that attempts to escape the build directory via '..' are rejected + using resolve()/relative_to() validation. Tests multiple attack vectors. + Real traversals that escape the base directory get 403. Paths like '....' + that resolve inside the base directory but don't exist get 404. """ # Create build structure build_dir = get_build_path(tmp_path, "test") @@ -565,14 +577,67 @@ async def test_download_binary_handler_path_traversal_protection( mock_storage.firmware_bin_path = firmware_file mock_storage_json.load.return_value = mock_storage - # Attempt path traversal attack - should be blocked - with pytest.raises(HTTPClientError) as exc_info: + # Mock async_run_system_command so paths that pass validation but don't exist + # return 404 deterministically without spawning a real subprocess. + with ( + patch( + "esphome.dashboard.web_server.async_run_system_command", + new_callable=AsyncMock, + return_value=(2, "", ""), + ), + pytest.raises(HTTPClientError) as exc_info, + ): await dashboard.fetch( f"/download.bin?configuration=test.yaml&file={attack_path}", method="GET", ) - # Should get 404 (file not found after sanitization) or 500 (idedata fails) - assert exc_info.value.code in (404, 500) + assert exc_info.value.code == expected_code + + +@pytest.mark.asyncio +@pytest.mark.usefixtures("mock_ext_storage_path") +async def test_download_binary_handler_no_firmware_bin_path( + dashboard: DashboardTestHelper, + mock_storage_json: MagicMock, +) -> None: + """Test that download returns 404 when firmware_bin_path is None. + + This covers configs created by StorageJSON.from_wizard() where no + firmware has been compiled yet. + """ + mock_storage = Mock() + mock_storage.name = "test_device" + mock_storage.firmware_bin_path = None + mock_storage_json.load.return_value = mock_storage + + with pytest.raises(HTTPClientError) as exc_info: + await dashboard.fetch( + "/download.bin?configuration=test.yaml&file=firmware.bin", + method="GET", + ) + assert exc_info.value.code == 404 + + +@pytest.mark.asyncio +@pytest.mark.usefixtures("mock_ext_storage_path") +@pytest.mark.parametrize("file_value", ["", "%20%20", "%20"]) +async def test_download_binary_handler_empty_file_name( + dashboard: DashboardTestHelper, + mock_storage_json: MagicMock, + file_value: str, +) -> None: + """Test that download returns 400 for empty or whitespace-only file names.""" + mock_storage = Mock() + mock_storage.name = "test_device" + mock_storage.firmware_bin_path = Path("/fake/firmware.bin") + mock_storage_json.load.return_value = mock_storage + + with pytest.raises(HTTPClientError) as exc_info: + await dashboard.fetch( + f"/download.bin?configuration=test.yaml&file={file_value}", + method="GET", + ) + assert exc_info.value.code == 400 @pytest.mark.asyncio From 5370687001745b2dfd590426eb3008158469a56b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:25:41 -0600 Subject: [PATCH 0565/2030] [wizard] Use secrets module for fallback AP password generation (#13864) --- esphome/wizard.py | 3 +-- tests/unit_tests/test_wizard.py | 13 ++++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/esphome/wizard.py b/esphome/wizard.py index 4b74847996..f83342cc6a 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -1,6 +1,5 @@ import base64 from pathlib import Path -import random import secrets import string from typing import Literal, NotRequired, TypedDict, Unpack @@ -130,7 +129,7 @@ def wizard_file(**kwargs: Unpack[WizardFileKwargs]) -> str: if len(ap_name) > 32: ap_name = ap_name_base kwargs["fallback_name"] = ap_name - kwargs["fallback_psk"] = "".join(random.choice(letters) for _ in range(12)) + kwargs["fallback_psk"] = "".join(secrets.choice(letters) for _ in range(12)) base = BASE_CONFIG_FRIENDLY if kwargs.get("friendly_name") else BASE_CONFIG diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index eb44c1c20f..0ce89230d8 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -2,7 +2,7 @@ from pathlib import Path from typing import Any -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch import pytest from pytest import MonkeyPatch @@ -632,3 +632,14 @@ def test_wizard_accepts_rpipico_board(tmp_path: Path, monkeypatch: MonkeyPatch): # rpipico doesn't support WiFi, so no api_encryption_key or ota_password assert "api_encryption_key" not in call_kwargs assert "ota_password" not in call_kwargs + + +def test_fallback_psk_uses_secrets_choice( + default_config: dict[str, Any], +) -> None: + """Test that fallback PSK is generated using secrets.choice.""" + with patch("esphome.wizard.secrets.choice", return_value="X") as mock_choice: + config = wz.wizard_file(**default_config) + + assert 'password: "XXXXXXXXXXXX"' in config + assert mock_choice.call_count == 12 From e24528c842f6cbab9b71a07d6d738006fd5dd509 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:25:59 -0600 Subject: [PATCH 0566/2030] [analyze-memory] Attribute CSWTCH symbols from SDK archives (#13850) --- esphome/analyze_memory/__init__.py | 156 +++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 42 deletions(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index d8c941e76f..d8abc8bafb 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -397,47 +397,38 @@ class MemoryAnalyzer: return pioenvs_dir return None - def _scan_cswtch_in_objects( - self, obj_dir: Path - ) -> dict[str, list[tuple[str, int]]]: - """Scan object files for CSWTCH symbols using a single nm invocation. + @staticmethod + def _parse_nm_cswtch_output( + output: str, + base_dir: Path | None, + cswtch_map: dict[str, list[tuple[str, int]]], + ) -> None: + """Parse nm output for CSWTCH symbols and add to cswtch_map. - Uses ``nm --print-file-name -S`` on all ``.o`` files at once. - Output format: ``/path/to/file.o:address size type name`` + Handles both ``.o`` files and ``.a`` archives. + + nm output formats:: + + .o files: /path/file.o:hex_addr hex_size type name + .a files: /path/lib.a:member.o:hex_addr hex_size type name + + For ``.o`` files, paths are made relative to *base_dir* when possible. + For ``.a`` archives (detected by ``:`` in the file portion), paths are + formatted as ``archive_stem/member.o`` (e.g. ``liblwip2-536-feat/lwip-esp.o``). Args: - obj_dir: Directory containing object files (.pioenvs/<env>/) - - Returns: - Dict mapping "CSWTCH$NNN:size" to list of (source_file, size) tuples. + output: Raw stdout from ``nm --print-file-name -S``. + base_dir: Base directory for computing relative paths of ``.o`` files. + Pass ``None`` when scanning archives outside the build tree. + cswtch_map: Dict to populate, mapping ``"CSWTCH$N:size"`` to source list. """ - cswtch_map: dict[str, list[tuple[str, int]]] = defaultdict(list) - - if not self.nm_path: - return cswtch_map - - # Find all .o files recursively, sorted for deterministic output - obj_files = sorted(obj_dir.rglob("*.o")) - if not obj_files: - return cswtch_map - - _LOGGER.debug("Scanning %d object files for CSWTCH symbols", len(obj_files)) - - # Single nm call with --print-file-name for all object files - result = run_tool( - [self.nm_path, "--print-file-name", "-S"] + [str(f) for f in obj_files], - timeout=30, - ) - if result is None or result.returncode != 0: - return cswtch_map - - for line in result.stdout.splitlines(): + for line in output.splitlines(): if "CSWTCH$" not in line: continue # Split on last ":" that precedes a hex address. - # nm --print-file-name format: filepath:hex_addr hex_size type name - # We split from the right: find the last colon followed by hex digits. + # For .o: "filepath.o" : "hex_addr hex_size type name" + # For .a: "filepath.a:member.o" : "hex_addr hex_size type name" parts_after_colon = line.rsplit(":", 1) if len(parts_after_colon) != 2: continue @@ -457,16 +448,89 @@ class MemoryAnalyzer: except ValueError: continue - # Get relative path from obj_dir for readability - try: - rel_path = str(Path(file_path).relative_to(obj_dir)) - except ValueError: + # Determine readable source path + # Use ".a:" to detect archive format (not bare ":" which matches + # Windows drive letters like "C:\...\file.o"). + if ".a:" in file_path: + # Archive format: "archive.a:member.o" → "archive_stem/member.o" + archive_part, member = file_path.rsplit(":", 1) + archive_name = Path(archive_part).stem + rel_path = f"{archive_name}/{member}" + elif base_dir is not None: + try: + rel_path = str(Path(file_path).relative_to(base_dir)) + except ValueError: + rel_path = file_path + else: rel_path = file_path key = f"{sym_name}:{size}" cswtch_map[key].append((rel_path, size)) - return cswtch_map + def _run_nm_cswtch_scan( + self, + files: list[Path], + base_dir: Path | None, + cswtch_map: dict[str, list[tuple[str, int]]], + ) -> None: + """Run nm on *files* and add any CSWTCH symbols to *cswtch_map*. + + Args: + files: Object (``.o``) or archive (``.a``) files to scan. + base_dir: Base directory for relative path computation (see + :meth:`_parse_nm_cswtch_output`). + cswtch_map: Dict to populate with results. + """ + if not self.nm_path or not files: + return + + _LOGGER.debug("Scanning %d files for CSWTCH symbols", len(files)) + + result = run_tool( + [self.nm_path, "--print-file-name", "-S"] + [str(f) for f in files], + timeout=30, + ) + if result is None or result.returncode != 0: + _LOGGER.debug( + "nm failed or timed out scanning %d files for CSWTCH symbols", + len(files), + ) + return + + self._parse_nm_cswtch_output(result.stdout, base_dir, cswtch_map) + + def _scan_cswtch_in_sdk_archives( + self, cswtch_map: dict[str, list[tuple[str, int]]] + ) -> None: + """Scan SDK library archives (.a) for CSWTCH symbols. + + Prebuilt SDK libraries (e.g. lwip, bearssl) are not compiled from source, + so their CSWTCH symbols only exist inside ``.a`` archives. Results are + merged into *cswtch_map* for keys not already found in ``.o`` files. + + The same source file (e.g. ``lwip-esp.o``) often appears in multiple + library variants (``liblwip2-536.a``, ``liblwip2-1460-feat.a``, etc.), + so results are deduplicated by member name. + """ + sdk_dirs = self._find_sdk_library_dirs() + if not sdk_dirs: + return + + sdk_archives = sorted(a for sdk_dir in sdk_dirs for a in sdk_dir.glob("*.a")) + + sdk_map: dict[str, list[tuple[str, int]]] = defaultdict(list) + self._run_nm_cswtch_scan(sdk_archives, None, sdk_map) + + # Merge SDK results, deduplicating by member name. + for key, sources in sdk_map.items(): + if key in cswtch_map: + continue + seen: dict[str, tuple[str, int]] = {} + for path, sz in sources: + member = Path(path).name + if member not in seen: + seen[member] = (path, sz) + cswtch_map[key] = list(seen.values()) def _source_file_to_component(self, source_file: str) -> str: """Map a source object file path to its component name. @@ -505,17 +569,25 @@ class MemoryAnalyzer: CSWTCH symbols are compiler-generated lookup tables for switch statements. They are local symbols, so the same name can appear in different object files. - This method scans .o files to attribute them to their source components. + This method scans .o files and SDK archives to attribute them to their + source components. """ obj_dir = self._find_object_files_dir() if obj_dir is None: _LOGGER.debug("No object files directory found, skipping CSWTCH analysis") return - # Scan object files for CSWTCH symbols - cswtch_map = self._scan_cswtch_in_objects(obj_dir) + # Scan build-dir object files for CSWTCH symbols + cswtch_map: dict[str, list[tuple[str, int]]] = defaultdict(list) + self._run_nm_cswtch_scan(sorted(obj_dir.rglob("*.o")), obj_dir, cswtch_map) + + # Also scan SDK library archives (.a) for CSWTCH symbols. + # Prebuilt SDK libraries (e.g. lwip, bearssl) are not compiled from source + # so their symbols only exist inside .a archives, not as loose .o files. + self._scan_cswtch_in_sdk_archives(cswtch_map) + if not cswtch_map: - _LOGGER.debug("No CSWTCH symbols found in object files") + _LOGGER.debug("No CSWTCH symbols found in object files or SDK archives") return # Collect CSWTCH symbols from the ELF (already parsed in sections) From 46f8302d8ff4aa8acf9751d0df948f86e4b61aa0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:26:15 -0600 Subject: [PATCH 0567/2030] [mqtt] Use stack buffer for discovery topic to avoid heap allocation (#13812) --- esphome/components/mqtt/mqtt_component.cpp | 21 +++++++++++---------- esphome/components/mqtt/mqtt_component.h | 9 +++++++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index e4b80de50a..8cf393e2df 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -34,10 +34,7 @@ inline char *append_char(char *p, char c) { // MQTT_COMPONENT_TYPE_MAX_LEN, MQTT_SUFFIX_MAX_LEN, and MQTT_DEFAULT_TOPIC_MAX_LEN are in mqtt_component.h. // ESPHOME_DEVICE_NAME_MAX_LEN and OBJECT_ID_MAX_LEN are defined in entity_base.h. // This ensures the stack buffers below are always large enough. -static constexpr size_t DISCOVERY_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) -// Format: prefix + "/" + type + "/" + name + "/" + object_id + "/config" + null -static constexpr size_t DISCOVERY_TOPIC_MAX_LEN = DISCOVERY_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + - ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 7 + 1; +// MQTT_DISCOVERY_PREFIX_MAX_LEN and MQTT_DISCOVERY_TOPIC_MAX_LEN are defined in mqtt_component.h // Function implementation of LOG_MQTT_COMPONENT macro to reduce code size void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, bool command_topic) { @@ -54,15 +51,15 @@ void MQTTComponent::set_subscribe_qos(uint8_t qos) { this->subscribe_qos_ = qos; void MQTTComponent::set_retain(bool retain) { this->retain_ = retain; } -std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const { +StringRef MQTTComponent::get_discovery_topic_to_(std::span<char, MQTT_DISCOVERY_TOPIC_MAX_LEN> buf, + const MQTTDiscoveryInfo &discovery_info) const { char sanitized_name[ESPHOME_DEVICE_NAME_MAX_LEN + 1]; str_sanitize_to(sanitized_name, App.get_name().c_str()); const char *comp_type = this->component_type(); char object_id_buf[OBJECT_ID_MAX_LEN]; StringRef object_id = this->get_default_object_id_to_(object_id_buf); - char buf[DISCOVERY_TOPIC_MAX_LEN]; - char *p = buf; + char *p = buf.data(); p = append_str(p, discovery_info.prefix.data(), discovery_info.prefix.size()); p = append_char(p, '/'); @@ -72,8 +69,9 @@ std::string MQTTComponent::get_discovery_topic_(const MQTTDiscoveryInfo &discove p = append_char(p, '/'); p = append_str(p, object_id.c_str(), object_id.size()); p = append_str(p, "/config", 7); + *p = '\0'; - return std::string(buf, p - buf); + return StringRef(buf.data(), p - buf.data()); } StringRef MQTTComponent::get_default_topic_for_to_(std::span<char, MQTT_DEFAULT_TOPIC_MAX_LEN> buf, const char *suffix, @@ -182,16 +180,19 @@ bool MQTTComponent::publish_json(const char *topic, const json::json_build_t &f) bool MQTTComponent::send_discovery_() { const MQTTDiscoveryInfo &discovery_info = global_mqtt_client->get_discovery_info(); + char discovery_topic_buf[MQTT_DISCOVERY_TOPIC_MAX_LEN]; + StringRef discovery_topic = this->get_discovery_topic_to_(discovery_topic_buf, discovery_info); + if (discovery_info.clean) { ESP_LOGV(TAG, "'%s': Cleaning discovery", this->friendly_name_().c_str()); - return global_mqtt_client->publish(this->get_discovery_topic_(discovery_info), "", 0, this->qos_, true); + return global_mqtt_client->publish(discovery_topic.c_str(), "", 0, this->qos_, true); } ESP_LOGV(TAG, "'%s': Sending discovery", this->friendly_name_().c_str()); // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return global_mqtt_client->publish_json( - this->get_discovery_topic_(discovery_info), + discovery_topic.c_str(), [this](JsonObject root) { SendDiscoveryConfig config; config.state_topic = true; diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 2cec6fda7e..76375fb106 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -32,6 +32,10 @@ static constexpr size_t MQTT_TOPIC_PREFIX_MAX_LEN = 64; // Validated in Python: // Format: prefix + "/" + type + "/" + object_id + "/" + suffix + null static constexpr size_t MQTT_DEFAULT_TOPIC_MAX_LEN = MQTT_TOPIC_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1 + MQTT_SUFFIX_MAX_LEN + 1; +static constexpr size_t MQTT_DISCOVERY_PREFIX_MAX_LEN = 64; // Validated in Python: cv.Length(max=64) +// Format: prefix + "/" + type + "/" + name + "/" + object_id + "/config" + null +static constexpr size_t MQTT_DISCOVERY_TOPIC_MAX_LEN = MQTT_DISCOVERY_PREFIX_MAX_LEN + 1 + MQTT_COMPONENT_TYPE_MAX_LEN + + 1 + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 7 + 1; class MQTTComponent; // Forward declaration void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, bool command_topic); @@ -263,8 +267,9 @@ class MQTTComponent : public Component { void subscribe_json(const std::string &topic, const mqtt_json_callback_t &callback, uint8_t qos = 0); protected: - /// Helper method to get the discovery topic for this component. - std::string get_discovery_topic_(const MQTTDiscoveryInfo &discovery_info) const; + /// Helper method to get the discovery topic for this component into a buffer. + StringRef get_discovery_topic_to_(std::span<char, MQTT_DISCOVERY_TOPIC_MAX_LEN> buf, + const MQTTDiscoveryInfo &discovery_info) const; /** Get this components state/command/... topic into a buffer. * From c3c0c40524105ad3165581b2c8241dc1990201cf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:26:29 -0600 Subject: [PATCH 0568/2030] [mqtt] Return friendly_name_() by const reference to avoid string copies (#13810) --- esphome/components/mqtt/mqtt_component.cpp | 6 +++--- esphome/components/mqtt/mqtt_component.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 8cf393e2df..09570106df 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -205,7 +205,7 @@ bool MQTTComponent::send_discovery_() { } // Fields from EntityBase - root[MQTT_NAME] = this->get_entity()->has_own_name() ? this->friendly_name_() : ""; + root[MQTT_NAME] = this->get_entity()->has_own_name() ? this->friendly_name_() : StringRef(); if (this->is_disabled_by_default_()) root[MQTT_ENABLED_BY_DEFAULT] = false; @@ -249,7 +249,7 @@ bool MQTTComponent::send_discovery_() { if (discovery_info.unique_id_generator == MQTT_MAC_ADDRESS_UNIQUE_ID_GENERATOR) { char friendly_name_hash[9]; buf_append_printf(friendly_name_hash, sizeof(friendly_name_hash), 0, "%08" PRIx32, - fnv1_hash(this->friendly_name_())); + fnv1_hash(this->friendly_name_().c_str())); // Format: mac-component_type-hash (e.g. "aabbccddeeff-sensor-12345678") // MAC (12) + "-" (1) + domain (max 20) + "-" (1) + hash (8) + null (1) = 43 char unique_id[MAC_ADDRESS_BUFFER_SIZE + ESPHOME_DOMAIN_MAX_LEN + 11]; @@ -415,7 +415,7 @@ void MQTTComponent::schedule_resend_state() { this->resend_state_ = true; } bool MQTTComponent::is_connected_() const { return global_mqtt_client->is_connected(); } // Pull these properties from EntityBase if not overridden -std::string MQTTComponent::friendly_name_() const { return this->get_entity()->get_name(); } +const StringRef &MQTTComponent::friendly_name_() const { return this->get_entity()->get_name(); } StringRef MQTTComponent::get_default_object_id_to_(std::span<char, OBJECT_ID_MAX_LEN> buf) const { return this->get_entity()->get_object_id_to(buf); } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 76375fb106..eb98158647 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -293,7 +293,7 @@ class MQTTComponent : public Component { virtual const EntityBase *get_entity() const = 0; /// Get the friendly name of this MQTT component. - std::string friendly_name_() const; + const StringRef &friendly_name_() const; /// Get the icon field of this component as StringRef StringRef get_icon_ref_() const; From 422f413680690b257429a4c4f8b51a700bee40e8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:26:44 -0600 Subject: [PATCH 0569/2030] [lps22] Replace set_retry with set_interval to avoid heap allocation (#13841) --- esphome/components/lps22/lps22.cpp | 14 ++++++++++---- esphome/components/lps22/lps22.h | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/esphome/components/lps22/lps22.cpp b/esphome/components/lps22/lps22.cpp index 526286ba72..7fc5774b08 100644 --- a/esphome/components/lps22/lps22.cpp +++ b/esphome/components/lps22/lps22.cpp @@ -38,22 +38,29 @@ void LPS22Component::dump_config() { LOG_UPDATE_INTERVAL(this); } +static constexpr uint32_t INTERVAL_READ = 0; + void LPS22Component::update() { uint8_t value = 0x00; this->read_register(CTRL_REG2, &value, 1); value |= CTRL_REG2_ONE_SHOT_MASK; this->write_register(CTRL_REG2, &value, 1); - this->set_retry(READ_INTERVAL, READ_ATTEMPTS, [this](uint8_t _) { return this->try_read_(); }); + this->read_attempts_remaining_ = READ_ATTEMPTS; + this->set_interval(INTERVAL_READ, READ_INTERVAL, [this]() { this->try_read_(); }); } -RetryResult LPS22Component::try_read_() { +void LPS22Component::try_read_() { uint8_t value = 0x00; this->read_register(STATUS, &value, 1); const uint8_t expected_status_mask = STATUS_T_DA_MASK | STATUS_P_DA_MASK; if ((value & expected_status_mask) != expected_status_mask) { ESP_LOGD(TAG, "STATUS not ready: %x", value); - return RetryResult::RETRY; + if (--this->read_attempts_remaining_ == 0) { + this->cancel_interval(INTERVAL_READ); + } + return; } + this->cancel_interval(INTERVAL_READ); if (this->temperature_sensor_ != nullptr) { uint8_t t_buf[2]{0}; @@ -68,7 +75,6 @@ RetryResult LPS22Component::try_read_() { uint32_t p_lsb = encode_uint24(p_buf[2], p_buf[1], p_buf[0]); this->pressure_sensor_->publish_state(PRESSURE_SCALE * static_cast<float>(p_lsb)); } - return RetryResult::DONE; } } // namespace lps22 diff --git a/esphome/components/lps22/lps22.h b/esphome/components/lps22/lps22.h index 549ea524ea..95ee4ad442 100644 --- a/esphome/components/lps22/lps22.h +++ b/esphome/components/lps22/lps22.h @@ -17,10 +17,11 @@ class LPS22Component : public sensor::Sensor, public PollingComponent, public i2 void dump_config() override; protected: + void try_read_(); + sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *pressure_sensor_{nullptr}; - - RetryResult try_read_(); + uint8_t read_attempts_remaining_{0}; }; } // namespace lps22 From bed01da345c6c652ef464d800aa2c8152c9681a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 03:45:40 -0600 Subject: [PATCH 0570/2030] [api] Guard varint parsing against overlong encodings (#13870) --- esphome/components/api/proto.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 92978f765f..41ea0043f9 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -112,8 +112,12 @@ class ProtoVarInt { uint64_t result = buffer[0] & 0x7F; uint8_t bitpos = 7; + // A 64-bit varint is at most 10 bytes (ceil(64/7)). Reject overlong encodings + // to avoid undefined behavior from shifting uint64_t by >= 64 bits. + uint32_t max_len = std::min(len, uint32_t(10)); + // Start from the second byte since we've already processed the first - for (uint32_t i = 1; i < len; i++) { + for (uint32_t i = 1; i < max_len; i++) { uint8_t val = buffer[i]; result |= uint64_t(val & 0x7F) << uint64_t(bitpos); bitpos += 7; From fb9328372028c941d7a1c1bc446efbf157c835d0 Mon Sep 17 00:00:00 2001 From: tronikos <tronikos@users.noreply.github.com> Date: Mon, 9 Feb 2026 01:52:49 -0800 Subject: [PATCH 0571/2030] [water_heater] Add state masking to distinguish explicit commands from no-change (#13879) --- .../components/water_heater/water_heater.cpp | 18 ++++++++++++------ esphome/components/water_heater/water_heater.h | 4 ++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index e6d1562352..9d7ae0cbc0 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -65,6 +65,7 @@ WaterHeaterCall &WaterHeaterCall::set_away(bool away) { } else { this->state_ &= ~WATER_HEATER_STATE_AWAY; } + this->state_mask_ |= WATER_HEATER_STATE_AWAY; return *this; } @@ -74,6 +75,7 @@ WaterHeaterCall &WaterHeaterCall::set_on(bool on) { } else { this->state_ &= ~WATER_HEATER_STATE_ON; } + this->state_mask_ |= WATER_HEATER_STATE_ON; return *this; } @@ -92,11 +94,11 @@ void WaterHeaterCall::perform() { if (!std::isnan(this->target_temperature_high_)) { ESP_LOGD(TAG, " Target Temperature High: %.2f", this->target_temperature_high_); } - if (this->state_ & WATER_HEATER_STATE_AWAY) { - ESP_LOGD(TAG, " Away: YES"); + if (this->state_mask_ & WATER_HEATER_STATE_AWAY) { + ESP_LOGD(TAG, " Away: %s", (this->state_ & WATER_HEATER_STATE_AWAY) ? "YES" : "NO"); } - if (this->state_ & WATER_HEATER_STATE_ON) { - ESP_LOGD(TAG, " On: YES"); + if (this->state_mask_ & WATER_HEATER_STATE_ON) { + ESP_LOGD(TAG, " On: %s", (this->state_ & WATER_HEATER_STATE_ON) ? "YES" : "NO"); } this->parent_->control(*this); } @@ -137,13 +139,17 @@ void WaterHeaterCall::validate_() { this->target_temperature_high_ = NAN; } } - if ((this->state_ & WATER_HEATER_STATE_AWAY) && !traits.get_supports_away_mode()) { - ESP_LOGW(TAG, "'%s' - Away mode not supported", this->parent_->get_name().c_str()); + if (!traits.get_supports_away_mode()) { + if (this->state_ & WATER_HEATER_STATE_AWAY) { + ESP_LOGW(TAG, "'%s' - Away mode not supported", this->parent_->get_name().c_str()); + } this->state_ &= ~WATER_HEATER_STATE_AWAY; + this->state_mask_ &= ~WATER_HEATER_STATE_AWAY; } // If ON/OFF not supported, device is always on - clear the flag silently if (!traits.has_feature_flags(WATER_HEATER_SUPPORTS_ON_OFF)) { this->state_ &= ~WATER_HEATER_STATE_ON; + this->state_mask_ &= ~WATER_HEATER_STATE_ON; } } diff --git a/esphome/components/water_heater/water_heater.h b/esphome/components/water_heater/water_heater.h index 7bd05ba7f5..93fcf5f401 100644 --- a/esphome/components/water_heater/water_heater.h +++ b/esphome/components/water_heater/water_heater.h @@ -91,6 +91,8 @@ class WaterHeaterCall { float get_target_temperature_high() const { return this->target_temperature_high_; } /// Get state flags value uint32_t get_state() const { return this->state_; } + /// Get mask of state flags that are being changed + uint32_t get_state_mask() const { return this->state_mask_; } protected: void validate_(); @@ -100,6 +102,7 @@ class WaterHeaterCall { float target_temperature_low_{NAN}; float target_temperature_high_{NAN}; uint32_t state_{0}; + uint32_t state_mask_{0}; }; struct WaterHeaterCallInternal : public WaterHeaterCall { @@ -111,6 +114,7 @@ struct WaterHeaterCallInternal : public WaterHeaterCall { this->target_temperature_low_ = restore.target_temperature_low_; this->target_temperature_high_ = restore.target_temperature_high_; this->state_ = restore.state_; + this->state_mask_ = restore.state_mask_; return *this; } }; From 790ac620ab10a228ac54ae0caedf7669650ff9e2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 06:42:12 -0600 Subject: [PATCH 0572/2030] [web_server_idf] Use C++17 nested namespace style (#13856) --- esphome/components/web_server_idf/multipart.cpp | 6 ++---- esphome/components/web_server_idf/multipart.h | 6 ++---- esphome/components/web_server_idf/utils.cpp | 6 ++---- esphome/components/web_server_idf/utils.h | 6 ++---- esphome/components/web_server_idf/web_server_idf.cpp | 6 ++---- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/esphome/components/web_server_idf/multipart.cpp b/esphome/components/web_server_idf/multipart.cpp index 2092a41a8e..52dafeb997 100644 --- a/esphome/components/web_server_idf/multipart.cpp +++ b/esphome/components/web_server_idf/multipart.cpp @@ -6,8 +6,7 @@ #include <cstring> #include "multipart_parser.h" -namespace esphome { -namespace web_server_idf { +namespace esphome::web_server_idf { static const char *const TAG = "multipart"; @@ -249,6 +248,5 @@ std::string str_trim(const std::string &str) { return str.substr(start, end - start + 1); } -} // namespace web_server_idf -} // namespace esphome +} // namespace esphome::web_server_idf #endif // defined(USE_ESP32) && defined(USE_WEBSERVER_OTA) diff --git a/esphome/components/web_server_idf/multipart.h b/esphome/components/web_server_idf/multipart.h index 8fbe90c4a0..9008be6459 100644 --- a/esphome/components/web_server_idf/multipart.h +++ b/esphome/components/web_server_idf/multipart.h @@ -10,8 +10,7 @@ #include <string> #include <utility> -namespace esphome { -namespace web_server_idf { +namespace esphome::web_server_idf { // Wrapper around zorxx/multipart-parser for ESP-IDF OTA uploads class MultipartReader { @@ -81,6 +80,5 @@ bool parse_multipart_boundary(const char *content_type, const char **boundary_st // Trim whitespace from both ends of a string std::string str_trim(const std::string &str); -} // namespace web_server_idf -} // namespace esphome +} // namespace esphome::web_server_idf #endif // defined(USE_ESP32) && defined(USE_WEBSERVER_OTA) diff --git a/esphome/components/web_server_idf/utils.cpp b/esphome/components/web_server_idf/utils.cpp index d3c3c3dc55..a1a2793b4a 100644 --- a/esphome/components/web_server_idf/utils.cpp +++ b/esphome/components/web_server_idf/utils.cpp @@ -8,8 +8,7 @@ #include "utils.h" -namespace esphome { -namespace web_server_idf { +namespace esphome::web_server_idf { static const char *const TAG = "web_server_idf_utils"; @@ -119,6 +118,5 @@ const char *stristr(const char *haystack, const char *needle) { return nullptr; } -} // namespace web_server_idf -} // namespace esphome +} // namespace esphome::web_server_idf #endif // USE_ESP32 diff --git a/esphome/components/web_server_idf/utils.h b/esphome/components/web_server_idf/utils.h index ae58f82398..bb0610dac0 100644 --- a/esphome/components/web_server_idf/utils.h +++ b/esphome/components/web_server_idf/utils.h @@ -5,8 +5,7 @@ #include <string> #include "esphome/core/helpers.h" -namespace esphome { -namespace web_server_idf { +namespace esphome::web_server_idf { /// Decode URL-encoded string in-place (e.g., %20 -> space, + -> space) /// Returns the new length of the decoded string @@ -29,6 +28,5 @@ bool str_ncmp_ci(const char *s1, const char *s2, size_t n); // Case-insensitive string search (like strstr but case-insensitive) const char *stristr(const char *haystack, const char *needle); -} // namespace web_server_idf -} // namespace esphome +} // namespace esphome::web_server_idf #endif // USE_ESP32 diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 39e6b7a790..ac7f99bef7 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -30,8 +30,7 @@ #include <cerrno> #include <sys/socket.h> -namespace esphome { -namespace web_server_idf { +namespace esphome::web_server_idf { #ifndef HTTPD_409 #define HTTPD_409 "409 Conflict" @@ -895,7 +894,6 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c } #endif // USE_WEBSERVER_OTA -} // namespace web_server_idf -} // namespace esphome +} // namespace esphome::web_server_idf #endif // !defined(USE_ESP32) From 22c77866d89da64ab96c830c716225d700b33906 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 06:42:26 -0600 Subject: [PATCH 0573/2030] [e131] Remove unnecessary heap allocation from packet receive loop (#13852) --- esphome/components/e131/e131.cpp | 7 ++----- esphome/components/e131/e131.h | 2 +- esphome/components/e131/e131_packet.cpp | 6 +++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index f11e7f4fe3..4187857901 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -55,7 +55,6 @@ void E131Component::setup() { } void E131Component::loop() { - std::vector<uint8_t> payload; E131Packet packet; int universe = 0; uint8_t buf[1460]; @@ -64,11 +63,9 @@ void E131Component::loop() { if (len == -1) { return; } - payload.resize(len); - memmove(&payload[0], buf, len); - if (!this->packet_(payload, universe, packet)) { - ESP_LOGV(TAG, "Invalid packet received of size %zu.", payload.size()); + if (!this->packet_(buf, (size_t) len, universe, packet)) { + ESP_LOGV(TAG, "Invalid packet received of size %zd.", len); return; } diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index 831138a545..d4b272eae2 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -38,7 +38,7 @@ class E131Component : public esphome::Component { void set_method(E131ListenMethod listen_method) { this->listen_method_ = listen_method; } protected: - bool packet_(const std::vector<uint8_t> &data, int &universe, E131Packet &packet); + bool packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet); bool process_(int universe, const E131Packet &packet); bool join_igmp_groups_(); void join_(int universe); diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index e663a3d0fc..ed081e5758 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -116,11 +116,11 @@ void E131Component::leave_(int universe) { ESP_LOGD(TAG, "Left %d universe for E1.31.", universe); } -bool E131Component::packet_(const std::vector<uint8_t> &data, int &universe, E131Packet &packet) { - if (data.size() < E131_MIN_PACKET_SIZE) +bool E131Component::packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet) { + if (len < E131_MIN_PACKET_SIZE) return false; - auto *sbuff = reinterpret_cast<const E131RawPacket *>(&data[0]); + auto *sbuff = reinterpret_cast<const E131RawPacket *>(data); if (memcmp(sbuff->acn_id, ACN_ID, sizeof(sbuff->acn_id)) != 0) return false; From 4ef238eb7b563a4a0aec21b4dd492a64543824aa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:26:03 -0600 Subject: [PATCH 0574/2030] [analyze-memory] Attribute third-party library symbols via nm scanning (#13878) --- esphome/analyze_memory/__init__.py | 366 ++++++++++++++++++++++++++++- esphome/analyze_memory/cli.py | 14 +- 2 files changed, 374 insertions(+), 6 deletions(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index d8abc8bafb..bf1bcbfa05 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -43,6 +43,7 @@ _READELF_SECTION_PATTERN = re.compile( # Component category prefixes _COMPONENT_PREFIX_ESPHOME = "[esphome]" _COMPONENT_PREFIX_EXTERNAL = "[external]" +_COMPONENT_PREFIX_LIB = "[lib]" _COMPONENT_CORE = f"{_COMPONENT_PREFIX_ESPHOME}core" _COMPONENT_API = f"{_COMPONENT_PREFIX_ESPHOME}api" @@ -56,6 +57,16 @@ SymbolInfoType = tuple[str, int, str] # RAM sections - symbols in these sections consume RAM RAM_SECTIONS = frozenset([".data", ".bss"]) +# nm symbol types for global/weak defined symbols (used for library symbol mapping) +# Only global (uppercase) and weak symbols are safe to use - local symbols (lowercase) +# can have name collisions across compilation units +_NM_DEFINED_GLOBAL_TYPES = frozenset({"T", "D", "B", "R", "W", "V"}) + +# Pattern matching compiler-generated local names that can collide across compilation +# units (e.g., packet$19, buf$20, flag$5261). These are unsafe for name-based lookup. +# Does NOT match mangled C++ names with optimization suffixes (e.g., func$isra$0). +_COMPILER_LOCAL_PATTERN = re.compile(r"^[a-zA-Z_]\w*\$\d+$") + @dataclass class MemorySection: @@ -179,11 +190,19 @@ class MemoryAnalyzer: self._sdk_symbols: list[SDKSymbol] = [] # CSWTCH symbols: list of (name, size, source_file, component) self._cswtch_symbols: list[tuple[str, int, str, str]] = [] + # Library symbol mapping: symbol_name -> library_name + self._lib_symbol_map: dict[str, str] = {} + # Library dir to name mapping: "lib641" -> "espsoftwareserial", + # "espressif__mdns" -> "mdns" + self._lib_hash_to_name: dict[str, str] = {} + # Heuristic category to library redirect: "mdns_lib" -> "[lib]mdns" + self._heuristic_to_lib: dict[str, str] = {} def analyze(self) -> dict[str, ComponentMemory]: """Analyze the ELF file and return component memory usage.""" self._parse_sections() self._parse_symbols() + self._scan_libraries() self._categorize_symbols() self._analyze_cswtch_symbols() self._analyze_sdk_libraries() @@ -328,15 +347,19 @@ class MemoryAnalyzer: # If no component match found, it's core return _COMPONENT_CORE + # Check library symbol map (more accurate than heuristic patterns) + if lib_name := self._lib_symbol_map.get(symbol_name): + return f"{_COMPONENT_PREFIX_LIB}{lib_name}" + # Check against symbol patterns for component, patterns in SYMBOL_PATTERNS.items(): if any(pattern in symbol_name for pattern in patterns): - return component + return self._heuristic_to_lib.get(component, component) # Check against demangled patterns for component, patterns in DEMANGLED_PATTERNS.items(): if any(pattern in demangled for pattern in patterns): - return component + return self._heuristic_to_lib.get(component, component) # Special cases that need more complex logic @@ -384,6 +407,327 @@ class MemoryAnalyzer: return "Other Core" + def _discover_pio_libraries( + self, + libraries: dict[str, list[Path]], + hash_to_name: dict[str, str], + ) -> None: + """Discover PlatformIO third-party libraries from the build directory. + + Scans ``lib<hex>/`` directories under ``.pioenvs/<env>/`` to find + library names and their ``.a`` archive or ``.o`` file paths. + + Args: + libraries: Dict to populate with library name -> file path list mappings. + Prefers ``.a`` archives when available, falls back to ``.o`` files + (e.g., pioarduino ESP32 Arduino builds only produce ``.o`` files). + hash_to_name: Dict to populate with dir name -> library name mappings + for CSWTCH attribution (e.g., ``lib641`` -> ``espsoftwareserial``). + """ + build_dir = self.elf_path.parent + + for entry in build_dir.iterdir(): + if not entry.is_dir() or not entry.name.startswith("lib"): + continue + # Validate that the suffix after "lib" is a hex hash + hex_part = entry.name[3:] + if not hex_part: + continue + try: + int(hex_part, 16) + except ValueError: + continue + + # Each lib<hex>/ directory contains a subdirectory named after the library + for lib_subdir in entry.iterdir(): + if not lib_subdir.is_dir(): + continue + lib_name = lib_subdir.name.lower() + + # Prefer .a archive (lib<LibraryName>.a), fall back to .o files + # e.g., lib72a/ESPAsyncTCP/... has lib72a/libESPAsyncTCP.a + archive = entry / f"lib{lib_subdir.name}.a" + if archive.exists(): + file_paths = [archive] + elif archives := list(entry.glob("*.a")): + # Case-insensitive fallback + file_paths = [archives[0]] + else: + # No .a archive (e.g., pioarduino CMake builds) - use .o files + file_paths = sorted(lib_subdir.rglob("*.o")) + + if file_paths: + libraries[lib_name] = file_paths + hash_to_name[entry.name] = lib_name + _LOGGER.debug( + "Discovered PlatformIO library: %s -> %s", + lib_subdir.name, + file_paths[0], + ) + + def _discover_idf_managed_components( + self, + libraries: dict[str, list[Path]], + hash_to_name: dict[str, str], + ) -> None: + """Discover ESP-IDF managed component libraries from the build directory. + + ESP-IDF managed components (from the IDF component registry) use a + ``<vendor>__<name>`` naming convention. Source files live under + ``managed_components/<vendor>__<name>/`` and the compiled archives are at + ``esp-idf/<vendor>__<name>/lib<vendor>__<name>.a``. + + Args: + libraries: Dict to populate with library name -> file path list mappings. + hash_to_name: Dict to populate with dir name -> library name mappings + for CSWTCH attribution (e.g., ``espressif__mdns`` -> ``mdns``). + """ + build_dir = self.elf_path.parent + + managed_dir = build_dir / "managed_components" + if not managed_dir.is_dir(): + return + + espidf_dir = build_dir / "esp-idf" + + for entry in managed_dir.iterdir(): + if not entry.is_dir() or "__" not in entry.name: + continue + + # Extract the short name: espressif__mdns -> mdns + full_name = entry.name # e.g., espressif__mdns + short_name = full_name.split("__", 1)[1].lower() + + # Find the .a archive under esp-idf/<vendor>__<name>/ + archive = espidf_dir / full_name / f"lib{full_name}.a" + if archive.exists(): + libraries[short_name] = [archive] + hash_to_name[full_name] = short_name + _LOGGER.debug( + "Discovered IDF managed component: %s -> %s", + short_name, + archive, + ) + + def _build_library_symbol_map( + self, libraries: dict[str, list[Path]] + ) -> dict[str, str]: + """Build a symbol-to-library mapping from library archives or object files. + + Runs ``nm --defined-only`` on each ``.a`` or ``.o`` file to collect + global and weak defined symbols. + + Args: + libraries: Dictionary mapping library name to list of file paths + (``.a`` archives or ``.o`` object files). + + Returns: + Dictionary mapping symbol name to library name. + """ + symbol_map: dict[str, str] = {} + + if not self.nm_path: + return symbol_map + + for lib_name, file_paths in libraries.items(): + result = run_tool( + [self.nm_path, "--defined-only", *(str(p) for p in file_paths)], + timeout=10, + ) + if result is None or result.returncode != 0: + continue + + for line in result.stdout.splitlines(): + parts = line.split() + if len(parts) < 3: + continue + + sym_type = parts[-2] + sym_name = parts[-1] + + # Include global defined symbols (uppercase) and weak symbols (W/V) + if sym_type in _NM_DEFINED_GLOBAL_TYPES: + symbol_map[sym_name] = lib_name + + return symbol_map + + @staticmethod + def _build_heuristic_to_lib_mapping( + library_names: set[str], + ) -> dict[str, str]: + """Build mapping from heuristic pattern categories to discovered libraries. + + Heuristic categories like ``mdns_lib``, ``web_server_lib``, ``async_tcp`` + exist as approximations for library attribution. When we discover the + actual library, symbols matching those heuristics should be redirected + to the ``[lib]`` category instead. + + The mapping is built by checking if the normalized category name + (stripped of ``_lib`` suffix and underscores) appears as a substring + of any discovered library name. + + Examples:: + + mdns_lib -> mdns -> in "mdns" or "esp8266mdns" -> [lib]mdns + web_server_lib -> webserver -> in "espasyncwebserver" -> [lib]espasyncwebserver + async_tcp -> asynctcp -> in "espasynctcp" -> [lib]espasynctcp + + Args: + library_names: Set of discovered library names (lowercase). + + Returns: + Dictionary mapping heuristic category to ``[lib]<name>`` string. + """ + mapping: dict[str, str] = {} + all_categories = set(SYMBOL_PATTERNS) | set(DEMANGLED_PATTERNS) + + for category in all_categories: + base = category.removesuffix("_lib").replace("_", "") + # Collect all libraries whose name contains the base string + candidates = [lib_name for lib_name in library_names if base in lib_name] + if not candidates: + continue + + # Choose a deterministic "best" match: + # 1. Prefer exact name matches over substring matches. + # 2. Among non-exact matches, prefer the shortest library name. + # 3. Break remaining ties lexicographically. + best_lib = min( + candidates, + key=lambda lib_name, _base=base: ( + lib_name != _base, + len(lib_name), + lib_name, + ), + ) + mapping[category] = f"{_COMPONENT_PREFIX_LIB}{best_lib}" + + if mapping: + _LOGGER.debug( + "Heuristic-to-library redirects: %s", + ", ".join(f"{k} -> {v}" for k, v in sorted(mapping.items())), + ) + + return mapping + + def _parse_map_file(self) -> dict[str, str] | None: + """Parse linker map file to build authoritative symbol-to-library mapping. + + The linker map file contains the definitive source attribution for every + symbol, including local/static ones that ``nm`` cannot safely export. + + Map file format (GNU ld):: + + .text._mdns_service_task + 0x400e9fdc 0x65c .pioenvs/env/esp-idf/espressif__mdns/libespressif__mdns.a(mdns.c.o) + + Each section entry has a ``.section.symbol_name`` line followed by an + indented line with address, size, and source path. + + Returns: + Symbol-to-library dict, or ``None`` if no usable map file exists. + """ + map_path = self.elf_path.with_suffix(".map") + if not map_path.exists() or map_path.stat().st_size < 10000: + return None + + _LOGGER.info("Parsing linker map file: %s", map_path.name) + + try: + map_text = map_path.read_text(encoding="utf-8", errors="replace") + except OSError as err: + _LOGGER.warning("Failed to read map file: %s", err) + return None + + symbol_map: dict[str, str] = {} + current_symbol: str | None = None + section_prefixes = (".text.", ".rodata.", ".data.", ".bss.", ".literal.") + + for line in map_text.splitlines(): + # Match section.symbol line: " .text.symbol_name" + # Single space indent, starts with dot + if len(line) > 2 and line[0] == " " and line[1] == ".": + stripped = line.strip() + for prefix in section_prefixes: + if stripped.startswith(prefix): + current_symbol = stripped[len(prefix) :] + break + else: + current_symbol = None + continue + + # Match source attribution line: " 0xADDR 0xSIZE source_path" + if current_symbol is None: + continue + + fields = line.split() + # Skip compiler-generated local names (e.g., packet$19, buf$20) + # that can collide across compilation units + if ( + len(fields) >= 3 + and fields[0].startswith("0x") + and fields[1].startswith("0x") + and not _COMPILER_LOCAL_PATTERN.match(current_symbol) + ): + source_path = fields[2] + # Check if source path contains a known library directory + for dir_key, lib_name in self._lib_hash_to_name.items(): + if dir_key in source_path: + symbol_map[current_symbol] = lib_name + break + + current_symbol = None + + return symbol_map or None + + def _scan_libraries(self) -> None: + """Discover third-party libraries and build symbol mapping. + + Scans both PlatformIO ``lib<hex>/`` directories (Arduino builds) and + ESP-IDF ``managed_components/`` (IDF builds) to find library archives. + + Uses the linker map file for authoritative symbol attribution when + available, falling back to ``nm`` scanning with heuristic redirects. + """ + libraries: dict[str, list[Path]] = {} + self._discover_pio_libraries(libraries, self._lib_hash_to_name) + self._discover_idf_managed_components(libraries, self._lib_hash_to_name) + + if not libraries: + _LOGGER.debug("No third-party libraries found") + return + + _LOGGER.info( + "Scanning %d libraries: %s", + len(libraries), + ", ".join(sorted(libraries)), + ) + + # Heuristic redirect catches local symbols (e.g., mdns_task_buffer$14) + # that can't be safely added to the symbol map due to name collisions + self._heuristic_to_lib = self._build_heuristic_to_lib_mapping( + set(libraries.keys()) + ) + + # Try linker map file first (authoritative, includes local symbols) + map_symbols = self._parse_map_file() + if map_symbols is not None: + self._lib_symbol_map = map_symbols + _LOGGER.info( + "Built library symbol map from linker map: %d symbols", + len(self._lib_symbol_map), + ) + return + + # Fall back to nm scanning (global symbols only) + self._lib_symbol_map = self._build_library_symbol_map(libraries) + + _LOGGER.info( + "Built library symbol map from nm: %d symbols from %d libraries", + len(self._lib_symbol_map), + len(libraries), + ) + def _find_object_files_dir(self) -> Path | None: """Find the directory containing object files for this build. @@ -559,9 +903,21 @@ class MemoryAnalyzer: if "esphome" in parts and "components" not in parts: return _COMPONENT_CORE - # Framework/library files - return the first path component - # e.g., lib65b/ESPAsyncTCP/... -> lib65b - # FrameworkArduino/... -> FrameworkArduino + # Framework/library files - check for PlatformIO library hash dirs + # e.g., lib65b/ESPAsyncTCP/... -> [lib]espasynctcp + if parts and parts[0] in self._lib_hash_to_name: + return f"{_COMPONENT_PREFIX_LIB}{self._lib_hash_to_name[parts[0]]}" + + # ESP-IDF managed components: managed_components/espressif__mdns/... -> [lib]mdns + if ( + len(parts) >= 2 + and parts[0] == "managed_components" + and parts[1] in self._lib_hash_to_name + ): + return f"{_COMPONENT_PREFIX_LIB}{self._lib_hash_to_name[parts[1]]}" + + # Other framework/library files - return the first path component + # e.g., FrameworkArduino/... -> FrameworkArduino return parts[0] if parts else source_file def _analyze_cswtch_symbols(self) -> None: diff --git a/esphome/analyze_memory/cli.py b/esphome/analyze_memory/cli.py index bb0eb7723e..dbc19c6b89 100644 --- a/esphome/analyze_memory/cli.py +++ b/esphome/analyze_memory/cli.py @@ -14,6 +14,7 @@ from . import ( _COMPONENT_CORE, _COMPONENT_PREFIX_ESPHOME, _COMPONENT_PREFIX_EXTERNAL, + _COMPONENT_PREFIX_LIB, RAM_SECTIONS, MemoryAnalyzer, ) @@ -407,6 +408,11 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): for name, mem in components if name.startswith(_COMPONENT_PREFIX_EXTERNAL) ] + library_components = [ + (name, mem) + for name, mem in components + if name.startswith(_COMPONENT_PREFIX_LIB) + ] top_esphome_components = sorted( esphome_components, key=lambda x: x[1].flash_total, reverse=True @@ -417,6 +423,11 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): external_components, key=lambda x: x[1].flash_total, reverse=True ) + # Include all library components + top_library_components = sorted( + library_components, key=lambda x: x[1].flash_total, reverse=True + ) + # Check if API component exists and ensure it's included api_component = None for name, mem in components: @@ -435,10 +446,11 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): if name in system_components_to_include ] - # Combine all components to analyze: top ESPHome + all external + API if not already included + system components + # Combine all components to analyze: top ESPHome + all external + libraries + API if not already included + system components components_to_analyze = ( list(top_esphome_components) + list(top_external_components) + + list(top_library_components) + system_components ) if api_component and api_component not in components_to_analyze: From 1c60efa4b6591f4b1fad1f76811faec142ab3d3c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:30:49 -0600 Subject: [PATCH 0575/2030] [ota] Use secrets module for OTA authentication cnonce (#13863) --- esphome/espota2.py | 6 ++-- tests/unit_tests/test_espota2.py | 47 +++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/esphome/espota2.py b/esphome/espota2.py index 2d90251b38..c342eb4463 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -6,7 +6,7 @@ import hashlib import io import logging from pathlib import Path -import random +import secrets import socket import sys import time @@ -300,8 +300,8 @@ def perform_ota( nonce = nonce_bytes.decode() _LOGGER.debug("Auth: %s Nonce is %s", hash_name, nonce) - # Generate cnonce - cnonce = hash_func(str(random.random()).encode()).hexdigest() + # Generate cnonce matching the hash algorithm's digest size + cnonce = secrets.token_hex(nonce_size // 2) _LOGGER.debug("Auth: %s CNonce is %s", hash_name, cnonce) send_check(sock, cnonce, "auth cnonce") diff --git a/tests/unit_tests/test_espota2.py b/tests/unit_tests/test_espota2.py index 1885b769f1..20ba4b1f76 100644 --- a/tests/unit_tests/test_espota2.py +++ b/tests/unit_tests/test_espota2.py @@ -18,8 +18,8 @@ from esphome import espota2 from esphome.core import EsphomeError # Test constants -MOCK_RANDOM_VALUE = 0.123456 -MOCK_RANDOM_BYTES = b"0.123456" +MOCK_MD5_CNONCE = "a" * 32 # Mock 32-char hex string from secrets.token_hex(16) +MOCK_SHA256_CNONCE = "b" * 64 # Mock 64-char hex string from secrets.token_hex(32) MOCK_MD5_NONCE = b"12345678901234567890123456789012" # 32 char nonce for MD5 MOCK_SHA256_NONCE = b"1234567890123456789012345678901234567890123456789012345678901234" # 64 char nonce for SHA256 @@ -55,10 +55,18 @@ def mock_time() -> Generator[None]: @pytest.fixture -def mock_random() -> Generator[Mock]: - """Mock random for predictable test values.""" - with patch("random.random", return_value=MOCK_RANDOM_VALUE) as mock_rand: - yield mock_rand +def mock_token_hex() -> Generator[Mock]: + """Mock secrets.token_hex for predictable test values.""" + + def _token_hex(nbytes: int) -> str: + if nbytes == 16: + return MOCK_MD5_CNONCE + if nbytes == 32: + return MOCK_SHA256_CNONCE + raise ValueError(f"Unexpected nbytes for token_hex mock: {nbytes}") + + with patch("esphome.espota2.secrets.token_hex", side_effect=_token_hex) as mock: + yield mock @pytest.fixture @@ -236,7 +244,7 @@ def test_send_check_socket_error(mock_socket: Mock) -> None: @pytest.mark.usefixtures("mock_time") def test_perform_ota_successful_md5_auth( - mock_socket: Mock, mock_file: io.BytesIO, mock_random: Mock + mock_socket: Mock, mock_file: io.BytesIO, mock_token_hex: Mock ) -> None: """Test successful OTA with MD5 authentication.""" # Setup socket responses for recv calls @@ -272,8 +280,11 @@ def test_perform_ota_successful_md5_auth( ) ) - # Verify cnonce was sent (MD5 of random.random()) - cnonce = hashlib.md5(MOCK_RANDOM_BYTES).hexdigest() + # Verify token_hex was called with MD5 digest size + mock_token_hex.assert_called_once_with(16) + + # Verify cnonce was sent + cnonce = MOCK_MD5_CNONCE assert mock_socket.sendall.call_args_list[2] == call(cnonce.encode()) # Verify auth result was computed correctly @@ -366,7 +377,7 @@ def test_perform_ota_auth_without_password(mock_socket: Mock) -> None: @pytest.mark.usefixtures("mock_time") def test_perform_ota_md5_auth_wrong_password( - mock_socket: Mock, mock_file: io.BytesIO, mock_random: Mock + mock_socket: Mock, mock_file: io.BytesIO, mock_token_hex: Mock ) -> None: """Test OTA fails when MD5 authentication is rejected due to wrong password.""" # Setup socket responses for recv calls @@ -390,7 +401,7 @@ def test_perform_ota_md5_auth_wrong_password( @pytest.mark.usefixtures("mock_time") def test_perform_ota_sha256_auth_wrong_password( - mock_socket: Mock, mock_file: io.BytesIO, mock_random: Mock + mock_socket: Mock, mock_file: io.BytesIO, mock_token_hex: Mock ) -> None: """Test OTA fails when SHA256 authentication is rejected due to wrong password.""" # Setup socket responses for recv calls @@ -603,7 +614,7 @@ def test_progress_bar(capsys: CaptureFixture[str]) -> None: # Tests for SHA256 authentication @pytest.mark.usefixtures("mock_time") def test_perform_ota_successful_sha256_auth( - mock_socket: Mock, mock_file: io.BytesIO, mock_random: Mock + mock_socket: Mock, mock_file: io.BytesIO, mock_token_hex: Mock ) -> None: """Test successful OTA with SHA256 authentication.""" # Setup socket responses for recv calls @@ -639,8 +650,11 @@ def test_perform_ota_successful_sha256_auth( ) ) - # Verify cnonce was sent (SHA256 of random.random()) - cnonce = hashlib.sha256(MOCK_RANDOM_BYTES).hexdigest() + # Verify token_hex was called with SHA256 digest size + mock_token_hex.assert_called_once_with(32) + + # Verify cnonce was sent + cnonce = MOCK_SHA256_CNONCE assert mock_socket.sendall.call_args_list[2] == call(cnonce.encode()) # Verify auth result was computed correctly with SHA256 @@ -654,7 +668,7 @@ def test_perform_ota_successful_sha256_auth( @pytest.mark.usefixtures("mock_time") def test_perform_ota_sha256_fallback_to_md5( - mock_socket: Mock, mock_file: io.BytesIO, mock_random: Mock + mock_socket: Mock, mock_file: io.BytesIO, mock_token_hex: Mock ) -> None: """Test SHA256-capable client falls back to MD5 for compatibility.""" # This test verifies the temporary backward compatibility @@ -692,7 +706,8 @@ def test_perform_ota_sha256_fallback_to_md5( ) # But authentication was done with MD5 - cnonce = hashlib.md5(MOCK_RANDOM_BYTES).hexdigest() + mock_token_hex.assert_called_once_with(16) + cnonce = MOCK_MD5_CNONCE expected_hash = hashlib.md5() expected_hash.update(b"testpass") expected_hash.update(MOCK_MD5_NONCE) From 8b8acb3b2722c8c605dc84a7af9719f7b287ea9b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:31:06 -0600 Subject: [PATCH 0576/2030] [dashboard] Use constant-time comparison for username check (#13865) --- esphome/dashboard/settings.py | 15 +++++--- tests/dashboard/test_settings.py | 66 +++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/esphome/dashboard/settings.py b/esphome/dashboard/settings.py index 6035b4a1d6..3b22180b1d 100644 --- a/esphome/dashboard/settings.py +++ b/esphome/dashboard/settings.py @@ -32,7 +32,7 @@ class DashboardSettings: def __init__(self) -> None: """Initialize the dashboard settings.""" self.config_dir: Path = None - self.password_hash: str = "" + self.password_hash: bytes = b"" self.username: str = "" self.using_password: bool = False self.on_ha_addon: bool = False @@ -84,11 +84,14 @@ class DashboardSettings: def check_password(self, username: str, password: str) -> bool: if not self.using_auth: return True - if username != self.username: - return False - - # Compare password in constant running time (to prevent timing attacks) - return hmac.compare_digest(self.password_hash, password_hash(password)) + # Compare in constant running time (to prevent timing attacks) + username_matches = hmac.compare_digest( + username.encode("utf-8"), self.username.encode("utf-8") + ) + password_matches = hmac.compare_digest( + self.password_hash, password_hash(password) + ) + return username_matches and password_matches def rel_path(self, *args: Any) -> Path: """Return a path relative to the ESPHome config folder.""" diff --git a/tests/dashboard/test_settings.py b/tests/dashboard/test_settings.py index 91a8ec70c3..55776ac7c4 100644 --- a/tests/dashboard/test_settings.py +++ b/tests/dashboard/test_settings.py @@ -1,4 +1,4 @@ -"""Tests for dashboard settings Path-related functionality.""" +"""Tests for DashboardSettings (path resolution and authentication).""" from __future__ import annotations @@ -10,6 +10,7 @@ import pytest from esphome.core import CORE from esphome.dashboard.settings import DashboardSettings +from esphome.dashboard.util.password import password_hash @pytest.fixture @@ -221,3 +222,66 @@ def test_config_path_parent_resolves_to_config_dir(tmp_path: Path) -> None: # Verify that CORE.config_path itself uses the sentinel file assert CORE.config_path.name == "___DASHBOARD_SENTINEL___.yaml" assert not CORE.config_path.exists() # Sentinel file doesn't actually exist + + +@pytest.fixture +def auth_settings(dashboard_settings: DashboardSettings) -> DashboardSettings: + """Create DashboardSettings with auth configured, based on dashboard_settings.""" + dashboard_settings.username = "admin" + dashboard_settings.using_password = True + dashboard_settings.password_hash = password_hash("correctpassword") + return dashboard_settings + + +def test_check_password_correct_credentials(auth_settings: DashboardSettings) -> None: + """Test check_password returns True for correct username and password.""" + assert auth_settings.check_password("admin", "correctpassword") is True + + +def test_check_password_wrong_password(auth_settings: DashboardSettings) -> None: + """Test check_password returns False for wrong password.""" + assert auth_settings.check_password("admin", "wrongpassword") is False + + +def test_check_password_wrong_username(auth_settings: DashboardSettings) -> None: + """Test check_password returns False for wrong username.""" + assert auth_settings.check_password("notadmin", "correctpassword") is False + + +def test_check_password_both_wrong(auth_settings: DashboardSettings) -> None: + """Test check_password returns False when both are wrong.""" + assert auth_settings.check_password("notadmin", "wrongpassword") is False + + +def test_check_password_no_auth(dashboard_settings: DashboardSettings) -> None: + """Test check_password returns True when auth is not configured.""" + assert dashboard_settings.check_password("anyone", "anything") is True + + +def test_check_password_non_ascii_username( + dashboard_settings: DashboardSettings, +) -> None: + """Test check_password handles non-ASCII usernames without TypeError.""" + dashboard_settings.username = "\u00e9l\u00e8ve" + dashboard_settings.using_password = True + dashboard_settings.password_hash = password_hash("pass") + assert dashboard_settings.check_password("\u00e9l\u00e8ve", "pass") is True + assert dashboard_settings.check_password("\u00e9l\u00e8ve", "wrong") is False + assert dashboard_settings.check_password("other", "pass") is False + + +def test_check_password_ha_addon_no_password( + dashboard_settings: DashboardSettings, + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test check_password doesn't crash in HA add-on mode without a password. + + In HA add-on mode, using_ha_addon_auth can be True while using_password + is False, leaving password_hash as b"". This must not raise TypeError + in hmac.compare_digest. + """ + monkeypatch.delenv("DISABLE_HA_AUTHENTICATION", raising=False) + dashboard_settings.on_ha_addon = True + dashboard_settings.using_password = False + # password_hash stays as default b"" + assert dashboard_settings.check_password("anyone", "anything") is False From 248fc06dacbb4e5cfe861bcda003d2fdb2f7d60b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:44:20 -0600 Subject: [PATCH 0577/2030] [scheduler] Eliminate heap allocation in full_cleanup_removed_items_ (#13837) --- esphome/core/scheduler.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 047bf4ef17..6797640f54 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -390,20 +390,19 @@ void Scheduler::full_cleanup_removed_items_() { // 4. No operations inside can block or take other locks, so no deadlock risk LockGuard guard{this->lock_}; - std::vector<std::unique_ptr<SchedulerItem>> valid_items; - - // Move all non-removed items to valid_items, recycle removed ones - for (auto &item : this->items_) { - if (!is_item_removed_(item.get())) { - valid_items.push_back(std::move(item)); + // Compact in-place: move valid items forward, recycle removed ones + size_t write = 0; + for (size_t read = 0; read < this->items_.size(); ++read) { + if (!is_item_removed_(this->items_[read].get())) { + if (write != read) { + this->items_[write] = std::move(this->items_[read]); + } + ++write; } else { - // Recycle removed items - this->recycle_item_main_loop_(std::move(item)); + this->recycle_item_main_loop_(std::move(this->items_[read])); } } - - // Replace items_ with the filtered list - this->items_ = std::move(valid_items); + this->items_.erase(this->items_.begin() + write, this->items_.end()); // Rebuild the heap structure since items are no longer in heap order std::make_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); this->to_remove_ = 0; From c812ac8b29aff567a219a263000494fb4b04b5f2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:44:35 -0600 Subject: [PATCH 0578/2030] [ms8607] Replace set_retry with set_timeout chain to avoid heap allocation (#13842) --- esphome/components/ms8607/ms8607.cpp | 86 ++++++++++++++-------------- esphome/components/ms8607/ms8607.h | 4 ++ 2 files changed, 48 insertions(+), 42 deletions(-) diff --git a/esphome/components/ms8607/ms8607.cpp b/esphome/components/ms8607/ms8607.cpp index 215131eb8e..88a3e6d7dc 100644 --- a/esphome/components/ms8607/ms8607.cpp +++ b/esphome/components/ms8607/ms8607.cpp @@ -72,53 +72,55 @@ void MS8607Component::setup() { // I do not know why the device sometimes NACKs the reset command, but // try 3 times in case it's a transitory issue on this boot - this->set_retry( - "reset", 5, 3, - [this](const uint8_t remaining_setup_attempts) { - ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, - this->humidity_device_->get_address()); - // I believe sending the reset command to both addresses is preferable to - // skipping humidity if PT fails for some reason. - // However, only consider the reset successful if they both ACK - bool const pt_successful = this->write_bytes(MS8607_PT_CMD_RESET, nullptr, 0); - bool const h_successful = this->humidity_device_->write_bytes(MS8607_CMD_H_RESET, nullptr, 0); + // Backoff: executes at now, +5ms, +30ms + this->reset_attempts_remaining_ = 3; + this->reset_interval_ = 5; + this->try_reset_(); +} - if (!(pt_successful && h_successful)) { - ESP_LOGE(TAG, "Resetting I2C devices failed"); - if (!pt_successful && !h_successful) { - this->error_code_ = ErrorCode::PTH_RESET_FAILED; - } else if (!pt_successful) { - this->error_code_ = ErrorCode::PT_RESET_FAILED; - } else { - this->error_code_ = ErrorCode::H_RESET_FAILED; - } +void MS8607Component::try_reset_() { + ESP_LOGD(TAG, "Resetting both I2C addresses: 0x%02X, 0x%02X", this->address_, this->humidity_device_->get_address()); + // I believe sending the reset command to both addresses is preferable to + // skipping humidity if PT fails for some reason. + // However, only consider the reset successful if they both ACK + bool const pt_successful = this->write_bytes(MS8607_PT_CMD_RESET, nullptr, 0); + bool const h_successful = this->humidity_device_->write_bytes(MS8607_CMD_H_RESET, nullptr, 0); - if (remaining_setup_attempts > 0) { - this->status_set_error(); - } else { - this->mark_failed(); - } - return RetryResult::RETRY; - } + if (!(pt_successful && h_successful)) { + ESP_LOGE(TAG, "Resetting I2C devices failed"); + if (!pt_successful && !h_successful) { + this->error_code_ = ErrorCode::PTH_RESET_FAILED; + } else if (!pt_successful) { + this->error_code_ = ErrorCode::PT_RESET_FAILED; + } else { + this->error_code_ = ErrorCode::H_RESET_FAILED; + } - this->setup_status_ = SetupStatus::NEEDS_PROM_READ; - this->error_code_ = ErrorCode::NONE; - this->status_clear_error(); + if (--this->reset_attempts_remaining_ > 0) { + uint32_t delay = this->reset_interval_; + this->reset_interval_ *= 5; + this->set_timeout("reset", delay, [this]() { this->try_reset_(); }); + this->status_set_error(); + } else { + this->mark_failed(); + } + return; + } - // 15ms delay matches datasheet, Adafruit_MS8607 & SparkFun_PHT_MS8607_Arduino_Library - this->set_timeout("prom-read", 15, [this]() { - if (this->read_calibration_values_from_prom_()) { - this->setup_status_ = SetupStatus::SUCCESSFUL; - this->status_clear_error(); - } else { - this->mark_failed(); - return; - } - }); + this->setup_status_ = SetupStatus::NEEDS_PROM_READ; + this->error_code_ = ErrorCode::NONE; + this->status_clear_error(); - return RetryResult::DONE; - }, - 5.0f); // executes at now, +5ms, +25ms + // 15ms delay matches datasheet, Adafruit_MS8607 & SparkFun_PHT_MS8607_Arduino_Library + this->set_timeout("prom-read", 15, [this]() { + if (this->read_calibration_values_from_prom_()) { + this->setup_status_ = SetupStatus::SUCCESSFUL; + this->status_clear_error(); + } else { + this->mark_failed(); + return; + } + }); } void MS8607Component::update() { diff --git a/esphome/components/ms8607/ms8607.h b/esphome/components/ms8607/ms8607.h index 67ce2817fa..ceb3dd22c8 100644 --- a/esphome/components/ms8607/ms8607.h +++ b/esphome/components/ms8607/ms8607.h @@ -44,6 +44,8 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { void set_humidity_device(MS8607HumidityDevice *humidity_device) { humidity_device_ = humidity_device; } protected: + /// Attempt to reset both I2C devices, retrying with backoff on failure + void try_reset_(); /** Read and store the Pressure & Temperature calibration settings from the PROM. Intended to be called during setup(), this will set the `failure_reason_` @@ -102,6 +104,8 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { enum class SetupStatus; /// Current step in the multi-step & possibly delayed setup() process SetupStatus setup_status_; + uint32_t reset_interval_{5}; + uint8_t reset_attempts_remaining_{0}; }; } // namespace ms8607 From 938a11595dc221cc86586bb778d332d7c60a4753 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:44:50 -0600 Subject: [PATCH 0579/2030] [speaker] Replace set_retry with set_interval to avoid heap allocation (#13843) --- .../media_player/speaker_media_player.cpp | 42 +++++++++---------- .../media_player/speaker_media_player.h | 5 +++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 94f555c26e..fdf6bf66cd 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -103,6 +103,20 @@ void SpeakerMediaPlayer::set_playlist_delay_ms(AudioPipelineType pipeline_type, } } +void SpeakerMediaPlayer::stop_and_unpause_media_() { + this->media_pipeline_->stop(); + this->unpause_media_remaining_ = 3; + this->set_interval("unpause_med", 50, [this]() { + if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) { + this->cancel_interval("unpause_med"); + this->media_pipeline_->set_pause_state(false); + this->is_paused_ = false; + } else if (--this->unpause_media_remaining_ == 0) { + this->cancel_interval("unpause_med"); + } + }); +} + void SpeakerMediaPlayer::watch_media_commands_() { if (!this->is_ready()) { return; @@ -144,15 +158,7 @@ void SpeakerMediaPlayer::watch_media_commands_() { if (this->is_paused_) { // If paused, stop the media pipeline and unpause it after confirming its stopped. This avoids playing a // short segment of the paused file before starting the new one. - this->media_pipeline_->stop(); - this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) { - if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) { - this->media_pipeline_->set_pause_state(false); - this->is_paused_ = false; - return RetryResult::DONE; - } - return RetryResult::RETRY; - }); + this->stop_and_unpause_media_(); } else { // Not paused, just directly start the file if (media_command.file.has_value()) { @@ -197,27 +203,21 @@ void SpeakerMediaPlayer::watch_media_commands_() { this->cancel_timeout("next_ann"); this->announcement_playlist_.clear(); this->announcement_pipeline_->stop(); - this->set_retry("unpause_ann", 50, 3, [this](const uint8_t remaining_attempts) { + this->unpause_announcement_remaining_ = 3; + this->set_interval("unpause_ann", 50, [this]() { if (this->announcement_pipeline_state_ == AudioPipelineState::STOPPED) { + this->cancel_interval("unpause_ann"); this->announcement_pipeline_->set_pause_state(false); - return RetryResult::DONE; + } else if (--this->unpause_announcement_remaining_ == 0) { + this->cancel_interval("unpause_ann"); } - return RetryResult::RETRY; }); } } else { if (this->media_pipeline_ != nullptr) { this->cancel_timeout("next_media"); this->media_playlist_.clear(); - this->media_pipeline_->stop(); - this->set_retry("unpause_med", 50, 3, [this](const uint8_t remaining_attempts) { - if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) { - this->media_pipeline_->set_pause_state(false); - this->is_paused_ = false; - return RetryResult::DONE; - } - return RetryResult::RETRY; - }); + this->stop_and_unpause_media_(); } } diff --git a/esphome/components/speaker/media_player/speaker_media_player.h b/esphome/components/speaker/media_player/speaker_media_player.h index 722f98ceea..6796fc9c00 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.h +++ b/esphome/components/speaker/media_player/speaker_media_player.h @@ -112,6 +112,9 @@ class SpeakerMediaPlayer : public Component, /// media pipelines are defined. inline bool single_pipeline_() { return (this->media_speaker_ == nullptr); } + /// Stops the media pipeline and polls until stopped to unpause it, avoiding an audible glitch. + void stop_and_unpause_media_(); + // Processes commands from media_control_command_queue_. void watch_media_commands_(); @@ -141,6 +144,8 @@ class SpeakerMediaPlayer : public Component, bool is_paused_{false}; bool is_muted_{false}; + uint8_t unpause_media_remaining_{0}; + uint8_t unpause_announcement_remaining_{0}; // The amount to change the volume on volume up/down commands float volume_increment_; From 66af9980983f4f6fd09e0c7e672231ddd3edfe45 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:45:03 -0600 Subject: [PATCH 0580/2030] [dashboard] Handle malformed Basic Auth headers gracefully (#13866) --- esphome/dashboard/web_server.py | 7 ++- tests/dashboard/test_web_server.py | 83 ++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 00974bf460..92cab929ef 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -120,8 +120,11 @@ def is_authenticated(handler: BaseHandler) -> bool: if auth_header := handler.request.headers.get("Authorization"): assert isinstance(auth_header, str) if auth_header.startswith("Basic "): - auth_decoded = base64.b64decode(auth_header[6:]).decode() - username, password = auth_decoded.split(":", 1) + try: + auth_decoded = base64.b64decode(auth_header[6:]).decode() + username, password = auth_decoded.split(":", 1) + except (binascii.Error, ValueError, UnicodeDecodeError): + return False return settings.check_password(username, password) return handler.get_secure_cookie(AUTH_COOKIE_NAME) == COOKIE_AUTHENTICATED_YES diff --git a/tests/dashboard/test_web_server.py b/tests/dashboard/test_web_server.py index 9ea7a5164b..daff384515 100644 --- a/tests/dashboard/test_web_server.py +++ b/tests/dashboard/test_web_server.py @@ -2,6 +2,7 @@ from __future__ import annotations from argparse import Namespace import asyncio +import base64 from collections.abc import Generator from contextlib import asynccontextmanager import gzip @@ -1741,3 +1742,85 @@ def test_proc_on_exit_skips_when_already_closed() -> None: handler.write_message.assert_not_called() handler.close.assert_not_called() + + +def _make_auth_handler(auth_header: str | None = None) -> Mock: + """Create a mock handler with the given Authorization header.""" + handler = Mock() + handler.request = Mock() + if auth_header is not None: + handler.request.headers = {"Authorization": auth_header} + else: + handler.request.headers = {} + handler.get_secure_cookie = Mock(return_value=None) + return handler + + +@pytest.fixture +def mock_auth_settings(mock_dashboard_settings: MagicMock) -> MagicMock: + """Fixture to configure mock dashboard settings with auth enabled.""" + mock_dashboard_settings.using_auth = True + mock_dashboard_settings.on_ha_addon = False + return mock_dashboard_settings + + +@pytest.mark.usefixtures("mock_auth_settings") +def test_is_authenticated_malformed_base64() -> None: + """Test that invalid base64 in Authorization header returns False.""" + handler = _make_auth_handler("Basic !!!not-valid-base64!!!") + assert web_server.is_authenticated(handler) is False + + +@pytest.mark.usefixtures("mock_auth_settings") +def test_is_authenticated_bad_base64_padding() -> None: + """Test that incorrect base64 padding (binascii.Error) returns False.""" + handler = _make_auth_handler("Basic abc") + assert web_server.is_authenticated(handler) is False + + +@pytest.mark.usefixtures("mock_auth_settings") +def test_is_authenticated_invalid_utf8() -> None: + """Test that base64 decoding to invalid UTF-8 returns False.""" + # \xff\xfe is invalid UTF-8 + bad_payload = base64.b64encode(b"\xff\xfe").decode("ascii") + handler = _make_auth_handler(f"Basic {bad_payload}") + assert web_server.is_authenticated(handler) is False + + +@pytest.mark.usefixtures("mock_auth_settings") +def test_is_authenticated_no_colon() -> None: + """Test that base64 payload without ':' separator returns False.""" + no_colon = base64.b64encode(b"nocolonhere").decode("ascii") + handler = _make_auth_handler(f"Basic {no_colon}") + assert web_server.is_authenticated(handler) is False + + +def test_is_authenticated_valid_credentials( + mock_auth_settings: MagicMock, +) -> None: + """Test that valid Basic auth credentials are checked.""" + creds = base64.b64encode(b"admin:secret").decode("ascii") + mock_auth_settings.check_password.return_value = True + handler = _make_auth_handler(f"Basic {creds}") + assert web_server.is_authenticated(handler) is True + mock_auth_settings.check_password.assert_called_once_with("admin", "secret") + + +def test_is_authenticated_wrong_credentials( + mock_auth_settings: MagicMock, +) -> None: + """Test that valid Basic auth with wrong credentials returns False.""" + creds = base64.b64encode(b"admin:wrong").decode("ascii") + mock_auth_settings.check_password.return_value = False + handler = _make_auth_handler(f"Basic {creds}") + assert web_server.is_authenticated(handler) is False + + +def test_is_authenticated_no_auth_configured( + mock_dashboard_settings: MagicMock, +) -> None: + """Test that requests pass when auth is not configured.""" + mock_dashboard_settings.using_auth = False + mock_dashboard_settings.on_ha_addon = False + handler = _make_auth_handler() + assert web_server.is_authenticated(handler) is True From be4e573cc4af420e8f34af8d9c667e11a9662349 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:45:18 -0600 Subject: [PATCH 0581/2030] [esp32_hosted] Replace set_retry with set_interval to avoid heap allocation (#13844) --- .../update/esp32_hosted_update.cpp | 20 +++++++++++++------ .../esp32_hosted/update/esp32_hosted_update.h | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index a7d5f7e3d5..c8e2e879d4 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -27,6 +27,11 @@ static const char *const TAG = "esp32_hosted.update"; // Older coprocessor firmware versions have a 1500-byte limit per RPC call constexpr size_t CHUNK_SIZE = 1500; +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE +// Interval/timeout IDs (uint32_t to avoid string comparison) +constexpr uint32_t INITIAL_CHECK_INTERVAL_ID = 0; +#endif + // Compile-time version string from esp_hosted_host_fw_ver.h macros #define STRINGIFY_(x) #x #define STRINGIFY(x) STRINGIFY_(x) @@ -127,15 +132,18 @@ void Esp32HostedUpdate::setup() { this->status_clear_error(); this->publish_state(); #else - // HTTP mode: retry initial check every 10s until network is ready (max 6 attempts) + // HTTP mode: check every 10s until network is ready (max 6 attempts) // Only if update interval is > 1 minute to avoid redundant checks if (this->get_update_interval() > 60000) { - this->set_retry("initial_check", 10000, 6, [this](uint8_t) { - if (!network::is_connected()) { - return RetryResult::RETRY; + this->initial_check_remaining_ = 6; + this->set_interval(INITIAL_CHECK_INTERVAL_ID, 10000, [this]() { + bool connected = network::is_connected(); + if (--this->initial_check_remaining_ == 0 || connected) { + this->cancel_interval(INITIAL_CHECK_INTERVAL_ID); + if (connected) { + this->check(); + } } - this->check(); - return RetryResult::DONE; }); } #endif diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.h b/esphome/components/esp32_hosted/update/esp32_hosted_update.h index 7c9645c12a..005e6a6f21 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.h +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.h @@ -44,6 +44,7 @@ class Esp32HostedUpdate : public update::UpdateEntity, public PollingComponent { // HTTP mode helpers bool fetch_manifest_(); bool stream_firmware_to_coprocessor_(); + uint8_t initial_check_remaining_{0}; #else // Embedded mode members const uint8_t *firmware_data_{nullptr}; From 3cde3dacebf4bc39d36fcd37abc342e198d0500f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 08:45:33 -0600 Subject: [PATCH 0582/2030] [api] Collapse APIServerConnection intermediary layer (#13872) --- esphome/components/api/api_connection.cpp | 122 ++++++---- esphome/components/api/api_connection.h | 109 +++++---- esphome/components/api/api_pb2_service.cpp | 194 --------------- esphome/components/api/api_pb2_service.h | 261 --------------------- script/api_protobuf/api_protobuf.py | 40 ---- 5 files changed, 141 insertions(+), 585 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index efc3d210b4..ddc24a7e2c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -283,7 +283,7 @@ void APIConnection::loop() { #endif } -bool APIConnection::send_disconnect_response() { +bool APIConnection::send_disconnect_response_() { // remote initiated disconnect_client // don't close yet, we still need to send the disconnect response // close will happen on next loop @@ -406,7 +406,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c msg.device_class = cover->get_device_class_ref(); return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::cover_command(const CoverCommandRequest &msg) { +void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover) if (msg.has_position) call.set_position(msg.position); @@ -449,7 +449,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con msg.supported_preset_modes = &traits.supported_preset_modes(); return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::fan_command(const FanCommandRequest &msg) { +void APIConnection::on_fan_command_request(const FanCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan) if (msg.has_state) call.set_state(msg.state); @@ -517,7 +517,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c msg.effects = &effects_list; return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::light_command(const LightCommandRequest &msg) { +void APIConnection::on_light_command_request(const LightCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light) if (msg.has_state) call.set_state(msg.state); @@ -594,7 +594,7 @@ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection * msg.device_class = a_switch->get_device_class_ref(); return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::switch_command(const SwitchCommandRequest &msg) { +void APIConnection::on_switch_command_request(const SwitchCommandRequest &msg) { ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch) if (msg.state) { @@ -692,7 +692,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection msg.supported_swing_modes = &traits.get_supported_swing_modes(); return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::climate_command(const ClimateCommandRequest &msg) { +void APIConnection::on_climate_command_request(const ClimateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate) if (msg.has_mode) call.set_mode(static_cast<climate::ClimateMode>(msg.mode)); @@ -742,7 +742,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection * msg.step = number->traits.get_step(); return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::number_command(const NumberCommandRequest &msg) { +void APIConnection::on_number_command_request(const NumberCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(number::Number, number, number) call.set_value(msg.state); call.perform(); @@ -767,7 +767,7 @@ uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *co ListEntitiesDateResponse msg; return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::date_command(const DateCommandRequest &msg) { +void APIConnection::on_date_command_request(const DateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date) call.set_date(msg.year, msg.month, msg.day); call.perform(); @@ -792,7 +792,7 @@ uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *co ListEntitiesTimeResponse msg; return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::time_command(const TimeCommandRequest &msg) { +void APIConnection::on_time_command_request(const TimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time) call.set_time(msg.hour, msg.minute, msg.second); call.perform(); @@ -819,7 +819,7 @@ uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection ListEntitiesDateTimeResponse msg; return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::datetime_command(const DateTimeCommandRequest &msg) { +void APIConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime) call.set_datetime(msg.epoch_seconds); call.perform(); @@ -848,7 +848,7 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co msg.pattern = text->traits.get_pattern_ref(); return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::text_command(const TextCommandRequest &msg) { +void APIConnection::on_text_command_request(const TextCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(text::Text, text, text) call.set_value(msg.state); call.perform(); @@ -874,7 +874,7 @@ uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection * msg.options = &select->traits.get_options(); return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::select_command(const SelectCommandRequest &msg) { +void APIConnection::on_select_command_request(const SelectCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(select::Select, select, select) call.set_option(msg.state.c_str(), msg.state.size()); call.perform(); @@ -888,7 +888,7 @@ uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection * msg.device_class = button->get_device_class_ref(); return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size); } -void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg) { +void esphome::api::APIConnection::on_button_command_request(const ButtonCommandRequest &msg) { ENTITY_COMMAND_GET(button::Button, button, button) button->press(); } @@ -914,7 +914,7 @@ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *co msg.requires_code = a_lock->traits.get_requires_code(); return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::lock_command(const LockCommandRequest &msg) { +void APIConnection::on_lock_command_request(const LockCommandRequest &msg) { ENTITY_COMMAND_GET(lock::Lock, a_lock, lock) switch (msg.command) { @@ -952,7 +952,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c msg.supports_stop = traits.get_supports_stop(); return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::valve_command(const ValveCommandRequest &msg) { +void APIConnection::on_valve_command_request(const ValveCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve) if (msg.has_position) call.set_position(msg.position); @@ -996,7 +996,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) { +void APIConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player) if (msg.has_command) { call.set_command(static_cast<media_player::MediaPlayerCommand>(msg.command)); @@ -1063,7 +1063,7 @@ uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection * ListEntitiesCameraResponse msg; return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::camera_image(const CameraImageRequest &msg) { +void APIConnection::on_camera_image_request(const CameraImageRequest &msg) { if (camera::Camera::instance() == nullptr) return; @@ -1092,41 +1092,47 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) { #endif #ifdef USE_BLUETOOTH_PROXY -void APIConnection::subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) { +void APIConnection::on_subscribe_bluetooth_le_advertisements_request( + const SubscribeBluetoothLEAdvertisementsRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->subscribe_api_connection(this, msg.flags); } -void APIConnection::unsubscribe_bluetooth_le_advertisements() { +void APIConnection::on_unsubscribe_bluetooth_le_advertisements_request() { bluetooth_proxy::global_bluetooth_proxy->unsubscribe_api_connection(this); } -void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) { +void APIConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_device_request(msg); } -void APIConnection::bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) { +void APIConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read(msg); } -void APIConnection::bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) { +void APIConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write(msg); } -void APIConnection::bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) { +void APIConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read_descriptor(msg); } -void APIConnection::bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) { +void APIConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write_descriptor(msg); } -void APIConnection::bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) { +void APIConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_send_services(msg); } -void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) { +void APIConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_notify(msg); } -bool APIConnection::send_subscribe_bluetooth_connections_free_response() { +bool APIConnection::send_subscribe_bluetooth_connections_free_response_() { bluetooth_proxy::global_bluetooth_proxy->send_connections_free(this); return true; } +void APIConnection::on_subscribe_bluetooth_connections_free_request() { + if (!this->send_subscribe_bluetooth_connections_free_response_()) { + this->on_fatal_error(); + } +} -void APIConnection::bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) { +void APIConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) { bluetooth_proxy::global_bluetooth_proxy->bluetooth_scanner_set_mode( msg.mode == enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE); } @@ -1138,7 +1144,7 @@ bool APIConnection::check_voice_assistant_api_connection_() const { voice_assistant::global_voice_assistant->get_api_connection() == this; } -void APIConnection::subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) { +void APIConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) { if (voice_assistant::global_voice_assistant != nullptr) { voice_assistant::global_voice_assistant->client_subscription(this, msg.subscribe); } @@ -1184,7 +1190,7 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno } } -bool APIConnection::send_voice_assistant_get_configuration_response(const VoiceAssistantConfigurationRequest &msg) { +bool APIConnection::send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg) { VoiceAssistantConfigurationResponse resp; if (!this->check_voice_assistant_api_connection_()) { return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE); @@ -1221,8 +1227,13 @@ bool APIConnection::send_voice_assistant_get_configuration_response(const VoiceA resp.max_active_wake_words = config.max_active_wake_words; return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE); } +void APIConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) { + if (!this->send_voice_assistant_get_configuration_response_(msg)) { + this->on_fatal_error(); + } +} -void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) { +void APIConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) { if (this->check_voice_assistant_api_connection_()) { voice_assistant::global_voice_assistant->on_set_configuration(msg.active_wake_words); } @@ -1230,11 +1241,11 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon #endif #ifdef USE_ZWAVE_PROXY -void APIConnection::zwave_proxy_frame(const ZWaveProxyFrame &msg) { +void APIConnection::on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) { zwave_proxy::global_zwave_proxy->send_frame(msg.data, msg.data_len); } -void APIConnection::zwave_proxy_request(const ZWaveProxyRequest &msg) { +void APIConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) { zwave_proxy::global_zwave_proxy->zwave_proxy_request(this, msg.type); } #endif @@ -1262,7 +1273,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, AP return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) { +void APIConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel) switch (msg.command) { case enums::ALARM_CONTROL_PANEL_DISARM: @@ -1322,7 +1333,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::water_heater_command(const WaterHeaterCommandRequest &msg) { +void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(water_heater::WaterHeater, water_heater, water_heater) if (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_MODE) call.set_mode(static_cast<water_heater::WaterHeaterMode>(msg.mode)); @@ -1364,7 +1375,7 @@ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *c #endif #ifdef USE_IR_RF -void APIConnection::infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) { +void APIConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) { // TODO: When RF is implemented, add a field to the message to distinguish IR vs RF // and dispatch to the appropriate entity type based on that field. #ifdef USE_INFRARED @@ -1418,7 +1429,7 @@ uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection * msg.device_class = update->get_device_class_ref(); return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size); } -void APIConnection::update_command(const UpdateCommandRequest &msg) { +void APIConnection::on_update_command_request(const UpdateCommandRequest &msg) { ENTITY_COMMAND_GET(update::UpdateEntity, update, update) switch (msg.command) { @@ -1469,7 +1480,7 @@ void APIConnection::complete_authentication_() { #endif } -bool APIConnection::send_hello_response(const HelloRequest &msg) { +bool APIConnection::send_hello_response_(const HelloRequest &msg) { // Copy client name with truncation if needed (set_client_name handles truncation) this->helper_->set_client_name(msg.client_info.c_str(), msg.client_info.size()); this->client_api_version_major_ = msg.api_version_major; @@ -1490,12 +1501,12 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) { return this->send_message(resp, HelloResponse::MESSAGE_TYPE); } -bool APIConnection::send_ping_response() { +bool APIConnection::send_ping_response_() { PingResponse resp; return this->send_message(resp, PingResponse::MESSAGE_TYPE); } -bool APIConnection::send_device_info_response() { +bool APIConnection::send_device_info_response_() { DeviceInfoResponse resp{}; resp.name = StringRef(App.get_name()); resp.friendly_name = StringRef(App.get_friendly_name()); @@ -1618,6 +1629,26 @@ bool APIConnection::send_device_info_response() { return this->send_message(resp, DeviceInfoResponse::MESSAGE_TYPE); } +void APIConnection::on_hello_request(const HelloRequest &msg) { + if (!this->send_hello_response_(msg)) { + this->on_fatal_error(); + } +} +void APIConnection::on_disconnect_request() { + if (!this->send_disconnect_response_()) { + this->on_fatal_error(); + } +} +void APIConnection::on_ping_request() { + if (!this->send_ping_response_()) { + this->on_fatal_error(); + } +} +void APIConnection::on_device_info_request() { + if (!this->send_device_info_response_()) { + this->on_fatal_error(); + } +} #ifdef USE_API_HOMEASSISTANT_STATES void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) { @@ -1656,7 +1687,7 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes } #endif #ifdef USE_API_USER_DEFINED_ACTIONS -void APIConnection::execute_service(const ExecuteServiceRequest &msg) { +void APIConnection::on_execute_service_request(const ExecuteServiceRequest &msg) { bool found = false; #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES // Register the call and get a unique server-generated action_call_id @@ -1722,7 +1753,7 @@ void APIConnection::on_homeassistant_action_response(const HomeassistantActionRe }; #endif #ifdef USE_API_NOISE -bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyRequest &msg) { +bool APIConnection::send_noise_encryption_set_key_response_(const NoiseEncryptionSetKeyRequest &msg) { NoiseEncryptionSetKeyResponse resp; resp.success = false; @@ -1743,9 +1774,14 @@ bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryption return this->send_message(resp, NoiseEncryptionSetKeyResponse::MESSAGE_TYPE); } +void APIConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) { + if (!this->send_noise_encryption_set_key_response_(msg)) { + this->on_fatal_error(); + } +} #endif #ifdef USE_API_HOMEASSISTANT_STATES -void APIConnection::subscribe_home_assistant_states() { state_subs_at_ = 0; } +void APIConnection::on_subscribe_home_assistant_states_request() { state_subs_at_ = 0; } #endif bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { if (this->flags_.remove) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 935393b2da..ae7f864568 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -47,72 +47,72 @@ class APIConnection final : public APIServerConnection { #endif #ifdef USE_COVER bool send_cover_state(cover::Cover *cover); - void cover_command(const CoverCommandRequest &msg) override; + void on_cover_command_request(const CoverCommandRequest &msg) override; #endif #ifdef USE_FAN bool send_fan_state(fan::Fan *fan); - void fan_command(const FanCommandRequest &msg) override; + void on_fan_command_request(const FanCommandRequest &msg) override; #endif #ifdef USE_LIGHT bool send_light_state(light::LightState *light); - void light_command(const LightCommandRequest &msg) override; + void on_light_command_request(const LightCommandRequest &msg) override; #endif #ifdef USE_SENSOR bool send_sensor_state(sensor::Sensor *sensor); #endif #ifdef USE_SWITCH bool send_switch_state(switch_::Switch *a_switch); - void switch_command(const SwitchCommandRequest &msg) override; + void on_switch_command_request(const SwitchCommandRequest &msg) override; #endif #ifdef USE_TEXT_SENSOR bool send_text_sensor_state(text_sensor::TextSensor *text_sensor); #endif #ifdef USE_CAMERA void set_camera_state(std::shared_ptr<camera::CameraImage> image); - void camera_image(const CameraImageRequest &msg) override; + void on_camera_image_request(const CameraImageRequest &msg) override; #endif #ifdef USE_CLIMATE bool send_climate_state(climate::Climate *climate); - void climate_command(const ClimateCommandRequest &msg) override; + void on_climate_command_request(const ClimateCommandRequest &msg) override; #endif #ifdef USE_NUMBER bool send_number_state(number::Number *number); - void number_command(const NumberCommandRequest &msg) override; + void on_number_command_request(const NumberCommandRequest &msg) override; #endif #ifdef USE_DATETIME_DATE bool send_date_state(datetime::DateEntity *date); - void date_command(const DateCommandRequest &msg) override; + void on_date_command_request(const DateCommandRequest &msg) override; #endif #ifdef USE_DATETIME_TIME bool send_time_state(datetime::TimeEntity *time); - void time_command(const TimeCommandRequest &msg) override; + void on_time_command_request(const TimeCommandRequest &msg) override; #endif #ifdef USE_DATETIME_DATETIME bool send_datetime_state(datetime::DateTimeEntity *datetime); - void datetime_command(const DateTimeCommandRequest &msg) override; + void on_date_time_command_request(const DateTimeCommandRequest &msg) override; #endif #ifdef USE_TEXT bool send_text_state(text::Text *text); - void text_command(const TextCommandRequest &msg) override; + void on_text_command_request(const TextCommandRequest &msg) override; #endif #ifdef USE_SELECT bool send_select_state(select::Select *select); - void select_command(const SelectCommandRequest &msg) override; + void on_select_command_request(const SelectCommandRequest &msg) override; #endif #ifdef USE_BUTTON - void button_command(const ButtonCommandRequest &msg) override; + void on_button_command_request(const ButtonCommandRequest &msg) override; #endif #ifdef USE_LOCK bool send_lock_state(lock::Lock *a_lock); - void lock_command(const LockCommandRequest &msg) override; + void on_lock_command_request(const LockCommandRequest &msg) override; #endif #ifdef USE_VALVE bool send_valve_state(valve::Valve *valve); - void valve_command(const ValveCommandRequest &msg) override; + void on_valve_command_request(const ValveCommandRequest &msg) override; #endif #ifdef USE_MEDIA_PLAYER bool send_media_player_state(media_player::MediaPlayer *media_player); - void media_player_command(const MediaPlayerCommandRequest &msg) override; + void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override; #endif bool try_send_log_message(int level, const char *tag, const char *line, size_t message_len); #ifdef USE_API_HOMEASSISTANT_SERVICES @@ -126,18 +126,18 @@ class APIConnection final : public APIServerConnection { #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES #endif // USE_API_HOMEASSISTANT_SERVICES #ifdef USE_BLUETOOTH_PROXY - void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; - void unsubscribe_bluetooth_le_advertisements() override; + void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; + void on_unsubscribe_bluetooth_le_advertisements_request() override; - void bluetooth_device_request(const BluetoothDeviceRequest &msg) override; - void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) override; - void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) override; - void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) override; - void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) override; - void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) override; - void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) override; - bool send_subscribe_bluetooth_connections_free_response() override; - void bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) override; + void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override; + void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) override; + void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) override; + void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) override; + void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) override; + void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) override; + void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override; + void on_subscribe_bluetooth_connections_free_request() override; + void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override; #endif #ifdef USE_HOMEASSISTANT_TIME @@ -148,33 +148,33 @@ class APIConnection final : public APIServerConnection { #endif #ifdef USE_VOICE_ASSISTANT - void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) override; + void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) override; void on_voice_assistant_response(const VoiceAssistantResponse &msg) override; void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override; void on_voice_assistant_audio(const VoiceAssistantAudio &msg) override; void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg) override; void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg) override; - bool send_voice_assistant_get_configuration_response(const VoiceAssistantConfigurationRequest &msg) override; - void voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; + void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) override; + void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; #endif #ifdef USE_ZWAVE_PROXY - void zwave_proxy_frame(const ZWaveProxyFrame &msg) override; - void zwave_proxy_request(const ZWaveProxyRequest &msg) override; + void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) override; + void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override; #endif #ifdef USE_ALARM_CONTROL_PANEL bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); - void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override; + void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) override; #endif #ifdef USE_WATER_HEATER bool send_water_heater_state(water_heater::WaterHeater *water_heater); - void water_heater_command(const WaterHeaterCommandRequest &msg) override; + void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; #endif #ifdef USE_IR_RF - void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) override; + void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) override; void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg); #endif @@ -184,7 +184,7 @@ class APIConnection final : public APIServerConnection { #ifdef USE_UPDATE bool send_update_state(update::UpdateEntity *update); - void update_command(const UpdateCommandRequest &msg) override; + void on_update_command_request(const UpdateCommandRequest &msg) override; #endif void on_disconnect_response() override; @@ -198,12 +198,12 @@ class APIConnection final : public APIServerConnection { #ifdef USE_HOMEASSISTANT_TIME void on_get_time_response(const GetTimeResponse &value) override; #endif - bool send_hello_response(const HelloRequest &msg) override; - bool send_disconnect_response() override; - bool send_ping_response() override; - bool send_device_info_response() override; - void list_entities() override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } - void subscribe_states() override { + void on_hello_request(const HelloRequest &msg) override; + void on_disconnect_request() override; + void on_ping_request() override; + void on_device_info_request() override; + void on_list_entities_request() override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } + void on_subscribe_states_request() override { this->flags_.state_subscription = true; // Start initial state iterator only if no iterator is active // If list_entities is running, we'll start initial_state when it completes @@ -211,19 +211,19 @@ class APIConnection final : public APIServerConnection { this->begin_iterator_(ActiveIterator::INITIAL_STATE); } } - void subscribe_logs(const SubscribeLogsRequest &msg) override { + void on_subscribe_logs_request(const SubscribeLogsRequest &msg) override { this->flags_.log_subscription = msg.level; if (msg.dump_config) App.schedule_dump_config(); } #ifdef USE_API_HOMEASSISTANT_SERVICES - void subscribe_homeassistant_services() override { this->flags_.service_call_subscription = true; } + void on_subscribe_homeassistant_services_request() override { this->flags_.service_call_subscription = true; } #endif #ifdef USE_API_HOMEASSISTANT_STATES - void subscribe_home_assistant_states() override; + void on_subscribe_home_assistant_states_request() override; #endif #ifdef USE_API_USER_DEFINED_ACTIONS - void execute_service(const ExecuteServiceRequest &msg) override; + void on_execute_service_request(const ExecuteServiceRequest &msg) override; #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON @@ -233,7 +233,7 @@ class APIConnection final : public APIServerConnection { #endif // USE_API_USER_DEFINED_ACTION_RESPONSES #endif #ifdef USE_API_NOISE - bool send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyRequest &msg) override; + void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) override; #endif bool is_authenticated() override { @@ -283,6 +283,21 @@ class APIConnection final : public APIServerConnection { // Helper function to handle authentication completion void complete_authentication_(); + // Pattern B helpers: send response and return success/failure + bool send_hello_response_(const HelloRequest &msg); + bool send_disconnect_response_(); + bool send_ping_response_(); + bool send_device_info_response_(); +#ifdef USE_API_NOISE + bool send_noise_encryption_set_key_response_(const NoiseEncryptionSetKeyRequest &msg); +#endif +#ifdef USE_BLUETOOTH_PROXY + bool send_subscribe_bluetooth_connections_free_response_(); +#endif +#ifdef USE_VOICE_ASSISTANT + bool send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg); +#endif + #ifdef USE_CAMERA void try_send_camera_image_(); #endif diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index df66b6eb83..1c04eacc82 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -623,200 +623,6 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } } -void APIServerConnection::on_hello_request(const HelloRequest &msg) { - if (!this->send_hello_response(msg)) { - this->on_fatal_error(); - } -} -void APIServerConnection::on_disconnect_request() { - if (!this->send_disconnect_response()) { - this->on_fatal_error(); - } -} -void APIServerConnection::on_ping_request() { - if (!this->send_ping_response()) { - this->on_fatal_error(); - } -} -void APIServerConnection::on_device_info_request() { - if (!this->send_device_info_response()) { - this->on_fatal_error(); - } -} -void APIServerConnection::on_list_entities_request() { this->list_entities(); } -void APIServerConnection::on_subscribe_states_request() { this->subscribe_states(); } -void APIServerConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) { this->subscribe_logs(msg); } -#ifdef USE_API_HOMEASSISTANT_SERVICES -void APIServerConnection::on_subscribe_homeassistant_services_request() { this->subscribe_homeassistant_services(); } -#endif -#ifdef USE_API_HOMEASSISTANT_STATES -void APIServerConnection::on_subscribe_home_assistant_states_request() { this->subscribe_home_assistant_states(); } -#endif -#ifdef USE_API_USER_DEFINED_ACTIONS -void APIServerConnection::on_execute_service_request(const ExecuteServiceRequest &msg) { this->execute_service(msg); } -#endif -#ifdef USE_API_NOISE -void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) { - if (!this->send_noise_encryption_set_key_response(msg)) { - this->on_fatal_error(); - } -} -#endif -#ifdef USE_BUTTON -void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) { this->button_command(msg); } -#endif -#ifdef USE_CAMERA -void APIServerConnection::on_camera_image_request(const CameraImageRequest &msg) { this->camera_image(msg); } -#endif -#ifdef USE_CLIMATE -void APIServerConnection::on_climate_command_request(const ClimateCommandRequest &msg) { this->climate_command(msg); } -#endif -#ifdef USE_COVER -void APIServerConnection::on_cover_command_request(const CoverCommandRequest &msg) { this->cover_command(msg); } -#endif -#ifdef USE_DATETIME_DATE -void APIServerConnection::on_date_command_request(const DateCommandRequest &msg) { this->date_command(msg); } -#endif -#ifdef USE_DATETIME_DATETIME -void APIServerConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) { - this->datetime_command(msg); -} -#endif -#ifdef USE_FAN -void APIServerConnection::on_fan_command_request(const FanCommandRequest &msg) { this->fan_command(msg); } -#endif -#ifdef USE_LIGHT -void APIServerConnection::on_light_command_request(const LightCommandRequest &msg) { this->light_command(msg); } -#endif -#ifdef USE_LOCK -void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) { this->lock_command(msg); } -#endif -#ifdef USE_MEDIA_PLAYER -void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) { - this->media_player_command(msg); -} -#endif -#ifdef USE_NUMBER -void APIServerConnection::on_number_command_request(const NumberCommandRequest &msg) { this->number_command(msg); } -#endif -#ifdef USE_SELECT -void APIServerConnection::on_select_command_request(const SelectCommandRequest &msg) { this->select_command(msg); } -#endif -#ifdef USE_SIREN -void APIServerConnection::on_siren_command_request(const SirenCommandRequest &msg) { this->siren_command(msg); } -#endif -#ifdef USE_SWITCH -void APIServerConnection::on_switch_command_request(const SwitchCommandRequest &msg) { this->switch_command(msg); } -#endif -#ifdef USE_TEXT -void APIServerConnection::on_text_command_request(const TextCommandRequest &msg) { this->text_command(msg); } -#endif -#ifdef USE_DATETIME_TIME -void APIServerConnection::on_time_command_request(const TimeCommandRequest &msg) { this->time_command(msg); } -#endif -#ifdef USE_UPDATE -void APIServerConnection::on_update_command_request(const UpdateCommandRequest &msg) { this->update_command(msg); } -#endif -#ifdef USE_VALVE -void APIServerConnection::on_valve_command_request(const ValveCommandRequest &msg) { this->valve_command(msg); } -#endif -#ifdef USE_WATER_HEATER -void APIServerConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) { - this->water_heater_command(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request( - const SubscribeBluetoothLEAdvertisementsRequest &msg) { - this->subscribe_bluetooth_le_advertisements(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) { - this->bluetooth_device_request(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) { - this->bluetooth_gatt_get_services(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) { - this->bluetooth_gatt_read(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) { - this->bluetooth_gatt_write(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) { - this->bluetooth_gatt_read_descriptor(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) { - this->bluetooth_gatt_write_descriptor(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) { - this->bluetooth_gatt_notify(msg); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_subscribe_bluetooth_connections_free_request() { - if (!this->send_subscribe_bluetooth_connections_free_response()) { - this->on_fatal_error(); - } -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_unsubscribe_bluetooth_le_advertisements_request() { - this->unsubscribe_bluetooth_le_advertisements(); -} -#endif -#ifdef USE_BLUETOOTH_PROXY -void APIServerConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) { - this->bluetooth_scanner_set_mode(msg); -} -#endif -#ifdef USE_VOICE_ASSISTANT -void APIServerConnection::on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) { - this->subscribe_voice_assistant(msg); -} -#endif -#ifdef USE_VOICE_ASSISTANT -void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) { - if (!this->send_voice_assistant_get_configuration_response(msg)) { - this->on_fatal_error(); - } -} -#endif -#ifdef USE_VOICE_ASSISTANT -void APIServerConnection::on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) { - this->voice_assistant_set_configuration(msg); -} -#endif -#ifdef USE_ALARM_CONTROL_PANEL -void APIServerConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) { - this->alarm_control_panel_command(msg); -} -#endif -#ifdef USE_ZWAVE_PROXY -void APIServerConnection::on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) { this->zwave_proxy_frame(msg); } -#endif -#ifdef USE_ZWAVE_PROXY -void APIServerConnection::on_z_wave_proxy_request(const ZWaveProxyRequest &msg) { this->zwave_proxy_request(msg); } -#endif -#ifdef USE_IR_RF -void APIServerConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) { - this->infrared_rf_transmit_raw_timings(msg); -} -#endif - void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { // Check authentication/connection requirements for messages switch (msg_type) { diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index b8c9e4da6f..4dc6ce27d0 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -229,268 +229,7 @@ class APIServerConnectionBase : public ProtoService { }; class APIServerConnection : public APIServerConnectionBase { - public: - virtual bool send_hello_response(const HelloRequest &msg) = 0; - virtual bool send_disconnect_response() = 0; - virtual bool send_ping_response() = 0; - virtual bool send_device_info_response() = 0; - virtual void list_entities() = 0; - virtual void subscribe_states() = 0; - virtual void subscribe_logs(const SubscribeLogsRequest &msg) = 0; -#ifdef USE_API_HOMEASSISTANT_SERVICES - virtual void subscribe_homeassistant_services() = 0; -#endif -#ifdef USE_API_HOMEASSISTANT_STATES - virtual void subscribe_home_assistant_states() = 0; -#endif -#ifdef USE_API_USER_DEFINED_ACTIONS - virtual void execute_service(const ExecuteServiceRequest &msg) = 0; -#endif -#ifdef USE_API_NOISE - virtual bool send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyRequest &msg) = 0; -#endif -#ifdef USE_BUTTON - virtual void button_command(const ButtonCommandRequest &msg) = 0; -#endif -#ifdef USE_CAMERA - virtual void camera_image(const CameraImageRequest &msg) = 0; -#endif -#ifdef USE_CLIMATE - virtual void climate_command(const ClimateCommandRequest &msg) = 0; -#endif -#ifdef USE_COVER - virtual void cover_command(const CoverCommandRequest &msg) = 0; -#endif -#ifdef USE_DATETIME_DATE - virtual void date_command(const DateCommandRequest &msg) = 0; -#endif -#ifdef USE_DATETIME_DATETIME - virtual void datetime_command(const DateTimeCommandRequest &msg) = 0; -#endif -#ifdef USE_FAN - virtual void fan_command(const FanCommandRequest &msg) = 0; -#endif -#ifdef USE_LIGHT - virtual void light_command(const LightCommandRequest &msg) = 0; -#endif -#ifdef USE_LOCK - virtual void lock_command(const LockCommandRequest &msg) = 0; -#endif -#ifdef USE_MEDIA_PLAYER - virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0; -#endif -#ifdef USE_NUMBER - virtual void number_command(const NumberCommandRequest &msg) = 0; -#endif -#ifdef USE_SELECT - virtual void select_command(const SelectCommandRequest &msg) = 0; -#endif -#ifdef USE_SIREN - virtual void siren_command(const SirenCommandRequest &msg) = 0; -#endif -#ifdef USE_SWITCH - virtual void switch_command(const SwitchCommandRequest &msg) = 0; -#endif -#ifdef USE_TEXT - virtual void text_command(const TextCommandRequest &msg) = 0; -#endif -#ifdef USE_DATETIME_TIME - virtual void time_command(const TimeCommandRequest &msg) = 0; -#endif -#ifdef USE_UPDATE - virtual void update_command(const UpdateCommandRequest &msg) = 0; -#endif -#ifdef USE_VALVE - virtual void valve_command(const ValveCommandRequest &msg) = 0; -#endif -#ifdef USE_WATER_HEATER - virtual void water_heater_command(const WaterHeaterCommandRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_device_request(const BluetoothDeviceRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual bool send_subscribe_bluetooth_connections_free_response() = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void unsubscribe_bluetooth_le_advertisements() = 0; -#endif -#ifdef USE_BLUETOOTH_PROXY - virtual void bluetooth_scanner_set_mode(const BluetoothScannerSetModeRequest &msg) = 0; -#endif -#ifdef USE_VOICE_ASSISTANT - virtual void subscribe_voice_assistant(const SubscribeVoiceAssistantRequest &msg) = 0; -#endif -#ifdef USE_VOICE_ASSISTANT - virtual bool send_voice_assistant_get_configuration_response(const VoiceAssistantConfigurationRequest &msg) = 0; -#endif -#ifdef USE_VOICE_ASSISTANT - virtual void voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) = 0; -#endif -#ifdef USE_ALARM_CONTROL_PANEL - virtual void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) = 0; -#endif -#ifdef USE_ZWAVE_PROXY - virtual void zwave_proxy_frame(const ZWaveProxyFrame &msg) = 0; -#endif -#ifdef USE_ZWAVE_PROXY - virtual void zwave_proxy_request(const ZWaveProxyRequest &msg) = 0; -#endif -#ifdef USE_IR_RF - virtual void infrared_rf_transmit_raw_timings(const InfraredRFTransmitRawTimingsRequest &msg) = 0; -#endif protected: - void on_hello_request(const HelloRequest &msg) override; - void on_disconnect_request() override; - void on_ping_request() override; - void on_device_info_request() override; - void on_list_entities_request() override; - void on_subscribe_states_request() override; - void on_subscribe_logs_request(const SubscribeLogsRequest &msg) override; -#ifdef USE_API_HOMEASSISTANT_SERVICES - void on_subscribe_homeassistant_services_request() override; -#endif -#ifdef USE_API_HOMEASSISTANT_STATES - void on_subscribe_home_assistant_states_request() override; -#endif -#ifdef USE_API_USER_DEFINED_ACTIONS - void on_execute_service_request(const ExecuteServiceRequest &msg) override; -#endif -#ifdef USE_API_NOISE - void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) override; -#endif -#ifdef USE_BUTTON - void on_button_command_request(const ButtonCommandRequest &msg) override; -#endif -#ifdef USE_CAMERA - void on_camera_image_request(const CameraImageRequest &msg) override; -#endif -#ifdef USE_CLIMATE - void on_climate_command_request(const ClimateCommandRequest &msg) override; -#endif -#ifdef USE_COVER - void on_cover_command_request(const CoverCommandRequest &msg) override; -#endif -#ifdef USE_DATETIME_DATE - void on_date_command_request(const DateCommandRequest &msg) override; -#endif -#ifdef USE_DATETIME_DATETIME - void on_date_time_command_request(const DateTimeCommandRequest &msg) override; -#endif -#ifdef USE_FAN - void on_fan_command_request(const FanCommandRequest &msg) override; -#endif -#ifdef USE_LIGHT - void on_light_command_request(const LightCommandRequest &msg) override; -#endif -#ifdef USE_LOCK - void on_lock_command_request(const LockCommandRequest &msg) override; -#endif -#ifdef USE_MEDIA_PLAYER - void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override; -#endif -#ifdef USE_NUMBER - void on_number_command_request(const NumberCommandRequest &msg) override; -#endif -#ifdef USE_SELECT - void on_select_command_request(const SelectCommandRequest &msg) override; -#endif -#ifdef USE_SIREN - void on_siren_command_request(const SirenCommandRequest &msg) override; -#endif -#ifdef USE_SWITCH - void on_switch_command_request(const SwitchCommandRequest &msg) override; -#endif -#ifdef USE_TEXT - void on_text_command_request(const TextCommandRequest &msg) override; -#endif -#ifdef USE_DATETIME_TIME - void on_time_command_request(const TimeCommandRequest &msg) override; -#endif -#ifdef USE_UPDATE - void on_update_command_request(const UpdateCommandRequest &msg) override; -#endif -#ifdef USE_VALVE - void on_valve_command_request(const ValveCommandRequest &msg) override; -#endif -#ifdef USE_WATER_HEATER - void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_subscribe_bluetooth_connections_free_request() override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_unsubscribe_bluetooth_le_advertisements_request() override; -#endif -#ifdef USE_BLUETOOTH_PROXY - void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override; -#endif -#ifdef USE_VOICE_ASSISTANT - void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) override; -#endif -#ifdef USE_VOICE_ASSISTANT - void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) override; -#endif -#ifdef USE_VOICE_ASSISTANT - void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; -#endif -#ifdef USE_ALARM_CONTROL_PANEL - void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) override; -#endif -#ifdef USE_ZWAVE_PROXY - void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) override; -#endif -#ifdef USE_ZWAVE_PROXY - void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override; -#endif -#ifdef USE_IR_RF - void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) override; -#endif void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 5fbc1137a8..8673996a25 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2906,7 +2906,6 @@ static const char *const TAG = "api.service"; class_name = "APIServerConnection" hpp += "\n" hpp += f"class {class_name} : public {class_name}Base {{\n" - hpp += " public:\n" hpp_protected = "" cpp += "\n" @@ -2914,14 +2913,8 @@ static const char *const TAG = "api.service"; message_auth_map: dict[str, bool] = {} message_conn_map: dict[str, bool] = {} - m = serv.method[0] for m in serv.method: - func = m.name inp = m.input_type[1:] - ret = m.output_type[1:] - is_void = ret == "void" - snake = camel_to_snake(inp) - on_func = f"on_{snake}" needs_conn = get_opt(m, pb.needs_setup_connection, True) needs_auth = get_opt(m, pb.needs_authentication, True) @@ -2929,39 +2922,6 @@ static const char *const TAG = "api.service"; message_auth_map[inp] = needs_auth message_conn_map[inp] = needs_conn - ifdef = message_ifdef_map.get(inp, ifdefs.get(inp)) - - if ifdef is not None: - hpp += f"#ifdef {ifdef}\n" - hpp_protected += f"#ifdef {ifdef}\n" - cpp += f"#ifdef {ifdef}\n" - - is_empty = inp in EMPTY_MESSAGES - param = "" if is_empty else f"const {inp} &msg" - arg = "" if is_empty else "msg" - - hpp_protected += f" void {on_func}({param}) override;\n" - if is_void: - hpp += f" virtual void {func}({param}) = 0;\n" - else: - hpp += f" virtual bool send_{func}_response({param}) = 0;\n" - - cpp += f"void {class_name}::{on_func}({param}) {{\n" - body = "" - if is_void: - body += f"this->{func}({arg});\n" - else: - body += f"if (!this->send_{func}_response({arg})) {{\n" - body += " this->on_fatal_error();\n" - body += "}\n" - - cpp += indent(body) + "\n" + "}\n" - - if ifdef is not None: - hpp += "#endif\n" - hpp_protected += "#endif\n" - cpp += "#endif\n" - # Generate optimized read_message with authentication checking # Categorize messages by their authentication requirements no_conn_ids: set[int] = set() From c28c97fbaf15c4ce353317e873054fb00a1d7a6d Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Mon, 9 Feb 2026 09:19:00 -0600 Subject: [PATCH 0583/2030] [mixer] Refactor for stability and to support Sendspin (#12253) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/mixer/speaker/__init__.py | 10 +- esphome/components/mixer/speaker/automation.h | 4 +- .../mixer/speaker/mixer_speaker.cpp | 438 +++++++++++++----- .../components/mixer/speaker/mixer_speaker.h | 53 ++- 4 files changed, 364 insertions(+), 141 deletions(-) diff --git a/esphome/components/mixer/speaker/__init__.py b/esphome/components/mixer/speaker/__init__.py index c4069851af..a3025d7121 100644 --- a/esphome/components/mixer/speaker/__init__.py +++ b/esphome/components/mixer/speaker/__init__.py @@ -1,6 +1,6 @@ from esphome import automation import esphome.codegen as cg -from esphome.components import audio, esp32, speaker +from esphome.components import audio, esp32, socket, speaker import esphome.config_validation as cv from esphome.const import ( CONF_BITS_PER_SAMPLE, @@ -61,7 +61,7 @@ def _set_stream_limits(config): def _validate_source_speaker(config): fconf = fv.full_config.get() - # Get ID for the output speaker and add it to the source speakrs config to easily inherit properties + # Get ID for the output speaker and add it to the source speakers config to easily inherit properties path = fconf.get_path_for_id(config[CONF_ID])[:-3] path.append(CONF_OUTPUT_SPEAKER) output_speaker_id = fconf.get_config_for_path(path) @@ -111,6 +111,9 @@ FINAL_VALIDATE_SCHEMA = cv.All( async def to_code(config): + # Enable wake_loop_threadsafe for immediate command processing from other tasks + socket.require_wake_loop_threadsafe() + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) @@ -127,6 +130,9 @@ async def to_code(config): "CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True ) + # Initialize FixedVector with exact count of source speakers + cg.add(var.init_source_speakers(len(config[CONF_SOURCE_SPEAKERS]))) + for speaker_config in config[CONF_SOURCE_SPEAKERS]: source_speaker = cg.new_Pvariable(speaker_config[CONF_ID]) diff --git a/esphome/components/mixer/speaker/automation.h b/esphome/components/mixer/speaker/automation.h index 2fb2f49373..4fa3853583 100644 --- a/esphome/components/mixer/speaker/automation.h +++ b/esphome/components/mixer/speaker/automation.h @@ -8,8 +8,8 @@ namespace esphome { namespace mixer_speaker { template<typename... Ts> class DuckingApplyAction : public Action<Ts...>, public Parented<SourceSpeaker> { - TEMPLATABLE_VALUE(uint8_t, decibel_reduction) - TEMPLATABLE_VALUE(uint32_t, duration) + TEMPLATABLE_VALUE(uint8_t, decibel_reduction); + TEMPLATABLE_VALUE(uint32_t, duration); void play(const Ts &...x) override { this->parent_->apply_ducking(this->decibel_reduction_.value(x...), this->duration_.value(x...)); } diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 043b629cf1..100acbebc3 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -2,11 +2,13 @@ #ifdef USE_ESP32 +#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include <algorithm> +#include <array> #include <cstring> namespace esphome { @@ -14,6 +16,7 @@ namespace mixer_speaker { static const UBaseType_t MIXER_TASK_PRIORITY = 10; +static const uint32_t STOPPING_TIMEOUT_MS = 5000; static const uint32_t TRANSFER_BUFFER_DURATION_MS = 50; static const uint32_t TASK_DELAY_MS = 25; @@ -27,21 +30,53 @@ static const char *const TAG = "speaker_mixer"; // Gives the Q15 fixed point scaling factor to reduce by 0 dB, 1dB, ..., 50 dB // dB to PCM scaling factor formula: floating_point_scale_factor = 2^(-db/6.014) // float to Q15 fixed point formula: q15_scale_factor = floating_point_scale_factor * 2^(15) -static const std::vector<int16_t> DECIBEL_REDUCTION_TABLE = { +static const std::array<int16_t, 51> DECIBEL_REDUCTION_TABLE = { 32767, 29201, 26022, 23189, 20665, 18415, 16410, 14624, 13032, 11613, 10349, 9222, 8218, 7324, 6527, 5816, 5183, 4619, 4116, 3668, 3269, 2913, 2596, 2313, 2061, 1837, 1637, 1459, 1300, 1158, 1032, 920, 820, 731, 651, 580, 517, 461, 411, 366, 326, 291, 259, 231, 206, 183, 163, 146, 130, 116, 103}; -enum MixerEventGroupBits : uint32_t { - COMMAND_STOP = (1 << 0), // stops the mixer task - STATE_STARTING = (1 << 10), - STATE_RUNNING = (1 << 11), - STATE_STOPPING = (1 << 12), - STATE_STOPPED = (1 << 13), - ERR_ESP_NO_MEM = (1 << 19), - ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits +// Event bits for SourceSpeaker command processing +enum SourceSpeakerEventBits : uint32_t { + SOURCE_SPEAKER_COMMAND_START = (1 << 0), + SOURCE_SPEAKER_COMMAND_STOP = (1 << 1), + SOURCE_SPEAKER_COMMAND_FINISH = (1 << 2), }; +// Event bits for mixer task control and state +enum MixerTaskEventBits : uint32_t { + MIXER_TASK_COMMAND_START = (1 << 0), + MIXER_TASK_COMMAND_STOP = (1 << 1), + MIXER_TASK_STATE_STARTING = (1 << 10), + MIXER_TASK_STATE_RUNNING = (1 << 11), + MIXER_TASK_STATE_STOPPING = (1 << 12), + MIXER_TASK_STATE_STOPPED = (1 << 13), + MIXER_TASK_ERR_ESP_NO_MEM = (1 << 19), + MIXER_TASK_ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits +}; + +static inline uint32_t atomic_subtract_clamped(std::atomic<uint32_t> &var, uint32_t amount) { + uint32_t current = var.load(std::memory_order_acquire); + uint32_t subtracted = 0; + if (current > 0) { + uint32_t new_value; + do { + subtracted = std::min(amount, current); + new_value = current - subtracted; + } while (!var.compare_exchange_weak(current, new_value, std::memory_order_release, std::memory_order_acquire)); + } + return subtracted; +} + +static bool create_event_group(EventGroupHandle_t &event_group, Component *component) { + event_group = xEventGroupCreate(); + if (event_group == nullptr) { + ESP_LOGE(TAG, "Failed to create event group"); + component->mark_failed(); + return false; + } + return true; +} + void SourceSpeaker::dump_config() { ESP_LOGCONFIG(TAG, "Mixer Source Speaker\n" @@ -55,22 +90,70 @@ void SourceSpeaker::dump_config() { } void SourceSpeaker::setup() { - this->parent_->get_output_speaker()->add_audio_output_callback([this](uint32_t new_frames, int64_t write_timestamp) { - // The SourceSpeaker may not have included any audio in the mixed output, so verify there were pending frames - uint32_t speakers_playback_frames = std::min(new_frames, this->pending_playback_frames_); - this->pending_playback_frames_ -= speakers_playback_frames; + if (!create_event_group(this->event_group_, this)) { + return; + } - if (speakers_playback_frames > 0) { - this->audio_output_callback_(speakers_playback_frames, write_timestamp); + // Start with loop disabled since we begin in STATE_STOPPED with no pending commands + this->disable_loop(); + + this->parent_->get_output_speaker()->add_audio_output_callback([this](uint32_t new_frames, int64_t write_timestamp) { + // First, drain the playback delay (frames in pipeline before this source started contributing) + uint32_t delay_to_drain = atomic_subtract_clamped(this->playback_delay_frames_, new_frames); + uint32_t remaining_frames = new_frames - delay_to_drain; + + // Then, count towards this source's pending playback frames + if (remaining_frames > 0) { + uint32_t speakers_playback_frames = atomic_subtract_clamped(this->pending_playback_frames_, remaining_frames); + if (speakers_playback_frames > 0) { + this->audio_output_callback_(speakers_playback_frames, write_timestamp); + } } }); } void SourceSpeaker::loop() { + uint32_t event_bits = xEventGroupGetBits(this->event_group_); + + // Process commands with priority: STOP > FINISH > START + // This ensures stop commands take precedence over conflicting start commands + if (event_bits & SOURCE_SPEAKER_COMMAND_STOP) { + if (this->state_ == speaker::STATE_RUNNING) { + // Clear both STOP and START bits - stop takes precedence + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_STOP | SOURCE_SPEAKER_COMMAND_START); + this->enter_stopping_state_(); + } else if (this->state_ == speaker::STATE_STOPPED) { + // Already stopped, just clear the command bits + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_STOP | SOURCE_SPEAKER_COMMAND_START); + } + // Leave bits set if transitioning states (STARTING/STOPPING) - will be processed once state allows + } else if (event_bits & SOURCE_SPEAKER_COMMAND_FINISH) { + if (this->state_ == speaker::STATE_RUNNING) { + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_FINISH); + this->stop_gracefully_ = true; + } else if (this->state_ == speaker::STATE_STOPPED) { + // Already stopped, just clear the command bit + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_FINISH); + } + // Leave bit set if transitioning states - will be processed once state allows + } else if (event_bits & SOURCE_SPEAKER_COMMAND_START) { + if (this->state_ == speaker::STATE_STOPPED) { + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_START); + this->state_ = speaker::STATE_STARTING; + } else if (this->state_ == speaker::STATE_RUNNING) { + // Already running, just clear the command bit + xEventGroupClearBits(this->event_group_, SOURCE_SPEAKER_COMMAND_START); + } + // Leave bit set if transitioning states - will be processed once state allows + } + // Process state machine switch (this->state_) { case speaker::STATE_STARTING: { esp_err_t err = this->start_(); if (err == ESP_OK) { + this->pending_playback_frames_.store(0, std::memory_order_release); // reset pending playback frames + this->playback_delay_frames_.store(0, std::memory_order_release); // reset playback delay + this->has_contributed_.store(false, std::memory_order_release); // reset contribution tracking this->state_ = speaker::STATE_RUNNING; this->stop_gracefully_ = false; this->last_seen_data_ms_ = millis(); @@ -78,41 +161,62 @@ void SourceSpeaker::loop() { } else { switch (err) { case ESP_ERR_NO_MEM: - this->status_set_error(LOG_STR("Failed to start mixer: not enough memory")); + this->status_set_error(LOG_STR("Not enough memory")); break; case ESP_ERR_NOT_SUPPORTED: - this->status_set_error(LOG_STR("Failed to start mixer: unsupported bits per sample")); + this->status_set_error(LOG_STR("Unsupported bit depth")); break; case ESP_ERR_INVALID_ARG: - this->status_set_error( - LOG_STR("Failed to start mixer: audio stream isn't compatible with the other audio stream.")); + this->status_set_error(LOG_STR("Incompatible audio streams")); break; case ESP_ERR_INVALID_STATE: - this->status_set_error(LOG_STR("Failed to start mixer: mixer task failed to start")); + this->status_set_error(LOG_STR("Task failed")); break; default: - this->status_set_error(LOG_STR("Failed to start mixer")); + this->status_set_error(LOG_STR("Failed")); break; } - this->state_ = speaker::STATE_STOPPING; + this->enter_stopping_state_(); } break; } case speaker::STATE_RUNNING: - if (!this->transfer_buffer_->has_buffered_data()) { + if (!this->transfer_buffer_->has_buffered_data() && + (this->pending_playback_frames_.load(std::memory_order_acquire) == 0)) { + // No audio data in buffer waiting to get mixed and no frames are pending playback if ((this->timeout_ms_.has_value() && ((millis() - this->last_seen_data_ms_) > this->timeout_ms_.value())) || this->stop_gracefully_) { - this->state_ = speaker::STATE_STOPPING; + // Timeout exceeded or graceful stop requested + this->enter_stopping_state_(); } } break; - case speaker::STATE_STOPPING: - this->stop_(); - this->stop_gracefully_ = false; - this->state_ = speaker::STATE_STOPPED; + case speaker::STATE_STOPPING: { + if ((this->parent_->get_output_speaker()->get_pause_state()) || + ((millis() - this->stopping_start_ms_) > STOPPING_TIMEOUT_MS)) { + // If parent speaker is paused or if the stopping timeout is exceeded, force stop the output speaker + this->parent_->get_output_speaker()->stop(); + } + + if (this->parent_->get_output_speaker()->is_stopped() || + (this->pending_playback_frames_.load(std::memory_order_acquire) == 0)) { + // Output speaker is stopped OR all pending playback frames have played + this->pending_playback_frames_.store(0, std::memory_order_release); + this->stop_gracefully_ = false; + + this->state_ = speaker::STATE_STOPPED; + } break; + } case speaker::STATE_STOPPED: + // Re-check event bits for any new commands that may have arrived + event_bits = xEventGroupGetBits(this->event_group_); + if (!(event_bits & + (SOURCE_SPEAKER_COMMAND_START | SOURCE_SPEAKER_COMMAND_STOP | SOURCE_SPEAKER_COMMAND_FINISH))) { + // No pending commands, disable loop to save CPU cycles + this->disable_loop(); + } break; } } @@ -122,17 +226,34 @@ size_t SourceSpeaker::play(const uint8_t *data, size_t length, TickType_t ticks_ this->start(); } size_t bytes_written = 0; - if (this->ring_buffer_.use_count() == 1) { - std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + if (temp_ring_buffer.use_count() > 0) { + // Only write to the ring buffer if the reference is valid bytes_written = temp_ring_buffer->write_without_replacement(data, length, ticks_to_wait); if (bytes_written > 0) { this->last_seen_data_ms_ = millis(); } + } else { + // Delay to avoid repeatedly hammering while waiting for the speaker to start + vTaskDelay(ticks_to_wait); } return bytes_written; } -void SourceSpeaker::start() { this->state_ = speaker::STATE_STARTING; } +void SourceSpeaker::send_command_(uint32_t command_bit, bool wake_loop) { + this->enable_loop_soon_any_context(); + uint32_t event_bits = xEventGroupGetBits(this->event_group_); + if (!(event_bits & command_bit)) { + xEventGroupSetBits(this->event_group_, command_bit); +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + if (wake_loop) { + App.wake_loop_threadsafe(); + } +#endif + } +} + +void SourceSpeaker::start() { this->send_command_(SOURCE_SPEAKER_COMMAND_START, true); } esp_err_t SourceSpeaker::start_() { const size_t ring_buffer_size = this->audio_stream_info_.ms_to_bytes(this->buffer_duration_ms_); @@ -143,35 +264,26 @@ esp_err_t SourceSpeaker::start_() { if (this->transfer_buffer_ == nullptr) { return ESP_ERR_NO_MEM; } - std::shared_ptr<RingBuffer> temp_ring_buffer; - if (!this->ring_buffer_.use_count()) { + std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + if (!temp_ring_buffer) { temp_ring_buffer = RingBuffer::create(ring_buffer_size); this->ring_buffer_ = temp_ring_buffer; } - if (!this->ring_buffer_.use_count()) { + if (!temp_ring_buffer) { return ESP_ERR_NO_MEM; } else { this->transfer_buffer_->set_source(temp_ring_buffer); } } - this->pending_playback_frames_ = 0; // reset return this->parent_->start(this->audio_stream_info_); } -void SourceSpeaker::stop() { - if (this->state_ != speaker::STATE_STOPPED) { - this->state_ = speaker::STATE_STOPPING; - } -} +void SourceSpeaker::stop() { this->send_command_(SOURCE_SPEAKER_COMMAND_STOP); } -void SourceSpeaker::stop_() { - this->transfer_buffer_.reset(); // deallocates the transfer buffer -} - -void SourceSpeaker::finish() { this->stop_gracefully_ = true; } +void SourceSpeaker::finish() { this->send_command_(SOURCE_SPEAKER_COMMAND_FINISH); } bool SourceSpeaker::has_buffered_data() const { return ((this->transfer_buffer_.use_count() > 0) && this->transfer_buffer_->has_buffered_data()); @@ -191,19 +303,16 @@ void SourceSpeaker::set_volume(float volume) { float SourceSpeaker::get_volume() { return this->parent_->get_output_speaker()->get_volume(); } -size_t SourceSpeaker::process_data_from_source(TickType_t ticks_to_wait) { - if (!this->transfer_buffer_.use_count()) { - return 0; - } - +size_t SourceSpeaker::process_data_from_source(std::shared_ptr<audio::AudioSourceTransferBuffer> &transfer_buffer, + TickType_t ticks_to_wait) { // Store current offset, as these samples are already ducked - const size_t current_length = this->transfer_buffer_->available(); + const size_t current_length = transfer_buffer->available(); - size_t bytes_read = this->transfer_buffer_->transfer_data_from_source(ticks_to_wait); + size_t bytes_read = transfer_buffer->transfer_data_from_source(ticks_to_wait); uint32_t samples_to_duck = this->audio_stream_info_.bytes_to_samples(bytes_read); if (samples_to_duck > 0) { - int16_t *current_buffer = reinterpret_cast<int16_t *>(this->transfer_buffer_->get_buffer_start() + current_length); + int16_t *current_buffer = reinterpret_cast<int16_t *>(transfer_buffer->get_buffer_start() + current_length); duck_samples(current_buffer, samples_to_duck, &this->current_ducking_db_reduction_, &this->ducking_transition_samples_remaining_, this->samples_per_ducking_step_, @@ -215,10 +324,13 @@ size_t SourceSpeaker::process_data_from_source(TickType_t ticks_to_wait) { void SourceSpeaker::apply_ducking(uint8_t decibel_reduction, uint32_t duration) { if (this->target_ducking_db_reduction_ != decibel_reduction) { + // Start transition from the previous target (which becomes the new current level) this->current_ducking_db_reduction_ = this->target_ducking_db_reduction_; this->target_ducking_db_reduction_ = decibel_reduction; + // Calculate the number of intermediate dB steps for the transition timing. + // Subtract 1 because the first step is taken immediately after this calculation. uint8_t total_ducking_steps = 0; if (this->target_ducking_db_reduction_ > this->current_ducking_db_reduction_) { // The dB reduction level is increasing (which results in quieter audio) @@ -234,7 +346,7 @@ void SourceSpeaker::apply_ducking(uint8_t decibel_reduction, uint32_t duration) this->samples_per_ducking_step_ = this->ducking_transition_samples_remaining_ / total_ducking_steps; this->ducking_transition_samples_remaining_ = - this->samples_per_ducking_step_ * total_ducking_steps; // Adjust for integer division rounding + this->samples_per_ducking_step_ * total_ducking_steps; // adjust for integer division rounding this->current_ducking_db_reduction_ += this->db_change_per_ducking_step_; } else { @@ -293,6 +405,12 @@ void SourceSpeaker::duck_samples(int16_t *input_buffer, uint32_t input_samples_t } } +void SourceSpeaker::enter_stopping_state_() { + this->state_ = speaker::STATE_STOPPING; + this->stopping_start_ms_ = millis(); + this->transfer_buffer_.reset(); +} + void MixerSpeaker::dump_config() { ESP_LOGCONFIG(TAG, "Speaker Mixer:\n" @@ -301,42 +419,74 @@ void MixerSpeaker::dump_config() { } void MixerSpeaker::setup() { - this->event_group_ = xEventGroupCreate(); - - if (this->event_group_ == nullptr) { - ESP_LOGE(TAG, "Failed to create event group"); - this->mark_failed(); + if (!create_event_group(this->event_group_, this)) { return; } + + // Register callback to track frames in the output pipeline + this->output_speaker_->add_audio_output_callback([this](uint32_t new_frames, int64_t write_timestamp) { + atomic_subtract_clamped(this->frames_in_pipeline_, new_frames); + }); + + // Start with loop disabled since no task is running and no commands are pending + this->disable_loop(); } void MixerSpeaker::loop() { uint32_t event_group_bits = xEventGroupGetBits(this->event_group_); - if (event_group_bits & MixerEventGroupBits::STATE_STARTING) { - ESP_LOGD(TAG, "Starting speaker mixer"); - xEventGroupClearBits(this->event_group_, MixerEventGroupBits::STATE_STARTING); + // Handle pending start request + if (event_group_bits & MIXER_TASK_COMMAND_START) { + // Only start the task if it's fully stopped and cleaned up + if (!this->status_has_error() && (this->task_handle_ == nullptr) && (this->task_stack_buffer_ == nullptr)) { + esp_err_t err = this->start_task_(); + switch (err) { + case ESP_OK: + xEventGroupClearBits(this->event_group_, MIXER_TASK_COMMAND_START); + break; + case ESP_ERR_NO_MEM: + ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); + this->status_momentary_error("memory-failure", 1000); + return; + case ESP_ERR_INVALID_STATE: + ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); + this->status_momentary_error("task-failure", 1000); + return; + default: + ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); + this->status_momentary_error("failure", 1000); + return; + } + } } - if (event_group_bits & MixerEventGroupBits::ERR_ESP_NO_MEM) { - this->status_set_error(LOG_STR("Failed to allocate the mixer's internal buffer")); - xEventGroupClearBits(this->event_group_, MixerEventGroupBits::ERR_ESP_NO_MEM); + + if (event_group_bits & MIXER_TASK_STATE_STARTING) { + ESP_LOGD(TAG, "Starting"); + xEventGroupClearBits(this->event_group_, MIXER_TASK_STATE_STARTING); } - if (event_group_bits & MixerEventGroupBits::STATE_RUNNING) { - ESP_LOGD(TAG, "Started speaker mixer"); + if (event_group_bits & MIXER_TASK_ERR_ESP_NO_MEM) { + this->status_set_error(LOG_STR("Not enough memory")); + xEventGroupClearBits(this->event_group_, MIXER_TASK_ERR_ESP_NO_MEM); + } + if (event_group_bits & MIXER_TASK_STATE_RUNNING) { + ESP_LOGV(TAG, "Started"); this->status_clear_error(); - xEventGroupClearBits(this->event_group_, MixerEventGroupBits::STATE_RUNNING); + xEventGroupClearBits(this->event_group_, MIXER_TASK_STATE_RUNNING); } - if (event_group_bits & MixerEventGroupBits::STATE_STOPPING) { - ESP_LOGD(TAG, "Stopping speaker mixer"); - xEventGroupClearBits(this->event_group_, MixerEventGroupBits::STATE_STOPPING); + if (event_group_bits & MIXER_TASK_STATE_STOPPING) { + ESP_LOGV(TAG, "Stopping"); + xEventGroupClearBits(this->event_group_, MIXER_TASK_STATE_STOPPING); } - if (event_group_bits & MixerEventGroupBits::STATE_STOPPED) { + if (event_group_bits & MIXER_TASK_STATE_STOPPED) { if (this->delete_task_() == ESP_OK) { - xEventGroupClearBits(this->event_group_, MixerEventGroupBits::ALL_BITS); + ESP_LOGD(TAG, "Stopped"); + xEventGroupClearBits(this->event_group_, MIXER_TASK_ALL_BITS); } } if (this->task_handle_ != nullptr) { + // If the mixer task is running, check if all source speakers are stopped + bool all_stopped = true; for (auto &speaker : this->source_speakers_) { @@ -344,7 +494,15 @@ void MixerSpeaker::loop() { } if (all_stopped) { - this->stop(); + // Send stop command signal to the mixer task since no source speakers are active + xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_STOP); + } + } else if (this->task_stack_buffer_ == nullptr) { + // Task is fully stopped and cleaned up, check if we can disable loop + event_group_bits = xEventGroupGetBits(this->event_group_); + if (event_group_bits == 0) { + // No pending events, disable loop to save CPU cycles + this->disable_loop(); } } } @@ -366,7 +524,18 @@ esp_err_t MixerSpeaker::start(audio::AudioStreamInfo &stream_info) { } } - return this->start_task_(); + this->enable_loop_soon_any_context(); // ensure loop processes command + + uint32_t event_bits = xEventGroupGetBits(this->event_group_); + if (!(event_bits & MIXER_TASK_COMMAND_START)) { + // Set MIXER_TASK_COMMAND_START bit if not already set, and then immediately wake for low latency + xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_START); +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + App.wake_loop_threadsafe(); +#endif + } + + return ESP_OK; } esp_err_t MixerSpeaker::start_task_() { @@ -397,28 +566,31 @@ esp_err_t MixerSpeaker::start_task_() { } esp_err_t MixerSpeaker::delete_task_() { - if (!this->task_created_) { + if (this->task_handle_ != nullptr) { + // Delete the task + vTaskDelete(this->task_handle_); this->task_handle_ = nullptr; - - if (this->task_stack_buffer_ != nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } - - this->task_stack_buffer_ = nullptr; - } - - return ESP_OK; } - return ESP_ERR_INVALID_STATE; -} + if ((this->task_handle_ == nullptr) && (this->task_stack_buffer_ != nullptr)) { + // Deallocate the task stack buffer + if (this->task_stack_in_psram_) { + RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); + stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); + } else { + RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); + stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); + } -void MixerSpeaker::stop() { xEventGroupSetBits(this->event_group_, MixerEventGroupBits::COMMAND_STOP); } + this->task_stack_buffer_ = nullptr; + } + + if ((this->task_handle_ != nullptr) || (this->task_stack_buffer_ != nullptr)) { + return ESP_ERR_INVALID_STATE; + } + + return ESP_OK; +} void MixerSpeaker::copy_frames(const int16_t *input_buffer, audio::AudioStreamInfo input_stream_info, int16_t *output_buffer, audio::AudioStreamInfo output_stream_info, @@ -472,32 +644,34 @@ void MixerSpeaker::mix_audio_samples(const int16_t *primary_buffer, audio::Audio } void MixerSpeaker::audio_mixer_task(void *params) { - MixerSpeaker *this_mixer = (MixerSpeaker *) params; + MixerSpeaker *this_mixer = static_cast<MixerSpeaker *>(params); - xEventGroupSetBits(this_mixer->event_group_, MixerEventGroupBits::STATE_STARTING); - - this_mixer->task_created_ = true; + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STARTING); std::unique_ptr<audio::AudioSinkTransferBuffer> output_transfer_buffer = audio::AudioSinkTransferBuffer::create( this_mixer->audio_stream_info_.value().ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); if (output_transfer_buffer == nullptr) { - xEventGroupSetBits(this_mixer->event_group_, - MixerEventGroupBits::STATE_STOPPED | MixerEventGroupBits::ERR_ESP_NO_MEM); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED | MIXER_TASK_ERR_ESP_NO_MEM); - this_mixer->task_created_ = false; - vTaskDelete(nullptr); + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } output_transfer_buffer->set_sink(this_mixer->output_speaker_); - xEventGroupSetBits(this_mixer->event_group_, MixerEventGroupBits::STATE_RUNNING); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_RUNNING); bool sent_finished = false; + // Pre-allocate vectors to avoid heap allocation in the loop (max 8 source speakers per schema) + FixedVector<SourceSpeaker *> speakers_with_data; + FixedVector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; + speakers_with_data.init(this_mixer->source_speakers_.size()); + transfer_buffers_with_data.init(this_mixer->source_speakers_.size()); + while (true) { uint32_t event_group_bits = xEventGroupGetBits(this_mixer->event_group_); - if (event_group_bits & MixerEventGroupBits::COMMAND_STOP) { + if (event_group_bits & MIXER_TASK_COMMAND_STOP) { break; } @@ -507,15 +681,20 @@ void MixerSpeaker::audio_mixer_task(void *params) { const uint32_t output_frames_free = this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free()); - std::vector<SourceSpeaker *> speakers_with_data; - std::vector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; + speakers_with_data.clear(); + transfer_buffers_with_data.clear(); for (auto &speaker : this_mixer->source_speakers_) { - if (speaker->get_transfer_buffer().use_count() > 0) { + if (speaker->is_running() && !speaker->get_pause_state()) { + // Speaker is running and not paused, so it possibly can provide audio data std::shared_ptr<audio::AudioSourceTransferBuffer> transfer_buffer = speaker->get_transfer_buffer().lock(); - speaker->process_data_from_source(0); // Transfers and ducks audio from source ring buffers + if (transfer_buffer.use_count() == 0) { + // No transfer buffer allocated, so skip processing this speaker + continue; + } + speaker->process_data_from_source(transfer_buffer, 0); // Transfers and ducks audio from source ring buffers - if ((transfer_buffer->available() > 0) && !speaker->get_pause_state()) { + if (transfer_buffer->available() > 0) { // Store the locked transfer buffers in their own vector to avoid releasing ownership until after the loop transfer_buffers_with_data.push_back(transfer_buffer); speakers_with_data.push_back(speaker); @@ -547,13 +726,21 @@ void MixerSpeaker::audio_mixer_task(void *params) { reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), this_mixer->audio_stream_info_.value(), frames_to_mix); - // Update source speaker buffer length - transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); - speakers_with_data[0]->pending_playback_frames_ += frames_to_mix; + // Set playback delay for newly contributing source + if (!speakers_with_data[0]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[0]->playback_delay_frames_.store( + this_mixer->frames_in_pipeline_.load(std::memory_order_acquire), std::memory_order_release); + speakers_with_data[0]->has_contributed_.store(true, std::memory_order_release); + } - // Update output transfer buffer length + // Update source speaker pending frames + speakers_with_data[0]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); + transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); + + // Update output transfer buffer length and pipeline frame count output_transfer_buffer->increase_buffer_length( this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); + this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); } else { // Speaker's stream info doesn't match the output speaker's, so it's a new source speaker if (!this_mixer->output_speaker_->is_stopped()) { @@ -568,6 +755,8 @@ void MixerSpeaker::audio_mixer_task(void *params) { active_stream_info.get_sample_rate()); this_mixer->output_speaker_->set_audio_stream_info(this_mixer->audio_stream_info_.value()); this_mixer->output_speaker_->start(); + // Reset pipeline frame count since we're starting fresh with a new sample rate + this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); sent_finished = false; } } @@ -596,26 +785,39 @@ void MixerSpeaker::audio_mixer_task(void *params) { } } + // Get current pipeline depth for delay calculation (before incrementing) + uint32_t current_pipeline_frames = this_mixer->frames_in_pipeline_.load(std::memory_order_acquire); + // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { + // Set playback delay for newly contributing sources + if (!speakers_with_data[i]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[i]->playback_delay_frames_.store(current_pipeline_frames, std::memory_order_release); + speakers_with_data[i]->has_contributed_.store(true, std::memory_order_release); + } + + speakers_with_data[i]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); transfer_buffers_with_data[i]->decrease_buffer_length( speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); - speakers_with_data[i]->pending_playback_frames_ += frames_to_mix; } - // Update output transfer buffer length + // Update output transfer buffer length and pipeline frame count (once, not per source) output_transfer_buffer->increase_buffer_length( this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); + this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); } } - xEventGroupSetBits(this_mixer->event_group_, MixerEventGroupBits::STATE_STOPPING); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPING); + + // Reset pipeline frame count since the task is stopping + this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); output_transfer_buffer.reset(); - xEventGroupSetBits(this_mixer->event_group_, MixerEventGroupBits::STATE_STOPPED); - this_mixer->task_created_ = false; - vTaskDelete(nullptr); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED); + + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } } // namespace mixer_speaker diff --git a/esphome/components/mixer/speaker/mixer_speaker.h b/esphome/components/mixer/speaker/mixer_speaker.h index 48bacc4471..e920f9895a 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.h +++ b/esphome/components/mixer/speaker/mixer_speaker.h @@ -7,26 +7,31 @@ #include "esphome/components/speaker/speaker.h" #include "esphome/core/component.h" +#include "esphome/core/helpers.h" -#include <freertos/event_groups.h> #include <freertos/FreeRTOS.h> +#include <freertos/event_groups.h> + +#include <atomic> namespace esphome { namespace mixer_speaker { /* Classes for mixing several source speaker audio streams and writing it to another speaker component. * - Volume controls are passed through to the output speaker + * - Source speaker commands are signaled via event group bits and processed in its loop function to ensure thread + * safety * - Directly handles pausing at the SourceSpeaker level; pause state is not passed through to the output speaker. - * - Audio sent to the SourceSpeaker's must have 16 bits per sample. + * - Audio sent to the SourceSpeaker must have 16 bits per sample. * - Audio sent to the SourceSpeaker can have any number of channels. They are duplicated or ignored as needed to match * the number of channels required for the output speaker. - * - In queue mode, the audio sent to the SoureSpeakers can have different sample rates. + * - In queue mode, the audio sent to the SourceSpeakers can have different sample rates. * - In non-queue mode, the audio sent to the SourceSpeakers must have the same sample rates. * - SourceSpeaker has an internal ring buffer. It also allocates a shared_ptr for an AudioTranserBuffer object. * - Audio Data Flow: * - Audio data played on a SourceSpeaker first writes to its internal ring buffer. * - MixerSpeaker task temporarily takes shared ownership of each SourceSpeaker's AudioTransferBuffer. - * - MixerSpeaker calls SourceSpeaker's `process_data_from_source`, which tranfers audio from the SourceSpeaker's + * - MixerSpeaker calls SourceSpeaker's `process_data_from_source`, which transfers audio from the SourceSpeaker's * ring buffer to its AudioTransferBuffer. Audio ducking is applied at this step. * - In queue mode, MixerSpeaker prioritizes the earliest configured SourceSpeaker with audio data. Audio data is * sent to the output speaker. @@ -63,13 +68,15 @@ class SourceSpeaker : public speaker::Speaker, public Component { bool get_pause_state() const override { return this->pause_state_; } /// @brief Transfers audio from the ring buffer into the transfer buffer. Ducks audio while transferring. + /// @param transfer_buffer Locked shared_ptr to the transfer buffer (must be valid, not null) /// @param ticks_to_wait FreeRTOS ticks to wait while waiting to read from the ring buffer. /// @return Number of bytes transferred from the ring buffer. - size_t process_data_from_source(TickType_t ticks_to_wait); + size_t process_data_from_source(std::shared_ptr<audio::AudioSourceTransferBuffer> &transfer_buffer, + TickType_t ticks_to_wait); /// @brief Sets the ducking level for the source speaker. - /// @param decibel_reduction (uint8_t) The dB reduction level. For example, 0 is no change, 10 is a reduction by 10 dB - /// @param duration (uint32_t) The number of milliseconds to transition from the current level to the new level + /// @param decibel_reduction The dB reduction level. For example, 0 is no change, 10 is a reduction by 10 dB + /// @param duration The number of milliseconds to transition from the current level to the new level void apply_ducking(uint8_t decibel_reduction, uint32_t duration); void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; } @@ -81,14 +88,15 @@ class SourceSpeaker : public speaker::Speaker, public Component { protected: friend class MixerSpeaker; esp_err_t start_(); - void stop_(); + void enter_stopping_state_(); + void send_command_(uint32_t command_bit, bool wake_loop = false); /// @brief Ducks audio samples by a specified amount. When changing the ducking amount, it can transition gradually /// over a specified amount of samples. /// @param input_buffer buffer with audio samples to be ducked in place /// @param input_samples_to_duck number of samples to process in ``input_buffer`` /// @param current_ducking_db_reduction pointer to the current dB reduction - /// @param ducking_transition_samples_remaining pointer to the total number of samples left before the the + /// @param ducking_transition_samples_remaining pointer to the total number of samples left before the /// transition is finished /// @param samples_per_ducking_step total number of samples per ducking step for the transition /// @param db_change_per_ducking_step the change in dB reduction per step @@ -114,7 +122,12 @@ class SourceSpeaker : public speaker::Speaker, public Component { uint32_t ducking_transition_samples_remaining_{0}; uint32_t samples_per_ducking_step_{0}; - uint32_t pending_playback_frames_{0}; + std::atomic<uint32_t> pending_playback_frames_{0}; + std::atomic<uint32_t> playback_delay_frames_{0}; // Frames in output pipeline when this source started contributing + std::atomic<bool> has_contributed_{false}; // Tracks if source has contributed during this session + + EventGroupHandle_t event_group_{nullptr}; + uint32_t stopping_start_ms_{0}; }; class MixerSpeaker : public Component { @@ -123,10 +136,11 @@ class MixerSpeaker : public Component { void setup() override; void loop() override; + void init_source_speakers(size_t count) { this->source_speakers_.init(count); } void add_source_speaker(SourceSpeaker *source_speaker) { this->source_speakers_.push_back(source_speaker); } /// @brief Starts the mixer task. Called by a source speaker giving the current audio stream information - /// @param stream_info The calling source speakers audio stream information + /// @param stream_info The calling source speaker's audio stream information /// @return ESP_ERR_NOT_SUPPORTED if the incoming stream is incompatible due to unsupported bits per sample /// ESP_ERR_INVALID_ARG if the incoming stream is incompatible to be mixed with the other input audio stream /// ESP_ERR_NO_MEM if there isn't enough memory for the task's stack @@ -134,8 +148,6 @@ class MixerSpeaker : public Component { /// ESP_OK if the incoming stream is compatible and the mixer task starts esp_err_t start(audio::AudioStreamInfo &stream_info); - void stop(); - void set_output_channels(uint8_t output_channels) { this->output_channels_ = output_channels; } void set_output_speaker(speaker::Speaker *speaker) { this->output_speaker_ = speaker; } void set_queue_mode(bool queue_mode) { this->queue_mode_ = queue_mode; } @@ -143,6 +155,9 @@ class MixerSpeaker : public Component { speaker::Speaker *get_output_speaker() const { return this->output_speaker_; } + /// @brief Returns the current number of frames in the output pipeline (written but not yet played) + uint32_t get_frames_in_pipeline() const { return this->frames_in_pipeline_.load(std::memory_order_acquire); } + protected: /// @brief Copies audio frames from the input buffer to the output buffer taking into account the number of channels /// in each stream. If the output stream has more channels, the input samples are duplicated. If the output stream has @@ -159,11 +174,11 @@ class MixerSpeaker : public Component { /// and secondary samples are duplicated or dropped as necessary to ensure the output stream has the configured number /// of channels. Output samples are clamped to the corresponding int16 min or max values if the mixed sample /// overflows. - /// @param primary_buffer (int16_t *) samples buffer for the primary stream + /// @param primary_buffer samples buffer for the primary stream /// @param primary_stream_info stream info for the primary stream - /// @param secondary_buffer (int16_t *) samples buffer for secondary stream + /// @param secondary_buffer samples buffer for secondary stream /// @param secondary_stream_info stream info for the secondary stream - /// @param output_buffer (int16_t *) buffer for the mixed samples + /// @param output_buffer buffer for the mixed samples /// @param output_stream_info stream info for the output buffer /// @param frames_to_mix number of frames in the primary and secondary buffers to mix together static void mix_audio_samples(const int16_t *primary_buffer, audio::AudioStreamInfo primary_stream_info, @@ -185,20 +200,20 @@ class MixerSpeaker : public Component { EventGroupHandle_t event_group_{nullptr}; - std::vector<SourceSpeaker *> source_speakers_; + FixedVector<SourceSpeaker *> source_speakers_; speaker::Speaker *output_speaker_{nullptr}; uint8_t output_channels_; bool queue_mode_; bool task_stack_in_psram_{false}; - bool task_created_{false}; - TaskHandle_t task_handle_{nullptr}; StaticTask_t task_stack_; StackType_t *task_stack_buffer_{nullptr}; optional<audio::AudioStreamInfo> audio_stream_info_; + + std::atomic<uint32_t> frames_in_pipeline_{0}; // Frames written to output but not yet played }; } // namespace mixer_speaker From 919afa1553a40bd9c756d871a87b55a77de7bfb8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 11:47:59 -0600 Subject: [PATCH 0584/2030] [web_server_base] Fix RP2040 compilation when Crypto-no-arduino is present (#13887) --- esphome/components/web_server_base/__init__.py | 13 +++++++++++++ .../web_server_base/fix_rp2040_hash.py.script | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 esphome/components/web_server_base/fix_rp2040_hash.py.script diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 11408ae260..7986ac964d 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -1,8 +1,11 @@ +from pathlib import Path + import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_ID from esphome.core import CORE, coroutine_with_priority from esphome.coroutine import CoroPriority +from esphome.helpers import copy_file_if_changed CODEOWNERS = ["@esphome/core"] DEPENDENCIES = ["network"] @@ -49,5 +52,15 @@ async def to_code(config): CORE.add_platformio_option( "lib_ignore", ["ESPAsyncTCP", "AsyncTCP", "AsyncTCP_RP2040W"] ) + # ESPAsyncWebServer uses Hash library for sha1() on RP2040 + cg.add_library("Hash", None) + # Fix Hash.h include conflict: Crypto-no-arduino (used by dsmr) + # provides a Hash.h that shadows the framework's Hash library. + # Prepend the framework Hash path so it's found first. + copy_file_if_changed( + Path(__file__).parent / "fix_rp2040_hash.py.script", + CORE.relative_build_path("fix_rp2040_hash.py"), + ) + cg.add_platformio_option("extra_scripts", ["pre:fix_rp2040_hash.py"]) # https://github.com/ESP32Async/ESPAsyncWebServer/blob/main/library.json cg.add_library("ESP32Async/ESPAsyncWebServer", "3.9.6") diff --git a/esphome/components/web_server_base/fix_rp2040_hash.py.script b/esphome/components/web_server_base/fix_rp2040_hash.py.script new file mode 100644 index 0000000000..2cf24569de --- /dev/null +++ b/esphome/components/web_server_base/fix_rp2040_hash.py.script @@ -0,0 +1,11 @@ +# ESPAsyncWebServer includes <Hash.h> expecting the Arduino-Pico framework's Hash +# library (which provides sha1() functions). However, the Crypto-no-arduino library +# (used by dsmr) also provides a Hash.h that can shadow the framework version when +# PlatformIO's chain+ LDF mode auto-discovers it as a dependency. +# Prepend the framework Hash path to CXXFLAGS so it is found first. +import os + +Import("env") +framework_dir = env.PioPlatform().get_package_dir("framework-arduinopico") +hash_src = os.path.join(framework_dir, "libraries", "Hash", "src") +env.Prepend(CXXFLAGS=["-I" + hash_src]) From 04a6238c7b2decb53e89066ce0da49d6e56b34ff Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:49:58 -0500 Subject: [PATCH 0585/2030] [esp32] Set UV_CACHE_DIR inside data dir so Clean All clears it (#13888) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 90f6035aba..6f5011246c 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1435,6 +1435,10 @@ async def to_code(config): CORE.relative_internal_path(".espressif") ) + # Set the uv cache inside the data dir so "Clean All" clears it. + # Avoids persistent corrupted cache from mid-stream download failures. + os.environ["UV_CACHE_DIR"] = str(CORE.relative_internal_path(".uv_cache")) + if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: cg.add_build_flag("-DUSE_ESP_IDF") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF") From c658d7b57faa41def0808c11d6fbd046abd4eb6b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:02:02 -0600 Subject: [PATCH 0586/2030] [api] Merge auth check into base read_message, eliminate APIServerConnection (#13873) --- esphome/components/api/api_connection.h | 2 +- esphome/components/api/api_pb2_service.cpp | 41 +++--- esphome/components/api/api_pb2_service.h | 5 - script/api_protobuf/api_protobuf.py | 156 ++++++++++----------- 4 files changed, 91 insertions(+), 113 deletions(-) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index ae7f864568..7f738a9bfd 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -28,7 +28,7 @@ static constexpr size_t MAX_INITIAL_PER_BATCH = 34; // For clients >= AP static_assert(MAX_MESSAGES_PER_BATCH >= MAX_INITIAL_PER_BATCH, "MAX_MESSAGES_PER_BATCH must be >= MAX_INITIAL_PER_BATCH"); -class APIConnection final : public APIServerConnection { +class APIConnection final : public APIServerConnectionBase { public: friend class APIServer; friend class ListEntitiesIterator; diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 1c04eacc82..2d15deb90d 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -21,6 +21,23 @@ void APIServerConnectionBase::log_receive_message_(const LogString *name) { #endif void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { + // Check authentication/connection requirements + switch (msg_type) { + case HelloRequest::MESSAGE_TYPE: // No setup required + case DisconnectRequest::MESSAGE_TYPE: // No setup required + case PingRequest::MESSAGE_TYPE: // No setup required + break; + case DeviceInfoRequest::MESSAGE_TYPE: // Connection setup only + if (!this->check_connection_setup_()) { + return; + } + break; + default: + if (!this->check_authenticated_()) { + return; + } + break; + } switch (msg_type) { case HelloRequest::MESSAGE_TYPE: { HelloRequest msg; @@ -623,28 +640,4 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } } -void APIServerConnection::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { - // Check authentication/connection requirements for messages - switch (msg_type) { - case HelloRequest::MESSAGE_TYPE: // No setup required - case DisconnectRequest::MESSAGE_TYPE: // No setup required - case PingRequest::MESSAGE_TYPE: // No setup required - break; // Skip all checks for these messages - case DeviceInfoRequest::MESSAGE_TYPE: // Connection setup only - if (!this->check_connection_setup_()) { - return; // Connection not setup - } - break; - default: - // All other messages require authentication (which includes connection check) - if (!this->check_authenticated_()) { - return; // Authentication failed - } - break; - } - - // Call base implementation to process the message - APIServerConnectionBase::read_message(msg_size, msg_type, msg_data); -} - } // namespace esphome::api diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 4dc6ce27d0..1441507406 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -228,9 +228,4 @@ class APIServerConnectionBase : public ProtoService { void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; -class APIServerConnection : public APIServerConnectionBase { - protected: - void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; -}; - } // namespace esphome::api diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 8673996a25..ece0b5692f 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2881,9 +2881,82 @@ static const char *const TAG = "api.service"; cases = list(RECEIVE_CASES.items()) cases.sort() + + serv = file.service[0] + + # Build a mapping of message input types to their authentication requirements + message_auth_map: dict[str, bool] = {} + message_conn_map: dict[str, bool] = {} + + for m in serv.method: + inp = m.input_type[1:] + needs_conn = get_opt(m, pb.needs_setup_connection, True) + needs_auth = get_opt(m, pb.needs_authentication, True) + + # Store authentication requirements for message types + message_auth_map[inp] = needs_auth + message_conn_map[inp] = needs_conn + + # Categorize messages by their authentication requirements + no_conn_ids: set[int] = set() + conn_only_ids: set[int] = set() + + for id_, (_, _, case_msg_name) in cases: + if case_msg_name in message_auth_map: + needs_auth = message_auth_map[case_msg_name] + needs_conn = message_conn_map[case_msg_name] + + if not needs_conn: + no_conn_ids.add(id_) + elif not needs_auth: + conn_only_ids.add(id_) + + # Helper to generate case statements with ifdefs + def generate_cases(ids: set[int], comment: str) -> str: + result = "" + for id_ in sorted(ids): + _, ifdef, msg_name = RECEIVE_CASES[id_] + if ifdef: + result += f"#ifdef {ifdef}\n" + result += f" case {msg_name}::MESSAGE_TYPE: {comment}\n" + if ifdef: + result += "#endif\n" + return result + + # Generate read_message with auth check before dispatch hpp += " protected:\n" hpp += " void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;\n" + out = f"void {class_name}::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {{\n" + + # Auth check block before dispatch switch + out += " // Check authentication/connection requirements\n" + if no_conn_ids or conn_only_ids: + out += " switch (msg_type) {\n" + + if no_conn_ids: + out += generate_cases(no_conn_ids, "// No setup required") + out += " break;\n" + + if conn_only_ids: + out += generate_cases(conn_only_ids, "// Connection setup only") + out += " if (!this->check_connection_setup_()) {\n" + out += " return;\n" + out += " }\n" + out += " break;\n" + + out += " default:\n" + out += " if (!this->check_authenticated_()) {\n" + out += " return;\n" + out += " }\n" + out += " break;\n" + out += " }\n" + else: + out += " if (!this->check_authenticated_()) {\n" + out += " return;\n" + out += " }\n" + + # Dispatch switch out += " switch (msg_type) {\n" for i, (case, ifdef, message_name) in cases: if ifdef is not None: @@ -2902,89 +2975,6 @@ static const char *const TAG = "api.service"; cpp += out hpp += "};\n" - serv = file.service[0] - class_name = "APIServerConnection" - hpp += "\n" - hpp += f"class {class_name} : public {class_name}Base {{\n" - hpp_protected = "" - cpp += "\n" - - # Build a mapping of message input types to their authentication requirements - message_auth_map: dict[str, bool] = {} - message_conn_map: dict[str, bool] = {} - - for m in serv.method: - inp = m.input_type[1:] - needs_conn = get_opt(m, pb.needs_setup_connection, True) - needs_auth = get_opt(m, pb.needs_authentication, True) - - # Store authentication requirements for message types - message_auth_map[inp] = needs_auth - message_conn_map[inp] = needs_conn - - # Generate optimized read_message with authentication checking - # Categorize messages by their authentication requirements - no_conn_ids: set[int] = set() - conn_only_ids: set[int] = set() - - for id_, (_, _, case_msg_name) in cases: - if case_msg_name in message_auth_map: - needs_auth = message_auth_map[case_msg_name] - needs_conn = message_conn_map[case_msg_name] - - if not needs_conn: - no_conn_ids.add(id_) - elif not needs_auth: - conn_only_ids.add(id_) - - # Generate override if we have messages that skip checks - if no_conn_ids or conn_only_ids: - # Helper to generate case statements with ifdefs - def generate_cases(ids: set[int], comment: str) -> str: - result = "" - for id_ in sorted(ids): - _, ifdef, msg_name = RECEIVE_CASES[id_] - if ifdef: - result += f"#ifdef {ifdef}\n" - result += f" case {msg_name}::MESSAGE_TYPE: {comment}\n" - if ifdef: - result += "#endif\n" - return result - - hpp_protected += " void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;\n" - - cpp += f"\nvoid {class_name}::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {{\n" - cpp += " // Check authentication/connection requirements for messages\n" - cpp += " switch (msg_type) {\n" - - # Messages that don't need any checks - if no_conn_ids: - cpp += generate_cases(no_conn_ids, "// No setup required") - cpp += " break; // Skip all checks for these messages\n" - - # Messages that only need connection setup - if conn_only_ids: - cpp += generate_cases(conn_only_ids, "// Connection setup only") - cpp += " if (!this->check_connection_setup_()) {\n" - cpp += " return; // Connection not setup\n" - cpp += " }\n" - cpp += " break;\n" - - cpp += " default:\n" - cpp += " // All other messages require authentication (which includes connection check)\n" - cpp += " if (!this->check_authenticated_()) {\n" - cpp += " return; // Authentication failed\n" - cpp += " }\n" - cpp += " break;\n" - cpp += " }\n\n" - cpp += " // Call base implementation to process the message\n" - cpp += f" {class_name}Base::read_message(msg_size, msg_type, msg_data);\n" - cpp += "}\n" - - hpp += " protected:\n" - hpp += hpp_protected - hpp += "};\n" - hpp += """\ } // namespace esphome::api From 2383b6b8b461d14594d9cd08199d7bc3db444a8f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:05:32 -0600 Subject: [PATCH 0587/2030] [core] Deprecate set_retry, cancel_retry, and RetryResult (#13845) --- esphome/core/component.cpp | 19 +++++++++- esphome/core/component.h | 71 ++++++++++++-------------------------- esphome/core/scheduler.cpp | 7 ++++ esphome/core/scheduler.h | 23 +++++++++--- 4 files changed, 66 insertions(+), 54 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index f09a39d2bb..6d8d1c57af 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -152,7 +152,10 @@ void Component::set_retry(const std::string &name, uint32_t initial_wait_time, u void Component::set_retry(const char *name, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); +#pragma GCC diagnostic pop } bool Component::cancel_retry(const std::string &name) { // NOLINT @@ -163,7 +166,10 @@ bool Component::cancel_retry(const std::string &name) { // NOLINT } bool Component::cancel_retry(const char *name) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" return App.scheduler.cancel_retry(this, name); +#pragma GCC diagnostic pop } void Component::set_timeout(const std::string &name, uint32_t timeout, std::function<void()> &&f) { // NOLINT @@ -203,10 +209,18 @@ bool Component::cancel_interval(uint32_t id) { return App.scheduler.cancel_inter void Component::set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_retry(this, id, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); +#pragma GCC diagnostic pop } -bool Component::cancel_retry(uint32_t id) { return App.scheduler.cancel_retry(this, id); } +bool Component::cancel_retry(uint32_t id) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return App.scheduler.cancel_retry(this, id); +#pragma GCC diagnostic pop +} void Component::call_loop() { this->loop(); } void Component::call_setup() { this->setup(); } @@ -371,7 +385,10 @@ void Component::set_interval(uint32_t interval, std::function<void()> &&f) { // } void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); +#pragma GCC diagnostic pop } bool Component::is_failed() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; } bool Component::is_ready() const { diff --git a/esphome/core/component.h b/esphome/core/component.h index 97f2afe1a4..c3582e23b1 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -68,6 +68,7 @@ extern const uint8_t STATUS_LED_OK; extern const uint8_t STATUS_LED_WARNING; extern const uint8_t STATUS_LED_ERROR; +// Remove before 2026.8.0 enum class RetryResult { DONE, RETRY }; extern const uint16_t WARN_IF_BLOCKING_OVER_MS; @@ -347,68 +348,40 @@ class Component { bool cancel_interval(const char *name); // NOLINT bool cancel_interval(uint32_t id); // NOLINT - /** Set an retry function with a unique name. Empty name means no cancelling possible. - * - * This will call the retry function f on the next scheduler loop. f should return RetryResult::DONE if - * it is successful and no repeat is required. Otherwise, returning RetryResult::RETRY will call f - * again in the future. - * - * The first retry of f happens after `initial_wait_time` milliseconds. The delay between retries is - * increased by multiplying by `backoff_increase_factor` each time. If no backoff_increase_factor is - * supplied (default = 1.0), the wait time will stay constant. - * - * The retry function f needs to accept a single argument: the number of attempts remaining. On the - * final retry of f, this value will be 0. - * - * This retry function can also be cancelled by name via cancel_retry(). - * - * IMPORTANT: Do not rely on this having correct timing. This is only called from - * loop() and therefore can be significantly delayed. - * - * REMARK: It is an error to supply a negative or zero `backoff_increase_factor`, and 1.0 will be used instead. - * - * REMARK: The interval between retries is stored into a `uint32_t`, so this doesn't behave correctly - * if `initial_wait_time * (backoff_increase_factor ** (max_attempts - 2))` overflows. - * - * @param name The identifier for this retry function. - * @param initial_wait_time The time in ms before f is called again - * @param max_attempts The maximum number of executions - * @param f The function (or lambda) that should be called - * @param backoff_increase_factor time between retries is multiplied by this factor on every retry after the first - * @see cancel_retry() - */ - // Remove before 2026.7.0 - ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") + /// @deprecated set_retry is deprecated. Use set_timeout or set_interval instead. Removed in 2026.8.0. + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor = 1.0f); // NOLINT + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(const char *name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor = 1.0f); // NOLINT - /** Set a retry function with a numeric ID (zero heap allocation). - * - * @param id The numeric identifier for this retry function - * @param initial_wait_time The wait time after the first execution - * @param max_attempts The max number of attempts - * @param f The function to call - * @param backoff_increase_factor The factor to increase the retry interval by - */ + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor = 1.0f); // NOLINT + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f, // NOLINT float backoff_increase_factor = 1.0f); // NOLINT - /** Cancel a retry function. - * - * @param name The identifier for this retry function. - * @return Whether a retry function was deleted. - */ - // Remove before 2026.7.0 - ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") bool cancel_retry(const std::string &name); // NOLINT - bool cancel_retry(const char *name); // NOLINT - bool cancel_retry(uint32_t id); // NOLINT + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") + bool cancel_retry(const char *name); // NOLINT + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") + bool cancel_retry(uint32_t id); // NOLINT /** Set a timeout function with a unique name. * diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 6797640f54..a5e308829a 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -252,6 +252,11 @@ bool HOT Scheduler::cancel_interval(Component *component, uint32_t id) { return this->cancel_item_(component, NameType::NUMERIC_ID, nullptr, id, SchedulerItem::INTERVAL); } +// Suppress deprecation warnings for RetryResult usage in the still-present (but deprecated) retry implementation. +// Remove before 2026.8.0 along with all retry code. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + struct RetryArgs { // Ordered to minimize padding on 32-bit systems std::function<RetryResult(uint8_t)> func; @@ -364,6 +369,8 @@ bool HOT Scheduler::cancel_retry(Component *component, uint32_t id) { return this->cancel_retry_(component, NameType::NUMERIC_ID, nullptr, id); } +#pragma GCC diagnostic pop // End suppression of deprecated RetryResult warnings + optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) { // IMPORTANT: This method should only be called from the main thread (loop task). // It performs cleanup and accesses items_[0] without holding a lock, which is only diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 7de1023e6d..20b069f3f0 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -72,18 +72,30 @@ class Scheduler { bool cancel_interval(Component *component, const char *name); bool cancel_interval(Component *component, uint32_t id); - ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f); + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(Component *component, const char *name, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f); - /// Set a retry with a numeric ID (zero heap allocation) + // Remove before 2026.8.0 + ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", + "2026.2.0") void set_retry(Component *component, uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor = 1.0f); - ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") bool cancel_retry(Component *component, const std::string &name); + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") bool cancel_retry(Component *component, const char *name); + // Remove before 2026.8.0 + ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") bool cancel_retry(Component *component, uint32_t id); // Calculate when the next scheduled item should run @@ -231,11 +243,14 @@ class Scheduler { uint32_t hash_or_id, uint32_t delay, std::function<void()> func, bool is_retry = false, bool skip_cancel = false); - // Common implementation for retry + // Common implementation for retry - Remove before 2026.8.0 // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" void set_retry_common_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> func, float backoff_increase_factor); +#pragma GCC diagnostic pop // Common implementation for cancel_retry bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); From 3b0df145b72f8df89b690ab8b3aaa7175d4d8089 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:05:59 -0600 Subject: [PATCH 0588/2030] [cse7766] Batch UART reads to reduce loop overhead (#13817) --- esphome/components/cse7766/cse7766.cpp | 48 +++++++++++++++++--------- esphome/components/cse7766/cse7766.h | 4 ++- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index df4872deac..45abd3ca3d 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -7,7 +7,6 @@ namespace esphome { namespace cse7766 { static const char *const TAG = "cse7766"; -static constexpr size_t CSE7766_RAW_DATA_SIZE = 24; void CSE7766Component::loop() { const uint32_t now = App.get_loop_component_start_time(); @@ -16,25 +15,39 @@ void CSE7766Component::loop() { this->raw_data_index_ = 0; } - if (this->available() == 0) { + // Early return prevents updating last_transmission_ when no data is available. + int avail = this->available(); + if (avail <= 0) { return; } this->last_transmission_ = now; - while (this->available() != 0) { - this->read_byte(&this->raw_data_[this->raw_data_index_]); - if (!this->check_byte_()) { - this->raw_data_index_ = 0; - this->status_set_warning(); - continue; - } - if (this->raw_data_index_ == 23) { - this->parse_data_(); - this->status_clear_warning(); + // Read all available bytes in batches to reduce UART call overhead. + // At 4800 baud (~480 bytes/sec) with ~122 Hz loop rate, typically ~4 bytes per call. + uint8_t buf[CSE7766_RAW_DATA_SIZE]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; } + avail -= to_read; - this->raw_data_index_ = (this->raw_data_index_ + 1) % 24; + for (size_t i = 0; i < to_read; i++) { + this->raw_data_[this->raw_data_index_] = buf[i]; + if (!this->check_byte_()) { + this->raw_data_index_ = 0; + this->status_set_warning(); + continue; + } + + if (this->raw_data_index_ == CSE7766_RAW_DATA_SIZE - 1) { + this->parse_data_(); + this->status_clear_warning(); + } + + this->raw_data_index_ = (this->raw_data_index_ + 1) % CSE7766_RAW_DATA_SIZE; + } } } @@ -53,14 +66,15 @@ bool CSE7766Component::check_byte_() { return true; } - if (index == 23) { + if (index == CSE7766_RAW_DATA_SIZE - 1) { uint8_t checksum = 0; - for (uint8_t i = 2; i < 23; i++) { + for (uint8_t i = 2; i < CSE7766_RAW_DATA_SIZE - 1; i++) { checksum += this->raw_data_[i]; } - if (checksum != this->raw_data_[23]) { - ESP_LOGW(TAG, "Invalid checksum from CSE7766: 0x%02X != 0x%02X", checksum, this->raw_data_[23]); + if (checksum != this->raw_data_[CSE7766_RAW_DATA_SIZE - 1]) { + ESP_LOGW(TAG, "Invalid checksum from CSE7766: 0x%02X != 0x%02X", checksum, + this->raw_data_[CSE7766_RAW_DATA_SIZE - 1]); return false; } return true; diff --git a/esphome/components/cse7766/cse7766.h b/esphome/components/cse7766/cse7766.h index efddccd3c5..66a4e04633 100644 --- a/esphome/components/cse7766/cse7766.h +++ b/esphome/components/cse7766/cse7766.h @@ -8,6 +8,8 @@ namespace esphome { namespace cse7766 { +static constexpr size_t CSE7766_RAW_DATA_SIZE = 24; + class CSE7766Component : public Component, public uart::UARTDevice { public: void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } @@ -33,7 +35,7 @@ class CSE7766Component : public Component, public uart::UARTDevice { this->raw_data_[start_index + 2]); } - uint8_t raw_data_[24]; + uint8_t raw_data_[CSE7766_RAW_DATA_SIZE]; uint8_t raw_data_index_{0}; uint32_t last_transmission_{0}; sensor::Sensor *voltage_sensor_{nullptr}; From c7883cb5ae6f69ca7de1f4281c5661b41f98fb95 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:06:38 -0600 Subject: [PATCH 0589/2030] [ld2450] Batch UART reads to reduce loop overhead (#13818) --- esphome/components/ld2450/ld2450.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index ca8d918441..38ba0d7f96 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -276,8 +276,19 @@ void LD2450Component::dump_config() { } void LD2450Component::loop() { - while (this->available()) { - this->readline_(this->read()); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[MAX_LINE_LENGTH]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->readline_(buf[i]); + } } } From 50fe8e51f9dfb610e74049fcc0db440e22301d54 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:07:28 -0600 Subject: [PATCH 0590/2030] [ld2412] Batch UART reads to reduce loop overhead (#13819) --- esphome/components/ld2412/ld2412.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index c2f441e472..f8ceee78eb 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -310,8 +310,19 @@ void LD2412Component::restart_and_read_all_info() { } void LD2412Component::loop() { - while (this->available()) { - this->readline_(this->read()); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[MAX_LINE_LENGTH]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->readline_(buf[i]); + } } } From c43d3889b041ee1322232b1ea089c5cb5544d738 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:07:42 -0600 Subject: [PATCH 0591/2030] [modbus] Use stack buffer instead of heap vector in send() (#13853) --- esphome/components/modbus/modbus.cpp | 39 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 5e9387b843..357cd48e11 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -219,39 +219,50 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address return; } - std::vector<uint8_t> data; - data.push_back(address); - data.push_back(function_code); + static constexpr size_t ADDR_SIZE = 1; + static constexpr size_t FC_SIZE = 1; + static constexpr size_t START_ADDR_SIZE = 2; + static constexpr size_t NUM_ENTITIES_SIZE = 2; + static constexpr size_t BYTE_COUNT_SIZE = 1; + static constexpr size_t MAX_PAYLOAD_SIZE = std::numeric_limits<uint8_t>::max(); + static constexpr size_t CRC_SIZE = 2; + static constexpr size_t MAX_FRAME_SIZE = + ADDR_SIZE + FC_SIZE + START_ADDR_SIZE + NUM_ENTITIES_SIZE + BYTE_COUNT_SIZE + MAX_PAYLOAD_SIZE + CRC_SIZE; + uint8_t data[MAX_FRAME_SIZE]; + size_t pos = 0; + + data[pos++] = address; + data[pos++] = function_code; if (this->role == ModbusRole::CLIENT) { - data.push_back(start_address >> 8); - data.push_back(start_address >> 0); + data[pos++] = start_address >> 8; + data[pos++] = start_address >> 0; if (function_code != ModbusFunctionCode::WRITE_SINGLE_COIL && function_code != ModbusFunctionCode::WRITE_SINGLE_REGISTER) { - data.push_back(number_of_entities >> 8); - data.push_back(number_of_entities >> 0); + data[pos++] = number_of_entities >> 8; + data[pos++] = number_of_entities >> 0; } } if (payload != nullptr) { if (this->role == ModbusRole::SERVER || function_code == ModbusFunctionCode::WRITE_MULTIPLE_COILS || function_code == ModbusFunctionCode::WRITE_MULTIPLE_REGISTERS) { // Write multiple - data.push_back(payload_len); // Byte count is required for write + data[pos++] = payload_len; // Byte count is required for write } else { payload_len = 2; // Write single register or coil } for (int i = 0; i < payload_len; i++) { - data.push_back(payload[i]); + data[pos++] = payload[i]; } } - auto crc = crc16(data.data(), data.size()); - data.push_back(crc >> 0); - data.push_back(crc >> 8); + auto crc = crc16(data, pos); + data[pos++] = crc >> 0; + data[pos++] = crc >> 8; if (this->flow_control_pin_ != nullptr) this->flow_control_pin_->digital_write(true); - this->write_array(data); + this->write_array(data, pos); this->flush(); if (this->flow_control_pin_ != nullptr) @@ -261,7 +272,7 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; #endif - ESP_LOGV(TAG, "Modbus write: %s", format_hex_pretty_to(hex_buf, data.data(), data.size())); + ESP_LOGV(TAG, "Modbus write: %s", format_hex_pretty_to(hex_buf, data, pos)); } // Helper function for lambdas From d33f23dc43dad9c7891f2789e811dec248d83e5a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:07:55 -0600 Subject: [PATCH 0592/2030] [ld2410] Batch UART reads to reduce loop overhead (#13820) --- esphome/components/ld2410/ld2410.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index 5294f7cd36..b57b1d9978 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -275,8 +275,19 @@ void LD2410Component::restart_and_read_all_info() { } void LD2410Component::loop() { - while (this->available()) { - this->readline_(this->read()); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[MAX_LINE_LENGTH]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->readline_(buf[i]); + } } } From 8b24112be5aadb2952d7dff58cbfd05341349e29 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:14:48 -0600 Subject: [PATCH 0593/2030] [pipsolar] Batch UART reads to reduce per-loop overhead (#13829) --- esphome/components/pipsolar/pipsolar.cpp | 64 +++++++++++++++--------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index bafd5273da..d7b37f6130 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -13,9 +13,12 @@ void Pipsolar::setup() { } void Pipsolar::empty_uart_buffer_() { - uint8_t byte; - while (this->available()) { - this->read_byte(&byte); + uint8_t buf[64]; + int avail; + while ((avail = this->available()) > 0) { + if (!this->read_array(buf, std::min(static_cast<size_t>(avail), sizeof(buf)))) { + break; + } } } @@ -94,32 +97,47 @@ void Pipsolar::loop() { } if (this->state_ == STATE_COMMAND || this->state_ == STATE_POLL) { - while (this->available()) { - uint8_t byte; - this->read_byte(&byte); - - // make sure data and null terminator fit in buffer - if (this->read_pos_ >= PIPSOLAR_READ_BUFFER_LENGTH - 1) { - this->read_pos_ = 0; - this->empty_uart_buffer_(); - ESP_LOGW(TAG, "response data too long, discarding."); + int avail = this->available(); + while (avail > 0) { + uint8_t buf[64]; + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { break; } - this->read_buffer_[this->read_pos_] = byte; - this->read_pos_++; + avail -= to_read; + bool done = false; + for (size_t i = 0; i < to_read; i++) { + uint8_t byte = buf[i]; - // end of answer - if (byte == 0x0D) { - this->read_buffer_[this->read_pos_] = 0; - this->empty_uart_buffer_(); - if (this->state_ == STATE_POLL) { - this->state_ = STATE_POLL_COMPLETE; + // make sure data and null terminator fit in buffer + if (this->read_pos_ >= PIPSOLAR_READ_BUFFER_LENGTH - 1) { + this->read_pos_ = 0; + this->empty_uart_buffer_(); + ESP_LOGW(TAG, "response data too long, discarding."); + done = true; + break; } - if (this->state_ == STATE_COMMAND) { - this->state_ = STATE_COMMAND_COMPLETE; + this->read_buffer_[this->read_pos_] = byte; + this->read_pos_++; + + // end of answer + if (byte == 0x0D) { + this->read_buffer_[this->read_pos_] = 0; + this->empty_uart_buffer_(); + if (this->state_ == STATE_POLL) { + this->state_ = STATE_POLL_COMPLETE; + } + if (this->state_ == STATE_COMMAND) { + this->state_ = STATE_COMMAND_COMPLETE; + } + done = true; + break; } } - } // available + if (done) { + break; + } + } } if (this->state_ == STATE_COMMAND) { if (millis() - this->command_start_millis_ > esphome::pipsolar::Pipsolar::COMMAND_TIMEOUT) { From 623f33c9f9ea480d35d258b34c2fca427ce54ae4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:15:04 -0600 Subject: [PATCH 0594/2030] [rd03d] Batch UART reads to reduce per-loop overhead (#13830) --- esphome/components/rd03d/rd03d.cpp | 67 +++++++++++++++++------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index 090e4dcf32..e4dbdf41cb 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -1,4 +1,5 @@ #include "rd03d.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include <cmath> @@ -80,37 +81,47 @@ void RD03DComponent::dump_config() { } void RD03DComponent::loop() { - while (this->available()) { - uint8_t byte = this->read(); - ESP_LOGVV(TAG, "Received byte: 0x%02X, buffer_pos: %d", byte, this->buffer_pos_); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + for (size_t i = 0; i < to_read; i++) { + uint8_t byte = buf[i]; + ESP_LOGVV(TAG, "Received byte: 0x%02X, buffer_pos: %d", byte, this->buffer_pos_); - // Check if we're looking for frame header - if (this->buffer_pos_ < FRAME_HEADER_SIZE) { - if (byte == FRAME_HEADER[this->buffer_pos_]) { - this->buffer_[this->buffer_pos_++] = byte; - } else if (byte == FRAME_HEADER[0]) { - // Start over if we see a potential new header - this->buffer_[0] = byte; - this->buffer_pos_ = 1; - } else { + // Check if we're looking for frame header + if (this->buffer_pos_ < FRAME_HEADER_SIZE) { + if (byte == FRAME_HEADER[this->buffer_pos_]) { + this->buffer_[this->buffer_pos_++] = byte; + } else if (byte == FRAME_HEADER[0]) { + // Start over if we see a potential new header + this->buffer_[0] = byte; + this->buffer_pos_ = 1; + } else { + this->buffer_pos_ = 0; + } + continue; + } + + // Accumulate data bytes + this->buffer_[this->buffer_pos_++] = byte; + + // Check if we have a complete frame + if (this->buffer_pos_ == FRAME_SIZE) { + // Validate footer + if (this->buffer_[FRAME_SIZE - 2] == FRAME_FOOTER[0] && this->buffer_[FRAME_SIZE - 1] == FRAME_FOOTER[1]) { + this->process_frame_(); + } else { + ESP_LOGW(TAG, "Invalid frame footer: 0x%02X 0x%02X (expected 0x55 0xCC)", this->buffer_[FRAME_SIZE - 2], + this->buffer_[FRAME_SIZE - 1]); + } this->buffer_pos_ = 0; } - continue; - } - - // Accumulate data bytes - this->buffer_[this->buffer_pos_++] = byte; - - // Check if we have a complete frame - if (this->buffer_pos_ == FRAME_SIZE) { - // Validate footer - if (this->buffer_[FRAME_SIZE - 2] == FRAME_FOOTER[0] && this->buffer_[FRAME_SIZE - 1] == FRAME_FOOTER[1]) { - this->process_frame_(); - } else { - ESP_LOGW(TAG, "Invalid frame footer: 0x%02X 0x%02X (expected 0x55 0xCC)", this->buffer_[FRAME_SIZE - 2], - this->buffer_[FRAME_SIZE - 1]); - } - this->buffer_pos_ = 0; } } } From e7a900fbaa082c906dcb54f438a876da11763456 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:15:15 -0600 Subject: [PATCH 0595/2030] [rf_bridge] Batch UART reads to reduce per-loop overhead (#13831) --- esphome/components/rf_bridge/rf_bridge.cpp | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/esphome/components/rf_bridge/rf_bridge.cpp b/esphome/components/rf_bridge/rf_bridge.cpp index 8105767485..e33c13aafe 100644 --- a/esphome/components/rf_bridge/rf_bridge.cpp +++ b/esphome/components/rf_bridge/rf_bridge.cpp @@ -136,14 +136,21 @@ void RFBridgeComponent::loop() { this->last_bridge_byte_ = now; } - while (this->available()) { - uint8_t byte; - this->read_byte(&byte); - if (this->parse_bridge_byte_(byte)) { - ESP_LOGVV(TAG, "Parsed: 0x%02X", byte); - this->last_bridge_byte_ = now; - } else { - this->rx_buffer_.clear(); + int avail = this->available(); + while (avail > 0) { + uint8_t buf[64]; + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + for (size_t i = 0; i < to_read; i++) { + if (this->parse_bridge_byte_(buf[i])) { + ESP_LOGVV(TAG, "Parsed: 0x%02X", buf[i]); + this->last_bridge_byte_ = now; + } else { + this->rx_buffer_.clear(); + } } } } From e176cf50abb2acfb911d72c8f1c9445530542a5b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:15:28 -0600 Subject: [PATCH 0596/2030] [dfplayer] Batch UART reads to reduce per-loop overhead (#13832) --- esphome/components/dfplayer/dfplayer.cpp | 264 ++++++++++++----------- 1 file changed, 137 insertions(+), 127 deletions(-) diff --git a/esphome/components/dfplayer/dfplayer.cpp b/esphome/components/dfplayer/dfplayer.cpp index 70bd42e1a5..48c06be558 100644 --- a/esphome/components/dfplayer/dfplayer.cpp +++ b/esphome/components/dfplayer/dfplayer.cpp @@ -1,4 +1,5 @@ #include "dfplayer.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" namespace esphome { @@ -131,140 +132,149 @@ void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) { } void DFPlayer::loop() { - // Read message - while (this->available()) { - uint8_t byte; - this->read_byte(&byte); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + for (size_t bi = 0; bi < to_read; bi++) { + uint8_t byte = buf[bi]; - if (this->read_pos_ == DFPLAYER_READ_BUFFER_LENGTH) - this->read_pos_ = 0; + if (this->read_pos_ == DFPLAYER_READ_BUFFER_LENGTH) + this->read_pos_ = 0; - switch (this->read_pos_) { - case 0: // Start mark - if (byte != 0x7E) - continue; - break; - case 1: // Version - if (byte != 0xFF) { - ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte); - this->read_pos_ = 0; - continue; - } - break; - case 2: // Buffer length - if (byte != 0x06) { - ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte); - this->read_pos_ = 0; - continue; - } - break; - case 9: // End byte + switch (this->read_pos_) { + case 0: // Start mark + if (byte != 0x7E) + continue; + break; + case 1: // Version + if (byte != 0xFF) { + ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte); + this->read_pos_ = 0; + continue; + } + break; + case 2: // Buffer length + if (byte != 0x06) { + ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte); + this->read_pos_ = 0; + continue; + } + break; + case 9: // End byte #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE - char byte_sequence[100]; - byte_sequence[0] = '\0'; - for (size_t i = 0; i < this->read_pos_ + 1; ++i) { - snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ", - this->read_buffer_[i]); - } - ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence); + char byte_sequence[100]; + byte_sequence[0] = '\0'; + for (size_t i = 0; i < this->read_pos_ + 1; ++i) { + snprintf(byte_sequence + strlen(byte_sequence), sizeof(byte_sequence) - strlen(byte_sequence), "%02X ", + this->read_buffer_[i]); + } + ESP_LOGVV(TAG, "Received byte sequence: %s", byte_sequence); #endif - if (byte != 0xEF) { - ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte); + if (byte != 0xEF) { + ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte); + this->read_pos_ = 0; + continue; + } + // Parse valid received command + uint8_t cmd = this->read_buffer_[3]; + uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6]; + + ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument); + + switch (cmd) { + case 0x3A: + if (argument == 1) { + ESP_LOGI(TAG, "USB loaded"); + } else if (argument == 2) { + ESP_LOGI(TAG, "TF Card loaded"); + } + break; + case 0x3B: + if (argument == 1) { + ESP_LOGI(TAG, "USB unloaded"); + } else if (argument == 2) { + ESP_LOGI(TAG, "TF Card unloaded"); + } + break; + case 0x3F: + if (argument == 1) { + ESP_LOGI(TAG, "USB available"); + } else if (argument == 2) { + ESP_LOGI(TAG, "TF Card available"); + } else if (argument == 3) { + ESP_LOGI(TAG, "USB, TF Card available"); + } + break; + case 0x40: + ESP_LOGV(TAG, "Nack"); + this->ack_set_is_playing_ = false; + this->ack_reset_is_playing_ = false; + switch (argument) { + case 0x01: + ESP_LOGE(TAG, "Module is busy or uninitialized"); + break; + case 0x02: + ESP_LOGE(TAG, "Module is in sleep mode"); + break; + case 0x03: + ESP_LOGE(TAG, "Serial receive error"); + break; + case 0x04: + ESP_LOGE(TAG, "Checksum incorrect"); + break; + case 0x05: + ESP_LOGE(TAG, "Specified track is out of current track scope"); + this->is_playing_ = false; + break; + case 0x06: + ESP_LOGE(TAG, "Specified track is not found"); + this->is_playing_ = false; + break; + case 0x07: + ESP_LOGE(TAG, + "Insertion error (an inserting operation only can be done when a track is being played)"); + break; + case 0x08: + ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)"); + break; + case 0x09: + ESP_LOGE(TAG, "Entered into sleep mode"); + this->is_playing_ = false; + break; + } + break; + case 0x41: + ESP_LOGV(TAG, "Ack ok"); + this->is_playing_ |= this->ack_set_is_playing_; + this->is_playing_ &= !this->ack_reset_is_playing_; + this->ack_set_is_playing_ = false; + this->ack_reset_is_playing_ = false; + break; + case 0x3C: + ESP_LOGV(TAG, "Playback finished (USB drive)"); + this->is_playing_ = false; + this->on_finished_playback_callback_.call(); + case 0x3D: + ESP_LOGV(TAG, "Playback finished (SD card)"); + this->is_playing_ = false; + this->on_finished_playback_callback_.call(); + break; + default: + ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument); + } + this->sent_cmd_ = 0; this->read_pos_ = 0; continue; - } - // Parse valid received command - uint8_t cmd = this->read_buffer_[3]; - uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6]; - - ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument); - - switch (cmd) { - case 0x3A: - if (argument == 1) { - ESP_LOGI(TAG, "USB loaded"); - } else if (argument == 2) { - ESP_LOGI(TAG, "TF Card loaded"); - } - break; - case 0x3B: - if (argument == 1) { - ESP_LOGI(TAG, "USB unloaded"); - } else if (argument == 2) { - ESP_LOGI(TAG, "TF Card unloaded"); - } - break; - case 0x3F: - if (argument == 1) { - ESP_LOGI(TAG, "USB available"); - } else if (argument == 2) { - ESP_LOGI(TAG, "TF Card available"); - } else if (argument == 3) { - ESP_LOGI(TAG, "USB, TF Card available"); - } - break; - case 0x40: - ESP_LOGV(TAG, "Nack"); - this->ack_set_is_playing_ = false; - this->ack_reset_is_playing_ = false; - switch (argument) { - case 0x01: - ESP_LOGE(TAG, "Module is busy or uninitialized"); - break; - case 0x02: - ESP_LOGE(TAG, "Module is in sleep mode"); - break; - case 0x03: - ESP_LOGE(TAG, "Serial receive error"); - break; - case 0x04: - ESP_LOGE(TAG, "Checksum incorrect"); - break; - case 0x05: - ESP_LOGE(TAG, "Specified track is out of current track scope"); - this->is_playing_ = false; - break; - case 0x06: - ESP_LOGE(TAG, "Specified track is not found"); - this->is_playing_ = false; - break; - case 0x07: - ESP_LOGE(TAG, "Insertion error (an inserting operation only can be done when a track is being played)"); - break; - case 0x08: - ESP_LOGE(TAG, "SD card reading failed (SD card pulled out or damaged)"); - break; - case 0x09: - ESP_LOGE(TAG, "Entered into sleep mode"); - this->is_playing_ = false; - break; - } - break; - case 0x41: - ESP_LOGV(TAG, "Ack ok"); - this->is_playing_ |= this->ack_set_is_playing_; - this->is_playing_ &= !this->ack_reset_is_playing_; - this->ack_set_is_playing_ = false; - this->ack_reset_is_playing_ = false; - break; - case 0x3C: - ESP_LOGV(TAG, "Playback finished (USB drive)"); - this->is_playing_ = false; - this->on_finished_playback_callback_.call(); - case 0x3D: - ESP_LOGV(TAG, "Playback finished (SD card)"); - this->is_playing_ = false; - this->on_finished_playback_callback_.call(); - break; - default: - ESP_LOGE(TAG, "Received unknown cmd %#02x arg %#04x", cmd, argument); - } - this->sent_cmd_ = 0; - this->read_pos_ = 0; - continue; + } + this->read_buffer_[this->read_pos_] = byte; + this->read_pos_++; } - this->read_buffer_[this->read_pos_] = byte; - this->read_pos_++; } } void DFPlayer::dump_config() { From a5ee4510433c247e8eebe982ff82d587a2e303f1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:17:58 -0600 Subject: [PATCH 0597/2030] [tuya] Batch UART reads to reduce per-loop overhead (#13827) --- esphome/components/tuya/tuya.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 2812fb6ad6..9ee4c09b86 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -31,10 +31,19 @@ void Tuya::setup() { } void Tuya::loop() { - while (this->available()) { - uint8_t c; - this->read_byte(&c); - this->handle_char_(c); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->handle_char_(buf[i]); + } } process_command_queue_(); } From 8fffe7453dd4cca340808964e8cd7ea24c8002df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:18:12 -0600 Subject: [PATCH 0598/2030] [seeed_mr24hpc1/mr60fda2/mr60bha2] Batch UART reads to reduce per-loop overhead (#13825) --- .../seeed_mr24hpc1/seeed_mr24hpc1.cpp | 17 ++++++++++----- .../seeed_mr60bha2/seeed_mr60bha2.cpp | 21 ++++++++++++------- .../seeed_mr60fda2/seeed_mr60fda2.cpp | 17 ++++++++++----- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 08d83f9390..3f2103b401 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -106,12 +106,19 @@ void MR24HPC1Component::update_() { // main loop void MR24HPC1Component::loop() { - uint8_t byte; + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; - // Is there data on the serial port - while (this->available()) { - this->read_byte(&byte); - this->r24_split_data_frame_(byte); // split data frame + for (size_t i = 0; i < to_read; i++) { + this->r24_split_data_frame_(buf[i]); // split data frame + } } if ((this->s_output_info_switch_flag_ == OUTPUT_SWTICH_OFF) && diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp index b9ce1f9151..d95e13241d 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp @@ -30,14 +30,21 @@ void MR60BHA2Component::dump_config() { // main loop void MR60BHA2Component::loop() { - uint8_t byte; + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; - // Is there data on the serial port - while (this->available()) { - this->read_byte(&byte); - this->rx_message_.push_back(byte); - if (!this->validate_message_()) { - this->rx_message_.clear(); + for (size_t i = 0; i < to_read; i++) { + this->rx_message_.push_back(buf[i]); + if (!this->validate_message_()) { + this->rx_message_.clear(); + } } } } diff --git a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp index b5b5b4d05a..441ee2b5c2 100644 --- a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +++ b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp @@ -49,12 +49,19 @@ void MR60FDA2Component::setup() { // main loop void MR60FDA2Component::loop() { - uint8_t byte; + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; - // Is there data on the serial port - while (this->available()) { - this->read_byte(&byte); - this->split_frame_(byte); // split data frame + for (size_t i = 0; i < to_read; i++) { + this->split_frame_(buf[i]); // split data frame + } } } From 4a9ff48f0246a4bd6131f19a76fce42db9af8781 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:20:50 -0600 Subject: [PATCH 0599/2030] [nextion] Batch UART reads to reduce loop overhead (#13823) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index fd6ce0a24b..56bbc840fb 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -397,11 +397,17 @@ bool Nextion::remove_from_q_(bool report_empty) { } void Nextion::process_serial_() { - uint8_t d; + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; - while (this->available()) { - read_byte(&d); - this->command_data_ += d; + this->command_data_.append(reinterpret_cast<const char *>(buf), to_read); } } // nextion.tech/instruction-set/ From cd55eb927ddba835775dd71f2da7e2cdb7b59ea7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:21:15 -0600 Subject: [PATCH 0600/2030] [modbus] Batch UART reads to reduce loop overhead (#13822) --- esphome/components/modbus/modbus.cpp | 29 ++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 357cd48e11..c1f5635028 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -19,16 +19,25 @@ void Modbus::setup() { void Modbus::loop() { const uint32_t now = App.get_loop_component_start_time(); - while (this->available()) { - uint8_t byte; - this->read_byte(&byte); - if (this->parse_modbus_byte_(byte)) { - this->last_modbus_byte_ = now; - } else { - size_t at = this->rx_buffer_.size(); - if (at > 0) { - ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse failed", at); - this->rx_buffer_.clear(); + // Read all available bytes in batches to reduce UART call overhead. + int avail = this->available(); + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + if (this->parse_modbus_byte_(buf[i])) { + this->last_modbus_byte_ = now; + } else { + size_t at = this->rx_buffer_.size(); + if (at > 0) { + ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse failed", at); + this->rx_buffer_.clear(); + } } } } From 41a9588d811088ad72e9e6655c29256aa597b0c2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:26:06 -0600 Subject: [PATCH 0601/2030] [i2c] Replace switch with if-else to avoid CSWTCH table in RAM (#13815) --- esphome/components/i2c/i2c_bus_arduino.cpp | 34 ++++++++++------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index e728830147..edd6b81588 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -134,25 +134,23 @@ ErrorCode ArduinoI2CBus::write_readv(uint8_t address, const uint8_t *write_buffe for (size_t j = 0; j != read_count; j++) read_buffer[j] = wire_->read(); } - switch (status) { - case 0: - return ERROR_OK; - case 1: - // transmit buffer not large enough - ESP_LOGVV(TAG, "TX failed: buffer not large enough"); - return ERROR_UNKNOWN; - case 2: - case 3: - ESP_LOGVV(TAG, "TX failed: not acknowledged: %d", status); - return ERROR_NOT_ACKNOWLEDGED; - case 5: - ESP_LOGVV(TAG, "TX failed: timeout"); - return ERROR_UNKNOWN; - case 4: - default: - ESP_LOGVV(TAG, "TX failed: unknown error %u", status); - return ERROR_UNKNOWN; + // Avoid switch to prevent compiler-generated lookup table in RAM on ESP8266 + if (status == 0) + return ERROR_OK; + if (status == 1) { + ESP_LOGVV(TAG, "TX failed: buffer not large enough"); + return ERROR_UNKNOWN; } + if (status == 2 || status == 3) { + ESP_LOGVV(TAG, "TX failed: not acknowledged: %u", status); + return ERROR_NOT_ACKNOWLEDGED; + } + if (status == 5) { + ESP_LOGVV(TAG, "TX failed: timeout"); + return ERROR_UNKNOWN; + } + ESP_LOGVV(TAG, "TX failed: unknown error %u", status); + return ERROR_UNKNOWN; } /// Perform I2C bus recovery, see: From e4ea016d1e6a7cb7a93f12c6cd2c1e419858c899 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:26:19 -0600 Subject: [PATCH 0602/2030] [ci] Block new std::to_string() usage, suggest snprintf alternatives (#13369) --- .../components/api/homeassistant_service.h | 4 +- esphome/components/esp32_ble/ble_uuid.h | 2 +- .../voice_assistant/voice_assistant.h | 2 +- script/ci-custom.py | 47 +++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 8ee23c75fe..2322d96eef 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -25,7 +25,9 @@ template<typename... X> class TemplatableStringValue : public TemplatableValue<s private: // Helper to convert value to string - handles the case where value is already a string - template<typename T> static std::string value_to_string(T &&val) { return to_string(std::forward<T>(val)); } + template<typename T> static std::string value_to_string(T &&val) { + return to_string(std::forward<T>(val)); // NOLINT + } // Overloads for string types - needed because std::to_string doesn't support them static std::string value_to_string(char *val) { diff --git a/esphome/components/esp32_ble/ble_uuid.h b/esphome/components/esp32_ble/ble_uuid.h index 6c8ef7bfd9..503fde6945 100644 --- a/esphome/components/esp32_ble/ble_uuid.h +++ b/esphome/components/esp32_ble/ble_uuid.h @@ -48,7 +48,7 @@ class ESPBTUUID { // Remove before 2026.8.0 ESPDEPRECATED("Use to_str() instead. Removed in 2026.8.0", "2026.2.0") - std::string to_string() const; + std::string to_string() const; // NOLINT const char *to_str(std::span<char, UUID_STR_LEN> output) const; protected: diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 2a5f3a55a7..0ef7ecc81a 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -83,7 +83,7 @@ struct Timer { } // Remove before 2026.8.0 ESPDEPRECATED("Use to_str() instead. Removed in 2026.8.0", "2026.2.0") - std::string to_string() const { + std::string to_string() const { // NOLINT char buffer[TO_STR_BUFFER_SIZE]; return this->to_str(buffer); } diff --git a/script/ci-custom.py b/script/ci-custom.py index b5bec74fa7..8c405b04ae 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -756,6 +756,53 @@ def lint_no_sprintf(fname, match): ) +@lint_re_check( + # Match std::to_string() or unqualified to_string() calls + # The esphome namespace has "using std::to_string;" so unqualified calls resolve to std::to_string + # Use negative lookbehind for unqualified calls to avoid matching: + # - Function definitions: "const char *to_string(" or "std::string to_string(" + # - Method definitions: "Class::to_string(" + # - Method calls: ".to_string(" or "->to_string(" + # - Other identifiers: "_to_string(" + # Also explicitly match std::to_string since : is in the lookbehind + r"(?:(?<![*&.\w>:])to_string|std\s*::\s*to_string)\s*\(" + CPP_RE_EOL, + include=cpp_include, + exclude=[ + # Vendored library + "esphome/components/http_request/httplib.h", + # Deprecated helpers that return std::string + "esphome/core/helpers.cpp", + # The using declaration itself + "esphome/core/helpers.h", + # Test fixtures - not production embedded code + "tests/integration/fixtures/*", + ], +) +def lint_no_std_to_string(fname, match): + return ( + f"{highlight('std::to_string()')} (including unqualified {highlight('to_string()')}) " + f"allocates heap memory. On long-running embedded devices, repeated heap allocations " + f"fragment memory over time.\n" + f"Please use {highlight('snprintf()')} with a stack buffer instead.\n" + f"\n" + f"Buffer sizes and format specifiers (sizes include sign and null terminator):\n" + f" uint8_t: 4 chars - %u (or PRIu8)\n" + f" int8_t: 5 chars - %d (or PRId8)\n" + f" uint16_t: 6 chars - %u (or PRIu16)\n" + f" int16_t: 7 chars - %d (or PRId16)\n" + f" uint32_t: 11 chars - %" + "PRIu32\n" + " int32_t: 12 chars - %" + "PRId32\n" + " uint64_t: 21 chars - %" + "PRIu64\n" + " int64_t: 21 chars - %" + "PRId64\n" + f" float/double: 24 chars - %.8g (15 digits + sign + decimal + e+XXX)\n" + f" 317 chars - %f (for DBL_MAX: 309 int digits + decimal + 6 frac + sign)\n" + f"\n" + f"For sensor values, use value_accuracy_to_buf() from helpers.h.\n" + f'Example: char buf[11]; snprintf(buf, sizeof(buf), "%" PRIu32, value);\n' + f"(If strictly necessary, add `{highlight('// NOLINT')}` to the end of the line)" + ) + + @lint_re_check( # Match scanf family functions: scanf, sscanf, fscanf, vscanf, vsscanf, vfscanf # Also match std:: prefixed versions From 6c6da8a3cd2ab8dd41c6cd20cbed8884a30a7906 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 12:45:24 -0600 Subject: [PATCH 0603/2030] [api] Skip class generation for empty SOURCE_CLIENT protobuf messages (#13880) --- esphome/components/api/api_pb2.h | 91 ---------------------- esphome/components/api/api_pb2_dump.cpp | 28 ------- esphome/components/api/api_pb2_service.cpp | 16 ++-- script/api_protobuf/api_protobuf.py | 53 ++++++++++--- 4 files changed, 52 insertions(+), 136 deletions(-) diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index cf6c65f285..15819da172 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -440,19 +440,6 @@ class PingResponse final : public ProtoMessage { protected: }; -class DeviceInfoRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 9; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "device_info_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; #ifdef USE_AREAS class AreaInfo final : public ProtoMessage { public: @@ -546,19 +533,6 @@ class DeviceInfoResponse final : public ProtoMessage { protected: }; -class ListEntitiesRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 11; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; class ListEntitiesDoneResponse final : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 19; @@ -572,19 +546,6 @@ class ListEntitiesDoneResponse final : public ProtoMessage { protected: }; -class SubscribeStatesRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 20; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_states_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; #ifdef USE_BINARY_SENSOR class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { public: @@ -1037,19 +998,6 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { }; #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -class SubscribeHomeassistantServicesRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 34; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_homeassistant_services_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; class HomeassistantServiceMap final : public ProtoMessage { public: StringRef key{}; @@ -1117,19 +1065,6 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { }; #endif #ifdef USE_API_HOMEASSISTANT_STATES -class SubscribeHomeAssistantStatesRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 38; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_home_assistant_states_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; class SubscribeHomeAssistantStateResponse final : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 39; @@ -2160,19 +2095,6 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { protected: }; -class SubscribeBluetoothConnectionsFreeRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 80; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_bluetooth_connections_free_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; class BluetoothConnectionsFreeResponse final : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 81; @@ -2279,19 +2201,6 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { protected: }; -class UnsubscribeBluetoothLEAdvertisementsRequest final : public ProtoMessage { - public: - static constexpr uint8_t MESSAGE_TYPE = 87; - static constexpr uint8_t ESTIMATED_SIZE = 0; -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "unsubscribe_bluetooth_le_advertisements_request"; } -#endif -#ifdef HAS_PROTO_MESSAGE_DUMP - const char *dump_to(DumpBuffer &out) const override; -#endif - - protected: -}; class BluetoothDeviceClearCacheResponse final : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 88; diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index e9db36ae21..f1e3bdcafe 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -764,10 +764,6 @@ const char *PingResponse::dump_to(DumpBuffer &out) const { out.append("PingResponse {}"); return out.c_str(); } -const char *DeviceInfoRequest::dump_to(DumpBuffer &out) const { - out.append("DeviceInfoRequest {}"); - return out.c_str(); -} #ifdef USE_AREAS const char *AreaInfo::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "AreaInfo"); @@ -848,18 +844,10 @@ const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { #endif return out.c_str(); } -const char *ListEntitiesRequest::dump_to(DumpBuffer &out) const { - out.append("ListEntitiesRequest {}"); - return out.c_str(); -} const char *ListEntitiesDoneResponse::dump_to(DumpBuffer &out) const { out.append("ListEntitiesDoneResponse {}"); return out.c_str(); } -const char *SubscribeStatesRequest::dump_to(DumpBuffer &out) const { - out.append("SubscribeStatesRequest {}"); - return out.c_str(); -} #ifdef USE_BINARY_SENSOR const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "ListEntitiesBinarySensorResponse"); @@ -1191,10 +1179,6 @@ const char *NoiseEncryptionSetKeyResponse::dump_to(DumpBuffer &out) const { } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -const char *SubscribeHomeassistantServicesRequest::dump_to(DumpBuffer &out) const { - out.append("SubscribeHomeassistantServicesRequest {}"); - return out.c_str(); -} const char *HomeassistantServiceMap::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HomeassistantServiceMap"); dump_field(out, "key", this->key); @@ -1245,10 +1229,6 @@ const char *HomeassistantActionResponse::dump_to(DumpBuffer &out) const { } #endif #ifdef USE_API_HOMEASSISTANT_STATES -const char *SubscribeHomeAssistantStatesRequest::dump_to(DumpBuffer &out) const { - out.append("SubscribeHomeAssistantStatesRequest {}"); - return out.c_str(); -} const char *SubscribeHomeAssistantStateResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "SubscribeHomeAssistantStateResponse"); dump_field(out, "entity_id", this->entity_id); @@ -1924,10 +1904,6 @@ const char *BluetoothGATTNotifyDataResponse::dump_to(DumpBuffer &out) const { dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); return out.c_str(); } -const char *SubscribeBluetoothConnectionsFreeRequest::dump_to(DumpBuffer &out) const { - out.append("SubscribeBluetoothConnectionsFreeRequest {}"); - return out.c_str(); -} const char *BluetoothConnectionsFreeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothConnectionsFreeResponse"); dump_field(out, "free", this->free); @@ -1970,10 +1946,6 @@ const char *BluetoothDeviceUnpairingResponse::dump_to(DumpBuffer &out) const { dump_field(out, "error", this->error); return out.c_str(); } -const char *UnsubscribeBluetoothLEAdvertisementsRequest::dump_to(DumpBuffer &out) const { - out.append("UnsubscribeBluetoothLEAdvertisementsRequest {}"); - return out.c_str(); -} const char *BluetoothDeviceClearCacheResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "BluetoothDeviceClearCacheResponse"); dump_field(out, "address", this->address); diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index 2d15deb90d..f9151ae3b4 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -27,7 +27,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, case DisconnectRequest::MESSAGE_TYPE: // No setup required case PingRequest::MESSAGE_TYPE: // No setup required break; - case DeviceInfoRequest::MESSAGE_TYPE: // Connection setup only + case 9 /* DeviceInfoRequest is empty */: // Connection setup only if (!this->check_connection_setup_()) { return; } @@ -76,21 +76,21 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, this->on_ping_response(); break; } - case DeviceInfoRequest::MESSAGE_TYPE: { + case 9 /* DeviceInfoRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_device_info_request")); #endif this->on_device_info_request(); break; } - case ListEntitiesRequest::MESSAGE_TYPE: { + case 11 /* ListEntitiesRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_list_entities_request")); #endif this->on_list_entities_request(); break; } - case SubscribeStatesRequest::MESSAGE_TYPE: { + case 20 /* SubscribeStatesRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_subscribe_states_request")); #endif @@ -151,7 +151,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES - case SubscribeHomeassistantServicesRequest::MESSAGE_TYPE: { + case 34 /* SubscribeHomeassistantServicesRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_subscribe_homeassistant_services_request")); #endif @@ -169,7 +169,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, break; } #ifdef USE_API_HOMEASSISTANT_STATES - case SubscribeHomeAssistantStatesRequest::MESSAGE_TYPE: { + case 38 /* SubscribeHomeAssistantStatesRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_subscribe_home_assistant_states_request")); #endif @@ -376,7 +376,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } #endif #ifdef USE_BLUETOOTH_PROXY - case SubscribeBluetoothConnectionsFreeRequest::MESSAGE_TYPE: { + case 80 /* SubscribeBluetoothConnectionsFreeRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_subscribe_bluetooth_connections_free_request")); #endif @@ -385,7 +385,7 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, } #endif #ifdef USE_BLUETOOTH_PROXY - case UnsubscribeBluetoothLEAdvertisementsRequest::MESSAGE_TYPE: { + case 87 /* UnsubscribeBluetoothLEAdvertisementsRequest is empty */: { #ifdef HAS_PROTO_MESSAGE_DUMP this->log_receive_message_(LOG_STR("on_unsubscribe_bluetooth_le_advertisements_request")); #endif diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index ece0b5692f..4fbee49dae 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2277,6 +2277,12 @@ ifdefs: dict[str, str] = {} # Track messages with no fields (empty messages) for parameter elision EMPTY_MESSAGES: set[str] = set() +# Track empty SOURCE_CLIENT messages that don't need class generation +# These messages have no fields and are only received (never sent), so the +# class definition (vtable, dump_to, message_name, ESTIMATED_SIZE) is dead code +# that the compiler compiles but the linker strips away. +SKIP_CLASS_GENERATION: set[str] = set() + def get_opt( desc: descriptor.DescriptorProto, @@ -2527,7 +2533,11 @@ def build_service_message_type( case += "#endif\n" case += f"this->{func}({'msg' if not is_empty else ''});\n" case += "break;" - RECEIVE_CASES[id_] = (case, ifdef, mt.name) + if mt.name in SKIP_CLASS_GENERATION: + case_label = f"{id_} /* {mt.name} is empty */" + else: + case_label = f"{mt.name}::MESSAGE_TYPE" + RECEIVE_CASES[id_] = (case, ifdef, case_label) # Only close ifdef if we opened it if ifdef is not None: @@ -2723,6 +2733,19 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint mt = file.message_type + # Identify empty SOURCE_CLIENT messages that don't need class generation + for m in mt: + if m.options.deprecated: + continue + if not m.options.HasExtension(pb.id): + continue + source = message_source_map.get(m.name) + if source != SOURCE_CLIENT: + continue + has_fields = any(not field.options.deprecated for field in m.field) + if not has_fields: + SKIP_CLASS_GENERATION.add(m.name) + # Collect messages by base class base_class_groups = collect_messages_by_base_class(mt) @@ -2755,6 +2778,10 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint if m.name not in used_messages and not m.options.HasExtension(pb.id): continue + # Skip class generation for empty SOURCE_CLIENT messages + if m.name in SKIP_CLASS_GENERATION: + continue + s, c, dc = build_message_type(m, base_class_fields, message_source_map) msg_ifdef = message_ifdef_map.get(m.name) @@ -2901,10 +2928,18 @@ static const char *const TAG = "api.service"; no_conn_ids: set[int] = set() conn_only_ids: set[int] = set() - for id_, (_, _, case_msg_name) in cases: - if case_msg_name in message_auth_map: - needs_auth = message_auth_map[case_msg_name] - needs_conn = message_conn_map[case_msg_name] + # Build a reverse lookup from message id to message name for auth lookups + id_to_msg_name: dict[int, str] = {} + for mt in file.message_type: + id_ = get_opt(mt, pb.id) + if id_ is not None and not mt.options.deprecated: + id_to_msg_name[id_] = mt.name + + for id_, (_, _, case_label) in cases: + msg_name = id_to_msg_name.get(id_, "") + if msg_name in message_auth_map: + needs_auth = message_auth_map[msg_name] + needs_conn = message_conn_map[msg_name] if not needs_conn: no_conn_ids.add(id_) @@ -2915,10 +2950,10 @@ static const char *const TAG = "api.service"; def generate_cases(ids: set[int], comment: str) -> str: result = "" for id_ in sorted(ids): - _, ifdef, msg_name = RECEIVE_CASES[id_] + _, ifdef, case_label = RECEIVE_CASES[id_] if ifdef: result += f"#ifdef {ifdef}\n" - result += f" case {msg_name}::MESSAGE_TYPE: {comment}\n" + result += f" case {case_label}: {comment}\n" if ifdef: result += "#endif\n" return result @@ -2958,11 +2993,11 @@ static const char *const TAG = "api.service"; # Dispatch switch out += " switch (msg_type) {\n" - for i, (case, ifdef, message_name) in cases: + for i, (case, ifdef, case_label) in cases: if ifdef is not None: out += f"#ifdef {ifdef}\n" - c = f" case {message_name}::MESSAGE_TYPE: {{\n" + c = f" case {case_label}: {{\n" c += indent(case, " ") + "\n" c += " }" out += c + "\n" From e0712cc53b464ebf3af3c4cb811eabc11173524e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 13:16:22 -0600 Subject: [PATCH 0604/2030] [scheduler] Make core timer ID collisions impossible with type-safe internal IDs (#13882) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../components/binary_sensor/automation.cpp | 34 +++-- esphome/components/binary_sensor/filter.cpp | 39 ++++-- esphome/components/sensor/filter.cpp | 11 +- esphome/core/base_automation.h | 10 +- esphome/core/component.cpp | 16 ++- esphome/core/component.h | 14 ++ esphome/core/scheduler.cpp | 8 +- esphome/core/scheduler.h | 37 +++++- .../scheduler_internal_id_no_collision.yaml | 109 +++++++++++++++ ...test_scheduler_internal_id_no_collision.py | 124 ++++++++++++++++++ 10 files changed, 359 insertions(+), 43 deletions(-) create mode 100644 tests/integration/fixtures/scheduler_internal_id_no_collision.yaml create mode 100644 tests/integration/test_scheduler_internal_id_no_collision.py diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index dfe911a2f8..faebe7e88f 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -5,6 +5,14 @@ namespace esphome::binary_sensor { static const char *const TAG = "binary_sensor.automation"; +// MultiClickTrigger timeout IDs. +// MultiClickTrigger is its own Component instance, so the scheduler scopes +// IDs by component pointer — no risk of collisions between instances. +constexpr uint32_t MULTICLICK_TRIGGER_ID = 0; +constexpr uint32_t MULTICLICK_COOLDOWN_ID = 1; +constexpr uint32_t MULTICLICK_IS_VALID_ID = 2; +constexpr uint32_t MULTICLICK_IS_NOT_VALID_ID = 3; + void MultiClickTrigger::on_state_(bool state) { // Handle duplicate events if (state == this->last_state_) { @@ -27,7 +35,7 @@ void MultiClickTrigger::on_state_(bool state) { evt.min_length, evt.max_length); this->at_index_ = 1; if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) { - this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); }); + this->set_timeout(MULTICLICK_TRIGGER_ID, evt.min_length, [this]() { this->trigger_(); }); } else { this->schedule_is_valid_(evt.min_length); this->schedule_is_not_valid_(evt.max_length); @@ -57,13 +65,13 @@ void MultiClickTrigger::on_state_(bool state) { this->schedule_is_not_valid_(evt.max_length); } else if (*this->at_index_ + 1 != this->timing_.size()) { ESP_LOGV(TAG, "B i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT - this->cancel_timeout("is_not_valid"); + this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); this->schedule_is_valid_(evt.min_length); } else { ESP_LOGV(TAG, "C i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT this->is_valid_ = false; - this->cancel_timeout("is_not_valid"); - this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); }); + this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); + this->set_timeout(MULTICLICK_TRIGGER_ID, evt.min_length, [this]() { this->trigger_(); }); } *this->at_index_ = *this->at_index_ + 1; @@ -71,14 +79,14 @@ void MultiClickTrigger::on_state_(bool state) { void MultiClickTrigger::schedule_cooldown_() { ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %" PRIu32 " ms", this->invalid_cooldown_); this->is_in_cooldown_ = true; - this->set_timeout("cooldown", this->invalid_cooldown_, [this]() { + this->set_timeout(MULTICLICK_COOLDOWN_ID, this->invalid_cooldown_, [this]() { ESP_LOGV(TAG, "Multi Click: Cooldown ended, matching is now enabled again."); this->is_in_cooldown_ = false; }); this->at_index_.reset(); - this->cancel_timeout("trigger"); - this->cancel_timeout("is_valid"); - this->cancel_timeout("is_not_valid"); + this->cancel_timeout(MULTICLICK_TRIGGER_ID); + this->cancel_timeout(MULTICLICK_IS_VALID_ID); + this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); } void MultiClickTrigger::schedule_is_valid_(uint32_t min_length) { if (min_length == 0) { @@ -86,13 +94,13 @@ void MultiClickTrigger::schedule_is_valid_(uint32_t min_length) { return; } this->is_valid_ = false; - this->set_timeout("is_valid", min_length, [this]() { + this->set_timeout(MULTICLICK_IS_VALID_ID, min_length, [this]() { ESP_LOGV(TAG, "Multi Click: You can now %s the button.", this->parent_->state ? "RELEASE" : "PRESS"); this->is_valid_ = true; }); } void MultiClickTrigger::schedule_is_not_valid_(uint32_t max_length) { - this->set_timeout("is_not_valid", max_length, [this]() { + this->set_timeout(MULTICLICK_IS_NOT_VALID_ID, max_length, [this]() { ESP_LOGV(TAG, "Multi Click: You waited too long to %s.", this->parent_->state ? "RELEASE" : "PRESS"); this->is_valid_ = false; this->schedule_cooldown_(); @@ -106,9 +114,9 @@ void MultiClickTrigger::cancel() { void MultiClickTrigger::trigger_() { ESP_LOGV(TAG, "Multi Click: Hooray, multi click is valid. Triggering!"); this->at_index_.reset(); - this->cancel_timeout("trigger"); - this->cancel_timeout("is_valid"); - this->cancel_timeout("is_not_valid"); + this->cancel_timeout(MULTICLICK_TRIGGER_ID); + this->cancel_timeout(MULTICLICK_IS_VALID_ID); + this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); this->trigger(); } diff --git a/esphome/components/binary_sensor/filter.cpp b/esphome/components/binary_sensor/filter.cpp index 9c7238f6d7..d69671c5bf 100644 --- a/esphome/components/binary_sensor/filter.cpp +++ b/esphome/components/binary_sensor/filter.cpp @@ -6,6 +6,14 @@ namespace esphome::binary_sensor { static const char *const TAG = "sensor.filter"; +// Timeout IDs for filter classes. +// Each filter is its own Component instance, so the scheduler scopes +// IDs by component pointer — no risk of collisions between instances. +constexpr uint32_t FILTER_TIMEOUT_ID = 0; +// AutorepeatFilter needs two distinct IDs (both timeouts on the same component) +constexpr uint32_t AUTOREPEAT_TIMING_ID = 0; +constexpr uint32_t AUTOREPEAT_ON_OFF_ID = 1; + void Filter::output(bool value) { if (this->next_ == nullptr) { this->parent_->send_state_internal(value); @@ -23,16 +31,16 @@ void Filter::input(bool value) { } void TimeoutFilter::input(bool value) { - this->set_timeout("timeout", this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); }); + this->set_timeout(FILTER_TIMEOUT_ID, this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); }); // we do not de-dup here otherwise changes from invalid to valid state will not be output this->output(value); } optional<bool> DelayedOnOffFilter::new_value(bool value) { if (value) { - this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); }); + this->set_timeout(FILTER_TIMEOUT_ID, this->on_delay_.value(), [this]() { this->output(true); }); } else { - this->set_timeout("ON_OFF", this->off_delay_.value(), [this]() { this->output(false); }); + this->set_timeout(FILTER_TIMEOUT_ID, this->off_delay_.value(), [this]() { this->output(false); }); } return {}; } @@ -41,10 +49,10 @@ float DelayedOnOffFilter::get_setup_priority() const { return setup_priority::HA optional<bool> DelayedOnFilter::new_value(bool value) { if (value) { - this->set_timeout("ON", this->delay_.value(), [this]() { this->output(true); }); + this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(true); }); return {}; } else { - this->cancel_timeout("ON"); + this->cancel_timeout(FILTER_TIMEOUT_ID); return false; } } @@ -53,10 +61,10 @@ float DelayedOnFilter::get_setup_priority() const { return setup_priority::HARDW optional<bool> DelayedOffFilter::new_value(bool value) { if (!value) { - this->set_timeout("OFF", this->delay_.value(), [this]() { this->output(false); }); + this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(false); }); return {}; } else { - this->cancel_timeout("OFF"); + this->cancel_timeout(FILTER_TIMEOUT_ID); return true; } } @@ -76,8 +84,8 @@ optional<bool> AutorepeatFilter::new_value(bool value) { this->next_timing_(); return true; } else { - this->cancel_timeout("TIMING"); - this->cancel_timeout("ON_OFF"); + this->cancel_timeout(AUTOREPEAT_TIMING_ID); + this->cancel_timeout(AUTOREPEAT_ON_OFF_ID); this->active_timing_ = 0; return false; } @@ -88,8 +96,10 @@ void AutorepeatFilter::next_timing_() { // 1st time: starts waiting the first delay // 2nd time: starts waiting the second delay and starts toggling with the first time_off / _on // last time: no delay to start but have to bump the index to reflect the last - if (this->active_timing_ < this->timings_.size()) - this->set_timeout("TIMING", this->timings_[this->active_timing_].delay, [this]() { this->next_timing_(); }); + if (this->active_timing_ < this->timings_.size()) { + this->set_timeout(AUTOREPEAT_TIMING_ID, this->timings_[this->active_timing_].delay, + [this]() { this->next_timing_(); }); + } if (this->active_timing_ <= this->timings_.size()) { this->active_timing_++; @@ -104,7 +114,8 @@ void AutorepeatFilter::next_timing_() { void AutorepeatFilter::next_value_(bool val) { const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2]; this->output(val); // This is at least the second one so not initial - this->set_timeout("ON_OFF", val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); }); + this->set_timeout(AUTOREPEAT_ON_OFF_ID, val ? timing.time_on : timing.time_off, + [this, val]() { this->next_value_(!val); }); } float AutorepeatFilter::get_setup_priority() const { return setup_priority::HARDWARE; } @@ -115,7 +126,7 @@ optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); } optional<bool> SettleFilter::new_value(bool value) { if (!this->steady_) { - this->set_timeout("SETTLE", this->delay_.value(), [this, value]() { + this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this, value]() { this->steady_ = true; this->output(value); }); @@ -123,7 +134,7 @@ optional<bool> SettleFilter::new_value(bool value) { } else { this->steady_ = false; this->output(value); - this->set_timeout("SETTLE", this->delay_.value(), [this]() { this->steady_ = true; }); + this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->steady_ = true; }); return value; } } diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 375505a557..ea0e2f0d7c 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -9,6 +9,11 @@ namespace esphome::sensor { static const char *const TAG = "sensor.filter"; +// Filter scheduler IDs. +// Each filter is its own Component instance, so the scheduler scopes +// IDs by component pointer — no risk of collisions between instances. +constexpr uint32_t FILTER_ID = 0; + // Filter void Filter::input(float value) { ESP_LOGVV(TAG, "Filter(%p)::input(%f)", this, value); @@ -191,7 +196,7 @@ optional<float> ThrottleAverageFilter::new_value(float value) { return {}; } void ThrottleAverageFilter::setup() { - this->set_interval("throttle_average", this->time_period_, [this]() { + this->set_interval(FILTER_ID, this->time_period_, [this]() { ESP_LOGVV(TAG, "ThrottleAverageFilter(%p)::interval(sum=%f, n=%i)", this, this->sum_, this->n_); if (this->n_ == 0) { if (this->have_nan_) @@ -383,7 +388,7 @@ optional<float> TimeoutFilterConfigured::new_value(float value) { // DebounceFilter optional<float> DebounceFilter::new_value(float value) { - this->set_timeout("debounce", this->time_period_, [this, value]() { this->output(value); }); + this->set_timeout(FILTER_ID, this->time_period_, [this, value]() { this->output(value); }); return {}; } @@ -406,7 +411,7 @@ optional<float> HeartbeatFilter::new_value(float value) { } void HeartbeatFilter::setup() { - this->set_interval("heartbeat", this->time_period_, [this]() { + this->set_interval(FILTER_ID, this->time_period_, [this]() { ESP_LOGVV(TAG, "HeartbeatFilter(%p)::interval(has_value=%s, last_input=%f)", this, YESNO(this->has_value_), this->last_input_); if (!this->has_value_) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 19d0ccf972..67e1755cc9 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -191,15 +191,17 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon // instead of std::bind to avoid bind overhead (~16 bytes heap + faster execution) if constexpr (sizeof...(Ts) == 0) { App.scheduler.set_timer_common_( - this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::STATIC_STRING, "delay", 0, this->delay_.value(), + this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL, nullptr, + static_cast<uint32_t>(InternalSchedulerID::DELAY_ACTION), this->delay_.value(), [this]() { this->play_next_(); }, /* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1); } else { // For delays with arguments, use std::bind to preserve argument values // Arguments must be copied because original references may be invalid after delay auto f = std::bind(&DelayAction<Ts...>::play_next_, this, x...); - App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::STATIC_STRING, - "delay", 0, this->delay_.value(x...), std::move(f), + App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL, + nullptr, static_cast<uint32_t>(InternalSchedulerID::DELAY_ACTION), + this->delay_.value(x...), std::move(f), /* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1); } } @@ -208,7 +210,7 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon void play(const Ts &...x) override { /* ignore - see play_complex */ } - void stop() override { this->cancel_timeout("delay"); } + void stop() override { this->cancel_timeout(InternalSchedulerID::DELAY_ACTION); } }; template<typename... Ts> class LambdaAction : public Action<Ts...> { diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 6d8d1c57af..90aa36f4db 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -201,12 +201,24 @@ void Component::set_timeout(uint32_t id, uint32_t timeout, std::function<void()> bool Component::cancel_timeout(uint32_t id) { return App.scheduler.cancel_timeout(this, id); } +void Component::set_timeout(InternalSchedulerID id, uint32_t timeout, std::function<void()> &&f) { // NOLINT + App.scheduler.set_timeout(this, id, timeout, std::move(f)); +} + +bool Component::cancel_timeout(InternalSchedulerID id) { return App.scheduler.cancel_timeout(this, id); } + void Component::set_interval(uint32_t id, uint32_t interval, std::function<void()> &&f) { // NOLINT App.scheduler.set_interval(this, id, interval, std::move(f)); } bool Component::cancel_interval(uint32_t id) { return App.scheduler.cancel_interval(this, id); } +void Component::set_interval(InternalSchedulerID id, uint32_t interval, std::function<void()> &&f) { // NOLINT + App.scheduler.set_interval(this, id, interval, std::move(f)); +} + +bool Component::cancel_interval(InternalSchedulerID id) { return App.scheduler.cancel_interval(this, id); } + void Component::set_retry(uint32_t id, uint32_t initial_wait_time, uint8_t max_attempts, std::function<RetryResult(uint8_t)> &&f, float backoff_increase_factor) { // NOLINT #pragma GCC diagnostic push @@ -533,12 +545,12 @@ void PollingComponent::call_setup() { void PollingComponent::start_poller() { // Register interval. - this->set_interval("update", this->get_update_interval(), [this]() { this->update(); }); + this->set_interval(InternalSchedulerID::POLLING_UPDATE, this->get_update_interval(), [this]() { this->update(); }); } void PollingComponent::stop_poller() { // Clear the interval to suspend component - this->cancel_interval("update"); + this->cancel_interval(InternalSchedulerID::POLLING_UPDATE); } uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } diff --git a/esphome/core/component.h b/esphome/core/component.h index c3582e23b1..9ab77cc2f9 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -49,6 +49,14 @@ extern const float LATE; static const uint32_t SCHEDULER_DONT_RUN = 4294967295UL; +/// Type-safe scheduler IDs for core base classes. +/// Uses a separate NameType (NUMERIC_ID_INTERNAL) so IDs can never collide +/// with component-level NUMERIC_ID values, even if the uint32_t values overlap. +enum class InternalSchedulerID : uint32_t { + POLLING_UPDATE = 0, // PollingComponent interval + DELAY_ACTION = 1, // DelayAction timeout +}; + // Forward declaration class PollingComponent; @@ -335,6 +343,8 @@ class Component { */ void set_interval(uint32_t id, uint32_t interval, std::function<void()> &&f); // NOLINT + void set_interval(InternalSchedulerID id, uint32_t interval, std::function<void()> &&f); // NOLINT + void set_interval(uint32_t interval, std::function<void()> &&f); // NOLINT /** Cancel an interval function. @@ -347,6 +357,7 @@ class Component { bool cancel_interval(const std::string &name); // NOLINT bool cancel_interval(const char *name); // NOLINT bool cancel_interval(uint32_t id); // NOLINT + bool cancel_interval(InternalSchedulerID id); // NOLINT /// @deprecated set_retry is deprecated. Use set_timeout or set_interval instead. Removed in 2026.8.0. // Remove before 2026.8.0 @@ -425,6 +436,8 @@ class Component { */ void set_timeout(uint32_t id, uint32_t timeout, std::function<void()> &&f); // NOLINT + void set_timeout(InternalSchedulerID id, uint32_t timeout, std::function<void()> &&f); // NOLINT + void set_timeout(uint32_t timeout, std::function<void()> &&f); // NOLINT /** Cancel a timeout function. @@ -437,6 +450,7 @@ class Component { bool cancel_timeout(const std::string &name); // NOLINT bool cancel_timeout(const char *name); // NOLINT bool cancel_timeout(uint32_t id); // NOLINT + bool cancel_timeout(InternalSchedulerID id); // NOLINT /** Defer a callback to the next loop() call. * diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index a5e308829a..97ac28b623 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -53,9 +53,12 @@ struct SchedulerNameLog { } else if (name_type == NameType::HASHED_STRING) { ESPHOME_snprintf_P(buffer, sizeof(buffer), ESPHOME_PSTR("hash:0x%08" PRIX32), hash_or_id); return buffer; - } else { // NUMERIC_ID + } else if (name_type == NameType::NUMERIC_ID) { ESPHOME_snprintf_P(buffer, sizeof(buffer), ESPHOME_PSTR("id:%" PRIu32), hash_or_id); return buffer; + } else { // NUMERIC_ID_INTERNAL + ESPHOME_snprintf_P(buffer, sizeof(buffer), ESPHOME_PSTR("iid:%" PRIu32), hash_or_id); + return buffer; } } }; @@ -137,6 +140,9 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type case NameType::NUMERIC_ID: item->set_numeric_id(hash_or_id); break; + case NameType::NUMERIC_ID_INTERNAL: + item->set_internal_id(hash_or_id); + break; } item->type = type; item->callback = std::move(func); diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 20b069f3f0..ede729d164 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -46,11 +46,20 @@ class Scheduler { void set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func); /// Set a timeout with a numeric ID (zero heap allocation) void set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function<void()> func); + /// Set a timeout with an internal scheduler ID (separate namespace from component NUMERIC_ID) + void set_timeout(Component *component, InternalSchedulerID id, uint32_t timeout, std::function<void()> func) { + this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::NUMERIC_ID_INTERNAL, nullptr, + static_cast<uint32_t>(id), timeout, std::move(func)); + } ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_timeout(Component *component, const std::string &name); bool cancel_timeout(Component *component, const char *name); bool cancel_timeout(Component *component, uint32_t id); + bool cancel_timeout(Component *component, InternalSchedulerID id) { + return this->cancel_item_(component, NameType::NUMERIC_ID_INTERNAL, nullptr, static_cast<uint32_t>(id), + SchedulerItem::TIMEOUT); + } ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") void set_interval(Component *component, const std::string &name, uint32_t interval, std::function<void()> func); @@ -66,11 +75,20 @@ class Scheduler { void set_interval(Component *component, const char *name, uint32_t interval, std::function<void()> func); /// Set an interval with a numeric ID (zero heap allocation) void set_interval(Component *component, uint32_t id, uint32_t interval, std::function<void()> func); + /// Set an interval with an internal scheduler ID (separate namespace from component NUMERIC_ID) + void set_interval(Component *component, InternalSchedulerID id, uint32_t interval, std::function<void()> func) { + this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::NUMERIC_ID_INTERNAL, nullptr, + static_cast<uint32_t>(id), interval, std::move(func)); + } ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") bool cancel_interval(Component *component, const std::string &name); bool cancel_interval(Component *component, const char *name); bool cancel_interval(Component *component, uint32_t id); + bool cancel_interval(Component *component, InternalSchedulerID id) { + return this->cancel_item_(component, NameType::NUMERIC_ID_INTERNAL, nullptr, static_cast<uint32_t>(id), + SchedulerItem::INTERVAL); + } // Remove before 2026.8.0 ESPDEPRECATED("set_retry is deprecated and will be removed in 2026.8.0. Use set_timeout or set_interval instead.", @@ -112,11 +130,12 @@ class Scheduler { void process_to_add(); // Name storage type discriminator for SchedulerItem - // Used to distinguish between static strings, hashed strings, and numeric IDs + // Used to distinguish between static strings, hashed strings, numeric IDs, and internal numeric IDs enum class NameType : uint8_t { - STATIC_STRING = 0, // const char* pointer to static/flash storage - HASHED_STRING = 1, // uint32_t FNV-1a hash of a runtime string - NUMERIC_ID = 2 // uint32_t numeric identifier + STATIC_STRING = 0, // const char* pointer to static/flash storage + HASHED_STRING = 1, // uint32_t FNV-1a hash of a runtime string + NUMERIC_ID = 2, // uint32_t numeric identifier (component-level) + NUMERIC_ID_INTERNAL = 3 // uint32_t numeric identifier (core/internal, separate namespace) }; protected: @@ -147,7 +166,7 @@ class Scheduler { // Bit-packed fields (4 bits used, 4 bits padding in 1 byte) enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; - NameType name_type_ : 2; // Discriminator for name_ union (STATIC_STRING, HASHED_STRING, NUMERIC_ID) + NameType name_type_ : 2; // Discriminator for name_ union (0–3, see NameType enum) bool is_retry : 1; // True if this is a retry timeout // 4 bits padding #else @@ -155,7 +174,7 @@ class Scheduler { // Bit-packed fields (5 bits used, 3 bits padding in 1 byte) enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; bool remove : 1; - NameType name_type_ : 2; // Discriminator for name_ union (STATIC_STRING, HASHED_STRING, NUMERIC_ID) + NameType name_type_ : 2; // Discriminator for name_ union (0–3, see NameType enum) bool is_retry : 1; // True if this is a retry timeout // 3 bits padding #endif @@ -218,6 +237,12 @@ class Scheduler { name_type_ = NameType::NUMERIC_ID; } + // Helper to set an internal numeric ID (separate namespace from NUMERIC_ID) + void set_internal_id(uint32_t id) { + name_.hash_or_id = id; + name_type_ = NameType::NUMERIC_ID_INTERNAL; + } + static bool cmp(const std::unique_ptr<SchedulerItem> &a, const std::unique_ptr<SchedulerItem> &b); // Note: We use 48 bits total (32 + 16), stored in a 64-bit value for API compatibility. diff --git a/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml b/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml new file mode 100644 index 0000000000..46dbb8e728 --- /dev/null +++ b/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml @@ -0,0 +1,109 @@ +esphome: + name: scheduler-internal-id-test + on_boot: + priority: -100 + then: + - logger.log: "Starting scheduler internal ID collision tests" + +host: +api: +logger: + level: VERBOSE + +globals: + - id: tests_done + type: bool + initial_value: 'false' + +script: + - id: test_internal_id_no_collision + then: + - logger.log: "Testing NUMERIC_ID_INTERNAL vs NUMERIC_ID isolation" + - lambda: |- + // All tests use the same component and the same uint32_t value (0). + // NUMERIC_ID_INTERNAL and NUMERIC_ID are separate NameType values, + // so the scheduler must treat them as independent timers. + auto *comp = id(test_sensor); + + // ---- Test 1: Both timeout types fire independently ---- + // Set an internal timeout with ID 0 + App.scheduler.set_timeout(comp, InternalSchedulerID{0}, 50, []() { + ESP_LOGI("test", "Internal timeout 0 fired"); + }); + // Set a component numeric timeout with the same ID 0 + App.scheduler.set_timeout(comp, 0U, 50, []() { + ESP_LOGI("test", "Numeric timeout 0 fired"); + }); + + // ---- Test 2: Cancelling numeric ID does NOT cancel internal ID ---- + // Set an internal timeout with ID 1 + App.scheduler.set_timeout(comp, InternalSchedulerID{1}, 100, []() { + ESP_LOGI("test", "Internal timeout 1 survived cancel"); + }); + // Set a numeric timeout with the same ID 1 + App.scheduler.set_timeout(comp, 1U, 100, []() { + ESP_LOGE("test", "ERROR: Numeric timeout 1 should have been cancelled"); + }); + // Cancel only the numeric one + App.scheduler.cancel_timeout(comp, 1U); + + // ---- Test 3: Cancelling internal ID does NOT cancel numeric ID ---- + // Set a numeric timeout with ID 2 + App.scheduler.set_timeout(comp, 2U, 150, []() { + ESP_LOGI("test", "Numeric timeout 2 survived cancel"); + }); + // Set an internal timeout with the same ID 2 + App.scheduler.set_timeout(comp, InternalSchedulerID{2}, 150, []() { + ESP_LOGE("test", "ERROR: Internal timeout 2 should have been cancelled"); + }); + // Cancel only the internal one + App.scheduler.cancel_timeout(comp, InternalSchedulerID{2}); + + // ---- Test 4: Both interval types fire independently ---- + static int internal_interval_count = 0; + static int numeric_interval_count = 0; + App.scheduler.set_interval(comp, InternalSchedulerID{3}, 100, []() { + internal_interval_count++; + if (internal_interval_count == 2) { + ESP_LOGI("test", "Internal interval 3 fired twice"); + App.scheduler.cancel_interval(id(test_sensor), InternalSchedulerID{3}); + } + }); + App.scheduler.set_interval(comp, 3U, 100, []() { + numeric_interval_count++; + if (numeric_interval_count == 2) { + ESP_LOGI("test", "Numeric interval 3 fired twice"); + App.scheduler.cancel_interval(id(test_sensor), 3U); + } + }); + + // ---- Test 5: String name does NOT collide with internal ID ---- + // Use string name and internal ID 10 on same component + App.scheduler.set_timeout(comp, "collision_test", 200, []() { + ESP_LOGI("test", "String timeout collision_test fired"); + }); + App.scheduler.set_timeout(comp, InternalSchedulerID{10}, 200, []() { + ESP_LOGI("test", "Internal timeout 10 fired"); + }); + + // Log completion after all timers should have fired + App.scheduler.set_timeout(comp, 9999U, 1500, []() { + ESP_LOGI("test", "All collision tests complete"); + }); + +sensor: + - platform: template + name: Test Sensor + id: test_sensor + lambda: return 1.0; + update_interval: never + +interval: + - interval: 0.1s + then: + - if: + condition: + lambda: 'return id(tests_done) == false;' + then: + - lambda: 'id(tests_done) = true;' + - script.execute: test_internal_id_no_collision diff --git a/tests/integration/test_scheduler_internal_id_no_collision.py b/tests/integration/test_scheduler_internal_id_no_collision.py new file mode 100644 index 0000000000..d30e725e00 --- /dev/null +++ b/tests/integration/test_scheduler_internal_id_no_collision.py @@ -0,0 +1,124 @@ +"""Test that NUMERIC_ID_INTERNAL and NUMERIC_ID cannot collide. + +Verifies that InternalSchedulerID (used by core base classes like +PollingComponent and DelayAction) and uint32_t numeric IDs (used by +components) are in completely separate matching namespaces, even when +the underlying uint32_t values are identical and on the same component. +""" + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_scheduler_internal_id_no_collision( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that internal and numeric IDs with same value don't collide.""" + # Test 1: Both types fire independently with same ID + internal_timeout_0_fired = asyncio.Event() + numeric_timeout_0_fired = asyncio.Event() + + # Test 2: Cancelling numeric doesn't cancel internal + internal_timeout_1_survived = asyncio.Event() + numeric_timeout_1_error = asyncio.Event() + + # Test 3: Cancelling internal doesn't cancel numeric + numeric_timeout_2_survived = asyncio.Event() + internal_timeout_2_error = asyncio.Event() + + # Test 4: Both interval types fire independently + internal_interval_3_done = asyncio.Event() + numeric_interval_3_done = asyncio.Event() + + # Test 5: String name doesn't collide with internal ID + string_timeout_fired = asyncio.Event() + internal_timeout_10_fired = asyncio.Event() + + # Completion + all_tests_complete = asyncio.Event() + + def on_log_line(line: str) -> None: + clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line) + + if "Internal timeout 0 fired" in clean_line: + internal_timeout_0_fired.set() + elif "Numeric timeout 0 fired" in clean_line: + numeric_timeout_0_fired.set() + elif "Internal timeout 1 survived cancel" in clean_line: + internal_timeout_1_survived.set() + elif "ERROR: Numeric timeout 1 should have been cancelled" in clean_line: + numeric_timeout_1_error.set() + elif "Numeric timeout 2 survived cancel" in clean_line: + numeric_timeout_2_survived.set() + elif "ERROR: Internal timeout 2 should have been cancelled" in clean_line: + internal_timeout_2_error.set() + elif "Internal interval 3 fired twice" in clean_line: + internal_interval_3_done.set() + elif "Numeric interval 3 fired twice" in clean_line: + numeric_interval_3_done.set() + elif "String timeout collision_test fired" in clean_line: + string_timeout_fired.set() + elif "Internal timeout 10 fired" in clean_line: + internal_timeout_10_fired.set() + elif "All collision tests complete" in clean_line: + all_tests_complete.set() + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "scheduler-internal-id-test" + + try: + await asyncio.wait_for(all_tests_complete.wait(), timeout=5.0) + except TimeoutError: + pytest.fail("Not all collision tests completed within 5 seconds") + + # Test 1: Both timeout types with same ID 0 must fire + assert internal_timeout_0_fired.is_set(), ( + "Internal timeout with ID 0 should have fired" + ) + assert numeric_timeout_0_fired.is_set(), ( + "Numeric timeout with ID 0 should have fired" + ) + + # Test 2: Cancelling numeric ID must NOT cancel internal ID + assert internal_timeout_1_survived.is_set(), ( + "Internal timeout 1 should survive cancellation of numeric timeout 1" + ) + assert not numeric_timeout_1_error.is_set(), ( + "Numeric timeout 1 should have been cancelled" + ) + + # Test 3: Cancelling internal ID must NOT cancel numeric ID + assert numeric_timeout_2_survived.is_set(), ( + "Numeric timeout 2 should survive cancellation of internal timeout 2" + ) + assert not internal_timeout_2_error.is_set(), ( + "Internal timeout 2 should have been cancelled" + ) + + # Test 4: Both interval types with same ID must fire independently + assert internal_interval_3_done.is_set(), ( + "Internal interval 3 should have fired at least twice" + ) + assert numeric_interval_3_done.is_set(), ( + "Numeric interval 3 should have fired at least twice" + ) + + # Test 5: String name and internal ID don't collide + assert string_timeout_fired.is_set(), ( + "String timeout 'collision_test' should have fired" + ) + assert internal_timeout_10_fired.is_set(), ( + "Internal timeout 10 should have fired alongside string timeout" + ) From 00256e3ca0bf29f7ab3c7226b9a92aa292848394 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 10 Feb 2026 06:35:41 +1100 Subject: [PATCH 0605/2030] [mipi_rgb] Allow use on P4 (#13740) --- esphome/components/mipi_rgb/display.py | 4 +- esphome/components/mipi_rgb/mipi_rgb.cpp | 4 +- esphome/components/mipi_rgb/mipi_rgb.h | 6 +- tests/components/mipi_rgb/common.yaml | 52 +++++++++++++++++ .../mipi_rgb/test.esp32-p4-idf.yaml | 6 ++ .../mipi_rgb/test.esp32-s3-idf.yaml | 56 +------------------ .../common/spi/esp32-p4-idf.yaml | 12 ++++ 7 files changed, 78 insertions(+), 62 deletions(-) create mode 100644 tests/components/mipi_rgb/common.yaml create mode 100644 tests/components/mipi_rgb/test.esp32-p4-idf.yaml create mode 100644 tests/test_build_components/common/spi/esp32-p4-idf.yaml diff --git a/esphome/components/mipi_rgb/display.py b/esphome/components/mipi_rgb/display.py index 084fe6de14..24988cfcf8 100644 --- a/esphome/components/mipi_rgb/display.py +++ b/esphome/components/mipi_rgb/display.py @@ -11,7 +11,7 @@ from esphome.components.const import ( CONF_DRAW_ROUNDING, ) from esphome.components.display import CONF_SHOW_TEST_CARD -from esphome.components.esp32 import VARIANT_ESP32S3, only_on_variant +from esphome.components.esp32 import VARIANT_ESP32P4, VARIANT_ESP32S3, only_on_variant from esphome.components.mipi import ( COLOR_ORDERS, CONF_DE_PIN, @@ -225,7 +225,7 @@ def _config_schema(config): return cv.All( schema, cv.only_on_esp32, - only_on_variant(supported=[VARIANT_ESP32S3]), + only_on_variant(supported=[VARIANT_ESP32S3, VARIANT_ESP32P4]), )(config) diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index d0e716bd24..7ff6868c15 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -1,4 +1,4 @@ -#ifdef USE_ESP32_VARIANT_ESP32S3 +#if defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4) #include "mipi_rgb.h" #include "esphome/core/gpio.h" #include "esphome/core/hal.h" @@ -401,4 +401,4 @@ void MipiRgb::dump_config() { } // namespace mipi_rgb } // namespace esphome -#endif // USE_ESP32_VARIANT_ESP32S3 +#endif // defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4) diff --git a/esphome/components/mipi_rgb/mipi_rgb.h b/esphome/components/mipi_rgb/mipi_rgb.h index 173e23752d..76b48bb249 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.h +++ b/esphome/components/mipi_rgb/mipi_rgb.h @@ -1,6 +1,6 @@ #pragma once -#ifdef USE_ESP32_VARIANT_ESP32S3 +#if defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4) #include "esphome/core/gpio.h" #include "esphome/components/display/display.h" #include "esp_lcd_panel_ops.h" @@ -28,7 +28,7 @@ class MipiRgb : public display::Display { void setup() override; void loop() override; void update() override; - void fill(Color color); + void fill(Color color) override; void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, display::ColorOrder order, display::ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad) override; void write_to_display_(int x_start, int y_start, int w, int h, const uint8_t *ptr, int x_offset, int y_offset, @@ -115,7 +115,7 @@ class MipiRgbSpi : public MipiRgb, void write_command_(uint8_t value); void write_data_(uint8_t value); void write_init_sequence_(); - void dump_config(); + void dump_config() override; GPIOPin *dc_pin_{nullptr}; std::vector<uint8_t> init_sequence_; diff --git a/tests/components/mipi_rgb/common.yaml b/tests/components/mipi_rgb/common.yaml new file mode 100644 index 0000000000..c137bc6af3 --- /dev/null +++ b/tests/components/mipi_rgb/common.yaml @@ -0,0 +1,52 @@ +display: + - platform: mipi_rgb + spi_id: spi_bus + model: ZX2D10GE01R-V4848 + update_interval: 1s + color_order: BGR + draw_rounding: 2 + pixel_mode: 18bit + invert_colors: false + use_axis_flips: true + pclk_frequency: 15000000.0 + pclk_inverted: true + byte_order: big_endian + hsync_pulse_width: 10 + hsync_back_porch: 10 + hsync_front_porch: 10 + vsync_pulse_width: 2 + vsync_back_porch: 12 + vsync_front_porch: 14 + data_pins: + red: + - number: 10 + - number: 16 + - number: 9 + - number: 15 + - number: 46 + green: + - number: 8 + - number: 13 + - number: 18 + - number: 12 + - number: 11 + - number: 17 + blue: + - number: 47 + - number: 1 + - number: 0 + - number: 42 + - number: 14 + de_pin: + number: 39 + pclk_pin: + number: 45 + hsync_pin: + number: 38 + vsync_pin: + number: 48 + data_rate: 1000000.0 + spi_mode: MODE0 + cs_pin: + number: 21 + show_test_card: true diff --git a/tests/components/mipi_rgb/test.esp32-p4-idf.yaml b/tests/components/mipi_rgb/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..62427492eb --- /dev/null +++ b/tests/components/mipi_rgb/test.esp32-p4-idf.yaml @@ -0,0 +1,6 @@ +packages: + spi: !include ../../test_build_components/common/spi/esp32-p4-idf.yaml + +psram: + +<<: !include common.yaml diff --git a/tests/components/mipi_rgb/test.esp32-s3-idf.yaml b/tests/components/mipi_rgb/test.esp32-s3-idf.yaml index 642292f7c4..399c25c1d0 100644 --- a/tests/components/mipi_rgb/test.esp32-s3-idf.yaml +++ b/tests/components/mipi_rgb/test.esp32-s3-idf.yaml @@ -4,58 +4,4 @@ packages: psram: mode: octal -display: - - platform: mipi_rgb - spi_id: spi_bus - model: ZX2D10GE01R-V4848 - update_interval: 1s - color_order: BGR - draw_rounding: 2 - pixel_mode: 18bit - invert_colors: false - use_axis_flips: true - pclk_frequency: 15000000.0 - pclk_inverted: true - byte_order: big_endian - hsync_pulse_width: 10 - hsync_back_porch: 10 - hsync_front_porch: 10 - vsync_pulse_width: 2 - vsync_back_porch: 12 - vsync_front_porch: 14 - data_pins: - red: - - number: 10 - - number: 16 - - number: 9 - - number: 15 - - number: 46 - ignore_strapping_warning: true - green: - - number: 8 - - number: 13 - - number: 18 - - number: 12 - - number: 11 - - number: 17 - blue: - - number: 47 - - number: 1 - - number: 0 - ignore_strapping_warning: true - - number: 42 - - number: 14 - de_pin: - number: 39 - pclk_pin: - number: 45 - ignore_strapping_warning: true - hsync_pin: - number: 38 - vsync_pin: - number: 48 - data_rate: 1000000.0 - spi_mode: MODE0 - cs_pin: - number: 21 - show_test_card: true +<<: !include common.yaml diff --git a/tests/test_build_components/common/spi/esp32-p4-idf.yaml b/tests/test_build_components/common/spi/esp32-p4-idf.yaml new file mode 100644 index 0000000000..5f232a7e94 --- /dev/null +++ b/tests/test_build_components/common/spi/esp32-p4-idf.yaml @@ -0,0 +1,12 @@ +# Common SPI configuration for ESP32-P4 IDF tests + +substitutions: + clk_pin: GPIO36 + mosi_pin: GPIO32 + miso_pin: GPIO33 + +spi: + - id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} From b6fdd299537529f128b570594b3a3584cf7cc8df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 14:42:40 -0600 Subject: [PATCH 0606/2030] [voice_assistant] Replace timer unordered_map with vector to eliminate per-tick heap allocation (#13857) --- .../components/voice_assistant/__init__.py | 7 ++- .../voice_assistant/voice_assistant.cpp | 46 ++++++++++--------- .../voice_assistant/voice_assistant.h | 9 ++-- .../voice_assistant/common-idf.yaml | 21 +++++++++ tests/components/voice_assistant/common.yaml | 21 +++++++++ 5 files changed, 77 insertions(+), 27 deletions(-) diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index d28c786dd8..8b7dcb4f21 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -371,7 +371,12 @@ async def to_code(config): if on_timer_tick := config.get(CONF_ON_TIMER_TICK): await automation.build_automation( var.get_timer_tick_trigger(), - [(cg.std_vector.template(Timer), "timers")], + [ + ( + cg.std_vector.template(Timer).operator("const").operator("ref"), + "timers", + ) + ], on_timer_tick, ) has_timers = True diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 7f5fbe62e1..6267d97480 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -859,35 +859,43 @@ void VoiceAssistant::on_audio(const api::VoiceAssistantAudio &msg) { } void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse &msg) { - Timer timer = { - .id = msg.timer_id, - .name = msg.name, - .total_seconds = msg.total_seconds, - .seconds_left = msg.seconds_left, - .is_active = msg.is_active, - }; - this->timers_[timer.id] = timer; + // Find existing timer or add a new one + auto it = this->timers_.begin(); + for (; it != this->timers_.end(); ++it) { + if (it->id == msg.timer_id) + break; + } + if (it == this->timers_.end()) { + this->timers_.push_back({}); + it = this->timers_.end() - 1; + } + it->id = msg.timer_id; + it->name = msg.name; + it->total_seconds = msg.total_seconds; + it->seconds_left = msg.seconds_left; + it->is_active = msg.is_active; + char timer_buf[Timer::TO_STR_BUFFER_SIZE]; ESP_LOGD(TAG, "Timer Event\n" " Type: %" PRId32 "\n" " %s", - msg.event_type, timer.to_str(timer_buf)); + msg.event_type, it->to_str(timer_buf)); switch (msg.event_type) { case api::enums::VOICE_ASSISTANT_TIMER_STARTED: - this->timer_started_trigger_.trigger(timer); + this->timer_started_trigger_.trigger(*it); break; case api::enums::VOICE_ASSISTANT_TIMER_UPDATED: - this->timer_updated_trigger_.trigger(timer); + this->timer_updated_trigger_.trigger(*it); break; case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED: - this->timer_cancelled_trigger_.trigger(timer); - this->timers_.erase(timer.id); + this->timer_cancelled_trigger_.trigger(*it); + this->timers_.erase(it); break; case api::enums::VOICE_ASSISTANT_TIMER_FINISHED: - this->timer_finished_trigger_.trigger(timer); - this->timers_.erase(timer.id); + this->timer_finished_trigger_.trigger(*it); + this->timers_.erase(it); break; } @@ -901,16 +909,12 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse } void VoiceAssistant::timer_tick_() { - std::vector<Timer> res; - res.reserve(this->timers_.size()); - for (auto &pair : this->timers_) { - auto &timer = pair.second; + for (auto &timer : this->timers_) { if (timer.is_active && timer.seconds_left > 0) { timer.seconds_left--; } - res.push_back(timer); } - this->timer_tick_trigger_.trigger(res); + this->timer_tick_trigger_.trigger(this->timers_); } void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) { diff --git a/esphome/components/voice_assistant/voice_assistant.h b/esphome/components/voice_assistant/voice_assistant.h index 0ef7ecc81a..b1b5f20bff 100644 --- a/esphome/components/voice_assistant/voice_assistant.h +++ b/esphome/components/voice_assistant/voice_assistant.h @@ -24,7 +24,6 @@ #include "esphome/components/socket/socket.h" #include <span> -#include <unordered_map> #include <vector> namespace esphome { @@ -226,9 +225,9 @@ class VoiceAssistant : public Component { Trigger<Timer> *get_timer_updated_trigger() { return &this->timer_updated_trigger_; } Trigger<Timer> *get_timer_cancelled_trigger() { return &this->timer_cancelled_trigger_; } Trigger<Timer> *get_timer_finished_trigger() { return &this->timer_finished_trigger_; } - Trigger<std::vector<Timer>> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; } + Trigger<const std::vector<Timer> &> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; } void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; } - const std::unordered_map<std::string, Timer> &get_timers() const { return this->timers_; } + const std::vector<Timer> &get_timers() const { return this->timers_; } protected: bool allocate_buffers_(); @@ -267,13 +266,13 @@ class VoiceAssistant : public Component { api::APIConnection *api_client_{nullptr}; - std::unordered_map<std::string, Timer> timers_; + std::vector<Timer> timers_; void timer_tick_(); Trigger<Timer> timer_started_trigger_; Trigger<Timer> timer_finished_trigger_; Trigger<Timer> timer_updated_trigger_; Trigger<Timer> timer_cancelled_trigger_; - Trigger<std::vector<Timer>> timer_tick_trigger_; + Trigger<const std::vector<Timer> &> timer_tick_trigger_; bool has_timers_{false}; bool timer_tick_running_{false}; diff --git a/tests/components/voice_assistant/common-idf.yaml b/tests/components/voice_assistant/common-idf.yaml index ab8cbf2434..8565683700 100644 --- a/tests/components/voice_assistant/common-idf.yaml +++ b/tests/components/voice_assistant/common-idf.yaml @@ -68,3 +68,24 @@ voice_assistant: - logger.log: format: "Voice assistant error - code %s, message: %s" args: [code.c_str(), message.c_str()] + on_timer_started: + - logger.log: + format: "Timer started: %s" + args: [timer.id.c_str()] + on_timer_updated: + - logger.log: + format: "Timer updated: %s" + args: [timer.id.c_str()] + on_timer_cancelled: + - logger.log: + format: "Timer cancelled: %s" + args: [timer.id.c_str()] + on_timer_finished: + - logger.log: + format: "Timer finished: %s" + args: [timer.id.c_str()] + on_timer_tick: + - lambda: |- + for (auto &timer : timers) { + ESP_LOGD("timer", "Timer %s: %" PRIu32 "s left", timer.name.c_str(), timer.seconds_left); + } diff --git a/tests/components/voice_assistant/common.yaml b/tests/components/voice_assistant/common.yaml index f248154b7e..d09de74396 100644 --- a/tests/components/voice_assistant/common.yaml +++ b/tests/components/voice_assistant/common.yaml @@ -58,3 +58,24 @@ voice_assistant: - logger.log: format: "Voice assistant error - code %s, message: %s" args: [code.c_str(), message.c_str()] + on_timer_started: + - logger.log: + format: "Timer started: %s" + args: [timer.id.c_str()] + on_timer_updated: + - logger.log: + format: "Timer updated: %s" + args: [timer.id.c_str()] + on_timer_cancelled: + - logger.log: + format: "Timer cancelled: %s" + args: [timer.id.c_str()] + on_timer_finished: + - logger.log: + format: "Timer finished: %s" + args: [timer.id.c_str()] + on_timer_tick: + - lambda: |- + for (auto &timer : timers) { + ESP_LOGD("timer", "Timer %s: %" PRIu32 "s left", timer.name.c_str(), timer.seconds_left); + } From dbf202bf0de5beb0cd09661d424961b810f2db08 Mon Sep 17 00:00:00 2001 From: tronikos <tronikos@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:57:36 -0800 Subject: [PATCH 0607/2030] Add get_away and get_on in WaterHeaterCall and deprecate get_state (#13891) --- esphome/components/water_heater/water_heater.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/esphome/components/water_heater/water_heater.h b/esphome/components/water_heater/water_heater.h index 93fcf5f401..070ae99575 100644 --- a/esphome/components/water_heater/water_heater.h +++ b/esphome/components/water_heater/water_heater.h @@ -90,9 +90,22 @@ class WaterHeaterCall { float get_target_temperature_low() const { return this->target_temperature_low_; } float get_target_temperature_high() const { return this->target_temperature_high_; } /// Get state flags value + ESPDEPRECATED("get_state() is deprecated, use get_away() and get_on() instead. (Removed in 2026.8.0)", "2026.2.0") uint32_t get_state() const { return this->state_; } - /// Get mask of state flags that are being changed - uint32_t get_state_mask() const { return this->state_mask_; } + + optional<bool> get_away() const { + if (this->state_mask_ & WATER_HEATER_STATE_AWAY) { + return (this->state_ & WATER_HEATER_STATE_AWAY) != 0; + } + return {}; + } + + optional<bool> get_on() const { + if (this->state_mask_ & WATER_HEATER_STATE_ON) { + return (this->state_ & WATER_HEATER_STATE_ON) != 0; + } + return {}; + } protected: void validate_(); From b2b9e0cb0ae69b9d9415790e637172996a2cb2ef Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Mon, 9 Feb 2026 22:00:08 +0100 Subject: [PATCH 0608/2030] [nrf52,zigee] print reporting status (#13890) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/zigbee/zigbee_zephyr.cpp | 29 +++++++++++++++++++++ esphome/components/zigbee/zigbee_zephyr.h | 1 + 2 files changed, 30 insertions(+) diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index 4763943e88..65639de61b 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -3,6 +3,7 @@ #include "esphome/core/log.h" #include <zephyr/settings/settings.h> #include <zephyr/storage/flash_map.h> +#include "esphome/core/hal.h" extern "C" { #include <zboss_api.h> @@ -223,6 +224,7 @@ void ZigbeeComponent::dump_config() { get_wipe_on_boot(), YESNO(zb_zdo_joined()), zb_get_current_channel(), zb_get_current_page(), zb_get_sleep_threshold(), role(), ieee_addr_buf, zb_get_short_address(), extended_pan_id_buf, zb_get_pan_id()); + dump_reporting_(); } static void send_attribute_report(zb_bufid_t bufid, zb_uint16_t cmd_id) { @@ -244,6 +246,33 @@ void ZigbeeComponent::factory_reset() { ZB_SCHEDULE_APP_CALLBACK(zb_bdb_reset_via_local_action, 0); } +void ZigbeeComponent::dump_reporting_() { +#ifdef ESPHOME_LOG_HAS_VERBOSE + auto now = millis(); + bool first = true; + for (zb_uint8_t j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) { + if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) { + zb_zcl_reporting_info_t *rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; + for (zb_uint8_t i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) { + if (!first) { + ESP_LOGV(TAG, ""); + } + first = false; + ESP_LOGV(TAG, "Endpoint: %d, cluster_id %d, attr_id %d, flags %d, report in %ums", rep_info->ep, + rep_info->cluster_id, rep_info->attr_id, rep_info->flags, + ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED) + ? ZB_TIME_BEACON_INTERVAL_TO_MSEC(rep_info->run_time) - now + : 0); + ESP_LOGV(TAG, "Min_interval %ds, max_interval %ds, def_min_interval %ds, def_max_interval %ds", + rep_info->u.send_info.min_interval, rep_info->u.send_info.max_interval, + rep_info->u.send_info.def_min_interval, rep_info->u.send_info.def_max_interval); + rep_info++; + } + } + } +#endif +} + } // namespace esphome::zigbee extern "C" void zboss_signal_handler(zb_uint8_t param) { diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index 05895e8e61..bd4b092ad5 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -87,6 +87,7 @@ class ZigbeeComponent : public Component { #ifdef USE_ZIGBEE_WIPE_ON_BOOT void erase_flash_(int area); #endif + void dump_reporting_(); std::array<std::function<void(zb_bufid_t bufid)>, ZIGBEE_ENDPOINTS_COUNT> callbacks_{}; CallbackManager<void()> join_cb_; Trigger<> join_trigger_; From 8f74b027b48e102f96551a6a6b8d0857ce72fc44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:40:32 -0600 Subject: [PATCH 0609/2030] Bump setuptools from 80.10.2 to 82.0.0 (#13897) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1bd43ea2f1..339bc65eed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools==80.10.2", "wheel>=0.43,<0.47"] +requires = ["setuptools==82.0.0", "wheel>=0.43,<0.47"] build-backend = "setuptools.build_meta" [project] From 475db750e08ebc6c76f4a05695f66c49bca3efce Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:41:16 -0500 Subject: [PATCH 0610/2030] [uart] Change available() return type from int to size_t (#13893) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bl0942/bl0942.cpp | 6 +++--- esphome/components/tormatic/tormatic_cover.cpp | 2 +- esphome/components/uart/uart.h | 2 +- esphome/components/uart/uart_component.cpp | 6 +++--- esphome/components/uart/uart_component.h | 2 +- .../components/uart/uart_component_esp8266.cpp | 15 +++++++++------ esphome/components/uart/uart_component_esp8266.h | 4 ++-- .../components/uart/uart_component_esp_idf.cpp | 2 +- esphome/components/uart/uart_component_esp_idf.h | 2 +- esphome/components/uart/uart_component_host.cpp | 7 ++++--- esphome/components/uart/uart_component_host.h | 2 +- .../components/uart/uart_component_libretiny.cpp | 2 +- .../components/uart/uart_component_libretiny.h | 2 +- esphome/components/uart/uart_component_rp2040.cpp | 2 +- esphome/components/uart/uart_component_rp2040.h | 2 +- esphome/components/usb_cdc_acm/usb_cdc_acm.h | 2 +- .../components/usb_cdc_acm/usb_cdc_acm_esp32.cpp | 4 ++-- esphome/components/usb_uart/usb_uart.h | 2 +- esphome/components/weikai/weikai.cpp | 2 +- esphome/components/weikai/weikai.h | 2 +- tests/components/uart/common.h | 2 +- 21 files changed, 38 insertions(+), 34 deletions(-) diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index 95dd689b07..b408c5549c 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -46,16 +46,16 @@ static const uint32_t PKT_TIMEOUT_MS = 200; void BL0942::loop() { DataPacket buffer; - int avail = this->available(); + size_t avail = this->available(); if (!avail) { return; } - if (static_cast<size_t>(avail) < sizeof(buffer)) { + if (avail < sizeof(buffer)) { if (!this->rx_start_) { this->rx_start_ = millis(); } else if (millis() > this->rx_start_ + PKT_TIMEOUT_MS) { - ESP_LOGW(TAG, "Junk on wire. Throwing away partial message (%d bytes)", avail); + ESP_LOGW(TAG, "Junk on wire. Throwing away partial message (%zu bytes)", avail); this->read_array((uint8_t *) &buffer, avail); this->rx_start_ = 0; } diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index ef93964a28..be412d62a8 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -251,7 +251,7 @@ void Tormatic::stop_at_target_() { // Read a GateStatus from the unit. The unit only sends messages in response to // status requests or commands, so a message needs to be sent first. optional<GateStatus> Tormatic::read_gate_status_() { - if (this->available() < static_cast<int>(sizeof(MessageHeader))) { + if (this->available() < sizeof(MessageHeader)) { return {}; } diff --git a/esphome/components/uart/uart.h b/esphome/components/uart/uart.h index 72c282f1c4..bb91e5cd7c 100644 --- a/esphome/components/uart/uart.h +++ b/esphome/components/uart/uart.h @@ -43,7 +43,7 @@ class UARTDevice { return res; } - int available() { return this->parent_->available(); } + size_t available() { return this->parent_->available(); } void flush() { this->parent_->flush(); } diff --git a/esphome/components/uart/uart_component.cpp b/esphome/components/uart/uart_component.cpp index 30fc208fc9..762e56c399 100644 --- a/esphome/components/uart/uart_component.cpp +++ b/esphome/components/uart/uart_component.cpp @@ -5,13 +5,13 @@ namespace esphome::uart { static const char *const TAG = "uart"; bool UARTComponent::check_read_timeout_(size_t len) { - if (this->available() >= int(len)) + if (this->available() >= len) return true; uint32_t start_time = millis(); - while (this->available() < int(len)) { + while (this->available() < len) { if (millis() - start_time > 100) { - ESP_LOGE(TAG, "Reading from UART timed out at byte %u!", this->available()); + ESP_LOGE(TAG, "Reading from UART timed out at byte %zu!", this->available()); return false; } yield(); diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index ea6e1562f4..b6ffbbd51f 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -69,7 +69,7 @@ class UARTComponent { // Pure virtual method to return the number of bytes available for reading. // @return Number of available bytes. - virtual int available() = 0; + virtual size_t available() = 0; // Pure virtual method to block until all bytes have been written to the UART bus. virtual void flush() = 0; diff --git a/esphome/components/uart/uart_component_esp8266.cpp b/esphome/components/uart/uart_component_esp8266.cpp index 504d494e2e..3ebf381c84 100644 --- a/esphome/components/uart/uart_component_esp8266.cpp +++ b/esphome/components/uart/uart_component_esp8266.cpp @@ -206,7 +206,7 @@ bool ESP8266UartComponent::read_array(uint8_t *data, size_t len) { #endif return true; } -int ESP8266UartComponent::available() { +size_t ESP8266UartComponent::available() { if (this->hw_serial_ != nullptr) { return this->hw_serial_->available(); } else { @@ -329,11 +329,14 @@ uint8_t ESP8266SoftwareSerial::peek_byte() { void ESP8266SoftwareSerial::flush() { // Flush is a NO-OP with software serial, all bytes are written immediately. } -int ESP8266SoftwareSerial::available() { - int avail = int(this->rx_in_pos_) - int(this->rx_out_pos_); - if (avail < 0) - return avail + this->rx_buffer_size_; - return avail; +size_t ESP8266SoftwareSerial::available() { + // Read volatile rx_in_pos_ once to avoid TOCTOU race with ISR. + // When in >= out, data is contiguous: [out..in). + // When in < out, data wraps: [out..buf_size) + [0..in). + size_t in = this->rx_in_pos_; + if (in >= this->rx_out_pos_) + return in - this->rx_out_pos_; + return this->rx_buffer_size_ - this->rx_out_pos_ + in; } } // namespace esphome::uart diff --git a/esphome/components/uart/uart_component_esp8266.h b/esphome/components/uart/uart_component_esp8266.h index e33dd00644..e84cbe386d 100644 --- a/esphome/components/uart/uart_component_esp8266.h +++ b/esphome/components/uart/uart_component_esp8266.h @@ -23,7 +23,7 @@ class ESP8266SoftwareSerial { void write_byte(uint8_t data); - int available(); + size_t available(); protected: static void gpio_intr(ESP8266SoftwareSerial *arg); @@ -57,7 +57,7 @@ class ESP8266UartComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; uint32_t get_config(); diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 90997787aa..19b9a4077f 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -338,7 +338,7 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { return read_len == (int32_t) length_to_read; } -int IDFUARTComponent::available() { +size_t IDFUARTComponent::available() { size_t available = 0; esp_err_t err; diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index bd6d0c792e..1ecb02d7ab 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -22,7 +22,7 @@ class IDFUARTComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; uint8_t get_hw_serial_number() { return this->uart_num_; } diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 69b24607d1..0e5ef3c6bd 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -265,7 +265,7 @@ bool HostUartComponent::read_array(uint8_t *data, size_t len) { return true; } -int HostUartComponent::available() { +size_t HostUartComponent::available() { if (this->file_descriptor_ == -1) { return 0; } @@ -275,9 +275,10 @@ int HostUartComponent::available() { this->update_error_(strerror(errno)); return 0; } + size_t result = available; if (this->has_peek_) - available++; - return available; + result++; + return result; }; void HostUartComponent::flush() { diff --git a/esphome/components/uart/uart_component_host.h b/esphome/components/uart/uart_component_host.h index a4a6946c0c..89b951093b 100644 --- a/esphome/components/uart/uart_component_host.h +++ b/esphome/components/uart/uart_component_host.h @@ -17,7 +17,7 @@ class HostUartComponent : public UARTComponent, public Component { void write_array(const uint8_t *data, size_t len) override; bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; void set_name(std::string port_name) { port_name_ = port_name; }; diff --git a/esphome/components/uart/uart_component_libretiny.cpp b/esphome/components/uart/uart_component_libretiny.cpp index 863732c88d..cb4465068d 100644 --- a/esphome/components/uart/uart_component_libretiny.cpp +++ b/esphome/components/uart/uart_component_libretiny.cpp @@ -169,7 +169,7 @@ bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) { return true; } -int LibreTinyUARTComponent::available() { return this->serial_->available(); } +size_t LibreTinyUARTComponent::available() { return this->serial_->available(); } void LibreTinyUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); diff --git a/esphome/components/uart/uart_component_libretiny.h b/esphome/components/uart/uart_component_libretiny.h index ec13e7da5a..31f082d31e 100644 --- a/esphome/components/uart/uart_component_libretiny.h +++ b/esphome/components/uart/uart_component_libretiny.h @@ -21,7 +21,7 @@ class LibreTinyUARTComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; uint16_t get_config(); diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 5799d26a54..0c6834055c 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -186,7 +186,7 @@ bool RP2040UartComponent::read_array(uint8_t *data, size_t len) { #endif return true; } -int RP2040UartComponent::available() { return this->serial_->available(); } +size_t RP2040UartComponent::available() { return this->serial_->available(); } void RP2040UartComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); diff --git a/esphome/components/uart/uart_component_rp2040.h b/esphome/components/uart/uart_component_rp2040.h index d626d11a2e..4ca58e8dc6 100644 --- a/esphome/components/uart/uart_component_rp2040.h +++ b/esphome/components/uart/uart_component_rp2040.h @@ -24,7 +24,7 @@ class RP2040UartComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; uint16_t get_config(); diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index 065d7282d5..ddcc65232d 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -81,7 +81,7 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC void write_array(const uint8_t *data, size_t len) override; bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; - int available() override; + size_t available() override; void flush() override; protected: diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index 224d6e3ab1..d33fb80f78 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -318,12 +318,12 @@ bool USBCDCACMInstance::read_array(uint8_t *data, size_t len) { return bytes_read == original_len; } -int USBCDCACMInstance::available() { +size_t USBCDCACMInstance::available() { UBaseType_t waiting = 0; if (this->usb_rx_ringbuf_ != nullptr) { vRingbufferGetInfo(this->usb_rx_ringbuf_, nullptr, nullptr, nullptr, nullptr, &waiting); } - return static_cast<int>(waiting) + (this->has_peek_ ? 1 : 0); + return waiting + (this->has_peek_ ? 1 : 0); } void USBCDCACMInstance::flush() { diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 96c17bd155..94e6120457 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -97,7 +97,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon bool peek_byte(uint8_t *data) override; ; bool read_array(uint8_t *data, size_t len) override; - int available() override { return static_cast<int>(this->input_buffer_.get_available()); } + size_t available() override { return this->input_buffer_.get_available(); } void flush() override {} void check_logger_conflict() override {} void set_parity(UARTParityOptions parity) { this->parity_ = parity; } diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index d0a8f8366b..1d835daf1e 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -401,7 +401,7 @@ bool WeikaiChannel::peek_byte(uint8_t *buffer) { return this->receive_buffer_.peek(*buffer); } -int WeikaiChannel::available() { +size_t WeikaiChannel::available() { size_t available = this->receive_buffer_.count(); if (!available) available = xfer_fifo_to_buffer_(); diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h index 4440d9414e..43c3a1e4f4 100644 --- a/esphome/components/weikai/weikai.h +++ b/esphome/components/weikai/weikai.h @@ -374,7 +374,7 @@ class WeikaiChannel : public uart::UARTComponent { /// @brief Returns the number of bytes in the receive buffer /// @return the number of bytes available in the receiver fifo - int available() override; + size_t available() override; /// @brief Flush the output fifo. /// @details If we refer to Serial.flush() in Arduino it says: ** Waits for the transmission of outgoing serial data diff --git a/tests/components/uart/common.h b/tests/components/uart/common.h index 5597b86410..1f9bfa15e7 100644 --- a/tests/components/uart/common.h +++ b/tests/components/uart/common.h @@ -29,7 +29,7 @@ class MockUARTComponent : public UARTComponent { MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); - MOCK_METHOD(int, available, (), (override)); + MOCK_METHOD(size_t, available, (), (override)); MOCK_METHOD(void, flush, (), (override)); MOCK_METHOD(void, check_logger_conflict, (), (override)); }; From 7c1327f96ae904641800650deb4c95348fc23fd4 Mon Sep 17 00:00:00 2001 From: George Joseph <gtjoseph@users.noreply.github.com> Date: Mon, 9 Feb 2026 15:44:47 -0700 Subject: [PATCH 0611/2030] [mipi_dsi] Add WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD 3.4C and 4C (#13840) --- .../components/mipi_dsi/models/waveshare.py | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/esphome/components/mipi_dsi/models/waveshare.py b/esphome/components/mipi_dsi/models/waveshare.py index f83cacc5a3..bf4f9063bb 100644 --- a/esphome/components/mipi_dsi/models/waveshare.py +++ b/esphome/components/mipi_dsi/models/waveshare.py @@ -120,3 +120,101 @@ DriverChip( (0xB2, 0x10), ], ) + +DriverChip( + "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-3.4C", + height=800, + width=800, + hsync_back_porch=20, + hsync_pulse_width=20, + hsync_front_porch=40, + vsync_back_porch=12, + vsync_pulse_width=4, + vsync_front_porch=24, + pclk_frequency="80MHz", + lane_bit_rate="1.5Gbps", + swap_xy=cv.UNDEFINED, + color_order="RGB", + initsequence=[ + (0xE0, 0x00), # select userpage + (0xE1, 0x93), (0xE2, 0x65), (0xE3, 0xF8), + (0x80, 0x01), # Select number of lanes (2) + (0xE0, 0x01), # select page 1 + (0x00, 0x00), (0x01, 0x41), (0x03, 0x10), (0x04, 0x44), (0x17, 0x00), (0x18, 0xD0), (0x19, 0x00), (0x1A, 0x00), + (0x1B, 0xD0), (0x1C, 0x00), (0x24, 0xFE), (0x35, 0x26), (0x37, 0x09), (0x38, 0x04), (0x39, 0x08), (0x3A, 0x0A), + (0x3C, 0x78), (0x3D, 0xFF), (0x3E, 0xFF), (0x3F, 0xFF), (0x40, 0x00), (0x41, 0x64), (0x42, 0xC7), (0x43, 0x18), + (0x44, 0x0B), (0x45, 0x14), (0x55, 0x02), (0x57, 0x49), (0x59, 0x0A), (0x5A, 0x1B), (0x5B, 0x19), (0x5D, 0x7F), + (0x5E, 0x56), (0x5F, 0x43), (0x60, 0x37), (0x61, 0x33), (0x62, 0x25), (0x63, 0x2A), (0x64, 0x16), (0x65, 0x30), + (0x66, 0x2F), (0x67, 0x32), (0x68, 0x53), (0x69, 0x43), (0x6A, 0x4C), (0x6B, 0x40), (0x6C, 0x3D), (0x6D, 0x31), + (0x6E, 0x20), (0x6F, 0x0F), (0x70, 0x7F), (0x71, 0x56), (0x72, 0x43), (0x73, 0x37), (0x74, 0x33), (0x75, 0x25), + (0x76, 0x2A), (0x77, 0x16), (0x78, 0x30), (0x79, 0x2F), (0x7A, 0x32), (0x7B, 0x53), (0x7C, 0x43), (0x7D, 0x4C), + (0x7E, 0x40), (0x7F, 0x3D), (0x80, 0x31), (0x81, 0x20), (0x82, 0x0F), + (0xE0, 0x02), # select page 2 + (0x00, 0x5F), (0x01, 0x5F), (0x02, 0x5E), (0x03, 0x5E), (0x04, 0x50), (0x05, 0x48), (0x06, 0x48), (0x07, 0x4A), + (0x08, 0x4A), (0x09, 0x44), (0x0A, 0x44), (0x0B, 0x46), (0x0C, 0x46), (0x0D, 0x5F), (0x0E, 0x5F), (0x0F, 0x57), + (0x10, 0x57), (0x11, 0x77), (0x12, 0x77), (0x13, 0x40), (0x14, 0x42), (0x15, 0x5F), (0x16, 0x5F), (0x17, 0x5F), + (0x18, 0x5E), (0x19, 0x5E), (0x1A, 0x50), (0x1B, 0x49), (0x1C, 0x49), (0x1D, 0x4B), (0x1E, 0x4B), (0x1F, 0x45), + (0x20, 0x45), (0x21, 0x47), (0x22, 0x47), (0x23, 0x5F), (0x24, 0x5F), (0x25, 0x57), (0x26, 0x57), (0x27, 0x77), + (0x28, 0x77), (0x29, 0x41), (0x2A, 0x43), (0x2B, 0x5F), (0x2C, 0x1E), (0x2D, 0x1E), (0x2E, 0x1F), (0x2F, 0x1F), + (0x30, 0x10), (0x31, 0x07), (0x32, 0x07), (0x33, 0x05), (0x34, 0x05), (0x35, 0x0B), (0x36, 0x0B), (0x37, 0x09), + (0x38, 0x09), (0x39, 0x1F), (0x3A, 0x1F), (0x3B, 0x17), (0x3C, 0x17), (0x3D, 0x17), (0x3E, 0x17), (0x3F, 0x03), + (0x40, 0x01), (0x41, 0x1F), (0x42, 0x1E), (0x43, 0x1E), (0x44, 0x1F), (0x45, 0x1F), (0x46, 0x10), (0x47, 0x06), + (0x48, 0x06), (0x49, 0x04), (0x4A, 0x04), (0x4B, 0x0A), (0x4C, 0x0A), (0x4D, 0x08), (0x4E, 0x08), (0x4F, 0x1F), + (0x50, 0x1F), (0x51, 0x17), (0x52, 0x17), (0x53, 0x17), (0x54, 0x17), (0x55, 0x02), (0x56, 0x00), (0x57, 0x1F), + (0xE0, 0x02), # select page 2 + (0x58, 0x40), (0x59, 0x00), (0x5A, 0x00), (0x5B, 0x30), (0x5C, 0x01), (0x5D, 0x30), (0x5E, 0x01), (0x5F, 0x02), + (0x60, 0x30), (0x61, 0x03), (0x62, 0x04), (0x63, 0x04), (0x64, 0xA6), (0x65, 0x43), (0x66, 0x30), (0x67, 0x73), + (0x68, 0x05), (0x69, 0x04), (0x6A, 0x7F), (0x6B, 0x08), (0x6C, 0x00), (0x6D, 0x04), (0x6E, 0x04), (0x6F, 0x88), + (0x75, 0xD9), (0x76, 0x00), (0x77, 0x33), (0x78, 0x43), + (0xE0, 0x00), # select userpage + ], +) + +DriverChip( + "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-4C", + height=720, + width=720, + hsync_back_porch=20, + hsync_pulse_width=20, + hsync_front_porch=40, + vsync_back_porch=12, + vsync_pulse_width=4, + vsync_front_porch=24, + pclk_frequency="80MHz", + lane_bit_rate="1.5Gbps", + swap_xy=cv.UNDEFINED, + color_order="RGB", + initsequence=[ + (0xE0, 0x00), # select userpage + (0xE1, 0x93), (0xE2, 0x65), (0xE3, 0xF8), + (0x80, 0x01), # Select number of lanes (2) + (0xE0, 0x01), # select page 1 + (0x00, 0x00), (0x01, 0x41), (0x03, 0x10), (0x04, 0x44), (0x17, 0x00), (0x18, 0xD0), (0x19, 0x00), (0x1A, 0x00), + (0x1B, 0xD0), (0x1C, 0x00), (0x24, 0xFE), (0x35, 0x26), (0x37, 0x09), (0x38, 0x04), (0x39, 0x08), (0x3A, 0x0A), + (0x3C, 0x78), (0x3D, 0xFF), (0x3E, 0xFF), (0x3F, 0xFF), (0x40, 0x04), (0x41, 0x64), (0x42, 0xC7), (0x43, 0x18), + (0x44, 0x0B), (0x45, 0x14), (0x55, 0x02), (0x57, 0x49), (0x59, 0x0A), (0x5A, 0x1B), (0x5B, 0x19), (0x5D, 0x7F), + (0x5E, 0x56), (0x5F, 0x43), (0x60, 0x37), (0x61, 0x33), (0x62, 0x25), (0x63, 0x2A), (0x64, 0x16), (0x65, 0x30), + (0x66, 0x2F), (0x67, 0x32), (0x68, 0x53), (0x69, 0x43), (0x6A, 0x4C), (0x6B, 0x40), (0x6C, 0x3D), (0x6D, 0x31), + (0x6E, 0x20), (0x6F, 0x0F), (0x70, 0x7F), (0x71, 0x56), (0x72, 0x43), (0x73, 0x37), (0x74, 0x33), (0x75, 0x25), + (0x76, 0x2A), (0x77, 0x16), (0x78, 0x30), (0x79, 0x2F), (0x7A, 0x32), (0x7B, 0x53), (0x7C, 0x43), (0x7D, 0x4C), + (0x7E, 0x40), (0x7F, 0x3D), (0x80, 0x31), (0x81, 0x20), (0x82, 0x0F), + (0xE0, 0x02), # select page 2 + (0x00, 0x5F), (0x01, 0x5F), (0x02, 0x5E), (0x03, 0x5E), (0x04, 0x50), (0x05, 0x48), (0x06, 0x48), (0x07, 0x4A), + (0x08, 0x4A), (0x09, 0x44), (0x0A, 0x44), (0x0B, 0x46), (0x0C, 0x46), (0x0D, 0x5F), (0x0E, 0x5F), (0x0F, 0x57), + (0x10, 0x57), (0x11, 0x77), (0x12, 0x77), (0x13, 0x40), (0x14, 0x42), (0x15, 0x5F), (0x16, 0x5F), (0x17, 0x5F), + (0x18, 0x5E), (0x19, 0x5E), (0x1A, 0x50), (0x1B, 0x49), (0x1C, 0x49), (0x1D, 0x4B), (0x1E, 0x4B), (0x1F, 0x45), + (0x20, 0x45), (0x21, 0x47), (0x22, 0x47), (0x23, 0x5F), (0x24, 0x5F), (0x25, 0x57), (0x26, 0x57), (0x27, 0x77), + (0x28, 0x77), (0x29, 0x41), (0x2A, 0x43), (0x2B, 0x5F), (0x2C, 0x1E), (0x2D, 0x1E), (0x2E, 0x1F), (0x2F, 0x1F), + (0x30, 0x10), (0x31, 0x07), (0x32, 0x07), (0x33, 0x05), (0x34, 0x05), (0x35, 0x0B), (0x36, 0x0B), (0x37, 0x09), + (0x38, 0x09), (0x39, 0x1F), (0x3A, 0x1F), (0x3B, 0x17), (0x3C, 0x17), (0x3D, 0x17), (0x3E, 0x17), (0x3F, 0x03), + (0x40, 0x01), (0x41, 0x1F), (0x42, 0x1E), (0x43, 0x1E), (0x44, 0x1F), (0x45, 0x1F), (0x46, 0x10), (0x47, 0x06), + (0x48, 0x06), (0x49, 0x04), (0x4A, 0x04), (0x4B, 0x0A), (0x4C, 0x0A), (0x4D, 0x08), (0x4E, 0x08), (0x4F, 0x1F), + (0x50, 0x1F), (0x51, 0x17), (0x52, 0x17), (0x53, 0x17), (0x54, 0x17), (0x55, 0x02), (0x56, 0x00), (0x57, 0x1F), + (0xE0, 0x02), # select page 2 + (0x58, 0x40), (0x59, 0x00), (0x5A, 0x00), (0x5B, 0x30), (0x5C, 0x01), (0x5D, 0x30), (0x5E, 0x01), (0x5F, 0x02), + (0x60, 0x30), (0x61, 0x03), (0x62, 0x04), (0x63, 0x04), (0x64, 0xA6), (0x65, 0x43), (0x66, 0x30), (0x67, 0x73), + (0x68, 0x05), (0x69, 0x04), (0x6A, 0x7F), (0x6B, 0x08), (0x6C, 0x00), (0x6D, 0x04), (0x6E, 0x04), (0x6F, 0x88), + (0x75, 0xD9), (0x76, 0x00), (0x77, 0x33), (0x78, 0x43), + (0xE0, 0x00), # select userpage + ] +) From 3767c5ec91c7ab483a8a68982b82cdd028cc5546 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 16:48:08 -0600 Subject: [PATCH 0612/2030] [scheduler] Make core timer ID collisions impossible with type-safe internal IDs (#13882) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> From dacc557a16232b4e51e47609fa94ce7f66808c70 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:15:48 -0600 Subject: [PATCH 0613/2030] [uart] Convert parity_to_str to PROGMEM_STRING_TABLE (#13805) --- esphome/components/uart/uart.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/esphome/components/uart/uart.cpp b/esphome/components/uart/uart.cpp index 6cfd6537a5..337fa352c1 100644 --- a/esphome/components/uart/uart.cpp +++ b/esphome/components/uart/uart.cpp @@ -3,12 +3,16 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include <cinttypes> namespace esphome::uart { static const char *const TAG = "uart"; +// UART parity strings indexed by UARTParityOptions enum (0-2): NONE, EVEN, ODD +PROGMEM_STRING_TABLE(UARTParityStrings, "NONE", "EVEN", "ODD", "UNKNOWN"); + void UARTDevice::check_uart_settings(uint32_t baud_rate, uint8_t stop_bits, UARTParityOptions parity, uint8_t data_bits) { if (this->parent_->get_baud_rate() != baud_rate) { @@ -30,16 +34,7 @@ void UARTDevice::check_uart_settings(uint32_t baud_rate, uint8_t stop_bits, UART } const LogString *parity_to_str(UARTParityOptions parity) { - switch (parity) { - case UART_CONFIG_PARITY_NONE: - return LOG_STR("NONE"); - case UART_CONFIG_PARITY_EVEN: - return LOG_STR("EVEN"); - case UART_CONFIG_PARITY_ODD: - return LOG_STR("ODD"); - default: - return LOG_STR("UNKNOWN"); - } + return UARTParityStrings::get_log_str(static_cast<uint8_t>(parity), UARTParityStrings::LAST_INDEX); } } // namespace esphome::uart From 78df8be31fd061cba7a09179db45977aba08e6e5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:16:27 -0600 Subject: [PATCH 0614/2030] [logger] Resolve thread name once and pass through logging chain (#13836) --- esphome/components/logger/logger.cpp | 43 ++++--- esphome/components/logger/logger.h | 114 +++++++++--------- .../logger/task_log_buffer_esp32.cpp | 3 +- .../components/logger/task_log_buffer_esp32.h | 2 +- .../logger/task_log_buffer_host.cpp | 12 +- .../components/logger/task_log_buffer_host.h | 3 +- .../logger/task_log_buffer_libretiny.cpp | 3 +- .../logger/task_log_buffer_libretiny.h | 2 +- 8 files changed, 93 insertions(+), 89 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 4cbd4f1bf1..bb20c403e5 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -36,8 +36,9 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch #endif // Fast path: main thread, no recursion (99.9% of all logs) + // Pass nullptr for thread_name since we already know this is the main task if (is_main_task && !this->main_task_recursion_guard_) [[likely]] { - this->log_message_to_buffer_and_send_(this->main_task_recursion_guard_, level, tag, line, format, args); + this->log_message_to_buffer_and_send_(this->main_task_recursion_guard_, level, tag, line, format, args, nullptr); return; } @@ -47,21 +48,23 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch } // Non-main thread handling (~0.1% of logs) + // Resolve thread name once and pass it through the logging chain. + // ESP32/LibreTiny: use TaskHandle_t overload to avoid redundant xTaskGetCurrentTaskHandle() + // (we already have the handle from the main task check above). + // Host: pass a stack buffer for pthread_getname_np to write into. #if defined(USE_ESP32) || defined(USE_LIBRETINY) - this->log_vprintf_non_main_thread_(level, tag, line, format, args, current_task); + const char *thread_name = get_thread_name_(current_task); #else // USE_HOST - this->log_vprintf_non_main_thread_(level, tag, line, format, args); + char thread_name_buf[THREAD_NAME_BUF_SIZE]; + const char *thread_name = this->get_thread_name_(thread_name_buf); #endif + this->log_vprintf_non_main_thread_(level, tag, line, format, args, thread_name); } // Handles non-main thread logging only // Kept separate from hot path to improve instruction cache performance -#if defined(USE_ESP32) || defined(USE_LIBRETINY) void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, - TaskHandle_t current_task) { -#else // USE_HOST -void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args) { -#endif + const char *thread_name) { // Check if already in recursion for this non-main thread/task if (this->is_non_main_task_recursive_()) { return; @@ -73,12 +76,8 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li bool message_sent = false; #ifdef USE_ESPHOME_TASK_LOG_BUFFER // For non-main threads/tasks, queue the message for callbacks -#if defined(USE_ESP32) || defined(USE_LIBRETINY) message_sent = - this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), current_task, format, args); -#else // USE_HOST - message_sent = this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), format, args); -#endif + this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), thread_name, format, args); if (message_sent) { // Enable logger loop to process the buffered message // This is safe to call from any context including ISRs @@ -101,19 +100,27 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li #endif char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE]; // MUST be stack allocated for thread safety LogBuffer buf{console_buffer, MAX_CONSOLE_LOG_MSG_SIZE}; - this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf); + this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf, thread_name); this->write_to_console_(buf); } // RAII guard automatically resets on return } #else -// Implementation for all other platforms (single-task, no threading) +// Implementation for single-task platforms (ESP8266, RP2040, Zephyr) +// TODO: Zephyr may have multiple threads (work queues, etc.) but uses this single-task path. +// Logging calls are NOT thread-safe: global_recursion_guard_ is a plain bool and tx_buffer_ has no locking. +// Not a problem in practice yet since Zephyr has no API support (logs are console-only). void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT if (level > this->level_for(tag) || global_recursion_guard_) return; - - this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args); +#ifdef USE_ZEPHYR + char tmp[MAX_POINTER_REPRESENTATION]; + this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args, + this->get_thread_name_(tmp)); +#else // Other single-task platforms don't have thread names, so pass nullptr + this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args, nullptr); +#endif } #endif // USE_ESP32 / USE_HOST / USE_LIBRETINY @@ -129,7 +136,7 @@ void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __Flas if (level > this->level_for(tag) || global_recursion_guard_) return; - this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args); + this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args, nullptr); } #endif // USE_STORE_LOG_STR_IN_FLASH diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 1678fed5f5..ecf032ee0e 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -2,6 +2,7 @@ #include <cstdarg> #include <map> +#include <span> #include <type_traits> #if defined(USE_ESP32) || defined(USE_HOST) #include <pthread.h> @@ -124,6 +125,10 @@ static constexpr uint16_t MAX_HEADER_SIZE = 128; // "0x" + 2 hex digits per byte + '\0' static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1; +// Stack buffer size for retrieving thread/task names from the OS +// macOS allows up to 64 bytes, Linux up to 16 +static constexpr size_t THREAD_NAME_BUF_SIZE = 64; + // Buffer wrapper for log formatting functions struct LogBuffer { char *data; @@ -408,34 +413,24 @@ class Logger : public Component { #if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) // Handles non-main thread logging only (~0.1% of calls) -#if defined(USE_ESP32) || defined(USE_LIBRETINY) - // ESP32/LibreTiny: Pass task handle to avoid calling xTaskGetCurrentTaskHandle() twice + // thread_name is resolved by the caller from the task handle, avoiding redundant lookups void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, - TaskHandle_t current_task); -#else // USE_HOST - // Host: No task handle parameter needed (not used in send_message_thread_safe) - void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args); -#endif + const char *thread_name); #endif void process_messages_(); void write_msg_(const char *msg, uint16_t len); // Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator + // thread_name: name of the calling thread/task, or nullptr for main task (callers already know which task they're on) inline void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format, - va_list args, LogBuffer &buf) { -#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_HOST) - buf.write_header(level, tag, line, this->get_thread_name_()); -#elif defined(USE_ZEPHYR) - char tmp[MAX_POINTER_REPRESENTATION]; - buf.write_header(level, tag, line, this->get_thread_name_(tmp)); -#else - buf.write_header(level, tag, line, nullptr); -#endif + va_list args, LogBuffer &buf, const char *thread_name) { + buf.write_header(level, tag, line, thread_name); buf.format_body(format, args); } #ifdef USE_STORE_LOG_STR_IN_FLASH // Format a log message with flash string format and write it to a buffer with header, footer, and null terminator + // ESP8266-only (single-task), thread_name is always nullptr inline void HOT format_log_to_buffer_with_terminator_P_(uint8_t level, const char *tag, int line, const __FlashStringHelper *format, va_list args, LogBuffer &buf) { @@ -466,9 +461,10 @@ class Logger : public Component { // Helper to format and send a log message to both console and listeners // Template handles both const char* (RAM) and __FlashStringHelper* (flash) format strings + // thread_name: name of the calling thread/task, or nullptr for main task template<typename FormatType> inline void HOT log_message_to_buffer_and_send_(bool &recursion_guard, uint8_t level, const char *tag, int line, - FormatType format, va_list args) { + FormatType format, va_list args, const char *thread_name) { RecursionGuard guard(recursion_guard); LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; #ifdef USE_STORE_LOG_STR_IN_FLASH @@ -477,7 +473,7 @@ class Logger : public Component { } else #endif { - this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf); + this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, buf, thread_name); } this->notify_listeners_(level, tag, buf); this->write_log_buffer_to_console_(buf); @@ -565,37 +561,57 @@ class Logger : public Component { bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms #endif -#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) - const char *HOT get_thread_name_( -#ifdef USE_ZEPHYR - char *buff + // --- get_thread_name_ overloads (per-platform) --- + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Primary overload - takes a task handle directly to avoid redundant xTaskGetCurrentTaskHandle() calls + // when the caller already has the handle (e.g. from the main task check in log_vprintf_) + const char *get_thread_name_(TaskHandle_t task) { + if (task == this->main_task_) { + return nullptr; // Main task + } +#if defined(USE_ESP32) + return pcTaskGetName(task); +#elif defined(USE_LIBRETINY) + return pcTaskGetTaskName(task); #endif - ) { -#ifdef USE_ZEPHYR + } + + // Convenience overload - gets the current task handle and delegates + const char *HOT get_thread_name_() { return this->get_thread_name_(xTaskGetCurrentTaskHandle()); } + +#elif defined(USE_HOST) + // Takes a caller-provided buffer for the thread name (stack-allocated for thread safety) + const char *HOT get_thread_name_(std::span<char> buff) { + pthread_t current_thread = pthread_self(); + if (pthread_equal(current_thread, main_thread_)) { + return nullptr; // Main thread + } + // For non-main threads, get the thread name into the caller-provided buffer + if (pthread_getname_np(current_thread, buff.data(), buff.size()) == 0) { + return buff.data(); + } + return nullptr; + } + +#elif defined(USE_ZEPHYR) + const char *HOT get_thread_name_(std::span<char> buff) { k_tid_t current_task = k_current_get(); -#else - TaskHandle_t current_task = xTaskGetCurrentTaskHandle(); -#endif if (current_task == main_task_) { return nullptr; // Main task - } else { -#if defined(USE_ESP32) - return pcTaskGetName(current_task); -#elif defined(USE_LIBRETINY) - return pcTaskGetTaskName(current_task); -#elif defined(USE_ZEPHYR) - const char *name = k_thread_name_get(current_task); - if (name) { - // zephyr print task names only if debug component is present - return name; - } - std::snprintf(buff, MAX_POINTER_REPRESENTATION, "%p", current_task); - return buff; -#endif } + const char *name = k_thread_name_get(current_task); + if (name) { + // zephyr print task names only if debug component is present + return name; + } + std::snprintf(buff.data(), buff.size(), "%p", current_task); + return buff.data(); } #endif + // --- Non-main task recursion guards (per-platform) --- + #if defined(USE_ESP32) || defined(USE_HOST) // RAII guard for non-main task recursion using pthread TLS class NonMainTaskRecursionGuard { @@ -635,22 +651,6 @@ class Logger : public Component { inline RecursionGuard make_non_main_task_guard_() { return RecursionGuard(non_main_task_recursion_guard_); } #endif -#ifdef USE_HOST - const char *HOT get_thread_name_() { - pthread_t current_thread = pthread_self(); - if (pthread_equal(current_thread, main_thread_)) { - return nullptr; // Main thread - } - // For non-main threads, return the thread name - // We store it in thread-local storage to avoid allocation - static thread_local char thread_name_buf[32]; - if (pthread_getname_np(current_thread, thread_name_buf, sizeof(thread_name_buf)) == 0) { - return thread_name_buf; - } - return nullptr; - } -#endif - #if defined(USE_ESP32) || defined(USE_LIBRETINY) // Disable loop when task buffer is empty (with USB CDC check on ESP32) inline void disable_loop_when_buffer_empty_() { diff --git a/esphome/components/logger/task_log_buffer_esp32.cpp b/esphome/components/logger/task_log_buffer_esp32.cpp index b9dfe45b7f..56c0a4ae2d 100644 --- a/esphome/components/logger/task_log_buffer_esp32.cpp +++ b/esphome/components/logger/task_log_buffer_esp32.cpp @@ -59,7 +59,7 @@ void TaskLogBuffer::release_message_main_loop(void *token) { last_processed_counter_ = message_counter_.load(std::memory_order_relaxed); } -bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, TaskHandle_t task_handle, +bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) { // First, calculate the exact length needed using a null buffer (no actual writing) va_list args_copy; @@ -95,7 +95,6 @@ bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uin // Store the thread name now instead of waiting until main loop processing // This avoids crashes if the task completes or is deleted between when this message // is enqueued and when it's processed by the main loop - const char *thread_name = pcTaskGetName(task_handle); if (thread_name != nullptr) { strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1); msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination diff --git a/esphome/components/logger/task_log_buffer_esp32.h b/esphome/components/logger/task_log_buffer_esp32.h index fde9bd60d5..6c1bafaeba 100644 --- a/esphome/components/logger/task_log_buffer_esp32.h +++ b/esphome/components/logger/task_log_buffer_esp32.h @@ -58,7 +58,7 @@ class TaskLogBuffer { void release_message_main_loop(void *token); // Thread-safe - send a message to the ring buffer from any thread - bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, TaskHandle_t task_handle, + bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args); // Check if there are messages ready to be processed using an atomic counter for performance diff --git a/esphome/components/logger/task_log_buffer_host.cpp b/esphome/components/logger/task_log_buffer_host.cpp index 0660aeb061..676686304a 100644 --- a/esphome/components/logger/task_log_buffer_host.cpp +++ b/esphome/components/logger/task_log_buffer_host.cpp @@ -70,8 +70,8 @@ void TaskLogBufferHost::commit_write_slot_(int slot_index) { } } -bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *format, - va_list args) { +bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args) { // Acquire a slot int slot_index = this->acquire_write_slot_(); if (slot_index < 0) { @@ -85,11 +85,9 @@ bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, msg.tag = tag; msg.line = line; - // Get thread name using pthread - char thread_name_buf[LogMessage::MAX_THREAD_NAME_SIZE]; - // pthread_getname_np works the same on Linux and macOS - if (pthread_getname_np(pthread_self(), thread_name_buf, sizeof(thread_name_buf)) == 0) { - strncpy(msg.thread_name, thread_name_buf, sizeof(msg.thread_name) - 1); + // Store the thread name now to avoid crashes if thread exits before processing + if (thread_name != nullptr) { + strncpy(msg.thread_name, thread_name, sizeof(msg.thread_name) - 1); msg.thread_name[sizeof(msg.thread_name) - 1] = '\0'; } else { msg.thread_name[0] = '\0'; diff --git a/esphome/components/logger/task_log_buffer_host.h b/esphome/components/logger/task_log_buffer_host.h index d421d50ec6..f8e4ee7bee 100644 --- a/esphome/components/logger/task_log_buffer_host.h +++ b/esphome/components/logger/task_log_buffer_host.h @@ -86,7 +86,8 @@ class TaskLogBufferHost { // Thread-safe - send a message to the buffer from any thread // Returns true if message was queued, false if buffer is full - bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *format, va_list args); + bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args); // Check if there are messages ready to be processed inline bool HOT has_messages() const { diff --git a/esphome/components/logger/task_log_buffer_libretiny.cpp b/esphome/components/logger/task_log_buffer_libretiny.cpp index 580066e621..5a22857dcb 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.cpp +++ b/esphome/components/logger/task_log_buffer_libretiny.cpp @@ -101,7 +101,7 @@ void TaskLogBufferLibreTiny::release_message_main_loop() { } bool TaskLogBufferLibreTiny::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, - TaskHandle_t task_handle, const char *format, va_list args) { + const char *thread_name, const char *format, va_list args) { // First, calculate the exact length needed using a null buffer (no actual writing) va_list args_copy; va_copy(args_copy, args); @@ -162,7 +162,6 @@ bool TaskLogBufferLibreTiny::send_message_thread_safe(uint8_t level, const char msg->line = line; // Store the thread name now to avoid crashes if task is deleted before processing - const char *thread_name = pcTaskGetTaskName(task_handle); if (thread_name != nullptr) { strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1); msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; diff --git a/esphome/components/logger/task_log_buffer_libretiny.h b/esphome/components/logger/task_log_buffer_libretiny.h index bf6b2d2fa4..bf315e828a 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.h +++ b/esphome/components/logger/task_log_buffer_libretiny.h @@ -70,7 +70,7 @@ class TaskLogBufferLibreTiny { void release_message_main_loop(); // Thread-safe - send a message to the buffer from any thread - bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, TaskHandle_t task_handle, + bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args); // Fast check using volatile counter - no lock needed From bcd4a9fc39a3a35e4ea58d28f2bfc9495e7790bd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:20:53 -0600 Subject: [PATCH 0615/2030] [pylontech] Batch UART reads to reduce loop overhead (#13824) --- esphome/components/pylontech/pylontech.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/esphome/components/pylontech/pylontech.cpp b/esphome/components/pylontech/pylontech.cpp index 1dc7caaf16..d724253256 100644 --- a/esphome/components/pylontech/pylontech.cpp +++ b/esphome/components/pylontech/pylontech.cpp @@ -56,17 +56,23 @@ void PylontechComponent::setup() { void PylontechComponent::update() { this->write_str("pwr\n"); } void PylontechComponent::loop() { - if (this->available() > 0) { + int avail = this->available(); + if (avail > 0) { // pylontech sends a lot of data very suddenly // we need to quickly put it all into our own buffer, otherwise the uart's buffer will overflow - uint8_t data; int recv = 0; - while (this->available() > 0) { - if (this->read_byte(&data)) { - buffer_[buffer_index_write_] += (char) data; - recv++; - if (buffer_[buffer_index_write_].back() == static_cast<char>(ASCII_LF) || - buffer_[buffer_index_write_].length() >= MAX_DATA_LENGTH_BYTES) { + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + recv += to_read; + + for (size_t i = 0; i < to_read; i++) { + buffer_[buffer_index_write_] += (char) buf[i]; + if (buf[i] == ASCII_LF || buffer_[buffer_index_write_].length() >= MAX_DATA_LENGTH_BYTES) { // complete line received buffer_index_write_ = (buffer_index_write_ + 1) % NUM_BUFFERS; } From 2edfcf278fb8cb549b175701b4a70fe96c742eda Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:21:10 -0600 Subject: [PATCH 0616/2030] [hlk_fm22x] Replace per-cycle vector allocation with member buffer (#13859) --- esphome/components/hlk_fm22x/hlk_fm22x.cpp | 62 +++++++++++++--------- esphome/components/hlk_fm22x/hlk_fm22x.h | 10 ++-- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.cpp b/esphome/components/hlk_fm22x/hlk_fm22x.cpp index c0f14c7105..18d26f057a 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.cpp +++ b/esphome/components/hlk_fm22x/hlk_fm22x.cpp @@ -1,20 +1,16 @@ #include "hlk_fm22x.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" -#include <array> #include <cinttypes> namespace esphome::hlk_fm22x { static const char *const TAG = "hlk_fm22x"; -// Maximum response size is 36 bytes (VERIFY reply: face_id + 32-byte name) -static constexpr size_t HLK_FM22X_MAX_RESPONSE_SIZE = 36; - void HlkFm22xComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up HLK-FM22X..."); this->set_enrolling_(false); - while (this->available()) { + while (this->available() > 0) { this->read(); } this->defer([this]() { this->send_command_(HlkFm22xCommand::GET_STATUS); }); @@ -35,7 +31,7 @@ void HlkFm22xComponent::update() { } void HlkFm22xComponent::enroll_face(const std::string &name, HlkFm22xFaceDirection direction) { - if (name.length() > 31) { + if (name.length() > HLK_FM22X_NAME_SIZE - 1) { ESP_LOGE(TAG, "enroll_face(): name too long '%s'", name.c_str()); return; } @@ -88,7 +84,7 @@ void HlkFm22xComponent::send_command_(HlkFm22xCommand command, const uint8_t *da } this->wait_cycles_ = 0; this->active_command_ = command; - while (this->available()) + while (this->available() > 0) this->read(); this->write((uint8_t) (START_CODE >> 8)); this->write((uint8_t) (START_CODE & 0xFF)); @@ -137,17 +133,24 @@ void HlkFm22xComponent::recv_command_() { checksum ^= byte; length |= byte; - std::vector<uint8_t> data; - data.reserve(length); + if (length > HLK_FM22X_MAX_RESPONSE_SIZE) { + ESP_LOGE(TAG, "Response too large: %u bytes", length); + // Discard exactly the remaining payload and checksum for this frame + for (uint16_t i = 0; i < length + 1 && this->available() > 0; ++i) + this->read(); + return; + } + for (uint16_t idx = 0; idx < length; ++idx) { byte = this->read(); checksum ^= byte; - data.push_back(byte); + this->recv_buf_[idx] = byte; } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(HLK_FM22X_MAX_RESPONSE_SIZE)]; - ESP_LOGV(TAG, "Recv type: 0x%.2X, data: %s", response_type, format_hex_pretty_to(hex_buf, data.data(), data.size())); + ESP_LOGV(TAG, "Recv type: 0x%.2X, data: %s", response_type, + format_hex_pretty_to(hex_buf, this->recv_buf_.data(), length)); #endif byte = this->read(); @@ -157,10 +160,10 @@ void HlkFm22xComponent::recv_command_() { } switch (response_type) { case HlkFm22xResponseType::NOTE: - this->handle_note_(data); + this->handle_note_(this->recv_buf_.data(), length); break; case HlkFm22xResponseType::REPLY: - this->handle_reply_(data); + this->handle_reply_(this->recv_buf_.data(), length); break; default: ESP_LOGW(TAG, "Unexpected response type: 0x%.2X", response_type); @@ -168,11 +171,15 @@ void HlkFm22xComponent::recv_command_() { } } -void HlkFm22xComponent::handle_note_(const std::vector<uint8_t> &data) { +void HlkFm22xComponent::handle_note_(const uint8_t *data, size_t length) { + if (length < 1) { + ESP_LOGE(TAG, "Empty note data"); + return; + } switch (data[0]) { case HlkFm22xNoteType::FACE_STATE: - if (data.size() < 17) { - ESP_LOGE(TAG, "Invalid face note data size: %u", data.size()); + if (length < 17) { + ESP_LOGE(TAG, "Invalid face note data size: %zu", length); break; } { @@ -209,9 +216,13 @@ void HlkFm22xComponent::handle_note_(const std::vector<uint8_t> &data) { } } -void HlkFm22xComponent::handle_reply_(const std::vector<uint8_t> &data) { +void HlkFm22xComponent::handle_reply_(const uint8_t *data, size_t length) { auto expected = this->active_command_; this->active_command_ = HlkFm22xCommand::NONE; + if (length < 2) { + ESP_LOGE(TAG, "Reply too short: %zu bytes", length); + return; + } if (data[0] != (uint8_t) expected) { ESP_LOGE(TAG, "Unexpected response command. Expected: 0x%.2X, Received: 0x%.2X", expected, data[0]); return; @@ -238,16 +249,20 @@ void HlkFm22xComponent::handle_reply_(const std::vector<uint8_t> &data) { } switch (expected) { case HlkFm22xCommand::VERIFY: { + if (length < 4 + HLK_FM22X_NAME_SIZE) { + ESP_LOGE(TAG, "VERIFY response too short: %zu bytes", length); + break; + } int16_t face_id = ((int16_t) data[2] << 8) | data[3]; - std::string name(data.begin() + 4, data.begin() + 36); - ESP_LOGD(TAG, "Face verified. ID: %d, name: %s", face_id, name.c_str()); + const char *name_ptr = reinterpret_cast<const char *>(data + 4); + ESP_LOGD(TAG, "Face verified. ID: %d, name: %.*s", face_id, (int) HLK_FM22X_NAME_SIZE, name_ptr); if (this->last_face_id_sensor_ != nullptr) { this->last_face_id_sensor_->publish_state(face_id); } if (this->last_face_name_text_sensor_ != nullptr) { - this->last_face_name_text_sensor_->publish_state(name); + this->last_face_name_text_sensor_->publish_state(name_ptr, HLK_FM22X_NAME_SIZE); } - this->face_scan_matched_callback_.call(face_id, name); + this->face_scan_matched_callback_.call(face_id, std::string(name_ptr, HLK_FM22X_NAME_SIZE)); break; } case HlkFm22xCommand::ENROLL: { @@ -266,9 +281,8 @@ void HlkFm22xComponent::handle_reply_(const std::vector<uint8_t> &data) { this->defer([this]() { this->send_command_(HlkFm22xCommand::GET_VERSION); }); break; case HlkFm22xCommand::GET_VERSION: - if (this->version_text_sensor_ != nullptr) { - std::string version(data.begin() + 2, data.end()); - this->version_text_sensor_->publish_state(version); + if (this->version_text_sensor_ != nullptr && length > 2) { + this->version_text_sensor_->publish_state(reinterpret_cast<const char *>(data + 2), length - 2); } this->defer([this]() { this->get_face_count_(); }); break; diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.h b/esphome/components/hlk_fm22x/hlk_fm22x.h index 9c981d3c44..0ea4636281 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.h +++ b/esphome/components/hlk_fm22x/hlk_fm22x.h @@ -7,12 +7,15 @@ #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/uart/uart.h" +#include <array> #include <utility> -#include <vector> namespace esphome::hlk_fm22x { static const uint16_t START_CODE = 0xEFAA; +static constexpr size_t HLK_FM22X_NAME_SIZE = 32; +// Maximum response payload: command(1) + result(1) + face_id(2) + name(32) = 36 +static constexpr size_t HLK_FM22X_MAX_RESPONSE_SIZE = 36; enum HlkFm22xCommand { NONE = 0x00, RESET = 0x10, @@ -118,10 +121,11 @@ class HlkFm22xComponent : public PollingComponent, public uart::UARTDevice { void get_face_count_(); void send_command_(HlkFm22xCommand command, const uint8_t *data = nullptr, size_t size = 0); void recv_command_(); - void handle_note_(const std::vector<uint8_t> &data); - void handle_reply_(const std::vector<uint8_t> &data); + void handle_note_(const uint8_t *data, size_t length); + void handle_reply_(const uint8_t *data, size_t length); void set_enrolling_(bool enrolling); + std::array<uint8_t, HLK_FM22X_MAX_RESPONSE_SIZE> recv_buf_; HlkFm22xCommand active_command_ = HlkFm22xCommand::NONE; uint16_t wait_cycles_ = 0; sensor::Sensor *face_count_sensor_{nullptr}; From 57b85a840017e6aa8662c1a0228bcb50052a597a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:24:20 -0600 Subject: [PATCH 0617/2030] [dlms_meter] Batch UART reads to reduce per-loop overhead (#13828) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/dlms_meter/dlms_meter.cpp | 27 +++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/esphome/components/dlms_meter/dlms_meter.cpp b/esphome/components/dlms_meter/dlms_meter.cpp index 6aa465143e..11d05b3a08 100644 --- a/esphome/components/dlms_meter/dlms_meter.cpp +++ b/esphome/components/dlms_meter/dlms_meter.cpp @@ -28,15 +28,28 @@ void DlmsMeterComponent::dump_config() { void DlmsMeterComponent::loop() { // Read while data is available, netznoe uses two frames so allow 2x max frame length - while (this->available()) { - if (this->receive_buffer_.size() >= MBUS_MAX_FRAME_LENGTH * 2) { + size_t avail = this->available(); + if (avail > 0) { + size_t remaining = MBUS_MAX_FRAME_LENGTH * 2 - this->receive_buffer_.size(); + if (remaining == 0) { ESP_LOGW(TAG, "Receive buffer full, dropping remaining bytes"); - break; + } else { + // Read all available bytes in batches to reduce UART call overhead. + // Cap reads to remaining buffer capacity. + if (avail > remaining) { + avail = remaining; + } + uint8_t buf[64]; + while (avail > 0) { + size_t to_read = std::min(avail, sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + this->receive_buffer_.insert(this->receive_buffer_.end(), buf, buf + to_read); + this->last_read_ = millis(); + } } - uint8_t c; - this->read_byte(&c); - this->receive_buffer_.push_back(c); - this->last_read_ = millis(); } if (!this->receive_buffer_.empty() && millis() - this->last_read_ > this->read_timeout_) { From 01a90074ba94e9661aa077ba272bc6e2d350ee51 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:25:34 -0600 Subject: [PATCH 0618/2030] [ld2420] Batch UART reads to reduce loop overhead (#13821) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/ld2420/ld2420.cpp | 22 ++++++++++++++++++++-- esphome/components/ld2420/ld2420.h | 2 ++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 10c623bce0..69b69f4a61 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -335,9 +335,10 @@ void LD2420Component::revert_config_action() { void LD2420Component::loop() { // If there is a active send command do not process it here, the send command call will handle it. - while (!this->cmd_active_ && this->available()) { - this->readline_(this->read(), this->buffer_data_, MAX_LINE_LENGTH); + if (this->cmd_active_) { + return; } + this->read_batch_(this->buffer_data_); } void LD2420Component::update_radar_data(uint16_t const *gate_energy, uint8_t sample_number) { @@ -539,6 +540,23 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) { } } +void LD2420Component::read_batch_(std::span<uint8_t, MAX_LINE_LENGTH> buffer) { + // Read all available bytes in batches to reduce UART call overhead. + size_t avail = this->available(); + uint8_t buf[MAX_LINE_LENGTH]; + while (avail > 0) { + size_t to_read = std::min(avail, sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->readline_(buf[i], buffer.data(), buffer.size()); + } + } +} + void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { this->cmd_reply_.command = buffer[CMD_FRAME_COMMAND]; this->cmd_reply_.length = buffer[CMD_FRAME_DATA_LENGTH]; diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 50ddf45264..6d81f86497 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -4,6 +4,7 @@ #include "esphome/components/uart/uart.h" #include "esphome/core/automation.h" #include "esphome/core/helpers.h" +#include <span> #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" #endif @@ -165,6 +166,7 @@ class LD2420Component : public Component, public uart::UARTDevice { void handle_energy_mode_(uint8_t *buffer, int len); void handle_ack_data_(uint8_t *buffer, int len); void readline_(int rx_data, uint8_t *buffer, int len); + void read_batch_(std::span<uint8_t, MAX_LINE_LENGTH> buffer); void set_calibration_(bool state) { this->calibration_ = state; }; bool get_calibration_() { return this->calibration_; }; From 097901e9c89e284e424bb51eb6cc504a07ba261b Mon Sep 17 00:00:00 2001 From: Sean Kelly <xconverge@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:30:37 -0800 Subject: [PATCH 0619/2030] [aqi] Fix AQI calculation for specific pm2.5 or pm10 readings (#13770) --- esphome/components/aqi/aqi_calculator.h | 38 +++++++++++++++++++----- esphome/components/aqi/caqi_calculator.h | 30 ++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/esphome/components/aqi/aqi_calculator.h b/esphome/components/aqi/aqi_calculator.h index 993504c1e9..d624af0432 100644 --- a/esphome/components/aqi/aqi_calculator.h +++ b/esphome/components/aqi/aqi_calculator.h @@ -1,5 +1,6 @@ #pragma once +#include <algorithm> #include <cmath> #include <limits> #include "abstract_aqi_calculator.h" @@ -14,7 +15,11 @@ class AQICalculator : public AbstractAQICalculator { float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); + float aqi = std::max(pm2_5_index, pm10_0_index); + if (aqi < 0.0f) { + aqi = 0.0f; + } + return static_cast<uint16_t>(std::lround(aqi)); } protected: @@ -22,13 +27,27 @@ class AQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; - static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {{0.0f, 9.0f}, {9.1f, 35.4f}, - {35.5f, 55.4f}, {55.5f, 125.4f}, - {125.5f, 225.4f}, {225.5f, std::numeric_limits<float>::max()}}; + static constexpr float PM2_5_GRID[NUM_LEVELS][2] = { + // clang-format off + {0.0f, 9.1f}, + {9.1f, 35.5f}, + {35.5f, 55.5f}, + {55.5f, 125.5f}, + {125.5f, 225.5f}, + {225.5f, std::numeric_limits<float>::max()} + // clang-format on + }; - static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {{0.0f, 54.0f}, {55.0f, 154.0f}, - {155.0f, 254.0f}, {255.0f, 354.0f}, - {355.0f, 424.0f}, {425.0f, std::numeric_limits<float>::max()}}; + static constexpr float PM10_0_GRID[NUM_LEVELS][2] = { + // clang-format off + {0.0f, 55.0f}, + {55.0f, 155.0f}, + {155.0f, 255.0f}, + {255.0f, 355.0f}, + {355.0f, 425.0f}, + {425.0f, std::numeric_limits<float>::max()} + // clang-format on + }; static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); @@ -45,7 +64,10 @@ class AQICalculator : public AbstractAQICalculator { static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { - if (value >= array[i][0] && value <= array[i][1]) { + const bool in_range = + (value >= array[i][0]) && ((i == NUM_LEVELS - 1) ? (value <= array[i][1]) // last bucket inclusive + : (value < array[i][1])); // others exclusive on hi + if (in_range) { return i; } } diff --git a/esphome/components/aqi/caqi_calculator.h b/esphome/components/aqi/caqi_calculator.h index d2ec4bb98f..fe2efe7059 100644 --- a/esphome/components/aqi/caqi_calculator.h +++ b/esphome/components/aqi/caqi_calculator.h @@ -1,5 +1,6 @@ #pragma once +#include <algorithm> #include <cmath> #include <limits> #include "abstract_aqi_calculator.h" @@ -12,7 +13,11 @@ class CAQICalculator : public AbstractAQICalculator { float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); + float aqi = std::max(pm2_5_index, pm10_0_index); + if (aqi < 0.0f) { + aqi = 0.0f; + } + return static_cast<uint16_t>(std::lround(aqi)); } protected: @@ -21,10 +26,24 @@ class CAQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 75}, {76, 100}, {101, 400}}; static constexpr float PM2_5_GRID[NUM_LEVELS][2] = { - {0.0f, 15.0f}, {15.1f, 30.0f}, {30.1f, 55.0f}, {55.1f, 110.0f}, {110.1f, std::numeric_limits<float>::max()}}; + // clang-format off + {0.0f, 15.1f}, + {15.1f, 30.1f}, + {30.1f, 55.1f}, + {55.1f, 110.1f}, + {110.1f, std::numeric_limits<float>::max()} + // clang-format on + }; static constexpr float PM10_0_GRID[NUM_LEVELS][2] = { - {0.0f, 25.0f}, {25.1f, 50.0f}, {50.1f, 90.0f}, {90.1f, 180.0f}, {180.1f, std::numeric_limits<float>::max()}}; + // clang-format off + {0.0f, 25.1f}, + {25.1f, 50.1f}, + {50.1f, 90.1f}, + {90.1f, 180.1f}, + {180.1f, std::numeric_limits<float>::max()} + // clang-format on + }; static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); @@ -42,7 +61,10 @@ class CAQICalculator : public AbstractAQICalculator { static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { - if (value >= array[i][0] && value <= array[i][1]) { + const bool in_range = + (value >= array[i][0]) && ((i == NUM_LEVELS - 1) ? (value <= array[i][1]) // last bucket inclusive + : (value < array[i][1])); // others exclusive on hi + if (in_range) { return i; } } From 87ac263264b02033638abbed3d661ff33ff7bffd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Feb 2026 18:32:52 -0600 Subject: [PATCH 0620/2030] [dsmr] Batch UART reads to reduce per-loop overhead (#13826) --- esphome/components/dsmr/dsmr.cpp | 243 +++++++++++++++++-------------- esphome/components/dsmr/dsmr.h | 1 + 2 files changed, 137 insertions(+), 107 deletions(-) diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index c78d37bf5e..20fbd20cd6 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -40,9 +40,7 @@ bool Dsmr::ready_to_request_data_() { this->start_requesting_data_(); } if (!this->requesting_data_) { - while (this->available()) { - this->read(); - } + this->drain_rx_buffer_(); } } return this->requesting_data_; @@ -115,138 +113,169 @@ void Dsmr::stop_requesting_data_() { } else { ESP_LOGV(TAG, "Stop reading data from P1 port"); } - while (this->available()) { - this->read(); - } + this->drain_rx_buffer_(); this->requesting_data_ = false; } } +void Dsmr::drain_rx_buffer_() { + uint8_t buf[64]; + int avail; + while ((avail = this->available()) > 0) { + if (!this->read_array(buf, std::min(static_cast<size_t>(avail), sizeof(buf)))) { + break; + } + } +} + void Dsmr::reset_telegram_() { this->header_found_ = false; this->footer_found_ = false; this->bytes_read_ = 0; this->crypt_bytes_read_ = 0; this->crypt_telegram_len_ = 0; - this->last_read_time_ = 0; } void Dsmr::receive_telegram_() { while (this->available_within_timeout_()) { - const char c = this->read(); + // Read all available bytes in batches to reduce UART call overhead. + uint8_t buf[64]; + int avail = this->available(); + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) + return; + avail -= to_read; - // Find a new telegram header, i.e. forward slash. - if (c == '/') { - ESP_LOGV(TAG, "Header of telegram found"); - this->reset_telegram_(); - this->header_found_ = true; - } - if (!this->header_found_) - continue; + for (size_t i = 0; i < to_read; i++) { + const char c = static_cast<char>(buf[i]); - // Check for buffer overflow. - if (this->bytes_read_ >= this->max_telegram_len_) { - this->reset_telegram_(); - ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", this->max_telegram_len_); - return; - } + // Find a new telegram header, i.e. forward slash. + if (c == '/') { + ESP_LOGV(TAG, "Header of telegram found"); + this->reset_telegram_(); + this->header_found_ = true; + } + if (!this->header_found_) + continue; - // Some v2.2 or v3 meters will send a new value which starts with '(' - // in a new line, while the value belongs to the previous ObisId. For - // proper parsing, remove these new line characters. - if (c == '(') { - while (true) { - auto previous_char = this->telegram_[this->bytes_read_ - 1]; - if (previous_char == '\n' || previous_char == '\r') { - this->bytes_read_--; - } else { - break; + // Check for buffer overflow. + if (this->bytes_read_ >= this->max_telegram_len_) { + this->reset_telegram_(); + ESP_LOGE(TAG, "Error: telegram larger than buffer (%d bytes)", this->max_telegram_len_); + return; + } + + // Some v2.2 or v3 meters will send a new value which starts with '(' + // in a new line, while the value belongs to the previous ObisId. For + // proper parsing, remove these new line characters. + if (c == '(') { + while (true) { + auto previous_char = this->telegram_[this->bytes_read_ - 1]; + if (previous_char == '\n' || previous_char == '\r') { + this->bytes_read_--; + } else { + break; + } + } + } + + // Store the byte in the buffer. + this->telegram_[this->bytes_read_] = c; + this->bytes_read_++; + + // Check for a footer, i.e. exclamation mark, followed by a hex checksum. + if (c == '!') { + ESP_LOGV(TAG, "Footer of telegram found"); + this->footer_found_ = true; + continue; + } + // Check for the end of the hex checksum, i.e. a newline. + if (this->footer_found_ && c == '\n') { + // Parse the telegram and publish sensor values. + this->parse_telegram(); + this->reset_telegram_(); + return; } } } - - // Store the byte in the buffer. - this->telegram_[this->bytes_read_] = c; - this->bytes_read_++; - - // Check for a footer, i.e. exclamation mark, followed by a hex checksum. - if (c == '!') { - ESP_LOGV(TAG, "Footer of telegram found"); - this->footer_found_ = true; - continue; - } - // Check for the end of the hex checksum, i.e. a newline. - if (this->footer_found_ && c == '\n') { - // Parse the telegram and publish sensor values. - this->parse_telegram(); - this->reset_telegram_(); - return; - } } } void Dsmr::receive_encrypted_telegram_() { while (this->available_within_timeout_()) { - const char c = this->read(); + // Read all available bytes in batches to reduce UART call overhead. + uint8_t buf[64]; + int avail = this->available(); + while (avail > 0) { + size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) + return; + avail -= to_read; - // Find a new telegram start byte. - if (!this->header_found_) { - if ((uint8_t) c != 0xDB) { - continue; + for (size_t i = 0; i < to_read; i++) { + const char c = static_cast<char>(buf[i]); + + // Find a new telegram start byte. + if (!this->header_found_) { + if ((uint8_t) c != 0xDB) { + continue; + } + ESP_LOGV(TAG, "Start byte 0xDB of encrypted telegram found"); + this->reset_telegram_(); + this->header_found_ = true; + } + + // Check for buffer overflow. + if (this->crypt_bytes_read_ >= this->max_telegram_len_) { + this->reset_telegram_(); + ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", this->max_telegram_len_); + return; + } + + // Store the byte in the buffer. + this->crypt_telegram_[this->crypt_bytes_read_] = c; + this->crypt_bytes_read_++; + + // Read the length of the incoming encrypted telegram. + if (this->crypt_telegram_len_ == 0 && this->crypt_bytes_read_ > 20) { + // Complete header + data bytes + this->crypt_telegram_len_ = 13 + (this->crypt_telegram_[11] << 8 | this->crypt_telegram_[12]); + ESP_LOGV(TAG, "Encrypted telegram length: %d bytes", this->crypt_telegram_len_); + } + + // Check for the end of the encrypted telegram. + if (this->crypt_telegram_len_ == 0 || this->crypt_bytes_read_ != this->crypt_telegram_len_) { + continue; + } + ESP_LOGV(TAG, "End of encrypted telegram found"); + + // Decrypt the encrypted telegram. + GCM<AES128> *gcmaes128{new GCM<AES128>()}; + gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize()); + // the iv is 8 bytes of the system title + 4 bytes frame counter + // system title is at byte 2 and frame counter at byte 15 + for (int i = 10; i < 14; i++) + this->crypt_telegram_[i] = this->crypt_telegram_[i + 4]; + constexpr uint16_t iv_size{12}; + gcmaes128->setIV(&this->crypt_telegram_[2], iv_size); + gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_), + // the ciphertext start at byte 18 + &this->crypt_telegram_[18], + // cipher size + this->crypt_bytes_read_ - 17); + delete gcmaes128; // NOLINT(cppcoreguidelines-owning-memory) + + this->bytes_read_ = strnlen(this->telegram_, this->max_telegram_len_); + ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", this->bytes_read_); + ESP_LOGVV(TAG, "Decrypted telegram: %s", this->telegram_); + + // Parse the decrypted telegram and publish sensor values. + this->parse_telegram(); + this->reset_telegram_(); + return; } - ESP_LOGV(TAG, "Start byte 0xDB of encrypted telegram found"); - this->reset_telegram_(); - this->header_found_ = true; } - - // Check for buffer overflow. - if (this->crypt_bytes_read_ >= this->max_telegram_len_) { - this->reset_telegram_(); - ESP_LOGE(TAG, "Error: encrypted telegram larger than buffer (%d bytes)", this->max_telegram_len_); - return; - } - - // Store the byte in the buffer. - this->crypt_telegram_[this->crypt_bytes_read_] = c; - this->crypt_bytes_read_++; - - // Read the length of the incoming encrypted telegram. - if (this->crypt_telegram_len_ == 0 && this->crypt_bytes_read_ > 20) { - // Complete header + data bytes - this->crypt_telegram_len_ = 13 + (this->crypt_telegram_[11] << 8 | this->crypt_telegram_[12]); - ESP_LOGV(TAG, "Encrypted telegram length: %d bytes", this->crypt_telegram_len_); - } - - // Check for the end of the encrypted telegram. - if (this->crypt_telegram_len_ == 0 || this->crypt_bytes_read_ != this->crypt_telegram_len_) { - continue; - } - ESP_LOGV(TAG, "End of encrypted telegram found"); - - // Decrypt the encrypted telegram. - GCM<AES128> *gcmaes128{new GCM<AES128>()}; - gcmaes128->setKey(this->decryption_key_.data(), gcmaes128->keySize()); - // the iv is 8 bytes of the system title + 4 bytes frame counter - // system title is at byte 2 and frame counter at byte 15 - for (int i = 10; i < 14; i++) - this->crypt_telegram_[i] = this->crypt_telegram_[i + 4]; - constexpr uint16_t iv_size{12}; - gcmaes128->setIV(&this->crypt_telegram_[2], iv_size); - gcmaes128->decrypt(reinterpret_cast<uint8_t *>(this->telegram_), - // the ciphertext start at byte 18 - &this->crypt_telegram_[18], - // cipher size - this->crypt_bytes_read_ - 17); - delete gcmaes128; // NOLINT(cppcoreguidelines-owning-memory) - - this->bytes_read_ = strnlen(this->telegram_, this->max_telegram_len_); - ESP_LOGV(TAG, "Decrypted telegram size: %d bytes", this->bytes_read_); - ESP_LOGVV(TAG, "Decrypted telegram: %s", this->telegram_); - - // Parse the decrypted telegram and publish sensor values. - this->parse_telegram(); - this->reset_telegram_(); - return; } } diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index b7e05a22b3..fafcf62b87 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -85,6 +85,7 @@ class Dsmr : public Component, public uart::UARTDevice { void receive_telegram_(); void receive_encrypted_telegram_(); void reset_telegram_(); + void drain_rx_buffer_(); /// Wait for UART data to become available within the read timeout. /// From dcbb0204794d672fcfc66f4174bb4ca0a1e9dc9f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Feb 2026 20:02:41 -0500 Subject: [PATCH 0621/2030] [uart] Fix available() return type to size_t across components (#13898) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/cse7766/cse7766.cpp | 6 +++--- esphome/components/dfplayer/dfplayer.cpp | 4 ++-- esphome/components/dsmr/dsmr.cpp | 12 ++++++------ esphome/components/ld2410/ld2410.cpp | 4 ++-- esphome/components/ld2412/ld2412.cpp | 4 ++-- esphome/components/ld2450/ld2450.cpp | 4 ++-- esphome/components/modbus/modbus.cpp | 4 ++-- esphome/components/nextion/nextion.cpp | 4 ++-- esphome/components/pipsolar/pipsolar.cpp | 8 ++++---- esphome/components/pylontech/pylontech.cpp | 4 ++-- esphome/components/rd03d/rd03d.cpp | 4 ++-- esphome/components/rf_bridge/rf_bridge.cpp | 4 ++-- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp | 4 ++-- esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp | 4 ++-- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp | 4 ++-- esphome/components/tuya/tuya.cpp | 4 ++-- 16 files changed, 39 insertions(+), 39 deletions(-) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 45abd3ca3d..7ffdf757a0 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -16,8 +16,8 @@ void CSE7766Component::loop() { } // Early return prevents updating last_transmission_ when no data is available. - int avail = this->available(); - if (avail <= 0) { + size_t avail = this->available(); + if (avail == 0) { return; } @@ -27,7 +27,7 @@ void CSE7766Component::loop() { // At 4800 baud (~480 bytes/sec) with ~122 Hz loop rate, typically ~4 bytes per call. uint8_t buf[CSE7766_RAW_DATA_SIZE]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/dfplayer/dfplayer.cpp b/esphome/components/dfplayer/dfplayer.cpp index 48c06be558..79f8fd03c3 100644 --- a/esphome/components/dfplayer/dfplayer.cpp +++ b/esphome/components/dfplayer/dfplayer.cpp @@ -133,10 +133,10 @@ void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) { void DFPlayer::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/dsmr/dsmr.cpp b/esphome/components/dsmr/dsmr.cpp index 20fbd20cd6..baf7f59314 100644 --- a/esphome/components/dsmr/dsmr.cpp +++ b/esphome/components/dsmr/dsmr.cpp @@ -120,9 +120,9 @@ void Dsmr::stop_requesting_data_() { void Dsmr::drain_rx_buffer_() { uint8_t buf[64]; - int avail; + size_t avail; while ((avail = this->available()) > 0) { - if (!this->read_array(buf, std::min(static_cast<size_t>(avail), sizeof(buf)))) { + if (!this->read_array(buf, std::min(avail, sizeof(buf)))) { break; } } @@ -140,9 +140,9 @@ void Dsmr::receive_telegram_() { while (this->available_within_timeout_()) { // Read all available bytes in batches to reduce UART call overhead. uint8_t buf[64]; - int avail = this->available(); + size_t avail = this->available(); while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) return; avail -= to_read; @@ -206,9 +206,9 @@ void Dsmr::receive_encrypted_telegram_() { while (this->available_within_timeout_()) { // Read all available bytes in batches to reduce UART call overhead. uint8_t buf[64]; - int avail = this->available(); + size_t avail = this->available(); while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) return; avail -= to_read; diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index b57b1d9978..95a04f768a 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -276,10 +276,10 @@ void LD2410Component::restart_and_read_all_info() { void LD2410Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[MAX_LINE_LENGTH]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index f8ceee78eb..95e19e0d5f 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -311,10 +311,10 @@ void LD2412Component::restart_and_read_all_info() { void LD2412Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[MAX_LINE_LENGTH]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 38ba0d7f96..b04b509a16 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -277,10 +277,10 @@ void LD2450Component::dump_config() { void LD2450Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[MAX_LINE_LENGTH]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index c1f5635028..d40343db33 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -20,10 +20,10 @@ void Modbus::loop() { const uint32_t now = App.get_loop_component_start_time(); // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 56bbc840fb..9f1ce47837 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -398,10 +398,10 @@ bool Nextion::remove_from_q_(bool report_empty) { void Nextion::process_serial_() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index d7b37f6130..e6831ad19e 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -14,9 +14,9 @@ void Pipsolar::setup() { void Pipsolar::empty_uart_buffer_() { uint8_t buf[64]; - int avail; + size_t avail; while ((avail = this->available()) > 0) { - if (!this->read_array(buf, std::min(static_cast<size_t>(avail), sizeof(buf)))) { + if (!this->read_array(buf, std::min(avail, sizeof(buf)))) { break; } } @@ -97,10 +97,10 @@ void Pipsolar::loop() { } if (this->state_ == STATE_COMMAND || this->state_ == STATE_POLL) { - int avail = this->available(); + size_t avail = this->available(); while (avail > 0) { uint8_t buf[64]; - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/pylontech/pylontech.cpp b/esphome/components/pylontech/pylontech.cpp index d724253256..7eb89d5b32 100644 --- a/esphome/components/pylontech/pylontech.cpp +++ b/esphome/components/pylontech/pylontech.cpp @@ -56,14 +56,14 @@ void PylontechComponent::setup() { void PylontechComponent::update() { this->write_str("pwr\n"); } void PylontechComponent::loop() { - int avail = this->available(); + size_t avail = this->available(); if (avail > 0) { // pylontech sends a lot of data very suddenly // we need to quickly put it all into our own buffer, otherwise the uart's buffer will overflow int recv = 0; uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index e4dbdf41cb..d47347fcfa 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -82,10 +82,10 @@ void RD03DComponent::dump_config() { void RD03DComponent::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/rf_bridge/rf_bridge.cpp b/esphome/components/rf_bridge/rf_bridge.cpp index e33c13aafe..d8c148145c 100644 --- a/esphome/components/rf_bridge/rf_bridge.cpp +++ b/esphome/components/rf_bridge/rf_bridge.cpp @@ -136,10 +136,10 @@ void RFBridgeComponent::loop() { this->last_bridge_byte_ = now; } - int avail = this->available(); + size_t avail = this->available(); while (avail > 0) { uint8_t buf[64]; - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 3f2103b401..99d519b434 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -107,10 +107,10 @@ void MR24HPC1Component::update_() { // main loop void MR24HPC1Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp index d95e13241d..12f188fe03 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp @@ -31,10 +31,10 @@ void MR60BHA2Component::dump_config() { // main loop void MR60BHA2Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp index 441ee2b5c2..5d571618d3 100644 --- a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +++ b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp @@ -50,10 +50,10 @@ void MR60FDA2Component::setup() { // main loop void MR60FDA2Component::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } diff --git a/esphome/components/tuya/tuya.cpp b/esphome/components/tuya/tuya.cpp index 9ee4c09b86..a1acbf2f56 100644 --- a/esphome/components/tuya/tuya.cpp +++ b/esphome/components/tuya/tuya.cpp @@ -32,10 +32,10 @@ void Tuya::setup() { void Tuya::loop() { // Read all available bytes in batches to reduce UART call overhead. - int avail = this->available(); + size_t avail = this->available(); uint8_t buf[64]; while (avail > 0) { - size_t to_read = std::min(static_cast<size_t>(avail), sizeof(buf)); + size_t to_read = std::min(avail, sizeof(buf)); if (!this->read_array(buf, to_read)) { break; } From b97a728cf1e8b35c0f9e60ca9c5f7a50fdd5c224 Mon Sep 17 00:00:00 2001 From: Cody Cutrer <cody@cutrer.us> Date: Mon, 9 Feb 2026 20:40:44 -0700 Subject: [PATCH 0622/2030] [ld2450] add on_data callback (#13601) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ld2450/__init__.py | 13 ++++++++++++- esphome/components/ld2450/ld2450.cpp | 6 ++++++ esphome/components/ld2450/ld2450.h | 12 ++++++++++++ tests/components/ld2450/common.yaml | 3 +++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2450/__init__.py b/esphome/components/ld2450/__init__.py index bd6d697c90..5854a5794c 100644 --- a/esphome/components/ld2450/__init__.py +++ b/esphome/components/ld2450/__init__.py @@ -1,7 +1,8 @@ +from esphome import automation import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_THROTTLE +from esphome.const import CONF_ID, CONF_ON_DATA, CONF_THROTTLE, CONF_TRIGGER_ID AUTO_LOAD = ["ld24xx"] DEPENDENCIES = ["uart"] @@ -11,6 +12,8 @@ MULTI_CONF = True ld2450_ns = cg.esphome_ns.namespace("ld2450") LD2450Component = ld2450_ns.class_("LD2450Component", cg.Component, uart.UARTDevice) +LD2450DataTrigger = ld2450_ns.class_("LD2450DataTrigger", automation.Trigger.template()) + CONF_LD2450_ID = "ld2450_id" CONFIG_SCHEMA = cv.All( @@ -20,6 +23,11 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_THROTTLE): cv.invalid( f"{CONF_THROTTLE} has been removed; use per-sensor filters, instead" ), + cv.Optional(CONF_ON_DATA): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LD2450DataTrigger), + } + ), } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -45,3 +53,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) + for conf in config.get(CONF_ON_DATA, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index b04b509a16..1ea5c18271 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -413,6 +413,10 @@ void LD2450Component::restart_and_read_all_info() { this->set_timeout(1500, [this]() { this->read_all_info(); }); } +void LD2450Component::add_on_data_callback(std::function<void()> &&callback) { + this->data_callback_.add(std::move(callback)); +} + // Send command with values to LD2450 void LD2450Component::send_command_(uint8_t command, const uint8_t *command_value, uint8_t command_value_len) { ESP_LOGV(TAG, "Sending COMMAND %02X", command); @@ -613,6 +617,8 @@ void LD2450Component::handle_periodic_data_() { this->still_presence_millis_ = App.get_loop_component_start_time(); } #endif + + this->data_callback_.call(); } bool LD2450Component::handle_ack_data_() { diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index b94c3cac37..fe69cd81d0 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -141,6 +141,9 @@ class LD2450Component : public Component, public uart::UARTDevice { int32_t zone2_x1, int32_t zone2_y1, int32_t zone2_x2, int32_t zone2_y2, int32_t zone3_x1, int32_t zone3_y1, int32_t zone3_x2, int32_t zone3_y2); + /// Add a callback that will be called after each successfully processed periodic data frame. + void add_on_data_callback(std::function<void()> &&callback); + protected: void send_command_(uint8_t command_str, const uint8_t *command_value, uint8_t command_value_len); void set_config_mode_(bool enable); @@ -190,6 +193,15 @@ class LD2450Component : public Component, public uart::UARTDevice { #ifdef USE_TEXT_SENSOR std::array<text_sensor::TextSensor *, 3> direction_text_sensors_{}; #endif + + LazyCallbackManager<void()> data_callback_; +}; + +class LD2450DataTrigger : public Trigger<> { + public: + explicit LD2450DataTrigger(LD2450Component *parent) { + parent->add_on_data_callback([this]() { this->trigger(); }); + } }; } // namespace esphome::ld2450 diff --git a/tests/components/ld2450/common.yaml b/tests/components/ld2450/common.yaml index cfa3c922fc..617228ca34 100644 --- a/tests/components/ld2450/common.yaml +++ b/tests/components/ld2450/common.yaml @@ -1,5 +1,8 @@ ld2450: - id: ld2450_radar + on_data: + then: + - logger.log: "LD2450 Radar Data Received" button: - platform: ld2450 From 5caed68cd9a9a36e9d3fb805bb2e464dcfe18e73 Mon Sep 17 00:00:00 2001 From: tronikos <tronikos@users.noreply.github.com> Date: Tue, 10 Feb 2026 03:36:56 -0800 Subject: [PATCH 0623/2030] [api] Deprecate WATER_HEATER_COMMAND_HAS_STATE (#13892) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/api/api.proto | 4 +++- esphome/components/api/api_connection.cpp | 6 +++++- esphome/components/api/api_pb2.h | 2 ++ esphome/components/api/api_pb2_dump.cpp | 4 ++++ 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index d25934c60b..18dac6a2d1 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1155,9 +1155,11 @@ enum WaterHeaterCommandHasField { WATER_HEATER_COMMAND_HAS_NONE = 0; WATER_HEATER_COMMAND_HAS_MODE = 1; WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE = 2; - WATER_HEATER_COMMAND_HAS_STATE = 4; + WATER_HEATER_COMMAND_HAS_STATE = 4 [deprecated=true]; WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW = 8; WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH = 16; + WATER_HEATER_COMMAND_HAS_ON_STATE = 32; + WATER_HEATER_COMMAND_HAS_AWAY_STATE = 64; } message WaterHeaterCommandRequest { diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index ddc24a7e2c..c00f413e67 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1343,8 +1343,12 @@ void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequ call.set_target_temperature_low(msg.target_temperature_low); if (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH) call.set_target_temperature_high(msg.target_temperature_high); - if (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_STATE) { + if ((msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_AWAY_STATE) || + (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_STATE)) { call.set_away((msg.state & water_heater::WATER_HEATER_STATE_AWAY) != 0); + } + if ((msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_ON_STATE) || + (msg.has_fields & enums::WATER_HEATER_COMMAND_HAS_STATE)) { call.set_on((msg.state & water_heater::WATER_HEATER_STATE_ON) != 0); } call.perform(); diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 15819da172..d001f869c5 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -147,6 +147,8 @@ enum WaterHeaterCommandHasField : uint32_t { WATER_HEATER_COMMAND_HAS_STATE = 4, WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW = 8, WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH = 16, + WATER_HEATER_COMMAND_HAS_ON_STATE = 32, + WATER_HEATER_COMMAND_HAS_AWAY_STATE = 64, }; #ifdef USE_NUMBER enum NumberMode : uint32_t { diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index f1e3bdcafe..73690610ed 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -385,6 +385,10 @@ const char *proto_enum_to_string<enums::WaterHeaterCommandHasField>(enums::Water return "WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW"; case enums::WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH: return "WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH"; + case enums::WATER_HEATER_COMMAND_HAS_ON_STATE: + return "WATER_HEATER_COMMAND_HAS_ON_STATE"; + case enums::WATER_HEATER_COMMAND_HAS_AWAY_STATE: + return "WATER_HEATER_COMMAND_HAS_AWAY_STATE"; default: return "UNKNOWN"; } From 1c3af302991d9e907b5df7161f61a5b8dd959805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:45:31 +0000 Subject: [PATCH 0624/2030] Bump aioesphomeapi from 43.14.0 to 44.0.0 (#13906) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1771867535..b8adc22013 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.1.0 click==8.1.7 esphome-dashboard==20260110.0 -aioesphomeapi==43.14.0 +aioesphomeapi==44.0.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From e85a022c775176936ad6938edb6b1d6d41b12388 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:49:59 +0000 Subject: [PATCH 0625/2030] Bump esphome-dashboard from 20260110.0 to 20260210.0 (#13905) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b8adc22013..a0a29ad30a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ pyserial==3.5 platformio==6.1.19 esptool==5.1.0 click==8.1.7 -esphome-dashboard==20260110.0 +esphome-dashboard==20260210.0 aioesphomeapi==44.0.0 zeroconf==0.148.0 puremagic==1.30 From e3141211c3ce78767569b39896a52b75efa4796e Mon Sep 17 00:00:00 2001 From: tronikos <tronikos@users.noreply.github.com> Date: Tue, 10 Feb 2026 04:45:18 -0800 Subject: [PATCH 0626/2030] [water_heater] Add On/Off and Away mode support to template platform (#13839) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../template/water_heater/__init__.py | 30 +++++++ .../template/water_heater/automation.h | 11 ++- .../water_heater/template_water_heater.cpp | 35 +++++++- .../water_heater/template_water_heater.h | 4 + tests/components/template/common-base.yaml | 6 ++ .../fixtures/water_heater_template.yaml | 15 ++++ .../integration/test_water_heater_template.py | 89 ++++++++++++++----- 7 files changed, 164 insertions(+), 26 deletions(-) diff --git a/esphome/components/template/water_heater/__init__.py b/esphome/components/template/water_heater/__init__.py index 5f96155fbf..71f98c826a 100644 --- a/esphome/components/template/water_heater/__init__.py +++ b/esphome/components/template/water_heater/__init__.py @@ -3,6 +3,7 @@ import esphome.codegen as cg from esphome.components import water_heater import esphome.config_validation as cv from esphome.const import ( + CONF_AWAY, CONF_ID, CONF_MODE, CONF_OPTIMISTIC, @@ -18,6 +19,7 @@ from esphome.types import ConfigType from .. import template_ns CONF_CURRENT_TEMPERATURE = "current_temperature" +CONF_IS_ON = "is_on" TemplateWaterHeater = template_ns.class_( "TemplateWaterHeater", cg.Component, water_heater.WaterHeater @@ -51,6 +53,8 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_SUPPORTED_MODES): cv.ensure_list( water_heater.validate_water_heater_mode ), + cv.Optional(CONF_AWAY): cv.returning_lambda, + cv.Optional(CONF_IS_ON): cv.returning_lambda, } ) .extend(cv.COMPONENT_SCHEMA) @@ -98,6 +102,22 @@ async def to_code(config: ConfigType) -> None: if CONF_SUPPORTED_MODES in config: cg.add(var.set_supported_modes(config[CONF_SUPPORTED_MODES])) + if CONF_AWAY in config: + template_ = await cg.process_lambda( + config[CONF_AWAY], + [], + return_type=cg.optional.template(bool), + ) + cg.add(var.set_away_lambda(template_)) + + if CONF_IS_ON in config: + template_ = await cg.process_lambda( + config[CONF_IS_ON], + [], + return_type=cg.optional.template(bool), + ) + cg.add(var.set_is_on_lambda(template_)) + @automation.register_action( "water_heater.template.publish", @@ -110,6 +130,8 @@ async def to_code(config: ConfigType) -> None: cv.Optional(CONF_MODE): cv.templatable( water_heater.validate_water_heater_mode ), + cv.Optional(CONF_AWAY): cv.templatable(cv.boolean), + cv.Optional(CONF_IS_ON): cv.templatable(cv.boolean), } ), ) @@ -134,4 +156,12 @@ async def water_heater_template_publish_to_code( template_ = await cg.templatable(mode, args, water_heater.WaterHeaterMode) cg.add(var.set_mode(template_)) + if CONF_AWAY in config: + template_ = await cg.templatable(config[CONF_AWAY], args, bool) + cg.add(var.set_away(template_)) + + if CONF_IS_ON in config: + template_ = await cg.templatable(config[CONF_IS_ON], args, bool) + cg.add(var.set_is_on(template_)) + return var diff --git a/esphome/components/template/water_heater/automation.h b/esphome/components/template/water_heater/automation.h index 3dad2b85ae..d19542db41 100644 --- a/esphome/components/template/water_heater/automation.h +++ b/esphome/components/template/water_heater/automation.h @@ -11,12 +11,15 @@ class TemplateWaterHeaterPublishAction : public Action<Ts...>, public Parented<T TEMPLATABLE_VALUE(float, current_temperature) TEMPLATABLE_VALUE(float, target_temperature) TEMPLATABLE_VALUE(water_heater::WaterHeaterMode, mode) + TEMPLATABLE_VALUE(bool, away) + TEMPLATABLE_VALUE(bool, is_on) void play(const Ts &...x) override { if (this->current_temperature_.has_value()) { this->parent_->set_current_temperature(this->current_temperature_.value(x...)); } - bool needs_call = this->target_temperature_.has_value() || this->mode_.has_value(); + bool needs_call = this->target_temperature_.has_value() || this->mode_.has_value() || this->away_.has_value() || + this->is_on_.has_value(); if (needs_call) { auto call = this->parent_->make_call(); if (this->target_temperature_.has_value()) { @@ -25,6 +28,12 @@ class TemplateWaterHeaterPublishAction : public Action<Ts...>, public Parented<T if (this->mode_.has_value()) { call.set_mode(this->mode_.value(x...)); } + if (this->away_.has_value()) { + call.set_away(this->away_.value(x...)); + } + if (this->is_on_.has_value()) { + call.set_on(this->is_on_.value(x...)); + } call.perform(); } else { this->parent_->publish_state(); diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index c354deee0e..57c76286a0 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -17,7 +17,7 @@ void TemplateWaterHeater::setup() { } } if (!this->current_temperature_f_.has_value() && !this->target_temperature_f_.has_value() && - !this->mode_f_.has_value()) + !this->mode_f_.has_value() && !this->away_f_.has_value() && !this->is_on_f_.has_value()) this->disable_loop(); } @@ -32,6 +32,12 @@ water_heater::WaterHeaterTraits TemplateWaterHeater::traits() { if (this->target_temperature_f_.has_value()) { traits.add_feature_flags(water_heater::WATER_HEATER_SUPPORTS_TARGET_TEMPERATURE); } + if (this->away_f_.has_value()) { + traits.set_supports_away_mode(true); + } + if (this->is_on_f_.has_value()) { + traits.add_feature_flags(water_heater::WATER_HEATER_SUPPORTS_ON_OFF); + } return traits; } @@ -62,6 +68,22 @@ void TemplateWaterHeater::loop() { } } + auto away = this->away_f_.call(); + if (away.has_value()) { + if (*away != this->is_away()) { + this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *away); + changed = true; + } + } + + auto is_on = this->is_on_f_.call(); + if (is_on.has_value()) { + if (*is_on != this->is_on()) { + this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *is_on); + changed = true; + } + } + if (changed) { this->publish_state(); } @@ -90,6 +112,17 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) { } } + if (call.get_away().has_value()) { + if (this->optimistic_) { + this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *call.get_away()); + } + } + if (call.get_on().has_value()) { + if (this->optimistic_) { + this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *call.get_on()); + } + } + this->set_trigger_.trigger(); if (this->optimistic_) { diff --git a/esphome/components/template/water_heater/template_water_heater.h b/esphome/components/template/water_heater/template_water_heater.h index 22173209aa..045a142e40 100644 --- a/esphome/components/template/water_heater/template_water_heater.h +++ b/esphome/components/template/water_heater/template_water_heater.h @@ -24,6 +24,8 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { this->target_temperature_f_.set(std::forward<F>(f)); } template<typename F> void set_mode_lambda(F &&f) { this->mode_f_.set(std::forward<F>(f)); } + template<typename F> void set_away_lambda(F &&f) { this->away_f_.set(std::forward<F>(f)); } + template<typename F> void set_is_on_lambda(F &&f) { this->is_on_f_.set(std::forward<F>(f)); } void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void set_restore_mode(TemplateWaterHeaterRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } @@ -49,6 +51,8 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater { TemplateLambda<float> current_temperature_f_; TemplateLambda<float> target_temperature_f_; TemplateLambda<water_heater::WaterHeaterMode> mode_f_; + TemplateLambda<bool> away_f_; + TemplateLambda<bool> is_on_f_; TemplateWaterHeaterRestoreMode restore_mode_{WATER_HEATER_NO_RESTORE}; water_heater::WaterHeaterModeMask supported_modes_; bool optimistic_{true}; diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index b8742f8c7b..e9ddfcf43e 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -13,6 +13,8 @@ esphome: id: template_water_heater target_temperature: 50.0 mode: ECO + away: false + is_on: true # Templated - water_heater.template.publish: @@ -20,6 +22,8 @@ esphome: current_temperature: !lambda "return 45.0;" target_temperature: !lambda "return 55.0;" mode: !lambda "return water_heater::WATER_HEATER_MODE_GAS;" + away: !lambda "return true;" + is_on: !lambda "return false;" # Test C++ API: set_template() with stateless lambda (no captures) # NOTE: set_template() is not intended to be a public API, but we test it to ensure it doesn't break. @@ -414,6 +418,8 @@ water_heater: current_temperature: !lambda "return 42.0f;" target_temperature: !lambda "return 60.0f;" mode: !lambda "return water_heater::WATER_HEATER_MODE_ECO;" + away: !lambda "return false;" + is_on: !lambda "return true;" supported_modes: - "OFF" - ECO diff --git a/tests/integration/fixtures/water_heater_template.yaml b/tests/integration/fixtures/water_heater_template.yaml index 1aaded1991..0c82ff68ce 100644 --- a/tests/integration/fixtures/water_heater_template.yaml +++ b/tests/integration/fixtures/water_heater_template.yaml @@ -4,6 +4,14 @@ host: api: logger: +globals: + - id: global_away + type: bool + initial_value: "false" + - id: global_is_on + type: bool + initial_value: "true" + water_heater: - platform: template id: test_boiler @@ -11,6 +19,8 @@ water_heater: optimistic: true current_temperature: !lambda "return 45.0f;" target_temperature: !lambda "return 60.0f;" + away: !lambda "return id(global_away);" + is_on: !lambda "return id(global_is_on);" # Note: No mode lambda - we want optimistic mode changes to stick # A mode lambda would override mode changes in loop() supported_modes: @@ -22,3 +32,8 @@ water_heater: min_temperature: 30.0 max_temperature: 85.0 target_temperature_step: 0.5 + set_action: + - lambda: |- + // Sync optimistic state back to globals so lambdas reflect the change + id(global_away) = id(test_boiler).is_away(); + id(global_is_on) = id(test_boiler).is_on(); diff --git a/tests/integration/test_water_heater_template.py b/tests/integration/test_water_heater_template.py index 6b4a685d0d..096d4c8461 100644 --- a/tests/integration/test_water_heater_template.py +++ b/tests/integration/test_water_heater_template.py @@ -5,7 +5,13 @@ from __future__ import annotations import asyncio import aioesphomeapi -from aioesphomeapi import WaterHeaterInfo, WaterHeaterMode, WaterHeaterState +from aioesphomeapi import ( + WaterHeaterFeature, + WaterHeaterInfo, + WaterHeaterMode, + WaterHeaterState, + WaterHeaterStateFlag, +) import pytest from .state_utils import InitialStateHelper @@ -22,18 +28,25 @@ async def test_water_heater_template( loop = asyncio.get_running_loop() async with run_compiled(yaml_config), api_client_connected() as client: states: dict[int, aioesphomeapi.EntityState] = {} - gas_mode_future: asyncio.Future[WaterHeaterState] = loop.create_future() - eco_mode_future: asyncio.Future[WaterHeaterState] = loop.create_future() + state_future: asyncio.Future[WaterHeaterState] | None = None def on_state(state: aioesphomeapi.EntityState) -> None: states[state.key] = state - if isinstance(state, WaterHeaterState): - # Wait for GAS mode - if state.mode == WaterHeaterMode.GAS and not gas_mode_future.done(): - gas_mode_future.set_result(state) - # Wait for ECO mode (we start at OFF, so test transitioning to ECO) - elif state.mode == WaterHeaterMode.ECO and not eco_mode_future.done(): - eco_mode_future.set_result(state) + if ( + isinstance(state, WaterHeaterState) + and state_future is not None + and not state_future.done() + ): + state_future.set_result(state) + + async def wait_for_state(timeout: float = 5.0) -> WaterHeaterState: + """Wait for next water heater state change.""" + nonlocal state_future + state_future = loop.create_future() + try: + return await asyncio.wait_for(state_future, timeout) + finally: + state_future = None # Get entities and set up state synchronization entities, services = await client.list_entities_services() @@ -89,24 +102,52 @@ async def test_water_heater_template( f"Expected target temp 60.0, got {initial_state.target_temperature}" ) + # Verify supported features: away mode and on/off (fixture has away + is_on lambdas) + assert ( + test_water_heater.supported_features & WaterHeaterFeature.SUPPORTS_AWAY_MODE + ) != 0, "Expected SUPPORTS_AWAY_MODE in supported_features" + assert ( + test_water_heater.supported_features & WaterHeaterFeature.SUPPORTS_ON_OFF + ) != 0, "Expected SUPPORTS_ON_OFF in supported_features" + + # Verify initial state: on (is_on lambda returns true), not away (away lambda returns false) + assert (initial_state.state & WaterHeaterStateFlag.ON) != 0, ( + "Expected initial state to include ON flag" + ) + assert (initial_state.state & WaterHeaterStateFlag.AWAY) == 0, ( + "Expected initial state to not include AWAY flag" + ) + + # Test turning on away mode + client.water_heater_command(test_water_heater.key, away=True) + away_on_state = await wait_for_state() + assert (away_on_state.state & WaterHeaterStateFlag.AWAY) != 0 + # ON flag should still be set (is_on lambda returns true) + assert (away_on_state.state & WaterHeaterStateFlag.ON) != 0 + + # Test turning off away mode + client.water_heater_command(test_water_heater.key, away=False) + away_off_state = await wait_for_state() + assert (away_off_state.state & WaterHeaterStateFlag.AWAY) == 0 + assert (away_off_state.state & WaterHeaterStateFlag.ON) != 0 + + # Test turning off (on=False) + client.water_heater_command(test_water_heater.key, on=False) + off_state = await wait_for_state() + assert (off_state.state & WaterHeaterStateFlag.ON) == 0 + assert (off_state.state & WaterHeaterStateFlag.AWAY) == 0 + + # Test turning back on (on=True) + client.water_heater_command(test_water_heater.key, on=True) + on_state = await wait_for_state() + assert (on_state.state & WaterHeaterStateFlag.ON) != 0 + # Test changing to GAS mode client.water_heater_command(test_water_heater.key, mode=WaterHeaterMode.GAS) - - try: - gas_state = await asyncio.wait_for(gas_mode_future, timeout=5.0) - except TimeoutError: - pytest.fail("GAS mode change not received within 5 seconds") - - assert isinstance(gas_state, WaterHeaterState) + gas_state = await wait_for_state() assert gas_state.mode == WaterHeaterMode.GAS # Test changing to ECO mode (from GAS) client.water_heater_command(test_water_heater.key, mode=WaterHeaterMode.ECO) - - try: - eco_state = await asyncio.wait_for(eco_mode_future, timeout=5.0) - except TimeoutError: - pytest.fail("ECO mode change not received within 5 seconds") - - assert isinstance(eco_state, WaterHeaterState) + eco_state = await wait_for_state() assert eco_state.mode == WaterHeaterMode.ECO From d4ccc64dc05da9ebf8fbba72b02cf3443585f37e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 08:55:59 -0600 Subject: [PATCH 0627/2030] [http_request] Fix IDF chunked response completion detection (#13886) --- .../components/http_request/http_request.h | 46 ++++++++++++++-- .../http_request/http_request_idf.cpp | 53 +++++++++++++------ .../http_request/http_request_idf.h | 1 + 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index c88360ca78..a427cc4a05 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -103,6 +103,42 @@ inline bool is_success(int const status) { return status >= HTTP_STATUS_OK && st * - ESP-IDF: blocking reads, 0 only returned when all content read * - Arduino: non-blocking, 0 means "no data yet" or "all content read" * + * Chunked responses that complete in a reasonable time work correctly on both + * platforms. The limitation below applies only to *streaming* chunked + * responses where data arrives slowly over a long period. + * + * Streaming chunked responses are NOT supported (all platforms): + * The read helpers (http_read_loop_result, http_read_fully) block the main + * event loop until all response data is received. For streaming responses + * where data trickles in slowly (e.g., TTS streaming via ffmpeg proxy), + * this starves the event loop on both ESP-IDF and Arduino. If data arrives + * just often enough to avoid the caller's timeout, the loop runs + * indefinitely. If data stops entirely, ESP-IDF fails with + * -ESP_ERR_HTTP_EAGAIN (transport timeout) while Arduino spins with + * delay(1) until the caller's timeout fires. Supporting streaming requires + * a non-blocking incremental read pattern that yields back to the event + * loop between chunks. Components that need streaming should use + * esp_http_client directly on a separate FreeRTOS task with + * esp_http_client_is_complete_data_received() for completion detection + * (see audio_reader.cpp for an example). + * + * Chunked transfer encoding - platform differences: + * - ESP-IDF HttpContainer: + * HttpContainerIDF overrides is_read_complete() to call + * esp_http_client_is_complete_data_received(), which is the + * authoritative completion check for both chunked and non-chunked + * transfers. When esp_http_client_read() returns 0 for a completed + * chunked response, read() returns 0 and is_read_complete() returns + * true, so callers get COMPLETE from http_read_loop_result(). + * + * - Arduino HttpContainer: + * Chunked responses are decoded internally (see + * HttpContainerArduino::read_chunked_()). When the final chunk arrives, + * is_chunked_ is cleared and content_length is set to bytes_read_. + * Completion is then detected via is_read_complete(), and a subsequent + * read() returns 0 to indicate "all content read" (not + * HTTP_ERROR_CONNECTION_CLOSED). + * * Use the helper functions below instead of checking return values directly: * - http_read_loop_result(): for manual loops with per-chunk processing * - http_read_fully(): for simple "read N bytes into buffer" operations @@ -204,9 +240,13 @@ class HttpContainer : public Parented<HttpRequestComponent> { size_t get_bytes_read() const { return this->bytes_read_; } - /// Check if all expected content has been read - /// For chunked responses, returns false (completion detected via read() returning error/EOF) - bool is_read_complete() const { + /// Check if all expected content has been read. + /// Base implementation handles non-chunked responses and status-code-based no-body checks. + /// Platform implementations may override for chunked completion detection: + /// - ESP-IDF: overrides to call esp_http_client_is_complete_data_received() for chunked. + /// - Arduino: read_chunked_() clears is_chunked_ and sets content_length on the final + /// chunk, after which the base implementation detects completion. + virtual bool is_read_complete() const { // Per RFC 9112, these responses have no body: // - 1xx (Informational), 204 No Content, 205 Reset Content, 304 Not Modified if ((this->status_code >= 100 && this->status_code < 200) || this->status_code == HTTP_STATUS_NO_CONTENT || diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index bd12b7d123..486984a694 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -218,32 +218,50 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c return container; } +bool HttpContainerIDF::is_read_complete() const { + // Base class handles no-body status codes and non-chunked content_length completion + if (HttpContainer::is_read_complete()) { + return true; + } + // For chunked responses, use the authoritative ESP-IDF completion check + return this->is_chunked_ && esp_http_client_is_complete_data_received(this->client_); +} + // ESP-IDF HTTP read implementation (blocking mode) // // WARNING: Return values differ from BSD sockets! See http_request.h for full documentation. // // esp_http_client_read() in blocking mode returns: // > 0: bytes read -// 0: connection closed (end of stream) +// 0: all chunked data received (is_chunk_complete true) or connection closed +// -ESP_ERR_HTTP_EAGAIN: transport timeout, no data available yet // < 0: error // // We normalize to HttpContainer::read() contract: // > 0: bytes read -// 0: all content read (only returned when content_length is known and fully read) +// 0: all content read (for both content_length-based and chunked completion) // < 0: error/connection closed // // Note on chunked transfer encoding: // esp_http_client_fetch_headers() returns 0 for chunked responses (no Content-Length header). -// We handle this by skipping the content_length check when content_length is 0, -// allowing esp_http_client_read() to handle chunked decoding internally and signal EOF -// by returning 0. +// When esp_http_client_read() returns 0 for a chunked response, is_read_complete() calls +// esp_http_client_is_complete_data_received() to distinguish successful completion from +// connection errors. Callers use http_read_loop_result() which checks is_read_complete() +// to return COMPLETE for successful chunked EOF. +// +// Streaming chunked responses are not supported (see http_request.h for details). +// When data stops arriving, esp_http_client_read() returns -ESP_ERR_HTTP_EAGAIN +// after its internal transport timeout (configured via timeout_ms) expires. +// This is passed through as a negative return value, which callers treat as an error. int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { const uint32_t start = millis(); watchdog::WatchdogManager wdm(this->parent_->get_watchdog_timeout()); - // Check if we've already read all expected content (non-chunked only) - // For chunked responses (content_length == 0), esp_http_client_read() handles EOF - if (this->is_read_complete()) { + // Check if we've already read all expected content (non-chunked and no-body only). + // Use the base class check here, NOT the override: esp_http_client_is_complete_data_received() + // returns true as soon as all data arrives from the network, but data may still be in + // the client's internal buffer waiting to be consumed by esp_http_client_read(). + if (HttpContainer::is_read_complete()) { return 0; // All content read successfully } @@ -258,15 +276,18 @@ int HttpContainerIDF::read(uint8_t *buf, size_t max_len) { return read_len_or_error; } - // esp_http_client_read() returns 0 in two cases: - // 1. Known content_length: connection closed before all data received (error) - // 2. Chunked encoding (content_length == 0): end of stream reached (EOF) - // For case 1, returning HTTP_ERROR_CONNECTION_CLOSED is correct. - // For case 2, 0 indicates that all chunked data has already been delivered - // in previous successful read() calls, so treating this as a closed - // connection does not cause any loss of response data. + // esp_http_client_read() returns 0 when: + // - Known content_length: connection closed before all data received (error) + // - Chunked encoding: all chunks received (is_chunk_complete true, genuine EOF) + // + // Return 0 in both cases. Callers use http_read_loop_result() which calls + // is_read_complete() to distinguish these: + // - Chunked complete: is_read_complete() returns true (via + // esp_http_client_is_complete_data_received()), caller gets COMPLETE + // - Non-chunked incomplete: is_read_complete() returns false, caller + // eventually gets TIMEOUT (since no more data arrives) if (read_len_or_error == 0) { - return HTTP_ERROR_CONNECTION_CLOSED; + return 0; } // Negative value - error, return the actual error code for debugging diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index ad11811a8f..2a130eae58 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -16,6 +16,7 @@ class HttpContainerIDF : public HttpContainer { HttpContainerIDF(esp_http_client_handle_t client) : client_(client) {} int read(uint8_t *buf, size_t max_len) override; void end() override; + bool is_read_complete() const override; /// @brief Feeds the watchdog timer if the executing task has one attached void feed_wdt(); From 298efb53400852a09e2f8bdf16feac9a58422059 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 10 Feb 2026 08:56:31 -0600 Subject: [PATCH 0628/2030] [resampler] Refactor for stability and to support Sendspin (#12254) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../components/resampler/speaker/__init__.py | 20 +- .../resampler/speaker/resampler_speaker.cpp | 245 +++++++++++++----- .../resampler/speaker/resampler_speaker.h | 24 +- 3 files changed, 203 insertions(+), 86 deletions(-) diff --git a/esphome/components/resampler/speaker/__init__.py b/esphome/components/resampler/speaker/__init__.py index 7036862d14..4e4705a889 100644 --- a/esphome/components/resampler/speaker/__init__.py +++ b/esphome/components/resampler/speaker/__init__.py @@ -1,5 +1,5 @@ import esphome.codegen as cg -from esphome.components import audio, esp32, speaker +from esphome.components import audio, esp32, socket, speaker import esphome.config_validation as cv from esphome.const import ( CONF_BITS_PER_SAMPLE, @@ -34,7 +34,7 @@ def _set_stream_limits(config): return config -def _validate_audio_compatability(config): +def _validate_audio_compatibility(config): inherit_property_from(CONF_BITS_PER_SAMPLE, CONF_OUTPUT_SPEAKER)(config) inherit_property_from(CONF_NUM_CHANNELS, CONF_OUTPUT_SPEAKER)(config) inherit_property_from(CONF_SAMPLE_RATE, CONF_OUTPUT_SPEAKER)(config) @@ -73,10 +73,13 @@ CONFIG_SCHEMA = cv.All( ) -FINAL_VALIDATE_SCHEMA = _validate_audio_compatability +FINAL_VALIDATE_SCHEMA = _validate_audio_compatibility async def to_code(config): + # Enable wake_loop_threadsafe for immediate command processing from other tasks + socket.require_wake_loop_threadsafe() + var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await speaker.register_speaker(var, config) @@ -86,12 +89,11 @@ async def to_code(config): cg.add(var.set_buffer_duration(config[CONF_BUFFER_DURATION])) - if task_stack_in_psram := config.get(CONF_TASK_STACK_IN_PSRAM): - cg.add(var.set_task_stack_in_psram(task_stack_in_psram)) - if task_stack_in_psram and config[CONF_TASK_STACK_IN_PSRAM]: - esp32.add_idf_sdkconfig_option( - "CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True - ) + if config.get(CONF_TASK_STACK_IN_PSRAM): + cg.add(var.set_task_stack_in_psram(True)) + esp32.add_idf_sdkconfig_option( + "CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY", True + ) cg.add(var.set_target_bits_per_sample(config[CONF_BITS_PER_SAMPLE])) cg.add(var.set_target_sample_rate(config[CONF_SAMPLE_RATE])) diff --git a/esphome/components/resampler/speaker/resampler_speaker.cpp b/esphome/components/resampler/speaker/resampler_speaker.cpp index ad61aca084..74420f906a 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.cpp +++ b/esphome/components/resampler/speaker/resampler_speaker.cpp @@ -4,6 +4,8 @@ #include "esphome/components/audio/audio_resampler.h" +#include "esphome/core/application.h" +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -17,13 +19,17 @@ static const UBaseType_t RESAMPLER_TASK_PRIORITY = 1; static const uint32_t TRANSFER_BUFFER_DURATION_MS = 50; -static const uint32_t TASK_DELAY_MS = 20; static const uint32_t TASK_STACK_SIZE = 3072; +static const uint32_t STATE_TRANSITION_TIMEOUT_MS = 5000; + static const char *const TAG = "resampler_speaker"; enum ResamplingEventGroupBits : uint32_t { - COMMAND_STOP = (1 << 0), // stops the resampler task + COMMAND_STOP = (1 << 0), // signals stop request + COMMAND_START = (1 << 1), // signals start request + COMMAND_FINISH = (1 << 2), // signals finish request (graceful stop) + TASK_COMMAND_STOP = (1 << 5), // signals the task to stop STATE_STARTING = (1 << 10), STATE_RUNNING = (1 << 11), STATE_STOPPING = (1 << 12), @@ -34,9 +40,16 @@ enum ResamplingEventGroupBits : uint32_t { ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits }; +void ResamplerSpeaker::dump_config() { + ESP_LOGCONFIG(TAG, + "Resampler Speaker:\n" + " Target Bits Per Sample: %u\n" + " Target Sample Rate: %" PRIu32 " Hz", + this->target_bits_per_sample_, this->target_sample_rate_); +} + void ResamplerSpeaker::setup() { this->event_group_ = xEventGroupCreate(); - if (this->event_group_ == nullptr) { ESP_LOGE(TAG, "Failed to create event group"); this->mark_failed(); @@ -55,81 +68,155 @@ void ResamplerSpeaker::setup() { this->audio_output_callback_(new_frames, write_timestamp); } }); + + // Start with loop disabled since no task is running and no commands are pending + this->disable_loop(); } void ResamplerSpeaker::loop() { uint32_t event_group_bits = xEventGroupGetBits(this->event_group_); + // Process commands with priority: STOP > FINISH > START + // This ensures stop commands take precedence over conflicting start commands + if (event_group_bits & ResamplingEventGroupBits::COMMAND_STOP) { + if (this->state_ == speaker::STATE_RUNNING || this->state_ == speaker::STATE_STARTING) { + // Clear STOP, START, and FINISH bits - stop takes precedence + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_STOP | + ResamplingEventGroupBits::COMMAND_START | + ResamplingEventGroupBits::COMMAND_FINISH); + this->waiting_for_output_ = false; + this->enter_stopping_state_(); + } else if (this->state_ == speaker::STATE_STOPPED) { + // Already stopped, just clear the command bits + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_STOP | + ResamplingEventGroupBits::COMMAND_START | + ResamplingEventGroupBits::COMMAND_FINISH); + } + // Leave bits set if STATE_STOPPING - will be processed once stopped + } else if (event_group_bits & ResamplingEventGroupBits::COMMAND_FINISH) { + if (this->state_ == speaker::STATE_RUNNING) { + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_FINISH); + this->output_speaker_->finish(); + } else if (this->state_ == speaker::STATE_STOPPED) { + // Already stopped, just clear the command bit + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_FINISH); + } + // Leave bit set if transitioning states - will be processed once state allows + } else if (event_group_bits & ResamplingEventGroupBits::COMMAND_START) { + if (this->state_ == speaker::STATE_STOPPED) { + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_START); + this->state_ = speaker::STATE_STARTING; + } else if (this->state_ == speaker::STATE_RUNNING) { + // Already running, just clear the command bit + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::COMMAND_START); + } + // Leave bit set if transitioning states - will be processed once state allows + } + + // Re-read bits after command processing (enter_stopping_state_ may have set task bits) + event_group_bits = xEventGroupGetBits(this->event_group_); + if (event_group_bits & ResamplingEventGroupBits::STATE_STARTING) { - ESP_LOGD(TAG, "Starting resampler task"); + ESP_LOGD(TAG, "Starting"); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_STARTING); } if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NO_MEM) { - this->status_set_error(LOG_STR("Resampler task failed to allocate the internal buffers")); + this->status_set_error(LOG_STR("Not enough memory")); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM); - this->state_ = speaker::STATE_STOPPING; + this->enter_stopping_state_(); } if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED) { - this->status_set_error(LOG_STR("Cannot resample due to an unsupported audio stream")); + this->status_set_error(LOG_STR("Unsupported stream")); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED); - this->state_ = speaker::STATE_STOPPING; + this->enter_stopping_state_(); } if (event_group_bits & ResamplingEventGroupBits::ERR_ESP_FAIL) { - this->status_set_error(LOG_STR("Resampler task failed")); + this->status_set_error(LOG_STR("Resampler failure")); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL); - this->state_ = speaker::STATE_STOPPING; + this->enter_stopping_state_(); } if (event_group_bits & ResamplingEventGroupBits::STATE_RUNNING) { - ESP_LOGD(TAG, "Started resampler task"); + ESP_LOGV(TAG, "Started"); this->status_clear_error(); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_RUNNING); } if (event_group_bits & ResamplingEventGroupBits::STATE_STOPPING) { - ESP_LOGD(TAG, "Stopping resampler task"); + ESP_LOGV(TAG, "Stopping"); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_STOPPING); } if (event_group_bits & ResamplingEventGroupBits::STATE_STOPPED) { - if (this->delete_task_() == ESP_OK) { - ESP_LOGD(TAG, "Stopped resampler task"); - xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ALL_BITS); - } + this->delete_task_(); + ESP_LOGD(TAG, "Stopped"); + xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ALL_BITS); } switch (this->state_) { case speaker::STATE_STARTING: { - esp_err_t err = this->start_(); - if (err == ESP_OK) { - this->status_clear_error(); - this->state_ = speaker::STATE_RUNNING; + if (!this->waiting_for_output_) { + esp_err_t err = this->start_(); + if (err == ESP_OK) { + this->callback_remainder_ = 0; // reset callback remainder + this->status_clear_error(); + this->waiting_for_output_ = true; + this->state_start_ms_ = App.get_loop_component_start_time(); + } else { + this->set_start_error_(err); + this->waiting_for_output_ = false; + this->enter_stopping_state_(); + } } else { - switch (err) { - case ESP_ERR_INVALID_STATE: - this->status_set_error(LOG_STR("Failed to start resampler: resampler task failed to start")); - break; - case ESP_ERR_NO_MEM: - this->status_set_error(LOG_STR("Failed to start resampler: not enough memory for task stack")); - default: - this->status_set_error(LOG_STR("Failed to start resampler")); - break; + if (this->output_speaker_->is_running()) { + this->state_ = speaker::STATE_RUNNING; + this->waiting_for_output_ = false; + } else if ((App.get_loop_component_start_time() - this->state_start_ms_) > STATE_TRANSITION_TIMEOUT_MS) { + // Timed out waiting for the output speaker to start + this->waiting_for_output_ = false; + this->enter_stopping_state_(); } - - this->state_ = speaker::STATE_STOPPING; } break; } case speaker::STATE_RUNNING: if (this->output_speaker_->is_stopped()) { - this->state_ = speaker::STATE_STOPPING; + this->enter_stopping_state_(); + } + break; + case speaker::STATE_STOPPING: { + if ((this->output_speaker_->get_pause_state()) || + ((App.get_loop_component_start_time() - this->state_start_ms_) > STATE_TRANSITION_TIMEOUT_MS)) { + // If output speaker is paused or stopping timeout exceeded, force stop + this->output_speaker_->stop(); } + if (this->output_speaker_->is_stopped() && (this->task_handle_ == nullptr)) { + // Only transition to stopped state once the output speaker and resampler task are fully stopped + this->waiting_for_output_ = false; + this->state_ = speaker::STATE_STOPPED; + } break; - case speaker::STATE_STOPPING: - this->stop_(); - this->state_ = speaker::STATE_STOPPED; - break; + } case speaker::STATE_STOPPED: + event_group_bits = xEventGroupGetBits(this->event_group_); + if (event_group_bits == 0) { + // No pending events, disable loop to save CPU cycles + this->disable_loop(); + } + break; + } +} + +void ResamplerSpeaker::set_start_error_(esp_err_t err) { + switch (err) { + case ESP_ERR_INVALID_STATE: + this->status_set_error(LOG_STR("Task failed to start")); + break; + case ESP_ERR_NO_MEM: + this->status_set_error(LOG_STR("Not enough memory")); + break; + default: + this->status_set_error(LOG_STR("Failed to start")); break; } } @@ -143,16 +230,33 @@ size_t ResamplerSpeaker::play(const uint8_t *data, size_t length, TickType_t tic if ((this->output_speaker_->is_running()) && (!this->requires_resampling_())) { bytes_written = this->output_speaker_->play(data, length, ticks_to_wait); } else { - if (this->ring_buffer_.use_count() == 1) { - std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + if (temp_ring_buffer) { + // Only write to the ring buffer if the reference is valid bytes_written = temp_ring_buffer->write_without_replacement(data, length, ticks_to_wait); + } else { + // Delay to avoid repeatedly hammering while waiting for the speaker to start + vTaskDelay(ticks_to_wait); } } return bytes_written; } -void ResamplerSpeaker::start() { this->state_ = speaker::STATE_STARTING; } +void ResamplerSpeaker::send_command_(uint32_t command_bit, bool wake_loop) { + this->enable_loop_soon_any_context(); + uint32_t event_bits = xEventGroupGetBits(this->event_group_); + if (!(event_bits & command_bit)) { + xEventGroupSetBits(this->event_group_, command_bit); +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + if (wake_loop) { + App.wake_loop_threadsafe(); + } +#endif + } +} + +void ResamplerSpeaker::start() { this->send_command_(ResamplingEventGroupBits::COMMAND_START, true); } esp_err_t ResamplerSpeaker::start_() { this->target_stream_info_ = audio::AudioStreamInfo( @@ -185,7 +289,7 @@ esp_err_t ResamplerSpeaker::start_task_() { } if (this->task_handle_ == nullptr) { - this->task_handle_ = xTaskCreateStatic(resample_task, "sample", TASK_STACK_SIZE, (void *) this, + this->task_handle_ = xTaskCreateStatic(resample_task, "resampler", TASK_STACK_SIZE, (void *) this, RESAMPLER_TASK_PRIORITY, this->task_stack_buffer_, &this->task_stack_); } @@ -196,43 +300,47 @@ esp_err_t ResamplerSpeaker::start_task_() { return ESP_OK; } -void ResamplerSpeaker::stop() { this->state_ = speaker::STATE_STOPPING; } +void ResamplerSpeaker::stop() { this->send_command_(ResamplingEventGroupBits::COMMAND_STOP); } -void ResamplerSpeaker::stop_() { +void ResamplerSpeaker::enter_stopping_state_() { + this->state_ = speaker::STATE_STOPPING; + this->state_start_ms_ = App.get_loop_component_start_time(); if (this->task_handle_ != nullptr) { - xEventGroupSetBits(this->event_group_, ResamplingEventGroupBits::COMMAND_STOP); + xEventGroupSetBits(this->event_group_, ResamplingEventGroupBits::TASK_COMMAND_STOP); } this->output_speaker_->stop(); } -esp_err_t ResamplerSpeaker::delete_task_() { - if (!this->task_created_) { +void ResamplerSpeaker::delete_task_() { + if (this->task_handle_ != nullptr) { + // Delete the suspended task + vTaskDelete(this->task_handle_); this->task_handle_ = nullptr; - - if (this->task_stack_buffer_ != nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } - - this->task_stack_buffer_ = nullptr; - } - - return ESP_OK; } - return ESP_ERR_INVALID_STATE; + if (this->task_stack_buffer_ != nullptr) { + // Deallocate the task stack buffer + if (this->task_stack_in_psram_) { + RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); + stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); + } else { + RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); + stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); + } + + this->task_stack_buffer_ = nullptr; + } } -void ResamplerSpeaker::finish() { this->output_speaker_->finish(); } +void ResamplerSpeaker::finish() { this->send_command_(ResamplingEventGroupBits::COMMAND_FINISH); } bool ResamplerSpeaker::has_buffered_data() const { bool has_ring_buffer_data = false; - if (this->requires_resampling_() && (this->ring_buffer_.use_count() > 0)) { - has_ring_buffer_data = (this->ring_buffer_.lock()->available() > 0); + if (this->requires_resampling_()) { + std::shared_ptr<RingBuffer> temp_ring_buffer = this->ring_buffer_.lock(); + if (temp_ring_buffer) { + has_ring_buffer_data = (temp_ring_buffer->available() > 0); + } } return (has_ring_buffer_data || this->output_speaker_->has_buffered_data()); } @@ -253,9 +361,8 @@ bool ResamplerSpeaker::requires_resampling_() const { } void ResamplerSpeaker::resample_task(void *params) { - ResamplerSpeaker *this_resampler = (ResamplerSpeaker *) params; + ResamplerSpeaker *this_resampler = static_cast<ResamplerSpeaker *>(params); - this_resampler->task_created_ = true; xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STARTING); std::unique_ptr<audio::AudioResampler> resampler = @@ -269,7 +376,7 @@ void ResamplerSpeaker::resample_task(void *params) { std::shared_ptr<RingBuffer> temp_ring_buffer = RingBuffer::create(this_resampler->audio_stream_info_.ms_to_bytes(this_resampler->buffer_duration_ms_)); - if (temp_ring_buffer.use_count() == 0) { + if (!temp_ring_buffer) { err = ESP_ERR_NO_MEM; } else { this_resampler->ring_buffer_ = temp_ring_buffer; @@ -291,7 +398,7 @@ void ResamplerSpeaker::resample_task(void *params) { while (err == ESP_OK) { uint32_t event_bits = xEventGroupGetBits(this_resampler->event_group_); - if (event_bits & ResamplingEventGroupBits::COMMAND_STOP) { + if (event_bits & ResamplingEventGroupBits::TASK_COMMAND_STOP) { break; } @@ -310,8 +417,8 @@ void ResamplerSpeaker::resample_task(void *params) { xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPING); resampler.reset(); xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPED); - this_resampler->task_created_ = false; - vTaskDelete(nullptr); + + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } } // namespace resampler diff --git a/esphome/components/resampler/speaker/resampler_speaker.h b/esphome/components/resampler/speaker/resampler_speaker.h index 810087ab7f..c1ebd7e7b5 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.h +++ b/esphome/components/resampler/speaker/resampler_speaker.h @@ -8,14 +8,16 @@ #include "esphome/core/component.h" -#include <freertos/event_groups.h> #include <freertos/FreeRTOS.h> +#include <freertos/event_groups.h> namespace esphome { namespace resampler { class ResamplerSpeaker : public Component, public speaker::Speaker { public: + float get_setup_priority() const override { return esphome::setup_priority::DATA; } + void dump_config() override; void setup() override; void loop() override; @@ -65,13 +67,18 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { /// ESP_ERR_INVALID_STATE if the task wasn't created esp_err_t start_task_(); - /// @brief Stops the output speaker. If the resampling task is running, it sends the stop command. - void stop_(); + /// @brief Transitions to STATE_STOPPING, records the stopping timestamp, sends the task stop command if the task is + /// running, and stops the output speaker. + void enter_stopping_state_(); - /// @brief Deallocates the task stack and resets the pointers. - /// @return ESP_OK if successful - /// ESP_ERR_INVALID_STATE if the task hasn't stopped itself - esp_err_t delete_task_(); + /// @brief Sets the appropriate status error based on the start failure reason. + void set_start_error_(esp_err_t err); + + /// @brief Deletes the resampler task if suspended, deallocates the task stack, and resets the related pointers. + void delete_task_(); + + /// @brief Sends a command via event group bits, enables the loop, and optionally wakes the main loop. + void send_command_(uint32_t command_bit, bool wake_loop = false); inline bool requires_resampling_() const; static void resample_task(void *params); @@ -83,7 +90,7 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { speaker::Speaker *output_speaker_{nullptr}; bool task_stack_in_psram_{false}; - bool task_created_{false}; + bool waiting_for_output_{false}; TaskHandle_t task_handle_{nullptr}; StaticTask_t task_stack_; @@ -98,6 +105,7 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { uint32_t target_sample_rate_; uint32_t buffer_duration_ms_; + uint32_t state_start_ms_{0}; uint64_t callback_remainder_{0}; }; From 13a124c86d3c6944d4fb27462c4a98a2bc553881 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:10:27 -0500 Subject: [PATCH 0629/2030] [pulse_counter] Migrate from legacy PCNT API to new ESP-IDF 5.x API (#13904) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 1 + esphome/components/hlw8012/sensor.py | 5 +- .../pulse_counter/pulse_counter_sensor.cpp | 113 ++++++++++-------- .../pulse_counter/pulse_counter_sensor.h | 21 ++-- esphome/components/pulse_counter/sensor.py | 5 +- 5 files changed, 72 insertions(+), 73 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 6f5011246c..8c052acc87 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -135,6 +135,7 @@ DEFAULT_EXCLUDED_IDF_COMPONENTS = ( "esp_driver_dac", # DAC driver - only needed by esp32_dac component "esp_driver_i2s", # I2S driver - only needed by i2s_audio component "esp_driver_mcpwm", # MCPWM driver - ESPHome doesn't use motor control PWM + "esp_driver_pcnt", # PCNT driver - only needed by pulse_counter, hlw8012 components "esp_driver_rmt", # RMT driver - only needed by remote_transmitter/receiver, neopixelbus "esp_driver_touch_sens", # Touch sensor driver - only needed by esp32_touch "esp_driver_twai", # TWAI/CAN driver - only needed by esp32_can component diff --git a/esphome/components/hlw8012/sensor.py b/esphome/components/hlw8012/sensor.py index 4727877633..1d793ac6b1 100644 --- a/esphome/components/hlw8012/sensor.py +++ b/esphome/components/hlw8012/sensor.py @@ -94,10 +94,7 @@ CONFIG_SCHEMA = cv.Schema( async def to_code(config): if CORE.is_esp32: - # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) - # HLW8012 uses pulse_counter's PCNT storage which requires driver/pcnt.h - # TODO: Remove this once pulse_counter migrates to new PCNT API (driver/pulse_cnt.h) - include_builtin_idf_component("driver") + include_builtin_idf_component("esp_driver_pcnt") var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index c0d74cef4a..ef4cc980f6 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -1,6 +1,11 @@ #include "pulse_counter_sensor.h" #include "esphome/core/log.h" +#ifdef HAS_PCNT +#include <esp_private/esp_clk.h> +#include <hal/pcnt_ll.h> +#endif + namespace esphome { namespace pulse_counter { @@ -56,103 +61,107 @@ pulse_counter_t BasicPulseCounterStorage::read_raw_value() { #ifdef HAS_PCNT bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { - static pcnt_unit_t next_pcnt_unit = PCNT_UNIT_0; - static pcnt_channel_t next_pcnt_channel = PCNT_CHANNEL_0; this->pin = pin; this->pin->setup(); - this->pcnt_unit = next_pcnt_unit; - this->pcnt_channel = next_pcnt_channel; - next_pcnt_unit = pcnt_unit_t(int(next_pcnt_unit) + 1); - if (int(next_pcnt_unit) >= PCNT_UNIT_0 + PCNT_UNIT_MAX) { - next_pcnt_unit = PCNT_UNIT_0; - next_pcnt_channel = pcnt_channel_t(int(next_pcnt_channel) + 1); + + pcnt_unit_config_t unit_config = { + .low_limit = INT16_MIN, + .high_limit = INT16_MAX, + .flags = {.accum_count = true}, + }; + esp_err_t error = pcnt_new_unit(&unit_config, &this->pcnt_unit); + if (error != ESP_OK) { + ESP_LOGE(TAG, "Creating PCNT unit failed: %s", esp_err_to_name(error)); + return false; } - ESP_LOGCONFIG(TAG, - " PCNT Unit Number: %u\n" - " PCNT Channel Number: %u", - this->pcnt_unit, this->pcnt_channel); + pcnt_chan_config_t chan_config = { + .edge_gpio_num = this->pin->get_pin(), + .level_gpio_num = -1, + }; + error = pcnt_new_channel(this->pcnt_unit, &chan_config, &this->pcnt_channel); + if (error != ESP_OK) { + ESP_LOGE(TAG, "Creating PCNT channel failed: %s", esp_err_to_name(error)); + return false; + } - pcnt_count_mode_t rising = PCNT_COUNT_DIS, falling = PCNT_COUNT_DIS; + pcnt_channel_edge_action_t rising = PCNT_CHANNEL_EDGE_ACTION_HOLD; + pcnt_channel_edge_action_t falling = PCNT_CHANNEL_EDGE_ACTION_HOLD; switch (this->rising_edge_mode) { case PULSE_COUNTER_DISABLE: - rising = PCNT_COUNT_DIS; + rising = PCNT_CHANNEL_EDGE_ACTION_HOLD; break; case PULSE_COUNTER_INCREMENT: - rising = PCNT_COUNT_INC; + rising = PCNT_CHANNEL_EDGE_ACTION_INCREASE; break; case PULSE_COUNTER_DECREMENT: - rising = PCNT_COUNT_DEC; + rising = PCNT_CHANNEL_EDGE_ACTION_DECREASE; break; } switch (this->falling_edge_mode) { case PULSE_COUNTER_DISABLE: - falling = PCNT_COUNT_DIS; + falling = PCNT_CHANNEL_EDGE_ACTION_HOLD; break; case PULSE_COUNTER_INCREMENT: - falling = PCNT_COUNT_INC; + falling = PCNT_CHANNEL_EDGE_ACTION_INCREASE; break; case PULSE_COUNTER_DECREMENT: - falling = PCNT_COUNT_DEC; + falling = PCNT_CHANNEL_EDGE_ACTION_DECREASE; break; } - pcnt_config_t pcnt_config = { - .pulse_gpio_num = this->pin->get_pin(), - .ctrl_gpio_num = PCNT_PIN_NOT_USED, - .lctrl_mode = PCNT_MODE_KEEP, - .hctrl_mode = PCNT_MODE_KEEP, - .pos_mode = rising, - .neg_mode = falling, - .counter_h_lim = 0, - .counter_l_lim = 0, - .unit = this->pcnt_unit, - .channel = this->pcnt_channel, - }; - esp_err_t error = pcnt_unit_config(&pcnt_config); + error = pcnt_channel_set_edge_action(this->pcnt_channel, rising, falling); if (error != ESP_OK) { - ESP_LOGE(TAG, "Configuring Pulse Counter failed: %s", esp_err_to_name(error)); + ESP_LOGE(TAG, "Setting PCNT edge action failed: %s", esp_err_to_name(error)); return false; } if (this->filter_us != 0) { - uint16_t filter_val = std::min(static_cast<unsigned int>(this->filter_us * 80u), 1023u); - ESP_LOGCONFIG(TAG, " Filter Value: %" PRIu32 "us (val=%u)", this->filter_us, filter_val); - error = pcnt_set_filter_value(this->pcnt_unit, filter_val); + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); + pcnt_glitch_filter_config_t filter_config = { + .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), + }; + error = pcnt_unit_set_glitch_filter(this->pcnt_unit, &filter_config); if (error != ESP_OK) { - ESP_LOGE(TAG, "Setting filter value failed: %s", esp_err_to_name(error)); - return false; - } - error = pcnt_filter_enable(this->pcnt_unit); - if (error != ESP_OK) { - ESP_LOGE(TAG, "Enabling filter failed: %s", esp_err_to_name(error)); + ESP_LOGE(TAG, "Setting PCNT glitch filter failed: %s", esp_err_to_name(error)); return false; } } - error = pcnt_counter_pause(this->pcnt_unit); + error = pcnt_unit_add_watch_point(this->pcnt_unit, INT16_MIN); if (error != ESP_OK) { - ESP_LOGE(TAG, "Pausing pulse counter failed: %s", esp_err_to_name(error)); + ESP_LOGE(TAG, "Adding PCNT low limit watch point failed: %s", esp_err_to_name(error)); return false; } - error = pcnt_counter_clear(this->pcnt_unit); + error = pcnt_unit_add_watch_point(this->pcnt_unit, INT16_MAX); if (error != ESP_OK) { - ESP_LOGE(TAG, "Clearing pulse counter failed: %s", esp_err_to_name(error)); + ESP_LOGE(TAG, "Adding PCNT high limit watch point failed: %s", esp_err_to_name(error)); return false; } - error = pcnt_counter_resume(this->pcnt_unit); + + error = pcnt_unit_enable(this->pcnt_unit); if (error != ESP_OK) { - ESP_LOGE(TAG, "Resuming pulse counter failed: %s", esp_err_to_name(error)); + ESP_LOGE(TAG, "Enabling PCNT unit failed: %s", esp_err_to_name(error)); + return false; + } + error = pcnt_unit_clear_count(this->pcnt_unit); + if (error != ESP_OK) { + ESP_LOGE(TAG, "Clearing PCNT unit failed: %s", esp_err_to_name(error)); + return false; + } + error = pcnt_unit_start(this->pcnt_unit); + if (error != ESP_OK) { + ESP_LOGE(TAG, "Starting PCNT unit failed: %s", esp_err_to_name(error)); return false; } return true; } pulse_counter_t HwPulseCounterStorage::read_raw_value() { - pulse_counter_t counter; - pcnt_get_counter_value(this->pcnt_unit, &counter); - pulse_counter_t ret = counter - this->last_value; - this->last_value = counter; + int count; + pcnt_unit_get_count(this->pcnt_unit, &count); + pulse_counter_t ret = count - this->last_value; + this->last_value = count; return ret; } #endif // HAS_PCNT diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index f906e9e5cb..a7913d5d66 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -6,14 +6,13 @@ #include <cinttypes> -// TODO: Migrate from legacy PCNT API (driver/pcnt.h) to new PCNT API (driver/pulse_cnt.h) -// The legacy PCNT API is deprecated in ESP-IDF 5.x. Migration would allow removing the -// "driver" IDF component dependency. See: -// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/peripherals.html#id6 -#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) -#include <driver/pcnt.h> +#if defined(USE_ESP32) +#include <soc/soc_caps.h> +#ifdef SOC_PCNT_SUPPORTED +#include <driver/pulse_cnt.h> #define HAS_PCNT -#endif // defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) +#endif // SOC_PCNT_SUPPORTED +#endif // USE_ESP32 namespace esphome { namespace pulse_counter { @@ -24,11 +23,7 @@ enum PulseCounterCountMode { PULSE_COUNTER_DECREMENT, }; -#ifdef HAS_PCNT -using pulse_counter_t = int16_t; -#else // HAS_PCNT using pulse_counter_t = int32_t; -#endif // HAS_PCNT struct PulseCounterStorageBase { virtual bool pulse_counter_setup(InternalGPIOPin *pin) = 0; @@ -58,8 +53,8 @@ struct HwPulseCounterStorage : public PulseCounterStorageBase { bool pulse_counter_setup(InternalGPIOPin *pin) override; pulse_counter_t read_raw_value() override; - pcnt_unit_t pcnt_unit; - pcnt_channel_t pcnt_channel; + pcnt_unit_handle_t pcnt_unit{nullptr}; + pcnt_channel_handle_t pcnt_channel{nullptr}; }; #endif // HAS_PCNT diff --git a/esphome/components/pulse_counter/sensor.py b/esphome/components/pulse_counter/sensor.py index 65be5ee793..0124463567 100644 --- a/esphome/components/pulse_counter/sensor.py +++ b/esphome/components/pulse_counter/sensor.py @@ -129,10 +129,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): use_pcnt = config.get(CONF_USE_PCNT) if CORE.is_esp32 and use_pcnt: - # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) - # Provides driver/pcnt.h header for hardware pulse counter API - # TODO: Remove this once pulse_counter migrates to new PCNT API (driver/pulse_cnt.h) - include_builtin_idf_component("driver") + include_builtin_idf_component("esp_driver_pcnt") var = await sensor.new_sensor(config, use_pcnt) await cg.register_component(var, config) From 03b41855f5137bf54adc859084baf5a1171ad92a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:03:26 -0500 Subject: [PATCH 0630/2030] [esp32_hosted] Bump esp_wifi_remote and esp_hosted versions (#13911) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_hosted/__init__.py | 4 ++-- esphome/idf_component.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 170f436f02..287c780769 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -95,9 +95,9 @@ async def to_code(config): framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] os.environ["ESP_IDF_VERSION"] = f"{framework_ver.major}.{framework_ver.minor}" if framework_ver >= cv.Version(5, 5, 0): - esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.2.4") + esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.3.2") esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") - esp32.add_idf_component(name="espressif/esp_hosted", ref="2.9.3") + esp32.add_idf_component(name="espressif/esp_hosted", ref="2.11.5") else: esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0") esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index b4a2c9b909..f39ea9b3ae 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -10,7 +10,7 @@ dependencies: espressif/mdns: version: 1.9.1 espressif/esp_wifi_remote: - version: 1.2.4 + version: 1.3.2 rules: - if: "target in [esp32h2, esp32p4]" espressif/eppp_link: @@ -18,7 +18,7 @@ dependencies: rules: - if: "target in [esp32h2, esp32p4]" espressif/esp_hosted: - version: 2.9.3 + version: 2.11.5 rules: - if: "target in [esp32h2, esp32p4]" zorxx/multipart-parser: From c4b109eebd223ea73736bd85d972362fb5c81ad0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:09:56 -0500 Subject: [PATCH 0631/2030] [esp32_rmt_led_strip, remote_receiver, pulse_counter] Replace hardcoded clock frequencies with runtime queries (#13908) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../esp32_rmt_led_strip/led_strip.cpp | 23 +++++++++++-------- .../pulse_counter/pulse_counter_sensor.cpp | 6 +++-- .../remote_receiver/remote_receiver_esp32.cpp | 11 ++++----- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 4ca0b998b1..8bb5cbb62e 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -7,22 +7,25 @@ #include "esphome/core/log.h" #include <esp_attr.h> +#include <esp_clk_tree.h> namespace esphome { namespace esp32_rmt_led_strip { static const char *const TAG = "esp32_rmt_led_strip"; -#ifdef USE_ESP32_VARIANT_ESP32H2 -static const uint32_t RMT_CLK_FREQ = 32000000; -static const uint8_t RMT_CLK_DIV = 1; -#else -static const uint32_t RMT_CLK_FREQ = 80000000; -static const uint8_t RMT_CLK_DIV = 2; -#endif - static const size_t RMT_SYMBOLS_PER_BYTE = 8; +// Query the RMT default clock source frequency. This varies by variant: +// APB (80MHz) on ESP32/S2/S3/C3, PLL_F80M (80MHz) on C6/P4, XTAL (32MHz) on H2. +// Worst-case reset time is WS2811 at 300µs = 24000 ticks at 80MHz, well within +// the 15-bit rmt_symbol_word_t duration field max of 32767. +static uint32_t rmt_resolution_hz() { + uint32_t freq; + esp_clk_tree_src_get_freq_hz((soc_module_clk_t) RMT_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &freq); + return freq; +} + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) static size_t IRAM_ATTR HOT encoder_callback(const void *data, size_t size, size_t symbols_written, size_t symbols_free, rmt_symbol_word_t *symbols, bool *done, void *arg) { @@ -92,7 +95,7 @@ void ESP32RMTLEDStripLightOutput::setup() { rmt_tx_channel_config_t channel; memset(&channel, 0, sizeof(channel)); channel.clk_src = RMT_CLK_SRC_DEFAULT; - channel.resolution_hz = RMT_CLK_FREQ / RMT_CLK_DIV; + channel.resolution_hz = rmt_resolution_hz(); channel.gpio_num = gpio_num_t(this->pin_); channel.mem_block_symbols = this->rmt_symbols_; channel.trans_queue_depth = 1; @@ -137,7 +140,7 @@ void ESP32RMTLEDStripLightOutput::setup() { void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bit0_low, uint32_t bit1_high, uint32_t bit1_low, uint32_t reset_time_high, uint32_t reset_time_low) { - float ratio = (float) RMT_CLK_FREQ / RMT_CLK_DIV / 1e09f; + float ratio = (float) rmt_resolution_hz() / 1e09f; // 0-bit this->params_.bit0.duration0 = (uint32_t) (ratio * bit0_high); diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index ef4cc980f6..8ac5a28d8f 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -2,7 +2,7 @@ #include "esphome/core/log.h" #ifdef HAS_PCNT -#include <esp_private/esp_clk.h> +#include <esp_clk_tree.h> #include <hal/pcnt_ll.h> #endif @@ -117,7 +117,9 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } if (this->filter_us != 0) { - uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); + uint32_t apb_freq; + esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_APB, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &apb_freq); + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / apb_freq; pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), }; diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index eda8365169..f95244ea45 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -3,15 +3,11 @@ #ifdef USE_ESP32 #include <driver/gpio.h> +#include <esp_clk_tree.h> namespace esphome::remote_receiver { static const char *const TAG = "remote_receiver.esp32"; -#ifdef USE_ESP32_VARIANT_ESP32H2 -static const uint32_t RMT_CLK_FREQ = 32000000; -#else -static const uint32_t RMT_CLK_FREQ = 80000000; -#endif static bool IRAM_ATTR HOT rmt_callback(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *event, void *arg) { RemoteReceiverComponentStore *store = (RemoteReceiverComponentStore *) arg; @@ -98,7 +94,10 @@ void RemoteReceiverComponent::setup() { } uint32_t event_size = sizeof(rmt_rx_done_event_data_t); - uint32_t max_filter_ns = 255u * 1000 / (RMT_CLK_FREQ / 1000000); + uint32_t rmt_freq; + esp_clk_tree_src_get_freq_hz((soc_module_clk_t) RMT_CLK_SRC_DEFAULT, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &rmt_freq); + uint32_t max_filter_ns = UINT8_MAX * 1000u / (rmt_freq / 1000000); memset(&this->store_.config, 0, sizeof(this->store_.config)); this->store_.config.signal_range_min_ns = std::min(this->filter_us_ * 1000, max_filter_ns); this->store_.config.signal_range_max_ns = this->idle_us_ * 1000; From b8ec3aab1d2cc36a96902aa39cae9331a02f1f93 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:16:25 -0500 Subject: [PATCH 0632/2030] [ci] Pin ESP-IDF version for Arduino framework builds (#13909) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .clang-tidy.hash | 2 +- platformio.ini | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 63ddbbac05..37f82e2755 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -37ec8d5a343c8d0a485fd2118cbdabcbccd7b9bca197e4a392be75087974dced +8dc4dae0acfa22f26c7cde87fc24e60b27f29a73300e02189b78f0315e5d0695 diff --git a/platformio.ini b/platformio.ini index d198862a25..94b1f1a727 100644 --- a/platformio.ini +++ b/platformio.ini @@ -136,6 +136,7 @@ extends = common:arduino platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip platform_packages = pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6.tar.xz + pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz framework = arduino, espidf ; Arduino as an ESP-IDF component lib_deps = From 2585779f11daab1b41fd333382c0f2dcd8bd174e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 12:23:16 -0600 Subject: [PATCH 0633/2030] [api] Remove duplicate peername storage to save RAM (#13540) --- esphome/components/api/api_connection.cpp | 30 ++++++++++++------- esphome/components/api/api_connection.h | 6 ++-- esphome/components/api/api_frame_helper.cpp | 18 +++++++++-- esphome/components/api/api_frame_helper.h | 9 +++--- .../components/api/api_frame_helper_noise.cpp | 7 ++++- .../api/api_frame_helper_plaintext.cpp | 7 ++++- esphome/components/api/api_server.cpp | 8 +++-- .../voice_assistant/voice_assistant.cpp | 6 ++-- 8 files changed, 65 insertions(+), 26 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index c00f413e67..e51689fd07 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -133,8 +133,8 @@ void APIConnection::start() { return; } // Initialize client name with peername (IP address) until Hello message provides actual name - const char *peername = this->helper_->get_client_peername(); - this->helper_->set_client_name(peername, strlen(peername)); + char peername[socket::SOCKADDR_STR_LEN]; + this->helper_->set_client_name(this->helper_->get_peername_to(peername), strlen(peername)); } APIConnection::~APIConnection() { @@ -179,8 +179,8 @@ void APIConnection::begin_iterator_(ActiveIterator type) { void APIConnection::loop() { if (this->flags_.next_close) { - // requested a disconnect - this->helper_->close(); + // requested a disconnect - don't close socket here, let APIServer::loop() do it + // so getpeername() still works for the disconnect trigger this->flags_.remove = true; return; } @@ -293,7 +293,8 @@ bool APIConnection::send_disconnect_response_() { return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE); } void APIConnection::on_disconnect_response() { - this->helper_->close(); + // Don't close socket here, let APIServer::loop() do it + // so getpeername() still works for the disconnect trigger this->flags_.remove = true; } @@ -1469,8 +1470,11 @@ void APIConnection::complete_authentication_() { this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED); this->log_client_(ESPHOME_LOG_LEVEL_DEBUG, LOG_STR("connected")); #ifdef USE_API_CLIENT_CONNECTED_TRIGGER - this->parent_->get_client_connected_trigger()->trigger(std::string(this->helper_->get_client_name()), - std::string(this->helper_->get_client_peername())); + { + char peername[socket::SOCKADDR_STR_LEN]; + this->parent_->get_client_connected_trigger()->trigger(std::string(this->helper_->get_client_name()), + std::string(this->helper_->get_peername_to(peername))); + } #endif #ifdef USE_HOMEASSISTANT_TIME if (homeassistant::global_homeassistant_time != nullptr) { @@ -1489,8 +1493,9 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) { this->helper_->set_client_name(msg.client_info.c_str(), msg.client_info.size()); this->client_api_version_major_ = msg.api_version_major; this->client_api_version_minor_ = msg.api_version_minor; + char peername[socket::SOCKADDR_STR_LEN]; ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->helper_->get_client_name(), - this->helper_->get_client_peername(), this->client_api_version_major_, this->client_api_version_minor_); + this->helper_->get_peername_to(peername), this->client_api_version_major_, this->client_api_version_minor_); HelloResponse resp; resp.api_version_major = 1; @@ -1838,7 +1843,8 @@ void APIConnection::on_no_setup_connection() { this->log_client_(ESPHOME_LOG_LEVEL_DEBUG, LOG_STR("no connection setup")); } void APIConnection::on_fatal_error() { - this->helper_->close(); + // Don't close socket here - keep it open so getpeername() works for logging + // Socket will be closed when client is removed from the list in APIServer::loop() this->flags_.remove = true; } @@ -2195,12 +2201,14 @@ void APIConnection::process_state_subscriptions_() { #endif // USE_API_HOMEASSISTANT_STATES void APIConnection::log_client_(int level, const LogString *message) { + char peername[socket::SOCKADDR_STR_LEN]; esp_log_printf_(level, TAG, __LINE__, ESPHOME_LOG_FORMAT("%s (%s): %s"), this->helper_->get_client_name(), - this->helper_->get_client_peername(), LOG_STR_ARG(message)); + this->helper_->get_peername_to(peername), LOG_STR_ARG(message)); } void APIConnection::log_warning_(const LogString *message, APIError err) { - ESP_LOGW(TAG, "%s (%s): %s %s errno=%d", this->helper_->get_client_name(), this->helper_->get_client_peername(), + char peername[socket::SOCKADDR_STR_LEN]; + ESP_LOGW(TAG, "%s (%s): %s %s errno=%d", this->helper_->get_client_name(), this->helper_->get_peername_to(peername), LOG_STR_ARG(message), LOG_STR_ARG(api_error_to_logstr(err)), errno); } diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 7f738a9bfd..abcb162865 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -276,8 +276,10 @@ class APIConnection final : public APIServerConnectionBase { bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; const char *get_name() const { return this->helper_->get_client_name(); } - /// Get peer name (IP address) - cached at connection init time - const char *get_peername() const { return this->helper_->get_client_peername(); } + /// Get peer name (IP address) into caller-provided buffer, returns buf for convenience + const char *get_peername_to(std::span<char, socket::SOCKADDR_STR_LEN> buf) const { + return this->helper_->get_peername_to(buf); + } protected: // Helper function to handle authentication completion diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index dd44fe9e17..e432a976b0 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -16,7 +16,12 @@ static const char *const TAG = "api.frame_helper"; static constexpr size_t API_MAX_LOG_BYTES = 168; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE -#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__) +#define HELPER_LOG(msg, ...) \ + do { \ + char peername_buf[socket::SOCKADDR_STR_LEN]; \ + this->get_peername_to(peername_buf); \ + ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, peername_buf, ##__VA_ARGS__); \ + } while (0) #else #define HELPER_LOG(msg, ...) ((void) 0) #endif @@ -240,13 +245,20 @@ APIError APIFrameHelper::try_send_tx_buf_() { return APIError::OK; // All buffers sent successfully } +const char *APIFrameHelper::get_peername_to(std::span<char, socket::SOCKADDR_STR_LEN> buf) const { + if (this->socket_) { + this->socket_->getpeername_to(buf); + } else { + buf[0] = '\0'; + } + return buf.data(); +} + APIError APIFrameHelper::init_common_() { if (state_ != State::INITIALIZE || this->socket_ == nullptr) { HELPER_LOG("Bad state for init %d", (int) state_); return APIError::BAD_STATE; } - // Cache peername now while socket is valid - needed for error logging after socket failure - this->socket_->getpeername_to(this->client_peername_); int err = this->socket_->setblocking(false); if (err != 0) { state_ = State::FAILED; diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index f311e34fd7..03f3814bb9 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -90,8 +90,9 @@ class APIFrameHelper { // Get client name (null-terminated) const char *get_client_name() const { return this->client_name_; } - // Get client peername/IP (null-terminated, cached at init time for availability after socket failure) - const char *get_client_peername() const { return this->client_peername_; } + // Get client peername/IP into caller-provided buffer (fetches on-demand from socket) + // Returns pointer to buf for convenience in printf-style calls + const char *get_peername_to(std::span<char, socket::SOCKADDR_STR_LEN> buf) const; // Set client name from buffer with length (truncates if needed) void set_client_name(const char *name, size_t len) { size_t copy_len = std::min(len, sizeof(this->client_name_) - 1); @@ -105,6 +106,8 @@ class APIFrameHelper { bool can_write_without_blocking() { return this->state_ == State::DATA && this->tx_buf_count_ == 0; } int getpeername(struct sockaddr *addr, socklen_t *addrlen) { return socket_->getpeername(addr, addrlen); } APIError close() { + if (state_ == State::CLOSED) + return APIError::OK; // Already closed state_ = State::CLOSED; int err = this->socket_->close(); if (err == -1) @@ -231,8 +234,6 @@ class APIFrameHelper { // Client name buffer - stores name from Hello message or initial peername char client_name_[CLIENT_INFO_NAME_MAX_LEN]{}; - // Cached peername/IP address - captured at init time for availability after socket failure - char client_peername_[socket::SOCKADDR_STR_LEN]{}; // Group smaller types together uint16_t rx_buf_len_ = 0; diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 4a9257231d..c1641b398a 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -29,7 +29,12 @@ static constexpr size_t PROLOGUE_INIT_LEN = 12; // strlen("NoiseAPIInit") static constexpr size_t API_MAX_LOG_BYTES = 168; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE -#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__) +#define HELPER_LOG(msg, ...) \ + do { \ + char peername_buf[socket::SOCKADDR_STR_LEN]; \ + this->get_peername_to(peername_buf); \ + ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, peername_buf, ##__VA_ARGS__); \ + } while (0) #else #define HELPER_LOG(msg, ...) ((void) 0) #endif diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index 3dfd683929..ed3cc8934e 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -21,7 +21,12 @@ static const char *const TAG = "api.plaintext"; static constexpr size_t API_MAX_LOG_BYTES = 168; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE -#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, this->client_peername_, ##__VA_ARGS__) +#define HELPER_LOG(msg, ...) \ + do { \ + char peername_buf[socket::SOCKADDR_STR_LEN]; \ + this->get_peername_to(peername_buf); \ + ESP_LOGVV(TAG, "%s (%s): " msg, this->client_name_, peername_buf, ##__VA_ARGS__); \ + } while (0) #else #define HELPER_LOG(msg, ...) ((void) 0) #endif diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index c56449455d..53b41a5c14 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -192,11 +192,15 @@ void APIServer::loop() { ESP_LOGV(TAG, "Remove connection %s", client->get_name()); #ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - // Save client info before removal for the trigger + // Save client info before closing socket and removal for the trigger + char peername_buf[socket::SOCKADDR_STR_LEN]; std::string client_name(client->get_name()); - std::string client_peername(client->get_peername()); + std::string client_peername(client->get_peername_to(peername_buf)); #endif + // Close socket now (was deferred from on_fatal_error to allow getpeername) + client->helper_->close(); + // Swap with the last element and pop (avoids expensive vector shifts) if (client_index < this->clients_.size() - 1) { std::swap(this->clients_[client_index], this->clients_.back()); diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 6267d97480..641d4d6ff8 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -430,12 +430,14 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr } if (this->api_client_ != nullptr) { + char current_peername[socket::SOCKADDR_STR_LEN]; + char new_peername[socket::SOCKADDR_STR_LEN]; ESP_LOGE(TAG, "Multiple API Clients attempting to connect to Voice Assistant\n" "Current client: %s (%s)\n" "New client: %s (%s)", - this->api_client_->get_name(), this->api_client_->get_peername(), client->get_name(), - client->get_peername()); + this->api_client_->get_name(), this->api_client_->get_peername_to(current_peername), client->get_name(), + client->get_peername_to(new_peername)); return; } From eea7e9edffe8bdf321c3e8042c0c7614b926b16b Mon Sep 17 00:00:00 2001 From: Jas Strong <jasmine@electronpusher.org> Date: Thu, 5 Feb 2026 00:06:52 -0800 Subject: [PATCH 0634/2030] [rd03d] Revert incorrect field order swap (#13769) Co-authored-by: jas <jas@asspa.in> --- esphome/components/rd03d/rd03d.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index ba05abe8e0..090e4dcf32 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -132,18 +132,15 @@ void RD03DComponent::process_frame_() { // Header is 4 bytes, each target is 8 bytes uint8_t offset = FRAME_HEADER_SIZE + (i * TARGET_DATA_SIZE); - // Extract raw bytes for this target - // Note: Despite datasheet Table 5-2 showing order as X, Y, Speed, Resolution, - // actual radar output has Resolution before Speed (verified empirically - - // stationary targets were showing non-zero speed with original field order) + // Extract raw bytes for this target (per datasheet Table 5-2: X, Y, Speed, Resolution) uint8_t x_low = this->buffer_[offset + 0]; uint8_t x_high = this->buffer_[offset + 1]; uint8_t y_low = this->buffer_[offset + 2]; uint8_t y_high = this->buffer_[offset + 3]; - uint8_t res_low = this->buffer_[offset + 4]; - uint8_t res_high = this->buffer_[offset + 5]; - uint8_t speed_low = this->buffer_[offset + 6]; - uint8_t speed_high = this->buffer_[offset + 7]; + uint8_t speed_low = this->buffer_[offset + 4]; + uint8_t speed_high = this->buffer_[offset + 5]; + uint8_t res_low = this->buffer_[offset + 6]; + uint8_t res_high = this->buffer_[offset + 7]; // Decode values per RD-03D format int16_t x = decode_value(x_low, x_high); From 9eee4c992450bcfaec1e7516f96ccacad7b09a4f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Feb 2026 09:00:16 -0500 Subject: [PATCH 0635/2030] [core] Add capacity check to register_component_ (#13778) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/core/application.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 55eb25ce09..76ce976131 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -81,6 +81,10 @@ void Application::register_component_(Component *comp) { return; } } + if (this->components_.size() >= ESPHOME_COMPONENT_COUNT) { + ESP_LOGE(TAG, "Cannot register component %s - at capacity!", LOG_STR_ARG(comp->get_component_log_str())); + return; + } this->components_.push_back(comp); } void Application::setup() { From 438a0c428985b9d8c37ac2e036d7a955809a8793 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Feb 2026 04:09:48 -0500 Subject: [PATCH 0636/2030] [ota] Fix CLI upload option shown when only http_request platform configured (#13784) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> --- esphome/__main__.py | 9 +++- tests/unit_tests/test_main.py | 85 ++++++++++++++++++++++++++++------- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 6cec481abc..e49a1eea9d 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -287,8 +287,13 @@ def has_api() -> bool: def has_ota() -> bool: - """Check if OTA is available.""" - return CONF_OTA in CORE.config + """Check if OTA upload is available (requires platform: esphome).""" + if CONF_OTA not in CORE.config: + return False + return any( + ota_item.get(CONF_PLATFORM) == CONF_ESPHOME + for ota_item in CORE.config[CONF_OTA] + ) def has_mqtt_ip_lookup() -> bool: diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 3268f7ee87..c9aa446323 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -32,6 +32,7 @@ from esphome.__main__ import ( has_mqtt_ip_lookup, has_mqtt_logging, has_non_ip_address, + has_ota, has_resolvable_address, mqtt_get_ip, run_esphome, @@ -332,7 +333,9 @@ def test_choose_upload_log_host_with_mixed_hostnames_and_ips() -> None: def test_choose_upload_log_host_with_ota_list() -> None: """Test with OTA as the only item in the list.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default=["OTA"], @@ -345,7 +348,7 @@ def test_choose_upload_log_host_with_ota_list() -> None: @pytest.mark.usefixtures("mock_has_mqtt_logging") def test_choose_upload_log_host_with_ota_list_mqtt_fallback() -> None: """Test with OTA list falling back to MQTT when no address.""" - setup_core(config={CONF_OTA: {}, "mqtt": {}}) + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], "mqtt": {}}) result = choose_upload_log_host( default=["OTA"], @@ -408,7 +411,9 @@ def test_choose_upload_log_host_with_serial_device_with_ports( def test_choose_upload_log_host_with_ota_device_with_ota_config() -> None: """Test OTA device when OTA is configured.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default="OTA", @@ -475,7 +480,9 @@ def test_choose_upload_log_host_with_ota_device_no_fallback() -> None: @pytest.mark.usefixtures("mock_choose_prompt") def test_choose_upload_log_host_multiple_devices() -> None: """Test with multiple devices including special identifiers.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) mock_ports = [MockSerialPort("/dev/ttyUSB0", "USB Serial")] @@ -514,7 +521,9 @@ def test_choose_upload_log_host_no_defaults_with_serial_ports( @pytest.mark.usefixtures("mock_no_serial_ports") def test_choose_upload_log_host_no_defaults_with_ota() -> None: """Test interactive mode with OTA option.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) with patch( "esphome.__main__.choose_prompt", return_value="192.168.1.100" @@ -575,7 +584,11 @@ def test_choose_upload_log_host_no_defaults_with_all_options( ) -> None: """Test interactive mode with all options available.""" setup_core( - config={CONF_OTA: {}, CONF_API: {}, CONF_MQTT: {CONF_BROKER: "mqtt.local"}}, + config={ + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], + CONF_API: {}, + CONF_MQTT: {CONF_BROKER: "mqtt.local"}, + }, address="192.168.1.100", ) @@ -604,7 +617,11 @@ def test_choose_upload_log_host_no_defaults_with_all_options_logging( ) -> None: """Test interactive mode with all options available.""" setup_core( - config={CONF_OTA: {}, CONF_API: {}, CONF_MQTT: {CONF_BROKER: "mqtt.local"}}, + config={ + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], + CONF_API: {}, + CONF_MQTT: {CONF_BROKER: "mqtt.local"}, + }, address="192.168.1.100", ) @@ -632,7 +649,9 @@ def test_choose_upload_log_host_no_defaults_with_all_options_logging( @pytest.mark.usefixtures("mock_no_serial_ports") def test_choose_upload_log_host_check_default_matches() -> None: """Test when check_default matches an available option.""" - setup_core(config={CONF_OTA: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, address="192.168.1.100" + ) result = choose_upload_log_host( default=None, @@ -704,7 +723,10 @@ def test_choose_upload_log_host_mixed_resolved_unresolved() -> None: def test_choose_upload_log_host_ota_both_conditions() -> None: """Test OTA device when both OTA and API are configured and enabled.""" - setup_core(config={CONF_OTA: {}, CONF_API: {}}, address="192.168.1.100") + setup_core( + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}}, + address="192.168.1.100", + ) result = choose_upload_log_host( default="OTA", @@ -719,7 +741,7 @@ def test_choose_upload_log_host_ota_ip_all_options() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -744,7 +766,7 @@ def test_choose_upload_log_host_ota_local_all_options() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -769,7 +791,7 @@ def test_choose_upload_log_host_ota_ip_all_options_logging() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -794,7 +816,7 @@ def test_choose_upload_log_host_ota_local_all_options_logging() -> None: """Test OTA device when both static IP, OTA, API and MQTT are configured and enabled but MDNS not.""" setup_core( config={ - CONF_OTA: {}, + CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}], CONF_API: {}, CONF_MQTT: { CONF_BROKER: "mqtt.local", @@ -817,7 +839,7 @@ def test_choose_upload_log_host_ota_local_all_options_logging() -> None: @pytest.mark.usefixtures("mock_no_mqtt_logging") def test_choose_upload_log_host_no_address_with_ota_config() -> None: """Test OTA device when OTA is configured but no address is set.""" - setup_core(config={CONF_OTA: {}}) + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) with pytest.raises( EsphomeError, match="All specified devices .* could not be resolved" @@ -1532,10 +1554,43 @@ def test_has_mqtt() -> None: assert has_mqtt() is False # Test with other components but no MQTT - setup_core(config={CONF_API: {}, CONF_OTA: {}}) + setup_core(config={CONF_API: {}, CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) assert has_mqtt() is False +def test_has_ota() -> None: + """Test has_ota function. + + The has_ota function should only return True when OTA is configured + with platform: esphome, not when only platform: http_request is configured. + This is because CLI OTA upload only works with the esphome platform. + """ + # Test with OTA esphome platform configured + setup_core(config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}) + assert has_ota() is True + + # Test with OTA http_request platform only (should return False) + # This is the bug scenario from issue #13783 + setup_core(config={CONF_OTA: [{CONF_PLATFORM: "http_request"}]}) + assert has_ota() is False + + # Test without OTA configured + setup_core(config={}) + assert has_ota() is False + + # Test with multiple OTA platforms including esphome + setup_core( + config={ + CONF_OTA: [{CONF_PLATFORM: "http_request"}, {CONF_PLATFORM: CONF_ESPHOME}] + } + ) + assert has_ota() is True + + # Test with empty OTA list + setup_core(config={CONF_OTA: []}) + assert has_ota() is False + + def test_get_port_type() -> None: """Test get_port_type function.""" From c1455ccc29815b20aa814c82b14cf23c2fac8ca1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Feb 2026 22:19:20 +0100 Subject: [PATCH 0637/2030] [dashboard] Close WebSocket after process exit to prevent zombie connections (#13834) --- esphome/dashboard/web_server.py | 1 + tests/dashboard/test_web_server.py | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index f94d8eea22..da50279864 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -317,6 +317,7 @@ class EsphomeCommandWebSocket(CheckOriginMixin, tornado.websocket.WebSocketHandl # Check if the proc was not forcibly closed _LOGGER.info("Process exited with return code %s", returncode) self.write_message({"event": "exit", "code": returncode}) + self.close() def on_close(self) -> None: # Check if proc exists (if 'start' has been run) diff --git a/tests/dashboard/test_web_server.py b/tests/dashboard/test_web_server.py index 10ca6061e6..7642876ee5 100644 --- a/tests/dashboard/test_web_server.py +++ b/tests/dashboard/test_web_server.py @@ -29,7 +29,7 @@ from esphome.dashboard.entries import ( bool_to_entry_state, ) from esphome.dashboard.models import build_importable_device_dict -from esphome.dashboard.web_server import DashboardSubscriber +from esphome.dashboard.web_server import DashboardSubscriber, EsphomeCommandWebSocket from esphome.zeroconf import DiscoveredImport from .common import get_fixture_path @@ -1654,3 +1654,25 @@ async def test_websocket_check_origin_multiple_trusted_domains( assert data["event"] == "initial_state" finally: ws.close() + + +def test_proc_on_exit_calls_close() -> None: + """Test _proc_on_exit sends exit event and closes the WebSocket.""" + handler = Mock(spec=EsphomeCommandWebSocket) + handler._is_closed = False + + EsphomeCommandWebSocket._proc_on_exit(handler, 0) + + handler.write_message.assert_called_once_with({"event": "exit", "code": 0}) + handler.close.assert_called_once() + + +def test_proc_on_exit_skips_when_already_closed() -> None: + """Test _proc_on_exit does nothing when WebSocket is already closed.""" + handler = Mock(spec=EsphomeCommandWebSocket) + handler._is_closed = True + + EsphomeCommandWebSocket._proc_on_exit(handler, 0) + + handler.write_message.assert_not_called() + handler.close.assert_not_called() From a5dc4b0fce2c0b2b279abb6cc8eaa49b642d19d4 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sun, 8 Feb 2026 18:52:05 +0100 Subject: [PATCH 0638/2030] [nrf52,logger] fix printk (#13874) --- esphome/components/logger/logger_zephyr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index 41f53beec0..c0fb5c502b 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -68,7 +68,7 @@ void HOT Logger::write_msg_(const char *msg, size_t len) { #ifdef CONFIG_PRINTK // Requires the debug component and an active SWD connection. // It is used for pyocd rtt -t nrf52840 - k_str_out(const_cast<char *>(msg), len); + printk("%.*s", static_cast<int>(len), msg); #endif if (this->uart_dev_ == nullptr) { return; From 0b047c334d3142753169ccb308ae2dda0a7c32b6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:53:43 +1100 Subject: [PATCH 0639/2030] [lvgl] Fix crash with unconfigured `top_layer` (#13846) --- esphome/components/lvgl/schemas.py | 1 + tests/components/lvgl/test.host.yaml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 45d933c00e..2aeeedbd10 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -436,6 +436,7 @@ def container_schema(widget_type: WidgetType, extras=None): schema = schema.extend(widget_type.schema) def validator(value): + value = value or {} return append_layout_schema(schema, value)(value) return validator diff --git a/tests/components/lvgl/test.host.yaml b/tests/components/lvgl/test.host.yaml index 00a8cd8c01..f84156c9d8 100644 --- a/tests/components/lvgl/test.host.yaml +++ b/tests/components/lvgl/test.host.yaml @@ -20,6 +20,8 @@ lvgl: - id: lvgl_0 default_font: space16 displays: sdl0 + top_layer: + - id: lvgl_1 displays: sdl1 on_idle: From 1f761902b6f17984216b7a690f0bb68fc3d2afee Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Feb 2026 12:49:58 -0500 Subject: [PATCH 0640/2030] [esp32] Set UV_CACHE_DIR inside data dir so Clean All clears it (#13888) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 7fb708dea4..3a330a3722 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1026,6 +1026,10 @@ async def to_code(config): Path(__file__).parent / "iram_fix.py.script", ) + # Set the uv cache inside the data dir so "Clean All" clears it. + # Avoids persistent corrupted cache from mid-stream download failures. + os.environ["UV_CACHE_DIR"] = str(CORE.relative_internal_path(".uv_cache")) + if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: cg.add_platformio_option("framework", "espidf") cg.add_build_flag("-DUSE_ESP_IDF") From 1a6c67f92ef4d46ed4134d2e16a102e96d5159a4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:45:03 -0600 Subject: [PATCH 0641/2030] [ssd1306_base] Move switch tables to PROGMEM with lookup tables (#13814) --- .../components/ssd1306_base/ssd1306_base.cpp | 136 ++++++++---------- .../components/ssd1306_base/ssd1306_base.h | 5 +- .../components/ssd1306_i2c/ssd1306_i2c.cpp | 2 +- .../components/ssd1306_spi/ssd1306_spi.cpp | 2 +- 4 files changed, 65 insertions(+), 80 deletions(-) diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index e0e7f94ce0..be99bd93da 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -1,6 +1,7 @@ #include "ssd1306_base.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace ssd1306_base { @@ -40,6 +41,55 @@ static const uint8_t SSD1305_COMMAND_SET_AREA_COLOR = 0xD8; static const uint8_t SH1107_COMMAND_SET_START_LINE = 0xDC; static const uint8_t SH1107_COMMAND_CHARGE_PUMP = 0xAD; +// Verify first enum value and table sizes match SSD1306_MODEL_COUNT +static_assert(SSD1306_MODEL_128_32 == 0, "SSD1306Model enum must start at 0"); + +// PROGMEM lookup table indexed by SSD1306Model enum (width, height per model) +struct ModelDimensions { + uint8_t width; + uint8_t height; +}; +static const ModelDimensions MODEL_DIMS[] PROGMEM = { + {128, 32}, // SSD1306_MODEL_128_32 + {128, 64}, // SSD1306_MODEL_128_64 + {96, 16}, // SSD1306_MODEL_96_16 + {64, 48}, // SSD1306_MODEL_64_48 + {64, 32}, // SSD1306_MODEL_64_32 + {72, 40}, // SSD1306_MODEL_72_40 + {128, 32}, // SH1106_MODEL_128_32 + {128, 64}, // SH1106_MODEL_128_64 + {96, 16}, // SH1106_MODEL_96_16 + {64, 48}, // SH1106_MODEL_64_48 + {64, 128}, // SH1107_MODEL_128_64 (note: width is 64, height is 128) + {128, 128}, // SH1107_MODEL_128_128 + {128, 32}, // SSD1305_MODEL_128_32 + {128, 64}, // SSD1305_MODEL_128_64 +}; + +// clang-format off +PROGMEM_STRING_TABLE(ModelStrings, + "SSD1306 128x32", // SSD1306_MODEL_128_32 + "SSD1306 128x64", // SSD1306_MODEL_128_64 + "SSD1306 96x16", // SSD1306_MODEL_96_16 + "SSD1306 64x48", // SSD1306_MODEL_64_48 + "SSD1306 64x32", // SSD1306_MODEL_64_32 + "SSD1306 72x40", // SSD1306_MODEL_72_40 + "SH1106 128x32", // SH1106_MODEL_128_32 + "SH1106 128x64", // SH1106_MODEL_128_64 + "SH1106 96x16", // SH1106_MODEL_96_16 + "SH1106 64x48", // SH1106_MODEL_64_48 + "SH1107 128x64", // SH1107_MODEL_128_64 + "SH1107 128x128", // SH1107_MODEL_128_128 + "SSD1305 128x32", // SSD1305_MODEL_128_32 + "SSD1305 128x64", // SSD1305_MODEL_128_64 + "Unknown" // fallback +); +// clang-format on +static_assert(sizeof(MODEL_DIMS) / sizeof(MODEL_DIMS[0]) == SSD1306_MODEL_COUNT, + "MODEL_DIMS must have one entry per SSD1306Model"); +static_assert(ModelStrings::COUNT == SSD1306_MODEL_COUNT + 1, + "ModelStrings must have one entry per SSD1306Model plus fallback"); + void SSD1306::setup() { this->init_internal_(this->get_buffer_length_()); @@ -146,6 +196,7 @@ void SSD1306::setup() { break; case SH1107_MODEL_128_64: case SH1107_MODEL_128_128: + case SSD1306_MODEL_COUNT: // Not used, but prevents build warning break; } @@ -274,54 +325,14 @@ void SSD1306::turn_off() { this->is_on_ = false; } int SSD1306::get_height_internal() { - switch (this->model_) { - case SH1107_MODEL_128_64: - case SH1107_MODEL_128_128: - return 128; - case SSD1306_MODEL_128_32: - case SSD1306_MODEL_64_32: - case SH1106_MODEL_128_32: - case SSD1305_MODEL_128_32: - return 32; - case SSD1306_MODEL_128_64: - case SH1106_MODEL_128_64: - case SSD1305_MODEL_128_64: - return 64; - case SSD1306_MODEL_96_16: - case SH1106_MODEL_96_16: - return 16; - case SSD1306_MODEL_64_48: - case SH1106_MODEL_64_48: - return 48; - case SSD1306_MODEL_72_40: - return 40; - default: - return 0; - } + if (this->model_ >= SSD1306_MODEL_COUNT) + return 0; + return progmem_read_byte(&MODEL_DIMS[this->model_].height); } int SSD1306::get_width_internal() { - switch (this->model_) { - case SSD1306_MODEL_128_32: - case SH1106_MODEL_128_32: - case SSD1306_MODEL_128_64: - case SH1106_MODEL_128_64: - case SSD1305_MODEL_128_32: - case SSD1305_MODEL_128_64: - case SH1107_MODEL_128_128: - return 128; - case SSD1306_MODEL_96_16: - case SH1106_MODEL_96_16: - return 96; - case SSD1306_MODEL_64_48: - case SSD1306_MODEL_64_32: - case SH1106_MODEL_64_48: - case SH1107_MODEL_128_64: - return 64; - case SSD1306_MODEL_72_40: - return 72; - default: - return 0; - } + if (this->model_ >= SSD1306_MODEL_COUNT) + return 0; + return progmem_read_byte(&MODEL_DIMS[this->model_].width); } size_t SSD1306::get_buffer_length_() { return size_t(this->get_width_internal()) * size_t(this->get_height_internal()) / 8u; @@ -361,37 +372,8 @@ void SSD1306::init_reset_() { this->reset_pin_->digital_write(true); } } -const char *SSD1306::model_str_() { - switch (this->model_) { - case SSD1306_MODEL_128_32: - return "SSD1306 128x32"; - case SSD1306_MODEL_128_64: - return "SSD1306 128x64"; - case SSD1306_MODEL_64_32: - return "SSD1306 64x32"; - case SSD1306_MODEL_96_16: - return "SSD1306 96x16"; - case SSD1306_MODEL_64_48: - return "SSD1306 64x48"; - case SSD1306_MODEL_72_40: - return "SSD1306 72x40"; - case SH1106_MODEL_128_32: - return "SH1106 128x32"; - case SH1106_MODEL_128_64: - return "SH1106 128x64"; - case SH1106_MODEL_96_16: - return "SH1106 96x16"; - case SH1106_MODEL_64_48: - return "SH1106 64x48"; - case SH1107_MODEL_128_64: - return "SH1107 128x64"; - case SSD1305_MODEL_128_32: - return "SSD1305 128x32"; - case SSD1305_MODEL_128_64: - return "SSD1305 128x64"; - default: - return "Unknown"; - } +const LogString *SSD1306::model_str_() { + return ModelStrings::get_log_str(static_cast<uint8_t>(this->model_), ModelStrings::LAST_INDEX); } } // namespace ssd1306_base diff --git a/esphome/components/ssd1306_base/ssd1306_base.h b/esphome/components/ssd1306_base/ssd1306_base.h index a573437386..3cc795a323 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.h +++ b/esphome/components/ssd1306_base/ssd1306_base.h @@ -22,6 +22,9 @@ enum SSD1306Model { SH1107_MODEL_128_128, SSD1305_MODEL_128_32, SSD1305_MODEL_128_64, + // When adding a new model, add it before SSD1306_MODEL_COUNT and update + // MODEL_DIMS and ModelStrings tables in ssd1306_base.cpp + SSD1306_MODEL_COUNT, // must be last }; class SSD1306 : public display::DisplayBuffer { @@ -70,7 +73,7 @@ class SSD1306 : public display::DisplayBuffer { int get_height_internal() override; int get_width_internal() override; size_t get_buffer_length_(); - const char *model_str_(); + const LogString *model_str_(); SSD1306Model model_{SSD1306_MODEL_128_64}; GPIOPin *reset_pin_{nullptr}; diff --git a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp index 47a21a8ff4..e1f6e91243 100644 --- a/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp +++ b/esphome/components/ssd1306_i2c/ssd1306_i2c.cpp @@ -28,7 +28,7 @@ void I2CSSD1306::dump_config() { " Offset X: %d\n" " Offset Y: %d\n" " Inverted Color: %s", - this->model_str_(), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), + LOG_STR_ARG(this->model_str_()), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), this->offset_x_, this->offset_y_, YESNO(this->invert_)); LOG_I2C_DEVICE(this); LOG_PIN(" Reset Pin: ", this->reset_pin_); diff --git a/esphome/components/ssd1306_spi/ssd1306_spi.cpp b/esphome/components/ssd1306_spi/ssd1306_spi.cpp index db28dfc564..af9a17c8ab 100644 --- a/esphome/components/ssd1306_spi/ssd1306_spi.cpp +++ b/esphome/components/ssd1306_spi/ssd1306_spi.cpp @@ -24,7 +24,7 @@ void SPISSD1306::dump_config() { " Offset X: %d\n" " Offset Y: %d\n" " Inverted Color: %s", - this->model_str_(), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), + LOG_STR_ARG(this->model_str_()), YESNO(this->external_vcc_), YESNO(this->flip_x_), YESNO(this->flip_y_), this->offset_x_, this->offset_y_, YESNO(this->invert_)); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DC Pin: ", this->dc_pin_); From 4168e8c30d6cf7f6d7e572e827c1851b956853f3 Mon Sep 17 00:00:00 2001 From: Sean Kelly <xconverge@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:30:37 -0800 Subject: [PATCH 0642/2030] [aqi] Fix AQI calculation for specific pm2.5 or pm10 readings (#13770) --- esphome/components/aqi/aqi_calculator.h | 38 +++++++++++++++++++----- esphome/components/aqi/caqi_calculator.h | 30 ++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/esphome/components/aqi/aqi_calculator.h b/esphome/components/aqi/aqi_calculator.h index 993504c1e9..d624af0432 100644 --- a/esphome/components/aqi/aqi_calculator.h +++ b/esphome/components/aqi/aqi_calculator.h @@ -1,5 +1,6 @@ #pragma once +#include <algorithm> #include <cmath> #include <limits> #include "abstract_aqi_calculator.h" @@ -14,7 +15,11 @@ class AQICalculator : public AbstractAQICalculator { float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); + float aqi = std::max(pm2_5_index, pm10_0_index); + if (aqi < 0.0f) { + aqi = 0.0f; + } + return static_cast<uint16_t>(std::lround(aqi)); } protected: @@ -22,13 +27,27 @@ class AQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; - static constexpr float PM2_5_GRID[NUM_LEVELS][2] = {{0.0f, 9.0f}, {9.1f, 35.4f}, - {35.5f, 55.4f}, {55.5f, 125.4f}, - {125.5f, 225.4f}, {225.5f, std::numeric_limits<float>::max()}}; + static constexpr float PM2_5_GRID[NUM_LEVELS][2] = { + // clang-format off + {0.0f, 9.1f}, + {9.1f, 35.5f}, + {35.5f, 55.5f}, + {55.5f, 125.5f}, + {125.5f, 225.5f}, + {225.5f, std::numeric_limits<float>::max()} + // clang-format on + }; - static constexpr float PM10_0_GRID[NUM_LEVELS][2] = {{0.0f, 54.0f}, {55.0f, 154.0f}, - {155.0f, 254.0f}, {255.0f, 354.0f}, - {355.0f, 424.0f}, {425.0f, std::numeric_limits<float>::max()}}; + static constexpr float PM10_0_GRID[NUM_LEVELS][2] = { + // clang-format off + {0.0f, 55.0f}, + {55.0f, 155.0f}, + {155.0f, 255.0f}, + {255.0f, 355.0f}, + {355.0f, 425.0f}, + {425.0f, std::numeric_limits<float>::max()} + // clang-format on + }; static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); @@ -45,7 +64,10 @@ class AQICalculator : public AbstractAQICalculator { static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { - if (value >= array[i][0] && value <= array[i][1]) { + const bool in_range = + (value >= array[i][0]) && ((i == NUM_LEVELS - 1) ? (value <= array[i][1]) // last bucket inclusive + : (value < array[i][1])); // others exclusive on hi + if (in_range) { return i; } } diff --git a/esphome/components/aqi/caqi_calculator.h b/esphome/components/aqi/caqi_calculator.h index d2ec4bb98f..fe2efe7059 100644 --- a/esphome/components/aqi/caqi_calculator.h +++ b/esphome/components/aqi/caqi_calculator.h @@ -1,5 +1,6 @@ #pragma once +#include <algorithm> #include <cmath> #include <limits> #include "abstract_aqi_calculator.h" @@ -12,7 +13,11 @@ class CAQICalculator : public AbstractAQICalculator { float pm2_5_index = calculate_index(pm2_5_value, PM2_5_GRID); float pm10_0_index = calculate_index(pm10_0_value, PM10_0_GRID); - return static_cast<uint16_t>(std::round((pm2_5_index < pm10_0_index) ? pm10_0_index : pm2_5_index)); + float aqi = std::max(pm2_5_index, pm10_0_index); + if (aqi < 0.0f) { + aqi = 0.0f; + } + return static_cast<uint16_t>(std::lround(aqi)); } protected: @@ -21,10 +26,24 @@ class CAQICalculator : public AbstractAQICalculator { static constexpr int INDEX_GRID[NUM_LEVELS][2] = {{0, 25}, {26, 50}, {51, 75}, {76, 100}, {101, 400}}; static constexpr float PM2_5_GRID[NUM_LEVELS][2] = { - {0.0f, 15.0f}, {15.1f, 30.0f}, {30.1f, 55.0f}, {55.1f, 110.0f}, {110.1f, std::numeric_limits<float>::max()}}; + // clang-format off + {0.0f, 15.1f}, + {15.1f, 30.1f}, + {30.1f, 55.1f}, + {55.1f, 110.1f}, + {110.1f, std::numeric_limits<float>::max()} + // clang-format on + }; static constexpr float PM10_0_GRID[NUM_LEVELS][2] = { - {0.0f, 25.0f}, {25.1f, 50.0f}, {50.1f, 90.0f}, {90.1f, 180.0f}, {180.1f, std::numeric_limits<float>::max()}}; + // clang-format off + {0.0f, 25.1f}, + {25.1f, 50.1f}, + {50.1f, 90.1f}, + {90.1f, 180.1f}, + {180.1f, std::numeric_limits<float>::max()} + // clang-format on + }; static float calculate_index(float value, const float array[NUM_LEVELS][2]) { int grid_index = get_grid_index(value, array); @@ -42,7 +61,10 @@ class CAQICalculator : public AbstractAQICalculator { static int get_grid_index(float value, const float array[NUM_LEVELS][2]) { for (int i = 0; i < NUM_LEVELS; i++) { - if (value >= array[i][0] && value <= array[i][1]) { + const bool in_range = + (value >= array[i][0]) && ((i == NUM_LEVELS - 1) ? (value <= array[i][1]) // last bucket inclusive + : (value < array[i][1])); // others exclusive on hi + if (in_range) { return i; } } From a99f75ca7102036544a3285f615a830fb7b01975 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 11 Feb 2026 08:45:06 +1300 Subject: [PATCH 0643/2030] Bump version to 2026.1.5 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 140ac06565..356739412b 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.1.4 +PROJECT_NUMBER = 2026.1.5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 862c7e37e6..e5c1162834 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.1.4" +__version__ = "2026.1.5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From c03abcdb861da71e2f51c596e8f46179a2124d87 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:53:53 -0600 Subject: [PATCH 0644/2030] [http_request] Reduce heap allocations in update check by parsing JSON directly from buffer (#13588) --- .../update/http_request_update.cpp | 24 +++++++------------ esphome/components/json/json_util.cpp | 7 +++++- esphome/components/json/json_util.h | 2 ++ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index c63e55d159..85609bd31f 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -90,16 +90,14 @@ void HttpRequestUpdate::update_task(void *params) { UPDATE_RETURN; } size_t read_index = container->get_bytes_read(); + size_t content_length = container->content_length; + + container->end(); + container.reset(); // Release ownership of the container's shared_ptr bool valid = false; - { // Ensures the response string falls out of scope and deallocates before the task ends - std::string response((char *) data, read_index); - allocator.deallocate(data, container->content_length); - - container->end(); - container.reset(); // Release ownership of the container's shared_ptr - - valid = json::parse_json(response, [this_update](JsonObject root) -> bool { + { // Scope to ensure JsonDocument is destroyed before deallocating buffer + valid = json::parse_json(data, read_index, [this_update](JsonObject root) -> bool { if (!root[ESPHOME_F("name")].is<const char *>() || !root[ESPHOME_F("version")].is<const char *>() || !root[ESPHOME_F("builds")].is<JsonArray>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); @@ -137,6 +135,7 @@ void HttpRequestUpdate::update_task(void *params) { return false; }); } + allocator.deallocate(data, content_length); if (!valid) { ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); @@ -157,17 +156,12 @@ void HttpRequestUpdate::update_task(void *params) { } } - { // Ensures the current version string falls out of scope and deallocates before the task ends - std::string current_version; #ifdef ESPHOME_PROJECT_VERSION - current_version = ESPHOME_PROJECT_VERSION; + this_update->update_info_.current_version = ESPHOME_PROJECT_VERSION; #else - current_version = ESPHOME_VERSION; + this_update->update_info_.current_version = ESPHOME_VERSION; #endif - this_update->update_info_.current_version = current_version; - } - bool trigger_update_available = false; if (this_update->update_info_.latest_version.empty() || diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index 869d29f92e..69f8bfc61a 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -25,8 +25,13 @@ std::string build_json(const json_build_t &f) { } bool parse_json(const std::string &data, const json_parse_t &f) { + // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + return parse_json(reinterpret_cast<const uint8_t *>(data.c_str()), data.size(), f); +} + +bool parse_json(const uint8_t *data, size_t len, const json_parse_t &f) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - JsonDocument doc = parse_json(reinterpret_cast<const uint8_t *>(data.c_str()), data.size()); + JsonDocument doc = parse_json(data, len); if (doc.overflowed() || doc.isNull()) return false; return f(doc.as<JsonObject>()); diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index 91cc84dc14..ca074926bd 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -50,6 +50,8 @@ std::string build_json(const json_build_t &f); /// Parse a JSON string and run the provided json parse function if it's valid. bool parse_json(const std::string &data, const json_parse_t &f); +/// Parse JSON from raw bytes and run the provided json parse function if it's valid. +bool parse_json(const uint8_t *data, size_t len, const json_parse_t &f); /// Parse a JSON string and return the root JsonDocument (or an unbound object on error) JsonDocument parse_json(const uint8_t *data, size_t len); From 727bb27611e185fecaf83bd3945ac8aebf420a55 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:54:07 -0600 Subject: [PATCH 0645/2030] [bmp3xx_base/bmp581_base] Convert oversampling and IIR filter strings to PROGMEM_STRING_TABLE (#13808) --- .../components/bmp3xx_base/bmp3xx_base.cpp | 47 ++++------------- .../components/bmp581_base/bmp581_base.cpp | 51 ++++--------------- 2 files changed, 20 insertions(+), 78 deletions(-) diff --git a/esphome/components/bmp3xx_base/bmp3xx_base.cpp b/esphome/components/bmp3xx_base/bmp3xx_base.cpp index d7d9972170..c781252de3 100644 --- a/esphome/components/bmp3xx_base/bmp3xx_base.cpp +++ b/esphome/components/bmp3xx_base/bmp3xx_base.cpp @@ -6,8 +6,9 @@ */ #include "bmp3xx_base.h" -#include "esphome/core/log.h" #include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include <cinttypes> namespace esphome { @@ -26,46 +27,18 @@ static const LogString *chip_type_to_str(uint8_t chip_type) { } } +// Oversampling strings indexed by Oversampling enum (0-5): NONE, X2, X4, X8, X16, X32 +PROGMEM_STRING_TABLE(OversamplingStrings, "None", "2x", "4x", "8x", "16x", "32x", ""); + static const LogString *oversampling_to_str(Oversampling oversampling) { - switch (oversampling) { - case Oversampling::OVERSAMPLING_NONE: - return LOG_STR("None"); - case Oversampling::OVERSAMPLING_X2: - return LOG_STR("2x"); - case Oversampling::OVERSAMPLING_X4: - return LOG_STR("4x"); - case Oversampling::OVERSAMPLING_X8: - return LOG_STR("8x"); - case Oversampling::OVERSAMPLING_X16: - return LOG_STR("16x"); - case Oversampling::OVERSAMPLING_X32: - return LOG_STR("32x"); - default: - return LOG_STR(""); - } + return OversamplingStrings::get_log_str(static_cast<uint8_t>(oversampling), OversamplingStrings::LAST_INDEX); } +// IIR filter strings indexed by IIRFilter enum (0-7): OFF, 2, 4, 8, 16, 32, 64, 128 +PROGMEM_STRING_TABLE(IIRFilterStrings, "OFF", "2x", "4x", "8x", "16x", "32x", "64x", "128x", ""); + static const LogString *iir_filter_to_str(IIRFilter filter) { - switch (filter) { - case IIRFilter::IIR_FILTER_OFF: - return LOG_STR("OFF"); - case IIRFilter::IIR_FILTER_2: - return LOG_STR("2x"); - case IIRFilter::IIR_FILTER_4: - return LOG_STR("4x"); - case IIRFilter::IIR_FILTER_8: - return LOG_STR("8x"); - case IIRFilter::IIR_FILTER_16: - return LOG_STR("16x"); - case IIRFilter::IIR_FILTER_32: - return LOG_STR("32x"); - case IIRFilter::IIR_FILTER_64: - return LOG_STR("64x"); - case IIRFilter::IIR_FILTER_128: - return LOG_STR("128x"); - default: - return LOG_STR(""); - } + return IIRFilterStrings::get_log_str(static_cast<uint8_t>(filter), IIRFilterStrings::LAST_INDEX); } void BMP3XXComponent::setup() { diff --git a/esphome/components/bmp581_base/bmp581_base.cpp b/esphome/components/bmp581_base/bmp581_base.cpp index 67c6771862..c4a96ebc39 100644 --- a/esphome/components/bmp581_base/bmp581_base.cpp +++ b/esphome/components/bmp581_base/bmp581_base.cpp @@ -11,57 +11,26 @@ */ #include "bmp581_base.h" -#include "esphome/core/log.h" #include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome::bmp581_base { static const char *const TAG = "bmp581"; +// Oversampling strings indexed by Oversampling enum (0-7): NONE, X2, X4, X8, X16, X32, X64, X128 +PROGMEM_STRING_TABLE(OversamplingStrings, "None", "2x", "4x", "8x", "16x", "32x", "64x", "128x", ""); + static const LogString *oversampling_to_str(Oversampling oversampling) { - switch (oversampling) { - case Oversampling::OVERSAMPLING_NONE: - return LOG_STR("None"); - case Oversampling::OVERSAMPLING_X2: - return LOG_STR("2x"); - case Oversampling::OVERSAMPLING_X4: - return LOG_STR("4x"); - case Oversampling::OVERSAMPLING_X8: - return LOG_STR("8x"); - case Oversampling::OVERSAMPLING_X16: - return LOG_STR("16x"); - case Oversampling::OVERSAMPLING_X32: - return LOG_STR("32x"); - case Oversampling::OVERSAMPLING_X64: - return LOG_STR("64x"); - case Oversampling::OVERSAMPLING_X128: - return LOG_STR("128x"); - default: - return LOG_STR(""); - } + return OversamplingStrings::get_log_str(static_cast<uint8_t>(oversampling), OversamplingStrings::LAST_INDEX); } +// IIR filter strings indexed by IIRFilter enum (0-7): OFF, 2, 4, 8, 16, 32, 64, 128 +PROGMEM_STRING_TABLE(IIRFilterStrings, "OFF", "2x", "4x", "8x", "16x", "32x", "64x", "128x", ""); + static const LogString *iir_filter_to_str(IIRFilter filter) { - switch (filter) { - case IIRFilter::IIR_FILTER_OFF: - return LOG_STR("OFF"); - case IIRFilter::IIR_FILTER_2: - return LOG_STR("2x"); - case IIRFilter::IIR_FILTER_4: - return LOG_STR("4x"); - case IIRFilter::IIR_FILTER_8: - return LOG_STR("8x"); - case IIRFilter::IIR_FILTER_16: - return LOG_STR("16x"); - case IIRFilter::IIR_FILTER_32: - return LOG_STR("32x"); - case IIRFilter::IIR_FILTER_64: - return LOG_STR("64x"); - case IIRFilter::IIR_FILTER_128: - return LOG_STR("128x"); - default: - return LOG_STR(""); - } + return IIRFilterStrings::get_log_str(static_cast<uint8_t>(filter), IIRFilterStrings::LAST_INDEX); } void BMP581Component::dump_config() { From 2a6d9d632505b5ccfef1678bdfe69f30c9d9b8df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:54:22 -0600 Subject: [PATCH 0646/2030] [mqtt] Avoid heap allocation in on_log by using const char* publish overload (#13809) --- esphome/components/mqtt/mqtt_client.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index d503461257..90b423c386 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -170,10 +170,8 @@ void MQTTClientComponent::send_device_info_() { void MQTTClientComponent::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) { (void) tag; if (level <= this->log_level_ && this->is_connected()) { - this->publish({.topic = this->log_message_.topic, - .payload = std::string(message, message_len), - .qos = this->log_message_.qos, - .retain = this->log_message_.retain}); + this->publish(this->log_message_.topic.c_str(), message, message_len, this->log_message_.qos, + this->log_message_.retain); } } #endif From 86feb4e27a3f4943197b19485fb7f83c64300269 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:54:37 -0600 Subject: [PATCH 0647/2030] [rtttl] Convert state_to_string to PROGMEM_STRING_TABLE (#13807) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index c179282c50..5a64f37da4 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -2,6 +2,7 @@ #include <cmath> #include "esphome/core/hal.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" namespace esphome { namespace rtttl { @@ -375,22 +376,13 @@ void Rtttl::loop() { } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE +// RTTTL state strings indexed by State enum (0-4): STOPPED, INIT, STARTING, RUNNING, STOPPING, plus UNKNOWN fallback +PROGMEM_STRING_TABLE(RtttlStateStrings, "STATE_STOPPED", "STATE_INIT", "STATE_STARTING", "STATE_RUNNING", + "STATE_STOPPING", "UNKNOWN"); + static const LogString *state_to_string(State state) { - switch (state) { - case STATE_STOPPED: - return LOG_STR("STATE_STOPPED"); - case STATE_STARTING: - return LOG_STR("STATE_STARTING"); - case STATE_RUNNING: - return LOG_STR("STATE_RUNNING"); - case STATE_STOPPING: - return LOG_STR("STATE_STOPPING"); - case STATE_INIT: - return LOG_STR("STATE_INIT"); - default: - return LOG_STR("UNKNOWN"); - } -}; + return RtttlStateStrings::get_log_str(static_cast<uint8_t>(state), RtttlStateStrings::LAST_INDEX); +} #endif void Rtttl::set_state_(State state) { From 5365faa8773c889de4e31c7eac16a6db23b760ce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:54:48 -0600 Subject: [PATCH 0648/2030] [debug] Move ESP8266 switch tables to flash with PROGMEM_STRING_TABLE (#13813) --- esphome/components/debug/debug_esp8266.cpp | 68 +++++++++++----------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index a4b6468b49..1a07ec4f3a 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -1,6 +1,7 @@ #include "debug_component.h" #ifdef USE_ESP8266 #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include <Esp.h> extern "C" { @@ -19,27 +20,38 @@ namespace debug { static const char *const TAG = "debug"; +// PROGMEM string table for reset reasons, indexed by reason code (0-6), with "Unknown" as fallback +// clang-format off +PROGMEM_STRING_TABLE(ResetReasonStrings, + "Power On", // 0 = REASON_DEFAULT_RST + "Hardware Watchdog", // 1 = REASON_WDT_RST + "Exception", // 2 = REASON_EXCEPTION_RST + "Software Watchdog", // 3 = REASON_SOFT_WDT_RST + "Software/System restart", // 4 = REASON_SOFT_RESTART + "Deep-Sleep Wake", // 5 = REASON_DEEP_SLEEP_AWAKE + "External System", // 6 = REASON_EXT_SYS_RST + "Unknown" // 7 = fallback +); +// clang-format on +static_assert(REASON_DEFAULT_RST == 0, "Reset reason enum values must match table indices"); +static_assert(REASON_WDT_RST == 1, "Reset reason enum values must match table indices"); +static_assert(REASON_EXCEPTION_RST == 2, "Reset reason enum values must match table indices"); +static_assert(REASON_SOFT_WDT_RST == 3, "Reset reason enum values must match table indices"); +static_assert(REASON_SOFT_RESTART == 4, "Reset reason enum values must match table indices"); +static_assert(REASON_DEEP_SLEEP_AWAKE == 5, "Reset reason enum values must match table indices"); +static_assert(REASON_EXT_SYS_RST == 6, "Reset reason enum values must match table indices"); + +// PROGMEM string table for flash chip modes, indexed by mode code (0-3), with "UNKNOWN" as fallback +PROGMEM_STRING_TABLE(FlashModeStrings, "QIO", "QOUT", "DIO", "DOUT", "UNKNOWN"); +static_assert(FM_QIO == 0, "Flash mode enum values must match table indices"); +static_assert(FM_QOUT == 1, "Flash mode enum values must match table indices"); +static_assert(FM_DIO == 2, "Flash mode enum values must match table indices"); +static_assert(FM_DOUT == 3, "Flash mode enum values must match table indices"); + // Get reset reason string from reason code (no heap allocation) // Returns LogString* pointing to flash (PROGMEM) on ESP8266 static const LogString *get_reset_reason_str(uint32_t reason) { - switch (reason) { - case REASON_DEFAULT_RST: - return LOG_STR("Power On"); - case REASON_WDT_RST: - return LOG_STR("Hardware Watchdog"); - case REASON_EXCEPTION_RST: - return LOG_STR("Exception"); - case REASON_SOFT_WDT_RST: - return LOG_STR("Software Watchdog"); - case REASON_SOFT_RESTART: - return LOG_STR("Software/System restart"); - case REASON_DEEP_SLEEP_AWAKE: - return LOG_STR("Deep-Sleep Wake"); - case REASON_EXT_SYS_RST: - return LOG_STR("External System"); - default: - return LOG_STR("Unknown"); - } + return ResetReasonStrings::get_log_str(static_cast<uint8_t>(reason), ResetReasonStrings::LAST_INDEX); } // Size for core version hex buffer @@ -92,23 +104,9 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> constexpr size_t size = DEVICE_INFO_BUFFER_SIZE; char *buf = buffer.data(); - const LogString *flash_mode; - switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance) - case FM_QIO: - flash_mode = LOG_STR("QIO"); - break; - case FM_QOUT: - flash_mode = LOG_STR("QOUT"); - break; - case FM_DIO: - flash_mode = LOG_STR("DIO"); - break; - case FM_DOUT: - flash_mode = LOG_STR("DOUT"); - break; - default: - flash_mode = LOG_STR("UNKNOWN"); - } + const LogString *flash_mode = FlashModeStrings::get_log_str( + static_cast<uint8_t>(ESP.getFlashChipMode()), // NOLINT(readability-static-accessed-through-instance) + FlashModeStrings::LAST_INDEX); uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT(readability-static-accessed-through-instance) uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT(readability-static-accessed-through-instance) ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, From e2fad9a6c911b6c60663db91a9cf30d8ab4ee991 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:55:01 -0600 Subject: [PATCH 0649/2030] [sprinkler] Convert state and request origin strings to PROGMEM_STRING_TABLE (#13806) --- esphome/components/sprinkler/sprinkler.cpp | 42 ++++++---------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index eae6ecbf31..9e423c1760 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -4,6 +4,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include <cinttypes> #include <utility> @@ -1544,42 +1545,19 @@ void Sprinkler::log_multiplier_zero_warning_(const LogString *method_name) { ESP_LOGW(TAG, "%s called but multiplier is set to zero; no action taken", LOG_STR_ARG(method_name)); } +// Request origin strings indexed by SprinklerValveRunRequestOrigin enum (0-2): USER, CYCLE, QUEUE +PROGMEM_STRING_TABLE(SprinklerRequestOriginStrings, "USER", "CYCLE", "QUEUE", "UNKNOWN"); + const LogString *Sprinkler::req_as_str_(SprinklerValveRunRequestOrigin origin) { - switch (origin) { - case USER: - return LOG_STR("USER"); - - case CYCLE: - return LOG_STR("CYCLE"); - - case QUEUE: - return LOG_STR("QUEUE"); - - default: - return LOG_STR("UNKNOWN"); - } + return SprinklerRequestOriginStrings::get_log_str(static_cast<uint8_t>(origin), + SprinklerRequestOriginStrings::LAST_INDEX); } +// Sprinkler state strings indexed by SprinklerState enum (0-4): IDLE, STARTING, ACTIVE, STOPPING, BYPASS +PROGMEM_STRING_TABLE(SprinklerStateStrings, "IDLE", "STARTING", "ACTIVE", "STOPPING", "BYPASS", "UNKNOWN"); + const LogString *Sprinkler::state_as_str_(SprinklerState state) { - switch (state) { - case IDLE: - return LOG_STR("IDLE"); - - case STARTING: - return LOG_STR("STARTING"); - - case ACTIVE: - return LOG_STR("ACTIVE"); - - case STOPPING: - return LOG_STR("STOPPING"); - - case BYPASS: - return LOG_STR("BYPASS"); - - default: - return LOG_STR("UNKNOWN"); - } + return SprinklerStateStrings::get_log_str(static_cast<uint8_t>(state), SprinklerStateStrings::LAST_INDEX); } void Sprinkler::start_timer_(const SprinklerTimerIndex timer_index) { From c65d3a0072d9d7e2202b6d657c41d035b2a9fa90 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:55:16 -0600 Subject: [PATCH 0650/2030] [mqtt] Add zero-allocation topic getters to MQTT_COMPONENT_CUSTOM_TOPIC macro (#13811) --- esphome/components/mqtt/mqtt_climate.cpp | 34 +++++++++++++----------- esphome/components/mqtt/mqtt_component.h | 5 ++++ esphome/components/mqtt/mqtt_cover.cpp | 6 ++--- esphome/components/mqtt/mqtt_fan.cpp | 9 ++++--- esphome/components/mqtt/mqtt_valve.cpp | 4 +-- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 158cfb5552..81b2e0e8db 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -300,9 +300,11 @@ const EntityBase *MQTTClimateComponent::get_entity() const { return this->device bool MQTTClimateComponent::publish_state_() { auto traits = this->device_->get_traits(); + // Reusable stack buffer for topic construction (avoids heap allocation per publish) + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; // mode bool success = true; - if (!this->publish(this->get_mode_state_topic(), climate_mode_to_mqtt_str(this->device_->mode))) + if (!this->publish(this->get_mode_state_topic_to(topic_buf), climate_mode_to_mqtt_str(this->device_->mode))) success = false; int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); @@ -311,68 +313,70 @@ bool MQTTClimateComponent::publish_state_() { if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE) && !std::isnan(this->device_->current_temperature)) { len = value_accuracy_to_buf(payload, this->device_->current_temperature, current_accuracy); - if (!this->publish(this->get_current_temperature_state_topic(), payload, len)) + if (!this->publish(this->get_current_temperature_state_topic_to(topic_buf), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { len = value_accuracy_to_buf(payload, this->device_->target_temperature_low, target_accuracy); - if (!this->publish(this->get_target_temperature_low_state_topic(), payload, len)) + if (!this->publish(this->get_target_temperature_low_state_topic_to(topic_buf), payload, len)) success = false; len = value_accuracy_to_buf(payload, this->device_->target_temperature_high, target_accuracy); - if (!this->publish(this->get_target_temperature_high_state_topic(), payload, len)) + if (!this->publish(this->get_target_temperature_high_state_topic_to(topic_buf), payload, len)) success = false; } else { len = value_accuracy_to_buf(payload, this->device_->target_temperature, target_accuracy); - if (!this->publish(this->get_target_temperature_state_topic(), payload, len)) + if (!this->publish(this->get_target_temperature_state_topic_to(topic_buf), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY) && !std::isnan(this->device_->current_humidity)) { len = value_accuracy_to_buf(payload, this->device_->current_humidity, 0); - if (!this->publish(this->get_current_humidity_state_topic(), payload, len)) + if (!this->publish(this->get_current_humidity_state_topic_to(topic_buf), payload, len)) success = false; } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY) && !std::isnan(this->device_->target_humidity)) { len = value_accuracy_to_buf(payload, this->device_->target_humidity, 0); - if (!this->publish(this->get_target_humidity_state_topic(), payload, len)) + if (!this->publish(this->get_target_humidity_state_topic_to(topic_buf), payload, len)) success = false; } if (traits.get_supports_presets() || !traits.get_supported_custom_presets().empty()) { if (this->device_->has_custom_preset()) { - if (!this->publish(this->get_preset_state_topic(), this->device_->get_custom_preset())) + if (!this->publish(this->get_preset_state_topic_to(topic_buf), this->device_->get_custom_preset().c_str())) success = false; } else if (this->device_->preset.has_value()) { - if (!this->publish(this->get_preset_state_topic(), climate_preset_to_mqtt_str(this->device_->preset.value()))) + if (!this->publish(this->get_preset_state_topic_to(topic_buf), + climate_preset_to_mqtt_str(this->device_->preset.value()))) success = false; - } else if (!this->publish(this->get_preset_state_topic(), "")) { + } else if (!this->publish(this->get_preset_state_topic_to(topic_buf), "")) { success = false; } } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { - if (!this->publish(this->get_action_state_topic(), climate_action_to_mqtt_str(this->device_->action))) + if (!this->publish(this->get_action_state_topic_to(topic_buf), climate_action_to_mqtt_str(this->device_->action))) success = false; } if (traits.get_supports_fan_modes()) { if (this->device_->has_custom_fan_mode()) { - if (!this->publish(this->get_fan_mode_state_topic(), this->device_->get_custom_fan_mode())) + if (!this->publish(this->get_fan_mode_state_topic_to(topic_buf), this->device_->get_custom_fan_mode().c_str())) success = false; } else if (this->device_->fan_mode.has_value()) { - if (!this->publish(this->get_fan_mode_state_topic(), + if (!this->publish(this->get_fan_mode_state_topic_to(topic_buf), climate_fan_mode_to_mqtt_str(this->device_->fan_mode.value()))) success = false; - } else if (!this->publish(this->get_fan_mode_state_topic(), "")) { + } else if (!this->publish(this->get_fan_mode_state_topic_to(topic_buf), "")) { success = false; } } if (traits.get_supports_swing_modes()) { - if (!this->publish(this->get_swing_mode_state_topic(), climate_swing_mode_to_mqtt_str(this->device_->swing_mode))) + if (!this->publish(this->get_swing_mode_state_topic_to(topic_buf), + climate_swing_mode_to_mqtt_str(this->device_->swing_mode))) success = false; } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index eb98158647..853712940a 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -59,6 +59,11 @@ void log_mqtt_component(const char *tag, MQTTComponent *obj, bool state_topic, b \ public: \ void set_custom_##name##_##type##_topic(const std::string &topic) { this->custom_##name##_##type##_topic_ = topic; } \ + StringRef get_##name##_##type##_topic_to(std::span<char, MQTT_DEFAULT_TOPIC_MAX_LEN> buf) const { \ + if (!this->custom_##name##_##type##_topic_.empty()) \ + return StringRef(this->custom_##name##_##type##_topic_.data(), this->custom_##name##_##type##_topic_.size()); \ + return this->get_default_topic_for_to_(buf, #name "/" #type, sizeof(#name "/" #type) - 1); \ + } \ std::string get_##name##_##type##_topic() const { \ if (this->custom_##name##_##type##_topic_.empty()) \ return this->get_default_topic_for_(#name "/" #type); \ diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index 50e68ecbcc..c21af413ed 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -112,19 +112,19 @@ bool MQTTCoverComponent::send_initial_state() { return this->publish_state(); } bool MQTTCoverComponent::publish_state() { auto traits = this->cover_->get_traits(); bool success = true; + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; if (traits.get_supports_position()) { char pos[VALUE_ACCURACY_MAX_LEN]; size_t len = value_accuracy_to_buf(pos, roundf(this->cover_->position * 100), 0); - if (!this->publish(this->get_position_state_topic(), pos, len)) + if (!this->publish(this->get_position_state_topic_to(topic_buf), pos, len)) success = false; } if (traits.get_supports_tilt()) { char pos[VALUE_ACCURACY_MAX_LEN]; size_t len = value_accuracy_to_buf(pos, roundf(this->cover_->tilt * 100), 0); - if (!this->publish(this->get_tilt_state_topic(), pos, len)) + if (!this->publish(this->get_tilt_state_topic_to(topic_buf), pos, len)) success = false; } - char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; if (!this->publish(this->get_state_topic_to_(topic_buf), cover_state_to_mqtt_str(this->cover_->current_operation, this->cover_->position, traits.get_supports_position()))) diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index 84d51895c5..ae2b8c4600 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -173,19 +173,20 @@ bool MQTTFanComponent::publish_state() { this->publish(this->get_state_topic_to_(topic_buf), state_s); bool failed = false; if (this->state_->get_traits().supports_direction()) { - bool success = this->publish(this->get_direction_state_topic(), fan_direction_to_mqtt_str(this->state_->direction)); + bool success = this->publish(this->get_direction_state_topic_to(topic_buf), + fan_direction_to_mqtt_str(this->state_->direction)); failed = failed || !success; } if (this->state_->get_traits().supports_oscillation()) { - bool success = - this->publish(this->get_oscillation_state_topic(), fan_oscillation_to_mqtt_str(this->state_->oscillating)); + bool success = this->publish(this->get_oscillation_state_topic_to(topic_buf), + fan_oscillation_to_mqtt_str(this->state_->oscillating)); failed = failed || !success; } auto traits = this->state_->get_traits(); if (traits.supports_speed()) { char buf[12]; size_t len = buf_append_printf(buf, sizeof(buf), 0, "%d", this->state_->speed); - bool success = this->publish(this->get_speed_level_state_topic(), buf, len); + bool success = this->publish(this->get_speed_level_state_topic_to(topic_buf), buf, len); failed = failed || !success; } return !failed; diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 16e25f6a8a..2b9f02858b 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -87,13 +87,13 @@ bool MQTTValveComponent::send_initial_state() { return this->publish_state(); } bool MQTTValveComponent::publish_state() { auto traits = this->valve_->get_traits(); bool success = true; + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; if (traits.get_supports_position()) { char pos[VALUE_ACCURACY_MAX_LEN]; size_t len = value_accuracy_to_buf(pos, roundf(this->valve_->position * 100), 0); - if (!this->publish(this->get_position_state_topic(), pos, len)) + if (!this->publish(this->get_position_state_topic_to(topic_buf), pos, len)) success = false; } - char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; if (!this->publish(this->get_state_topic_to_(topic_buf), valve_state_to_mqtt_str(this->valve_->current_operation, this->valve_->position, traits.get_supports_position()))) From 868a2151e3ef63606e933257e49200216fe50eb2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 13:56:12 -0600 Subject: [PATCH 0651/2030] [web_server_idf] Reduce heap allocations by using stack buffers (#13549) --- .../web_server_idf/web_server_idf.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index ac7f99bef7..0dd1948dcc 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -344,14 +344,15 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw memcpy(user_info + user_len + 1, password, pass_len); user_info[user_info_len] = '\0'; - size_t n = 0, out; - esp_crypto_base64_encode(nullptr, 0, &n, reinterpret_cast<const uint8_t *>(user_info), user_info_len); - - auto digest = std::unique_ptr<char[]>(new char[n + 1]); - esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest.get()), n, &out, + // Base64 output size is ceil(input_len * 4/3) + 1, with input bounded to 256 bytes + // max output is ceil(256 * 4/3) + 1 = 343 bytes, use 350 for safety + constexpr size_t max_digest_len = 350; + char digest[max_digest_len]; + size_t out; + esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest), max_digest_len, &out, reinterpret_cast<const uint8_t *>(user_info), user_info_len); - return strcmp(digest.get(), auth_str + auth_prefix_len) == 0; + return strcmp(digest, auth_str + auth_prefix_len) == 0; } void AsyncWebServerRequest::requestAuthentication(const char *realm) const { @@ -861,12 +862,12 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c } }); - // Process data - std::unique_ptr<char[]> buffer(new char[MULTIPART_CHUNK_SIZE]); + // Process data - use stack buffer to avoid heap allocation + char buffer[MULTIPART_CHUNK_SIZE]; size_t bytes_since_yield = 0; for (size_t remaining = r->content_len; remaining > 0;) { - int recv_len = httpd_req_recv(r, buffer.get(), std::min(remaining, MULTIPART_CHUNK_SIZE)); + int recv_len = httpd_req_recv(r, buffer, std::min(remaining, MULTIPART_CHUNK_SIZE)); if (recv_len <= 0) { httpd_resp_send_err(r, recv_len == HTTPD_SOCK_ERR_TIMEOUT ? HTTPD_408_REQ_TIMEOUT : HTTPD_400_BAD_REQUEST, @@ -874,7 +875,7 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c return recv_len == HTTPD_SOCK_ERR_TIMEOUT ? ESP_ERR_TIMEOUT : ESP_FAIL; } - if (reader->parse(buffer.get(), recv_len) != static_cast<size_t>(recv_len)) { + if (reader->parse(buffer, recv_len) != static_cast<size_t>(recv_len)) { ESP_LOGW(TAG, "Multipart parser error"); httpd_resp_send_err(r, HTTPD_400_BAD_REQUEST, nullptr); return ESP_FAIL; From d152438335c21a1590da26f0a3b3fd19d3d480aa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 14:07:09 -0600 Subject: [PATCH 0652/2030] [libretiny] Update LibreTiny to v1.12.1 (#13851) --- .clang-tidy.hash | 2 +- esphome/components/bk72xx/boards.py | 23 +- esphome/components/libretiny/__init__.py | 10 +- esphome/components/ln882x/boards.py | 126 ++++--- esphome/components/rtl87xx/boards.py | 420 +++++++++++++++++++++-- platformio.ini | 2 +- 6 files changed, 474 insertions(+), 109 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 37f82e2755..3ffe32af88 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -8dc4dae0acfa22f26c7cde87fc24e60b27f29a73300e02189b78f0315e5d0695 +74867fc82764102ce1275ea2bc43e3aeee7619679537c6db61114a33342bb4c7 diff --git a/esphome/components/bk72xx/boards.py b/esphome/components/bk72xx/boards.py index 3850dbe266..4bee69fe6d 100644 --- a/esphome/components/bk72xx/boards.py +++ b/esphome/components/bk72xx/boards.py @@ -159,6 +159,10 @@ BK72XX_BOARD_PINS = { "A0": 23, }, "cbu": { + "SPI0_CS": 15, + "SPI0_MISO": 17, + "SPI0_MOSI": 16, + "SPI0_SCK": 14, "WIRE1_SCL": 20, "WIRE1_SDA": 21, "WIRE2_SCL": 0, @@ -227,6 +231,10 @@ BK72XX_BOARD_PINS = { "A0": 23, }, "generic-bk7231t-qfn32-tuya": { + "SPI0_CS": 15, + "SPI0_MISO": 17, + "SPI0_MOSI": 16, + "SPI0_SCK": 14, "WIRE1_SCL": 20, "WIRE1_SDA": 21, "WIRE2_SCL": 0, @@ -295,6 +303,10 @@ BK72XX_BOARD_PINS = { "A0": 23, }, "generic-bk7231n-qfn32-tuya": { + "SPI0_CS": 15, + "SPI0_MISO": 17, + "SPI0_MOSI": 16, + "SPI0_SCK": 14, "WIRE1_SCL": 20, "WIRE1_SDA": 21, "WIRE2_SCL": 0, @@ -485,8 +497,7 @@ BK72XX_BOARD_PINS = { }, "cb3s": { "WIRE1_SCL": 20, - "WIRE1_SDA_0": 21, - "WIRE1_SDA_1": 21, + "WIRE1_SDA": 21, "SERIAL1_RX": 10, "SERIAL1_TX": 11, "SERIAL2_TX": 0, @@ -647,6 +658,10 @@ BK72XX_BOARD_PINS = { "A0": 23, }, "generic-bk7252": { + "SPI0_CS": 15, + "SPI0_MISO": 17, + "SPI0_MOSI": 16, + "SPI0_SCK": 14, "WIRE1_SCL": 20, "WIRE1_SDA": 21, "WIRE2_SCL": 0, @@ -1096,6 +1111,10 @@ BK72XX_BOARD_PINS = { "A0": 23, }, "cb3se": { + "SPI0_CS": 15, + "SPI0_MISO": 17, + "SPI0_MOSI": 16, + "SPI0_SCK": 14, "WIRE2_SCL": 0, "WIRE2_SDA": 1, "SERIAL1_RX": 10, diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 553179beec..01445da7ee 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -193,14 +193,14 @@ def _notify_old_style(config): # The dev and latest branches will be at *least* this version, which is what matters. # Use GitHub releases directly to avoid PlatformIO moderation delays. ARDUINO_VERSIONS = { - "dev": (cv.Version(1, 11, 0), "https://github.com/libretiny-eu/libretiny.git"), + "dev": (cv.Version(1, 12, 1), "https://github.com/libretiny-eu/libretiny.git"), "latest": ( - cv.Version(1, 11, 0), - "https://github.com/libretiny-eu/libretiny.git#v1.11.0", + cv.Version(1, 12, 1), + "https://github.com/libretiny-eu/libretiny.git#v1.12.1", ), "recommended": ( - cv.Version(1, 11, 0), - "https://github.com/libretiny-eu/libretiny.git#v1.11.0", + cv.Version(1, 12, 1), + "https://github.com/libretiny-eu/libretiny.git#v1.12.1", ), } diff --git a/esphome/components/ln882x/boards.py b/esphome/components/ln882x/boards.py index 600371951d..df44419ed2 100644 --- a/esphome/components/ln882x/boards.py +++ b/esphome/components/ln882x/boards.py @@ -154,28 +154,26 @@ LN882X_BOARD_PINS = { "A7": 21, }, "wb02a": { - "WIRE0_SCL_0": 7, - "WIRE0_SCL_1": 5, + "WIRE0_SCL_0": 1, + "WIRE0_SCL_1": 2, "WIRE0_SCL_2": 3, - "WIRE0_SCL_3": 10, - "WIRE0_SCL_4": 2, - "WIRE0_SCL_5": 1, - "WIRE0_SCL_6": 4, - "WIRE0_SCL_7": 5, - "WIRE0_SCL_8": 9, - "WIRE0_SCL_9": 24, - "WIRE0_SCL_10": 25, - "WIRE0_SDA_0": 7, - "WIRE0_SDA_1": 5, + "WIRE0_SCL_3": 4, + "WIRE0_SCL_4": 5, + "WIRE0_SCL_5": 7, + "WIRE0_SCL_6": 9, + "WIRE0_SCL_7": 10, + "WIRE0_SCL_8": 24, + "WIRE0_SCL_9": 25, + "WIRE0_SDA_0": 1, + "WIRE0_SDA_1": 2, "WIRE0_SDA_2": 3, - "WIRE0_SDA_3": 10, - "WIRE0_SDA_4": 2, - "WIRE0_SDA_5": 1, - "WIRE0_SDA_6": 4, - "WIRE0_SDA_7": 5, - "WIRE0_SDA_8": 9, - "WIRE0_SDA_9": 24, - "WIRE0_SDA_10": 25, + "WIRE0_SDA_3": 4, + "WIRE0_SDA_4": 5, + "WIRE0_SDA_5": 7, + "WIRE0_SDA_6": 9, + "WIRE0_SDA_7": 10, + "WIRE0_SDA_8": 24, + "WIRE0_SDA_9": 25, "SERIAL0_RX": 3, "SERIAL0_TX": 2, "SERIAL1_RX": 24, @@ -221,32 +219,32 @@ LN882X_BOARD_PINS = { "A1": 4, }, "wl2s": { - "WIRE0_SCL_0": 7, - "WIRE0_SCL_1": 12, - "WIRE0_SCL_2": 3, - "WIRE0_SCL_3": 10, - "WIRE0_SCL_4": 2, - "WIRE0_SCL_5": 0, - "WIRE0_SCL_6": 19, - "WIRE0_SCL_7": 11, - "WIRE0_SCL_8": 9, - "WIRE0_SCL_9": 24, - "WIRE0_SCL_10": 25, - "WIRE0_SCL_11": 5, - "WIRE0_SCL_12": 1, - "WIRE0_SDA_0": 7, - "WIRE0_SDA_1": 12, - "WIRE0_SDA_2": 3, - "WIRE0_SDA_3": 10, - "WIRE0_SDA_4": 2, - "WIRE0_SDA_5": 0, - "WIRE0_SDA_6": 19, - "WIRE0_SDA_7": 11, - "WIRE0_SDA_8": 9, - "WIRE0_SDA_9": 24, - "WIRE0_SDA_10": 25, - "WIRE0_SDA_11": 5, - "WIRE0_SDA_12": 1, + "WIRE0_SCL_0": 0, + "WIRE0_SCL_1": 1, + "WIRE0_SCL_2": 2, + "WIRE0_SCL_3": 3, + "WIRE0_SCL_4": 5, + "WIRE0_SCL_5": 7, + "WIRE0_SCL_6": 9, + "WIRE0_SCL_7": 10, + "WIRE0_SCL_8": 11, + "WIRE0_SCL_9": 12, + "WIRE0_SCL_10": 19, + "WIRE0_SCL_11": 24, + "WIRE0_SCL_12": 25, + "WIRE0_SDA_0": 0, + "WIRE0_SDA_1": 1, + "WIRE0_SDA_2": 2, + "WIRE0_SDA_3": 3, + "WIRE0_SDA_4": 5, + "WIRE0_SDA_5": 7, + "WIRE0_SDA_6": 9, + "WIRE0_SDA_7": 10, + "WIRE0_SDA_8": 11, + "WIRE0_SDA_9": 12, + "WIRE0_SDA_10": 19, + "WIRE0_SDA_11": 24, + "WIRE0_SDA_12": 25, "SERIAL0_RX": 3, "SERIAL0_TX": 2, "SERIAL1_RX": 24, @@ -301,24 +299,24 @@ LN882X_BOARD_PINS = { "A2": 1, }, "ln-02": { - "WIRE0_SCL_0": 11, - "WIRE0_SCL_1": 19, - "WIRE0_SCL_2": 3, - "WIRE0_SCL_3": 24, - "WIRE0_SCL_4": 2, - "WIRE0_SCL_5": 25, - "WIRE0_SCL_6": 1, - "WIRE0_SCL_7": 0, - "WIRE0_SCL_8": 9, - "WIRE0_SDA_0": 11, - "WIRE0_SDA_1": 19, - "WIRE0_SDA_2": 3, - "WIRE0_SDA_3": 24, - "WIRE0_SDA_4": 2, - "WIRE0_SDA_5": 25, - "WIRE0_SDA_6": 1, - "WIRE0_SDA_7": 0, - "WIRE0_SDA_8": 9, + "WIRE0_SCL_0": 0, + "WIRE0_SCL_1": 1, + "WIRE0_SCL_2": 2, + "WIRE0_SCL_3": 3, + "WIRE0_SCL_4": 9, + "WIRE0_SCL_5": 11, + "WIRE0_SCL_6": 19, + "WIRE0_SCL_7": 24, + "WIRE0_SCL_8": 25, + "WIRE0_SDA_0": 0, + "WIRE0_SDA_1": 1, + "WIRE0_SDA_2": 2, + "WIRE0_SDA_3": 3, + "WIRE0_SDA_4": 9, + "WIRE0_SDA_5": 11, + "WIRE0_SDA_6": 19, + "WIRE0_SDA_7": 24, + "WIRE0_SDA_8": 25, "SERIAL0_RX": 3, "SERIAL0_TX": 2, "SERIAL1_RX": 24, diff --git a/esphome/components/rtl87xx/boards.py b/esphome/components/rtl87xx/boards.py index 45ef02b7e7..3a5ee853f2 100644 --- a/esphome/components/rtl87xx/boards.py +++ b/esphome/components/rtl87xx/boards.py @@ -71,6 +71,10 @@ RTL87XX_BOARDS = { "name": "WR3L Wi-Fi Module", "family": FAMILY_RTL8710B, }, + "wbru": { + "name": "WBRU Wi-Fi Module", + "family": FAMILY_RTL8720C, + }, "wr2le": { "name": "WR2LE Wi-Fi Module", "family": FAMILY_RTL8710B, @@ -83,6 +87,14 @@ RTL87XX_BOARDS = { "name": "T103_V1.0", "family": FAMILY_RTL8710B, }, + "cr3l": { + "name": "CR3L Wi-Fi Module", + "family": FAMILY_RTL8720C, + }, + "generic-rtl8720cm-4mb-1712k": { + "name": "Generic - RTL8720CM (4M/1712k)", + "family": FAMILY_RTL8720C, + }, "generic-rtl8720cf-2mb-896k": { "name": "Generic - RTL8720CF (2M/896k)", "family": FAMILY_RTL8720C, @@ -103,6 +115,10 @@ RTL87XX_BOARDS = { "name": "WR2L Wi-Fi Module", "family": FAMILY_RTL8710B, }, + "wbr1": { + "name": "WBR1 Wi-Fi Module", + "family": FAMILY_RTL8720C, + }, "wr1": { "name": "WR1 Wi-Fi Module", "family": FAMILY_RTL8710B, @@ -119,10 +135,10 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, "WIRE1_SDA": 23, "SERIAL0_CTS": 19, @@ -230,10 +246,10 @@ RTL87XX_BOARD_PINS = { "A1": 41, }, "wbr3": { - "WIRE0_SCL_0": 11, - "WIRE0_SCL_1": 2, - "WIRE0_SCL_2": 19, - "WIRE0_SCL_3": 15, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 11, + "WIRE0_SCL_2": 15, + "WIRE0_SCL_3": 19, "WIRE0_SDA_0": 3, "WIRE0_SDA_1": 12, "WIRE0_SDA_2": 16, @@ -242,10 +258,10 @@ RTL87XX_BOARD_PINS = { "SERIAL0_TX_0": 11, "SERIAL0_TX_1": 14, "SERIAL1_CTS": 4, - "SERIAL1_RX_0": 2, - "SERIAL1_RX_1": 0, - "SERIAL1_TX_0": 3, - "SERIAL1_TX_1": 1, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX_0": 1, + "SERIAL1_TX_1": 3, "SERIAL2_CTS": 19, "SERIAL2_RX": 15, "SERIAL2_TX": 16, @@ -296,6 +312,12 @@ RTL87XX_BOARD_PINS = { }, "generic-rtl8710bn-2mb-468k": { "SPI0_CS": 19, + "SPI0_FCS": 6, + "SPI0_FD0": 9, + "SPI0_FD1": 7, + "SPI0_FD2": 8, + "SPI0_FD3": 11, + "SPI0_FSCK": 10, "SPI0_MISO": 22, "SPI0_MOSI": 23, "SPI0_SCK": 18, @@ -396,10 +418,10 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, "WIRE1_SDA": 23, "SERIAL0_CTS": 19, @@ -463,10 +485,10 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, "WIRE1_SDA": 23, "SERIAL0_CTS": 19, @@ -714,6 +736,12 @@ RTL87XX_BOARD_PINS = { }, "generic-rtl8710bn-2mb-788k": { "SPI0_CS": 19, + "SPI0_FCS": 6, + "SPI0_FD0": 9, + "SPI0_FD1": 7, + "SPI0_FD2": 8, + "SPI0_FD3": 11, + "SPI0_FSCK": 10, "SPI0_MISO": 22, "SPI0_MOSI": 23, "SPI0_SCK": 18, @@ -807,6 +835,12 @@ RTL87XX_BOARD_PINS = { }, "generic-rtl8710bx-4mb-980k": { "SPI0_CS": 19, + "SPI0_FCS": 6, + "SPI0_FD0": 9, + "SPI0_FD1": 7, + "SPI0_FD2": 8, + "SPI0_FD3": 11, + "SPI0_FSCK": 10, "SPI0_MISO": 22, "SPI0_MOSI": 23, "SPI0_SCK": 18, @@ -957,8 +991,8 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, "WIRE0_SDA_0": 19, "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, @@ -1088,6 +1122,99 @@ RTL87XX_BOARD_PINS = { "A0": 19, "A1": 41, }, + "wbru": { + "SPI0_CS_0": 2, + "SPI0_CS_1": 7, + "SPI0_CS_2": 15, + "SPI0_MISO_0": 10, + "SPI0_MISO_1": 20, + "SPI0_MOSI_0": 4, + "SPI0_MOSI_1": 9, + "SPI0_MOSI_2": 19, + "SPI0_SCK_0": 3, + "SPI0_SCK_1": 8, + "SPI0_SCK_2": 16, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 11, + "WIRE0_SCL_2": 15, + "WIRE0_SCL_3": 19, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 12, + "WIRE0_SDA_2": 16, + "WIRE0_SDA_3": 20, + "SERIAL0_CTS": 10, + "SERIAL0_RTS": 9, + "SERIAL0_RX_0": 12, + "SERIAL0_RX_1": 13, + "SERIAL0_TX_0": 11, + "SERIAL0_TX_1": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX": 3, + "SERIAL2_CTS": 19, + "SERIAL2_RTS": 20, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CS0": 7, + "CTS0": 10, + "CTS1": 4, + "CTS2": 19, + "MOSI0": 19, + "PA00": 0, + "PA0": 0, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PA19": 19, + "PA20": 20, + "PWM0": 0, + "PWM1": 12, + "PWM5": 17, + "PWM6": 18, + "RTS0": 9, + "RTS2": 20, + "RX2": 15, + "SCK0": 16, + "TX1": 3, + "TX2": 16, + "D0": 8, + "D1": 9, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 15, + "D6": 16, + "D7": 11, + "D8": 12, + "D9": 17, + "D10": 18, + "D11": 19, + "D12": 14, + "D13": 13, + "D14": 20, + "D15": 0, + "D16": 10, + "D17": 7, + }, "wr2le": { "MISO0": 22, "MISO1": 22, @@ -1116,21 +1243,21 @@ RTL87XX_BOARD_PINS = { "SPI0_MISO": 20, "SPI0_MOSI_0": 4, "SPI0_MOSI_1": 19, - "SPI0_SCK_0": 16, - "SPI0_SCK_1": 3, + "SPI0_SCK_0": 3, + "SPI0_SCK_1": 16, "WIRE0_SCL_0": 2, "WIRE0_SCL_1": 15, "WIRE0_SCL_2": 19, - "WIRE0_SDA_0": 20, + "WIRE0_SDA_0": 3, "WIRE0_SDA_1": 16, - "WIRE0_SDA_2": 3, + "WIRE0_SDA_2": 20, "SERIAL0_RX": 13, "SERIAL0_TX": 14, "SERIAL1_CTS": 4, - "SERIAL1_RX_0": 2, - "SERIAL1_RX_1": 0, - "SERIAL1_TX_0": 3, - "SERIAL1_TX_1": 1, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX_0": 1, + "SERIAL1_TX_1": 3, "SERIAL2_CTS": 19, "SERIAL2_RTS": 20, "SERIAL2_RX": 15, @@ -1251,6 +1378,168 @@ RTL87XX_BOARD_PINS = { "A0": 19, "A1": 41, }, + "cr3l": { + "SPI0_CS_0": 2, + "SPI0_CS_1": 15, + "SPI0_MISO": 20, + "SPI0_MOSI_0": 4, + "SPI0_MOSI_1": 19, + "SPI0_SCK_0": 3, + "SPI0_SCK_1": 16, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 15, + "WIRE0_SCL_2": 19, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 16, + "WIRE0_SDA_2": 20, + "SERIAL0_RX": 13, + "SERIAL0_TX": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX": 2, + "SERIAL1_TX": 3, + "SERIAL2_CTS": 19, + "SERIAL2_RTS": 20, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CTS1": 4, + "CTS2": 19, + "MISO0": 20, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PA19": 19, + "PA20": 20, + "PWM0": 20, + "PWM5": 17, + "PWM6": 18, + "RTS2": 20, + "RX0": 13, + "RX1": 2, + "RX2": 15, + "SCL0": 19, + "SDA0": 16, + "TX0": 14, + "TX1": 3, + "TX2": 16, + "D0": 20, + "D1": 2, + "D2": 3, + "D3": 4, + "D4": 15, + "D5": 16, + "D6": 17, + "D7": 18, + "D8": 19, + "D9": 13, + "D10": 14, + }, + "generic-rtl8720cm-4mb-1712k": { + "SPI0_CS_0": 2, + "SPI0_CS_1": 7, + "SPI0_CS_2": 15, + "SPI0_MISO_0": 10, + "SPI0_MISO_1": 20, + "SPI0_MOSI_0": 4, + "SPI0_MOSI_1": 9, + "SPI0_MOSI_2": 19, + "SPI0_SCK_0": 3, + "SPI0_SCK_1": 8, + "SPI0_SCK_2": 16, + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 11, + "WIRE0_SCL_2": 15, + "WIRE0_SCL_3": 19, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 12, + "WIRE0_SDA_2": 16, + "WIRE0_SDA_3": 20, + "SERIAL0_CTS": 10, + "SERIAL0_RTS": 9, + "SERIAL0_RX_0": 12, + "SERIAL0_RX_1": 13, + "SERIAL0_TX_0": 11, + "SERIAL0_TX_1": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX_0": 1, + "SERIAL1_TX_1": 3, + "SERIAL2_CTS": 19, + "SERIAL2_RTS": 20, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CS0": 15, + "CTS0": 10, + "CTS1": 4, + "CTS2": 19, + "MOSI0": 19, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA07": 7, + "PA7": 7, + "PA08": 8, + "PA8": 8, + "PA09": 9, + "PA9": 9, + "PA10": 10, + "PA11": 11, + "PA12": 12, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PA19": 19, + "PA20": 20, + "PA23": 23, + "PWM0": 20, + "PWM5": 17, + "PWM6": 18, + "PWM7": 23, + "RTS0": 9, + "RTS2": 20, + "RX2": 15, + "SCK0": 16, + "TX2": 16, + "D0": 0, + "D1": 1, + "D2": 2, + "D3": 3, + "D4": 4, + "D5": 7, + "D6": 8, + "D7": 9, + "D8": 10, + "D9": 11, + "D10": 12, + "D11": 13, + "D12": 14, + "D13": 15, + "D14": 16, + "D15": 17, + "D16": 18, + "D17": 19, + "D18": 20, + "D19": 23, + }, "generic-rtl8720cf-2mb-896k": { "SPI0_CS_0": 2, "SPI0_CS_1": 7, @@ -1456,8 +1745,8 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, "WIRE0_SDA_0": 19, "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, @@ -1585,6 +1874,65 @@ RTL87XX_BOARD_PINS = { "D4": 12, "A0": 19, }, + "wbr1": { + "WIRE0_SCL_0": 2, + "WIRE0_SCL_1": 11, + "WIRE0_SCL_2": 15, + "WIRE0_SDA_0": 3, + "WIRE0_SDA_1": 12, + "WIRE0_SDA_2": 16, + "SERIAL0_RX_0": 12, + "SERIAL0_RX_1": 13, + "SERIAL0_TX_0": 11, + "SERIAL0_TX_1": 14, + "SERIAL1_CTS": 4, + "SERIAL1_RX_0": 0, + "SERIAL1_RX_1": 2, + "SERIAL1_TX_0": 1, + "SERIAL1_TX_1": 3, + "SERIAL2_RX": 15, + "SERIAL2_TX": 16, + "CTS1": 4, + "MOSI0": 4, + "PA00": 0, + "PA0": 0, + "PA01": 1, + "PA1": 1, + "PA02": 2, + "PA2": 2, + "PA03": 3, + "PA3": 3, + "PA04": 4, + "PA4": 4, + "PA11": 11, + "PA12": 12, + "PA13": 13, + "PA14": 14, + "PA15": 15, + "PA16": 16, + "PA17": 17, + "PA18": 18, + "PWM5": 17, + "PWM6": 18, + "PWM7": 13, + "RX2": 15, + "SCL0": 15, + "SDA0": 12, + "TX2": 16, + "D0": 14, + "D1": 13, + "D2": 2, + "D3": 3, + "D4": 16, + "D5": 4, + "D6": 11, + "D7": 15, + "D8": 12, + "D9": 17, + "D10": 18, + "D11": 0, + "D12": 1, + }, "wr1": { "SPI0_CS": 19, "SPI0_MISO": 22, @@ -1594,10 +1942,10 @@ RTL87XX_BOARD_PINS = { "SPI1_MISO": 22, "SPI1_MOSI": 23, "SPI1_SCK": 18, - "WIRE0_SCL_0": 29, - "WIRE0_SCL_1": 22, - "WIRE0_SDA_0": 30, - "WIRE0_SDA_1": 19, + "WIRE0_SCL_0": 22, + "WIRE0_SCL_1": 29, + "WIRE0_SDA_0": 19, + "WIRE0_SDA_1": 30, "WIRE1_SCL": 18, "WIRE1_SDA": 23, "SERIAL0_CTS": 19, diff --git a/platformio.ini b/platformio.ini index 94b1f1a727..6b29daf87a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -214,7 +214,7 @@ build_unflags = ; This are common settings for the LibreTiny (all variants) using Arduino. [common:libretiny-arduino] extends = common:arduino -platform = https://github.com/libretiny-eu/libretiny.git#v1.11.0 +platform = https://github.com/libretiny-eu/libretiny.git#v1.12.1 framework = arduino lib_compat_mode = soft lib_deps = From 548b7e5dab6a92aa103c7662647b647e02d4d580 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:04:12 -0500 Subject: [PATCH 0653/2030] [esp32] Fix ESP32-P4 test: replace stale esp_hosted component ref (#13920) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- tests/components/esp32/test.esp32-p4-idf.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/components/esp32/test.esp32-p4-idf.yaml b/tests/components/esp32/test.esp32-p4-idf.yaml index d67787b3d5..bc054f5aee 100644 --- a/tests/components/esp32/test.esp32-p4-idf.yaml +++ b/tests/components/esp32/test.esp32-p4-idf.yaml @@ -6,8 +6,8 @@ esp32: type: esp-idf components: - espressif/mdns^1.8.2 - - name: espressif/esp_hosted - ref: 2.7.0 + - name: espressif/button + ref: 4.1.5 advanced: enable_idf_experimental_features: yes disable_debug_stubs: true From b4707344d322473550f8fb46024949ce57eaf033 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:44:12 -0500 Subject: [PATCH 0654/2030] [esp32] Upgrade uv to 0.10.1 and increase HTTP retries (#13918) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- docker/Dockerfile | 2 +- esphome/components/esp32/__init__.py | 8 -------- esphome/platformio_api.py | 2 ++ 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 348a503bc8..8ebdd1e49b 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -23,7 +23,7 @@ RUN if command -v apk > /dev/null; then \ ENV PIP_DISABLE_PIP_VERSION_CHECK=1 -RUN pip install --no-cache-dir -U pip uv==0.6.14 +RUN pip install --no-cache-dir -U pip uv==0.10.1 COPY requirements.txt / diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index d3c343b9db..a680a78951 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1436,14 +1436,6 @@ async def to_code(config): CORE.relative_internal_path(".espressif") ) - # Set the uv cache inside the data dir so "Clean All" clears it. - # Avoids persistent corrupted cache from mid-stream download failures. - os.environ["UV_CACHE_DIR"] = str(CORE.relative_internal_path(".uv_cache")) - - # Set the uv cache inside the data dir so "Clean All" clears it. - # Avoids persistent corrupted cache from mid-stream download failures. - os.environ["UV_CACHE_DIR"] = str(CORE.relative_internal_path(".uv_cache")) - if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: cg.add_build_flag("-DUSE_ESP_IDF") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ESP_IDF") diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index e66f9a2c97..d42f89d029 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -133,6 +133,8 @@ def run_platformio_cli(*args, **kwargs) -> str | int: ) # Suppress Python syntax warnings from third-party scripts during compilation os.environ.setdefault("PYTHONWARNINGS", "ignore::SyntaxWarning") + # Increase uv retry count to handle transient network errors (default is 3) + os.environ.setdefault("UV_HTTP_RETRIES", "10") cmd = ["platformio"] + list(args) if not CORE.verbose: From 58659e4893851cfd21167a34fda25dd768c85bd8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 18:48:13 -0600 Subject: [PATCH 0655/2030] [mdns] Throttle MDNS.update() polling on ESP8266 and RP2040 (#13917) --- esphome/components/mdns/mdns_component.h | 25 +++++++++++++++++++++--- esphome/components/mdns/mdns_esp8266.cpp | 11 ++++++++--- esphome/components/mdns/mdns_rp2040.cpp | 11 ++++++++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index f696cfff1c..32f8f16ec1 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -45,9 +45,28 @@ class MDNSComponent : public Component { void setup() override; void dump_config() override; -#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_ARDUINO) - void loop() override; -#endif + // Polling interval for MDNS.update() on platforms that require it (ESP8266, RP2040). + // + // On these platforms, MDNS.update() calls _process(true) which only manages timer-driven + // state machines (probe/announce timeouts and service query cache TTLs). Incoming mDNS + // packets are handled independently via the lwIP onRx UDP callback and are NOT affected + // by how often update() is called. + // + // The shortest internal timer is the 250ms probe interval (RFC 6762 Section 8.1). + // Announcement intervals are 1000ms and cache TTL checks are on the order of seconds + // to minutes. A 50ms polling interval provides sufficient resolution for all timers + // while completely removing mDNS from the per-iteration loop list. + // + // In steady state (after the ~8 second boot probe/announce phase completes), update() + // checks timers that are set to never expire, making every call pure overhead. + // + // Tasmota uses a 50ms main loop cycle with mDNS working correctly, confirming this + // interval is safe in production. + // + // By using set_interval() instead of overriding loop(), the component is excluded from + // the main loop list via has_overridden_loop(), eliminating all per-iteration overhead + // including virtual dispatch. + static constexpr uint32_t MDNS_UPDATE_INTERVAL_MS = 50; float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; } #ifdef USE_MDNS_EXTRA_SERVICES diff --git a/esphome/components/mdns/mdns_esp8266.cpp b/esphome/components/mdns/mdns_esp8266.cpp index dcbe5ebd52..295a408cbd 100644 --- a/esphome/components/mdns/mdns_esp8266.cpp +++ b/esphome/components/mdns/mdns_esp8266.cpp @@ -36,9 +36,14 @@ static void register_esp8266(MDNSComponent *, StaticVector<MDNSService, MDNS_SER } } -void MDNSComponent::setup() { this->setup_buffers_and_register_(register_esp8266); } - -void MDNSComponent::loop() { MDNS.update(); } +void MDNSComponent::setup() { + this->setup_buffers_and_register_(register_esp8266); + // Schedule MDNS.update() via set_interval() instead of overriding loop(). + // This removes the component from the per-iteration loop list entirely, + // eliminating virtual dispatch overhead on every main loop cycle. + // See MDNS_UPDATE_INTERVAL_MS comment in mdns_component.h for safety analysis. + this->set_interval(MDNS_UPDATE_INTERVAL_MS, []() { MDNS.update(); }); +} void MDNSComponent::on_shutdown() { MDNS.close(); diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index e4a9b60cdb..05d991c1fa 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -35,9 +35,14 @@ static void register_rp2040(MDNSComponent *, StaticVector<MDNSService, MDNS_SERV } } -void MDNSComponent::setup() { this->setup_buffers_and_register_(register_rp2040); } - -void MDNSComponent::loop() { MDNS.update(); } +void MDNSComponent::setup() { + this->setup_buffers_and_register_(register_rp2040); + // Schedule MDNS.update() via set_interval() instead of overriding loop(). + // This removes the component from the per-iteration loop list entirely, + // eliminating virtual dispatch overhead on every main loop cycle. + // See MDNS_UPDATE_INTERVAL_MS comment in mdns_component.h for safety analysis. + this->set_interval(MDNS_UPDATE_INTERVAL_MS, []() { MDNS.update(); }); +} void MDNSComponent::on_shutdown() { MDNS.close(); From 42bc0994f1da8754b47255f5c4aaa848f8bfb259 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Wed, 11 Feb 2026 04:10:29 +0100 Subject: [PATCH 0656/2030] [rtttl] Code Improvements (#13653) Co-authored-by: Keith Burzinski <kbx81x@gmail.com> --- esphome/components/rtttl/rtttl.cpp | 412 +++++++++++++++-------------- esphome/components/rtttl/rtttl.h | 55 ++-- 2 files changed, 239 insertions(+), 228 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 5a64f37da4..6e86405b74 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -4,28 +4,72 @@ #include "esphome/core/log.h" #include "esphome/core/progmem.h" -namespace esphome { -namespace rtttl { +namespace esphome::rtttl { static const char *const TAG = "rtttl"; -static const uint32_t DOUBLE_NOTE_GAP_MS = 10; - // These values can also be found as constants in the Tone library (Tone.h) static const uint16_t NOTES[] = {0, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951}; -static const uint16_t I2S_SPEED = 1000; +#if defined(USE_OUTPUT) || defined(USE_SPEAKER) +static const uint32_t DOUBLE_NOTE_GAP_MS = 10; +#endif // USE_OUTPUT || USE_SPEAKER -#undef HALF_PI -static const double HALF_PI = 1.5707963267948966192313216916398; +#ifdef USE_SPEAKER +static const size_t SAMPLE_BUFFER_SIZE = 2048; + +struct SpeakerSample { + int8_t left{0}; + int8_t right{0}; +}; inline double deg2rad(double degrees) { static const double PI_ON_180 = 4.0 * atan(1.0) / 180.0; return degrees * PI_ON_180; } +#endif // USE_SPEAKER + +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE +// RTTTL state strings indexed by State enum (0-4): STOPPED, INIT, STARTING, RUNNING, STOPPING, plus UNKNOWN fallback +PROGMEM_STRING_TABLE(RtttlStateStrings, "State::STOPPED", "State::INIT", "State::STARTING", "State::RUNNING", + "State::STOPPING", "UNKNOWN"); + +static const LogString *state_to_string(State state) { + return RtttlStateStrings::get_log_str(static_cast<uint8_t>(state), RtttlStateStrings::LAST_INDEX); +} +#endif // ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + +static uint8_t note_index_from_char(char note) { + switch (note) { + case 'c': + return 1; + // 'c#': 2 + case 'd': + return 3; + // 'd#': 4 + case 'e': + return 5; + case 'f': + return 6; + // 'f#': 7 + case 'g': + return 8; + // 'g#': 9 + case 'a': + return 10; + // 'a#': 11 + // Support both 'b' (English notation for B natural) and 'h' (German notation for B natural) + case 'b': + case 'h': + return 12; + case 'p': + default: + return 0; + } +} void Rtttl::dump_config() { ESP_LOGCONFIG(TAG, @@ -34,161 +78,34 @@ void Rtttl::dump_config() { this->gain_); } -void Rtttl::play(std::string rtttl) { - if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { - size_t pos = this->rtttl_.find(':'); - size_t len = (pos != std::string::npos) ? pos : this->rtttl_.length(); - ESP_LOGW(TAG, "Already playing: %.*s", (int) len, this->rtttl_.c_str()); - return; - } - - this->rtttl_ = std::move(rtttl); - - this->default_duration_ = 4; - this->default_octave_ = 6; - this->note_duration_ = 0; - - int bpm = 63; - uint8_t num; - - // Get name - this->position_ = this->rtttl_.find(':'); - - // it's somewhat documented to be up to 10 characters but let's be a bit flexible here - if (this->position_ == std::string::npos || this->position_ > 15) { - ESP_LOGE(TAG, "Unable to determine name; missing ':'"); - return; - } - - ESP_LOGD(TAG, "Playing song %.*s", (int) this->position_, this->rtttl_.c_str()); - - // get default duration - this->position_ = this->rtttl_.find("d=", this->position_); - if (this->position_ == std::string::npos) { - ESP_LOGE(TAG, "Missing 'd='"); - return; - } - this->position_ += 2; - num = this->get_integer_(); - if (num > 0) - this->default_duration_ = num; - - // get default octave - this->position_ = this->rtttl_.find("o=", this->position_); - if (this->position_ == std::string::npos) { - ESP_LOGE(TAG, "Missing 'o="); - return; - } - this->position_ += 2; - num = get_integer_(); - if (num >= 3 && num <= 7) - this->default_octave_ = num; - - // get BPM - this->position_ = this->rtttl_.find("b=", this->position_); - if (this->position_ == std::string::npos) { - ESP_LOGE(TAG, "Missing b="); - return; - } - this->position_ += 2; - num = get_integer_(); - if (num != 0) - bpm = num; - - this->position_ = this->rtttl_.find(':', this->position_); - if (this->position_ == std::string::npos) { - ESP_LOGE(TAG, "Missing second ':'"); - return; - } - this->position_++; - - // BPM usually expresses the number of quarter notes per minute - this->wholenote_ = 60 * 1000L * 4 / bpm; // this is the time for whole note (in milliseconds) - - this->output_freq_ = 0; - this->last_note_ = millis(); - this->note_duration_ = 1; - -#ifdef USE_SPEAKER - if (this->speaker_ != nullptr) { - this->set_state_(State::STATE_INIT); - this->samples_sent_ = 0; - this->samples_count_ = 0; - } -#endif -#ifdef USE_OUTPUT - if (this->output_ != nullptr) { - this->set_state_(State::STATE_RUNNING); - } -#endif -} - -void Rtttl::stop() { -#ifdef USE_OUTPUT - if (this->output_ != nullptr) { - this->output_->set_level(0.0); - this->set_state_(STATE_STOPPED); - } -#endif -#ifdef USE_SPEAKER - if (this->speaker_ != nullptr) { - if (this->speaker_->is_running()) { - this->speaker_->stop(); - } - this->set_state_(STATE_STOPPING); - } -#endif - this->position_ = this->rtttl_.length(); - this->note_duration_ = 0; -} - -void Rtttl::finish_() { - ESP_LOGV(TAG, "Rtttl::finish_()"); -#ifdef USE_OUTPUT - if (this->output_ != nullptr) { - this->output_->set_level(0.0); - this->set_state_(State::STATE_STOPPED); - } -#endif -#ifdef USE_SPEAKER - if (this->speaker_ != nullptr) { - SpeakerSample sample[2]; - sample[0].left = 0; - sample[0].right = 0; - sample[1].left = 0; - sample[1].right = 0; - this->speaker_->play((uint8_t *) (&sample), 8); - this->speaker_->finish(); - this->set_state_(State::STATE_STOPPING); - } -#endif - // Ensure no more notes are played in case finish_() is called for an error. - this->position_ = this->rtttl_.length(); - this->note_duration_ = 0; -} - void Rtttl::loop() { - if (this->state_ == State::STATE_STOPPED) { + if (this->state_ == State::STOPPED) { this->disable_loop(); return; } +#ifdef USE_OUTPUT + if (this->output_ != nullptr && millis() - this->last_note_ < this->note_duration_) { + return; + } +#endif // USE_OUTPUT + #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { - if (this->state_ == State::STATE_STOPPING) { + if (this->state_ == State::STOPPING) { if (this->speaker_->is_stopped()) { - this->set_state_(State::STATE_STOPPED); + this->set_state_(State::STOPPED); } else { return; } - } else if (this->state_ == State::STATE_INIT) { + } else if (this->state_ == State::INIT) { if (this->speaker_->is_stopped()) { this->speaker_->start(); - this->set_state_(State::STATE_STARTING); + this->set_state_(State::STARTING); } - } else if (this->state_ == State::STATE_STARTING) { + } else if (this->state_ == State::STARTING) { if (this->speaker_->is_running()) { - this->set_state_(State::STATE_RUNNING); + this->set_state_(State::RUNNING); } } if (!this->speaker_->is_running()) { @@ -230,19 +147,17 @@ void Rtttl::loop() { } } } -#endif -#ifdef USE_OUTPUT - if (this->output_ != nullptr && millis() - this->last_note_ < this->note_duration_) - return; -#endif +#endif // USE_SPEAKER + if (this->position_ >= this->rtttl_.length()) { this->finish_(); return; } // align to note: most rtttl's out there does not add and space after the ',' separator but just in case... - while (this->rtttl_[this->position_] == ',' || this->rtttl_[this->position_] == ' ') + while (this->rtttl_[this->position_] == ',' || this->rtttl_[this->position_] == ' ') { this->position_++; + } // first, get note duration, if available uint8_t num = this->get_integer_(); @@ -254,35 +169,8 @@ void Rtttl::loop() { this->wholenote_ / this->default_duration_; // we will need to check if we are a dotted note after } - uint8_t note; + uint8_t note = note_index_from_char(this->rtttl_[this->position_]); - switch (this->rtttl_[this->position_]) { - case 'c': - note = 1; - break; - case 'd': - note = 3; - break; - case 'e': - note = 5; - break; - case 'f': - note = 6; - break; - case 'g': - note = 8; - break; - case 'a': - note = 10; - break; - case 'h': - case 'b': - note = 12; - break; - case 'p': - default: - note = 0; - } this->position_++; // now, get optional '#' sharp @@ -292,7 +180,7 @@ void Rtttl::loop() { } // now, get scale - uint8_t scale = get_integer_(); + uint8_t scale = this->get_integer_(); if (scale == 0) { scale = this->default_octave_; } @@ -345,7 +233,8 @@ void Rtttl::loop() { this->output_->set_level(0.0); } } -#endif +#endif // USE_OUTPUT + #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { this->samples_sent_ = 0; @@ -370,20 +259,152 @@ void Rtttl::loop() { } // Convert from frequency in Hz to high and low samples in fixed point } -#endif +#endif // USE_SPEAKER this->last_note_ = millis(); } -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE -// RTTTL state strings indexed by State enum (0-4): STOPPED, INIT, STARTING, RUNNING, STOPPING, plus UNKNOWN fallback -PROGMEM_STRING_TABLE(RtttlStateStrings, "STATE_STOPPED", "STATE_INIT", "STATE_STARTING", "STATE_RUNNING", - "STATE_STOPPING", "UNKNOWN"); +void Rtttl::play(std::string rtttl) { + if (this->state_ != State::STOPPED && this->state_ != State::STOPPING) { + size_t pos = this->rtttl_.find(':'); + size_t len = (pos != std::string::npos) ? pos : this->rtttl_.length(); + ESP_LOGW(TAG, "Already playing: %.*s", (int) len, this->rtttl_.c_str()); + return; + } -static const LogString *state_to_string(State state) { - return RtttlStateStrings::get_log_str(static_cast<uint8_t>(state), RtttlStateStrings::LAST_INDEX); + this->rtttl_ = std::move(rtttl); + + this->default_duration_ = 4; + this->default_octave_ = 6; + this->note_duration_ = 0; + + int bpm = 63; + uint8_t num; + + // Get name + this->position_ = this->rtttl_.find(':'); + + // it's somewhat documented to be up to 10 characters but let's be a bit flexible here + if (this->position_ == std::string::npos || this->position_ > 15) { + ESP_LOGE(TAG, "Unable to determine name; missing ':'"); + return; + } + + ESP_LOGD(TAG, "Playing song %.*s", (int) this->position_, this->rtttl_.c_str()); + + // get default duration + this->position_ = this->rtttl_.find("d=", this->position_); + if (this->position_ == std::string::npos) { + ESP_LOGE(TAG, "Missing 'd='"); + return; + } + this->position_ += 2; + num = this->get_integer_(); + if (num > 0) { + this->default_duration_ = num; + } + + // get default octave + this->position_ = this->rtttl_.find("o=", this->position_); + if (this->position_ == std::string::npos) { + ESP_LOGE(TAG, "Missing 'o="); + return; + } + this->position_ += 2; + num = this->get_integer_(); + if (num >= 3 && num <= 7) { + this->default_octave_ = num; + } + + // get BPM + this->position_ = this->rtttl_.find("b=", this->position_); + if (this->position_ == std::string::npos) { + ESP_LOGE(TAG, "Missing b="); + return; + } + this->position_ += 2; + num = this->get_integer_(); + if (num != 0) { + bpm = num; + } + + this->position_ = this->rtttl_.find(':', this->position_); + if (this->position_ == std::string::npos) { + ESP_LOGE(TAG, "Missing second ':'"); + return; + } + this->position_++; + + // BPM usually expresses the number of quarter notes per minute + this->wholenote_ = 60 * 1000L * 4 / bpm; // this is the time for whole note (in milliseconds) + + this->output_freq_ = 0; + this->last_note_ = millis(); + this->note_duration_ = 1; + +#ifdef USE_OUTPUT + if (this->output_ != nullptr) { + this->set_state_(State::RUNNING); + } +#endif // USE_OUTPUT + +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + this->set_state_(State::INIT); + this->samples_sent_ = 0; + this->samples_count_ = 0; + } +#endif // USE_SPEAKER +} + +void Rtttl::stop() { +#ifdef USE_OUTPUT + if (this->output_ != nullptr) { + this->output_->set_level(0.0); + this->set_state_(State::STOPPED); + } +#endif // USE_OUTPUT + +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + if (this->speaker_->is_running()) { + this->speaker_->stop(); + } + this->set_state_(State::STOPPING); + } +#endif // USE_SPEAKER + + this->position_ = this->rtttl_.length(); + this->note_duration_ = 0; +} + +void Rtttl::finish_() { + ESP_LOGV(TAG, "Rtttl::finish_()"); + +#ifdef USE_OUTPUT + if (this->output_ != nullptr) { + this->output_->set_level(0.0); + this->set_state_(State::STOPPED); + } +#endif // USE_OUTPUT + +#ifdef USE_SPEAKER + if (this->speaker_ != nullptr) { + SpeakerSample sample[2]; + sample[0].left = 0; + sample[0].right = 0; + sample[1].left = 0; + sample[1].right = 0; + this->speaker_->play((uint8_t *) (&sample), 8); + this->speaker_->finish(); + this->set_state_(State::STOPPING); + } +#endif // USE_SPEAKER + + // Ensure no more notes are played in case finish_() is called for an error. + this->position_ = this->rtttl_.length(); + this->note_duration_ = 0; } -#endif void Rtttl::set_state_(State state) { State old_state = this->state_; @@ -391,15 +412,14 @@ void Rtttl::set_state_(State state) { ESP_LOGV(TAG, "State changed from %s to %s", LOG_STR_ARG(state_to_string(old_state)), LOG_STR_ARG(state_to_string(state))); - // Clear loop_done when transitioning from STOPPED to any other state - if (state == State::STATE_STOPPED) { + // Clear loop_done when transitioning from `State::STOPPED` to any other state + if (state == State::STOPPED) { this->disable_loop(); this->on_finished_playback_callback_.call(); ESP_LOGD(TAG, "Playback finished"); - } else if (old_state == State::STATE_STOPPED) { + } else if (old_state == State::STOPPED) { this->enable_loop(); } } -} // namespace rtttl -} // namespace esphome +} // namespace esphome::rtttl diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 1e924a897c..6f5df07766 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -5,48 +5,41 @@ #ifdef USE_OUTPUT #include "esphome/components/output/float_output.h" -#endif +#endif // USE_OUTPUT #ifdef USE_SPEAKER #include "esphome/components/speaker/speaker.h" -#endif +#endif // USE_SPEAKER -namespace esphome { -namespace rtttl { +namespace esphome::rtttl { -enum State : uint8_t { - STATE_STOPPED = 0, - STATE_INIT, - STATE_STARTING, - STATE_RUNNING, - STATE_STOPPING, +enum class State : uint8_t { + STOPPED = 0, + INIT, + STARTING, + RUNNING, + STOPPING, }; -#ifdef USE_SPEAKER -static const size_t SAMPLE_BUFFER_SIZE = 2048; - -struct SpeakerSample { - int8_t left{0}; - int8_t right{0}; -}; -#endif - class Rtttl : public Component { public: #ifdef USE_OUTPUT void set_output(output::FloatOutput *output) { this->output_ = output; } -#endif +#endif // USE_OUTPUT + #ifdef USE_SPEAKER void set_speaker(speaker::Speaker *speaker) { this->speaker_ = speaker; } -#endif - float get_gain() { return gain_; } - void set_gain(float gain) { this->gain_ = clamp(gain, 0.0f, 1.0f); } +#endif // USE_SPEAKER + + void dump_config() override; + void loop() override; void play(std::string rtttl); void stop(); - void dump_config() override; - bool is_playing() { return this->state_ != State::STATE_STOPPED; } - void loop() override; + float get_gain() { return this->gain_; } + void set_gain(float gain) { this->gain_ = clamp(gain, 0.0f, 1.0f); } + + bool is_playing() { return this->state_ != State::STOPPED; } void add_on_finished_playback_callback(std::function<void()> callback) { this->on_finished_playback_callback_.add(std::move(callback)); @@ -90,12 +83,12 @@ class Rtttl : public Component { /// The gain of the output. float gain_{0.6f}; /// The current state of the RTTTL player. - State state_{State::STATE_STOPPED}; + State state_{State::STOPPED}; #ifdef USE_OUTPUT /// The output to write the sound to. output::FloatOutput *output_; -#endif +#endif // USE_OUTPUT #ifdef USE_SPEAKER /// The speaker to write the sound to. @@ -110,8 +103,7 @@ class Rtttl : public Component { int samples_count_{0}; /// The number of samples for the gap between notes. int samples_gap_{0}; - -#endif +#endif // USE_SPEAKER /// The callback to call when playback is finished. CallbackManager<void()> on_finished_playback_callback_; @@ -145,5 +137,4 @@ class FinishedPlaybackTrigger : public Trigger<> { } }; -} // namespace rtttl -} // namespace esphome +} // namespace esphome::rtttl From e3bafc1b45502971f699a5746685f2f91e6ea29a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 21:29:29 -0600 Subject: [PATCH 0657/2030] [esp32_ble] Extract state transitions from ESP32BLE::loop() hot path (#13903) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/esp32_ble/ble.cpp | 70 ++++++++++++++-------------- esphome/components/esp32_ble/ble.h | 4 ++ 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 87b5e2b738..acbe9d88fc 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -369,42 +369,9 @@ bool ESP32BLE::ble_dismantle_() { } void ESP32BLE::loop() { - switch (this->state_) { - case BLE_COMPONENT_STATE_OFF: - case BLE_COMPONENT_STATE_DISABLED: - return; - case BLE_COMPONENT_STATE_DISABLE: { - ESP_LOGD(TAG, "Disabling"); - -#ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT - for (auto *ble_event_handler : this->ble_status_event_handlers_) { - ble_event_handler->ble_before_disabled_event_handler(); - } -#endif - - if (!ble_dismantle_()) { - ESP_LOGE(TAG, "Could not be dismantled"); - this->mark_failed(); - return; - } - this->state_ = BLE_COMPONENT_STATE_DISABLED; - return; - } - case BLE_COMPONENT_STATE_ENABLE: { - ESP_LOGD(TAG, "Enabling"); - this->state_ = BLE_COMPONENT_STATE_OFF; - - if (!ble_setup_()) { - ESP_LOGE(TAG, "Could not be set up"); - this->mark_failed(); - return; - } - - this->state_ = BLE_COMPONENT_STATE_ACTIVE; - return; - } - case BLE_COMPONENT_STATE_ACTIVE: - break; + if (this->state_ != BLE_COMPONENT_STATE_ACTIVE) { + this->loop_handle_state_transition_not_active_(); + return; } BLEEvent *ble_event = this->ble_events_.pop(); @@ -520,6 +487,37 @@ void ESP32BLE::loop() { } } +void ESP32BLE::loop_handle_state_transition_not_active_() { + // Caller ensures state_ != ACTIVE + if (this->state_ == BLE_COMPONENT_STATE_DISABLE) { + ESP_LOGD(TAG, "Disabling"); + +#ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT + for (auto *ble_event_handler : this->ble_status_event_handlers_) { + ble_event_handler->ble_before_disabled_event_handler(); + } +#endif + + if (!ble_dismantle_()) { + ESP_LOGE(TAG, "Could not be dismantled"); + this->mark_failed(); + return; + } + this->state_ = BLE_COMPONENT_STATE_DISABLED; + } else if (this->state_ == BLE_COMPONENT_STATE_ENABLE) { + ESP_LOGD(TAG, "Enabling"); + this->state_ = BLE_COMPONENT_STATE_OFF; + + if (!ble_setup_()) { + ESP_LOGE(TAG, "Could not be set up"); + this->mark_failed(); + return; + } + + this->state_ = BLE_COMPONENT_STATE_ACTIVE; + } +} + // Helper function to load new event data based on type void load_ble_event(BLEEvent *event, esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) { event->load_gap_event(e, p); diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 1999c870f8..f1ab81b6dc 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -155,6 +155,10 @@ class ESP32BLE : public Component { #endif static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); + // Handle DISABLE and ENABLE transitions when not in the ACTIVE state. + // Other non-ACTIVE states (e.g. OFF, DISABLED) are currently treated as no-ops. + void __attribute__((noinline)) loop_handle_state_transition_not_active_(); + bool ble_setup_(); bool ble_dismantle_(); bool ble_pre_setup_(); From 5281fd32730a4669cab2706c22d625b3fc12e909 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 21:30:34 -0600 Subject: [PATCH 0658/2030] [api] Extract cold code from APIConnection::loop() hot path (#13901) --- esphome/components/api/api_connection.cpp | 74 ++++++++++++++--------- esphome/components/api/api_connection.h | 23 +++---- esphome/components/api/list_entities.h | 1 - esphome/components/api/subscribe_state.h | 1 - esphome/core/component_iterator.h | 1 + 5 files changed, 56 insertions(+), 44 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index e51689fd07..14ccbd2248 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -219,35 +219,8 @@ void APIConnection::loop() { this->process_batch_(); } - switch (this->active_iterator_) { - case ActiveIterator::LIST_ENTITIES: - if (this->iterator_storage_.list_entities.completed()) { - this->destroy_active_iterator_(); - if (this->flags_.state_subscription) { - this->begin_iterator_(ActiveIterator::INITIAL_STATE); - } - } else { - this->process_iterator_batch_(this->iterator_storage_.list_entities); - } - break; - case ActiveIterator::INITIAL_STATE: - if (this->iterator_storage_.initial_state.completed()) { - this->destroy_active_iterator_(); - // Process any remaining batched messages immediately - if (!this->deferred_batch_.empty()) { - this->process_batch_(); - } - // Now that everything is sent, enable immediate sending for future state changes - this->flags_.should_try_send_immediately = true; - // Release excess memory from buffers that grew during initial sync - this->deferred_batch_.release_buffer(); - this->helper_->release_buffers(); - } else { - this->process_iterator_batch_(this->iterator_storage_.initial_state); - } - break; - case ActiveIterator::NONE: - break; + if (this->active_iterator_ != ActiveIterator::NONE) { + this->process_active_iterator_(); } if (this->flags_.sent_ping) { @@ -283,6 +256,49 @@ void APIConnection::loop() { #endif } +void APIConnection::process_active_iterator_() { + // Caller ensures active_iterator_ != NONE + if (this->active_iterator_ == ActiveIterator::LIST_ENTITIES) { + if (this->iterator_storage_.list_entities.completed()) { + this->destroy_active_iterator_(); + if (this->flags_.state_subscription) { + this->begin_iterator_(ActiveIterator::INITIAL_STATE); + } + } else { + this->process_iterator_batch_(this->iterator_storage_.list_entities); + } + } else { // INITIAL_STATE + if (this->iterator_storage_.initial_state.completed()) { + this->destroy_active_iterator_(); + // Process any remaining batched messages immediately + if (!this->deferred_batch_.empty()) { + this->process_batch_(); + } + // Now that everything is sent, enable immediate sending for future state changes + this->flags_.should_try_send_immediately = true; + // Release excess memory from buffers that grew during initial sync + this->deferred_batch_.release_buffer(); + this->helper_->release_buffers(); + } else { + this->process_iterator_batch_(this->iterator_storage_.initial_state); + } + } +} + +void APIConnection::process_iterator_batch_(ComponentIterator &iterator) { + size_t initial_size = this->deferred_batch_.size(); + size_t max_batch = this->get_max_batch_size_(); + while (!iterator.completed() && (this->deferred_batch_.size() - initial_size) < max_batch) { + iterator.advance(); + } + + // If the batch is full, process it immediately + // Note: iterator.advance() already calls schedule_batch_() via schedule_message_() + if (this->deferred_batch_.size() >= max_batch) { + this->process_batch_(); + } +} + bool APIConnection::send_disconnect_response_() { // remote initiated disconnect_client // don't close yet, we still need to send the disconnect response diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index abcb162865..a16d681760 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -15,6 +15,10 @@ #include <limits> #include <vector> +namespace esphome { +class ComponentIterator; +} // namespace esphome + namespace esphome::api { // Keepalive timeout in milliseconds @@ -366,20 +370,13 @@ class APIConnection final : public APIServerConnectionBase { return this->client_supports_api_version(1, 14) ? MAX_INITIAL_PER_BATCH : MAX_INITIAL_PER_BATCH_LEGACY; } - // Helper method to process multiple entities from an iterator in a batch - template<typename Iterator> void process_iterator_batch_(Iterator &iterator) { - size_t initial_size = this->deferred_batch_.size(); - size_t max_batch = this->get_max_batch_size_(); - while (!iterator.completed() && (this->deferred_batch_.size() - initial_size) < max_batch) { - iterator.advance(); - } + // Process active iterator (list_entities/initial_state) during connection setup. + // Extracted from loop() — only runs during initial handshake, NONE in steady state. + void __attribute__((noinline)) process_active_iterator_(); - // If the batch is full, process it immediately - // Note: iterator.advance() already calls schedule_batch_() via schedule_message_() - if (this->deferred_batch_.size() >= max_batch) { - this->process_batch_(); - } - } + // Helper method to process multiple entities from an iterator in a batch. + // Takes ComponentIterator base class reference to avoid duplicate template instantiations. + void process_iterator_batch_(ComponentIterator &iterator); #ifdef USE_BINARY_SENSOR static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size); diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index bef36dd015..90769f9a81 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -94,7 +94,6 @@ class ListEntitiesIterator : public ComponentIterator { bool on_update(update::UpdateEntity *entity) override; #endif bool on_end() override; - bool completed() { return this->state_ == IteratorState::NONE; } protected: APIConnection *client_; diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 3c9f33835a..6f8577ca7b 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -88,7 +88,6 @@ class InitialStateIterator : public ComponentIterator { #ifdef USE_UPDATE bool on_update(update::UpdateEntity *entity) override; #endif - bool completed() { return this->state_ == IteratorState::NONE; } protected: APIConnection *client_; diff --git a/esphome/core/component_iterator.h b/esphome/core/component_iterator.h index e13d81a8e4..6c03b74a17 100644 --- a/esphome/core/component_iterator.h +++ b/esphome/core/component_iterator.h @@ -26,6 +26,7 @@ class ComponentIterator { public: void begin(bool include_internal = false); void advance(); + bool completed() const { return this->state_ == IteratorState::NONE; } virtual bool on_begin(); #ifdef USE_BINARY_SENSOR virtual bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) = 0; From 225c13326a1c6cc88d3eb9b37ddd9257517fc22b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 21:41:07 -0600 Subject: [PATCH 0659/2030] [core] Extract dump_config from Application::loop() hot path (#13900) --- esphome/core/application.cpp | 46 ++++++++++++++++++++---------------- esphome/core/application.h | 5 ++++ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 0daabc0282..7b5435185d 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -204,36 +204,40 @@ void Application::loop() { this->last_loop_ = last_op_end_time; if (this->dump_config_at_ < this->components_.size()) { - if (this->dump_config_at_ == 0) { - char build_time_str[Application::BUILD_TIME_STR_SIZE]; - this->get_build_time_string(build_time_str); - ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", build_time_str); + this->process_dump_config_(); + } +} + +void Application::process_dump_config_() { + if (this->dump_config_at_ == 0) { + char build_time_str[Application::BUILD_TIME_STR_SIZE]; + this->get_build_time_string(build_time_str); + ESP_LOGI(TAG, "ESPHome version " ESPHOME_VERSION " compiled on %s", build_time_str); #ifdef ESPHOME_PROJECT_NAME - ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION); + ESP_LOGI(TAG, "Project " ESPHOME_PROJECT_NAME " version " ESPHOME_PROJECT_VERSION); #endif #ifdef USE_ESP32 - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); - ESP_LOGI(TAG, "ESP32 Chip: %s rev%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100, - chip_info.revision % 100, chip_info.cores); + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + ESP_LOGI(TAG, "ESP32 Chip: %s rev%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100, + chip_info.revision % 100, chip_info.cores); #if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET) - // Suggest optimization for chips that don't need the PSRAM cache workaround - if (chip_info.revision >= 300) { + // Suggest optimization for chips that don't need the PSRAM cache workaround + if (chip_info.revision >= 300) { #ifdef USE_PSRAM - ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to save ~10KB IRAM", chip_info.revision / 100, - chip_info.revision % 100); + ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to save ~10KB IRAM", chip_info.revision / 100, + chip_info.revision % 100); #else - ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to reduce binary size", chip_info.revision / 100, - chip_info.revision % 100); -#endif - } -#endif + ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to reduce binary size", chip_info.revision / 100, + chip_info.revision % 100); #endif } - - this->components_[this->dump_config_at_]->call_dump_config(); - this->dump_config_at_++; +#endif +#endif } + + this->components_[this->dump_config_at_]->call_dump_config(); + this->dump_config_at_++; } void IRAM_ATTR HOT Application::feed_wdt(uint32_t time) { diff --git a/esphome/core/application.h b/esphome/core/application.h index 592bf809f1..8478100a56 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -519,6 +519,11 @@ class Application { void before_loop_tasks_(uint32_t loop_start_time); void after_loop_tasks_(); + /// Process dump_config output one component per loop iteration. + /// Extracted from loop() to keep cold startup/reconnect logging out of the hot path. + /// Caller must ensure dump_config_at_ < components_.size(). + void __attribute__((noinline)) process_dump_config_(); + void feed_wdt_arch_(); /// Perform a delay while also monitoring socket file descriptors for readiness From 38bba3f5a276310a24787331d333a6eae794963d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Feb 2026 21:42:13 -0600 Subject: [PATCH 0660/2030] [scheduler] Reduce set_timer_common_ hot path size by 25% (#13899) --- esphome/core/scheduler.cpp | 106 ++++++++++++++++++------------------- esphome/core/scheduler.h | 42 +++++++-------- 2 files changed, 73 insertions(+), 75 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 97ac28b623..4194c3aa9e 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -107,6 +107,24 @@ static void validate_static_string(const char *name) { // iterating over them from the loop task is fine; but iterating from any other context requires the lock to be held to // avoid the main thread modifying the list while it is being accessed. +// Calculate random offset for interval timers +// Extracted from set_timer_common_ to reduce code size - float math + random_float() +// only needed for intervals, not timeouts +uint32_t Scheduler::calculate_interval_offset_(uint32_t delay) { + return static_cast<uint32_t>(std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); +} + +// Check if a retry was already cancelled in items_ or to_add_ +// Extracted from set_timer_common_ to reduce code size - retry path is cold and deprecated +// Remove before 2026.8.0 along with all retry code +bool Scheduler::is_retry_cancelled_locked_(Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id) { + return has_cancelled_timeout_in_container_locked_(this->items_, component, name_type, static_name, hash_or_id, + /* match_retry= */ true) || + has_cancelled_timeout_in_container_locked_(this->to_add_, component, name_type, static_name, hash_or_id, + /* match_retry= */ true); +} + // Common implementation for both timeout and interval // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, @@ -130,84 +148,66 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Create and populate the scheduler item auto item = this->get_item_from_pool_locked_(); item->component = component; - switch (name_type) { - case NameType::STATIC_STRING: - item->set_static_name(static_name); - break; - case NameType::HASHED_STRING: - item->set_hashed_name(hash_or_id); - break; - case NameType::NUMERIC_ID: - item->set_numeric_id(hash_or_id); - break; - case NameType::NUMERIC_ID_INTERNAL: - item->set_internal_id(hash_or_id); - break; - } + item->set_name(name_type, static_name, hash_or_id); item->type = type; item->callback = std::move(func); // Reset remove flag - recycled items may have been cancelled (remove=true) in previous use this->set_item_removed_(item.get(), false); item->is_retry = is_retry; + // Determine target container: defer_queue_ for deferred items, to_add_ for everything else. + // Using a pointer lets both paths share the cancel + push_back epilogue. + auto *target = &this->to_add_; + #ifndef ESPHOME_THREAD_SINGLE // Special handling for defer() (delay = 0, type = TIMEOUT) // Single-core platforms don't need thread-safe defer handling if (delay == 0 && type == SchedulerItem::TIMEOUT) { // Put in defer queue for guaranteed FIFO execution - if (!skip_cancel) { - this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); - } - this->defer_queue_.push_back(std::move(item)); - return; - } + target = &this->defer_queue_; + } else #endif /* not ESPHOME_THREAD_SINGLE */ - - // Type-specific setup - if (type == SchedulerItem::INTERVAL) { - item->interval = delay; - // first execution happens immediately after a random smallish offset - // Calculate random offset (0 to min(interval/2, 5s)) - uint32_t offset = (uint32_t) (std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); - item->set_next_execution(now + offset); + { + // Type-specific setup + if (type == SchedulerItem::INTERVAL) { + item->interval = delay; + // first execution happens immediately after a random smallish offset + uint32_t offset = this->calculate_interval_offset_(delay); + item->set_next_execution(now + offset); #ifdef ESPHOME_LOG_HAS_VERBOSE - SchedulerNameLog name_log; - ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", - name_log.format(name_type, static_name, hash_or_id), delay, offset); + SchedulerNameLog name_log; + ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", + name_log.format(name_type, static_name, hash_or_id), delay, offset); #endif - } else { - item->interval = 0; - item->set_next_execution(now + delay); - } + } else { + item->interval = 0; + item->set_next_execution(now + delay); + } #ifdef ESPHOME_DEBUG_SCHEDULER - this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now); + this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now); #endif /* ESPHOME_DEBUG_SCHEDULER */ - // For retries, check if there's a cancelled timeout first - // Skip check for anonymous retries (STATIC_STRING with nullptr) - they can't be cancelled by name - if (is_retry && (name_type != NameType::STATIC_STRING || static_name != nullptr) && type == SchedulerItem::TIMEOUT && - (has_cancelled_timeout_in_container_locked_(this->items_, component, name_type, static_name, hash_or_id, - /* match_retry= */ true) || - has_cancelled_timeout_in_container_locked_(this->to_add_, component, name_type, static_name, hash_or_id, - /* match_retry= */ true))) { - // Skip scheduling - the retry was cancelled + // For retries, check if there's a cancelled timeout first + // Skip check for anonymous retries (STATIC_STRING with nullptr) - they can't be cancelled by name + if (is_retry && (name_type != NameType::STATIC_STRING || static_name != nullptr) && + type == SchedulerItem::TIMEOUT && + this->is_retry_cancelled_locked_(component, name_type, static_name, hash_or_id)) { + // Skip scheduling - the retry was cancelled #ifdef ESPHOME_DEBUG_SCHEDULER - SchedulerNameLog skip_name_log; - ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", - skip_name_log.format(name_type, static_name, hash_or_id)); + SchedulerNameLog skip_name_log; + ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", + skip_name_log.format(name_type, static_name, hash_or_id)); #endif - return; + return; + } } - // If name is provided, do atomic cancel-and-add (unless skip_cancel is true) - // Cancel existing items + // Common epilogue: atomic cancel-and-add (unless skip_cancel is true) if (!skip_cancel) { this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } - // Add new item directly to to_add_ - // since we have the lock held - this->to_add_.push_back(std::move(item)); + target->push_back(std::move(item)); } void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func) { diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index ede729d164..394178a831 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -219,28 +219,15 @@ class Scheduler { // Helper to get the name type NameType get_name_type() const { return name_type_; } - // Helper to set a static string name (no allocation) - void set_static_name(const char *name) { - name_.static_name = name; - name_type_ = NameType::STATIC_STRING; - } - - // Helper to set a hashed string name (hash computed from std::string) - void set_hashed_name(uint32_t hash) { - name_.hash_or_id = hash; - name_type_ = NameType::HASHED_STRING; - } - - // Helper to set a numeric ID name - void set_numeric_id(uint32_t id) { - name_.hash_or_id = id; - name_type_ = NameType::NUMERIC_ID; - } - - // Helper to set an internal numeric ID (separate namespace from NUMERIC_ID) - void set_internal_id(uint32_t id) { - name_.hash_or_id = id; - name_type_ = NameType::NUMERIC_ID_INTERNAL; + // Set name storage: for STATIC_STRING stores the pointer, for all other types stores hash_or_id. + // Both union members occupy the same offset, so only one store is needed. + void set_name(NameType type, const char *static_name, uint32_t hash_or_id) { + if (type == NameType::STATIC_STRING) { + name_.static_name = static_name; + } else { + name_.hash_or_id = hash_or_id; + } + name_type_ = type; } static bool cmp(const std::unique_ptr<SchedulerItem> &a, const std::unique_ptr<SchedulerItem> &b); @@ -355,6 +342,17 @@ class Scheduler { // Helper to perform full cleanup when too many items are cancelled void full_cleanup_removed_items_(); + // Helper to calculate random offset for interval timers - extracted to reduce code size of set_timer_common_ + // IMPORTANT: Must not be inlined - called only for intervals, keeping it out of the hot path saves flash. + uint32_t __attribute__((noinline)) calculate_interval_offset_(uint32_t delay); + + // Helper to check if a retry was already cancelled - extracted to reduce code size of set_timer_common_ + // Remove before 2026.8.0 along with all retry code. + // IMPORTANT: Must not be inlined - retry path is cold and deprecated. + // IMPORTANT: Caller must hold the scheduler lock before calling this function. + bool __attribute__((noinline)) + is_retry_cancelled_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); + #ifdef ESPHOME_DEBUG_SCHEDULER // Helper for debug logging in set_timer_common_ - extracted to reduce code size void debug_log_timer_(const SchedulerItem *item, NameType name_type, const char *static_name, uint32_t hash_or_id, From 4fb1ddf21204f562600641a77fca7cc226e4792a Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:40:21 +0100 Subject: [PATCH 0661/2030] [api] Fix compiler format warnings (#13931) --- esphome/components/api/api_connection.cpp | 2 +- esphome/components/api/proto.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 14ccbd2248..34d9744adc 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1510,7 +1510,7 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) { this->client_api_version_major_ = msg.api_version_major; this->client_api_version_minor_ = msg.api_version_minor; char peername[socket::SOCKADDR_STR_LEN]; - ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu32 ".%" PRIu32, this->helper_->get_client_name(), + ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu16 ".%" PRIu16, this->helper_->get_client_name(), this->helper_->get_peername_to(peername), this->client_api_version_major_, this->client_api_version_minor_); HelloResponse resp; diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 2a0ddf91db..764dd3f391 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -133,7 +133,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { break; } default: - ESP_LOGV(TAG, "Invalid field type %u at offset %ld", field_type, (long) (ptr - buffer)); + ESP_LOGV(TAG, "Invalid field type %" PRIu32 " at offset %ld", field_type, (long) (ptr - buffer)); return; } } From 8e785a22161684aa8aab084895d02e208e4dc4e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 08:40:41 -0600 Subject: [PATCH 0662/2030] [web_server] Remove unnecessary packed attribute from DeferredEvent (#13932) --- esphome/components/web_server/web_server.h | 12 +++++++----- esphome/components/web_server_idf/web_server_idf.h | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 224c051ece..ce09ebf7a9 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -112,10 +112,10 @@ class DeferredUpdateEventSource : public AsyncEventSource { /* This class holds a pointer to the source component that wants to publish a state event, and a pointer to a function that will lazily generate that event. The two pointers allow dedup in the deferred queue if multiple publishes for - the same component are backed up, and take up only 8 bytes of memory. The entry in the deferred queue (a - std::vector) is the DeferredEvent instance itself (not a pointer to one elsewhere in heap) so still only 8 bytes per - entry (and no heap fragmentation). Even 100 backed up events (you'd have to have at least 100 sensors publishing - because of dedup) would take up only 0.8 kB. + the same component are backed up, and take up only two pointers of memory. The entry in the deferred queue (a + std::vector) is the DeferredEvent instance itself (not a pointer to one elsewhere in heap) so still only two + pointers per entry (and no heap fragmentation). Even 100 backed up events (you'd have to have at least 100 sensors + publishing because of dedup) would take up only 0.8 kB. */ struct DeferredEvent { friend class DeferredUpdateEventSource; @@ -130,7 +130,9 @@ class DeferredUpdateEventSource : public AsyncEventSource { bool operator==(const DeferredEvent &test) const { return (source_ == test.source_ && message_generator_ == test.message_generator_); } - } __attribute__((packed)); + }; + static_assert(sizeof(DeferredEvent) == sizeof(void *) + sizeof(message_generator_t *), + "DeferredEvent should have no padding"); protected: // surface a couple methods from the base class diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 1760544963..6a409de74e 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -259,9 +259,9 @@ using message_generator_t = std::string(esphome::web_server::WebServer *, void * /* This class holds a pointer to the source component that wants to publish a state event, and a pointer to a function that will lazily generate that event. The two pointers allow dedup in the deferred queue if multiple publishes for - the same component are backed up, and take up only 8 bytes of memory. The entry in the deferred queue (a - std::vector) is the DeferredEvent instance itself (not a pointer to one elsewhere in heap) so still only 8 bytes per - entry (and no heap fragmentation). Even 100 backed up events (you'd have to have at least 100 sensors publishing + the same component are backed up, and take up only two pointers of memory. The entry in the deferred queue (a + std::vector) is the DeferredEvent instance itself (not a pointer to one elsewhere in heap) so still only two pointers + per entry (and no heap fragmentation). Even 100 backed up events (you'd have to have at least 100 sensors publishing because of dedup) would take up only 0.8 kB. */ struct DeferredEvent { @@ -277,7 +277,9 @@ struct DeferredEvent { bool operator==(const DeferredEvent &test) const { return (source_ == test.source_ && message_generator_ == test.message_generator_); } -} __attribute__((packed)); +}; +static_assert(sizeof(DeferredEvent) == sizeof(void *) + sizeof(message_generator_t *), + "DeferredEvent should have no padding"); class AsyncEventSourceResponse { friend class AsyncEventSource; From 37f97c9043d260600a5a853ff451bb634f7ad2f9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 08:41:15 -0600 Subject: [PATCH 0663/2030] [esp8266][rp2040] Eliminate heap fallback in preference save/load (#13928) --- esphome/components/esp8266/preferences.cpp | 29 +++++++++++----------- esphome/components/rp2040/preferences.cpp | 23 +++++++++-------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index f037b881a8..e749b1f633 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -33,6 +33,10 @@ static constexpr uint32_t MAX_PREFERENCE_WORDS = 255; #define ESP_RTC_USER_MEM ((uint32_t *) ESP_RTC_USER_MEM_START) +// Flash storage size depends on esp8266 -> restore_from_flash YAML option (default: false). +// When enabled (USE_ESP8266_PREFERENCES_FLASH), all preferences default to flash and need +// 128 words (512 bytes). When disabled, only explicit flash prefs use this storage so +// 64 words (256 bytes) suffices since most preferences go to RTC memory instead. #ifdef USE_ESP8266_PREFERENCES_FLASH static constexpr uint32_t ESP8266_FLASH_STORAGE_SIZE = 128; #else @@ -127,9 +131,11 @@ static bool load_from_rtc(size_t offset, uint32_t *data, size_t len) { return true; } -// Stack buffer size - 16 words total: up to 15 words of preference data + 1 word CRC (60 bytes of preference data) -// This handles virtually all real-world preferences without heap allocation -static constexpr size_t PREF_BUFFER_WORDS = 16; +// Maximum buffer for any single preference - bounded by storage sizes. +// Flash prefs: bounded by ESP8266_FLASH_STORAGE_SIZE (128 or 64 words). +// RTC prefs: bounded by RTC_NORMAL_REGION_WORDS (96) - a single pref can't span both RTC regions. +static constexpr size_t PREF_MAX_BUFFER_WORDS = + ESP8266_FLASH_STORAGE_SIZE > RTC_NORMAL_REGION_WORDS ? ESP8266_FLASH_STORAGE_SIZE : RTC_NORMAL_REGION_WORDS; class ESP8266PreferenceBackend : public ESPPreferenceBackend { public: @@ -141,15 +147,13 @@ class ESP8266PreferenceBackend : public ESPPreferenceBackend { bool save(const uint8_t *data, size_t len) override { if (bytes_to_words(len) != this->length_words) return false; - const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; - SmallBufferWithHeapFallback<PREF_BUFFER_WORDS, uint32_t> buffer_alloc(buffer_size); - uint32_t *buffer = buffer_alloc.get(); + if (buffer_size > PREF_MAX_BUFFER_WORDS) + return false; + uint32_t buffer[PREF_MAX_BUFFER_WORDS]; memset(buffer, 0, buffer_size * sizeof(uint32_t)); - memcpy(buffer, data, len); buffer[this->length_words] = calculate_crc(buffer, buffer + this->length_words, this->type); - return this->in_flash ? save_to_flash(this->offset, buffer, buffer_size) : save_to_rtc(this->offset, buffer, buffer_size); } @@ -157,19 +161,16 @@ class ESP8266PreferenceBackend : public ESPPreferenceBackend { bool load(uint8_t *data, size_t len) override { if (bytes_to_words(len) != this->length_words) return false; - const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; - SmallBufferWithHeapFallback<PREF_BUFFER_WORDS, uint32_t> buffer_alloc(buffer_size); - uint32_t *buffer = buffer_alloc.get(); - + if (buffer_size > PREF_MAX_BUFFER_WORDS) + return false; + uint32_t buffer[PREF_MAX_BUFFER_WORDS]; bool ret = this->in_flash ? load_from_flash(this->offset, buffer, buffer_size) : load_from_rtc(this->offset, buffer, buffer_size); if (!ret) return false; - if (buffer[this->length_words] != calculate_crc(buffer, buffer + this->length_words, this->type)) return false; - memcpy(data, buffer, len); return true; } diff --git a/esphome/components/rp2040/preferences.cpp b/esphome/components/rp2040/preferences.cpp index 172da32adc..fa72fd9a24 100644 --- a/esphome/components/rp2040/preferences.cpp +++ b/esphome/components/rp2040/preferences.cpp @@ -25,8 +25,8 @@ static uint8_t s_flash_storage[RP2040_FLASH_STORAGE_SIZE]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static bool s_flash_dirty = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -// Stack buffer size for preferences - covers virtually all real-world preferences without heap allocation -static constexpr size_t PREF_BUFFER_SIZE = 64; +// No preference can exceed the total flash storage, so stack buffer covers all cases. +static constexpr size_t PREF_MAX_BUFFER_SIZE = RP2040_FLASH_STORAGE_SIZE; extern "C" uint8_t _EEPROM_start; @@ -46,14 +46,14 @@ class RP2040PreferenceBackend : public ESPPreferenceBackend { bool save(const uint8_t *data, size_t len) override { const size_t buffer_size = len + 1; - SmallBufferWithHeapFallback<PREF_BUFFER_SIZE> buffer_alloc(buffer_size); - uint8_t *buffer = buffer_alloc.get(); - + if (buffer_size > PREF_MAX_BUFFER_SIZE) + return false; + uint8_t buffer[PREF_MAX_BUFFER_SIZE]; memcpy(buffer, data, len); - buffer[len] = calculate_crc(buffer, buffer + len, type); + buffer[len] = calculate_crc(buffer, buffer + len, this->type); for (size_t i = 0; i < buffer_size; i++) { - uint32_t j = offset + i; + uint32_t j = this->offset + i; if (j >= RP2040_FLASH_STORAGE_SIZE) return false; uint8_t v = buffer[i]; @@ -66,17 +66,18 @@ class RP2040PreferenceBackend : public ESPPreferenceBackend { } bool load(uint8_t *data, size_t len) override { const size_t buffer_size = len + 1; - SmallBufferWithHeapFallback<PREF_BUFFER_SIZE> buffer_alloc(buffer_size); - uint8_t *buffer = buffer_alloc.get(); + if (buffer_size > PREF_MAX_BUFFER_SIZE) + return false; + uint8_t buffer[PREF_MAX_BUFFER_SIZE]; for (size_t i = 0; i < buffer_size; i++) { - uint32_t j = offset + i; + uint32_t j = this->offset + i; if (j >= RP2040_FLASH_STORAGE_SIZE) return false; buffer[i] = s_flash_storage[j]; } - uint8_t crc = calculate_crc(buffer, buffer + len, type); + uint8_t crc = calculate_crc(buffer, buffer + len, this->type); if (buffer[len] != crc) { return false; } From 9bdae5183ca87c99d44381d01cb4c20b4f7ecdab Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Wed, 11 Feb 2026 16:43:55 +0100 Subject: [PATCH 0664/2030] [nrf52,logger] add support for task_log_buffer_size (#13862) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/logger/__init__.py | 14 +- esphome/components/logger/log_buffer.h | 190 +++++++++++++++ esphome/components/logger/logger.cpp | 91 +++----- esphome/components/logger/logger.h | 219 ++---------------- esphome/components/logger/logger_zephyr.cpp | 2 +- .../logger/task_log_buffer_esp32.cpp | 17 +- .../components/logger/task_log_buffer_esp32.h | 5 +- .../logger/task_log_buffer_host.cpp | 23 +- .../components/logger/task_log_buffer_host.h | 13 +- .../logger/task_log_buffer_libretiny.cpp | 22 +- .../logger/task_log_buffer_libretiny.h | 8 +- .../logger/task_log_buffer_zephyr.cpp | 116 ++++++++++ .../logger/task_log_buffer_zephyr.h | 66 ++++++ esphome/core/defines.h | 1 + .../logger/test.nrf52-adafruit.yaml | 1 + 15 files changed, 479 insertions(+), 309 deletions(-) create mode 100644 esphome/components/logger/log_buffer.h create mode 100644 esphome/components/logger/task_log_buffer_zephyr.cpp create mode 100644 esphome/components/logger/task_log_buffer_zephyr.h diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 40ceaec7dc..b2952d7995 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -231,9 +231,16 @@ CONFIG_SCHEMA = cv.All( bk72xx=768, ln882x=768, rtl87xx=768, + nrf52=768, ): cv.All( cv.only_on( - [PLATFORM_ESP32, PLATFORM_BK72XX, PLATFORM_LN882X, PLATFORM_RTL87XX] + [ + PLATFORM_ESP32, + PLATFORM_BK72XX, + PLATFORM_LN882X, + PLATFORM_RTL87XX, + PLATFORM_NRF52, + ] ), cv.validate_bytes, cv.Any( @@ -313,11 +320,13 @@ async def to_code(config): ) if CORE.is_esp32: cg.add(log.create_pthread_key()) - if CORE.is_esp32 or CORE.is_libretiny: + if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] if task_log_buffer_size > 0: cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") cg.add(log.init_log_buffer(task_log_buffer_size)) + if CORE.using_zephyr: + zephyr_add_prj_conf("MPSC_PBUF", True) elif CORE.is_host: cg.add(log.create_pthread_key()) cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") @@ -417,6 +426,7 @@ async def to_code(config): pass if CORE.is_nrf52: + zephyr_add_prj_conf("THREAD_LOCAL_STORAGE", True) if config[CONF_HARDWARE_UART] == UART0: zephyr_add_overlay("""&uart0 { status = "okay";};""") if config[CONF_HARDWARE_UART] == UART1: diff --git a/esphome/components/logger/log_buffer.h b/esphome/components/logger/log_buffer.h new file mode 100644 index 0000000000..3d87278248 --- /dev/null +++ b/esphome/components/logger/log_buffer.h @@ -0,0 +1,190 @@ +#pragma once + +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome::logger { + +// Maximum header size: 35 bytes fixed + 32 bytes tag + 16 bytes thread name = 83 bytes (45 byte safety margin) +static constexpr uint16_t MAX_HEADER_SIZE = 128; + +// ANSI color code last digit (30-38 range, store only last digit to save RAM) +static constexpr char LOG_LEVEL_COLOR_DIGIT[] = { + '\0', // NONE + '1', // ERROR (31 = red) + '3', // WARNING (33 = yellow) + '2', // INFO (32 = green) + '5', // CONFIG (35 = magenta) + '6', // DEBUG (36 = cyan) + '7', // VERBOSE (37 = gray) + '8', // VERY_VERBOSE (38 = white) +}; + +static constexpr char LOG_LEVEL_LETTER_CHARS[] = { + '\0', // NONE + 'E', // ERROR + 'W', // WARNING + 'I', // INFO + 'C', // CONFIG + 'D', // DEBUG + 'V', // VERBOSE (VERY_VERBOSE uses two 'V's) +}; + +// Buffer wrapper for log formatting functions +struct LogBuffer { + char *data; + uint16_t size; + uint16_t pos{0}; + // Replaces the null terminator with a newline for console output. + // Must be called after notify_listeners_() since listeners need null-terminated strings. + // Console output uses length-based writes (buf.pos), so null terminator is not needed. + void terminate_with_newline() { + if (this->pos < this->size) { + this->data[this->pos++] = '\n'; + } else if (this->size > 0) { + // Buffer was full - replace last char with newline to ensure it's visible + this->data[this->size - 1] = '\n'; + this->pos = this->size; + } + } + void HOT write_header(uint8_t level, const char *tag, int line, const char *thread_name) { + // Early return if insufficient space - intentionally don't update pos to prevent partial writes + if (this->pos + MAX_HEADER_SIZE > this->size) + return; + + char *p = this->current_(); + + // Write ANSI color + this->write_ansi_color_(p, level); + + // Construct: [LEVEL][tag:line] + *p++ = '['; + if (level != 0) { + if (level >= 7) { + *p++ = 'V'; // VERY_VERBOSE = "VV" + *p++ = 'V'; + } else { + *p++ = LOG_LEVEL_LETTER_CHARS[level]; + } + } + *p++ = ']'; + *p++ = '['; + + // Copy tag + this->copy_string_(p, tag); + + *p++ = ':'; + + // Format line number without modulo operations + if (line > 999) [[unlikely]] { + int thousands = line / 1000; + *p++ = '0' + thousands; + line -= thousands * 1000; + } + int hundreds = line / 100; + int remainder = line - hundreds * 100; + int tens = remainder / 10; + *p++ = '0' + hundreds; + *p++ = '0' + tens; + *p++ = '0' + (remainder - tens * 10); + *p++ = ']'; + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST) + // Write thread name with bold red color + if (thread_name != nullptr) { + this->write_ansi_color_(p, 1); // Bold red for thread name + *p++ = '['; + this->copy_string_(p, thread_name); + *p++ = ']'; + this->write_ansi_color_(p, level); // Restore original color + } +#endif + + *p++ = ':'; + *p++ = ' '; + + this->pos = p - this->data; + } + void HOT format_body(const char *format, va_list args) { + this->format_vsnprintf_(format, args); + this->finalize_(); + } +#ifdef USE_STORE_LOG_STR_IN_FLASH + void HOT format_body_P(PGM_P format, va_list args) { + this->format_vsnprintf_P_(format, args); + this->finalize_(); + } +#endif + void write_body(const char *text, uint16_t text_length) { + this->write_(text, text_length); + this->finalize_(); + } + + private: + bool full_() const { return this->pos >= this->size; } + uint16_t remaining_() const { return this->size - this->pos; } + char *current_() { return this->data + this->pos; } + void write_(const char *value, uint16_t length) { + const uint16_t available = this->remaining_(); + const uint16_t copy_len = (length < available) ? length : available; + if (copy_len > 0) { + memcpy(this->current_(), value, copy_len); + this->pos += copy_len; + } + } + void finalize_() { + // Write color reset sequence + static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; + this->write_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN); + // Null terminate + this->data[this->full_() ? this->size - 1 : this->pos] = '\0'; + } + void strip_trailing_newlines_() { + while (this->pos > 0 && this->data[this->pos - 1] == '\n') + this->pos--; + } + void process_vsnprintf_result_(int ret) { + if (ret < 0) + return; + const uint16_t rem = this->remaining_(); + this->pos += (ret >= rem) ? (rem - 1) : static_cast<uint16_t>(ret); + this->strip_trailing_newlines_(); + } + void format_vsnprintf_(const char *format, va_list args) { + if (this->full_()) + return; + this->process_vsnprintf_result_(vsnprintf(this->current_(), this->remaining_(), format, args)); + } +#ifdef USE_STORE_LOG_STR_IN_FLASH + void format_vsnprintf_P_(PGM_P format, va_list args) { + if (this->full_()) + return; + this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(), format, args)); + } +#endif + // Write ANSI color escape sequence to buffer, updates pointer in place + // Caller is responsible for ensuring buffer has sufficient space + void write_ansi_color_(char *&p, uint8_t level) { + if (level == 0) + return; + // Direct buffer fill: "\033[{bold};3{color}m" (7 bytes) + *p++ = '\033'; + *p++ = '['; + *p++ = (level == 1) ? '1' : '0'; // Only ERROR is bold + *p++ = ';'; + *p++ = '3'; + *p++ = LOG_LEVEL_COLOR_DIGIT[level]; + *p++ = 'm'; + } + // Copy string without null terminator, updates pointer in place + // Caller is responsible for ensuring buffer has sufficient space + void copy_string_(char *&p, const char *str) { + const size_t len = strlen(str); + // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - intentionally no null terminator, building string piece by + // piece + memcpy(p, str, len); + p += len; + } +}; + +} // namespace esphome::logger diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index bb20c403e5..e1b49bcb61 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -10,9 +10,9 @@ namespace esphome::logger { static const char *const TAG = "logger"; -#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) -// Implementation for multi-threaded platforms (ESP32 with FreeRTOS, Host with pthreads, LibreTiny with FreeRTOS) -// Main thread/task always uses direct buffer access for console output and callbacks +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) +// Implementation for multi-threaded platforms (ESP32 with FreeRTOS, Host with pthreads, LibreTiny with FreeRTOS, +// Zephyr) Main thread/task always uses direct buffer access for console output and callbacks // // For non-main threads/tasks: // - WITH task log buffer: Prefer sending to ring buffer for async processing @@ -31,6 +31,9 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch // Get task handle once - used for both main task check and passing to non-main thread handler TaskHandle_t current_task = xTaskGetCurrentTaskHandle(); const bool is_main_task = (current_task == this->main_task_); +#elif (USE_ZEPHYR) + k_tid_t current_task = k_current_get(); + const bool is_main_task = (current_task == this->main_task_); #else // USE_HOST const bool is_main_task = pthread_equal(pthread_self(), this->main_thread_); #endif @@ -54,6 +57,9 @@ void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const ch // Host: pass a stack buffer for pthread_getname_np to write into. #if defined(USE_ESP32) || defined(USE_LIBRETINY) const char *thread_name = get_thread_name_(current_task); +#elif defined(USE_ZEPHYR) + char thread_name_buf[MAX_POINTER_REPRESENTATION]; + const char *thread_name = get_thread_name_(thread_name_buf, current_task); #else // USE_HOST char thread_name_buf[THREAD_NAME_BUF_SIZE]; const char *thread_name = this->get_thread_name_(thread_name_buf); @@ -83,18 +89,21 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li // This is safe to call from any context including ISRs this->enable_loop_soon_any_context(); } -#endif // USE_ESPHOME_TASK_LOG_BUFFER - +#endif // Emergency console logging for non-main threads when ring buffer is full or disabled // This is a fallback mechanism to ensure critical log messages are visible // Note: This may cause interleaved/corrupted console output if multiple threads // log simultaneously, but it's better than losing important messages entirely #ifdef USE_HOST - if (!message_sent) { + if (!message_sent) +#else + if (!message_sent && this->baud_rate_ > 0) // If logging is enabled, write to console +#endif + { +#ifdef USE_HOST // Host always has console output - no baud_rate check needed static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 512; #else - if (!message_sent && this->baud_rate_ > 0) { // If logging is enabled, write to console // Maximum size for console log messages (includes null terminator) static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144; #endif @@ -107,22 +116,16 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li // RAII guard automatically resets on return } #else -// Implementation for single-task platforms (ESP8266, RP2040, Zephyr) -// TODO: Zephyr may have multiple threads (work queues, etc.) but uses this single-task path. +// Implementation for single-task platforms (ESP8266, RP2040) // Logging calls are NOT thread-safe: global_recursion_guard_ is a plain bool and tx_buffer_ has no locking. // Not a problem in practice yet since Zephyr has no API support (logs are console-only). void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT if (level > this->level_for(tag) || global_recursion_guard_) return; -#ifdef USE_ZEPHYR - char tmp[MAX_POINTER_REPRESENTATION]; - this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args, - this->get_thread_name_(tmp)); -#else // Other single-task platforms don't have thread names, so pass nullptr + // Other single-task platforms don't have thread names, so pass nullptr this->log_message_to_buffer_and_send_(global_recursion_guard_, level, tag, line, format, args, nullptr); -#endif } -#endif // USE_ESP32 / USE_HOST / USE_LIBRETINY +#endif // USE_ESP32 || USE_HOST || USE_LIBRETINY || USE_ZEPHYR #ifdef USE_STORE_LOG_STR_IN_FLASH // Implementation for ESP8266 with flash string support. @@ -163,19 +166,12 @@ Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate } #ifdef USE_ESPHOME_TASK_LOG_BUFFER void Logger::init_log_buffer(size_t total_buffer_size) { -#ifdef USE_HOST // Host uses slot count instead of byte size - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->log_buffer_ = new logger::TaskLogBufferHost(total_buffer_size); -#elif defined(USE_ESP32) // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size); -#elif defined(USE_LIBRETINY) - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->log_buffer_ = new logger::TaskLogBufferLibreTiny(total_buffer_size); -#endif -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +// Zephyr needs loop working to check when CDC port is open +#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) // Start with loop disabled when using task buffer (unless using USB CDC on ESP32) // The loop will be enabled automatically when messages arrive this->disable_loop_when_buffer_empty_(); @@ -183,52 +179,33 @@ void Logger::init_log_buffer(size_t total_buffer_size) { } #endif -#ifdef USE_ESPHOME_TASK_LOG_BUFFER -void Logger::loop() { this->process_messages_(); } +#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)) +void Logger::loop() { + this->process_messages_(); +#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC) + this->cdc_loop_(); +#endif +} #endif void Logger::process_messages_() { #ifdef USE_ESPHOME_TASK_LOG_BUFFER // Process any buffered messages when available if (this->log_buffer_->has_messages()) { -#ifdef USE_HOST - logger::TaskLogBufferHost::LogMessage *message; - while (this->log_buffer_->get_message_main_loop(&message)) { - const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; - LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; - this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, message->text, - message->text_length, buf); - this->log_buffer_->release_message_main_loop(); - this->write_log_buffer_to_console_(buf); - } -#elif defined(USE_ESP32) logger::TaskLogBuffer::LogMessage *message; - const char *text; - void *received_token; - while (this->log_buffer_->borrow_message_main_loop(&message, &text, &received_token)) { + uint16_t text_length; + while (this->log_buffer_->borrow_message_main_loop(message, text_length)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; - this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, text, - message->text_length, buf); - // Release the message to allow other tasks to use it as soon as possible - this->log_buffer_->release_message_main_loop(received_token); - this->write_log_buffer_to_console_(buf); - } -#elif defined(USE_LIBRETINY) - logger::TaskLogBufferLibreTiny::LogMessage *message; - const char *text; - while (this->log_buffer_->borrow_message_main_loop(&message, &text)) { - const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; - LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; - this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, text, - message->text_length, buf); + this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, + message->text_data(), text_length, buf); // Release the message to allow other tasks to use it as soon as possible this->log_buffer_->release_message_main_loop(); this->write_log_buffer_to_console_(buf); } -#endif } -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +// Zephyr needs loop working to check when CDC port is open +#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) else { // No messages to process, disable loop if appropriate // This reduces overhead when there's no async logging activity diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index ecf032ee0e..835542dd8f 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -13,15 +13,11 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#ifdef USE_ESPHOME_TASK_LOG_BUFFER -#ifdef USE_HOST +#include "log_buffer.h" #include "task_log_buffer_host.h" -#elif defined(USE_ESP32) #include "task_log_buffer_esp32.h" -#elif defined(USE_LIBRETINY) #include "task_log_buffer_libretiny.h" -#endif -#endif +#include "task_log_buffer_zephyr.h" #ifdef USE_ARDUINO #if defined(USE_ESP8266) @@ -97,195 +93,10 @@ struct CStrCompare { }; #endif -// ANSI color code last digit (30-38 range, store only last digit to save RAM) -static constexpr char LOG_LEVEL_COLOR_DIGIT[] = { - '\0', // NONE - '1', // ERROR (31 = red) - '3', // WARNING (33 = yellow) - '2', // INFO (32 = green) - '5', // CONFIG (35 = magenta) - '6', // DEBUG (36 = cyan) - '7', // VERBOSE (37 = gray) - '8', // VERY_VERBOSE (38 = white) -}; - -static constexpr char LOG_LEVEL_LETTER_CHARS[] = { - '\0', // NONE - 'E', // ERROR - 'W', // WARNING - 'I', // INFO - 'C', // CONFIG - 'D', // DEBUG - 'V', // VERBOSE (VERY_VERBOSE uses two 'V's) -}; - -// Maximum header size: 35 bytes fixed + 32 bytes tag + 16 bytes thread name = 83 bytes (45 byte safety margin) -static constexpr uint16_t MAX_HEADER_SIZE = 128; - -// "0x" + 2 hex digits per byte + '\0' -static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1; - // Stack buffer size for retrieving thread/task names from the OS // macOS allows up to 64 bytes, Linux up to 16 static constexpr size_t THREAD_NAME_BUF_SIZE = 64; -// Buffer wrapper for log formatting functions -struct LogBuffer { - char *data; - uint16_t size; - uint16_t pos{0}; - // Replaces the null terminator with a newline for console output. - // Must be called after notify_listeners_() since listeners need null-terminated strings. - // Console output uses length-based writes (buf.pos), so null terminator is not needed. - void terminate_with_newline() { - if (this->pos < this->size) { - this->data[this->pos++] = '\n'; - } else if (this->size > 0) { - // Buffer was full - replace last char with newline to ensure it's visible - this->data[this->size - 1] = '\n'; - this->pos = this->size; - } - } - void HOT write_header(uint8_t level, const char *tag, int line, const char *thread_name) { - // Early return if insufficient space - intentionally don't update pos to prevent partial writes - if (this->pos + MAX_HEADER_SIZE > this->size) - return; - - char *p = this->current_(); - - // Write ANSI color - this->write_ansi_color_(p, level); - - // Construct: [LEVEL][tag:line] - *p++ = '['; - if (level != 0) { - if (level >= 7) { - *p++ = 'V'; // VERY_VERBOSE = "VV" - *p++ = 'V'; - } else { - *p++ = LOG_LEVEL_LETTER_CHARS[level]; - } - } - *p++ = ']'; - *p++ = '['; - - // Copy tag - this->copy_string_(p, tag); - - *p++ = ':'; - - // Format line number without modulo operations - if (line > 999) [[unlikely]] { - int thousands = line / 1000; - *p++ = '0' + thousands; - line -= thousands * 1000; - } - int hundreds = line / 100; - int remainder = line - hundreds * 100; - int tens = remainder / 10; - *p++ = '0' + hundreds; - *p++ = '0' + tens; - *p++ = '0' + (remainder - tens * 10); - *p++ = ']'; - -#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST) - // Write thread name with bold red color - if (thread_name != nullptr) { - this->write_ansi_color_(p, 1); // Bold red for thread name - *p++ = '['; - this->copy_string_(p, thread_name); - *p++ = ']'; - this->write_ansi_color_(p, level); // Restore original color - } -#endif - - *p++ = ':'; - *p++ = ' '; - - this->pos = p - this->data; - } - void HOT format_body(const char *format, va_list args) { - this->format_vsnprintf_(format, args); - this->finalize_(); - } -#ifdef USE_STORE_LOG_STR_IN_FLASH - void HOT format_body_P(PGM_P format, va_list args) { - this->format_vsnprintf_P_(format, args); - this->finalize_(); - } -#endif - void write_body(const char *text, uint16_t text_length) { - this->write_(text, text_length); - this->finalize_(); - } - - private: - bool full_() const { return this->pos >= this->size; } - uint16_t remaining_() const { return this->size - this->pos; } - char *current_() { return this->data + this->pos; } - void write_(const char *value, uint16_t length) { - const uint16_t available = this->remaining_(); - const uint16_t copy_len = (length < available) ? length : available; - if (copy_len > 0) { - memcpy(this->current_(), value, copy_len); - this->pos += copy_len; - } - } - void finalize_() { - // Write color reset sequence - static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; - this->write_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN); - // Null terminate - this->data[this->full_() ? this->size - 1 : this->pos] = '\0'; - } - void strip_trailing_newlines_() { - while (this->pos > 0 && this->data[this->pos - 1] == '\n') - this->pos--; - } - void process_vsnprintf_result_(int ret) { - if (ret < 0) - return; - const uint16_t rem = this->remaining_(); - this->pos += (ret >= rem) ? (rem - 1) : static_cast<uint16_t>(ret); - this->strip_trailing_newlines_(); - } - void format_vsnprintf_(const char *format, va_list args) { - if (this->full_()) - return; - this->process_vsnprintf_result_(vsnprintf(this->current_(), this->remaining_(), format, args)); - } -#ifdef USE_STORE_LOG_STR_IN_FLASH - void format_vsnprintf_P_(PGM_P format, va_list args) { - if (this->full_()) - return; - this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(), format, args)); - } -#endif - // Write ANSI color escape sequence to buffer, updates pointer in place - // Caller is responsible for ensuring buffer has sufficient space - void write_ansi_color_(char *&p, uint8_t level) { - if (level == 0) - return; - // Direct buffer fill: "\033[{bold};3{color}m" (7 bytes) - *p++ = '\033'; - *p++ = '['; - *p++ = (level == 1) ? '1' : '0'; // Only ERROR is bold - *p++ = ';'; - *p++ = '3'; - *p++ = LOG_LEVEL_COLOR_DIGIT[level]; - *p++ = 'm'; - } - // Copy string without null terminator, updates pointer in place - // Caller is responsible for ensuring buffer has sufficient space - void copy_string_(char *&p, const char *str) { - const size_t len = strlen(str); - // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - intentionally no null terminator, building string piece by - // piece - memcpy(p, str, len); - p += len; - } -}; - #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) /** Enum for logging UART selection * @@ -411,11 +222,14 @@ class Logger : public Component { bool &flag_; }; -#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) // Handles non-main thread logging only (~0.1% of calls) // thread_name is resolved by the caller from the task handle, avoiding redundant lookups void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, const char *thread_name); +#endif +#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC) + void cdc_loop_(); #endif void process_messages_(); void write_msg_(const char *msg, uint16_t len); @@ -534,13 +348,7 @@ class Logger : public Component { std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners #endif #ifdef USE_ESPHOME_TASK_LOG_BUFFER -#ifdef USE_HOST - logger::TaskLogBufferHost *log_buffer_{nullptr}; // Allocated once, never freed -#elif defined(USE_ESP32) logger::TaskLogBuffer *log_buffer_{nullptr}; // Allocated once, never freed -#elif defined(USE_LIBRETINY) - logger::TaskLogBufferLibreTiny *log_buffer_{nullptr}; // Allocated once, never freed -#endif #endif // Group smaller types together at the end @@ -552,7 +360,7 @@ class Logger : public Component { #ifdef USE_LIBRETINY UARTSelection uart_{UART_SELECTION_DEFAULT}; #endif -#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) bool main_task_recursion_guard_{false}; #ifdef USE_LIBRETINY bool non_main_task_recursion_guard_{false}; // Shared guard for all non-main tasks on LibreTiny @@ -595,8 +403,10 @@ class Logger : public Component { } #elif defined(USE_ZEPHYR) - const char *HOT get_thread_name_(std::span<char> buff) { - k_tid_t current_task = k_current_get(); + const char *HOT get_thread_name_(std::span<char> buff, k_tid_t current_task = nullptr) { + if (current_task == nullptr) { + current_task = k_current_get(); + } if (current_task == main_task_) { return nullptr; // Main task } @@ -635,7 +445,7 @@ class Logger : public Component { // Create RAII guard for non-main task recursion inline NonMainTaskRecursionGuard make_non_main_task_guard_() { return NonMainTaskRecursionGuard(log_recursion_key_); } -#elif defined(USE_LIBRETINY) +#elif defined(USE_LIBRETINY) || defined(USE_ZEPHYR) // LibreTiny doesn't have FreeRTOS TLS, so use a simple approach: // - Main task uses dedicated boolean (same as ESP32) // - Non-main tasks share a single recursion guard @@ -643,6 +453,8 @@ class Logger : public Component { // - Recursion from logging within logging is the main concern // - Cross-task "recursion" is prevented by the buffer mutex anyway // - Missing a recursive call from another task is acceptable (falls back to direct output) + // + // Zephyr use __thread as TLS // Check if non-main task is already in recursion inline bool HOT is_non_main_task_recursive_() const { return non_main_task_recursion_guard_; } @@ -651,7 +463,8 @@ class Logger : public Component { inline RecursionGuard make_non_main_task_guard_() { return RecursionGuard(non_main_task_recursion_guard_); } #endif -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +// Zephyr needs loop working to check when CDC port is open +#if defined(USE_ESPHOME_TASK_LOG_BUFFER) && !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) // Disable loop when task buffer is empty (with USB CDC check on ESP32) inline void disable_loop_when_buffer_empty_() { // Thread safety note: This is safe even if another task calls enable_loop_soon_any_context() diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index 1fc0acd573..f565c5760c 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -14,7 +14,7 @@ namespace esphome::logger { static const char *const TAG = "logger"; #ifdef USE_LOGGER_USB_CDC -void Logger::loop() { +void Logger::cdc_loop_() { if (this->uart_ != UART_SELECTION_USB_CDC || this->uart_dev_ == nullptr) { return; } diff --git a/esphome/components/logger/task_log_buffer_esp32.cpp b/esphome/components/logger/task_log_buffer_esp32.cpp index 56c0a4ae2d..e747ddc4d8 100644 --- a/esphome/components/logger/task_log_buffer_esp32.cpp +++ b/esphome/components/logger/task_log_buffer_esp32.cpp @@ -31,8 +31,8 @@ TaskLogBuffer::~TaskLogBuffer() { } } -bool TaskLogBuffer::borrow_message_main_loop(LogMessage **message, const char **text, void **received_token) { - if (message == nullptr || text == nullptr || received_token == nullptr) { +bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) { + if (this->current_token_) { return false; } @@ -43,18 +43,19 @@ bool TaskLogBuffer::borrow_message_main_loop(LogMessage **message, const char ** } LogMessage *msg = static_cast<LogMessage *>(received_item); - *message = msg; - *text = msg->text_data(); - *received_token = received_item; + message = msg; + text_length = msg->text_length; + this->current_token_ = received_item; return true; } -void TaskLogBuffer::release_message_main_loop(void *token) { - if (token == nullptr) { +void TaskLogBuffer::release_message_main_loop() { + if (this->current_token_ == nullptr) { return; } - vRingbufferReturnItem(ring_buffer_, token); + vRingbufferReturnItem(ring_buffer_, this->current_token_); + this->current_token_ = nullptr; // Update counter to mark all messages as processed last_processed_counter_ = message_counter_.load(std::memory_order_relaxed); } diff --git a/esphome/components/logger/task_log_buffer_esp32.h b/esphome/components/logger/task_log_buffer_esp32.h index 6c1bafaeba..88d72eacfc 100644 --- a/esphome/components/logger/task_log_buffer_esp32.h +++ b/esphome/components/logger/task_log_buffer_esp32.h @@ -52,10 +52,10 @@ class TaskLogBuffer { ~TaskLogBuffer(); // NOT thread-safe - borrow a message from the ring buffer, only call from main loop - bool borrow_message_main_loop(LogMessage **message, const char **text, void **received_token); + bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length); // NOT thread-safe - release a message buffer and update the counter, only call from main loop - void release_message_main_loop(void *token); + void release_message_main_loop(); // Thread-safe - send a message to the ring buffer from any thread bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, @@ -78,6 +78,7 @@ class TaskLogBuffer { // Atomic counter for message tracking (only differences matter) std::atomic<uint16_t> message_counter_{0}; // Incremented when messages are committed mutable uint16_t last_processed_counter_{0}; // Tracks last processed message + void *current_token_{nullptr}; }; } // namespace esphome::logger diff --git a/esphome/components/logger/task_log_buffer_host.cpp b/esphome/components/logger/task_log_buffer_host.cpp index 676686304a..c2ab009db4 100644 --- a/esphome/components/logger/task_log_buffer_host.cpp +++ b/esphome/components/logger/task_log_buffer_host.cpp @@ -10,16 +10,16 @@ namespace esphome::logger { -TaskLogBufferHost::TaskLogBufferHost(size_t slot_count) : slot_count_(slot_count) { +TaskLogBuffer::TaskLogBuffer(size_t slot_count) : slot_count_(slot_count) { // Allocate message slots this->slots_ = std::make_unique<LogMessage[]>(slot_count); } -TaskLogBufferHost::~TaskLogBufferHost() { +TaskLogBuffer::~TaskLogBuffer() { // unique_ptr handles cleanup automatically } -int TaskLogBufferHost::acquire_write_slot_() { +int TaskLogBuffer::acquire_write_slot_() { // Try to reserve a slot using compare-and-swap size_t current_reserve = this->reserve_index_.load(std::memory_order_relaxed); @@ -43,7 +43,7 @@ int TaskLogBufferHost::acquire_write_slot_() { } } -void TaskLogBufferHost::commit_write_slot_(int slot_index) { +void TaskLogBuffer::commit_write_slot_(int slot_index) { // Mark the slot as ready for reading this->slots_[slot_index].ready.store(true, std::memory_order_release); @@ -70,8 +70,8 @@ void TaskLogBufferHost::commit_write_slot_(int slot_index) { } } -bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, - const char *format, va_list args) { +bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args) { // Acquire a slot int slot_index = this->acquire_write_slot_(); if (slot_index < 0) { @@ -115,11 +115,7 @@ bool TaskLogBufferHost::send_message_thread_safe(uint8_t level, const char *tag, return true; } -bool TaskLogBufferHost::get_message_main_loop(LogMessage **message) { - if (message == nullptr) { - return false; - } - +bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) { size_t current_read = this->read_index_.load(std::memory_order_relaxed); size_t current_write = this->write_index_.load(std::memory_order_acquire); @@ -134,11 +130,12 @@ bool TaskLogBufferHost::get_message_main_loop(LogMessage **message) { return false; } - *message = &msg; + message = &msg; + text_length = msg.text_length; return true; } -void TaskLogBufferHost::release_message_main_loop() { +void TaskLogBuffer::release_message_main_loop() { size_t current_read = this->read_index_.load(std::memory_order_relaxed); // Clear the ready flag diff --git a/esphome/components/logger/task_log_buffer_host.h b/esphome/components/logger/task_log_buffer_host.h index f8e4ee7bee..1d4d2b0ec1 100644 --- a/esphome/components/logger/task_log_buffer_host.h +++ b/esphome/components/logger/task_log_buffer_host.h @@ -21,12 +21,12 @@ namespace esphome::logger { * * Threading Model: Multi-Producer Single-Consumer (MPSC) * - Multiple threads can safely call send_message_thread_safe() concurrently - * - Only the main loop thread calls get_message_main_loop() and release_message_main_loop() + * - Only the main loop thread calls borrow_message_main_loop() and release_message_main_loop() * * Producers (multiple threads) Consumer (main loop only) * │ │ * ▼ ▼ - * acquire_write_slot_() get_message_main_loop() + * acquire_write_slot_() bool borrow_message_main_loop() * CAS on reserve_index_ read write_index_ * │ check ready flag * ▼ │ @@ -48,7 +48,7 @@ namespace esphome::logger { * - Atomic CAS for slot reservation allows multiple producers without locks * - Single consumer (main loop) processes messages in order */ -class TaskLogBufferHost { +class TaskLogBuffer { public: // Default number of message slots - host has plenty of memory static constexpr size_t DEFAULT_SLOT_COUNT = 64; @@ -71,15 +71,16 @@ class TaskLogBufferHost { thread_name[0] = '\0'; text[0] = '\0'; } + inline char *text_data() { return this->text; } }; /// Constructor that takes the number of message slots - explicit TaskLogBufferHost(size_t slot_count); - ~TaskLogBufferHost(); + explicit TaskLogBuffer(size_t slot_count); + ~TaskLogBuffer(); // NOT thread-safe - get next message from buffer, only call from main loop // Returns true if a message was retrieved, false if buffer is empty - bool get_message_main_loop(LogMessage **message); + bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length); // NOT thread-safe - release the message after processing, only call from main loop void release_message_main_loop(); diff --git a/esphome/components/logger/task_log_buffer_libretiny.cpp b/esphome/components/logger/task_log_buffer_libretiny.cpp index 5a22857dcb..5969f6fb40 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.cpp +++ b/esphome/components/logger/task_log_buffer_libretiny.cpp @@ -8,7 +8,7 @@ namespace esphome::logger { -TaskLogBufferLibreTiny::TaskLogBufferLibreTiny(size_t total_buffer_size) { +TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) { this->size_ = total_buffer_size; // Allocate memory for the circular buffer using ESPHome's RAM allocator RAMAllocator<uint8_t> allocator; @@ -17,7 +17,7 @@ TaskLogBufferLibreTiny::TaskLogBufferLibreTiny(size_t total_buffer_size) { this->mutex_ = xSemaphoreCreateMutex(); } -TaskLogBufferLibreTiny::~TaskLogBufferLibreTiny() { +TaskLogBuffer::~TaskLogBuffer() { if (this->mutex_ != nullptr) { vSemaphoreDelete(this->mutex_); this->mutex_ = nullptr; @@ -29,7 +29,7 @@ TaskLogBufferLibreTiny::~TaskLogBufferLibreTiny() { } } -size_t TaskLogBufferLibreTiny::available_contiguous_space() const { +size_t TaskLogBuffer::available_contiguous_space() const { if (this->head_ >= this->tail_) { // head is ahead of or equal to tail // Available space is from head to end, plus from start to tail @@ -47,11 +47,7 @@ size_t TaskLogBufferLibreTiny::available_contiguous_space() const { } } -bool TaskLogBufferLibreTiny::borrow_message_main_loop(LogMessage **message, const char **text) { - if (message == nullptr || text == nullptr) { - return false; - } - +bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) { // Check if buffer was initialized successfully if (this->mutex_ == nullptr || this->storage_ == nullptr) { return false; @@ -77,15 +73,15 @@ bool TaskLogBufferLibreTiny::borrow_message_main_loop(LogMessage **message, cons this->tail_ = 0; msg = reinterpret_cast<LogMessage *>(this->storage_); } - *message = msg; - *text = msg->text_data(); + message = msg; + text_length = msg->text_length; this->current_message_size_ = message_total_size(msg->text_length); // Keep mutex held until release_message_main_loop() return true; } -void TaskLogBufferLibreTiny::release_message_main_loop() { +void TaskLogBuffer::release_message_main_loop() { // Advance tail past the current message this->tail_ += this->current_message_size_; @@ -100,8 +96,8 @@ void TaskLogBufferLibreTiny::release_message_main_loop() { xSemaphoreGive(this->mutex_); } -bool TaskLogBufferLibreTiny::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, - const char *thread_name, const char *format, va_list args) { +bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args) { // First, calculate the exact length needed using a null buffer (no actual writing) va_list args_copy; va_copy(args_copy, args); diff --git a/esphome/components/logger/task_log_buffer_libretiny.h b/esphome/components/logger/task_log_buffer_libretiny.h index bf315e828a..c065065fe7 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.h +++ b/esphome/components/logger/task_log_buffer_libretiny.h @@ -40,7 +40,7 @@ namespace esphome::logger { * - Volatile counter enables fast has_messages() without lock overhead * - If message doesn't fit at end, padding is added and message wraps to start */ -class TaskLogBufferLibreTiny { +class TaskLogBuffer { public: // Structure for a log message header (text data follows immediately after) struct LogMessage { @@ -60,11 +60,11 @@ class TaskLogBufferLibreTiny { static constexpr uint8_t PADDING_MARKER_LEVEL = 0xFF; // Constructor that takes a total buffer size - explicit TaskLogBufferLibreTiny(size_t total_buffer_size); - ~TaskLogBufferLibreTiny(); + explicit TaskLogBuffer(size_t total_buffer_size); + ~TaskLogBuffer(); // NOT thread-safe - borrow a message from the buffer, only call from main loop - bool borrow_message_main_loop(LogMessage **message, const char **text); + bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length); // NOT thread-safe - release a message buffer, only call from main loop void release_message_main_loop(); diff --git a/esphome/components/logger/task_log_buffer_zephyr.cpp b/esphome/components/logger/task_log_buffer_zephyr.cpp new file mode 100644 index 0000000000..44d12d08a3 --- /dev/null +++ b/esphome/components/logger/task_log_buffer_zephyr.cpp @@ -0,0 +1,116 @@ +#ifdef USE_ZEPHYR + +#include "task_log_buffer_zephyr.h" + +namespace esphome::logger { + +__thread bool non_main_task_recursion_guard_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +#ifdef USE_ESPHOME_TASK_LOG_BUFFER + +static inline uint32_t total_size_in_32bit_words(uint16_t text_length) { + // Calculate total size in 32-bit words needed (header + text length + null terminator + 3(4 bytes alignment) + return (sizeof(TaskLogBuffer::LogMessage) + text_length + 1 + 3) / sizeof(uint32_t); +} + +static inline uint32_t get_wlen(const mpsc_pbuf_generic *item) { + return total_size_in_32bit_words(reinterpret_cast<const TaskLogBuffer::LogMessage *>(item)->text_length); +} + +TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) { + // alignment to 4 bytes + total_buffer_size = (total_buffer_size + 3) / sizeof(uint32_t); + this->mpsc_config_.buf = new uint32_t[total_buffer_size]; + this->mpsc_config_.size = total_buffer_size; + this->mpsc_config_.flags = MPSC_PBUF_MODE_OVERWRITE; + this->mpsc_config_.get_wlen = get_wlen, + + mpsc_pbuf_init(&this->log_buffer_, &this->mpsc_config_); +} + +TaskLogBuffer::~TaskLogBuffer() { delete[] this->mpsc_config_.buf; } + +bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args) { + // First, calculate the exact length needed using a null buffer (no actual writing) + va_list args_copy; + va_copy(args_copy, args); + int ret = vsnprintf(nullptr, 0, format, args_copy); + va_end(args_copy); + + if (ret <= 0) { + return false; // Formatting error or empty message + } + + // Calculate actual text length (capped to maximum size) + static constexpr size_t MAX_TEXT_SIZE = 255; + size_t text_length = (static_cast<size_t>(ret) > MAX_TEXT_SIZE) ? MAX_TEXT_SIZE : ret; + size_t total_size = total_size_in_32bit_words(text_length); + auto *msg = reinterpret_cast<LogMessage *>(mpsc_pbuf_alloc(&this->log_buffer_, total_size, K_NO_WAIT)); + if (msg == nullptr) { + return false; + } + msg->level = level; + msg->tag = tag; + msg->line = line; + strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1); + msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination + + // Format the message text directly into the acquired memory + // We add 1 to text_length to ensure space for null terminator during formatting + char *text_area = msg->text_data(); + ret = vsnprintf(text_area, text_length + 1, format, args); + + // Handle unexpected formatting error (ret < 0 is encoding error; ret == 0 is valid empty output) + if (ret < 0) { + // this should not happen, vsnprintf was called already once + // fill with '\n' to not call mpsc_pbuf_free from producer + // it will be trimmed anyway + for (size_t i = 0; i < text_length; ++i) { + text_area[i] = '\n'; + } + text_area[text_length] = 0; + // do not return false to free the buffer from main thread + } + + msg->text_length = text_length; + + mpsc_pbuf_commit(&this->log_buffer_, reinterpret_cast<mpsc_pbuf_generic *>(msg)); + return true; +} + +bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) { + if (this->current_token_) { + return false; + } + + this->current_token_ = mpsc_pbuf_claim(&this->log_buffer_); + + if (this->current_token_ == nullptr) { + return false; + } + + // we claimed buffer already, const_cast is safe here + message = const_cast<LogMessage *>(reinterpret_cast<const LogMessage *>(this->current_token_)); + + text_length = message->text_length; + // Remove trailing newlines + while (text_length > 0 && message->text_data()[text_length - 1] == '\n') { + text_length--; + } + + return true; +} + +void TaskLogBuffer::release_message_main_loop() { + if (this->current_token_ == nullptr) { + return; + } + mpsc_pbuf_free(&this->log_buffer_, this->current_token_); + this->current_token_ = nullptr; +} +#endif // USE_ESPHOME_TASK_LOG_BUFFER + +} // namespace esphome::logger + +#endif // USE_ZEPHYR diff --git a/esphome/components/logger/task_log_buffer_zephyr.h b/esphome/components/logger/task_log_buffer_zephyr.h new file mode 100644 index 0000000000..cc2ed1f687 --- /dev/null +++ b/esphome/components/logger/task_log_buffer_zephyr.h @@ -0,0 +1,66 @@ +#pragma once + +#ifdef USE_ZEPHYR + +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" +#include <zephyr/sys/mpsc_pbuf.h> + +namespace esphome::logger { + +// "0x" + 2 hex digits per byte + '\0' +static constexpr size_t MAX_POINTER_REPRESENTATION = 2 + sizeof(void *) * 2 + 1; + +extern __thread bool non_main_task_recursion_guard_; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +#ifdef USE_ESPHOME_TASK_LOG_BUFFER + +class TaskLogBuffer { + public: + // Structure for a log message header (text data follows immediately after) + struct LogMessage { + MPSC_PBUF_HDR; // this is only 2 bits but no more than 30 bits directly after + uint16_t line; // Source code line number + uint8_t level; // Log level (0-7) +#if defined(CONFIG_THREAD_NAME) + char thread_name[CONFIG_THREAD_MAX_NAME_LEN]; // Store thread name directly (only used for non-main threads) +#else + char thread_name[MAX_POINTER_REPRESENTATION]; // Store thread name directly (only used for non-main threads) +#endif + const char *tag; // We store the pointer, assuming tags are static + uint16_t text_length; // Length of the message text (up to ~64KB) + + // Methods for accessing message contents + inline char *text_data() { return reinterpret_cast<char *>(this) + sizeof(LogMessage); } + }; + // Constructor that takes a total buffer size + explicit TaskLogBuffer(size_t total_buffer_size); + ~TaskLogBuffer(); + + // Check if there are messages ready to be processed using an atomic counter for performance + inline bool HOT has_messages() { return mpsc_pbuf_is_pending(&this->log_buffer_); } + + // Get the total buffer size in bytes + inline size_t size() const { return this->mpsc_config_.size * sizeof(uint32_t); } + + // NOT thread-safe - borrow a message from the ring buffer, only call from main loop + bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length); + + // NOT thread-safe - release a message buffer and update the counter, only call from main loop + void release_message_main_loop(); + + // Thread-safe - send a message to the ring buffer from any thread + bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, + const char *format, va_list args); + + protected: + mpsc_pbuf_buffer_config mpsc_config_{}; + mpsc_pbuf_buffer log_buffer_{}; + const mpsc_pbuf_generic *current_token_{}; +}; + +#endif // USE_ESPHOME_TASK_LOG_BUFFER + +} // namespace esphome::logger + +#endif // USE_ZEPHYR diff --git a/esphome/core/defines.h b/esphome/core/defines.h index ee865a7e65..0c888933bf 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -320,6 +320,7 @@ #endif #ifdef USE_NRF52 +#define USE_ESPHOME_TASK_LOG_BUFFER #define USE_NRF52_DFU #define USE_NRF52_REG0_VOUT 5 #define USE_NRF52_UICR_ERASE diff --git a/tests/components/logger/test.nrf52-adafruit.yaml b/tests/components/logger/test.nrf52-adafruit.yaml index 70b485daac..821a136250 100644 --- a/tests/components/logger/test.nrf52-adafruit.yaml +++ b/tests/components/logger/test.nrf52-adafruit.yaml @@ -5,3 +5,4 @@ esphome: logger: level: DEBUG + task_log_buffer_size: 0 From 923445eb5dbaaf87c164c709a2cc2b34473a8a56 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 10:06:44 -0600 Subject: [PATCH 0665/2030] [light] Eliminate redundant clamp in LightCall::validate_() (#13923) --- esphome/components/light/light_call.cpp | 25 ++++++++++--------- esphome/components/light/light_color_values.h | 19 ++++++++------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 3b4e136ba5..0291b2c3c6 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -270,22 +270,23 @@ LightColorValues LightCall::validate_() { if (this->has_state()) v.set_state(this->state_); -#define VALIDATE_AND_APPLY(field, setter, name_str, ...) \ + // clamp_and_log_if_invalid already clamps in-place, so assign directly + // to avoid redundant clamp code from the setter being inlined. +#define VALIDATE_AND_APPLY(field, name_str, ...) \ if (this->has_##field()) { \ clamp_and_log_if_invalid(name, this->field##_, LOG_STR(name_str), ##__VA_ARGS__); \ - v.setter(this->field##_); \ + v.field##_ = this->field##_; \ } - VALIDATE_AND_APPLY(brightness, set_brightness, "Brightness") - VALIDATE_AND_APPLY(color_brightness, set_color_brightness, "Color brightness") - VALIDATE_AND_APPLY(red, set_red, "Red") - VALIDATE_AND_APPLY(green, set_green, "Green") - VALIDATE_AND_APPLY(blue, set_blue, "Blue") - VALIDATE_AND_APPLY(white, set_white, "White") - VALIDATE_AND_APPLY(cold_white, set_cold_white, "Cold white") - VALIDATE_AND_APPLY(warm_white, set_warm_white, "Warm white") - VALIDATE_AND_APPLY(color_temperature, set_color_temperature, "Color temperature", traits.get_min_mireds(), - traits.get_max_mireds()) + VALIDATE_AND_APPLY(brightness, "Brightness") + VALIDATE_AND_APPLY(color_brightness, "Color brightness") + VALIDATE_AND_APPLY(red, "Red") + VALIDATE_AND_APPLY(green, "Green") + VALIDATE_AND_APPLY(blue, "Blue") + VALIDATE_AND_APPLY(white, "White") + VALIDATE_AND_APPLY(cold_white, "Cold white") + VALIDATE_AND_APPLY(warm_white, "Warm white") + VALIDATE_AND_APPLY(color_temperature, "Color temperature", traits.get_min_mireds(), traits.get_max_mireds()) #undef VALIDATE_AND_APPLY diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index 97756b9f26..dc23263312 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -95,15 +95,18 @@ class LightColorValues { */ void normalize_color() { if (this->color_mode_ & ColorCapability::RGB) { - float max_value = fmaxf(this->get_red(), fmaxf(this->get_green(), this->get_blue())); + float max_value = fmaxf(this->red_, fmaxf(this->green_, this->blue_)); + // Assign directly to avoid redundant clamp in set_red/green/blue. + // Values are guaranteed in [0,1]: inputs are already clamped to [0,1], + // and dividing by max_value (the largest) keeps results in [0,1]. if (max_value == 0.0f) { - this->set_red(1.0f); - this->set_green(1.0f); - this->set_blue(1.0f); + this->red_ = 1.0f; + this->green_ = 1.0f; + this->blue_ = 1.0f; } else { - this->set_red(this->get_red() / max_value); - this->set_green(this->get_green() / max_value); - this->set_blue(this->get_blue() / max_value); + this->red_ /= max_value; + this->green_ /= max_value; + this->blue_ /= max_value; } } } @@ -276,6 +279,8 @@ class LightColorValues { /// Set the warm white property of these light color values. In range 0.0 to 1.0. void set_warm_white(float warm_white) { this->warm_white_ = clamp(warm_white, 0.0f, 1.0f); } + friend class LightCall; + protected: float state_; ///< ON / OFF, float for transition float brightness_; From b1f0db9da812cfcf250a0f3c558232e23c2cbc60 Mon Sep 17 00:00:00 2001 From: Djordje Mandic <6750655+DjordjeMandic@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:10:32 +0100 Subject: [PATCH 0666/2030] [bl0942] Update reference values (#12867) --- esphome/components/bl0942/bl0942.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index 37b884e6ca..10b29a72c6 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -59,10 +59,10 @@ namespace bl0942 { // // Which makes BL0952_EREF = BL0942_PREF * 3600000 / 419430.4 -static const float BL0942_PREF = 596; // taken from tasmota -static const float BL0942_UREF = 15873.35944299; // should be 73989/1.218 -static const float BL0942_IREF = 251213.46469622; // 305978/1.218 -static const float BL0942_EREF = 3304.61127328; // Measured +static const float BL0942_PREF = 623.0270705; // calculated using UREF and IREF +static const float BL0942_UREF = 15883.34116; // calculated for (390k x 5 / 510R) voltage divider +static const float BL0942_IREF = 251065.6814; // calculated for 1mR shunt +static const float BL0942_EREF = 5347.484240; // calculated using UREF and IREF struct DataPacket { uint8_t frame_header; @@ -86,11 +86,11 @@ enum LineFrequency : uint8_t { class BL0942 : public PollingComponent, public uart::UARTDevice { public: - void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } - void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; } - void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; } - void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; } - void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; } + void set_voltage_sensor(sensor::Sensor *voltage_sensor) { this->voltage_sensor_ = voltage_sensor; } + void set_current_sensor(sensor::Sensor *current_sensor) { this->current_sensor_ = current_sensor; } + void set_power_sensor(sensor::Sensor *power_sensor) { this->power_sensor_ = power_sensor; } + void set_energy_sensor(sensor::Sensor *energy_sensor) { this->energy_sensor_ = energy_sensor; } + void set_frequency_sensor(sensor::Sensor *frequency_sensor) { this->frequency_sensor_ = frequency_sensor; } void set_line_freq(LineFrequency freq) { this->line_freq_ = freq; } void set_address(uint8_t address) { this->address_ = address; } void set_reset(bool reset) { this->reset_ = reset; } From 930a1861683b0f66f4800cc820e6718c2c818939 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 11:03:27 -0600 Subject: [PATCH 0667/2030] [web_server_idf] Use constant-time comparison for Basic Auth (#13868) --- .../web_server_idf/web_server_idf.cpp | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 0dd1948dcc..2e07fb6e0a 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -352,7 +352,26 @@ bool AsyncWebServerRequest::authenticate(const char *username, const char *passw esp_crypto_base64_encode(reinterpret_cast<uint8_t *>(digest), max_digest_len, &out, reinterpret_cast<const uint8_t *>(user_info), user_info_len); - return strcmp(digest, auth_str + auth_prefix_len) == 0; + // Constant-time comparison to avoid timing side channels. + // No early return on length mismatch — the length difference is folded + // into the accumulator so any mismatch is rejected. + const char *provided = auth_str + auth_prefix_len; + size_t digest_len = out; // length from esp_crypto_base64_encode + // Derive provided_len from the already-sized std::string rather than + // rescanning with strlen (avoids attacker-controlled scan length). + size_t provided_len = auth.value().size() - auth_prefix_len; + // Use full-width XOR so any bit difference in the lengths is preserved + // (uint8_t truncation would miss differences in higher bytes, e.g. + // digest_len vs digest_len + 256). + volatile size_t result = digest_len ^ provided_len; + // Iterate over the expected digest length only — the full-width length + // XOR above already rejects any length mismatch, and bounding the loop + // prevents a long Authorization header from forcing extra work. + for (size_t i = 0; i < digest_len; i++) { + char provided_ch = (i < provided_len) ? provided[i] : 0; + result |= static_cast<uint8_t>(digest[i] ^ provided_ch); + } + return result == 0; } void AsyncWebServerRequest::requestAuthentication(const char *realm) const { From 069c90ec4aeb46fc26a23ad3a7376c20f9a8e44c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 11:34:43 -0600 Subject: [PATCH 0668/2030] [api] Split process_batch_ to reduce stack on single-message hot path (#13907) --- esphome/components/api/api_connection.cpp | 81 +++++++++++++---------- esphome/components/api/api_connection.h | 6 +- 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 34d9744adc..4bc3c9b307 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1921,10 +1921,6 @@ bool APIConnection::schedule_batch_() { } void APIConnection::process_batch_() { - // Ensure MessageInfo remains trivially destructible for our placement new approach - static_assert(std::is_trivially_destructible<MessageInfo>::value, - "MessageInfo must remain trivially destructible with this placement-new approach"); - if (this->deferred_batch_.empty()) { this->flags_.batch_scheduled = false; return; @@ -1949,6 +1945,10 @@ void APIConnection::process_batch_() { for (size_t i = 0; i < num_items; i++) { total_estimated_size += this->deferred_batch_[i].estimated_size; } + // Clamp to MAX_BATCH_PACKET_SIZE — we won't send more than that per batch + if (total_estimated_size > MAX_BATCH_PACKET_SIZE) { + total_estimated_size = MAX_BATCH_PACKET_SIZE; + } this->prepare_first_message_buffer(shared_buf, header_padding, total_estimated_size); @@ -1972,7 +1972,20 @@ void APIConnection::process_batch_() { return; } - size_t messages_to_process = std::min(num_items, MAX_MESSAGES_PER_BATCH); + // Multi-message path — heavy stack frame isolated in separate noinline function + this->process_batch_multi_(shared_buf, num_items, header_padding, footer_size); +} + +// Separated from process_batch_() so the single-message fast path gets a minimal +// stack frame without the MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo) array. +void APIConnection::process_batch_multi_(std::vector<uint8_t> &shared_buf, size_t num_items, uint8_t header_padding, + uint8_t footer_size) { + // Ensure MessageInfo remains trivially destructible for our placement new approach + static_assert(std::is_trivially_destructible<MessageInfo>::value, + "MessageInfo must remain trivially destructible with this placement-new approach"); + + const size_t messages_to_process = std::min(num_items, MAX_MESSAGES_PER_BATCH); + const uint8_t frame_overhead = header_padding + footer_size; // Stack-allocated array for message info alignas(MessageInfo) char message_info_storage[MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo)]; @@ -1999,7 +2012,7 @@ void APIConnection::process_batch_() { // Message was encoded successfully // payload_size is header_padding + actual payload size + footer_size - uint16_t proto_payload_size = payload_size - header_padding - footer_size; + uint16_t proto_payload_size = payload_size - frame_overhead; // Use placement new to construct MessageInfo in pre-allocated stack array // This avoids default-constructing all MAX_MESSAGES_PER_BATCH elements // Explicit destruction is not needed because MessageInfo is trivially destructible, @@ -2015,42 +2028,38 @@ void APIConnection::process_batch_() { current_offset = shared_buf.size() + footer_size; } - if (items_processed == 0) { - this->deferred_batch_.clear(); - return; - } + if (items_processed > 0) { + // Add footer space for the last message (for Noise protocol MAC) + if (footer_size > 0) { + shared_buf.resize(shared_buf.size() + footer_size); + } - // Add footer space for the last message (for Noise protocol MAC) - if (footer_size > 0) { - shared_buf.resize(shared_buf.size() + footer_size); - } - - // Send all collected messages - APIError err = this->helper_->write_protobuf_messages(ProtoWriteBuffer{&shared_buf}, - std::span<const MessageInfo>(message_info, items_processed)); - if (err != APIError::OK && err != APIError::WOULD_BLOCK) { - this->fatal_error_with_log_(LOG_STR("Batch write failed"), err); - } + // Send all collected messages + APIError err = this->helper_->write_protobuf_messages(ProtoWriteBuffer{&shared_buf}, + std::span<const MessageInfo>(message_info, items_processed)); + if (err != APIError::OK && err != APIError::WOULD_BLOCK) { + this->fatal_error_with_log_(LOG_STR("Batch write failed"), err); + } #ifdef HAS_PROTO_MESSAGE_DUMP - // Log messages after send attempt for VV debugging - // It's safe to use the buffer for logging at this point regardless of send result - for (size_t i = 0; i < items_processed; i++) { - const auto &item = this->deferred_batch_[i]; - this->log_batch_item_(item); - } + // Log messages after send attempt for VV debugging + // It's safe to use the buffer for logging at this point regardless of send result + for (size_t i = 0; i < items_processed; i++) { + const auto &item = this->deferred_batch_[i]; + this->log_batch_item_(item); + } #endif - // Handle remaining items more efficiently - if (items_processed < this->deferred_batch_.size()) { - // Remove processed items from the beginning - this->deferred_batch_.remove_front(items_processed); - // Reschedule for remaining items - this->schedule_batch_(); - } else { - // All items processed - this->clear_batch_(); + // Partial batch — remove processed items and reschedule + if (items_processed < this->deferred_batch_.size()) { + this->deferred_batch_.remove_front(items_processed); + this->schedule_batch_(); + return; + } } + + // All items processed (or none could be processed) + this->clear_batch_(); } // Dispatch message encoding based on message_type diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index a16d681760..d3d09a01c8 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -548,8 +548,8 @@ class APIConnection final : public APIServerConnectionBase { batch_start_time = 0; } - // Remove processed items from the front - void remove_front(size_t count) { items.erase(items.begin(), items.begin() + count); } + // Remove processed items from the front — noinline to keep memmove out of warm callers + void remove_front(size_t count) __attribute__((noinline)) { items.erase(items.begin(), items.begin() + count); } bool empty() const { return items.empty(); } size_t size() const { return items.size(); } @@ -621,6 +621,8 @@ class APIConnection final : public APIServerConnectionBase { bool schedule_batch_(); void process_batch_(); + void process_batch_multi_(std::vector<uint8_t> &shared_buf, size_t num_items, uint8_t header_padding, + uint8_t footer_size) __attribute__((noinline)); void clear_batch_() { this->deferred_batch_.clear(); this->flags_.batch_scheduled = false; From 1411868a0ba980b6fdb26aadf519dcfe0a3377d1 Mon Sep 17 00:00:00 2001 From: Nate Clark <nate@nateclark.com> Date: Wed, 11 Feb 2026 12:40:27 -0500 Subject: [PATCH 0669/2030] [mqtt.cover] Add option to publish states as JSON payload (#12639) Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> --- esphome/components/cover/__init__.py | 23 ++++++++ esphome/components/mqtt/mqtt_cover.cpp | 77 ++++++++++++++++++++------ esphome/components/mqtt/mqtt_cover.h | 6 ++ esphome/const.py | 1 + esphome/core/defines.h | 1 + tests/components/mqtt/common.yaml | 48 ++++++++++++++++ 6 files changed, 140 insertions(+), 16 deletions(-) diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 41774f3d71..648fe7decf 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_ICON, CONF_ID, CONF_MQTT_ID, + CONF_MQTT_JSON_STATE_PAYLOAD, CONF_ON_IDLE, CONF_ON_OPEN, CONF_POSITION, @@ -119,6 +120,9 @@ _COVER_SCHEMA = ( .extend( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTCoverComponent), + cv.Optional(CONF_MQTT_JSON_STATE_PAYLOAD): cv.All( + cv.requires_component("mqtt"), cv.boolean + ), cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), cv.Optional(CONF_POSITION_COMMAND_TOPIC): cv.All( cv.requires_component("mqtt"), cv.subscribe_topic @@ -148,6 +152,22 @@ _COVER_SCHEMA = ( _COVER_SCHEMA.add_extra(entity_duplicate_validator("cover")) +def _validate_mqtt_state_topics(config): + if config.get(CONF_MQTT_JSON_STATE_PAYLOAD): + if CONF_POSITION_STATE_TOPIC in config: + raise cv.Invalid( + f"'{CONF_POSITION_STATE_TOPIC}' cannot be used with '{CONF_MQTT_JSON_STATE_PAYLOAD}: true'" + ) + if CONF_TILT_STATE_TOPIC in config: + raise cv.Invalid( + f"'{CONF_TILT_STATE_TOPIC}' cannot be used with '{CONF_MQTT_JSON_STATE_PAYLOAD}: true'" + ) + return config + + +_COVER_SCHEMA.add_extra(_validate_mqtt_state_topics) + + def cover_schema( class_: MockObjClass, *, @@ -195,6 +215,9 @@ async def setup_cover_core_(var, config): position_command_topic := config.get(CONF_POSITION_COMMAND_TOPIC) ) is not None: cg.add(mqtt_.set_custom_position_command_topic(position_command_topic)) + if config.get(CONF_MQTT_JSON_STATE_PAYLOAD): + cg.add_define("USE_MQTT_COVER_JSON") + cg.add(mqtt_.set_use_json_format(True)) if (tilt_state_topic := config.get(CONF_TILT_STATE_TOPIC)) is not None: cg.add(mqtt_.set_custom_tilt_state_topic(tilt_state_topic)) if (tilt_command_topic := config.get(CONF_TILT_COMMAND_TOPIC)) is not None: diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index c21af413ed..9752004094 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -67,17 +67,26 @@ void MQTTCoverComponent::dump_config() { auto traits = this->cover_->get_traits(); bool has_command_topic = traits.get_supports_position() || !traits.get_supports_tilt(); LOG_MQTT_COMPONENT(true, has_command_topic); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; +#ifdef USE_MQTT_COVER_JSON + if (this->use_json_format_) { + ESP_LOGCONFIG(TAG, " JSON State Payload: YES"); + } else { +#endif + if (traits.get_supports_position()) { + ESP_LOGCONFIG(TAG, " Position State Topic: '%s'", this->get_position_state_topic_to(topic_buf).c_str()); + } + if (traits.get_supports_tilt()) { + ESP_LOGCONFIG(TAG, " Tilt State Topic: '%s'", this->get_tilt_state_topic_to(topic_buf).c_str()); + } +#ifdef USE_MQTT_COVER_JSON + } +#endif if (traits.get_supports_position()) { - ESP_LOGCONFIG(TAG, - " Position State Topic: '%s'\n" - " Position Command Topic: '%s'", - this->get_position_state_topic().c_str(), this->get_position_command_topic().c_str()); + ESP_LOGCONFIG(TAG, " Position Command Topic: '%s'", this->get_position_command_topic_to(topic_buf).c_str()); } if (traits.get_supports_tilt()) { - ESP_LOGCONFIG(TAG, - " Tilt State Topic: '%s'\n" - " Tilt Command Topic: '%s'", - this->get_tilt_state_topic().c_str(), this->get_tilt_command_topic().c_str()); + ESP_LOGCONFIG(TAG, " Tilt Command Topic: '%s'", this->get_tilt_command_topic_to(topic_buf).c_str()); } } void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { @@ -92,13 +101,33 @@ void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf if (traits.get_is_assumed_state()) { root[MQTT_OPTIMISTIC] = true; } - if (traits.get_supports_position()) { - root[MQTT_POSITION_TOPIC] = this->get_position_state_topic(); - root[MQTT_SET_POSITION_TOPIC] = this->get_position_command_topic(); - } - if (traits.get_supports_tilt()) { - root[MQTT_TILT_STATUS_TOPIC] = this->get_tilt_state_topic(); - root[MQTT_TILT_COMMAND_TOPIC] = this->get_tilt_command_topic(); + char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; +#ifdef USE_MQTT_COVER_JSON + if (this->use_json_format_) { + // JSON mode: all state published to state_topic as JSON, use templates to extract + root[MQTT_VALUE_TEMPLATE] = ESPHOME_F("{{ value_json.state }}"); + if (traits.get_supports_position()) { + root[MQTT_POSITION_TOPIC] = this->get_state_topic_to_(topic_buf); + root[MQTT_POSITION_TEMPLATE] = ESPHOME_F("{{ value_json.position }}"); + root[MQTT_SET_POSITION_TOPIC] = this->get_position_command_topic_to(topic_buf); + } + if (traits.get_supports_tilt()) { + root[MQTT_TILT_STATUS_TOPIC] = this->get_state_topic_to_(topic_buf); + root[MQTT_TILT_STATUS_TEMPLATE] = ESPHOME_F("{{ value_json.tilt }}"); + root[MQTT_TILT_COMMAND_TOPIC] = this->get_tilt_command_topic_to(topic_buf); + } + } else +#endif + { + // Standard mode: separate topics for position and tilt + if (traits.get_supports_position()) { + root[MQTT_POSITION_TOPIC] = this->get_position_state_topic_to(topic_buf); + root[MQTT_SET_POSITION_TOPIC] = this->get_position_command_topic_to(topic_buf); + } + if (traits.get_supports_tilt()) { + root[MQTT_TILT_STATUS_TOPIC] = this->get_tilt_state_topic_to(topic_buf); + root[MQTT_TILT_COMMAND_TOPIC] = this->get_tilt_command_topic_to(topic_buf); + } } if (traits.get_supports_tilt() && !traits.get_supports_position()) { config.command_topic = false; @@ -111,8 +140,24 @@ const EntityBase *MQTTCoverComponent::get_entity() const { return this->cover_; bool MQTTCoverComponent::send_initial_state() { return this->publish_state(); } bool MQTTCoverComponent::publish_state() { auto traits = this->cover_->get_traits(); - bool success = true; char topic_buf[MQTT_DEFAULT_TOPIC_MAX_LEN]; +#ifdef USE_MQTT_COVER_JSON + if (this->use_json_format_) { + return this->publish_json(this->get_state_topic_to_(topic_buf), [this, traits](JsonObject root) { + // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson + root[ESPHOME_F("state")] = cover_state_to_mqtt_str(this->cover_->current_operation, this->cover_->position, + traits.get_supports_position()); + if (traits.get_supports_position()) { + root[ESPHOME_F("position")] = static_cast<int>(roundf(this->cover_->position * 100)); + } + if (traits.get_supports_tilt()) { + root[ESPHOME_F("tilt")] = static_cast<int>(roundf(this->cover_->tilt * 100)); + } + // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) + }); + } +#endif + bool success = true; if (traits.get_supports_position()) { char pos[VALUE_ACCURACY_MAX_LEN]; size_t len = value_accuracy_to_buf(pos, roundf(this->cover_->position * 100), 0); diff --git a/esphome/components/mqtt/mqtt_cover.h b/esphome/components/mqtt/mqtt_cover.h index 13582d14d1..f801af5d12 100644 --- a/esphome/components/mqtt/mqtt_cover.h +++ b/esphome/components/mqtt/mqtt_cover.h @@ -27,12 +27,18 @@ class MQTTCoverComponent : public mqtt::MQTTComponent { bool publish_state(); void dump_config() override; +#ifdef USE_MQTT_COVER_JSON + void set_use_json_format(bool use_json_format) { this->use_json_format_ = use_json_format; } +#endif protected: const char *component_type() const override; const EntityBase *get_entity() const override; cover::Cover *cover_; +#ifdef USE_MQTT_COVER_JSON + bool use_json_format_{false}; +#endif }; } // namespace esphome::mqtt diff --git a/esphome/const.py b/esphome/const.py index 4bf47b8f83..00d8013cc6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -639,6 +639,7 @@ CONF_MOVEMENT_COUNTER = "movement_counter" CONF_MOVING_DISTANCE = "moving_distance" CONF_MQTT = "mqtt" CONF_MQTT_ID = "mqtt_id" +CONF_MQTT_JSON_STATE_PAYLOAD = "mqtt_json_state_payload" CONF_MULTIPLE = "multiple" CONF_MULTIPLEXER = "multiplexer" CONF_MULTIPLY = "multiply" diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 0c888933bf..bfe9d620df 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -145,6 +145,7 @@ #define USE_MD5 #define USE_SHA256 #define USE_MQTT +#define USE_MQTT_COVER_JSON #define USE_NETWORK #define USE_ONLINE_IMAGE_BMP_SUPPORT #define USE_ONLINE_IMAGE_PNG_SUPPORT diff --git a/tests/components/mqtt/common.yaml b/tests/components/mqtt/common.yaml index 4cf2692593..8c58e9b080 100644 --- a/tests/components/mqtt/common.yaml +++ b/tests/components/mqtt/common.yaml @@ -219,6 +219,7 @@ cover: name: Template Cover state_topic: some/topic/cover qos: 2 + mqtt_json_state_payload: true lambda: |- if (id(some_binary_sensor).state) { return COVER_OPEN; @@ -231,6 +232,53 @@ cover: stop_action: - logger.log: stop_action optimistic: true + - platform: template + name: Template Cover with Position and Tilt + state_topic: some/topic/cover_pt + position_state_topic: some/topic/cover_pt/position + position_command_topic: some/topic/cover_pt/position/set + tilt_state_topic: some/topic/cover_pt/tilt + tilt_command_topic: some/topic/cover_pt/tilt/set + qos: 2 + has_position: true + lambda: |- + if (id(some_binary_sensor).state) { + return COVER_OPEN; + } + return COVER_CLOSED; + position_action: + - logger.log: position_action + tilt_action: + - logger.log: tilt_action + open_action: + - logger.log: open_action + close_action: + - logger.log: close_action + stop_action: + - logger.log: stop_action + optimistic: true + - platform: template + name: Template Cover with Position and Tilt JSON + state_topic: some/topic/cover_pt_json + qos: 2 + mqtt_json_state_payload: true + has_position: true + lambda: |- + if (id(some_binary_sensor).state) { + return COVER_OPEN; + } + return COVER_CLOSED; + position_action: + - logger.log: position_action + tilt_action: + - logger.log: tilt_action + open_action: + - logger.log: open_action + close_action: + - logger.log: close_action + stop_action: + - logger.log: stop_action + optimistic: true datetime: - platform: template From 0ec02d48869c782ff38f57b7b2f47f7a77c04aef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 11:41:53 -0600 Subject: [PATCH 0670/2030] [preferences] Replace per-element erase with clear() in sync() (#13934) --- esphome/components/esp32/preferences.cpp | 8 +++----- esphome/components/libretiny/preferences.cpp | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index 7d5af023b4..8d6fdc86f6 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -124,14 +124,11 @@ class ESP32Preferences : public ESPPreferences { return true; ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); - // goal try write all pending saves even if one fails int cached = 0, written = 0, failed = 0; esp_err_t last_err = ESP_OK; uint32_t last_key = 0; - // go through vector from back to front (makes erase easier/more efficient) - for (ssize_t i = s_pending_save.size() - 1; i >= 0; i--) { - const auto &save = s_pending_save[i]; + for (const auto &save : s_pending_save) { char key_str[KEY_BUFFER_SIZE]; snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); ESP_LOGVV(TAG, "Checking if NVS data %s has changed", key_str); @@ -150,8 +147,9 @@ class ESP32Preferences : public ESPPreferences { ESP_LOGV(TAG, "NVS data not changed skipping %" PRIu32 " len=%zu", save.key, save.len); cached++; } - s_pending_save.erase(s_pending_save.begin() + i); } + s_pending_save.clear(); + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, failed); if (failed > 0) { diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 5a60b535da..8549631e46 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -114,14 +114,11 @@ class LibreTinyPreferences : public ESPPreferences { return true; ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); - // goal try write all pending saves even if one fails int cached = 0, written = 0, failed = 0; fdb_err_t last_err = FDB_NO_ERR; uint32_t last_key = 0; - // go through vector from back to front (makes erase easier/more efficient) - for (ssize_t i = s_pending_save.size() - 1; i >= 0; i--) { - const auto &save = s_pending_save[i]; + for (const auto &save : s_pending_save) { char key_str[KEY_BUFFER_SIZE]; snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); ESP_LOGVV(TAG, "Checking if FDB data %s has changed", key_str); @@ -141,8 +138,9 @@ class LibreTinyPreferences : public ESPPreferences { ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.len); cached++; } - s_pending_save.erase(s_pending_save.begin() + i); } + s_pending_save.clear(); + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, failed); if (failed > 0) { From 8d62a6a88a4dc016c836794c6d3e66376feef9cd Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Wed, 11 Feb 2026 18:54:31 +0100 Subject: [PATCH 0671/2030] [openthread] Fix warning on old C89 implicit field zero init (#13935) --- esphome/components/openthread/openthread_esp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index a9aff3cce4..79cd809809 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -104,7 +104,7 @@ void OpenThreadComponent::ot_main() { esp_cli_custom_command_init(); #endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION - otLinkModeConfig link_mode_config = {0}; + otLinkModeConfig link_mode_config{}; #if CONFIG_OPENTHREAD_FTD link_mode_config.mRxOnWhenIdle = true; link_mode_config.mDeviceType = true; From c9c125aa8d5b30295e7fa93a08070077440b929d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 11:54:58 -0600 Subject: [PATCH 0672/2030] [socket] Devirtualize Socket::ready() and implement working ready() for LWIP raw TCP (#13913) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/socket/bsd_sockets_impl.cpp | 29 ++----------------- .../components/socket/lwip_raw_tcp_impl.cpp | 4 +++ .../components/socket/lwip_sockets_impl.cpp | 29 ++----------------- esphome/components/socket/socket.cpp | 4 +++ esphome/components/socket/socket.h | 24 ++++++++++++--- esphome/core/application.cpp | 9 ------ esphome/core/application.h | 16 +++++++++- 7 files changed, 47 insertions(+), 68 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.cpp b/esphome/components/socket/bsd_sockets_impl.cpp index b670b9c068..c96713f376 100644 --- a/esphome/components/socket/bsd_sockets_impl.cpp +++ b/esphome/components/socket/bsd_sockets_impl.cpp @@ -16,19 +16,13 @@ namespace esphome::socket { class BSDSocketImpl final : public Socket { public: - BSDSocketImpl(int fd, bool monitor_loop = false) : fd_(fd) { -#ifdef USE_SOCKET_SELECT_SUPPORT + BSDSocketImpl(int fd, bool monitor_loop = false) { + this->fd_ = fd; // Register new socket with the application for select() if monitoring requested if (monitor_loop && this->fd_ >= 0) { // Only set loop_monitored_ to true if registration succeeds this->loop_monitored_ = App.register_socket_fd(this->fd_); - } else { - this->loop_monitored_ = false; } -#else - // Without select support, ignore monitor_loop parameter - (void) monitor_loop; -#endif } ~BSDSocketImpl() override { if (!this->closed_) { @@ -52,12 +46,10 @@ class BSDSocketImpl final : public Socket { int bind(const struct sockaddr *addr, socklen_t addrlen) override { return ::bind(this->fd_, addr, addrlen); } int close() override { if (!this->closed_) { -#ifdef USE_SOCKET_SELECT_SUPPORT // Unregister from select() before closing if monitored if (this->loop_monitored_) { App.unregister_socket_fd(this->fd_); } -#endif int ret = ::close(this->fd_); this->closed_ = true; return ret; @@ -130,23 +122,6 @@ class BSDSocketImpl final : public Socket { ::fcntl(this->fd_, F_SETFL, fl); return 0; } - - int get_fd() const override { return this->fd_; } - -#ifdef USE_SOCKET_SELECT_SUPPORT - bool ready() const override { - if (!this->loop_monitored_) - return true; - return App.is_socket_ready(this->fd_); - } -#endif - - protected: - int fd_; - bool closed_{false}; -#ifdef USE_SOCKET_SELECT_SUPPORT - bool loop_monitored_{false}; -#endif }; // Helper to create a socket with optional monitoring diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index a9c2eda4e8..aa37386d70 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -452,6 +452,8 @@ class LWIPRawImpl : public Socket { errno = ENOSYS; return -1; } + bool ready() const override { return this->rx_buf_ != nullptr || this->rx_closed_ || this->pcb_ == nullptr; } + int setblocking(bool blocking) final { if (pcb_ == nullptr) { errno = ECONNRESET; @@ -576,6 +578,8 @@ class LWIPRawListenImpl final : public LWIPRawImpl { tcp_err(pcb_, LWIPRawImpl::s_err_fn); // Use base class error handler } + bool ready() const override { return this->accepted_socket_count_ > 0; } + std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override { if (pcb_ == nullptr) { errno = EBADF; diff --git a/esphome/components/socket/lwip_sockets_impl.cpp b/esphome/components/socket/lwip_sockets_impl.cpp index a885f243f3..79d68e085a 100644 --- a/esphome/components/socket/lwip_sockets_impl.cpp +++ b/esphome/components/socket/lwip_sockets_impl.cpp @@ -11,19 +11,13 @@ namespace esphome::socket { class LwIPSocketImpl final : public Socket { public: - LwIPSocketImpl(int fd, bool monitor_loop = false) : fd_(fd) { -#ifdef USE_SOCKET_SELECT_SUPPORT + LwIPSocketImpl(int fd, bool monitor_loop = false) { + this->fd_ = fd; // Register new socket with the application for select() if monitoring requested if (monitor_loop && this->fd_ >= 0) { // Only set loop_monitored_ to true if registration succeeds this->loop_monitored_ = App.register_socket_fd(this->fd_); - } else { - this->loop_monitored_ = false; } -#else - // Without select support, ignore monitor_loop parameter - (void) monitor_loop; -#endif } ~LwIPSocketImpl() override { if (!this->closed_) { @@ -49,12 +43,10 @@ class LwIPSocketImpl final : public Socket { int bind(const struct sockaddr *addr, socklen_t addrlen) override { return lwip_bind(this->fd_, addr, addrlen); } int close() override { if (!this->closed_) { -#ifdef USE_SOCKET_SELECT_SUPPORT // Unregister from select() before closing if monitored if (this->loop_monitored_) { App.unregister_socket_fd(this->fd_); } -#endif int ret = lwip_close(this->fd_); this->closed_ = true; return ret; @@ -97,23 +89,6 @@ class LwIPSocketImpl final : public Socket { lwip_fcntl(this->fd_, F_SETFL, fl); return 0; } - - int get_fd() const override { return this->fd_; } - -#ifdef USE_SOCKET_SELECT_SUPPORT - bool ready() const override { - if (!this->loop_monitored_) - return true; - return App.is_socket_ready(this->fd_); - } -#endif - - protected: - int fd_; - bool closed_{false}; -#ifdef USE_SOCKET_SELECT_SUPPORT - bool loop_monitored_{false}; -#endif }; // Helper to create a socket with optional monitoring diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index fd8725b363..2fcc162ead 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -10,6 +10,10 @@ namespace esphome::socket { Socket::~Socket() {} +#ifdef USE_SOCKET_SELECT_SUPPORT +bool Socket::ready() const { return !this->loop_monitored_ || App.is_socket_ready_(this->fd_); } +#endif + // Platform-specific inet_ntop wrappers #if defined(USE_SOCKET_IMPL_LWIP_TCP) // LWIP raw TCP (ESP8266) uses inet_ntoa_r which takes struct by value diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index e8b0948acd..c0098d689a 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -63,13 +63,29 @@ class Socket { virtual int setblocking(bool blocking) = 0; virtual int loop() { return 0; }; - /// Get the underlying file descriptor (returns -1 if not supported) - virtual int get_fd() const { return -1; } + /// Get the underlying file descriptor (returns -1 if not supported) + /// Non-virtual: only one socket implementation is active per build. +#ifdef USE_SOCKET_SELECT_SUPPORT + int get_fd() const { return this->fd_; } +#else + int get_fd() const { return -1; } +#endif /// Check if socket has data ready to read - /// For loop-monitored sockets, checks with the Application's select() results - /// For non-monitored sockets, always returns true (assumes data may be available) + /// For select()-based sockets: non-virtual, checks Application's select() results + /// For LWIP raw TCP sockets: virtual, checks internal buffer state +#ifdef USE_SOCKET_SELECT_SUPPORT + bool ready() const; +#else virtual bool ready() const { return true; } +#endif + + protected: +#ifdef USE_SOCKET_SELECT_SUPPORT + int fd_{-1}; + bool closed_{false}; + bool loop_monitored_{false}; +#endif }; /// Create a socket of the given domain, type and protocol. diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 7b5435185d..449acc64cf 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -609,15 +609,6 @@ void Application::unregister_socket_fd(int fd) { } } -bool Application::is_socket_ready(int fd) const { - // This function is thread-safe for reading the result of select() - // However, it should only be called after select() has been executed in the main loop - // The read_fds_ is only modified by select() in the main loop - if (fd < 0 || fd >= FD_SETSIZE) - return false; - - return FD_ISSET(fd, &this->read_fds_); -} #endif void Application::yield_with_select_(uint32_t delay_ms) { diff --git a/esphome/core/application.h b/esphome/core/application.h index 8478100a56..30611227a2 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -101,6 +101,10 @@ #include "esphome/components/update/update_entity.h" #endif +namespace esphome::socket { +class Socket; +} // namespace esphome::socket + namespace esphome { // Teardown timeout constant (in milliseconds) @@ -491,7 +495,8 @@ class Application { void unregister_socket_fd(int fd); /// Check if there's data available on a socket without blocking /// This function is thread-safe for reading, but should be called after select() has run - bool is_socket_ready(int fd) const; + /// The read_fds_ is only modified by select() in the main loop + bool is_socket_ready(int fd) const { return fd >= 0 && this->is_socket_ready_(fd); } #ifdef USE_WAKE_LOOP_THREADSAFE /// Wake the main event loop from a FreeRTOS task @@ -503,6 +508,15 @@ class Application { protected: friend Component; + friend class socket::Socket; + +#ifdef USE_SOCKET_SELECT_SUPPORT + /// Fast path for Socket::ready() via friendship - skips negative fd check. + /// Safe because: fd was validated in register_socket_fd() at registration time, + /// and Socket::ready() only calls this when loop_monitored_ is true (registration succeeded). + /// FD_ISSET may include its own upper bounds check depending on platform. + bool is_socket_ready_(int fd) const { return FD_ISSET(fd, &this->read_fds_); } +#endif void register_component_(Component *comp); From 483b7693e1c79d974de4f22b126bc0f918004569 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 13:57:08 -0600 Subject: [PATCH 0673/2030] [api] Fix debug asserts in production code, encode_bool bug, and reduce flash overhead (#13936) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../api/api_frame_helper_plaintext.cpp | 5 +- esphome/components/api/proto.h | 95 +++++++------------ esphome/core/defines.h | 1 + tests/integration/conftest.py | 1 + 4 files changed, 40 insertions(+), 62 deletions(-) diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index ed3cc8934e..5069dbf68b 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -295,9 +295,8 @@ APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffe buf_start[header_offset] = 0x00; // indicator // Encode varints directly into buffer - ProtoVarInt(msg.payload_size).encode_to_buffer_unchecked(buf_start + header_offset + 1, size_varint_len); - ProtoVarInt(msg.message_type) - .encode_to_buffer_unchecked(buf_start + header_offset + 1 + size_varint_len, type_varint_len); + encode_varint_to_buffer(msg.payload_size, buf_start + header_offset + 1); + encode_varint_to_buffer(msg.message_type, buf_start + header_offset + 1 + size_varint_len); // Add iovec for this message (header + payload) size_t msg_len = static_cast<size_t>(total_header_len + msg.payload_size); diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 41ea0043f9..8ac79633cf 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -57,6 +57,16 @@ inline uint16_t count_packed_varints(const uint8_t *data, size_t len) { return count; } +/// Encode a varint directly into a pre-allocated buffer. +/// Caller must ensure buffer has space (use ProtoSize::varint() to calculate). +inline void encode_varint_to_buffer(uint32_t val, uint8_t *buffer) { + while (val > 0x7F) { + *buffer++ = static_cast<uint8_t>(val | 0x80); + val >>= 7; + } + *buffer = static_cast<uint8_t>(val); +} + /* * StringRef Ownership Model for API Protocol Messages * =================================================== @@ -93,17 +103,17 @@ class ProtoVarInt { ProtoVarInt() : value_(0) {} explicit ProtoVarInt(uint64_t value) : value_(value) {} + /// Parse a varint from buffer. consumed must be a valid pointer (not null). static optional<ProtoVarInt> parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed) { - if (len == 0) { - if (consumed != nullptr) - *consumed = 0; +#ifdef ESPHOME_DEBUG_API + assert(consumed != nullptr); +#endif + if (len == 0) return {}; - } // Most common case: single-byte varint (values 0-127) if ((buffer[0] & 0x80) == 0) { - if (consumed != nullptr) - *consumed = 1; + *consumed = 1; return ProtoVarInt(buffer[0]); } @@ -122,14 +132,11 @@ class ProtoVarInt { result |= uint64_t(val & 0x7F) << uint64_t(bitpos); bitpos += 7; if ((val & 0x80) == 0) { - if (consumed != nullptr) - *consumed = i + 1; + *consumed = i + 1; return ProtoVarInt(result); } } - if (consumed != nullptr) - *consumed = 0; return {}; // Incomplete or invalid varint } @@ -153,50 +160,6 @@ class ProtoVarInt { // with ZigZag encoding return decode_zigzag64(this->value_); } - /** - * Encode the varint value to a pre-allocated buffer without bounds checking. - * - * @param buffer The pre-allocated buffer to write the encoded varint to - * @param len The size of the buffer in bytes - * - * @note The caller is responsible for ensuring the buffer is large enough - * to hold the encoded value. Use ProtoSize::varint() to calculate - * the exact size needed before calling this method. - * @note No bounds checking is performed for performance reasons. - */ - void encode_to_buffer_unchecked(uint8_t *buffer, size_t len) { - uint64_t val = this->value_; - if (val <= 0x7F) { - buffer[0] = val; - return; - } - size_t i = 0; - while (val && i < len) { - uint8_t temp = val & 0x7F; - val >>= 7; - if (val) { - buffer[i++] = temp | 0x80; - } else { - buffer[i++] = temp; - } - } - } - void encode(std::vector<uint8_t> &out) { - uint64_t val = this->value_; - if (val <= 0x7F) { - out.push_back(val); - return; - } - while (val) { - uint8_t temp = val & 0x7F; - val >>= 7; - if (val) { - out.push_back(temp | 0x80); - } else { - out.push_back(temp); - } - } - } protected: uint64_t value_; @@ -256,8 +219,20 @@ class ProtoWriteBuffer { public: ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer) {} void write(uint8_t value) { this->buffer_->push_back(value); } - void encode_varint_raw(ProtoVarInt value) { value.encode(*this->buffer_); } - void encode_varint_raw(uint32_t value) { this->encode_varint_raw(ProtoVarInt(value)); } + void encode_varint_raw(uint32_t value) { + while (value > 0x7F) { + this->buffer_->push_back(static_cast<uint8_t>(value | 0x80)); + value >>= 7; + } + this->buffer_->push_back(static_cast<uint8_t>(value)); + } + void encode_varint_raw_64(uint64_t value) { + while (value > 0x7F) { + this->buffer_->push_back(static_cast<uint8_t>(value | 0x80)); + value >>= 7; + } + this->buffer_->push_back(static_cast<uint8_t>(value)); + } /** * Encode a field key (tag/wire type combination). * @@ -307,13 +282,13 @@ class ProtoWriteBuffer { if (value == 0 && !force) return; this->encode_field_raw(field_id, 0); // type 0: Varint - uint64 - this->encode_varint_raw(ProtoVarInt(value)); + this->encode_varint_raw_64(value); } void encode_bool(uint32_t field_id, bool value, bool force = false) { if (!value && !force) return; this->encode_field_raw(field_id, 0); // type 0: Varint - bool - this->write(0x01); + this->buffer_->push_back(value ? 0x01 : 0x00); } void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { if (value == 0 && !force) @@ -938,13 +913,15 @@ inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessa this->buffer_->resize(this->buffer_->size() + varint_length_bytes); // Write the length varint directly - ProtoVarInt(msg_length_bytes).encode_to_buffer_unchecked(this->buffer_->data() + begin, varint_length_bytes); + encode_varint_to_buffer(msg_length_bytes, this->buffer_->data() + begin); // Now encode the message content - it will append to the buffer value.encode(*this); +#ifdef ESPHOME_DEBUG_API // Verify that the encoded size matches what we calculated assert(this->buffer_->size() == begin + varint_length_bytes + msg_length_bytes); +#endif } // Implementation of decode_to_message - must be after ProtoDecodableMessage is defined diff --git a/esphome/core/defines.h b/esphome/core/defines.h index bfe9d620df..7e6df31ea2 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -14,6 +14,7 @@ #define ESPHOME_PROJECT_VERSION_30 "v2" #define ESPHOME_VARIANT "ESP32" #define ESPHOME_DEBUG_SCHEDULER +#define ESPHOME_DEBUG_API // Default threading model for static analysis (ESP32 is multi-threaded with atomics) #define ESPHOME_THREAD_MULTI_ATOMICS diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 50e8d4122b..36df1bc83e 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -197,6 +197,7 @@ async def yaml_config(request: pytest.FixtureRequest, unused_tcp_port: int) -> s " platformio_options:\n" " build_flags:\n" ' - "-DDEBUG" # Enable assert() statements\n' + ' - "-DESPHOME_DEBUG_API" # Enable API protocol asserts\n' ' - "-g" # Add debug symbols', ) From 7287a43f2a30d0477b9d78064aca0d9331bdb844 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Feb 2026 15:12:05 -0600 Subject: [PATCH 0674/2030] Bump docker/build-push-action from 6.18.0 to 6.19.1 in /.github/actions/build-image (#13937) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 9c7f051e05..494304eced 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -47,7 +47,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false @@ -73,7 +73,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false From 374cbf4452e01053fe0bd7a0cf666f11f712e2f7 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Wed, 11 Feb 2026 22:21:10 +0100 Subject: [PATCH 0675/2030] [nrf52,zigbee] count sleep time of zigbee thread (#13933) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/zigbee/zigbee_zephyr.cpp | 15 ++++++++++++--- esphome/components/zigbee/zigbee_zephyr.h | 2 ++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index 65639de61b..c103363b4a 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -61,11 +61,19 @@ void ZigbeeComponent::zboss_signal_handler_esphome(zb_bufid_t bufid) { break; } + auto before = millis(); auto err = zigbee_default_signal_handler(bufid); if (err != RET_OK) { ESP_LOGE(TAG, "Zigbee_default_signal_handler ERROR %u [%s]", err, zb_error_to_string_get(err)); } + if (sig == ZB_COMMON_SIGNAL_CAN_SLEEP) { + this->sleep_remainder_ += millis() - before; + uint32_t seconds = this->sleep_remainder_ / 1000; + this->sleep_remainder_ -= seconds * 1000; + this->sleep_time_ += seconds; + } + switch (sig) { case ZB_BDB_SIGNAL_STEERING: ESP_LOGD(TAG, "ZB_BDB_SIGNAL_STEERING, status: %d", status); @@ -213,6 +221,7 @@ void ZigbeeComponent::dump_config() { "Zigbee\n" " Wipe on boot: %s\n" " Device is joined to the network: %s\n" + " Sleep time: %us\n" " Current channel: %d\n" " Current page: %d\n" " Sleep threshold: %ums\n" @@ -221,9 +230,9 @@ void ZigbeeComponent::dump_config() { " Short addr: 0x%04X\n" " Long pan id: 0x%s\n" " Short pan id: 0x%04X", - get_wipe_on_boot(), YESNO(zb_zdo_joined()), zb_get_current_channel(), zb_get_current_page(), - zb_get_sleep_threshold(), role(), ieee_addr_buf, zb_get_short_address(), extended_pan_id_buf, - zb_get_pan_id()); + get_wipe_on_boot(), YESNO(zb_zdo_joined()), this->sleep_time_, zb_get_current_channel(), + zb_get_current_page(), zb_get_sleep_threshold(), role(), ieee_addr_buf, zb_get_short_address(), + extended_pan_id_buf, zb_get_pan_id()); dump_reporting_(); } diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index bd4b092ad5..dcc2b40a16 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -92,6 +92,8 @@ class ZigbeeComponent : public Component { CallbackManager<void()> join_cb_; Trigger<> join_trigger_; bool force_report_{false}; + uint32_t sleep_time_{}; + uint32_t sleep_remainder_{}; }; class ZigbeeEntity { From e12ed08487a310860ba9ea39b7b75b99cb69ceca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 15:24:24 -0600 Subject: [PATCH 0676/2030] [wifi] Add CompactString to reduce WiFi scan heap fragmentation (#13472) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../esp32_improv/esp32_improv_component.cpp | 4 +- .../improv_serial/improv_serial_component.cpp | 20 ++- esphome/components/wifi/wifi_component.cpp | 144 +++++++++++++----- esphome/components/wifi/wifi_component.h | 76 ++++++++- .../wifi/wifi_component_esp8266.cpp | 26 ++-- .../wifi/wifi_component_esp_idf.cpp | 25 ++- .../wifi/wifi_component_libretiny.cpp | 8 +- .../components/wifi/wifi_component_pico_w.cpp | 9 +- .../wifi_info/wifi_info_text_sensor.cpp | 2 +- 9 files changed, 225 insertions(+), 89 deletions(-) diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 1a19472c87..83bc842a3d 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -338,8 +338,8 @@ void ESP32ImprovComponent::process_incoming_data_() { return; } wifi::WiFiAP sta{}; - sta.set_ssid(command.ssid); - sta.set_password(command.password); + sta.set_ssid(command.ssid.c_str()); + sta.set_password(command.password.c_str()); this->connecting_sta_ = sta; wifi::global_wifi_component->set_sta(sta); diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index b4d9943955..edceb9a3b1 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -235,8 +235,8 @@ bool ImprovSerialComponent::parse_improv_payload_(improv::ImprovCommand &command switch (command.command) { case improv::WIFI_SETTINGS: { wifi::WiFiAP sta{}; - sta.set_ssid(command.ssid); - sta.set_password(command.password); + sta.set_ssid(command.ssid.c_str()); + sta.set_password(command.password.c_str()); this->connecting_sta_ = sta; wifi::global_wifi_component->set_sta(sta); @@ -267,16 +267,26 @@ bool ImprovSerialComponent::parse_improv_payload_(improv::ImprovCommand &command for (auto &scan : results) { if (scan.get_is_hidden()) continue; - const std::string &ssid = scan.get_ssid(); - if (std::find(networks.begin(), networks.end(), ssid) != networks.end()) + const char *ssid_cstr = scan.get_ssid().c_str(); + // Check if we've already sent this SSID + bool duplicate = false; + for (const auto &seen : networks) { + if (strcmp(seen.c_str(), ssid_cstr) == 0) { + duplicate = true; + break; + } + } + if (duplicate) continue; + // Only allocate std::string after confirming it's not a duplicate + std::string ssid(ssid_cstr); // Send each ssid separately to avoid overflowing the buffer char rssi_buf[5]; // int8_t: -128 to 127, max 4 chars + null *int8_to_str(rssi_buf, scan.get_rssi()) = '\0'; std::vector<uint8_t> data = improv::build_rpc_response(improv::GET_WIFI_NETWORKS, {ssid, rssi_buf, YESNO(scan.get_with_auth())}, false); this->send_response_(data); - networks.push_back(ssid); + networks.push_back(std::move(ssid)); } // Send empty response to signify the end of the list. std::vector<uint8_t> data = diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index e350f990af..61d05d7635 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -20,6 +20,7 @@ #endif #include <algorithm> +#include <new> #include <utility> #include "lwip/dns.h" #include "lwip/err.h" @@ -47,6 +48,69 @@ namespace esphome::wifi { static const char *const TAG = "wifi"; +// CompactString implementation +CompactString::CompactString(const char *str, size_t len) { + if (len > MAX_LENGTH) { + len = MAX_LENGTH; // Clamp to max valid length + } + + this->length_ = len; + if (len <= INLINE_CAPACITY) { + // Store inline with null terminator + this->is_heap_ = 0; + if (len > 0) { + std::memcpy(this->storage_, str, len); + } + this->storage_[len] = '\0'; + } else { + // Heap allocate with null terminator + this->is_heap_ = 1; + char *heap_data = new char[len + 1]; // NOLINT(cppcoreguidelines-owning-memory) + std::memcpy(heap_data, str, len); + heap_data[len] = '\0'; + this->set_heap_ptr_(heap_data); + } +} + +CompactString::CompactString(const CompactString &other) : CompactString(other.data(), other.size()) {} + +CompactString &CompactString::operator=(const CompactString &other) { + if (this != &other) { + this->~CompactString(); + new (this) CompactString(other); + } + return *this; +} + +CompactString::CompactString(CompactString &&other) noexcept : length_(other.length_), is_heap_(other.is_heap_) { + // Copy full storage (includes null terminator for inline, or pointer for heap) + std::memcpy(this->storage_, other.storage_, INLINE_CAPACITY + 1); + other.length_ = 0; + other.is_heap_ = 0; + other.storage_[0] = '\0'; +} + +CompactString &CompactString::operator=(CompactString &&other) noexcept { + if (this != &other) { + this->~CompactString(); + new (this) CompactString(std::move(other)); + } + return *this; +} + +CompactString::~CompactString() { + if (this->is_heap_) { + delete[] this->get_heap_ptr_(); // NOLINT(cppcoreguidelines-owning-memory) + } +} + +bool CompactString::operator==(const CompactString &other) const { + return this->size() == other.size() && std::memcmp(this->data(), other.data(), this->size()) == 0; +} +bool CompactString::operator==(const StringRef &other) const { + return this->size() == other.size() && std::memcmp(this->data(), other.c_str(), this->size()) == 0; +} + /// WiFi Retry Logic - Priority-Based BSSID Selection /// /// The WiFi component uses a state machine with priority degradation to handle connection failures @@ -349,18 +413,18 @@ bool WiFiComponent::needs_scan_results_() const { return this->scan_result_.empty() || !this->scan_result_[0].get_matches(); } -bool WiFiComponent::ssid_was_seen_in_scan_(const std::string &ssid) const { +bool WiFiComponent::ssid_was_seen_in_scan_(const CompactString &ssid) const { // Check if this SSID is configured as hidden // If explicitly marked hidden, we should always try hidden mode regardless of scan results for (const auto &conf : this->sta_) { - if (conf.get_ssid() == ssid && conf.get_hidden()) { + if (conf.ssid_ == ssid && conf.get_hidden()) { return false; // Treat as not seen - force hidden mode attempt } } // Otherwise, check if we saw it in scan results for (const auto &scan : this->scan_result_) { - if (scan.get_ssid() == ssid) { + if (scan.ssid_ == ssid) { return true; } } @@ -409,14 +473,14 @@ bool WiFiComponent::matches_configured_network_(const char *ssid, const uint8_t continue; } // For BSSID-only configs (empty SSID), match by BSSID - if (sta.get_ssid().empty()) { + if (sta.ssid_.empty()) { if (sta.has_bssid() && std::memcmp(sta.get_bssid().data(), bssid, 6) == 0) { return true; } continue; } // Match by SSID - if (sta.get_ssid() == ssid) { + if (sta.ssid_ == ssid) { return true; } } @@ -465,18 +529,18 @@ int8_t WiFiComponent::find_next_hidden_sta_(int8_t start_index) { if (!include_explicit_hidden && sta.get_hidden()) { int8_t first_non_hidden_idx = this->find_first_non_hidden_index_(); if (first_non_hidden_idx < 0 || static_cast<int8_t>(i) < first_non_hidden_idx) { - ESP_LOGD(TAG, "Skipping " LOG_SECRET("'%s'") " (explicit hidden, already tried)", sta.get_ssid().c_str()); + ESP_LOGD(TAG, "Skipping " LOG_SECRET("'%s'") " (explicit hidden, already tried)", sta.ssid_.c_str()); continue; } } // In BLIND_RETRY mode, treat all networks as candidates // In SCAN_BASED mode, only retry networks that weren't seen in the scan - if (this->retry_hidden_mode_ == RetryHiddenMode::BLIND_RETRY || !this->ssid_was_seen_in_scan_(sta.get_ssid())) { - ESP_LOGD(TAG, "Hidden candidate " LOG_SECRET("'%s'") " at index %d", sta.get_ssid().c_str(), static_cast<int>(i)); + if (this->retry_hidden_mode_ == RetryHiddenMode::BLIND_RETRY || !this->ssid_was_seen_in_scan_(sta.ssid_)) { + ESP_LOGD(TAG, "Hidden candidate " LOG_SECRET("'%s'") " at index %d", sta.ssid_.c_str(), static_cast<int>(i)); return static_cast<int8_t>(i); } - ESP_LOGD(TAG, "Skipping hidden retry for visible network " LOG_SECRET("'%s'"), sta.get_ssid().c_str()); + ESP_LOGD(TAG, "Skipping hidden retry for visible network " LOG_SECRET("'%s'"), sta.ssid_.c_str()); } // No hidden SSIDs found return -1; @@ -593,11 +657,11 @@ void WiFiComponent::start() { // Fast connect optimization: only use when we have saved BSSID+channel data // Without saved data, try first configured network or use normal flow if (loaded_fast_connect) { - ESP_LOGI(TAG, "Starting fast_connect (saved) " LOG_SECRET("'%s'"), params.get_ssid().c_str()); + ESP_LOGI(TAG, "Starting fast_connect (saved) " LOG_SECRET("'%s'"), params.ssid_.c_str()); this->start_connecting(params); } else if (!this->sta_.empty() && !this->sta_[0].get_hidden()) { // No saved data, but have configured networks - try first non-hidden network - ESP_LOGI(TAG, "Starting fast_connect (config) " LOG_SECRET("'%s'"), this->sta_[0].get_ssid().c_str()); + ESP_LOGI(TAG, "Starting fast_connect (config) " LOG_SECRET("'%s'"), this->sta_[0].ssid_.c_str()); this->selected_sta_index_ = 0; params = this->build_params_for_current_phase_(); this->start_connecting(params); @@ -827,7 +891,7 @@ void WiFiComponent::setup_ap_config_() { if (this->ap_setup_) return; - if (this->ap_.get_ssid().empty()) { + if (this->ap_.ssid_.empty()) { // Build AP SSID from app name without heap allocation // WiFi SSID max is 32 bytes, with MAC suffix we keep first 25 + last 7 static constexpr size_t AP_SSID_MAX_LEN = 32; @@ -863,7 +927,7 @@ void WiFiComponent::setup_ap_config_() { " AP SSID: '%s'\n" " AP Password: '%s'\n" " IP Address: %s", - this->ap_.get_ssid().c_str(), this->ap_.get_password().c_str(), this->wifi_soft_ap_ip().str_to(ip_buf)); + this->ap_.ssid_.c_str(), this->ap_.password_.c_str(), this->wifi_soft_ap_ip().str_to(ip_buf)); #ifdef USE_WIFI_MANUAL_IP auto manual_ip = this->ap_.get_manual_ip(); @@ -960,9 +1024,12 @@ WiFiAP WiFiComponent::get_sta() const { return config ? *config : WiFiAP{}; } void WiFiComponent::save_wifi_sta(const std::string &ssid, const std::string &password) { + this->save_wifi_sta(ssid.c_str(), password.c_str()); +} +void WiFiComponent::save_wifi_sta(const char *ssid, const char *password) { SavedWifiSettings save{}; // zero-initialized - all bytes set to \0, guaranteeing null termination - strncpy(save.ssid, ssid.c_str(), sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0 - strncpy(save.password, password.c_str(), sizeof(save.password) - 1); // max 64 chars, byte 64 remains \0 + strncpy(save.ssid, ssid, sizeof(save.ssid) - 1); // max 32 chars, byte 32 remains \0 + strncpy(save.password, password, sizeof(save.password) - 1); // max 64 chars, byte 64 remains \0 this->pref_.save(&save); // ensure it's written immediately global_preferences->sync(); @@ -996,14 +1063,14 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { ESP_LOGI(TAG, "Connecting to " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") " (priority %d, attempt %u/%u in phase %s)...", - ap.get_ssid().c_str(), ap.has_bssid() ? bssid_s : LOG_STR_LITERAL("any"), priority, this->num_retried_ + 1, + ap.ssid_.c_str(), ap.has_bssid() ? bssid_s : LOG_STR_LITERAL("any"), priority, this->num_retried_ + 1, get_max_retries_for_phase(this->retry_phase_), LOG_STR_ARG(retry_phase_to_log_string(this->retry_phase_))); #ifdef ESPHOME_LOG_HAS_VERBOSE ESP_LOGV(TAG, "Connection Params:\n" " SSID: '%s'", - ap.get_ssid().c_str()); + ap.ssid_.c_str()); if (ap.has_bssid()) { ESP_LOGV(TAG, " BSSID: %s", bssid_s); } else { @@ -1036,7 +1103,7 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { client_key_present ? "present" : "not present"); } else { #endif - ESP_LOGV(TAG, " Password: " LOG_SECRET("'%s'"), ap.get_password().c_str()); + ESP_LOGV(TAG, " Password: " LOG_SECRET("'%s'"), ap.password_.c_str()); #ifdef USE_WIFI_WPA2_EAP } #endif @@ -1411,7 +1478,7 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { if (const WiFiAP *config = this->get_selected_sta_(); this->retry_phase_ == WiFiRetryPhase::RETRY_HIDDEN && config && !config->get_hidden() && this->scan_result_.empty()) { - ESP_LOGW(TAG, LOG_SECRET("'%s'") " should be marked hidden", config->get_ssid().c_str()); + ESP_LOGW(TAG, LOG_SECRET("'%s'") " should be marked hidden", config->ssid_.c_str()); } // Reset to initial phase on successful connection (don't log transition, just reset state) this->retry_phase_ = WiFiRetryPhase::INITIAL_CONNECT; @@ -1825,11 +1892,11 @@ void WiFiComponent::log_and_adjust_priority_for_failed_connect_() { } // Get SSID for logging (use pointer to avoid copy) - const std::string *ssid = nullptr; + const char *ssid = nullptr; if (this->retry_phase_ == WiFiRetryPhase::SCAN_CONNECTING && !this->scan_result_.empty()) { - ssid = &this->scan_result_[0].get_ssid(); + ssid = this->scan_result_[0].ssid_.c_str(); } else if (const WiFiAP *config = this->get_selected_sta_()) { - ssid = &config->get_ssid(); + ssid = config->ssid_.c_str(); } // Only decrease priority on the last attempt for this phase @@ -1849,8 +1916,8 @@ void WiFiComponent::log_and_adjust_priority_for_failed_connect_() { } char bssid_s[18]; format_mac_addr_upper(failed_bssid.value().data(), bssid_s); - ESP_LOGD(TAG, "Failed " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") ", priority %d → %d", - ssid != nullptr ? ssid->c_str() : "", bssid_s, old_priority, new_priority); + ESP_LOGD(TAG, "Failed " LOG_SECRET("'%s'") " " LOG_SECRET("(%s)") ", priority %d → %d", ssid != nullptr ? ssid : "", + bssid_s, old_priority, new_priority); // After adjusting priority, check if all priorities are now at minimum // If so, clear the vector to save memory and reset for fresh start @@ -2098,10 +2165,14 @@ void WiFiComponent::save_fast_connect_settings_() { } #endif -void WiFiAP::set_ssid(const std::string &ssid) { this->ssid_ = ssid; } +void WiFiAP::set_ssid(const std::string &ssid) { this->ssid_ = CompactString(ssid.c_str(), ssid.size()); } +void WiFiAP::set_ssid(const char *ssid) { this->ssid_ = CompactString(ssid, strlen(ssid)); } void WiFiAP::set_bssid(const bssid_t &bssid) { this->bssid_ = bssid; } void WiFiAP::clear_bssid() { this->bssid_ = {}; } -void WiFiAP::set_password(const std::string &password) { this->password_ = password; } +void WiFiAP::set_password(const std::string &password) { + this->password_ = CompactString(password.c_str(), password.size()); +} +void WiFiAP::set_password(const char *password) { this->password_ = CompactString(password, strlen(password)); } #ifdef USE_WIFI_WPA2_EAP void WiFiAP::set_eap(optional<EAPAuth> eap_auth) { this->eap_ = std::move(eap_auth); } #endif @@ -2111,10 +2182,8 @@ void WiFiAP::clear_channel() { this->channel_ = 0; } void WiFiAP::set_manual_ip(optional<ManualIP> manual_ip) { this->manual_ip_ = manual_ip; } #endif void WiFiAP::set_hidden(bool hidden) { this->hidden_ = hidden; } -const std::string &WiFiAP::get_ssid() const { return this->ssid_; } const bssid_t &WiFiAP::get_bssid() const { return this->bssid_; } bool WiFiAP::has_bssid() const { return this->bssid_ != bssid_t{}; } -const std::string &WiFiAP::get_password() const { return this->password_; } #ifdef USE_WIFI_WPA2_EAP const optional<EAPAuth> &WiFiAP::get_eap() const { return this->eap_; } #endif @@ -2125,12 +2194,12 @@ const optional<ManualIP> &WiFiAP::get_manual_ip() const { return this->manual_ip #endif bool WiFiAP::get_hidden() const { return this->hidden_; } -WiFiScanResult::WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, - bool is_hidden) +WiFiScanResult::WiFiScanResult(const bssid_t &bssid, const char *ssid, size_t ssid_len, uint8_t channel, int8_t rssi, + bool with_auth, bool is_hidden) : bssid_(bssid), channel_(channel), rssi_(rssi), - ssid_(std::move(ssid)), + ssid_(ssid, ssid_len), with_auth_(with_auth), is_hidden_(is_hidden) {} bool WiFiScanResult::matches(const WiFiAP &config) const { @@ -2139,9 +2208,9 @@ bool WiFiScanResult::matches(const WiFiAP &config) const { // don't match SSID if (!this->is_hidden_) return false; - } else if (!config.get_ssid().empty()) { + } else if (!config.ssid_.empty()) { // check if SSID matches - if (config.get_ssid() != this->ssid_) + if (this->ssid_ != config.ssid_) return false; } else { // network is configured without SSID - match other settings @@ -2152,15 +2221,15 @@ bool WiFiScanResult::matches(const WiFiAP &config) const { #ifdef USE_WIFI_WPA2_EAP // BSSID requires auth but no PSK or EAP credentials given - if (this->with_auth_ && (config.get_password().empty() && !config.get_eap().has_value())) + if (this->with_auth_ && (config.password_.empty() && !config.get_eap().has_value())) return false; // BSSID does not require auth, but PSK or EAP credentials given - if (!this->with_auth_ && (!config.get_password().empty() || config.get_eap().has_value())) + if (!this->with_auth_ && (!config.password_.empty() || config.get_eap().has_value())) return false; #else // If PSK given, only match for networks with auth (and vice versa) - if (config.get_password().empty() == this->with_auth_) + if (config.password_.empty() == this->with_auth_) return false; #endif @@ -2173,7 +2242,6 @@ bool WiFiScanResult::matches(const WiFiAP &config) const { bool WiFiScanResult::get_matches() const { return this->matches_; } void WiFiScanResult::set_matches(bool matches) { this->matches_ = matches; } const bssid_t &WiFiScanResult::get_bssid() const { return this->bssid_; } -const std::string &WiFiScanResult::get_ssid() const { return this->ssid_; } uint8_t WiFiScanResult::get_channel() const { return this->channel_; } int8_t WiFiScanResult::get_rssi() const { return this->rssi_; } bool WiFiScanResult::get_with_auth() const { return this->with_auth_; } @@ -2284,7 +2352,7 @@ void WiFiComponent::process_roaming_scan_() { for (const auto &result : this->scan_result_) { // Must be same SSID, different BSSID - if (current_ssid != result.get_ssid() || result.get_bssid() == current_bssid) + if (result.ssid_ != current_ssid || result.get_bssid() == current_bssid) continue; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 58f19c184a..ac28a1bc81 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -172,12 +172,67 @@ template<typename T> using wifi_scan_vector_t = std::vector<T>; template<typename T> using wifi_scan_vector_t = FixedVector<T>; #endif +/// 20-byte string: 18 chars inline + null, heap for longer. Always null-terminated. +/// Used internally for WiFi SSID/password storage to reduce heap fragmentation. +class CompactString { + public: + static constexpr uint8_t MAX_LENGTH = 127; + static constexpr uint8_t INLINE_CAPACITY = 18; // 18 chars + null terminator fits in 19 bytes + + CompactString() : length_(0), is_heap_(0) { this->storage_[0] = '\0'; } + CompactString(const char *str, size_t len); + CompactString(const CompactString &other); + CompactString(CompactString &&other) noexcept; + CompactString &operator=(const CompactString &other); + CompactString &operator=(CompactString &&other) noexcept; + ~CompactString(); + + const char *data() const { return this->is_heap_ ? this->get_heap_ptr_() : this->storage_; } + const char *c_str() const { return this->data(); } // Always null-terminated + size_t size() const { return this->length_; } + bool empty() const { return this->length_ == 0; } + + /// Return a StringRef view of this string (zero-copy) + StringRef ref() const { return StringRef(this->data(), this->size()); } + + bool operator==(const CompactString &other) const; + bool operator!=(const CompactString &other) const { return !(*this == other); } + bool operator==(const StringRef &other) const; + bool operator!=(const StringRef &other) const { return !(*this == other); } + bool operator==(const char *other) const { return *this == StringRef(other); } + bool operator!=(const char *other) const { return !(*this == other); } + + protected: + char *get_heap_ptr_() const { + char *ptr; + std::memcpy(&ptr, this->storage_, sizeof(ptr)); + return ptr; + } + void set_heap_ptr_(char *ptr) { std::memcpy(this->storage_, &ptr, sizeof(ptr)); } + + // Storage for string data. When is_heap_=0, contains the string directly (null-terminated). + // When is_heap_=1, first sizeof(char*) bytes contain pointer to heap allocation. + char storage_[INLINE_CAPACITY + 1]; // 19 bytes: 18 chars + null terminator + uint8_t length_ : 7; // String length (0-127) + uint8_t is_heap_ : 1; // 1 if using heap pointer, 0 if using inline storage + // Total size: 20 bytes (19 bytes storage + 1 byte bitfields) +}; + +static_assert(sizeof(CompactString) == 20, "CompactString must be exactly 20 bytes"); + class WiFiAP { + friend class WiFiComponent; + friend class WiFiScanResult; + public: void set_ssid(const std::string &ssid); + void set_ssid(const char *ssid); + void set_ssid(StringRef ssid) { this->ssid_ = CompactString(ssid.c_str(), ssid.size()); } void set_bssid(const bssid_t &bssid); void clear_bssid(); void set_password(const std::string &password); + void set_password(const char *password); + void set_password(StringRef password) { this->password_ = CompactString(password.c_str(), password.size()); } #ifdef USE_WIFI_WPA2_EAP void set_eap(optional<EAPAuth> eap_auth); #endif // USE_WIFI_WPA2_EAP @@ -188,10 +243,10 @@ class WiFiAP { void set_manual_ip(optional<ManualIP> manual_ip); #endif void set_hidden(bool hidden); - const std::string &get_ssid() const; + StringRef get_ssid() const { return this->ssid_.ref(); } + StringRef get_password() const { return this->password_.ref(); } const bssid_t &get_bssid() const; bool has_bssid() const; - const std::string &get_password() const; #ifdef USE_WIFI_WPA2_EAP const optional<EAPAuth> &get_eap() const; #endif // USE_WIFI_WPA2_EAP @@ -204,8 +259,8 @@ class WiFiAP { bool get_hidden() const; protected: - std::string ssid_; - std::string password_; + CompactString ssid_; + CompactString password_; #ifdef USE_WIFI_WPA2_EAP optional<EAPAuth> eap_; #endif // USE_WIFI_WPA2_EAP @@ -220,15 +275,18 @@ class WiFiAP { }; class WiFiScanResult { + friend class WiFiComponent; + public: - WiFiScanResult(const bssid_t &bssid, std::string ssid, uint8_t channel, int8_t rssi, bool with_auth, bool is_hidden); + WiFiScanResult(const bssid_t &bssid, const char *ssid, size_t ssid_len, uint8_t channel, int8_t rssi, bool with_auth, + bool is_hidden); bool matches(const WiFiAP &config) const; bool get_matches() const; void set_matches(bool matches); const bssid_t &get_bssid() const; - const std::string &get_ssid() const; + StringRef get_ssid() const { return this->ssid_.ref(); } uint8_t get_channel() const; int8_t get_rssi() const; bool get_with_auth() const; @@ -242,7 +300,7 @@ class WiFiScanResult { bssid_t bssid_; uint8_t channel_; int8_t rssi_; - std::string ssid_; + CompactString ssid_; int8_t priority_{0}; bool matches_{false}; bool with_auth_; @@ -381,6 +439,8 @@ class WiFiComponent : public Component { void set_passive_scan(bool passive); void save_wifi_sta(const std::string &ssid, const std::string &password); + void save_wifi_sta(const char *ssid, const char *password); + void save_wifi_sta(StringRef ssid, StringRef password) { this->save_wifi_sta(ssid.c_str(), password.c_str()); } // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -545,7 +605,7 @@ class WiFiComponent : public Component { int8_t find_first_non_hidden_index_() const; /// Check if an SSID was seen in the most recent scan results /// Used to skip hidden mode for SSIDs we know are visible - bool ssid_was_seen_in_scan_(const std::string &ssid) const; + bool ssid_was_seen_in_scan_(const CompactString &ssid) const; /// Check if full scan results are needed (captive portal active, improv, listeners) bool needs_full_scan_results_() const; /// Check if network matches any configured network (for scan result filtering) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 6488de8dae..c87345f0bf 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -247,16 +247,16 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { struct station_config conf {}; memset(&conf, 0, sizeof(conf)); - if (ap.get_ssid().size() > sizeof(conf.ssid)) { + if (ap.ssid_.size() > sizeof(conf.ssid)) { ESP_LOGE(TAG, "SSID too long"); return false; } - if (ap.get_password().size() > sizeof(conf.password)) { + if (ap.password_.size() > sizeof(conf.password)) { ESP_LOGE(TAG, "Password too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), ap.get_ssid().size()); - memcpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), ap.get_password().size()); + memcpy(reinterpret_cast<char *>(conf.ssid), ap.ssid_.c_str(), ap.ssid_.size()); + memcpy(reinterpret_cast<char *>(conf.password), ap.password_.c_str(), ap.password_.size()); if (ap.has_bssid()) { conf.bssid_set = 1; @@ -266,7 +266,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { } #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 4, 0) - if (ap.get_password().empty()) { + if (ap.password_.empty()) { conf.threshold.authmode = AUTH_OPEN; } else { // Set threshold based on configured minimum auth mode @@ -738,8 +738,8 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { const char *ssid_cstr = reinterpret_cast<const char *>(it->ssid); if (needs_full || this->matches_configured_network_(ssid_cstr, it->bssid)) { this->scan_result_.emplace_back( - bssid_t{it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]}, - std::string(ssid_cstr, it->ssid_len), it->channel, it->rssi, it->authmode != AUTH_OPEN, it->is_hidden != 0); + bssid_t{it->bssid[0], it->bssid[1], it->bssid[2], it->bssid[3], it->bssid[4], it->bssid[5]}, ssid_cstr, + it->ssid_len, it->channel, it->rssi, it->authmode != AUTH_OPEN, it->is_hidden != 0); } else { this->log_discarded_scan_result_(ssid_cstr, it->bssid, it->rssi, it->channel); } @@ -832,27 +832,27 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { return false; struct softap_config conf {}; - if (ap.get_ssid().size() > sizeof(conf.ssid)) { + if (ap.ssid_.size() > sizeof(conf.ssid)) { ESP_LOGE(TAG, "AP SSID too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.ssid), ap.get_ssid().c_str(), ap.get_ssid().size()); - conf.ssid_len = static_cast<uint8>(ap.get_ssid().size()); + memcpy(reinterpret_cast<char *>(conf.ssid), ap.ssid_.c_str(), ap.ssid_.size()); + conf.ssid_len = static_cast<uint8>(ap.ssid_.size()); conf.channel = ap.has_channel() ? ap.get_channel() : 1; conf.ssid_hidden = ap.get_hidden(); conf.max_connection = 5; conf.beacon_interval = 100; - if (ap.get_password().empty()) { + if (ap.password_.empty()) { conf.authmode = AUTH_OPEN; *conf.password = 0; } else { conf.authmode = AUTH_WPA2_PSK; - if (ap.get_password().size() > sizeof(conf.password)) { + if (ap.password_.size() > sizeof(conf.password)) { ESP_LOGE(TAG, "AP password too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.password), ap.get_password().c_str(), ap.get_password().size()); + memcpy(reinterpret_cast<char *>(conf.password), ap.password_.c_str(), ap.password_.size()); } ETS_UART_INTR_DISABLE(); diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index d74d083954..52ee482121 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -300,19 +300,19 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html#_CPPv417wifi_sta_config_t wifi_config_t conf; memset(&conf, 0, sizeof(conf)); - if (ap.get_ssid().size() > sizeof(conf.sta.ssid)) { + if (ap.ssid_.size() > sizeof(conf.sta.ssid)) { ESP_LOGE(TAG, "SSID too long"); return false; } - if (ap.get_password().size() > sizeof(conf.sta.password)) { + if (ap.password_.size() > sizeof(conf.sta.password)) { ESP_LOGE(TAG, "Password too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.sta.ssid), ap.get_ssid().c_str(), ap.get_ssid().size()); - memcpy(reinterpret_cast<char *>(conf.sta.password), ap.get_password().c_str(), ap.get_password().size()); + memcpy(reinterpret_cast<char *>(conf.sta.ssid), ap.ssid_.c_str(), ap.ssid_.size()); + memcpy(reinterpret_cast<char *>(conf.sta.password), ap.password_.c_str(), ap.password_.size()); // The weakest authmode to accept in the fast scan mode - if (ap.get_password().empty()) { + if (ap.password_.empty()) { conf.sta.threshold.authmode = WIFI_AUTH_OPEN; } else { // Set threshold based on configured minimum auth mode @@ -864,8 +864,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { if (needs_full || this->matches_configured_network_(ssid_cstr, record.bssid)) { bssid_t bssid; std::copy(record.bssid, record.bssid + 6, bssid.begin()); - std::string ssid(ssid_cstr); - this->scan_result_.emplace_back(bssid, std::move(ssid), record.primary, record.rssi, + this->scan_result_.emplace_back(bssid, ssid_cstr, strlen(ssid_cstr), record.primary, record.rssi, record.authmode != WIFI_AUTH_OPEN, ssid_cstr[0] == '\0'); } else { this->log_discarded_scan_result_(ssid_cstr, record.bssid, record.rssi, record.primary); @@ -1055,26 +1054,26 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { wifi_config_t conf; memset(&conf, 0, sizeof(conf)); - if (ap.get_ssid().size() > sizeof(conf.ap.ssid)) { + if (ap.ssid_.size() > sizeof(conf.ap.ssid)) { ESP_LOGE(TAG, "AP SSID too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.ap.ssid), ap.get_ssid().c_str(), ap.get_ssid().size()); + memcpy(reinterpret_cast<char *>(conf.ap.ssid), ap.ssid_.c_str(), ap.ssid_.size()); conf.ap.channel = ap.has_channel() ? ap.get_channel() : 1; - conf.ap.ssid_hidden = ap.get_ssid().size(); + conf.ap.ssid_hidden = ap.get_hidden(); conf.ap.max_connection = 5; conf.ap.beacon_interval = 100; - if (ap.get_password().empty()) { + if (ap.password_.empty()) { conf.ap.authmode = WIFI_AUTH_OPEN; *conf.ap.password = 0; } else { conf.ap.authmode = WIFI_AUTH_WPA2_PSK; - if (ap.get_password().size() > sizeof(conf.ap.password)) { + if (ap.password_.size() > sizeof(conf.ap.password)) { ESP_LOGE(TAG, "AP password too long"); return false; } - memcpy(reinterpret_cast<char *>(conf.ap.password), ap.get_password().c_str(), ap.get_password().size()); + memcpy(reinterpret_cast<char *>(conf.ap.password), ap.password_.c_str(), ap.password_.size()); } // pairwise cipher of SoftAP, group cipher will be derived using this. diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 5fd9d7663b..2cc05928af 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -193,7 +193,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; String ssid = WiFi.SSID(); - if (ssid && strcmp(ssid.c_str(), ap.get_ssid().c_str()) != 0) { + if (ssid && strcmp(ssid.c_str(), ap.ssid_.c_str()) != 0) { WiFi.disconnect(); } @@ -213,7 +213,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { s_sta_state = LTWiFiSTAState::CONNECTING; s_ignored_disconnect_count = 0; - WiFiStatus status = WiFi.begin(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), + WiFiStatus status = WiFi.begin(ap.ssid_.c_str(), ap.password_.empty() ? NULL : ap.password_.c_str(), ap.get_channel(), // 0 = auto ap.has_bssid() ? ap.get_bssid().data() : NULL); if (status != WL_CONNECTED) { @@ -688,7 +688,7 @@ void WiFiComponent::wifi_scan_done_callback_() { auto &ap = scan->ap[i]; this->scan_result_.emplace_back(bssid_t{ap.bssid.addr[0], ap.bssid.addr[1], ap.bssid.addr[2], ap.bssid.addr[3], ap.bssid.addr[4], ap.bssid.addr[5]}, - std::string(ssid_cstr), ap.channel, ap.rssi, ap.auth != WIFI_AUTH_OPEN, + ssid_cstr, strlen(ssid_cstr), ap.channel, ap.rssi, ap.auth != WIFI_AUTH_OPEN, ssid_cstr[0] == '\0'); } else { auto &ap = scan->ap[i]; @@ -735,7 +735,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { yield(); - return WiFi.softAP(ap.get_ssid().c_str(), ap.get_password().empty() ? NULL : ap.get_password().c_str(), + return WiFi.softAP(ap.ssid_.c_str(), ap.password_.empty() ? NULL : ap.password_.c_str(), ap.has_channel() ? ap.get_channel() : 1, ap.get_hidden()); } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 818ad1059c..1baf21e2b2 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -78,7 +78,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; #endif - auto ret = WiFi.begin(ap.get_ssid().c_str(), ap.get_password().c_str()); + auto ret = WiFi.begin(ap.ssid_.c_str(), ap.password_.c_str()); if (ret != WL_CONNECTED) return false; @@ -149,9 +149,8 @@ void WiFiComponent::wifi_scan_result(void *env, const cyw43_ev_scan_result_t *re bssid_t bssid; std::copy(result->bssid, result->bssid + 6, bssid.begin()); - std::string ssid(ssid_cstr); - WiFiScanResult res(bssid, std::move(ssid), result->channel, result->rssi, result->auth_mode != CYW43_AUTH_OPEN, - ssid_cstr[0] == '\0'); + WiFiScanResult res(bssid, ssid_cstr, strlen(ssid_cstr), result->channel, result->rssi, + result->auth_mode != CYW43_AUTH_OPEN, ssid_cstr[0] == '\0'); if (std::find(this->scan_result_.begin(), this->scan_result_.end(), res) == this->scan_result_.end()) { this->scan_result_.push_back(res); } @@ -204,7 +203,7 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { } #endif - WiFi.beginAP(ap.get_ssid().c_str(), ap.get_password().c_str(), ap.has_channel() ? ap.get_channel() : 1); + WiFi.beginAP(ap.ssid_.c_str(), ap.password_.c_str(), ap.has_channel() ? ap.get_channel() : 1); return true; } diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.cpp b/esphome/components/wifi_info/wifi_info_text_sensor.cpp index a63b30b892..b5ebfd7390 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.cpp +++ b/esphome/components/wifi_info/wifi_info_text_sensor.cpp @@ -89,7 +89,7 @@ void ScanResultsWiFiInfo::on_wifi_scan_results(const wifi::wifi_scan_vector_t<wi for (const auto &scan : results) { if (scan.get_is_hidden()) continue; - const std::string &ssid = scan.get_ssid(); + const auto &ssid = scan.get_ssid(); // Max space: ssid + ": " (2) + "-128" (4) + "dB\n" (3) = ssid + 9 if (ptr + ssid.size() + 9 > end) break; From fecb145a7170b708e2e03e50a39a04b2eada94d7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 17:42:18 -0600 Subject: [PATCH 0677/2030] [web_server_idf] Revert multipart upload buffer back to heap to fix httpd stack overflow (#13941) --- esphome/components/web_server_idf/web_server_idf.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 2e07fb6e0a..d7d6f90355 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -881,12 +881,12 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c } }); - // Process data - use stack buffer to avoid heap allocation - char buffer[MULTIPART_CHUNK_SIZE]; + // Use heap buffer - 1460 bytes is too large for the httpd task stack + auto buffer = std::make_unique<char[]>(MULTIPART_CHUNK_SIZE); size_t bytes_since_yield = 0; for (size_t remaining = r->content_len; remaining > 0;) { - int recv_len = httpd_req_recv(r, buffer, std::min(remaining, MULTIPART_CHUNK_SIZE)); + int recv_len = httpd_req_recv(r, buffer.get(), std::min(remaining, MULTIPART_CHUNK_SIZE)); if (recv_len <= 0) { httpd_resp_send_err(r, recv_len == HTTPD_SOCK_ERR_TIMEOUT ? HTTPD_408_REQ_TIMEOUT : HTTPD_400_BAD_REQUEST, @@ -894,7 +894,7 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c return recv_len == HTTPD_SOCK_ERR_TIMEOUT ? ESP_ERR_TIMEOUT : ESP_FAIL; } - if (reader->parse(buffer, recv_len) != static_cast<size_t>(recv_len)) { + if (reader->parse(buffer.get(), recv_len) != static_cast<size_t>(recv_len)) { ESP_LOGW(TAG, "Multipart parser error"); httpd_resp_send_err(r, HTTPD_400_BAD_REQUEST, nullptr); return ESP_FAIL; From ae42bfa40448930cf9c101a7bfbc200c86c57c7c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 17:42:33 -0600 Subject: [PATCH 0678/2030] [web_server_idf] Remove std::string temporaries from multipart header parsing (#13940) --- .../components/web_server_idf/multipart.cpp | 87 +++++++++++-------- esphome/components/web_server_idf/multipart.h | 9 +- esphome/components/web_server_idf/utils.cpp | 11 ++- esphome/components/web_server_idf/utils.h | 4 +- .../web_server_idf/web_server_idf.cpp | 5 +- 5 files changed, 67 insertions(+), 49 deletions(-) diff --git a/esphome/components/web_server_idf/multipart.cpp b/esphome/components/web_server_idf/multipart.cpp index 52dafeb997..7744272a5c 100644 --- a/esphome/components/web_server_idf/multipart.cpp +++ b/esphome/components/web_server_idf/multipart.cpp @@ -54,14 +54,15 @@ size_t MultipartReader::parse(const char *data, size_t len) { void MultipartReader::process_header_(const char *value, size_t length) { // Process the completed header (field + value pair) - std::string value_str(value, length); + const char *field = current_header_field_.c_str(); + size_t field_len = current_header_field_.length(); - if (str_startswith_case_insensitive(current_header_field_, "content-disposition")) { + if (str_startswith_case_insensitive(field, field_len, "content-disposition")) { // Parse name and filename from Content-Disposition - current_part_.name = extract_header_param(value_str, "name"); - current_part_.filename = extract_header_param(value_str, "filename"); - } else if (str_startswith_case_insensitive(current_header_field_, "content-type")) { - current_part_.content_type = str_trim(value_str); + extract_header_param(value, length, "name", current_part_.name); + extract_header_param(value, length, "filename", current_part_.filename); + } else if (str_startswith_case_insensitive(field, field_len, "content-type")) { + str_trim(value, length, current_part_.content_type); } // Clear field for next header @@ -107,25 +108,29 @@ int MultipartReader::on_part_data_end(multipart_parser *parser) { // ========== Utility Functions ========== // Case-insensitive string prefix check -bool str_startswith_case_insensitive(const std::string &str, const std::string &prefix) { - if (str.length() < prefix.length()) { +bool str_startswith_case_insensitive(const char *str, size_t str_len, const char *prefix) { + size_t prefix_len = strlen(prefix); + if (str_len < prefix_len) { return false; } - return str_ncmp_ci(str.c_str(), prefix.c_str(), prefix.length()); + return str_ncmp_ci(str, prefix, prefix_len); } // Extract a parameter value from a header line // Handles both quoted and unquoted values -std::string extract_header_param(const std::string &header, const std::string ¶m) { +// Assigns to out if found, clears out otherwise +void extract_header_param(const char *header, size_t header_len, const char *param, std::string &out) { + size_t param_len = strlen(param); size_t search_pos = 0; - while (search_pos < header.length()) { + while (search_pos < header_len) { // Look for param name - const char *found = stristr(header.c_str() + search_pos, param.c_str()); + const char *found = strcasestr_n(header + search_pos, header_len - search_pos, param); if (!found) { - return ""; + out.clear(); + return; } - size_t pos = found - header.c_str(); + size_t pos = found - header; // Check if this is a word boundary (not part of another parameter) if (pos > 0 && header[pos - 1] != ' ' && header[pos - 1] != ';' && header[pos - 1] != '\t') { @@ -134,14 +139,14 @@ std::string extract_header_param(const std::string &header, const std::string &p } // Move past param name - pos += param.length(); + pos += param_len; // Skip whitespace and find '=' - while (pos < header.length() && (header[pos] == ' ' || header[pos] == '\t')) { + while (pos < header_len && (header[pos] == ' ' || header[pos] == '\t')) { pos++; } - if (pos >= header.length() || header[pos] != '=') { + if (pos >= header_len || header[pos] != '=') { search_pos = pos; continue; } @@ -149,36 +154,39 @@ std::string extract_header_param(const std::string &header, const std::string &p pos++; // Skip '=' // Skip whitespace after '=' - while (pos < header.length() && (header[pos] == ' ' || header[pos] == '\t')) { + while (pos < header_len && (header[pos] == ' ' || header[pos] == '\t')) { pos++; } - if (pos >= header.length()) { - return ""; + if (pos >= header_len) { + out.clear(); + return; } // Check if value is quoted if (header[pos] == '"') { pos++; - size_t end = header.find('"', pos); - if (end != std::string::npos) { - return header.substr(pos, end - pos); + const char *end = static_cast<const char *>(memchr(header + pos, '"', header_len - pos)); + if (end) { + out.assign(header + pos, end - (header + pos)); + return; } // Malformed - no closing quote - return ""; + out.clear(); + return; } // Unquoted value - find the end (semicolon, comma, or end of string) size_t end = pos; - while (end < header.length() && header[end] != ';' && header[end] != ',' && header[end] != ' ' && - header[end] != '\t') { + while (end < header_len && header[end] != ';' && header[end] != ',' && header[end] != ' ' && header[end] != '\t') { end++; } - return header.substr(pos, end - pos); + out.assign(header + pos, end - pos); + return; } - return ""; + out.clear(); } // Parse boundary from Content-Type header @@ -189,13 +197,15 @@ bool parse_multipart_boundary(const char *content_type, const char **boundary_st return false; } + size_t content_type_len = strlen(content_type); + // Check for multipart/form-data (case-insensitive) - if (!stristr(content_type, "multipart/form-data")) { + if (!strcasestr_n(content_type, content_type_len, "multipart/form-data")) { return false; } // Look for boundary parameter - const char *b = stristr(content_type, "boundary="); + const char *b = strcasestr_n(content_type, content_type_len, "boundary="); if (!b) { return false; } @@ -238,14 +248,15 @@ bool parse_multipart_boundary(const char *content_type, const char **boundary_st return true; } -// Trim whitespace from both ends of a string -std::string str_trim(const std::string &str) { - size_t start = str.find_first_not_of(" \t\r\n"); - if (start == std::string::npos) { - return ""; - } - size_t end = str.find_last_not_of(" \t\r\n"); - return str.substr(start, end - start + 1); +// Trim whitespace from both ends, assign result to out +void str_trim(const char *str, size_t len, std::string &out) { + const char *start = str; + const char *end = str + len; + while (start < end && (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n')) + start++; + while (end > start && (end[-1] == ' ' || end[-1] == '\t' || end[-1] == '\r' || end[-1] == '\n')) + end--; + out.assign(start, end - start); } } // namespace esphome::web_server_idf diff --git a/esphome/components/web_server_idf/multipart.h b/esphome/components/web_server_idf/multipart.h index 9008be6459..cb1e0ecd1d 100644 --- a/esphome/components/web_server_idf/multipart.h +++ b/esphome/components/web_server_idf/multipart.h @@ -66,19 +66,20 @@ class MultipartReader { // ========== Utility Functions ========== // Case-insensitive string prefix check -bool str_startswith_case_insensitive(const std::string &str, const std::string &prefix); +bool str_startswith_case_insensitive(const char *str, size_t str_len, const char *prefix); // Extract a parameter value from a header line // Handles both quoted and unquoted values -std::string extract_header_param(const std::string &header, const std::string ¶m); +// Assigns to out if found, clears out otherwise +void extract_header_param(const char *header, size_t header_len, const char *param, std::string &out); // Parse boundary from Content-Type header // Returns true if boundary found, false otherwise // boundary_start and boundary_len will point to the boundary value bool parse_multipart_boundary(const char *content_type, const char **boundary_start, size_t *boundary_len); -// Trim whitespace from both ends of a string -std::string str_trim(const std::string &str); +// Trim whitespace from both ends, assign result to out +void str_trim(const char *str, size_t len, std::string &out); } // namespace esphome::web_server_idf #endif // defined(USE_ESP32) && defined(USE_WEBSERVER_OTA) diff --git a/esphome/components/web_server_idf/utils.cpp b/esphome/components/web_server_idf/utils.cpp index a1a2793b4a..81ae626277 100644 --- a/esphome/components/web_server_idf/utils.cpp +++ b/esphome/components/web_server_idf/utils.cpp @@ -98,8 +98,8 @@ bool str_ncmp_ci(const char *s1, const char *s2, size_t n) { return true; } -// Case-insensitive string search (like strstr but case-insensitive) -const char *stristr(const char *haystack, const char *needle) { +// Bounded case-insensitive string search (like strcasestr but length-bounded) +const char *strcasestr_n(const char *haystack, size_t haystack_len, const char *needle) { if (!haystack) { return nullptr; } @@ -109,7 +109,12 @@ const char *stristr(const char *haystack, const char *needle) { return haystack; } - for (const char *p = haystack; *p; p++) { + if (haystack_len < needle_len) { + return nullptr; + } + + const char *end = haystack + haystack_len - needle_len + 1; + for (const char *p = haystack; p < end; p++) { if (str_ncmp_ci(p, needle, needle_len)) { return p; } diff --git a/esphome/components/web_server_idf/utils.h b/esphome/components/web_server_idf/utils.h index bb0610dac0..87635c0458 100644 --- a/esphome/components/web_server_idf/utils.h +++ b/esphome/components/web_server_idf/utils.h @@ -25,8 +25,8 @@ inline bool char_equals_ci(char a, char b) { return ::tolower(a) == ::tolower(b) // Helper function for case-insensitive string region comparison bool str_ncmp_ci(const char *s1, const char *s2, size_t n); -// Case-insensitive string search (like strstr but case-insensitive) -const char *stristr(const char *haystack, const char *needle); +// Bounded case-insensitive string search (like strcasestr but length-bounded) +const char *strcasestr_n(const char *haystack, size_t haystack_len, const char *needle); } // namespace esphome::web_server_idf #endif // USE_ESP32 diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index d7d6f90355..f1f89beb49 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -171,10 +171,11 @@ esp_err_t AsyncWebServer::request_post_handler(httpd_req_t *r) { const char *content_type_char = content_type.value().c_str(); // Check most common case first - if (stristr(content_type_char, "application/x-www-form-urlencoded") != nullptr) { + size_t content_type_len = strlen(content_type_char); + if (strcasestr_n(content_type_char, content_type_len, "application/x-www-form-urlencoded") != nullptr) { // Normal form data - proceed with regular handling #ifdef USE_WEBSERVER_OTA - } else if (stristr(content_type_char, "multipart/form-data") != nullptr) { + } else if (strcasestr_n(content_type_char, content_type_len, "multipart/form-data") != nullptr) { auto *server = static_cast<AsyncWebServer *>(r->user_ctx); return server->handle_multipart_upload_(r, content_type_char); #endif From 96eb129cf80f7dcf8f0aa08e57a3b341fc0293c6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Feb 2026 20:29:17 -0500 Subject: [PATCH 0679/2030] [esp32] Bump Arduino to 3.3.7, platform to 55.03.37 (#13943) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .clang-tidy.hash | 2 +- esphome/components/esp32/__init__.py | 14 ++++++++------ esphome/components/esp32/boards.py | 16 ++++++++++++++++ esphome/core/defines.h | 2 +- platformio.ini | 6 +++--- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 3ffe32af88..d6d401ee66 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -74867fc82764102ce1275ea2bc43e3aeee7619679537c6db61114a33342bb4c7 +ce05c28e9dc0b12c4f6e7454986ffea5123ac974a949da841be698c535f2083e diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index a680a78951..b78b945a24 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -645,11 +645,12 @@ def _is_framework_url(source: str) -> bool: # The default/recommended arduino framework version # - https://github.com/espressif/arduino-esp32/releases ARDUINO_FRAMEWORK_VERSION_LOOKUP = { - "recommended": cv.Version(3, 3, 6), - "latest": cv.Version(3, 3, 6), - "dev": cv.Version(3, 3, 6), + "recommended": cv.Version(3, 3, 7), + "latest": cv.Version(3, 3, 7), + "dev": cv.Version(3, 3, 7), } ARDUINO_PLATFORM_VERSION_LOOKUP = { + cv.Version(3, 3, 7): cv.Version(55, 3, 37), cv.Version(3, 3, 6): cv.Version(55, 3, 36), cv.Version(3, 3, 5): cv.Version(55, 3, 35), cv.Version(3, 3, 4): cv.Version(55, 3, 31, "2"), @@ -668,6 +669,7 @@ ARDUINO_PLATFORM_VERSION_LOOKUP = { # These versions correspond to pioarduino/esp-idf releases # See: https://github.com/pioarduino/esp-idf/releases ARDUINO_IDF_VERSION_LOOKUP = { + cv.Version(3, 3, 7): cv.Version(5, 5, 2), cv.Version(3, 3, 6): cv.Version(5, 5, 2), cv.Version(3, 3, 5): cv.Version(5, 5, 2), cv.Version(3, 3, 4): cv.Version(5, 5, 1), @@ -691,7 +693,7 @@ ESP_IDF_FRAMEWORK_VERSION_LOOKUP = { "dev": cv.Version(5, 5, 2), } ESP_IDF_PLATFORM_VERSION_LOOKUP = { - cv.Version(5, 5, 2): cv.Version(55, 3, 36), + cv.Version(5, 5, 2): cv.Version(55, 3, 37), cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"), cv.Version(5, 5, 0): cv.Version(55, 3, 31, "2"), cv.Version(5, 4, 3): cv.Version(55, 3, 32), @@ -708,8 +710,8 @@ ESP_IDF_PLATFORM_VERSION_LOOKUP = { # The platform-espressif32 version # - https://github.com/pioarduino/platform-espressif32/releases PLATFORM_VERSION_LOOKUP = { - "recommended": cv.Version(55, 3, 36), - "latest": cv.Version(55, 3, 36), + "recommended": cv.Version(55, 3, 37), + "latest": cv.Version(55, 3, 37), "dev": "https://github.com/pioarduino/platform-espressif32.git#develop", } diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 8b066064f2..66367d63ae 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -1686,6 +1686,10 @@ BOARDS = { "name": "Espressif ESP32-C6-DevKitM-1", "variant": VARIANT_ESP32C6, }, + "esp32-c61-devkitc1": { + "name": "Espressif ESP32-C61-DevKitC-1 (4 MB Flash)", + "variant": VARIANT_ESP32C61, + }, "esp32-c61-devkitc1-n8r2": { "name": "Espressif ESP32-C61-DevKitC-1 N8R2 (8 MB Flash Quad, 2 MB PSRAM Quad)", "variant": VARIANT_ESP32C61, @@ -1718,6 +1722,10 @@ BOARDS = { "name": "Espressif ESP32-P4 rev.300 generic", "variant": VARIANT_ESP32P4, }, + "esp32-p4_r3-evboard": { + "name": "Espressif ESP32-P4 Function EV Board v1.6 (rev.301)", + "variant": VARIANT_ESP32P4, + }, "esp32-pico-devkitm-2": { "name": "Espressif ESP32-PICO-DevKitM-2", "variant": VARIANT_ESP32, @@ -2554,6 +2562,10 @@ BOARDS = { "name": "XinaBox CW02", "variant": VARIANT_ESP32, }, + "yb_esp32s3_amp": { + "name": "YelloByte YB-ESP32-S3-AMP", + "variant": VARIANT_ESP32S3, + }, "yb_esp32s3_amp_v2": { "name": "YelloByte YB-ESP32-S3-AMP (Rev.2)", "variant": VARIANT_ESP32S3, @@ -2562,6 +2574,10 @@ BOARDS = { "name": "YelloByte YB-ESP32-S3-AMP (Rev.3)", "variant": VARIANT_ESP32S3, }, + "yb_esp32s3_dac": { + "name": "YelloByte YB-ESP32-S3-DAC", + "variant": VARIANT_ESP32S3, + }, "yb_esp32s3_drv": { "name": "YelloByte YB-ESP32-S3-DRV", "variant": VARIANT_ESP32S3, diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 7e6df31ea2..8fc30760c7 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -239,7 +239,7 @@ #define USB_HOST_MAX_REQUESTS 16 #ifdef USE_ARDUINO -#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 6) +#define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 7) #define USE_ETHERNET #define USE_ETHERNET_KSZ8081 #define USE_ETHERNET_MANUAL_IP diff --git a/platformio.ini b/platformio.ini index 6b29daf87a..09b3d8722d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -133,9 +133,9 @@ extra_scripts = post:esphome/components/esp8266/post_build.py.script ; This are common settings for the ESP32 (all variants) using Arduino. [common:esp32-arduino] extends = common:arduino -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = - pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.6/esp32-core-3.3.6.tar.xz + pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7.tar.xz pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz framework = arduino, espidf ; Arduino as an ESP-IDF component @@ -169,7 +169,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script ; This are common settings for the ESP32 (all variants) using IDF. [common:esp32-idf] extends = common:idf -platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.36/platform-espressif32.zip +platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz From db6aea8969ba5fe6f7e6202e1d8f68f27a13cad3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Feb 2026 22:11:48 -0500 Subject: [PATCH 0680/2030] Allow Python 3.14 (#13945) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .github/workflows/ci.yml | 1 + pyproject.toml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 841c297bce..8718772f53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,6 +115,7 @@ jobs: python-version: - "3.11" - "3.13" + - "3.14" os: - ubuntu-latest - macOS-latest diff --git a/pyproject.toml b/pyproject.toml index 339bc65eed..c6a2c22a5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,8 +20,8 @@ classifiers = [ "Topic :: Home Automation", ] -# Python 3.14 is currently not supported by IDF <= 5.5.1, see https://github.com/esphome/esphome/issues/11502 -requires-python = ">=3.11.0,<3.14" +# Python 3.14 is not supported on Windows, see https://github.com/zephyrproject-rtos/windows-curses/issues/76 +requires-python = ">=3.11.0,<3.15" dynamic = ["dependencies", "optional-dependencies", "version"] From c9d2adb717954968d212cc242a08751d41d3de56 Mon Sep 17 00:00:00 2001 From: Awesome Walrus <74941879+QRPp@users.noreply.github.com> Date: Thu, 12 Feb 2026 03:34:59 +0000 Subject: [PATCH 0681/2030] [wifi] Allow fast_connect without preconfigured networks (#13946) --- esphome/components/wifi/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 6863e6fb62..e865de8663 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -288,11 +288,6 @@ def _validate(config): config = config.copy() config[CONF_NETWORKS] = [] - if config.get(CONF_FAST_CONNECT, False): - networks = config.get(CONF_NETWORKS, []) - if not networks: - raise cv.Invalid("At least one network required for fast_connect!") - if CONF_USE_ADDRESS not in config: use_address = CORE.name + config[CONF_DOMAIN] if CONF_MANUAL_IP in config: From da1ea2cfa3204797a9ea79a2d4103c4ac56b469a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Feb 2026 23:07:05 -0600 Subject: [PATCH 0682/2030] [ethernet] Add per-PHY compile guards to eliminate unused PHY drivers (#13947) --- esphome/components/ethernet/__init__.py | 7 +- .../ethernet/ethernet_component.cpp | 69 ++++++++++++------- esphome/core/defines.h | 6 ++ 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 38489ceb2b..52f5f44d41 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -130,11 +130,16 @@ ETHERNET_TYPES = { } # PHY types that need compile-time defines for conditional compilation +# Each RMII PHY type gets a define so unused PHY drivers are excluded by the linker _PHY_TYPE_TO_DEFINE = { + "LAN8720": "USE_ETHERNET_LAN8720", + "RTL8201": "USE_ETHERNET_RTL8201", + "DP83848": "USE_ETHERNET_DP83848", + "IP101": "USE_ETHERNET_IP101", + "JL1101": "USE_ETHERNET_JL1101", "KSZ8081": "USE_ETHERNET_KSZ8081", "KSZ8081RNA": "USE_ETHERNET_KSZ8081", "LAN8670": "USE_ETHERNET_LAN8670", - # Add other PHY types here only if they need conditional compilation } SPI_ETHERNET_TYPES = ["W5500", "DM9051"] diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index af7fed608b..f9d98ad51b 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -186,31 +186,43 @@ void EthernetComponent::setup() { } #endif #if CONFIG_ETH_USE_ESP32_EMAC +#ifdef USE_ETHERNET_LAN8720 case ETHERNET_TYPE_LAN8720: { this->phy_ = esp_eth_phy_new_lan87xx(&phy_config); break; } +#endif +#ifdef USE_ETHERNET_RTL8201 case ETHERNET_TYPE_RTL8201: { this->phy_ = esp_eth_phy_new_rtl8201(&phy_config); break; } +#endif +#ifdef USE_ETHERNET_DP83848 case ETHERNET_TYPE_DP83848: { this->phy_ = esp_eth_phy_new_dp83848(&phy_config); break; } +#endif +#ifdef USE_ETHERNET_IP101 case ETHERNET_TYPE_IP101: { this->phy_ = esp_eth_phy_new_ip101(&phy_config); break; } +#endif +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: { this->phy_ = esp_eth_phy_new_jl1101(&phy_config); break; } +#endif +#ifdef USE_ETHERNET_KSZ8081 case ETHERNET_TYPE_KSZ8081: case ETHERNET_TYPE_KSZ8081RNA: { this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config); break; } +#endif #ifdef USE_ETHERNET_LAN8670 case ETHERNET_TYPE_LAN8670: { this->phy_ = esp_eth_phy_new_lan867x(&phy_config); @@ -343,26 +355,32 @@ void EthernetComponent::loop() { void EthernetComponent::dump_config() { const char *eth_type; switch (this->type_) { +#ifdef USE_ETHERNET_LAN8720 case ETHERNET_TYPE_LAN8720: eth_type = "LAN8720"; break; - +#endif +#ifdef USE_ETHERNET_RTL8201 case ETHERNET_TYPE_RTL8201: eth_type = "RTL8201"; break; - +#endif +#ifdef USE_ETHERNET_DP83848 case ETHERNET_TYPE_DP83848: eth_type = "DP83848"; break; - +#endif +#ifdef USE_ETHERNET_IP101 case ETHERNET_TYPE_IP101: eth_type = "IP101"; break; - +#endif +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: eth_type = "JL1101"; break; - +#endif +#ifdef USE_ETHERNET_KSZ8081 case ETHERNET_TYPE_KSZ8081: eth_type = "KSZ8081"; break; @@ -370,19 +388,22 @@ void EthernetComponent::dump_config() { case ETHERNET_TYPE_KSZ8081RNA: eth_type = "KSZ8081RNA"; break; - +#endif +#if CONFIG_ETH_SPI_ETHERNET_W5500 case ETHERNET_TYPE_W5500: eth_type = "W5500"; break; - - case ETHERNET_TYPE_OPENETH: - eth_type = "OPENETH"; - break; - +#endif +#if CONFIG_ETH_SPI_ETHERNET_DM9051 case ETHERNET_TYPE_DM9051: eth_type = "DM9051"; break; - +#endif +#ifdef USE_ETHERNET_OPENETH + case ETHERNET_TYPE_OPENETH: + eth_type = "OPENETH"; + break; +#endif #ifdef USE_ETHERNET_LAN8670 case ETHERNET_TYPE_LAN8670: eth_type = "LAN8670"; @@ -686,16 +707,22 @@ void EthernetComponent::dump_connect_params_() { char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE]; char dns1_buf[network::IP_ADDRESS_BUFFER_SIZE]; char dns2_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; ESP_LOGCONFIG(TAG, " IP Address: %s\n" " Hostname: '%s'\n" " Subnet: %s\n" " Gateway: %s\n" " DNS1: %s\n" - " DNS2: %s", + " DNS2: %s\n" + " MAC Address: %s\n" + " Is Full Duplex: %s\n" + " Link Speed: %u", network::IPAddress(&ip.ip).str_to(ip_buf), App.get_name().c_str(), network::IPAddress(&ip.netmask).str_to(subnet_buf), network::IPAddress(&ip.gw).str_to(gateway_buf), - network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf)); + network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf), + this->get_eth_mac_address_pretty_into_buffer(mac_buf), + YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); #if USE_NETWORK_IPV6 struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; @@ -706,14 +733,6 @@ void EthernetComponent::dump_connect_params_() { ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(if_ip6s[i])); } #endif /* USE_NETWORK_IPV6 */ - - char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; - ESP_LOGCONFIG(TAG, - " MAC Address: %s\n" - " Is Full Duplex: %s\n" - " Link Speed: %u", - this->get_eth_mac_address_pretty_into_buffer(mac_buf), - YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); } #ifdef USE_ETHERNET_SPI @@ -837,13 +856,15 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) { esp_err_t err; - constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; +#ifdef USE_ETHERNET_RTL8201 + constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; 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"); } +#endif ESP_LOGD(TAG, "Writing to PHY Register Address: 0x%02" PRIX32 "\n" @@ -852,11 +873,13 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi err = mac->write_phy_reg(mac, this->phy_addr_, register_data.address, register_data.value); ESPHL_ERROR_CHECK(err, "Writing PHY Register failed"); +#ifdef USE_ETHERNET_RTL8201 if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { ESP_LOGD(TAG, "Select PHY Register Page 0x00"); 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 } #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 8fc30760c7..bfa33e4e59 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -241,7 +241,13 @@ #ifdef USE_ARDUINO #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 7) #define USE_ETHERNET +#define USE_ETHERNET_LAN8720 +#define USE_ETHERNET_RTL8201 +#define USE_ETHERNET_DP83848 +#define USE_ETHERNET_IP101 +#define USE_ETHERNET_JL1101 #define USE_ETHERNET_KSZ8081 +#define USE_ETHERNET_LAN8670 #define USE_ETHERNET_MANUAL_IP #define USE_ETHERNET_IP_STATE_LISTENERS #define USE_ETHERNET_CONNECT_TRIGGER From 97d6f394dea5b7f5694ae82437efe7c08bb30d72 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Feb 2026 23:04:18 +1300 Subject: [PATCH 0683/2030] Bump version to 2026.2.0b1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index efc2f464e3..16516a387f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0-dev +PROJECT_NUMBER = 2026.2.0b1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 00d8013cc6..3b5cccfb25 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0-dev" +__version__ = "2026.2.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d6461251f925c4be1197a34f7d6be761a1cc014f Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Feb 2026 23:04:19 +1300 Subject: [PATCH 0684/2030] Bump version to 2026.3.0-dev --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index efc2f464e3..1a9e0b4e10 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0-dev +PROJECT_NUMBER = 2026.3.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 00d8013cc6..f72cbc8893 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0-dev" +__version__ = "2026.3.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 8a08c688f628a0a2302db29dd52646168ea6fe99 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:25:51 +0100 Subject: [PATCH 0685/2030] [mipi_spi] Add Waveshare 1.83 v2 panel (#13680) --- .../components/mipi_spi/models/waveshare.py | 83 ++++++++++++++++++- tests/components/mipi_spi/common.yaml | 24 +++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/esphome/components/mipi_spi/models/waveshare.py b/esphome/components/mipi_spi/models/waveshare.py index e4e090da2e..cc86101f5e 100644 --- a/esphome/components/mipi_spi/models/waveshare.py +++ b/esphome/components/mipi_spi/models/waveshare.py @@ -1,4 +1,17 @@ -from esphome.components.mipi import DriverChip +from esphome.components.mipi import ( + ETMOD, + FRMCTR2, + GMCTRN1, + GMCTRP1, + IFCTR, + MODE_RGB, + PWCTR1, + PWCTR3, + PWCTR4, + PWCTR5, + PWSET, + DriverChip, +) import esphome.config_validation as cv from .amoled import CO5300 @@ -129,6 +142,16 @@ DriverChip( ), ), ) +ST7789P = DriverChip( + "ST7789P", + # Max supported dimensions + width=240, + height=320, + # SPI: RGB layout + color_order=MODE_RGB, + invert_colors=True, + draw_rounding=1, +) ILI9488_A.extend( "PICO-RESTOUCH-LCD-3.5", @@ -162,3 +185,61 @@ AXS15231.extend( cs_pin=9, reset_pin=21, ) + +# Waveshare 1.83-v2 +# +# Do not use on 1.83-v1: Vendor warning on different chip! +ST7789P.extend( + "WAVESHARE-1.83-V2", + # Panel size smaller than ST7789 max allowed + width=240, + height=284, + # Vendor specific init derived from vendor sample code + # "LCD_1.83_Code_Rev2/ESP32/LCD_1in83/LCD_Driver.cpp" + # Compatible MIT license, see esphome/LICENSE file. + initsequence=( + (FRMCTR2, 0x0C, 0x0C, 0x00, 0x33, 0x33), + (ETMOD, 0x35), + (0xBB, 0x19), + (PWCTR1, 0x2C), + (PWCTR3, 0x01), + (PWCTR4, 0x12), + (PWCTR5, 0x20), + (IFCTR, 0x0F), + (PWSET, 0xA4, 0xA1), + ( + GMCTRP1, + 0xD0, + 0x04, + 0x0D, + 0x11, + 0x13, + 0x2B, + 0x3F, + 0x54, + 0x4C, + 0x18, + 0x0D, + 0x0B, + 0x1F, + 0x23, + ), + ( + GMCTRN1, + 0xD0, + 0x04, + 0x0C, + 0x11, + 0x13, + 0x2C, + 0x3F, + 0x44, + 0x51, + 0x2F, + 0x1F, + 0x1F, + 0x20, + 0x23, + ), + ), +) diff --git a/tests/components/mipi_spi/common.yaml b/tests/components/mipi_spi/common.yaml index 692a9f436e..a867b726ed 100644 --- a/tests/components/mipi_spi/common.yaml +++ b/tests/components/mipi_spi/common.yaml @@ -3,9 +3,15 @@ display: spi_16: true pixel_mode: 18bit model: ili9488 - dc_pin: ${dc_pin} - cs_pin: ${cs_pin} - reset_pin: ${reset_pin} + dc_pin: + allow_other_uses: true + number: ${dc_pin} + cs_pin: + allow_other_uses: true + number: ${cs_pin} + reset_pin: + allow_other_uses: true + number: ${reset_pin} data_rate: 20MHz invert_colors: true show_test_card: true @@ -24,3 +30,15 @@ display: height: 200 enable_pin: ${enable_pin} bus_mode: single + + - platform: mipi_spi + model: WAVESHARE-1.83-V2 + dc_pin: + allow_other_uses: true + number: ${dc_pin} + cs_pin: + allow_other_uses: true + number: ${cs_pin} + reset_pin: + allow_other_uses: true + number: ${reset_pin} From 7b251dcc310a7751f85c22de33d493288c0f700a Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino <glm.net@gmail.com> Date: Thu, 12 Feb 2026 13:23:59 -0300 Subject: [PATCH 0686/2030] [schema-gen] fix Windows: ensure UTF-8 encoding when reading component files (#13952) --- script/build_language_schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/build_language_schema.py b/script/build_language_schema.py index c9501cb193..bea540dc63 100755 --- a/script/build_language_schema.py +++ b/script/build_language_schema.py @@ -369,7 +369,7 @@ def get_logger_tags(): "api.service", ] for file in CORE_COMPONENTS_PATH.rglob("*.cpp"): - data = file.read_text() + data = file.read_text(encoding="utf-8") match = pattern.search(data) if match: tags.append(match.group(1)) From 9aa98ed6c65d7f2f025bdc9c5eb3ebe78e9bb71d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 10:26:10 -0600 Subject: [PATCH 0687/2030] [uart] Remove redundant mutex, fix flush race, conditional event queue (#13955) --- .../uart/uart_component_esp_idf.cpp | 49 ++++++++++--------- .../components/uart/uart_component_esp_idf.h | 17 +++++-- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 19b9a4077f..6c242220a6 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -90,7 +90,6 @@ void IDFUARTComponent::setup() { return; } this->uart_num_ = static_cast<uart_port_t>(next_uart_num++); - this->lock_ = xSemaphoreCreateMutex(); #if (SOC_UART_LP_NUM >= 1) size_t fifo_len = ((this->uart_num_ < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN); @@ -102,11 +101,7 @@ void IDFUARTComponent::setup() { this->rx_buffer_size_ = fifo_len * 2; } - xSemaphoreTake(this->lock_, portMAX_DELAY); - this->load_settings(false); - - xSemaphoreGive(this->lock_); } void IDFUARTComponent::load_settings(bool dump_config) { @@ -126,13 +121,20 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } } +#ifdef USE_UART_WAKE_LOOP_ON_RX + constexpr int event_queue_size = 20; + QueueHandle_t *event_queue_ptr = &this->uart_event_queue_; +#else + constexpr int event_queue_size = 0; + QueueHandle_t *event_queue_ptr = nullptr; +#endif err = uart_driver_install(this->uart_num_, // UART number this->rx_buffer_size_, // RX ring buffer size - 0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will - // block task until all data has been sent out - 20, // event queue size/depth - &this->uart_event_queue_, // event queue - 0 // Flags used to allocate the interrupt + 0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will + // block task until all data has been sent out + event_queue_size, // event queue size/depth + event_queue_ptr, // event queue + 0 // Flags used to allocate the interrupt ); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err)); @@ -282,9 +284,7 @@ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) { } void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { - xSemaphoreTake(this->lock_, portMAX_DELAY); int32_t write_len = uart_write_bytes(this->uart_num_, data, len); - xSemaphoreGive(this->lock_); if (write_len != (int32_t) len) { ESP_LOGW(TAG, "uart_write_bytes failed: %d != %zu", write_len, len); this->mark_failed(); @@ -299,7 +299,6 @@ void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { bool IDFUARTComponent::peek_byte(uint8_t *data) { if (!this->check_read_timeout_()) return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); if (this->has_peek_) { *data = this->peek_byte_; } else { @@ -311,7 +310,6 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) { this->peek_byte_ = *data; } } - xSemaphoreGive(this->lock_); return true; } @@ -320,7 +318,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { int32_t read_len = 0; if (!this->check_read_timeout_(len)) return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); if (this->has_peek_) { length_to_read--; *data = this->peek_byte_; @@ -329,7 +326,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { } if (length_to_read > 0) read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS); - xSemaphoreGive(this->lock_); #ifdef USE_UART_DEBUGGER for (size_t i = 0; i < len; i++) { this->debug_callback_.call(UART_DIRECTION_RX, data[i]); @@ -342,9 +338,7 @@ size_t IDFUARTComponent::available() { size_t available = 0; esp_err_t err; - xSemaphoreTake(this->lock_, portMAX_DELAY); err = uart_get_buffered_data_len(this->uart_num_, &available); - xSemaphoreGive(this->lock_); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_get_buffered_data_len failed: %s", esp_err_to_name(err)); @@ -358,9 +352,7 @@ size_t IDFUARTComponent::available() { void IDFUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); - xSemaphoreTake(this->lock_, portMAX_DELAY); uart_wait_tx_done(this->uart_num_, portMAX_DELAY); - xSemaphoreGive(this->lock_); } void IDFUARTComponent::check_logger_conflict() {} @@ -384,6 +376,13 @@ void IDFUARTComponent::start_rx_event_task_() { ESP_LOGV(TAG, "RX event task started"); } +// FreeRTOS task that relays UART ISR events to the main loop. +// This task exists because wake_loop_threadsafe() is not ISR-safe (it uses a +// UDP loopback socket), so we need a task as an ISR-to-main-loop trampoline. +// IMPORTANT: This task must NOT call any UART wrapper methods (read_array, +// write_array, peek_byte, etc.) or touch has_peek_/peek_byte_ — all reading +// is done by the main loop. This task only reads from the event queue and +// calls App.wake_loop_threadsafe(). void IDFUARTComponent::rx_event_task_func(void *param) { auto *self = static_cast<IDFUARTComponent *>(param); uart_event_t event; @@ -405,8 +404,14 @@ void IDFUARTComponent::rx_event_task_func(void *param) { case UART_FIFO_OVF: case UART_BUFFER_FULL: - ESP_LOGW(TAG, "FIFO overflow or ring buffer full - clearing"); - uart_flush_input(self->uart_num_); + // Don't call uart_flush_input() here — this task does not own the read side. + // ESP-IDF examples flush on overflow because the same task handles both events + // and reads, so flush and read are serialized. Here, reads happen on the main + // loop, so flushing from this task races with read_array() and can destroy data + // mid-read. The driver self-heals without an explicit flush: uart_read_bytes() + // calls uart_check_buf_full() after each chunk, which moves stashed FIFO bytes + // into the ring buffer and re-enables RX interrupts once space is freed. + ESP_LOGW(TAG, "FIFO overflow or ring buffer full"); #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); #endif diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index 1ecb02d7ab..1517eab509 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -8,6 +8,13 @@ namespace esphome::uart { +/// ESP-IDF UART driver wrapper. +/// +/// Thread safety: All public methods must only be called from the main loop. +/// The ESP-IDF UART driver API does not guarantee thread safety, and ESPHome's +/// peek byte state (has_peek_/peek_byte_) is not synchronized. The rx_event_task +/// (when enabled) must not call any of these methods — it communicates with the +/// main loop exclusively via App.wake_loop_threadsafe(). class IDFUARTComponent : public UARTComponent, public Component { public: void setup() override; @@ -26,7 +33,9 @@ class IDFUARTComponent : public UARTComponent, public Component { void flush() override; uint8_t get_hw_serial_number() { return this->uart_num_; } +#ifdef USE_UART_WAKE_LOOP_ON_RX QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; } +#endif /** * Load the UART with the current settings. @@ -46,18 +55,20 @@ class IDFUARTComponent : public UARTComponent, public Component { protected: void check_logger_conflict() override; uart_port_t uart_num_; - QueueHandle_t uart_event_queue_; uart_config_t get_config_(); - SemaphoreHandle_t lock_; bool has_peek_{false}; uint8_t peek_byte_; #ifdef USE_UART_WAKE_LOOP_ON_RX - // RX notification support + // RX notification support — runs on a separate FreeRTOS task. + // IMPORTANT: rx_event_task_func must NOT call any UART wrapper methods (read_array, + // write_array, etc.) or touch has_peek_/peek_byte_. It must only read from the + // event queue and call App.wake_loop_threadsafe(). void start_rx_event_task_(); static void rx_event_task_func(void *param); + QueueHandle_t uart_event_queue_; TaskHandle_t rx_event_task_handle_{nullptr}; #endif // USE_UART_WAKE_LOOP_ON_RX }; From 725e774fe79aac107288af979bf8ff7da7479feb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 10:26:36 -0600 Subject: [PATCH 0688/2030] [web_server] Guard icon JSON field with USE_ENTITY_ICON (#13948) --- esphome/components/web_server/web_server.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index dfd602be6b..7da8b49c6d 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -557,7 +557,9 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J root[ESPHOME_F("device")] = device_name; } #endif +#ifdef USE_ENTITY_ICON root[ESPHOME_F("icon")] = obj->get_icon_ref(); +#endif root[ESPHOME_F("entity_category")] = obj->get_entity_category(); bool is_disabled = obj->is_disabled_by_default(); if (is_disabled) From 60fef5e656396593f2a2867241ebf7c576549917 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 10:26:54 -0600 Subject: [PATCH 0689/2030] [analyze_memory] Fix mDNS packet buffer miscategorized as wifi_config (#13949) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/analyze_memory/const.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/analyze_memory/const.py b/esphome/analyze_memory/const.py index 66866615a6..3bdf555ae3 100644 --- a/esphome/analyze_memory/const.py +++ b/esphome/analyze_memory/const.py @@ -256,7 +256,7 @@ SYMBOL_PATTERNS = { "ipv6_stack": ["nd6_", "ip6_", "mld6_", "icmp6_", "icmp6_input"], # Order matters! More specific categories must come before general ones. # mdns must come before bluetooth to avoid "_mdns_disable_pcb" matching "ble_" pattern - "mdns_lib": ["mdns"], + "mdns_lib": ["mdns", "packet$"], # memory_mgmt must come before wifi_stack to catch mmu_hal_* symbols "memory_mgmt": [ "mem_", @@ -794,7 +794,6 @@ SYMBOL_PATTERNS = { "s_dp", "s_ni", "s_reg_dump", - "packet$", "d_mult_table", "K", "fcstab", From 0e1433329da006a6f58dfc1d5e086d93d743bf07 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 11:04:23 -0600 Subject: [PATCH 0690/2030] [api] Extract cold code from APIServer::loop() hot path (#13902) --- esphome/components/api/api_server.cpp | 130 ++++++++++++++------------ esphome/components/api/api_server.h | 5 + 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 53b41a5c14..5503cf4db8 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -117,37 +117,7 @@ void APIServer::setup() { void APIServer::loop() { // Accept new clients only if the socket exists and has incoming connections if (this->socket_ && this->socket_->ready()) { - while (true) { - struct sockaddr_storage source_addr; - socklen_t addr_len = sizeof(source_addr); - - auto sock = this->socket_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len); - if (!sock) - break; - - char peername[socket::SOCKADDR_STR_LEN]; - sock->getpeername_to(peername); - - // Check if we're at the connection limit - if (this->clients_.size() >= this->max_connections_) { - ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, peername); - // Immediately close - socket destructor will handle cleanup - sock.reset(); - continue; - } - - ESP_LOGD(TAG, "Accept %s", peername); - - auto *conn = new APIConnection(std::move(sock), this); - this->clients_.emplace_back(conn); - conn->start(); - - // First client connected - clear warning and update timestamp - if (this->clients_.size() == 1 && this->reboot_timeout_ != 0) { - this->status_clear_warning(); - this->last_connected_ = App.get_loop_component_start_time(); - } - } + this->accept_new_connections_(); } if (this->clients_.empty()) { @@ -178,46 +148,84 @@ void APIServer::loop() { while (client_index < this->clients_.size()) { auto &client = this->clients_[client_index]; - if (!client->flags_.remove) { + if (client->flags_.remove) { + // Rare case: handle disconnection (don't increment - swapped element needs processing) + this->remove_client_(client_index); + } else { // Common case: process active client client->loop(); client_index++; + } + } +} + +void APIServer::remove_client_(size_t client_index) { + auto &client = this->clients_[client_index]; + +#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES + this->unregister_active_action_calls_for_connection(client.get()); +#endif + ESP_LOGV(TAG, "Remove connection %s", client->get_name()); + +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Save client info before closing socket and removal for the trigger + char peername_buf[socket::SOCKADDR_STR_LEN]; + std::string client_name(client->get_name()); + std::string client_peername(client->get_peername_to(peername_buf)); +#endif + + // Close socket now (was deferred from on_fatal_error to allow getpeername) + client->helper_->close(); + + // Swap with the last element and pop (avoids expensive vector shifts) + if (client_index < this->clients_.size() - 1) { + std::swap(this->clients_[client_index], this->clients_.back()); + } + this->clients_.pop_back(); + + // Last client disconnected - set warning and start tracking for reboot timeout + if (this->clients_.empty() && this->reboot_timeout_ != 0) { + this->status_set_warning(); + this->last_connected_ = App.get_loop_component_start_time(); + } + +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Fire trigger after client is removed so api.connected reflects the true state + this->client_disconnected_trigger_.trigger(client_name, client_peername); +#endif +} + +void APIServer::accept_new_connections_() { + while (true) { + struct sockaddr_storage source_addr; + socklen_t addr_len = sizeof(source_addr); + + auto sock = this->socket_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len); + if (!sock) + break; + + char peername[socket::SOCKADDR_STR_LEN]; + sock->getpeername_to(peername); + + // Check if we're at the connection limit + if (this->clients_.size() >= this->max_connections_) { + ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, peername); + // Immediately close - socket destructor will handle cleanup + sock.reset(); continue; } - // Rare case: handle disconnection -#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - this->unregister_active_action_calls_for_connection(client.get()); -#endif - ESP_LOGV(TAG, "Remove connection %s", client->get_name()); + ESP_LOGD(TAG, "Accept %s", peername); -#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - // Save client info before closing socket and removal for the trigger - char peername_buf[socket::SOCKADDR_STR_LEN]; - std::string client_name(client->get_name()); - std::string client_peername(client->get_peername_to(peername_buf)); -#endif + auto *conn = new APIConnection(std::move(sock), this); + this->clients_.emplace_back(conn); + conn->start(); - // Close socket now (was deferred from on_fatal_error to allow getpeername) - client->helper_->close(); - - // Swap with the last element and pop (avoids expensive vector shifts) - if (client_index < this->clients_.size() - 1) { - std::swap(this->clients_[client_index], this->clients_.back()); - } - this->clients_.pop_back(); - - // Last client disconnected - set warning and start tracking for reboot timeout - if (this->clients_.empty() && this->reboot_timeout_ != 0) { - this->status_set_warning(); + // First client connected - clear warning and update timestamp + if (this->clients_.size() == 1 && this->reboot_timeout_ != 0) { + this->status_clear_warning(); this->last_connected_ = App.get_loop_component_start_time(); } - -#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - // Fire trigger after client is removed so api.connected reflects the true state - this->client_disconnected_trigger_.trigger(client_name, client_peername); -#endif - // Don't increment client_index since we need to process the swapped element } } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 6ab3cdc576..28f60343e0 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -234,6 +234,11 @@ class APIServer : public Component, #endif protected: + // Accept incoming socket connections. Only called when socket has pending connections. + void __attribute__((noinline)) accept_new_connections_(); + // Remove a disconnected client by index. Swaps with last element and pops. + void __attribute__((noinline)) remove_client_(size_t client_index); + #ifdef USE_API_NOISE bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg, const psk_t &active_psk, bool make_active); From cde8b6671932d3b75b0a323ef947f24cd9f2872f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 11:04:41 -0600 Subject: [PATCH 0691/2030] [web_server] Switch from getParam to arg API to eliminate heap allocations (#13942) --- .../captive_portal/captive_portal.cpp | 8 +- esphome/components/web_server/web_server.cpp | 94 +++++++++---------- esphome/components/web_server/web_server.h | 53 ++++------- esphome/components/web_server_idf/utils.cpp | 41 ++++---- esphome/components/web_server_idf/utils.h | 5 +- .../web_server_idf/web_server_idf.cpp | 52 ++++++++-- .../web_server_idf/web_server_idf.h | 11 +-- 7 files changed, 134 insertions(+), 130 deletions(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 8d88a10b27..5af6ab29a2 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -47,8 +47,8 @@ void CaptivePortal::handle_config(AsyncWebServerRequest *request) { request->send(stream); } void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) { - std::string ssid = request->arg("ssid").c_str(); // NOLINT(readability-redundant-string-cstr) - std::string psk = request->arg("psk").c_str(); // NOLINT(readability-redundant-string-cstr) + const auto &ssid = request->arg("ssid"); + const auto &psk = request->arg("psk"); ESP_LOGI(TAG, "Requested WiFi Settings Change:\n" " SSID='%s'\n" @@ -56,10 +56,10 @@ void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) { ssid.c_str(), psk.c_str()); #ifdef USE_ESP8266 // ESP8266 is single-threaded, call directly - wifi::global_wifi_component->save_wifi_sta(ssid, psk); + wifi::global_wifi_component->save_wifi_sta(ssid.c_str(), psk.c_str()); #else // Defer save to main loop thread to avoid NVS operations from HTTP thread - this->defer([ssid, psk]() { wifi::global_wifi_component->save_wifi_sta(ssid, psk); }); + this->defer([ssid, psk]() { wifi::global_wifi_component->save_wifi_sta(ssid.c_str(), psk.c_str()); }); #endif request->redirect(ESPHOME_F("/?save")); } diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 7da8b49c6d..c7a0639382 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -585,8 +585,7 @@ static void set_json_icon_state_value(JsonObject &root, EntityBase *obj, const c // Helper to get request detail parameter static JsonDetail get_request_detail(AsyncWebServerRequest *request) { - auto *param = request->getParam(ESPHOME_F("detail")); - return (param && param->value() == "all") ? DETAIL_ALL : DETAIL_STATE; + return request->arg(ESPHOME_F("detail")) == "all" ? DETAIL_ALL : DETAIL_STATE; } #ifdef USE_SENSOR @@ -863,10 +862,10 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc } auto call = is_on ? obj->turn_on() : obj->turn_off(); - parse_int_param_(request, ESPHOME_F("speed_level"), call, &decltype(call)::set_speed); + parse_num_param_(request, ESPHOME_F("speed_level"), call, &decltype(call)::set_speed); - if (request->hasParam(ESPHOME_F("oscillation"))) { - auto speed = request->getParam(ESPHOME_F("oscillation"))->value(); + if (request->hasArg(ESPHOME_F("oscillation"))) { + auto speed = request->arg(ESPHOME_F("oscillation")); auto val = parse_on_off(speed.c_str()); switch (val) { case PARSE_ON: @@ -1042,14 +1041,14 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa } auto traits = obj->get_traits(); - if ((request->hasParam(ESPHOME_F("position")) && !traits.get_supports_position()) || - (request->hasParam(ESPHOME_F("tilt")) && !traits.get_supports_tilt())) { + if ((request->hasArg(ESPHOME_F("position")) && !traits.get_supports_position()) || + (request->hasArg(ESPHOME_F("tilt")) && !traits.get_supports_tilt())) { request->send(409); return; } - parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); - parse_float_param_(request, ESPHOME_F("tilt"), call, &decltype(call)::set_tilt); + parse_num_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); + parse_num_param_(request, ESPHOME_F("tilt"), call, &decltype(call)::set_tilt); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1108,7 +1107,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM } auto call = obj->make_call(); - parse_float_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); + parse_num_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1176,12 +1175,13 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat auto call = obj->make_call(); - if (!request->hasParam(ESPHOME_F("value"))) { + const auto &value = request->arg(ESPHOME_F("value")); + // Arduino String has isEmpty() not empty(), use length() for cross-platform compatibility + if (value.length() == 0) { // NOLINT(readability-container-size-empty) request->send(409); return; } - - parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_date); + call.set_date(value.c_str(), value.length()); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1236,12 +1236,13 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat auto call = obj->make_call(); - if (!request->hasParam(ESPHOME_F("value"))) { + const auto &value = request->arg(ESPHOME_F("value")); + // Arduino String has isEmpty() not empty(), use length() for cross-platform compatibility + if (value.length() == 0) { // NOLINT(readability-container-size-empty) request->send(409); return; } - - parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_time); + call.set_time(value.c_str(), value.length()); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1295,12 +1296,13 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur auto call = obj->make_call(); - if (!request->hasParam(ESPHOME_F("value"))) { + const auto &value = request->arg(ESPHOME_F("value")); + // Arduino String has isEmpty() not empty(), use length() for cross-platform compatibility + if (value.length() == 0) { // NOLINT(readability-container-size-empty) request->send(409); return; } - - parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_datetime); + call.set_datetime(value.c_str(), value.length()); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1479,10 +1481,14 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url parse_string_param_(request, ESPHOME_F("swing_mode"), call, &decltype(call)::set_swing_mode); // Parse temperature parameters - parse_float_param_(request, ESPHOME_F("target_temperature_high"), call, - &decltype(call)::set_target_temperature_high); - parse_float_param_(request, ESPHOME_F("target_temperature_low"), call, &decltype(call)::set_target_temperature_low); - parse_float_param_(request, ESPHOME_F("target_temperature"), call, &decltype(call)::set_target_temperature); + // static_cast needed to disambiguate overloaded setters (float vs optional<float>) + using ClimateCall = decltype(call); + parse_num_param_(request, ESPHOME_F("target_temperature_high"), call, + static_cast<ClimateCall &(ClimateCall::*) (float)>(&ClimateCall::set_target_temperature_high)); + parse_num_param_(request, ESPHOME_F("target_temperature_low"), call, + static_cast<ClimateCall &(ClimateCall::*) (float)>(&ClimateCall::set_target_temperature_low)); + parse_num_param_(request, ESPHOME_F("target_temperature"), call, + static_cast<ClimateCall &(ClimateCall::*) (float)>(&ClimateCall::set_target_temperature)); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1723,12 +1729,12 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa } auto traits = obj->get_traits(); - if (request->hasParam(ESPHOME_F("position")) && !traits.get_supports_position()) { + if (request->hasArg(ESPHOME_F("position")) && !traits.get_supports_position()) { request->send(409); return; } - parse_float_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); + parse_num_param_(request, ESPHOME_F("position"), call, &decltype(call)::set_position); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1872,12 +1878,12 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons parse_string_param_(request, ESPHOME_F("mode"), base_call, &water_heater::WaterHeaterCall::set_mode); // Parse temperature parameters - parse_float_param_(request, ESPHOME_F("target_temperature"), base_call, - &water_heater::WaterHeaterCall::set_target_temperature); - parse_float_param_(request, ESPHOME_F("target_temperature_low"), base_call, - &water_heater::WaterHeaterCall::set_target_temperature_low); - parse_float_param_(request, ESPHOME_F("target_temperature_high"), base_call, - &water_heater::WaterHeaterCall::set_target_temperature_high); + parse_num_param_(request, ESPHOME_F("target_temperature"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature); + parse_num_param_(request, ESPHOME_F("target_temperature_low"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature_low); + parse_num_param_(request, ESPHOME_F("target_temperature_high"), base_call, + &water_heater::WaterHeaterCall::set_target_temperature_high); // Parse away mode parameter parse_bool_param_(request, ESPHOME_F("away"), base_call, &water_heater::WaterHeaterCall::set_away); @@ -1981,16 +1987,16 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur auto call = obj->make_call(); // Parse carrier frequency (optional) - if (request->hasParam(ESPHOME_F("carrier_frequency"))) { - auto value = parse_number<uint32_t>(request->getParam(ESPHOME_F("carrier_frequency"))->value().c_str()); + { + auto value = parse_number<uint32_t>(request->arg(ESPHOME_F("carrier_frequency")).c_str()); if (value.has_value()) { call.set_carrier_frequency(*value); } } // Parse repeat count (optional, defaults to 1) - if (request->hasParam(ESPHOME_F("repeat_count"))) { - auto value = parse_number<uint32_t>(request->getParam(ESPHOME_F("repeat_count"))->value().c_str()); + { + auto value = parse_number<uint32_t>(request->arg(ESPHOME_F("repeat_count")).c_str()); if (value.has_value()) { call.set_repeat_count(*value); } @@ -1998,18 +2004,12 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur // Parse base64url-encoded raw timings (required) // Base64url is URL-safe: uses A-Za-z0-9-_ (no special characters needing escaping) - if (!request->hasParam(ESPHOME_F("data"))) { - request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Missing 'data' parameter")); - return; - } + const auto &data_arg = request->arg(ESPHOME_F("data")); - // .c_str() is required for Arduino framework where value() returns Arduino String instead of std::string - std::string encoded = - request->getParam(ESPHOME_F("data"))->value().c_str(); // NOLINT(readability-redundant-string-cstr) - - // Validate base64url is not empty - if (encoded.empty()) { - request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Empty 'data' parameter")); + // Validate base64url is not empty (also catches missing parameter since arg() returns empty string) + // Arduino String has isEmpty() not empty(), use length() for cross-platform compatibility + if (data_arg.length() == 0) { // NOLINT(readability-container-size-empty) + request->send(400, ESPHOME_F("text/plain"), ESPHOME_F("Missing or empty 'data' parameter")); return; } @@ -2017,7 +2017,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur // it outlives the call - set_raw_timings_base64url stores a pointer, so the string // must remain valid until perform() completes. // ESP8266 also needs this because ESPAsyncWebServer callbacks run in "sys" context. - this->defer([call, encoded = std::move(encoded)]() mutable { + this->defer([call, encoded = std::string(data_arg.c_str(), data_arg.length())]() mutable { call.set_raw_timings_base64url(encoded); call.perform(); }); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index ce09ebf7a9..026da763ea 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -513,11 +513,9 @@ class WebServer : public Controller, template<typename T, typename Ret> void parse_light_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(float), float scale = 1.0f) { - if (request->hasParam(param_name)) { - auto value = parse_number<float>(request->getParam(param_name)->value().c_str()); - if (value.has_value()) { - (call.*setter)(*value / scale); - } + auto value = parse_number<float>(request->arg(param_name).c_str()); + if (value.has_value()) { + (call.*setter)(*value / scale); } } @@ -525,34 +523,19 @@ class WebServer : public Controller, template<typename T, typename Ret> void parse_light_param_uint_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(uint32_t), uint32_t scale = 1) { - if (request->hasParam(param_name)) { - auto value = parse_number<uint32_t>(request->getParam(param_name)->value().c_str()); - if (value.has_value()) { - (call.*setter)(*value * scale); - } + auto value = parse_number<uint32_t>(request->arg(param_name).c_str()); + if (value.has_value()) { + (call.*setter)(*value * scale); } } #endif - // Generic helper to parse and apply a float parameter - template<typename T, typename Ret> - void parse_float_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(float)) { - if (request->hasParam(param_name)) { - auto value = parse_number<float>(request->getParam(param_name)->value().c_str()); - if (value.has_value()) { - (call.*setter)(*value); - } - } - } - - // Generic helper to parse and apply an int parameter - template<typename T, typename Ret> - void parse_int_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(int)) { - if (request->hasParam(param_name)) { - auto value = parse_number<int>(request->getParam(param_name)->value().c_str()); - if (value.has_value()) { - (call.*setter)(*value); - } + // Generic helper to parse and apply a numeric parameter + template<typename NumT, typename T, typename Ret> + void parse_num_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(NumT)) { + auto value = parse_number<NumT>(request->arg(param_name).c_str()); + if (value.has_value()) { + (call.*setter)(*value); } } @@ -560,10 +543,9 @@ class WebServer : public Controller, template<typename T, typename Ret> void parse_string_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(const std::string &)) { - if (request->hasParam(param_name)) { - // .c_str() is required for Arduino framework where value() returns Arduino String instead of std::string - std::string value = request->getParam(param_name)->value().c_str(); // NOLINT(readability-redundant-string-cstr) - (call.*setter)(value); + if (request->hasArg(param_name)) { + const auto &value = request->arg(param_name); + (call.*setter)(std::string(value.c_str(), value.length())); } } @@ -573,8 +555,9 @@ class WebServer : public Controller, // Invalid values are ignored (setter not called) template<typename T, typename Ret> void parse_bool_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, Ret (T::*setter)(bool)) { - if (request->hasParam(param_name)) { - auto param_value = request->getParam(param_name)->value(); + const auto ¶m_value = request->arg(param_name); + // Arduino String has isEmpty() not empty(), use length() for cross-platform compatibility + if (param_value.length() > 0) { // NOLINT(readability-container-size-empty) // First check on/off (default), then true/false (custom) auto val = parse_on_off(param_value.c_str()); if (val == PARSE_NONE) { diff --git a/esphome/components/web_server_idf/utils.cpp b/esphome/components/web_server_idf/utils.cpp index 81ae626277..c58ca2a24f 100644 --- a/esphome/components/web_server_idf/utils.cpp +++ b/esphome/components/web_server_idf/utils.cpp @@ -1,17 +1,13 @@ #ifdef USE_ESP32 -#include <memory> #include <cstring> #include <cctype> #include "esphome/core/helpers.h" -#include "esphome/core/log.h" #include "http_parser.h" #include "utils.h" namespace esphome::web_server_idf { -static const char *const TAG = "web_server_idf_utils"; - size_t url_decode(char *str) { char *start = str; char *ptr = str, buf; @@ -54,32 +50,15 @@ optional<std::string> request_get_header(httpd_req_t *req, const char *name) { return {str}; } -optional<std::string> request_get_url_query(httpd_req_t *req) { - auto len = httpd_req_get_url_query_len(req); - if (len == 0) { - return {}; - } - - std::string str; - str.resize(len); - - auto res = httpd_req_get_url_query_str(req, &str[0], len + 1); - if (res != ESP_OK) { - ESP_LOGW(TAG, "Can't get query for request: %s", esp_err_to_name(res)); - return {}; - } - - return {str}; -} - optional<std::string> query_key_value(const char *query_url, size_t query_len, const char *key) { if (query_url == nullptr || query_len == 0) { return {}; } - // Use stack buffer for typical query strings, heap fallback for large ones - SmallBufferWithHeapFallback<256, char> val(query_len); - + // Value can't exceed query_len. Use small stack buffer for typical values, + // heap fallback for long ones (e.g. base64 IR data) to limit stack usage + // since callers may also have stack buffers for the query string. + SmallBufferWithHeapFallback<128, char> val(query_len); if (httpd_query_key_value(query_url, key, val.get(), query_len) != ESP_OK) { return {}; } @@ -88,6 +67,18 @@ optional<std::string> query_key_value(const char *query_url, size_t query_len, c return {val.get()}; } +bool query_has_key(const char *query_url, size_t query_len, const char *key) { + if (query_url == nullptr || query_len == 0) { + return false; + } + // Minimal buffer — we only care if the key exists, not the value + char buf[1]; + // httpd_query_key_value returns ESP_OK if found, ESP_ERR_HTTPD_RESULT_TRUNC if found + // but value truncated (expected with 1-byte buffer), or other errors for invalid input + auto err = httpd_query_key_value(query_url, key, buf, sizeof(buf)); + return err == ESP_OK || err == ESP_ERR_HTTPD_RESULT_TRUNC; +} + // Helper function for case-insensitive string region comparison bool str_ncmp_ci(const char *s1, const char *s2, size_t n) { for (size_t i = 0; i < n; i++) { diff --git a/esphome/components/web_server_idf/utils.h b/esphome/components/web_server_idf/utils.h index 87635c0458..027a2f7b6c 100644 --- a/esphome/components/web_server_idf/utils.h +++ b/esphome/components/web_server_idf/utils.h @@ -13,11 +13,8 @@ size_t url_decode(char *str); bool request_has_header(httpd_req_t *req, const char *name); optional<std::string> request_get_header(httpd_req_t *req, const char *name); -optional<std::string> request_get_url_query(httpd_req_t *req); optional<std::string> query_key_value(const char *query_url, size_t query_len, const char *key); -inline optional<std::string> query_key_value(const std::string &query_url, const std::string &key) { - return query_key_value(query_url.c_str(), query_url.size(), key.c_str()); -} +bool query_has_key(const char *query_url, size_t query_len, const char *key); // Helper function for case-insensitive character comparison inline bool char_equals_ci(char a, char b) { return ::tolower(a) == ::tolower(b); } diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index f1f89beb49..1798159e7f 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -393,13 +393,7 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const char *name) { } // Look up value from query strings - optional<std::string> val = query_key_value(this->post_query_.c_str(), this->post_query_.size(), name); - if (!val.has_value()) { - auto url_query = request_get_url_query(*this); - if (url_query.has_value()) { - val = query_key_value(url_query.value().c_str(), url_query.value().size(), name); - } - } + auto val = this->find_query_value_(name); // Don't cache misses to avoid wasting memory when handlers check for // optional parameters that don't exist in the request @@ -412,6 +406,50 @@ AsyncWebParameter *AsyncWebServerRequest::getParam(const char *name) { return param; } +/// Search post_query then URL query with a callback. +/// Returns first truthy result, or value-initialized default. +/// URL query is accessed directly from req->uri (same pattern as url_to()). +template<typename Func> +static auto search_query_sources(httpd_req_t *req, const std::string &post_query, const char *name, Func func) + -> decltype(func(nullptr, size_t{0}, name)) { + if (!post_query.empty()) { + auto result = func(post_query.c_str(), post_query.size(), name); + if (result) { + return result; + } + } + // Use httpd API for query length, then access string directly from URI. + // http_parser identifies components by offset/length without modifying the URI string. + // This is the same pattern used by url_to(). + auto len = httpd_req_get_url_query_len(req); + if (len == 0) { + return {}; + } + const char *query = strchr(req->uri, '?'); + if (query == nullptr) { + return {}; + } + query++; // skip '?' + return func(query, len, name); +} + +optional<std::string> AsyncWebServerRequest::find_query_value_(const char *name) const { + return search_query_sources(this->req_, this->post_query_, name, + [](const char *q, size_t len, const char *k) { return query_key_value(q, len, k); }); +} + +bool AsyncWebServerRequest::hasArg(const char *name) { + return search_query_sources(this->req_, this->post_query_, name, query_has_key); +} + +std::string AsyncWebServerRequest::arg(const char *name) { + auto val = this->find_query_value_(name); + if (val.has_value()) { + return std::move(val.value()); + } + return {}; +} + void AsyncWebServerResponse::addHeader(const char *name, const char *value) { httpd_resp_set_hdr(*this->req_, name, value); } diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 6a409de74e..12df0303de 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -170,14 +170,8 @@ class AsyncWebServerRequest { AsyncWebParameter *getParam(const std::string &name) { return this->getParam(name.c_str()); } // NOLINTNEXTLINE(readability-identifier-naming) - bool hasArg(const char *name) { return this->hasParam(name); } - std::string arg(const char *name) { - auto *param = this->getParam(name); - if (param) { - return param->value(); - } - return {}; - } + bool hasArg(const char *name); + std::string arg(const char *name); std::string arg(const std::string &name) { return this->arg(name.c_str()); } operator httpd_req_t *() const { return this->req_; } @@ -192,6 +186,7 @@ class AsyncWebServerRequest { // is faster than tree/hash overhead. AsyncWebParameter stores both name and value to avoid // duplicate storage. Only successful lookups are cached to prevent cache pollution when // handlers check for optional parameters that don't exist. + optional<std::string> find_query_value_(const char *name) const; std::vector<AsyncWebParameter *> params_; std::string post_query_; AsyncWebServerRequest(httpd_req_t *req) : req_(req) {} From 0dcff82bb479b131a4dbb33d00940c7a91120dc2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 11:14:36 -0600 Subject: [PATCH 0692/2030] [wifi] Deprecate wifi_ssid() in favor of wifi_ssid_to() (#13958) --- esphome/components/wifi/wifi_component.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index ac28a1bc81..53ff0d9cad 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -502,6 +502,8 @@ class WiFiComponent : public Component { } network::IPAddresses wifi_sta_ip_addresses(); + // Remove before 2026.9.0 + ESPDEPRECATED("Use wifi_ssid_to() instead. Removed in 2026.9.0", "2026.3.0") std::string wifi_ssid(); /// Write SSID to buffer without heap allocation. /// Returns pointer to buffer, or empty string if not connected. From e3a457e40268949364f776fd5ec3ff5fd833a443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Ma=C5=88as?= <lukas.manas@gmail.com> Date: Thu, 12 Feb 2026 18:20:54 +0100 Subject: [PATCH 0693/2030] [pulse_meter] Fix early edge detection (#12360) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../pulse_meter/pulse_meter_sensor.cpp | 75 ++++++++++--------- .../pulse_meter/pulse_meter_sensor.h | 11 ++- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 007deb66e5..433e1f0b7e 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -38,8 +38,7 @@ void PulseMeterSensor::setup() { } void PulseMeterSensor::loop() { - // Reset the count in get before we pass it back to the ISR as set - this->get_->count_ = 0; + State state; { // Lock the interrupt so the interrupt code doesn't interfere with itself @@ -58,31 +57,35 @@ void PulseMeterSensor::loop() { } this->last_pin_val_ = current; - // Swap out set and get to get the latest state from the ISR - std::swap(this->set_, this->get_); + // Get the latest state from the ISR and reset the count in the ISR + state.last_detected_edge_us_ = this->state_.last_detected_edge_us_; + state.last_rising_edge_us_ = this->state_.last_rising_edge_us_; + state.count_ = this->state_.count_; + this->state_.count_ = 0; } const uint32_t now = micros(); // If an edge was peeked, repay the debt - if (this->peeked_edge_ && this->get_->count_ > 0) { + if (this->peeked_edge_ && state.count_ > 0) { this->peeked_edge_ = false; - this->get_->count_--; // NOLINT(clang-diagnostic-deprecated-volatile) + state.count_--; } - // If there is an unprocessed edge, and filter_us_ has passed since, count this edge early - if (this->get_->last_rising_edge_us_ != this->get_->last_detected_edge_us_ && - now - this->get_->last_rising_edge_us_ >= this->filter_us_) { + // If there is an unprocessed edge, and filter_us_ has passed since, count this edge early. + // Wait for the debt to be repaid before counting another unprocessed edge early. + if (!this->peeked_edge_ && state.last_rising_edge_us_ != state.last_detected_edge_us_ && + now - state.last_rising_edge_us_ >= this->filter_us_) { this->peeked_edge_ = true; - this->get_->last_detected_edge_us_ = this->get_->last_rising_edge_us_; - this->get_->count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + state.last_detected_edge_us_ = state.last_rising_edge_us_; + state.count_++; } // Check if we detected a pulse this loop - if (this->get_->count_ > 0) { + if (state.count_ > 0) { // Keep a running total of pulses if a total sensor is configured if (this->total_sensor_ != nullptr) { - this->total_pulses_ += this->get_->count_; + this->total_pulses_ += state.count_; const uint32_t total = this->total_pulses_; this->total_sensor_->publish_state(total); } @@ -94,15 +97,15 @@ void PulseMeterSensor::loop() { this->meter_state_ = MeterState::RUNNING; } break; case MeterState::RUNNING: { - uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_; - float pulse_width_us = delta_us / float(this->get_->count_); - ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us, - this->get_->count_, pulse_width_us); + uint32_t delta_us = state.last_detected_edge_us_ - this->last_processed_edge_us_; + float pulse_width_us = delta_us / float(state.count_); + ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us, state.count_, + pulse_width_us); this->publish_state((60.0f * 1000000.0f) / pulse_width_us); } break; } - this->last_processed_edge_us_ = this->get_->last_detected_edge_us_; + this->last_processed_edge_us_ = state.last_detected_edge_us_; } // No detected edges this loop else { @@ -141,14 +144,14 @@ void IRAM_ATTR PulseMeterSensor::edge_intr(PulseMeterSensor *sensor) { // This is an interrupt handler - we can't call any virtual method from this method // Get the current time before we do anything else so the measurements are consistent const uint32_t now = micros(); - auto &state = sensor->edge_state_; - auto &set = *sensor->set_; + auto &edge_state = sensor->edge_state_; + auto &state = sensor->state_; - if ((now - state.last_sent_edge_us_) >= sensor->filter_us_) { - state.last_sent_edge_us_ = now; - set.last_detected_edge_us_ = now; - set.last_rising_edge_us_ = now; - set.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + if ((now - edge_state.last_sent_edge_us_) >= sensor->filter_us_) { + edge_state.last_sent_edge_us_ = now; + state.last_detected_edge_us_ = now; + state.last_rising_edge_us_ = now; + state.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) } // This ISR is bound to rising edges, so the pin is high @@ -160,26 +163,26 @@ void IRAM_ATTR PulseMeterSensor::pulse_intr(PulseMeterSensor *sensor) { // Get the current time before we do anything else so the measurements are consistent const uint32_t now = micros(); const bool pin_val = sensor->isr_pin_.digital_read(); - auto &state = sensor->pulse_state_; - auto &set = *sensor->set_; + auto &pulse_state = sensor->pulse_state_; + auto &state = sensor->state_; // Filter length has passed since the last interrupt - const bool length = now - state.last_intr_ >= sensor->filter_us_; + const bool length = now - pulse_state.last_intr_ >= sensor->filter_us_; - if (length && state.latched_ && !sensor->last_pin_val_) { // Long enough low edge - state.latched_ = false; - } else if (length && !state.latched_ && sensor->last_pin_val_) { // Long enough high edge - state.latched_ = true; - set.last_detected_edge_us_ = state.last_intr_; - set.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + if (length && pulse_state.latched_ && !sensor->last_pin_val_) { // Long enough low edge + pulse_state.latched_ = false; + } else if (length && !pulse_state.latched_ && sensor->last_pin_val_) { // Long enough high edge + pulse_state.latched_ = true; + state.last_detected_edge_us_ = pulse_state.last_intr_; + state.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) } // Due to order of operations this includes // length && latched && rising (just reset from a long low edge) // !latched && (rising || high) (noise on the line resetting the potential rising edge) - set.last_rising_edge_us_ = !state.latched_ && pin_val ? now : set.last_detected_edge_us_; + state.last_rising_edge_us_ = !pulse_state.latched_ && pin_val ? now : state.last_detected_edge_us_; - state.last_intr_ = now; + pulse_state.last_intr_ = now; sensor->last_pin_val_ = pin_val; } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index 5800c4ec42..e46f1e615f 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -46,17 +46,16 @@ class PulseMeterSensor : public sensor::Sensor, public Component { uint32_t total_pulses_ = 0; uint32_t last_processed_edge_us_ = 0; - // This struct (and the two pointers) are used to pass data between the ISR and loop. - // These two pointers are exchanged each loop. - // Use these to send data from the ISR to the loop not the other way around (except for resetting the values). + // This struct and variable are used to pass data between the ISR and loop. + // The data from state_ is read and then count_ in state_ is reset in each loop. + // This must be done while guarded by an InterruptLock. Use this variable to send data + // from the ISR to the loop not the other way around (except for resetting count_). struct State { uint32_t last_detected_edge_us_ = 0; uint32_t last_rising_edge_us_ = 0; uint32_t count_ = 0; }; - State state_[2]; - volatile State *set_ = state_; - volatile State *get_ = state_ + 1; + volatile State state_{}; // Only use the following variables in the ISR or while guarded by an InterruptLock ISRInternalGPIOPin isr_pin_; From 7fd535179e4cc793047ebcf802b0fe174b3987cb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 11:47:44 -0600 Subject: [PATCH 0694/2030] [helpers] Add heap warnings to format_hex_pretty, deprecate ethernet/web_server std::string APIs (#13959) --- .../components/ethernet/ethernet_component.h | 2 ++ .../components/web_server_idf/web_server_idf.h | 3 ++- esphome/core/helpers.h | 18 ++++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 5a2869c5a7..b4859c308d 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -110,6 +110,8 @@ class EthernetComponent : public Component { const char *get_use_address() const; void set_use_address(const char *use_address); void get_eth_mac_address_raw(uint8_t *mac); + // Remove before 2026.9.0 + ESPDEPRECATED("Use get_eth_mac_address_pretty_into_buffer() instead. Removed in 2026.9.0", "2026.3.0") std::string get_eth_mac_address_pretty(); const char *get_eth_mac_address_pretty_into_buffer(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf); eth_duplex_t get_duplex_mode(); diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 12df0303de..74601ffda8 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -116,7 +116,8 @@ class AsyncWebServerRequest { /// Write URL (without query string) to buffer, returns StringRef pointing to buffer. /// URL is decoded (e.g., %20 -> space). StringRef url_to(std::span<char, URL_BUF_SIZE> buffer) const; - /// Get URL as std::string. Prefer url_to() to avoid heap allocation. + // Remove before 2026.9.0 + ESPDEPRECATED("Use url_to() instead. Removed in 2026.9.0", "2026.3.0") std::string url() const { char buffer[URL_BUF_SIZE]; return std::string(this->url_to(buffer)); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index f7de34b6d5..34c7452484 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1083,6 +1083,9 @@ template<std::size_t N> std::string format_hex(const std::array<uint8_t, N> &dat * Each byte is displayed as a two-digit uppercase hex value, separated by the specified separator. * Optionally includes the total byte count in parentheses at the end. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @param data Pointer to the byte array to format. * @param length Number of bytes in the array. * @param separator Character to use between hex bytes (default: '.'). @@ -1108,6 +1111,9 @@ std::string format_hex_pretty(const uint8_t *data, size_t length, char separator * * Similar to the byte array version, but formats 16-bit words as 4-digit hex values. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @param data Pointer to the 16-bit word array to format. * @param length Number of 16-bit words in the array. * @param separator Character to use between hex words (default: '.'). @@ -1131,6 +1137,9 @@ std::string format_hex_pretty(const uint16_t *data, size_t length, char separato * Convenience overload for std::vector<uint8_t>. Formats each byte as a two-digit * uppercase hex value with customizable separator. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @param data Vector of bytes to format. * @param separator Character to use between hex bytes (default: '.'). * @param show_length Whether to append the byte count in parentheses (default: true). @@ -1154,6 +1163,9 @@ std::string format_hex_pretty(const std::vector<uint8_t> &data, char separator = * Convenience overload for std::vector<uint16_t>. Each 16-bit word is formatted * as a 4-digit uppercase hex value in big-endian order. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @param data Vector of 16-bit words to format. * @param separator Character to use between hex words (default: '.'). * @param show_length Whether to append the word count in parentheses (default: true). @@ -1176,6 +1188,9 @@ std::string format_hex_pretty(const std::vector<uint16_t> &data, char separator * Treats each character in the string as a byte and formats it in hex. * Useful for debugging binary data stored in std::string containers. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @param data String whose bytes should be formatted as hex. * @param separator Character to use between hex bytes (default: '.'). * @param show_length Whether to append the byte count in parentheses (default: true). @@ -1198,6 +1213,9 @@ std::string format_hex_pretty(const std::string &data, char separator = '.', boo * Converts the integer to big-endian byte order and formats each byte as hex. * The most significant byte appears first in the output string. * + * @warning Allocates heap memory. Use format_hex_pretty_to() with a stack buffer instead. + * Causes heap fragmentation on long-running devices. + * * @tparam T Unsigned integer type (uint8_t, uint16_t, uint32_t, uint64_t, etc.). * @param val The unsigned integer value to format. * @param separator Character to use between hex bytes (default: '.'). From bbc88d92ea0c30efd12d11a27edfe50ea618e299 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:31:43 -0600 Subject: [PATCH 0695/2030] Bump docker/build-push-action from 6.19.1 to 6.19.2 in /.github/actions/build-image (#13965) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 494304eced..38e93c4f17 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -47,7 +47,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false @@ -73,7 +73,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@601a80b39c9405e50806ae38af30926f9d957c47 # v6.19.1 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false From db7870ef5fb3f7fce20f897f7c6279f82695e8c9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:04:39 -0500 Subject: [PATCH 0696/2030] [alarm_control_panel] Fix flaky integration test race condition (#13964) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- ...t_alarm_control_panel_state_transitions.py | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/integration/test_alarm_control_panel_state_transitions.py b/tests/integration/test_alarm_control_panel_state_transitions.py index 09348f5bea..0b07710961 100644 --- a/tests/integration/test_alarm_control_panel_state_transitions.py +++ b/tests/integration/test_alarm_control_panel_state_transitions.py @@ -270,6 +270,14 @@ async def test_alarm_control_panel_state_transitions( # The chime_sensor has chime: true, so opening it while disarmed # should trigger on_chime callback + # Set up future for the on_ready from opening the chime sensor + # (alarm becomes "not ready" when chime sensor opens). + # We must wait for this BEFORE creating the close future, otherwise + # the open event's log can arrive late and resolve the close future, + # causing the test to proceed before the chime close is processed. + ready_after_chime_open: asyncio.Future[bool] = loop.create_future() + ready_futures.append(ready_after_chime_open) + # We're currently DISARMED - open the chime sensor client.switch_command(chime_switch_info.key, True) @@ -279,11 +287,18 @@ async def test_alarm_control_panel_state_transitions( except TimeoutError: pytest.fail(f"on_chime callback not fired. Log lines: {log_lines[-20:]}") - # Close the chime sensor and wait for alarm to become ready again - # We need to wait for this transition before testing door sensor, - # otherwise there's a race where the door sensor state change could - # arrive before the chime sensor state change, leaving the alarm in - # a continuous "not ready" state with no on_ready callback fired. + # Wait for the on_ready from the chime sensor opening + try: + await asyncio.wait_for(ready_after_chime_open, timeout=2.0) + except TimeoutError: + pytest.fail( + f"on_ready callback not fired when chime sensor opened. " + f"Log lines: {log_lines[-20:]}" + ) + + # Now create the future for the close event and close the sensor. + # Since we waited for the open event above, the close event's + # on_ready log cannot be confused with the open event's. ready_after_chime_close: asyncio.Future[bool] = loop.create_future() ready_futures.append(ready_after_chime_close) From 136d17366f5ab2a08912ce2f6a5459eea358ec24 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:12:17 -0500 Subject: [PATCH 0697/2030] [docker] Suppress git detached HEAD advice (#13962) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8ebdd1e49b..540d28be7f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,7 +9,8 @@ FROM ghcr.io/esphome/docker-base:${BUILD_OS}-ha-addon-${BUILD_BASE_VERSION} AS b ARG BUILD_TYPE FROM base-source-${BUILD_TYPE} AS base -RUN git config --system --add safe.directory "*" +RUN git config --system --add safe.directory "*" \ + && git config --system advice.detachedHead false # Install build tools for Python packages that require compilation # (e.g., ruamel.yaml.clibz used by ESP-IDF's idf-component-manager) From 36aba385af3f502462f1a38fb6c334e580ad7155 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 18:20:21 -0600 Subject: [PATCH 0698/2030] [web_server] Flatten deq_push_back_with_dedup_ to inline vector realloc (#13968) --- esphome/components/web_server/web_server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index c7a0639382..3acd2d2119 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -198,7 +198,8 @@ EntityMatchResult UrlMatch::match_entity(EntityBase *entity) const { #if !defined(USE_ESP32) && defined(USE_ARDUINO) // helper for allowing only unique entries in the queue -void DeferredUpdateEventSource::deq_push_back_with_dedup_(void *source, message_generator_t *message_generator) { +void __attribute__((flatten)) +DeferredUpdateEventSource::deq_push_back_with_dedup_(void *source, message_generator_t *message_generator) { DeferredEvent item(source, message_generator); // Use range-based for loop instead of std::find_if to reduce template instantiation overhead and binary size From 7dff631dcb133e69a26d841a1f0645cac812202a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 18:20:39 -0600 Subject: [PATCH 0699/2030] [core] Flatten single-callsite vector realloc functions (#13970) --- esphome/components/api/api_connection.cpp | 6 ++++-- esphome/components/api/api_connection.h | 2 ++ esphome/components/api/api_server.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 13 +++++++++++++ esphome/components/wifi/wifi_component.h | 13 +------------ 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 4bc3c9b307..4d564af9e2 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1864,6 +1864,8 @@ void APIConnection::on_fatal_error() { this->flags_.remove = true; } +void __attribute__((flatten)) APIConnection::DeferredBatch::push_item(const BatchItem &item) { items.push_back(item); } + void APIConnection::DeferredBatch::add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, uint8_t aux_data_index) { // Check if we already have a message of this type for this entity @@ -1880,7 +1882,7 @@ void APIConnection::DeferredBatch::add_item(EntityBase *entity, uint8_t message_ } } // No existing item found (or event), add new one - items.push_back({entity, message_type, estimated_size, aux_data_index}); + this->push_item({entity, message_type, estimated_size, aux_data_index}); } void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { @@ -1888,7 +1890,7 @@ void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t me // This avoids expensive vector::insert which shifts all elements // Note: We only ever have one high-priority message at a time (ping OR disconnect) // If we're disconnecting, pings are blocked, so this simple swap is sufficient - items.push_back({entity, message_type, estimated_size, AUX_DATA_UNUSED}); + this->push_item({entity, message_type, estimated_size, AUX_DATA_UNUSED}); if (items.size() > 1) { // Swap the new high-priority item to the front std::swap(items.front(), items.back()); diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index d3d09a01c8..e34bed8ada 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -541,6 +541,8 @@ class APIConnection final : public APIServerConnectionBase { uint8_t aux_data_index = AUX_DATA_UNUSED); // Add item to the front of the batch (for high priority messages like ping) void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size); + // Single push_back site to avoid duplicate _M_realloc_insert instantiation + void push_item(const BatchItem &item); // Clear all items void clear() { diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 5503cf4db8..211bda66de 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -195,7 +195,7 @@ void APIServer::remove_client_(size_t client_index) { #endif } -void APIServer::accept_new_connections_() { +void __attribute__((flatten)) APIServer::accept_new_connections_() { while (true) { struct sockaddr_storage source_addr; socklen_t addr_len = sizeof(source_addr); diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 61d05d7635..a2efac8d26 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -487,6 +487,19 @@ bool WiFiComponent::matches_configured_network_(const char *ssid, const uint8_t return false; } +void __attribute__((flatten)) WiFiComponent::set_sta_priority(bssid_t bssid, int8_t priority) { + for (auto &it : this->sta_priorities_) { + if (it.bssid == bssid) { + it.priority = priority; + return; + } + } + this->sta_priorities_.push_back(WiFiSTAPriority{ + .bssid = bssid, + .priority = priority, + }); +} + void WiFiComponent::log_discarded_scan_result_(const char *ssid, const uint8_t *bssid, int8_t rssi, uint8_t channel) { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE // Skip logging during roaming scans to avoid log buffer overflow diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 53ff0d9cad..4a038f602c 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -488,18 +488,7 @@ class WiFiComponent : public Component { } return 0; } - void set_sta_priority(const bssid_t bssid, int8_t priority) { - for (auto &it : this->sta_priorities_) { - if (it.bssid == bssid) { - it.priority = priority; - return; - } - } - this->sta_priorities_.push_back(WiFiSTAPriority{ - .bssid = bssid, - .priority = priority, - }); - } + void set_sta_priority(bssid_t bssid, int8_t priority); network::IPAddresses wifi_sta_ip_addresses(); // Remove before 2026.9.0 From e0c03b2dfa39021bcff1805376ce53dde1e8bbdf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 18:20:58 -0600 Subject: [PATCH 0700/2030] [api] Fix ESP8266 noise API handshake deadlock and prompt socket cleanup (#13972) --- esphome/components/api/api_frame_helper_noise.cpp | 10 ++++++---- esphome/components/api/api_server.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index c1641b398a..1ae848dead 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -138,10 +138,12 @@ APIError APINoiseFrameHelper::handle_noise_error_(int err, const LogString *func /// Run through handshake messages (if in that phase) APIError APINoiseFrameHelper::loop() { - // During handshake phase, process as many actions as possible until we can't progress - // socket_->ready() stays true until next main loop, but state_action() will return - // WOULD_BLOCK when no more data is available to read - while (state_ != State::DATA && this->socket_->ready()) { + // Cache ready() outside the loop. On ESP8266 LWIP raw TCP, ready() returns false once + // the rx buffer is consumed. Re-checking each iteration would block handshake writes + // that must follow reads, deadlocking the handshake. state_action() will return + // WOULD_BLOCK when no more data is available to read. + bool socket_ready = this->socket_->ready(); + while (state_ != State::DATA && socket_ready) { APIError err = state_action_(); if (err == APIError::WOULD_BLOCK) { break; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 211bda66de..f25a9bc0e2 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -148,12 +148,16 @@ void APIServer::loop() { while (client_index < this->clients_.size()) { auto &client = this->clients_[client_index]; + // Common case: process active client + if (!client->flags_.remove) { + client->loop(); + } + // Handle disconnection promptly - close socket to free LWIP PCB + // resources and prevent retransmit crashes on ESP8266. if (client->flags_.remove) { // Rare case: handle disconnection (don't increment - swapped element needs processing) this->remove_client_(client_index); } else { - // Common case: process active client - client->loop(); client_index++; } } From b04e427f01974947856793b0a53425cccfe180bc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Feb 2026 06:39:00 -0600 Subject: [PATCH 0701/2030] [usb_host] Extract cold path from loop(), replace std::string with buffer API (#13957) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/usb_host/usb_host.h | 1 + .../components/usb_host/usb_host_client.cpp | 123 ++++++++++-------- 2 files changed, 67 insertions(+), 57 deletions(-) diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index d11a148a0f..d1ec356613 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -148,6 +148,7 @@ class USBClient : public Component { EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE> event_pool; protected: + void handle_open_state_(); TransferRequest *get_trq_(); // Lock-free allocation using atomic bitmask (multi-consumer safe) virtual void disconnect(); virtual void on_connected() {} diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 09da6e3b73..0612d7a841 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -9,6 +9,7 @@ #include <cinttypes> #include <cstring> #include <atomic> +#include <span> namespace esphome { namespace usb_host { @@ -142,18 +143,23 @@ static void usb_client_print_config_descriptor(const usb_config_desc_t *cfg_desc } while (next_desc != NULL); } #endif -static std::string get_descriptor_string(const usb_str_desc_t *desc) { - char buffer[256]; - if (desc == nullptr) +// USB string descriptors: bLength (uint8_t, max 255) includes the 2-byte header (bLength and bDescriptorType). +// Character count = (bLength - 2) / 2, max 126 chars + null terminator. +static constexpr size_t DESC_STRING_BUF_SIZE = 128; + +static const char *get_descriptor_string(const usb_str_desc_t *desc, std::span<char, DESC_STRING_BUF_SIZE> buffer) { + if (desc == nullptr || desc->bLength < 2) return "(unspecified)"; - char *p = buffer; - for (int i = 0; i != desc->bLength / 2; i++) { + int char_count = (desc->bLength - 2) / 2; + char *p = buffer.data(); + char *end = p + buffer.size() - 1; + for (int i = 0; i != char_count && p < end; i++) { auto c = desc->wData[i]; if (c < 0x100) *p++ = static_cast<char>(c); } *p = '\0'; - return {buffer}; + return buffer.data(); } // CALLBACK CONTEXT: USB task (called from usb_host_client_handle_events in USB task) @@ -259,60 +265,63 @@ void USBClient::loop() { ESP_LOGW(TAG, "Dropped %u USB events due to queue overflow", dropped); } - switch (this->state_) { - case USB_CLIENT_OPEN: { - int err; - ESP_LOGD(TAG, "Open device %d", this->device_addr_); - err = usb_host_device_open(this->handle_, this->device_addr_, &this->device_handle_); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Device open failed: %s", esp_err_to_name(err)); - this->state_ = USB_CLIENT_INIT; - break; - } - ESP_LOGD(TAG, "Get descriptor device %d", this->device_addr_); - const usb_device_desc_t *desc; - err = usb_host_get_device_descriptor(this->device_handle_, &desc); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Device get_desc failed: %s", esp_err_to_name(err)); - this->disconnect(); - } else { - ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct); - if (desc->idVendor == this->vid_ && desc->idProduct == this->pid_ || this->vid_ == 0 && this->pid_ == 0) { - usb_device_info_t dev_info; - err = usb_host_device_info(this->device_handle_, &dev_info); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err)); - this->disconnect(); - break; - } - this->state_ = USB_CLIENT_CONNECTED; - ESP_LOGD(TAG, "Device connected: Manuf: %s; Prod: %s; Serial: %s", - get_descriptor_string(dev_info.str_desc_manufacturer).c_str(), - get_descriptor_string(dev_info.str_desc_product).c_str(), - get_descriptor_string(dev_info.str_desc_serial_num).c_str()); + if (this->state_ == USB_CLIENT_OPEN) { + this->handle_open_state_(); + } +} + +void USBClient::handle_open_state_() { + int err; + ESP_LOGD(TAG, "Open device %d", this->device_addr_); + err = usb_host_device_open(this->handle_, this->device_addr_, &this->device_handle_); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Device open failed: %s", esp_err_to_name(err)); + this->state_ = USB_CLIENT_INIT; + return; + } + ESP_LOGD(TAG, "Get descriptor device %d", this->device_addr_); + const usb_device_desc_t *desc; + err = usb_host_get_device_descriptor(this->device_handle_, &desc); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Device get_desc failed: %s", esp_err_to_name(err)); + this->disconnect(); + return; + } + ESP_LOGD(TAG, "Device descriptor: vid %X pid %X", desc->idVendor, desc->idProduct); + if (desc->idVendor != this->vid_ || desc->idProduct != this->pid_) { + if (this->vid_ != 0 || this->pid_ != 0) { + ESP_LOGD(TAG, "Not our device, closing"); + this->disconnect(); + return; + } + } + usb_device_info_t dev_info; + err = usb_host_device_info(this->device_handle_, &dev_info); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Device info failed: %s", esp_err_to_name(err)); + this->disconnect(); + return; + } + this->state_ = USB_CLIENT_CONNECTED; + char buf_manuf[DESC_STRING_BUF_SIZE]; + char buf_product[DESC_STRING_BUF_SIZE]; + char buf_serial[DESC_STRING_BUF_SIZE]; + ESP_LOGD(TAG, "Device connected: Manuf: %s; Prod: %s; Serial: %s", + get_descriptor_string(dev_info.str_desc_manufacturer, buf_manuf), + get_descriptor_string(dev_info.str_desc_product, buf_product), + get_descriptor_string(dev_info.str_desc_serial_num, buf_serial)); #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE - const usb_device_desc_t *device_desc; - err = usb_host_get_device_descriptor(this->device_handle_, &device_desc); - if (err == ESP_OK) - usb_client_print_device_descriptor(device_desc); - const usb_config_desc_t *config_desc; - err = usb_host_get_active_config_descriptor(this->device_handle_, &config_desc); - if (err == ESP_OK) - usb_client_print_config_descriptor(config_desc, nullptr); + const usb_device_desc_t *device_desc; + err = usb_host_get_device_descriptor(this->device_handle_, &device_desc); + if (err == ESP_OK) + usb_client_print_device_descriptor(device_desc); + const usb_config_desc_t *config_desc; + err = usb_host_get_active_config_descriptor(this->device_handle_, &config_desc); + if (err == ESP_OK) + usb_client_print_config_descriptor(config_desc, nullptr); #endif - this->on_connected(); - } else { - ESP_LOGD(TAG, "Not our device, closing"); - this->disconnect(); - } - } - break; - } - - default: - break; - } + this->on_connected(); } void USBClient::on_opened(uint8_t addr) { From 903971de12c1b291ca8cd367ce5cdf9af8b304ae Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Fri, 13 Feb 2026 10:25:43 -0600 Subject: [PATCH 0702/2030] [runtime_image, online_image] Create runtime_image component to decode images (#10212) --- CODEOWNERS | 1 + esphome/components/online_image/__init__.py | 119 +----- ...{image_decoder.cpp => download_buffer.cpp} | 38 +- .../components/online_image/download_buffer.h | 44 ++ .../components/online_image/online_image.cpp | 396 ++++++------------ .../components/online_image/online_image.h | 135 +----- esphome/components/runtime_image/__init__.py | 191 +++++++++ .../bmp_decoder.cpp} | 28 +- .../bmp_decoder.h} | 22 +- .../runtime_image/image_decoder.cpp | 28 ++ .../image_decoder.h | 72 ++-- .../jpeg_decoder.cpp} | 49 ++- .../jpeg_decoder.h} | 17 +- .../png_decoder.cpp} | 25 +- .../png_decoder.h} | 19 +- .../runtime_image/runtime_image.cpp | 300 +++++++++++++ .../components/runtime_image/runtime_image.h | 214 ++++++++++ esphome/core/defines.h | 6 +- 18 files changed, 1075 insertions(+), 629 deletions(-) rename esphome/components/online_image/{image_decoder.cpp => download_buffer.cpp} (52%) create mode 100644 esphome/components/online_image/download_buffer.h create mode 100644 esphome/components/runtime_image/__init__.py rename esphome/components/{online_image/bmp_image.cpp => runtime_image/bmp_decoder.cpp} (82%) rename esphome/components/{online_image/bmp_image.h => runtime_image/bmp_decoder.h} (52%) create mode 100644 esphome/components/runtime_image/image_decoder.cpp rename esphome/components/{online_image => runtime_image}/image_decoder.h (60%) rename esphome/components/{online_image/jpeg_image.cpp => runtime_image/jpeg_decoder.cpp} (69%) rename esphome/components/{online_image/jpeg_image.h => runtime_image/jpeg_decoder.h} (54%) rename esphome/components/{online_image/png_image.cpp => runtime_image/png_decoder.cpp} (82%) rename esphome/components/{online_image/png_image.h => runtime_image/png_decoder.h} (65%) create mode 100644 esphome/components/runtime_image/runtime_image.cpp create mode 100644 esphome/components/runtime_image/runtime_image.h diff --git a/CODEOWNERS b/CODEOWNERS index 25e6dc1b29..2aa0656343 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -411,6 +411,7 @@ esphome/components/rp2040_pwm/* @jesserockz esphome/components/rpi_dpi_rgb/* @clydebarrow esphome/components/rtl87xx/* @kuba2k2 esphome/components/rtttl/* @glmnet +esphome/components/runtime_image/* @clydebarrow @guillempages @kahrendt esphome/components/runtime_stats/* @bdraco esphome/components/rx8130/* @beormund esphome/components/safe_mode/* @jsuanet @kbx81 @paulmonigatti diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 7a6d25bc7d..057244e03d 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -2,97 +2,34 @@ import logging from esphome import automation import esphome.codegen as cg -from esphome.components.const import CONF_BYTE_ORDER, CONF_REQUEST_HEADERS +from esphome.components import runtime_image +from esphome.components.const import CONF_REQUEST_HEADERS from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent -from esphome.components.image import ( - CONF_INVERT_ALPHA, - CONF_TRANSPARENCY, - IMAGE_SCHEMA, - Image_, - get_image_type_enum, - get_transparency_enum, - validate_settings, -) import esphome.config_validation as cv from esphome.const import ( CONF_BUFFER_SIZE, - CONF_DITHER, - CONF_FILE, - CONF_FORMAT, CONF_ID, CONF_ON_ERROR, - CONF_RESIZE, CONF_TRIGGER_ID, - CONF_TYPE, CONF_URL, ) from esphome.core import Lambda -AUTO_LOAD = ["image"] +AUTO_LOAD = ["image", "runtime_image"] DEPENDENCIES = ["display", "http_request"] CODEOWNERS = ["@guillempages", "@clydebarrow"] MULTI_CONF = True CONF_ON_DOWNLOAD_FINISHED = "on_download_finished" -CONF_PLACEHOLDER = "placeholder" CONF_UPDATE = "update" _LOGGER = logging.getLogger(__name__) online_image_ns = cg.esphome_ns.namespace("online_image") -ImageFormat = online_image_ns.enum("ImageFormat") - - -class Format: - def __init__(self, image_type): - self.image_type = image_type - - @property - def enum(self): - return getattr(ImageFormat, self.image_type) - - def actions(self): - pass - - -class BMPFormat(Format): - def __init__(self): - super().__init__("BMP") - - def actions(self): - cg.add_define("USE_ONLINE_IMAGE_BMP_SUPPORT") - - -class JPEGFormat(Format): - def __init__(self): - super().__init__("JPEG") - - def actions(self): - cg.add_define("USE_ONLINE_IMAGE_JPEG_SUPPORT") - cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2") - - -class PNGFormat(Format): - def __init__(self): - super().__init__("PNG") - - def actions(self): - cg.add_define("USE_ONLINE_IMAGE_PNG_SUPPORT") - cg.add_library("pngle", "1.1.0") - - -IMAGE_FORMATS = { - x.image_type: x - for x in ( - BMPFormat(), - JPEGFormat(), - PNGFormat(), - ) -} -IMAGE_FORMATS.update({"JPG": IMAGE_FORMATS["JPEG"]}) - -OnlineImage = online_image_ns.class_("OnlineImage", cg.PollingComponent, Image_) +OnlineImage = online_image_ns.class_( + "OnlineImage", cg.PollingComponent, runtime_image.RuntimeImage +) # Actions SetUrlAction = online_image_ns.class_( @@ -111,29 +48,17 @@ DownloadErrorTrigger = online_image_ns.class_( ) -def remove_options(*options): - return { - cv.Optional(option): cv.invalid( - f"{option} is an invalid option for online_image" - ) - for option in options - } - - ONLINE_IMAGE_SCHEMA = ( - IMAGE_SCHEMA.extend(remove_options(CONF_FILE, CONF_INVERT_ALPHA, CONF_DITHER)) + runtime_image.runtime_image_schema(OnlineImage) .extend( { - cv.Required(CONF_ID): cv.declare_id(OnlineImage), - cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), # Online Image specific options + cv.GenerateID(CONF_HTTP_REQUEST_ID): cv.use_id(HttpRequestComponent), cv.Required(CONF_URL): cv.url, + cv.Optional(CONF_BUFFER_SIZE, default=65536): cv.int_range(256, 65536), cv.Optional(CONF_REQUEST_HEADERS): cv.All( cv.Schema({cv.string: cv.templatable(cv.string)}) ), - cv.Required(CONF_FORMAT): cv.one_of(*IMAGE_FORMATS, upper=True), - cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_), - cv.Optional(CONF_BUFFER_SIZE, default=65536): cv.int_range(256, 65536), cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( @@ -162,7 +87,7 @@ CONFIG_SCHEMA = cv.Schema( rp2040_arduino=cv.Version(0, 0, 0), host=cv.Version(0, 0, 0), ), - validate_settings, + runtime_image.validate_runtime_image_settings, ) ) @@ -199,23 +124,21 @@ async def online_image_action_to_code(config, action_id, template_arg, args): async def to_code(config): - image_format = IMAGE_FORMATS[config[CONF_FORMAT]] - image_format.actions() + # Use the enhanced helper function to get all runtime image parameters + settings = await runtime_image.process_runtime_image_config(config) url = config[CONF_URL] - width, height = config.get(CONF_RESIZE, (0, 0)) - transparent = get_transparency_enum(config[CONF_TRANSPARENCY]) - var = cg.new_Pvariable( config[CONF_ID], url, - width, - height, - image_format.enum, - get_image_type_enum(config[CONF_TYPE]), - transparent, + settings.width, + settings.height, + settings.format_enum, + settings.image_type_enum, + settings.transparent, + settings.placeholder or cg.nullptr, config[CONF_BUFFER_SIZE], - config.get(CONF_BYTE_ORDER) != "LITTLE_ENDIAN", + settings.byte_order_big_endian, ) await cg.register_component(var, config) await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID]) @@ -227,10 +150,6 @@ async def to_code(config): else: cg.add(var.add_request_header(key, value)) - if placeholder_id := config.get(CONF_PLACEHOLDER): - placeholder = await cg.get_variable(placeholder_id) - cg.add(var.set_placeholder(placeholder)) - for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(bool, "cached")], conf) diff --git a/esphome/components/online_image/image_decoder.cpp b/esphome/components/online_image/download_buffer.cpp similarity index 52% rename from esphome/components/online_image/image_decoder.cpp rename to esphome/components/online_image/download_buffer.cpp index 0ab7dadde3..999005df82 100644 --- a/esphome/components/online_image/image_decoder.cpp +++ b/esphome/components/online_image/download_buffer.cpp @@ -1,29 +1,10 @@ -#include "image_decoder.h" -#include "online_image.h" - +#include "download_buffer.h" #include "esphome/core/log.h" +#include <cstring> -namespace esphome { -namespace online_image { +namespace esphome::online_image { -static const char *const TAG = "online_image.decoder"; - -bool ImageDecoder::set_size(int width, int height) { - bool success = this->image_->resize_(width, height) > 0; - this->x_scale_ = static_cast<double>(this->image_->buffer_width_) / width; - this->y_scale_ = static_cast<double>(this->image_->buffer_height_) / height; - return success; -} - -void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) { - auto width = std::min(this->image_->buffer_width_, static_cast<int>(std::ceil((x + w) * this->x_scale_))); - auto height = std::min(this->image_->buffer_height_, static_cast<int>(std::ceil((y + h) * this->y_scale_))); - for (int i = x * this->x_scale_; i < width; i++) { - for (int j = y * this->y_scale_; j < height; j++) { - this->image_->draw_pixel_(i, j, color); - } - } -} +static const char *const TAG = "online_image.download_buffer"; DownloadBuffer::DownloadBuffer(size_t size) : size_(size) { this->buffer_ = this->allocator_.allocate(size); @@ -43,10 +24,12 @@ uint8_t *DownloadBuffer::data(size_t offset) { } size_t DownloadBuffer::read(size_t len) { - this->unread_ -= len; - if (this->unread_ > 0) { - memmove(this->data(), this->data(len), this->unread_); + if (len >= this->unread_) { + this->unread_ = 0; + return 0; } + this->unread_ -= len; + memmove(this->data(), this->data(len), this->unread_); return this->unread_; } @@ -69,5 +52,4 @@ size_t DownloadBuffer::resize(size_t size) { } } -} // namespace online_image -} // namespace esphome +} // namespace esphome::online_image diff --git a/esphome/components/online_image/download_buffer.h b/esphome/components/online_image/download_buffer.h new file mode 100644 index 0000000000..110a4b608a --- /dev/null +++ b/esphome/components/online_image/download_buffer.h @@ -0,0 +1,44 @@ +#pragma once + +#include "esphome/core/helpers.h" +#include <cstddef> +#include <cstdint> + +namespace esphome::online_image { + +/** + * @brief Buffer for managing downloaded data. + * + * This class provides a buffer for downloading data with tracking of + * unread bytes and dynamic resizing capabilities. + */ +class DownloadBuffer { + public: + DownloadBuffer(size_t size); + ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); } + + uint8_t *data(size_t offset = 0); + uint8_t *append() { return this->data(this->unread_); } + + size_t unread() const { return this->unread_; } + size_t size() const { return this->size_; } + size_t free_capacity() const { return this->size_ - this->unread_; } + + size_t read(size_t len); + size_t write(size_t len) { + this->unread_ += len; + return this->unread_; + } + + void reset() { this->unread_ = 0; } + size_t resize(size_t size); + + protected: + RAMAllocator<uint8_t> allocator_{}; + uint8_t *buffer_; + size_t size_; + /** Total number of downloaded bytes not yet read. */ + size_t unread_; +}; + +} // namespace esphome::online_image diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index 4e2ecc2c77..6f5b82116d 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -1,6 +1,6 @@ #include "online_image.h" - #include "esphome/core/log.h" +#include <algorithm> static const char *const TAG = "online_image"; static const char *const ETAG_HEADER_NAME = "etag"; @@ -8,142 +8,82 @@ static const char *const IF_NONE_MATCH_HEADER_NAME = "if-none-match"; static const char *const LAST_MODIFIED_HEADER_NAME = "last-modified"; static const char *const IF_MODIFIED_SINCE_HEADER_NAME = "if-modified-since"; -#include "image_decoder.h" +namespace esphome::online_image { -#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT -#include "bmp_image.h" -#endif -#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT -#include "jpeg_image.h" -#endif -#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT -#include "png_image.h" -#endif - -namespace esphome { -namespace online_image { - -using image::ImageType; - -inline bool is_color_on(const Color &color) { - // This produces the most accurate monochrome conversion, but is slightly slower. - // return (0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b) > 127; - - // Approximation using fast integer computations; produces acceptable results - // Equivalent to 0.25 * R + 0.5 * G + 0.25 * B - return ((color.r >> 2) + (color.g >> 1) + (color.b >> 2)) & 0x80; -} - -OnlineImage::OnlineImage(const std::string &url, int width, int height, ImageFormat format, ImageType type, - image::Transparency transparency, uint32_t download_buffer_size, bool is_big_endian) - : Image(nullptr, 0, 0, type, transparency), - buffer_(nullptr), - download_buffer_(download_buffer_size), - download_buffer_initial_size_(download_buffer_size), - format_(format), - fixed_width_(width), - fixed_height_(height), - is_big_endian_(is_big_endian) { +OnlineImage::OnlineImage(const std::string &url, int width, int height, runtime_image::ImageFormat format, + image::ImageType type, image::Transparency transparency, image::Image *placeholder, + uint32_t buffer_size, bool is_big_endian) + : RuntimeImage(format, type, transparency, placeholder, is_big_endian, width, height), + download_buffer_(buffer_size), + download_buffer_initial_size_(buffer_size) { this->set_url(url); } -void OnlineImage::draw(int x, int y, display::Display *display, Color color_on, Color color_off) { - if (this->data_start_) { - Image::draw(x, y, display, color_on, color_off); - } else if (this->placeholder_) { - this->placeholder_->draw(x, y, display, color_on, color_off); +bool OnlineImage::validate_url_(const std::string &url) { + if (url.empty()) { + ESP_LOGE(TAG, "URL is empty"); + return false; } -} - -void OnlineImage::release() { - if (this->buffer_) { - ESP_LOGV(TAG, "Deallocating old buffer"); - this->allocator_.deallocate(this->buffer_, this->get_buffer_size_()); - this->data_start_ = nullptr; - this->buffer_ = nullptr; - this->width_ = 0; - this->height_ = 0; - this->buffer_width_ = 0; - this->buffer_height_ = 0; - this->last_modified_ = ""; - this->etag_ = ""; - this->end_connection_(); + if (url.length() > 2048) { + ESP_LOGE(TAG, "URL is too long"); + return false; } -} - -size_t OnlineImage::resize_(int width_in, int height_in) { - int width = this->fixed_width_; - int height = this->fixed_height_; - if (this->is_auto_resize_()) { - width = width_in; - height = height_in; - if (this->width_ != width && this->height_ != height) { - this->release(); - } + if (url.compare(0, 7, "http://") != 0 && url.compare(0, 8, "https://") != 0) { + ESP_LOGE(TAG, "URL must start with http:// or https://"); + return false; } - size_t new_size = this->get_buffer_size_(width, height); - if (this->buffer_) { - // Buffer already allocated => no need to resize - return new_size; - } - ESP_LOGD(TAG, "Allocating new buffer of %zu bytes", new_size); - this->buffer_ = this->allocator_.allocate(new_size); - if (this->buffer_ == nullptr) { - ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size, - this->allocator_.get_max_free_block_size()); - this->end_connection_(); - return 0; - } - this->buffer_width_ = width; - this->buffer_height_ = height; - this->width_ = width; - ESP_LOGV(TAG, "New size: (%d, %d)", width, height); - return new_size; + return true; } void OnlineImage::update() { - if (this->decoder_) { + if (this->is_decoding()) { ESP_LOGW(TAG, "Image already being updated."); return; } - ESP_LOGI(TAG, "Updating image %s", this->url_.c_str()); - std::list<http_request::Header> headers = {}; - - http_request::Header accept_header; - accept_header.name = "Accept"; - std::string accept_mime_type; - switch (this->format_) { -#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT - case ImageFormat::BMP: - accept_mime_type = "image/bmp"; - break; -#endif // USE_ONLINE_IMAGE_BMP_SUPPORT -#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT - case ImageFormat::JPEG: - accept_mime_type = "image/jpeg"; - break; -#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT -#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT - case ImageFormat::PNG: - accept_mime_type = "image/png"; - break; -#endif // USE_ONLINE_IMAGE_PNG_SUPPORT - default: - accept_mime_type = "image/*"; + if (!this->validate_url_(this->url_)) { + ESP_LOGE(TAG, "Invalid URL: %s", this->url_.c_str()); + this->download_error_callback_.call(); + return; } - accept_header.value = accept_mime_type + ",*/*;q=0.8"; + ESP_LOGD(TAG, "Updating image from %s", this->url_.c_str()); + + std::list<http_request::Header> headers; + + // Add caching headers if we have them if (!this->etag_.empty()) { - headers.push_back(http_request::Header{IF_NONE_MATCH_HEADER_NAME, this->etag_}); + headers.push_back({IF_NONE_MATCH_HEADER_NAME, this->etag_}); } - if (!this->last_modified_.empty()) { - headers.push_back(http_request::Header{IF_MODIFIED_SINCE_HEADER_NAME, this->last_modified_}); + headers.push_back({IF_MODIFIED_SINCE_HEADER_NAME, this->last_modified_}); } - headers.push_back(accept_header); + // Add Accept header based on image format + const char *accept_mime_type; + switch (this->get_format()) { +#ifdef USE_RUNTIME_IMAGE_BMP + case runtime_image::BMP: + accept_mime_type = "image/bmp,*/*;q=0.8"; + break; +#endif +#ifdef USE_RUNTIME_IMAGE_JPEG + case runtime_image::JPEG: + accept_mime_type = "image/jpeg,*/*;q=0.8"; + break; +#endif +#ifdef USE_RUNTIME_IMAGE_PNG + case runtime_image::PNG: + accept_mime_type = "image/png,*/*;q=0.8"; + break; +#endif + default: + accept_mime_type = "image/*,*/*;q=0.8"; + break; + } + headers.push_back({"Accept", accept_mime_type}); + // User headers last so they can override any of the above for (auto &header : this->request_headers_) { headers.push_back(http_request::Header{header.first, header.second.value()}); } @@ -175,186 +115,117 @@ void OnlineImage::update() { ESP_LOGD(TAG, "Starting download"); size_t total_size = this->downloader_->content_length; -#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT - if (this->format_ == ImageFormat::BMP) { - ESP_LOGD(TAG, "Allocating BMP decoder"); - this->decoder_ = make_unique<BmpDecoder>(this); - this->enable_loop(); + // Initialize decoder with the known format + if (!this->begin_decode(total_size)) { + ESP_LOGE(TAG, "Failed to initialize decoder for format %d", this->get_format()); + this->end_connection_(); + this->download_error_callback_.call(); + return; } -#endif // USE_ONLINE_IMAGE_BMP_SUPPORT -#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT - if (this->format_ == ImageFormat::JPEG) { - ESP_LOGD(TAG, "Allocating JPEG decoder"); - this->decoder_ = esphome::make_unique<JpegDecoder>(this); - this->enable_loop(); - } -#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT -#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT - if (this->format_ == ImageFormat::PNG) { - ESP_LOGD(TAG, "Allocating PNG decoder"); - this->decoder_ = make_unique<PngDecoder>(this); - this->enable_loop(); - } -#endif // USE_ONLINE_IMAGE_PNG_SUPPORT - if (!this->decoder_) { - ESP_LOGE(TAG, "Could not instantiate decoder. Image format unsupported: %d", this->format_); - this->end_connection_(); - this->download_error_callback_.call(); - return; - } - auto prepare_result = this->decoder_->prepare(total_size); - if (prepare_result < 0) { - this->end_connection_(); - this->download_error_callback_.call(); - return; + // JPEG requires the complete image in the download buffer before decoding + if (this->get_format() == runtime_image::JPEG && total_size > this->download_buffer_.size()) { + this->download_buffer_.resize(total_size); } + ESP_LOGI(TAG, "Downloading image (Size: %zu)", total_size); this->start_time_ = ::time(nullptr); + this->enable_loop(); } void OnlineImage::loop() { - if (!this->decoder_) { + if (!this->is_decoding()) { // Not decoding at the moment => nothing to do. this->disable_loop(); return; } - if (!this->downloader_ || this->decoder_->is_finished()) { - this->data_start_ = buffer_; - this->width_ = buffer_width_; - this->height_ = buffer_height_; - ESP_LOGD(TAG, "Image fully downloaded, read %zu bytes, width/height = %d/%d", this->downloader_->get_bytes_read(), - this->width_, this->height_); - ESP_LOGD(TAG, "Total time: %" PRIu32 "s", (uint32_t) (::time(nullptr) - this->start_time_)); + + if (!this->downloader_) { + ESP_LOGE(TAG, "Downloader not instantiated; cannot download"); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } + + // Check if download is complete — use decoder's format-specific completion check + // to handle both known content-length and chunked transfer encoding + if (this->is_decode_finished() || (this->downloader_->content_length > 0 && + this->downloader_->get_bytes_read() >= this->downloader_->content_length && + this->download_buffer_.unread() == 0)) { + // Finalize decoding + this->end_decode(); + + ESP_LOGD(TAG, "Image fully downloaded, %zu bytes in %" PRIu32 "s", this->downloader_->get_bytes_read(), + (uint32_t) (::time(nullptr) - this->start_time_)); + + // Save caching headers this->etag_ = this->downloader_->get_response_header(ETAG_HEADER_NAME); this->last_modified_ = this->downloader_->get_response_header(LAST_MODIFIED_HEADER_NAME); + this->download_finished_callback_.call(false); this->end_connection_(); return; } - if (this->downloader_ == nullptr) { - ESP_LOGE(TAG, "Downloader not instantiated; cannot download"); - return; - } + + // Download and decode more data size_t available = this->download_buffer_.free_capacity(); - if (available) { - // Some decoders need to fully download the image before downloading. - // In case of huge images, don't wait blocking until the whole image has been downloaded, - // use smaller chunks + if (available > 0) { + // Download in chunks to avoid blocking available = std::min(available, this->download_buffer_initial_size_); auto len = this->downloader_->read(this->download_buffer_.append(), available); + if (len > 0) { this->download_buffer_.write(len); - auto fed = this->decoder_->decode(this->download_buffer_.data(), this->download_buffer_.unread()); - if (fed < 0) { - ESP_LOGE(TAG, "Error when decoding image."); + + // Feed data to decoder + auto consumed = this->feed_data(this->download_buffer_.data(), this->download_buffer_.unread()); + + if (consumed < 0) { + ESP_LOGE(TAG, "Error decoding image: %d", consumed); this->end_connection_(); this->download_error_callback_.call(); return; } - this->download_buffer_.read(fed); - } - } -} -void OnlineImage::map_chroma_key(Color &color) { - if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) { - if (color.g == 1 && color.r == 0 && color.b == 0) { - color.g = 0; - } - if (color.w < 0x80) { - color.r = 0; - color.g = this->type_ == ImageType::IMAGE_TYPE_RGB565 ? 4 : 1; - color.b = 0; - } - } -} - -void OnlineImage::draw_pixel_(int x, int y, Color color) { - if (!this->buffer_) { - ESP_LOGE(TAG, "Buffer not allocated!"); - return; - } - if (x < 0 || y < 0 || x >= this->buffer_width_ || y >= this->buffer_height_) { - ESP_LOGE(TAG, "Tried to paint a pixel (%d,%d) outside the image!", x, y); - return; - } - uint32_t pos = this->get_position_(x, y); - switch (this->type_) { - case ImageType::IMAGE_TYPE_BINARY: { - const uint32_t width_8 = ((this->width_ + 7u) / 8u) * 8u; - pos = x + y * width_8; - auto bitno = 0x80 >> (pos % 8u); - pos /= 8u; - auto on = is_color_on(color); - if (this->has_transparency() && color.w < 0x80) - on = false; - if (on) { - this->buffer_[pos] |= bitno; - } else { - this->buffer_[pos] &= ~bitno; + if (consumed > 0) { + this->download_buffer_.read(consumed); } - break; + } else if (len < 0) { + ESP_LOGE(TAG, "Error downloading image: %d", len); + this->end_connection_(); + this->download_error_callback_.call(); + return; } - case ImageType::IMAGE_TYPE_GRAYSCALE: { - auto gray = static_cast<uint8_t>(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b); - if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) { - if (gray == 1) { - gray = 0; - } - if (color.w < 0x80) { - gray = 1; - } - } else if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { - if (color.w != 0xFF) - gray = color.w; - } - this->buffer_[pos] = gray; - break; - } - case ImageType::IMAGE_TYPE_RGB565: { - this->map_chroma_key(color); - uint16_t col565 = display::ColorUtil::color_to_565(color); - if (this->is_big_endian_) { - this->buffer_[pos + 0] = static_cast<uint8_t>((col565 >> 8) & 0xFF); - this->buffer_[pos + 1] = static_cast<uint8_t>(col565 & 0xFF); - } else { - this->buffer_[pos + 0] = static_cast<uint8_t>(col565 & 0xFF); - this->buffer_[pos + 1] = static_cast<uint8_t>((col565 >> 8) & 0xFF); - } - if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { - this->buffer_[pos + 2] = color.w; - } - break; - } - case ImageType::IMAGE_TYPE_RGB: { - this->map_chroma_key(color); - this->buffer_[pos + 0] = color.r; - this->buffer_[pos + 1] = color.g; - this->buffer_[pos + 2] = color.b; - if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { - this->buffer_[pos + 3] = color.w; - } - break; + } else { + // Buffer is full, need to decode some data first + auto consumed = this->feed_data(this->download_buffer_.data(), this->download_buffer_.unread()); + if (consumed > 0) { + this->download_buffer_.read(consumed); + } else if (consumed < 0) { + ESP_LOGE(TAG, "Decode error with full buffer: %d", consumed); + this->end_connection_(); + this->download_error_callback_.call(); + return; + } else { + // Decoder can't process more data, might need complete image + // This is normal for JPEG which needs complete data + ESP_LOGV(TAG, "Decoder waiting for more data"); } } } void OnlineImage::end_connection_() { + // Abort any in-progress decode to free decoder resources. + // Use RuntimeImage::release() directly to avoid recursion with OnlineImage::release(). + if (this->is_decoding()) { + RuntimeImage::release(); + } if (this->downloader_) { this->downloader_->end(); this->downloader_ = nullptr; } - this->decoder_.reset(); this->download_buffer_.reset(); -} - -bool OnlineImage::validate_url_(const std::string &url) { - if ((url.length() < 8) || !url.starts_with("http") || (url.find("://") == std::string::npos)) { - ESP_LOGE(TAG, "URL is invalid and/or must be prefixed with 'http://' or 'https://'"); - return false; - } - return true; + this->disable_loop(); } void OnlineImage::add_on_finished_callback(std::function<void(bool)> &&callback) { @@ -365,5 +236,16 @@ void OnlineImage::add_on_error_callback(std::function<void()> &&callback) { this->download_error_callback_.add(std::move(callback)); } -} // namespace online_image -} // namespace esphome +void OnlineImage::release() { + // Clear cache headers + this->etag_ = ""; + this->last_modified_ = ""; + + // End any active connection + this->end_connection_(); + + // Call parent's release to free the image buffer + RuntimeImage::release(); +} + +} // namespace esphome::online_image diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 12d409ca29..c7c80c7c66 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -1,15 +1,14 @@ #pragma once +#include "download_buffer.h" #include "esphome/components/http_request/http_request.h" -#include "esphome/components/image/image.h" +#include "esphome/components/runtime_image/runtime_image.h" +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" -#include "image_decoder.h" - -namespace esphome { -namespace online_image { +namespace esphome::online_image { using t_http_codes = enum { HTTP_CODE_OK = 200, @@ -17,27 +16,13 @@ using t_http_codes = enum { HTTP_CODE_NOT_FOUND = 404, }; -/** - * @brief Format that the image is encoded with. - */ -enum ImageFormat { - /** Automatically detect from MIME type. Not supported yet. */ - AUTO, - /** JPEG format. */ - JPEG, - /** PNG format. */ - PNG, - /** BMP format. */ - BMP, -}; - /** * @brief Download an image from a given URL, and decode it using the specified decoder. * The image will then be stored in a buffer, so that it can be re-displayed without the * need to re-download or re-decode. */ class OnlineImage : public PollingComponent, - public image::Image, + public runtime_image::RuntimeImage, public Parented<esphome::http_request::HttpRequestComponent> { public: /** @@ -46,17 +31,19 @@ class OnlineImage : public PollingComponent, * @param url URL to download the image from. * @param width Desired width of the target image area. * @param height Desired height of the target image area. - * @param format Format that the image is encoded in (@see ImageFormat). + * @param format Format that the image is encoded in (@see runtime_image::ImageFormat). + * @param type The pixel format for the image. + * @param transparency The transparency type for the image. + * @param placeholder Optional placeholder image to show while loading. * @param buffer_size Size of the buffer used to download the image. + * @param is_big_endian Whether the image is stored in big-endian format. */ - OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type, - image::Transparency transparency, uint32_t buffer_size, bool is_big_endian); - - void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override; + OnlineImage(const std::string &url, int width, int height, runtime_image::ImageFormat format, image::ImageType type, + image::Transparency transparency, image::Image *placeholder, uint32_t buffer_size, + bool is_big_endian = false); void update() override; void loop() override; - void map_chroma_key(Color &color); /** Set the URL to download the image from. */ void set_url(const std::string &url) { @@ -69,82 +56,26 @@ class OnlineImage : public PollingComponent, /** Add the request header */ template<typename V> void add_request_header(const std::string &header, V value) { - this->request_headers_.push_back(std::pair<std::string, TemplatableValue<std::string> >(header, value)); + this->request_headers_.push_back(std::pair<std::string, TemplatableValue<std::string>>(header, value)); } - /** - * @brief Set the image that needs to be shown as long as the downloaded image - * is not available. - * - * @param placeholder Pointer to the (@link Image) to show as placeholder. - */ - void set_placeholder(image::Image *placeholder) { this->placeholder_ = placeholder; } - /** * Release the buffer storing the image. The image will need to be downloaded again * to be able to be displayed. */ void release(); - /** - * Resize the download buffer - * - * @param size The new size for the download buffer. - */ - size_t resize_download_buffer(size_t size) { return this->download_buffer_.resize(size); } - void add_on_finished_callback(std::function<void(bool)> &&callback); void add_on_error_callback(std::function<void()> &&callback); protected: bool validate_url_(const std::string &url); - - RAMAllocator<uint8_t> allocator_{}; - - uint32_t get_buffer_size_() const { return get_buffer_size_(this->buffer_width_, this->buffer_height_); } - int get_buffer_size_(int width, int height) const { return (this->get_bpp() * width + 7u) / 8u * height; } - - int get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; } - - ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const { return this->fixed_width_ == 0 || this->fixed_height_ == 0; } - - /** - * @brief Resize the image buffer to the requested dimensions. - * - * The buffer will be allocated if not existing. - * If the dimensions have been fixed in the yaml config, the buffer will be created - * with those dimensions and not resized, even on request. - * Otherwise, the old buffer will be deallocated and a new buffer with the requested - * allocated - * - * @param width - * @param height - * @return 0 if no memory could be allocated, the size of the new buffer otherwise. - */ - size_t resize_(int width, int height); - - /** - * @brief Draw a pixel into the buffer. - * - * This is used by the decoder to fill the buffer that will later be displayed - * by the `draw` method. This will internally convert the supplied 32 bit RGBA - * color into the requested image storage format. - * - * @param x Horizontal pixel position. - * @param y Vertical pixel position. - * @param color 32 bit color to put into the pixel. - */ - void draw_pixel_(int x, int y, Color color); - void end_connection_(); CallbackManager<void(bool)> download_finished_callback_{}; CallbackManager<void()> download_error_callback_{}; std::shared_ptr<http_request::HttpContainer> downloader_{nullptr}; - std::unique_ptr<ImageDecoder> decoder_{nullptr}; - - uint8_t *buffer_; DownloadBuffer download_buffer_; /** * This is the *initial* size of the download buffer, not the current size. @@ -153,40 +84,10 @@ class OnlineImage : public PollingComponent, */ size_t download_buffer_initial_size_; - const ImageFormat format_; - image::Image *placeholder_{nullptr}; - std::string url_{""}; - std::vector<std::pair<std::string, TemplatableValue<std::string> > > request_headers_; + std::vector<std::pair<std::string, TemplatableValue<std::string>>> request_headers_; - /** width requested on configuration, or 0 if non specified. */ - const int fixed_width_; - /** height requested on configuration, or 0 if non specified. */ - const int fixed_height_; - /** - * Whether the image is stored in big-endian format. - * This is used to determine how to store 16 bit colors in the buffer. - */ - bool is_big_endian_; - /** - * Actual width of the current image. If fixed_width_ is specified, - * this will be equal to it; otherwise it will be set once the decoding - * starts and the original size is known. - * This needs to be separate from "BaseImage::get_width()" because the latter - * must return 0 until the image has been decoded (to avoid showing partially - * decoded images). - */ - int buffer_width_; - /** - * Actual height of the current image. If fixed_height_ is specified, - * this will be equal to it; otherwise it will be set once the decoding - * starts and the original size is known. - * This needs to be separate from "BaseImage::get_height()" because the latter - * must return 0 until the image has been decoded (to avoid showing partially - * decoded images). - */ - int buffer_height_; /** * The value of the ETag HTTP header provided in the last response. */ @@ -197,9 +98,6 @@ class OnlineImage : public PollingComponent, std::string last_modified_ = ""; time_t start_time_; - - friend bool ImageDecoder::set_size(int width, int height); - friend void ImageDecoder::draw(int x, int y, int w, int h, const Color &color); }; template<typename... Ts> class OnlineImageSetUrlAction : public Action<Ts...> { @@ -241,5 +139,4 @@ class DownloadErrorTrigger : public Trigger<> { } }; -} // namespace online_image -} // namespace esphome +} // namespace esphome::online_image diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py new file mode 100644 index 0000000000..0773a53d91 --- /dev/null +++ b/esphome/components/runtime_image/__init__.py @@ -0,0 +1,191 @@ +from dataclasses import dataclass + +import esphome.codegen as cg +from esphome.components.const import CONF_BYTE_ORDER +from esphome.components.image import ( + IMAGE_TYPE, + Image_, + validate_settings, + validate_transparency, + validate_type, +) +import esphome.config_validation as cv +from esphome.const import CONF_FORMAT, CONF_ID, CONF_RESIZE, CONF_TYPE + +AUTO_LOAD = ["image"] +CODEOWNERS = ["@guillempages", "@clydebarrow", "@kahrendt"] + +CONF_PLACEHOLDER = "placeholder" +CONF_TRANSPARENCY = "transparency" + +runtime_image_ns = cg.esphome_ns.namespace("runtime_image") + +# Base decoder classes +ImageDecoder = runtime_image_ns.class_("ImageDecoder") +BmpDecoder = runtime_image_ns.class_("BmpDecoder", ImageDecoder) +JpegDecoder = runtime_image_ns.class_("JpegDecoder", ImageDecoder) +PngDecoder = runtime_image_ns.class_("PngDecoder", ImageDecoder) + +# Runtime image class +RuntimeImage = runtime_image_ns.class_( + "RuntimeImage", cg.esphome_ns.namespace("image").class_("Image") +) + +# Image format enum +ImageFormat = runtime_image_ns.enum("ImageFormat") +IMAGE_FORMAT_AUTO = ImageFormat.AUTO +IMAGE_FORMAT_JPEG = ImageFormat.JPEG +IMAGE_FORMAT_PNG = ImageFormat.PNG +IMAGE_FORMAT_BMP = ImageFormat.BMP + +# Export enum for decode errors +DecodeError = runtime_image_ns.enum("DecodeError") +DECODE_ERROR_INVALID_TYPE = DecodeError.DECODE_ERROR_INVALID_TYPE +DECODE_ERROR_UNSUPPORTED_FORMAT = DecodeError.DECODE_ERROR_UNSUPPORTED_FORMAT +DECODE_ERROR_OUT_OF_MEMORY = DecodeError.DECODE_ERROR_OUT_OF_MEMORY + + +class Format: + """Base class for image format definitions.""" + + def __init__(self, name: str, decoder_class: cg.MockObjClass) -> None: + self.name = name + self.decoder_class = decoder_class + + def actions(self) -> None: + """Add defines and libraries needed for this format.""" + + +class BMPFormat(Format): + """BMP format decoder configuration.""" + + def __init__(self): + super().__init__("BMP", BmpDecoder) + + def actions(self) -> None: + cg.add_define("USE_RUNTIME_IMAGE_BMP") + + +class JPEGFormat(Format): + """JPEG format decoder configuration.""" + + def __init__(self): + super().__init__("JPEG", JpegDecoder) + + def actions(self) -> None: + cg.add_define("USE_RUNTIME_IMAGE_JPEG") + cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2") + + +class PNGFormat(Format): + """PNG format decoder configuration.""" + + def __init__(self): + super().__init__("PNG", PngDecoder) + + def actions(self) -> None: + cg.add_define("USE_RUNTIME_IMAGE_PNG") + cg.add_library("pngle", "1.1.0") + + +# Registry of available formats +IMAGE_FORMATS = { + "BMP": BMPFormat(), + "JPEG": JPEGFormat(), + "PNG": PNGFormat(), + "JPG": JPEGFormat(), # Alias for JPEG +} + + +def get_format(format_name: str) -> Format | None: + """Get a format instance by name.""" + return IMAGE_FORMATS.get(format_name.upper()) + + +def enable_format(format_name: str) -> Format | None: + """Enable a specific image format by adding its defines and libraries.""" + format_obj = get_format(format_name) + if format_obj: + format_obj.actions() + return format_obj + return None + + +# Runtime image configuration schema base - to be extended by components +def runtime_image_schema(image_class: cg.MockObjClass = RuntimeImage) -> cv.Schema: + """Create a runtime image schema with the specified image class.""" + return cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(image_class), + cv.Required(CONF_FORMAT): cv.one_of(*IMAGE_FORMATS, upper=True), + cv.Optional(CONF_RESIZE): cv.dimensions, + cv.Required(CONF_TYPE): validate_type(IMAGE_TYPE), + cv.Optional(CONF_BYTE_ORDER): cv.one_of( + "BIG_ENDIAN", "LITTLE_ENDIAN", upper=True + ), + cv.Optional(CONF_TRANSPARENCY, default="OPAQUE"): validate_transparency(), + cv.Optional(CONF_PLACEHOLDER): cv.use_id(Image_), + } + ) + + +def validate_runtime_image_settings(config: dict) -> dict: + """Apply validate_settings from image component to runtime image config.""" + return validate_settings(config) + + +@dataclass +class RuntimeImageSettings: + """Processed runtime image configuration parameters.""" + + width: int + height: int + format_enum: cg.MockObj + image_type_enum: cg.MockObj + transparent: cg.MockObj + byte_order_big_endian: bool + placeholder: cg.MockObj | None + + +async def process_runtime_image_config(config: dict) -> RuntimeImageSettings: + """ + Helper function to process common runtime image configuration parameters. + Handles format enabling and returns all necessary enums and parameters. + """ + from esphome.components.image import get_image_type_enum, get_transparency_enum + + # Get resize dimensions with default (0, 0) + width, height = config.get(CONF_RESIZE, (0, 0)) + + # Handle format (required for runtime images) + format_name = config[CONF_FORMAT] + # Enable the format in the runtime_image component + enable_format(format_name) + # Map format names to enum values (handle JPG as alias for JPEG) + if format_name.upper() == "JPG": + format_name = "JPEG" + format_enum = getattr(ImageFormat, format_name.upper()) + + # Get image type enum + image_type_enum = get_image_type_enum(config[CONF_TYPE]) + + # Get transparency enum + transparent = get_transparency_enum(config.get(CONF_TRANSPARENCY, "OPAQUE")) + + # Get byte order (True for big endian, False for little endian) + byte_order_big_endian = config.get(CONF_BYTE_ORDER) != "LITTLE_ENDIAN" + + # Get placeholder if specified + placeholder = None + if placeholder_id := config.get(CONF_PLACEHOLDER): + placeholder = await cg.get_variable(placeholder_id) + + return RuntimeImageSettings( + width=width, + height=height, + format_enum=format_enum, + image_type_enum=image_type_enum, + transparent=transparent, + byte_order_big_endian=byte_order_big_endian, + placeholder=placeholder, + ) diff --git a/esphome/components/online_image/bmp_image.cpp b/esphome/components/runtime_image/bmp_decoder.cpp similarity index 82% rename from esphome/components/online_image/bmp_image.cpp rename to esphome/components/runtime_image/bmp_decoder.cpp index 676a2efca9..1a56484c60 100644 --- a/esphome/components/online_image/bmp_image.cpp +++ b/esphome/components/runtime_image/bmp_decoder.cpp @@ -1,15 +1,14 @@ -#include "bmp_image.h" +#include "bmp_decoder.h" -#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT +#ifdef USE_RUNTIME_IMAGE_BMP #include "esphome/components/display/display.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { -static const char *const TAG = "online_image.bmp"; +static const char *const TAG = "image_decoder.bmp"; int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { size_t index = 0; @@ -30,7 +29,11 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { return DECODE_ERROR_INVALID_TYPE; } - this->download_size_ = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]); + // BMP file contains its own size in the header + size_t file_size = encode_uint32(buffer[5], buffer[4], buffer[3], buffer[2]); + if (this->expected_size_ == 0) { + this->expected_size_ = file_size; // Use file header size if not provided + } this->data_offset_ = encode_uint32(buffer[13], buffer[12], buffer[11], buffer[10]); this->current_index_ = 14; @@ -90,8 +93,8 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { while (index < size) { uint8_t current_byte = buffer[index]; for (uint8_t i = 0; i < 8; i++) { - size_t x = (this->paint_index_ % this->width_) + i; - size_t y = (this->height_ - 1) - (this->paint_index_ / this->width_); + size_t x = (this->paint_index_ % static_cast<size_t>(this->width_)) + i; + size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_)); Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF; this->draw(x, y, 1, 1, c); } @@ -110,8 +113,8 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { uint8_t b = buffer[index]; uint8_t g = buffer[index + 1]; uint8_t r = buffer[index + 2]; - size_t x = this->paint_index_ % this->width_; - size_t y = (this->height_ - 1) - (this->paint_index_ / this->width_); + size_t x = this->paint_index_ % static_cast<size_t>(this->width_); + size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_)); Color c = Color(r, g, b); this->draw(x, y, 1, 1, c); this->paint_index_++; @@ -133,7 +136,6 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { return size; }; -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_BMP_SUPPORT +#endif // USE_RUNTIME_IMAGE_BMP diff --git a/esphome/components/online_image/bmp_image.h b/esphome/components/runtime_image/bmp_decoder.h similarity index 52% rename from esphome/components/online_image/bmp_image.h rename to esphome/components/runtime_image/bmp_decoder.h index 916ffea1ad..37db6b4940 100644 --- a/esphome/components/online_image/bmp_image.h +++ b/esphome/components/runtime_image/bmp_decoder.h @@ -1,27 +1,32 @@ #pragma once #include "esphome/core/defines.h" -#ifdef USE_ONLINE_IMAGE_BMP_SUPPORT +#ifdef USE_RUNTIME_IMAGE_BMP #include "image_decoder.h" +#include "runtime_image.h" -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { /** - * @brief Image decoder specialization for PNG images. + * @brief Image decoder specialization for BMP images. */ class BmpDecoder : public ImageDecoder { public: /** * @brief Construct a new BMP Decoder object. * - * @param display The image to decode the stream into. + * @param image The RuntimeImage to decode the stream into. */ - BmpDecoder(OnlineImage *image) : ImageDecoder(image) {} + BmpDecoder(RuntimeImage *image) : ImageDecoder(image) {} int HOT decode(uint8_t *buffer, size_t size) override; + bool is_finished() const override { + // BMP is finished when we've decoded all pixel data + return this->paint_index_ >= static_cast<size_t>(this->width_ * this->height_); + } + protected: size_t current_index_{0}; size_t paint_index_{0}; @@ -36,7 +41,6 @@ class BmpDecoder : public ImageDecoder { uint8_t padding_bytes_{0}; }; -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_BMP_SUPPORT +#endif // USE_RUNTIME_IMAGE_BMP diff --git a/esphome/components/runtime_image/image_decoder.cpp b/esphome/components/runtime_image/image_decoder.cpp new file mode 100644 index 0000000000..8d3320b5d1 --- /dev/null +++ b/esphome/components/runtime_image/image_decoder.cpp @@ -0,0 +1,28 @@ +#include "image_decoder.h" +#include "runtime_image.h" +#include "esphome/core/log.h" +#include <algorithm> +#include <cmath> + +namespace esphome::runtime_image { + +static const char *const TAG = "image_decoder"; + +bool ImageDecoder::set_size(int width, int height) { + bool success = this->image_->resize(width, height) > 0; + this->x_scale_ = static_cast<double>(this->image_->get_buffer_width()) / width; + this->y_scale_ = static_cast<double>(this->image_->get_buffer_height()) / height; + return success; +} + +void ImageDecoder::draw(int x, int y, int w, int h, const Color &color) { + auto width = std::min(this->image_->get_buffer_width(), static_cast<int>(std::ceil((x + w) * this->x_scale_))); + auto height = std::min(this->image_->get_buffer_height(), static_cast<int>(std::ceil((y + h) * this->y_scale_))); + for (int i = x * this->x_scale_; i < width; i++) { + for (int j = y * this->y_scale_; j < height; j++) { + this->image_->draw_pixel(i, j, color); + } + } +} + +} // namespace esphome::runtime_image diff --git a/esphome/components/online_image/image_decoder.h b/esphome/components/runtime_image/image_decoder.h similarity index 60% rename from esphome/components/online_image/image_decoder.h rename to esphome/components/runtime_image/image_decoder.h index d11b8b46d3..926108a8a0 100644 --- a/esphome/components/online_image/image_decoder.h +++ b/esphome/components/runtime_image/image_decoder.h @@ -1,8 +1,7 @@ #pragma once #include "esphome/core/color.h" -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { enum DecodeError : int { DECODE_ERROR_INVALID_TYPE = -1, @@ -10,7 +9,7 @@ enum DecodeError : int { DECODE_ERROR_OUT_OF_MEMORY = -3, }; -class OnlineImage; +class RuntimeImage; /** * @brief Class to abstract decoding different image formats. @@ -20,19 +19,19 @@ class ImageDecoder { /** * @brief Construct a new Image Decoder object * - * @param image The image to decode the stream into. + * @param image The RuntimeImage to decode the stream into. */ - ImageDecoder(OnlineImage *image) : image_(image) {} + ImageDecoder(RuntimeImage *image) : image_(image) {} virtual ~ImageDecoder() = default; /** * @brief Initialize the decoder. * - * @param download_size The total number of bytes that need to be downloaded for the image. + * @param expected_size Hint about the expected data size (0 if unknown). * @return int Returns 0 on success, a {@see DecodeError} value in case of an error. */ - virtual int prepare(size_t download_size) { - this->download_size_ = download_size; + virtual int prepare(size_t expected_size) { + this->expected_size_ = expected_size; return 0; } @@ -73,49 +72,26 @@ class ImageDecoder { */ void draw(int x, int y, int w, int h, const Color &color); - bool is_finished() const { return this->decoded_bytes_ == this->download_size_; } + /** + * @brief Check if the decoder has finished processing. + * + * This should be overridden by decoders that can detect completion + * based on format-specific markers rather than byte counts. + */ + virtual bool is_finished() const { + if (this->expected_size_ > 0) { + return this->decoded_bytes_ >= this->expected_size_; + } + // If size is unknown, derived classes should override this + return false; + } protected: - OnlineImage *image_; - // Initializing to 1, to ensure it is distinguishable from initial "decoded_bytes_". - // Will be overwritten anyway once the download size is known. - size_t download_size_ = 1; - size_t decoded_bytes_ = 0; + RuntimeImage *image_; + size_t expected_size_ = 0; // Expected data size (0 if unknown) + size_t decoded_bytes_ = 0; // Bytes processed so far double x_scale_ = 1.0; double y_scale_ = 1.0; }; -class DownloadBuffer { - public: - DownloadBuffer(size_t size); - - virtual ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); } - - uint8_t *data(size_t offset = 0); - - uint8_t *append() { return this->data(this->unread_); } - - size_t unread() const { return this->unread_; } - size_t size() const { return this->size_; } - size_t free_capacity() const { return this->size_ - this->unread_; } - - size_t read(size_t len); - size_t write(size_t len) { - this->unread_ += len; - return this->unread_; - } - - void reset() { this->unread_ = 0; } - - size_t resize(size_t size); - - protected: - RAMAllocator<uint8_t> allocator_{}; - uint8_t *buffer_; - size_t size_; - /** Total number of downloaded bytes not yet read. */ - size_t unread_; -}; - -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image diff --git a/esphome/components/online_image/jpeg_image.cpp b/esphome/components/runtime_image/jpeg_decoder.cpp similarity index 69% rename from esphome/components/online_image/jpeg_image.cpp rename to esphome/components/runtime_image/jpeg_decoder.cpp index 10586091d5..dcaa07cd58 100644 --- a/esphome/components/online_image/jpeg_image.cpp +++ b/esphome/components/runtime_image/jpeg_decoder.cpp @@ -1,16 +1,19 @@ -#include "jpeg_image.h" -#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT +#include "jpeg_decoder.h" +#ifdef USE_RUNTIME_IMAGE_JPEG #include "esphome/components/display/display_buffer.h" #include "esphome/core/application.h" +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "online_image.h" -static const char *const TAG = "online_image.jpeg"; +#ifdef USE_ESP_IDF +#include "esp_task_wdt.h" +#endif -namespace esphome { -namespace online_image { +static const char *const TAG = "image_decoder.jpeg"; + +namespace esphome::runtime_image { /** * @brief Callback method that will be called by the JPEGDEC engine when a chunk @@ -22,8 +25,14 @@ static int draw_callback(JPEGDRAW *jpeg) { ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser; // Some very big images take too long to decode, so feed the watchdog on each callback - // to avoid crashing. - App.feed_wdt(); + // to avoid crashing if the executing task has a watchdog enabled. +#ifdef USE_ESP_IDF + if (esp_task_wdt_status(nullptr) == ESP_OK) { +#endif + App.feed_wdt(); +#ifdef USE_ESP_IDF + } +#endif size_t position = 0; size_t height = static_cast<size_t>(jpeg->iHeight); size_t width = static_cast<size_t>(jpeg->iWidth); @@ -43,22 +52,23 @@ static int draw_callback(JPEGDRAW *jpeg) { return 1; } -int JpegDecoder::prepare(size_t download_size) { - ImageDecoder::prepare(download_size); - auto size = this->image_->resize_download_buffer(download_size); - if (size < download_size) { - ESP_LOGE(TAG, "Download buffer resize failed!"); - return DECODE_ERROR_OUT_OF_MEMORY; - } +int JpegDecoder::prepare(size_t expected_size) { + ImageDecoder::prepare(expected_size); + // JPEG decoder needs complete data before decoding return 0; } int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) { - if (size < this->download_size_) { - ESP_LOGV(TAG, "Download not complete. Size: %d/%d", size, this->download_size_); + // JPEG decoder requires complete data + // If we know the expected size, wait for it + if (this->expected_size_ > 0 && size < this->expected_size_) { + ESP_LOGV(TAG, "Download not complete. Size: %zu/%zu", size, this->expected_size_); return 0; } + // If size unknown, try to decode and see if it's valid + // The JPEGDEC library will fail gracefully if data is incomplete + if (!this->jpeg_.openRAM(buffer, size, draw_callback)) { ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError()); return DECODE_ERROR_INVALID_TYPE; @@ -88,7 +98,6 @@ int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) { return size; } -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT +#endif // USE_RUNTIME_IMAGE_JPEG diff --git a/esphome/components/online_image/jpeg_image.h b/esphome/components/runtime_image/jpeg_decoder.h similarity index 54% rename from esphome/components/online_image/jpeg_image.h rename to esphome/components/runtime_image/jpeg_decoder.h index fd488d6138..ed2401e263 100644 --- a/esphome/components/online_image/jpeg_image.h +++ b/esphome/components/runtime_image/jpeg_decoder.h @@ -1,12 +1,12 @@ #pragma once #include "image_decoder.h" +#include "runtime_image.h" #include "esphome/core/defines.h" -#ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT +#ifdef USE_RUNTIME_IMAGE_JPEG #include <JPEGDEC.h> -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { /** * @brief Image decoder specialization for JPEG images. @@ -16,19 +16,18 @@ class JpegDecoder : public ImageDecoder { /** * @brief Construct a new JPEG Decoder object. * - * @param display The image to decode the stream into. + * @param image The RuntimeImage to decode the stream into. */ - JpegDecoder(OnlineImage *image) : ImageDecoder(image) {} + JpegDecoder(RuntimeImage *image) : ImageDecoder(image) {} ~JpegDecoder() override {} - int prepare(size_t download_size) override; + int prepare(size_t expected_size) override; int HOT decode(uint8_t *buffer, size_t size) override; protected: JPEGDEC jpeg_{}; }; -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_JPEG_SUPPORT +#endif // USE_RUNTIME_IMAGE_JPEG diff --git a/esphome/components/online_image/png_image.cpp b/esphome/components/runtime_image/png_decoder.cpp similarity index 82% rename from esphome/components/online_image/png_image.cpp rename to esphome/components/runtime_image/png_decoder.cpp index ce9d3bdc91..9fe4a9c4ff 100644 --- a/esphome/components/online_image/png_image.cpp +++ b/esphome/components/runtime_image/png_decoder.cpp @@ -1,15 +1,14 @@ -#include "png_image.h" -#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT +#include "png_decoder.h" +#ifdef USE_RUNTIME_IMAGE_PNG #include "esphome/components/display/display_buffer.h" #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -static const char *const TAG = "online_image.png"; +static const char *const TAG = "image_decoder.png"; -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { /** * @brief Callback method that will be called by the PNGLE engine when the basic @@ -49,7 +48,7 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui } } -PngDecoder::PngDecoder(OnlineImage *image) : ImageDecoder(image) { +PngDecoder::PngDecoder(RuntimeImage *image) : ImageDecoder(image) { { pngle_t *pngle = this->allocator_.allocate(1, PNGLE_T_SIZE); if (!pngle) { @@ -69,8 +68,8 @@ PngDecoder::~PngDecoder() { } } -int PngDecoder::prepare(size_t download_size) { - ImageDecoder::prepare(download_size); +int PngDecoder::prepare(size_t expected_size) { + ImageDecoder::prepare(expected_size); if (!this->pngle_) { ESP_LOGE(TAG, "PNG decoder engine not initialized!"); return DECODE_ERROR_OUT_OF_MEMORY; @@ -86,8 +85,9 @@ int HOT PngDecoder::decode(uint8_t *buffer, size_t size) { ESP_LOGE(TAG, "PNG decoder engine not initialized!"); return DECODE_ERROR_OUT_OF_MEMORY; } - if (size < 256 && size < this->download_size_ - this->decoded_bytes_) { - ESP_LOGD(TAG, "Waiting for data"); + // PNG can be decoded progressively, but wait for a reasonable chunk + if (size < 256 && this->expected_size_ > 0 && size < this->expected_size_ - this->decoded_bytes_) { + ESP_LOGD(TAG, "Waiting for more data"); return 0; } auto fed = pngle_feed(this->pngle_, buffer, size); @@ -99,7 +99,6 @@ int HOT PngDecoder::decode(uint8_t *buffer, size_t size) { return fed; } -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_PNG_SUPPORT +#endif // USE_RUNTIME_IMAGE_PNG diff --git a/esphome/components/online_image/png_image.h b/esphome/components/runtime_image/png_decoder.h similarity index 65% rename from esphome/components/online_image/png_image.h rename to esphome/components/runtime_image/png_decoder.h index 40e85dde33..b5c1e70c2a 100644 --- a/esphome/components/online_image/png_image.h +++ b/esphome/components/runtime_image/png_decoder.h @@ -3,11 +3,11 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "image_decoder.h" -#ifdef USE_ONLINE_IMAGE_PNG_SUPPORT +#include "runtime_image.h" +#ifdef USE_RUNTIME_IMAGE_PNG #include <pngle.h> -namespace esphome { -namespace online_image { +namespace esphome::runtime_image { /** * @brief Image decoder specialization for PNG images. @@ -17,12 +17,12 @@ class PngDecoder : public ImageDecoder { /** * @brief Construct a new PNG Decoder object. * - * @param display The image to decode the stream into. + * @param image The RuntimeImage to decode the stream into. */ - PngDecoder(OnlineImage *image); + PngDecoder(RuntimeImage *image); ~PngDecoder() override; - int prepare(size_t download_size) override; + int prepare(size_t expected_size) override; int HOT decode(uint8_t *buffer, size_t size) override; void increment_pixels_decoded(uint32_t count) { this->pixels_decoded_ += count; } @@ -30,11 +30,10 @@ class PngDecoder : public ImageDecoder { protected: RAMAllocator<pngle_t> allocator_; - pngle_t *pngle_; + pngle_t *pngle_{nullptr}; uint32_t pixels_decoded_{0}; }; -} // namespace online_image -} // namespace esphome +} // namespace esphome::runtime_image -#endif // USE_ONLINE_IMAGE_PNG_SUPPORT +#endif // USE_RUNTIME_IMAGE_PNG diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp new file mode 100644 index 0000000000..1d70f38d6b --- /dev/null +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -0,0 +1,300 @@ +#include "runtime_image.h" +#include "image_decoder.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include <cstring> + +#ifdef USE_RUNTIME_IMAGE_BMP +#include "bmp_decoder.h" +#endif +#ifdef USE_RUNTIME_IMAGE_JPEG +#include "jpeg_decoder.h" +#endif +#ifdef USE_RUNTIME_IMAGE_PNG +#include "png_decoder.h" +#endif + +namespace esphome::runtime_image { + +static const char *const TAG = "runtime_image"; + +inline bool is_color_on(const Color &color) { + // This produces the most accurate monochrome conversion, but is slightly slower. + // return (0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b) > 127; + + // Approximation using fast integer computations; produces acceptable results + // Equivalent to 0.25 * R + 0.5 * G + 0.25 * B + return ((color.r >> 2) + (color.g >> 1) + (color.b >> 2)) & 0x80; +} + +RuntimeImage::RuntimeImage(ImageFormat format, image::ImageType type, image::Transparency transparency, + image::Image *placeholder, bool is_big_endian, int fixed_width, int fixed_height) + : Image(nullptr, 0, 0, type, transparency), + format_(format), + fixed_width_(fixed_width), + fixed_height_(fixed_height), + placeholder_(placeholder), + is_big_endian_(is_big_endian) {} + +RuntimeImage::~RuntimeImage() { this->release(); } + +int RuntimeImage::resize(int width, int height) { + // Use fixed dimensions if specified (0 means auto-resize) + int target_width = this->fixed_width_ ? this->fixed_width_ : width; + int target_height = this->fixed_height_ ? this->fixed_height_ : height; + + size_t result = this->resize_buffer_(target_width, target_height); + if (result > 0 && this->progressive_display_) { + // Update display dimensions for progressive display + this->width_ = this->buffer_width_; + this->height_ = this->buffer_height_; + this->data_start_ = this->buffer_; + } + return result; +} + +void RuntimeImage::draw_pixel(int x, int y, const Color &color) { + if (!this->buffer_) { + ESP_LOGE(TAG, "Buffer not allocated!"); + return; + } + if (x < 0 || y < 0 || x >= this->buffer_width_ || y >= this->buffer_height_) { + ESP_LOGE(TAG, "Tried to paint a pixel (%d,%d) outside the image!", x, y); + return; + } + + switch (this->type_) { + case image::IMAGE_TYPE_BINARY: { + const uint32_t width_8 = ((this->buffer_width_ + 7u) / 8u) * 8u; + uint32_t pos = x + y * width_8; + auto bitno = 0x80 >> (pos % 8u); + pos /= 8u; + auto on = is_color_on(color); + if (this->has_transparency() && color.w < 0x80) + on = false; + if (on) { + this->buffer_[pos] |= bitno; + } else { + this->buffer_[pos] &= ~bitno; + } + break; + } + case image::IMAGE_TYPE_GRAYSCALE: { + uint32_t pos = this->get_position_(x, y); + auto gray = static_cast<uint8_t>(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b); + if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) { + if (gray == 1) { + gray = 0; + } + if (color.w < 0x80) { + gray = 1; + } + } else if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { + if (color.w != 0xFF) + gray = color.w; + } + this->buffer_[pos] = gray; + break; + } + case image::IMAGE_TYPE_RGB565: { + uint32_t pos = this->get_position_(x, y); + Color mapped_color = color; + this->map_chroma_key(mapped_color); + uint16_t rgb565 = display::ColorUtil::color_to_565(mapped_color); + if (this->is_big_endian_) { + this->buffer_[pos + 0] = static_cast<uint8_t>((rgb565 >> 8) & 0xFF); + this->buffer_[pos + 1] = static_cast<uint8_t>(rgb565 & 0xFF); + } else { + this->buffer_[pos + 0] = static_cast<uint8_t>(rgb565 & 0xFF); + this->buffer_[pos + 1] = static_cast<uint8_t>((rgb565 >> 8) & 0xFF); + } + if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { + this->buffer_[pos + 2] = color.w; + } + break; + } + case image::IMAGE_TYPE_RGB: { + uint32_t pos = this->get_position_(x, y); + Color mapped_color = color; + this->map_chroma_key(mapped_color); + this->buffer_[pos + 0] = mapped_color.r; + this->buffer_[pos + 1] = mapped_color.g; + this->buffer_[pos + 2] = mapped_color.b; + if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { + this->buffer_[pos + 3] = color.w; + } + break; + } + } +} + +void RuntimeImage::map_chroma_key(Color &color) { + if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) { + if (color.g == 1 && color.r == 0 && color.b == 0) { + color.g = 0; + } + if (color.w < 0x80) { + color.r = 0; + color.g = this->type_ == image::IMAGE_TYPE_RGB565 ? 4 : 1; + color.b = 0; + } + } +} + +void RuntimeImage::draw(int x, int y, display::Display *display, Color color_on, Color color_off) { + if (this->data_start_) { + // If we have a complete image, use the base class draw method + Image::draw(x, y, display, color_on, color_off); + } else if (this->placeholder_) { + // Show placeholder while the runtime image is not available + this->placeholder_->draw(x, y, display, color_on, color_off); + } + // If no image is loaded and no placeholder, nothing to draw +} + +bool RuntimeImage::begin_decode(size_t expected_size) { + if (this->decoder_) { + ESP_LOGW(TAG, "Decoding already in progress"); + return false; + } + + this->decoder_ = this->create_decoder_(); + if (!this->decoder_) { + ESP_LOGE(TAG, "Failed to create decoder for format %d", this->format_); + return false; + } + + this->total_size_ = expected_size; + this->decoded_bytes_ = 0; + + // Initialize decoder + int result = this->decoder_->prepare(expected_size); + if (result < 0) { + ESP_LOGE(TAG, "Failed to prepare decoder: %d", result); + this->decoder_ = nullptr; + return false; + } + + return true; +} + +int RuntimeImage::feed_data(uint8_t *data, size_t len) { + if (!this->decoder_) { + ESP_LOGE(TAG, "No decoder initialized"); + return -1; + } + + int consumed = this->decoder_->decode(data, len); + if (consumed > 0) { + this->decoded_bytes_ += consumed; + } + + return consumed; +} + +bool RuntimeImage::end_decode() { + if (!this->decoder_) { + return false; + } + + // Finalize the image for display + if (!this->progressive_display_) { + // Only now make the image visible + this->width_ = this->buffer_width_; + this->height_ = this->buffer_height_; + this->data_start_ = this->buffer_; + } + + // Clean up decoder + this->decoder_ = nullptr; + + ESP_LOGD(TAG, "Decoding complete: %dx%d, %zu bytes", this->width_, this->height_, this->decoded_bytes_); + return true; +} + +bool RuntimeImage::is_decode_finished() const { + if (!this->decoder_) { + return false; + } + return this->decoder_->is_finished(); +} + +void RuntimeImage::release() { + this->release_buffer_(); + // Reset decoder separately — release() can be called from within the decoder + // (via set_size -> resize -> resize_buffer_), so we must not destroy the decoder here. + // The decoder lifecycle is managed by begin_decode()/end_decode(). + this->decoder_ = nullptr; +} + +void RuntimeImage::release_buffer_() { + if (this->buffer_) { + ESP_LOGV(TAG, "Releasing buffer of size %zu", this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); + this->allocator_.deallocate(this->buffer_, this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); + this->buffer_ = nullptr; + this->data_start_ = nullptr; + this->width_ = 0; + this->height_ = 0; + this->buffer_width_ = 0; + this->buffer_height_ = 0; + } +} + +size_t RuntimeImage::resize_buffer_(int width, int height) { + size_t new_size = this->get_buffer_size_(width, height); + + if (this->buffer_ && this->buffer_width_ == width && this->buffer_height_ == height) { + // Buffer already allocated with correct size + return new_size; + } + + // Release old buffer if dimensions changed + if (this->buffer_) { + this->release_buffer_(); + } + + ESP_LOGD(TAG, "Allocating buffer: %dx%d, %zu bytes", width, height, new_size); + this->buffer_ = this->allocator_.allocate(new_size); + + if (!this->buffer_) { + ESP_LOGE(TAG, "Failed to allocate %zu bytes. Largest free block: %zu", new_size, + this->allocator_.get_max_free_block_size()); + return 0; + } + + // Clear buffer + memset(this->buffer_, 0, new_size); + + this->buffer_width_ = width; + this->buffer_height_ = height; + + return new_size; +} + +size_t RuntimeImage::get_buffer_size_(int width, int height) const { + return (this->get_bpp() * width + 7u) / 8u * height; +} + +int RuntimeImage::get_position_(int x, int y) const { return (x + y * this->buffer_width_) * this->get_bpp() / 8; } + +std::unique_ptr<ImageDecoder> RuntimeImage::create_decoder_() { + switch (this->format_) { +#ifdef USE_RUNTIME_IMAGE_BMP + case BMP: + return make_unique<BmpDecoder>(this); +#endif +#ifdef USE_RUNTIME_IMAGE_JPEG + case JPEG: + return make_unique<JpegDecoder>(this); +#endif +#ifdef USE_RUNTIME_IMAGE_PNG + case PNG: + return make_unique<PngDecoder>(this); +#endif + default: + ESP_LOGE(TAG, "Unsupported image format: %d", this->format_); + return nullptr; + } +} + +} // namespace esphome::runtime_image diff --git a/esphome/components/runtime_image/runtime_image.h b/esphome/components/runtime_image/runtime_image.h new file mode 100644 index 0000000000..0a5279d86d --- /dev/null +++ b/esphome/components/runtime_image/runtime_image.h @@ -0,0 +1,214 @@ +#pragma once + +#include "esphome/components/image/image.h" +#include "esphome/core/helpers.h" + +namespace esphome::runtime_image { + +// Forward declaration +class ImageDecoder; + +/** + * @brief Image format types that can be decoded dynamically. + */ +enum ImageFormat { + /** Automatically detect from data. Not implemented yet. */ + AUTO, + /** JPEG format. */ + JPEG, + /** PNG format. */ + PNG, + /** BMP format. */ + BMP, +}; + +/** + * @brief A dynamic image that can be loaded and decoded at runtime. + * + * This class provides dynamic buffer allocation and management for images + * that are decoded at runtime, as opposed to static images compiled into + * the firmware. It serves as a base class for components that need to + * load images dynamically from various sources. + */ +class RuntimeImage : public image::Image { + public: + /** + * @brief Construct a new RuntimeImage object. + * + * @param format The image format to decode. + * @param type The pixel format for the image. + * @param transparency The transparency type for the image. + * @param placeholder Optional placeholder image to show while loading. + * @param is_big_endian Whether the image is stored in big-endian format. + * @param fixed_width Fixed width for the image (0 for auto-resize). + * @param fixed_height Fixed height for the image (0 for auto-resize). + */ + RuntimeImage(ImageFormat format, image::ImageType type, image::Transparency transparency, + image::Image *placeholder = nullptr, bool is_big_endian = false, int fixed_width = 0, + int fixed_height = 0); + + ~RuntimeImage(); + + // Decoder interface methods + /** + * @brief Resize the image buffer to the requested dimensions. + * + * The buffer will be allocated if not existing. + * If fixed dimensions have been specified in the constructor, the buffer will be created + * with those dimensions and not resized, even on request. + * Otherwise, the old buffer will be deallocated and a new buffer with the requested + * dimensions allocated. + * + * @param width Requested width (ignored if fixed_width_ is set) + * @param height Requested height (ignored if fixed_height_ is set) + * @return Size of the allocated buffer in bytes, or 0 if allocation failed. + */ + int resize(int width, int height); + void draw_pixel(int x, int y, const Color &color); + void map_chroma_key(Color &color); + int get_buffer_width() const { return this->buffer_width_; } + int get_buffer_height() const { return this->buffer_height_; } + + // Image drawing interface + void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override; + + /** + * @brief Begin decoding an image. + * + * @param expected_size Optional hint about the expected data size. + * @return true if decoder was successfully initialized. + */ + bool begin_decode(size_t expected_size = 0); + + /** + * @brief Feed data to the decoder. + * + * @param data Pointer to the data buffer. + * @param len Length of data to process. + * @return Number of bytes consumed by the decoder. + */ + int feed_data(uint8_t *data, size_t len); + + /** + * @brief Complete the decoding process. + * + * @return true if decoding completed successfully. + */ + bool end_decode(); + + /** + * @brief Check if decoding is currently in progress. + */ + bool is_decoding() const { return this->decoder_ != nullptr; } + + /** + * @brief Check if the decoder has finished processing all data. + * + * This delegates to the decoder's format-specific completion check, + * which handles both known-size and chunked transfer cases. + */ + bool is_decode_finished() const; + + /** + * @brief Check if an image is currently loaded. + */ + bool is_loaded() const { return this->buffer_ != nullptr; } + + /** + * @brief Get the image format. + */ + ImageFormat get_format() const { return this->format_; } + + /** + * @brief Release the image buffer and free memory. + */ + void release(); + + /** + * @brief Set whether to allow progressive display during decode. + * + * When enabled, the image can be displayed even while still decoding. + * When disabled, the image is only displayed after decoding completes. + */ + void set_progressive_display(bool progressive) { this->progressive_display_ = progressive; } + + protected: + /** + * @brief Resize the image buffer to the requested dimensions. + * + * @param width New width in pixels. + * @param height New height in pixels. + * @return Size of the allocated buffer, or 0 on failure. + */ + size_t resize_buffer_(int width, int height); + + /** + * @brief Release only the image buffer without resetting the decoder. + * + * This is safe to call from within the decoder (e.g., during resize). + */ + void release_buffer_(); + + /** + * @brief Get the buffer size in bytes for given dimensions. + */ + size_t get_buffer_size_(int width, int height) const; + + /** + * @brief Get the position in the buffer for a pixel. + */ + int get_position_(int x, int y) const; + + /** + * @brief Create decoder instance for the image's format. + */ + std::unique_ptr<ImageDecoder> create_decoder_(); + + // Memory management + RAMAllocator<uint8_t> allocator_{}; + uint8_t *buffer_{nullptr}; + + // Decoder management + std::unique_ptr<ImageDecoder> decoder_{nullptr}; + /** The image format this RuntimeImage is configured to decode. */ + const ImageFormat format_; + + /** + * Actual width of the current image. + * This needs to be separate from "Image::get_width()" because the latter + * must return 0 until the image has been decoded (to avoid showing partially + * decoded images). When progressive_display_ is enabled, Image dimensions + * are updated during decoding to allow rendering in progress. + */ + int buffer_width_{0}; + /** + * Actual height of the current image. + * This needs to be separate from "Image::get_height()" because the latter + * must return 0 until the image has been decoded (to avoid showing partially + * decoded images). When progressive_display_ is enabled, Image dimensions + * are updated during decoding to allow rendering in progress. + */ + int buffer_height_{0}; + + // Decoding state + size_t total_size_{0}; + size_t decoded_bytes_{0}; + + /** Fixed width requested on configuration, or 0 if not specified. */ + const int fixed_width_{0}; + /** Fixed height requested on configuration, or 0 if not specified. */ + const int fixed_height_{0}; + + /** Placeholder image to show when the runtime image is not available. */ + image::Image *placeholder_{nullptr}; + + // Configuration + bool progressive_display_{false}; + /** + * Whether the image is stored in big-endian format. + * This is used to determine how to store 16 bit colors in the buffer. + */ + bool is_big_endian_{false}; +}; + +} // namespace esphome::runtime_image diff --git a/esphome/core/defines.h b/esphome/core/defines.h index bfa33e4e59..0d6c1a42e8 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -148,9 +148,9 @@ #define USE_MQTT #define USE_MQTT_COVER_JSON #define USE_NETWORK -#define USE_ONLINE_IMAGE_BMP_SUPPORT -#define USE_ONLINE_IMAGE_PNG_SUPPORT -#define USE_ONLINE_IMAGE_JPEG_SUPPORT +#define USE_RUNTIME_IMAGE_BMP +#define USE_RUNTIME_IMAGE_PNG +#define USE_RUNTIME_IMAGE_JPEG #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_LISTENER From f24e7709aca9e0cb7fc5951ea82141fec1b5dd9e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Feb 2026 16:21:50 -0600 Subject: [PATCH 0703/2030] [core] Make LOG_ENTITY_ICON a no-op when icons are compiled out (#13973) --- esphome/core/entity_base.cpp | 2 ++ esphome/core/entity_base.h | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 811b856b5e..f6a7ec1dfd 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -152,11 +152,13 @@ void EntityBase_UnitOfMeasurement::set_unit_of_measurement(const char *unit_of_m this->unit_of_measurement_ = unit_of_measurement; } +#ifdef USE_ENTITY_ICON void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) { if (!obj.get_icon_ref().empty()) { ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj.get_icon_ref().c_str()); } } +#endif void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj) { if (!obj.get_device_class_ref().empty()) { diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 86cb75495b..cbc07cc44c 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -231,8 +231,13 @@ class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming) }; /// Log entity icon if set (for use in dump_config) +#ifdef USE_ENTITY_ICON #define LOG_ENTITY_ICON(tag, prefix, obj) log_entity_icon(tag, prefix, obj) void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj); +#else +#define LOG_ENTITY_ICON(tag, prefix, obj) ((void) 0) +inline void log_entity_icon(const char *, const char *, const EntityBase &) {} +#endif /// Log entity device class if set (for use in dump_config) #define LOG_ENTITY_DEVICE_CLASS(tag, prefix, obj) log_entity_device_class(tag, prefix, obj) void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj); From 79d9fbf64579bee42d14adc9a4e17f8ddac3ac0b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Feb 2026 16:22:05 -0600 Subject: [PATCH 0704/2030] [nfc] Replace constant std::vector with static constexpr std::array (#13978) --- esphome/components/pn532/pn532.h | 4 +- .../components/pn532/pn532_mifare_classic.cpp | 68 +++++++++---------- .../pn532/pn532_mifare_ultralight.cpp | 16 ++--- esphome/components/pn7150/pn7150.h | 4 +- .../pn7150/pn7150_mifare_classic.cpp | 66 +++++++++--------- .../pn7150/pn7150_mifare_ultralight.cpp | 13 ++-- esphome/components/pn7160/pn7160.h | 4 +- .../pn7160/pn7160_mifare_classic.cpp | 66 +++++++++--------- .../pn7160/pn7160_mifare_ultralight.cpp | 13 ++-- 9 files changed, 130 insertions(+), 124 deletions(-) diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index 73a6c15164..f98c0f9322 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -76,7 +76,7 @@ class PN532 : public PollingComponent { std::unique_ptr<nfc::NfcTag> read_mifare_classic_tag_(nfc::NfcTagUid &uid); bool read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); - bool write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); + bool write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len); bool auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, uint8_t key_num, const uint8_t *key); bool format_mifare_classic_mifare_(nfc::NfcTagUid &uid); bool format_mifare_classic_ndef_(nfc::NfcTagUid &uid); @@ -88,7 +88,7 @@ class PN532 : public PollingComponent { uint16_t read_mifare_ultralight_capacity_(); bool find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); - bool write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data); + bool write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len); bool write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *message); bool clean_mifare_ultralight_(); diff --git a/esphome/components/pn532/pn532_mifare_classic.cpp b/esphome/components/pn532/pn532_mifare_classic.cpp index b762d5d936..cca6acd96d 100644 --- a/esphome/components/pn532/pn532_mifare_classic.cpp +++ b/esphome/components/pn532/pn532_mifare_classic.cpp @@ -1,3 +1,4 @@ +#include <array> #include <memory> #include "pn532.h" @@ -106,10 +107,10 @@ bool PN532::auth_mifare_classic_block_(nfc::NfcTagUid &uid, uint8_t block_num, u } bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) { - std::vector<uint8_t> blank_buffer( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> trailer_buffer( - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BUFFER = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> TRAILER_BUFFER = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; bool error = false; @@ -118,20 +119,20 @@ bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) { continue; } if (block != 0) { - if (!this->write_mifare_classic_block_(block, blank_buffer)) { + if (!this->write_mifare_classic_block_(block, BLANK_BUFFER.data(), BLANK_BUFFER.size())) { ESP_LOGE(TAG, "Unable to write block %d", block); error = true; } } - if (!this->write_mifare_classic_block_(block + 1, blank_buffer)) { + if (!this->write_mifare_classic_block_(block + 1, BLANK_BUFFER.data(), BLANK_BUFFER.size())) { ESP_LOGE(TAG, "Unable to write block %d", block + 1); error = true; } - if (!this->write_mifare_classic_block_(block + 2, blank_buffer)) { + if (!this->write_mifare_classic_block_(block + 2, BLANK_BUFFER.data(), BLANK_BUFFER.size())) { ESP_LOGE(TAG, "Unable to write block %d", block + 2); error = true; } - if (!this->write_mifare_classic_block_(block + 3, trailer_buffer)) { + if (!this->write_mifare_classic_block_(block + 3, TRAILER_BUFFER.data(), TRAILER_BUFFER.size())) { ESP_LOGE(TAG, "Unable to write block %d", block + 3); error = true; } @@ -141,28 +142,28 @@ bool PN532::format_mifare_classic_mifare_(nfc::NfcTagUid &uid) { } bool PN532::format_mifare_classic_ndef_(nfc::NfcTagUid &uid) { - std::vector<uint8_t> empty_ndef_message( - {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> blank_block( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> block_1_data( - {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_2_data( - {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_3_trailer( - {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); - std::vector<uint8_t> ndef_trailer( - {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> EMPTY_NDEF_MESSAGE = { + 0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BLOCK = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_1_DATA = { + 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_2_DATA = { + 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_3_TRAILER = { + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> NDEF_TRAILER = { + 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (!this->auth_mifare_classic_block_(uid, 0, nfc::MIFARE_CMD_AUTH_B, nfc::DEFAULT_KEY)) { ESP_LOGE(TAG, "Unable to authenticate block 0 for formatting!"); return false; } - if (!this->write_mifare_classic_block_(1, block_1_data)) + if (!this->write_mifare_classic_block_(1, BLOCK_1_DATA.data(), BLOCK_1_DATA.size())) return false; - if (!this->write_mifare_classic_block_(2, block_2_data)) + if (!this->write_mifare_classic_block_(2, BLOCK_2_DATA.data(), BLOCK_2_DATA.size())) return false; - if (!this->write_mifare_classic_block_(3, block_3_trailer)) + if (!this->write_mifare_classic_block_(3, BLOCK_3_TRAILER.data(), BLOCK_3_TRAILER.size())) return false; ESP_LOGD(TAG, "Sector 0 formatted to NDEF"); @@ -172,36 +173,36 @@ bool PN532::format_mifare_classic_ndef_(nfc::NfcTagUid &uid) { return false; } if (block == 4) { - if (!this->write_mifare_classic_block_(block, empty_ndef_message)) { + if (!this->write_mifare_classic_block_(block, EMPTY_NDEF_MESSAGE.data(), EMPTY_NDEF_MESSAGE.size())) { ESP_LOGE(TAG, "Unable to write block %d", block); } } else { - if (!this->write_mifare_classic_block_(block, blank_block)) { + if (!this->write_mifare_classic_block_(block, BLANK_BLOCK.data(), BLANK_BLOCK.size())) { ESP_LOGE(TAG, "Unable to write block %d", block); } } - if (!this->write_mifare_classic_block_(block + 1, blank_block)) { + if (!this->write_mifare_classic_block_(block + 1, BLANK_BLOCK.data(), BLANK_BLOCK.size())) { ESP_LOGE(TAG, "Unable to write block %d", block + 1); } - if (!this->write_mifare_classic_block_(block + 2, blank_block)) { + if (!this->write_mifare_classic_block_(block + 2, BLANK_BLOCK.data(), BLANK_BLOCK.size())) { ESP_LOGE(TAG, "Unable to write block %d", block + 2); } - if (!this->write_mifare_classic_block_(block + 3, ndef_trailer)) { + if (!this->write_mifare_classic_block_(block + 3, NDEF_TRAILER.data(), NDEF_TRAILER.size())) { ESP_LOGE(TAG, "Unable to write trailer block %d", block + 3); } } return true; } -bool PN532::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &write_data) { - std::vector<uint8_t> data({ +bool PN532::write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len) { + std::vector<uint8_t> cmd({ PN532_COMMAND_INDATAEXCHANGE, 0x01, // One card nfc::MIFARE_CMD_WRITE, block_num, }); - data.insert(data.end(), write_data.begin(), write_data.end()); - if (!this->write_command_(data)) { + cmd.insert(cmd.end(), data, data + len); + if (!this->write_command_(cmd)) { ESP_LOGE(TAG, "Error writing block %d", block_num); return false; } @@ -243,8 +244,7 @@ bool PN532::write_mifare_classic_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage *mes } } - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_CLASSIC_BLOCK_SIZE); - if (!this->write_mifare_classic_block_(current_block, data)) { + if (!this->write_mifare_classic_block_(current_block, encoded.data() + index, nfc::MIFARE_CLASSIC_BLOCK_SIZE)) { return false; } index += nfc::MIFARE_CLASSIC_BLOCK_SIZE; diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index 01e41df5c0..a8a8e2d573 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -1,3 +1,4 @@ +#include <array> #include <memory> #include "pn532.h" @@ -143,8 +144,7 @@ bool PN532::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage * uint8_t current_page = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; while (index < buffer_length) { - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE); - if (!this->write_mifare_ultralight_page_(current_page, data)) { + if (!this->write_mifare_ultralight_page_(current_page, encoded.data() + index, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE)) { return false; } index += nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; @@ -157,25 +157,25 @@ bool PN532::clean_mifare_ultralight_() { uint32_t capacity = this->read_mifare_ultralight_capacity_(); uint8_t pages = (capacity / nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) + nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; - std::vector<uint8_t> blank_data = {0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE> BLANK_DATA = {0x00, 0x00, 0x00, 0x00}; for (int i = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; i < pages; i++) { - if (!this->write_mifare_ultralight_page_(i, blank_data)) { + if (!this->write_mifare_ultralight_page_(i, BLANK_DATA.data(), BLANK_DATA.size())) { return false; } } return true; } -bool PN532::write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data) { - std::vector<uint8_t> data({ +bool PN532::write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len) { + std::vector<uint8_t> cmd({ PN532_COMMAND_INDATAEXCHANGE, 0x01, // One card nfc::MIFARE_CMD_WRITE_ULTRALIGHT, page_num, }); - data.insert(data.end(), write_data.begin(), write_data.end()); - if (!this->write_command_(data)) { + cmd.insert(cmd.end(), write_data, write_data + len); + if (!this->write_command_(cmd)) { ESP_LOGE(TAG, "Error writing page %u", page_num); return false; } diff --git a/esphome/components/pn7150/pn7150.h b/esphome/components/pn7150/pn7150.h index a5dcef9f99..5feba17d21 100644 --- a/esphome/components/pn7150/pn7150.h +++ b/esphome/components/pn7150/pn7150.h @@ -236,7 +236,7 @@ class PN7150 : public nfc::Nfcc, public Component { uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag); uint8_t read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); - uint8_t write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); + uint8_t write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len); uint8_t auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, const uint8_t *key); uint8_t sect_to_auth_(uint8_t block_num); uint8_t format_mifare_classic_mifare_(); @@ -250,7 +250,7 @@ class PN7150 : public nfc::Nfcc, public Component { uint16_t read_mifare_ultralight_capacity_(); uint8_t find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); - uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data); + uint8_t write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len); uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message); uint8_t clean_mifare_ultralight_(); diff --git a/esphome/components/pn7150/pn7150_mifare_classic.cpp b/esphome/components/pn7150/pn7150_mifare_classic.cpp index dee81b610a..61434cdb28 100644 --- a/esphome/components/pn7150/pn7150_mifare_classic.cpp +++ b/esphome/components/pn7150/pn7150_mifare_classic.cpp @@ -1,3 +1,4 @@ +#include <array> #include <memory> #include "pn7150.h" @@ -139,10 +140,10 @@ uint8_t PN7150::sect_to_auth_(const uint8_t block_num) { } uint8_t PN7150::format_mifare_classic_mifare_() { - std::vector<uint8_t> blank_buffer( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> trailer_buffer( - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BUFFER = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> TRAILER_BUFFER = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; auto status = nfc::STATUS_OK; @@ -151,20 +152,20 @@ uint8_t PN7150::format_mifare_classic_mifare_() { continue; } if (block != 0) { - if (this->write_mifare_classic_block_(block, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } - if (this->write_mifare_classic_block_(block + 1, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 1, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 1); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 2, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 2, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 2); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 3, trailer_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 3, TRAILER_BUFFER.data(), TRAILER_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 3); status = nfc::STATUS_FAILED; } @@ -174,30 +175,30 @@ uint8_t PN7150::format_mifare_classic_mifare_() { } uint8_t PN7150::format_mifare_classic_ndef_() { - std::vector<uint8_t> empty_ndef_message( - {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> blank_block( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> block_1_data( - {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_2_data( - {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_3_trailer( - {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); - std::vector<uint8_t> ndef_trailer( - {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> EMPTY_NDEF_MESSAGE = { + 0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BLOCK = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_1_DATA = { + 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_2_DATA = { + 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_3_TRAILER = { + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> NDEF_TRAILER = { + 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (this->auth_mifare_classic_block_(0, nfc::MIFARE_CMD_AUTH_B, nfc::DEFAULT_KEY) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to authenticate block 0 for formatting"); return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(1, block_1_data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(1, BLOCK_1_DATA.data(), BLOCK_1_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(2, block_2_data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(2, BLOCK_2_DATA.data(), BLOCK_2_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(3, block_3_trailer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(3, BLOCK_3_TRAILER.data(), BLOCK_3_TRAILER.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } @@ -210,25 +211,26 @@ uint8_t PN7150::format_mifare_classic_ndef_() { return nfc::STATUS_FAILED; } if (block == 4) { - if (this->write_mifare_classic_block_(block, empty_ndef_message) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, EMPTY_NDEF_MESSAGE.data(), EMPTY_NDEF_MESSAGE.size()) != + nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } else { - if (this->write_mifare_classic_block_(block, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } - if (this->write_mifare_classic_block_(block + 1, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 1, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 1); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 2, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 2, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 2); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 3, ndef_trailer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 3, NDEF_TRAILER.data(), NDEF_TRAILER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write trailer block %u", block + 3); status = nfc::STATUS_FAILED; } @@ -236,7 +238,7 @@ uint8_t PN7150::format_mifare_classic_ndef_() { return status; } -uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &write_data) { +uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len) { nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, {XCHG_DATA_OID, nfc::MIFARE_CMD_WRITE, block_num}); @@ -248,7 +250,7 @@ uint8_t PN7150::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8 } // write command part two tx.set_payload({XCHG_DATA_OID}); - tx.get_message().insert(tx.get_message().end(), write_data.begin(), write_data.end()); + tx.get_message().insert(tx.get_message().end(), data, data + len); ESP_LOGVV(TAG, "Write XCHG_DATA_REQ 2: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { @@ -294,8 +296,8 @@ uint8_t PN7150::write_mifare_classic_tag_(const std::shared_ptr<nfc::NdefMessage } } - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_CLASSIC_BLOCK_SIZE); - if (this->write_mifare_classic_block_(current_block, data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(current_block, encoded.data() + index, nfc::MIFARE_CLASSIC_BLOCK_SIZE) != + nfc::STATUS_OK) { return nfc::STATUS_FAILED; } index += nfc::MIFARE_CLASSIC_BLOCK_SIZE; diff --git a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp index 166065f6c1..46f5dba2b7 100644 --- a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp +++ b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp @@ -1,3 +1,4 @@ +#include <array> #include <cinttypes> #include <memory> @@ -144,8 +145,8 @@ uint8_t PN7150::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::sha uint8_t current_page = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; while (index < buffer_length) { - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE); - if (this->write_mifare_ultralight_page_(current_page, data) != nfc::STATUS_OK) { + if (this->write_mifare_ultralight_page_(current_page, encoded.data() + index, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) != + nfc::STATUS_OK) { return nfc::STATUS_FAILED; } index += nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; @@ -158,19 +159,19 @@ uint8_t PN7150::clean_mifare_ultralight_() { uint32_t capacity = this->read_mifare_ultralight_capacity_(); uint8_t pages = (capacity / nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) + nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; - std::vector<uint8_t> blank_data = {0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE> BLANK_DATA = {0x00, 0x00, 0x00, 0x00}; for (int i = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; i < pages; i++) { - if (this->write_mifare_ultralight_page_(i, blank_data) != nfc::STATUS_OK) { + if (this->write_mifare_ultralight_page_(i, BLANK_DATA.data(), BLANK_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } } return nfc::STATUS_OK; } -uint8_t PN7150::write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data) { +uint8_t PN7150::write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len) { std::vector<uint8_t> payload = {nfc::MIFARE_CMD_WRITE_ULTRALIGHT, page_num}; - payload.insert(payload.end(), write_data.begin(), write_data.end()); + payload.insert(payload.end(), write_data, write_data + len); nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, payload); diff --git a/esphome/components/pn7160/pn7160.h b/esphome/components/pn7160/pn7160.h index 572fab3351..9f2d10c2d5 100644 --- a/esphome/components/pn7160/pn7160.h +++ b/esphome/components/pn7160/pn7160.h @@ -253,7 +253,7 @@ class PN7160 : public nfc::Nfcc, public Component { uint8_t read_mifare_classic_tag_(nfc::NfcTag &tag); uint8_t read_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); - uint8_t write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &data); + uint8_t write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len); uint8_t auth_mifare_classic_block_(uint8_t block_num, uint8_t key_num, const uint8_t *key); uint8_t sect_to_auth_(uint8_t block_num); uint8_t format_mifare_classic_mifare_(); @@ -267,7 +267,7 @@ class PN7160 : public nfc::Nfcc, public Component { uint16_t read_mifare_ultralight_capacity_(); uint8_t find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length, uint8_t &message_start_index); - uint8_t write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data); + uint8_t write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len); uint8_t write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::shared_ptr<nfc::NdefMessage> &message); uint8_t clean_mifare_ultralight_(); diff --git a/esphome/components/pn7160/pn7160_mifare_classic.cpp b/esphome/components/pn7160/pn7160_mifare_classic.cpp index 57d2042eaa..710a7198c6 100644 --- a/esphome/components/pn7160/pn7160_mifare_classic.cpp +++ b/esphome/components/pn7160/pn7160_mifare_classic.cpp @@ -1,3 +1,4 @@ +#include <array> #include <memory> #include "pn7160.h" @@ -139,10 +140,10 @@ uint8_t PN7160::sect_to_auth_(const uint8_t block_num) { } uint8_t PN7160::format_mifare_classic_mifare_() { - std::vector<uint8_t> blank_buffer( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> trailer_buffer( - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BUFFER = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> TRAILER_BUFFER = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; auto status = nfc::STATUS_OK; @@ -151,20 +152,20 @@ uint8_t PN7160::format_mifare_classic_mifare_() { continue; } if (block != 0) { - if (this->write_mifare_classic_block_(block, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } - if (this->write_mifare_classic_block_(block + 1, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 1, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 1); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 2, blank_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 2, BLANK_BUFFER.data(), BLANK_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 2); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 3, trailer_buffer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 3, TRAILER_BUFFER.data(), TRAILER_BUFFER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 3); status = nfc::STATUS_FAILED; } @@ -174,30 +175,30 @@ uint8_t PN7160::format_mifare_classic_mifare_() { } uint8_t PN7160::format_mifare_classic_ndef_() { - std::vector<uint8_t> empty_ndef_message( - {0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> blank_block( - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - std::vector<uint8_t> block_1_data( - {0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_2_data( - {0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}); - std::vector<uint8_t> block_3_trailer( - {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); - std::vector<uint8_t> ndef_trailer( - {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}); + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> EMPTY_NDEF_MESSAGE = { + 0x03, 0x03, 0xD0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLANK_BLOCK = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_1_DATA = { + 0x14, 0x01, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_2_DATA = { + 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1, 0x03, 0xE1}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> BLOCK_3_TRAILER = { + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0x78, 0x77, 0x88, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + static constexpr std::array<uint8_t, nfc::MIFARE_CLASSIC_BLOCK_SIZE> NDEF_TRAILER = { + 0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7, 0x7F, 0x07, 0x88, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; if (this->auth_mifare_classic_block_(0, nfc::MIFARE_CMD_AUTH_B, nfc::DEFAULT_KEY) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to authenticate block 0 for formatting"); return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(1, block_1_data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(1, BLOCK_1_DATA.data(), BLOCK_1_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(2, block_2_data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(2, BLOCK_2_DATA.data(), BLOCK_2_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(3, block_3_trailer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(3, BLOCK_3_TRAILER.data(), BLOCK_3_TRAILER.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } @@ -210,25 +211,26 @@ uint8_t PN7160::format_mifare_classic_ndef_() { return nfc::STATUS_FAILED; } if (block == 4) { - if (this->write_mifare_classic_block_(block, empty_ndef_message) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, EMPTY_NDEF_MESSAGE.data(), EMPTY_NDEF_MESSAGE.size()) != + nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } else { - if (this->write_mifare_classic_block_(block, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block); status = nfc::STATUS_FAILED; } } - if (this->write_mifare_classic_block_(block + 1, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 1, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 1); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 2, blank_block) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 2, BLANK_BLOCK.data(), BLANK_BLOCK.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write block %u", block + 2); status = nfc::STATUS_FAILED; } - if (this->write_mifare_classic_block_(block + 3, ndef_trailer) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(block + 3, NDEF_TRAILER.data(), NDEF_TRAILER.size()) != nfc::STATUS_OK) { ESP_LOGE(TAG, "Unable to write trailer block %u", block + 3); status = nfc::STATUS_FAILED; } @@ -236,7 +238,7 @@ uint8_t PN7160::format_mifare_classic_ndef_() { return status; } -uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8_t> &write_data) { +uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, const uint8_t *data, size_t len) { nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, {XCHG_DATA_OID, nfc::MIFARE_CMD_WRITE, block_num}); char buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; @@ -248,7 +250,7 @@ uint8_t PN7160::write_mifare_classic_block_(uint8_t block_num, std::vector<uint8 } // write command part two tx.set_payload({XCHG_DATA_OID}); - tx.get_message().insert(tx.get_message().end(), write_data.begin(), write_data.end()); + tx.get_message().insert(tx.get_message().end(), data, data + len); ESP_LOGVV(TAG, "Write XCHG_DATA_REQ 2: %s", nfc::format_bytes_to(buf, tx.get_message())); if (this->transceive_(tx, rx, NFCC_TAG_WRITE_TIMEOUT) != nfc::STATUS_OK) { @@ -294,8 +296,8 @@ uint8_t PN7160::write_mifare_classic_tag_(const std::shared_ptr<nfc::NdefMessage } } - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_CLASSIC_BLOCK_SIZE); - if (this->write_mifare_classic_block_(current_block, data) != nfc::STATUS_OK) { + if (this->write_mifare_classic_block_(current_block, encoded.data() + index, nfc::MIFARE_CLASSIC_BLOCK_SIZE) != + nfc::STATUS_OK) { return nfc::STATUS_FAILED; } index += nfc::MIFARE_CLASSIC_BLOCK_SIZE; diff --git a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp index c473ff48d9..9dc8d3dd2d 100644 --- a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp +++ b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp @@ -1,3 +1,4 @@ +#include <array> #include <cinttypes> #include <memory> @@ -144,8 +145,8 @@ uint8_t PN7160::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::sha uint8_t current_page = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; while (index < buffer_length) { - std::vector<uint8_t> data(encoded.begin() + index, encoded.begin() + index + nfc::MIFARE_ULTRALIGHT_PAGE_SIZE); - if (this->write_mifare_ultralight_page_(current_page, data) != nfc::STATUS_OK) { + if (this->write_mifare_ultralight_page_(current_page, encoded.data() + index, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) != + nfc::STATUS_OK) { return nfc::STATUS_FAILED; } index += nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; @@ -158,19 +159,19 @@ uint8_t PN7160::clean_mifare_ultralight_() { uint32_t capacity = this->read_mifare_ultralight_capacity_(); uint8_t pages = (capacity / nfc::MIFARE_ULTRALIGHT_PAGE_SIZE) + nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; - std::vector<uint8_t> blank_data = {0x00, 0x00, 0x00, 0x00}; + static constexpr std::array<uint8_t, nfc::MIFARE_ULTRALIGHT_PAGE_SIZE> BLANK_DATA = {0x00, 0x00, 0x00, 0x00}; for (int i = nfc::MIFARE_ULTRALIGHT_DATA_START_PAGE; i < pages; i++) { - if (this->write_mifare_ultralight_page_(i, blank_data) != nfc::STATUS_OK) { + if (this->write_mifare_ultralight_page_(i, BLANK_DATA.data(), BLANK_DATA.size()) != nfc::STATUS_OK) { return nfc::STATUS_FAILED; } } return nfc::STATUS_OK; } -uint8_t PN7160::write_mifare_ultralight_page_(uint8_t page_num, std::vector<uint8_t> &write_data) { +uint8_t PN7160::write_mifare_ultralight_page_(uint8_t page_num, const uint8_t *write_data, size_t len) { std::vector<uint8_t> payload = {nfc::MIFARE_CMD_WRITE_ULTRALIGHT, page_num}; - payload.insert(payload.end(), write_data.begin(), write_data.end()); + payload.insert(payload.end(), write_data, write_data + len); nfc::NciMessage rx; nfc::NciMessage tx(nfc::NCI_PKT_MT_DATA, payload); From 931b47673c49e3f29324290b52d591aacab5faed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Feb 2026 16:22:26 -0600 Subject: [PATCH 0705/2030] Bump github/codeql-action from 4.32.2 to 4.32.3 (#13981) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 51ea4085e0..376825bad6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2 + uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 with: category: "/language:${{matrix.language}}" From 7c70b2e04ed80804eb38feac3b4c39abcbc61409 Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino <glm.net@gmail.com> Date: Thu, 12 Feb 2026 13:23:59 -0300 Subject: [PATCH 0706/2030] [schema-gen] fix Windows: ensure UTF-8 encoding when reading component files (#13952) --- script/build_language_schema.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/build_language_schema.py b/script/build_language_schema.py index c9501cb193..bea540dc63 100755 --- a/script/build_language_schema.py +++ b/script/build_language_schema.py @@ -369,7 +369,7 @@ def get_logger_tags(): "api.service", ] for file in CORE_COMPONENTS_PATH.rglob("*.cpp"): - data = file.read_text() + data = file.read_text(encoding="utf-8") match = pattern.search(data) if match: tags.append(match.group(1)) From 844210519a4a662c76e159a45c7bf09760053254 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 10:26:10 -0600 Subject: [PATCH 0707/2030] [uart] Remove redundant mutex, fix flush race, conditional event queue (#13955) --- .../uart/uart_component_esp_idf.cpp | 49 ++++++++++--------- .../components/uart/uart_component_esp_idf.h | 17 +++++-- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 19b9a4077f..6c242220a6 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -90,7 +90,6 @@ void IDFUARTComponent::setup() { return; } this->uart_num_ = static_cast<uart_port_t>(next_uart_num++); - this->lock_ = xSemaphoreCreateMutex(); #if (SOC_UART_LP_NUM >= 1) size_t fifo_len = ((this->uart_num_ < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN); @@ -102,11 +101,7 @@ void IDFUARTComponent::setup() { this->rx_buffer_size_ = fifo_len * 2; } - xSemaphoreTake(this->lock_, portMAX_DELAY); - this->load_settings(false); - - xSemaphoreGive(this->lock_); } void IDFUARTComponent::load_settings(bool dump_config) { @@ -126,13 +121,20 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } } +#ifdef USE_UART_WAKE_LOOP_ON_RX + constexpr int event_queue_size = 20; + QueueHandle_t *event_queue_ptr = &this->uart_event_queue_; +#else + constexpr int event_queue_size = 0; + QueueHandle_t *event_queue_ptr = nullptr; +#endif err = uart_driver_install(this->uart_num_, // UART number this->rx_buffer_size_, // RX ring buffer size - 0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will - // block task until all data has been sent out - 20, // event queue size/depth - &this->uart_event_queue_, // event queue - 0 // Flags used to allocate the interrupt + 0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will + // block task until all data has been sent out + event_queue_size, // event queue size/depth + event_queue_ptr, // event queue + 0 // Flags used to allocate the interrupt ); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err)); @@ -282,9 +284,7 @@ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) { } void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { - xSemaphoreTake(this->lock_, portMAX_DELAY); int32_t write_len = uart_write_bytes(this->uart_num_, data, len); - xSemaphoreGive(this->lock_); if (write_len != (int32_t) len) { ESP_LOGW(TAG, "uart_write_bytes failed: %d != %zu", write_len, len); this->mark_failed(); @@ -299,7 +299,6 @@ void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { bool IDFUARTComponent::peek_byte(uint8_t *data) { if (!this->check_read_timeout_()) return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); if (this->has_peek_) { *data = this->peek_byte_; } else { @@ -311,7 +310,6 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) { this->peek_byte_ = *data; } } - xSemaphoreGive(this->lock_); return true; } @@ -320,7 +318,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { int32_t read_len = 0; if (!this->check_read_timeout_(len)) return false; - xSemaphoreTake(this->lock_, portMAX_DELAY); if (this->has_peek_) { length_to_read--; *data = this->peek_byte_; @@ -329,7 +326,6 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { } if (length_to_read > 0) read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS); - xSemaphoreGive(this->lock_); #ifdef USE_UART_DEBUGGER for (size_t i = 0; i < len; i++) { this->debug_callback_.call(UART_DIRECTION_RX, data[i]); @@ -342,9 +338,7 @@ size_t IDFUARTComponent::available() { size_t available = 0; esp_err_t err; - xSemaphoreTake(this->lock_, portMAX_DELAY); err = uart_get_buffered_data_len(this->uart_num_, &available); - xSemaphoreGive(this->lock_); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_get_buffered_data_len failed: %s", esp_err_to_name(err)); @@ -358,9 +352,7 @@ size_t IDFUARTComponent::available() { void IDFUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); - xSemaphoreTake(this->lock_, portMAX_DELAY); uart_wait_tx_done(this->uart_num_, portMAX_DELAY); - xSemaphoreGive(this->lock_); } void IDFUARTComponent::check_logger_conflict() {} @@ -384,6 +376,13 @@ void IDFUARTComponent::start_rx_event_task_() { ESP_LOGV(TAG, "RX event task started"); } +// FreeRTOS task that relays UART ISR events to the main loop. +// This task exists because wake_loop_threadsafe() is not ISR-safe (it uses a +// UDP loopback socket), so we need a task as an ISR-to-main-loop trampoline. +// IMPORTANT: This task must NOT call any UART wrapper methods (read_array, +// write_array, peek_byte, etc.) or touch has_peek_/peek_byte_ — all reading +// is done by the main loop. This task only reads from the event queue and +// calls App.wake_loop_threadsafe(). void IDFUARTComponent::rx_event_task_func(void *param) { auto *self = static_cast<IDFUARTComponent *>(param); uart_event_t event; @@ -405,8 +404,14 @@ void IDFUARTComponent::rx_event_task_func(void *param) { case UART_FIFO_OVF: case UART_BUFFER_FULL: - ESP_LOGW(TAG, "FIFO overflow or ring buffer full - clearing"); - uart_flush_input(self->uart_num_); + // Don't call uart_flush_input() here — this task does not own the read side. + // ESP-IDF examples flush on overflow because the same task handles both events + // and reads, so flush and read are serialized. Here, reads happen on the main + // loop, so flushing from this task races with read_array() and can destroy data + // mid-read. The driver self-heals without an explicit flush: uart_read_bytes() + // calls uart_check_buf_full() after each chunk, which moves stashed FIFO bytes + // into the ring buffer and re-enables RX interrupts once space is freed. + ESP_LOGW(TAG, "FIFO overflow or ring buffer full"); #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); #endif diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index 1ecb02d7ab..1517eab509 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -8,6 +8,13 @@ namespace esphome::uart { +/// ESP-IDF UART driver wrapper. +/// +/// Thread safety: All public methods must only be called from the main loop. +/// The ESP-IDF UART driver API does not guarantee thread safety, and ESPHome's +/// peek byte state (has_peek_/peek_byte_) is not synchronized. The rx_event_task +/// (when enabled) must not call any of these methods — it communicates with the +/// main loop exclusively via App.wake_loop_threadsafe(). class IDFUARTComponent : public UARTComponent, public Component { public: void setup() override; @@ -26,7 +33,9 @@ class IDFUARTComponent : public UARTComponent, public Component { void flush() override; uint8_t get_hw_serial_number() { return this->uart_num_; } +#ifdef USE_UART_WAKE_LOOP_ON_RX QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; } +#endif /** * Load the UART with the current settings. @@ -46,18 +55,20 @@ class IDFUARTComponent : public UARTComponent, public Component { protected: void check_logger_conflict() override; uart_port_t uart_num_; - QueueHandle_t uart_event_queue_; uart_config_t get_config_(); - SemaphoreHandle_t lock_; bool has_peek_{false}; uint8_t peek_byte_; #ifdef USE_UART_WAKE_LOOP_ON_RX - // RX notification support + // RX notification support — runs on a separate FreeRTOS task. + // IMPORTANT: rx_event_task_func must NOT call any UART wrapper methods (read_array, + // write_array, etc.) or touch has_peek_/peek_byte_. It must only read from the + // event queue and call App.wake_loop_threadsafe(). void start_rx_event_task_(); static void rx_event_task_func(void *param); + QueueHandle_t uart_event_queue_; TaskHandle_t rx_event_task_handle_{nullptr}; #endif // USE_UART_WAKE_LOOP_ON_RX }; From ead7937dbf74a26b92c9c2dbf14b0d875356edcd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 11:04:23 -0600 Subject: [PATCH 0708/2030] [api] Extract cold code from APIServer::loop() hot path (#13902) --- esphome/components/api/api_server.cpp | 130 ++++++++++++++------------ esphome/components/api/api_server.h | 5 + 2 files changed, 74 insertions(+), 61 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 53b41a5c14..5503cf4db8 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -117,37 +117,7 @@ void APIServer::setup() { void APIServer::loop() { // Accept new clients only if the socket exists and has incoming connections if (this->socket_ && this->socket_->ready()) { - while (true) { - struct sockaddr_storage source_addr; - socklen_t addr_len = sizeof(source_addr); - - auto sock = this->socket_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len); - if (!sock) - break; - - char peername[socket::SOCKADDR_STR_LEN]; - sock->getpeername_to(peername); - - // Check if we're at the connection limit - if (this->clients_.size() >= this->max_connections_) { - ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, peername); - // Immediately close - socket destructor will handle cleanup - sock.reset(); - continue; - } - - ESP_LOGD(TAG, "Accept %s", peername); - - auto *conn = new APIConnection(std::move(sock), this); - this->clients_.emplace_back(conn); - conn->start(); - - // First client connected - clear warning and update timestamp - if (this->clients_.size() == 1 && this->reboot_timeout_ != 0) { - this->status_clear_warning(); - this->last_connected_ = App.get_loop_component_start_time(); - } - } + this->accept_new_connections_(); } if (this->clients_.empty()) { @@ -178,46 +148,84 @@ void APIServer::loop() { while (client_index < this->clients_.size()) { auto &client = this->clients_[client_index]; - if (!client->flags_.remove) { + if (client->flags_.remove) { + // Rare case: handle disconnection (don't increment - swapped element needs processing) + this->remove_client_(client_index); + } else { // Common case: process active client client->loop(); client_index++; + } + } +} + +void APIServer::remove_client_(size_t client_index) { + auto &client = this->clients_[client_index]; + +#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES + this->unregister_active_action_calls_for_connection(client.get()); +#endif + ESP_LOGV(TAG, "Remove connection %s", client->get_name()); + +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Save client info before closing socket and removal for the trigger + char peername_buf[socket::SOCKADDR_STR_LEN]; + std::string client_name(client->get_name()); + std::string client_peername(client->get_peername_to(peername_buf)); +#endif + + // Close socket now (was deferred from on_fatal_error to allow getpeername) + client->helper_->close(); + + // Swap with the last element and pop (avoids expensive vector shifts) + if (client_index < this->clients_.size() - 1) { + std::swap(this->clients_[client_index], this->clients_.back()); + } + this->clients_.pop_back(); + + // Last client disconnected - set warning and start tracking for reboot timeout + if (this->clients_.empty() && this->reboot_timeout_ != 0) { + this->status_set_warning(); + this->last_connected_ = App.get_loop_component_start_time(); + } + +#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER + // Fire trigger after client is removed so api.connected reflects the true state + this->client_disconnected_trigger_.trigger(client_name, client_peername); +#endif +} + +void APIServer::accept_new_connections_() { + while (true) { + struct sockaddr_storage source_addr; + socklen_t addr_len = sizeof(source_addr); + + auto sock = this->socket_->accept_loop_monitored((struct sockaddr *) &source_addr, &addr_len); + if (!sock) + break; + + char peername[socket::SOCKADDR_STR_LEN]; + sock->getpeername_to(peername); + + // Check if we're at the connection limit + if (this->clients_.size() >= this->max_connections_) { + ESP_LOGW(TAG, "Max connections (%d), rejecting %s", this->max_connections_, peername); + // Immediately close - socket destructor will handle cleanup + sock.reset(); continue; } - // Rare case: handle disconnection -#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - this->unregister_active_action_calls_for_connection(client.get()); -#endif - ESP_LOGV(TAG, "Remove connection %s", client->get_name()); + ESP_LOGD(TAG, "Accept %s", peername); -#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - // Save client info before closing socket and removal for the trigger - char peername_buf[socket::SOCKADDR_STR_LEN]; - std::string client_name(client->get_name()); - std::string client_peername(client->get_peername_to(peername_buf)); -#endif + auto *conn = new APIConnection(std::move(sock), this); + this->clients_.emplace_back(conn); + conn->start(); - // Close socket now (was deferred from on_fatal_error to allow getpeername) - client->helper_->close(); - - // Swap with the last element and pop (avoids expensive vector shifts) - if (client_index < this->clients_.size() - 1) { - std::swap(this->clients_[client_index], this->clients_.back()); - } - this->clients_.pop_back(); - - // Last client disconnected - set warning and start tracking for reboot timeout - if (this->clients_.empty() && this->reboot_timeout_ != 0) { - this->status_set_warning(); + // First client connected - clear warning and update timestamp + if (this->clients_.size() == 1 && this->reboot_timeout_ != 0) { + this->status_clear_warning(); this->last_connected_ = App.get_loop_component_start_time(); } - -#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER - // Fire trigger after client is removed so api.connected reflects the true state - this->client_disconnected_trigger_.trigger(client_name, client_peername); -#endif - // Don't increment client_index since we need to process the swapped element } } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 6ab3cdc576..28f60343e0 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -234,6 +234,11 @@ class APIServer : public Component, #endif protected: + // Accept incoming socket connections. Only called when socket has pending connections. + void __attribute__((noinline)) accept_new_connections_(); + // Remove a disconnected client by index. Swaps with last element and pops. + void __attribute__((noinline)) remove_client_(size_t client_index); + #ifdef USE_API_NOISE bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg, const psk_t &active_psk, bool make_active); From e9bf9bc691196e4fff13a2c0d866c1e588968f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Ma=C5=88as?= <lukas.manas@gmail.com> Date: Thu, 12 Feb 2026 18:20:54 +0100 Subject: [PATCH 0709/2030] [pulse_meter] Fix early edge detection (#12360) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../pulse_meter/pulse_meter_sensor.cpp | 75 ++++++++++--------- .../pulse_meter/pulse_meter_sensor.h | 11 ++- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.cpp b/esphome/components/pulse_meter/pulse_meter_sensor.cpp index 007deb66e5..433e1f0b7e 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.cpp +++ b/esphome/components/pulse_meter/pulse_meter_sensor.cpp @@ -38,8 +38,7 @@ void PulseMeterSensor::setup() { } void PulseMeterSensor::loop() { - // Reset the count in get before we pass it back to the ISR as set - this->get_->count_ = 0; + State state; { // Lock the interrupt so the interrupt code doesn't interfere with itself @@ -58,31 +57,35 @@ void PulseMeterSensor::loop() { } this->last_pin_val_ = current; - // Swap out set and get to get the latest state from the ISR - std::swap(this->set_, this->get_); + // Get the latest state from the ISR and reset the count in the ISR + state.last_detected_edge_us_ = this->state_.last_detected_edge_us_; + state.last_rising_edge_us_ = this->state_.last_rising_edge_us_; + state.count_ = this->state_.count_; + this->state_.count_ = 0; } const uint32_t now = micros(); // If an edge was peeked, repay the debt - if (this->peeked_edge_ && this->get_->count_ > 0) { + if (this->peeked_edge_ && state.count_ > 0) { this->peeked_edge_ = false; - this->get_->count_--; // NOLINT(clang-diagnostic-deprecated-volatile) + state.count_--; } - // If there is an unprocessed edge, and filter_us_ has passed since, count this edge early - if (this->get_->last_rising_edge_us_ != this->get_->last_detected_edge_us_ && - now - this->get_->last_rising_edge_us_ >= this->filter_us_) { + // If there is an unprocessed edge, and filter_us_ has passed since, count this edge early. + // Wait for the debt to be repaid before counting another unprocessed edge early. + if (!this->peeked_edge_ && state.last_rising_edge_us_ != state.last_detected_edge_us_ && + now - state.last_rising_edge_us_ >= this->filter_us_) { this->peeked_edge_ = true; - this->get_->last_detected_edge_us_ = this->get_->last_rising_edge_us_; - this->get_->count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + state.last_detected_edge_us_ = state.last_rising_edge_us_; + state.count_++; } // Check if we detected a pulse this loop - if (this->get_->count_ > 0) { + if (state.count_ > 0) { // Keep a running total of pulses if a total sensor is configured if (this->total_sensor_ != nullptr) { - this->total_pulses_ += this->get_->count_; + this->total_pulses_ += state.count_; const uint32_t total = this->total_pulses_; this->total_sensor_->publish_state(total); } @@ -94,15 +97,15 @@ void PulseMeterSensor::loop() { this->meter_state_ = MeterState::RUNNING; } break; case MeterState::RUNNING: { - uint32_t delta_us = this->get_->last_detected_edge_us_ - this->last_processed_edge_us_; - float pulse_width_us = delta_us / float(this->get_->count_); - ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us, - this->get_->count_, pulse_width_us); + uint32_t delta_us = state.last_detected_edge_us_ - this->last_processed_edge_us_; + float pulse_width_us = delta_us / float(state.count_); + ESP_LOGV(TAG, "New pulse, delta: %" PRIu32 " µs, count: %" PRIu32 ", width: %.5f µs", delta_us, state.count_, + pulse_width_us); this->publish_state((60.0f * 1000000.0f) / pulse_width_us); } break; } - this->last_processed_edge_us_ = this->get_->last_detected_edge_us_; + this->last_processed_edge_us_ = state.last_detected_edge_us_; } // No detected edges this loop else { @@ -141,14 +144,14 @@ void IRAM_ATTR PulseMeterSensor::edge_intr(PulseMeterSensor *sensor) { // This is an interrupt handler - we can't call any virtual method from this method // Get the current time before we do anything else so the measurements are consistent const uint32_t now = micros(); - auto &state = sensor->edge_state_; - auto &set = *sensor->set_; + auto &edge_state = sensor->edge_state_; + auto &state = sensor->state_; - if ((now - state.last_sent_edge_us_) >= sensor->filter_us_) { - state.last_sent_edge_us_ = now; - set.last_detected_edge_us_ = now; - set.last_rising_edge_us_ = now; - set.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + if ((now - edge_state.last_sent_edge_us_) >= sensor->filter_us_) { + edge_state.last_sent_edge_us_ = now; + state.last_detected_edge_us_ = now; + state.last_rising_edge_us_ = now; + state.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) } // This ISR is bound to rising edges, so the pin is high @@ -160,26 +163,26 @@ void IRAM_ATTR PulseMeterSensor::pulse_intr(PulseMeterSensor *sensor) { // Get the current time before we do anything else so the measurements are consistent const uint32_t now = micros(); const bool pin_val = sensor->isr_pin_.digital_read(); - auto &state = sensor->pulse_state_; - auto &set = *sensor->set_; + auto &pulse_state = sensor->pulse_state_; + auto &state = sensor->state_; // Filter length has passed since the last interrupt - const bool length = now - state.last_intr_ >= sensor->filter_us_; + const bool length = now - pulse_state.last_intr_ >= sensor->filter_us_; - if (length && state.latched_ && !sensor->last_pin_val_) { // Long enough low edge - state.latched_ = false; - } else if (length && !state.latched_ && sensor->last_pin_val_) { // Long enough high edge - state.latched_ = true; - set.last_detected_edge_us_ = state.last_intr_; - set.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) + if (length && pulse_state.latched_ && !sensor->last_pin_val_) { // Long enough low edge + pulse_state.latched_ = false; + } else if (length && !pulse_state.latched_ && sensor->last_pin_val_) { // Long enough high edge + pulse_state.latched_ = true; + state.last_detected_edge_us_ = pulse_state.last_intr_; + state.count_++; // NOLINT(clang-diagnostic-deprecated-volatile) } // Due to order of operations this includes // length && latched && rising (just reset from a long low edge) // !latched && (rising || high) (noise on the line resetting the potential rising edge) - set.last_rising_edge_us_ = !state.latched_ && pin_val ? now : set.last_detected_edge_us_; + state.last_rising_edge_us_ = !pulse_state.latched_ && pin_val ? now : state.last_detected_edge_us_; - state.last_intr_ = now; + pulse_state.last_intr_ = now; sensor->last_pin_val_ = pin_val; } diff --git a/esphome/components/pulse_meter/pulse_meter_sensor.h b/esphome/components/pulse_meter/pulse_meter_sensor.h index 5800c4ec42..e46f1e615f 100644 --- a/esphome/components/pulse_meter/pulse_meter_sensor.h +++ b/esphome/components/pulse_meter/pulse_meter_sensor.h @@ -46,17 +46,16 @@ class PulseMeterSensor : public sensor::Sensor, public Component { uint32_t total_pulses_ = 0; uint32_t last_processed_edge_us_ = 0; - // This struct (and the two pointers) are used to pass data between the ISR and loop. - // These two pointers are exchanged each loop. - // Use these to send data from the ISR to the loop not the other way around (except for resetting the values). + // This struct and variable are used to pass data between the ISR and loop. + // The data from state_ is read and then count_ in state_ is reset in each loop. + // This must be done while guarded by an InterruptLock. Use this variable to send data + // from the ISR to the loop not the other way around (except for resetting count_). struct State { uint32_t last_detected_edge_us_ = 0; uint32_t last_rising_edge_us_ = 0; uint32_t count_ = 0; }; - State state_[2]; - volatile State *set_ = state_; - volatile State *get_ = state_ + 1; + volatile State state_{}; // Only use the following variables in the ISR or while guarded by an InterruptLock ISRInternalGPIOPin isr_pin_; From c08356b0c1d973963cf7d615849b45184b47e4ed Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:04:39 -0500 Subject: [PATCH 0710/2030] [alarm_control_panel] Fix flaky integration test race condition (#13964) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- ...t_alarm_control_panel_state_transitions.py | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tests/integration/test_alarm_control_panel_state_transitions.py b/tests/integration/test_alarm_control_panel_state_transitions.py index 09348f5bea..0b07710961 100644 --- a/tests/integration/test_alarm_control_panel_state_transitions.py +++ b/tests/integration/test_alarm_control_panel_state_transitions.py @@ -270,6 +270,14 @@ async def test_alarm_control_panel_state_transitions( # The chime_sensor has chime: true, so opening it while disarmed # should trigger on_chime callback + # Set up future for the on_ready from opening the chime sensor + # (alarm becomes "not ready" when chime sensor opens). + # We must wait for this BEFORE creating the close future, otherwise + # the open event's log can arrive late and resolve the close future, + # causing the test to proceed before the chime close is processed. + ready_after_chime_open: asyncio.Future[bool] = loop.create_future() + ready_futures.append(ready_after_chime_open) + # We're currently DISARMED - open the chime sensor client.switch_command(chime_switch_info.key, True) @@ -279,11 +287,18 @@ async def test_alarm_control_panel_state_transitions( except TimeoutError: pytest.fail(f"on_chime callback not fired. Log lines: {log_lines[-20:]}") - # Close the chime sensor and wait for alarm to become ready again - # We need to wait for this transition before testing door sensor, - # otherwise there's a race where the door sensor state change could - # arrive before the chime sensor state change, leaving the alarm in - # a continuous "not ready" state with no on_ready callback fired. + # Wait for the on_ready from the chime sensor opening + try: + await asyncio.wait_for(ready_after_chime_open, timeout=2.0) + except TimeoutError: + pytest.fail( + f"on_ready callback not fired when chime sensor opened. " + f"Log lines: {log_lines[-20:]}" + ) + + # Now create the future for the close event and close the sensor. + # Since we waited for the open event above, the close event's + # on_ready log cannot be confused with the open event's. ready_after_chime_close: asyncio.Future[bool] = loop.create_future() ready_futures.append(ready_after_chime_close) From 297dfb0db41174bdb786e419e8100f0c30233d23 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:12:17 -0500 Subject: [PATCH 0711/2030] [docker] Suppress git detached HEAD advice (#13962) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- docker/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8ebdd1e49b..540d28be7f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -9,7 +9,8 @@ FROM ghcr.io/esphome/docker-base:${BUILD_OS}-ha-addon-${BUILD_BASE_VERSION} AS b ARG BUILD_TYPE FROM base-source-${BUILD_TYPE} AS base -RUN git config --system --add safe.directory "*" +RUN git config --system --add safe.directory "*" \ + && git config --system advice.detachedHead false # Install build tools for Python packages that require compilation # (e.g., ruamel.yaml.clibz used by ESP-IDF's idf-component-manager) From f6aeef2e68f1c891f401f80c5886215baf811892 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Feb 2026 18:20:58 -0600 Subject: [PATCH 0712/2030] [api] Fix ESP8266 noise API handshake deadlock and prompt socket cleanup (#13972) --- esphome/components/api/api_frame_helper_noise.cpp | 10 ++++++---- esphome/components/api/api_server.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index c1641b398a..1ae848dead 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -138,10 +138,12 @@ APIError APINoiseFrameHelper::handle_noise_error_(int err, const LogString *func /// Run through handshake messages (if in that phase) APIError APINoiseFrameHelper::loop() { - // During handshake phase, process as many actions as possible until we can't progress - // socket_->ready() stays true until next main loop, but state_action() will return - // WOULD_BLOCK when no more data is available to read - while (state_ != State::DATA && this->socket_->ready()) { + // Cache ready() outside the loop. On ESP8266 LWIP raw TCP, ready() returns false once + // the rx buffer is consumed. Re-checking each iteration would block handshake writes + // that must follow reads, deadlocking the handshake. state_action() will return + // WOULD_BLOCK when no more data is available to read. + bool socket_ready = this->socket_->ready(); + while (state_ != State::DATA && socket_ready) { APIError err = state_action_(); if (err == APIError::WOULD_BLOCK) { break; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 5503cf4db8..28128d39bc 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -148,12 +148,16 @@ void APIServer::loop() { while (client_index < this->clients_.size()) { auto &client = this->clients_[client_index]; + // Common case: process active client + if (!client->flags_.remove) { + client->loop(); + } + // Handle disconnection promptly - close socket to free LWIP PCB + // resources and prevent retransmit crashes on ESP8266. if (client->flags_.remove) { // Rare case: handle disconnection (don't increment - swapped element needs processing) this->remove_client_(client_index); } else { - // Common case: process active client - client->loop(); client_index++; } } From a8a324cbfbdcb2b41de9de3a544230bf372a104a Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Sat, 14 Feb 2026 13:53:54 +1300 Subject: [PATCH 0713/2030] Bump version to 2026.2.0b2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 16516a387f..572e20a694 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0b1 +PROJECT_NUMBER = 2026.2.0b2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 3b5cccfb25..247b2b7e4e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0b1" +__version__ = "2026.2.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 36776b40c2010b6635c9bad297e4985c9db4cbcb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Feb 2026 08:21:04 -0700 Subject: [PATCH 0714/2030] [wifi] Fix ESP8266 DHCP state corruption from premature dhcp_renew() (#13983) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/wifi/wifi_component_esp8266.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index c87345f0bf..cbf7d7d80f 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -216,23 +216,16 @@ bool WiFiComponent::wifi_apply_hostname_() { ESP_LOGV(TAG, "Set hostname failed"); } - // inform dhcp server of hostname change using dhcp_renew() + // Update hostname on all lwIP interfaces so DHCP packets include it. + // lwIP includes the hostname in DHCP DISCOVER/REQUEST automatically + // via LWIP_NETIF_HOSTNAME — no dhcp_renew() needed. The hostname is + // fixed at compile time and never changes at runtime. for (netif *intf = netif_list; intf; intf = intf->next) { - // unconditionally update all known interfaces #if LWIP_VERSION_MAJOR == 1 intf->hostname = (char *) wifi_station_get_hostname(); #else intf->hostname = wifi_station_get_hostname(); #endif - if (netif_dhcp_data(intf) != nullptr) { - // renew already started DHCP leases - err_t lwipret = dhcp_renew(intf); - if (lwipret != ERR_OK) { - ESP_LOGW(TAG, "wifi_apply_hostname_(%s): lwIP error %d on interface %c%c (index %d)", intf->hostname, - (int) lwipret, intf->name[0], intf->name[1], intf->num); - ret = false; - } - } } return ret; From 5a6d64814a3a5f51f6e238620938416523947e94 Mon Sep 17 00:00:00 2001 From: AndreKR <haensel@creations.de> Date: Sat, 14 Feb 2026 18:08:26 +0100 Subject: [PATCH 0715/2030] [http_request] Improve TLS logging on ESP8266 (#13985) --- .../http_request/http_request_arduino.cpp | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index aee1f651bf..e5b919e380 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -9,9 +9,20 @@ #include "esphome/core/defines.h" #include "esphome/core/log.h" +// Include BearSSL error constants for TLS failure diagnostics +#ifdef USE_ESP8266 +#include <bearssl/bearssl_ssl.h> +#endif + namespace esphome::http_request { static const char *const TAG = "http_request.arduino"; +#ifdef USE_ESP8266 +static constexpr int RX_BUFFER_SIZE = 512; +static constexpr int TX_BUFFER_SIZE = 512; +// ESP8266 Arduino core (WiFiClientSecureBearSSL.cpp) returns -1000 on OOM +static constexpr int ESP8266_SSL_ERR_OOM = -1000; +#endif std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &url, const std::string &method, const std::string &body, @@ -47,7 +58,7 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); stream_ptr = std::make_unique<WiFiClientSecure>(); WiFiClientSecure *secure_client = static_cast<WiFiClientSecure *>(stream_ptr.get()); - secure_client->setBufferSizes(512, 512); + secure_client->setBufferSizes(RX_BUFFER_SIZE, TX_BUFFER_SIZE); secure_client->setInsecure(); } else { stream_ptr = std::make_unique<WiFiClient>(); @@ -107,13 +118,42 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur container->status_code = container->client_.sendRequest(method.c_str(), body.c_str()); App.feed_wdt(); if (container->status_code < 0) { +#if defined(USE_ESP8266) && defined(USE_HTTP_REQUEST_ESP8266_HTTPS) + if (secure) { + WiFiClientSecure *secure_client = static_cast<WiFiClientSecure *>(stream_ptr.get()); + int last_error = secure_client->getLastSSLError(); + + if (last_error != 0) { + const LogString *error_msg; + switch (last_error) { + case ESP8266_SSL_ERR_OOM: + error_msg = LOG_STR("Unable to allocate buffer memory"); + break; + case BR_ERR_TOO_LARGE: + error_msg = LOG_STR("Incoming TLS record does not fit in receive buffer (BR_ERR_TOO_LARGE)"); + break; + default: + error_msg = LOG_STR("Unknown SSL error"); + break; + } + ESP_LOGW(TAG, "SSL failure: %s (Code: %d)", LOG_STR_ARG(error_msg), last_error); + if (last_error == ESP8266_SSL_ERR_OOM) { + ESP_LOGW(TAG, "Heap free: %u bytes, configured buffer sizes: %u bytes", ESP.getFreeHeap(), + static_cast<unsigned int>(RX_BUFFER_SIZE + TX_BUFFER_SIZE)); + } + } else { + ESP_LOGW(TAG, "Connection failure with no error code"); + } + } +#endif + 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 (!is_success(container->status_code)) { ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); this->status_momentary_error("failed", 1000); From 38404b2013f031c921ac43cbec4f3d4b898deccf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Feb 2026 15:11:17 -0700 Subject: [PATCH 0716/2030] Bump ruff from 0.15.0 to 0.15.1 (#13980) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 991e053d5a..6d89060b0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.0 + rev: v0.15.1 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 2cf6f6456e..9e99855f6f 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.4 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.0 # also change in .pre-commit-config.yaml when updating +ruff==0.15.1 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From f48c8a64443e56e06f90271cbfd8d0e67116093d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 12:11:36 -0500 Subject: [PATCH 0717/2030] [combination] Fix 'coeffecient' typo with backward-compatible deprecation (#14004) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/combination/combination.cpp | 2 +- esphome/components/combination/sensor.py | 46 +++++++++++++++---- tests/components/combination/common.yaml | 4 +- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/esphome/components/combination/combination.cpp b/esphome/components/combination/combination.cpp index 716d270390..ece7cca482 100644 --- a/esphome/components/combination/combination.cpp +++ b/esphome/components/combination/combination.cpp @@ -126,7 +126,7 @@ void LinearCombinationComponent::setup() { } void LinearCombinationComponent::handle_new_value(float value) { - // Multiplies each sensor state by a configured coeffecient and then sums + // Multiplies each sensor state by a configured coefficient and then sums if (!std::isfinite(value)) return; diff --git a/esphome/components/combination/sensor.py b/esphome/components/combination/sensor.py index f5255fec03..0204162e8d 100644 --- a/esphome/components/combination/sensor.py +++ b/esphome/components/combination/sensor.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv @@ -15,6 +17,8 @@ from esphome.const import ( ) from esphome.core.entity_helpers import inherit_property_from +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@Cat-Ion", "@kahrendt"] combination_ns = cg.esphome_ns.namespace("combination") @@ -47,7 +51,8 @@ SumCombinationComponent = combination_ns.class_( "SumCombinationComponent", cg.Component, sensor.Sensor ) -CONF_COEFFECIENT = "coeffecient" +CONF_COEFFICIENT = "coefficient" +CONF_COEFFECIENT = "coeffecient" # Deprecated, remove before 2026.12.0 CONF_ERROR = "error" CONF_KALMAN = "kalman" CONF_LINEAR = "linear" @@ -68,11 +73,34 @@ KALMAN_SOURCE_SCHEMA = cv.Schema( } ) -LINEAR_SOURCE_SCHEMA = cv.Schema( - { - cv.Required(CONF_SOURCE): cv.use_id(sensor.Sensor), - cv.Required(CONF_COEFFECIENT): cv.templatable(cv.float_), - } + +def _migrate_coeffecient(config): + """Migrate deprecated 'coeffecient' spelling to 'coefficient'.""" + if CONF_COEFFECIENT in config: + if CONF_COEFFICIENT in config: + raise cv.Invalid( + f"Cannot specify both '{CONF_COEFFICIENT}' and '{CONF_COEFFECIENT}'" + ) + _LOGGER.warning( + "'%s' is deprecated, use '%s' instead. Will be removed in 2026.12.0", + CONF_COEFFECIENT, + CONF_COEFFICIENT, + ) + config[CONF_COEFFICIENT] = config.pop(CONF_COEFFECIENT) + elif CONF_COEFFICIENT not in config: + raise cv.Invalid(f"'{CONF_COEFFICIENT}' is a required option") + return config + + +LINEAR_SOURCE_SCHEMA = cv.All( + cv.Schema( + { + cv.Required(CONF_SOURCE): cv.use_id(sensor.Sensor), + cv.Optional(CONF_COEFFICIENT): cv.templatable(cv.float_), + cv.Optional(CONF_COEFFECIENT): cv.templatable(cv.float_), + } + ), + _migrate_coeffecient, ) SENSOR_ONLY_SOURCE_SCHEMA = cv.Schema( @@ -162,12 +190,12 @@ async def to_code(config): ) cg.add(var.add_source(source, error)) elif config[CONF_TYPE] == CONF_LINEAR: - coeffecient = await cg.templatable( - source_conf[CONF_COEFFECIENT], + coefficient = await cg.templatable( + source_conf[CONF_COEFFICIENT], [(float, "x")], cg.float_, ) - cg.add(var.add_source(source, coeffecient)) + cg.add(var.add_source(source, coefficient)) else: cg.add(var.add_source(source)) diff --git a/tests/components/combination/common.yaml b/tests/components/combination/common.yaml index 0e5d512d08..5d46419399 100644 --- a/tests/components/combination/common.yaml +++ b/tests/components/combination/common.yaml @@ -27,9 +27,9 @@ sensor: name: Linearly combined temperatures sources: - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" + coefficient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - source: template_temperature2 - coeffecient: 1.5 + coefficient: 1.5 - platform: combination type: max name: Max of combined temperatures From 0f4dc6702df0d9646cfd28d85ae86a34bc2f6b6d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 12:11:50 -0500 Subject: [PATCH 0718/2030] [fan] Fix preset_mode not restored on boot (#14002) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/fan/fan.cpp | 8 +++++++- esphome/components/fan/fan.h | 4 +++- esphome/components/hbridge/fan/hbridge_fan.cpp | 8 ++++---- esphome/components/speed/fan/speed_fan.cpp | 8 ++++---- esphome/components/template/fan/template_fan.cpp | 10 +++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index d70a2940bc..c1e0a3dc2e 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -221,12 +221,17 @@ void Fan::publish_state() { } // Random 32-bit value, change this every time the layout of the FanRestoreState struct changes. -constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABA; +constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABB; optional<FanRestoreState> Fan::restore_state_() { FanRestoreState recovered{}; this->rtc_ = this->make_entity_preference<FanRestoreState>(RESTORE_STATE_VERSION); bool restored = this->rtc_.load(&recovered); + if (!restored) { + // No valid saved data; ensure preset_mode sentinel is set + recovered.preset_mode = FanRestoreState::NO_PRESET; + } + switch (this->restore_mode_) { case FanRestoreMode::NO_RESTORE: return {}; @@ -264,6 +269,7 @@ void Fan::save_state_() { state.oscillating = this->oscillating; state.speed = this->speed; state.direction = this->direction; + state.preset_mode = FanRestoreState::NO_PRESET; if (this->has_preset_mode()) { const auto &preset_modes = traits.supported_preset_modes(); diff --git a/esphome/components/fan/fan.h b/esphome/components/fan/fan.h index 55d4ba8825..2caf3a712a 100644 --- a/esphome/components/fan/fan.h +++ b/esphome/components/fan/fan.h @@ -91,11 +91,13 @@ class FanCall { }; struct FanRestoreState { + static constexpr uint8_t NO_PRESET = UINT8_MAX; + bool state; int speed; bool oscillating; FanDirection direction; - uint8_t preset_mode; + uint8_t preset_mode{NO_PRESET}; /// Convert this struct to a fan call that can be performed. FanCall to_call(Fan &fan); diff --git a/esphome/components/hbridge/fan/hbridge_fan.cpp b/esphome/components/hbridge/fan/hbridge_fan.cpp index 9bf58f9d1e..38e4129e66 100644 --- a/esphome/components/hbridge/fan/hbridge_fan.cpp +++ b/esphome/components/hbridge/fan/hbridge_fan.cpp @@ -28,15 +28,15 @@ fan::FanCall HBridgeFan::brake() { } void HBridgeFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); this->write_state_(); } - - // Construct traits - this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void HBridgeFan::dump_config() { diff --git a/esphome/components/speed/fan/speed_fan.cpp b/esphome/components/speed/fan/speed_fan.cpp index af98e3a51f..55f7fd162c 100644 --- a/esphome/components/speed/fan/speed_fan.cpp +++ b/esphome/components/speed/fan/speed_fan.cpp @@ -7,15 +7,15 @@ namespace speed { static const char *const TAG = "speed.fan"; void SpeedFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); this->write_state_(); } - - // Construct traits - this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void SpeedFan::dump_config() { LOG_FAN("", "Speed Fan", this); } diff --git a/esphome/components/template/fan/template_fan.cpp b/esphome/components/template/fan/template_fan.cpp index 0e1920a984..cd267bd552 100644 --- a/esphome/components/template/fan/template_fan.cpp +++ b/esphome/components/template/fan/template_fan.cpp @@ -6,15 +6,15 @@ namespace esphome::template_ { static const char *const TAG = "template.fan"; void TemplateFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = + fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); } - - // Construct traits - this->traits_ = - fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void TemplateFan::dump_config() { LOG_FAN("", "Template Fan", this); } From 6303bc3e355bd73c22658a2745d8d5e19e195755 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:23:06 -0500 Subject: [PATCH 0719/2030] [esp32_rmt] Handle ESP32 variants without RMT hardware (#14001) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_rmt/__init__.py | 22 +++++ .../components/esp32_rmt_led_strip/light.py | 6 +- esphome/components/remote_base/remote_base.h | 5 +- .../components/remote_receiver/__init__.py | 41 +++++++- .../remote_receiver/remote_receiver.cpp | 2 +- .../remote_receiver/remote_receiver.h | 17 ++-- .../remote_receiver/remote_receiver_esp32.cpp | 5 +- .../components/remote_transmitter/__init__.py | 93 ++++++++++++------- .../remote_transmitter/automation.h | 6 +- .../remote_transmitter/remote_transmitter.cpp | 8 +- .../remote_transmitter/remote_transmitter.h | 21 +++-- .../remote_transmitter_esp32.cpp | 11 ++- .../remote_receiver/test.esp32-c2-idf.yaml | 12 +++ .../remote_transmitter/test.esp32-c2-idf.yaml | 7 ++ 14 files changed, 181 insertions(+), 75 deletions(-) create mode 100644 tests/components/remote_receiver/test.esp32-c2-idf.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-c2-idf.yaml diff --git a/esphome/components/esp32_rmt/__init__.py b/esphome/components/esp32_rmt/__init__.py index 272c7c81ba..1076bcabdc 100644 --- a/esphome/components/esp32_rmt/__init__.py +++ b/esphome/components/esp32_rmt/__init__.py @@ -1,8 +1,30 @@ from esphome.components import esp32 import esphome.config_validation as cv +from esphome.core import CORE CODEOWNERS = ["@jesserockz"] +VARIANTS_NO_RMT = {esp32.VARIANT_ESP32C2, esp32.VARIANT_ESP32C61} + + +def validate_rmt_not_supported(rmt_only_keys): + """Validate that RMT-only config keys are not used on variants without RMT hardware.""" + rmt_only_keys = set(rmt_only_keys) + + def _validator(config): + if CORE.is_esp32: + variant = esp32.get_esp32_variant() + if variant in VARIANTS_NO_RMT: + unsupported = rmt_only_keys.intersection(config) + if unsupported: + keys = ", ".join(sorted(f"'{k}'" for k in unsupported)) + raise cv.Invalid( + f"{keys} not available on {variant} (no RMT hardware)" + ) + return config + + return _validator + def validate_clock_resolution(): def _validator(value): diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 6d41f6b5b8..1c6943b003 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -3,7 +3,7 @@ import logging from esphome import pins import esphome.codegen as cg -from esphome.components import esp32, light +from esphome.components import esp32, esp32_rmt, light from esphome.components.const import CONF_USE_PSRAM from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv @@ -71,6 +71,10 @@ CONF_RESET_LOW = "reset_low" CONFIG_SCHEMA = cv.All( + esp32.only_on_variant( + unsupported=list(esp32_rmt.VARIANTS_NO_RMT), + msg_prefix="ESP32 RMT LED strip", + ), light.ADDRESSABLE_LIGHT_SCHEMA.extend( { cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(ESP32RMTLEDStripLightOutput), diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 0cac28506f..d73fff2b0a 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -119,6 +119,8 @@ class RemoteComponentBase { }; #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED class RemoteRMTChannel { public: void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; } @@ -137,7 +139,8 @@ class RemoteRMTChannel { uint32_t clock_resolution_{1000000}; uint32_t rmt_symbols_; }; -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 class RemoteTransmitterBase : public RemoteComponentBase { public: diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index b3dc213c5f..362f6e99db 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -65,6 +65,8 @@ RemoteReceiverComponent = remote_receiver_ns.class_( def validate_config(config): if CORE.is_esp32: variant = esp32.get_esp32_variant() + if variant in esp32_rmt.VARIANTS_NO_RMT: + return config if variant in (esp32.VARIANT_ESP32, esp32.VARIANT_ESP32S2): max_idle = 65535 else: @@ -110,6 +112,8 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_BUFFER_SIZE, esp32="10000b", + esp32_c2="1000b", + esp32_c61="1000b", esp8266="1000b", bk72xx="1000b", ln882x="1000b", @@ -131,9 +135,11 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_RMT_SYMBOLS, esp32=192, + esp32_c2=cv.UNDEFINED, esp32_c3=96, esp32_c5=96, esp32_c6=96, + esp32_c61=cv.UNDEFINED, esp32_h2=96, esp32_p4=192, esp32_s2=192, @@ -145,6 +151,8 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_RECEIVE_SYMBOLS, esp32=192, + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), cv.Optional(CONF_USE_DMA): cv.All( esp32.only_on_variant( @@ -152,24 +160,45 @@ CONFIG_SCHEMA = remote_base.validate_triggers( ), cv.boolean, ), - cv.SplitDefault(CONF_CARRIER_DUTY_PERCENT, esp32=100): cv.All( + cv.SplitDefault( + CONF_CARRIER_DUTY_PERCENT, + esp32=100, + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, + ): cv.All( cv.only_on_esp32, cv.percentage_int, cv.Range(min=1, max=100), ), - cv.SplitDefault(CONF_CARRIER_FREQUENCY, esp32="0Hz"): cv.All( - cv.only_on_esp32, cv.frequency, cv.int_ - ), + cv.SplitDefault( + CONF_CARRIER_FREQUENCY, + esp32="0Hz", + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, + ): cv.All(cv.only_on_esp32, cv.frequency, cv.int_), } ) .extend(cv.COMPONENT_SCHEMA) + .add_extra( + esp32_rmt.validate_rmt_not_supported( + [ + CONF_CLOCK_RESOLUTION, + CONF_USE_DMA, + CONF_RMT_SYMBOLS, + CONF_FILTER_SYMBOLS, + CONF_RECEIVE_SYMBOLS, + CONF_CARRIER_DUTY_PERCENT, + CONF_CARRIER_FREQUENCY, + ] + ) + ) .add_extra(validate_config) ) async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - if CORE.is_esp32: + if CORE.is_esp32 and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT: # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) esp32.include_builtin_idf_component("esp_driver_rmt") @@ -213,6 +242,8 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_IDF, }, "remote_receiver.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, PlatformFramework.RTL87XX_ARDUINO, diff --git a/esphome/components/remote_receiver/remote_receiver.cpp b/esphome/components/remote_receiver/remote_receiver.cpp index de47457dac..d59ee63695 100644 --- a/esphome/components/remote_receiver/remote_receiver.cpp +++ b/esphome/components/remote_receiver/remote_receiver.cpp @@ -3,7 +3,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) namespace esphome::remote_receiver { diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 3d9199a904..5da9283a6e 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -6,12 +6,15 @@ #include <cinttypes> #if defined(USE_ESP32) +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/rmt_rx.h> -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 namespace esphome::remote_receiver { -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) struct RemoteReceiverComponentStore { static void gpio_intr(RemoteReceiverComponentStore *arg); @@ -35,7 +38,7 @@ struct RemoteReceiverComponentStore { volatile bool prev_level{false}; volatile bool overflow{false}; }; -#elif defined(USE_ESP32) +#elif defined(USE_ESP32) && SOC_RMT_SUPPORTED struct RemoteReceiverComponentStore { /// Stores RMT symbols and rx done event data volatile uint8_t *buffer{nullptr}; @@ -54,7 +57,7 @@ struct RemoteReceiverComponentStore { class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, public Component -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED , public remote_base::RemoteRMTChannel #endif @@ -66,7 +69,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void dump_config() override; void loop() override; -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void set_filter_symbols(uint32_t filter_symbols) { this->filter_symbols_ = filter_symbols; } void set_receive_symbols(uint32_t receive_symbols) { this->receive_symbols_ = receive_symbols; } void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } @@ -78,7 +81,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; } protected: -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void decode_rmt_(rmt_symbol_word_t *item, size_t item_count); rmt_channel_handle_t channel_{NULL}; uint32_t filter_symbols_{0}; @@ -94,7 +97,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, RemoteReceiverComponentStore store_; #endif -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) HighFrequencyLoopRequester high_freq_; #endif diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index f95244ea45..357a36d052 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -2,6 +2,8 @@ #include "esphome/core/log.h" #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/gpio.h> #include <esp_clk_tree.h> @@ -248,4 +250,5 @@ void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_c } // namespace esphome::remote_receiver -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index 8383b9dd75..fc772f88b2 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -40,45 +40,66 @@ DigitalWriteAction = remote_transmitter_ns.class_( cg.Parented.template(RemoteTransmitterComponent), ) + MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( - cv.percentage_int, cv.Range(min=1, max=100) - ), - cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( - cv.only_on_esp32, - esp32_rmt.validate_clock_resolution(), - ), - cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_on_esp32, cv.boolean), - cv.Optional(CONF_USE_DMA): cv.All( - esp32.only_on_variant( - supported=[esp32.VARIANT_ESP32P4, esp32.VARIANT_ESP32S3] +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( + cv.percentage_int, cv.Range(min=1, max=100) ), - cv.boolean, - ), - cv.SplitDefault( - CONF_RMT_SYMBOLS, - esp32=64, - esp32_c3=48, - esp32_c5=48, - esp32_c6=48, - esp32_h2=48, - esp32_p4=48, - esp32_s2=64, - esp32_s3=48, - ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), - cv.Optional(CONF_NON_BLOCKING): cv.All(cv.only_on_esp32, cv.boolean), - cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), - cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), - } -).extend(cv.COMPONENT_SCHEMA) + cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( + cv.only_on_esp32, + esp32_rmt.validate_clock_resolution(), + ), + cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_on_esp32, cv.boolean), + cv.Optional(CONF_USE_DMA): cv.All( + esp32.only_on_variant( + supported=[esp32.VARIANT_ESP32P4, esp32.VARIANT_ESP32S3] + ), + cv.boolean, + ), + cv.SplitDefault( + CONF_RMT_SYMBOLS, + esp32=64, + esp32_c2=cv.UNDEFINED, + esp32_c3=48, + esp32_c5=48, + esp32_c6=48, + esp32_c61=cv.UNDEFINED, + esp32_h2=48, + esp32_p4=48, + esp32_s2=64, + esp32_s3=48, + ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), + cv.Optional(CONF_NON_BLOCKING): cv.All(cv.only_on_esp32, cv.boolean), + cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), + cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .add_extra( + esp32_rmt.validate_rmt_not_supported( + [ + CONF_CLOCK_RESOLUTION, + CONF_EOT_LEVEL, + CONF_USE_DMA, + CONF_RMT_SYMBOLS, + CONF_NON_BLOCKING, + ] + ) + ) +) def _validate_non_blocking(config): - if CORE.is_esp32 and CONF_NON_BLOCKING not in config: + if ( + CORE.is_esp32 + and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT + and CONF_NON_BLOCKING not in config + ): _LOGGER.warning( "'non_blocking' is not set for 'remote_transmitter' and will default to 'true'.\n" "The default behavior changed in 2025.11.0; previously blocking mode was used.\n" @@ -111,7 +132,7 @@ async def digital_write_action_to_code(config, action_id, template_arg, args): async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - if CORE.is_esp32: + if CORE.is_esp32 and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT: # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) esp32.include_builtin_idf_component("esp_driver_rmt") @@ -155,6 +176,8 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_IDF, }, "remote_transmitter.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, PlatformFramework.RTL87XX_ARDUINO, diff --git a/esphome/components/remote_transmitter/automation.h b/esphome/components/remote_transmitter/automation.h index bee1d0be8a..8da4cfd95d 100644 --- a/esphome/components/remote_transmitter/automation.h +++ b/esphome/components/remote_transmitter/automation.h @@ -5,8 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { template<typename... Ts> class DigitalWriteAction : public Action<Ts...>, public Parented<RemoteTransmitterComponent> { public: @@ -14,5 +13,4 @@ template<typename... Ts> class DigitalWriteAction : public Action<Ts...>, public void play(const Ts &...x) override { this->parent_->digital_write(this->value_.value(x...)); } }; -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter.cpp b/esphome/components/remote_transmitter/remote_transmitter.cpp index d35541e2e1..51a3c0b1d4 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter.cpp @@ -2,10 +2,9 @@ #include "esphome/core/log.h" #include "esphome/core/application.h" -#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { static const char *const TAG = "remote_transmitter"; @@ -105,7 +104,6 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen this->complete_trigger_.trigger(); } -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter #endif diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index 65bd2ac8b2..aee52ea170 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -6,13 +6,15 @@ #include <vector> #if defined(USE_ESP32) +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/rmt_tx.h> -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1) // IDF version 5.5.1 and above is required because of a bug in // the RMT encoder: https://github.com/espressif/esp-idf/issues/17244 @@ -33,7 +35,7 @@ struct RemoteTransmitterComponentStore { class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, public Component -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED , public remote_base::RemoteRMTChannel #endif @@ -51,7 +53,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void digital_write(bool value); -#if defined(USE_ESP32) +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } void set_eot_level(bool eot_level) { this->eot_level_ = eot_level; } void set_non_blocking(bool non_blocking) { this->non_blocking_ = non_blocking; } @@ -62,7 +64,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) void calculate_on_off_time_(uint32_t carrier_frequency, uint32_t *on_time_period, uint32_t *off_time_period); void mark_(uint32_t on_time, uint32_t off_time, uint32_t usec); @@ -73,7 +75,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, uint32_t target_time_; #endif -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void configure_rmt_(); void wait_for_rmt_(); @@ -100,5 +102,4 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, Trigger<> complete_trigger_; }; -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index 89d97895b2..71773e3ddf 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -3,10 +3,11 @@ #include "esphome/core/application.h" #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/gpio.h> -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { static const char *const TAG = "remote_transmitter"; @@ -358,7 +359,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen } #endif -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 diff --git a/tests/components/remote_receiver/test.esp32-c2-idf.yaml b/tests/components/remote_receiver/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..87154e19fc --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-c2-idf.yaml @@ -0,0 +1,12 @@ +remote_receiver: + id: rcvr + pin: GPIO2 + dump: all + <<: !include common-actions.yaml + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_transmitter/test.esp32-c2-idf.yaml b/tests/components/remote_transmitter/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..424cd8d249 --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-c2-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + id: xmitr + pin: GPIO2 + carrier_duty_percent: 50% + +packages: + buttons: !include common-buttons.yaml From 15da6d0a0b3a7ec14462e49c00f329af3808ce7b Mon Sep 17 00:00:00 2001 From: Pawelo <81100874+pgolawsk@users.noreply.github.com> Date: Sun, 15 Feb 2026 21:58:51 +0100 Subject: [PATCH 0720/2030] [epaper_spi] Add WeAct 3-color e-paper display support (#13894) --- esphome/components/epaper_spi/display.py | 4 - .../components/epaper_spi/epaper_weact_3c.cpp | 231 ++++++++++++++++++ .../components/epaper_spi/epaper_weact_3c.h | 39 +++ .../components/epaper_spi/models/weact_bwr.py | 75 ++++++ .../epaper_spi/test.esp32-s3-idf.yaml | 63 +++++ 5 files changed, 408 insertions(+), 4 deletions(-) create mode 100644 esphome/components/epaper_spi/epaper_weact_3c.cpp create mode 100644 esphome/components/epaper_spi/epaper_weact_3c.h create mode 100644 esphome/components/epaper_spi/models/weact_bwr.py diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index 13f66691b2..2657071f45 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -49,10 +49,6 @@ EPaperBase = epaper_spi_ns.class_( ) Transform = epaper_spi_ns.enum("Transform") -EPaperSpectraE6 = epaper_spi_ns.class_("EPaperSpectraE6", EPaperBase) -EPaper7p3InSpectraE6 = epaper_spi_ns.class_("EPaper7p3InSpectraE6", EPaperSpectraE6) - - # Import all models dynamically from the models package for module_info in pkgutil.iter_modules(models.__path__): importlib.import_module(f".models.{module_info.name}", package=__package__) diff --git a/esphome/components/epaper_spi/epaper_weact_3c.cpp b/esphome/components/epaper_spi/epaper_weact_3c.cpp new file mode 100644 index 0000000000..bd83105dd7 --- /dev/null +++ b/esphome/components/epaper_spi/epaper_weact_3c.cpp @@ -0,0 +1,231 @@ +#include "epaper_weact_3c.h" +#include "esphome/core/log.h" + +namespace esphome::epaper_spi { + +static constexpr const char *const TAG = "epaper_weact_3c"; + +// SSD1680 3-color display notes: +// - Buffer uses 1 bit per pixel, 8 pixels per byte +// - Buffer first half (black_offset): Black/White plane (1=black, 0=white) +// - Buffer second half (red_offset): Red plane (1=red, 0=no red) +// - Total buffer: width * height / 4 bytes = 2 * (width * height / 8) +// - For 128x296: 128*296/4 = 9472 bytes total (4736 per color) + +void EPaperWeAct3C::draw_pixel_at(int x, int y, Color color) { + if (!this->rotate_coordinates_(x, y)) + return; + + // Calculate position in the 1-bit buffer + const uint32_t pos = (x / 8) + (y * this->row_width_); + const uint8_t bit = 0x80 >> (x & 0x07); + const uint32_t red_offset = this->buffer_length_ / 2u; + + // Use luminance threshold for B/W mapping + // Split at halfway point (382 = (255*3)/2) + bool is_white = (static_cast<int>(color.r) + color.g + color.b) > 382; + + // Update black/white plane (first half of buffer) + if (is_white) { + // White pixel - clear bit in black plane + this->buffer_[pos] &= ~bit; + } else { + // Black pixel - set bit in black plane + this->buffer_[pos] |= bit; + } + + // Update red plane (second half of buffer) + // Red if red component is dominant (r > g+b) + if (color.r > color.g + color.b) { + // Red pixel - set bit in red plane + this->buffer_[red_offset + pos] |= bit; + } else { + // Not red - clear bit in red plane + this->buffer_[red_offset + pos] &= ~bit; + } +} + +void EPaperWeAct3C::fill(Color color) { + // For 3-color e-paper with 1-bit buffer format: + // - Black buffer: 1=black, 0=white + // - Red buffer: 1=red, 0=no red + // The buffer is stored as two halves: [black plane][red plane] + const size_t half_buffer = this->buffer_length_ / 2u; + + // Use luminance threshold for B/W mapping + bool is_white = (static_cast<int>(color.r) + color.g + color.b) > 382; + bool is_red = color.r > color.g + color.b; + + // Fill both planes + if (is_white) { + // White - both planes = 0x00 + this->buffer_.fill(0x00); + } else if (is_red) { + // Red - black plane = 0x00, red plane = 0xFF + for (size_t i = 0; i < half_buffer; i++) + this->buffer_[i] = 0x00; + for (size_t i = 0; i < half_buffer; i++) + this->buffer_[half_buffer + i] = 0xFF; + } else { + // Black - black plane = 0xFF, red plane = 0x00 + for (size_t i = 0; i < half_buffer; i++) + this->buffer_[i] = 0xFF; + for (size_t i = 0; i < half_buffer; i++) + this->buffer_[half_buffer + i] = 0x00; + } +} + +void EPaperWeAct3C::clear() { + // Clear buffer to white, just like real paper. + this->fill(COLOR_ON); +} + +void EPaperWeAct3C::set_window_() { + // For full screen refresh, we always start from (0,0) + // The y_low_/y_high_ values track the dirty region for optimization, + // but for display refresh we need to write from the beginning + uint16_t x_start = 0; + uint16_t x_end = this->width_ - 1; + uint16_t y_start = 0; + uint16_t y_end = this->height_ - 1; // height = 296 for 2.9" display + + // Set RAM X address boundaries (0x44) + // X coordinates are byte-aligned (divided by 8) + this->cmd_data(0x44, {(uint8_t) (x_start / 8), (uint8_t) (x_end / 8)}); + + // Set RAM Y address boundaries (0x45) + // Format: Y start (LSB, MSB), Y end (LSB, MSB) + this->cmd_data(0x45, {(uint8_t) y_start, (uint8_t) (y_start >> 8), (uint8_t) (y_end & 0xFF), (uint8_t) (y_end >> 8)}); + + // Reset RAM X counter to start (0x4E) - 1 byte + this->cmd_data(0x4E, {(uint8_t) (x_start / 8)}); + + // Reset RAM Y counter to start (0x4F) - 2 bytes (LSB, MSB) + this->cmd_data(0x4F, {(uint8_t) y_start, (uint8_t) (y_start >> 8)}); +} + +bool HOT EPaperWeAct3C::transfer_data() { + const uint32_t start_time = millis(); + const size_t buffer_length = this->buffer_length_; + const size_t half_buffer = buffer_length / 2u; + + ESP_LOGV(TAG, "transfer_data: buffer_length=%u, half_buffer=%u", buffer_length, half_buffer); + + // Use a local buffer for SPI transfers + static constexpr size_t MAX_TRANSFER_SIZE = 128; + uint8_t bytes_to_send[MAX_TRANSFER_SIZE]; + + // First, send the RED buffer (0x26 = WRITE_COLOR) + // The red plane is in the second half of our buffer + // NOTE: Must set RAM window first to reset address counters! + if (this->current_data_index_ < half_buffer) { + if (this->current_data_index_ == 0) { + ESP_LOGV(TAG, "transfer_data: sending RED buffer (0x26)"); + this->set_window_(); // Reset RAM X/Y counters to start position + this->command(0x26); + } + + this->start_data_(); + size_t red_offset = half_buffer; + while (this->current_data_index_ < half_buffer) { + size_t bytes_to_copy = std::min(MAX_TRANSFER_SIZE, half_buffer - this->current_data_index_); + + for (size_t i = 0; i < bytes_to_copy; i++) { + bytes_to_send[i] = this->buffer_[red_offset + this->current_data_index_ + i]; + } + + this->write_array(bytes_to_send, bytes_to_copy); + + this->current_data_index_ += bytes_to_copy; + + if (millis() - start_time > MAX_TRANSFER_TIME) { + // Let the main loop run and come back next loop + this->disable(); + return false; + } + } + this->disable(); + } + + // Finished the red buffer, now send the BLACK buffer (0x24 = WRITE_BLACK) + // The black plane is in the first half of our buffer + if (this->current_data_index_ < buffer_length) { + if (this->current_data_index_ == half_buffer) { + ESP_LOGV(TAG, "transfer_data: finished red buffer, sending BLACK buffer (0x24)"); + + // Do NOT reset RAM counters here for WeAct displays (Reference implementation behavior) + // this->set_window(); + this->command(0x24); + // Continue using current_data_index_, but we need to map it to the start of the buffer + } + + this->start_data_(); + while (this->current_data_index_ < buffer_length) { + size_t remaining = buffer_length - this->current_data_index_; + size_t bytes_to_copy = std::min(MAX_TRANSFER_SIZE, remaining); + + // Calculate offset into the BLACK buffer (which is at the start of this->buffer_) + // current_data_index_ goes from half_buffer to buffer_length + size_t buffer_offset = this->current_data_index_ - half_buffer; + + for (size_t i = 0; i < bytes_to_copy; i++) { + bytes_to_send[i] = this->buffer_[buffer_offset + i]; + } + + this->write_array(bytes_to_send, bytes_to_copy); + + this->current_data_index_ += bytes_to_copy; + + if (millis() - start_time > MAX_TRANSFER_TIME) { + // Let the main loop run and come back next loop + this->disable(); + return false; + } + } + this->disable(); + } + + this->current_data_index_ = 0; + ESP_LOGV(TAG, "transfer_data: completed (red=%u, black=%u bytes)", half_buffer, half_buffer); + return true; +} + +void EPaperWeAct3C::refresh_screen(bool partial) { + // SSD1680 refresh sequence: + // Reset RAM X/Y address counters to 0,0 so display reads from start + // 0x4E: RAM X counter - 1 byte (X / 8) + // 0x4F: RAM Y counter - 2 bytes (Y LSB, Y MSB) + this->cmd_data(0x4E, {0x00}); // RAM X counter = 0 (1 byte) + this->cmd_data(0x4F, {0x00, 0x00}); // RAM Y counter = 0 (2 bytes) + + // Send UPDATE_FULL command (0x22) with display update control parameter + // Both WeAct and waveshare reference use 0xF7: {0x22, 0xF7} + // 0xF7 = Display update: Load temperature, Load LUT, Enable RAM content + this->cmd_data(0x22, {0xF7}); // Command 0x22 with parameter 0xF7 + this->command(0x20); // Activate display update + + // COMMAND TERMINATE FRAME READ WRITE (required by SSD1680) + // Removed 0xFF based on working reference implementation + // this->command(0xFF); +} + +void EPaperWeAct3C::power_on() { + // Power on sequence - send command to turn on power + // According to SSD1680 spec: 0x22, 0xF8 powers on the display + this->cmd_data(0x22, {0xF8}); // Power on + this->command(0x20); // Activate +} + +void EPaperWeAct3C::power_off() { + // Power off sequence - send command to turn off power + // According to SSD1680 spec: 0x22, 0x83 powers off the display + this->cmd_data(0x22, {0x83}); // Power off + this->command(0x20); // Activate +} + +void EPaperWeAct3C::deep_sleep() { + // Deep sleep sequence + this->cmd_data(0x10, {0x01}); // Deep sleep mode +} + +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/epaper_weact_3c.h b/esphome/components/epaper_spi/epaper_weact_3c.h new file mode 100644 index 0000000000..2df6f1ba09 --- /dev/null +++ b/esphome/components/epaper_spi/epaper_weact_3c.h @@ -0,0 +1,39 @@ +#pragma once + +#include "epaper_spi.h" + +namespace esphome::epaper_spi { + +/** + * WeAct 3-color e-paper displays (SSD1683 controller). + * Supports multiple sizes: 2.9" (128x296), 4.2" (400x300), etc. + * + * Color scheme: Black, White, Red (BWR) + * Buffer layout: 1 bit per pixel, separate planes + * - Buffer first half: Black/White plane (1=black, 0=white) + * - Buffer second half: Red plane (1=red, 0=no red) + * - Total buffer: width * height / 4 bytes (2 * width * height / 8) + */ +class EPaperWeAct3C : public EPaperBase { + public: + EPaperWeAct3C(const char *name, uint16_t width, uint16_t height, const uint8_t *init_sequence, + size_t init_sequence_length) + : EPaperBase(name, width, height, init_sequence, init_sequence_length, DISPLAY_TYPE_BINARY) { + this->buffer_length_ = this->row_width_ * height * 2; + } + + void fill(Color color) override; + void clear() override; + + protected: + void set_window_(); + void refresh_screen(bool partial) override; + void power_on() override; + void power_off() override; + void deep_sleep() override; + void draw_pixel_at(int x, int y, Color color) override; + + bool transfer_data() override; +}; + +} // namespace esphome::epaper_spi diff --git a/esphome/components/epaper_spi/models/weact_bwr.py b/esphome/components/epaper_spi/models/weact_bwr.py new file mode 100644 index 0000000000..21a015b08d --- /dev/null +++ b/esphome/components/epaper_spi/models/weact_bwr.py @@ -0,0 +1,75 @@ +"""WeAct Black/White/Red e-paper displays using SSD1683 controller. + +Supported models: +- weact-2.13in-3c: 122x250 pixels (2.13" display) +- weact-2.9in-3c: 128x296 pixels (2.9" display) +- weact-4.2in-3c: 400x300 pixels (4.2" display) + +These displays use SSD1680 or SSD1683 controller and require a specific initialization +sequence. The DRV_OUT_CTL command is calculated from the display height. +""" + +from . import EpaperModel + + +class WeActBWR(EpaperModel): + """Base EpaperModel class for WeAct Black/White/Red displays using SSD1683 controller.""" + + def __init__(self, name, **defaults): + super().__init__(name, "EPaperWeAct3C", **defaults) + + def get_init_sequence(self, config): + """Generate initialization sequence for WeAct BWR displays. + + The initialization sequence is based on SSD1680 and SSD1683 controller datasheet + and the WeAct display specifications. + """ + _, height = self.get_dimensions(config) + # DRV_OUT_CTL: MSB of (height-1), LSB of (height-1), gate setting (0x00) + height_minus_1 = height - 1 + msb = height_minus_1 >> 8 + lsb = height_minus_1 & 0xFF + return ( + # Step 1: Software Reset (0x12) - REQUIRED per SSD1680, but works without it as well, so it's commented out for now + # (0x12,), + # Step 2: Wait 10ms after SWRESET (?) not sure how to implement wht waiting for 10ms after SWRESET, so it's commented out for now + # Step 3: DRV_OUT_CTL - driver output control (height-dependent) + # Format: (command, LSB, MSB, gate setting) + (0x01, lsb, msb, 0x00), + # Step 4: DATA_ENTRY - data entry mode (0x03 = decrement Y, increment X) + (0x11, 0x03), + # Step 5: BORDER_FULL - border waveform control + (0x3C, 0x05), + # Step 6: TEMP_SENS - internal temperature sensor + (0x18, 0x80), + # Step 7: DISPLAY_UPDATE - display update control + (0x21, 0x00, 0x80), + ) + + +# Model: WeAct 2.9" 3C - 128x296 pixels, SSD1680 controller +weact_2p9in3c = WeActBWR( + "weact-2.9in-3c", + width=128, + height=296, + data_rate="10MHz", + minimum_update_interval="1s", +) + +# Model: WeAct 2.13" 3C - 122x250 pixels, SSD1680 controller +weact_2p13in3c = WeActBWR( + "weact-2.13in-3c", + width=122, + height=250, + data_rate="10MHz", + minimum_update_interval="1s", +) + +# Model: WeAct 4.2" 3C - 400x300 pixels, SSD1683 controller +weact_4p2in3c = WeActBWR( + "weact-4.2in-3c", + width=400, + height=300, + data_rate="10MHz", + minimum_update_interval="10s", +) diff --git a/tests/components/epaper_spi/test.esp32-s3-idf.yaml b/tests/components/epaper_spi/test.esp32-s3-idf.yaml index 333ab567cd..aa454c73fa 100644 --- a/tests/components/epaper_spi/test.esp32-s3-idf.yaml +++ b/tests/components/epaper_spi/test.esp32-s3-idf.yaml @@ -64,3 +64,66 @@ display: # Override pins to avoid conflict with other display configs busy_pin: 43 dc_pin: 42 + + # WeAct 2.13" 3-color e-paper (122x250, SSD1680) + - platform: epaper_spi + spi_id: spi_bus + model: weact-2.13in-3c + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + lambda: |- + it.filled_rectangle(0, 0, it.get_width(), it.get_height(), Color::WHITE); + it.circle(it.get_width() / 2, it.get_height() / 2, 20, Color::BLACK); + it.circle(it.get_width() / 2, it.get_height() / 2, 15, Color(255, 0, 0)); + + # WeAct 2.9" 3-color e-paper (128x296, SSD1683) + - platform: epaper_spi + spi_id: spi_bus + model: weact-2.9in-3c + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + lambda: |- + it.filled_rectangle(0, 0, it.get_width(), it.get_height(), Color::WHITE); + it.circle(it.get_width() / 2, it.get_height() / 2, 20, Color::BLACK); + it.circle(it.get_width() / 2, it.get_height() / 2, 15, Color(255, 0, 0)); + + # WeAct 4.2" 3-color e-paper (400x300, SSD1683) + - platform: epaper_spi + spi_id: spi_bus + model: weact-4.2in-3c + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + lambda: |- + it.filled_rectangle(0, 0, it.get_width(), it.get_height(), Color::WHITE); + it.circle(it.get_width() / 2, it.get_height() / 2, 30, Color::BLACK); + it.circle(it.get_width() / 2, it.get_height() / 2, 20, Color(255, 0, 0)); From 066419019fb9997522788e940adbbf27243d5e6e Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Sun, 15 Feb 2026 15:09:35 -0600 Subject: [PATCH 0721/2030] [audio] Support reallocating non-empty AudioTransferBuffer (#13979) --- .../audio/audio_transfer_buffer.cpp | 34 +++++++++++++++---- .../components/audio/audio_transfer_buffer.h | 3 ++ 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/esphome/components/audio/audio_transfer_buffer.cpp b/esphome/components/audio/audio_transfer_buffer.cpp index 790cd62db0..ddb669e0eb 100644 --- a/esphome/components/audio/audio_transfer_buffer.cpp +++ b/esphome/components/audio/audio_transfer_buffer.cpp @@ -2,6 +2,8 @@ #ifdef USE_ESP32 +#include <cstring> + #include "esphome/core/helpers.h" namespace esphome { @@ -75,12 +77,32 @@ bool AudioTransferBuffer::has_buffered_data() const { } bool AudioTransferBuffer::reallocate(size_t new_buffer_size) { - if (this->buffer_length_ > 0) { - // Buffer currently has data, so reallocation is impossible + if (this->buffer_ == nullptr) { + return this->allocate_buffer_(new_buffer_size); + } + + if (new_buffer_size < this->buffer_length_) { + // New size is too small to hold existing data return false; } - this->deallocate_buffer_(); - return this->allocate_buffer_(new_buffer_size); + + // Shift existing data to the start of the buffer so realloc preserves it + if ((this->buffer_length_ > 0) && (this->data_start_ != this->buffer_)) { + std::memmove(this->buffer_, this->data_start_, this->buffer_length_); + this->data_start_ = this->buffer_; + } + + RAMAllocator<uint8_t> allocator; + uint8_t *new_buffer = allocator.reallocate(this->buffer_, new_buffer_size); + if (new_buffer == nullptr) { + // Reallocation failed, but the original buffer is still valid + return false; + } + + this->buffer_ = new_buffer; + this->data_start_ = this->buffer_; + this->buffer_size_ = new_buffer_size; + return true; } bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) { @@ -115,7 +137,7 @@ size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_ if (pre_shift) { // Shift data in buffer to start if (this->buffer_length_ > 0) { - memmove(this->buffer_, this->data_start_, this->buffer_length_); + std::memmove(this->buffer_, this->data_start_, this->buffer_length_); } this->data_start_ = this->buffer_; } @@ -150,7 +172,7 @@ size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait, if (post_shift) { // Shift unwritten data to the start of the buffer - memmove(this->buffer_, this->data_start_, this->buffer_length_); + std::memmove(this->buffer_, this->data_start_, this->buffer_length_); this->data_start_ = this->buffer_; } diff --git a/esphome/components/audio/audio_transfer_buffer.h b/esphome/components/audio/audio_transfer_buffer.h index edb484e7d2..24c0670d1a 100644 --- a/esphome/components/audio/audio_transfer_buffer.h +++ b/esphome/components/audio/audio_transfer_buffer.h @@ -56,6 +56,9 @@ class AudioTransferBuffer { /// @return True if there is data, false otherwise. virtual bool has_buffered_data() const; + /// @brief Reallocates the transfer buffer, preserving any existing data. + /// @param new_buffer_size The new size in bytes. Must be at least as large as available(). + /// @return True if successful, false otherwise. On failure, the original buffer remains valid. bool reallocate(size_t new_buffer_size); protected: From f2cb5db9e0dd543d33dd45e561412adf3c616f0e Mon Sep 17 00:00:00 2001 From: "Cornelius A. Ludmann" <github@cornelius-ludmann.de> Date: Mon, 16 Feb 2026 03:44:30 +0100 Subject: [PATCH 0722/2030] [epaper_spi] Add Waveshare 7.5in e-Paper (H) (#13991) --- .../components/epaper_spi/models/jd79660.py | 32 +++++++++++++++++++ .../epaper_spi/test.esp32-s3-idf.yaml | 17 ++++++++++ 2 files changed, 49 insertions(+) diff --git a/esphome/components/epaper_spi/models/jd79660.py b/esphome/components/epaper_spi/models/jd79660.py index 2d8830ebd2..a0457c5812 100644 --- a/esphome/components/epaper_spi/models/jd79660.py +++ b/esphome/components/epaper_spi/models/jd79660.py @@ -84,3 +84,35 @@ jd79660.extend( (0xA5, 0x00,), ), ) + +# Waveshare 7.5-H +# +# Vendor init derived from vendor sample code +# <https://github.com/waveshareteam/e-Paper/blob/master/E-paper_Separate_Program/7in5_e-Paper_H/ESP32/EPD_7in5h.cpp> +# Compatible MIT license, see esphome/LICENSE file. +# +# Note: busy pin uses LOW=busy, HIGH=idle. Configure with inverted: true in YAML. +# +# fmt: off +jd79660.extend( + "Waveshare-7.5in-H", + width=800, + height=480, + + initsequence=( + (0x00, 0x0F, 0x29,), + (0x06, 0x0F, 0x8B, 0x93, 0xA1,), + (0x41, 0x00,), + (0x50, 0x37,), + (0x60, 0x02, 0x02,), + (0x61, 800 // 256, 800 % 256, 480 // 256, 480 % 256,), # RES: 800x480 + (0x62, 0x98, 0x98, 0x98, 0x75, 0xCA, 0xB2, 0x98, 0x7E,), + (0x65, 0x00, 0x00, 0x00, 0x00,), + (0xE7, 0x1C,), + (0xE3, 0x00,), + (0xE9, 0x01,), + (0x30, 0x08,), + # Power On (0x04): Must be early part of init seq = Disabled later! + (0x04,), + ), +) diff --git a/tests/components/epaper_spi/test.esp32-s3-idf.yaml b/tests/components/epaper_spi/test.esp32-s3-idf.yaml index aa454c73fa..9593d0f6f0 100644 --- a/tests/components/epaper_spi/test.esp32-s3-idf.yaml +++ b/tests/components/epaper_spi/test.esp32-s3-idf.yaml @@ -57,6 +57,23 @@ display: allow_other_uses: true number: GPIO4 + - platform: epaper_spi + spi_id: spi_bus + model: waveshare-7.5in-H + cs_pin: + allow_other_uses: true + number: GPIO5 + dc_pin: + allow_other_uses: true + number: GPIO17 + reset_pin: + allow_other_uses: true + number: GPIO16 + busy_pin: + allow_other_uses: true + number: GPIO4 + inverted: true + - platform: epaper_spi model: seeed-reterminal-e1002 - platform: epaper_spi From f2c827f9a2395ac34144bddbb3f9a3edd4c43bd0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Feb 2026 08:08:43 -0600 Subject: [PATCH 0723/2030] [runtime_image] Remove stored RAMAllocator member (#13998) --- esphome/components/runtime_image/png_decoder.cpp | 6 ++++-- esphome/components/runtime_image/png_decoder.h | 1 - esphome/components/runtime_image/runtime_image.cpp | 8 +++++--- esphome/components/runtime_image/runtime_image.h | 1 - 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/esphome/components/runtime_image/png_decoder.cpp b/esphome/components/runtime_image/png_decoder.cpp index 9fe4a9c4ff..591504328d 100644 --- a/esphome/components/runtime_image/png_decoder.cpp +++ b/esphome/components/runtime_image/png_decoder.cpp @@ -50,7 +50,8 @@ static void draw_callback(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, ui PngDecoder::PngDecoder(RuntimeImage *image) : ImageDecoder(image) { { - pngle_t *pngle = this->allocator_.allocate(1, PNGLE_T_SIZE); + RAMAllocator<pngle_t> allocator; + pngle_t *pngle = allocator.allocate(1, PNGLE_T_SIZE); if (!pngle) { ESP_LOGE(TAG, "Failed to allocate memory for PNGLE engine!"); return; @@ -64,7 +65,8 @@ PngDecoder::PngDecoder(RuntimeImage *image) : ImageDecoder(image) { PngDecoder::~PngDecoder() { if (this->pngle_) { pngle_reset(this->pngle_); - this->allocator_.deallocate(this->pngle_, PNGLE_T_SIZE); + RAMAllocator<pngle_t> allocator; + allocator.deallocate(this->pngle_, PNGLE_T_SIZE); } } diff --git a/esphome/components/runtime_image/png_decoder.h b/esphome/components/runtime_image/png_decoder.h index b5c1e70c2a..24521d33a8 100644 --- a/esphome/components/runtime_image/png_decoder.h +++ b/esphome/components/runtime_image/png_decoder.h @@ -29,7 +29,6 @@ class PngDecoder : public ImageDecoder { uint32_t get_pixels_decoded() const { return this->pixels_decoded_; } protected: - RAMAllocator<pngle_t> allocator_; pngle_t *pngle_{nullptr}; uint32_t pixels_decoded_{0}; }; diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 1d70f38d6b..603ea76f01 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -230,7 +230,8 @@ void RuntimeImage::release() { void RuntimeImage::release_buffer_() { if (this->buffer_) { ESP_LOGV(TAG, "Releasing buffer of size %zu", this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); - this->allocator_.deallocate(this->buffer_, this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); + RAMAllocator<uint8_t> allocator; + allocator.deallocate(this->buffer_, this->get_buffer_size_(this->buffer_width_, this->buffer_height_)); this->buffer_ = nullptr; this->data_start_ = nullptr; this->width_ = 0; @@ -254,11 +255,12 @@ size_t RuntimeImage::resize_buffer_(int width, int height) { } ESP_LOGD(TAG, "Allocating buffer: %dx%d, %zu bytes", width, height, new_size); - this->buffer_ = this->allocator_.allocate(new_size); + RAMAllocator<uint8_t> allocator; + this->buffer_ = allocator.allocate(new_size); if (!this->buffer_) { ESP_LOGE(TAG, "Failed to allocate %zu bytes. Largest free block: %zu", new_size, - this->allocator_.get_max_free_block_size()); + allocator.get_max_free_block_size()); return 0; } diff --git a/esphome/components/runtime_image/runtime_image.h b/esphome/components/runtime_image/runtime_image.h index 0a5279d86d..4bdcdcac9e 100644 --- a/esphome/components/runtime_image/runtime_image.h +++ b/esphome/components/runtime_image/runtime_image.h @@ -165,7 +165,6 @@ class RuntimeImage : public image::Image { std::unique_ptr<ImageDecoder> create_decoder_(); // Memory management - RAMAllocator<uint8_t> allocator_{}; uint8_t *buffer_{nullptr}; // Decoder management From ffb9a00e2683d6ad0aad47fc4c6a783ca615e101 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Feb 2026 08:09:13 -0600 Subject: [PATCH 0724/2030] [online_image] Remove stored RAMAllocator member from DownloadBuffer (#13999) --- esphome/components/online_image/download_buffer.cpp | 10 ++++++---- esphome/components/online_image/download_buffer.h | 6 ++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/online_image/download_buffer.cpp b/esphome/components/online_image/download_buffer.cpp index 999005df82..2ec6365aa1 100644 --- a/esphome/components/online_image/download_buffer.cpp +++ b/esphome/components/online_image/download_buffer.cpp @@ -7,7 +7,8 @@ namespace esphome::online_image { static const char *const TAG = "online_image.download_buffer"; DownloadBuffer::DownloadBuffer(size_t size) : size_(size) { - this->buffer_ = this->allocator_.allocate(size); + RAMAllocator<uint8_t> allocator; + this->buffer_ = allocator.allocate(size); this->reset(); if (!this->buffer_) { ESP_LOGE(TAG, "Initial allocation of download buffer failed!"); @@ -38,15 +39,16 @@ size_t DownloadBuffer::resize(size_t size) { // Avoid useless reallocations; if the buffer is big enough, don't reallocate. return this->size_; } - this->allocator_.deallocate(this->buffer_, this->size_); - this->buffer_ = this->allocator_.allocate(size); + RAMAllocator<uint8_t> allocator; + allocator.deallocate(this->buffer_, this->size_); + this->buffer_ = allocator.allocate(size); this->reset(); if (this->buffer_) { this->size_ = size; return size; } else { ESP_LOGE(TAG, "allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", size, - this->allocator_.get_max_free_block_size()); + allocator.get_max_free_block_size()); this->size_ = 0; return 0; } diff --git a/esphome/components/online_image/download_buffer.h b/esphome/components/online_image/download_buffer.h index 110a4b608a..73061b23b5 100644 --- a/esphome/components/online_image/download_buffer.h +++ b/esphome/components/online_image/download_buffer.h @@ -15,7 +15,10 @@ namespace esphome::online_image { class DownloadBuffer { public: DownloadBuffer(size_t size); - ~DownloadBuffer() { this->allocator_.deallocate(this->buffer_, this->size_); } + ~DownloadBuffer() { + RAMAllocator<uint8_t> allocator; + allocator.deallocate(this->buffer_, this->size_); + } uint8_t *data(size_t offset = 0); uint8_t *append() { return this->data(this->unread_); } @@ -34,7 +37,6 @@ class DownloadBuffer { size_t resize(size_t size); protected: - RAMAllocator<uint8_t> allocator_{}; uint8_t *buffer_; size_t size_; /** Total number of downloaded bytes not yet read. */ From 81872d9822d1930e2408110acfcdb8e8e3dfd95a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Feb 2026 08:09:26 -0600 Subject: [PATCH 0725/2030] [camera, camera_encoder] Remove stored RAMAllocator member (#13997) --- esphome/components/camera/buffer_impl.cpp | 12 ++++++++---- esphome/components/camera/buffer_impl.h | 1 - .../camera_encoder/encoder_buffer_impl.cpp | 9 ++++++--- .../components/camera_encoder/encoder_buffer_impl.h | 1 - 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/esphome/components/camera/buffer_impl.cpp b/esphome/components/camera/buffer_impl.cpp index d17a4e2707..97cdd2e104 100644 --- a/esphome/components/camera/buffer_impl.cpp +++ b/esphome/components/camera/buffer_impl.cpp @@ -3,18 +3,22 @@ namespace esphome::camera { BufferImpl::BufferImpl(size_t size) { - this->data_ = this->allocator_.allocate(size); + RAMAllocator<uint8_t> allocator; + this->data_ = allocator.allocate(size); this->size_ = size; } BufferImpl::BufferImpl(CameraImageSpec *spec) { - this->data_ = this->allocator_.allocate(spec->bytes_per_image()); + RAMAllocator<uint8_t> allocator; + this->data_ = allocator.allocate(spec->bytes_per_image()); this->size_ = spec->bytes_per_image(); } BufferImpl::~BufferImpl() { - if (this->data_ != nullptr) - this->allocator_.deallocate(this->data_, this->size_); + if (this->data_ != nullptr) { + RAMAllocator<uint8_t> allocator; + allocator.deallocate(this->data_, this->size_); + } } } // namespace esphome::camera diff --git a/esphome/components/camera/buffer_impl.h b/esphome/components/camera/buffer_impl.h index 46398295fa..5e42df7957 100644 --- a/esphome/components/camera/buffer_impl.h +++ b/esphome/components/camera/buffer_impl.h @@ -18,7 +18,6 @@ class BufferImpl : public Buffer { ~BufferImpl() override; protected: - RAMAllocator<uint8_t> allocator_; size_t size_{}; uint8_t *data_{}; }; diff --git a/esphome/components/camera_encoder/encoder_buffer_impl.cpp b/esphome/components/camera_encoder/encoder_buffer_impl.cpp index db84026496..f12c66f203 100644 --- a/esphome/components/camera_encoder/encoder_buffer_impl.cpp +++ b/esphome/components/camera_encoder/encoder_buffer_impl.cpp @@ -4,7 +4,8 @@ namespace esphome::camera_encoder { bool EncoderBufferImpl::set_buffer_size(size_t size) { if (size > this->capacity_) { - uint8_t *p = this->allocator_.reallocate(this->data_, size); + RAMAllocator<uint8_t> allocator; + uint8_t *p = allocator.reallocate(this->data_, size); if (p == nullptr) return false; @@ -16,8 +17,10 @@ bool EncoderBufferImpl::set_buffer_size(size_t size) { } EncoderBufferImpl::~EncoderBufferImpl() { - if (this->data_ != nullptr) - this->allocator_.deallocate(this->data_, this->capacity_); + if (this->data_ != nullptr) { + RAMAllocator<uint8_t> allocator; + allocator.deallocate(this->data_, this->capacity_); + } } } // namespace esphome::camera_encoder diff --git a/esphome/components/camera_encoder/encoder_buffer_impl.h b/esphome/components/camera_encoder/encoder_buffer_impl.h index 13eccb7d56..d394daff14 100644 --- a/esphome/components/camera_encoder/encoder_buffer_impl.h +++ b/esphome/components/camera_encoder/encoder_buffer_impl.h @@ -16,7 +16,6 @@ class EncoderBufferImpl : public camera::EncoderBuffer { ~EncoderBufferImpl() override; protected: - RAMAllocator<uint8_t> allocator_; size_t capacity_{}; size_t size_{}; uint8_t *data_{}; From 0c4827d348e4f55807fa910490e59144711ef392 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Feb 2026 08:09:53 -0600 Subject: [PATCH 0726/2030] [json, core] Remove stored RAMAllocator, make constructors constexpr (#14000) --- esphome/components/json/json_util.h | 11 ++++++----- esphome/core/helpers.h | 11 ++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index ca074926bd..c472b9a9ec 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -18,7 +18,10 @@ namespace json { // Build an allocator for the JSON Library using the RAMAllocator class // This is only compiled when PSRAM is enabled struct SpiRamAllocator : ArduinoJson::Allocator { - void *allocate(size_t size) override { return allocator_.allocate(size); } + void *allocate(size_t size) override { + RAMAllocator<uint8_t> allocator; + return allocator.allocate(size); + } void deallocate(void *ptr) override { // ArduinoJson's Allocator interface doesn't provide the size parameter in deallocate. @@ -31,11 +34,9 @@ struct SpiRamAllocator : ArduinoJson::Allocator { } void *reallocate(void *ptr, size_t new_size) override { - return allocator_.reallocate(static_cast<uint8_t *>(ptr), new_size); + RAMAllocator<uint8_t> allocator; + return allocator.reallocate(static_cast<uint8_t *>(ptr), new_size); } - - protected: - RAMAllocator<uint8_t> allocator_{RAMAllocator<uint8_t>::NONE}; }; #endif diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 34c7452484..298b93fbc4 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1673,13 +1673,10 @@ template<class T> class RAMAllocator { ALLOW_FAILURE = 1 << 2, // Does nothing. Kept for compatibility. }; - RAMAllocator() = default; - RAMAllocator(uint8_t flags) { - // default is both external and internal - flags &= ALLOC_INTERNAL | ALLOC_EXTERNAL; - if (flags != 0) - this->flags_ = flags; - } + constexpr RAMAllocator() = default; + constexpr RAMAllocator(uint8_t flags) + : flags_((flags & (ALLOC_INTERNAL | ALLOC_EXTERNAL)) != 0 ? (flags & (ALLOC_INTERNAL | ALLOC_EXTERNAL)) + : (ALLOC_INTERNAL | ALLOC_EXTERNAL)) {} template<class U> constexpr RAMAllocator(const RAMAllocator<U> &other) : flags_{other.flags_} {} T *allocate(size_t n) { return this->allocate(n, sizeof(T)); } From 1517b7799a0e829a33555f02bd49915d53b7dd13 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Feb 2026 08:21:04 -0700 Subject: [PATCH 0727/2030] [wifi] Fix ESP8266 DHCP state corruption from premature dhcp_renew() (#13983) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/wifi/wifi_component_esp8266.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index c87345f0bf..cbf7d7d80f 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -216,23 +216,16 @@ bool WiFiComponent::wifi_apply_hostname_() { ESP_LOGV(TAG, "Set hostname failed"); } - // inform dhcp server of hostname change using dhcp_renew() + // Update hostname on all lwIP interfaces so DHCP packets include it. + // lwIP includes the hostname in DHCP DISCOVER/REQUEST automatically + // via LWIP_NETIF_HOSTNAME — no dhcp_renew() needed. The hostname is + // fixed at compile time and never changes at runtime. for (netif *intf = netif_list; intf; intf = intf->next) { - // unconditionally update all known interfaces #if LWIP_VERSION_MAJOR == 1 intf->hostname = (char *) wifi_station_get_hostname(); #else intf->hostname = wifi_station_get_hostname(); #endif - if (netif_dhcp_data(intf) != nullptr) { - // renew already started DHCP leases - err_t lwipret = dhcp_renew(intf); - if (lwipret != ERR_OK) { - ESP_LOGW(TAG, "wifi_apply_hostname_(%s): lwIP error %d on interface %c%c (index %d)", intf->hostname, - (int) lwipret, intf->name[0], intf->name[1], intf->num); - ret = false; - } - } } return ret; From f6362aa8da61be4ba14edaf8c4156ba75c5fe1ef Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 12:11:36 -0500 Subject: [PATCH 0728/2030] [combination] Fix 'coeffecient' typo with backward-compatible deprecation (#14004) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/combination/combination.cpp | 2 +- esphome/components/combination/sensor.py | 46 +++++++++++++++---- tests/components/combination/common.yaml | 4 +- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/esphome/components/combination/combination.cpp b/esphome/components/combination/combination.cpp index 716d270390..ece7cca482 100644 --- a/esphome/components/combination/combination.cpp +++ b/esphome/components/combination/combination.cpp @@ -126,7 +126,7 @@ void LinearCombinationComponent::setup() { } void LinearCombinationComponent::handle_new_value(float value) { - // Multiplies each sensor state by a configured coeffecient and then sums + // Multiplies each sensor state by a configured coefficient and then sums if (!std::isfinite(value)) return; diff --git a/esphome/components/combination/sensor.py b/esphome/components/combination/sensor.py index f5255fec03..0204162e8d 100644 --- a/esphome/components/combination/sensor.py +++ b/esphome/components/combination/sensor.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv @@ -15,6 +17,8 @@ from esphome.const import ( ) from esphome.core.entity_helpers import inherit_property_from +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@Cat-Ion", "@kahrendt"] combination_ns = cg.esphome_ns.namespace("combination") @@ -47,7 +51,8 @@ SumCombinationComponent = combination_ns.class_( "SumCombinationComponent", cg.Component, sensor.Sensor ) -CONF_COEFFECIENT = "coeffecient" +CONF_COEFFICIENT = "coefficient" +CONF_COEFFECIENT = "coeffecient" # Deprecated, remove before 2026.12.0 CONF_ERROR = "error" CONF_KALMAN = "kalman" CONF_LINEAR = "linear" @@ -68,11 +73,34 @@ KALMAN_SOURCE_SCHEMA = cv.Schema( } ) -LINEAR_SOURCE_SCHEMA = cv.Schema( - { - cv.Required(CONF_SOURCE): cv.use_id(sensor.Sensor), - cv.Required(CONF_COEFFECIENT): cv.templatable(cv.float_), - } + +def _migrate_coeffecient(config): + """Migrate deprecated 'coeffecient' spelling to 'coefficient'.""" + if CONF_COEFFECIENT in config: + if CONF_COEFFICIENT in config: + raise cv.Invalid( + f"Cannot specify both '{CONF_COEFFICIENT}' and '{CONF_COEFFECIENT}'" + ) + _LOGGER.warning( + "'%s' is deprecated, use '%s' instead. Will be removed in 2026.12.0", + CONF_COEFFECIENT, + CONF_COEFFICIENT, + ) + config[CONF_COEFFICIENT] = config.pop(CONF_COEFFECIENT) + elif CONF_COEFFICIENT not in config: + raise cv.Invalid(f"'{CONF_COEFFICIENT}' is a required option") + return config + + +LINEAR_SOURCE_SCHEMA = cv.All( + cv.Schema( + { + cv.Required(CONF_SOURCE): cv.use_id(sensor.Sensor), + cv.Optional(CONF_COEFFICIENT): cv.templatable(cv.float_), + cv.Optional(CONF_COEFFECIENT): cv.templatable(cv.float_), + } + ), + _migrate_coeffecient, ) SENSOR_ONLY_SOURCE_SCHEMA = cv.Schema( @@ -162,12 +190,12 @@ async def to_code(config): ) cg.add(var.add_source(source, error)) elif config[CONF_TYPE] == CONF_LINEAR: - coeffecient = await cg.templatable( - source_conf[CONF_COEFFECIENT], + coefficient = await cg.templatable( + source_conf[CONF_COEFFICIENT], [(float, "x")], cg.float_, ) - cg.add(var.add_source(source, coeffecient)) + cg.add(var.add_source(source, coefficient)) else: cg.add(var.add_source(source)) diff --git a/tests/components/combination/common.yaml b/tests/components/combination/common.yaml index 0e5d512d08..5d46419399 100644 --- a/tests/components/combination/common.yaml +++ b/tests/components/combination/common.yaml @@ -27,9 +27,9 @@ sensor: name: Linearly combined temperatures sources: - source: template_temperature1 - coeffecient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" + coefficient: !lambda "return 0.4 + std::abs(x - 25) * 0.023;" - source: template_temperature2 - coeffecient: 1.5 + coefficient: 1.5 - platform: combination type: max name: Max of combined temperatures From df29cdbf1742c0676e9bd5870a86d462c0a91dfd Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 12:11:50 -0500 Subject: [PATCH 0729/2030] [fan] Fix preset_mode not restored on boot (#14002) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/fan/fan.cpp | 8 +++++++- esphome/components/fan/fan.h | 4 +++- esphome/components/hbridge/fan/hbridge_fan.cpp | 8 ++++---- esphome/components/speed/fan/speed_fan.cpp | 8 ++++---- esphome/components/template/fan/template_fan.cpp | 10 +++++----- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index d70a2940bc..c1e0a3dc2e 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -221,12 +221,17 @@ void Fan::publish_state() { } // Random 32-bit value, change this every time the layout of the FanRestoreState struct changes. -constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABA; +constexpr uint32_t RESTORE_STATE_VERSION = 0x71700ABB; optional<FanRestoreState> Fan::restore_state_() { FanRestoreState recovered{}; this->rtc_ = this->make_entity_preference<FanRestoreState>(RESTORE_STATE_VERSION); bool restored = this->rtc_.load(&recovered); + if (!restored) { + // No valid saved data; ensure preset_mode sentinel is set + recovered.preset_mode = FanRestoreState::NO_PRESET; + } + switch (this->restore_mode_) { case FanRestoreMode::NO_RESTORE: return {}; @@ -264,6 +269,7 @@ void Fan::save_state_() { state.oscillating = this->oscillating; state.speed = this->speed; state.direction = this->direction; + state.preset_mode = FanRestoreState::NO_PRESET; if (this->has_preset_mode()) { const auto &preset_modes = traits.supported_preset_modes(); diff --git a/esphome/components/fan/fan.h b/esphome/components/fan/fan.h index 55d4ba8825..2caf3a712a 100644 --- a/esphome/components/fan/fan.h +++ b/esphome/components/fan/fan.h @@ -91,11 +91,13 @@ class FanCall { }; struct FanRestoreState { + static constexpr uint8_t NO_PRESET = UINT8_MAX; + bool state; int speed; bool oscillating; FanDirection direction; - uint8_t preset_mode; + uint8_t preset_mode{NO_PRESET}; /// Convert this struct to a fan call that can be performed. FanCall to_call(Fan &fan); diff --git a/esphome/components/hbridge/fan/hbridge_fan.cpp b/esphome/components/hbridge/fan/hbridge_fan.cpp index 9bf58f9d1e..38e4129e66 100644 --- a/esphome/components/hbridge/fan/hbridge_fan.cpp +++ b/esphome/components/hbridge/fan/hbridge_fan.cpp @@ -28,15 +28,15 @@ fan::FanCall HBridgeFan::brake() { } void HBridgeFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); this->write_state_(); } - - // Construct traits - this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, true, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void HBridgeFan::dump_config() { diff --git a/esphome/components/speed/fan/speed_fan.cpp b/esphome/components/speed/fan/speed_fan.cpp index af98e3a51f..55f7fd162c 100644 --- a/esphome/components/speed/fan/speed_fan.cpp +++ b/esphome/components/speed/fan/speed_fan.cpp @@ -7,15 +7,15 @@ namespace speed { static const char *const TAG = "speed.fan"; void SpeedFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); this->write_state_(); } - - // Construct traits - this->traits_ = fan::FanTraits(this->oscillating_ != nullptr, true, this->direction_ != nullptr, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void SpeedFan::dump_config() { LOG_FAN("", "Speed Fan", this); } diff --git a/esphome/components/template/fan/template_fan.cpp b/esphome/components/template/fan/template_fan.cpp index 0e1920a984..cd267bd552 100644 --- a/esphome/components/template/fan/template_fan.cpp +++ b/esphome/components/template/fan/template_fan.cpp @@ -6,15 +6,15 @@ namespace esphome::template_ { static const char *const TAG = "template.fan"; void TemplateFan::setup() { + // Construct traits before restore so preset modes can be looked up by index + this->traits_ = + fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_); + this->traits_.set_supported_preset_modes(this->preset_modes_); + auto restore = this->restore_state_(); if (restore.has_value()) { restore->apply(*this); } - - // Construct traits - this->traits_ = - fan::FanTraits(this->has_oscillating_, this->speed_count_ > 0, this->has_direction_, this->speed_count_); - this->traits_.set_supported_preset_modes(this->preset_modes_); } void TemplateFan::dump_config() { LOG_FAN("", "Template Fan", this); } From e945e9b6591602ec98c1db102aeb13586a76ab92 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Feb 2026 13:23:06 -0500 Subject: [PATCH 0730/2030] [esp32_rmt] Handle ESP32 variants without RMT hardware (#14001) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_rmt/__init__.py | 22 +++++ .../components/esp32_rmt_led_strip/light.py | 6 +- esphome/components/remote_base/remote_base.h | 5 +- .../components/remote_receiver/__init__.py | 41 +++++++- .../remote_receiver/remote_receiver.cpp | 2 +- .../remote_receiver/remote_receiver.h | 17 ++-- .../remote_receiver/remote_receiver_esp32.cpp | 5 +- .../components/remote_transmitter/__init__.py | 93 ++++++++++++------- .../remote_transmitter/automation.h | 6 +- .../remote_transmitter/remote_transmitter.cpp | 8 +- .../remote_transmitter/remote_transmitter.h | 21 +++-- .../remote_transmitter_esp32.cpp | 11 ++- .../remote_receiver/test.esp32-c2-idf.yaml | 12 +++ .../remote_transmitter/test.esp32-c2-idf.yaml | 7 ++ 14 files changed, 181 insertions(+), 75 deletions(-) create mode 100644 tests/components/remote_receiver/test.esp32-c2-idf.yaml create mode 100644 tests/components/remote_transmitter/test.esp32-c2-idf.yaml diff --git a/esphome/components/esp32_rmt/__init__.py b/esphome/components/esp32_rmt/__init__.py index 272c7c81ba..1076bcabdc 100644 --- a/esphome/components/esp32_rmt/__init__.py +++ b/esphome/components/esp32_rmt/__init__.py @@ -1,8 +1,30 @@ from esphome.components import esp32 import esphome.config_validation as cv +from esphome.core import CORE CODEOWNERS = ["@jesserockz"] +VARIANTS_NO_RMT = {esp32.VARIANT_ESP32C2, esp32.VARIANT_ESP32C61} + + +def validate_rmt_not_supported(rmt_only_keys): + """Validate that RMT-only config keys are not used on variants without RMT hardware.""" + rmt_only_keys = set(rmt_only_keys) + + def _validator(config): + if CORE.is_esp32: + variant = esp32.get_esp32_variant() + if variant in VARIANTS_NO_RMT: + unsupported = rmt_only_keys.intersection(config) + if unsupported: + keys = ", ".join(sorted(f"'{k}'" for k in unsupported)) + raise cv.Invalid( + f"{keys} not available on {variant} (no RMT hardware)" + ) + return config + + return _validator + def validate_clock_resolution(): def _validator(value): diff --git a/esphome/components/esp32_rmt_led_strip/light.py b/esphome/components/esp32_rmt_led_strip/light.py index 6d41f6b5b8..1c6943b003 100644 --- a/esphome/components/esp32_rmt_led_strip/light.py +++ b/esphome/components/esp32_rmt_led_strip/light.py @@ -3,7 +3,7 @@ import logging from esphome import pins import esphome.codegen as cg -from esphome.components import esp32, light +from esphome.components import esp32, esp32_rmt, light from esphome.components.const import CONF_USE_PSRAM from esphome.components.esp32 import include_builtin_idf_component import esphome.config_validation as cv @@ -71,6 +71,10 @@ CONF_RESET_LOW = "reset_low" CONFIG_SCHEMA = cv.All( + esp32.only_on_variant( + unsupported=list(esp32_rmt.VARIANTS_NO_RMT), + msg_prefix="ESP32 RMT LED strip", + ), light.ADDRESSABLE_LIGHT_SCHEMA.extend( { cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(ESP32RMTLEDStripLightOutput), diff --git a/esphome/components/remote_base/remote_base.h b/esphome/components/remote_base/remote_base.h index 0cac28506f..d73fff2b0a 100644 --- a/esphome/components/remote_base/remote_base.h +++ b/esphome/components/remote_base/remote_base.h @@ -119,6 +119,8 @@ class RemoteComponentBase { }; #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED class RemoteRMTChannel { public: void set_clock_resolution(uint32_t clock_resolution) { this->clock_resolution_ = clock_resolution; } @@ -137,7 +139,8 @@ class RemoteRMTChannel { uint32_t clock_resolution_{1000000}; uint32_t rmt_symbols_; }; -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 class RemoteTransmitterBase : public RemoteComponentBase { public: diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index b3dc213c5f..362f6e99db 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -65,6 +65,8 @@ RemoteReceiverComponent = remote_receiver_ns.class_( def validate_config(config): if CORE.is_esp32: variant = esp32.get_esp32_variant() + if variant in esp32_rmt.VARIANTS_NO_RMT: + return config if variant in (esp32.VARIANT_ESP32, esp32.VARIANT_ESP32S2): max_idle = 65535 else: @@ -110,6 +112,8 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_BUFFER_SIZE, esp32="10000b", + esp32_c2="1000b", + esp32_c61="1000b", esp8266="1000b", bk72xx="1000b", ln882x="1000b", @@ -131,9 +135,11 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_RMT_SYMBOLS, esp32=192, + esp32_c2=cv.UNDEFINED, esp32_c3=96, esp32_c5=96, esp32_c6=96, + esp32_c61=cv.UNDEFINED, esp32_h2=96, esp32_p4=192, esp32_s2=192, @@ -145,6 +151,8 @@ CONFIG_SCHEMA = remote_base.validate_triggers( cv.SplitDefault( CONF_RECEIVE_SYMBOLS, esp32=192, + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), cv.Optional(CONF_USE_DMA): cv.All( esp32.only_on_variant( @@ -152,24 +160,45 @@ CONFIG_SCHEMA = remote_base.validate_triggers( ), cv.boolean, ), - cv.SplitDefault(CONF_CARRIER_DUTY_PERCENT, esp32=100): cv.All( + cv.SplitDefault( + CONF_CARRIER_DUTY_PERCENT, + esp32=100, + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, + ): cv.All( cv.only_on_esp32, cv.percentage_int, cv.Range(min=1, max=100), ), - cv.SplitDefault(CONF_CARRIER_FREQUENCY, esp32="0Hz"): cv.All( - cv.only_on_esp32, cv.frequency, cv.int_ - ), + cv.SplitDefault( + CONF_CARRIER_FREQUENCY, + esp32="0Hz", + esp32_c2=cv.UNDEFINED, + esp32_c61=cv.UNDEFINED, + ): cv.All(cv.only_on_esp32, cv.frequency, cv.int_), } ) .extend(cv.COMPONENT_SCHEMA) + .add_extra( + esp32_rmt.validate_rmt_not_supported( + [ + CONF_CLOCK_RESOLUTION, + CONF_USE_DMA, + CONF_RMT_SYMBOLS, + CONF_FILTER_SYMBOLS, + CONF_RECEIVE_SYMBOLS, + CONF_CARRIER_DUTY_PERCENT, + CONF_CARRIER_FREQUENCY, + ] + ) + ) .add_extra(validate_config) ) async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - if CORE.is_esp32: + if CORE.is_esp32 and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT: # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) esp32.include_builtin_idf_component("esp_driver_rmt") @@ -213,6 +242,8 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_IDF, }, "remote_receiver.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, PlatformFramework.RTL87XX_ARDUINO, diff --git a/esphome/components/remote_receiver/remote_receiver.cpp b/esphome/components/remote_receiver/remote_receiver.cpp index de47457dac..d59ee63695 100644 --- a/esphome/components/remote_receiver/remote_receiver.cpp +++ b/esphome/components/remote_receiver/remote_receiver.cpp @@ -3,7 +3,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) namespace esphome::remote_receiver { diff --git a/esphome/components/remote_receiver/remote_receiver.h b/esphome/components/remote_receiver/remote_receiver.h index 3d9199a904..5da9283a6e 100644 --- a/esphome/components/remote_receiver/remote_receiver.h +++ b/esphome/components/remote_receiver/remote_receiver.h @@ -6,12 +6,15 @@ #include <cinttypes> #if defined(USE_ESP32) +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/rmt_rx.h> -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 namespace esphome::remote_receiver { -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) struct RemoteReceiverComponentStore { static void gpio_intr(RemoteReceiverComponentStore *arg); @@ -35,7 +38,7 @@ struct RemoteReceiverComponentStore { volatile bool prev_level{false}; volatile bool overflow{false}; }; -#elif defined(USE_ESP32) +#elif defined(USE_ESP32) && SOC_RMT_SUPPORTED struct RemoteReceiverComponentStore { /// Stores RMT symbols and rx done event data volatile uint8_t *buffer{nullptr}; @@ -54,7 +57,7 @@ struct RemoteReceiverComponentStore { class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, public Component -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED , public remote_base::RemoteRMTChannel #endif @@ -66,7 +69,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void dump_config() override; void loop() override; -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void set_filter_symbols(uint32_t filter_symbols) { this->filter_symbols_ = filter_symbols; } void set_receive_symbols(uint32_t receive_symbols) { this->receive_symbols_ = receive_symbols; } void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } @@ -78,7 +81,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; } protected: -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void decode_rmt_(rmt_symbol_word_t *item, size_t item_count); rmt_channel_handle_t channel_{NULL}; uint32_t filter_symbols_{0}; @@ -94,7 +97,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase, RemoteReceiverComponentStore store_; #endif -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) HighFrequencyLoopRequester high_freq_; #endif diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_esp32.cpp index f95244ea45..357a36d052 100644 --- a/esphome/components/remote_receiver/remote_receiver_esp32.cpp +++ b/esphome/components/remote_receiver/remote_receiver_esp32.cpp @@ -2,6 +2,8 @@ #include "esphome/core/log.h" #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/gpio.h> #include <esp_clk_tree.h> @@ -248,4 +250,5 @@ void RemoteReceiverComponent::decode_rmt_(rmt_symbol_word_t *item, size_t item_c } // namespace esphome::remote_receiver -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index 8383b9dd75..fc772f88b2 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -40,45 +40,66 @@ DigitalWriteAction = remote_transmitter_ns.class_( cg.Parented.template(RemoteTransmitterComponent), ) + MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( - cv.percentage_int, cv.Range(min=1, max=100) - ), - cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( - cv.only_on_esp32, - esp32_rmt.validate_clock_resolution(), - ), - cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_on_esp32, cv.boolean), - cv.Optional(CONF_USE_DMA): cv.All( - esp32.only_on_variant( - supported=[esp32.VARIANT_ESP32P4, esp32.VARIANT_ESP32S3] +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( + cv.percentage_int, cv.Range(min=1, max=100) ), - cv.boolean, - ), - cv.SplitDefault( - CONF_RMT_SYMBOLS, - esp32=64, - esp32_c3=48, - esp32_c5=48, - esp32_c6=48, - esp32_h2=48, - esp32_p4=48, - esp32_s2=64, - esp32_s3=48, - ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), - cv.Optional(CONF_NON_BLOCKING): cv.All(cv.only_on_esp32, cv.boolean), - cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), - cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), - } -).extend(cv.COMPONENT_SCHEMA) + cv.Optional(CONF_CLOCK_RESOLUTION): cv.All( + cv.only_on_esp32, + esp32_rmt.validate_clock_resolution(), + ), + cv.Optional(CONF_EOT_LEVEL): cv.All(cv.only_on_esp32, cv.boolean), + cv.Optional(CONF_USE_DMA): cv.All( + esp32.only_on_variant( + supported=[esp32.VARIANT_ESP32P4, esp32.VARIANT_ESP32S3] + ), + cv.boolean, + ), + cv.SplitDefault( + CONF_RMT_SYMBOLS, + esp32=64, + esp32_c2=cv.UNDEFINED, + esp32_c3=48, + esp32_c5=48, + esp32_c6=48, + esp32_c61=cv.UNDEFINED, + esp32_h2=48, + esp32_p4=48, + esp32_s2=64, + esp32_s3=48, + ): cv.All(cv.only_on_esp32, cv.int_range(min=2)), + cv.Optional(CONF_NON_BLOCKING): cv.All(cv.only_on_esp32, cv.boolean), + cv.Optional(CONF_ON_TRANSMIT): automation.validate_automation(single=True), + cv.Optional(CONF_ON_COMPLETE): automation.validate_automation(single=True), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .add_extra( + esp32_rmt.validate_rmt_not_supported( + [ + CONF_CLOCK_RESOLUTION, + CONF_EOT_LEVEL, + CONF_USE_DMA, + CONF_RMT_SYMBOLS, + CONF_NON_BLOCKING, + ] + ) + ) +) def _validate_non_blocking(config): - if CORE.is_esp32 and CONF_NON_BLOCKING not in config: + if ( + CORE.is_esp32 + and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT + and CONF_NON_BLOCKING not in config + ): _LOGGER.warning( "'non_blocking' is not set for 'remote_transmitter' and will default to 'true'.\n" "The default behavior changed in 2025.11.0; previously blocking mode was used.\n" @@ -111,7 +132,7 @@ async def digital_write_action_to_code(config, action_id, template_arg, args): async def to_code(config): pin = await cg.gpio_pin_expression(config[CONF_PIN]) - if CORE.is_esp32: + if CORE.is_esp32 and esp32.get_esp32_variant() not in esp32_rmt.VARIANTS_NO_RMT: # Re-enable ESP-IDF's RMT driver (excluded by default to save compile time) esp32.include_builtin_idf_component("esp_driver_rmt") @@ -155,6 +176,8 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_IDF, }, "remote_transmitter.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, PlatformFramework.RTL87XX_ARDUINO, diff --git a/esphome/components/remote_transmitter/automation.h b/esphome/components/remote_transmitter/automation.h index bee1d0be8a..8da4cfd95d 100644 --- a/esphome/components/remote_transmitter/automation.h +++ b/esphome/components/remote_transmitter/automation.h @@ -5,8 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { template<typename... Ts> class DigitalWriteAction : public Action<Ts...>, public Parented<RemoteTransmitterComponent> { public: @@ -14,5 +13,4 @@ template<typename... Ts> class DigitalWriteAction : public Action<Ts...>, public void play(const Ts &...x) override { this->parent_->digital_write(this->value_.value(x...)); } }; -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter.cpp b/esphome/components/remote_transmitter/remote_transmitter.cpp index d35541e2e1..51a3c0b1d4 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter.cpp @@ -2,10 +2,9 @@ #include "esphome/core/log.h" #include "esphome/core/application.h" -#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) +#if defined(USE_LIBRETINY) || defined(USE_ESP8266) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { static const char *const TAG = "remote_transmitter"; @@ -105,7 +104,6 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen this->complete_trigger_.trigger(); } -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter #endif diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index 65bd2ac8b2..aee52ea170 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -6,13 +6,15 @@ #include <vector> #if defined(USE_ESP32) +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/rmt_tx.h> -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1) // IDF version 5.5.1 and above is required because of a bug in // the RMT encoder: https://github.com/espressif/esp-idf/issues/17244 @@ -33,7 +35,7 @@ struct RemoteTransmitterComponentStore { class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, public Component -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED , public remote_base::RemoteRMTChannel #endif @@ -51,7 +53,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, void digital_write(bool value); -#if defined(USE_ESP32) +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void set_with_dma(bool with_dma) { this->with_dma_ = with_dma; } void set_eot_level(bool eot_level) { this->eot_level_ = eot_level; } void set_non_blocking(bool non_blocking) { this->non_blocking_ = non_blocking; } @@ -62,7 +64,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, protected: void send_internal(uint32_t send_times, uint32_t send_wait) override; -#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) || defined(USE_RP2040) || (defined(USE_ESP32) && !SOC_RMT_SUPPORTED) void calculate_on_off_time_(uint32_t carrier_frequency, uint32_t *on_time_period, uint32_t *off_time_period); void mark_(uint32_t on_time, uint32_t off_time, uint32_t usec); @@ -73,7 +75,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, uint32_t target_time_; #endif -#ifdef USE_ESP32 +#if defined(USE_ESP32) && SOC_RMT_SUPPORTED void configure_rmt_(); void wait_for_rmt_(); @@ -100,5 +102,4 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, Trigger<> complete_trigger_; }; -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index 89d97895b2..71773e3ddf 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -3,10 +3,11 @@ #include "esphome/core/application.h" #ifdef USE_ESP32 +#include <soc/soc_caps.h> +#if SOC_RMT_SUPPORTED #include <driver/gpio.h> -namespace esphome { -namespace remote_transmitter { +namespace esphome::remote_transmitter { static const char *const TAG = "remote_transmitter"; @@ -358,7 +359,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen } #endif -} // namespace remote_transmitter -} // namespace esphome +} // namespace esphome::remote_transmitter -#endif +#endif // SOC_RMT_SUPPORTED +#endif // USE_ESP32 diff --git a/tests/components/remote_receiver/test.esp32-c2-idf.yaml b/tests/components/remote_receiver/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..87154e19fc --- /dev/null +++ b/tests/components/remote_receiver/test.esp32-c2-idf.yaml @@ -0,0 +1,12 @@ +remote_receiver: + id: rcvr + pin: GPIO2 + dump: all + <<: !include common-actions.yaml + +binary_sensor: + - platform: remote_receiver + name: Panasonic Remote Input + panasonic: + address: 0x4004 + command: 0x100BCBD diff --git a/tests/components/remote_transmitter/test.esp32-c2-idf.yaml b/tests/components/remote_transmitter/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..424cd8d249 --- /dev/null +++ b/tests/components/remote_transmitter/test.esp32-c2-idf.yaml @@ -0,0 +1,7 @@ +remote_transmitter: + id: xmitr + pin: GPIO2 + carrier_duty_percent: 50% + +packages: + buttons: !include common-buttons.yaml From 5904808804b1f86e30583eb3ebbab0eb461905e0 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:24:35 +1300 Subject: [PATCH 0731/2030] Bump version to 2026.2.0b3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 572e20a694..b43b5a428e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0b2 +PROJECT_NUMBER = 2026.2.0b3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 247b2b7e4e..fd916da92b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0b2" +__version__ = "2026.2.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 4cd3f6c36a5485d6efa570e71cd861d705e7ac29 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Feb 2026 21:30:57 -0600 Subject: [PATCH 0732/2030] [api] Remove unused reserve from APIServer constructor (#14017) --- esphome/components/api/api_server.cpp | 6 +----- esphome/components/api/api_server.h | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index f25a9bc0e2..67a117e68f 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -28,11 +28,7 @@ static const char *const TAG = "api"; // APIServer APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -APIServer::APIServer() { - global_api_server = this; - // Pre-allocate shared write buffer - shared_write_buffer_.reserve(64); -} +APIServer::APIServer() { global_api_server = this; } void APIServer::setup() { ControllerRegistry::register_controller(this); diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 28f60343e0..323acc2efb 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -268,7 +268,11 @@ class APIServer : public Component, // Vectors and strings (12 bytes each on 32-bit) std::vector<std::unique_ptr<APIConnection>> clients_; - std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections + // Shared proto write buffer for all connections. + // Not pre-allocated: all send paths call prepare_first_message_buffer() which + // reserves the exact needed size. Pre-allocating here would cause heap fragmentation + // since the buffer would almost always reallocate on first use. + std::vector<uint8_t> shared_write_buffer_; #ifdef USE_API_HOMEASSISTANT_STATES std::vector<HomeAssistantStateSubscription> state_subs_; #endif From e826d71bd85b7a91b683c0502846fbcc9b9d3f02 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:16:57 +0100 Subject: [PATCH 0733/2030] [openthread] Fix compiler format warning (#14030) --- esphome/components/openthread/openthread_esp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 79cd809809..ec212d1f68 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -115,7 +115,7 @@ void OpenThreadComponent::ot_main() { ESP_LOGE(TAG, "Failed to set OpenThread pollperiod."); } uint32_t link_polling_period = otLinkGetPollPeriod(esp_openthread_get_instance()); - ESP_LOGD(TAG, "Link Polling Period: %d", link_polling_period); + ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, link_polling_period); } link_mode_config.mRxOnWhenIdle = this->poll_period == 0; link_mode_config.mDeviceType = false; From 81ed70325c164612878457033c5f08b27b19f331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= <contact@rodrigomartin.dev> Date: Tue, 17 Feb 2026 18:45:21 +0100 Subject: [PATCH 0734/2030] [esp32_ble_server] fix infinitely large characteristic value (#14011) --- .../components/esp32_ble_server/__init__.py | 2 +- .../esp32_ble_server/ble_characteristic.cpp | 28 +++++++++++++++---- .../esp32_ble_server/ble_characteristic.h | 1 - 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index a7e2522fac..cb494ed1bc 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -527,7 +527,7 @@ async def to_code_characteristic(service_var, char_conf): action_conf, char_conf[CONF_CHAR_VALUE_ACTION_ID_], cg.TemplateArguments(), - {}, + [], ) cg.add(value_action.play()) else: diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index 0482848ea0..a1b1ff94bb 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -246,9 +246,27 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt if (this->handle_ != param->write.handle) break; + esp_gatt_status_t status = ESP_GATT_OK; + if (param->write.is_prep) { - this->value_.insert(this->value_.end(), param->write.value, param->write.value + param->write.len); - this->write_event_ = true; + const size_t offset = param->write.offset; + const size_t write_len = param->write.len; + const size_t new_size = offset + write_len; + // Clean the buffer on the first prepared write event + if (offset == 0) { + this->value_.clear(); + } + + if (offset != this->value_.size()) { + status = ESP_GATT_INVALID_OFFSET; + } else if (new_size > ESP_GATT_MAX_ATTR_LEN) { + status = ESP_GATT_INVALID_ATTR_LEN; + } else { + if (this->value_.size() < new_size) { + this->value_.resize(new_size); + } + memcpy(this->value_.data() + offset, param->write.value, write_len); + } } else { this->set_value(ByteBuffer::wrap(param->write.value, param->write.len)); } @@ -263,7 +281,7 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt memcpy(response.attr_value.value, param->write.value, param->write.len); esp_err_t err = - esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &response); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, &response); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gatts_send_response failed: %d", err); @@ -280,9 +298,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt } case ESP_GATTS_EXEC_WRITE_EVT: { - if (!this->write_event_) + // BLE stack will guarantee that ESP_GATTS_EXEC_WRITE_EVT is only received after prepared writes + if (this->value_.empty()) break; - this->write_event_ = false; if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { if (this->on_write_callback_) { (*this->on_write_callback_)(this->value_, param->exec_write.conn_id); diff --git a/esphome/components/esp32_ble_server/ble_characteristic.h b/esphome/components/esp32_ble_server/ble_characteristic.h index b913915789..c2cdb1660c 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.h +++ b/esphome/components/esp32_ble_server/ble_characteristic.h @@ -77,7 +77,6 @@ class BLECharacteristic { } protected: - bool write_event_{false}; BLEService *service_{}; ESPBTUUID uuid_; esp_gatt_char_prop_t properties_; From 5bb863f7dadadedf3c8620d1e275d7d354fedae8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:24:39 -0600 Subject: [PATCH 0735/2030] Bump actions/stale from 10.1.1 to 10.2.0 (#14036) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 7e03e2a5f9..ba5c32e016 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 + uses: actions/stale@b5d41d4e1d5dceea10e7104786b73624c18a190f # v10.2.0 with: debug-only: ${{ github.ref != 'refs/heads/dev' }} # Dry-run when not run on dev branch remove-stale-when-updated: true From a0c4fa649640eb7618049462765e293d6458c48d Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:16:57 +0100 Subject: [PATCH 0736/2030] [openthread] Fix compiler format warning (#14030) --- esphome/components/openthread/openthread_esp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 79cd809809..ec212d1f68 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -115,7 +115,7 @@ void OpenThreadComponent::ot_main() { ESP_LOGE(TAG, "Failed to set OpenThread pollperiod."); } uint32_t link_polling_period = otLinkGetPollPeriod(esp_openthread_get_instance()); - ESP_LOGD(TAG, "Link Polling Period: %d", link_polling_period); + ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, link_polling_period); } link_mode_config.mRxOnWhenIdle = this->poll_period == 0; link_mode_config.mDeviceType = false; From d9f493ab7ae31e199a94939a9e189b2bc105ea87 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Feb 2026 10:13:41 +1300 Subject: [PATCH 0737/2030] Bump version to 2026.2.0b4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index b43b5a428e..f9deb32899 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0b3 +PROJECT_NUMBER = 2026.2.0b4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index fd916da92b..f494b5d41e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0b3" +__version__ = "2026.2.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From fb35ddebb9915f6bda82e4050943ee5de1ba0360 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 08:22:07 -0600 Subject: [PATCH 0738/2030] [display] Make COLOR_OFF and COLOR_ON inline constexpr (#14044) --- esphome/components/display/display.cpp | 3 +-- esphome/components/display/display.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index ebc3c0a9f6..53a087803c 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -9,8 +9,7 @@ namespace esphome { namespace display { static const char *const TAG = "display"; -const Color COLOR_OFF(0, 0, 0, 0); -const Color COLOR_ON(255, 255, 255, 255); +// COLOR_OFF and COLOR_ON are now inline constexpr in display.h void Display::fill(Color color) { this->filled_rectangle(0, 0, this->get_width(), this->get_height(), color); } void Display::clear() { this->fill(COLOR_OFF); } diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index 47d40915aa..e40f6ec963 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -298,9 +298,9 @@ using display_writer_t = DisplayWriter<Display>; } /// Turn the pixel OFF. -extern const Color COLOR_OFF; +inline constexpr Color COLOR_OFF(0, 0, 0, 0); /// Turn the pixel ON. -extern const Color COLOR_ON; +inline constexpr Color COLOR_ON(255, 255, 255, 255); class BaseImage { public: From fb89900c64f2a88d6f86feaa43e453af8d83b53c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 08:22:36 -0600 Subject: [PATCH 0739/2030] [core] Make setup_priority and component state constants constexpr (#14041) --- esphome/core/component.cpp | 32 ++--------------------- esphome/core/component.h | 52 +++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 56 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 90aa36f4db..a452f4d400 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -76,36 +76,8 @@ void store_component_error_message(const Component *component, const char *messa } } // namespace -namespace setup_priority { - -const float BUS = 1000.0f; -const float IO = 900.0f; -const float HARDWARE = 800.0f; -const float DATA = 600.0f; -const float PROCESSOR = 400.0; -const float BLUETOOTH = 350.0f; -const float AFTER_BLUETOOTH = 300.0f; -const float WIFI = 250.0f; -const float ETHERNET = 250.0f; -const float BEFORE_CONNECTION = 220.0f; -const float AFTER_WIFI = 200.0f; -const float AFTER_CONNECTION = 100.0f; -const float LATE = -100.0f; - -} // namespace setup_priority - -// Component state uses bits 0-2 (8 states, 5 used) -const uint8_t COMPONENT_STATE_MASK = 0x07; -const uint8_t COMPONENT_STATE_CONSTRUCTION = 0x00; -const uint8_t COMPONENT_STATE_SETUP = 0x01; -const uint8_t COMPONENT_STATE_LOOP = 0x02; -const uint8_t COMPONENT_STATE_FAILED = 0x03; -const uint8_t COMPONENT_STATE_LOOP_DONE = 0x04; -// Status LED uses bits 3-4 -const uint8_t STATUS_LED_MASK = 0x18; -const uint8_t STATUS_LED_OK = 0x00; -const uint8_t STATUS_LED_WARNING = 0x08; // Bit 3 -const uint8_t STATUS_LED_ERROR = 0x10; // Bit 4 +// setup_priority, component state, and status LED constants are now +// constexpr in component.h const uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning const uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again diff --git a/esphome/core/component.h b/esphome/core/component.h index 9ab77cc2f9..848bc0ba35 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -21,33 +21,31 @@ struct LogString; namespace setup_priority { /// For communication buses like i2c/spi -extern const float BUS; +inline constexpr float BUS = 1000.0f; /// For components that represent GPIO pins like PCF8573 -extern const float IO; +inline constexpr float IO = 900.0f; /// For components that deal with hardware and are very important like GPIO switch -extern const float HARDWARE; +inline constexpr float HARDWARE = 800.0f; /// For components that import data from directly connected sensors like DHT. -extern const float DATA; -/// Alias for DATA (here for compatibility reasons) -extern const float HARDWARE_LATE; +inline constexpr float DATA = 600.0f; /// For components that use data from sensors like displays -extern const float PROCESSOR; -extern const float BLUETOOTH; -extern const float AFTER_BLUETOOTH; -extern const float WIFI; -extern const float ETHERNET; +inline constexpr float PROCESSOR = 400.0f; +inline constexpr float BLUETOOTH = 350.0f; +inline constexpr float AFTER_BLUETOOTH = 300.0f; +inline constexpr float WIFI = 250.0f; +inline constexpr float ETHERNET = 250.0f; /// For components that should be initialized after WiFi and before API is connected. -extern const float BEFORE_CONNECTION; +inline constexpr float BEFORE_CONNECTION = 220.0f; /// For components that should be initialized after WiFi is connected. -extern const float AFTER_WIFI; +inline constexpr float AFTER_WIFI = 200.0f; /// For components that should be initialized after a data connection (API/MQTT) is connected. -extern const float AFTER_CONNECTION; +inline constexpr float AFTER_CONNECTION = 100.0f; /// For components that should be initialized at the very end of the setup process. -extern const float LATE; +inline constexpr float LATE = -100.0f; } // namespace setup_priority -static const uint32_t SCHEDULER_DONT_RUN = 4294967295UL; +inline constexpr uint32_t SCHEDULER_DONT_RUN = 4294967295UL; /// Type-safe scheduler IDs for core base classes. /// Uses a separate NameType (NUMERIC_ID_INTERNAL) so IDs can never collide @@ -65,16 +63,18 @@ void log_update_interval(const char *tag, PollingComponent *component); #define LOG_UPDATE_INTERVAL(this) log_update_interval(TAG, this) -extern const uint8_t COMPONENT_STATE_MASK; -extern const uint8_t COMPONENT_STATE_CONSTRUCTION; -extern const uint8_t COMPONENT_STATE_SETUP; -extern const uint8_t COMPONENT_STATE_LOOP; -extern const uint8_t COMPONENT_STATE_FAILED; -extern const uint8_t COMPONENT_STATE_LOOP_DONE; -extern const uint8_t STATUS_LED_MASK; -extern const uint8_t STATUS_LED_OK; -extern const uint8_t STATUS_LED_WARNING; -extern const uint8_t STATUS_LED_ERROR; +// Component state uses bits 0-2 (8 states, 5 used) +inline constexpr uint8_t COMPONENT_STATE_MASK = 0x07; +inline constexpr uint8_t COMPONENT_STATE_CONSTRUCTION = 0x00; +inline constexpr uint8_t COMPONENT_STATE_SETUP = 0x01; +inline constexpr uint8_t COMPONENT_STATE_LOOP = 0x02; +inline constexpr uint8_t COMPONENT_STATE_FAILED = 0x03; +inline constexpr uint8_t COMPONENT_STATE_LOOP_DONE = 0x04; +// Status LED uses bits 3-4 +inline constexpr uint8_t STATUS_LED_MASK = 0x18; +inline constexpr uint8_t STATUS_LED_OK = 0x00; +inline constexpr uint8_t STATUS_LED_WARNING = 0x08; +inline constexpr uint8_t STATUS_LED_ERROR = 0x10; // Remove before 2026.8.0 enum class RetryResult { DONE, RETRY }; From 652c669777ecaa125f575aa7eac72bf7f5cc5a1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:08:02 -0600 Subject: [PATCH 0740/2030] Bump pillow from 11.3.0 to 12.1.1 (#14048) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a0a29ad30a..77d30ecd3d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import ruamel.yaml.clib==0.2.15 # dashboard_import esphome-glyphsets==0.2.0 -pillow==11.3.0 +pillow==12.1.1 resvg-py==0.2.6 freetype-py==2.5.1 jinja2==3.1.6 From f73bcc0e7bebba965a76859f680ac16681833a4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 09:08:12 -0600 Subject: [PATCH 0741/2030] Bump cryptography from 45.0.1 to 46.0.5 (#14049) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 77d30ecd3d..2e6268284a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -cryptography==45.0.1 +cryptography==46.0.5 voluptuous==0.16.0 PyYAML==6.0.3 paho-mqtt==1.6.1 From 9cd7b0b32b1a4c27a3b0673b1d10187e69e55109 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:09:33 -0500 Subject: [PATCH 0742/2030] [external_components] Clean up incomplete clone on failed ref fetch (#14051) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 4 +- esphome/git.py | 47 ++++++----- esphome/helpers.py | 20 ++++- esphome/writer.py | 27 +------ tests/unit_tests/test_git.py | 113 ++++++++++++++++++++++++++- 5 files changed, 162 insertions(+), 49 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b78b945a24..8b3e1afea6 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -44,9 +44,9 @@ from esphome.const import ( from esphome.core import CORE, HexInt, TimePeriod from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv -from esphome.helpers import copy_file_if_changed, write_file_if_changed +from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache, rmtree +from esphome.writer import clean_cmake_cache from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa diff --git a/esphome/git.py b/esphome/git.py index 4ff07ffe75..a45768b5cd 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -5,12 +5,12 @@ import hashlib import logging from pathlib import Path import re -import shutil import subprocess import urllib.parse import esphome.config_validation as cv from esphome.core import CORE, TimePeriodSeconds +from esphome.helpers import rmtree _LOGGER = logging.getLogger(__name__) @@ -115,24 +115,35 @@ def clone_or_update( if not repo_dir.is_dir(): _LOGGER.info("Cloning %s", key) _LOGGER.debug("Location: %s", repo_dir) - cmd = ["git", "clone", "--depth=1"] - cmd += ["--", url, str(repo_dir)] - run_git_command(cmd) + try: + cmd = ["git", "clone", "--depth=1"] + cmd += ["--", url, str(repo_dir)] + run_git_command(cmd) - if ref is not None: - # We need to fetch the PR branch first, otherwise git will complain - # about missing objects - _LOGGER.info("Fetching %s", ref) - run_git_command(["git", "fetch", "--", "origin", ref], git_dir=repo_dir) - run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], git_dir=repo_dir) + if ref is not None: + # We need to fetch the PR branch first, otherwise git will complain + # about missing objects + _LOGGER.info("Fetching %s", ref) + run_git_command(["git", "fetch", "--", "origin", ref], git_dir=repo_dir) + run_git_command( + ["git", "reset", "--hard", "FETCH_HEAD"], git_dir=repo_dir + ) - if submodules is not None: - _LOGGER.info( - "Initializing submodules (%s) for %s", ", ".join(submodules), key - ) - run_git_command( - ["git", "submodule", "update", "--init"] + submodules, git_dir=repo_dir - ) + if submodules is not None: + _LOGGER.info( + "Initializing submodules (%s) for %s", ", ".join(submodules), key + ) + run_git_command( + ["git", "submodule", "update", "--init"] + submodules, + git_dir=repo_dir, + ) + except GitException: + # Remove incomplete clone to prevent stale state. Without this, + # a failed ref fetch leaves a clone on the default branch, and + # subsequent calls skip the update due to the refresh window. + if repo_dir.is_dir(): + rmtree(repo_dir) + raise else: # Check refresh needed @@ -193,7 +204,7 @@ def clone_or_update( err, ) _LOGGER.info("Removing broken repository at %s", repo_dir) - shutil.rmtree(repo_dir) + rmtree(repo_dir) _LOGGER.info("Successfully removed broken repository, re-cloning...") # Recursively call clone_or_update to re-clone diff --git a/esphome/helpers.py b/esphome/helpers.py index ae142b7f8b..145ebd4096 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -8,6 +8,7 @@ from pathlib import Path import platform import re import shutil +import stat import tempfile from typing import TYPE_CHECKING from urllib.parse import urlparse @@ -354,6 +355,23 @@ def is_ha_addon(): return get_bool_env("ESPHOME_IS_HA_ADDON") +def rmtree(path: Path | str) -> None: + """Remove a directory tree, handling read-only files on Windows. + + On Windows, git pack files and other files may be marked read-only, + causing shutil.rmtree to fail. This handles that by removing the + read-only flag and retrying. + """ + + def _onerror(func, path, exc_info): + if os.access(path, os.W_OK): + raise exc_info[1].with_traceback(exc_info[2]) + os.chmod(path, stat.S_IWUSR | stat.S_IRUSR) + func(path) + + shutil.rmtree(path, onerror=_onerror) + + def walk_files(path: Path): for root, _, files in os.walk(path): for name in files: @@ -481,8 +499,6 @@ def list_starts_with(list_, sub): def file_compare(path1: Path, path2: Path) -> bool: """Return True if the files path1 and path2 have the same contents.""" - import stat - try: stat1, stat2 = path1.stat(), path2.stat() except OSError: diff --git a/esphome/writer.py b/esphome/writer.py index 661118e518..fd4c811fb3 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -1,14 +1,10 @@ -from collections.abc import Callable import importlib import json import logging import os from pathlib import Path import re -import shutil -import stat import time -from types import TracebackType from esphome import loader from esphome.config import iter_component_configs, iter_components @@ -25,6 +21,7 @@ from esphome.helpers import ( get_str_env, is_ha_addon, read_file, + rmtree, walk_files, write_file, write_file_if_changed, @@ -404,28 +401,6 @@ def clean_cmake_cache(): pioenvs_cmake_path.unlink() -def _rmtree_error_handler( - func: Callable[[str], object], - path: str, - exc_info: tuple[type[BaseException], BaseException, TracebackType | None], -) -> None: - """Error handler for shutil.rmtree to handle read-only files on Windows. - - On Windows, git pack files and other files may be marked read-only, - causing shutil.rmtree to fail with "Access is denied". This handler - removes the read-only flag and retries the deletion. - """ - if os.access(path, os.W_OK): - raise exc_info[1].with_traceback(exc_info[2]) - os.chmod(path, stat.S_IWUSR | stat.S_IRUSR) - func(path) - - -def rmtree(path: Path | str) -> None: - """Remove a directory tree, handling read-only files on Windows.""" - shutil.rmtree(path, onerror=_rmtree_error_handler) - - def clean_build(clear_pio_cache: bool = True): # Allow skipping cache cleaning for integration tests if os.environ.get("ESPHOME_SKIP_CLEAN_BUILD"): diff --git a/tests/unit_tests/test_git.py b/tests/unit_tests/test_git.py index 0411fe5e43..745dfad487 100644 --- a/tests/unit_tests/test_git.py +++ b/tests/unit_tests/test_git.py @@ -656,7 +656,7 @@ def test_clone_or_update_recover_broken_flag_prevents_infinite_loop( # Should raise on the second attempt when _recover_broken=False # This hits the "if not _recover_broken: raise" path with ( - unittest.mock.patch("esphome.git.shutil.rmtree", side_effect=mock_rmtree), + unittest.mock.patch("esphome.git.rmtree", side_effect=mock_rmtree), pytest.raises(GitCommandError, match="fatal: unable to write new index file"), ): git.clone_or_update( @@ -671,3 +671,114 @@ def test_clone_or_update_recover_broken_flag_prevents_infinite_loop( stash_calls = [c for c in call_list if "stash" in c[0][0]] # Should have exactly two stash calls assert len(stash_calls) == 2 + + +def test_clone_or_update_cleans_up_on_failed_ref_fetch( + tmp_path: Path, mock_run_git_command: Mock +) -> None: + """Test that a failed ref fetch removes the incomplete clone directory. + + When cloning with a specific ref, if `git clone` succeeds but the + subsequent `git fetch <ref>` fails, the clone directory should be + removed so the next attempt starts fresh instead of finding a stale + clone on the default branch. + """ + CORE.config_path = tmp_path / "test.yaml" + + url = "https://github.com/test/repo" + ref = "pull/123/head" + domain = "test" + repo_dir = _compute_repo_dir(url, ref, domain) + + def git_command_side_effect( + cmd: list[str], cwd: str | None = None, **kwargs: Any + ) -> str: + cmd_type = _get_git_command_type(cmd) + if cmd_type == "clone": + # Simulate successful clone by creating the directory + repo_dir.mkdir(parents=True, exist_ok=True) + (repo_dir / ".git").mkdir(exist_ok=True) + return "" + if cmd_type == "fetch": + raise GitCommandError("fatal: couldn't find remote ref pull/123/head") + return "" + + mock_run_git_command.side_effect = git_command_side_effect + + refresh = TimePeriodSeconds(days=1) + + with pytest.raises(GitCommandError, match="couldn't find remote ref"): + git.clone_or_update( + url=url, + ref=ref, + refresh=refresh, + domain=domain, + ) + + # The incomplete clone directory should have been removed + assert not repo_dir.exists() + + # Verify clone was attempted then fetch failed + call_list = mock_run_git_command.call_args_list + clone_calls = [c for c in call_list if "clone" in c[0][0]] + assert len(clone_calls) == 1 + fetch_calls = [c for c in call_list if "fetch" in c[0][0]] + assert len(fetch_calls) == 1 + + +def test_clone_or_update_stale_clone_is_retried_after_cleanup( + tmp_path: Path, mock_run_git_command: Mock +) -> None: + """Test that after cleanup, a subsequent call does a fresh clone. + + This is the full scenario: first call fails at fetch (directory cleaned up), + second call sees no directory and clones fresh. + """ + CORE.config_path = tmp_path / "test.yaml" + + url = "https://github.com/test/repo" + ref = "pull/123/head" + domain = "test" + repo_dir = _compute_repo_dir(url, ref, domain) + + call_count = {"clone": 0, "fetch": 0} + + def git_command_side_effect( + cmd: list[str], cwd: str | None = None, **kwargs: Any + ) -> str: + cmd_type = _get_git_command_type(cmd) + if cmd_type == "clone": + call_count["clone"] += 1 + repo_dir.mkdir(parents=True, exist_ok=True) + (repo_dir / ".git").mkdir(exist_ok=True) + return "" + if cmd_type == "fetch": + call_count["fetch"] += 1 + if call_count["fetch"] == 1: + # First fetch fails + raise GitCommandError("fatal: couldn't find remote ref pull/123/head") + # Second fetch succeeds + return "" + if cmd_type == "reset": + return "" + return "" + + mock_run_git_command.side_effect = git_command_side_effect + + refresh = TimePeriodSeconds(days=1) + + # First call: clone succeeds, fetch fails, directory cleaned up + with pytest.raises(GitCommandError, match="couldn't find remote ref"): + git.clone_or_update(url=url, ref=ref, refresh=refresh, domain=domain) + + assert not repo_dir.exists() + + # Second call: fresh clone + fetch succeeds + result_dir, _ = git.clone_or_update( + url=url, ref=ref, refresh=refresh, domain=domain + ) + + assert result_dir == repo_dir + assert repo_dir.exists() + assert call_count["clone"] == 2 + assert call_count["fetch"] == 2 From 6b8264fcaa56e7d9868733f9b3e39135c886f67f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:09:33 -0500 Subject: [PATCH 0743/2030] [external_components] Clean up incomplete clone on failed ref fetch (#14051) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 4 +- esphome/git.py | 47 ++++++----- esphome/helpers.py | 20 ++++- esphome/writer.py | 27 +------ tests/unit_tests/test_git.py | 113 ++++++++++++++++++++++++++- 5 files changed, 162 insertions(+), 49 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b78b945a24..8b3e1afea6 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -44,9 +44,9 @@ from esphome.const import ( from esphome.core import CORE, HexInt, TimePeriod from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv -from esphome.helpers import copy_file_if_changed, write_file_if_changed +from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache, rmtree +from esphome.writer import clean_cmake_cache from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa diff --git a/esphome/git.py b/esphome/git.py index 4ff07ffe75..a45768b5cd 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -5,12 +5,12 @@ import hashlib import logging from pathlib import Path import re -import shutil import subprocess import urllib.parse import esphome.config_validation as cv from esphome.core import CORE, TimePeriodSeconds +from esphome.helpers import rmtree _LOGGER = logging.getLogger(__name__) @@ -115,24 +115,35 @@ def clone_or_update( if not repo_dir.is_dir(): _LOGGER.info("Cloning %s", key) _LOGGER.debug("Location: %s", repo_dir) - cmd = ["git", "clone", "--depth=1"] - cmd += ["--", url, str(repo_dir)] - run_git_command(cmd) + try: + cmd = ["git", "clone", "--depth=1"] + cmd += ["--", url, str(repo_dir)] + run_git_command(cmd) - if ref is not None: - # We need to fetch the PR branch first, otherwise git will complain - # about missing objects - _LOGGER.info("Fetching %s", ref) - run_git_command(["git", "fetch", "--", "origin", ref], git_dir=repo_dir) - run_git_command(["git", "reset", "--hard", "FETCH_HEAD"], git_dir=repo_dir) + if ref is not None: + # We need to fetch the PR branch first, otherwise git will complain + # about missing objects + _LOGGER.info("Fetching %s", ref) + run_git_command(["git", "fetch", "--", "origin", ref], git_dir=repo_dir) + run_git_command( + ["git", "reset", "--hard", "FETCH_HEAD"], git_dir=repo_dir + ) - if submodules is not None: - _LOGGER.info( - "Initializing submodules (%s) for %s", ", ".join(submodules), key - ) - run_git_command( - ["git", "submodule", "update", "--init"] + submodules, git_dir=repo_dir - ) + if submodules is not None: + _LOGGER.info( + "Initializing submodules (%s) for %s", ", ".join(submodules), key + ) + run_git_command( + ["git", "submodule", "update", "--init"] + submodules, + git_dir=repo_dir, + ) + except GitException: + # Remove incomplete clone to prevent stale state. Without this, + # a failed ref fetch leaves a clone on the default branch, and + # subsequent calls skip the update due to the refresh window. + if repo_dir.is_dir(): + rmtree(repo_dir) + raise else: # Check refresh needed @@ -193,7 +204,7 @@ def clone_or_update( err, ) _LOGGER.info("Removing broken repository at %s", repo_dir) - shutil.rmtree(repo_dir) + rmtree(repo_dir) _LOGGER.info("Successfully removed broken repository, re-cloning...") # Recursively call clone_or_update to re-clone diff --git a/esphome/helpers.py b/esphome/helpers.py index ae142b7f8b..145ebd4096 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -8,6 +8,7 @@ from pathlib import Path import platform import re import shutil +import stat import tempfile from typing import TYPE_CHECKING from urllib.parse import urlparse @@ -354,6 +355,23 @@ def is_ha_addon(): return get_bool_env("ESPHOME_IS_HA_ADDON") +def rmtree(path: Path | str) -> None: + """Remove a directory tree, handling read-only files on Windows. + + On Windows, git pack files and other files may be marked read-only, + causing shutil.rmtree to fail. This handles that by removing the + read-only flag and retrying. + """ + + def _onerror(func, path, exc_info): + if os.access(path, os.W_OK): + raise exc_info[1].with_traceback(exc_info[2]) + os.chmod(path, stat.S_IWUSR | stat.S_IRUSR) + func(path) + + shutil.rmtree(path, onerror=_onerror) + + def walk_files(path: Path): for root, _, files in os.walk(path): for name in files: @@ -481,8 +499,6 @@ def list_starts_with(list_, sub): def file_compare(path1: Path, path2: Path) -> bool: """Return True if the files path1 and path2 have the same contents.""" - import stat - try: stat1, stat2 = path1.stat(), path2.stat() except OSError: diff --git a/esphome/writer.py b/esphome/writer.py index 661118e518..fd4c811fb3 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -1,14 +1,10 @@ -from collections.abc import Callable import importlib import json import logging import os from pathlib import Path import re -import shutil -import stat import time -from types import TracebackType from esphome import loader from esphome.config import iter_component_configs, iter_components @@ -25,6 +21,7 @@ from esphome.helpers import ( get_str_env, is_ha_addon, read_file, + rmtree, walk_files, write_file, write_file_if_changed, @@ -404,28 +401,6 @@ def clean_cmake_cache(): pioenvs_cmake_path.unlink() -def _rmtree_error_handler( - func: Callable[[str], object], - path: str, - exc_info: tuple[type[BaseException], BaseException, TracebackType | None], -) -> None: - """Error handler for shutil.rmtree to handle read-only files on Windows. - - On Windows, git pack files and other files may be marked read-only, - causing shutil.rmtree to fail with "Access is denied". This handler - removes the read-only flag and retries the deletion. - """ - if os.access(path, os.W_OK): - raise exc_info[1].with_traceback(exc_info[2]) - os.chmod(path, stat.S_IWUSR | stat.S_IRUSR) - func(path) - - -def rmtree(path: Path | str) -> None: - """Remove a directory tree, handling read-only files on Windows.""" - shutil.rmtree(path, onerror=_rmtree_error_handler) - - def clean_build(clear_pio_cache: bool = True): # Allow skipping cache cleaning for integration tests if os.environ.get("ESPHOME_SKIP_CLEAN_BUILD"): diff --git a/tests/unit_tests/test_git.py b/tests/unit_tests/test_git.py index 0411fe5e43..745dfad487 100644 --- a/tests/unit_tests/test_git.py +++ b/tests/unit_tests/test_git.py @@ -656,7 +656,7 @@ def test_clone_or_update_recover_broken_flag_prevents_infinite_loop( # Should raise on the second attempt when _recover_broken=False # This hits the "if not _recover_broken: raise" path with ( - unittest.mock.patch("esphome.git.shutil.rmtree", side_effect=mock_rmtree), + unittest.mock.patch("esphome.git.rmtree", side_effect=mock_rmtree), pytest.raises(GitCommandError, match="fatal: unable to write new index file"), ): git.clone_or_update( @@ -671,3 +671,114 @@ def test_clone_or_update_recover_broken_flag_prevents_infinite_loop( stash_calls = [c for c in call_list if "stash" in c[0][0]] # Should have exactly two stash calls assert len(stash_calls) == 2 + + +def test_clone_or_update_cleans_up_on_failed_ref_fetch( + tmp_path: Path, mock_run_git_command: Mock +) -> None: + """Test that a failed ref fetch removes the incomplete clone directory. + + When cloning with a specific ref, if `git clone` succeeds but the + subsequent `git fetch <ref>` fails, the clone directory should be + removed so the next attempt starts fresh instead of finding a stale + clone on the default branch. + """ + CORE.config_path = tmp_path / "test.yaml" + + url = "https://github.com/test/repo" + ref = "pull/123/head" + domain = "test" + repo_dir = _compute_repo_dir(url, ref, domain) + + def git_command_side_effect( + cmd: list[str], cwd: str | None = None, **kwargs: Any + ) -> str: + cmd_type = _get_git_command_type(cmd) + if cmd_type == "clone": + # Simulate successful clone by creating the directory + repo_dir.mkdir(parents=True, exist_ok=True) + (repo_dir / ".git").mkdir(exist_ok=True) + return "" + if cmd_type == "fetch": + raise GitCommandError("fatal: couldn't find remote ref pull/123/head") + return "" + + mock_run_git_command.side_effect = git_command_side_effect + + refresh = TimePeriodSeconds(days=1) + + with pytest.raises(GitCommandError, match="couldn't find remote ref"): + git.clone_or_update( + url=url, + ref=ref, + refresh=refresh, + domain=domain, + ) + + # The incomplete clone directory should have been removed + assert not repo_dir.exists() + + # Verify clone was attempted then fetch failed + call_list = mock_run_git_command.call_args_list + clone_calls = [c for c in call_list if "clone" in c[0][0]] + assert len(clone_calls) == 1 + fetch_calls = [c for c in call_list if "fetch" in c[0][0]] + assert len(fetch_calls) == 1 + + +def test_clone_or_update_stale_clone_is_retried_after_cleanup( + tmp_path: Path, mock_run_git_command: Mock +) -> None: + """Test that after cleanup, a subsequent call does a fresh clone. + + This is the full scenario: first call fails at fetch (directory cleaned up), + second call sees no directory and clones fresh. + """ + CORE.config_path = tmp_path / "test.yaml" + + url = "https://github.com/test/repo" + ref = "pull/123/head" + domain = "test" + repo_dir = _compute_repo_dir(url, ref, domain) + + call_count = {"clone": 0, "fetch": 0} + + def git_command_side_effect( + cmd: list[str], cwd: str | None = None, **kwargs: Any + ) -> str: + cmd_type = _get_git_command_type(cmd) + if cmd_type == "clone": + call_count["clone"] += 1 + repo_dir.mkdir(parents=True, exist_ok=True) + (repo_dir / ".git").mkdir(exist_ok=True) + return "" + if cmd_type == "fetch": + call_count["fetch"] += 1 + if call_count["fetch"] == 1: + # First fetch fails + raise GitCommandError("fatal: couldn't find remote ref pull/123/head") + # Second fetch succeeds + return "" + if cmd_type == "reset": + return "" + return "" + + mock_run_git_command.side_effect = git_command_side_effect + + refresh = TimePeriodSeconds(days=1) + + # First call: clone succeeds, fetch fails, directory cleaned up + with pytest.raises(GitCommandError, match="couldn't find remote ref"): + git.clone_or_update(url=url, ref=ref, refresh=refresh, domain=domain) + + assert not repo_dir.exists() + + # Second call: fresh clone + fetch succeeds + result_dir, _ = git.clone_or_update( + url=url, ref=ref, refresh=refresh, domain=domain + ) + + assert result_dir == repo_dir + assert repo_dir.exists() + assert call_count["clone"] == 2 + assert call_count["fetch"] == 2 From ab572c2882c499f5e517f10c704ced98221543f9 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:03:44 +1300 Subject: [PATCH 0744/2030] Bump version to 2026.2.0b5 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index f9deb32899..88565b4a83 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0b4 +PROJECT_NUMBER = 2026.2.0b5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index f494b5d41e..b746a55cd4 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0b4" +__version__ = "2026.2.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 2c89cded4b50130cf3a570971705f488f0e27fed Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Feb 2026 09:30:04 +1300 Subject: [PATCH 0745/2030] Bump version to 2026.2.0 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 88565b4a83..38135f9106 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0b5 +PROJECT_NUMBER = 2026.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index b746a55cd4..9115055e7b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0b5" +__version__ = "2026.2.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 4a038978d27b4ed193de8fb934ff32221ae9a31f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 15:04:14 -0600 Subject: [PATCH 0746/2030] [pca9685] Make mode constants inline constexpr (#14042) --- esphome/components/pca9685/pca9685_output.cpp | 6 +----- esphome/components/pca9685/pca9685_output.h | 10 +++++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/esphome/components/pca9685/pca9685_output.cpp b/esphome/components/pca9685/pca9685_output.cpp index 77e3d5a6c6..89a6bcdcc0 100644 --- a/esphome/components/pca9685/pca9685_output.cpp +++ b/esphome/components/pca9685/pca9685_output.cpp @@ -8,11 +8,7 @@ namespace pca9685 { static const char *const TAG = "pca9685"; -const uint8_t PCA9685_MODE_INVERTED = 0x10; -const uint8_t PCA9685_MODE_OUTPUT_ONACK = 0x08; -const uint8_t PCA9685_MODE_OUTPUT_TOTEM_POLE = 0x04; -const uint8_t PCA9685_MODE_OUTNE_HIGHZ = 0x02; -const uint8_t PCA9685_MODE_OUTNE_LOW = 0x01; +// PCA9685 mode constants are now inline constexpr in pca9685_output.h static const uint8_t PCA9685_REGISTER_SOFTWARE_RESET = 0x06; static const uint8_t PCA9685_REGISTER_MODE1 = 0x00; diff --git a/esphome/components/pca9685/pca9685_output.h b/esphome/components/pca9685/pca9685_output.h index 288c923d4c..785cc974da 100644 --- a/esphome/components/pca9685/pca9685_output.h +++ b/esphome/components/pca9685/pca9685_output.h @@ -13,15 +13,15 @@ enum class PhaseBalancer { }; /// Inverts polarity of channel output signal -extern const uint8_t PCA9685_MODE_INVERTED; +inline constexpr uint8_t PCA9685_MODE_INVERTED = 0x10; /// Channel update happens upon ACK (post-set) rather than on STOP (endTransmission) -extern const uint8_t PCA9685_MODE_OUTPUT_ONACK; +inline constexpr uint8_t PCA9685_MODE_OUTPUT_ONACK = 0x08; /// Use a totem-pole (push-pull) style output rather than an open-drain structure. -extern const uint8_t PCA9685_MODE_OUTPUT_TOTEM_POLE; +inline constexpr uint8_t PCA9685_MODE_OUTPUT_TOTEM_POLE = 0x04; /// For active low output enable, sets channel output to high-impedance state -extern const uint8_t PCA9685_MODE_OUTNE_HIGHZ; +inline constexpr uint8_t PCA9685_MODE_OUTNE_HIGHZ = 0x02; /// Similarly, sets channel output to high if in totem-pole mode, otherwise -extern const uint8_t PCA9685_MODE_OUTNE_LOW; +inline constexpr uint8_t PCA9685_MODE_OUTNE_LOW = 0x01; class PCA9685Output; From 82cfa00a97a8b6c9d0361c2bec66c3723a2be6e6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 15:04:30 -0600 Subject: [PATCH 0747/2030] [tlc59208f] Make mode constants inline constexpr (#14043) --- esphome/components/tlc59208f/tlc59208f_output.cpp | 12 +----------- esphome/components/tlc59208f/tlc59208f_output.h | 14 +++++++------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/esphome/components/tlc59208f/tlc59208f_output.cpp b/esphome/components/tlc59208f/tlc59208f_output.cpp index 85311a877c..d35585fe5f 100644 --- a/esphome/components/tlc59208f/tlc59208f_output.cpp +++ b/esphome/components/tlc59208f/tlc59208f_output.cpp @@ -26,17 +26,7 @@ const uint8_t TLC59208F_MODE1_SUB3 = (1 << 1); // 0: device doesn't respond to i2c all-call 3, 1*: responds to all-call const uint8_t TLC59208F_MODE1_ALLCALL = (1 << 0); -// 0*: Group dimming, 1: Group blinking -const uint8_t TLC59208F_MODE2_DMBLNK = (1 << 5); -// 0*: Output change on Stop command, 1: Output change on ACK -const uint8_t TLC59208F_MODE2_OCH = (1 << 3); -// 0*: WDT disabled, 1: WDT enabled -const uint8_t TLC59208F_MODE2_WDTEN = (1 << 2); -// WDT timeouts -const uint8_t TLC59208F_MODE2_WDT_5MS = (0 << 0); -const uint8_t TLC59208F_MODE2_WDT_15MS = (1 << 0); -const uint8_t TLC59208F_MODE2_WDT_25MS = (2 << 0); -const uint8_t TLC59208F_MODE2_WDT_35MS = (3 << 0); +// TLC59208F MODE2 constants are now inline constexpr in tlc59208f_output.h // --- Special function --- // Call address to perform software reset, no devices will ACK diff --git a/esphome/components/tlc59208f/tlc59208f_output.h b/esphome/components/tlc59208f/tlc59208f_output.h index 68ca8061d7..34663cd364 100644 --- a/esphome/components/tlc59208f/tlc59208f_output.h +++ b/esphome/components/tlc59208f/tlc59208f_output.h @@ -9,16 +9,16 @@ namespace esphome { namespace tlc59208f { // 0*: Group dimming, 1: Group blinking -extern const uint8_t TLC59208F_MODE2_DMBLNK; +inline constexpr uint8_t TLC59208F_MODE2_DMBLNK = (1 << 5); // 0*: Output change on Stop command, 1: Output change on ACK -extern const uint8_t TLC59208F_MODE2_OCH; +inline constexpr uint8_t TLC59208F_MODE2_OCH = (1 << 3); // 0*: WDT disabled, 1: WDT enabled -extern const uint8_t TLC59208F_MODE2_WDTEN; +inline constexpr uint8_t TLC59208F_MODE2_WDTEN = (1 << 2); // WDT timeouts -extern const uint8_t TLC59208F_MODE2_WDT_5MS; -extern const uint8_t TLC59208F_MODE2_WDT_15MS; -extern const uint8_t TLC59208F_MODE2_WDT_25MS; -extern const uint8_t TLC59208F_MODE2_WDT_35MS; +inline constexpr uint8_t TLC59208F_MODE2_WDT_5MS = (0 << 0); +inline constexpr uint8_t TLC59208F_MODE2_WDT_15MS = (1 << 0); +inline constexpr uint8_t TLC59208F_MODE2_WDT_25MS = (2 << 0); +inline constexpr uint8_t TLC59208F_MODE2_WDT_35MS = (3 << 0); class TLC59208FOutput; From 09fc0288953d13a09bafef3e9038b36d3ff4c1ee Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 15:16:26 -0600 Subject: [PATCH 0748/2030] [core] Remove dead global_state variable (#14060) --- esphome/core/component.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index a452f4d400..47c4a70c0f 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -82,8 +82,6 @@ void store_component_error_message(const Component *component, const char *messa const uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning const uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again -uint32_t global_state = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - float Component::get_loop_priority() const { return 0.0f; } float Component::get_setup_priority() const { return setup_priority::DATA; } From 02e310f2c9549349ae12615f3fec627d9189479a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 16:48:13 -0600 Subject: [PATCH 0749/2030] [core] Remove unnecessary IRAM_ATTR from yield(), delay(), feed_wdt(), and arch_feed_wdt() (#14063) --- esphome/components/esp32/core.cpp | 6 +++--- esphome/components/esp8266/core.cpp | 6 +++--- esphome/components/host/core.cpp | 6 +++--- esphome/components/libretiny/core.cpp | 6 +++--- esphome/components/rp2040/core.cpp | 6 +++--- esphome/core/application.cpp | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 09a45c14a6..202d929ab9 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -21,9 +21,9 @@ extern "C" __attribute__((weak)) void initArduino() {} namespace esphome { -void IRAM_ATTR HOT yield() { vPortYield(); } +void HOT yield() { vPortYield(); } uint32_t IRAM_ATTR HOT millis() { return (uint32_t) (esp_timer_get_time() / 1000ULL); } -void IRAM_ATTR HOT delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } +void HOT delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } uint32_t IRAM_ATTR HOT micros() { return (uint32_t) esp_timer_get_time(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { @@ -44,7 +44,7 @@ void arch_init() { esp_ota_mark_app_valid_cancel_rollback(); #endif } -void IRAM_ATTR HOT arch_feed_wdt() { esp_task_wdt_reset(); } +void HOT arch_feed_wdt() { esp_task_wdt_reset(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 784b87916b..236d3022be 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -14,9 +14,9 @@ extern "C" { namespace esphome { -void IRAM_ATTR HOT yield() { ::yield(); } +void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } -void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); } +void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { @@ -27,7 +27,7 @@ void arch_restart() { } } void arch_init() {} -void IRAM_ATTR HOT arch_feed_wdt() { system_soft_wdt_feed(); } +void HOT arch_feed_wdt() { system_soft_wdt_feed(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index 164d622dd4..c20a33fa37 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -11,7 +11,7 @@ namespace esphome { -void IRAM_ATTR HOT yield() { ::sched_yield(); } +void HOT yield() { ::sched_yield(); } uint32_t IRAM_ATTR HOT millis() { struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); @@ -19,7 +19,7 @@ uint32_t IRAM_ATTR HOT millis() { uint32_t ms = round(spec.tv_nsec / 1e6); return ((uint32_t) seconds) * 1000U + ms; } -void IRAM_ATTR HOT delay(uint32_t ms) { +void HOT delay(uint32_t ms) { struct timespec ts; ts.tv_sec = ms / 1000; ts.tv_nsec = (ms % 1000) * 1000000; @@ -48,7 +48,7 @@ void arch_restart() { exit(0); } void arch_init() { // pass } -void IRAM_ATTR HOT arch_feed_wdt() { +void HOT arch_feed_wdt() { // pass } diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index b22740f02a..4dda7c3856 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -11,10 +11,10 @@ void loop(); namespace esphome { -void IRAM_ATTR HOT yield() { ::yield(); } +void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } -void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); } +void HOT delay(uint32_t ms) { ::delay(ms); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } void arch_init() { @@ -30,7 +30,7 @@ void arch_restart() { while (1) { } } -void IRAM_ATTR HOT arch_feed_wdt() { lt_wdt_feed(); } +void HOT arch_feed_wdt() { lt_wdt_feed(); } uint32_t arch_get_cpu_cycle_count() { return lt_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return lt_cpu_get_freq(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index d88e9f54b7..37378d88bb 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -9,9 +9,9 @@ namespace esphome { -void IRAM_ATTR HOT yield() { ::yield(); } +void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } -void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); } +void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { @@ -27,7 +27,7 @@ void arch_init() { #endif } -void IRAM_ATTR HOT arch_feed_wdt() { watchdog_update(); } +void HOT arch_feed_wdt() { watchdog_update(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 449acc64cf..406885fd81 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -240,7 +240,7 @@ void Application::process_dump_config_() { this->dump_config_at_++; } -void IRAM_ATTR HOT Application::feed_wdt(uint32_t time) { +void HOT Application::feed_wdt(uint32_t time) { static uint32_t last_feed = 0; // Use provided time if available, otherwise get current time uint32_t now = time ? time : millis(); From 387f615dae037ad8a19dd6f0fad7e04741eee1d7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 16:48:30 -0600 Subject: [PATCH 0750/2030] [api] Add handshake timeout to prevent connection slot exhaustion (#14050) --- esphome/components/api/api_connection.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 4d564af9e2..5a7994a322 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -60,6 +60,11 @@ static constexpr uint8_t MAX_MESSAGES_PER_LOOP = 5; static constexpr uint8_t MAX_PING_RETRIES = 60; static constexpr uint16_t PING_RETRY_INTERVAL = 1000; static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * 5) / 2; +// Timeout for completing the handshake (Noise transport + HelloRequest). +// A stalled handshake from a buggy client or network glitch holds a connection +// slot, which can prevent legitimate clients from reconnecting. Also hardens +// against the less likely case of intentional connection slot exhaustion. +static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 15000; static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION); @@ -205,7 +210,12 @@ void APIConnection::loop() { this->fatal_error_with_log_(LOG_STR("Reading failed"), err); return; } else { - this->last_traffic_ = now; + // Only update last_traffic_ after authentication to ensure the + // handshake timeout is an absolute deadline from connection start. + // Pre-auth messages (e.g. PingRequest) must not reset the timer. + if (this->is_authenticated()) { + this->last_traffic_ = now; + } // read a packet this->read_message(buffer.data_len, buffer.type, buffer.data); if (this->flags_.remove) @@ -223,6 +233,15 @@ void APIConnection::loop() { this->process_active_iterator_(); } + // Disconnect clients that haven't completed the handshake in time. + // Stale half-open connections from buggy clients or network issues can + // accumulate and block legitimate clients from reconnecting. + if (!this->is_authenticated() && now - this->last_traffic_ > HANDSHAKE_TIMEOUT_MS) { + this->on_fatal_error(); + this->log_client_(ESPHOME_LOG_LEVEL_WARN, LOG_STR("handshake timeout; disconnecting")); + return; + } + if (this->flags_.sent_ping) { // Disconnect if not responded within 2.5*keepalive if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) { @@ -1484,6 +1503,8 @@ void APIConnection::complete_authentication_() { } this->flags_.connection_state = static_cast<uint8_t>(ConnectionState::AUTHENTICATED); + // Reset traffic timer so keepalive starts from authentication, not connection start + this->last_traffic_ = App.get_loop_component_start_time(); this->log_client_(ESPHOME_LOG_LEVEL_DEBUG, LOG_STR("connected")); #ifdef USE_API_CLIENT_CONNECTED_TRIGGER { From d90754dc0a182785575f2232f3faa29c4d787c84 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 16:49:19 -0600 Subject: [PATCH 0751/2030] [http_request] Replace heavy STL containers with std::vector for headers (#14024) --- esphome/components/http_request/__init__.py | 2 +- .../components/http_request/http_request.cpp | 22 +++---- .../components/http_request/http_request.h | 58 ++++++++++++------- .../http_request/http_request_arduino.cpp | 12 ++-- .../http_request/http_request_arduino.h | 2 +- .../http_request/http_request_host.cpp | 6 +- .../http_request/http_request_host.h | 2 +- .../http_request/http_request_idf.cpp | 16 ++--- .../http_request/http_request_idf.h | 7 +-- 9 files changed, 65 insertions(+), 62 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 64d74323d6..5faffccbe4 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -310,7 +310,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args): cg.add(var.add_request_header(key, template_)) for value in config.get(CONF_COLLECT_HEADERS, []): - cg.add(var.add_collect_header(value)) + cg.add(var.add_collect_header(value.lower())) if response_conf := config.get(CONF_ON_RESPONSE): if capture_response: diff --git a/esphome/components/http_request/http_request.cpp b/esphome/components/http_request/http_request.cpp index 11dde4715a..6590d2018e 100644 --- a/esphome/components/http_request/http_request.cpp +++ b/esphome/components/http_request/http_request.cpp @@ -22,23 +22,15 @@ void HttpRequestComponent::dump_config() { } std::string HttpContainer::get_response_header(const std::string &header_name) { - auto response_headers = this->get_response_headers(); - auto header_name_lower_case = str_lower_case(header_name); - if (response_headers.count(header_name_lower_case) == 0) { - ESP_LOGW(TAG, "No header with name %s found", header_name_lower_case.c_str()); - return ""; - } else { - auto values = response_headers[header_name_lower_case]; - if (values.empty()) { - ESP_LOGE(TAG, "header with name %s returned an empty list, this shouldn't happen", - header_name_lower_case.c_str()); - return ""; - } else { - auto header_value = values.front(); - ESP_LOGD(TAG, "Header with name %s found with value %s", header_name_lower_case.c_str(), header_value.c_str()); - return header_value; + auto lower = str_lower_case(header_name); + for (const auto &entry : this->response_headers_) { + if (entry.name == lower) { + ESP_LOGD(TAG, "Header with name %s found with value %s", lower.c_str(), entry.value.c_str()); + return entry.value; } } + ESP_LOGW(TAG, "No header with name %s found", lower.c_str()); + return ""; } } // namespace esphome::http_request diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index a427cc4a05..458ffe94a8 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -80,6 +80,16 @@ inline bool is_redirect(int const status) { */ inline bool is_success(int const status) { return status >= HTTP_STATUS_OK && status < HTTP_STATUS_MULTIPLE_CHOICES; } +/// Check if a header name should be collected (linear scan, fine for small lists) +inline bool should_collect_header(const std::vector<std::string> &lower_case_collect_headers, + const std::string &lower_header_name) { + for (const auto &h : lower_case_collect_headers) { + if (h == lower_header_name) + return true; + } + return false; +} + /* * HTTP Container Read Semantics * ============================= @@ -258,20 +268,13 @@ class HttpContainer : public Parented<HttpRequestComponent> { return !this->is_chunked_ && this->bytes_read_ >= this->content_length; } - /** - * @brief Get response headers. - * - * @return The key is the lower case response header name, the value is the header value. - */ - std::map<std::string, std::list<std::string>> get_response_headers() { return this->response_headers_; } - std::string get_response_header(const std::string &header_name); protected: size_t bytes_read_{0}; bool secure_{false}; bool is_chunked_{false}; ///< True if response uses chunked transfer encoding - std::map<std::string, std::list<std::string>> response_headers_{}; + std::vector<Header> response_headers_{}; }; /// Read data from HTTP container into buffer with timeout handling @@ -333,8 +336,8 @@ class HttpRequestComponent : public Component { return this->start(url, "GET", "", request_headers); } std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) { - return this->start(url, "GET", "", request_headers, collect_headers); + const std::vector<std::string> &lower_case_collect_headers) { + return this->start(url, "GET", "", request_headers, lower_case_collect_headers); } std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body) { return this->start(url, "POST", body, {}); @@ -345,29 +348,40 @@ class HttpRequestComponent : public Component { } std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) { - return this->start(url, "POST", body, request_headers, collect_headers); + const std::vector<std::string> &lower_case_collect_headers) { + return this->start(url, "POST", body, request_headers, lower_case_collect_headers); } std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers) { - return this->start(url, method, body, request_headers, {}); + // Call perform() directly to avoid ambiguity with the std::set overload + return this->perform(url, method, body, request_headers, {}); + } + + // Remove before 2027.1.0 + ESPDEPRECATED("Pass collect_headers as std::vector<std::string> instead of std::set. Removed in 2027.1.0.", + "2026.7.0") + std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, + const std::list<Header> &request_headers, + const std::set<std::string> &collect_headers) { + std::vector<std::string> lower; + lower.reserve(collect_headers.size()); + for (const auto &h : collect_headers) { + lower.push_back(str_lower_case(h)); + } + return this->perform(url, method, body, request_headers, lower); } std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) { - std::set<std::string> lower_case_collect_headers; - for (const std::string &collect_header : collect_headers) { - lower_case_collect_headers.insert(str_lower_case(collect_header)); - } + const std::vector<std::string> &lower_case_collect_headers) { return this->perform(url, method, body, request_headers, lower_case_collect_headers); } protected: virtual std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) = 0; + const std::vector<std::string> &lower_case_collect_headers) = 0; const char *useragent_{nullptr}; bool follow_redirects_{}; uint16_t redirect_limit_{}; @@ -389,7 +403,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { this->request_headers_.insert({key, value}); } - void add_collect_header(const char *value) { this->collect_headers_.insert(value); } + void add_collect_header(const char *value) { this->lower_case_collect_headers_.push_back(value); } void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.insert({key, value}); } @@ -431,7 +445,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { } auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, request_headers, - this->collect_headers_); + this->lower_case_collect_headers_); auto captured_args = std::make_tuple(x...); @@ -494,7 +508,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { void encode_json_func_(Ts... x, JsonObject root) { this->json_func_(x..., root); } HttpRequestComponent *parent_; std::map<const char *, TemplatableValue<const char *, Ts...>> request_headers_{}; - std::set<std::string> collect_headers_{"content-type", "content-length"}; + std::vector<std::string> lower_case_collect_headers_{"content-type", "content-length"}; std::map<const char *, TemplatableValue<std::string, Ts...>> json_{}; std::function<void(Ts..., JsonObject)> json_func_{nullptr}; #ifdef USE_HTTP_REQUEST_RESPONSE diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index e5b919e380..3f60b76b58 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -27,7 +27,7 @@ static constexpr int ESP8266_SSL_ERR_OOM = -1000; std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) { + const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); @@ -107,9 +107,9 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur } // returned needed headers must be collected before the requests - const char *header_keys[collect_headers.size()]; + const char *header_keys[lower_case_collect_headers.size()]; int index = 0; - for (auto const &header_name : collect_headers) { + for (auto const &header_name : lower_case_collect_headers) { header_keys[index++] = header_name.c_str(); } container->client_.collectHeaders(header_keys, index); @@ -160,14 +160,14 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur // Still return the container, so it can be used to get the status code and error message } - container->response_headers_ = {}; + container->response_headers_.clear(); auto header_count = container->client_.headers(); for (int i = 0; i < header_count; i++) { const std::string header_name = str_lower_case(container->client_.headerName(i).c_str()); - if (collect_headers.count(header_name) > 0) { + if (should_collect_header(lower_case_collect_headers, header_name)) { std::string header_value = container->client_.header(i).c_str(); ESP_LOGD(TAG, "Received response header, name: %s, value: %s", header_name.c_str(), header_value.c_str()); - container->response_headers_[header_name].push_back(header_value); + container->response_headers_.push_back({header_name, header_value}); } } diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h index a1084b12d5..dbd61de364 100644 --- a/esphome/components/http_request/http_request_arduino.h +++ b/esphome/components/http_request/http_request_arduino.h @@ -50,7 +50,7 @@ class HttpRequestArduino : public HttpRequestComponent { protected: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) override; + const std::vector<std::string> &lower_case_collect_headers) override; }; } // namespace esphome::http_request diff --git a/esphome/components/http_request/http_request_host.cpp b/esphome/components/http_request/http_request_host.cpp index b94570be12..714a73fc31 100644 --- a/esphome/components/http_request/http_request_host.cpp +++ b/esphome/components/http_request/http_request_host.cpp @@ -19,7 +19,7 @@ static const char *const TAG = "http_request.host"; std::shared_ptr<HttpContainer> HttpRequestHost::perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &response_headers) { + const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); ESP_LOGW(TAG, "HTTP Request failed; Not connected to network"); @@ -116,8 +116,8 @@ std::shared_ptr<HttpContainer> HttpRequestHost::perform(const std::string &url, for (auto header : response.headers) { ESP_LOGD(TAG, "Header: %s: %s", header.first.c_str(), header.second.c_str()); auto lower_name = str_lower_case(header.first); - if (response_headers.find(lower_name) != response_headers.end()) { - container->response_headers_[lower_name].emplace_back(header.second); + if (should_collect_header(lower_case_collect_headers, lower_name)) { + container->response_headers_.push_back({lower_name, header.second}); } } container->duration_ms = millis() - start; diff --git a/esphome/components/http_request/http_request_host.h b/esphome/components/http_request/http_request_host.h index 32e149e6a3..79f5b7e817 100644 --- a/esphome/components/http_request/http_request_host.h +++ b/esphome/components/http_request/http_request_host.h @@ -20,7 +20,7 @@ class HttpRequestHost : public HttpRequestComponent { public: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &response_headers) override; + const std::vector<std::string> &lower_case_collect_headers) override; void set_ca_path(const char *ca_path) { this->ca_path_ = ca_path; } protected: diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 486984a694..0921c50b9f 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -19,8 +19,8 @@ namespace esphome::http_request { static const char *const TAG = "http_request.idf"; struct UserData { - const std::set<std::string> &collect_headers; - std::map<std::string, std::list<std::string>> response_headers; + const std::vector<std::string> &lower_case_collect_headers; + std::vector<Header> &response_headers; }; void HttpRequestIDF::dump_config() { @@ -38,10 +38,10 @@ esp_err_t HttpRequestIDF::http_event_handler(esp_http_client_event_t *evt) { switch (evt->event_id) { case HTTP_EVENT_ON_HEADER: { const std::string header_name = str_lower_case(evt->header_key); - if (user_data->collect_headers.count(header_name)) { + if (should_collect_header(user_data->lower_case_collect_headers, header_name)) { const std::string header_value = evt->header_value; ESP_LOGD(TAG, "Received response header, name: %s, value: %s", header_name.c_str(), header_value.c_str()); - user_data->response_headers[header_name].push_back(header_value); + user_data->response_headers.push_back({header_name, header_value}); } break; } @@ -55,7 +55,7 @@ esp_err_t HttpRequestIDF::http_event_handler(esp_http_client_event_t *evt) { std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) { + const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); ESP_LOGE(TAG, "HTTP Request failed; Not connected to network"); @@ -110,8 +110,6 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c watchdog::WatchdogManager wdm(this->get_watchdog_timeout()); config.event_handler = http_event_handler; - auto user_data = UserData{collect_headers, {}}; - config.user_data = static_cast<void *>(&user_data); esp_http_client_handle_t client = esp_http_client_init(&config); @@ -120,6 +118,9 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c container->set_secure(secure); + auto user_data = UserData{lower_case_collect_headers, container->response_headers_}; + esp_http_client_set_user_data(client, static_cast<void *>(&user_data)); + for (const auto &header : request_headers) { esp_http_client_set_header(client, header.name.c_str(), header.value.c_str()); } @@ -164,7 +165,6 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c container->feed_wdt(); container->status_code = esp_http_client_get_status_code(client); container->feed_wdt(); - container->set_response_headers(user_data.response_headers); container->duration_ms = millis() - start; if (is_success(container->status_code)) { return container; diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 2a130eae58..9206ba6f5d 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -21,11 +21,8 @@ class HttpContainerIDF : public HttpContainer { /// @brief Feeds the watchdog timer if the executing task has one attached void feed_wdt(); - void set_response_headers(std::map<std::string, std::list<std::string>> &response_headers) { - this->response_headers_ = std::move(response_headers); - } - protected: + friend class HttpRequestIDF; esp_http_client_handle_t client_; }; @@ -41,7 +38,7 @@ class HttpRequestIDF : public HttpRequestComponent { protected: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, - const std::set<std::string> &collect_headers) override; + const std::vector<std::string> &lower_case_collect_headers) override; // if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE uint16_t buffer_size_rx_{}; uint16_t buffer_size_tx_{}; From bd055e75b9c2def6d9e12170e771920115c9751f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 16:49:37 -0600 Subject: [PATCH 0752/2030] [core] Shrink Application::dump_config_at_ from size_t to uint16_t (#14053) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/application.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index 30611227a2..e0299f3db3 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -582,9 +582,6 @@ class Application { std::string name_; std::string friendly_name_; - // size_t members - size_t dump_config_at_{SIZE_MAX}; - // 4-byte members uint32_t last_loop_{0}; uint32_t loop_component_start_time_{0}; @@ -594,7 +591,8 @@ class Application { #endif // 2-byte members (grouped together for alignment) - uint16_t loop_interval_{16}; // Loop interval in ms (max 65535ms = 65.5 seconds) + uint16_t dump_config_at_{std::numeric_limits<uint16_t>::max()}; // Index into components_ for dump_config progress + uint16_t loop_interval_{16}; // Loop interval in ms (max 65535ms = 65.5 seconds) uint16_t looping_components_active_end_{0}; // Index marking end of active components in looping_components_ uint16_t current_loop_index_{0}; // For safe reentrant modifications during iteration From 5f82017a310bd60123eadee17a5f2f3d36106694 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:01:00 -0600 Subject: [PATCH 0753/2030] [udp] Register socket consumption for CONFIG_LWIP_MAX_SOCKETS (#14068) --- esphome/components/udp/__init__.py | 63 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index bfaa5f2516..c9586d0b95 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -14,6 +14,7 @@ import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID from esphome.core import ID from esphome.cpp_generator import MockObj +from esphome.types import ConfigType CODEOWNERS = ["@clydebarrow"] DEPENDENCIES = ["network"] @@ -65,33 +66,47 @@ RELOCATED = { ) } -CONFIG_SCHEMA = cv.COMPONENT_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(UDPComponent), - cv.Optional(CONF_PORT, default=18511): cv.Any( - cv.port, - cv.Schema( + +def _consume_udp_sockets(config: ConfigType) -> ConfigType: + """Register socket needs for UDP component.""" + from esphome.components import socket + + # UDP uses up to 2 sockets: 1 broadcast + 1 listen + # Whether each is used depends on code generation, so register worst case + socket.consume_sockets(2, "udp")(config) + return config + + +CONFIG_SCHEMA = cv.All( + cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(UDPComponent), + cv.Optional(CONF_PORT, default=18511): cv.Any( + cv.port, + cv.Schema( + { + cv.Required(CONF_LISTEN_PORT): cv.port, + cv.Required(CONF_BROADCAST_PORT): cv.port, + } + ), + ), + cv.Optional( + CONF_LISTEN_ADDRESS, default="255.255.255.255" + ): cv.ipv4address_multi_broadcast, + cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list( + cv.ipv4address, + ), + cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( { - cv.Required(CONF_LISTEN_PORT): cv.port, - cv.Required(CONF_BROADCAST_PORT): cv.port, + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + Trigger.template(trigger_args) + ), } ), - ), - cv.Optional( - CONF_LISTEN_ADDRESS, default="255.255.255.255" - ): cv.ipv4address_multi_broadcast, - cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list( - cv.ipv4address, - ), - cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Trigger.template(trigger_args) - ), - } - ), - } -).extend(RELOCATED) + } + ).extend(RELOCATED), + _consume_udp_sockets, +) async def register_udp_client(var, config): From 3b869f172064dc994f2ff001e4c73c8da858b01e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:01:37 -0600 Subject: [PATCH 0754/2030] [web_server] Double socket allocation to prevent connection exhaustion (#14067) --- esphome/components/web_server/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 8b02a6baee..294a5e0a15 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -144,9 +144,10 @@ def _consume_web_server_sockets(config: ConfigType) -> ConfigType: """Register socket needs for web_server component.""" from esphome.components import socket - # Web server needs 1 listening socket + typically 2 concurrent client connections - # (browser makes 2 connections for page + event stream) - sockets_needed = 3 + # Web server needs 1 listening socket + typically 5 concurrent client connections + # (browser opens connections for page resources, SSE event stream, and POST + # requests for entity control which may linger before closing) + sockets_needed = 6 socket.consume_sockets(sockets_needed, "web_server")(config) return config From 565443b710eb8b56bd7bc2d53fef765d195e4303 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:08:53 -0600 Subject: [PATCH 0755/2030] [pulse_counter] Fix compilation on ESP32-C6/C5/H2/P4 (#14070) --- esphome/components/pulse_counter/pulse_counter_sensor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index 8ac5a28d8f..ef4cc980f6 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -2,7 +2,7 @@ #include "esphome/core/log.h" #ifdef HAS_PCNT -#include <esp_clk_tree.h> +#include <esp_private/esp_clk.h> #include <hal/pcnt_ll.h> #endif @@ -117,9 +117,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } if (this->filter_us != 0) { - uint32_t apb_freq; - esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_APB, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &apb_freq); - uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / apb_freq; + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), }; From be853afc2465a291d3a4806122884c52d0bd905e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 20:57:56 -0600 Subject: [PATCH 0756/2030] [core] Conditionally compile setup_priority override infrastructure (#14057) --- esphome/core/application.cpp | 2 ++ esphome/core/component.cpp | 19 +++++++++++++------ esphome/core/component.h | 1 + esphome/core/defines.h | 1 + esphome/cpp_helpers.py | 3 ++- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 406885fd81..b216233f9b 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -137,8 +137,10 @@ void Application::setup() { ESP_LOGI(TAG, "setup() finished successfully!"); +#ifdef USE_SETUP_PRIORITY_OVERRIDE // Clear setup priority overrides to free memory clear_setup_priority_overrides(); +#endif #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) // Set up wake socket for waking main loop from tasks diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 47c4a70c0f..ba0f1663b9 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -41,20 +41,23 @@ struct ComponentErrorMessage { bool is_flash_ptr; }; +#ifdef USE_SETUP_PRIORITY_OVERRIDE struct ComponentPriorityOverride { const Component *component; float priority; }; +// Setup priority overrides - freed after setup completes +// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +std::vector<ComponentPriorityOverride> *setup_priority_overrides = nullptr; +#endif + // Error messages for failed components // Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead // This is never freed as error messages persist for the lifetime of the device // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) std::vector<ComponentErrorMessage> *component_error_messages = nullptr; -// Setup priority overrides - freed after setup completes -// Using raw pointer instead of unique_ptr to avoid global constructor/destructor overhead -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -std::vector<ComponentPriorityOverride> *setup_priority_overrides = nullptr; // Helper to store error messages - reduces duplication between deprecated and new API // Remove before 2026.6.0 when deprecated const char* API is removed @@ -459,6 +462,7 @@ void log_update_interval(const char *tag, PollingComponent *component) { } } float Component::get_actual_setup_priority() const { +#ifdef USE_SETUP_PRIORITY_OVERRIDE // Check if there's an override in the global vector if (setup_priority_overrides) { // Linear search is fine for small n (typically < 5 overrides) @@ -468,14 +472,14 @@ float Component::get_actual_setup_priority() const { } } } +#endif return this->get_setup_priority(); } +#ifdef USE_SETUP_PRIORITY_OVERRIDE void Component::set_setup_priority(float priority) { // Lazy allocate the vector if needed if (!setup_priority_overrides) { setup_priority_overrides = new std::vector<ComponentPriorityOverride>(); - // Reserve some space to avoid reallocations (most configs have < 10 overrides) - setup_priority_overrides->reserve(10); } // Check if this component already has an override @@ -489,6 +493,7 @@ void Component::set_setup_priority(float priority) { // Add new override setup_priority_overrides->emplace_back(ComponentPriorityOverride{this, priority}); } +#endif bool Component::has_overridden_loop() const { #if defined(USE_HOST) || defined(CLANG_TIDY) @@ -557,10 +562,12 @@ uint32_t WarnIfComponentBlockingGuard::finish() { WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {} +#ifdef USE_SETUP_PRIORITY_OVERRIDE void clear_setup_priority_overrides() { // Free the setup priority map completely delete setup_priority_overrides; setup_priority_overrides = nullptr; } +#endif } // namespace esphome diff --git a/esphome/core/component.h b/esphome/core/component.h index 848bc0ba35..6f7f77dbc1 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -563,6 +563,7 @@ class WarnIfComponentBlockingGuard { }; // Function to clear setup priority overrides after all components are set up +// Only has an implementation when USE_SETUP_PRIORITY_OVERRIDE is defined void clear_setup_priority_overrides(); } // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 0d6c1a42e8..bcafcb4c60 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -109,6 +109,7 @@ #define USE_SAFE_MODE_CALLBACK #define USE_SELECT #define USE_SENSOR +#define USE_SETUP_PRIORITY_OVERRIDE #define USE_STATUS_LED #define USE_STATUS_SENSOR #define USE_SWITCH diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 2698b9b3d5..954a28d3d1 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -9,7 +9,7 @@ from esphome.const import ( ) from esphome.core import CORE, ID, coroutine from esphome.coroutine import FakeAwaitable -from esphome.cpp_generator import LogStringLiteral, add, get_variable +from esphome.cpp_generator import LogStringLiteral, add, add_define, get_variable from esphome.cpp_types import App from esphome.types import ConfigFragmentType, ConfigType from esphome.util import Registry, RegistryEntry @@ -49,6 +49,7 @@ async def register_component(var, config): ) CORE.component_ids.remove(id_) if CONF_SETUP_PRIORITY in config: + add_define("USE_SETUP_PRIORITY_OVERRIDE") add(var.set_setup_priority(config[CONF_SETUP_PRIORITY])) if CONF_UPDATE_INTERVAL in config: add(var.set_update_interval(config[CONF_UPDATE_INTERVAL])) From e4c233b6ceef1d1a306e5879752ffc9815d1190b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 20:59:31 -0600 Subject: [PATCH 0757/2030] [mqtt] Use constexpr for compile-time constants (#14075) --- esphome/components/mqtt/mqtt_backend_esp32.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index adba0cf004..ccc4c4026c 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -114,11 +114,11 @@ struct QueueElement { class MQTTBackendESP32 final : public MQTTBackend { public: - static const size_t MQTT_BUFFER_SIZE = 4096; - static const size_t TASK_STACK_SIZE = 3072; - static const size_t TASK_STACK_SIZE_TLS = 4096; // Larger stack for TLS operations - static const ssize_t TASK_PRIORITY = 5; - static const uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 + static constexpr size_t MQTT_BUFFER_SIZE = 4096; + static constexpr size_t TASK_STACK_SIZE = 3072; + static constexpr size_t TASK_STACK_SIZE_TLS = 4096; // Larger stack for TLS operations + static constexpr ssize_t TASK_PRIORITY = 5; + static constexpr uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 void set_keep_alive(uint16_t keep_alive) final { this->keep_alive_ = keep_alive; } void set_client_id(const char *client_id) final { this->client_id_ = client_id; } From 66d2ac8cb93a5b7380210ee7933d28620dabd3ab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:00:09 -0600 Subject: [PATCH 0758/2030] [web_server] Move climate static traits to DETAIL_ALL only (#14066) --- esphome/components/web_server/web_server.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 3acd2d2119..a796c1426b 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1546,16 +1546,16 @@ std::string WebServer::climate_json_(climate::Climate *obj, JsonDetail start_con for (auto const &custom_preset : traits.get_supported_custom_presets()) opt.add(custom_preset); } + root[ESPHOME_F("max_temp")] = + (value_accuracy_to_buf(temp_buf, traits.get_visual_max_temperature(), target_accuracy), temp_buf); + root[ESPHOME_F("min_temp")] = + (value_accuracy_to_buf(temp_buf, traits.get_visual_min_temperature(), target_accuracy), temp_buf); + root[ESPHOME_F("step")] = traits.get_visual_target_temperature_step(); this->add_sorting_info_(root, obj); } bool has_state = false; root[ESPHOME_F("mode")] = PSTR_LOCAL(climate_mode_to_string(obj->mode)); - root[ESPHOME_F("max_temp")] = - (value_accuracy_to_buf(temp_buf, traits.get_visual_max_temperature(), target_accuracy), temp_buf); - root[ESPHOME_F("min_temp")] = - (value_accuracy_to_buf(temp_buf, traits.get_visual_min_temperature(), target_accuracy), temp_buf); - root[ESPHOME_F("step")] = traits.get_visual_target_temperature_step(); if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { root[ESPHOME_F("action")] = PSTR_LOCAL(climate_action_to_string(obj->action)); root[ESPHOME_F("state")] = root[ESPHOME_F("action")]; From 7e118178b3d5e208eab87e0f882b38dcb18e5ed6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:00:24 -0600 Subject: [PATCH 0759/2030] [web_server] Fix water_heater JSON key names and move traits to DETAIL_ALL (#14064) --- esphome/components/web_server/web_server.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index a796c1426b..e3d131f58e 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1922,6 +1922,9 @@ std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDe JsonArray modes = root[ESPHOME_F("modes")].to<JsonArray>(); for (auto m : traits.get_supported_modes()) modes.add(PSTR_LOCAL(water_heater::water_heater_mode_to_string(m))); + root[ESPHOME_F("min_temp")] = traits.get_min_temperature(); + root[ESPHOME_F("max_temp")] = traits.get_max_temperature(); + root[ESPHOME_F("step")] = traits.get_target_temperature_step(); this->add_sorting_info_(root, obj); } @@ -1944,10 +1947,6 @@ std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDe root[ESPHOME_F("target_temperature")] = target; } - root[ESPHOME_F("min_temperature")] = traits.get_min_temperature(); - root[ESPHOME_F("max_temperature")] = traits.get_max_temperature(); - root[ESPHOME_F("step")] = traits.get_target_temperature_step(); - if (traits.get_supports_away_mode()) { root[ESPHOME_F("away")] = obj->is_away(); } From 9c9365c146064177dbc371d425307f8e2cb728d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:07:06 -0600 Subject: [PATCH 0760/2030] [bluetooth_proxy][esp32_ble_client][esp32_ble_server] Use constexpr for compile-time constants (#14073) --- esphome/components/bluetooth_proxy/bluetooth_proxy.h | 4 ++-- .../components/esp32_ble_client/ble_client_base.cpp | 12 ++++++------ .../components/esp32_ble_server/ble_characteristic.h | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index ab9aee2d81..62a035e79f 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -35,8 +35,8 @@ using namespace esp32_ble_client; // Version 3: New connection API // Version 4: Pairing support // Version 5: Cache clear support -static const uint32_t LEGACY_ACTIVE_CONNECTIONS_VERSION = 5; -static const uint32_t LEGACY_PASSIVE_ONLY_VERSION = 1; +static constexpr uint32_t LEGACY_ACTIVE_CONNECTIONS_VERSION = 5; +static constexpr uint32_t LEGACY_PASSIVE_ONLY_VERSION = 1; enum BluetoothProxyFeature : uint32_t { FEATURE_PASSIVE_SCAN = 1 << 0, diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index c464c89390..3f0eeeab4a 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -16,17 +16,17 @@ static const char *const TAG = "esp32_ble_client"; // Intermediate connection parameters for standard operation // ESP-IDF defaults (12.5-15ms) are too slow for stable connections through WiFi-based BLE proxies, // causing disconnections. These medium parameters balance responsiveness with bandwidth usage. -static const uint16_t MEDIUM_MIN_CONN_INTERVAL = 0x07; // 7 * 1.25ms = 8.75ms -static const uint16_t MEDIUM_MAX_CONN_INTERVAL = 0x09; // 9 * 1.25ms = 11.25ms +static constexpr uint16_t MEDIUM_MIN_CONN_INTERVAL = 0x07; // 7 * 1.25ms = 8.75ms +static constexpr uint16_t MEDIUM_MAX_CONN_INTERVAL = 0x09; // 9 * 1.25ms = 11.25ms // The timeout value was increased from 6s to 8s to address stability issues observed // in certain BLE devices when operating through WiFi-based BLE proxies. The longer // timeout reduces the likelihood of disconnections during periods of high latency. -static const uint16_t MEDIUM_CONN_TIMEOUT = 800; // 800 * 10ms = 8s +static constexpr uint16_t MEDIUM_CONN_TIMEOUT = 800; // 800 * 10ms = 8s // Fastest connection parameters for devices with short discovery timeouts -static const uint16_t FAST_MIN_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms (BLE minimum) -static const uint16_t FAST_MAX_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms -static const uint16_t FAST_CONN_TIMEOUT = 1000; // 1000 * 10ms = 10s +static constexpr uint16_t FAST_MIN_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms (BLE minimum) +static constexpr uint16_t FAST_MAX_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms +static constexpr uint16_t FAST_CONN_TIMEOUT = 1000; // 1000 * 10ms = 10s static const esp_bt_uuid_t NOTIFY_DESC_UUID = { .len = ESP_UUID_LEN_16, .uuid = diff --git a/esphome/components/esp32_ble_server/ble_characteristic.h b/esphome/components/esp32_ble_server/ble_characteristic.h index c2cdb1660c..72897d1dfb 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.h +++ b/esphome/components/esp32_ble_server/ble_characteristic.h @@ -57,12 +57,12 @@ class BLECharacteristic { ESPBTUUID get_uuid() { return this->uuid_; } std::vector<uint8_t> &get_value() { return this->value_; } - static const uint32_t PROPERTY_READ = 1 << 0; - static const uint32_t PROPERTY_WRITE = 1 << 1; - static const uint32_t PROPERTY_NOTIFY = 1 << 2; - static const uint32_t PROPERTY_BROADCAST = 1 << 3; - static const uint32_t PROPERTY_INDICATE = 1 << 4; - static const uint32_t PROPERTY_WRITE_NR = 1 << 5; + static constexpr uint32_t PROPERTY_READ = 1 << 0; + static constexpr uint32_t PROPERTY_WRITE = 1 << 1; + static constexpr uint32_t PROPERTY_NOTIFY = 1 << 2; + static constexpr uint32_t PROPERTY_BROADCAST = 1 << 3; + static constexpr uint32_t PROPERTY_INDICATE = 1 << 4; + static constexpr uint32_t PROPERTY_WRITE_NR = 1 << 5; bool is_created(); bool is_failed(); From 76c151c6e6948fbe2f5c62356ef299797cc83480 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:07:38 -0600 Subject: [PATCH 0761/2030] [api] Use constexpr for compile-time constant (#14072) --- esphome/components/api/api_frame_helper_noise.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 1ae848dead..492988128a 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -474,7 +474,7 @@ APIError APINoiseFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, s // buf_start[1], buf_start[2] to be set after encryption // Write message header (to be encrypted) - const uint8_t msg_offset = 3; + constexpr uint8_t msg_offset = 3; buf_start[msg_offset] = static_cast<uint8_t>(msg.message_type >> 8); // type high byte buf_start[msg_offset + 1] = static_cast<uint8_t>(msg.message_type); // type low byte buf_start[msg_offset + 2] = static_cast<uint8_t>(msg.payload_size >> 8); // data_len high byte From ee7d63f73a3587cc86c6d6fe71e5fcd3df4e31b5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:09:49 -0600 Subject: [PATCH 0762/2030] [packet_transport] Use constexpr for compile-time constants (#14074) --- esphome/components/packet_transport/packet_transport.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index 365a5f2ec7..7b7a852398 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -58,9 +58,9 @@ union FuData { float f32; }; -static const uint16_t MAGIC_NUMBER = 0x4553; -static const uint16_t MAGIC_PING = 0x5048; -static const uint32_t PREF_HASH = 0x45535043; +static constexpr uint16_t MAGIC_NUMBER = 0x4553; +static constexpr uint16_t MAGIC_PING = 0x5048; +static constexpr uint32_t PREF_HASH = 0x45535043; enum DataKey { ZERO_FILL_KEY, DATA_KEY, From 20239d1bb304ceea6f7056c0466071178ad8af50 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:16:09 -0600 Subject: [PATCH 0763/2030] [remote_base] Use constexpr for compile-time constants (#14076) --- .../remote_base/abbwelcome_protocol.cpp | 8 +++---- .../remote_base/abbwelcome_protocol.h | 4 ++-- .../components/remote_base/aeha_protocol.cpp | 14 +++++------ .../remote_base/byronsx_protocol.cpp | 10 ++++---- .../remote_base/canalsat_protocol.cpp | 8 +++---- .../components/remote_base/dish_protocol.cpp | 10 ++++---- .../components/remote_base/dooya_protocol.cpp | 12 +++++----- .../remote_base/drayton_protocol.cpp | 22 ++++++++--------- .../components/remote_base/jvc_protocol.cpp | 12 +++++----- .../remote_base/keeloq_protocol.cpp | 22 ++++++++--------- .../components/remote_base/lg_protocol.cpp | 10 ++++---- .../remote_base/magiquest_protocol.cpp | 10 ++++---- .../components/remote_base/midea_protocol.h | 2 +- .../components/remote_base/nec_protocol.cpp | 10 ++++---- .../components/remote_base/nexa_protocol.cpp | 22 ++++++++--------- .../remote_base/panasonic_protocol.cpp | 10 ++++---- .../remote_base/pioneer_protocol.cpp | 12 +++++----- .../remote_base/pronto_protocol.cpp | 24 +++++++++---------- .../components/remote_base/rc5_protocol.cpp | 4 ++-- .../components/remote_base/rc6_protocol.cpp | 10 ++++---- .../remote_base/roomba_protocol.cpp | 10 ++++---- .../remote_base/samsung36_protocol.cpp | 20 ++++++++-------- .../remote_base/samsung_protocol.cpp | 14 +++++------ .../components/remote_base/sony_protocol.cpp | 10 ++++---- .../remote_base/symphony_protocol.cpp | 14 +++++------ .../remote_base/toshiba_ac_protocol.cpp | 16 ++++++------- .../components/remote_base/toto_protocol.cpp | 12 +++++----- 27 files changed, 166 insertions(+), 166 deletions(-) diff --git a/esphome/components/remote_base/abbwelcome_protocol.cpp b/esphome/components/remote_base/abbwelcome_protocol.cpp index 352ae10ed7..a67ca48dbe 100644 --- a/esphome/components/remote_base/abbwelcome_protocol.cpp +++ b/esphome/components/remote_base/abbwelcome_protocol.cpp @@ -6,10 +6,10 @@ namespace remote_base { static const char *const TAG = "remote.abbwelcome"; -static const uint32_t BIT_ONE_SPACE_US = 102; -static const uint32_t BIT_ZERO_MARK_US = 32; // 18-44 -static const uint32_t BIT_ZERO_SPACE_US = BIT_ONE_SPACE_US - BIT_ZERO_MARK_US; -static const uint16_t BYTE_SPACE_US = 210; +static constexpr uint32_t BIT_ONE_SPACE_US = 102; +static constexpr uint32_t BIT_ZERO_MARK_US = 32; // 18-44 +static constexpr uint32_t BIT_ZERO_SPACE_US = BIT_ONE_SPACE_US - BIT_ZERO_MARK_US; +static constexpr uint16_t BYTE_SPACE_US = 210; uint8_t ABBWelcomeData::calc_cs_() const { uint8_t checksum = 0; diff --git a/esphome/components/remote_base/abbwelcome_protocol.h b/esphome/components/remote_base/abbwelcome_protocol.h index 1dddedf8ce..66664a89f3 100644 --- a/esphome/components/remote_base/abbwelcome_protocol.h +++ b/esphome/components/remote_base/abbwelcome_protocol.h @@ -11,8 +11,8 @@ namespace esphome { namespace remote_base { -static const uint8_t MAX_DATA_LENGTH = 15; -static const uint8_t DATA_LENGTH_MASK = 0x3f; +static constexpr uint8_t MAX_DATA_LENGTH = 15; +static constexpr uint8_t DATA_LENGTH_MASK = 0x3f; /* Message Format: diff --git a/esphome/components/remote_base/aeha_protocol.cpp b/esphome/components/remote_base/aeha_protocol.cpp index 3b926e7981..f40cff7623 100644 --- a/esphome/components/remote_base/aeha_protocol.cpp +++ b/esphome/components/remote_base/aeha_protocol.cpp @@ -7,13 +7,13 @@ namespace remote_base { static const char *const TAG = "remote.aeha"; -static const uint16_t BITWISE = 425; -static const uint16_t HEADER_HIGH_US = BITWISE * 8; -static const uint16_t HEADER_LOW_US = BITWISE * 4; -static const uint16_t BIT_HIGH_US = BITWISE; -static const uint16_t BIT_ONE_LOW_US = BITWISE * 3; -static const uint16_t BIT_ZERO_LOW_US = BITWISE; -static const uint16_t TRAILER = BITWISE; +static constexpr uint16_t BITWISE = 425; +static constexpr uint16_t HEADER_HIGH_US = BITWISE * 8; +static constexpr uint16_t HEADER_LOW_US = BITWISE * 4; +static constexpr uint16_t BIT_HIGH_US = BITWISE; +static constexpr uint16_t BIT_ONE_LOW_US = BITWISE * 3; +static constexpr uint16_t BIT_ZERO_LOW_US = BITWISE; +static constexpr uint16_t TRAILER = BITWISE; void AEHAProtocol::encode(RemoteTransmitData *dst, const AEHAData &data) { dst->reserve(2 + 32 + (data.data.size() * 2) + 1); diff --git a/esphome/components/remote_base/byronsx_protocol.cpp b/esphome/components/remote_base/byronsx_protocol.cpp index 6bfa4b7ff9..f243b5bdfd 100644 --- a/esphome/components/remote_base/byronsx_protocol.cpp +++ b/esphome/components/remote_base/byronsx_protocol.cpp @@ -8,11 +8,11 @@ namespace remote_base { static const char *const TAG = "remote.byronsx"; -static const uint32_t BIT_TIME_US = 333; -static const uint8_t NBITS_ADDRESS = 8; -static const uint8_t NBITS_COMMAND = 4; -static const uint8_t NBITS_START_BIT = 1; -static const uint8_t NBITS_DATA = NBITS_ADDRESS + NBITS_COMMAND /*+ NBITS_COMMAND*/; +static constexpr uint32_t BIT_TIME_US = 333; +static constexpr uint8_t NBITS_ADDRESS = 8; +static constexpr uint8_t NBITS_COMMAND = 4; +static constexpr uint8_t NBITS_START_BIT = 1; +static constexpr uint8_t NBITS_DATA = NBITS_ADDRESS + NBITS_COMMAND /*+ NBITS_COMMAND*/; /* ByronSX Protocol diff --git a/esphome/components/remote_base/canalsat_protocol.cpp b/esphome/components/remote_base/canalsat_protocol.cpp index bee3d57fd8..1468b66939 100644 --- a/esphome/components/remote_base/canalsat_protocol.cpp +++ b/esphome/components/remote_base/canalsat_protocol.cpp @@ -7,10 +7,10 @@ namespace remote_base { static const char *const CANALSAT_TAG = "remote.canalsat"; static const char *const CANALSATLD_TAG = "remote.canalsatld"; -static const uint16_t CANALSAT_FREQ = 55500; -static const uint16_t CANALSATLD_FREQ = 56000; -static const uint16_t CANALSAT_UNIT = 250; -static const uint16_t CANALSATLD_UNIT = 320; +static constexpr uint16_t CANALSAT_FREQ = 55500; +static constexpr uint16_t CANALSATLD_FREQ = 56000; +static constexpr uint16_t CANALSAT_UNIT = 250; +static constexpr uint16_t CANALSATLD_UNIT = 320; CanalSatProtocol::CanalSatProtocol() { this->frequency_ = CANALSAT_FREQ; diff --git a/esphome/components/remote_base/dish_protocol.cpp b/esphome/components/remote_base/dish_protocol.cpp index 754b6c3b12..69226101bf 100644 --- a/esphome/components/remote_base/dish_protocol.cpp +++ b/esphome/components/remote_base/dish_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.dish"; -static const uint32_t HEADER_HIGH_US = 400; -static const uint32_t HEADER_LOW_US = 6100; -static const uint32_t BIT_HIGH_US = 400; -static const uint32_t BIT_ONE_LOW_US = 1700; -static const uint32_t BIT_ZERO_LOW_US = 2800; +static constexpr uint32_t HEADER_HIGH_US = 400; +static constexpr uint32_t HEADER_LOW_US = 6100; +static constexpr uint32_t BIT_HIGH_US = 400; +static constexpr uint32_t BIT_ONE_LOW_US = 1700; +static constexpr uint32_t BIT_ZERO_LOW_US = 2800; void DishProtocol::encode(RemoteTransmitData *dst, const DishData &data) { dst->reserve(138); diff --git a/esphome/components/remote_base/dooya_protocol.cpp b/esphome/components/remote_base/dooya_protocol.cpp index 04c5fef8f3..84bdbf3e08 100644 --- a/esphome/components/remote_base/dooya_protocol.cpp +++ b/esphome/components/remote_base/dooya_protocol.cpp @@ -6,12 +6,12 @@ namespace remote_base { static const char *const TAG = "remote.dooya"; -static const uint32_t HEADER_HIGH_US = 5000; -static const uint32_t HEADER_LOW_US = 1500; -static const uint32_t BIT_ZERO_HIGH_US = 350; -static const uint32_t BIT_ZERO_LOW_US = 750; -static const uint32_t BIT_ONE_HIGH_US = 750; -static const uint32_t BIT_ONE_LOW_US = 350; +static constexpr uint32_t HEADER_HIGH_US = 5000; +static constexpr uint32_t HEADER_LOW_US = 1500; +static constexpr uint32_t BIT_ZERO_HIGH_US = 350; +static constexpr uint32_t BIT_ZERO_LOW_US = 750; +static constexpr uint32_t BIT_ONE_HIGH_US = 750; +static constexpr uint32_t BIT_ONE_LOW_US = 350; void DooyaProtocol::encode(RemoteTransmitData *dst, const DooyaData &data) { dst->set_carrier_frequency(0); diff --git a/esphome/components/remote_base/drayton_protocol.cpp b/esphome/components/remote_base/drayton_protocol.cpp index da2e985af0..946bd9cacb 100644 --- a/esphome/components/remote_base/drayton_protocol.cpp +++ b/esphome/components/remote_base/drayton_protocol.cpp @@ -8,18 +8,18 @@ namespace remote_base { static const char *const TAG = "remote.drayton"; -static const uint32_t BIT_TIME_US = 500; -static const uint8_t CARRIER_KHZ = 2; -static const uint8_t NBITS_PREAMBLE = 12; -static const uint8_t NBITS_SYNC = 4; -static const uint8_t NBITS_ADDRESS = 16; -static const uint8_t NBITS_CHANNEL = 5; -static const uint8_t NBITS_COMMAND = 7; -static const uint8_t NDATABITS = NBITS_ADDRESS + NBITS_CHANNEL + NBITS_COMMAND; -static const uint8_t MIN_RX_SRC = (NDATABITS + NBITS_SYNC / 2); +static constexpr uint32_t BIT_TIME_US = 500; +static constexpr uint8_t CARRIER_KHZ = 2; +static constexpr uint8_t NBITS_PREAMBLE = 12; +static constexpr uint8_t NBITS_SYNC = 4; +static constexpr uint8_t NBITS_ADDRESS = 16; +static constexpr uint8_t NBITS_CHANNEL = 5; +static constexpr uint8_t NBITS_COMMAND = 7; +static constexpr uint8_t NDATABITS = NBITS_ADDRESS + NBITS_CHANNEL + NBITS_COMMAND; +static constexpr uint8_t MIN_RX_SRC = (NDATABITS + NBITS_SYNC / 2); -static const uint8_t CMD_ON = 0x41; -static const uint8_t CMD_OFF = 0x02; +static constexpr uint8_t CMD_ON = 0x41; +static constexpr uint8_t CMD_OFF = 0x02; /* Drayton Protocol diff --git a/esphome/components/remote_base/jvc_protocol.cpp b/esphome/components/remote_base/jvc_protocol.cpp index ca423b61e6..c33cae7a48 100644 --- a/esphome/components/remote_base/jvc_protocol.cpp +++ b/esphome/components/remote_base/jvc_protocol.cpp @@ -6,12 +6,12 @@ namespace remote_base { static const char *const TAG = "remote.jvc"; -static const uint8_t NBITS = 16; -static const uint32_t HEADER_HIGH_US = 8400; -static const uint32_t HEADER_LOW_US = 4200; -static const uint32_t BIT_ONE_LOW_US = 1725; -static const uint32_t BIT_ZERO_LOW_US = 525; -static const uint32_t BIT_HIGH_US = 525; +static constexpr uint8_t NBITS = 16; +static constexpr uint32_t HEADER_HIGH_US = 8400; +static constexpr uint32_t HEADER_LOW_US = 4200; +static constexpr uint32_t BIT_ONE_LOW_US = 1725; +static constexpr uint32_t BIT_ZERO_LOW_US = 525; +static constexpr uint32_t BIT_HIGH_US = 525; void JVCProtocol::encode(RemoteTransmitData *dst, const JVCData &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/keeloq_protocol.cpp b/esphome/components/remote_base/keeloq_protocol.cpp index 72540c37f1..e95c79ef25 100644 --- a/esphome/components/remote_base/keeloq_protocol.cpp +++ b/esphome/components/remote_base/keeloq_protocol.cpp @@ -8,18 +8,18 @@ namespace remote_base { static const char *const TAG = "remote.keeloq"; -static const uint32_t BIT_TIME_US = 380; -static const uint8_t NBITS_PREAMBLE = 12; -static const uint8_t NBITS_REPEAT = 1; -static const uint8_t NBITS_VLOW = 1; -static const uint8_t NBITS_SERIAL = 28; -static const uint8_t NBITS_BUTTONS = 4; -static const uint8_t NBITS_DISC = 12; -static const uint8_t NBITS_SYNC_CNT = 16; +static constexpr uint32_t BIT_TIME_US = 380; +static constexpr uint8_t NBITS_PREAMBLE = 12; +static constexpr uint8_t NBITS_REPEAT = 1; +static constexpr uint8_t NBITS_VLOW = 1; +static constexpr uint8_t NBITS_SERIAL = 28; +static constexpr uint8_t NBITS_BUTTONS = 4; +static constexpr uint8_t NBITS_DISC = 12; +static constexpr uint8_t NBITS_SYNC_CNT = 16; -static const uint8_t NBITS_FIXED_DATA = NBITS_REPEAT + NBITS_VLOW + NBITS_BUTTONS + NBITS_SERIAL; -static const uint8_t NBITS_ENCRYPTED_DATA = NBITS_BUTTONS + NBITS_DISC + NBITS_SYNC_CNT; -static const uint8_t NBITS_DATA = NBITS_FIXED_DATA + NBITS_ENCRYPTED_DATA; +static constexpr uint8_t NBITS_FIXED_DATA = NBITS_REPEAT + NBITS_VLOW + NBITS_BUTTONS + NBITS_SERIAL; +static constexpr uint8_t NBITS_ENCRYPTED_DATA = NBITS_BUTTONS + NBITS_DISC + NBITS_SYNC_CNT; +static constexpr uint8_t NBITS_DATA = NBITS_FIXED_DATA + NBITS_ENCRYPTED_DATA; /* KeeLoq Protocol diff --git a/esphome/components/remote_base/lg_protocol.cpp b/esphome/components/remote_base/lg_protocol.cpp index d25c59d2b1..4c54ff00bd 100644 --- a/esphome/components/remote_base/lg_protocol.cpp +++ b/esphome/components/remote_base/lg_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.lg"; -static const uint32_t HEADER_HIGH_US = 8000; -static const uint32_t HEADER_LOW_US = 4000; -static const uint32_t BIT_HIGH_US = 600; -static const uint32_t BIT_ONE_LOW_US = 1600; -static const uint32_t BIT_ZERO_LOW_US = 550; +static constexpr uint32_t HEADER_HIGH_US = 8000; +static constexpr uint32_t HEADER_LOW_US = 4000; +static constexpr uint32_t BIT_HIGH_US = 600; +static constexpr uint32_t BIT_ONE_LOW_US = 1600; +static constexpr uint32_t BIT_ZERO_LOW_US = 550; void LGProtocol::encode(RemoteTransmitData *dst, const LGData &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/magiquest_protocol.cpp b/esphome/components/remote_base/magiquest_protocol.cpp index 1cec58a55f..f25a982fdc 100644 --- a/esphome/components/remote_base/magiquest_protocol.cpp +++ b/esphome/components/remote_base/magiquest_protocol.cpp @@ -10,11 +10,11 @@ namespace remote_base { static const char *const TAG = "remote.magiquest"; -static const uint32_t MAGIQUEST_UNIT = 288; // us -static const uint32_t MAGIQUEST_ONE_MARK = 2 * MAGIQUEST_UNIT; -static const uint32_t MAGIQUEST_ONE_SPACE = 2 * MAGIQUEST_UNIT; -static const uint32_t MAGIQUEST_ZERO_MARK = MAGIQUEST_UNIT; -static const uint32_t MAGIQUEST_ZERO_SPACE = 3 * MAGIQUEST_UNIT; +static constexpr uint32_t MAGIQUEST_UNIT = 288; // us +static constexpr uint32_t MAGIQUEST_ONE_MARK = 2 * MAGIQUEST_UNIT; +static constexpr uint32_t MAGIQUEST_ONE_SPACE = 2 * MAGIQUEST_UNIT; +static constexpr uint32_t MAGIQUEST_ZERO_MARK = MAGIQUEST_UNIT; +static constexpr uint32_t MAGIQUEST_ZERO_SPACE = 3 * MAGIQUEST_UNIT; void MagiQuestProtocol::encode(RemoteTransmitData *dst, const MagiQuestData &data) { dst->reserve(101); // 2 start bits, 48 data bits, 1 stop bit diff --git a/esphome/components/remote_base/midea_protocol.h b/esphome/components/remote_base/midea_protocol.h index ddefff867a..334e8a7cb3 100644 --- a/esphome/components/remote_base/midea_protocol.h +++ b/esphome/components/remote_base/midea_protocol.h @@ -62,7 +62,7 @@ class MideaData { this->data_[idx] |= (value << shift); } void set_mask_(uint8_t idx, bool state, uint8_t mask = 255) { this->set_value_(idx, state ? mask : 0, mask); } - static const uint8_t OFFSET_CS = 5; + static constexpr uint8_t OFFSET_CS = 5; // 48-bits data std::array<uint8_t, 6> data_; // Calculate checksum diff --git a/esphome/components/remote_base/nec_protocol.cpp b/esphome/components/remote_base/nec_protocol.cpp index 6ea9a8583c..062f81b4d6 100644 --- a/esphome/components/remote_base/nec_protocol.cpp +++ b/esphome/components/remote_base/nec_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.nec"; -static const uint32_t HEADER_HIGH_US = 9000; -static const uint32_t HEADER_LOW_US = 4500; -static const uint32_t BIT_HIGH_US = 560; -static const uint32_t BIT_ONE_LOW_US = 1690; -static const uint32_t BIT_ZERO_LOW_US = 560; +static constexpr uint32_t HEADER_HIGH_US = 9000; +static constexpr uint32_t HEADER_LOW_US = 4500; +static constexpr uint32_t BIT_HIGH_US = 560; +static constexpr uint32_t BIT_ONE_LOW_US = 1690; +static constexpr uint32_t BIT_ZERO_LOW_US = 560; void NECProtocol::encode(RemoteTransmitData *dst, const NECData &data) { ESP_LOGD(TAG, "Sending NEC: address=0x%04X, command=0x%04X command_repeats=%d", data.address, data.command, diff --git a/esphome/components/remote_base/nexa_protocol.cpp b/esphome/components/remote_base/nexa_protocol.cpp index 862165714e..28b415d4d6 100644 --- a/esphome/components/remote_base/nexa_protocol.cpp +++ b/esphome/components/remote_base/nexa_protocol.cpp @@ -6,18 +6,18 @@ namespace remote_base { static const char *const TAG = "remote.nexa"; -static const uint8_t NBITS = 32; -static const uint32_t HEADER_HIGH_US = 319; -static const uint32_t HEADER_LOW_US = 2610; -static const uint32_t BIT_HIGH_US = 319; -static const uint32_t BIT_ONE_LOW_US = 1000; -static const uint32_t BIT_ZERO_LOW_US = 140; +static constexpr uint8_t NBITS = 32; +static constexpr uint32_t HEADER_HIGH_US = 319; +static constexpr uint32_t HEADER_LOW_US = 2610; +static constexpr uint32_t BIT_HIGH_US = 319; +static constexpr uint32_t BIT_ONE_LOW_US = 1000; +static constexpr uint32_t BIT_ZERO_LOW_US = 140; -static const uint32_t TX_HEADER_HIGH_US = 250; -static const uint32_t TX_HEADER_LOW_US = TX_HEADER_HIGH_US * 10; -static const uint32_t TX_BIT_HIGH_US = 250; -static const uint32_t TX_BIT_ONE_LOW_US = TX_BIT_HIGH_US * 5; -static const uint32_t TX_BIT_ZERO_LOW_US = TX_BIT_HIGH_US * 1; +static constexpr uint32_t TX_HEADER_HIGH_US = 250; +static constexpr uint32_t TX_HEADER_LOW_US = TX_HEADER_HIGH_US * 10; +static constexpr uint32_t TX_BIT_HIGH_US = 250; +static constexpr uint32_t TX_BIT_ONE_LOW_US = TX_BIT_HIGH_US * 5; +static constexpr uint32_t TX_BIT_ZERO_LOW_US = TX_BIT_HIGH_US * 1; void NexaProtocol::one(RemoteTransmitData *dst) const { // '1' => '10' diff --git a/esphome/components/remote_base/panasonic_protocol.cpp b/esphome/components/remote_base/panasonic_protocol.cpp index d6cf1a160d..e0acc42692 100644 --- a/esphome/components/remote_base/panasonic_protocol.cpp +++ b/esphome/components/remote_base/panasonic_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.panasonic"; -static const uint32_t HEADER_HIGH_US = 3502; -static const uint32_t HEADER_LOW_US = 1750; -static const uint32_t BIT_HIGH_US = 502; -static const uint32_t BIT_ZERO_LOW_US = 400; -static const uint32_t BIT_ONE_LOW_US = 1244; +static constexpr uint32_t HEADER_HIGH_US = 3502; +static constexpr uint32_t HEADER_LOW_US = 1750; +static constexpr uint32_t BIT_HIGH_US = 502; +static constexpr uint32_t BIT_ZERO_LOW_US = 400; +static constexpr uint32_t BIT_ONE_LOW_US = 1244; void PanasonicProtocol::encode(RemoteTransmitData *dst, const PanasonicData &data) { dst->reserve(100); diff --git a/esphome/components/remote_base/pioneer_protocol.cpp b/esphome/components/remote_base/pioneer_protocol.cpp index 043565282d..f350ef66ae 100644 --- a/esphome/components/remote_base/pioneer_protocol.cpp +++ b/esphome/components/remote_base/pioneer_protocol.cpp @@ -6,12 +6,12 @@ namespace remote_base { static const char *const TAG = "remote.pioneer"; -static const uint32_t HEADER_HIGH_US = 9000; -static const uint32_t HEADER_LOW_US = 4500; -static const uint32_t BIT_HIGH_US = 560; -static const uint32_t BIT_ONE_LOW_US = 1690; -static const uint32_t BIT_ZERO_LOW_US = 560; -static const uint32_t TRAILER_SPACE_US = 25500; +static constexpr uint32_t HEADER_HIGH_US = 9000; +static constexpr uint32_t HEADER_LOW_US = 4500; +static constexpr uint32_t BIT_HIGH_US = 560; +static constexpr uint32_t BIT_ONE_LOW_US = 1690; +static constexpr uint32_t BIT_ZERO_LOW_US = 560; +static constexpr uint32_t TRAILER_SPACE_US = 25500; void PioneerProtocol::encode(RemoteTransmitData *dst, const PioneerData &data) { uint32_t address1 = ((data.rc_code_1 & 0xff00) | (~(data.rc_code_1 >> 8) & 0xff)); diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index 401a0976b2..cff3145199 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -59,18 +59,18 @@ bool ProntoData::operator==(const ProntoData &rhs) const { } // DO NOT EXPORT from this file -static const uint16_t MICROSECONDS_T_MAX = 0xFFFFU; -static const uint16_t LEARNED_TOKEN = 0x0000U; -static const uint16_t LEARNED_NON_MODULATED_TOKEN = 0x0100U; -static const uint16_t BITS_IN_HEXADECIMAL = 4U; -static const uint16_t DIGITS_IN_PRONTO_NUMBER = 4U; -static const uint16_t NUMBERS_IN_PREAMBLE = 4U; -static const uint16_t HEX_MASK = 0xFU; -static const uint32_t REFERENCE_FREQUENCY = 4145146UL; -static const uint16_t FALLBACK_FREQUENCY = 64767U; // To use with frequency = 0; -static const uint32_t MICROSECONDS_IN_SECONDS = 1000000UL; -static const uint16_t PRONTO_DEFAULT_GAP = 45000; -static const uint16_t MARK_EXCESS_MICROS = 20; +static constexpr uint16_t MICROSECONDS_T_MAX = 0xFFFFU; +static constexpr uint16_t LEARNED_TOKEN = 0x0000U; +static constexpr uint16_t LEARNED_NON_MODULATED_TOKEN = 0x0100U; +static constexpr uint16_t BITS_IN_HEXADECIMAL = 4U; +static constexpr uint16_t DIGITS_IN_PRONTO_NUMBER = 4U; +static constexpr uint16_t NUMBERS_IN_PREAMBLE = 4U; +static constexpr uint16_t HEX_MASK = 0xFU; +static constexpr uint32_t REFERENCE_FREQUENCY = 4145146UL; +static constexpr uint16_t FALLBACK_FREQUENCY = 64767U; // To use with frequency = 0; +static constexpr uint32_t MICROSECONDS_IN_SECONDS = 1000000UL; +static constexpr uint16_t PRONTO_DEFAULT_GAP = 45000; +static constexpr uint16_t MARK_EXCESS_MICROS = 20; static constexpr size_t PRONTO_LOG_CHUNK_SIZE = 230; static uint16_t to_frequency_k_hz(uint16_t code) { diff --git a/esphome/components/remote_base/rc5_protocol.cpp b/esphome/components/remote_base/rc5_protocol.cpp index 08f2f2eaa3..bb6d382d80 100644 --- a/esphome/components/remote_base/rc5_protocol.cpp +++ b/esphome/components/remote_base/rc5_protocol.cpp @@ -6,8 +6,8 @@ namespace remote_base { static const char *const TAG = "remote.rc5"; -static const uint32_t BIT_TIME_US = 889; -static const uint8_t NBITS = 14; +static constexpr uint32_t BIT_TIME_US = 889; +static constexpr uint8_t NBITS = 14; void RC5Protocol::encode(RemoteTransmitData *dst, const RC5Data &data) { static bool toggle = false; diff --git a/esphome/components/remote_base/rc6_protocol.cpp b/esphome/components/remote_base/rc6_protocol.cpp index fcb4da11a4..b442bb4c27 100644 --- a/esphome/components/remote_base/rc6_protocol.cpp +++ b/esphome/components/remote_base/rc6_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const RC6_TAG = "remote.rc6"; -static const uint16_t RC6_FREQ = 36000; -static const uint16_t RC6_UNIT = 444; -static const uint16_t RC6_HEADER_MARK = (6 * RC6_UNIT); -static const uint16_t RC6_HEADER_SPACE = (2 * RC6_UNIT); -static const uint16_t RC6_MODE_MASK = 0x07; +static constexpr uint16_t RC6_FREQ = 36000; +static constexpr uint16_t RC6_UNIT = 444; +static constexpr uint16_t RC6_HEADER_MARK = (6 * RC6_UNIT); +static constexpr uint16_t RC6_HEADER_SPACE = (2 * RC6_UNIT); +static constexpr uint16_t RC6_MODE_MASK = 0x07; void RC6Protocol::encode(RemoteTransmitData *dst, const RC6Data &data) { dst->reserve(44); diff --git a/esphome/components/remote_base/roomba_protocol.cpp b/esphome/components/remote_base/roomba_protocol.cpp index 2d2dde114a..6b7d216374 100644 --- a/esphome/components/remote_base/roomba_protocol.cpp +++ b/esphome/components/remote_base/roomba_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.roomba"; -static const uint8_t NBITS = 8; -static const uint32_t BIT_ONE_HIGH_US = 3000; -static const uint32_t BIT_ONE_LOW_US = 1000; -static const uint32_t BIT_ZERO_HIGH_US = BIT_ONE_LOW_US; -static const uint32_t BIT_ZERO_LOW_US = BIT_ONE_HIGH_US; +static constexpr uint8_t NBITS = 8; +static constexpr uint32_t BIT_ONE_HIGH_US = 3000; +static constexpr uint32_t BIT_ONE_LOW_US = 1000; +static constexpr uint32_t BIT_ZERO_HIGH_US = BIT_ONE_LOW_US; +static constexpr uint32_t BIT_ZERO_LOW_US = BIT_ONE_HIGH_US; void RoombaProtocol::encode(RemoteTransmitData *dst, const RoombaData &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/samsung36_protocol.cpp b/esphome/components/remote_base/samsung36_protocol.cpp index bd3eee5849..10e8bd2d01 100644 --- a/esphome/components/remote_base/samsung36_protocol.cpp +++ b/esphome/components/remote_base/samsung36_protocol.cpp @@ -6,17 +6,17 @@ namespace remote_base { static const char *const TAG = "remote.samsung36"; -static const uint8_t NBITS = 78; +static constexpr uint8_t NBITS = 78; -static const uint32_t HEADER_HIGH_US = 4500; -static const uint32_t HEADER_LOW_US = 4500; -static const uint32_t BIT_HIGH_US = 500; -static const uint32_t BIT_ONE_LOW_US = 1500; -static const uint32_t BIT_ZERO_LOW_US = 500; -static const uint32_t MIDDLE_HIGH_US = 500; -static const uint32_t MIDDLE_LOW_US = 4500; -static const uint32_t FOOTER_HIGH_US = 500; -static const uint32_t FOOTER_LOW_US = 59000; +static constexpr uint32_t HEADER_HIGH_US = 4500; +static constexpr uint32_t HEADER_LOW_US = 4500; +static constexpr uint32_t BIT_HIGH_US = 500; +static constexpr uint32_t BIT_ONE_LOW_US = 1500; +static constexpr uint32_t BIT_ZERO_LOW_US = 500; +static constexpr uint32_t MIDDLE_HIGH_US = 500; +static constexpr uint32_t MIDDLE_LOW_US = 4500; +static constexpr uint32_t FOOTER_HIGH_US = 500; +static constexpr uint32_t FOOTER_LOW_US = 59000; void Samsung36Protocol::encode(RemoteTransmitData *dst, const Samsung36Data &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/samsung_protocol.cpp b/esphome/components/remote_base/samsung_protocol.cpp index 2d6d5531e5..2a48cbb918 100644 --- a/esphome/components/remote_base/samsung_protocol.cpp +++ b/esphome/components/remote_base/samsung_protocol.cpp @@ -7,13 +7,13 @@ namespace remote_base { static const char *const TAG = "remote.samsung"; -static const uint32_t HEADER_HIGH_US = 4500; -static const uint32_t HEADER_LOW_US = 4500; -static const uint32_t BIT_HIGH_US = 560; -static const uint32_t BIT_ONE_LOW_US = 1690; -static const uint32_t BIT_ZERO_LOW_US = 560; -static const uint32_t FOOTER_HIGH_US = 560; -static const uint32_t FOOTER_LOW_US = 560; +static constexpr uint32_t HEADER_HIGH_US = 4500; +static constexpr uint32_t HEADER_LOW_US = 4500; +static constexpr uint32_t BIT_HIGH_US = 560; +static constexpr uint32_t BIT_ONE_LOW_US = 1690; +static constexpr uint32_t BIT_ZERO_LOW_US = 560; +static constexpr uint32_t FOOTER_HIGH_US = 560; +static constexpr uint32_t FOOTER_LOW_US = 560; void SamsungProtocol::encode(RemoteTransmitData *dst, const SamsungData &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/sony_protocol.cpp b/esphome/components/remote_base/sony_protocol.cpp index 69f2b49c42..504b346925 100644 --- a/esphome/components/remote_base/sony_protocol.cpp +++ b/esphome/components/remote_base/sony_protocol.cpp @@ -6,11 +6,11 @@ namespace remote_base { static const char *const TAG = "remote.sony"; -static const uint32_t HEADER_HIGH_US = 2400; -static const uint32_t HEADER_LOW_US = 600; -static const uint32_t BIT_ONE_HIGH_US = 1200; -static const uint32_t BIT_ZERO_HIGH_US = 600; -static const uint32_t BIT_LOW_US = 600; +static constexpr uint32_t HEADER_HIGH_US = 2400; +static constexpr uint32_t HEADER_LOW_US = 600; +static constexpr uint32_t BIT_ONE_HIGH_US = 1200; +static constexpr uint32_t BIT_ZERO_HIGH_US = 600; +static constexpr uint32_t BIT_LOW_US = 600; void SonyProtocol::encode(RemoteTransmitData *dst, const SonyData &data) { dst->set_carrier_frequency(40000); diff --git a/esphome/components/remote_base/symphony_protocol.cpp b/esphome/components/remote_base/symphony_protocol.cpp index 34b5dba07f..f30a980d91 100644 --- a/esphome/components/remote_base/symphony_protocol.cpp +++ b/esphome/components/remote_base/symphony_protocol.cpp @@ -13,16 +13,16 @@ static const char *const TAG = "remote.symphony"; // footer-gap handling used there. // Symphony protocol timing specifications (tuned to handset captures) -static const uint32_t BIT_ZERO_HIGH_US = 460; // short -static const uint32_t BIT_ZERO_LOW_US = 1260; // long -static const uint32_t BIT_ONE_HIGH_US = 1260; // long -static const uint32_t BIT_ONE_LOW_US = 460; // short -static const uint32_t CARRIER_FREQUENCY = 38000; +static constexpr uint32_t BIT_ZERO_HIGH_US = 460; // short +static constexpr uint32_t BIT_ZERO_LOW_US = 1260; // long +static constexpr uint32_t BIT_ONE_HIGH_US = 1260; // long +static constexpr uint32_t BIT_ONE_LOW_US = 460; // short +static constexpr uint32_t CARRIER_FREQUENCY = 38000; // IRremoteESP8266 reference: kSymphonyFooterGap = 4 * (mark + space) -static const uint32_t FOOTER_GAP_US = 4 * (BIT_ZERO_HIGH_US + BIT_ZERO_LOW_US); +static constexpr uint32_t FOOTER_GAP_US = 4 * (BIT_ZERO_HIGH_US + BIT_ZERO_LOW_US); // Typical inter-frame gap (~34.8 ms observed) -static const uint32_t INTER_FRAME_GAP_US = 34760; +static constexpr uint32_t INTER_FRAME_GAP_US = 34760; void SymphonyProtocol::encode(RemoteTransmitData *dst, const SymphonyData &data) { dst->set_carrier_frequency(CARRIER_FREQUENCY); diff --git a/esphome/components/remote_base/toshiba_ac_protocol.cpp b/esphome/components/remote_base/toshiba_ac_protocol.cpp index 42241eea8c..a20a29b84a 100644 --- a/esphome/components/remote_base/toshiba_ac_protocol.cpp +++ b/esphome/components/remote_base/toshiba_ac_protocol.cpp @@ -7,14 +7,14 @@ namespace remote_base { static const char *const TAG = "remote.toshibaac"; -static const uint32_t HEADER_HIGH_US = 4500; -static const uint32_t HEADER_LOW_US = 4500; -static const uint32_t BIT_HIGH_US = 560; -static const uint32_t BIT_ONE_LOW_US = 1690; -static const uint32_t BIT_ZERO_LOW_US = 560; -static const uint32_t FOOTER_HIGH_US = 560; -static const uint32_t FOOTER_LOW_US = 4500; -static const uint16_t PACKET_SPACE = 5500; +static constexpr uint32_t HEADER_HIGH_US = 4500; +static constexpr uint32_t HEADER_LOW_US = 4500; +static constexpr uint32_t BIT_HIGH_US = 560; +static constexpr uint32_t BIT_ONE_LOW_US = 1690; +static constexpr uint32_t BIT_ZERO_LOW_US = 560; +static constexpr uint32_t FOOTER_HIGH_US = 560; +static constexpr uint32_t FOOTER_LOW_US = 4500; +static constexpr uint16_t PACKET_SPACE = 5500; void ToshibaAcProtocol::encode(RemoteTransmitData *dst, const ToshibaAcData &data) { dst->set_carrier_frequency(38000); diff --git a/esphome/components/remote_base/toto_protocol.cpp b/esphome/components/remote_base/toto_protocol.cpp index ba21263bc8..f08258c4a3 100644 --- a/esphome/components/remote_base/toto_protocol.cpp +++ b/esphome/components/remote_base/toto_protocol.cpp @@ -6,12 +6,12 @@ namespace remote_base { static const char *const TAG = "remote.toto"; -static const uint32_t PREAMBLE_HIGH_US = 6200; -static const uint32_t PREAMBLE_LOW_US = 2800; -static const uint32_t BIT_HIGH_US = 550; -static const uint32_t BIT_ONE_LOW_US = 1700; -static const uint32_t BIT_ZERO_LOW_US = 550; -static const uint32_t TOTO_HEADER = 0x2008; +static constexpr uint32_t PREAMBLE_HIGH_US = 6200; +static constexpr uint32_t PREAMBLE_LOW_US = 2800; +static constexpr uint32_t BIT_HIGH_US = 550; +static constexpr uint32_t BIT_ONE_LOW_US = 1700; +static constexpr uint32_t BIT_ZERO_LOW_US = 550; +static constexpr uint32_t TOTO_HEADER = 0x2008; void TotoProtocol::encode(RemoteTransmitData *dst, const TotoData &data) { uint32_t payload = 0; From dff9780d3af9f6ce41bf9b3db8e6138dc197c08f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:19:48 -0600 Subject: [PATCH 0764/2030] [core] Use constexpr for compile-time constants (#14071) --- esphome/core/application.h | 2 +- esphome/core/helpers.cpp | 6 +++--- esphome/core/scheduler.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index e0299f3db3..5b3e3dfed6 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -111,7 +111,7 @@ namespace esphome { // For reboots, it's more important to shut down quickly than disconnect cleanly // since we're not entering deep sleep. The only consequence of not shutting down // cleanly is a warning in the log. -static const uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for quick reboot +static constexpr uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for quick reboot class Application { public: diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index c2f7f67d9a..09e755ca71 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -846,9 +846,9 @@ void IRAM_ATTR HOT delay_microseconds_safe(uint32_t us) { // avoids CPU locks that could trigger WDT or affect WiFi/BT stability uint32_t start = micros(); - const uint32_t lag = 5000; // microseconds, specifies the maximum time for a CPU busy-loop. - // it must be larger than the worst-case duration of a delay(1) call (hardware tasks) - // 5ms is conservative, it could be reduced when exact BT/WiFi stack delays are known + constexpr uint32_t lag = 5000; // microseconds, specifies the maximum time for a CPU busy-loop. + // it must be larger than the worst-case duration of a delay(1) call (hardware tasks) + // 5ms is conservative, it could be reduced when exact BT/WiFi stack delays are known if (us > lag) { delay((us - lag) / 1000UL); // note: in disabled-interrupt contexts delay() won't actually sleep while (micros() - start < us - lag) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 4194c3aa9e..3294f689e8 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -728,7 +728,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { // Define a safe window around the rollover point (10 seconds) // This covers any reasonable scheduler delays or thread preemption - static const uint32_t ROLLOVER_WINDOW = 10000; // 10 seconds in milliseconds + static constexpr uint32_t ROLLOVER_WINDOW = 10000; // 10 seconds in milliseconds // Check if we're near the rollover boundary (close to std::numeric_limits<uint32_t>::max() or just past 0) bool near_rollover = (last > (std::numeric_limits<uint32_t>::max() - ROLLOVER_WINDOW)) || (now < ROLLOVER_WINDOW); From e7f202186450ad2f865ecbc865ca87b10b243dc3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:32:24 -0600 Subject: [PATCH 0765/2030] [http_request] Replace std::map with std::vector in action template (#14026) --- esphome/components/http_request/__init__.py | 6 +++++- esphome/components/http_request/http_request.h | 11 ++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 5faffccbe4..2d6ecae0bc 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -302,10 +302,14 @@ async def http_request_action_to_code(config, action_id, template_arg, args): lambda_ = await cg.process_lambda(json_, args_, return_type=cg.void) cg.add(var.set_json(lambda_)) else: + cg.add(var.init_json(len(json_))) for key in json_: template_ = await cg.templatable(json_[key], args, cg.std_string) cg.add(var.add_json(key, template_)) - for key, value in config.get(CONF_REQUEST_HEADERS, {}).items(): + request_headers = config.get(CONF_REQUEST_HEADERS, {}) + if request_headers: + cg.add(var.init_request_headers(len(request_headers))) + for key, value in request_headers.items(): template_ = await cg.templatable(value, args, cg.const_char_ptr) cg.add(var.add_request_header(key, template_)) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 458ffe94a8..2b2d05c63f 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -1,7 +1,6 @@ #pragma once #include <list> -#include <map> #include <memory> #include <set> #include <utility> @@ -399,13 +398,15 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { TEMPLATABLE_VALUE(bool, capture_response) #endif + void init_request_headers(size_t count) { this->request_headers_.init(count); } void add_request_header(const char *key, TemplatableValue<const char *, Ts...> value) { - this->request_headers_.insert({key, value}); + this->request_headers_.push_back({key, value}); } void add_collect_header(const char *value) { this->lower_case_collect_headers_.push_back(value); } - void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.insert({key, value}); } + void init_json(size_t count) { this->json_.init(count); } + void add_json(const char *key, TemplatableValue<std::string, Ts...> value) { this->json_.push_back({key, value}); } void set_json(std::function<void(Ts..., JsonObject)> json_func) { this->json_func_ = json_func; } @@ -507,9 +508,9 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { } void encode_json_func_(Ts... x, JsonObject root) { this->json_func_(x..., root); } HttpRequestComponent *parent_; - std::map<const char *, TemplatableValue<const char *, Ts...>> request_headers_{}; + FixedVector<std::pair<const char *, TemplatableValue<const char *, Ts...>>> request_headers_{}; std::vector<std::string> lower_case_collect_headers_{"content-type", "content-length"}; - std::map<const char *, TemplatableValue<std::string, Ts...>> json_{}; + FixedVector<std::pair<const char *, TemplatableValue<std::string, Ts...>>> json_{}; std::function<void(Ts..., JsonObject)> json_func_{nullptr}; #ifdef USE_HTTP_REQUEST_RESPONSE Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> success_trigger_with_response_; From eaf0d03a37a85ead5f33c5b3512d80944f2bfa09 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:32:37 -0600 Subject: [PATCH 0766/2030] [ld2420] Use constexpr for compile-time constants (#14079) --- esphome/components/ld2420/ld2420.cpp | 118 +++++++++++++-------------- esphome/components/ld2420/ld2420.h | 6 +- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 69b69f4a61..cf78a1a460 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -63,73 +63,73 @@ namespace esphome::ld2420 { static const char *const TAG = "ld2420"; // Local const's -static const uint16_t REFRESH_RATE_MS = 1000; +static constexpr uint16_t REFRESH_RATE_MS = 1000; // Command sets -static const uint16_t CMD_DISABLE_CONF = 0x00FE; -static const uint16_t CMD_ENABLE_CONF = 0x00FF; -static const uint16_t CMD_PARM_HIGH_TRESH = 0x0012; -static const uint16_t CMD_PARM_LOW_TRESH = 0x0021; -static const uint16_t CMD_PROTOCOL_VER = 0x0002; -static const uint16_t CMD_READ_ABD_PARAM = 0x0008; -static const uint16_t CMD_READ_REG_ADDR = 0x0020; -static const uint16_t CMD_READ_REGISTER = 0x0002; -static const uint16_t CMD_READ_SERIAL_NUM = 0x0011; -static const uint16_t CMD_READ_SYS_PARAM = 0x0013; -static const uint16_t CMD_READ_VERSION = 0x0000; -static const uint16_t CMD_RESTART = 0x0068; -static const uint16_t CMD_SYSTEM_MODE = 0x0000; -static const uint16_t CMD_SYSTEM_MODE_GR = 0x0003; -static const uint16_t CMD_SYSTEM_MODE_MTT = 0x0001; -static const uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064; -static const uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000; -static const uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004; -static const uint16_t CMD_SYSTEM_MODE_VS = 0x0002; -static const uint16_t CMD_WRITE_ABD_PARAM = 0x0007; -static const uint16_t CMD_WRITE_REGISTER = 0x0001; -static const uint16_t CMD_WRITE_SYS_PARAM = 0x0012; +static constexpr uint16_t CMD_DISABLE_CONF = 0x00FE; +static constexpr uint16_t CMD_ENABLE_CONF = 0x00FF; +static constexpr uint16_t CMD_PARM_HIGH_TRESH = 0x0012; +static constexpr uint16_t CMD_PARM_LOW_TRESH = 0x0021; +static constexpr uint16_t CMD_PROTOCOL_VER = 0x0002; +static constexpr uint16_t CMD_READ_ABD_PARAM = 0x0008; +static constexpr uint16_t CMD_READ_REG_ADDR = 0x0020; +static constexpr uint16_t CMD_READ_REGISTER = 0x0002; +static constexpr uint16_t CMD_READ_SERIAL_NUM = 0x0011; +static constexpr uint16_t CMD_READ_SYS_PARAM = 0x0013; +static constexpr uint16_t CMD_READ_VERSION = 0x0000; +static constexpr uint16_t CMD_RESTART = 0x0068; +static constexpr uint16_t CMD_SYSTEM_MODE = 0x0000; +static constexpr uint16_t CMD_SYSTEM_MODE_GR = 0x0003; +static constexpr uint16_t CMD_SYSTEM_MODE_MTT = 0x0001; +static constexpr uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064; +static constexpr uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000; +static constexpr uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004; +static constexpr uint16_t CMD_SYSTEM_MODE_VS = 0x0002; +static constexpr uint16_t CMD_WRITE_ABD_PARAM = 0x0007; +static constexpr uint16_t CMD_WRITE_REGISTER = 0x0001; +static constexpr uint16_t CMD_WRITE_SYS_PARAM = 0x0012; -static const uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04; -static const uint8_t CMD_ABD_DATA_REPLY_START = 0x0A; -static const uint8_t CMD_MAX_BYTES = 0x64; -static const uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02; +static constexpr uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04; +static constexpr uint8_t CMD_ABD_DATA_REPLY_START = 0x0A; +static constexpr uint8_t CMD_MAX_BYTES = 0x64; +static constexpr uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02; -static const uint8_t LD2420_ERROR_NONE = 0x00; -static const uint8_t LD2420_ERROR_TIMEOUT = 0x02; -static const uint8_t LD2420_ERROR_UNKNOWN = 0x01; +static constexpr uint8_t LD2420_ERROR_NONE = 0x00; +static constexpr uint8_t LD2420_ERROR_TIMEOUT = 0x02; +static constexpr uint8_t LD2420_ERROR_UNKNOWN = 0x01; // Register address values -static const uint16_t CMD_MIN_GATE_REG = 0x0000; -static const uint16_t CMD_MAX_GATE_REG = 0x0001; -static const uint16_t CMD_TIMEOUT_REG = 0x0004; -static const uint16_t CMD_GATE_MOVE_THRESH[TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, - 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, - 0x001C, 0x001D, 0x001E, 0x001F}; -static const uint16_t CMD_GATE_STILL_THRESH[TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, - 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, - 0x002C, 0x002D, 0x002E, 0x002F}; -static const uint32_t FACTORY_MOVE_THRESH[TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250, - 250, 250, 250, 250, 250, 250, 250, 250}; -static const uint32_t FACTORY_STILL_THRESH[TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150, - 150, 100, 100, 100, 100, 100, 100, 100}; -static const uint16_t FACTORY_TIMEOUT = 120; -static const uint16_t FACTORY_MIN_GATE = 1; -static const uint16_t FACTORY_MAX_GATE = 12; +static constexpr uint16_t CMD_MIN_GATE_REG = 0x0000; +static constexpr uint16_t CMD_MAX_GATE_REG = 0x0001; +static constexpr uint16_t CMD_TIMEOUT_REG = 0x0004; +static constexpr uint16_t CMD_GATE_MOVE_THRESH[TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, + 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, + 0x001C, 0x001D, 0x001E, 0x001F}; +static constexpr uint16_t CMD_GATE_STILL_THRESH[TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, + 0x002C, 0x002D, 0x002E, 0x002F}; +static constexpr uint32_t FACTORY_MOVE_THRESH[TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250}; +static constexpr uint32_t FACTORY_STILL_THRESH[TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150, + 150, 100, 100, 100, 100, 100, 100, 100}; +static constexpr uint16_t FACTORY_TIMEOUT = 120; +static constexpr uint16_t FACTORY_MIN_GATE = 1; +static constexpr uint16_t FACTORY_MAX_GATE = 12; // COMMAND_BYTE Header & Footer -static const uint32_t CMD_FRAME_FOOTER = 0x01020304; -static const uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD; -static const uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD; -static const uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA; -static const uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8; -static const uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4; -static const int CALIBRATE_VERSION_MIN = 154; -static const uint8_t CMD_FRAME_COMMAND = 6; -static const uint8_t CMD_FRAME_DATA_LENGTH = 4; -static const uint8_t CMD_FRAME_STATUS = 7; -static const uint8_t CMD_ERROR_WORD = 8; -static const uint8_t ENERGY_SENSOR_START = 9; -static const uint8_t CALIBRATE_REPORT_INTERVAL = 4; +static constexpr uint32_t CMD_FRAME_FOOTER = 0x01020304; +static constexpr uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD; +static constexpr uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD; +static constexpr uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA; +static constexpr uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8; +static constexpr uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4; +static constexpr int CALIBRATE_VERSION_MIN = 154; +static constexpr uint8_t CMD_FRAME_COMMAND = 6; +static constexpr uint8_t CMD_FRAME_DATA_LENGTH = 4; +static constexpr uint8_t CMD_FRAME_STATUS = 7; +static constexpr uint8_t CMD_ERROR_WORD = 8; +static constexpr uint8_t ENERGY_SENSOR_START = 9; +static constexpr uint8_t CALIBRATE_REPORT_INTERVAL = 4; static const char *const OP_NORMAL_MODE_STRING = "Normal"; static const char *const OP_SIMPLE_MODE_STRING = "Simple"; diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 6d81f86497..02250c5911 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -20,9 +20,9 @@ namespace esphome::ld2420 { -static const uint8_t CALIBRATE_SAMPLES = 64; -static const uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer -static const uint8_t TOTAL_GATES = 16; +static constexpr uint8_t CALIBRATE_SAMPLES = 64; +static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer +static constexpr uint8_t TOTAL_GATES = 16; enum OpMode : uint8_t { OP_NORMAL_MODE = 1, From 9a8b00a42835b20db98081f1801c5cbafafc723a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:33:23 -0600 Subject: [PATCH 0767/2030] [nfc] Use constexpr for compile-time constants (#14077) --- esphome/components/nfc/nci_core.h | 228 +++++++++++------------ esphome/components/nfc/ndef_message.h | 2 +- esphome/components/nfc/ndef_record.h | 16 +- esphome/components/nfc/ndef_record_uri.h | 2 +- esphome/components/nfc/nfc.h | 60 +++--- 5 files changed, 154 insertions(+), 154 deletions(-) diff --git a/esphome/components/nfc/nci_core.h b/esphome/components/nfc/nci_core.h index fdaf6d0cc5..6b42070ed0 100644 --- a/esphome/components/nfc/nci_core.h +++ b/esphome/components/nfc/nci_core.h @@ -8,137 +8,137 @@ namespace esphome { namespace nfc { // Header info -static const uint8_t NCI_PKT_HEADER_SIZE = 3; // NCI packet (pkt) headers are always three bytes -static const uint8_t NCI_PKT_MT_GID_OFFSET = 0; // NCI packet (pkt) MT and GID offsets -static const uint8_t NCI_PKT_OID_OFFSET = 1; // NCI packet (pkt) OID offset -static const uint8_t NCI_PKT_LENGTH_OFFSET = 2; // NCI packet (pkt) message length (size) offset -static const uint8_t NCI_PKT_PAYLOAD_OFFSET = 3; // NCI packet (pkt) payload offset +static constexpr uint8_t NCI_PKT_HEADER_SIZE = 3; // NCI packet (pkt) headers are always three bytes +static constexpr uint8_t NCI_PKT_MT_GID_OFFSET = 0; // NCI packet (pkt) MT and GID offsets +static constexpr uint8_t NCI_PKT_OID_OFFSET = 1; // NCI packet (pkt) OID offset +static constexpr uint8_t NCI_PKT_LENGTH_OFFSET = 2; // NCI packet (pkt) message length (size) offset +static constexpr uint8_t NCI_PKT_PAYLOAD_OFFSET = 3; // NCI packet (pkt) payload offset // Important masks -static const uint8_t NCI_PKT_MT_MASK = 0xE0; // NCI packet (pkt) message type mask -static const uint8_t NCI_PKT_PBF_MASK = 0x10; // packet boundary flag bit -static const uint8_t NCI_PKT_GID_MASK = 0x0F; -static const uint8_t NCI_PKT_OID_MASK = 0x3F; +static constexpr uint8_t NCI_PKT_MT_MASK = 0xE0; // NCI packet (pkt) message type mask +static constexpr uint8_t NCI_PKT_PBF_MASK = 0x10; // packet boundary flag bit +static constexpr uint8_t NCI_PKT_GID_MASK = 0x0F; +static constexpr uint8_t NCI_PKT_OID_MASK = 0x3F; // Message types -static const uint8_t NCI_PKT_MT_DATA = 0x00; // For sending commands to NFC endpoint (card/tag) -static const uint8_t NCI_PKT_MT_CTRL_COMMAND = 0x20; // For sending commands to NFCC -static const uint8_t NCI_PKT_MT_CTRL_RESPONSE = 0x40; // Response from NFCC to commands -static const uint8_t NCI_PKT_MT_CTRL_NOTIFICATION = 0x60; // Notification from NFCC +static constexpr uint8_t NCI_PKT_MT_DATA = 0x00; // For sending commands to NFC endpoint (card/tag) +static constexpr uint8_t NCI_PKT_MT_CTRL_COMMAND = 0x20; // For sending commands to NFCC +static constexpr uint8_t NCI_PKT_MT_CTRL_RESPONSE = 0x40; // Response from NFCC to commands +static constexpr uint8_t NCI_PKT_MT_CTRL_NOTIFICATION = 0x60; // Notification from NFCC // GIDs -static const uint8_t NCI_CORE_GID = 0x0; -static const uint8_t RF_GID = 0x1; -static const uint8_t NFCEE_GID = 0x1; -static const uint8_t NCI_PROPRIETARY_GID = 0xF; +static constexpr uint8_t NCI_CORE_GID = 0x0; +static constexpr uint8_t RF_GID = 0x1; +static constexpr uint8_t NFCEE_GID = 0x1; +static constexpr uint8_t NCI_PROPRIETARY_GID = 0xF; // OIDs -static const uint8_t NCI_CORE_RESET_OID = 0x00; -static const uint8_t NCI_CORE_INIT_OID = 0x01; -static const uint8_t NCI_CORE_SET_CONFIG_OID = 0x02; -static const uint8_t NCI_CORE_GET_CONFIG_OID = 0x03; -static const uint8_t NCI_CORE_CONN_CREATE_OID = 0x04; -static const uint8_t NCI_CORE_CONN_CLOSE_OID = 0x05; -static const uint8_t NCI_CORE_CONN_CREDITS_OID = 0x06; -static const uint8_t NCI_CORE_GENERIC_ERROR_OID = 0x07; -static const uint8_t NCI_CORE_INTERFACE_ERROR_OID = 0x08; +static constexpr uint8_t NCI_CORE_RESET_OID = 0x00; +static constexpr uint8_t NCI_CORE_INIT_OID = 0x01; +static constexpr uint8_t NCI_CORE_SET_CONFIG_OID = 0x02; +static constexpr uint8_t NCI_CORE_GET_CONFIG_OID = 0x03; +static constexpr uint8_t NCI_CORE_CONN_CREATE_OID = 0x04; +static constexpr uint8_t NCI_CORE_CONN_CLOSE_OID = 0x05; +static constexpr uint8_t NCI_CORE_CONN_CREDITS_OID = 0x06; +static constexpr uint8_t NCI_CORE_GENERIC_ERROR_OID = 0x07; +static constexpr uint8_t NCI_CORE_INTERFACE_ERROR_OID = 0x08; -static const uint8_t RF_DISCOVER_MAP_OID = 0x00; -static const uint8_t RF_SET_LISTEN_MODE_ROUTING_OID = 0x01; -static const uint8_t RF_GET_LISTEN_MODE_ROUTING_OID = 0x02; -static const uint8_t RF_DISCOVER_OID = 0x03; -static const uint8_t RF_DISCOVER_SELECT_OID = 0x04; -static const uint8_t RF_INTF_ACTIVATED_OID = 0x05; -static const uint8_t RF_DEACTIVATE_OID = 0x06; -static const uint8_t RF_FIELD_INFO_OID = 0x07; -static const uint8_t RF_T3T_POLLING_OID = 0x08; -static const uint8_t RF_NFCEE_ACTION_OID = 0x09; -static const uint8_t RF_NFCEE_DISCOVERY_REQ_OID = 0x0A; -static const uint8_t RF_PARAMETER_UPDATE_OID = 0x0B; +static constexpr uint8_t RF_DISCOVER_MAP_OID = 0x00; +static constexpr uint8_t RF_SET_LISTEN_MODE_ROUTING_OID = 0x01; +static constexpr uint8_t RF_GET_LISTEN_MODE_ROUTING_OID = 0x02; +static constexpr uint8_t RF_DISCOVER_OID = 0x03; +static constexpr uint8_t RF_DISCOVER_SELECT_OID = 0x04; +static constexpr uint8_t RF_INTF_ACTIVATED_OID = 0x05; +static constexpr uint8_t RF_DEACTIVATE_OID = 0x06; +static constexpr uint8_t RF_FIELD_INFO_OID = 0x07; +static constexpr uint8_t RF_T3T_POLLING_OID = 0x08; +static constexpr uint8_t RF_NFCEE_ACTION_OID = 0x09; +static constexpr uint8_t RF_NFCEE_DISCOVERY_REQ_OID = 0x0A; +static constexpr uint8_t RF_PARAMETER_UPDATE_OID = 0x0B; -static const uint8_t NFCEE_DISCOVER_OID = 0x00; -static const uint8_t NFCEE_MODE_SET_OID = 0x01; +static constexpr uint8_t NFCEE_DISCOVER_OID = 0x00; +static constexpr uint8_t NFCEE_MODE_SET_OID = 0x01; // Interfaces -static const uint8_t INTF_NFCEE_DIRECT = 0x00; -static const uint8_t INTF_FRAME = 0x01; -static const uint8_t INTF_ISODEP = 0x02; -static const uint8_t INTF_NFCDEP = 0x03; -static const uint8_t INTF_TAGCMD = 0x80; // NXP proprietary +static constexpr uint8_t INTF_NFCEE_DIRECT = 0x00; +static constexpr uint8_t INTF_FRAME = 0x01; +static constexpr uint8_t INTF_ISODEP = 0x02; +static constexpr uint8_t INTF_NFCDEP = 0x03; +static constexpr uint8_t INTF_TAGCMD = 0x80; // NXP proprietary // Bit rates -static const uint8_t NFC_BIT_RATE_106 = 0x00; -static const uint8_t NFC_BIT_RATE_212 = 0x01; -static const uint8_t NFC_BIT_RATE_424 = 0x02; -static const uint8_t NFC_BIT_RATE_848 = 0x03; -static const uint8_t NFC_BIT_RATE_1695 = 0x04; -static const uint8_t NFC_BIT_RATE_3390 = 0x05; -static const uint8_t NFC_BIT_RATE_6780 = 0x06; +static constexpr uint8_t NFC_BIT_RATE_106 = 0x00; +static constexpr uint8_t NFC_BIT_RATE_212 = 0x01; +static constexpr uint8_t NFC_BIT_RATE_424 = 0x02; +static constexpr uint8_t NFC_BIT_RATE_848 = 0x03; +static constexpr uint8_t NFC_BIT_RATE_1695 = 0x04; +static constexpr uint8_t NFC_BIT_RATE_3390 = 0x05; +static constexpr uint8_t NFC_BIT_RATE_6780 = 0x06; // Protocols -static const uint8_t PROT_UNDETERMINED = 0x00; -static const uint8_t PROT_T1T = 0x01; -static const uint8_t PROT_T2T = 0x02; -static const uint8_t PROT_T3T = 0x03; -static const uint8_t PROT_ISODEP = 0x04; -static const uint8_t PROT_NFCDEP = 0x05; -static const uint8_t PROT_T5T = 0x06; -static const uint8_t PROT_MIFARE = 0x80; +static constexpr uint8_t PROT_UNDETERMINED = 0x00; +static constexpr uint8_t PROT_T1T = 0x01; +static constexpr uint8_t PROT_T2T = 0x02; +static constexpr uint8_t PROT_T3T = 0x03; +static constexpr uint8_t PROT_ISODEP = 0x04; +static constexpr uint8_t PROT_NFCDEP = 0x05; +static constexpr uint8_t PROT_T5T = 0x06; +static constexpr uint8_t PROT_MIFARE = 0x80; // RF Technologies -static const uint8_t NFC_RF_TECH_A = 0x00; -static const uint8_t NFC_RF_TECH_B = 0x01; -static const uint8_t NFC_RF_TECH_F = 0x02; -static const uint8_t NFC_RF_TECH_15693 = 0x03; +static constexpr uint8_t NFC_RF_TECH_A = 0x00; +static constexpr uint8_t NFC_RF_TECH_B = 0x01; +static constexpr uint8_t NFC_RF_TECH_F = 0x02; +static constexpr uint8_t NFC_RF_TECH_15693 = 0x03; // RF Technology & Modes -static const uint8_t MODE_MASK = 0xF0; -static const uint8_t MODE_LISTEN_MASK = 0x80; -static const uint8_t MODE_POLL = 0x00; +static constexpr uint8_t MODE_MASK = 0xF0; +static constexpr uint8_t MODE_LISTEN_MASK = 0x80; +static constexpr uint8_t MODE_POLL = 0x00; -static const uint8_t TECH_PASSIVE_NFCA = 0x00; -static const uint8_t TECH_PASSIVE_NFCB = 0x01; -static const uint8_t TECH_PASSIVE_NFCF = 0x02; -static const uint8_t TECH_ACTIVE_NFCA = 0x03; -static const uint8_t TECH_ACTIVE_NFCF = 0x05; -static const uint8_t TECH_PASSIVE_15693 = 0x06; +static constexpr uint8_t TECH_PASSIVE_NFCA = 0x00; +static constexpr uint8_t TECH_PASSIVE_NFCB = 0x01; +static constexpr uint8_t TECH_PASSIVE_NFCF = 0x02; +static constexpr uint8_t TECH_ACTIVE_NFCA = 0x03; +static constexpr uint8_t TECH_ACTIVE_NFCF = 0x05; +static constexpr uint8_t TECH_PASSIVE_15693 = 0x06; // Status codes -static const uint8_t STATUS_OK = 0x00; -static const uint8_t STATUS_REJECTED = 0x01; -static const uint8_t STATUS_RF_FRAME_CORRUPTED = 0x02; -static const uint8_t STATUS_FAILED = 0x03; -static const uint8_t STATUS_NOT_INITIALIZED = 0x04; -static const uint8_t STATUS_SYNTAX_ERROR = 0x05; -static const uint8_t STATUS_SEMANTIC_ERROR = 0x06; -static const uint8_t STATUS_INVALID_PARAM = 0x09; -static const uint8_t STATUS_MESSAGE_SIZE_EXCEEDED = 0x0A; -static const uint8_t DISCOVERY_ALREADY_STARTED = 0xA0; -static const uint8_t DISCOVERY_TARGET_ACTIVATION_FAILED = 0xA1; -static const uint8_t DISCOVERY_TEAR_DOWN = 0xA2; -static const uint8_t RF_TRANSMISSION_ERROR = 0xB0; -static const uint8_t RF_PROTOCOL_ERROR = 0xB1; -static const uint8_t RF_TIMEOUT_ERROR = 0xB2; -static const uint8_t NFCEE_INTERFACE_ACTIVATION_FAILED = 0xC0; -static const uint8_t NFCEE_TRANSMISSION_ERROR = 0xC1; -static const uint8_t NFCEE_PROTOCOL_ERROR = 0xC2; -static const uint8_t NFCEE_TIMEOUT_ERROR = 0xC3; +static constexpr uint8_t STATUS_OK = 0x00; +static constexpr uint8_t STATUS_REJECTED = 0x01; +static constexpr uint8_t STATUS_RF_FRAME_CORRUPTED = 0x02; +static constexpr uint8_t STATUS_FAILED = 0x03; +static constexpr uint8_t STATUS_NOT_INITIALIZED = 0x04; +static constexpr uint8_t STATUS_SYNTAX_ERROR = 0x05; +static constexpr uint8_t STATUS_SEMANTIC_ERROR = 0x06; +static constexpr uint8_t STATUS_INVALID_PARAM = 0x09; +static constexpr uint8_t STATUS_MESSAGE_SIZE_EXCEEDED = 0x0A; +static constexpr uint8_t DISCOVERY_ALREADY_STARTED = 0xA0; +static constexpr uint8_t DISCOVERY_TARGET_ACTIVATION_FAILED = 0xA1; +static constexpr uint8_t DISCOVERY_TEAR_DOWN = 0xA2; +static constexpr uint8_t RF_TRANSMISSION_ERROR = 0xB0; +static constexpr uint8_t RF_PROTOCOL_ERROR = 0xB1; +static constexpr uint8_t RF_TIMEOUT_ERROR = 0xB2; +static constexpr uint8_t NFCEE_INTERFACE_ACTIVATION_FAILED = 0xC0; +static constexpr uint8_t NFCEE_TRANSMISSION_ERROR = 0xC1; +static constexpr uint8_t NFCEE_PROTOCOL_ERROR = 0xC2; +static constexpr uint8_t NFCEE_TIMEOUT_ERROR = 0xC3; // Deactivation types/reasons -static const uint8_t DEACTIVATION_TYPE_IDLE = 0x00; -static const uint8_t DEACTIVATION_TYPE_SLEEP = 0x01; -static const uint8_t DEACTIVATION_TYPE_SLEEP_AF = 0x02; -static const uint8_t DEACTIVATION_TYPE_DISCOVERY = 0x03; +static constexpr uint8_t DEACTIVATION_TYPE_IDLE = 0x00; +static constexpr uint8_t DEACTIVATION_TYPE_SLEEP = 0x01; +static constexpr uint8_t DEACTIVATION_TYPE_SLEEP_AF = 0x02; +static constexpr uint8_t DEACTIVATION_TYPE_DISCOVERY = 0x03; // RF discover map modes -static const uint8_t RF_DISCOVER_MAP_MODE_POLL = 0x1; -static const uint8_t RF_DISCOVER_MAP_MODE_LISTEN = 0x2; +static constexpr uint8_t RF_DISCOVER_MAP_MODE_POLL = 0x1; +static constexpr uint8_t RF_DISCOVER_MAP_MODE_LISTEN = 0x2; // RF discover notification types -static const uint8_t RF_DISCOVER_NTF_NT_LAST = 0x00; -static const uint8_t RF_DISCOVER_NTF_NT_LAST_RL = 0x01; -static const uint8_t RF_DISCOVER_NTF_NT_MORE = 0x02; +static constexpr uint8_t RF_DISCOVER_NTF_NT_LAST = 0x00; +static constexpr uint8_t RF_DISCOVER_NTF_NT_LAST_RL = 0x01; +static constexpr uint8_t RF_DISCOVER_NTF_NT_MORE = 0x02; // Important message offsets -static const uint8_t RF_DISCOVER_NTF_DISCOVERY_ID = 0 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_DISCOVER_NTF_PROTOCOL = 1 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_DISCOVER_NTF_MODE_TECH = 2 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_DISCOVER_NTF_RF_TECH_LENGTH = 3 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_DISCOVER_NTF_RF_TECH_PARAMS = 4 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_DISCOVERY_ID = 0 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_INTERFACE = 1 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_PROTOCOL = 2 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_MODE_TECH = 3 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_MAX_SIZE = 4 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_INIT_CRED = 5 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_RF_TECH_LENGTH = 6 + NCI_PKT_HEADER_SIZE; -static const uint8_t RF_INTF_ACTIVATED_NTF_RF_TECH_PARAMS = 7 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_DISCOVER_NTF_DISCOVERY_ID = 0 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_DISCOVER_NTF_PROTOCOL = 1 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_DISCOVER_NTF_MODE_TECH = 2 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_DISCOVER_NTF_RF_TECH_LENGTH = 3 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_DISCOVER_NTF_RF_TECH_PARAMS = 4 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_DISCOVERY_ID = 0 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_INTERFACE = 1 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_PROTOCOL = 2 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_MODE_TECH = 3 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_MAX_SIZE = 4 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_INIT_CRED = 5 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_RF_TECH_LENGTH = 6 + NCI_PKT_HEADER_SIZE; +static constexpr uint8_t RF_INTF_ACTIVATED_NTF_RF_TECH_PARAMS = 7 + NCI_PKT_HEADER_SIZE; } // namespace nfc } // namespace esphome diff --git a/esphome/components/nfc/ndef_message.h b/esphome/components/nfc/ndef_message.h index 2e81fb216c..48f79b8854 100644 --- a/esphome/components/nfc/ndef_message.h +++ b/esphome/components/nfc/ndef_message.h @@ -12,7 +12,7 @@ namespace esphome { namespace nfc { -static const uint8_t MAX_NDEF_RECORDS = 4; +static constexpr uint8_t MAX_NDEF_RECORDS = 4; class NdefMessage { public: diff --git a/esphome/components/nfc/ndef_record.h b/esphome/components/nfc/ndef_record.h index 76d8b6a50a..1a7c24aee9 100644 --- a/esphome/components/nfc/ndef_record.h +++ b/esphome/components/nfc/ndef_record.h @@ -8,14 +8,14 @@ namespace esphome { namespace nfc { -static const uint8_t TNF_EMPTY = 0x00; -static const uint8_t TNF_WELL_KNOWN = 0x01; -static const uint8_t TNF_MIME_MEDIA = 0x02; -static const uint8_t TNF_ABSOLUTE_URI = 0x03; -static const uint8_t TNF_EXTERNAL_TYPE = 0x04; -static const uint8_t TNF_UNKNOWN = 0x05; -static const uint8_t TNF_UNCHANGED = 0x06; -static const uint8_t TNF_RESERVED = 0x07; +static constexpr uint8_t TNF_EMPTY = 0x00; +static constexpr uint8_t TNF_WELL_KNOWN = 0x01; +static constexpr uint8_t TNF_MIME_MEDIA = 0x02; +static constexpr uint8_t TNF_ABSOLUTE_URI = 0x03; +static constexpr uint8_t TNF_EXTERNAL_TYPE = 0x04; +static constexpr uint8_t TNF_UNKNOWN = 0x05; +static constexpr uint8_t TNF_UNCHANGED = 0x06; +static constexpr uint8_t TNF_RESERVED = 0x07; class NdefRecord { public: diff --git a/esphome/components/nfc/ndef_record_uri.h b/esphome/components/nfc/ndef_record_uri.h index 1eadda1b4f..2f7790a9a9 100644 --- a/esphome/components/nfc/ndef_record_uri.h +++ b/esphome/components/nfc/ndef_record_uri.h @@ -9,7 +9,7 @@ namespace esphome { namespace nfc { -static const uint8_t PAYLOAD_IDENTIFIERS_COUNT = 0x23; +static constexpr uint8_t PAYLOAD_IDENTIFIERS_COUNT = 0x23; static const char *const PAYLOAD_IDENTIFIERS[] = {"", "http://www.", "https://www.", diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index 5191904833..cdaea82af6 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -12,47 +12,47 @@ namespace esphome { namespace nfc { -static const uint8_t MIFARE_CLASSIC_BLOCK_SIZE = 16; -static const uint8_t MIFARE_CLASSIC_LONG_TLV_SIZE = 4; -static const uint8_t MIFARE_CLASSIC_SHORT_TLV_SIZE = 2; -static const uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW = 4; -static const uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH = 16; -static const uint8_t MIFARE_CLASSIC_16BLOCK_SECT_START = 32; +static constexpr uint8_t MIFARE_CLASSIC_BLOCK_SIZE = 16; +static constexpr uint8_t MIFARE_CLASSIC_LONG_TLV_SIZE = 4; +static constexpr uint8_t MIFARE_CLASSIC_SHORT_TLV_SIZE = 2; +static constexpr uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_LOW = 4; +static constexpr uint8_t MIFARE_CLASSIC_BLOCKS_PER_SECT_HIGH = 16; +static constexpr uint8_t MIFARE_CLASSIC_16BLOCK_SECT_START = 32; -static const uint8_t MIFARE_ULTRALIGHT_PAGE_SIZE = 4; -static const uint8_t MIFARE_ULTRALIGHT_READ_SIZE = 4; -static const uint8_t MIFARE_ULTRALIGHT_DATA_START_PAGE = 4; -static const uint8_t MIFARE_ULTRALIGHT_MAX_PAGE = 63; +static constexpr uint8_t MIFARE_ULTRALIGHT_PAGE_SIZE = 4; +static constexpr uint8_t MIFARE_ULTRALIGHT_READ_SIZE = 4; +static constexpr uint8_t MIFARE_ULTRALIGHT_DATA_START_PAGE = 4; +static constexpr uint8_t MIFARE_ULTRALIGHT_MAX_PAGE = 63; -static const uint8_t TAG_TYPE_MIFARE_CLASSIC = 0; -static const uint8_t TAG_TYPE_1 = 1; -static const uint8_t TAG_TYPE_2 = 2; -static const uint8_t TAG_TYPE_3 = 3; -static const uint8_t TAG_TYPE_4 = 4; -static const uint8_t TAG_TYPE_UNKNOWN = 99; +static constexpr uint8_t TAG_TYPE_MIFARE_CLASSIC = 0; +static constexpr uint8_t TAG_TYPE_1 = 1; +static constexpr uint8_t TAG_TYPE_2 = 2; +static constexpr uint8_t TAG_TYPE_3 = 3; +static constexpr uint8_t TAG_TYPE_4 = 4; +static constexpr uint8_t TAG_TYPE_UNKNOWN = 99; // Mifare Commands -static const uint8_t MIFARE_CMD_AUTH_A = 0x60; -static const uint8_t MIFARE_CMD_AUTH_B = 0x61; -static const uint8_t MIFARE_CMD_HALT = 0x50; -static const uint8_t MIFARE_CMD_READ = 0x30; -static const uint8_t MIFARE_CMD_WRITE = 0xA0; -static const uint8_t MIFARE_CMD_WRITE_ULTRALIGHT = 0xA2; +static constexpr uint8_t MIFARE_CMD_AUTH_A = 0x60; +static constexpr uint8_t MIFARE_CMD_AUTH_B = 0x61; +static constexpr uint8_t MIFARE_CMD_HALT = 0x50; +static constexpr uint8_t MIFARE_CMD_READ = 0x30; +static constexpr uint8_t MIFARE_CMD_WRITE = 0xA0; +static constexpr uint8_t MIFARE_CMD_WRITE_ULTRALIGHT = 0xA2; // Mifare Ack/Nak -static const uint8_t MIFARE_CMD_ACK = 0x0A; -static const uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_VALID = 0x00; -static const uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_VALID = 0x01; -static const uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_INVALID = 0x04; -static const uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_INVALID = 0x05; +static constexpr uint8_t MIFARE_CMD_ACK = 0x0A; +static constexpr uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_VALID = 0x00; +static constexpr uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_VALID = 0x01; +static constexpr uint8_t MIFARE_CMD_NAK_INVALID_XFER_BUFF_INVALID = 0x04; +static constexpr uint8_t MIFARE_CMD_NAK_CRC_ERROR_XFER_BUFF_INVALID = 0x05; static const char *const MIFARE_CLASSIC = "Mifare Classic"; static const char *const NFC_FORUM_TYPE_2 = "NFC Forum Type 2"; static const char *const ERROR = "Error"; -static const uint8_t DEFAULT_KEY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; -static const uint8_t NDEF_KEY[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; -static const uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; +static constexpr uint8_t DEFAULT_KEY[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; +static constexpr uint8_t NDEF_KEY[6] = {0xD3, 0xF7, 0xD3, 0xF7, 0xD3, 0xF7}; +static constexpr uint8_t MAD_KEY[6] = {0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5}; /// Max UID size is 10 bytes, formatted as "XX-XX-XX-XX-XX-XX-XX-XX-XX-XX\0" = 30 chars static constexpr size_t FORMAT_UID_BUFFER_SIZE = 30; From 2f9b76f129c2b278b0c45ba5c66430d638631ee2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:33:39 -0600 Subject: [PATCH 0768/2030] [pn7160] Use constexpr for compile-time constants (#14078) --- esphome/components/pn7150/pn7150.h | 111 +++++++++---------- esphome/components/pn7160/pn7160.h | 121 +++++++++++---------- esphome/components/pn7160_spi/pn7160_spi.h | 4 +- 3 files changed, 119 insertions(+), 117 deletions(-) diff --git a/esphome/components/pn7150/pn7150.h b/esphome/components/pn7150/pn7150.h index 5feba17d21..c5dd283832 100644 --- a/esphome/components/pn7150/pn7150.h +++ b/esphome/components/pn7150/pn7150.h @@ -14,48 +14,48 @@ namespace esphome { namespace pn7150 { -static const uint16_t NFCC_DEFAULT_TIMEOUT = 10; -static const uint16_t NFCC_INIT_TIMEOUT = 50; -static const uint16_t NFCC_TAG_WRITE_TIMEOUT = 15; +static constexpr uint16_t NFCC_DEFAULT_TIMEOUT = 10; +static constexpr uint16_t NFCC_INIT_TIMEOUT = 50; +static constexpr uint16_t NFCC_TAG_WRITE_TIMEOUT = 15; -static const uint8_t NFCC_MAX_COMM_FAILS = 3; -static const uint8_t NFCC_MAX_ERROR_COUNT = 10; +static constexpr uint8_t NFCC_MAX_COMM_FAILS = 3; +static constexpr uint8_t NFCC_MAX_ERROR_COUNT = 10; -static const uint8_t XCHG_DATA_OID = 0x10; -static const uint8_t MF_SECTORSEL_OID = 0x32; -static const uint8_t MFC_AUTHENTICATE_OID = 0x40; -static const uint8_t TEST_PRBS_OID = 0x30; -static const uint8_t TEST_ANTENNA_OID = 0x3D; -static const uint8_t TEST_GET_REGISTER_OID = 0x33; +static constexpr uint8_t XCHG_DATA_OID = 0x10; +static constexpr uint8_t MF_SECTORSEL_OID = 0x32; +static constexpr uint8_t MFC_AUTHENTICATE_OID = 0x40; +static constexpr uint8_t TEST_PRBS_OID = 0x30; +static constexpr uint8_t TEST_ANTENNA_OID = 0x3D; +static constexpr uint8_t TEST_GET_REGISTER_OID = 0x33; -static const uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00; // key select A -static const uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80; // key select B -static const uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10; +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00; // key select A +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80; // key select B +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10; -static const uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, - 0x00, 0x00, 0x85, 0x01, 0x01, 0x00}; -static const uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04, - 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00}; -static const uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03}; -static const uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04}; -static const uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0}; -static const uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6}; -static const uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00}; -static const uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82}; +static constexpr uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, + 0x00, 0x00, 0x85, 0x01, 0x01, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04, + 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03}; +static constexpr uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04}; +static constexpr uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0}; +static constexpr uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6}; +static constexpr uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82}; -static const uint8_t CORE_CONFIG_SOLO[] = {0x01, // Number of parameter fields - 0x00, // config param identifier (TOTAL_DURATION) - 0x02, // length of value - 0x01, // TOTAL_DURATION (low)... - 0x00}; // TOTAL_DURATION (high): 1 ms +static constexpr uint8_t CORE_CONFIG_SOLO[] = {0x01, // Number of parameter fields + 0x00, // config param identifier (TOTAL_DURATION) + 0x02, // length of value + 0x01, // TOTAL_DURATION (low)... + 0x00}; // TOTAL_DURATION (high): 1 ms -static const uint8_t CORE_CONFIG_RW_CE[] = {0x01, // Number of parameter fields - 0x00, // config param identifier (TOTAL_DURATION) - 0x02, // length of value - 0xF8, // TOTAL_DURATION (low)... - 0x02}; // TOTAL_DURATION (high): 760 ms +static constexpr uint8_t CORE_CONFIG_RW_CE[] = {0x01, // Number of parameter fields + 0x00, // config param identifier (TOTAL_DURATION) + 0x02, // length of value + 0xF8, // TOTAL_DURATION (low)... + 0x02}; // TOTAL_DURATION (high): 760 ms -static const uint8_t PMU_CFG[] = { +static constexpr uint8_t PMU_CFG[] = { 0x01, // Number of parameters 0xA0, 0x0E, // ext. tag 3, // length @@ -64,7 +64,7 @@ static const uint8_t PMU_CFG[] = { 0x01, // RFU; must be 0x00 for CFG1 and 0x01 for CFG2 }; -static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes +static constexpr uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes nfc::PROT_T1T, nfc::RF_DISCOVER_MAP_MODE_POLL, nfc::INTF_FRAME, // poll mode nfc::PROT_T2T, nfc::RF_DISCOVER_MAP_MODE_POLL, @@ -76,28 +76,29 @@ static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes nfc::PROT_MIFARE, nfc::RF_DISCOVER_MAP_MODE_POLL, nfc::INTF_TAGCMD}; // poll mode -static const uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = {nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode +static constexpr uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = { + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode -static const uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode +static constexpr uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode -static const uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode +static constexpr uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode -static const uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming) - 1, // number of table entries - 0x01, // type = protocol-based - 3, // length - 0, // DH NFCEE ID, a static ID representing the DH-NFCEE - 0x01, // power state - nfc::PROT_ISODEP}; // protocol +static constexpr uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming) + 1, // number of table entries + 0x01, // type = protocol-based + 3, // length + 0, // DH NFCEE ID, a static ID representing the DH-NFCEE + 0x01, // power state + nfc::PROT_ISODEP}; // protocol enum class CardEmulationState : uint8_t { CARD_EMU_IDLE, diff --git a/esphome/components/pn7160/pn7160.h b/esphome/components/pn7160/pn7160.h index 9f2d10c2d5..77ab49399c 100644 --- a/esphome/components/pn7160/pn7160.h +++ b/esphome/components/pn7160/pn7160.h @@ -14,48 +14,48 @@ namespace esphome { namespace pn7160 { -static const uint16_t NFCC_DEFAULT_TIMEOUT = 10; -static const uint16_t NFCC_INIT_TIMEOUT = 50; -static const uint16_t NFCC_TAG_WRITE_TIMEOUT = 15; +static constexpr uint16_t NFCC_DEFAULT_TIMEOUT = 10; +static constexpr uint16_t NFCC_INIT_TIMEOUT = 50; +static constexpr uint16_t NFCC_TAG_WRITE_TIMEOUT = 15; -static const uint8_t NFCC_MAX_COMM_FAILS = 3; -static const uint8_t NFCC_MAX_ERROR_COUNT = 10; +static constexpr uint8_t NFCC_MAX_COMM_FAILS = 3; +static constexpr uint8_t NFCC_MAX_ERROR_COUNT = 10; -static const uint8_t XCHG_DATA_OID = 0x10; -static const uint8_t MF_SECTORSEL_OID = 0x32; -static const uint8_t MFC_AUTHENTICATE_OID = 0x40; -static const uint8_t TEST_PRBS_OID = 0x30; -static const uint8_t TEST_ANTENNA_OID = 0x3D; -static const uint8_t TEST_GET_REGISTER_OID = 0x33; +static constexpr uint8_t XCHG_DATA_OID = 0x10; +static constexpr uint8_t MF_SECTORSEL_OID = 0x32; +static constexpr uint8_t MFC_AUTHENTICATE_OID = 0x40; +static constexpr uint8_t TEST_PRBS_OID = 0x30; +static constexpr uint8_t TEST_ANTENNA_OID = 0x3D; +static constexpr uint8_t TEST_GET_REGISTER_OID = 0x33; -static const uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00; // key select A -static const uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80; // key select B -static const uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10; +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_A = 0x00; // key select A +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_KS_B = 0x80; // key select B +static constexpr uint8_t MFC_AUTHENTICATE_PARAM_EMBED_KEY = 0x10; -static const uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, - 0x00, 0x00, 0x85, 0x01, 0x01, 0x00}; -static const uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04, - 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00}; -static const uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03}; -static const uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04}; -static const uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0}; -static const uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6}; -static const uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00}; -static const uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82}; +static constexpr uint8_t CARD_EMU_T4T_APP_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76, + 0x00, 0x00, 0x85, 0x01, 0x01, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_CC[] = {0x00, 0x0F, 0x20, 0x00, 0xFF, 0x00, 0xFF, 0x04, + 0x06, 0xE1, 0x04, 0x00, 0xFF, 0x00, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_CC_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03}; +static constexpr uint8_t CARD_EMU_T4T_NDEF_SELECT[] = {0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x04}; +static constexpr uint8_t CARD_EMU_T4T_READ[] = {0x00, 0xB0}; +static constexpr uint8_t CARD_EMU_T4T_WRITE[] = {0x00, 0xD6}; +static constexpr uint8_t CARD_EMU_T4T_OK[] = {0x90, 0x00}; +static constexpr uint8_t CARD_EMU_T4T_NOK[] = {0x6A, 0x82}; -static const uint8_t CORE_CONFIG_SOLO[] = {0x01, // Number of parameter fields - 0x00, // config param identifier (TOTAL_DURATION) - 0x02, // length of value - 0x01, // TOTAL_DURATION (low)... - 0x00}; // TOTAL_DURATION (high): 1 ms +static constexpr uint8_t CORE_CONFIG_SOLO[] = {0x01, // Number of parameter fields + 0x00, // config param identifier (TOTAL_DURATION) + 0x02, // length of value + 0x01, // TOTAL_DURATION (low)... + 0x00}; // TOTAL_DURATION (high): 1 ms -static const uint8_t CORE_CONFIG_RW_CE[] = {0x01, // Number of parameter fields - 0x00, // config param identifier (TOTAL_DURATION) - 0x02, // length of value - 0xF8, // TOTAL_DURATION (low)... - 0x02}; // TOTAL_DURATION (high): 760 ms +static constexpr uint8_t CORE_CONFIG_RW_CE[] = {0x01, // Number of parameter fields + 0x00, // config param identifier (TOTAL_DURATION) + 0x02, // length of value + 0xF8, // TOTAL_DURATION (low)... + 0x02}; // TOTAL_DURATION (high): 760 ms -static const uint8_t PMU_CFG[] = { +static constexpr uint8_t PMU_CFG[] = { 0x01, // Number of parameters 0xA0, 0x0E, // ext. tag 11, // length @@ -74,7 +74,7 @@ static const uint8_t PMU_CFG[] = { 0x0C, // RFU }; -static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes +static constexpr uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes nfc::PROT_T1T, nfc::RF_DISCOVER_MAP_MODE_POLL, nfc::INTF_FRAME, // poll mode nfc::PROT_T2T, nfc::RF_DISCOVER_MAP_MODE_POLL, @@ -86,33 +86,34 @@ static const uint8_t RF_DISCOVER_MAP_CONFIG[] = { // poll modes nfc::PROT_MIFARE, nfc::RF_DISCOVER_MAP_MODE_POLL, nfc::INTF_TAGCMD}; // poll mode -static const uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = {nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode +static constexpr uint8_t RF_DISCOVERY_LISTEN_CONFIG[] = { + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode -static const uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode +static constexpr uint8_t RF_DISCOVERY_POLL_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF}; // poll mode -static const uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode - nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode - nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode +static constexpr uint8_t RF_DISCOVERY_CONFIG[] = {nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCA, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCB, // poll mode + nfc::MODE_POLL | nfc::TECH_PASSIVE_NFCF, // poll mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCA, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCB, // listen mode + nfc::MODE_LISTEN_MASK | nfc::TECH_PASSIVE_NFCF}; // listen mode -static const uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming) - 2, // number of table entries - 0x01, // type = protocol-based - 3, // length - 0, // DH NFCEE ID, a static ID representing the DH-NFCEE - 0x07, // power state - nfc::PROT_ISODEP, // protocol - 0x00, // type = technology-based - 3, // length - 0, // DH NFCEE ID, a static ID representing the DH-NFCEE - 0x07, // power state - nfc::TECH_PASSIVE_NFCA}; // technology +static constexpr uint8_t RF_LISTEN_MODE_ROUTING_CONFIG[] = {0x00, // "more" (another message is coming) + 2, // number of table entries + 0x01, // type = protocol-based + 3, // length + 0, // DH NFCEE ID, a static ID representing the DH-NFCEE + 0x07, // power state + nfc::PROT_ISODEP, // protocol + 0x00, // type = technology-based + 3, // length + 0, // DH NFCEE ID, a static ID representing the DH-NFCEE + 0x07, // power state + nfc::TECH_PASSIVE_NFCA}; // technology enum class CardEmulationState : uint8_t { CARD_EMU_IDLE, diff --git a/esphome/components/pn7160_spi/pn7160_spi.h b/esphome/components/pn7160_spi/pn7160_spi.h index 7d4460a76d..9b6e21fa2a 100644 --- a/esphome/components/pn7160_spi/pn7160_spi.h +++ b/esphome/components/pn7160_spi/pn7160_spi.h @@ -10,8 +10,8 @@ namespace esphome { namespace pn7160_spi { -static const uint8_t TDD_SPI_READ = 0xFF; -static const uint8_t TDD_SPI_WRITE = 0x0A; +static constexpr uint8_t TDD_SPI_READ = 0xFF; +static constexpr uint8_t TDD_SPI_WRITE = 0x0A; class PN7160Spi : public pn7160::PN7160, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING, From c8598fe6206e4402b07bce9aed2bf4416f5a1859 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:34:25 -0600 Subject: [PATCH 0769/2030] [bluetooth_proxy] Use constexpr for remaining compile-time constants (#14080) --- esphome/components/bluetooth_proxy/bluetooth_proxy.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 62a035e79f..85461755aa 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -23,9 +23,9 @@ namespace esphome::bluetooth_proxy { -static const esp_err_t ESP_GATT_NOT_CONNECTED = -1; -static const int DONE_SENDING_SERVICES = -2; -static const int INIT_SENDING_SERVICES = -3; +static constexpr esp_err_t ESP_GATT_NOT_CONNECTED = -1; +static constexpr int DONE_SENDING_SERVICES = -2; +static constexpr int INIT_SENDING_SERVICES = -3; using namespace esp32_ble_client; From 3c227eeca46d5ca6e99e5e59a9585d0f168642fb Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Feb 2026 21:50:39 -0600 Subject: [PATCH 0770/2030] [audio] Add support for sinking via an arbitrary callback (#14035) --- esphome/components/audio/audio_transfer_buffer.cpp | 2 ++ esphome/components/audio/audio_transfer_buffer.h | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/esphome/components/audio/audio_transfer_buffer.cpp b/esphome/components/audio/audio_transfer_buffer.cpp index ddb669e0eb..a8be55d62f 100644 --- a/esphome/components/audio/audio_transfer_buffer.cpp +++ b/esphome/components/audio/audio_transfer_buffer.cpp @@ -165,6 +165,8 @@ size_t AudioSinkTransferBuffer::transfer_data_to_sink(TickType_t ticks_to_wait, if (this->ring_buffer_.use_count() > 0) { bytes_written = this->ring_buffer_->write_without_replacement((void *) this->data_start_, this->available(), ticks_to_wait); + } else if (this->sink_callback_ != nullptr) { + bytes_written = this->sink_callback_->audio_sink_write(this->data_start_, this->available(), ticks_to_wait); } this->decrease_buffer_length(bytes_written); diff --git a/esphome/components/audio/audio_transfer_buffer.h b/esphome/components/audio/audio_transfer_buffer.h index 24c0670d1a..22c22cc9ae 100644 --- a/esphome/components/audio/audio_transfer_buffer.h +++ b/esphome/components/audio/audio_transfer_buffer.h @@ -15,6 +15,12 @@ namespace esphome { namespace audio { +/// @brief Abstract interface for writing decoded audio data to a sink. +class AudioSinkCallback { + public: + virtual size_t audio_sink_write(uint8_t *data, size_t length, TickType_t ticks_to_wait) = 0; +}; + class AudioTransferBuffer { /* * @brief Class that facilitates tranferring data between a buffer and an audio source or sink. @@ -108,6 +114,10 @@ class AudioSinkTransferBuffer : public AudioTransferBuffer { void set_sink(speaker::Speaker *speaker) { this->speaker_ = speaker; } #endif + /// @brief Adds a callback as the transfer buffer's sink. + /// @param callback Pointer to the AudioSinkCallback implementation + void set_sink(AudioSinkCallback *callback) { this->sink_callback_ = callback; } + void clear_buffered_data() override; bool has_buffered_data() const override; @@ -116,6 +126,7 @@ class AudioSinkTransferBuffer : public AudioTransferBuffer { #ifdef USE_SPEAKER speaker::Speaker *speaker_{nullptr}; #endif + AudioSinkCallback *sink_callback_{nullptr}; }; class AudioSourceTransferBuffer : public AudioTransferBuffer { From 264c8faedd0ab956b0437ec2ecc0bacae1708923 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Feb 2026 21:51:01 -0600 Subject: [PATCH 0771/2030] [media_player] Add more commands to support Sendspin (#12258) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/media_player/__init__.py | 250 +++++++----------- esphome/components/media_player/automation.h | 27 ++ .../components/media_player/media_player.cpp | 52 ++++ .../components/media_player/media_player.h | 46 ++-- tests/components/media_player/common.yaml | 25 ++ 5 files changed, 232 insertions(+), 168 deletions(-) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index c6ffe50d79..b2afbe5e58 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -35,86 +35,73 @@ MEDIA_PLAYER_FORMAT_PURPOSE_ENUM = { "announcement": MediaPlayerFormatPurpose.PURPOSE_ANNOUNCEMENT, } - -PlayAction = media_player_ns.class_( - "PlayAction", automation.Action, cg.Parented.template(MediaPlayer) -) -PlayMediaAction = media_player_ns.class_( - "PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer) -) -ToggleAction = media_player_ns.class_( - "ToggleAction", automation.Action, cg.Parented.template(MediaPlayer) -) -PauseAction = media_player_ns.class_( - "PauseAction", automation.Action, cg.Parented.template(MediaPlayer) -) -StopAction = media_player_ns.class_( - "StopAction", automation.Action, cg.Parented.template(MediaPlayer) -) -VolumeUpAction = media_player_ns.class_( - "VolumeUpAction", automation.Action, cg.Parented.template(MediaPlayer) -) -VolumeDownAction = media_player_ns.class_( - "VolumeDownAction", automation.Action, cg.Parented.template(MediaPlayer) -) -VolumeSetAction = media_player_ns.class_( - "VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer) -) -TurnOnAction = media_player_ns.class_( - "TurnOnAction", automation.Action, cg.Parented.template(MediaPlayer) -) -TurnOffAction = media_player_ns.class_( - "TurnOffAction", automation.Action, cg.Parented.template(MediaPlayer) -) - +# Local config key constants CONF_ANNOUNCEMENT = "announcement" CONF_ON_PLAY = "on_play" CONF_ON_PAUSE = "on_pause" CONF_ON_ANNOUNCEMENT = "on_announcement" CONF_MEDIA_URL = "media_url" -StateTrigger = media_player_ns.class_("StateTrigger", automation.Trigger.template()) -IdleTrigger = media_player_ns.class_("IdleTrigger", automation.Trigger.template()) -PlayTrigger = media_player_ns.class_("PlayTrigger", automation.Trigger.template()) -PauseTrigger = media_player_ns.class_("PauseTrigger", automation.Trigger.template()) -AnnoucementTrigger = media_player_ns.class_( - "AnnouncementTrigger", automation.Trigger.template() +# Command actions that all share the same schema and codegen handler +_COMMAND_ACTIONS = [ + "play", + "pause", + "stop", + "toggle", + "volume_up", + "volume_down", + "turn_on", + "turn_off", + "next", + "previous", + "mute", + "unmute", + "repeat_off", + "repeat_one", + "repeat_all", + "shuffle", + "unshuffle", + "group_join", + "clear_playlist", +] + +# State triggers: (config_key, C++ class name) +_STATE_TRIGGERS = [ + (CONF_ON_STATE, "StateTrigger"), + (CONF_ON_IDLE, "IdleTrigger"), + (CONF_ON_PLAY, "PlayTrigger"), + (CONF_ON_PAUSE, "PauseTrigger"), + (CONF_ON_ANNOUNCEMENT, "AnnouncementTrigger"), + (CONF_ON_TURN_ON, "OnTrigger"), + (CONF_ON_TURN_OFF, "OffTrigger"), +] + +# State conditions that all share the same schema and codegen handler +_STATE_CONDITIONS = [ + "idle", + "paused", + "playing", + "announcing", + "on", + "off", + "muted", +] + +# Special action classes with custom schemas/handlers +PlayMediaAction = media_player_ns.class_( + "PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer) ) -OnTrigger = media_player_ns.class_("OnTrigger", automation.Trigger.template()) -OffTrigger = media_player_ns.class_("OffTrigger", automation.Trigger.template()) -IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition) -IsPausedCondition = media_player_ns.class_("IsPausedCondition", automation.Condition) -IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition) -IsAnnouncingCondition = media_player_ns.class_( - "IsAnnouncingCondition", automation.Condition +VolumeSetAction = media_player_ns.class_( + "VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer) ) -IsOnCondition = media_player_ns.class_("IsOnCondition", automation.Condition) -IsOffCondition = media_player_ns.class_("IsOffCondition", automation.Condition) async def setup_media_player_core_(var, config): await setup_entity(var, config, "media_player") - for conf in config.get(CONF_ON_STATE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_IDLE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_PLAY, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_PAUSE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_ANNOUNCEMENT, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_TURN_ON, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_TURN_OFF, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + for conf_key, _ in _STATE_TRIGGERS: + for conf in config.get(conf_key, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) async def register_media_player(var, config): @@ -133,41 +120,14 @@ async def new_media_player(config, *args): _MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( { - cv.Optional(CONF_ON_STATE): automation.validate_automation( + cv.Optional(conf_key): automation.validate_automation( { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + media_player_ns.class_(class_name, automation.Trigger.template()) + ), } - ), - cv.Optional(CONF_ON_IDLE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(IdleTrigger), - } - ), - cv.Optional(CONF_ON_PLAY): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PlayTrigger), - } - ), - cv.Optional(CONF_ON_PAUSE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger), - } - ), - cv.Optional(CONF_ON_ANNOUNCEMENT): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(AnnoucementTrigger), - } - ), - cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OnTrigger), - } - ), - cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(OffTrigger), - } - ), + ) + for conf_key, class_name in _STATE_TRIGGERS } ) @@ -228,56 +188,48 @@ async def media_player_play_media_action(config, action_id, template_arg, args): return var -@automation.register_action("media_player.play", PlayAction, MEDIA_PLAYER_ACTION_SCHEMA) -@automation.register_action( - "media_player.toggle", ToggleAction, MEDIA_PLAYER_ACTION_SCHEMA -) -@automation.register_action( - "media_player.pause", PauseAction, MEDIA_PLAYER_ACTION_SCHEMA -) -@automation.register_action("media_player.stop", StopAction, MEDIA_PLAYER_ACTION_SCHEMA) -@automation.register_action( - "media_player.volume_up", VolumeUpAction, MEDIA_PLAYER_ACTION_SCHEMA -) -@automation.register_action( - "media_player.volume_down", VolumeDownAction, MEDIA_PLAYER_ACTION_SCHEMA -) -@automation.register_action( - "media_player.turn_on", TurnOnAction, MEDIA_PLAYER_ACTION_SCHEMA -) -@automation.register_action( - "media_player.turn_off", TurnOffAction, MEDIA_PLAYER_ACTION_SCHEMA -) -async def media_player_action(config, action_id, template_arg, args): - var = cg.new_Pvariable(action_id, template_arg) - await cg.register_parented(var, config[CONF_ID]) - announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_) - cg.add(var.set_announcement(announcement)) - return var +def _snake_to_camel(name): + return "".join(word.capitalize() for word in name.split("_")) -@automation.register_condition( - "media_player.is_idle", IsIdleCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -@automation.register_condition( - "media_player.is_paused", IsPausedCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -@automation.register_condition( - "media_player.is_playing", IsPlayingCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -@automation.register_condition( - "media_player.is_announcing", IsAnnouncingCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -@automation.register_condition( - "media_player.is_on", IsOnCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -@automation.register_condition( - "media_player.is_off", IsOffCondition, MEDIA_PLAYER_CONDITION_SCHEMA -) -async def media_player_condition(config, action_id, template_arg, args): - var = cg.new_Pvariable(action_id, template_arg) - await cg.register_parented(var, config[CONF_ID]) - return var +def _register_command_actions(): + async def handler(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + announcement = await cg.templatable(config[CONF_ANNOUNCEMENT], args, cg.bool_) + cg.add(var.set_announcement(announcement)) + return var + + for action_name in _COMMAND_ACTIONS: + class_name = f"{_snake_to_camel(action_name)}Action" + action_class = media_player_ns.class_( + class_name, automation.Action, cg.Parented.template(MediaPlayer) + ) + automation.register_action( + f"media_player.{action_name}", action_class, MEDIA_PLAYER_ACTION_SCHEMA + )(handler) + + +_register_command_actions() + + +def _register_state_conditions(): + async def handler(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + + for condition_name in _STATE_CONDITIONS: + class_name = f"Is{_snake_to_camel(condition_name)}Condition" + condition_class = media_player_ns.class_(class_name, automation.Condition) + automation.register_condition( + f"media_player.is_{condition_name}", + condition_class, + MEDIA_PLAYER_CONDITION_SCHEMA, + )(handler) + + +_register_state_conditions() @automation.register_action( diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 50e7693cb5..90e7bf75b5 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -32,6 +32,28 @@ template<typename... Ts> using TurnOnAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_TURN_ON, Ts...>; template<typename... Ts> using TurnOffAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_TURN_OFF, Ts...>; +template<typename... Ts> +using NextAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_NEXT, Ts...>; +template<typename... Ts> +using PreviousAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PREVIOUS, Ts...>; +template<typename... Ts> +using MuteAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_MUTE, Ts...>; +template<typename... Ts> +using UnmuteAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_UNMUTE, Ts...>; +template<typename... Ts> +using RepeatOffAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_OFF, Ts...>; +template<typename... Ts> +using RepeatOneAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ONE, Ts...>; +template<typename... Ts> +using RepeatAllAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_REPEAT_ALL, Ts...>; +template<typename... Ts> +using ShuffleAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_SHUFFLE, Ts...>; +template<typename... Ts> +using UnshuffleAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_UNSHUFFLE, Ts...>; +template<typename... Ts> +using GroupJoinAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_GROUP_JOIN, Ts...>; +template<typename... Ts> +using ClearPlaylistAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST, Ts...>; template<typename... Ts> class PlayMediaAction : public Action<Ts...>, public Parented<MediaPlayer> { TEMPLATABLE_VALUE(std::string, media_url) @@ -105,5 +127,10 @@ template<typename... Ts> class IsOffCondition : public Condition<Ts...>, public bool check(const Ts &...x) override { return this->parent_->state == MediaPlayerState::MEDIA_PLAYER_STATE_OFF; } }; +template<typename... Ts> class IsMutedCondition : public Condition<Ts...>, public Parented<MediaPlayer> { + public: + bool check(const Ts &...x) override { return this->parent_->is_muted(); } +}; + } // namespace media_player } // namespace esphome diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 17d9b054da..a53d598b0f 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -60,11 +60,39 @@ const char *media_player_command_to_string(MediaPlayerCommand command) { return "TURN_ON"; case MEDIA_PLAYER_COMMAND_TURN_OFF: return "TURN_OFF"; + case MEDIA_PLAYER_COMMAND_NEXT: + return "NEXT"; + case MEDIA_PLAYER_COMMAND_PREVIOUS: + return "PREVIOUS"; + case MEDIA_PLAYER_COMMAND_REPEAT_ALL: + return "REPEAT_ALL"; + case MEDIA_PLAYER_COMMAND_SHUFFLE: + return "SHUFFLE"; + case MEDIA_PLAYER_COMMAND_UNSHUFFLE: + return "UNSHUFFLE"; + case MEDIA_PLAYER_COMMAND_GROUP_JOIN: + return "GROUP_JOIN"; default: return "UNKNOWN"; } } +void MediaPlayerTraits::set_supports_pause(bool supports_pause) { + if (supports_pause) { + this->feature_flags_ |= MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY; + } else { + this->feature_flags_ &= ~(MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY); + } +} + +void MediaPlayerTraits::set_supports_turn_off_on(bool supports_turn_off_on) { + if (supports_turn_off_on) { + this->feature_flags_ |= MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON; + } else { + this->feature_flags_ &= ~(MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON); + } +} + void MediaPlayerCall::validate_() { if (this->media_url_.has_value()) { if (this->command_.has_value() && this->command_.value() != MEDIA_PLAYER_COMMAND_ENQUEUE) { @@ -125,6 +153,30 @@ MediaPlayerCall &MediaPlayerCall::set_command(const char *command) { this->set_command(MEDIA_PLAYER_COMMAND_TURN_ON); } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TURN_OFF")) == 0) { this->set_command(MEDIA_PLAYER_COMMAND_TURN_OFF); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("VOLUME_UP")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_VOLUME_UP); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("VOLUME_DOWN")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_VOLUME_DOWN); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("ENQUEUE")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_ENQUEUE); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_ONE")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_ONE); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_OFF")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_OFF); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("REPEAT_ALL")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_REPEAT_ALL); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("CLEAR_PLAYLIST")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("NEXT")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_NEXT); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("PREVIOUS")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_PREVIOUS); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("SHUFFLE")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_SHUFFLE); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("UNSHUFFLE")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_UNSHUFFLE); + } else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("GROUP_JOIN")) == 0) { + this->set_command(MEDIA_PLAYER_COMMAND_GROUP_JOIN); } else { ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command); } diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index f75a68dd85..3509747718 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -58,6 +58,12 @@ enum MediaPlayerCommand : uint8_t { MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST = 11, MEDIA_PLAYER_COMMAND_TURN_ON = 12, MEDIA_PLAYER_COMMAND_TURN_OFF = 13, + MEDIA_PLAYER_COMMAND_NEXT = 14, + MEDIA_PLAYER_COMMAND_PREVIOUS = 15, + MEDIA_PLAYER_COMMAND_REPEAT_ALL = 16, + MEDIA_PLAYER_COMMAND_SHUFFLE = 17, + MEDIA_PLAYER_COMMAND_UNSHUFFLE = 18, + MEDIA_PLAYER_COMMAND_GROUP_JOIN = 19, }; const char *media_player_command_to_string(MediaPlayerCommand command); @@ -74,38 +80,40 @@ struct MediaPlayerSupportedFormat { uint32_t sample_bytes; }; +// Base features always reported for all media players +static constexpr uint32_t BASE_MEDIA_PLAYER_FEATURES = + MediaPlayerEntityFeature::PLAY_MEDIA | MediaPlayerEntityFeature::BROWSE_MEDIA | MediaPlayerEntityFeature::STOP | + MediaPlayerEntityFeature::VOLUME_SET | MediaPlayerEntityFeature::VOLUME_MUTE | + MediaPlayerEntityFeature::MEDIA_ANNOUNCE; + class MediaPlayer; class MediaPlayerTraits { public: MediaPlayerTraits() = default; - void set_supports_pause(bool supports_pause) { this->supports_pause_ = supports_pause; } - bool get_supports_pause() const { return this->supports_pause_; } - - void set_supports_turn_off_on(bool supports_turn_off_on) { this->supports_turn_off_on_ = supports_turn_off_on; } - bool get_supports_turn_off_on() const { return this->supports_turn_off_on_; } + uint32_t get_feature_flags() const { return this->feature_flags_; } + void add_feature_flags(uint32_t feature_flags) { this->feature_flags_ |= feature_flags; } + void clear_feature_flags(uint32_t feature_flags) { this->feature_flags_ &= ~feature_flags; } + // Returns true only if all specified flags are set + bool has_feature_flags(uint32_t feature_flags) const { + return (this->feature_flags_ & feature_flags) == feature_flags; + } std::vector<MediaPlayerSupportedFormat> &get_supported_formats() { return this->supported_formats_; } - uint32_t get_feature_flags() const { - uint32_t flags = 0; - flags |= MediaPlayerEntityFeature::PLAY_MEDIA | MediaPlayerEntityFeature::BROWSE_MEDIA | - MediaPlayerEntityFeature::STOP | MediaPlayerEntityFeature::VOLUME_SET | - MediaPlayerEntityFeature::VOLUME_MUTE | MediaPlayerEntityFeature::MEDIA_ANNOUNCE; - if (this->get_supports_pause()) { - flags |= MediaPlayerEntityFeature::PAUSE | MediaPlayerEntityFeature::PLAY; - } - if (this->get_supports_turn_off_on()) { - flags |= MediaPlayerEntityFeature::TURN_OFF | MediaPlayerEntityFeature::TURN_ON; - } - return flags; + // Legacy setters/getters are kept for backward compatibility + void set_supports_pause(bool supports_pause); + bool get_supports_pause() const { return this->has_feature_flags(MediaPlayerEntityFeature::PAUSE); } + + void set_supports_turn_off_on(bool supports_turn_off_on); + bool get_supports_turn_off_on() const { + return this->has_feature_flags(MediaPlayerEntityFeature::TURN_ON | MediaPlayerEntityFeature::TURN_OFF); } protected: std::vector<MediaPlayerSupportedFormat> supported_formats_{}; - bool supports_pause_{false}; - bool supports_turn_off_on_{false}; + uint32_t feature_flags_{BASE_MEDIA_PLAYER_FEATURES}; }; class MediaPlayerCall { diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml index 763bc231c0..c83ee89ad4 100644 --- a/tests/components/media_player/common.yaml +++ b/tests/components/media_player/common.yaml @@ -23,8 +23,27 @@ media_player: - media_player.stop: - media_player.stop: announcement: true + on_announcement: + - media_player.play: + on_turn_on: + - media_player.play: + on_turn_off: + - media_player.stop: on_pause: - media_player.toggle: + - media_player.turn_on: + - media_player.turn_off: + - media_player.next: + - media_player.previous: + - media_player.mute: + - media_player.unmute: + - media_player.repeat_off: + - media_player.repeat_one: + - media_player.repeat_all: + - media_player.shuffle: + - media_player.unshuffle: + - media_player.group_join: + - media_player.clear_playlist: - wait_until: media_player.is_idle: - wait_until: @@ -33,6 +52,12 @@ media_player: media_player.is_announcing: - wait_until: media_player.is_paused: + - wait_until: + media_player.is_on: + - wait_until: + media_player.is_off: + - wait_until: + media_player.is_muted: - media_player.volume_up: - media_player.volume_down: - media_player.volume_set: 50% From ba7134ee3f870ce00d2990d84b142b734028330f Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Feb 2026 21:51:16 -0600 Subject: [PATCH 0772/2030] [mdns] add Sendspin advertisement support (#14013) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/mdns/__init__.py | 2 +- esphome/components/mdns/mdns_component.cpp | 19 ++++++++++++++++++- esphome/core/defines.h | 2 ++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index 3088d8ad7e..f87f929615 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -21,7 +21,7 @@ DEPENDENCIES = ["network"] # Components that create mDNS services at runtime # IMPORTANT: If you add a new component here, you must also update the corresponding # #ifdef blocks in mdns_component.cpp compile_records_() method -COMPONENTS_WITH_MDNS_SERVICES = ("api", "prometheus", "web_server") +COMPONENTS_WITH_MDNS_SERVICES = ("api", "prometheus", "sendspin", "web_server") mdns_ns = cg.esphome_ns.namespace("mdns") MDNSComponent = mdns_ns.class_("MDNSComponent", cg.Component) diff --git a/esphome/components/mdns/mdns_component.cpp b/esphome/components/mdns/mdns_component.cpp index 47db92610a..5e5e1279d9 100644 --- a/esphome/components/mdns/mdns_component.cpp +++ b/esphome/components/mdns/mdns_component.cpp @@ -29,6 +29,10 @@ static const char *const TAG = "mdns"; #define USE_WEBSERVER_PORT 80 // NOLINT #endif +#ifndef USE_SENDSPIN_PORT +#define USE_SENDSPIN_PORT 8928 // NOLINT +#endif + // Define all constant strings using the macro MDNS_STATIC_CONST_CHAR(SERVICE_TCP, "_tcp"); @@ -150,6 +154,18 @@ void MDNSComponent::compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUN prom_service.port = USE_WEBSERVER_PORT; #endif +#ifdef USE_SENDSPIN + MDNS_STATIC_CONST_CHAR(SERVICE_SENDSPIN, "_sendspin"); + MDNS_STATIC_CONST_CHAR(TXT_SENDSPIN_PATH, "path"); + MDNS_STATIC_CONST_CHAR(VALUE_SENDSPIN_PATH, "/sendspin"); + + auto &sendspin_service = services.emplace_next(); + sendspin_service.service_type = MDNS_STR(SERVICE_SENDSPIN); + sendspin_service.proto = MDNS_STR(SERVICE_TCP); + sendspin_service.port = USE_SENDSPIN_PORT; + sendspin_service.txt_records = {{MDNS_STR(TXT_SENDSPIN_PATH), MDNS_STR(VALUE_SENDSPIN_PATH)}}; +#endif + #ifdef USE_WEBSERVER MDNS_STATIC_CONST_CHAR(SERVICE_HTTP, "_http"); @@ -159,7 +175,8 @@ void MDNSComponent::compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUN web_service.port = USE_WEBSERVER_PORT; #endif -#if !defined(USE_API) && !defined(USE_PROMETHEUS) && !defined(USE_WEBSERVER) && !defined(USE_MDNS_EXTRA_SERVICES) +#if !defined(USE_API) && !defined(USE_PROMETHEUS) && !defined(USE_SENDSPIN) && !defined(USE_WEBSERVER) && \ + !defined(USE_MDNS_EXTRA_SERVICES) MDNS_STATIC_CONST_CHAR(SERVICE_HTTP, "_http"); MDNS_STATIC_CONST_CHAR(TXT_VERSION, "version"); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index bcafcb4c60..a70c6cd0d0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -210,6 +210,8 @@ #define USE_ESP32_IMPROV_NEXT_URL #define USE_MICROPHONE #define USE_PSRAM +#define USE_SENDSPIN +#define USE_SENDSPIN_PORT 8928 // NOLINT #define USE_SOCKET_IMPL_BSD_SOCKETS #define USE_SOCKET_SELECT_SUPPORT #define USE_WAKE_LOOP_THREADSAFE From eefad194d06241f0594d1ae97a18c6cad618863a Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Feb 2026 21:51:33 -0600 Subject: [PATCH 0773/2030] [audio, speaker] Add support for decoding Ogg Opus files (#13967) --- esphome/components/audio/__init__.py | 42 ++++++++++ esphome/components/audio/audio.cpp | 4 + esphome/components/audio/audio.h | 3 + esphome/components/audio/audio_decoder.cpp | 60 +++++++++++++- esphome/components/audio/audio_decoder.h | 15 +++- esphome/components/audio/audio_reader.cpp | 13 +++ .../speaker/media_player/__init__.py | 82 ++++++++++++++++--- .../speaker/media_player/audio_pipeline.cpp | 10 +++ esphome/core/defines.h | 1 + esphome/idf_component.yml | 2 + .../speaker/audio_dac.esp32-ard.yaml | 10 --- .../speaker/common-media_player.yaml | 7 ++ .../speaker/media_player.esp32-s3-idf.yaml | 9 -- ...idf.yaml => test-audio_dac.esp32-idf.yaml} | 0 ....yaml => test-media_player.esp32-idf.yaml} | 0 tests/components/speaker/test.esp32-ard.yaml | 10 --- 16 files changed, 222 insertions(+), 46 deletions(-) delete mode 100644 tests/components/speaker/audio_dac.esp32-ard.yaml delete mode 100644 tests/components/speaker/media_player.esp32-s3-idf.yaml rename tests/components/speaker/{audio_dac.esp32-idf.yaml => test-audio_dac.esp32-idf.yaml} (100%) rename tests/components/speaker/{media_player.esp32-idf.yaml => test-media_player.esp32-idf.yaml} (100%) delete mode 100644 tests/components/speaker/test.esp32-ard.yaml diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index f48b776ddd..d8d426ec63 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -1,10 +1,14 @@ +from dataclasses import dataclass + import esphome.codegen as cg from esphome.components.esp32 import add_idf_component, include_builtin_idf_component import esphome.config_validation as cv from esphome.const import CONF_BITS_PER_SAMPLE, CONF_NUM_CHANNELS, CONF_SAMPLE_RATE +from esphome.core import CORE import esphome.final_validate as fv CODEOWNERS = ["@kahrendt"] +DOMAIN = "audio" audio_ns = cg.esphome_ns.namespace("audio") AudioFile = audio_ns.struct("AudioFile") @@ -14,9 +18,38 @@ AUDIO_FILE_TYPE_ENUM = { "WAV": AudioFileType.WAV, "MP3": AudioFileType.MP3, "FLAC": AudioFileType.FLAC, + "OPUS": AudioFileType.OPUS, } +@dataclass +class AudioData: + flac_support: bool = False + mp3_support: bool = False + opus_support: bool = False + + +def _get_data() -> AudioData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = AudioData() + return CORE.data[DOMAIN] + + +def request_flac_support() -> None: + """Request FLAC codec support for audio decoding.""" + _get_data().flac_support = True + + +def request_mp3_support() -> None: + """Request MP3 codec support for audio decoding.""" + _get_data().mp3_support = True + + +def request_opus_support() -> None: + """Request Opus codec support for audio decoding.""" + _get_data().opus_support = True + + CONF_MIN_BITS_PER_SAMPLE = "min_bits_per_sample" CONF_MAX_BITS_PER_SAMPLE = "max_bits_per_sample" CONF_MIN_CHANNELS = "min_channels" @@ -173,3 +206,12 @@ async def to_code(config): name="esphome/esp-audio-libs", ref="2.0.3", ) + + data = _get_data() + if data.flac_support: + cg.add_define("USE_AUDIO_FLAC_SUPPORT") + if data.mp3_support: + cg.add_define("USE_AUDIO_MP3_SUPPORT") + if data.opus_support: + cg.add_define("USE_AUDIO_OPUS_SUPPORT") + add_idf_component(name="esphome/micro-opus", ref="0.3.3") diff --git a/esphome/components/audio/audio.cpp b/esphome/components/audio/audio.cpp index 9cc9b7d0da..40592f6107 100644 --- a/esphome/components/audio/audio.cpp +++ b/esphome/components/audio/audio.cpp @@ -46,6 +46,10 @@ const char *audio_file_type_to_string(AudioFileType file_type) { #ifdef USE_AUDIO_MP3_SUPPORT case AudioFileType::MP3: return "MP3"; +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + case AudioFileType::OPUS: + return "OPUS"; #endif case AudioFileType::WAV: return "WAV"; diff --git a/esphome/components/audio/audio.h b/esphome/components/audio/audio.h index e01d7eb101..7d7db9e944 100644 --- a/esphome/components/audio/audio.h +++ b/esphome/components/audio/audio.h @@ -112,6 +112,9 @@ enum class AudioFileType : uint8_t { #endif #ifdef USE_AUDIO_MP3_SUPPORT MP3, +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + OPUS, #endif WAV, }; diff --git a/esphome/components/audio/audio_decoder.cpp b/esphome/components/audio/audio_decoder.cpp index 8f514468c4..ee6d7d0a15 100644 --- a/esphome/components/audio/audio_decoder.cpp +++ b/esphome/components/audio/audio_decoder.cpp @@ -3,10 +3,13 @@ #ifdef USE_ESP32 #include "esphome/core/hal.h" +#include "esphome/core/log.h" namespace esphome { namespace audio { +static const char *const TAG = "audio.decoder"; + static const uint32_t DECODING_TIMEOUT_MS = 50; // The decode function will yield after this duration static const uint32_t READ_WRITE_TIMEOUT_MS = 20; // Timeout for transferring audio data @@ -79,6 +82,14 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) { // Always reallocate the output transfer buffer to the smallest necessary size this->output_transfer_buffer_->reallocate(this->free_buffer_required_); break; +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + case AudioFileType::OPUS: + this->opus_decoder_ = make_unique<micro_opus::OggOpusDecoder>(); + this->free_buffer_required_ = + this->output_transfer_buffer_->capacity(); // Adjusted and reallocated after reading the header + this->decoder_buffers_internally_ = true; + break; #endif case AudioFileType::WAV: this->wav_decoder_ = make_unique<esp_audio_libs::wav_decoder::WAVDecoder>(); @@ -158,8 +169,9 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { // Decode more audio // Only shift data on the first loop iteration to avoid unnecessary, slow moves - size_t bytes_read = this->input_transfer_buffer_->transfer_data_from_source(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), - first_loop_iteration); + // If the decoder buffers internally, then never shift + size_t bytes_read = this->input_transfer_buffer_->transfer_data_from_source( + pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), first_loop_iteration && !this->decoder_buffers_internally_); if (!first_loop_iteration && (this->input_transfer_buffer_->available() < bytes_processed)) { // Less data is available than what was processed in last iteration, so don't attempt to decode. @@ -195,6 +207,11 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { case AudioFileType::MP3: state = this->decode_mp3_(); break; +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + case AudioFileType::OPUS: + state = this->decode_opus_(); + break; #endif case AudioFileType::WAV: state = this->decode_wav_(); @@ -339,6 +356,45 @@ FileDecoderState AudioDecoder::decode_mp3_() { } #endif +#ifdef USE_AUDIO_OPUS_SUPPORT +FileDecoderState AudioDecoder::decode_opus_() { + bool processed_header = this->opus_decoder_->is_initialized(); + + size_t bytes_consumed, samples_decoded; + + micro_opus::OggOpusResult result = this->opus_decoder_->decode( + this->input_transfer_buffer_->get_buffer_start(), this->input_transfer_buffer_->available(), + this->output_transfer_buffer_->get_buffer_end(), this->output_transfer_buffer_->free(), bytes_consumed, + samples_decoded); + + if (result == micro_opus::OGG_OPUS_OK) { + if (!processed_header && this->opus_decoder_->is_initialized()) { + // Header processed and stream info is available + this->audio_stream_info_ = + audio::AudioStreamInfo(this->opus_decoder_->get_bit_depth(), this->opus_decoder_->get_channels(), + this->opus_decoder_->get_sample_rate()); + } + if (samples_decoded > 0 && this->audio_stream_info_.has_value()) { + // Some audio was processed + this->output_transfer_buffer_->increase_buffer_length( + this->audio_stream_info_.value().frames_to_bytes(samples_decoded)); + } + this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed); + } else if (result == micro_opus::OGG_OPUS_OUTPUT_BUFFER_TOO_SMALL) { + // Reallocate to decode the packet on the next call + this->free_buffer_required_ = this->opus_decoder_->get_required_output_buffer_size(); + if (!this->output_transfer_buffer_->reallocate(this->free_buffer_required_)) { + // Couldn't reallocate output buffer + return FileDecoderState::FAILED; + } + } else { + ESP_LOGE(TAG, "Opus decoder failed: %" PRId8, result); + return FileDecoderState::POTENTIALLY_FAILED; + } + return FileDecoderState::MORE_TO_PROCESS; +} +#endif + FileDecoderState AudioDecoder::decode_wav_() { if (!this->audio_stream_info_.has_value()) { // Header hasn't been processed diff --git a/esphome/components/audio/audio_decoder.h b/esphome/components/audio/audio_decoder.h index 2ca1d623fe..cad16110ae 100644 --- a/esphome/components/audio/audio_decoder.h +++ b/esphome/components/audio/audio_decoder.h @@ -24,6 +24,11 @@ #endif #include <wav_decoder.h> +// micro-opus +#ifdef USE_AUDIO_OPUS_SUPPORT +#include <micro_opus/ogg_opus_decoder.h> +#endif + namespace esphome { namespace audio { @@ -47,7 +52,7 @@ class AudioDecoder { * @brief Class that facilitates decoding an audio file. * The audio file is read from a ring buffer source, decoded, and sent to an audio sink (ring buffer or speaker * component). - * Supports wav, flac, and mp3 formats. + * Supports wav, flac, mp3, and ogg opus formats. */ public: /// @brief Allocates the input and output transfer buffers @@ -55,7 +60,7 @@ class AudioDecoder { /// @param output_buffer_size Size of the output transfer buffer in bytes. AudioDecoder(size_t input_buffer_size, size_t output_buffer_size); - /// @brief Deallocates the MP3 decoder (the flac and wav decoders are deallocated automatically) + /// @brief Deallocates the MP3 decoder (the flac, opus, and wav decoders are deallocated automatically) ~AudioDecoder(); /// @brief Adds a source ring buffer for raw file data. Takes ownership of the ring buffer in a shared_ptr. @@ -108,6 +113,10 @@ class AudioDecoder { #ifdef USE_AUDIO_MP3_SUPPORT FileDecoderState decode_mp3_(); esp_audio_libs::helix_decoder::HMP3Decoder mp3_decoder_; +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + FileDecoderState decode_opus_(); + std::unique_ptr<micro_opus::OggOpusDecoder> opus_decoder_; #endif FileDecoderState decode_wav_(); @@ -124,6 +133,8 @@ class AudioDecoder { bool end_of_file_{false}; bool wav_has_known_end_{false}; + bool decoder_buffers_internally_{false}; + bool pause_output_{false}; uint32_t accumulated_frames_written_{0}; diff --git a/esphome/components/audio/audio_reader.cpp b/esphome/components/audio/audio_reader.cpp index 4e4bd31f9b..78d69d7a39 100644 --- a/esphome/components/audio/audio_reader.cpp +++ b/esphome/components/audio/audio_reader.cpp @@ -197,6 +197,11 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) { else if (str_endswith_ignore_case(url, ".flac")) { file_type = AudioFileType::FLAC; } +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + else if (str_endswith_ignore_case(url, ".opus")) { + file_type = AudioFileType::OPUS; + } #endif else { file_type = AudioFileType::NONE; @@ -241,6 +246,14 @@ AudioFileType AudioReader::get_audio_type(const char *content_type) { if (strcasecmp(content_type, "audio/flac") == 0 || strcasecmp(content_type, "audio/x-flac") == 0) { return AudioFileType::FLAC; } +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + // Match "audio/ogg" with a codecs parameter containing "opus" + // Valid forms: audio/ogg;codecs=opus, audio/ogg; codecs="opus", etc. + // Plain "audio/ogg" without a codecs parameter is not matched, as those are almost always Ogg Vorbis streams + if (strncasecmp(content_type, "audio/ogg", 9) == 0 && strcasestr(content_type + 9, "opus") != nullptr) { + return AudioFileType::OPUS; + } #endif return AudioFileType::NONE; } diff --git a/esphome/components/speaker/media_player/__init__.py b/esphome/components/speaker/media_player/__init__.py index 034312236c..b302bd9b23 100644 --- a/esphome/components/speaker/media_player/__init__.py +++ b/esphome/components/speaker/media_player/__init__.py @@ -26,7 +26,6 @@ from esphome.const import ( from esphome.core import CORE, HexInt from esphome.core.entity_helpers import inherit_property_from from esphome.external_files import download_content -from esphome.final_validate import full_config _LOGGER = logging.getLogger(__name__) @@ -37,6 +36,10 @@ DEPENDENCIES = ["network"] CODEOWNERS = ["@kahrendt", "@synesthesiam"] DOMAIN = "media_player" +CODEC_SUPPORT_ALL = "all" +CODEC_SUPPORT_NEEDED = "needed" +CODEC_SUPPORT_NONE = "none" + TYPE_LOCAL = "local" TYPE_WEB = "web" @@ -110,6 +113,8 @@ def _get_supported_format_struct(pipeline, type): args.append(("format", "flac")) elif pipeline[CONF_FORMAT] == "MP3": args.append(("format", "mp3")) + elif pipeline[CONF_FORMAT] == "OPUS": + args.append(("format", "opus")) elif pipeline[CONF_FORMAT] == "WAV": args.append(("format", "wav")) @@ -173,6 +178,13 @@ def _read_audio_file_and_type(file_config): media_file_type = audio.AUDIO_FILE_TYPE_ENUM["MP3"] elif file_type in ("flac"): media_file_type = audio.AUDIO_FILE_TYPE_ENUM["FLAC"] + elif ( + file_type in ("ogg") + and len(data) >= 36 + and data.startswith(b"OggS") + and data[28:36] == b"OpusHead" + ): + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["OPUS"] return data, media_file_type @@ -199,6 +211,10 @@ def _validate_pipeline(config): inherit_property_from(CONF_NUM_CHANNELS, CONF_SPEAKER)(config) inherit_property_from(CONF_SAMPLE_RATE, CONF_SPEAKER)(config) + # Opus only supports 48 kHz + if config.get(CONF_FORMAT) == "OPUS" and config.get(CONF_SAMPLE_RATE) != 48000: + raise cv.Invalid("Opus only supports a sample rate of 48000 Hz") + # Validate the transcoder settings is compatible with the speaker audio.final_validate_audio_schema( "speaker media_player", @@ -225,12 +241,27 @@ def _validate_repeated_speaker(config): def _final_validate(config): - # Default to using codec if psram is enabled - if (use_codec := config.get(CONF_CODEC_SUPPORT_ENABLED)) is None: - use_codec = psram.DOMAIN in full_config.get() - conf_id = config[CONF_ID].id - core_data = CORE.data.setdefault(DOMAIN, {conf_id: {}}) - core_data[conf_id][CONF_CODEC_SUPPORT_ENABLED] = use_codec + # Normalize boolean values to string equivalents + codec_mode = config[CONF_CODEC_SUPPORT_ENABLED] + if codec_mode is True: + codec_mode = CODEC_SUPPORT_ALL + elif codec_mode is False: + codec_mode = CODEC_SUPPORT_NONE + + use_codec = codec_mode != CODEC_SUPPORT_NONE + + # In "needed" mode, collect formats from pipelines and files + needed_formats = set() + need_all = False + if codec_mode == CODEC_SUPPORT_NEEDED: + for pipeline_key in (CONF_ANNOUNCEMENT_PIPELINE, CONF_MEDIA_PIPELINE): + if pipeline := config.get(pipeline_key): + fmt = pipeline[CONF_FORMAT] + if fmt == "NONE": + # No preferred format means any format could arrive + need_all = True + else: + needed_formats.add(fmt) for file_config in config.get(CONF_FILES, []): _, media_file_type = _read_audio_file_and_type(file_config) @@ -243,6 +274,26 @@ def _final_validate(config): raise cv.Invalid( f"Unsupported local media file type, set {CONF_CODEC_SUPPORT_ENABLED} to true or convert the media file to wav" ) + # In "needed" mode, add file format to needed codecs + if codec_mode == CODEC_SUPPORT_NEEDED: + for fmt_name, fmt_enum in audio.AUDIO_FILE_TYPE_ENUM.items(): + if str(media_file_type) == str(fmt_enum): + if fmt_name not in ("WAV", "NONE"): + needed_formats.add(fmt_name) + break + + # Request codec support + if codec_mode == CODEC_SUPPORT_ALL or need_all: + audio.request_flac_support() + audio.request_mp3_support() + audio.request_opus_support() + elif codec_mode == CODEC_SUPPORT_NEEDED: + if "FLAC" in needed_formats: + audio.request_flac_support() + if "MP3" in needed_formats: + audio.request_mp3_support() + if "OPUS" in needed_formats: + audio.request_opus_support() return config @@ -307,7 +358,17 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_BUFFER_SIZE, default=1000000): cv.int_range( min=4000, max=4000000 ), - cv.Optional(CONF_CODEC_SUPPORT_ENABLED): cv.boolean, + cv.Optional( + CONF_CODEC_SUPPORT_ENABLED, default=CODEC_SUPPORT_NEEDED + ): cv.Any( + cv.boolean, + cv.one_of( + CODEC_SUPPORT_ALL, + CODEC_SUPPORT_NEEDED, + CODEC_SUPPORT_NONE, + lower=True, + ), + ), cv.Optional(CONF_FILES): cv.ensure_list(MEDIA_FILE_TYPE_SCHEMA), cv.Optional(CONF_TASK_STACK_IN_PSRAM): cv.All( cv.boolean, cv.requires_component(psram.DOMAIN) @@ -340,11 +401,6 @@ FINAL_VALIDATE_SCHEMA = cv.All( async def to_code(config): - if CORE.data[DOMAIN][config[CONF_ID].id][CONF_CODEC_SUPPORT_ENABLED]: - # Compile all supported audio codecs - cg.add_define("USE_AUDIO_FLAC_SUPPORT", True) - cg.add_define("USE_AUDIO_MP3_SUPPORT", True) - var = await media_player.new_media_player(config) await cg.register_component(var, config) diff --git a/esphome/components/speaker/media_player/audio_pipeline.cpp b/esphome/components/speaker/media_player/audio_pipeline.cpp index 8be37d740a..177743feb1 100644 --- a/esphome/components/speaker/media_player/audio_pipeline.cpp +++ b/esphome/components/speaker/media_player/audio_pipeline.cpp @@ -13,7 +13,12 @@ namespace speaker { static const uint32_t INITIAL_BUFFER_MS = 1000; // Start playback after buffering this duration of the file static const uint32_t READ_TASK_STACK_SIZE = 5 * 1024; +// Opus decoding uses more stack than other codecs +#ifdef USE_AUDIO_OPUS_SUPPORT +static const uint32_t DECODE_TASK_STACK_SIZE = 5 * 1024; +#else static const uint32_t DECODE_TASK_STACK_SIZE = 3 * 1024; +#endif static const uint32_t INFO_ERROR_QUEUE_COUNT = 5; @@ -552,6 +557,11 @@ void AudioPipeline::decode_task(void *params) { case audio::AudioFileType::FLAC: initial_bytes_to_buffer /= 2; // Estimate the FLAC compression factor is 2 break; +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + case audio::AudioFileType::OPUS: + initial_bytes_to_buffer /= 8; // Estimate the Opus compression factor is 8 + break; #endif default: break; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a70c6cd0d0..5559ec88d0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -130,6 +130,7 @@ #define USE_AUDIO_DAC #define USE_AUDIO_FLAC_SUPPORT #define USE_AUDIO_MP3_SUPPORT +#define USE_AUDIO_OPUS_SUPPORT #define USE_API #define USE_API_CLIENT_CONNECTED_TRIGGER #define USE_API_CLIENT_DISCONNECTED_TRIGGER diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index f39ea9b3ae..83b2d9d95c 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -3,6 +3,8 @@ dependencies: version: "7.4.2" esphome/esp-audio-libs: version: 2.0.3 + esphome/micro-opus: + version: 0.3.3 espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: diff --git a/tests/components/speaker/audio_dac.esp32-ard.yaml b/tests/components/speaker/audio_dac.esp32-ard.yaml deleted file mode 100644 index 3f5d1bba7c..0000000000 --- a/tests/components/speaker/audio_dac.esp32-ard.yaml +++ /dev/null @@ -1,10 +0,0 @@ -substitutions: - i2s_bclk_pin: GPIO27 - i2s_lrclk_pin: GPIO26 - i2s_mclk_pin: GPIO25 - i2s_dout_pin: GPIO23 - -packages: - i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml - -<<: !include common-audio_dac.yaml diff --git a/tests/components/speaker/common-media_player.yaml b/tests/components/speaker/common-media_player.yaml index edc9f670fc..c958c0d912 100644 --- a/tests/components/speaker/common-media_player.yaml +++ b/tests/components/speaker/common-media_player.yaml @@ -1,5 +1,11 @@ <<: !include common.yaml +wifi: + ap: + +psram: + mode: quad + media_player: - platform: speaker id: speaker_media_player_id @@ -10,3 +16,4 @@ media_player: volume_max: 0.95 volume_min: 0.0 task_stack_in_psram: true + codec_support_enabled: all diff --git a/tests/components/speaker/media_player.esp32-s3-idf.yaml b/tests/components/speaker/media_player.esp32-s3-idf.yaml deleted file mode 100644 index b3eec04d23..0000000000 --- a/tests/components/speaker/media_player.esp32-s3-idf.yaml +++ /dev/null @@ -1,9 +0,0 @@ -substitutions: - scl_pin: GPIO2 - sda_pin: GPIO3 - i2s_bclk_pin: GPIO4 - i2s_lrclk_pin: GPIO5 - i2s_mclk_pin: GPIO6 - i2s_dout_pin: GPIO7 - -<<: !include common-media_player.yaml diff --git a/tests/components/speaker/audio_dac.esp32-idf.yaml b/tests/components/speaker/test-audio_dac.esp32-idf.yaml similarity index 100% rename from tests/components/speaker/audio_dac.esp32-idf.yaml rename to tests/components/speaker/test-audio_dac.esp32-idf.yaml diff --git a/tests/components/speaker/media_player.esp32-idf.yaml b/tests/components/speaker/test-media_player.esp32-idf.yaml similarity index 100% rename from tests/components/speaker/media_player.esp32-idf.yaml rename to tests/components/speaker/test-media_player.esp32-idf.yaml diff --git a/tests/components/speaker/test.esp32-ard.yaml b/tests/components/speaker/test.esp32-ard.yaml deleted file mode 100644 index 13350cd097..0000000000 --- a/tests/components/speaker/test.esp32-ard.yaml +++ /dev/null @@ -1,10 +0,0 @@ -substitutions: - i2s_bclk_pin: GPIO27 - i2s_lrclk_pin: GPIO26 - i2s_mclk_pin: GPIO25 - i2s_dout_pin: GPIO4 - -packages: - i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml - -<<: !include common.yaml From 4d05e4d5765c037f234ddebb8442af2007c4fc60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20H=C3=B6rsken?= <mback2k@users.noreply.github.com> Date: Thu, 19 Feb 2026 04:52:38 +0100 Subject: [PATCH 0774/2030] [esp32_camera] Add support for sensors without JPEG support (#9496) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/esp32_camera/__init__.py | 50 ++++- .../components/esp32_camera/esp32_camera.cpp | 207 +++++++++++++----- .../components/esp32_camera/esp32_camera.h | 14 ++ esphome/core/defines.h | 1 + .../common/i2c_camera/esp32-idf.yaml | 1 + 5 files changed, 212 insertions(+), 61 deletions(-) diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index db6244fb3f..3a5d87792b 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -22,8 +22,10 @@ from esphome.const import ( CONF_TRIGGER_ID, CONF_VSYNC_PIN, ) +from esphome.core import CORE from esphome.core.entity_helpers import setup_entity import esphome.final_validate as fv +from esphome.types import ConfigType _LOGGER = logging.getLogger(__name__) @@ -84,6 +86,18 @@ FRAME_SIZES = { "2560X1920": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_2560X1920, "QSXGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_2560X1920, } +ESP32CameraPixelFormat = esp32_camera_ns.enum("ESP32CameraPixelFormat") +PIXEL_FORMATS = { + "RGB565": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_RGB565, + "YUV422": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_YUV422, + "YUV420": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_YUV420, + "GRAYSCALE": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_GRAYSCALE, + "JPEG": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_JPEG, + "RGB888": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_RGB888, + "RAW": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_RAW, + "RGB444": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_RGB444, + "RGB555": ESP32CameraPixelFormat.ESP32_PIXEL_FORMAT_RGB555, +} ESP32GainControlMode = esp32_camera_ns.enum("ESP32GainControlMode") ENUM_GAIN_CONTROL_MODE = { "MANUAL": ESP32GainControlMode.ESP32_GC_MODE_MANU, @@ -131,6 +145,7 @@ CONF_EXTERNAL_CLOCK = "external_clock" CONF_I2C_PINS = "i2c_pins" CONF_POWER_DOWN_PIN = "power_down_pin" # image +CONF_PIXEL_FORMAT = "pixel_format" CONF_JPEG_QUALITY = "jpeg_quality" CONF_VERTICAL_FLIP = "vertical_flip" CONF_HORIZONTAL_MIRROR = "horizontal_mirror" @@ -171,6 +186,21 @@ def validate_fb_location_(value): return validator(value) +def validate_jpeg_quality(config: ConfigType) -> ConfigType: + quality = config.get(CONF_JPEG_QUALITY) + pixel_format = config.get(CONF_PIXEL_FORMAT, "JPEG") + + if quality == 0: + # Set default JPEG quality if not specified for backwards compatibility + if pixel_format == "JPEG": + config[CONF_JPEG_QUALITY] = 10 + # For pixel formats other than JPEG, the valid 0 means no conversion + elif quality < 6 or quality > 63: + raise cv.Invalid(f"jpeg_quality must be between 6 and 63, got {quality}") + + return config + + CONFIG_SCHEMA = cv.All( cv.ENTITY_BASE_SCHEMA.extend( { @@ -206,7 +236,12 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum( FRAME_SIZES, upper=True ), - cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=6, max=63), + cv.Optional(CONF_PIXEL_FORMAT, default="JPEG"): cv.enum( + PIXEL_FORMATS, upper=True + ), + cv.Optional(CONF_JPEG_QUALITY, default=0): cv.Any( + cv.one_of(0), cv.int_range(min=6, max=63) + ), cv.Optional(CONF_CONTRAST, default=0): camera_range_param, cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param, cv.Optional(CONF_SATURATION, default=0): camera_range_param, @@ -270,11 +305,21 @@ CONFIG_SCHEMA = cv.All( ), } ).extend(cv.COMPONENT_SCHEMA), + validate_jpeg_quality, cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID), ) def _final_validate(config): + # Check psram requirement for non-JPEG formats + if ( + config.get(CONF_PIXEL_FORMAT, "JPEG") != "JPEG" + and psram_domain not in CORE.loaded_integrations + ): + raise cv.Invalid( + f"Non-JPEG pixel formats require the '{psram_domain}' component for JPEG conversion" + ) + if CONF_I2C_PINS not in config: return fconf = fv.full_config.get() @@ -298,6 +343,7 @@ SETTERS = { CONF_RESET_PIN: "set_reset_pin", CONF_POWER_DOWN_PIN: "set_power_down_pin", # image + CONF_PIXEL_FORMAT: "set_pixel_format", CONF_JPEG_QUALITY: "set_jpeg_quality", CONF_VERTICAL_FLIP: "set_vertical_flip", CONF_HORIZONTAL_MIRROR: "set_horizontal_mirror", @@ -351,6 +397,8 @@ async def to_code(config): cg.add(var.set_frame_size(config[CONF_RESOLUTION])) cg.add_define("USE_CAMERA") + if config[CONF_JPEG_QUALITY] != 0 and config[CONF_PIXEL_FORMAT] != "JPEG": + cg.add_define("USE_ESP32_CAMERA_JPEG_CONVERSION") add_idf_component(name="espressif/esp32-camera", ref="2.1.1") add_idf_sdkconfig_option("CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW", True) diff --git a/esphome/components/esp32_camera/esp32_camera.cpp b/esphome/components/esp32_camera/esp32_camera.cpp index cfe06b1673..655ae54f0a 100644 --- a/esphome/components/esp32_camera/esp32_camera.cpp +++ b/esphome/components/esp32_camera/esp32_camera.cpp @@ -16,6 +16,74 @@ static constexpr size_t FRAMEBUFFER_TASK_STACK_SIZE = 1792; static constexpr uint32_t FRAME_LOG_INTERVAL_MS = 60000; #endif +static const char *frame_size_to_str(framesize_t size) { + switch (size) { + case FRAMESIZE_QQVGA: + return "160x120 (QQVGA)"; + case FRAMESIZE_QCIF: + return "176x155 (QCIF)"; + case FRAMESIZE_HQVGA: + return "240x176 (HQVGA)"; + case FRAMESIZE_QVGA: + return "320x240 (QVGA)"; + case FRAMESIZE_CIF: + return "400x296 (CIF)"; + case FRAMESIZE_VGA: + return "640x480 (VGA)"; + case FRAMESIZE_SVGA: + return "800x600 (SVGA)"; + case FRAMESIZE_XGA: + return "1024x768 (XGA)"; + case FRAMESIZE_SXGA: + return "1280x1024 (SXGA)"; + case FRAMESIZE_UXGA: + return "1600x1200 (UXGA)"; + case FRAMESIZE_FHD: + return "1920x1080 (FHD)"; + case FRAMESIZE_P_HD: + return "720x1280 (P_HD)"; + case FRAMESIZE_P_3MP: + return "864x1536 (P_3MP)"; + case FRAMESIZE_QXGA: + return "2048x1536 (QXGA)"; + case FRAMESIZE_QHD: + return "2560x1440 (QHD)"; + case FRAMESIZE_WQXGA: + return "2560x1600 (WQXGA)"; + case FRAMESIZE_P_FHD: + return "1080x1920 (P_FHD)"; + case FRAMESIZE_QSXGA: + return "2560x1920 (QSXGA)"; + default: + return "UNKNOWN"; + } +} + +static const char *pixel_format_to_str(pixformat_t format) { + switch (format) { + case PIXFORMAT_RGB565: + return "RGB565"; + case PIXFORMAT_YUV422: + return "YUV422"; + case PIXFORMAT_YUV420: + return "YUV420"; + case PIXFORMAT_GRAYSCALE: + return "GRAYSCALE"; + case PIXFORMAT_JPEG: + return "JPEG"; + case PIXFORMAT_RGB888: + return "RGB888"; + case PIXFORMAT_RAW: + return "RAW"; + case PIXFORMAT_RGB444: + return "RGB444"; + case PIXFORMAT_RGB555: + return "RGB555"; + default: + return "UNKNOWN"; + } +} + /* ---------------- public API (derivated) ---------------- */ void ESP32Camera::setup() { #ifdef USE_I2C @@ -68,64 +136,9 @@ void ESP32Camera::dump_config() { this->name_.c_str(), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2, conf.pin_d3, conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href, conf.pin_pclk, conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset); - switch (this->config_.frame_size) { - case FRAMESIZE_QQVGA: - ESP_LOGCONFIG(TAG, " Resolution: 160x120 (QQVGA)"); - break; - case FRAMESIZE_QCIF: - ESP_LOGCONFIG(TAG, " Resolution: 176x155 (QCIF)"); - break; - case FRAMESIZE_HQVGA: - ESP_LOGCONFIG(TAG, " Resolution: 240x176 (HQVGA)"); - break; - case FRAMESIZE_QVGA: - ESP_LOGCONFIG(TAG, " Resolution: 320x240 (QVGA)"); - break; - case FRAMESIZE_CIF: - ESP_LOGCONFIG(TAG, " Resolution: 400x296 (CIF)"); - break; - case FRAMESIZE_VGA: - ESP_LOGCONFIG(TAG, " Resolution: 640x480 (VGA)"); - break; - case FRAMESIZE_SVGA: - ESP_LOGCONFIG(TAG, " Resolution: 800x600 (SVGA)"); - break; - case FRAMESIZE_XGA: - ESP_LOGCONFIG(TAG, " Resolution: 1024x768 (XGA)"); - break; - case FRAMESIZE_SXGA: - ESP_LOGCONFIG(TAG, " Resolution: 1280x1024 (SXGA)"); - break; - case FRAMESIZE_UXGA: - ESP_LOGCONFIG(TAG, " Resolution: 1600x1200 (UXGA)"); - break; - case FRAMESIZE_FHD: - ESP_LOGCONFIG(TAG, " Resolution: 1920x1080 (FHD)"); - break; - case FRAMESIZE_P_HD: - ESP_LOGCONFIG(TAG, " Resolution: 720x1280 (P_HD)"); - break; - case FRAMESIZE_P_3MP: - ESP_LOGCONFIG(TAG, " Resolution: 864x1536 (P_3MP)"); - break; - case FRAMESIZE_QXGA: - ESP_LOGCONFIG(TAG, " Resolution: 2048x1536 (QXGA)"); - break; - case FRAMESIZE_QHD: - ESP_LOGCONFIG(TAG, " Resolution: 2560x1440 (QHD)"); - break; - case FRAMESIZE_WQXGA: - ESP_LOGCONFIG(TAG, " Resolution: 2560x1600 (WQXGA)"); - break; - case FRAMESIZE_P_FHD: - ESP_LOGCONFIG(TAG, " Resolution: 1080x1920 (P_FHD)"); - break; - case FRAMESIZE_QSXGA: - ESP_LOGCONFIG(TAG, " Resolution: 2560x1920 (QSXGA)"); - break; - default: - break; - } + + ESP_LOGCONFIG(TAG, " Resolution: %s", frame_size_to_str(this->config_.frame_size)); + ESP_LOGCONFIG(TAG, " Pixel Format: %s", pixel_format_to_str(this->config_.pixel_format)); if (this->is_failed()) { ESP_LOGE(TAG, " Setup Failed: %s", esp_err_to_name(this->init_error_)); @@ -184,8 +197,19 @@ void ESP32Camera::loop() { // check if we can return the image if (this->can_return_image_()) { // return image - auto *fb = this->current_image_->get_raw_buffer(); - xQueueSend(this->framebuffer_return_queue_, &fb, portMAX_DELAY); +#ifdef USE_ESP32_CAMERA_JPEG_CONVERSION + if (this->config_.pixel_format != PIXFORMAT_JPEG && this->config_.jpeg_quality > 0) { + // for non-JPEG format, we need to free the data and raw buffer + auto *jpg_buf = this->current_image_->get_data_buffer(); + free(jpg_buf); // NOLINT(cppcoreguidelines-no-malloc) + auto *fb = this->current_image_->get_raw_buffer(); + this->fb_allocator_.deallocate(fb, 1); + } else +#endif + { + auto *fb = this->current_image_->get_raw_buffer(); + xQueueSend(this->framebuffer_return_queue_, &fb, portMAX_DELAY); + } this->current_image_.reset(); } @@ -212,6 +236,38 @@ void ESP32Camera::loop() { xQueueSend(this->framebuffer_return_queue_, &fb, portMAX_DELAY); return; } + +#ifdef USE_ESP32_CAMERA_JPEG_CONVERSION + if (this->config_.pixel_format != PIXFORMAT_JPEG && this->config_.jpeg_quality > 0) { + // for non-JPEG format, we need to convert the frame to JPEG + uint8_t *jpg_buf; + size_t jpg_buf_len; + size_t width = fb->width; + size_t height = fb->height; + struct timeval timestamp = fb->timestamp; + bool ok = frame2jpg(fb, 100 - this->config_.jpeg_quality, &jpg_buf, &jpg_buf_len); + // return the original frame buffer to the queue + xQueueSend(this->framebuffer_return_queue_, &fb, portMAX_DELAY); + if (!ok) { + ESP_LOGE(TAG, "Failed to convert frame to JPEG!"); + return; + } + // create a new camera_fb_t for the JPEG data + fb = this->fb_allocator_.allocate(1); + if (fb == nullptr) { + ESP_LOGE(TAG, "Failed to allocate memory for camera frame buffer!"); + free(jpg_buf); // NOLINT(cppcoreguidelines-no-malloc) + return; + } + memset(fb, 0, sizeof(camera_fb_t)); + fb->buf = jpg_buf; + fb->len = jpg_buf_len; + fb->width = width; + fb->height = height; + fb->format = PIXFORMAT_JPEG; + fb->timestamp = timestamp; + } +#endif this->current_image_ = std::make_shared<ESP32CameraImage>(fb, this->single_requesters_ | this->stream_requesters_); #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE @@ -342,6 +398,37 @@ void ESP32Camera::set_frame_size(ESP32CameraFrameSize size) { break; } } +void ESP32Camera::set_pixel_format(ESP32CameraPixelFormat format) { + switch (format) { + case ESP32_PIXEL_FORMAT_RGB565: + this->config_.pixel_format = PIXFORMAT_RGB565; + break; + case ESP32_PIXEL_FORMAT_YUV422: + this->config_.pixel_format = PIXFORMAT_YUV422; + break; + case ESP32_PIXEL_FORMAT_YUV420: + this->config_.pixel_format = PIXFORMAT_YUV420; + break; + case ESP32_PIXEL_FORMAT_GRAYSCALE: + this->config_.pixel_format = PIXFORMAT_GRAYSCALE; + break; + case ESP32_PIXEL_FORMAT_JPEG: + this->config_.pixel_format = PIXFORMAT_JPEG; + break; + case ESP32_PIXEL_FORMAT_RGB888: + this->config_.pixel_format = PIXFORMAT_RGB888; + break; + case ESP32_PIXEL_FORMAT_RAW: + this->config_.pixel_format = PIXFORMAT_RAW; + break; + case ESP32_PIXEL_FORMAT_RGB444: + this->config_.pixel_format = PIXFORMAT_RGB444; + break; + case ESP32_PIXEL_FORMAT_RGB555: + this->config_.pixel_format = PIXFORMAT_RGB555; + break; + } +} void ESP32Camera::set_jpeg_quality(uint8_t quality) { this->config_.jpeg_quality = quality; } void ESP32Camera::set_vertical_flip(bool vertical_flip) { this->vertical_flip_ = vertical_flip; } void ESP32Camera::set_horizontal_mirror(bool horizontal_mirror) { this->horizontal_mirror_ = horizontal_mirror; } diff --git a/esphome/components/esp32_camera/esp32_camera.h b/esphome/components/esp32_camera/esp32_camera.h index eea93b7e01..9fbd3848f2 100644 --- a/esphome/components/esp32_camera/esp32_camera.h +++ b/esphome/components/esp32_camera/esp32_camera.h @@ -41,6 +41,18 @@ enum ESP32CameraFrameSize { ESP32_CAMERA_SIZE_2560X1920, // QSXGA }; +enum ESP32CameraPixelFormat { + ESP32_PIXEL_FORMAT_RGB565, + ESP32_PIXEL_FORMAT_YUV422, + ESP32_PIXEL_FORMAT_YUV420, + ESP32_PIXEL_FORMAT_GRAYSCALE, + ESP32_PIXEL_FORMAT_JPEG, + ESP32_PIXEL_FORMAT_RGB888, + ESP32_PIXEL_FORMAT_RAW, + ESP32_PIXEL_FORMAT_RGB444, + ESP32_PIXEL_FORMAT_RGB555, +}; + enum ESP32AgcGainCeiling { ESP32_GAINCEILING_2X = GAINCEILING_2X, ESP32_GAINCEILING_4X = GAINCEILING_4X, @@ -126,6 +138,7 @@ class ESP32Camera : public camera::Camera { void set_reset_pin(uint8_t pin); void set_power_down_pin(uint8_t pin); /* -- image */ + void set_pixel_format(ESP32CameraPixelFormat format); void set_frame_size(ESP32CameraFrameSize size); void set_jpeg_quality(uint8_t quality); void set_vertical_flip(bool vertical_flip); @@ -220,6 +233,7 @@ class ESP32Camera : public camera::Camera { #ifdef USE_I2C i2c::InternalI2CBus *i2c_bus_{nullptr}; #endif // USE_I2C + RAMAllocator<camera_fb_t> fb_allocator_{RAMAllocator<camera_fb_t>::ALLOC_INTERNAL}; }; class ESP32CameraImageTrigger : public Trigger<CameraImageData>, public camera::CameraListener { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 5559ec88d0..a7fb9f197c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -43,6 +43,7 @@ #define USE_DEVICES #define USE_DISPLAY #define USE_ENTITY_ICON +#define USE_ESP32_CAMERA_JPEG_CONVERSION #define USE_ESP32_HOSTED #define USE_ESP32_IMPROV_STATE_CALLBACK #define USE_EVENT diff --git a/tests/test_build_components/common/i2c_camera/esp32-idf.yaml b/tests/test_build_components/common/i2c_camera/esp32-idf.yaml index 443ebbebd9..07ab6cdc8d 100644 --- a/tests/test_build_components/common/i2c_camera/esp32-idf.yaml +++ b/tests/test_build_components/common/i2c_camera/esp32-idf.yaml @@ -30,6 +30,7 @@ esp32_camera: resolution: 640x480 jpeg_quality: 10 frame_buffer_location: PSRAM + pixel_format: JPEG on_image: then: - lambda: |- From 4cc1e6a9103dc804e9e4516ff1f6fe313701ccf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= <contact@rodrigomartin.dev> Date: Thu, 19 Feb 2026 15:23:22 +0100 Subject: [PATCH 0775/2030] [esp32_ble_server] add test for lambda characteristic (#14091) --- tests/components/esp32_ble_server/common.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/components/esp32_ble_server/common.yaml b/tests/components/esp32_ble_server/common.yaml index e9576a8262..7fe0b2eb5f 100644 --- a/tests/components/esp32_ble_server/common.yaml +++ b/tests/components/esp32_ble_server/common.yaml @@ -33,6 +33,10 @@ esp32_ble_server: - uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc42d advertise: false characteristics: + - id: test_lambda_characteristic + uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc12c + read: true + value: !lambda return { 1, 2 }; - id: test_change_characteristic uuid: 2a24b789-7a1b-4535-af3e-ee76a35cc11c read: true From 7b53a9895000219aac5895de48c5bd15715d7aea Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 08:39:44 -0600 Subject: [PATCH 0776/2030] [socket] Log error when UDP socket requested on LWIP TCP-only platforms (#14089) --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index aa37386d70..6e95f5bc7a 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -680,6 +680,11 @@ class LWIPRawListenImpl final : public LWIPRawImpl { }; std::unique_ptr<Socket> socket(int domain, int type, int protocol) { + if (type != SOCK_STREAM) { + ESP_LOGE(TAG, "UDP sockets not supported on this platform, use WiFiUDP"); + errno = EPROTOTYPE; + return nullptr; + } auto *pcb = tcp_new(); if (pcb == nullptr) return nullptr; From 6daca09794d7d48478e4c6751907ae5a4b5aa7b3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 08:40:08 -0600 Subject: [PATCH 0777/2030] [logger] Replace LogListener virtual interface with LogCallback struct (#14084) --- esphome/components/api/api_server.cpp | 5 +- esphome/components/api/api_server.h | 6 +- esphome/components/ble_nus/ble_nus.cpp | 5 +- esphome/components/ble_nus/ble_nus.h | 9 +-- esphome/components/logger/logger.h | 66 ++++++++++---------- esphome/components/mqtt/mqtt_client.cpp | 5 +- esphome/components/mqtt/mqtt_client.h | 9 +-- esphome/components/syslog/esphome_syslog.cpp | 7 ++- esphome/components/syslog/esphome_syslog.h | 5 +- esphome/components/web_server/web_server.cpp | 5 +- esphome/components/web_server/web_server.h | 11 +--- 11 files changed, 65 insertions(+), 68 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 67a117e68f..1a1d0b229b 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -92,7 +92,10 @@ void APIServer::setup() { #ifdef USE_LOGGER if (logger::global_logger != nullptr) { - logger::global_logger->add_log_listener(this); + logger::global_logger->add_log_callback( + this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + static_cast<APIServer *>(self)->on_log(level, tag, message, message_len); + }); } #endif diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 323acc2efb..3b9ba0e23b 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -37,10 +37,6 @@ struct SavedNoisePsk { class APIServer : public Component, public Controller -#ifdef USE_LOGGER - , - public logger::LogListener -#endif #ifdef USE_CAMERA , public camera::CameraListener @@ -56,7 +52,7 @@ class APIServer : public Component, void on_shutdown() override; bool teardown() override; #ifdef USE_LOGGER - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override; + void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); #endif #ifdef USE_CAMERA void on_camera_image(const std::shared_ptr<camera::CameraImage> &image) override; diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index 0de65b623f..a10132eb3e 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -87,7 +87,10 @@ void BLENUS::setup() { global_ble_nus = this; #ifdef USE_LOGGER if (logger::global_logger != nullptr && this->expose_log_) { - logger::global_logger->add_log_listener(this); + logger::global_logger->add_log_callback( + this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + static_cast<BLENUS *>(self)->on_log(level, tag, message, message_len); + }); } #endif } diff --git a/esphome/components/ble_nus/ble_nus.h b/esphome/components/ble_nus/ble_nus.h index ef20fc5e5b..b2b0ee7713 100644 --- a/esphome/components/ble_nus/ble_nus.h +++ b/esphome/components/ble_nus/ble_nus.h @@ -10,12 +10,7 @@ namespace esphome::ble_nus { -class BLENUS : public Component -#ifdef USE_LOGGER - , - public logger::LogListener -#endif -{ +class BLENUS : public Component { enum TxStatus { TX_DISABLED, TX_ENABLED, @@ -29,7 +24,7 @@ class BLENUS : public Component size_t write_array(const uint8_t *data, size_t len); void set_expose_log(bool expose_log) { this->expose_log_ = expose_log; } #ifdef USE_LOGGER - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override; + void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); #endif protected: diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 835542dd8f..2a7552af92 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -40,26 +40,25 @@ struct device; namespace esphome::logger { -/** Interface for receiving log messages without std::function overhead. +/** Lightweight callback for receiving log messages without virtual dispatch overhead. * - * Components can implement this interface instead of using lambdas with std::function - * to reduce flash usage from std::function type erasure machinery. + * Replaces the former LogListener virtual interface to eliminate per-implementer + * vtable sub-tables and thunk code (~39 bytes saved per class that used LogListener). * * Usage: - * class MyComponent : public Component, public LogListener { - * public: - * void setup() override { - * if (logger::global_logger != nullptr) - * logger::global_logger->add_log_listener(this); - * } - * void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override { - * // Handle log message - * } - * }; + * // In your component's setup(): + * if (logger::global_logger != nullptr) + * logger::global_logger->add_log_callback( + * this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + * static_cast<MyComponent *>(self)->on_log(level, tag, message, message_len); + * }); */ -class LogListener { - public: - virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) = 0; +struct LogCallback { + void *instance; + void (*fn)(void *, uint8_t, const char *, const char *, size_t); + void invoke(uint8_t level, const char *tag, const char *message, size_t message_len) const { + this->fn(this->instance, level, tag, message, message_len); + } }; #ifdef USE_LOGGER_LEVEL_LISTENERS @@ -187,11 +186,13 @@ class Logger : public Component { inline uint8_t level_for(const char *tag); #ifdef USE_LOG_LISTENERS - /// Register a log listener to receive log messages - void add_log_listener(LogListener *listener) { this->log_listeners_.push_back(listener); } + /// Register a log callback to receive log messages + void add_log_callback(void *instance, void (*fn)(void *, uint8_t, const char *, const char *, size_t)) { + this->log_callbacks_.push_back(LogCallback{instance, fn}); + } #else /// No-op when log listeners are disabled - void add_log_listener(LogListener *listener) {} + void add_log_callback(void *instance, void (*fn)(void *, uint8_t, const char *, const char *, size_t)) {} #endif #ifdef USE_LOGGER_LEVEL_LISTENERS @@ -253,11 +254,11 @@ class Logger : public Component { } #endif - // Helper to notify log listeners + // Helper to notify log callbacks inline void HOT notify_listeners_(uint8_t level, const char *tag, const LogBuffer &buf) { #ifdef USE_LOG_LISTENERS - for (auto *listener : this->log_listeners_) - listener->on_log(level, tag, buf.data, buf.pos); + for (auto &cb : this->log_callbacks_) + cb.invoke(level, tag, buf.data, buf.pos); #endif } @@ -341,8 +342,8 @@ class Logger : public Component { std::map<const char *, uint8_t, CStrCompare> log_levels_{}; #endif #ifdef USE_LOG_LISTENERS - StaticVector<LogListener *, ESPHOME_LOG_MAX_LISTENERS> - log_listeners_; // Log message listeners (API, MQTT, syslog, etc.) + StaticVector<LogCallback, ESPHOME_LOG_MAX_LISTENERS> + log_callbacks_; // Log message callbacks (API, MQTT, syslog, etc.) #endif #ifdef USE_LOGGER_LEVEL_LISTENERS std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners @@ -478,15 +479,16 @@ class Logger : public Component { }; extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *>, public LogListener { +class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *> { public: - explicit LoggerMessageTrigger(Logger *parent, uint8_t level) : level_(level) { parent->add_log_listener(this); } - - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override { - (void) message_len; - if (level <= this->level_) { - this->trigger(level, tag, message); - } + explicit LoggerMessageTrigger(Logger *parent, uint8_t level) : level_(level) { + parent->add_log_callback(this, + [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + auto *trigger = static_cast<LoggerMessageTrigger *>(self); + if (level <= trigger->level_) { + trigger->trigger(level, tag, message); + } + }); } protected: diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 90b423c386..9905b4677e 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -64,7 +64,10 @@ void MQTTClientComponent::setup() { }); #ifdef USE_LOGGER if (this->is_log_message_enabled() && logger::global_logger != nullptr) { - logger::global_logger->add_log_listener(this); + logger::global_logger->add_log_callback( + this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + static_cast<MQTTClientComponent *>(self)->on_log(level, tag, message, message_len); + }); } #endif diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 38bc0b4da3..21edd53eda 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -99,12 +99,7 @@ enum MQTTClientState { class MQTTComponent; -class MQTTClientComponent : public Component -#ifdef USE_LOGGER - , - public logger::LogListener -#endif -{ +class MQTTClientComponent : public Component { public: MQTTClientComponent(); @@ -252,7 +247,7 @@ class MQTTClientComponent : public Component float get_setup_priority() const override; #ifdef USE_LOGGER - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override; + void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); #endif void on_message(const std::string &topic, const std::string &payload); diff --git a/esphome/components/syslog/esphome_syslog.cpp b/esphome/components/syslog/esphome_syslog.cpp index 376de54db4..790d08ffa6 100644 --- a/esphome/components/syslog/esphome_syslog.cpp +++ b/esphome/components/syslog/esphome_syslog.cpp @@ -18,7 +18,12 @@ constexpr int LOG_LEVEL_TO_SYSLOG_SEVERITY[] = { 7 // VERY_VERBOSE }; -void Syslog::setup() { logger::global_logger->add_log_listener(this); } +void Syslog::setup() { + logger::global_logger->add_log_callback( + this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + static_cast<Syslog *>(self)->on_log(level, tag, message, message_len); + }); +} void Syslog::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) { this->log_(level, tag, message, message_len); diff --git a/esphome/components/syslog/esphome_syslog.h b/esphome/components/syslog/esphome_syslog.h index bde6ab5ed4..be4fa91436 100644 --- a/esphome/components/syslog/esphome_syslog.h +++ b/esphome/components/syslog/esphome_syslog.h @@ -2,17 +2,16 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/components/logger/logger.h" #include "esphome/components/udp/udp_component.h" #include "esphome/components/time/real_time_clock.h" #ifdef USE_NETWORK namespace esphome::syslog { -class Syslog : public Component, public Parented<udp::UDPComponent>, public logger::LogListener { +class Syslog : public Component, public Parented<udp::UDPComponent> { public: Syslog(int level, time::RealTimeClock *time) : log_level_(level), time_(time) {} void setup() override; - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override; + void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); void set_strip(bool strip) { this->strip_ = strip; } void set_facility(int facility) { this->facility_ = facility; } diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e3d131f58e..a44a47379e 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -395,7 +395,10 @@ void WebServer::setup() { #ifdef USE_LOGGER if (logger::global_logger != nullptr && this->expose_log_) { - logger::global_logger->add_log_listener(this); + logger::global_logger->add_log_callback( + this, [](void *self, uint8_t level, const char *tag, const char *message, size_t message_len) { + static_cast<WebServer *>(self)->on_log(level, tag, message, message_len); + }); } #endif diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 026da763ea..6afe618b59 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -186,14 +186,7 @@ class DeferredUpdateEventSourceList : public std::list<DeferredUpdateEventSource * under the '/light/...', '/sensor/...', ... URLs. A full documentation for this API * can be found under https://esphome.io/web-api/. */ -class WebServer : public Controller, - public Component, - public AsyncWebHandler -#ifdef USE_LOGGER - , - public logger::LogListener -#endif -{ +class WebServer : public Controller, public Component, public AsyncWebHandler { #if !defined(USE_ESP32) && defined(USE_ARDUINO) friend class DeferredUpdateEventSourceList; #endif @@ -254,7 +247,7 @@ class WebServer : public Controller, void dump_config() override; #ifdef USE_LOGGER - void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override; + void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); #endif /// MQTT setup priority. From b0085e21f74972909be1b2cb54b05a01ddb558c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 08:40:23 -0600 Subject: [PATCH 0778/2030] [core] Devirtualize call_loop() and mark_failed() in Component (#14083) --- esphome/core/component.cpp | 12 +++++------- esphome/core/component.h | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index ba0f1663b9..f283a69064 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -207,7 +207,7 @@ bool Component::cancel_retry(uint32_t id) { #pragma GCC diagnostic pop } -void Component::call_loop() { this->loop(); } +void Component::call_loop_() { this->loop(); } void Component::call_setup() { this->setup(); } void Component::call_dump_config() { this->dump_config(); @@ -258,11 +258,11 @@ void Component::call() { case COMPONENT_STATE_SETUP: // State setup: Call first loop and set state to loop this->set_component_state_(COMPONENT_STATE_LOOP); - this->call_loop(); + this->call_loop_(); break; case COMPONENT_STATE_LOOP: // State loop: Call loop - this->call_loop(); + this->call_loop_(); break; case COMPONENT_STATE_FAILED: // State failed: Do nothing @@ -497,16 +497,14 @@ void Component::set_setup_priority(float priority) { bool Component::has_overridden_loop() const { #if defined(USE_HOST) || defined(CLANG_TIDY) - bool loop_overridden = true; - bool call_loop_overridden = true; + return true; #else #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpmf-conversions" bool loop_overridden = (void *) (this->*(&Component::loop)) != (void *) (&Component::loop); - bool call_loop_overridden = (void *) (this->*(&Component::call_loop)) != (void *) (&Component::call_loop); #pragma GCC diagnostic pop + return loop_overridden; #endif - return loop_overridden || call_loop_overridden; } PollingComponent::PollingComponent(uint32_t update_interval) : update_interval_(update_interval) {} diff --git a/esphome/core/component.h b/esphome/core/component.h index 6f7f77dbc1..d4dad3c9a6 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -165,7 +165,7 @@ class Component { * For example, i2c based components can check if the remote device is responding and otherwise * mark the component as failed. Eventually this will also enable smart status LEDs. */ - virtual void mark_failed(); + void mark_failed(); // Remove before 2026.6.0 ESPDEPRECATED("Use mark_failed(LOG_STR(\"static string literal\")) instead. Do NOT use .c_str() from temporary " @@ -286,7 +286,7 @@ class Component { protected: friend class Application; - virtual void call_loop(); + void call_loop_(); virtual void call_setup(); virtual void call_dump_config(); From 535980b9bd37ebf405a6305e34e980e3f16a5af6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 08:40:41 -0600 Subject: [PATCH 0779/2030] [cse7761] Use constexpr for compile-time constants (#14081) --- esphome/components/cse7761/cse7761.cpp | 38 +++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/esphome/components/cse7761/cse7761.cpp b/esphome/components/cse7761/cse7761.cpp index 7c5ee833a4..f4966357d4 100644 --- a/esphome/components/cse7761/cse7761.cpp +++ b/esphome/components/cse7761/cse7761.cpp @@ -15,29 +15,29 @@ static const char *const TAG = "cse7761"; * https://github.com/arendst/Tasmota/blob/development/tasmota/xnrg_19_cse7761.ino \*********************************************************************************************/ -static const int CSE7761_UREF = 42563; // RmsUc -static const int CSE7761_IREF = 52241; // RmsIAC -static const int CSE7761_PREF = 44513; // PowerPAC +static constexpr int CSE7761_UREF = 42563; // RmsUc +static constexpr int CSE7761_IREF = 52241; // RmsIAC +static constexpr int CSE7761_PREF = 44513; // PowerPAC -static const uint8_t CSE7761_REG_SYSCON = 0x00; // (2) System Control Register (0x0A04) -static const uint8_t CSE7761_REG_EMUCON = 0x01; // (2) Metering control register (0x0000) -static const uint8_t CSE7761_REG_EMUCON2 = 0x13; // (2) Metering control register 2 (0x0001) -static const uint8_t CSE7761_REG_PULSE1SEL = 0x1D; // (2) Pin function output select register (0x3210) +static constexpr uint8_t CSE7761_REG_SYSCON = 0x00; // (2) System Control Register (0x0A04) +static constexpr uint8_t CSE7761_REG_EMUCON = 0x01; // (2) Metering control register (0x0000) +static constexpr uint8_t CSE7761_REG_EMUCON2 = 0x13; // (2) Metering control register 2 (0x0001) +static constexpr uint8_t CSE7761_REG_PULSE1SEL = 0x1D; // (2) Pin function output select register (0x3210) -static const uint8_t CSE7761_REG_RMSIA = 0x24; // (3) The effective value of channel A current (0x000000) -static const uint8_t CSE7761_REG_RMSIB = 0x25; // (3) The effective value of channel B current (0x000000) -static const uint8_t CSE7761_REG_RMSU = 0x26; // (3) Voltage RMS (0x000000) -static const uint8_t CSE7761_REG_POWERPA = 0x2C; // (4) Channel A active power, update rate 27.2Hz (0x00000000) -static const uint8_t CSE7761_REG_POWERPB = 0x2D; // (4) Channel B active power, update rate 27.2Hz (0x00000000) -static const uint8_t CSE7761_REG_SYSSTATUS = 0x43; // (1) System status register +static constexpr uint8_t CSE7761_REG_RMSIA = 0x24; // (3) The effective value of channel A current (0x000000) +static constexpr uint8_t CSE7761_REG_RMSIB = 0x25; // (3) The effective value of channel B current (0x000000) +static constexpr uint8_t CSE7761_REG_RMSU = 0x26; // (3) Voltage RMS (0x000000) +static constexpr uint8_t CSE7761_REG_POWERPA = 0x2C; // (4) Channel A active power, update rate 27.2Hz (0x00000000) +static constexpr uint8_t CSE7761_REG_POWERPB = 0x2D; // (4) Channel B active power, update rate 27.2Hz (0x00000000) +static constexpr uint8_t CSE7761_REG_SYSSTATUS = 0x43; // (1) System status register -static const uint8_t CSE7761_REG_COEFFCHKSUM = 0x6F; // (2) Coefficient checksum -static const uint8_t CSE7761_REG_RMSIAC = 0x70; // (2) Channel A effective current conversion coefficient +static constexpr uint8_t CSE7761_REG_COEFFCHKSUM = 0x6F; // (2) Coefficient checksum +static constexpr uint8_t CSE7761_REG_RMSIAC = 0x70; // (2) Channel A effective current conversion coefficient -static const uint8_t CSE7761_SPECIAL_COMMAND = 0xEA; // Start special command -static const uint8_t CSE7761_CMD_RESET = 0x96; // Reset command, after receiving the command, the chip resets -static const uint8_t CSE7761_CMD_CLOSE_WRITE = 0xDC; // Close write operation -static const uint8_t CSE7761_CMD_ENABLE_WRITE = 0xE5; // Enable write operation +static constexpr uint8_t CSE7761_SPECIAL_COMMAND = 0xEA; // Start special command +static constexpr uint8_t CSE7761_CMD_RESET = 0x96; // Reset command, after receiving the command, the chip resets +static constexpr uint8_t CSE7761_CMD_CLOSE_WRITE = 0xDC; // Close write operation +static constexpr uint8_t CSE7761_CMD_ENABLE_WRITE = 0xE5; // Enable write operation enum CSE7761 { RMS_IAC, RMS_IBC, RMS_UC, POWER_PAC, POWER_PBC, POWER_SC, ENERGY_AC, ENERGY_BC }; From 01a46f665f550085022bed7d994e043045f5553a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Feb 2026 09:42:22 -0500 Subject: [PATCH 0780/2030] Bump esptool from 5.1.0 to 5.2.0 (#14058) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2e6268284a..be3445dceb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ tzlocal==5.3.1 # from time tzdata>=2021.1 # from time pyserial==3.5 platformio==6.1.19 -esptool==5.1.0 +esptool==5.2.0 click==8.1.7 esphome-dashboard==20260210.0 aioesphomeapi==44.0.0 From b5a8e1c94cfa2d82c2e9b9241ae62c1abd7dd3a7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 09:06:46 -0600 Subject: [PATCH 0781/2030] [ci] Update lint message to recommend constexpr over static const (#14099) --- script/ci-custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/ci-custom.py b/script/ci-custom.py index 8c405b04ae..231f587068 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -301,7 +301,7 @@ def highlight(s): ], ) def lint_no_defines(fname, match): - s = highlight(f"static const uint8_t {match.group(1)} = {match.group(2)};") + s = highlight(f"static constexpr uint8_t {match.group(1)} = {match.group(2)};") return ( "#define macros for integer constants are not allowed, please use " f"{s} style instead (replace uint8_t with the appropriate " From 0484b2852dcf76161f5ae36d447e8d9e1cdad747 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 09:27:05 -0600 Subject: [PATCH 0782/2030] [e131] Fix E1.31 on ESP8266 and RP2040 by restoring WiFiUDP support (#14086) --- esphome/components/e131/e131.cpp | 31 ++++++++++++++++++++++++- esphome/components/e131/e131.h | 8 +++++++ esphome/components/e131/e131_packet.cpp | 2 ++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index 4187857901..941927122c 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -14,12 +14,17 @@ static const int PORT = 5568; E131Component::E131Component() {} E131Component::~E131Component() { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) if (this->socket_) { this->socket_->close(); } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + this->udp_.stop(); +#endif } void E131Component::setup() { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) this->socket_ = socket::socket_ip(SOCK_DGRAM, IPPROTO_IP); int enable = 1; @@ -50,6 +55,13 @@ void E131Component::setup() { this->mark_failed(); return; } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + if (!this->udp_.begin(PORT)) { + ESP_LOGW(TAG, "Cannot bind E1.31 to port %d.", PORT); + this->mark_failed(); + return; + } +#endif join_igmp_groups_(); } @@ -59,19 +71,36 @@ void E131Component::loop() { int universe = 0; uint8_t buf[1460]; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) ssize_t len = this->socket_->read(buf, sizeof(buf)); if (len == -1) { return; } if (!this->packet_(buf, (size_t) len, universe, packet)) { - ESP_LOGV(TAG, "Invalid packet received of size %zd.", len); + ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); return; } if (!this->process_(universe, packet)) { ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + while (auto packet_size = this->udp_.parsePacket()) { + auto len = this->udp_.read(buf, sizeof(buf)); + if (len <= 0) + continue; + + if (!this->packet_(buf, (size_t) len, universe, packet)) { + ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); + continue; + } + + if (!this->process_(universe, packet)) { + ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); + } + } +#endif } void E131Component::add_effect(E131AddressableLightEffect *light_effect) { diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index d4b272eae2..72da9ddebe 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -1,7 +1,11 @@ #pragma once #include "esphome/core/defines.h" #ifdef USE_NETWORK +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) #include "esphome/components/socket/socket.h" +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) +#include <WiFiUdp.h> +#endif #include "esphome/core/component.h" #include <cinttypes> @@ -45,7 +49,11 @@ class E131Component : public esphome::Component { void leave_(int universe); E131ListenMethod listen_method_{E131_MULTICAST}; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) std::unique_ptr<socket::Socket> socket_; +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + WiFiUDP udp_; +#endif std::vector<E131AddressableLightEffect *> light_effects_; std::map<int, int> universe_consumers_; }; diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index ed081e5758..aa5c740454 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -62,8 +62,10 @@ const size_t E131_MIN_PACKET_SIZE = reinterpret_cast<size_t>(&((E131RawPacket *) bool E131Component::join_igmp_groups_() { if (listen_method_ != E131_MULTICAST) return false; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) if (this->socket_ == nullptr) return false; +#endif for (auto universe : universe_consumers_) { if (!universe.second) From 916cf0d8b7f945bb6e3ee30702469f22013b09c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 09:28:00 -0600 Subject: [PATCH 0783/2030] [e131] Replace std::map with std::vector for universe tracking (#14087) --- esphome/components/e131/e131.h | 9 ++++-- esphome/components/e131/e131_packet.cpp | 39 ++++++++++++++++--------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index 72da9ddebe..fee447b678 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -9,7 +9,6 @@ #include "esphome/core/component.h" #include <cinttypes> -#include <map> #include <memory> #include <vector> @@ -27,6 +26,11 @@ struct E131Packet { uint8_t values[E131_MAX_PROPERTY_VALUES_COUNT]; }; +struct UniverseConsumer { + uint16_t universe; + uint16_t consumers; +}; + class E131Component : public esphome::Component { public: E131Component(); @@ -45,6 +49,7 @@ class E131Component : public esphome::Component { bool packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet); bool process_(int universe, const E131Packet &packet); bool join_igmp_groups_(); + UniverseConsumer *find_universe_(int universe); void join_(int universe); void leave_(int universe); @@ -55,7 +60,7 @@ class E131Component : public esphome::Component { WiFiUDP udp_; #endif std::vector<E131AddressableLightEffect *> light_effects_; - std::map<int, int> universe_consumers_; + std::vector<UniverseConsumer> universe_consumers_; }; } // namespace e131 diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index aa5c740454..b90e6d5c91 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -60,19 +60,19 @@ union E131RawPacket { const size_t E131_MIN_PACKET_SIZE = reinterpret_cast<size_t>(&((E131RawPacket *) nullptr)->property_values[1]); bool E131Component::join_igmp_groups_() { - if (listen_method_ != E131_MULTICAST) + if (this->listen_method_ != E131_MULTICAST) return false; #if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) if (this->socket_ == nullptr) return false; #endif - for (auto universe : universe_consumers_) { - if (!universe.second) + for (auto &entry : this->universe_consumers_) { + if (!entry.consumers) continue; ip4_addr_t multicast_addr = - network::IPAddress(239, 255, ((universe.first >> 8) & 0xff), ((universe.first >> 0) & 0xff)); + network::IPAddress(239, 255, ((entry.universe >> 8) & 0xff), ((entry.universe >> 0) & 0xff)); err_t err; { @@ -81,34 +81,47 @@ bool E131Component::join_igmp_groups_() { } if (err) { - ESP_LOGW(TAG, "IGMP join for %d universe of E1.31 failed. Multicast might not work.", universe.first); + ESP_LOGW(TAG, "IGMP join for %d universe of E1.31 failed. Multicast might not work.", entry.universe); } } return true; } +UniverseConsumer *E131Component::find_universe_(int universe) { + for (auto &entry : this->universe_consumers_) { + if (entry.universe == universe) + return &entry; + } + return nullptr; +} + void E131Component::join_(int universe) { // store only latest received packet for the given universe - auto consumers = ++universe_consumers_[universe]; - - if (consumers > 1) { - return; // we already joined before + auto *consumer = this->find_universe_(universe); + if (consumer != nullptr) { + if (consumer->consumers++ > 0) { + return; // we already joined before + } + } else { + this->universe_consumers_.push_back({static_cast<uint16_t>(universe), 1}); } - if (join_igmp_groups_()) { + if (this->join_igmp_groups_()) { ESP_LOGD(TAG, "Joined %d universe for E1.31.", universe); } } void E131Component::leave_(int universe) { - auto consumers = --universe_consumers_[universe]; + auto *consumer = this->find_universe_(universe); + if (consumer == nullptr) + return; - if (consumers > 0) { + if (--consumer->consumers > 0) { return; // we have other consumers of the given universe } - if (listen_method_ == E131_MULTICAST) { + if (this->listen_method_ == E131_MULTICAST) { ip4_addr_t multicast_addr = network::IPAddress(239, 255, ((universe >> 8) & 0xff), ((universe >> 0) & 0xff)); LwIPLock lock; From a8171da0033ce797ef59125a69b270cfe35e36eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 09:38:57 -0600 Subject: [PATCH 0784/2030] [web_server] Reduce set_json_id flash and stack usage (#14029) --- esphome/components/web_server/web_server.cpp | 46 ++++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index a44a47379e..f352e5896c 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -374,7 +374,7 @@ std::string WebServer::get_config_json() { json::JsonBuilder builder; JsonObject root = builder.root(); - root[ESPHOME_F("title")] = App.get_friendly_name().empty() ? App.get_name() : App.get_friendly_name(); + root[ESPHOME_F("title")] = App.get_friendly_name().empty() ? App.get_name().c_str() : App.get_friendly_name().c_str(); char comment_buffer[ESPHOME_COMMENT_SIZE]; App.get_comment_string(comment_buffer); root[ESPHOME_F("comment")] = comment_buffer; @@ -513,21 +513,27 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J size_t device_len = device_name ? strlen(device_name) : 0; #endif - // Build id into stack buffer - ArduinoJson copies the string - // Format: {prefix}/{device?}/{name} + // Single stack buffer for both id formats - ArduinoJson copies the string before we overwrite // Buffer sizes use constants from entity_base.h validated in core/config.py // Note: Device name uses ESPHOME_FRIENDLY_NAME_MAX_LEN (sub-device max 120), not ESPHOME_DEVICE_NAME_MAX_LEN // (hostname) + // Without USE_DEVICES: legacy id ({prefix}-{object_id}) is the largest format + // With USE_DEVICES: name_id ({prefix}/{device}/{name}) is the largest format + static constexpr size_t LEGACY_ID_SIZE = ESPHOME_DOMAIN_MAX_LEN + 1 + OBJECT_ID_MAX_LEN; #ifdef USE_DEVICES static constexpr size_t ID_BUF_SIZE = - ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1; + std::max(ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1, + LEGACY_ID_SIZE); #else - static constexpr size_t ID_BUF_SIZE = ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1; + static constexpr size_t ID_BUF_SIZE = + std::max(ESPHOME_DOMAIN_MAX_LEN + 1 + ESPHOME_FRIENDLY_NAME_MAX_LEN + 1, LEGACY_ID_SIZE); #endif char id_buf[ID_BUF_SIZE]; - char *p = id_buf; - memcpy(p, prefix, prefix_len); - p += prefix_len; + memcpy(id_buf, prefix, prefix_len); // NOLINT(bugprone-not-null-terminated-result) + + // name_id: new format {prefix}/{device?}/{name} - frontend should prefer this + // Remove in 2026.8.0 when id switches to new format permanently + char *p = id_buf + prefix_len; *p++ = '/'; #ifdef USE_DEVICES if (device_name) { @@ -538,31 +544,25 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J #endif memcpy(p, name.c_str(), name_len); p[name_len] = '\0'; - - // name_id: new format {prefix}/{device?}/{name} - frontend should prefer this - // Remove in 2026.8.0 when id switches to new format permanently root[ESPHOME_F("name_id")] = id_buf; // id: old format {prefix}-{object_id} for backward compatibility - // Will switch to new format in 2026.8.0 - char legacy_buf[ESPHOME_DOMAIN_MAX_LEN + 1 + OBJECT_ID_MAX_LEN]; - char *lp = legacy_buf; - memcpy(lp, prefix, prefix_len); - lp += prefix_len; - *lp++ = '-'; - obj->write_object_id_to(lp, sizeof(legacy_buf) - (lp - legacy_buf)); - root[ESPHOME_F("id")] = legacy_buf; + // Will switch to new format in 2026.8.0 - reuses prefix already in id_buf + id_buf[prefix_len] = '-'; + obj->write_object_id_to(id_buf + prefix_len + 1, ID_BUF_SIZE - prefix_len - 1); + root[ESPHOME_F("id")] = id_buf; if (start_config == DETAIL_ALL) { root[ESPHOME_F("domain")] = prefix; - root[ESPHOME_F("name")] = name; + // Use .c_str() to avoid instantiating set<StringRef> template (saves ~24B) + root[ESPHOME_F("name")] = name.c_str(); #ifdef USE_DEVICES if (device_name) { root[ESPHOME_F("device")] = device_name; } #endif #ifdef USE_ENTITY_ICON - root[ESPHOME_F("icon")] = obj->get_icon_ref(); + root[ESPHOME_F("icon")] = obj->get_icon_ref().c_str(); #endif root[ESPHOME_F("entity_category")] = obj->get_entity_category(); bool is_disabled = obj->is_disabled_by_default(); @@ -632,7 +632,7 @@ std::string WebServer::sensor_json_(sensor::Sensor *obj, float value, JsonDetail if (start_config == DETAIL_ALL) { this->add_sorting_info_(root, obj); if (!uom_ref.empty()) - root[ESPHOME_F("uom")] = uom_ref; + root[ESPHOME_F("uom")] = uom_ref.c_str(); } return builder.serialize(); @@ -1147,7 +1147,7 @@ std::string WebServer::number_json_(number::Number *obj, float value, JsonDetail root[ESPHOME_F("step")] = (value_accuracy_to_buf(val_buf, obj->traits.get_step(), accuracy), val_buf); root[ESPHOME_F("mode")] = (int) obj->traits.get_mode(); if (!uom_ref.empty()) - root[ESPHOME_F("uom")] = uom_ref; + root[ESPHOME_F("uom")] = uom_ref.c_str(); this->add_sorting_info_(root, obj); } From 5304750215a7be803d87bb9f059d43952fe084f6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:00:34 -0500 Subject: [PATCH 0785/2030] [socket] Fix IPv6 compilation error on host platform (#14101) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/socket/socket.cpp | 10 ++++++++-- tests/components/socket/common.yaml | 11 +++++++++++ tests/components/socket/test-ipv6.esp32-idf.yaml | 4 ++++ tests/components/socket/test-ipv6.host.yaml | 4 ++++ tests/components/socket/test.esp32-idf.yaml | 1 + tests/components/socket/test.host.yaml | 3 +++ 6 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/components/socket/common.yaml create mode 100644 tests/components/socket/test-ipv6.esp32-idf.yaml create mode 100644 tests/components/socket/test-ipv6.host.yaml create mode 100644 tests/components/socket/test.esp32-idf.yaml create mode 100644 tests/components/socket/test.host.yaml diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 2fcc162ead..6154c497e0 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -59,8 +59,14 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s #if USE_NETWORK_IPV6 else if (addr_ptr->sa_family == AF_INET6 && len >= sizeof(sockaddr_in6)) { const auto *addr = reinterpret_cast<const struct sockaddr_in6 *>(addr_ptr); -#ifndef USE_SOCKET_IMPL_LWIP_TCP - // Format IPv4-mapped IPv6 addresses as regular IPv4 (not supported on ESP8266 raw TCP) +#ifdef USE_HOST + // Format IPv4-mapped IPv6 addresses as regular IPv4 (POSIX layout, no LWIP union) + if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr) && + esphome_inet_ntop4(&addr->sin6_addr.s6_addr[12], buf.data(), buf.size()) != nullptr) { + return strlen(buf.data()); + } +#elif !defined(USE_SOCKET_IMPL_LWIP_TCP) + // Format IPv4-mapped IPv6 addresses as regular IPv4 (LWIP layout) if (addr->sin6_addr.un.u32_addr[0] == 0 && addr->sin6_addr.un.u32_addr[1] == 0 && addr->sin6_addr.un.u32_addr[2] == htonl(0xFFFF) && esphome_inet_ntop4(&addr->sin6_addr.un.u32_addr[3], buf.data(), buf.size()) != nullptr) { diff --git a/tests/components/socket/common.yaml b/tests/components/socket/common.yaml new file mode 100644 index 0000000000..aaf49f1611 --- /dev/null +++ b/tests/components/socket/common.yaml @@ -0,0 +1,11 @@ +substitutions: + network_enable_ipv6: "false" + +socket: + +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: ${network_enable_ipv6} diff --git a/tests/components/socket/test-ipv6.esp32-idf.yaml b/tests/components/socket/test-ipv6.esp32-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/socket/test-ipv6.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/socket/test-ipv6.host.yaml b/tests/components/socket/test-ipv6.host.yaml new file mode 100644 index 0000000000..fdd52c574e --- /dev/null +++ b/tests/components/socket/test-ipv6.host.yaml @@ -0,0 +1,4 @@ +socket: + +network: + enable_ipv6: true diff --git a/tests/components/socket/test.esp32-idf.yaml b/tests/components/socket/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/socket/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/socket/test.host.yaml b/tests/components/socket/test.host.yaml new file mode 100644 index 0000000000..e0c5d7cea3 --- /dev/null +++ b/tests/components/socket/test.host.yaml @@ -0,0 +1,3 @@ +socket: + +network: From f7459670d34b47f66210eaaca7586be33f84205c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 10:10:22 -0600 Subject: [PATCH 0786/2030] [core] Optimize WarnIfComponentBlockingGuard::finish() hot path (#14040) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/component.cpp | 38 ++++++++++++++++++-------------------- esphome/core/component.h | 7 ++++--- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index f283a69064..b458ea2a84 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -82,8 +82,8 @@ void store_component_error_message(const Component *component, const char *messa // setup_priority, component state, and status LED constants are now // constexpr in component.h -const uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; ///< Initial blocking time allowed without warning -const uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again +static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS = + 10U; ///< How long the blocking time must be larger to warn again float Component::get_loop_priority() const { return 0.0f; } @@ -529,37 +529,35 @@ void PollingComponent::stop_poller() { uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } -WarnIfComponentBlockingGuard::WarnIfComponentBlockingGuard(Component *component, uint32_t start_time) - : started_(start_time), component_(component) {} +static void __attribute__((noinline, cold)) warn_blocking(Component *component, uint32_t blocking_time) { + bool should_warn; + if (component != nullptr) { + should_warn = component->should_warn_of_blocking(blocking_time); + } else { + should_warn = true; // Already checked > WARN_IF_BLOCKING_OVER_MS in caller + } + if (should_warn) { + ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms), max is 30 ms", + component == nullptr ? LOG_STR_LITERAL("<null>") : LOG_STR_ARG(component->get_component_log_str()), + blocking_time); + } +} + uint32_t WarnIfComponentBlockingGuard::finish() { uint32_t curr_time = millis(); - uint32_t blocking_time = curr_time - this->started_; - #ifdef USE_RUNTIME_STATS // Record component runtime stats if (global_runtime_stats != nullptr) { global_runtime_stats->record_component_time(this->component_, blocking_time, curr_time); } #endif - bool should_warn; - if (this->component_ != nullptr) { - should_warn = this->component_->should_warn_of_blocking(blocking_time); - } else { - should_warn = blocking_time > WARN_IF_BLOCKING_OVER_MS; + if (blocking_time > WARN_IF_BLOCKING_OVER_MS) { + warn_blocking(this->component_, blocking_time); } - if (should_warn) { - ESP_LOGW(TAG, "%s took a long time for an operation (%" PRIu32 " ms)", - component_ == nullptr ? LOG_STR_LITERAL("<null>") : LOG_STR_ARG(component_->get_component_log_str()), - blocking_time); - ESP_LOGW(TAG, "Components should block for at most 30 ms"); - } - return curr_time; } -WarnIfComponentBlockingGuard::~WarnIfComponentBlockingGuard() {} - #ifdef USE_SETUP_PRIORITY_OVERRIDE void clear_setup_priority_overrides() { // Free the setup priority map completely diff --git a/esphome/core/component.h b/esphome/core/component.h index d4dad3c9a6..b99641a275 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -79,7 +79,7 @@ inline constexpr uint8_t STATUS_LED_ERROR = 0x10; // Remove before 2026.8.0 enum class RetryResult { DONE, RETRY }; -extern const uint16_t WARN_IF_BLOCKING_OVER_MS; +inline constexpr uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; class Component { public: @@ -550,12 +550,13 @@ class PollingComponent : public Component { class WarnIfComponentBlockingGuard { public: - WarnIfComponentBlockingGuard(Component *component, uint32_t start_time); + WarnIfComponentBlockingGuard(Component *component, uint32_t start_time) + : started_(start_time), component_(component) {} // Finish the timing operation and return the current time uint32_t finish(); - ~WarnIfComponentBlockingGuard(); + ~WarnIfComponentBlockingGuard() = default; protected: uint32_t started_; From b11ad26c4f70050d1656200234b0642760bdea68 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 19 Feb 2026 10:20:19 -0600 Subject: [PATCH 0787/2030] [audio] Support decoding audio directly from flash (#14098) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/audio/audio_decoder.cpp | 102 ++++++++++-------- esphome/components/audio/audio_decoder.h | 26 +++-- .../audio/audio_transfer_buffer.cpp | 17 ++- .../components/audio/audio_transfer_buffer.h | 67 +++++++++++- 4 files changed, 159 insertions(+), 53 deletions(-) diff --git a/esphome/components/audio/audio_decoder.cpp b/esphome/components/audio/audio_decoder.cpp index ee6d7d0a15..7794b5b0d3 100644 --- a/esphome/components/audio/audio_decoder.cpp +++ b/esphome/components/audio/audio_decoder.cpp @@ -15,8 +15,8 @@ static const uint32_t READ_WRITE_TIMEOUT_MS = 20; // Timeout for transferring a static const uint32_t MAX_POTENTIALLY_FAILED_COUNT = 10; -AudioDecoder::AudioDecoder(size_t input_buffer_size, size_t output_buffer_size) { - this->input_transfer_buffer_ = AudioSourceTransferBuffer::create(input_buffer_size); +AudioDecoder::AudioDecoder(size_t input_buffer_size, size_t output_buffer_size) + : input_buffer_size_(input_buffer_size) { this->output_transfer_buffer_ = AudioSinkTransferBuffer::create(output_buffer_size); } @@ -29,11 +29,20 @@ AudioDecoder::~AudioDecoder() { } esp_err_t AudioDecoder::add_source(std::weak_ptr<RingBuffer> &input_ring_buffer) { - if (this->input_transfer_buffer_ != nullptr) { - this->input_transfer_buffer_->set_source(input_ring_buffer); - return ESP_OK; + auto source = AudioSourceTransferBuffer::create(this->input_buffer_size_); + if (source == nullptr) { + return ESP_ERR_NO_MEM; } - return ESP_ERR_NO_MEM; + source->set_source(input_ring_buffer); + this->input_buffer_ = std::move(source); + return ESP_OK; +} + +esp_err_t AudioDecoder::add_source(const uint8_t *data_pointer, size_t length) { + auto source = make_unique<ConstAudioSourceBuffer>(); + source->set_data(data_pointer, length); + this->input_buffer_ = std::move(source); + return ESP_OK; } esp_err_t AudioDecoder::add_sink(std::weak_ptr<RingBuffer> &output_ring_buffer) { @@ -54,8 +63,16 @@ esp_err_t AudioDecoder::add_sink(speaker::Speaker *speaker) { } #endif +esp_err_t AudioDecoder::add_sink(AudioSinkCallback *callback) { + if (this->output_transfer_buffer_ != nullptr) { + this->output_transfer_buffer_->set_sink(callback); + return ESP_OK; + } + return ESP_ERR_NO_MEM; +} + esp_err_t AudioDecoder::start(AudioFileType audio_file_type) { - if ((this->input_transfer_buffer_ == nullptr) || (this->output_transfer_buffer_ == nullptr)) { + if (this->output_transfer_buffer_ == nullptr) { return ESP_ERR_NO_MEM; } @@ -112,6 +129,10 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) { } AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { + if (this->input_buffer_ == nullptr) { + return AudioDecoderState::FAILED; + } + if (stop_gracefully) { if (this->output_transfer_buffer_->available() == 0) { if (this->end_of_file_) { @@ -119,7 +140,7 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { return AudioDecoderState::FINISHED; } - if (!this->input_transfer_buffer_->has_buffered_data()) { + if (!this->input_buffer_->has_buffered_data()) { // If all the internal buffers are empty, the decoding is done return AudioDecoderState::FINISHED; } @@ -170,10 +191,10 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { // Only shift data on the first loop iteration to avoid unnecessary, slow moves // If the decoder buffers internally, then never shift - size_t bytes_read = this->input_transfer_buffer_->transfer_data_from_source( - pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), first_loop_iteration && !this->decoder_buffers_internally_); + size_t bytes_read = this->input_buffer_->fill(pdMS_TO_TICKS(READ_WRITE_TIMEOUT_MS), + first_loop_iteration && !this->decoder_buffers_internally_); - if (!first_loop_iteration && (this->input_transfer_buffer_->available() < bytes_processed)) { + if (!first_loop_iteration && (this->input_buffer_->available() < bytes_processed)) { // Less data is available than what was processed in last iteration, so don't attempt to decode. // This attempts to avoid the decoder from consistently trying to decode an incomplete frame. The transfer buffer // will shift the remaining data to the start and copy more from the source the next time the decode function is @@ -181,19 +202,21 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { break; } - bytes_available_before_processing = this->input_transfer_buffer_->available(); + bytes_available_before_processing = this->input_buffer_->available(); if ((this->potentially_failed_count_ > 0) && (bytes_read == 0)) { // Failed to decode in last attempt and there is no new data - if ((this->input_transfer_buffer_->free() == 0) && first_loop_iteration) { - // The input buffer is full. Since it previously failed on the exact same data, we can never recover + if ((this->input_buffer_->free() == 0) && first_loop_iteration) { + // The input buffer is full (or read-only, e.g. const flash source). Since it previously failed on the exact + // same data, we can never recover. For const sources this is correct: the entire file is already available, so + // a decode failure is genuine, not a transient out-of-data condition. state = FileDecoderState::FAILED; } else { // Attempt to get more data next time state = FileDecoderState::IDLE; } - } else if (this->input_transfer_buffer_->available() == 0) { + } else if (this->input_buffer_->available() == 0) { // No data to decode, attempt to get more data next time state = FileDecoderState::IDLE; } else { @@ -224,7 +247,7 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { } first_loop_iteration = false; - bytes_processed = bytes_available_before_processing - this->input_transfer_buffer_->available(); + bytes_processed = bytes_available_before_processing - this->input_buffer_->available(); if (state == FileDecoderState::POTENTIALLY_FAILED) { ++this->potentially_failed_count_; @@ -243,8 +266,7 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { FileDecoderState AudioDecoder::decode_flac_() { if (!this->audio_stream_info_.has_value()) { // Header hasn't been read - auto result = this->flac_decoder_->read_header(this->input_transfer_buffer_->get_buffer_start(), - this->input_transfer_buffer_->available()); + auto result = this->flac_decoder_->read_header(this->input_buffer_->data(), this->input_buffer_->available()); if (result > esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) { // Serrious error reading FLAC header, there is no recovery @@ -252,7 +274,7 @@ FileDecoderState AudioDecoder::decode_flac_() { } size_t bytes_consumed = this->flac_decoder_->get_bytes_index(); - this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed); + this->input_buffer_->consume(bytes_consumed); if (result == esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) { return FileDecoderState::MORE_TO_PROCESS; @@ -273,8 +295,7 @@ FileDecoderState AudioDecoder::decode_flac_() { } uint32_t output_samples = 0; - auto result = this->flac_decoder_->decode_frame(this->input_transfer_buffer_->get_buffer_start(), - this->input_transfer_buffer_->available(), + auto result = this->flac_decoder_->decode_frame(this->input_buffer_->data(), this->input_buffer_->available(), this->output_transfer_buffer_->get_buffer_end(), &output_samples); if (result == esp_audio_libs::flac::FLAC_DECODER_ERROR_OUT_OF_DATA) { @@ -283,7 +304,7 @@ FileDecoderState AudioDecoder::decode_flac_() { } size_t bytes_consumed = this->flac_decoder_->get_bytes_index(); - this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed); + this->input_buffer_->consume(bytes_consumed); if (result > esp_audio_libs::flac::FLAC_DECODER_ERROR_OUT_OF_DATA) { // Corrupted frame, don't retry with current buffer content, wait for new sync @@ -305,26 +326,25 @@ FileDecoderState AudioDecoder::decode_flac_() { #ifdef USE_AUDIO_MP3_SUPPORT FileDecoderState AudioDecoder::decode_mp3_() { // Look for the next sync word - int buffer_length = (int) this->input_transfer_buffer_->available(); - int32_t offset = - esp_audio_libs::helix_decoder::MP3FindSyncWord(this->input_transfer_buffer_->get_buffer_start(), buffer_length); + int buffer_length = (int) this->input_buffer_->available(); + int32_t offset = esp_audio_libs::helix_decoder::MP3FindSyncWord(this->input_buffer_->data(), buffer_length); if (offset < 0) { // New data may have the sync word - this->input_transfer_buffer_->decrease_buffer_length(buffer_length); + this->input_buffer_->consume(buffer_length); return FileDecoderState::POTENTIALLY_FAILED; } // Advance read pointer to match the offset for the syncword - this->input_transfer_buffer_->decrease_buffer_length(offset); - const uint8_t *buffer_start = this->input_transfer_buffer_->get_buffer_start(); + this->input_buffer_->consume(offset); + const uint8_t *buffer_start = this->input_buffer_->data(); - buffer_length = (int) this->input_transfer_buffer_->available(); + buffer_length = (int) this->input_buffer_->available(); int err = esp_audio_libs::helix_decoder::MP3Decode(this->mp3_decoder_, &buffer_start, &buffer_length, (int16_t *) this->output_transfer_buffer_->get_buffer_end(), 0); - size_t consumed = this->input_transfer_buffer_->available() - buffer_length; - this->input_transfer_buffer_->decrease_buffer_length(consumed); + size_t consumed = this->input_buffer_->available() - buffer_length; + this->input_buffer_->consume(consumed); if (err) { switch (err) { @@ -363,9 +383,8 @@ FileDecoderState AudioDecoder::decode_opus_() { size_t bytes_consumed, samples_decoded; micro_opus::OggOpusResult result = this->opus_decoder_->decode( - this->input_transfer_buffer_->get_buffer_start(), this->input_transfer_buffer_->available(), - this->output_transfer_buffer_->get_buffer_end(), this->output_transfer_buffer_->free(), bytes_consumed, - samples_decoded); + this->input_buffer_->data(), this->input_buffer_->available(), this->output_transfer_buffer_->get_buffer_end(), + this->output_transfer_buffer_->free(), bytes_consumed, samples_decoded); if (result == micro_opus::OGG_OPUS_OK) { if (!processed_header && this->opus_decoder_->is_initialized()) { @@ -379,7 +398,7 @@ FileDecoderState AudioDecoder::decode_opus_() { this->output_transfer_buffer_->increase_buffer_length( this->audio_stream_info_.value().frames_to_bytes(samples_decoded)); } - this->input_transfer_buffer_->decrease_buffer_length(bytes_consumed); + this->input_buffer_->consume(bytes_consumed); } else if (result == micro_opus::OGG_OPUS_OUTPUT_BUFFER_TOO_SMALL) { // Reallocate to decode the packet on the next call this->free_buffer_required_ = this->opus_decoder_->get_required_output_buffer_size(); @@ -399,11 +418,11 @@ FileDecoderState AudioDecoder::decode_wav_() { if (!this->audio_stream_info_.has_value()) { // Header hasn't been processed - esp_audio_libs::wav_decoder::WAVDecoderResult result = this->wav_decoder_->decode_header( - this->input_transfer_buffer_->get_buffer_start(), this->input_transfer_buffer_->available()); + esp_audio_libs::wav_decoder::WAVDecoderResult result = + this->wav_decoder_->decode_header(this->input_buffer_->data(), this->input_buffer_->available()); if (result == esp_audio_libs::wav_decoder::WAV_DECODER_SUCCESS_IN_DATA) { - this->input_transfer_buffer_->decrease_buffer_length(this->wav_decoder_->bytes_processed()); + this->input_buffer_->consume(this->wav_decoder_->bytes_processed()); this->audio_stream_info_ = audio::AudioStreamInfo( this->wav_decoder_->bits_per_sample(), this->wav_decoder_->num_channels(), this->wav_decoder_->sample_rate()); @@ -419,7 +438,7 @@ FileDecoderState AudioDecoder::decode_wav_() { } } else { if (!this->wav_has_known_end_ || (this->wav_bytes_left_ > 0)) { - size_t bytes_to_copy = this->input_transfer_buffer_->available(); + size_t bytes_to_copy = this->input_buffer_->available(); if (this->wav_has_known_end_) { bytes_to_copy = std::min(bytes_to_copy, this->wav_bytes_left_); @@ -428,9 +447,8 @@ FileDecoderState AudioDecoder::decode_wav_() { bytes_to_copy = std::min(bytes_to_copy, this->output_transfer_buffer_->free()); if (bytes_to_copy > 0) { - std::memcpy(this->output_transfer_buffer_->get_buffer_end(), this->input_transfer_buffer_->get_buffer_start(), - bytes_to_copy); - this->input_transfer_buffer_->decrease_buffer_length(bytes_to_copy); + std::memcpy(this->output_transfer_buffer_->get_buffer_end(), this->input_buffer_->data(), bytes_to_copy); + this->input_buffer_->consume(bytes_to_copy); this->output_transfer_buffer_->increase_buffer_length(bytes_to_copy); if (this->wav_has_known_end_) { this->wav_bytes_left_ -= bytes_to_copy; diff --git a/esphome/components/audio/audio_decoder.h b/esphome/components/audio/audio_decoder.h index cad16110ae..726baa289e 100644 --- a/esphome/components/audio/audio_decoder.h +++ b/esphome/components/audio/audio_decoder.h @@ -50,12 +50,12 @@ enum class FileDecoderState : uint8_t { class AudioDecoder { /* * @brief Class that facilitates decoding an audio file. - * The audio file is read from a ring buffer source, decoded, and sent to an audio sink (ring buffer or speaker - * component). + * The audio file is read from a source (ring buffer or const data pointer), decoded, and sent to an audio sink + * (ring buffer, speaker component, or callback). * Supports wav, flac, mp3, and ogg opus formats. */ public: - /// @brief Allocates the input and output transfer buffers + /// @brief Allocates the output transfer buffer and stores the input buffer size for later use by add_source() /// @param input_buffer_size Size of the input transfer buffer in bytes. /// @param output_buffer_size Size of the output transfer buffer in bytes. AudioDecoder(size_t input_buffer_size, size_t output_buffer_size); @@ -80,6 +80,17 @@ class AudioDecoder { esp_err_t add_sink(speaker::Speaker *speaker); #endif + /// @brief Adds a const data pointer as the source for raw file data. Does not allocate a transfer buffer. + /// @param data_pointer Pointer to the const audio data (e.g., stored in flash memory) + /// @param length Size of the data in bytes + /// @return ESP_OK + esp_err_t add_source(const uint8_t *data_pointer, size_t length); + + /// @brief Adds a callback as the sink for decoded audio. + /// @param callback Pointer to the AudioSinkCallback implementation + /// @return ESP_OK if successful, ESP_ERR_NO_MEM if the transfer buffer wasn't allocated + esp_err_t add_sink(AudioSinkCallback *callback); + /// @brief Sets up decoding the file /// @param audio_file_type AudioFileType of the file /// @return ESP_OK if successful, ESP_ERR_NO_MEM if the transfer buffers fail to allocate, or ESP_ERR_NOT_SUPPORTED if @@ -120,25 +131,26 @@ class AudioDecoder { #endif FileDecoderState decode_wav_(); - std::unique_ptr<AudioSourceTransferBuffer> input_transfer_buffer_; + std::unique_ptr<AudioReadableBuffer> input_buffer_; std::unique_ptr<AudioSinkTransferBuffer> output_transfer_buffer_; AudioFileType audio_file_type_{AudioFileType::NONE}; optional<AudioStreamInfo> audio_stream_info_{}; + size_t input_buffer_size_{0}; size_t free_buffer_required_{0}; size_t wav_bytes_left_{0}; uint32_t potentially_failed_count_{0}; + uint32_t accumulated_frames_written_{0}; + uint32_t playback_ms_{0}; + bool end_of_file_{false}; bool wav_has_known_end_{false}; bool decoder_buffers_internally_{false}; bool pause_output_{false}; - - uint32_t accumulated_frames_written_{0}; - uint32_t playback_ms_{0}; }; } // namespace audio } // namespace esphome diff --git a/esphome/components/audio/audio_transfer_buffer.cpp b/esphome/components/audio/audio_transfer_buffer.cpp index a8be55d62f..5cd7cf9e63 100644 --- a/esphome/components/audio/audio_transfer_buffer.cpp +++ b/esphome/components/audio/audio_transfer_buffer.cpp @@ -142,7 +142,7 @@ size_t AudioSourceTransferBuffer::transfer_data_from_source(TickType_t ticks_to_ this->data_start_ = this->buffer_; } - size_t bytes_to_read = this->free(); + size_t bytes_to_read = AudioTransferBuffer::free(); size_t bytes_read = 0; if (bytes_to_read > 0) { if (this->ring_buffer_.use_count() > 0) { @@ -193,6 +193,21 @@ bool AudioSinkTransferBuffer::has_buffered_data() const { return (this->available() > 0); } +size_t AudioSourceTransferBuffer::free() const { return AudioTransferBuffer::free(); } + +bool AudioSourceTransferBuffer::has_buffered_data() const { return AudioTransferBuffer::has_buffered_data(); } + +void ConstAudioSourceBuffer::set_data(const uint8_t *data, size_t length) { + this->data_start_ = data; + this->length_ = length; +} + +void ConstAudioSourceBuffer::consume(size_t bytes) { + bytes = std::min(bytes, this->length_); + this->length_ -= bytes; + this->data_start_ += bytes; +} + } // namespace audio } // namespace esphome diff --git a/esphome/components/audio/audio_transfer_buffer.h b/esphome/components/audio/audio_transfer_buffer.h index 22c22cc9ae..c32d4d0e41 100644 --- a/esphome/components/audio/audio_transfer_buffer.h +++ b/esphome/components/audio/audio_transfer_buffer.h @@ -32,7 +32,7 @@ class AudioTransferBuffer { /// @brief Destructor that deallocates the transfer buffer ~AudioTransferBuffer(); - /// @brief Returns a pointer to the start of the transfer buffer where available() bytes of exisiting data can be read + /// @brief Returns a pointer to the start of the transfer buffer where available() bytes of existing data can be read uint8_t *get_buffer_start() const { return this->data_start_; } /// @brief Returns a pointer to the end of the transfer buffer where free() bytes of new data can be written @@ -129,10 +129,41 @@ class AudioSinkTransferBuffer : public AudioTransferBuffer { AudioSinkCallback *sink_callback_{nullptr}; }; -class AudioSourceTransferBuffer : public AudioTransferBuffer { +/// @brief Abstract interface for reading audio data from a buffer. +/// Provides a common read interface for both mutable transfer buffers and read-only const buffers. +class AudioReadableBuffer { + public: + virtual ~AudioReadableBuffer() = default; + + /// @brief Returns a pointer to the start of readable data + virtual const uint8_t *data() const = 0; + + /// @brief Returns the number of bytes available to read + virtual size_t available() const = 0; + + /// @brief Returns the number of free bytes available to write. Defaults to 0 for read-only buffers. + virtual size_t free() const { return 0; } + + /// @brief Advances past consumed data + /// @param bytes Number of bytes consumed + virtual void consume(size_t bytes) = 0; + + /// @brief Tests if there is any buffered data + virtual bool has_buffered_data() const = 0; + + /// @brief Refills the buffer from its source. No-op by default for read-only buffers. + /// @param ticks_to_wait FreeRTOS ticks to block while waiting for data + /// @param pre_shift If true, shifts existing data to the start of the buffer before reading + /// @return Number of bytes read + virtual size_t fill(TickType_t ticks_to_wait, bool pre_shift) { return 0; } + size_t fill(TickType_t ticks_to_wait) { return this->fill(ticks_to_wait, true); } +}; + +class AudioSourceTransferBuffer : public AudioTransferBuffer, public AudioReadableBuffer { /* * @brief A class that implements a transfer buffer for audio sources. * Supports reading audio data from a ring buffer into the transfer buffer for processing. + * Implements AudioReadableBuffer for use by consumers that only need read access. */ public: /// @brief Creates a new source transfer buffer. @@ -140,7 +171,7 @@ class AudioSourceTransferBuffer : public AudioTransferBuffer { /// @return unique_ptr if successfully allocated, nullptr otherwise static std::unique_ptr<AudioSourceTransferBuffer> create(size_t buffer_size); - /// @brief Reads any available data from the sink into the transfer buffer. + /// @brief Reads any available data from the source into the transfer buffer. /// @param ticks_to_wait FreeRTOS ticks to block while waiting for the source to have enough data /// @param pre_shift If true, any unwritten data is moved to the start of the buffer before transferring from the /// source. Defaults to true. @@ -150,6 +181,36 @@ class AudioSourceTransferBuffer : public AudioTransferBuffer { /// @brief Adds a ring buffer as the transfer buffer's source. /// @param ring_buffer weak_ptr to the allocated ring buffer void set_source(const std::weak_ptr<RingBuffer> &ring_buffer) { this->ring_buffer_ = ring_buffer.lock(); }; + + // AudioReadableBuffer interface + const uint8_t *data() const override { return this->data_start_; } + size_t available() const override { return this->buffer_length_; } + size_t free() const override; + void consume(size_t bytes) override { this->decrease_buffer_length(bytes); } + bool has_buffered_data() const override; + size_t fill(TickType_t ticks_to_wait, bool pre_shift) override { + return this->transfer_data_from_source(ticks_to_wait, pre_shift); + } +}; + +/// @brief A lightweight read-only audio buffer for const data sources (e.g., flash memory). +/// Does not allocate memory or transfer data from external sources. +class ConstAudioSourceBuffer : public AudioReadableBuffer { + public: + /// @brief Sets the data pointer and length for the buffer + /// @param data Pointer to the const audio data + /// @param length Size of the data in bytes + void set_data(const uint8_t *data, size_t length); + + // AudioReadableBuffer interface + const uint8_t *data() const override { return this->data_start_; } + size_t available() const override { return this->length_; } + void consume(size_t bytes) override; + bool has_buffered_data() const override { return this->length_ > 0; } + + protected: + const uint8_t *data_start_{nullptr}; + size_t length_{0}; }; } // namespace audio From bd50b80882d990855561216548965d4c01aad9fd Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:34:40 -0500 Subject: [PATCH 0788/2030] [opentherm] Remove deprecated opentherm_version config option (#14103) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/opentherm/__init__.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/esphome/components/opentherm/__init__.py b/esphome/components/opentherm/__init__.py index dddb9dc891..36f85a9766 100644 --- a/esphome/components/opentherm/__init__.py +++ b/esphome/components/opentherm/__init__.py @@ -1,4 +1,3 @@ -import logging from typing import Any from esphome import automation, pins @@ -24,7 +23,6 @@ CONF_CH2_ACTIVE = "ch2_active" CONF_SUMMER_MODE_ACTIVE = "summer_mode_active" CONF_DHW_BLOCK = "dhw_block" CONF_SYNC_MODE = "sync_mode" -CONF_OPENTHERM_VERSION = "opentherm_version" # Deprecated, will be removed CONF_BEFORE_SEND = "before_send" CONF_BEFORE_PROCESS_RESPONSE = "before_process_response" @@ -38,8 +36,6 @@ BeforeProcessResponseTrigger = generate.opentherm_ns.class_( automation.Trigger.template(generate.OpenthermData.operator("ref")), ) -_LOGGER = logging.getLogger(__name__) - CONFIG_SCHEMA = cv.All( cv.Schema( { @@ -54,7 +50,6 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_SUMMER_MODE_ACTIVE, False): cv.boolean, cv.Optional(CONF_DHW_BLOCK, False): cv.boolean, cv.Optional(CONF_SYNC_MODE, False): cv.boolean, - cv.Optional(CONF_OPENTHERM_VERSION): cv.positive_float, # Deprecated cv.Optional(CONF_BEFORE_SEND): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BeforeSendTrigger), @@ -123,11 +118,6 @@ async def to_code(config: dict[str, Any]) -> None: cg.add(getattr(var, f"set_{key}_{const.SETTING}")(value)) settings.append(key) else: - if key == CONF_OPENTHERM_VERSION: - _LOGGER.warning( - "opentherm_version is deprecated and will be removed in esphome 2025.2.0\n" - "Please change to 'opentherm_version_controller'." - ) cg.add(getattr(var, f"set_{key}")(value)) if len(input_sensors) > 0: From bf2e22da4f7ebf660d517f27702500a67d11ea9b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:55:03 -0500 Subject: [PATCH 0789/2030] [esp32] Remove deprecated add_idf_component() parameters and IDF component refresh option (#14105) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 68 ++++++---------------------- 1 file changed, 14 insertions(+), 54 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 8b3e1afea6..b1b3f0dc16 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -25,7 +25,6 @@ from esphome.const import ( CONF_PLATFORM_VERSION, CONF_PLATFORMIO_OPTIONS, CONF_REF, - CONF_REFRESH, CONF_SAFE_MODE, CONF_SOURCE, CONF_TYPE, @@ -41,7 +40,7 @@ from esphome.const import ( ThreadModel, __version__, ) -from esphome.core import CORE, HexInt, TimePeriod +from esphome.core import CORE, HexInt from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed @@ -499,49 +498,24 @@ def add_idf_component( repo: str | None = None, ref: str | None = None, path: str | None = None, - refresh: TimePeriod | None = None, - components: list[str] | None = None, - submodules: list[str] | None = None, ): """Add an esp-idf component to the project.""" if not repo and not ref and not path: raise ValueError("Requires at least one of repo, ref or path") - if refresh or submodules or components: - _LOGGER.warning( - "The refresh, components and submodules parameters in add_idf_component() are " - "deprecated and will be removed in ESPHome 2026.1. If you are seeing this, report " - "an issue to the external_component author and ask them to update it." - ) components_registry = CORE.data[KEY_ESP32][KEY_COMPONENTS] - if components: - for comp in components: - existing = components_registry.get(comp) - if existing and existing.get(KEY_REF) != ref: - _LOGGER.warning( - "IDF component %s version conflict %s replaced by %s", - comp, - existing.get(KEY_REF), - ref, - ) - components_registry[comp] = { - KEY_REPO: repo, - KEY_REF: ref, - KEY_PATH: f"{path}/{comp}" if path else comp, - } - else: - existing = components_registry.get(name) - if existing and existing.get(KEY_REF) != ref: - _LOGGER.warning( - "IDF component %s version conflict %s replaced by %s", - name, - existing.get(KEY_REF), - ref, - ) - components_registry[name] = { - KEY_REPO: repo, - KEY_REF: ref, - KEY_PATH: path, - } + existing = components_registry.get(name) + if existing and existing.get(KEY_REF) != ref: + _LOGGER.warning( + "IDF component %s version conflict %s replaced by %s", + name, + existing.get(KEY_REF), + ref, + ) + components_registry[name] = { + KEY_REPO: repo, + KEY_REF: ref, + KEY_PATH: path, + } def exclude_builtin_idf_component(name: str) -> None: @@ -1037,16 +1011,6 @@ def _parse_idf_component(value: str) -> ConfigType: ) -def _validate_idf_component(config: ConfigType) -> ConfigType: - """Validate IDF component config and warn about deprecated options.""" - if CONF_REFRESH in config: - _LOGGER.warning( - "The 'refresh' option for IDF components is deprecated and has no effect. " - "It will be removed in ESPHome 2026.1. Please remove it from your configuration." - ) - return config - - FRAMEWORK_ESP_IDF = "esp-idf" FRAMEWORK_ARDUINO = "arduino" FRAMEWORK_SCHEMA = cv.Schema( @@ -1135,13 +1099,9 @@ FRAMEWORK_SCHEMA = cv.Schema( cv.Optional(CONF_SOURCE): cv.git_ref, cv.Optional(CONF_REF): cv.string, cv.Optional(CONF_PATH): cv.string, - cv.Optional(CONF_REFRESH): cv.All( - cv.string, cv.source_refresh - ), } ), ), - _validate_idf_component, ) ), } From ed74790eed87afff0f252fb2330dceb9b1a293de Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:56:06 -0500 Subject: [PATCH 0790/2030] [i2c] Remove deprecated stop parameter overloads and readv/writev methods (#14106) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/i2c/i2c.h | 31 ----------------- esphome/components/i2c/i2c_bus.h | 58 -------------------------------- 2 files changed, 89 deletions(-) diff --git a/esphome/components/i2c/i2c.h b/esphome/components/i2c/i2c.h index 48a6e751cf..aab98d5f46 100644 --- a/esphome/components/i2c/i2c.h +++ b/esphome/components/i2c/i2c.h @@ -267,37 +267,6 @@ class I2CDevice { bool write_byte_16(uint8_t a_register, uint16_t data) const { return write_bytes_16(a_register, &data, 1); } - // Deprecated functions - - ESPDEPRECATED("The stop argument is no longer used. This will be removed from ESPHome 2026.3.0", "2025.9.0") - ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop) { - return this->read_register(a_register, data, len); - } - - ESPDEPRECATED("The stop argument is no longer used. This will be removed from ESPHome 2026.3.0", "2025.9.0") - ErrorCode read_register16(uint16_t a_register, uint8_t *data, size_t len, bool stop) { - return this->read_register16(a_register, data, len); - } - - ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be " - "removed from ESPHome 2026.3.0", - "2025.9.0") - ErrorCode write(const uint8_t *data, size_t len, bool stop) const { return this->write(data, len); } - - ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be " - "removed from ESPHome 2026.3.0", - "2025.9.0") - ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop) const { - return this->write_register(a_register, data, len); - } - - ESPDEPRECATED("The stop argument is no longer used; use write_read() for consecutive write and read. This will be " - "removed from ESPHome 2026.3.0", - "2025.9.0") - ErrorCode write_register16(uint16_t a_register, const uint8_t *data, size_t len, bool stop) const { - return this->write_register16(a_register, data, len); - } - protected: uint8_t address_{0x00}; ///< store the address of the device on the bus I2CBus *bus_{nullptr}; ///< pointer to I2CBus instance diff --git a/esphome/components/i2c/i2c_bus.h b/esphome/components/i2c/i2c_bus.h index 3de5d5ca7b..2bc0dc1ef9 100644 --- a/esphome/components/i2c/i2c_bus.h +++ b/esphome/components/i2c/i2c_bus.h @@ -1,8 +1,6 @@ #pragma once #include <cstddef> #include <cstdint> -#include <cstring> -#include <memory> #include <utility> #include <vector> @@ -24,18 +22,6 @@ enum ErrorCode { ERROR_CRC = 7, ///< bytes received with a CRC error }; -/// @brief the ReadBuffer structure stores a pointer to a read buffer and its length -struct ReadBuffer { - uint8_t *data; ///< pointer to the read buffer - size_t len; ///< length of the buffer -}; - -/// @brief the WriteBuffer structure stores a pointer to a write buffer and its length -struct WriteBuffer { - const uint8_t *data; ///< pointer to the write buffer - size_t len; ///< length of the buffer -}; - /// @brief This Class provides the methods to read and write bytes from an I2CBus. /// @note The I2CBus virtual class follows a *Factory design pattern* that provides all the interfaces methods required /// by clients while deferring the actual implementation of these methods to a subclasses. I2C-bus specification and @@ -68,50 +54,6 @@ class I2CBus { return this->write_readv(address, buffer, len, nullptr, 0); } - ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.", - "2025.9.0") - ErrorCode readv(uint8_t address, ReadBuffer *read_buffers, size_t count) { - size_t total_len = 0; - for (size_t i = 0; i != count; i++) { - total_len += read_buffers[i].len; - } - - SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C reads are small - uint8_t *buffer = buffer_alloc.get(); - - auto err = this->write_readv(address, nullptr, 0, buffer, total_len); - if (err != ERROR_OK) - return err; - size_t pos = 0; - for (size_t i = 0; i != count; i++) { - if (read_buffers[i].len != 0) { - std::memcpy(read_buffers[i].data, buffer + pos, read_buffers[i].len); - pos += read_buffers[i].len; - } - } - return ERROR_OK; - } - - ESPDEPRECATED("This method is deprecated and will be removed in ESPHome 2026.3.0. Use write_readv() instead.", - "2025.9.0") - ErrorCode writev(uint8_t address, const WriteBuffer *write_buffers, size_t count, bool stop = true) { - size_t total_len = 0; - for (size_t i = 0; i != count; i++) { - total_len += write_buffers[i].len; - } - - SmallBufferWithHeapFallback<128> buffer_alloc(total_len); // Most I2C writes are small - uint8_t *buffer = buffer_alloc.get(); - - size_t pos = 0; - for (size_t i = 0; i != count; i++) { - std::memcpy(buffer + pos, write_buffers[i].data, write_buffers[i].len); - pos += write_buffers[i].len; - } - - return this->write_readv(address, buffer, total_len, nullptr, 0); - } - protected: /// @brief Scans the I2C bus for devices. Devices presence is kept in an array of std::pair /// that contains the address and the corresponding bool presence flag. From d2026b4cd74bbeb9b86941bf1887f3d93d639387 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 19 Feb 2026 10:56:34 -0600 Subject: [PATCH 0791/2030] [audio] Disable FLAC CRC validation to improve decoding efficiency (#14108) --- esphome/components/audio/audio_decoder.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/audio/audio_decoder.cpp b/esphome/components/audio/audio_decoder.cpp index 7794b5b0d3..bc05bc0006 100644 --- a/esphome/components/audio/audio_decoder.cpp +++ b/esphome/components/audio/audio_decoder.cpp @@ -85,6 +85,10 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) { #ifdef USE_AUDIO_FLAC_SUPPORT case AudioFileType::FLAC: this->flac_decoder_ = make_unique<esp_audio_libs::flac::FLACDecoder>(); + // CRC check slows down decoding by 15-20% on an ESP32-S3. FLAC sources in ESPHome are either from an http source + // or built into the firmware, so the data integrity is already verified by the time it gets to the decoder, + // making the CRC check unnecessary. + this->flac_decoder_->set_crc_check_enabled(false); this->free_buffer_required_ = this->output_transfer_buffer_->capacity(); // Adjusted and reallocated after reading the header break; From da616e05574af7216a3b5668ab1d2d0e3dce0ca1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:00:05 -0500 Subject: [PATCH 0792/2030] [ethernet] Improve clk_mode deprecation warning with actionable YAML (#14104) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ethernet/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 52f5f44d41..935d2004d4 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -218,12 +218,19 @@ def _validate(config): ) elif config[CONF_TYPE] != "OPENETH": if CONF_CLK_MODE in config: + mode, pin = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] LOGGER.warning( - "[ethernet] The 'clk_mode' option is deprecated and will be removed in ESPHome 2026.1. " - "Please update your configuration to use 'clk' instead." + "[ethernet] The 'clk_mode' option is deprecated. " + "Please replace 'clk_mode: %s' with:\n" + " clk:\n" + " mode: %s\n" + " pin: %s\n" + "Removal scheduled for 2026.7.0.", + config[CONF_CLK_MODE], + mode, + pin, ) - mode = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] - config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode[0], CONF_PIN: mode[1]}) + config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode, CONF_PIN: pin}) del config[CONF_CLK_MODE] elif CONF_CLK not in config: raise cv.Invalid("'clk' is a required option for [ethernet].") From 9aa17984df3a0766c18c02ed60f4575ba69a7fb9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:25:26 -0500 Subject: [PATCH 0793/2030] [pulse_counter] Fix build failure when use_pcnt is false (#14111) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/pulse_counter/pulse_counter_sensor.h | 4 ++-- .../pulse_counter/test-no-pcnt.esp32-idf.yaml | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index a7913d5d66..7a68858099 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -8,10 +8,10 @@ #if defined(USE_ESP32) #include <soc/soc_caps.h> -#ifdef SOC_PCNT_SUPPORTED +#if defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>) #include <driver/pulse_cnt.h> #define HAS_PCNT -#endif // SOC_PCNT_SUPPORTED +#endif // defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>) #endif // USE_ESP32 namespace esphome { diff --git a/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml b/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml new file mode 100644 index 0000000000..cd15cc781d --- /dev/null +++ b/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + use_pcnt: false + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s From 7a5c3cee0d0f3fd77423438f036e8b6596a3246b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 11:41:00 -0600 Subject: [PATCH 0794/2030] [esp32_ble] Enable CONFIG_BT_RELEASE_IRAM on ESP32-C2 (#14109) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_ble/__init__.py | 10 ++++++++++ tests/components/esp32_ble/test.esp32-c2-idf.yaml | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 tests/components/esp32_ble/test.esp32-c2-idf.yaml diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index dcc3ce71cf..d2020ada22 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -9,6 +9,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import socket from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +from esphome.components.esp32.const import VARIANT_ESP32C2 import esphome.config_validation as cv from esphome.const import ( CONF_ENABLE_ON_BOOT, @@ -387,6 +388,15 @@ def final_validation(config): f"Name '{name}' is too long, maximum length is {max_length} characters" ) + # ESP32-C2 has very limited RAM (~272KB). Without releasing BLE IRAM, + # esp_bt_controller_init fails with ESP_ERR_NO_MEM. + # CONFIG_BT_RELEASE_IRAM changes the memory layout so IRAM and DRAM share + # space more flexibly, giving the BT controller enough contiguous memory. + # This requires CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT to be disabled. + if get_esp32_variant() == VARIANT_ESP32C2: + add_idf_sdkconfig_option("CONFIG_BT_RELEASE_IRAM", True) + add_idf_sdkconfig_option("CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT", False) + # Set GATT Client/Server sdkconfig options based on which components are loaded full_config = fv.full_config.get() diff --git a/tests/components/esp32_ble/test.esp32-c2-idf.yaml b/tests/components/esp32_ble/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..f8defaf28f --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-c2-idf.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +esp32_ble: + io_capability: keyboard_only + disable_bt_logs: false From f2c98d612607d61c483d08cc77e92795af85c131 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:45:04 -0500 Subject: [PATCH 0795/2030] [safe_mode] Log brownout as reset reason on OTA rollback (#14113) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/safe_mode/safe_mode.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index f32511531a..6cae4bf9d5 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -11,6 +11,7 @@ #if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) #include <esp_ota_ops.h> +#include <esp_system.h> #endif namespace esphome::safe_mode { @@ -54,6 +55,10 @@ void SafeModeComponent::dump_config() { "OTA rollback detected! Rolled back from partition '%s'\n" "The device reset before the boot was marked successful", last_invalid->label); + if (esp_reset_reason() == ESP_RST_BROWNOUT) { + ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!\n" + "See https://esphome.io/guides/faq.html#brownout-detector-was-triggered"); + } } #endif } From 4aa8f57d3609c12c10c3877c83b06d0c52975e7a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 14:08:44 -0600 Subject: [PATCH 0796/2030] [json] Add SerializationBuffer for stack-first JSON serialization (#13625) --- esphome/components/api/user_services.h | 4 +- esphome/components/json/json_util.cpp | 81 +++++++- esphome/components/json/json_util.h | 111 +++++++++- esphome/components/mqtt/mqtt_client.cpp | 4 +- esphome/components/web_server/web_server.cpp | 191 +++++++++--------- esphome/components/web_server/web_server.h | 138 +++++++------ .../web_server_idf/web_server_idf.cpp | 6 +- .../web_server_idf/web_server_idf.h | 3 +- tests/components/json/common.yaml | 13 +- 9 files changed, 367 insertions(+), 184 deletions(-) diff --git a/esphome/components/api/user_services.h b/esphome/components/api/user_services.h index 85fba2a435..0fc529108c 100644 --- a/esphome/components/api/user_services.h +++ b/esphome/components/api/user_services.h @@ -264,9 +264,9 @@ template<typename... Ts> class APIRespondAction : public Action<Ts...> { // Build and send JSON response json::JsonBuilder builder; this->json_builder_(x..., builder.root()); - std::string json_str = builder.serialize(); + auto json_buf = builder.serialize(); this->parent_->send_action_response(call_id, success, StringRef(error_message), - reinterpret_cast<const uint8_t *>(json_str.data()), json_str.size()); + reinterpret_cast<const uint8_t *>(json_buf.data()), json_buf.size()); return; } #endif diff --git a/esphome/components/json/json_util.cpp b/esphome/components/json/json_util.cpp index 69f8bfc61a..6c60a04d20 100644 --- a/esphome/components/json/json_util.cpp +++ b/esphome/components/json/json_util.cpp @@ -15,7 +15,7 @@ static const char *const TAG = "json"; static SpiRamAllocator global_json_allocator; #endif -std::string build_json(const json_build_t &f) { +SerializationBuffer<> build_json(const json_build_t &f) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson JsonBuilder builder; JsonObject root = builder.root(); @@ -66,14 +66,83 @@ JsonDocument parse_json(const uint8_t *data, size_t len) { // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) } -std::string JsonBuilder::serialize() { +SerializationBuffer<> JsonBuilder::serialize() { + // =========================================================================================== + // CRITICAL: NRVO (Named Return Value Optimization) - DO NOT REFACTOR WITHOUT UNDERSTANDING + // =========================================================================================== + // + // This function is carefully structured to enable NRVO. The compiler constructs `result` + // directly in the caller's stack frame, eliminating the move constructor call entirely. + // + // WITHOUT NRVO: Each return would trigger SerializationBuffer's move constructor, which + // must memcpy up to 512 bytes of stack buffer content. This happens on EVERY JSON + // serialization (sensor updates, web server responses, MQTT publishes, etc.). + // + // WITH NRVO: Zero memcpy, zero move constructor overhead. The buffer lives directly + // where the caller needs it. + // + // Requirements for NRVO to work: + // 1. Single named variable (`result`) returned from ALL paths + // 2. All paths must return the SAME variable (not different variables) + // 3. No std::move() on the return statement + // + // If you must modify this function: + // - Keep a single `result` variable declared at the top + // - All code paths must return `result` (not a different variable) + // - Verify NRVO still works by checking the disassembly for move constructor calls + // - Test: objdump -d -C firmware.elf | grep "SerializationBuffer.*SerializationBuffer" + // Should show only destructor, NOT move constructor + // + // Try stack buffer first. 640 bytes covers 99.9% of JSON payloads (sensors ~200B, + // lights ~170B, climate ~500-700B). Only entities with 40+ options exceed this. + // + // IMPORTANT: ArduinoJson's serializeJson() with a bounded buffer returns the actual + // bytes written (truncated count), NOT the would-be size like snprintf(). When the + // payload exceeds the buffer, the return value equals the buffer capacity. The heap + // fallback doubles the buffer size until the payload fits. This avoids instantiating + // measureJson()'s DummyWriter templates (~736 bytes flash) at the cost of temporarily + // over-allocating heap (at most 2x) for the rare payloads that exceed 640 bytes. + // + // =========================================================================================== + constexpr size_t buf_size = SerializationBuffer<>::BUFFER_SIZE; + SerializationBuffer<> result(buf_size - 1); // Max content size (reserve 1 for null) + if (doc_.overflowed()) { ESP_LOGE(TAG, "JSON document overflow"); - return "{}"; + auto *buf = result.data_writable_(); + buf[0] = '{'; + buf[1] = '}'; + buf[2] = '\0'; + result.set_size_(2); + return result; } - std::string output; - serializeJson(doc_, output); - return output; + + size_t size = serializeJson(doc_, result.data_writable_(), buf_size); + if (size < buf_size) { + // Fits in stack buffer - update size to actual length + result.set_size_(size); + return result; + } + + // Payload exceeded stack buffer. Double the buffer and retry until it fits. + // In practice, one iteration (1024 bytes) covers all known entity types. + // Payloads exceeding 1024 bytes are not known to exist in real configurations. + // Cap at 5120 as a safety limit to prevent runaway allocation. + constexpr size_t max_heap_size = 5120; + size_t heap_size = buf_size * 2; + while (heap_size <= max_heap_size) { + result.reallocate_heap_(heap_size - 1); + size = serializeJson(doc_, result.data_writable_(), heap_size); + if (size < heap_size) { + result.set_size_(size); + return result; + } + heap_size *= 2; + } + // Payload exceeds 5120 bytes - return truncated result + ESP_LOGW(TAG, "JSON payload too large, truncated to %zu bytes", size); + result.set_size_(size); + return result; } } // namespace json diff --git a/esphome/components/json/json_util.h b/esphome/components/json/json_util.h index c472b9a9ec..0dc9ff883c 100644 --- a/esphome/components/json/json_util.h +++ b/esphome/components/json/json_util.h @@ -1,5 +1,7 @@ #pragma once +#include <cstring> +#include <string> #include <vector> #include "esphome/core/defines.h" @@ -14,6 +16,108 @@ namespace esphome { namespace json { +/// Buffer for JSON serialization that uses stack allocation for small payloads. +/// Template parameter STACK_SIZE specifies the stack buffer size (default 512 bytes). +/// Supports move semantics for efficient return-by-value. +template<size_t STACK_SIZE = 640> class SerializationBuffer { + public: + static constexpr size_t BUFFER_SIZE = STACK_SIZE; ///< Stack buffer size for this instantiation + + /// Construct with known size (typically from measureJson) + explicit SerializationBuffer(size_t size) : size_(size) { + if (size + 1 <= STACK_SIZE) { + buffer_ = stack_buffer_; + } else { + heap_buffer_ = new char[size + 1]; + buffer_ = heap_buffer_; + } + buffer_[0] = '\0'; + } + + ~SerializationBuffer() { delete[] heap_buffer_; } + + // Move constructor - works with same template instantiation + SerializationBuffer(SerializationBuffer &&other) noexcept : heap_buffer_(other.heap_buffer_), size_(other.size_) { + if (other.buffer_ == other.stack_buffer_) { + // Stack buffer - must copy content + std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1); + buffer_ = stack_buffer_; + } else { + // Heap buffer - steal ownership + buffer_ = heap_buffer_; + other.heap_buffer_ = nullptr; + } + // Leave moved-from object in valid empty state + other.stack_buffer_[0] = '\0'; + other.buffer_ = other.stack_buffer_; + other.size_ = 0; + } + + // Move assignment + SerializationBuffer &operator=(SerializationBuffer &&other) noexcept { + if (this != &other) { + delete[] heap_buffer_; + heap_buffer_ = other.heap_buffer_; + size_ = other.size_; + if (other.buffer_ == other.stack_buffer_) { + std::memcpy(stack_buffer_, other.stack_buffer_, size_ + 1); + buffer_ = stack_buffer_; + } else { + buffer_ = heap_buffer_; + other.heap_buffer_ = nullptr; + } + // Leave moved-from object in valid empty state + other.stack_buffer_[0] = '\0'; + other.buffer_ = other.stack_buffer_; + other.size_ = 0; + } + return *this; + } + + // Delete copy operations + SerializationBuffer(const SerializationBuffer &) = delete; + SerializationBuffer &operator=(const SerializationBuffer &) = delete; + + /// Get null-terminated C string + const char *c_str() const { return buffer_; } + /// Get data pointer + const char *data() const { return buffer_; } + /// Get string length (excluding null terminator) + size_t size() const { return size_; } + + /// Implicit conversion to std::string for backward compatibility + /// WARNING: This allocates a new std::string on the heap. Prefer using + /// c_str() or data()/size() directly when possible to avoid allocation. + operator std::string() const { return std::string(buffer_, size_); } // NOLINT(google-explicit-constructor) + + private: + friend class JsonBuilder; ///< Allows JsonBuilder::serialize() to call private methods + + /// Get writable buffer (for serialization) + char *data_writable_() { return buffer_; } + /// Set actual size after serialization (must not exceed allocated size) + /// Also ensures null termination for c_str() safety + void set_size_(size_t size) { + size_ = size; + buffer_[size] = '\0'; + } + + /// Reallocate to heap buffer with new size (for when stack buffer is too small) + /// This invalidates any previous buffer content. Used by JsonBuilder::serialize(). + void reallocate_heap_(size_t size) { + delete[] heap_buffer_; + heap_buffer_ = new char[size + 1]; + buffer_ = heap_buffer_; + size_ = size; + buffer_[0] = '\0'; + } + + char stack_buffer_[STACK_SIZE]; + char *heap_buffer_{nullptr}; + char *buffer_; + size_t size_; +}; + #ifdef USE_PSRAM // Build an allocator for the JSON Library using the RAMAllocator class // This is only compiled when PSRAM is enabled @@ -47,7 +151,8 @@ using json_parse_t = std::function<bool(JsonObject)>; using json_build_t = std::function<void(JsonObject)>; /// Build a JSON string with the provided json build function. -std::string build_json(const json_build_t &f); +/// Returns SerializationBuffer for stack-first allocation; implicitly converts to std::string. +SerializationBuffer<> build_json(const json_build_t &f); /// Parse a JSON string and run the provided json parse function if it's valid. bool parse_json(const std::string &data, const json_parse_t &f); @@ -72,7 +177,9 @@ class JsonBuilder { return root_; } - std::string serialize(); + /// Serialize the JSON document to a SerializationBuffer (stack-first allocation) + /// Uses 512-byte stack buffer by default, falls back to heap for larger JSON + SerializationBuffer<> serialize(); private: #ifdef USE_PSRAM diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 9905b4677e..c433804dd9 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -543,8 +543,8 @@ bool MQTTClientComponent::publish(const char *topic, const char *payload, size_t } bool MQTTClientComponent::publish_json(const char *topic, const json::json_build_t &f, uint8_t qos, bool retain) { - std::string message = json::build_json(f); - return this->publish(topic, message.c_str(), message.length(), qos, retain); + auto message = json::build_json(f); + return this->publish(topic, message.c_str(), message.size(), qos, retain); } void MQTTClientComponent::enable() { diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index f352e5896c..4b572417c1 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -214,7 +214,7 @@ DeferredUpdateEventSource::deq_push_back_with_dedup_(void *source, message_gener void DeferredUpdateEventSource::process_deferred_queue_() { while (!deferred_queue_.empty()) { DeferredEvent &de = deferred_queue_.front(); - std::string message = de.message_generator_(web_server_, de.source_); + auto message = de.message_generator_(web_server_, de.source_); if (this->send(message.c_str(), "state") != DISCARDED) { // O(n) but memory efficiency is more important than speed here which is why std::vector was chosen deferred_queue_.erase(deferred_queue_.begin()); @@ -271,7 +271,7 @@ void DeferredUpdateEventSource::deferrable_send_state(void *source, const char * // deferred queue still not empty which means downstream event queue full, no point trying to send first deq_push_back_with_dedup_(source, message_generator); } else { - std::string message = message_generator(web_server_, source); + auto message = message_generator(web_server_, source); if (this->send(message.c_str(), "state") == DISCARDED) { deq_push_back_with_dedup_(source, message_generator); } else { @@ -325,7 +325,7 @@ void DeferredUpdateEventSourceList::on_client_connect_(DeferredUpdateEventSource ws->defer([ws, source]() { // Configure reconnect timeout and send config // this should always go through since the AsyncEventSourceClient event queue is empty on connect - std::string message = ws->get_config_json(); + auto message = ws->get_config_json(); source->try_send_nodefer(message.c_str(), "ping", millis(), 30000); #ifdef USE_WEBSERVER_SORTING @@ -334,10 +334,10 @@ void DeferredUpdateEventSourceList::on_client_connect_(DeferredUpdateEventSource JsonObject root = builder.root(); root[ESPHOME_F("name")] = group.second.name; root[ESPHOME_F("sorting_weight")] = group.second.weight; - message = builder.serialize(); + auto group_msg = builder.serialize(); // up to 31 groups should be able to be queued initially without defer - source->try_send_nodefer(message.c_str(), "sorting_group"); + source->try_send_nodefer(group_msg.c_str(), "sorting_group"); } #endif @@ -370,7 +370,7 @@ void WebServer::set_css_include(const char *css_include) { this->css_include_ = void WebServer::set_js_include(const char *js_include) { this->js_include_ = js_include; } #endif -std::string WebServer::get_config_json() { +json::SerializationBuffer<> WebServer::get_config_json() { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -606,20 +606,20 @@ void WebServer::handle_sensor_request(AsyncWebServerRequest *request, const UrlM // Note: request->method() is always HTTP_GET here (canHandle ensures this) if (entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->sensor_json_(obj, obj->state, detail); + auto data = this->sensor_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } } request->send(404); } -std::string WebServer::sensor_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::sensor_state_json_generator(WebServer *web_server, void *source) { return web_server->sensor_json_((sensor::Sensor *) (source), ((sensor::Sensor *) (source))->state, DETAIL_STATE); } -std::string WebServer::sensor_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::sensor_all_json_generator(WebServer *web_server, void *source) { return web_server->sensor_json_((sensor::Sensor *) (source), ((sensor::Sensor *) (source))->state, DETAIL_ALL); } -std::string WebServer::sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -653,23 +653,23 @@ void WebServer::handle_text_sensor_request(AsyncWebServerRequest *request, const // Note: request->method() is always HTTP_GET here (canHandle ensures this) if (entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->text_sensor_json_(obj, obj->state, detail); + auto data = this->text_sensor_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } } request->send(404); } -std::string WebServer::text_sensor_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::text_sensor_state_json_generator(WebServer *web_server, void *source) { return web_server->text_sensor_json_((text_sensor::TextSensor *) (source), ((text_sensor::TextSensor *) (source))->state, DETAIL_STATE); } -std::string WebServer::text_sensor_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::text_sensor_all_json_generator(WebServer *web_server, void *source) { return web_server->text_sensor_json_((text_sensor::TextSensor *) (source), ((text_sensor::TextSensor *) (source))->state, DETAIL_ALL); } -std::string WebServer::text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value, - JsonDetail start_config) { +json::SerializationBuffer<> WebServer::text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value, + JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -714,7 +714,7 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->switch_json_(obj, obj->state, detail); + auto data = this->switch_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } @@ -739,13 +739,13 @@ void WebServer::handle_switch_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } -std::string WebServer::switch_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::switch_state_json_generator(WebServer *web_server, void *source) { return web_server->switch_json_((switch_::Switch *) (source), ((switch_::Switch *) (source))->state, DETAIL_STATE); } -std::string WebServer::switch_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::switch_all_json_generator(WebServer *web_server, void *source) { return web_server->switch_json_((switch_::Switch *) (source), ((switch_::Switch *) (source))->state, DETAIL_ALL); } -std::string WebServer::switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -767,7 +767,7 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM continue; if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->button_json_(obj, detail); + auto data = this->button_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("press"))) { DEFER_ACTION(obj, obj->press()); @@ -780,10 +780,10 @@ void WebServer::handle_button_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } -std::string WebServer::button_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::button_all_json_generator(WebServer *web_server, void *source) { return web_server->button_json_((button::Button *) (source), DETAIL_ALL); } -std::string WebServer::button_json_(button::Button *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::button_json_(button::Button *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -810,22 +810,23 @@ void WebServer::handle_binary_sensor_request(AsyncWebServerRequest *request, con // Note: request->method() is always HTTP_GET here (canHandle ensures this) if (entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->binary_sensor_json_(obj, obj->state, detail); + auto data = this->binary_sensor_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } } request->send(404); } -std::string WebServer::binary_sensor_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::binary_sensor_state_json_generator(WebServer *web_server, void *source) { return web_server->binary_sensor_json_((binary_sensor::BinarySensor *) (source), ((binary_sensor::BinarySensor *) (source))->state, DETAIL_STATE); } -std::string WebServer::binary_sensor_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::binary_sensor_all_json_generator(WebServer *web_server, void *source) { return web_server->binary_sensor_json_((binary_sensor::BinarySensor *) (source), ((binary_sensor::BinarySensor *) (source))->state, DETAIL_ALL); } -std::string WebServer::binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, + JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -852,7 +853,7 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->fan_json_(obj, detail); + auto data = this->fan_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("toggle"))) { DEFER_ACTION(obj, obj->toggle().perform()); @@ -893,13 +894,13 @@ void WebServer::handle_fan_request(AsyncWebServerRequest *request, const UrlMatc } request->send(404); } -std::string WebServer::fan_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::fan_state_json_generator(WebServer *web_server, void *source) { return web_server->fan_json_((fan::Fan *) (source), DETAIL_STATE); } -std::string WebServer::fan_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::fan_all_json_generator(WebServer *web_server, void *source) { return web_server->fan_json_((fan::Fan *) (source), DETAIL_ALL); } -std::string WebServer::fan_json_(fan::Fan *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::fan_json_(fan::Fan *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -933,7 +934,7 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->light_json_(obj, detail); + auto data = this->light_json_(obj, detail); request->send(200, "application/json", data.c_str()); } else if (match.method_equals(ESPHOME_F("toggle"))) { DEFER_ACTION(obj, obj->toggle().perform()); @@ -972,13 +973,13 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa } request->send(404); } -std::string WebServer::light_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::light_state_json_generator(WebServer *web_server, void *source) { return web_server->light_json_((light::LightState *) (source), DETAIL_STATE); } -std::string WebServer::light_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::light_all_json_generator(WebServer *web_server, void *source) { return web_server->light_json_((light::LightState *) (source), DETAIL_ALL); } -std::string WebServer::light_json_(light::LightState *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::light_json_(light::LightState *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1012,7 +1013,7 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->cover_json_(obj, detail); + auto data = this->cover_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1060,13 +1061,13 @@ void WebServer::handle_cover_request(AsyncWebServerRequest *request, const UrlMa } request->send(404); } -std::string WebServer::cover_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::cover_state_json_generator(WebServer *web_server, void *source) { return web_server->cover_json_((cover::Cover *) (source), DETAIL_STATE); } -std::string WebServer::cover_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::cover_all_json_generator(WebServer *web_server, void *source) { return web_server->cover_json_((cover::Cover *) (source), DETAIL_ALL); } -std::string WebServer::cover_json_(cover::Cover *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::cover_json_(cover::Cover *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1101,7 +1102,7 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->number_json_(obj, obj->state, detail); + auto data = this->number_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1120,13 +1121,13 @@ void WebServer::handle_number_request(AsyncWebServerRequest *request, const UrlM request->send(404); } -std::string WebServer::number_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::number_state_json_generator(WebServer *web_server, void *source) { return web_server->number_json_((number::Number *) (source), ((number::Number *) (source))->state, DETAIL_STATE); } -std::string WebServer::number_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::number_all_json_generator(WebServer *web_server, void *source) { return web_server->number_json_((number::Number *) (source), ((number::Number *) (source))->state, DETAIL_ALL); } -std::string WebServer::number_json_(number::Number *obj, float value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::number_json_(number::Number *obj, float value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1168,7 +1169,7 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat continue; if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->date_json_(obj, detail); + auto data = this->date_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1194,13 +1195,13 @@ void WebServer::handle_date_request(AsyncWebServerRequest *request, const UrlMat request->send(404); } -std::string WebServer::date_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::date_state_json_generator(WebServer *web_server, void *source) { return web_server->date_json_((datetime::DateEntity *) (source), DETAIL_STATE); } -std::string WebServer::date_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::date_all_json_generator(WebServer *web_server, void *source) { return web_server->date_json_((datetime::DateEntity *) (source), DETAIL_ALL); } -std::string WebServer::date_json_(datetime::DateEntity *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::date_json_(datetime::DateEntity *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1229,7 +1230,7 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat continue; if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->time_json_(obj, detail); + auto data = this->time_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1254,13 +1255,13 @@ void WebServer::handle_time_request(AsyncWebServerRequest *request, const UrlMat } request->send(404); } -std::string WebServer::time_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::time_state_json_generator(WebServer *web_server, void *source) { return web_server->time_json_((datetime::TimeEntity *) (source), DETAIL_STATE); } -std::string WebServer::time_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::time_all_json_generator(WebServer *web_server, void *source) { return web_server->time_json_((datetime::TimeEntity *) (source), DETAIL_ALL); } -std::string WebServer::time_json_(datetime::TimeEntity *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::time_json_(datetime::TimeEntity *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1289,7 +1290,7 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur continue; if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->datetime_json_(obj, detail); + auto data = this->datetime_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1314,13 +1315,13 @@ void WebServer::handle_datetime_request(AsyncWebServerRequest *request, const Ur } request->send(404); } -std::string WebServer::datetime_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::datetime_state_json_generator(WebServer *web_server, void *source) { return web_server->datetime_json_((datetime::DateTimeEntity *) (source), DETAIL_STATE); } -std::string WebServer::datetime_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::datetime_all_json_generator(WebServer *web_server, void *source) { return web_server->datetime_json_((datetime::DateTimeEntity *) (source), DETAIL_ALL); } -std::string WebServer::datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1351,7 +1352,7 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->text_json_(obj, obj->state, detail); + auto data = this->text_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1370,13 +1371,13 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat request->send(404); } -std::string WebServer::text_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::text_state_json_generator(WebServer *web_server, void *source) { return web_server->text_json_((text::Text *) (source), ((text::Text *) (source))->state, DETAIL_STATE); } -std::string WebServer::text_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::text_all_json_generator(WebServer *web_server, void *source) { return web_server->text_json_((text::Text *) (source), ((text::Text *) (source))->state, DETAIL_ALL); } -std::string WebServer::text_json_(text::Text *obj, const std::string &value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::text_json_(text::Text *obj, const std::string &value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1408,7 +1409,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), detail); + auto data = this->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -1427,15 +1428,15 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } -std::string WebServer::select_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::select_state_json_generator(WebServer *web_server, void *source) { auto *obj = (select::Select *) (source); return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_STATE); } -std::string WebServer::select_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::select_all_json_generator(WebServer *web_server, void *source) { auto *obj = (select::Select *) (source); return web_server->select_json_(obj, obj->has_state() ? obj->current_option() : StringRef(), DETAIL_ALL); } -std::string WebServer::select_json_(select::Select *obj, StringRef value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::select_json_(select::Select *obj, StringRef value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1467,7 +1468,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->climate_json_(obj, detail); + auto data = this->climate_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1500,15 +1501,15 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url } request->send(404); } -std::string WebServer::climate_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::climate_state_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->climate_json_((climate::Climate *) (source), DETAIL_STATE); } -std::string WebServer::climate_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::climate_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->climate_json_((climate::Climate *) (source), DETAIL_ALL); } -std::string WebServer::climate_json_(climate::Climate *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::climate_json_(climate::Climate *obj, JsonDetail start_config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1641,7 +1642,7 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->lock_json_(obj, obj->state, detail); + auto data = this->lock_json_(obj, obj->state, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1666,13 +1667,13 @@ void WebServer::handle_lock_request(AsyncWebServerRequest *request, const UrlMat } request->send(404); } -std::string WebServer::lock_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::lock_state_json_generator(WebServer *web_server, void *source) { return web_server->lock_json_((lock::Lock *) (source), ((lock::Lock *) (source))->state, DETAIL_STATE); } -std::string WebServer::lock_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::lock_all_json_generator(WebServer *web_server, void *source) { return web_server->lock_json_((lock::Lock *) (source), ((lock::Lock *) (source))->state, DETAIL_ALL); } -std::string WebServer::lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1700,7 +1701,7 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->valve_json_(obj, detail); + auto data = this->valve_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1746,13 +1747,13 @@ void WebServer::handle_valve_request(AsyncWebServerRequest *request, const UrlMa } request->send(404); } -std::string WebServer::valve_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::valve_state_json_generator(WebServer *web_server, void *source) { return web_server->valve_json_((valve::Valve *) (source), DETAIL_STATE); } -std::string WebServer::valve_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::valve_all_json_generator(WebServer *web_server, void *source) { return web_server->valve_json_((valve::Valve *) (source), DETAIL_ALL); } -std::string WebServer::valve_json_(valve::Valve *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::valve_json_(valve::Valve *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1785,7 +1786,7 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->alarm_control_panel_json_(obj, obj->get_state(), detail); + auto data = this->alarm_control_panel_json_(obj, obj->get_state(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -1825,19 +1826,19 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques } request->send(404); } -std::string WebServer::alarm_control_panel_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::alarm_control_panel_state_json_generator(WebServer *web_server, void *source) { return web_server->alarm_control_panel_json_((alarm_control_panel::AlarmControlPanel *) (source), ((alarm_control_panel::AlarmControlPanel *) (source))->get_state(), DETAIL_STATE); } -std::string WebServer::alarm_control_panel_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::alarm_control_panel_all_json_generator(WebServer *web_server, void *source) { return web_server->alarm_control_panel_json_((alarm_control_panel::AlarmControlPanel *) (source), ((alarm_control_panel::AlarmControlPanel *) (source))->get_state(), DETAIL_ALL); } -std::string WebServer::alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj, - alarm_control_panel::AlarmControlPanelState value, - JsonDetail start_config) { +json::SerializationBuffer<> WebServer::alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj, + alarm_control_panel::AlarmControlPanelState value, + JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -1866,7 +1867,7 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->water_heater_json_(obj, detail); + auto data = this->water_heater_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -1902,14 +1903,14 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons request->send(404); } -std::string WebServer::water_heater_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::water_heater_state_json_generator(WebServer *web_server, void *source) { return web_server->water_heater_json_(static_cast<water_heater::WaterHeater *>(source), DETAIL_STATE); } -std::string WebServer::water_heater_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::water_heater_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->water_heater_json_(static_cast<water_heater::WaterHeater *>(source), DETAIL_ALL); } -std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); char buf[PSTR_LOCAL_SIZE]; @@ -1971,7 +1972,7 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->infrared_json_(obj, detail); + auto data = this->infrared_json_(obj, detail); request->send(200, ESPHOME_F("application/json"), data.c_str()); return; } @@ -2031,12 +2032,12 @@ void WebServer::handle_infrared_request(AsyncWebServerRequest *request, const Ur request->send(404); } -std::string WebServer::infrared_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::infrared_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->infrared_json_(static_cast<infrared::Infrared *>(source), DETAIL_ALL); } -std::string WebServer::infrared_json_(infrared::Infrared *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::infrared_json_(infrared::Infrared *obj, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -2071,7 +2072,7 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa // Note: request->method() is always HTTP_GET here (canHandle ensures this) if (entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->event_json_(obj, StringRef(), detail); + auto data = this->event_json_(obj, StringRef(), detail); request->send(200, "application/json", data.c_str()); return; } @@ -2081,16 +2082,16 @@ void WebServer::handle_event_request(AsyncWebServerRequest *request, const UrlMa static StringRef get_event_type(event::Event *event) { return event ? event->get_last_event_type() : StringRef(); } -std::string WebServer::event_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::event_state_json_generator(WebServer *web_server, void *source) { auto *event = static_cast<event::Event *>(source); return web_server->event_json_(event, get_event_type(event), DETAIL_STATE); } // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson -std::string WebServer::event_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::event_all_json_generator(WebServer *web_server, void *source) { auto *event = static_cast<event::Event *>(source); return web_server->event_json_(event, get_event_type(event), DETAIL_ALL); } -std::string WebServer::event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config) { json::JsonBuilder builder; JsonObject root = builder.root(); @@ -2124,7 +2125,7 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM if (request->method() == HTTP_GET && entity_match.action_is_empty) { auto detail = get_request_detail(request); - std::string data = this->update_json_(obj, detail); + auto data = this->update_json_(obj, detail); request->send(200, "application/json", data.c_str()); return; } @@ -2140,15 +2141,15 @@ void WebServer::handle_update_request(AsyncWebServerRequest *request, const UrlM } request->send(404); } -std::string WebServer::update_state_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::update_state_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE); } -std::string WebServer::update_all_json_generator(WebServer *web_server, void *source) { +json::SerializationBuffer<> WebServer::update_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE); } -std::string WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) { +json::SerializationBuffer<> WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson json::JsonBuilder builder; JsonObject root = builder.root(); diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 6afe618b59..76c1c8b0bd 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -2,6 +2,7 @@ #include "list_entities.h" +#include "esphome/components/json/json_util.h" #include "esphome/components/web_server_base/web_server_base.h" #ifdef USE_WEBSERVER #include "esphome/core/component.h" @@ -103,7 +104,7 @@ enum JsonDetail { DETAIL_ALL, DETAIL_STATE }; can be forgotten. */ #if !defined(USE_ESP32) && defined(USE_ARDUINO) -using message_generator_t = std::string(WebServer *, void *); +using message_generator_t = json::SerializationBuffer<>(WebServer *, void *); class DeferredUpdateEventSourceList; class DeferredUpdateEventSource : public AsyncEventSource { @@ -257,7 +258,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { void handle_index_request(AsyncWebServerRequest *request); /// Return the webserver configuration as JSON. - std::string get_config_json(); + json::SerializationBuffer<> get_config_json(); #ifdef USE_WEBSERVER_CSS_INCLUDE /// Handle included css request under '/0.css'. @@ -279,8 +280,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a sensor request under '/sensor/<id>'. void handle_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string sensor_state_json_generator(WebServer *web_server, void *source); - static std::string sensor_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> sensor_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> sensor_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_SWITCH @@ -289,8 +290,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a switch request under '/switch/<id>/</turn_on/turn_off/toggle>'. void handle_switch_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string switch_state_json_generator(WebServer *web_server, void *source); - static std::string switch_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> switch_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> switch_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_BUTTON @@ -298,7 +299,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { void handle_button_request(AsyncWebServerRequest *request, const UrlMatch &match); // Buttons are stateless, so there is no button_state_json_generator - static std::string button_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> button_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_BINARY_SENSOR @@ -307,8 +308,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a binary sensor request under '/binary_sensor/<id>'. void handle_binary_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string binary_sensor_state_json_generator(WebServer *web_server, void *source); - static std::string binary_sensor_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> binary_sensor_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> binary_sensor_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_FAN @@ -317,8 +318,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a fan request under '/fan/<id>/</turn_on/turn_off/toggle>'. void handle_fan_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string fan_state_json_generator(WebServer *web_server, void *source); - static std::string fan_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> fan_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> fan_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_LIGHT @@ -327,8 +328,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a light request under '/light/<id>/</turn_on/turn_off/toggle>'. void handle_light_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string light_state_json_generator(WebServer *web_server, void *source); - static std::string light_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> light_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> light_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_TEXT_SENSOR @@ -337,8 +338,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a text sensor request under '/text_sensor/<id>'. void handle_text_sensor_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string text_sensor_state_json_generator(WebServer *web_server, void *source); - static std::string text_sensor_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> text_sensor_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> text_sensor_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_COVER @@ -347,8 +348,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a cover request under '/cover/<id>/<open/close/stop/set>'. void handle_cover_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string cover_state_json_generator(WebServer *web_server, void *source); - static std::string cover_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> cover_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> cover_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_NUMBER @@ -356,8 +357,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a number request under '/number/<id>'. void handle_number_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string number_state_json_generator(WebServer *web_server, void *source); - static std::string number_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> number_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> number_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_DATETIME_DATE @@ -365,8 +366,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a date request under '/date/<id>'. void handle_date_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string date_state_json_generator(WebServer *web_server, void *source); - static std::string date_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> date_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> date_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_DATETIME_TIME @@ -374,8 +375,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a time request under '/time/<id>'. void handle_time_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string time_state_json_generator(WebServer *web_server, void *source); - static std::string time_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> time_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> time_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_DATETIME_DATETIME @@ -383,8 +384,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a datetime request under '/datetime/<id>'. void handle_datetime_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string datetime_state_json_generator(WebServer *web_server, void *source); - static std::string datetime_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> datetime_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> datetime_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_TEXT @@ -392,8 +393,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a text input request under '/text/<id>'. void handle_text_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string text_state_json_generator(WebServer *web_server, void *source); - static std::string text_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> text_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> text_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_SELECT @@ -401,8 +402,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a select request under '/select/<id>'. void handle_select_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string select_state_json_generator(WebServer *web_server, void *source); - static std::string select_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> select_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> select_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_CLIMATE @@ -410,8 +411,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a climate request under '/climate/<id>'. void handle_climate_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string climate_state_json_generator(WebServer *web_server, void *source); - static std::string climate_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> climate_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> climate_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_LOCK @@ -420,8 +421,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a lock request under '/lock/<id>/</lock/unlock/open>'. void handle_lock_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string lock_state_json_generator(WebServer *web_server, void *source); - static std::string lock_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> lock_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> lock_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_VALVE @@ -430,8 +431,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a valve request under '/valve/<id>/<open/close/stop/set>'. void handle_valve_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string valve_state_json_generator(WebServer *web_server, void *source); - static std::string valve_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> valve_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> valve_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_ALARM_CONTROL_PANEL @@ -440,8 +441,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a alarm_control_panel request under '/alarm_control_panel/<id>'. void handle_alarm_control_panel_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string alarm_control_panel_state_json_generator(WebServer *web_server, void *source); - static std::string alarm_control_panel_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> alarm_control_panel_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> alarm_control_panel_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_WATER_HEATER @@ -450,22 +451,22 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a water_heater request under '/water_heater/<id>/<mode/set>'. void handle_water_heater_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string water_heater_state_json_generator(WebServer *web_server, void *source); - static std::string water_heater_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> water_heater_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> water_heater_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_INFRARED /// Handle an infrared request under '/infrared/<id>/transmit'. void handle_infrared_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string infrared_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> infrared_all_json_generator(WebServer *web_server, void *source); #endif #ifdef USE_EVENT void on_event(event::Event *obj) override; - static std::string event_state_json_generator(WebServer *web_server, void *source); - static std::string event_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> event_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> event_all_json_generator(WebServer *web_server, void *source); /// Handle a event request under '/event<id>'. void handle_event_request(AsyncWebServerRequest *request, const UrlMatch &match); @@ -477,8 +478,8 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { /// Handle a update request under '/update/<id>'. void handle_update_request(AsyncWebServerRequest *request, const UrlMatch &match); - static std::string update_state_json_generator(WebServer *web_server, void *source); - static std::string update_all_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> update_state_json_generator(WebServer *web_server, void *source); + static json::SerializationBuffer<> update_all_json_generator(WebServer *web_server, void *source); #endif /// Override the web handler's canHandle method. @@ -586,71 +587,74 @@ class WebServer : public Controller, public Component, public AsyncWebHandler { private: #ifdef USE_SENSOR - std::string sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config); + json::SerializationBuffer<> sensor_json_(sensor::Sensor *obj, float value, JsonDetail start_config); #endif #ifdef USE_SWITCH - std::string switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config); + json::SerializationBuffer<> switch_json_(switch_::Switch *obj, bool value, JsonDetail start_config); #endif #ifdef USE_BUTTON - std::string button_json_(button::Button *obj, JsonDetail start_config); + json::SerializationBuffer<> button_json_(button::Button *obj, JsonDetail start_config); #endif #ifdef USE_BINARY_SENSOR - std::string binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, JsonDetail start_config); + json::SerializationBuffer<> binary_sensor_json_(binary_sensor::BinarySensor *obj, bool value, + JsonDetail start_config); #endif #ifdef USE_FAN - std::string fan_json_(fan::Fan *obj, JsonDetail start_config); + json::SerializationBuffer<> fan_json_(fan::Fan *obj, JsonDetail start_config); #endif #ifdef USE_LIGHT - std::string light_json_(light::LightState *obj, JsonDetail start_config); + json::SerializationBuffer<> light_json_(light::LightState *obj, JsonDetail start_config); #endif #ifdef USE_TEXT_SENSOR - std::string text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value, JsonDetail start_config); + json::SerializationBuffer<> text_sensor_json_(text_sensor::TextSensor *obj, const std::string &value, + JsonDetail start_config); #endif #ifdef USE_COVER - std::string cover_json_(cover::Cover *obj, JsonDetail start_config); + json::SerializationBuffer<> cover_json_(cover::Cover *obj, JsonDetail start_config); #endif #ifdef USE_NUMBER - std::string number_json_(number::Number *obj, float value, JsonDetail start_config); + json::SerializationBuffer<> number_json_(number::Number *obj, float value, JsonDetail start_config); #endif #ifdef USE_DATETIME_DATE - std::string date_json_(datetime::DateEntity *obj, JsonDetail start_config); + json::SerializationBuffer<> date_json_(datetime::DateEntity *obj, JsonDetail start_config); #endif #ifdef USE_DATETIME_TIME - std::string time_json_(datetime::TimeEntity *obj, JsonDetail start_config); + json::SerializationBuffer<> time_json_(datetime::TimeEntity *obj, JsonDetail start_config); #endif #ifdef USE_DATETIME_DATETIME - std::string datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config); + json::SerializationBuffer<> datetime_json_(datetime::DateTimeEntity *obj, JsonDetail start_config); #endif #ifdef USE_TEXT - std::string text_json_(text::Text *obj, const std::string &value, JsonDetail start_config); + json::SerializationBuffer<> text_json_(text::Text *obj, const std::string &value, JsonDetail start_config); #endif #ifdef USE_SELECT - std::string select_json_(select::Select *obj, StringRef value, JsonDetail start_config); + json::SerializationBuffer<> select_json_(select::Select *obj, StringRef value, JsonDetail start_config); #endif #ifdef USE_CLIMATE - std::string climate_json_(climate::Climate *obj, JsonDetail start_config); + json::SerializationBuffer<> climate_json_(climate::Climate *obj, JsonDetail start_config); #endif #ifdef USE_LOCK - std::string lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config); + json::SerializationBuffer<> lock_json_(lock::Lock *obj, lock::LockState value, JsonDetail start_config); #endif #ifdef USE_VALVE - std::string valve_json_(valve::Valve *obj, JsonDetail start_config); + json::SerializationBuffer<> valve_json_(valve::Valve *obj, JsonDetail start_config); #endif #ifdef USE_ALARM_CONTROL_PANEL - std::string alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj, - alarm_control_panel::AlarmControlPanelState value, JsonDetail start_config); + json::SerializationBuffer<> alarm_control_panel_json_(alarm_control_panel::AlarmControlPanel *obj, + alarm_control_panel::AlarmControlPanelState value, + JsonDetail start_config); #endif #ifdef USE_EVENT - std::string event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config); + json::SerializationBuffer<> event_json_(event::Event *obj, StringRef event_type, JsonDetail start_config); #endif #ifdef USE_WATER_HEATER - std::string water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config); + json::SerializationBuffer<> water_heater_json_(water_heater::WaterHeater *obj, JsonDetail start_config); #endif #ifdef USE_INFRARED - std::string infrared_json_(infrared::Infrared *obj, JsonDetail start_config); + json::SerializationBuffer<> infrared_json_(infrared::Infrared *obj, JsonDetail start_config); #endif #ifdef USE_UPDATE - std::string update_json_(update::UpdateEntity *obj, JsonDetail start_config); + json::SerializationBuffer<> update_json_(update::UpdateEntity *obj, JsonDetail start_config); #endif }; diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 1798159e7f..4034a22586 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -563,7 +563,7 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(const AsyncWebServerRequest * // Configure reconnect timeout and send config // this should always go through since the tcp send buffer is empty on connect - std::string message = ws->get_config_json(); + auto message = ws->get_config_json(); this->try_send_nodefer(message.c_str(), "ping", millis(), 30000); #ifdef USE_WEBSERVER_SORTING @@ -617,7 +617,7 @@ void AsyncEventSourceResponse::deq_push_back_with_dedup_(void *source, message_g void AsyncEventSourceResponse::process_deferred_queue_() { while (!deferred_queue_.empty()) { DeferredEvent &de = deferred_queue_.front(); - std::string message = de.message_generator_(web_server_, de.source_); + auto message = de.message_generator_(web_server_, de.source_); if (this->try_send_nodefer(message.c_str(), "state")) { // O(n) but memory efficiency is more important than speed here which is why std::vector was chosen deferred_queue_.erase(deferred_queue_.begin()); @@ -854,7 +854,7 @@ void AsyncEventSourceResponse::deferrable_send_state(void *source, const char *e // trying to send first deq_push_back_with_dedup_(source, message_generator); } else { - std::string message = message_generator(web_server_, source); + auto message = message_generator(web_server_, source); if (!this->try_send_nodefer(message.c_str(), "state")) { deq_push_back_with_dedup_(source, message_generator); } diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 74601ffda8..76ddfa35fd 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -16,6 +16,7 @@ #include <vector> #ifdef USE_WEBSERVER +#include "esphome/components/json/json_util.h" #include "esphome/components/web_server/list_entities.h" #endif @@ -250,7 +251,7 @@ class AsyncWebHandler { class AsyncEventSource; class AsyncEventSourceResponse; -using message_generator_t = std::string(esphome::web_server::WebServer *, void *); +using message_generator_t = json::SerializationBuffer<>(esphome::web_server::WebServer *, void *); /* This class holds a pointer to the source component that wants to publish a state event, and a pointer to a function diff --git a/tests/components/json/common.yaml b/tests/components/json/common.yaml index c36c7f2a5a..c4bf6c3831 100644 --- a/tests/components/json/common.yaml +++ b/tests/components/json/common.yaml @@ -4,15 +4,16 @@ interval: - interval: 60s then: - lambda: |- - // Test build_json - std::string json_str = esphome::json::build_json([](JsonObject root) { + // Test build_json - returns SerializationBuffer, use auto to avoid heap allocation + auto json_buf = esphome::json::build_json([](JsonObject root) { root["sensor"] = "temperature"; root["value"] = 23.5; root["unit"] = "°C"; }); - ESP_LOGD("test", "Built JSON: %s", json_str.c_str()); + ESP_LOGD("test", "Built JSON: %s", json_buf.c_str()); - // Test parse_json + // Test parse_json - implicit conversion to std::string for backward compatibility + std::string json_str = json_buf; bool parse_ok = esphome::json::parse_json(json_str, [](JsonObject root) { if (root["sensor"].is<const char*>() && root["value"].is<float>()) { const char* sensor = root["sensor"]; @@ -26,10 +27,10 @@ interval: }); ESP_LOGD("test", "Parse result (JSON syntax only): %s", parse_ok ? "success" : "failed"); - // Test JsonBuilder class + // Test JsonBuilder class - returns SerializationBuffer esphome::json::JsonBuilder builder; JsonObject obj = builder.root(); obj["test"] = "direct_builder"; obj["count"] = 42; - std::string result = builder.serialize(); + auto result = builder.serialize(); ESP_LOGD("test", "JsonBuilder result: %s", result.c_str()); From 17a810b939ba7ab0019fa65149e2db2622d2466c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:14:48 -0500 Subject: [PATCH 0797/2030] [wifi] Sync output_power with PHY max TX power to prevent brownout (#14118) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/wifi/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index e865de8663..afceec6c54 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -1,4 +1,5 @@ import logging +import math from esphome import automation from esphome.automation import Condition @@ -493,6 +494,13 @@ async def to_code(config): cg.add(var.set_passive_scan(True)) if CONF_OUTPUT_POWER in config: cg.add(var.set_output_power(config[CONF_OUTPUT_POWER])) + if CORE.is_esp32: + # Set PHY max TX power to match output_power so calibration also uses + # reduced power. This prevents brownout during PHY init on marginal + # power supplies, which is critical for OTA updates with rollback enabled. + # Kconfig range is 10-20, ESPHome allows 8.5-20.5 + phy_tx_power = max(10, min(20, math.ceil(config[CONF_OUTPUT_POWER]))) + add_idf_sdkconfig_option("CONFIG_ESP_PHY_MAX_WIFI_TX_POWER", phy_tx_power) # enable_on_boot defaults to true in C++ - only set if false if not config[CONF_ENABLE_ON_BOOT]: cg.add(var.set_enable_on_boot(False)) From cceb109303f16a8723b11e3e9bf9a26f985be197 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 17:48:18 -0600 Subject: [PATCH 0798/2030] [uart] Always call pin setup for UART0 default pins on ESP-IDF (#14130) --- .../uart/uart_component_esp_idf.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 6c242220a6..ea7a09fee6 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -19,6 +19,13 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; +/// Check if a pin number matches one of the default UART0 GPIO pins. +/// These pins may have residual state from the boot console that requires +/// explicit reset before UART reconfiguration (ESP-IDF issue #17459). +static constexpr bool is_default_uart0_pin(int8_t pin_num) { + return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; +} + uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -150,20 +157,26 @@ void IDFUARTComponent::load_settings(bool dump_config) { // Commit 9ed617fb17 removed gpio_func_sel() calls from uart_set_pin(), which breaks // UART on default UART0 pins that may have residual state from boot console. // Reset these pins before configuring UART to ensure they're in a clean state. - if (tx == U0TXD_GPIO_NUM || tx == U0RXD_GPIO_NUM) { + if (is_default_uart0_pin(tx)) { gpio_reset_pin(static_cast<gpio_num_t>(tx)); } - if (rx == U0TXD_GPIO_NUM || rx == U0RXD_GPIO_NUM) { + if (is_default_uart0_pin(rx)) { gpio_reset_pin(static_cast<gpio_num_t>(rx)); } - // Setup pins after reset to preserve open drain/pullup/pulldown flags + // Setup pins after reset to configure GPIO direction and pull resistors. + // For UART0 default pins, setup() must always be called because gpio_reset_pin() + // above sets GPIO_MODE_DISABLE which disables the input buffer. Without setup(), + // uart_set_pin() on ESP-IDF 5.4.2+ does not re-enable the input buffer for + // IOMUX-connected pins, so the RX pin cannot receive data (see issue #10132). + // For other pins, only call setup() if pull or open-drain flags are set to avoid + // disturbing the default pin state which breaks some external components (#11823). auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; } const auto mask = gpio::Flags::FLAG_OPEN_DRAIN | gpio::Flags::FLAG_PULLUP | gpio::Flags::FLAG_PULLDOWN; - if ((pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { + if (is_default_uart0_pin(pin->get_pin()) || (pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { pin->setup(); } }; From 1b4de55efda47b59e1572f432ef40b932311da38 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 19:12:37 -0500 Subject: [PATCH 0799/2030] [pulse_counter] Fix PCNT glitch filter calculation off by 1000x (#14132) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/pulse_counter/pulse_counter_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index ef4cc980f6..5e62c0a410 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -117,7 +117,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } if (this->filter_us != 0) { - uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000u / ((uint32_t) esp_clk_apb_freq() / 1000000u); pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), }; From d29288547ec2d5b9e68b61c2186522efaad041b7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 18:54:33 -0600 Subject: [PATCH 0800/2030] [core] Use constexpr for PROGMEM arrays (#14127) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/cpp_generator.py | 2 +- tests/unit_tests/test_cpp_generator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 83f2d6cf81..fe666bdd6e 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -424,7 +424,7 @@ class ProgmemAssignmentExpression(AssignmentExpression): super().__init__(type_, "", name, rhs) def __str__(self): - return f"static const {self.type} {self.name}[] PROGMEM = {self.rhs}" + return f"static constexpr {self.type} {self.name}[] PROGMEM = {self.rhs}" class StaticConstAssignmentExpression(AssignmentExpression): diff --git a/tests/unit_tests/test_cpp_generator.py b/tests/unit_tests/test_cpp_generator.py index 8755e6e2a1..049d21027f 100644 --- a/tests/unit_tests/test_cpp_generator.py +++ b/tests/unit_tests/test_cpp_generator.py @@ -325,7 +325,7 @@ class TestStatements: ), ( cg.ProgmemAssignmentExpression(ct.uint16, "foo", "bar"), - 'static const uint16_t foo[] PROGMEM = "bar"', + 'static constexpr uint16_t foo[] PROGMEM = "bar"', ), ), ) From 94712b3961dd962d0a43636301c5edccd08121b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 18:54:44 -0600 Subject: [PATCH 0801/2030] [esp8266][web_server] Use constexpr for PROGMEM arrays in codegen (#14128) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp8266/gpio.py | 4 ++-- esphome/components/web_server/__init__.py | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index 2e8d6496bc..43508afaf9 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -202,11 +202,11 @@ async def add_pin_initial_states_array(): cg.add_global( cg.RawExpression( - f"const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_MODE[16] PROGMEM = {{{initial_modes_s}}}" + f"constexpr uint8_t ESPHOME_ESP8266_GPIO_INITIAL_MODE[16] PROGMEM = {{{initial_modes_s}}}" ) ) cg.add_global( cg.RawExpression( - f"const uint8_t ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[16] PROGMEM = {{{initial_levels_s}}}" + f"constexpr uint8_t ESPHOME_ESP8266_GPIO_INITIAL_LEVEL[16] PROGMEM = {{{initial_levels_s}}}" ) ) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 294a5e0a15..9305a2de61 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -280,10 +280,8 @@ def add_resource_as_progmem( content_encoded = gzip.compress(content_encoded) content_encoded_size = len(content_encoded) bytes_as_int = ", ".join(str(x) for x in content_encoded) - uint8_t = f"const uint8_t ESPHOME_WEBSERVER_{resource_name}[{content_encoded_size}] PROGMEM = {{{bytes_as_int}}}" - size_t = ( - f"const size_t ESPHOME_WEBSERVER_{resource_name}_SIZE = {content_encoded_size}" - ) + uint8_t = f"constexpr uint8_t ESPHOME_WEBSERVER_{resource_name}[{content_encoded_size}] PROGMEM = {{{bytes_as_int}}}" + size_t = f"constexpr size_t ESPHOME_WEBSERVER_{resource_name}_SIZE = {content_encoded_size}" cg.add_global(cg.RawExpression(uint8_t)) cg.add_global(cg.RawExpression(size_t)) From c1265a9490711813a6036b8a772dd36e3e871089 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 18:54:57 -0600 Subject: [PATCH 0802/2030] [core] Use constexpr for hand-written PROGMEM arrays in C++ (#14129) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/api/api_frame_helper_noise.cpp | 2 +- esphome/components/bme680/bme680.cpp | 8 +++--- .../components/captive_portal/captive_index.h | 4 +-- esphome/components/display/display.cpp | 6 ++-- esphome/components/ili9xxx/ili9xxx_init.h | 28 +++++++++---------- esphome/components/max7219/max7219.cpp | 2 +- esphome/components/max7219digit/max7219font.h | 2 +- .../components/ssd1306_base/ssd1306_base.cpp | 2 +- esphome/components/st7735/st7735.cpp | 2 +- esphome/components/tm1621/tm1621.cpp | 2 +- esphome/components/tm1637/tm1637.cpp | 2 +- esphome/components/tm1638/sevenseg.h | 2 +- .../components/web_server/server_index_v2.h | 4 +-- .../components/web_server/server_index_v3.h | 4 +-- 14 files changed, 35 insertions(+), 35 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 492988128a..2aad732f7f 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -19,7 +19,7 @@ namespace esphome::api { static const char *const TAG = "api.noise"; #ifdef USE_ESP8266 -static const char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit"; +static constexpr char PROLOGUE_INIT[] PROGMEM = "NoiseAPIInit"; #else static const char *const PROLOGUE_INIT = "NoiseAPIInit"; #endif diff --git a/esphome/components/bme680/bme680.cpp b/esphome/components/bme680/bme680.cpp index 5e52c84b3d..e3cd80de00 100644 --- a/esphome/components/bme680/bme680.cpp +++ b/esphome/components/bme680/bme680.cpp @@ -22,11 +22,11 @@ static const uint8_t BME680_REGISTER_CHIPID = 0xD0; static const uint8_t BME680_REGISTER_FIELD0 = 0x1D; -const float BME680_GAS_LOOKUP_TABLE_1[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, - 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0}; +constexpr float BME680_GAS_LOOKUP_TABLE_1[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -0.8, + 0.0, 0.0, -0.2, -0.5, 0.0, -1.0, 0.0, 0.0}; -const float BME680_GAS_LOOKUP_TABLE_2[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, - -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; +constexpr float BME680_GAS_LOOKUP_TABLE_2[16] PROGMEM = {0.0, 0.0, 0.0, 0.0, 0.1, 0.7, 0.0, -0.8, + -0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; [[maybe_unused]] static const char *oversampling_to_str(BME680Oversampling oversampling) { switch (oversampling) { diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index 645ebb7a2f..a81edc1900 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -6,7 +6,7 @@ namespace esphome::captive_portal { #ifdef USE_CAPTIVE_PORTAL_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x95, 0x16, 0x6b, 0x8f, 0xdb, 0x36, 0xf2, 0x7b, 0x7e, 0x05, 0x8f, 0x49, 0xbb, 0x52, 0xb3, 0x7a, 0x7a, 0xed, 0x6c, 0x24, 0x51, 0x45, 0x9a, 0xbb, 0xa2, 0x05, 0x9a, 0x36, 0xc0, 0x6e, 0x73, 0x1f, 0x82, 0x00, 0x4b, 0x53, 0x23, 0x8b, 0x31, 0x45, 0xea, 0x48, 0xca, 0x8f, 0x18, 0xbe, 0xdf, @@ -86,7 +86,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xfc, 0xda, 0xd1, 0xf8, 0xe9, 0xa3, 0xe1, 0xa6, 0xfb, 0x1f, 0x53, 0x58, 0x46, 0xb2, 0xf9, 0x0a, 0x00, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x1b, 0xf8, 0x0a, 0x00, 0x64, 0x5a, 0xd3, 0xfa, 0xe7, 0xf3, 0x62, 0xd8, 0x06, 0x1b, 0xe9, 0x6a, 0x8a, 0x81, 0x2b, 0xb5, 0x49, 0x14, 0x37, 0xdc, 0x9e, 0x1a, 0xcb, 0x56, 0x87, 0xfb, 0xff, 0xf7, 0x73, 0x75, 0x12, 0x0a, 0xd6, 0x48, 0x84, 0xc6, 0x21, 0xa4, 0x6d, 0xb5, 0x71, 0xef, 0x13, 0xbe, 0x4e, 0x54, 0xf1, 0x64, 0x8f, 0x3f, 0xcc, 0x9a, 0x78, diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 53a087803c..2bd7d03600 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -810,9 +810,9 @@ bool Display::clamp_y_(int y, int h, int &min_y, int &max_y) { return min_y < max_y; } -const uint8_t TESTCARD_FONT[3][8] PROGMEM = {{0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00}, // 'R' - {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00}, // 'G' - {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}}; // 'B' +constexpr uint8_t TESTCARD_FONT[3][8] PROGMEM = {{0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00}, // 'R' + {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00}, // 'G' + {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}}; // 'B' void Display::test_card() { int w = get_width(), h = get_height(), image_w, image_h; diff --git a/esphome/components/ili9xxx/ili9xxx_init.h b/esphome/components/ili9xxx/ili9xxx_init.h index 7b176ed57a..f0c6a94a65 100644 --- a/esphome/components/ili9xxx/ili9xxx_init.h +++ b/esphome/components/ili9xxx/ili9xxx_init.h @@ -7,7 +7,7 @@ namespace esphome { namespace ili9xxx { // clang-format off -static const uint8_t PROGMEM INITCMD_M5STACK[] = { +static constexpr uint8_t PROGMEM INITCMD_M5STACK[] = { 0xEF, 3, 0x03, 0x80, 0x02, 0xCF, 3, 0x00, 0xC1, 0x30, 0xED, 4, 0x64, 0x03, 0x12, 0x81, @@ -37,7 +37,7 @@ static const uint8_t PROGMEM INITCMD_M5STACK[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_M5CORE[] = { +static constexpr uint8_t PROGMEM INITCMD_M5CORE[] = { ILI9XXX_SETEXTC, 3, 0xFF,0x93,0x42, // Turn on the external command ILI9XXX_PWCTR1 , 2, 0x12, 0x12, ILI9XXX_PWCTR2 , 1, 0x03, @@ -56,7 +56,7 @@ static const uint8_t PROGMEM INITCMD_M5CORE[] = { -static const uint8_t PROGMEM INITCMD_ILI9341[] = { +static constexpr uint8_t PROGMEM INITCMD_ILI9341[] = { 0xEF, 3, 0x03, 0x80, 0x02, 0xCF, 3, 0x00, 0xC1, 0x30, 0xED, 4, 0x64, 0x03, 0x12, 0x81, @@ -86,7 +86,7 @@ static const uint8_t PROGMEM INITCMD_ILI9341[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_ILI9481[] = { +static constexpr uint8_t PROGMEM INITCMD_ILI9481[] = { ILI9XXX_SLPOUT , 0x80, // Exit sleep mode ILI9XXX_PWSET , 3, 0x07, 0x41, 0x1D, ILI9XXX_VMCTR , 3, 0x00, 0x1C, 0x1F, @@ -105,7 +105,7 @@ static const uint8_t PROGMEM INITCMD_ILI9481[] = { 0x00 // end }; -static const uint8_t PROGMEM INITCMD_ILI9481_18[] = { +static constexpr uint8_t PROGMEM INITCMD_ILI9481_18[] = { ILI9XXX_SLPOUT , 0x80, // Exit sleep mode ILI9XXX_PWSET , 3, 0x07, 0x41, 0x1D, ILI9XXX_VMCTR , 3, 0x00, 0x1C, 0x1F, @@ -124,7 +124,7 @@ static const uint8_t PROGMEM INITCMD_ILI9481_18[] = { 0x00 // end }; -static const uint8_t PROGMEM INITCMD_ILI9486[] = { +static constexpr uint8_t PROGMEM INITCMD_ILI9486[] = { ILI9XXX_SLPOUT, 0x80, ILI9XXX_PIXFMT, 1, 0x55, ILI9XXX_PWCTR3, 1, 0x44, @@ -173,7 +173,7 @@ static const uint8_t INITCMD_WAVESHARE_RES_3_5[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_ILI9488_A[] = { +static constexpr uint8_t PROGMEM INITCMD_ILI9488_A[] = { ILI9XXX_GMCTRP1,15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F, ILI9XXX_GMCTRN1,15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F, @@ -206,7 +206,7 @@ static const uint8_t PROGMEM INITCMD_ILI9488_A[] = { 0x00 // end }; -static const uint8_t PROGMEM INITCMD_ST7796[] = { +static constexpr uint8_t PROGMEM INITCMD_ST7796[] = { // This ST7796S initilization routine was copied from https://github.com/prenticedavid/Adafruit_ST7796S_kbv/blob/master/Adafruit_ST7796S_kbv.cpp ILI9XXX_SWRESET, 0x80, // Soft reset, then delay 150 ms ILI9XXX_CSCON, 1, 0xC3, // ?? Unlock Manufacturer @@ -226,7 +226,7 @@ static const uint8_t PROGMEM INITCMD_ST7796[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_S3BOX[] = { +static constexpr uint8_t PROGMEM INITCMD_S3BOX[] = { 0xEF, 3, 0x03, 0x80, 0x02, 0xCF, 3, 0x00, 0xC1, 0x30, 0xED, 4, 0x64, 0x03, 0x12, 0x81, @@ -256,7 +256,7 @@ static const uint8_t PROGMEM INITCMD_S3BOX[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_S3BOXLITE[] = { +static constexpr uint8_t PROGMEM INITCMD_S3BOXLITE[] = { 0xEF, 3, 0x03, 0x80, 0x02, 0xCF, 3, 0x00, 0xC1, 0x30, 0xED, 4, 0x64, 0x03, 0x12, 0x81, @@ -286,7 +286,7 @@ static const uint8_t PROGMEM INITCMD_S3BOXLITE[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_ST7789V[] = { +static constexpr uint8_t PROGMEM INITCMD_ST7789V[] = { ILI9XXX_SLPOUT , 0x80, // Exit Sleep ILI9XXX_DISPON , 0x80, // Display on ILI9XXX_MADCTL , 1, 0x08, // Memory Access Control, BGR @@ -313,7 +313,7 @@ static const uint8_t PROGMEM INITCMD_ST7789V[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_GC9A01A[] = { +static constexpr uint8_t PROGMEM INITCMD_GC9A01A[] = { 0xEF, 0, 0xEB, 1, 0x14, // ? 0xFE, 0, @@ -367,7 +367,7 @@ static const uint8_t PROGMEM INITCMD_GC9A01A[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_GC9D01N[] = { +static constexpr uint8_t PROGMEM INITCMD_GC9D01N[] = { // Enable Inter_command 0xFE, 0, // Inter Register Enable 1 (FEh) 0xEF, 0, // Inter Register Enable 2 (EFh) @@ -426,7 +426,7 @@ static const uint8_t PROGMEM INITCMD_GC9D01N[] = { 0x00 // End of list }; -static const uint8_t PROGMEM INITCMD_ST7735[] = { +static constexpr uint8_t PROGMEM INITCMD_ST7735[] = { ILI9XXX_SWRESET, 0, // Soft reset, then delay 10ms ILI9XXX_DELAY(10), ILI9XXX_SLPOUT , 0, // Exit Sleep, delay diff --git a/esphome/components/max7219/max7219.cpp b/esphome/components/max7219/max7219.cpp index d701e6fc86..bec62ea005 100644 --- a/esphome/components/max7219/max7219.cpp +++ b/esphome/components/max7219/max7219.cpp @@ -15,7 +15,7 @@ static const uint8_t MAX7219_REGISTER_SHUTDOWN = 0x0C; static const uint8_t MAX7219_REGISTER_TEST = 0x0F; static const uint8_t MAX7219_UNKNOWN_CHAR = 0b11111111; -const uint8_t MAX7219_ASCII_TO_RAW[95] PROGMEM = { +constexpr uint8_t MAX7219_ASCII_TO_RAW[95] PROGMEM = { 0b00000000, // ' ', ord 0x20 0b10110000, // '!', ord 0x21 0b00100010, // '"', ord 0x22 diff --git a/esphome/components/max7219digit/max7219font.h b/esphome/components/max7219digit/max7219font.h index 22d64d1ecd..53674dc60f 100644 --- a/esphome/components/max7219digit/max7219font.h +++ b/esphome/components/max7219digit/max7219font.h @@ -7,7 +7,7 @@ namespace max7219digit { // bit patterns for the CP437 font -const uint8_t MAX7219_DOT_MATRIX_FONT[256][8] PROGMEM = { +constexpr uint8_t MAX7219_DOT_MATRIX_FONT[256][8] PROGMEM = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 {0x7E, 0x81, 0x95, 0xB1, 0xB1, 0x95, 0x81, 0x7E}, // 0x01 {0x7E, 0xFF, 0xEB, 0xCF, 0xCF, 0xEB, 0xFF, 0x7E}, // 0x02 diff --git a/esphome/components/ssd1306_base/ssd1306_base.cpp b/esphome/components/ssd1306_base/ssd1306_base.cpp index be99bd93da..5bd83ec8a8 100644 --- a/esphome/components/ssd1306_base/ssd1306_base.cpp +++ b/esphome/components/ssd1306_base/ssd1306_base.cpp @@ -49,7 +49,7 @@ struct ModelDimensions { uint8_t width; uint8_t height; }; -static const ModelDimensions MODEL_DIMS[] PROGMEM = { +static constexpr ModelDimensions MODEL_DIMS[] PROGMEM = { {128, 32}, // SSD1306_MODEL_128_32 {128, 64}, // SSD1306_MODEL_128_64 {96, 16}, // SSD1306_MODEL_96_16 diff --git a/esphome/components/st7735/st7735.cpp b/esphome/components/st7735/st7735.cpp index 1a74b5ce1e..58459b79bb 100644 --- a/esphome/components/st7735/st7735.cpp +++ b/esphome/components/st7735/st7735.cpp @@ -68,7 +68,7 @@ static const uint8_t ST7735_GMCTRP1 = 0xE0; static const uint8_t ST7735_GMCTRN1 = 0xE1; // clang-format off -static const uint8_t PROGMEM +static constexpr uint8_t PROGMEM BCMD[] = { // Init commands for 7735B screens 18, // 18 commands in list: ST77XX_SWRESET, ST_CMD_DELAY, // 1: Software reset, no args, w/delay diff --git a/esphome/components/tm1621/tm1621.cpp b/esphome/components/tm1621/tm1621.cpp index 6859973857..c82d306460 100644 --- a/esphome/components/tm1621/tm1621.cpp +++ b/esphome/components/tm1621/tm1621.cpp @@ -23,7 +23,7 @@ enum Tm1621Device { TM1621_USER, TM1621_POWR316D, TM1621_THR316D }; const uint8_t TM1621_COMMANDS[] = {TM1621_SYS_EN, TM1621_LCD_ON, TM1621_BIAS, TM1621_TIMER_DIS, TM1621_WDT_DIS, TM1621_TONE_OFF, TM1621_IRQ_DIS}; -const char TM1621_KCHAR[] PROGMEM = {"0|1|2|3|4|5|6|7|8|9|-| "}; +constexpr char TM1621_KCHAR[] PROGMEM = {"0|1|2|3|4|5|6|7|8|9|-| "}; // 0 1 2 3 4 5 6 7 8 9 - off const uint8_t TM1621_DIGIT_ROW[2][12] = {{0x5F, 0x50, 0x3D, 0x79, 0x72, 0x6B, 0x6F, 0x51, 0x7F, 0x7B, 0x20, 0x00}, {0xF5, 0x05, 0xB6, 0x97, 0x47, 0xD3, 0xF3, 0x85, 0xF7, 0xD7, 0x02, 0x00}}; diff --git a/esphome/components/tm1637/tm1637.cpp b/esphome/components/tm1637/tm1637.cpp index 49da01472f..f9c876f40c 100644 --- a/esphome/components/tm1637/tm1637.cpp +++ b/esphome/components/tm1637/tm1637.cpp @@ -27,7 +27,7 @@ const uint8_t TM1637_DATA_FIXED_ADDR = 0x04; //!< Fixed address // --- // D X // XABCDEFG -const uint8_t TM1637_ASCII_TO_RAW[] PROGMEM = { +constexpr uint8_t TM1637_ASCII_TO_RAW[] PROGMEM = { 0b00000000, // ' ', ord 0x20 0b10110000, // '!', ord 0x21 0b00100010, // '"', ord 0x22 diff --git a/esphome/components/tm1638/sevenseg.h b/esphome/components/tm1638/sevenseg.h index e20a55a69f..a4c16c7422 100644 --- a/esphome/components/tm1638/sevenseg.h +++ b/esphome/components/tm1638/sevenseg.h @@ -4,7 +4,7 @@ namespace esphome { namespace tm1638 { namespace TM1638Translation { -const unsigned char SEVEN_SEG[] PROGMEM = { +constexpr unsigned char SEVEN_SEG[] PROGMEM = { 0x00, /* (space) */ 0x86, /* ! */ 0x22, /* " */ diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index cc37db6a6b..b5dac9ae4c 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdb, 0x48, 0xb6, 0xe0, 0xf3, 0xd4, 0x57, 0x40, 0x28, 0xb5, 0x8c, 0x2c, 0x26, 0xc1, 0x45, 0x92, 0x2d, 0x83, 0x4a, 0xb2, 0x65, 0xd9, 0xd5, 0x76, 0x97, 0xb7, 0xb6, 0xec, 0xda, 0x58, 0x6c, 0x09, 0x02, 0x92, 0x44, 0x96, 0x41, 0x80, 0x05, 0x24, 0xb5, 0x14, 0x89, @@ -697,7 +697,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x56, 0x78, 0xff, 0xff, 0x01, 0xa2, 0x89, 0x8c, 0x0d, 0xc4, 0x97, 0x00, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x1b, 0xc3, 0x97, 0x11, 0x55, 0xb5, 0x65, 0x2c, 0x8a, 0x8a, 0x55, 0x0b, 0xd0, 0xba, 0x80, 0x1b, 0x32, 0xb0, 0x81, 0x4f, 0x27, 0x63, 0xf1, 0x7e, 0x88, 0xe3, 0xd8, 0x52, 0x84, 0x55, 0xe8, 0x35, 0x5b, 0x2b, 0x82, 0xe1, 0xed, 0x1f, 0xfd, 0xde, 0x63, 0x38, 0x3a, 0x71, 0x78, 0xb0, 0x42, 0x17, 0x15, 0x54, 0x23, 0xe1, 0xaa, 0x28, 0x11, 0x94, 0x23, diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index bd47071dce..1f61b19fb5 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x7b, 0x7f, 0x1a, 0xb9, 0xb2, 0x28, 0xfa, 0xf7, 0x3d, 0x9f, 0xc2, 0xee, 0x9d, 0xf1, 0xb4, 0x8c, 0x68, 0x03, 0x36, 0x8e, 0xd3, 0x58, 0xe6, 0xe4, 0x39, 0xc9, 0x3c, 0x92, 0x4c, 0x9c, 0x64, 0x26, 0xc3, 0xb0, 0x33, 0xa2, 0x11, 0xa0, 0xa4, 0x91, 0x98, 0x96, 0x88, 0xed, 0x01, @@ -4104,7 +4104,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x37, 0x7a, 0x03, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x5b, 0x36, 0x7a, 0x53, 0xc2, 0x36, 0x06, 0x5a, 0x1f, 0xd4, 0x4e, 0x00, 0xb3, 0xd6, 0xea, 0xff, 0x0a, 0xab, 0x51, 0x94, 0xb1, 0xe6, 0xb0, 0x2e, 0x61, 0xbb, 0x1a, 0x70, 0x3b, 0xd8, 0x06, 0xfd, 0x7d, 0x2f, 0x1a, 0x00, 0x55, 0x35, 0xe3, 0xa8, 0x1c, 0x62, 0xca, 0xd3, 0xb4, 0x00, 0xdb, 0x5e, 0x43, 0xa7, 0x14, 0x08, 0xa4, 0x51, 0x99, 0x96, 0xb6, From afbc45bf32fe8146183d0d44fc16213cdebddbdb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 20:35:42 -0600 Subject: [PATCH 0803/2030] [e131] Drain all queued packets per loop iteration (#14133) --- esphome/components/e131/e131.cpp | 26 +++++--------------------- esphome/components/e131/e131.h | 9 +++++++++ 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index 941927122c..a7a695c167 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -70,27 +70,12 @@ void E131Component::loop() { E131Packet packet; int universe = 0; uint8_t buf[1460]; + ssize_t len; -#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) - ssize_t len = this->socket_->read(buf, sizeof(buf)); - if (len == -1) { - return; - } - - if (!this->packet_(buf, (size_t) len, universe, packet)) { - ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); - return; - } - - if (!this->process_(universe, packet)) { - ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); - } -#elif defined(USE_SOCKET_IMPL_LWIP_TCP) - while (auto packet_size = this->udp_.parsePacket()) { - auto len = this->udp_.read(buf, sizeof(buf)); - if (len <= 0) - continue; - + // Drain all queued packets so multi-universe frames are applied + // atomically before the light writes. Without this, each universe + // packet would trigger a separate full-strip write causing tearing. + while ((len = this->read_(buf, sizeof(buf))) > 0) { if (!this->packet_(buf, (size_t) len, universe, packet)) { ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); continue; @@ -100,7 +85,6 @@ void E131Component::loop() { ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); } } -#endif } void E131Component::add_effect(E131AddressableLightEffect *light_effect) { diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index fee447b678..8f0b808946 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -46,6 +46,15 @@ class E131Component : public esphome::Component { void set_method(E131ListenMethod listen_method) { this->listen_method_ = listen_method; } protected: + inline ssize_t read_(uint8_t *buf, size_t len) { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) + return this->socket_->read(buf, len); +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + if (!this->udp_.parsePacket()) + return -1; + return this->udp_.read(buf, len); +#endif + } bool packet_(const uint8_t *data, size_t len, int &universe, E131Packet &packet); bool process_(int universe, const E131Packet &packet); bool join_igmp_groups_(); From 7a2a149061c3b9480a3d1900f3e8cad1f1ad75ac Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 21:43:29 -0500 Subject: [PATCH 0804/2030] [esp32] Bump ESP-IDF to 5.5.3 (#14122) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .clang-tidy.hash | 2 +- esphome/components/esp32/__init__.py | 17 +++++++++++++---- esphome/components/esp32_ble/__init__.py | 15 +++++++++------ platformio.ini | 4 ++-- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index d6d401ee66..df584fa716 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -ce05c28e9dc0b12c4f6e7454986ffea5123ac974a949da841be698c535f2083e +3258307fa645ba77307e502075c02c4d710e92c48250839db3526d36a9655444 diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b1b3f0dc16..cdde1c4ed5 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -643,7 +643,7 @@ ARDUINO_PLATFORM_VERSION_LOOKUP = { # These versions correspond to pioarduino/esp-idf releases # See: https://github.com/pioarduino/esp-idf/releases ARDUINO_IDF_VERSION_LOOKUP = { - cv.Version(3, 3, 7): cv.Version(5, 5, 2), + cv.Version(3, 3, 7): cv.Version(5, 5, 3), cv.Version(3, 3, 6): cv.Version(5, 5, 2), cv.Version(3, 3, 5): cv.Version(5, 5, 2), cv.Version(3, 3, 4): cv.Version(5, 5, 1), @@ -662,11 +662,12 @@ ARDUINO_IDF_VERSION_LOOKUP = { # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases ESP_IDF_FRAMEWORK_VERSION_LOOKUP = { - "recommended": cv.Version(5, 5, 2), - "latest": cv.Version(5, 5, 2), - "dev": cv.Version(5, 5, 2), + "recommended": cv.Version(5, 5, 3), + "latest": cv.Version(5, 5, 3), + "dev": cv.Version(5, 5, 3), } ESP_IDF_PLATFORM_VERSION_LOOKUP = { + cv.Version(5, 5, 3): cv.Version(55, 3, 37), cv.Version(5, 5, 2): cv.Version(55, 3, 37), cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"), cv.Version(5, 5, 0): cv.Version(55, 3, 31, "2"), @@ -1471,6 +1472,14 @@ async def to_code(config): f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True ) + # ESP32-P4: ESP-IDF 5.5.3 changed the default of ESP32P4_SELECTS_REV_LESS_V3 + # from y to n. PlatformIO uses sections.ld.in (for rev <3) or + # sections.rev3.ld.in (for rev >=3) based on board definition. + # Set the sdkconfig option to match the board's revision. + if variant == VARIANT_ESP32P4: + is_rev3 = "_r3" in config[CONF_BOARD] + add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", not is_rev3) + # Set minimum chip revision for ESP32 variant # Setting this to 3.0 or higher reduces flash size by excluding workaround code, # and for PSRAM users saves significant IRAM by keeping C library functions in ROM. diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index d2020ada22..80fcf051b9 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -413,18 +413,21 @@ def final_validation(config): add_idf_sdkconfig_option("CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID", True) add_idf_sdkconfig_option("CONFIG_ESP_HOSTED_BLUEDROID_HCI_VHCI", True) - # Check if BLE Server is needed - has_ble_server = "esp32_ble_server" in full_config - # Check if BLE Client is needed (via esp32_ble_tracker or esp32_ble_client) has_ble_client = ( "esp32_ble_tracker" in full_config or "esp32_ble_client" in full_config ) - # ESP-IDF BLE stack requires GATT Server to be enabled when GATT Client is enabled - # This is an internal dependency in the Bluedroid stack (tested ESP-IDF 5.4.2-5.5.1) + # Always enable GATTS: ESP-IDF 5.5.2.260206 has a bug in gatt_main.c where a + # GATT_TRACE_DEBUG references 'msg_len' outside the GATTS_INCLUDED/GATTC_INCLUDED + # guard, causing a compile error when both are disabled. + # Additionally, when GATT Client is enabled, GATT Server must also be enabled + # as an internal dependency in the Bluedroid stack. # See: https://github.com/espressif/esp-idf/issues/17724 - add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server or has_ble_client) + # TODO: Revert to conditional once the gatt_main.c bug is fixed upstream: + # has_ble_server = "esp32_ble_server" in full_config + # add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server or has_ble_client) + add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", True) add_idf_sdkconfig_option("CONFIG_BT_GATTC_ENABLE", has_ble_client) # Handle max_connections: check for deprecated location in esp32_ble_tracker diff --git a/platformio.ini b/platformio.ini index 09b3d8722d..fdd6a36428 100644 --- a/platformio.ini +++ b/platformio.ini @@ -136,7 +136,7 @@ extends = common:arduino platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7.tar.xz - pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz + pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3/esp-idf-v5.5.3.tar.xz framework = arduino, espidf ; Arduino as an ESP-IDF component lib_deps = @@ -171,7 +171,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:idf platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = - pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.2/esp-idf-v5.5.2.tar.xz + pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3/esp-idf-v5.5.3.tar.xz framework = espidf lib_deps = From b67b2cc3ab86ebbc7cfb3d0a893bf96bd50ef9a6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 21:56:20 -0500 Subject: [PATCH 0805/2030] [ld2450] Add frame header synchronization to fix initialization regression (#14135) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/ld2450/ld2450.cpp | 22 ++- esphome/components/ld2450/ld2450.h | 1 + tests/components/ld2450/common.h | 61 +++++++ tests/components/ld2450/ld2450_readline.cpp | 181 ++++++++++++++++++++ 4 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 tests/components/ld2450/common.h create mode 100644 tests/components/ld2450/ld2450_readline.cpp diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 1ea5c18271..2af45235a3 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -769,15 +769,33 @@ void LD2450Component::readline_(int readch) { return; // No data available } + // Frame header synchronization: verify first 4 bytes match a known frame header. + // This prevents the parser from accumulating mid-frame data after losing sync + // (e.g. after module restart or UART noise). + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { + const uint8_t byte = static_cast<uint8_t>(readch); + // Verify header bytes match the frame type established by byte 0 + if (this->buffer_pos_ > 0) { + const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; + if (byte != expected[this->buffer_pos_]) { + this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame + } + } + // First byte must match start of a data or command frame header + if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { + return; + } + } + if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { - // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; + return; } - if (this->buffer_pos_ < 4) { + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { return; // Not enough data to process yet } if (this->buffer_data_[this->buffer_pos_ - 2] == DATA_FRAME_FOOTER[0] && diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index fe69cd81d0..44e5912b2a 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/automation.h" #include "esphome/core/defines.h" #include "esphome/core/component.h" #ifdef USE_SENSOR diff --git a/tests/components/ld2450/common.h b/tests/components/ld2450/common.h new file mode 100644 index 0000000000..d5ffbe1295 --- /dev/null +++ b/tests/components/ld2450/common.h @@ -0,0 +1,61 @@ +#pragma once +#include <cstdint> +#include <cstring> +#include <vector> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include "esphome/components/ld2450/ld2450.h" +#include "esphome/components/uart/uart_component.h" + +namespace esphome::ld2450::testing { + +// Mock UART component to satisfy UARTDevice parent requirement. +class MockUARTComponent : public uart::UARTComponent { + public: + void write_array(const uint8_t *data, size_t len) override {} + MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); + MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); + MOCK_METHOD(size_t, available, (), (override)); + MOCK_METHOD(void, flush, (), (override)); + MOCK_METHOD(void, check_logger_conflict, (), (override)); +}; + +// Expose protected members for testing. +class TestableLD2450 : public LD2450Component { + public: + using LD2450Component::buffer_data_; + using LD2450Component::buffer_pos_; + using LD2450Component::readline_; + + void feed(const std::vector<uint8_t> &data) { + for (uint8_t byte : data) { + this->readline_(byte); + } + } +}; + +// LD2450 periodic data frame: header (4) + 3 targets * 8 bytes + footer (2) = 30 bytes +// All-zero targets means no presence detected. +inline std::vector<uint8_t> make_periodic_frame(uint8_t fill = 0x00) { + std::vector<uint8_t> frame = {0xAA, 0xFF, 0x03, 0x00}; // DATA_FRAME_HEADER + for (int i = 0; i < 24; i++) { + frame.push_back(fill); // 3 targets * 8 bytes + } + frame.push_back(0x55); // DATA_FRAME_FOOTER + frame.push_back(0xCC); + return frame; +} + +// LD2450 command ACK frame for CMD_ENABLE_CONF (0xFF), successful. +// header (4) + length (2) + command (2) + result (2) + footer (4) = 14 bytes +inline std::vector<uint8_t> make_ack_frame() { + return { + 0xFD, 0xFC, 0xFB, 0xFA, // CMD_FRAME_HEADER + 0x04, 0x00, // length = 4 + 0xFF, 0x01, // command = enable_conf, status = success + 0x00, 0x00, // result = ok + 0x04, 0x03, 0x02, 0x01 // CMD_FRAME_FOOTER + }; +} + +} // namespace esphome::ld2450::testing diff --git a/tests/components/ld2450/ld2450_readline.cpp b/tests/components/ld2450/ld2450_readline.cpp new file mode 100644 index 0000000000..68b1dd6881 --- /dev/null +++ b/tests/components/ld2450/ld2450_readline.cpp @@ -0,0 +1,181 @@ +#include "common.h" + +namespace esphome::ld2450::testing { + +class LD2450ReadlineTest : public ::testing::Test { + protected: + void SetUp() override { + this->ld2450_.set_uart_parent(&this->mock_uart_); + // Ensure clean state + ASSERT_EQ(this->ld2450_.buffer_pos_, 0); + } + + MockUARTComponent mock_uart_; + TestableLD2450 ld2450_; +}; + +// --- Good data tests --- + +TEST_F(LD2450ReadlineTest, ValidPeriodicFrame) { + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + // After a complete valid frame, buffer should be reset + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, ValidCommandAckFrame) { + auto frame = make_ack_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, BackToBackPeriodicFrames) { + auto frame = make_periodic_frame(); + for (int i = 0; i < 5; i++) { + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Frame " << i << " not processed"; + } +} + +TEST_F(LD2450ReadlineTest, BackToBackMixedFrames) { + auto periodic = make_periodic_frame(); + auto ack = make_ack_frame(); + this->ld2450_.feed(periodic); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + this->ld2450_.feed(ack); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + this->ld2450_.feed(periodic); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Garbage rejection tests --- + +TEST_F(LD2450ReadlineTest, GarbageDiscarded) { + // Feed bytes that don't match any header start byte + std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99, 0x00, 0xFF, 0x7F}; + this->ld2450_.feed(garbage); + // Header sync should discard all of these + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { + std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99}; + this->ld2450_.feed(garbage); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Header synchronization tests --- + +TEST_F(LD2450ReadlineTest, PartialDataHeaderThenMismatch) { + // Start of a data frame header, then invalid byte + this->ld2450_.feed({0xAA, 0xFF, 0x42}); // 0x42 doesn't match DATA_FRAME_HEADER[2] (0x03) + // Parser should have reset + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, PartialCmdHeaderThenMismatch) { + // Start of a command frame header, then invalid byte + this->ld2450_.feed({0xFD, 0xFC, 0xFB, 0x42}); // 0x42 doesn't match CMD_FRAME_HEADER[3] (0xFA) + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, PartialHeaderThenValidFrame) { + // Partial header that fails, then a complete valid frame + this->ld2450_.feed({0xAA, 0xFF, 0x42}); // Fails at byte 3 + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, HeaderMismatchRecoveryOnNewHeaderByte) { + // Start data header, mismatch at byte 2, but mismatch byte is start of command header + this->ld2450_.feed({0xAA, 0xFF}); + EXPECT_EQ(this->ld2450_.buffer_pos_, 2); // Accumulating header + + this->ld2450_.feed({0xFD}); // Doesn't match DATA_FRAME_HEADER[2]=0x03, but IS CMD_FRAME_HEADER[0] + // Parser should reset and start new frame with 0xFD + EXPECT_EQ(this->ld2450_.buffer_pos_, 1); + EXPECT_EQ(this->ld2450_.buffer_data_[0], 0xFD); +} + +// --- Mid-frame / overflow recovery tests --- + +TEST_F(LD2450ReadlineTest, MidFrameDataRecovery) { + // Simulate starting mid-frame: feed the tail end of a periodic frame (no valid header) + // These bytes would be part of target data in a real frame + std::vector<uint8_t> mid_frame = {0x10, 0x20, 0x30, 0x40, 0x55, 0xCC}; + this->ld2450_.feed(mid_frame); + // All discarded (none match header start bytes) + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Now feed a valid frame + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, OverflowRecovery) { + // Feed a valid data frame header followed by enough filler to cause overflow. + // Header (4) + 36 filler = 40 bytes in buffer. The 41st byte triggers overflow. + std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; // Valid header + for (int i = 0; i < 37; i++) { + overflow_data.push_back(0x11); // Filler that won't match any footer + } + // 41 bytes total: 40 stored, 41st triggers overflow and resets buffer_pos_ to 0 + this->ld2450_.feed(overflow_data); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Feed a valid frame and verify recovery + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, RepeatedOverflowDoesNotLoop) { + // Simulate the bug scenario: repeated overflows should not prevent recovery. + // Feed 3 rounds of overflow-inducing data. + for (int round = 0; round < 3; round++) { + std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; + for (int i = 0; i < 37; i++) { + overflow_data.push_back(0x22); + } + this->ld2450_.feed(overflow_data); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Overflow round " << round; + } + + // Parser should still recover and process a valid frame + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, SimulatedRestartGarbageThenFrames) { + // Simulate LD2450 restart: burst of garbage bytes (partial frames, noise) + // followed by normal periodic data. + // Partial periodic frame (as if we started reading mid-frame), a stale footer, and more garbage + std::vector<uint8_t> restart_noise = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, // mid-frame data + 0x55, 0xCC, // stale footer bytes + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, // more garbage + }; + + this->ld2450_.feed(restart_noise); + // All garbage should be discarded + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Now the LD2450 starts sending valid frames + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +} // namespace esphome::ld2450::testing From a2f0607c1e860d1173c80e0a763fda99e71e69f6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:04:38 -0500 Subject: [PATCH 0806/2030] [ld2410] Add frame header synchronization to readline_() (#14136) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2410/ld2410.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index 95a04f768a..a3c2193d67 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -601,15 +601,33 @@ void LD2410Component::readline_(int readch) { return; // No data available } + // Frame header synchronization: verify first 4 bytes match a known frame header. + // This prevents the parser from getting stuck in an overflow loop after losing sync + // (e.g. after module restart or UART noise). + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { + const uint8_t byte = static_cast<uint8_t>(readch); + // Verify header bytes match the frame type established by byte 0 + if (this->buffer_pos_ > 0) { + const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; + if (byte != expected[this->buffer_pos_]) { + this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame + } + } + // First byte must match start of a data or command frame header + if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { + return; + } + } + if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { - // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; + return; } - if (this->buffer_pos_ < 4) { + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { return; // Not enough data to process yet } if (ld2410::validate_header_footer(DATA_FRAME_FOOTER, &this->buffer_data_[this->buffer_pos_ - 4])) { From 5af871acce9c33284d483620131056af2ad48071 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:36:12 -0500 Subject: [PATCH 0807/2030] [ld2420] Increase MAX_LINE_LENGTH to allow footer-based resync (#14137) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2420/ld2420.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 02250c5911..358793fe64 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -21,7 +21,9 @@ namespace esphome::ld2420 { static constexpr uint8_t CALIBRATE_SAMPLES = 64; -static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer +// Energy frame is 45 bytes; +1 for null terminator, +4 so that a frame footer always lands +// inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 50; static constexpr uint8_t TOTAL_GATES = 16; enum OpMode : uint8_t { From efe54e3b5e3d3ddefee703048ff37bb4ec9b0b5f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 23:25:25 -0500 Subject: [PATCH 0808/2030] [ld2410/ld2450] Replace header sync with buffer size increase for frame resync (#14138) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2410/ld2410.cpp | 19 +-- esphome/components/ld2410/ld2410.h | 6 +- esphome/components/ld2450/ld2450.cpp | 19 +-- esphome/components/ld2450/ld2450.h | 8 +- tests/components/ld2450/ld2450_readline.cpp | 158 ++++++++------------ 5 files changed, 72 insertions(+), 138 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index a3c2193d67..f8f782f804 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -601,28 +601,11 @@ void LD2410Component::readline_(int readch) { return; // No data available } - // Frame header synchronization: verify first 4 bytes match a known frame header. - // This prevents the parser from getting stuck in an overflow loop after losing sync - // (e.g. after module restart or UART noise). - if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { - const uint8_t byte = static_cast<uint8_t>(readch); - // Verify header bytes match the frame type established by byte 0 - if (this->buffer_pos_ > 0) { - const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; - if (byte != expected[this->buffer_pos_]) { - this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame - } - } - // First byte must match start of a data or command frame header - if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { - return; - } - } - if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { + // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; return; diff --git a/esphome/components/ld2410/ld2410.h b/esphome/components/ld2410/ld2410.h index efe585fb76..687ed21d1d 100644 --- a/esphome/components/ld2410/ld2410.h +++ b/esphome/components/ld2410/ld2410.h @@ -33,8 +33,10 @@ namespace esphome::ld2410 { using namespace ld24xx; -static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer -static constexpr uint8_t TOTAL_GATES = 9; // Total number of gates supported by the LD2410 +// Engineering data frame is 45 bytes; +1 for null terminator, +4 so that a frame footer always +// lands inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 50; +static constexpr uint8_t TOTAL_GATES = 9; // Total number of gates supported by the LD2410 class LD2410Component : public Component, public uart::UARTDevice { #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 2af45235a3..d30c164769 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -769,28 +769,11 @@ void LD2450Component::readline_(int readch) { return; // No data available } - // Frame header synchronization: verify first 4 bytes match a known frame header. - // This prevents the parser from accumulating mid-frame data after losing sync - // (e.g. after module restart or UART noise). - if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { - const uint8_t byte = static_cast<uint8_t>(readch); - // Verify header bytes match the frame type established by byte 0 - if (this->buffer_pos_ > 0) { - const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; - if (byte != expected[this->buffer_pos_]) { - this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame - } - } - // First byte must match start of a data or command frame header - if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { - return; - } - } - if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { + // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; return; diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 44e5912b2a..30f96c0a9c 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -38,9 +38,11 @@ using namespace ld24xx; // Constants static constexpr uint8_t DEFAULT_PRESENCE_TIMEOUT = 5; // Timeout to reset presense status 5 sec. -static constexpr uint8_t MAX_LINE_LENGTH = 41; // Max characters for serial buffer -static constexpr uint8_t MAX_TARGETS = 3; // Max 3 Targets in LD2450 -static constexpr uint8_t MAX_ZONES = 3; // Max 3 Zones in LD2450 +// Zone query response is 40 bytes; +1 for null terminator, +4 so that a frame footer always +// lands inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 45; +static constexpr uint8_t MAX_TARGETS = 3; // Max 3 Targets in LD2450 +static constexpr uint8_t MAX_ZONES = 3; // Max 3 Zones in LD2450 enum Direction : uint8_t { DIRECTION_APPROACHING = 0, diff --git a/tests/components/ld2450/ld2450_readline.cpp b/tests/components/ld2450/ld2450_readline.cpp index 68b1dd6881..cb97f633bf 100644 --- a/tests/components/ld2450/ld2450_readline.cpp +++ b/tests/components/ld2450/ld2450_readline.cpp @@ -48,19 +48,39 @@ TEST_F(LD2450ReadlineTest, BackToBackMixedFrames) { EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -// --- Garbage rejection tests --- - -TEST_F(LD2450ReadlineTest, GarbageDiscarded) { - // Feed bytes that don't match any header start byte - std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99, 0x00, 0xFF, 0x7F}; - this->ld2450_.feed(garbage); - // Header sync should discard all of these - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} +// --- Garbage then valid frame tests --- TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { + // Garbage bytes accumulate in the buffer but don't match any footer. + // A valid frame follows; its footer resets the buffer and resyncs. std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99}; this->ld2450_.feed(garbage); + EXPECT_GT(this->ld2450_.buffer_pos_, 0); // Garbage accumulated + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + // Footer from the valid frame resyncs the parser + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Footer-based resynchronization tests --- + +TEST_F(LD2450ReadlineTest, FooterInGarbageResyncs) { + // Garbage containing a periodic frame footer (0x55 0xCC) triggers + // a buffer reset, allowing the next frame to be parsed cleanly. + std::vector<uint8_t> garbage_with_footer = {0x01, 0x02, 0x03, 0x04, 0x55, 0xCC}; + this->ld2450_.feed(garbage_with_footer); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); // Footer reset the buffer + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, CmdFooterInGarbageResyncs) { + // Garbage containing a command frame footer (04 03 02 01) also resyncs. + std::vector<uint8_t> garbage_with_footer = {0x10, 0x20, 0x30, 0x40, 0x04, 0x03, 0x02, 0x01}; + this->ld2450_.feed(garbage_with_footer); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); auto frame = make_periodic_frame(); @@ -68,112 +88,56 @@ TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -// --- Header synchronization tests --- +// --- Overflow recovery tests --- -TEST_F(LD2450ReadlineTest, PartialDataHeaderThenMismatch) { - // Start of a data frame header, then invalid byte - this->ld2450_.feed({0xAA, 0xFF, 0x42}); // 0x42 doesn't match DATA_FRAME_HEADER[2] (0x03) - // Parser should have reset - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, PartialCmdHeaderThenMismatch) { - // Start of a command frame header, then invalid byte - this->ld2450_.feed({0xFD, 0xFC, 0xFB, 0x42}); // 0x42 doesn't match CMD_FRAME_HEADER[3] (0xFA) - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, PartialHeaderThenValidFrame) { - // Partial header that fails, then a complete valid frame - this->ld2450_.feed({0xAA, 0xFF, 0x42}); // Fails at byte 3 - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, HeaderMismatchRecoveryOnNewHeaderByte) { - // Start data header, mismatch at byte 2, but mismatch byte is start of command header - this->ld2450_.feed({0xAA, 0xFF}); - EXPECT_EQ(this->ld2450_.buffer_pos_, 2); // Accumulating header - - this->ld2450_.feed({0xFD}); // Doesn't match DATA_FRAME_HEADER[2]=0x03, but IS CMD_FRAME_HEADER[0] - // Parser should reset and start new frame with 0xFD - EXPECT_EQ(this->ld2450_.buffer_pos_, 1); - EXPECT_EQ(this->ld2450_.buffer_data_[0], 0xFD); -} - -// --- Mid-frame / overflow recovery tests --- - -TEST_F(LD2450ReadlineTest, MidFrameDataRecovery) { - // Simulate starting mid-frame: feed the tail end of a periodic frame (no valid header) - // These bytes would be part of target data in a real frame - std::vector<uint8_t> mid_frame = {0x10, 0x20, 0x30, 0x40, 0x55, 0xCC}; - this->ld2450_.feed(mid_frame); - // All discarded (none match header start bytes) - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - // Now feed a valid frame - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, OverflowRecovery) { - // Feed a valid data frame header followed by enough filler to cause overflow. - // Header (4) + 36 filler = 40 bytes in buffer. The 41st byte triggers overflow. - std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; // Valid header - for (int i = 0; i < 37; i++) { - overflow_data.push_back(0x11); // Filler that won't match any footer - } - // 41 bytes total: 40 stored, 41st triggers overflow and resets buffer_pos_ to 0 +TEST_F(LD2450ReadlineTest, OverflowResetsBuffer) { + // Fill the buffer to capacity with filler that won't match any footer. + // MAX_LINE_LENGTH is 45, usable is 44. The 45th byte triggers overflow. + std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11); + this->ld2450_.feed(overflow_data); + // After overflow, buffer_pos_ resets to 0 (via the < 4 early return path) + EXPECT_LT(this->ld2450_.buffer_pos_, 4); +} + +TEST_F(LD2450ReadlineTest, OverflowThenValidFrame) { + // Overflow, then a valid frame should be processed. + std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11); this->ld2450_.feed(overflow_data); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - // Feed a valid frame and verify recovery auto frame = make_periodic_frame(); this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -TEST_F(LD2450ReadlineTest, RepeatedOverflowDoesNotLoop) { - // Simulate the bug scenario: repeated overflows should not prevent recovery. - // Feed 3 rounds of overflow-inducing data. - for (int round = 0; round < 3; round++) { - std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; - for (int i = 0; i < 37; i++) { - overflow_data.push_back(0x22); - } - this->ld2450_.feed(overflow_data); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Overflow round " << round; - } - - // Parser should still recover and process a valid frame +TEST_F(LD2450ReadlineTest, BufferLargeEnoughForDesyncedFooter) { + // The key fix: the buffer (45) is large enough that a desynced periodic frame's + // footer (at most 30 bytes into the stream) will land inside the buffer before overflow. + // Simulate starting 10 bytes into a periodic frame, then a full frame follows. + std::vector<uint8_t> mid_frame = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; + // Then a complete periodic frame whose footer will land at position 40 (10 + 30), + // well within the buffer size of 45. auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); + mid_frame.insert(mid_frame.end(), frame.begin(), frame.end()); + + this->ld2450_.feed(mid_frame); + // The footer from the frame should have triggered a reset EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -TEST_F(LD2450ReadlineTest, SimulatedRestartGarbageThenFrames) { - // Simulate LD2450 restart: burst of garbage bytes (partial frames, noise) - // followed by normal periodic data. - // Partial periodic frame (as if we started reading mid-frame), a stale footer, and more garbage +TEST_F(LD2450ReadlineTest, SimulatedRestartThenFrames) { + // Simulate LD2450 restart: burst of garbage followed by valid periodic frames. + // The garbage + first frame should fit in the buffer so the footer resyncs. std::vector<uint8_t> restart_noise = { - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, // mid-frame data - 0x55, 0xCC, // stale footer bytes - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, // more garbage + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 8 bytes of mid-frame data }; + auto frame = make_periodic_frame(); + // 8 garbage + 30 frame = 38 bytes, well within buffer of 45 + restart_noise.insert(restart_noise.end(), frame.begin(), frame.end()); this->ld2450_.feed(restart_noise); - // All garbage should be discarded - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - // Now the LD2450 starts sending valid frames - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + // Subsequent frames should work normally this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } From efe8a6c8ebfd3e831b9757356db7f08fc331472e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= <contact@rodrigomartin.dev> Date: Tue, 17 Feb 2026 18:45:21 +0100 Subject: [PATCH 0809/2030] [esp32_ble_server] fix infinitely large characteristic value (#14011) --- .../components/esp32_ble_server/__init__.py | 2 +- .../esp32_ble_server/ble_characteristic.cpp | 28 +++++++++++++++---- .../esp32_ble_server/ble_characteristic.h | 1 - 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index a7e2522fac..cb494ed1bc 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -527,7 +527,7 @@ async def to_code_characteristic(service_var, char_conf): action_conf, char_conf[CONF_CHAR_VALUE_ACTION_ID_], cg.TemplateArguments(), - {}, + [], ) cg.add(value_action.play()) else: diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index 0482848ea0..a1b1ff94bb 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -246,9 +246,27 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt if (this->handle_ != param->write.handle) break; + esp_gatt_status_t status = ESP_GATT_OK; + if (param->write.is_prep) { - this->value_.insert(this->value_.end(), param->write.value, param->write.value + param->write.len); - this->write_event_ = true; + const size_t offset = param->write.offset; + const size_t write_len = param->write.len; + const size_t new_size = offset + write_len; + // Clean the buffer on the first prepared write event + if (offset == 0) { + this->value_.clear(); + } + + if (offset != this->value_.size()) { + status = ESP_GATT_INVALID_OFFSET; + } else if (new_size > ESP_GATT_MAX_ATTR_LEN) { + status = ESP_GATT_INVALID_ATTR_LEN; + } else { + if (this->value_.size() < new_size) { + this->value_.resize(new_size); + } + memcpy(this->value_.data() + offset, param->write.value, write_len); + } } else { this->set_value(ByteBuffer::wrap(param->write.value, param->write.len)); } @@ -263,7 +281,7 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt memcpy(response.attr_value.value, param->write.value, param->write.len); esp_err_t err = - esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, &response); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, &response); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gatts_send_response failed: %d", err); @@ -280,9 +298,9 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt } case ESP_GATTS_EXEC_WRITE_EVT: { - if (!this->write_event_) + // BLE stack will guarantee that ESP_GATTS_EXEC_WRITE_EVT is only received after prepared writes + if (this->value_.empty()) break; - this->write_event_ = false; if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC) { if (this->on_write_callback_) { (*this->on_write_callback_)(this->value_, param->exec_write.conn_id); diff --git a/esphome/components/esp32_ble_server/ble_characteristic.h b/esphome/components/esp32_ble_server/ble_characteristic.h index b913915789..c2cdb1660c 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.h +++ b/esphome/components/esp32_ble_server/ble_characteristic.h @@ -77,7 +77,6 @@ class BLECharacteristic { } protected: - bool write_event_{false}; BLEService *service_{}; ESPBTUUID uuid_; esp_gatt_char_prop_t properties_; From 8c0cc3a2d8bfc978865e940b03e30262f9331ead Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:01:00 -0600 Subject: [PATCH 0810/2030] [udp] Register socket consumption for CONFIG_LWIP_MAX_SOCKETS (#14068) --- esphome/components/udp/__init__.py | 63 ++++++++++++++++++------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index bfaa5f2516..c9586d0b95 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -14,6 +14,7 @@ import esphome.config_validation as cv from esphome.const import CONF_DATA, CONF_ID, CONF_PORT, CONF_TRIGGER_ID from esphome.core import ID from esphome.cpp_generator import MockObj +from esphome.types import ConfigType CODEOWNERS = ["@clydebarrow"] DEPENDENCIES = ["network"] @@ -65,33 +66,47 @@ RELOCATED = { ) } -CONFIG_SCHEMA = cv.COMPONENT_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(UDPComponent), - cv.Optional(CONF_PORT, default=18511): cv.Any( - cv.port, - cv.Schema( + +def _consume_udp_sockets(config: ConfigType) -> ConfigType: + """Register socket needs for UDP component.""" + from esphome.components import socket + + # UDP uses up to 2 sockets: 1 broadcast + 1 listen + # Whether each is used depends on code generation, so register worst case + socket.consume_sockets(2, "udp")(config) + return config + + +CONFIG_SCHEMA = cv.All( + cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(UDPComponent), + cv.Optional(CONF_PORT, default=18511): cv.Any( + cv.port, + cv.Schema( + { + cv.Required(CONF_LISTEN_PORT): cv.port, + cv.Required(CONF_BROADCAST_PORT): cv.port, + } + ), + ), + cv.Optional( + CONF_LISTEN_ADDRESS, default="255.255.255.255" + ): cv.ipv4address_multi_broadcast, + cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list( + cv.ipv4address, + ), + cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( { - cv.Required(CONF_LISTEN_PORT): cv.port, - cv.Required(CONF_BROADCAST_PORT): cv.port, + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + Trigger.template(trigger_args) + ), } ), - ), - cv.Optional( - CONF_LISTEN_ADDRESS, default="255.255.255.255" - ): cv.ipv4address_multi_broadcast, - cv.Optional(CONF_ADDRESSES, default=["255.255.255.255"]): cv.ensure_list( - cv.ipv4address, - ), - cv.Optional(CONF_ON_RECEIVE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Trigger.template(trigger_args) - ), - } - ), - } -).extend(RELOCATED) + } + ).extend(RELOCATED), + _consume_udp_sockets, +) async def register_udp_client(var, config): From e4aa23abaac53320b89d99ecd39efe9e60cbe7bd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:01:37 -0600 Subject: [PATCH 0811/2030] [web_server] Double socket allocation to prevent connection exhaustion (#14067) --- esphome/components/web_server/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 8b02a6baee..294a5e0a15 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -144,9 +144,10 @@ def _consume_web_server_sockets(config: ConfigType) -> ConfigType: """Register socket needs for web_server component.""" from esphome.components import socket - # Web server needs 1 listening socket + typically 2 concurrent client connections - # (browser makes 2 connections for page + event stream) - sockets_needed = 3 + # Web server needs 1 listening socket + typically 5 concurrent client connections + # (browser opens connections for page resources, SSE event stream, and POST + # requests for entity control which may linger before closing) + sockets_needed = 6 socket.consume_sockets(sockets_needed, "web_server")(config) return config From 887172d663c5f7bd1ffc4a4ac35f99eecccf2a6c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 19:08:53 -0600 Subject: [PATCH 0812/2030] [pulse_counter] Fix compilation on ESP32-C6/C5/H2/P4 (#14070) --- esphome/components/pulse_counter/pulse_counter_sensor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index 8ac5a28d8f..ef4cc980f6 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -2,7 +2,7 @@ #include "esphome/core/log.h" #ifdef HAS_PCNT -#include <esp_clk_tree.h> +#include <esp_private/esp_clk.h> #include <hal/pcnt_ll.h> #endif @@ -117,9 +117,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } if (this->filter_us != 0) { - uint32_t apb_freq; - esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_APB, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &apb_freq); - uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / apb_freq; + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), }; From cb8b14e64b6c4fbd01f96e75106f0b2ed452ffcc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:00:24 -0600 Subject: [PATCH 0813/2030] [web_server] Fix water_heater JSON key names and move traits to DETAIL_ALL (#14064) --- esphome/components/web_server/web_server.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index dfd602be6b..c894d32a4b 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1913,6 +1913,9 @@ std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDe JsonArray modes = root[ESPHOME_F("modes")].to<JsonArray>(); for (auto m : traits.get_supported_modes()) modes.add(PSTR_LOCAL(water_heater::water_heater_mode_to_string(m))); + root[ESPHOME_F("min_temp")] = traits.get_min_temperature(); + root[ESPHOME_F("max_temp")] = traits.get_max_temperature(); + root[ESPHOME_F("step")] = traits.get_target_temperature_step(); this->add_sorting_info_(root, obj); } @@ -1935,10 +1938,6 @@ std::string WebServer::water_heater_json_(water_heater::WaterHeater *obj, JsonDe root[ESPHOME_F("target_temperature")] = target; } - root[ESPHOME_F("min_temperature")] = traits.get_min_temperature(); - root[ESPHOME_F("max_temperature")] = traits.get_max_temperature(); - root[ESPHOME_F("step")] = traits.get_target_temperature_step(); - if (traits.get_supports_away_mode()) { root[ESPHOME_F("away")] = obj->is_away(); } From 2491b4f85c1825b7dd8bc4273eafca643cf8c120 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Feb 2026 21:32:37 -0600 Subject: [PATCH 0814/2030] [ld2420] Use constexpr for compile-time constants (#14079) --- esphome/components/ld2420/ld2420.cpp | 118 +++++++++++++-------------- esphome/components/ld2420/ld2420.h | 6 +- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 69b69f4a61..cf78a1a460 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -63,73 +63,73 @@ namespace esphome::ld2420 { static const char *const TAG = "ld2420"; // Local const's -static const uint16_t REFRESH_RATE_MS = 1000; +static constexpr uint16_t REFRESH_RATE_MS = 1000; // Command sets -static const uint16_t CMD_DISABLE_CONF = 0x00FE; -static const uint16_t CMD_ENABLE_CONF = 0x00FF; -static const uint16_t CMD_PARM_HIGH_TRESH = 0x0012; -static const uint16_t CMD_PARM_LOW_TRESH = 0x0021; -static const uint16_t CMD_PROTOCOL_VER = 0x0002; -static const uint16_t CMD_READ_ABD_PARAM = 0x0008; -static const uint16_t CMD_READ_REG_ADDR = 0x0020; -static const uint16_t CMD_READ_REGISTER = 0x0002; -static const uint16_t CMD_READ_SERIAL_NUM = 0x0011; -static const uint16_t CMD_READ_SYS_PARAM = 0x0013; -static const uint16_t CMD_READ_VERSION = 0x0000; -static const uint16_t CMD_RESTART = 0x0068; -static const uint16_t CMD_SYSTEM_MODE = 0x0000; -static const uint16_t CMD_SYSTEM_MODE_GR = 0x0003; -static const uint16_t CMD_SYSTEM_MODE_MTT = 0x0001; -static const uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064; -static const uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000; -static const uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004; -static const uint16_t CMD_SYSTEM_MODE_VS = 0x0002; -static const uint16_t CMD_WRITE_ABD_PARAM = 0x0007; -static const uint16_t CMD_WRITE_REGISTER = 0x0001; -static const uint16_t CMD_WRITE_SYS_PARAM = 0x0012; +static constexpr uint16_t CMD_DISABLE_CONF = 0x00FE; +static constexpr uint16_t CMD_ENABLE_CONF = 0x00FF; +static constexpr uint16_t CMD_PARM_HIGH_TRESH = 0x0012; +static constexpr uint16_t CMD_PARM_LOW_TRESH = 0x0021; +static constexpr uint16_t CMD_PROTOCOL_VER = 0x0002; +static constexpr uint16_t CMD_READ_ABD_PARAM = 0x0008; +static constexpr uint16_t CMD_READ_REG_ADDR = 0x0020; +static constexpr uint16_t CMD_READ_REGISTER = 0x0002; +static constexpr uint16_t CMD_READ_SERIAL_NUM = 0x0011; +static constexpr uint16_t CMD_READ_SYS_PARAM = 0x0013; +static constexpr uint16_t CMD_READ_VERSION = 0x0000; +static constexpr uint16_t CMD_RESTART = 0x0068; +static constexpr uint16_t CMD_SYSTEM_MODE = 0x0000; +static constexpr uint16_t CMD_SYSTEM_MODE_GR = 0x0003; +static constexpr uint16_t CMD_SYSTEM_MODE_MTT = 0x0001; +static constexpr uint16_t CMD_SYSTEM_MODE_SIMPLE = 0x0064; +static constexpr uint16_t CMD_SYSTEM_MODE_DEBUG = 0x0000; +static constexpr uint16_t CMD_SYSTEM_MODE_ENERGY = 0x0004; +static constexpr uint16_t CMD_SYSTEM_MODE_VS = 0x0002; +static constexpr uint16_t CMD_WRITE_ABD_PARAM = 0x0007; +static constexpr uint16_t CMD_WRITE_REGISTER = 0x0001; +static constexpr uint16_t CMD_WRITE_SYS_PARAM = 0x0012; -static const uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04; -static const uint8_t CMD_ABD_DATA_REPLY_START = 0x0A; -static const uint8_t CMD_MAX_BYTES = 0x64; -static const uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02; +static constexpr uint8_t CMD_ABD_DATA_REPLY_SIZE = 0x04; +static constexpr uint8_t CMD_ABD_DATA_REPLY_START = 0x0A; +static constexpr uint8_t CMD_MAX_BYTES = 0x64; +static constexpr uint8_t CMD_REG_DATA_REPLY_SIZE = 0x02; -static const uint8_t LD2420_ERROR_NONE = 0x00; -static const uint8_t LD2420_ERROR_TIMEOUT = 0x02; -static const uint8_t LD2420_ERROR_UNKNOWN = 0x01; +static constexpr uint8_t LD2420_ERROR_NONE = 0x00; +static constexpr uint8_t LD2420_ERROR_TIMEOUT = 0x02; +static constexpr uint8_t LD2420_ERROR_UNKNOWN = 0x01; // Register address values -static const uint16_t CMD_MIN_GATE_REG = 0x0000; -static const uint16_t CMD_MAX_GATE_REG = 0x0001; -static const uint16_t CMD_TIMEOUT_REG = 0x0004; -static const uint16_t CMD_GATE_MOVE_THRESH[TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, - 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, - 0x001C, 0x001D, 0x001E, 0x001F}; -static const uint16_t CMD_GATE_STILL_THRESH[TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, - 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, - 0x002C, 0x002D, 0x002E, 0x002F}; -static const uint32_t FACTORY_MOVE_THRESH[TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250, - 250, 250, 250, 250, 250, 250, 250, 250}; -static const uint32_t FACTORY_STILL_THRESH[TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150, - 150, 100, 100, 100, 100, 100, 100, 100}; -static const uint16_t FACTORY_TIMEOUT = 120; -static const uint16_t FACTORY_MIN_GATE = 1; -static const uint16_t FACTORY_MAX_GATE = 12; +static constexpr uint16_t CMD_MIN_GATE_REG = 0x0000; +static constexpr uint16_t CMD_MAX_GATE_REG = 0x0001; +static constexpr uint16_t CMD_TIMEOUT_REG = 0x0004; +static constexpr uint16_t CMD_GATE_MOVE_THRESH[TOTAL_GATES] = {0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, + 0x0016, 0x0017, 0x0018, 0x0019, 0x001A, 0x001B, + 0x001C, 0x001D, 0x001E, 0x001F}; +static constexpr uint16_t CMD_GATE_STILL_THRESH[TOTAL_GATES] = {0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, + 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, + 0x002C, 0x002D, 0x002E, 0x002F}; +static constexpr uint32_t FACTORY_MOVE_THRESH[TOTAL_GATES] = {60000, 30000, 400, 250, 250, 250, 250, 250, + 250, 250, 250, 250, 250, 250, 250, 250}; +static constexpr uint32_t FACTORY_STILL_THRESH[TOTAL_GATES] = {40000, 20000, 200, 200, 200, 200, 200, 150, + 150, 100, 100, 100, 100, 100, 100, 100}; +static constexpr uint16_t FACTORY_TIMEOUT = 120; +static constexpr uint16_t FACTORY_MIN_GATE = 1; +static constexpr uint16_t FACTORY_MAX_GATE = 12; // COMMAND_BYTE Header & Footer -static const uint32_t CMD_FRAME_FOOTER = 0x01020304; -static const uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD; -static const uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD; -static const uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA; -static const uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8; -static const uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4; -static const int CALIBRATE_VERSION_MIN = 154; -static const uint8_t CMD_FRAME_COMMAND = 6; -static const uint8_t CMD_FRAME_DATA_LENGTH = 4; -static const uint8_t CMD_FRAME_STATUS = 7; -static const uint8_t CMD_ERROR_WORD = 8; -static const uint8_t ENERGY_SENSOR_START = 9; -static const uint8_t CALIBRATE_REPORT_INTERVAL = 4; +static constexpr uint32_t CMD_FRAME_FOOTER = 0x01020304; +static constexpr uint32_t CMD_FRAME_HEADER = 0xFAFBFCFD; +static constexpr uint32_t DEBUG_FRAME_FOOTER = 0xFAFBFCFD; +static constexpr uint32_t DEBUG_FRAME_HEADER = 0x1410BFAA; +static constexpr uint32_t ENERGY_FRAME_FOOTER = 0xF5F6F7F8; +static constexpr uint32_t ENERGY_FRAME_HEADER = 0xF1F2F3F4; +static constexpr int CALIBRATE_VERSION_MIN = 154; +static constexpr uint8_t CMD_FRAME_COMMAND = 6; +static constexpr uint8_t CMD_FRAME_DATA_LENGTH = 4; +static constexpr uint8_t CMD_FRAME_STATUS = 7; +static constexpr uint8_t CMD_ERROR_WORD = 8; +static constexpr uint8_t ENERGY_SENSOR_START = 9; +static constexpr uint8_t CALIBRATE_REPORT_INTERVAL = 4; static const char *const OP_NORMAL_MODE_STRING = "Normal"; static const char *const OP_SIMPLE_MODE_STRING = "Simple"; diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 6d81f86497..02250c5911 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -20,9 +20,9 @@ namespace esphome::ld2420 { -static const uint8_t CALIBRATE_SAMPLES = 64; -static const uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer -static const uint8_t TOTAL_GATES = 16; +static constexpr uint8_t CALIBRATE_SAMPLES = 64; +static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer +static constexpr uint8_t TOTAL_GATES = 16; enum OpMode : uint8_t { OP_NORMAL_MODE = 1, From 25b14f995309a7dfbb4857d53f8c9a67aa8a7308 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 09:27:05 -0600 Subject: [PATCH 0815/2030] [e131] Fix E1.31 on ESP8266 and RP2040 by restoring WiFiUDP support (#14086) --- esphome/components/e131/e131.cpp | 31 ++++++++++++++++++++++++- esphome/components/e131/e131.h | 8 +++++++ esphome/components/e131/e131_packet.cpp | 2 ++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index 4187857901..941927122c 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -14,12 +14,17 @@ static const int PORT = 5568; E131Component::E131Component() {} E131Component::~E131Component() { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) if (this->socket_) { this->socket_->close(); } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + this->udp_.stop(); +#endif } void E131Component::setup() { +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) this->socket_ = socket::socket_ip(SOCK_DGRAM, IPPROTO_IP); int enable = 1; @@ -50,6 +55,13 @@ void E131Component::setup() { this->mark_failed(); return; } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + if (!this->udp_.begin(PORT)) { + ESP_LOGW(TAG, "Cannot bind E1.31 to port %d.", PORT); + this->mark_failed(); + return; + } +#endif join_igmp_groups_(); } @@ -59,19 +71,36 @@ void E131Component::loop() { int universe = 0; uint8_t buf[1460]; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) ssize_t len = this->socket_->read(buf, sizeof(buf)); if (len == -1) { return; } if (!this->packet_(buf, (size_t) len, universe, packet)) { - ESP_LOGV(TAG, "Invalid packet received of size %zd.", len); + ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); return; } if (!this->process_(universe, packet)) { ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); } +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + while (auto packet_size = this->udp_.parsePacket()) { + auto len = this->udp_.read(buf, sizeof(buf)); + if (len <= 0) + continue; + + if (!this->packet_(buf, (size_t) len, universe, packet)) { + ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); + continue; + } + + if (!this->process_(universe, packet)) { + ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); + } + } +#endif } void E131Component::add_effect(E131AddressableLightEffect *light_effect) { diff --git a/esphome/components/e131/e131.h b/esphome/components/e131/e131.h index d4b272eae2..72da9ddebe 100644 --- a/esphome/components/e131/e131.h +++ b/esphome/components/e131/e131.h @@ -1,7 +1,11 @@ #pragma once #include "esphome/core/defines.h" #ifdef USE_NETWORK +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) #include "esphome/components/socket/socket.h" +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) +#include <WiFiUdp.h> +#endif #include "esphome/core/component.h" #include <cinttypes> @@ -45,7 +49,11 @@ class E131Component : public esphome::Component { void leave_(int universe); E131ListenMethod listen_method_{E131_MULTICAST}; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) std::unique_ptr<socket::Socket> socket_; +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) + WiFiUDP udp_; +#endif std::vector<E131AddressableLightEffect *> light_effects_; std::map<int, int> universe_consumers_; }; diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index ed081e5758..aa5c740454 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -62,8 +62,10 @@ const size_t E131_MIN_PACKET_SIZE = reinterpret_cast<size_t>(&((E131RawPacket *) bool E131Component::join_igmp_groups_() { if (listen_method_ != E131_MULTICAST) return false; +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) if (this->socket_ == nullptr) return false; +#endif for (auto universe : universe_consumers_) { if (!universe.second) From 2d2178c90a7d8357a1b51cd51c02b6f800d70559 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 11:00:34 -0500 Subject: [PATCH 0816/2030] [socket] Fix IPv6 compilation error on host platform (#14101) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/socket/socket.cpp | 10 ++++++++-- tests/components/socket/common.yaml | 11 +++++++++++ tests/components/socket/test-ipv6.esp32-idf.yaml | 4 ++++ tests/components/socket/test-ipv6.host.yaml | 4 ++++ tests/components/socket/test.esp32-idf.yaml | 1 + tests/components/socket/test.host.yaml | 3 +++ 6 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 tests/components/socket/common.yaml create mode 100644 tests/components/socket/test-ipv6.esp32-idf.yaml create mode 100644 tests/components/socket/test-ipv6.host.yaml create mode 100644 tests/components/socket/test.esp32-idf.yaml create mode 100644 tests/components/socket/test.host.yaml diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 2fcc162ead..6154c497e0 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -59,8 +59,14 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s #if USE_NETWORK_IPV6 else if (addr_ptr->sa_family == AF_INET6 && len >= sizeof(sockaddr_in6)) { const auto *addr = reinterpret_cast<const struct sockaddr_in6 *>(addr_ptr); -#ifndef USE_SOCKET_IMPL_LWIP_TCP - // Format IPv4-mapped IPv6 addresses as regular IPv4 (not supported on ESP8266 raw TCP) +#ifdef USE_HOST + // Format IPv4-mapped IPv6 addresses as regular IPv4 (POSIX layout, no LWIP union) + if (IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr) && + esphome_inet_ntop4(&addr->sin6_addr.s6_addr[12], buf.data(), buf.size()) != nullptr) { + return strlen(buf.data()); + } +#elif !defined(USE_SOCKET_IMPL_LWIP_TCP) + // Format IPv4-mapped IPv6 addresses as regular IPv4 (LWIP layout) if (addr->sin6_addr.un.u32_addr[0] == 0 && addr->sin6_addr.un.u32_addr[1] == 0 && addr->sin6_addr.un.u32_addr[2] == htonl(0xFFFF) && esphome_inet_ntop4(&addr->sin6_addr.un.u32_addr[3], buf.data(), buf.size()) != nullptr) { diff --git a/tests/components/socket/common.yaml b/tests/components/socket/common.yaml new file mode 100644 index 0000000000..aaf49f1611 --- /dev/null +++ b/tests/components/socket/common.yaml @@ -0,0 +1,11 @@ +substitutions: + network_enable_ipv6: "false" + +socket: + +wifi: + ssid: MySSID + password: password1 + +network: + enable_ipv6: ${network_enable_ipv6} diff --git a/tests/components/socket/test-ipv6.esp32-idf.yaml b/tests/components/socket/test-ipv6.esp32-idf.yaml new file mode 100644 index 0000000000..da1324b17e --- /dev/null +++ b/tests/components/socket/test-ipv6.esp32-idf.yaml @@ -0,0 +1,4 @@ +substitutions: + network_enable_ipv6: "true" + +<<: !include common.yaml diff --git a/tests/components/socket/test-ipv6.host.yaml b/tests/components/socket/test-ipv6.host.yaml new file mode 100644 index 0000000000..fdd52c574e --- /dev/null +++ b/tests/components/socket/test-ipv6.host.yaml @@ -0,0 +1,4 @@ +socket: + +network: + enable_ipv6: true diff --git a/tests/components/socket/test.esp32-idf.yaml b/tests/components/socket/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/socket/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/socket/test.host.yaml b/tests/components/socket/test.host.yaml new file mode 100644 index 0000000000..e0c5d7cea3 --- /dev/null +++ b/tests/components/socket/test.host.yaml @@ -0,0 +1,3 @@ +socket: + +network: From a343ff19895c0699671766f7ee8a0b0ec81bd321 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:00:05 -0500 Subject: [PATCH 0817/2030] [ethernet] Improve clk_mode deprecation warning with actionable YAML (#14104) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ethernet/__init__.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 52f5f44d41..935d2004d4 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -218,12 +218,19 @@ def _validate(config): ) elif config[CONF_TYPE] != "OPENETH": if CONF_CLK_MODE in config: + mode, pin = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] LOGGER.warning( - "[ethernet] The 'clk_mode' option is deprecated and will be removed in ESPHome 2026.1. " - "Please update your configuration to use 'clk' instead." + "[ethernet] The 'clk_mode' option is deprecated. " + "Please replace 'clk_mode: %s' with:\n" + " clk:\n" + " mode: %s\n" + " pin: %s\n" + "Removal scheduled for 2026.7.0.", + config[CONF_CLK_MODE], + mode, + pin, ) - mode = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] - config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode[0], CONF_PIN: mode[1]}) + config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode, CONF_PIN: pin}) del config[CONF_CLK_MODE] elif CONF_CLK not in config: raise cv.Invalid("'clk' is a required option for [ethernet].") From ac76fc44098f2a7adb74b212093c9353ff0c8912 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:25:26 -0500 Subject: [PATCH 0818/2030] [pulse_counter] Fix build failure when use_pcnt is false (#14111) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/pulse_counter/pulse_counter_sensor.h | 4 ++-- .../pulse_counter/test-no-pcnt.esp32-idf.yaml | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.h b/esphome/components/pulse_counter/pulse_counter_sensor.h index a7913d5d66..7a68858099 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.h +++ b/esphome/components/pulse_counter/pulse_counter_sensor.h @@ -8,10 +8,10 @@ #if defined(USE_ESP32) #include <soc/soc_caps.h> -#ifdef SOC_PCNT_SUPPORTED +#if defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>) #include <driver/pulse_cnt.h> #define HAS_PCNT -#endif // SOC_PCNT_SUPPORTED +#endif // defined(SOC_PCNT_SUPPORTED) && __has_include(<driver/pulse_cnt.h>) #endif // USE_ESP32 namespace esphome { diff --git a/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml b/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml new file mode 100644 index 0000000000..cd15cc781d --- /dev/null +++ b/tests/components/pulse_counter/test-no-pcnt.esp32-idf.yaml @@ -0,0 +1,10 @@ +sensor: + - platform: pulse_counter + name: Pulse Counter + pin: 4 + use_pcnt: false + count_mode: + rising_edge: INCREMENT + falling_edge: DECREMENT + internal_filter: 13us + update_interval: 15s From d78496321e2a65208fe83d7ea93d7107914419b0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 11:41:00 -0600 Subject: [PATCH 0819/2030] [esp32_ble] Enable CONFIG_BT_RELEASE_IRAM on ESP32-C2 (#14109) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_ble/__init__.py | 10 ++++++++++ tests/components/esp32_ble/test.esp32-c2-idf.yaml | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 tests/components/esp32_ble/test.esp32-c2-idf.yaml diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index dcc3ce71cf..d2020ada22 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -9,6 +9,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import socket from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +from esphome.components.esp32.const import VARIANT_ESP32C2 import esphome.config_validation as cv from esphome.const import ( CONF_ENABLE_ON_BOOT, @@ -387,6 +388,15 @@ def final_validation(config): f"Name '{name}' is too long, maximum length is {max_length} characters" ) + # ESP32-C2 has very limited RAM (~272KB). Without releasing BLE IRAM, + # esp_bt_controller_init fails with ESP_ERR_NO_MEM. + # CONFIG_BT_RELEASE_IRAM changes the memory layout so IRAM and DRAM share + # space more flexibly, giving the BT controller enough contiguous memory. + # This requires CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT to be disabled. + if get_esp32_variant() == VARIANT_ESP32C2: + add_idf_sdkconfig_option("CONFIG_BT_RELEASE_IRAM", True) + add_idf_sdkconfig_option("CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT", False) + # Set GATT Client/Server sdkconfig options based on which components are loaded full_config = fv.full_config.get() diff --git a/tests/components/esp32_ble/test.esp32-c2-idf.yaml b/tests/components/esp32_ble/test.esp32-c2-idf.yaml new file mode 100644 index 0000000000..f8defaf28f --- /dev/null +++ b/tests/components/esp32_ble/test.esp32-c2-idf.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +esp32_ble: + io_capability: keyboard_only + disable_bt_logs: false From 0fc09462ff73e82b380389c3ae1f885947fc70f5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 12:45:04 -0500 Subject: [PATCH 0820/2030] [safe_mode] Log brownout as reset reason on OTA rollback (#14113) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/safe_mode/safe_mode.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index f32511531a..6cae4bf9d5 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -11,6 +11,7 @@ #if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) #include <esp_ota_ops.h> +#include <esp_system.h> #endif namespace esphome::safe_mode { @@ -54,6 +55,10 @@ void SafeModeComponent::dump_config() { "OTA rollback detected! Rolled back from partition '%s'\n" "The device reset before the boot was marked successful", last_invalid->label); + if (esp_reset_reason() == ESP_RST_BROWNOUT) { + ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!\n" + "See https://esphome.io/guides/faq.html#brownout-detector-was-triggered"); + } } #endif } From f412ab4f8b954ca7f81125237df452832decaa56 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 15:14:48 -0500 Subject: [PATCH 0821/2030] [wifi] Sync output_power with PHY max TX power to prevent brownout (#14118) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/wifi/__init__.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index e865de8663..afceec6c54 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -1,4 +1,5 @@ import logging +import math from esphome import automation from esphome.automation import Condition @@ -493,6 +494,13 @@ async def to_code(config): cg.add(var.set_passive_scan(True)) if CONF_OUTPUT_POWER in config: cg.add(var.set_output_power(config[CONF_OUTPUT_POWER])) + if CORE.is_esp32: + # Set PHY max TX power to match output_power so calibration also uses + # reduced power. This prevents brownout during PHY init on marginal + # power supplies, which is critical for OTA updates with rollback enabled. + # Kconfig range is 10-20, ESPHome allows 8.5-20.5 + phy_tx_power = max(10, min(20, math.ceil(config[CONF_OUTPUT_POWER]))) + add_idf_sdkconfig_option("CONFIG_ESP_PHY_MAX_WIFI_TX_POWER", phy_tx_power) # enable_on_boot defaults to true in C++ - only set if false if not config[CONF_ENABLE_ON_BOOT]: cg.add(var.set_enable_on_boot(False)) From 7bdeb32a8a1ca43e07b64e80daa0afa13bc68206 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Feb 2026 17:48:18 -0600 Subject: [PATCH 0822/2030] [uart] Always call pin setup for UART0 default pins on ESP-IDF (#14130) --- .../uart/uart_component_esp_idf.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 6c242220a6..ea7a09fee6 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -19,6 +19,13 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; +/// Check if a pin number matches one of the default UART0 GPIO pins. +/// These pins may have residual state from the boot console that requires +/// explicit reset before UART reconfiguration (ESP-IDF issue #17459). +static constexpr bool is_default_uart0_pin(int8_t pin_num) { + return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; +} + uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -150,20 +157,26 @@ void IDFUARTComponent::load_settings(bool dump_config) { // Commit 9ed617fb17 removed gpio_func_sel() calls from uart_set_pin(), which breaks // UART on default UART0 pins that may have residual state from boot console. // Reset these pins before configuring UART to ensure they're in a clean state. - if (tx == U0TXD_GPIO_NUM || tx == U0RXD_GPIO_NUM) { + if (is_default_uart0_pin(tx)) { gpio_reset_pin(static_cast<gpio_num_t>(tx)); } - if (rx == U0TXD_GPIO_NUM || rx == U0RXD_GPIO_NUM) { + if (is_default_uart0_pin(rx)) { gpio_reset_pin(static_cast<gpio_num_t>(rx)); } - // Setup pins after reset to preserve open drain/pullup/pulldown flags + // Setup pins after reset to configure GPIO direction and pull resistors. + // For UART0 default pins, setup() must always be called because gpio_reset_pin() + // above sets GPIO_MODE_DISABLE which disables the input buffer. Without setup(), + // uart_set_pin() on ESP-IDF 5.4.2+ does not re-enable the input buffer for + // IOMUX-connected pins, so the RX pin cannot receive data (see issue #10132). + // For other pins, only call setup() if pull or open-drain flags are set to avoid + // disturbing the default pin state which breaks some external components (#11823). auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; } const auto mask = gpio::Flags::FLAG_OPEN_DRAIN | gpio::Flags::FLAG_PULLUP | gpio::Flags::FLAG_PULLDOWN; - if ((pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { + if (is_default_uart0_pin(pin->get_pin()) || (pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { pin->setup(); } }; From e7e1acc0a2fb1e1c3c5ce7fc448cca2050bb2d17 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 19:12:37 -0500 Subject: [PATCH 0823/2030] [pulse_counter] Fix PCNT glitch filter calculation off by 1000x (#14132) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/pulse_counter/pulse_counter_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index ef4cc980f6..5e62c0a410 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -117,7 +117,7 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } if (this->filter_us != 0) { - uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000000u / (uint32_t) esp_clk_apb_freq(); + uint32_t max_glitch_ns = PCNT_LL_MAX_GLITCH_WIDTH * 1000u / ((uint32_t) esp_clk_apb_freq() / 1000000u); pcnt_glitch_filter_config_t filter_config = { .max_glitch_ns = std::min(this->filter_us * 1000u, max_glitch_ns), }; From d19c1b689af4dbbe85e24f02580e586f6025ea73 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 21:56:20 -0500 Subject: [PATCH 0824/2030] [ld2450] Add frame header synchronization to fix initialization regression (#14135) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/ld2450/ld2450.cpp | 22 ++- esphome/components/ld2450/ld2450.h | 1 + tests/components/ld2450/common.h | 61 +++++++ tests/components/ld2450/ld2450_readline.cpp | 181 ++++++++++++++++++++ 4 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 tests/components/ld2450/common.h create mode 100644 tests/components/ld2450/ld2450_readline.cpp diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 1ea5c18271..2af45235a3 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -769,15 +769,33 @@ void LD2450Component::readline_(int readch) { return; // No data available } + // Frame header synchronization: verify first 4 bytes match a known frame header. + // This prevents the parser from accumulating mid-frame data after losing sync + // (e.g. after module restart or UART noise). + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { + const uint8_t byte = static_cast<uint8_t>(readch); + // Verify header bytes match the frame type established by byte 0 + if (this->buffer_pos_ > 0) { + const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; + if (byte != expected[this->buffer_pos_]) { + this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame + } + } + // First byte must match start of a data or command frame header + if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { + return; + } + } + if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { - // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; + return; } - if (this->buffer_pos_ < 4) { + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { return; // Not enough data to process yet } if (this->buffer_data_[this->buffer_pos_ - 2] == DATA_FRAME_FOOTER[0] && diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index fe69cd81d0..44e5912b2a 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/automation.h" #include "esphome/core/defines.h" #include "esphome/core/component.h" #ifdef USE_SENSOR diff --git a/tests/components/ld2450/common.h b/tests/components/ld2450/common.h new file mode 100644 index 0000000000..d5ffbe1295 --- /dev/null +++ b/tests/components/ld2450/common.h @@ -0,0 +1,61 @@ +#pragma once +#include <cstdint> +#include <cstring> +#include <vector> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include "esphome/components/ld2450/ld2450.h" +#include "esphome/components/uart/uart_component.h" + +namespace esphome::ld2450::testing { + +// Mock UART component to satisfy UARTDevice parent requirement. +class MockUARTComponent : public uart::UARTComponent { + public: + void write_array(const uint8_t *data, size_t len) override {} + MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); + MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); + MOCK_METHOD(size_t, available, (), (override)); + MOCK_METHOD(void, flush, (), (override)); + MOCK_METHOD(void, check_logger_conflict, (), (override)); +}; + +// Expose protected members for testing. +class TestableLD2450 : public LD2450Component { + public: + using LD2450Component::buffer_data_; + using LD2450Component::buffer_pos_; + using LD2450Component::readline_; + + void feed(const std::vector<uint8_t> &data) { + for (uint8_t byte : data) { + this->readline_(byte); + } + } +}; + +// LD2450 periodic data frame: header (4) + 3 targets * 8 bytes + footer (2) = 30 bytes +// All-zero targets means no presence detected. +inline std::vector<uint8_t> make_periodic_frame(uint8_t fill = 0x00) { + std::vector<uint8_t> frame = {0xAA, 0xFF, 0x03, 0x00}; // DATA_FRAME_HEADER + for (int i = 0; i < 24; i++) { + frame.push_back(fill); // 3 targets * 8 bytes + } + frame.push_back(0x55); // DATA_FRAME_FOOTER + frame.push_back(0xCC); + return frame; +} + +// LD2450 command ACK frame for CMD_ENABLE_CONF (0xFF), successful. +// header (4) + length (2) + command (2) + result (2) + footer (4) = 14 bytes +inline std::vector<uint8_t> make_ack_frame() { + return { + 0xFD, 0xFC, 0xFB, 0xFA, // CMD_FRAME_HEADER + 0x04, 0x00, // length = 4 + 0xFF, 0x01, // command = enable_conf, status = success + 0x00, 0x00, // result = ok + 0x04, 0x03, 0x02, 0x01 // CMD_FRAME_FOOTER + }; +} + +} // namespace esphome::ld2450::testing diff --git a/tests/components/ld2450/ld2450_readline.cpp b/tests/components/ld2450/ld2450_readline.cpp new file mode 100644 index 0000000000..68b1dd6881 --- /dev/null +++ b/tests/components/ld2450/ld2450_readline.cpp @@ -0,0 +1,181 @@ +#include "common.h" + +namespace esphome::ld2450::testing { + +class LD2450ReadlineTest : public ::testing::Test { + protected: + void SetUp() override { + this->ld2450_.set_uart_parent(&this->mock_uart_); + // Ensure clean state + ASSERT_EQ(this->ld2450_.buffer_pos_, 0); + } + + MockUARTComponent mock_uart_; + TestableLD2450 ld2450_; +}; + +// --- Good data tests --- + +TEST_F(LD2450ReadlineTest, ValidPeriodicFrame) { + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + // After a complete valid frame, buffer should be reset + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, ValidCommandAckFrame) { + auto frame = make_ack_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, BackToBackPeriodicFrames) { + auto frame = make_periodic_frame(); + for (int i = 0; i < 5; i++) { + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Frame " << i << " not processed"; + } +} + +TEST_F(LD2450ReadlineTest, BackToBackMixedFrames) { + auto periodic = make_periodic_frame(); + auto ack = make_ack_frame(); + this->ld2450_.feed(periodic); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + this->ld2450_.feed(ack); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + this->ld2450_.feed(periodic); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Garbage rejection tests --- + +TEST_F(LD2450ReadlineTest, GarbageDiscarded) { + // Feed bytes that don't match any header start byte + std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99, 0x00, 0xFF, 0x7F}; + this->ld2450_.feed(garbage); + // Header sync should discard all of these + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { + std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99}; + this->ld2450_.feed(garbage); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Header synchronization tests --- + +TEST_F(LD2450ReadlineTest, PartialDataHeaderThenMismatch) { + // Start of a data frame header, then invalid byte + this->ld2450_.feed({0xAA, 0xFF, 0x42}); // 0x42 doesn't match DATA_FRAME_HEADER[2] (0x03) + // Parser should have reset + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, PartialCmdHeaderThenMismatch) { + // Start of a command frame header, then invalid byte + this->ld2450_.feed({0xFD, 0xFC, 0xFB, 0x42}); // 0x42 doesn't match CMD_FRAME_HEADER[3] (0xFA) + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, PartialHeaderThenValidFrame) { + // Partial header that fails, then a complete valid frame + this->ld2450_.feed({0xAA, 0xFF, 0x42}); // Fails at byte 3 + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, HeaderMismatchRecoveryOnNewHeaderByte) { + // Start data header, mismatch at byte 2, but mismatch byte is start of command header + this->ld2450_.feed({0xAA, 0xFF}); + EXPECT_EQ(this->ld2450_.buffer_pos_, 2); // Accumulating header + + this->ld2450_.feed({0xFD}); // Doesn't match DATA_FRAME_HEADER[2]=0x03, but IS CMD_FRAME_HEADER[0] + // Parser should reset and start new frame with 0xFD + EXPECT_EQ(this->ld2450_.buffer_pos_, 1); + EXPECT_EQ(this->ld2450_.buffer_data_[0], 0xFD); +} + +// --- Mid-frame / overflow recovery tests --- + +TEST_F(LD2450ReadlineTest, MidFrameDataRecovery) { + // Simulate starting mid-frame: feed the tail end of a periodic frame (no valid header) + // These bytes would be part of target data in a real frame + std::vector<uint8_t> mid_frame = {0x10, 0x20, 0x30, 0x40, 0x55, 0xCC}; + this->ld2450_.feed(mid_frame); + // All discarded (none match header start bytes) + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Now feed a valid frame + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, OverflowRecovery) { + // Feed a valid data frame header followed by enough filler to cause overflow. + // Header (4) + 36 filler = 40 bytes in buffer. The 41st byte triggers overflow. + std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; // Valid header + for (int i = 0; i < 37; i++) { + overflow_data.push_back(0x11); // Filler that won't match any footer + } + // 41 bytes total: 40 stored, 41st triggers overflow and resets buffer_pos_ to 0 + this->ld2450_.feed(overflow_data); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Feed a valid frame and verify recovery + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, RepeatedOverflowDoesNotLoop) { + // Simulate the bug scenario: repeated overflows should not prevent recovery. + // Feed 3 rounds of overflow-inducing data. + for (int round = 0; round < 3; round++) { + std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; + for (int i = 0; i < 37; i++) { + overflow_data.push_back(0x22); + } + this->ld2450_.feed(overflow_data); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Overflow round " << round; + } + + // Parser should still recover and process a valid frame + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, SimulatedRestartGarbageThenFrames) { + // Simulate LD2450 restart: burst of garbage bytes (partial frames, noise) + // followed by normal periodic data. + // Partial periodic frame (as if we started reading mid-frame), a stale footer, and more garbage + std::vector<uint8_t> restart_noise = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, // mid-frame data + 0x55, 0xCC, // stale footer bytes + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, // more garbage + }; + + this->ld2450_.feed(restart_noise); + // All garbage should be discarded + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + // Now the LD2450 starts sending valid frames + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +} // namespace esphome::ld2450::testing From 49afe53a2cfae55feb304695ee1735a5f0e5bc43 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:04:38 -0500 Subject: [PATCH 0825/2030] [ld2410] Add frame header synchronization to readline_() (#14136) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2410/ld2410.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index 95a04f768a..a3c2193d67 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -601,15 +601,33 @@ void LD2410Component::readline_(int readch) { return; // No data available } + // Frame header synchronization: verify first 4 bytes match a known frame header. + // This prevents the parser from getting stuck in an overflow loop after losing sync + // (e.g. after module restart or UART noise). + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { + const uint8_t byte = static_cast<uint8_t>(readch); + // Verify header bytes match the frame type established by byte 0 + if (this->buffer_pos_ > 0) { + const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; + if (byte != expected[this->buffer_pos_]) { + this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame + } + } + // First byte must match start of a data or command frame header + if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { + return; + } + } + if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { - // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; + return; } - if (this->buffer_pos_ < 4) { + if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { return; // Not enough data to process yet } if (ld2410::validate_header_footer(DATA_FRAME_FOOTER, &this->buffer_data_[this->buffer_pos_ - 4])) { From 4c8e0575f94fb660bba85403347b999a424abe92 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 22:36:12 -0500 Subject: [PATCH 0826/2030] [ld2420] Increase MAX_LINE_LENGTH to allow footer-based resync (#14137) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2420/ld2420.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 02250c5911..358793fe64 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -21,7 +21,9 @@ namespace esphome::ld2420 { static constexpr uint8_t CALIBRATE_SAMPLES = 64; -static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer +// Energy frame is 45 bytes; +1 for null terminator, +4 so that a frame footer always lands +// inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 50; static constexpr uint8_t TOTAL_GATES = 16; enum OpMode : uint8_t { From 28d510191c150ac3163bfdc80f23738c2cddb908 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 19 Feb 2026 23:25:25 -0500 Subject: [PATCH 0827/2030] [ld2410/ld2450] Replace header sync with buffer size increase for frame resync (#14138) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2410/ld2410.cpp | 19 +-- esphome/components/ld2410/ld2410.h | 6 +- esphome/components/ld2450/ld2450.cpp | 19 +-- esphome/components/ld2450/ld2450.h | 8 +- tests/components/ld2450/ld2450_readline.cpp | 158 ++++++++------------ 5 files changed, 72 insertions(+), 138 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index a3c2193d67..f8f782f804 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -601,28 +601,11 @@ void LD2410Component::readline_(int readch) { return; // No data available } - // Frame header synchronization: verify first 4 bytes match a known frame header. - // This prevents the parser from getting stuck in an overflow loop after losing sync - // (e.g. after module restart or UART noise). - if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { - const uint8_t byte = static_cast<uint8_t>(readch); - // Verify header bytes match the frame type established by byte 0 - if (this->buffer_pos_ > 0) { - const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; - if (byte != expected[this->buffer_pos_]) { - this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame - } - } - // First byte must match start of a data or command frame header - if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { - return; - } - } - if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { + // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; return; diff --git a/esphome/components/ld2410/ld2410.h b/esphome/components/ld2410/ld2410.h index efe585fb76..687ed21d1d 100644 --- a/esphome/components/ld2410/ld2410.h +++ b/esphome/components/ld2410/ld2410.h @@ -33,8 +33,10 @@ namespace esphome::ld2410 { using namespace ld24xx; -static constexpr uint8_t MAX_LINE_LENGTH = 46; // Max characters for serial buffer -static constexpr uint8_t TOTAL_GATES = 9; // Total number of gates supported by the LD2410 +// Engineering data frame is 45 bytes; +1 for null terminator, +4 so that a frame footer always +// lands inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 50; +static constexpr uint8_t TOTAL_GATES = 9; // Total number of gates supported by the LD2410 class LD2410Component : public Component, public uart::UARTDevice { #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 2af45235a3..d30c164769 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -769,28 +769,11 @@ void LD2450Component::readline_(int readch) { return; // No data available } - // Frame header synchronization: verify first 4 bytes match a known frame header. - // This prevents the parser from accumulating mid-frame data after losing sync - // (e.g. after module restart or UART noise). - if (this->buffer_pos_ < HEADER_FOOTER_SIZE) { - const uint8_t byte = static_cast<uint8_t>(readch); - // Verify header bytes match the frame type established by byte 0 - if (this->buffer_pos_ > 0) { - const uint8_t *expected = (this->buffer_data_[0] == DATA_FRAME_HEADER[0]) ? DATA_FRAME_HEADER : CMD_FRAME_HEADER; - if (byte != expected[this->buffer_pos_]) { - this->buffer_pos_ = 0; // Reset and fall through to check if this byte starts a new frame - } - } - // First byte must match start of a data or command frame header - if (this->buffer_pos_ == 0 && byte != DATA_FRAME_HEADER[0] && byte != CMD_FRAME_HEADER[0]) { - return; - } - } - if (this->buffer_pos_ < MAX_LINE_LENGTH - 1) { this->buffer_data_[this->buffer_pos_++] = readch; this->buffer_data_[this->buffer_pos_] = 0; } else { + // We should never get here, but just in case... ESP_LOGW(TAG, "Max command length exceeded; ignoring"); this->buffer_pos_ = 0; return; diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 44e5912b2a..30f96c0a9c 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -38,9 +38,11 @@ using namespace ld24xx; // Constants static constexpr uint8_t DEFAULT_PRESENCE_TIMEOUT = 5; // Timeout to reset presense status 5 sec. -static constexpr uint8_t MAX_LINE_LENGTH = 41; // Max characters for serial buffer -static constexpr uint8_t MAX_TARGETS = 3; // Max 3 Targets in LD2450 -static constexpr uint8_t MAX_ZONES = 3; // Max 3 Zones in LD2450 +// Zone query response is 40 bytes; +1 for null terminator, +4 so that a frame footer always +// lands inside the buffer during footer-based resynchronization after losing sync. +static constexpr uint8_t MAX_LINE_LENGTH = 45; +static constexpr uint8_t MAX_TARGETS = 3; // Max 3 Targets in LD2450 +static constexpr uint8_t MAX_ZONES = 3; // Max 3 Zones in LD2450 enum Direction : uint8_t { DIRECTION_APPROACHING = 0, diff --git a/tests/components/ld2450/ld2450_readline.cpp b/tests/components/ld2450/ld2450_readline.cpp index 68b1dd6881..cb97f633bf 100644 --- a/tests/components/ld2450/ld2450_readline.cpp +++ b/tests/components/ld2450/ld2450_readline.cpp @@ -48,19 +48,39 @@ TEST_F(LD2450ReadlineTest, BackToBackMixedFrames) { EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -// --- Garbage rejection tests --- - -TEST_F(LD2450ReadlineTest, GarbageDiscarded) { - // Feed bytes that don't match any header start byte - std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99, 0x00, 0xFF, 0x7F}; - this->ld2450_.feed(garbage); - // Header sync should discard all of these - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} +// --- Garbage then valid frame tests --- TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { + // Garbage bytes accumulate in the buffer but don't match any footer. + // A valid frame follows; its footer resets the buffer and resyncs. std::vector<uint8_t> garbage = {0x01, 0x02, 0x03, 0x42, 0x99}; this->ld2450_.feed(garbage); + EXPECT_GT(this->ld2450_.buffer_pos_, 0); // Garbage accumulated + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + // Footer from the valid frame resyncs the parser + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +// --- Footer-based resynchronization tests --- + +TEST_F(LD2450ReadlineTest, FooterInGarbageResyncs) { + // Garbage containing a periodic frame footer (0x55 0xCC) triggers + // a buffer reset, allowing the next frame to be parsed cleanly. + std::vector<uint8_t> garbage_with_footer = {0x01, 0x02, 0x03, 0x04, 0x55, 0xCC}; + this->ld2450_.feed(garbage_with_footer); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); // Footer reset the buffer + + auto frame = make_periodic_frame(); + this->ld2450_.feed(frame); + EXPECT_EQ(this->ld2450_.buffer_pos_, 0); +} + +TEST_F(LD2450ReadlineTest, CmdFooterInGarbageResyncs) { + // Garbage containing a command frame footer (04 03 02 01) also resyncs. + std::vector<uint8_t> garbage_with_footer = {0x10, 0x20, 0x30, 0x40, 0x04, 0x03, 0x02, 0x01}; + this->ld2450_.feed(garbage_with_footer); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); auto frame = make_periodic_frame(); @@ -68,112 +88,56 @@ TEST_F(LD2450ReadlineTest, GarbageThenValidFrame) { EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -// --- Header synchronization tests --- +// --- Overflow recovery tests --- -TEST_F(LD2450ReadlineTest, PartialDataHeaderThenMismatch) { - // Start of a data frame header, then invalid byte - this->ld2450_.feed({0xAA, 0xFF, 0x42}); // 0x42 doesn't match DATA_FRAME_HEADER[2] (0x03) - // Parser should have reset - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, PartialCmdHeaderThenMismatch) { - // Start of a command frame header, then invalid byte - this->ld2450_.feed({0xFD, 0xFC, 0xFB, 0x42}); // 0x42 doesn't match CMD_FRAME_HEADER[3] (0xFA) - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, PartialHeaderThenValidFrame) { - // Partial header that fails, then a complete valid frame - this->ld2450_.feed({0xAA, 0xFF, 0x42}); // Fails at byte 3 - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, HeaderMismatchRecoveryOnNewHeaderByte) { - // Start data header, mismatch at byte 2, but mismatch byte is start of command header - this->ld2450_.feed({0xAA, 0xFF}); - EXPECT_EQ(this->ld2450_.buffer_pos_, 2); // Accumulating header - - this->ld2450_.feed({0xFD}); // Doesn't match DATA_FRAME_HEADER[2]=0x03, but IS CMD_FRAME_HEADER[0] - // Parser should reset and start new frame with 0xFD - EXPECT_EQ(this->ld2450_.buffer_pos_, 1); - EXPECT_EQ(this->ld2450_.buffer_data_[0], 0xFD); -} - -// --- Mid-frame / overflow recovery tests --- - -TEST_F(LD2450ReadlineTest, MidFrameDataRecovery) { - // Simulate starting mid-frame: feed the tail end of a periodic frame (no valid header) - // These bytes would be part of target data in a real frame - std::vector<uint8_t> mid_frame = {0x10, 0x20, 0x30, 0x40, 0x55, 0xCC}; - this->ld2450_.feed(mid_frame); - // All discarded (none match header start bytes) - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - // Now feed a valid frame - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); -} - -TEST_F(LD2450ReadlineTest, OverflowRecovery) { - // Feed a valid data frame header followed by enough filler to cause overflow. - // Header (4) + 36 filler = 40 bytes in buffer. The 41st byte triggers overflow. - std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; // Valid header - for (int i = 0; i < 37; i++) { - overflow_data.push_back(0x11); // Filler that won't match any footer - } - // 41 bytes total: 40 stored, 41st triggers overflow and resets buffer_pos_ to 0 +TEST_F(LD2450ReadlineTest, OverflowResetsBuffer) { + // Fill the buffer to capacity with filler that won't match any footer. + // MAX_LINE_LENGTH is 45, usable is 44. The 45th byte triggers overflow. + std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11); + this->ld2450_.feed(overflow_data); + // After overflow, buffer_pos_ resets to 0 (via the < 4 early return path) + EXPECT_LT(this->ld2450_.buffer_pos_, 4); +} + +TEST_F(LD2450ReadlineTest, OverflowThenValidFrame) { + // Overflow, then a valid frame should be processed. + std::vector<uint8_t> overflow_data(MAX_LINE_LENGTH, 0x11); this->ld2450_.feed(overflow_data); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - // Feed a valid frame and verify recovery auto frame = make_periodic_frame(); this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -TEST_F(LD2450ReadlineTest, RepeatedOverflowDoesNotLoop) { - // Simulate the bug scenario: repeated overflows should not prevent recovery. - // Feed 3 rounds of overflow-inducing data. - for (int round = 0; round < 3; round++) { - std::vector<uint8_t> overflow_data = {0xAA, 0xFF, 0x03, 0x00}; - for (int i = 0; i < 37; i++) { - overflow_data.push_back(0x22); - } - this->ld2450_.feed(overflow_data); - EXPECT_EQ(this->ld2450_.buffer_pos_, 0) << "Overflow round " << round; - } - - // Parser should still recover and process a valid frame +TEST_F(LD2450ReadlineTest, BufferLargeEnoughForDesyncedFooter) { + // The key fix: the buffer (45) is large enough that a desynced periodic frame's + // footer (at most 30 bytes into the stream) will land inside the buffer before overflow. + // Simulate starting 10 bytes into a periodic frame, then a full frame follows. + std::vector<uint8_t> mid_frame = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; + // Then a complete periodic frame whose footer will land at position 40 (10 + 30), + // well within the buffer size of 45. auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); + mid_frame.insert(mid_frame.end(), frame.begin(), frame.end()); + + this->ld2450_.feed(mid_frame); + // The footer from the frame should have triggered a reset EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } -TEST_F(LD2450ReadlineTest, SimulatedRestartGarbageThenFrames) { - // Simulate LD2450 restart: burst of garbage bytes (partial frames, noise) - // followed by normal periodic data. - // Partial periodic frame (as if we started reading mid-frame), a stale footer, and more garbage +TEST_F(LD2450ReadlineTest, SimulatedRestartThenFrames) { + // Simulate LD2450 restart: burst of garbage followed by valid periodic frames. + // The garbage + first frame should fit in the buffer so the footer resyncs. std::vector<uint8_t> restart_noise = { - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, // mid-frame data - 0x55, 0xCC, // stale footer bytes - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, // more garbage + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 8 bytes of mid-frame data }; + auto frame = make_periodic_frame(); + // 8 garbage + 30 frame = 38 bytes, well within buffer of 45 + restart_noise.insert(restart_noise.end(), frame.begin(), frame.end()); this->ld2450_.feed(restart_noise); - // All garbage should be discarded - EXPECT_EQ(this->ld2450_.buffer_pos_, 0); - - // Now the LD2450 starts sending valid frames - auto frame = make_periodic_frame(); - this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); + // Subsequent frames should work normally this->ld2450_.feed(frame); EXPECT_EQ(this->ld2450_.buffer_pos_, 0); } From 8aaf0b8d8546471d5733b7e565a29f2be2d4582e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:17:12 -0500 Subject: [PATCH 0828/2030] Bump version to 2026.2.1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 38135f9106..d41a79b0dc 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.0 +PROJECT_NUMBER = 2026.2.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 9115055e7b..b3c15b1e27 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.0" +__version__ = "2026.2.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From b0a35559b3aa905a46b662b5834689a45b840e33 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 10:19:01 -0600 Subject: [PATCH 0829/2030] [esp32] Bump ESP-IDF to 5.5.3.1, revert GATTS workaround (#14147) --- .clang-tidy.hash | 2 +- esphome/components/esp32/__init__.py | 25 +++++++++++++++--------- esphome/components/esp32_ble/__init__.py | 15 ++++++-------- platformio.ini | 4 ++-- 4 files changed, 25 insertions(+), 21 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index df584fa716..777c846371 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -3258307fa645ba77307e502075c02c4d710e92c48250839db3526d36a9655444 +5eb1e5852765114ad06533220d3160b6c23f5ccefc4de41828699de5dfff5ad6 diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index cdde1c4ed5..b6682100f7 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -587,16 +587,22 @@ def _format_framework_arduino_version(ver: cv.Version) -> str: return f"{ARDUINO_FRAMEWORK_PKG}@https://github.com/espressif/arduino-esp32/releases/download/{ver}/{filename}" -def _format_framework_espidf_version(ver: cv.Version, release: str) -> str: +def _format_framework_espidf_version( + ver: cv.Version, release: str | None = None +) -> str: # format the given espidf (https://github.com/pioarduino/esp-idf/releases) version to # a PIO platformio/framework-espidf value if ver == cv.Version(5, 4, 3) or ver >= cv.Version(5, 5, 1): ext = "tar.xz" else: ext = "zip" + # Build version string with dot-separated extra (e.g., "5.5.3.1" not "5.5.3-1") + ver_str = f"{ver.major}.{ver.minor}.{ver.patch}" + if ver.extra: + ver_str += f".{ver.extra}" if release: - return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{str(ver)}.{release}/esp-idf-v{str(ver)}.{ext}" - return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{str(ver)}/esp-idf-v{str(ver)}.{ext}" + return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{ver_str}.{release}/esp-idf-v{ver_str}.{ext}" + return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{ver_str}/esp-idf-v{ver_str}.{ext}" def _is_framework_url(source: str) -> bool: @@ -643,7 +649,7 @@ ARDUINO_PLATFORM_VERSION_LOOKUP = { # These versions correspond to pioarduino/esp-idf releases # See: https://github.com/pioarduino/esp-idf/releases ARDUINO_IDF_VERSION_LOOKUP = { - cv.Version(3, 3, 7): cv.Version(5, 5, 3), + cv.Version(3, 3, 7): cv.Version(5, 5, 3, "1"), cv.Version(3, 3, 6): cv.Version(5, 5, 2), cv.Version(3, 3, 5): cv.Version(5, 5, 2), cv.Version(3, 3, 4): cv.Version(5, 5, 1), @@ -662,11 +668,12 @@ ARDUINO_IDF_VERSION_LOOKUP = { # The default/recommended esp-idf framework version # - https://github.com/espressif/esp-idf/releases ESP_IDF_FRAMEWORK_VERSION_LOOKUP = { - "recommended": cv.Version(5, 5, 3), - "latest": cv.Version(5, 5, 3), - "dev": cv.Version(5, 5, 3), + "recommended": cv.Version(5, 5, 3, "1"), + "latest": cv.Version(5, 5, 3, "1"), + "dev": cv.Version(5, 5, 3, "1"), } ESP_IDF_PLATFORM_VERSION_LOOKUP = { + cv.Version(5, 5, 3, "1"): cv.Version(55, 3, 37), cv.Version(5, 5, 3): cv.Version(55, 3, 37), cv.Version(5, 5, 2): cv.Version(55, 3, 37), cv.Version(5, 5, 1): cv.Version(55, 3, 31, "2"), @@ -730,7 +737,7 @@ def _check_versions(config): platform_lookup = ESP_IDF_PLATFORM_VERSION_LOOKUP.get(version) value[CONF_SOURCE] = value.get( CONF_SOURCE, - _format_framework_espidf_version(version, value.get(CONF_RELEASE, None)), + _format_framework_espidf_version(version, value.get(CONF_RELEASE)), ) if _is_framework_url(value[CONF_SOURCE]): value[CONF_SOURCE] = f"pioarduino/framework-espidf@{value[CONF_SOURCE]}" @@ -1428,7 +1435,7 @@ async def to_code(config): if (idf_ver := ARDUINO_IDF_VERSION_LOOKUP.get(framework_ver)) is not None: cg.add_platformio_option( "platform_packages", - [_format_framework_espidf_version(idf_ver, None)], + [_format_framework_espidf_version(idf_ver)], ) # Use stub package to skip downloading precompiled libs stubs_dir = CORE.relative_build_path("arduino_libs_stub") diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 80fcf051b9..c0e2f78bde 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -418,16 +418,13 @@ def final_validation(config): "esp32_ble_tracker" in full_config or "esp32_ble_client" in full_config ) - # Always enable GATTS: ESP-IDF 5.5.2.260206 has a bug in gatt_main.c where a - # GATT_TRACE_DEBUG references 'msg_len' outside the GATTS_INCLUDED/GATTC_INCLUDED - # guard, causing a compile error when both are disabled. - # Additionally, when GATT Client is enabled, GATT Server must also be enabled - # as an internal dependency in the Bluedroid stack. + # Check if BLE Server is needed + has_ble_server = "esp32_ble_server" in full_config + + # ESP-IDF BLE stack requires GATT Server to be enabled when GATT Client is enabled + # This is an internal dependency in the Bluedroid stack # See: https://github.com/espressif/esp-idf/issues/17724 - # TODO: Revert to conditional once the gatt_main.c bug is fixed upstream: - # has_ble_server = "esp32_ble_server" in full_config - # add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server or has_ble_client) - add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", True) + add_idf_sdkconfig_option("CONFIG_BT_GATTS_ENABLE", has_ble_server or has_ble_client) add_idf_sdkconfig_option("CONFIG_BT_GATTC_ENABLE", has_ble_client) # Handle max_connections: check for deprecated location in esp32_ble_tracker diff --git a/platformio.ini b/platformio.ini index fdd6a36428..e35dce2228 100644 --- a/platformio.ini +++ b/platformio.ini @@ -136,7 +136,7 @@ extends = common:arduino platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = pioarduino/framework-arduinoespressif32@https://github.com/espressif/arduino-esp32/releases/download/3.3.7/esp32-core-3.3.7.tar.xz - pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3/esp-idf-v5.5.3.tar.xz + pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3.1/esp-idf-v5.5.3.1.tar.xz framework = arduino, espidf ; Arduino as an ESP-IDF component lib_deps = @@ -171,7 +171,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:idf platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip platform_packages = - pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3/esp-idf-v5.5.3.tar.xz + pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v5.5.3.1/esp-idf-v5.5.3.1.tar.xz framework = espidf lib_deps = From 9ce01fc369c5451e1f980e49cea08e51b6a0cc53 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:20:05 -0500 Subject: [PATCH 0830/2030] [esp32] Add engineering_sample option for ESP32-P4 (#14139) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 43 +++++++++++++++++-- esphome/components/esp32/boards.py | 5 ++- script/generate-esp32-boards.py | 15 ++++++- tests/components/esp32/test.esp32-p4-idf.yaml | 1 + 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b6682100f7..06677006ea 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -87,6 +87,7 @@ IS_TARGET_PLATFORM = True CONF_ASSERTION_LEVEL = "assertion_level" CONF_COMPILER_OPTIMIZATION = "compiler_optimization" CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features" +CONF_ENGINEERING_SAMPLE = "engineering_sample" CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components" CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" @@ -785,6 +786,15 @@ def _detect_variant(value): # variant has already been validated against the known set value = value.copy() value[CONF_BOARD] = STANDARD_BOARDS[variant] + if variant == VARIANT_ESP32P4: + engineering_sample = value.get(CONF_ENGINEERING_SAMPLE) + if engineering_sample is None: + _LOGGER.warning( + "No board specified for ESP32-P4. Defaulting to production silicon (rev3). " + "If you have an early engineering sample (pre-rev3), set 'engineering_sample: true'." + ) + elif engineering_sample: + value[CONF_BOARD] = "esp32-p4-evboard" elif board in BOARDS: variant = variant or BOARDS[board][KEY_VARIANT] if variant != BOARDS[board][KEY_VARIANT]: @@ -848,6 +858,30 @@ def final_validate(config): path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_MINIMUM_CHIP_REVISION], ) ) + if ( + config[CONF_VARIANT] != VARIANT_ESP32P4 + and config.get(CONF_ENGINEERING_SAMPLE) is not None + ): + errs.append( + cv.Invalid( + f"'{CONF_ENGINEERING_SAMPLE}' is only supported on {VARIANT_ESP32P4}", + path=[CONF_ENGINEERING_SAMPLE], + ) + ) + if ( + config[CONF_VARIANT] == VARIANT_ESP32P4 + and config.get(CONF_ENGINEERING_SAMPLE) is not None + ): + board_is_es = BOARDS.get(config[CONF_BOARD], {}).get( + "engineering_sample", False + ) + if config[CONF_ENGINEERING_SAMPLE] != board_is_es: + errs.append( + cv.Invalid( + f"'{CONF_ENGINEERING_SAMPLE}' does not match board '{config[CONF_BOARD]}'", + path=[CONF_ENGINEERING_SAMPLE], + ) + ) if advanced[CONF_EXECUTE_FROM_PSRAM]: if config[CONF_VARIANT] != VARIANT_ESP32S3: errs.append( @@ -1197,6 +1231,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_CPU_FREQUENCY): cv.one_of( *FULL_CPU_FREQUENCIES, upper=True ), + cv.Optional(CONF_ENGINEERING_SAMPLE): cv.boolean, cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of( *FLASH_SIZES, upper=True ), @@ -1482,10 +1517,12 @@ async def to_code(config): # ESP32-P4: ESP-IDF 5.5.3 changed the default of ESP32P4_SELECTS_REV_LESS_V3 # from y to n. PlatformIO uses sections.ld.in (for rev <3) or # sections.rev3.ld.in (for rev >=3) based on board definition. - # Set the sdkconfig option to match the board's revision. + # Set the sdkconfig option to match the board's chip revision. if variant == VARIANT_ESP32P4: - is_rev3 = "_r3" in config[CONF_BOARD] - add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", not is_rev3) + is_eng_sample = BOARDS.get(config[CONF_BOARD], {}).get( + "engineering_sample", False + ) + add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", is_eng_sample) # Set minimum chip revision for ESP32 variant # Setting this to 3.0 or higher reduces flash size by excluding workaround code, diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 66367d63ae..2bd08e7c39 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -20,7 +20,7 @@ STANDARD_BOARDS = { VARIANT_ESP32C6: "esp32-c6-devkitm-1", VARIANT_ESP32C61: "esp32-c61-devkitc1-n8r2", VARIANT_ESP32H2: "esp32-h2-devkitm-1", - VARIANT_ESP32P4: "esp32-p4-evboard", + VARIANT_ESP32P4: "esp32-p4_r3-evboard", VARIANT_ESP32S2: "esp32-s2-kaluga-1", VARIANT_ESP32S3: "esp32-s3-devkitc-1", } @@ -1713,10 +1713,12 @@ BOARDS = { "esp32-p4": { "name": "Espressif ESP32-P4 ES (pre rev.300) generic", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "esp32-p4-evboard": { "name": "Espressif ESP32-P4 Function EV Board (ES pre rev.300)", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "esp32-p4_r3": { "name": "Espressif ESP32-P4 rev.300 generic", @@ -2141,6 +2143,7 @@ BOARDS = { "m5stack-tab5-p4": { "name": "M5STACK Tab5 esp32-p4 Board (ES pre rev.300)", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "m5stack-timer-cam": { "name": "M5Stack Timer CAM", diff --git a/script/generate-esp32-boards.py b/script/generate-esp32-boards.py index 81b78b04be..ab4a38ced5 100755 --- a/script/generate-esp32-boards.py +++ b/script/generate-esp32-boards.py @@ -43,10 +43,14 @@ def get_boards(): name = board_info["name"] board = fname.stem variant = mcu.upper() - boards[board] = { + chip_variant = board_info["build"].get("chip_variant", "") + entry = { "name": name, "variant": f"VARIANT_{variant}", } + if chip_variant.endswith("_es"): + entry["engineering_sample"] = True + boards[board] = entry return boards @@ -55,6 +59,12 @@ TEMPLATE = """ "%s": { "variant": %s, },""" +TEMPLATE_ES = """ "%s": { + "name": "%s", + "variant": %s, + "engineering_sample": True, + },""" + def main(check: bool): boards = get_boards() @@ -66,7 +76,8 @@ def main(check: bool): if line == "BOARDS = {": parts.append(line) parts.extend( - TEMPLATE % (board, info["name"], info["variant"]) + (TEMPLATE_ES if info.get("engineering_sample") else TEMPLATE) + % (board, info["name"], info["variant"]) for board, info in sorted(boards.items()) ) parts.append("}") diff --git a/tests/components/esp32/test.esp32-p4-idf.yaml b/tests/components/esp32/test.esp32-p4-idf.yaml index bc054f5aee..fd42fac5a3 100644 --- a/tests/components/esp32/test.esp32-p4-idf.yaml +++ b/tests/components/esp32/test.esp32-p4-idf.yaml @@ -1,5 +1,6 @@ esp32: variant: esp32p4 + engineering_sample: true flash_size: 32MB cpu_frequency: 400MHz framework: From 403235e2d4ec6a27ac4ad35f79b7dc2afb413611 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 11:20:29 -0500 Subject: [PATCH 0831/2030] [wifi] Add band_mode configuration for ESP32-C5 dual-band WiFi (#14148) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/wifi/__init__.py | 22 ++++++++++++++++++- esphome/components/wifi/wifi_component.cpp | 16 ++++++++++++++ esphome/components/wifi/wifi_component.h | 13 +++++++++++ .../wifi/wifi_component_esp_idf.cpp | 7 ++++++ tests/components/wifi/test.esp32-c5-idf.yaml | 5 +++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/components/wifi/test.esp32-c5-idf.yaml diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index afceec6c54..540d0a0ab1 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -5,7 +5,12 @@ from esphome import automation from esphome.automation import Condition import esphome.codegen as cg from esphome.components.const import CONF_USE_PSRAM -from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant +from esphome.components.esp32 import ( + add_idf_sdkconfig_option, + const, + get_esp32_variant, + only_on_variant, +) from esphome.components.network import ( has_high_performance_networking, ip_address_literal, @@ -64,6 +69,7 @@ _LOGGER = logging.getLogger(__name__) NO_WIFI_VARIANTS = [const.VARIANT_ESP32H2, const.VARIANT_ESP32P4] CONF_SAVE = "save" +CONF_BAND_MODE = "band_mode" CONF_MIN_AUTH_MODE = "min_auth_mode" CONF_POST_CONNECT_ROAMING = "post_connect_roaming" @@ -90,6 +96,13 @@ WIFI_POWER_SAVE_MODES = { "HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, } +WiFiBandMode = cg.global_ns.enum("wifi_band_mode_t") +WIFI_BAND_MODES = { + "AUTO": WiFiBandMode.WIFI_BAND_MODE_AUTO, + "2.4GHZ": WiFiBandMode.WIFI_BAND_MODE_2G_ONLY, + "5GHZ": WiFiBandMode.WIFI_BAND_MODE_5G_ONLY, +} + WifiMinAuthMode = wifi_ns.enum("WifiMinAuthMode") WIFI_MIN_AUTH_MODES = { "WPA": WifiMinAuthMode.WIFI_MIN_AUTH_MODE_WPA, @@ -353,6 +366,11 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_ENABLE_RRM, esp32=False): cv.All( cv.boolean, cv.only_on_esp32 ), + cv.Optional(CONF_BAND_MODE): cv.All( + cv.enum(WIFI_BAND_MODES, upper=True), + cv.only_on_esp32, + only_on_variant(supported=[const.VARIANT_ESP32C5]), + ), cv.Optional(CONF_PASSIVE_SCAN, default=False): cv.boolean, cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, cv.Optional(CONF_POST_CONNECT_ROAMING, default=True): cv.boolean, @@ -527,6 +545,8 @@ async def to_code(config): cg.add(var.set_btm(config[CONF_ENABLE_BTM])) if config[CONF_ENABLE_RRM]: cg.add(var.set_rrm(config[CONF_ENABLE_RRM])) + if CONF_BAND_MODE in config: + cg.add(var.set_band_mode(config[CONF_BAND_MODE])) if config.get(CONF_USE_PSRAM): add_idf_sdkconfig_option("CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP", True) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index a2efac8d26..8b3060c7c3 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1469,6 +1469,22 @@ void WiFiComponent::dump_config() { ESP_LOGCONFIG(TAG, " Disabled"); return; } +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + const char *band_mode_s; + switch (this->band_mode_) { + case WIFI_BAND_MODE_2G_ONLY: + band_mode_s = "2.4GHz"; + break; + case WIFI_BAND_MODE_5G_ONLY: + band_mode_s = "5GHz"; + break; + case WIFI_BAND_MODE_AUTO: + default: + band_mode_s = "Auto"; + break; + } + ESP_LOGCONFIG(TAG, " Band Mode: %s", band_mode_s); +#endif if (this->is_connected()) { this->print_connect_params_(); } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 4a038f602c..5f903e092a 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -45,6 +45,10 @@ extern "C" { #include <WiFi.h> #endif +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) +#include <esp_wifi_types.h> +#endif + #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) #include <freertos/FreeRTOS.h> #include <freertos/semphr.h> @@ -435,6 +439,9 @@ class WiFiComponent : public Component { void set_power_save_mode(WiFiPowerSaveMode power_save); void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; } void set_output_power(float output_power) { output_power_ = output_power; } +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + void set_band_mode(wifi_band_mode_t band_mode) { this->band_mode_ = band_mode; } +#endif void set_passive_scan(bool passive); @@ -652,6 +659,9 @@ class WiFiComponent : public Component { bool wifi_sta_pre_setup_(); bool wifi_apply_output_power_(float output_power); bool wifi_apply_power_save_(); +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + bool wifi_apply_band_mode_(); +#endif bool wifi_sta_ip_config_(const optional<ManualIP> &manual_ip); bool wifi_apply_hostname_(); bool wifi_sta_connect_(const WiFiAP &ap); @@ -774,6 +784,9 @@ class WiFiComponent : public Component { // 1-byte enums and integers WiFiComponentState state_{WIFI_COMPONENT_STATE_OFF}; WiFiPowerSaveMode power_save_{WIFI_POWER_SAVE_NONE}; +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + wifi_band_mode_t band_mode_{WIFI_BAND_MODE_AUTO}; +#endif WifiMinAuthMode min_auth_mode_{WIFI_MIN_AUTH_MODE_WPA2}; WiFiRetryPhase retry_phase_{WiFiRetryPhase::INITIAL_CONNECT}; uint8_t num_retried_{0}; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 52ee482121..57bbceb1b8 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -292,6 +292,10 @@ bool WiFiComponent::wifi_apply_power_save_() { return success; } +#ifdef SOC_WIFI_SUPPORT_5G +bool WiFiComponent::wifi_apply_band_mode_() { return esp_wifi_set_band_mode(this->band_mode_) == ESP_OK; } +#endif + bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // enable STA if (!this->wifi_mode_(true, {})) @@ -726,6 +730,9 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { s_sta_started = true; // re-apply power save mode wifi_apply_power_save_(); +#ifdef SOC_WIFI_SUPPORT_5G + wifi_apply_band_mode_(); +#endif } else if (data->event_base == WIFI_EVENT && data->event_id == WIFI_EVENT_STA_STOP) { ESP_LOGV(TAG, "STA stop"); diff --git a/tests/components/wifi/test.esp32-c5-idf.yaml b/tests/components/wifi/test.esp32-c5-idf.yaml new file mode 100644 index 0000000000..92a52db09e --- /dev/null +++ b/tests/components/wifi/test.esp32-c5-idf.yaml @@ -0,0 +1,5 @@ +wifi: + band_mode: 5GHZ + +packages: + - !include common.yaml From 9c0eed8a67a392868d2a8e6c8a220314271c847e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 12:03:39 -0500 Subject: [PATCH 0832/2030] [e131] Remove dead LWIP TCP code path from loop() (#14155) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/e131/e131.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/esphome/components/e131/e131.cpp b/esphome/components/e131/e131.cpp index d04ab8a58d..a7a695c167 100644 --- a/esphome/components/e131/e131.cpp +++ b/esphome/components/e131/e131.cpp @@ -85,22 +85,6 @@ void E131Component::loop() { ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); } } -#elif defined(USE_SOCKET_IMPL_LWIP_TCP) - while (auto packet_size = this->udp_.parsePacket()) { - auto len = this->udp_.read(buf, sizeof(buf)); - if (len <= 0) - continue; - - if (!this->packet_(buf, (size_t) len, universe, packet)) { - ESP_LOGV(TAG, "Invalid packet received of size %d.", (int) len); - continue; - } - - if (!this->process_(universe, packet)) { - ESP_LOGV(TAG, "Ignored packet for %d universe of size %d.", universe, packet.count); - } - } -#endif } void E131Component::add_effect(E131AddressableLightEffect *light_effect) { From b85a49cdb3c65c24ffdb725a56dc9f48c2fd7f3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 13:27:15 -0600 Subject: [PATCH 0833/2030] Bump github/codeql-action from 4.32.3 to 4.32.4 (#14161) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 376825bad6..5d7c32eaa9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@9e907b5e64f6b83e7804b09294d44122997950d6 # v4.32.3 + uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 with: category: "/language:${{matrix.language}}" From 1a376328911b184cbc5b7251688607f7ff62384a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:27:45 +0000 Subject: [PATCH 0834/2030] Bump pylint from 4.0.4 to 4.0.5 (#14160) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 9e99855f6f..611e552829 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,4 +1,4 @@ -pylint==4.0.4 +pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating ruff==0.15.1 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating From edfc3e3501ec3b0652a7a341d5542f70c488b79c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:32:41 +0000 Subject: [PATCH 0835/2030] Bump ruff from 0.15.1 to 0.15.2 (#14159) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d89060b0d..07d02e0e3c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.1 + rev: v0.15.2 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 611e552829..3e5dc8a90c 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.1 # also change in .pre-commit-config.yaml when updating +ruff==0.15.2 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From 48115eca18b8c9937595a0fe26ce50fde4ebb15f Mon Sep 17 00:00:00 2001 From: Pawelo <81100874+pgolawsk@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:08:31 +0100 Subject: [PATCH 0836/2030] [safe_mode] Extract RTC_KEY constant for shared use (#14121) Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/safe_mode/safe_mode.cpp | 2 +- esphome/components/safe_mode/safe_mode.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index 6cae4bf9d5..bd80048c64 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -104,7 +104,7 @@ bool SafeModeComponent::should_enter_safe_mode(uint8_t num_attempts, uint32_t en this->safe_mode_enable_time_ = enable_time; this->safe_mode_boot_is_good_after_ = boot_is_good_after; this->safe_mode_num_attempts_ = num_attempts; - this->rtc_ = global_preferences->make_preference<uint32_t>(233825507UL, false); + this->rtc_ = global_preferences->make_preference<uint32_t>(RTC_KEY, false); #if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) // Check partition state to detect if bootloader supports rollback diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index d6f669f39f..a4d27c15da 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -11,6 +11,9 @@ namespace esphome::safe_mode { +/// RTC key for storing boot loop counter - used by safe_mode and preferences backends +constexpr uint32_t RTC_KEY = 233825507UL; + /// SafeModeComponent provides a safe way to recover from repeated boot failures class SafeModeComponent : public Component { public: From db6aa58f40b4c6be322f8c26312605bb2fca8dd6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:06:46 -0500 Subject: [PATCH 0837/2030] [max7219digit] Fix typo in action names (#14162) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/max7219digit/display.py | 22 +++++++++++----------- tests/components/max7219digit/common.yaml | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index e6d53efc5d..a251eaccea 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -133,12 +133,12 @@ MAX7219_ON_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "max7129digit.invert_off", DisplayInvertAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.invert_off", DisplayInvertAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.invert_on", DisplayInvertAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.invert_on", DisplayInvertAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_invert_to_code(config, action_id, template_arg, args): +async def max7219digit_invert_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -146,12 +146,12 @@ async def max7129digit_invert_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7129digit.turn_off", DisplayVisibilityAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.turn_off", DisplayVisibilityAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.turn_on", DisplayVisibilityAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.turn_on", DisplayVisibilityAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_visible_to_code(config, action_id, template_arg, args): +async def max7219digit_visible_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -159,12 +159,12 @@ async def max7129digit_visible_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7129digit.reverse_off", DisplayReverseAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.reverse_off", DisplayReverseAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.reverse_on", DisplayReverseAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.reverse_on", DisplayReverseAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_reverse_to_code(config, action_id, template_arg, args): +async def max7219digit_reverse_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -183,9 +183,9 @@ MAX7219_INTENSITY_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "max7129digit.intensity", DisplayIntensityAction, MAX7219_INTENSITY_SCHEMA + "max7219digit.intensity", DisplayIntensityAction, MAX7219_INTENSITY_SCHEMA ) -async def max7129digit_intensity_to_code(config, action_id, template_arg, args): +async def max7219digit_intensity_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) template_ = await cg.templatable(config[CONF_INTENSITY], args, cg.uint8) diff --git a/tests/components/max7219digit/common.yaml b/tests/components/max7219digit/common.yaml index 525b7b8d3e..4d2dbb781d 100644 --- a/tests/components/max7219digit/common.yaml +++ b/tests/components/max7219digit/common.yaml @@ -13,10 +13,10 @@ esphome: on_boot: - priority: 100 then: - - max7129digit.invert_off: - - max7129digit.invert_on: - - max7129digit.turn_on: - - max7129digit.turn_off: - - max7129digit.reverse_on: - - max7129digit.reverse_off: - - max7129digit.intensity: 10 + - max7219digit.invert_off: + - max7219digit.invert_on: + - max7219digit.turn_on: + - max7219digit.turn_off: + - max7219digit.reverse_on: + - max7219digit.reverse_off: + - max7219digit.intensity: 10 From 1d3054ef5e463f1b018e297ffe547c7e621ddfd4 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Fri, 20 Feb 2026 23:12:50 +0100 Subject: [PATCH 0838/2030] [nrf52,logger] Early debug (#11685) --- esphome/components/debug/debug_zephyr.cpp | 45 +-------- esphome/components/logger/__init__.py | 24 +++++ esphome/components/logger/logger.cpp | 3 + esphome/components/logger/logger.h | 1 + esphome/components/logger/logger_zephyr.cpp | 97 +++++++++++++++++++ esphome/components/nrf52/__init__.py | 1 + esphome/components/zephyr/gpio.h | 6 +- esphome/components/zephyr/preferences.h | 6 +- esphome/components/zephyr/reset_reason.cpp | 63 ++++++++++++ esphome/components/zephyr/reset_reason.h | 18 ++++ esphome/config_validation.py | 2 + esphome/core/defines.h | 2 + .../logger/test.nrf52-adafruit.yaml | 2 + 13 files changed, 219 insertions(+), 51 deletions(-) create mode 100644 esphome/components/zephyr/reset_reason.cpp create mode 100644 esphome/components/zephyr/reset_reason.h diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index 0291cc3061..ecca7150bd 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -2,6 +2,7 @@ #ifdef USE_ZEPHYR #include <climits> #include "esphome/core/log.h" +#include <esphome/components/zephyr/reset_reason.h> #include <zephyr/drivers/hwinfo.h> #include <hal/nrf_power.h> #include <cstdint> @@ -15,16 +16,6 @@ static const char *const TAG = "debug"; constexpr std::uintptr_t MBR_PARAM_PAGE_ADDR = 0xFFC; constexpr std::uintptr_t MBR_BOOTLOADER_ADDR = 0xFF8; -static size_t append_reset_reason(char *buf, size_t size, size_t pos, bool set, const char *reason) { - if (!set) { - return pos; - } - if (pos > 0) { - pos = buf_append_printf(buf, size, pos, ", "); - } - return buf_append_printf(buf, size, pos, "%s", reason); -} - static inline uint32_t read_mem_u32(uintptr_t addr) { return *reinterpret_cast<volatile uint32_t *>(addr); // NOLINT(performance-no-int-to-ptr) } @@ -57,39 +48,7 @@ static inline uint32_t sd_version_get() { } const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { - char *buf = buffer.data(); - const size_t size = RESET_REASON_BUFFER_SIZE; - - uint32_t cause; - auto ret = hwinfo_get_reset_cause(&cause); - if (ret) { - ESP_LOGE(TAG, "Unable to get reset cause: %d", ret); - buf[0] = '\0'; - return buf; - } - size_t pos = 0; - - pos = append_reset_reason(buf, size, pos, cause & RESET_PIN, "External pin"); - pos = append_reset_reason(buf, size, pos, cause & RESET_SOFTWARE, "Software reset"); - pos = append_reset_reason(buf, size, pos, cause & RESET_BROWNOUT, "Brownout (drop in voltage)"); - pos = append_reset_reason(buf, size, pos, cause & RESET_POR, "Power-on reset (POR)"); - pos = append_reset_reason(buf, size, pos, cause & RESET_WATCHDOG, "Watchdog timer expiration"); - pos = append_reset_reason(buf, size, pos, cause & RESET_DEBUG, "Debug event"); - pos = append_reset_reason(buf, size, pos, cause & RESET_SECURITY, "Security violation"); - pos = append_reset_reason(buf, size, pos, cause & RESET_LOW_POWER_WAKE, "Waking up from low power mode"); - pos = append_reset_reason(buf, size, pos, cause & RESET_CPU_LOCKUP, "CPU lock-up detected"); - pos = append_reset_reason(buf, size, pos, cause & RESET_PARITY, "Parity error"); - pos = append_reset_reason(buf, size, pos, cause & RESET_PLL, "PLL error"); - pos = append_reset_reason(buf, size, pos, cause & RESET_CLOCK, "Clock error"); - pos = append_reset_reason(buf, size, pos, cause & RESET_HARDWARE, "Hardware reset"); - pos = append_reset_reason(buf, size, pos, cause & RESET_USER, "User reset"); - pos = append_reset_reason(buf, size, pos, cause & RESET_TEMPERATURE, "Temperature reset"); - - // Ensure null termination if nothing was written - if (pos == 0) { - buf[0] = '\0'; - } - + const char *buf = zephyr::get_reset_reason(buffer); ESP_LOGD(TAG, "Reset Reason: %s", buf); return buf; } diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index b2952d7995..c8f3c52911 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -101,6 +101,8 @@ CONF_INITIAL_LEVEL = "initial_level" CONF_LOGGER_ID = "logger_id" CONF_RUNTIME_TAG_LEVELS = "runtime_tag_levels" CONF_TASK_LOG_BUFFER_SIZE = "task_log_buffer_size" +CONF_WAIT_FOR_CDC = "wait_for_cdc" +CONF_EARLY_MESSAGE = "early_message" UART_SELECTION_ESP32 = { VARIANT_ESP32: [UART0, UART1, UART2], @@ -208,6 +210,12 @@ def validate_initial_no_higher_than_global(config): return config +def validate_wait_for_cdc(config): + if config.get(CONF_WAIT_FOR_CDC) and config.get(CONF_HARDWARE_UART) != USB_CDC: + raise cv.Invalid("wait_for_cdc requires hardware_uart: USB_CDC") + return config + + Logger = logger_ns.class_("Logger", cg.Component) LoggerMessageTrigger = logger_ns.class_( "LoggerMessageTrigger", @@ -300,10 +308,18 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault( CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH, esp8266=True ): cv.All(cv.only_on_esp8266, cv.boolean), + cv.SplitDefault(CONF_WAIT_FOR_CDC, nrf52=False): cv.All( + cv.only_on(PLATFORM_NRF52), + cv.boolean, + ), + cv.SplitDefault(CONF_EARLY_MESSAGE, nrf52=False): cv.All( + cv.only_on(PLATFORM_NRF52), cv.boolean + ), } ).extend(cv.COMPONENT_SCHEMA), validate_local_no_higher_than_global, validate_initial_no_higher_than_global, + validate_wait_for_cdc, ) @@ -425,13 +441,21 @@ async def to_code(config): except cv.Invalid: pass + if config.get(CONF_WAIT_FOR_CDC): + cg.add_define("USE_LOGGER_WAIT_FOR_CDC") + if config.get(CONF_EARLY_MESSAGE): + cg.add_define("USE_LOGGER_EARLY_MESSAGE") + if CORE.is_nrf52: + # esphome implement own fatal error handler which save PC/LR before reset + zephyr_add_prj_conf("RESET_ON_FATAL_ERROR", False) zephyr_add_prj_conf("THREAD_LOCAL_STORAGE", True) if config[CONF_HARDWARE_UART] == UART0: zephyr_add_overlay("""&uart0 { status = "okay";};""") if config[CONF_HARDWARE_UART] == UART1: zephyr_add_overlay("""&uart1 { status = "okay";};""") if config[CONF_HARDWARE_UART] == USB_CDC: + cg.add_define("USE_LOGGER_UART_SELECTION_USB_CDC") zephyr_add_prj_conf("UART_LINE_CTRL", True) zephyr_add_cdc_acm(config, 0) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index e1b49bcb61..87963c5fc5 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -261,6 +261,9 @@ void Logger::dump_config() { ESP_LOGCONFIG(TAG, " Level for '%s': %s", it.first, LOG_STR_ARG(get_log_level_str(it.second))); } #endif +#ifdef USE_ZEPHYR + dump_crash_(); +#endif } void Logger::set_log_level(uint8_t level) { diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 2a7552af92..c6c379f6c6 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -317,6 +317,7 @@ class Logger : public Component { Stream *hw_serial_{nullptr}; #endif #if defined(USE_ZEPHYR) + void dump_crash_(); const device *uart_dev_{nullptr}; #endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index f565c5760c..d6193ff36b 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -8,9 +8,30 @@ #include <zephyr/drivers/uart.h> #include <zephyr/sys/printk.h> #include <zephyr/usb/usb_device.h> +#ifdef USE_LOGGER_EARLY_MESSAGE +#include <esphome/components/zephyr/reset_reason.h> +#endif + +namespace esphome::zephyr_coredump { + +__attribute__((weak)) void print_coredump() {} + +} // namespace esphome::zephyr_coredump namespace esphome::logger { +static const uint32_t CRASH_MAGIC = 0xDEADBEEF; + +__attribute__((section(".noinit"))) struct { + uint32_t magic; + uint32_t reason; + uint32_t pc; + uint32_t lr; +#if defined(CONFIG_THREAD_NAME) + char thread[CONFIG_THREAD_MAX_NAME_LEN]; +#endif +} crash_buf; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static const char *const TAG = "logger"; #ifdef USE_LOGGER_USB_CDC @@ -57,10 +78,26 @@ void Logger::pre_setup() { ESP_LOGE(TAG, "%s is not ready.", LOG_STR_ARG(get_uart_selection_())); } else { this->uart_dev_ = uart_dev; +#if defined(USE_LOGGER_WAIT_FOR_CDC) && defined(USE_LOGGER_UART_SELECTION_USB_CDC) + uint32_t dtr = 0; + uint32_t count = (10 * 100); // wait 10 sec for USB CDC to have early logs + while (dtr == 0 && count-- != 0) { + uart_line_ctrl_get(this->uart_dev_, UART_LINE_CTRL_DTR, &dtr); + delay(10); + arch_feed_wdt(); + } +#endif } } global_logger = this; ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_LOGGER_EARLY_MESSAGE + char reason_buffer[zephyr::RESET_REASON_BUFFER_SIZE]; + const char *reset_reason = zephyr::get_reset_reason(std::span<char, zephyr::RESET_REASON_BUFFER_SIZE>(reason_buffer)); + ESP_LOGI(TAG, "Reset reason: %s", reset_reason); + dump_crash_(); + zephyr_coredump::print_coredump(); +#endif } void HOT Logger::write_msg_(const char *msg, uint16_t len) { @@ -93,6 +130,66 @@ const LogString *Logger::get_uart_selection_() { } } +static const uint8_t REASON_BUF_SIZE = 32; + +static const char *reason_to_str(unsigned int reason, char *buf) { + switch (reason) { + case K_ERR_CPU_EXCEPTION: + return "CPU exception"; + case K_ERR_SPURIOUS_IRQ: + return "Unhandled interrupt"; + case K_ERR_STACK_CHK_FAIL: + return "Stack overflow"; + case K_ERR_KERNEL_OOPS: + return "Kernel oops"; + case K_ERR_KERNEL_PANIC: + return "Kernel panic"; + default: + snprintf(buf, REASON_BUF_SIZE, "Unknown error (%u)", reason); + return buf; + } +} + +void Logger::dump_crash_() { + ESP_LOGD(TAG, "Crash buffer address %p", &crash_buf); + if (crash_buf.magic == CRASH_MAGIC) { + char reason_buf[REASON_BUF_SIZE]; + ESP_LOGE(TAG, "Last crash:"); + ESP_LOGE(TAG, "Reason=%s PC=0x%08x LR=0x%08x", reason_to_str(crash_buf.reason, reason_buf), crash_buf.pc, + crash_buf.lr); +#if defined(CONFIG_THREAD_NAME) + ESP_LOGE(TAG, "Thread: %s", crash_buf.thread); +#endif + } +} + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) { + crash_buf.magic = CRASH_MAGIC; + crash_buf.reason = reason; + if (esf) { + crash_buf.pc = esf->basic.pc; + crash_buf.lr = esf->basic.lr; + } +#if defined(CONFIG_THREAD_NAME) + auto thread = k_current_get(); + const char *name = k_thread_name_get(thread); + if (name) { + strncpy(crash_buf.thread, name, sizeof(crash_buf.thread) - 1); + crash_buf.thread[sizeof(crash_buf.thread) - 1] = '\0'; + } else { + crash_buf.thread[0] = '\0'; + } +#endif + arch_restart(); +} + } // namespace esphome::logger +extern "C" { + +void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) { + esphome::logger::k_sys_fatal_error_handler(reason, esf); +} +} + #endif diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 7d3d59f0ad..95e3670124 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -266,6 +266,7 @@ async def to_code(config: ConfigType) -> None: }; """ ) + zephyr_add_prj_conf("REBOOT", True) @coroutine_with_priority(CoroPriority.DIAGNOSTICS) diff --git a/esphome/components/zephyr/gpio.h b/esphome/components/zephyr/gpio.h index 94f25f02ac..907fbe9f9c 100644 --- a/esphome/components/zephyr/gpio.h +++ b/esphome/components/zephyr/gpio.h @@ -3,8 +3,7 @@ #ifdef USE_ZEPHYR #include "esphome/core/hal.h" #include <zephyr/device.h> -namespace esphome { -namespace zephyr { +namespace esphome::zephyr { class ZephyrGPIOPin : public InternalGPIOPin { public: @@ -39,7 +38,6 @@ class ZephyrGPIOPin : public InternalGPIOPin { bool value_{false}; }; -} // namespace zephyr -} // namespace esphome +} // namespace esphome::zephyr #endif // USE_ZEPHYR diff --git a/esphome/components/zephyr/preferences.h b/esphome/components/zephyr/preferences.h index 6a37e41b46..4bee96d79e 100644 --- a/esphome/components/zephyr/preferences.h +++ b/esphome/components/zephyr/preferences.h @@ -2,12 +2,10 @@ #ifdef USE_ZEPHYR -namespace esphome { -namespace zephyr { +namespace esphome::zephyr { void setup_preferences(); -} // namespace zephyr -} // namespace esphome +} #endif diff --git a/esphome/components/zephyr/reset_reason.cpp b/esphome/components/zephyr/reset_reason.cpp new file mode 100644 index 0000000000..24b32196db --- /dev/null +++ b/esphome/components/zephyr/reset_reason.cpp @@ -0,0 +1,63 @@ +#include "reset_reason.h" + +#if defined(USE_ZEPHYR) && (defined(USE_LOGGER_EARLY_MESSAGE) || defined(USE_DEBUG)) +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include <zephyr/drivers/hwinfo.h> + +namespace esphome::zephyr { + +static const char *const TAG = "zephyr"; + +static size_t append_reset_reason(char *buf, size_t size, size_t pos, bool set, const char *reason) { + if (!set) { + return pos; + } + if (pos > 0) { + pos = buf_append_printf(buf, size, pos, ", "); + } + return buf_append_printf(buf, size, pos, "%s", reason); +} + +const char *get_reset_reason(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { + char *buf = buffer.data(); + const size_t size = RESET_REASON_BUFFER_SIZE; + + uint32_t cause; + auto ret = hwinfo_get_reset_cause(&cause); + if (ret) { + ESP_LOGE(TAG, "Unable to get reset cause: %d", ret); + buf[0] = '\0'; + return buf; + } + size_t pos = 0; + + if (cause == 0) { + pos = append_reset_reason(buf, size, pos, true, "None"); + } else { + pos = append_reset_reason(buf, size, pos, cause & RESET_PIN, "External pin"); + pos = append_reset_reason(buf, size, pos, cause & RESET_SOFTWARE, "Software reset"); + pos = append_reset_reason(buf, size, pos, cause & RESET_BROWNOUT, "Brownout (drop in voltage)"); + pos = append_reset_reason(buf, size, pos, cause & RESET_POR, "Power-on reset (POR)"); + pos = append_reset_reason(buf, size, pos, cause & RESET_WATCHDOG, "Watchdog timer expiration"); + pos = append_reset_reason(buf, size, pos, cause & RESET_DEBUG, "Debug event"); + pos = append_reset_reason(buf, size, pos, cause & RESET_SECURITY, "Security violation"); + pos = append_reset_reason(buf, size, pos, cause & RESET_LOW_POWER_WAKE, "Waking up from low power mode"); + pos = append_reset_reason(buf, size, pos, cause & RESET_CPU_LOCKUP, "CPU lock-up detected"); + pos = append_reset_reason(buf, size, pos, cause & RESET_PARITY, "Parity error"); + pos = append_reset_reason(buf, size, pos, cause & RESET_PLL, "PLL error"); + pos = append_reset_reason(buf, size, pos, cause & RESET_CLOCK, "Clock error"); + pos = append_reset_reason(buf, size, pos, cause & RESET_HARDWARE, "Hardware reset"); + pos = append_reset_reason(buf, size, pos, cause & RESET_USER, "User reset"); + pos = append_reset_reason(buf, size, pos, cause & RESET_TEMPERATURE, "Temperature reset"); + } + + // Ensure null termination if nothing was written + if (pos == 0) { + buf[0] = '\0'; + } + return buf; +} +} // namespace esphome::zephyr + +#endif diff --git a/esphome/components/zephyr/reset_reason.h b/esphome/components/zephyr/reset_reason.h new file mode 100644 index 0000000000..2c2e7b8470 --- /dev/null +++ b/esphome/components/zephyr/reset_reason.h @@ -0,0 +1,18 @@ +#pragma once + +#include "esphome/core/defines.h" + +#if defined(USE_ZEPHYR) && (defined(USE_LOGGER_EARLY_MESSAGE) || defined(USE_DEBUG)) + +#include <cstddef> +#include <span> + +namespace esphome::zephyr { + +static constexpr size_t RESET_REASON_BUFFER_SIZE = 128; + +const char *get_reset_reason(std::span<char, RESET_REASON_BUFFER_SIZE> buffer); + +} // namespace esphome::zephyr + +#endif diff --git a/esphome/config_validation.py b/esphome/config_validation.py index a9d1a72e5a..ef1c66a20e 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -70,6 +70,7 @@ from esphome.const import ( KEY_TARGET_FRAMEWORK, PLATFORM_ESP32, PLATFORM_ESP8266, + PLATFORM_NRF52, PLATFORM_RP2040, SCHEDULER_DONT_RUN, TYPE_GIT, @@ -695,6 +696,7 @@ def only_with_framework( only_on_esp32 = only_on(PLATFORM_ESP32) only_on_esp8266 = only_on(PLATFORM_ESP8266) +only_on_nrf52 = only_on(PLATFORM_NRF52) only_on_rp2040 = only_on(PLATFORM_RP2040) only_with_arduino = only_with_framework(Framework.ARDUINO) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a7fb9f197c..c82b222a3d 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -334,6 +334,8 @@ #ifdef USE_NRF52 #define USE_ESPHOME_TASK_LOG_BUFFER +#define USE_LOGGER_EARLY_MESSAGE +#define USE_LOGGER_WAIT_FOR_CDC #define USE_NRF52_DFU #define USE_NRF52_REG0_VOUT 5 #define USE_NRF52_UICR_ERASE diff --git a/tests/components/logger/test.nrf52-adafruit.yaml b/tests/components/logger/test.nrf52-adafruit.yaml index 821a136250..062451188f 100644 --- a/tests/components/logger/test.nrf52-adafruit.yaml +++ b/tests/components/logger/test.nrf52-adafruit.yaml @@ -5,4 +5,6 @@ esphome: logger: level: DEBUG + wait_for_cdc: true + early_message: true task_log_buffer_size: 0 From d206c75b0b815c1cdd5d4f0741f0b04f22918138 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 19:20:44 -0600 Subject: [PATCH 0839/2030] [logger] Fix loop disable optimization using wrong preprocessor guard (#14158) --- esphome/components/logger/logger.cpp | 13 ++++++------- esphome/components/logger/logger.h | 10 +++++----- esphome/components/logger/logger_zephyr.cpp | 2 +- esphome/core/defines.h | 4 ++++ 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 87963c5fc5..22a95e4835 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -170,19 +170,19 @@ void Logger::init_log_buffer(size_t total_buffer_size) { // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size); -// Zephyr needs loop working to check when CDC port is open -#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) - // Start with loop disabled when using task buffer (unless using USB CDC on ESP32) +#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) + // Start with loop disabled when using task buffer // The loop will be enabled automatically when messages arrive + // Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_() this->disable_loop_when_buffer_empty_(); #endif } #endif -#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)) +#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void Logger::loop() { this->process_messages_(); -#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC) +#if defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC) this->cdc_loop_(); #endif } @@ -204,8 +204,7 @@ void Logger::process_messages_() { this->write_log_buffer_to_console_(buf); } } -// Zephyr needs loop working to check when CDC port is open -#if !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) +#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) else { // No messages to process, disable loop if appropriate // This reduces overhead when there's no async logging activity diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index c6c379f6c6..8bf1edebb8 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -147,7 +147,7 @@ class Logger : public Component { #ifdef USE_ESPHOME_TASK_LOG_BUFFER void init_log_buffer(size_t total_buffer_size); #endif -#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC)) +#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void loop() override; #endif /// Manually set the baud rate for serial, set to 0 to disable. @@ -229,7 +229,7 @@ class Logger : public Component { void log_vprintf_non_main_thread_(uint8_t level, const char *tag, int line, const char *format, va_list args, const char *thread_name); #endif -#if defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC) +#if defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC) void cdc_loop_(); #endif void process_messages_(); @@ -465,9 +465,9 @@ class Logger : public Component { inline RecursionGuard make_non_main_task_guard_() { return RecursionGuard(non_main_task_recursion_guard_); } #endif -// Zephyr needs loop working to check when CDC port is open -#if defined(USE_ESPHOME_TASK_LOG_BUFFER) && !(defined(USE_ZEPHYR) || defined(USE_LOGGER_USB_CDC)) - // Disable loop when task buffer is empty (with USB CDC check on ESP32) +#if defined(USE_ESPHOME_TASK_LOG_BUFFER) && !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) + // Disable loop when task buffer is empty + // Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_() inline void disable_loop_when_buffer_empty_() { // Thread safety note: This is safe even if another task calls enable_loop_soon_any_context() // concurrently. If that happens between our check and disable_loop(), the enable request diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index d6193ff36b..c2d24d6efc 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -34,7 +34,7 @@ __attribute__((section(".noinit"))) struct { static const char *const TAG = "logger"; -#ifdef USE_LOGGER_USB_CDC +#ifdef USE_LOGGER_UART_SELECTION_USB_CDC void Logger::cdc_loop_() { if (this->uart_ != UART_SELECTION_USB_CDC || this->uart_dev_ == nullptr) { return; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c82b222a3d..5109dd36f4 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -270,10 +270,12 @@ #if defined(USE_ESP32_VARIANT_ESP32S2) #define USE_LOGGER_USB_CDC +#define USE_LOGGER_UART_SELECTION_USB_CDC #elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \ defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \ defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S3) #define USE_LOGGER_USB_CDC +#define USE_LOGGER_UART_SELECTION_USB_CDC #define USE_LOGGER_USB_SERIAL_JTAG #endif #endif @@ -335,6 +337,8 @@ #ifdef USE_NRF52 #define USE_ESPHOME_TASK_LOG_BUFFER #define USE_LOGGER_EARLY_MESSAGE +#define USE_LOGGER_UART_SELECTION_USB_CDC +#define USE_LOGGER_USB_CDC #define USE_LOGGER_WAIT_FOR_CDC #define USE_NRF52_DFU #define USE_NRF52_REG0_VOUT 5 From 35037d1a5b7c5ad7f4dbabaaa60dab2e7d76af01 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 19:20:58 -0600 Subject: [PATCH 0840/2030] [core] Deduplicate base64 encode/decode logic (#14143) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/helpers.cpp | 88 ++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 09e755ca71..9f850b5df8 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -545,38 +545,36 @@ static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c == std::string base64_encode(const std::vector<uint8_t> &buf) { return base64_encode(buf.data(), buf.size()); } +// Encode 3 input bytes to 4 base64 characters, append 'count' to ret. +static inline void base64_encode_triple(const char *char_array_3, int count, std::string &ret) { + char char_array_4[4]; + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (int j = 0; j < count; j++) + ret += BASE64_CHARS[static_cast<uint8_t>(char_array_4[j])]; +} + std::string base64_encode(const uint8_t *buf, size_t buf_len) { std::string ret; int i = 0; - int j = 0; char char_array_3[3]; - char char_array_4[4]; while (buf_len--) { char_array_3[i++] = *(buf++); if (i == 3) { - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (i = 0; (i < 4); i++) - ret += BASE64_CHARS[static_cast<uint8_t>(char_array_4[i])]; + base64_encode_triple(char_array_3, 4, ret); i = 0; } } if (i) { - for (j = i; j < 3; j++) + for (int j = i; j < 3; j++) char_array_3[j] = '\0'; - char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; - char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); - char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); - char_array_4[3] = char_array_3[2] & 0x3f; - - for (j = 0; (j < i + 1); j++) - ret += BASE64_CHARS[static_cast<uint8_t>(char_array_4[j])]; + base64_encode_triple(char_array_3, i + 1, ret); while ((i++ < 3)) ret += '='; @@ -589,13 +587,33 @@ size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf return base64_decode(reinterpret_cast<const uint8_t *>(encoded_string.data()), encoded_string.size(), buf, buf_len); } +// Decode 4 base64 characters to up to 'count' output bytes, returns true if truncated. +static inline bool base64_decode_quad(uint8_t *char_array_4, int count, uint8_t *buf, size_t buf_len, size_t &out) { + for (int i = 0; i < 4; i++) + char_array_4[i] = base64_find_char(char_array_4[i]); + + uint8_t char_array_3[3]; + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + bool truncated = false; + for (int j = 0; j < count; j++) { + if (out < buf_len) { + buf[out++] = char_array_3[j]; + } else { + truncated = true; + } + } + return truncated; +} + size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len) { size_t in_len = encoded_len; int i = 0; - int j = 0; size_t in = 0; size_t out = 0; - uint8_t char_array_4[4], char_array_3[3]; + uint8_t char_array_4[4]; bool truncated = false; // SAFETY: The loop condition checks is_base64() before processing each character. @@ -605,42 +623,16 @@ size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *b char_array_4[i++] = encoded_data[in]; in++; if (i == 4) { - for (i = 0; i < 4; i++) - char_array_4[i] = base64_find_char(char_array_4[i]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (i = 0; i < 3; i++) { - if (out < buf_len) { - buf[out++] = char_array_3[i]; - } else { - truncated = true; - } - } + truncated |= base64_decode_quad(char_array_4, 3, buf, buf_len, out); i = 0; } } if (i) { - for (j = i; j < 4; j++) + for (int j = i; j < 4; j++) char_array_4[j] = 0; - for (j = 0; j < 4; j++) - char_array_4[j] = base64_find_char(char_array_4[j]); - - char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); - char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); - char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; - - for (j = 0; j < i - 1; j++) { - if (out < buf_len) { - buf[out++] = char_array_3[j]; - } else { - truncated = true; - } - } + truncated |= base64_decode_quad(char_array_4, i - 1, buf, buf_len, out); } if (truncated) { From a3f279c1cf150f6908b84df9976e72821995e7b0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 19:21:14 -0600 Subject: [PATCH 0841/2030] [usb_host] Implement disable_loop/enable_loop pattern for USB components (#14163) --- esphome/components/usb_host/usb_host.h | 21 +++++++++++-------- .../components/usb_host/usb_host_client.cpp | 17 ++++++++++++++- esphome/components/usb_uart/usb_uart.cpp | 11 +++++++++- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index d1ec356613..a6a97d0bd7 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -73,12 +73,12 @@ static constexpr UBaseType_t USB_TASK_PRIORITY = 5; // Higher priority than mai // used to report a transfer status struct TransferStatus { - bool success; - uint16_t error_code; uint8_t *data; size_t data_len; - uint8_t endpoint; void *user_data; + uint16_t error_code; + uint8_t endpoint; + bool success; }; using transfer_cb_t = std::function<void(const TransferStatus &)>; @@ -127,7 +127,7 @@ class USBClient : public Component { friend class USBHost; public: - USBClient(uint16_t vid, uint16_t pid) : vid_(vid), pid_(pid), trq_in_use_(0) {} + USBClient(uint16_t vid, uint16_t pid) : trq_in_use_(0), vid_(vid), pid_(pid) {} void setup() override; void loop() override; // setup must happen after the host bus has been setup @@ -148,6 +148,10 @@ class USBClient : public Component { EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE> event_pool; protected: + // Process USB events from the queue. Returns true if any work was done. + // Subclasses should call this instead of USBClient::loop() to combine + // with their own work check for a single disable_loop() decision. + bool process_usb_events_(); void handle_open_state_(); TransferRequest *get_trq_(); // Lock-free allocation using atomic bitmask (multi-consumer safe) virtual void disconnect(); @@ -161,20 +165,19 @@ class USBClient : public Component { static void usb_task_fn(void *arg); [[noreturn]] void usb_task_loop() const; + // Members ordered to minimize struct padding on 32-bit platforms + TransferRequest requests_[MAX_REQUESTS]{}; TaskHandle_t usb_task_handle_{nullptr}; - usb_host_client_handle_t handle_{}; usb_device_handle_t device_handle_{}; int device_addr_{-1}; int state_{USB_CLIENT_INIT}; - uint16_t vid_{}; - uint16_t pid_{}; // Lock-free pool management using atomic bitmask (no dynamic allocation) // Bit i = 1: requests_[i] is in use, Bit i = 0: requests_[i] is available // Supports multiple concurrent consumers and producers (both threads can allocate/deallocate) - // Bitmask type automatically selected: uint16_t for <= 16 slots, uint32_t for 17-32 slots std::atomic<trq_bitmask_t> trq_in_use_; - TransferRequest requests_[MAX_REQUESTS]{}; + uint16_t vid_{}; + uint16_t pid_{}; }; class USBHost : public Component { public: diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 0612d7a841..a9be38fb03 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -197,6 +197,9 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * // Push to lock-free queue (always succeeds since pool size == queue size) client->event_queue.push(event); + // Re-enable component loop to process the queued event + client->enable_loop_soon_any_context(); + // Wake main loop immediately to process USB event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); @@ -243,10 +246,13 @@ void USBClient::usb_task_loop() const { } } -void USBClient::loop() { +bool USBClient::process_usb_events_() { + bool had_work = false; + // Process any events from the USB task UsbEvent *event; while ((event = this->event_queue.pop()) != nullptr) { + had_work = true; switch (event->type) { case EVENT_DEVICE_NEW: this->on_opened(event->data.device_new.address); @@ -266,8 +272,17 @@ void USBClient::loop() { } if (this->state_ == USB_CLIENT_OPEN) { + had_work = true; this->handle_open_state_(); } + + return had_work; +} + +void USBClient::loop() { + if (!this->process_usb_events_()) { + this->disable_loop(); + } } void USBClient::handle_open_state_() { diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index edd01c26c6..5c2806c456 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -172,11 +172,12 @@ bool USBUartChannel::read_array(uint8_t *data, size_t len) { } void USBUartComponent::setup() { USBClient::setup(); } void USBUartComponent::loop() { - USBClient::loop(); + bool had_work = this->process_usb_events_(); // Process USB data from the lock-free queue UsbDataChunk *chunk; while ((chunk = this->usb_data_queue_.pop()) != nullptr) { + had_work = true; auto *channel = chunk->channel; #ifdef USE_UART_DEBUGGER @@ -198,6 +199,11 @@ void USBUartComponent::loop() { if (dropped > 0) { ESP_LOGW(TAG, "Dropped %u USB data chunks due to buffer overflow", dropped); } + + // Disable loop when idle. Callbacks re-enable via enable_loop_soon_any_context(). + if (!had_work) { + this->disable_loop(); + } } void USBUartComponent::dump_config() { USBClient::dump_config(); @@ -264,6 +270,9 @@ void USBUartComponent::start_input(USBUartChannel *channel) { // Push always succeeds because pool size == queue size this->usb_data_queue_.push(chunk); + // Re-enable component loop to process the queued data + this->enable_loop_soon_any_context(); + // Wake main loop immediately to process USB data instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); From 0e38acd67a178ca6490284093c7034e8bfde5532 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 19:21:56 -0600 Subject: [PATCH 0842/2030] [api] Warn when clients connect with outdated API version (#14145) --- esphome/components/api/api_connection.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 5a7994a322..5b02bee537 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1534,6 +1534,12 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) { ESP_LOGV(TAG, "Hello from client: '%s' | %s | API Version %" PRIu16 ".%" PRIu16, this->helper_->get_client_name(), this->helper_->get_peername_to(peername), this->client_api_version_major_, this->client_api_version_minor_); + // TODO: Remove before 2026.8.0 (one version after get_object_id backward compat removal) + if (!this->client_supports_api_version(1, 14)) { + ESP_LOGW(TAG, "'%s' using outdated API %" PRIu16 ".%" PRIu16 ", update to 1.14+", this->helper_->get_client_name(), + this->client_api_version_major_, this->client_api_version_minor_); + } + HelloResponse resp; resp.api_version_major = 1; resp.api_version_minor = 14; From 8589f80d8fea4751aeac15134c91ca79fdf850a9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 20:59:49 -0600 Subject: [PATCH 0843/2030] [api,ota,captive_portal] Fix fd leaks and clean up socket_ip_loop_monitored setup paths (#14167) --- esphome/components/api/api_server.cpp | 30 +++++++++---------- esphome/components/api/api_server.h | 9 +++++- .../captive_portal/dns_server_esp32_idf.cpp | 9 ++---- .../captive_portal/dns_server_esp32_idf.h | 9 ++++-- .../components/esphome/ota/ota_esphome.cpp | 26 +++++++++------- esphome/components/esphome/ota/ota_esphome.h | 3 +- 6 files changed, 49 insertions(+), 37 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 1a1d0b229b..5b096788f5 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -30,6 +30,12 @@ APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-c APIServer::APIServer() { global_api_server = this; } +void APIServer::socket_failed_(const LogString *msg) { + ESP_LOGW(TAG, "Socket %s: errno %d", LOG_STR_ARG(msg), errno); + this->destroy_socket_(); + this->mark_failed(); +} + void APIServer::setup() { ControllerRegistry::register_controller(this); @@ -48,22 +54,20 @@ void APIServer::setup() { #endif #endif - this->socket_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections + this->socket_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0).release(); // monitored for incoming connections if (this->socket_ == nullptr) { - ESP_LOGW(TAG, "Could not create socket"); - this->mark_failed(); + this->socket_failed_(LOG_STR("creation")); return; } int enable = 1; int err = this->socket_->setsockopt(SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to set reuseaddr: errno %d", err); + ESP_LOGW(TAG, "Socket reuseaddr: errno %d", errno); // we can still continue } err = this->socket_->setblocking(false); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to set nonblocking mode: errno %d", err); - this->mark_failed(); + this->socket_failed_(LOG_STR("nonblocking")); return; } @@ -71,22 +75,19 @@ void APIServer::setup() { socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_); if (sl == 0) { - ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno); - this->mark_failed(); + this->socket_failed_(LOG_STR("set sockaddr")); return; } err = this->socket_->bind((struct sockaddr *) &server, sl); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno); - this->mark_failed(); + this->socket_failed_(LOG_STR("bind")); return; } err = this->socket_->listen(this->listen_backlog_); if (err != 0) { - ESP_LOGW(TAG, "Socket unable to listen: errno %d", errno); - this->mark_failed(); + this->socket_failed_(LOG_STR("listen")); return; } @@ -622,10 +623,7 @@ void APIServer::on_shutdown() { this->shutting_down_ = true; // Close the listening socket to prevent new connections - if (this->socket_) { - this->socket_->close(); - this->socket_ = nullptr; - } + this->destroy_socket_(); // Change batch delay to 5ms for quick flushing during shutdown this->batch_delay_ = 5; diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 3b9ba0e23b..fed29016b3 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -249,8 +249,15 @@ class APIServer : public Component, void add_state_subscription_(std::string entity_id, optional<std::string> attribute, std::function<void(const std::string &)> f, bool once); #endif // USE_API_HOMEASSISTANT_STATES + // No explicit close() needed — listen sockets have no active connections on + // failure/shutdown. Destructor handles fd cleanup (close or abort per platform). + inline void destroy_socket_() { + delete this->socket_; + this->socket_ = nullptr; + } + void socket_failed_(const LogString *msg); // Pointers and pointer-like types first (4 bytes each) - std::unique_ptr<socket::Socket> socket_ = nullptr; + socket::Socket *socket_{nullptr}; #ifdef USE_API_CLIENT_CONNECTED_TRIGGER Trigger<std::string, std::string> client_connected_trigger_; #endif diff --git a/esphome/components/captive_portal/dns_server_esp32_idf.cpp b/esphome/components/captive_portal/dns_server_esp32_idf.cpp index 5743cbd671..bd9989a40c 100644 --- a/esphome/components/captive_portal/dns_server_esp32_idf.cpp +++ b/esphome/components/captive_portal/dns_server_esp32_idf.cpp @@ -53,7 +53,7 @@ void DNSServer::start(const network::IPAddress &ip) { #endif // Create loop-monitored UDP socket - this->socket_ = socket::socket_ip_loop_monitored(SOCK_DGRAM, IPPROTO_UDP); + this->socket_ = socket::socket_ip_loop_monitored(SOCK_DGRAM, IPPROTO_UDP).release(); if (this->socket_ == nullptr) { ESP_LOGE(TAG, "Socket create failed"); return; @@ -70,17 +70,14 @@ void DNSServer::start(const network::IPAddress &ip) { int err = this->socket_->bind((struct sockaddr *) &server_addr, addr_len); if (err != 0) { ESP_LOGE(TAG, "Bind failed: %d", errno); - this->socket_ = nullptr; + this->destroy_socket_(); return; } ESP_LOGV(TAG, "Bound to port %d", DNS_PORT); } void DNSServer::stop() { - if (this->socket_ != nullptr) { - this->socket_->close(); - this->socket_ = nullptr; - } + this->destroy_socket_(); ESP_LOGV(TAG, "Stopped"); } diff --git a/esphome/components/captive_portal/dns_server_esp32_idf.h b/esphome/components/captive_portal/dns_server_esp32_idf.h index 3e0ac07373..f8e4cfec84 100644 --- a/esphome/components/captive_portal/dns_server_esp32_idf.h +++ b/esphome/components/captive_portal/dns_server_esp32_idf.h @@ -1,7 +1,6 @@ #pragma once #ifdef USE_ESP32 -#include <memory> #include "esphome/core/helpers.h" #include "esphome/components/network/ip_address.h" #include "esphome/components/socket/socket.h" @@ -15,9 +14,15 @@ class DNSServer { void process_next_request(); protected: + // No explicit close() needed — listen sockets have no active connections on + // failure/shutdown. Destructor handles fd cleanup (close or abort per platform). + inline void destroy_socket_() { + delete this->socket_; + this->socket_ = nullptr; + } static constexpr size_t DNS_BUFFER_SIZE = 192; - std::unique_ptr<socket::Socket> socket_{nullptr}; + socket::Socket *socket_{nullptr}; network::IPAddress server_ip_; uint8_t buffer_[DNS_BUFFER_SIZE]; }; diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index df2ea98f2c..a1cdf59d2b 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -28,10 +28,9 @@ static constexpr uint32_t OTA_SOCKET_TIMEOUT_HANDSHAKE = 20000; // milliseconds static constexpr uint32_t OTA_SOCKET_TIMEOUT_DATA = 90000; // milliseconds for data transfer void ESPHomeOTAComponent::setup() { - this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0); // monitored for incoming connections + this->server_ = socket::socket_ip_loop_monitored(SOCK_STREAM, 0).release(); // monitored for incoming connections if (this->server_ == nullptr) { - this->log_socket_error_(LOG_STR("creation")); - this->mark_failed(); + this->server_failed_(LOG_STR("creation")); return; } int enable = 1; @@ -42,8 +41,7 @@ void ESPHomeOTAComponent::setup() { } err = this->server_->setblocking(false); if (err != 0) { - this->log_socket_error_(LOG_STR("non-blocking")); - this->mark_failed(); + this->server_failed_(LOG_STR("nonblocking")); return; } @@ -51,22 +49,19 @@ void ESPHomeOTAComponent::setup() { socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), this->port_); if (sl == 0) { - this->log_socket_error_(LOG_STR("set sockaddr")); - this->mark_failed(); + this->server_failed_(LOG_STR("set sockaddr")); return; } err = this->server_->bind((struct sockaddr *) &server, sizeof(server)); if (err != 0) { - this->log_socket_error_(LOG_STR("bind")); - this->mark_failed(); + this->server_failed_(LOG_STR("bind")); return; } err = this->server_->listen(1); // Only one client at a time if (err != 0) { - this->log_socket_error_(LOG_STR("listen")); - this->mark_failed(); + this->server_failed_(LOG_STR("listen")); return; } } @@ -455,6 +450,15 @@ void ESPHomeOTAComponent::log_remote_closed_(const LogString *during) { ESP_LOGW(TAG, "Remote closed at %s", LOG_STR_ARG(during)); } +void ESPHomeOTAComponent::server_failed_(const LogString *msg) { + this->log_socket_error_(msg); + // No explicit close() needed — listen sockets have no active connections on + // failure/shutdown. Destructor handles fd cleanup (close or abort per platform). + delete this->server_; + this->server_ = nullptr; + this->mark_failed(); +} + bool ESPHomeOTAComponent::handle_read_error_(ssize_t read, const LogString *desc) { if (read == -1 && this->would_block_(errno)) { return false; // No data yet, try again next loop diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index e199b7e406..c9e89c82ba 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -66,6 +66,7 @@ class ESPHomeOTAComponent : public ota::OTAComponent { this->handshake_buf_pos_ = 0; // Reset buffer position for next state } + void server_failed_(const LogString *msg); void log_socket_error_(const LogString *msg); void log_read_error_(const LogString *what); void log_start_(const LogString *phase); @@ -83,7 +84,7 @@ class ESPHomeOTAComponent : public ota::OTAComponent { std::unique_ptr<uint8_t[]> auth_buf_; #endif // USE_OTA_PASSWORD - std::unique_ptr<socket::Socket> server_; + socket::Socket *server_{nullptr}; std::unique_ptr<socket::Socket> client_; std::unique_ptr<ota::OTABackend> backend_; From abe37c98413c6b78a7a01bec82f4b2f14e68cd77 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 21:08:49 -0600 Subject: [PATCH 0844/2030] [uptime] Use scheduler millis_64() for rollover-safe uptime tracking (#14170) --- .../uptime/sensor/uptime_seconds_sensor.cpp | 27 +++++-------------- .../uptime/sensor/uptime_seconds_sensor.h | 9 ++----- .../uptime/sensor/uptime_timestamp_sensor.cpp | 6 ++--- .../uptime/sensor/uptime_timestamp_sensor.h | 6 ++--- .../uptime/text_sensor/uptime_text_sensor.cpp | 24 ++++------------- .../uptime/text_sensor/uptime_text_sensor.h | 8 ++---- esphome/core/scheduler.cpp | 2 ++ esphome/core/scheduler.h | 3 +++ 8 files changed, 24 insertions(+), 61 deletions(-) diff --git a/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp b/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp index 54260d7e80..20e8ed8fda 100644 --- a/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +++ b/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp @@ -1,30 +1,16 @@ #include "uptime_seconds_sensor.h" -#include "esphome/core/hal.h" -#include "esphome/core/helpers.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { static const char *const TAG = "uptime.sensor"; void UptimeSecondsSensor::update() { - const uint32_t ms = millis(); - const uint64_t ms_mask = (1ULL << 32) - 1ULL; - const uint32_t last_ms = this->uptime_ & ms_mask; - if (ms < last_ms) { - this->uptime_ += ms_mask + 1ULL; - ESP_LOGD(TAG, "Detected roll-over \xf0\x9f\xa6\x84"); - } - this->uptime_ &= ~ms_mask; - this->uptime_ |= ms; - - // Do separate second and milliseconds conversion to avoid floating point division errors - // Probably some IEEE standard already guarantees this division can be done without loss - // of precision in a single division, but let's do it like this to be sure. - const uint64_t seconds_int = this->uptime_ / 1000ULL; - const float seconds = float(seconds_int) + (this->uptime_ % 1000ULL) / 1000.0f; + const uint64_t uptime = App.scheduler.millis_64(); + const uint64_t seconds_int = uptime / 1000ULL; + const float seconds = float(seconds_int) + (uptime % 1000ULL) / 1000.0f; this->publish_state(seconds); } float UptimeSecondsSensor::get_setup_priority() const { return setup_priority::HARDWARE; } @@ -33,5 +19,4 @@ void UptimeSecondsSensor::dump_config() { ESP_LOGCONFIG(TAG, " Type: Seconds"); } -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime diff --git a/esphome/components/uptime/sensor/uptime_seconds_sensor.h b/esphome/components/uptime/sensor/uptime_seconds_sensor.h index 210195052f..1b80a4480a 100644 --- a/esphome/components/uptime/sensor/uptime_seconds_sensor.h +++ b/esphome/components/uptime/sensor/uptime_seconds_sensor.h @@ -3,8 +3,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/core/component.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { class UptimeSecondsSensor : public sensor::Sensor, public PollingComponent { public: @@ -12,10 +11,6 @@ class UptimeSecondsSensor : public sensor::Sensor, public PollingComponent { void dump_config() override; float get_setup_priority() const override; - - protected: - uint64_t uptime_{0}; }; -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime diff --git a/esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp b/esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp index 69033be11c..4e0f06be1c 100644 --- a/esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp +++ b/esphome/components/uptime/sensor/uptime_timestamp_sensor.cpp @@ -6,8 +6,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { static const char *const TAG = "uptime.sensor"; @@ -33,7 +32,6 @@ void UptimeTimestampSensor::dump_config() { ESP_LOGCONFIG(TAG, " Type: Timestamp"); } -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime #endif // USE_TIME diff --git a/esphome/components/uptime/sensor/uptime_timestamp_sensor.h b/esphome/components/uptime/sensor/uptime_timestamp_sensor.h index f38b5d53b4..912c0b7655 100644 --- a/esphome/components/uptime/sensor/uptime_timestamp_sensor.h +++ b/esphome/components/uptime/sensor/uptime_timestamp_sensor.h @@ -8,8 +8,7 @@ #include "esphome/components/time/real_time_clock.h" #include "esphome/core/component.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { class UptimeTimestampSensor : public sensor::Sensor, public Component { public: @@ -24,7 +23,6 @@ class UptimeTimestampSensor : public sensor::Sensor, public Component { time::RealTimeClock *time_; }; -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime #endif // USE_TIME diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index acd3980a1a..88ae53fbfc 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -1,11 +1,10 @@ #include "uptime_text_sensor.h" -#include "esphome/core/hal.h" +#include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { static const char *const TAG = "uptime.sensor"; @@ -17,22 +16,10 @@ static void append_unit(char *buf, size_t buf_size, size_t &pos, const char *sep pos = buf_append_printf(buf, buf_size, pos, "%u%s", value, label); } -void UptimeTextSensor::setup() { - this->last_ms_ = millis(); - if (this->last_ms_ < 60 * 1000) - this->last_ms_ = 0; - this->update(); -} +void UptimeTextSensor::setup() { this->update(); } void UptimeTextSensor::update() { - auto now = millis(); - // get whole seconds since last update. Note that even if the millis count has overflowed between updates, - // the difference will still be correct due to the way twos-complement arithmetic works. - uint32_t delta = now - this->last_ms_; - this->last_ms_ = now - delta % 1000; // save remainder for next update - delta /= 1000; - this->uptime_ += delta; - uint32_t uptime = this->uptime_; + uint32_t uptime = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); unsigned interval = this->get_update_interval() / 1000; // Calculate all time units @@ -89,5 +76,4 @@ void UptimeTextSensor::update() { float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; } void UptimeTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Uptime Text Sensor", this); } -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.h b/esphome/components/uptime/text_sensor/uptime_text_sensor.h index 947d9c91e9..a97ba332bb 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.h +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.h @@ -5,8 +5,7 @@ #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/core/component.h" -namespace esphome { -namespace uptime { +namespace esphome::uptime { class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent { public: @@ -35,9 +34,6 @@ class UptimeTextSensor : public text_sensor::TextSensor, public PollingComponent const char *seconds_text_; const char *separator_; bool expand_{}; - uint32_t uptime_{0}; // uptime in seconds, will overflow after 136 years - uint32_t last_ms_{0}; }; -} // namespace uptime -} // namespace esphome +} // namespace esphome::uptime diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 3294f689e8..e82efcc520 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -675,6 +675,8 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } +uint64_t Scheduler::millis_64() { return this->millis_64_(millis()); } + uint64_t Scheduler::millis_64_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 394178a831..afe11aaca6 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -116,6 +116,9 @@ class Scheduler { ESPDEPRECATED("cancel_retry is deprecated and will be removed in 2026.8.0.", "2026.2.0") bool cancel_retry(Component *component, uint32_t id); + /// Get 64-bit millisecond timestamp (handles 32-bit millis() rollover) + uint64_t millis_64(); + // Calculate when the next scheduled item should run // @param now Fresh timestamp from millis() - must not be stale/cached // Returns the time in milliseconds until the next scheduled item, or nullopt if no items From f8f98bf428e1db199f4b5bf79a4b3362b7d5672d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 21:16:49 -0600 Subject: [PATCH 0845/2030] [logger] Reduce UART driver heap waste on ESP32 (#14168) --- esphome/components/logger/logger_esp32.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index dfa643d5e9..9d64771aec 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -77,9 +77,10 @@ void init_uart(uart_port_t uart_num, uint32_t baud_rate, int tx_buffer_size) { uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; uart_config.source_clk = UART_SCLK_DEFAULT; uart_param_config(uart_num, &uart_config); - const int uart_buffer_size = tx_buffer_size; - // Install UART driver using an event queue here - uart_driver_install(uart_num, uart_buffer_size, uart_buffer_size, 10, nullptr, 0); + // The logger only writes to UART, never reads, so use the minimum RX buffer. + // ESP-IDF requires rx_buffer_size > UART_HW_FIFO_LEN (128 bytes). + const int min_rx_buffer_size = UART_HW_FIFO_LEN(uart_num) + 1; + uart_driver_install(uart_num, min_rx_buffer_size, tx_buffer_size, 0, nullptr, 0); } void Logger::pre_setup() { From f77da803c9b316c78a51e602563dcd6d916682f7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Feb 2026 21:39:18 -0600 Subject: [PATCH 0846/2030] [api] Write protobuf encode output to pre-sized buffer directly (#14018) --- esphome/components/api/api_connection.cpp | 35 ++--- esphome/components/api/api_pb2.cpp | 180 +++++++++++----------- esphome/components/api/api_pb2.h | 176 ++++++++++----------- esphome/components/api/proto.cpp | 15 ++ esphome/components/api/proto.h | 108 ++++++++----- script/api_protobuf/api_protobuf.py | 12 +- 6 files changed, 286 insertions(+), 240 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 5b02bee537..9fc263abbd 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -347,9 +347,7 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess #endif // Calculate size - ProtoSize size_calc; - msg.calculate_size(size_calc); - uint32_t calculated_size = size_calc.get_size(); + uint32_t calculated_size = msg.calculated_size(); // Cache frame sizes to avoid repeated virtual calls const uint8_t header_padding = conn->helper_->frame_header_padding(); @@ -377,19 +375,14 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess shared_buf.resize(current_size + footer_size + header_padding); } - // Encode directly into buffer - size_t size_before_encode = shared_buf.size(); - msg.encode({&shared_buf}); + // Pre-resize buffer to include payload, then encode through raw pointer + size_t write_start = shared_buf.size(); + shared_buf.resize(write_start + calculated_size); + ProtoWriteBuffer buffer{&shared_buf, write_start}; + msg.encode(buffer); - // Calculate actual encoded size (not including header that was already added) - size_t actual_payload_size = shared_buf.size() - size_before_encode; - - // Return actual total size (header + actual payload + footer) - size_t actual_total_size = header_padding + actual_payload_size + footer_size; - - // Verify that calculate_size() returned the correct value - assert(calculated_size == actual_payload_size); - return static_cast<uint16_t>(actual_total_size); + // Return total size (header + payload + footer) + return static_cast<uint16_t>(header_padding + calculated_size + footer_size); } #ifdef USE_BINARY_SENSOR @@ -1854,12 +1847,14 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { return false; } bool APIConnection::send_message_impl(const ProtoMessage &msg, uint8_t message_type) { - ProtoSize size; - msg.calculate_size(size); + uint32_t payload_size = msg.calculated_size(); std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref(); - this->prepare_first_message_buffer(shared_buf, size.get_size()); - msg.encode({&shared_buf}); - return this->send_buffer({&shared_buf}, message_type); + this->prepare_first_message_buffer(shared_buf, payload_size); + size_t write_start = shared_buf.size(); + shared_buf.resize(write_start + payload_size); + ProtoWriteBuffer buffer{&shared_buf, write_start}; + msg.encode(buffer); + return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type); } bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 743f51dac7..5c50a8aa5b 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -31,7 +31,7 @@ bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) } return true; } -void HelloResponse::encode(ProtoWriteBuffer buffer) const { +void HelloResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->api_version_major); buffer.encode_uint32(2, this->api_version_minor); buffer.encode_string(3, this->server_info); @@ -44,7 +44,7 @@ void HelloResponse::calculate_size(ProtoSize &size) const { size.add_length(1, this->name.size()); } #ifdef USE_AREAS -void AreaInfo::encode(ProtoWriteBuffer buffer) const { +void AreaInfo::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->area_id); buffer.encode_string(2, this->name); } @@ -54,7 +54,7 @@ void AreaInfo::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_DEVICES -void DeviceInfo::encode(ProtoWriteBuffer buffer) const { +void DeviceInfo::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->device_id); buffer.encode_string(2, this->name); buffer.encode_uint32(3, this->area_id); @@ -65,7 +65,7 @@ void DeviceInfo::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->area_id); } #endif -void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { +void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(2, this->name); buffer.encode_string(3, this->mac_address); buffer.encode_string(4, this->esphome_version); @@ -111,7 +111,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const { } #endif #ifdef USE_AREAS - buffer.encode_message(22, this->area); + buffer.encode_message(22, this->area, false); #endif #ifdef USE_ZWAVE_PROXY buffer.encode_uint32(23, this->zwave_proxy_feature_flags); @@ -176,7 +176,7 @@ void DeviceInfoResponse::calculate_size(ProtoSize &size) const { #endif } #ifdef USE_BINARY_SENSOR -void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -206,7 +206,7 @@ void ListEntitiesBinarySensorResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const { +void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -224,7 +224,7 @@ void BinarySensorStateResponse::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_COVER -void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -260,7 +260,7 @@ void ListEntitiesCoverResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void CoverStateResponse::encode(ProtoWriteBuffer buffer) const { +void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(3, this->position); buffer.encode_float(4, this->tilt); @@ -317,7 +317,7 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_FAN -void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -359,7 +359,7 @@ void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void FanStateResponse::encode(ProtoWriteBuffer buffer) const { +void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); buffer.encode_bool(3, this->oscillating); @@ -443,7 +443,7 @@ bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_LIGHT -void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -489,7 +489,7 @@ void ListEntitiesLightResponse::calculate_size(ProtoSize &size) const { size.add_uint32(2, this->device_id); #endif } -void LightStateResponse::encode(ProtoWriteBuffer buffer) const { +void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); buffer.encode_float(3, this->brightness); @@ -635,7 +635,7 @@ bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SENSOR -void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -671,7 +671,7 @@ void ListEntitiesSensorResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void SensorStateResponse::encode(ProtoWriteBuffer buffer) const { +void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -689,7 +689,7 @@ void SensorStateResponse::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_SWITCH -void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -719,7 +719,7 @@ void ListEntitiesSwitchResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void SwitchStateResponse::encode(ProtoWriteBuffer buffer) const { +void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); #ifdef USE_DEVICES @@ -760,7 +760,7 @@ bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_TEXT_SENSOR -void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -788,7 +788,7 @@ void ListEntitiesTextSensorResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const { +void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -818,7 +818,7 @@ bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { } return true; } -void SubscribeLogsResponse::encode(ProtoWriteBuffer buffer) const { +void SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->level)); buffer.encode_bytes(3, this->message_ptr_, this->message_len_); } @@ -839,11 +839,11 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD } return true; } -void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); } +void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } void NoiseEncryptionSetKeyResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -void HomeassistantServiceMap::encode(ProtoWriteBuffer buffer) const { +void HomeassistantServiceMap::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->key); buffer.encode_string(2, this->value); } @@ -851,7 +851,7 @@ void HomeassistantServiceMap::calculate_size(ProtoSize &size) const { size.add_length(1, this->key.size()); size.add_length(1, this->value.size()); } -void HomeassistantActionRequest::encode(ProtoWriteBuffer buffer) const { +void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->service); for (auto &it : this->data) { buffer.encode_message(2, it); @@ -924,7 +924,7 @@ bool HomeassistantActionResponse::decode_length(uint32_t field_id, ProtoLengthDe } #endif #ifdef USE_API_HOMEASSISTANT_STATES -void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer buffer) const { +void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->entity_id); buffer.encode_string(2, this->attribute); buffer.encode_bool(3, this->once); @@ -976,7 +976,7 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { return true; } #ifdef USE_API_USER_DEFINED_ACTIONS -void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); buffer.encode_uint32(2, static_cast<uint32_t>(this->type)); } @@ -984,7 +984,7 @@ void ListEntitiesServicesArgument::calculate_size(ProtoSize &size) const { size.add_length(1, this->name.size()); size.add_uint32(1, static_cast<uint32_t>(this->type)); } -void ListEntitiesServicesResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); buffer.encode_fixed32(2, this->key); for (auto &it : this->args) { @@ -1103,7 +1103,7 @@ void ExecuteServiceRequest::decode(const uint8_t *buffer, size_t length) { } #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES -void ExecuteServiceResponse::encode(ProtoWriteBuffer buffer) const { +void ExecuteServiceResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->call_id); buffer.encode_bool(2, this->success); buffer.encode_string(3, this->error_message); @@ -1121,7 +1121,7 @@ void ExecuteServiceResponse::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_CAMERA -void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1147,7 +1147,7 @@ void ListEntitiesCameraResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void CameraImageResponse::encode(ProtoWriteBuffer buffer) const { +void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bytes(2, this->data_ptr_, this->data_len_); buffer.encode_bool(3, this->done); @@ -1178,7 +1178,7 @@ bool CameraImageRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { } #endif #ifdef USE_CLIMATE -void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1276,7 +1276,7 @@ void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const { #endif size.add_uint32(2, this->feature_flags); } -void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const { +void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); buffer.encode_float(3, this->current_temperature); @@ -1407,7 +1407,7 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_WATER_HEATER -void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1449,7 +1449,7 @@ void ListEntitiesWaterHeaterResponse::calculate_size(ProtoSize &size) const { } size.add_uint32(1, this->supported_features); } -void WaterHeaterStateResponse::encode(ProtoWriteBuffer buffer) const { +void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(2, this->current_temperature); buffer.encode_float(3, this->target_temperature); @@ -1515,7 +1515,7 @@ bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value } #endif #ifdef USE_NUMBER -void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1553,7 +1553,7 @@ void ListEntitiesNumberResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void NumberStateResponse::encode(ProtoWriteBuffer buffer) const { +void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -1596,7 +1596,7 @@ bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SELECT -void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1630,7 +1630,7 @@ void ListEntitiesSelectResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void SelectStateResponse::encode(ProtoWriteBuffer buffer) const { +void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -1681,7 +1681,7 @@ bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SIREN -void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1719,7 +1719,7 @@ void ListEntitiesSirenResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void SirenStateResponse::encode(ProtoWriteBuffer buffer) const { +void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->state); #ifdef USE_DEVICES @@ -1789,7 +1789,7 @@ bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_LOCK -void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1823,7 +1823,7 @@ void ListEntitiesLockResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void LockStateResponse::encode(ProtoWriteBuffer buffer) const { +void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES @@ -1878,7 +1878,7 @@ bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_BUTTON -void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1930,7 +1930,7 @@ bool ButtonCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_MEDIA_PLAYER -void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer buffer) const { +void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->format); buffer.encode_uint32(2, this->sample_rate); buffer.encode_uint32(3, this->num_channels); @@ -1944,7 +1944,7 @@ void MediaPlayerSupportedFormat::calculate_size(ProtoSize &size) const { size.add_uint32(1, static_cast<uint32_t>(this->purpose)); size.add_uint32(1, this->sample_bytes); } -void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -1978,7 +1978,7 @@ void ListEntitiesMediaPlayerResponse::calculate_size(ProtoSize &size) const { #endif size.add_uint32(1, this->feature_flags); } -void MediaPlayerStateResponse::encode(ProtoWriteBuffer buffer) const { +void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); buffer.encode_float(3, this->volume); @@ -2062,7 +2062,7 @@ bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, } return true; } -void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer buffer) const { +void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_sint32(2, this->rssi); buffer.encode_uint32(3, this->address_type); @@ -2074,7 +2074,7 @@ void BluetoothLERawAdvertisement::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->address_type); size.add_length(1, this->data_len); } -void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { for (uint16_t i = 0; i < this->advertisements_len; i++) { buffer.encode_message(1, this->advertisements[i]); } @@ -2103,7 +2103,7 @@ bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) } return true; } -void BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->connected); buffer.encode_uint32(3, this->mtu); @@ -2125,7 +2125,7 @@ bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarI } return true; } -void BluetoothGATTDescriptor::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTDescriptor::encode(ProtoWriteBuffer &buffer) const { if (this->uuid[0] != 0 || this->uuid[1] != 0) { buffer.encode_uint64(1, this->uuid[0], true); buffer.encode_uint64(1, this->uuid[1], true); @@ -2141,7 +2141,7 @@ void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->handle); size.add_uint32(1, this->short_uuid); } -void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const { if (this->uuid[0] != 0 || this->uuid[1] != 0) { buffer.encode_uint64(1, this->uuid[0], true); buffer.encode_uint64(1, this->uuid[1], true); @@ -2163,7 +2163,7 @@ void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const { size.add_repeated_message(1, this->descriptors); size.add_uint32(1, this->short_uuid); } -void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const { if (this->uuid[0] != 0 || this->uuid[1] != 0) { buffer.encode_uint64(1, this->uuid[0], true); buffer.encode_uint64(1, this->uuid[1], true); @@ -2183,7 +2183,7 @@ void BluetoothGATTService::calculate_size(ProtoSize &size) const { size.add_repeated_message(1, this->characteristics); size.add_uint32(1, this->short_uuid); } -void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); for (auto &it : this->services) { buffer.encode_message(2, it); @@ -2193,7 +2193,7 @@ void BluetoothGATTGetServicesResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); size.add_repeated_message(1, this->services); } -void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); } void BluetoothGATTGetServicesDoneResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); } @@ -2210,7 +2210,7 @@ bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, ProtoVarInt valu } return true; } -void BluetoothGATTReadResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTReadResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); @@ -2302,7 +2302,7 @@ bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, ProtoVarInt va } return true; } -void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); @@ -2312,7 +2312,7 @@ void BluetoothGATTNotifyDataResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->handle); size.add_length(1, this->data_len_); } -void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->free); buffer.encode_uint32(2, this->limit); for (const auto &it : this->allocated) { @@ -2330,7 +2330,7 @@ void BluetoothConnectionsFreeResponse::calculate_size(ProtoSize &size) const { } } } -void BluetoothGATTErrorResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTErrorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); buffer.encode_int32(3, this->error); @@ -2340,7 +2340,7 @@ void BluetoothGATTErrorResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->handle); size.add_int32(1, this->error); } -void BluetoothGATTWriteResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTWriteResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } @@ -2348,7 +2348,7 @@ void BluetoothGATTWriteResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); size.add_uint32(1, this->handle); } -void BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } @@ -2356,7 +2356,7 @@ void BluetoothGATTNotifyResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); size.add_uint32(1, this->handle); } -void BluetoothDevicePairingResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothDevicePairingResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->paired); buffer.encode_int32(3, this->error); @@ -2366,7 +2366,7 @@ void BluetoothDevicePairingResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->paired); size.add_int32(1, this->error); } -void BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); @@ -2376,7 +2376,7 @@ void BluetoothDeviceUnpairingResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); size.add_int32(1, this->error); } -void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); @@ -2386,7 +2386,7 @@ void BluetoothDeviceClearCacheResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); size.add_int32(1, this->error); } -void BluetoothScannerStateResponse::encode(ProtoWriteBuffer buffer) const { +void BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->state)); buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); buffer.encode_uint32(3, static_cast<uint32_t>(this->configured_mode)); @@ -2421,7 +2421,7 @@ bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarIn } return true; } -void VoiceAssistantAudioSettings::encode(ProtoWriteBuffer buffer) const { +void VoiceAssistantAudioSettings::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->noise_suppression_level); buffer.encode_uint32(2, this->auto_gain); buffer.encode_float(3, this->volume_multiplier); @@ -2431,11 +2431,11 @@ void VoiceAssistantAudioSettings::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->auto_gain); size.add_float(1, this->volume_multiplier); } -void VoiceAssistantRequest::encode(ProtoWriteBuffer buffer) const { +void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->start); buffer.encode_string(2, this->conversation_id); buffer.encode_uint32(3, this->flags); - buffer.encode_message(4, this->audio_settings); + buffer.encode_message(4, this->audio_settings, false); buffer.encode_string(5, this->wake_word_phrase); } void VoiceAssistantRequest::calculate_size(ProtoSize &size) const { @@ -2516,7 +2516,7 @@ bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited } return true; } -void VoiceAssistantAudio::encode(ProtoWriteBuffer buffer) const { +void VoiceAssistantAudio::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(1, this->data, this->data_len); buffer.encode_bool(2, this->end); } @@ -2587,9 +2587,9 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength } return true; } -void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer buffer) const { buffer.encode_bool(1, this->success); } +void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } void VoiceAssistantAnnounceFinished::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } -void VoiceAssistantWakeWord::encode(ProtoWriteBuffer buffer) const { +void VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->id); buffer.encode_string(2, this->wake_word); for (auto &it : this->trained_languages) { @@ -2656,7 +2656,7 @@ bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoL } return true; } -void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer buffer) const { +void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer) const { for (auto &it : this->available_wake_words) { buffer.encode_message(1, it); } @@ -2686,7 +2686,7 @@ bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengt } #endif #ifdef USE_ALARM_CONTROL_PANEL -void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -2718,7 +2718,7 @@ void ListEntitiesAlarmControlPanelResponse::calculate_size(ProtoSize &size) cons size.add_uint32(1, this->device_id); #endif } -void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer buffer) const { +void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES @@ -2770,7 +2770,7 @@ bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit } #endif #ifdef USE_TEXT -void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -2804,7 +2804,7 @@ void ListEntitiesTextResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void TextStateResponse::encode(ProtoWriteBuffer buffer) const { +void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); @@ -2855,7 +2855,7 @@ bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_DATE -void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -2881,7 +2881,7 @@ void ListEntitiesDateResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void DateStateResponse::encode(ProtoWriteBuffer buffer) const { +void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_uint32(3, this->year); @@ -2934,7 +2934,7 @@ bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_TIME -void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -2960,7 +2960,7 @@ void ListEntitiesTimeResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void TimeStateResponse::encode(ProtoWriteBuffer buffer) const { +void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_uint32(3, this->hour); @@ -3013,7 +3013,7 @@ bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_EVENT -void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -3049,7 +3049,7 @@ void ListEntitiesEventResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void EventResponse::encode(ProtoWriteBuffer buffer) const { +void EventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_string(2, this->event_type); #ifdef USE_DEVICES @@ -3065,7 +3065,7 @@ void EventResponse::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_VALVE -void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -3099,7 +3099,7 @@ void ListEntitiesValveResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void ValveStateResponse::encode(ProtoWriteBuffer buffer) const { +void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_float(2, this->position); buffer.encode_uint32(3, static_cast<uint32_t>(this->current_operation)); @@ -3148,7 +3148,7 @@ bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_DATETIME -void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -3174,7 +3174,7 @@ void ListEntitiesDateTimeResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void DateTimeStateResponse::encode(ProtoWriteBuffer buffer) const { +void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_fixed32(3, this->epoch_seconds); @@ -3217,7 +3217,7 @@ bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_UPDATE -void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -3245,7 +3245,7 @@ void ListEntitiesUpdateResponse::calculate_size(ProtoSize &size) const { size.add_uint32(1, this->device_id); #endif } -void UpdateStateResponse::encode(ProtoWriteBuffer buffer) const { +void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_bool(3, this->in_progress); @@ -3314,7 +3314,7 @@ bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited valu } return true; } -void ZWaveProxyFrame::encode(ProtoWriteBuffer buffer) const { buffer.encode_bytes(1, this->data, this->data_len); } +void ZWaveProxyFrame::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(1, this->data, this->data_len); } void ZWaveProxyFrame::calculate_size(ProtoSize &size) const { size.add_length(1, this->data_len); } bool ZWaveProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3338,7 +3338,7 @@ bool ZWaveProxyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited va } return true; } -void ZWaveProxyRequest::encode(ProtoWriteBuffer buffer) const { +void ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->type)); buffer.encode_bytes(2, this->data, this->data_len); } @@ -3348,7 +3348,7 @@ void ZWaveProxyRequest::calculate_size(ProtoSize &size) const { } #endif #ifdef USE_INFRARED -void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer buffer) const { +void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); buffer.encode_fixed32(2, this->key); buffer.encode_string(3, this->name); @@ -3419,7 +3419,7 @@ bool InfraredRFTransmitRawTimingsRequest::decode_32bit(uint32_t field_id, Proto3 } return true; } -void InfraredRFReceiveEvent::encode(ProtoWriteBuffer buffer) const { +void InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer) const { #ifdef USE_DEVICES buffer.encode_uint32(1, this->device_id); #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index d001f869c5..c90873d993 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -382,7 +382,7 @@ class HelloResponse final : public ProtoMessage { uint32_t api_version_minor{0}; StringRef server_info{}; StringRef name{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -447,7 +447,7 @@ class AreaInfo final : public ProtoMessage { public: uint32_t area_id{0}; StringRef name{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -462,7 +462,7 @@ class DeviceInfo final : public ProtoMessage { uint32_t device_id{0}; StringRef name{}; uint32_t area_id{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -527,7 +527,7 @@ class DeviceInfoResponse final : public ProtoMessage { #ifdef USE_ZWAVE_PROXY uint32_t zwave_home_id{0}; #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -558,7 +558,7 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; bool is_status_binary_sensor{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -575,7 +575,7 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage { #endif bool state{false}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -597,7 +597,7 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage { bool supports_tilt{false}; StringRef device_class{}; bool supports_stop{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -615,7 +615,7 @@ class CoverStateResponse final : public StateResponseProtoMessage { float position{0.0f}; float tilt{0.0f}; enums::CoverOperation current_operation{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -657,7 +657,7 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { bool supports_direction{false}; int32_t supported_speed_count{0}; const std::vector<const char *> *supported_preset_modes{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -677,7 +677,7 @@ class FanStateResponse final : public StateResponseProtoMessage { enums::FanDirection direction{}; int32_t speed_level{0}; StringRef preset_mode{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -724,7 +724,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage { float min_mireds{0.0f}; float max_mireds{0.0f}; const FixedVector<const char *> *effects{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -751,7 +751,7 @@ class LightStateResponse final : public StateResponseProtoMessage { float cold_white{0.0f}; float warm_white{0.0f}; StringRef effect{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -815,7 +815,7 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage { bool force_update{false}; StringRef device_class{}; enums::SensorStateClass state_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -832,7 +832,7 @@ class SensorStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -851,7 +851,7 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage { #endif bool assumed_state{false}; StringRef device_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -867,7 +867,7 @@ class SwitchStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "switch_state_response"; } #endif bool state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -901,7 +901,7 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_text_sensor_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -918,7 +918,7 @@ class TextSensorStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -957,7 +957,7 @@ class SubscribeLogsResponse final : public ProtoMessage { this->message_ptr_ = data; this->message_len_ = len; } - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -990,7 +990,7 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { const char *message_name() const override { return "noise_encryption_set_key_response"; } #endif bool success{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1004,7 +1004,7 @@ class HomeassistantServiceMap final : public ProtoMessage { public: StringRef key{}; StringRef value{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1033,7 +1033,7 @@ class HomeassistantActionRequest final : public ProtoMessage { #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON StringRef response_template{}; #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1077,7 +1077,7 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage { StringRef entity_id{}; StringRef attribute{}; bool once{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1138,7 +1138,7 @@ class ListEntitiesServicesArgument final : public ProtoMessage { public: StringRef name{}; enums::ServiceArgType type{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1157,7 +1157,7 @@ class ListEntitiesServicesResponse final : public ProtoMessage { uint32_t key{0}; FixedVector<ListEntitiesServicesArgument> args{}; enums::SupportsResponseType supports_response{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1227,7 +1227,7 @@ class ExecuteServiceResponse final : public ProtoMessage { const uint8_t *response_data{nullptr}; uint16_t response_data_len{0}; #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1244,7 +1244,7 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_camera_response"; } #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1266,7 +1266,7 @@ class CameraImageResponse final : public StateResponseProtoMessage { this->data_len_ = len; } bool done{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1317,7 +1317,7 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage { float visual_min_humidity{0.0f}; float visual_max_humidity{0.0f}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1345,7 +1345,7 @@ class ClimateStateResponse final : public StateResponseProtoMessage { StringRef custom_preset{}; float current_humidity{0.0f}; float target_humidity{0.0f}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1403,7 +1403,7 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage { float target_temperature_step{0.0f}; const water_heater::WaterHeaterModeMask *supported_modes{}; uint32_t supported_features{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1424,7 +1424,7 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage { uint32_t state{0}; float target_temperature_low{0.0f}; float target_temperature_high{0.0f}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1468,7 +1468,7 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage { StringRef unit_of_measurement{}; enums::NumberMode mode{}; StringRef device_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1485,7 +1485,7 @@ class NumberStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1519,7 +1519,7 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_select_response"; } #endif const FixedVector<const char *> *options{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1536,7 +1536,7 @@ class SelectStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1573,7 +1573,7 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage { const FixedVector<const char *> *tones{}; bool supports_duration{false}; bool supports_volume{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1589,7 +1589,7 @@ class SirenStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "siren_state_response"; } #endif bool state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1634,7 +1634,7 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage { bool supports_open{false}; bool requires_code{false}; StringRef code_format{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1650,7 +1650,7 @@ class LockStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "lock_state_response"; } #endif enums::LockState state{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1687,7 +1687,7 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_button_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1719,7 +1719,7 @@ class MediaPlayerSupportedFormat final : public ProtoMessage { uint32_t num_channels{0}; enums::MediaPlayerFormatPurpose purpose{}; uint32_t sample_bytes{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1737,7 +1737,7 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage { bool supports_pause{false}; std::vector<MediaPlayerSupportedFormat> supported_formats{}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1755,7 +1755,7 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage { enums::MediaPlayerState state{}; float volume{0.0f}; bool muted{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1811,7 +1811,7 @@ class BluetoothLERawAdvertisement final : public ProtoMessage { uint32_t address_type{0}; uint8_t data[62]{}; uint8_t data_len{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1828,7 +1828,7 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage { #endif std::array<BluetoothLERawAdvertisement, BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE> advertisements{}; uint16_t advertisements_len{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1865,7 +1865,7 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage { bool connected{false}; uint32_t mtu{0}; int32_t error{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1893,7 +1893,7 @@ class BluetoothGATTDescriptor final : public ProtoMessage { std::array<uint64_t, 2> uuid{}; uint32_t handle{0}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1908,7 +1908,7 @@ class BluetoothGATTCharacteristic final : public ProtoMessage { uint32_t properties{0}; FixedVector<BluetoothGATTDescriptor> descriptors{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1922,7 +1922,7 @@ class BluetoothGATTService final : public ProtoMessage { uint32_t handle{0}; FixedVector<BluetoothGATTCharacteristic> characteristics{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1939,7 +1939,7 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage { #endif uint64_t address{0}; std::vector<BluetoothGATTService> services{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1955,7 +1955,7 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage { const char *message_name() const override { return "bluetooth_gatt_get_services_done_response"; } #endif uint64_t address{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1994,7 +1994,7 @@ class BluetoothGATTReadResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2089,7 +2089,7 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2107,7 +2107,7 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage { uint32_t free{0}; uint32_t limit{0}; std::array<uint64_t, BLUETOOTH_PROXY_MAX_CONNECTIONS> allocated{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2125,7 +2125,7 @@ class BluetoothGATTErrorResponse final : public ProtoMessage { uint64_t address{0}; uint32_t handle{0}; int32_t error{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2142,7 +2142,7 @@ class BluetoothGATTWriteResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2159,7 +2159,7 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2177,7 +2177,7 @@ class BluetoothDevicePairingResponse final : public ProtoMessage { uint64_t address{0}; bool paired{false}; int32_t error{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2195,7 +2195,7 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2213,7 +2213,7 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2231,7 +2231,7 @@ class BluetoothScannerStateResponse final : public ProtoMessage { enums::BluetoothScannerState state{}; enums::BluetoothScannerMode mode{}; enums::BluetoothScannerMode configured_mode{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2277,7 +2277,7 @@ class VoiceAssistantAudioSettings final : public ProtoMessage { uint32_t noise_suppression_level{0}; uint32_t auto_gain{0}; float volume_multiplier{0.0f}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2297,7 +2297,7 @@ class VoiceAssistantRequest final : public ProtoMessage { uint32_t flags{0}; VoiceAssistantAudioSettings audio_settings{}; StringRef wake_word_phrase{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2359,7 +2359,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { const uint8_t *data{nullptr}; uint16_t data_len{0}; bool end{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2417,7 +2417,7 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage { const char *message_name() const override { return "voice_assistant_announce_finished"; } #endif bool success{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2430,7 +2430,7 @@ class VoiceAssistantWakeWord final : public ProtoMessage { StringRef id{}; StringRef wake_word{}; std::vector<std::string> trained_languages{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2480,7 +2480,7 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage { std::vector<VoiceAssistantWakeWord> available_wake_words{}; const std::vector<std::string> *active_wake_words{}; uint32_t max_active_wake_words{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2515,7 +2515,7 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess uint32_t supported_features{0}; bool requires_code{false}; bool requires_code_to_arm{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2531,7 +2531,7 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "alarm_control_panel_state_response"; } #endif enums::AlarmControlPanelState state{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2570,7 +2570,7 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage { uint32_t max_length{0}; StringRef pattern{}; enums::TextMode mode{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2587,7 +2587,7 @@ class TextStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2621,7 +2621,7 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_date_response"; } #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2640,7 +2640,7 @@ class DateStateResponse final : public StateResponseProtoMessage { uint32_t year{0}; uint32_t month{0}; uint32_t day{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2675,7 +2675,7 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_time_response"; } #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2694,7 +2694,7 @@ class TimeStateResponse final : public StateResponseProtoMessage { uint32_t hour{0}; uint32_t minute{0}; uint32_t second{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2731,7 +2731,7 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; const FixedVector<const char *> *event_types{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2747,7 +2747,7 @@ class EventResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "event_response"; } #endif StringRef event_type{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2768,7 +2768,7 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage { bool assumed_state{false}; bool supports_position{false}; bool supports_stop{false}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2785,7 +2785,7 @@ class ValveStateResponse final : public StateResponseProtoMessage { #endif float position{0.0f}; enums::ValveOperation current_operation{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2820,7 +2820,7 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_date_time_response"; } #endif - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2837,7 +2837,7 @@ class DateTimeStateResponse final : public StateResponseProtoMessage { #endif bool missing_state{false}; uint32_t epoch_seconds{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2871,7 +2871,7 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_update_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2895,7 +2895,7 @@ class UpdateStateResponse final : public StateResponseProtoMessage { StringRef title{}; StringRef release_summary{}; StringRef release_url{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2930,7 +2930,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { #endif const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2949,7 +2949,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { enums::ZWaveProxyRequestType type{}; const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2969,7 +2969,7 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_infrared_response"; } #endif uint32_t capabilities{0}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3016,7 +3016,7 @@ class InfraredRFReceiveEvent final : public ProtoMessage { #endif uint32_t key{0}; const std::vector<int32_t> *timings{}; - void encode(ProtoWriteBuffer buffer) const override; + void encode(ProtoWriteBuffer &buffer) const override; void calculate_size(ProtoSize &size) const override; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 764dd3f391..73a3bab12a 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -70,6 +70,21 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size return count; } +#ifdef ESPHOME_DEBUG_API +void ProtoWriteBuffer::debug_check_bounds_(size_t bytes, const char *caller) { + if (this->pos_ + bytes > this->buffer_->data() + this->buffer_->size()) { + ESP_LOGE(TAG, "ProtoWriteBuffer bounds check failed in %s: bytes=%zu offset=%td buf_size=%zu", caller, bytes, + this->pos_ - this->buffer_->data(), this->buffer_->size()); + abort(); + } +} +void ProtoWriteBuffer::debug_check_encode_size_(uint32_t field_id, uint32_t expected, ptrdiff_t actual) { + ESP_LOGE(TAG, "encode_message: size mismatch for field %" PRIu32 ": calculated=%" PRIu32 " actual=%td", field_id, + expected, actual); + abort(); +} +#endif + void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { const uint8_t *ptr = buffer; const uint8_t *end = buffer + length; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 8ac79633cf..4522fc9665 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -217,21 +217,26 @@ class Proto32Bit { class ProtoWriteBuffer { public: - ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer) {} - void write(uint8_t value) { this->buffer_->push_back(value); } + ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} + ProtoWriteBuffer(std::vector<uint8_t> *buffer, size_t write_pos) + : buffer_(buffer), pos_(buffer->data() + write_pos) {} void encode_varint_raw(uint32_t value) { while (value > 0x7F) { - this->buffer_->push_back(static_cast<uint8_t>(value | 0x80)); + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value | 0x80); value >>= 7; } - this->buffer_->push_back(static_cast<uint8_t>(value)); + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value); } void encode_varint_raw_64(uint64_t value) { while (value > 0x7F) { - this->buffer_->push_back(static_cast<uint8_t>(value | 0x80)); + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value | 0x80); value >>= 7; } - this->buffer_->push_back(static_cast<uint8_t>(value)); + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value); } /** * Encode a field key (tag/wire type combination). @@ -245,23 +250,18 @@ class ProtoWriteBuffer { * * Following https://protobuf.dev/programming-guides/encoding/#structure */ - void encode_field_raw(uint32_t field_id, uint32_t type) { - uint32_t val = (field_id << 3) | (type & WIRE_TYPE_MASK); - this->encode_varint_raw(val); - } + void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); } void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { if (len == 0 && !force) return; this->encode_field_raw(field_id, 2); // type 2: Length-delimited string this->encode_varint_raw(len); - - // Using resize + memcpy instead of insert provides significant performance improvement: - // ~10-11x faster for 16-32 byte strings, ~3x faster for 64-byte strings - // as it avoids iterator checks and potential element moves that insert performs - size_t old_size = this->buffer_->size(); - this->buffer_->resize(old_size + len); - std::memcpy(this->buffer_->data() + old_size, string, len); + // Direct memcpy into pre-sized buffer — avoids push_back() per-byte capacity checks + // and vector::insert() iterator overhead. ~10-11x faster for 16-32 byte strings. + this->debug_check_bounds_(len); + std::memcpy(this->pos_, string, len); + this->pos_ += len; } void encode_string(uint32_t field_id, const std::string &value, bool force = false) { this->encode_string(field_id, value.data(), value.size(), force); @@ -288,17 +288,26 @@ class ProtoWriteBuffer { if (!value && !force) return; this->encode_field_raw(field_id, 0); // type 0: Varint - bool - this->buffer_->push_back(value ? 0x01 : 0x00); + this->debug_check_bounds_(1); + *this->pos_++ = value ? 0x01 : 0x00; } - void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { + // noinline: 51 call sites; inlining causes net code growth vs a single out-of-line copy + __attribute__((noinline)) void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { if (value == 0 && !force) return; this->encode_field_raw(field_id, 5); // type 5: 32-bit fixed32 - this->write((value >> 0) & 0xFF); - this->write((value >> 8) & 0xFF); - this->write((value >> 16) & 0xFF); - this->write((value >> 24) & 0xFF); + this->debug_check_bounds_(4); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + // Protobuf fixed32 is little-endian, so direct copy works + std::memcpy(this->pos_, &value, 4); + this->pos_ += 4; +#else + *this->pos_++ = (value >> 0) & 0xFF; + *this->pos_++ = (value >> 8) & 0xFF; + *this->pos_++ = (value >> 16) & 0xFF; + *this->pos_++ = (value >> 24) & 0xFF; +#endif } // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally // not supported to reduce overhead on embedded systems. All ESPHome devices are @@ -334,11 +343,20 @@ class ProtoWriteBuffer { } /// Encode a packed repeated sint32 field (zero-copy from vector) void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values); - void encode_message(uint32_t field_id, const ProtoMessage &value); + /// Encode a nested message field (force=true for repeated, false for singular) + void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = true); std::vector<uint8_t> *get_buffer() const { return buffer_; } protected: +#ifdef ESPHOME_DEBUG_API + void debug_check_bounds_(size_t bytes, const char *caller = __builtin_FUNCTION()); + void debug_check_encode_size_(uint32_t field_id, uint32_t expected, ptrdiff_t actual); +#else + void debug_check_bounds_([[maybe_unused]] size_t bytes) {} +#endif + std::vector<uint8_t> *buffer_; + uint8_t *pos_; }; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -416,9 +434,11 @@ class ProtoMessage { public: virtual ~ProtoMessage() = default; // Default implementation for messages with no fields - virtual void encode(ProtoWriteBuffer buffer) const {} + virtual void encode(ProtoWriteBuffer &buffer) const {} // Default implementation for messages with no fields virtual void calculate_size(ProtoSize &size) const {} + // Convenience: calculate and return size directly (defined after ProtoSize) + uint32_t calculated_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP virtual const char *dump_to(DumpBuffer &out) const = 0; virtual const char *message_name() const { return "unknown"; } @@ -877,6 +897,14 @@ class ProtoSize { } }; +// Implementation of methods that depend on ProtoSize being fully defined + +inline uint32_t ProtoMessage::calculated_size() const { + ProtoSize size; + this->calculate_size(size); + return size.get_size(); +} + // Implementation of encode_packed_sint32 - must be after ProtoSize is defined inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) { if (values.empty()) @@ -897,30 +925,30 @@ inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std: } // Implementation of encode_message - must be after ProtoMessage is defined -inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value) { - this->encode_field_raw(field_id, 2); // type 2: Length-delimited message - +inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value, bool force) { // Calculate the message size first ProtoSize msg_size; value.calculate_size(msg_size); uint32_t msg_length_bytes = msg_size.get_size(); - // Calculate how many bytes the length varint needs - uint32_t varint_length_bytes = ProtoSize::varint(msg_length_bytes); + // Skip empty singular messages (matches add_message_field which skips when nested_size == 0) + // Repeated messages (force=true) are always encoded since an empty item is meaningful + if (msg_length_bytes == 0 && !force) + return; - // Reserve exact space for the length varint - size_t begin = this->buffer_->size(); - this->buffer_->resize(this->buffer_->size() + varint_length_bytes); + this->encode_field_raw(field_id, 2); // type 2: Length-delimited message - // Write the length varint directly - encode_varint_to_buffer(msg_length_bytes, this->buffer_->data() + begin); - - // Now encode the message content - it will append to the buffer - value.encode(*this); + // Write the length varint directly through pos_ + this->encode_varint_raw(msg_length_bytes); + // Encode nested message - pos_ advances directly through the reference #ifdef ESPHOME_DEBUG_API - // Verify that the encoded size matches what we calculated - assert(this->buffer_->size() == begin + varint_length_bytes + msg_length_bytes); + uint8_t *start = this->pos_; + value.encode(*this); + if (static_cast<uint32_t>(this->pos_ - start) != msg_length_bytes) + this->debug_check_encode_size_(field_id, msg_length_bytes, this->pos_ - start); +#else + value.encode(*this); #endif } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 4fbee49dae..cc881caa5c 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -689,6 +689,14 @@ class MessageType(TypeInfo): def encode_func(self) -> str: return "encode_message" + @property + def encode_content(self) -> str: + # Singular message fields pass force=false (skip empty messages) + # The default for encode_nested_message is force=true (for repeated fields) + return ( + f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, false);" + ) + @property def decode_length(self) -> str: # Override to return None for message types because we can't use template-based @@ -2186,7 +2194,7 @@ def build_message_type( # Only generate encode method if this message needs encoding and has fields if needs_encode and encode: - o = f"void {desc.name}::encode(ProtoWriteBuffer buffer) const {{" + o = f"void {desc.name}::encode(ProtoWriteBuffer &buffer) const {{" if len(encode) == 1 and len(encode[0]) + len(o) + 3 < 120: o += f" {encode[0]} }}\n" else: @@ -2194,7 +2202,7 @@ def build_message_type( o += indent("\n".join(encode)) + "\n" o += "}\n" cpp += o - prot = "void encode(ProtoWriteBuffer buffer) const override;" + prot = "void encode(ProtoWriteBuffer &buffer) const override;" public_content.append(prot) # If no fields to encode or message doesn't need encoding, the default implementation in ProtoMessage will be used From 2eac106f119627e2ac58d39f4ebd92990895366a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Mart=C3=ADn?= <contact@rodrigomartin.dev> Date: Sat, 21 Feb 2026 05:20:27 +0100 Subject: [PATCH 0847/2030] [mqtt] add missing precision in HA autodiscovery (#14010) --- esphome/components/mqtt/mqtt_const.h | 1 + esphome/components/mqtt/mqtt_sensor.cpp | 4 ++++ esphome/components/sensor/sensor.h | 2 ++ 3 files changed, 7 insertions(+) diff --git a/esphome/components/mqtt/mqtt_const.h b/esphome/components/mqtt/mqtt_const.h index 221af00371..36a7dfb41a 100644 --- a/esphome/components/mqtt/mqtt_const.h +++ b/esphome/components/mqtt/mqtt_const.h @@ -243,6 +243,7 @@ X(MQTT_STATE_VALUE_TEMPLATE, "stat_val_tpl", "state_value_template") \ X(MQTT_STEP, "step", "step") \ X(MQTT_SUBTYPE, "stype", "subtype") \ + X(MQTT_SUGGESTED_DISPLAY_PRECISION, "sug_dsp_prc", "suggested_display_precision") \ X(MQTT_SUPPORTED_COLOR_MODES, "sup_clrm", "supported_color_modes") \ X(MQTT_SUPPORTED_FEATURES, "sup_feat", "supported_features") \ X(MQTT_SWING_MODE_COMMAND_TEMPLATE, "swing_mode_cmd_tpl", "swing_mode_command_template") \ diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index e83eab6732..a7d311d194 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -49,6 +49,10 @@ void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon root[MQTT_DEVICE_CLASS] = device_class; } + if (this->sensor_->has_accuracy_decimals()) { + root[MQTT_SUGGESTED_DISPLAY_PRECISION] = this->sensor_->get_accuracy_decimals(); + } + const auto unit_of_measurement = this->sensor_->get_unit_of_measurement_ref(); if (!unit_of_measurement.empty()) { root[MQTT_UNIT_OF_MEASUREMENT] = unit_of_measurement; diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index f9a45cb1d0..80981b8e28 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -48,6 +48,8 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa int8_t get_accuracy_decimals(); /// Manually set the accuracy in decimals. void set_accuracy_decimals(int8_t accuracy_decimals); + /// Check if the accuracy in decimals has been manually set. + bool has_accuracy_decimals() const { return this->sensor_flags_.has_accuracy_override; } /// Get the state class, using the manual override if set. StateClass get_state_class(); From 518f08b9097bdb3a980483f1358e309987de7402 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 20 Feb 2026 22:51:13 -1000 Subject: [PATCH 0848/2030] [mipi_dsi] Disallow swap_xy (#14124) --- esphome/components/mipi_dsi/display.py | 26 +++++-------------- .../mipi_dsi/fixtures/mipi_dsi.yaml | 7 ++++- .../mipi_dsi/test_mipi_dsi_config.py | 6 +++-- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index c288b33cd2..de3791b3a4 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -87,38 +87,24 @@ COLOR_DEPTHS = { def model_schema(config): model = MODELS[config[CONF_MODEL].upper()] + model.defaults[CONF_SWAP_XY] = cv.UNDEFINED transform = cv.Schema( { cv.Required(CONF_MIRROR_X): cv.boolean, cv.Required(CONF_MIRROR_Y): cv.boolean, + cv.Optional(CONF_SWAP_XY): cv.invalid( + "Axis swapping not supported by DSI displays" + ), } ) - if model.get_default(CONF_SWAP_XY) != cv.UNDEFINED: - transform = transform.extend( - { - cv.Optional(CONF_SWAP_XY): cv.invalid( - "Axis swapping not supported by this model" - ) - } - ) - else: - transform = transform.extend( - { - cv.Required(CONF_SWAP_XY): cv.boolean, - } - ) # CUSTOM model will need to provide a custom init sequence iseqconf = ( cv.Required(CONF_INIT_SEQUENCE) if model.initsequence is None else cv.Optional(CONF_INIT_SEQUENCE) ) - swap_xy = config.get(CONF_TRANSFORM, {}).get(CONF_SWAP_XY, False) - - # Dimensions are optional if the model has a default width and the swap_xy transform is not overridden - cv_dimensions = ( - cv.Optional if model.get_default(CONF_WIDTH) and not swap_xy else cv.Required - ) + # Dimensions are optional if the model has a default width + cv_dimensions = cv.Optional if model.get_default(CONF_WIDTH) else cv.Required pixel_modes = (PIXEL_MODE_16BIT, PIXEL_MODE_24BIT, "16", "24") schema = display.FULL_DISPLAY_SCHEMA.extend( { diff --git a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml index 7d1fc84121..6de2bd5a77 100644 --- a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml +++ b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml @@ -15,8 +15,13 @@ esp_ldo: display: - platform: mipi_dsi + id: p4_nano model: WAVESHARE-P4-NANO-10.1 - + rotation: 90 + - platform: mipi_dsi + id: p4_86 + model: "WAVESHARE-P4-86-PANEL" + rotation: 180 i2c: sda: GPIO7 scl: GPIO8 diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index f8a9af0279..d465a8c81b 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -119,9 +119,11 @@ def test_code_generation( main_cpp = generate_main(component_fixture_path("mipi_dsi.yaml")) assert ( - "mipi_dsi_mipi_dsi_id = new mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" + "p4_nano = new mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" in main_cpp ) assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp - assert "mipi_dsi_mipi_dsi_id->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp + assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" in main_cpp # assert "backlight_id = new light::LightState(mipi_dsi_dsibacklight_id);" in main_cpp From 6ecb01dedc00595aa2565bcf302cde3d7ad1d4e9 Mon Sep 17 00:00:00 2001 From: Sxt Fov <140247217+sxtfov@users.noreply.github.com> Date: Sat, 21 Feb 2026 14:45:15 +0100 Subject: [PATCH 0849/2030] [cc1101] actions to change general and tuner settings (#14141) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/cc1101/__init__.py | 92 +++++++++++++++++++++++++ esphome/components/cc1101/cc1101.h | 78 ++++++++++++++++++++++ tests/components/cc1101/common.yaml | 96 +++++++++++++++++++++++++++ 3 files changed, 266 insertions(+) diff --git a/esphome/components/cc1101/__init__.py b/esphome/components/cc1101/__init__.py index fbdd7010b4..14b92a18a4 100644 --- a/esphome/components/cc1101/__init__.py +++ b/esphome/components/cc1101/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_DATA, CONF_FREQUENCY, CONF_ID, + CONF_VALUE, CONF_WAIT_TIME, ) from esphome.core import ID @@ -333,3 +334,94 @@ async def send_packet_action_to_code(config, action_id, template_arg, args): arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) cg.add(var.set_data_static(arr, len(data))) return var + + +# Setter action definitions: (setter_name, validator, template_type, enum_map) +_SETTER_ACTIONS = [ + ( + "set_frequency", + cv.All(cv.frequency, cv.float_range(min=300.0e6, max=928.0e6)), + float, + None, + ), + ("set_output_power", cv.float_range(min=-30.0, max=11.0), float, None), + ("set_modulation_type", cv.enum(MODULATION, upper=False), Modulation, MODULATION), + ("set_symbol_rate", cv.float_range(min=600, max=500000), float, None), + ( + "set_rx_attenuation", + cv.enum(RX_ATTENUATION, upper=False), + RxAttenuation, + RX_ATTENUATION, + ), + ("set_dc_blocking_filter", cv.boolean, bool, None), + ("set_manchester", cv.boolean, bool, None), + ( + "set_filter_bandwidth", + cv.All(cv.frequency, cv.float_range(min=58000, max=812000)), + float, + None, + ), + ( + "set_fsk_deviation", + cv.All(cv.frequency, cv.float_range(min=1500, max=381000)), + float, + None, + ), + ("set_msk_deviation", cv.int_range(min=1, max=8), cg.uint8, None), + ("set_channel", cv.uint8_t, cg.uint8, None), + ( + "set_channel_spacing", + cv.All(cv.frequency, cv.float_range(min=25000, max=405000)), + float, + None, + ), + ( + "set_if_frequency", + cv.All(cv.frequency, cv.float_range(min=25000, max=788000)), + float, + None, + ), +] + + +def _register_setter_actions(): + for setter_name, validator, templ_type, enum_map in _SETTER_ACTIONS: + class_name = ( + "".join(word.capitalize() for word in setter_name.split("_")) + "Action" + ) + action_cls = ns.class_( + class_name, automation.Action, cg.Parented.template(CC1101Component) + ) + schema = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(CC1101Component), + cv.Required(CONF_VALUE): cv.templatable(validator), + }, + key=CONF_VALUE, + ) + + async def _setter_action_to_code( + config, + action_id, + template_arg, + args, + _setter=setter_name, + _type=templ_type, + _map=enum_map, + ): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + data = config[CONF_VALUE] + if cg.is_template(data): + templ_ = await cg.templatable(data, args, _type) + cg.add(getattr(var, _setter)(templ_)) + else: + cg.add(getattr(var, _setter)(_map[data] if _map else data)) + return var + + automation.register_action(f"cc1101.{setter_name}", action_cls, schema)( + _setter_action_to_code + ) + + +_register_setter_actions() diff --git a/esphome/components/cc1101/cc1101.h b/esphome/components/cc1101/cc1101.h index e55071e7e3..2efd9e082d 100644 --- a/esphome/components/cc1101/cc1101.h +++ b/esphome/components/cc1101/cc1101.h @@ -161,4 +161,82 @@ template<typename... Ts> class SendPacketAction : public Action<Ts...>, public P size_t data_static_len_{0}; }; +template<typename... Ts> class SetSymbolRateAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, symbol_rate) + void play(const Ts &...x) override { this->parent_->set_symbol_rate(this->symbol_rate_.value(x...)); } +}; + +template<typename... Ts> class SetFrequencyAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, frequency) + void play(const Ts &...x) override { this->parent_->set_frequency(this->frequency_.value(x...)); } +}; + +template<typename... Ts> class SetOutputPowerAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, output_power) + void play(const Ts &...x) override { this->parent_->set_output_power(this->output_power_.value(x...)); } +}; + +template<typename... Ts> class SetModulationTypeAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(Modulation, modulation_type) + void play(const Ts &...x) override { this->parent_->set_modulation_type(this->modulation_type_.value(x...)); } +}; + +template<typename... Ts> class SetRxAttenuationAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(RxAttenuation, rx_attenuation) + void play(const Ts &...x) override { this->parent_->set_rx_attenuation(this->rx_attenuation_.value(x...)); } +}; + +template<typename... Ts> class SetDcBlockingFilterAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(bool, dc_blocking_filter) + void play(const Ts &...x) override { this->parent_->set_dc_blocking_filter(this->dc_blocking_filter_.value(x...)); } +}; + +template<typename... Ts> class SetManchesterAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(bool, manchester) + void play(const Ts &...x) override { this->parent_->set_manchester(this->manchester_.value(x...)); } +}; + +template<typename... Ts> class SetFilterBandwidthAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, filter_bandwidth) + void play(const Ts &...x) override { this->parent_->set_filter_bandwidth(this->filter_bandwidth_.value(x...)); } +}; + +template<typename... Ts> class SetFskDeviationAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, fsk_deviation) + void play(const Ts &...x) override { this->parent_->set_fsk_deviation(this->fsk_deviation_.value(x...)); } +}; + +template<typename... Ts> class SetMskDeviationAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(uint8_t, msk_deviation) + void play(const Ts &...x) override { this->parent_->set_msk_deviation(this->msk_deviation_.value(x...)); } +}; + +template<typename... Ts> class SetChannelAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(uint8_t, channel) + void play(const Ts &...x) override { this->parent_->set_channel(this->channel_.value(x...)); } +}; + +template<typename... Ts> class SetChannelSpacingAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, channel_spacing) + void play(const Ts &...x) override { this->parent_->set_channel_spacing(this->channel_spacing_.value(x...)); } +}; + +template<typename... Ts> class SetIfFrequencyAction : public Action<Ts...>, public Parented<CC1101Component> { + public: + TEMPLATABLE_VALUE(float, if_frequency) + void play(const Ts &...x) override { this->parent_->set_if_frequency(this->if_frequency_.value(x...)); } +}; + } // namespace esphome::cc1101 diff --git a/tests/components/cc1101/common.yaml b/tests/components/cc1101/common.yaml index 42ec50911f..9784bfce8b 100644 --- a/tests/components/cc1101/common.yaml +++ b/tests/components/cc1101/common.yaml @@ -35,3 +35,99 @@ button: data: [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef] - cc1101.send_packet: !lambda |- return {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; + + - cc1101.set_frequency: !lambda |- + return 433.91e6; + - cc1101.set_frequency: + value: "433.91MHz" + - cc1101.set_frequency: + value: 433911000 + - cc1101.set_frequency: 433912000 + + - cc1101.set_output_power: !lambda |- + return -29.9; + - cc1101.set_output_power: + value: "-28" + - cc1101.set_output_power: + value: 10 + - cc1101.set_output_power: 11 + + - cc1101.set_modulation_type: !lambda |- + return cc1101::Modulation::MODULATION_2_FSK; + - cc1101.set_modulation_type: + value: "4-FSK" + - cc1101.set_modulation_type: "GFSK" + + - cc1101.set_symbol_rate: !lambda |- + return 6000.0; + - cc1101.set_symbol_rate: + value: "7000.0" + - cc1101.set_symbol_rate: + value: 8000.0 + - cc1101.set_symbol_rate: 9000 + + - cc1101.set_rx_attenuation: !lambda |- + return cc1101::RxAttenuation::RX_ATTENUATION_0DB; + - cc1101.set_rx_attenuation: + value: "6dB" + - cc1101.set_rx_attenuation: "12dB" + + - cc1101.set_dc_blocking_filter: !lambda |- + return false; + - cc1101.set_dc_blocking_filter: + value: true + - cc1101.set_dc_blocking_filter: false + + - cc1101.set_manchester: !lambda |- + return false; + - cc1101.set_manchester: + value: true + - cc1101.set_manchester: false + + - cc1101.set_filter_bandwidth: !lambda |- + return 58e3; + - cc1101.set_filter_bandwidth: + value: "59kHz" + - cc1101.set_filter_bandwidth: + value: 60000 + - cc1101.set_filter_bandwidth: "61kHz" + + - cc1101.set_fsk_deviation: !lambda |- + return 1.5e3; + - cc1101.set_fsk_deviation: + value: "1.6kHz" + - cc1101.set_fsk_deviation: + value: 1700 + - cc1101.set_fsk_deviation: "1.8kHz" + + - cc1101.set_msk_deviation: !lambda |- + return 1; + - cc1101.set_msk_deviation: + value: "2" + - cc1101.set_msk_deviation: + value: 3 + - cc1101.set_msk_deviation: "4" + + - cc1101.set_channel: !lambda |- + return 0; + - cc1101.set_channel: + value: "1" + - cc1101.set_channel: + value: 3 + - cc1101.set_channel: 3 + + - cc1101.set_channel_spacing: !lambda |- + return 25e3; + - cc1101.set_channel_spacing: + value: "26kHz" + - cc1101.set_channel_spacing: + value: 27000 + - cc1101.set_channel_spacing: "28kHz" + + - cc1101.set_if_frequency: !lambda |- + return 25e3; + - cc1101.set_if_frequency: + value: "26kHz" + - cc1101.set_if_frequency: + value: 27000 + - cc1101.set_if_frequency: "28kHz" From 7fb09da7cf228b3a5d2bbdfd60b3e6fb571b0331 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 11:08:13 -0600 Subject: [PATCH 0850/2030] [dsmr] Add deprecated std::string overload for set_decryption_key (#14180) --- esphome/components/dsmr/dsmr.h | 3 +++ tests/components/dsmr/common.yaml | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index fafcf62b87..dc81ba9b2a 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -64,6 +64,9 @@ class Dsmr : public Component, public uart::UARTDevice { void dump_config() override; void set_decryption_key(const char *decryption_key); + // Remove before 2026.8.0 + ESPDEPRECATED("Pass .c_str() - e.g. set_decryption_key(key.c_str()). Removed in 2026.8.0", "2026.2.0") + void set_decryption_key(const std::string &decryption_key) { this->set_decryption_key(decryption_key.c_str()); } void set_max_telegram_length(size_t length) { this->max_telegram_len_ = length; } void set_request_pin(GPIOPin *request_pin) { this->request_pin_ = request_pin; } void set_request_interval(uint32_t interval) { this->request_interval_ = interval; } diff --git a/tests/components/dsmr/common.yaml b/tests/components/dsmr/common.yaml index 038bf2806b..d11ce37d59 100644 --- a/tests/components/dsmr/common.yaml +++ b/tests/components/dsmr/common.yaml @@ -1,4 +1,13 @@ +esphome: + on_boot: + then: + - lambda: |- + // Test deprecated std::string overload still compiles + std::string key = "00112233445566778899aabbccddeeff"; + id(dsmr_instance).set_decryption_key(key); + dsmr: + id: dsmr_instance decryption_key: 00112233445566778899aabbccddeeff max_telegram_length: 1000 request_pin: ${request_pin} From 416b97311b800e9563e48da0e403ed22e717ff61 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 11:12:35 -0600 Subject: [PATCH 0851/2030] [mqtt] Remove broken ESP8266 ssl_fingerprints option (#14182) --- esphome/__main__.py | 14 --------- esphome/components/mqtt/__init__.py | 21 -------------- .../components/mqtt/mqtt_backend_esp8266.h | 5 ---- .../components/mqtt/mqtt_backend_libretiny.h | 5 ---- esphome/components/mqtt/mqtt_client.cpp | 7 ----- esphome/components/mqtt/mqtt_client.h | 15 ---------- esphome/const.py | 1 - esphome/mqtt.py | 29 ++----------------- 8 files changed, 2 insertions(+), 95 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index c86b5604e1..488955f503 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -944,12 +944,6 @@ def command_clean_all(args: ArgsProtocol) -> int | None: return 0 -def command_mqtt_fingerprint(args: ArgsProtocol, config: ConfigType) -> int | None: - from esphome import mqtt - - return mqtt.get_fingerprint(config) - - def command_version(args: ArgsProtocol) -> int | None: safe_print(f"Version: {const.__version__}") return 0 @@ -1237,7 +1231,6 @@ POST_CONFIG_ACTIONS = { "run": command_run, "clean": command_clean, "clean-mqtt": command_clean_mqtt, - "mqtt-fingerprint": command_mqtt_fingerprint, "idedata": command_idedata, "rename": command_rename, "discover": command_discover, @@ -1451,13 +1444,6 @@ def parse_args(argv): ) parser_wizard.add_argument("configuration", help="Your YAML configuration file.") - parser_fingerprint = subparsers.add_parser( - "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker." - ) - parser_fingerprint.add_argument( - "configuration", help="Your YAML configuration file(s).", nargs="+" - ) - subparsers.add_parser("version", help="Print the ESPHome version and exit.") parser_clean = subparsers.add_parser( diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index fe153fedfa..44e8836487 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -1,5 +1,3 @@ -import re - from esphome import automation from esphome.automation import Condition import esphome.codegen as cg @@ -46,7 +44,6 @@ from esphome.const import ( CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SKIP_CERT_CN_CHECK, - CONF_SSL_FINGERPRINTS, CONF_STATE_TOPIC, CONF_SUBSCRIBE_QOS, CONF_TOPIC, @@ -221,13 +218,6 @@ def validate_config(value): return out -def validate_fingerprint(value): - value = cv.string(value) - if re.match(r"^[0-9a-f]{40}$", value) is None: - raise cv.Invalid("fingerprint must be valid SHA1 hash") - return value - - def _consume_mqtt_sockets(config: ConfigType) -> ConfigType: """Register socket needs for MQTT component.""" # MQTT needs 1 socket for the broker connection @@ -291,9 +281,6 @@ CONFIG_SCHEMA = cv.All( ), validate_message_just_topic, ), - cv.Optional(CONF_SSL_FINGERPRINTS): cv.All( - cv.only_on_esp8266, cv.ensure_list(validate_fingerprint) - ), cv.Optional(CONF_KEEPALIVE, default="15s"): cv.positive_time_period_seconds, cv.Optional( CONF_REBOOT_TIMEOUT, default="15min" @@ -444,14 +431,6 @@ async def to_code(config): if CONF_LEVEL in log_topic: cg.add(var.set_log_level(logger.LOG_LEVELS[log_topic[CONF_LEVEL]])) - if CONF_SSL_FINGERPRINTS in config: - for fingerprint in config[CONF_SSL_FINGERPRINTS]: - arr = [ - cg.RawExpression(f"0x{fingerprint[i : i + 2]}") for i in range(0, 40, 2) - ] - cg.add(var.add_ssl_fingerprint(arr)) - cg.add_build_flag("-DASYNC_TCP_SSL_ENABLED=1") - cg.add(var.set_keep_alive(config[CONF_KEEPALIVE])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) diff --git a/esphome/components/mqtt/mqtt_backend_esp8266.h b/esphome/components/mqtt/mqtt_backend_esp8266.h index 470d1e6a8b..0bf5b510a4 100644 --- a/esphome/components/mqtt/mqtt_backend_esp8266.h +++ b/esphome/components/mqtt/mqtt_backend_esp8266.h @@ -21,11 +21,6 @@ class MQTTBackendESP8266 final : public MQTTBackend { } void set_server(network::IPAddress ip, uint16_t port) final { mqtt_client_.setServer(ip, port); } void set_server(const char *host, uint16_t port) final { mqtt_client_.setServer(host, port); } -#if ASYNC_TCP_SSL_ENABLED - void set_secure(bool secure) { mqtt_client.setSecure(secure); } - void add_server_fingerprint(const uint8_t *fingerprint) { mqtt_client.addServerFingerprint(fingerprint); } -#endif - void set_on_connect(std::function<on_connect_callback_t> &&callback) final { this->mqtt_client_.onConnect(std::move(callback)); } diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h index 24bf018a90..5fa3406193 100644 --- a/esphome/components/mqtt/mqtt_backend_libretiny.h +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -21,11 +21,6 @@ class MQTTBackendLibreTiny final : public MQTTBackend { } void set_server(network::IPAddress ip, uint16_t port) final { mqtt_client_.setServer(IPAddress(ip), port); } void set_server(const char *host, uint16_t port) final { mqtt_client_.setServer(host, port); } -#if ASYNC_TCP_SSL_ENABLED - void set_secure(bool secure) { mqtt_client.setSecure(secure); } - void add_server_fingerprint(const uint8_t *fingerprint) { mqtt_client.addServerFingerprint(fingerprint); } -#endif - void set_on_connect(std::function<on_connect_callback_t> &&callback) final { this->mqtt_client_.onConnect(std::move(callback)); } diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index c433804dd9..1a03c5329e 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -749,13 +749,6 @@ void MQTTClientComponent::set_on_disconnect(mqtt_on_disconnect_callback_t &&call this->on_disconnect_.add(std::move(callback_copy)); } -#if ASYNC_TCP_SSL_ENABLED -void MQTTClientComponent::add_ssl_fingerprint(const std::array<uint8_t, SHA1_SIZE> &fingerprint) { - this->mqtt_backend_.setSecure(true); - this->mqtt_backend_.addServerFingerprint(fingerprint.data()); -} -#endif - MQTTClientComponent *global_mqtt_client = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) // MQTTMessageTrigger diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 21edd53eda..127e4073b0 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -137,21 +137,6 @@ class MQTTClientComponent : public Component { bool is_discovery_enabled() const; bool is_discovery_ip_enabled() const; -#if ASYNC_TCP_SSL_ENABLED - /** Add a SSL fingerprint to use for TCP SSL connections to the MQTT broker. - * - * To use this feature you first have to globally enable the `ASYNC_TCP_SSL_ENABLED` define flag. - * This function can be called multiple times and any certificate that matches any of the provided fingerprints - * will match. Calling this method will also automatically disable all non-ssl connections. - * - * @warning This is *not* secure and *not* how SSL is usually done. You'll have to add - * a separate fingerprint for every certificate you use. Additionally, the hashing - * algorithm used here due to the constraints of the MCU, SHA1, is known to be insecure. - * - * @param fingerprint The SSL fingerprint as a 20 value long std::array. - */ - void add_ssl_fingerprint(const std::array<uint8_t, SHA1_SIZE> &fingerprint); -#endif #ifdef USE_ESP32 void set_ca_certificate(const char *cert) { this->mqtt_backend_.set_ca_certificate(cert); } void set_cl_certificate(const char *cert) { this->mqtt_backend_.set_cl_certificate(cert); } diff --git a/esphome/const.py b/esphome/const.py index f72cbc8893..0179aa129e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -943,7 +943,6 @@ CONF_SPI = "spi" CONF_SPI_ID = "spi_id" CONF_SPIKE_REJECTION = "spike_rejection" CONF_SSID = "ssid" -CONF_SSL_FINGERPRINTS = "ssl_fingerprints" CONF_STARTUP_DELAY = "startup_delay" CONF_STATE = "state" CONF_STATE_CLASS = "state_class" diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 042df12d67..cbf78bd3f6 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -1,6 +1,5 @@ import contextlib from datetime import datetime -import hashlib import json import logging import ssl @@ -22,14 +21,12 @@ from esphome.const import ( CONF_PASSWORD, CONF_PORT, CONF_SKIP_CERT_CN_CHECK, - CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME, ) -from esphome.core import CORE, EsphomeError +from esphome.core import EsphomeError from esphome.helpers import get_int_env, get_str_env -from esphome.log import AnsiFore, color from esphome.types import ConfigType from esphome.util import safe_print @@ -102,9 +99,7 @@ def prepare( elif username: client.username_pw_set(username, password) - if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get( - CONF_CERTIFICATE_AUTHORITY - ): + if config[CONF_MQTT].get(CONF_CERTIFICATE_AUTHORITY): context = ssl.create_default_context( cadata=config[CONF_MQTT].get(CONF_CERTIFICATE_AUTHORITY) ) @@ -283,23 +278,3 @@ def clear_topic(config, topic, username=None, password=None, client_id=None): client.publish(msg.topic, None, retain=True) return initialize(config, [topic], on_message, None, username, password, client_id) - - -# From marvinroger/async-mqtt-client -> scripts/get-fingerprint/get-fingerprint.py -def get_fingerprint(config): - addr = str(config[CONF_MQTT][CONF_BROKER]), int(config[CONF_MQTT][CONF_PORT]) - _LOGGER.info("Getting fingerprint from %s:%s", addr[0], addr[1]) - try: - cert_pem = ssl.get_server_certificate(addr) - except OSError as err: - _LOGGER.error("Unable to connect to server: %s", err) - return 1 - cert_der = ssl.PEM_cert_to_DER_cert(cert_pem) - - sha1 = hashlib.sha1(cert_der).hexdigest() - - safe_print(f"SHA1 Fingerprint: {color(AnsiFore.CYAN, sha1)}") - safe_print( - f"Copy the string above into mqtt.ssl_fingerprints section of {CORE.config_path}" - ) - return 0 From 6ff17fbf7c3d4b24ae0e20103c0828823d49b1dc Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 21 Feb 2026 07:17:54 -1000 Subject: [PATCH 0852/2030] [epaper_spi] Fix color mapping for weact (#14134) --- esphome/components/epaper_spi/epaper_spi.h | 2 +- .../components/epaper_spi/epaper_weact_3c.cpp | 43 ++++++++++++------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/esphome/components/epaper_spi/epaper_spi.h b/esphome/components/epaper_spi/epaper_spi.h index a8c2fe9b56..a743985518 100644 --- a/esphome/components/epaper_spi/epaper_spi.h +++ b/esphome/components/epaper_spi/epaper_spi.h @@ -76,7 +76,7 @@ class EPaperBase : public Display, static uint8_t color_to_bit(Color color) { // It's always a shade of gray. Map to BLACK or WHITE. // We split the luminance at a suitable point - if ((static_cast<int>(color.r) + color.g + color.b) > 512) { + if ((color.r + color.g + color.b) >= 382) { return 1; } return 0; diff --git a/esphome/components/epaper_spi/epaper_weact_3c.cpp b/esphome/components/epaper_spi/epaper_weact_3c.cpp index bd83105dd7..d4dac7076c 100644 --- a/esphome/components/epaper_spi/epaper_weact_3c.cpp +++ b/esphome/components/epaper_spi/epaper_weact_3c.cpp @@ -5,9 +5,24 @@ namespace esphome::epaper_spi { static constexpr const char *const TAG = "epaper_weact_3c"; +enum class BwrState : uint8_t { + BWR_BLACK, + BWR_WHITE, + BWR_RED, +}; + +static BwrState color_to_bwr(Color color) { + if (color.r > color.g + color.b && color.r > 127) { + return BwrState::BWR_RED; + } + if (color.r + color.g + color.b >= 382) { + return BwrState::BWR_WHITE; + } + return BwrState::BWR_BLACK; +} // SSD1680 3-color display notes: // - Buffer uses 1 bit per pixel, 8 pixels per byte -// - Buffer first half (black_offset): Black/White plane (1=black, 0=white) +// - Buffer first half (black_offset): Black/White plane (0=black, 1=white) // - Buffer second half (red_offset): Red plane (1=red, 0=no red) // - Total buffer: width * height / 4 bytes = 2 * (width * height / 8) // - For 128x296: 128*296/4 = 9472 bytes total (4736 per color) @@ -23,20 +38,20 @@ void EPaperWeAct3C::draw_pixel_at(int x, int y, Color color) { // Use luminance threshold for B/W mapping // Split at halfway point (382 = (255*3)/2) - bool is_white = (static_cast<int>(color.r) + color.g + color.b) > 382; + auto bwr = color_to_bwr(color); // Update black/white plane (first half of buffer) - if (is_white) { - // White pixel - clear bit in black plane - this->buffer_[pos] &= ~bit; - } else { - // Black pixel - set bit in black plane + if (bwr == BwrState::BWR_WHITE) { + // White pixel - set bit in black plane this->buffer_[pos] |= bit; + } else { + // Black pixel - clear bit in black plane + this->buffer_[pos] &= ~bit; } // Update red plane (second half of buffer) // Red if red component is dominant (r > g+b) - if (color.r > color.g + color.b) { + if (bwr == BwrState::BWR_RED) { // Red pixel - set bit in red plane this->buffer_[red_offset + pos] |= bit; } else { @@ -53,21 +68,20 @@ void EPaperWeAct3C::fill(Color color) { const size_t half_buffer = this->buffer_length_ / 2u; // Use luminance threshold for B/W mapping - bool is_white = (static_cast<int>(color.r) + color.g + color.b) > 382; - bool is_red = color.r > color.g + color.b; + auto bits = color_to_bwr(color); // Fill both planes - if (is_white) { - // White - both planes = 0x00 + if (bits == BwrState::BWR_BLACK) { + // Black - both planes = 0x00 this->buffer_.fill(0x00); - } else if (is_red) { + } else if (bits == BwrState::BWR_RED) { // Red - black plane = 0x00, red plane = 0xFF for (size_t i = 0; i < half_buffer; i++) this->buffer_[i] = 0x00; for (size_t i = 0; i < half_buffer; i++) this->buffer_[half_buffer + i] = 0xFF; } else { - // Black - black plane = 0xFF, red plane = 0x00 + // White - black plane = 0xFF, red plane = 0x00 for (size_t i = 0; i < half_buffer; i++) this->buffer_[i] = 0xFF; for (size_t i = 0; i < half_buffer; i++) @@ -112,7 +126,6 @@ bool HOT EPaperWeAct3C::transfer_data() { ESP_LOGV(TAG, "transfer_data: buffer_length=%u, half_buffer=%u", buffer_length, half_buffer); // Use a local buffer for SPI transfers - static constexpr size_t MAX_TRANSFER_SIZE = 128; uint8_t bytes_to_send[MAX_TRANSFER_SIZE]; // First, send the RED buffer (0x26 = WRITE_COLOR) From 48ba007c22d7c542e9de8740aacb8c94ac438a10 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sat, 21 Feb 2026 20:16:20 +0100 Subject: [PATCH 0853/2030] [nrf52] print line number after crash in logs (#14165) --- esphome/__main__.py | 19 ++++++++++--- esphome/components/nrf52/__init__.py | 40 ++++++++++++++++++++++++++++ tests/unit_tests/test_main.py | 6 +++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 488955f503..ffedb90bde 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -431,6 +431,14 @@ def run_miniterm(config: ConfigType, port: str, args) -> int: return 1 _LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate) + process_stacktrace = None + + try: + module = importlib.import_module("esphome.components." + CORE.target_platform) + process_stacktrace = getattr(module, "process_stacktrace") + except AttributeError: + pass + backtrace_state = False ser = serial.Serial() ser.baudrate = baud_rate @@ -472,9 +480,14 @@ def run_miniterm(config: ConfigType, port: str, args) -> int: ) safe_print(parser.parse_line(line, time_str)) - backtrace_state = platformio_api.process_stacktrace( - config, line, backtrace_state=backtrace_state - ) + if process_stacktrace: + backtrace_state = process_stacktrace( + config, line, backtrace_state + ) + else: + backtrace_state = platformio_api.process_stacktrace( + config, line, backtrace_state=backtrace_state + ) except serial.SerialException: _LOGGER.error("Serial port closed!") return 0 diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 95e3670124..a12d1db1ab 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -3,6 +3,8 @@ from __future__ import annotations import asyncio import logging from pathlib import Path +import re +import subprocess from esphome import pins import esphome.codegen as cg @@ -380,3 +382,41 @@ def show_logs(config: ConfigType, args, devices: list[str]) -> bool: asyncio.run(logger_connect(address)) return True return False + + +def _addr2line(addr2line: str, elf: Path, addr: str) -> str: + try: + result = subprocess.run( + [addr2line, "-e", elf, addr], + capture_output=True, + text=True, + check=True, + ) + return result.stdout.strip().splitlines()[0] + except Exception as err: # pylint: disable=broad-except + _LOGGER.error("Running command failed: %s", err) + return "" + + +def process_stacktrace(config: ConfigType, line: str, backtrace_state: bool) -> bool: + if "Last crash:" in line: + return True + if backtrace_state: + match = re.search(r"PC=(0x[0-9a-fA-F]+)\s+LR=(0x[0-9a-fA-F]+)", line) + if match: + pc = match.group(1) + lr = match.group(2) + from esphome.analyze_memory.toolchain import find_tool + + addr2line = find_tool("addr2line") + if addr2line is None: + return False + elf = CORE.relative_pioenvs_path(CORE.name, "firmware.elf") + if not elf.exists(): + _LOGGER.warning("%s does not exists", elf) + return False + _LOGGER.error("=== CRASH ===") + _LOGGER.error("PC: %s", _addr2line(addr2line, elf, pc)) + _LOGGER.error("LR: %s", _addr2line(addr2line, elf, lr)) + + return False diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index c9aa446323..cef561c54b 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -2951,6 +2951,7 @@ def test_run_miniterm_batches_lines_with_same_timestamp( mock_serial = MockSerial([chunk, MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, @@ -2989,6 +2990,7 @@ def test_run_miniterm_different_chunks_different_timestamps( mock_serial = MockSerial([chunk1, chunk2, MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, @@ -3019,6 +3021,7 @@ def test_run_miniterm_handles_split_lines() -> None: mock_serial = MockSerial([chunk1, chunk2, MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, @@ -3057,6 +3060,7 @@ def test_run_miniterm_backtrace_state_maintained() -> None: mock_serial = MockSerial([backtrace_chunk, MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, @@ -3122,6 +3126,7 @@ def test_run_miniterm_handles_empty_reads( mock_serial = MockSerial([b"", chunk, b"", MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, @@ -3194,6 +3199,7 @@ def test_run_miniterm_buffer_limit_prevents_unbounded_growth() -> None: mock_serial = MockSerial([large_data_no_newline, final_line, MOCK_SERIAL_END]) + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: PLATFORM_ESP32} config = { CONF_LOGGER: { CONF_BAUD_RATE: 115200, From 9571a979eb7ff1d881a4a833a639ff54c861174e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 13:53:45 -0600 Subject: [PATCH 0854/2030] [ci] Suggest StringRef instead of std::string_view (#14183) --- script/ci-custom.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/script/ci-custom.py b/script/ci-custom.py index 231f587068..df819e0f04 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -494,6 +494,22 @@ def lint_no_byte_datatype(fname, match): ) +@lint_re_check( + r"(?:std\s*::\s*string_view|#include\s*<string_view>)" + CPP_RE_EOL, + include=cpp_include, +) +def lint_no_std_string_view(fname, match): + return ( + f"{highlight('std::string_view')} is not allowed in ESPHome. " + f"It pulls in significant STL template machinery that bloats flash on " + f"resource-constrained embedded targets, does not work well with ArduinoJson, " + f"and duplicates functionality already provided by {highlight('StringRef')}.\n" + f"Please use {highlight('StringRef')} from {highlight('esphome/core/string_ref.h')} " + f"for non-owning string references, or {highlight('const char *')} for simple cases.\n" + f"(If strictly necessary, add `{highlight('// NOLINT')}` to the end of the line)" + ) + + @lint_post_check def lint_constants_usage(): errs = [] From 5a07908dfa9ef499b20e8a53f23e5ea94b9eb682 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 13:54:20 -0600 Subject: [PATCH 0855/2030] [api] Fix build error when lambda returns StringRef in homeassistant.event data (#14187) --- esphome/components/api/homeassistant_service.h | 2 ++ tests/components/homeassistant/common.yaml | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 2322d96eef..340699e1a6 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -36,6 +36,8 @@ template<typename... X> class TemplatableStringValue : public TemplatableValue<s static std::string value_to_string(const char *val) { return std::string(val); } // For lambdas returning .c_str() static std::string value_to_string(const std::string &val) { return val; } static std::string value_to_string(std::string &&val) { return std::move(val); } + static std::string value_to_string(const StringRef &val) { return val.str(); } + static std::string value_to_string(StringRef &&val) { return val.str(); } public: TemplatableStringValue() : TemplatableValue<std::string, X...>() {} diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index 9c6cb71b8b..60e3defd49 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -90,6 +90,19 @@ text_sensor: id: ha_hello_world_text2 attribute: some_attribute +event: + - platform: template + name: Test Event + id: test_event + event_types: + - test_event_type + on_event: + - homeassistant.event: + event: esphome.test_event + data: + event_name: !lambda |- + return event_type; + time: - platform: homeassistant on_time: From e521522b388dce7066ade34d96869187e7c47ca6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 13:54:43 -0600 Subject: [PATCH 0856/2030] [haier] Fix uninitialized HonSettings causing API connection failures (#14188) --- esphome/components/haier/hon_climate.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index a567ab1d89..608d5e7f21 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -29,10 +29,10 @@ enum class CleaningState : uint8_t { enum class HonControlMethod { MONITOR_ONLY = 0, SET_GROUP_PARAMETERS, SET_SINGLE_PARAMETER }; struct HonSettings { - hon_protocol::VerticalSwingMode last_vertiacal_swing; - hon_protocol::HorizontalSwingMode last_horizontal_swing; - bool beeper_state; - bool quiet_mode_state; + hon_protocol::VerticalSwingMode last_vertiacal_swing{hon_protocol::VerticalSwingMode::CENTER}; + hon_protocol::HorizontalSwingMode last_horizontal_swing{hon_protocol::HorizontalSwingMode::CENTER}; + bool beeper_state{true}; + bool quiet_mode_state{false}; }; class HonClimate : public HaierClimateBase { @@ -189,7 +189,7 @@ class HonClimate : public HaierClimateBase { int big_data_sensors_{0}; esphome::optional<hon_protocol::VerticalSwingMode> current_vertical_swing_{}; esphome::optional<hon_protocol::HorizontalSwingMode> current_horizontal_swing_{}; - HonSettings settings_; + HonSettings settings_{}; ESPPreferenceObject hon_rtc_; SwitchState quiet_mode_state_{SwitchState::OFF}; }; From 6f198adb0c79bcc8e14cdb07cbf484bb23aa1e52 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 14:29:50 -0600 Subject: [PATCH 0857/2030] [scheduler] Reduce lock acquisitions in process_defer_queue_ (#14107) --- esphome/core/scheduler.cpp | 23 +++++++++++ esphome/core/scheduler.h | 79 ++++++++++++++++++-------------------- 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index e82efcc520..b810df7e1c 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -421,6 +421,29 @@ void Scheduler::full_cleanup_removed_items_() { this->to_remove_ = 0; } +#ifndef ESPHOME_THREAD_SINGLE +void Scheduler::compact_defer_queue_locked_() { + // Rare case: new items were added during processing - compact the vector + // This only happens when: + // 1. A deferred callback calls defer() again, or + // 2. Another thread calls defer() while we're processing + // + // Move unprocessed items (added during this loop) to the front for next iteration + // + // SAFETY: Compacted items may include cancelled items (marked for removal via + // cancel_item_locked_() during execution). This is safe because should_skip_item_() + // checks is_item_removed_() before executing, so cancelled items will be skipped + // and recycled on the next loop iteration. + size_t remaining = this->defer_queue_.size() - this->defer_queue_front_; + for (size_t i = 0; i < remaining; i++) { + this->defer_queue_[i] = std::move(this->defer_queue_[this->defer_queue_front_ + i]); + } + // Use erase() instead of resize() to avoid instantiating _M_default_append + // (saves ~156 bytes flash). Erasing from the end is O(1) - no shifting needed. + this->defer_queue_.erase(this->defer_queue_.begin() + remaining, this->defer_queue_.end()); +} +#endif /* not ESPHOME_THREAD_SINGLE */ + void HOT Scheduler::call(uint32_t now) { #ifndef ESPHOME_THREAD_SINGLE this->process_defer_queue_(now); diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index afe11aaca6..041c6f4687 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -387,41 +387,46 @@ class Scheduler { // No lock needed: single consumer (main loop), stale read just means we process less this iteration size_t defer_queue_end = this->defer_queue_.size(); + // Fast path: nothing to process, avoid lock entirely. + // Safe without lock: single consumer (main loop) reads front_, and a stale size() read + // from a concurrent push can only make us see fewer items — they'll be processed next loop. + if (this->defer_queue_front_ >= defer_queue_end) + return; + + // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), + // recycle each item after re-acquiring the lock for the next iteration (N+1 total). + // The lock is held across: recycle → loop condition → move-out, then released for execution. + std::unique_ptr<SchedulerItem> item; + + this->lock_.lock(); while (this->defer_queue_front_ < defer_queue_end) { - std::unique_ptr<SchedulerItem> item; - { - LockGuard lock(this->lock_); - // SAFETY: Moving out the unique_ptr leaves a nullptr in the vector at defer_queue_front_. - // This is intentional and safe because: - // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function - // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_ - // and has_cancelled_timeout_in_container_locked_ in scheduler.h) - // 3. The lock protects concurrent access, but the nullptr remains until cleanup - item = std::move(this->defer_queue_[this->defer_queue_front_]); - this->defer_queue_front_++; - } + // SAFETY: Moving out the unique_ptr leaves a nullptr in the vector at defer_queue_front_. + // This is intentional and safe because: + // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function + // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_ + // and has_cancelled_timeout_in_container_locked_ in scheduler.h) + // 3. The lock protects concurrent access, but the nullptr remains until cleanup + item = std::move(this->defer_queue_[this->defer_queue_front_]); + this->defer_queue_front_++; + this->lock_.unlock(); // Execute callback without holding lock to prevent deadlocks // if the callback tries to call defer() again if (!this->should_skip_item_(item.get())) { now = this->execute_item_(item.get(), now); } - // Recycle the defer item after execution - { - LockGuard lock(this->lock_); - this->recycle_item_main_loop_(std::move(item)); - } - } - // If we've consumed all items up to the snapshot point, clean up the dead space - // Single consumer (main loop), so no lock needed for this check - if (this->defer_queue_front_ >= defer_queue_end) { - LockGuard lock(this->lock_); - this->cleanup_defer_queue_locked_(); + this->lock_.lock(); + this->recycle_item_main_loop_(std::move(item)); } + // Clean up the queue (lock already held from last recycle or initial acquisition) + this->cleanup_defer_queue_locked_(); + this->lock_.unlock(); } - // Helper to cleanup defer_queue_ after processing + // Helper to cleanup defer_queue_ after processing. + // Keeps the common clear() path inline, outlines the rare compaction to keep + // cold code out of the hot instruction cache lines. // IMPORTANT: Caller must hold the scheduler lock before calling this function. inline void cleanup_defer_queue_locked_() { // Check if new items were added by producers during processing @@ -429,27 +434,17 @@ class Scheduler { // Common case: no new items - clear everything this->defer_queue_.clear(); } else { - // Rare case: new items were added during processing - compact the vector - // This only happens when: - // 1. A deferred callback calls defer() again, or - // 2. Another thread calls defer() while we're processing - // - // Move unprocessed items (added during this loop) to the front for next iteration - // - // SAFETY: Compacted items may include cancelled items (marked for removal via - // cancel_item_locked_() during execution). This is safe because should_skip_item_() - // checks is_item_removed_() before executing, so cancelled items will be skipped - // and recycled on the next loop iteration. - size_t remaining = this->defer_queue_.size() - this->defer_queue_front_; - for (size_t i = 0; i < remaining; i++) { - this->defer_queue_[i] = std::move(this->defer_queue_[this->defer_queue_front_ + i]); - } - // Use erase() instead of resize() to avoid instantiating _M_default_append - // (saves ~156 bytes flash). Erasing from the end is O(1) - no shifting needed. - this->defer_queue_.erase(this->defer_queue_.begin() + remaining, this->defer_queue_.end()); + // Rare case: new items were added during processing - outlined to keep cold code + // out of the hot instruction cache lines + this->compact_defer_queue_locked_(); } this->defer_queue_front_ = 0; } + + // Cold path for compacting defer_queue_ when new items were added during processing. + // IMPORTANT: Caller must hold the scheduler lock before calling this function. + // IMPORTANT: Must not be inlined - rare path, outlined to keep it out of the hot instruction cache lines. + void __attribute__((noinline)) compact_defer_queue_locked_(); #endif /* not ESPHOME_THREAD_SINGLE */ // Helper to check if item is marked for removal (platform-specific) From 462ac2956312f21e506b1e2e13a6960e18d0d813 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 17:29:41 -0600 Subject: [PATCH 0858/2030] [scheduler] Use relaxed memory ordering for atomic reads under lock (#14140) --- esphome/core/scheduler.cpp | 10 +++++----- esphome/core/scheduler.h | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index b810df7e1c..36b65f6ff7 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -406,7 +406,7 @@ void Scheduler::full_cleanup_removed_items_() { // Compact in-place: move valid items forward, recycle removed ones size_t write = 0; for (size_t read = 0; read < this->items_.size(); ++read) { - if (!is_item_removed_(this->items_[read].get())) { + if (!is_item_removed_locked_(this->items_[read].get())) { if (write != read) { this->items_[write] = std::move(this->items_[read]); } @@ -531,7 +531,7 @@ void HOT Scheduler::call(uint32_t now) { // Multi-threaded platforms without atomics: must take lock to safely read remove flag { LockGuard guard{this->lock_}; - if (is_item_removed_(item.get())) { + if (is_item_removed_locked_(item.get())) { this->recycle_item_main_loop_(this->pop_raw_locked_()); this->to_remove_--; continue; @@ -568,7 +568,7 @@ void HOT Scheduler::call(uint32_t now) { // during the function call and know if we were cancelled. auto executed_item = this->pop_raw_locked_(); - if (executed_item->remove) { + if (this->is_item_removed_locked_(executed_item.get())) { // We were removed/cancelled in the function call, recycle and continue this->to_remove_--; this->recycle_item_main_loop_(std::move(executed_item)); @@ -595,7 +595,7 @@ void HOT Scheduler::call(uint32_t now) { void HOT Scheduler::process_to_add() { LockGuard guard{this->lock_}; for (auto &it : this->to_add_) { - if (is_item_removed_(it.get())) { + if (is_item_removed_locked_(it.get())) { // Recycle cancelled items this->recycle_item_main_loop_(std::move(it)); continue; @@ -628,7 +628,7 @@ size_t HOT Scheduler::cleanup_() { LockGuard guard{this->lock_}; while (!this->items_.empty()) { auto &item = this->items_[0]; - if (!item->remove) + if (!this->is_item_removed_locked_(item.get())) break; this->to_remove_--; this->recycle_item_main_loop_(this->pop_raw_locked_()); diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 041c6f4687..384d76b6b0 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -314,8 +314,8 @@ class Scheduler { // Fixes: https://github.com/esphome/esphome/issues/11940 if (!item) return false; - if (item->component != component || item->type != type || (skip_removed && item->remove) || - (match_retry && !item->is_retry)) { + if (item->component != component || item->type != type || + (skip_removed && this->is_item_removed_locked_(item.get())) || (match_retry && !item->is_retry)) { return false; } // Name type must match @@ -463,6 +463,18 @@ class Scheduler { #endif } + // Helper to check if item is marked for removal when lock is already held. + // Uses relaxed ordering since the mutex provides all necessary synchronization. + // IMPORTANT: Caller must hold the scheduler lock before calling this function. + bool is_item_removed_locked_(SchedulerItem *item) const { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + // Lock already held - relaxed is sufficient, mutex provides ordering + return item->remove.load(std::memory_order_relaxed); +#else + return item->remove; +#endif + } + // Helper to set item removal flag (platform-specific) // For ESPHOME_THREAD_MULTI_NO_ATOMICS platforms, the caller must hold the scheduler lock before calling this // function. Uses memory_order_release when setting to true (for cancellation synchronization), @@ -519,7 +531,7 @@ class Scheduler { // it will iterate over these nullptr items. This check prevents crashes. if (!item) continue; - if (is_item_removed_(item.get()) && + if (this->is_item_removed_locked_(item.get()) && this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, match_retry, /* skip_removed= */ false)) { return true; From a4682615234ac61ff7825e2a922807b11e6772fa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 19:41:26 -0600 Subject: [PATCH 0859/2030] [scheduler] De-template and consolidate scheduler helper functions (#14164) --- esphome/core/scheduler.cpp | 14 +++++++++---- esphome/core/scheduler.h | 41 +++++++------------------------------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 36b65f6ff7..e4e0751e10 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -119,10 +119,16 @@ uint32_t Scheduler::calculate_interval_offset_(uint32_t delay) { // Remove before 2026.8.0 along with all retry code bool Scheduler::is_retry_cancelled_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id) { - return has_cancelled_timeout_in_container_locked_(this->items_, component, name_type, static_name, hash_or_id, - /* match_retry= */ true) || - has_cancelled_timeout_in_container_locked_(this->to_add_, component, name_type, static_name, hash_or_id, - /* match_retry= */ true); + for (auto *container : {&this->items_, &this->to_add_}) { + for (auto &item : *container) { + if (item && this->is_item_removed_locked_(item.get()) && + this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, + /* match_retry= */ true, /* skip_removed= */ false)) { + return true; + } + } + } + return false; } // Common implementation for both timeout and interval diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 384d76b6b0..16b0ded312 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -308,8 +308,8 @@ class Scheduler { SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const { // THREAD SAFETY: Check for nullptr first to prevent LoadProhibited crashes. On multi-threaded // platforms, items can be moved out of defer_queue_ during processing, leaving nullptr entries. - // PR #11305 added nullptr checks in callers (mark_matching_items_removed_locked_() and - // has_cancelled_timeout_in_container_locked_()), but this check provides defense-in-depth: helper + // PR #11305 added nullptr checks in callers (mark_matching_items_removed_locked_()), but this check + // provides defense-in-depth: helper // functions should be safe regardless of caller behavior. // Fixes: https://github.com/esphome/esphome/issues/11940 if (!item) @@ -403,8 +403,7 @@ class Scheduler { // SAFETY: Moving out the unique_ptr leaves a nullptr in the vector at defer_queue_front_. // This is intentional and safe because: // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function - // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_ - // and has_cancelled_timeout_in_container_locked_ in scheduler.h) + // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_) // 3. The lock protects concurrent access, but the nullptr remains until cleanup item = std::move(this->defer_queue_[this->defer_queue_front_]); this->defer_queue_front_++; @@ -497,19 +496,16 @@ class Scheduler { // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal // IMPORTANT: Must be called with scheduler lock held - template<typename Container> - size_t mark_matching_items_removed_locked_(Container &container, Component *component, NameType name_type, - const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, - bool match_retry) { + size_t mark_matching_items_removed_locked_(std::vector<std::unique_ptr<SchedulerItem>> &container, + Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { size_t count = 0; for (auto &item : container) { // Skip nullptr items (can happen in defer_queue_ when items are being processed) // The defer_queue_ uses index-based processing: items are std::moved out but left in the // vector as nullptr until cleanup. Even though this function is called with lock held, // the vector can still contain nullptr items from the processing loop. This check prevents crashes. - if (!item) - continue; - if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { + if (item && this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { this->set_item_removed_(item.get(), true); count++; } @@ -517,29 +513,6 @@ class Scheduler { return count; } - // Template helper to check if any item in a container matches our criteria - // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id - // IMPORTANT: Must be called with scheduler lock held - template<typename Container> - bool has_cancelled_timeout_in_container_locked_(const Container &container, Component *component, NameType name_type, - const char *static_name, uint32_t hash_or_id, - bool match_retry) const { - for (const auto &item : container) { - // Skip nullptr items (can happen in defer_queue_ when items are being processed) - // The defer_queue_ uses index-based processing: items are std::moved out but left in the - // vector as nullptr until cleanup. If this function is called during defer queue processing, - // it will iterate over these nullptr items. This check prevents crashes. - if (!item) - continue; - if (this->is_item_removed_locked_(item.get()) && - this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, - match_retry, /* skip_removed= */ false)) { - return true; - } - } - return false; - } - Mutex lock_; std::vector<std::unique_ptr<SchedulerItem>> items_; std::vector<std::unique_ptr<SchedulerItem>> to_add_; From d5c9c56fdfcdd0112e1913f05f84e297908460a7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 19:41:43 -0600 Subject: [PATCH 0860/2030] [platformio] Add exponential backoff and session reset to download retries (#14191) --- esphome/platformio_api.py | 41 ++++- tests/unit_tests/test_platformio_api.py | 196 +++++++++++++++++++++++- 2 files changed, 231 insertions(+), 6 deletions(-) diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index d42f89d029..5d4065207f 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -5,6 +5,7 @@ import os from pathlib import Path import re import subprocess +import time from typing import Any from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME, KEY_CORE @@ -44,31 +45,61 @@ def patch_structhash(): def patch_file_downloader(): - """Patch PlatformIO's FileDownloader to retry on PackageException errors.""" + """Patch PlatformIO's FileDownloader to retry on PackageException errors. + + PlatformIO's FileDownloader uses HTTPSession which lacks built-in retry + for 502/503 errors. We add retries with exponential backoff and close the + session between attempts to force a fresh TCP connection, which may route + to a different CDN edge node. + """ from platformio.package.download import FileDownloader from platformio.package.exception import PackageException + if getattr(FileDownloader.__init__, "_esphome_patched", False): + return + original_init = FileDownloader.__init__ def patched_init(self, *args: Any, **kwargs: Any) -> None: - max_retries = 3 + max_retries = 5 for attempt in range(max_retries): try: - return original_init(self, *args, **kwargs) + original_init(self, *args, **kwargs) + return except PackageException as e: if attempt < max_retries - 1: + # Exponential backoff: 2, 4, 8, 16 seconds + delay = 2 ** (attempt + 1) _LOGGER.warning( - "Package download failed: %s. Retrying... (attempt %d/%d)", + "Package download failed: %s. " + "Retrying in %d seconds... (attempt %d/%d)", str(e), + delay, attempt + 1, max_retries, ) + # Close the response and session to free resources + # and force a new TCP connection on retry, which may + # route to a different CDN edge node + # pylint: disable=protected-access,broad-except + try: + if ( + hasattr(self, "_http_response") + and self._http_response is not None + ): + self._http_response.close() + if hasattr(self, "_http_session"): + self._http_session.close() + except Exception: + pass + # pylint: enable=protected-access,broad-except + time.sleep(delay) else: # Final attempt - re-raise raise - return None + patched_init._esphome_patched = True # type: ignore[attr-defined] # pylint: disable=protected-access FileDownloader.__init__ = patched_init diff --git a/tests/unit_tests/test_platformio_api.py b/tests/unit_tests/test_platformio_api.py index 4d7b635e59..1686144277 100644 --- a/tests/unit_tests/test_platformio_api.py +++ b/tests/unit_tests/test_platformio_api.py @@ -6,7 +6,7 @@ import os from pathlib import Path import shutil from types import SimpleNamespace -from unittest.mock import MagicMock, Mock, patch +from unittest.mock import MagicMock, Mock, call, patch import pytest @@ -673,6 +673,200 @@ def test_process_stacktrace_bad_alloc( assert state is False +def test_patch_file_downloader_succeeds_first_try() -> None: + """Test patch_file_downloader succeeds on first attempt.""" + mock_exception_cls = type("PackageException", (Exception,), {}) + original_init = MagicMock() + + with patch.dict( + "sys.modules", + { + "platformio": MagicMock(), + "platformio.package": MagicMock(), + "platformio.package.download": SimpleNamespace( + FileDownloader=type("FileDownloader", (), {"__init__": original_init}) + ), + "platformio.package.exception": SimpleNamespace( + PackageException=mock_exception_cls + ), + }, + ): + platformio_api.patch_file_downloader() + + from platformio.package.download import FileDownloader + + instance = object.__new__(FileDownloader) + FileDownloader.__init__(instance, "http://example.com/file.zip") + + original_init.assert_called_once() + + +def test_patch_file_downloader_retries_on_failure() -> None: + """Test patch_file_downloader retries with backoff on PackageException.""" + mock_exception_cls = type("PackageException", (Exception,), {}) + call_count = 0 + + def failing_init(self, *args, **kwargs): + nonlocal call_count + call_count += 1 + if call_count < 3: + raise mock_exception_cls(f"502 error attempt {call_count}") + + with ( + patch.dict( + "sys.modules", + { + "platformio": MagicMock(), + "platformio.package": MagicMock(), + "platformio.package.download": SimpleNamespace( + FileDownloader=type( + "FileDownloader", (), {"__init__": failing_init} + ) + ), + "platformio.package.exception": SimpleNamespace( + PackageException=mock_exception_cls + ), + }, + ), + patch("time.sleep") as mock_sleep, + ): + platformio_api.patch_file_downloader() + + from platformio.package.download import FileDownloader + + instance = object.__new__(FileDownloader) + FileDownloader.__init__(instance, "http://example.com/file.zip") + + # Should have been called 3 times (2 failures + 1 success) + assert call_count == 3 + + # Should have slept with exponential backoff: 2s, 4s + assert mock_sleep.call_count == 2 + mock_sleep.assert_any_call(2) + mock_sleep.assert_any_call(4) + + +def test_patch_file_downloader_raises_after_max_retries() -> None: + """Test patch_file_downloader raises after exhausting all retries.""" + mock_exception_cls = type("PackageException", (Exception,), {}) + + def always_failing_init(self, *args, **kwargs): + raise mock_exception_cls("502 error") + + with ( + patch.dict( + "sys.modules", + { + "platformio": MagicMock(), + "platformio.package": MagicMock(), + "platformio.package.download": SimpleNamespace( + FileDownloader=type( + "FileDownloader", (), {"__init__": always_failing_init} + ) + ), + "platformio.package.exception": SimpleNamespace( + PackageException=mock_exception_cls + ), + }, + ), + patch("time.sleep") as mock_sleep, + ): + platformio_api.patch_file_downloader() + + from platformio.package.download import FileDownloader + + instance = object.__new__(FileDownloader) + with pytest.raises(mock_exception_cls, match="502 error"): + FileDownloader.__init__(instance, "http://example.com/file.zip") + + # Should have slept 4 times (before attempts 2-5), not on final attempt + assert mock_sleep.call_count == 4 + mock_sleep.assert_has_calls([call(2), call(4), call(8), call(16)]) + + +def test_patch_file_downloader_closes_session_and_response_between_retries() -> None: + """Test patch_file_downloader closes HTTP session and response between retries.""" + mock_exception_cls = type("PackageException", (Exception,), {}) + mock_session = MagicMock() + mock_response = MagicMock() + call_count = 0 + + def failing_init_with_session(self, *args, **kwargs): + nonlocal call_count + call_count += 1 + self._http_session = mock_session + self._http_response = mock_response + if call_count < 2: + raise mock_exception_cls("502 error") + + with ( + patch.dict( + "sys.modules", + { + "platformio": MagicMock(), + "platformio.package": MagicMock(), + "platformio.package.download": SimpleNamespace( + FileDownloader=type( + "FileDownloader", + (), + {"__init__": failing_init_with_session}, + ) + ), + "platformio.package.exception": SimpleNamespace( + PackageException=mock_exception_cls + ), + }, + ), + patch("time.sleep"), + ): + platformio_api.patch_file_downloader() + + from platformio.package.download import FileDownloader + + instance = object.__new__(FileDownloader) + FileDownloader.__init__(instance, "http://example.com/file.zip") + + # Both response and session should have been closed between retries + mock_response.close.assert_called_once() + mock_session.close.assert_called_once() + + +def test_patch_file_downloader_idempotent() -> None: + """Test patch_file_downloader does not stack wrappers when called multiple times.""" + mock_exception_cls = type("PackageException", (Exception,), {}) + call_count = 0 + + def counting_init(self, *args, **kwargs): + nonlocal call_count + call_count += 1 + + with patch.dict( + "sys.modules", + { + "platformio": MagicMock(), + "platformio.package": MagicMock(), + "platformio.package.download": SimpleNamespace( + FileDownloader=type("FileDownloader", (), {"__init__": counting_init}) + ), + "platformio.package.exception": SimpleNamespace( + PackageException=mock_exception_cls + ), + }, + ): + # Patch multiple times + platformio_api.patch_file_downloader() + platformio_api.patch_file_downloader() + platformio_api.patch_file_downloader() + + from platformio.package.download import FileDownloader + + instance = object.__new__(FileDownloader) + FileDownloader.__init__(instance, "http://example.com/file.zip") + + # Should only be called once, not 3 times from stacked wrappers + assert call_count == 1 + + def test_platformio_log_filter_allows_non_platformio_messages() -> None: """Test that non-platformio logger messages are allowed through.""" log_filter = platformio_api.PlatformioLogFilter() From 49e4ae54beb20f7de57a24274c851c13a382d0e4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 23:22:59 -0600 Subject: [PATCH 0861/2030] [bme68x_bsec2] Fix compilation on ESP32 Arduino (#14194) --- esphome/components/bme68x_bsec2/__init__.py | 5 ++++- tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml diff --git a/esphome/components/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py index e421efb2d6..4200b2f0b8 100644 --- a/esphome/components/bme68x_bsec2/__init__.py +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -178,8 +178,11 @@ async def to_code_base(config): bsec2_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_bsec2_configuration(bsec2_arr, len(rhs))) - # Although this component does not use SPI, the BSEC2 Arduino library requires the SPI library + # The BSEC2 and BME68x Arduino libraries unconditionally include Wire.h and + # SPI.h in their source files, so these libraries must be available even though + # ESPHome uses its own I2C/SPI abstractions instead of the Arduino ones. if core.CORE.using_arduino: + cg.add_library("Wire", None) cg.add_library("SPI", None) cg.add_library( "BME68x Sensor library", diff --git a/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml new file mode 100644 index 0000000000..7c503b0ccb --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml + +<<: !include common.yaml From e013b4867519c44b570fd6cf05872a7324845009 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sun, 22 Feb 2026 06:44:06 +0100 Subject: [PATCH 0862/2030] [nextion] Add error log for failed HTTP status during TFT upload (#14190) --- esphome/components/nextion/nextion_upload_arduino.cpp | 1 + esphome/components/nextion/nextion_upload_esp32.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index 220c75f9d3..a433eff883 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -220,6 +220,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } if (code != 200 and code != 206) { + ESP_LOGE(TAG, "HTTP request failed with status %d", code); return this->upload_end_(false); } diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index c4e6ff7182..46352afd75 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -238,6 +238,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { esp_get_free_heap_size()); int status_code = esp_http_client_get_status_code(http_client); if (status_code != 200 && status_code != 206) { + ESP_LOGE(TAG, "HTTP request failed with status %d", status_code); return this->upload_end_(false); } From 1753074eef3ea117dff2cb02995330227b242379 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 15:01:07 -0600 Subject: [PATCH 0863/2030] [web_server_base] Remove unnecessary Component inheritance and modernize (#14204) --- esphome/components/web_server_base/__init__.py | 3 +-- .../web_server_base/web_server_base.cpp | 18 ++---------------- .../web_server_base/web_server_base.h | 18 +++++++----------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 7986ac964d..183b907ae6 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -20,7 +20,7 @@ def AUTO_LOAD(): web_server_base_ns = cg.esphome_ns.namespace("web_server_base") -WebServerBase = web_server_base_ns.class_("WebServerBase", cg.Component) +WebServerBase = web_server_base_ns.class_("WebServerBase") CONF_WEB_SERVER_BASE_ID = "web_server_base_id" CONFIG_SCHEMA = cv.Schema( @@ -33,7 +33,6 @@ CONFIG_SCHEMA = cv.Schema( @coroutine_with_priority(CoroPriority.WEB_SERVER_BASE) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - await cg.register_component(var, config) cg.add(cg.RawExpression(f"{web_server_base_ns}::global_web_server_base = {var}")) if CORE.is_esp32: diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index 6e7097338c..dbbcd10d8d 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -1,19 +1,11 @@ #include "web_server_base.h" #ifdef USE_NETWORK -#include "esphome/core/application.h" -#include "esphome/core/helpers.h" -#include "esphome/core/log.h" -namespace esphome { -namespace web_server_base { - -static const char *const TAG = "web_server_base"; +namespace esphome::web_server_base { WebServerBase *global_web_server_base = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) void WebServerBase::add_handler(AsyncWebHandler *handler) { - // remove all handlers - #ifdef USE_WEBSERVER_AUTH if (!credentials_.username.empty()) { handler = new internal::AuthMiddlewareHandler(handler, &credentials_); @@ -25,11 +17,5 @@ void WebServerBase::add_handler(AsyncWebHandler *handler) { } } -float WebServerBase::get_setup_priority() const { - // Before WiFi (captive portal) - return setup_priority::WIFI + 2.0f; -} - -} // namespace web_server_base -} // namespace esphome +} // namespace esphome::web_server_base #endif diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 0c25467f1b..54421c851e 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -1,11 +1,9 @@ #pragma once #include "esphome/core/defines.h" #ifdef USE_NETWORK -#include <memory> #include <utility> #include <vector> -#include "esphome/core/component.h" #include "esphome/core/progmem.h" #if USE_ESP32 @@ -21,8 +19,7 @@ using PlatformString = std::string; using PlatformString = String; #endif -namespace esphome { -namespace web_server_base { +namespace esphome::web_server_base { class WebServerBase; extern WebServerBase *global_web_server_base; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -91,14 +88,14 @@ class AuthMiddlewareHandler : public MiddlewareHandler { } // namespace internal -class WebServerBase : public Component { +class WebServerBase { public: void init() { if (this->initialized_) { this->initialized_++; return; } - this->server_ = std::make_unique<AsyncWebServer>(this->port_); + this->server_ = new AsyncWebServer(this->port_); // All content is controlled and created by user - so allowing all origins is fine here. // NOTE: Currently 1 header. If more are added, update in __init__.py: // cg.add_define("WEB_SERVER_DEFAULT_HEADERS_COUNT", 1) @@ -113,11 +110,11 @@ class WebServerBase : public Component { void deinit() { this->initialized_--; if (this->initialized_ == 0) { + delete this->server_; this->server_ = nullptr; } } - AsyncWebServer *get_server() const { return this->server_.get(); } - float get_setup_priority() const override; + AsyncWebServer *get_server() const { return this->server_; } #ifdef USE_WEBSERVER_AUTH void set_auth_username(std::string auth_username) { credentials_.username = std::move(auth_username); } @@ -132,13 +129,12 @@ class WebServerBase : public Component { protected: int initialized_{0}; uint16_t port_{80}; - std::unique_ptr<AsyncWebServer> server_{nullptr}; + AsyncWebServer *server_{nullptr}; std::vector<AsyncWebHandler *> handlers_; #ifdef USE_WEBSERVER_AUTH internal::Credentials credentials_; #endif }; -} // namespace web_server_base -} // namespace esphome +} // namespace esphome::web_server_base #endif From 509f06afac19fc54b3fae2a67802771312b91133 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 15:56:09 -0600 Subject: [PATCH 0864/2030] [network] Improve IPAddress::str() deprecation warning with usage example (#14195) --- esphome/components/network/ip_address.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index d0ac8164af..b2a2c563e2 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -61,7 +61,9 @@ struct IPAddress { IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); } IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; } // Remove before 2026.8.0 - ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") + ESPDEPRECATED( + "str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0", + "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); @@ -150,7 +152,9 @@ struct IPAddress { bool is_ip6() const { return IP_IS_V6(&ip_addr_); } bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); } // Remove before 2026.8.0 - ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") + ESPDEPRECATED( + "str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0", + "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); From ede2da2fbc167814c5598adb6d866c239a0772c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 15:57:23 -0600 Subject: [PATCH 0865/2030] [core] Conditionally compile get_loop_priority with USE_LOOP_PRIORITY (#14210) --- esphome/components/ch422g/ch422g.cpp | 2 ++ esphome/components/ch422g/ch422g.h | 2 ++ esphome/components/ch423/ch423.cpp | 2 ++ esphome/components/ch423/ch423.h | 2 ++ esphome/components/deep_sleep/deep_sleep_component.cpp | 2 ++ esphome/components/deep_sleep/deep_sleep_component.h | 2 ++ esphome/components/pca9554/pca9554.cpp | 2 ++ esphome/components/pca9554/pca9554.h | 2 ++ esphome/components/pcf8574/pcf8574.cpp | 2 ++ esphome/components/pcf8574/pcf8574.h | 2 ++ esphome/components/status_led/light/status_led_light.h | 2 ++ esphome/components/status_led/status_led.cpp | 2 ++ esphome/components/status_led/status_led.h | 2 ++ esphome/components/wifi/__init__.py | 7 +++++++ esphome/components/wifi/wifi_component.cpp | 2 ++ esphome/components/wifi/wifi_component.h | 2 ++ esphome/core/application.cpp | 2 ++ esphome/core/component.cpp | 2 ++ esphome/core/component.h | 3 +++ esphome/core/defines.h | 1 + 20 files changed, 45 insertions(+) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index eef95b9ba2..5f5e848c76 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -124,9 +124,11 @@ bool CH422GComponent::write_outputs_() { float CH422GComponent::get_setup_priority() const { return setup_priority::IO; } +#ifdef USE_LOOP_PRIORITY // Run our loop() method very early in the loop, so that we cache read values // before other components call our digital_read() method. float CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI +#endif void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } diff --git a/esphome/components/ch422g/ch422g.h b/esphome/components/ch422g/ch422g.h index 8ed63db90a..1b96568209 100644 --- a/esphome/components/ch422g/ch422g.h +++ b/esphome/components/ch422g/ch422g.h @@ -23,7 +23,9 @@ class CH422GComponent : public Component, public i2c::I2CDevice { void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif void dump_config() override; protected: diff --git a/esphome/components/ch423/ch423.cpp b/esphome/components/ch423/ch423.cpp index 4abbbe7adf..805d8df877 100644 --- a/esphome/components/ch423/ch423.cpp +++ b/esphome/components/ch423/ch423.cpp @@ -129,9 +129,11 @@ bool CH423Component::write_outputs_() { float CH423Component::get_setup_priority() const { return setup_priority::IO; } +#ifdef USE_LOOP_PRIORITY // Run our loop() method very early in the loop, so that we cache read values // before other components call our digital_read() method. float CH423Component::get_loop_priority() const { return 9.0f; } // Just after WIFI +#endif void CH423GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } diff --git a/esphome/components/ch423/ch423.h b/esphome/components/ch423/ch423.h index 7adc7de6a1..d85648a8f9 100644 --- a/esphome/components/ch423/ch423.h +++ b/esphome/components/ch423/ch423.h @@ -22,7 +22,9 @@ class CH423Component : public Component, public i2c::I2CDevice { void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif void dump_config() override; protected: diff --git a/esphome/components/deep_sleep/deep_sleep_component.cpp b/esphome/components/deep_sleep/deep_sleep_component.cpp index 8066b411ff..0511518419 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.cpp +++ b/esphome/components/deep_sleep/deep_sleep_component.cpp @@ -40,9 +40,11 @@ void DeepSleepComponent::loop() { this->begin_sleep(); } +#ifdef USE_LOOP_PRIORITY float DeepSleepComponent::get_loop_priority() const { return -100.0f; // run after everything else is ready } +#endif void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; } diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index 3e6eda2257..1998b815f3 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -113,7 +113,9 @@ class DeepSleepComponent : public Component { void setup() override; void dump_config() override; void loop() override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif float get_setup_priority() const override; /// Helper to enter deep sleep mode diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index c574ce6593..d94767ef07 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -122,8 +122,10 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) { float PCA9554Component::get_setup_priority() const { return setup_priority::IO; } +#ifdef USE_LOOP_PRIORITY // Run our loop() method early to invalidate cache before any other components access the pins float PCA9554Component::get_loop_priority() const { return 9.0f; } // Just after WIFI +#endif void PCA9554GPIOPin::setup() { pin_mode(flags_); } void PCA9554GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } diff --git a/esphome/components/pca9554/pca9554.h b/esphome/components/pca9554/pca9554.h index bf752e50c9..6dd15ccb4b 100644 --- a/esphome/components/pca9554/pca9554.h +++ b/esphome/components/pca9554/pca9554.h @@ -23,7 +23,9 @@ class PCA9554Component : public Component, float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif void dump_config() override; diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index b7d3848f0e..fa9496e7e4 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -99,8 +99,10 @@ bool PCF8574Component::write_gpio_() { } float PCF8574Component::get_setup_priority() const { return setup_priority::IO; } +#ifdef USE_LOOP_PRIORITY // Run our loop() method early to invalidate cache before any other components access the pins float PCF8574Component::get_loop_priority() const { return 9.0f; } // Just after WIFI +#endif void PCF8574GPIOPin::setup() { pin_mode(flags_); } void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } diff --git a/esphome/components/pcf8574/pcf8574.h b/esphome/components/pcf8574/pcf8574.h index 5203030142..23bccc26c9 100644 --- a/esphome/components/pcf8574/pcf8574.h +++ b/esphome/components/pcf8574/pcf8574.h @@ -26,7 +26,9 @@ class PCF8574Component : public Component, void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif void dump_config() override; diff --git a/esphome/components/status_led/light/status_led_light.h b/esphome/components/status_led/light/status_led_light.h index bfa144526a..a5c98d90d4 100644 --- a/esphome/components/status_led/light/status_led_light.h +++ b/esphome/components/status_led/light/status_led_light.h @@ -30,7 +30,9 @@ class StatusLEDLightOutput : public light::LightOutput, public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override { return 50.0f; } +#endif protected: GPIOPin *pin_{nullptr}; diff --git a/esphome/components/status_led/status_led.cpp b/esphome/components/status_led/status_led.cpp index 344c1e3070..93a8d4b38e 100644 --- a/esphome/components/status_led/status_led.cpp +++ b/esphome/components/status_led/status_led.cpp @@ -28,7 +28,9 @@ void StatusLED::loop() { } } float StatusLED::get_setup_priority() const { return setup_priority::HARDWARE; } +#ifdef USE_LOOP_PRIORITY float StatusLED::get_loop_priority() const { return 50.0f; } +#endif } // namespace status_led } // namespace esphome diff --git a/esphome/components/status_led/status_led.h b/esphome/components/status_led/status_led.h index 490557f3e7..f262eb260c 100644 --- a/esphome/components/status_led/status_led.h +++ b/esphome/components/status_led/status_led.h @@ -14,7 +14,9 @@ class StatusLED : public Component { void dump_config() override; void loop() override; float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif protected: GPIOPin *pin_; diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 540d0a0ab1..8c1deb6217 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -536,6 +536,13 @@ async def to_code(config): cg.add_library("ESP8266WiFi", None) elif CORE.is_rp2040: cg.add_library("WiFi", None) + # RP2040's mDNS library (LEAmDNS) relies on LwipIntf::stateUpCB() to restart + # mDNS when the network interface reconnects. However, this callback is disabled + # in the arduino-pico framework. As a workaround, we block component setup until + # WiFi is connected via can_proceed(), ensuring mDNS.begin() is called with an + # active connection. This define enables the loop priority sorting infrastructure + # used during the setup blocking phase. + cg.add_define("USE_LOOP_PRIORITY") if CORE.is_esp32: if config[CONF_ENABLE_BTM] or config[CONF_ENABLE_RRM]: diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8b3060c7c3..d5d0419395 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -968,9 +968,11 @@ void WiFiComponent::set_ap(const WiFiAP &ap) { } #endif // USE_WIFI_AP +#ifdef USE_LOOP_PRIORITY float WiFiComponent::get_loop_priority() const { return 10.0f; // before other loop components } +#endif void WiFiComponent::init_sta(size_t count) { this->sta_.init(count); } void WiFiComponent::add_sta(const WiFiAP &ap) { this->sta_.push_back(ap); } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 5f903e092a..984930c80c 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -458,7 +458,9 @@ class WiFiComponent : public Component { void restart_adapter(); /// WIFI setup_priority. float get_setup_priority() const override; +#ifdef USE_LOOP_PRIORITY float get_loop_priority() const override; +#endif /// Reconnect WiFi if required. void loop() override; diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index b216233f9b..c6597897dc 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -109,9 +109,11 @@ void Application::setup() { if (component->can_proceed()) continue; +#ifdef USE_LOOP_PRIORITY // Sort components 0 through i by loop priority insertion_sort_by_priority<decltype(this->components_.begin()), &Component::get_loop_priority>( this->components_.begin(), this->components_.begin() + i + 1); +#endif do { uint8_t new_app_state = STATUS_LED_WARNING; diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b458ea2a84..b4a19a0776 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -85,7 +85,9 @@ void store_component_error_message(const Component *component, const char *messa static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again +#ifdef USE_LOOP_PRIORITY float Component::get_loop_priority() const { return 0.0f; } +#endif float Component::get_setup_priority() const { return setup_priority::DATA; } diff --git a/esphome/core/component.h b/esphome/core/component.h index b99641a275..7ea9fdf3b3 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -5,6 +5,7 @@ #include <functional> #include <string> +#include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/optional.h" @@ -117,7 +118,9 @@ class Component { * * @return The loop priority of this component */ +#ifdef USE_LOOP_PRIORITY virtual float get_loop_priority() const; +#endif void call(); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 5109dd36f4..02335e2745 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -312,6 +312,7 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) +#define USE_LOOP_PRIORITY #define USE_HTTP_REQUEST_RESPONSE #define USE_I2C #define USE_LOGGER_USB_CDC From ee1f52132573ab5498eaa566d3289d1103a4a186 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 16:59:54 -0600 Subject: [PATCH 0866/2030] [http_request] Replace std::list<Header> with std::vector in perform() chain (#14027) --- .../components/http_request/http_request.h | 89 +++++++++++++++---- .../http_request/http_request_arduino.cpp | 2 +- .../http_request/http_request_arduino.h | 2 +- .../http_request/http_request_host.cpp | 2 +- .../http_request/http_request_host.h | 2 +- .../http_request/http_request_idf.cpp | 2 +- .../http_request/http_request_idf.h | 2 +- .../components/online_image/online_image.cpp | 2 +- 8 files changed, 79 insertions(+), 24 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 2b2d05c63f..8bdea470b5 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -330,38 +330,72 @@ class HttpRequestComponent : public Component { void set_follow_redirects(bool follow_redirects) { this->follow_redirects_ = follow_redirects; } void set_redirect_limit(uint16_t limit) { this->redirect_limit_ = limit; } - std::shared_ptr<HttpContainer> get(const std::string &url) { return this->start(url, "GET", "", {}); } - std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers) { + std::shared_ptr<HttpContainer> get(const std::string &url) { + return this->start(url, "GET", "", std::vector<Header>{}); + } + std::shared_ptr<HttpContainer> get(const std::string &url, const std::vector<Header> &request_headers) { return this->start(url, "GET", "", request_headers); } - std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers, + std::shared_ptr<HttpContainer> get(const std::string &url, const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { return this->start(url, "GET", "", request_headers, lower_case_collect_headers); } std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body) { - return this->start(url, "POST", body, {}); + return this->start(url, "POST", body, std::vector<Header>{}); } std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body, - const std::list<Header> &request_headers) { + const std::vector<Header> &request_headers) { return this->start(url, "POST", body, request_headers); } std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { return this->start(url, "POST", body, request_headers, lower_case_collect_headers); } + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") + std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers) { + return this->get(url, std::vector<Header>(request_headers.begin(), request_headers.end())); + } + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") + std::shared_ptr<HttpContainer> get(const std::string &url, const std::list<Header> &request_headers, + const std::vector<std::string> &collect_headers) { + return this->get(url, std::vector<Header>(request_headers.begin(), request_headers.end()), collect_headers); + } + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") + std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body, + const std::list<Header> &request_headers) { + return this->post(url, body, std::vector<Header>(request_headers.begin(), request_headers.end())); + } + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") + std::shared_ptr<HttpContainer> post(const std::string &url, const std::string &body, + const std::list<Header> &request_headers, + const std::vector<std::string> &collect_headers) { + return this->post(url, body, std::vector<Header>(request_headers.begin(), request_headers.end()), collect_headers); + } + + std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, + const std::vector<Header> &request_headers) { + // Call perform() directly to avoid ambiguity with the deprecated overloads + return this->perform(url, method, body, request_headers, {}); + } + + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers) { - // Call perform() directly to avoid ambiguity with the std::set overload - return this->perform(url, method, body, request_headers, {}); + return this->start(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end())); } // Remove before 2027.1.0 ESPDEPRECATED("Pass collect_headers as std::vector<std::string> instead of std::set. Removed in 2027.1.0.", "2026.7.0") std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::set<std::string> &collect_headers) { std::vector<std::string> lower; lower.reserve(collect_headers.size()); @@ -371,15 +405,39 @@ class HttpRequestComponent : public Component { return this->perform(url, method, body, request_headers, lower); } + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list, and collect_headers as " + "std::vector<std::string> instead of std::set. Removed in 2027.1.0.", + "2026.7.0") std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, const std::list<Header> &request_headers, + const std::set<std::string> &collect_headers) { + std::vector<std::string> lower; + lower.reserve(collect_headers.size()); + for (const auto &h : collect_headers) { + lower.push_back(str_lower_case(h)); + } + return this->perform(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end()), lower); + } + + // Remove before 2027.1.0 + ESPDEPRECATED("Pass request_headers as std::vector<Header> instead of std::list. Removed in 2027.1.0.", "2026.7.0") + std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, + const std::list<Header> &request_headers, + const std::vector<std::string> &lower_case_collect_headers) { + return this->perform(url, method, body, std::vector<Header>(request_headers.begin(), request_headers.end()), + lower_case_collect_headers); + } + + std::shared_ptr<HttpContainer> start(const std::string &url, const std::string &method, const std::string &body, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { return this->perform(url, method, body, request_headers, lower_case_collect_headers); } protected: virtual std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, - const std::string &body, const std::list<Header> &request_headers, + const std::string &body, const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) = 0; const char *useragent_{nullptr}; bool follow_redirects_{}; @@ -436,13 +494,10 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1); body = json::build_json(f); } - std::list<Header> request_headers; - for (const auto &item : this->request_headers_) { - auto val = item.second; - Header header; - header.name = item.first; - header.value = val.value(x...); - request_headers.push_back(header); + std::vector<Header> request_headers; + request_headers.reserve(this->request_headers_.size()); + for (const auto &[key, val] : this->request_headers_) { + request_headers.push_back({key, val.value(x...)}); } auto container = this->parent_->start(this->url_.value(x...), this->method_.value(x...), body, request_headers, diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 3f60b76b58..56b51e8b5a 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -26,7 +26,7 @@ static constexpr int ESP8266_SSL_ERR_OOM = -1000; std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h index dbd61de364..d5ce5c0ff3 100644 --- a/esphome/components/http_request/http_request_arduino.h +++ b/esphome/components/http_request/http_request_arduino.h @@ -49,7 +49,7 @@ class HttpContainerArduino : public HttpContainer { class HttpRequestArduino : public HttpRequestComponent { protected: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) override; }; diff --git a/esphome/components/http_request/http_request_host.cpp b/esphome/components/http_request/http_request_host.cpp index 714a73fc31..60ab4d68a0 100644 --- a/esphome/components/http_request/http_request_host.cpp +++ b/esphome/components/http_request/http_request_host.cpp @@ -18,7 +18,7 @@ static const char *const TAG = "http_request.host"; std::shared_ptr<HttpContainer> HttpRequestHost::perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); diff --git a/esphome/components/http_request/http_request_host.h b/esphome/components/http_request/http_request_host.h index 79f5b7e817..52be0e8a16 100644 --- a/esphome/components/http_request/http_request_host.h +++ b/esphome/components/http_request/http_request_host.h @@ -19,7 +19,7 @@ class HttpContainerHost : public HttpContainer { class HttpRequestHost : public HttpRequestComponent { public: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) override; void set_ca_path(const char *ca_path) { this->ca_path_ = ca_path; } diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index 0921c50b9f..dda61e2400 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -54,7 +54,7 @@ esp_err_t HttpRequestIDF::http_event_handler(esp_http_client_event_t *evt) { std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { this->status_momentary_error("failed", 1000); diff --git a/esphome/components/http_request/http_request_idf.h b/esphome/components/http_request/http_request_idf.h index 9206ba6f5d..9ed1a97b1a 100644 --- a/esphome/components/http_request/http_request_idf.h +++ b/esphome/components/http_request/http_request_idf.h @@ -37,7 +37,7 @@ class HttpRequestIDF : public HttpRequestComponent { protected: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, - const std::list<Header> &request_headers, + const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) override; // if zero ESP-IDF will use DEFAULT_HTTP_BUF_SIZE uint16_t buffer_size_rx_{}; diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index 6f5b82116d..da866599c9 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -49,7 +49,7 @@ void OnlineImage::update() { ESP_LOGD(TAG, "Updating image from %s", this->url_.c_str()); - std::list<http_request::Header> headers; + std::vector<http_request::Header> headers; // Add caching headers if we have them if (!this->etag_.empty()) { From 5fddce6638f47c296e1267bbeeadaf677277d635 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 17:02:05 -0600 Subject: [PATCH 0867/2030] [logger] Make tx_buffer_ compile-time sized (#14205) --- esphome/components/logger/__init__.py | 3 ++- esphome/components/logger/logger.cpp | 7 ++----- esphome/components/logger/logger.h | 9 +++++---- esphome/components/logger/logger_esp32.cpp | 6 +++--- esphome/components/logger/logger_host.cpp | 4 ++-- esphome/core/defines.h | 1 + tests/dummy_main.cpp | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index c8f3c52911..264197c175 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -329,10 +329,11 @@ async def to_code(config): level = config[CONF_LEVEL] CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)] + tx_buffer_size = config[CONF_TX_BUFFER_SIZE] + cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) log = cg.new_Pvariable( config[CONF_ID], baud_rate, - config[CONF_TX_BUFFER_SIZE], ) if CORE.is_esp32: cg.add(log.create_pthread_key()) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 22a95e4835..497809cd2e 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -152,10 +152,7 @@ inline uint8_t Logger::level_for(const char *tag) { return this->current_level_; } -Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate), tx_buffer_size_(tx_buffer_size) { - // add 1 to buffer size for null terminator - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->tx_buffer_ = new char[this->tx_buffer_size_ + 1]; +Logger::Logger(uint32_t baud_rate) : baud_rate_(baud_rate) { #if defined(USE_ESP32) || defined(USE_LIBRETINY) this->main_task_ = xTaskGetCurrentTaskHandle(); #elif defined(USE_ZEPHYR) @@ -196,7 +193,7 @@ void Logger::process_messages_() { uint16_t text_length; while (this->log_buffer_->borrow_message_main_loop(message, text_length)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; - LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; + LogBuffer buf{this->tx_buffer_, ESPHOME_LOGGER_TX_BUFFER_SIZE}; this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, message->text_data(), text_length, buf); // Release the message to allow other tasks to use it as soon as possible diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 8bf1edebb8..90722ee79c 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -143,7 +143,7 @@ enum UARTSelection : uint8_t { */ class Logger : public Component { public: - explicit Logger(uint32_t baud_rate, size_t tx_buffer_size); + explicit Logger(uint32_t baud_rate); #ifdef USE_ESPHOME_TASK_LOG_BUFFER void init_log_buffer(size_t total_buffer_size); #endif @@ -281,7 +281,7 @@ class Logger : public Component { inline void HOT log_message_to_buffer_and_send_(bool &recursion_guard, uint8_t level, const char *tag, int line, FormatType format, va_list args, const char *thread_name) { RecursionGuard guard(recursion_guard); - LogBuffer buf{this->tx_buffer_, this->tx_buffer_size_}; + LogBuffer buf{this->tx_buffer_, ESPHOME_LOGGER_TX_BUFFER_SIZE}; #ifdef USE_STORE_LOG_STR_IN_FLASH if constexpr (std::is_same_v<FormatType, const __FlashStringHelper *>) { this->format_log_to_buffer_with_terminator_P_(level, tag, line, format, args, buf); @@ -312,7 +312,6 @@ class Logger : public Component { // Group 4-byte aligned members first uint32_t baud_rate_; - char *tx_buffer_{nullptr}; #if defined(USE_ARDUINO) && !defined(USE_ESP32) Stream *hw_serial_{nullptr}; #endif @@ -354,7 +353,6 @@ class Logger : public Component { #endif // Group smaller types together at the end - uint16_t tx_buffer_size_{0}; uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE}; #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR) UARTSelection uart_{UART_SELECTION_UART0}; @@ -371,6 +369,9 @@ class Logger : public Component { bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms #endif + // Large buffer placed last to keep frequently-accessed member offsets small + char tx_buffer_[ESPHOME_LOGGER_TX_BUFFER_SIZE + 1]; // +1 for null terminator + // --- get_thread_name_ overloads (per-platform) --- #if defined(USE_ESP32) || defined(USE_LIBRETINY) diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index 9d64771aec..d6ad77ff4f 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -89,16 +89,16 @@ void Logger::pre_setup() { switch (this->uart_) { case UART_SELECTION_UART0: this->uart_num_ = UART_NUM_0; - init_uart(this->uart_num_, baud_rate_, tx_buffer_size_); + init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE); break; case UART_SELECTION_UART1: this->uart_num_ = UART_NUM_1; - init_uart(this->uart_num_, baud_rate_, tx_buffer_size_); + init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE); break; #ifdef USE_ESP32_VARIANT_ESP32 case UART_SELECTION_UART2: this->uart_num_ = UART_NUM_2; - init_uart(this->uart_num_, baud_rate_, tx_buffer_size_); + init_uart(this->uart_num_, baud_rate_, ESPHOME_LOGGER_TX_BUFFER_SIZE); break; #endif #ifdef USE_LOGGER_USB_CDC diff --git a/esphome/components/logger/logger_host.cpp b/esphome/components/logger/logger_host.cpp index be12b6df6a..fe094f6e9e 100644 --- a/esphome/components/logger/logger_host.cpp +++ b/esphome/components/logger/logger_host.cpp @@ -5,8 +5,8 @@ namespace esphome::logger { void HOT Logger::write_msg_(const char *msg, uint16_t len) { static constexpr size_t TIMESTAMP_LEN = 10; // "[HH:MM:SS]" - // tx_buffer_size_ defaults to 512, so 768 covers default + headroom - char buffer[TIMESTAMP_LEN + 768]; + static constexpr size_t HEADROOM = 128; // Extra space for ANSI codes, newline, etc. + char buffer[TIMESTAMP_LEN + ESPHOME_LOGGER_TX_BUFFER_SIZE + HEADROOM]; time_t rawtime; time(&rawtime); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 02335e2745..1128df94f0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -21,6 +21,7 @@ // logger #define ESPHOME_LOG_LEVEL ESPHOME_LOG_LEVEL_VERY_VERBOSE +#define ESPHOME_LOGGER_TX_BUFFER_SIZE 512 #define USE_LOG_LISTENERS #define ESPHOME_LOG_MAX_LISTENERS 8 diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index e6fe733807..52f1fbd319 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -13,7 +13,7 @@ using namespace esphome; void setup() { App.pre_setup("livingroom", "LivingRoom", false); - auto *log = new logger::Logger(115200, 512); // NOLINT + auto *log = new logger::Logger(115200); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); App.register_component(log); From b539a5aa51e08db837d30be5310b917fa61f631b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 17:07:56 -0600 Subject: [PATCH 0868/2030] [water_heater] Fix device_id missing from state responses (#14212) --- esphome/components/api/api_connection.cpp | 3 +- .../fixtures/device_id_in_state.yaml | 115 ++++++++++++ tests/integration/test_device_id_in_state.py | 173 ++++++++++++------ 3 files changed, 232 insertions(+), 59 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 9fc263abbd..7bc9c45c05 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1346,9 +1346,8 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne resp.target_temperature_low = wh->get_target_temperature_low(); resp.target_temperature_high = wh->get_target_temperature_high(); resp.state = wh->get_state(); - resp.key = wh->get_object_id_hash(); - return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(wh, resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); } uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *wh = static_cast<water_heater::WaterHeater *>(entity); diff --git a/tests/integration/fixtures/device_id_in_state.yaml b/tests/integration/fixtures/device_id_in_state.yaml index c8548617b8..a5dfb7ee45 100644 --- a/tests/integration/fixtures/device_id_in_state.yaml +++ b/tests/integration/fixtures/device_id_in_state.yaml @@ -46,6 +46,7 @@ sensor: binary_sensor: - platform: template + id: motion_detected name: Motion Detected device_id: motion_sensor lambda: return true; @@ -82,3 +83,117 @@ output: write_action: - lambda: |- ESP_LOGD("test", "Light output: %d", state); + +cover: + - platform: template + name: Garage Door + device_id: motion_sensor + optimistic: true + +fan: + - platform: template + name: Ceiling Fan + device_id: humidity_monitor + speed_count: 3 + has_oscillating: false + has_direction: false + +lock: + - platform: template + name: Front Door Lock + device_id: motion_sensor + optimistic: true + +number: + - platform: template + name: Target Temperature + device_id: temperature_monitor + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + +select: + - platform: template + name: Mode Select + device_id: humidity_monitor + optimistic: true + options: + - "Auto" + - "Manual" + +text: + - platform: template + name: Device Label + device_id: temperature_monitor + optimistic: true + mode: text + +valve: + - platform: template + name: Water Valve + device_id: humidity_monitor + optimistic: true + +globals: + - id: global_away + type: bool + initial_value: "false" + - id: global_is_on + type: bool + initial_value: "true" + +water_heater: + - platform: template + name: Test Boiler + device_id: temperature_monitor + optimistic: true + current_temperature: !lambda "return 45.0f;" + target_temperature: !lambda "return 60.0f;" + away: !lambda "return id(global_away);" + is_on: !lambda "return id(global_is_on);" + supported_modes: + - "off" + - electric + visual: + min_temperature: 30.0 + max_temperature: 85.0 + target_temperature_step: 0.5 + set_action: + - lambda: |- + ESP_LOGD("test", "Water heater set"); + +alarm_control_panel: + - platform: template + name: House Alarm + device_id: motion_sensor + codes: + - "1234" + restore_mode: ALWAYS_DISARMED + binary_sensors: + - input: motion_detected + +datetime: + - platform: template + name: Schedule Date + device_id: temperature_monitor + type: date + optimistic: true + - platform: template + name: Schedule Time + device_id: humidity_monitor + type: time + optimistic: true + - platform: template + name: Schedule DateTime + device_id: motion_sensor + type: datetime + optimistic: true + +event: + - platform: template + name: Doorbell + device_id: motion_sensor + event_types: + - "press" + - "double_press" diff --git a/tests/integration/test_device_id_in_state.py b/tests/integration/test_device_id_in_state.py index 51088bcbf7..48de94a85a 100644 --- a/tests/integration/test_device_id_in_state.py +++ b/tests/integration/test_device_id_in_state.py @@ -4,11 +4,80 @@ from __future__ import annotations import asyncio -from aioesphomeapi import BinarySensorState, EntityState, SensorState, TextSensorState +from aioesphomeapi import ( + AlarmControlPanelEntityState, + BinarySensorState, + CoverState, + DateState, + DateTimeState, + EntityState, + FanState, + LightState, + LockEntityState, + NumberState, + SelectState, + SensorState, + SwitchState, + TextSensorState, + TextState, + TimeState, + ValveState, + WaterHeaterState, +) import pytest from .types import APIClientConnectedFactory, RunCompiledFunction +# Mapping of entity name to device name for all entities with device_id +ENTITY_TO_DEVICE = { + # Original entities + "Temperature": "Temperature Monitor", + "Humidity": "Humidity Monitor", + "Motion Detected": "Motion Sensor", + "Temperature Monitor Power": "Temperature Monitor", + "Temperature Status": "Temperature Monitor", + "Motion Light": "Motion Sensor", + # New entity types + "Garage Door": "Motion Sensor", + "Ceiling Fan": "Humidity Monitor", + "Front Door Lock": "Motion Sensor", + "Target Temperature": "Temperature Monitor", + "Mode Select": "Humidity Monitor", + "Device Label": "Temperature Monitor", + "Water Valve": "Humidity Monitor", + "Test Boiler": "Temperature Monitor", + "House Alarm": "Motion Sensor", + "Schedule Date": "Temperature Monitor", + "Schedule Time": "Humidity Monitor", + "Schedule DateTime": "Motion Sensor", + "Doorbell": "Motion Sensor", +} + +# Entities without device_id (should have device_id 0) +NO_DEVICE_ENTITIES = {"No Device Sensor"} + +# State types that should have non-zero device_id, mapped by their aioesphomeapi class +EXPECTED_STATE_TYPES = [ + (SensorState, "sensor"), + (BinarySensorState, "binary_sensor"), + (SwitchState, "switch"), + (TextSensorState, "text_sensor"), + (LightState, "light"), + (CoverState, "cover"), + (FanState, "fan"), + (LockEntityState, "lock"), + (NumberState, "number"), + (SelectState, "select"), + (TextState, "text"), + (ValveState, "valve"), + (WaterHeaterState, "water_heater"), + (AlarmControlPanelEntityState, "alarm_control_panel"), + (DateState, "date"), + (TimeState, "time"), + (DateTimeState, "datetime"), + # Event is stateless (no initial state sent on subscribe) +] + @pytest.mark.asyncio async def test_device_id_in_state( @@ -40,34 +109,35 @@ async def test_device_id_in_state( entity_device_mapping: dict[int, int] = {} for entity in all_entities: - # All entities have name and key attributes - if entity.name == "Temperature": - entity_device_mapping[entity.key] = device_ids["Temperature Monitor"] - elif entity.name == "Humidity": - entity_device_mapping[entity.key] = device_ids["Humidity Monitor"] - elif entity.name == "Motion Detected": - entity_device_mapping[entity.key] = device_ids["Motion Sensor"] - elif entity.name in {"Temperature Monitor Power", "Temperature Status"}: - entity_device_mapping[entity.key] = device_ids["Temperature Monitor"] - elif entity.name == "Motion Light": - entity_device_mapping[entity.key] = device_ids["Motion Sensor"] - elif entity.name == "No Device Sensor": - # Entity without device_id should have device_id 0 + if entity.name in ENTITY_TO_DEVICE: + expected_device = ENTITY_TO_DEVICE[entity.name] + entity_device_mapping[entity.key] = device_ids[expected_device] + elif entity.name in NO_DEVICE_ENTITIES: entity_device_mapping[entity.key] = 0 - assert len(entity_device_mapping) >= 6, ( - f"Expected at least 6 mapped entities, got {len(entity_device_mapping)}" + expected_count = len(ENTITY_TO_DEVICE) + len(NO_DEVICE_ENTITIES) + assert len(entity_device_mapping) >= expected_count, ( + f"Expected at least {expected_count} mapped entities, " + f"got {len(entity_device_mapping)}. " + f"Missing: {set(ENTITY_TO_DEVICE) | NO_DEVICE_ENTITIES - {e.name for e in all_entities}}" + ) + + # Subscribe to states and wait for all mapped entities + # Event entities are stateless (no initial state on subscribe), + # so exclude them from the expected count + stateless_keys = {e.key for e in all_entities if e.name == "Doorbell"} + stateful_count = len(entity_device_mapping) - len( + stateless_keys & entity_device_mapping.keys() ) - # Subscribe to states loop = asyncio.get_running_loop() states: dict[int, EntityState] = {} states_future: asyncio.Future[bool] = loop.create_future() def on_state(state: EntityState) -> None: - states[state.key] = state - # Check if we have states for all mapped entities - if len(states) >= len(entity_device_mapping) and not states_future.done(): + if state.key in entity_device_mapping: + states[state.key] = state + if len(states) >= stateful_count and not states_future.done(): states_future.set_result(True) client.subscribe_states(on_state) @@ -76,9 +146,16 @@ async def test_device_id_in_state( try: await asyncio.wait_for(states_future, timeout=10.0) except TimeoutError: + received_names = {e.name for e in all_entities if e.key in states} + missing_names = ( + (set(ENTITY_TO_DEVICE) | NO_DEVICE_ENTITIES) + - received_names + - {"Doorbell"} + ) pytest.fail( f"Did not receive all entity states within 10 seconds. " - f"Received {len(states)} states, expected {len(entity_device_mapping)}" + f"Received {len(states)} states. " + f"Missing: {missing_names}" ) # Verify each state has the correct device_id @@ -86,51 +163,33 @@ async def test_device_id_in_state( for key, expected_device_id in entity_device_mapping.items(): if key in states: state = states[key] + entity_name = next( + (e.name for e in all_entities if e.key == key), f"key={key}" + ) assert state.device_id == expected_device_id, ( - f"State for key {key} has device_id {state.device_id}, " - f"expected {expected_device_id}" + f"State for '{entity_name}' (type={type(state).__name__}) " + f"has device_id {state.device_id}, expected {expected_device_id}" ) verified_count += 1 - assert verified_count >= 6, ( - f"Only verified {verified_count} states, expected at least 6" + # All stateful entities should be verified (everything except Doorbell event) + expected_verified = expected_count - 1 # exclude Doorbell + assert verified_count >= expected_verified, ( + f"Only verified {verified_count} states, expected at least {expected_verified}" ) - # Test specific state types to ensure device_id is present - # Find a sensor state with device_id - sensor_state = next( - ( + # Verify each expected state type has at least one instance with non-zero device_id + for state_type, type_name in EXPECTED_STATE_TYPES: + matching = [ s for s in states.values() - if isinstance(s, SensorState) - and isinstance(s.state, float) - and s.device_id != 0 - ), - None, - ) - assert sensor_state is not None, "No sensor state with device_id found" - assert sensor_state.device_id > 0, "Sensor state should have non-zero device_id" - - # Find a binary sensor state - binary_sensor_state = next( - (s for s in states.values() if isinstance(s, BinarySensorState)), - None, - ) - assert binary_sensor_state is not None, "No binary sensor state found" - assert binary_sensor_state.device_id > 0, ( - "Binary sensor state should have non-zero device_id" - ) - - # Find a text sensor state - text_sensor_state = next( - (s for s in states.values() if isinstance(s, TextSensorState)), - None, - ) - assert text_sensor_state is not None, "No text sensor state found" - assert text_sensor_state.device_id > 0, ( - "Text sensor state should have non-zero device_id" - ) + if isinstance(s, state_type) and s.device_id != 0 + ] + assert matching, ( + f"No {type_name} state (type={state_type.__name__}) " + f"with non-zero device_id found" + ) # Verify the "No Device Sensor" has device_id = 0 no_device_key = next( From ded457c2c1a5b27aba9af05b7b29a38dd832e7fa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 18:52:46 -0600 Subject: [PATCH 0869/2030] [libretiny] Tune oversized lwIP defaults for ESPHome (#14186) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/__init__.py | 4 +- esphome/components/captive_portal/__init__.py | 6 +- esphome/components/esp32/__init__.py | 59 +++---- .../esp32_camera_web_server/__init__.py | 6 +- esphome/components/esphome/ota/__init__.py | 5 +- esphome/components/libretiny/__init__.py | 153 +++++++++++++++++- esphome/components/mdns/__init__.py | 2 +- esphome/components/socket/__init__.py | 90 ++++++++++- esphome/components/udp/__init__.py | 2 +- esphome/components/web_server/__init__.py | 6 +- .../components/web_server_base/__init__.py | 25 ++- esphome/components/wifi/__init__.py | 20 +++ .../socket/test_wake_loop_threadsafe.py | 8 +- 13 files changed, 327 insertions(+), 59 deletions(-) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 9bff9f5635..3f7cafb485 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -233,8 +233,8 @@ def _consume_api_sockets(config: ConfigType) -> ConfigType: # API needs 1 listening socket + typically 3 concurrent client connections # (not max_connections, which is the upper limit rarely reached) - sockets_needed = 1 + 3 - socket.consume_sockets(sockets_needed, "api")(config) + socket.consume_sockets(3, "api")(config) + socket.consume_sockets(1, "api", socket.SocketType.TCP_LISTEN)(config) return config diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index 049618219e..6c190814c0 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -76,13 +76,15 @@ def _final_validate(config: ConfigType) -> ConfigType: # Register socket needs for DNS server and additional HTTP connections # - 1 UDP socket for DNS server - # - 3 additional TCP sockets for captive portal detection probes + configuration requests + # - 3 TCP sockets for captive portal detection probes + configuration requests # OS captive portal detection makes multiple probe requests that stay in TIME_WAIT. # Need headroom for actual user configuration requests. # LRU purging will reclaim idle sockets to prevent exhaustion from repeated attempts. + # The listening socket is registered by web_server_base (shared HTTP server). from esphome.components import socket - socket.consume_sockets(4, "captive_portal")(config) + socket.consume_sockets(3, "captive_portal")(config) + socket.consume_sockets(1, "captive_portal", socket.SocketType.UDP)(config) return config diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 06677006ea..4c211b2f2a 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1258,21 +1258,15 @@ def _configure_lwip_max_sockets(conf: dict) -> None: This function runs in to_code() after all components have registered their socket needs. User-provided sdkconfig_options take precedence. """ - from esphome.components.socket import KEY_SOCKET_CONSUMERS + from esphome.components.socket import get_socket_counts # Check if user manually specified CONFIG_LWIP_MAX_SOCKETS user_max_sockets = conf[CONF_SDKCONFIG_OPTIONS].get("CONFIG_LWIP_MAX_SOCKETS") - socket_consumers: dict[str, int] = CORE.data.get(KEY_SOCKET_CONSUMERS, {}) - total_sockets = sum(socket_consumers.values()) - - # Early return if no sockets registered and no user override - if total_sockets == 0 and user_max_sockets is None: - return - - components_list = ", ".join( - f"{name}={count}" for name, count in sorted(socket_consumers.items()) - ) + # CONFIG_LWIP_MAX_SOCKETS is a single VFS socket pool shared by all socket + # types (TCP clients, TCP listeners, and UDP). Include all three counts. + sc = get_socket_counts() + total_sockets = sc.tcp + sc.udp + sc.tcp_listen # User specified their own value - respect it but warn if insufficient if user_max_sockets is not None: @@ -1281,22 +1275,23 @@ def _configure_lwip_max_sockets(conf: dict) -> None: user_max_sockets, ) - # Warn if user's value is less than what components need - if total_sockets > 0: - user_sockets_int = 0 - with contextlib.suppress(ValueError, TypeError): - user_sockets_int = int(user_max_sockets) + user_sockets_int = 0 + with contextlib.suppress(ValueError, TypeError): + user_sockets_int = int(user_max_sockets) - if user_sockets_int < total_sockets: - _LOGGER.warning( - "CONFIG_LWIP_MAX_SOCKETS is set to %d but your configuration " - "needs %d sockets (registered: %s). You may experience socket " - "exhaustion errors. Consider increasing to at least %d.", - user_sockets_int, - total_sockets, - components_list, - total_sockets, - ) + if user_sockets_int < total_sockets: + _LOGGER.warning( + "CONFIG_LWIP_MAX_SOCKETS is set to %d but your configuration " + "needs %d sockets (%d TCP + %d UDP + %d TCP_LISTEN). You may " + "experience socket exhaustion errors. Consider increasing to " + "at least %d.", + user_sockets_int, + total_sockets, + sc.tcp, + sc.udp, + sc.tcp_listen, + total_sockets, + ) # User's value already added via sdkconfig_options processing return @@ -1305,11 +1300,19 @@ def _configure_lwip_max_sockets(conf: dict) -> None: max_sockets = max(DEFAULT_MAX_SOCKETS, total_sockets) log_level = logging.INFO if max_sockets > DEFAULT_MAX_SOCKETS else logging.DEBUG + sock_min = " (min)" if max_sockets > total_sockets else "" _LOGGER.log( log_level, - "Setting CONFIG_LWIP_MAX_SOCKETS to %d (registered: %s)", + "Setting CONFIG_LWIP_MAX_SOCKETS to %d%s " + "(TCP=%d [%s], UDP=%d [%s], TCP_LISTEN=%d [%s])", max_sockets, - components_list, + sock_min, + sc.tcp, + sc.tcp_details, + sc.udp, + sc.udp_details, + sc.tcp_listen, + sc.tcp_listen_details, ) add_idf_sdkconfig_option("CONFIG_LWIP_MAX_SOCKETS", max_sockets) diff --git a/esphome/components/esp32_camera_web_server/__init__.py b/esphome/components/esp32_camera_web_server/__init__.py index ed1aaa2e07..da260ad7a1 100644 --- a/esphome/components/esp32_camera_web_server/__init__.py +++ b/esphome/components/esp32_camera_web_server/__init__.py @@ -20,8 +20,10 @@ def _consume_camera_web_server_sockets(config: ConfigType) -> ConfigType: from esphome.components import socket # Each camera web server instance needs 1 listening socket + 2 client connections - sockets_needed = 3 - socket.consume_sockets(sockets_needed, "esp32_camera_web_server")(config) + socket.consume_sockets(2, "esp32_camera_web_server")(config) + socket.consume_sockets(1, "esp32_camera_web_server", socket.SocketType.TCP_LISTEN)( + config + ) return config diff --git a/esphome/components/esphome/ota/__init__.py b/esphome/components/esphome/ota/__init__.py index 2f637d714d..337064dd27 100644 --- a/esphome/components/esphome/ota/__init__.py +++ b/esphome/components/esphome/ota/__init__.py @@ -97,8 +97,9 @@ def _consume_ota_sockets(config: ConfigType) -> ConfigType: """Register socket needs for OTA component.""" from esphome.components import socket - # OTA needs 1 listening socket (client connections are temporary during updates) - socket.consume_sockets(1, "ota")(config) + # OTA needs 1 listening socket. The active transfer connection during an update + # uses a TCP PCB from the general pool, covered by MIN_TCP_SOCKETS headroom. + socket.consume_sockets(1, "ota", socket.SocketType.TCP_LISTEN)(config) return config diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 01445da7ee..2291114d9a 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -275,6 +275,146 @@ BASE_SCHEMA.add_extra(_detect_variant) BASE_SCHEMA.add_extra(_update_core_data) +def _configure_lwip(config: dict) -> None: + """Configure lwIP options for LibreTiny platforms. + + The BK/RTL/LN SDKs each ship different lwIP defaults. BK72XX defaults are + wildly oversized for ESPHome's IoT use case, causing OOM on BK7231N. + RTL87XX and LN882H have more conservative defaults but still need tuning + for ESPHome's socket usage patterns. + + See https://github.com/esphome/esphome/issues/14095 + + Comparison of SDK defaults vs ESPHome targets (TCP_MSS=1460 on all LT): + + Setting ESP8266 ESP32 BK SDK RTL SDK LN SDK New + ──────────────────────────────────────────────────────────────────────────── + TCP_SND_BUF 2×MSS 4×MSS 10×MSS 5×MSS 7×MSS 4×MSS + TCP_WND 4×MSS 4×MSS 3/10×MSS 2×MSS 3×MSS 4×MSS + MEM_LIBC_MALLOC 1 1 0 0 1 1 + MEMP_MEM_MALLOC 1 1 0 0 0 1 + MEM_SIZE N/A* N/A* 16/32KB 5KB N/A* N/A* BK + PBUF_POOL_SIZE 10 16 3/10 20 20 10 BK + MAX_SOCKETS_TCP 5 16 12 —** —** dynamic + MAX_SOCKETS_UDP 4 16 22 —** —** dynamic + TCP_SND_QUEUELEN ~8 17 20 20 35 17 + MEMP_NUM_TCP_SEG 10 16 40 20 =qlen 17 + MEMP_NUM_TCP_PCB 5 16 12 10 8 =TCP + MEMP_NUM_TCP_PCB_LISTEN 4 16 4 5 3 dynamic + MEMP_NUM_UDP_PCB 4 16 25*** 7**** 7**** =UDP + MEMP_NUM_NETCONN 0 10 38 4***** =sum =sum + MEMP_NUM_NETBUF 0 2 16 2***** 8 4 + MEMP_NUM_TCPIP_MSG_INPKT 4 8 16 8***** 12 8 + + * ESP8266/ESP32/LN882H use MEM_LIBC_MALLOC=1 (system heap, no dedicated pool). + ESP8266/ESP32 also use MEMP_MEM_MALLOC=1 (MEMP pools from heap, not static). + ** RTL/LN SDKs don't define MAX_SOCKETS_TCP/UDP (LibreTiny-specific). + *** BK LT overlay: MAX_SOCKETS_UDP+2+1 = 25. + **** RTL/LN LT overlay overrides to flat 7. + ***** Not defined in RTL SDK — lwIP opt.h defaults shown. + "dynamic" = auto-calculated from component socket registrations via + socket.get_socket_counts() with minimums of 8 TCP / 6 UDP. + """ + from esphome.components.socket import ( + MIN_TCP_LISTEN_SOCKETS, + MIN_TCP_SOCKETS, + MIN_UDP_SOCKETS, + get_socket_counts, + ) + + sc = get_socket_counts() + # Apply platform minimums — ensure headroom for ESPHome's needs + tcp_sockets = max(MIN_TCP_SOCKETS, sc.tcp) + udp_sockets = max(MIN_UDP_SOCKETS, sc.udp) + # Listening sockets — registered by components (api, ota, web_server_base, etc.) + # Not all components register yet, so ensure a minimum for baseline operation. + listening_tcp = max(MIN_TCP_LISTEN_SOCKETS, sc.tcp_listen) + + # TCP_SND_BUF: ESPAsyncWebServer allocates malloc(tcp_sndbuf()) per + # response chunk. At 10×MSS=14.6KB (BK default) this causes OOM (#14095). + # 4×MSS=5,840 matches ESP32. RTL(5×) and LN(7×) are close already. + tcp_snd_buf = "(4*TCP_MSS)" # BK: 10×MSS, RTL: 5×MSS, LN: 7×MSS + + # TCP_WND: receive window. 4×MSS matches ESP32. + # RTL SDK uses only 2×MSS; increasing to 4× is safe and improves throughput. + tcp_wnd = "(4*TCP_MSS)" # BK: 10×MSS, RTL: 2×MSS, LN: 3×MSS + + # TCP_SND_QUEUELEN: max pbufs queued for send buffer + # ESP-IDF formula: (4 * TCP_SND_BUF + (TCP_MSS - 1)) / TCP_MSS + # With 4×MSS: (4*5840 + 1459) / 1460 = 17 — match ESP32 + tcp_snd_queuelen = 17 # BK: 20, RTL: 20, LN: 35 + # MEMP_NUM_TCP_SEG: segment pool, must be >= TCP_SND_QUEUELEN (lwIP sanity check) + memp_num_tcp_seg = tcp_snd_queuelen # BK: 40, RTL: 20, LN: =qlen + + lwip_opts: list[str] = [ + # Disable statistics — not needed for production, saves RAM + "LWIP_STATS=0", # BK: 1, RTL: 0 already, LN: 0 already + "MEM_STATS=0", + "MEMP_STATS=0", + # TCP send buffer — 4×MSS matches ESP32 + f"TCP_SND_BUF={tcp_snd_buf}", + # TCP receive window — 4×MSS matches ESP32 + f"TCP_WND={tcp_wnd}", + # Socket counts — auto-calculated from component registrations + f"MAX_SOCKETS_TCP={tcp_sockets}", + f"MAX_SOCKETS_UDP={udp_sockets}", + # Listening sockets — BK SDK uses this to derive MEMP_NUM_TCP_PCB_LISTEN; + # RTL/LN don't use it, but we set MEMP_NUM_TCP_PCB_LISTEN explicitly below. + f"MAX_LISTENING_SOCKETS_TCP={listening_tcp}", + # Queued segment limits — derived from 4×MSS buffer size + f"TCP_SND_QUEUELEN={tcp_snd_queuelen}", + f"MEMP_NUM_TCP_SEG={memp_num_tcp_seg}", # must be >= queuelen + # PCB pools — active connections + listening sockets + f"MEMP_NUM_TCP_PCB={tcp_sockets}", # BK: 12, RTL: 10, LN: 8 + f"MEMP_NUM_TCP_PCB_LISTEN={listening_tcp}", # BK: =MAX_LISTENING, RTL: 5, LN: 3 + # UDP PCB pool — includes wifi.lwip_internal (DHCP + DNS) + f"MEMP_NUM_UDP_PCB={udp_sockets}", # BK: 25, RTL/LN: 7 via LT + # Netconn pool — each socket (active + listening) needs a netconn + f"MEMP_NUM_NETCONN={tcp_sockets + udp_sockets + listening_tcp}", + # Netbuf pool + "MEMP_NUM_NETBUF=4", # BK: 16, RTL: 2 (opt.h), LN: 8 + # Inbound message pool + "MEMP_NUM_TCPIP_MSG_INPKT=8", # BK: 16, RTL: 8 (opt.h), LN: 12 + ] + + # Use system heap for all lwIP allocations on all LibreTiny platforms. + # - MEM_LIBC_MALLOC=1: Use system heap instead of dedicated lwIP heap. + # LN882H already ships with this. BK SDK defaults to a 16/32KB dedicated + # pool that fragments during OTA. RTL SDK defaults to a 5KB pool. + # All three SDKs wire malloc → pvPortMalloc (FreeRTOS thread-safe heap). + # - MEMP_MEM_MALLOC=1: Allocate MEMP pools from heap on demand instead + # of static arrays. Saves ~20KB RAM on BK72XX. Safe because WiFi + # receive paths run in task context, not ISR context. ESP32 and ESP8266 + # both ship with MEMP_MEM_MALLOC=1. + lwip_opts.append("MEM_LIBC_MALLOC=1") + lwip_opts.append("MEMP_MEM_MALLOC=1") + + # BK72XX-specific: PBUF_POOL_SIZE override + # BK SDK "reduced plan" sets this to only 3 — too few for multiple + # concurrent connections (API + web_server + OTA). BK default plan + # uses 10; match that. RTL(20) and LN(20) need no override. + # With MEMP_MEM_MALLOC=1, this is a max count (allocated on demand). + if CORE.is_bk72xx: + lwip_opts.append("PBUF_POOL_SIZE=10") + + tcp_min = " (min)" if tcp_sockets > sc.tcp else "" + udp_min = " (min)" if udp_sockets > sc.udp else "" + listen_min = " (min)" if listening_tcp > sc.tcp_listen else "" + _LOGGER.info( + "Configuring lwIP: TCP=%d%s [%s], UDP=%d%s [%s], TCP_LISTEN=%d%s [%s]", + tcp_sockets, + tcp_min, + sc.tcp_details, + udp_sockets, + udp_min, + sc.udp_details, + listening_tcp, + listen_min, + sc.tcp_listen_details, + ) + cg.add_platformio_option("custom_options.lwip", lwip_opts) + + # pylint: disable=use-dict-literal async def component_to_code(config): var = cg.new_Pvariable(config[CONF_ID]) @@ -389,11 +529,12 @@ async def component_to_code(config): "custom_options.sys_config#h", _BK7231N_SYS_CONFIG_OPTIONS ) - # Disable LWIP statistics to save RAM - not needed in production - # Must explicitly disable all sub-stats to avoid redefinition warnings - cg.add_platformio_option( - "custom_options.lwip", - ["LWIP_STATS=0", "MEM_STATS=0", "MEMP_STATS=0"], - ) + # Tune lwIP for ESPHome's actual needs. + # The SDK defaults (TCP_SND_BUF=10*MSS, MAX_SOCKETS_TCP=12, MEM_SIZE=32KB) + # are wildly oversized for an IoT device. ESPAsyncWebServer allocates + # malloc(tcp_sndbuf()) per response chunk — at 14.6KB this causes silent + # OOM on memory-constrained chips like BK7231N. + # See https://github.com/esphome/esphome/issues/14095 + _configure_lwip(config) await cg.register_component(var, config) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index f87f929615..420e6a60e3 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -56,7 +56,7 @@ def _consume_mdns_sockets(config: ConfigType) -> ConfigType: from esphome.components import socket # mDNS needs 2 sockets (IPv4 + IPv6 multicast) - socket.consume_sockets(2, "mdns")(config) + socket.consume_sockets(2, "mdns", socket.SocketType.UDP)(config) return config diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index e364da78f8..d82f0c7aba 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -1,9 +1,14 @@ from collections.abc import Callable, MutableMapping +from dataclasses import dataclass +from enum import StrEnum +import logging import esphome.codegen as cg import esphome.config_validation as cv from esphome.core import CORE +_LOGGER = logging.getLogger(__name__) + CODEOWNERS = ["@esphome/core"] CONF_IMPLEMENTATION = "implementation" @@ -13,33 +18,110 @@ IMPLEMENTATION_BSD_SOCKETS = "bsd_sockets" # Socket tracking infrastructure # Components register their socket needs and platforms read this to configure appropriately -KEY_SOCKET_CONSUMERS = "socket_consumers" +KEY_SOCKET_CONSUMERS_TCP = "socket_consumers_tcp" +KEY_SOCKET_CONSUMERS_UDP = "socket_consumers_udp" +KEY_SOCKET_CONSUMERS_TCP_LISTEN = "socket_consumers_tcp_listen" + +# Recommended minimum socket counts. +# Platforms should apply these (or their own) on top of get_socket_counts(). +# These cover minimal configs (e.g. api-only without web_server). +# When web_server is present, its 5 registered sockets push past the TCP minimum. +MIN_TCP_SOCKETS = 8 +MIN_UDP_SOCKETS = 6 +# Minimum listening sockets — at least api + ota baseline. +MIN_TCP_LISTEN_SOCKETS = 2 # Wake loop threadsafe support tracking KEY_WAKE_LOOP_THREADSAFE_REQUIRED = "wake_loop_threadsafe_required" +class SocketType(StrEnum): + TCP = "tcp" + UDP = "udp" + TCP_LISTEN = "tcp_listen" + + +_SOCKET_TYPE_KEYS = { + SocketType.TCP: KEY_SOCKET_CONSUMERS_TCP, + SocketType.UDP: KEY_SOCKET_CONSUMERS_UDP, + SocketType.TCP_LISTEN: KEY_SOCKET_CONSUMERS_TCP_LISTEN, +} + + def consume_sockets( - value: int, consumer: str + value: int, consumer: str, socket_type: SocketType = SocketType.TCP ) -> Callable[[MutableMapping], MutableMapping]: """Register socket usage for a component. Args: value: Number of sockets needed by the component consumer: Name of the component consuming the sockets + socket_type: Type of socket (SocketType.TCP, SocketType.UDP, or SocketType.TCP_LISTEN) Returns: A validator function that records the socket usage """ + typed_key = _SOCKET_TYPE_KEYS[socket_type] def _consume_sockets(config: MutableMapping) -> MutableMapping: - consumers: dict[str, int] = CORE.data.setdefault(KEY_SOCKET_CONSUMERS, {}) + consumers: dict[str, int] = CORE.data.setdefault(typed_key, {}) consumers[consumer] = consumers.get(consumer, 0) + value return config return _consume_sockets +def _format_consumers(consumers: dict[str, int]) -> str: + """Format consumer dict as 'name=count, ...' or 'none'.""" + if not consumers: + return "none" + return ", ".join(f"{name}={count}" for name, count in sorted(consumers.items())) + + +@dataclass(frozen=True) +class SocketCounts: + """Socket counts and component details for platform configuration.""" + + tcp: int + udp: int + tcp_listen: int + tcp_details: str + udp_details: str + tcp_listen_details: str + + +def get_socket_counts() -> SocketCounts: + """Return socket counts and component details for platform configuration. + + Platforms call this during code generation to configure lwIP socket limits. + All components will have registered their needs by then. + + Platforms should apply their own minimums on top of these values. + """ + tcp_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_TCP, {}) + udp_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_UDP, {}) + tcp_listen_consumers = CORE.data.get(KEY_SOCKET_CONSUMERS_TCP_LISTEN, {}) + tcp = sum(tcp_consumers.values()) + udp = sum(udp_consumers.values()) + tcp_listen = sum(tcp_listen_consumers.values()) + + tcp_details = _format_consumers(tcp_consumers) + udp_details = _format_consumers(udp_consumers) + tcp_listen_details = _format_consumers(tcp_listen_consumers) + _LOGGER.debug( + "Socket counts: TCP=%d (%s), UDP=%d (%s), TCP_LISTEN=%d (%s)", + tcp, + tcp_details, + udp, + udp_details, + tcp_listen, + tcp_listen_details, + ) + return SocketCounts( + tcp, udp, tcp_listen, tcp_details, udp_details, tcp_listen_details + ) + + def require_wake_loop_threadsafe() -> None: """Mark that wake_loop_threadsafe support is required by a component. @@ -66,7 +148,7 @@ def require_wake_loop_threadsafe() -> None: CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True cg.add_define("USE_WAKE_LOOP_THREADSAFE") # Consume 1 socket for the shared wake notification socket - consume_sockets(1, "socket.wake_loop_threadsafe")({}) + consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({}) CONFIG_SCHEMA = cv.Schema( diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index c9586d0b95..37dd871a6c 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -73,7 +73,7 @@ def _consume_udp_sockets(config: ConfigType) -> ConfigType: # UDP uses up to 2 sockets: 1 broadcast + 1 listen # Whether each is used depends on code generation, so register worst case - socket.consume_sockets(2, "udp")(config) + socket.consume_sockets(2, "udp", socket.SocketType.UDP)(config) return config diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 9305a2de61..84910b6f90 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -144,11 +144,11 @@ def _consume_web_server_sockets(config: ConfigType) -> ConfigType: """Register socket needs for web_server component.""" from esphome.components import socket - # Web server needs 1 listening socket + typically 5 concurrent client connections + # Web server needs typically 5 concurrent client connections # (browser opens connections for page resources, SSE event stream, and POST # requests for entity control which may linger before closing) - sockets_needed = 6 - socket.consume_sockets(sockets_needed, "web_server")(config) + # The listening socket is registered by web_server_base (shared with captive_portal) + socket.consume_sockets(5, "web_server")(config) return config diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 183b907ae6..b587841dfd 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -23,10 +23,27 @@ web_server_base_ns = cg.esphome_ns.namespace("web_server_base") WebServerBase = web_server_base_ns.class_("WebServerBase") CONF_WEB_SERVER_BASE_ID = "web_server_base_id" -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(WebServerBase), - } + + +def _consume_web_server_base_sockets(config): + """Register the shared listening socket for the HTTP server. + + web_server_base is the shared HTTP server used by web_server and captive_portal. + The listening socket is registered here rather than in each consumer. + """ + from esphome.components import socket + + socket.consume_sockets(1, "web_server_base", socket.SocketType.TCP_LISTEN)(config) + return config + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(WebServerBase), + } + ), + _consume_web_server_base_sockets, ) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 8c1deb6217..b89245b10e 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -58,6 +58,7 @@ from esphome.const import ( ) from esphome.core import CORE, CoroPriority, HexInt, coroutine_with_priority import esphome.final_validate as fv +from esphome.types import ConfigType from . import wpa2_eap @@ -269,9 +270,28 @@ def final_validate(config): ) +def _consume_wifi_sockets(config: ConfigType) -> ConfigType: + """Register UDP PCBs used internally by lwIP for DHCP and DNS. + + Only needed on LibreTiny where we directly set MEMP_NUM_UDP_PCB (the raw + PCB pool shared by both application sockets and lwIP internals like DHCP/DNS). + On ESP32, CONFIG_LWIP_MAX_SOCKETS only controls the POSIX socket layer — + DHCP/DNS use raw udp_new() which bypasses it entirely. + """ + if not (CORE.is_bk72xx or CORE.is_rtl87xx or CORE.is_ln882x): + return config + from esphome.components import socket + + # lwIP allocates UDP PCBs for DHCP client and DNS resolver internally. + # These are not application sockets but consume MEMP_NUM_UDP_PCB pool entries. + socket.consume_sockets(2, "wifi.lwip_internal", socket.SocketType.UDP)(config) + return config + + FINAL_VALIDATE_SCHEMA = cv.All( final_validate, validate_variant, + _consume_wifi_sockets, ) diff --git a/tests/components/socket/test_wake_loop_threadsafe.py b/tests/components/socket/test_wake_loop_threadsafe.py index b4bc95176d..a40b6068a8 100644 --- a/tests/components/socket/test_wake_loop_threadsafe.py +++ b/tests/components/socket/test_wake_loop_threadsafe.py @@ -66,12 +66,12 @@ def test_require_wake_loop_threadsafe__no_networking_does_not_consume_socket() - CORE.config = {"logger": {}} # Track initial socket consumer state - initial_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS, {}) + initial_udp = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) # Call require_wake_loop_threadsafe socket.require_wake_loop_threadsafe() # Verify no socket was consumed - consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS, {}) - assert "socket.wake_loop_threadsafe" not in consumers - assert consumers == initial_consumers + udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) + assert "socket.wake_loop_threadsafe" not in udp_consumers + assert udp_consumers == initial_udp From 263fff0ba2fc5ea7b9c849da88600f17852a86aa Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:35:00 +0100 Subject: [PATCH 0870/2030] Move CONF_OUTPUT_POWER into const.py (#14201) --- esphome/components/cc1101/__init__.py | 2 +- esphome/components/wifi/__init__.py | 2 +- esphome/const.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/cc1101/__init__.py b/esphome/components/cc1101/__init__.py index 14b92a18a4..e2e5986daf 100644 --- a/esphome/components/cc1101/__init__.py +++ b/esphome/components/cc1101/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_DATA, CONF_FREQUENCY, CONF_ID, + CONF_OUTPUT_POWER, CONF_VALUE, CONF_WAIT_TIME, ) @@ -22,7 +23,6 @@ ns = cg.esphome_ns.namespace("cc1101") CC1101Component = ns.class_("CC1101Component", cg.Component, spi.SPIDevice) # Config keys -CONF_OUTPUT_POWER = "output_power" CONF_RX_ATTENUATION = "rx_attenuation" CONF_DC_BLOCKING_FILTER = "dc_blocking_filter" CONF_IF_FREQUENCY = "if_frequency" diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index b89245b10e..2aa63b87cc 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -42,6 +42,7 @@ from esphome.const import ( CONF_ON_CONNECT, CONF_ON_DISCONNECT, CONF_ON_ERROR, + CONF_OUTPUT_POWER, CONF_PASSWORD, CONF_POWER_SAVE_MODE, CONF_PRIORITY, @@ -344,7 +345,6 @@ def _validate(config): return config -CONF_OUTPUT_POWER = "output_power" CONF_PASSIVE_SCAN = "passive_scan" CONFIG_SCHEMA = cv.All( cv.Schema( diff --git a/esphome/const.py b/esphome/const.py index 0179aa129e..ccc9d56dbb 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -748,6 +748,7 @@ CONF_OTA = "ota" CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature" CONF_OUTPUT = "output" CONF_OUTPUT_ID = "output_id" +CONF_OUTPUT_POWER = "output_power" CONF_OUTPUT_SPEAKER = "output_speaker" CONF_OUTPUTS = "outputs" CONF_OVERSAMPLING = "oversampling" From 6e70987451dfce381645e06ec61e87fab745b900 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 21:35:30 -0600 Subject: [PATCH 0871/2030] [binary_sensor] Conditionally compile filter infrastructure (#14215) --- esphome/components/binary_sensor/__init__.py | 1 + esphome/components/binary_sensor/binary_sensor.cpp | 6 ++++++ esphome/components/binary_sensor/binary_sensor.h | 6 ++++++ esphome/components/binary_sensor/filter.cpp | 5 +++++ esphome/components/binary_sensor/filter.h | 5 +++++ esphome/core/defines.h | 1 + 6 files changed, 24 insertions(+) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index c38d6b78d3..4500168cb1 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -562,6 +562,7 @@ async def setup_binary_sensor_core_(var, config): if inverted := config.get(CONF_INVERTED): cg.add(var.set_inverted(inverted)) if filters_config := config.get(CONF_FILTERS): + cg.add_define("USE_BINARY_SENSOR_FILTER") filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config) cg.add(var.add_filters(filters)) diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index 7c3b06970d..c4d3a29a1e 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -18,11 +18,15 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi } void BinarySensor::publish_state(bool new_state) { +#ifdef USE_BINARY_SENSOR_FILTER if (this->filter_list_ == nullptr) { +#endif this->send_state_internal(new_state); +#ifdef USE_BINARY_SENSOR_FILTER } else { this->filter_list_->input(new_state); } +#endif } void BinarySensor::publish_initial_state(bool new_state) { this->invalidate_state(); @@ -47,6 +51,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) { return false; } +#ifdef USE_BINARY_SENSOR_FILTER void BinarySensor::add_filter(Filter *filter) { filter->parent_ = this; if (this->filter_list_ == nullptr) { @@ -63,6 +68,7 @@ void BinarySensor::add_filters(std::initializer_list<Filter *> filters) { this->add_filter(filter); } } +#endif // USE_BINARY_SENSOR_FILTER bool BinarySensor::is_status_binary_sensor() const { return false; } } // namespace esphome::binary_sensor diff --git a/esphome/components/binary_sensor/binary_sensor.h b/esphome/components/binary_sensor/binary_sensor.h index 83c992bfed..4b655e1bd1 100644 --- a/esphome/components/binary_sensor/binary_sensor.h +++ b/esphome/components/binary_sensor/binary_sensor.h @@ -2,7 +2,9 @@ #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" +#ifdef USE_BINARY_SENSOR_FILTER #include "esphome/components/binary_sensor/filter.h" +#endif #include <initializer_list> @@ -45,8 +47,10 @@ class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceCl */ void publish_initial_state(bool new_state); +#ifdef USE_BINARY_SENSOR_FILTER void add_filter(Filter *filter); void add_filters(std::initializer_list<Filter *> filters); +#endif // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) @@ -60,7 +64,9 @@ class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceCl bool state{}; protected: +#ifdef USE_BINARY_SENSOR_FILTER Filter *filter_list_{nullptr}; +#endif bool set_new_state(const optional<bool> &new_state) override; }; diff --git a/esphome/components/binary_sensor/filter.cpp b/esphome/components/binary_sensor/filter.cpp index d69671c5bf..25a69c413a 100644 --- a/esphome/components/binary_sensor/filter.cpp +++ b/esphome/components/binary_sensor/filter.cpp @@ -1,3 +1,6 @@ +#include "esphome/core/defines.h" +#ifdef USE_BINARY_SENSOR_FILTER + #include "filter.h" #include "binary_sensor.h" @@ -142,3 +145,5 @@ optional<bool> SettleFilter::new_value(bool value) { float SettleFilter::get_setup_priority() const { return setup_priority::HARDWARE; } } // namespace esphome::binary_sensor + +#endif // USE_BINARY_SENSOR_FILTER diff --git a/esphome/components/binary_sensor/filter.h b/esphome/components/binary_sensor/filter.h index 59bc43eeba..2735a32ab0 100644 --- a/esphome/components/binary_sensor/filter.h +++ b/esphome/components/binary_sensor/filter.h @@ -1,5 +1,8 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_BINARY_SENSOR_FILTER + #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" @@ -138,3 +141,5 @@ class SettleFilter : public Filter, public Component { }; } // namespace esphome::binary_sensor + +#endif // USE_BINARY_SENSOR_FILTER diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1128df94f0..99e80785ec 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -29,6 +29,7 @@ #define USE_ALARM_CONTROL_PANEL #define USE_AREAS #define USE_BINARY_SENSOR +#define USE_BINARY_SENSOR_FILTER #define USE_BUTTON #define USE_CAMERA #define USE_CLIMATE From 93ce582ad30d1059cf59335882a6bd231a93127e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 21:35:51 -0600 Subject: [PATCH 0872/2030] [sensor] Conditionally compile filter infrastructure (#14214) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bme680_bsec/bme680_bsec.h | 1 + esphome/components/haier/hon_climate.h | 1 + esphome/components/kamstrup_kmp/kamstrup_kmp.h | 1 + esphome/components/sensor/__init__.py | 1 + esphome/components/sensor/filter.cpp | 5 +++++ esphome/components/sensor/filter.h | 6 +++++- esphome/components/sensor/sensor.cpp | 6 ++++++ esphome/components/sensor/sensor.h | 8 ++++++++ esphome/components/sound_level/sound_level.h | 1 + esphome/components/wireguard/wireguard.h | 1 + esphome/core/defines.h | 1 + 11 files changed, 31 insertions(+), 1 deletion(-) diff --git a/esphome/components/bme680_bsec/bme680_bsec.h b/esphome/components/bme680_bsec/bme680_bsec.h index ec919f31df..22aa2789e6 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.h +++ b/esphome/components/bme680_bsec/bme680_bsec.h @@ -7,6 +7,7 @@ #include "esphome/core/preferences.h" #include "esphome/core/defines.h" #include <map> +#include <queue> #ifdef USE_BSEC #include <bsec.h> diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 608d5e7f21..4565ed2981 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -1,6 +1,7 @@ #pragma once #include <chrono> +#include <queue> #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" #endif diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.h b/esphome/components/kamstrup_kmp/kamstrup_kmp.h index f84e360132..725cf20abf 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.h +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.h @@ -1,5 +1,6 @@ #pragma once +#include <queue> #include "esphome/components/sensor/sensor.h" #include "esphome/components/uart/uart.h" #include "esphome/core/component.h" diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index ebbe0fbccc..b0e0c28bda 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -903,6 +903,7 @@ async def setup_sensor_core_(var, config): if config[CONF_FORCE_UPDATE]: cg.add(var.set_force_update(True)) if config.get(CONF_FILTERS): # must exist and not be empty + cg.add_define("USE_SENSOR_FILTER") filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index ea0e2f0d7c..cd4db98457 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -1,3 +1,6 @@ +#include "esphome/core/defines.h" +#ifdef USE_SENSOR_FILTER + #include "filter.h" #include <cmath> #include "esphome/core/application.h" @@ -580,3 +583,5 @@ void StreamingMovingAverageFilter::reset_batch() { } } // namespace esphome::sensor + +#endif // USE_SENSOR_FILTER diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 573b916a5d..8bfcdb37cf 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -1,6 +1,8 @@ #pragma once -#include <queue> +#include "esphome/core/defines.h" +#ifdef USE_SENSOR_FILTER + #include <utility> #include <vector> #include "esphome/core/automation.h" @@ -638,3 +640,5 @@ class StreamingMovingAverageFilter : public StreamingFilter { }; } // namespace esphome::sensor + +#endif // USE_SENSOR_FILTER diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index ae2ee3e3d1..a7af6403ef 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -68,11 +68,15 @@ void Sensor::publish_state(float state) { ESP_LOGV(TAG, "'%s': Received new state %f", this->name_.c_str(), state); +#ifdef USE_SENSOR_FILTER if (this->filter_list_ == nullptr) { +#endif this->internal_send_state_to_frontend(state); +#ifdef USE_SENSOR_FILTER } else { this->filter_list_->input(state); } +#endif } void Sensor::add_on_state_callback(std::function<void(float)> &&callback) { this->callback_.add(std::move(callback)); } @@ -80,6 +84,7 @@ void Sensor::add_on_raw_state_callback(std::function<void(float)> &&callback) { this->raw_callback_.add(std::move(callback)); } +#ifdef USE_SENSOR_FILTER void Sensor::add_filter(Filter *filter) { // inefficient, but only happens once on every sensor setup and nobody's going to have massive amounts of // filters @@ -109,6 +114,7 @@ void Sensor::clear_filters() { } this->filter_list_ = nullptr; } +#endif // USE_SENSOR_FILTER float Sensor::get_state() const { return this->state; } float Sensor::get_raw_state() const { return this->raw_state; } diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index 80981b8e28..54e75ee2a1 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -4,13 +4,17 @@ #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#ifdef USE_SENSOR_FILTER #include "esphome/components/sensor/filter.h" +#endif #include <initializer_list> #include <memory> namespace esphome::sensor { +class Sensor; + void log_sensor(const char *tag, const char *prefix, const char *type, Sensor *obj); #define LOG_SENSOR(prefix, type, obj) log_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj) @@ -67,6 +71,7 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa /// Set force update mode. void set_force_update(bool force_update) { sensor_flags_.force_update = force_update; } +#ifdef USE_SENSOR_FILTER /// Add a filter to the filter chain. Will be appended to the back. void add_filter(Filter *filter); @@ -87,6 +92,7 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa /// Clear the entire filter chain. void clear_filters(); +#endif /// Getter-syntax for .state. float get_state() const; @@ -130,7 +136,9 @@ class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBa LazyCallbackManager<void(float)> raw_callback_; ///< Storage for raw state callbacks. LazyCallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks. +#ifdef USE_SENSOR_FILTER Filter *filter_list_{nullptr}; ///< Store all active filters. +#endif // Group small members together to avoid padding int8_t accuracy_decimals_{-1}; ///< Accuracy in decimals (-1 = not set) diff --git a/esphome/components/sound_level/sound_level.h b/esphome/components/sound_level/sound_level.h index dc35f69fe2..a1021eb1e8 100644 --- a/esphome/components/sound_level/sound_level.h +++ b/esphome/components/sound_level/sound_level.h @@ -6,6 +6,7 @@ #include "esphome/components/microphone/microphone_source.h" #include "esphome/components/sensor/sensor.h" +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/ring_buffer.h" diff --git a/esphome/components/wireguard/wireguard.h b/esphome/components/wireguard/wireguard.h index e8470c75cd..c11d592cd1 100644 --- a/esphome/components/wireguard/wireguard.h +++ b/esphome/components/wireguard/wireguard.h @@ -4,6 +4,7 @@ #include <ctime> #include <initializer_list> +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/components/time/real_time_clock.h" diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 99e80785ec..ff32edff16 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -112,6 +112,7 @@ #define USE_SAFE_MODE_CALLBACK #define USE_SELECT #define USE_SENSOR +#define USE_SENSOR_FILTER #define USE_SETUP_PRIORITY_OVERRIDE #define USE_STATUS_LED #define USE_STATUS_SENSOR From d239a2400dddfb9854ea5e6c7f476002b6bf22c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 21:36:21 -0600 Subject: [PATCH 0873/2030] [text_sensor] Conditionally compile filter infrastructure (#14213) --- esphome/components/text_sensor/__init__.py | 1 + esphome/components/text_sensor/filter.cpp | 5 +++++ esphome/components/text_sensor/filter.h | 5 +++++ esphome/components/text_sensor/text_sensor.cpp | 18 +++++++++++++----- esphome/components/text_sensor/text_sensor.h | 8 ++++++++ esphome/core/defines.h | 1 + 6 files changed, 33 insertions(+), 5 deletions(-) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 0d22400a8e..2e8edb43c9 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -204,6 +204,7 @@ async def setup_text_sensor_core_(var, config): cg.add(var.set_device_class(device_class)) if config.get(CONF_FILTERS): # must exist and not be empty + cg.add_define("USE_TEXT_SENSOR_FILTER") filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) diff --git a/esphome/components/text_sensor/filter.cpp b/esphome/components/text_sensor/filter.cpp index 4ee12e8602..f6552c7c66 100644 --- a/esphome/components/text_sensor/filter.cpp +++ b/esphome/components/text_sensor/filter.cpp @@ -1,3 +1,6 @@ +#include "esphome/core/defines.h" +#ifdef USE_TEXT_SENSOR_FILTER + #include "filter.h" #include "text_sensor.h" #include "esphome/core/log.h" @@ -106,3 +109,5 @@ bool MapFilter::new_value(std::string &value) { } // namespace text_sensor } // namespace esphome + +#endif // USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/filter.h b/esphome/components/text_sensor/filter.h index 1922b503ca..f88e8645cc 100644 --- a/esphome/components/text_sensor/filter.h +++ b/esphome/components/text_sensor/filter.h @@ -1,5 +1,8 @@ #pragma once +#include "esphome/core/defines.h" +#ifdef USE_TEXT_SENSOR_FILTER + #include "esphome/core/component.h" #include "esphome/core/helpers.h" @@ -164,3 +167,5 @@ class MapFilter : public Filter { } // namespace text_sensor } // namespace esphome + +#endif // USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index c48bdf4b82..c66d08ec40 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -24,7 +24,9 @@ void TextSensor::publish_state(const std::string &state) { this->publish_state(s void TextSensor::publish_state(const char *state) { this->publish_state(state, strlen(state)); } void TextSensor::publish_state(const char *state, size_t len) { +#ifdef USE_TEXT_SENSOR_FILTER if (this->filter_list_ == nullptr) { +#endif // No filters: raw_state == state, store once and use for both callbacks // Only assign if changed to avoid heap allocation if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) { @@ -33,6 +35,7 @@ void TextSensor::publish_state(const char *state, size_t len) { this->raw_callback_.call(this->state); ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), this->state.c_str()); this->notify_frontend_(); +#ifdef USE_TEXT_SENSOR_FILTER } else { // Has filters: need separate raw storage #pragma GCC diagnostic push @@ -46,8 +49,10 @@ void TextSensor::publish_state(const char *state, size_t len) { this->filter_list_->input(this->raw_state); #pragma GCC diagnostic pop } +#endif } +#ifdef USE_TEXT_SENSOR_FILTER void TextSensor::add_filter(Filter *filter) { // inefficient, but only happens once on every sensor setup and nobody's going to have massive amounts of // filters @@ -77,6 +82,7 @@ void TextSensor::clear_filters() { } this->filter_list_ = nullptr; } +#endif // USE_TEXT_SENSOR_FILTER void TextSensor::add_on_state_callback(std::function<void(const std::string &)> callback) { this->callback_.add(std::move(callback)); @@ -87,14 +93,16 @@ void TextSensor::add_on_raw_state_callback(std::function<void(const std::string const std::string &TextSensor::get_state() const { return this->state; } const std::string &TextSensor::get_raw_state() const { - if (this->filter_list_ == nullptr) { - return this->state; // No filters, raw == filtered - } -// Suppress deprecation warning - get_raw_state() is the replacement API +#ifdef USE_TEXT_SENSOR_FILTER + if (this->filter_list_ != nullptr) { + // Suppress deprecation warning - get_raw_state() is the replacement API #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - return this->raw_state; + return this->raw_state; #pragma GCC diagnostic pop + } +#endif + return this->state; // No filters, raw == filtered } void TextSensor::internal_send_state_to_frontend(const std::string &state) { this->internal_send_state_to_frontend(state.data(), state.size()); diff --git a/esphome/components/text_sensor/text_sensor.h b/esphome/components/text_sensor/text_sensor.h index 1352a8c1e4..97373dc716 100644 --- a/esphome/components/text_sensor/text_sensor.h +++ b/esphome/components/text_sensor/text_sensor.h @@ -3,7 +3,9 @@ #include "esphome/core/component.h" #include "esphome/core/entity_base.h" #include "esphome/core/helpers.h" +#ifdef USE_TEXT_SENSOR_FILTER #include "esphome/components/text_sensor/filter.h" +#endif #include <initializer_list> #include <memory> @@ -11,6 +13,8 @@ namespace esphome { namespace text_sensor { +class TextSensor; + void log_text_sensor(const char *tag, const char *prefix, const char *type, TextSensor *obj); #define LOG_TEXT_SENSOR(prefix, type, obj) log_text_sensor(TAG, prefix, LOG_STR_LITERAL(type), obj) @@ -45,6 +49,7 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass { void publish_state(const char *state); void publish_state(const char *state, size_t len); +#ifdef USE_TEXT_SENSOR_FILTER /// Add a filter to the filter chain. Will be appended to the back. void add_filter(Filter *filter); @@ -56,6 +61,7 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass { /// Clear the entire filter chain. void clear_filters(); +#endif void add_on_state_callback(std::function<void(const std::string &)> callback); /// Add a callback that will be called every time the sensor sends a raw value. @@ -73,7 +79,9 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass { LazyCallbackManager<void(const std::string &)> raw_callback_; ///< Storage for raw state callbacks. LazyCallbackManager<void(const std::string &)> callback_; ///< Storage for filtered state callbacks. +#ifdef USE_TEXT_SENSOR_FILTER Filter *filter_list_{nullptr}; ///< Store all active filters. +#endif }; } // namespace text_sensor diff --git a/esphome/core/defines.h b/esphome/core/defines.h index ff32edff16..a1e3d1707f 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -119,6 +119,7 @@ #define USE_SWITCH #define USE_TEXT #define USE_TEXT_SENSOR +#define USE_TEXT_SENSOR_FILTER #define USE_TIME #define USE_TOUCHSCREEN #define USE_UART_DEBUGGER From 5c388a5200b65a9e4470d4f4a681e41c49517915 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:39:36 +0100 Subject: [PATCH 0874/2030] [openthread_info] Optimize: Devirtualize/unify (#14208) --- .../openthread_info_text_sensor.h | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/esphome/components/openthread_info/openthread_info_text_sensor.h b/esphome/components/openthread_info/openthread_info_text_sensor.h index ac5623e0c1..10e83281f0 100644 --- a/esphome/components/openthread_info/openthread_info_text_sensor.h +++ b/esphome/components/openthread_info/openthread_info_text_sensor.h @@ -25,7 +25,7 @@ class OpenThreadInstancePollingComponent : public PollingComponent { virtual void update_instance(otInstance *instance) = 0; }; -class IPAddressOpenThreadInfo : public PollingComponent, public text_sensor::TextSensor { +class IPAddressOpenThreadInfo final : public PollingComponent, public text_sensor::TextSensor { public: void update() override { std::optional<otIp6Address> address = openthread::global_openthread_component->get_omr_address(); @@ -48,7 +48,7 @@ class IPAddressOpenThreadInfo : public PollingComponent, public text_sensor::Tex std::string last_ip_; }; -class RoleOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { +class RoleOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { public: void update_instance(otInstance *instance) override { otDeviceRole role = otThreadGetDeviceRole(instance); @@ -64,7 +64,7 @@ class RoleOpenThreadInfo : public OpenThreadInstancePollingComponent, public tex otDeviceRole last_role_; }; -class Rloc16OpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { +class Rloc16OpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { public: void update_instance(otInstance *instance) override { uint16_t rloc16 = otThreadGetRloc16(instance); @@ -75,14 +75,13 @@ class Rloc16OpenThreadInfo : public OpenThreadInstancePollingComponent, public t this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: uint16_t last_rloc16_; }; -class ExtAddrOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { +class ExtAddrOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { public: void update_instance(otInstance *instance) override { const auto *extaddr = otLinkGetExtendedAddress(instance); @@ -93,14 +92,13 @@ class ExtAddrOpenThreadInfo : public OpenThreadInstancePollingComponent, public this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: std::array<uint8_t, 8> last_extaddr_{}; }; -class Eui64OpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { +class Eui64OpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { public: void update_instance(otInstance *instance) override { otExtAddress addr; @@ -113,14 +111,13 @@ class Eui64OpenThreadInfo : public OpenThreadInstancePollingComponent, public te this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: std::array<uint8_t, 8> last_eui64_{}; }; -class ChannelOpenThreadInfo : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { +class ChannelOpenThreadInfo final : public OpenThreadInstancePollingComponent, public text_sensor::TextSensor { public: void update_instance(otInstance *instance) override { uint8_t channel = otLinkGetChannel(instance); @@ -131,7 +128,6 @@ class ChannelOpenThreadInfo : public OpenThreadInstancePollingComponent, public this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: @@ -153,7 +149,7 @@ class DatasetOpenThreadInfo : public OpenThreadInstancePollingComponent { virtual void update_dataset(otOperationalDataset *dataset) = 0; }; -class NetworkNameOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor { +class NetworkNameOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor { public: void update_dataset(otOperationalDataset *dataset) override { if (this->last_network_name_ != dataset->mNetworkName.m8) { @@ -161,14 +157,13 @@ class NetworkNameOpenThreadInfo : public DatasetOpenThreadInfo, public text_sens this->publish_state(this->last_network_name_); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: std::string last_network_name_; }; -class NetworkKeyOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor { +class NetworkKeyOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor { public: void update_dataset(otOperationalDataset *dataset) override { if (!std::equal(this->last_key_.begin(), this->last_key_.end(), dataset->mNetworkKey.m8)) { @@ -178,14 +173,13 @@ class NetworkKeyOpenThreadInfo : public DatasetOpenThreadInfo, public text_senso this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: std::array<uint8_t, 16> last_key_{}; }; -class PanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor { +class PanIdOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor { public: void update_dataset(otOperationalDataset *dataset) override { uint16_t panid = dataset->mPanId; @@ -196,14 +190,13 @@ class PanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::Te this->publish_state(buf); } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: uint16_t last_panid_; }; -class ExtPanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor::TextSensor { +class ExtPanIdOpenThreadInfo final : public DatasetOpenThreadInfo, public text_sensor::TextSensor { public: void update_dataset(otOperationalDataset *dataset) override { if (!std::equal(this->last_extpanid_.begin(), this->last_extpanid_.end(), dataset->mExtendedPanId.m8)) { @@ -214,7 +207,6 @@ class ExtPanIdOpenThreadInfo : public DatasetOpenThreadInfo, public text_sensor: } } - float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } void dump_config() override; protected: From 680160453355210018b073e0036c256d45a143ce Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:40:40 +0100 Subject: [PATCH 0875/2030] [openthread] Add Thread version DEBUG trace (#14196) --- esphome/components/openthread/openthread_esp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index ec212d1f68..4f8db0634a 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -104,6 +104,8 @@ void OpenThreadComponent::ot_main() { esp_cli_custom_command_init(); #endif // CONFIG_OPENTHREAD_CLI_ESP_EXTENSION + ESP_LOGD(TAG, "Thread Version: %" PRIu16, otThreadGetVersion()); + otLinkModeConfig link_mode_config{}; #if CONFIG_OPENTHREAD_FTD link_mode_config.mRxOnWhenIdle = true; From ee94bc471541a460c989b51cf317530b7ffa4611 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 23 Feb 2026 04:43:42 +0100 Subject: [PATCH 0876/2030] [openthread] Refactor to optimize and match code rules (#14156) --- esphome/components/openthread/openthread.cpp | 4 +-- esphome/components/openthread/openthread.h | 10 +++---- .../components/openthread/openthread_esp.cpp | 29 ++++++++++--------- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index 90da17e2d3..d22a14aeae 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -35,9 +35,9 @@ void OpenThreadComponent::dump_config() { #elif CONFIG_OPENTHREAD_MTD ESP_LOGCONFIG(TAG, " Device Type: MTD"); // TBD: Synchronized Sleepy End Device - if (this->poll_period > 0) { + if (this->poll_period_ > 0) { ESP_LOGCONFIG(TAG, " Device is configured as Sleepy End Device (SED)"); - uint32_t duration = this->poll_period / 1000; + uint32_t duration = this->poll_period_ / 1000; ESP_LOGCONFIG(TAG, " Poll Period: %" PRIu32 "s", duration); } else { ESP_LOGCONFIG(TAG, " Device is configured as Minimal End Device (MED)"); diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 3c60acaadd..9e429f289b 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -36,22 +36,22 @@ class OpenThreadComponent : public Component { const char *get_use_address() const; void set_use_address(const char *use_address); #if CONFIG_OPENTHREAD_MTD - void set_poll_period(uint32_t poll_period) { this->poll_period = poll_period; } + void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; } #endif protected: std::optional<otIp6Address> get_omr_address_(InstanceLock &lock); + std::function<void()> factory_reset_external_callback_; +#if CONFIG_OPENTHREAD_MTD + uint32_t poll_period_{0}; +#endif bool teardown_started_{false}; bool teardown_complete_{false}; - std::function<void()> factory_reset_external_callback_; private: // Stores a pointer to a string literal (static storage duration). // ONLY set from Python-generated code with string literals - never dynamic strings. const char *use_address_{""}; -#if CONFIG_OPENTHREAD_MTD - uint32_t poll_period{0}; -#endif }; extern OpenThreadComponent *global_openthread_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 4f8db0634a..bb70701471 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -81,9 +81,11 @@ void OpenThreadComponent::ot_main() { // Initialize the OpenThread stack // otLoggingSetLevel(OT_LOG_LEVEL_DEBG); ESP_ERROR_CHECK(esp_openthread_init(&config)); + // Fetch OT instance once to avoid repeated call into OT stack + otInstance *instance = esp_openthread_get_instance(); #if CONFIG_OPENTHREAD_STATE_INDICATOR_ENABLE - ESP_ERROR_CHECK(esp_openthread_state_indicator_init(esp_openthread_get_instance())); + ESP_ERROR_CHECK(esp_openthread_state_indicator_init(instance)); #endif #if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC @@ -112,28 +114,29 @@ void OpenThreadComponent::ot_main() { link_mode_config.mDeviceType = true; link_mode_config.mNetworkData = true; #elif CONFIG_OPENTHREAD_MTD - if (this->poll_period > 0) { - if (otLinkSetPollPeriod(esp_openthread_get_instance(), this->poll_period) != OT_ERROR_NONE) { - ESP_LOGE(TAG, "Failed to set OpenThread pollperiod."); + if (this->poll_period_ > 0) { + if (otLinkSetPollPeriod(instance, this->poll_period_) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to set pollperiod"); } - uint32_t link_polling_period = otLinkGetPollPeriod(esp_openthread_get_instance()); - ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, link_polling_period); + ESP_LOGD(TAG, "Link Polling Period: %" PRIu32, otLinkGetPollPeriod(instance)); } - link_mode_config.mRxOnWhenIdle = this->poll_period == 0; + link_mode_config.mRxOnWhenIdle = this->poll_period_ == 0; link_mode_config.mDeviceType = false; link_mode_config.mNetworkData = false; #endif - if (otThreadSetLinkMode(esp_openthread_get_instance(), link_mode_config) != OT_ERROR_NONE) { - ESP_LOGE(TAG, "Failed to set OpenThread linkmode."); + if (otThreadSetLinkMode(instance, link_mode_config) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to set linkmode"); } - link_mode_config = otThreadGetLinkMode(esp_openthread_get_instance()); +#ifdef ESPHOME_LOG_HAS_DEBUG // Fetch link mode from OT only when DEBUG + link_mode_config = otThreadGetLinkMode(instance); ESP_LOGD(TAG, "Link Mode Device Type: %s\n" "Link Mode Network Data: %s\n" "Link Mode RX On When Idle: %s", - link_mode_config.mDeviceType ? "true" : "false", link_mode_config.mNetworkData ? "true" : "false", - link_mode_config.mRxOnWhenIdle ? "true" : "false"); + TRUEFALSE(link_mode_config.mDeviceType), TRUEFALSE(link_mode_config.mNetworkData), + TRUEFALSE(link_mode_config.mRxOnWhenIdle)); +#endif // Run the main loop #if CONFIG_OPENTHREAD_CLI @@ -144,7 +147,7 @@ void OpenThreadComponent::ot_main() { #ifndef USE_OPENTHREAD_FORCE_DATASET // Check if openthread has a valid dataset from a previous execution - otError error = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &dataset); + otError error = otDatasetGetActiveTlvs(instance, &dataset); if (error != OT_ERROR_NONE) { // Make sure the length is 0 so we fallback to the configuration dataset.mLength = 0; From 417f4535af983e90d5ac2407847a29f15cb4905e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 22:25:20 -0600 Subject: [PATCH 0877/2030] [logger] Use subtraction-based line number formatting to avoid division (#14219) --- esphome/components/logger/log_buffer.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/esphome/components/logger/log_buffer.h b/esphome/components/logger/log_buffer.h index 3d87278248..a56276f732 100644 --- a/esphome/components/logger/log_buffer.h +++ b/esphome/components/logger/log_buffer.h @@ -75,18 +75,13 @@ struct LogBuffer { *p++ = ':'; - // Format line number without modulo operations + // Format line number using subtraction loops (no division - important for ESP8266 which lacks hardware divider) if (line > 999) [[unlikely]] { - int thousands = line / 1000; - *p++ = '0' + thousands; - line -= thousands * 1000; + write_digit(p, line, 1000); } - int hundreds = line / 100; - int remainder = line - hundreds * 100; - int tens = remainder / 10; - *p++ = '0' + hundreds; - *p++ = '0' + tens; - *p++ = '0' + (remainder - tens * 10); + write_digit(p, line, 100); + write_digit(p, line, 10); + *p++ = '0' + line; *p++ = ']'; #if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR) || defined(USE_HOST) @@ -162,6 +157,15 @@ struct LogBuffer { this->process_vsnprintf_result_(vsnprintf_P(this->current_(), this->remaining_(), format, args)); } #endif + // Extract one decimal digit via subtraction (no division - important for ESP8266) + static inline void ESPHOME_ALWAYS_INLINE write_digit(char *&p, int &value, int divisor) { + char d = '0'; + while (value >= divisor) { + d++; + value -= divisor; + } + *p++ = d; + } // Write ANSI color escape sequence to buffer, updates pointer in place // Caller is responsible for ensuring buffer has sufficient space void write_ansi_color_(char *&p, uint8_t level) { From fb6c7d81d5b3832c19eb1dd7b61c70a944742d8a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 23 Feb 2026 00:08:40 -0500 Subject: [PATCH 0878/2030] [core] Fix multiline log continuations without leading whitespace (#14217) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../absolute_humidity/absolute_humidity.cpp | 5 +- esphome/components/anova/anova.cpp | 6 +- esphome/components/as3935/as3935.cpp | 6 +- esphome/components/at581x/at581x.cpp | 16 ++--- .../components/binary_sensor/automation.cpp | 6 +- esphome/components/bl0940/bl0940.cpp | 5 +- .../current_based/current_based_cover.cpp | 8 +-- esphome/components/debug/debug_esp32.cpp | 60 ++++++++++--------- esphome/components/debug/debug_esp8266.cpp | 18 +++--- esphome/components/debug/debug_libretiny.cpp | 14 +++-- esphome/components/debug/debug_zephyr.cpp | 42 +++++++------ .../components/dfrobot_sen0395/commands.cpp | 16 ++--- esphome/components/emmeti/emmeti.cpp | 19 ++---- .../components/ens160_base/ens160_base.cpp | 13 ++-- esphome/components/es8388/es8388.cpp | 7 ++- .../esp32_ble_client/ble_client_base.cpp | 6 +- .../update/esp32_hosted_update.cpp | 11 ++-- .../packet_transport/espnow_transport.cpp | 8 +-- .../ethernet/ethernet_component.cpp | 5 +- esphome/components/ezo_pmp/ezo_pmp.cpp | 6 +- esphome/components/gcja5/gcja5.cpp | 8 +-- .../graphical_display_menu.cpp | 14 ++--- .../components/honeywellabp/honeywellabp.cpp | 5 +- .../http_request/ota/ota_http_request.cpp | 3 +- .../components/ina2xx_base/ina2xx_base.cpp | 6 +- esphome/components/ld2410/ld2410.cpp | 7 +-- esphome/components/ld2412/ld2412.cpp | 5 +- esphome/components/ledc/ledc_output.cpp | 6 +- esphome/components/max6956/max6956.cpp | 6 +- .../components/mqtt/mqtt_backend_esp32.cpp | 5 +- .../nextion/nextion_upload_arduino.cpp | 22 ++----- .../nextion/nextion_upload_esp32.cpp | 30 ++-------- .../components/openthread/openthread_esp.cpp | 8 +-- .../components/pi4ioe5v6408/pi4ioe5v6408.cpp | 7 ++- esphome/components/pipsolar/pipsolar.cpp | 3 +- esphome/components/pn532/pn532.cpp | 5 +- esphome/components/pn7150/pn7150.cpp | 15 +++-- esphome/components/pn7160/pn7160.cpp | 16 +++-- esphome/components/qmp6988/qmp6988.cpp | 26 ++++---- .../remote_base/pronto_protocol.cpp | 5 +- esphome/components/safe_mode/safe_mode.cpp | 10 ++-- esphome/components/sim800l/sim800l.cpp | 2 +- esphome/components/sonoff_d1/sonoff_d1.cpp | 10 +--- esphome/components/sun/sun.cpp | 29 ++++----- .../components/usb_host/usb_host_client.cpp | 44 +++++++------- esphome/components/usb_uart/cp210x.cpp | 6 +- .../voice_assistant/voice_assistant.cpp | 4 +- esphome/components/wl_134/wl_134.cpp | 13 ++-- esphome/components/xgzp68xx/xgzp68xx.cpp | 6 +- script/ci-custom.py | 33 ++++++++++ 50 files changed, 291 insertions(+), 345 deletions(-) diff --git a/esphome/components/absolute_humidity/absolute_humidity.cpp b/esphome/components/absolute_humidity/absolute_humidity.cpp index 9c66531d05..40676f8655 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.cpp +++ b/esphome/components/absolute_humidity/absolute_humidity.cpp @@ -92,10 +92,7 @@ void AbsoluteHumidityComponent::loop() { // Calculate absolute humidity const float absolute_humidity = vapor_density(es, hr, temperature_k); - ESP_LOGD(TAG, - "Saturation vapor pressure %f kPa\n" - "Publishing absolute humidity %f g/m³", - es, absolute_humidity); + ESP_LOGD(TAG, "Saturation vapor pressure %f kPa, absolute humidity %f g/m³", es, absolute_humidity); // Publish absolute humidity this->status_clear_warning(); diff --git a/esphome/components/anova/anova.cpp b/esphome/components/anova/anova.cpp index 5054488089..2693224a97 100644 --- a/esphome/components/anova/anova.cpp +++ b/esphome/components/anova/anova.cpp @@ -67,10 +67,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_ case ESP_GATTC_SEARCH_CMPL_EVT: { auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID); if (chr == nullptr) { - ESP_LOGW(TAG, - "[%s] No control service found at device, not an Anova..?\n" - "[%s] Note, this component does not currently support Anova Nano.", - this->get_name().c_str(), this->get_name().c_str()); + ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str()); + ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str()); break; } this->char_handle_ = chr->handle; diff --git a/esphome/components/as3935/as3935.cpp b/esphome/components/as3935/as3935.cpp index dd0ab714f7..c4dc0466a0 100644 --- a/esphome/components/as3935/as3935.cpp +++ b/esphome/components/as3935/as3935.cpp @@ -307,9 +307,9 @@ void AS3935Component::tune_antenna() { uint8_t tune_val = this->read_capacitance(); ESP_LOGI(TAG, "Starting antenna tuning\n" - "Division Ratio is set to: %d\n" - "Internal Capacitor is set to: %d\n" - "Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio", + " Division Ratio is set to: %d\n" + " Internal Capacitor is set to: %d\n" + " Displaying oscillator on INT pin. Measure its frequency - multiply value by Division Ratio", div_ratio, tune_val); this->display_oscillator(true, ANTFREQ); } diff --git a/esphome/components/at581x/at581x.cpp b/esphome/components/at581x/at581x.cpp index 6804a7f4b5..728fbe20c6 100644 --- a/esphome/components/at581x/at581x.cpp +++ b/esphome/components/at581x/at581x.cpp @@ -77,14 +77,14 @@ void AT581XComponent::dump_config() { LOG_I2C_DEVICE(this); } bool AT581XComponent::i2c_write_config() { ESP_LOGCONFIG(TAG, "Writing new config for AT581X\n" - "Frequency: %dMHz\n" - "Sensing distance: %d\n" - "Power: %dµA\n" - "Gain: %d\n" - "Trigger base time: %dms\n" - "Trigger keep time: %dms\n" - "Protect time: %dms\n" - "Self check time: %dms", + " Frequency: %dMHz\n" + " Sensing distance: %d\n" + " Power: %dµA\n" + " Gain: %d\n" + " Trigger base time: %dms\n" + " Trigger keep time: %dms\n" + " Protect time: %dms\n" + " Self check time: %dms", this->freq_, this->delta_, this->power_, this->gain_, this->trigger_base_time_ms_, this->trigger_keep_time_ms_, this->protect_time_ms_, this->self_check_time_ms_); diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index faebe7e88f..7e43d42357 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -29,10 +29,8 @@ void MultiClickTrigger::on_state_(bool state) { // Start matching MultiClickTriggerEvent evt = this->timing_[0]; if (evt.state == state) { - ESP_LOGV(TAG, - "START min=%" PRIu32 " max=%" PRIu32 "\n" - "Multi Click: Starting multi click action!", - evt.min_length, evt.max_length); + ESP_LOGV(TAG, "START min=%" PRIu32 " max=%" PRIu32, evt.min_length, evt.max_length); + ESP_LOGV(TAG, "Multi Click: Starting multi click action!"); this->at_index_ = 1; if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) { this->set_timeout(MULTICLICK_TRIGGER_ID, evt.min_length, [this]() { this->trigger_(); }); diff --git a/esphome/components/bl0940/bl0940.cpp b/esphome/components/bl0940/bl0940.cpp index 42e20eb69b..31625ebf6d 100644 --- a/esphome/components/bl0940/bl0940.cpp +++ b/esphome/components/bl0940/bl0940.cpp @@ -182,7 +182,10 @@ void BL0940::recalibrate_() { ESP_LOGD(TAG, "Recalibrated reference values:\n" - "Voltage: %f\n, Current: %f\n, Power: %f\n, Energy: %f\n", + " Voltage: %f\n" + " Current: %f\n" + " Power: %f\n" + " Energy: %f", this->voltage_reference_cal_, this->current_reference_cal_, this->power_reference_cal_, this->energy_reference_cal_); } diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index 5dfaeeff39..58ae7cbc34 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -148,14 +148,14 @@ void CurrentBasedCover::dump_config() { } ESP_LOGCONFIG(TAG, " Close Duration: %.1fs\n" - "Obstacle Rollback: %.1f%%", + " Obstacle Rollback: %.1f%%", this->close_duration_ / 1e3f, this->obstacle_rollback_ * 100); if (this->max_duration_ != UINT32_MAX) { - ESP_LOGCONFIG(TAG, "Maximum duration: %.1fs", this->max_duration_ / 1e3f); + ESP_LOGCONFIG(TAG, " Maximum duration: %.1fs", this->max_duration_ / 1e3f); } ESP_LOGCONFIG(TAG, - "Start sensing delay: %.1fs\n" - "Malfunction detection: %s", + " Start sensing delay: %.1fs\n" + " Malfunction detection: %s", this->start_sensing_delay_ / 1e3f, YESNO(this->malfunction_detection_)); } diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index aad4c7426c..6898621dd0 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -79,7 +79,6 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE } else { snprintf(buf, size, "unknown source"); } - ESP_LOGD(TAG, "Reset Reason: %s", buf); return buf; } @@ -107,7 +106,6 @@ const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFE } else { wake_reason = "unknown source"; } - ESP_LOGD(TAG, "Wakeup Reason: %s", wake_reason); // Return the static string directly - no need to copy to buffer return wake_reason; } @@ -172,7 +170,6 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> } uint32_t flash_size = ESP.getFlashChipSize() / 1024; // NOLINT uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000; // NOLINT - ESP_LOGD(TAG, "Flash Chip: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode); pos = buf_append_printf(buf, size, pos, "|Flash: %" PRIu32 "kB Speed:%" PRIu32 "MHz Mode:%s", flash_size, flash_speed, flash_mode); #endif @@ -194,39 +191,46 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> if (info.features != 0) { pos = buf_append_printf(buf, size, pos, "%sOther:0x%" PRIx32, first_feature ? "" : ", ", info.features); } - ESP_LOGD(TAG, "Chip: Model=%s, Cores=%u, Revision=%u", model, info.cores, info.revision); pos = buf_append_printf(buf, size, pos, " Cores:%u Revision:%u", info.cores, info.revision); uint32_t cpu_freq_mhz = arch_get_cpu_freq_hz() / 1000000; - ESP_LOGD(TAG, "CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); - // Framework detection -#ifdef USE_ARDUINO - ESP_LOGD(TAG, "Framework: Arduino"); - pos = buf_append_printf(buf, size, pos, "|Framework: Arduino"); -#elif defined(USE_ESP32) - ESP_LOGD(TAG, "Framework: ESP-IDF"); - pos = buf_append_printf(buf, size, pos, "|Framework: ESP-IDF"); -#else - ESP_LOGW(TAG, "Framework: UNKNOWN"); - pos = buf_append_printf(buf, size, pos, "|Framework: UNKNOWN"); -#endif - - ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version()); - pos = buf_append_printf(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version()); - - uint8_t mac[6]; - get_mac_address_raw(mac); - ESP_LOGD(TAG, "EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - pos = buf_append_printf(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], - mac[4], mac[5]); - char reason_buffer[RESET_REASON_BUFFER_SIZE]; const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); - pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason); - const char *wakeup_cause = get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); + + uint8_t mac[6]; + get_mac_address_raw(mac); + + ESP_LOGD(TAG, + "ESP32 debug info:\n" + " Chip: %s\n" + " Cores: %u\n" + " Revision: %u\n" + " CPU Frequency: %" PRIu32 " MHz\n" + " ESP-IDF Version: %s\n" + " EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X\n" + " Reset Reason: %s\n" + " Wakeup Cause: %s", + model, info.cores, info.revision, cpu_freq_mhz, esp_get_idf_version(), mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5], reset_reason, wakeup_cause); +#if defined(USE_ARDUINO) + ESP_LOGD(TAG, " Flash: Size=%" PRIu32 "kB Speed=%" PRIu32 "MHz Mode=%s", flash_size, flash_speed, flash_mode); +#endif + // Framework detection +#ifdef USE_ARDUINO + ESP_LOGD(TAG, " Framework: Arduino"); + pos = buf_append_printf(buf, size, pos, "|Framework: Arduino"); +#else + ESP_LOGD(TAG, " Framework: ESP-IDF"); + pos = buf_append_printf(buf, size, pos, "|Framework: ESP-IDF"); +#endif + + pos = buf_append_printf(buf, size, pos, "|ESP-IDF: %s", esp_get_idf_version()); + pos = buf_append_printf(buf, size, pos, "|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], + mac[4], mac[5]); + pos = buf_append_printf(buf, size, pos, "|Reset: %s", reset_reason); pos = buf_append_printf(buf, size, pos, "|Wakeup: %s", wakeup_cause); return pos; diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 1a07ec4f3a..4df4aaa851 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -128,14 +128,16 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> // NOLINTEND(readability-static-accessed-through-instance) ESP_LOGD(TAG, - "Chip ID: 0x%08" PRIX32 "\n" - "SDK Version: %s\n" - "Core Version: %s\n" - "Boot Version=%u Mode=%u\n" - "CPU Frequency: %u\n" - "Flash Chip ID=0x%08" PRIX32 "\n" - "Reset Reason: %s\n" - "Reset Info: %s", + "ESP8266 debug info:\n" + " Chip ID: 0x%08" PRIX32 "\n" + " SDK Version: %s\n" + " Core Version: %s\n" + " Boot Version: %u\n" + " Boot Mode: %u\n" + " CPU Frequency: %u\n" + " Flash Chip ID: 0x%08" PRIX32 "\n" + " Reset Reason: %s\n" + " Reset Info: %s", chip_id, sdk_version, get_core_version_str(core_version_buffer), boot_version, boot_mode, cpu_freq, flash_chip_id, reset_reason, get_reset_info_str(reset_info_buffer, resetInfo.reason)); diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index 14bbdb945a..39269d6f2f 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -27,12 +27,14 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> uint32_t mac_id = lt_cpu_get_mac_id(); ESP_LOGD(TAG, - "LibreTiny Version: %s\n" - "Chip: %s (%04x) @ %u MHz\n" - "Chip ID: 0x%06" PRIX32 "\n" - "Board: %s\n" - "Flash: %" PRIu32 " KiB / RAM: %" PRIu32 " KiB\n" - "Reset Reason: %s", + "LibreTiny debug info:\n" + " Version: %s\n" + " Chip: %s (%04x) @ %u MHz\n" + " Chip ID: 0x%06" PRIX32 "\n" + " Board: %s\n" + " Flash: %" PRIu32 " KiB\n" + " RAM: %" PRIu32 " KiB\n" + " Reset Reason: %s", lt_get_version(), lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz(), mac_id, lt_get_board_code(), flash_kib, ram_kib, reset_reason); diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index ecca7150bd..bd6432e949 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -79,13 +79,13 @@ static void fa_cb(const struct flash_area *fa, void *user_data) { void DebugComponent::log_partition_info_() { #if CONFIG_FLASH_MAP_LABELS ESP_LOGCONFIG(TAG, "ID | Device | Device Name " - "| Label | Offset | Size\n" - "--------------------------------------------" + "| Label | Offset | Size"); + ESP_LOGCONFIG(TAG, "--------------------------------------------" "-----------------------------------------------"); #else ESP_LOGCONFIG(TAG, "ID | Device | Device Name " - "| Offset | Size\n" - "-----------------------------------------" + "| Offset | Size"); + ESP_LOGCONFIG(TAG, "-----------------------------------------" "------------------------------"); #endif flash_area_foreach(fa_cb, nullptr); @@ -284,11 +284,12 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> char mac_pretty[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; get_mac_address_pretty_into_buffer(mac_pretty); ESP_LOGD(TAG, - "Code page size: %u, code size: %u, device id: 0x%08x%08x\n" - "Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n" - "Device address type: %s, address: %s\n" - "Part code: nRF%x, version: %c%c%c%c, package: %s\n" - "RAM: %ukB, Flash: %ukB, production test: %sdone", + "nRF debug info:\n" + " Code page size: %u, code size: %u, device id: 0x%08x%08x\n" + " Encryption root: 0x%08x%08x%08x%08x, Identity Root: 0x%08x%08x%08x%08x\n" + " Device address type: %s, address: %s\n" + " Part code: nRF%x, version: %c%c%c%c, package: %s\n" + " RAM: %ukB, Flash: %ukB, production test: %sdone", NRF_FICR->CODEPAGESIZE, NRF_FICR->CODESIZE, NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0], NRF_FICR->ER[0], NRF_FICR->ER[1], NRF_FICR->ER[2], NRF_FICR->ER[3], NRF_FICR->IR[0], NRF_FICR->IR[1], NRF_FICR->IR[2], NRF_FICR->IR[3], (NRF_FICR->DEVICEADDRTYPE & 0x1 ? "Random" : "Public"), mac_pretty, NRF_FICR->INFO.PART, @@ -299,23 +300,22 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) == UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos; ESP_LOGD( - TAG, "GPIO as NFC pins: %s, GPIO as nRESET pin: %s", + TAG, " GPIO as NFC pins: %s, GPIO as nRESET pin: %s", YESNO((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)), YESNO(n_reset_enabled)); if (n_reset_enabled) { uint8_t port = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PORT_Msk) >> UICR_PSELRESET_PORT_Pos; uint8_t pin = (NRF_UICR->PSELRESET[0] & UICR_PSELRESET_PIN_Msk) >> UICR_PSELRESET_PIN_Pos; - ESP_LOGD(TAG, "nRESET port P%u.%02u", port, pin); + ESP_LOGD(TAG, " nRESET port P%u.%02u", port, pin); } #ifdef USE_BOOTLOADER_MCUBOOT - ESP_LOGD(TAG, "bootloader: mcuboot"); + ESP_LOGD(TAG, " Bootloader: mcuboot"); #else - ESP_LOGD(TAG, "bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF, + ESP_LOGD(TAG, " Bootloader: Adafruit, version %u.%u.%u", (BOOTLOADER_VERSION_REGISTER >> 16) & 0xFF, (BOOTLOADER_VERSION_REGISTER >> 8) & 0xFF, BOOTLOADER_VERSION_REGISTER & 0xFF); - ESP_LOGD(TAG, - "MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x\n" - "MBR param page addr 0x%08x, UICR param page addr 0x%08x", - read_mem_u32(MBR_BOOTLOADER_ADDR), NRF_UICR->NRFFW[0], read_mem_u32(MBR_PARAM_PAGE_ADDR), + ESP_LOGD(TAG, " MBR bootloader addr 0x%08x, UICR bootloader addr 0x%08x", read_mem_u32(MBR_BOOTLOADER_ADDR), + NRF_UICR->NRFFW[0]); + ESP_LOGD(TAG, " MBR param page addr 0x%08x, UICR param page addr 0x%08x", read_mem_u32(MBR_PARAM_PAGE_ADDR), NRF_UICR->NRFFW[1]); if (is_sd_present()) { uint32_t const sd_id = sd_id_get(); @@ -326,7 +326,7 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> ver[1] = (sd_version - ver[0] * 1000000) / 1000; ver[2] = (sd_version - ver[0] * 1000000 - ver[1] * 1000); - ESP_LOGD(TAG, "SoftDevice: S%u %u.%u.%u", sd_id, ver[0], ver[1], ver[2]); + ESP_LOGD(TAG, " SoftDevice: S%u %u.%u.%u", sd_id, ver[0], ver[1], ver[2]); #ifdef USE_SOFTDEVICE_ID #ifdef USE_SOFTDEVICE_VERSION if (USE_SOFTDEVICE_ID != sd_id || USE_SOFTDEVICE_VERSION != ver[0]) { @@ -352,10 +352,8 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> } return res; }; - ESP_LOGD(TAG, - "NRFFW %s\n" - "NRFHW %s", - uicr(NRF_UICR->NRFFW, 13).c_str(), uicr(NRF_UICR->NRFHW, 12).c_str()); + ESP_LOGD(TAG, " NRFFW %s", uicr(NRF_UICR->NRFFW, 13).c_str()); + ESP_LOGD(TAG, " NRFHW %s", uicr(NRF_UICR->NRFHW, 12).c_str()); return pos; } diff --git a/esphome/components/dfrobot_sen0395/commands.cpp b/esphome/components/dfrobot_sen0395/commands.cpp index 2c44c6fba9..0f69c82f39 100644 --- a/esphome/components/dfrobot_sen0395/commands.cpp +++ b/esphome/components/dfrobot_sen0395/commands.cpp @@ -187,18 +187,18 @@ uint8_t DetRangeCfgCommand::on_message(std::string &message) { } else if (message == "Done") { ESP_LOGI(TAG, "Updated detection area config:\n" - "Detection area 1 from %.02fm to %.02fm.", + " Detection area 1 from %.02fm to %.02fm.", this->min1_, this->max1_); if (this->min2_ >= 0 && this->max2_ >= 0) { - ESP_LOGI(TAG, "Detection area 2 from %.02fm to %.02fm.", this->min2_, this->max2_); + ESP_LOGI(TAG, " Detection area 2 from %.02fm to %.02fm.", this->min2_, this->max2_); } if (this->min3_ >= 0 && this->max3_ >= 0) { - ESP_LOGI(TAG, "Detection area 3 from %.02fm to %.02fm.", this->min3_, this->max3_); + ESP_LOGI(TAG, " Detection area 3 from %.02fm to %.02fm.", this->min3_, this->max3_); } if (this->min4_ >= 0 && this->max4_ >= 0) { - ESP_LOGI(TAG, "Detection area 4 from %.02fm to %.02fm.", this->min4_, this->max4_); + ESP_LOGI(TAG, " Detection area 4 from %.02fm to %.02fm.", this->min4_, this->max4_); } - ESP_LOGD(TAG, "Used command: %s", this->cmd_.c_str()); + ESP_LOGD(TAG, " Used command: %s", this->cmd_.c_str()); return 1; // Command done } return 0; // Command not done yet. @@ -222,10 +222,10 @@ uint8_t SetLatencyCommand::on_message(std::string &message) { } else if (message == "Done") { ESP_LOGI(TAG, "Updated output latency config:\n" - "Signal that someone was detected is delayed by %.03f s.\n" - "Signal that nobody is detected anymore is delayed by %.03f s.", + " Signal that someone was detected is delayed by %.03f s.\n" + " Signal that nobody is detected anymore is delayed by %.03f s.", this->delay_after_detection_, this->delay_after_disappear_); - ESP_LOGD(TAG, "Used command: %s", this->cmd_.c_str()); + ESP_LOGD(TAG, " Used command: %s", this->cmd_.c_str()); return 1; // Command done } return 0; // Command not done yet diff --git a/esphome/components/emmeti/emmeti.cpp b/esphome/components/emmeti/emmeti.cpp index 5286f962b8..d3e923cbef 100644 --- a/esphome/components/emmeti/emmeti.cpp +++ b/esphome/components/emmeti/emmeti.cpp @@ -153,10 +153,7 @@ void EmmetiClimate::reverse_add_(T val, size_t len, esphome::remote_base::Remote bool EmmetiClimate::check_checksum_(uint8_t checksum) { uint8_t expected = this->gen_checksum_(); - ESP_LOGV(TAG, - "Expected checksum: %X\n" - "Checksum received: %X", - expected, checksum); + ESP_LOGV(TAG, "Expected checksum: %X, Checksum received: %X", expected, checksum); return checksum == expected; } @@ -266,10 +263,7 @@ bool EmmetiClimate::on_receive(remote_base::RemoteReceiveData data) { } } - ESP_LOGD(TAG, - "Swing: %d\n" - "Sleep: %d", - (curr_state.bitmap >> 1) & 0x01, (curr_state.bitmap >> 2) & 0x01); + ESP_LOGD(TAG, "Swing: %d, Sleep: %d", (curr_state.bitmap >> 1) & 0x01, (curr_state.bitmap >> 2) & 0x01); for (size_t pos = 0; pos < 4; pos++) { if (data.expect_item(EMMETI_BIT_MARK, EMMETI_ONE_SPACE)) { @@ -295,13 +289,8 @@ bool EmmetiClimate::on_receive(remote_base::RemoteReceiveData data) { } } - ESP_LOGD(TAG, - "Turbo: %d\n" - "Light: %d\n" - "Tree: %d\n" - "Blow: %d", - (curr_state.bitmap >> 3) & 0x01, (curr_state.bitmap >> 4) & 0x01, (curr_state.bitmap >> 5) & 0x01, - (curr_state.bitmap >> 6) & 0x01); + ESP_LOGD(TAG, "Turbo: %d, Light: %d, Tree: %d, Blow: %d", (curr_state.bitmap >> 3) & 0x01, + (curr_state.bitmap >> 4) & 0x01, (curr_state.bitmap >> 5) & 0x01, (curr_state.bitmap >> 6) & 0x01); uint16_t control_data = 0; for (size_t pos = 0; pos < 11; pos++) { diff --git a/esphome/components/ens160_base/ens160_base.cpp b/esphome/components/ens160_base/ens160_base.cpp index 785b053f04..e1cee5005c 100644 --- a/esphome/components/ens160_base/ens160_base.cpp +++ b/esphome/components/ens160_base/ens160_base.cpp @@ -152,12 +152,13 @@ void ENS160Component::update() { // verbose status logging ESP_LOGV(TAG, - "Status: ENS160 STATAS bit 0x%x\n" - "Status: ENS160 STATER bit 0x%x\n" - "Status: ENS160 VALIDITY FLAG 0x%02x\n" - "Status: ENS160 NEWDAT bit 0x%x\n" - "Status: ENS160 NEWGPR bit 0x%x", - (ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS, + "ENS160 Status Register: 0x%02x\n" + " STATAS bit 0x%x\n" + " STATER bit 0x%x\n" + " VALIDITY FLAG 0x%02x\n" + " NEWDAT bit 0x%x\n" + " NEWGPR bit 0x%x", + status_value, (ENS160_DATA_STATUS_STATAS & (status_value)) == ENS160_DATA_STATUS_STATAS, (ENS160_DATA_STATUS_STATER & (status_value)) == ENS160_DATA_STATUS_STATER, (ENS160_DATA_STATUS_VALIDITY & status_value) >> 2, (ENS160_DATA_STATUS_NEWDAT & (status_value)) == ENS160_DATA_STATUS_NEWDAT, diff --git a/esphome/components/es8388/es8388.cpp b/esphome/components/es8388/es8388.cpp index 9deb29416f..72026a2a84 100644 --- a/esphome/components/es8388/es8388.cpp +++ b/esphome/components/es8388/es8388.cpp @@ -209,9 +209,10 @@ bool ES8388::set_dac_output(DacOutputLine line) { }; ESP_LOGV(TAG, - "Setting ES8388_DACPOWER to 0x%02X\n" - "Setting ES8388_DACCONTROL24 / ES8388_DACCONTROL25 to 0x%02X\n" - "Setting ES8388_DACCONTROL26 / ES8388_DACCONTROL27 to 0x%02X", + "DAC output config:\n" + " DACPOWER: 0x%02X\n" + " DACCONTROL24/25: 0x%02X\n" + " DACCONTROL26/27: 0x%02X", dac_power, reg_out1, reg_out2); ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL24, reg_out1)); // LOUT1VOL diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 3f0eeeab4a..e6a85c784a 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -423,10 +423,8 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ for (auto &svc : this->services_) { char uuid_buf[espbt::UUID_STR_LEN]; svc->uuid.to_str(uuid_buf); - ESP_LOGV(TAG, - "[%d] [%s] Service UUID: %s\n" - "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", - this->connection_index_, this->address_str_, uuid_buf, this->connection_index_, this->address_str_, + ESP_LOGV(TAG, "[%d] [%s] Service UUID: %s", this->connection_index_, this->address_str_, uuid_buf); + ESP_LOGV(TAG, "[%d] [%s] start_handle: 0x%x end_handle: 0x%x", this->connection_index_, this->address_str_, svc->start_handle, svc->end_handle); } #endif diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index c8e2e879d4..dcd6e643c2 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -106,11 +106,12 @@ void Esp32HostedUpdate::setup() { esp_app_desc_t *app_desc = (esp_app_desc_t *) (this->firmware_data_ + app_desc_offset); if (app_desc->magic_word == ESP_APP_DESC_MAGIC_WORD) { ESP_LOGD(TAG, - "Firmware version: %s\n" - "Project name: %s\n" - "Build date: %s\n" - "Build time: %s\n" - "IDF version: %s", + "ESP32 Hosted firmware:\n" + " Firmware version: %s\n" + " Project name: %s\n" + " Build date: %s\n" + " Build time: %s\n" + " IDF version: %s", app_desc->version, app_desc->project_name, app_desc->date, app_desc->time, app_desc->idf_ver); this->update_info_.latest_version = app_desc->version; if (this->update_info_.latest_version != this->update_info_.current_version) { diff --git a/esphome/components/espnow/packet_transport/espnow_transport.cpp b/esphome/components/espnow/packet_transport/espnow_transport.cpp index 3d16f28c7d..6e4f606466 100644 --- a/esphome/components/espnow/packet_transport/espnow_transport.cpp +++ b/esphome/components/espnow/packet_transport/espnow_transport.cpp @@ -21,11 +21,9 @@ void ESPNowTransport::setup() { return; } - ESP_LOGI(TAG, - "Registering ESP-NOW handlers\n" - "Peer address: %02X:%02X:%02X:%02X:%02X:%02X", - this->peer_address_[0], this->peer_address_[1], this->peer_address_[2], this->peer_address_[3], - this->peer_address_[4], this->peer_address_[5]); + ESP_LOGI(TAG, "Registering ESP-NOW handlers, peer: %02X:%02X:%02X:%02X:%02X:%02X", this->peer_address_[0], + this->peer_address_[1], this->peer_address_[2], this->peer_address_[3], this->peer_address_[4], + this->peer_address_[5]); // Register received handler this->parent_->register_received_handler(this); diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index f9d98ad51b..fcd32223e4 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -866,10 +866,7 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi } #endif - ESP_LOGD(TAG, - "Writing to PHY Register Address: 0x%02" PRIX32 "\n" - "Writing to PHY Register Value: 0x%04" PRIX32, - register_data.address, register_data.value); + ESP_LOGD(TAG, "Writing PHY reg 0x%02" PRIX32 " = 0x%04" PRIX32, register_data.address, 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"); diff --git a/esphome/components/ezo_pmp/ezo_pmp.cpp b/esphome/components/ezo_pmp/ezo_pmp.cpp index 9d2f4fc687..bf6e3926b8 100644 --- a/esphome/components/ezo_pmp/ezo_pmp.cpp +++ b/esphome/components/ezo_pmp/ezo_pmp.cpp @@ -150,9 +150,9 @@ void EzoPMP::read_command_result_() { if (current_char == '\0') { ESP_LOGV(TAG, "Read Response from device: %s\n" - "First Component: %s\n" - "Second Component: %s\n" - "Third Component: %s", + " First Component: %s\n" + " Second Component: %s\n" + " Third Component: %s", (char *) response_buffer, (char *) first_parameter_buffer, (char *) second_parameter_buffer, (char *) third_parameter_buffer); diff --git a/esphome/components/gcja5/gcja5.cpp b/esphome/components/gcja5/gcja5.cpp index f7f7f8d02c..43b2fa20d3 100644 --- a/esphome/components/gcja5/gcja5.cpp +++ b/esphome/components/gcja5/gcja5.cpp @@ -97,10 +97,10 @@ void GCJA5Component::parse_data_() { ESP_LOGI(TAG, "GCJA5 Status\n" - "Overall Status : %i\n" - "PD Status : %i\n" - "LD Status : %i\n" - "Fan Status : %i", + " Overall Status : %i\n" + " PD Status : %i\n" + " LD Status : %i\n" + " Fan Status : %i", (status >> 6) & 0x03, (status >> 4) & 0x03, (status >> 2) & 0x03, (status >> 0) & 0x03); } } diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.cpp b/esphome/components/graphical_display_menu/graphical_display_menu.cpp index 2b120a746f..cf1672f217 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.cpp +++ b/esphome/components/graphical_display_menu/graphical_display_menu.cpp @@ -38,13 +38,13 @@ void GraphicalDisplayMenu::setup() { void GraphicalDisplayMenu::dump_config() { ESP_LOGCONFIG(TAG, "Graphical Display Menu\n" - "Has Display: %s\n" - "Popup Mode: %s\n" - "Advanced Drawing Mode: %s\n" - "Has Font: %s\n" - "Mode: %s\n" - "Active: %s\n" - "Menu items:", + " Has Display: %s\n" + " Popup Mode: %s\n" + " Advanced Drawing Mode: %s\n" + " Has Font: %s\n" + " Mode: %s\n" + " Active: %s\n" + " Menu items:", YESNO(this->display_ != nullptr), YESNO(this->display_ != nullptr), YESNO(this->display_ == nullptr), YESNO(this->font_ != nullptr), this->mode_ == display_menu_base::MENU_MODE_ROTARY ? "Rotary" : "Joystick", YESNO(this->active_)); diff --git a/esphome/components/honeywellabp/honeywellabp.cpp b/esphome/components/honeywellabp/honeywellabp.cpp index c204325dfc..58c5df230f 100644 --- a/esphome/components/honeywellabp/honeywellabp.cpp +++ b/esphome/components/honeywellabp/honeywellabp.cpp @@ -35,10 +35,7 @@ uint8_t HONEYWELLABPSensor::readsensor_() { pressure_count_ = ((uint16_t) (buf_[0]) << 8 & 0x3F00) | ((uint16_t) (buf_[1]) & 0xFF); // 11 - bit temperature is all of byte 2 (lowest 8 bits) and the first three bits of byte 3 temperature_count_ = (((uint16_t) (buf_[2]) << 3) & 0x7F8) | (((uint16_t) (buf_[3]) >> 5) & 0x7); - ESP_LOGV(TAG, - "Sensor pressure_count_ %d\n" - "Sensor temperature_count_ %d", - pressure_count_, temperature_count_); + ESP_LOGV(TAG, "Sensor pressure_count_ %d, temperature_count_ %d", pressure_count_, temperature_count_); } return status_; } diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 882def4d7f..d77a768211 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -105,8 +105,7 @@ uint8_t OtaHttpRequestComponent::do_ota_() { // we will compute MD5 on the fly for verification -- Arduino OTA seems to ignore it md5_receive.init(); - ESP_LOGV(TAG, "MD5Digest initialized\n" - "OTA backend begin"); + ESP_LOGV(TAG, "MD5Digest initialized, OTA backend begin"); auto backend = ota::make_ota_backend(); auto error_code = backend->begin(container->content_length); if (error_code != ota::OTA_RESPONSE_OK) { diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index de01c99a19..8a20192c1e 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -362,10 +362,8 @@ bool INA2XX::configure_shunt_() { ESP_LOGW(TAG, "Shunt value too high"); } this->shunt_cal_ &= 0x7FFF; - ESP_LOGV(TAG, - "Given Rshunt=%f Ohm and Max_current=%.3f\n" - "New CURRENT_LSB=%f, SHUNT_CAL=%u", - this->shunt_resistance_ohm_, this->max_current_a_, this->current_lsb_, this->shunt_cal_); + ESP_LOGV(TAG, "Rshunt=%f Ohm, max current=%.3f A, current LSB=%f, shunt cal=%u", this->shunt_resistance_ohm_, + this->max_current_a_, this->current_lsb_, this->shunt_cal_); return this->write_unsigned_16_(RegisterMap::REG_SHUNT_CAL, this->shunt_cal_); } diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index f8f782f804..dd1d53857d 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -489,11 +489,8 @@ bool LD2410Component::handle_ack_data_() { this->out_pin_level_ = this->buffer_data_[12]; const auto *light_function_str = find_str(LIGHT_FUNCTIONS_BY_UINT, this->light_function_); const auto *out_pin_level_str = find_str(OUT_PIN_LEVELS_BY_UINT, this->out_pin_level_); - ESP_LOGV(TAG, - "Light function: %s\n" - "Light threshold: %u\n" - "Out pin level: %s", - light_function_str, this->light_threshold_, out_pin_level_str); + ESP_LOGV(TAG, "Light function: %s, threshold: %u, out pin level: %s", light_function_str, this->light_threshold_, + out_pin_level_str); #ifdef USE_SELECT if (this->light_function_select_ != nullptr) { this->light_function_select_->publish_state(light_function_str); diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 95e19e0d5f..484d5bd281 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -530,10 +530,7 @@ bool LD2412Component::handle_ack_data_() { this->light_function_ = this->buffer_data_[10]; this->light_threshold_ = this->buffer_data_[11]; const auto *light_function_str = find_str(LIGHT_FUNCTIONS_BY_UINT, this->light_function_); - ESP_LOGV(TAG, - "Light function: %s\n" - "Light threshold: %u", - light_function_str, this->light_threshold_); + ESP_LOGV(TAG, "Light function: %s, threshold: %u", light_function_str, this->light_threshold_); #ifdef USE_SELECT if (this->light_function_select_ != nullptr) { this->light_function_select_->publish_state(light_function_str); diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index a203dde115..a01d42ac8b 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -130,10 +130,8 @@ void LEDCOutput::setup() { } int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); - ESP_LOGV(TAG, - "Configured frequency %f with a bit depth of %u bits\n" - "Angle of %.1f° results in hpoint %u", - this->frequency_, this->bit_depth_, this->phase_angle_, hpoint); + ESP_LOGV(TAG, "Configured frequency %f with bit depth %u, angle %.1f° hpoint %u", this->frequency_, this->bit_depth_, + this->phase_angle_, hpoint); ledc_channel_config_t chan_conf{}; chan_conf.gpio_num = this->pin_->get_pin(); diff --git a/esphome/components/max6956/max6956.cpp b/esphome/components/max6956/max6956.cpp index 6ba17f11d1..a350e66ee0 100644 --- a/esphome/components/max6956/max6956.cpp +++ b/esphome/components/max6956/max6956.cpp @@ -146,11 +146,11 @@ void MAX6956::dump_config() { if (brightness_mode_ == MAX6956CURRENTMODE::GLOBAL) { ESP_LOGCONFIG(TAG, - "current mode: global\n" - "global brightness: %u", + " Current mode: global\n" + " Brightness: %u", global_brightness_); } else { - ESP_LOGCONFIG(TAG, "current mode: segment"); + ESP_LOGCONFIG(TAG, " Current mode: segment"); } } diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index c12c79499f..8a7fb965e9 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -165,10 +165,7 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) { case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "MQTT_EVENT_ERROR"); if (event.error_handle.error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) { - ESP_LOGE(TAG, - "Last error code reported from esp-tls: 0x%x\n" - "Last tls stack error number: 0x%x\n" - "Last captured errno : %d (%s)", + ESP_LOGE(TAG, "Last esp-tls error: 0x%x, tls stack error: 0x%x, socket errno: %d (%s)", event.error_handle.esp_tls_last_esp_err, event.error_handle.esp_tls_stack_err, event.error_handle.esp_transport_sock_errno, strerror(event.error_handle.esp_transport_sock_errno)); } else if (event.error_handle.error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) { diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index a433eff883..46a04c1b2e 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -25,11 +25,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); if (range_size <= 0 or range_end <= range_start) { - ESP_LOGE(TAG, "Invalid range"); - ESP_LOGD(TAG, - "Range end: %" PRIu32 "\n" - "Range size: %" PRIu32, - range_end, range_size); + ESP_LOGE(TAG, "Invalid range end: %" PRIu32 ", size: %" PRIu32, range_end, range_size); return -1; } @@ -138,11 +134,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { - ESP_LOGD(TAG, - "TFT upload requested\n" - "Exit reparse: %s\n" - "URL: %s", - YESNO(exit_reparse), this->tft_url_.c_str()); + ESP_LOGD(TAG, "TFT upload requested, exit reparse: %s, URL: %s", YESNO(exit_reparse), this->tft_url_.c_str()); if (this->connection_state_.is_updating_) { ESP_LOGW(TAG, "Upload in progress"); @@ -172,10 +164,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); // Define the configuration for the HTTP client - ESP_LOGV(TAG, - "Init HTTP client\n" - "Heap: %" PRIu32, - EspClass::getFreeHeap()); + ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, EspClass::getFreeHeap()); HTTPClient http_client; http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along @@ -262,10 +251,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { this->reset_(false); delay(250); // NOLINT - ESP_LOGV(TAG, - "Heap: %" PRIu32 "\n" - "Upload cmd: %s", - EspClass::getFreeHeap(), command); + ESP_LOGV(TAG, "Heap: %" PRIu32 ", upload cmd: %s", EspClass::getFreeHeap(), command); this->send_command_(command); if (baud_rate != this->original_baud_rate_) { diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index 46352afd75..43f59a8d4b 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -27,11 +27,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); if (range_size <= 0 or range_end <= range_start) { - ESP_LOGD(TAG, - "Range end: %" PRIu32 "\n" - "Range size: %" PRIu32, - range_end, range_size); - ESP_LOGE(TAG, "Invalid range"); + ESP_LOGE(TAG, "Invalid range end: %" PRIu32 ", size: %" PRIu32, range_end, range_size); return -1; } @@ -159,11 +155,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r } bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { - ESP_LOGD(TAG, - "TFT upload requested\n" - "Exit reparse: %s\n" - "URL: %s", - YESNO(exit_reparse), this->tft_url_.c_str()); + ESP_LOGD(TAG, "TFT upload requested, exit reparse: %s, URL: %s", YESNO(exit_reparse), this->tft_url_.c_str()); if (this->connection_state_.is_updating_) { ESP_LOGW(TAG, "Upload in progress"); @@ -193,10 +185,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate); // Define the configuration for the HTTP client - ESP_LOGV(TAG, - "Init HTTP client\n" - "Heap: %" PRIu32, - esp_get_free_heap_size()); + ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, esp_get_free_heap_size()); esp_http_client_config_t config = { .url = this->tft_url_.c_str(), .cert_pem = nullptr, @@ -220,10 +209,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } // Perform the HTTP request - ESP_LOGV(TAG, - "Check connection\n" - "Heap: %" PRIu32, - esp_get_free_heap_size()); + ESP_LOGV(TAG, "Check connection, heap: %" PRIu32, esp_get_free_heap_size()); err = esp_http_client_perform(http_client); if (err != ESP_OK) { ESP_LOGE(TAG, "HTTP failed: %s", esp_err_to_name(err)); @@ -232,10 +218,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { } // Check the HTTP Status Code - ESP_LOGV(TAG, - "Check status\n" - "Heap: %" PRIu32, - esp_get_free_heap_size()); + ESP_LOGV(TAG, "Check status, heap: %" PRIu32, esp_get_free_heap_size()); int status_code = esp_http_client_get_status_code(http_client); if (status_code != 200 && status_code != 206) { ESP_LOGE(TAG, "HTTP request failed with status %d", status_code); @@ -344,8 +327,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ESP_LOGV(TAG, "Heap: %" PRIu32 " left: %" PRIu32, esp_get_free_heap_size(), this->content_length_); } - ESP_LOGD(TAG, "TFT upload complete\n" - "Close HTTP"); + ESP_LOGD(TAG, "TFT upload complete, closing HTTP"); esp_http_client_close(http_client); esp_http_client_cleanup(http_client); ESP_LOGV(TAG, "Connection closed"); diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index bb70701471..9dd68a1ccc 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -130,10 +130,7 @@ void OpenThreadComponent::ot_main() { } #ifdef ESPHOME_LOG_HAS_DEBUG // Fetch link mode from OT only when DEBUG link_mode_config = otThreadGetLinkMode(instance); - ESP_LOGD(TAG, - "Link Mode Device Type: %s\n" - "Link Mode Network Data: %s\n" - "Link Mode RX On When Idle: %s", + ESP_LOGD(TAG, "Link Mode Device Type: %s, Network Data: %s, RX On When Idle: %s", TRUEFALSE(link_mode_config.mDeviceType), TRUEFALSE(link_mode_config.mNetworkData), TRUEFALSE(link_mode_config.mRxOnWhenIdle)); #endif @@ -152,8 +149,7 @@ void OpenThreadComponent::ot_main() { // Make sure the length is 0 so we fallback to the configuration dataset.mLength = 0; } else { - ESP_LOGI(TAG, "Found OpenThread-managed dataset, ignoring esphome configuration\n" - "(set force_dataset: true to override)"); + ESP_LOGI(TAG, "Found existing dataset, ignoring config (force_dataset: true to override)"); } #endif diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index fdff11dedb..9247e114f0 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -144,9 +144,10 @@ bool PI4IOE5V6408Component::write_gpio_modes_() { } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE ESP_LOGV(TAG, - "Wrote GPIO modes: 0b" BYTE_TO_BINARY_PATTERN "\n" - "Wrote GPIO pullup/pulldown: 0b" BYTE_TO_BINARY_PATTERN "\n" - "Wrote GPIO pull enable: 0b" BYTE_TO_BINARY_PATTERN, + "Wrote GPIO config:\n" + " modes: 0b" BYTE_TO_BINARY_PATTERN "\n" + " pullup/pulldown: 0b" BYTE_TO_BINARY_PATTERN "\n" + " pull enable: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(this->mode_mask_), BYTE_TO_BINARY(this->pull_up_down_mask_), BYTE_TO_BINARY(this->pull_enable_mask_)); #endif diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index e6831ad19e..f95bf4aedb 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -748,8 +748,7 @@ esphome::optional<bool> Pipsolar::get_bit_(std::string bits, uint8_t bit_pos) { } void Pipsolar::dump_config() { - ESP_LOGCONFIG(TAG, "Pipsolar:\n" - "enabled polling commands:"); + ESP_LOGCONFIG(TAG, "Pipsolar enabled polling commands:"); for (auto &enabled_polling_command : this->enabled_polling_commands_) { if (enabled_polling_command.length != 0) { ESP_LOGCONFIG(TAG, "%s", enabled_polling_command.command); diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index 5366aab54e..1ab0da3df7 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -31,10 +31,7 @@ void PN532::setup() { this->mark_failed(); return; } - ESP_LOGD(TAG, - "Found chip PN5%02X\n" - "Firmware ver. %d.%d", - version_data[0], version_data[1], version_data[2]); + ESP_LOGD(TAG, "Found chip PN5%02X, Firmware v%d.%d", version_data[0], version_data[1], version_data[2]); if (!this->write_command_({ PN532_COMMAND_SAMCONFIGURATION, diff --git a/esphome/components/pn7150/pn7150.cpp b/esphome/components/pn7150/pn7150.cpp index 7bec1e08a9..8c76c8b88c 100644 --- a/esphome/components/pn7150/pn7150.cpp +++ b/esphome/components/pn7150/pn7150.cpp @@ -243,9 +243,7 @@ uint8_t PN7150::reset_core_(const bool reset_config, const bool power) { return nfc::STATUS_FAILED; } - ESP_LOGD(TAG, - "Configuration %s\n" - "NCI version: %s", + ESP_LOGD(TAG, "Configuration %s, NCI version: %s", rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 2] ? "reset" : "retained", rx.get_message()[nfc::NCI_PKT_PAYLOAD_OFFSET + 1] == 0x20 ? "2.0" : "1.0"); @@ -274,11 +272,12 @@ uint8_t PN7150::init_core_() { uint8_t flash_minor_version = rx.get_message()[19 + rx.get_message()[8]]; ESP_LOGD(TAG, - "Manufacturer ID: 0x%02X\n" - "Hardware version: 0x%02X\n" - "ROM code version: 0x%02X\n" - "FLASH major version: 0x%02X\n" - "FLASH minor version: 0x%02X", + "PN7150 chip info:\n" + " Manufacturer ID: 0x%02X\n" + " Hardware version: 0x%02X\n" + " ROM code version: 0x%02X\n" + " FLASH major version: 0x%02X\n" + " FLASH minor version: 0x%02X", manf_id, hw_version, rom_code_version, flash_major_version, flash_minor_version); return rx.get_simple_status_response(); diff --git a/esphome/components/pn7160/pn7160.cpp b/esphome/components/pn7160/pn7160.cpp index 28907b8e30..3fcd1221a7 100644 --- a/esphome/components/pn7160/pn7160.cpp +++ b/esphome/components/pn7160/pn7160.cpp @@ -265,10 +265,7 @@ uint8_t PN7160::reset_core_(const bool reset_config, const bool power) { return nfc::STATUS_FAILED; } - ESP_LOGD(TAG, - "Configuration %s\n" - "NCI version: %s\n" - "Manufacturer ID: 0x%02X", + ESP_LOGD(TAG, "Configuration %s, NCI version: %s, Manufacturer ID: 0x%02X", rx.get_message()[4] ? "reset" : "retained", rx.get_message()[5] == 0x20 ? "2.0" : "1.0", rx.get_message()[6]); rx.get_message().erase(rx.get_message().begin(), rx.get_message().begin() + 8); @@ -301,11 +298,12 @@ uint8_t PN7160::init_core_() { char feat_buf[nfc::FORMAT_BYTES_BUFFER_SIZE]; ESP_LOGD(TAG, - "Hardware version: %u\n" - "ROM code version: %u\n" - "FLASH major version: %u\n" - "FLASH minor version: %u\n" - "Features: %s", + "PN7160 chip info:\n" + " Hardware version: %u\n" + " ROM code version: %u\n" + " FLASH major version: %u\n" + " FLASH minor version: %u\n" + " Features: %s", hw_version, rom_code_version, flash_major_version, flash_minor_version, nfc::format_bytes_to(feat_buf, features)); diff --git a/esphome/components/qmp6988/qmp6988.cpp b/esphome/components/qmp6988/qmp6988.cpp index 4e1ef27d5e..24fe34e785 100644 --- a/esphome/components/qmp6988/qmp6988.cpp +++ b/esphome/components/qmp6988/qmp6988.cpp @@ -128,15 +128,14 @@ bool QMP6988Component::get_calibration_data_() { qmp6988_data_.qmp6988_cali.COE_bp3 = (int16_t) encode_uint16(a_data_uint8_tr[16], a_data_uint8_tr[17]); ESP_LOGV(TAG, - "<-----------calibration data-------------->\n" - "COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]", + "Calibration data:\n" + " COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\n" + " COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\n" + " COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]", qmp6988_data_.qmp6988_cali.COE_a0, qmp6988_data_.qmp6988_cali.COE_a1, qmp6988_data_.qmp6988_cali.COE_a2, - qmp6988_data_.qmp6988_cali.COE_b00); - ESP_LOGV(TAG, "COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bt1, - qmp6988_data_.qmp6988_cali.COE_bt2, qmp6988_data_.qmp6988_cali.COE_bp1, qmp6988_data_.qmp6988_cali.COE_b11); - ESP_LOGV(TAG, "COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]\r\n", qmp6988_data_.qmp6988_cali.COE_bp2, + qmp6988_data_.qmp6988_cali.COE_b00, qmp6988_data_.qmp6988_cali.COE_bt1, qmp6988_data_.qmp6988_cali.COE_bt2, + qmp6988_data_.qmp6988_cali.COE_bp1, qmp6988_data_.qmp6988_cali.COE_b11, qmp6988_data_.qmp6988_cali.COE_bp2, qmp6988_data_.qmp6988_cali.COE_b12, qmp6988_data_.qmp6988_cali.COE_b21, qmp6988_data_.qmp6988_cali.COE_bp3); - ESP_LOGV(TAG, "<-----------calibration data-------------->\r\n"); qmp6988_data_.ik.a0 = qmp6988_data_.qmp6988_cali.COE_a0; // 20Q4 qmp6988_data_.ik.b00 = qmp6988_data_.qmp6988_cali.COE_b00; // 20Q4 @@ -153,14 +152,13 @@ bool QMP6988Component::get_calibration_data_() { qmp6988_data_.ik.b21 = 13836L * (int64_t) qmp6988_data_.qmp6988_cali.COE_b21 + 79333336L; // 29Q60 qmp6988_data_.ik.bp3 = 2915L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65 ESP_LOGV(TAG, - "<----------- int calibration data -------------->\n" - "a0[%d] a1[%d] a2[%d] b00[%d]", - qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2, qmp6988_data_.ik.b00); - ESP_LOGV(TAG, "bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\r\n", qmp6988_data_.ik.bt1, qmp6988_data_.ik.bt2, - qmp6988_data_.ik.bp1, qmp6988_data_.ik.b11); - ESP_LOGV(TAG, "bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]\r\n", qmp6988_data_.ik.bp2, qmp6988_data_.ik.b12, + "Int calibration data:\n" + " a0[%d] a1[%d] a2[%d] b00[%d]\n" + " bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\n" + " bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]", + qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2, qmp6988_data_.ik.b00, qmp6988_data_.ik.bt1, + qmp6988_data_.ik.bt2, qmp6988_data_.ik.bp1, qmp6988_data_.ik.b11, qmp6988_data_.ik.bp2, qmp6988_data_.ik.b12, qmp6988_data_.ik.b21, qmp6988_data_.ik.bp3); - ESP_LOGV(TAG, "<----------- int calibration data -------------->\r\n"); return true; } diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index cff3145199..43029cbc2f 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -104,10 +104,7 @@ void ProntoProtocol::send_pronto_(RemoteTransmitData *dst, const std::vector<uin uint16_t intros = 2 * data[2]; uint16_t repeats = 2 * data[3]; - ESP_LOGD(TAG, - "Send Pronto: intros=%d\n" - "Send Pronto: repeats=%d", - intros, repeats); + ESP_LOGD(TAG, "Send Pronto: intros=%d, repeats=%d", intros, repeats); if (NUMBERS_IN_PREAMBLE + intros + repeats != data.size()) { // inconsistent sizes ESP_LOGE(TAG, "Inconsistent data, not sending"); return; diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index bd80048c64..aa4fdb8291 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -51,13 +51,11 @@ void SafeModeComponent::dump_config() { #if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition(); if (last_invalid != nullptr) { - ESP_LOGW(TAG, - "OTA rollback detected! Rolled back from partition '%s'\n" - "The device reset before the boot was marked successful", - last_invalid->label); + ESP_LOGW(TAG, "OTA rollback detected! Rolled back from partition '%s'", last_invalid->label); + ESP_LOGW(TAG, "The device reset before the boot was marked successful"); if (esp_reset_reason() == ESP_RST_BROWNOUT) { - ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!\n" - "See https://esphome.io/guides/faq.html#brownout-detector-was-triggered"); + ESP_LOGW(TAG, "Last reset was due to brownout - check your power supply!"); + ESP_LOGW(TAG, "See https://esphome.io/guides/faq.html#brownout-detector-was-triggered"); } } #endif diff --git a/esphome/components/sim800l/sim800l.cpp b/esphome/components/sim800l/sim800l.cpp index 251e18648b..2115c72cef 100644 --- a/esphome/components/sim800l/sim800l.cpp +++ b/esphome/components/sim800l/sim800l.cpp @@ -326,7 +326,7 @@ void Sim800LComponent::parse_cmd_(std::string message) { if (ok || message.compare(0, 6, "+CMGL:") == 0) { ESP_LOGD(TAG, "Received SMS from: %s\n" - "%s", + " %s", this->sender_.c_str(), this->message_.c_str()); this->sms_received_callback_.call(this->message_, this->sender_); this->state_ = STATE_RECEIVED_SMS; diff --git a/esphome/components/sonoff_d1/sonoff_d1.cpp b/esphome/components/sonoff_d1/sonoff_d1.cpp index 7b99086546..03586b6398 100644 --- a/esphome/components/sonoff_d1/sonoff_d1.cpp +++ b/esphome/components/sonoff_d1/sonoff_d1.cpp @@ -93,10 +93,7 @@ bool SonoffD1Output::read_command_(uint8_t *cmd, size_t &len) { if (this->read_array(cmd, 6)) { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(6)]; - ESP_LOGV(TAG, - "[%04d] Reading from dimmer:\n" - "[%04d] %s", - this->write_count_, this->write_count_, format_hex_pretty_to(hex_buf, cmd, 6)); + ESP_LOGV(TAG, "[%04d] Reading from dimmer: %s", this->write_count_, format_hex_pretty_to(hex_buf, cmd, 6)); #endif if (cmd[0] != 0xAA || cmd[1] != 0x55) { @@ -190,10 +187,7 @@ bool SonoffD1Output::write_command_(uint8_t *cmd, const size_t len, bool needs_a do { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(SONOFF_D1_MAX_CMD_SIZE)]; - ESP_LOGV(TAG, - "[%04d] Writing to the dimmer:\n" - "[%04d] %s", - this->write_count_, this->write_count_, format_hex_pretty_to(hex_buf, cmd, len)); + ESP_LOGV(TAG, "[%04d] Writing to the dimmer: %s", this->write_count_, format_hex_pretty_to(hex_buf, cmd, len)); #endif this->write_array(cmd, len); this->write_count_++; diff --git a/esphome/components/sun/sun.cpp b/esphome/components/sun/sun.cpp index e8fc4e44d1..d55a14f192 100644 --- a/esphome/components/sun/sun.cpp +++ b/esphome/components/sun/sun.cpp @@ -174,20 +174,21 @@ struct SunAtTime { // debug output like in example 25.a, p. 165 auto eq = equatorial_coordinate(); ESP_LOGV(TAG, - "jde: %f\n" - "T: %f\n" - "L_0: %f\n" - "M: %f\n" - "e: %f\n" - "C: %f\n" - "Odot: %f\n" - "Omega: %f\n" - "lambda: %f\n" - "epsilon_0: %f\n" - "epsilon: %f\n" - "v: %f\n" - "right_ascension: %f\n" - "declination: %f", + "Sun position:\n" + " jde: %f\n" + " T: %f\n" + " L_0: %f\n" + " M: %f\n" + " e: %f\n" + " C: %f\n" + " Odot: %f\n" + " Omega: %f\n" + " lambda: %f\n" + " epsilon_0: %f\n" + " epsilon: %f\n" + " v: %f\n" + " right_ascension: %f\n" + " declination: %f", jde, t, mean_longitude(), mean_anomaly(), eccentricity(), equation_of_center(), true_longitude(), omega(), apparent_longitude(), mean_obliquity(), true_obliquity(), true_anomaly(), eq.right_ascension, eq.declination); diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index a9be38fb03..422d74095c 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -70,14 +70,14 @@ static void usbh_print_intf_desc(const usb_intf_desc_t *intf_desc) { static void usbh_print_cfg_desc(const usb_config_desc_t *cfg_desc) { ESP_LOGV(TAG, "*** Configuration descriptor ***\n" - "bLength %d\n" - "bDescriptorType %d\n" - "wTotalLength %d\n" - "bNumInterfaces %d\n" - "bConfigurationValue %d\n" - "iConfiguration %d\n" - "bmAttributes 0x%x\n" - "bMaxPower %dmA", + " bLength %d\n" + " bDescriptorType %d\n" + " wTotalLength %d\n" + " bNumInterfaces %d\n" + " bConfigurationValue %d\n" + " iConfiguration %d\n" + " bmAttributes 0x%x\n" + " bMaxPower %dmA", cfg_desc->bLength, cfg_desc->bDescriptorType, cfg_desc->wTotalLength, cfg_desc->bNumInterfaces, cfg_desc->bConfigurationValue, cfg_desc->iConfiguration, cfg_desc->bmAttributes, cfg_desc->bMaxPower * 2); } @@ -89,20 +89,20 @@ static void usb_client_print_device_descriptor(const usb_device_desc_t *devc_des ESP_LOGV(TAG, "*** Device descriptor ***\n" - "bLength %d\n" - "bDescriptorType %d\n" - "bcdUSB %d.%d0\n" - "bDeviceClass 0x%x\n" - "bDeviceSubClass 0x%x\n" - "bDeviceProtocol 0x%x\n" - "bMaxPacketSize0 %d\n" - "idVendor 0x%x\n" - "idProduct 0x%x\n" - "bcdDevice %d.%d0\n" - "iManufacturer %d\n" - "iProduct %d\n" - "iSerialNumber %d\n" - "bNumConfigurations %d", + " bLength %d\n" + " bDescriptorType %d\n" + " bcdUSB %d.%d0\n" + " bDeviceClass 0x%x\n" + " bDeviceSubClass 0x%x\n" + " bDeviceProtocol 0x%x\n" + " bMaxPacketSize0 %d\n" + " idVendor 0x%x\n" + " idProduct 0x%x\n" + " bcdDevice %d.%d0\n" + " iManufacturer %d\n" + " iProduct %d\n" + " iSerialNumber %d\n" + " bNumConfigurations %d", devc_desc->bLength, devc_desc->bDescriptorType, ((devc_desc->bcdUSB >> 8) & 0xF), ((devc_desc->bcdUSB >> 4) & 0xF), devc_desc->bDeviceClass, devc_desc->bDeviceSubClass, devc_desc->bDeviceProtocol, devc_desc->bMaxPacketSize0, devc_desc->idVendor, devc_desc->idProduct, diff --git a/esphome/components/usb_uart/cp210x.cpp b/esphome/components/usb_uart/cp210x.cpp index 483286560a..fa8c2331b2 100644 --- a/esphome/components/usb_uart/cp210x.cpp +++ b/esphome/components/usb_uart/cp210x.cpp @@ -58,10 +58,8 @@ std::vector<CdcEps> USBUartTypeCP210X::parse_descriptors(usb_device_handle_t dev ESP_LOGE(TAG, "get_active_config_descriptor failed"); return {}; } - ESP_LOGD(TAG, - "bDeviceClass: %u, bDeviceSubClass: %u\n" - "bNumInterfaces: %u", - device_desc->bDeviceClass, device_desc->bDeviceSubClass, config_desc->bNumInterfaces); + ESP_LOGD(TAG, "bDeviceClass: %u, bDeviceSubClass: %u, bNumInterfaces: %u", device_desc->bDeviceClass, + device_desc->bDeviceSubClass, config_desc->bNumInterfaces); if (device_desc->bDeviceClass != 0) { ESP_LOGE(TAG, "bDeviceClass != 0"); return {}; diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 641d4d6ff8..d6cbfd4b21 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -434,8 +434,8 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr char new_peername[socket::SOCKADDR_STR_LEN]; ESP_LOGE(TAG, "Multiple API Clients attempting to connect to Voice Assistant\n" - "Current client: %s (%s)\n" - "New client: %s (%s)", + " Current client: %s (%s)\n" + " New client: %s (%s)", this->api_client_->get_name(), this->api_client_->get_peername_to(current_peername), client->get_name(), client->get_peername_to(new_peername)); return; diff --git a/esphome/components/wl_134/wl_134.cpp b/esphome/components/wl_134/wl_134.cpp index a589f71c84..a902adfddd 100644 --- a/esphome/components/wl_134/wl_134.cpp +++ b/esphome/components/wl_134/wl_134.cpp @@ -70,12 +70,13 @@ Wl134Component::Rfid134Error Wl134Component::read_packet_() { RFID134_PACKET_CHECKSUM - RFID134_PACKET_RESERVED1); ESP_LOGV(TAG, - "Tag id: %012lld\n" - "Country: %03d\n" - "isData: %s\n" - "isAnimal: %s\n" - "Reserved0: %d\n" - "Reserved1: %" PRId32, + "RFID134 Tag:\n" + " Tag id: %012lld\n" + " Country: %03d\n" + " isData: %s\n" + " isAnimal: %s\n" + " Reserved0: %d\n" + " Reserved1: %" PRId32, reading.id, reading.country, reading.isData ? "true" : "false", reading.isAnimal ? "true" : "false", reading.reserved0, reading.reserved1); diff --git a/esphome/components/xgzp68xx/xgzp68xx.cpp b/esphome/components/xgzp68xx/xgzp68xx.cpp index b5b786c105..5e816469ac 100644 --- a/esphome/components/xgzp68xx/xgzp68xx.cpp +++ b/esphome/components/xgzp68xx/xgzp68xx.cpp @@ -72,10 +72,8 @@ void XGZP68XXComponent::update() { temperature_raw = encode_uint16(data[3], data[4]); // Convert the pressure data to hPa - ESP_LOGV(TAG, - "Got raw pressure=%" PRIu32 ", raw temperature=%u\n" - "K value is %u", - pressure_raw, temperature_raw, this->k_value_); + ESP_LOGV(TAG, "Got raw pressure=%" PRIu32 ", raw temperature=%u, K value=%u", pressure_raw, temperature_raw, + this->k_value_); // Sign extend the pressure float pressure_in_pa = (float) (((int32_t) pressure_raw << 8) >> 8); diff --git a/script/ci-custom.py b/script/ci-custom.py index df819e0f04..85a446ba0d 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -841,6 +841,39 @@ def lint_no_scanf(fname, match): ) +LOG_MULTILINE_RE = re.compile(r"ESP_LOG\w+\s*\(.*?;", re.DOTALL) +LOG_BAD_CONTINUATION_RE = re.compile(r'\\n(?:[^ \\"\r\n\t]|"\s*\n\s*"[^ \\])') +LOG_PERCENT_S_CONTINUATION_RE = re.compile(r'\\n(?:%s|"\s*\n\s*"%s)') + + +@lint_content_check(include=cpp_include) +def lint_log_multiline_continuation(fname, content): + errs = [] + for log_match in LOG_MULTILINE_RE.finditer(content): + log_text = log_match.group(0) + for bad_match in LOG_BAD_CONTINUATION_RE.finditer(log_text): + # %s may expand to a whitespace prefix at runtime, skip those + if LOG_PERCENT_S_CONTINUATION_RE.match(log_text, bad_match.start()): + continue + # Calculate line number from position in full content + abs_pos = log_match.start() + bad_match.start() + lineno = content.count("\n", 0, abs_pos) + 1 + col = abs_pos - content.rfind("\n", 0, abs_pos) + errs.append( + ( + lineno, + col, + "Multi-line log message has a continuation line that does " + "not start with a space. The log viewer uses leading " + "whitespace to detect continuation lines and re-add the " + f"log tag prefix (e.g. {highlight('[C][component:042]:')}).\n" + "Either start the continuation with a space/indent, or " + "split into separate ESP_LOG* calls.", + ) + ) + return errs + + @lint_content_find_check( "ESP_LOG", include=["*.h", "*.tcc"], From 1f945a334a472420d3f3e62c453f3ab3c5246c27 Mon Sep 17 00:00:00 2001 From: Joshua Sing <joshua@joshuasing.dev> Date: Tue, 24 Feb 2026 04:01:23 +1100 Subject: [PATCH 0879/2030] [hdc302x] Add new component (#10160) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/hdc302x/__init__.py | 1 + esphome/components/hdc302x/hdc302x.cpp | 171 ++++++++++++++++++ esphome/components/hdc302x/hdc302x.h | 68 +++++++ esphome/components/hdc302x/sensor.py | 135 ++++++++++++++ tests/components/hdc302x/common.yaml | 19 ++ tests/components/hdc302x/test.esp32-idf.yaml | 4 + .../components/hdc302x/test.esp8266-ard.yaml | 4 + tests/components/hdc302x/test.rp2040-ard.yaml | 4 + 9 files changed, 407 insertions(+) create mode 100644 esphome/components/hdc302x/__init__.py create mode 100644 esphome/components/hdc302x/hdc302x.cpp create mode 100644 esphome/components/hdc302x/hdc302x.h create mode 100644 esphome/components/hdc302x/sensor.py create mode 100644 tests/components/hdc302x/common.yaml create mode 100644 tests/components/hdc302x/test.esp32-idf.yaml create mode 100644 tests/components/hdc302x/test.esp8266-ard.yaml create mode 100644 tests/components/hdc302x/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 2aa0656343..6728e76bba 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -213,6 +213,7 @@ esphome/components/hbridge/light/* @DotNetDann esphome/components/hbridge/switch/* @dwmw2 esphome/components/hc8/* @omartijn esphome/components/hdc2010/* @optimusprimespace @ssieb +esphome/components/hdc302x/* @joshuasing esphome/components/he60r/* @clydebarrow esphome/components/heatpumpir/* @rob-deutsch esphome/components/hitachi_ac424/* @sourabhjaiswal diff --git a/esphome/components/hdc302x/__init__.py b/esphome/components/hdc302x/__init__.py new file mode 100644 index 0000000000..d8165281bf --- /dev/null +++ b/esphome/components/hdc302x/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@joshuasing"] diff --git a/esphome/components/hdc302x/hdc302x.cpp b/esphome/components/hdc302x/hdc302x.cpp new file mode 100644 index 0000000000..b50d34169a --- /dev/null +++ b/esphome/components/hdc302x/hdc302x.cpp @@ -0,0 +1,171 @@ +#include "hdc302x.h" + +#include "esphome/core/hal.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome::hdc302x { + +static const char *const TAG = "hdc302x.sensor"; + +// Commands (per datasheet Table 7-4) +static const uint8_t HDC302X_CMD_SOFT_RESET[2] = {0x30, 0xa2}; +static const uint8_t HDC302X_CMD_CLEAR_STATUS_REGISTER[2] = {0x30, 0x41}; + +static const uint8_t HDC302X_CMD_TRIGGER_MSB = 0x24; + +static const uint8_t HDC302X_CMD_HEATER_ENABLE[2] = {0x30, 0x6d}; +static const uint8_t HDC302X_CMD_HEATER_DISABLE[2] = {0x30, 0x66}; +static const uint8_t HDC302X_CMD_HEATER_CONFIGURE[2] = {0x30, 0x6e}; + +void HDC302XComponent::setup() { + // Soft reset the device + if (this->write(HDC302X_CMD_SOFT_RESET, 2) != i2c::ERROR_OK) { + this->mark_failed(LOG_STR("Soft reset failed")); + return; + } + // Delay SensorRR (reset ready), per datasheet, 6.5. + delay(3); + + // Clear status register + if (this->write(HDC302X_CMD_CLEAR_STATUS_REGISTER, 2) != i2c::ERROR_OK) { + this->mark_failed(LOG_STR("Clear status failed")); + return; + } +} + +void HDC302XComponent::dump_config() { + ESP_LOGCONFIG(TAG, + "HDC302x:\n" + " Heater: %s", + this->heater_active_ ? "active" : "inactive"); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Temperature", this->temp_sensor_); + LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); +} + +void HDC302XComponent::update() { + uint8_t cmd[] = { + HDC302X_CMD_TRIGGER_MSB, + this->power_mode_, + }; + if (this->write(cmd, 2) != i2c::ERROR_OK) { + this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + + // Read data after ADC conversion has completed + this->set_timeout(this->conversion_delay_ms_(), [this]() { this->read_data_(); }); +} + +void HDC302XComponent::start_heater(uint16_t power, uint32_t duration_ms) { + if (!this->disable_heater_()) { + ESP_LOGD(TAG, "Heater disable before start failed"); + } + if (!this->configure_heater_(power) || !this->enable_heater_()) { + ESP_LOGW(TAG, "Heater start failed"); + return; + } + this->heater_active_ = true; + this->cancel_timeout("heater_off"); + if (duration_ms > 0) { + this->set_timeout("heater_off", duration_ms, [this]() { this->stop_heater(); }); + } +} + +void HDC302XComponent::stop_heater() { + this->cancel_timeout("heater_off"); + if (!this->disable_heater_()) { + ESP_LOGW(TAG, "Heater stop failed"); + } + this->heater_active_ = false; +} + +bool HDC302XComponent::enable_heater_() { + if (this->write(HDC302X_CMD_HEATER_ENABLE, 2) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Enable heater failed"); + return false; + } + return true; +} + +bool HDC302XComponent::configure_heater_(uint16_t power_level) { + if (power_level > 0x3fff) { + ESP_LOGW(TAG, "Heater power 0x%04x exceeds max 0x3fff", power_level); + return false; + } + + // Heater current level config. + uint8_t config[] = { + static_cast<uint8_t>((power_level >> 8) & 0xff), // MSB + static_cast<uint8_t>(power_level & 0xff) // LSB + }; + + // Configure level of heater current (per datasheet 7.5.7.8). + uint8_t cmd[] = { + HDC302X_CMD_HEATER_CONFIGURE[0], HDC302X_CMD_HEATER_CONFIGURE[1], config[0], config[1], + crc8(config, 2, 0xff, 0x31, true), + }; + if (this->write(cmd, sizeof(cmd)) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Configure heater failed"); + return false; + } + + return true; +} + +bool HDC302XComponent::disable_heater_() { + if (this->write(HDC302X_CMD_HEATER_DISABLE, 2) != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Disable heater failed"); + return false; + } + return true; +} + +void HDC302XComponent::read_data_() { + uint8_t buf[6]; + if (this->read(buf, 6) != i2c::ERROR_OK) { + this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + + // Check checksums + if (crc8(buf, 2, 0xff, 0x31, true) != buf[2] || crc8(buf + 3, 2, 0xff, 0x31, true) != buf[5]) { + this->status_set_warning(LOG_STR("Read data: invalid CRC")); + return; + } + + this->status_clear_warning(); + + if (this->temp_sensor_ != nullptr) { + uint16_t raw_t = encode_uint16(buf[0], buf[1]); + // Calculate temperature in Celsius per datasheet section 7.3.3. + float temp = -45 + 175 * (float(raw_t) / 65535.0f); + this->temp_sensor_->publish_state(temp); + } + + if (this->humidity_sensor_ != nullptr) { + uint16_t raw_rh = encode_uint16(buf[3], buf[4]); + // Calculate RH% per datasheet section 7.3.3. + float humidity = 100 * (float(raw_rh) / 65535.0f); + this->humidity_sensor_->publish_state(humidity); + } +} + +uint32_t HDC302XComponent::conversion_delay_ms_() { + // ADC conversion delay per datasheet, Table 7-5. - Trigger on Demand + switch (this->power_mode_) { + case HDC302XPowerMode::BALANCED: + return 8; + case HDC302XPowerMode::LOW_POWER: + return 5; + case HDC302XPowerMode::ULTRA_LOW_POWER: + return 4; + case HDC302XPowerMode::HIGH_ACCURACY: + default: + return 13; + } +} + +} // namespace esphome::hdc302x diff --git a/esphome/components/hdc302x/hdc302x.h b/esphome/components/hdc302x/hdc302x.h new file mode 100644 index 0000000000..6afea0a8c0 --- /dev/null +++ b/esphome/components/hdc302x/hdc302x.h @@ -0,0 +1,68 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome::hdc302x { + +enum HDC302XPowerMode : uint8_t { + HIGH_ACCURACY = 0x00, + BALANCED = 0x0b, + LOW_POWER = 0x16, + ULTRA_LOW_POWER = 0xff, +}; + +/** + HDC302x Temperature and humidity sensor. + + Datasheet: + https://www.ti.com/lit/ds/symlink/hdc3020.pdf + */ +class HDC302XComponent : public PollingComponent, public i2c::I2CDevice { + public: + void setup() override; + void dump_config() override; + void update() override; + + void start_heater(uint16_t power, uint32_t duration_ms); + void stop_heater(); + + void set_temp_sensor(sensor::Sensor *temp_sensor) { this->temp_sensor_ = temp_sensor; } + void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } + + void set_power_mode(HDC302XPowerMode power_mode) { this->power_mode_ = power_mode; } + + protected: + sensor::Sensor *temp_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; + + HDC302XPowerMode power_mode_{HDC302XPowerMode::HIGH_ACCURACY}; + bool heater_active_{false}; + + bool enable_heater_(); + bool configure_heater_(uint16_t power_level); + bool disable_heater_(); + void read_data_(); + uint32_t conversion_delay_ms_(); +}; + +template<typename... Ts> class HeaterOnAction : public Action<Ts...>, public Parented<HDC302XComponent> { + public: + TEMPLATABLE_VALUE(uint16_t, power) + TEMPLATABLE_VALUE(uint32_t, duration) + + void play(const Ts &...x) override { + auto power_val = this->power_.value(x...); + auto duration_val = this->duration_.value(x...); + this->parent_->start_heater(power_val, duration_val); + } +}; + +template<typename... Ts> class HeaterOffAction : public Action<Ts...>, public Parented<HDC302XComponent> { + public: + void play(const Ts &...x) override { this->parent_->stop_heater(); } +}; + +} // namespace esphome::hdc302x diff --git a/esphome/components/hdc302x/sensor.py b/esphome/components/hdc302x/sensor.py new file mode 100644 index 0000000000..7215a4cfb7 --- /dev/null +++ b/esphome/components/hdc302x/sensor.py @@ -0,0 +1,135 @@ +from esphome import automation +from esphome.automation import maybe_simple_id +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_DURATION, + CONF_HUMIDITY, + CONF_ID, + CONF_POWER, + CONF_POWER_MODE, + CONF_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PERCENT, +) + +DEPENDENCIES = ["i2c"] + +hdc302x_ns = cg.esphome_ns.namespace("hdc302x") +HDC302XComponent = hdc302x_ns.class_( + "HDC302XComponent", cg.PollingComponent, i2c.I2CDevice +) + +HDC302XPowerMode = hdc302x_ns.enum("HDC302XPowerMode") +POWER_MODE_OPTIONS = { + "HIGH_ACCURACY": HDC302XPowerMode.HIGH_ACCURACY, + "BALANCED": HDC302XPowerMode.BALANCED, + "LOW_POWER": HDC302XPowerMode.LOW_POWER, + "ULTRA_LOW_POWER": HDC302XPowerMode.ULTRA_LOW_POWER, +} + +# Actions +HeaterOnAction = hdc302x_ns.class_("HeaterOnAction", automation.Action) +HeaterOffAction = hdc302x_ns.class_("HeaterOffAction", automation.Action) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HDC302XComponent), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_HUMIDITY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_POWER_MODE, default="HIGH_ACCURACY"): cv.enum( + POWER_MODE_OPTIONS, upper=True + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x44)) # Default address per datasheet, Table 7-2. +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + if temp_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temp_config) + cg.add(var.set_temp_sensor(sens)) + + if humidity_config := config.get(CONF_HUMIDITY): + sens = await sensor.new_sensor(humidity_config) + cg.add(var.set_humidity_sensor(sens)) + + cg.add(var.set_power_mode(config[CONF_POWER_MODE])) + + +# HDC302x heater power configs, per datasheet Table 7-15. +HDC302X_HEATER_POWER_MAP = { + "QUARTER": 0x009F, + "HALF": 0x03FF, + "FULL": 0x3FFF, +} + + +def heater_power_value(value): + """Accept enum names or raw uint16 values""" + if isinstance(value, cv.Lambda): + return value + if isinstance(value, str): + upper = value.upper() + if upper in HDC302X_HEATER_POWER_MAP: + return HDC302X_HEATER_POWER_MAP[upper] + raise cv.Invalid( + f"Unknown heater power preset: {value}. Use QUARTER, HALF, FULL, or a raw value 0-16383" + ) + return cv.int_range(min=0, max=0x3FFF)(value) + + +HDC302X_ACTION_SCHEMA = maybe_simple_id({cv.GenerateID(): cv.use_id(HDC302XComponent)}) + +HDC302X_HEATER_ON_ACTION_SCHEMA = maybe_simple_id( + { + cv.GenerateID(): cv.use_id(HDC302XComponent), + cv.Optional(CONF_POWER, default="QUARTER"): cv.templatable(heater_power_value), + cv.Optional(CONF_DURATION, default="5s"): cv.templatable( + cv.positive_time_period_milliseconds + ), + } +) + + +@automation.register_action( + "hdc302x.heater_on", HeaterOnAction, HDC302X_HEATER_ON_ACTION_SCHEMA +) +async def hdc302x_heater_on_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + template_ = await cg.templatable(config[CONF_POWER], args, cg.uint16) + cg.add(var.set_power(template_)) + template_ = await cg.templatable(config[CONF_DURATION], args, cg.uint32) + cg.add(var.set_duration(template_)) + return var + + +@automation.register_action( + "hdc302x.heater_off", HeaterOffAction, HDC302X_ACTION_SCHEMA +) +async def hdc302x_heater_off_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var diff --git a/tests/components/hdc302x/common.yaml b/tests/components/hdc302x/common.yaml new file mode 100644 index 0000000000..56bb31effe --- /dev/null +++ b/tests/components/hdc302x/common.yaml @@ -0,0 +1,19 @@ +esphome: + on_boot: + then: + - hdc302x.heater_on: + id: hdc302x_sensor + power: QUARTER + duration: 5s + - hdc302x.heater_off: + id: hdc302x_sensor + +sensor: + - platform: hdc302x + id: hdc302x_sensor + i2c_id: i2c_bus + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc302x/test.esp32-idf.yaml b/tests/components/hdc302x/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/hdc302x/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/hdc302x/test.esp8266-ard.yaml b/tests/components/hdc302x/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/hdc302x/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/hdc302x/test.rp2040-ard.yaml b/tests/components/hdc302x/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/hdc302x/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml From e199145f1c3b168e8584c4613f1d814c1694a4f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 12:20:55 -0600 Subject: [PATCH 0880/2030] [core] Avoid expensive modulo in LockFreeQueue for non-power-of-2 sizes (#14221) --- esphome/core/lock_free_queue.h | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/esphome/core/lock_free_queue.h b/esphome/core/lock_free_queue.h index e96b739b58..522fbd36e1 100644 --- a/esphome/core/lock_free_queue.h +++ b/esphome/core/lock_free_queue.h @@ -38,13 +38,27 @@ template<class T, uint8_t SIZE> class LockFreeQueue { } protected: + // Advance ring buffer index by one, wrapping at SIZE. + // Power-of-2 sizes use modulo (compiler emits single mask instruction). + // Non-power-of-2 sizes use comparison to avoid expensive multiply-shift sequences. + static constexpr uint8_t next_index(uint8_t index) { + if constexpr ((SIZE & (SIZE - 1)) == 0) { + return (index + 1) % SIZE; + } else { + uint8_t next = index + 1; + if (next >= SIZE) [[unlikely]] + next = 0; + return next; + } + } + // Internal push that reports queue state - for use by derived classes bool push_internal_(T *element, bool &was_empty, uint8_t &old_tail) { if (element == nullptr) return false; uint8_t current_tail = tail_.load(std::memory_order_relaxed); - uint8_t next_tail = (current_tail + 1) % SIZE; + uint8_t next_tail = next_index(current_tail); // Read head before incrementing tail uint8_t head_before = head_.load(std::memory_order_acquire); @@ -73,14 +87,21 @@ template<class T, uint8_t SIZE> class LockFreeQueue { } T *element = buffer_[current_head]; - head_.store((current_head + 1) % SIZE, std::memory_order_release); + head_.store(next_index(current_head), std::memory_order_release); return element; } size_t size() const { uint8_t tail = tail_.load(std::memory_order_acquire); uint8_t head = head_.load(std::memory_order_acquire); - return (tail - head + SIZE) % SIZE; + if constexpr ((SIZE & (SIZE - 1)) == 0) { + return (tail - head + SIZE) % SIZE; + } else { + int diff = static_cast<int>(tail) - static_cast<int>(head); + if (diff < 0) + diff += SIZE; + return static_cast<size_t>(diff); + } } uint16_t get_and_reset_dropped_count() { return dropped_count_.exchange(0, std::memory_order_relaxed); } @@ -90,7 +111,7 @@ template<class T, uint8_t SIZE> class LockFreeQueue { bool empty() const { return head_.load(std::memory_order_acquire) == tail_.load(std::memory_order_acquire); } bool full() const { - uint8_t next_tail = (tail_.load(std::memory_order_relaxed) + 1) % SIZE; + uint8_t next_tail = next_index(tail_.load(std::memory_order_relaxed)); return next_tail == head_.load(std::memory_order_acquire); } From 0d32a5321ca20943eea2d5c9c9d3b3aeac44b568 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 23 Feb 2026 13:46:53 -0500 Subject: [PATCH 0881/2030] [remote_transmitter/remote_receiver] Rename _esp32.cpp to _rmt.cpp (#14226) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/remote_receiver/__init__.py | 2 +- .../{remote_receiver_esp32.cpp => remote_receiver_rmt.cpp} | 0 esphome/components/remote_transmitter/__init__.py | 2 +- ...{remote_transmitter_esp32.cpp => remote_transmitter_rmt.cpp} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename esphome/components/remote_receiver/{remote_receiver_esp32.cpp => remote_receiver_rmt.cpp} (100%) rename esphome/components/remote_transmitter/{remote_transmitter_esp32.cpp => remote_transmitter_rmt.cpp} (100%) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 362f6e99db..53a0f8fb77 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -237,7 +237,7 @@ async def to_code(config): FILTER_SOURCE_FILES = filter_source_files_from_platform( { - "remote_receiver_esp32.cpp": { + "remote_receiver_rmt.cpp": { PlatformFramework.ESP32_ARDUINO, PlatformFramework.ESP32_IDF, }, diff --git a/esphome/components/remote_receiver/remote_receiver_esp32.cpp b/esphome/components/remote_receiver/remote_receiver_rmt.cpp similarity index 100% rename from esphome/components/remote_receiver/remote_receiver_esp32.cpp rename to esphome/components/remote_receiver/remote_receiver_rmt.cpp diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index fc772f88b2..371dbb685f 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -171,7 +171,7 @@ async def to_code(config): FILTER_SOURCE_FILES = filter_source_files_from_platform( { - "remote_transmitter_esp32.cpp": { + "remote_transmitter_rmt.cpp": { PlatformFramework.ESP32_ARDUINO, PlatformFramework.ESP32_IDF, }, diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_rmt.cpp similarity index 100% rename from esphome/components/remote_transmitter/remote_transmitter_esp32.cpp rename to esphome/components/remote_transmitter/remote_transmitter_rmt.cpp From daee71a2c17871b1f23e782059ae9e906abeb9f2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:21:29 -0500 Subject: [PATCH 0882/2030] [http_request] Retry update check on startup until network is ready (#14228) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../update/http_request_update.cpp | 24 ++++++++++++++++++- .../http_request/update/http_request_update.h | 1 + 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 85609bd31f..1900f69a69 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -24,8 +24,29 @@ namespace http_request { static const char *const TAG = "http_request.update"; static const size_t MAX_READ_SIZE = 256; +static constexpr uint32_t INITIAL_CHECK_INTERVAL_ID = 0; +static constexpr uint32_t INITIAL_CHECK_INTERVAL_MS = 10000; +static constexpr uint8_t INITIAL_CHECK_MAX_ATTEMPTS = 6; -void HttpRequestUpdate::setup() { this->ota_parent_->add_state_listener(this); } +void HttpRequestUpdate::setup() { + this->ota_parent_->add_state_listener(this); + + // Check periodically until network is ready + // Only if update interval is > total retry window to avoid redundant checks + if (this->get_update_interval() != SCHEDULER_DONT_RUN && + this->get_update_interval() > INITIAL_CHECK_INTERVAL_MS * INITIAL_CHECK_MAX_ATTEMPTS) { + this->initial_check_remaining_ = INITIAL_CHECK_MAX_ATTEMPTS; + this->set_interval(INITIAL_CHECK_INTERVAL_ID, INITIAL_CHECK_INTERVAL_MS, [this]() { + bool connected = network::is_connected(); + if (--this->initial_check_remaining_ == 0 || connected) { + this->cancel_interval(INITIAL_CHECK_INTERVAL_ID); + if (connected) { + this->update(); + } + } + }); + } +} void HttpRequestUpdate::on_ota_state(ota::OTAState state, float progress, uint8_t error) { if (state == ota::OTAState::OTA_IN_PROGRESS) { @@ -45,6 +66,7 @@ void HttpRequestUpdate::update() { ESP_LOGD(TAG, "Network not connected, skipping update check"); return; } + this->cancel_interval(INITIAL_CHECK_INTERVAL_ID); #ifdef USE_ESP32 xTaskCreate(HttpRequestUpdate::update_task, "update_task", 8192, (void *) this, 1, &this->update_task_handle_); #else diff --git a/esphome/components/http_request/update/http_request_update.h b/esphome/components/http_request/update/http_request_update.h index cf34ace18e..b8350346f9 100644 --- a/esphome/components/http_request/update/http_request_update.h +++ b/esphome/components/http_request/update/http_request_update.h @@ -40,6 +40,7 @@ class HttpRequestUpdate final : public update::UpdateEntity, public PollingCompo #ifdef USE_ESP32 TaskHandle_t update_task_handle_{nullptr}; #endif + uint8_t initial_check_remaining_{0}; }; } // namespace http_request From 063c6a9e45576eb5b22c94977cddac1f1eab1aef Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Mon, 23 Feb 2026 21:06:20 +0100 Subject: [PATCH 0883/2030] [esp32,core] Move CONF_ENABLE_OTA_ROLLBACK to core (#14231) --- esphome/components/esp32/__init__.py | 2 +- esphome/const.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 4c211b2f2a..62367443da 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_BOARD, CONF_COMPONENTS, CONF_DISABLED, + CONF_ENABLE_OTA_ROLLBACK, CONF_ESPHOME, CONF_FRAMEWORK, CONF_IGNORE_EFUSE_CUSTOM_MAC, @@ -90,7 +91,6 @@ CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features" CONF_ENGINEERING_SAMPLE = "engineering_sample" CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components" CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" -CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision" CONF_RELEASE = "release" diff --git a/esphome/const.py b/esphome/const.py index ccc9d56dbb..0b1037d091 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -354,6 +354,7 @@ CONF_ELSE = "else" CONF_ENABLE_BTM = "enable_btm" CONF_ENABLE_IPV6 = "enable_ipv6" CONF_ENABLE_ON_BOOT = "enable_on_boot" +CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" CONF_ENABLE_PIN = "enable_pin" CONF_ENABLE_PRIVATE_NETWORK_ACCESS = "enable_private_network_access" CONF_ENABLE_RRM = "enable_rrm" From 918bbfb0d3c73be7616fc7e7ab57238f27bc35ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 20:22:32 +0000 Subject: [PATCH 0884/2030] Bump aioesphomeapi from 44.0.0 to 44.1.0 (#14232) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index be3445dceb..d22097b3ca 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.1.7 esphome-dashboard==20260210.0 -aioesphomeapi==44.0.0 +aioesphomeapi==44.1.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 02c37bb6d63d9ccb457a13f35b6f2e3c80c35cc9 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Mon, 23 Feb 2026 21:23:40 +0100 Subject: [PATCH 0885/2030] [nrf52,logger] generate crash magic in python (#14173) --- esphome/components/logger/logger_zephyr.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/logger/logger_zephyr.cpp b/esphome/components/logger/logger_zephyr.cpp index c2d24d6efc..6b46b93c61 100644 --- a/esphome/components/logger/logger_zephyr.cpp +++ b/esphome/components/logger/logger_zephyr.cpp @@ -20,8 +20,6 @@ __attribute__((weak)) void print_coredump() {} namespace esphome::logger { -static const uint32_t CRASH_MAGIC = 0xDEADBEEF; - __attribute__((section(".noinit"))) struct { uint32_t magic; uint32_t reason; @@ -152,7 +150,7 @@ static const char *reason_to_str(unsigned int reason, char *buf) { void Logger::dump_crash_() { ESP_LOGD(TAG, "Crash buffer address %p", &crash_buf); - if (crash_buf.magic == CRASH_MAGIC) { + if (crash_buf.magic == App.get_config_hash()) { char reason_buf[REASON_BUF_SIZE]; ESP_LOGE(TAG, "Last crash:"); ESP_LOGE(TAG, "Reason=%s PC=0x%08x LR=0x%08x", reason_to_str(crash_buf.reason, reason_buf), crash_buf.pc, @@ -164,7 +162,7 @@ void Logger::dump_crash_() { } void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf) { - crash_buf.magic = CRASH_MAGIC; + crash_buf.magic = App.get_config_hash(); crash_buf.reason = reason; if (esf) { crash_buf.pc = esf->basic.pc; From 4a529003527b3d475742b29ae2fed82e55b0066c Mon Sep 17 00:00:00 2001 From: James Myatt <james@jamesmyatt.co.uk> Date: Mon, 23 Feb 2026 21:16:32 +0000 Subject: [PATCH 0886/2030] [nfc] Fix logging tag for nfc helpers (#14235) --- esphome/components/nfc/nfc_helpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/nfc/nfc_helpers.cpp b/esphome/components/nfc/nfc_helpers.cpp index bfaed6e486..fb0954a833 100644 --- a/esphome/components/nfc/nfc_helpers.cpp +++ b/esphome/components/nfc/nfc_helpers.cpp @@ -39,7 +39,7 @@ std::string get_random_ha_tag_ndef() { for (int i = 0; i < 12; i++) { uri += ALPHANUM[random_uint32() % (sizeof(ALPHANUM) - 1)]; } - ESP_LOGD("pn7160", "Payload to be written: %s", uri.c_str()); + ESP_LOGD(TAG, "Payload to be written: %s", uri.c_str()); return uri; } From 869678953dfbe22f2b784e8ec927bfa394676671 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 17:03:24 -0600 Subject: [PATCH 0887/2030] [core] Add pow10_int helper, replace powf in normalize_accuracy and sensor filters (#14114) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/sensor/filter.cpp | 5 +++-- esphome/core/helpers.cpp | 11 +++++++++-- esphome/core/helpers.h | 15 +++++++++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index cd4db98457..0fe1effe17 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -5,6 +5,7 @@ #include <cmath> #include "esphome/core/application.h" #include "esphome/core/hal.h" +#include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "sensor.h" @@ -240,7 +241,7 @@ ValueListFilter::ValueListFilter(std::initializer_list<TemplatableValue<float>> bool ValueListFilter::value_matches_any_(float sensor_value) { int8_t accuracy = this->parent_->get_accuracy_decimals(); - float accuracy_mult = powf(10.0f, accuracy); + float accuracy_mult = pow10_int(accuracy); float rounded_sensor = roundf(accuracy_mult * sensor_value); for (auto &filter_value : this->values_) { @@ -472,7 +473,7 @@ optional<float> ClampFilter::new_value(float value) { RoundFilter::RoundFilter(uint8_t precision) : precision_(precision) {} optional<float> RoundFilter::new_value(float value) { if (std::isfinite(value)) { - float accuracy_mult = powf(10.0f, this->precision_); + float accuracy_mult = pow10_int(this->precision_); return roundf(accuracy_mult * value) / accuracy_mult; } return value; diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 9f850b5df8..6d801e7ebc 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -468,8 +468,15 @@ ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) { static inline void normalize_accuracy_decimals(float &value, int8_t &accuracy_decimals) { if (accuracy_decimals < 0) { - auto multiplier = powf(10.0f, accuracy_decimals); - value = roundf(value * multiplier) / multiplier; + float divisor; + if (accuracy_decimals == -1) { + divisor = 10.0f; + } else if (accuracy_decimals == -2) { + divisor = 100.0f; + } else { + divisor = pow10_int(-accuracy_decimals); + } + value = roundf(value / divisor) * divisor; accuracy_decimals = 0; } } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 298b93fbc4..b606e68df3 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -439,6 +439,21 @@ template<size_t STACK_SIZE, typename T = uint8_t> class SmallBufferWithHeapFallb /// @name Mathematics ///@{ +/// Compute 10^exp using iterative multiplication/division. +/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. +/// Matches powf(10, exp) for the int8_t exponent range used by sensor accuracy_decimals. +inline float pow10_int(int8_t exp) { + float result = 1.0f; + if (exp >= 0) { + for (int8_t i = 0; i < exp; i++) + result *= 10.0f; + } else { + for (int8_t i = exp; i < 0; i++) + result /= 10.0f; + } + return result; +} + /// Remap \p value from the range (\p min, \p max) to (\p min_out, \p max_out). template<typename T, typename U> T remap(U value, U min, U max, T min_out, T max_out) { return (value - min) * (max_out - min_out) / (max - min) + min_out; From ebf1047da79805e86ec7a7e1058a2c50c55e42b0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:51:56 -0500 Subject: [PATCH 0888/2030] [core] Move build_info_data.h out of application.h to fix incremental rebuilds (#14230) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../components/version/version_text_sensor.cpp | 1 + esphome/components/web_server/web_server.cpp | 2 +- esphome/core/application.cpp | 11 +++++++++++ esphome/core/application.h | 18 ++++++++---------- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 2e5686008b..74bb4c76e8 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -1,5 +1,6 @@ #include "version_text_sensor.h" #include "esphome/core/application.h" +#include "esphome/core/build_info_data.h" #include "esphome/core/log.h" #include "esphome/core/version.h" #include "esphome/core/helpers.h" diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 4b572417c1..682008c40e 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -375,7 +375,7 @@ json::SerializationBuffer<> WebServer::get_config_json() { JsonObject root = builder.root(); root[ESPHOME_F("title")] = App.get_friendly_name().empty() ? App.get_name().c_str() : App.get_friendly_name().c_str(); - char comment_buffer[ESPHOME_COMMENT_SIZE]; + char comment_buffer[Application::ESPHOME_COMMENT_SIZE_MAX]; App.get_comment_string(comment_buffer); root[ESPHOME_F("comment")] = comment_buffer; #if defined(USE_WEBSERVER_OTA_DISABLED) || !defined(USE_WEBSERVER_OTA) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index c6597897dc..1cb7dc0075 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -749,4 +749,15 @@ void Application::get_build_time_string(std::span<char, BUILD_TIME_STR_SIZE> buf buffer[buffer.size() - 1] = '\0'; } +void Application::get_comment_string(std::span<char, ESPHOME_COMMENT_SIZE_MAX> buffer) { + ESPHOME_strncpy_P(buffer.data(), ESPHOME_COMMENT_STR, ESPHOME_COMMENT_SIZE); + buffer[ESPHOME_COMMENT_SIZE - 1] = '\0'; +} + +uint32_t Application::get_config_hash() { return ESPHOME_CONFIG_HASH; } + +uint32_t Application::get_config_version_hash() { return fnv1a_hash_extend(ESPHOME_CONFIG_HASH, ESPHOME_VERSION); } + +time_t Application::get_build_time() { return ESPHOME_BUILD_TIME; } + } // namespace esphome diff --git a/esphome/core/application.h b/esphome/core/application.h index 5b3e3dfed6..cd275bb97f 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -6,7 +6,6 @@ #include <span> #include <string> #include <vector> -#include "esphome/core/build_info_data.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" @@ -274,16 +273,15 @@ class Application { return ""; } + /// Maximum size of the comment buffer (including null terminator) + static constexpr size_t ESPHOME_COMMENT_SIZE_MAX = 256; + /// Copy the comment string into the provided buffer - /// Buffer must be ESPHOME_COMMENT_SIZE bytes (compile-time enforced) - void get_comment_string(std::span<char, ESPHOME_COMMENT_SIZE> buffer) { - ESPHOME_strncpy_P(buffer.data(), ESPHOME_COMMENT_STR, buffer.size()); - buffer[buffer.size() - 1] = '\0'; - } + void get_comment_string(std::span<char, ESPHOME_COMMENT_SIZE_MAX> buffer); /// Get the comment of this Application as a string std::string get_comment() { - char buffer[ESPHOME_COMMENT_SIZE]; + char buffer[ESPHOME_COMMENT_SIZE_MAX]; this->get_comment_string(buffer); return std::string(buffer); } @@ -294,13 +292,13 @@ class Application { static constexpr size_t BUILD_TIME_STR_SIZE = 26; /// Get the config hash as a 32-bit integer - constexpr uint32_t get_config_hash() { return ESPHOME_CONFIG_HASH; } + uint32_t get_config_hash(); /// Get the config hash extended with ESPHome version - constexpr uint32_t get_config_version_hash() { return fnv1a_hash_extend(ESPHOME_CONFIG_HASH, ESPHOME_VERSION); } + uint32_t get_config_version_hash(); /// Get the build time as a Unix timestamp - constexpr time_t get_build_time() { return ESPHOME_BUILD_TIME; } + time_t get_build_time(); /// Copy the build time string into the provided buffer /// Buffer must be BUILD_TIME_STR_SIZE bytes (compile-time enforced) From 30cc51eac97948449aa87a4e741bab84bb79d6a2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:49:00 -0600 Subject: [PATCH 0889/2030] [version] Use C++17 nested namespace syntax (#14240) --- esphome/components/version/version_text_sensor.cpp | 6 ++---- esphome/components/version/version_text_sensor.h | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 74bb4c76e8..4a08001cc4 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -6,8 +6,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/progmem.h" -namespace esphome { -namespace version { +namespace esphome::version { static const char *const TAG = "version.text_sensor"; @@ -36,5 +35,4 @@ void VersionTextSensor::setup() { void VersionTextSensor::set_hide_timestamp(bool hide_timestamp) { this->hide_timestamp_ = hide_timestamp; } void VersionTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Version Text Sensor", this); } -} // namespace version -} // namespace esphome +} // namespace esphome::version diff --git a/esphome/components/version/version_text_sensor.h b/esphome/components/version/version_text_sensor.h index b7d8001120..6153c5dd7c 100644 --- a/esphome/components/version/version_text_sensor.h +++ b/esphome/components/version/version_text_sensor.h @@ -3,8 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/text_sensor/text_sensor.h" -namespace esphome { -namespace version { +namespace esphome::version { class VersionTextSensor : public text_sensor::TextSensor, public Component { public: @@ -16,5 +15,4 @@ class VersionTextSensor : public text_sensor::TextSensor, public Component { bool hide_timestamp_{false}; }; -} // namespace version -} // namespace esphome +} // namespace esphome::version From 843d06df3f5bf63e9447d1a10eaaa6987f0b5705 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:49:15 -0600 Subject: [PATCH 0890/2030] [switch] Use C++17 nested namespace syntax (#14241) --- esphome/components/switch/automation.cpp | 6 ++---- esphome/components/switch/automation.h | 6 ++---- .../switch/binary_sensor/switch_binary_sensor.cpp | 6 ++---- .../switch/binary_sensor/switch_binary_sensor.h | 6 ++---- esphome/components/switch/switch.cpp | 6 ++---- esphome/components/switch/switch.h | 14 ++++++-------- 6 files changed, 16 insertions(+), 28 deletions(-) diff --git a/esphome/components/switch/automation.cpp b/esphome/components/switch/automation.cpp index 5989ae9ce3..9a0221fe56 100644 --- a/esphome/components/switch/automation.cpp +++ b/esphome/components/switch/automation.cpp @@ -1,10 +1,8 @@ #include "automation.h" #include "esphome/core/log.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { static const char *const TAG = "switch.automation"; -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ diff --git a/esphome/components/switch/automation.h b/esphome/components/switch/automation.h index 27d3474c97..ed1f056c8b 100644 --- a/esphome/components/switch/automation.h +++ b/esphome/components/switch/automation.h @@ -4,8 +4,7 @@ #include "esphome/core/automation.h" #include "esphome/components/switch/switch.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { template<typename... Ts> class TurnOnAction : public Action<Ts...> { public: @@ -104,5 +103,4 @@ template<typename... Ts> class SwitchPublishAction : public Action<Ts...> { Switch *switch_; }; -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ diff --git a/esphome/components/switch/binary_sensor/switch_binary_sensor.cpp b/esphome/components/switch/binary_sensor/switch_binary_sensor.cpp index ba57154446..19995fb1ae 100644 --- a/esphome/components/switch/binary_sensor/switch_binary_sensor.cpp +++ b/esphome/components/switch/binary_sensor/switch_binary_sensor.cpp @@ -1,8 +1,7 @@ #include "switch_binary_sensor.h" #include "esphome/core/log.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { static const char *const TAG = "switch.binary_sensor"; @@ -13,5 +12,4 @@ void SwitchBinarySensor::setup() { void SwitchBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "Switch Binary Sensor", this); } -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ diff --git a/esphome/components/switch/binary_sensor/switch_binary_sensor.h b/esphome/components/switch/binary_sensor/switch_binary_sensor.h index 53b07da903..0b77cdd920 100644 --- a/esphome/components/switch/binary_sensor/switch_binary_sensor.h +++ b/esphome/components/switch/binary_sensor/switch_binary_sensor.h @@ -4,8 +4,7 @@ #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { class SwitchBinarySensor : public binary_sensor::BinarySensor, public Component { public: @@ -17,5 +16,4 @@ class SwitchBinarySensor : public binary_sensor::BinarySensor, public Component Switch *source_; }; -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 61a273d25c..9e9af21368 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -3,8 +3,7 @@ #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { static const char *const TAG = "switch"; @@ -107,5 +106,4 @@ void log_switch(const char *tag, const char *prefix, const char *type, Switch *o } } -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ diff --git a/esphome/components/switch/switch.h b/esphome/components/switch/switch.h index 9319adf9ed..982c640cf9 100644 --- a/esphome/components/switch/switch.h +++ b/esphome/components/switch/switch.h @@ -5,8 +5,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" -namespace esphome { -namespace switch_ { +namespace esphome::switch_ { #define SUB_SWITCH(name) \ protected: \ @@ -16,10 +15,10 @@ namespace switch_ { void set_##name##_switch(switch_::Switch *s) { this->name##_switch_ = s; } // bit0: on/off. bit1: persistent. bit2: inverted. bit3: disabled -const int RESTORE_MODE_ON_MASK = 0x01; -const int RESTORE_MODE_PERSISTENT_MASK = 0x02; -const int RESTORE_MODE_INVERTED_MASK = 0x04; -const int RESTORE_MODE_DISABLED_MASK = 0x08; +constexpr int RESTORE_MODE_ON_MASK = 0x01; +constexpr int RESTORE_MODE_PERSISTENT_MASK = 0x02; +constexpr int RESTORE_MODE_INVERTED_MASK = 0x04; +constexpr int RESTORE_MODE_DISABLED_MASK = 0x08; enum SwitchRestoreMode : uint8_t { SWITCH_ALWAYS_OFF = !RESTORE_MODE_ON_MASK, @@ -146,5 +145,4 @@ class Switch : public EntityBase, public EntityBase_DeviceClass { #define LOG_SWITCH(prefix, type, obj) log_switch((TAG), (prefix), LOG_STR_LITERAL(type), (obj)) void log_switch(const char *tag, const char *prefix, const char *type, Switch *obj); -} // namespace switch_ -} // namespace esphome +} // namespace esphome::switch_ From 63c1496115befafbdf8565f48b34ab7a6ea57753 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:49:25 -0600 Subject: [PATCH 0891/2030] [text] Use C++17 nested namespace syntax (#14242) --- esphome/components/text/automation.h | 6 ++---- esphome/components/text/text.cpp | 6 ++---- esphome/components/text/text.h | 6 ++---- esphome/components/text/text_call.cpp | 6 ++---- esphome/components/text/text_call.h | 6 ++---- esphome/components/text/text_traits.h | 6 ++---- 6 files changed, 12 insertions(+), 24 deletions(-) diff --git a/esphome/components/text/automation.h b/esphome/components/text/automation.h index e7667fe491..ac8166d0be 100644 --- a/esphome/components/text/automation.h +++ b/esphome/components/text/automation.h @@ -4,8 +4,7 @@ #include "esphome/core/component.h" #include "text.h" -namespace esphome { -namespace text { +namespace esphome::text { class TextStateTrigger : public Trigger<std::string> { public: @@ -29,5 +28,4 @@ template<typename... Ts> class TextSetAction : public Action<Ts...> { Text *text_; }; -} // namespace text -} // namespace esphome +} // namespace esphome::text diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index e3f74b685b..d8ab6b1b92 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -4,8 +4,7 @@ #include "esphome/core/log.h" #include <cstring> -namespace esphome { -namespace text { +namespace esphome::text { static const char *const TAG = "text"; @@ -34,5 +33,4 @@ void Text::add_on_state_callback(std::function<void(const std::string &)> &&call this->state_callback_.add(std::move(callback)); } -} // namespace text -} // namespace esphome +} // namespace esphome::text diff --git a/esphome/components/text/text.h b/esphome/components/text/text.h index 3a1bea56cb..7d255e5688 100644 --- a/esphome/components/text/text.h +++ b/esphome/components/text/text.h @@ -6,8 +6,7 @@ #include "text_call.h" #include "text_traits.h" -namespace esphome { -namespace text { +namespace esphome::text { #define LOG_TEXT(prefix, type, obj) \ if ((obj) != nullptr) { \ @@ -47,5 +46,4 @@ class Text : public EntityBase { LazyCallbackManager<void(const std::string &)> state_callback_; }; -} // namespace text -} // namespace esphome +} // namespace esphome::text diff --git a/esphome/components/text/text_call.cpp b/esphome/components/text/text_call.cpp index 0d0a1d228d..8a1630c5ca 100644 --- a/esphome/components/text/text_call.cpp +++ b/esphome/components/text/text_call.cpp @@ -2,8 +2,7 @@ #include "esphome/core/log.h" #include "text.h" -namespace esphome { -namespace text { +namespace esphome::text { static const char *const TAG = "text"; @@ -52,5 +51,4 @@ void TextCall::perform() { this->parent_->control(target_value); } -} // namespace text -} // namespace esphome +} // namespace esphome::text diff --git a/esphome/components/text/text_call.h b/esphome/components/text/text_call.h index 9f75a25c6b..532fae34b2 100644 --- a/esphome/components/text/text_call.h +++ b/esphome/components/text/text_call.h @@ -3,8 +3,7 @@ #include "esphome/core/helpers.h" #include "text_traits.h" -namespace esphome { -namespace text { +namespace esphome::text { class Text; @@ -21,5 +20,4 @@ class TextCall { void validate_(); }; -} // namespace text -} // namespace esphome +} // namespace esphome::text diff --git a/esphome/components/text/text_traits.h b/esphome/components/text/text_traits.h index 473daafb8e..72e65b83ce 100644 --- a/esphome/components/text/text_traits.h +++ b/esphome/components/text/text_traits.h @@ -4,8 +4,7 @@ #include "esphome/core/string_ref.h" -namespace esphome { -namespace text { +namespace esphome::text { enum TextMode : uint8_t { TEXT_MODE_TEXT = 0, @@ -37,5 +36,4 @@ class TextTraits { TextMode mode_{TEXT_MODE_TEXT}; }; -} // namespace text -} // namespace esphome +} // namespace esphome::text From 500aa7bf1d27378ea94141babdad6c83b0176f4f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:49:35 -0600 Subject: [PATCH 0892/2030] [text_sensor] Use C++17 nested namespace syntax (#14243) --- esphome/components/text_sensor/automation.h | 6 ++---- esphome/components/text_sensor/filter.cpp | 6 ++---- esphome/components/text_sensor/filter.h | 6 ++---- esphome/components/text_sensor/text_sensor.cpp | 6 ++---- esphome/components/text_sensor/text_sensor.h | 6 ++---- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/esphome/components/text_sensor/automation.h b/esphome/components/text_sensor/automation.h index 709c54c140..ab30362774 100644 --- a/esphome/components/text_sensor/automation.h +++ b/esphome/components/text_sensor/automation.h @@ -6,8 +6,7 @@ #include "esphome/core/automation.h" #include "esphome/components/text_sensor/text_sensor.h" -namespace esphome { -namespace text_sensor { +namespace esphome::text_sensor { class TextSensorStateTrigger : public Trigger<std::string> { public: @@ -46,5 +45,4 @@ template<typename... Ts> class TextSensorPublishAction : public Action<Ts...> { TextSensor *sensor_; }; -} // namespace text_sensor -} // namespace esphome +} // namespace esphome::text_sensor diff --git a/esphome/components/text_sensor/filter.cpp b/esphome/components/text_sensor/filter.cpp index f6552c7c66..f7c6a695fb 100644 --- a/esphome/components/text_sensor/filter.cpp +++ b/esphome/components/text_sensor/filter.cpp @@ -6,8 +6,7 @@ #include "esphome/core/log.h" #include "esphome/core/hal.h" -namespace esphome { -namespace text_sensor { +namespace esphome::text_sensor { static const char *const TAG = "text_sensor.filter"; @@ -107,7 +106,6 @@ bool MapFilter::new_value(std::string &value) { return true; // Pass through if no match } -} // namespace text_sensor -} // namespace esphome +} // namespace esphome::text_sensor #endif // USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/filter.h b/esphome/components/text_sensor/filter.h index f88e8645cc..8a8bc55c8e 100644 --- a/esphome/components/text_sensor/filter.h +++ b/esphome/components/text_sensor/filter.h @@ -6,8 +6,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" -namespace esphome { -namespace text_sensor { +namespace esphome::text_sensor { class TextSensor; @@ -165,7 +164,6 @@ class MapFilter : public Filter { FixedVector<Substitution> mappings_; }; -} // namespace text_sensor -} // namespace esphome +} // namespace esphome::text_sensor #endif // USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index c66d08ec40..91561c5f42 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -4,8 +4,7 @@ #include "esphome/core/log.h" #include <cstring> -namespace esphome { -namespace text_sensor { +namespace esphome::text_sensor { static const char *const TAG = "text_sensor"; @@ -125,5 +124,4 @@ void TextSensor::notify_frontend_() { #endif } -} // namespace text_sensor -} // namespace esphome +} // namespace esphome::text_sensor diff --git a/esphome/components/text_sensor/text_sensor.h b/esphome/components/text_sensor/text_sensor.h index 97373dc716..9916aa63b2 100644 --- a/esphome/components/text_sensor/text_sensor.h +++ b/esphome/components/text_sensor/text_sensor.h @@ -10,8 +10,7 @@ #include <initializer_list> #include <memory> -namespace esphome { -namespace text_sensor { +namespace esphome::text_sensor { class TextSensor; @@ -84,5 +83,4 @@ class TextSensor : public EntityBase, public EntityBase_DeviceClass { #endif }; -} // namespace text_sensor -} // namespace esphome +} // namespace esphome::text_sensor From a694003fe3f2aca98e930f9d1836d43ac2ee05d4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:49:48 -0600 Subject: [PATCH 0893/2030] [usb_host] Use C++17 nested namespace syntax (#14244) --- esphome/components/usb_host/usb_host.h | 26 +++++++++---------- .../components/usb_host/usb_host_client.cpp | 6 ++--- .../usb_host/usb_host_component.cpp | 6 ++--- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index a6a97d0bd7..2eec0c9699 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -12,8 +12,7 @@ #include "esphome/core/event_pool.h" #include <atomic> -namespace esphome { -namespace usb_host { +namespace esphome::usb_host { // THREADING MODEL: // This component uses a dedicated USB task for event processing to prevent data loss. @@ -44,16 +43,16 @@ struct TransferRequest; class USBClient; // constants for setup packet type -static const uint8_t USB_RECIP_DEVICE = 0; -static const uint8_t USB_RECIP_INTERFACE = 1; -static const uint8_t USB_RECIP_ENDPOINT = 2; -static const uint8_t USB_TYPE_STANDARD = 0 << 5; -static const uint8_t USB_TYPE_CLASS = 1 << 5; -static const uint8_t USB_TYPE_VENDOR = 2 << 5; -static const uint8_t USB_DIR_MASK = 1 << 7; -static const uint8_t USB_DIR_IN = 1 << 7; -static const uint8_t USB_DIR_OUT = 0; -static const size_t SETUP_PACKET_SIZE = 8; +static constexpr uint8_t USB_RECIP_DEVICE = 0; +static constexpr uint8_t USB_RECIP_INTERFACE = 1; +static constexpr uint8_t USB_RECIP_ENDPOINT = 2; +static constexpr uint8_t USB_TYPE_STANDARD = 0 << 5; +static constexpr uint8_t USB_TYPE_CLASS = 1 << 5; +static constexpr uint8_t USB_TYPE_VENDOR = 2 << 5; +static constexpr uint8_t USB_DIR_MASK = 1 << 7; +static constexpr uint8_t USB_DIR_IN = 1 << 7; +static constexpr uint8_t USB_DIR_OUT = 0; +static constexpr size_t SETUP_PACKET_SIZE = 8; static constexpr size_t MAX_REQUESTS = USB_HOST_MAX_REQUESTS; // maximum number of outstanding requests possible. static_assert(MAX_REQUESTS >= 1 && MAX_REQUESTS <= 32, "MAX_REQUESTS must be between 1 and 32"); @@ -189,7 +188,6 @@ class USBHost : public Component { std::vector<USBClient *> clients_{}; }; -} // namespace usb_host -} // namespace esphome +} // namespace esphome::usb_host #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 422d74095c..5b0aed4c59 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -10,8 +10,7 @@ #include <cstring> #include <atomic> #include <span> -namespace esphome { -namespace usb_host { +namespace esphome::usb_host { #pragma GCC diagnostic ignored "-Wparentheses" @@ -568,6 +567,5 @@ void USBClient::release_trq(TransferRequest *trq) { this->trq_in_use_.fetch_and(mask, std::memory_order_release); } -} // namespace usb_host -} // namespace esphome +} // namespace esphome::usb_host #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_host/usb_host_component.cpp b/esphome/components/usb_host/usb_host_component.cpp index 790fe6713b..8ce0a70dc9 100644 --- a/esphome/components/usb_host/usb_host_component.cpp +++ b/esphome/components/usb_host/usb_host_component.cpp @@ -4,8 +4,7 @@ #include <cinttypes> #include "esphome/core/log.h" -namespace esphome { -namespace usb_host { +namespace esphome::usb_host { void USBHost::setup() { usb_host_config_t config{}; @@ -28,7 +27,6 @@ void USBHost::loop() { } } -} // namespace usb_host -} // namespace esphome +} // namespace esphome::usb_host #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 From 1614eb9c9cc3be784d22f262171b7978b21ebbb3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:50:00 -0600 Subject: [PATCH 0894/2030] [i2c] Use C++17 nested namespace syntax (#14245) --- esphome/components/i2c/i2c.cpp | 6 ++---- esphome/components/i2c/i2c.h | 6 ++---- esphome/components/i2c/i2c_bus.h | 6 ++---- esphome/components/i2c/i2c_bus_arduino.cpp | 6 ++---- esphome/components/i2c/i2c_bus_arduino.h | 6 ++---- esphome/components/i2c/i2c_bus_esp_idf.cpp | 6 ++---- esphome/components/i2c/i2c_bus_esp_idf.h | 6 ++---- 7 files changed, 14 insertions(+), 28 deletions(-) diff --git a/esphome/components/i2c/i2c.cpp b/esphome/components/i2c/i2c.cpp index b9b5d79428..76b3ec3b4d 100644 --- a/esphome/components/i2c/i2c.cpp +++ b/esphome/components/i2c/i2c.cpp @@ -5,8 +5,7 @@ #include "esphome/core/log.h" #include <memory> -namespace esphome { -namespace i2c { +namespace esphome::i2c { static const char *const TAG = "i2c"; @@ -109,5 +108,4 @@ uint8_t I2CRegister16::get() const { return value; } -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c diff --git a/esphome/components/i2c/i2c.h b/esphome/components/i2c/i2c.h index aab98d5f46..00929db620 100644 --- a/esphome/components/i2c/i2c.h +++ b/esphome/components/i2c/i2c.h @@ -6,8 +6,7 @@ #include "esphome/core/optional.h" #include "i2c_bus.h" -namespace esphome { -namespace i2c { +namespace esphome::i2c { #define LOG_I2C_DEVICE(this) ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_); @@ -272,5 +271,4 @@ class I2CDevice { I2CBus *bus_{nullptr}; ///< pointer to I2CBus instance }; -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c diff --git a/esphome/components/i2c/i2c_bus.h b/esphome/components/i2c/i2c_bus.h index 2bc0dc1ef9..0c5e80bfe5 100644 --- a/esphome/components/i2c/i2c_bus.h +++ b/esphome/components/i2c/i2c_bus.h @@ -6,8 +6,7 @@ #include "esphome/core/helpers.h" -namespace esphome { -namespace i2c { +namespace esphome::i2c { /// @brief Error codes returned by I2CBus and I2CDevice methods enum ErrorCode { @@ -69,5 +68,4 @@ class InternalI2CBus : public I2CBus { virtual int get_port() const = 0; }; -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index edd6b81588..5120eb4c00 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -7,8 +7,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace i2c { +namespace esphome::i2c { static const char *const TAG = "i2c.arduino"; @@ -262,7 +261,6 @@ void ArduinoI2CBus::recover_() { recovery_result_ = RECOVERY_COMPLETED; } -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c #endif // defined(USE_ARDUINO) && !defined(USE_ESP32) diff --git a/esphome/components/i2c/i2c_bus_arduino.h b/esphome/components/i2c/i2c_bus_arduino.h index 2d69e7684c..edc14af7bc 100644 --- a/esphome/components/i2c/i2c_bus_arduino.h +++ b/esphome/components/i2c/i2c_bus_arduino.h @@ -6,8 +6,7 @@ #include "esphome/core/component.h" #include "i2c_bus.h" -namespace esphome { -namespace i2c { +namespace esphome::i2c { enum RecoveryCode { RECOVERY_FAILED_SCL_LOW, @@ -45,7 +44,6 @@ class ArduinoI2CBus : public InternalI2CBus, public Component { bool initialized_ = false; }; -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c #endif // defined(USE_ARDUINO) && !defined(USE_ESP32) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index 7a965ce5ad..eaefabf75b 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -10,8 +10,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace i2c { +namespace esphome::i2c { static const char *const TAG = "i2c.idf"; @@ -312,6 +311,5 @@ void IDFI2CBus::recover_() { recovery_result_ = RECOVERY_COMPLETED; } -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c #endif // USE_ESP32 diff --git a/esphome/components/i2c/i2c_bus_esp_idf.h b/esphome/components/i2c/i2c_bus_esp_idf.h index 84f4616967..c23f9f0c54 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.h +++ b/esphome/components/i2c/i2c_bus_esp_idf.h @@ -6,8 +6,7 @@ #include "i2c_bus.h" #include <driver/i2c_master.h> -namespace esphome { -namespace i2c { +namespace esphome::i2c { enum RecoveryCode { RECOVERY_FAILED_SCL_LOW, @@ -56,7 +55,6 @@ class IDFI2CBus : public InternalI2CBus, public Component { #endif }; -} // namespace i2c -} // namespace esphome +} // namespace esphome::i2c #endif // USE_ESP32 From 70e47f301d0dd936ce0d30241aa1427fbab02812 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:50:11 -0600 Subject: [PATCH 0895/2030] [ethernet] Use C++17 nested namespace syntax (#14246) --- esphome/components/ethernet/ethernet_component.cpp | 6 ++---- esphome/components/ethernet/ethernet_component.h | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index fcd32223e4..f855bc89cc 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -19,8 +19,7 @@ #include <driver/spi_master.h> #endif -namespace esphome { -namespace ethernet { +namespace esphome::ethernet { #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) // work around IDF compile issue on P4 https://github.com/espressif/esp-idf/pull/15637 @@ -881,7 +880,6 @@ void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister regi #endif -} // namespace ethernet -} // namespace esphome +} // namespace esphome::ethernet #endif // USE_ESP32 diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index b4859c308d..1cd44d2b2c 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -15,8 +15,7 @@ #include "esp_mac.h" #include "esp_idf_version.h" -namespace esphome { -namespace ethernet { +namespace esphome::ethernet { #ifdef USE_ETHERNET_IP_STATE_LISTENERS /** Listener interface for Ethernet IP state changes. @@ -218,7 +217,6 @@ extern EthernetComponent *global_eth_component; extern "C" esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config); #endif -} // namespace ethernet -} // namespace esphome +} // namespace esphome::ethernet #endif // USE_ESP32 From 7d9d90d3f8c4b431b74ad197f9f354f9a4795f59 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 19:50:22 -0600 Subject: [PATCH 0896/2030] [cse7766] Use C++17 nested namespace syntax (#14247) --- esphome/components/cse7766/cse7766.cpp | 6 ++---- esphome/components/cse7766/cse7766.h | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 7ffdf757a0..806b79e19e 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -3,8 +3,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace cse7766 { +namespace esphome::cse7766 { static const char *const TAG = "cse7766"; @@ -258,5 +257,4 @@ void CSE7766Component::dump_config() { this->check_uart_settings(4800, 1, uart::UART_CONFIG_PARITY_EVEN); } -} // namespace cse7766 -} // namespace esphome +} // namespace esphome::cse7766 diff --git a/esphome/components/cse7766/cse7766.h b/esphome/components/cse7766/cse7766.h index 66a4e04633..77b80dd824 100644 --- a/esphome/components/cse7766/cse7766.h +++ b/esphome/components/cse7766/cse7766.h @@ -5,8 +5,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/uart/uart.h" -namespace esphome { -namespace cse7766 { +namespace esphome::cse7766 { static constexpr size_t CSE7766_RAW_DATA_SIZE = 24; @@ -49,5 +48,4 @@ class CSE7766Component : public Component, public uart::UARTDevice { uint16_t cf_pulses_last_{0}; }; -} // namespace cse7766 -} // namespace esphome +} // namespace esphome::cse7766 From ad2da0af52469c18b8741a60e6b4aa977415bf8c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Feb 2026 20:00:21 -0600 Subject: [PATCH 0897/2030] [network] Use C++17 nested namespace syntax (#14248) --- esphome/components/network/ip_address.h | 6 ++---- esphome/components/network/util.cpp | 6 ++---- esphome/components/network/util.h | 6 ++---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index b2a2c563e2..c0e7b2886c 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -37,8 +37,7 @@ using ip4_addr_t = in_addr; #include <esp_netif.h> #endif -namespace esphome { -namespace network { +namespace esphome::network { /// Buffer size for IP address string (IPv6 max: 39 chars + null) static constexpr size_t IP_ADDRESS_BUFFER_SIZE = 40; @@ -187,6 +186,5 @@ struct IPAddress { using IPAddresses = std::array<IPAddress, 5>; -} // namespace network -} // namespace esphome +} // namespace esphome::network #endif diff --git a/esphome/components/network/util.cpp b/esphome/components/network/util.cpp index 5e741fd244..e397d77077 100644 --- a/esphome/components/network/util.cpp +++ b/esphome/components/network/util.cpp @@ -17,8 +17,7 @@ #include "esphome/components/modem/modem_component.h" #endif -namespace esphome { -namespace network { +namespace esphome::network { // The order of the components is important: WiFi should come after any possible main interfaces (it may be used as // an AP that use a previous interface for NAT). @@ -109,6 +108,5 @@ const char *get_use_address() { #endif } -} // namespace network -} // namespace esphome +} // namespace esphome::network #endif diff --git a/esphome/components/network/util.h b/esphome/components/network/util.h index 3dc12232aa..ae949ab0a8 100644 --- a/esphome/components/network/util.h +++ b/esphome/components/network/util.h @@ -4,8 +4,7 @@ #include <string> #include "ip_address.h" -namespace esphome { -namespace network { +namespace esphome::network { /// Return whether the node is connected to the network (through wifi, eth, ...) bool is_connected(); @@ -15,6 +14,5 @@ bool is_disabled(); const char *get_use_address(); IPAddresses get_ip_addresses(); -} // namespace network -} // namespace esphome +} // namespace esphome::network #endif From abf7074518379503dec1a19dd46b8019c1d3a789 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Feb 2026 08:27:48 -0500 Subject: [PATCH 0898/2030] [esp32] Improve ESP32-P4 engineering sample warning message (#14252) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 62367443da..a34747a183 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -790,8 +790,15 @@ def _detect_variant(value): engineering_sample = value.get(CONF_ENGINEERING_SAMPLE) if engineering_sample is None: _LOGGER.warning( - "No board specified for ESP32-P4. Defaulting to production silicon (rev3). " - "If you have an early engineering sample (pre-rev3), set 'engineering_sample: true'." + "No board specified for ESP32-P4. Defaulting to production silicon (rev3).\n" + "If you have an early engineering sample (pre-rev3), add this to your config:\n" + "\n" + " esp32:\n" + " engineering_sample: true\n" + "\n" + "To check your chip revision, look for 'chip revision: vX.Y' in the boot log.\n" + "Engineering samples will show a revision below v3.0.\n" + "The 'debug:' component also reports the revision (e.g. Revision: 100 = v1.0, 300 = v3.0)." ) elif engineering_sample: value[CONF_BOARD] = "esp32-p4-evboard" From 72263eda855c7ffee631a5281fe4c5c9549f4deb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=2E=20=C3=81rkosi=20R=C3=B3bert?= <robreg@zsurob.hu> Date: Tue, 24 Feb 2026 14:31:58 +0100 Subject: [PATCH 0899/2030] [version] text sensor add option `hide_hash` to restore the pre-2026.1 behavior (#14251) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/version/text_sensor.py | 11 +++++- .../version/version_text_sensor.cpp | 34 ++++++++++++++----- .../components/version/version_text_sensor.h | 2 ++ esphome/const.py | 1 + tests/components/version/common.yaml | 15 +++++++- 5 files changed, 52 insertions(+), 11 deletions(-) diff --git a/esphome/components/version/text_sensor.py b/esphome/components/version/text_sensor.py index ba8c493d4b..a55e18a5a7 100644 --- a/esphome/components/version/text_sensor.py +++ b/esphome/components/version/text_sensor.py @@ -1,7 +1,12 @@ import esphome.codegen as cg from esphome.components import text_sensor import esphome.config_validation as cv -from esphome.const import CONF_HIDE_TIMESTAMP, ENTITY_CATEGORY_DIAGNOSTIC, ICON_NEW_BOX +from esphome.const import ( + CONF_HIDE_HASH, + CONF_HIDE_TIMESTAMP, + ENTITY_CATEGORY_DIAGNOSTIC, + ICON_NEW_BOX, +) version_ns = cg.esphome_ns.namespace("version") VersionTextSensor = version_ns.class_( @@ -16,6 +21,9 @@ CONFIG_SCHEMA = ( .extend( { cv.GenerateID(): cv.declare_id(VersionTextSensor), + # Hide the config hash suffix and restore the pre-2026.1 + # version text format when set to true. + cv.Optional(CONF_HIDE_HASH, default=False): cv.boolean, cv.Optional(CONF_HIDE_TIMESTAMP, default=False): cv.boolean, } ) @@ -26,4 +34,5 @@ CONFIG_SCHEMA = ( async def to_code(config): var = await text_sensor.new_text_sensor(config) await cg.register_component(var, config) + cg.add(var.set_hide_hash(config[CONF_HIDE_HASH])) cg.add(var.set_hide_timestamp(config[CONF_HIDE_TIMESTAMP])) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 4a08001cc4..8aec98d2da 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -1,37 +1,53 @@ #include "version_text_sensor.h" #include "esphome/core/application.h" #include "esphome/core/build_info_data.h" -#include "esphome/core/log.h" -#include "esphome/core/version.h" #include "esphome/core/helpers.h" +#include "esphome/core/log.h" #include "esphome/core/progmem.h" +#include "esphome/core/version.h" namespace esphome::version { static const char *const TAG = "version.text_sensor"; void VersionTextSensor::setup() { - static const char PREFIX[] PROGMEM = ESPHOME_VERSION " (config hash 0x"; + static const char HASH_PREFIX[] PROGMEM = ESPHOME_VERSION " (config hash 0x"; + static const char VERSION_PREFIX[] PROGMEM = ESPHOME_VERSION; static const char BUILT_STR[] PROGMEM = ", built "; - // Buffer size: PREFIX + 8 hex chars + BUILT_STR + BUILD_TIME_STR_SIZE + ")" + null - constexpr size_t buf_size = sizeof(PREFIX) + 8 + sizeof(BUILT_STR) + esphome::Application::BUILD_TIME_STR_SIZE + 2; + + // Buffer size: HASH_PREFIX + 8 hex chars + BUILT_STR + BUILD_TIME_STR_SIZE + ")" + null + constexpr size_t buf_size = + sizeof(HASH_PREFIX) + 8 + sizeof(BUILT_STR) + esphome::Application::BUILD_TIME_STR_SIZE + 2; char version_str[buf_size]; - ESPHOME_strncpy_P(version_str, PREFIX, sizeof(version_str)); + // hide_hash restores the pre-2026.1 base format by omitting + // the " (config hash 0x...)" suffix entirely. + if (this->hide_hash_) { + ESPHOME_strncpy_P(version_str, VERSION_PREFIX, sizeof(version_str)); + } else { + ESPHOME_strncpy_P(version_str, HASH_PREFIX, sizeof(version_str)); - size_t len = strlen(version_str); - snprintf(version_str + len, sizeof(version_str) - len, "%08" PRIx32, App.get_config_hash()); + size_t len = strlen(version_str); + snprintf(version_str + len, sizeof(version_str) - len, "%08" PRIx32, App.get_config_hash()); + } + // Keep hide_timestamp behavior independent from hide_hash so all + // combinations remain available to users. if (!this->hide_timestamp_) { size_t len = strlen(version_str); ESPHOME_strncat_P(version_str, BUILT_STR, sizeof(version_str) - len - 1); ESPHOME_strncat_P(version_str, ESPHOME_BUILD_TIME_STR, sizeof(version_str) - strlen(version_str) - 1); } - strncat(version_str, ")", sizeof(version_str) - strlen(version_str) - 1); + // The closing parenthesis is part of the config-hash suffix and must + // only be appended when that suffix is present. + if (!this->hide_hash_) { + strncat(version_str, ")", sizeof(version_str) - strlen(version_str) - 1); + } version_str[sizeof(version_str) - 1] = '\0'; this->publish_state(version_str); } +void VersionTextSensor::set_hide_hash(bool hide_hash) { this->hide_hash_ = hide_hash; } void VersionTextSensor::set_hide_timestamp(bool hide_timestamp) { this->hide_timestamp_ = hide_timestamp; } void VersionTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Version Text Sensor", this); } diff --git a/esphome/components/version/version_text_sensor.h b/esphome/components/version/version_text_sensor.h index 6153c5dd7c..fec898ae03 100644 --- a/esphome/components/version/version_text_sensor.h +++ b/esphome/components/version/version_text_sensor.h @@ -7,11 +7,13 @@ namespace esphome::version { class VersionTextSensor : public text_sensor::TextSensor, public Component { public: + void set_hide_hash(bool hide_hash); void set_hide_timestamp(bool hide_timestamp); void setup() override; void dump_config() override; protected: + bool hide_hash_{false}; bool hide_timestamp_{false}; }; diff --git a/esphome/const.py b/esphome/const.py index 0b1037d091..1611aeb101 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -463,6 +463,7 @@ CONF_HEAT_OVERRUN = "heat_overrun" CONF_HEATER = "heater" CONF_HEIGHT = "height" CONF_HIDDEN = "hidden" +CONF_HIDE_HASH = "hide_hash" CONF_HIDE_TIMESTAMP = "hide_timestamp" CONF_HIGH = "high" CONF_HIGH_VOLTAGE_REFERENCE = "high_voltage_reference" diff --git a/tests/components/version/common.yaml b/tests/components/version/common.yaml index 7713afc37c..f9ff778e14 100644 --- a/tests/components/version/common.yaml +++ b/tests/components/version/common.yaml @@ -1,3 +1,16 @@ text_sensor: - platform: version - name: "ESPHome Version" + name: "ESPHome Version Full" + + - platform: version + name: "ESPHome Version No Timestamp" + hide_timestamp: true + + - platform: version + name: "ESPHome Version No Hash" + hide_hash: true + + - platform: version + name: "ESPHome Version Shortest" + hide_timestamp: true + hide_hash: true From 4abbed0cd4ee94845cee7034a1d06d9a279167a3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:33:33 +1100 Subject: [PATCH 0900/2030] [mipi_dsi] Allow transform disable; fix warnings (#14216) --- esphome/components/mipi_dsi/display.py | 24 +++++++++++-------- esphome/components/mipi_dsi/mipi_dsi.cpp | 4 ++-- esphome/components/mipi_dsi/mipi_dsi.h | 10 ++++---- .../mipi_dsi/fixtures/mipi_dsi.yaml | 17 +++++++++++++ .../mipi_dsi/test_mipi_dsi_config.py | 3 ++- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index de3791b3a4..85bfad7f1a 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -39,6 +39,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_COLOR_ORDER, CONF_DIMENSIONS, + CONF_DISABLED, CONF_ENABLE_PIN, CONF_ID, CONF_INIT_SEQUENCE, @@ -88,14 +89,17 @@ COLOR_DEPTHS = { def model_schema(config): model = MODELS[config[CONF_MODEL].upper()] model.defaults[CONF_SWAP_XY] = cv.UNDEFINED - transform = cv.Schema( - { - cv.Required(CONF_MIRROR_X): cv.boolean, - cv.Required(CONF_MIRROR_Y): cv.boolean, - cv.Optional(CONF_SWAP_XY): cv.invalid( - "Axis swapping not supported by DSI displays" - ), - } + transform = cv.Any( + cv.Schema( + { + cv.Required(CONF_MIRROR_X): cv.boolean, + cv.Required(CONF_MIRROR_Y): cv.boolean, + cv.Optional(CONF_SWAP_XY): cv.invalid( + "Axis swapping not supported by DSI displays" + ), + } + ), + cv.one_of(CONF_DISABLED, lower=True), ) # CUSTOM model will need to provide a custom init sequence iseqconf = ( @@ -199,9 +203,9 @@ async def to_code(config): cg.add(var.set_vsync_pulse_width(config[CONF_VSYNC_PULSE_WIDTH])) cg.add(var.set_vsync_back_porch(config[CONF_VSYNC_BACK_PORCH])) cg.add(var.set_vsync_front_porch(config[CONF_VSYNC_FRONT_PORCH])) - cg.add(var.set_pclk_frequency(int(config[CONF_PCLK_FREQUENCY] / 1e6))) + cg.add(var.set_pclk_frequency(config[CONF_PCLK_FREQUENCY] / 1.0e6)) cg.add(var.set_lanes(int(config[CONF_LANES]))) - cg.add(var.set_lane_bit_rate(int(config[CONF_LANE_BIT_RATE] / 1e6))) + cg.add(var.set_lane_bit_rate(config[CONF_LANE_BIT_RATE] / 1.0e6)) if reset_pin := config.get(CONF_RESET_PIN): reset = await cg.gpio_pin_expression(reset_pin) cg.add(var.set_reset_pin(reset)) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 18cafab684..4d45cfb799 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -374,7 +374,7 @@ void MIPI_DSI::dump_config() { "\n Swap X/Y: %s" "\n Rotation: %d degrees" "\n DSI Lanes: %u" - "\n Lane Bit Rate: %uMbps" + "\n Lane Bit Rate: %.0fMbps" "\n HSync Pulse Width: %u" "\n HSync Back Porch: %u" "\n HSync Front Porch: %u" @@ -385,7 +385,7 @@ void MIPI_DSI::dump_config() { "\n Display Pixel Mode: %d bit" "\n Color Order: %s" "\n Invert Colors: %s" - "\n Pixel Clock: %dMHz", + "\n Pixel Clock: %.1fMHz", this->model_, this->width_, this->height_, YESNO(this->madctl_ & (MADCTL_XFLIP | MADCTL_MX)), YESNO(this->madctl_ & (MADCTL_YFLIP | MADCTL_MY)), YESNO(this->madctl_ & MADCTL_MV), this->rotation_, this->lanes_, this->lane_bit_rate_, this->hsync_pulse_width_, this->hsync_back_porch_, diff --git a/esphome/components/mipi_dsi/mipi_dsi.h b/esphome/components/mipi_dsi/mipi_dsi.h index 1cffe3b178..6e27912aa5 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.h +++ b/esphome/components/mipi_dsi/mipi_dsi.h @@ -47,7 +47,7 @@ class MIPI_DSI : public display::Display { void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_enable_pins(std::vector<GPIOPin *> enable_pins) { this->enable_pins_ = std::move(enable_pins); } - void set_pclk_frequency(uint32_t pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } + void set_pclk_frequency(float pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } int get_width_internal() override { return this->width_; } int get_height_internal() override { return this->height_; } void set_hsync_back_porch(uint16_t hsync_back_porch) { this->hsync_back_porch_ = hsync_back_porch; } @@ -58,7 +58,7 @@ class MIPI_DSI : public display::Display { void set_vsync_front_porch(uint16_t vsync_front_porch) { this->vsync_front_porch_ = vsync_front_porch; } void set_init_sequence(const std::vector<uint8_t> &init_sequence) { this->init_sequence_ = init_sequence; } void set_model(const char *model) { this->model_ = model; } - void set_lane_bit_rate(uint16_t lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } + void set_lane_bit_rate(float lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } void set_lanes(uint8_t lanes) { this->lanes_ = lanes; } void set_madctl(uint8_t madctl) { this->madctl_ = madctl; } @@ -95,9 +95,9 @@ class MIPI_DSI : public display::Display { uint16_t vsync_front_porch_ = 10; const char *model_{"Unknown"}; std::vector<uint8_t> init_sequence_{}; - uint16_t pclk_frequency_ = 16; // in MHz - uint16_t lane_bit_rate_{1500}; // in Mbps - uint8_t lanes_{2}; // 1, 2, 3 or 4 lanes + float pclk_frequency_ = 16; // in MHz + float lane_bit_rate_{1500}; // in Mbps + uint8_t lanes_{2}; // 1, 2, 3 or 4 lanes bool invert_colors_{}; display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; diff --git a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml index 6de2bd5a77..6f76dcb1d1 100644 --- a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml +++ b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml @@ -22,6 +22,23 @@ display: id: p4_86 model: "WAVESHARE-P4-86-PANEL" rotation: 180 + - platform: mipi_dsi + model: custom + id: custom_id + dimensions: + width: 400 + height: 1280 + hsync_back_porch: 40 + hsync_pulse_width: 30 + hsync_front_porch: 40 + vsync_back_porch: 20 + vsync_pulse_width: 10 + vsync_front_porch: 20 + pclk_frequency: 48Mhz + lane_bit_rate: 1.2Gbps + rotation: 180 + transform: disabled + init_sequence: i2c: sda: GPIO7 scl: GPIO8 diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index d465a8c81b..92f56b5451 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -123,7 +123,8 @@ def test_code_generation( in main_cpp ) assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp - assert "p4_nano->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_lane_bit_rate(1500.0f);" in main_cpp assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" in main_cpp + assert "custom_id->set_rotation(display::DISPLAY_ROTATION_180_DEGREES);" in main_cpp # assert "backlight_id = new light::LightState(mipi_dsi_dsibacklight_id);" in main_cpp From 6554ad7c7ef933a094b31583bb2dd285831bc8b3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 12:08:51 -0600 Subject: [PATCH 0901/2030] [core] Prevent inlining of mark_matching_items_removed_locked_ on Thumb-1 (#14256) --- esphome/core/scheduler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 16b0ded312..ed457b87f6 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -496,9 +496,9 @@ class Scheduler { // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal // IMPORTANT: Must be called with scheduler lock held - size_t mark_matching_items_removed_locked_(std::vector<std::unique_ptr<SchedulerItem>> &container, - Component *component, NameType name_type, const char *static_name, - uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { + __attribute__((noinline)) size_t mark_matching_items_removed_locked_( + std::vector<std::unique_ptr<SchedulerItem>> &container, Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { size_t count = 0; for (auto &item : container) { // Skip nullptr items (can happen in defer_queue_ when items are being processed) From fe3c2ba5553f4d07328d1c5b1e927ca0cbea25e1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:15:22 -0500 Subject: [PATCH 0902/2030] [http_request.ota] Percent-encode credentials in URL (#14257) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../http_request/ota/ota_http_request.cpp | 22 +++++++++++++++++++ .../http_request/ota/ota_http_request.h | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index d77a768211..0db3a50b47 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -1,5 +1,7 @@ #include "ota_http_request.h" +#include <cctype> + #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" @@ -209,6 +211,26 @@ uint8_t OtaHttpRequestComponent::do_ota_() { return ota::OTA_RESPONSE_OK; } +// URL-encode characters that are not unreserved per RFC 3986 section 2.3. +// This is needed for embedding userinfo (username/password) in URLs safely. +static std::string url_encode(const std::string &str) { + std::string result; + result.reserve(str.size()); + for (char c : str) { + if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~') { + result += c; + } else { + result += '%'; + result += format_hex_pretty_char((static_cast<uint8_t>(c) >> 4) & 0x0F); + result += format_hex_pretty_char(static_cast<uint8_t>(c) & 0x0F); + } + } + return result; +} + +void OtaHttpRequestComponent::set_password(const std::string &password) { this->password_ = url_encode(password); } +void OtaHttpRequestComponent::set_username(const std::string &username) { this->username_ = url_encode(username); } + std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { if (this->username_.empty() || this->password_.empty()) { return url; diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 8735189e99..e3f1a4aa90 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -29,9 +29,9 @@ class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRe 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_password(const std::string &password); void set_url(const std::string &url); - void set_username(const std::string &username) { this->username_ = username; } + void set_username(const std::string &username); std::string md5_computed() { return this->md5_computed_; } std::string md5_expected() { return this->md5_expected_; } From af00d601be022c0ba3b5d9656c9906c95b4edb64 Mon Sep 17 00:00:00 2001 From: Andrew Rankin <andrew@eiknet.com> Date: Tue, 24 Feb 2026 16:19:13 -0500 Subject: [PATCH 0903/2030] [esp32_ble_server] add max_clients option for multi-client support (#14239) --- .../components/esp32_ble_server/__init__.py | 20 +++++++++++++++++++ .../esp32_ble_server/ble_server.cpp | 11 +++++++++- .../components/esp32_ble_server/ble_server.h | 4 ++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index cb494ed1bc..b08e791e7e 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -24,6 +24,7 @@ from esphome.const import ( __version__ as ESPHOME_VERSION, ) from esphome.core import CORE +import esphome.final_validate as fv from esphome.schema_extractors import SCHEMA_EXTRACT AUTO_LOAD = ["esp32_ble", "bytebuffer"] @@ -42,6 +43,7 @@ CONF_FIRMWARE_VERSION = "firmware_version" CONF_INDICATE = "indicate" CONF_MANUFACTURER = "manufacturer" CONF_MANUFACTURER_DATA = "manufacturer_data" +CONF_MAX_CLIENTS = "max_clients" CONF_ON_WRITE = "on_write" CONF_READ = "read" CONF_STRING = "string" @@ -287,6 +289,22 @@ def create_device_information_service(config): def final_validate_config(config): + # Validate max_clients does not exceed esp32_ble max_connections + max_clients = config[CONF_MAX_CLIENTS] + if max_clients > 1: + full_config = fv.full_config.get() + ble_config = full_config.get("esp32_ble", {}) + max_connections = ble_config.get( + "max_connections", esp32_ble.DEFAULT_MAX_CONNECTIONS + ) + if max_clients > max_connections: + raise cv.Invalid( + f"'max_clients' ({max_clients}) cannot exceed esp32_ble " + f"'max_connections' ({max_connections}). " + f"Please set 'max_connections: {max_clients}' in the " + f"'esp32_ble' component." + ) + # Check if all characteristics that require notifications have the notify property set for char_id in CORE.data.get(DOMAIN, {}).get(KEY_NOTIFY_REQUIRED, set()): # Look for the characteristic in the configuration @@ -428,6 +446,7 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_MODEL): value_schema("string", templatable=False), cv.Optional(CONF_FIRMWARE_VERSION): value_schema("string", templatable=False), cv.Optional(CONF_MANUFACTURER_DATA): cv.Schema([cv.uint8_t]), + cv.Optional(CONF_MAX_CLIENTS, default=1): cv.int_range(min=1, max=9), cv.Optional(CONF_SERVICES, default=[]): cv.ensure_list(SERVICE_SCHEMA), cv.Optional(CONF_ON_CONNECT): automation.validate_automation(single=True), cv.Optional(CONF_ON_DISCONNECT): automation.validate_automation(single=True), @@ -552,6 +571,7 @@ async def to_code(config): esp32_ble.register_ble_status_event_handler(parent, var) cg.add(var.set_parent(parent)) cg.add(parent.advertising_set_appearance(config[CONF_APPEARANCE])) + cg.add(var.set_max_clients(config[CONF_MAX_CLIENTS])) if CONF_MANUFACTURER_DATA in config: cg.add(var.set_manufacturer_data(config[CONF_MANUFACTURER_DATA])) for service_config in config[CONF_SERVICES]: diff --git a/esphome/components/esp32_ble_server/ble_server.cpp b/esphome/components/esp32_ble_server/ble_server.cpp index 2c13a8ac36..f292cf8722 100644 --- a/esphome/components/esp32_ble_server/ble_server.cpp +++ b/esphome/components/esp32_ble_server/ble_server.cpp @@ -175,6 +175,10 @@ void BLEServer::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t ga case ESP_GATTS_CONNECT_EVT: { ESP_LOGD(TAG, "BLE Client connected"); this->add_client_(param->connect.conn_id); + // Resume advertising so additional clients can discover and connect + if (this->client_count_ < this->max_clients_) { + this->parent_->advertising_start(); + } this->dispatch_callbacks_(CallbackType::ON_CONNECT, param->connect.conn_id); break; } @@ -241,7 +245,12 @@ void BLEServer::ble_before_disabled_event_handler() { float BLEServer::get_setup_priority() const { return setup_priority::AFTER_BLUETOOTH + 10; } -void BLEServer::dump_config() { ESP_LOGCONFIG(TAG, "ESP32 BLE Server:"); } +void BLEServer::dump_config() { + ESP_LOGCONFIG(TAG, + "ESP32 BLE Server:\n" + " Max clients: %u", + this->max_clients_); +} BLEServer *global_ble_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/esp32_ble_server/ble_server.h b/esphome/components/esp32_ble_server/ble_server.h index 6fa86dd67f..ff7e0044e4 100644 --- a/esphome/components/esp32_ble_server/ble_server.h +++ b/esphome/components/esp32_ble_server/ble_server.h @@ -39,6 +39,9 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv this->restart_advertising_(); } + void set_max_clients(uint8_t max_clients) { this->max_clients_ = max_clients; } + uint8_t get_max_clients() const { return this->max_clients_; } + BLEService *create_service(ESPBTUUID uuid, bool advertise = false, uint16_t num_handles = 15); void remove_service(ESPBTUUID uuid, uint8_t inst_id = 0); BLEService *get_service(ESPBTUUID uuid, uint8_t inst_id = 0); @@ -95,6 +98,7 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv uint16_t clients_[USE_ESP32_BLE_MAX_CONNECTIONS]{}; uint8_t client_count_{0}; + uint8_t max_clients_{1}; std::vector<ServiceEntry> services_{}; std::vector<BLEService *> services_to_start_{}; BLEService *device_information_service_{}; From cca4777f6458c1bf41e2cdd79f91aafe699e9c08 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 17:51:01 -0600 Subject: [PATCH 0904/2030] [web_server_idf] Pass std::function by rvalue reference (#14262) --- esphome/components/web_server_idf/multipart.h | 4 ++-- esphome/components/web_server_idf/web_server_idf.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/web_server_idf/multipart.h b/esphome/components/web_server_idf/multipart.h index cb1e0ecd1d..8b94b0491e 100644 --- a/esphome/components/web_server_idf/multipart.h +++ b/esphome/components/web_server_idf/multipart.h @@ -33,8 +33,8 @@ class MultipartReader { ~MultipartReader(); // Set callbacks for handling data - void set_data_callback(DataCallback callback) { data_callback_ = std::move(callback); } - void set_part_complete_callback(PartCompleteCallback callback) { part_complete_callback_ = std::move(callback); } + void set_data_callback(DataCallback &&callback) { data_callback_ = std::move(callback); } + void set_part_complete_callback(PartCompleteCallback &&callback) { part_complete_callback_ = std::move(callback); } // Parse incoming data size_t parse(const char *data, size_t len); diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 76ddfa35fd..9d81d89ec7 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -204,7 +204,7 @@ class AsyncWebServer { ~AsyncWebServer() { this->end(); } // NOLINTNEXTLINE(readability-identifier-naming) - void onNotFound(std::function<void(AsyncWebServerRequest *request)> fn) { on_not_found_ = std::move(fn); } + void onNotFound(std::function<void(AsyncWebServerRequest *request)> &&fn) { on_not_found_ = std::move(fn); } void begin(); void end(); @@ -327,7 +327,7 @@ class AsyncEventSource : public AsyncWebHandler { // NOLINTNEXTLINE(readability-identifier-naming) void handleRequest(AsyncWebServerRequest *request) override; // NOLINTNEXTLINE(readability-identifier-naming) - void onConnect(connect_handler_t cb) { this->on_connect_ = std::move(cb); } + void onConnect(connect_handler_t &&cb) { this->on_connect_ = std::move(cb); } void try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0); void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator); From 4dc6b12ec51d9e8610ca5be0fc77ebf9c3f39da3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 17:56:43 -0600 Subject: [PATCH 0905/2030] [api] Pass std::function by rvalue reference in state subscriptions (#14261) --- esphome/components/api/api_server.cpp | 20 ++++++++++---------- esphome/components/api/api_server.h | 20 ++++++++++---------- esphome/components/api/user_services.h | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 5b096788f5..0352d7347b 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -433,8 +433,8 @@ void APIServer::handle_action_response(uint32_t call_id, bool success, StringRef #ifdef USE_API_HOMEASSISTANT_STATES // Helper to add subscription (reduces duplication) -void APIServer::add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f, - bool once) { +void APIServer::add_state_subscription_(const char *entity_id, const char *attribute, + std::function<void(StringRef)> &&f, bool once) { this->state_subs_.push_back(HomeAssistantStateSubscription{ .entity_id = entity_id, .attribute = attribute, .callback = std::move(f), .once = once, // entity_id_dynamic_storage and attribute_dynamic_storage remain nullptr (no heap allocation) @@ -443,7 +443,7 @@ void APIServer::add_state_subscription_(const char *entity_id, const char *attri // Helper to add subscription with heap-allocated strings (reduces duplication) void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute, - std::function<void(StringRef)> f, bool once) { + std::function<void(StringRef)> &&f, bool once) { HomeAssistantStateSubscription sub; // Allocate heap storage for the strings sub.entity_id_dynamic_storage = std::make_unique<std::string>(std::move(entity_id)); @@ -463,29 +463,29 @@ void APIServer::add_state_subscription_(std::string entity_id, optional<std::str // New const char* overload (for internal components - zero allocation) void APIServer::subscribe_home_assistant_state(const char *entity_id, const char *attribute, - std::function<void(StringRef)> f) { + std::function<void(StringRef)> &&f) { this->add_state_subscription_(entity_id, attribute, std::move(f), false); } void APIServer::get_home_assistant_state(const char *entity_id, const char *attribute, - std::function<void(StringRef)> f) { + std::function<void(StringRef)> &&f) { this->add_state_subscription_(entity_id, attribute, std::move(f), true); } // std::string overload with StringRef callback (zero-allocation callback) void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(StringRef)> f) { + std::function<void(StringRef)> &&f) { this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false); } void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(StringRef)> f) { + std::function<void(StringRef)> &&f) { this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true); } // Legacy helper: wraps std::string callback and delegates to StringRef version void APIServer::add_state_subscription_(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f, bool once) { + std::function<void(const std::string &)> &&f, bool once) { // Wrap callback to convert StringRef -> std::string, then delegate this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::function<void(StringRef)>([f = std::move(f)](StringRef state) { f(state.str()); }), @@ -494,12 +494,12 @@ void APIServer::add_state_subscription_(std::string entity_id, optional<std::str // Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string) void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f) { + std::function<void(const std::string &)> &&f) { this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), false); } void APIServer::get_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f) { + std::function<void(const std::string &)> &&f) { this->add_state_subscription_(std::move(entity_id), std::move(attribute), std::move(f), true); } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index fed29016b3..3abf68358c 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -201,20 +201,20 @@ class APIServer : public Component, }; // New const char* overload (for internal components - zero allocation) - void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f); - void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> f); + void subscribe_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f); + void get_home_assistant_state(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f); // std::string overload with StringRef callback (for custom_api_device.h with zero-allocation callback) void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(StringRef)> f); + std::function<void(StringRef)> &&f); void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(StringRef)> f); + std::function<void(StringRef)> &&f); // Legacy std::string overload (for custom_api_device.h - converts StringRef to std::string for callback) void subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f); + std::function<void(const std::string &)> &&f); void get_home_assistant_state(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f); + std::function<void(const std::string &)> &&f); const std::vector<HomeAssistantStateSubscription> &get_state_subs() const; #endif @@ -241,13 +241,13 @@ class APIServer : public Component, #endif // USE_API_NOISE #ifdef USE_API_HOMEASSISTANT_STATES // Helper methods to reduce code duplication - void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> f, - bool once); - void add_state_subscription_(std::string entity_id, optional<std::string> attribute, std::function<void(StringRef)> f, + void add_state_subscription_(const char *entity_id, const char *attribute, std::function<void(StringRef)> &&f, bool once); + void add_state_subscription_(std::string entity_id, optional<std::string> attribute, + std::function<void(StringRef)> &&f, bool once); // Legacy helper: wraps std::string callback and delegates to StringRef version void add_state_subscription_(std::string entity_id, optional<std::string> attribute, - std::function<void(const std::string &)> f, bool once); + std::function<void(const std::string &)> &&f, bool once); #endif // USE_API_HOMEASSISTANT_STATES // No explicit close() needed — listen sockets have no active connections on // failure/shutdown. Destructor handles fd cleanup (close or abort per platform). diff --git a/esphome/components/api/user_services.h b/esphome/components/api/user_services.h index 0fc529108c..d1b8a6ef0d 100644 --- a/esphome/components/api/user_services.h +++ b/esphome/components/api/user_services.h @@ -230,7 +230,7 @@ template<typename... Ts> class APIRespondAction : public Action<Ts...> { void set_is_optional_mode(bool is_optional) { this->is_optional_mode_ = is_optional; } #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - void set_data(std::function<void(Ts..., JsonObject)> func) { + void set_data(std::function<void(Ts..., JsonObject)> &&func) { this->json_builder_ = std::move(func); this->has_data_ = true; } From 08dc487b5b668f1dbf4ec6573aceca2de0d1fdd8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 18:08:07 -0600 Subject: [PATCH 0906/2030] [core] Pass std::function by rvalue reference in scheduler (#14260) --- esphome/core/scheduler.cpp | 15 ++++++++------- esphome/core/scheduler.h | 18 +++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index e4e0751e10..674d70abcf 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -135,7 +135,7 @@ bool Scheduler::is_retry_cancelled_locked_(Component *component, NameType name_t // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, const char *static_name, uint32_t hash_or_id, uint32_t delay, - std::function<void()> func, bool is_retry, bool skip_cancel) { + std::function<void()> &&func, bool is_retry, bool skip_cancel) { if (delay == SCHEDULER_DONT_RUN) { // Still need to cancel existing timer if we have a name/id if (!skip_cancel) { @@ -216,17 +216,18 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type target->push_back(std::move(item)); } -void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func) { +void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, + std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::STATIC_STRING, name, 0, timeout, std::move(func)); } void HOT Scheduler::set_timeout(Component *component, const std::string &name, uint32_t timeout, - std::function<void()> func) { + std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), timeout, std::move(func)); } -void HOT Scheduler::set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function<void()> func) { +void HOT Scheduler::set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::NUMERIC_ID, nullptr, id, timeout, std::move(func)); } @@ -240,17 +241,17 @@ bool HOT Scheduler::cancel_timeout(Component *component, uint32_t id) { return this->cancel_item_(component, NameType::NUMERIC_ID, nullptr, id, SchedulerItem::TIMEOUT); } void HOT Scheduler::set_interval(Component *component, const std::string &name, uint32_t interval, - std::function<void()> func) { + std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::HASHED_STRING, nullptr, fnv1a_hash(name), interval, std::move(func)); } void HOT Scheduler::set_interval(Component *component, const char *name, uint32_t interval, - std::function<void()> func) { + std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::STATIC_STRING, name, 0, interval, std::move(func)); } -void HOT Scheduler::set_interval(Component *component, uint32_t id, uint32_t interval, std::function<void()> func) { +void HOT Scheduler::set_interval(Component *component, uint32_t id, uint32_t interval, std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::NUMERIC_ID, nullptr, id, interval, std::move(func)); } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index ed457b87f6..b6a8336606 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -33,7 +33,7 @@ class Scheduler { // std::string overload - deprecated, use const char* or uint32_t instead // Remove before 2026.7.0 ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") - void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function<void()> func); + void set_timeout(Component *component, const std::string &name, uint32_t timeout, std::function<void()> &&func); /** Set a timeout with a const char* name. * @@ -43,11 +43,11 @@ class Scheduler { * - A static const char* variable * - A pointer with lifetime >= the scheduled task */ - void set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> func); + void set_timeout(Component *component, const char *name, uint32_t timeout, std::function<void()> &&func); /// Set a timeout with a numeric ID (zero heap allocation) - void set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function<void()> func); + void set_timeout(Component *component, uint32_t id, uint32_t timeout, std::function<void()> &&func); /// Set a timeout with an internal scheduler ID (separate namespace from component NUMERIC_ID) - void set_timeout(Component *component, InternalSchedulerID id, uint32_t timeout, std::function<void()> func) { + void set_timeout(Component *component, InternalSchedulerID id, uint32_t timeout, std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::TIMEOUT, NameType::NUMERIC_ID_INTERNAL, nullptr, static_cast<uint32_t>(id), timeout, std::move(func)); } @@ -62,7 +62,7 @@ class Scheduler { } ESPDEPRECATED("Use const char* or uint32_t overload instead. Removed in 2026.7.0", "2026.1.0") - void set_interval(Component *component, const std::string &name, uint32_t interval, std::function<void()> func); + void set_interval(Component *component, const std::string &name, uint32_t interval, std::function<void()> &&func); /** Set an interval with a const char* name. * @@ -72,11 +72,11 @@ class Scheduler { * - A static const char* variable * - A pointer with lifetime >= the scheduled task */ - void set_interval(Component *component, const char *name, uint32_t interval, std::function<void()> func); + void set_interval(Component *component, const char *name, uint32_t interval, std::function<void()> &&func); /// Set an interval with a numeric ID (zero heap allocation) - void set_interval(Component *component, uint32_t id, uint32_t interval, std::function<void()> func); + void set_interval(Component *component, uint32_t id, uint32_t interval, std::function<void()> &&func); /// Set an interval with an internal scheduler ID (separate namespace from component NUMERIC_ID) - void set_interval(Component *component, InternalSchedulerID id, uint32_t interval, std::function<void()> func) { + void set_interval(Component *component, InternalSchedulerID id, uint32_t interval, std::function<void()> &&func) { this->set_timer_common_(component, SchedulerItem::INTERVAL, NameType::NUMERIC_ID_INTERNAL, nullptr, static_cast<uint32_t>(id), interval, std::move(func)); } @@ -255,7 +255,7 @@ class Scheduler { // Common implementation for both timeout and interval // name_type determines storage type: STATIC_STRING uses static_name, others use hash_or_id void set_timer_common_(Component *component, SchedulerItem::Type type, NameType name_type, const char *static_name, - uint32_t hash_or_id, uint32_t delay, std::function<void()> func, bool is_retry = false, + uint32_t hash_or_id, uint32_t delay, std::function<void()> &&func, bool is_retry = false, bool skip_cancel = false); // Common implementation for retry - Remove before 2026.8.0 From 2ff876c629a3181e1907fc52594d1257f5165139 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 18:18:44 -0600 Subject: [PATCH 0907/2030] [core] Use custom deleter for SchedulerItem unique_ptr to prevent destructor inlining (#14258) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/core/scheduler.cpp | 22 ++++++++++------- esphome/core/scheduler.h | 48 ++++++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 674d70abcf..d9c66b2000 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -33,6 +33,11 @@ static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; +// Prevent inlining of SchedulerItem deletion. On BK7231N (Thumb-1), GCC inlines +// ~unique_ptr<SchedulerItem> (~30 bytes each) at every destruction site. Defining +// the deleter in the .cpp file ensures a single copy of the destructor + operator delete. +void Scheduler::SchedulerItemDeleter::operator()(SchedulerItem *ptr) const noexcept { delete ptr; } + #if defined(ESPHOME_LOG_HAS_VERBOSE) || defined(ESPHOME_DEBUG_SCHEDULER) // Helper struct for formatting scheduler item names consistently in logs // Uses a stack buffer to avoid heap allocation @@ -468,7 +473,7 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; - std::vector<std::unique_ptr<SchedulerItem>> old_items; + std::vector<SchedulerItemPtr> old_items; #ifdef ESPHOME_THREAD_MULTI_ATOMICS const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); @@ -481,7 +486,7 @@ void HOT Scheduler::call(uint32_t now) { // Cleanup before debug output this->cleanup_(); while (!this->items_.empty()) { - std::unique_ptr<SchedulerItem> item; + SchedulerItemPtr item; { LockGuard guard{this->lock_}; item = this->pop_raw_locked_(); @@ -642,7 +647,7 @@ size_t HOT Scheduler::cleanup_() { } return this->items_.size(); } -std::unique_ptr<Scheduler::SchedulerItem> HOT Scheduler::pop_raw_locked_() { +Scheduler::SchedulerItemPtr HOT Scheduler::pop_raw_locked_() { std::pop_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); // Move the item out before popping - this is the item that was at the front of the heap @@ -865,8 +870,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { #endif } -bool HOT Scheduler::SchedulerItem::cmp(const std::unique_ptr<SchedulerItem> &a, - const std::unique_ptr<SchedulerItem> &b) { +bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) // Optimize for common case: check low bits first when high bits are equal return (a->next_execution_high_ == b->next_execution_high_) ? (a->next_execution_low_ > b->next_execution_low_) @@ -877,7 +881,7 @@ bool HOT Scheduler::SchedulerItem::cmp(const std::unique_ptr<SchedulerItem> &a, // IMPORTANT: Caller must hold the scheduler lock before calling this function. // This protects scheduler_item_pool_ from concurrent access by other threads // that may be acquiring items from the pool in set_timer_common_(). -void Scheduler::recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item) { +void Scheduler::recycle_item_main_loop_(SchedulerItemPtr item) { if (!item) return; @@ -920,8 +924,8 @@ void Scheduler::debug_log_timer_(const SchedulerItem *item, NameType name_type, // Helper to get or create a scheduler item from the pool // IMPORTANT: Caller must hold the scheduler lock before calling this function. -std::unique_ptr<Scheduler::SchedulerItem> Scheduler::get_item_from_pool_locked_() { - std::unique_ptr<SchedulerItem> item; +Scheduler::SchedulerItemPtr Scheduler::get_item_from_pool_locked_() { + SchedulerItemPtr item; if (!this->scheduler_item_pool_.empty()) { item = std::move(this->scheduler_item_pool_.back()); this->scheduler_item_pool_.pop_back(); @@ -929,7 +933,7 @@ std::unique_ptr<Scheduler::SchedulerItem> Scheduler::get_item_from_pool_locked_( ESP_LOGD(TAG, "Reused item from pool (pool size now: %zu)", this->scheduler_item_pool_.size()); #endif } else { - item = make_unique<SchedulerItem>(); + item = SchedulerItemPtr(new SchedulerItem()); #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Allocated new item (pool empty)"); #endif diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index b6a8336606..840ee7159a 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -142,6 +142,19 @@ class Scheduler { }; protected: + struct SchedulerItem; + + // Custom deleter for SchedulerItem unique_ptr that prevents the compiler from + // inlining the destructor at every destruction site. On BK7231N (Thumb-1), GCC + // inlines ~unique_ptr<SchedulerItem> (~30 bytes: null check + ~std::function + + // operator delete) at every destruction site, while ESP32/ESP8266/RTL8720CF outline + // it into a single helper. This noinline deleter ensures only one copy exists. + // operator() is defined in scheduler.cpp to prevent inlining. + struct SchedulerItemDeleter { + void operator()(SchedulerItem *ptr) const noexcept; + }; + using SchedulerItemPtr = std::unique_ptr<SchedulerItem, SchedulerItemDeleter>; + struct SchedulerItem { // Ordered by size to minimize padding Component *component; @@ -233,7 +246,7 @@ class Scheduler { name_type_ = type; } - static bool cmp(const std::unique_ptr<SchedulerItem> &a, const std::unique_ptr<SchedulerItem> &b); + static bool cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b); // Note: We use 48 bits total (32 + 16), stored in a 64-bit value for API compatibility. // The upper 16 bits of the 64-bit value are always zero, which is fine since @@ -276,10 +289,10 @@ class Scheduler { size_t cleanup_(); // Remove and return the front item from the heap // IMPORTANT: Caller must hold the scheduler lock before calling this function. - std::unique_ptr<SchedulerItem> pop_raw_locked_(); + SchedulerItemPtr pop_raw_locked_(); // Get or create a scheduler item from the pool // IMPORTANT: Caller must hold the scheduler lock before calling this function. - std::unique_ptr<SchedulerItem> get_item_from_pool_locked_(); + SchedulerItemPtr get_item_from_pool_locked_(); private: // Helper to cancel items - must be called with lock held @@ -303,9 +316,9 @@ class Scheduler { // Helper function to check if item matches criteria for cancellation // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // IMPORTANT: Must be called with scheduler lock held - inline bool HOT matches_item_locked_(const std::unique_ptr<SchedulerItem> &item, Component *component, - NameType name_type, const char *static_name, uint32_t hash_or_id, - SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const { + inline bool HOT matches_item_locked_(const SchedulerItemPtr &item, Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, + bool match_retry, bool skip_removed = true) const { // THREAD SAFETY: Check for nullptr first to prevent LoadProhibited crashes. On multi-threaded // platforms, items can be moved out of defer_queue_ during processing, leaving nullptr entries. // PR #11305 added nullptr checks in callers (mark_matching_items_removed_locked_()), but this check @@ -340,7 +353,7 @@ class Scheduler { // IMPORTANT: Only call from main loop context! Recycling clears the callback, // so calling from another thread while the callback is executing causes use-after-free. // IMPORTANT: Caller must hold the scheduler lock before calling this function. - void recycle_item_main_loop_(std::unique_ptr<SchedulerItem> item); + void recycle_item_main_loop_(SchedulerItemPtr item); // Helper to perform full cleanup when too many items are cancelled void full_cleanup_removed_items_(); @@ -396,7 +409,7 @@ class Scheduler { // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), // recycle each item after re-acquiring the lock for the next iteration (N+1 total). // The lock is held across: recycle → loop condition → move-out, then released for execution. - std::unique_ptr<SchedulerItem> item; + SchedulerItemPtr item; this->lock_.lock(); while (this->defer_queue_front_ < defer_queue_end) { @@ -496,9 +509,10 @@ class Scheduler { // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal // IMPORTANT: Must be called with scheduler lock held - __attribute__((noinline)) size_t mark_matching_items_removed_locked_( - std::vector<std::unique_ptr<SchedulerItem>> &container, Component *component, NameType name_type, - const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { + __attribute__((noinline)) size_t mark_matching_items_removed_locked_(std::vector<SchedulerItemPtr> &container, + Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry) { size_t count = 0; for (auto &item : container) { // Skip nullptr items (can happen in defer_queue_ when items are being processed) @@ -514,15 +528,15 @@ class Scheduler { } Mutex lock_; - std::vector<std::unique_ptr<SchedulerItem>> items_; - std::vector<std::unique_ptr<SchedulerItem>> to_add_; + std::vector<SchedulerItemPtr> items_; + std::vector<SchedulerItemPtr> to_add_; #ifndef ESPHOME_THREAD_SINGLE // Single-core platforms don't need the defer queue and save ~32 bytes of RAM // Using std::vector instead of std::deque avoids 512-byte chunked allocations // Index tracking avoids O(n) erase() calls when draining the queue each loop - std::vector<std::unique_ptr<SchedulerItem>> defer_queue_; // FIFO queue for defer() calls - size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) -#endif /* ESPHOME_THREAD_SINGLE */ + std::vector<SchedulerItemPtr> defer_queue_; // FIFO queue for defer() calls + size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) +#endif /* ESPHOME_THREAD_SINGLE */ uint32_t to_remove_{0}; // Memory pool for recycling SchedulerItem objects to reduce heap churn. @@ -533,7 +547,7 @@ class Scheduler { // - The pool significantly reduces heap fragmentation which is critical because heap allocation/deallocation // can stall the entire system, causing timing issues and dropped events for any components that need // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) - std::vector<std::unique_ptr<SchedulerItem>> scheduler_item_pool_; + std::vector<SchedulerItemPtr> scheduler_item_pool_; #ifdef ESPHOME_THREAD_MULTI_ATOMICS /* From 3460a8c9225f504fdfdd9166d603fe2c3fb41474 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 18:44:50 -0600 Subject: [PATCH 0908/2030] [dlms_meter/kamstrup_kmp] Replace powf with pow10_int (#14125) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/dlms_meter/dlms_meter.cpp | 4 +--- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/esphome/components/dlms_meter/dlms_meter.cpp b/esphome/components/dlms_meter/dlms_meter.cpp index 11d05b3a08..bd2150e8dd 100644 --- a/esphome/components/dlms_meter/dlms_meter.cpp +++ b/esphome/components/dlms_meter/dlms_meter.cpp @@ -1,7 +1,5 @@ #include "dlms_meter.h" -#include <cmath> - #if defined(USE_ESP8266_FRAMEWORK_ARDUINO) #include <bearssl/bearssl.h> #elif defined(USE_ESP32) @@ -410,7 +408,7 @@ void DlmsMeterComponent::decode_obis_(uint8_t *plaintext, uint16_t message_lengt if (current_position + 1 < message_length) { int8_t scaler = static_cast<int8_t>(plaintext[current_position + 1]); if (scaler != 0) { - value *= powf(10.0f, scaler); + value *= pow10_int(scaler); } } diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp index 534939f9af..00c65a1937 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -222,11 +222,11 @@ void KamstrupKMPComponent::parse_command_message_(uint16_t command, const uint8_ } // Calculate exponent - float exponent = msg[6] & 0x3F; + int8_t exp_val = msg[6] & 0x3F; if (msg[6] & 0x40) { - exponent = -exponent; + exp_val = -exp_val; } - exponent = powf(10, exponent); + float exponent = pow10_int(exp_val); if (msg[6] & 0x80) { exponent = -exponent; } From 905e81330ee3af27a82f2f6cf3675497bd6fcc70 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:28:19 +1300 Subject: [PATCH 0909/2030] Don't get stuck forever on a failed component can_proceed (#14267) --- esphome/core/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 1cb7dc0075..6a7683a987 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -134,7 +134,7 @@ void Application::setup() { this->after_loop_tasks_(); this->app_state_ = new_app_state; yield(); - } while (!component->can_proceed()); + } while (!component->can_proceed() && !component->is_failed()); } ESP_LOGI(TAG, "setup() finished successfully!"); From 1dac501b049ffea5a1767df5dfbd429d768c0af2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 21:39:51 -0600 Subject: [PATCH 0910/2030] [light] Add additional light effect test cases (#14266) --- tests/components/light/common.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/components/light/common.yaml b/tests/components/light/common.yaml index 55525fc67f..e5fab62a79 100644 --- a/tests/components/light/common.yaml +++ b/tests/components/light/common.yaml @@ -71,6 +71,32 @@ esphome: - light.control: id: test_monochromatic_light state: on + # Test static effect name resolution at codegen time + - light.turn_on: + id: test_monochromatic_light + effect: Strobe + - light.turn_on: + id: test_monochromatic_light + effect: none + # Test resolving a different effect on the same light + - light.control: + id: test_monochromatic_light + effect: My Flicker + # Test effect: None (capitalized) + - light.control: + id: test_monochromatic_light + effect: None + # Test effect lambda with no args (on_boot has empty Ts...) + - light.turn_on: + id: test_monochromatic_light + effect: !lambda 'return "Strobe";' + # Test effect lambda with non-empty args (repeat passes uint32_t iteration) + - repeat: + count: 3 + then: + - light.turn_on: + id: test_monochromatic_light + effect: !lambda 'return iteration > 1 ? "Strobe" : "none";' - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% From 2e705a919fc8a4e9990e4fc5870e4677a05f6e46 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Feb 2026 23:26:00 -0500 Subject: [PATCH 0911/2030] [pid] Fix deadband threshold conversion for Fahrenheit (#14268) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/pid/climate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py index 5919d2cac8..5fa3166f9d 100644 --- a/esphome/components/pid/climate.py +++ b/esphome/components/pid/climate.py @@ -50,8 +50,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_HEAT_OUTPUT): cv.use_id(output.FloatOutput), cv.Optional(CONF_DEADBAND_PARAMETERS): cv.Schema( { - cv.Required(CONF_THRESHOLD_HIGH): cv.temperature, - cv.Required(CONF_THRESHOLD_LOW): cv.temperature, + cv.Required(CONF_THRESHOLD_HIGH): cv.temperature_delta, + cv.Required(CONF_THRESHOLD_LOW): cv.temperature_delta, cv.Optional(CONF_KP_MULTIPLIER, default=0.1): cv.float_, cv.Optional(CONF_KI_MULTIPLIER, default=0.0): cv.float_, cv.Optional(CONF_KD_MULTIPLIER, default=0.0): cv.float_, From b134c4679ca5f609633a2b97681a41867e62c12d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Feb 2026 22:33:57 -0600 Subject: [PATCH 0912/2030] [light] Replace std::lerp with lightweight lerp_fast in LightColorValues::lerp (#14238) --- .../components/light/light_color_values.cpp | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/esphome/components/light/light_color_values.cpp b/esphome/components/light/light_color_values.cpp index 2f22bb3c68..e54cc0a12a 100644 --- a/esphome/components/light/light_color_values.cpp +++ b/esphome/components/light/light_color_values.cpp @@ -1,27 +1,30 @@ #include "light_color_values.h" -#include <cmath> - namespace esphome::light { +// Lightweight lerp: a + t * (b - a). +// Avoids std::lerp's NaN/infinity handling which Clang doesn't optimize out, +// adding ~200 bytes per call. Safe because all values are finite floats. +static float __attribute__((noinline)) lerp_fast(float a, float b, float t) { return a + t * (b - a); } + LightColorValues LightColorValues::lerp(const LightColorValues &start, const LightColorValues &end, float completion) { // Directly interpolate the raw values to avoid getter/setter overhead. // This is safe because: - // - All LightColorValues have their values clamped when set via the setters - // - std::lerp guarantees output is in the same range as inputs + // - All LightColorValues except color_temperature_ have their values clamped when set via the setters + // - lerp_fast output stays in range when inputs are in range and 0 <= completion <= 1 // - Therefore the output doesn't need clamping, so we can skip the setters LightColorValues v; v.color_mode_ = end.color_mode_; - v.state_ = std::lerp(start.state_, end.state_, completion); - v.brightness_ = std::lerp(start.brightness_, end.brightness_, completion); - v.color_brightness_ = std::lerp(start.color_brightness_, end.color_brightness_, completion); - v.red_ = std::lerp(start.red_, end.red_, completion); - v.green_ = std::lerp(start.green_, end.green_, completion); - v.blue_ = std::lerp(start.blue_, end.blue_, completion); - v.white_ = std::lerp(start.white_, end.white_, completion); - v.color_temperature_ = std::lerp(start.color_temperature_, end.color_temperature_, completion); - v.cold_white_ = std::lerp(start.cold_white_, end.cold_white_, completion); - v.warm_white_ = std::lerp(start.warm_white_, end.warm_white_, completion); + v.state_ = lerp_fast(start.state_, end.state_, completion); + v.brightness_ = lerp_fast(start.brightness_, end.brightness_, completion); + v.color_brightness_ = lerp_fast(start.color_brightness_, end.color_brightness_, completion); + v.red_ = lerp_fast(start.red_, end.red_, completion); + v.green_ = lerp_fast(start.green_, end.green_, completion); + v.blue_ = lerp_fast(start.blue_, end.blue_, completion); + v.white_ = lerp_fast(start.white_, end.white_, completion); + v.color_temperature_ = lerp_fast(start.color_temperature_, end.color_temperature_, completion); + v.cold_white_ = lerp_fast(start.cold_white_, end.cold_white_, completion); + v.warm_white_ = lerp_fast(start.warm_white_, end.warm_white_, completion); return v; } From bb05cfb7119102b877ad583d9d9091ff57663a44 Mon Sep 17 00:00:00 2001 From: Big Mike <mikelawrence@users.noreply.github.com> Date: Wed, 25 Feb 2026 06:34:58 -0600 Subject: [PATCH 0913/2030] [sensirion_common] Move sen5x's sensirion_convert_to_string_in_place() function to sensirion_common (#14269) --- esphome/components/sen5x/sen5x.cpp | 9 --------- esphome/components/sensirion_common/i2c_sensirion.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index fc4932d867..09dda8bca4 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -56,15 +56,6 @@ static const LogString *rht_accel_mode_to_string(RhtAccelerationMode mode) { } } -// This function performs an in-place conversion of the provided buffer -// from uint16_t values to big endianness -static inline const char *sensirion_convert_to_string_in_place(uint16_t *array, size_t length) { - for (size_t i = 0; i < length; i++) { - array[i] = convert_big_endian(array[i]); - } - return reinterpret_cast<const char *>(array); -} - void SEN5XComponent::setup() { // the sensor needs 1000 ms to enter the idle state this->set_timeout(1000, [this]() { diff --git a/esphome/components/sensirion_common/i2c_sensirion.h b/esphome/components/sensirion_common/i2c_sensirion.h index f3eb3761f6..3c2c14ccb8 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.h +++ b/esphome/components/sensirion_common/i2c_sensirion.h @@ -21,6 +21,17 @@ class SensirionI2CDevice : public i2c::I2CDevice { public: enum CommandLen : uint8_t { ADDR_8_BIT = 1, ADDR_16_BIT = 2 }; + /** + * This function performs an in-place conversion of the provided buffer + * from uint16_t values to big endianness. Useful for Sensirion strings in SEN5X and SEN6X + */ + static inline const char *sensirion_convert_to_string_in_place(uint16_t *array, size_t length) { + for (size_t i = 0; i < length; i++) { + array[i] = convert_big_endian(array[i]); + } + return reinterpret_cast<const char *>(array); + } + /** Read data words from I2C device. * handles CRC check used by Sensirion sensors * @param data pointer to raw result From 228874a52b268070199dc37f4622cca1361e729b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:45:50 -0500 Subject: [PATCH 0914/2030] [config] Improve dimensions validation and fix online_image resize aspect ratio (#14274) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/runtime_image/runtime_image.cpp | 9 +++++++++ esphome/config_validation.py | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 603ea76f01..5a4a2ea7d6 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -2,6 +2,7 @@ #include "image_decoder.h" #include "esphome/core/log.h" #include "esphome/core/helpers.h" +#include <algorithm> #include <cstring> #ifdef USE_RUNTIME_IMAGE_BMP @@ -43,6 +44,14 @@ int RuntimeImage::resize(int width, int height) { int target_width = this->fixed_width_ ? this->fixed_width_ : width; int target_height = this->fixed_height_ ? this->fixed_height_ : height; + // When both fixed dimensions are set, scale uniformly to preserve aspect ratio + if (this->fixed_width_ && this->fixed_height_ && width > 0 && height > 0) { + float scale = + std::min(static_cast<float>(this->fixed_width_) / width, static_cast<float>(this->fixed_height_) / height); + target_width = static_cast<int>(width * scale); + target_height = static_cast<int>(height * scale); + } + size_t result = this->resize_buffer_(target_width, target_height); if (result > 0 && this->progressive_display_) { // Update display dimensions for progressive display diff --git a/esphome/config_validation.py b/esphome/config_validation.py index ef1c66a20e..3b0e4da298 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1640,7 +1640,10 @@ def dimensions(value): if width <= 0 or height <= 0: raise Invalid("Width and height must at least be 1") return [width, height] - value = string(value) + if not isinstance(value, str): + raise Invalid( + "Dimensions must be a string (WIDTHxHEIGHT). Got a number instead, try quoting the value." + ) match = re.match(r"\s*([0-9]+)\s*[xX]\s*([0-9]+)\s*", value) if not match: raise Invalid( From 1beeb9ab5c34b1b28ba3c8dc8e78cc12be511dc2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 09:54:32 -0600 Subject: [PATCH 0915/2030] [web_server] Fix uptime display overflow after ~24.8 days (#13739) --- esphome/components/web_server/web_server.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 682008c40e..e2f9c21331 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -385,6 +385,7 @@ json::SerializationBuffer<> WebServer::get_config_json() { #endif root[ESPHOME_F("log")] = this->expose_log_; root[ESPHOME_F("lang")] = "en"; + root[ESPHOME_F("uptime")] = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); return builder.serialize(); } @@ -411,7 +412,12 @@ void WebServer::setup() { // doesn't need defer functionality - if the queue is full, the client JS knows it's alive because it's clearly // getting a lot of events - this->set_interval(10000, [this]() { this->events_.try_send_nodefer("", "ping", millis(), 30000); }); + this->set_interval(10000, [this]() { + char buf[32]; + auto uptime = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); + buf_append_printf(buf, sizeof(buf), 0, "{\"uptime\":%u}", uptime); + this->events_.try_send_nodefer(buf, "ping", millis(), 30000); + }); } void WebServer::loop() { this->events_.loop(); } From 78ab63581b48575d04448e49d1ecc298627bce1a Mon Sep 17 00:00:00 2001 From: esphomebot <esphome@openhomefoundation.org> Date: Thu, 26 Feb 2026 05:09:45 +1300 Subject: [PATCH 0916/2030] Update webserver local assets to 20260225-155043 (#14275) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../components/captive_portal/captive_index.h | 4 +- .../components/web_server/server_index_v2.h | 2286 ++--- .../components/web_server/server_index_v3.h | 8037 +++++++++-------- 3 files changed, 5166 insertions(+), 5161 deletions(-) diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index a81edc1900..645ebb7a2f 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -6,7 +6,7 @@ namespace esphome::captive_portal { #ifdef USE_CAPTIVE_PORTAL_GZIP -constexpr uint8_t INDEX_GZ[] PROGMEM = { +const uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x95, 0x16, 0x6b, 0x8f, 0xdb, 0x36, 0xf2, 0x7b, 0x7e, 0x05, 0x8f, 0x49, 0xbb, 0x52, 0xb3, 0x7a, 0x7a, 0xed, 0x6c, 0x24, 0x51, 0x45, 0x9a, 0xbb, 0xa2, 0x05, 0x9a, 0x36, 0xc0, 0x6e, 0x73, 0x1f, 0x82, 0x00, 0x4b, 0x53, 0x23, 0x8b, 0x31, 0x45, 0xea, 0x48, 0xca, 0x8f, 0x18, 0xbe, 0xdf, @@ -86,7 +86,7 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0xfc, 0xda, 0xd1, 0xf8, 0xe9, 0xa3, 0xe1, 0xa6, 0xfb, 0x1f, 0x53, 0x58, 0x46, 0xb2, 0xf9, 0x0a, 0x00, 0x00}; #else // Brotli (default, smaller) -constexpr uint8_t INDEX_BR[] PROGMEM = { +const uint8_t INDEX_BR[] PROGMEM = { 0x1b, 0xf8, 0x0a, 0x00, 0x64, 0x5a, 0xd3, 0xfa, 0xe7, 0xf3, 0x62, 0xd8, 0x06, 0x1b, 0xe9, 0x6a, 0x8a, 0x81, 0x2b, 0xb5, 0x49, 0x14, 0x37, 0xdc, 0x9e, 0x1a, 0xcb, 0x56, 0x87, 0xfb, 0xff, 0xf7, 0x73, 0x75, 0x12, 0x0a, 0xd6, 0x48, 0x84, 0xc6, 0x21, 0xa4, 0x6d, 0xb5, 0x71, 0xef, 0x13, 0xbe, 0x4e, 0x54, 0xf1, 0x64, 0x8f, 0x3f, 0xcc, 0x9a, 0x78, diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index b5dac9ae4c..ffa9c87b3a 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -constexpr uint8_t INDEX_GZ[] PROGMEM = { +const uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdb, 0x48, 0xb6, 0xe0, 0xf3, 0xd4, 0x57, 0x40, 0x28, 0xb5, 0x8c, 0x2c, 0x26, 0xc1, 0x45, 0x92, 0x2d, 0x83, 0x4a, 0xb2, 0x65, 0xd9, 0xd5, 0x76, 0x97, 0xb7, 0xb6, 0xec, 0xda, 0x58, 0x6c, 0x09, 0x02, 0x92, 0x44, 0x96, 0x41, 0x80, 0x05, 0x24, 0xb5, 0x14, 0x89, @@ -41,10 +41,10 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x90, 0xe0, 0xbe, 0xe3, 0x24, 0x21, 0x7d, 0x18, 0xf1, 0x84, 0x3b, 0xb0, 0x8a, 0xe9, 0xd8, 0x4a, 0x08, 0xb1, 0x73, 0xd1, 0xd6, 0x1e, 0x24, 0x5e, 0xd2, 0xb0, 0x6d, 0x2c, 0xa1, 0xc4, 0x09, 0x47, 0xf8, 0x23, 0x71, 0x12, 0xec, 0xba, 0x2e, 0x47, 0xa4, 0xbf, 0xd0, 0x58, 0x49, 0x8c, 0x79, 0x0e, 0x92, 0x61, 0x7b, 0xe4, 0x71, 0x37, 0xa3, 0xe1, 0x3c, - 0xa0, 0x8e, 0xc3, 0x70, 0x8e, 0x53, 0x44, 0xfa, 0xac, 0xe1, 0x64, 0xa4, 0x0f, 0xcb, 0x9d, 0xd5, 0xd7, 0x9a, 0x90, - 0x9d, 0x36, 0x52, 0x30, 0x66, 0x1a, 0x40, 0xc0, 0xb0, 0x82, 0x27, 0x23, 0xc4, 0x4e, 0xe6, 0xd3, 0x4b, 0x9a, 0xd9, + 0xa0, 0x8e, 0xc3, 0x70, 0x8e, 0x33, 0x44, 0xfa, 0xac, 0xe1, 0xa4, 0xa4, 0x0f, 0xcb, 0x9d, 0xd6, 0xd7, 0x9a, 0x90, + 0x9d, 0x36, 0x52, 0x30, 0xa6, 0x1a, 0x40, 0xc0, 0xb0, 0x82, 0x27, 0x25, 0xc4, 0x4e, 0xe6, 0xd3, 0x4b, 0x9a, 0xd9, 0x65, 0xb5, 0x5e, 0x8d, 0x2c, 0xe6, 0x39, 0xb5, 0x82, 0x3c, 0xb7, 0xc6, 0xf3, 0x24, 0xe0, 0x2c, 0x4d, 0x2c, 0xbb, - 0x91, 0x35, 0x6c, 0x49, 0x0e, 0x25, 0x35, 0xd8, 0xa8, 0x40, 0x4e, 0x8e, 0x1a, 0xc9, 0x30, 0x6d, 0x74, 0x46, 0x18, + 0x91, 0x36, 0x6c, 0x49, 0x0e, 0x25, 0x35, 0xd8, 0xa8, 0x40, 0x4e, 0x8e, 0x1a, 0xc9, 0x30, 0x6b, 0x74, 0x46, 0x18, 0xa0, 0x44, 0x3d, 0xd5, 0x9f, 0x42, 0x00, 0xc5, 0x09, 0xcc, 0xb1, 0xc0, 0x4f, 0x38, 0xcc, 0x52, 0x4c, 0x31, 0xe7, 0x83, 0xc4, 0x5d, 0xdf, 0x28, 0x84, 0xbb, 0x53, 0x7f, 0xe6, 0x50, 0xd2, 0xa7, 0x82, 0xb8, 0xfc, 0x24, 0x00, 0x58, 0x6b, 0xeb, 0x36, 0xa0, 0x1e, 0x75, 0x2b, 0x92, 0x42, 0x1e, 0x77, 0xc7, 0x69, 0xf6, 0xcc, 0x0f, 0x22, 0x68, 0x57, @@ -85,8 +85,8 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x12, 0x0d, 0x1c, 0x44, 0x95, 0xd0, 0x39, 0xec, 0x81, 0xd6, 0x3d, 0x3c, 0xfb, 0xfc, 0xdc, 0x6e, 0x70, 0xac, 0xd0, 0x30, 0xa1, 0x7a, 0xe8, 0xdb, 0xa7, 0x54, 0x6a, 0x57, 0x42, 0xf7, 0x58, 0xc3, 0x8c, 0xdc, 0x41, 0x6e, 0x48, 0xc7, 0x2c, 0x31, 0xa6, 0x5d, 0x03, 0x09, 0x73, 0x9c, 0xa3, 0xc2, 0x58, 0xd0, 0x8d, 0x5d, 0x0b, 0xb5, 0x46, 0xae, 0xdc, - 0x62, 0x22, 0x54, 0x09, 0x63, 0x19, 0x87, 0x74, 0x54, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x54, 0x00, 0x3a, 0xe4, 0xa3, - 0x9e, 0x7a, 0x4f, 0x72, 0x89, 0xb9, 0x8c, 0xfe, 0x32, 0xa7, 0x39, 0x97, 0x74, 0xec, 0x70, 0x9c, 0x62, 0x06, 0xfc, + 0x62, 0x22, 0x54, 0x09, 0x63, 0x19, 0x87, 0x74, 0x54, 0x60, 0x81, 0x7a, 0x3d, 0x9b, 0x4c, 0x00, 0x3a, 0xe4, 0xa3, + 0x9e, 0x7a, 0x4f, 0x72, 0x89, 0xb9, 0x8c, 0xfe, 0x32, 0xa7, 0x39, 0x97, 0x74, 0xec, 0x70, 0x9c, 0x61, 0x06, 0xfc, 0x3a, 0x4d, 0xc6, 0x6c, 0x32, 0xcf, 0x40, 0xe3, 0x81, 0xcd, 0x48, 0x93, 0xf9, 0x94, 0xea, 0xa7, 0x4d, 0xb0, 0xbd, 0x99, 0x81, 0x4c, 0xcc, 0x81, 0xa6, 0xef, 0x26, 0x27, 0x80, 0x95, 0xa3, 0xe5, 0xf2, 0xaf, 0xba, 0x93, 0x6a, 0x29, 0x4b, 0x2d, 0x6d, 0x65, 0x4d, 0x28, 0x47, 0x4a, 0x26, 0xef, 0x74, 0x14, 0xf8, 0x7c, 0x44, 0x76, 0xda, 0x25, 0x0d, @@ -120,15 +120,15 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x11, 0x53, 0x33, 0x73, 0x80, 0x0b, 0x7c, 0x92, 0xe2, 0x34, 0x3f, 0x50, 0x74, 0x07, 0x06, 0x47, 0xb1, 0x02, 0x08, 0x47, 0x8b, 0x22, 0x64, 0xf9, 0x76, 0x0c, 0xfc, 0x21, 0x50, 0x3e, 0x35, 0x46, 0xb8, 0x2f, 0xa0, 0x25, 0x8f, 0x53, 0x5a, 0x73, 0x09, 0x99, 0xd2, 0x27, 0x34, 0xa3, 0xf9, 0x06, 0x74, 0x17, 0x41, 0xef, 0x6f, 0xe4, 0x2b, 0xd0, 0xca, - 0x00, 0x8a, 0xbc, 0x67, 0xaa, 0x13, 0x35, 0x0a, 0x50, 0x3c, 0x95, 0x09, 0x91, 0x9b, 0xd6, 0x2c, 0x48, 0xa5, 0xb1, - 0x4b, 0x23, 0x5c, 0xb1, 0xdc, 0x8c, 0x38, 0x8e, 0x93, 0x83, 0x11, 0xa7, 0x75, 0xfb, 0x6a, 0x12, 0xf9, 0xda, 0x24, + 0x00, 0x8a, 0xbc, 0x67, 0xaa, 0x13, 0x35, 0x0a, 0x50, 0x3c, 0x95, 0x09, 0x91, 0x9b, 0xd5, 0x2c, 0x48, 0xa5, 0xb1, + 0x4b, 0x23, 0x5c, 0xb1, 0xdc, 0x94, 0x38, 0x8e, 0x93, 0x83, 0x11, 0xa7, 0x75, 0xfb, 0x6a, 0x12, 0xf9, 0xda, 0x24, 0x72, 0xd7, 0x30, 0xb4, 0x50, 0x45, 0xcb, 0x46, 0x73, 0x8f, 0x73, 0x64, 0xd6, 0x02, 0x7d, 0xd5, 0x05, 0x06, 0x8d, - 0x4a, 0x7e, 0x1b, 0x13, 0x8e, 0x33, 0x65, 0xe5, 0x28, 0x52, 0x03, 0x8e, 0x51, 0x35, 0x49, 0x91, 0xdc, 0x1b, 0x35, - 0x93, 0x37, 0xc5, 0x19, 0x5a, 0x51, 0xee, 0x8b, 0x42, 0x21, 0x89, 0x22, 0xb5, 0x38, 0x35, 0xad, 0xd8, 0x40, 0x0b, - 0x4e, 0x89, 0xd2, 0x84, 0xa5, 0xe2, 0xb3, 0x8a, 0x9c, 0xb2, 0xdf, 0x1d, 0x42, 0xd2, 0x0a, 0x37, 0x35, 0x95, 0x52, - 0xeb, 0x56, 0x29, 0xc2, 0x91, 0x56, 0x4a, 0xb3, 0x6a, 0xe2, 0x84, 0xd8, 0xda, 0x27, 0x61, 0x0f, 0x16, 0x35, 0xbb, - 0xd0, 0x33, 0xaa, 0x15, 0x1e, 0xf0, 0xd4, 0x6c, 0x13, 0xbe, 0x37, 0x11, 0x4d, 0xad, 0x1f, 0x03, 0xe3, 0x59, 0x0d, - 0xe3, 0x06, 0x6a, 0x53, 0xc9, 0xbb, 0xd2, 0x11, 0x89, 0xea, 0x8d, 0x1d, 0x8a, 0x33, 0xb9, 0x10, 0x6b, 0x58, 0x5c, + 0x4a, 0x7e, 0x1b, 0x13, 0x8e, 0x53, 0x65, 0xe5, 0x28, 0x52, 0x03, 0x8e, 0x51, 0x35, 0xc9, 0x90, 0xdc, 0x1b, 0x35, + 0x93, 0x37, 0xc3, 0x29, 0x5a, 0x51, 0xee, 0x8b, 0x42, 0x21, 0x89, 0x22, 0xb5, 0x38, 0x35, 0xad, 0xd8, 0x40, 0x0b, + 0xce, 0x88, 0xd2, 0x84, 0xa5, 0xe2, 0xb3, 0x8a, 0x9c, 0xb2, 0xdf, 0x1d, 0x42, 0xb2, 0x0a, 0x37, 0x35, 0x95, 0x52, + 0xeb, 0x56, 0x19, 0xc2, 0x91, 0x56, 0x4a, 0xd3, 0x6a, 0xe2, 0x84, 0xd8, 0xda, 0x27, 0x61, 0x0f, 0x16, 0x35, 0xbb, + 0xd0, 0x33, 0xaa, 0x15, 0x1e, 0xf0, 0xd4, 0x74, 0x13, 0xbe, 0x37, 0x11, 0x4d, 0xad, 0x1f, 0x03, 0xe3, 0x69, 0x0d, + 0xe3, 0x06, 0x6a, 0x33, 0xc9, 0xbb, 0xb2, 0x11, 0x89, 0xea, 0x8d, 0x1d, 0x8a, 0x53, 0xb9, 0x10, 0x6b, 0x58, 0x5c, 0x55, 0x3e, 0x05, 0x11, 0x82, 0x19, 0x9b, 0x83, 0x7a, 0x67, 0x4a, 0x08, 0x07, 0x80, 0x67, 0xcb, 0xe5, 0x1a, 0xd9, 0x6d, 0xd4, 0x41, 0x91, 0x5b, 0x59, 0x86, 0xcb, 0xe5, 0x33, 0x8e, 0x1c, 0xa5, 0xfd, 0x62, 0x8a, 0x06, 0x9a, 0xe7, 0x9e, 0xbc, 0x84, 0x5a, 0x42, 0x19, 0xad, 0x4a, 0x4a, 0xb3, 0xa1, 0x4e, 0xb5, 0xf5, 0x85, 0xe2, 0x06, 0xe3, 0x3e, @@ -141,7 +141,7 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x65, 0x01, 0xf4, 0x56, 0x0c, 0xef, 0xca, 0x64, 0xaf, 0x09, 0xd3, 0x52, 0xfe, 0x4a, 0xb7, 0xa0, 0xa6, 0xcc, 0xdc, 0x34, 0xf1, 0x95, 0x4f, 0xb5, 0x27, 0xdd, 0x26, 0x3b, 0x9d, 0x5e, 0x69, 0xf7, 0x69, 0x6a, 0xe8, 0x49, 0xf7, 0x86, 0x12, 0xaa, 0xe9, 0x3c, 0x0e, 0x15, 0xb0, 0x0c, 0x61, 0xaa, 0xe8, 0xe8, 0x9a, 0xc5, 0x71, 0x55, 0xfa, 0x39, 0x9c, - 0x3d, 0x57, 0x9c, 0x3d, 0xd5, 0x9c, 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd9, 0x5d, 0xd5, 0x3c, 0x5d, 0xdb, 0x9e, 0xa9, + 0x3d, 0x57, 0x9c, 0x3d, 0xd3, 0x9c, 0x1d, 0x58, 0x05, 0x70, 0x76, 0xd9, 0x5d, 0xd5, 0x3c, 0x5b, 0xdb, 0x9e, 0x99, 0xe4, 0xe9, 0xb9, 0xb0, 0xa5, 0x61, 0xbc, 0xb9, 0x86, 0x00, 0x95, 0xba, 0xd7, 0x47, 0x47, 0xb9, 0x62, 0xc0, 0x08, 0x94, 0x9e, 0x4c, 0x6a, 0xba, 0x29, 0x3e, 0x3a, 0x08, 0xe7, 0x05, 0x2d, 0x29, 0xfb, 0xe4, 0x19, 0xf8, 0xea, 0x8c, 0xe9, 0x80, 0x18, 0x13, 0xc5, 0x9f, 0xa5, 0x46, 0xe9, 0xd9, 0x31, 0x35, 0xbb, 0x5c, 0xcf, 0x0e, 0x78, 0x7d, 0x35, @@ -181,1135 +181,1137 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x19, 0xb3, 0x7a, 0xcb, 0x65, 0xa8, 0x00, 0xa4, 0x6c, 0xdd, 0x1d, 0x03, 0x2b, 0xbe, 0x93, 0xac, 0xf9, 0xac, 0x32, 0xff, 0xda, 0x46, 0xf5, 0xf8, 0x28, 0x4b, 0xae, 0xfc, 0x98, 0x85, 0x16, 0xa7, 0xd3, 0x59, 0xec, 0x73, 0x6a, 0xa9, 0xf9, 0x5a, 0x3e, 0x74, 0x64, 0x97, 0x3a, 0xc3, 0xcc, 0xb0, 0x39, 0x67, 0x3a, 0xf0, 0x04, 0x7b, 0xc5, 0x81, 0x28, - 0x95, 0xd2, 0x3b, 0x9e, 0x56, 0x41, 0xb0, 0xd5, 0x38, 0x5f, 0xb3, 0x03, 0xbe, 0xb0, 0x91, 0x90, 0xcf, 0x39, 0x86, - 0xa0, 0x25, 0x21, 0xdd, 0x81, 0x7d, 0x9c, 0x5f, 0x4d, 0xfa, 0x36, 0xc4, 0x68, 0x32, 0xf2, 0x41, 0xb8, 0x86, 0xa0, - 0x42, 0x44, 0xda, 0xbd, 0xe8, 0x98, 0xf6, 0xa2, 0x46, 0x43, 0x6b, 0xd1, 0x3e, 0x49, 0x86, 0x91, 0x6c, 0x1e, 0xe0, - 0x10, 0xcf, 0x49, 0xb3, 0x83, 0x67, 0xa4, 0x2d, 0x9a, 0xf4, 0x66, 0xc7, 0xbe, 0x1a, 0x66, 0x6f, 0xcf, 0xc9, 0xdc, - 0xd8, 0xcf, 0xf9, 0x0b, 0xb0, 0xf7, 0xc9, 0x0c, 0x87, 0x24, 0x73, 0xe9, 0x0d, 0x0d, 0x1c, 0x1f, 0xe1, 0x50, 0x71, - 0x1a, 0xd4, 0x43, 0x33, 0x62, 0x54, 0x03, 0x33, 0x82, 0x7c, 0x18, 0x84, 0xc3, 0xce, 0x88, 0x10, 0x62, 0xef, 0x34, - 0x9b, 0xf6, 0x20, 0x23, 0x13, 0xee, 0x41, 0x89, 0xa1, 0x2c, 0x93, 0x29, 0x14, 0x75, 0x8d, 0x22, 0xe7, 0x0d, 0x77, - 0x39, 0xcd, 0xb9, 0x03, 0xc5, 0xe0, 0x01, 0xc8, 0x35, 0x61, 0xdb, 0xc7, 0x2d, 0xbb, 0x01, 0xa5, 0x82, 0x38, 0x11, - 0xce, 0xc8, 0x35, 0xf2, 0xc2, 0xe1, 0xfe, 0xc8, 0x14, 0x00, 0xa2, 0x10, 0x06, 0xbf, 0x1e, 0x84, 0xc3, 0xb6, 0x18, - 0xbc, 0x6f, 0x0f, 0x9c, 0x8c, 0xe4, 0x52, 0x43, 0x1b, 0xe4, 0xde, 0x07, 0x31, 0x55, 0xe4, 0x29, 0xe0, 0xd4, 0xb8, - 0x73, 0xd2, 0xec, 0x7a, 0xce, 0xdc, 0x9c, 0x44, 0x13, 0x06, 0x53, 0x58, 0xc0, 0x01, 0x81, 0xfa, 0x38, 0x23, 0x30, - 0x62, 0xd5, 0xec, 0xda, 0x53, 0xcf, 0x0f, 0xec, 0x07, 0x83, 0x73, 0xee, 0x8d, 0xb9, 0x1c, 0xfe, 0x9c, 0x2f, 0x97, - 0xf0, 0xef, 0x98, 0x0f, 0x32, 0x72, 0x2d, 0x8a, 0x26, 0xaa, 0x68, 0x0a, 0x45, 0x1f, 0x3c, 0x00, 0x15, 0xe7, 0xa5, - 0x96, 0x25, 0xd7, 0x64, 0x4a, 0x04, 0xec, 0x7b, 0x7b, 0xc9, 0x30, 0x6a, 0x74, 0x46, 0xe0, 0xe4, 0xcf, 0x78, 0xfe, - 0x1d, 0xe3, 0x91, 0x63, 0xb7, 0xfa, 0x36, 0x1a, 0xd8, 0x16, 0x2c, 0x6d, 0x2f, 0x6d, 0x10, 0x89, 0x61, 0xbf, 0xf1, - 0x8a, 0x7b, 0xf3, 0x3e, 0x69, 0x0f, 0x1c, 0xa6, 0x5c, 0x7a, 0x08, 0xfb, 0x8a, 0x71, 0xb6, 0xf1, 0x1c, 0x35, 0x18, - 0x6f, 0xe8, 0xe7, 0x39, 0x6a, 0xdc, 0x36, 0xa6, 0xc8, 0xf3, 0x1b, 0xb7, 0x0d, 0x67, 0x4e, 0x08, 0x69, 0x76, 0xcb, - 0x66, 0x5a, 0xfc, 0x45, 0xc8, 0x9b, 0x6a, 0x7f, 0xe7, 0x50, 0x6c, 0x87, 0xb4, 0xe1, 0x24, 0x43, 0x3a, 0x5a, 0x2e, - 0xed, 0xe3, 0x41, 0xdf, 0x46, 0x0d, 0x47, 0x13, 0x5a, 0x4b, 0x53, 0x1a, 0x42, 0x98, 0x8d, 0x0a, 0x15, 0x4f, 0x7a, - 0x52, 0x8b, 0x1d, 0x2d, 0xaa, 0xcd, 0x6e, 0xf0, 0x00, 0x5a, 0x94, 0x86, 0x8c, 0x54, 0x58, 0x67, 0x30, 0x4d, 0x4d, - 0xcc, 0x29, 0x69, 0xe3, 0x8c, 0x68, 0xf7, 0x75, 0x44, 0x78, 0x45, 0xf0, 0x3e, 0xa9, 0xaa, 0xe3, 0x61, 0x80, 0xc3, - 0x11, 0x79, 0x2a, 0x0d, 0x92, 0x9e, 0x76, 0x8e, 0xd3, 0x98, 0x3c, 0x59, 0x89, 0xe2, 0x06, 0x10, 0x60, 0xb9, 0x71, - 0x83, 0x79, 0x96, 0xd1, 0x84, 0xbf, 0x4e, 0x43, 0xa5, 0xa7, 0xd1, 0x18, 0x4c, 0x25, 0x08, 0xcf, 0x62, 0x50, 0xd2, - 0xba, 0x7a, 0x67, 0xcc, 0xd7, 0x5e, 0xcf, 0xc8, 0x5c, 0xea, 0x4f, 0x22, 0x68, 0xdb, 0x9b, 0x29, 0xcb, 0xd8, 0x41, - 0x78, 0xae, 0xa2, 0xb9, 0x8e, 0xeb, 0xba, 0x33, 0x37, 0x80, 0xd7, 0x30, 0x40, 0x8e, 0x0a, 0xb1, 0x8f, 0x9c, 0x9c, - 0xdc, 0xb8, 0x09, 0xbd, 0x11, 0xa3, 0x3a, 0xa8, 0x92, 0xcc, 0x7a, 0x7b, 0x1d, 0x47, 0x3d, 0xc1, 0x6e, 0x72, 0x37, - 0x49, 0x43, 0x0a, 0xe8, 0x81, 0xf8, 0xbd, 0x2a, 0x8a, 0xfc, 0xdc, 0x0c, 0x52, 0x55, 0xf0, 0x0d, 0x4d, 0xff, 0xf5, - 0x0c, 0x9c, 0xbe, 0x42, 0xd9, 0x2a, 0x2b, 0x4b, 0x4f, 0x38, 0x42, 0x6c, 0xec, 0xcc, 0x5c, 0x08, 0xee, 0x09, 0x12, - 0x62, 0x60, 0xcb, 0xcd, 0x4c, 0xa2, 0xba, 0x2d, 0xfb, 0x9c, 0x92, 0x70, 0x98, 0x35, 0x1a, 0xc2, 0x11, 0x3d, 0x97, - 0x24, 0x31, 0x43, 0x78, 0x5a, 0xee, 0x2d, 0x5d, 0xef, 0x2d, 0xa9, 0x8f, 0xe4, 0x4c, 0xeb, 0x0e, 0xdd, 0x06, 0xe3, - 0x48, 0xf8, 0x0a, 0xb9, 0x73, 0x8b, 0xf0, 0x98, 0xb4, 0x9c, 0xa1, 0x3b, 0xf8, 0xf3, 0x08, 0x0d, 0x1c, 0xf7, 0x2b, - 0xd4, 0x92, 0x8c, 0x63, 0x8a, 0x7a, 0xbe, 0x1c, 0x62, 0x21, 0xa2, 0x98, 0x1d, 0x2c, 0x7c, 0x89, 0x5e, 0x8a, 0x13, - 0x7f, 0x4a, 0xbd, 0x31, 0xec, 0x71, 0x4d, 0x37, 0x6f, 0x31, 0xd0, 0x91, 0x37, 0x56, 0x9c, 0xc4, 0xb5, 0x07, 0xbf, - 0xf0, 0xf2, 0x69, 0x60, 0x0f, 0xbe, 0xae, 0x9e, 0xfe, 0x6c, 0x0f, 0xbe, 0xe5, 0xde, 0xb7, 0x85, 0x72, 0x77, 0xd7, - 0x86, 0x78, 0xa8, 0x87, 0x28, 0xe4, 0xc2, 0x18, 0x98, 0x9b, 0xa3, 0x75, 0x47, 0xc7, 0x0c, 0x15, 0x6c, 0x5c, 0xb2, - 0xa2, 0xdc, 0xe5, 0xfe, 0x04, 0x50, 0x6a, 0xac, 0x40, 0x6e, 0x46, 0xf7, 0xab, 0x09, 0x03, 0xa1, 0x68, 0x6a, 0x05, - 0x54, 0xce, 0xfa, 0x6d, 0xb4, 0xa8, 0xd5, 0x15, 0x1a, 0x53, 0x3d, 0x9a, 0x5e, 0x72, 0xe9, 0x29, 0x69, 0xf7, 0xa6, - 0xc7, 0xb3, 0xde, 0xb4, 0xd1, 0x40, 0xb9, 0x26, 0xac, 0xf9, 0x70, 0x3a, 0xc2, 0xaf, 0xc1, 0xab, 0x67, 0x52, 0x12, - 0xae, 0x4d, 0xaf, 0xab, 0xa6, 0xd7, 0x68, 0xa4, 0x05, 0xea, 0x19, 0x4d, 0x67, 0xb2, 0x69, 0x51, 0x48, 0x9c, 0xac, - 0x12, 0xda, 0x11, 0x12, 0x25, 0x90, 0x12, 0x45, 0x08, 0x39, 0xe3, 0x68, 0x63, 0xaf, 0xd0, 0x27, 0x34, 0x17, 0x3b, - 0x16, 0x98, 0xa7, 0x94, 0x11, 0x0e, 0x60, 0x01, 0x9a, 0x96, 0xae, 0xe0, 0x5b, 0x3c, 0x6f, 0x74, 0x04, 0x91, 0x37, - 0x3b, 0xbd, 0x7a, 0x5f, 0x8f, 0xaa, 0xbe, 0xf0, 0xbc, 0x41, 0x6e, 0x4b, 0x2c, 0x15, 0x69, 0xa3, 0x51, 0xd4, 0xe3, - 0x9d, 0x7a, 0xdf, 0xd6, 0x22, 0x10, 0x27, 0xab, 0xa9, 0x19, 0x5a, 0xbe, 0x56, 0x12, 0x95, 0xb9, 0x2c, 0x49, 0x68, - 0x06, 0x32, 0x94, 0x70, 0xcc, 0x8a, 0xa2, 0x94, 0xeb, 0x6f, 0x40, 0x88, 0x62, 0x4a, 0x12, 0xe0, 0x3b, 0xc2, 0xec, - 0xc2, 0x29, 0xce, 0x70, 0x24, 0xb8, 0x06, 0x21, 0xe4, 0x54, 0x27, 0xb5, 0x70, 0xc1, 0x81, 0x7c, 0xc2, 0x0c, 0x89, - 0x94, 0x13, 0xea, 0x9e, 0xef, 0x9e, 0xa6, 0x77, 0x9a, 0x64, 0x43, 0x36, 0xf2, 0x44, 0xb5, 0x58, 0xf1, 0xad, 0x80, - 0xbc, 0x73, 0x38, 0x2a, 0xc3, 0x23, 0xae, 0x60, 0x7f, 0x4f, 0x59, 0x46, 0x85, 0x06, 0xbe, 0xab, 0xcd, 0x3e, 0xbf, - 0xae, 0x3e, 0xfa, 0xa6, 0xf3, 0x06, 0x10, 0x19, 0x80, 0x6f, 0x27, 0x25, 0x6b, 0xd5, 0xce, 0x77, 0x4f, 0xde, 0x6c, - 0x32, 0x81, 0x97, 0x4b, 0x65, 0xfc, 0xfa, 0xa0, 0xd9, 0xe0, 0xa0, 0x82, 0xd4, 0x57, 0x3f, 0x3c, 0xc7, 0x17, 0x0a, - 0x52, 0xe0, 0x24, 0x40, 0x45, 0xe7, 0xbb, 0x27, 0xef, 0x9d, 0x44, 0xb8, 0x96, 0x10, 0x36, 0xa7, 0xed, 0x64, 0xc4, - 0x89, 0x08, 0x45, 0x72, 0xee, 0x25, 0xe3, 0xca, 0x0c, 0xf1, 0xed, 0x45, 0xe2, 0x25, 0xd8, 0x0f, 0x43, 0x36, 0x22, - 0xbe, 0xc2, 0x00, 0xf1, 0x11, 0xf6, 0x6b, 0x66, 0x19, 0x81, 0x05, 0x10, 0x63, 0x9d, 0xc1, 0x4a, 0xb8, 0x52, 0xf1, - 0x43, 0xd8, 0x17, 0xa3, 0xf2, 0x42, 0x8a, 0x8e, 0x9f, 0xd7, 0x72, 0xd3, 0x2a, 0x6b, 0xf4, 0x5b, 0xb0, 0x9c, 0xf4, - 0xc3, 0x6b, 0xd5, 0x75, 0x59, 0xf0, 0x54, 0x27, 0x91, 0x9d, 0xef, 0x9e, 0xbc, 0x52, 0x79, 0x64, 0x33, 0x5f, 0x73, - 0xfb, 0x35, 0x0b, 0xf3, 0xe4, 0x95, 0x5b, 0xbd, 0x15, 0x95, 0xcf, 0x77, 0x4f, 0x3e, 0x6c, 0xaa, 0x06, 0xe5, 0xc5, - 0xbc, 0x32, 0xf1, 0x05, 0x7c, 0x0b, 0x1a, 0x7b, 0x0b, 0x25, 0x1a, 0x3c, 0x56, 0x60, 0x21, 0x8e, 0xbc, 0xbc, 0x28, - 0x3d, 0x23, 0x4f, 0x71, 0x4a, 0x44, 0x1c, 0xa8, 0xbe, 0x6a, 0x4a, 0xc9, 0x63, 0x69, 0x72, 0x16, 0xa4, 0x33, 0xba, - 0x25, 0x38, 0x74, 0x82, 0x5c, 0x36, 0x85, 0x04, 0x1a, 0x01, 0x3a, 0xc3, 0x3b, 0x6d, 0xd4, 0xab, 0x0b, 0xaf, 0x54, - 0x10, 0x69, 0x56, 0x93, 0x2c, 0x38, 0x22, 0x6d, 0xec, 0x93, 0x36, 0x0e, 0x48, 0x3e, 0x6c, 0x4b, 0xf1, 0xd0, 0x0b, - 0xca, 0x7e, 0xa5, 0x90, 0x81, 0xdc, 0xb0, 0x40, 0xee, 0x56, 0x29, 0x7e, 0xc3, 0x5e, 0x20, 0x5c, 0x8f, 0x42, 0xa2, - 0x87, 0xd2, 0x68, 0x75, 0x32, 0x9c, 0x89, 0x8e, 0xcf, 0xd8, 0x65, 0x0c, 0xd9, 0x25, 0x30, 0x2b, 0xcc, 0x91, 0x57, - 0x56, 0xed, 0xa8, 0xaa, 0x81, 0x2b, 0xd6, 0x29, 0xc3, 0x81, 0x0b, 0x8c, 0x1b, 0x07, 0x2a, 0x19, 0x27, 0x5f, 0x6f, - 0xf2, 0x70, 0x6f, 0xcf, 0x91, 0x8d, 0xbe, 0xe3, 0x4e, 0xa6, 0xdf, 0x57, 0xa1, 0xbb, 0x6f, 0x25, 0xaf, 0x08, 0x91, - 0x80, 0xbf, 0xd1, 0xf0, 0x47, 0x05, 0xc4, 0xa1, 0x9d, 0xa0, 0x8e, 0x41, 0x0d, 0xbc, 0xd0, 0xf4, 0xea, 0xd3, 0x6f, - 0x34, 0xca, 0x30, 0x6d, 0x1d, 0x5b, 0x27, 0x38, 0x2d, 0xae, 0x9c, 0x32, 0xff, 0xa7, 0xbd, 0x96, 0x35, 0xa5, 0x41, - 0x40, 0xcc, 0xa4, 0x59, 0xa6, 0x27, 0x63, 0x6c, 0x09, 0x06, 0xf5, 0x5e, 0xa8, 0xc4, 0x05, 0x2c, 0x72, 0xac, 0x54, - 0x25, 0xcd, 0xce, 0xba, 0xc8, 0xd3, 0x95, 0x20, 0x2c, 0x05, 0x95, 0x1a, 0x85, 0x22, 0xef, 0x57, 0xeb, 0x99, 0x97, - 0x38, 0x47, 0xca, 0xc7, 0x25, 0xa0, 0x10, 0xc8, 0xea, 0x96, 0x48, 0x79, 0x4e, 0x26, 0xdb, 0x49, 0xfe, 0xc4, 0x20, - 0xf9, 0x27, 0x84, 0x1a, 0xe4, 0x2f, 0x3d, 0x1c, 0x6e, 0xaa, 0x5c, 0x0b, 0xb9, 0x7e, 0x75, 0x3a, 0x23, 0xe0, 0x43, - 0xab, 0x63, 0xb4, 0x16, 0x57, 0xdc, 0xc2, 0x50, 0xcc, 0x1d, 0x22, 0xbc, 0x90, 0x58, 0x07, 0x81, 0x9d, 0x2a, 0xaa, - 0x06, 0x43, 0x6f, 0x72, 0xe9, 0x99, 0x1c, 0xf0, 0xe4, 0xc3, 0xdd, 0x01, 0xd1, 0xd3, 0xd9, 0xfa, 0xce, 0x35, 0x32, - 0x40, 0x61, 0xd6, 0xc6, 0xc6, 0xad, 0xe7, 0x83, 0xc2, 0xf8, 0x65, 0x20, 0xbb, 0xce, 0x7c, 0x56, 0x36, 0xa1, 0x96, - 0x7f, 0x00, 0x6d, 0xa7, 0x23, 0x6a, 0x50, 0xa3, 0x5b, 0xe0, 0x47, 0x32, 0x0f, 0xd5, 0xcf, 0xb6, 0xb0, 0x8f, 0x13, - 0x51, 0x81, 0x26, 0xe1, 0xe6, 0xd7, 0x4f, 0x0a, 0x45, 0x26, 0x12, 0x34, 0xb4, 0x00, 0xfe, 0x27, 0x49, 0x1e, 0xe8, - 0x46, 0xc8, 0x05, 0x40, 0xd0, 0x44, 0xe0, 0xa9, 0x42, 0x98, 0x6d, 0x57, 0xce, 0xf7, 0xe7, 0x3b, 0x84, 0x4c, 0x2a, - 0xe7, 0xe3, 0xbb, 0x2a, 0xfb, 0x0a, 0xc8, 0x02, 0x79, 0x60, 0x3c, 0x96, 0x05, 0x32, 0x7e, 0x79, 0xaa, 0xab, 0x0b, - 0x03, 0xd2, 0xad, 0xf4, 0x6d, 0x23, 0xb6, 0x29, 0xbc, 0x72, 0xf2, 0xbd, 0x46, 0xc3, 0xca, 0xdb, 0x5d, 0x78, 0xfb, - 0x92, 0x0b, 0x18, 0xe1, 0xf9, 0xbd, 0xa8, 0xad, 0xfb, 0x2d, 0x3e, 0xae, 0xa6, 0xb0, 0xac, 0x2c, 0x8a, 0xcb, 0x92, - 0x9c, 0x66, 0xfc, 0x09, 0x1d, 0xa7, 0x19, 0x84, 0x2c, 0x4a, 0x9c, 0xa0, 0x62, 0xd7, 0x70, 0xdb, 0x89, 0xf9, 0x19, - 0x71, 0x82, 0x95, 0x09, 0x8a, 0x5f, 0x1f, 0x45, 0xd4, 0xfa, 0x7c, 0xb5, 0xd5, 0x64, 0x6f, 0xef, 0x5d, 0x85, 0x26, - 0x05, 0xa5, 0x80, 0xc2, 0x60, 0x5a, 0x52, 0xa5, 0x51, 0xa1, 0xdc, 0x5d, 0xa7, 0x74, 0x01, 0x68, 0x86, 0x61, 0xf2, - 0x9e, 0xe7, 0x84, 0x17, 0x93, 0x55, 0x16, 0xaf, 0x5c, 0x13, 0xcc, 0x34, 0x5b, 0x80, 0xc3, 0x83, 0xa1, 0x2d, 0x7d, - 0x45, 0x79, 0x95, 0x12, 0x5b, 0xc2, 0x70, 0x0a, 0xc8, 0x72, 0x84, 0x11, 0x62, 0x50, 0xe0, 0x46, 0xa3, 0xe4, 0x2d, - 0xe8, 0x95, 0x11, 0xce, 0xdd, 0x08, 0x92, 0x60, 0x6b, 0x5b, 0x16, 0x21, 0x2c, 0x33, 0x73, 0x8c, 0x5c, 0x82, 0x93, - 0xe7, 0x9b, 0x3c, 0xca, 0x9a, 0xa8, 0xa9, 0x90, 0x3a, 0x50, 0x23, 0x45, 0x65, 0x03, 0xf7, 0xca, 0x61, 0x4a, 0x71, - 0xd3, 0x71, 0x33, 0x60, 0xc0, 0x3f, 0x73, 0x47, 0xc6, 0xa2, 0x40, 0x66, 0x64, 0xee, 0xdc, 0xa9, 0x0d, 0xdd, 0xcb, - 0x44, 0x33, 0xac, 0x10, 0x17, 0x99, 0x68, 0xca, 0x44, 0x5c, 0xef, 0xb4, 0xe2, 0xa5, 0x57, 0x32, 0x8f, 0x9a, 0x6b, - 0x2e, 0x58, 0x65, 0x92, 0x18, 0xd3, 0xbf, 0x92, 0xa9, 0xd1, 0x65, 0x25, 0x50, 0xc3, 0xe8, 0xb5, 0xf5, 0x44, 0xac, - 0x01, 0x2d, 0x80, 0xbe, 0x16, 0xa7, 0xdc, 0x58, 0x51, 0xed, 0xc3, 0x16, 0x63, 0x1a, 0x52, 0xff, 0x1d, 0xe4, 0xba, - 0xac, 0xee, 0xf9, 0xe7, 0x42, 0x16, 0x32, 0x9c, 0xd7, 0x18, 0x7b, 0x2a, 0x18, 0x3b, 0x02, 0x3d, 0x4d, 0xa7, 0x7f, - 0x0f, 0x54, 0xca, 0x8b, 0xca, 0x5d, 0x74, 0x14, 0x89, 0xbd, 0x2e, 0xc3, 0xe5, 0xc6, 0xef, 0x95, 0xd5, 0xf0, 0x18, - 0x81, 0x34, 0x20, 0xac, 0x38, 0x7b, 0x8a, 0x70, 0xde, 0x68, 0xf4, 0xf2, 0x63, 0x5a, 0xb9, 0x48, 0x2a, 0x18, 0x19, - 0x44, 0x74, 0x81, 0xe0, 0x6b, 0x32, 0x14, 0x62, 0xfe, 0x3a, 0x3f, 0x3b, 0x07, 0x57, 0xfb, 0xc9, 0x3b, 0xc7, 0xe4, - 0x6a, 0x66, 0xdd, 0x32, 0x68, 0x0a, 0xf3, 0x71, 0xaa, 0x78, 0xcb, 0xdb, 0xbb, 0x33, 0x3c, 0x00, 0xee, 0x9d, 0x0e, - 0x86, 0x6c, 0x34, 0xd4, 0xe3, 0x92, 0x25, 0x94, 0xbb, 0xaf, 0x87, 0xaa, 0xc4, 0x44, 0x73, 0xb0, 0x1e, 0xaf, 0x4c, - 0x59, 0x4e, 0xf2, 0xa2, 0xc8, 0x69, 0x15, 0xdf, 0x5f, 0xc9, 0xc0, 0x14, 0xc2, 0x65, 0xdd, 0xd9, 0x7e, 0x3a, 0x23, - 0x1c, 0x1b, 0x84, 0xfa, 0x76, 0x5b, 0xe8, 0xa3, 0x02, 0x13, 0xf6, 0xb5, 0x12, 0x8a, 0xdf, 0x6e, 0x12, 0x8a, 0x38, - 0x55, 0x5b, 0x5e, 0x08, 0xc4, 0xce, 0x3d, 0x04, 0xa2, 0x72, 0xb2, 0x6b, 0x99, 0x08, 0xea, 0x48, 0x4d, 0x26, 0xd6, - 0x97, 0x94, 0xa4, 0x98, 0xa9, 0xd5, 0xe8, 0x77, 0x97, 0x4b, 0x36, 0x6c, 0x83, 0x13, 0xc9, 0xb6, 0xe1, 0x67, 0x47, - 0xfe, 0x34, 0x38, 0xb1, 0x74, 0x02, 0x3b, 0xac, 0x34, 0x59, 0x90, 0x0b, 0x69, 0xce, 0x8e, 0xc8, 0xca, 0x12, 0x34, - 0xad, 0x28, 0x48, 0x11, 0x38, 0x61, 0x65, 0x94, 0x09, 0x20, 0x16, 0xb2, 0x42, 0x19, 0x90, 0xce, 0xc6, 0xf4, 0x3f, - 0x6d, 0x5e, 0x7e, 0x5a, 0x13, 0xad, 0xc9, 0x15, 0xa9, 0x3e, 0xd4, 0x12, 0x0e, 0x14, 0x04, 0x4a, 0x3f, 0xdc, 0x11, - 0x26, 0x68, 0x25, 0xca, 0x91, 0x29, 0x87, 0x70, 0x1b, 0x5c, 0x68, 0x3b, 0xef, 0x64, 0x80, 0x77, 0x83, 0x34, 0xc1, - 0x99, 0x41, 0xd7, 0xcf, 0x09, 0xaf, 0xb1, 0x92, 0x88, 0x28, 0x4b, 0x09, 0x07, 0x82, 0x4c, 0x39, 0x49, 0x87, 0xed, - 0x11, 0x28, 0xa0, 0x3d, 0xff, 0x38, 0xad, 0x4c, 0x60, 0xbf, 0xd1, 0x40, 0x81, 0x1e, 0x35, 0x1a, 0xb2, 0x86, 0x3f, - 0xc2, 0x14, 0xfb, 0xd2, 0x30, 0x39, 0xdd, 0xdb, 0x73, 0x82, 0x6a, 0xdc, 0xa1, 0x3f, 0x42, 0x38, 0x5b, 0x2e, 0x1d, - 0x01, 0x56, 0x80, 0x96, 0xcb, 0xc0, 0x04, 0x4b, 0xbc, 0x86, 0x66, 0x93, 0x01, 0x27, 0x13, 0x21, 0x00, 0x27, 0x00, - 0x61, 0x83, 0x38, 0x81, 0x72, 0xee, 0x05, 0xe0, 0x8c, 0x6a, 0xa4, 0x43, 0xbf, 0xd1, 0x19, 0x19, 0x8c, 0x6b, 0xe8, - 0x8f, 0x48, 0x50, 0x40, 0x72, 0x6b, 0xae, 0x44, 0xe4, 0xcf, 0x20, 0xca, 0x7e, 0x16, 0x92, 0x45, 0x76, 0x68, 0xae, - 0xc6, 0xaa, 0x33, 0xa0, 0xa4, 0x28, 0xb5, 0xac, 0xba, 0x5e, 0x2d, 0x0b, 0xa2, 0xac, 0x84, 0x55, 0x2c, 0x78, 0x00, - 0x96, 0x7d, 0x49, 0xe6, 0xbf, 0xf0, 0x32, 0xcd, 0xfa, 0xdb, 0x8d, 0xc9, 0xd5, 0xae, 0xeb, 0xfa, 0xd9, 0x44, 0x44, - 0x32, 0x74, 0x14, 0x56, 0x10, 0xff, 0xbe, 0x02, 0xd3, 0x18, 0x78, 0x58, 0x8e, 0x35, 0x22, 0x12, 0x7c, 0xad, 0xda, - 0xe8, 0x13, 0x25, 0xbf, 0x6e, 0xf4, 0x32, 0x48, 0x48, 0xbe, 0xfe, 0xad, 0x90, 0x1c, 0x28, 0x48, 0x24, 0x79, 0xac, - 0xe0, 0x6c, 0x0b, 0x2e, 0x7e, 0xe5, 0x2b, 0x38, 0xdb, 0x8e, 0xdb, 0x92, 0x21, 0x6c, 0x83, 0xcf, 0xe0, 0x0d, 0x12, - 0xd0, 0xaa, 0xc0, 0x80, 0xf2, 0x70, 0x55, 0xf7, 0x92, 0xac, 0x14, 0x84, 0x29, 0x27, 0x0e, 0xab, 0x6f, 0x80, 0x4a, - 0x1b, 0x35, 0x0c, 0x5f, 0xe6, 0x4d, 0x90, 0xe1, 0x12, 0xa8, 0xa7, 0xae, 0x00, 0x39, 0x29, 0x5f, 0x3b, 0xa4, 0x22, - 0xec, 0x48, 0x25, 0xce, 0x0d, 0xfc, 0x19, 0x9f, 0x67, 0xa0, 0x4a, 0xe5, 0xfa, 0x37, 0x14, 0xc3, 0x59, 0x10, 0x51, - 0x06, 0x3f, 0xa0, 0x60, 0xe6, 0xe7, 0x39, 0xbb, 0x92, 0x65, 0xea, 0x37, 0xce, 0x88, 0x26, 0xe5, 0x5c, 0xea, 0x84, - 0x29, 0xea, 0xa5, 0x8a, 0x4e, 0xeb, 0x68, 0x7b, 0x76, 0x45, 0x13, 0xfe, 0x92, 0xe5, 0x9c, 0x26, 0x30, 0xfd, 0x8a, - 0xe2, 0x60, 0x46, 0x39, 0x82, 0x0d, 0x5b, 0x6b, 0xe5, 0x87, 0xe1, 0x9d, 0x4d, 0x78, 0x5d, 0x07, 0x8a, 0xfc, 0x24, - 0x8c, 0xe5, 0x20, 0x66, 0x42, 0xa3, 0x4e, 0xe2, 0x2c, 0x6b, 0x9a, 0xf9, 0x34, 0x95, 0xb2, 0x21, 0xb8, 0xbb, 0xc3, - 0x88, 0x96, 0x04, 0x5a, 0x7a, 0xde, 0xa9, 0xb5, 0x40, 0xc0, 0x7b, 0xcb, 0x22, 0x98, 0x33, 0xc1, 0xdc, 0xe0, 0xa8, - 0x6e, 0x1d, 0x4e, 0x4d, 0x37, 0xdf, 0x6d, 0x3c, 0xd8, 0xb6, 0x49, 0x38, 0x08, 0x3a, 0x79, 0xb8, 0xdd, 0xb2, 0x7a, - 0xa5, 0x25, 0x87, 0x96, 0x16, 0xec, 0xbe, 0x8c, 0x19, 0x2d, 0x34, 0x79, 0x21, 0xbd, 0x15, 0x77, 0x39, 0xf9, 0x05, - 0x4e, 0x0e, 0x3d, 0xe7, 0xd3, 0x78, 0xe5, 0x80, 0x4c, 0x6f, 0xb7, 0xd4, 0xfe, 0x77, 0xb9, 0xf3, 0x04, 0xbf, 0x82, - 0xb0, 0xee, 0x37, 0x55, 0xf5, 0xf5, 0x70, 0xee, 0x37, 0x15, 0x82, 0xbe, 0xf1, 0xd6, 0xea, 0x19, 0x61, 0xdc, 0xae, - 0x7b, 0xe4, 0xb6, 0x6d, 0xad, 0x2d, 0xfd, 0x28, 0x83, 0x48, 0x32, 0xd5, 0x52, 0xec, 0x07, 0x5c, 0x25, 0xaa, 0x41, - 0xc2, 0x5c, 0xdd, 0x42, 0xa2, 0x2a, 0xc5, 0x50, 0xea, 0xf0, 0xdb, 0x96, 0x47, 0xc9, 0x98, 0x54, 0xda, 0x19, 0x6f, - 0xfd, 0x8c, 0xef, 0xc2, 0x2e, 0xcb, 0xd6, 0x4e, 0xe3, 0x45, 0x04, 0x3c, 0x68, 0xf7, 0x1b, 0xc2, 0x30, 0xb6, 0x73, - 0x79, 0x18, 0xc8, 0xec, 0x9f, 0x64, 0x5a, 0x77, 0xab, 0x5b, 0x19, 0xaf, 0xc1, 0xfe, 0x47, 0x38, 0xd2, 0x47, 0xe4, - 0xa8, 0xe2, 0xc0, 0xd4, 0x5b, 0x14, 0xa5, 0x53, 0x20, 0x93, 0xca, 0x5b, 0x82, 0x70, 0x56, 0x88, 0xf0, 0xf6, 0xf7, - 0xf8, 0x07, 0xc5, 0x12, 0xcf, 0x4b, 0x8e, 0xf3, 0xec, 0xbe, 0x1c, 0x51, 0x82, 0x5f, 0x46, 0xef, 0x81, 0x8e, 0x05, - 0x85, 0x16, 0x9a, 0x8a, 0x9e, 0xa6, 0x6a, 0x22, 0x5b, 0xf3, 0x52, 0x31, 0x2d, 0x33, 0x6a, 0xc4, 0x30, 0x1b, 0x12, - 0x39, 0xb5, 0x95, 0xcd, 0xcb, 0x5d, 0x55, 0x1b, 0x17, 0x6d, 0xc1, 0x62, 0x15, 0x58, 0x5c, 0x2e, 0x9d, 0x3a, 0xaa, - 0x09, 0x33, 0xe2, 0x18, 0x08, 0x33, 0x23, 0xa1, 0xa2, 0xa6, 0x59, 0xcb, 0x36, 0x0e, 0x5a, 0xcd, 0x27, 0xd2, 0xba, - 0x79, 0x0d, 0x0e, 0xd3, 0x85, 0x20, 0x9b, 0x9b, 0x3e, 0x05, 0x2c, 0x67, 0x57, 0x0e, 0x64, 0x60, 0xe8, 0xc7, 0x32, - 0x57, 0xb6, 0x4a, 0x6a, 0xdd, 0x80, 0x5f, 0x74, 0x47, 0xb6, 0xac, 0x42, 0xdd, 0xfa, 0x7b, 0x23, 0xd7, 0xe8, 0x69, - 0xba, 0x2d, 0xd7, 0xa8, 0xa6, 0xed, 0xee, 0xb4, 0xd1, 0xdd, 0x79, 0xa9, 0x72, 0xac, 0xcd, 0x55, 0x7e, 0xc3, 0x70, - 0x1d, 0xa0, 0x4d, 0x89, 0x66, 0xcd, 0x55, 0x4e, 0x8b, 0xe2, 0xbc, 0x3c, 0x4d, 0x20, 0x52, 0x77, 0xce, 0x25, 0xfd, - 0x2b, 0xab, 0x51, 0x1c, 0xca, 0x75, 0xbe, 0x27, 0x93, 0x38, 0xbd, 0xf4, 0xe3, 0xf7, 0x30, 0x5e, 0xf5, 0xf2, 0xf9, - 0x6d, 0x98, 0xf9, 0x9c, 0x2a, 0xee, 0x52, 0xc1, 0xf0, 0xbd, 0x01, 0xc3, 0xf7, 0x92, 0x4f, 0x57, 0xed, 0xf1, 0xe2, - 0x65, 0xd9, 0x81, 0x77, 0x5e, 0x68, 0x96, 0x71, 0xcb, 0x37, 0x8f, 0xb1, 0xca, 0xc2, 0x6e, 0x4b, 0x16, 0x76, 0xcb, - 0x9d, 0xd5, 0xae, 0x1c, 0xe7, 0x87, 0xcd, 0xbd, 0xac, 0x73, 0xb6, 0x1f, 0xaa, 0x8d, 0xff, 0x83, 0x77, 0x67, 0x1b, - 0x83, 0xcb, 0xed, 0xbb, 0xfb, 0x22, 0x59, 0x45, 0x82, 0xfc, 0x12, 0x92, 0x0e, 0x38, 0xe9, 0x1b, 0x87, 0x0e, 0x2a, - 0x39, 0xa5, 0xf3, 0x80, 0x9c, 0x60, 0x9e, 0xf3, 0x74, 0xaa, 0xfa, 0xcc, 0xd5, 0x49, 0x23, 0xf1, 0x12, 0x5c, 0xd1, - 0x22, 0xd6, 0xee, 0xd5, 0xcf, 0x72, 0x2d, 0x3e, 0xb2, 0x24, 0xf4, 0x72, 0xac, 0xa4, 0x48, 0xee, 0xa5, 0x05, 0xd1, - 0xd9, 0xc6, 0xeb, 0xef, 0xf0, 0x98, 0x25, 0x2c, 0x8f, 0x68, 0xe6, 0x64, 0x68, 0xb1, 0x6d, 0xb0, 0x0c, 0x02, 0x32, - 0x72, 0x30, 0xfc, 0xd7, 0xea, 0xd4, 0x9f, 0x0b, 0xbd, 0x81, 0x1f, 0x68, 0x4a, 0x79, 0x94, 0x86, 0x90, 0x96, 0xe2, - 0x86, 0xe5, 0xa1, 0xa6, 0xbd, 0xbd, 0x1d, 0xc7, 0x16, 0x6e, 0x09, 0x38, 0x00, 0x6e, 0xbe, 0x41, 0x83, 0x05, 0x9c, - 0xcf, 0xa9, 0x86, 0xa6, 0x68, 0x41, 0x57, 0x8f, 0xb2, 0x70, 0xf7, 0x23, 0xbd, 0xc5, 0x09, 0x2a, 0x0a, 0x4f, 0x42, - 0x6d, 0x8f, 0x19, 0x8d, 0x43, 0x1b, 0x7f, 0xa4, 0xb7, 0x5e, 0x79, 0x66, 0x5c, 0x1c, 0x71, 0x16, 0x0b, 0x68, 0xa7, - 0xd7, 0x89, 0x8d, 0xab, 0x41, 0xbc, 0x45, 0x81, 0xd3, 0x8c, 0x4d, 0x80, 0x38, 0xbf, 0xa1, 0xb7, 0x9e, 0xec, 0x8f, - 0x19, 0xe7, 0xf5, 0xd0, 0x42, 0xa3, 0xde, 0x35, 0x8a, 0xcd, 0x65, 0x50, 0x06, 0xc5, 0x50, 0xb4, 0x1d, 0x91, 0x5a, - 0xbd, 0xca, 0x3c, 0x44, 0xa8, 0xb8, 0xef, 0x54, 0xf0, 0x37, 0xa6, 0x68, 0xe3, 0xb5, 0xcc, 0xd7, 0x95, 0x46, 0x14, - 0x1a, 0x54, 0x99, 0x1e, 0xbb, 0x4e, 0xa2, 0x77, 0x9d, 0x3a, 0x84, 0x60, 0x38, 0xc2, 0xbe, 0xe1, 0xaa, 0x53, 0xef, - 0xaf, 0x32, 0x21, 0xa4, 0x8a, 0x24, 0xbd, 0xa8, 0xda, 0x59, 0xbb, 0x0e, 0xe0, 0x1d, 0x12, 0x5a, 0x7c, 0x71, 0x26, - 0xb3, 0xd0, 0xd9, 0xa2, 0x7f, 0xe3, 0xc4, 0x59, 0xe8, 0x29, 0x78, 0x89, 0x89, 0x45, 0x5e, 0x00, 0x15, 0x2a, 0xfa, - 0x92, 0x09, 0x80, 0x6c, 0xec, 0xb0, 0x35, 0xa9, 0x99, 0x0a, 0xa9, 0xe9, 0x1a, 0x18, 0xdf, 0x22, 0x25, 0xa9, 0x40, - 0x86, 0x50, 0x22, 0x85, 0xd0, 0x53, 0x8b, 0xab, 0x48, 0xc8, 0x5c, 0xd0, 0xf2, 0x04, 0x9d, 0x5c, 0xf3, 0xb4, 0x06, - 0x96, 0x23, 0xfa, 0x41, 0x85, 0x07, 0x53, 0xa2, 0xb2, 0x42, 0x51, 0x1e, 0xcd, 0xd6, 0xe9, 0xad, 0x4e, 0xe6, 0xea, - 0x69, 0x11, 0x8d, 0x12, 0x27, 0x42, 0x8b, 0xc4, 0x89, 0x70, 0x0a, 0xe9, 0x88, 0x59, 0x51, 0xc2, 0x4f, 0xcd, 0xd5, - 0xa8, 0x25, 0x2b, 0x6f, 0x3e, 0xe5, 0x07, 0xca, 0x3c, 0x87, 0x14, 0x4d, 0x9c, 0x68, 0x9e, 0x92, 0x38, 0xe2, 0xb8, - 0x9d, 0xb1, 0x6c, 0xdf, 0xab, 0x04, 0x1d, 0x05, 0xd8, 0xdf, 0xb8, 0xb3, 0x30, 0x66, 0x61, 0x9e, 0xe8, 0x56, 0xa7, - 0xfe, 0x54, 0xb0, 0xaf, 0xca, 0x21, 0x75, 0x72, 0xb2, 0x22, 0x71, 0xee, 0x4e, 0xb5, 0xfc, 0x65, 0x4e, 0xb3, 0xdb, - 0x33, 0x0a, 0xa9, 0xce, 0x29, 0x1c, 0xf8, 0xad, 0x96, 0xa1, 0xca, 0x53, 0x1f, 0xa4, 0x42, 0x59, 0x29, 0xea, 0xe7, - 0x00, 0x57, 0x4f, 0x09, 0x16, 0x22, 0xda, 0x68, 0x38, 0x62, 0xe4, 0x6e, 0xa1, 0x5b, 0xcf, 0x4f, 0xd2, 0x1e, 0x03, - 0xff, 0x5a, 0x85, 0x69, 0x15, 0x2c, 0xc0, 0x99, 0x79, 0x26, 0x75, 0x98, 0x8f, 0x56, 0xbd, 0x32, 0x50, 0x04, 0xe1, - 0xbb, 0x74, 0xfb, 0x54, 0x37, 0x25, 0xcd, 0x6e, 0x9f, 0x6a, 0x2d, 0xe8, 0x27, 0x12, 0x7e, 0xb0, 0x1a, 0xa7, 0x3c, - 0xc1, 0xcc, 0x8a, 0x02, 0x15, 0x00, 0xde, 0x5f, 0x7a, 0x8e, 0xf3, 0x17, 0x95, 0x32, 0xe8, 0x42, 0x2c, 0xf6, 0x2c, - 0x4e, 0x35, 0x13, 0xaf, 0xc6, 0xff, 0xcb, 0xda, 0xf8, 0x7f, 0x31, 0x4e, 0x9d, 0x82, 0x69, 0x34, 0x49, 0x68, 0xa8, - 0x59, 0x27, 0x92, 0x04, 0x28, 0xf4, 0xb6, 0x8c, 0x93, 0x8f, 0x17, 0x1e, 0x68, 0x5c, 0x8b, 0x71, 0x9a, 0xf0, 0xe6, - 0xd8, 0x9f, 0xb2, 0xf8, 0xd6, 0x9b, 0xb3, 0xe6, 0x34, 0x4d, 0xd2, 0x7c, 0xe6, 0x07, 0x14, 0xe7, 0xb7, 0x39, 0xa7, - 0xd3, 0xe6, 0x9c, 0xe1, 0xe7, 0x34, 0xbe, 0xa2, 0x9c, 0x05, 0x3e, 0xb6, 0x4f, 0x32, 0xe6, 0xc7, 0xd6, 0x6b, 0x3f, - 0xcb, 0xd2, 0x6b, 0x1b, 0xbf, 0x4b, 0x2f, 0x53, 0x9e, 0xe2, 0x37, 0x37, 0xb7, 0x13, 0x9a, 0xe0, 0x0f, 0x97, 0xf3, - 0x84, 0xcf, 0x71, 0xee, 0x27, 0x79, 0x33, 0xa7, 0x19, 0x1b, 0xf7, 0x82, 0x34, 0x4e, 0xb3, 0x26, 0x64, 0x6c, 0x4f, - 0xa9, 0x17, 0xb3, 0x49, 0xc4, 0xad, 0xd0, 0xcf, 0x3e, 0xf6, 0x9a, 0xcd, 0x59, 0xc6, 0xa6, 0x7e, 0x76, 0xdb, 0x14, - 0x35, 0xbc, 0x2f, 0xdb, 0xfb, 0xfe, 0xe3, 0xf1, 0x41, 0x8f, 0x67, 0x7e, 0x92, 0x33, 0x58, 0x26, 0xcf, 0x8f, 0x63, - 0x6b, 0xff, 0xb0, 0x3d, 0xcd, 0x77, 0x64, 0x20, 0xcf, 0x4f, 0x78, 0x71, 0x81, 0xdf, 0x03, 0xdc, 0xee, 0x25, 0x4f, - 0xf0, 0xe5, 0x9c, 0xf3, 0x34, 0x59, 0x04, 0xf3, 0x2c, 0x4f, 0x33, 0x6f, 0x96, 0xb2, 0x84, 0xd3, 0xac, 0x77, 0x99, - 0x66, 0x21, 0xcd, 0x9a, 0x99, 0x1f, 0xb2, 0x79, 0xee, 0x1d, 0xcc, 0x6e, 0x7a, 0xa0, 0x59, 0x4c, 0xb2, 0x74, 0x9e, - 0x84, 0x6a, 0x2c, 0x96, 0x44, 0x34, 0x63, 0xdc, 0x7c, 0x21, 0x2e, 0x32, 0xf1, 0x62, 0x96, 0x50, 0x3f, 0x6b, 0x4e, - 0xa0, 0x31, 0x98, 0x45, 0xed, 0x90, 0x4e, 0x70, 0x36, 0xb9, 0xf4, 0x9d, 0x4e, 0xf7, 0x11, 0xd6, 0xff, 0xbb, 0x87, - 0xc8, 0x6a, 0x6f, 0x2e, 0xee, 0xb4, 0xdb, 0x7f, 0x42, 0xbd, 0x95, 0x51, 0x04, 0x40, 0x5e, 0x67, 0x76, 0x63, 0xe5, - 0x29, 0x64, 0xb4, 0x6d, 0x6a, 0xd9, 0x9b, 0xf9, 0x21, 0xe4, 0x03, 0x7b, 0xdd, 0xd9, 0x4d, 0x01, 0xb3, 0xf3, 0x64, - 0x8a, 0xa9, 0x9a, 0xa4, 0x7a, 0x5a, 0xfc, 0x56, 0x88, 0x8f, 0x36, 0x43, 0xdc, 0xd5, 0x10, 0x57, 0x58, 0x6f, 0x86, - 0xf3, 0x4c, 0xc4, 0x56, 0xbd, 0x4e, 0x2e, 0x01, 0x89, 0xd2, 0x2b, 0x9a, 0x69, 0x38, 0xc4, 0xc3, 0x6f, 0x06, 0xa3, - 0xbb, 0x19, 0x8c, 0xa3, 0x4f, 0x81, 0x91, 0x25, 0xe1, 0xa2, 0xbe, 0xae, 0x9d, 0x8c, 0x4e, 0x7b, 0x11, 0x05, 0x7a, - 0xf2, 0xba, 0xf0, 0xfb, 0x9a, 0x85, 0x3c, 0x92, 0x3f, 0x05, 0x39, 0x5f, 0xcb, 0x77, 0x87, 0xed, 0xb6, 0x7c, 0xce, - 0xd9, 0xaf, 0xd4, 0xeb, 0xb8, 0x50, 0xa1, 0xb8, 0xc0, 0x3f, 0x94, 0xa7, 0x79, 0xeb, 0xdc, 0x13, 0xff, 0xc5, 0x3c, - 0xe6, 0x6b, 0xa4, 0x28, 0x56, 0x87, 0xa2, 0x71, 0xaa, 0x65, 0xa5, 0x14, 0x3e, 0xe0, 0xb6, 0x13, 0xdc, 0x91, 0xb0, - 0x7e, 0x79, 0x8c, 0x93, 0x0d, 0xfe, 0x22, 0xf3, 0x2e, 0x3c, 0x88, 0x74, 0x18, 0xa9, 0x86, 0x59, 0x2f, 0xed, 0x93, - 0x76, 0x2f, 0x6d, 0x36, 0x91, 0x93, 0x91, 0x64, 0x98, 0xaa, 0xe4, 0x3c, 0x87, 0x0d, 0xa4, 0xb1, 0x9d, 0x23, 0x2f, - 0x83, 0xb3, 0xa6, 0xcb, 0x65, 0x15, 0x06, 0x60, 0xe2, 0xb4, 0xc6, 0x0f, 0x5c, 0x55, 0xc0, 0xb9, 0xc1, 0xc9, 0x7d, - 0x7d, 0xbd, 0x4b, 0xa2, 0x79, 0x45, 0x9c, 0x06, 0x02, 0x73, 0xee, 0xcc, 0xe7, 0x11, 0x78, 0x29, 0x4a, 0xf1, 0x53, - 0xa5, 0x30, 0xd9, 0x2d, 0x1b, 0x0d, 0x92, 0x32, 0xbf, 0x0d, 0xf2, 0xf8, 0x92, 0x02, 0x7a, 0xb9, 0xe4, 0x04, 0x7a, - 0xac, 0xfa, 0xff, 0xc0, 0x0d, 0x49, 0x9d, 0xb8, 0x2c, 0x09, 0xe2, 0x79, 0x48, 0x73, 0xd1, 0x43, 0x25, 0xce, 0xe1, - 0x6e, 0x88, 0xb2, 0x96, 0x68, 0x02, 0xbd, 0x8b, 0x6c, 0x1e, 0xa8, 0x08, 0xb7, 0xa8, 0x94, 0xcf, 0x4d, 0xf1, 0x5c, - 0xb5, 0x7d, 0x5d, 0x25, 0x8b, 0x42, 0x4b, 0x77, 0x9e, 0xb0, 0x5f, 0xe6, 0xf4, 0x9c, 0x85, 0xc6, 0xc9, 0x5d, 0x9a, - 0x04, 0x69, 0x48, 0x3f, 0xbc, 0x7b, 0x01, 0xd9, 0xee, 0x69, 0x02, 0x24, 0x96, 0x48, 0x7f, 0x17, 0xce, 0x49, 0xe2, - 0x86, 0xf4, 0x8a, 0x05, 0x74, 0x70, 0xb1, 0xbb, 0xd8, 0x58, 0x51, 0xbe, 0x46, 0x45, 0xeb, 0x02, 0xfc, 0x77, 0x12, - 0xca, 0x8b, 0xdd, 0xc5, 0x25, 0x2f, 0x5a, 0xbb, 0x8b, 0xc4, 0x0d, 0xd3, 0xa9, 0xcf, 0x12, 0xf8, 0x9d, 0x17, 0xbb, - 0x0b, 0x06, 0x3f, 0x78, 0x71, 0x51, 0x54, 0x89, 0xa2, 0x25, 0x44, 0xc6, 0x14, 0x14, 0xee, 0x3a, 0xc8, 0xfd, 0x39, - 0x65, 0x89, 0x28, 0xba, 0xab, 0x67, 0xaa, 0x7b, 0x05, 0x24, 0xff, 0x4a, 0xa4, 0xc1, 0xac, 0xcd, 0xe5, 0xf3, 0xfb, - 0x9a, 0xcb, 0x34, 0xe1, 0x4c, 0xa4, 0xc5, 0xeb, 0x70, 0x4e, 0xe4, 0xe7, 0xe7, 0x81, 0x3c, 0x89, 0x9a, 0x57, 0xa7, - 0x2e, 0x7c, 0x81, 0x58, 0x69, 0x01, 0x53, 0x69, 0xec, 0xd3, 0xed, 0x47, 0x25, 0x93, 0xbb, 0x8c, 0xbf, 0x92, 0xaa, - 0xf2, 0x74, 0x9e, 0x05, 0x10, 0xeb, 0x55, 0x2a, 0xc5, 0xba, 0x57, 0xcc, 0x16, 0xfa, 0x9b, 0x8d, 0xb9, 0x91, 0x64, - 0xcb, 0xe1, 0x4c, 0x5f, 0x75, 0x6d, 0x07, 0x15, 0xf1, 0x44, 0x58, 0x33, 0x26, 0x56, 0xef, 0x9c, 0x85, 0x10, 0x78, - 0x61, 0xa1, 0x4a, 0x58, 0xac, 0x4d, 0x12, 0x54, 0xa4, 0x50, 0x64, 0x90, 0xc2, 0x65, 0x3b, 0x59, 0xb5, 0x0a, 0x84, - 0x10, 0x19, 0xd7, 0x03, 0xe1, 0xdb, 0xec, 0xec, 0xed, 0xe5, 0xd5, 0x89, 0x36, 0xa6, 0x70, 0xbe, 0x5c, 0x72, 0xea, - 0xe4, 0xf2, 0xd4, 0x4d, 0x44, 0x40, 0x19, 0x63, 0x58, 0xbe, 0xf1, 0x32, 0x5c, 0xf6, 0xe4, 0xe5, 0x45, 0x2f, 0x12, - 0x48, 0x94, 0x28, 0x23, 0x1a, 0xa9, 0x27, 0x5a, 0x25, 0xc3, 0xe6, 0xeb, 0xf2, 0x20, 0x7f, 0x0d, 0xeb, 0xed, 0x95, - 0xc5, 0x91, 0x56, 0x55, 0xb4, 0x5a, 0x9a, 0xa7, 0x19, 0x77, 0x1c, 0x1f, 0x07, 0x88, 0xf4, 0x7d, 0x31, 0xfb, 0x63, - 0x99, 0xef, 0x31, 0x68, 0x76, 0xbc, 0x4e, 0xe9, 0x0f, 0xa9, 0x9d, 0xaf, 0x96, 0xd9, 0x66, 0xea, 0x8c, 0x2e, 0xe0, - 0x09, 0x97, 0xbf, 0x15, 0xfa, 0xaa, 0x02, 0x39, 0xbb, 0xea, 0xb9, 0x9c, 0x24, 0x56, 0x0c, 0x4d, 0x2a, 0x03, 0x4e, - 0x0d, 0xaa, 0x61, 0x3a, 0xc2, 0x6c, 0xcb, 0xd8, 0xa8, 0xa8, 0x10, 0x51, 0x6e, 0xee, 0x0b, 0xa9, 0x04, 0x9d, 0x1b, - 0xd4, 0x7d, 0xc1, 0xb4, 0x1b, 0xaf, 0x4e, 0x77, 0x85, 0x42, 0x91, 0xc1, 0x19, 0x36, 0x55, 0x93, 0xb0, 0xdc, 0x92, - 0x64, 0x23, 0xf1, 0xba, 0xf2, 0x91, 0x66, 0xa4, 0x0a, 0x28, 0xae, 0x75, 0x00, 0xc9, 0x90, 0x9b, 0x00, 0x03, 0xc7, - 0x40, 0xce, 0xf5, 0x14, 0x80, 0xc7, 0x8c, 0x29, 0x9c, 0x54, 0x52, 0x1c, 0x07, 0x2f, 0xa4, 0x76, 0xef, 0xd9, 0x6f, - 0xdf, 0x9c, 0xbd, 0xb7, 0x31, 0x5c, 0x75, 0x46, 0xb3, 0xdc, 0x5b, 0xd8, 0x2a, 0xc7, 0xb0, 0x09, 0xf1, 0x6a, 0xdb, - 0xb3, 0xfd, 0x19, 0x1c, 0xda, 0x16, 0x4c, 0xb5, 0x75, 0xd3, 0xbc, 0xbe, 0xbe, 0x6e, 0xc2, 0x89, 0xb2, 0xe6, 0x3c, - 0x8b, 0x25, 0xbb, 0x09, 0xed, 0xa2, 0x40, 0x2e, 0x8f, 0x68, 0x52, 0x5e, 0x86, 0x94, 0xc6, 0xd4, 0x8d, 0xd3, 0x89, - 0x3c, 0x0f, 0xbb, 0xea, 0x9e, 0x88, 0x2f, 0x8e, 0xc5, 0x25, 0x5f, 0xfd, 0x63, 0x2e, 0xaf, 0x57, 0xe3, 0x19, 0xfc, - 0xec, 0x43, 0xf0, 0xea, 0xb8, 0xc5, 0x23, 0xf1, 0x70, 0x06, 0xbb, 0x49, 0x3c, 0xed, 0x2e, 0xd6, 0xa8, 0x6e, 0x00, - 0x5d, 0x44, 0x7d, 0x39, 0xb5, 0x5c, 0xd4, 0xba, 0xf0, 0xe2, 0x8b, 0x8b, 0xe2, 0xb8, 0x05, 0x7d, 0xb5, 0x74, 0xbf, - 0x97, 0x69, 0x78, 0xab, 0xdb, 0x97, 0x94, 0x08, 0x97, 0x3d, 0x25, 0xa4, 0x0f, 0x5d, 0xc0, 0xb8, 0x61, 0x5f, 0xe0, - 0x4c, 0xb1, 0xd0, 0x61, 0xf5, 0x50, 0x8c, 0x2c, 0x60, 0x98, 0x05, 0x94, 0x00, 0xb9, 0x41, 0xe7, 0x61, 0xd9, 0x40, - 0xec, 0x76, 0x59, 0xb4, 0x0d, 0x40, 0x59, 0xb1, 0xda, 0x3f, 0xd2, 0xcd, 0x5d, 0x91, 0x85, 0x86, 0x38, 0x34, 0x81, - 0xbf, 0x40, 0xf0, 0xaf, 0x00, 0xfc, 0xb8, 0x25, 0xd1, 0x74, 0x61, 0x5e, 0x3b, 0x23, 0x2f, 0x84, 0x28, 0x91, 0x39, - 0xcc, 0x38, 0x7e, 0xcf, 0xf1, 0xc7, 0x0b, 0x51, 0x55, 0x6b, 0x09, 0xa0, 0xbe, 0x82, 0x36, 0xd5, 0xd6, 0xea, 0x60, - 0x90, 0xc6, 0xb1, 0x3f, 0xcb, 0xa9, 0xa7, 0x7f, 0x28, 0x85, 0x01, 0xf4, 0x8e, 0x75, 0x0d, 0x4d, 0xe5, 0x3d, 0x9d, - 0x82, 0x1e, 0xb7, 0xae, 0x3e, 0x5e, 0xf9, 0x99, 0xd3, 0x6c, 0x06, 0xcd, 0xcb, 0x09, 0x2a, 0x78, 0xb4, 0x30, 0xd5, - 0x8d, 0x87, 0xed, 0x76, 0x0f, 0x92, 0x54, 0x9b, 0x7e, 0xcc, 0x26, 0x89, 0x17, 0xd3, 0x31, 0x2f, 0x38, 0x9c, 0x1e, - 0x5c, 0x68, 0xfd, 0xce, 0xed, 0x1e, 0x66, 0x74, 0x6a, 0xb9, 0xf0, 0xf7, 0xee, 0x81, 0x0b, 0x1e, 0x7a, 0x09, 0x8f, - 0x9a, 0x22, 0x19, 0x1a, 0x8e, 0x72, 0xf0, 0xa8, 0xf6, 0xbc, 0x30, 0x06, 0x0a, 0x28, 0xe8, 0xbe, 0x05, 0xcf, 0x2c, - 0x1e, 0x61, 0x9e, 0x99, 0xf5, 0x12, 0xb4, 0x58, 0x9b, 0xc1, 0xba, 0x0a, 0xb6, 0x8f, 0x8a, 0x5c, 0x58, 0x2c, 0x8b, - 0x35, 0xbc, 0x18, 0xaa, 0x74, 0xc1, 0x92, 0xd9, 0x9c, 0x0f, 0x85, 0xe7, 0x3f, 0x83, 0x33, 0x24, 0x23, 0x6c, 0x94, - 0x00, 0x3c, 0x23, 0xd5, 0x3e, 0xf0, 0xe3, 0xc0, 0x81, 0x4e, 0xac, 0xa6, 0x75, 0x94, 0xd1, 0x29, 0xea, 0x4d, 0x59, - 0xd2, 0x94, 0xef, 0x0e, 0x0d, 0xdd, 0xcd, 0x7d, 0x04, 0x4f, 0x85, 0x2b, 0x7a, 0xc3, 0x22, 0xc1, 0x77, 0xc3, 0xbc, - 0x2e, 0x46, 0x45, 0xd1, 0x4b, 0xb9, 0x33, 0x7c, 0xe1, 0xa0, 0x11, 0xfe, 0xd5, 0xb8, 0xc4, 0xc6, 0xd6, 0x54, 0x6d, - 0xe3, 0x2e, 0xda, 0x52, 0xc5, 0xa4, 0x4b, 0x51, 0xed, 0x57, 0x02, 0x15, 0x5f, 0x3a, 0x36, 0xcd, 0x67, 0x4d, 0xc9, - 0x7e, 0x9a, 0x82, 0x7c, 0x6c, 0x68, 0x8a, 0x94, 0x3b, 0x9b, 0xd2, 0x85, 0xe0, 0x2c, 0xea, 0x1c, 0x8b, 0xf4, 0xb8, - 0x8c, 0xca, 0x73, 0x4f, 0xea, 0xd9, 0x3c, 0xe9, 0x84, 0x6a, 0x5b, 0xff, 0xe2, 0xa4, 0xce, 0xa6, 0x40, 0xfe, 0x97, - 0x77, 0xfd, 0xf9, 0x71, 0x0c, 0x03, 0x5e, 0x68, 0xa5, 0xc1, 0xbc, 0x1a, 0x65, 0xc8, 0x47, 0x0e, 0x2a, 0xd4, 0x9e, - 0x79, 0x22, 0xf4, 0x6e, 0xe3, 0x82, 0xc1, 0x1d, 0xae, 0x23, 0x6a, 0xf2, 0x04, 0x33, 0x83, 0x9c, 0x80, 0x5a, 0xee, - 0x78, 0xaf, 0x62, 0x33, 0x52, 0x6b, 0xb7, 0xc4, 0x84, 0x88, 0x9d, 0x25, 0xa1, 0x6d, 0xfd, 0x39, 0x88, 0x59, 0xf0, - 0x91, 0xd8, 0xbb, 0x0b, 0x07, 0xad, 0x1f, 0x0d, 0x15, 0x3b, 0x54, 0xf3, 0x5c, 0x54, 0x8f, 0x36, 0xa4, 0xae, 0xc1, - 0x4e, 0xe5, 0xed, 0x41, 0x76, 0x1f, 0x54, 0x9b, 0xe3, 0x96, 0x1c, 0xa7, 0x7f, 0x51, 0x9c, 0x57, 0xb7, 0x82, 0x55, - 0x50, 0x00, 0x9a, 0x65, 0xb9, 0x25, 0xe8, 0x8f, 0xd8, 0x72, 0x0b, 0xd5, 0x2c, 0x40, 0x6c, 0xd2, 0x3e, 0xb2, 0x2d, - 0xc9, 0x60, 0x00, 0x4e, 0xae, 0x78, 0x8d, 0x6d, 0xfd, 0xb9, 0x2c, 0xa3, 0xa5, 0xdb, 0x47, 0xe4, 0xad, 0x10, 0x1b, - 0xc6, 0x02, 0x5b, 0xdf, 0x0d, 0x29, 0xf7, 0x59, 0x2c, 0x9b, 0xf4, 0xb4, 0x97, 0x62, 0x65, 0x46, 0xcb, 0x65, 0x5e, - 0x9f, 0x0b, 0xab, 0x63, 0x50, 0xcc, 0xec, 0xb8, 0x55, 0xc1, 0x2d, 0x66, 0x26, 0xf6, 0x87, 0x19, 0x3f, 0xad, 0x66, - 0x28, 0xdf, 0x59, 0x7f, 0x0e, 0xc4, 0xc9, 0x2a, 0x00, 0x30, 0x53, 0x00, 0x42, 0x64, 0x5f, 0x2a, 0x21, 0x8e, 0x4f, - 0x32, 0x97, 0xfb, 0xd9, 0x84, 0xf2, 0x15, 0xc4, 0xfa, 0x32, 0x91, 0xb7, 0xa7, 0xa3, 0xf8, 0x6b, 0xd0, 0x06, 0x75, - 0x68, 0x41, 0xcf, 0x2d, 0x06, 0xa0, 0xaa, 0x92, 0x8d, 0x1a, 0x6f, 0x84, 0x40, 0xf6, 0x89, 0xc5, 0x91, 0xdc, 0x3e, - 0x13, 0xdc, 0x5e, 0xc6, 0xe1, 0x2c, 0x31, 0x96, 0x00, 0xb1, 0xb0, 0xad, 0x81, 0x84, 0x9c, 0x86, 0x12, 0x66, 0x92, - 0x8a, 0x56, 0x59, 0x71, 0xdc, 0x92, 0xb5, 0x25, 0x3b, 0x96, 0x95, 0x00, 0x09, 0x62, 0x9f, 0x56, 0x38, 0x80, 0xe4, - 0x6f, 0x13, 0x0f, 0x21, 0xbb, 0x2a, 0x89, 0x4d, 0x9c, 0x31, 0xeb, 0x1f, 0xc7, 0xfe, 0x25, 0x8d, 0xfb, 0xbb, 0x8b, - 0x74, 0xb9, 0x6c, 0x17, 0xc7, 0x2d, 0xf9, 0x68, 0x1d, 0x0b, 0xbe, 0x21, 0xef, 0x06, 0x15, 0x4b, 0x0c, 0x07, 0x37, - 0x21, 0x25, 0x56, 0xe7, 0x82, 0x79, 0xaa, 0x83, 0xc2, 0xb6, 0x44, 0x16, 0x8a, 0xa8, 0x54, 0xea, 0x34, 0x85, 0x6d, - 0xb1, 0x70, 0xbd, 0x2c, 0xe7, 0x74, 0x06, 0xa5, 0xd1, 0x72, 0xd9, 0x29, 0x6c, 0x6b, 0xca, 0x12, 0x78, 0x4a, 0x97, - 0x4b, 0x71, 0x26, 0x72, 0xca, 0x12, 0xa7, 0x0d, 0x64, 0x6b, 0x5b, 0x53, 0xff, 0x46, 0x4c, 0x58, 0xbf, 0xf1, 0x6f, - 0x9c, 0x8e, 0x7a, 0xe5, 0x96, 0xf8, 0xc9, 0x81, 0xe2, 0xaa, 0x15, 0xf5, 0xd5, 0x8a, 0x86, 0x78, 0x2e, 0x4f, 0x7b, - 0x11, 0x27, 0x24, 0xfe, 0xe6, 0x15, 0x0d, 0xf5, 0x8a, 0xce, 0xb7, 0xac, 0xe8, 0xfc, 0x8e, 0x15, 0x0d, 0xd4, 0xea, - 0x59, 0x25, 0xee, 0xb2, 0xe5, 0xb2, 0xd3, 0xae, 0xb0, 0x77, 0xdc, 0x0a, 0xd9, 0x15, 0xac, 0x06, 0x68, 0x6a, 0x9c, - 0x4d, 0xe9, 0x66, 0xa2, 0xac, 0xa3, 0x98, 0x7e, 0x16, 0x26, 0x2b, 0x2c, 0xa4, 0x75, 0x2c, 0x98, 0x74, 0x5d, 0x06, - 0x26, 0xff, 0x48, 0xca, 0x66, 0x80, 0x87, 0x1c, 0xf0, 0x10, 0xe9, 0xbb, 0x42, 0x1d, 0xfb, 0xbd, 0x8d, 0x6d, 0xcb, - 0xd6, 0x64, 0x7d, 0x51, 0x9c, 0x83, 0x8c, 0x10, 0xf3, 0xbb, 0x17, 0x2d, 0x42, 0x6d, 0xbb, 0xbf, 0x9d, 0xe6, 0x20, - 0x87, 0xe0, 0x3a, 0xcd, 0x42, 0xdb, 0x93, 0x55, 0x3f, 0x0b, 0x55, 0x53, 0x96, 0xa8, 0x8c, 0xb4, 0xad, 0xb4, 0x56, - 0xbd, 0x37, 0x29, 0xae, 0x7b, 0x78, 0x28, 0x6b, 0xcc, 0x7c, 0xce, 0x69, 0x96, 0x28, 0xca, 0xb5, 0xed, 0xff, 0x10, - 0x54, 0xb8, 0x81, 0xaf, 0x04, 0x7a, 0x01, 0x34, 0x01, 0x2a, 0x9d, 0x5b, 0xf1, 0x7c, 0x29, 0x9e, 0x76, 0x2a, 0x65, - 0xf3, 0x16, 0x99, 0x7a, 0xbf, 0x2c, 0x02, 0x33, 0x64, 0x3e, 0xa5, 0xe1, 0xb9, 0x60, 0xd0, 0x83, 0xf8, 0x42, 0x29, - 0x8f, 0x2b, 0xe2, 0xae, 0x6a, 0x80, 0xed, 0x9f, 0xe6, 0xdd, 0x47, 0x07, 0xa7, 0x36, 0x96, 0x3c, 0x3e, 0x1d, 0x8f, - 0x6d, 0x54, 0x58, 0xf7, 0x6b, 0xd6, 0x39, 0xf8, 0x69, 0xfe, 0xf5, 0xb3, 0xf6, 0xd7, 0x65, 0xe3, 0x04, 0x88, 0x48, - 0x25, 0x41, 0x68, 0x51, 0x65, 0xc0, 0xab, 0x67, 0x34, 0xf6, 0x93, 0xed, 0xd3, 0x19, 0x9a, 0xd3, 0xc9, 0x67, 0x94, - 0x86, 0x40, 0x9c, 0x78, 0xad, 0xf4, 0x3c, 0xa6, 0x57, 0x54, 0xdf, 0xd0, 0xb8, 0x61, 0xb0, 0x0d, 0x2d, 0x82, 0x74, - 0x9e, 0x70, 0x95, 0x0d, 0xa2, 0x58, 0xad, 0x31, 0xa5, 0x0b, 0x31, 0x07, 0x53, 0x9d, 0xbf, 0x95, 0x72, 0xae, 0x2e, - 0xbd, 0x8a, 0x0b, 0x6c, 0x1b, 0x00, 0x6c, 0x85, 0x6c, 0xb0, 0xa5, 0xdc, 0x6b, 0xe3, 0xf6, 0x36, 0xd8, 0x70, 0x07, - 0x79, 0xb6, 0x3d, 0xd2, 0x78, 0x12, 0x0e, 0xdd, 0xda, 0xa5, 0x1a, 0x5b, 0xf1, 0xf5, 0x49, 0x0c, 0x5c, 0x66, 0xd0, - 0x59, 0x42, 0xf3, 0x7c, 0x2b, 0x02, 0xca, 0x45, 0xc4, 0x76, 0x55, 0xdb, 0xde, 0xd2, 0x0b, 0x6e, 0x63, 0xd8, 0x61, - 0x02, 0xe0, 0x32, 0xac, 0xac, 0x6a, 0xd1, 0xf1, 0x98, 0x06, 0xa5, 0x3f, 0x1c, 0x02, 0x84, 0x63, 0x16, 0x73, 0x88, - 0x93, 0x89, 0x00, 0x96, 0xfd, 0x3a, 0x4d, 0xa8, 0x8d, 0x74, 0xca, 0xab, 0x82, 0x5f, 0xc9, 0xff, 0xcd, 0xf0, 0xc8, - 0x1e, 0xeb, 0xb0, 0xa8, 0x51, 0x96, 0x4b, 0xed, 0xae, 0xa9, 0x95, 0xd7, 0x11, 0x99, 0x0a, 0x7f, 0xcc, 0xb6, 0x0d, - 0x74, 0xbf, 0x6d, 0xb2, 0xe8, 0x7c, 0x7d, 0xd8, 0x69, 0x17, 0x36, 0xb6, 0xa1, 0xbb, 0xfb, 0xee, 0x12, 0xd1, 0x6a, - 0x1f, 0x5a, 0xcd, 0x93, 0xcf, 0x69, 0xd7, 0xed, 0x3c, 0xee, 0xd8, 0x58, 0xde, 0xb5, 0x80, 0x8a, 0x92, 0x19, 0x04, - 0xe0, 0x21, 0xfe, 0xdd, 0x53, 0xa9, 0x77, 0x7e, 0x3f, 0x78, 0x1e, 0x76, 0xda, 0x36, 0xb6, 0x73, 0x9e, 0xce, 0x3e, - 0x63, 0x0a, 0xfb, 0x36, 0xb6, 0x83, 0x38, 0xcd, 0xa9, 0x39, 0x07, 0xa9, 0xce, 0xfe, 0xfe, 0x49, 0x48, 0x88, 0x66, - 0x19, 0xcd, 0x73, 0xcb, 0xec, 0x5f, 0x91, 0xd2, 0x27, 0x18, 0xe6, 0x46, 0x8a, 0xcb, 0x29, 0x17, 0x78, 0x91, 0xd7, - 0x20, 0x98, 0x54, 0x25, 0xcb, 0xd6, 0x88, 0x4d, 0x88, 0x80, 0x92, 0xb1, 0x49, 0xed, 0xea, 0x93, 0x23, 0x6f, 0xd8, - 0x7a, 0x72, 0x60, 0x19, 0x38, 0x5f, 0x1f, 0xa0, 0x56, 0x32, 0x65, 0xc9, 0xf9, 0x86, 0x52, 0xff, 0x66, 0x43, 0x29, - 0xa8, 0x6c, 0x25, 0x74, 0xea, 0x8a, 0x9e, 0x4f, 0x63, 0xbd, 0x52, 0x7c, 0x4c, 0x10, 0x43, 0xe1, 0x7f, 0xfc, 0x04, - 0xa4, 0xc6, 0x32, 0x88, 0x1e, 0x7e, 0xfb, 0x70, 0x50, 0xf2, 0x39, 0xc3, 0x95, 0xbd, 0xfc, 0xbe, 0x19, 0x42, 0x69, - 0x13, 0x9c, 0xfc, 0xf1, 0x67, 0xcd, 0x95, 0xde, 0x7c, 0x9a, 0xe0, 0x0c, 0xad, 0xea, 0x77, 0x2c, 0xbd, 0x3a, 0xea, - 0xbf, 0xba, 0xf6, 0x1b, 0x8a, 0x95, 0xe2, 0x53, 0xae, 0x7f, 0x10, 0xb3, 0x69, 0x45, 0x02, 0xeb, 0x60, 0x0a, 0x8d, - 0x07, 0x32, 0xbe, 0xcc, 0x4e, 0xa4, 0xea, 0x73, 0x0e, 0xe7, 0x58, 0xe1, 0xaa, 0x90, 0x79, 0x46, 0xcf, 0xe3, 0xf4, - 0x7a, 0xf5, 0xf2, 0xb3, 0xed, 0x95, 0x23, 0x36, 0x89, 0x8c, 0xc3, 0x69, 0x94, 0x94, 0x8b, 0x70, 0xe7, 0x00, 0xc5, - 0xbf, 0xfc, 0xb3, 0xeb, 0xfe, 0xcb, 0x3f, 0x7f, 0xb2, 0x2a, 0x74, 0x5f, 0x5c, 0x60, 0x5e, 0x75, 0xbb, 0x7d, 0x77, - 0x6d, 0x1e, 0xa9, 0x8e, 0xf3, 0xcd, 0x75, 0xd6, 0x16, 0x01, 0xde, 0xaf, 0x2d, 0xc1, 0x5a, 0xa1, 0xdc, 0x7d, 0xd6, - 0x6f, 0x01, 0x0c, 0xe6, 0xf5, 0x49, 0xc8, 0xa0, 0xd2, 0xef, 0x02, 0xed, 0x02, 0x79, 0xf7, 0x5a, 0x91, 0xdf, 0x8e, - 0xe1, 0x4f, 0xcd, 0xe1, 0x77, 0x82, 0xaf, 0xfc, 0x13, 0xf1, 0xc5, 0x45, 0x99, 0x85, 0x68, 0x36, 0x85, 0x3b, 0x0e, - 0x06, 0x6b, 0x25, 0x4a, 0xf1, 0xf0, 0xda, 0xa8, 0x2f, 0xce, 0x50, 0x92, 0xf8, 0xe2, 0x15, 0x5c, 0x6c, 0x74, 0x7c, - 0x99, 0x69, 0x67, 0xeb, 0x1d, 0xc2, 0x01, 0xba, 0xa8, 0xcf, 0x4a, 0x74, 0xba, 0x26, 0x19, 0xa0, 0x14, 0xcc, 0x0d, - 0x00, 0x13, 0xc7, 0x17, 0xca, 0xda, 0x3c, 0x95, 0x6e, 0x18, 0x6f, 0x95, 0xb4, 0x95, 0x7b, 0xa6, 0x86, 0x74, 0x6c, - 0xbd, 0x17, 0xf8, 0x12, 0x95, 0x69, 0x65, 0xdd, 0x0b, 0x57, 0x17, 0xd8, 0x11, 0x25, 0xfb, 0xb9, 0xf2, 0xe3, 0xab, - 0xfb, 0x31, 0xbe, 0xed, 0x02, 0x75, 0x69, 0x2d, 0xff, 0xd1, 0x2a, 0xc1, 0xb2, 0xb9, 0xdc, 0xa4, 0x0f, 0x5c, 0xfb, - 0x9c, 0x66, 0xe7, 0x11, 0x24, 0x42, 0x65, 0x9f, 0x60, 0x4e, 0xb0, 0xd2, 0x98, 0x8a, 0xbf, 0x8c, 0xa8, 0x8b, 0xa4, - 0xff, 0x41, 0x9c, 0x8a, 0x41, 0x16, 0x23, 0x0c, 0x65, 0x2c, 0xc2, 0xff, 0xe7, 0x5b, 0xff, 0x61, 0xf8, 0xd6, 0xdd, - 0x43, 0xd4, 0xce, 0x48, 0x7f, 0xf6, 0x42, 0xfe, 0xc7, 0x66, 0x77, 0xb9, 0x60, 0x77, 0xbf, 0x81, 0xd1, 0xe5, 0xff, - 0x18, 0x46, 0x27, 0x6c, 0x64, 0xcd, 0xe9, 0xd6, 0x42, 0xcd, 0xb7, 0xae, 0x7f, 0xed, 0xdf, 0x56, 0xfb, 0x2a, 0xbe, - 0x38, 0xb9, 0xf6, 0x6f, 0xab, 0x45, 0xd8, 0xce, 0x2e, 0x56, 0xfb, 0x18, 0xd8, 0x6f, 0x5e, 0xdb, 0x9e, 0xfd, 0xe6, - 0xeb, 0xaf, 0x6d, 0x7c, 0x91, 0x53, 0x3e, 0x80, 0x42, 0xb2, 0xbb, 0xd8, 0x59, 0xad, 0x08, 0x6e, 0x14, 0x98, 0xa2, - 0x08, 0x7b, 0xe1, 0xac, 0x06, 0x0c, 0xcb, 0xcf, 0xd3, 0xc4, 0x84, 0xe6, 0x2d, 0x58, 0xf6, 0x9f, 0x0b, 0x8e, 0xe8, - 0x65, 0x0d, 0x1e, 0x51, 0xba, 0x0a, 0x90, 0x28, 0xac, 0x41, 0x54, 0x5d, 0x19, 0x74, 0x37, 0xff, 0xaf, 0xae, 0x45, - 0x90, 0xb7, 0x7d, 0x44, 0x83, 0xf8, 0xe2, 0x73, 0xc4, 0x87, 0x1c, 0xac, 0xf2, 0xd8, 0x69, 0x77, 0xa7, 0x5f, 0xec, - 0x2e, 0xa2, 0xbd, 0x3d, 0x36, 0xb0, 0xb1, 0xb8, 0xa7, 0xa9, 0xd8, 0x24, 0x5c, 0x72, 0xf8, 0x93, 0xc2, 0x9f, 0xac, - 0x62, 0xd4, 0x2c, 0x19, 0x67, 0x7e, 0x46, 0xc3, 0xed, 0x4c, 0xba, 0xbc, 0xdf, 0x48, 0x91, 0x86, 0x4c, 0xc0, 0xce, - 0xcf, 0x45, 0xea, 0xd1, 0x94, 0x81, 0x3e, 0xba, 0x63, 0x7e, 0xc5, 0x47, 0x5d, 0x88, 0x56, 0x7e, 0x04, 0xc0, 0x44, - 0x38, 0x25, 0x79, 0x99, 0xeb, 0x00, 0xb7, 0x6a, 0xaa, 0xec, 0x10, 0x6c, 0x23, 0xe1, 0x75, 0x0f, 0x49, 0x5f, 0xa4, - 0x3d, 0xbc, 0x48, 0xb8, 0x13, 0xba, 0x3c, 0x63, 0x53, 0x07, 0xe1, 0x4e, 0x1b, 0x21, 0xed, 0x6c, 0x08, 0x49, 0x7f, - 0x87, 0xe5, 0xaf, 0xfd, 0xd7, 0x4e, 0x28, 0x2e, 0xe2, 0x12, 0x9f, 0xee, 0x81, 0x43, 0x92, 0x4f, 0xe6, 0xe3, 0x31, - 0xcd, 0x1c, 0x7d, 0x00, 0xf0, 0xab, 0x03, 0x38, 0x63, 0x0c, 0x6f, 0x9f, 0xfa, 0xdc, 0xff, 0x96, 0xd1, 0x6b, 0x27, - 0x43, 0xbd, 0xb4, 0xba, 0x9c, 0x31, 0xc4, 0x73, 0x44, 0xfa, 0x11, 0x24, 0xc6, 0xbf, 0x48, 0xf8, 0x7e, 0xd7, 0x99, - 0x7f, 0x75, 0x80, 0x43, 0xb8, 0xf2, 0x42, 0x67, 0x75, 0xcb, 0xbb, 0x4a, 0x3e, 0xb0, 0x84, 0x1f, 0xc9, 0x63, 0x98, - 0x19, 0x52, 0xee, 0xc3, 0x32, 0x23, 0xc6, 0xf2, 0xcb, 0x0e, 0x43, 0xd2, 0x0f, 0x1a, 0x44, 0x1e, 0xca, 0x14, 0xb7, - 0xec, 0x9e, 0x46, 0x7e, 0x76, 0x0a, 0x07, 0xbe, 0x01, 0xd0, 0x4b, 0x9e, 0xfa, 0x4e, 0x50, 0x7e, 0xc9, 0xc9, 0x69, - 0xfd, 0xd4, 0x68, 0x4d, 0xb0, 0x48, 0x8a, 0xa9, 0x8a, 0x5a, 0x50, 0x74, 0x6e, 0x16, 0x91, 0xc6, 0x6e, 0x0b, 0xc3, - 0x1e, 0xec, 0x6d, 0xf4, 0xd1, 0xea, 0xa5, 0x6b, 0x5e, 0x67, 0xfe, 0xac, 0x8c, 0x1b, 0x9c, 0xfa, 0x59, 0xc6, 0x68, - 0x66, 0x39, 0xcf, 0x7f, 0x45, 0xde, 0xbf, 0xfc, 0xf3, 0xe6, 0xf8, 0x81, 0x0a, 0x19, 0x58, 0x90, 0x5c, 0xd2, 0x14, - 0xe9, 0xd8, 0xc4, 0x0e, 0x64, 0x43, 0x5b, 0x87, 0x3b, 0xf6, 0x8f, 0xda, 0xed, 0xb6, 0x0a, 0x09, 0x74, 0xe4, 0x4f, - 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x10, 0x51, 0x65, 0x62, 0xcb, 0x00, 0xe5, 0x51, 0x7b, 0x76, 0x63, 0xf7, 0x61, 0x3b, - 0x28, 0x28, 0xde, 0xd1, 0x19, 0xf5, 0xf9, 0x67, 0x8d, 0x9f, 0x89, 0x26, 0xe5, 0xf0, 0x1d, 0x3d, 0x74, 0x35, 0xee, - 0xca, 0xa0, 0x87, 0xab, 0x83, 0xbe, 0x67, 0x53, 0x71, 0x75, 0xd3, 0xb6, 0x51, 0x85, 0xa7, 0xba, 0x36, 0x26, 0x97, - 0x2d, 0x6c, 0x4b, 0x60, 0x3c, 0x4a, 0xe3, 0x90, 0x66, 0xc4, 0xa6, 0xee, 0xc4, 0xb5, 0x1e, 0xb7, 0xdb, 0x6d, 0xdc, - 0x3c, 0x38, 0x6c, 0xb7, 0xf1, 0xe1, 0xc3, 0x36, 0x6e, 0xc2, 0x1f, 0xd7, 0x75, 0x57, 0x60, 0xb8, 0x2b, 0x6a, 0xdb, - 0x69, 0x67, 0x74, 0xaa, 0x00, 0xbc, 0x33, 0xac, 0x58, 0xed, 0x09, 0xb8, 0x60, 0x5a, 0xed, 0x7b, 0x29, 0xd9, 0xd4, - 0x05, 0x07, 0x2a, 0x1d, 0x55, 0xf8, 0x0b, 0xb3, 0x2a, 0x68, 0x4a, 0xe5, 0xc5, 0x7f, 0x2f, 0x14, 0x21, 0x78, 0xd6, - 0x29, 0xdc, 0x5e, 0x2a, 0xe2, 0xa5, 0x90, 0x0a, 0x04, 0x1f, 0x48, 0xe3, 0x3e, 0x4b, 0xe0, 0xdb, 0x59, 0x3a, 0x6a, - 0xaa, 0x19, 0x55, 0xb6, 0x92, 0x74, 0xfb, 0x40, 0x86, 0xa5, 0x37, 0x11, 0xc4, 0xe8, 0x01, 0xc2, 0xfe, 0x7d, 0x1a, - 0xa8, 0x15, 0x84, 0xfa, 0xc1, 0x7d, 0xea, 0x6b, 0xec, 0x8f, 0x1e, 0x88, 0xe4, 0xa4, 0x9d, 0x68, 0xb9, 0xdc, 0xf1, - 0x97, 0xcb, 0x9d, 0xe0, 0xfe, 0x33, 0x94, 0xcb, 0xab, 0x4f, 0x41, 0xc0, 0xcd, 0x9f, 0x12, 0xe8, 0x17, 0x50, 0xee, - 0x45, 0x58, 0x82, 0x24, 0x9f, 0x7c, 0xac, 0x06, 0x94, 0x8f, 0x41, 0xb1, 0x82, 0x94, 0x90, 0x44, 0xd2, 0x3e, 0x5f, - 0x2e, 0x15, 0xf1, 0xe3, 0x39, 0xf1, 0xcb, 0xa2, 0x8e, 0x8d, 0x67, 0x24, 0x28, 0x1f, 0x6d, 0x01, 0xf2, 0x4c, 0x71, - 0xa9, 0x0a, 0xe2, 0x6b, 0x3f, 0x4b, 0x4c, 0x80, 0x5f, 0xa7, 0x96, 0x1a, 0xd6, 0x9a, 0x65, 0xe9, 0x15, 0x83, 0xe4, - 0x97, 0x95, 0x81, 0xa7, 0x04, 0x2e, 0xfe, 0xea, 0x99, 0xa1, 0x70, 0xa3, 0x83, 0xf7, 0x9a, 0xcf, 0xc2, 0x2d, 0x93, - 0xe5, 0x04, 0xbd, 0x50, 0xcd, 0xcd, 0x9b, 0xeb, 0x69, 0xbd, 0xf3, 0xaf, 0xbd, 0x99, 0x7e, 0x78, 0x26, 0xf3, 0x6c, - 0xbc, 0x69, 0x79, 0xb2, 0xe6, 0x2d, 0x79, 0x0d, 0xb1, 0x1f, 0x5b, 0xf3, 0x6d, 0xb8, 0x67, 0x53, 0xf2, 0xb8, 0x77, - 0x2f, 0xcf, 0xa8, 0x9f, 0x05, 0xd1, 0x5b, 0x3f, 0xf3, 0xa7, 0x79, 0x6f, 0xac, 0x6f, 0xf1, 0xd2, 0x14, 0x70, 0x3e, - 0x16, 0x99, 0x4e, 0x49, 0x70, 0x6b, 0xe3, 0x10, 0xe1, 0xea, 0xbd, 0x84, 0x40, 0xfa, 0xb9, 0x6d, 0x3c, 0x37, 0x5f, - 0xc1, 0x3a, 0xdb, 0x78, 0x8a, 0xb0, 0x4c, 0x20, 0x7a, 0xfb, 0x47, 0xa6, 0x0e, 0x61, 0xc8, 0x75, 0xf1, 0xc6, 0x6e, - 0xf5, 0x95, 0x3b, 0x9d, 0x4c, 0xf4, 0x7e, 0x25, 0x99, 0x68, 0x03, 0x1a, 0xad, 0x8c, 0xe6, 0xb3, 0x34, 0xc9, 0xa9, - 0x8d, 0xdf, 0x43, 0x3b, 0x79, 0x15, 0xb3, 0xd9, 0x70, 0x8d, 0xe6, 0xca, 0xa6, 0xe2, 0x8d, 0x6c, 0x07, 0x41, 0x9d, - 0xf7, 0xdf, 0x97, 0x71, 0x7c, 0x1d, 0xdf, 0x11, 0x89, 0xe8, 0x8c, 0x6e, 0xc9, 0x95, 0xcd, 0xe9, 0x27, 0x73, 0x65, - 0xe3, 0x7b, 0xe5, 0xca, 0xe6, 0xf4, 0x8f, 0xce, 0x95, 0x65, 0xd4, 0xc8, 0x95, 0x05, 0x39, 0xf7, 0xf5, 0xbd, 0x52, - 0x2e, 0x75, 0x26, 0x5c, 0x7a, 0x9d, 0x93, 0x8e, 0x8a, 0x81, 0xc4, 0xe9, 0x04, 0xf2, 0x2d, 0xff, 0xf1, 0xe9, 0x93, - 0x71, 0x3a, 0x31, 0x93, 0x27, 0xe1, 0xc3, 0x24, 0x40, 0x76, 0x38, 0x25, 0x0b, 0xfb, 0xa7, 0x9b, 0xce, 0x93, 0x61, - 0xa7, 0xb7, 0xdf, 0x99, 0xda, 0x9e, 0x0d, 0x4e, 0x47, 0x51, 0xd0, 0xee, 0xed, 0xef, 0x43, 0xc1, 0xb5, 0x51, 0xd0, - 0x85, 0x02, 0x66, 0x14, 0x1c, 0x42, 0x41, 0x60, 0x14, 0x3c, 0x84, 0x82, 0xd0, 0x28, 0x78, 0x04, 0x05, 0x57, 0x76, - 0x31, 0x64, 0x65, 0x42, 0xf0, 0x23, 0x24, 0x6e, 0x30, 0xdc, 0x49, 0xeb, 0xa7, 0xb7, 0x23, 0xa2, 0xab, 0x3c, 0x2a, - 0x6f, 0x7e, 0x68, 0x1e, 0xe8, 0x8b, 0x0a, 0x2f, 0xbe, 0xb8, 0x00, 0xd6, 0x0a, 0x17, 0xb1, 0x60, 0x88, 0x49, 0xca, - 0x9a, 0xfb, 0xfa, 0xb5, 0xed, 0x95, 0x59, 0xb3, 0x6d, 0xdc, 0xd5, 0x79, 0xb3, 0x9e, 0x8d, 0x04, 0x5f, 0x92, 0x2f, - 0x0e, 0x1b, 0xa1, 0xea, 0x16, 0xee, 0x00, 0xac, 0x2e, 0xe0, 0xdc, 0x47, 0x78, 0xaa, 0x15, 0x20, 0xea, 0xc0, 0x07, - 0x18, 0xde, 0xb3, 0x29, 0xd5, 0xfb, 0x45, 0x0f, 0x60, 0x89, 0xcc, 0xe2, 0x5e, 0x54, 0x29, 0x46, 0x6f, 0xf1, 0xb8, - 0xba, 0xf3, 0xf5, 0x3d, 0x91, 0x77, 0xe8, 0xa5, 0x58, 0x86, 0xb9, 0x66, 0x98, 0xfb, 0x13, 0x0f, 0x52, 0x28, 0x21, - 0x63, 0xc4, 0x1b, 0x13, 0x42, 0xda, 0x83, 0xb9, 0xf7, 0x16, 0x5f, 0x47, 0x34, 0xf1, 0xa6, 0x45, 0xaf, 0x5c, 0x7f, - 0x99, 0xd2, 0xf9, 0xbe, 0xbc, 0x28, 0x5c, 0xd0, 0x44, 0xf5, 0x56, 0x42, 0xd9, 0x2c, 0x69, 0x67, 0x4b, 0xce, 0x9f, - 0xa1, 0xec, 0x8c, 0xe3, 0xf4, 0xba, 0x09, 0xe2, 0x7e, 0x63, 0x1e, 0x20, 0xcc, 0xad, 0xcc, 0x03, 0x7c, 0x09, 0xb0, - 0x96, 0x4f, 0xef, 0xfd, 0x49, 0xf9, 0xfb, 0x15, 0xcd, 0x73, 0x7f, 0xa2, 0x6a, 0x6e, 0xcf, 0xfb, 0x13, 0x20, 0x9a, - 0x39, 0x7f, 0x1a, 0x08, 0x48, 0xce, 0x03, 0x84, 0x40, 0x40, 0x57, 0xe5, 0xea, 0xc1, 0xcc, 0xeb, 0x69, 0x7e, 0x02, - 0x55, 0xf5, 0x22, 0xee, 0x4f, 0xaa, 0x82, 0xe3, 0x59, 0x46, 0x55, 0x02, 0x21, 0x60, 0xb1, 0x38, 0x6e, 0x41, 0x81, - 0x7c, 0xbd, 0x25, 0x9d, 0x4f, 0x73, 0x97, 0xed, 0x49, 0x7d, 0x96, 0x4e, 0xe7, 0x33, 0x4f, 0xa6, 0x94, 0xc7, 0x52, - 0xd6, 0x33, 0xf2, 0xbe, 0xec, 0x04, 0xf0, 0x9f, 0x3a, 0x78, 0xf1, 0xe5, 0x78, 0x3c, 0xbe, 0x33, 0xbd, 0xef, 0xcb, - 0x70, 0x4c, 0xbb, 0xf4, 0xb0, 0x07, 0xa7, 0x16, 0x9a, 0x2a, 0x11, 0xad, 0x53, 0x08, 0xdc, 0x2d, 0xee, 0x57, 0x19, - 0x72, 0xd6, 0x78, 0xb4, 0xb8, 0x7f, 0xaa, 0x5f, 0x31, 0xcb, 0xe8, 0x62, 0xea, 0x67, 0x13, 0x96, 0x78, 0xed, 0xc2, - 0xbd, 0x5a, 0x28, 0x50, 0x8f, 0x8e, 0x8e, 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x51, 0x4e, 0xa3, - 0xdd, 0x1e, 0x8f, 0x0b, 0x97, 0xe9, 0x82, 0xfd, 0x6e, 0x10, 0xee, 0x77, 0x0b, 0xf7, 0xda, 0xa8, 0x51, 0xb8, 0x54, - 0x3d, 0x65, 0x34, 0xac, 0x1d, 0x7d, 0x78, 0xd4, 0x6e, 0x17, 0xae, 0x24, 0xb4, 0x05, 0xc4, 0xe4, 0xe4, 0x4f, 0xcf, - 0x9f, 0xf3, 0xb4, 0xb8, 0x28, 0x8a, 0x5e, 0xcc, 0x9d, 0xe1, 0xae, 0xba, 0x56, 0x52, 0x7e, 0x87, 0xb1, 0x40, 0x23, - 0xfc, 0xb5, 0x99, 0x39, 0x07, 0xc4, 0x2c, 0x32, 0xe6, 0x62, 0x9d, 0x58, 0x57, 0x7b, 0x0d, 0x94, 0x25, 0x5e, 0x7f, - 0x4d, 0xe2, 0x2a, 0xa1, 0x0e, 0xf8, 0x18, 0xd4, 0x94, 0xb7, 0x9f, 0x27, 0xdb, 0xa4, 0x47, 0xf6, 0x69, 0xe9, 0x71, - 0x79, 0x1f, 0xe1, 0x91, 0xfd, 0xe1, 0xc2, 0x23, 0x31, 0x85, 0x87, 0x64, 0x1d, 0xd7, 0x9c, 0xd8, 0x41, 0x44, 0x83, - 0x8f, 0x97, 0xe9, 0x4d, 0x13, 0xb6, 0x44, 0x66, 0x0b, 0xb1, 0x72, 0xf5, 0x5b, 0x33, 0xf9, 0x75, 0x67, 0xc6, 0x47, - 0x1c, 0x85, 0x8e, 0xff, 0x26, 0x21, 0xf6, 0x1b, 0x1d, 0xd8, 0x93, 0x25, 0xe3, 0x31, 0xb1, 0xdf, 0x8c, 0xc7, 0xb6, - 0xbe, 0x1c, 0xc7, 0xe7, 0x54, 0xd4, 0x7a, 0x5d, 0x2b, 0x11, 0xb5, 0xc0, 0xd0, 0xaf, 0xca, 0xcc, 0x02, 0x95, 0x77, - 0x67, 0xe6, 0xd8, 0xa9, 0x37, 0x21, 0xcb, 0x61, 0xab, 0xc1, 0xb7, 0x25, 0xeb, 0x97, 0xf3, 0x27, 0xb5, 0x2f, 0x29, - 0x95, 0x00, 0x6f, 0xf8, 0xfc, 0xd3, 0xea, 0xcd, 0x70, 0x13, 0xaa, 0x55, 0xfc, 0x27, 0xb7, 0x2f, 0x42, 0xe7, 0x9a, - 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0x95, 0x5b, 0x1f, 0x24, 0x8c, 0x84, 0x98, 0xd3, 0x2a, 0x78, 0x3a, 0x99, 0xc4, 0xe2, - 0x30, 0x49, 0xcd, 0xe0, 0x96, 0xcd, 0x07, 0xb5, 0xf9, 0x7a, 0x66, 0x43, 0xf5, 0x79, 0x0d, 0xf1, 0xbd, 0x61, 0x79, - 0x5a, 0xf8, 0x4a, 0x7d, 0x78, 0x56, 0xc4, 0x04, 0x17, 0x8a, 0xc7, 0x2f, 0xe4, 0x19, 0x53, 0x8e, 0x59, 0x28, 0x9b, - 0xb3, 0xb0, 0x28, 0xd4, 0xe9, 0xfc, 0x90, 0xe5, 0x33, 0xd0, 0x9e, 0x64, 0x4b, 0xfa, 0x29, 0x16, 0x9e, 0x5f, 0x1b, - 0xc9, 0x6d, 0xb5, 0xe5, 0x2a, 0xb4, 0x9d, 0x26, 0xb3, 0x85, 0xae, 0x79, 0x61, 0x2b, 0x93, 0x4d, 0x23, 0xd1, 0xb6, - 0x24, 0x3e, 0x65, 0xda, 0x9d, 0x31, 0x43, 0xc8, 0xfc, 0x29, 0x17, 0x44, 0xbf, 0xd2, 0x05, 0x85, 0x69, 0x65, 0x89, - 0x37, 0x12, 0x5b, 0x22, 0x55, 0x2c, 0x9f, 0xf9, 0x89, 0x36, 0xe6, 0x24, 0x3f, 0xd8, 0x5d, 0x54, 0x2b, 0x5f, 0xd8, - 0x1a, 0x6c, 0x49, 0xbc, 0xfd, 0xe3, 0x16, 0x34, 0xe8, 0x5b, 0x35, 0xd0, 0x93, 0xb5, 0x0c, 0xb3, 0xbb, 0xf3, 0xae, - 0x3f, 0x5e, 0xb8, 0xf9, 0x35, 0x76, 0xf3, 0x6b, 0xeb, 0xab, 0x45, 0xf3, 0x9a, 0x5e, 0x7e, 0x64, 0xbc, 0xc9, 0xfd, - 0x59, 0x13, 0xbc, 0xa7, 0x22, 0x33, 0x44, 0xb1, 0x67, 0xa1, 0xa3, 0x4b, 0xd3, 0xaf, 0x37, 0xcf, 0x21, 0x3d, 0x5b, - 0x98, 0x51, 0x5e, 0x92, 0x26, 0xb4, 0x57, 0x3f, 0xbe, 0x67, 0x66, 0x18, 0x6b, 0x6c, 0x8d, 0x16, 0x29, 0xa4, 0x73, - 0xf3, 0x5b, 0xaf, 0xad, 0xd8, 0x7a, 0x5b, 0xa7, 0x0f, 0xb7, 0x37, 0xd6, 0xf7, 0x14, 0x72, 0x1b, 0x42, 0x7a, 0x65, - 0xeb, 0xf9, 0xcf, 0xdb, 0xf2, 0xbb, 0x3f, 0x75, 0x98, 0x0d, 0xf2, 0x49, 0xf4, 0xff, 0xc6, 0x29, 0xc0, 0xd5, 0x62, - 0x71, 0x98, 0xed, 0x3e, 0x90, 0x79, 0xfe, 0x98, 0xd3, 0x0c, 0xdf, 0xa7, 0xe6, 0xa5, 0xb8, 0x77, 0x62, 0x01, 0x62, - 0xc6, 0xeb, 0x1c, 0xd5, 0x53, 0xb1, 0xef, 0xee, 0xfe, 0xee, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x1e, 0x56, 0xdb, 0xee, - 0xc1, 0x46, 0x88, 0xfd, 0x5b, 0x8f, 0x25, 0x42, 0xe6, 0x5d, 0x42, 0x52, 0x48, 0x6f, 0x96, 0xaa, 0x53, 0x99, 0x19, - 0x8d, 0xc5, 0xa7, 0xd7, 0xd5, 0x52, 0xec, 0x3f, 0x9c, 0xdd, 0xe8, 0xd5, 0xe8, 0xac, 0x9c, 0xb6, 0xfc, 0x43, 0x0f, - 0x55, 0x6e, 0x3f, 0xc5, 0x59, 0x3f, 0x18, 0x78, 0x38, 0xbb, 0xe9, 0x49, 0x41, 0xdb, 0xcc, 0x24, 0x54, 0xed, 0xd9, - 0x8d, 0x79, 0xac, 0xb4, 0xea, 0xc8, 0x72, 0xf7, 0x73, 0x8b, 0xfa, 0x39, 0xed, 0xc1, 0x97, 0xa6, 0x58, 0xe0, 0xc7, - 0x4a, 0x98, 0x4f, 0x59, 0x18, 0xc6, 0xb4, 0xa7, 0xe5, 0xb5, 0xd5, 0x79, 0x08, 0xa7, 0x32, 0xcd, 0x25, 0xab, 0xaf, - 0x8a, 0x81, 0xbc, 0x12, 0x4f, 0xfe, 0x65, 0x9e, 0xc6, 0xf0, 0x9d, 0xc7, 0x8d, 0xe8, 0x54, 0xc7, 0x15, 0xdb, 0x15, - 0xf2, 0xc4, 0xef, 0xfa, 0x5c, 0x0e, 0xdb, 0x7f, 0xea, 0x89, 0x05, 0x6f, 0xf7, 0x78, 0x3a, 0xf3, 0x9a, 0xfb, 0xf5, - 0x89, 0xc0, 0xab, 0x72, 0x0a, 0x78, 0xc3, 0xb4, 0x30, 0x48, 0x2b, 0xc9, 0xa7, 0x2d, 0xb7, 0xa3, 0xca, 0x44, 0x07, - 0x60, 0x84, 0x96, 0x45, 0x45, 0x7d, 0x32, 0xff, 0x98, 0xdd, 0xf2, 0x78, 0xf3, 0x6e, 0x79, 0xac, 0x77, 0xcb, 0xdd, - 0x14, 0xfb, 0xe5, 0xb8, 0x03, 0xff, 0xf5, 0xaa, 0x09, 0x79, 0x6d, 0x6b, 0x7f, 0x76, 0x63, 0x81, 0x9e, 0xd6, 0xec, - 0xce, 0x6e, 0xe4, 0xa1, 0x5a, 0x48, 0x5c, 0x6b, 0xc3, 0x31, 0x53, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, 0x5e, - 0x75, 0x0e, 0xe0, 0x1d, 0xb4, 0x3a, 0x5c, 0x7f, 0xd7, 0xbd, 0x7b, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, 0x63, - 0xe4, 0x72, 0xff, 0xf2, 0x92, 0x86, 0xde, 0x38, 0x0d, 0xe6, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdc, 0xd2, - 0x2b, 0xfd, 0xe8, 0xa6, 0xf2, 0x88, 0xaf, 0xee, 0x61, 0x51, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, 0x7b, - 0xb0, 0x61, 0x13, 0xfc, 0x9b, 0xac, 0xcd, 0xc6, 0xc9, 0xfc, 0x5e, 0x64, 0xdc, 0x89, 0x84, 0xcf, 0xc2, 0x81, 0xb9, - 0x86, 0xed, 0xa3, 0xcd, 0xe0, 0x0e, 0xf5, 0x48, 0x23, 0x2d, 0x14, 0x94, 0xdc, 0x09, 0xe9, 0xd8, 0x9f, 0xc7, 0xfc, - 0xee, 0x5e, 0xb7, 0x51, 0xc6, 0x5a, 0xaf, 0x77, 0x30, 0xf4, 0xaa, 0xee, 0x3d, 0xb9, 0xf4, 0x97, 0x8f, 0x0f, 0xe0, - 0x3f, 0x79, 0xf8, 0xe5, 0xb2, 0xd2, 0xd5, 0xa5, 0xd5, 0x0b, 0xba, 0xfa, 0x55, 0x4d, 0x19, 0x97, 0x22, 0x5c, 0xe8, - 0xe3, 0xf7, 0xad, 0x0d, 0x5a, 0xe5, 0xbd, 0xaa, 0x2b, 0x2d, 0xeb, 0xb3, 0x6a, 0x7f, 0x5e, 0xe7, 0xf7, 0xac, 0x1b, - 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x7a, 0x7e, 0xad, 0xb2, 0xc6, 0xb8, 0xa8, 0x7f, 0x45, 0x2e, 0x4b, 0x13, 0x45, - 0xa6, 0xa2, 0x82, 0x95, 0x72, 0x25, 0xad, 0x94, 0x94, 0x92, 0x8b, 0xe3, 0xc1, 0xcd, 0x34, 0xb6, 0xae, 0xe4, 0xfd, - 0x38, 0xc4, 0xee, 0xb8, 0x6d, 0xdb, 0x12, 0x4e, 0x3a, 0xf8, 0x4c, 0x97, 0xfd, 0xe1, 0xfd, 0xd7, 0xcd, 0x23, 0x7b, - 0x00, 0x9a, 0xd6, 0xd5, 0x44, 0x68, 0x76, 0x2f, 0xfd, 0x5b, 0x9a, 0x9d, 0x77, 0x95, 0x0b, 0x5e, 0xe6, 0x8b, 0x8b, - 0x32, 0xab, 0x6b, 0x5b, 0x37, 0xd3, 0x38, 0xc9, 0x89, 0x1d, 0x71, 0x3e, 0xf3, 0x5a, 0xad, 0xeb, 0xeb, 0x6b, 0xf7, - 0x7a, 0xdf, 0x4d, 0xb3, 0x49, 0xab, 0xdb, 0x6e, 0xb7, 0xe1, 0x8b, 0x1f, 0xb6, 0x75, 0xc5, 0xe8, 0xf5, 0x93, 0xf4, - 0x86, 0xd8, 0x6d, 0xab, 0x6d, 0x75, 0xba, 0x47, 0x56, 0xa7, 0x7b, 0xe0, 0x3e, 0x3c, 0xb2, 0xfb, 0x5f, 0x58, 0xd6, - 0x71, 0x48, 0xc7, 0x39, 0xfc, 0xb0, 0xac, 0x63, 0xa1, 0x78, 0xc9, 0xdf, 0x96, 0xe5, 0x06, 0x71, 0xde, 0xec, 0x58, - 0x0b, 0xf5, 0x68, 0x59, 0x70, 0x8b, 0x90, 0x67, 0x7d, 0x39, 0xee, 0x8e, 0x0f, 0xc6, 0x8f, 0x7b, 0xaa, 0xb8, 0xf8, - 0xa2, 0x56, 0x1d, 0xcb, 0x7f, 0xbb, 0x46, 0xb3, 0x9c, 0x67, 0xe9, 0x47, 0xaa, 0x5c, 0xfb, 0x16, 0x88, 0x9e, 0x8d, - 0x4d, 0xbb, 0xeb, 0x23, 0x75, 0x8e, 0x2e, 0x83, 0x71, 0xb7, 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0x1e, 0xb7, 0x34, - 0xe8, 0xc7, 0x26, 0x9a, 0x3a, 0xcd, 0x4d, 0x88, 0xea, 0xd8, 0x6a, 0x8e, 0x13, 0x3d, 0xbf, 0x63, 0x38, 0xb4, 0xae, - 0x75, 0x55, 0x01, 0x81, 0x6d, 0x85, 0xc4, 0x7e, 0xd5, 0xe9, 0x1e, 0xe1, 0x4e, 0xe7, 0xa1, 0xfb, 0xf0, 0x28, 0x68, - 0xe3, 0x03, 0xf7, 0xa0, 0xb9, 0xef, 0x3e, 0xc4, 0x47, 0xcd, 0x23, 0x7c, 0xf4, 0xfc, 0x28, 0x68, 0x1e, 0xb8, 0x07, - 0xb8, 0xdd, 0x3c, 0x82, 0xc2, 0xe6, 0x51, 0xf3, 0xe8, 0xaa, 0x79, 0x70, 0x14, 0xb4, 0x45, 0x69, 0xd7, 0x3d, 0x3c, - 0x6c, 0x76, 0xda, 0xee, 0xe1, 0x21, 0x3e, 0x74, 0x1f, 0x3e, 0x6c, 0x76, 0xf6, 0xdd, 0x87, 0x0f, 0x5f, 0x1e, 0x1e, - 0xb9, 0xfb, 0xf0, 0x6e, 0x7f, 0x3f, 0xd8, 0x77, 0x3b, 0x9d, 0x26, 0xfc, 0xc1, 0x47, 0x6e, 0x57, 0xfe, 0xe8, 0x74, - 0xdc, 0xfd, 0x0e, 0x6e, 0xc7, 0x87, 0x5d, 0xf7, 0xe1, 0x63, 0x2c, 0xfe, 0x8a, 0x6a, 0x58, 0xfc, 0x81, 0x6e, 0xf0, - 0x63, 0xb7, 0xfb, 0x50, 0xfe, 0x12, 0x1d, 0x5e, 0x1d, 0x1c, 0xfd, 0x68, 0xb7, 0xb6, 0xce, 0xa1, 0x23, 0xe7, 0x70, - 0x74, 0xe8, 0xee, 0xef, 0xe3, 0x83, 0x8e, 0x7b, 0xb4, 0x1f, 0x35, 0x0f, 0xba, 0xee, 0xc3, 0x47, 0x41, 0xb3, 0xe3, - 0x3e, 0x7a, 0x84, 0xdb, 0xcd, 0x7d, 0xb7, 0x8b, 0x3b, 0xee, 0xc1, 0xbe, 0xf8, 0xb1, 0xef, 0x76, 0xaf, 0x1e, 0x3d, - 0x76, 0x1f, 0x1e, 0x46, 0x0f, 0xdd, 0x83, 0x6f, 0x0f, 0x8e, 0xdc, 0xee, 0x7e, 0xb4, 0xff, 0xd0, 0xed, 0x3e, 0xba, - 0x7a, 0xe8, 0x1e, 0x44, 0xcd, 0xee, 0xc3, 0x3b, 0x5b, 0x76, 0xba, 0x2e, 0xe0, 0x48, 0xbc, 0x86, 0x17, 0x58, 0xbd, - 0x80, 0xff, 0x23, 0xd1, 0xf6, 0xdf, 0xb0, 0x9b, 0x7c, 0xbd, 0xe9, 0x63, 0xf7, 0xe8, 0x51, 0x20, 0xab, 0x43, 0x41, - 0x53, 0xd7, 0x80, 0x26, 0x57, 0x4d, 0x39, 0xac, 0xe8, 0xae, 0xa9, 0x3b, 0xd2, 0xff, 0xab, 0xc1, 0xae, 0x9a, 0x30, - 0xb0, 0x1c, 0xf7, 0xdf, 0xb5, 0x9f, 0x72, 0xc9, 0x8f, 0x5b, 0x13, 0x49, 0xfa, 0x93, 0xfe, 0x17, 0xf2, 0x73, 0x3e, - 0x5f, 0x5c, 0x60, 0x7f, 0x9b, 0xe3, 0x23, 0xfe, 0xb4, 0xe3, 0x23, 0xa2, 0xf7, 0xf1, 0x7c, 0xc4, 0x7f, 0xb8, 0xe7, - 0xc3, 0x5f, 0x75, 0x9b, 0xdf, 0xf0, 0x35, 0x07, 0xc7, 0xaa, 0x55, 0xfc, 0x82, 0x3b, 0xc3, 0x14, 0x3e, 0x1d, 0x5d, - 0xf4, 0x6e, 0x38, 0x89, 0xa8, 0xe9, 0x07, 0x4a, 0x81, 0xc5, 0xde, 0x70, 0xc9, 0x63, 0x83, 0x6d, 0x08, 0x09, 0x3f, - 0x8d, 0x90, 0xef, 0xee, 0x83, 0x8f, 0xf0, 0x0f, 0xc7, 0x47, 0x60, 0xe2, 0xa3, 0xe6, 0xc9, 0x17, 0x9e, 0x06, 0xe1, - 0x29, 0x38, 0x13, 0xcf, 0x0e, 0xdc, 0x9a, 0xd1, 0xb0, 0x5b, 0xf4, 0x4a, 0x44, 0xee, 0x64, 0x70, 0xfd, 0xf9, 0xe7, - 0x04, 0x1d, 0xe4, 0x15, 0x39, 0xc4, 0x56, 0x6e, 0x99, 0x99, 0x90, 0x3a, 0xea, 0xa1, 0x14, 0x4a, 0x5d, 0xb7, 0xed, - 0xb6, 0x4b, 0x97, 0x0e, 0x5c, 0x8b, 0x44, 0x16, 0x29, 0xf7, 0xbd, 0x9d, 0x0e, 0x8e, 0xd3, 0x09, 0x5c, 0x96, 0x24, - 0x3e, 0x1f, 0x07, 0x27, 0x1e, 0x02, 0xf9, 0xe5, 0x3e, 0x48, 0x9f, 0x50, 0x8e, 0x1e, 0x3f, 0xfb, 0xf8, 0x37, 0x08, - 0x62, 0xea, 0x98, 0xc4, 0x14, 0xbc, 0x1d, 0xaf, 0x68, 0xc8, 0x7c, 0xc7, 0x76, 0x66, 0x19, 0x1d, 0xd3, 0x2c, 0x6f, - 0xd6, 0xee, 0xeb, 0x11, 0x57, 0xf5, 0x20, 0x5b, 0x41, 0x38, 0xce, 0xe0, 0x73, 0x48, 0x64, 0xa8, 0xfc, 0x8d, 0xb6, - 0x32, 0xc0, 0xec, 0x02, 0xeb, 0x92, 0x0c, 0x64, 0x6d, 0xa5, 0xb4, 0xd9, 0x52, 0x6b, 0xeb, 0xb8, 0xdd, 0x43, 0x64, - 0x89, 0x62, 0xf8, 0xd0, 0xcc, 0x0f, 0x4e, 0x73, 0xbf, 0xfd, 0x27, 0x64, 0x34, 0x2b, 0x3b, 0x1a, 0x29, 0x77, 0x5b, - 0x52, 0x7e, 0x8e, 0x70, 0x25, 0xec, 0x6a, 0x4b, 0x8a, 0xf8, 0x52, 0xce, 0xdd, 0x46, 0xbd, 0x44, 0x25, 0xcd, 0xc9, - 0x2b, 0x01, 0xc7, 0x6c, 0xe2, 0x18, 0xd7, 0x4d, 0x24, 0xf2, 0x43, 0x36, 0x70, 0x5b, 0x3d, 0x42, 0x45, 0x55, 0x25, - 0x41, 0x0b, 0x11, 0x6d, 0x61, 0x89, 0x95, 0x2c, 0x97, 0x4e, 0x02, 0x2e, 0x72, 0x62, 0xe0, 0x14, 0x9e, 0x51, 0x0d, - 0xc9, 0x09, 0x2e, 0x01, 0x12, 0x08, 0x26, 0x89, 0xfc, 0xb7, 0x2a, 0xd6, 0x3f, 0x94, 0xe3, 0xcb, 0x8d, 0xfd, 0x64, - 0x02, 0x54, 0xe8, 0x27, 0x93, 0x35, 0xb7, 0x9a, 0x0c, 0x18, 0xad, 0x94, 0x56, 0x5d, 0x55, 0xee, 0xb3, 0xfc, 0xc9, - 0xed, 0x7b, 0x75, 0xe3, 0xb5, 0x0d, 0xde, 0x69, 0x11, 0xdf, 0xa8, 0xbe, 0xce, 0xd3, 0x20, 0x0f, 0x8e, 0xa7, 0x94, - 0xfb, 0xf2, 0xb0, 0x1a, 0xe8, 0x13, 0x90, 0xcb, 0x62, 0x29, 0x6b, 0x54, 0x05, 0xf5, 0x89, 0x3c, 0xcc, 0x2f, 0x45, - 0x3d, 0xb6, 0xd4, 0x55, 0x71, 0x4d, 0xb1, 0x34, 0xa4, 0x83, 0xa5, 0x3f, 0x26, 0xf0, 0xc5, 0x71, 0x64, 0x92, 0xa4, - 0x76, 0xff, 0x41, 0x99, 0xeb, 0xb2, 0x6d, 0x11, 0x62, 0x96, 0x7c, 0x1c, 0x66, 0x34, 0xfe, 0x27, 0xf2, 0x80, 0x05, - 0x69, 0xf2, 0x60, 0x64, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, 0x8e, 0xc9, 0x03, 0x90, 0xf1, 0x9e, 0xb0, 0x3e, 0x80, 0x11, - 0x36, 0x6e, 0xa6, 0x31, 0x16, 0x1a, 0xd3, 0x3d, 0x14, 0x22, 0x09, 0xae, 0xdd, 0x3d, 0xb4, 0x2d, 0x69, 0x13, 0x8b, - 0xdf, 0x7d, 0x29, 0x4e, 0x85, 0x12, 0x60, 0x75, 0xba, 0xee, 0x61, 0xd4, 0x75, 0x1f, 0x5f, 0x3d, 0x72, 0x8f, 0xa2, - 0xce, 0xa3, 0xab, 0x26, 0xfc, 0xdb, 0x75, 0x1f, 0xc7, 0xcd, 0xae, 0xfb, 0x18, 0xfe, 0xff, 0xf6, 0xc0, 0x3d, 0x8c, - 0x9a, 0x1d, 0xf7, 0xe8, 0x6a, 0xdf, 0xdd, 0x7f, 0xd9, 0xe9, 0xba, 0xfb, 0x56, 0xc7, 0x92, 0xed, 0x80, 0x5d, 0x4b, - 0xee, 0xfc, 0x60, 0x65, 0x43, 0x6c, 0x08, 0xc6, 0xc9, 0x03, 0x77, 0x36, 0x16, 0x67, 0xa4, 0xcd, 0xfd, 0xa9, 0x9c, - 0x75, 0x4f, 0xfd, 0x0c, 0xbe, 0x6c, 0x5a, 0xdf, 0xbb, 0xb5, 0x77, 0xb8, 0xc6, 0x2f, 0x36, 0x0c, 0x31, 0x13, 0x11, - 0x70, 0xf3, 0xae, 0x35, 0xb8, 0xa8, 0x4c, 0x7c, 0x08, 0x4a, 0xdf, 0x87, 0xbf, 0x9d, 0xb4, 0x65, 0x45, 0x7d, 0xe7, - 0xbe, 0x60, 0x16, 0x4c, 0x7c, 0x72, 0x4f, 0x0c, 0xf2, 0x22, 0x2c, 0x56, 0xc7, 0x87, 0x73, 0x7f, 0x59, 0x6a, 0x5c, - 0x37, 0x47, 0xab, 0x20, 0x7f, 0xc8, 0xe0, 0x82, 0xc0, 0xa2, 0xd0, 0xa0, 0xd7, 0xdc, 0xb4, 0x15, 0x96, 0x04, 0xbf, - 0xa0, 0xf9, 0xc0, 0x86, 0x22, 0xdb, 0xb3, 0x85, 0x8b, 0xcf, 0x2e, 0xbf, 0xee, 0x5a, 0x12, 0x76, 0x55, 0x80, 0xc5, - 0xed, 0x0f, 0xb0, 0x6b, 0x01, 0x3f, 0x36, 0xda, 0xdb, 0xdb, 0xba, 0x5f, 0x84, 0x02, 0x09, 0x73, 0xad, 0x3e, 0x0a, - 0x69, 0xb2, 0x22, 0xdb, 0x44, 0x74, 0xd9, 0xaf, 0x40, 0x21, 0x52, 0x78, 0xba, 0xa4, 0x3e, 0x77, 0xfd, 0x44, 0x9e, - 0x20, 0x30, 0x18, 0x16, 0xee, 0xd0, 0x7d, 0x54, 0xa4, 0xdc, 0x97, 0x49, 0x61, 0xe6, 0x3e, 0x4f, 0xb9, 0xaf, 0x2f, - 0x4f, 0xf2, 0x79, 0xed, 0xe0, 0x7c, 0xd4, 0xed, 0xbf, 0x79, 0x7f, 0x62, 0xc9, 0xed, 0x79, 0xdc, 0x8a, 0xba, 0xfd, - 0x63, 0xe1, 0x33, 0x91, 0x61, 0x7f, 0x22, 0xc3, 0xfe, 0x96, 0xba, 0x35, 0x06, 0x22, 0x69, 0x45, 0x4b, 0x4e, 0x5b, - 0xd8, 0x0c, 0xd2, 0xdb, 0x3b, 0x9d, 0xc7, 0x9c, 0xc1, 0x47, 0x8d, 0x5a, 0x22, 0xe6, 0x2f, 0x72, 0x08, 0xf4, 0x21, - 0x54, 0xa5, 0x1d, 0x5e, 0xf2, 0x44, 0xfb, 0x86, 0xc7, 0x2c, 0xa6, 0xfa, 0xd8, 0xa9, 0xea, 0xaa, 0x4c, 0xf8, 0x59, - 0xaf, 0x9d, 0xcf, 0x2f, 0x21, 0xe9, 0x41, 0xa7, 0x17, 0x7d, 0x50, 0x0d, 0x8e, 0xc5, 0x50, 0x10, 0xb9, 0x97, 0x62, - 0x5a, 0x7f, 0xbe, 0xb5, 0xbe, 0xa4, 0x6a, 0xf6, 0x4a, 0x42, 0xc0, 0x55, 0x1d, 0xd1, 0x7e, 0xbf, 0x74, 0x17, 0x9b, - 0xef, 0x8a, 0xe3, 0x56, 0xb4, 0xdf, 0xbf, 0xf0, 0x26, 0xaa, 0xbf, 0x97, 0xe9, 0x64, 0x73, 0x5f, 0x71, 0x3a, 0x19, - 0x88, 0x73, 0xf0, 0xf2, 0x4e, 0x27, 0xad, 0xfc, 0xa6, 0xb1, 0xdd, 0x3f, 0x56, 0xca, 0x80, 0x25, 0xc2, 0xea, 0xf6, - 0x61, 0x5b, 0x1f, 0xad, 0x8f, 0xd3, 0x09, 0x6c, 0x48, 0xd9, 0xc4, 0x18, 0xa4, 0xe6, 0x71, 0x8f, 0x3a, 0xfd, 0x63, - 0xdf, 0x12, 0xbc, 0x45, 0x30, 0x8f, 0xdc, 0x6b, 0x41, 0xe3, 0x28, 0x9d, 0x52, 0x97, 0xa5, 0xad, 0x6b, 0x7a, 0xd9, - 0xf4, 0x67, 0xac, 0x72, 0x6f, 0x83, 0xd2, 0x51, 0x0e, 0x99, 0xae, 0xa4, 0x58, 0x75, 0x2b, 0x77, 0xdb, 0x01, 0xd8, - 0x3c, 0xda, 0x35, 0x27, 0x7c, 0x72, 0x06, 0x58, 0x69, 0xff, 0xb8, 0xe5, 0xaf, 0x60, 0x44, 0xf0, 0xfb, 0x42, 0x39, - 0xda, 0xc1, 0xb0, 0xb9, 0x14, 0xf9, 0x5d, 0x52, 0x1c, 0x68, 0x87, 0xbc, 0x12, 0xd4, 0x85, 0xdd, 0xff, 0xd7, 0xff, - 0xf1, 0xbf, 0x94, 0x8f, 0xfd, 0xb8, 0x15, 0x75, 0x74, 0x5f, 0x2b, 0xab, 0x52, 0x1c, 0xc3, 0x45, 0x35, 0x55, 0x50, - 0x98, 0xde, 0x34, 0x27, 0x19, 0x0b, 0x9b, 0x91, 0x1f, 0x8f, 0xed, 0xfe, 0x76, 0x6c, 0xca, 0xfc, 0xc3, 0xa6, 0x0e, - 0xa7, 0xae, 0x17, 0x01, 0xbd, 0xfe, 0xa6, 0x5b, 0x17, 0x74, 0x4a, 0x97, 0xd8, 0xda, 0xe6, 0x1d, 0x0c, 0xd5, 0xee, - 0xab, 0xdd, 0xc3, 0x90, 0xa8, 0x6f, 0x42, 0x2b, 0x0e, 0x98, 0xd4, 0xae, 0x5f, 0x28, 0x6c, 0xab, 0x0c, 0x6a, 0xfd, - 0xdf, 0xff, 0xf9, 0x5f, 0xfe, 0x9b, 0x7e, 0x84, 0x58, 0xd5, 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, - 0x85, 0xfc, 0x33, 0x15, 0xcf, 0x12, 0x4c, 0xc5, 0xaa, 0x82, 0x59, 0x92, 0xbb, 0x58, 0x70, 0xaa, 0x6d, 0xca, 0x72, - 0xce, 0x82, 0xfa, 0x85, 0x0c, 0x67, 0x62, 0x40, 0xb1, 0x33, 0x15, 0x74, 0x62, 0x87, 0x17, 0x15, 0x41, 0xd5, 0x50, - 0x2e, 0x08, 0xb7, 0x38, 0x6e, 0x01, 0xbe, 0xef, 0x77, 0x9f, 0x8c, 0x5b, 0x2e, 0xc7, 0x42, 0x93, 0x09, 0x94, 0x14, - 0x55, 0xb9, 0x05, 0xb1, 0x95, 0x05, 0x3c, 0x7a, 0x5d, 0xa3, 0x58, 0xac, 0x5e, 0xad, 0x4d, 0xef, 0xe7, 0x79, 0xce, - 0xd9, 0x18, 0x50, 0x2e, 0xfd, 0xc4, 0x22, 0x8c, 0xdd, 0x04, 0x5d, 0x31, 0xbe, 0x2d, 0x44, 0x2f, 0x92, 0x40, 0x0f, - 0x8e, 0xfe, 0x54, 0xfc, 0x79, 0x0a, 0x1a, 0x99, 0xe5, 0x4c, 0xfd, 0x1b, 0x65, 0x9e, 0x3f, 0x6c, 0xb7, 0x67, 0x37, - 0x68, 0x51, 0x8d, 0x80, 0xb7, 0x0d, 0x26, 0xe8, 0xd8, 0xec, 0x50, 0xc4, 0xbf, 0x4b, 0x37, 0x76, 0xdb, 0x02, 0x5f, - 0xb8, 0xd5, 0x2e, 0x8a, 0xaf, 0x16, 0xc2, 0x93, 0xca, 0x7e, 0x85, 0x38, 0xb5, 0x72, 0x3a, 0x5f, 0xa6, 0xe6, 0xe4, - 0x16, 0x46, 0xab, 0xae, 0x6c, 0x15, 0x75, 0xd6, 0xaf, 0x66, 0x31, 0xe3, 0xec, 0x66, 0x84, 0xfc, 0x00, 0x62, 0xde, - 0x51, 0x07, 0x47, 0xdd, 0x45, 0xd9, 0x3d, 0xe7, 0xe9, 0xd4, 0x0c, 0xac, 0x53, 0x9f, 0x06, 0x74, 0xac, 0x9d, 0xf5, - 0xea, 0xbd, 0x0c, 0x9a, 0x17, 0xd1, 0xfe, 0x86, 0xb1, 0x14, 0x48, 0x22, 0xa0, 0x6e, 0xb5, 0x8b, 0x2f, 0x61, 0x07, - 0x2e, 0xc6, 0x71, 0xea, 0x73, 0x4f, 0x10, 0x6c, 0xcf, 0x0c, 0xcf, 0xfb, 0xc0, 0x93, 0xd2, 0x85, 0x01, 0x4f, 0x4f, - 0x56, 0x05, 0xb7, 0x79, 0xfd, 0x8a, 0xc6, 0xc2, 0x15, 0xcd, 0xcd, 0xae, 0xa4, 0xd7, 0xed, 0x3b, 0x15, 0xf5, 0x7e, - 0x5e, 0x73, 0x57, 0x29, 0x81, 0xd4, 0x45, 0x9b, 0xdf, 0x4b, 0xb9, 0x2e, 0xdf, 0x7e, 0xcf, 0x1d, 0x5b, 0x80, 0x69, - 0xaf, 0xd6, 0x12, 0x85, 0x50, 0xeb, 0x39, 0xf9, 0xae, 0x34, 0x99, 0xfc, 0xd9, 0x4c, 0x54, 0x44, 0xbd, 0xe3, 0x96, - 0xd4, 0x74, 0x81, 0x7b, 0x88, 0x94, 0x0e, 0x99, 0x41, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xdc, 0x0a, 0xf8, - 0x56, 0x78, 0xff, 0xff, 0x01, 0xa2, 0x89, 0x8c, 0x0d, 0xc4, 0x97, 0x00, 0x00}; + 0x95, 0xd2, 0x3b, 0x9e, 0x56, 0x41, 0xb0, 0xd5, 0x38, 0x5f, 0xb3, 0x03, 0xbe, 0xb0, 0x91, 0x90, 0xcf, 0x39, 0xce, + 0x08, 0x48, 0xd1, 0xee, 0xc0, 0x3e, 0xce, 0xaf, 0x26, 0x7d, 0x1b, 0x62, 0x34, 0x29, 0xf9, 0x20, 0x5c, 0x43, 0x50, + 0x21, 0x22, 0xed, 0x5e, 0x74, 0x4c, 0x7b, 0x51, 0xa3, 0xa1, 0xb5, 0x68, 0x9f, 0x24, 0xc3, 0x48, 0x36, 0x0f, 0x70, + 0x88, 0xe7, 0xa4, 0xd9, 0xc1, 0x33, 0xd2, 0x16, 0x4d, 0x7a, 0xb3, 0x63, 0x5f, 0x0d, 0xb3, 0xb7, 0xe7, 0xa4, 0x6e, + 0xec, 0xe7, 0xfc, 0x05, 0xd8, 0xfb, 0x64, 0x86, 0x43, 0x92, 0xba, 0xf4, 0x86, 0x06, 0x8e, 0x8f, 0x70, 0xa8, 0x38, + 0x0d, 0xea, 0xa1, 0x19, 0x31, 0xaa, 0x81, 0x19, 0x41, 0x3e, 0x0c, 0xc2, 0x61, 0x67, 0x44, 0x08, 0xb1, 0x77, 0x9a, + 0x4d, 0x7b, 0x90, 0x92, 0x09, 0xf7, 0xa0, 0xc4, 0x50, 0x96, 0xc9, 0x14, 0x8a, 0xba, 0x46, 0x91, 0xf3, 0x86, 0xbb, + 0x9c, 0xe6, 0xdc, 0x81, 0x62, 0xf0, 0x00, 0xe4, 0x9a, 0xb0, 0xed, 0xe3, 0x96, 0xdd, 0x80, 0x52, 0x41, 0x9c, 0x08, + 0xa7, 0xe4, 0x1a, 0x79, 0xe1, 0x70, 0x7f, 0x64, 0x0a, 0x00, 0x51, 0x08, 0x83, 0x5f, 0x0f, 0xc2, 0x61, 0x5b, 0x0c, + 0xde, 0xb7, 0x07, 0x4e, 0x4a, 0x72, 0xa9, 0xa1, 0x0d, 0x72, 0xef, 0x83, 0x98, 0x2a, 0xf2, 0x14, 0x70, 0x6a, 0xdc, + 0x39, 0x69, 0x76, 0x3d, 0x67, 0x6e, 0x4e, 0xa2, 0x09, 0x83, 0x29, 0x2c, 0xe0, 0x80, 0x40, 0x7d, 0x9c, 0x12, 0x18, + 0xb1, 0x6a, 0x76, 0xed, 0xa9, 0xe7, 0x07, 0xf6, 0x83, 0xc1, 0x39, 0xf7, 0xc6, 0x5c, 0x0e, 0x7f, 0xce, 0x97, 0x4b, + 0xf8, 0x77, 0xcc, 0x07, 0x29, 0xb9, 0x16, 0x45, 0x13, 0x55, 0x34, 0x85, 0xa2, 0x0f, 0x1e, 0x80, 0x8a, 0xf3, 0x52, + 0xcb, 0x92, 0x6b, 0x32, 0x25, 0x02, 0xf6, 0xbd, 0xbd, 0x64, 0x18, 0x35, 0x3a, 0x23, 0x70, 0xf2, 0x67, 0x3c, 0xff, + 0x8e, 0xf1, 0xc8, 0xb1, 0x5b, 0x7d, 0x1b, 0x0d, 0x6c, 0x0b, 0x96, 0xb6, 0x97, 0x35, 0x88, 0xc4, 0xb0, 0xdf, 0x78, + 0xc5, 0xbd, 0x79, 0x9f, 0xb4, 0x07, 0x0e, 0x53, 0x2e, 0x3d, 0x84, 0x7d, 0xc5, 0x38, 0xdb, 0x78, 0x8e, 0x1a, 0x8c, + 0x37, 0xf4, 0xf3, 0x1c, 0x35, 0x6e, 0x1b, 0x53, 0xe4, 0xf9, 0x8d, 0xdb, 0x86, 0x33, 0x27, 0x84, 0x34, 0xbb, 0x65, + 0x33, 0x2d, 0xfe, 0x22, 0xe4, 0x4d, 0xb5, 0xbf, 0x73, 0x28, 0xb6, 0x43, 0xd6, 0x70, 0x92, 0x21, 0x1d, 0x2d, 0x97, + 0xf6, 0xf1, 0xa0, 0x6f, 0xa3, 0x86, 0xa3, 0x09, 0xad, 0xa5, 0x29, 0x0d, 0x21, 0xcc, 0x46, 0x85, 0x8a, 0x27, 0x3d, + 0xa9, 0xc5, 0x8e, 0x16, 0xd5, 0x66, 0x37, 0x78, 0x00, 0x2d, 0x4a, 0x43, 0x46, 0x2a, 0xac, 0x33, 0x98, 0xa6, 0x26, + 0xe6, 0x8c, 0xb4, 0x71, 0x4a, 0xb4, 0xfb, 0x3a, 0x22, 0xbc, 0x22, 0x78, 0x9f, 0x54, 0xd5, 0xf1, 0x30, 0xc0, 0xe1, + 0x88, 0x3c, 0x95, 0x06, 0x49, 0x4f, 0x3b, 0xc7, 0x69, 0x4c, 0x9e, 0xac, 0x44, 0x71, 0x03, 0x08, 0xb0, 0xdc, 0xb8, + 0xc1, 0x3c, 0xcb, 0x68, 0xc2, 0x5f, 0xa7, 0xa1, 0xd2, 0xd3, 0x68, 0x0c, 0xa6, 0x12, 0x84, 0x67, 0x31, 0x28, 0x69, + 0x5d, 0xbd, 0x33, 0xe6, 0x6b, 0xaf, 0x67, 0x64, 0x2e, 0xf5, 0x27, 0x11, 0xb4, 0xed, 0xcd, 0x94, 0x65, 0xec, 0x20, + 0x3c, 0x57, 0xd1, 0x5c, 0xc7, 0x75, 0xdd, 0x99, 0x1b, 0xc0, 0x6b, 0x18, 0x20, 0x47, 0x85, 0xd8, 0x47, 0x4e, 0x4e, + 0x6e, 0xdc, 0x84, 0xde, 0x88, 0x51, 0x1d, 0x54, 0x49, 0x66, 0xbd, 0xbd, 0x8e, 0xa3, 0x9e, 0x60, 0x37, 0xb9, 0x9b, + 0xa4, 0x21, 0x05, 0xf4, 0x40, 0xfc, 0x5e, 0x15, 0x45, 0x7e, 0x6e, 0x06, 0xa9, 0x2a, 0xf8, 0x86, 0xa6, 0xff, 0x7a, + 0x06, 0x4e, 0x5f, 0xa1, 0x6c, 0x95, 0x95, 0xa5, 0x27, 0x1c, 0x21, 0x36, 0x76, 0x66, 0x2e, 0x04, 0xf7, 0x04, 0x09, + 0x31, 0xb0, 0xe5, 0x66, 0x26, 0x51, 0xdd, 0x96, 0x7d, 0x4e, 0x49, 0x38, 0x4c, 0x1b, 0x0d, 0xe1, 0x88, 0x9e, 0x4b, + 0x92, 0x98, 0x21, 0x3c, 0x2d, 0xf7, 0x96, 0xae, 0xf7, 0x96, 0xd4, 0x47, 0x72, 0xa6, 0x75, 0x87, 0x6e, 0x83, 0x71, + 0x24, 0x7c, 0x85, 0xdc, 0xb9, 0x45, 0x78, 0x4c, 0x5a, 0xce, 0xd0, 0x1d, 0xfc, 0x79, 0x84, 0x06, 0x8e, 0xfb, 0x15, + 0x6a, 0x49, 0xc6, 0x31, 0x45, 0x3d, 0x5f, 0x0e, 0xb1, 0x10, 0x51, 0xcc, 0x0e, 0x16, 0xbe, 0x44, 0x2f, 0xc3, 0x89, + 0x3f, 0xa5, 0xde, 0x18, 0xf6, 0xb8, 0xa6, 0x9b, 0xb7, 0x18, 0xe8, 0xc8, 0x1b, 0x2b, 0x4e, 0xe2, 0xda, 0x83, 0x5f, + 0x78, 0xf9, 0x34, 0xb0, 0x07, 0x5f, 0x57, 0x4f, 0x7f, 0xb6, 0x07, 0xdf, 0x72, 0xef, 0xdb, 0x42, 0xb9, 0xbb, 0x6b, + 0x43, 0x3c, 0xd4, 0x43, 0x14, 0x72, 0x61, 0x0c, 0xcc, 0xcd, 0xd1, 0xba, 0xa3, 0x63, 0x86, 0x0a, 0x36, 0x2e, 0x59, + 0x51, 0xee, 0x72, 0x7f, 0x02, 0x28, 0x35, 0x56, 0x20, 0x37, 0xa3, 0xfb, 0xd5, 0x84, 0x81, 0x50, 0x34, 0xb5, 0x02, + 0x2a, 0x67, 0xfd, 0x36, 0x5a, 0xd4, 0xea, 0x0a, 0x8d, 0xa9, 0x1e, 0x4d, 0x2f, 0xb9, 0xf4, 0x94, 0xb4, 0x7b, 0xd3, + 0xe3, 0x59, 0x6f, 0xda, 0x68, 0xa0, 0x5c, 0x13, 0xd6, 0x7c, 0x38, 0x1d, 0xe1, 0xd7, 0xe0, 0xd5, 0x33, 0x29, 0x09, + 0xd7, 0xa6, 0xd7, 0x55, 0xd3, 0x6b, 0x34, 0xb2, 0x02, 0xf5, 0x8c, 0xa6, 0x33, 0xd9, 0xb4, 0x28, 0x24, 0x4e, 0x56, + 0x09, 0xed, 0x08, 0x89, 0x12, 0x48, 0x89, 0x22, 0x84, 0x9c, 0x71, 0xb4, 0xb1, 0x57, 0xe8, 0x13, 0x9a, 0x8b, 0x1d, + 0x0b, 0xcc, 0x53, 0xca, 0x08, 0x07, 0xb0, 0x00, 0x4d, 0x4b, 0x57, 0xf0, 0x2d, 0x9e, 0x37, 0x3a, 0x82, 0xc8, 0x9b, + 0x9d, 0x5e, 0xbd, 0xaf, 0x47, 0x55, 0x5f, 0x78, 0xde, 0x20, 0xb7, 0x25, 0x96, 0x8a, 0xac, 0xd1, 0x28, 0xea, 0xf1, + 0x4e, 0xbd, 0x6f, 0x6b, 0x11, 0x88, 0x93, 0xd5, 0xd4, 0x0c, 0x2d, 0x5f, 0x2b, 0x89, 0xca, 0x5c, 0x96, 0x24, 0x34, + 0x03, 0x19, 0x4a, 0x38, 0x66, 0x45, 0x51, 0xca, 0xf5, 0x37, 0x20, 0x44, 0x31, 0x25, 0x09, 0xf0, 0x1d, 0x61, 0x76, + 0xe1, 0x0c, 0xa7, 0x38, 0x12, 0x5c, 0x83, 0x10, 0x72, 0xaa, 0x93, 0x5a, 0xb8, 0xe0, 0x40, 0x3e, 0x61, 0x86, 0x44, + 0xca, 0x09, 0x75, 0xcf, 0x77, 0x4f, 0xd3, 0x3b, 0x4d, 0xb2, 0x21, 0x1b, 0x79, 0xa2, 0x5a, 0xac, 0xf8, 0x56, 0x40, + 0xde, 0x39, 0x1c, 0x95, 0xe1, 0x11, 0x57, 0xb0, 0xbf, 0xa7, 0x2c, 0xa3, 0x42, 0x03, 0xdf, 0xd5, 0x66, 0x9f, 0x5f, + 0x57, 0x1f, 0x7d, 0xd3, 0x79, 0x03, 0x88, 0x0c, 0xc0, 0xb7, 0x93, 0x91, 0xb5, 0x6a, 0xe7, 0xbb, 0x27, 0x6f, 0x36, + 0x99, 0xc0, 0xcb, 0xa5, 0x32, 0x7e, 0x7d, 0xd0, 0x6c, 0x70, 0x50, 0x41, 0xea, 0xab, 0x1f, 0x9e, 0xe3, 0x0b, 0x05, + 0x29, 0x70, 0x12, 0xa0, 0xa2, 0xf3, 0xdd, 0x93, 0xf7, 0x4e, 0x22, 0x5c, 0x4b, 0x08, 0x9b, 0xd3, 0x76, 0x52, 0xe2, + 0x44, 0x84, 0x22, 0x39, 0xf7, 0x92, 0x71, 0xa5, 0x86, 0xf8, 0xf6, 0x22, 0xf1, 0x12, 0xec, 0x87, 0x21, 0x1b, 0x11, + 0x5f, 0x61, 0x80, 0xf8, 0x08, 0xfb, 0x35, 0xb3, 0x8c, 0xc0, 0x02, 0x88, 0xb1, 0xce, 0x60, 0x25, 0x5c, 0xa9, 0xf8, + 0x21, 0xec, 0x8b, 0x51, 0x79, 0x21, 0x45, 0xc7, 0xcf, 0x6b, 0xb9, 0x69, 0x95, 0x35, 0xfa, 0x2d, 0x58, 0x4e, 0xfa, + 0xe1, 0xb5, 0xea, 0xba, 0x2c, 0x78, 0xaa, 0x93, 0xc8, 0xce, 0x77, 0x4f, 0x5e, 0xa9, 0x3c, 0xb2, 0x99, 0xaf, 0xb9, + 0xfd, 0x9a, 0x85, 0x79, 0xf2, 0xca, 0xad, 0xde, 0x8a, 0xca, 0xe7, 0xbb, 0x27, 0x1f, 0x36, 0x55, 0x83, 0xf2, 0x62, + 0x5e, 0x99, 0xf8, 0x02, 0xbe, 0x05, 0x8d, 0xbd, 0x85, 0x12, 0x0d, 0x1e, 0x2b, 0xb0, 0x10, 0x47, 0x5e, 0x5e, 0x94, + 0x9e, 0x91, 0xa7, 0x38, 0x23, 0x22, 0x0e, 0x54, 0x5f, 0x35, 0xa5, 0xe4, 0xb1, 0x34, 0x39, 0x0b, 0xd2, 0x19, 0xdd, + 0x12, 0x1c, 0x3a, 0x41, 0x2e, 0x9b, 0x42, 0x02, 0x8d, 0x00, 0x9d, 0xe1, 0x9d, 0x36, 0xea, 0xd5, 0x85, 0x57, 0x26, + 0x88, 0x34, 0xad, 0x49, 0x16, 0x1c, 0x91, 0x36, 0xf6, 0x49, 0x1b, 0x07, 0x24, 0x1f, 0xb6, 0xa5, 0x78, 0xe8, 0x05, + 0x65, 0xbf, 0x52, 0xc8, 0x40, 0x6e, 0x58, 0x20, 0x77, 0xab, 0x14, 0xbf, 0x61, 0x2f, 0x10, 0xae, 0x47, 0x21, 0xd1, + 0x43, 0x69, 0xb4, 0x3a, 0x29, 0x4e, 0x45, 0xc7, 0x67, 0xec, 0x32, 0x86, 0xec, 0x12, 0x98, 0x15, 0xe6, 0xc8, 0x2b, + 0xab, 0x76, 0x54, 0xd5, 0xc0, 0x15, 0xeb, 0x94, 0xe2, 0xc0, 0x05, 0xc6, 0x8d, 0x03, 0x95, 0x8c, 0x93, 0xaf, 0x37, + 0x79, 0xb8, 0xb7, 0xe7, 0xc8, 0x46, 0xdf, 0x71, 0x27, 0xd5, 0xef, 0xab, 0xd0, 0xdd, 0xb7, 0x92, 0x57, 0x84, 0x48, + 0xc0, 0xdf, 0x68, 0xf8, 0xa3, 0x02, 0xe2, 0xd0, 0x4e, 0x50, 0xc7, 0xa0, 0x06, 0x5e, 0x68, 0x7a, 0xf5, 0xe9, 0x37, + 0x1a, 0x65, 0x98, 0xb6, 0x8e, 0xad, 0x13, 0x9c, 0x15, 0x57, 0x4e, 0x99, 0xff, 0xd3, 0x5e, 0xcb, 0x9a, 0xd2, 0x20, + 0x20, 0x66, 0xd2, 0x2c, 0xd3, 0x93, 0x31, 0xb6, 0x04, 0x83, 0x7a, 0x2f, 0x54, 0xe2, 0x02, 0x16, 0x39, 0x56, 0xaa, + 0x92, 0x66, 0x67, 0x5d, 0xe4, 0xe9, 0x4a, 0x10, 0x96, 0x82, 0x4a, 0x8d, 0x42, 0x91, 0xf7, 0xab, 0xf5, 0xcc, 0x4b, + 0x9c, 0x23, 0xe5, 0xe3, 0x12, 0x50, 0x08, 0x64, 0x75, 0x4b, 0xa4, 0x3c, 0x27, 0x93, 0xed, 0x24, 0x7f, 0x62, 0x90, + 0xfc, 0x13, 0x42, 0x0d, 0xf2, 0x97, 0x1e, 0x0e, 0x37, 0x55, 0xae, 0x85, 0x5c, 0xbf, 0x3a, 0x9d, 0x11, 0xf0, 0xa1, + 0xd5, 0x31, 0x5a, 0x8b, 0x2b, 0x6e, 0x61, 0x28, 0xe6, 0x0e, 0x11, 0x5e, 0x48, 0xac, 0x83, 0xc0, 0x4e, 0x15, 0x55, + 0x83, 0xa1, 0x37, 0xb9, 0xf4, 0x4c, 0x0e, 0x78, 0xf2, 0xe1, 0xee, 0x80, 0xe8, 0xe9, 0x6c, 0x7d, 0xe7, 0x1a, 0x19, + 0xa0, 0x30, 0x6b, 0x63, 0xe3, 0xd6, 0xf3, 0x41, 0x61, 0xfc, 0x32, 0x90, 0x5d, 0x67, 0x3e, 0x2b, 0x9b, 0x50, 0xcb, + 0x3f, 0x80, 0xb6, 0xd3, 0x11, 0x35, 0xa8, 0xd1, 0x2d, 0xf0, 0x23, 0x99, 0x87, 0xea, 0x67, 0x5b, 0xd8, 0xc7, 0x89, + 0xa8, 0x40, 0x93, 0x70, 0xf3, 0xeb, 0x27, 0x85, 0x22, 0x13, 0x09, 0x1a, 0x5a, 0x00, 0xff, 0x93, 0x24, 0x0f, 0x74, + 0x23, 0xe4, 0x02, 0x20, 0x68, 0x22, 0xf0, 0x54, 0x21, 0xcc, 0xb6, 0x2b, 0xe7, 0xfb, 0xf3, 0x1d, 0x42, 0x26, 0x95, + 0xf3, 0xf1, 0x5d, 0x95, 0x7d, 0x05, 0x64, 0x81, 0x3c, 0x30, 0x1e, 0xcb, 0x02, 0x19, 0xbf, 0x3c, 0xd5, 0xd5, 0x85, + 0x01, 0xe9, 0x56, 0xfa, 0xb6, 0x11, 0xdb, 0x14, 0x5e, 0x39, 0xf9, 0x5e, 0xa3, 0x61, 0xe5, 0xed, 0x2e, 0xbc, 0x7d, + 0xc9, 0x05, 0x8c, 0xf0, 0xfc, 0x5e, 0xd4, 0xd6, 0xfd, 0x16, 0x1f, 0x57, 0x53, 0x58, 0x56, 0x16, 0xc5, 0x65, 0x49, + 0x4e, 0x33, 0xfe, 0x84, 0x8e, 0xd3, 0x0c, 0x42, 0x16, 0x25, 0x4e, 0x50, 0xb1, 0x6b, 0xb8, 0xed, 0xc4, 0xfc, 0x8c, + 0x38, 0xc1, 0xca, 0x04, 0xc5, 0xaf, 0x8f, 0x22, 0x6a, 0x7d, 0xbe, 0xda, 0x6a, 0xb2, 0xb7, 0xf7, 0xae, 0x42, 0x93, + 0x82, 0x52, 0x40, 0x61, 0x30, 0x2d, 0xa9, 0xd2, 0xa8, 0x50, 0xee, 0xae, 0x53, 0xba, 0x00, 0x34, 0xc3, 0x30, 0x79, + 0xcf, 0x73, 0xc2, 0x8b, 0xc9, 0x2a, 0x8b, 0x57, 0xae, 0x09, 0x66, 0x9a, 0x2d, 0xc0, 0xe1, 0xc1, 0xd0, 0x96, 0xbe, + 0xa2, 0xbc, 0x4a, 0x89, 0x2d, 0x61, 0x38, 0x05, 0x64, 0x39, 0xc2, 0x08, 0x31, 0x28, 0x70, 0xa3, 0x51, 0xf2, 0x16, + 0xf4, 0xca, 0x08, 0xe7, 0x6e, 0x04, 0x49, 0xb0, 0xb5, 0x2d, 0x8b, 0x10, 0x96, 0x99, 0x39, 0x46, 0x2e, 0xc1, 0xc9, + 0xf3, 0x4d, 0x1e, 0x65, 0x4d, 0xd4, 0x54, 0x48, 0x1d, 0xa8, 0x91, 0xa1, 0xb2, 0x81, 0x7b, 0xe5, 0x30, 0xa5, 0xb8, + 0xe9, 0xb8, 0x19, 0x30, 0xe0, 0x9f, 0xb9, 0x23, 0x63, 0x51, 0x20, 0x33, 0x52, 0x77, 0xee, 0xd4, 0x86, 0xee, 0xa5, + 0xa2, 0x19, 0x56, 0x88, 0x8b, 0x4c, 0x34, 0xa5, 0x22, 0xae, 0x77, 0x5a, 0xf1, 0xd2, 0x2b, 0x99, 0x47, 0xcd, 0x35, + 0x17, 0xac, 0x32, 0x49, 0x8c, 0xe9, 0x5f, 0xc9, 0xd4, 0xe8, 0xb2, 0x12, 0xa8, 0x61, 0xf4, 0xda, 0x7a, 0x22, 0xd6, + 0x80, 0x16, 0x40, 0x5f, 0x8b, 0x53, 0x6e, 0xac, 0xa8, 0xf6, 0x61, 0x8b, 0x31, 0x0d, 0xa9, 0xff, 0x0e, 0x72, 0x5d, + 0x56, 0xf7, 0xfc, 0x73, 0x21, 0x0b, 0x19, 0xce, 0x6b, 0x8c, 0x3d, 0x13, 0x8c, 0x1d, 0x81, 0x9e, 0xa6, 0xd3, 0xbf, + 0x07, 0x2a, 0xe5, 0x45, 0xe5, 0x2e, 0x3a, 0x8a, 0xc4, 0x5e, 0x97, 0xe1, 0x72, 0xe3, 0xf7, 0xca, 0x6a, 0x78, 0x8c, + 0x40, 0x1a, 0x10, 0x56, 0x9c, 0x3d, 0x43, 0x38, 0x6f, 0x34, 0x7a, 0xf9, 0x31, 0xad, 0x5c, 0x24, 0x15, 0x8c, 0x0c, + 0x22, 0xba, 0x40, 0xf0, 0x35, 0x19, 0x0a, 0x31, 0x7f, 0x9d, 0x9f, 0x9d, 0x83, 0xab, 0xfd, 0xe4, 0x9d, 0x63, 0x72, + 0x35, 0xb3, 0x6e, 0x19, 0x34, 0x85, 0xf9, 0x38, 0x55, 0xbc, 0xe5, 0xed, 0xdd, 0x19, 0x1e, 0x00, 0xf7, 0x4e, 0x07, + 0x43, 0x36, 0x1a, 0xea, 0x71, 0xc9, 0x12, 0xca, 0xdd, 0xd7, 0x43, 0x55, 0x62, 0xa2, 0x39, 0x58, 0x8f, 0x57, 0xa6, + 0x2c, 0x27, 0x79, 0x51, 0xe4, 0xb4, 0x8a, 0xef, 0xaf, 0x64, 0x60, 0x0a, 0xe1, 0xb2, 0xee, 0x6c, 0x3f, 0x9d, 0x11, + 0x8e, 0x0d, 0x42, 0x7d, 0xbb, 0x2d, 0xf4, 0x51, 0x81, 0x09, 0xfb, 0x5a, 0x09, 0xc5, 0x6f, 0x37, 0x09, 0x45, 0x9c, + 0xa9, 0x2d, 0x2f, 0x04, 0x62, 0xe7, 0x1e, 0x02, 0x51, 0x39, 0xd9, 0xb5, 0x4c, 0x04, 0x75, 0xa4, 0x26, 0x13, 0xeb, + 0x4b, 0x4a, 0x32, 0xcc, 0xd4, 0x6a, 0xf4, 0xbb, 0xcb, 0x25, 0x1b, 0xb6, 0xc1, 0x89, 0x64, 0xdb, 0xf0, 0xb3, 0x23, + 0x7f, 0x1a, 0x9c, 0x58, 0x3a, 0x81, 0x1d, 0x56, 0x9a, 0x2c, 0xc8, 0x85, 0x34, 0x67, 0x47, 0x64, 0x65, 0x09, 0x9a, + 0x56, 0x14, 0xa4, 0x08, 0x9c, 0xb0, 0x32, 0xca, 0x04, 0x10, 0x0b, 0x59, 0xa1, 0x0c, 0x48, 0x67, 0x63, 0xfa, 0x9f, + 0x36, 0x2f, 0x3f, 0xad, 0x89, 0xd6, 0xe4, 0x8a, 0x54, 0x1f, 0x6a, 0x09, 0x07, 0x0a, 0x02, 0xa5, 0x1f, 0xee, 0x08, + 0x13, 0xb4, 0x12, 0xe5, 0xc8, 0x94, 0x43, 0xb8, 0x0d, 0x2e, 0xb4, 0x9d, 0x77, 0x32, 0xc0, 0xbb, 0x41, 0x9a, 0xe0, + 0xd4, 0xa0, 0xeb, 0xe7, 0x84, 0xd7, 0x58, 0x49, 0x44, 0x94, 0xa5, 0x84, 0x03, 0x41, 0xa6, 0x9c, 0x64, 0xc3, 0xf6, + 0x08, 0x14, 0xd0, 0x9e, 0x7f, 0x9c, 0x55, 0x26, 0xb0, 0xdf, 0x68, 0xa0, 0x40, 0x8f, 0x1a, 0x0d, 0x59, 0xc3, 0x1f, + 0x61, 0x8a, 0x7d, 0x69, 0x98, 0x9c, 0xee, 0xed, 0x39, 0x41, 0x35, 0xee, 0xd0, 0x1f, 0x21, 0x9c, 0x2e, 0x97, 0x8e, + 0x00, 0x2b, 0x40, 0xcb, 0x65, 0x60, 0x82, 0x25, 0x5e, 0x43, 0xb3, 0xc9, 0x80, 0x93, 0x89, 0x10, 0x80, 0x13, 0x80, + 0xb0, 0x41, 0x9c, 0x40, 0x39, 0xf7, 0x02, 0x70, 0x46, 0x35, 0xb2, 0xa1, 0xdf, 0xe8, 0x8c, 0x0c, 0xc6, 0x35, 0xf4, + 0x47, 0x24, 0x28, 0xd2, 0xbd, 0xbd, 0x9d, 0x5c, 0x89, 0xc8, 0x9f, 0x41, 0x94, 0xfd, 0x2c, 0x24, 0x8b, 0xec, 0xd0, + 0x5c, 0x8d, 0x55, 0x67, 0x40, 0x49, 0x51, 0x6a, 0x59, 0x75, 0xbd, 0x5a, 0x16, 0x44, 0x59, 0x09, 0xab, 0x58, 0xf0, + 0x00, 0x2c, 0xfb, 0x92, 0xcc, 0x7f, 0xe1, 0x65, 0x9a, 0xf5, 0xb7, 0x1b, 0x93, 0xab, 0x5d, 0xd7, 0xf5, 0xb3, 0x89, + 0x88, 0x64, 0xe8, 0x28, 0xac, 0x20, 0xfe, 0x7d, 0x05, 0xa6, 0x31, 0xf0, 0xb0, 0x1c, 0x6b, 0x44, 0x24, 0xf8, 0x5a, + 0xb5, 0xd1, 0x27, 0x4a, 0x7e, 0xdd, 0xe8, 0x65, 0x90, 0x90, 0x7c, 0xfd, 0x5b, 0x21, 0x39, 0x50, 0x90, 0x48, 0xf2, + 0x58, 0xc1, 0xd9, 0x16, 0x5c, 0xfc, 0xca, 0x57, 0x70, 0xb6, 0x1d, 0xb7, 0x25, 0x43, 0xd8, 0x06, 0x9f, 0xc1, 0x1b, + 0x24, 0xa0, 0x55, 0x81, 0x01, 0xe5, 0xe1, 0xaa, 0xee, 0x25, 0x59, 0x29, 0x08, 0x53, 0x4e, 0x1c, 0x56, 0xdf, 0x00, + 0x95, 0x36, 0x6a, 0x18, 0xbe, 0xcc, 0x9b, 0x20, 0xc3, 0x25, 0x50, 0x4f, 0x5d, 0x01, 0x72, 0x52, 0xbe, 0x76, 0x48, + 0x45, 0xd8, 0x91, 0x4a, 0x9c, 0x1b, 0xf8, 0x33, 0x3e, 0xcf, 0x40, 0x95, 0xca, 0xf5, 0x6f, 0x28, 0x86, 0xb3, 0x20, + 0xa2, 0x0c, 0x7e, 0x40, 0xc1, 0xcc, 0xcf, 0x73, 0x76, 0x25, 0xcb, 0xd4, 0x6f, 0x9c, 0x12, 0x4d, 0xca, 0xb9, 0xd4, + 0x09, 0x33, 0xd4, 0xcb, 0x14, 0x9d, 0xd6, 0xd1, 0xf6, 0xec, 0x8a, 0x26, 0xfc, 0x25, 0xcb, 0x39, 0x4d, 0x60, 0xfa, + 0x15, 0xc5, 0xc1, 0x8c, 0x72, 0x04, 0x1b, 0xb6, 0xd6, 0xca, 0x0f, 0xc3, 0x3b, 0x9b, 0xf0, 0xba, 0x0e, 0x14, 0xf9, + 0x49, 0x18, 0xcb, 0x41, 0xcc, 0x84, 0x46, 0x9d, 0xc4, 0x59, 0xd6, 0x34, 0xf3, 0x69, 0x2a, 0x65, 0x43, 0x70, 0x77, + 0x87, 0x11, 0x2d, 0x09, 0xb4, 0xf4, 0xbc, 0x53, 0x6b, 0x81, 0x80, 0xf7, 0x96, 0x45, 0x30, 0x67, 0x82, 0xb9, 0xc1, + 0x51, 0xdd, 0x3a, 0x9c, 0x9a, 0x6e, 0xbe, 0xdb, 0x78, 0xb0, 0x6d, 0x93, 0x70, 0x10, 0x74, 0xf2, 0x70, 0xbb, 0x65, + 0xf5, 0x4a, 0x4b, 0x0e, 0x2d, 0x2d, 0xd8, 0x7d, 0x19, 0x33, 0x5a, 0x68, 0xf2, 0x42, 0x7a, 0x2b, 0xee, 0x72, 0xf2, + 0x0b, 0x9c, 0x1c, 0x7a, 0xce, 0xa7, 0xf1, 0xca, 0x01, 0x99, 0xde, 0x6e, 0xa9, 0xfd, 0xef, 0x72, 0xe7, 0x09, 0x7e, + 0x05, 0x61, 0xdd, 0x6f, 0xaa, 0xea, 0xeb, 0xe1, 0xdc, 0x6f, 0x2a, 0x04, 0x7d, 0xe3, 0xad, 0xd5, 0x33, 0xc2, 0xb8, + 0x5d, 0xf7, 0xc8, 0x6d, 0xdb, 0x5a, 0x5b, 0xfa, 0x51, 0x06, 0x91, 0x64, 0xaa, 0xa5, 0xd8, 0x0f, 0xb8, 0x4a, 0x54, + 0x83, 0x84, 0xb9, 0xba, 0x85, 0x44, 0x55, 0x8a, 0xa1, 0xd4, 0xe1, 0xb7, 0x2d, 0x8f, 0x92, 0x31, 0x99, 0xb4, 0x33, + 0xde, 0xfa, 0x19, 0xdf, 0x85, 0x5d, 0x96, 0xae, 0x9d, 0xc6, 0x8b, 0x08, 0x78, 0xd0, 0xee, 0x37, 0x84, 0x61, 0x6c, + 0xe7, 0xf2, 0x30, 0x90, 0xd9, 0x3f, 0x49, 0xb5, 0xee, 0x56, 0xb7, 0x32, 0x5e, 0x83, 0xfd, 0x8f, 0x70, 0xa4, 0x8f, + 0xc8, 0x51, 0xc5, 0x81, 0xa9, 0xb7, 0x28, 0x4a, 0xa7, 0x40, 0x2a, 0x95, 0xb7, 0x04, 0xe1, 0xb4, 0x10, 0xe1, 0xed, + 0xef, 0xf1, 0x0f, 0x8a, 0x25, 0x9e, 0x97, 0x1c, 0xe7, 0xd9, 0x7d, 0x39, 0xa2, 0x04, 0xbf, 0x8c, 0xde, 0x03, 0x1d, + 0x0b, 0x0a, 0x2d, 0x34, 0x15, 0x3d, 0x4d, 0xd5, 0x44, 0xb6, 0xe6, 0xa5, 0x62, 0x5a, 0x66, 0xd4, 0x88, 0x61, 0x36, + 0x24, 0x72, 0x6a, 0x2b, 0x9b, 0x97, 0xbb, 0xaa, 0x36, 0x2e, 0xda, 0x82, 0xc5, 0x2a, 0xb0, 0xb8, 0x5c, 0x3a, 0x75, + 0x54, 0x13, 0x66, 0xc4, 0x31, 0x10, 0x66, 0x46, 0x42, 0x45, 0x4d, 0xb3, 0x96, 0x6d, 0x1c, 0xb4, 0x9a, 0x4f, 0xa4, + 0x75, 0xf3, 0x1a, 0x1c, 0xa6, 0x0b, 0x41, 0x36, 0x37, 0x7d, 0x0a, 0x58, 0xce, 0xae, 0x1c, 0xc8, 0xc0, 0xd0, 0x8f, + 0x65, 0xae, 0x6c, 0x95, 0xd4, 0xba, 0x01, 0xbf, 0xe8, 0x8e, 0x6c, 0x59, 0x85, 0xba, 0xf5, 0xf7, 0x46, 0xae, 0xd1, + 0xd3, 0x74, 0x5b, 0xae, 0x51, 0x4d, 0xdb, 0xdd, 0x69, 0xa3, 0xbb, 0xf3, 0x52, 0xe5, 0x58, 0x9b, 0xab, 0xfc, 0x86, + 0xe1, 0x3a, 0x40, 0x9b, 0x12, 0xcd, 0x9a, 0xab, 0x9c, 0x16, 0xc5, 0x79, 0x79, 0x9a, 0x40, 0xa4, 0xee, 0x9c, 0x4b, + 0xfa, 0x57, 0x56, 0xa3, 0x38, 0x94, 0xeb, 0x7c, 0x4f, 0x26, 0x71, 0x7a, 0xe9, 0xc7, 0xef, 0x61, 0xbc, 0xea, 0xe5, + 0xf3, 0xdb, 0x30, 0xf3, 0x39, 0x55, 0xdc, 0xa5, 0x82, 0xe1, 0x7b, 0x03, 0x86, 0xef, 0x25, 0x9f, 0xae, 0xda, 0xe3, + 0xc5, 0xcb, 0xb2, 0x03, 0xef, 0xbc, 0xd0, 0x2c, 0xe3, 0x96, 0x6f, 0x1e, 0x63, 0x95, 0x85, 0xdd, 0x96, 0x2c, 0xec, + 0x96, 0x3b, 0xab, 0x5d, 0x39, 0xce, 0x0f, 0x9b, 0x7b, 0x59, 0xe7, 0x6c, 0x3f, 0x54, 0x1b, 0xff, 0x07, 0xef, 0xce, + 0x36, 0x06, 0x97, 0xdb, 0x77, 0xf7, 0x45, 0xb2, 0x8a, 0x04, 0xf9, 0x25, 0x24, 0x1d, 0x70, 0xd2, 0x37, 0x0e, 0x1d, + 0x54, 0x72, 0x4a, 0xe7, 0x01, 0x39, 0xc1, 0x3c, 0xe7, 0xe9, 0x54, 0xf5, 0x99, 0xab, 0x93, 0x46, 0xe2, 0x25, 0xb8, + 0xa2, 0x45, 0xac, 0xdd, 0xab, 0x9f, 0xe5, 0x5a, 0x7c, 0x64, 0x49, 0xe8, 0xe5, 0x58, 0x49, 0x91, 0xdc, 0xcb, 0x0a, + 0xa2, 0xb3, 0x8d, 0xd7, 0xdf, 0xe1, 0x31, 0x4b, 0x58, 0x1e, 0xd1, 0xcc, 0x49, 0xd1, 0x62, 0xdb, 0x60, 0x29, 0x04, + 0x64, 0xe4, 0x60, 0xf8, 0xaf, 0xd5, 0xa9, 0x3f, 0x17, 0x7a, 0x03, 0x3f, 0xd0, 0x94, 0xf2, 0x28, 0x0d, 0x21, 0x2d, + 0xc5, 0x0d, 0xcb, 0x43, 0x4d, 0x7b, 0x7b, 0x3b, 0x8e, 0x2d, 0xdc, 0x12, 0x70, 0x00, 0xdc, 0x7c, 0x83, 0x06, 0x0b, + 0x38, 0x9f, 0x53, 0x0d, 0x4d, 0xd1, 0x82, 0xae, 0x1e, 0x65, 0xe1, 0xee, 0x47, 0x7a, 0x8b, 0x13, 0x54, 0x14, 0x9e, + 0x84, 0xda, 0x1e, 0x33, 0x1a, 0x87, 0x36, 0xfe, 0x48, 0x6f, 0xbd, 0xf2, 0xcc, 0xb8, 0x38, 0xe2, 0x2c, 0x16, 0xd0, + 0x4e, 0xaf, 0x13, 0x1b, 0x57, 0x83, 0x78, 0x8b, 0x02, 0xa7, 0x19, 0x9b, 0x00, 0x71, 0x7e, 0x43, 0x6f, 0x3d, 0xd9, + 0x1f, 0x33, 0xce, 0xeb, 0xa1, 0x85, 0x46, 0xbd, 0x6b, 0x14, 0x9b, 0xcb, 0xa0, 0x0c, 0x8a, 0xa1, 0x68, 0x3b, 0x22, + 0xb5, 0x7a, 0x95, 0x79, 0x88, 0x50, 0x71, 0xdf, 0xa9, 0xe0, 0x6f, 0x4c, 0xd1, 0xc6, 0x6b, 0x99, 0xaf, 0x2b, 0x8d, + 0x28, 0x34, 0xa8, 0x32, 0x3d, 0x76, 0x9d, 0x44, 0xef, 0x3a, 0x75, 0x08, 0xc1, 0x70, 0x84, 0x7d, 0xc3, 0x55, 0xa7, + 0xde, 0x5f, 0x65, 0x42, 0x48, 0x15, 0x49, 0x7a, 0x51, 0xb5, 0xb3, 0x76, 0x1d, 0xc0, 0x3b, 0x24, 0xb4, 0xf8, 0xe2, + 0x4c, 0x66, 0xa1, 0xb3, 0x45, 0xff, 0xc6, 0x89, 0xb3, 0xd0, 0x53, 0xf0, 0x12, 0x13, 0x8b, 0xbc, 0x00, 0x2a, 0x54, + 0xf4, 0x25, 0x13, 0x00, 0xd9, 0xd8, 0x61, 0x6b, 0x52, 0x33, 0x13, 0x52, 0xd3, 0x35, 0x30, 0xbe, 0x45, 0x4a, 0x52, + 0x81, 0x0c, 0xa1, 0x44, 0x0a, 0xa1, 0xa7, 0x16, 0x57, 0x91, 0x90, 0xb9, 0xa0, 0xe5, 0x09, 0x3a, 0xb9, 0xe6, 0x59, + 0x0d, 0x2c, 0x47, 0xf4, 0x83, 0x0a, 0x0f, 0xa6, 0x44, 0x65, 0x85, 0xa2, 0x3c, 0x9a, 0xad, 0xd3, 0x5b, 0x9d, 0xd4, + 0xd5, 0xd3, 0x22, 0x1a, 0x25, 0x4e, 0x84, 0x16, 0x89, 0x13, 0xe1, 0x0c, 0xd2, 0x11, 0xd3, 0xa2, 0x84, 0x9f, 0x9a, + 0xab, 0x51, 0x4b, 0x56, 0xde, 0x7c, 0xca, 0x0f, 0x94, 0x79, 0x0e, 0x29, 0x9a, 0x38, 0xd1, 0x3c, 0x25, 0x71, 0xc4, + 0x71, 0x3b, 0x63, 0xd9, 0xbe, 0x57, 0x09, 0x3a, 0x0a, 0xb0, 0xbf, 0x71, 0x67, 0x61, 0xcc, 0xc2, 0x3c, 0xd1, 0xad, + 0x4e, 0xfd, 0xa9, 0x60, 0x5f, 0x95, 0x43, 0xea, 0xe4, 0x64, 0x45, 0xe2, 0xdc, 0x9d, 0x6a, 0xf9, 0xcb, 0x9c, 0x66, + 0xb7, 0x67, 0x14, 0x52, 0x9d, 0x53, 0x38, 0xf0, 0x5b, 0x2d, 0x43, 0x95, 0xa7, 0x3e, 0xc8, 0x84, 0xb2, 0x52, 0xd4, + 0xcf, 0x01, 0xae, 0x9e, 0x12, 0x2c, 0x44, 0xb4, 0xd1, 0x70, 0xc4, 0xc8, 0xdd, 0x42, 0xb7, 0x9e, 0x9f, 0xa4, 0x3d, + 0x06, 0xfe, 0xb5, 0x0a, 0xd3, 0x2a, 0x58, 0x80, 0x53, 0xf3, 0x4c, 0xea, 0x30, 0x1f, 0xad, 0x7a, 0x65, 0xa0, 0x08, + 0xc2, 0x77, 0xd9, 0xf6, 0xa9, 0x6e, 0x4a, 0x9a, 0xdd, 0x3e, 0xd5, 0x5a, 0xd0, 0x4f, 0x24, 0xfc, 0x60, 0x35, 0x4e, + 0x79, 0x82, 0x99, 0x15, 0x05, 0x2a, 0x00, 0xbc, 0xbf, 0xf4, 0x1c, 0xe7, 0x2f, 0x2a, 0x65, 0xd0, 0x85, 0x58, 0xec, + 0x59, 0x9c, 0x6a, 0x26, 0x5e, 0x8d, 0xff, 0x97, 0xb5, 0xf1, 0xff, 0x62, 0x9c, 0x3a, 0x05, 0xd3, 0x68, 0x92, 0xd0, + 0x50, 0xb3, 0x4e, 0x24, 0x09, 0x50, 0xe8, 0x6d, 0x19, 0x27, 0x1f, 0x2f, 0x3c, 0xd0, 0xb8, 0x16, 0xe3, 0x34, 0xe1, + 0xcd, 0xb1, 0x3f, 0x65, 0xf1, 0xad, 0x37, 0x67, 0xcd, 0x69, 0x9a, 0xa4, 0xf9, 0xcc, 0x0f, 0x28, 0xce, 0x6f, 0x73, + 0x4e, 0xa7, 0xcd, 0x39, 0xc3, 0xcf, 0x69, 0x7c, 0x45, 0x39, 0x0b, 0x7c, 0x6c, 0x9f, 0x64, 0xcc, 0x8f, 0xad, 0xd7, + 0x7e, 0x96, 0xa5, 0xd7, 0x36, 0x7e, 0x97, 0x5e, 0xa6, 0x3c, 0xc5, 0x6f, 0x6e, 0x6e, 0x27, 0x34, 0xc1, 0x1f, 0x2e, + 0xe7, 0x09, 0x9f, 0xe3, 0xdc, 0x4f, 0xf2, 0x66, 0x4e, 0x33, 0x36, 0xee, 0x05, 0x69, 0x9c, 0x66, 0x4d, 0xc8, 0xd8, + 0x9e, 0x52, 0x2f, 0x66, 0x93, 0x88, 0x5b, 0xa1, 0x9f, 0x7d, 0xec, 0x35, 0x9b, 0xb3, 0x8c, 0x4d, 0xfd, 0xec, 0xb6, + 0x29, 0x6a, 0x78, 0x5f, 0xb6, 0xf7, 0xfd, 0xc7, 0xe3, 0x83, 0x1e, 0xcf, 0xfc, 0x24, 0x67, 0xb0, 0x4c, 0x9e, 0x1f, + 0xc7, 0xd6, 0xfe, 0x61, 0x7b, 0x9a, 0xef, 0xc8, 0x40, 0x9e, 0x9f, 0xf0, 0xe2, 0x02, 0xbf, 0x07, 0xb8, 0xdd, 0x4b, + 0x9e, 0xe0, 0xcb, 0x39, 0xe7, 0x69, 0xb2, 0x08, 0xe6, 0x59, 0x9e, 0x66, 0xde, 0x2c, 0x65, 0x09, 0xa7, 0x59, 0xef, + 0x32, 0xcd, 0x42, 0x9a, 0x35, 0x33, 0x3f, 0x64, 0xf3, 0xdc, 0x3b, 0x98, 0xdd, 0xf4, 0x40, 0xb3, 0x98, 0x64, 0xe9, + 0x3c, 0x09, 0xd5, 0x58, 0x2c, 0x89, 0x68, 0xc6, 0xb8, 0xf9, 0x42, 0x5c, 0x64, 0xe2, 0xc5, 0x2c, 0xa1, 0x7e, 0xd6, + 0x9c, 0x40, 0x63, 0x30, 0x8b, 0xda, 0x21, 0x9d, 0xe0, 0x6c, 0x72, 0xe9, 0x3b, 0x9d, 0xee, 0x23, 0xac, 0xff, 0x77, + 0x0f, 0x91, 0xd5, 0xde, 0x5c, 0xdc, 0x69, 0xb7, 0xff, 0x84, 0x7a, 0x2b, 0xa3, 0x08, 0x80, 0xbc, 0xce, 0xec, 0xc6, + 0xca, 0x53, 0xc8, 0x68, 0xdb, 0xd4, 0xb2, 0x37, 0xf3, 0x43, 0xc8, 0x07, 0xf6, 0xba, 0xb3, 0x9b, 0x02, 0x66, 0xe7, + 0xc9, 0x14, 0x53, 0x35, 0x49, 0xf5, 0xb4, 0xf8, 0xad, 0x10, 0x1f, 0x6d, 0x86, 0xb8, 0xab, 0x21, 0xae, 0xb0, 0xde, + 0x0c, 0xe7, 0x99, 0x88, 0xad, 0x7a, 0x9d, 0x5c, 0x02, 0x12, 0xa5, 0x57, 0x34, 0xd3, 0x70, 0x88, 0x87, 0xdf, 0x0c, + 0x46, 0x77, 0x33, 0x18, 0x47, 0x9f, 0x02, 0x23, 0x4b, 0xc2, 0x45, 0x7d, 0x5d, 0x3b, 0x19, 0x9d, 0xf6, 0x22, 0x0a, + 0xf4, 0xe4, 0x75, 0xe1, 0xf7, 0x35, 0x0b, 0x79, 0x24, 0x7f, 0x0a, 0x72, 0xbe, 0x96, 0xef, 0x0e, 0xdb, 0x6d, 0xf9, + 0x9c, 0xb3, 0x5f, 0xa9, 0xd7, 0x71, 0xa1, 0x42, 0x71, 0x81, 0x7f, 0x28, 0x4f, 0xf3, 0xd6, 0xb9, 0x27, 0xfe, 0x8b, + 0x79, 0xcc, 0xd7, 0x48, 0x51, 0xac, 0x0e, 0x45, 0xe3, 0x54, 0xcb, 0x4a, 0x29, 0x7c, 0xc0, 0x6d, 0x27, 0xb8, 0x23, + 0x61, 0xfd, 0xf2, 0x18, 0x27, 0x1b, 0xfc, 0x45, 0xe6, 0x5d, 0x78, 0x10, 0xe9, 0x30, 0x52, 0x0d, 0xd3, 0x5e, 0xd6, + 0x27, 0xed, 0x5e, 0xd6, 0x6c, 0x22, 0x27, 0x25, 0xc9, 0x30, 0x53, 0xc9, 0x79, 0x0e, 0x1b, 0xa4, 0xc2, 0xd8, 0xce, + 0x91, 0x97, 0xc2, 0x59, 0xd3, 0xe5, 0xb2, 0x0a, 0x03, 0x30, 0x71, 0x5a, 0xe3, 0x07, 0xae, 0x2a, 0xe0, 0xdc, 0xe0, + 0xe4, 0xbe, 0xbe, 0xde, 0x25, 0xd1, 0xbc, 0x22, 0x4e, 0x03, 0x81, 0x39, 0x77, 0xe6, 0xf3, 0x08, 0xbc, 0x14, 0xa5, + 0xf8, 0xa9, 0x52, 0x98, 0xec, 0x96, 0x8d, 0x06, 0x49, 0x99, 0xdf, 0x06, 0x79, 0x7c, 0x49, 0x01, 0xbd, 0x5c, 0x72, + 0x02, 0x3d, 0x56, 0xfd, 0x7f, 0xe0, 0x86, 0xa4, 0x4e, 0x5c, 0x96, 0x04, 0xf1, 0x3c, 0xa4, 0xb9, 0xe8, 0xa1, 0x12, + 0xe7, 0x70, 0x37, 0x44, 0x59, 0x4b, 0x34, 0x81, 0xde, 0x45, 0x36, 0x0f, 0x54, 0x84, 0x5b, 0x54, 0xca, 0xe7, 0xa6, + 0x78, 0xae, 0xda, 0xbe, 0xae, 0x92, 0x45, 0xa1, 0xa5, 0x3b, 0x4f, 0xd8, 0x2f, 0x73, 0x7a, 0xce, 0x42, 0xe3, 0xe4, + 0x2e, 0x4d, 0x82, 0x34, 0xa4, 0x1f, 0xde, 0xbd, 0x80, 0x6c, 0xf7, 0x34, 0x01, 0x12, 0x4b, 0xa4, 0xbf, 0x0b, 0xe7, + 0x24, 0x71, 0x43, 0x7a, 0xc5, 0x02, 0x3a, 0xb8, 0xd8, 0x5d, 0x6c, 0xac, 0x28, 0x5f, 0xa3, 0xa2, 0x75, 0x21, 0x92, + 0xfe, 0x04, 0x94, 0x17, 0xbb, 0x8b, 0x4b, 0x5e, 0xb4, 0x76, 0x17, 0x89, 0x1b, 0xa6, 0x53, 0x9f, 0x25, 0xf0, 0x3b, + 0x2f, 0x76, 0x17, 0x0c, 0x7e, 0xf0, 0xe2, 0xa2, 0xa8, 0x12, 0x45, 0x4b, 0x88, 0x8c, 0x29, 0x28, 0xdc, 0x75, 0x90, + 0xfb, 0x73, 0xca, 0x12, 0x51, 0x74, 0x57, 0xcf, 0x54, 0xf7, 0x0a, 0x48, 0xfe, 0x95, 0x48, 0x83, 0x59, 0x9b, 0xcb, + 0xe7, 0xf7, 0x35, 0x97, 0x69, 0xc2, 0x99, 0x48, 0x8b, 0xd7, 0xe1, 0x9c, 0xc8, 0xcf, 0xcf, 0x03, 0x79, 0x12, 0x35, + 0xaf, 0x4e, 0x5d, 0xf8, 0x02, 0xb1, 0xd2, 0x02, 0xa6, 0x99, 0x30, 0xf6, 0xe9, 0xf6, 0xa3, 0x92, 0xc9, 0x5d, 0xc6, + 0x5f, 0x49, 0x55, 0x79, 0x3a, 0xcf, 0x02, 0x88, 0xf5, 0x2a, 0x95, 0x62, 0xdd, 0x2b, 0x66, 0x0b, 0xfd, 0xcd, 0xc6, + 0xdc, 0x48, 0xb2, 0xe5, 0x70, 0xa6, 0xaf, 0xba, 0xb6, 0x83, 0x8a, 0x78, 0x22, 0xac, 0x19, 0x13, 0xab, 0x77, 0xce, + 0x42, 0x08, 0xbc, 0xb0, 0x50, 0x25, 0x2c, 0xd6, 0x26, 0x09, 0x2a, 0x52, 0x28, 0x32, 0x48, 0xe1, 0xb2, 0x9d, 0xb4, + 0x5a, 0x05, 0x42, 0x88, 0x8c, 0xeb, 0x81, 0xf0, 0x6d, 0x76, 0xf6, 0xf6, 0xf2, 0xea, 0x44, 0x1b, 0x53, 0x38, 0x5f, + 0x2e, 0x39, 0x75, 0x72, 0x79, 0xea, 0x26, 0x22, 0xa0, 0x8c, 0x31, 0x2c, 0xdf, 0x78, 0x29, 0x2e, 0x7b, 0xf2, 0xf2, + 0xa2, 0x17, 0x09, 0x24, 0x4a, 0x94, 0x11, 0x8d, 0xd4, 0x13, 0xad, 0x92, 0x61, 0xf3, 0x75, 0x79, 0x90, 0xbf, 0x86, + 0xf5, 0xf6, 0xca, 0xe2, 0x48, 0xab, 0x2a, 0x5a, 0x2d, 0xcd, 0xd3, 0x8c, 0x3b, 0x8e, 0x8f, 0x03, 0x44, 0xfa, 0xbe, + 0x98, 0xfd, 0xb1, 0xcc, 0xf7, 0x18, 0x34, 0x3b, 0x5e, 0xa7, 0xf4, 0x87, 0xd4, 0xce, 0x57, 0xcb, 0x6c, 0x33, 0x75, + 0x46, 0x17, 0xf0, 0x84, 0xcb, 0xdf, 0x0a, 0x7d, 0x55, 0x81, 0x9c, 0x5d, 0xf5, 0x5c, 0x4e, 0x12, 0x2b, 0x86, 0x26, + 0x95, 0x01, 0xa7, 0x06, 0xd5, 0x30, 0x1b, 0x61, 0xb6, 0x65, 0x6c, 0x54, 0x54, 0x88, 0x28, 0x37, 0xf7, 0x85, 0x54, + 0x82, 0xce, 0x0d, 0xea, 0xbe, 0x60, 0xda, 0x8d, 0x57, 0xa7, 0xbb, 0x42, 0xa1, 0xc8, 0xe0, 0x0c, 0x9b, 0xaa, 0x49, + 0x58, 0x6e, 0x49, 0xb2, 0x91, 0x78, 0x5d, 0xf9, 0x48, 0x25, 0x6d, 0x6c, 0xae, 0x22, 0x92, 0x21, 0x37, 0x01, 0x06, + 0x8e, 0x81, 0x9c, 0xeb, 0x29, 0x00, 0x8f, 0x19, 0x53, 0x38, 0xa9, 0xa4, 0x38, 0x0e, 0x5e, 0x48, 0xed, 0xde, 0xb3, + 0xdf, 0xbe, 0x39, 0x7b, 0x6f, 0x63, 0xb8, 0xea, 0x8c, 0x66, 0xb9, 0xb7, 0xb0, 0x55, 0x8e, 0x61, 0x13, 0xe2, 0xd5, + 0xb6, 0x67, 0xfb, 0x33, 0x38, 0xb4, 0x2d, 0x98, 0x6a, 0xeb, 0xa6, 0x79, 0x7d, 0x7d, 0xdd, 0x84, 0x13, 0x65, 0xcd, + 0x79, 0x16, 0x4b, 0x76, 0x13, 0xda, 0x45, 0x81, 0x5c, 0x1e, 0xd1, 0xa4, 0xbc, 0x0c, 0x29, 0x8d, 0xa9, 0x1b, 0xa7, + 0x13, 0x79, 0x1e, 0x76, 0xd5, 0x3d, 0x11, 0x5f, 0x1c, 0x8b, 0x4b, 0xbe, 0xfa, 0xc7, 0x5c, 0x5e, 0xaf, 0xc6, 0x33, + 0xf8, 0xd9, 0x87, 0xe0, 0xd5, 0x71, 0x8b, 0x47, 0xe2, 0xe1, 0x0c, 0x76, 0x93, 0x78, 0xda, 0x5d, 0xac, 0x51, 0xdd, + 0x00, 0xba, 0x88, 0xfa, 0x72, 0x6a, 0xb9, 0xa8, 0x75, 0xe1, 0xc5, 0x17, 0x17, 0xc5, 0x71, 0x0b, 0xfa, 0x6a, 0xe9, + 0x7e, 0x2f, 0xd3, 0xf0, 0x56, 0xb7, 0x2f, 0x29, 0x11, 0x2e, 0x7b, 0x4a, 0x48, 0x1f, 0xba, 0x80, 0x71, 0xc3, 0xbe, + 0xc0, 0x99, 0x62, 0xa1, 0xc3, 0xea, 0xa1, 0x18, 0x59, 0xc0, 0x30, 0x0b, 0x28, 0x01, 0x72, 0x83, 0xce, 0xc3, 0xb2, + 0x81, 0xd8, 0xed, 0xb2, 0x68, 0x1b, 0x80, 0xb2, 0x62, 0xb5, 0x7f, 0xa4, 0x9b, 0xbb, 0x22, 0x0b, 0x0d, 0x71, 0x68, + 0x02, 0x7f, 0x81, 0xe0, 0x5f, 0x01, 0xf8, 0x71, 0x4b, 0xa2, 0xe9, 0xc2, 0xbc, 0x76, 0x46, 0x5e, 0x08, 0x51, 0x22, + 0x73, 0x98, 0x71, 0xfc, 0x9e, 0xe3, 0x8f, 0x17, 0xa2, 0xaa, 0xd6, 0x12, 0x40, 0x7d, 0x05, 0x6d, 0xaa, 0xad, 0xd5, + 0xc1, 0x20, 0x8d, 0x63, 0x7f, 0x96, 0x53, 0x4f, 0xff, 0x50, 0x0a, 0x03, 0xe8, 0x1d, 0xeb, 0x1a, 0x9a, 0xca, 0x7b, + 0x3a, 0x05, 0x3d, 0x6e, 0x5d, 0x7d, 0xbc, 0xf2, 0x33, 0xa7, 0xd9, 0x0c, 0x9a, 0x97, 0x13, 0x54, 0xf0, 0x68, 0x61, + 0xaa, 0x1b, 0x0f, 0xdb, 0xed, 0x1e, 0x24, 0xa9, 0x36, 0xfd, 0x98, 0x4d, 0x12, 0x2f, 0xa6, 0x63, 0x5e, 0x70, 0x38, + 0x3d, 0xb8, 0xd0, 0xfa, 0x9d, 0xdb, 0x3d, 0xcc, 0xe8, 0xd4, 0x72, 0xe1, 0xef, 0xdd, 0x03, 0x17, 0x3c, 0xf4, 0x12, + 0x1e, 0x35, 0x45, 0x32, 0x34, 0x1c, 0xe5, 0xe0, 0x51, 0xed, 0x79, 0x61, 0x0c, 0x14, 0x50, 0xd0, 0x7d, 0x0b, 0x9e, + 0x59, 0x3c, 0xc2, 0x3c, 0x33, 0xeb, 0x25, 0x68, 0xb1, 0x36, 0x83, 0x75, 0x15, 0x6c, 0x1f, 0x15, 0xb9, 0xb0, 0x58, + 0x16, 0x6b, 0x78, 0x31, 0x54, 0xe9, 0x82, 0x25, 0xb3, 0x39, 0x1f, 0x0a, 0xcf, 0x7f, 0x06, 0x67, 0x48, 0x46, 0xd8, + 0x28, 0x01, 0x78, 0x46, 0xaa, 0x7d, 0xe0, 0xc7, 0x81, 0x03, 0x9d, 0x58, 0x4d, 0xeb, 0x28, 0xa3, 0x53, 0xd4, 0x9b, + 0xb2, 0xa4, 0x29, 0xdf, 0x1d, 0x1a, 0xba, 0x9b, 0xfb, 0x08, 0x9e, 0x0a, 0x57, 0xf4, 0x86, 0x45, 0x82, 0xef, 0x86, + 0x79, 0x5d, 0x8c, 0x8a, 0xa2, 0x97, 0x72, 0x67, 0xf8, 0xc2, 0x41, 0x23, 0xfc, 0xab, 0x71, 0x89, 0x8d, 0xad, 0xa9, + 0xda, 0xc6, 0x5d, 0xb4, 0xa5, 0x8a, 0x49, 0x97, 0xa2, 0xda, 0xaf, 0x04, 0x2a, 0xbe, 0x74, 0x6c, 0x9a, 0xcf, 0x9a, + 0x92, 0xfd, 0x34, 0x05, 0xf9, 0xd8, 0xd0, 0x14, 0x29, 0x77, 0x36, 0xa5, 0x0b, 0xc1, 0x59, 0xd4, 0x39, 0x16, 0xe9, + 0x71, 0x19, 0x95, 0xe7, 0x9e, 0xd4, 0xb3, 0x79, 0xd2, 0x09, 0xd5, 0xb6, 0xfe, 0xc5, 0x49, 0x9d, 0x4d, 0x81, 0xfc, + 0x2f, 0xef, 0xfa, 0xf3, 0xe3, 0x18, 0x06, 0xbc, 0xd0, 0x4a, 0x83, 0x79, 0x35, 0xca, 0x90, 0x8f, 0x1c, 0x54, 0xa8, + 0x3d, 0xf3, 0x44, 0xe8, 0xdd, 0xc6, 0x05, 0x83, 0x3b, 0x5c, 0x47, 0xd4, 0xe4, 0x09, 0x66, 0x06, 0x39, 0x01, 0xb5, + 0xdc, 0xf1, 0x5e, 0xc5, 0x66, 0xa4, 0xd6, 0x6e, 0x89, 0x09, 0x11, 0x3b, 0x4b, 0x42, 0xdb, 0xfa, 0x73, 0x10, 0xb3, + 0xe0, 0x23, 0xb1, 0x77, 0x17, 0x0e, 0x5a, 0x3f, 0x1a, 0x2a, 0x76, 0xa8, 0xe6, 0xb9, 0xa8, 0x1e, 0x6d, 0xc8, 0x5c, + 0x83, 0x9d, 0xca, 0xdb, 0x83, 0xec, 0x3e, 0xa8, 0x36, 0xc7, 0x2d, 0x39, 0x4e, 0xff, 0xa2, 0x38, 0xaf, 0x6e, 0x05, + 0xab, 0xa0, 0x00, 0x34, 0xcb, 0x72, 0x4b, 0xd0, 0x1f, 0xb1, 0xe5, 0x16, 0xaa, 0x59, 0x80, 0xd8, 0xa4, 0x7d, 0x64, + 0x5b, 0x92, 0xc1, 0x00, 0x9c, 0x5c, 0xf1, 0x1a, 0xdb, 0xfa, 0x73, 0x59, 0x46, 0x4b, 0xb7, 0x8f, 0xc8, 0x5b, 0x21, + 0x36, 0x8c, 0x05, 0xb6, 0xbe, 0x1b, 0x52, 0xee, 0xb3, 0x58, 0x36, 0xe9, 0x69, 0x2f, 0xc5, 0xca, 0x8c, 0x96, 0xcb, + 0xbc, 0x3e, 0x17, 0x56, 0xc7, 0xa0, 0x98, 0xd9, 0x71, 0xab, 0x82, 0x5b, 0xcc, 0x4c, 0xec, 0x0f, 0x33, 0x7e, 0x5a, + 0xcd, 0x50, 0xbe, 0xb3, 0xfe, 0x1c, 0x88, 0x93, 0x55, 0x00, 0x60, 0xaa, 0x00, 0x84, 0xc8, 0xbe, 0x54, 0x42, 0x1c, + 0x9f, 0xa4, 0x2e, 0xf7, 0xb3, 0x09, 0xe5, 0x2b, 0x88, 0xf5, 0x65, 0x22, 0x6f, 0x4f, 0x47, 0xf1, 0xd7, 0xa0, 0x0d, + 0xea, 0xd0, 0x82, 0x9e, 0x5b, 0x0c, 0x40, 0x55, 0x25, 0x1b, 0x35, 0xde, 0x08, 0x81, 0xec, 0x13, 0x8b, 0x23, 0xb9, + 0x7d, 0x2a, 0xb8, 0xbd, 0x8c, 0xc3, 0x59, 0x62, 0x2c, 0x01, 0x62, 0x61, 0x5b, 0x03, 0x09, 0x39, 0x0d, 0x25, 0xcc, + 0x24, 0x13, 0xad, 0xd2, 0xe2, 0xb8, 0x25, 0x6b, 0x4b, 0x76, 0x2c, 0x2b, 0x01, 0x12, 0xc4, 0x3e, 0xad, 0x70, 0x00, + 0xc9, 0xdf, 0x26, 0x1e, 0x42, 0x76, 0x55, 0x12, 0x9b, 0x38, 0x63, 0xd6, 0x3f, 0x8e, 0xfd, 0x4b, 0x1a, 0xf7, 0x77, + 0x17, 0xd9, 0x72, 0xd9, 0x2e, 0x8e, 0x5b, 0xf2, 0xd1, 0x3a, 0x16, 0x7c, 0x43, 0xde, 0x0d, 0x2a, 0x96, 0x18, 0x0e, + 0x6e, 0x42, 0x4a, 0xac, 0xce, 0x05, 0xf3, 0x54, 0x07, 0x85, 0x6d, 0x89, 0x2c, 0x14, 0x51, 0xa9, 0xd4, 0x69, 0x0a, + 0xdb, 0x62, 0xe1, 0x7a, 0x59, 0xce, 0xe9, 0x0c, 0x4a, 0xa3, 0xe5, 0xb2, 0x53, 0xd8, 0xd6, 0x94, 0x25, 0xf0, 0x94, + 0x2d, 0x97, 0xe2, 0x4c, 0xe4, 0x94, 0x25, 0x4e, 0x1b, 0xc8, 0xd6, 0xb6, 0xa6, 0xfe, 0x8d, 0x98, 0xb0, 0x7e, 0xe3, + 0xdf, 0x38, 0x1d, 0xf5, 0xca, 0x2d, 0xf1, 0x93, 0x03, 0xc5, 0x55, 0x2b, 0xea, 0xab, 0x15, 0x0d, 0xf1, 0x5c, 0x9e, + 0xf6, 0x22, 0x4e, 0x48, 0xfc, 0xcd, 0x2b, 0x1a, 0xea, 0x15, 0x9d, 0x6f, 0x59, 0xd1, 0xf9, 0x1d, 0x2b, 0x1a, 0xa8, + 0xd5, 0xb3, 0x4a, 0xdc, 0xa5, 0xcb, 0x65, 0xa7, 0x5d, 0x61, 0xef, 0xb8, 0x15, 0xb2, 0x2b, 0x58, 0x0d, 0xd0, 0xd4, + 0x38, 0x9b, 0xd2, 0xcd, 0x44, 0x59, 0x47, 0x31, 0xfd, 0x2c, 0x4c, 0x56, 0x58, 0xc8, 0xea, 0x58, 0x30, 0xe9, 0xba, + 0x0c, 0x4c, 0xfe, 0x91, 0x94, 0xcd, 0x00, 0x0f, 0x39, 0xe0, 0x21, 0xd2, 0x77, 0x85, 0x3a, 0xf6, 0x7b, 0x1b, 0xdb, + 0x96, 0xad, 0xc9, 0xfa, 0xa2, 0x38, 0x07, 0x19, 0x21, 0xe6, 0x77, 0x2f, 0x5a, 0x84, 0xda, 0x76, 0x7f, 0x3b, 0xcd, + 0x41, 0x0e, 0xc1, 0x75, 0x9a, 0x85, 0xb6, 0x27, 0xab, 0x7e, 0x16, 0xaa, 0xa6, 0x2c, 0x51, 0x19, 0x69, 0x5b, 0x69, + 0xad, 0x7a, 0x6f, 0x52, 0x5c, 0xf7, 0xf0, 0x50, 0xd6, 0x98, 0xf9, 0x9c, 0xd3, 0x2c, 0x51, 0x94, 0x6b, 0xdb, 0xff, + 0x21, 0xa8, 0x70, 0x03, 0x5f, 0x09, 0xf4, 0x02, 0x68, 0x02, 0x54, 0x3a, 0xb7, 0xe2, 0xf9, 0x52, 0x3c, 0xed, 0x54, + 0xca, 0xe6, 0x2d, 0x32, 0xf5, 0x7e, 0x59, 0x04, 0x66, 0xc8, 0x7c, 0x4a, 0xc3, 0x73, 0xc1, 0xa0, 0x07, 0xf1, 0x85, + 0x52, 0x1e, 0x57, 0xc4, 0x5d, 0xd5, 0x00, 0xdb, 0x3f, 0xcd, 0xbb, 0x8f, 0x0e, 0x4e, 0x6d, 0x2c, 0x79, 0x7c, 0x3a, + 0x1e, 0xdb, 0xa8, 0xb0, 0xee, 0xd7, 0xac, 0x73, 0xf0, 0xd3, 0xfc, 0xeb, 0x67, 0xed, 0xaf, 0xcb, 0xc6, 0x09, 0x10, + 0x91, 0x4a, 0x82, 0xd0, 0xa2, 0xca, 0x80, 0x57, 0xcf, 0x68, 0xec, 0x27, 0xdb, 0xa7, 0x33, 0x34, 0xa7, 0x93, 0xcf, + 0x28, 0x0d, 0x81, 0x38, 0xf1, 0x5a, 0xe9, 0x79, 0x4c, 0xaf, 0xa8, 0xbe, 0xa1, 0x71, 0xc3, 0x60, 0x1b, 0x5a, 0x04, + 0xe9, 0x3c, 0xe1, 0x2a, 0x1b, 0x44, 0xb1, 0x5a, 0x63, 0x4a, 0x17, 0x62, 0x0e, 0xa6, 0x3a, 0x7f, 0x2b, 0xe5, 0x5c, + 0x5d, 0x7a, 0x15, 0x17, 0xd8, 0x36, 0x00, 0xd8, 0x0a, 0xd9, 0x60, 0x4b, 0xb9, 0xd7, 0xc6, 0xed, 0x6d, 0xb0, 0xe1, + 0x0e, 0xf2, 0x6c, 0x7b, 0xa4, 0xf1, 0x24, 0x1c, 0xba, 0xb5, 0x4b, 0x35, 0xb6, 0xe2, 0xeb, 0x93, 0x18, 0xb8, 0xcc, + 0xa0, 0xb3, 0x84, 0xe6, 0xf9, 0x56, 0x04, 0x94, 0x8b, 0x88, 0xed, 0xaa, 0xb6, 0xbd, 0xa5, 0x17, 0xdc, 0xc6, 0xb0, + 0xc3, 0x04, 0xc0, 0x65, 0x58, 0x59, 0xd5, 0xa2, 0xe3, 0x31, 0x0d, 0x4a, 0x7f, 0x38, 0x04, 0x08, 0xc7, 0x2c, 0xe6, + 0x10, 0x27, 0x13, 0x01, 0x2c, 0xfb, 0x75, 0x9a, 0x50, 0x1b, 0xe9, 0x94, 0x57, 0x05, 0xbf, 0x92, 0xff, 0x9b, 0xe1, + 0x91, 0x3d, 0xd6, 0x61, 0x51, 0xa3, 0x2c, 0x97, 0xda, 0x5d, 0x53, 0x2b, 0xaf, 0x23, 0x32, 0x15, 0xfe, 0x98, 0x6d, + 0x1b, 0xe8, 0x7e, 0xdb, 0x64, 0xd1, 0xf9, 0xfa, 0xb0, 0xd3, 0x2e, 0x6c, 0x6c, 0x43, 0x77, 0xf7, 0xdd, 0x25, 0xa2, + 0xd5, 0x3e, 0xb4, 0x9a, 0x27, 0x9f, 0xd3, 0xae, 0xdb, 0x79, 0xdc, 0xb1, 0xb1, 0xbc, 0x6b, 0x01, 0x15, 0x25, 0x33, + 0x08, 0xc0, 0x43, 0xfc, 0xbb, 0xa7, 0x52, 0xef, 0xfc, 0x7e, 0xf0, 0x3c, 0xec, 0xb4, 0x6d, 0x6c, 0xe7, 0x3c, 0x9d, + 0x7d, 0xc6, 0x14, 0xf6, 0x6d, 0x6c, 0x07, 0x71, 0x9a, 0x53, 0x73, 0x0e, 0x52, 0x9d, 0xfd, 0xfd, 0x93, 0x90, 0x10, + 0xcd, 0x32, 0x9a, 0xe7, 0x96, 0xd9, 0xbf, 0x22, 0xa5, 0x4f, 0x30, 0xcc, 0x8d, 0x14, 0x97, 0x53, 0x2e, 0xf0, 0x22, + 0xaf, 0x41, 0x30, 0xa9, 0x4a, 0x96, 0xad, 0x11, 0x9b, 0x10, 0x01, 0x25, 0x63, 0x93, 0xda, 0xd5, 0x27, 0x47, 0xde, + 0xb0, 0xf5, 0xe4, 0xc0, 0x32, 0x70, 0xbe, 0x3e, 0x40, 0xad, 0x64, 0xca, 0x92, 0xf3, 0x0d, 0xa5, 0xfe, 0xcd, 0x86, + 0x52, 0x50, 0xd9, 0x4a, 0xe8, 0xd4, 0x15, 0x3d, 0x9f, 0xc6, 0x7a, 0xa5, 0xf8, 0x98, 0x20, 0x86, 0xc2, 0xff, 0xf8, + 0x09, 0x48, 0x8d, 0x65, 0x10, 0x3d, 0xfc, 0xf6, 0xe1, 0xa0, 0xe4, 0x73, 0x86, 0x2b, 0x7b, 0xf9, 0x7d, 0x33, 0x84, + 0xd2, 0x26, 0x38, 0xf9, 0xe3, 0xcf, 0x9a, 0x2b, 0xbd, 0xf9, 0x34, 0xc1, 0x19, 0x5a, 0xd5, 0xef, 0x58, 0x7a, 0x75, + 0xd4, 0x7f, 0x75, 0xed, 0x37, 0x14, 0x2b, 0xc5, 0xa7, 0x5c, 0xff, 0x20, 0x66, 0xd3, 0x8a, 0x04, 0xd6, 0xc1, 0x14, + 0x1a, 0x0f, 0x64, 0x7c, 0x99, 0x9d, 0x48, 0xd5, 0xe7, 0x1c, 0xce, 0xb1, 0xc2, 0x55, 0x21, 0xf3, 0x8c, 0x9e, 0xc7, + 0xe9, 0xf5, 0xea, 0xe5, 0x67, 0xdb, 0x2b, 0x47, 0x6c, 0x12, 0x19, 0x87, 0xd3, 0x28, 0x29, 0x17, 0xe1, 0xce, 0x01, + 0x8a, 0x7f, 0xf9, 0x67, 0xd7, 0xfd, 0x97, 0x7f, 0xfe, 0x64, 0x55, 0xe8, 0xbe, 0xb8, 0xc0, 0xbc, 0xea, 0x76, 0xfb, + 0xee, 0xda, 0x3c, 0x52, 0x1d, 0xe7, 0x9b, 0xeb, 0xac, 0x2d, 0x02, 0xbc, 0x5f, 0x5b, 0x82, 0xb5, 0x42, 0xb9, 0xfb, + 0xac, 0xdf, 0x02, 0x18, 0xcc, 0xeb, 0x93, 0x90, 0x41, 0xa5, 0xdf, 0x05, 0xda, 0x05, 0xf2, 0xee, 0xb5, 0x22, 0xbf, + 0x1d, 0xc3, 0x9f, 0x9a, 0xc3, 0xef, 0x04, 0x5f, 0xf9, 0x27, 0xe2, 0x8b, 0x8b, 0x32, 0x0b, 0xd1, 0x6c, 0x0a, 0x77, + 0x1c, 0x0c, 0xd6, 0x4a, 0x94, 0xe2, 0xe1, 0xb5, 0x51, 0x5f, 0x9c, 0xa1, 0x24, 0xf1, 0xc5, 0x2b, 0xb8, 0xd8, 0xe8, + 0xf8, 0x32, 0xd3, 0xce, 0xd6, 0x3b, 0x84, 0x03, 0x74, 0x51, 0x9f, 0x95, 0xe8, 0x74, 0x4d, 0x32, 0x40, 0x29, 0x98, + 0x1b, 0x00, 0x26, 0x8e, 0x2f, 0x94, 0xb5, 0x79, 0x2a, 0xdd, 0x30, 0xde, 0x2a, 0x69, 0x2b, 0xf7, 0x4c, 0x0d, 0xe9, + 0xd8, 0x7a, 0x2f, 0xf0, 0x25, 0x2a, 0xd3, 0xca, 0xba, 0x17, 0xae, 0x2e, 0xb0, 0x23, 0x4a, 0xf6, 0x73, 0xe5, 0xc7, + 0x57, 0xf7, 0x63, 0x7c, 0xdb, 0x05, 0xea, 0xd2, 0x5a, 0xfe, 0xa3, 0x55, 0x82, 0x65, 0x73, 0xb9, 0x49, 0x1f, 0xb8, + 0xf6, 0x39, 0xcd, 0xce, 0x23, 0x48, 0x84, 0xca, 0x3e, 0xc1, 0x9c, 0x60, 0xa5, 0x31, 0x15, 0x7f, 0x19, 0x51, 0x17, + 0x49, 0xff, 0x83, 0x38, 0x15, 0x83, 0x2c, 0x46, 0x18, 0xca, 0x58, 0x84, 0xff, 0xcf, 0xb7, 0xfe, 0xc3, 0xf0, 0xad, + 0xbb, 0x87, 0xa8, 0x9d, 0x91, 0xfe, 0xec, 0x85, 0xfc, 0x8f, 0xcd, 0xee, 0x72, 0xc1, 0xee, 0x7e, 0x03, 0xa3, 0xcb, + 0xff, 0x31, 0x8c, 0x4e, 0xd8, 0xc8, 0x9a, 0xd3, 0xad, 0x85, 0x9a, 0x6f, 0x5d, 0xff, 0xda, 0xbf, 0xad, 0xf6, 0x55, + 0x7c, 0x71, 0x72, 0xed, 0xdf, 0x56, 0x8b, 0xb0, 0x9d, 0x5d, 0xac, 0xf6, 0x31, 0xb0, 0xdf, 0xbc, 0xb6, 0x3d, 0xfb, + 0xcd, 0xd7, 0x5f, 0xdb, 0xf8, 0x22, 0xa7, 0x7c, 0x00, 0x85, 0x64, 0x77, 0xb1, 0xb3, 0x5a, 0x11, 0xdc, 0x28, 0x30, + 0x45, 0x11, 0xf6, 0x82, 0xa4, 0x43, 0xe3, 0x3d, 0xcb, 0xcf, 0xd3, 0xc4, 0x84, 0xe6, 0x2d, 0x58, 0xf6, 0x9f, 0x0b, + 0x8e, 0xe8, 0x65, 0x0d, 0x1e, 0x51, 0xba, 0x0a, 0x90, 0x28, 0xac, 0x41, 0x54, 0x5d, 0x19, 0x74, 0x37, 0xff, 0xaf, + 0xae, 0x45, 0x90, 0xb7, 0x7d, 0x44, 0x83, 0xf8, 0xe2, 0x73, 0xc4, 0x87, 0x1c, 0xac, 0xf2, 0xd8, 0x69, 0x77, 0xa7, + 0x5f, 0xec, 0x2e, 0xa2, 0xbd, 0x3d, 0x36, 0xb0, 0xb1, 0xb8, 0xa7, 0xa9, 0xd8, 0x24, 0x5c, 0x72, 0xf8, 0x93, 0xc1, + 0x9f, 0xb4, 0x62, 0xd4, 0x2c, 0x19, 0x67, 0x7e, 0x46, 0xc3, 0xed, 0x4c, 0xba, 0xbc, 0xdf, 0x48, 0x91, 0x86, 0x4c, + 0xc0, 0xce, 0xcf, 0x45, 0xea, 0xd1, 0x94, 0x81, 0x3e, 0xba, 0x63, 0x7e, 0xc5, 0x47, 0x5d, 0x88, 0x56, 0x7e, 0x04, + 0xc0, 0x44, 0x38, 0x25, 0x79, 0x99, 0xeb, 0x00, 0xb7, 0x6a, 0xaa, 0xec, 0x10, 0x6c, 0x23, 0xe1, 0x75, 0x0f, 0x49, + 0x5f, 0xa4, 0x3d, 0xbc, 0x48, 0xb8, 0x13, 0xba, 0x3c, 0x63, 0x53, 0x07, 0xe1, 0x4e, 0x1b, 0x21, 0xed, 0x6c, 0x08, + 0x49, 0x7f, 0x87, 0xe5, 0xaf, 0xfd, 0xd7, 0x4e, 0x28, 0x2e, 0xe2, 0x12, 0x9f, 0xee, 0x81, 0x43, 0x92, 0x4f, 0xe6, + 0xe3, 0x31, 0xcd, 0x1c, 0x7d, 0x00, 0xf0, 0xab, 0x03, 0x38, 0x63, 0x0c, 0x6f, 0x9f, 0xfa, 0xdc, 0xff, 0x96, 0xd1, + 0x6b, 0x27, 0x45, 0xbd, 0xac, 0xba, 0x9c, 0x31, 0xc4, 0x73, 0x44, 0xfa, 0x11, 0x24, 0xc6, 0xbf, 0x48, 0xf8, 0x7e, + 0xd7, 0x99, 0x7f, 0x75, 0x80, 0x43, 0xb8, 0xf2, 0x42, 0x67, 0x75, 0xcb, 0xbb, 0x4a, 0x3e, 0xb0, 0x84, 0x1f, 0xc9, + 0x63, 0x98, 0x29, 0x52, 0xee, 0xc3, 0x32, 0x23, 0xc6, 0xf2, 0xcb, 0x0e, 0x43, 0xd2, 0x0f, 0x1a, 0x44, 0x1e, 0xca, + 0x14, 0xb7, 0xec, 0x9e, 0x46, 0x7e, 0x76, 0x0a, 0x07, 0xbe, 0x01, 0xd0, 0x4b, 0x9e, 0xfa, 0x4e, 0x50, 0x7e, 0xc9, + 0xc9, 0x69, 0xfd, 0xd4, 0x68, 0x4d, 0xb0, 0x48, 0x8a, 0xa9, 0x8a, 0x5a, 0x50, 0x74, 0x6e, 0x16, 0x91, 0xc6, 0x6e, + 0x0b, 0xc3, 0x1e, 0xec, 0x6d, 0xf4, 0xd1, 0xea, 0xa5, 0x6b, 0x5e, 0x67, 0xfe, 0xac, 0x8c, 0x1b, 0x9c, 0xfa, 0x59, + 0xc6, 0x68, 0x66, 0x39, 0xcf, 0x7f, 0x45, 0xde, 0xbf, 0xfc, 0xf3, 0xe6, 0xf8, 0x81, 0x0a, 0x19, 0x58, 0x90, 0x5c, + 0xd2, 0x14, 0xe9, 0xd8, 0xc4, 0x0e, 0x64, 0x43, 0x5b, 0x87, 0x3b, 0xf6, 0x8f, 0xda, 0xed, 0xb6, 0x0a, 0x09, 0x74, + 0xe4, 0x4f, 0x88, 0x01, 0xc0, 0x4f, 0x78, 0x10, 0x51, 0x65, 0x62, 0xcb, 0x00, 0xe5, 0x51, 0x7b, 0x76, 0x63, 0xf7, + 0x61, 0x3b, 0x28, 0x28, 0xde, 0xd1, 0x19, 0xf5, 0xf9, 0x67, 0x8d, 0x9f, 0x89, 0x26, 0xe5, 0xf0, 0x1d, 0x3d, 0x74, + 0x35, 0xee, 0xca, 0xa0, 0x87, 0xab, 0x83, 0xbe, 0x67, 0x53, 0x71, 0x75, 0xd3, 0xb6, 0x51, 0x85, 0xa7, 0xba, 0x36, + 0x26, 0x97, 0x2d, 0x6c, 0x4b, 0x60, 0x3c, 0x4a, 0xe3, 0x90, 0x66, 0xc4, 0xa6, 0xee, 0xc4, 0xb5, 0x1e, 0xb7, 0xdb, + 0x6d, 0xdc, 0x3c, 0x38, 0x6c, 0xb7, 0xf1, 0xe1, 0xc3, 0x36, 0x6e, 0xc2, 0x1f, 0xd7, 0x75, 0x57, 0x60, 0xb8, 0x2b, + 0x6a, 0xdb, 0x69, 0x67, 0x74, 0xaa, 0x00, 0xbc, 0x33, 0xac, 0x58, 0xed, 0x09, 0xb8, 0x60, 0x5a, 0xed, 0x7b, 0x29, + 0xd9, 0xd4, 0x05, 0x07, 0x2a, 0x1d, 0x55, 0xf8, 0x0b, 0xd3, 0x2a, 0x68, 0x4a, 0xe5, 0xc5, 0x7f, 0x2f, 0x14, 0x21, + 0x78, 0xd6, 0x29, 0xdc, 0x5e, 0x2a, 0xe2, 0xa5, 0x90, 0x0a, 0x04, 0x1f, 0x48, 0xe3, 0x3e, 0x4b, 0xe0, 0xdb, 0x59, + 0x3a, 0x6a, 0xaa, 0x19, 0x55, 0xba, 0x92, 0x74, 0xfb, 0x40, 0x86, 0xa5, 0x37, 0x11, 0xc4, 0xe8, 0x01, 0xc2, 0xfe, + 0x7d, 0x1a, 0xa8, 0x15, 0x84, 0xfa, 0xc1, 0x7d, 0xea, 0x6b, 0xec, 0x8f, 0x1e, 0x88, 0xe4, 0xa4, 0x9d, 0x68, 0xb9, + 0xdc, 0xf1, 0x97, 0xcb, 0x9d, 0xe0, 0xfe, 0x33, 0x94, 0xcb, 0xab, 0x4f, 0x41, 0xc0, 0xcd, 0x9f, 0x12, 0xe8, 0x17, + 0x50, 0xee, 0x45, 0x58, 0x82, 0x24, 0x9f, 0x7c, 0xac, 0x06, 0x94, 0x8f, 0x41, 0xb1, 0x82, 0x94, 0x90, 0x44, 0xd2, + 0x3e, 0x5f, 0x2e, 0x15, 0xf1, 0xe3, 0x39, 0xf1, 0xcb, 0xa2, 0x8e, 0x8d, 0x67, 0x24, 0x28, 0x1f, 0x6d, 0x01, 0xf2, + 0x4c, 0x71, 0xa9, 0x0a, 0xe2, 0x6b, 0x3f, 0x4b, 0x4c, 0x80, 0x5f, 0xa7, 0x96, 0x1a, 0xd6, 0x9a, 0x65, 0xe9, 0x15, + 0x83, 0xe4, 0x97, 0x95, 0x81, 0xa7, 0x04, 0x2e, 0xfe, 0xea, 0x99, 0xa1, 0x70, 0xa3, 0x83, 0xf7, 0x9a, 0xcf, 0xc2, + 0x2d, 0x93, 0xe5, 0x04, 0xbd, 0x50, 0xcd, 0xcd, 0x9b, 0xeb, 0x69, 0xbd, 0xf3, 0xaf, 0xbd, 0x99, 0x7e, 0x78, 0x26, + 0xf3, 0x6c, 0xbc, 0x69, 0x79, 0xb2, 0xe6, 0x2d, 0x79, 0x0d, 0xb1, 0x1f, 0x5b, 0xf3, 0x6d, 0xb8, 0x67, 0x53, 0xf2, + 0xb8, 0x77, 0x2f, 0xcf, 0xa8, 0x9f, 0x05, 0xd1, 0x5b, 0x3f, 0xf3, 0xa7, 0x79, 0x6f, 0xac, 0x6f, 0xf1, 0xd2, 0x14, + 0x70, 0x3e, 0x16, 0x99, 0x4e, 0x49, 0x70, 0x6b, 0xe3, 0x10, 0xe1, 0xea, 0xbd, 0x84, 0x40, 0xfa, 0xb9, 0x6d, 0x3c, + 0x37, 0x5f, 0xc1, 0x3a, 0xdb, 0x78, 0x8a, 0xb0, 0x4c, 0x20, 0x7a, 0xfb, 0x47, 0xa6, 0x0e, 0x61, 0xc8, 0x75, 0xf1, + 0xc6, 0x6e, 0xf5, 0x95, 0x3b, 0x9d, 0x4c, 0xf4, 0x7e, 0x25, 0x99, 0x68, 0x03, 0x1a, 0xad, 0x8c, 0xe6, 0xb3, 0x34, + 0xc9, 0xa9, 0x8d, 0xdf, 0x43, 0x3b, 0x79, 0x15, 0xb3, 0xd9, 0x70, 0x8d, 0xe6, 0xca, 0xa6, 0xe2, 0x8d, 0x6c, 0x07, + 0x41, 0x9d, 0xf7, 0xdf, 0x97, 0x71, 0x7c, 0x1d, 0xdf, 0x11, 0x89, 0xe8, 0x8c, 0x6e, 0xc9, 0x95, 0xcd, 0xe9, 0x27, + 0x73, 0x65, 0xe3, 0x7b, 0xe5, 0xca, 0xe6, 0xf4, 0x8f, 0xce, 0x95, 0x65, 0xd4, 0xc8, 0x95, 0x05, 0x39, 0xf7, 0xf5, + 0xbd, 0x52, 0x2e, 0x75, 0x26, 0x5c, 0x7a, 0x9d, 0x93, 0x8e, 0x8a, 0x81, 0xc4, 0xe9, 0x04, 0xf2, 0x2d, 0xff, 0xf1, + 0xe9, 0x93, 0x71, 0x3a, 0x31, 0x93, 0x27, 0xe1, 0xc3, 0x24, 0x40, 0x76, 0x38, 0x23, 0x0b, 0xfb, 0xa7, 0x9b, 0xce, + 0x93, 0x61, 0xa7, 0xb7, 0xdf, 0x99, 0xda, 0x9e, 0x0d, 0x4e, 0x47, 0x51, 0xd0, 0xee, 0xed, 0xef, 0x43, 0xc1, 0xb5, + 0x51, 0xd0, 0x85, 0x02, 0x66, 0x14, 0x1c, 0x42, 0x41, 0x60, 0x14, 0x3c, 0x84, 0x82, 0xd0, 0x28, 0x78, 0x04, 0x05, + 0x57, 0x76, 0x31, 0x64, 0x65, 0x42, 0xf0, 0x23, 0x24, 0x6e, 0x30, 0xdc, 0xc9, 0xea, 0xa7, 0xb7, 0x23, 0xa2, 0xab, + 0x3c, 0x2a, 0x6f, 0x7e, 0x68, 0x1e, 0xe8, 0x8b, 0x0a, 0x2f, 0xbe, 0xb8, 0x00, 0xd6, 0x0a, 0x17, 0xb1, 0x60, 0x88, + 0x49, 0xca, 0x9a, 0xfb, 0xfa, 0xb5, 0xed, 0x95, 0x59, 0xb3, 0x6d, 0xdc, 0xd5, 0x79, 0xb3, 0x9e, 0x8d, 0x04, 0x5f, + 0x92, 0x2f, 0x0e, 0x1b, 0xa1, 0xea, 0x16, 0xee, 0x00, 0xac, 0x2e, 0xe0, 0xdc, 0x47, 0x78, 0xaa, 0x15, 0x20, 0xea, + 0xc0, 0x07, 0x18, 0xde, 0xb3, 0x29, 0xd5, 0xfb, 0x45, 0x0f, 0x60, 0x89, 0xcc, 0xe2, 0x5e, 0x54, 0x29, 0x46, 0x6f, + 0xf1, 0xb8, 0xba, 0xf3, 0xf5, 0x3d, 0x91, 0x77, 0xe8, 0x65, 0x58, 0x86, 0xb9, 0x66, 0x98, 0xfb, 0x13, 0x0f, 0x52, + 0x28, 0x21, 0x63, 0xc4, 0x1b, 0x13, 0x42, 0xda, 0x83, 0xb9, 0xf7, 0x16, 0x5f, 0x47, 0x34, 0xf1, 0xa6, 0x45, 0xaf, + 0x5c, 0x7f, 0x99, 0xd2, 0xf9, 0xbe, 0xbc, 0x28, 0x5c, 0xd0, 0x44, 0xf5, 0x56, 0x42, 0xd9, 0x2c, 0x69, 0x67, 0x4b, + 0xce, 0x9f, 0xa1, 0xec, 0x8c, 0xe3, 0xf4, 0xba, 0x09, 0xe2, 0x7e, 0x63, 0x1e, 0x20, 0xcc, 0xad, 0xcc, 0x03, 0x7c, + 0x09, 0xb0, 0x96, 0x4f, 0xef, 0xfd, 0x49, 0xf9, 0xfb, 0x15, 0xcd, 0x73, 0x7f, 0xa2, 0x6a, 0x6e, 0xcf, 0xfb, 0x13, + 0x20, 0x9a, 0x39, 0x7f, 0x1a, 0x08, 0x48, 0xce, 0x03, 0x84, 0x40, 0x40, 0x57, 0xe5, 0xea, 0xc1, 0xcc, 0xeb, 0x69, + 0x7e, 0x02, 0x55, 0xf5, 0x22, 0xee, 0x4f, 0xaa, 0x82, 0xe3, 0x59, 0x46, 0x55, 0x02, 0x21, 0x60, 0xb1, 0x38, 0x6e, + 0x41, 0x81, 0x7c, 0xbd, 0x25, 0x9d, 0x4f, 0x73, 0x97, 0xed, 0x49, 0x7d, 0x96, 0x4e, 0xe7, 0x33, 0x4f, 0xa6, 0x94, + 0xc7, 0x52, 0xd6, 0x33, 0xf2, 0xbe, 0xec, 0x04, 0xf0, 0x9f, 0x3a, 0x78, 0xf1, 0xe5, 0x78, 0x3c, 0xbe, 0x33, 0xbd, + 0xef, 0xcb, 0x70, 0x4c, 0xbb, 0xf4, 0xb0, 0x07, 0xa7, 0x16, 0x9a, 0x2a, 0x11, 0xad, 0x53, 0x08, 0xdc, 0x2d, 0xee, + 0x57, 0x19, 0x72, 0xd6, 0x78, 0xb4, 0xb8, 0x7f, 0xaa, 0x5f, 0x31, 0xcb, 0xe8, 0x62, 0xea, 0x67, 0x13, 0x96, 0x78, + 0xed, 0xc2, 0xbd, 0x5a, 0x28, 0x50, 0x8f, 0x8e, 0x8e, 0x0a, 0x37, 0xd4, 0x4f, 0xed, 0x30, 0x2c, 0xdc, 0x60, 0x51, + 0x4e, 0xa3, 0xdd, 0x1e, 0x8f, 0x0b, 0x97, 0xe9, 0x82, 0xfd, 0x6e, 0x10, 0xee, 0x77, 0x0b, 0xf7, 0xda, 0xa8, 0x51, + 0xb8, 0x54, 0x3d, 0x65, 0x34, 0xac, 0x1d, 0x7d, 0x78, 0xd4, 0x6e, 0x17, 0xae, 0x24, 0xb4, 0x05, 0xc4, 0xe4, 0xe4, + 0x4f, 0xcf, 0x9f, 0x73, 0x30, 0x98, 0x8a, 0x5e, 0xcc, 0x9d, 0xe1, 0xae, 0xba, 0x56, 0x52, 0x7e, 0x87, 0xb1, 0x40, + 0x23, 0xfc, 0xb5, 0x99, 0x39, 0x07, 0xc4, 0x2c, 0x32, 0xe6, 0x62, 0x9d, 0x58, 0x57, 0x7b, 0x0d, 0x94, 0x25, 0x5e, + 0x7f, 0x4d, 0xe2, 0x2a, 0xa1, 0x0e, 0xf8, 0x18, 0xd4, 0x94, 0xb7, 0x9f, 0x27, 0xdb, 0xa4, 0x47, 0xf6, 0x69, 0xe9, + 0x71, 0x79, 0x1f, 0xe1, 0x91, 0xfd, 0xe1, 0xc2, 0x23, 0x31, 0x85, 0x87, 0x64, 0x1d, 0xd7, 0x9c, 0xd8, 0x41, 0x44, + 0x83, 0x8f, 0x97, 0xe9, 0x4d, 0x13, 0xb6, 0x44, 0x66, 0x0b, 0xb1, 0x72, 0xf5, 0x5b, 0x33, 0xf9, 0x75, 0x67, 0xc6, + 0x47, 0x1c, 0x85, 0x8e, 0xff, 0x26, 0x21, 0xf6, 0x1b, 0x1d, 0xd8, 0x93, 0x25, 0xe3, 0x31, 0xb1, 0xdf, 0x8c, 0xc7, + 0xb6, 0xbe, 0x1c, 0xc7, 0xe7, 0x54, 0xd4, 0x7a, 0x5d, 0x2b, 0x11, 0xb5, 0xc0, 0xd0, 0xaf, 0xca, 0xcc, 0x02, 0x95, + 0x77, 0x67, 0xe6, 0xd8, 0xa9, 0x37, 0x21, 0xcb, 0x61, 0xab, 0xc1, 0xb7, 0x25, 0xeb, 0x97, 0xf3, 0x27, 0xb5, 0x2f, + 0x29, 0x95, 0x00, 0x6f, 0xf8, 0xfc, 0xd3, 0xea, 0xcd, 0x70, 0x13, 0xaa, 0x55, 0xfc, 0x27, 0xb7, 0x2f, 0x42, 0xe7, + 0x9a, 0xa3, 0x82, 0xe5, 0x6f, 0x92, 0x95, 0x5b, 0x1f, 0x24, 0x8c, 0x84, 0x98, 0xd3, 0x2a, 0x78, 0x3a, 0x99, 0xc4, + 0xe2, 0x30, 0x49, 0xcd, 0xe0, 0x96, 0xcd, 0x07, 0xb5, 0xf9, 0x7a, 0x66, 0x43, 0xf5, 0x79, 0x0d, 0xf1, 0xbd, 0x61, + 0x79, 0x5a, 0xf8, 0x4a, 0x7d, 0x78, 0x56, 0xc4, 0x04, 0x17, 0x8a, 0xc7, 0x2f, 0xe4, 0x19, 0x53, 0x8e, 0x59, 0x28, + 0x9b, 0xb3, 0xb0, 0x28, 0xd4, 0xe9, 0xfc, 0x90, 0xe5, 0x33, 0xd0, 0x9e, 0x64, 0x4b, 0xfa, 0x29, 0x16, 0x9e, 0x5f, + 0x1b, 0xc9, 0x6d, 0xb5, 0xe5, 0x2a, 0xb4, 0x9d, 0x26, 0xb3, 0x85, 0xae, 0x79, 0x61, 0x2b, 0x93, 0x4d, 0x23, 0xd1, + 0xb6, 0x24, 0x3e, 0x65, 0xda, 0x9d, 0x31, 0x43, 0xc8, 0xfc, 0x29, 0x17, 0x44, 0xbf, 0xd2, 0x05, 0x85, 0x69, 0x65, + 0x89, 0x37, 0x12, 0x5b, 0x22, 0x55, 0x2c, 0x9f, 0xf9, 0x89, 0x36, 0xe6, 0x24, 0x3f, 0xd8, 0x5d, 0x54, 0x2b, 0x5f, + 0xd8, 0x1a, 0x6c, 0x49, 0xbc, 0xfd, 0xe3, 0x16, 0x34, 0xe8, 0x5b, 0x35, 0xd0, 0x93, 0xb5, 0x0c, 0xb3, 0xbb, 0xf3, + 0xae, 0x3f, 0x5e, 0xb8, 0xf9, 0x35, 0x76, 0xf3, 0x6b, 0xeb, 0xab, 0x45, 0xf3, 0x9a, 0x5e, 0x7e, 0x64, 0xbc, 0xc9, + 0xfd, 0x59, 0x13, 0xbc, 0xa7, 0x22, 0x33, 0x44, 0xb1, 0x67, 0xa1, 0xa3, 0x4b, 0xd3, 0xaf, 0x37, 0xcf, 0x21, 0x3d, + 0x5b, 0x98, 0x51, 0x5e, 0x92, 0x26, 0xb4, 0x57, 0x3f, 0xbe, 0x67, 0x66, 0x18, 0x6b, 0x6c, 0x8d, 0x16, 0x29, 0xa4, + 0x73, 0xf3, 0x5b, 0xaf, 0xad, 0xd8, 0x7a, 0x5b, 0xa7, 0x0f, 0xb7, 0x37, 0xd6, 0xf7, 0x14, 0x72, 0x1b, 0x42, 0x7a, + 0x65, 0xeb, 0xf9, 0xcf, 0xdb, 0xf2, 0xbb, 0x3f, 0x75, 0x98, 0x0d, 0xf2, 0x49, 0xf4, 0xff, 0xc6, 0x29, 0xc0, 0xd5, + 0x62, 0x71, 0x98, 0xed, 0x3e, 0x90, 0x79, 0xfe, 0x98, 0xd3, 0x0c, 0xdf, 0xa7, 0xe6, 0xa5, 0xb8, 0x77, 0x62, 0x01, + 0x62, 0xc6, 0xeb, 0x1c, 0xd5, 0x53, 0xb1, 0xef, 0xee, 0xfe, 0xee, 0xe9, 0x17, 0x0a, 0x47, 0xfa, 0x1e, 0x56, 0xdb, + 0xee, 0xc1, 0x46, 0x88, 0xfd, 0x5b, 0x8f, 0x25, 0x42, 0xe6, 0x5d, 0x42, 0x52, 0x48, 0x6f, 0x96, 0xaa, 0x53, 0x99, + 0x19, 0x8d, 0xc5, 0xa7, 0xd7, 0xd5, 0x52, 0xec, 0x3f, 0x9c, 0xdd, 0xe8, 0xd5, 0xe8, 0xac, 0x9c, 0xb6, 0xfc, 0x43, + 0x0f, 0x55, 0x6e, 0x3f, 0xc5, 0x59, 0x3f, 0x18, 0x78, 0x38, 0xbb, 0xe9, 0x49, 0x41, 0xdb, 0xcc, 0x24, 0x54, 0xed, + 0xd9, 0x8d, 0x79, 0xac, 0xb4, 0xea, 0xc8, 0x72, 0xf7, 0x73, 0x8b, 0xfa, 0x39, 0xed, 0xc1, 0x97, 0xa6, 0x58, 0xe0, + 0xc7, 0x4a, 0x98, 0x4f, 0x59, 0x18, 0xc6, 0xb4, 0xa7, 0xe5, 0xb5, 0xd5, 0x79, 0x08, 0xa7, 0x32, 0xcd, 0x25, 0xab, + 0xaf, 0x8a, 0x81, 0xbc, 0x12, 0x4f, 0xfe, 0x65, 0x9e, 0xc6, 0xf0, 0x9d, 0xc7, 0x8d, 0xe8, 0x54, 0xc7, 0x15, 0xdb, + 0x15, 0xf2, 0xc4, 0xef, 0xfa, 0x5c, 0x0e, 0xdb, 0x7f, 0xea, 0x89, 0x05, 0x6f, 0xf7, 0x78, 0x3a, 0xf3, 0x9a, 0xfb, + 0xf5, 0x89, 0xc0, 0xab, 0x72, 0x0a, 0x78, 0xc3, 0xb4, 0x30, 0x48, 0x2b, 0xc9, 0xa7, 0x2d, 0xb7, 0xa3, 0xca, 0x44, + 0x07, 0x60, 0x84, 0x96, 0x45, 0x45, 0x7d, 0x32, 0xff, 0x98, 0xdd, 0xf2, 0x78, 0xf3, 0x6e, 0x79, 0xac, 0x77, 0xcb, + 0xdd, 0x14, 0xfb, 0xe5, 0xb8, 0x03, 0xff, 0xf5, 0xaa, 0x09, 0x79, 0x6d, 0x6b, 0x7f, 0x76, 0x63, 0x81, 0x9e, 0xd6, + 0xec, 0xce, 0x6e, 0xe4, 0xa1, 0x5a, 0x48, 0x5c, 0x6b, 0xc3, 0x31, 0x53, 0xdc, 0xb6, 0xa0, 0x10, 0xfe, 0x6f, 0xd7, + 0x5e, 0x75, 0x0e, 0xe0, 0x1d, 0xb4, 0x3a, 0x5c, 0x7f, 0xd7, 0xbd, 0x7b, 0xd3, 0x7a, 0x49, 0xca, 0x1d, 0x4f, 0x73, + 0x63, 0xe4, 0x72, 0xff, 0xf2, 0x92, 0x86, 0xde, 0x38, 0x0d, 0xe6, 0xf9, 0x3f, 0x29, 0xf8, 0x15, 0x12, 0xef, 0xdc, + 0xd2, 0x2b, 0xfd, 0xe8, 0xa6, 0xf2, 0x88, 0xaf, 0xee, 0x61, 0x51, 0xae, 0x93, 0x97, 0x07, 0x7e, 0x4c, 0x9d, 0xae, + 0x7b, 0xb0, 0x61, 0x13, 0xfc, 0x9b, 0xac, 0xcd, 0xc6, 0xc9, 0xfc, 0x5e, 0x64, 0xdc, 0x89, 0x84, 0xcf, 0xc2, 0x81, + 0xb9, 0x86, 0xed, 0xa3, 0xcd, 0xe0, 0x0e, 0xf5, 0x48, 0x23, 0x2d, 0x14, 0x94, 0xdc, 0x09, 0xe9, 0xd8, 0x9f, 0xc7, + 0xfc, 0xee, 0x5e, 0xb7, 0x51, 0xc6, 0x5a, 0xaf, 0x77, 0x30, 0xf4, 0xaa, 0xee, 0x3d, 0xb9, 0xf4, 0x97, 0x8f, 0x0f, + 0xe0, 0x3f, 0x79, 0xf8, 0xe5, 0xb2, 0xd2, 0xd5, 0xa5, 0xd5, 0x0b, 0xba, 0xfa, 0x55, 0x4d, 0x19, 0x97, 0x22, 0x5c, + 0xe8, 0xe3, 0xf7, 0xad, 0x0d, 0x5a, 0xe5, 0xbd, 0xaa, 0x2b, 0x2d, 0xeb, 0xb3, 0x6a, 0x7f, 0x5e, 0xe7, 0xf7, 0xac, + 0x1b, 0x48, 0xcd, 0xb5, 0x5e, 0x57, 0x7d, 0x7a, 0x7e, 0xad, 0xb2, 0xc6, 0xb8, 0xa8, 0x7f, 0x45, 0x2e, 0x4b, 0x13, + 0x45, 0xa6, 0xa2, 0x82, 0x95, 0x72, 0x25, 0xad, 0x94, 0x94, 0x92, 0x8b, 0xe3, 0xc1, 0xcd, 0x34, 0xb6, 0xae, 0xe4, + 0xfd, 0x38, 0xc4, 0xee, 0xb8, 0x6d, 0xdb, 0x12, 0x4e, 0x3a, 0xf8, 0x4c, 0x97, 0xfd, 0xe1, 0xfd, 0xd7, 0xcd, 0x23, + 0x7b, 0x00, 0x9a, 0xd6, 0xd5, 0x44, 0x68, 0x76, 0x2f, 0xfd, 0x5b, 0x9a, 0x9d, 0x77, 0x95, 0x0b, 0x5e, 0xe6, 0x8b, + 0x8b, 0x32, 0xab, 0x6b, 0x5b, 0x37, 0xd3, 0x38, 0xc9, 0x89, 0x1d, 0x71, 0x3e, 0xf3, 0x5a, 0xad, 0xeb, 0xeb, 0x6b, + 0xf7, 0x7a, 0xdf, 0x4d, 0xb3, 0x49, 0xab, 0xdb, 0x6e, 0xb7, 0xe1, 0x8b, 0x1f, 0xb6, 0x75, 0xc5, 0xe8, 0xf5, 0x93, + 0xf4, 0x86, 0xd8, 0x6d, 0xab, 0x6d, 0x75, 0xba, 0x47, 0x56, 0xa7, 0x7b, 0xe0, 0x3e, 0x3c, 0xb2, 0xfb, 0x5f, 0x58, + 0xd6, 0x71, 0x48, 0xc7, 0x39, 0xfc, 0xb0, 0xac, 0x63, 0xa1, 0x78, 0xc9, 0xdf, 0x96, 0xe5, 0x06, 0x71, 0xde, 0xec, + 0x58, 0x0b, 0xf5, 0x68, 0x59, 0x70, 0x8b, 0x90, 0x67, 0x7d, 0x39, 0xee, 0x8e, 0x0f, 0xc6, 0x8f, 0x7b, 0xaa, 0xb8, + 0xf8, 0xa2, 0x56, 0x1d, 0xcb, 0x7f, 0xbb, 0x46, 0xb3, 0x9c, 0x67, 0xe9, 0x47, 0xaa, 0x5c, 0xfb, 0x16, 0x88, 0x9e, + 0x8d, 0x4d, 0xbb, 0xeb, 0x23, 0x75, 0x8e, 0x2e, 0x83, 0x71, 0xb7, 0xaa, 0x2e, 0x60, 0x6c, 0x95, 0x40, 0x1e, 0xb7, + 0x34, 0xe8, 0xc7, 0x26, 0x9a, 0x3a, 0xcd, 0x4d, 0x88, 0xea, 0xd8, 0x6a, 0x8e, 0x13, 0x3d, 0xbf, 0x63, 0x38, 0xb4, + 0xae, 0x75, 0x55, 0x01, 0x81, 0x6d, 0x85, 0xc4, 0x7e, 0xd5, 0xe9, 0x1e, 0xe1, 0x4e, 0xe7, 0xa1, 0xfb, 0xf0, 0x28, + 0x68, 0xe3, 0x03, 0xf7, 0xa0, 0xb9, 0xef, 0x3e, 0xc4, 0x47, 0xcd, 0x23, 0x7c, 0xf4, 0xfc, 0x28, 0x68, 0x1e, 0xb8, + 0x07, 0xb8, 0xdd, 0x3c, 0x82, 0xc2, 0xe6, 0x51, 0xf3, 0xe8, 0xaa, 0x79, 0x70, 0x14, 0xb4, 0x45, 0x69, 0xd7, 0x3d, + 0x3c, 0x6c, 0x76, 0xda, 0xee, 0xe1, 0x21, 0x3e, 0x74, 0x1f, 0x3e, 0x6c, 0x76, 0xf6, 0xdd, 0x87, 0x0f, 0x5f, 0x1e, + 0x1e, 0xb9, 0xfb, 0xf0, 0x6e, 0x7f, 0x3f, 0xd8, 0x77, 0x3b, 0x9d, 0x26, 0xfc, 0xc1, 0x47, 0x6e, 0x57, 0xfe, 0xe8, + 0x74, 0xdc, 0xfd, 0x0e, 0x6e, 0xc7, 0x87, 0x5d, 0xf7, 0xe1, 0x63, 0x2c, 0xfe, 0x8a, 0x6a, 0x58, 0xfc, 0x81, 0x6e, + 0xf0, 0x63, 0xb7, 0xfb, 0x50, 0xfe, 0x12, 0x1d, 0x5e, 0x1d, 0x1c, 0xfd, 0x68, 0xb7, 0xb6, 0xce, 0xa1, 0x23, 0xe7, + 0x70, 0x74, 0xe8, 0xee, 0xef, 0xe3, 0x83, 0x8e, 0x7b, 0xb4, 0x1f, 0x35, 0x0f, 0xba, 0xee, 0xc3, 0x47, 0x41, 0xb3, + 0xe3, 0x3e, 0x7a, 0x84, 0xdb, 0xcd, 0x7d, 0xb7, 0x8b, 0x3b, 0xee, 0xc1, 0xbe, 0xf8, 0xb1, 0xef, 0x76, 0xaf, 0x1e, + 0x3d, 0x76, 0x1f, 0x1e, 0x46, 0x0f, 0xdd, 0x83, 0x6f, 0x0f, 0x8e, 0xdc, 0xee, 0x7e, 0xb4, 0xff, 0xd0, 0xed, 0x3e, + 0xba, 0x7a, 0xe8, 0x1e, 0x44, 0xcd, 0xee, 0xc3, 0x3b, 0x5b, 0x76, 0xba, 0x2e, 0xe0, 0x48, 0xbc, 0x86, 0x17, 0x58, + 0xbd, 0x80, 0xff, 0x23, 0xd1, 0xf6, 0xdf, 0xb0, 0x9b, 0x7c, 0xbd, 0xe9, 0x63, 0xf7, 0xe8, 0x51, 0x20, 0xab, 0x43, + 0x41, 0x53, 0xd7, 0x80, 0x26, 0x57, 0x4d, 0x39, 0xac, 0xe8, 0xae, 0xa9, 0x3b, 0xd2, 0xff, 0xab, 0xc1, 0xae, 0x9a, + 0x30, 0xb0, 0x1c, 0xf7, 0xdf, 0xb5, 0x9f, 0x72, 0xc9, 0x8f, 0x5b, 0x13, 0x49, 0xfa, 0x93, 0xfe, 0x17, 0xf2, 0x73, + 0x3e, 0x5f, 0x5c, 0x60, 0x7f, 0x9b, 0xe3, 0x23, 0xfe, 0xb4, 0xe3, 0x23, 0xa2, 0xf7, 0xf1, 0x7c, 0xc4, 0x7f, 0xb8, + 0xe7, 0xc3, 0x5f, 0x75, 0x9b, 0xdf, 0xf0, 0x35, 0x07, 0xc7, 0xaa, 0x55, 0xfc, 0x82, 0x3b, 0xc3, 0x14, 0x3e, 0x1d, + 0x5d, 0xf4, 0x6e, 0x38, 0x89, 0xa8, 0xe9, 0x07, 0x4a, 0x81, 0xc5, 0xde, 0x70, 0xc9, 0x63, 0x83, 0x6d, 0x08, 0x09, + 0x3f, 0x8d, 0x90, 0xef, 0xee, 0x83, 0x8f, 0xf0, 0x0f, 0xc7, 0x47, 0x60, 0xe2, 0xa3, 0xe6, 0xc9, 0x17, 0x9e, 0x06, + 0xe1, 0x29, 0x38, 0x13, 0xcf, 0x0e, 0xdc, 0x9a, 0xd1, 0xb0, 0x5b, 0xf4, 0x4a, 0x44, 0xee, 0x64, 0x70, 0xfd, 0xf9, + 0xe7, 0x04, 0x1d, 0xe4, 0x15, 0x39, 0xc4, 0x56, 0x6e, 0x99, 0x99, 0x90, 0x3a, 0xea, 0xa1, 0x14, 0x4a, 0x5d, 0xb7, + 0xed, 0xb6, 0x4b, 0x97, 0x0e, 0x5c, 0x8b, 0x44, 0x16, 0x29, 0xf7, 0xbd, 0x9d, 0x0e, 0x8e, 0xd3, 0x09, 0x5c, 0x96, + 0x24, 0x3e, 0x1f, 0x07, 0x27, 0x1e, 0x02, 0xf9, 0xe5, 0x3e, 0x48, 0x9f, 0x50, 0x8e, 0x1e, 0x3f, 0xfb, 0xf8, 0x37, + 0x08, 0x62, 0xea, 0x98, 0xc4, 0x14, 0xbc, 0x1d, 0xaf, 0x68, 0xc8, 0x7c, 0xc7, 0x76, 0x66, 0x19, 0x1d, 0xd3, 0x2c, + 0x6f, 0xd6, 0xee, 0xeb, 0x11, 0x57, 0xf5, 0x20, 0x5b, 0x41, 0x38, 0xce, 0xe0, 0x73, 0x48, 0x64, 0xa8, 0xfc, 0x8d, + 0xb6, 0x32, 0xc0, 0xec, 0x02, 0xeb, 0x92, 0x0c, 0x64, 0x6d, 0xa5, 0xb4, 0xd9, 0x52, 0x6b, 0xeb, 0xb8, 0xdd, 0x43, + 0x64, 0x89, 0x62, 0xf8, 0xd0, 0xcc, 0x0f, 0x4e, 0x73, 0xbf, 0xfd, 0x27, 0x64, 0x34, 0x2b, 0x3b, 0x1a, 0x29, 0x77, + 0x5b, 0x52, 0x7e, 0x8e, 0x70, 0x25, 0xec, 0x6a, 0x4b, 0x8a, 0xf8, 0x52, 0xce, 0xdd, 0x46, 0xbd, 0x44, 0x25, 0xcd, + 0xc9, 0x2b, 0x01, 0xc7, 0x6c, 0xe2, 0x18, 0xd7, 0x4d, 0x24, 0xf2, 0x43, 0x36, 0x70, 0x5b, 0x3d, 0x42, 0x45, 0x55, + 0x25, 0x41, 0x0b, 0x11, 0x6d, 0x61, 0x89, 0x95, 0x2c, 0x97, 0x4e, 0x02, 0x2e, 0x72, 0x62, 0xe0, 0x14, 0x9e, 0x51, + 0x0d, 0xc9, 0x09, 0x2e, 0x01, 0x12, 0x08, 0x26, 0x89, 0xfc, 0xb7, 0x2a, 0xd6, 0x3f, 0x94, 0xe3, 0xcb, 0x8d, 0xfd, + 0x64, 0x02, 0x54, 0xe8, 0x27, 0x93, 0x35, 0xb7, 0x9a, 0x0c, 0x18, 0xad, 0x94, 0x56, 0x5d, 0x55, 0xee, 0xb3, 0xfc, + 0xc9, 0xed, 0x7b, 0x75, 0xe3, 0xb5, 0x0d, 0xde, 0x69, 0x11, 0xdf, 0xa8, 0xbe, 0xce, 0xd3, 0x20, 0x0f, 0x8e, 0xa7, + 0x94, 0xfb, 0xf2, 0xb0, 0x1a, 0xe8, 0x13, 0x90, 0xcb, 0x62, 0x29, 0x6b, 0x54, 0x05, 0xf5, 0x89, 0x3c, 0xcc, 0x2f, + 0x45, 0x3d, 0xb6, 0xd4, 0x55, 0x71, 0x4d, 0xb1, 0x34, 0xa4, 0x83, 0xa5, 0x3f, 0x26, 0xf0, 0xc5, 0x71, 0x64, 0x92, + 0xa4, 0x76, 0xff, 0x41, 0x99, 0xeb, 0xb2, 0x6d, 0x11, 0x62, 0x96, 0x7c, 0x1c, 0x66, 0x34, 0xfe, 0x27, 0xf2, 0x80, + 0x05, 0x69, 0xf2, 0x60, 0x64, 0xa3, 0x1e, 0x77, 0xa3, 0x8c, 0x8e, 0xc9, 0x03, 0x90, 0xf1, 0x9e, 0xb0, 0x3e, 0x80, + 0x11, 0x36, 0x6e, 0xa6, 0x31, 0x16, 0x1a, 0xd3, 0x3d, 0x14, 0x22, 0x09, 0xae, 0xdd, 0x3d, 0xb4, 0x2d, 0x69, 0x13, + 0x8b, 0xdf, 0x7d, 0x29, 0x4e, 0x85, 0x12, 0x60, 0x75, 0xba, 0xee, 0x61, 0xd4, 0x75, 0x1f, 0x5f, 0x3d, 0x72, 0x8f, + 0xa2, 0xce, 0xa3, 0xab, 0x26, 0xfc, 0xdb, 0x75, 0x1f, 0xc7, 0xcd, 0xae, 0xfb, 0x18, 0xfe, 0xff, 0xf6, 0xc0, 0x3d, + 0x8c, 0x9a, 0x1d, 0xf7, 0xe8, 0x6a, 0xdf, 0xdd, 0x7f, 0xd9, 0xe9, 0xba, 0xfb, 0x56, 0xc7, 0x92, 0xed, 0x80, 0x5d, + 0x4b, 0xee, 0xfc, 0x60, 0x65, 0x43, 0x6c, 0x08, 0xc6, 0xc9, 0x03, 0x77, 0x36, 0x16, 0x67, 0xa4, 0xcd, 0xfd, 0xa9, + 0x9c, 0x75, 0x4f, 0xfd, 0x0c, 0xbe, 0x6c, 0x5a, 0xdf, 0xbb, 0xb5, 0x77, 0xb8, 0xc6, 0x2f, 0x36, 0x0c, 0x31, 0x13, + 0x11, 0x70, 0xf3, 0xae, 0x35, 0x2a, 0xee, 0xb0, 0x93, 0xdf, 0x82, 0x52, 0x51, 0xb0, 0x32, 0xbb, 0xc8, 0x20, 0x6b, + 0x59, 0x03, 0x12, 0x80, 0x04, 0x0d, 0xae, 0xe6, 0x8f, 0x56, 0x74, 0x9e, 0xc1, 0xfd, 0x04, 0x9a, 0x97, 0x30, 0xf1, + 0x45, 0x3e, 0x01, 0xc3, 0x8b, 0xb0, 0x58, 0x05, 0x0f, 0x8e, 0x05, 0x66, 0xa9, 0x71, 0x1b, 0x1d, 0xad, 0x72, 0x00, + 0x42, 0x06, 0xf7, 0x07, 0x16, 0x85, 0x9e, 0x59, 0xcd, 0x8b, 0x5b, 0x21, 0x51, 0xb0, 0x13, 0x9a, 0x0f, 0x6c, 0x28, + 0xb2, 0x3d, 0x5b, 0x78, 0x00, 0xed, 0xf2, 0xe3, 0xaf, 0x25, 0xdd, 0x57, 0x05, 0x58, 0x5c, 0x0e, 0x01, 0x9b, 0x1a, + 0xd0, 0x67, 0xa3, 0xbd, 0xbd, 0xad, 0xdb, 0x49, 0xe8, 0x97, 0x30, 0xb5, 0xea, 0x9b, 0x91, 0x26, 0xa7, 0xb2, 0xcd, + 0x75, 0x28, 0xfb, 0x15, 0x18, 0x46, 0x0a, 0x2d, 0x97, 0xd4, 0xe7, 0xae, 0x9f, 0xc8, 0x03, 0x06, 0x06, 0x3f, 0xc3, + 0x1d, 0xba, 0x8f, 0x8a, 0x94, 0xfb, 0x32, 0x67, 0xcc, 0x64, 0x03, 0x29, 0xf7, 0xf5, 0xdd, 0x4a, 0x3e, 0xaf, 0x9d, + 0xab, 0x8f, 0xba, 0xfd, 0x37, 0xef, 0x4f, 0x2c, 0xb9, 0x7b, 0x8f, 0x5b, 0x51, 0xb7, 0x7f, 0x2c, 0x5c, 0x2a, 0x32, + 0x2b, 0x80, 0xc8, 0xac, 0x00, 0x4b, 0x5d, 0x2a, 0x03, 0x81, 0xb6, 0xa2, 0x25, 0xa7, 0x2d, 0x4c, 0x0a, 0xe9, 0x0c, + 0x9e, 0xce, 0x63, 0xce, 0xe0, 0x9b, 0x47, 0x2d, 0x91, 0x12, 0x20, 0x52, 0x0c, 0xf4, 0x19, 0x55, 0xa5, 0x3c, 0x5e, + 0xf2, 0x44, 0xbb, 0x8e, 0xc7, 0x2c, 0xa6, 0xfa, 0x54, 0xaa, 0xea, 0xaa, 0xcc, 0x07, 0x5a, 0xaf, 0x9d, 0xcf, 0x2f, + 0x21, 0x27, 0x42, 0x67, 0x1f, 0x7d, 0x50, 0x0d, 0x8e, 0xc5, 0x50, 0x10, 0xd8, 0x97, 0x52, 0x5c, 0x7f, 0xdd, 0xb5, + 0xbe, 0xa4, 0x6a, 0xf6, 0x4a, 0x80, 0xc0, 0x4d, 0x1e, 0xd1, 0x7e, 0xbf, 0xf4, 0x26, 0x9b, 0xef, 0x8a, 0xe3, 0x56, + 0xb4, 0xdf, 0xbf, 0xf0, 0x26, 0xaa, 0xbf, 0x97, 0xe9, 0x64, 0x73, 0x5f, 0x71, 0x3a, 0x19, 0x88, 0x63, 0xf2, 0xf2, + 0xca, 0x27, 0xad, 0x1b, 0xa7, 0xb1, 0xdd, 0x3f, 0x56, 0xba, 0x82, 0x25, 0xa2, 0xee, 0xf6, 0x61, 0x5b, 0x9f, 0xbc, + 0x8f, 0xd3, 0x09, 0xec, 0x57, 0xd9, 0xc4, 0x18, 0xa4, 0xe6, 0x90, 0x8f, 0x3a, 0xfd, 0x63, 0xdf, 0x12, 0xac, 0x47, + 0xf0, 0x96, 0xdc, 0x6b, 0x41, 0xe3, 0x28, 0x9d, 0x52, 0x97, 0xa5, 0xad, 0x6b, 0x7a, 0xd9, 0xf4, 0x67, 0xac, 0xf2, + 0x7e, 0x83, 0x4e, 0x52, 0x0e, 0x99, 0xae, 0x64, 0x60, 0x75, 0x2b, 0x6f, 0xdc, 0x01, 0x98, 0x44, 0xda, 0x73, 0x27, + 0x5c, 0x76, 0x06, 0x58, 0x69, 0xff, 0xb8, 0xe5, 0xaf, 0x60, 0x44, 0x6c, 0xc5, 0x42, 0xf9, 0xe1, 0xc1, 0xee, 0xb9, + 0x14, 0xe9, 0x5f, 0x52, 0x5a, 0x68, 0x7f, 0xbd, 0x92, 0xe3, 0x85, 0xdd, 0xff, 0xd7, 0xff, 0xf1, 0xbf, 0x94, 0x0b, + 0xfe, 0xb8, 0x15, 0x75, 0x74, 0x5f, 0x2b, 0xab, 0x52, 0x1c, 0xc3, 0x3d, 0x36, 0x55, 0xcc, 0x98, 0xde, 0x34, 0x27, + 0x19, 0x0b, 0x9b, 0x91, 0x1f, 0x8f, 0xed, 0xfe, 0x76, 0x6c, 0xca, 0xf4, 0xc4, 0xa6, 0x8e, 0xb6, 0xae, 0x17, 0x01, + 0xbd, 0xfe, 0xa6, 0x4b, 0x19, 0x74, 0xc6, 0x97, 0xd8, 0xda, 0xe6, 0x15, 0x0d, 0xd5, 0xee, 0xab, 0x5d, 0xd3, 0x90, + 0xa8, 0x4f, 0x46, 0x2b, 0x06, 0x99, 0xd4, 0x6e, 0x67, 0x28, 0x6c, 0xab, 0x8c, 0x79, 0xfd, 0xdf, 0xff, 0xf9, 0x5f, + 0xfe, 0x9b, 0x7e, 0x84, 0x50, 0xd6, 0xbf, 0xfe, 0xf7, 0xff, 0xfc, 0x7f, 0xfe, 0xf7, 0x7f, 0x85, 0xf4, 0x34, 0x15, + 0xee, 0x12, 0x4c, 0xc5, 0xaa, 0x62, 0x5d, 0x92, 0xbb, 0x58, 0x70, 0xe8, 0x6d, 0xca, 0x72, 0xce, 0x82, 0xfa, 0x7d, + 0x0d, 0x67, 0x62, 0x40, 0xb1, 0x33, 0x15, 0x74, 0x62, 0x87, 0x17, 0x15, 0x41, 0xd5, 0x50, 0x2e, 0x08, 0xb7, 0x38, + 0x6e, 0x01, 0xbe, 0xef, 0x77, 0xdd, 0x8c, 0x5b, 0x2e, 0xc7, 0x42, 0x93, 0x09, 0x94, 0x14, 0x55, 0xb9, 0x05, 0xa1, + 0x97, 0x05, 0x3c, 0x7a, 0x5d, 0xa3, 0x58, 0xac, 0x5e, 0xad, 0x4d, 0xef, 0xe7, 0x79, 0xce, 0xd9, 0x18, 0x50, 0x2e, + 0xdd, 0xc8, 0x22, 0xca, 0xdd, 0x04, 0x55, 0x32, 0xbe, 0x2d, 0x44, 0x2f, 0x92, 0x40, 0x0f, 0x8e, 0xfe, 0x54, 0xfc, + 0x79, 0x0a, 0x0a, 0x9b, 0xe5, 0x4c, 0xfd, 0x1b, 0x65, 0xbd, 0x3f, 0x6c, 0xb7, 0x67, 0x37, 0x68, 0x51, 0x8d, 0x80, + 0xb7, 0x0d, 0x26, 0xe8, 0xd8, 0xec, 0x50, 0x84, 0xc7, 0x4b, 0x2f, 0x77, 0xdb, 0x02, 0x57, 0xb9, 0xd5, 0x2e, 0x8a, + 0xaf, 0x16, 0xc2, 0xd1, 0xca, 0x7e, 0x85, 0x30, 0xb6, 0xf2, 0x49, 0x5f, 0xa6, 0xe6, 0xe4, 0x16, 0x46, 0xab, 0xae, + 0x6c, 0x15, 0x75, 0xd6, 0x6f, 0x6e, 0x31, 0xc3, 0xf0, 0x66, 0x00, 0xfd, 0x00, 0x42, 0xe2, 0x51, 0x07, 0x47, 0xdd, + 0x45, 0xd9, 0x3d, 0xe7, 0xe9, 0xd4, 0x8c, 0xbb, 0x53, 0x9f, 0x06, 0x74, 0xac, 0x7d, 0xf9, 0xea, 0xbd, 0x8c, 0xa9, + 0x17, 0xd1, 0xfe, 0x86, 0xb1, 0x14, 0x48, 0x22, 0xde, 0x6e, 0xb5, 0x8b, 0x2f, 0x61, 0x07, 0x2e, 0xc6, 0x71, 0xea, + 0x73, 0x4f, 0x10, 0x6c, 0xcf, 0x8c, 0xde, 0xfb, 0xc0, 0x93, 0xd2, 0x85, 0x01, 0x4f, 0x4f, 0x56, 0x05, 0xaf, 0x7a, + 0xfd, 0x06, 0xc7, 0xc2, 0x15, 0xcd, 0xcd, 0xae, 0xa4, 0x53, 0xee, 0x3b, 0x15, 0x14, 0x7f, 0x5e, 0xf3, 0x66, 0x29, + 0x81, 0xd4, 0x45, 0x9b, 0xdf, 0x4b, 0xb1, 0x2f, 0xdf, 0x7e, 0xcf, 0x1d, 0x5b, 0x80, 0x69, 0xaf, 0xd6, 0x12, 0x85, + 0x50, 0xeb, 0x39, 0xf9, 0xae, 0xb4, 0xa8, 0xfc, 0xd9, 0x4c, 0x54, 0x44, 0xbd, 0xe3, 0x96, 0x54, 0x84, 0x81, 0x7b, + 0x88, 0x8c, 0x0f, 0x99, 0x60, 0xa1, 0x2a, 0xa9, 0xad, 0x20, 0x7f, 0xa9, 0xd4, 0x0b, 0xf8, 0x94, 0x78, 0xff, 0xff, + 0x01, 0x65, 0x21, 0x07, 0x4b, 0xe3, 0x97, 0x00, 0x00}; #else // Brotli (default, smaller) -constexpr uint8_t INDEX_BR[] PROGMEM = { - 0x1b, 0xc3, 0x97, 0x11, 0x55, 0xb5, 0x65, 0x2c, 0x8a, 0x8a, 0x55, 0x0b, 0xd0, 0xba, 0x80, 0x1b, 0x32, 0xb0, 0x81, - 0x4f, 0x27, 0x63, 0xf1, 0x7e, 0x88, 0xe3, 0xd8, 0x52, 0x84, 0x55, 0xe8, 0x35, 0x5b, 0x2b, 0x82, 0xe1, 0xed, 0x1f, - 0xfd, 0xde, 0x63, 0x38, 0x3a, 0x71, 0x78, 0xb0, 0x42, 0x17, 0x15, 0x54, 0x23, 0xe1, 0xaa, 0x28, 0x11, 0x94, 0x23, - 0xb4, 0xf4, 0x91, 0x3c, 0xfc, 0xff, 0xab, 0x5a, 0x56, 0x2d, 0x07, 0xcb, 0x09, 0x6f, 0x79, 0x15, 0x1c, 0xd2, 0x87, - 0x40, 0x38, 0x97, 0xce, 0x9d, 0x87, 0x67, 0xe0, 0xa0, 0x4d, 0x49, 0x1a, 0x27, 0xf0, 0xf5, 0x8d, 0x9d, 0x72, 0x02, - 0x12, 0x45, 0x49, 0x2b, 0x48, 0xe0, 0x6a, 0xff, 0x5f, 0x6d, 0x55, 0xf1, 0x54, 0x12, 0xc1, 0x2f, 0x1e, 0xc8, 0x83, - 0x0c, 0x92, 0x0d, 0x75, 0xd8, 0xf5, 0xdd, 0xc7, 0x75, 0x50, 0x6c, 0xa1, 0xb2, 0x85, 0xad, 0x6d, 0x63, 0xd1, 0x96, - 0x38, 0xaa, 0x65, 0x4d, 0x1e, 0x6c, 0x14, 0x4e, 0x10, 0xed, 0xbe, 0xaf, 0xf3, 0xff, 0xeb, 0xf7, 0xc6, 0x6f, 0xd9, - 0x77, 0x24, 0x81, 0xbb, 0x26, 0xd0, 0x31, 0x81, 0xae, 0x49, 0x8d, 0x23, 0xb0, 0x5a, 0x62, 0xe5, 0x49, 0x4a, 0x17, - 0xa7, 0x66, 0xda, 0xb2, 0x6a, 0x9d, 0xf0, 0x4d, 0xa4, 0x1d, 0x59, 0xe6, 0x00, 0x55, 0x58, 0x63, 0xf9, 0x0c, 0xfe, - 0xa0, 0xbd, 0xa5, 0xfa, 0x75, 0x9f, 0xcb, 0x49, 0x22, 0x0c, 0xe1, 0xd5, 0xb0, 0xd8, 0x13, 0x72, 0xd3, 0x25, 0x4e, - 0x48, 0x1b, 0xa2, 0x76, 0x4f, 0x5c, 0x42, 0xe2, 0x98, 0x6d, 0x9b, 0x80, 0x3e, 0x69, 0x90, 0xcf, 0x69, 0xa5, 0x2e, - 0xc0, 0x47, 0x4f, 0x5c, 0xac, 0x83, 0x99, 0xe7, 0xfc, 0xff, 0xdf, 0x96, 0x7e, 0xa5, 0xd5, 0x2d, 0x98, 0x45, 0x4a, - 0x81, 0x52, 0x20, 0x67, 0x6d, 0x8d, 0xbd, 0xc4, 0x49, 0xb0, 0x41, 0xa8, 0xba, 0xf7, 0xbe, 0x77, 0x47, 0x45, 0x3d, - 0xea, 0xaa, 0x52, 0xcf, 0x6f, 0xb2, 0x2d, 0xea, 0x11, 0x1f, 0x0b, 0x6d, 0x7e, 0xef, 0x55, 0x75, 0xab, 0xaa, 0x5b, - 0xf6, 0x74, 0x4b, 0xf6, 0x18, 0xe7, 0x1c, 0x59, 0xf6, 0xfe, 0x01, 0xd2, 0xff, 0x8b, 0xe4, 0xf9, 0xe7, 0x2c, 0x52, - 0x84, 0x51, 0x02, 0x9c, 0xed, 0xc9, 0x31, 0x0a, 0x01, 0xd3, 0xcd, 0x36, 0xdc, 0x74, 0x55, 0x87, 0x2a, 0x51, 0x4e, - 0xcf, 0x28, 0xc5, 0x71, 0xec, 0x2d, 0x23, 0x97, 0xcb, 0x55, 0x7d, 0xfd, 0xd6, 0x83, 0x1d, 0xc6, 0x0a, 0x21, 0x9e, - 0x5d, 0x46, 0xd3, 0xfc, 0xcd, 0xca, 0x21, 0x21, 0x24, 0xce, 0x75, 0x5d, 0x7f, 0xa6, 0x0d, 0xf7, 0x70, 0x16, 0xd1, - 0xc4, 0x38, 0xe2, 0x00, 0xf9, 0x14, 0x84, 0xa1, 0x23, 0x9d, 0x6e, 0xcc, 0x71, 0xee, 0xa1, 0xc8, 0x1a, 0xc1, 0xb4, - 0xda, 0x43, 0x30, 0xcf, 0xe1, 0xc0, 0x01, 0x34, 0xb2, 0x3c, 0xb7, 0x7f, 0xf5, 0x81, 0xad, 0xdb, 0xf5, 0x23, 0x32, - 0xe8, 0xf1, 0x66, 0xa5, 0x04, 0xdc, 0x46, 0x71, 0x3d, 0x0e, 0x94, 0x8d, 0x00, 0x35, 0xab, 0xb1, 0x1b, 0x92, 0xef, - 0xcd, 0xef, 0x3f, 0x1d, 0x1c, 0x84, 0x98, 0xe9, 0x3f, 0x54, 0xae, 0x9d, 0x84, 0x17, 0xa2, 0x2e, 0x69, 0x5b, 0xc0, - 0xd5, 0x10, 0x62, 0x1e, 0x06, 0x1e, 0xa2, 0xe0, 0xb5, 0xd7, 0xe2, 0xe9, 0xb4, 0xc6, 0x33, 0x43, 0xc6, 0x96, 0x8b, - 0x5c, 0x0f, 0xd4, 0x5c, 0x18, 0x1c, 0x0e, 0xba, 0x54, 0x85, 0xf3, 0x4c, 0x2e, 0xa2, 0x4d, 0xd7, 0x9a, 0x23, 0xba, - 0x9a, 0xf4, 0xba, 0xa4, 0xf4, 0xdc, 0xdf, 0x7c, 0x53, 0x67, 0xdc, 0x17, 0x7a, 0x7e, 0x49, 0x87, 0x3f, 0xe3, 0xbc, - 0x98, 0x12, 0x88, 0xe8, 0x78, 0x4f, 0x91, 0x72, 0x75, 0x32, 0xc8, 0xd7, 0x95, 0xca, 0xd2, 0xcf, 0x7f, 0x83, 0x7d, - 0x06, 0x6e, 0x11, 0x1b, 0xc7, 0xf9, 0x71, 0x99, 0x5f, 0x17, 0x63, 0x5e, 0x35, 0xf3, 0xd5, 0xe1, 0x70, 0xd9, 0xbb, - 0xc1, 0x75, 0x93, 0x66, 0x1f, 0xd6, 0x83, 0xa5, 0xdb, 0x37, 0x7f, 0x59, 0xd3, 0xe6, 0x66, 0x37, 0x45, 0x5b, 0x5b, - 0x7e, 0xf1, 0xd4, 0xd3, 0x0b, 0xb5, 0x90, 0xaf, 0xeb, 0x69, 0xc2, 0xcd, 0x5c, 0x30, 0xca, 0x16, 0xda, 0x1d, 0xf0, - 0xb9, 0xea, 0xb2, 0xfc, 0xba, 0x5d, 0x25, 0xf3, 0xe3, 0xe4, 0x1b, 0xf1, 0xdb, 0x25, 0x73, 0x7d, 0x31, 0x43, 0x95, - 0x9a, 0x88, 0x6a, 0xf8, 0x47, 0x20, 0x2d, 0xb7, 0xd7, 0x78, 0x6f, 0xe2, 0xbb, 0xa1, 0x85, 0x75, 0xa4, 0xae, 0x6a, - 0x11, 0x25, 0xb7, 0xdf, 0xcd, 0xab, 0xa1, 0x2c, 0x20, 0xff, 0xd6, 0x84, 0xc8, 0x33, 0xee, 0x86, 0x44, 0x55, 0x79, - 0x98, 0x27, 0x37, 0x80, 0x50, 0xa9, 0x8e, 0x88, 0xb5, 0xcc, 0x13, 0xf0, 0x74, 0x38, 0xc7, 0xd8, 0x86, 0xc0, 0x7b, - 0x1d, 0x9e, 0xa6, 0x3b, 0xf3, 0xc3, 0xb5, 0x00, 0x77, 0xc3, 0xca, 0x83, 0x98, 0xba, 0x41, 0x85, 0x3c, 0xd9, 0x29, - 0xc8, 0x79, 0x52, 0x60, 0x25, 0xbb, 0xa6, 0x39, 0xca, 0x76, 0xf2, 0xa6, 0x7d, 0x57, 0xa3, 0xcc, 0xd6, 0xb8, 0xe7, - 0xcd, 0xdf, 0xf9, 0x24, 0x84, 0x14, 0x7f, 0x63, 0x51, 0x9b, 0x98, 0x4a, 0x48, 0xb8, 0x74, 0x9a, 0x74, 0xbf, 0xf1, - 0x9d, 0x48, 0x62, 0x9e, 0xe7, 0x8a, 0x92, 0x75, 0xc8, 0x64, 0x1b, 0xbf, 0xde, 0x54, 0x9b, 0xb6, 0x5c, 0x42, 0xc3, - 0x1a, 0x1e, 0x3f, 0xa7, 0x59, 0xa4, 0x90, 0x50, 0xb2, 0xa7, 0x25, 0x61, 0x65, 0x41, 0xde, 0x83, 0x2f, 0x53, 0x38, - 0x7c, 0xb9, 0xd3, 0xe7, 0x0b, 0x42, 0x59, 0xb8, 0xa9, 0xc0, 0xc4, 0x7b, 0x1b, 0x2b, 0xcd, 0xd7, 0x51, 0x43, 0x30, - 0x93, 0x3f, 0x13, 0xd6, 0x31, 0xfe, 0x55, 0x33, 0xb5, 0x25, 0x44, 0x09, 0x3e, 0xfc, 0x5c, 0x85, 0xac, 0x1b, 0xc1, - 0xd4, 0xb4, 0x54, 0xf2, 0x05, 0x97, 0x72, 0x0e, 0x24, 0x80, 0x50, 0x03, 0x26, 0x7f, 0xce, 0x9a, 0xbe, 0x9f, 0xf1, - 0xf2, 0x7e, 0xc4, 0x9b, 0x26, 0x24, 0x96, 0x37, 0x92, 0x0d, 0x75, 0xff, 0x64, 0xa0, 0xec, 0x38, 0xa6, 0x7a, 0xc8, - 0x7c, 0x1f, 0x76, 0x7b, 0x1a, 0x19, 0x21, 0xc8, 0x7d, 0x33, 0x42, 0xc3, 0x6c, 0x5e, 0xf0, 0x0b, 0x41, 0xaf, 0x8c, - 0x34, 0xa9, 0x8a, 0x2a, 0xbc, 0xff, 0xf5, 0x0b, 0x21, 0x7a, 0x1c, 0xea, 0xd1, 0xff, 0x4e, 0xe9, 0x2e, 0xd5, 0x12, - 0xc3, 0x7a, 0x28, 0xbc, 0x54, 0xe7, 0x95, 0xaa, 0xcd, 0x05, 0x02, 0x30, 0xe4, 0x56, 0x22, 0xfb, 0x9b, 0x91, 0x04, - 0xec, 0x30, 0x53, 0xfe, 0x75, 0x2d, 0xc2, 0x32, 0xc1, 0xe5, 0xcf, 0x59, 0x65, 0xaf, 0xe2, 0x93, 0x94, 0x3e, 0x9a, - 0x23, 0xaa, 0x2c, 0x61, 0x7c, 0x59, 0x10, 0xa4, 0x3c, 0x9b, 0x17, 0x9b, 0xc6, 0x8d, 0xdc, 0x51, 0x7b, 0x10, 0xaf, - 0x72, 0x1d, 0xc7, 0x12, 0x95, 0xad, 0x72, 0x02, 0x90, 0x3c, 0xbb, 0xef, 0x06, 0x61, 0xb0, 0x9c, 0x10, 0xa9, 0x2e, - 0x23, 0xfc, 0x73, 0xae, 0x0a, 0x6e, 0x25, 0x9a, 0x55, 0xcd, 0xfd, 0x37, 0xe8, 0x62, 0xb7, 0xe0, 0x8e, 0xcf, 0xeb, - 0xb9, 0xe1, 0x2a, 0xbc, 0x29, 0xfc, 0xb6, 0x64, 0x90, 0x5e, 0x59, 0x8e, 0x26, 0xd1, 0xaa, 0x8e, 0x38, 0x89, 0x68, - 0x81, 0xb1, 0xd9, 0x7f, 0xd2, 0xe2, 0xbd, 0xa0, 0x13, 0x2a, 0x6d, 0x2f, 0xd5, 0xe5, 0x74, 0xc6, 0x0f, 0x2e, 0xa8, - 0xd7, 0xc5, 0xf9, 0x94, 0x45, 0x50, 0xe1, 0xdb, 0xd4, 0x9f, 0xe9, 0x9c, 0x7a, 0x9f, 0x2f, 0x37, 0xcd, 0x73, 0x8f, - 0x65, 0xb7, 0x5b, 0x6b, 0x14, 0xb7, 0xae, 0x42, 0x6a, 0xc3, 0x8d, 0x97, 0x71, 0x5b, 0x2b, 0x28, 0xae, 0x08, 0x4f, - 0xb5, 0xa6, 0x89, 0x34, 0x76, 0x89, 0x53, 0x36, 0xc6, 0xfb, 0x77, 0x4b, 0xdc, 0x57, 0x4b, 0x99, 0x32, 0xc4, 0x34, - 0x3c, 0xa1, 0xee, 0x5e, 0x9a, 0x1a, 0x0c, 0x0b, 0x1e, 0xbb, 0x45, 0x7c, 0x21, 0x55, 0x09, 0x0a, 0x46, 0xe5, 0x34, - 0x4f, 0xbc, 0x78, 0xe8, 0x5d, 0xb0, 0x04, 0x88, 0xb7, 0xe8, 0xf2, 0x7e, 0x01, 0xc1, 0x8a, 0xd6, 0x0a, 0xb8, 0x13, - 0x4d, 0x90, 0xf0, 0x02, 0x1d, 0x06, 0x19, 0xea, 0x0d, 0xc8, 0x66, 0x95, 0xe8, 0x9d, 0xb3, 0x63, 0x50, 0x5a, 0xcd, - 0xa2, 0xbd, 0x76, 0x9e, 0xde, 0x05, 0xb6, 0xe4, 0xfc, 0x9c, 0x66, 0x63, 0xc6, 0x48, 0x9c, 0x5e, 0x14, 0x31, 0x65, - 0x9e, 0xa8, 0xb9, 0xb6, 0x44, 0x75, 0x9a, 0xbb, 0x3b, 0x63, 0xc6, 0x89, 0xfd, 0x7a, 0x15, 0x7d, 0xd7, 0xc7, 0x55, - 0xcd, 0x80, 0x0b, 0xcc, 0x86, 0xb5, 0xf1, 0xff, 0x69, 0x28, 0x94, 0x82, 0xbf, 0x9a, 0x75, 0x83, 0xe2, 0x5e, 0x2c, - 0xa7, 0xae, 0x27, 0x42, 0xd7, 0xdf, 0x19, 0xd8, 0x8f, 0x77, 0x84, 0x4f, 0x50, 0x46, 0x36, 0x76, 0xfb, 0xa6, 0x34, - 0xc2, 0xf5, 0x2a, 0xf9, 0xbc, 0x7f, 0x6a, 0xfb, 0x86, 0xfa, 0xfc, 0x58, 0x1c, 0xfb, 0x57, 0x6f, 0x28, 0xa6, 0x0e, - 0xdc, 0xc5, 0xec, 0xb9, 0x68, 0xbe, 0xb5, 0xce, 0xd1, 0x83, 0x87, 0xfc, 0x30, 0xec, 0x9d, 0x6e, 0x2c, 0xa6, 0xa6, - 0x8d, 0x07, 0x1a, 0x43, 0x02, 0xbf, 0x66, 0x0e, 0x6b, 0xf5, 0x40, 0x1c, 0xb1, 0x6a, 0x93, 0x53, 0x91, 0xfa, 0x8d, - 0x2a, 0x63, 0x85, 0x79, 0x2d, 0xae, 0x64, 0x21, 0x95, 0x75, 0x18, 0x28, 0x64, 0xa4, 0x3d, 0xa3, 0xdc, 0xb3, 0x82, - 0x87, 0xb9, 0xfe, 0x5d, 0x70, 0x87, 0xaf, 0xef, 0xed, 0x87, 0x26, 0xbe, 0x85, 0xf1, 0xa2, 0xec, 0x54, 0x66, 0x89, - 0x72, 0xcc, 0x02, 0x51, 0x24, 0xcf, 0x88, 0xe6, 0xf8, 0x9a, 0x8d, 0x21, 0x01, 0x72, 0x23, 0x20, 0xc7, 0xdd, 0x7b, - 0xc5, 0xb1, 0x4d, 0x88, 0x40, 0xa1, 0xdd, 0x2d, 0x90, 0x85, 0x82, 0x4c, 0x12, 0x49, 0xee, 0x8e, 0x86, 0x12, 0xfb, - 0x63, 0xf5, 0xd2, 0x85, 0x5b, 0x44, 0xb2, 0xb1, 0x1b, 0x12, 0x08, 0xa4, 0xf1, 0x3e, 0xd5, 0xe7, 0x02, 0x61, 0x29, - 0x40, 0xc7, 0xc1, 0x3f, 0x49, 0x09, 0xab, 0x99, 0x0c, 0x69, 0x36, 0x70, 0x57, 0xe6, 0x65, 0x37, 0xec, 0x7f, 0x67, - 0xa3, 0x02, 0xc2, 0xf1, 0xa1, 0x7f, 0xec, 0x26, 0x28, 0x32, 0x50, 0xb4, 0x42, 0x3d, 0x14, 0x94, 0x6e, 0x28, 0x62, - 0x50, 0xed, 0x8f, 0x9b, 0xc2, 0xdc, 0xdd, 0xc0, 0x64, 0x89, 0x8a, 0xd6, 0x3c, 0x79, 0x2f, 0xea, 0xdb, 0x88, 0xc1, - 0x27, 0x33, 0x76, 0xe8, 0x66, 0xa2, 0x92, 0x5d, 0xaa, 0x0c, 0xac, 0x83, 0x75, 0x2a, 0x95, 0x02, 0x2f, 0x6a, 0x72, - 0xf7, 0x2d, 0x20, 0x2a, 0xde, 0xa9, 0x8b, 0xce, 0xa0, 0x85, 0x57, 0x5a, 0xe8, 0x0c, 0xfa, 0xe5, 0x8c, 0x42, 0xd2, - 0xb1, 0xa6, 0x76, 0xb9, 0x4e, 0x54, 0x0c, 0xf6, 0x84, 0x0d, 0x4a, 0xb4, 0xfc, 0x43, 0x9b, 0x92, 0x88, 0x30, 0xd7, - 0x3d, 0x1f, 0xfe, 0x71, 0x66, 0x48, 0x1f, 0xde, 0xea, 0x21, 0x95, 0x24, 0xc2, 0x27, 0x7c, 0x39, 0x88, 0xd7, 0x1d, - 0x90, 0x14, 0xb8, 0x77, 0x5d, 0xb1, 0x76, 0x2f, 0x3b, 0xe2, 0xe5, 0x64, 0x4b, 0xcd, 0xb8, 0x2e, 0x53, 0xd0, 0xa8, - 0xe3, 0x78, 0xcb, 0xa7, 0xb0, 0xe1, 0x5d, 0xe9, 0x33, 0x3a, 0x16, 0x98, 0x25, 0x90, 0x08, 0x91, 0xde, 0x3f, 0xba, - 0x73, 0xa1, 0xe6, 0x75, 0x92, 0x19, 0x0a, 0x91, 0x5a, 0x25, 0x37, 0x41, 0x85, 0xe3, 0xa9, 0x42, 0xec, 0x48, 0x4a, - 0xca, 0x84, 0x23, 0x4c, 0x8f, 0x2b, 0xa2, 0xa3, 0xe4, 0x3e, 0x69, 0x2a, 0x19, 0x73, 0xf5, 0xbf, 0x4c, 0x69, 0x82, - 0xd9, 0x95, 0xc3, 0x21, 0x11, 0x20, 0x65, 0x5a, 0x6a, 0x37, 0x78, 0x3f, 0x22, 0x3e, 0x15, 0x80, 0x4a, 0x44, 0xa2, - 0x70, 0xcf, 0x2e, 0xfa, 0xb3, 0x28, 0x21, 0x62, 0x30, 0x13, 0xd3, 0x59, 0xf2, 0xfe, 0x5a, 0xe9, 0xe4, 0x75, 0xa3, - 0xab, 0x51, 0xcd, 0xeb, 0x07, 0x95, 0x8f, 0x98, 0x2b, 0x97, 0x4f, 0x02, 0x19, 0x5b, 0x4d, 0xae, 0xa9, 0xcc, 0xb3, - 0xb2, 0xb8, 0x0a, 0x0b, 0x54, 0x1b, 0xb5, 0x80, 0xeb, 0x73, 0x9d, 0xdb, 0x10, 0x75, 0xce, 0x41, 0xe4, 0x80, 0x1d, - 0x56, 0xb3, 0xd0, 0xd9, 0x31, 0x7d, 0x70, 0x99, 0x1c, 0xe1, 0x34, 0x9d, 0xb9, 0x63, 0x68, 0xa7, 0xf7, 0x22, 0x39, - 0x0c, 0x2e, 0x56, 0xa0, 0x0b, 0x28, 0xa7, 0x86, 0x31, 0x8a, 0x1c, 0x50, 0x62, 0xa9, 0x94, 0x72, 0x01, 0x40, 0x8b, - 0xa2, 0xab, 0xa0, 0x0c, 0x85, 0x2a, 0x69, 0x64, 0x0b, 0x07, 0x2b, 0x8e, 0x11, 0xaf, 0xbd, 0xfa, 0x21, 0x10, 0xb2, - 0x68, 0xbb, 0x06, 0xea, 0x40, 0xa9, 0xe6, 0xad, 0x7f, 0x17, 0xb9, 0xe8, 0xc2, 0xb3, 0x32, 0x40, 0x99, 0x3f, 0xaa, - 0x36, 0xeb, 0x4e, 0x26, 0x2f, 0xae, 0x8c, 0x17, 0xaa, 0x6c, 0x78, 0x90, 0x3c, 0x4b, 0x64, 0x4a, 0x28, 0x70, 0xca, - 0x92, 0xc6, 0x3e, 0xf1, 0xc1, 0x8e, 0xfc, 0xf6, 0x84, 0xb9, 0x39, 0x56, 0x46, 0x35, 0xe2, 0xe9, 0x8b, 0xaa, 0xeb, - 0x9a, 0x21, 0x42, 0xcd, 0x3f, 0x7c, 0xed, 0xac, 0xff, 0xa6, 0x1b, 0x8d, 0xde, 0x91, 0x75, 0xd6, 0xe4, 0xdf, 0x86, - 0xc1, 0x9d, 0xce, 0x9e, 0xd5, 0x55, 0x83, 0x58, 0x2b, 0x28, 0x02, 0xe1, 0x80, 0x07, 0xbf, 0xa9, 0x8e, 0xf6, 0x9b, - 0x80, 0x25, 0xef, 0x18, 0xda, 0x93, 0xea, 0x8a, 0x09, 0x4d, 0xcb, 0xe7, 0x1f, 0x41, 0x73, 0xa5, 0x86, 0xb2, 0x2c, - 0xf8, 0xf0, 0x01, 0x65, 0x06, 0xa5, 0xca, 0x51, 0x3b, 0xdd, 0x86, 0x5c, 0x13, 0x68, 0xa2, 0x27, 0x41, 0x9e, 0xaf, - 0xbf, 0x70, 0x57, 0xa5, 0x32, 0x90, 0x6f, 0x98, 0xec, 0xc2, 0x5d, 0xb2, 0xba, 0xca, 0x39, 0xfb, 0x2f, 0x51, 0xcc, - 0xf3, 0xbc, 0xa7, 0x23, 0x23, 0xbd, 0x67, 0x47, 0x6e, 0x6a, 0xc5, 0xf9, 0x29, 0x4a, 0x48, 0x16, 0x6d, 0x59, 0x68, - 0xcb, 0x11, 0x8c, 0x81, 0x12, 0x3a, 0x12, 0xb9, 0x0c, 0x59, 0xd6, 0xb0, 0xcc, 0xbe, 0xe5, 0x7f, 0xe3, 0x90, 0x49, - 0x4a, 0x72, 0x9a, 0x5c, 0xf7, 0xb2, 0xb8, 0xec, 0xca, 0x12, 0x95, 0xd8, 0x51, 0x6b, 0xba, 0x12, 0x43, 0xf2, 0xd5, - 0x7b, 0xda, 0xb4, 0xd4, 0x7e, 0x84, 0x74, 0x67, 0x46, 0x0a, 0xfa, 0xa0, 0xea, 0x6d, 0x74, 0xc1, 0xd1, 0x06, 0x90, - 0x63, 0x49, 0xf2, 0x3c, 0x29, 0x06, 0xd9, 0x44, 0x0a, 0x25, 0xea, 0x49, 0x0e, 0x63, 0x59, 0xc2, 0xdc, 0x8f, 0x12, - 0xcc, 0xd2, 0xb2, 0x8c, 0x91, 0x3e, 0x2d, 0x62, 0xa7, 0x14, 0x8f, 0x50, 0xf9, 0x38, 0xbb, 0xef, 0xa6, 0xa1, 0x24, - 0xd5, 0x49, 0x99, 0x20, 0x68, 0xcf, 0x81, 0xd0, 0x31, 0x01, 0xf3, 0xbd, 0xa9, 0xe8, 0x2f, 0x7f, 0x8e, 0x2b, 0x16, - 0xf6, 0x1f, 0x52, 0x3c, 0x33, 0xb3, 0x9b, 0x5f, 0x59, 0xce, 0x91, 0xe5, 0xcc, 0xd0, 0x49, 0x9b, 0x42, 0x0a, 0x1b, - 0x67, 0xbb, 0xfe, 0x82, 0x34, 0xef, 0x8d, 0x0e, 0x47, 0x7a, 0x09, 0xbf, 0x2f, 0x04, 0xd7, 0x87, 0x24, 0x8c, 0x90, - 0xab, 0x2e, 0xaa, 0xdd, 0x3c, 0x79, 0x91, 0xc2, 0x6a, 0x47, 0x47, 0x5c, 0x8a, 0xdd, 0xdb, 0x59, 0xc4, 0x5a, 0x91, - 0x0a, 0xf6, 0xbd, 0x32, 0x91, 0x89, 0xcd, 0xa0, 0x04, 0x67, 0x2b, 0x03, 0x7a, 0x56, 0xbb, 0x78, 0x26, 0xaa, 0xa3, - 0x26, 0xd4, 0x59, 0x81, 0x67, 0xa8, 0x01, 0x64, 0xeb, 0xbc, 0x69, 0xc9, 0x9e, 0x0e, 0x96, 0x93, 0xd4, 0x50, 0x9a, - 0x45, 0x04, 0xfe, 0xd0, 0xdd, 0xde, 0x93, 0x88, 0x0c, 0x03, 0x3f, 0xce, 0x46, 0x94, 0x07, 0xa8, 0x19, 0xc3, 0x89, - 0xa5, 0x49, 0x92, 0x35, 0x5c, 0x98, 0xf7, 0x56, 0x04, 0x71, 0xdf, 0xc7, 0xb6, 0x88, 0xfa, 0xdb, 0x51, 0x26, 0xd8, - 0x57, 0xeb, 0x04, 0xa2, 0x62, 0x16, 0xca, 0xe4, 0x5b, 0x42, 0x78, 0xcb, 0x03, 0xc3, 0xd5, 0xf9, 0x86, 0xd9, 0x58, - 0xb5, 0x92, 0x23, 0x5f, 0x55, 0x0b, 0x3b, 0x20, 0x1c, 0xb5, 0x2f, 0x1d, 0xeb, 0x67, 0xb7, 0x2a, 0x7a, 0x3d, 0x2d, - 0xbf, 0xda, 0xd4, 0x95, 0xaa, 0x03, 0xb9, 0x18, 0xa3, 0x6c, 0xc6, 0xa4, 0xd1, 0x00, 0xb5, 0x80, 0x5c, 0x59, 0x47, - 0xaa, 0x78, 0x9a, 0x96, 0x70, 0x88, 0x07, 0x1e, 0xaf, 0xae, 0x1d, 0xe9, 0x25, 0xdb, 0xa1, 0x03, 0xda, 0x7a, 0x87, - 0x6f, 0xbd, 0x76, 0x2d, 0xc6, 0x8d, 0x05, 0xbc, 0x01, 0xa0, 0x12, 0x95, 0x0a, 0x2a, 0xd1, 0x20, 0xe5, 0x52, 0xc5, - 0x75, 0xd0, 0x29, 0xd7, 0xb4, 0x58, 0x59, 0x2b, 0xbc, 0xcb, 0x03, 0xfc, 0x69, 0x07, 0xa4, 0xb2, 0xae, 0x82, 0x62, - 0xd1, 0xfd, 0x16, 0x84, 0x14, 0xe2, 0xcd, 0xf4, 0xcd, 0x1c, 0xcc, 0xc9, 0x92, 0x35, 0x5f, 0xcb, 0x13, 0x61, 0xb1, - 0x72, 0x6b, 0x4e, 0xce, 0x91, 0x51, 0x49, 0xdf, 0xde, 0x03, 0xa2, 0x6e, 0x76, 0x79, 0xbf, 0xf8, 0xd1, 0x33, 0xee, - 0x29, 0xf0, 0xf1, 0x76, 0xbf, 0x1b, 0x1c, 0x7e, 0x78, 0xcb, 0xe1, 0x90, 0x33, 0x48, 0x43, 0x1a, 0x1b, 0xc8, 0x10, - 0xbc, 0x58, 0x15, 0x16, 0xfc, 0xb1, 0x6e, 0x75, 0x89, 0xe8, 0x3c, 0x05, 0xfc, 0x3d, 0x73, 0x17, 0xba, 0x3f, 0x20, - 0x72, 0x17, 0xf2, 0x78, 0xde, 0x65, 0x52, 0x3e, 0x42, 0x1a, 0x49, 0xee, 0xdf, 0x47, 0x9a, 0xca, 0xe4, 0x7c, 0xf3, - 0x97, 0x3c, 0x2a, 0x54, 0xd6, 0xc1, 0x14, 0x1a, 0x94, 0xd4, 0x39, 0x60, 0xd0, 0x46, 0xc6, 0x55, 0xbd, 0x1c, 0x3a, - 0x69, 0xf5, 0x79, 0xb6, 0x07, 0x99, 0x22, 0x10, 0x9d, 0x1e, 0x94, 0x51, 0x06, 0x42, 0x00, 0xbc, 0x80, 0x00, 0x68, - 0x09, 0x06, 0x03, 0xf8, 0x48, 0xf7, 0x74, 0xd0, 0x98, 0x8c, 0xd3, 0xa7, 0x92, 0x0c, 0x75, 0xa9, 0xfc, 0x9a, 0x58, - 0x8f, 0x92, 0x25, 0x62, 0x52, 0x41, 0x0b, 0xc5, 0x8c, 0xe2, 0x53, 0xf3, 0xce, 0xdc, 0xd2, 0xfb, 0x92, 0x19, 0xc6, - 0x99, 0x66, 0xa9, 0xd3, 0x46, 0xf2, 0x91, 0xba, 0x4f, 0x79, 0xb0, 0x4a, 0x10, 0x9e, 0x12, 0xaa, 0x32, 0x3c, 0xd4, - 0x35, 0x53, 0x8a, 0x67, 0x38, 0x86, 0xe3, 0xf2, 0xad, 0x45, 0xea, 0xe0, 0x83, 0xc4, 0xa7, 0xef, 0x63, 0xa8, 0xad, - 0xf9, 0xe3, 0xaf, 0x1d, 0x09, 0xbf, 0x8c, 0x32, 0xcc, 0x95, 0x88, 0x03, 0x2d, 0x53, 0x60, 0x87, 0x0b, 0x3d, 0x4f, - 0xbc, 0xdc, 0x97, 0xb8, 0xa3, 0x40, 0x0f, 0x46, 0xec, 0xa9, 0x0f, 0x99, 0xdb, 0x33, 0x91, 0xb5, 0x2d, 0xea, 0xf5, - 0xdf, 0x17, 0xdf, 0xe5, 0xc9, 0xed, 0x98, 0x27, 0x75, 0x8a, 0x0a, 0xb4, 0x52, 0x7b, 0xcb, 0x7c, 0x5f, 0xcc, 0xc2, - 0xa3, 0xef, 0x56, 0xc8, 0x18, 0x43, 0x33, 0xf2, 0x60, 0x63, 0x44, 0x50, 0x16, 0x3b, 0x98, 0xdf, 0x29, 0x24, 0x3f, - 0x3e, 0xc8, 0x41, 0x23, 0x0a, 0x82, 0xaa, 0xfd, 0x05, 0x85, 0xb2, 0x30, 0xf6, 0x37, 0xbe, 0xf6, 0x3d, 0xb2, 0xea, - 0x14, 0xcb, 0xe3, 0xec, 0x33, 0x3e, 0x67, 0x71, 0xc5, 0xaa, 0x05, 0x59, 0x91, 0x7b, 0x25, 0x9e, 0x8e, 0x59, 0xda, - 0x66, 0xd1, 0xb4, 0x4e, 0x00, 0xef, 0x63, 0xe7, 0xb6, 0xdc, 0x0f, 0xb5, 0xfe, 0x08, 0xe2, 0xea, 0x8b, 0xb0, 0xf6, - 0x3c, 0x08, 0x2b, 0xaf, 0xa2, 0x40, 0x31, 0x6d, 0x4b, 0x7e, 0xde, 0xdb, 0xcf, 0xd8, 0x46, 0xf1, 0x44, 0xb6, 0x9b, - 0xf7, 0xb6, 0x67, 0xdb, 0x38, 0x65, 0x4a, 0xfd, 0x6d, 0xae, 0x0f, 0xfe, 0x0f, 0x11, 0x3f, 0xe6, 0x40, 0xbf, 0x5f, - 0xac, 0xa6, 0xf9, 0xa9, 0xf9, 0x64, 0x85, 0xd2, 0x07, 0xf0, 0xe2, 0xb2, 0x79, 0x31, 0x7a, 0xb5, 0xf6, 0x52, 0xc4, - 0xf2, 0x20, 0xf4, 0x2d, 0x62, 0x68, 0x3b, 0xc8, 0x2e, 0xdf, 0xcf, 0x05, 0xba, 0x60, 0xac, 0x47, 0xbf, 0x01, 0x9e, - 0xb4, 0xda, 0x38, 0x64, 0xe0, 0x32, 0x99, 0x73, 0x13, 0x24, 0xdd, 0x07, 0x55, 0xbf, 0xb7, 0xaf, 0xf2, 0xb8, 0xa2, - 0x07, 0x2e, 0xa8, 0x30, 0xdd, 0x71, 0xd7, 0xb5, 0xba, 0xfa, 0xdb, 0x1d, 0x78, 0x9e, 0x1b, 0xed, 0x45, 0xef, 0x6f, - 0xe2, 0x50, 0xc4, 0x95, 0xec, 0x0b, 0x88, 0x44, 0x26, 0x7e, 0xb3, 0x99, 0x24, 0xf6, 0xe5, 0x02, 0x66, 0x2a, 0x99, - 0x66, 0xb1, 0xb6, 0x74, 0x3b, 0xa7, 0x07, 0xaf, 0x86, 0xe5, 0x6c, 0x30, 0x3c, 0xcb, 0xc0, 0xe5, 0x97, 0xd7, 0xb8, - 0xe3, 0xa6, 0xad, 0x7f, 0xe5, 0x96, 0xf0, 0x25, 0xb2, 0xd4, 0xb5, 0xe4, 0xcf, 0x28, 0xb5, 0x1f, 0x34, 0x95, 0x7f, - 0x12, 0xf4, 0xb4, 0xf4, 0x3e, 0x2f, 0x9d, 0xca, 0xaf, 0xdf, 0xb7, 0x3d, 0xad, 0x16, 0xaf, 0xfe, 0x3a, 0xb9, 0x5e, - 0xff, 0xaf, 0xed, 0x1a, 0x3d, 0xfa, 0x39, 0xbd, 0xb2, 0xbf, 0x13, 0x9b, 0x85, 0x61, 0x77, 0x3d, 0x5d, 0x5c, 0x8b, - 0xea, 0xcf, 0x0f, 0xfc, 0xb3, 0xd3, 0x4a, 0x98, 0x8f, 0xbf, 0xb7, 0x98, 0x4c, 0xad, 0x66, 0xb7, 0xa6, 0x7b, 0xf8, - 0xe9, 0xa7, 0x1e, 0x04, 0xda, 0x95, 0x9c, 0xbb, 0xa6, 0x61, 0x98, 0x45, 0x85, 0x1a, 0x4e, 0xd1, 0x83, 0x3e, 0xda, - 0x1e, 0x37, 0xdf, 0x64, 0xeb, 0xc0, 0xed, 0x65, 0x93, 0x27, 0xcd, 0xd6, 0xf5, 0xb5, 0xc5, 0xf5, 0x5c, 0xa6, 0xcb, - 0x29, 0xb8, 0x91, 0x09, 0x1f, 0xe2, 0xbf, 0x6c, 0xc1, 0x64, 0x15, 0x90, 0xfc, 0x81, 0x14, 0xd7, 0xb7, 0xab, 0xab, - 0x5f, 0x65, 0xb9, 0x12, 0xb3, 0x8e, 0xb4, 0x06, 0x5a, 0x07, 0x41, 0xa3, 0xe6, 0x71, 0x21, 0x66, 0xae, 0xe9, 0x68, - 0x57, 0x72, 0x82, 0x0b, 0x50, 0x18, 0x4d, 0xfd, 0xc7, 0x4f, 0xa1, 0x36, 0xf7, 0x1a, 0xe5, 0x08, 0xae, 0x89, 0x62, - 0xf7, 0x9a, 0xb0, 0xdd, 0x82, 0x71, 0xaa, 0x78, 0x87, 0xaa, 0xca, 0x8d, 0xf6, 0xc5, 0x4c, 0x03, 0xa2, 0xca, 0x72, - 0x12, 0xe0, 0x10, 0x6f, 0x16, 0x6e, 0x92, 0xc4, 0xff, 0x1e, 0xbb, 0x48, 0x99, 0x14, 0xfe, 0xb9, 0x22, 0x64, 0xb1, - 0xd0, 0x2f, 0xb7, 0x8e, 0xd8, 0xd4, 0x0d, 0xab, 0xeb, 0x0f, 0x92, 0x99, 0x90, 0x9a, 0x89, 0xb0, 0xa2, 0x66, 0xbe, - 0x05, 0xdc, 0x93, 0x82, 0x89, 0xe7, 0x22, 0x6f, 0x6d, 0xd7, 0xfc, 0x7d, 0xea, 0xb3, 0xc5, 0x47, 0x91, 0x05, 0xd0, - 0x0d, 0x01, 0x02, 0x1a, 0xd7, 0xa7, 0xc5, 0x7a, 0x6f, 0x3b, 0xef, 0x5f, 0xd2, 0x58, 0x74, 0x3b, 0xe3, 0xca, 0x79, - 0xab, 0x68, 0xec, 0xe9, 0x02, 0x28, 0x69, 0xf5, 0xe5, 0xc7, 0x55, 0x3f, 0xbc, 0xdf, 0xc4, 0xad, 0xde, 0xc7, 0xbb, - 0xfe, 0xb5, 0x50, 0x8e, 0x34, 0x7c, 0x3a, 0xa5, 0xe1, 0xe5, 0x4e, 0x35, 0x31, 0x67, 0x3c, 0x2d, 0xaf, 0x5c, 0xd8, - 0x0d, 0xd9, 0xc6, 0xef, 0x7c, 0x68, 0xeb, 0x81, 0x5f, 0x76, 0x98, 0x22, 0x34, 0x27, 0x9b, 0x29, 0x2f, 0x90, 0x98, - 0xeb, 0x9b, 0xad, 0x38, 0xd8, 0x7b, 0x84, 0x36, 0xe1, 0xaf, 0x97, 0x24, 0x2b, 0xc4, 0xa8, 0xc2, 0x41, 0x5e, 0x1e, - 0xf6, 0x29, 0x4c, 0x82, 0xf5, 0x25, 0x3c, 0x04, 0x8a, 0x3e, 0x62, 0x14, 0xcb, 0xf1, 0x16, 0xea, 0x58, 0x8e, 0x83, - 0xde, 0x2c, 0x1f, 0xb5, 0xb1, 0x8b, 0x9f, 0x31, 0xb0, 0x62, 0xab, 0x90, 0xd3, 0x88, 0x35, 0x5b, 0xf8, 0xde, 0xdc, - 0xfa, 0xa1, 0xde, 0x73, 0x37, 0x24, 0x1c, 0x6e, 0x2b, 0xcf, 0x2f, 0xaa, 0x2d, 0x2b, 0xb5, 0x01, 0xde, 0xd2, 0x9d, - 0x79, 0x50, 0x49, 0x9b, 0xf7, 0x44, 0x76, 0x6f, 0x54, 0xf5, 0xd7, 0x4e, 0x16, 0xe2, 0x97, 0xdf, 0x45, 0xdb, 0x59, - 0x0a, 0x22, 0x5c, 0x84, 0x21, 0xd4, 0x56, 0xa5, 0x47, 0x51, 0x9e, 0xba, 0xfd, 0x14, 0x37, 0xa5, 0xdd, 0x06, 0x19, - 0xe9, 0xfe, 0x0d, 0x90, 0x82, 0x5e, 0x80, 0x40, 0x88, 0x7b, 0xd9, 0x1c, 0x0a, 0x98, 0x64, 0x90, 0x40, 0x2f, 0x13, - 0xac, 0x03, 0xfe, 0xa0, 0xe4, 0xbd, 0xed, 0xc0, 0x03, 0xe0, 0x80, 0xc2, 0x61, 0xa4, 0x7c, 0x65, 0x4e, 0x75, 0x46, - 0x66, 0xcb, 0xaa, 0x75, 0x13, 0x8f, 0xa6, 0xeb, 0x0a, 0x9c, 0x37, 0x15, 0x9b, 0x7f, 0x26, 0x0a, 0xdb, 0x4e, 0xc4, - 0xa9, 0x2c, 0x14, 0x98, 0xa8, 0x31, 0x48, 0x4f, 0x0d, 0x96, 0xad, 0x4a, 0xd3, 0xf8, 0x10, 0xcb, 0x6e, 0x1c, 0xa5, - 0xeb, 0x7a, 0x63, 0xe3, 0xcc, 0x41, 0x98, 0xbd, 0xb1, 0xd7, 0xee, 0xf9, 0x96, 0xb5, 0x37, 0xad, 0x0e, 0xc5, 0x63, - 0x65, 0x71, 0x53, 0xf9, 0xf2, 0xcd, 0xb9, 0x31, 0xe5, 0x59, 0xe6, 0x1c, 0xc2, 0x5a, 0xf0, 0xdf, 0xb0, 0x1b, 0x36, - 0x6d, 0x2c, 0xf9, 0x72, 0x5f, 0x10, 0xc1, 0xee, 0x92, 0xbd, 0xc6, 0xec, 0xb2, 0xa4, 0x0a, 0x43, 0xf0, 0xce, 0x67, - 0x2a, 0x11, 0xcb, 0x1f, 0x51, 0x94, 0x6f, 0x3c, 0xb6, 0xfb, 0xc2, 0x2a, 0xc1, 0xb0, 0x5e, 0x13, 0x78, 0xe1, 0x79, - 0x4b, 0x49, 0x8b, 0x49, 0x79, 0x59, 0x66, 0xf7, 0xcb, 0xee, 0xca, 0x0d, 0xc2, 0xc3, 0xbd, 0xa4, 0x15, 0x62, 0x18, - 0x35, 0x95, 0x2a, 0x70, 0x31, 0x22, 0xea, 0x98, 0xa7, 0xdb, 0xb2, 0xc4, 0x2f, 0x4d, 0x25, 0x49, 0x2d, 0x74, 0x6b, - 0x07, 0x87, 0xdf, 0x59, 0xd2, 0x44, 0x88, 0x2d, 0x28, 0x5e, 0x77, 0x48, 0x60, 0xe7, 0x9c, 0x52, 0xbe, 0x9f, 0x3f, - 0xca, 0x2c, 0x19, 0x5e, 0x95, 0x03, 0x55, 0xc8, 0xce, 0x0c, 0x19, 0xad, 0xb8, 0xeb, 0x44, 0x12, 0xf4, 0x2e, 0x12, - 0x83, 0x15, 0xc2, 0x7e, 0x28, 0xca, 0x12, 0xfd, 0x80, 0x57, 0x93, 0x1b, 0x78, 0x11, 0x58, 0x75, 0xe5, 0xb1, 0x53, - 0x12, 0xe4, 0x00, 0xf9, 0x49, 0x70, 0xd6, 0xc3, 0x4c, 0xee, 0x8e, 0x40, 0x04, 0x8f, 0x77, 0x32, 0x11, 0xd0, 0x06, - 0xf2, 0x55, 0x5d, 0xdc, 0x89, 0x44, 0x15, 0x82, 0xbf, 0x24, 0x77, 0xf4, 0x6e, 0xab, 0x34, 0x1a, 0xed, 0x6c, 0x28, - 0x4c, 0xdc, 0xc6, 0x75, 0xe3, 0x1d, 0x2f, 0x98, 0xa3, 0xcd, 0xe8, 0xae, 0x58, 0x9e, 0xe7, 0xcd, 0x4d, 0x69, 0x04, - 0x4b, 0xea, 0x2b, 0xcc, 0x4b, 0xb3, 0x56, 0x74, 0x64, 0x6c, 0x11, 0x24, 0x06, 0xcc, 0x69, 0x67, 0xc9, 0x62, 0xf5, - 0xdb, 0x58, 0x8b, 0x1c, 0x47, 0x58, 0x96, 0x04, 0x10, 0xcd, 0x0b, 0x91, 0x17, 0x43, 0x8e, 0xa3, 0x25, 0xaa, 0x14, - 0x18, 0x73, 0x8b, 0x18, 0x76, 0xb1, 0xc9, 0xc9, 0x6d, 0x69, 0xa4, 0x68, 0xf8, 0x26, 0xa7, 0xa7, 0xf7, 0xd6, 0xf0, - 0xda, 0x88, 0x64, 0xe4, 0x60, 0x7b, 0x2e, 0xb7, 0x25, 0xac, 0xf2, 0x53, 0xbf, 0x5b, 0x6b, 0x15, 0x2d, 0x97, 0xe3, - 0x60, 0xb4, 0xd7, 0x92, 0x45, 0xbb, 0x01, 0x35, 0x7f, 0xc9, 0xba, 0x87, 0x8c, 0x35, 0xda, 0xb0, 0xd5, 0x41, 0x5d, - 0x88, 0x73, 0x3e, 0xf6, 0x15, 0xfe, 0x46, 0x9e, 0xc0, 0x4c, 0x53, 0x72, 0x91, 0xff, 0xbe, 0xbf, 0x54, 0x25, 0xf9, - 0xeb, 0x60, 0x27, 0x3c, 0x16, 0x6a, 0x64, 0xbf, 0x57, 0x13, 0x33, 0x99, 0x61, 0x87, 0xf7, 0x09, 0xb8, 0x42, 0x7c, - 0x31, 0xc0, 0xce, 0x2c, 0x9d, 0x4b, 0xda, 0xa9, 0x8c, 0x19, 0x97, 0xe2, 0x38, 0x93, 0x26, 0x1b, 0x5b, 0x53, 0x7f, - 0x7b, 0x89, 0x55, 0x4b, 0x9e, 0x5a, 0x9f, 0x5b, 0x5f, 0xe3, 0xe3, 0x1c, 0xf2, 0xd6, 0x87, 0x19, 0xff, 0x64, 0x2b, - 0x4c, 0xd8, 0x3b, 0xa2, 0x45, 0xb0, 0x63, 0xa3, 0x81, 0x9f, 0xde, 0x8b, 0xa3, 0x65, 0x09, 0xda, 0x3f, 0x80, 0x55, - 0x5d, 0x85, 0x9c, 0xc9, 0xf0, 0xf3, 0xa4, 0x91, 0x58, 0x24, 0xc5, 0x02, 0x38, 0xdf, 0xab, 0xd9, 0xef, 0xd5, 0xeb, - 0x93, 0xd5, 0x64, 0xc8, 0xa8, 0xb3, 0xa4, 0x2e, 0xd4, 0x9f, 0x5d, 0xdf, 0x36, 0x75, 0x1d, 0x9c, 0x88, 0xeb, 0x4f, - 0xd0, 0xb6, 0x75, 0xc7, 0xd0, 0x9c, 0xa0, 0xa6, 0x3c, 0x53, 0x1c, 0xeb, 0x4e, 0xbf, 0x19, 0x8f, 0x6c, 0x6e, 0x3e, - 0xda, 0x44, 0x36, 0x5e, 0x8c, 0xc4, 0x16, 0x5e, 0xe8, 0x05, 0xd0, 0xa2, 0xbe, 0xc7, 0x42, 0xfc, 0xe4, 0xe8, 0x19, - 0x4e, 0x60, 0x04, 0x72, 0x2d, 0x64, 0xa0, 0xa4, 0x27, 0x1a, 0xb6, 0x55, 0x73, 0x0e, 0x07, 0x2f, 0x3f, 0xb1, 0x2d, - 0x79, 0x44, 0x07, 0x75, 0x86, 0xfe, 0x4a, 0x3e, 0xdb, 0x4f, 0x15, 0xef, 0x30, 0xd5, 0xf6, 0xeb, 0x72, 0x9c, 0x35, - 0xd3, 0x79, 0xd7, 0x90, 0x85, 0xe8, 0xf9, 0x60, 0x7b, 0x86, 0xd4, 0xb1, 0x8a, 0x56, 0xcd, 0xe2, 0xf5, 0xf0, 0xee, - 0x91, 0x25, 0x66, 0xeb, 0x76, 0x67, 0x74, 0xd8, 0x41, 0x50, 0x43, 0x0c, 0xd6, 0x6d, 0x21, 0x91, 0x19, 0x25, 0xc7, - 0xba, 0x10, 0x1f, 0xc1, 0x0d, 0x41, 0x29, 0xf4, 0xb0, 0x97, 0xd2, 0x4a, 0x3f, 0xea, 0x22, 0x19, 0x26, 0x83, 0x47, - 0xb3, 0x5b, 0x36, 0xd7, 0x62, 0x17, 0x55, 0xfd, 0xb3, 0xec, 0xda, 0x15, 0xf4, 0xd1, 0x14, 0x75, 0x42, 0x0d, 0x22, - 0x90, 0xde, 0xca, 0xdf, 0xe2, 0xf8, 0x92, 0x6e, 0x5c, 0xbf, 0x1e, 0xde, 0x84, 0xcc, 0xf9, 0x00, 0x0e, 0x00, 0xd3, - 0xc9, 0xfb, 0x77, 0x0e, 0x25, 0x55, 0x85, 0x46, 0x5a, 0xdf, 0x91, 0x1b, 0x6c, 0xc7, 0xe4, 0x21, 0x3a, 0xbe, 0x76, - 0x33, 0x40, 0x80, 0x36, 0x16, 0xfa, 0x1c, 0x5a, 0x6f, 0x24, 0xad, 0x04, 0x4b, 0xa0, 0xb3, 0xfa, 0xa1, 0xa5, 0xf0, - 0xd2, 0x90, 0x98, 0xfa, 0x0d, 0x96, 0x45, 0xa2, 0x24, 0xe6, 0xcf, 0xc2, 0x2b, 0xdb, 0xaa, 0xf0, 0x30, 0xc6, 0x0a, - 0xd0, 0x86, 0x58, 0xfb, 0x15, 0xbb, 0x22, 0xb0, 0xf0, 0xde, 0x12, 0xc0, 0xbb, 0x66, 0x8e, 0x02, 0x01, 0xc7, 0x2b, - 0x1c, 0x44, 0x1a, 0x8c, 0x3f, 0x5b, 0x89, 0x23, 0x47, 0x9a, 0xd5, 0x47, 0xef, 0xdb, 0xfd, 0x69, 0x8a, 0x47, 0xea, - 0x1c, 0xb7, 0x9e, 0x64, 0x81, 0x3f, 0xec, 0x9e, 0x0b, 0x2f, 0xac, 0xc8, 0x5e, 0xf6, 0x77, 0xf7, 0x92, 0xc5, 0x4d, - 0x2f, 0xf1, 0x55, 0x2f, 0x93, 0xeb, 0x95, 0x43, 0x0d, 0x6a, 0x60, 0xf3, 0x7d, 0x8f, 0xaa, 0x82, 0xdc, 0x80, 0xbf, - 0x77, 0xf3, 0x11, 0xc6, 0xb5, 0x0b, 0x9c, 0xe3, 0x52, 0x3d, 0xcc, 0x45, 0xcc, 0xa8, 0xa4, 0x76, 0x94, 0x5c, 0x40, - 0xaa, 0x93, 0x94, 0x0b, 0x32, 0xac, 0x5c, 0xa0, 0xb7, 0xfa, 0x14, 0xaf, 0x9c, 0x2d, 0x4d, 0x82, 0x28, 0xea, 0xb9, - 0x7b, 0x85, 0x0a, 0xc1, 0x7f, 0x1d, 0xc8, 0x8c, 0x29, 0x2b, 0x30, 0x57, 0x13, 0xea, 0x30, 0x4b, 0x26, 0xbc, 0x3c, - 0x8a, 0xe1, 0xc5, 0x08, 0x32, 0x6d, 0xa9, 0x22, 0xaa, 0xdf, 0x43, 0xdf, 0xa4, 0x68, 0x56, 0xa3, 0x10, 0x73, 0x8e, - 0x25, 0x15, 0x5c, 0xaf, 0xea, 0x10, 0x7e, 0x44, 0xad, 0xee, 0x15, 0x8e, 0xeb, 0x9c, 0x31, 0xb9, 0xf3, 0xad, 0x07, - 0x9c, 0x9e, 0xc7, 0xe9, 0x01, 0xb9, 0x6d, 0x2a, 0xa2, 0xfa, 0x18, 0x0f, 0x43, 0x58, 0xab, 0x59, 0x66, 0x08, 0x99, - 0xb7, 0x0d, 0xc5, 0xaf, 0x84, 0x66, 0xf3, 0x67, 0x57, 0x43, 0xf2, 0x79, 0xf1, 0xc4, 0x8d, 0xeb, 0x54, 0xc5, 0x12, - 0x93, 0xbc, 0x08, 0x2b, 0xcc, 0xe1, 0xb2, 0x37, 0x63, 0xd1, 0xf9, 0xc9, 0x79, 0x08, 0x09, 0x58, 0x94, 0x8f, 0x68, - 0xed, 0x19, 0x50, 0x50, 0x2d, 0xc7, 0xa9, 0x5a, 0x03, 0xc6, 0xf6, 0x3c, 0x78, 0x4b, 0xf9, 0x2f, 0xdb, 0x03, 0xd4, - 0x93, 0xed, 0x9c, 0x62, 0x30, 0x86, 0xf0, 0x94, 0x6e, 0x03, 0x9c, 0x90, 0xca, 0x16, 0x0e, 0xaa, 0xf5, 0x37, 0x37, - 0x2f, 0xb4, 0x81, 0x12, 0x7f, 0x49, 0x91, 0xd6, 0x8a, 0x14, 0x8f, 0x30, 0x34, 0x05, 0x9f, 0xf1, 0xd8, 0x93, 0x78, - 0xcf, 0xdd, 0x97, 0x35, 0x22, 0x05, 0x71, 0x2e, 0xfc, 0x85, 0x08, 0x2b, 0x47, 0x88, 0x79, 0xca, 0x0d, 0x95, 0x64, - 0x5f, 0xda, 0xb3, 0xfa, 0x2a, 0x0b, 0x78, 0xea, 0xb2, 0x4f, 0xe1, 0x85, 0xc0, 0x1c, 0xae, 0x3d, 0x7a, 0x52, 0x3f, - 0x9a, 0x01, 0xab, 0x7a, 0x6e, 0x31, 0x8d, 0x50, 0x51, 0xb8, 0x84, 0x20, 0x6e, 0x29, 0x41, 0x84, 0x61, 0x66, 0x8d, - 0x87, 0x4f, 0x0c, 0xeb, 0x29, 0x0c, 0x00, 0xa6, 0xa4, 0xa1, 0x7b, 0x86, 0x32, 0x81, 0x7b, 0x69, 0x17, 0x28, 0xcf, - 0x5c, 0x65, 0x5e, 0x4e, 0xee, 0x31, 0x0c, 0x9c, 0xcc, 0xd6, 0x16, 0xd3, 0xc8, 0x88, 0xac, 0x03, 0x2d, 0xd4, 0x91, - 0xbf, 0x57, 0x2b, 0x2b, 0xbb, 0x6e, 0x02, 0xdd, 0x8b, 0x7a, 0x2f, 0xfd, 0x22, 0x42, 0xdc, 0x5e, 0xa5, 0xa7, 0x80, - 0x69, 0xf8, 0x14, 0xf7, 0x33, 0xa9, 0x10, 0x78, 0x15, 0xf4, 0x3c, 0x90, 0xc8, 0x1e, 0xe2, 0x0e, 0xea, 0x06, 0x00, - 0x92, 0x5b, 0xe2, 0x4a, 0x41, 0x5a, 0x1b, 0x52, 0x25, 0xeb, 0x3f, 0xb5, 0xd5, 0x28, 0x01, 0xc8, 0x47, 0xf6, 0xcd, - 0x91, 0xc6, 0x2b, 0x08, 0x2d, 0x5c, 0x48, 0x39, 0xcc, 0xe0, 0x51, 0x13, 0x74, 0x22, 0x33, 0xc1, 0xe6, 0x56, 0xb0, - 0x8d, 0x9f, 0xbc, 0x79, 0x1d, 0x89, 0x0a, 0xd3, 0x8f, 0xe2, 0xdf, 0xab, 0x3b, 0x6e, 0x8a, 0xb2, 0xe2, 0x21, 0xf7, - 0xfd, 0x1c, 0x3f, 0x37, 0x45, 0x49, 0x9a, 0x13, 0xbe, 0x54, 0x32, 0x9d, 0xb4, 0x17, 0x47, 0x6d, 0x8e, 0x96, 0x3d, - 0x00, 0x79, 0xc5, 0x4b, 0x60, 0xdd, 0x63, 0xe5, 0xbb, 0x96, 0x56, 0x99, 0xf9, 0x88, 0xaa, 0x2a, 0x2a, 0x24, 0x9a, - 0xe0, 0x22, 0xb3, 0x26, 0xb6, 0x71, 0x5a, 0x1c, 0x06, 0x90, 0x42, 0x63, 0x58, 0x31, 0xe4, 0xa1, 0xf9, 0xb1, 0x98, - 0x17, 0xe1, 0x89, 0x2c, 0xba, 0x2e, 0x28, 0xe5, 0x67, 0x48, 0x69, 0xa6, 0x8c, 0x6c, 0x8b, 0x65, 0x38, 0x9c, 0x01, - 0xc0, 0x5c, 0xeb, 0x88, 0xa8, 0x54, 0x98, 0xec, 0x98, 0x54, 0xc6, 0x5e, 0xc9, 0x9f, 0xa5, 0x84, 0x88, 0x08, 0xab, - 0xb3, 0x6d, 0x03, 0x62, 0x77, 0x0e, 0xea, 0x11, 0x9e, 0x2d, 0x33, 0xd8, 0xc4, 0xb2, 0x08, 0xce, 0x8a, 0xaa, 0xaa, - 0x46, 0xa3, 0xf9, 0xb0, 0x37, 0x34, 0xde, 0x64, 0xee, 0x0c, 0x85, 0xb0, 0x75, 0x3b, 0x42, 0x50, 0x6e, 0x3c, 0xdb, - 0x86, 0xd6, 0x86, 0x0f, 0x33, 0x37, 0xf5, 0x41, 0x5e, 0x2e, 0xa2, 0xaa, 0xd1, 0x66, 0xcf, 0x53, 0xca, 0xd3, 0x68, - 0xef, 0xa9, 0x3b, 0x29, 0x09, 0x95, 0xdd, 0x24, 0x2a, 0x0a, 0x6c, 0xe1, 0x59, 0x12, 0x12, 0x40, 0x71, 0xfb, 0xeb, - 0x50, 0x83, 0xfc, 0x8b, 0x91, 0x83, 0x03, 0x5f, 0xd5, 0x81, 0xb5, 0x2b, 0x20, 0xcd, 0xcf, 0x64, 0xd2, 0x5b, 0x7c, - 0xef, 0x6e, 0xe8, 0xc3, 0x47, 0x91, 0x22, 0xdc, 0x47, 0x68, 0x1d, 0x27, 0x21, 0x6e, 0x01, 0xf7, 0x9b, 0x6d, 0x2f, - 0x3e, 0x6a, 0x3a, 0x41, 0x66, 0x68, 0x5c, 0x1b, 0x2f, 0x9b, 0x56, 0xa4, 0x16, 0x28, 0x54, 0x20, 0x1f, 0xe9, 0x7e, - 0x2b, 0x01, 0x29, 0xc7, 0xa9, 0xdc, 0x76, 0xaf, 0x93, 0xf2, 0x1c, 0xee, 0x86, 0x8a, 0xe8, 0x75, 0x3d, 0xda, 0x12, - 0xd0, 0x62, 0x4e, 0x06, 0x7e, 0x3a, 0x5a, 0x45, 0xbe, 0x9c, 0x38, 0xc5, 0x39, 0x55, 0x2d, 0xd6, 0x3c, 0xf8, 0x78, - 0x97, 0x07, 0xc2, 0xfe, 0x92, 0x8c, 0x93, 0x31, 0x00, 0x59, 0xc5, 0x02, 0x73, 0xe0, 0x40, 0xed, 0x36, 0x27, 0x6a, - 0x03, 0x0e, 0xd4, 0xea, 0xce, 0x9e, 0xa6, 0x32, 0xd9, 0xa7, 0x94, 0xe3, 0x57, 0xf8, 0x82, 0xa5, 0xac, 0x46, 0xda, - 0x8a, 0x6a, 0x79, 0xae, 0xa5, 0x05, 0x50, 0x4b, 0x65, 0xa9, 0x6c, 0x29, 0xa4, 0x18, 0xdf, 0xec, 0xf1, 0x31, 0x12, - 0xba, 0x52, 0x3c, 0x4f, 0x2e, 0x03, 0xed, 0xf2, 0x37, 0x9e, 0xc2, 0x74, 0xc6, 0x04, 0xa6, 0xa9, 0x89, 0x2b, 0xb2, - 0x79, 0xff, 0xfe, 0xda, 0xa9, 0xb6, 0xec, 0x48, 0xaa, 0x40, 0xda, 0x2c, 0x76, 0x74, 0x69, 0x4c, 0x81, 0xe0, 0xaa, - 0xa1, 0xdb, 0xe2, 0x68, 0x77, 0xfe, 0xe1, 0xce, 0x2c, 0xa4, 0x6b, 0xa2, 0x1c, 0x49, 0xe4, 0xc7, 0xa5, 0x10, 0x50, - 0xa3, 0xbe, 0x10, 0x4e, 0xa4, 0xfe, 0xc8, 0x90, 0x4b, 0x17, 0xb3, 0x43, 0x6b, 0x54, 0xd7, 0x2d, 0x00, 0x2d, 0x7d, - 0x0f, 0x23, 0x43, 0x21, 0x6c, 0xc4, 0xb0, 0xcf, 0x53, 0xea, 0xe3, 0xca, 0x49, 0x17, 0x5d, 0x62, 0x29, 0x64, 0xde, - 0xc7, 0x24, 0x6f, 0x92, 0x46, 0x89, 0xc8, 0xeb, 0x2c, 0xe5, 0xa4, 0x2e, 0x4e, 0xe2, 0x28, 0x6f, 0x29, 0x64, 0x20, - 0xd5, 0x4d, 0x2a, 0xdd, 0x96, 0x4b, 0x25, 0xf4, 0x58, 0xf6, 0xb7, 0xe4, 0x06, 0xaf, 0xfb, 0x72, 0x1c, 0xfc, 0x31, - 0xf2, 0xcf, 0x13, 0x5b, 0x2c, 0x45, 0x07, 0xd0, 0x83, 0x20, 0xa5, 0x35, 0x40, 0xc2, 0xcf, 0xeb, 0x5b, 0xdf, 0x09, - 0xbe, 0x76, 0x04, 0xb4, 0x42, 0xb0, 0x72, 0xbd, 0x0a, 0x35, 0xdd, 0x5e, 0x36, 0x56, 0x65, 0x54, 0x75, 0xb0, 0x83, - 0x68, 0x89, 0x24, 0x04, 0xf8, 0x9c, 0xbc, 0x43, 0xea, 0x87, 0x9a, 0x74, 0xeb, 0x4b, 0xbe, 0x88, 0xd6, 0xb5, 0x92, - 0x67, 0x04, 0x57, 0xdf, 0xa8, 0xc9, 0xc2, 0xad, 0xe3, 0x27, 0x51, 0xd7, 0x4e, 0xd5, 0x15, 0x31, 0x07, 0x04, 0x98, - 0xaa, 0x86, 0x11, 0x75, 0x9f, 0x24, 0xc9, 0xbf, 0xc4, 0x54, 0x80, 0x0a, 0x96, 0x49, 0xbd, 0xfa, 0xbf, 0x6f, 0xb5, - 0xee, 0x7f, 0xbc, 0xc1, 0xba, 0x9a, 0xe7, 0xb7, 0x77, 0x7a, 0x00, 0x30, 0x80, 0x1f, 0x83, 0xaa, 0x0e, 0x5e, 0x6e, - 0xc7, 0x0b, 0xbb, 0x32, 0x05, 0xa9, 0x09, 0xf8, 0xac, 0x92, 0xfe, 0xcf, 0x91, 0x06, 0x82, 0xe6, 0x6b, 0x64, 0x6d, - 0x6c, 0x46, 0x24, 0x72, 0xdf, 0x65, 0x83, 0x8f, 0x57, 0xe1, 0xd9, 0x11, 0xf8, 0x65, 0x6c, 0x9d, 0xd3, 0x31, 0xcb, - 0x07, 0x09, 0x2c, 0x17, 0x6a, 0xbf, 0x7a, 0xcc, 0xf9, 0x44, 0x88, 0x53, 0x54, 0xa8, 0x27, 0xa8, 0x08, 0x32, 0x81, - 0x62, 0x91, 0x96, 0xa8, 0xe3, 0x2a, 0xce, 0x11, 0x16, 0x10, 0x5a, 0xa7, 0x44, 0x44, 0xbc, 0x1d, 0xd0, 0x11, 0xbc, - 0xad, 0x21, 0x27, 0xee, 0x38, 0x37, 0x6b, 0x1b, 0x98, 0xcb, 0x20, 0xd5, 0xa0, 0xe9, 0xee, 0x0b, 0x6c, 0xc0, 0x43, - 0x9c, 0x37, 0x8e, 0x4f, 0xe2, 0x72, 0x8b, 0x2c, 0x72, 0x0e, 0x45, 0x5d, 0x5e, 0xd4, 0xc8, 0xc4, 0x24, 0xa1, 0x0e, - 0x4f, 0x21, 0xa4, 0xdb, 0x17, 0x30, 0x98, 0x16, 0x4c, 0xe3, 0xac, 0x4e, 0x12, 0xc0, 0x2d, 0x9f, 0xde, 0x0f, 0xc3, - 0x97, 0x1e, 0x6a, 0x07, 0xd1, 0xb9, 0x88, 0xf8, 0x4d, 0xdb, 0xd4, 0x28, 0x4c, 0x1e, 0xae, 0xad, 0xef, 0xa9, 0xe1, - 0x23, 0x24, 0xe1, 0x5f, 0xc3, 0xa2, 0x08, 0x48, 0xdc, 0xa6, 0xb7, 0x5c, 0x30, 0xe9, 0x9d, 0x66, 0x21, 0xb4, 0xd9, - 0x0c, 0x52, 0xa5, 0x6a, 0x3e, 0xc0, 0xca, 0xb4, 0xd3, 0xff, 0xe4, 0xe4, 0xb6, 0x24, 0x05, 0x41, 0xb4, 0xd2, 0xef, - 0x4c, 0x99, 0xb0, 0xc6, 0x98, 0x40, 0xde, 0x15, 0x25, 0x9c, 0x67, 0xd0, 0x49, 0x2c, 0x00, 0x3b, 0x5a, 0x7f, 0x2f, - 0xff, 0x0e, 0x8b, 0xd1, 0xa9, 0xd1, 0x9b, 0x4e, 0x92, 0xa9, 0xd6, 0x7f, 0x7b, 0x00, 0x7f, 0x9c, 0x81, 0xb5, 0x3e, - 0x77, 0x81, 0xb5, 0xdb, 0x4d, 0x12, 0x52, 0xba, 0x25, 0xaf, 0xaa, 0xaf, 0x62, 0xdd, 0xa4, 0x54, 0xee, 0x67, 0xbf, - 0xbf, 0xbd, 0xd8, 0x32, 0x82, 0xc3, 0x3a, 0xa7, 0x18, 0x58, 0x80, 0x0d, 0x73, 0x19, 0x6e, 0x56, 0x3b, 0x81, 0xa0, - 0xa4, 0x97, 0xe4, 0xc3, 0x36, 0x43, 0xb2, 0xe3, 0x53, 0x2d, 0x91, 0xd0, 0x33, 0x9e, 0xf6, 0x35, 0x80, 0xc0, 0xbb, - 0x73, 0x93, 0xd2, 0x7a, 0xf3, 0x19, 0x79, 0xaf, 0x4a, 0x14, 0x91, 0x61, 0x4a, 0x8c, 0x67, 0x4e, 0x08, 0xd2, 0x7e, - 0xcd, 0x60, 0x6b, 0xbf, 0x19, 0x3c, 0x8d, 0x9b, 0x87, 0xe6, 0x88, 0x20, 0x72, 0x31, 0x7d, 0x90, 0xc2, 0x9f, 0x25, - 0xe3, 0xf2, 0x85, 0xcf, 0x6c, 0xc3, 0x75, 0x5a, 0x49, 0x80, 0x73, 0x8a, 0xbb, 0x79, 0xca, 0x33, 0xb1, 0x58, 0x9e, - 0xbc, 0x7c, 0xb5, 0xac, 0xd2, 0x14, 0x38, 0x83, 0x0f, 0x71, 0x19, 0xa9, 0x34, 0xc8, 0x94, 0x14, 0x3f, 0x9e, 0x27, - 0x93, 0x6e, 0x6f, 0x6a, 0x95, 0xb0, 0xab, 0x06, 0x87, 0xea, 0x13, 0x2a, 0x4b, 0x4f, 0xdb, 0x52, 0x0b, 0xcc, 0x63, - 0x1f, 0x04, 0x98, 0x7c, 0x93, 0x7d, 0xcc, 0xda, 0x11, 0x74, 0x0f, 0x4a, 0xe5, 0x32, 0x1e, 0x06, 0xb8, 0xa9, 0x82, - 0x00, 0xd2, 0xc7, 0x7a, 0x0a, 0x73, 0x79, 0x8f, 0x89, 0x0e, 0x8b, 0x1e, 0x46, 0xa0, 0x2e, 0xd4, 0xc2, 0x08, 0xcc, - 0x90, 0x07, 0x53, 0xb1, 0x74, 0xe2, 0x4f, 0x37, 0xd8, 0xfa, 0xdc, 0x8f, 0x73, 0x4d, 0xbb, 0x63, 0x96, 0x06, 0x48, - 0xaa, 0xa3, 0xee, 0x37, 0xfa, 0x46, 0x3d, 0x9e, 0x75, 0x8b, 0xf7, 0x69, 0x33, 0xa6, 0xbd, 0xa9, 0x3c, 0x1e, 0x55, - 0xdb, 0xef, 0xdf, 0x16, 0x97, 0xa8, 0x96, 0x92, 0xa5, 0x3d, 0xc8, 0xbe, 0x3b, 0xa3, 0x00, 0xb7, 0xef, 0x78, 0x13, - 0x1e, 0x20, 0xcf, 0x91, 0x4e, 0xcc, 0x6d, 0xd8, 0x53, 0x9d, 0x03, 0xed, 0xfc, 0xe7, 0x47, 0xa9, 0xb0, 0xf3, 0xf7, - 0xa7, 0x61, 0xe9, 0x3d, 0x49, 0x18, 0x05, 0x8e, 0xd2, 0xef, 0xde, 0x77, 0x59, 0xad, 0xf4, 0x71, 0x81, 0xcb, 0x9d, - 0xd7, 0x56, 0x9c, 0x78, 0xb1, 0x61, 0x3d, 0x25, 0x8f, 0x63, 0x14, 0x63, 0x6f, 0x7a, 0xb2, 0xee, 0x8c, 0xdd, 0x3d, - 0x85, 0xb5, 0x67, 0x3d, 0x25, 0x48, 0xb7, 0x92, 0x1f, 0xf7, 0xfe, 0x23, 0xb6, 0x53, 0x25, 0xdd, 0xf4, 0x07, 0xdb, - 0x2f, 0x3f, 0x3a, 0x3b, 0x88, 0x07, 0xad, 0xb3, 0x32, 0x9d, 0xa5, 0xeb, 0x2a, 0xe9, 0x72, 0xb8, 0x40, 0xde, 0xcd, - 0xc4, 0x73, 0x61, 0xae, 0xbf, 0xce, 0x36, 0x42, 0x05, 0xf6, 0xe5, 0x6a, 0xbc, 0xbd, 0x47, 0xcc, 0xe7, 0x72, 0x2e, - 0xfb, 0xde, 0xa2, 0x29, 0x04, 0x7d, 0x8b, 0x91, 0x72, 0xc1, 0x38, 0x4e, 0x90, 0x0f, 0xb8, 0x34, 0xde, 0x07, 0xb4, - 0x18, 0xa3, 0x5b, 0xf8, 0x79, 0x0c, 0xdb, 0x03, 0x6c, 0xcd, 0xfc, 0x73, 0xc2, 0x63, 0x5e, 0x88, 0x30, 0x4d, 0x1e, - 0x50, 0x53, 0xb2, 0x81, 0x0f, 0x36, 0x9c, 0x9f, 0x15, 0x12, 0xc3, 0x00, 0xcb, 0x23, 0x4f, 0xa7, 0x8d, 0xec, 0x69, - 0xa8, 0x2e, 0xcf, 0x73, 0xb5, 0xde, 0x82, 0x9e, 0x30, 0x9d, 0xe5, 0x65, 0x1a, 0xee, 0xd2, 0x3b, 0x13, 0xec, 0x70, - 0xb9, 0x6b, 0x38, 0x69, 0x99, 0x22, 0x55, 0x8e, 0xf3, 0xc6, 0x71, 0x9a, 0x33, 0x06, 0xe2, 0x29, 0xe6, 0xf5, 0xeb, - 0x54, 0x60, 0xd1, 0x62, 0x5c, 0xbe, 0x40, 0x69, 0x60, 0xea, 0x2f, 0x36, 0x32, 0x53, 0xa1, 0x75, 0x00, 0x31, 0x59, - 0x82, 0x3f, 0x1b, 0xa4, 0xb4, 0xa0, 0x10, 0x8d, 0x0a, 0xb7, 0xd5, 0x3f, 0xdc, 0x15, 0xb5, 0x4a, 0x13, 0xd1, 0xee, - 0x5d, 0xf1, 0xce, 0x10, 0xdb, 0xc5, 0x5b, 0x4e, 0x07, 0x50, 0x8c, 0x1a, 0x1d, 0xd0, 0xa4, 0x60, 0x7b, 0xb4, 0xfe, - 0x26, 0x29, 0xe5, 0x79, 0x66, 0x44, 0xf6, 0x58, 0xc0, 0xfa, 0x6e, 0x70, 0x18, 0x5b, 0x5b, 0x55, 0x58, 0xef, 0x9b, - 0x36, 0xc1, 0x1c, 0x80, 0xfd, 0x96, 0x44, 0xf1, 0xde, 0x27, 0x7f, 0x49, 0x8c, 0xd1, 0xf5, 0x3d, 0x17, 0x59, 0x7a, - 0x63, 0x28, 0x26, 0x48, 0xae, 0x69, 0x56, 0xc9, 0xe2, 0x18, 0x8d, 0x46, 0x41, 0xc9, 0x39, 0x31, 0x8e, 0x50, 0x36, - 0x40, 0x3d, 0x4d, 0x49, 0xe9, 0x02, 0x40, 0x66, 0x58, 0x4d, 0x0f, 0x0a, 0x60, 0x19, 0x8d, 0xb4, 0x40, 0xe5, 0x59, - 0x74, 0x14, 0xee, 0x79, 0x72, 0x9a, 0x6b, 0x66, 0xd5, 0xe0, 0xf0, 0x96, 0x07, 0x8a, 0xca, 0x79, 0x7a, 0x36, 0x99, - 0x8f, 0xe8, 0x20, 0xd2, 0x6b, 0x1a, 0xff, 0xb6, 0xaf, 0x44, 0x74, 0x70, 0x1b, 0x09, 0x16, 0x9c, 0xfd, 0x90, 0x93, - 0x21, 0x72, 0x7f, 0xb5, 0xce, 0xf4, 0x83, 0x0a, 0xfd, 0x6e, 0x35, 0x84, 0x48, 0xf9, 0x4a, 0xd8, 0xd8, 0x94, 0x3b, - 0x35, 0xe8, 0xbc, 0xd3, 0x30, 0x91, 0xa1, 0x70, 0x7c, 0xcf, 0x6d, 0xe9, 0x13, 0x6d, 0x56, 0x37, 0xce, 0xfc, 0xe3, - 0x01, 0x3f, 0x59, 0x9a, 0x22, 0x68, 0x4d, 0xa5, 0x4e, 0x07, 0xe8, 0x96, 0x48, 0x83, 0xa3, 0x7c, 0x60, 0x5e, 0x78, - 0xd0, 0x52, 0xbb, 0xa1, 0x44, 0x57, 0x74, 0x14, 0xee, 0x91, 0xe7, 0x02, 0x1a, 0x67, 0x0a, 0xba, 0x1e, 0x71, 0x54, - 0x3b, 0x63, 0x28, 0xc5, 0x1c, 0x0c, 0xe6, 0x50, 0xd6, 0x64, 0x8d, 0x7d, 0x6c, 0xbd, 0x44, 0x77, 0xe3, 0x19, 0x22, - 0xd7, 0x13, 0x1a, 0x87, 0xa4, 0xeb, 0x99, 0x91, 0xc2, 0x30, 0x84, 0x77, 0x40, 0xf2, 0xee, 0xc4, 0xfa, 0x5c, 0xa9, - 0xa4, 0x1d, 0x69, 0x63, 0x60, 0x17, 0xcf, 0x62, 0xb6, 0xb0, 0x22, 0x3b, 0x71, 0x6d, 0xbd, 0xb6, 0x76, 0xfd, 0x15, - 0xa2, 0xc2, 0x78, 0x6c, 0xeb, 0x70, 0x9e, 0x33, 0x72, 0xc5, 0x0d, 0x13, 0x3f, 0xcb, 0xae, 0xcf, 0x3c, 0x95, 0xf4, - 0x5f, 0x84, 0xd6, 0x4f, 0x5d, 0x71, 0x81, 0x75, 0xb7, 0x4d, 0xec, 0xfa, 0x75, 0x4a, 0x6a, 0x5d, 0xb9, 0x0b, 0xfd, - 0x8f, 0xad, 0xed, 0x58, 0x6d, 0xe6, 0x69, 0xde, 0x7f, 0xe8, 0x44, 0x1d, 0xe4, 0x9f, 0x7e, 0xb5, 0x1b, 0xb9, 0x91, - 0x16, 0x2f, 0xc9, 0xc7, 0xbb, 0x9e, 0xe6, 0x0b, 0x1e, 0xfb, 0xf3, 0x66, 0xd8, 0xf3, 0x32, 0xbf, 0x16, 0xec, 0xcf, - 0xd3, 0xd9, 0x67, 0x8e, 0x1e, 0xdf, 0x1f, 0xd2, 0xc4, 0xa3, 0xe9, 0xf3, 0xe4, 0xcf, 0xe4, 0x5c, 0x24, 0x8f, 0xc9, - 0x5e, 0xf5, 0xb6, 0xed, 0x22, 0xa5, 0x11, 0xa0, 0x8e, 0xde, 0xac, 0xdf, 0x85, 0x74, 0x4d, 0x32, 0x15, 0x0f, 0xca, - 0xa7, 0x7c, 0x20, 0xbe, 0xae, 0xbf, 0x4c, 0xf7, 0x50, 0x88, 0x78, 0x11, 0xf8, 0xef, 0xf9, 0xfe, 0x23, 0xb6, 0x59, - 0x57, 0x5a, 0x9d, 0xcd, 0x8d, 0x1e, 0xba, 0x7d, 0x75, 0x32, 0xf5, 0x89, 0x94, 0x51, 0x7a, 0x5d, 0x88, 0x97, 0x18, - 0x17, 0x37, 0xf9, 0x21, 0xdb, 0x7e, 0x18, 0x9f, 0xd7, 0xf8, 0x81, 0x08, 0x8a, 0xb0, 0x8f, 0x19, 0x32, 0x3e, 0x40, - 0x4d, 0xe5, 0x54, 0xb0, 0x62, 0x5a, 0xa9, 0x4a, 0x03, 0xa0, 0x69, 0xf4, 0x4b, 0x94, 0x7f, 0xa6, 0x07, 0xf2, 0xc3, - 0x1f, 0xbd, 0x75, 0xde, 0x3f, 0xa7, 0xff, 0xbe, 0xff, 0xfc, 0xa3, 0x06, 0x26, 0x05, 0x64, 0xdd, 0x87, 0x95, 0x6d, - 0x12, 0x8e, 0xca, 0xc6, 0x55, 0x56, 0x13, 0x75, 0x07, 0x99, 0x5e, 0xcd, 0x6c, 0xf7, 0xcd, 0x5b, 0xf6, 0xa1, 0x17, - 0xd1, 0x4c, 0xc9, 0xa3, 0x52, 0xe4, 0x1d, 0x72, 0x71, 0xf5, 0x39, 0x7c, 0x19, 0xeb, 0xaa, 0x90, 0x5f, 0xa9, 0x8a, - 0xe7, 0xa5, 0x0f, 0x82, 0xa8, 0x73, 0x72, 0x0c, 0x12, 0xc7, 0x91, 0x07, 0x14, 0xd8, 0x9f, 0xeb, 0x39, 0x74, 0xcf, - 0xeb, 0xcb, 0x09, 0x3c, 0x0d, 0x97, 0xb0, 0x5d, 0xef, 0xbc, 0x4b, 0x1f, 0x6a, 0x32, 0x4a, 0xb0, 0x8d, 0x74, 0x73, - 0xe8, 0xa0, 0x51, 0x3b, 0x7a, 0xe4, 0xe3, 0x9e, 0xf1, 0xd1, 0x05, 0x8a, 0xbe, 0xc7, 0xb9, 0xd1, 0x33, 0x57, 0x0e, - 0xfa, 0x5c, 0xae, 0xbb, 0xa6, 0xbd, 0xaa, 0x13, 0xa3, 0x63, 0x52, 0x79, 0x29, 0x0a, 0x20, 0x49, 0xaa, 0xa7, 0x2d, - 0x52, 0xfb, 0xa9, 0x9c, 0x0d, 0x6c, 0x9e, 0xe1, 0x5e, 0x3c, 0x13, 0x4a, 0x42, 0x37, 0xfc, 0xc5, 0xb9, 0xa6, 0x7d, - 0x61, 0x99, 0xaa, 0x30, 0xb8, 0x61, 0x35, 0x2d, 0x21, 0xe8, 0x35, 0x08, 0x36, 0x0d, 0xee, 0x3f, 0x8e, 0x20, 0xd8, - 0x04, 0x5a, 0x3b, 0x83, 0x94, 0x81, 0x33, 0x36, 0xe2, 0x1f, 0xae, 0x68, 0x10, 0xc9, 0xcd, 0x03, 0x4f, 0xe2, 0xe5, - 0xb0, 0x24, 0x52, 0xde, 0x40, 0x28, 0x08, 0x7a, 0x2a, 0xb8, 0x08, 0x52, 0xd0, 0x98, 0xf6, 0x98, 0x1d, 0xa8, 0x36, - 0x38, 0x6e, 0x80, 0xcb, 0x57, 0x49, 0xd9, 0xa4, 0xda, 0xd4, 0x65, 0xaa, 0x62, 0xc7, 0xe0, 0x91, 0x97, 0xd6, 0x41, - 0x7a, 0x81, 0x22, 0x68, 0x8a, 0x52, 0xa4, 0x57, 0x35, 0x1d, 0x85, 0xb6, 0xa8, 0x36, 0x18, 0x3d, 0xa8, 0x18, 0x28, - 0xa9, 0xb0, 0xd8, 0xc8, 0x46, 0xd1, 0x9f, 0x19, 0x22, 0x8c, 0xc2, 0x0f, 0xed, 0xca, 0xc8, 0x87, 0x8f, 0x6a, 0x98, - 0xbd, 0x9b, 0x44, 0xb1, 0xc8, 0x4b, 0x7d, 0x5e, 0xf3, 0x88, 0x9a, 0x9d, 0x26, 0xf9, 0xfc, 0x66, 0x35, 0x70, 0x8a, - 0x49, 0xc9, 0x4e, 0x78, 0xb7, 0x4a, 0x4c, 0x82, 0x88, 0xad, 0xdf, 0x3e, 0xf5, 0xbc, 0x1b, 0xb8, 0xb4, 0xf7, 0x23, - 0x61, 0x7b, 0x59, 0xf2, 0xe8, 0xf0, 0xb2, 0xa8, 0xb9, 0xf9, 0xc6, 0x9c, 0xea, 0x2a, 0xd5, 0x1b, 0x02, 0x7e, 0x95, - 0x8e, 0x5e, 0x94, 0x09, 0x0a, 0xa7, 0x36, 0xdd, 0x07, 0x93, 0x11, 0xd0, 0xd1, 0xb3, 0x1a, 0xcd, 0xf2, 0xf4, 0xd5, - 0x32, 0xb1, 0xc3, 0xc6, 0xe8, 0x23, 0x0a, 0xbc, 0x6c, 0x55, 0x06, 0x47, 0x1a, 0x55, 0xca, 0xcc, 0x0b, 0xa2, 0xea, - 0x44, 0xad, 0x60, 0x2f, 0x35, 0xf8, 0x0f, 0x08, 0xd3, 0x25, 0x0f, 0x9c, 0x1a, 0x80, 0x1c, 0xb3, 0x88, 0x74, 0x54, - 0x80, 0xdf, 0x3e, 0x4d, 0xcf, 0x98, 0x6b, 0xb8, 0xcb, 0x1a, 0x44, 0x11, 0x6d, 0x1f, 0xb1, 0x44, 0xd2, 0x1d, 0x2e, - 0x8c, 0x29, 0x42, 0xb8, 0x39, 0x2a, 0x04, 0x01, 0xac, 0x30, 0xf8, 0x12, 0xe3, 0x80, 0xb4, 0xa8, 0x7b, 0x14, 0x5e, - 0xb6, 0x0a, 0xbe, 0xcb, 0x05, 0xc7, 0x58, 0xd9, 0xbb, 0x90, 0x58, 0x17, 0xa2, 0x41, 0xb7, 0xfc, 0x7b, 0x84, 0xfc, - 0x6a, 0x68, 0x66, 0xb5, 0xf9, 0x0a, 0xee, 0x5b, 0xaf, 0x9d, 0x4d, 0x26, 0x30, 0xbb, 0x12, 0x55, 0x21, 0x8b, 0x90, - 0xb2, 0x17, 0x22, 0xd3, 0xb4, 0x95, 0x28, 0x39, 0x47, 0x40, 0x12, 0xd8, 0x02, 0x01, 0x36, 0xf8, 0xa1, 0x5a, 0x96, - 0x43, 0x09, 0x55, 0x0d, 0x8c, 0x90, 0xef, 0xc5, 0x02, 0x88, 0x5a, 0x56, 0xbd, 0xa2, 0x0c, 0xec, 0x68, 0xd9, 0xeb, - 0xac, 0x67, 0x40, 0xc9, 0x7e, 0x83, 0x40, 0x78, 0x1b, 0x9e, 0xbe, 0xff, 0x26, 0xe4, 0xd1, 0x99, 0x63, 0x4d, 0x58, - 0x78, 0x44, 0x6e, 0x1c, 0x60, 0xe5, 0x73, 0x5b, 0x82, 0x90, 0x05, 0xa5, 0xdf, 0x95, 0x2b, 0x7b, 0xd4, 0x67, 0xa6, - 0x46, 0x15, 0x82, 0xbc, 0xb9, 0xec, 0x03, 0x69, 0xa9, 0x03, 0xed, 0x1f, 0x90, 0x81, 0xc1, 0x09, 0xdc, 0x3b, 0x55, - 0x84, 0xb2, 0xc7, 0x18, 0xfe, 0xdc, 0xa6, 0xa6, 0x4d, 0xdc, 0xf3, 0x33, 0x98, 0x14, 0x03, 0x92, 0x95, 0x92, 0x7b, - 0x9e, 0xff, 0xae, 0x86, 0x2a, 0x48, 0x28, 0x4c, 0x4b, 0xf0, 0x24, 0x2b, 0x23, 0x84, 0xc8, 0x44, 0xc7, 0x41, 0xe7, - 0x40, 0xbc, 0xba, 0x37, 0x30, 0x9f, 0xd9, 0x31, 0x4b, 0x7e, 0xf7, 0x68, 0xb9, 0x4e, 0xc4, 0xb2, 0x86, 0x1f, 0x46, - 0xb3, 0x1b, 0xfb, 0x89, 0x70, 0xdd, 0xc2, 0x1a, 0x97, 0x06, 0xcf, 0xd0, 0xad, 0xf6, 0xf8, 0x4d, 0xce, 0x50, 0x4c, - 0xdb, 0x74, 0xac, 0x0e, 0xaf, 0xaf, 0xd5, 0xac, 0xb2, 0x85, 0x6a, 0xb7, 0x9c, 0x5f, 0xab, 0x6a, 0xcd, 0xd6, 0x6e, - 0xa1, 0x95, 0xd5, 0xe7, 0x3f, 0x8b, 0xf9, 0x9c, 0xc2, 0x62, 0x7e, 0x30, 0x80, 0xbb, 0x28, 0xe2, 0xc5, 0x89, 0xbb, - 0xe6, 0xda, 0xfe, 0xa0, 0xf6, 0xca, 0xe5, 0xe3, 0x6b, 0x8f, 0xfb, 0xef, 0x22, 0x46, 0xbd, 0xb0, 0x8f, 0x02, 0xb8, - 0x56, 0x23, 0x1e, 0x0f, 0x1f, 0x5d, 0xcc, 0xab, 0x35, 0xf5, 0x49, 0x1d, 0x79, 0xcf, 0x5d, 0xef, 0x5b, 0x5a, 0xb2, - 0x38, 0xad, 0x3c, 0xcd, 0x3e, 0x10, 0x23, 0xb3, 0x81, 0xd6, 0x9b, 0x34, 0x43, 0x86, 0x3b, 0x12, 0x7c, 0xb2, 0x52, - 0xf4, 0xe2, 0x64, 0xf7, 0xd4, 0x20, 0x52, 0xb2, 0xd1, 0xcc, 0x42, 0xa0, 0x96, 0x97, 0x21, 0xd3, 0x74, 0x2c, 0x0a, - 0x51, 0x0e, 0x2c, 0x28, 0x0f, 0x9a, 0x30, 0xc5, 0x93, 0x70, 0x1a, 0x47, 0x92, 0x62, 0x35, 0x0d, 0xb9, 0xcd, 0x49, - 0x89, 0x1a, 0xd2, 0xd5, 0xb9, 0xc1, 0x03, 0xad, 0x16, 0x98, 0xc0, 0xa1, 0x24, 0x05, 0x98, 0x6b, 0xa4, 0x67, 0x88, - 0x28, 0x04, 0x03, 0xf4, 0xfa, 0x96, 0x9d, 0x87, 0xce, 0xbb, 0x93, 0x72, 0x59, 0x53, 0x10, 0x6f, 0x3e, 0xf6, 0xa1, - 0x65, 0xa6, 0x75, 0x27, 0x37, 0x54, 0xf2, 0x7c, 0x09, 0xb5, 0x34, 0x81, 0xfb, 0x84, 0x8b, 0x6a, 0x26, 0x54, 0x21, - 0xff, 0x26, 0xf7, 0xfd, 0x62, 0xef, 0xc2, 0xbc, 0xba, 0x7d, 0x80, 0xcf, 0x8f, 0x97, 0x2a, 0x47, 0xe1, 0x93, 0x91, - 0xdc, 0x6a, 0x25, 0x9f, 0x67, 0x10, 0x32, 0xf3, 0x85, 0x9b, 0xbb, 0x1f, 0xb5, 0xe9, 0xc3, 0x26, 0x7f, 0xd6, 0x81, - 0xe5, 0xb6, 0x79, 0x25, 0x26, 0x7f, 0xac, 0x76, 0x2c, 0xda, 0x7b, 0x77, 0x85, 0x3e, 0x8a, 0xf5, 0xe9, 0x84, 0xbb, - 0x7f, 0xa8, 0x7c, 0x5e, 0x36, 0xfa, 0x48, 0x5d, 0xae, 0x8f, 0x7f, 0x85, 0xee, 0x8b, 0x84, 0x6a, 0x58, 0xe3, 0xbd, - 0x4c, 0xb9, 0x30, 0x7b, 0x81, 0x8d, 0xb9, 0x3a, 0xed, 0x66, 0x52, 0x82, 0x6e, 0xdb, 0xfb, 0x8f, 0xfc, 0x08, 0x67, - 0x11, 0x05, 0x37, 0xf9, 0x9d, 0x19, 0xcb, 0xa1, 0x3f, 0xdf, 0x99, 0x41, 0x2f, 0x1f, 0xc2, 0xde, 0xc5, 0xbb, 0xf4, - 0x01, 0xb9, 0x1e, 0xa7, 0x4a, 0x3e, 0xfb, 0xb1, 0xfe, 0x56, 0xc9, 0x3f, 0x8b, 0x84, 0x79, 0x6b, 0x62, 0x85, 0xb9, - 0x31, 0x49, 0x7e, 0xfb, 0xeb, 0xb6, 0xa5, 0x9d, 0xc9, 0xed, 0x62, 0xd3, 0xba, 0x85, 0x67, 0x42, 0x36, 0x81, 0x89, - 0xd9, 0x2f, 0x52, 0xd0, 0x95, 0x32, 0x35, 0x6e, 0x92, 0xd2, 0xca, 0xb3, 0xce, 0xdb, 0x77, 0xcc, 0x1c, 0xd7, 0xa7, - 0x2a, 0x0b, 0x72, 0xab, 0x28, 0xe4, 0x14, 0xda, 0x63, 0xe4, 0x12, 0x3a, 0x4c, 0x97, 0xdc, 0x45, 0xcc, 0x65, 0x11, - 0xd3, 0x7b, 0x79, 0xee, 0x93, 0x10, 0xd3, 0x66, 0x3b, 0xe5, 0x95, 0xfc, 0x0f, 0xb9, 0x79, 0x90, 0x55, 0x41, 0x1d, - 0x80, 0xe9, 0xfd, 0xd5, 0xfa, 0xf3, 0xd9, 0xd2, 0xe0, 0x54, 0x71, 0xf0, 0xf2, 0x53, 0x69, 0x72, 0xf3, 0xc6, 0x39, - 0xdd, 0x10, 0x95, 0x4a, 0x39, 0x16, 0x83, 0x8e, 0x91, 0xa3, 0x6a, 0x34, 0x8b, 0xf9, 0x04, 0x75, 0xed, 0x24, 0xfe, - 0x78, 0x26, 0x67, 0x35, 0x54, 0x73, 0x17, 0x7c, 0x72, 0x6c, 0x79, 0x37, 0x0d, 0xc5, 0x70, 0x7f, 0xb7, 0x55, 0x3f, - 0x67, 0x74, 0xd6, 0x4d, 0x0f, 0x05, 0x37, 0x70, 0xbe, 0xeb, 0xe1, 0x4b, 0x69, 0xdd, 0xaa, 0x59, 0x2a, 0x51, 0x10, - 0xaa, 0xa4, 0xb9, 0x7a, 0xc3, 0xd4, 0x40, 0x1f, 0x6a, 0xfe, 0x8e, 0x32, 0x98, 0xe2, 0x12, 0x00, 0x35, 0xc9, 0xe1, - 0xdb, 0xd4, 0x42, 0xc9, 0x48, 0x6f, 0x05, 0xe6, 0x18, 0xff, 0x1b, 0x48, 0x43, 0x26, 0x03, 0x6e, 0xf5, 0x35, 0xbf, - 0x99, 0xe4, 0xdf, 0x74, 0xdf, 0x07, 0xe7, 0xd3, 0x38, 0x7d, 0x0d, 0x05, 0xf6, 0x41, 0x7b, 0x9f, 0xf6, 0x9c, 0x29, - 0x69, 0x7b, 0x5c, 0x6d, 0xc5, 0x57, 0xdc, 0x4d, 0x61, 0xf0, 0x4f, 0x0f, 0x84, 0x22, 0xfa, 0x6e, 0xe0, 0x50, 0xb8, - 0x1d, 0x3f, 0x31, 0x8d, 0xa8, 0x43, 0xa6, 0xaa, 0x2f, 0x49, 0x3e, 0xda, 0xfc, 0x21, 0xac, 0x09, 0x8e, 0x1c, 0xe3, - 0xa6, 0x67, 0xa8, 0x88, 0xcc, 0x13, 0xaf, 0x76, 0x0f, 0x9c, 0x9a, 0x80, 0xeb, 0x79, 0x64, 0xde, 0xa7, 0xa9, 0x6d, - 0x70, 0xf1, 0x04, 0xb9, 0x73, 0x03, 0x78, 0xa7, 0x56, 0x57, 0xfb, 0x97, 0x5a, 0xef, 0x42, 0x84, 0x5b, 0x00, 0x51, - 0x8e, 0x5f, 0x64, 0x13, 0xb9, 0x7f, 0x70, 0xe6, 0x62, 0x4e, 0xc3, 0x3d, 0xd2, 0xa1, 0xe4, 0xee, 0x10, 0xb5, 0xce, - 0x2a, 0x67, 0x72, 0xa3, 0x98, 0x25, 0x93, 0x42, 0x00, 0x04, 0xa6, 0x55, 0xbe, 0x22, 0x02, 0xb8, 0x0a, 0x0b, 0x8d, - 0xa6, 0x28, 0xf2, 0x2b, 0xaa, 0xed, 0x67, 0xb4, 0x5b, 0xf6, 0xa3, 0xa3, 0x6b, 0xc7, 0x4c, 0x6a, 0x35, 0x71, 0xe9, - 0x48, 0x0a, 0x66, 0x98, 0xbc, 0xb9, 0x28, 0xe4, 0x15, 0x1f, 0xcc, 0x0f, 0x43, 0x02, 0x53, 0x69, 0x05, 0x85, 0x5c, - 0xaf, 0xb1, 0x33, 0x47, 0xa8, 0xe1, 0x34, 0x6b, 0x3c, 0x3d, 0x7d, 0x5e, 0x8a, 0xd7, 0x8e, 0x53, 0xb5, 0xcd, 0x38, - 0x1d, 0x2c, 0xc2, 0x79, 0x91, 0x76, 0x59, 0xb6, 0x12, 0x81, 0xec, 0xc7, 0xf4, 0x6f, 0xe3, 0xbc, 0xd0, 0xbf, 0x59, - 0xe7, 0x58, 0x9e, 0xc0, 0xc8, 0x12, 0x2d, 0x54, 0xc7, 0xfc, 0xa7, 0x56, 0x6c, 0xad, 0xf0, 0x9d, 0xa8, 0x24, 0xc6, - 0xab, 0x73, 0x69, 0xcf, 0x75, 0xe7, 0x87, 0x10, 0x2c, 0x0f, 0xf0, 0xb3, 0xb8, 0xca, 0xf7, 0x67, 0x85, 0x5b, 0xe9, - 0x3f, 0xeb, 0xe6, 0xef, 0x8a, 0xde, 0x93, 0x8f, 0x1f, 0x52, 0xc4, 0x34, 0x81, 0xf9, 0xae, 0x01, 0x34, 0x55, 0x48, - 0x58, 0x94, 0x2a, 0x6e, 0x43, 0x8e, 0xf7, 0xcf, 0xeb, 0x5e, 0xc4, 0xa2, 0x94, 0x23, 0xbb, 0x8e, 0x3b, 0x7e, 0x29, - 0x30, 0x03, 0x5c, 0xc0, 0xf7, 0x50, 0x4e, 0xa0, 0x1f, 0x3b, 0x8f, 0x8f, 0x44, 0x51, 0x38, 0x65, 0xbc, 0x53, 0x58, - 0xeb, 0xf0, 0x42, 0x79, 0x97, 0x6e, 0x14, 0xd3, 0xa8, 0x89, 0x9f, 0x32, 0xbe, 0xb1, 0x1a, 0x3d, 0xd6, 0x35, 0xba, - 0x1f, 0xcd, 0x8f, 0x82, 0x36, 0xb0, 0x88, 0xbd, 0xff, 0xd3, 0x21, 0xc5, 0xc4, 0xe4, 0xbc, 0x65, 0x2c, 0x70, 0x24, - 0xa4, 0xca, 0xad, 0xcc, 0xf7, 0xa9, 0x88, 0xca, 0xf4, 0x2b, 0x9c, 0xf1, 0x3b, 0x42, 0x44, 0x15, 0x16, 0xfb, 0xa7, - 0xd6, 0x3d, 0x66, 0xd2, 0xcd, 0xa6, 0x3e, 0x55, 0x20, 0x0d, 0x45, 0x9e, 0xaa, 0xe9, 0x25, 0x34, 0xb7, 0xbb, 0xcf, - 0xcf, 0x67, 0x8f, 0x0a, 0xf2, 0xf9, 0xef, 0x0f, 0xfa, 0xfe, 0xbe, 0x90, 0x07, 0xad, 0x6f, 0xe5, 0x33, 0xd4, 0xfe, - 0x75, 0x95, 0x3d, 0x35, 0xc0, 0x99, 0x22, 0x92, 0x97, 0xfc, 0x08, 0xa7, 0x6b, 0x6e, 0x96, 0xbe, 0x7a, 0xca, 0x75, - 0x3f, 0x5d, 0xce, 0x6a, 0x91, 0x1c, 0x33, 0x44, 0xd0, 0xde, 0xc8, 0xb8, 0xc7, 0xf7, 0x59, 0x22, 0x9d, 0x85, 0x09, - 0xba, 0x88, 0xea, 0xf6, 0x68, 0x43, 0xd9, 0xad, 0xe6, 0x2d, 0xf7, 0xc6, 0x1f, 0xe8, 0x7b, 0xd6, 0x8b, 0xa0, 0x34, - 0x94, 0x60, 0xc7, 0xdd, 0xa8, 0x71, 0x44, 0x3a, 0xd7, 0x1d, 0xa4, 0x91, 0x7b, 0xa1, 0x58, 0x52, 0xde, 0x77, 0xb3, - 0xa3, 0x30, 0x69, 0x81, 0x15, 0x76, 0xea, 0xf2, 0xe0, 0x6e, 0x5a, 0x98, 0x75, 0x0a, 0x85, 0xca, 0x74, 0x31, 0xf0, - 0xc5, 0xa6, 0xb4, 0xae, 0x57, 0x0e, 0xc8, 0x01, 0x8c, 0x8e, 0x83, 0x14, 0x26, 0xd5, 0x58, 0x92, 0xca, 0xd0, 0xd1, - 0x72, 0x68, 0x59, 0xaa, 0x14, 0x14, 0xbd, 0x03, 0x0c, 0xca, 0x78, 0xf6, 0xff, 0xc3, 0x9c, 0x0b, 0x83, 0x58, 0x0e, - 0xec, 0x57, 0x64, 0x5f, 0x5d, 0x77, 0xc2, 0x49, 0x54, 0x10, 0xa6, 0xba, 0x91, 0xa9, 0x47, 0x15, 0xd8, 0x84, 0x1c, - 0xd2, 0x24, 0xc9, 0xe9, 0xc0, 0x04, 0x72, 0xe4, 0x69, 0x13, 0x51, 0x17, 0x92, 0xca, 0xe5, 0x97, 0xce, 0xb7, 0x5f, - 0x71, 0xe6, 0x2f, 0x30, 0x92, 0x53, 0x4a, 0xc7, 0x3a, 0x8b, 0xf1, 0x3b, 0xed, 0x7e, 0x3a, 0x6f, 0xfb, 0x9c, 0x5f, - 0x72, 0x80, 0xde, 0x42, 0x55, 0xce, 0x10, 0x90, 0x1e, 0xfa, 0xfe, 0x7a, 0x47, 0xb5, 0xa0, 0x3b, 0x6e, 0xfa, 0xe4, - 0x33, 0xce, 0x5e, 0xad, 0x93, 0xcf, 0x4f, 0xde, 0x28, 0xc4, 0x48, 0x04, 0x5d, 0x3b, 0x52, 0x95, 0x76, 0x9f, 0x6f, - 0xe4, 0x2a, 0x5c, 0xae, 0x41, 0xb3, 0x83, 0xa2, 0x53, 0xda, 0xcf, 0x94, 0xb1, 0xae, 0x7e, 0x4a, 0x0e, 0x1b, 0xb0, - 0xd9, 0x10, 0xe3, 0x48, 0xdc, 0x78, 0xa5, 0x62, 0x80, 0x33, 0x37, 0xaa, 0x61, 0xa5, 0xb7, 0x9d, 0x93, 0x5f, 0xe2, - 0x95, 0x06, 0xcf, 0x13, 0x2c, 0xd1, 0x45, 0x9f, 0x57, 0x8f, 0xd3, 0x51, 0xe6, 0x1b, 0xea, 0xdf, 0xa0, 0xda, 0x26, - 0x5d, 0x88, 0x75, 0x9a, 0xce, 0x21, 0xcf, 0x95, 0x1f, 0xdd, 0x99, 0x20, 0x73, 0x47, 0x85, 0x6b, 0xd5, 0xa0, 0x40, - 0x53, 0xf6, 0xc9, 0x4a, 0x78, 0x74, 0xeb, 0x93, 0x4c, 0xda, 0x47, 0x6b, 0xe5, 0xc3, 0xad, 0x28, 0xfb, 0x77, 0xcf, - 0xbf, 0xf7, 0x99, 0xde, 0x22, 0x1d, 0xd7, 0xac, 0xf6, 0x2f, 0xf8, 0x29, 0xe7, 0x34, 0xde, 0x12, 0xa5, 0x44, 0xe5, - 0x87, 0xe3, 0x80, 0x58, 0xbc, 0x41, 0xfc, 0xd1, 0x0f, 0xdc, 0xec, 0x45, 0xac, 0x2f, 0x55, 0x5a, 0x54, 0x7f, 0xb2, - 0xc7, 0x55, 0x0d, 0x8e, 0x1f, 0xeb, 0xf9, 0x75, 0xac, 0xbc, 0x13, 0x0d, 0xb0, 0x56, 0x02, 0x1f, 0xdb, 0x95, 0x80, - 0x02, 0x22, 0xbd, 0x25, 0x6f, 0xcf, 0xff, 0x77, 0x8b, 0xfd, 0x7e, 0x47, 0xf7, 0xd3, 0xce, 0x8d, 0xaa, 0xd1, 0x69, - 0x53, 0x58, 0x0a, 0xdb, 0xee, 0xb3, 0xc0, 0x45, 0xc6, 0x80, 0x40, 0x35, 0xe6, 0x1f, 0x92, 0x30, 0xa7, 0xc0, 0xbb, - 0x3c, 0x38, 0x8e, 0xfc, 0x96, 0xfa, 0xc6, 0x0a, 0xf7, 0xef, 0xf6, 0xae, 0xb7, 0x20, 0x42, 0x65, 0x9f, 0xa0, 0xdc, - 0x91, 0x3f, 0xf6, 0xd3, 0x0b, 0xd4, 0x47, 0x61, 0xaf, 0x60, 0xd5, 0xd1, 0xa2, 0x6b, 0x07, 0x3a, 0x07, 0xbd, 0x1b, - 0x51, 0x51, 0xf9, 0x98, 0x8d, 0xa5, 0x66, 0x7c, 0x04, 0x30, 0x02, 0x58, 0x0c, 0x71, 0xe2, 0xda, 0x2b, 0xf7, 0x35, - 0xba, 0x02, 0x02, 0x8c, 0xe1, 0x1f, 0x36, 0x38, 0xb7, 0x5e, 0x59, 0x06, 0x9a, 0x1c, 0xe0, 0xd4, 0x26, 0x8b, 0x53, - 0x8b, 0x53, 0xbc, 0xdf, 0xf9, 0xc6, 0xe8, 0xed, 0x05, 0x39, 0x1d, 0xf0, 0x1e, 0x7b, 0x14, 0x15, 0x35, 0x64, 0xa0, - 0x85, 0x6f, 0xbb, 0x21, 0x62, 0x65, 0x30, 0x0b, 0xfa, 0x70, 0xee, 0xfb, 0xf3, 0x4b, 0x2a, 0x54, 0xff, 0x57, 0xaf, - 0xbd, 0xae, 0x5a, 0xf0, 0xc4, 0x35, 0xec, 0x2e, 0xb8, 0x72, 0x4a, 0xed, 0x58, 0xa5, 0xa7, 0x9d, 0x64, 0x50, 0x10, - 0xda, 0x21, 0x85, 0x67, 0xff, 0x67, 0x51, 0x7d, 0x9e, 0x5b, 0xcd, 0xa1, 0xfa, 0xcc, 0x3a, 0x0e, 0x88, 0x7f, 0x3f, - 0xca, 0xbb, 0x3a, 0x08, 0x50, 0x35, 0xe4, 0x93, 0x02, 0xf3, 0x5f, 0xf1, 0x2c, 0x6f, 0x44, 0xba, 0x9d, 0xd9, 0x7d, - 0x8d, 0xcb, 0x99, 0xdc, 0x4e, 0xe6, 0x9b, 0x79, 0xb8, 0xd9, 0x79, 0x7f, 0xbd, 0xa5, 0x4a, 0xda, 0x7a, 0xa5, 0x3e, - 0x3d, 0xe0, 0x38, 0x20, 0xd2, 0x66, 0x19, 0x46, 0x73, 0x7e, 0xee, 0x06, 0xbe, 0x1f, 0x16, 0x61, 0xbe, 0x5f, 0xfb, - 0xb5, 0xe0, 0xc6, 0x24, 0x6f, 0x24, 0x4e, 0xd4, 0xc0, 0x65, 0x8a, 0xa1, 0x2b, 0x05, 0xbc, 0x89, 0x43, 0x5f, 0xc3, - 0x94, 0x1d, 0xf4, 0x5e, 0xb8, 0x1e, 0xf5, 0x74, 0xc4, 0x05, 0xae, 0xba, 0x79, 0x24, 0x93, 0xcc, 0x37, 0x94, 0x31, - 0xde, 0xf0, 0xaa, 0xdf, 0xb8, 0x73, 0xaf, 0x93, 0x32, 0x80, 0x5d, 0x2a, 0x28, 0x7e, 0xbc, 0x6a, 0x55, 0x53, 0x9f, - 0x8a, 0x10, 0xb2, 0x90, 0x4b, 0x01, 0xee, 0xf2, 0xfc, 0x99, 0x7c, 0x1e, 0x5d, 0xdc, 0x0d, 0x55, 0x03, 0xd0, 0x6a, - 0xea, 0xeb, 0x02, 0xc6, 0x91, 0x27, 0x45, 0xca, 0x70, 0x66, 0x6d, 0x78, 0x51, 0xab, 0x4f, 0xb9, 0xa4, 0x21, 0xa3, - 0xb6, 0x53, 0xea, 0x41, 0xbe, 0xd6, 0xd9, 0xec, 0x91, 0x37, 0xb8, 0xa1, 0x65, 0xbb, 0x92, 0x8f, 0x20, 0x8a, 0x26, - 0xc0, 0x72, 0x96, 0xb6, 0x09, 0x32, 0xf8, 0x0e, 0x2d, 0x92, 0xc1, 0x10, 0xb1, 0xc0, 0x9e, 0x77, 0xab, 0xe2, 0xb5, - 0xbd, 0x9c, 0x6a, 0x27, 0xd3, 0xef, 0x72, 0x74, 0xf6, 0x81, 0x3a, 0x1c, 0xac, 0xea, 0x65, 0x17, 0x6a, 0xfd, 0xbb, - 0x1f, 0xda, 0x0a, 0x02, 0x59, 0x03, 0x27, 0x4a, 0x8a, 0xbd, 0x52, 0x65, 0x6b, 0xe4, 0x24, 0xc0, 0x5d, 0x1f, 0xcf, - 0x44, 0x14, 0xb3, 0x74, 0x4e, 0xbf, 0x0b, 0x42, 0x8f, 0x31, 0xac, 0x90, 0x6a, 0x02, 0x8d, 0x9f, 0x5c, 0xd1, 0xdd, - 0x60, 0x35, 0xd9, 0x33, 0xd2, 0x17, 0x63, 0x3d, 0xdd, 0xd9, 0x36, 0xa8, 0x43, 0xfb, 0x6c, 0xb6, 0xaf, 0x2b, 0x8c, - 0x58, 0xf9, 0xa2, 0x1a, 0x7b, 0x61, 0x0b, 0xdc, 0xa9, 0x0b, 0x91, 0xb1, 0x62, 0x66, 0x7a, 0xc2, 0x50, 0x70, 0x5c, - 0x23, 0x1f, 0xe3, 0xc4, 0x4c, 0xa4, 0xb4, 0x2b, 0x76, 0x9a, 0x12, 0x70, 0x0a, 0x84, 0x8e, 0x3d, 0xed, 0xd6, 0x6a, - 0x41, 0xf2, 0x60, 0xe9, 0xb2, 0x1f, 0xe2, 0x7a, 0x3c, 0x2d, 0x29, 0x84, 0x20, 0x5c, 0x9c, 0x9e, 0x75, 0xb3, 0x8c, - 0xe3, 0xc1, 0x94, 0xa6, 0xc3, 0xfe, 0x69, 0x3f, 0xad, 0x0c, 0x3e, 0xde, 0x57, 0x2b, 0x3c, 0x76, 0x20, 0xf8, 0x3c, - 0xfa, 0xde, 0x20, 0xcf, 0xff, 0x34, 0xc9, 0xff, 0x3a, 0x86, 0x40, 0x0d, 0x5b, 0xb1, 0xa0, 0x1b, 0xbe, 0xb1, 0x09, - 0x5e, 0xae, 0x99, 0x57, 0x3a, 0x5b, 0x8b, 0xb3, 0x88, 0x0c, 0x0b, 0x78, 0x7c, 0xf3, 0xe3, 0xfa, 0x23, 0x9c, 0x8d, - 0xcb, 0x18, 0xc3, 0x4b, 0x6e, 0x80, 0x24, 0x21, 0x5c, 0x42, 0xcc, 0x58, 0x77, 0xcf, 0x0d, 0x6e, 0xab, 0x8d, 0xaf, - 0x01, 0xb7, 0x9e, 0x2f, 0xc6, 0xcb, 0x84, 0xf3, 0xe9, 0xcf, 0xca, 0x75, 0x4f, 0xa5, 0xb9, 0x51, 0x6f, 0xb5, 0xfe, - 0xe3, 0xd9, 0xef, 0x1e, 0xb0, 0x24, 0xdc, 0x4f, 0x2d, 0xc3, 0x7c, 0xf2, 0xea, 0x92, 0x89, 0x10, 0xcf, 0x02, 0x5a, - 0x0e, 0x51, 0x88, 0x0f, 0x17, 0x90, 0xe7, 0xee, 0xe8, 0x70, 0xe4, 0x76, 0x9a, 0x4b, 0x23, 0x47, 0x76, 0x30, 0xb4, - 0xa8, 0xa4, 0x0b, 0xab, 0x95, 0x69, 0x9f, 0x4a, 0x37, 0x22, 0x72, 0x20, 0x31, 0x59, 0xb1, 0xcf, 0x30, 0xd3, 0x0e, - 0x9c, 0x7a, 0x40, 0xfc, 0xcf, 0x7f, 0x11, 0x19, 0xca, 0x09, 0x2f, 0xb5, 0xb0, 0x84, 0xa5, 0xca, 0x6c, 0x1f, 0x8f, - 0x9c, 0xca, 0xcc, 0xaa, 0x57, 0x8b, 0x78, 0xeb, 0x8d, 0x86, 0xa6, 0x13, 0x23, 0xc5, 0x07, 0xbe, 0x8c, 0x02, 0x2a, - 0x34, 0xe9, 0xa1, 0x88, 0xd7, 0xf3, 0xcc, 0x39, 0x04, 0xe0, 0x1b, 0x7d, 0xb7, 0x54, 0x75, 0x5d, 0x5f, 0xec, 0x77, - 0x29, 0xf7, 0x25, 0x05, 0xb1, 0xe4, 0xdc, 0x3d, 0xc6, 0x39, 0x1c, 0x39, 0x78, 0x6a, 0x24, 0x15, 0x75, 0x16, 0x89, - 0xc4, 0x82, 0x96, 0xd2, 0xed, 0xb0, 0xdc, 0x03, 0xa6, 0x51, 0xa8, 0x6a, 0xa3, 0xc7, 0x5d, 0x97, 0x00, 0xda, 0xec, - 0x24, 0x84, 0xf7, 0xf0, 0x7d, 0xb6, 0x98, 0x0b, 0xb9, 0xe0, 0x6c, 0x7f, 0x9b, 0x53, 0x29, 0x57, 0xb1, 0x67, 0xa3, - 0xb4, 0x43, 0xf3, 0xed, 0xdc, 0xb3, 0x5a, 0x32, 0x2b, 0x62, 0x0c, 0x91, 0xd3, 0x37, 0x92, 0xb6, 0x0d, 0xd2, 0xe1, - 0x70, 0xcd, 0x90, 0xe0, 0x73, 0x5e, 0x6b, 0x2f, 0xc5, 0x93, 0x71, 0x52, 0xf8, 0x6f, 0x26, 0xd9, 0x79, 0x6d, 0xfd, - 0xa3, 0x3f, 0x24, 0x5b, 0x01, 0xc1, 0x13, 0x7e, 0x35, 0xd9, 0xcc, 0xae, 0xb9, 0xf9, 0xbd, 0x86, 0xf6, 0xd4, 0x52, - 0xb0, 0x66, 0x02, 0xad, 0x4d, 0xca, 0xe7, 0xa2, 0x8f, 0xaf, 0x57, 0x77, 0x24, 0xee, 0xd3, 0x67, 0xd2, 0x35, 0x25, - 0x2f, 0x19, 0x0b, 0xca, 0x37, 0xbc, 0xd9, 0x1f, 0xa3, 0x08, 0xa8, 0x1a, 0x72, 0x05, 0xf5, 0x75, 0x4f, 0xa6, 0xcf, - 0xda, 0x41, 0x58, 0xaf, 0x02, 0x9b, 0x80, 0x22, 0x11, 0xfd, 0xb7, 0x79, 0x8f, 0x3e, 0xe4, 0xd0, 0x1d, 0xb2, 0x37, - 0xb0, 0x9e, 0xac, 0x74, 0x27, 0x11, 0x8a, 0x0a, 0x9f, 0x3b, 0x01, 0xa5, 0x64, 0x07, 0xa5, 0x06, 0x7c, 0xd6, 0x4b, - 0xe4, 0x98, 0xf9, 0xc6, 0xf1, 0x2e, 0xf1, 0x8e, 0xb2, 0xf8, 0xc0, 0x81, 0x9d, 0xea, 0xe7, 0xef, 0x63, 0xf9, 0x72, - 0x8c, 0x07, 0x91, 0xd1, 0xef, 0x45, 0x01, 0xbe, 0xec, 0x37, 0xcd, 0xc8, 0xf3, 0xaf, 0xbf, 0xa5, 0x8d, 0x3c, 0xf3, - 0x6b, 0xa9, 0x84, 0x65, 0xdd, 0x9d, 0x3f, 0x45, 0xbb, 0x94, 0xd8, 0x70, 0x5b, 0xf4, 0xc1, 0x20, 0x97, 0x1b, 0x00, - 0x1f, 0x70, 0x2e, 0xff, 0x99, 0xa3, 0x50, 0x3e, 0x52, 0xeb, 0xf2, 0x64, 0x29, 0xc4, 0x98, 0xfc, 0x8d, 0x51, 0x2d, - 0x67, 0xae, 0x8f, 0xfc, 0x7e, 0xc1, 0x2f, 0x9c, 0x9d, 0xee, 0x07, 0xc8, 0x02, 0x41, 0x8b, 0x15, 0x5d, 0xe9, 0xa1, - 0xa8, 0xa5, 0xaa, 0x18, 0x4a, 0xf3, 0x62, 0x2c, 0x2d, 0x8a, 0x69, 0x63, 0x0f, 0x5e, 0x20, 0x52, 0x70, 0x3d, 0x35, - 0x4b, 0xa6, 0xd0, 0x43, 0xcf, 0xe0, 0x9e, 0xa9, 0xa4, 0xac, 0x75, 0x4e, 0xc3, 0xc0, 0x0a, 0x66, 0xc4, 0x0a, 0x6b, - 0xab, 0x93, 0x96, 0xbd, 0x02, 0x31, 0x96, 0x05, 0x0a, 0x14, 0xaa, 0x83, 0x58, 0x49, 0x15, 0x12, 0xcc, 0xd9, 0x16, - 0x23, 0x3d, 0x5b, 0x49, 0x95, 0xee, 0x34, 0x34, 0xe7, 0x67, 0x85, 0xd1, 0x1b, 0x01, 0xdd, 0xa2, 0xb8, 0xbf, 0x5f, - 0xd7, 0xb0, 0x41, 0x66, 0xa5, 0x2a, 0xaa, 0x17, 0x51, 0x95, 0x69, 0x46, 0x5a, 0x82, 0xec, 0xf9, 0x0c, 0xe4, 0xaa, - 0x72, 0xd4, 0x1e, 0xd3, 0x5e, 0x00, 0xd5, 0xe8, 0xb3, 0xe8, 0xe8, 0x45, 0x9a, 0x43, 0x5d, 0x37, 0x6c, 0xa9, 0x15, - 0x65, 0x52, 0x50, 0xac, 0x91, 0xdf, 0x4e, 0xb2, 0x46, 0x44, 0x76, 0xb3, 0x8b, 0xef, 0xe9, 0xae, 0x92, 0x4d, 0xb2, - 0xf1, 0x69, 0x1c, 0x20, 0xb4, 0x4e, 0x48, 0x2c, 0x6a, 0xbc, 0xe0, 0x2d, 0xe1, 0xd2, 0x72, 0x18, 0x7f, 0x74, 0xbc, - 0xbf, 0xe4, 0x0a, 0x0f, 0xac, 0x48, 0xeb, 0x84, 0x45, 0x7e, 0x32, 0x2e, 0xe0, 0xd7, 0xfe, 0xac, 0x90, 0x59, 0x33, - 0x16, 0xb9, 0xf0, 0x59, 0x94, 0x27, 0xb1, 0xae, 0x2d, 0xdd, 0x93, 0x71, 0xff, 0xd8, 0x99, 0x3a, 0xde, 0x9f, 0x74, - 0x08, 0xfc, 0x02, 0x50, 0xaa, 0x1e, 0x10, 0xfb, 0xc0, 0xf7, 0x78, 0x65, 0x51, 0x04, 0x97, 0xe1, 0xf6, 0x90, 0x8a, - 0xf2, 0x34, 0x77, 0xd5, 0xb4, 0xf2, 0x17, 0x21, 0x09, 0xaa, 0xe1, 0x9b, 0x94, 0xa4, 0x40, 0xe9, 0xa3, 0x1c, 0x26, - 0x3d, 0x62, 0x9f, 0xdf, 0xfb, 0xd2, 0x67, 0xa7, 0xf0, 0xa5, 0x4f, 0xba, 0x66, 0x6d, 0x85, 0xb7, 0xff, 0x36, 0xb0, - 0x83, 0x99, 0x1e, 0xc5, 0xef, 0x87, 0x38, 0x2d, 0xd6, 0x32, 0xea, 0xce, 0x2f, 0x96, 0xbd, 0x0d, 0xf9, 0x3f, 0xfc, - 0xee, 0x82, 0xd3, 0xf0, 0xfd, 0x69, 0xd5, 0xdd, 0x78, 0x5b, 0x39, 0x74, 0xbf, 0x75, 0xbf, 0x6d, 0xa5, 0x5b, 0x3a, - 0x79, 0xe1, 0x7f, 0x7b, 0xef, 0x9c, 0xfb, 0x96, 0x8b, 0xcf, 0x24, 0x33, 0x5e, 0x7d, 0x12, 0xeb, 0x74, 0xac, 0x20, - 0xbd, 0x72, 0x91, 0x49, 0xaf, 0xb7, 0xc6, 0xf1, 0x8b, 0xc4, 0xda, 0xee, 0xc4, 0x9a, 0x7d, 0x50, 0x35, 0x79, 0x8c, - 0xc1, 0xa3, 0xad, 0x2c, 0xa6, 0x3f, 0x58, 0xe7, 0xd1, 0xff, 0x36, 0xb2, 0x39, 0x6e, 0x5c, 0x8e, 0x36, 0x7f, 0xb1, - 0x44, 0x3c, 0x5b, 0xed, 0x57, 0xde, 0xa7, 0xb5, 0x25, 0x8b, 0xbf, 0x49, 0x4b, 0xd2, 0x5a, 0x8c, 0xef, 0xe5, 0x83, - 0x25, 0x7d, 0x8a, 0x3d, 0x07, 0x11, 0x1a, 0xb1, 0xe6, 0x82, 0x1a, 0xb9, 0x4e, 0x57, 0x02, 0xb1, 0x0b, 0x3f, 0x1f, - 0x7a, 0x8a, 0x0b, 0xa4, 0x3a, 0xc8, 0xcb, 0x40, 0x35, 0x51, 0x40, 0x3f, 0x50, 0x53, 0x82, 0x9c, 0x67, 0x7b, 0xc7, - 0xb7, 0x87, 0xaf, 0xf1, 0xf6, 0xcc, 0xd2, 0x46, 0x64, 0x7e, 0x8b, 0x07, 0x47, 0x58, 0x9a, 0xdb, 0x09, 0x93, 0x45, - 0xd8, 0x42, 0xd1, 0xf2, 0x0e, 0xd9, 0x63, 0xf3, 0x4b, 0x03, 0xd5, 0x85, 0x1c, 0xb1, 0x9e, 0xff, 0x5a, 0xef, 0xd2, - 0x15, 0xbc, 0x4b, 0xfb, 0xa2, 0x97, 0x66, 0x3d, 0x04, 0x40, 0x77, 0xea, 0xcf, 0x40, 0x95, 0xb9, 0xa1, 0x28, 0x7d, - 0x7e, 0x9d, 0xb5, 0xa7, 0xda, 0x55, 0xe0, 0xde, 0x69, 0x78, 0x76, 0x42, 0x56, 0x2e, 0x11, 0xfd, 0x18, 0xec, 0x73, - 0x02, 0xfd, 0x41, 0x33, 0xb4, 0xaf, 0x3b, 0x3a, 0x71, 0x09, 0x28, 0x13, 0x75, 0xb8, 0x24, 0x46, 0x30, 0x7e, 0x90, - 0x83, 0x0d, 0xbc, 0x5a, 0xdf, 0xa5, 0x24, 0xae, 0xba, 0x73, 0x08, 0xd1, 0x6b, 0xde, 0xff, 0xea, 0xd7, 0x60, 0xbf, - 0xde, 0xe8, 0x26, 0x23, 0xf2, 0xf7, 0xfc, 0x9c, 0x4b, 0x34, 0x63, 0x88, 0x10, 0x55, 0x2c, 0x5a, 0xf3, 0x1c, 0x0b, - 0x58, 0x9e, 0x97, 0xe0, 0xbb, 0x7c, 0xde, 0x75, 0x62, 0xab, 0x89, 0xa5, 0x6a, 0x30, 0x62, 0x17, 0x0e, 0xde, 0x07, - 0x29, 0x30, 0x70, 0x59, 0x76, 0xd2, 0x7d, 0x47, 0x32, 0x1b, 0x1f, 0x34, 0x07, 0x04, 0x37, 0x3d, 0xc8, 0x02, 0x7f, - 0x23, 0x8c, 0xa1, 0x85, 0x07, 0xeb, 0xa1, 0xd9, 0xa6, 0xbc, 0x06, 0x17, 0xdc, 0x74, 0xa5, 0x22, 0xd5, 0x97, 0xb6, - 0x5a, 0x06, 0x0a, 0x4b, 0xb3, 0x60, 0xe0, 0x5b, 0x5a, 0x2c, 0x8b, 0x10, 0x83, 0x3c, 0x5c, 0xe7, 0x24, 0x84, 0xf2, - 0x04, 0xa1, 0x0e, 0x05, 0x66, 0x3c, 0x38, 0x9d, 0x22, 0x70, 0x30, 0xaf, 0x39, 0xaf, 0x3b, 0xbf, 0x67, 0xc2, 0x32, - 0x4b, 0x8f, 0x7b, 0x0d, 0x97, 0x4b, 0x13, 0x39, 0xd0, 0xbd, 0xd9, 0xfb, 0xdb, 0x2d, 0xf2, 0xbe, 0x11, 0x5a, 0xb1, - 0x0d, 0x17, 0x15, 0x17, 0x59, 0xb4, 0xba, 0xc4, 0xb8, 0x93, 0xae, 0x57, 0xee, 0x85, 0xdd, 0x7a, 0xea, 0x9e, 0xac, - 0x37, 0x4c, 0xe1, 0xd3, 0xb0, 0x8c, 0x25, 0xc4, 0x1a, 0x4b, 0x47, 0xff, 0xbb, 0x2c, 0x7c, 0x96, 0xb5, 0x07, 0x0c, - 0x85, 0xb8, 0x3f, 0xd3, 0xe3, 0x27, 0x00, 0x0e, 0xc7, 0x13, 0x1f, 0x27, 0xe0, 0x40, 0x6b, 0x49, 0xa1, 0x5b, 0x33, - 0x01, 0x11, 0x6b, 0x4b, 0xfe, 0x4b, 0x5f, 0x89, 0x52, 0xf4, 0xd9, 0xb1, 0xeb, 0xdc, 0xe4, 0xfd, 0xdb, 0xea, 0x58, - 0x35, 0x2d, 0x21, 0xef, 0xba, 0x05, 0xea, 0x61, 0xf9, 0xfb, 0xae, 0x58, 0xd1, 0x11, 0x08, 0x3c, 0x7f, 0x63, 0x5a, - 0xac, 0x4f, 0x06, 0x48, 0xd7, 0x83, 0x4f, 0x58, 0x24, 0x9e, 0x82, 0x63, 0x20, 0x8e, 0xab, 0xe1, 0x23, 0xf3, 0xc3, - 0xff, 0x2c, 0x27, 0x56, 0xa6, 0x9d, 0xc9, 0xa9, 0x63, 0xaa, 0x23, 0x83, 0x00, 0xfa, 0x22, 0xf7, 0xb8, 0xee, 0xbf, - 0x3a, 0xb5, 0x54, 0x31, 0x6c, 0xb6, 0x37, 0x71, 0x6b, 0xee, 0xc4, 0x7a, 0xa5, 0xcb, 0xe0, 0xd3, 0xca, 0xfd, 0xe2, - 0xf4, 0x43, 0x26, 0xcc, 0xe0, 0x6c, 0xf1, 0xe5, 0x83, 0x4d, 0x0f, 0x19, 0x0d, 0x80, 0x09, 0x4b, 0xe9, 0x27, 0x83, - 0x94, 0x3e, 0x3f, 0x31, 0x12, 0xda, 0x36, 0xf8, 0x67, 0x6e, 0x2e, 0x47, 0x39, 0xd0, 0x7f, 0x18, 0xec, 0x62, 0xa3, - 0xb7, 0x49, 0x18, 0x3f, 0x40, 0x9a, 0xbd, 0xd1, 0x8f, 0x7a, 0xcd, 0xa1, 0x25, 0x16, 0xe5, 0xd5, 0x93, 0xfc, 0x98, - 0x65, 0x46, 0x01, 0xf8, 0x90, 0xf7, 0x1e, 0xfa, 0xe7, 0x98, 0x62, 0xce, 0xe1, 0xeb, 0xf8, 0xd7, 0x0e, 0x62, 0x6d, - 0xed, 0x74, 0xcd, 0xff, 0xce, 0x5c, 0x78, 0x6a, 0x73, 0xc2, 0x8c, 0xb6, 0x5f, 0xbd, 0xba, 0xda, 0x74, 0x18, 0x01, - 0x34, 0xbe, 0xc2, 0xe8, 0xb1, 0x09, 0xdd, 0x06, 0x66, 0x24, 0xe0, 0x9e, 0x67, 0xd2, 0x95, 0x8e, 0x3f, 0x16, 0xf0, - 0x66, 0xe6, 0x77, 0xa0, 0x09, 0x77, 0x57, 0xd2, 0x68, 0x4b, 0x92, 0x1c, 0xf9, 0x6d, 0xc1, 0x44, 0xb1, 0x75, 0xeb, - 0x26, 0xbc, 0x16, 0xf8, 0xff, 0xf8, 0x41, 0x00, 0xf2, 0x6e, 0x51, 0xb3, 0xa4, 0x76, 0x9a, 0xe6, 0x2b, 0x4d, 0x29, - 0xbb, 0xb0, 0x72, 0x93, 0x5d, 0xce, 0xfc, 0xff, 0x30, 0x82, 0x9b, 0x1c, 0x3e, 0x89, 0x1e, 0xda, 0x57, 0x80, 0xa4, - 0x07, 0x44, 0x17, 0x0f, 0x5a, 0x38, 0x7e, 0x23, 0xca, 0x1c, 0x2c, 0x6c, 0x0b, 0x96, 0x05, 0x83, 0x28, 0x7b, 0x04, - 0xf3, 0x0b, 0x1d, 0x98, 0xfc, 0x4d, 0xef, 0x28, 0xe7, 0x10, 0xe9, 0xd5, 0x77, 0x25, 0xa7, 0xae, 0x9d, 0x5e, 0xfa, - 0xbf, 0x69, 0x02, 0x4c, 0xe6, 0xb6, 0xbe, 0x4e, 0x2d, 0x5f, 0xf8, 0x3c, 0x6b, 0x2f, 0x8a, 0x71, 0xfc, 0xed, 0x8a, - 0x8e, 0x77, 0xc6, 0xac, 0x77, 0x14, 0x35, 0xad, 0xae, 0x7d, 0x75, 0xd3, 0x82, 0x6e, 0x9c, 0x10, 0x3c, 0xc6, 0x87, - 0x58, 0x7e, 0xde, 0x7c, 0x93, 0x50, 0xc7, 0xdf, 0xc6, 0x1e, 0x6f, 0x9b, 0x29, 0x3c, 0xb1, 0x03, 0x7e, 0x47, 0xf7, - 0x96, 0x8e, 0x57, 0x57, 0x4c, 0x7c, 0x08, 0x4e, 0x45, 0x80, 0xd7, 0x93, 0x24, 0xbe, 0x29, 0x89, 0x83, 0x0d, 0xa7, - 0xd6, 0xb6, 0xc2, 0x7d, 0x59, 0xbb, 0x43, 0x16, 0x4e, 0xe3, 0x9b, 0xa8, 0x1b, 0x1e, 0x71, 0xc6, 0x49, 0xdc, 0xea, - 0xa9, 0xef, 0xb6, 0x41, 0x8c, 0xc0, 0xe1, 0x0a, 0x30, 0x3e, 0x11, 0x3e, 0xc4, 0x6c, 0x6a, 0x00, 0xa7, 0x22, 0xb0, - 0xea, 0x87, 0x03, 0x4c, 0xd9, 0xfd, 0x94, 0x0f, 0xe9, 0x88, 0xc0, 0xcc, 0xf4, 0x10, 0xe5, 0xfd, 0xe7, 0xf0, 0x48, - 0xde, 0x9f, 0x4f, 0x86, 0xe1, 0x50, 0xc8, 0xb5, 0xd9, 0xb0, 0x07, 0x56, 0xbe, 0xe0, 0x06, 0xe7, 0x6b, 0xb6, 0xed, - 0xda, 0x84, 0xdc, 0xfc, 0x23, 0x9e, 0x61, 0x97, 0x98, 0xde, 0xdc, 0x3b, 0x5d, 0x47, 0x3d, 0xdf, 0x2b, 0x17, 0x52, - 0xc3, 0x3e, 0xd1, 0xe2, 0xd1, 0xf3, 0x6c, 0xa4, 0x75, 0xc7, 0xc9, 0x5b, 0xfd, 0x4b, 0x72, 0x24, 0x04, 0xc5, 0x4f, - 0xb2, 0xf6, 0x3e, 0x91, 0x6d, 0xdf, 0x05, 0xcf, 0xad, 0xf6, 0x3a, 0x42, 0x77, 0xfa, 0xd3, 0x23, 0x6c, 0x4a, 0xe7, - 0xe7, 0x0e, 0xa0, 0x3a, 0x92, 0xf3, 0xd9, 0xe5, 0x1e, 0x06, 0xe5, 0x70, 0xc5, 0x33, 0x70, 0xb7, 0x62, 0xe6, 0x21, - 0xd2, 0x35, 0x5a, 0x7f, 0xf7, 0x82, 0x37, 0x5c, 0x33, 0x59, 0x1b, 0x91, 0xdc, 0x16, 0xf2, 0x30, 0xc7, 0x08, 0x65, - 0xbe, 0xa0, 0xfc, 0x70, 0xd1, 0x66, 0x72, 0x96, 0x84, 0x2f, 0x24, 0x0a, 0xfc, 0x49, 0x95, 0x67, 0xae, 0x1c, 0x2f, - 0x57, 0x6c, 0x60, 0x2e, 0xe8, 0x8b, 0x51, 0x40, 0x22, 0x73, 0xb7, 0xfc, 0x32, 0xcf, 0x90, 0xfc, 0x35, 0x72, 0x6d, - 0x07, 0x58, 0xbe, 0xce, 0x53, 0x06, 0x37, 0x2e, 0x5a, 0x0b, 0x1d, 0x5f, 0x4a, 0x26, 0x41, 0x91, 0x42, 0xa8, 0xb4, - 0x48, 0x68, 0xd4, 0x2a, 0x15, 0x30, 0x6e, 0xa1, 0xa1, 0xdf, 0x6b, 0xd5, 0xe7, 0x4f, 0xd8, 0xf9, 0x63, 0x94, 0xff, - 0x51, 0x5c, 0x04, 0xc8, 0x91, 0xb7, 0xa8, 0x1b, 0xf0, 0x4c, 0x91, 0xd4, 0x66, 0x8e, 0x4b, 0x24, 0x1c, 0x83, 0x64, - 0x61, 0xb7, 0x61, 0xef, 0x7f, 0xc7, 0xd7, 0x54, 0x90, 0x30, 0x88, 0xf0, 0xeb, 0x2c, 0x83, 0x6e, 0xe0, 0x22, 0x98, - 0x6a, 0x84, 0x07, 0x1c, 0x45, 0xdd, 0x35, 0xab, 0x80, 0x13, 0x28, 0x41, 0xc9, 0x22, 0x89, 0x1f, 0x77, 0xa0, 0xff, - 0x5f, 0x8a, 0x51, 0x7d, 0xd6, 0xd7, 0xb7, 0x15, 0xd4, 0x43, 0x87, 0x02, 0x15, 0x19, 0x37, 0xc0, 0x66, 0x8f, 0x8f, - 0x45, 0x0e, 0xd8, 0x30, 0xf9, 0xaf, 0xb0, 0xb0, 0x52, 0xd9, 0x72, 0x3a, 0xfc, 0xcb, 0x35, 0x8b, 0x83, 0x3d, 0x3c, - 0x4c, 0xe3, 0x30, 0x3e, 0xa5, 0x25, 0x7d, 0x5e, 0xe8, 0xa4, 0x51, 0xd1, 0xf9, 0x71, 0x9e, 0xf5, 0x7d, 0x57, 0xf2, - 0xf8, 0x35, 0x5e, 0x9f, 0xd9, 0x53, 0x74, 0x9d, 0x1f, 0x7e, 0xf4, 0xa3, 0xb1, 0x65, 0xfc, 0x37, 0x7a, 0x61, 0x4f, - 0x17, 0x94, 0x96, 0x81, 0xf7, 0xe9, 0xd1, 0x62, 0x25, 0xfb, 0x82, 0x1c, 0x7d, 0x8c, 0x8e, 0xf6, 0x78, 0x4e, 0xf9, - 0x79, 0x16, 0xe7, 0xfd, 0xed, 0x6b, 0xbc, 0x38, 0xf3, 0xac, 0x5c, 0xeb, 0xcd, 0xa7, 0xde, 0x06, 0xec, 0x2d, 0x70, - 0x3f, 0x89, 0xdd, 0x40, 0x84, 0x93, 0x60, 0x0c, 0xd3, 0xbd, 0x69, 0x44, 0x03, 0xec, 0x77, 0xed, 0xf9, 0xc0, 0x03, - 0xfd, 0xcf, 0xe6, 0xf5, 0xe0, 0xdc, 0x6e, 0x54, 0x53, 0x0a, 0x70, 0xc1, 0x64, 0x45, 0x31, 0x46, 0x82, 0x48, 0x23, - 0xbd, 0x1d, 0x1d, 0xb9, 0xa8, 0x2b, 0x9c, 0x26, 0xba, 0xe4, 0x69, 0xe2, 0x26, 0x65, 0x6b, 0x99, 0x00, 0x50, 0x96, - 0x64, 0xec, 0xd0, 0xf3, 0x7a, 0x80, 0xf4, 0x0e, 0x72, 0x42, 0x2c, 0xc7, 0x25, 0x90, 0x2d, 0x19, 0x7c, 0xfb, 0x0f, - 0xab, 0x40, 0x5e, 0x6f, 0xe8, 0xb0, 0x09, 0x69, 0xf6, 0x38, 0x3d, 0x7d, 0x71, 0x00, 0xae, 0x44, 0xa6, 0x67, 0x9a, - 0x06, 0x17, 0x7d, 0x8e, 0x3e, 0x34, 0xc2, 0x5a, 0x60, 0x2a, 0xea, 0xb4, 0xe5, 0xad, 0x52, 0x71, 0xf3, 0xe0, 0x78, - 0x0a, 0x07, 0x43, 0x33, 0x30, 0x22, 0x7f, 0xfa, 0x0f, 0x1b, 0xc6, 0x72, 0x24, 0xad, 0x6c, 0x98, 0xbf, 0xec, 0x72, - 0x2b, 0x37, 0x4b, 0x12, 0x9a, 0x86, 0x5e, 0x3d, 0x88, 0x15, 0xde, 0xa9, 0xff, 0xe7, 0x41, 0x69, 0x83, 0x38, 0x87, - 0x64, 0x01, 0x51, 0x3c, 0x47, 0x38, 0xc5, 0xa0, 0xc5, 0x6c, 0x90, 0xc3, 0x94, 0x81, 0xc0, 0x2b, 0xab, 0x37, 0x81, - 0x1b, 0x71, 0xb9, 0xec, 0xe9, 0xd4, 0x6b, 0xae, 0x9d, 0xd4, 0x26, 0xb2, 0x08, 0x57, 0xf8, 0xcd, 0x07, 0x80, 0xae, - 0x36, 0xd4, 0x51, 0x08, 0xe4, 0x08, 0x9b, 0xe7, 0x8a, 0x14, 0xdd, 0x78, 0x7c, 0x1b, 0xf6, 0x2d, 0x47, 0x88, 0xcd, - 0x8f, 0xb9, 0x6b, 0x8d, 0x06, 0x8d, 0x4c, 0x32, 0x6c, 0x5c, 0x0a, 0x76, 0x92, 0xa0, 0x87, 0x1a, 0xc7, 0x38, 0x94, - 0x15, 0x7a, 0x1e, 0x19, 0xe3, 0x88, 0xaf, 0x7c, 0xc9, 0x9a, 0x93, 0x68, 0x91, 0x8a, 0x81, 0xfd, 0x1c, 0xbe, 0xce, - 0x0b, 0x41, 0x2e, 0x8e, 0xb8, 0xe9, 0xa9, 0x21, 0xa7, 0x3e, 0x19, 0x14, 0xa8, 0x88, 0x5b, 0xaf, 0x2d, 0x68, 0x98, - 0x47, 0x01, 0x71, 0x6e, 0x16, 0x38, 0xc2, 0x29, 0x2c, 0x6a, 0xff, 0xe0, 0xe8, 0xbc, 0x75, 0xb4, 0x40, 0x90, 0xda, - 0x09, 0x67, 0x38, 0x99, 0xd1, 0x11, 0x32, 0xc3, 0xe5, 0xf1, 0x71, 0x53, 0xd3, 0x5a, 0x53, 0xa7, 0x95, 0x22, 0xc9, - 0x0c, 0x69, 0x26, 0xb0, 0xc4, 0x0f, 0xdb, 0xde, 0x5c, 0xa4, 0x62, 0x45, 0xe0, 0x2d, 0x66, 0xfc, 0x5c, 0xd8, 0x81, - 0xe2, 0xd5, 0x84, 0x0e, 0x6c, 0xaa, 0xfc, 0xdc, 0xe6, 0xa6, 0x27, 0xfc, 0xc2, 0x61, 0xfa, 0x75, 0x26, 0xfa, 0x59, - 0x98, 0xa3, 0xd5, 0x41, 0x2f, 0x5c, 0x21, 0xe3, 0xc4, 0x33, 0x64, 0xd9, 0x94, 0x43, 0xf7, 0x1a, 0x25, 0x8a, 0xa4, - 0x01, 0x39, 0xda, 0x43, 0x4e, 0x2e, 0xf3, 0xa4, 0xd5, 0x34, 0x2a, 0xbb, 0x24, 0xe1, 0x2d, 0x7e, 0xe4, 0x31, 0xa1, - 0x44, 0xf9, 0x3c, 0xcd, 0x33, 0x92, 0xac, 0x71, 0xb7, 0xa3, 0xe0, 0x1a, 0xbd, 0xb5, 0xba, 0xac, 0xd5, 0xb0, 0x9f, - 0xc8, 0xbf, 0x52, 0x47, 0x6f, 0x52, 0x3c, 0x18, 0x04, 0x19, 0x86, 0xab, 0x96, 0xdd, 0x43, 0x8b, 0x1e, 0xfb, 0xa2, - 0xfa, 0x77, 0x83, 0x60, 0xe2, 0x49, 0x21, 0x84, 0x96, 0x91, 0x03, 0xfd, 0x37, 0x55, 0xaa, 0x25, 0x12, 0xde, 0x3b, - 0x9f, 0xb3, 0x77, 0x13, 0xa4, 0x04, 0xb3, 0x4d, 0x95, 0x7b, 0x20, 0x5c, 0x87, 0x80, 0xd7, 0x0d, 0x77, 0xa8, 0x77, - 0x91, 0x5b, 0x11, 0x74, 0x29, 0x05, 0x88, 0x88, 0x00, 0x8c, 0x5e, 0x0c, 0x34, 0x1c, 0xa6, 0x19, 0xac, 0x44, 0x82, - 0x7f, 0x95, 0x85, 0x21, 0xb5, 0xec, 0x28, 0x07, 0xc0, 0x66, 0xb3, 0x11, 0x8c, 0xbe, 0x60, 0x05, 0x7c, 0x36, 0x89, - 0xff, 0xc6, 0xa9, 0x6a, 0xa6, 0x75, 0x23, 0xe5, 0xdd, 0xb8, 0xb1, 0x76, 0x81, 0x18, 0xa6, 0xa5, 0x75, 0x3b, 0x21, - 0x09, 0x28, 0x0d, 0x0b, 0x9f, 0x3c, 0xbf, 0x3d, 0x46, 0xd7, 0xdf, 0x1f, 0x3e, 0x30, 0x49, 0x14, 0x19, 0x55, 0x32, - 0x30, 0x4d, 0x84, 0x8c, 0x6f, 0x11, 0x3a, 0x1e, 0x8e, 0xa6, 0x45, 0x7e, 0xea, 0x75, 0x6c, 0x37, 0x50, 0x8f, 0x2f, - 0xbf, 0xb6, 0xdc, 0x39, 0xd1, 0xda, 0xe9, 0xb8, 0x3f, 0x04, 0x9a, 0x9c, 0x88, 0xaa, 0xb2, 0x18, 0x25, 0xfb, 0x87, - 0x81, 0x6d, 0x24, 0x39, 0xf5, 0x54, 0x18, 0x77, 0x6f, 0x73, 0x4f, 0x87, 0x89, 0x8b, 0x23, 0xff, 0xcb, 0x1f, 0xc1, - 0xb5, 0x52, 0xbc, 0xf2, 0x1d, 0xd8, 0x72, 0x09, 0x57, 0x0e, 0x56, 0x0d, 0x02, 0xa2, 0x94, 0x00, 0x72, 0x1d, 0x1f, - 0x1d, 0xe3, 0x24, 0x79, 0xd7, 0x33, 0xd6, 0xd4, 0x6c, 0x49, 0x69, 0xe6, 0x63, 0x5f, 0x53, 0x69, 0x1e, 0xe7, 0x9a, - 0x60, 0x96, 0x64, 0xd9, 0x49, 0x56, 0x80, 0xd7, 0x74, 0x0d, 0xf3, 0x55, 0x85, 0x40, 0x30, 0xdf, 0x55, 0x99, 0x8b, - 0x53, 0x85, 0xb8, 0x1d, 0x09, 0x6d, 0xaa, 0x45, 0x78, 0xe1, 0xc0, 0x38, 0x9c, 0x5f, 0x33, 0x2d, 0x06, 0x06, 0x20, - 0x57, 0x52, 0x6f, 0x84, 0xf3, 0xf4, 0x20, 0x6f, 0x43, 0xf1, 0xa4, 0xc0, 0x56, 0xac, 0x78, 0xf0, 0xad, 0x97, 0x46, - 0xb3, 0xca, 0x68, 0x97, 0x5b, 0x71, 0xa6, 0xf3, 0xa4, 0xcf, 0x4e, 0x9b, 0xd2, 0xad, 0x87, 0x80, 0x0a, 0xe5, 0xf9, - 0x19, 0xcf, 0xc7, 0x2b, 0xc4, 0x39, 0xe6, 0xac, 0x09, 0xd5, 0x73, 0x61, 0xfd, 0x3a, 0x3d, 0x64, 0xff, 0x7a, 0xbc, - 0xb5, 0xce, 0x54, 0xdc, 0x3c, 0x53, 0xc8, 0x54, 0xfc, 0x15, 0xf7, 0x5e, 0x3c, 0x30, 0x5c, 0x93, 0xc7, 0x90, 0x67, - 0x2a, 0x27, 0x7c, 0x69, 0xa0, 0xe9, 0x20, 0xaa, 0xd3, 0xad, 0x10, 0x57, 0x5d, 0x18, 0xa2, 0x70, 0xf7, 0x29, 0x2f, - 0x48, 0xeb, 0xb0, 0xf7, 0x54, 0xa3, 0xc3, 0xa0, 0xa6, 0x40, 0x9d, 0x16, 0x83, 0x95, 0xb4, 0x5c, 0x50, 0x0e, 0x05, - 0x33, 0xd5, 0x06, 0x1e, 0xd8, 0x9a, 0xff, 0x7f, 0x40, 0x21, 0x7a, 0xdc, 0xf6, 0xaf, 0xfc, 0x05, 0x73, 0xc2, 0x8c, - 0x25, 0x33, 0x3c, 0xbc, 0xda, 0x19, 0x7f, 0x0a, 0xba, 0xb1, 0x6a, 0xa3, 0x8c, 0x55, 0x39, 0x51, 0x06, 0xf7, 0x93, - 0xa5, 0x98, 0x3a, 0x85, 0x0b, 0x31, 0x95, 0x97, 0x7d, 0xa4, 0x92, 0x52, 0x1c, 0x79, 0x51, 0x01, 0xc0, 0xbc, 0x0b, - 0x34, 0x65, 0xca, 0x93, 0x20, 0x09, 0x5c, 0x54, 0x01, 0xd1, 0x8c, 0x97, 0x73, 0x7a, 0xe3, 0x2b, 0x8e, 0x7b, 0xc4, - 0x49, 0x74, 0xe6, 0x10, 0xd4, 0xf5, 0xf9, 0x29, 0x23, 0x62, 0x41, 0xd8, 0x57, 0x8c, 0x43, 0xd9, 0x4e, 0x58, 0x5f, - 0xac, 0xd7, 0x77, 0xde, 0x24, 0x8a, 0xa4, 0x2b, 0xb3, 0x7c, 0xe4, 0xfb, 0x0c, 0x99, 0xad, 0x92, 0x8d, 0x38, 0x86, - 0x32, 0xce, 0x19, 0x8f, 0x62, 0x03, 0x81, 0xb3, 0xa5, 0x2f, 0xb5, 0x90, 0xe3, 0xb2, 0x34, 0x94, 0xc7, 0xc0, 0xb9, - 0x2b, 0xdb, 0x9b, 0xd7, 0xf1, 0x31, 0xe7, 0xfd, 0xb7, 0xeb, 0x4d, 0xad, 0xa8, 0x3f, 0x63, 0xd5, 0x86, 0x7d, 0x81, - 0xa2, 0x79, 0x30, 0xeb, 0x74, 0x8e, 0xf2, 0x88, 0x27, 0x9c, 0x3c, 0x8b, 0x3a, 0xd6, 0xae, 0x8f, 0x92, 0x17, 0x67, - 0xaf, 0xa3, 0xe2, 0x34, 0x88, 0x7e, 0x59, 0xcd, 0x52, 0x07, 0xd7, 0x77, 0xc8, 0x5e, 0xe6, 0x72, 0xed, 0x44, 0xa9, - 0x86, 0x06, 0xce, 0x9f, 0xe4, 0xab, 0xd8, 0x3e, 0xe1, 0x2c, 0x67, 0xa2, 0xca, 0x7e, 0x9d, 0x07, 0xa9, 0x30, 0xe7, - 0xf8, 0xe3, 0xd2, 0x86, 0xe8, 0x2b, 0x22, 0x24, 0xe6, 0xac, 0xfb, 0xce, 0xa6, 0x2c, 0x71, 0xe9, 0xc3, 0x08, 0xa1, - 0x9f, 0x18, 0xa1, 0x19, 0x47, 0x3d, 0x6f, 0xfe, 0xb7, 0x91, 0xef, 0xb3, 0x9e, 0x53, 0x74, 0xc7, 0x7b, 0xb2, 0x1a, - 0x2a, 0xdb, 0xe9, 0x67, 0xee, 0xd4, 0x9e, 0x82, 0x53, 0x7b, 0x82, 0x4a, 0x90, 0xc0, 0xcf, 0x0b, 0xcf, 0xf1, 0xa4, - 0xd9, 0x54, 0x17, 0x4f, 0xdb, 0x5f, 0x8d, 0xcf, 0x2f, 0x95, 0x8d, 0xaf, 0x38, 0xbb, 0x52, 0x68, 0x67, 0x78, 0x4b, - 0x67, 0xae, 0x0c}; +const uint8_t INDEX_BR[] PROGMEM = { + 0x1b, 0xe2, 0x97, 0xa3, 0x90, 0xa2, 0x95, 0x55, 0x51, 0x04, 0x1b, 0x07, 0x80, 0x20, 0x79, 0x0e, 0x50, 0xab, 0x02, + 0xdb, 0x98, 0x16, 0xf4, 0x7b, 0x22, 0xa3, 0x4d, 0xd3, 0x86, 0xc1, 0x26, 0x48, 0x49, 0x60, 0xbe, 0xb3, 0xc9, 0xa1, + 0x8c, 0x96, 0x10, 0x1b, 0x21, 0xcf, 0x48, 0x68, 0xce, 0x10, 0x34, 0x32, 0x7c, 0xbf, 0x71, 0x7b, 0x03, 0x8f, 0xdd, + 0x37, 0x06, 0x9a, 0x30, 0x50, 0xe4, 0x08, 0x47, 0x68, 0xec, 0x93, 0xdc, 0x7d, 0x53, 0xf5, 0x4f, 0xd7, 0x8a, 0xcf, + 0x2f, 0x85, 0x3a, 0x6c, 0xa9, 0x63, 0xcb, 0xf5, 0xc8, 0x18, 0xe3, 0xf5, 0xdb, 0x0c, 0x05, 0x9b, 0x48, 0x2c, 0x42, + 0x21, 0xa0, 0x2c, 0x25, 0xf7, 0xcb, 0xb7, 0xaa, 0x65, 0xd5, 0x7f, 0x3e, 0x2f, 0x94, 0x2b, 0x53, 0xa7, 0x0f, 0x4e, + 0x56, 0xa9, 0xf7, 0xce, 0x54, 0x88, 0x39, 0xef, 0xea, 0x3d, 0x69, 0x56, 0xd0, 0x52, 0x96, 0x0a, 0x5b, 0x35, 0xd4, + 0x42, 0xd6, 0x35, 0x10, 0xf3, 0x7f, 0xec, 0x95, 0xd3, 0x2a, 0xfe, 0x4d, 0x22, 0x6a, 0xd6, 0x69, 0x6e, 0x7b, 0x5a, + 0xdd, 0x33, 0x58, 0x21, 0xa4, 0x33, 0xd6, 0x61, 0x05, 0xf5, 0x08, 0xa9, 0x10, 0x32, 0xf5, 0xdc, 0x04, 0x59, 0x72, + 0x41, 0xf4, 0x09, 0xfa, 0x08, 0x08, 0x9b, 0xcc, 0xf3, 0x2d, 0x71, 0xb4, 0x1c, 0xe3, 0x04, 0x64, 0x9a, 0x96, 0x5b, + 0x16, 0x58, 0xed, 0xbf, 0x37, 0xd5, 0x2a, 0x6d, 0x80, 0x66, 0xcf, 0xba, 0xd4, 0xb8, 0xd4, 0x38, 0x65, 0x10, 0x57, + 0x3a, 0xe7, 0x93, 0xe0, 0x82, 0x90, 0x78, 0xef, 0xfd, 0xff, 0x96, 0xed, 0x30, 0x44, 0x77, 0x13, 0x3b, 0x70, 0x92, + 0xe8, 0xb0, 0xf4, 0x25, 0x5a, 0xc9, 0xff, 0xff, 0xbb, 0x01, 0x76, 0x03, 0x94, 0x16, 0x20, 0xa5, 0x2d, 0x8a, 0xe2, + 0x56, 0x51, 0xd4, 0xdc, 0x18, 0xcb, 0x99, 0xb3, 0x4e, 0x3b, 0x55, 0x67, 0x5d, 0x64, 0xa3, 0xc4, 0xf8, 0xec, 0x2a, + 0xb7, 0x51, 0x68, 0x6c, 0x7a, 0xd9, 0x85, 0x97, 0x9e, 0xcb, 0x61, 0x26, 0xbe, 0xeb, 0x3a, 0x6b, 0xe5, 0x38, 0xd8, + 0x63, 0xa8, 0xb5, 0xba, 0xbe, 0xbd, 0x1d, 0xe3, 0xc4, 0x11, 0xa3, 0x08, 0xc4, 0xfe, 0x26, 0x3a, 0xfb, 0x01, 0x5d, + 0xb4, 0xfc, 0x1d, 0x78, 0xca, 0xb2, 0xac, 0x61, 0x39, 0x21, 0xe5, 0x6b, 0x5a, 0x70, 0x76, 0x57, 0x91, 0x4c, 0x8c, + 0x3d, 0x0e, 0x50, 0x4e, 0x41, 0x1c, 0xda, 0x62, 0xd2, 0xf1, 0x25, 0xce, 0x03, 0xf4, 0xfa, 0x3b, 0xc1, 0xc4, 0xed, + 0xc1, 0xdf, 0x8f, 0xe1, 0xc0, 0x0e, 0x34, 0x72, 0x3c, 0xb3, 0x3f, 0xfa, 0xc0, 0xe6, 0xcd, 0xf4, 0x01, 0x19, 0xf4, + 0x28, 0x5b, 0xde, 0x02, 0x6e, 0xa2, 0x24, 0x59, 0x76, 0x94, 0x8d, 0x00, 0x35, 0xab, 0xbe, 0xd9, 0xc0, 0xfb, 0xfa, + 0x97, 0x4f, 0x8f, 0x6e, 0xa4, 0x28, 0x0a, 0xfd, 0x43, 0xd9, 0xf2, 0xb2, 0xc2, 0x75, 0x49, 0x97, 0x8c, 0xcd, 0x61, + 0xb3, 0x64, 0x52, 0x1e, 0x46, 0x1e, 0xa2, 0xe0, 0xb5, 0x26, 0xd3, 0xf5, 0x3c, 0x9e, 0x19, 0x32, 0x45, 0xb9, 0x28, + 0xf5, 0x40, 0xcf, 0xa5, 0xf1, 0xcd, 0x8d, 0x29, 0x55, 0xe3, 0x2c, 0x43, 0x12, 0xa2, 0x4d, 0x37, 0xda, 0x94, 0x3e, + 0x49, 0x88, 0x4f, 0x2c, 0xa5, 0x67, 0xbe, 0xb7, 0x75, 0x28, 0xb8, 0x2f, 0x0d, 0x75, 0xce, 0x87, 0x3f, 0xe3, 0x30, + 0x5a, 0x25, 0x92, 0x30, 0xd3, 0x2d, 0x45, 0xca, 0xe5, 0x49, 0xc7, 0x4d, 0x13, 0x95, 0xa5, 0x9f, 0x7f, 0x2d, 0x49, + 0x46, 0x5a, 0x49, 0x11, 0x12, 0xd2, 0xdd, 0x38, 0x3c, 0x31, 0x63, 0x5e, 0xb6, 0xe6, 0xde, 0xcd, 0xcd, 0x6d, 0x67, + 0x46, 0x53, 0x16, 0x86, 0xd4, 0xad, 0x07, 0xac, 0xdb, 0xd7, 0x9f, 0x48, 0xcc, 0xa6, 0x4d, 0x9f, 0x6c, 0x8b, 0xf2, + 0xcb, 0xcd, 0x1b, 0x1e, 0xa9, 0x39, 0x37, 0x4d, 0xcd, 0x80, 0x9b, 0x19, 0x67, 0x64, 0x70, 0xb0, 0x38, 0x00, 0x9f, + 0xab, 0x26, 0xca, 0xb7, 0xbb, 0x55, 0x50, 0xcf, 0x31, 0x65, 0x12, 0xb6, 0x2b, 0x36, 0x9d, 0x17, 0x2b, 0x50, 0xd1, + 0x13, 0x72, 0x80, 0x7f, 0x88, 0x62, 0xe4, 0xee, 0x40, 0xb7, 0x56, 0xd2, 0x66, 0xa3, 0xb0, 0x0e, 0x31, 0xeb, 0x9a, + 0x27, 0xc1, 0xd5, 0x7b, 0x63, 0xb3, 0x84, 0x1b, 0xc8, 0xbf, 0x35, 0x29, 0x8a, 0x3c, 0xd0, 0x66, 0x03, 0x2a, 0x3e, + 0xb9, 0x79, 0x4c, 0x16, 0x01, 0xaa, 0xe8, 0x0e, 0x01, 0x1c, 0x73, 0x05, 0x78, 0x3a, 0x9c, 0x23, 0xb8, 0x18, 0x78, + 0xc5, 0xcd, 0x53, 0x7f, 0xb4, 0x61, 0xb8, 0x11, 0xa4, 0xcd, 0xc6, 0x27, 0x27, 0xb6, 0xae, 0x51, 0x01, 0x1d, 0xec, + 0xe4, 0x6b, 0x99, 0xe4, 0xdb, 0x2d, 0xbb, 0x66, 0x38, 0x54, 0xf5, 0xf2, 0xba, 0xc3, 0x24, 0x41, 0xfa, 0xae, 0x46, + 0x43, 0xdd, 0xfd, 0x9d, 0x0d, 0x52, 0x98, 0x1c, 0x7f, 0xab, 0x29, 0x83, 0x0f, 0xb9, 0x11, 0xe0, 0xd3, 0x49, 0x86, + 0xef, 0xbb, 0xdf, 0x0a, 0x04, 0x76, 0x11, 0x07, 0x48, 0x7f, 0x86, 0x4c, 0x3a, 0x84, 0xf5, 0xb6, 0x32, 0x54, 0x59, + 0xed, 0xd5, 0xf1, 0xf0, 0xf8, 0x39, 0x2d, 0x10, 0x85, 0x11, 0xd2, 0xef, 0x72, 0xcb, 0xd2, 0x8f, 0xf2, 0x2e, 0x7c, + 0x9b, 0x28, 0xa6, 0x07, 0x7f, 0x7a, 0x7c, 0x43, 0x28, 0x0b, 0x3f, 0xe5, 0x98, 0x64, 0x6f, 0x63, 0xad, 0xd9, 0x90, + 0x34, 0x84, 0x30, 0xf9, 0x53, 0x6e, 0xea, 0xe3, 0x5f, 0x36, 0x39, 0xe7, 0x26, 0x49, 0xf0, 0xe9, 0xe7, 0x32, 0x50, + 0x58, 0x41, 0x1e, 0xaa, 0x98, 0x6f, 0x6b, 0xfa, 0x94, 0x4b, 0x20, 0x01, 0x84, 0x2a, 0x32, 0x84, 0x73, 0x5a, 0x39, + 0x4a, 0x57, 0xbc, 0xbd, 0x86, 0xa4, 0xb2, 0x77, 0x99, 0xe5, 0xdd, 0x44, 0x5d, 0xd5, 0xde, 0x5b, 0x94, 0x7e, 0xec, + 0x53, 0xdd, 0x67, 0xb8, 0x8d, 0xbb, 0x1d, 0x65, 0xf4, 0xe8, 0xe4, 0x73, 0x3d, 0xbc, 0xba, 0xd9, 0x30, 0xbe, 0x1f, + 0xeb, 0x0b, 0x21, 0xaf, 0x24, 0x9a, 0x44, 0xa2, 0x0a, 0xbf, 0xfe, 0xfa, 0x06, 0x14, 0x59, 0x76, 0x6d, 0x97, 0x7e, + 0xe0, 0x70, 0x8c, 0x41, 0x28, 0xac, 0x0b, 0xad, 0x4b, 0xb5, 0xbb, 0x54, 0xeb, 0x0d, 0x05, 0x24, 0xc7, 0xad, 0x04, + 0xfb, 0x9b, 0x12, 0x44, 0xec, 0x20, 0x03, 0xff, 0xba, 0x91, 0xa0, 0x50, 0xba, 0x24, 0xed, 0x9c, 0x96, 0x7e, 0xef, + 0x6f, 0x24, 0x6c, 0xd1, 0x8c, 0x55, 0xe9, 0x0f, 0x8c, 0x2f, 0x8b, 0x62, 0x44, 0x3c, 0x1b, 0x46, 0x3b, 0x49, 0x99, + 0xdc, 0xd6, 0x7a, 0x70, 0x5d, 0xe5, 0x2a, 0x62, 0x2e, 0x54, 0xab, 0x44, 0xf2, 0xf4, 0x61, 0xb2, 0xd8, 0x07, 0x8b, + 0x01, 0x3e, 0x04, 0x19, 0xe1, 0x5d, 0x8e, 0x2a, 0xff, 0x86, 0xa3, 0x59, 0xe5, 0xcc, 0x8d, 0xd3, 0x51, 0x6f, 0xc1, + 0x15, 0x9f, 0x37, 0x73, 0x3d, 0x49, 0x99, 0xca, 0x53, 0x3a, 0x96, 0x0c, 0x92, 0x2b, 0x8b, 0xde, 0x08, 0x68, 0x52, + 0x87, 0x31, 0xb2, 0x68, 0x81, 0xb1, 0xe9, 0x9f, 0x78, 0xf1, 0x22, 0xe8, 0x84, 0x48, 0xdb, 0x49, 0x4d, 0xd2, 0xea, + 0x80, 0x1f, 0xec, 0x50, 0x77, 0x66, 0xe7, 0x13, 0x36, 0x02, 0x85, 0x6f, 0xdd, 0x68, 0xe0, 0x4b, 0x6c, 0x5b, 0xbe, + 0x18, 0xca, 0xaf, 0x92, 0x97, 0xdd, 0x4e, 0x90, 0x28, 0x4e, 0x48, 0x42, 0x62, 0xc3, 0xf1, 0xf7, 0x71, 0x59, 0x2b, + 0x24, 0x2e, 0x4b, 0xf1, 0x52, 0x2d, 0x7b, 0xbf, 0x8f, 0x5d, 0x1a, 0x29, 0x6b, 0xdd, 0xed, 0x8b, 0x0d, 0xa3, 0xaf, + 0x1a, 0x94, 0x32, 0xc4, 0x54, 0x3d, 0xa1, 0xee, 0x41, 0x42, 0x00, 0xc3, 0xc2, 0x23, 0x57, 0x52, 0x9c, 0x48, 0x54, + 0x42, 0x82, 0x61, 0xb1, 0xcb, 0x1b, 0xae, 0x8f, 0xfa, 0x30, 0x6c, 0x00, 0xc4, 0x1b, 0x74, 0x7c, 0x99, 0x51, 0x60, + 0x45, 0x6d, 0x05, 0xe0, 0x44, 0x15, 0x24, 0x98, 0xb1, 0x40, 0x5f, 0xa1, 0x5e, 0x43, 0x55, 0xae, 0x10, 0xbd, 0x9d, + 0x80, 0x41, 0x6e, 0x35, 0x5d, 0xe8, 0xb2, 0x34, 0x7a, 0x1b, 0xb8, 0x29, 0xad, 0x6d, 0xd3, 0xb4, 0x4f, 0x32, 0x0e, + 0x4e, 0xd7, 0xb3, 0x98, 0x12, 0x37, 0xd4, 0x5c, 0x19, 0xbd, 0x26, 0xaa, 0xbb, 0x5b, 0x7d, 0x92, 0xd3, 0xb7, 0xd3, + 0x2e, 0xfa, 0x6e, 0xf6, 0x2b, 0xaa, 0xc4, 0x24, 0x46, 0x6d, 0x58, 0xe9, 0x7e, 0x8d, 0x27, 0x23, 0x14, 0xbc, 0x15, + 0xaf, 0x1b, 0x88, 0x7b, 0xd1, 0x9d, 0xba, 0x9c, 0x08, 0xd2, 0xf9, 0x9b, 0x81, 0xfd, 0xf8, 0x94, 0xc1, 0x0a, 0xf1, + 0xc8, 0xfa, 0x4e, 0x5b, 0x87, 0x86, 0x34, 0xed, 0x92, 0xcf, 0xfd, 0x49, 0xda, 0xd7, 0x25, 0xc9, 0xe3, 0x22, 0xdf, + 0x9e, 0xdd, 0x53, 0x30, 0x15, 0xe0, 0x2c, 0x5a, 0xcf, 0x41, 0xb3, 0x0d, 0xa4, 0x3a, 0x7b, 0x70, 0xc8, 0x9e, 0x4e, + 0x6b, 0xa7, 0xeb, 0xa3, 0x55, 0xd5, 0xc6, 0x45, 0x89, 0x21, 0x81, 0x5f, 0xb1, 0x29, 0x01, 0xe4, 0x40, 0xe4, 0xd1, + 0x6b, 0xe3, 0x4b, 0xe1, 0xfa, 0xf5, 0x12, 0x7d, 0x82, 0x59, 0xb9, 0xfa, 0x07, 0x0d, 0xa9, 0xa4, 0xd5, 0x80, 0x90, + 0x91, 0xfa, 0x8c, 0xf2, 0xcc, 0x0a, 0xee, 0x97, 0xce, 0x17, 0x31, 0x3a, 0x3c, 0xfd, 0x6e, 0x3f, 0x34, 0xf6, 0x2d, + 0x94, 0x17, 0x65, 0xa5, 0x32, 0x73, 0x94, 0x13, 0x80, 0x24, 0x96, 0x3c, 0x25, 0xd2, 0xc6, 0xb7, 0xad, 0x2d, 0x11, + 0xc1, 0x37, 0x7c, 0x88, 0x77, 0xee, 0x05, 0xc7, 0x26, 0x21, 0x81, 0x0a, 0xed, 0x76, 0x01, 0x14, 0x54, 0x90, 0x89, + 0x23, 0xc9, 0xd5, 0xd1, 0x20, 0xb1, 0x3f, 0x56, 0x36, 0x1d, 0x3c, 0x22, 0x92, 0xb5, 0xcd, 0x06, 0xd0, 0x91, 0xc6, + 0xab, 0x4a, 0x92, 0x83, 0x08, 0x4b, 0x00, 0x3a, 0x56, 0xfe, 0x49, 0x4a, 0x5c, 0x4e, 0xd0, 0x85, 0x41, 0xc1, 0x5d, + 0x1a, 0xc6, 0xcd, 0x26, 0xb9, 0xb0, 0x52, 0x01, 0xfd, 0x78, 0xe8, 0xc7, 0x63, 0x0f, 0x45, 0x0a, 0x82, 0x56, 0x88, + 0x87, 0x9c, 0xd2, 0x81, 0x22, 0xfa, 0xa5, 0xfe, 0x71, 0x9b, 0x37, 0xbf, 0x26, 0xe6, 0x46, 0x89, 0x8a, 0xe6, 0x3c, + 0xa6, 0x52, 0xd4, 0xc7, 0x88, 0xc1, 0x3f, 0x66, 0xec, 0xd0, 0x61, 0xa2, 0x92, 0x5e, 0xaa, 0x54, 0xac, 0x83, 0x75, + 0x26, 0x95, 0x02, 0xed, 0xd4, 0xf8, 0xe2, 0x9b, 0x48, 0x12, 0xbc, 0x13, 0xb3, 0xce, 0x20, 0x85, 0x97, 0x2a, 0xac, + 0x95, 0xe8, 0x97, 0x2d, 0x0a, 0xa2, 0xc4, 0x35, 0xb4, 0x0e, 0x69, 0x42, 0x11, 0xec, 0x09, 0x1d, 0x94, 0x68, 0xf9, + 0x87, 0xb6, 0xca, 0x48, 0x82, 0x72, 0xdf, 0xf3, 0xc1, 0xbb, 0xcb, 0x80, 0xf4, 0xf0, 0x51, 0x0f, 0x29, 0x24, 0x16, + 0x3e, 0x61, 0xcb, 0x01, 0x5d, 0xb7, 0x41, 0x52, 0x00, 0xef, 0xaa, 0x62, 0x79, 0xd9, 0x2c, 0x88, 0xbb, 0x93, 0x35, + 0x35, 0x63, 0xbf, 0x4c, 0x60, 0xa7, 0x82, 0xa3, 0xd5, 0xb6, 0x09, 0x6b, 0xa9, 0x96, 0x24, 0xa3, 0x63, 0x81, 0x59, + 0x02, 0x89, 0x10, 0xe9, 0xfe, 0x58, 0x9c, 0x03, 0x31, 0xaf, 0x93, 0xcc, 0x80, 0xf3, 0xd4, 0x2a, 0x47, 0x13, 0x28, + 0x1c, 0xc7, 0x72, 0xbe, 0x26, 0x29, 0xc9, 0x13, 0x0e, 0xb0, 0x1a, 0xaf, 0xb0, 0x8e, 0x82, 0xfb, 0xb8, 0xa6, 0xa4, + 0xcc, 0xee, 0x7f, 0x99, 0xd2, 0xc4, 0x60, 0x57, 0xa2, 0x03, 0x12, 0x40, 0x4a, 0xb3, 0xd4, 0x62, 0xf0, 0x79, 0x44, + 0x3c, 0x16, 0x82, 0x89, 0x88, 0x44, 0xe1, 0x2b, 0x5d, 0xcb, 0xcf, 0xbc, 0x04, 0x84, 0xca, 0x4c, 0x83, 0xce, 0x92, + 0xd7, 0xaa, 0xa4, 0x86, 0xf6, 0x1b, 0xed, 0x46, 0x35, 0x2b, 0x9f, 0x14, 0x3e, 0x64, 0x1d, 0xb9, 0x7f, 0x1a, 0x98, + 0x64, 0xbd, 0xc9, 0x29, 0x95, 0x76, 0x96, 0xaf, 0xfe, 0xf5, 0x05, 0x8a, 0x8d, 0xaa, 0xa3, 0xe9, 0xb6, 0x3e, 0xda, + 0x10, 0x75, 0xf6, 0x11, 0x71, 0xc0, 0x13, 0x56, 0x33, 0x97, 0x5f, 0x65, 0xf8, 0xe1, 0x32, 0x39, 0x20, 0x45, 0x73, + 0x66, 0xa2, 0x6b, 0xfa, 0xef, 0x22, 0x39, 0x70, 0x89, 0xad, 0xc0, 0x14, 0x50, 0x46, 0x15, 0x63, 0x64, 0x39, 0x90, + 0xc4, 0x52, 0xc9, 0xe5, 0x7c, 0x84, 0x16, 0x59, 0x57, 0x4e, 0x19, 0x0a, 0x95, 0xd3, 0xc8, 0x1c, 0x36, 0x29, 0x8e, + 0x61, 0x5e, 0x96, 0xea, 0x79, 0x86, 0x90, 0x26, 0xdd, 0xd5, 0xa7, 0x88, 0x42, 0xcd, 0xaa, 0x7d, 0x17, 0xa6, 0xbe, + 0x08, 0x57, 0x85, 0x01, 0xf2, 0xfc, 0x61, 0x2d, 0xb2, 0xce, 0xa4, 0xf1, 0x62, 0x67, 0xbc, 0xa0, 0xb2, 0x61, 0x24, + 0x59, 0x96, 0x38, 0x28, 0x41, 0xe0, 0x94, 0x90, 0xc6, 0x3e, 0x71, 0xb8, 0x2d, 0x3f, 0x1e, 0x33, 0xb7, 0xe9, 0x50, + 0x46, 0x31, 0xe2, 0xea, 0x49, 0x95, 0x75, 0x0d, 0xe7, 0x21, 0xe6, 0x0f, 0x2f, 0x8b, 0xda, 0x6f, 0xba, 0xd2, 0xe8, + 0xc6, 0xa1, 0xb3, 0x02, 0x6d, 0x4f, 0x27, 0x73, 0x3a, 0x7d, 0x11, 0x57, 0x75, 0x52, 0x10, 0x50, 0x04, 0xc2, 0x1e, + 0x8f, 0xfe, 0x51, 0x1a, 0xed, 0x1f, 0x01, 0x4b, 0xd6, 0x31, 0xd8, 0x93, 0x6a, 0x8f, 0x09, 0x49, 0xcb, 0xdb, 0x1f, + 0x81, 0xb9, 0x52, 0x25, 0xd1, 0x43, 0xf0, 0xe1, 0x08, 0xa5, 0x05, 0x85, 0x64, 0xd3, 0x93, 0x6e, 0x43, 0xa6, 0x09, + 0x98, 0xe8, 0x71, 0x90, 0x67, 0xc3, 0x1b, 0x17, 0x55, 0x88, 0x3e, 0x3e, 0x30, 0xd9, 0xa5, 0x63, 0xb4, 0x69, 0x95, + 0x6d, 0xf6, 0x9f, 0xa1, 0xd8, 0xef, 0xf7, 0xd7, 0xcc, 0xa1, 0x48, 0xef, 0x3a, 0x23, 0x37, 0xb1, 0xe0, 0xfc, 0x14, + 0x25, 0xc6, 0xb3, 0xb6, 0x34, 0xa4, 0xe5, 0x10, 0x45, 0x48, 0x0e, 0x1d, 0x82, 0xbe, 0x0c, 0x19, 0x56, 0x57, 0xe8, + 0xf0, 0x2d, 0xfd, 0x82, 0x43, 0x26, 0x29, 0x39, 0xd2, 0x64, 0xbf, 0x97, 0xc4, 0x64, 0x57, 0xba, 0xa8, 0x40, 0x87, + 0xd5, 0xb4, 0x13, 0x43, 0xb2, 0xd5, 0xbb, 0xda, 0x66, 0xa9, 0xe5, 0x08, 0xee, 0xce, 0x03, 0xc9, 0x1f, 0x81, 0xaa, + 0xe7, 0xd1, 0x19, 0x47, 0x0b, 0x44, 0x9d, 0x4b, 0x92, 0xdb, 0x49, 0x31, 0xc8, 0x26, 0x52, 0x28, 0x90, 0xae, 0x10, + 0x8d, 0x61, 0x31, 0x6d, 0x3f, 0x08, 0x1c, 0x2c, 0x75, 0x9b, 0x64, 0xa4, 0xcf, 0x9d, 0xdd, 0x26, 0xc5, 0x23, 0x54, + 0x1e, 0xb5, 0xee, 0xbb, 0x69, 0x49, 0x90, 0xea, 0x24, 0x4f, 0x10, 0xb4, 0x67, 0x63, 0xef, 0x98, 0x80, 0xf9, 0xde, + 0x54, 0xcc, 0xaf, 0xa7, 0x6e, 0xc2, 0xc2, 0xee, 0x43, 0x8a, 0x5b, 0x66, 0x76, 0xf2, 0x9d, 0xf9, 0x1c, 0x69, 0xce, + 0x0c, 0x9d, 0xd4, 0x29, 0x24, 0xb3, 0xb1, 0xb7, 0xf4, 0x17, 0xa4, 0x79, 0x77, 0x2f, 0x3a, 0x94, 0x4d, 0xf8, 0x3d, + 0x21, 0xb8, 0x1e, 0x91, 0xc3, 0x08, 0xbe, 0xea, 0x90, 0xd8, 0xcd, 0x46, 0x2b, 0x52, 0x68, 0xed, 0x68, 0x88, 0x4b, + 0xb6, 0x7b, 0x37, 0x0b, 0x00, 0x88, 0x90, 0xd3, 0xef, 0x95, 0x86, 0x8c, 0x2d, 0xfd, 0xe2, 0x8c, 0xad, 0x14, 0xe8, + 0x59, 0x2d, 0xe2, 0x09, 0xaf, 0x09, 0x29, 0x41, 0x67, 0x85, 0x63, 0x86, 0xea, 0x43, 0xd0, 0xce, 0x1b, 0x4a, 0xb6, + 0x74, 0x30, 0x9c, 0xb8, 0x86, 0x92, 0x2d, 0x8c, 0x18, 0x1f, 0xba, 0xd9, 0x7b, 0x5a, 0x24, 0x43, 0xc1, 0x8f, 0x54, + 0x11, 0xe5, 0x22, 0x6a, 0x46, 0x68, 0x6c, 0x69, 0x30, 0x8a, 0x36, 0x9c, 0x9b, 0x77, 0x57, 0x04, 0x71, 0xd9, 0x27, + 0x56, 0x52, 0xc4, 0x8f, 0x83, 0xc4, 0xe9, 0x57, 0xab, 0x11, 0xf4, 0x32, 0x67, 0xa1, 0x34, 0xbe, 0x29, 0x85, 0x79, + 0xe4, 0x81, 0xc1, 0xb2, 0xb5, 0x0d, 0xd3, 0x3e, 0x69, 0x59, 0x3d, 0x5f, 0x55, 0x03, 0xdb, 0x20, 0x1c, 0xb5, 0x2c, + 0x1d, 0xeb, 0xe7, 0xb3, 0x8a, 0x5e, 0x37, 0xf2, 0xaf, 0x56, 0xac, 0xc5, 0x17, 0x20, 0x3b, 0x63, 0x98, 0xcd, 0x98, + 0x34, 0x2a, 0xa0, 0x16, 0x92, 0x29, 0x6b, 0x8b, 0x8a, 0xa7, 0x49, 0x09, 0x1b, 0x1a, 0x70, 0x34, 0x2d, 0x0b, 0xe9, + 0xc5, 0xeb, 0xa1, 0x7d, 0x70, 0xd6, 0xe1, 0x73, 0xcb, 0xd2, 0x23, 0x58, 0x0d, 0x78, 0x8d, 0x88, 0x12, 0x44, 0x2a, + 0xa4, 0x44, 0x85, 0x94, 0x43, 0x15, 0xd3, 0x41, 0xa7, 0x5c, 0x53, 0x67, 0xa5, 0x95, 0x79, 0x97, 0xc6, 0xf8, 0xd3, + 0x22, 0xa4, 0xb0, 0xae, 0x80, 0xc1, 0xa2, 0xf8, 0x0d, 0x04, 0xc0, 0x8b, 0x35, 0xd3, 0x33, 0x31, 0x30, 0xc7, 0x4b, + 0x5a, 0xde, 0x4b, 0x13, 0x66, 0xb1, 0x74, 0x63, 0x53, 0xa8, 0x8f, 0x8c, 0x42, 0x7a, 0xce, 0x25, 0x20, 0xea, 0xa6, + 0xc7, 0x97, 0xd9, 0x7a, 0xcf, 0xb8, 0x24, 0xff, 0x75, 0xbe, 0xdd, 0x9b, 0x15, 0x0e, 0xcf, 0x3d, 0x72, 0x38, 0x70, + 0x06, 0xa9, 0x48, 0x63, 0x06, 0x39, 0x05, 0x2f, 0x7a, 0x85, 0x19, 0x7f, 0xa4, 0x2b, 0x59, 0x22, 0x0a, 0x4f, 0x00, + 0x7f, 0x57, 0x2d, 0x42, 0xb7, 0x07, 0x84, 0xef, 0x42, 0xc6, 0x67, 0x35, 0x4c, 0xf2, 0x47, 0x18, 0x23, 0xf1, 0xe5, + 0x7b, 0x70, 0x53, 0x99, 0x8c, 0x6f, 0x7e, 0xcb, 0x92, 0x40, 0x65, 0x19, 0x4c, 0x53, 0x83, 0x92, 0x3a, 0xfb, 0x04, + 0x79, 0xe4, 0xbc, 0xaa, 0x1b, 0xa6, 0x4e, 0x9a, 0x49, 0x1e, 0xf4, 0x41, 0xa6, 0x08, 0x44, 0xa7, 0x8b, 0x61, 0xe4, + 0x81, 0x10, 0x00, 0xcf, 0x11, 0x88, 0xb4, 0x04, 0xce, 0x00, 0x8e, 0xe9, 0x9c, 0x0c, 0x1a, 0x91, 0xd1, 0xf8, 0xa9, + 0x51, 0x84, 0x8a, 0x54, 0xae, 0x63, 0xc7, 0xe1, 0x68, 0x89, 0x68, 0x94, 0xdf, 0x40, 0x31, 0x05, 0xff, 0xd2, 0xb8, + 0xb5, 0x69, 0xd7, 0x7b, 0xe2, 0x19, 0xc6, 0x96, 0xa6, 0x99, 0xa6, 0x45, 0xd1, 0x48, 0xdd, 0x67, 0x0c, 0x57, 0x2c, + 0x41, 0x9b, 0x84, 0xa2, 0x0c, 0xa3, 0x3a, 0xa6, 0x4a, 0x71, 0x0b, 0x47, 0x68, 0x54, 0xbe, 0xb5, 0x08, 0xed, 0xfd, + 0xc4, 0xf1, 0xe9, 0x32, 0x42, 0x5a, 0x9f, 0x1f, 0xbd, 0x2c, 0x30, 0xfd, 0x32, 0x9c, 0xa1, 0xaf, 0x44, 0x44, 0x34, + 0xad, 0x02, 0x3b, 0x1c, 0xe8, 0x6a, 0xc3, 0x4b, 0x73, 0x17, 0xb7, 0x35, 0xd1, 0x83, 0x33, 0xf6, 0x54, 0x86, 0xf4, + 0xed, 0x99, 0xc8, 0xba, 0x28, 0xea, 0xf6, 0xb7, 0x93, 0xaf, 0xe1, 0xb1, 0xf9, 0x78, 0x4c, 0xea, 0x14, 0xe5, 0x6b, + 0xa2, 0xd6, 0xea, 0x5a, 0x1f, 0x82, 0x99, 0x79, 0xf4, 0x5c, 0x31, 0x19, 0xe3, 0xd4, 0x8c, 0x8c, 0xac, 0xef, 0x59, + 0xe2, 0xc5, 0x36, 0xf1, 0x3b, 0x85, 0xe4, 0x47, 0xc7, 0x19, 0xd2, 0x88, 0x82, 0xa0, 0xca, 0xfc, 0x8a, 0x42, 0x19, + 0x18, 0xe9, 0xe7, 0xb6, 0xf6, 0x03, 0x72, 0xc5, 0x28, 0x96, 0xf1, 0x6c, 0x33, 0x3e, 0xe5, 0xea, 0x1f, 0x57, 0x34, + 0xc8, 0xb2, 0xb4, 0xdf, 0x89, 0xa7, 0x6d, 0x1e, 0xda, 0x66, 0x5e, 0xd9, 0x24, 0x02, 0x78, 0x95, 0x26, 0xd9, 0xf6, + 0x70, 0xaa, 0xf5, 0x47, 0xe0, 0x57, 0x5e, 0x41, 0x80, 0xcb, 0x49, 0x58, 0xb9, 0x8b, 0x02, 0x45, 0xb5, 0x2d, 0xb8, + 0x7c, 0xb0, 0x4b, 0x9f, 0x47, 0xb1, 0x44, 0x36, 0xf7, 0xc0, 0x6c, 0x51, 0x44, 0x78, 0x4a, 0xbd, 0xad, 0x51, 0xef, + 0xdf, 0x4d, 0x11, 0x1f, 0x71, 0x24, 0x77, 0x27, 0xab, 0x6e, 0x1c, 0x95, 0x47, 0x5a, 0x28, 0xfd, 0x00, 0x2f, 0x2e, + 0x9a, 0x4b, 0x97, 0x8a, 0xc7, 0x5e, 0x0a, 0xd9, 0x46, 0xc2, 0xdc, 0x22, 0x4e, 0x6d, 0xfb, 0x6a, 0xf2, 0xfd, 0x5c, + 0xd0, 0x24, 0x31, 0xeb, 0x4b, 0x97, 0xd6, 0x86, 0x4f, 0x32, 0xbd, 0xb3, 0xcf, 0x7a, 0xf6, 0x64, 0xce, 0xe4, 0xc6, + 0xe0, 0x39, 0xa8, 0xfa, 0xbd, 0xfd, 0x94, 0xba, 0x6e, 0x78, 0x94, 0xc4, 0x94, 0x26, 0x7f, 0xe1, 0x4e, 0x92, 0xe9, + 0xae, 0x33, 0x1f, 0x25, 0xdd, 0x37, 0x1c, 0xce, 0xde, 0xdf, 0xc6, 0x5d, 0x81, 0x54, 0x16, 0x1f, 0x43, 0x24, 0x3c, + 0xf1, 0xeb, 0xad, 0x31, 0xe0, 0xa1, 0x40, 0xc0, 0x83, 0x4a, 0xba, 0x59, 0xac, 0x15, 0x1d, 0xe7, 0x74, 0xff, 0x66, + 0x13, 0xce, 0x0a, 0xc3, 0x93, 0x1c, 0x27, 0xb1, 0xcb, 0xab, 0xdc, 0x4e, 0xa5, 0xad, 0x7e, 0x9a, 0x6c, 0xc0, 0x5b, + 0x68, 0x43, 0xd1, 0x72, 0x7c, 0x86, 0x5d, 0xf5, 0x43, 0x53, 0xf9, 0x27, 0xa1, 0x14, 0xc7, 0x36, 0x0d, 0x63, 0x0d, + 0xb9, 0xfe, 0xbe, 0x1d, 0xc8, 0xb4, 0x7a, 0xf3, 0xcf, 0xd9, 0xf7, 0xea, 0xed, 0x58, 0x37, 0x3c, 0x91, 0xde, 0x0e, + 0xfe, 0x7a, 0x48, 0x8a, 0x62, 0x79, 0x7b, 0x55, 0xfd, 0xd7, 0x16, 0xbf, 0x7e, 0xac, 0x2e, 0x6b, 0x2c, 0x96, 0xf9, + 0xf8, 0xb2, 0x1a, 0x4f, 0x2d, 0xef, 0xdf, 0x4e, 0xf5, 0x87, 0x2f, 0x3f, 0xf5, 0x1a, 0xb8, 0x3a, 0x73, 0x9e, 0xa4, + 0x57, 0x14, 0xfb, 0x28, 0x57, 0xc1, 0x4b, 0xf8, 0x20, 0x3f, 0x6d, 0x8f, 0xeb, 0xa7, 0xfb, 0x65, 0x3d, 0x1f, 0x68, + 0xc9, 0xe3, 0x66, 0xeb, 0xed, 0x8d, 0xe6, 0xd5, 0x5e, 0xa6, 0x75, 0x0e, 0x1b, 0x13, 0x7c, 0x28, 0xb7, 0x8a, 0x82, + 0xf1, 0x26, 0x20, 0xf9, 0x03, 0x31, 0xaf, 0xde, 0x36, 0xbb, 0xbe, 0xfc, 0x58, 0xac, 0x59, 0x5e, 0x61, 0x01, 0x96, + 0x35, 0x1a, 0x9a, 0xb3, 0x01, 0x67, 0x49, 0x7a, 0xaf, 0xae, 0xce, 0x9c, 0xe0, 0x9c, 0xc9, 0xed, 0x4d, 0xfc, 0xc7, + 0x4f, 0x53, 0x6d, 0xce, 0x32, 0xcb, 0xe1, 0x2f, 0x8e, 0x62, 0x67, 0x71, 0xd8, 0x6e, 0xc0, 0xfa, 0xaa, 0xe3, 0x2d, + 0xaa, 0xca, 0x56, 0xe7, 0x62, 0x26, 0x4b, 0x44, 0xe5, 0x76, 0xd2, 0xe1, 0x40, 0x37, 0x73, 0x6b, 0x1f, 0xf8, 0xdf, + 0x63, 0x17, 0x2a, 0x9d, 0xc2, 0x3f, 0x97, 0x47, 0x05, 0x17, 0x72, 0x9b, 0x6c, 0x2e, 0xb9, 0x91, 0xee, 0x58, 0x9f, + 0xbc, 0xb1, 0x33, 0x13, 0x46, 0x33, 0x11, 0x56, 0xd8, 0x0f, 0x47, 0xc0, 0x3d, 0x2e, 0x18, 0x7b, 0x2e, 0xfc, 0xd6, + 0xc5, 0x96, 0xbd, 0x77, 0x7d, 0x36, 0xf9, 0x28, 0x64, 0x01, 0xfb, 0x0d, 0x81, 0x1d, 0x68, 0xdc, 0x1c, 0x47, 0x3b, + 0x24, 0xeb, 0x08, 0xe6, 0xa2, 0x5b, 0xc9, 0x56, 0x06, 0xbf, 0x55, 0xb8, 0x9f, 0xdc, 0x05, 0x20, 0x69, 0xf5, 0xee, + 0xc7, 0x5e, 0xdf, 0x7f, 0xd5, 0xcf, 0x5b, 0xbd, 0xca, 0xd8, 0x3e, 0x19, 0xf8, 0x48, 0x83, 0xae, 0x77, 0xc3, 0xcb, + 0x95, 0x6a, 0xa2, 0xcd, 0xb8, 0x59, 0x5e, 0xc9, 0xe8, 0x0d, 0xe9, 0xda, 0xee, 0x3c, 0x54, 0x27, 0x37, 0x5e, 0xb6, + 0x4c, 0x06, 0x78, 0x55, 0x67, 0x33, 0xf9, 0x05, 0x62, 0x7d, 0x7d, 0xd3, 0xc5, 0x16, 0x9a, 0xd9, 0x23, 0xd4, 0x09, + 0x7f, 0xbd, 0x8c, 0xa2, 0x52, 0x24, 0x7a, 0x69, 0x76, 0xf2, 0x78, 0xde, 0x1b, 0x6f, 0x0c, 0x59, 0x4e, 0xa6, 0x87, + 0x20, 0xd1, 0x47, 0xf4, 0x92, 0xc5, 0xf5, 0x0e, 0x83, 0xcf, 0x73, 0x94, 0x66, 0xd9, 0xb0, 0xf2, 0x45, 0xfc, 0x8c, + 0x8e, 0x25, 0x1b, 0xf9, 0xb8, 0x85, 0xad, 0x64, 0xd9, 0xe6, 0x7e, 0xd7, 0x3b, 0x5b, 0xd5, 0xcb, 0x37, 0x1b, 0xcb, + 0xee, 0x58, 0x79, 0x7e, 0x51, 0xa9, 0x59, 0x0a, 0x3b, 0x7c, 0x8e, 0x47, 0x6b, 0xc1, 0x92, 0xdb, 0xbc, 0x1c, 0x21, + 0xbd, 0x97, 0xa4, 0xbf, 0x76, 0xb2, 0x14, 0xc9, 0x87, 0xb2, 0xac, 0xf2, 0x1f, 0x92, 0x24, 0x62, 0x55, 0x14, 0xa6, + 0x1c, 0x64, 0x9e, 0x7c, 0x28, 0x37, 0xbd, 0x78, 0xe7, 0xab, 0xc2, 0x4f, 0x75, 0xd8, 0x4b, 0xeb, 0x37, 0x20, 0x0a, + 0x66, 0x01, 0x7c, 0x21, 0xee, 0x45, 0xb3, 0xeb, 0x99, 0x3c, 0x06, 0x09, 0xf4, 0x39, 0xf0, 0x0f, 0x3e, 0xfa, 0x01, + 0x05, 0x9f, 0x8b, 0x0e, 0x8c, 0x00, 0x00, 0x72, 0xc7, 0xa1, 0xec, 0xf9, 0xbd, 0x29, 0x57, 0x28, 0xab, 0xa1, 0x5a, + 0x9b, 0xfc, 0x49, 0x73, 0x1d, 0x09, 0xce, 0x7b, 0xa4, 0xc8, 0x3f, 0xf1, 0x7a, 0x36, 0x69, 0x1a, 0x62, 0x17, 0x15, + 0x0a, 0x4c, 0x54, 0xe9, 0x24, 0x4f, 0x95, 0x2c, 0xb5, 0x2a, 0x59, 0xa3, 0x07, 0x1f, 0x76, 0xeb, 0xb5, 0x79, 0x55, + 0x1e, 0x92, 0x9f, 0x25, 0x10, 0xa6, 0x7f, 0xa5, 0x65, 0xb9, 0xbd, 0xa1, 0x4a, 0xe5, 0x20, 0x0f, 0xc1, 0x23, 0xab, + 0xfc, 0xba, 0x7c, 0xe2, 0xc1, 0x8d, 0x28, 0x7f, 0xa5, 0xcf, 0x21, 0xa8, 0x04, 0xfe, 0x5b, 0x36, 0x9b, 0xbe, 0xf2, + 0xf9, 0xf6, 0xc7, 0x73, 0x41, 0x04, 0x4f, 0x97, 0xec, 0x0d, 0xe6, 0x6a, 0x6f, 0x50, 0x9a, 0xac, 0x7b, 0x67, 0x43, + 0xcc, 0x05, 0xcb, 0x1f, 0xd1, 0xe6, 0xdf, 0x27, 0xdf, 0xec, 0x85, 0x96, 0x40, 0xd3, 0x7a, 0x0d, 0xd0, 0x32, 0xcf, + 0x3b, 0x32, 0xd8, 0x23, 0xef, 0x52, 0x1e, 0x56, 0x1c, 0x57, 0xbd, 0xe4, 0xef, 0xe1, 0x2d, 0xdc, 0x69, 0x1b, 0x29, + 0x12, 0xf5, 0x3a, 0xab, 0x14, 0x81, 0xf3, 0x1e, 0xbe, 0x9a, 0xf3, 0x74, 0xaa, 0x21, 0xf1, 0x4b, 0xc7, 0xdc, 0x86, + 0x0a, 0xeb, 0x65, 0x31, 0xbb, 0xbf, 0x7b, 0x83, 0xdc, 0x12, 0x9b, 0xdf, 0x3b, 0x6f, 0x01, 0x48, 0xb5, 0xfa, 0x94, + 0xb2, 0x23, 0xff, 0x51, 0xaa, 0x1d, 0xf0, 0x2a, 0x1f, 0xa8, 0xa0, 0x1a, 0x33, 0xa4, 0xb4, 0xe2, 0xaa, 0x13, 0x49, + 0xd0, 0xdb, 0xa2, 0x64, 0xb0, 0x91, 0x29, 0xec, 0x43, 0x5e, 0x94, 0xe8, 0xfb, 0x52, 0xc9, 0x72, 0x0b, 0xaf, 0x1c, + 0xcb, 0x5a, 0xee, 0x1b, 0x25, 0x7e, 0x98, 0x20, 0x3f, 0x0d, 0x2f, 0x32, 0xf2, 0xe4, 0x6e, 0x71, 0x24, 0xf0, 0xf1, + 0x49, 0x26, 0x82, 0x7d, 0x03, 0x79, 0x92, 0x5c, 0x3c, 0x89, 0x44, 0x65, 0x62, 0xbb, 0xe4, 0xe8, 0xe8, 0xde, 0x24, + 0xa9, 0xd7, 0xd2, 0xe8, 0x50, 0xe8, 0xb8, 0x8d, 0x42, 0x6d, 0x1d, 0xcf, 0xd9, 0x94, 0x8d, 0x47, 0x77, 0xc9, 0x76, + 0x11, 0xb7, 0x87, 0xd2, 0x08, 0x95, 0xd4, 0x26, 0xe8, 0x58, 0x9a, 0x06, 0x91, 0xc7, 0x03, 0x5b, 0x84, 0x88, 0x3e, + 0x9b, 0x4a, 0x67, 0x39, 0xc4, 0x6a, 0x3b, 0x1f, 0x58, 0x8e, 0x2d, 0x87, 0x2c, 0x09, 0x28, 0x9a, 0x95, 0x22, 0xe1, + 0x60, 0xe0, 0x38, 0x9a, 0xa3, 0x4a, 0x81, 0x31, 0x73, 0x35, 0x87, 0x9d, 0xaf, 0x33, 0x72, 0x2c, 0x8d, 0x34, 0x1b, + 0xbe, 0x2e, 0x45, 0x77, 0x6b, 0xeb, 0x63, 0x6d, 0x44, 0x32, 0xb2, 0xc9, 0x9e, 0xcb, 0xdc, 0x13, 0x56, 0xe9, 0xa9, + 0xdc, 0x8d, 0x95, 0x94, 0x15, 0xe7, 0xf9, 0x64, 0xb4, 0xdb, 0x90, 0x45, 0xab, 0x06, 0xab, 0xf1, 0x25, 0xd3, 0xee, + 0xb3, 0x2f, 0xb5, 0x0d, 0xda, 0x6a, 0x52, 0x17, 0x68, 0xce, 0xc3, 0xba, 0xc2, 0xdf, 0xc8, 0x13, 0x38, 0x93, 0x9e, + 0xbd, 0xea, 0x2e, 0x3f, 0xaa, 0x51, 0xda, 0xee, 0x2d, 0x5c, 0x31, 0x8f, 0xb9, 0x0a, 0xc1, 0xae, 0xd5, 0x44, 0x4f, + 0x66, 0x90, 0xc3, 0xf7, 0x04, 0x5c, 0x8e, 0xfc, 0x66, 0x80, 0xed, 0xd9, 0x38, 0x97, 0xb4, 0x53, 0xde, 0x27, 0x2d, + 0x45, 0x7e, 0xc6, 0x4d, 0xd6, 0x9c, 0x28, 0xff, 0x97, 0x42, 0xac, 0xb2, 0xe0, 0x0b, 0xeb, 0x23, 0xeb, 0xef, 0xd1, + 0xa9, 0x4e, 0x79, 0xeb, 0xd5, 0x8c, 0x7e, 0x2b, 0x2a, 0x4c, 0xd8, 0x3b, 0xa0, 0xc1, 0x64, 0xc7, 0x5a, 0x0d, 0xed, + 0x6e, 0xd9, 0xd1, 0xa2, 0x38, 0x6d, 0xcf, 0x68, 0x55, 0x7b, 0x21, 0x23, 0x1e, 0x7e, 0x6e, 0x34, 0x12, 0x8b, 0xa4, + 0x58, 0x40, 0xe7, 0x2b, 0xea, 0xfd, 0xb5, 0x9c, 0xd3, 0x93, 0xd6, 0x64, 0xf0, 0xa8, 0x33, 0xa7, 0xce, 0x55, 0x9f, + 0xbd, 0xde, 0xd5, 0xa1, 0xf2, 0x27, 0xe2, 0xfa, 0x13, 0x34, 0x55, 0x55, 0x73, 0xd7, 0x4a, 0x90, 0x9a, 0xb2, 0x6c, + 0xe2, 0xc8, 0xa7, 0xc9, 0xf7, 0xf9, 0x4c, 0x87, 0xec, 0xc3, 0x75, 0xa8, 0x8a, 0x17, 0x23, 0xb1, 0x05, 0x21, 0xb9, + 0x70, 0x82, 0x65, 0x51, 0xdf, 0x63, 0x29, 0x8a, 0xa3, 0x84, 0x92, 0xe1, 0x05, 0x8a, 0xc0, 0x51, 0x0b, 0x0c, 0x94, + 0xe4, 0x44, 0x1d, 0x1a, 0xc9, 0xce, 0xd3, 0xc1, 0x8b, 0x4f, 0x6c, 0xf2, 0x2d, 0xa1, 0x43, 0x3a, 0x43, 0x79, 0x05, + 0xdf, 0x8b, 0x77, 0x45, 0x9e, 0x30, 0xd5, 0xd2, 0x31, 0xcf, 0xbd, 0x66, 0xfa, 0xd8, 0x35, 0x78, 0x21, 0xba, 0x0e, + 0x97, 0x67, 0x48, 0x19, 0xab, 0x48, 0xd5, 0x34, 0xed, 0x87, 0x77, 0x87, 0x28, 0x49, 0x55, 0xb6, 0xdb, 0x7b, 0xa7, + 0x2d, 0x44, 0x09, 0xa4, 0xc9, 0xba, 0x0d, 0x8c, 0x64, 0x7a, 0xce, 0xb1, 0x2a, 0x45, 0x31, 0x86, 0x19, 0x82, 0x5c, + 0xe8, 0xb0, 0x15, 0x92, 0x4a, 0x3f, 0xca, 0x22, 0xe8, 0x26, 0x9d, 0xf1, 0x60, 0x96, 0x81, 0x51, 0xe1, 0xf8, 0xa4, + 0xde, 0x85, 0x77, 0x6d, 0x73, 0x72, 0x68, 0x15, 0x69, 0x02, 0x75, 0x2c, 0x90, 0x1e, 0xe5, 0x6f, 0xbe, 0x7b, 0x8c, + 0x6b, 0xd3, 0xaf, 0x8b, 0x55, 0x21, 0x33, 0x76, 0x02, 0x07, 0x90, 0x69, 0xbb, 0xf9, 0x9d, 0x7d, 0xa3, 0x24, 0x05, + 0x23, 0xad, 0xe7, 0x9e, 0x19, 0x5c, 0x8c, 0xc9, 0x42, 0xb4, 0xad, 0x76, 0xd3, 0x47, 0x07, 0x6d, 0x64, 0xe5, 0x35, + 0x00, 0xab, 0x24, 0x2d, 0x39, 0x1b, 0xc0, 0xc2, 0x6a, 0xc7, 0x36, 0x4c, 0x2f, 0x0d, 0x80, 0x4d, 0xbf, 0x05, 0x58, + 0xc0, 0x0b, 0xa2, 0xfd, 0xcc, 0xbc, 0xd2, 0x2c, 0xc2, 0x03, 0xef, 0x13, 0x80, 0x0d, 0xb1, 0x52, 0x51, 0x2d, 0x16, + 0x0b, 0xaf, 0x14, 0x0b, 0x5a, 0xd3, 0xcc, 0x96, 0x4e, 0xc0, 0xfa, 0x72, 0x47, 0xa1, 0x3a, 0xe5, 0xaf, 0xa8, 0xc4, + 0x9a, 0x43, 0x55, 0xf1, 0xd1, 0xfd, 0x66, 0x7d, 0x9a, 0x62, 0x91, 0xda, 0xa7, 0xd6, 0x93, 0x0c, 0xf0, 0x76, 0x8b, + 0xe7, 0xc0, 0x4b, 0xcb, 0xa2, 0xf7, 0xbd, 0x9d, 0xb5, 0x64, 0x51, 0xdd, 0x72, 0x7c, 0xd5, 0xca, 0xe4, 0x74, 0x25, + 0x97, 0x82, 0x32, 0x14, 0xf9, 0x9e, 0x27, 0x49, 0x21, 0xae, 0x4f, 0x1f, 0xcc, 0x7c, 0x84, 0x71, 0x65, 0xc6, 0x8b, + 0x6f, 0xc5, 0xc3, 0x8c, 0x27, 0xa5, 0x48, 0x6a, 0x79, 0x51, 0x01, 0xa9, 0xc6, 0x28, 0xbe, 0x20, 0x43, 0xcf, 0xf9, + 0x7a, 0xd4, 0xa7, 0xb8, 0x73, 0xb6, 0x24, 0x0e, 0xa2, 0x70, 0x98, 0x3e, 0x2b, 0x54, 0x08, 0xfe, 0x3b, 0x20, 0x26, + 0x19, 0x82, 0x00, 0x73, 0x22, 0xa1, 0x0e, 0xb2, 0xf0, 0x84, 0x67, 0x7b, 0xc9, 0x68, 0x25, 0xa3, 0x13, 0xa9, 0x32, + 0x11, 0x51, 0xf9, 0xed, 0xca, 0x26, 0x41, 0xb3, 0xec, 0xa5, 0x28, 0xdc, 0x88, 0x25, 0x11, 0x5c, 0x2b, 0x83, 0x9b, + 0x7e, 0x44, 0xa9, 0xee, 0x96, 0x86, 0xeb, 0x8c, 0x65, 0x72, 0xe1, 0x1b, 0x6f, 0xe8, 0xfa, 0xd2, 0xf5, 0x67, 0xe4, + 0xb6, 0xa8, 0xf0, 0xc9, 0x47, 0xf2, 0xc0, 0xb9, 0xbe, 0x9a, 0x66, 0x3a, 0xc7, 0xbc, 0x8b, 0x50, 0x5c, 0x63, 0xb2, + 0xcd, 0x7e, 0xdb, 0x2c, 0xc1, 0xeb, 0xfc, 0x59, 0xb2, 0x9c, 0xa6, 0x02, 0x76, 0x31, 0xf1, 0x8b, 0xa0, 0x44, 0x1b, + 0xae, 0x7a, 0xff, 0xde, 0xd6, 0x7a, 0xf7, 0xd9, 0x07, 0x1c, 0x16, 0xe5, 0x6f, 0xd4, 0xf6, 0x0c, 0x28, 0xa8, 0xe4, + 0xb9, 0xab, 0xd6, 0x80, 0xb1, 0x1d, 0xc3, 0x0f, 0x51, 0x1f, 0xed, 0x1a, 0xa0, 0xae, 0xd9, 0xca, 0x29, 0x06, 0x63, + 0x00, 0x1d, 0xdd, 0xfa, 0xd4, 0x20, 0x75, 0x58, 0xd8, 0x94, 0xd6, 0xdb, 0x58, 0xbc, 0xd0, 0x22, 0xe6, 0x72, 0x95, + 0x2c, 0xad, 0xf9, 0x1a, 0xfe, 0x37, 0xb8, 0xa6, 0xe0, 0x77, 0x94, 0xbf, 0x92, 0x78, 0xd7, 0x9d, 0xd3, 0x0a, 0x89, + 0x82, 0x79, 0x2e, 0xbc, 0x22, 0xc2, 0x4a, 0x9f, 0x10, 0x73, 0xcc, 0x75, 0x99, 0x93, 0x7d, 0xe1, 0xd0, 0x1a, 0xa9, + 0x43, 0xc0, 0xa5, 0xfb, 0x1e, 0x4f, 0x2f, 0xf8, 0x12, 0x5d, 0x1d, 0xdf, 0xcb, 0x3c, 0x9a, 0x01, 0xab, 0xba, 0x6f, + 0x31, 0x09, 0x53, 0x51, 0x46, 0x09, 0x41, 0xdc, 0x54, 0x22, 0x0b, 0x43, 0xcf, 0x1a, 0x57, 0x1f, 0x3b, 0xad, 0xa7, + 0x0c, 0x00, 0x28, 0x25, 0x09, 0xdd, 0x33, 0x94, 0x31, 0xa3, 0x97, 0x56, 0x81, 0x72, 0xcb, 0xd5, 0xc1, 0xcb, 0xce, + 0x3d, 0x86, 0x81, 0x9d, 0xd9, 0x5a, 0x67, 0x1a, 0x07, 0x22, 0xcb, 0x40, 0x80, 0x38, 0xc8, 0xb7, 0xa9, 0xd2, 0x58, + 0x74, 0x03, 0xd4, 0xb5, 0xa8, 0x0f, 0xd2, 0x8e, 0x2c, 0xc4, 0x19, 0x26, 0x3a, 0x06, 0xf6, 0xa7, 0x97, 0x68, 0xa4, + 0xa4, 0x42, 0xe0, 0x95, 0x31, 0xf3, 0x40, 0x22, 0x7b, 0xa0, 0x1d, 0x94, 0x0d, 0x80, 0x24, 0x67, 0x8e, 0x2b, 0x05, + 0x69, 0x2d, 0x23, 0x96, 0xd0, 0xff, 0x13, 0x2b, 0x8d, 0x32, 0x01, 0xf9, 0xc8, 0xa1, 0x4d, 0x49, 0xe3, 0x79, 0x78, + 0x2d, 0x1c, 0x48, 0x3e, 0x4c, 0x7f, 0x9c, 0x05, 0x8d, 0xc8, 0x94, 0xd3, 0xb9, 0x15, 0x6c, 0xe3, 0x8b, 0x3b, 0x4f, + 0x23, 0x51, 0x61, 0xfa, 0xcc, 0x77, 0x96, 0xb7, 0x93, 0x55, 0x84, 0xe5, 0x8f, 0xb9, 0xec, 0xa7, 0xe8, 0x7f, 0xad, + 0xa2, 0x24, 0xc9, 0x06, 0x5f, 0x2a, 0x99, 0x8e, 0xdb, 0xf3, 0x6b, 0xad, 0x8d, 0x96, 0xee, 0x01, 0xce, 0x78, 0x0f, + 0xaa, 0x3b, 0x12, 0x7a, 0xc8, 0x69, 0xcd, 0x53, 0x87, 0xa8, 0xaa, 0xa0, 0x84, 0x44, 0x63, 0x5c, 0xa4, 0xd6, 0x44, + 0xea, 0x9b, 0xc5, 0xd3, 0x00, 0x92, 0x69, 0x0c, 0x2a, 0xaa, 0xdc, 0x57, 0xcf, 0x6c, 0x5e, 0x4c, 0x4f, 0xa4, 0xc9, + 0x74, 0x41, 0x2e, 0x3f, 0xc5, 0xe8, 0x66, 0x4a, 0xc9, 0xb2, 0x58, 0x86, 0xc3, 0x1e, 0x23, 0xcc, 0x01, 0x43, 0x44, + 0xa5, 0xc2, 0x78, 0xc3, 0xa4, 0xbc, 0x9f, 0x94, 0xfc, 0x69, 0x8a, 0xf3, 0x0b, 0x61, 0xf5, 0x61, 0x5b, 0x07, 0xb8, + 0x3a, 0x07, 0xe5, 0x08, 0xb7, 0x96, 0x07, 0xd8, 0xd8, 0x98, 0x47, 0x7b, 0x39, 0x55, 0x25, 0x22, 0xd3, 0xac, 0x3b, + 0x58, 0x52, 0xde, 0xa4, 0xef, 0x0c, 0x99, 0xb0, 0x75, 0x33, 0x14, 0x41, 0x6e, 0x3c, 0xc9, 0xae, 0xb1, 0xd5, 0x07, + 0x81, 0xb3, 0x7a, 0x44, 0x5e, 0xc6, 0xa3, 0xaa, 0xce, 0xaa, 0xed, 0x94, 0xfc, 0x34, 0xbc, 0x4f, 0xae, 0x3b, 0xc9, + 0x09, 0x95, 0xd5, 0x24, 0x2a, 0x0a, 0x8a, 0xc2, 0xf3, 0x24, 0x20, 0x82, 0xe2, 0x8c, 0xfa, 0xa1, 0x8a, 0xfa, 0xa6, + 0xc8, 0xfe, 0x71, 0xea, 0xd5, 0xbe, 0xe5, 0x25, 0x80, 0x24, 0x3f, 0x93, 0x49, 0x77, 0x8c, 0x7b, 0x67, 0x5d, 0x1e, + 0x3e, 0x4a, 0x14, 0xe6, 0x3e, 0x14, 0x57, 0x31, 0x49, 0x51, 0x2c, 0x01, 0xf7, 0xca, 0x65, 0x2f, 0x1e, 0x49, 0x3a, + 0x41, 0x66, 0xa8, 0x5c, 0x1b, 0xef, 0x9b, 0x7a, 0xa4, 0xea, 0x49, 0x96, 0x02, 0x79, 0xe4, 0xee, 0x77, 0x46, 0x50, + 0xf2, 0xfc, 0xb7, 0xec, 0x8a, 0xd7, 0x49, 0x79, 0x86, 0x36, 0x1b, 0x22, 0x7a, 0x5d, 0x8e, 0x36, 0x05, 0xcc, 0x31, + 0x23, 0x02, 0xfd, 0x73, 0xb0, 0x0a, 0xf9, 0xb2, 0xe3, 0x14, 0xdb, 0x54, 0x01, 0x4a, 0xb9, 0xf7, 0xfd, 0x55, 0x1e, + 0x08, 0xfb, 0x33, 0x92, 0x9c, 0x49, 0x46, 0x44, 0x50, 0xb6, 0xc0, 0x23, 0xb0, 0x2f, 0xa4, 0x8b, 0x13, 0xb5, 0x0a, + 0xfb, 0x82, 0x9a, 0xb3, 0x67, 0xa9, 0x88, 0xea, 0x14, 0x7d, 0xfc, 0xca, 0xb8, 0x60, 0x2e, 0xab, 0x91, 0xb6, 0x22, + 0x5a, 0x9e, 0xaa, 0x04, 0x04, 0xb5, 0x10, 0x0b, 0xb1, 0xa9, 0x80, 0x60, 0x7c, 0xaf, 0xa7, 0x27, 0x18, 0x31, 0x0b, + 0xc5, 0x8b, 0xcc, 0xe5, 0x44, 0xbb, 0xfc, 0x87, 0x9b, 0x30, 0x9d, 0x33, 0x86, 0x34, 0x22, 0xa9, 0x47, 0xd6, 0xef, + 0x5f, 0x2f, 0x2f, 0x54, 0x65, 0x13, 0x49, 0x65, 0x23, 0xee, 0xe6, 0x73, 0x9d, 0x1b, 0xd3, 0x44, 0x70, 0xc5, 0x92, + 0xd9, 0x62, 0xe3, 0xe9, 0xfc, 0xc3, 0x95, 0x59, 0x48, 0xd7, 0x44, 0x39, 0x92, 0xc8, 0x4f, 0x0a, 0xc1, 0x43, 0x8d, + 0xf2, 0x42, 0x18, 0x91, 0xfa, 0x6f, 0x86, 0xdc, 0x75, 0x29, 0xda, 0xd5, 0x46, 0x75, 0xd9, 0x02, 0xd8, 0xd2, 0xd7, + 0x30, 0x32, 0x14, 0x42, 0x47, 0x0c, 0x92, 0xdc, 0xa5, 0x3e, 0x2a, 0x19, 0xc8, 0xa2, 0x2b, 0xcc, 0x40, 0x99, 0x7b, + 0xe8, 0xe4, 0x8d, 0x93, 0x28, 0x01, 0xb9, 0x9f, 0x99, 0x4f, 0xea, 0xec, 0x24, 0xf2, 0x62, 0x2d, 0x05, 0x74, 0xa4, + 0xba, 0x4e, 0x25, 0x56, 0x59, 0xad, 0x84, 0x9e, 0x08, 0x76, 0x17, 0xcd, 0xe0, 0x55, 0x9b, 0xe7, 0xe9, 0xb1, 0xe6, + 0x9f, 0xc7, 0x57, 0x94, 0xb7, 0x35, 0x91, 0x16, 0x74, 0x22, 0xb4, 0xfa, 0xc0, 0x7d, 0xdd, 0x5c, 0xd9, 0x1a, 0xe4, + 0x65, 0x01, 0xd0, 0x72, 0xce, 0x72, 0x7a, 0x12, 0xca, 0xba, 0x79, 0x5e, 0x26, 0x99, 0x7b, 0x15, 0x07, 0x5b, 0x40, + 0x73, 0x01, 0x37, 0xc1, 0x67, 0x1f, 0x27, 0xa4, 0x7e, 0xa8, 0x3c, 0x56, 0x36, 0xdf, 0xd6, 0x60, 0xee, 0xdb, 0xc4, + 0xe9, 0xb0, 0xd9, 0x24, 0x22, 0x26, 0x73, 0x37, 0xb6, 0xde, 0x08, 0x67, 0x2d, 0x54, 0xed, 0x11, 0xf3, 0x84, 0x00, + 0x53, 0xd5, 0x20, 0x7c, 0xda, 0xc7, 0x49, 0x4c, 0x6f, 0x11, 0x15, 0xa0, 0x5c, 0x62, 0x52, 0xaf, 0xdc, 0xa5, 0xa5, + 0xd6, 0xbd, 0x4f, 0x17, 0x58, 0x57, 0xba, 0x78, 0xbc, 0xd3, 0x7d, 0xe0, 0x00, 0x70, 0x3f, 0x83, 0xaa, 0x55, 0x5e, + 0xaa, 0xea, 0x0b, 0x6a, 0x69, 0x82, 0x94, 0x04, 0xbc, 0x55, 0x49, 0xef, 0xe7, 0x99, 0x06, 0x82, 0xe6, 0x6b, 0x64, + 0x75, 0xe4, 0x0b, 0x91, 0xc8, 0x43, 0xcf, 0x4b, 0x7c, 0xbc, 0x08, 0xcf, 0x09, 0x1e, 0xbf, 0x8c, 0xad, 0x0b, 0x3a, + 0x65, 0xfe, 0x20, 0x81, 0xe5, 0x40, 0xed, 0xda, 0xe5, 0xeb, 0x38, 0x11, 0xec, 0x14, 0x05, 0xea, 0x29, 0x2a, 0x40, + 0x83, 0x40, 0xd1, 0x48, 0x0b, 0xe8, 0x24, 0xf9, 0x39, 0xa6, 0x05, 0x84, 0xd4, 0x29, 0x10, 0x31, 0xdf, 0x0e, 0xcb, + 0x11, 0xdc, 0x95, 0x22, 0x27, 0x9e, 0x38, 0x37, 0x6b, 0xe5, 0xcb, 0x7d, 0x88, 0xaa, 0x73, 0x7f, 0x7c, 0x83, 0x3b, + 0x70, 0x15, 0xdb, 0x8d, 0xe3, 0x1f, 0x71, 0xbf, 0x49, 0x16, 0x72, 0x0e, 0x44, 0x8a, 0xbc, 0x1c, 0x11, 0x22, 0x13, + 0x87, 0x3a, 0xdc, 0x84, 0x90, 0x8e, 0x2f, 0xa0, 0x3f, 0x8e, 0x98, 0xc6, 0x56, 0x9d, 0x26, 0x20, 0xe7, 0x3c, 0xbe, + 0x3d, 0x9d, 0xde, 0xba, 0xa8, 0x1e, 0x44, 0xdb, 0x22, 0xe2, 0x87, 0xb6, 0xa8, 0x51, 0xa8, 0x3c, 0x9c, 0x5a, 0x5f, + 0x53, 0xc3, 0x31, 0xc4, 0xe1, 0xdf, 0x06, 0x48, 0x00, 0x85, 0xdd, 0x26, 0xd7, 0x5c, 0xd0, 0xe9, 0x9d, 0xa4, 0x23, + 0xb4, 0xd6, 0xf4, 0x53, 0xb9, 0x6a, 0xd6, 0xc1, 0xca, 0xb4, 0xd3, 0xfb, 0x6c, 0xe3, 0xb6, 0x38, 0x01, 0x41, 0xb4, + 0xd2, 0xeb, 0x9b, 0x30, 0x61, 0x89, 0x31, 0x06, 0xde, 0x17, 0x62, 0xce, 0x53, 0x98, 0x49, 0xcc, 0xc7, 0x70, 0xb4, + 0x3a, 0x8b, 0x77, 0x6e, 0xd1, 0xa5, 0xbd, 0xd1, 0x9b, 0x36, 0x92, 0xa9, 0x84, 0x8e, 0x05, 0xf0, 0xc7, 0xe9, 0xa8, + 0x1d, 0x71, 0x07, 0x04, 0xd8, 0xca, 0x12, 0xe3, 0xd2, 0x2d, 0xd8, 0xaa, 0x6c, 0xf9, 0xb4, 0x71, 0xae, 0xdc, 0xcf, + 0xd6, 0x2e, 0x74, 0x44, 0x70, 0x58, 0x97, 0x34, 0x07, 0xe6, 0x63, 0xc1, 0x5c, 0x8a, 0x8b, 0xd5, 0x4e, 0x01, 0x12, + 0xb4, 0x92, 0x3c, 0x5c, 0x66, 0x48, 0x7a, 0x7c, 0xa2, 0x2e, 0x12, 0x72, 0xc6, 0x8d, 0xb6, 0x06, 0xec, 0xe0, 0xdd, + 0x5e, 0x8f, 0xb4, 0xee, 0xbc, 0x45, 0xde, 0x8b, 0xe2, 0x05, 0xa4, 0x9a, 0x02, 0x71, 0x65, 0x83, 0x20, 0xed, 0x3a, + 0x25, 0xac, 0xbf, 0x19, 0x2c, 0x8d, 0xdb, 0x77, 0x6d, 0x4a, 0x0f, 0x7a, 0x76, 0xa6, 0x87, 0x5c, 0xf8, 0xb3, 0xa2, + 0x6f, 0x5f, 0x79, 0xcb, 0x36, 0xec, 0xa7, 0xa5, 0x00, 0xb2, 0xba, 0xb8, 0x1b, 0xe7, 0xbc, 0x60, 0x8b, 0xa5, 0xc9, + 0xe9, 0xab, 0x65, 0x85, 0x9a, 0xc0, 0x1e, 0x7c, 0xa0, 0x65, 0xa4, 0x52, 0x5f, 0x29, 0x29, 0x5a, 0x1e, 0x1a, 0x93, + 0x6c, 0x6d, 0x6a, 0x85, 0xb8, 0xaa, 0x06, 0xab, 0xea, 0xe1, 0x12, 0x4b, 0x4b, 0xdb, 0x52, 0x0b, 0xcd, 0x75, 0xef, + 0x05, 0x98, 0x7c, 0x8f, 0x1e, 0xb1, 0xbc, 0x00, 0xba, 0xfb, 0x85, 0x7c, 0x19, 0x87, 0x41, 0x5a, 0x54, 0x41, 0x00, + 0xe9, 0x75, 0x1d, 0xc3, 0xa6, 0x61, 0x8d, 0x89, 0x0e, 0x8b, 0x3e, 0x8d, 0x40, 0x45, 0xa8, 0x81, 0x21, 0xd8, 0x42, + 0xae, 0x4c, 0xc5, 0xd2, 0xa9, 0x97, 0xc9, 0xe2, 0xd2, 0xe7, 0x5e, 0x6c, 0x6b, 0xd2, 0x15, 0xb3, 0x54, 0x41, 0x5c, + 0x1a, 0x75, 0xbd, 0xd1, 0x37, 0x6a, 0x79, 0xd0, 0x35, 0xde, 0xe3, 0x26, 0x19, 0xd6, 0xa6, 0x72, 0x7d, 0x94, 0x6c, + 0xb7, 0xff, 0x59, 0xb9, 0x44, 0xb5, 0xe4, 0x2c, 0xad, 0xb1, 0xea, 0x61, 0x8b, 0x02, 0x5c, 0xbe, 0xe3, 0x4e, 0xc6, + 0x00, 0x59, 0x8e, 0xb4, 0x61, 0x6e, 0x1d, 0xce, 0x65, 0x1b, 0x68, 0xfb, 0xcd, 0xa7, 0x92, 0x60, 0xeb, 0x57, 0x4f, + 0xa7, 0xb1, 0x4d, 0x91, 0xc3, 0x28, 0x70, 0x14, 0x9e, 0xbb, 0xe7, 0xbc, 0x5a, 0x29, 0xe3, 0x12, 0xdb, 0xed, 0x73, + 0xd3, 0x4f, 0x5e, 0xd9, 0x86, 0xf5, 0x14, 0x5f, 0x8f, 0x91, 0x8d, 0xbd, 0xe7, 0xc9, 0x7a, 0x32, 0x16, 0x77, 0x0c, + 0x80, 0x8b, 0x92, 0x62, 0xb8, 0x5b, 0xc1, 0xc5, 0x83, 0x5f, 0xf8, 0x7c, 0x2a, 0xa7, 0x9b, 0x34, 0xee, 0xcd, 0xbf, + 0xed, 0xed, 0x85, 0x07, 0xcd, 0x24, 0x7d, 0x99, 0xa5, 0xcb, 0x2a, 0xb9, 0x16, 0xc8, 0xb5, 0x1b, 0x9e, 0x8b, 0x72, + 0xbd, 0x69, 0x6b, 0x23, 0x4c, 0x50, 0xbc, 0x1c, 0xf8, 0xdb, 0xbb, 0xf8, 0xed, 0xb9, 0xec, 0xf9, 0xb9, 0xb7, 0x68, + 0x08, 0x31, 0xdf, 0xbc, 0x8f, 0x2a, 0x2b, 0x8e, 0x63, 0xe2, 0x7d, 0x3e, 0x34, 0xde, 0xeb, 0x1a, 0x2d, 0x63, 0xae, + 0xf0, 0xf3, 0x18, 0xaa, 0xda, 0xc7, 0xcd, 0x2d, 0xff, 0x6c, 0x77, 0x9d, 0x95, 0xa2, 0x30, 0x9b, 0xc9, 0xc3, 0xd2, + 0x94, 0xb4, 0x3b, 0x0e, 0x36, 0xdc, 0x3e, 0x2b, 0x00, 0x73, 0x00, 0x2c, 0x8f, 0x74, 0x7d, 0x16, 0x7b, 0x16, 0xca, + 0xb6, 0x8b, 0x38, 0x54, 0x6f, 0x61, 0x57, 0xdc, 0x9c, 0xe5, 0x59, 0xea, 0x6e, 0xe3, 0x0b, 0x03, 0x54, 0x3d, 0xe4, + 0x8e, 0x39, 0x92, 0x96, 0x09, 0xa6, 0x4a, 0x7e, 0xbb, 0x71, 0xdc, 0xcc, 0x19, 0x3b, 0xf1, 0x0c, 0xb3, 0x79, 0xea, + 0x0d, 0x2b, 0x9a, 0xf7, 0xed, 0x2b, 0xf7, 0x34, 0x30, 0xf1, 0xad, 0x8d, 0xca, 0x54, 0xf6, 0x75, 0x00, 0x94, 0x2c, + 0xd1, 0x9f, 0x76, 0x51, 0x5a, 0x57, 0x08, 0xa3, 0xc2, 0xa9, 0xf2, 0x0f, 0xd6, 0x92, 0x56, 0x31, 0x11, 0x8b, 0xa3, + 0x23, 0xcd, 0x19, 0xe0, 0x96, 0x78, 0xcb, 0xa8, 0x03, 0xc5, 0x98, 0xd1, 0xc6, 0x4c, 0xca, 0x6a, 0x8f, 0x66, 0x07, + 0xc2, 0xc8, 0x73, 0x6d, 0x11, 0xe9, 0x28, 0x60, 0xbd, 0x54, 0x70, 0xe0, 0x37, 0xef, 0x55, 0xa0, 0x79, 0xdf, 0xb3, + 0x01, 0xe5, 0x00, 0xee, 0x37, 0x74, 0x94, 0xd4, 0xa6, 0x8d, 0xbf, 0xe4, 0x8a, 0xd1, 0xd5, 0x83, 0x24, 0xd0, 0x36, + 0x63, 0xc0, 0x07, 0x4c, 0xae, 0xa8, 0x42, 0xfa, 0x34, 0x46, 0xde, 0x28, 0x90, 0x9c, 0x63, 0xd3, 0x50, 0x4c, 0x3b, + 0xac, 0x27, 0x91, 0x94, 0x0e, 0x22, 0x64, 0x8a, 0xc5, 0xf4, 0xa0, 0x0e, 0x96, 0x64, 0xa4, 0x75, 0x2a, 0x6f, 0x45, + 0x47, 0xfd, 0x9e, 0x8d, 0xa0, 0x39, 0xb6, 0xac, 0x2a, 0xd4, 0x37, 0xcb, 0x2d, 0x13, 0x95, 0x74, 0xf3, 0x6c, 0x2a, + 0x1f, 0x97, 0x83, 0xc8, 0xa6, 0x69, 0xc7, 0x6f, 0xfb, 0xbc, 0xc7, 0x0c, 0xee, 0x62, 0x84, 0x82, 0xac, 0x6d, 0xc8, + 0x60, 0x8f, 0x3c, 0x5c, 0xd0, 0x2d, 0xfd, 0x40, 0xa1, 0xdf, 0xae, 0x96, 0x00, 0x7e, 0x4a, 0xe0, 0x2b, 0x41, 0x6f, + 0x37, 0xb9, 0x53, 0xbb, 0xce, 0x3d, 0xef, 0x13, 0xd9, 0x0b, 0x27, 0x0f, 0x92, 0x6d, 0x5b, 0xa2, 0x6d, 0xd5, 0x8d, + 0x5b, 0xfe, 0xb1, 0xc3, 0x4f, 0x4a, 0x53, 0x44, 0xad, 0x49, 0xea, 0xb4, 0xb1, 0xdc, 0x12, 0xb5, 0xa3, 0xc1, 0x51, + 0xba, 0x11, 0x5e, 0xb8, 0xdf, 0x86, 0xfd, 0x86, 0x82, 0xb1, 0x1c, 0xbd, 0x72, 0x17, 0x1d, 0x0b, 0x68, 0x1c, 0x29, + 0xe8, 0xd8, 0x1e, 0x47, 0xb5, 0x31, 0x86, 0x72, 0xcc, 0xde, 0x70, 0x0c, 0x65, 0x35, 0x06, 0x6a, 0x63, 0xeb, 0x26, + 0x74, 0x37, 0x9e, 0x88, 0xe4, 0x30, 0xa0, 0x71, 0x40, 0xea, 0x96, 0x19, 0xa9, 0xfc, 0x3a, 0x27, 0x2c, 0x10, 0x83, + 0x3b, 0xf6, 0x78, 0xa1, 0x7d, 0xc1, 0x30, 0xc4, 0x11, 0xe8, 0x16, 0x8f, 0x62, 0xb6, 0xa8, 0x0c, 0xf5, 0xe2, 0xca, + 0x5a, 0x98, 0xc0, 0xda, 0x11, 0xa2, 0x42, 0x7f, 0x6c, 0xf3, 0x5d, 0x3b, 0x14, 0xe4, 0x8a, 0x1f, 0xc6, 0xfe, 0x32, + 0xfd, 0x68, 0xe4, 0xa9, 0xa4, 0xff, 0x22, 0x8c, 0x7e, 0xea, 0x84, 0x95, 0x13, 0x40, 0xf0, 0x27, 0x48, 0x72, 0xdb, + 0x78, 0x3f, 0x4c, 0x69, 0xa6, 0xff, 0xb1, 0xb1, 0xe9, 0x8a, 0xf7, 0x43, 0x3f, 0xcc, 0x1f, 0x3a, 0x51, 0x07, 0xf9, + 0xa7, 0x5f, 0x3c, 0x74, 0x5c, 0x8f, 0xed, 0x63, 0x4c, 0xdd, 0xb1, 0xa5, 0xf9, 0x78, 0xec, 0xda, 0x4b, 0xb6, 0xdb, + 0xf6, 0xe3, 0xf0, 0x64, 0x78, 0x38, 0x64, 0x43, 0x1a, 0xb8, 0xf7, 0xfc, 0x72, 0x8e, 0x3d, 0x4f, 0xde, 0x3d, 0xf4, + 0xe9, 0x81, 0x9c, 0x8b, 0x94, 0x31, 0xd9, 0x2d, 0x9e, 0xb6, 0x5d, 0xa4, 0x34, 0x02, 0xd4, 0xd1, 0x1b, 0xe1, 0x63, + 0x41, 0xd7, 0x24, 0x55, 0xc8, 0xa0, 0x7c, 0x86, 0x49, 0xa3, 0xea, 0x0f, 0xf1, 0x0c, 0x85, 0x88, 0x83, 0xc0, 0x7f, + 0xf9, 0x67, 0x8f, 0xd6, 0x13, 0xa7, 0xd5, 0x69, 0x6d, 0x78, 0xec, 0xf7, 0x65, 0x97, 0xa5, 0x9e, 0x94, 0x51, 0xba, + 0xcd, 0xc4, 0x4b, 0x8c, 0xcc, 0x4d, 0x7e, 0xc8, 0xb1, 0x3d, 0x75, 0x0f, 0x93, 0xff, 0x42, 0x04, 0x45, 0xb8, 0xc7, + 0x02, 0x19, 0xef, 0x21, 0x50, 0x39, 0x15, 0xa2, 0x98, 0x96, 0x8b, 0xb3, 0x05, 0xb0, 0x6b, 0xf4, 0x4b, 0x64, 0x45, + 0x3c, 0x33, 0x9e, 0xdf, 0xb5, 0x36, 0xd7, 0x01, 0xfc, 0x7e, 0x6d, 0xf4, 0x64, 0x46, 0xab, 0x80, 0xac, 0xfb, 0xa0, + 0x0c, 0x2e, 0x09, 0x4f, 0xa5, 0x3d, 0x97, 0xd5, 0x58, 0xd3, 0x7e, 0xa0, 0x57, 0x33, 0xfd, 0x69, 0xfb, 0xac, 0x21, + 0x74, 0x3d, 0x9a, 0x29, 0x05, 0x54, 0xaa, 0x7c, 0x50, 0x66, 0x5f, 0x5f, 0x40, 0x38, 0xa2, 0x55, 0xc8, 0x2f, 0x15, + 0xa7, 0x87, 0xb1, 0x8d, 0x82, 0x20, 0xdf, 0x79, 0x86, 0xc8, 0x0f, 0xc9, 0x13, 0x2a, 0xec, 0xce, 0xfd, 0x02, 0xf4, + 0x45, 0x85, 0xa7, 0xf4, 0xfd, 0x69, 0x8e, 0xdb, 0xd5, 0xbc, 0x8f, 0xef, 0x03, 0x19, 0x25, 0x58, 0x46, 0xba, 0x39, + 0x74, 0xd2, 0xa8, 0x1d, 0x3d, 0xf2, 0x95, 0x48, 0x8e, 0x2e, 0xd0, 0xf4, 0x3d, 0xd6, 0x86, 0x17, 0x49, 0x4a, 0xd0, + 0xa7, 0x72, 0x2d, 0xc9, 0xb0, 0x57, 0x75, 0x60, 0x74, 0x44, 0xde, 0x5e, 0x8a, 0x0d, 0x90, 0x24, 0xd5, 0xd3, 0x12, + 0xa1, 0xfd, 0x50, 0xce, 0x7a, 0x53, 0x7e, 0x89, 0x7b, 0xf1, 0x84, 0x57, 0x46, 0x74, 0xc3, 0x5f, 0x7c, 0x13, 0xe2, + 0x5e, 0x28, 0xee, 0x8b, 0x02, 0x96, 0x25, 0x54, 0x11, 0x41, 0x6f, 0x1a, 0xa8, 0x1c, 0x0c, 0xfd, 0xb1, 0x28, 0xf0, + 0x6c, 0x05, 0x58, 0x96, 0x09, 0x29, 0x03, 0x47, 0x6c, 0x44, 0xff, 0x4a, 0x9a, 0xfa, 0x29, 0xa5, 0xb9, 0x6f, 0x49, + 0xbc, 0xec, 0x17, 0x84, 0x94, 0x37, 0x10, 0x0a, 0x82, 0x96, 0x0a, 0xde, 0x04, 0x29, 0x68, 0x4c, 0x3b, 0xcc, 0x95, + 0x41, 0xd9, 0xe3, 0xb8, 0x01, 0x2e, 0x5f, 0x39, 0xa8, 0x4d, 0xd5, 0xeb, 0x24, 0xb6, 0x2a, 0x6e, 0xf4, 0x9f, 0xe8, + 0xd6, 0xda, 0x0f, 0x07, 0x28, 0x82, 0xb6, 0x28, 0x9b, 0xf4, 0x8a, 0xc6, 0xb3, 0x30, 0x16, 0x96, 0x3d, 0x46, 0x0f, + 0x6a, 0x06, 0x4a, 0x2a, 0xac, 0x36, 0x54, 0x28, 0xe6, 0x53, 0xbb, 0x08, 0xa3, 0xf0, 0x41, 0x53, 0x19, 0x79, 0xf8, + 0xd0, 0x9d, 0x46, 0xef, 0xc6, 0x51, 0x2c, 0x72, 0x43, 0x9b, 0xd7, 0x2c, 0x45, 0xc2, 0xa4, 0x49, 0x3e, 0xbd, 0x6c, + 0xd6, 0xb3, 0x66, 0xd2, 0xb2, 0x15, 0x7a, 0xd5, 0x78, 0x63, 0x20, 0x52, 0xd4, 0x6f, 0xbe, 0x4e, 0x7a, 0xb5, 0x9e, + 0xc3, 0xec, 0x47, 0xc2, 0xf2, 0xa2, 0xe8, 0x7a, 0xa6, 0xdb, 0xbc, 0x6a, 0xa3, 0x3b, 0x73, 0xaa, 0xaf, 0xd4, 0x60, + 0x08, 0xf8, 0x95, 0x73, 0x79, 0x50, 0x26, 0xa8, 0x9c, 0xd8, 0x76, 0x0f, 0x6d, 0x46, 0x40, 0x07, 0xcf, 0xb2, 0xd3, + 0xcc, 0x97, 0xaf, 0x96, 0x49, 0x31, 0xac, 0x77, 0xa9, 0x43, 0x81, 0x97, 0x7b, 0x95, 0xfe, 0x81, 0x46, 0x95, 0x32, + 0xf2, 0x82, 0xa8, 0x3a, 0xd1, 0x5e, 0x70, 0x10, 0xc7, 0x1d, 0xfe, 0x3d, 0xe2, 0x70, 0xc9, 0x3d, 0x87, 0x1d, 0x40, + 0x4e, 0x59, 0x44, 0x3a, 0xca, 0xc7, 0x77, 0x8f, 0xbe, 0x65, 0xcc, 0x31, 0xd2, 0x65, 0xf5, 0x53, 0x11, 0x6d, 0x1f, + 0x51, 0x12, 0xe9, 0x0e, 0x07, 0xfb, 0x14, 0x21, 0xde, 0x6c, 0x8a, 0x41, 0x00, 0x2b, 0x74, 0xbe, 0x44, 0x74, 0x42, + 0x5a, 0xd4, 0x03, 0x0a, 0x87, 0xad, 0x82, 0xcf, 0x72, 0xc1, 0x09, 0x96, 0xfe, 0x10, 0x13, 0xab, 0x52, 0x24, 0x3b, + 0x34, 0xcb, 0xbf, 0x4c, 0x6d, 0xaf, 0x96, 0xa6, 0x51, 0x6d, 0x1e, 0xc1, 0x7d, 0xe3, 0xb2, 0xa4, 0x68, 0x05, 0x76, + 0x97, 0xbd, 0x54, 0xc8, 0xc2, 0x86, 0x6b, 0x2f, 0x79, 0xa6, 0x6d, 0x4b, 0x5e, 0x34, 0x78, 0x40, 0x12, 0xd8, 0x7c, + 0x01, 0xac, 0xff, 0x71, 0xb5, 0x2c, 0x43, 0x2d, 0x54, 0x35, 0x30, 0x42, 0xbe, 0xdb, 0x75, 0x04, 0xd1, 0x9e, 0x55, + 0x37, 0xbf, 0x06, 0x26, 0x5a, 0xf6, 0x26, 0xb0, 0x74, 0x90, 0x45, 0x0b, 0x81, 0x60, 0xe7, 0xfe, 0x7c, 0xed, 0xb2, + 0xd8, 0xce, 0x78, 0x8c, 0x35, 0x61, 0xe1, 0x11, 0xb9, 0x71, 0x80, 0x95, 0xc7, 0x65, 0x09, 0x42, 0x56, 0x94, 0x61, + 0x57, 0xee, 0x1c, 0x50, 0x8f, 0x85, 0x1a, 0x55, 0x08, 0xb2, 0xd6, 0x67, 0xaf, 0xa7, 0x8a, 0x35, 0xc9, 0xfd, 0x3e, + 0x28, 0x30, 0x38, 0x83, 0xbb, 0x4d, 0x45, 0x28, 0x7d, 0x48, 0xe1, 0x4f, 0x6d, 0xba, 0x3e, 0x4b, 0x7b, 0x9e, 0x82, + 0x49, 0xb1, 0x20, 0x5e, 0x2b, 0xf9, 0xe7, 0xe9, 0x2f, 0x12, 0xa8, 0x83, 0x94, 0xdc, 0x98, 0x3e, 0xe2, 0xb5, 0x11, + 0x42, 0x64, 0xac, 0xe7, 0xa0, 0x71, 0x20, 0x9c, 0x52, 0x30, 0xa8, 0x9c, 0xd9, 0x32, 0x8b, 0xe9, 0x78, 0x67, 0x4b, + 0x9d, 0x90, 0x6d, 0x0d, 0x3f, 0xf0, 0x66, 0x1a, 0xfb, 0x89, 0x70, 0xdd, 0xdc, 0xe4, 0x5b, 0x83, 0x67, 0xe8, 0x14, + 0x33, 0x7e, 0x93, 0x31, 0x14, 0xd3, 0xd6, 0x3d, 0x17, 0x4f, 0x4f, 0x4f, 0xc5, 0xa8, 0xb2, 0xb9, 0xe2, 0x61, 0xbc, + 0x1c, 0xab, 0x6a, 0x55, 0x15, 0xd3, 0x42, 0x2b, 0xab, 0xcf, 0x7f, 0x16, 0xc3, 0x25, 0xba, 0xc5, 0x70, 0xb6, 0x08, + 0x6d, 0xa2, 0x88, 0x16, 0x8d, 0x74, 0xcd, 0xd5, 0xfd, 0x4e, 0xdd, 0x95, 0xec, 0xe3, 0xab, 0x77, 0xfb, 0x1f, 0x12, + 0x46, 0xad, 0x97, 0xee, 0x14, 0x90, 0x57, 0x23, 0x9e, 0xf7, 0x5f, 0xcf, 0x29, 0xaf, 0x5a, 0x5e, 0x1a, 0x7d, 0x14, + 0x3c, 0x67, 0xfa, 0xdc, 0xd0, 0xf8, 0x45, 0xd3, 0x28, 0xcd, 0x3e, 0x50, 0x23, 0xbb, 0x81, 0xd6, 0x9b, 0xb4, 0x43, + 0xc6, 0x3b, 0x12, 0x7c, 0xb2, 0x42, 0x78, 0x69, 0xdc, 0x9e, 0x38, 0x89, 0x94, 0x62, 0x34, 0x55, 0x29, 0x54, 0xb5, + 0xce, 0x0a, 0x4d, 0x5b, 0x55, 0x21, 0xc9, 0x81, 0x03, 0xa5, 0x93, 0x21, 0xcc, 0xf1, 0xa4, 0x9c, 0xc4, 0x93, 0xa4, + 0x59, 0xcd, 0x43, 0x4e, 0x79, 0x51, 0x92, 0x86, 0xf4, 0x75, 0xe6, 0x14, 0x80, 0x66, 0x03, 0x25, 0x70, 0x28, 0x49, + 0x01, 0x66, 0x1a, 0xd2, 0x33, 0x44, 0x14, 0x82, 0x01, 0x7a, 0x73, 0x15, 0x13, 0x8f, 0x13, 0x6f, 0x1b, 0xed, 0xb2, + 0xa6, 0x20, 0x9e, 0x7c, 0xec, 0x7d, 0xb3, 0x98, 0xd6, 0x9d, 0x5c, 0x50, 0xc9, 0xf3, 0xc5, 0xd4, 0xd2, 0x04, 0xee, + 0x13, 0x32, 0xd5, 0x8c, 0xa9, 0x42, 0xfe, 0x4d, 0xee, 0xdb, 0xd1, 0x7e, 0x2c, 0x8e, 0xc5, 0xbb, 0x33, 0x34, 0xdd, + 0xcd, 0x55, 0x8e, 0xdc, 0x37, 0x23, 0xb9, 0xd5, 0xb2, 0xa6, 0x11, 0x84, 0x2c, 0x7c, 0xe1, 0x7a, 0xed, 0xf5, 0xf1, + 0x7d, 0xd6, 0xfd, 0xab, 0x0d, 0xc7, 0x8b, 0xe6, 0x25, 0x1f, 0xd2, 0x5d, 0x31, 0xb1, 0x68, 0xaf, 0xfc, 0x24, 0xa9, + 0x77, 0x6a, 0x3d, 0x66, 0xc2, 0xdd, 0x3f, 0x94, 0xa6, 0x31, 0xd3, 0x3b, 0xea, 0x78, 0x3f, 0xba, 0xc3, 0x1c, 0x8a, + 0x98, 0x6a, 0x58, 0xdd, 0x48, 0xa5, 0x5c, 0x98, 0x9e, 0x61, 0x63, 0xae, 0x4e, 0x3b, 0x4a, 0x4a, 0xd0, 0xa9, 0x5a, + 0xff, 0x51, 0x1e, 0xe1, 0x34, 0x55, 0xc1, 0x4f, 0x5e, 0x6d, 0xc7, 0xa2, 0x6b, 0x2f, 0x47, 0x6b, 0xd1, 0xb3, 0x1d, + 0xe5, 0x84, 0x7d, 0x7c, 0x8f, 0x50, 0x75, 0x7d, 0xb1, 0x3e, 0xfd, 0xb5, 0xfe, 0x56, 0xee, 0x06, 0x2a, 0x81, 0x3a, + 0x1b, 0xcb, 0xec, 0x5a, 0x13, 0x17, 0xb6, 0xbf, 0x6e, 0x53, 0xab, 0x06, 0x4e, 0xf6, 0x6a, 0xc3, 0xca, 0x9a, 0xcf, + 0x84, 0x6c, 0x7c, 0x93, 0xb2, 0x5f, 0x88, 0xe1, 0x27, 0xa9, 0x4d, 0x4d, 0x9b, 0xa4, 0xb5, 0xfc, 0x2c, 0xd7, 0xcd, + 0xdb, 0x56, 0xc4, 0xe9, 0xbe, 0x28, 0x82, 0x9c, 0x22, 0x09, 0xd9, 0xc6, 0x78, 0x84, 0xb0, 0x85, 0x0e, 0xe2, 0x5c, + 0xba, 0x88, 0xb1, 0x2c, 0x62, 0x78, 0x2f, 0x8f, 0x7d, 0x12, 0x6a, 0xda, 0x68, 0xa7, 0x2c, 0xb2, 0xff, 0x3e, 0xd3, + 0x8f, 0x8b, 0x2a, 0xa8, 0x03, 0x30, 0xbd, 0xbf, 0x6a, 0x7b, 0xb9, 0x38, 0xea, 0x37, 0x15, 0x07, 0x57, 0xff, 0x94, + 0x36, 0x37, 0x6c, 0xaa, 0xf9, 0x86, 0xa8, 0x54, 0xca, 0xbe, 0x18, 0xf4, 0x8c, 0xec, 0x55, 0xa3, 0x51, 0xcc, 0xa7, + 0xd0, 0xb2, 0x44, 0xfc, 0xf1, 0x54, 0x28, 0x6a, 0xa8, 0xe6, 0x2e, 0xe4, 0xe4, 0xd8, 0x30, 0xf6, 0x27, 0x93, 0xdd, + 0x9e, 0xb6, 0xea, 0xa7, 0xac, 0x67, 0x48, 0x87, 0x87, 0x82, 0x1f, 0xb8, 0xdc, 0x75, 0xf1, 0xa6, 0xec, 0xdd, 0xaa, + 0x45, 0x2a, 0x51, 0x10, 0x2a, 0x9b, 0x7d, 0xf5, 0x86, 0xa9, 0x81, 0x1e, 0x6a, 0xf4, 0x40, 0x19, 0x4c, 0xf1, 0x09, + 0x80, 0x9a, 0xd6, 0xe1, 0xd3, 0xd4, 0x42, 0xd9, 0x48, 0xdf, 0x0b, 0xcc, 0x30, 0xfd, 0xd7, 0x61, 0xb2, 0x42, 0x06, + 0xfc, 0xea, 0x69, 0x79, 0x33, 0xce, 0xbf, 0xe7, 0xb6, 0x87, 0xde, 0xa7, 0x7e, 0xfa, 0x2a, 0x89, 0x71, 0x0f, 0xf6, + 0xf7, 0x69, 0xe6, 0x4c, 0xc9, 0xd8, 0x51, 0x01, 0x24, 0x54, 0xdc, 0x4c, 0x61, 0x08, 0x4f, 0x17, 0x82, 0x22, 0x86, + 0xae, 0x6f, 0xd7, 0xf3, 0x3b, 0xbe, 0x62, 0x1e, 0x51, 0xbb, 0x4c, 0xd5, 0x50, 0xd2, 0xfa, 0x30, 0x1b, 0x10, 0xd6, + 0x04, 0x4f, 0x8e, 0x70, 0xc3, 0xd2, 0x55, 0x44, 0x66, 0xc1, 0x0a, 0xcf, 0xc0, 0xa9, 0x09, 0xb8, 0x6e, 0x8a, 0xcc, + 0x7b, 0x9c, 0x00, 0xce, 0xc7, 0x63, 0x1c, 0xed, 0x29, 0xe0, 0xed, 0xb2, 0xba, 0xda, 0x5b, 0x6a, 0xbd, 0x73, 0x1e, + 0xda, 0x44, 0x10, 0x95, 0xf8, 0x79, 0x36, 0x91, 0xfb, 0x07, 0x6f, 0xce, 0xab, 0xc9, 0x96, 0xa4, 0x43, 0xc9, 0xdf, + 0x41, 0xd1, 0x9b, 0xac, 0xb0, 0x92, 0x1b, 0xc5, 0x22, 0x99, 0x34, 0x02, 0x20, 0x30, 0xaf, 0xf2, 0x1d, 0x11, 0xc0, + 0x55, 0x58, 0x68, 0x34, 0x45, 0x51, 0x5e, 0x51, 0x6d, 0x9e, 0xd1, 0xee, 0xd8, 0xaf, 0xe7, 0xb8, 0x2c, 0xd7, 0x96, + 0xd4, 0x6a, 0x2c, 0xeb, 0x48, 0x8a, 0x66, 0x18, 0xbc, 0x39, 0x2f, 0x05, 0x2f, 0xf1, 0xc1, 0x3c, 0x6f, 0x89, 0xaf, + 0x54, 0x5a, 0x41, 0x23, 0xd7, 0x6b, 0x8a, 0x99, 0x03, 0x9a, 0xd3, 0x65, 0x7a, 0x97, 0xe2, 0xfd, 0xeb, 0x15, 0xbf, + 0x2c, 0x5b, 0xaa, 0xba, 0xee, 0xfa, 0x93, 0x15, 0x71, 0x5c, 0x64, 0xb1, 0x6f, 0x59, 0xb4, 0x19, 0xec, 0x10, 0xfb, + 0x31, 0xed, 0xf3, 0x28, 0xcf, 0xb5, 0xcf, 0x36, 0x3f, 0x97, 0x10, 0x47, 0x96, 0x68, 0xbd, 0x3a, 0x62, 0x3f, 0xb5, + 0x64, 0x63, 0xb9, 0xef, 0x44, 0x29, 0x76, 0xb4, 0xb8, 0x90, 0xe6, 0x42, 0x1f, 0x3c, 0xd7, 0x83, 0xa5, 0x0c, 0x7f, + 0x16, 0x57, 0xb6, 0xf4, 0xaa, 0x1c, 0xad, 0xf4, 0x9f, 0x75, 0xa3, 0x87, 0x53, 0x9b, 0x62, 0xea, 0xde, 0x47, 0xc2, + 0x34, 0xa1, 0xf9, 0xbe, 0x21, 0x36, 0x55, 0x4c, 0x14, 0x44, 0x23, 0x6d, 0x03, 0xc7, 0xfb, 0xe7, 0xf5, 0x95, 0xa7, + 0xbc, 0x94, 0xfc, 0xe1, 0x3a, 0x6e, 0x79, 0x63, 0x68, 0x32, 0xf1, 0x06, 0xad, 0x07, 0x39, 0x81, 0x6d, 0x6c, 0x9f, + 0x1e, 0x69, 0x8f, 0xc2, 0x09, 0xe9, 0x4e, 0x39, 0xb4, 0x0e, 0xd7, 0x27, 0xef, 0xd0, 0x85, 0x28, 0x8d, 0x4c, 0xfc, + 0x84, 0xf4, 0xc6, 0x69, 0x74, 0xaa, 0xab, 0x7f, 0xf2, 0xbc, 0xb3, 0xd8, 0x37, 0xb0, 0xa0, 0xde, 0xff, 0xe9, 0xc6, + 0x50, 0x62, 0x3c, 0x6f, 0x19, 0x71, 0x4c, 0x84, 0xa4, 0xdc, 0x4a, 0xbe, 0x4f, 0x22, 0x2a, 0xb5, 0x52, 0x38, 0xa3, + 0x17, 0xf4, 0x88, 0x1a, 0x2c, 0x9e, 0x9f, 0x5a, 0xe7, 0xc0, 0xa4, 0x1b, 0xe5, 0xa5, 0x51, 0x20, 0x0d, 0x22, 0x4f, + 0xcd, 0xf4, 0x0c, 0x9a, 0xb7, 0x0f, 0xaf, 0x03, 0xf7, 0x9e, 0x20, 0x9f, 0xff, 0xfe, 0x30, 0xdc, 0xde, 0x1a, 0x68, + 0x96, 0xf5, 0x39, 0x76, 0x51, 0xeb, 0x8b, 0x15, 0x7a, 0x58, 0x80, 0xdd, 0x13, 0x92, 0xeb, 0x3f, 0x05, 0xe8, 0x1a, + 0xcc, 0xb2, 0x55, 0xc7, 0xbc, 0x6d, 0xfb, 0xb7, 0xf3, 0x2a, 0xdc, 0x1d, 0x33, 0x10, 0x68, 0x77, 0xc6, 0x38, 0x87, + 0xff, 0x67, 0x89, 0x64, 0x15, 0xc6, 0xe4, 0xa2, 0xbd, 0x6e, 0x0f, 0x97, 0xc4, 0x6e, 0xb5, 0x66, 0x39, 0xd3, 0x76, + 0x60, 0xeb, 0x39, 0x2f, 0xa2, 0xd2, 0x20, 0xc1, 0x4e, 0x6a, 0x43, 0x03, 0x44, 0x32, 0xe8, 0xf6, 0x52, 0xc6, 0xbd, + 0x20, 0x9f, 0x01, 0x7d, 0x6d, 0x67, 0x2e, 0xbd, 0x31, 0x35, 0xae, 0x70, 0x52, 0x97, 0x9d, 0xbb, 0xc9, 0x70, 0xd6, + 0x3e, 0x16, 0xca, 0xd7, 0x63, 0x81, 0x2f, 0xac, 0x8f, 0xd3, 0xf4, 0xc1, 0x1d, 0xd9, 0x47, 0x93, 0x63, 0x2f, 0xa6, + 0xa4, 0x2a, 0x33, 0x18, 0x65, 0x08, 0xb4, 0x74, 0x2d, 0xcb, 0x94, 0x62, 0x8f, 0xde, 0x3e, 0x9c, 0x32, 0x6e, 0xfa, + 0x79, 0x98, 0x73, 0xd0, 0x89, 0x65, 0x8b, 0xe7, 0x15, 0xd9, 0xc3, 0xd4, 0x9d, 0x00, 0x89, 0x04, 0x61, 0xa2, 0x0b, + 0x95, 0x7a, 0x90, 0x61, 0x4d, 0x78, 0x84, 0x34, 0x71, 0x71, 0x3a, 0x32, 0x61, 0x77, 0xe4, 0x49, 0x07, 0x51, 0x07, + 0x86, 0xca, 0xd5, 0x73, 0xfe, 0xd0, 0x63, 0xb2, 0x17, 0x14, 0xd9, 0xf6, 0x48, 0xe1, 0x9c, 0x79, 0xf3, 0x21, 0x7b, + 0xe8, 0x5f, 0x37, 0xbd, 0xe6, 0x88, 0x05, 0xf7, 0xb7, 0x50, 0x81, 0x32, 0x04, 0xdc, 0x1f, 0xfa, 0xee, 0x36, 0x47, + 0xad, 0xa0, 0x33, 0x30, 0x7d, 0xb2, 0xcf, 0xf4, 0x62, 0x4d, 0x69, 0xb8, 0x6f, 0x46, 0xce, 0xe0, 0x4e, 0xd0, 0xb5, + 0x33, 0xa9, 0xb4, 0xbb, 0x7c, 0x21, 0xa8, 0xf0, 0xe1, 0x1a, 0xb4, 0x3a, 0x88, 0x9c, 0x92, 0xfe, 0x4e, 0x48, 0x75, + 0xb5, 0x29, 0x26, 0xdc, 0x40, 0xcd, 0x06, 0x8a, 0xa3, 0x70, 0xe3, 0x07, 0x89, 0x01, 0x66, 0x6e, 0xa4, 0x61, 0x25, + 0xaf, 0x9d, 0x87, 0x5f, 0xec, 0x07, 0x39, 0xcf, 0x63, 0x2a, 0xd1, 0x43, 0x9f, 0x56, 0x75, 0xfd, 0x21, 0xe6, 0x1b, + 0x6a, 0x9f, 0x41, 0x6d, 0x93, 0x10, 0xa2, 0x4e, 0xd3, 0x3e, 0xe6, 0x59, 0xf9, 0xd1, 0xc1, 0x84, 0x98, 0x7b, 0x32, + 0xd0, 0xaa, 0x5d, 0x81, 0xa5, 0xec, 0x52, 0x95, 0x70, 0xed, 0xd4, 0x6f, 0x2a, 0x69, 0x17, 0xab, 0x95, 0x57, 0xa7, + 0xd8, 0xb3, 0x7f, 0xe7, 0xda, 0xfb, 0x90, 0xf1, 0x99, 0xe8, 0x58, 0xb3, 0xda, 0xbd, 0xee, 0x27, 0xce, 0x69, 0xbc, + 0xc4, 0x46, 0x09, 0xe5, 0x87, 0x69, 0x40, 0x3c, 0x78, 0x83, 0x78, 0xd7, 0x4f, 0x6c, 0xf6, 0xe2, 0xaa, 0x2f, 0x35, + 0x5a, 0xa8, 0x3f, 0xe9, 0xc3, 0xa3, 0x1a, 0x9c, 0x3c, 0x5c, 0x86, 0x27, 0x5f, 0x79, 0x3b, 0x19, 0xe0, 0xb1, 0x12, + 0xf8, 0xdc, 0x5a, 0x02, 0x4a, 0x47, 0x24, 0xaf, 0xe4, 0x03, 0xfa, 0x7f, 0x0e, 0xcf, 0x87, 0x5d, 0x8f, 0x9f, 0x2d, + 0x6d, 0xa8, 0x45, 0x27, 0x1d, 0x61, 0x09, 0x6a, 0x7b, 0x48, 0x43, 0x88, 0x8c, 0x1d, 0x81, 0x69, 0xcc, 0x9f, 0x14, + 0x61, 0x1e, 0x81, 0xf7, 0x39, 0x03, 0x8e, 0xda, 0x96, 0xf8, 0xc2, 0x09, 0x77, 0xef, 0xf2, 0xe1, 0x37, 0xf0, 0xbd, + 0xb2, 0x4b, 0x58, 0x6e, 0xab, 0x1d, 0xbb, 0xd9, 0x04, 0x9a, 0xa3, 0x28, 0x6e, 0xbf, 0x99, 0x68, 0xd1, 0xb3, 0xc3, + 0x7e, 0x0e, 0xba, 0x97, 0xa1, 0x42, 0xf9, 0x98, 0xf6, 0x99, 0xdc, 0xaf, 0x47, 0x80, 0x22, 0xe0, 0x10, 0x43, 0x6c, + 0xff, 0xd8, 0x2b, 0x0f, 0xb5, 0x9e, 0x05, 0x04, 0x14, 0xc3, 0x9f, 0x5c, 0x70, 0x66, 0xfa, 0xe0, 0x18, 0x30, 0x39, + 0x00, 0xd4, 0x06, 0x17, 0x8d, 0xc5, 0x29, 0xfe, 0xbf, 0xf3, 0x8d, 0xe4, 0xed, 0xba, 0x38, 0x1d, 0xf1, 0x2e, 0x9f, + 0x51, 0x54, 0xcc, 0x90, 0x42, 0x0b, 0xbf, 0xe8, 0x06, 0xc2, 0x4a, 0x11, 0x0b, 0x7a, 0x2b, 0x1f, 0xdb, 0xcb, 0x63, + 0x14, 0xaa, 0xff, 0xab, 0x97, 0xec, 0x8f, 0x5a, 0xf0, 0xd8, 0xa5, 0x58, 0xde, 0xf0, 0x91, 0x53, 0xaa, 0x87, 0xbb, + 0x78, 0xb3, 0x1d, 0x06, 0x05, 0xbd, 0x1d, 0x10, 0x6f, 0xfd, 0x9f, 0x25, 0x49, 0xb6, 0xdc, 0x6a, 0x86, 0x24, 0xb9, + 0xae, 0x8e, 0x3b, 0xe2, 0xdf, 0x8f, 0x78, 0x57, 0x1b, 0x1d, 0xaa, 0xf6, 0x7c, 0x5c, 0x67, 0xfe, 0x2b, 0xce, 0xf2, + 0x86, 0xa4, 0xd3, 0xcc, 0xee, 0x6b, 0x5c, 0xce, 0x65, 0x3b, 0x99, 0x2f, 0x66, 0x77, 0xb3, 0xfd, 0xf2, 0xfd, 0x96, + 0x2a, 0x63, 0xeb, 0xf9, 0x45, 0xf3, 0x31, 0xc7, 0x1d, 0x91, 0x94, 0x65, 0x18, 0xcb, 0xf9, 0xb9, 0x4b, 0xf3, 0xe3, + 0x0f, 0xc2, 0x9b, 0x1f, 0xbf, 0x78, 0x28, 0x38, 0x9d, 0x62, 0x2a, 0x23, 0x4e, 0x95, 0xce, 0x9c, 0x24, 0x86, 0xa9, + 0x14, 0x68, 0x26, 0xba, 0xbe, 0x06, 0xc9, 0x00, 0xbd, 0x82, 0xa6, 0xc3, 0xd0, 0x9f, 0xf1, 0x01, 0xae, 0x3a, 0x79, + 0xa6, 0x92, 0xcc, 0x17, 0x8c, 0x31, 0x5e, 0xf0, 0x43, 0xbf, 0xf0, 0xe4, 0x5e, 0x3b, 0x32, 0x80, 0x21, 0x15, 0x7b, + 0xfc, 0x78, 0xd1, 0x7c, 0x79, 0x69, 0x44, 0x08, 0x55, 0xc8, 0x52, 0x80, 0xa7, 0x3c, 0x7f, 0x26, 0xab, 0xeb, 0xd9, + 0x6f, 0x36, 0x5d, 0x69, 0xb8, 0xaf, 0xa6, 0x9e, 0x2a, 0x60, 0x6c, 0xb9, 0x91, 0x8f, 0x29, 0x66, 0xd6, 0x06, 0xeb, + 0x74, 0x50, 0xab, 0xc7, 0x1c, 0xe3, 0xa9, 0xa0, 0x2e, 0xa6, 0xd4, 0x93, 0x3c, 0xd6, 0xd9, 0xf4, 0x41, 0x36, 0xb8, + 0x81, 0x71, 0xc5, 0xc9, 0x47, 0x10, 0x45, 0x13, 0x60, 0x39, 0x4f, 0x5b, 0x44, 0x11, 0x7c, 0x87, 0x66, 0x14, 0xc1, + 0x10, 0xb1, 0x88, 0x2d, 0xef, 0x56, 0xc9, 0xbc, 0xbd, 0xec, 0x72, 0x92, 0xe9, 0xb7, 0xa5, 0xcc, 0x49, 0xa2, 0xc1, + 0xc1, 0x2a, 0x9f, 0xb5, 0xea, 0xa6, 0x1f, 0xec, 0x4b, 0x28, 0x00, 0x8e, 0xcc, 0xc0, 0x81, 0x92, 0x62, 0x56, 0xaa, + 0x8a, 0x1a, 0x39, 0x08, 0x70, 0xf2, 0xc3, 0x3f, 0x54, 0x5f, 0x84, 0xa5, 0xb3, 0xdb, 0x29, 0x08, 0x3d, 0xc1, 0x08, + 0x91, 0x40, 0xe3, 0x27, 0x97, 0x6c, 0xfa, 0xef, 0xdc, 0xcc, 0x48, 0x5f, 0xfe, 0xbd, 0x9e, 0xec, 0x6d, 0x6b, 0x50, + 0x30, 0xb9, 0x1e, 0xed, 0xeb, 0x58, 0x2b, 0x96, 0x4e, 0xa8, 0x4b, 0x7f, 0x71, 0x05, 0x3e, 0xa9, 0x09, 0x91, 0xb1, + 0x62, 0xa6, 0x32, 0x6b, 0x29, 0x78, 0xae, 0x7e, 0xcc, 0x65, 0x60, 0x26, 0x52, 0xda, 0x15, 0x93, 0xa6, 0x34, 0xf3, + 0x29, 0x17, 0xd1, 0xb3, 0x67, 0x5d, 0xa7, 0xa1, 0xb5, 0x0e, 0xac, 0xcb, 0x7e, 0x88, 0xb7, 0xf9, 0xd5, 0x99, 0xa6, + 0x30, 0xca, 0xf9, 0xab, 0xf3, 0x0e, 0x8b, 0x72, 0xb3, 0xbe, 0x62, 0x3e, 0xec, 0x1d, 0xda, 0x69, 0x65, 0xf4, 0xf1, + 0x5c, 0xad, 0x70, 0xdf, 0x81, 0x90, 0xf3, 0xe8, 0x7b, 0x03, 0x1e, 0xff, 0x0a, 0xff, 0xbf, 0x3e, 0x04, 0xda, 0xb1, + 0x15, 0x0c, 0xdd, 0xf0, 0x89, 0x4d, 0x70, 0x8f, 0x86, 0x99, 0xd3, 0xd9, 0xca, 0xef, 0x43, 0x22, 0xea, 0x16, 0x70, + 0xb7, 0x8b, 0x1f, 0xd7, 0x3e, 0xc3, 0xd5, 0xc8, 0xc6, 0x18, 0x0e, 0xb9, 0x01, 0xb2, 0x84, 0xf0, 0x09, 0x09, 0x63, + 0xdd, 0x39, 0x3f, 0x38, 0xa3, 0x31, 0xbe, 0xfb, 0x5b, 0xe7, 0xf9, 0x66, 0xbc, 0x8d, 0xf9, 0x75, 0xf2, 0x4d, 0xe7, + 0x7a, 0xa0, 0xf3, 0xf4, 0xa0, 0xd6, 0x6a, 0xfd, 0xc3, 0x4d, 0xef, 0x5d, 0x0c, 0x4b, 0xb8, 0x9f, 0x3a, 0xba, 0xb9, + 0x7b, 0x13, 0x11, 0x11, 0xa8, 0x3f, 0x78, 0x68, 0xd1, 0xf3, 0x09, 0xd4, 0xe9, 0x12, 0x22, 0xfa, 0xa3, 0xcd, 0x9e, + 0xdb, 0xc9, 0x9c, 0x3a, 0x79, 0xb2, 0x8d, 0xae, 0x45, 0x25, 0x5f, 0x58, 0x2c, 0xf3, 0x3e, 0x6d, 0xdd, 0x88, 0xc8, + 0x81, 0xc4, 0x64, 0xc5, 0x36, 0xc3, 0xd4, 0xd0, 0x71, 0xea, 0x22, 0xf1, 0x3f, 0xef, 0xeb, 0xc4, 0x50, 0xf2, 0xb2, + 0xd4, 0x02, 0x0b, 0x4b, 0x55, 0xd8, 0x3e, 0xee, 0x39, 0x95, 0x85, 0x55, 0x37, 0x46, 0xbc, 0x75, 0xdf, 0x76, 0x4d, + 0xc7, 0x26, 0x8a, 0xd7, 0x5f, 0xbf, 0x02, 0xad, 0x21, 0x3d, 0x16, 0xf1, 0x7e, 0x91, 0x8e, 0x63, 0x00, 0xde, 0x31, + 0x74, 0x0b, 0x77, 0xcb, 0xb2, 0x6a, 0xcf, 0xfb, 0x74, 0x0c, 0x25, 0x45, 0xb1, 0x94, 0xdc, 0x3d, 0x62, 0xeb, 0x71, + 0x94, 0xe0, 0xa9, 0xee, 0x3d, 0xbd, 0x45, 0x2a, 0x91, 0xa5, 0xa3, 0xf4, 0xd8, 0xcf, 0x29, 0x60, 0xea, 0xa5, 0xf8, + 0x7d, 0xf4, 0x68, 0x59, 0x32, 0x40, 0x8b, 0x8d, 0x58, 0xe5, 0x1d, 0x5b, 0xc1, 0x5a, 0x9c, 0x92, 0x63, 0xbc, 0xed, + 0xdd, 0x97, 0x54, 0xca, 0x5d, 0xcc, 0x6c, 0x94, 0x76, 0x6a, 0xbc, 0x1c, 0x1c, 0xa7, 0xa5, 0xb0, 0x22, 0xc6, 0x18, + 0x39, 0xbb, 0x12, 0xb4, 0x35, 0x42, 0x77, 0xb8, 0x66, 0x89, 0xff, 0xbe, 0xac, 0x2d, 0x6e, 0x25, 0x90, 0x91, 0x2f, + 0xc3, 0x37, 0xe5, 0x9b, 0xa0, 0xad, 0xfe, 0x62, 0x8f, 0xbe, 0x56, 0x10, 0x32, 0xe1, 0x57, 0x7c, 0x35, 0xba, 0xe6, + 0xf6, 0x7d, 0xd9, 0x4d, 0x56, 0x69, 0x92, 0x9d, 0x40, 0x6b, 0x93, 0xca, 0xb9, 0xf0, 0xf0, 0x39, 0x77, 0x47, 0x92, + 0x3e, 0x7d, 0x2a, 0xcc, 0x28, 0x79, 0xc9, 0x54, 0x50, 0x3a, 0xc8, 0x66, 0x7f, 0x82, 0x25, 0xa8, 0x87, 0x7c, 0x41, + 0x6d, 0xdd, 0xe3, 0xe9, 0xf3, 0x1a, 0x88, 0xeb, 0x65, 0xc3, 0x0a, 0x44, 0x22, 0xfa, 0x6f, 0xb3, 0x8f, 0x3e, 0x64, + 0x73, 0x42, 0xf6, 0xfa, 0x66, 0x8e, 0xd3, 0x9d, 0x44, 0x28, 0xca, 0x1d, 0xb7, 0x03, 0x4a, 0x29, 0x0e, 0x4a, 0xd5, + 0xf0, 0xd8, 0x2c, 0x91, 0x63, 0xe6, 0x07, 0xa7, 0xbb, 0xd8, 0x4f, 0x5c, 0x8b, 0x5f, 0xd8, 0xb1, 0x53, 0x79, 0xf3, + 0xcf, 0xbe, 0x7c, 0xd9, 0xc7, 0x83, 0xc8, 0xe8, 0x0f, 0x42, 0x11, 0x5f, 0xf6, 0x9b, 0x26, 0xf1, 0xe2, 0x17, 0xdf, + 0xd2, 0x53, 0x3c, 0xf7, 0x6b, 0x75, 0x11, 0xb7, 0x75, 0xf7, 0xbe, 0x8a, 0x76, 0x29, 0xb1, 0xe1, 0x36, 0x0c, 0x4f, + 0x93, 0xe4, 0xf4, 0x00, 0xe0, 0x03, 0xce, 0xe5, 0x3f, 0x73, 0x14, 0xca, 0x47, 0x2e, 0xc3, 0xf9, 0x62, 0x11, 0x62, + 0x4c, 0xfe, 0xc6, 0x18, 0xa5, 0x35, 0x6f, 0x9f, 0xb7, 0x77, 0xbf, 0x71, 0x6c, 0x78, 0x6d, 0xbc, 0x89, 0x86, 0x8a, + 0x16, 0xe5, 0x4d, 0xe1, 0x53, 0x5e, 0x17, 0x76, 0x79, 0xaf, 0xf0, 0x98, 0xf7, 0x0b, 0x4f, 0xf9, 0x60, 0xed, 0xd1, + 0x68, 0x45, 0x48, 0xc1, 0xb5, 0x40, 0xd6, 0x85, 0x42, 0x97, 0x71, 0x04, 0xf7, 0x94, 0x17, 0x6d, 0xcd, 0xef, 0xd0, + 0x44, 0x96, 0xff, 0x07, 0x62, 0x85, 0xd5, 0xe9, 0x07, 0x4d, 0xf1, 0x0a, 0xc4, 0x58, 0xe6, 0x58, 0x8a, 0xd5, 0xed, + 0x7f, 0xd6, 0x52, 0x31, 0x1e, 0x73, 0xb6, 0x99, 0x81, 0xbe, 0x5a, 0xbe, 0xc2, 0xc6, 0x40, 0xe3, 0xeb, 0x4d, 0x69, + 0xf5, 0x1a, 0x58, 0x8b, 0xfd, 0x7c, 0x4d, 0x23, 0x59, 0x89, 0xb0, 0x52, 0xe5, 0x61, 0x60, 0xa2, 0x2a, 0xf3, 0x8c, + 0x74, 0x04, 0xc5, 0xf3, 0xe9, 0x0b, 0xbe, 0x72, 0xd4, 0xda, 0x67, 0x05, 0xa8, 0x86, 0xc7, 0x42, 0x47, 0x2f, 0x8c, + 0xec, 0xea, 0xba, 0xa5, 0xa6, 0xb6, 0x67, 0x5f, 0x12, 0x6b, 0xe4, 0xb7, 0xe3, 0x67, 0x52, 0x24, 0xb4, 0x6c, 0xfc, + 0x3e, 0x8f, 0x77, 0xb1, 0xf7, 0x95, 0x86, 0x34, 0x40, 0x68, 0x9d, 0x90, 0x59, 0xd4, 0x74, 0xc1, 0x4b, 0xc2, 0xa7, + 0xa5, 0x8f, 0xe9, 0x47, 0xc7, 0xfb, 0x8b, 0xaf, 0xf0, 0x00, 0x47, 0x5a, 0xbb, 0xd8, 0xe4, 0xc7, 0xe3, 0x02, 0x7e, + 0xed, 0x37, 0x1d, 0x0a, 0x6b, 0xc6, 0x2a, 0x97, 0xde, 0xb4, 0xab, 0x8b, 0xe0, 0x6b, 0x4b, 0x9f, 0xf1, 0xb8, 0x7f, + 0xec, 0x4d, 0x1d, 0xef, 0x4f, 0x7a, 0x04, 0xbe, 0x01, 0x28, 0x15, 0x35, 0x88, 0x7d, 0x10, 0x7a, 0xbc, 0xb3, 0x2a, + 0x82, 0xcb, 0xf0, 0x38, 0xa4, 0xed, 0xf9, 0x32, 0xb3, 0xab, 0xc7, 0xf8, 0x8d, 0x90, 0x04, 0xdd, 0xf0, 0x4e, 0x5a, + 0x12, 0xa0, 0xf4, 0x51, 0x09, 0x93, 0x1c, 0xb1, 0xcf, 0x2f, 0x5a, 0xf6, 0xa6, 0x8d, 0x4e, 0xe1, 0x5b, 0x8f, 0x98, + 0x67, 0x6d, 0x99, 0xf3, 0x9f, 0x06, 0x71, 0x30, 0x93, 0xa3, 0xf8, 0xfd, 0x10, 0xe7, 0x45, 0x15, 0x75, 0xe9, 0xc5, + 0x6c, 0x6f, 0x03, 0xb6, 0xf0, 0xbb, 0x0f, 0xb3, 0x81, 0xef, 0x4f, 0x7d, 0xb9, 0xd6, 0xa1, 0x9e, 0xd1, 0xfd, 0x56, + 0x75, 0xdb, 0xc7, 0x91, 0x75, 0xf2, 0x9c, 0xc5, 0xc3, 0xe8, 0xdd, 0xf7, 0x85, 0xaf, 0x71, 0x66, 0xb4, 0xf8, 0x24, + 0x2a, 0x0a, 0x2b, 0x97, 0x41, 0xb9, 0x7c, 0x4d, 0x55, 0xb5, 0x47, 0x9b, 0x2f, 0x62, 0x74, 0x5e, 0xfc, 0x5e, 0xa7, + 0x8f, 0xba, 0xc6, 0xeb, 0x48, 0xf9, 0x68, 0x5f, 0x16, 0xc3, 0x1f, 0xac, 0x20, 0xb4, 0x98, 0xd8, 0xec, 0xb1, 0x5f, + 0x8e, 0x16, 0xa7, 0x67, 0x69, 0x33, 0xec, 0x34, 0x6d, 0xb5, 0x71, 0x3b, 0xd8, 0x6f, 0x1d, 0xd2, 0x92, 0xc4, 0x8b, + 0xf1, 0x15, 0x2a, 0x7f, 0xc0, 0x43, 0xec, 0x39, 0x48, 0xd0, 0x88, 0x35, 0xe7, 0xb7, 0xc8, 0x75, 0xba, 0x16, 0x48, + 0x5d, 0xf8, 0x7a, 0xe8, 0x61, 0xd2, 0x22, 0xd5, 0x41, 0x59, 0x06, 0xba, 0x89, 0x02, 0xfa, 0x9e, 0xba, 0x2d, 0xc8, + 0x45, 0xf6, 0xf7, 0x9c, 0x9d, 0xbe, 0xc6, 0xfb, 0x73, 0x0b, 0x3b, 0x51, 0xf8, 0xcd, 0x1f, 0x93, 0x18, 0xd6, 0xdc, + 0x76, 0x91, 0x2d, 0x82, 0xde, 0x6c, 0x5a, 0x3e, 0x28, 0x07, 0x6c, 0x7e, 0x69, 0xa1, 0xca, 0xc8, 0x11, 0xeb, 0xf9, + 0x6f, 0xf7, 0x63, 0x97, 0x98, 0x57, 0x41, 0xa8, 0x5e, 0xa9, 0x2a, 0x31, 0x80, 0x3e, 0xa9, 0x3d, 0x03, 0x75, 0x66, + 0x76, 0x55, 0xe9, 0xf5, 0xeb, 0xac, 0x3e, 0xd4, 0xee, 0x02, 0xf7, 0x4e, 0xc3, 0xb3, 0x13, 0x6b, 0x25, 0x8b, 0xe8, + 0x23, 0x24, 0x61, 0x02, 0xfd, 0x7e, 0xd7, 0xb5, 0xaf, 0x7b, 0x3a, 0x96, 0x05, 0x94, 0x89, 0x3a, 0x5c, 0x9c, 0x20, + 0x18, 0x3f, 0xc8, 0x71, 0x80, 0x6d, 0xe4, 0xc7, 0x2e, 0x8b, 0xab, 0xfe, 0x1c, 0x28, 0x92, 0xa0, 0xb9, 0x96, 0xfb, + 0x35, 0xb8, 0xaf, 0xef, 0x74, 0x93, 0x15, 0xd9, 0x65, 0x98, 0x33, 0xde, 0x30, 0xc6, 0x08, 0x51, 0xc5, 0x22, 0x9e, + 0xe7, 0xb8, 0x81, 0xe5, 0x71, 0x09, 0xde, 0x58, 0xce, 0x3b, 0xa3, 0xda, 0xf2, 0x6c, 0x80, 0xa6, 0xb4, 0x62, 0x1b, + 0x95, 0x6a, 0x65, 0x0c, 0x0c, 0x64, 0xcb, 0x4e, 0xa6, 0xef, 0xa9, 0x2c, 0xc6, 0xfb, 0x77, 0x47, 0x04, 0x37, 0x3d, + 0xca, 0x7c, 0x7d, 0x10, 0xc6, 0xd0, 0xdc, 0xc3, 0xa0, 0x62, 0xb7, 0x4d, 0x39, 0x06, 0x17, 0x5c, 0x74, 0xa2, 0x26, + 0x35, 0x94, 0x45, 0xb5, 0x8c, 0x14, 0x5e, 0xcd, 0x8a, 0xbe, 0xee, 0x69, 0xf1, 0x5a, 0x84, 0x18, 0x94, 0xe1, 0xba, + 0x24, 0x21, 0x54, 0x26, 0x08, 0x7d, 0xa8, 0x30, 0xa5, 0xc2, 0xeb, 0x94, 0x80, 0xfd, 0x3d, 0xcf, 0x79, 0xdd, 0xfb, + 0x5d, 0x3b, 0x2c, 0xb3, 0xe4, 0xb8, 0xd7, 0x70, 0xbb, 0x82, 0xbb, 0x23, 0xcf, 0x46, 0x76, 0x6b, 0x64, 0xf2, 0xbe, + 0x56, 0x0c, 0xe9, 0xb6, 0x60, 0x2a, 0x2e, 0x8a, 0x68, 0x95, 0xc5, 0xb8, 0x1d, 0xf8, 0x95, 0xbb, 0x45, 0xb3, 0x9e, + 0x3a, 0x93, 0xf5, 0x86, 0x21, 0x7c, 0x1a, 0x96, 0xb1, 0x84, 0x58, 0xbd, 0x1e, 0xf9, 0x7f, 0x97, 0x85, 0x47, 0x45, + 0xbb, 0x4f, 0x28, 0xc4, 0xbd, 0xc9, 0x8c, 0x37, 0x03, 0x70, 0x90, 0x63, 0x88, 0x63, 0x70, 0xa0, 0xb5, 0xac, 0xd0, + 0xa9, 0x91, 0x80, 0x88, 0xb5, 0x25, 0x7f, 0xd3, 0x5b, 0xec, 0x2a, 0x7a, 0x6d, 0xdb, 0x77, 0x8e, 0x7f, 0xfe, 0xb6, + 0xda, 0xd6, 0x4d, 0x2c, 0xe4, 0x9d, 0x91, 0x41, 0x3d, 0xb0, 0xbf, 0xef, 0x88, 0x13, 0x6d, 0x81, 0xc0, 0xd5, 0x07, + 0xd3, 0x62, 0x7d, 0xbc, 0x10, 0x31, 0x3f, 0xf8, 0x18, 0x26, 0xf1, 0x14, 0x1d, 0x7d, 0xc6, 0xe7, 0x86, 0x8f, 0xc2, + 0x0f, 0xff, 0xb3, 0x1c, 0x58, 0x99, 0x74, 0x24, 0xa7, 0x8e, 0xa9, 0x8e, 0x02, 0x02, 0xe8, 0x4c, 0xee, 0x91, 0xef, + 0xbf, 0x3a, 0xb4, 0x54, 0xb1, 0x6c, 0x3a, 0x43, 0xb3, 0x93, 0x4e, 0xac, 0x5b, 0xcc, 0x06, 0x9f, 0x38, 0xf7, 0x8b, + 0xcb, 0x0f, 0xe9, 0xc9, 0x61, 0x7f, 0x7b, 0xd2, 0x68, 0xd3, 0x63, 0x46, 0x03, 0x60, 0x0c, 0x2b, 0xfd, 0x78, 0x90, + 0xd2, 0xeb, 0x27, 0x6a, 0xa2, 0x65, 0x43, 0x78, 0x66, 0x3c, 0xba, 0x0c, 0x91, 0xfe, 0xc3, 0xa0, 0x78, 0xd8, 0x6c, + 0xbd, 0x32, 0x5f, 0xb0, 0x9a, 0x83, 0xd1, 0x0b, 0x82, 0x66, 0xc3, 0x16, 0x8b, 0xca, 0xea, 0x71, 0x7e, 0x84, 0x59, + 0x50, 0x00, 0x3e, 0x65, 0x6d, 0x80, 0xfe, 0x39, 0xe6, 0x98, 0x0b, 0x88, 0x46, 0xa3, 0x36, 0x52, 0x6d, 0xf5, 0xbc, + 0xe2, 0x9f, 0xa9, 0x38, 0x50, 0xeb, 0x3d, 0x39, 0x66, 0x7b, 0xca, 0xea, 0x6a, 0x93, 0x4a, 0x03, 0xb4, 0xbe, 0x4c, + 0xf0, 0xb5, 0x0e, 0xb5, 0x04, 0x72, 0x56, 0xc0, 0x67, 0x96, 0x56, 0x97, 0xd9, 0x3d, 0xe7, 0xf8, 0xbd, 0x78, 0xf7, + 0xa0, 0x33, 0xee, 0x36, 0xdf, 0x6d, 0x06, 0x3b, 0x2b, 0x91, 0xdf, 0x0f, 0x1c, 0xb0, 0xf5, 0xce, 0xf1, 0xb2, 0x16, + 0x78, 0xbf, 0x85, 0x41, 0x00, 0xf2, 0x7e, 0x81, 0x5d, 0xd2, 0x38, 0x0d, 0xf3, 0x95, 0xb6, 0x94, 0xc6, 0xb8, 0x72, + 0xfc, 0x94, 0x33, 0xff, 0x3f, 0xd4, 0x58, 0x19, 0xc7, 0x4f, 0x6c, 0x80, 0x76, 0x15, 0x20, 0xc9, 0x01, 0xd1, 0xc1, + 0x93, 0x16, 0x8f, 0xdf, 0x08, 0x0a, 0xfd, 0x6f, 0xae, 0xf9, 0xf5, 0x86, 0x41, 0x6c, 0x7b, 0x84, 0xf0, 0x0b, 0x6d, + 0xd8, 0xfc, 0x4d, 0x67, 0xcd, 0x25, 0x44, 0x72, 0xfd, 0x1d, 0x29, 0xa9, 0xab, 0xe7, 0x91, 0xfb, 0x93, 0x06, 0xc0, + 0xa4, 0xb2, 0xfa, 0x3a, 0xed, 0xf9, 0xc2, 0xeb, 0x79, 0x07, 0xb1, 0x19, 0xc7, 0xef, 0x8e, 0x98, 0xf8, 0x50, 0x54, + 0xd5, 0x59, 0xd4, 0xb4, 0x3a, 0xf6, 0xd6, 0x49, 0x07, 0x3a, 0x71, 0x41, 0xf0, 0x18, 0xbf, 0x04, 0xfb, 0x79, 0xf3, + 0x43, 0x42, 0x1d, 0xbf, 0xeb, 0x87, 0xe4, 0x7a, 0x37, 0x85, 0x07, 0x76, 0xc0, 0xf7, 0xf0, 0xc1, 0xda, 0x44, 0xd3, + 0xb9, 0x10, 0x1f, 0x42, 0x52, 0x11, 0x90, 0xf5, 0x24, 0x4e, 0x6e, 0x4a, 0x92, 0x60, 0xc3, 0x5e, 0xd6, 0xb6, 0x82, + 0xc3, 0xb9, 0x76, 0x87, 0x22, 0x9c, 0x46, 0x07, 0xdd, 0x0c, 0x8f, 0x38, 0xe3, 0xa4, 0x6e, 0x65, 0xea, 0xb3, 0x6d, + 0x10, 0x89, 0x91, 0x70, 0x05, 0x04, 0x9f, 0x08, 0x1e, 0x8c, 0x98, 0x1a, 0x20, 0xa9, 0x08, 0x70, 0xfd, 0xb0, 0x8d, + 0x50, 0x76, 0x3f, 0xe5, 0x27, 0x7c, 0x12, 0x43, 0x0e, 0x39, 0xac, 0xc3, 0xf3, 0xe7, 0x70, 0xd1, 0x50, 0x2c, 0xce, + 0x1c, 0x67, 0x5e, 0x94, 0xd5, 0xb4, 0x50, 0x9c, 0x58, 0xf9, 0x82, 0x07, 0x5c, 0x6f, 0xc0, 0xbc, 0x9d, 0x0a, 0x76, + 0xc6, 0x33, 0x5e, 0x61, 0x4a, 0x4c, 0x6f, 0x77, 0xce, 0x2b, 0x5d, 0xb9, 0x55, 0x14, 0xaf, 0x1a, 0xb4, 0x67, 0x46, + 0x5c, 0xf8, 0x3b, 0xad, 0x8d, 0x6e, 0xd9, 0xa5, 0x71, 0xf8, 0x37, 0x4a, 0x24, 0x04, 0x9b, 0x9f, 0x78, 0xe3, 0x3d, + 0xb4, 0x6b, 0xdf, 0x05, 0x87, 0x59, 0x7e, 0xfb, 0x1a, 0xfd, 0xe9, 0x4d, 0xcf, 0xb0, 0x28, 0xbd, 0x9f, 0x99, 0x83, + 0xea, 0x40, 0x56, 0x57, 0x87, 0x03, 0x0c, 0xda, 0xe1, 0x8e, 0x57, 0x90, 0x6e, 0xc5, 0x2c, 0x43, 0xa4, 0x33, 0x19, + 0xfd, 0xdd, 0x8b, 0x79, 0xc1, 0x3a, 0x04, 0x66, 0x1f, 0x0d, 0x73, 0x02, 0x17, 0xab, 0x0c, 0x0a, 0xa1, 0x0a, 0x21, + 0x7c, 0x1c, 0xe6, 0x8a, 0x9c, 0x06, 0x52, 0xe1, 0x8a, 0x9c, 0xfa, 0xa4, 0x83, 0x72, 0x1d, 0x3a, 0x5f, 0xad, 0x71, + 0x3c, 0xc5, 0x84, 0xbe, 0x18, 0x78, 0xa8, 0xaf, 0xd8, 0x2c, 0x3e, 0xf7, 0x42, 0x64, 0xfd, 0x0d, 0x98, 0xdc, 0xe0, + 0x65, 0x75, 0x9f, 0x85, 0x10, 0xb3, 0x70, 0x99, 0x19, 0xa9, 0x5f, 0x8a, 0x5a, 0x4f, 0xa3, 0x11, 0xa0, 0xd6, 0x3c, + 0xa0, 0x55, 0xcb, 0x10, 0x61, 0xfc, 0x25, 0xb4, 0xf4, 0x7b, 0xed, 0xe0, 0x86, 0x5f, 0xc5, 0x34, 0x1c, 0xc3, 0xfc, + 0x47, 0x11, 0x7a, 0x88, 0x01, 0x97, 0x71, 0x4d, 0xad, 0x5c, 0x8d, 0x06, 0xb9, 0x62, 0x7c, 0x01, 0x90, 0x32, 0x18, + 0x60, 0xac, 0x59, 0x28, 0x9e, 0x7f, 0xc7, 0x1f, 0x82, 0x08, 0xf5, 0x6a, 0x1f, 0xfb, 0xd1, 0x0d, 0x31, 0xa6, 0x36, + 0x3e, 0x26, 0x38, 0xf8, 0xd8, 0x5a, 0x69, 0xdf, 0x74, 0x95, 0x35, 0xc2, 0x09, 0xb4, 0xe0, 0xca, 0x3c, 0x88, 0x0f, + 0xa7, 0x36, 0xff, 0x2f, 0xc5, 0xaa, 0x1e, 0xbb, 0xfb, 0xfb, 0x23, 0x5c, 0x0f, 0x9d, 0x72, 0x90, 0x57, 0xb8, 0x00, + 0x2e, 0xbb, 0xea, 0x9c, 0x57, 0xbe, 0xb2, 0x4c, 0xfe, 0x16, 0x0e, 0x96, 0x0f, 0xca, 0x71, 0x3a, 0xfd, 0xcb, 0xb5, + 0x8b, 0xa3, 0x3d, 0x98, 0x4f, 0xd3, 0x30, 0xfe, 0x49, 0x2c, 0x7d, 0x5e, 0xd0, 0xd9, 0x6f, 0x48, 0x1b, 0x3f, 0x2e, + 0xb2, 0x7d, 0xe8, 0xba, 0x3c, 0x7f, 0x8d, 0xb7, 0xe7, 0x76, 0x4d, 0x9b, 0xce, 0xf7, 0x3f, 0xa5, 0xb3, 0x71, 0xcf, + 0xf8, 0x6f, 0xf4, 0x44, 0x27, 0xdf, 0x18, 0x7f, 0x48, 0x6b, 0xe3, 0xd3, 0x20, 0xbe, 0x6c, 0x0b, 0xb2, 0x87, 0x73, + 0x78, 0x1a, 0xce, 0x17, 0x94, 0x5f, 0x64, 0x71, 0xd1, 0x9f, 0xbe, 0xc6, 0x8b, 0x73, 0xcf, 0xcb, 0xb5, 0xd6, 0x7c, + 0x6a, 0x6d, 0xc0, 0xd6, 0x02, 0xe7, 0x46, 0xed, 0x96, 0x49, 0xaa, 0x56, 0xde, 0x88, 0xe9, 0x6c, 0x1a, 0x51, 0x07, + 0xfb, 0x7d, 0x7b, 0xdc, 0xf1, 0x40, 0xff, 0xb3, 0x79, 0x5d, 0x71, 0x6d, 0xd5, 0x4d, 0x77, 0x56, 0xe0, 0x0d, 0x93, + 0xa5, 0x23, 0x3c, 0x2b, 0x88, 0x34, 0xd2, 0x07, 0xa4, 0x65, 0x6d, 0xdb, 0x12, 0x43, 0xbb, 0x59, 0xc9, 0x34, 0x71, + 0x5b, 0x33, 0x5c, 0xe2, 0x4c, 0x08, 0x10, 0x49, 0xa6, 0x18, 0xba, 0xd6, 0x0c, 0x90, 0xde, 0x41, 0x49, 0x88, 0x65, + 0xbf, 0x04, 0x8a, 0x25, 0x83, 0x4f, 0xff, 0x61, 0x45, 0x4c, 0x8e, 0x37, 0x74, 0x70, 0x2a, 0x68, 0xf6, 0xd8, 0x8e, + 0xb9, 0x08, 0xc2, 0x97, 0x28, 0xf4, 0x4c, 0x63, 0x27, 0x57, 0x6d, 0x8e, 0x9e, 0xd8, 0x09, 0x6b, 0x1a, 0x05, 0x55, + 0xbb, 0xdf, 0xde, 0x2a, 0x15, 0x37, 0x57, 0x9c, 0xcf, 0x60, 0x8c, 0x27, 0x1d, 0x41, 0xe4, 0xcf, 0xfe, 0x02, 0xca, + 0xd0, 0x25, 0x8c, 0xb2, 0x65, 0xde, 0x8f, 0x26, 0xb7, 0x52, 0xc7, 0x92, 0xd0, 0xd4, 0xf5, 0xea, 0x8a, 0x54, 0xe1, + 0xfe, 0x2e, 0xfc, 0xb3, 0x06, 0x71, 0x87, 0x38, 0x87, 0x64, 0x01, 0x51, 0x3d, 0x63, 0x25, 0xc5, 0x20, 0x66, 0x36, + 0x28, 0x61, 0x4a, 0x9f, 0xb4, 0xda, 0x6a, 0x9d, 0x1c, 0x7b, 0x5c, 0xae, 0xea, 0x42, 0xd6, 0x2d, 0x7f, 0xa4, 0x45, + 0x22, 0x2d, 0x70, 0x85, 0xef, 0x2c, 0x00, 0x5d, 0x09, 0xe0, 0x29, 0x04, 0x72, 0x98, 0x84, 0xbf, 0x95, 0x55, 0xf4, + 0xe0, 0xfe, 0x6d, 0x98, 0x5b, 0x8e, 0x40, 0xc2, 0x87, 0xb9, 0x69, 0x8d, 0x3a, 0x8d, 0x4c, 0x6b, 0xd8, 0xba, 0x04, + 0xe2, 0x24, 0x41, 0x0b, 0x35, 0xf6, 0x71, 0x28, 0x1c, 0x7a, 0x1e, 0xb9, 0x49, 0xae, 0xe5, 0xca, 0x97, 0xa2, 0x39, + 0x89, 0x3d, 0x52, 0xd1, 0xb1, 0x9f, 0x91, 0xe3, 0xbc, 0x10, 0xe4, 0xe2, 0x48, 0x9a, 0x9e, 0x6a, 0x92, 0x43, 0x9b, + 0x0c, 0x2a, 0x94, 0xdb, 0x2c, 0x68, 0x73, 0x1b, 0xb1, 0xbf, 0x8e, 0x88, 0x0b, 0x1b, 0x40, 0x22, 0x9c, 0x5c, 0x55, + 0xfd, 0x2d, 0xb9, 0xbe, 0x6e, 0x7c, 0x55, 0x0b, 0x19, 0x0f, 0x28, 0x19, 0x4e, 0xea, 0xed, 0x19, 0x0a, 0xc3, 0xc5, + 0xfc, 0xb4, 0xbe, 0xb0, 0xd6, 0xd4, 0x6e, 0xa5, 0x48, 0x0a, 0x43, 0x9a, 0xf2, 0x44, 0xe2, 0x87, 0x65, 0x77, 0xb1, + 0x49, 0xc5, 0x8a, 0xc0, 0xfb, 0x9c, 0xf9, 0x73, 0xe1, 0xd4, 0x1a, 0xff, 0x21, 0xc0, 0xad, 0x39, 0x38, 0xa8, 0xbf, + 0x8b, 0xdc, 0x64, 0xab, 0x1e, 0x38, 0x4d, 0x7e, 0x74, 0x45, 0x3f, 0x8b, 0x62, 0xdc, 0x83, 0x41, 0x9e, 0xb3, 0x46, + 0x1c, 0x27, 0x5e, 0xa1, 0xc8, 0xa6, 0x12, 0xba, 0xdb, 0x75, 0xa6, 0x88, 0xeb, 0x90, 0xa3, 0x19, 0x72, 0x72, 0x38, + 0x4e, 0x5a, 0xcd, 0xa3, 0xb2, 0x49, 0x12, 0x9e, 0xe2, 0x47, 0xee, 0x13, 0x8a, 0x5d, 0x9f, 0x85, 0x32, 0x23, 0xce, + 0x19, 0x67, 0xdb, 0x0b, 0xae, 0xd1, 0x5b, 0x73, 0x90, 0x8e, 0x1d, 0xf6, 0xfc, 0x89, 0x22, 0x4c, 0x21, 0x65, 0xa7, + 0x26, 0x6d, 0xd2, 0x55, 0x97, 0x71, 0x9f, 0x0e, 0x75, 0x1c, 0x52, 0x3d, 0x3b, 0x1c, 0xea, 0xa5, 0x2d, 0x4f, 0x1c, + 0xe2, 0xca, 0x87, 0xfe, 0x38, 0xf2, 0xeb, 0xc2, 0x7a, 0x51, 0xc8, 0xf8, 0xa4, 0xd0, 0x49, 0x4b, 0x95, 0x78, 0x00, + 0xb7, 0x95, 0x4d, 0x6f, 0xcb, 0xd4, 0xda, 0xd0, 0x71, 0xe9, 0x6f, 0x02, 0xa4, 0x90, 0xc5, 0xa9, 0x5c, 0x0a, 0xe5, + 0x9a, 0xf1, 0xe2, 0xb0, 0xe2, 0xf6, 0xd5, 0x7d, 0xda, 0x57, 0x14, 0x1d, 0x20, 0x10, 0x11, 0x5a, 0x01, 0xc2, 0x17, + 0x26, 0x70, 0x75, 0x95, 0xa5, 0xb0, 0x8e, 0x09, 0xc1, 0x53, 0xf8, 0x46, 0x6a, 0xa5, 0x55, 0x46, 0xc4, 0x05, 0xdb, + 0x8d, 0x50, 0xf6, 0x00, 0x1a, 0x10, 0xc3, 0x49, 0xfc, 0x2f, 0x4f, 0x55, 0xcb, 0xb4, 0x5b, 0xc9, 0xa5, 0x91, 0x76, + 0xa3, 0x2d, 0xde, 0x98, 0x56, 0x14, 0x14, 0x13, 0x92, 0xbe, 0xd2, 0xa0, 0xd5, 0xb1, 0xf5, 0x9b, 0xbd, 0x5e, 0xbc, + 0x3a, 0xbe, 0xe3, 0xe4, 0x60, 0x94, 0x63, 0xc9, 0x20, 0x53, 0x11, 0xca, 0xc5, 0x45, 0xd8, 0x7a, 0xd8, 0xd9, 0x16, + 0xda, 0x69, 0xd0, 0x71, 0xb7, 0x82, 0x1a, 0x84, 0xf9, 0xd0, 0x73, 0xa7, 0xdb, 0x3e, 0x5d, 0x19, 0xb7, 0x8b, 0x78, + 0x95, 0xe3, 0x54, 0x55, 0x09, 0xa4, 0x64, 0xf3, 0x31, 0x48, 0x95, 0x24, 0x47, 0xa6, 0x0a, 0xeb, 0x1e, 0x6c, 0xef, + 0x98, 0x30, 0x09, 0x79, 0xe4, 0x7d, 0xf8, 0x27, 0x84, 0x5a, 0x8a, 0x7e, 0xdb, 0xf6, 0x6d, 0xc9, 0xe1, 0x95, 0xa3, + 0x55, 0x83, 0x80, 0xd8, 0x88, 0x00, 0x35, 0x8f, 0x8f, 0xf6, 0x26, 0x6e, 0xbd, 0xa3, 0x72, 0x37, 0x35, 0x7e, 0xcf, + 0x56, 0x76, 0x1e, 0xf9, 0x1d, 0xaf, 0xec, 0xe3, 0x42, 0x15, 0xec, 0x92, 0x12, 0x3d, 0xc9, 0xfa, 0xf1, 0xca, 0xa6, + 0x35, 0xfb, 0x79, 0x7d, 0x41, 0xc8, 0xe6, 0x55, 0xf6, 0xc8, 0xab, 0x42, 0xbd, 0x18, 0x09, 0x63, 0xaa, 0x43, 0x78, + 0xe3, 0xc8, 0xd8, 0x9f, 0x17, 0x32, 0x8d, 0x81, 0x05, 0x28, 0xb4, 0xd4, 0xbb, 0x11, 0x4f, 0x8f, 0x65, 0x56, 0xa4, + 0x75, 0x27, 0x5c, 0xc5, 0x7a, 0x09, 0x3f, 0xba, 0x0d, 0x58, 0x58, 0x29, 0xdd, 0x22, 0x97, 0x77, 0x75, 0x91, 0xf5, + 0xd9, 0x6b, 0x13, 0x43, 0xef, 0x92, 0x42, 0x85, 0xb2, 0x63, 0xca, 0x8a, 0xf9, 0x0a, 0x69, 0x8e, 0x05, 0x6f, 0x42, + 0xfd, 0xbc, 0x2d, 0x7f, 0x87, 0x2a, 0x16, 0x7f, 0x5d, 0xd1, 0x5b, 0xa7, 0x6a, 0xb6, 0xcf, 0x14, 0x33, 0x65, 0x3b, + 0x17, 0xee, 0x8b, 0xfb, 0x8d, 0x6f, 0x88, 0xa7, 0x62, 0xd5, 0x77, 0x45, 0x71, 0xe4, 0xa0, 0xc9, 0x20, 0xaa, 0x93, + 0xb5, 0x10, 0x77, 0x5d, 0x19, 0x92, 0x70, 0xe7, 0x09, 0x33, 0x48, 0xe7, 0xb0, 0x71, 0x55, 0x23, 0xd3, 0xa0, 0xe6, + 0x40, 0x9d, 0x54, 0x83, 0x15, 0xb4, 0x42, 0x52, 0xf6, 0x14, 0x33, 0x51, 0x07, 0xee, 0xf7, 0x9a, 0xfd, 0x3f, 0xa0, + 0x12, 0x7d, 0xdd, 0xf5, 0x57, 0x7d, 0x0b, 0xe7, 0x82, 0x05, 0x4b, 0x2a, 0xfb, 0x72, 0x5b, 0x6f, 0xfc, 0x29, 0x6c, + 0xea, 0xd4, 0xad, 0xbb, 0x5d, 0xea, 0x72, 0x9a, 0x0d, 0xce, 0x3b, 0x47, 0x31, 0x77, 0x0a, 0x1f, 0x62, 0x2e, 0x2f, + 0xd9, 0x44, 0x25, 0x57, 0x71, 0xe2, 0x45, 0x0d, 0x00, 0xf3, 0x0e, 0x90, 0x9c, 0x29, 0x61, 0x94, 0xf8, 0x73, 0x52, + 0x01, 0xd5, 0x94, 0xae, 0xb3, 0xb3, 0xee, 0x17, 0x7b, 0xfe, 0x8a, 0xbc, 0xbe, 0x72, 0x0c, 0xea, 0xe6, 0xbc, 0x20, + 0xa7, 0x98, 0x5f, 0x34, 0x25, 0x63, 0x4f, 0xb7, 0xad, 0xaa, 0x93, 0xb5, 0xcb, 0x8b, 0xda, 0x44, 0x89, 0x74, 0xc9, + 0x0d, 0x2f, 0xf5, 0xb6, 0xbc, 0x66, 0xcb, 0x93, 0x75, 0x7a, 0x2a, 0xd6, 0xd8, 0xbe, 0x08, 0x63, 0x7d, 0x18, 0x5d, + 0xe9, 0x49, 0x07, 0x39, 0x2d, 0x4b, 0x4b, 0xb9, 0x8b, 0x9c, 0x5b, 0xba, 0x5d, 0x3a, 0xcc, 0x8f, 0x19, 0x6b, 0x6f, + 0x8d, 0x8d, 0xad, 0xe5, 0xe6, 0xbf, 0xae, 0x6c, 0xc3, 0x54, 0xa1, 0x68, 0x01, 0x4c, 0xcf, 0x26, 0x87, 0xf5, 0x01, + 0x35, 0x53, 0x6f, 0x51, 0xbb, 0xe2, 0xf5, 0x4e, 0xf4, 0xbc, 0xfb, 0x0e, 0x6a, 0x86, 0x5a, 0x8f, 0x92, 0x68, 0xa9, + 0x7d, 0xef, 0x5b, 0x4a, 0x5b, 0xe6, 0xb1, 0xf2, 0xa2, 0xd4, 0x43, 0xfd, 0xea, 0x8f, 0xd3, 0xda, 0xb8, 0x27, 0xbc, + 0x65, 0xa3, 0xae, 0xe2, 0x63, 0x9f, 0xe7, 0xc2, 0xcc, 0x2c, 0x3e, 0x97, 0xd6, 0x83, 0x5f, 0x4e, 0xbb, 0x99, 0x39, + 0x3d, 0xbe, 0xa7, 0x83, 0xc4, 0x5c, 0x7a, 0x2f, 0x43, 0xa0, 0x68, 0x85, 0x66, 0x1d, 0x35, 0xcc, 0x79, 0x9f, 0x3a, + 0xc6, 0xcf, 0x7b, 0x4c, 0xc9, 0x1d, 0x3f, 0xe3, 0xf5, 0xd0, 0xa6, 0x9f, 0x3e, 0x66, 0xce, 0x87, 0x89, 0xf0, 0x6a, + 0x57, 0xa3, 0x13, 0x56, 0xe0, 0xeb, 0xa5, 0xc7, 0xc9, 0xa7, 0xbd, 0xaa, 0x5a, 0x5a, 0xdf, 0x7f, 0x6b, 0x62, 0x80, + 0xa9, 0x52, 0x7e, 0x45, 0xfb, 0xb9, 0xc6, 0x62, 0x86, 0x97, 0x74, 0xd9, 0xcb, 0x00}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index 1f61b19fb5..b7c15df32b 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -constexpr uint8_t INDEX_GZ[] PROGMEM = { +const uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x7b, 0x7f, 0x1a, 0xb9, 0xb2, 0x28, 0xfa, 0xf7, 0x3d, 0x9f, 0xc2, 0xee, 0x9d, 0xf1, 0xb4, 0x8c, 0x68, 0x03, 0x36, 0x8e, 0xd3, 0x58, 0xe6, 0xe4, 0x39, 0xc9, 0x3c, 0x92, 0x4c, 0x9c, 0x64, 0x26, 0xc3, 0xb0, 0x33, 0xa2, 0x11, 0xa0, 0xa4, 0x91, 0x98, 0x96, 0x88, 0xed, 0x01, @@ -3634,58 +3634,58 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x36, 0x16, 0x43, 0x14, 0xa2, 0x85, 0xb1, 0x9f, 0x44, 0x7a, 0x6a, 0xf7, 0x8b, 0xa8, 0x63, 0x84, 0xe7, 0x2e, 0x8e, 0x40, 0xbb, 0x60, 0xb2, 0xd8, 0xed, 0x3a, 0x06, 0xb0, 0x93, 0x12, 0x46, 0xf3, 0x4c, 0x91, 0xc8, 0x45, 0x3d, 0x95, 0x78, 0xf0, 0xa9, 0x53, 0x8d, 0x99, 0x83, 0xf0, 0x54, 0x31, 0xd4, 0xc0, 0xc7, 0x7a, 0xaf, 0x4d, 0xc8, 0x99, 0xff, - 0xaf, 0xbd, 0x67, 0x5b, 0x6e, 0xdb, 0x48, 0xf6, 0x3d, 0x5f, 0x01, 0xc1, 0x5e, 0x1b, 0xb0, 0x01, 0x08, 0x20, 0x75, - 0xa1, 0x49, 0x81, 0x4a, 0x6c, 0xcb, 0x49, 0x76, 0x95, 0x38, 0x65, 0x2b, 0xde, 0x8b, 0x56, 0x25, 0x82, 0xe4, 0x90, - 0xc4, 0x1a, 0x04, 0x58, 0x00, 0x28, 0x4a, 0xa1, 0xb1, 0xdf, 0xb2, 0x9f, 0x70, 0xbe, 0x61, 0xbf, 0xec, 0x54, 0x77, - 0xcf, 0x00, 0x83, 0x0b, 0x29, 0x2a, 0x76, 0xb2, 0x7b, 0xaa, 0x4e, 0x25, 0xb6, 0x89, 0xc1, 0xcc, 0xa0, 0xe7, 0xd6, - 0xdd, 0xd3, 0xd7, 0x32, 0xa5, 0xb4, 0x2b, 0xf8, 0x57, 0x58, 0x21, 0x57, 0x4a, 0x69, 0xcb, 0x81, 0x98, 0xd3, 0xed, - 0xe3, 0xaa, 0x81, 0x55, 0xa1, 0xb8, 0x27, 0x83, 0x99, 0x60, 0x65, 0xd7, 0x89, 0x79, 0x98, 0x75, 0x69, 0xc3, 0x1b, - 0x81, 0x0b, 0xa6, 0x87, 0x1b, 0x6a, 0x8d, 0xbb, 0x5e, 0x29, 0x14, 0x66, 0x5c, 0x9e, 0xd4, 0x13, 0xaf, 0xfc, 0x0c, - 0x5b, 0xba, 0x52, 0x05, 0x7c, 0x63, 0x2a, 0x95, 0x40, 0x0a, 0x16, 0x9c, 0xd2, 0xe7, 0xad, 0x34, 0x3a, 0x8f, 0x56, - 0x42, 0x70, 0x7c, 0xe2, 0x35, 0x14, 0xe2, 0x39, 0xe9, 0x8e, 0x4e, 0x02, 0xfa, 0xe1, 0x64, 0x1b, 0x28, 0x40, 0x56, - 0x4c, 0x70, 0xce, 0xb6, 0x0e, 0xe8, 0x32, 0x75, 0xfd, 0x78, 0x2d, 0xb6, 0x5c, 0x36, 0xf0, 0xf3, 0xb4, 0xb0, 0x25, - 0x96, 0x23, 0xe3, 0x53, 0x2f, 0x47, 0x21, 0x6d, 0xa8, 0xc6, 0xf7, 0x87, 0xeb, 0x37, 0xf2, 0x2d, 0x16, 0x3d, 0x32, - 0xa2, 0xe9, 0xcd, 0x55, 0xd8, 0x2d, 0x1b, 0x69, 0x4d, 0x80, 0x91, 0xe0, 0x49, 0x0c, 0x01, 0x03, 0x33, 0x23, 0xea, - 0xff, 0x36, 0xae, 0xa2, 0x7e, 0xb4, 0xbf, 0xcb, 0x91, 0xff, 0x4f, 0x6f, 0xdf, 0x5f, 0x80, 0x5e, 0xcb, 0x43, 0x45, - 0xf4, 0x5a, 0xe5, 0x36, 0x2c, 0x26, 0x68, 0x8a, 0xd4, 0xae, 0xea, 0x2d, 0x80, 0x3a, 0xe3, 0x8d, 0x61, 0xff, 0xd6, - 0x5c, 0xad, 0x56, 0x26, 0x58, 0xb4, 0x9a, 0xcb, 0x38, 0x20, 0xee, 0x70, 0xac, 0x66, 0x02, 0xa9, 0xb3, 0x0a, 0x52, - 0x87, 0x70, 0xb8, 0x3c, 0x9f, 0xca, 0xfb, 0x59, 0xb4, 0xfa, 0x26, 0x08, 0x64, 0xb1, 0x8d, 0x60, 0xe2, 0xb8, 0x24, - 0xa3, 0x84, 0x0c, 0x34, 0xd0, 0x3e, 0x59, 0x7e, 0x72, 0xcd, 0xed, 0x05, 0xc6, 0xd7, 0xc3, 0xbb, 0x6b, 0xae, 0x93, - 0xc8, 0xe3, 0x11, 0xbf, 0x1f, 0x9c, 0x8c, 0xfd, 0x1b, 0x05, 0x39, 0x4d, 0x57, 0x05, 0x67, 0xae, 0x80, 0x0d, 0x97, - 0x69, 0x1a, 0x85, 0x66, 0x1c, 0xad, 0xd4, 0xfe, 0x09, 0x3d, 0x88, 0x0a, 0x1e, 0x3d, 0xaa, 0xca, 0xd7, 0xa3, 0xc0, - 0x1f, 0x7d, 0x74, 0xd5, 0xc7, 0x6b, 0xdf, 0xed, 0x57, 0xf8, 0x49, 0x3b, 0x53, 0xfb, 0x00, 0xab, 0xf2, 0x4d, 0x10, - 0x9c, 0xec, 0x53, 0x8b, 0xfe, 0xc9, 0xfe, 0xd8, 0xbf, 0xe9, 0x4b, 0xa9, 0x61, 0xb8, 0xde, 0xd4, 0xe5, 0x21, 0x38, - 0x73, 0x4b, 0xb3, 0x04, 0x63, 0x3a, 0x8c, 0x98, 0x56, 0x5c, 0x7e, 0x21, 0xd6, 0x0c, 0xc1, 0xab, 0x8d, 0x50, 0x9c, - 0x1e, 0xc0, 0x55, 0xef, 0xd3, 0x27, 0x2d, 0xb7, 0x43, 0x9d, 0x49, 0x41, 0xda, 0x50, 0xcd, 0x87, 0x55, 0x0c, 0x8c, - 0x34, 0xa3, 0x6b, 0x22, 0x94, 0x5c, 0xa0, 0x1b, 0xa3, 0xcc, 0xc0, 0x0c, 0x3b, 0xde, 0x02, 0x34, 0x8e, 0xfc, 0xa7, - 0x74, 0x23, 0x1e, 0x41, 0x56, 0x6d, 0x09, 0x89, 0xeb, 0x92, 0xce, 0x85, 0x4e, 0x21, 0x8f, 0x13, 0x08, 0xca, 0x12, - 0xfc, 0x0e, 0xe9, 0x41, 0xb4, 0x40, 0x87, 0xac, 0x6e, 0x79, 0x70, 0x1e, 0x2f, 0x13, 0x79, 0xd4, 0xc4, 0xbc, 0x9c, - 0x96, 0x56, 0xa8, 0x5b, 0x5d, 0x2f, 0x11, 0x35, 0x72, 0x2f, 0xd9, 0xb4, 0x64, 0xa0, 0xc3, 0xd3, 0x52, 0xa3, 0x42, - 0x73, 0xc1, 0xab, 0x4f, 0x52, 0x1c, 0x31, 0x43, 0xbb, 0x4c, 0x8c, 0xe8, 0xaa, 0xa0, 0x53, 0x09, 0x21, 0xca, 0x6e, - 0x94, 0x15, 0x01, 0x9c, 0x69, 0xd5, 0xfb, 0x8f, 0xd7, 0x21, 0x12, 0xb6, 0xc4, 0xed, 0x97, 0xf7, 0x41, 0xea, 0x0d, - 0x4d, 0xda, 0xcc, 0xaa, 0xf2, 0xf5, 0x78, 0x18, 0xe4, 0x8b, 0x4d, 0x87, 0x60, 0xe6, 0x85, 0xe3, 0x80, 0x5d, 0x78, - 0xc3, 0xef, 0xb0, 0xce, 0xeb, 0x61, 0xf0, 0x0a, 0x2a, 0x64, 0x6a, 0xff, 0xf1, 0x9a, 0x48, 0x77, 0x13, 0xc2, 0xce, - 0x68, 0x0b, 0x54, 0xbf, 0xc3, 0x53, 0x2e, 0xb1, 0x98, 0x5a, 0x23, 0xb0, 0x44, 0x6e, 0x29, 0x8e, 0x6d, 0x19, 0x32, - 0x9e, 0xf2, 0x07, 0xf6, 0xa6, 0xc2, 0x4f, 0x2d, 0xc0, 0x15, 0x89, 0x13, 0x2c, 0xef, 0x4c, 0x19, 0x58, 0x22, 0xab, - 0xef, 0xa2, 0x95, 0x80, 0x94, 0x4f, 0x00, 0x85, 0xa8, 0x3c, 0x7d, 0x3f, 0x38, 0x91, 0xd5, 0x42, 0x28, 0x3b, 0xa7, - 0x7e, 0xe1, 0x57, 0xa6, 0x2a, 0x45, 0x02, 0xa8, 0xc5, 0xad, 0xda, 0x3f, 0xd9, 0x97, 0x6b, 0xf7, 0x07, 0xdd, 0x33, - 0x69, 0x70, 0xd8, 0xab, 0xb8, 0x37, 0x5f, 0x16, 0x0f, 0xd9, 0x95, 0x02, 0xb7, 0xe4, 0x0c, 0x4a, 0x60, 0x8e, 0xca, - 0x4d, 0x6a, 0xe4, 0x07, 0x52, 0x26, 0x16, 0x04, 0x8a, 0x76, 0x8f, 0xc0, 0x8f, 0x91, 0xde, 0xcd, 0x97, 0x90, 0x2c, - 0x33, 0x45, 0x6f, 0x03, 0xfe, 0x6f, 0x31, 0x25, 0x28, 0xe9, 0x66, 0x61, 0x12, 0xc5, 0x2a, 0x0c, 0xb3, 0x9a, 0x37, - 0x49, 0x91, 0xf2, 0xb5, 0xe1, 0x80, 0x1b, 0xc9, 0x2a, 0x4c, 0xd8, 0x7e, 0xb5, 0xa9, 0x34, 0xee, 0x81, 0x5e, 0xfc, - 0x50, 0xf8, 0x60, 0x2a, 0x48, 0x2b, 0x07, 0x70, 0x73, 0x3e, 0xaa, 0xcb, 0xc7, 0xbe, 0xf1, 0xe7, 0xc8, 0x18, 0x7a, - 0xc6, 0xb5, 0x67, 0xfc, 0x10, 0x5e, 0x65, 0x8d, 0x8b, 0x97, 0xe7, 0x92, 0x33, 0x58, 0x4f, 0x83, 0x08, 0x4c, 0xe5, - 0x4b, 0x85, 0x6f, 0x71, 0x9b, 0x91, 0x0b, 0x2f, 0x9e, 0x32, 0x91, 0xc2, 0x4d, 0xbc, 0x15, 0xb2, 0x03, 0x5d, 0x9a, - 0x16, 0x08, 0x4f, 0xb6, 0xc7, 0x4d, 0xeb, 0x7c, 0x6b, 0x94, 0xc6, 0xc1, 0x9f, 0xd8, 0x1d, 0xb0, 0x59, 0x49, 0x1a, - 0x2d, 0x40, 0x66, 0xe5, 0x4d, 0xb9, 0x0e, 0xc2, 0xd0, 0xd8, 0x6e, 0x9f, 0xfb, 0xf4, 0x89, 0x49, 0x59, 0xc5, 0xd2, - 0x68, 0x3a, 0x0d, 0x98, 0x26, 0x65, 0x1f, 0xcb, 0x3f, 0x73, 0xba, 0x67, 0x8b, 0xc8, 0xd5, 0x7a, 0xb6, 0xe9, 0x60, + 0xaf, 0xbd, 0xa7, 0xdd, 0x6e, 0x13, 0x49, 0xf6, 0xff, 0x3c, 0x05, 0x26, 0xd9, 0x04, 0x12, 0xc0, 0x20, 0xf9, 0x43, + 0x91, 0x8c, 0x3c, 0x93, 0xc4, 0x99, 0x8f, 0xf5, 0x4c, 0xe6, 0x24, 0x9e, 0xec, 0xbd, 0xeb, 0xf5, 0xb1, 0x90, 0xd4, + 0x92, 0xd8, 0x20, 0xd0, 0x01, 0x64, 0xd9, 0xa3, 0xb0, 0xcf, 0xb2, 0x8f, 0x70, 0x9f, 0x61, 0x9f, 0xec, 0x9e, 0xaa, + 0xea, 0x86, 0x06, 0x81, 0x2c, 0x4f, 0x32, 0xb3, 0x7b, 0xcf, 0xb9, 0x67, 0x26, 0x89, 0x68, 0xba, 0x9b, 0xea, 0xaf, + 0xaa, 0xea, 0xfa, 0x2c, 0x53, 0x4a, 0xbb, 0x82, 0x7f, 0x85, 0x15, 0x72, 0xa5, 0x94, 0xb6, 0x1c, 0x88, 0x39, 0xdd, + 0x3e, 0xae, 0x1a, 0x58, 0x15, 0x8a, 0x7b, 0x32, 0x98, 0x09, 0x56, 0x76, 0x9d, 0x98, 0x87, 0x59, 0x97, 0x36, 0xbc, + 0x11, 0xb8, 0x60, 0x7a, 0xd8, 0x50, 0x6b, 0xdc, 0xf5, 0x4a, 0xa1, 0x30, 0xe3, 0xf2, 0xa4, 0x9e, 0x78, 0xe5, 0x67, + 0xd8, 0xd2, 0x95, 0x2a, 0xe0, 0x1b, 0x53, 0xa9, 0x04, 0x52, 0xb0, 0xe0, 0x94, 0x3e, 0x6f, 0xa5, 0xd1, 0x79, 0xb4, + 0x12, 0x82, 0xe3, 0x13, 0xaf, 0xa6, 0x10, 0xcf, 0x49, 0x77, 0x74, 0x12, 0xd0, 0x0f, 0x27, 0x6b, 0xa0, 0x00, 0x59, + 0x31, 0xc1, 0x39, 0xdb, 0x3a, 0xa0, 0xcb, 0xd4, 0xf5, 0xe3, 0xb5, 0xd8, 0x72, 0xd9, 0xc0, 0xcf, 0xd3, 0xc2, 0x96, + 0x58, 0x8e, 0x8c, 0x4f, 0xbd, 0x1c, 0x85, 0xb4, 0xa6, 0x1a, 0xdf, 0x1f, 0xae, 0x5f, 0xcb, 0xb7, 0x58, 0xf4, 0xc8, + 0x88, 0xa6, 0xd7, 0x57, 0x61, 0xb7, 0x6c, 0xa4, 0xd5, 0x01, 0x46, 0x82, 0x27, 0x31, 0x04, 0x0c, 0xcc, 0x8c, 0xa8, + 0xff, 0xdb, 0xb8, 0x8a, 0xfa, 0xd1, 0xfe, 0x2e, 0x47, 0xfe, 0x3f, 0xbf, 0x7d, 0x7f, 0x01, 0x7a, 0x2d, 0x0f, 0x15, + 0xd1, 0x6b, 0x95, 0xdb, 0xb0, 0x98, 0xa0, 0x29, 0x52, 0xbb, 0xaa, 0xb7, 0x00, 0xea, 0x8c, 0x37, 0x86, 0xfd, 0x5b, + 0x73, 0xb5, 0x5a, 0x99, 0x60, 0xd1, 0x6a, 0x2e, 0xe3, 0x80, 0xb8, 0xc3, 0xb1, 0x9a, 0x09, 0xa4, 0xce, 0x2a, 0x48, + 0x1d, 0xc2, 0xe1, 0xf2, 0x7c, 0x2a, 0xef, 0x67, 0xd1, 0xea, 0x9b, 0x20, 0x90, 0xc5, 0x36, 0x82, 0x89, 0xe3, 0x92, + 0x8c, 0x12, 0x32, 0xd0, 0x40, 0xfb, 0x64, 0xf9, 0xc9, 0x35, 0xb7, 0x17, 0x18, 0x5f, 0x0f, 0xef, 0xae, 0xb9, 0x4e, + 0x22, 0x8f, 0x47, 0xfc, 0x7e, 0x70, 0x32, 0xf6, 0x6f, 0x14, 0xe4, 0x34, 0x5d, 0x15, 0x9c, 0xb9, 0x02, 0x36, 0x5c, + 0xa6, 0x69, 0x14, 0x9a, 0x71, 0xb4, 0x52, 0xfb, 0x27, 0xf4, 0x20, 0x2a, 0x78, 0xf4, 0xa8, 0x2a, 0x5f, 0x8f, 0x02, + 0x7f, 0xf4, 0xd1, 0x55, 0x1f, 0xaf, 0x7d, 0xb7, 0x5f, 0xe1, 0x27, 0xed, 0x4c, 0xed, 0x03, 0xac, 0xca, 0x37, 0x41, + 0x70, 0xb2, 0x4f, 0x2d, 0xfa, 0x27, 0xfb, 0x63, 0xff, 0xa6, 0x2f, 0xa5, 0x86, 0xe1, 0x7a, 0x53, 0x97, 0x87, 0xe0, + 0xcc, 0x2d, 0xcd, 0x12, 0x8c, 0xe9, 0x30, 0x62, 0x5a, 0x71, 0xf9, 0x85, 0x58, 0x33, 0x04, 0xaf, 0x36, 0x42, 0x71, + 0x7a, 0x00, 0x57, 0xbd, 0x4f, 0x9f, 0xb4, 0xdc, 0x0e, 0x75, 0x26, 0x05, 0x69, 0x43, 0x35, 0x1f, 0x56, 0x31, 0x30, + 0xd2, 0x8c, 0xae, 0x89, 0x50, 0x72, 0x81, 0x6e, 0x8c, 0x32, 0x03, 0x33, 0xec, 0x78, 0x0b, 0xd0, 0x38, 0xf2, 0x9f, + 0xd2, 0x8d, 0x78, 0x04, 0x59, 0xb5, 0x25, 0x24, 0xae, 0x4b, 0x3a, 0x17, 0x3a, 0x85, 0x3c, 0x4e, 0x20, 0x28, 0x4b, + 0xf0, 0x3b, 0xa4, 0x07, 0xd1, 0x02, 0x1d, 0xb2, 0xba, 0xe5, 0xc1, 0x79, 0xbc, 0x4c, 0xe4, 0x51, 0x13, 0xf3, 0x72, + 0x5a, 0x5a, 0xa1, 0x6e, 0x75, 0xbd, 0x44, 0xd4, 0xc8, 0xbd, 0xa4, 0x69, 0xc9, 0x40, 0x87, 0xa7, 0xa5, 0x46, 0x85, + 0xe6, 0x82, 0x57, 0x9f, 0xa4, 0x38, 0x62, 0x86, 0x76, 0x99, 0x18, 0xd1, 0x55, 0x41, 0xa7, 0x12, 0x42, 0x94, 0xdd, + 0x28, 0x2b, 0x02, 0x38, 0xd3, 0xaa, 0xf7, 0x1f, 0xaf, 0x43, 0x24, 0x6c, 0x89, 0xdb, 0x2f, 0xef, 0x83, 0xd4, 0x1b, + 0x9a, 0xb4, 0x99, 0x55, 0xe5, 0xeb, 0xf1, 0x30, 0xc8, 0x17, 0x9b, 0x0e, 0xc1, 0xcc, 0x0b, 0xc7, 0x01, 0xbb, 0xf0, + 0x86, 0xdf, 0x61, 0x9d, 0xd7, 0xc3, 0xe0, 0x15, 0x54, 0xc8, 0xd4, 0xfe, 0xe3, 0x35, 0x91, 0xee, 0x3a, 0x84, 0x9d, + 0xd1, 0x16, 0xa8, 0x7e, 0x87, 0xa7, 0x5c, 0x62, 0x31, 0xb5, 0x46, 0x60, 0x89, 0xdc, 0x52, 0x1c, 0xdb, 0x32, 0x64, + 0x3c, 0xe5, 0x0f, 0xec, 0x4d, 0x85, 0x9f, 0x5a, 0x80, 0x2b, 0x12, 0x27, 0x58, 0xde, 0x99, 0x32, 0xb0, 0x44, 0x56, + 0xdf, 0x45, 0x2b, 0x01, 0x29, 0x9f, 0x00, 0x0a, 0x51, 0x79, 0xfa, 0x7e, 0x70, 0x22, 0xab, 0x85, 0x50, 0x76, 0x4e, + 0xfd, 0xc2, 0xaf, 0x4c, 0x55, 0x8a, 0x04, 0x50, 0x8b, 0x5b, 0xb5, 0x7f, 0xb2, 0x2f, 0xd7, 0xee, 0x0f, 0xba, 0x67, + 0xd2, 0xe0, 0xb0, 0x57, 0x71, 0x6f, 0xbe, 0x2c, 0x1e, 0xb2, 0x2b, 0x05, 0x6e, 0xc9, 0x19, 0x94, 0xc0, 0x1c, 0x95, + 0x9b, 0x6c, 0x90, 0x1f, 0x48, 0x99, 0x58, 0x10, 0x28, 0xda, 0x3d, 0x02, 0x3f, 0x46, 0x7a, 0x37, 0x5f, 0x42, 0xb2, + 0xcc, 0x14, 0xbd, 0x0d, 0xf8, 0xbf, 0xc5, 0x94, 0xa0, 0xa4, 0x9b, 0x85, 0x49, 0x14, 0xab, 0x30, 0xcc, 0x6a, 0xde, + 0x24, 0x45, 0xca, 0xd7, 0x86, 0x03, 0xae, 0x25, 0xab, 0x30, 0x61, 0xfb, 0xd5, 0xa6, 0xd2, 0xb8, 0x07, 0x7a, 0xf1, + 0x43, 0xe1, 0x83, 0xa9, 0x20, 0xad, 0x1c, 0xc0, 0xe6, 0x7c, 0x54, 0x97, 0x8f, 0x7d, 0xe3, 0x2f, 0x91, 0x31, 0xf4, + 0x8c, 0x6b, 0xcf, 0xf8, 0x31, 0xbc, 0xca, 0x6a, 0x17, 0x2f, 0xcf, 0x25, 0x67, 0xb0, 0x9e, 0x06, 0x11, 0x98, 0xca, + 0x97, 0x0a, 0xdf, 0xe2, 0x36, 0x23, 0x17, 0x5e, 0x3c, 0x65, 0x22, 0x85, 0x9b, 0x78, 0x2b, 0x64, 0x07, 0xba, 0x34, + 0x2d, 0x10, 0x9e, 0x6c, 0x8f, 0x9b, 0xd6, 0xf9, 0xd6, 0x28, 0x8d, 0x83, 0x3f, 0xb3, 0x3b, 0x60, 0xb3, 0x92, 0x34, + 0x5a, 0x80, 0xcc, 0xca, 0x9b, 0x72, 0x1d, 0x84, 0xa1, 0xb1, 0xdd, 0x3e, 0xf7, 0xe9, 0x13, 0x93, 0xb2, 0x8a, 0xa5, + 0xd1, 0x74, 0x1a, 0x30, 0x4d, 0xca, 0x3e, 0x96, 0x7f, 0xe6, 0x74, 0xcf, 0x16, 0x91, 0xab, 0xf5, 0xac, 0xe9, 0x60, 0x89, 0x11, 0xb3, 0x9c, 0x1b, 0x04, 0xc4, 0x45, 0xc6, 0x55, 0xc8, 0x90, 0x6b, 0xe2, 0x5c, 0x14, 0x07, 0xd7, 0x1c, 0x47, 0xcb, 0x61, 0xc0, 0x4c, 0x3c, 0x0d, 0xf0, 0xc9, 0xf5, 0x70, 0x39, 0x1c, 0x06, 0x94, 0x2e, 0x0c, 0xe2, 0xaf, 0x45, 0x09, 0xca, 0x45, 0x33, 0xbd, 0x07, 0x83, 0xb2, 0xd2, 0x2a, 0xf8, 0x60, 0x33, 0x09, 0x37, 0x07, 0xfa, 0x40, - 0x0a, 0x32, 0xd0, 0xfa, 0x99, 0x76, 0x55, 0xb8, 0xb1, 0xb0, 0x44, 0xed, 0x35, 0xb0, 0x74, 0xee, 0xa5, 0xfa, 0x1e, - 0x67, 0x58, 0xf1, 0xc2, 0xb1, 0xf2, 0x8a, 0xf6, 0xae, 0x6a, 0xa8, 0x64, 0xfa, 0xc5, 0xb3, 0xcb, 0xa9, 0x86, 0xfa, - 0xda, 0xf7, 0xa6, 0x61, 0x94, 0xa4, 0xfe, 0x48, 0xbd, 0xea, 0xbd, 0xf6, 0xb5, 0xcb, 0x79, 0xaa, 0xe9, 0x57, 0xc6, - 0xb7, 0x72, 0x1e, 0x30, 0x81, 0x29, 0x31, 0x0d, 0xd8, 0x86, 0x3a, 0xf2, 0xe9, 0xd9, 0x56, 0x4f, 0x60, 0x64, 0xac, + 0x0a, 0x32, 0xd0, 0xcd, 0x33, 0xed, 0xaa, 0x70, 0x63, 0x61, 0x89, 0xda, 0xab, 0x61, 0xe9, 0xdc, 0x4b, 0xf5, 0x3d, + 0xce, 0xb0, 0xe2, 0x85, 0x63, 0xe5, 0x15, 0xed, 0x5d, 0xd5, 0x50, 0xc9, 0xf4, 0x8b, 0x67, 0x97, 0x53, 0x0d, 0xf5, + 0xb5, 0xef, 0x4d, 0xc3, 0x28, 0x49, 0xfd, 0x91, 0x7a, 0xd5, 0x7b, 0xed, 0x6b, 0x97, 0xf3, 0x54, 0xd3, 0xaf, 0x8c, + 0x6f, 0xe5, 0x3c, 0x60, 0x02, 0x53, 0x62, 0x1a, 0xb0, 0x86, 0x3a, 0xf2, 0xe9, 0xd9, 0x56, 0x4f, 0x60, 0x64, 0xac, 0xf3, 0xad, 0x0b, 0xb5, 0x2a, 0x19, 0xc5, 0x30, 0x55, 0x24, 0x64, 0x14, 0xfb, 0x56, 0xef, 0x91, 0x10, 0xe6, 0x9b, 0xe5, 0x1a, 0x99, 0x86, 0xb4, 0x20, 0xbe, 0x18, 0x04, 0x5f, 0x78, 0x8e, 0xd2, 0xf3, 0x9e, 0xec, 0xf5, 0x50, 0x22, 0xe3, 0x83, 0x6f, 0xca, 0x1c, 0xc8, 0xe3, 0x75, 0x9a, 0x81, 0xc9, 0x61, 0x18, 0xa5, 0x0a, 0x44, 0x76, 0x83, 0x0f, @@ -3695,3994 +3695,3997 @@ constexpr uint8_t INDEX_GZ[] PROGMEM = { 0xba, 0x25, 0xf4, 0xaa, 0x09, 0x76, 0x37, 0x16, 0x31, 0xf3, 0xb9, 0x18, 0x45, 0x30, 0x60, 0x95, 0xa3, 0x07, 0xc1, 0x9a, 0x72, 0xde, 0x2a, 0x05, 0x8b, 0x6b, 0x24, 0x18, 0x80, 0xb9, 0x38, 0x8f, 0x30, 0xc8, 0xae, 0x81, 0x91, 0x84, 0x08, 0x66, 0x62, 0x8c, 0x46, 0x24, 0x27, 0x91, 0xf3, 0xc3, 0xc5, 0x32, 0xc5, 0xc8, 0xf4, 0x00, 0x00, 0xcb, 0x54, - 0x05, 0x2f, 0x8c, 0x80, 0xeb, 0x8b, 0x0b, 0x4f, 0xa6, 0x2a, 0xfe, 0xb8, 0x5e, 0xc6, 0xa5, 0x33, 0x80, 0xe3, 0x70, - 0x18, 0xa8, 0xd7, 0x81, 0xc7, 0x98, 0x0f, 0x63, 0x64, 0x14, 0x69, 0x5d, 0xb4, 0x11, 0xda, 0x3f, 0x34, 0x20, 0x90, - 0x11, 0xf5, 0xd3, 0xd3, 0x82, 0xc6, 0xc1, 0x42, 0xb4, 0xea, 0xd2, 0x30, 0x07, 0x20, 0xa3, 0x3c, 0x85, 0xb9, 0x73, - 0xe1, 0x52, 0x2f, 0x4c, 0xeb, 0xd4, 0x0b, 0x95, 0xec, 0xea, 0x06, 0x38, 0x0d, 0x83, 0xec, 0xba, 0x70, 0x74, 0x2d, - 0xc6, 0x0b, 0x5b, 0x92, 0xca, 0x15, 0xb4, 0x74, 0x73, 0xb9, 0x3d, 0xdb, 0x22, 0xf6, 0xe7, 0x5e, 0x7c, 0x47, 0xe6, - 0x6f, 0x86, 0x6c, 0x23, 0xa7, 0xab, 0x0a, 0xd1, 0x03, 0x9a, 0x00, 0x22, 0x0d, 0xaa, 0xf2, 0x75, 0x5e, 0xc6, 0xf8, - 0x68, 0x73, 0x1b, 0x20, 0xf8, 0xd6, 0xb5, 0xfa, 0x9c, 0x59, 0x24, 0x7f, 0xa4, 0x26, 0x3d, 0x2d, 0xd9, 0x30, 0xbc, - 0xa4, 0x3c, 0xbc, 0xb0, 0xbc, 0xd1, 0x70, 0x30, 0x44, 0x29, 0x08, 0x6e, 0x1c, 0x19, 0x26, 0xc1, 0x6c, 0x5e, 0x51, - 0x7a, 0xf7, 0xbb, 0x2e, 0x07, 0x83, 0xe5, 0x08, 0x61, 0x39, 0x1a, 0x44, 0xb3, 0x9e, 0x58, 0x11, 0xe0, 0x45, 0x80, + 0x05, 0x2f, 0x8c, 0x80, 0xeb, 0x8b, 0x0b, 0x4f, 0xa6, 0x2a, 0xfe, 0x78, 0xb3, 0x8c, 0x4b, 0x67, 0x00, 0xc7, 0xe1, + 0x30, 0x50, 0xaf, 0x03, 0x8f, 0x31, 0x1f, 0xc6, 0xc8, 0x28, 0xd2, 0xba, 0x68, 0x23, 0xb4, 0x7f, 0xa8, 0x41, 0x20, + 0x23, 0xea, 0xa7, 0xa7, 0x05, 0xb5, 0x83, 0x85, 0x68, 0xd5, 0xa5, 0x61, 0x0e, 0x40, 0x46, 0x79, 0x0a, 0x73, 0xe7, + 0xc2, 0xa5, 0x5e, 0x98, 0xd6, 0xa9, 0x17, 0x2a, 0xd9, 0xd5, 0x0d, 0x70, 0x1a, 0x06, 0xd9, 0x75, 0xe1, 0xe8, 0x5a, + 0x8c, 0x17, 0xb6, 0x24, 0x95, 0x2b, 0x68, 0xe9, 0xe6, 0x72, 0x7b, 0xb6, 0x45, 0xec, 0xcf, 0xbd, 0xf8, 0x8e, 0xcc, + 0xdf, 0x0c, 0xd9, 0x46, 0x4e, 0x57, 0x15, 0xa2, 0x07, 0x34, 0x01, 0x44, 0x1a, 0x54, 0xe5, 0xeb, 0xbc, 0x8c, 0xf1, + 0xd1, 0xe6, 0x36, 0x40, 0xf0, 0xad, 0x6b, 0xf5, 0x39, 0xb3, 0x48, 0xfe, 0x48, 0x4d, 0x7a, 0x5a, 0xd2, 0x30, 0xbc, + 0xa4, 0x3c, 0xbc, 0xb0, 0xbc, 0xd1, 0x70, 0x30, 0x44, 0x29, 0x08, 0x6e, 0x1c, 0x19, 0x26, 0xc1, 0xac, 0x5f, 0x51, + 0x7a, 0xf7, 0x87, 0x2e, 0x07, 0x83, 0xe5, 0x08, 0x61, 0x39, 0x6a, 0x44, 0xb3, 0x9e, 0x58, 0x11, 0xe0, 0x45, 0x80, 0x0b, 0x89, 0x91, 0x03, 0xa1, 0xfc, 0x98, 0x4a, 0xbe, 0x85, 0x62, 0x38, 0x1a, 0x04, 0x3b, 0x1d, 0x8d, 0xd8, 0x75, 0x23, 0x6c, 0x15, 0x67, 0x27, 0xfb, 0x54, 0x9b, 0x88, 0x22, 0x55, 0x82, 0x69, 0x88, 0x61, 0x84, 0xc5, 0x2c, 0x40, 0x82, 0x70, 0xd7, 0x29, 0x2e, 0x3a, 0xd6, 0x1c, 0xd5, 0xd2, 0xce, 0x69, 0x99, 0xe1, 0xc1, 0x56, 0x6a, 0xff, 0x04, 0x53, 0x7e, 0x02, 0x59, 0x87, 0xa0, 0x58, 0x27, 0xfb, 0xf4, 0xa8, 0x54, 0x4e, 0x44, 0xd1, 0x89, 0x90, 0x41, 0x76, 0x79, 0x07, 0x0f, 0x3a, 0x2a, 0x49, 0xca, 0x16, 0x50, 0xea, 0x65, 0xaa, 0x32, 0xe7, 0x0c, 0x16, 0x8f, 0xbe, 0x07, 0xa1, 0x79, 0x6c, 0x70, 0x89, 0x50, 0x95, 0xb9, 0x77, 0x8b, 0x23, 0x17, 0x6f, 0xbc, 0x5b, 0xcd, 0xe1, 0xaf, 0x8a, - 0xb3, 0x96, 0x94, 0xcf, 0xda, 0xa8, 0x76, 0x43, 0x0e, 0xe0, 0x86, 0x3c, 0x6a, 0x5e, 0xdc, 0x99, 0x58, 0xdc, 0xf1, + 0xb3, 0x96, 0x94, 0xcf, 0xda, 0x68, 0xe3, 0x86, 0x1c, 0xc0, 0x0d, 0x79, 0x54, 0xbf, 0xb8, 0x33, 0xb1, 0xb8, 0xe3, 0x86, 0xc5, 0x1d, 0x6f, 0x59, 0xdc, 0x80, 0x2f, 0xa4, 0x92, 0x4f, 0x5d, 0x8c, 0xbe, 0xd4, 0xf9, 0xe4, 0x71, 0x7e, - 0xa4, 0xcb, 0xcf, 0x19, 0xce, 0x93, 0x99, 0x04, 0x60, 0x4b, 0xbc, 0x61, 0xae, 0x9a, 0xe6, 0x45, 0x9a, 0x88, 0xfa, - 0xc0, 0xf3, 0x53, 0x27, 0xc6, 0x0d, 0x29, 0xbc, 0xb5, 0xa0, 0x3a, 0x5e, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x1b, - 0x46, 0x3a, 0xdb, 0x32, 0xd2, 0x51, 0xe9, 0xe8, 0xf2, 0x61, 0xd3, 0x21, 0x94, 0x07, 0x05, 0x7b, 0x10, 0xfc, 0x2b, - 0x70, 0xcb, 0x94, 0xf7, 0xe1, 0x66, 0x1c, 0x2b, 0xed, 0xa8, 0x85, 0x97, 0x24, 0xab, 0x28, 0x06, 0x03, 0x05, 0xe8, - 0xe6, 0x61, 0x5b, 0x6a, 0xee, 0x87, 0x3c, 0xf6, 0xd9, 0xc6, 0xcd, 0x54, 0xbc, 0x97, 0xb7, 0x54, 0xeb, 0xf0, 0x90, - 0x6a, 0x2c, 0xbc, 0x34, 0x65, 0x31, 0x4e, 0xba, 0x07, 0x49, 0x32, 0xfe, 0x4b, 0xb6, 0x59, 0x03, 0x0e, 0x09, 0x24, - 0xac, 0x8e, 0x18, 0x7a, 0x01, 0x2c, 0x18, 0x69, 0x24, 0x43, 0x7d, 0x2d, 0xc5, 0x51, 0x8d, 0xf3, 0x89, 0xff, 0x11, - 0x8f, 0xab, 0x16, 0x4b, 0x9e, 0xbe, 0xce, 0x91, 0x6e, 0x2d, 0xbc, 0xf1, 0x7b, 0xb0, 0x83, 0xd1, 0x5a, 0x06, 0xf8, - 0xb4, 0xc8, 0x51, 0x53, 0x63, 0xe2, 0x09, 0x47, 0x05, 0x92, 0x44, 0x2c, 0xc9, 0x2d, 0x86, 0x21, 0xd8, 0x80, 0x67, - 0x4e, 0xae, 0xd6, 0xad, 0x6c, 0x7f, 0xea, 0xeb, 0x35, 0xac, 0x09, 0xa8, 0x2d, 0x70, 0xfb, 0xb9, 0xd0, 0x2d, 0x30, - 0x9c, 0x23, 0x1d, 0x14, 0xa5, 0x97, 0x90, 0x0e, 0xdd, 0x16, 0x97, 0xe9, 0x41, 0x0c, 0x54, 0x0b, 0xd4, 0x8a, 0x4f, - 0xa6, 0xf8, 0xcb, 0xb9, 0xca, 0x9e, 0x0c, 0xf1, 0x57, 0xeb, 0x2a, 0x57, 0x62, 0x55, 0xa4, 0x08, 0xd2, 0x98, 0xd5, - 0x7e, 0x69, 0x3f, 0x91, 0xb9, 0xf6, 0x03, 0xb6, 0x0d, 0x5f, 0xe0, 0x47, 0x8f, 0xd7, 0x09, 0x04, 0x28, 0x90, 0xc7, - 0x10, 0x5a, 0xb1, 0x9e, 0x35, 0x96, 0x4f, 0x37, 0x94, 0x0f, 0xf5, 0xdf, 0x99, 0xf0, 0xe3, 0x2e, 0x89, 0x0a, 0x9a, - 0x52, 0x96, 0x81, 0x5c, 0x0f, 0xfd, 0xd0, 0x8b, 0xef, 0xae, 0xe9, 0x16, 0xa2, 0x09, 0x16, 0x3f, 0x97, 0xed, 0x10, - 0x2f, 0x5a, 0xb6, 0x0e, 0x49, 0x25, 0x45, 0xd5, 0x1d, 0x27, 0xf4, 0xee, 0x9f, 0x62, 0x89, 0xbf, 0x2b, 0x5d, 0x63, - 0xf9, 0x82, 0x94, 0x3e, 0x74, 0xfd, 0x78, 0xad, 0xb1, 0x7a, 0x37, 0x95, 0xd1, 0x56, 0x18, 0x48, 0x58, 0x1e, 0xbc, - 0x12, 0xcf, 0xc7, 0x7e, 0x17, 0xcd, 0x3f, 0x86, 0xd1, 0xad, 0xf9, 0x78, 0x9d, 0x9e, 0xaa, 0x73, 0x2f, 0xfe, 0xc8, - 0xc6, 0xe6, 0xc8, 0x8f, 0x47, 0x01, 0x30, 0x8f, 0xc3, 0xc0, 0x0b, 0x3f, 0xf2, 0x47, 0x33, 0x5a, 0xa6, 0x68, 0xd0, - 0x75, 0xef, 0x0d, 0x5a, 0xcc, 0x09, 0x09, 0x12, 0x91, 0xab, 0x6d, 0x98, 0x05, 0xe5, 0xfd, 0x40, 0x5c, 0xeb, 0x0b, - 0x46, 0xb1, 0xa8, 0x65, 0x80, 0x3f, 0x02, 0xd8, 0x98, 0x41, 0x80, 0x07, 0x43, 0xc5, 0xf5, 0x52, 0x0d, 0x79, 0xa8, - 0xa4, 0x55, 0xcb, 0x33, 0x14, 0x5f, 0x63, 0x0f, 0xbf, 0xfe, 0x73, 0x50, 0xf2, 0x90, 0xcf, 0xe5, 0xbd, 0x7c, 0xde, - 0x08, 0xa1, 0xd4, 0x24, 0xc7, 0xc2, 0x07, 0x7c, 0x9c, 0x33, 0x98, 0x9b, 0x3f, 0x2d, 0x37, 0xf6, 0x92, 0x64, 0x39, - 0x67, 0x63, 0x52, 0x89, 0x9d, 0x16, 0x40, 0x95, 0xef, 0x21, 0x32, 0x60, 0x7f, 0x5f, 0xb6, 0x8e, 0x0f, 0x5e, 0x81, - 0x81, 0x1f, 0x30, 0x94, 0xd1, 0x64, 0xa2, 0x16, 0xa2, 0x80, 0x7b, 0x9a, 0x39, 0x07, 0x7f, 0x5f, 0xbe, 0x39, 0xb3, - 0xdf, 0xe4, 0x8d, 0x43, 0x60, 0x8c, 0x85, 0xb5, 0x12, 0xe7, 0x8b, 0x25, 0x78, 0xc5, 0x88, 0x26, 0x5e, 0xb8, 0x79, - 0x38, 0x97, 0xa5, 0x2d, 0xbe, 0x60, 0x6c, 0x0c, 0x0c, 0xb7, 0x51, 0x2b, 0xbd, 0x0e, 0xd8, 0x0d, 0xcb, 0x2d, 0xa1, - 0xea, 0x1f, 0x6b, 0x68, 0x81, 0xa1, 0x5a, 0xb9, 0xee, 0x91, 0x73, 0x75, 0xd2, 0x90, 0x06, 0x38, 0x06, 0x3e, 0x72, - 0xf9, 0x88, 0x55, 0x8e, 0xd4, 0xc0, 0x50, 0x25, 0x00, 0x36, 0x42, 0x76, 0xba, 0xa1, 0xbc, 0x0b, 0x88, 0x7a, 0x03, - 0x6c, 0x86, 0xa3, 0x77, 0x21, 0xb5, 0x05, 0x9f, 0xa7, 0x00, 0x4e, 0x9e, 0x56, 0x48, 0x4d, 0x36, 0xcd, 0x58, 0x93, - 0xa8, 0x4d, 0x25, 0x21, 0x8d, 0x70, 0x0e, 0x40, 0x2f, 0x19, 0x21, 0xae, 0x6a, 0x5c, 0x1b, 0xa5, 0x3c, 0xf2, 0x21, - 0x26, 0x7e, 0x0f, 0x59, 0x92, 0x6c, 0x9c, 0xb0, 0x7c, 0xd1, 0x0d, 0xb5, 0xa8, 0x5d, 0x9e, 0x8f, 0xa2, 0xdc, 0xb0, - 0x0d, 0x60, 0x09, 0x70, 0x80, 0xd5, 0x6f, 0x21, 0x79, 0xb9, 0x9e, 0x73, 0xf3, 0xce, 0x78, 0x3a, 0x54, 0xb9, 0xe9, - 0xdd, 0xa6, 0xf7, 0x2b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0x8d, 0xa0, 0x69, 0x25, 0xd4, 0x5b, 0x93, 0x2a, 0x61, 0x07, - 0x02, 0xa6, 0x0a, 0x7e, 0x65, 0x93, 0x09, 0x1b, 0xa5, 0x89, 0x2e, 0x64, 0x4c, 0x79, 0xb0, 0x75, 0x70, 0xb2, 0xdd, - 0x73, 0xd5, 0x1f, 0x21, 0xe4, 0x8c, 0x88, 0x49, 0xc8, 0x01, 0x12, 0x77, 0xa6, 0xe6, 0x69, 0xa2, 0x1e, 0xcb, 0x53, - 0xc4, 0xbf, 0x02, 0x52, 0xe8, 0x86, 0x72, 0x04, 0x8d, 0xd3, 0x9f, 0x62, 0x5f, 0x44, 0xb9, 0x11, 0xe8, 0x76, 0x54, - 0xb4, 0xed, 0xf8, 0xae, 0x9d, 0x37, 0x87, 0x8e, 0x9d, 0xa9, 0x06, 0xb8, 0x3a, 0x7f, 0xac, 0x6c, 0x63, 0x22, 0x50, - 0xae, 0x7a, 0xfe, 0xf6, 0xd5, 0x9f, 0xce, 0x5e, 0xef, 0x8a, 0x11, 0xb0, 0xcb, 0x36, 0x74, 0xb9, 0x0c, 0xb7, 0x74, - 0xfa, 0xf3, 0x8f, 0x0f, 0xeb, 0xb6, 0xe5, 0xbc, 0x70, 0x54, 0x83, 0xac, 0xd3, 0x25, 0xbc, 0x38, 0x8a, 0x6e, 0x58, - 0xfc, 0xd9, 0xd3, 0x20, 0x77, 0xde, 0x0c, 0xee, 0xdb, 0x9f, 0xce, 0x7e, 0xdc, 0x19, 0xd4, 0x23, 0xc7, 0x06, 0xdc, - 0x9e, 0x46, 0x8b, 0x07, 0x8c, 0xae, 0xad, 0x1a, 0xea, 0x28, 0x88, 0x12, 0xb6, 0x01, 0x82, 0x57, 0xe7, 0x6f, 0xdf, - 0xe3, 0x74, 0x15, 0x2c, 0x08, 0x75, 0xf5, 0x79, 0x83, 0xff, 0xe9, 0xdd, 0xd9, 0xfb, 0xf7, 0xaa, 0x81, 0xc9, 0xba, - 0x13, 0xb9, 0x77, 0xbe, 0x89, 0xef, 0xa1, 0x38, 0x8d, 0x7b, 0x9d, 0xa8, 0x1a, 0x5d, 0xa4, 0xcb, 0xa3, 0xa1, 0xb2, - 0xda, 0x36, 0xe7, 0xd4, 0x8e, 0x7f, 0x99, 0x6e, 0xbf, 0x3b, 0x8d, 0xab, 0x01, 0x1f, 0x6d, 0x27, 0xa9, 0xa5, 0x92, - 0xb9, 0x1f, 0x5e, 0x37, 0x94, 0x7a, 0xb7, 0x0d, 0xa5, 0x70, 0x7d, 0xac, 0xe1, 0xc7, 0x65, 0x34, 0x97, 0xd8, 0x11, - 0x76, 0x7b, 0xff, 0x74, 0x49, 0x77, 0xb8, 0xcf, 0x00, 0x9a, 0x27, 0x5b, 0xa9, 0x42, 0xdd, 0x50, 0xcc, 0x2f, 0x5e, - 0xf9, 0xdc, 0x8e, 0x02, 0xb0, 0xc9, 0x67, 0xb2, 0x1a, 0xb2, 0xcc, 0xaa, 0x72, 0x8f, 0x1a, 0xb7, 0x72, 0x2b, 0xa0, - 0x66, 0xa4, 0xba, 0xe1, 0x34, 0x65, 0xe1, 0x8d, 0xc1, 0xd0, 0xdd, 0x1c, 0x46, 0x69, 0x1a, 0xcd, 0xbb, 0x8e, 0xbd, - 0xb8, 0x55, 0x95, 0x9e, 0x10, 0x76, 0x70, 0x3b, 0xfc, 0xee, 0xbf, 0xff, 0x55, 0x41, 0xf3, 0x54, 0x7e, 0x9d, 0xb2, - 0xf9, 0x82, 0xc5, 0x5e, 0xba, 0x8c, 0x59, 0xa6, 0xfc, 0xfb, 0x7f, 0x5e, 0x55, 0x2e, 0xf6, 0x3d, 0xb9, 0x0d, 0xb1, - 0xf4, 0x72, 0x93, 0xeb, 0x20, 0x5a, 0xed, 0x15, 0x1e, 0x77, 0xf7, 0x54, 0x9e, 0xf9, 0xd3, 0x59, 0x5e, 0xfb, 0x34, - 0xdd, 0x32, 0x36, 0x01, 0x3d, 0xe9, 0x03, 0x94, 0xf3, 0x68, 0xd5, 0xfd, 0xf7, 0xbf, 0x72, 0x81, 0xcd, 0xbd, 0xbb, - 0xae, 0x19, 0xd0, 0xf2, 0x8a, 0x36, 0xd7, 0xa9, 0x2d, 0x31, 0xbc, 0xaf, 0x2d, 0x70, 0xad, 0x90, 0x76, 0x65, 0x5d, - 0x37, 0xb7, 0x65, 0x4c, 0xdf, 0xf9, 0xd3, 0xd9, 0xe7, 0x0e, 0x0a, 0x26, 0xf4, 0xde, 0x51, 0x41, 0xa5, 0x2f, 0x30, - 0xac, 0x41, 0x77, 0xf7, 0x05, 0xfb, 0xcc, 0x71, 0xdd, 0x37, 0xa4, 0x2f, 0x31, 0x1a, 0x2e, 0xb9, 0x7d, 0x3f, 0x18, - 0xe4, 0xc9, 0x6a, 0xe5, 0xf6, 0xe0, 0x33, 0x78, 0x5a, 0x2b, 0xe1, 0xec, 0x45, 0xd7, 0xd6, 0x29, 0x98, 0xcf, 0x0e, - 0x13, 0x82, 0xd6, 0xef, 0x0d, 0xd3, 0xb1, 0x19, 0x5f, 0x93, 0x13, 0x5b, 0xed, 0xdb, 0x35, 0x64, 0x0d, 0xa5, 0x98, - 0xe8, 0x34, 0xd7, 0x1a, 0x1a, 0xcd, 0xe0, 0xac, 0x62, 0x6f, 0x41, 0x4a, 0x02, 0x05, 0x35, 0x26, 0x20, 0x74, 0xa9, - 0xdc, 0xa2, 0x6f, 0xbc, 0xe0, 0x66, 0xb7, 0x0b, 0xd5, 0x66, 0x0a, 0x86, 0xa4, 0xf9, 0x3f, 0x47, 0xbc, 0x91, 0x2e, - 0x3f, 0x98, 0x76, 0xaf, 0xbc, 0x94, 0xc5, 0xd7, 0x33, 0xf0, 0xf6, 0x15, 0xd2, 0x03, 0x88, 0xa3, 0xbb, 0x0d, 0x29, - 0x97, 0xd8, 0xd2, 0x06, 0x34, 0x5a, 0x60, 0xb8, 0x5f, 0x87, 0xbb, 0xbf, 0x10, 0xe6, 0xee, 0x9e, 0x81, 0x3f, 0xe6, - 0x6f, 0x86, 0xbd, 0xb7, 0x51, 0xa6, 0xff, 0xc7, 0xde, 0xff, 0x8d, 0xd8, 0x7b, 0xeb, 0x77, 0x7e, 0xcd, 0xc2, 0xfe, - 0x1f, 0xc0, 0xf2, 0x5d, 0xe6, 0x9e, 0x71, 0x4c, 0xaf, 0x69, 0x9e, 0xab, 0xc5, 0xa5, 0xc3, 0x8b, 0x78, 0xb5, 0xa6, - 0x60, 0xe5, 0xc1, 0xd6, 0xb8, 0xe5, 0xa0, 0x87, 0xc8, 0x7e, 0xcb, 0x51, 0xfe, 0xed, 0x11, 0x7d, 0x42, 0x19, 0xaa, + 0xa4, 0xcb, 0xcf, 0x19, 0xce, 0x93, 0x99, 0x04, 0x60, 0x4b, 0xdc, 0x30, 0x57, 0x75, 0xf3, 0x22, 0x4d, 0xc4, 0xe6, + 0xc0, 0xf3, 0x53, 0x27, 0xc6, 0x0d, 0x29, 0xbc, 0xb5, 0xa0, 0x3a, 0x5e, 0xd8, 0xa5, 0xd8, 0xd0, 0xd0, 0x66, 0x0d, + 0x23, 0x9d, 0x6d, 0x19, 0xe9, 0xa8, 0x74, 0x74, 0xf9, 0xb0, 0xe9, 0x10, 0xca, 0x83, 0x82, 0x3d, 0x08, 0xfe, 0x15, + 0xb8, 0x65, 0xca, 0xfb, 0xb0, 0x19, 0xc7, 0x4a, 0x3b, 0x6a, 0xe1, 0x25, 0xc9, 0x2a, 0x8a, 0xc1, 0x40, 0x01, 0xba, + 0x79, 0xd8, 0x96, 0x9a, 0xfb, 0x21, 0x8f, 0x7d, 0xd6, 0xb8, 0x99, 0x8a, 0xf7, 0xf2, 0x96, 0x6a, 0x1d, 0x1e, 0x52, + 0x8d, 0x85, 0x97, 0xa6, 0x2c, 0xc6, 0x49, 0xf7, 0x20, 0x49, 0xc6, 0x7f, 0xc8, 0x36, 0xab, 0xc1, 0x21, 0x81, 0x84, + 0xd5, 0x11, 0x43, 0x2f, 0x80, 0x05, 0x23, 0x8d, 0x64, 0xa8, 0xaf, 0xa5, 0x38, 0xaa, 0x71, 0x3e, 0xf1, 0x3f, 0xe1, + 0x71, 0xd5, 0x62, 0xc9, 0xd3, 0xd7, 0x39, 0xd2, 0xad, 0x85, 0x37, 0x7e, 0x0f, 0x76, 0x30, 0x5a, 0xcb, 0x00, 0x9f, + 0x16, 0x39, 0x6a, 0x6a, 0x4c, 0x3c, 0xe1, 0xa8, 0x40, 0x92, 0x88, 0x25, 0xb9, 0xc5, 0x30, 0x04, 0x1b, 0xf0, 0xcc, + 0xc9, 0xd5, 0xba, 0x95, 0xed, 0x4f, 0x7d, 0x7d, 0x03, 0x6b, 0x02, 0x6a, 0x0b, 0xdc, 0x7e, 0x2e, 0x74, 0x0b, 0x0c, + 0xe7, 0x48, 0x07, 0x45, 0xe9, 0x25, 0xa4, 0x43, 0xb7, 0xc5, 0x65, 0x7a, 0x10, 0x03, 0xd5, 0x02, 0xb5, 0xe2, 0x93, + 0x29, 0xfe, 0x72, 0xae, 0xb2, 0x27, 0x43, 0xfc, 0xd5, 0xba, 0xca, 0x95, 0x58, 0x15, 0x29, 0x82, 0x34, 0x66, 0xb5, + 0x5f, 0xda, 0x4f, 0x64, 0xae, 0xfd, 0x80, 0x6d, 0xc3, 0x17, 0xf8, 0xd1, 0xe3, 0x75, 0x02, 0x01, 0x0a, 0xe4, 0x31, + 0x84, 0x56, 0xac, 0x67, 0xb5, 0xe5, 0xd3, 0x86, 0xf2, 0xa1, 0xfe, 0x07, 0x13, 0x7e, 0xdc, 0x25, 0x51, 0x41, 0x53, + 0xca, 0x32, 0x90, 0xeb, 0xa1, 0x1f, 0x7a, 0xf1, 0xdd, 0x35, 0xdd, 0x42, 0x34, 0xc1, 0xe2, 0xe7, 0xb2, 0x1d, 0xe2, + 0x45, 0xcb, 0xd6, 0x21, 0xa9, 0xa4, 0xa8, 0xba, 0xe3, 0x84, 0xde, 0xfd, 0x73, 0x2c, 0xf1, 0x77, 0xa5, 0x6b, 0x2c, + 0x5f, 0x90, 0xd2, 0x87, 0xae, 0x1f, 0xaf, 0x35, 0xb6, 0xd9, 0x4d, 0x65, 0xb4, 0x15, 0x06, 0x12, 0x96, 0x07, 0xaf, + 0xc4, 0xf3, 0xb1, 0xdf, 0x45, 0xf3, 0x8f, 0x61, 0x74, 0x6b, 0x3e, 0x5e, 0xa7, 0xa7, 0xea, 0xdc, 0x8b, 0x3f, 0xb2, + 0xb1, 0x39, 0xf2, 0xe3, 0x51, 0x00, 0xcc, 0xe3, 0x30, 0xf0, 0xc2, 0x8f, 0xfc, 0xd1, 0x8c, 0x96, 0x29, 0x1a, 0x74, + 0xdd, 0x7b, 0x83, 0x16, 0x73, 0x42, 0x82, 0x44, 0xe4, 0x6a, 0x6b, 0x66, 0x41, 0x79, 0x3f, 0x10, 0xd7, 0xfa, 0x82, + 0x51, 0x2c, 0x6a, 0x19, 0xe0, 0x8f, 0x00, 0x36, 0x66, 0x10, 0xe0, 0xc1, 0x50, 0x71, 0xbd, 0x54, 0x43, 0x1e, 0x2a, + 0x69, 0xd5, 0xf2, 0x0c, 0xc5, 0xd7, 0xd8, 0xc3, 0x6f, 0xff, 0x1c, 0x94, 0x3c, 0xe4, 0x73, 0x79, 0x2f, 0x9f, 0x37, + 0x42, 0x28, 0x35, 0xc9, 0xb1, 0xf0, 0x01, 0x1f, 0xe7, 0x0c, 0x66, 0xf3, 0xa7, 0xe5, 0xc6, 0x5e, 0x92, 0x2c, 0xe7, + 0x6c, 0x4c, 0x2a, 0xb1, 0xd3, 0x02, 0xa8, 0xf2, 0x3d, 0x44, 0x06, 0xec, 0x6f, 0xcb, 0xd6, 0xf1, 0xc1, 0x2b, 0x30, + 0xf0, 0x03, 0x86, 0x32, 0x9a, 0x4c, 0xd4, 0x42, 0x14, 0x70, 0x4f, 0x33, 0xe7, 0xe0, 0x6f, 0xcb, 0x37, 0x67, 0xf6, + 0x9b, 0xbc, 0x71, 0x08, 0x8c, 0xb1, 0xb0, 0x56, 0xe2, 0x7c, 0xb1, 0x04, 0xaf, 0x18, 0xd1, 0xc4, 0x0b, 0x9b, 0x87, + 0x73, 0x59, 0xda, 0xe2, 0x0b, 0xc6, 0xc6, 0xc0, 0x70, 0x1b, 0x1b, 0xa5, 0xd7, 0x01, 0xbb, 0x61, 0xb9, 0x25, 0xd4, + 0xe6, 0xc7, 0x6a, 0x5a, 0x60, 0xa8, 0x56, 0xae, 0x7b, 0xe4, 0x5c, 0x9d, 0x34, 0xa4, 0x01, 0x8e, 0x81, 0x8f, 0x5c, + 0x3e, 0x62, 0x95, 0x23, 0x35, 0x30, 0x54, 0x09, 0x80, 0x46, 0xc8, 0x4e, 0x1b, 0xca, 0xbb, 0x80, 0xa8, 0x1b, 0x60, + 0x33, 0x1c, 0xbd, 0x0b, 0xa9, 0x2d, 0xf8, 0x3c, 0x05, 0x70, 0xf2, 0xb4, 0x42, 0x6a, 0xd2, 0x34, 0x63, 0x75, 0xa2, + 0x36, 0x95, 0x84, 0x34, 0xc2, 0x39, 0x00, 0xbd, 0x64, 0x84, 0xb8, 0xaa, 0x76, 0x6d, 0x94, 0xf2, 0xc8, 0x87, 0x98, + 0xf8, 0x3d, 0x64, 0x49, 0xd2, 0x38, 0x61, 0xf9, 0xa2, 0x1b, 0x6a, 0x51, 0xbb, 0x3c, 0x1f, 0x45, 0xb9, 0x61, 0x1b, + 0xc0, 0x12, 0xe0, 0x00, 0xab, 0xdf, 0x42, 0xf2, 0x72, 0x3d, 0xe7, 0xe6, 0x9d, 0xf1, 0x74, 0xa8, 0x72, 0xd3, 0xbb, + 0xa6, 0xf7, 0x2b, 0x95, 0x03, 0x55, 0x22, 0xd3, 0xb5, 0xa0, 0x69, 0x25, 0xd4, 0xbb, 0x21, 0x55, 0xc2, 0x0e, 0x04, + 0x4c, 0x15, 0xfc, 0xca, 0x26, 0x13, 0x36, 0x4a, 0x13, 0x5d, 0xc8, 0x98, 0xf2, 0x60, 0xeb, 0xe0, 0x64, 0xbb, 0xe7, + 0xaa, 0x3f, 0x41, 0xc8, 0x19, 0x11, 0x93, 0x90, 0x03, 0x24, 0xee, 0x4c, 0xf5, 0xd3, 0x44, 0x3d, 0x96, 0xa7, 0x88, + 0x7f, 0x05, 0xa4, 0xd0, 0x35, 0xe5, 0x08, 0x1a, 0xa7, 0x3f, 0xc5, 0xbe, 0x88, 0x72, 0x23, 0xd0, 0xed, 0xa8, 0x68, + 0xdb, 0xf1, 0x5d, 0x3b, 0x6f, 0x0e, 0x1d, 0x3b, 0x53, 0x0d, 0x70, 0x75, 0xfe, 0x58, 0xd9, 0xc6, 0x44, 0xa0, 0x5c, + 0xf5, 0xfc, 0xed, 0xab, 0x3f, 0x9f, 0xbd, 0xde, 0x15, 0x23, 0x60, 0x97, 0x6d, 0xe8, 0x72, 0x19, 0x6e, 0xe9, 0xf4, + 0x97, 0x9f, 0x1e, 0xd6, 0x6d, 0xcb, 0x79, 0xe1, 0xa8, 0x06, 0x59, 0xa7, 0x4b, 0x78, 0x71, 0x14, 0xdd, 0xb0, 0xf8, + 0xb3, 0xa7, 0x41, 0xee, 0xbc, 0x1e, 0xdc, 0xb7, 0x3f, 0x9f, 0xfd, 0xb4, 0x33, 0xa8, 0x47, 0x8e, 0x0d, 0xb8, 0x3d, + 0x8d, 0x16, 0x0f, 0x18, 0x5d, 0x5b, 0x35, 0xd4, 0x51, 0x10, 0x25, 0xac, 0x01, 0x82, 0x57, 0xe7, 0x6f, 0xdf, 0xe3, + 0x74, 0x15, 0x2c, 0x08, 0x75, 0xf5, 0x79, 0x83, 0xff, 0xf9, 0xdd, 0xd9, 0xfb, 0xf7, 0xaa, 0x81, 0xc9, 0xba, 0x13, + 0xb9, 0x77, 0xbe, 0x89, 0xef, 0xa1, 0x38, 0xb5, 0x7b, 0x9d, 0xa8, 0x1a, 0x5d, 0xa4, 0xcb, 0xa3, 0xa1, 0xb2, 0x8d, + 0x6d, 0xce, 0xa9, 0x1d, 0xff, 0x32, 0xdd, 0x7e, 0x77, 0x1a, 0x57, 0x0d, 0x3e, 0xda, 0x4e, 0x52, 0x4b, 0x25, 0x73, + 0x3f, 0xbc, 0xae, 0x29, 0xf5, 0x6e, 0x6b, 0x4a, 0xe1, 0xfa, 0xb8, 0x81, 0x1f, 0x97, 0xd1, 0x5c, 0x62, 0x47, 0xd8, + 0xed, 0xfd, 0xd3, 0x25, 0xdd, 0xe1, 0x3e, 0x03, 0x68, 0x9e, 0x6c, 0xa5, 0x0a, 0x75, 0x4d, 0x31, 0xbf, 0x78, 0xe5, + 0x73, 0x3b, 0x0a, 0xc0, 0x26, 0x9f, 0xc9, 0x6a, 0xc8, 0x32, 0xab, 0xca, 0x3d, 0x6a, 0xdc, 0xca, 0xad, 0x80, 0x9a, + 0x91, 0xea, 0x86, 0xd3, 0x94, 0x85, 0x37, 0x06, 0x43, 0x77, 0x73, 0x18, 0xa5, 0x69, 0x34, 0xef, 0x3a, 0xf6, 0xe2, + 0x56, 0x55, 0x7a, 0x42, 0xd8, 0xc1, 0xed, 0xf0, 0xbb, 0xff, 0xfa, 0x67, 0x05, 0xcd, 0x53, 0xf9, 0x75, 0xca, 0xe6, + 0x0b, 0x16, 0x7b, 0xe9, 0x32, 0x66, 0x99, 0xf2, 0xaf, 0xff, 0x79, 0x55, 0xb9, 0xd8, 0xf7, 0xe4, 0x36, 0xc4, 0xd2, + 0xcb, 0x4d, 0xae, 0x83, 0x68, 0xb5, 0x57, 0x78, 0xdc, 0xdd, 0x53, 0x79, 0xe6, 0x4f, 0x67, 0x79, 0xed, 0xd3, 0x74, + 0xcb, 0xd8, 0x04, 0xf4, 0xa4, 0x0f, 0x50, 0xce, 0xa3, 0x55, 0xf7, 0x5f, 0xff, 0xcc, 0x05, 0x36, 0xf7, 0xee, 0xba, + 0x7a, 0x40, 0xcb, 0x2b, 0x5a, 0x5f, 0x67, 0x63, 0x89, 0xe1, 0xfd, 0xc6, 0x02, 0x6f, 0x14, 0xd2, 0xae, 0xdc, 0xd4, + 0xcd, 0x6d, 0x19, 0xd3, 0x77, 0xfe, 0x74, 0xf6, 0xb9, 0x83, 0x82, 0x09, 0xbd, 0x77, 0x54, 0x50, 0xe9, 0x0b, 0x0c, + 0x6b, 0xd0, 0xdd, 0x7d, 0xc1, 0x3e, 0x73, 0x5c, 0xf7, 0x0d, 0xe9, 0x4b, 0x8c, 0x86, 0x4b, 0x6e, 0xdf, 0x0f, 0x06, + 0x79, 0xb2, 0x5a, 0xb9, 0x3d, 0xf8, 0x0c, 0x9e, 0x6e, 0x94, 0x70, 0xf6, 0xa2, 0x6b, 0xeb, 0x14, 0xcc, 0x67, 0x87, + 0x09, 0x41, 0xeb, 0xf7, 0x9a, 0xe9, 0x68, 0xc6, 0xd7, 0xe4, 0xc4, 0xb6, 0xf1, 0xed, 0x0d, 0x64, 0x0d, 0xa5, 0x98, + 0xe8, 0x34, 0xd7, 0x1a, 0x1a, 0xf5, 0xe0, 0xac, 0x62, 0x6f, 0x41, 0x4a, 0x02, 0x05, 0x35, 0x26, 0x20, 0x74, 0xa9, + 0xdc, 0xa2, 0x6f, 0xbc, 0xe0, 0x66, 0xb7, 0x0b, 0x55, 0x33, 0x05, 0x43, 0xd2, 0xfc, 0xef, 0x23, 0xde, 0x48, 0x97, + 0x1f, 0x4c, 0xbb, 0x57, 0x5e, 0xca, 0xe2, 0xeb, 0x19, 0x78, 0xfb, 0x0a, 0xe9, 0x01, 0xc4, 0xd1, 0xdd, 0x86, 0x94, + 0x4b, 0x6c, 0x69, 0x0d, 0x1a, 0x2d, 0x30, 0xdc, 0x6f, 0xc3, 0xdd, 0x5f, 0x08, 0x73, 0x77, 0xcf, 0xc0, 0x1f, 0xf3, + 0x77, 0xc3, 0xde, 0xdb, 0x28, 0xd3, 0xff, 0x63, 0xef, 0xff, 0x44, 0xec, 0xbd, 0xf5, 0x3b, 0xbf, 0x65, 0x61, 0xff, + 0x0f, 0x60, 0xf9, 0x2e, 0x73, 0xcf, 0x38, 0xa6, 0xd7, 0x34, 0xcf, 0xd5, 0xe2, 0xd2, 0xe1, 0x45, 0xbc, 0xba, 0xa1, + 0x60, 0xe5, 0xc1, 0xd6, 0xb8, 0xe5, 0xa0, 0x87, 0xc8, 0x7e, 0xcb, 0x51, 0xfe, 0xfd, 0x11, 0x7d, 0x42, 0x19, 0xaa, 0x24, 0x4c, 0xdf, 0x3d, 0x33, 0x92, 0xd2, 0x48, 0xbc, 0x95, 0x77, 0xb7, 0x0b, 0xde, 0x11, 0xc0, 0x7e, 0xb3, 0xf2, - 0xee, 0x9a, 0x80, 0xdd, 0x88, 0x5e, 0xab, 0x1f, 0x3b, 0x05, 0x2f, 0x9f, 0x2e, 0xba, 0xf8, 0x18, 0x83, 0x84, 0xa5, - 0xa7, 0x50, 0xe8, 0x3e, 0x5e, 0xef, 0x55, 0x2b, 0x66, 0x03, 0xf0, 0x7f, 0x96, 0x00, 0x8f, 0x4a, 0x80, 0xfb, 0xc9, - 0x75, 0x14, 0x3e, 0x04, 0xf2, 0x9f, 0x40, 0xf8, 0xf3, 0xab, 0x41, 0xc7, 0xcf, 0xd5, 0x60, 0xc7, 0xd2, 0x2a, 0xf0, - 0x58, 0x58, 0x85, 0xbe, 0xd7, 0x2c, 0xab, 0xaf, 0x10, 0x5a, 0xa4, 0xb1, 0x8c, 0x08, 0xad, 0x02, 0x7a, 0x15, 0x05, - 0x74, 0x5c, 0x15, 0x92, 0xeb, 0x87, 0x93, 0xd8, 0x8b, 0xd9, 0x78, 0xf3, 0x15, 0xa0, 0x64, 0x9d, 0x7c, 0x67, 0x25, - 0xcb, 0xc5, 0x22, 0x8a, 0xd3, 0xe4, 0x1a, 0xe3, 0xb4, 0xcc, 0x7d, 0xb8, 0x50, 0x40, 0x46, 0xb1, 0x3c, 0x6a, 0xef, - 0x59, 0x93, 0x7c, 0xdb, 0x60, 0x6e, 0x39, 0xd9, 0x06, 0xf7, 0xbe, 0x31, 0xb8, 0xff, 0xce, 0x4c, 0xd2, 0x5f, 0xcc, - 0xac, 0x34, 0xf6, 0xe7, 0x9a, 0x6e, 0x38, 0xb6, 0xae, 0x0b, 0xf9, 0xca, 0xcc, 0xed, 0xef, 0x51, 0xb4, 0xe1, 0x99, - 0x0e, 0x51, 0x0b, 0xd1, 0xa3, 0x05, 0x6c, 0xe5, 0x5e, 0x2e, 0x27, 0x13, 0x16, 0x6b, 0x22, 0x2c, 0x23, 0xc4, 0x85, - 0x25, 0x63, 0x40, 0xf0, 0x73, 0xfc, 0xe0, 0xb3, 0x15, 0xe4, 0x7f, 0x2a, 0xc2, 0xaa, 0x83, 0xaf, 0x27, 0x99, 0x93, - 0x43, 0x6e, 0xb9, 0xb4, 0xdd, 0xd2, 0xc6, 0xcf, 0x0e, 0x8c, 0x19, 0x04, 0x63, 0x2a, 0xdc, 0xe3, 0x31, 0xce, 0x9f, - 0x1f, 0xa6, 0x1d, 0xfc, 0x02, 0x74, 0x00, 0x87, 0x37, 0x70, 0x73, 0xbf, 0x28, 0x65, 0x94, 0x77, 0x38, 0x73, 0xfb, - 0xc1, 0x73, 0x97, 0xf4, 0x3c, 0x68, 0xb7, 0xf7, 0x6a, 0xe6, 0xc5, 0xaf, 0xa2, 0x31, 0x43, 0x40, 0x87, 0x69, 0x04, - 0xde, 0x9a, 0x52, 0x18, 0x1e, 0x8c, 0xc2, 0x63, 0x96, 0x22, 0xf3, 0xec, 0x43, 0xd1, 0xb5, 0x5c, 0xe4, 0x3e, 0x7f, - 0xbc, 0x6f, 0xc0, 0x49, 0x6b, 0x5e, 0x69, 0xb1, 0x68, 0x7c, 0xa9, 0x1b, 0x5f, 0xc9, 0xbb, 0xf5, 0x95, 0x17, 0xc7, - 0x3e, 0x8b, 0x15, 0xed, 0xbb, 0x5f, 0x74, 0x79, 0xd3, 0x96, 0x14, 0x3a, 0x5c, 0xcb, 0xac, 0x60, 0x34, 0xba, 0x89, - 0xcf, 0x82, 0xb1, 0xab, 0x8e, 0xa8, 0x61, 0xae, 0xbc, 0x69, 0x77, 0x6c, 0xdb, 0xe6, 0x0a, 0x53, 0x87, 0x7e, 0x82, - 0xc2, 0x14, 0x7e, 0xc2, 0x43, 0x49, 0xbc, 0xd8, 0x21, 0x2e, 0xa2, 0x46, 0xce, 0x1a, 0x21, 0x7c, 0x47, 0xf1, 0x7c, + 0xee, 0xea, 0x80, 0x6d, 0x44, 0xaf, 0xd5, 0x8f, 0x9d, 0x82, 0x97, 0x4f, 0x17, 0x5d, 0x7c, 0x8c, 0x41, 0xc2, 0xd2, + 0x53, 0x28, 0x74, 0x1f, 0xaf, 0xf7, 0xaa, 0x15, 0xb3, 0x01, 0xf8, 0x3f, 0x4b, 0x80, 0x47, 0x25, 0xc0, 0xfd, 0xe4, + 0x3a, 0x0a, 0x1f, 0x02, 0xf9, 0xcf, 0x20, 0xfc, 0xf9, 0xcd, 0xa0, 0xe3, 0xe7, 0x36, 0x60, 0xc7, 0xd2, 0x2a, 0xf0, + 0x58, 0x58, 0x85, 0xbe, 0x57, 0x2f, 0xab, 0xaf, 0x10, 0x5a, 0xa4, 0xb1, 0x8c, 0x08, 0xad, 0x02, 0x7a, 0x15, 0x05, + 0x74, 0x5c, 0x15, 0x92, 0xeb, 0x87, 0x93, 0xd8, 0x8b, 0xd9, 0xb8, 0xf9, 0x0a, 0x50, 0xb2, 0x4e, 0xbe, 0xb3, 0x92, + 0xe5, 0x62, 0x11, 0xc5, 0x69, 0x72, 0x8d, 0x71, 0x5a, 0xe6, 0x3e, 0x5c, 0x28, 0x20, 0xa3, 0x58, 0x1e, 0xb5, 0xf7, + 0xac, 0x4e, 0xbe, 0x6d, 0x30, 0xb7, 0x9c, 0x6c, 0x83, 0x7b, 0xdf, 0x18, 0xdc, 0x7f, 0x67, 0x26, 0xe9, 0x2f, 0x66, + 0x56, 0x1a, 0xfb, 0x73, 0x4d, 0x37, 0x1c, 0x5b, 0xd7, 0x85, 0x7c, 0x65, 0xe6, 0xf6, 0xf7, 0x28, 0xda, 0xf0, 0x4c, + 0x87, 0xa8, 0x85, 0xe8, 0xd1, 0x02, 0xb6, 0x72, 0x2f, 0x97, 0x93, 0x09, 0x8b, 0x35, 0x11, 0x96, 0x11, 0xe2, 0xc2, + 0x92, 0x31, 0x20, 0xf8, 0x39, 0x7e, 0xf0, 0xd9, 0x0a, 0xf2, 0x3f, 0x15, 0x61, 0xd5, 0xc1, 0xd7, 0x93, 0xcc, 0xc9, + 0x21, 0xb7, 0x5c, 0xda, 0x6e, 0x69, 0xe3, 0x67, 0x07, 0xc6, 0x0c, 0x82, 0x31, 0x15, 0xee, 0xf1, 0x18, 0xe7, 0xcf, + 0x0f, 0xd3, 0x0e, 0x7e, 0x01, 0x3a, 0x80, 0xc3, 0x1b, 0xb8, 0xb9, 0x5f, 0x94, 0x32, 0xca, 0x3b, 0x9c, 0xb9, 0xfd, + 0xe0, 0xb9, 0x4b, 0x7a, 0x1e, 0xb4, 0xdb, 0x7b, 0x35, 0xf3, 0xe2, 0x57, 0xd1, 0x98, 0x21, 0xa0, 0xc3, 0x34, 0x02, + 0x6f, 0x4d, 0x29, 0x0c, 0x0f, 0x46, 0xe1, 0x31, 0x4b, 0x91, 0x79, 0xf6, 0xa1, 0xe8, 0x5a, 0x2e, 0x72, 0x9f, 0x3f, + 0xde, 0x37, 0xe0, 0xa4, 0xd5, 0xaf, 0xb4, 0x58, 0x34, 0xbe, 0xd4, 0xb5, 0xaf, 0xe4, 0xdd, 0xfa, 0xca, 0x8b, 0x63, + 0x9f, 0xc5, 0x8a, 0xf6, 0xdd, 0xaf, 0xba, 0xbc, 0x69, 0x4b, 0x0a, 0x1d, 0xae, 0x65, 0x56, 0x30, 0x1a, 0xdd, 0xc4, + 0x67, 0xc1, 0xd8, 0x55, 0x47, 0xd4, 0x30, 0x57, 0xde, 0xb4, 0x3b, 0xb6, 0x6d, 0x73, 0x85, 0xa9, 0x43, 0x3f, 0x41, + 0x61, 0x0a, 0x3f, 0xe1, 0xa1, 0x24, 0x5e, 0xec, 0x10, 0x17, 0xb1, 0x41, 0xce, 0x6a, 0x21, 0x7c, 0x47, 0xf1, 0x7c, 0x1e, 0x02, 0x1b, 0x8f, 0xfb, 0x23, 0x40, 0x73, 0x04, 0x58, 0x05, 0x4c, 0x15, 0x80, 0x0e, 0x1f, 0x02, 0xd0, 0x85, - 0x3f, 0xf7, 0xc3, 0x69, 0xb2, 0x11, 0x22, 0x54, 0x9b, 0x96, 0xe0, 0x49, 0xa9, 0x85, 0xaa, 0xe0, 0x1a, 0xce, 0xa2, - 0x00, 0xf2, 0x10, 0xa9, 0xcc, 0x9a, 0x5a, 0xca, 0x0b, 0xdb, 0xb6, 0x0d, 0xf3, 0x00, 0x32, 0xfe, 0x1d, 0x1e, 0xd9, - 0x86, 0x09, 0x7f, 0x59, 0x96, 0xd5, 0x20, 0x8f, 0xed, 0xcd, 0xfd, 0xd0, 0xa4, 0xc7, 0x96, 0xbd, 0x1b, 0xbc, 0xf7, - 0x5a, 0xf5, 0x26, 0x5c, 0x37, 0x36, 0xcc, 0x5d, 0x47, 0xb5, 0xa1, 0x9b, 0x94, 0x6d, 0xdd, 0x2c, 0x0a, 0xb8, 0xc4, - 0xe3, 0x61, 0x54, 0x88, 0xd1, 0xb0, 0xfc, 0x16, 0xd9, 0xd2, 0xb8, 0x9a, 0xc7, 0x42, 0xfd, 0x9e, 0x83, 0xd5, 0x55, - 0x5e, 0x45, 0xcb, 0x60, 0x8c, 0xe6, 0x50, 0x60, 0xbb, 0xac, 0x14, 0x56, 0xa1, 0x95, 0x64, 0x53, 0x90, 0x4b, 0x1c, - 0x13, 0xad, 0xbd, 0x47, 0xe2, 0x14, 0xc5, 0xda, 0x53, 0x9c, 0xe2, 0xcb, 0xa6, 0x2d, 0x78, 0xf5, 0x14, 0xe2, 0x09, - 0xed, 0xd0, 0x80, 0xef, 0x0b, 0xa8, 0x1f, 0xec, 0x52, 0x5f, 0xac, 0xdb, 0xd5, 0x53, 0x0a, 0x3a, 0xeb, 0x7d, 0xfa, - 0xb4, 0x37, 0xfa, 0xf4, 0x69, 0xaf, 0x96, 0xa9, 0x63, 0xf3, 0x08, 0x69, 0x63, 0x30, 0x1e, 0x62, 0x04, 0xe2, 0x06, - 0x11, 0xd0, 0xdf, 0x43, 0x79, 0xd7, 0xe3, 0xd1, 0xaa, 0xe8, 0x69, 0x64, 0xf0, 0x0f, 0xd2, 0x63, 0x90, 0x55, 0x26, - 0x65, 0xe6, 0x7a, 0x24, 0xe6, 0xf9, 0xf4, 0x89, 0x1f, 0x37, 0x63, 0xec, 0x8e, 0xf2, 0x22, 0x47, 0x35, 0x96, 0x6e, - 0x90, 0x3f, 0xaa, 0x08, 0xf2, 0x92, 0x63, 0xcc, 0x02, 0xe2, 0x95, 0x17, 0x87, 0x32, 0xc0, 0x3f, 0x46, 0x0a, 0xff, - 0xac, 0xc2, 0x23, 0xa2, 0x8e, 0xab, 0xab, 0x31, 0x71, 0x99, 0xb6, 0x24, 0x1c, 0x28, 0x2c, 0xdd, 0xa4, 0x0e, 0x2e, - 0x04, 0xb6, 0xc7, 0xb4, 0xa8, 0x62, 0x80, 0xe8, 0x5f, 0x8d, 0x27, 0x77, 0x2c, 0x86, 0xf5, 0xce, 0x5b, 0x75, 0x97, - 0xe2, 0xe1, 0x8c, 0x4c, 0xe2, 0xbb, 0x93, 0xdc, 0x6f, 0x79, 0x41, 0x5e, 0x87, 0x53, 0xf7, 0xdb, 0x58, 0x5b, 0x18, - 0xa9, 0xa1, 0x0a, 0x32, 0xa2, 0xea, 0xc6, 0xbc, 0x29, 0xc0, 0x6a, 0x6f, 0xce, 0xc3, 0xcd, 0x68, 0x62, 0x2b, 0x5c, - 0x4f, 0xd0, 0x57, 0x21, 0x1c, 0xdd, 0x61, 0x00, 0xe5, 0xe2, 0x3d, 0x81, 0x72, 0xcd, 0xb3, 0xef, 0x8d, 0xe5, 0x57, - 0xb0, 0xe0, 0xaa, 0x31, 0xd1, 0x0d, 0xf2, 0x01, 0x98, 0x7e, 0x49, 0x73, 0x7f, 0x8a, 0xa9, 0x3c, 0x97, 0xc2, 0xbd, - 0x0a, 0x07, 0x80, 0xeb, 0x8a, 0x03, 0x40, 0xc3, 0x7c, 0x2a, 0x31, 0x4b, 0x16, 0x51, 0x08, 0x77, 0xc5, 0xeb, 0xc2, - 0xc3, 0xeb, 0xba, 0xee, 0xe1, 0xd5, 0xd0, 0x14, 0xdf, 0x50, 0x3b, 0x50, 0x49, 0x5f, 0xfc, 0xa5, 0x62, 0xa1, 0x2f, - 0x48, 0x3d, 0x66, 0x29, 0x3f, 0xdb, 0xe4, 0xd9, 0xfd, 0xfd, 0xfd, 0x9e, 0xdd, 0xe7, 0x3b, 0x79, 0x76, 0x7f, 0xff, + 0x3f, 0xf7, 0xc3, 0x69, 0xd2, 0x08, 0x11, 0xaa, 0x4d, 0x4b, 0xf0, 0xa4, 0xd4, 0x42, 0x55, 0x70, 0x0d, 0x67, 0x51, + 0x00, 0x79, 0x88, 0x54, 0x66, 0x4d, 0x2d, 0xe5, 0x85, 0x6d, 0xdb, 0x86, 0x79, 0x00, 0x19, 0xff, 0x0e, 0x8f, 0x6c, + 0xc3, 0x84, 0xbf, 0x2c, 0xcb, 0xaa, 0x91, 0xc7, 0xf6, 0xe6, 0x7e, 0x68, 0xd2, 0x63, 0xcb, 0xde, 0x0d, 0xde, 0x7b, + 0xad, 0x7a, 0x13, 0xae, 0x1b, 0x1b, 0xe6, 0xae, 0xa3, 0xda, 0xd0, 0x4d, 0xca, 0xb6, 0x6e, 0x16, 0x05, 0x5c, 0xe2, + 0xf1, 0x30, 0x2a, 0xc4, 0x68, 0x58, 0x7e, 0x8b, 0x6c, 0x69, 0x5c, 0xcd, 0x63, 0xa1, 0x7e, 0xcf, 0xc1, 0xea, 0x2a, + 0xaf, 0xa2, 0x65, 0x30, 0x46, 0x73, 0x28, 0xb0, 0x5d, 0x56, 0x0a, 0xab, 0xd0, 0x4a, 0xb2, 0x29, 0xc8, 0x25, 0x8e, + 0x89, 0xd6, 0xde, 0x23, 0x71, 0x8a, 0x62, 0xed, 0x29, 0x4e, 0xf1, 0x65, 0xdd, 0x16, 0xbc, 0x7a, 0x0a, 0xf1, 0x84, + 0x76, 0x68, 0xc0, 0xf7, 0x05, 0xd4, 0x0f, 0x76, 0xa9, 0x2f, 0xd6, 0xed, 0xea, 0x29, 0x05, 0x9d, 0xf5, 0x3e, 0x7d, + 0xda, 0x1b, 0x7d, 0xfa, 0xb4, 0xb7, 0x91, 0xa9, 0xa3, 0x79, 0x84, 0xb4, 0x31, 0x18, 0x0f, 0x31, 0x02, 0x71, 0x83, + 0x08, 0xe8, 0xef, 0xa1, 0xbc, 0xeb, 0xf1, 0x68, 0x55, 0xf4, 0x34, 0x32, 0xf8, 0x07, 0xe9, 0x31, 0xc8, 0x2a, 0x93, + 0x32, 0x73, 0x3d, 0x12, 0xf3, 0x7c, 0xfa, 0xc4, 0x8f, 0x9b, 0x31, 0x76, 0x47, 0x79, 0x91, 0xa3, 0x1a, 0x4b, 0x37, + 0xc8, 0x1f, 0x55, 0x04, 0x79, 0xc9, 0x31, 0x66, 0x01, 0xf1, 0xca, 0x8b, 0x43, 0x19, 0xe0, 0x9f, 0x22, 0x85, 0x7f, + 0x56, 0xe1, 0x11, 0x51, 0xc7, 0xd5, 0xd5, 0x98, 0xb8, 0x4c, 0x5b, 0x12, 0x0e, 0x14, 0x96, 0x6e, 0x52, 0x07, 0x17, + 0x02, 0xdb, 0x63, 0x5a, 0x54, 0x31, 0x40, 0xf4, 0xaf, 0xc6, 0x93, 0x3b, 0x16, 0xc3, 0x7a, 0xe7, 0xad, 0xba, 0x4b, + 0xf1, 0x70, 0x46, 0x26, 0xf1, 0xdd, 0x49, 0xee, 0xb7, 0xbc, 0x20, 0xaf, 0xc3, 0xa9, 0xfb, 0x6d, 0xac, 0x2d, 0x8c, + 0xd4, 0x50, 0x05, 0x19, 0x51, 0x75, 0x63, 0x5e, 0x17, 0x60, 0xb5, 0x37, 0xe7, 0xe1, 0x66, 0x34, 0xb1, 0x15, 0xae, + 0x27, 0xe8, 0xab, 0x10, 0x8e, 0xee, 0x30, 0x80, 0x72, 0xf1, 0x9e, 0x40, 0xb9, 0xe6, 0xd9, 0xf7, 0xc6, 0xf2, 0x2b, + 0x58, 0x70, 0xd5, 0x98, 0xe8, 0x06, 0xf9, 0x00, 0x4c, 0xbf, 0xa4, 0xb9, 0x3f, 0xc5, 0x54, 0x9e, 0x4b, 0xe1, 0x5e, + 0x85, 0x03, 0xc0, 0x75, 0xc5, 0x01, 0xa0, 0x66, 0x3e, 0x95, 0x98, 0x25, 0x8b, 0x28, 0x84, 0xbb, 0xe2, 0x75, 0xe1, + 0xe1, 0x75, 0xbd, 0xe9, 0xe1, 0x55, 0xd3, 0x14, 0xdf, 0x50, 0x3b, 0x50, 0x49, 0x5f, 0xfc, 0x57, 0xc5, 0x42, 0x5f, + 0x90, 0x7a, 0xcc, 0x52, 0x7e, 0xd6, 0xe4, 0xd9, 0xfd, 0xfd, 0xfd, 0x9e, 0xdd, 0xe7, 0x3b, 0x79, 0x76, 0x7f, 0xff, 0xc5, 0x3d, 0xbb, 0xcf, 0x64, 0xcf, 0x6e, 0x20, 0xc1, 0x67, 0x6c, 0x27, 0x47, 0x5a, 0xe1, 0xd2, 0x12, 0xad, 0x12, - 0xd7, 0xe1, 0x9a, 0xb5, 0x64, 0x34, 0x63, 0x60, 0xaa, 0xc0, 0x59, 0xdd, 0x20, 0x9a, 0x82, 0xbf, 0xeb, 0x66, 0x8f, - 0xd6, 0x2f, 0xe5, 0xcf, 0x1a, 0x44, 0x53, 0x55, 0xca, 0xd3, 0x16, 0x8a, 0x3c, 0x6d, 0x10, 0x9b, 0xee, 0xef, 0xb7, - 0xce, 0xcb, 0x4b, 0xa7, 0xd7, 0x76, 0x20, 0xce, 0x29, 0x68, 0x9f, 0xb1, 0xc0, 0xee, 0xb5, 0xdb, 0x50, 0xb0, 0x92, - 0x0a, 0x5a, 0x50, 0xe0, 0x4b, 0x05, 0x87, 0x50, 0x30, 0x92, 0x0a, 0x8e, 0xa0, 0x60, 0x2c, 0x15, 0x1c, 0x43, 0xc1, - 0x8d, 0x9a, 0x5d, 0x86, 0xb9, 0xdf, 0xfa, 0xb1, 0x7e, 0x55, 0x4a, 0xd1, 0x99, 0x9b, 0x4a, 0x88, 0x2a, 0xc7, 0x86, - 0xc8, 0x17, 0x61, 0x1e, 0xe8, 0x9c, 0x47, 0x1b, 0x7c, 0x35, 0x00, 0xcc, 0x0b, 0x96, 0x23, 0x06, 0xd8, 0xdd, 0x50, - 0xcd, 0xb6, 0x78, 0xad, 0x76, 0x73, 0x3f, 0x6f, 0xdb, 0x68, 0x09, 0xbf, 0xe9, 0x2e, 0x46, 0xf1, 0x10, 0x95, 0x0f, - 0x9f, 0xcf, 0xf2, 0xe0, 0xd1, 0x4b, 0xb7, 0x08, 0x86, 0xd3, 0x86, 0x14, 0x3a, 0x9c, 0x57, 0x63, 0x1a, 0xd8, 0xcb, - 0x40, 0xac, 0x13, 0x71, 0x8a, 0xc4, 0x07, 0x14, 0x74, 0x86, 0xef, 0x79, 0x05, 0x0f, 0xc7, 0x43, 0xad, 0x13, 0xf4, - 0xf3, 0x3c, 0x82, 0x35, 0xe9, 0x52, 0x97, 0x46, 0xea, 0x4d, 0xbb, 0x33, 0x83, 0x0c, 0xa9, 0xba, 0x53, 0x48, 0x49, - 0x72, 0x3a, 0xee, 0x2e, 0x8c, 0xd5, 0x8c, 0x85, 0xdd, 0x09, 0x77, 0x3b, 0x84, 0xf5, 0x27, 0x4f, 0x92, 0xb9, 0x2e, - 0x5c, 0xa0, 0x70, 0x4f, 0x14, 0x6f, 0x09, 0x4a, 0x33, 0xdf, 0x4a, 0x85, 0xf7, 0x8e, 0x26, 0x1b, 0x59, 0x7d, 0x09, - 0x5f, 0x8b, 0xd7, 0x6c, 0xb8, 0x9c, 0x2a, 0xe7, 0xd1, 0xf4, 0x5e, 0xbf, 0x0a, 0xf9, 0x15, 0x40, 0xa9, 0x92, 0x35, - 0xa9, 0x29, 0xb6, 0x37, 0xff, 0x16, 0x3d, 0x66, 0xe5, 0xfa, 0x29, 0xc0, 0xa6, 0xa4, 0xc4, 0x36, 0xc0, 0x77, 0x60, - 0xb6, 0x25, 0xcf, 0x85, 0x73, 0x98, 0x3f, 0xe9, 0xf9, 0xc2, 0x93, 0xe0, 0xe9, 0xff, 0xc0, 0x92, 0xc4, 0x9b, 0x32, - 0x19, 0xb5, 0x94, 0x3a, 0x07, 0x2c, 0x98, 0xab, 0x93, 0x71, 0x02, 0x81, 0xb1, 0xf7, 0x6b, 0xfe, 0x28, 0xe0, 0x32, + 0xd7, 0xe1, 0x9a, 0xb5, 0x64, 0x34, 0x63, 0x60, 0xaa, 0xc0, 0x59, 0xdd, 0x20, 0x9a, 0x82, 0xbf, 0x6b, 0xb3, 0x47, + 0xeb, 0x97, 0xf2, 0x67, 0x0d, 0xa2, 0xa9, 0x2a, 0xe5, 0x69, 0x0b, 0x45, 0x9e, 0x36, 0x88, 0x4d, 0xf7, 0xb7, 0x5b, + 0xe7, 0xe5, 0xa5, 0xd3, 0x6b, 0x3b, 0x10, 0xe7, 0x14, 0xb4, 0xcf, 0x58, 0x60, 0xf7, 0xda, 0x6d, 0x28, 0x58, 0x49, + 0x05, 0x2d, 0x28, 0xf0, 0xa5, 0x82, 0x43, 0x28, 0x18, 0x49, 0x05, 0x47, 0x50, 0x30, 0x96, 0x0a, 0x8e, 0xa1, 0xe0, + 0x46, 0xcd, 0x2e, 0xc3, 0xdc, 0x6f, 0xfd, 0x58, 0xbf, 0x2a, 0xa5, 0xe8, 0xcc, 0x4d, 0x25, 0x44, 0x95, 0x63, 0x43, + 0xe4, 0x8b, 0x30, 0x0f, 0x74, 0xce, 0xa3, 0x0d, 0xbe, 0x1a, 0x00, 0xe6, 0x05, 0xcb, 0x11, 0x03, 0xec, 0x6e, 0xa8, + 0x66, 0x5b, 0xbc, 0x56, 0xbb, 0xb9, 0x9f, 0xb7, 0x6d, 0xb4, 0x84, 0xdf, 0x74, 0x17, 0xa3, 0x78, 0x88, 0xca, 0x87, + 0xcf, 0x67, 0x79, 0xf0, 0xe8, 0xa5, 0x5b, 0x04, 0xc3, 0x69, 0x43, 0x0a, 0x1d, 0xce, 0xab, 0x31, 0x0d, 0xec, 0x65, + 0x20, 0xd6, 0x89, 0x38, 0x45, 0xe2, 0x03, 0x0a, 0x3a, 0xc3, 0xf7, 0xbc, 0x82, 0x87, 0xe3, 0xa1, 0xd6, 0x09, 0xfa, + 0x79, 0x1e, 0xc1, 0x9a, 0x74, 0xa9, 0x4b, 0x23, 0xf5, 0xa6, 0xdd, 0x99, 0x41, 0x86, 0x54, 0xdd, 0x29, 0xa4, 0x24, + 0x39, 0x1d, 0x77, 0x17, 0xc6, 0x6a, 0xc6, 0xc2, 0xee, 0x84, 0xbb, 0x1d, 0xc2, 0xfa, 0x93, 0x27, 0xc9, 0x5c, 0x17, + 0x2e, 0x50, 0xb8, 0x27, 0x8a, 0xb7, 0x04, 0xa5, 0x99, 0x6f, 0xa5, 0xc2, 0x7b, 0x47, 0x93, 0x8d, 0xac, 0xbe, 0x84, + 0xaf, 0xc5, 0x6b, 0x36, 0x5c, 0x4e, 0x95, 0xf3, 0x68, 0x7a, 0xaf, 0x5f, 0x85, 0xfc, 0x0a, 0xa0, 0x54, 0xc9, 0x9a, + 0xd4, 0x14, 0xdb, 0x9b, 0x7f, 0x8b, 0x1e, 0xb3, 0x72, 0xfd, 0x14, 0x60, 0x53, 0x52, 0x62, 0x1b, 0xe0, 0x3b, 0x30, + 0xdb, 0x92, 0xe7, 0xc2, 0x39, 0xcc, 0x9f, 0xf4, 0x7c, 0xe1, 0x49, 0xf0, 0xf4, 0x7f, 0x64, 0x49, 0xe2, 0x4d, 0x99, + 0x8c, 0x5a, 0x4a, 0x9d, 0x03, 0x16, 0xcc, 0xd5, 0xc9, 0x38, 0x81, 0xc0, 0xd8, 0xfb, 0x1b, 0xfe, 0x28, 0xe0, 0x32, 0x0b, 0x7e, 0x5a, 0xb0, 0x68, 0x85, 0xf3, 0x86, 0x6f, 0xc1, 0xf2, 0x94, 0xfd, 0x28, 0x00, 0x89, 0xdc, 0xb0, 0xa0, 0x5a, 0x98, 0x7a, 0xd3, 0x6a, 0x11, 0xad, 0x75, 0x56, 0x42, 0x7b, 0x7a, 0xe9, 0x51, 0xe0, 0xc2, 0xcf, 0xb0, 0xcb, - 0x0f, 0xa2, 0xe9, 0x6f, 0x6a, 0x94, 0xbf, 0xc5, 0x99, 0xe2, 0x87, 0xd0, 0x08, 0xd3, 0x81, 0x85, 0x73, 0xac, 0x58, + 0x0f, 0xa2, 0xe9, 0xef, 0x6a, 0x94, 0xbf, 0xc5, 0x99, 0xe2, 0xc7, 0xd0, 0x08, 0xd3, 0x81, 0x85, 0x73, 0xac, 0x58, 0x30, 0x85, 0xdd, 0x30, 0x9d, 0x99, 0x18, 0x58, 0x4e, 0x6b, 0x85, 0xba, 0x61, 0xe1, 0xda, 0xae, 0xab, 0xe1, 0x34, 0xbb, 0xf1, 0x74, 0xe8, 0x69, 0x4e, 0xeb, 0xd8, 0x10, 0x7f, 0x2c, 0xfb, 0x50, 0xcf, 0xb0, 0x07, 0x65, 0xec, 0xdf, 0xac, 0x27, 0x51, 0x98, 0x9a, 0x13, 0x6f, 0xee, 0x07, 0x77, 0xdd, 0x79, 0x14, 0x46, 0xc9, 0xc2, 0x1b, 0xb1, 0x9e, 0xc4, 0x8f, 0x62, 0xa0, 0x66, 0x1e, 0x2b, 0xd0, 0xb1, 0x5a, 0x31, 0x9b, 0x53, 0xeb, 0x3c, 0x0e, 0xf3, 0x24, 0x60, 0xb7, 0x19, 0xff, 0x7c, 0xa9, 0x32, 0x55, 0xc5, 0x2d, 0x47, 0x2d, 0x80, 0x65, 0xe6, 0x41, 0x9e, 0x21, 0xb5, 0x41, - 0x8f, 0x4b, 0x1d, 0xbb, 0x56, 0xeb, 0x30, 0x66, 0x73, 0xc5, 0x3a, 0xdc, 0xd8, 0x79, 0x1c, 0xad, 0xfa, 0x00, 0x2d, - 0x36, 0x36, 0x13, 0x16, 0x4c, 0xf0, 0x8d, 0x89, 0x71, 0xa5, 0x44, 0x3f, 0x26, 0xda, 0x15, 0x40, 0x6f, 0x6c, 0xde, - 0x83, 0xd7, 0xdd, 0x96, 0x62, 0x4b, 0xfc, 0xf4, 0xb1, 0xbd, 0x90, 0xfa, 0x92, 0xe7, 0x4f, 0x5f, 0x63, 0x75, 0x47, - 0xb1, 0x7b, 0xa0, 0x3f, 0x9e, 0x04, 0xd1, 0xaa, 0x3b, 0xf3, 0xc7, 0x63, 0x16, 0xf6, 0x10, 0xe6, 0xbc, 0x90, 0x05, - 0x81, 0xbf, 0x48, 0xfc, 0xa4, 0x37, 0xf7, 0x6e, 0x79, 0xaf, 0x07, 0x9b, 0x7a, 0x6d, 0xf3, 0x5e, 0xdb, 0x3b, 0xf7, - 0x2a, 0x75, 0x03, 0x31, 0xac, 0xa8, 0x1f, 0x0e, 0xda, 0xa1, 0x62, 0x57, 0xc6, 0xb9, 0x73, 0xaf, 0x8b, 0x98, 0xad, - 0xe7, 0x5e, 0x3c, 0xf5, 0xc3, 0xae, 0x9d, 0x59, 0x37, 0x6b, 0xda, 0x18, 0x8f, 0x3a, 0x9d, 0x4e, 0x66, 0x8d, 0xc5, - 0x93, 0x3d, 0x1e, 0x67, 0xd6, 0x48, 0x3c, 0x4d, 0x26, 0xb6, 0x3d, 0x99, 0x64, 0x96, 0x2f, 0x0a, 0xda, 0xad, 0xd1, - 0xb8, 0xdd, 0xca, 0xac, 0x95, 0x54, 0x23, 0xb3, 0x18, 0x7f, 0x8a, 0xd9, 0xb8, 0x87, 0x1b, 0x89, 0xfb, 0x3f, 0x1f, - 0xdb, 0x76, 0x86, 0x18, 0xe0, 0xb2, 0x84, 0x9b, 0xd0, 0x74, 0xe5, 0x6a, 0xbd, 0x73, 0x4d, 0xa5, 0xf8, 0xdc, 0x68, - 0xd4, 0x58, 0x6f, 0xec, 0xc5, 0x1f, 0xaf, 0x14, 0x69, 0x14, 0x9e, 0x47, 0xd5, 0xd6, 0x62, 0x1a, 0xcc, 0xdb, 0x2e, - 0x24, 0xec, 0xe8, 0x0d, 0xa3, 0x18, 0xce, 0x6c, 0xec, 0x8d, 0xfd, 0x65, 0xd2, 0x75, 0x5a, 0x8b, 0x5b, 0x51, 0xc4, - 0xf7, 0x7a, 0x51, 0x80, 0x67, 0xaf, 0x9b, 0x44, 0x81, 0x3f, 0x16, 0x45, 0x9b, 0xce, 0x92, 0xd3, 0xd2, 0x7b, 0xc8, - 0xbf, 0xfa, 0x18, 0x74, 0xd9, 0x0b, 0x02, 0xc5, 0x6a, 0x27, 0x0a, 0xf3, 0x12, 0x34, 0x97, 0x53, 0xec, 0x84, 0xe6, - 0x05, 0x43, 0xd3, 0x3a, 0x07, 0x8b, 0xdb, 0x7c, 0xcf, 0x3b, 0x47, 0x8b, 0xdb, 0xec, 0xeb, 0x39, 0x1b, 0xfb, 0x9e, - 0xa2, 0x15, 0xbb, 0xc9, 0xb1, 0xc1, 0xa4, 0x4e, 0x5f, 0x6f, 0xd8, 0xa6, 0xe2, 0x58, 0x40, 0x62, 0xa3, 0x3d, 0x7f, - 0x0e, 0x72, 0x18, 0x2f, 0x4c, 0xb3, 0x6c, 0x70, 0x95, 0x65, 0xbd, 0x73, 0x5f, 0xbb, 0xfc, 0xab, 0x46, 0xb4, 0x90, - 0x4c, 0x50, 0x33, 0xfd, 0xca, 0x38, 0x63, 0xb2, 0xbb, 0x0c, 0x90, 0x31, 0x74, 0x95, 0x91, 0x2b, 0x13, 0xbd, 0xad, - 0x57, 0xa6, 0x49, 0xce, 0xab, 0x93, 0xf7, 0x4d, 0xb9, 0x0a, 0x52, 0x20, 0xa8, 0x70, 0xc6, 0xdc, 0x73, 0xc9, 0xf7, - 0x06, 0x98, 0x1e, 0xac, 0x4c, 0x51, 0x85, 0x5e, 0x6f, 0xe2, 0x3d, 0x2f, 0xee, 0xe7, 0x3d, 0xff, 0x96, 0xee, 0xc2, - 0x7b, 0x5e, 0x7c, 0x71, 0xde, 0xf3, 0x75, 0x3d, 0xaa, 0xd0, 0x45, 0xe4, 0xaa, 0xb9, 0xc1, 0x24, 0x90, 0xa6, 0x98, - 0xe2, 0xf5, 0xbf, 0x4e, 0x7f, 0x6d, 0x78, 0x17, 0xd1, 0x1b, 0x12, 0x05, 0xce, 0xa7, 0x82, 0x98, 0xf5, 0x6d, 0xe8, - 0xfe, 0x29, 0x96, 0x9f, 0x27, 0x13, 0xf7, 0x75, 0x24, 0x15, 0xe4, 0x4f, 0xdc, 0x97, 0xa4, 0x14, 0x5b, 0x99, 0xde, - 0xe4, 0xde, 0x3e, 0x90, 0x7d, 0x1a, 0x42, 0xb3, 0x92, 0x6b, 0xf7, 0x38, 0xf7, 0xb9, 0xeb, 0x95, 0x41, 0xd0, 0x72, - 0x27, 0x57, 0x11, 0x80, 0xab, 0x66, 0x19, 0x35, 0x65, 0x42, 0x06, 0xf0, 0xf2, 0xee, 0xfb, 0xb1, 0x76, 0x11, 0xe9, - 0x99, 0x9f, 0xbc, 0xad, 0x86, 0xbf, 0x12, 0x7a, 0x2e, 0x79, 0x38, 0x19, 0xf7, 0x9b, 0x93, 0xa2, 0xdc, 0xe2, 0x6b, - 0x6a, 0x7e, 0x5a, 0x1a, 0x69, 0x57, 0x6e, 0xd8, 0xa3, 0x98, 0xdf, 0x35, 0x62, 0xcc, 0xc3, 0xc4, 0xac, 0x39, 0x97, + 0x8f, 0x4b, 0x1d, 0xbb, 0x56, 0xeb, 0x30, 0x66, 0x73, 0xc5, 0x3a, 0x6c, 0xec, 0x3c, 0x8e, 0x56, 0x7d, 0x80, 0x16, + 0x1b, 0x9b, 0x09, 0x0b, 0x26, 0xf8, 0xc6, 0xc4, 0xb8, 0x52, 0xa2, 0x1f, 0x13, 0xed, 0x0a, 0xa0, 0x37, 0x36, 0xef, + 0xc1, 0xeb, 0x6e, 0x4b, 0xb1, 0x25, 0x7e, 0xfa, 0xd8, 0x5e, 0x48, 0x7d, 0xc9, 0xf3, 0xa7, 0xaf, 0xb1, 0xba, 0xa3, + 0xd8, 0x3d, 0xd0, 0x1f, 0x4f, 0x82, 0x68, 0xd5, 0x9d, 0xf9, 0xe3, 0x31, 0x0b, 0x7b, 0x08, 0x73, 0x5e, 0xc8, 0x82, + 0xc0, 0x5f, 0x24, 0x7e, 0xd2, 0x9b, 0x7b, 0xb7, 0xbc, 0xd7, 0x83, 0xa6, 0x5e, 0xdb, 0xbc, 0xd7, 0xf6, 0xce, 0xbd, + 0x4a, 0xdd, 0x40, 0x0c, 0x2b, 0xea, 0x87, 0x83, 0x76, 0xa8, 0xd8, 0x95, 0x71, 0xee, 0xdc, 0xeb, 0x22, 0x66, 0xeb, + 0xb9, 0x17, 0x4f, 0xfd, 0xb0, 0x6b, 0x67, 0xd6, 0xcd, 0x9a, 0x36, 0xc6, 0xa3, 0x4e, 0xa7, 0x93, 0x59, 0x63, 0xf1, + 0x64, 0x8f, 0xc7, 0x99, 0x35, 0x12, 0x4f, 0x93, 0x89, 0x6d, 0x4f, 0x26, 0x99, 0xe5, 0x8b, 0x82, 0x76, 0x6b, 0x34, + 0x6e, 0xb7, 0x32, 0x6b, 0x25, 0xd5, 0xc8, 0x2c, 0xc6, 0x9f, 0x62, 0x36, 0xee, 0xe1, 0x46, 0xe2, 0xfe, 0xcf, 0xc7, + 0xb6, 0x9d, 0x21, 0x06, 0xb8, 0x2c, 0xe1, 0x26, 0x34, 0x5d, 0xb9, 0x5a, 0xef, 0x5c, 0x53, 0x29, 0x3e, 0x37, 0x1a, + 0xd5, 0xd6, 0x1b, 0x7b, 0xf1, 0xc7, 0x2b, 0x45, 0x1a, 0x85, 0xe7, 0x51, 0xb5, 0xb5, 0x98, 0x06, 0xf3, 0xb6, 0x0b, + 0x09, 0x3b, 0x7a, 0xc3, 0x28, 0x86, 0x33, 0x1b, 0x7b, 0x63, 0x7f, 0x99, 0x74, 0x9d, 0xd6, 0xe2, 0x56, 0x14, 0xf1, + 0xbd, 0x5e, 0x14, 0xe0, 0xd9, 0xeb, 0x26, 0x51, 0xe0, 0x8f, 0x45, 0x51, 0xd3, 0x59, 0x72, 0x5a, 0x7a, 0x0f, 0xf9, + 0x57, 0x1f, 0x83, 0x2e, 0x7b, 0x41, 0xa0, 0x58, 0xed, 0x44, 0x61, 0x5e, 0x82, 0xe6, 0x72, 0x8a, 0x9d, 0xd0, 0xbc, + 0x60, 0x68, 0x5a, 0xe7, 0x60, 0x71, 0x9b, 0xef, 0x79, 0xe7, 0x68, 0x71, 0x9b, 0x7d, 0x3d, 0x67, 0x63, 0xdf, 0x53, + 0xb4, 0x62, 0x37, 0x39, 0x36, 0x98, 0xd4, 0xe9, 0xeb, 0x86, 0x6d, 0x2a, 0x8e, 0x05, 0x24, 0x36, 0xda, 0xf3, 0xe7, + 0x20, 0x87, 0xf1, 0xc2, 0x34, 0xcb, 0x06, 0x57, 0x59, 0xd6, 0x3b, 0xf7, 0xb5, 0xcb, 0xff, 0xd6, 0x88, 0x16, 0x92, + 0x09, 0x6a, 0xa6, 0x5f, 0x19, 0x67, 0x4c, 0x76, 0x97, 0x01, 0x32, 0x86, 0xae, 0x32, 0x72, 0x65, 0xa2, 0xb7, 0x9b, + 0x95, 0x69, 0x92, 0xf3, 0xea, 0xe4, 0x7d, 0x53, 0xae, 0x82, 0x14, 0x08, 0x2a, 0x9c, 0x31, 0xf7, 0x5c, 0xf2, 0xbd, + 0x01, 0xa6, 0x07, 0x2b, 0x53, 0x54, 0xa1, 0xd7, 0x4d, 0xbc, 0xe7, 0xc5, 0xfd, 0xbc, 0xe7, 0x5f, 0xd3, 0x5d, 0x78, + 0xcf, 0x8b, 0x2f, 0xce, 0x7b, 0xbe, 0xde, 0x8c, 0x2a, 0x74, 0x11, 0xb9, 0x6a, 0x6e, 0x30, 0x09, 0xa4, 0x29, 0xa6, + 0x78, 0xfd, 0xaf, 0xd3, 0xdf, 0x1a, 0xde, 0x45, 0xf4, 0x86, 0x44, 0x81, 0xf3, 0xa9, 0x20, 0x66, 0x7d, 0x1b, 0xba, + 0x7f, 0x8e, 0xe5, 0xe7, 0xc9, 0xc4, 0x7d, 0x1d, 0x49, 0x05, 0xf9, 0x13, 0xf7, 0x25, 0x29, 0xc5, 0x56, 0xa6, 0x37, + 0xb9, 0xb7, 0x0f, 0x64, 0x9f, 0x86, 0xd0, 0xac, 0xe4, 0xda, 0x3d, 0xce, 0x7d, 0xee, 0x7a, 0x65, 0x10, 0xb4, 0xdc, + 0xc9, 0x55, 0x04, 0xe0, 0xda, 0xb0, 0x8c, 0x9a, 0x32, 0x21, 0x03, 0x78, 0x79, 0xf7, 0xfd, 0x58, 0xbb, 0x88, 0xf4, + 0xcc, 0x4f, 0xde, 0x56, 0xc3, 0x5f, 0x09, 0x3d, 0x97, 0x3c, 0x9c, 0x8c, 0xfb, 0xcd, 0x49, 0x51, 0x6e, 0xf1, 0x35, + 0x35, 0x3f, 0x2d, 0x8d, 0xb4, 0x2b, 0x37, 0xec, 0x51, 0xcc, 0xef, 0x0d, 0x62, 0xcc, 0xc3, 0xc4, 0xac, 0x39, 0x97, 0xb7, 0xc6, 0x67, 0x88, 0x1a, 0x3a, 0xa6, 0xe6, 0xfe, 0x38, 0xcb, 0xf4, 0x9e, 0x98, 0x08, 0x89, 0xd0, 0xb2, 0xfb, 0x98, 0xb8, 0xa4, 0x10, 0x02, 0x71, 0x89, 0x0f, 0x59, 0x33, 0x5f, 0x80, 0x7f, 0x00, 0xb7, 0x7d, 0xe6, 0x73, 0xa6, - 0x2a, 0x34, 0x7d, 0xe4, 0x37, 0x22, 0x0d, 0x08, 0x0c, 0xda, 0x65, 0x6f, 0xab, 0xd2, 0x82, 0xd4, 0x1d, 0x5b, 0x69, - 0x72, 0xd0, 0xc1, 0x01, 0x62, 0xfc, 0x0a, 0xb1, 0x10, 0xa1, 0x1d, 0x5e, 0x07, 0x1f, 0x32, 0x35, 0xe7, 0xfd, 0x70, - 0xfb, 0xf5, 0x4f, 0xf6, 0xa1, 0x41, 0xbf, 0xa2, 0x74, 0xbb, 0xc7, 0x2f, 0x13, 0x58, 0x89, 0x64, 0x65, 0x58, 0xc9, - 0x4a, 0x79, 0xb6, 0x16, 0xf1, 0xb1, 0x53, 0x6f, 0x61, 0x82, 0x96, 0x07, 0x71, 0x2f, 0xc7, 0x78, 0x52, 0x28, 0xee, - 0xde, 0x32, 0x01, 0xdc, 0x88, 0x72, 0x14, 0xc4, 0x3f, 0xbd, 0xd1, 0x32, 0x4e, 0xa2, 0xb8, 0xbb, 0x88, 0xfc, 0x30, - 0x65, 0x71, 0x46, 0x82, 0x15, 0x9c, 0x1f, 0x31, 0x3d, 0x57, 0xeb, 0x68, 0xe1, 0x8d, 0xfc, 0xf4, 0xae, 0x6b, 0x73, - 0x96, 0xc2, 0xee, 0x71, 0xee, 0xc0, 0x6e, 0xac, 0xdf, 0xe5, 0xb3, 0xf9, 0x1c, 0x19, 0xbf, 0xb8, 0xce, 0xce, 0xc8, - 0xdb, 0xbc, 0x27, 0xbd, 0xa5, 0x08, 0xe1, 0xc0, 0x7e, 0x78, 0xb1, 0x39, 0x05, 0x2c, 0x0f, 0x4b, 0x6d, 0x8f, 0xd9, - 0xd4, 0x40, 0xac, 0x0d, 0x66, 0x86, 0xe2, 0x8f, 0x75, 0xa8, 0x2b, 0x76, 0x73, 0x31, 0x70, 0x3c, 0xfa, 0x2e, 0x90, - 0x75, 0xbd, 0x49, 0xca, 0x62, 0x63, 0x97, 0x9a, 0x43, 0x36, 0x89, 0x62, 0x46, 0xd9, 0xe4, 0x9c, 0xce, 0xe2, 0x76, - 0xf7, 0xee, 0xb7, 0x0f, 0xbf, 0xb9, 0x9f, 0x30, 0x4a, 0x35, 0xd1, 0x99, 0x7e, 0x4f, 0x6f, 0x75, 0x7a, 0x06, 0xac, - 0x21, 0xcd, 0xfc, 0x88, 0xa4, 0x20, 0x10, 0x09, 0xac, 0x31, 0x69, 0xc7, 0x22, 0xe2, 0x34, 0x2f, 0x66, 0x81, 0x97, - 0xfa, 0x37, 0x82, 0x67, 0x6c, 0x1f, 0x2d, 0x6e, 0xc5, 0x1a, 0x23, 0xc1, 0x7b, 0xc0, 0x22, 0x55, 0x40, 0x11, 0x8b, - 0x54, 0x2d, 0xc6, 0x45, 0xea, 0xd5, 0x46, 0x23, 0xe2, 0x58, 0x57, 0x28, 0xfd, 0xe1, 0xe2, 0x56, 0x26, 0xd1, 0x45, - 0xb3, 0x9c, 0x52, 0x57, 0x13, 0x90, 0xcc, 0xfd, 0xf1, 0x38, 0x60, 0x59, 0x69, 0xa1, 0xcb, 0x6b, 0x29, 0x4d, 0x4e, - 0x3e, 0x0f, 0xde, 0x30, 0x89, 0x82, 0x65, 0xca, 0x9a, 0xa7, 0x4b, 0x48, 0x74, 0x8b, 0xc9, 0xc1, 0xdf, 0x65, 0x58, - 0x0f, 0x81, 0xdd, 0x86, 0x6d, 0x62, 0xf7, 0x20, 0xdf, 0xa0, 0xd9, 0x2e, 0x83, 0x0e, 0xaf, 0x72, 0xa0, 0x8d, 0x86, - 0x81, 0x18, 0x40, 0x96, 0x08, 0x7b, 0x2b, 0x96, 0xc3, 0xcb, 0xf2, 0x9c, 0x6b, 0x79, 0x51, 0x56, 0x1e, 0xcc, 0x6f, - 0x73, 0xc6, 0x5e, 0x34, 0x9f, 0xb1, 0x17, 0xe2, 0x8c, 0x6d, 0xdf, 0x99, 0x8f, 0x26, 0x0e, 0xfc, 0xd7, 0x2b, 0x06, - 0xd4, 0xb5, 0x95, 0xf6, 0xe2, 0x56, 0x71, 0x16, 0xb7, 0x8a, 0xd9, 0x5a, 0xdc, 0x2a, 0xd8, 0x35, 0xba, 0xb7, 0x18, - 0x56, 0x4b, 0x37, 0x6c, 0x05, 0x0a, 0xe1, 0x8f, 0x5d, 0x7a, 0xe5, 0x1c, 0xc0, 0x3b, 0x68, 0x75, 0x58, 0x7f, 0xd7, - 0xda, 0x7e, 0xd4, 0xe9, 0x2c, 0x09, 0xa4, 0xad, 0x5b, 0xa9, 0x37, 0x1c, 0x82, 0x28, 0x33, 0x1a, 0x2d, 0x93, 0x7f, - 0x72, 0xf8, 0xf9, 0x24, 0x6e, 0x45, 0x04, 0x95, 0x7e, 0x44, 0x53, 0x50, 0x14, 0xde, 0x30, 0xd1, 0xc3, 0x3a, 0x5f, - 0xa7, 0x2e, 0x25, 0x47, 0x6c, 0x59, 0x07, 0x0d, 0x9b, 0xbc, 0x79, 0xa2, 0x7f, 0xb3, 0x55, 0xda, 0x8c, 0x62, 0x3e, - 0x63, 0x5a, 0xb6, 0x4e, 0xc7, 0xc3, 0x67, 0x83, 0xaf, 0xa6, 0xdd, 0x69, 0x06, 0xf7, 0x52, 0x7c, 0xe9, 0x4a, 0x10, - 0x15, 0x4e, 0xb7, 0x78, 0x28, 0x8e, 0xed, 0xbd, 0x6e, 0xda, 0x23, 0xb5, 0x5e, 0xb7, 0x10, 0x84, 0xa2, 0xee, 0x8e, - 0x58, 0xfe, 0xd1, 0x8b, 0x03, 0xf8, 0x8f, 0xb8, 0xfa, 0xbf, 0xa5, 0x4d, 0x8c, 0xfa, 0xeb, 0xb4, 0xc4, 0xa8, 0x13, - 0xab, 0x84, 0x8c, 0xf8, 0xee, 0xf5, 0x27, 0x93, 0x87, 0x35, 0xd8, 0xb9, 0x36, 0x79, 0x86, 0x55, 0x6b, 0xbf, 0x8c, - 0xa2, 0x80, 0x79, 0x61, 0xbd, 0xba, 0x98, 0x1e, 0x72, 0xf3, 0x4f, 0x5d, 0x68, 0x24, 0xee, 0x11, 0xe4, 0x94, 0xa0, - 0x62, 0x1b, 0xba, 0x4a, 0x9c, 0x6f, 0xba, 0x4a, 0xbc, 0xbb, 0xff, 0x2a, 0xf1, 0xc7, 0x9d, 0xae, 0x12, 0xef, 0xbe, - 0xf8, 0x55, 0xe2, 0xbc, 0x7e, 0x95, 0x38, 0x8f, 0x84, 0x3b, 0xb0, 0xf1, 0x66, 0xc9, 0x7f, 0x7e, 0x20, 0x7b, 0xdf, - 0x77, 0x91, 0x7b, 0x68, 0x53, 0xc2, 0xc3, 0x8b, 0x5f, 0x7d, 0xb1, 0xc0, 0x8d, 0xf8, 0x0e, 0xbd, 0xe3, 0x8a, 0xab, - 0x05, 0xc7, 0xec, 0xf8, 0x1d, 0xa9, 0x38, 0x88, 0xc2, 0xe9, 0x4f, 0x60, 0xef, 0x0d, 0xe2, 0xc0, 0x58, 0x7a, 0xe1, - 0x27, 0x3f, 0x45, 0x8b, 0xe5, 0x02, 0x15, 0x55, 0x1f, 0xfc, 0xc4, 0x1f, 0x06, 0x2c, 0x8f, 0x30, 0x49, 0x5a, 0x57, - 0x2e, 0x5b, 0x07, 0xc5, 0xab, 0xf8, 0xe9, 0xdd, 0x8a, 0x9f, 0xe8, 0x62, 0xcb, 0x7f, 0x93, 0x9b, 0xa0, 0xda, 0x7c, - 0x11, 0x11, 0x16, 0x62, 0x12, 0xd0, 0x0f, 0xbf, 0x8c, 0x9c, 0x8b, 0x58, 0x5e, 0xa5, 0x51, 0x0a, 0xf7, 0x8d, 0x8d, - 0xfd, 0xb0, 0x6a, 0x3f, 0x6f, 0x96, 0xba, 0x91, 0x27, 0xe0, 0xa8, 0x8b, 0xf3, 0xe7, 0xd1, 0x32, 0x61, 0xe3, 0x68, - 0x15, 0xaa, 0x46, 0xc8, 0xf5, 0xaa, 0x11, 0xca, 0xd4, 0xf3, 0x36, 0x65, 0x85, 0xa3, 0x6a, 0x2d, 0x60, 0x0e, 0x4d, - 0xd2, 0x60, 0x9b, 0x38, 0x44, 0x55, 0x84, 0x6c, 0xea, 0xed, 0x69, 0x5a, 0xe4, 0x3e, 0xac, 0xa5, 0xf0, 0x3c, 0x89, - 0x2c, 0x2e, 0x15, 0x4e, 0xb4, 0x50, 0x08, 0x17, 0x45, 0x14, 0xec, 0x86, 0x85, 0xe3, 0x6f, 0x28, 0x42, 0x64, 0xf1, - 0x16, 0x74, 0x55, 0xd9, 0x92, 0xaf, 0x07, 0x8f, 0x09, 0x4d, 0x8f, 0xaf, 0xa4, 0x69, 0x7c, 0x7b, 0xc3, 0xe2, 0xc0, - 0xbb, 0xd3, 0xf4, 0x2c, 0x0a, 0x7f, 0x80, 0x09, 0x78, 0x1d, 0xad, 0x42, 0xb9, 0x02, 0xa6, 0x6a, 0x6f, 0xd8, 0x4b, - 0x8d, 0xd1, 0xcb, 0x21, 0x66, 0x87, 0x04, 0x81, 0x6f, 0x2d, 0xbc, 0x29, 0xfb, 0x8b, 0x41, 0xff, 0xfe, 0x55, 0xcf, - 0x8c, 0x77, 0x51, 0xfe, 0xa1, 0x9f, 0x17, 0x3b, 0x7c, 0xe6, 0xc9, 0x93, 0xbd, 0xcd, 0xc3, 0xd6, 0x46, 0x01, 0xf3, - 0x62, 0x01, 0x45, 0x43, 0x6b, 0x7d, 0xe3, 0x29, 0x00, 0x28, 0x2e, 0xa2, 0xe5, 0x68, 0x86, 0x7e, 0xbb, 0x5f, 0x6e, - 0xbc, 0x29, 0xf4, 0xc9, 0x92, 0x4b, 0xfb, 0x2a, 0x1f, 0x7a, 0xa5, 0xa8, 0x98, 0x05, 0xfc, 0xfe, 0x19, 0xa4, 0xdf, - 0xfa, 0x0f, 0x4e, 0x43, 0x7d, 0xd7, 0xe4, 0x21, 0xbf, 0x1e, 0xb4, 0x79, 0x7b, 0x3e, 0x44, 0xe5, 0xa1, 0xc0, 0xd6, - 0x42, 0x49, 0xd7, 0x8c, 0x64, 0xb2, 0xea, 0xa4, 0xc9, 0x49, 0x64, 0x36, 0xe5, 0xc7, 0x11, 0x5f, 0x61, 0x56, 0xc9, - 0x6a, 0xc4, 0x60, 0x1c, 0x5b, 0x55, 0x90, 0x0c, 0xf7, 0xa6, 0x60, 0x88, 0xbe, 0xaa, 0xef, 0xe6, 0x7e, 0x68, 0x60, - 0x0e, 0xd8, 0xfa, 0x1b, 0xef, 0x16, 0xb2, 0x20, 0x02, 0x72, 0xab, 0xbe, 0x82, 0x42, 0x43, 0x8e, 0x16, 0xe4, 0x8d, - 0xc7, 0x9a, 0xda, 0x38, 0x13, 0x42, 0x1b, 0x38, 0xf8, 0x4a, 0x51, 0x14, 0x25, 0xbf, 0x46, 0x28, 0xf9, 0x3d, 0x02, - 0xcb, 0xf1, 0x3a, 0x00, 0xda, 0x92, 0x6c, 0x71, 0x4b, 0x25, 0x70, 0x33, 0x40, 0xfb, 0x69, 0x51, 0xc0, 0x13, 0xfd, - 0x80, 0x71, 0x0b, 0x15, 0x88, 0x0b, 0x3d, 0xa8, 0xbe, 0xbd, 0x18, 0xf2, 0x01, 0x76, 0x15, 0xbc, 0xb0, 0xe3, 0x5b, - 0x2e, 0x09, 0x56, 0x6c, 0x7a, 0x1c, 0xf4, 0x58, 0x73, 0x46, 0x98, 0x50, 0xc2, 0x82, 0xa0, 0x75, 0xa8, 0x24, 0x78, - 0x34, 0x58, 0x03, 0x6e, 0xc4, 0x7b, 0xd1, 0x6d, 0x3a, 0x67, 0xe1, 0x52, 0x35, 0xc0, 0xea, 0x04, 0x33, 0xf4, 0x40, - 0x9d, 0xd7, 0xc4, 0x6c, 0x01, 0xb6, 0x69, 0x6e, 0x39, 0x23, 0x5a, 0x28, 0x4c, 0x55, 0x3c, 0x63, 0xc4, 0x03, 0xe0, - 0x24, 0x1c, 0xb7, 0x55, 0x29, 0x04, 0x5f, 0xd2, 0xa8, 0x8c, 0xcd, 0x79, 0xc8, 0x2b, 0xe4, 0x14, 0xc8, 0x46, 0x8c, - 0x8b, 0x8b, 0xc4, 0xb4, 0x6b, 0x5e, 0x75, 0xd1, 0x72, 0x8d, 0x8c, 0x57, 0x11, 0x14, 0xc5, 0x7a, 0xbd, 0x1b, 0x0e, - 0x27, 0xa4, 0x25, 0xd8, 0xd8, 0xcf, 0xa8, 0xd6, 0xcf, 0x86, 0x41, 0x7f, 0x64, 0x77, 0x44, 0x48, 0x68, 0xaa, 0x3e, - 0xb2, 0x3b, 0x30, 0x0e, 0x3f, 0x03, 0x69, 0x8a, 0xba, 0x05, 0x5d, 0x1b, 0x90, 0xe8, 0x77, 0x04, 0xa9, 0x2a, 0xb6, - 0x1c, 0x20, 0x3b, 0xdb, 0x82, 0xc5, 0x29, 0x1c, 0xa9, 0x91, 0xf4, 0xc4, 0x21, 0xe6, 0x11, 0x0b, 0xb4, 0xc6, 0x39, - 0x36, 0x1b, 0x8e, 0x86, 0xfe, 0xcc, 0xb1, 0xed, 0xfd, 0x5a, 0x7d, 0x10, 0x64, 0x37, 0xd5, 0xd6, 0x8d, 0xd4, 0x75, - 0x6c, 0xd3, 0x7f, 0x66, 0xb5, 0x7a, 0x35, 0x1a, 0x2d, 0x65, 0x92, 0x1a, 0xa0, 0xf8, 0xab, 0xff, 0x78, 0xad, 0xd5, - 0x0e, 0xa4, 0x5e, 0x8d, 0x00, 0x80, 0xb0, 0x65, 0x5c, 0xfe, 0x35, 0xa8, 0x93, 0x7e, 0xca, 0x63, 0x45, 0x59, 0xcd, - 0x07, 0x90, 0x0b, 0x51, 0x83, 0x63, 0xf4, 0x07, 0xe5, 0xb9, 0xa2, 0xd1, 0xf1, 0xd1, 0xf5, 0x41, 0x4f, 0x60, 0x14, - 0x11, 0x22, 0x47, 0xee, 0xa0, 0xf2, 0xc5, 0xa4, 0x8a, 0xe1, 0x78, 0xd6, 0x35, 0x56, 0x68, 0xf4, 0xb6, 0x72, 0x0b, - 0xd8, 0xff, 0x06, 0xf2, 0x69, 0x0d, 0x21, 0xc6, 0x23, 0xd4, 0x80, 0xcc, 0xa9, 0xf7, 0x76, 0x08, 0xe1, 0x79, 0xe5, - 0xee, 0xca, 0x44, 0x72, 0xf7, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x99, 0xdc, 0x3d, 0xb0, 0x4b, 0x16, - 0x8e, 0xcb, 0x1d, 0x56, 0xe8, 0xd7, 0xee, 0xdd, 0x95, 0x30, 0x0a, 0xa4, 0x14, 0x8e, 0x1a, 0x30, 0x4a, 0x16, 0x85, - 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x3b, 0x71, 0x31, 0xd8, 0x80, 0xf2, 0x81, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0xe4, 0xad, - 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0x37, 0xee, 0xc4, 0x54, 0xb8, 0x2b, 0x16, 0x6d, 0x7c, 0x9e, 0x89, 0x6a, 0x57, - 0xa9, 0xb5, 0x7f, 0xbf, 0xd4, 0x3a, 0xbd, 0x4f, 0x6a, 0x4d, 0xd1, 0x61, 0xb8, 0x3d, 0xa8, 0x88, 0x92, 0x23, 0x98, - 0x73, 0x39, 0xce, 0x50, 0x49, 0xd4, 0x8d, 0xc1, 0x64, 0x1a, 0xac, 0x48, 0xa9, 0x37, 0x72, 0x40, 0x44, 0xf1, 0xb7, - 0x74, 0x41, 0x11, 0x0a, 0x75, 0x59, 0x36, 0x7e, 0x5e, 0xc8, 0xc6, 0xe9, 0x56, 0x53, 0xc4, 0x05, 0x11, 0xdc, 0xbf, - 0x14, 0x73, 0x27, 0xbf, 0x1d, 0x14, 0xb1, 0x77, 0x0a, 0x48, 0xa5, 0x68, 0x32, 0xc5, 0x45, 0x43, 0x8a, 0x51, 0x24, - 0x6e, 0x19, 0xe5, 0x50, 0x45, 0xe5, 0xaa, 0x45, 0x30, 0x99, 0xa2, 0x1c, 0xa4, 0xee, 0x08, 0x72, 0x5e, 0x2c, 0x6f, - 0x9b, 0x72, 0x34, 0x11, 0xf9, 0xb5, 0xb4, 0x49, 0xf2, 0xb0, 0x1f, 0x34, 0xc1, 0x42, 0x4c, 0x5f, 0xd1, 0x6b, 0xe7, - 0x36, 0x10, 0x08, 0x64, 0x43, 0x94, 0xa2, 0xfb, 0xa5, 0xf3, 0x94, 0x2d, 0xb9, 0x50, 0x5d, 0x3b, 0x48, 0xdd, 0x49, - 0x13, 0x2c, 0xcb, 0x23, 0x70, 0xae, 0xaf, 0x24, 0x09, 0x42, 0xd7, 0x56, 0xec, 0x5e, 0x03, 0x03, 0x80, 0xf4, 0xbf, - 0xfa, 0xcc, 0x59, 0x01, 0x90, 0x44, 0x2a, 0xb6, 0xac, 0xf3, 0xc7, 0x43, 0x6c, 0x92, 0x25, 0x3b, 0x56, 0xad, 0x7f, - 0x93, 0xe4, 0x3d, 0x6b, 0x1e, 0x13, 0xa4, 0x2c, 0xce, 0xe7, 0x35, 0xba, 0x02, 0x0e, 0xbe, 0xcb, 0xe2, 0x65, 0x88, - 0x49, 0x70, 0xcd, 0x34, 0xf6, 0x46, 0x1f, 0xd7, 0xd2, 0xf7, 0xb8, 0x48, 0x14, 0xc4, 0xc5, 0x65, 0xa5, 0x42, 0xcf, - 0xc3, 0x9c, 0x51, 0xac, 0x6b, 0xb5, 0x12, 0x49, 0x50, 0xd3, 0x7d, 0x64, 0xb7, 0xbd, 0x17, 0x93, 0x83, 0x8a, 0xfc, - 0xb4, 0x75, 0x58, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa3, 0x5f, 0x78, 0xf4, 0xa4, 0xdf, 0xff, 0xd3, 0x09, 0xff, 0x66, - 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x5a, 0xc9, 0x26, 0xb0, 0x26, 0x7e, 0x10, - 0x98, 0x01, 0xb8, 0x31, 0xac, 0x3f, 0x6b, 0x78, 0xd8, 0xcf, 0x12, 0xb2, 0x15, 0x7e, 0x46, 0x3f, 0xe5, 0x9d, 0x92, - 0xce, 0x96, 0xf3, 0xe1, 0x5a, 0x16, 0x94, 0x4b, 0xf2, 0xf3, 0xba, 0xcc, 0x5c, 0xfe, 0xec, 0x64, 0x32, 0x29, 0x4b, - 0x8d, 0x6d, 0xe5, 0x00, 0x25, 0xbf, 0x8f, 0x6c, 0xdb, 0xae, 0xce, 0xef, 0xa6, 0x83, 0x42, 0x07, 0xc3, 0x44, 0x21, - 0x7c, 0xe7, 0xfe, 0x3d, 0xf5, 0x3b, 0x41, 0x4b, 0x5d, 0x6d, 0x3a, 0x8f, 0xb4, 0xd5, 0xfe, 0x2b, 0x40, 0x41, 0xd4, - 0x70, 0xdf, 0xf1, 0xaf, 0xef, 0x95, 0x2d, 0x3d, 0x55, 0x0f, 0xf0, 0xc3, 0x1a, 0xdf, 0xb3, 0xd7, 0x77, 0x68, 0xba, - 0x69, 0x7b, 0x67, 0x56, 0x41, 0x76, 0x4b, 0x36, 0x4b, 0x3d, 0xb2, 0x54, 0xf2, 0x53, 0x36, 0x4f, 0xba, 0x23, 0x86, - 0x0a, 0x52, 0x4b, 0xa2, 0xb6, 0x68, 0xd5, 0x63, 0x4e, 0xc1, 0x8e, 0xcb, 0x11, 0x78, 0xd8, 0x56, 0x50, 0x59, 0x55, - 0xd3, 0xac, 0x89, 0x8f, 0x20, 0x15, 0x5b, 0xd7, 0x15, 0x4e, 0xb8, 0x4d, 0x0f, 0xed, 0x3f, 0x94, 0xea, 0x29, 0xc0, - 0x9d, 0xae, 0x85, 0xb5, 0x09, 0x29, 0x4f, 0xf0, 0xef, 0x5c, 0x39, 0xf7, 0x62, 0x71, 0x5b, 0x36, 0xee, 0xea, 0x80, - 0xba, 0xa9, 0x20, 0x65, 0x04, 0x75, 0x13, 0xea, 0xcb, 0x4d, 0x80, 0x26, 0xb2, 0x75, 0x0b, 0x58, 0xd0, 0x88, 0x29, - 0xa8, 0xe8, 0x08, 0x73, 0x50, 0xf1, 0x3a, 0x0b, 0x3b, 0xaf, 0x90, 0xef, 0xe3, 0x2f, 0xc8, 0x52, 0x0e, 0xe9, 0x4e, - 0xfe, 0x60, 0x3c, 0xef, 0xa0, 0x72, 0xaf, 0xb4, 0x55, 0xd1, 0x54, 0x06, 0xf7, 0x80, 0xb8, 0x91, 0x2a, 0xcb, 0x38, - 0x30, 0x29, 0x71, 0xbd, 0xa6, 0xaf, 0xeb, 0xe3, 0xde, 0xdc, 0xbd, 0x73, 0x08, 0x7a, 0x8d, 0xfa, 0x54, 0xed, 0xa4, - 0xda, 0xab, 0xea, 0xb0, 0x05, 0x9c, 0xb0, 0x02, 0xe0, 0x33, 0xab, 0xa0, 0xd1, 0x90, 0x52, 0xc1, 0x7d, 0x34, 0xe8, - 0xfc, 0xad, 0x8c, 0xac, 0xc5, 0x38, 0xb1, 0xbb, 0xe6, 0x2a, 0xd4, 0xb7, 0xd0, 0x0c, 0xc2, 0xdc, 0x71, 0xec, 0x84, - 0xcf, 0x26, 0xec, 0x18, 0x19, 0x5d, 0x39, 0xb8, 0x83, 0xf0, 0x94, 0x9a, 0x94, 0xfc, 0x84, 0x4e, 0x29, 0xea, 0x12, - 0xfe, 0xd8, 0x28, 0xbc, 0xbf, 0x28, 0x49, 0xe3, 0x79, 0xd0, 0x89, 0x96, 0xbe, 0x53, 0xed, 0xb9, 0x1f, 0xee, 0x5e, - 0xd7, 0xbb, 0xdd, 0xb9, 0x2e, 0x30, 0x87, 0x3b, 0x57, 0x06, 0xee, 0x12, 0x2b, 0x5f, 0xa4, 0xee, 0x1f, 0x25, 0xe5, - 0x81, 0x1c, 0x30, 0x51, 0xc5, 0x56, 0x74, 0xa3, 0xff, 0x71, 0xe9, 0x0e, 0x4e, 0x4e, 0x6f, 0xe7, 0x81, 0x72, 0xc3, - 0xe2, 0x04, 0x12, 0x4a, 0xa8, 0x8e, 0x65, 0xab, 0x0a, 0x1a, 0xf4, 0xfb, 0xe1, 0xd4, 0x55, 0x7f, 0xbe, 0x78, 0x63, - 0x76, 0xd4, 0x53, 0x30, 0xc7, 0xb8, 0x99, 0x22, 0x8b, 0x7b, 0xee, 0xdd, 0xb1, 0xf8, 0xba, 0xc5, 0x3d, 0x7e, 0x88, - 0xb9, 0xc5, 0x32, 0xa5, 0xa5, 0xee, 0x90, 0x12, 0x5e, 0xb9, 0xf1, 0xd9, 0xea, 0x65, 0x74, 0xeb, 0xaa, 0x80, 0x58, - 0x9d, 0x56, 0x47, 0x71, 0x5a, 0x07, 0xd6, 0x51, 0x47, 0xed, 0x7f, 0xa5, 0x28, 0x27, 0x63, 0x36, 0x49, 0xfa, 0x28, - 0x8e, 0x39, 0x41, 0x7e, 0x90, 0x7e, 0x2b, 0x8a, 0x35, 0x0a, 0x12, 0xd3, 0x51, 0xd6, 0xfc, 0x51, 0x51, 0x00, 0x19, - 0x75, 0x95, 0x47, 0x93, 0xd6, 0xe4, 0x60, 0xf2, 0xa2, 0xc7, 0x8b, 0xb3, 0xaf, 0x4a, 0xd5, 0x0d, 0xfa, 0xb7, 0x25, - 0x35, 0x4b, 0xd2, 0x38, 0xfa, 0xc8, 0x38, 0x2f, 0xa9, 0xe4, 0x82, 0xa2, 0x6a, 0xd3, 0x56, 0xfd, 0x4b, 0x4e, 0x67, - 0x38, 0x9a, 0xb4, 0x8a, 0xea, 0x08, 0xe3, 0x7e, 0x0e, 0xe4, 0xc9, 0xbe, 0x00, 0xfd, 0x44, 0x9e, 0x26, 0xc7, 0x6c, - 0x9a, 0x28, 0x47, 0xe5, 0x63, 0x9c, 0x8a, 0xf1, 0x9d, 0x40, 0xc6, 0xb5, 0xc2, 0x7b, 0x31, 0xc1, 0x66, 0xae, 0xfa, - 0x83, 0xd3, 0xea, 0x18, 0x8e, 0x73, 0x64, 0x1d, 0x75, 0x46, 0xb6, 0x71, 0x60, 0x1d, 0x98, 0x6d, 0xeb, 0xc8, 0xe8, - 0x98, 0x1d, 0xa3, 0xf3, 0x5d, 0x67, 0x64, 0x1e, 0x58, 0x07, 0x86, 0x6d, 0x76, 0xa0, 0xd0, 0xec, 0x98, 0x9d, 0x1b, - 0xf3, 0xa0, 0x33, 0xb2, 0xb1, 0xb4, 0x65, 0x1d, 0x1e, 0x9a, 0x8e, 0x6d, 0x1d, 0x1e, 0x1a, 0x87, 0xd6, 0xd1, 0x91, - 0xe9, 0xb4, 0xad, 0xa3, 0xa3, 0xf3, 0xc3, 0x8e, 0xd5, 0x86, 0x77, 0xed, 0xf6, 0xa8, 0x6d, 0x39, 0x8e, 0x09, 0x7f, - 0x19, 0x1d, 0xab, 0x45, 0x3f, 0x1c, 0xc7, 0x6a, 0x3b, 0x86, 0x1d, 0x1c, 0xb6, 0xac, 0xa3, 0x17, 0x06, 0xfe, 0x8d, - 0xd5, 0x0c, 0xfc, 0x0b, 0xba, 0x31, 0x5e, 0x58, 0xad, 0x23, 0xfa, 0x85, 0x1d, 0xde, 0x1c, 0x74, 0xfe, 0xa6, 0xee, - 0x6f, 0x1c, 0x83, 0x43, 0x63, 0xe8, 0x1c, 0x5a, 0xed, 0xb6, 0x71, 0xe0, 0x58, 0x9d, 0xf6, 0xcc, 0x3c, 0x68, 0x59, - 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, 0x6c, 0x5b, 0x2d, 0xc3, 0xb1, 0x0e, 0xda, 0xf8, 0xa3, 0x6d, - 0xb5, 0x6e, 0x8e, 0x5f, 0x58, 0x47, 0x87, 0xb3, 0x23, 0xeb, 0xe0, 0xc3, 0x41, 0xc7, 0x6a, 0xb5, 0x67, 0xed, 0x23, - 0xab, 0x75, 0x7c, 0x73, 0x64, 0x1d, 0xcc, 0xcc, 0xd6, 0xd1, 0xd6, 0x96, 0x4e, 0xcb, 0x82, 0x39, 0xc2, 0xd7, 0xf0, - 0xc2, 0xe0, 0x2f, 0xe0, 0xcf, 0x0c, 0xdb, 0xfe, 0x8e, 0xdd, 0x24, 0xf5, 0xa6, 0x2f, 0xac, 0xce, 0xf1, 0x88, 0xaa, - 0x43, 0x81, 0x29, 0x6a, 0x40, 0x93, 0x1b, 0x93, 0x3e, 0x8b, 0xdd, 0x99, 0xa2, 0x23, 0xf1, 0x87, 0x7f, 0xec, 0xc6, - 0x84, 0x0f, 0xd3, 0x77, 0xff, 0xa3, 0xfd, 0xe4, 0x4b, 0x7e, 0xb2, 0x3f, 0xa5, 0xad, 0x3f, 0xed, 0x7f, 0x75, 0x02, - 0x87, 0xbb, 0x3f, 0x30, 0x7e, 0xd9, 0xa4, 0x94, 0xfc, 0xc7, 0xfd, 0x4a, 0xc9, 0x97, 0xcb, 0x5d, 0x94, 0x92, 0xff, - 0xf8, 0xe2, 0x4a, 0xc9, 0x5f, 0xaa, 0xbe, 0x35, 0x6f, 0xaa, 0x59, 0xa8, 0xff, 0xb8, 0xae, 0x8a, 0x1c, 0x12, 0x4f, - 0xbb, 0xfc, 0x71, 0x79, 0x05, 0xf1, 0xe3, 0xdf, 0x44, 0xee, 0xcb, 0x65, 0xc9, 0xe0, 0x33, 0x02, 0x1c, 0xfb, 0x26, - 0x22, 0x1c, 0xfb, 0x61, 0xe9, 0x82, 0x95, 0x19, 0x67, 0x73, 0xfc, 0xb1, 0x39, 0xf3, 0x82, 0x49, 0xce, 0x22, 0x41, - 0x49, 0x0f, 0x8b, 0xc1, 0x6f, 0x1e, 0xc8, 0x33, 0xdc, 0x64, 0x96, 0xf3, 0x30, 0x01, 0x8b, 0x60, 0xb0, 0xe4, 0x98, - 0xc4, 0x59, 0xa5, 0xb1, 0x25, 0x22, 0xee, 0x5f, 0x73, 0x8f, 0xe2, 0x8d, 0xef, 0xd1, 0x00, 0xb8, 0xb9, 0x77, 0xa7, - 0xde, 0xaf, 0x02, 0x96, 0x75, 0xc2, 0x40, 0x1a, 0xb8, 0xfd, 0xa6, 0xf7, 0x65, 0x33, 0xdc, 0x8a, 0xe1, 0xf5, 0x66, - 0x48, 0x01, 0x92, 0x6a, 0x7b, 0xa7, 0x6c, 0xc6, 0x7b, 0xdf, 0x30, 0x1b, 0x3e, 0x5f, 0x6a, 0xbe, 0xc5, 0x86, 0x38, - 0xef, 0xb8, 0x3a, 0x55, 0xeb, 0x12, 0x9f, 0xd6, 0x3c, 0x21, 0xc5, 0x05, 0xb5, 0x30, 0x34, 0x2e, 0x38, 0x55, 0x5b, - 0x41, 0x7e, 0xc7, 0x96, 0xde, 0x95, 0xfa, 0x94, 0x8d, 0x93, 0x9f, 0xad, 0xf1, 0x5e, 0xe1, 0xff, 0x02, 0x9c, 0x28, - 0xe7, 0x78, 0x86, 0x91, 0x3c, 0xcf, 0x6b, 0xa9, 0x5f, 0x92, 0x46, 0x64, 0x33, 0x67, 0x5d, 0xe7, 0x45, 0x37, 0xba, - 0x25, 0x38, 0x6c, 0x2e, 0xb8, 0x20, 0xfc, 0x3c, 0x39, 0x01, 0x64, 0xe4, 0xa8, 0x81, 0x7e, 0x0e, 0xdb, 0x3a, 0x13, - 0xf5, 0x1e, 0xc1, 0x26, 0xe6, 0x9e, 0x80, 0x8a, 0x1c, 0xd2, 0x74, 0x3d, 0x09, 0x22, 0x2f, 0xed, 0x22, 0x9b, 0x26, - 0xb1, 0xbc, 0x2d, 0xf4, 0x58, 0xe8, 0x6d, 0x31, 0xa6, 0x93, 0x3b, 0xe6, 0x9d, 0xa0, 0xe7, 0xc3, 0x36, 0xfb, 0xbb, - 0xdc, 0xe1, 0x6c, 0x5d, 0x32, 0x47, 0x71, 0x0e, 0x8f, 0x0d, 0xe7, 0xc8, 0xb0, 0x8e, 0x0f, 0xf5, 0x4c, 0x1c, 0x38, - 0xb9, 0xcb, 0xd2, 0x84, 0x80, 0x03, 0x44, 0x0e, 0xa6, 0x1f, 0xfa, 0xa9, 0xef, 0x05, 0x19, 0xf0, 0xc3, 0xe5, 0x4b, - 0xca, 0x3f, 0x96, 0x49, 0x0a, 0x63, 0x14, 0x4c, 0x2f, 0x3a, 0x7f, 0x98, 0x43, 0x96, 0xae, 0x18, 0x0b, 0x37, 0x18, - 0xc6, 0x54, 0x7d, 0x49, 0x7e, 0x3b, 0xcb, 0xfa, 0x8c, 0xac, 0xd6, 0x86, 0x69, 0xc8, 0xf7, 0x87, 0x70, 0x7c, 0xc8, - 0x06, 0xc6, 0x77, 0x9b, 0x10, 0xee, 0xcf, 0xf7, 0x23, 0xdc, 0x94, 0xed, 0x82, 0x70, 0x7f, 0xfe, 0xe2, 0x08, 0xf7, - 0x3b, 0x19, 0xe1, 0x96, 0xfc, 0x07, 0x0b, 0x0d, 0xd3, 0x7b, 0x7c, 0xd6, 0xc0, 0x45, 0xf6, 0xb9, 0xba, 0x4f, 0x0c, - 0xbc, 0xaa, 0x17, 0xd9, 0x6b, 0xff, 0xbc, 0x94, 0x2d, 0xa8, 0x51, 0x00, 0x8a, 0x79, 0x1d, 0x7d, 0x74, 0x5d, 0xf6, - 0xc1, 0xd5, 0x4d, 0x84, 0x61, 0x80, 0x3e, 0xbf, 0x0f, 0xd3, 0xc0, 0x7a, 0xc7, 0xef, 0x91, 0xa0, 0xd0, 0x7d, 0x13, - 0xc5, 0x73, 0x0f, 0x53, 0x8c, 0xa8, 0x3a, 0xb8, 0xd3, 0xc1, 0x83, 0x0d, 0x81, 0x40, 0x46, 0x51, 0x38, 0xce, 0xb5, - 0x92, 0xcc, 0xbd, 0x24, 0x8e, 0x5b, 0xbd, 0x63, 0x5e, 0xac, 0x1a, 0xf4, 0x1a, 0x16, 0xf7, 0x59, 0xdb, 0x7e, 0xd6, - 0x3a, 0x78, 0x76, 0x64, 0xc3, 0xff, 0x0e, 0x6b, 0x67, 0x06, 0xaf, 0x38, 0x8f, 0xc2, 0x74, 0x56, 0xd4, 0xdc, 0x54, - 0x6d, 0xc5, 0xd8, 0xc7, 0xa2, 0xd6, 0x71, 0x73, 0xa5, 0xb1, 0x77, 0x57, 0xd4, 0x69, 0xac, 0x31, 0x8b, 0x96, 0x12, - 0x58, 0x0d, 0xd0, 0xf8, 0xe1, 0x12, 0xe4, 0xec, 0x52, 0x0d, 0xf9, 0x35, 0x1f, 0x6e, 0x31, 0x2e, 0xd6, 0xce, 0xae, - 0x44, 0x0e, 0x05, 0xb5, 0x27, 0xd2, 0xea, 0xdd, 0x3b, 0x83, 0x5c, 0x45, 0x69, 0x63, 0xce, 0x29, 0xcc, 0x6c, 0x08, - 0x19, 0xa7, 0x98, 0x58, 0x20, 0x8f, 0x16, 0x28, 0x8d, 0x97, 0xe1, 0x48, 0xc3, 0x9f, 0xde, 0x30, 0xd1, 0xfc, 0xfd, - 0xd8, 0xe2, 0x1f, 0xd6, 0x71, 0xd5, 0xbc, 0xbe, 0x5d, 0x24, 0x9d, 0x4f, 0xc4, 0xaa, 0x78, 0xcf, 0x52, 0x23, 0x46, - 0x3d, 0x36, 0x2d, 0xad, 0xe9, 0x7a, 0xcf, 0xf2, 0x86, 0xcf, 0x52, 0x23, 0x7c, 0x0e, 0xba, 0x4f, 0xd7, 0x7e, 0xf2, - 0x84, 0x6a, 0xed, 0xb9, 0x62, 0x58, 0xa7, 0xa3, 0x22, 0x33, 0x85, 0xe2, 0x4d, 0x23, 0x4a, 0x4e, 0xd1, 0x1d, 0x19, - 0xd1, 0xf3, 0xe7, 0x7d, 0xd7, 0xd1, 0x87, 0x31, 0xf3, 0x3e, 0x66, 0x22, 0xdc, 0x77, 0x88, 0xf9, 0x69, 0xcf, 0x77, - 0x33, 0x34, 0xd2, 0x1b, 0x5d, 0x69, 0x17, 0x70, 0x67, 0xb2, 0x85, 0x3b, 0x02, 0xc7, 0x5e, 0x90, 0xbb, 0x9e, 0x0c, - 0x0a, 0x3c, 0x61, 0xf0, 0x23, 0xea, 0xe4, 0xb7, 0xae, 0xb6, 0x65, 0x5b, 0xb6, 0x9a, 0x37, 0x9c, 0xf8, 0x53, 0x77, - 0x1d, 0xa5, 0x5e, 0x77, 0xcf, 0x31, 0x82, 0x68, 0x0a, 0x7e, 0x74, 0xa9, 0x9f, 0x06, 0xac, 0xab, 0xaa, 0xe0, 0x50, - 0x37, 0xa7, 0x7b, 0x79, 0xc6, 0xbd, 0x1b, 0xbc, 0x18, 0xd2, 0x96, 0xc7, 0x77, 0xc2, 0x15, 0x17, 0x83, 0xa5, 0xff, - 0x00, 0xc4, 0x50, 0x53, 0x35, 0x90, 0x0d, 0xb0, 0x38, 0x31, 0x65, 0x6f, 0xa1, 0xae, 0x02, 0x6d, 0x74, 0x95, 0x0f, - 0x62, 0x12, 0x7b, 0x73, 0xc8, 0xab, 0xbb, 0xce, 0x0c, 0x8e, 0x69, 0x55, 0x8e, 0x6a, 0x15, 0xe7, 0xc5, 0x91, 0xa1, - 0xb4, 0x1c, 0x43, 0xb1, 0x01, 0xdd, 0xaa, 0x99, 0xb1, 0xce, 0xae, 0x7a, 0xf7, 0x19, 0x3c, 0x10, 0x7e, 0x79, 0x44, - 0xe3, 0x20, 0x53, 0x07, 0xae, 0x4a, 0x4a, 0x29, 0x49, 0x8e, 0x26, 0x65, 0xd0, 0xf4, 0x49, 0xe9, 0x79, 0xc1, 0x6e, - 0x53, 0x1d, 0x34, 0x47, 0xa2, 0x8a, 0xaf, 0xaf, 0xd1, 0x61, 0xd8, 0x0f, 0x15, 0xff, 0xd3, 0x27, 0xcd, 0x07, 0x67, - 0x26, 0x57, 0x9a, 0x1f, 0x78, 0xd6, 0x4b, 0x13, 0xe6, 0x17, 0x6a, 0x7a, 0x9c, 0x2c, 0xf0, 0x34, 0x84, 0x7f, 0x8b, - 0x62, 0xf1, 0x83, 0x9b, 0x49, 0x58, 0x81, 0x17, 0x4e, 0x01, 0xa5, 0x79, 0xe1, 0xb4, 0x66, 0x8e, 0x45, 0x3e, 0xcf, - 0x95, 0xd2, 0xa2, 0xab, 0xc2, 0x54, 0x2a, 0x79, 0x79, 0x77, 0xe1, 0x4d, 0x7f, 0xf4, 0xe6, 0x4c, 0x53, 0x81, 0xca, - 0xa1, 0x8b, 0x6e, 0xa1, 0xc9, 0x7d, 0xee, 0x3e, 0x3d, 0x99, 0xb3, 0xd4, 0x23, 0x35, 0x10, 0x5c, 0x7e, 0x81, 0x1d, - 0x50, 0x38, 0xa1, 0xe1, 0x01, 0x2f, 0x5c, 0xca, 0xa5, 0x45, 0x74, 0xc2, 0x50, 0x38, 0x9d, 0x32, 0xd1, 0xe2, 0xd3, - 0x75, 0x0c, 0x72, 0x38, 0x18, 0x79, 0x98, 0x4f, 0xc7, 0x0d, 0x23, 0xb5, 0xff, 0x34, 0xf7, 0xcd, 0xdc, 0xb4, 0x08, - 0x81, 0x1f, 0x7e, 0xbc, 0x8c, 0x59, 0xf0, 0x4f, 0xf7, 0x29, 0x10, 0xee, 0xa7, 0x57, 0xaa, 0xde, 0x4b, 0xad, 0x59, - 0xcc, 0x26, 0xee, 0x53, 0xb8, 0x90, 0x76, 0xd1, 0x3c, 0x16, 0xb8, 0xf6, 0xe7, 0xb7, 0xf3, 0xc0, 0xc0, 0xeb, 0x3d, - 0xc1, 0xa2, 0xb6, 0x5b, 0x45, 0x5c, 0xf3, 0xf6, 0x4e, 0x97, 0xfa, 0x3e, 0xbf, 0xad, 0xc3, 0x0d, 0x70, 0x5d, 0xba, - 0x63, 0x3b, 0x3d, 0xbc, 0x3f, 0x0f, 0x03, 0x6f, 0xf4, 0xb1, 0x47, 0x6f, 0x4a, 0x0f, 0x26, 0x50, 0xeb, 0x91, 0xb7, - 0xe8, 0x22, 0x79, 0x95, 0x0b, 0xc1, 0x7b, 0x9a, 0x4a, 0x73, 0xce, 0xae, 0x71, 0x2f, 0xe3, 0x56, 0x5e, 0xe3, 0x97, - 0xf1, 0x53, 0xab, 0x99, 0x9f, 0x32, 0xf1, 0x29, 0x7c, 0xc8, 0x32, 0x71, 0x51, 0xa7, 0x2b, 0x2a, 0x5e, 0xac, 0xad, - 0xb6, 0xe2, 0x74, 0xbe, 0x3b, 0xbc, 0x71, 0xec, 0x59, 0xcb, 0xb1, 0x3a, 0x1f, 0x9c, 0xce, 0xac, 0x6d, 0x1d, 0x07, - 0x66, 0xdb, 0x3a, 0x86, 0x3f, 0x1f, 0x8e, 0xad, 0xce, 0xcc, 0x6c, 0x59, 0x07, 0x1f, 0x9c, 0x56, 0x60, 0x76, 0xac, - 0x63, 0xf8, 0x73, 0x4e, 0xad, 0xe0, 0x02, 0x44, 0xf7, 0x9d, 0xa7, 0x25, 0x2c, 0x20, 0xfd, 0xce, 0x75, 0xb2, 0x46, - 0x89, 0xbc, 0x35, 0xe8, 0x75, 0x17, 0x18, 0x45, 0x42, 0xe4, 0xaf, 0x09, 0x7b, 0x5a, 0xe8, 0x32, 0x4a, 0x2a, 0x2b, - 0xcc, 0xdb, 0x84, 0x1f, 0xba, 0xc8, 0xe6, 0xd9, 0x78, 0x8c, 0x78, 0x9b, 0xe6, 0x0c, 0x96, 0xba, 0xc8, 0x08, 0x8c, - 0xcf, 0x3f, 0x2f, 0x30, 0xfe, 0xba, 0x48, 0xc3, 0x2c, 0x61, 0x25, 0xf0, 0x3d, 0xb7, 0xc2, 0x68, 0x85, 0xb6, 0x15, - 0xf7, 0x01, 0x8e, 0xde, 0xfc, 0x4c, 0x58, 0x76, 0x7d, 0xd9, 0xbe, 0xa5, 0xcc, 0xd7, 0x9f, 0xd5, 0x0f, 0x0f, 0x0b, - 0x21, 0x67, 0x9f, 0x1c, 0xfb, 0x71, 0x0e, 0x9e, 0x84, 0xa2, 0x9d, 0xe6, 0xd4, 0x9f, 0xba, 0x41, 0xc1, 0x91, 0x58, - 0x7c, 0xe3, 0x05, 0x92, 0x21, 0x9b, 0xd4, 0x72, 0x2f, 0xc7, 0xfc, 0x4f, 0x9e, 0x14, 0xc0, 0x99, 0x15, 0xb8, 0x4f, - 0x9c, 0x43, 0x20, 0xbb, 0x87, 0xac, 0xbd, 0xd5, 0xa6, 0x92, 0x6e, 0x3a, 0xdb, 0x7c, 0xab, 0x8b, 0x4c, 0x47, 0xc2, - 0x6e, 0x4a, 0x58, 0x6c, 0x6c, 0x34, 0xec, 0xac, 0xd9, 0x6b, 0x40, 0xaa, 0xb8, 0xca, 0x55, 0x47, 0xd5, 0x7b, 0xa1, - 0x30, 0x3f, 0x08, 0xb7, 0x24, 0x79, 0xe3, 0x77, 0x31, 0x15, 0xa6, 0x66, 0xcb, 0x38, 0xee, 0x71, 0x10, 0xff, 0x4f, - 0x0f, 0x02, 0x9d, 0x35, 0xc1, 0x5e, 0xa2, 0x72, 0x5a, 0x4b, 0xce, 0x7b, 0x39, 0x5d, 0x25, 0x82, 0xca, 0x92, 0x53, - 0x15, 0x8a, 0xd4, 0xae, 0x8a, 0x8e, 0x61, 0x6a, 0x6e, 0x2c, 0x9a, 0x53, 0x8b, 0xa2, 0xc0, 0xf0, 0x31, 0xa1, 0xa6, - 0x70, 0x1c, 0xd5, 0x9f, 0x3c, 0xd9, 0x48, 0x84, 0xc8, 0x38, 0x27, 0x61, 0xa9, 0x60, 0xd0, 0x35, 0x55, 0xc6, 0x6f, - 0xaa, 0x8c, 0x62, 0xf2, 0x7e, 0x11, 0x6b, 0x08, 0x1b, 0x57, 0xda, 0x7b, 0xf8, 0x73, 0xc8, 0xbc, 0xd4, 0xe2, 0xca, - 0x52, 0x4d, 0x22, 0xee, 0x86, 0xc3, 0xda, 0x60, 0xdd, 0xca, 0xd3, 0x34, 0xf0, 0x34, 0x28, 0x8f, 0xd7, 0x7f, 0x5e, - 0xf2, 0xa8, 0x0e, 0xd0, 0xc7, 0x27, 0xbb, 0x88, 0xc3, 0xf9, 0x36, 0xf5, 0x28, 0x0e, 0x9a, 0x4c, 0x72, 0xa3, 0xd4, - 0x23, 0x7b, 0x0e, 0x1f, 0x43, 0xd7, 0x34, 0x47, 0xe4, 0x92, 0x22, 0x3f, 0xf4, 0xdf, 0x5e, 0x7c, 0xa3, 0xf0, 0xfd, - 0x4f, 0xd6, 0x02, 0x78, 0x91, 0xa1, 0x78, 0x33, 0x2e, 0xc5, 0x9b, 0x51, 0x78, 0x26, 0x63, 0xc8, 0xb9, 0x9a, 0xed, - 0xd3, 0x0c, 0xa2, 0x00, 0x9a, 0x6c, 0x28, 0xe6, 0xcb, 0x20, 0xf5, 0x17, 0x5e, 0x9c, 0xee, 0x63, 0xb0, 0x19, 0x0c, - 0x5e, 0xb3, 0x29, 0x1e, 0x04, 0x99, 0x61, 0x88, 0xec, 0x20, 0x69, 0x28, 0xec, 0x30, 0x26, 0x7e, 0x90, 0x9b, 0x61, - 0x88, 0x0f, 0x78, 0xa3, 0x11, 0x5b, 0xa4, 0x6e, 0x29, 0xa8, 0x4d, 0x34, 0x4a, 0x59, 0x6a, 0x26, 0x69, 0xcc, 0xbc, - 0xb9, 0x9a, 0x07, 0xb9, 0xaa, 0xf7, 0x97, 0x2c, 0x87, 0x10, 0xa5, 0x47, 0x84, 0xdb, 0xa2, 0x01, 0x82, 0x41, 0x04, - 0x80, 0x08, 0x41, 0x66, 0x68, 0x0a, 0xcf, 0xa3, 0x69, 0x65, 0x47, 0x15, 0x9c, 0xcb, 0x29, 0x26, 0x09, 0xa3, 0x9b, - 0x0c, 0x48, 0x8b, 0x47, 0x51, 0x70, 0xcd, 0x63, 0x58, 0xe4, 0xd9, 0x66, 0xd4, 0xfe, 0x09, 0xbf, 0xde, 0x2a, 0x18, - 0xbe, 0x45, 0x3d, 0xb4, 0x21, 0x0d, 0xda, 0xa6, 0xe8, 0x16, 0xfb, 0xbc, 0x32, 0x90, 0x26, 0xea, 0x19, 0x33, 0x59, - 0x12, 0x2c, 0x17, 0xc0, 0x08, 0x95, 0x0c, 0x66, 0x66, 0x4e, 0x3f, 0x77, 0xa7, 0x44, 0xa8, 0x90, 0x57, 0xfa, 0xf4, - 0xe9, 0xfd, 0xe0, 0xdf, 0xff, 0x82, 0x74, 0x9b, 0x33, 0x47, 0xc4, 0x94, 0xb8, 0x94, 0x6b, 0x71, 0xee, 0xd3, 0x18, - 0xa0, 0xb1, 0x14, 0x1b, 0x8b, 0x68, 0x7f, 0x62, 0x6b, 0x65, 0x83, 0x2b, 0x11, 0xa7, 0x0e, 0x12, 0xf5, 0xea, 0x22, - 0xf2, 0xc5, 0x00, 0x96, 0x77, 0x20, 0x62, 0xa2, 0x28, 0x7f, 0xbf, 0x7d, 0x79, 0xac, 0x14, 0xe1, 0x13, 0x9b, 0x2c, - 0x7a, 0x68, 0x0f, 0xf5, 0x4f, 0x3c, 0x05, 0x99, 0x16, 0x64, 0x3f, 0x92, 0xee, 0x3e, 0x0c, 0x73, 0x16, 0xcd, 0x99, - 0xe5, 0x47, 0xfb, 0x2b, 0x36, 0x34, 0xbd, 0x85, 0x4f, 0x76, 0x39, 0x28, 0x77, 0x53, 0x88, 0xf3, 0xcb, 0xcd, 0x5d, - 0x88, 0xbf, 0xce, 0x8a, 0xa9, 0x8c, 0x2a, 0x81, 0xd0, 0x5a, 0x85, 0x1e, 0xf0, 0x80, 0x07, 0x19, 0x13, 0x35, 0xfb, - 0x27, 0xfb, 0x5e, 0xbf, 0x9c, 0x79, 0xc6, 0x12, 0x19, 0x54, 0xcb, 0x44, 0xe0, 0x94, 0x12, 0xc8, 0x88, 0x5c, 0x31, - 0xc5, 0x83, 0x19, 0x4d, 0x26, 0x72, 0xb6, 0x18, 0xab, 0x0c, 0x5e, 0x3e, 0x69, 0xc5, 0x96, 0x8e, 0x16, 0xf4, 0xa5, - 0xfa, 0x27, 0xf2, 0x9f, 0x6a, 0x17, 0xd3, 0x44, 0xc1, 0x98, 0xe1, 0xb8, 0xd7, 0xb2, 0xce, 0xe4, 0x33, 0xf6, 0x88, - 0x2a, 0x71, 0x3c, 0x52, 0xcd, 0x71, 0xb8, 0x81, 0x73, 0xd9, 0x73, 0x5d, 0x42, 0x73, 0x55, 0x6c, 0x07, 0x93, 0xd8, - 0x90, 0x4d, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x65, 0xb1, 0x51, 0x75, 0x38, 0x75, 0x18, 0xf7, 0x3d, 0xb1, - 0xfd, 0x4a, 0x1b, 0x14, 0x36, 0x1e, 0x5f, 0x77, 0xc0, 0xef, 0xa2, 0x9f, 0x0a, 0x9a, 0x57, 0xbe, 0x26, 0x8c, 0x6e, - 0x06, 0xde, 0x5d, 0x24, 0x99, 0x31, 0xf1, 0x88, 0x26, 0xe7, 0x58, 0x7a, 0x21, 0x3c, 0x89, 0x6b, 0x07, 0x0d, 0x49, - 0x18, 0x64, 0xdd, 0xac, 0x1f, 0xb6, 0x82, 0xfe, 0x06, 0xec, 0xbe, 0xb3, 0x26, 0xd7, 0x2d, 0x0f, 0x06, 0x91, 0x67, - 0x56, 0x9c, 0xc3, 0xd2, 0x4b, 0x44, 0x0b, 0xd9, 0xc9, 0x3e, 0x8c, 0x0f, 0xa2, 0xb0, 0x94, 0x18, 0x27, 0x5f, 0x87, - 0x50, 0x2f, 0x5e, 0x42, 0xa6, 0x58, 0xdf, 0x8f, 0x05, 0xcf, 0x87, 0x17, 0x4b, 0x29, 0x97, 0xbc, 0x54, 0xa5, 0xce, - 0xcb, 0xd8, 0xcd, 0x4c, 0xe0, 0xfd, 0x29, 0x6a, 0x3f, 0x2c, 0x31, 0x3f, 0x6d, 0xd6, 0x4b, 0x99, 0x08, 0x72, 0x70, - 0x9e, 0x6e, 0x88, 0x83, 0xb0, 0xa9, 0x0a, 0xf1, 0xb3, 0x5b, 0x2a, 0x14, 0xfb, 0x78, 0x5b, 0xad, 0x82, 0x73, 0x2a, - 0xaa, 0x79, 0x9a, 0xfa, 0x08, 0x77, 0x7c, 0xad, 0x36, 0x96, 0x62, 0x74, 0x86, 0xd4, 0x85, 0xaa, 0x42, 0x16, 0xef, - 0x2d, 0x16, 0x54, 0x59, 0xef, 0x9d, 0xec, 0xd3, 0xb5, 0xb4, 0x4f, 0x3b, 0xac, 0x7f, 0x02, 0xa6, 0xdc, 0xb4, 0xe8, - 0xde, 0x62, 0xc1, 0x97, 0x94, 0x7e, 0xd1, 0x9b, 0xfd, 0x59, 0x3a, 0x0f, 0xfa, 0xff, 0x0b, 0x3a, 0x5f, 0xcc, 0x86, - 0x37, 0x7a, 0x03, 0x00}; + 0x2a, 0x34, 0x7d, 0xe4, 0x37, 0x22, 0x0d, 0x08, 0x0c, 0xda, 0x65, 0x6f, 0xab, 0xd2, 0x82, 0x6c, 0x3a, 0xb6, 0xd2, + 0xe4, 0xa0, 0x83, 0x03, 0xc4, 0xf8, 0x15, 0x62, 0x21, 0x42, 0x3b, 0xbc, 0x0e, 0x3e, 0x64, 0x6a, 0xce, 0xfb, 0xe1, + 0xf6, 0xeb, 0x9f, 0xec, 0x43, 0x83, 0x7e, 0x45, 0xe9, 0x76, 0x8f, 0x5f, 0x26, 0xb0, 0x12, 0xc9, 0xca, 0xb0, 0x92, + 0x95, 0xf2, 0x6c, 0x2d, 0xe2, 0x63, 0xa7, 0xde, 0xc2, 0x04, 0x2d, 0x0f, 0xe2, 0x5e, 0x8e, 0xf1, 0xa4, 0x50, 0xdc, + 0xbd, 0x65, 0x02, 0xb8, 0x11, 0xe5, 0x28, 0x88, 0x7f, 0x7a, 0xa3, 0x65, 0x9c, 0x44, 0x71, 0x77, 0x11, 0xf9, 0x61, + 0xca, 0xe2, 0x8c, 0x04, 0x2b, 0x38, 0x3f, 0x62, 0x7a, 0xae, 0xd6, 0xd1, 0xc2, 0x1b, 0xf9, 0xe9, 0x5d, 0xd7, 0xe6, + 0x2c, 0x85, 0xdd, 0xe3, 0xdc, 0x81, 0x5d, 0x5b, 0xbf, 0xcb, 0x67, 0xf3, 0x39, 0x32, 0x7e, 0xf1, 0x26, 0x3b, 0x23, + 0x6f, 0xf3, 0x9e, 0xf4, 0x96, 0x22, 0x84, 0x03, 0xfb, 0xe1, 0xc5, 0xe6, 0x14, 0xb0, 0x3c, 0x2c, 0xb5, 0x3d, 0x66, + 0x53, 0x03, 0xb1, 0x36, 0x98, 0x19, 0x8a, 0x3f, 0xd6, 0xa1, 0xae, 0xd8, 0xf5, 0xc5, 0xc0, 0xf1, 0xe8, 0xbb, 0x40, + 0xd6, 0xf5, 0x26, 0x29, 0x8b, 0x8d, 0x5d, 0x6a, 0x0e, 0xd9, 0x24, 0x8a, 0x19, 0x65, 0x93, 0x73, 0x3a, 0x8b, 0xdb, + 0xdd, 0xbb, 0xdf, 0x3e, 0xfc, 0xfa, 0x7e, 0xc2, 0x28, 0xd5, 0x44, 0x67, 0xfa, 0x3d, 0xbd, 0x6d, 0xd2, 0x33, 0x60, + 0x0d, 0x69, 0xe6, 0x47, 0x24, 0x05, 0x81, 0x48, 0x60, 0xb5, 0x49, 0x3b, 0x16, 0x11, 0xa7, 0x79, 0x31, 0x0b, 0xbc, + 0xd4, 0xbf, 0x11, 0x3c, 0x63, 0xfb, 0x68, 0x71, 0x2b, 0xd6, 0x18, 0x09, 0xde, 0x03, 0x16, 0xa9, 0x02, 0x8a, 0x58, + 0xa4, 0x6a, 0x31, 0x2e, 0x52, 0x6f, 0x63, 0x34, 0x22, 0x8e, 0x75, 0x85, 0xd2, 0x1f, 0x2e, 0x6e, 0x65, 0x12, 0x5d, + 0x34, 0xcb, 0x29, 0x75, 0x35, 0x01, 0xc9, 0xdc, 0x1f, 0x8f, 0x03, 0x96, 0x95, 0x16, 0xba, 0xbc, 0x96, 0xd2, 0xe4, + 0xe4, 0xf3, 0xe0, 0x0d, 0x93, 0x28, 0x58, 0xa6, 0xac, 0x7e, 0xba, 0x84, 0x44, 0xb7, 0x98, 0x1c, 0xfc, 0x5d, 0x86, + 0xf5, 0x10, 0xd8, 0x6d, 0xd8, 0x26, 0x76, 0x0f, 0xf2, 0x0d, 0x9a, 0xed, 0x32, 0xe8, 0xf0, 0x2a, 0x07, 0xda, 0xa8, + 0x19, 0x88, 0x01, 0x64, 0x89, 0xb0, 0xb7, 0x62, 0x39, 0xbc, 0x2c, 0xcf, 0xb9, 0x96, 0x17, 0x65, 0xe5, 0xc1, 0xfc, + 0x3e, 0x67, 0xec, 0x45, 0xfd, 0x19, 0x7b, 0x21, 0xce, 0xd8, 0xf6, 0x9d, 0xf9, 0x68, 0xe2, 0xc0, 0x7f, 0xbd, 0x62, + 0x40, 0x5d, 0x5b, 0x69, 0x2f, 0x6e, 0x15, 0x67, 0x71, 0xab, 0x98, 0xad, 0xc5, 0xad, 0x82, 0x5d, 0xa3, 0x7b, 0x8b, + 0x61, 0xb5, 0x74, 0xc3, 0x56, 0xa0, 0x10, 0xfe, 0xd8, 0xa5, 0x57, 0xce, 0x01, 0xbc, 0x83, 0x56, 0x87, 0x9b, 0xef, + 0x5a, 0xdb, 0x8f, 0x3a, 0x9d, 0x25, 0x81, 0xb4, 0x75, 0x2b, 0xf5, 0x86, 0x43, 0x10, 0x65, 0x46, 0xa3, 0x65, 0xf2, + 0x0f, 0x0e, 0x3f, 0x9f, 0xc4, 0xad, 0x88, 0xa0, 0xd2, 0x8f, 0x68, 0x0a, 0x8a, 0xc2, 0x1b, 0x26, 0x7a, 0x58, 0xe7, + 0xeb, 0xd4, 0xa5, 0xe4, 0x88, 0x2d, 0xeb, 0xa0, 0x66, 0x93, 0xd7, 0x4f, 0xf4, 0xef, 0xb6, 0x4a, 0xcd, 0x28, 0xe6, + 0x33, 0xa6, 0x65, 0xeb, 0x74, 0x3c, 0x7c, 0x36, 0xf8, 0x6a, 0xda, 0x9d, 0x7a, 0x70, 0x2f, 0xc5, 0x97, 0xae, 0x04, + 0x51, 0xe1, 0x74, 0x8b, 0x87, 0xe2, 0xd8, 0xde, 0x6b, 0xd3, 0x1e, 0xd9, 0xe8, 0x75, 0x0b, 0x41, 0x28, 0xea, 0xee, + 0x88, 0xe5, 0x1f, 0xbd, 0x38, 0x80, 0xff, 0x88, 0xab, 0xff, 0x6b, 0x5a, 0xc7, 0xa8, 0xbf, 0x4e, 0x4b, 0x8c, 0x3a, + 0xb1, 0x4a, 0xc8, 0x88, 0xef, 0x5e, 0x7f, 0x32, 0x79, 0x58, 0x83, 0x9d, 0x6b, 0x93, 0x67, 0x58, 0xb5, 0xf6, 0xcb, + 0x28, 0x0a, 0x98, 0x17, 0x6e, 0x56, 0x17, 0xd3, 0x43, 0x6e, 0xfe, 0xa9, 0x0b, 0x8d, 0xc4, 0x3d, 0x82, 0x9c, 0x12, + 0x54, 0x6c, 0x43, 0x57, 0x89, 0xf3, 0xa6, 0xab, 0xc4, 0xbb, 0xfb, 0xaf, 0x12, 0x3f, 0xec, 0x74, 0x95, 0x78, 0xf7, + 0xc5, 0xaf, 0x12, 0xe7, 0x9b, 0x57, 0x89, 0xf3, 0x48, 0xb8, 0x03, 0x1b, 0x6f, 0x96, 0xfc, 0xe7, 0x07, 0xb2, 0xf7, + 0x7d, 0x17, 0xb9, 0x87, 0x36, 0x25, 0x3c, 0xbc, 0xf8, 0xcd, 0x17, 0x0b, 0xdc, 0x88, 0xef, 0xd0, 0x3b, 0xae, 0xb8, + 0x5a, 0x70, 0xcc, 0x8e, 0xdf, 0x91, 0x8a, 0x83, 0x28, 0x9c, 0xfe, 0x0c, 0xf6, 0xde, 0x20, 0x0e, 0x8c, 0xa5, 0x17, + 0x7e, 0xf2, 0x73, 0xb4, 0x58, 0x2e, 0x50, 0x51, 0xf5, 0xc1, 0x4f, 0xfc, 0x61, 0xc0, 0xf2, 0x08, 0x93, 0xa4, 0x75, + 0xe5, 0xb2, 0x75, 0x50, 0xbc, 0x8a, 0x9f, 0xde, 0xad, 0xf8, 0x89, 0x2e, 0xb6, 0xfc, 0x37, 0xb9, 0x09, 0xaa, 0xf5, + 0x17, 0x11, 0x61, 0x21, 0x26, 0x01, 0xfd, 0xf0, 0xcb, 0xc8, 0xb9, 0x88, 0xe5, 0x55, 0x1a, 0xa5, 0x70, 0xdf, 0x68, + 0xec, 0x87, 0x55, 0xfb, 0x79, 0xb3, 0xd4, 0x8d, 0x3c, 0x01, 0xc7, 0xa6, 0x38, 0x7f, 0x1e, 0x2d, 0x13, 0x36, 0x8e, + 0x56, 0xa1, 0x6a, 0x84, 0x5c, 0xaf, 0x1a, 0xa1, 0x4c, 0x3d, 0x6f, 0x53, 0x56, 0x38, 0xaa, 0xd6, 0x02, 0xe6, 0xd0, + 0x24, 0x0d, 0xb6, 0x89, 0x43, 0x54, 0x45, 0xc8, 0xa6, 0xde, 0x9e, 0xa6, 0x45, 0xee, 0xc3, 0x5a, 0x0a, 0xcf, 0x93, + 0xc8, 0xe2, 0x52, 0xe1, 0x44, 0x0b, 0x85, 0x70, 0x51, 0x44, 0xc1, 0xae, 0x59, 0x38, 0xfe, 0x86, 0x22, 0x44, 0x16, + 0x6f, 0x41, 0x57, 0x95, 0x2d, 0xf9, 0x7a, 0xf0, 0x98, 0xd0, 0xf4, 0xf8, 0x4a, 0x9a, 0xc6, 0xb7, 0x37, 0x2c, 0x0e, + 0xbc, 0x3b, 0x4d, 0xcf, 0xa2, 0xf0, 0x47, 0x98, 0x80, 0xd7, 0xd1, 0x2a, 0x94, 0x2b, 0x60, 0xaa, 0xf6, 0x9a, 0xbd, + 0x54, 0x1b, 0xbd, 0x1c, 0x62, 0x76, 0x48, 0x10, 0xf8, 0xd6, 0xc2, 0x9b, 0xb2, 0xff, 0x32, 0xe8, 0xdf, 0xff, 0xd6, + 0x33, 0xe3, 0x5d, 0x94, 0x7f, 0xe8, 0x97, 0xc5, 0x0e, 0x9f, 0x79, 0xf2, 0x64, 0xaf, 0x79, 0xd8, 0xda, 0x28, 0x60, + 0x5e, 0x2c, 0xa0, 0xa8, 0x69, 0xad, 0x37, 0x9e, 0x02, 0x80, 0xe2, 0x22, 0x5a, 0x8e, 0x66, 0xe8, 0xb7, 0xfb, 0xe5, + 0xc6, 0x9b, 0x42, 0x9f, 0x2c, 0xb9, 0xb4, 0xaf, 0xf2, 0xa1, 0x57, 0x8a, 0x8a, 0x59, 0xc0, 0xef, 0x9f, 0x41, 0xfa, + 0xad, 0x7f, 0xe3, 0x34, 0x6c, 0xee, 0x9a, 0x3c, 0xe4, 0xd7, 0x83, 0x36, 0x6f, 0xcf, 0x87, 0xa8, 0x3c, 0x14, 0xd8, + 0x5a, 0x28, 0xe9, 0xea, 0x91, 0x4c, 0x56, 0x9d, 0x34, 0x39, 0x89, 0x4c, 0x53, 0x7e, 0x1c, 0xf1, 0x15, 0x66, 0x95, + 0xac, 0x46, 0x0c, 0xc6, 0xb1, 0x55, 0x05, 0xc9, 0x70, 0x6f, 0x0a, 0x86, 0xe8, 0xab, 0xfa, 0x6e, 0xee, 0x87, 0x06, + 0xe6, 0x80, 0xdd, 0x7c, 0xe3, 0xdd, 0x42, 0x16, 0x44, 0x40, 0x6e, 0xd5, 0x57, 0x50, 0x68, 0xc8, 0xd1, 0x82, 0xbc, + 0xf1, 0x58, 0x53, 0x6b, 0x67, 0x42, 0x68, 0x03, 0x07, 0x5f, 0x29, 0x8a, 0xa2, 0xe4, 0xd7, 0x08, 0x25, 0xbf, 0x47, + 0x60, 0x39, 0x5e, 0x07, 0x40, 0x5b, 0x92, 0x2d, 0x6e, 0xa9, 0x04, 0x6e, 0x06, 0x68, 0x3f, 0x2d, 0x0a, 0x78, 0xa2, + 0x1f, 0x30, 0x6e, 0xa1, 0x02, 0x71, 0xa1, 0x07, 0xd5, 0xb7, 0x17, 0x43, 0x3e, 0xc0, 0xae, 0x82, 0x17, 0x76, 0x7c, + 0xcb, 0x25, 0xc1, 0x8a, 0x4d, 0x8f, 0x83, 0x1e, 0xab, 0xcf, 0x08, 0x13, 0x4a, 0x58, 0x10, 0xb4, 0x0e, 0x95, 0x04, + 0x8f, 0x06, 0xab, 0xc1, 0x8d, 0x78, 0x2f, 0xba, 0x4d, 0xe7, 0x2c, 0x5c, 0xaa, 0x06, 0x58, 0x9d, 0x60, 0x86, 0x1e, + 0xa8, 0xf3, 0x9a, 0x98, 0x2d, 0xc0, 0x36, 0xf5, 0x2d, 0x67, 0x44, 0x0b, 0x85, 0xa9, 0x8a, 0x67, 0x8c, 0x78, 0x00, + 0x9c, 0x84, 0xe3, 0xb6, 0x2a, 0x85, 0xe0, 0x4b, 0x1a, 0x95, 0xb1, 0x39, 0x0f, 0x79, 0x85, 0x9c, 0x02, 0xd9, 0x88, + 0x71, 0x71, 0x91, 0x98, 0x76, 0xcd, 0xab, 0x2e, 0x5a, 0xae, 0x91, 0xf1, 0x2a, 0x82, 0xa2, 0x58, 0xdf, 0xec, 0x86, + 0xc3, 0x09, 0x69, 0x09, 0x1a, 0xfb, 0x19, 0x6d, 0xf4, 0xd3, 0x30, 0xe8, 0x8f, 0xec, 0x8e, 0x08, 0x09, 0x4d, 0xd5, + 0x47, 0x76, 0x07, 0xc6, 0xe1, 0x67, 0x20, 0x4d, 0x51, 0xb7, 0xa0, 0x6b, 0x03, 0x12, 0xfd, 0x8e, 0x20, 0x55, 0xc5, + 0x96, 0x03, 0x64, 0x67, 0x5b, 0xb0, 0x38, 0x85, 0x23, 0x35, 0x92, 0x9e, 0x38, 0xc4, 0x3c, 0x62, 0x81, 0x56, 0x3b, + 0xc7, 0x66, 0xcd, 0xd1, 0xd0, 0x9f, 0x39, 0xb6, 0xbd, 0xbf, 0x51, 0x1f, 0x04, 0xd9, 0x75, 0xb5, 0x75, 0x23, 0x75, + 0x1d, 0xdb, 0xf4, 0x9f, 0x59, 0xad, 0xde, 0x06, 0x8d, 0x96, 0x32, 0x49, 0x0d, 0x50, 0xfc, 0xd5, 0x7f, 0xbc, 0xd6, + 0x36, 0x0e, 0xa4, 0x5e, 0x8d, 0x00, 0x80, 0xb0, 0x65, 0x5c, 0xfe, 0x35, 0xd8, 0x24, 0xfd, 0x94, 0xc7, 0x8a, 0xb2, + 0x9a, 0x0f, 0x20, 0x17, 0xa2, 0x06, 0xc7, 0xe8, 0x4f, 0xca, 0x73, 0x45, 0xa3, 0xe3, 0xa3, 0xeb, 0x83, 0x9e, 0xc0, + 0x28, 0x22, 0x44, 0x8e, 0xdc, 0x41, 0xe5, 0x8b, 0x49, 0x15, 0xc3, 0xf1, 0xac, 0x6b, 0xac, 0xd0, 0xe8, 0x6d, 0xe5, + 0x16, 0xb0, 0xff, 0x06, 0xf2, 0x69, 0x0d, 0x21, 0xc6, 0x23, 0xd4, 0x80, 0xcc, 0xa9, 0xf7, 0x76, 0x08, 0xe1, 0x79, + 0xe5, 0xee, 0xca, 0x44, 0x72, 0xf7, 0xce, 0x90, 0xe8, 0xa0, 0x0e, 0x2d, 0xef, 0xaf, 0x9e, 0xdc, 0x3d, 0xb0, 0x4b, + 0x16, 0x8e, 0xcb, 0x1d, 0x56, 0xe8, 0xd7, 0xee, 0xdd, 0x95, 0x30, 0x0a, 0xa4, 0x14, 0x8e, 0x6a, 0x30, 0x4a, 0x16, + 0x85, 0xb8, 0xf9, 0xe9, 0xb8, 0xf9, 0x3b, 0x71, 0x31, 0xd8, 0x80, 0xf2, 0x81, 0xe4, 0xcd, 0x24, 0xa1, 0x38, 0xe4, + 0xad, 0xc4, 0x08, 0x5a, 0x9a, 0x60, 0x44, 0x1b, 0x77, 0x62, 0x2a, 0xdc, 0x15, 0x8b, 0x36, 0x3e, 0xcf, 0x44, 0xb5, + 0xab, 0xd4, 0xda, 0xbf, 0x5f, 0x6a, 0x9d, 0xde, 0x27, 0xb5, 0xa6, 0xe8, 0x30, 0xdc, 0x1e, 0x54, 0x44, 0xc9, 0x11, + 0xcc, 0xb9, 0x1c, 0x67, 0xa8, 0x24, 0xea, 0xc6, 0x60, 0x32, 0x35, 0x56, 0xa4, 0xd4, 0x1b, 0x39, 0x20, 0xa2, 0xf8, + 0x5b, 0xba, 0xa0, 0x08, 0x85, 0xba, 0x2c, 0x1b, 0x3f, 0x2f, 0x64, 0xe3, 0x74, 0xab, 0x29, 0xe2, 0x82, 0x08, 0xee, + 0x5f, 0x8a, 0xb9, 0x93, 0xdf, 0x0e, 0x8a, 0xd8, 0x3b, 0x05, 0xa4, 0x52, 0x34, 0x99, 0xe2, 0xa2, 0x21, 0xc5, 0x28, + 0x12, 0xb7, 0x8c, 0x72, 0xa8, 0xa2, 0x72, 0xd5, 0x22, 0x98, 0x4c, 0x51, 0x0e, 0x52, 0x77, 0x04, 0x39, 0x2f, 0x96, + 0xb7, 0x4d, 0x39, 0x9a, 0x88, 0xfc, 0x5a, 0xda, 0x24, 0x79, 0xd8, 0x0f, 0x9a, 0x60, 0x21, 0xa6, 0xaf, 0xe8, 0xb5, + 0x73, 0x1b, 0x08, 0x04, 0xb2, 0x26, 0x4a, 0xd1, 0xfd, 0xd2, 0x79, 0xca, 0x96, 0x5c, 0xa8, 0xae, 0x1d, 0xa4, 0xee, + 0xa4, 0x09, 0x96, 0xe5, 0x11, 0x38, 0xd7, 0x57, 0x92, 0x04, 0xa1, 0x6b, 0x2b, 0x76, 0xaf, 0x86, 0x01, 0x40, 0xfa, + 0x5f, 0x7d, 0xe6, 0xac, 0x00, 0x48, 0x22, 0x15, 0x5b, 0xd6, 0xf9, 0xe3, 0x21, 0x36, 0xc9, 0x92, 0x1d, 0xab, 0x6e, + 0x7e, 0x93, 0xe4, 0x3d, 0x6b, 0x1e, 0x13, 0xa4, 0x2c, 0xce, 0xe7, 0x35, 0xba, 0x02, 0x0e, 0xbe, 0xcb, 0xe2, 0x65, + 0x88, 0x49, 0x70, 0xcd, 0x34, 0xf6, 0x46, 0x1f, 0xd7, 0xd2, 0xf7, 0xb8, 0x48, 0x14, 0xc4, 0xc5, 0x65, 0xa5, 0x42, + 0xcf, 0xc3, 0x9c, 0x51, 0xac, 0x6b, 0xb5, 0x12, 0x49, 0x50, 0xd3, 0x7d, 0x64, 0xb7, 0xbd, 0x17, 0x93, 0x83, 0x8a, + 0xfc, 0xb4, 0x75, 0x58, 0x96, 0xae, 0xe7, 0x70, 0xcc, 0xa3, 0x5f, 0x79, 0xf4, 0xa4, 0x3f, 0xfe, 0xd3, 0x09, 0xff, + 0x66, 0x65, 0x8d, 0x3e, 0x07, 0x04, 0x68, 0x5f, 0x52, 0x4c, 0xcb, 0x6a, 0x9a, 0x8d, 0x92, 0x26, 0xb0, 0x26, 0x7e, + 0x10, 0x98, 0x01, 0xb8, 0x31, 0xac, 0x3f, 0x6b, 0x78, 0xd8, 0xcf, 0x12, 0xb2, 0x15, 0x7e, 0x46, 0x3f, 0xe5, 0x9d, + 0x92, 0xce, 0x96, 0xf3, 0xe1, 0x5a, 0x16, 0x94, 0x4b, 0xf2, 0xf3, 0x4d, 0x99, 0xb9, 0xfc, 0xd9, 0xc9, 0x64, 0x52, + 0x96, 0x1a, 0xdb, 0xca, 0x01, 0x4a, 0x7e, 0x1f, 0xd9, 0xb6, 0x5d, 0x9d, 0xdf, 0xa6, 0x83, 0x42, 0x07, 0xc3, 0x44, + 0x21, 0x7c, 0xe7, 0xfe, 0x3d, 0xf5, 0x07, 0x41, 0x4b, 0x5d, 0x35, 0x9d, 0x47, 0xda, 0x6a, 0xff, 0x11, 0xa0, 0x20, + 0x6a, 0xb8, 0xef, 0xf8, 0x6f, 0xee, 0x95, 0x2d, 0x3d, 0x55, 0x0f, 0xf0, 0xc3, 0x1a, 0xdf, 0xb3, 0xd7, 0x77, 0x68, + 0xda, 0xb4, 0xbd, 0x33, 0xab, 0x20, 0xbb, 0x25, 0x9b, 0xa5, 0x1e, 0x59, 0x2a, 0xf9, 0x29, 0x9b, 0x27, 0xdd, 0x11, + 0x43, 0x05, 0xa9, 0x25, 0x51, 0x5b, 0xb4, 0xea, 0x31, 0xa7, 0x60, 0xc7, 0xe5, 0x08, 0x3c, 0x6c, 0x2b, 0xa8, 0xac, + 0xda, 0xd0, 0xac, 0x89, 0x8f, 0x20, 0x15, 0x5b, 0x6f, 0x2a, 0x9c, 0x70, 0x9b, 0x1e, 0xda, 0x7f, 0x2a, 0xd5, 0x53, + 0x80, 0x3b, 0x5d, 0x0b, 0x6b, 0x13, 0x52, 0x9e, 0xe0, 0xdf, 0xb9, 0x72, 0xee, 0xc5, 0xe2, 0xb6, 0x6c, 0xdc, 0xd5, + 0x01, 0x75, 0x53, 0x41, 0xca, 0x08, 0xea, 0x3a, 0xd4, 0x97, 0x9b, 0x00, 0x4d, 0x64, 0xeb, 0x16, 0xb0, 0xa0, 0x11, + 0x53, 0x50, 0xd1, 0x11, 0xe6, 0xa0, 0xe2, 0x75, 0x16, 0x76, 0x5e, 0x21, 0xdf, 0xc7, 0x5f, 0x90, 0xa5, 0x1c, 0xd2, + 0x9d, 0xfc, 0xc9, 0x78, 0xde, 0x41, 0xe5, 0x5e, 0x69, 0xab, 0xa2, 0xa9, 0x0c, 0xee, 0x01, 0x71, 0x23, 0x55, 0x96, + 0x71, 0x60, 0x52, 0xe2, 0x7a, 0x4d, 0x5f, 0x6f, 0x8e, 0xbb, 0xb9, 0x7b, 0xe7, 0x10, 0xf4, 0x1a, 0x9b, 0x53, 0xb5, + 0x93, 0x6a, 0xaf, 0xaa, 0xc3, 0x16, 0x70, 0xc2, 0x0a, 0x80, 0xcf, 0xac, 0x82, 0x46, 0x43, 0x4a, 0x05, 0xf7, 0xd1, + 0xa0, 0xf3, 0xb7, 0x32, 0xb2, 0x16, 0xe3, 0xc4, 0xee, 0xea, 0xab, 0x50, 0xdf, 0x42, 0x33, 0x08, 0x73, 0xc7, 0xb1, + 0x13, 0x3e, 0x9b, 0xb0, 0x63, 0x64, 0x74, 0xe5, 0xe0, 0x0e, 0xc2, 0x53, 0x6a, 0x52, 0xf2, 0x13, 0x3a, 0xa5, 0xa8, + 0x4b, 0xf8, 0xa1, 0x56, 0x78, 0x7f, 0x51, 0x92, 0xc6, 0xf3, 0xa0, 0x13, 0x2d, 0x7d, 0xa7, 0xda, 0x73, 0x3f, 0xdc, + 0xbd, 0xae, 0x77, 0xbb, 0x73, 0x5d, 0x60, 0x0e, 0x77, 0xae, 0x0c, 0xdc, 0x25, 0x56, 0xbe, 0x48, 0xdd, 0x1f, 0x24, + 0xe5, 0x81, 0x1c, 0x30, 0x51, 0xc5, 0x56, 0x74, 0xa3, 0xff, 0x69, 0xe9, 0x0e, 0x4e, 0x4e, 0x6f, 0xe7, 0x81, 0x72, + 0xc3, 0xe2, 0x04, 0x12, 0x4a, 0xa8, 0x8e, 0x65, 0xab, 0x0a, 0x1a, 0xf4, 0xfb, 0xe1, 0xd4, 0x55, 0x7f, 0xb9, 0x78, + 0x63, 0x76, 0xd4, 0x53, 0x30, 0xc7, 0xb8, 0x99, 0x22, 0x8b, 0x7b, 0xee, 0xdd, 0xb1, 0xf8, 0xba, 0xc5, 0x3d, 0x7e, + 0x88, 0xb9, 0xc5, 0x32, 0xa5, 0xa5, 0xee, 0x90, 0x12, 0x5e, 0xb9, 0xf1, 0xd9, 0xea, 0x65, 0x74, 0xeb, 0xaa, 0x80, + 0x58, 0x9d, 0x56, 0x47, 0x71, 0x5a, 0x07, 0xd6, 0x51, 0x47, 0xed, 0x7f, 0xa5, 0x28, 0x27, 0x63, 0x36, 0x49, 0xfa, + 0x28, 0x8e, 0x39, 0x41, 0x7e, 0x90, 0x7e, 0x2b, 0x8a, 0x35, 0x0a, 0x12, 0xd3, 0x51, 0xd6, 0xfc, 0x51, 0x51, 0x00, + 0x19, 0x75, 0x95, 0x47, 0x93, 0xd6, 0xe4, 0x60, 0xf2, 0xa2, 0xc7, 0x8b, 0xb3, 0xaf, 0x4a, 0xd5, 0x0d, 0xfa, 0xb7, + 0x25, 0x35, 0x4b, 0xd2, 0x38, 0xfa, 0xc8, 0x38, 0x2f, 0xa9, 0xe4, 0x82, 0xa2, 0x6a, 0xd3, 0xd6, 0xe6, 0x97, 0x9c, + 0xce, 0x70, 0x34, 0x69, 0x15, 0xd5, 0x11, 0xc6, 0xfd, 0x1c, 0xc8, 0x93, 0x7d, 0x01, 0xfa, 0x89, 0x3c, 0x4d, 0x8e, + 0x59, 0x37, 0x51, 0x8e, 0xca, 0xc7, 0x38, 0x15, 0xe3, 0x3b, 0x81, 0x8c, 0x6b, 0x85, 0xf7, 0x62, 0x82, 0xcd, 0x5c, + 0xf5, 0x47, 0xa7, 0xd5, 0x31, 0x1c, 0xe7, 0xc8, 0x3a, 0xea, 0x8c, 0x6c, 0xe3, 0xc0, 0x3a, 0x30, 0xdb, 0xd6, 0x91, + 0xd1, 0x31, 0x3b, 0x46, 0xe7, 0xbb, 0xce, 0xc8, 0x3c, 0xb0, 0x0e, 0x0c, 0xdb, 0xec, 0x40, 0xa1, 0xd9, 0x31, 0x3b, + 0x37, 0xe6, 0x41, 0x67, 0x64, 0x63, 0x69, 0xcb, 0x3a, 0x3c, 0x34, 0x1d, 0xdb, 0x3a, 0x3c, 0x34, 0x0e, 0xad, 0xa3, + 0x23, 0xd3, 0x69, 0x5b, 0x47, 0x47, 0xe7, 0x87, 0x1d, 0xab, 0x0d, 0xef, 0xda, 0xed, 0x51, 0xdb, 0x72, 0x1c, 0x13, + 0xfe, 0x32, 0x3a, 0x56, 0x8b, 0x7e, 0x38, 0x8e, 0xd5, 0x76, 0x0c, 0x3b, 0x38, 0x6c, 0x59, 0x47, 0x2f, 0x0c, 0xfc, + 0x1b, 0xab, 0x19, 0xf8, 0x17, 0x74, 0x63, 0xbc, 0xb0, 0x5a, 0x47, 0xf4, 0x0b, 0x3b, 0xbc, 0x39, 0xe8, 0xfc, 0x55, + 0xdd, 0x6f, 0x1c, 0x83, 0x43, 0x63, 0xe8, 0x1c, 0x5a, 0xed, 0xb6, 0x71, 0xe0, 0x58, 0x9d, 0xf6, 0xcc, 0x3c, 0x68, + 0x59, 0x47, 0xc7, 0x23, 0xd3, 0xb1, 0x8e, 0x8f, 0x0d, 0xdb, 0x6c, 0x5b, 0x2d, 0xc3, 0xb1, 0x0e, 0xda, 0xf8, 0xa3, + 0x6d, 0xb5, 0x6e, 0x8e, 0x5f, 0x58, 0x47, 0x87, 0xb3, 0x23, 0xeb, 0xe0, 0xc3, 0x41, 0xc7, 0x6a, 0xb5, 0x67, 0xed, + 0x23, 0xab, 0x75, 0x7c, 0x73, 0x64, 0x1d, 0xcc, 0xcc, 0xd6, 0xd1, 0xd6, 0x96, 0x4e, 0xcb, 0x82, 0x39, 0xc2, 0xd7, + 0xf0, 0xc2, 0xe0, 0x2f, 0xe0, 0xcf, 0x0c, 0xdb, 0xfe, 0x81, 0xdd, 0x24, 0x9b, 0x4d, 0x5f, 0x58, 0x9d, 0xe3, 0x11, + 0x55, 0x87, 0x02, 0x53, 0xd4, 0x80, 0x26, 0x37, 0x26, 0x7d, 0x16, 0xbb, 0x33, 0x45, 0x47, 0xe2, 0x0f, 0xff, 0xd8, + 0x8d, 0x09, 0x1f, 0xa6, 0xef, 0xfe, 0x5b, 0xfb, 0xc9, 0x97, 0xfc, 0x64, 0x7f, 0x4a, 0x5b, 0x7f, 0xda, 0xff, 0xea, + 0x04, 0x0e, 0x77, 0x7f, 0x60, 0xfc, 0xda, 0xa4, 0x94, 0xfc, 0xfb, 0xfd, 0x4a, 0xc9, 0x97, 0xcb, 0x5d, 0x94, 0x92, + 0x7f, 0xff, 0xe2, 0x4a, 0xc9, 0x5f, 0xab, 0xbe, 0x35, 0x6f, 0xaa, 0x59, 0xa8, 0x7f, 0x58, 0x57, 0x45, 0x0e, 0x89, + 0xa7, 0x5d, 0xfe, 0xb4, 0xbc, 0x82, 0xf8, 0xf1, 0x6f, 0x22, 0xf7, 0xe5, 0xb2, 0x64, 0xf0, 0x19, 0x01, 0x8e, 0x7d, + 0x13, 0x11, 0x8e, 0xfd, 0xb0, 0x74, 0xc1, 0xca, 0x8c, 0xb3, 0x39, 0xfe, 0xd8, 0x9c, 0x79, 0xc1, 0x24, 0x67, 0x91, + 0xa0, 0xa4, 0x87, 0xc5, 0xe0, 0x37, 0x0f, 0xe4, 0x19, 0x6e, 0x32, 0xcb, 0x79, 0x98, 0x80, 0x45, 0x30, 0x58, 0x72, + 0x4c, 0xe2, 0xac, 0xd2, 0xd8, 0x12, 0x11, 0xf7, 0xaf, 0xb9, 0x47, 0x71, 0xe3, 0x7b, 0x34, 0x00, 0xae, 0xef, 0xdd, + 0xd9, 0xec, 0x57, 0x01, 0xcb, 0x3a, 0x61, 0x20, 0x0d, 0xdc, 0x7e, 0xdd, 0xfb, 0xb2, 0x19, 0x6e, 0xc5, 0xf0, 0xba, + 0x19, 0x52, 0x80, 0xa4, 0xda, 0xde, 0x29, 0x9b, 0xf1, 0xde, 0x37, 0xcc, 0x9a, 0xcf, 0x97, 0x9a, 0x6f, 0xb1, 0x21, + 0xce, 0x3b, 0xae, 0x4e, 0xd5, 0xba, 0xc4, 0xa7, 0xd5, 0x4f, 0x48, 0x71, 0x41, 0x2d, 0x0c, 0x8d, 0x0b, 0x4e, 0xd5, + 0x56, 0x90, 0xdf, 0xb1, 0xa5, 0x77, 0xa5, 0x3e, 0x65, 0xe3, 0xe4, 0x67, 0x6b, 0xbc, 0x57, 0xf8, 0xbf, 0x02, 0x27, + 0xca, 0x39, 0x9e, 0x61, 0x24, 0xcf, 0xf3, 0x5a, 0xea, 0x97, 0xa4, 0x11, 0xd9, 0xcc, 0x59, 0x6f, 0xf2, 0xa2, 0x8d, + 0x6e, 0x09, 0x0e, 0x9b, 0x0b, 0x2e, 0x08, 0x3f, 0x4f, 0x4e, 0x00, 0x19, 0x39, 0x6a, 0xa0, 0x9f, 0xc3, 0xb6, 0xce, + 0x44, 0xbd, 0x47, 0xb0, 0x89, 0xb9, 0x27, 0xa0, 0x22, 0x87, 0x34, 0x5d, 0x4f, 0x82, 0xc8, 0x4b, 0xbb, 0xc8, 0xa6, + 0x49, 0x2c, 0x6f, 0x0b, 0x3d, 0x16, 0x7a, 0x5b, 0x8c, 0xe9, 0xe4, 0x8e, 0x79, 0x27, 0xe8, 0xf9, 0xb0, 0xcd, 0xfe, + 0x2e, 0x77, 0x38, 0x5b, 0x97, 0xcc, 0x51, 0x9c, 0xc3, 0x63, 0xc3, 0x39, 0x32, 0xac, 0xe3, 0x43, 0x3d, 0x13, 0x07, + 0x4e, 0xee, 0xb2, 0x34, 0x21, 0xe0, 0x00, 0x91, 0x83, 0xe9, 0x87, 0x7e, 0xea, 0x7b, 0x41, 0x06, 0xfc, 0x70, 0xf9, + 0x92, 0xf2, 0xf7, 0x65, 0x92, 0xc2, 0x18, 0x05, 0xd3, 0x8b, 0xce, 0x1f, 0xe6, 0x90, 0xa5, 0x2b, 0xc6, 0xc2, 0x06, + 0xc3, 0x98, 0xaa, 0x2f, 0xc9, 0xef, 0x67, 0x59, 0x9f, 0x91, 0xd5, 0xda, 0x30, 0x0d, 0xf9, 0xfe, 0x10, 0x8e, 0x0f, + 0xd9, 0xc0, 0xf8, 0xae, 0x09, 0xe1, 0xfe, 0x72, 0x3f, 0xc2, 0x4d, 0xd9, 0x2e, 0x08, 0xf7, 0x97, 0x2f, 0x8e, 0x70, + 0xbf, 0x93, 0x11, 0x6e, 0xc9, 0x7f, 0xb0, 0xd0, 0x30, 0xbd, 0xc7, 0x67, 0x0d, 0x5c, 0x64, 0x9f, 0xab, 0xfb, 0xc4, + 0xc0, 0xab, 0x7a, 0x91, 0xbd, 0xf6, 0x2f, 0x4b, 0xd9, 0x82, 0x1a, 0x05, 0xa0, 0x98, 0xd7, 0xd1, 0x47, 0xd7, 0x65, + 0x1f, 0x5c, 0xdd, 0x44, 0x18, 0x06, 0xe8, 0xf3, 0xfb, 0x30, 0x0d, 0xac, 0x77, 0xfc, 0x1e, 0x09, 0x0a, 0xdd, 0x37, + 0x51, 0x3c, 0xf7, 0x30, 0xc5, 0x88, 0xaa, 0x83, 0x3b, 0x1d, 0x3c, 0xd8, 0x10, 0x08, 0x64, 0x14, 0x85, 0xe3, 0x5c, + 0x2b, 0xc9, 0xdc, 0x4b, 0xe2, 0xb8, 0xd5, 0x3b, 0xe6, 0xc5, 0xaa, 0x41, 0xaf, 0x61, 0x71, 0x9f, 0xb5, 0xed, 0x67, + 0xad, 0x83, 0x67, 0x47, 0x36, 0xfc, 0xef, 0xb0, 0x76, 0x66, 0xf0, 0x8a, 0xf3, 0x28, 0x4c, 0x67, 0x45, 0xcd, 0xa6, + 0x6a, 0x2b, 0xc6, 0x3e, 0x16, 0xb5, 0x8e, 0xeb, 0x2b, 0x8d, 0xbd, 0xbb, 0xa2, 0x4e, 0x6d, 0x8d, 0x59, 0xb4, 0x94, + 0xc0, 0xaa, 0x81, 0xc6, 0x0f, 0x97, 0x20, 0x67, 0x97, 0x6a, 0xc8, 0xaf, 0xf9, 0x70, 0x8b, 0x71, 0xb1, 0x76, 0x76, + 0x25, 0x72, 0x28, 0xa8, 0x3d, 0x91, 0x56, 0xef, 0xde, 0x19, 0xe4, 0x2a, 0x4a, 0x1b, 0x73, 0x4e, 0x61, 0x66, 0x43, + 0xc8, 0x38, 0xc5, 0xc4, 0x02, 0x79, 0xb4, 0x40, 0x69, 0xbc, 0x0c, 0x47, 0x1a, 0xfe, 0xf4, 0x86, 0x89, 0xe6, 0xef, + 0xc7, 0x16, 0xff, 0xb0, 0x8e, 0xab, 0xe6, 0xf5, 0xed, 0x22, 0xe9, 0x7c, 0x22, 0x56, 0xc5, 0x7b, 0x96, 0x1a, 0x31, + 0xea, 0xb1, 0x69, 0x69, 0x4d, 0xd7, 0x7b, 0x96, 0x37, 0x7c, 0x96, 0x1a, 0xe1, 0x73, 0xd0, 0x7d, 0xba, 0xf6, 0x93, + 0x27, 0x54, 0x6b, 0xcf, 0x15, 0xc3, 0x3a, 0x1d, 0x15, 0x99, 0x29, 0x14, 0x6f, 0x1a, 0x51, 0x72, 0x8a, 0xee, 0xc8, + 0x88, 0x9e, 0x3f, 0xef, 0xbb, 0x8e, 0x3e, 0x8c, 0x99, 0xf7, 0x31, 0x13, 0xe1, 0xbe, 0x43, 0xcc, 0x4f, 0x7b, 0xbe, + 0x9b, 0xa1, 0x91, 0x5e, 0xeb, 0x4a, 0xbb, 0x80, 0x3b, 0x93, 0x2d, 0xdc, 0x11, 0x38, 0xf6, 0x82, 0xdc, 0xf5, 0x64, + 0x50, 0xe0, 0x09, 0x83, 0x1f, 0x51, 0xe7, 0x7a, 0xe6, 0x25, 0x3f, 0x24, 0x51, 0xf8, 0xcb, 0x02, 0x82, 0x1f, 0x17, + 0x16, 0x45, 0xe2, 0x32, 0xd6, 0xb6, 0x6c, 0xcb, 0x56, 0xf3, 0xfe, 0x26, 0xfe, 0xd4, 0x5d, 0x47, 0xa9, 0xd7, 0xdd, + 0x73, 0x8c, 0x20, 0x9a, 0x82, 0x7b, 0x5d, 0xea, 0xa7, 0x01, 0xeb, 0xaa, 0x2a, 0xf8, 0xd9, 0xcd, 0xe9, 0xba, 0x9e, + 0x71, 0xa7, 0x07, 0x2f, 0x86, 0x6c, 0xe6, 0xf1, 0x9d, 0xf0, 0xd0, 0xc5, 0x18, 0xea, 0x3f, 0x02, 0x8d, 0xd4, 0x54, + 0x0d, 0x44, 0x06, 0x2c, 0x4e, 0x4c, 0xd9, 0x89, 0xa8, 0xab, 0x40, 0x1b, 0x5d, 0xe5, 0x63, 0x9b, 0xc4, 0xde, 0x1c, + 0xd2, 0xed, 0xae, 0x33, 0x83, 0x23, 0x60, 0x95, 0x63, 0x60, 0xc5, 0x79, 0x71, 0x64, 0x28, 0x2d, 0xc7, 0x50, 0x6c, + 0xc0, 0xc2, 0x6a, 0x66, 0xac, 0xb3, 0xab, 0xde, 0x7d, 0x76, 0x10, 0x84, 0x76, 0x1e, 0xd1, 0x38, 0xc8, 0x02, 0x82, + 0x6b, 0x98, 0x52, 0xca, 0x9d, 0xa3, 0x49, 0x89, 0x35, 0x7d, 0xd2, 0x85, 0x5e, 0xb0, 0xdb, 0x54, 0x07, 0x85, 0x92, + 0xa8, 0xe2, 0xeb, 0x6b, 0xf4, 0x23, 0xf6, 0x43, 0xc5, 0xff, 0xf4, 0x49, 0xf3, 0xc1, 0xc7, 0xc9, 0x95, 0xe6, 0x07, + 0x9e, 0xf5, 0xd2, 0x84, 0xf9, 0x85, 0xf6, 0x1e, 0x27, 0x0b, 0x1c, 0x10, 0xe1, 0xdf, 0xa2, 0x58, 0xfc, 0xe0, 0xd6, + 0x13, 0x56, 0xe0, 0x85, 0x53, 0xc0, 0x74, 0x5e, 0x38, 0xdd, 0xb0, 0xd2, 0x22, 0x57, 0xe8, 0x4a, 0x69, 0xd1, 0x55, + 0x61, 0x41, 0x95, 0xbc, 0xbc, 0xbb, 0xf0, 0xa6, 0x3f, 0x79, 0x73, 0xa6, 0xa9, 0x40, 0xfc, 0xd0, 0x73, 0xb7, 0x50, + 0xf0, 0x3e, 0x77, 0x9f, 0x9e, 0xcc, 0x59, 0xea, 0x91, 0x76, 0x08, 0xee, 0xc4, 0xc0, 0x25, 0x28, 0x9c, 0xfe, 0xf0, + 0x38, 0x18, 0x2e, 0xa5, 0xd8, 0x22, 0xf2, 0x61, 0x28, 0x9c, 0x7c, 0x99, 0x68, 0x08, 0xea, 0x3a, 0x06, 0xf9, 0x21, + 0x8c, 0x3c, 0x4c, 0xb3, 0xe3, 0x86, 0x91, 0xda, 0x7f, 0x9a, 0xbb, 0x6c, 0x36, 0x2d, 0x42, 0xe0, 0x87, 0x1f, 0x2f, + 0x63, 0x16, 0xfc, 0xc3, 0x7d, 0x0a, 0xf4, 0xfc, 0xe9, 0x95, 0xaa, 0xf7, 0x52, 0x6b, 0x16, 0xb3, 0x89, 0xfb, 0x14, + 0xee, 0xa9, 0x5d, 0xb4, 0x9a, 0x05, 0x66, 0xfe, 0xf9, 0xed, 0x3c, 0x30, 0xf0, 0xd6, 0x4f, 0xb0, 0xa8, 0xed, 0x56, + 0x11, 0xee, 0xbc, 0xbd, 0xd3, 0x5d, 0xbf, 0xcf, 0x2f, 0xf1, 0x70, 0x31, 0x5c, 0x97, 0xae, 0xde, 0x4e, 0x0f, 0xaf, + 0xd5, 0xc3, 0xc0, 0x1b, 0x7d, 0xec, 0xd1, 0x9b, 0xd2, 0x83, 0x09, 0x44, 0x7c, 0xe4, 0x2d, 0xba, 0x48, 0x75, 0xe5, + 0x42, 0x70, 0xaa, 0xa6, 0xd2, 0x9c, 0xe1, 0xab, 0xdd, 0xcb, 0xb8, 0x95, 0xd7, 0xf8, 0x65, 0xfc, 0xd4, 0x6a, 0xe6, + 0xa7, 0x4c, 0x7c, 0x0a, 0x1f, 0xb2, 0x4c, 0xdc, 0xdf, 0xe9, 0xe6, 0x8a, 0xf7, 0x6d, 0xab, 0xad, 0x38, 0x9d, 0xef, + 0x0e, 0x6f, 0x1c, 0x7b, 0xd6, 0x72, 0xac, 0xce, 0x07, 0xa7, 0x33, 0x6b, 0x5b, 0xc7, 0x81, 0xd9, 0xb6, 0x8e, 0xe1, + 0xcf, 0x87, 0x63, 0xab, 0x33, 0x33, 0x5b, 0xd6, 0xc1, 0x07, 0xa7, 0x15, 0x98, 0x1d, 0xeb, 0x18, 0xfe, 0x9c, 0x53, + 0x2b, 0xb8, 0x17, 0xd1, 0x35, 0xe8, 0x69, 0x09, 0x39, 0x48, 0xbf, 0x73, 0x55, 0xad, 0x51, 0xa2, 0x7a, 0x35, 0xea, + 0xde, 0x05, 0x06, 0x97, 0x10, 0x69, 0x6d, 0x30, 0xf4, 0x90, 0x16, 0xba, 0x8c, 0xd2, 0xcd, 0x0a, 0xc3, 0x37, 0xe1, + 0xa1, 0x5e, 0xe4, 0x3f, 0x95, 0x4e, 0x10, 0xaf, 0xdb, 0x4b, 0x68, 0xbb, 0x4b, 0x61, 0xe5, 0xb4, 0xca, 0xb1, 0x6b, + 0xc8, 0x7c, 0xac, 0x1b, 0xa0, 0x3a, 0x06, 0xc4, 0x54, 0x84, 0x83, 0xd2, 0x6a, 0xd1, 0x96, 0xc0, 0x66, 0x09, 0x4b, + 0xa9, 0x48, 0x13, 0x2d, 0x81, 0xd8, 0xe8, 0xba, 0x48, 0x58, 0x8c, 0x1d, 0xf3, 0x1a, 0x8c, 0x67, 0x56, 0xae, 0x7d, + 0xd5, 0xab, 0xe2, 0x4b, 0xf0, 0x8a, 0xb7, 0xc2, 0x68, 0x85, 0x56, 0x1f, 0xf7, 0xcd, 0x1d, 0xc6, 0x19, 0x60, 0xc2, + 0xe6, 0xac, 0x0c, 0x2c, 0x0f, 0x9d, 0x5d, 0xfd, 0xe0, 0x06, 0x82, 0x7e, 0xd0, 0x07, 0xa5, 0x44, 0xdd, 0x9f, 0xd5, + 0x0f, 0x8f, 0x62, 0x21, 0x27, 0xcb, 0x1c, 0xfb, 0x71, 0x0e, 0x9e, 0x44, 0x51, 0x9c, 0xfa, 0x4c, 0xa5, 0xba, 0x41, + 0xb1, 0x9c, 0x58, 0x7c, 0xe3, 0x05, 0x92, 0xdd, 0x9d, 0xd4, 0x72, 0x2f, 0x27, 0x54, 0x4f, 0x9e, 0x14, 0xc0, 0x99, + 0x15, 0xb8, 0x4f, 0x9c, 0x43, 0xe0, 0x12, 0x0e, 0x59, 0x7b, 0xab, 0x09, 0x28, 0x5d, 0xcc, 0xb6, 0xb9, 0x82, 0x17, + 0x89, 0x99, 0x84, 0x99, 0x97, 0x30, 0x30, 0x69, 0xb4, 0x43, 0xdd, 0x30, 0x2f, 0x81, 0xcc, 0x76, 0x95, 0x9b, 0x99, + 0xaa, 0xf7, 0x42, 0x61, 0x2d, 0x11, 0x6e, 0xc9, 0x49, 0xc7, 0xaf, 0x8e, 0x2a, 0x4c, 0xcd, 0x96, 0x71, 0xdc, 0xe3, + 0xcf, 0xfe, 0xef, 0x1e, 0x04, 0xfa, 0x96, 0x82, 0x79, 0x47, 0x05, 0x8b, 0x94, 0x7c, 0x0d, 0x73, 0x7a, 0x4f, 0x84, + 0x9e, 0x25, 0xa7, 0x2a, 0x14, 0xa9, 0x5d, 0x15, 0xfd, 0xd8, 0xd4, 0xdc, 0xb6, 0x35, 0xa7, 0x62, 0x45, 0x81, 0xe1, + 0x63, 0xfe, 0x4f, 0xe1, 0xe7, 0xaa, 0x3f, 0x79, 0xd2, 0x48, 0x1c, 0xc9, 0x96, 0x28, 0x61, 0xa9, 0xb8, 0x4f, 0x68, + 0xaa, 0x8c, 0x77, 0x55, 0x19, 0xf5, 0xe5, 0xfd, 0x22, 0x36, 0x13, 0x26, 0xb9, 0xb4, 0xf7, 0xf0, 0xe7, 0x90, 0x79, + 0xa9, 0xc5, 0x75, 0xbb, 0x9a, 0xc4, 0x74, 0x18, 0x80, 0x36, 0x32, 0x42, 0x21, 0xf9, 0x30, 0x07, 0x8f, 0xd7, 0x7f, + 0x59, 0xf2, 0x20, 0x14, 0xd0, 0xc7, 0xa7, 0x4f, 0x76, 0x11, 0x37, 0xf4, 0x6d, 0xea, 0x51, 0xdc, 0x36, 0x99, 0x17, + 0x88, 0x52, 0x8f, 0xec, 0x4f, 0x7c, 0x0c, 0xb5, 0x53, 0x1f, 0x41, 0x4c, 0x8a, 0x54, 0xd1, 0x7f, 0x7b, 0xf1, 0x8d, + 0xc2, 0x0f, 0x00, 0x59, 0x37, 0xe0, 0xc5, 0x8b, 0xe2, 0xe3, 0xb8, 0x14, 0x1f, 0x47, 0xe1, 0x99, 0x97, 0x21, 0x47, + 0x6c, 0xb6, 0x4f, 0x53, 0x88, 0x02, 0x73, 0xb2, 0xf9, 0x98, 0x2f, 0x83, 0xd4, 0x5f, 0x78, 0x71, 0xba, 0x8f, 0xc1, + 0x71, 0x30, 0xd8, 0x4e, 0x53, 0xfc, 0x0a, 0x32, 0x1b, 0x11, 0xd9, 0x4c, 0xd2, 0x50, 0xd8, 0x8d, 0x4c, 0xfc, 0x20, + 0x37, 0x1b, 0x11, 0x1f, 0xf0, 0x46, 0x23, 0xb6, 0x48, 0xdd, 0x52, 0x10, 0x9e, 0x68, 0x94, 0xb2, 0xd4, 0x4c, 0xd2, + 0x98, 0x79, 0x73, 0x35, 0x0f, 0xca, 0xb5, 0xd9, 0x5f, 0xb2, 0x1c, 0x42, 0x54, 0x21, 0x11, 0x1e, 0x8c, 0x06, 0x08, + 0x06, 0x1c, 0x00, 0x22, 0x04, 0xc5, 0xa1, 0x29, 0x3c, 0x8f, 0xa6, 0x95, 0x2d, 0x55, 0xb0, 0x54, 0xa7, 0x98, 0xd4, + 0x8c, 0x6e, 0x5e, 0x20, 0xdd, 0x1e, 0x45, 0xc1, 0x35, 0x8f, 0xb9, 0x91, 0x67, 0xc7, 0x51, 0xfb, 0x27, 0xfc, 0x3a, + 0xae, 0x60, 0xb8, 0x19, 0xf5, 0xd0, 0x86, 0xb4, 0x6d, 0x4d, 0xd1, 0x38, 0xf6, 0x79, 0x65, 0xa0, 0x99, 0xd4, 0x33, + 0x66, 0xde, 0x24, 0x58, 0x2e, 0x80, 0x64, 0x95, 0x0c, 0x7c, 0x66, 0x4e, 0x3f, 0x77, 0xff, 0x44, 0xa8, 0x90, 0xaa, + 0x7d, 0xfa, 0xf4, 0x7e, 0xf0, 0xaf, 0x7f, 0x42, 0x7a, 0xd0, 0x99, 0x23, 0x62, 0x60, 0x5c, 0xca, 0xb5, 0x38, 0x5b, + 0x6c, 0x0c, 0xd0, 0xb8, 0x8b, 0x8d, 0x45, 0x74, 0x42, 0xb1, 0xb7, 0xb2, 0xc1, 0x95, 0x88, 0xab, 0x07, 0x89, 0x85, + 0x75, 0x11, 0xa9, 0x63, 0x00, 0xcb, 0x3b, 0x10, 0x31, 0x5c, 0x94, 0xbf, 0xdd, 0xbe, 0x3c, 0x56, 0x8a, 0x70, 0x8f, + 0x75, 0x16, 0x48, 0xb4, 0x87, 0xfa, 0x27, 0x9e, 0x82, 0xdc, 0x14, 0xf2, 0x45, 0x49, 0x77, 0x1f, 0x86, 0x39, 0x8b, + 0xe6, 0xcc, 0xf2, 0xa3, 0xfd, 0x15, 0x1b, 0x9a, 0xde, 0xc2, 0x27, 0x3b, 0x22, 0x94, 0x13, 0x2a, 0xc4, 0x92, 0xe6, + 0xe6, 0x39, 0xc4, 0xf8, 0x67, 0xc5, 0x54, 0x46, 0x95, 0xc0, 0x6d, 0xad, 0x42, 0x6f, 0x79, 0xc0, 0x83, 0xa2, 0x89, + 0x9a, 0xfd, 0x93, 0x7d, 0xaf, 0x5f, 0xce, 0x94, 0x63, 0x89, 0x8c, 0xaf, 0x65, 0x2a, 0x70, 0x4a, 0x09, 0x6f, 0x44, + 0x6e, 0x9b, 0xe2, 0xc1, 0x8c, 0x26, 0x13, 0x39, 0xbb, 0x8d, 0x55, 0x06, 0x2f, 0x9f, 0xb4, 0x62, 0x4b, 0x47, 0x0b, + 0xfa, 0xd2, 0xe6, 0x27, 0xf2, 0x9f, 0x6a, 0x17, 0xd3, 0x5a, 0xc1, 0x98, 0xe1, 0xbc, 0x6f, 0x64, 0xc9, 0xc9, 0x67, + 0xec, 0x11, 0x55, 0xe2, 0x88, 0xa4, 0x9a, 0x93, 0xb1, 0x81, 0xa5, 0xda, 0x73, 0x5d, 0xc2, 0x73, 0x55, 0x74, 0x07, + 0x93, 0x58, 0x93, 0xfd, 0x16, 0x06, 0x9b, 0x42, 0x43, 0x93, 0xdc, 0x7b, 0xb1, 0x51, 0x75, 0x38, 0x9b, 0x30, 0xee, + 0x7b, 0x62, 0xfb, 0x95, 0x36, 0x28, 0x6c, 0x3c, 0xbe, 0xee, 0x80, 0xe0, 0x45, 0x3f, 0x15, 0x3c, 0xaf, 0x7c, 0x4d, + 0x28, 0xdd, 0x0c, 0xbc, 0xbb, 0x48, 0x32, 0xbb, 0xe2, 0x11, 0x58, 0xce, 0xb1, 0xf4, 0x42, 0x78, 0x3e, 0x6f, 0x1c, + 0x34, 0xa4, 0x61, 0x90, 0x25, 0x74, 0xf3, 0xb0, 0x15, 0x04, 0x38, 0x60, 0xf7, 0x9d, 0x35, 0xb9, 0x6e, 0x79, 0x30, + 0x88, 0x3c, 0xb3, 0xe2, 0x1c, 0x96, 0x5e, 0x22, 0x5a, 0xc8, 0x4e, 0xf6, 0x61, 0x7c, 0x94, 0xf7, 0x50, 0x30, 0x79, + 0xc2, 0xbe, 0x10, 0x6f, 0xbd, 0x7e, 0xd3, 0xad, 0xb7, 0xca, 0xa3, 0x94, 0x59, 0x2f, 0x5f, 0x87, 0xd8, 0x36, 0x5e, + 0x42, 0xb6, 0x67, 0xdf, 0x8f, 0x39, 0x61, 0x90, 0xbe, 0x92, 0x07, 0xc3, 0x2c, 0xd5, 0xd3, 0xb7, 0x06, 0x89, 0xa1, + 0x8c, 0xbb, 0x1f, 0x96, 0x98, 0x6e, 0x37, 0xeb, 0xa5, 0x4c, 0xc4, 0x6c, 0x38, 0x4f, 0x1b, 0xc2, 0x3a, 0x34, 0x55, + 0x21, 0x3e, 0x7c, 0x4b, 0x85, 0x62, 0x9b, 0x6f, 0xab, 0x55, 0x70, 0x56, 0x45, 0x35, 0x4f, 0x53, 0x1f, 0xe1, 0x81, + 0xd8, 0xa8, 0x8d, 0xa5, 0x18, 0x6c, 0x22, 0x75, 0xa1, 0xaa, 0x50, 0x2d, 0x78, 0x8b, 0x05, 0x55, 0xd6, 0x7b, 0x27, + 0xfb, 0x74, 0x9d, 0xee, 0xd3, 0x06, 0xec, 0x9f, 0x80, 0x65, 0x3a, 0xed, 0x09, 0x6f, 0xb1, 0xe0, 0x2b, 0x4e, 0xbf, + 0xe8, 0xcd, 0xfe, 0x2c, 0x9d, 0x07, 0xfd, 0xff, 0x05, 0x64, 0x23, 0xa6, 0xdb, 0x06, 0x7b, 0x03, 0x00}; #else // Brotli (default, smaller) -constexpr uint8_t INDEX_BR[] PROGMEM = { - 0x5b, 0x36, 0x7a, 0x53, 0xc2, 0x36, 0x06, 0x5a, 0x1f, 0xd4, 0x4e, 0x00, 0xb3, 0xd6, 0xea, 0xff, 0x0a, 0xab, 0x51, - 0x94, 0xb1, 0xe6, 0xb0, 0x2e, 0x61, 0xbb, 0x1a, 0x70, 0x3b, 0xd8, 0x06, 0xfd, 0x7d, 0x2f, 0x1a, 0x00, 0x55, 0x35, - 0xe3, 0xa8, 0x1c, 0x62, 0xca, 0xd3, 0xb4, 0x00, 0xdb, 0x5e, 0x43, 0xa7, 0x14, 0x08, 0xa4, 0x51, 0x99, 0x96, 0xb6, - 0xf5, 0x0e, 0x99, 0x80, 0x52, 0x31, 0xe8, 0x10, 0x27, 0x1c, 0x04, 0x11, 0x58, 0xc5, 0x1c, 0xcc, 0xd4, 0x74, 0x4c, - 0x33, 0x11, 0xbb, 0xdb, 0xb0, 0xb4, 0x0a, 0x87, 0x13, 0x12, 0xb4, 0x8f, 0xe7, 0xd1, 0xc8, 0x85, 0x26, 0x07, 0xab, - 0x2e, 0x7a, 0x6e, 0x93, 0xb9, 0x4c, 0xb4, 0x84, 0x5b, 0x59, 0xda, 0xde, 0x2f, 0x74, 0x88, 0x3c, 0x53, 0x3b, 0xfd, - 0x28, 0xf8, 0x60, 0x4b, 0xf2, 0xc2, 0x03, 0xda, 0x33, 0x59, 0xe4, 0x2a, 0x48, 0x26, 0xde, 0x20, 0x6e, 0xcb, 0x83, - 0xef, 0x81, 0x7a, 0x6b, 0x36, 0x9a, 0x3f, 0x38, 0x8e, 0xfd, 0xf9, 0x7e, 0x73, 0xab, 0x6e, 0x85, 0xf0, 0x62, 0xe0, - 0x60, 0x60, 0x23, 0x1b, 0x11, 0xaf, 0x39, 0x32, 0xed, 0x79, 0x20, 0x27, 0x04, 0x1f, 0x6b, 0xf4, 0xd9, 0x97, 0x2f, - 0x38, 0xe4, 0x5b, 0x75, 0xbb, 0xb4, 0xfe, 0xd5, 0xfb, 0x5f, 0xa5, 0xc2, 0x5c, 0x88, 0xc6, 0xdf, 0xd0, 0x1e, 0x10, - 0xa7, 0x44, 0x3b, 0xdd, 0xb8, 0xbd, 0x2c, 0x7a, 0x10, 0x61, 0xbe, 0x8b, 0xbb, 0x3c, 0x10, 0x0e, 0x5f, 0x06, 0xc6, - 0xe0, 0xf2, 0xe6, 0x88, 0xa8, 0xb8, 0xa2, 0xab, 0xf7, 0x6b, 0xab, 0xe9, 0xfb, 0xbd, 0xa6, 0xfe, 0xd7, 0xef, 0x23, - 0xd3, 0x86, 0xa9, 0xdc, 0x57, 0x3a, 0xf7, 0xb8, 0x49, 0x6e, 0x45, 0x76, 0xda, 0xa6, 0x21, 0xc3, 0x2b, 0x0f, 0xac, - 0xc9, 0x85, 0x03, 0x60, 0xdd, 0x28, 0x5d, 0xe5, 0x3b, 0xfb, 0xf3, 0xbb, 0xdc, 0xc2, 0x94, 0xab, 0x90, 0x2b, 0x05, - 0xc8, 0x64, 0x3f, 0x3f, 0xc8, 0x1a, 0xe3, 0xef, 0x17, 0x88, 0x77, 0x9f, 0x18, 0x8d, 0xda, 0xd2, 0xc0, 0xb8, 0x5b, - 0x99, 0x6e, 0xd9, 0x12, 0xaa, 0xdc, 0x2f, 0xeb, 0xff, 0xff, 0xfb, 0x4e, 0xff, 0xbf, 0x7e, 0xed, 0x55, 0x22, 0xe6, - 0x8a, 0x96, 0x64, 0x4c, 0xdf, 0x4b, 0x2c, 0xef, 0x43, 0x42, 0x69, 0x18, 0x37, 0x29, 0x19, 0x40, 0x1f, 0x19, 0x8a, - 0x6b, 0x84, 0xb5, 0x31, 0x6a, 0x1d, 0xd9, 0x57, 0x5b, 0x04, 0xbb, 0xd6, 0xde, 0xfa, 0x52, 0xfd, 0xbe, 0x7e, 0x1f, - 0xe7, 0x5d, 0xc3, 0x72, 0xc9, 0x69, 0x3a, 0x6f, 0xf7, 0x1e, 0x6d, 0x29, 0x74, 0xce, 0x4b, 0xde, 0x98, 0xe5, 0x62, - 0x40, 0x34, 0x7a, 0xba, 0x6d, 0x0c, 0x30, 0x01, 0xd0, 0x92, 0x98, 0x29, 0xed, 0xfb, 0xea, 0xeb, 0x7f, 0xfd, 0x56, - 0x3a, 0x29, 0x0a, 0x1f, 0xd9, 0xb7, 0x84, 0x3a, 0x26, 0xfa, 0xd6, 0xce, 0x76, 0x3a, 0x32, 0x19, 0x0a, 0xb2, 0x94, - 0xc7, 0x80, 0xbe, 0x24, 0x74, 0x27, 0x0a, 0xff, 0x5f, 0x5f, 0xd3, 0xfa, 0xfa, 0x95, 0x08, 0xbb, 0xcc, 0xa5, 0x4e, - 0x51, 0xa8, 0x7b, 0x7f, 0x4f, 0x49, 0xce, 0xb2, 0xec, 0x9e, 0x0a, 0x41, 0xcb, 0xb4, 0x8d, 0x17, 0xe1, 0x00, 0xdc, - 0x13, 0x13, 0x59, 0xf7, 0x30, 0x55, 0xeb, 0xbf, 0x9f, 0x97, 0x0d, 0x67, 0x15, 0x30, 0x14, 0x61, 0x0c, 0x48, 0xaa, - 0xd8, 0x41, 0x5a, 0x75, 0x4b, 0xd3, 0x16, 0xa5, 0xc1, 0xd4, 0xc8, 0x9c, 0x84, 0x1c, 0x78, 0x01, 0xe8, 0x24, 0x45, - 0xca, 0xff, 0x73, 0xbe, 0x2d, 0xad, 0xfe, 0x74, 0x75, 0x79, 0xa2, 0xba, 0x1f, 0x6a, 0x09, 0x10, 0xc6, 0x50, 0xb3, - 0x6c, 0x4a, 0xe7, 0x9f, 0x5d, 0xbf, 0x26, 0x78, 0xa6, 0x37, 0x07, 0xce, 0xa5, 0x55, 0xaf, 0xef, 0x06, 0xd4, 0x72, - 0x4f, 0x48, 0xdf, 0x15, 0x1b, 0xec, 0xd7, 0x48, 0xa6, 0xe5, 0xbd, 0xf3, 0x85, 0x88, 0xaa, 0x1c, 0x80, 0x11, 0xb4, - 0x51, 0x68, 0xa0, 0xbc, 0xbd, 0xf6, 0xaa, 0x6f, 0x55, 0x94, 0x8e, 0x0d, 0x8c, 0xc0, 0x32, 0xcb, 0xaf, 0x77, 0x27, - 0x94, 0x5c, 0xad, 0xbd, 0x6f, 0x92, 0xf0, 0x18, 0x70, 0x5a, 0x6c, 0x58, 0x38, 0x2f, 0xd9, 0x90, 0xa8, 0xf9, 0x9a, - 0xad, 0xc0, 0x05, 0x0a, 0xeb, 0x98, 0xcb, 0xaa, 0x7a, 0x8b, 0x0a, 0x89, 0xf8, 0x75, 0xfb, 0x7e, 0xc6, 0x7d, 0x4c, - 0x37, 0xc3, 0x0c, 0x86, 0x8d, 0x82, 0x27, 0x18, 0xd7, 0x33, 0xb5, 0x4c, 0x5f, 0x6f, 0xa7, 0x52, 0x3e, 0xdd, 0x19, - 0x97, 0x57, 0x40, 0x5b, 0x29, 0xed, 0xd9, 0x0b, 0xb1, 0xcb, 0x58, 0x04, 0x08, 0x0d, 0x20, 0x51, 0xe9, 0x1b, 0x22, - 0xf6, 0x9a, 0x6f, 0xe8, 0xe9, 0xbc, 0x01, 0x2c, 0x70, 0xf8, 0x86, 0x54, 0x72, 0xa5, 0x38, 0x22, 0xd0, 0xcb, 0x95, - 0xe1, 0xc1, 0xb5, 0xb9, 0x59, 0x01, 0xae, 0xd5, 0x5a, 0x4a, 0xfa, 0x13, 0x37, 0x9b, 0xd6, 0xff, 0x3e, 0x2f, 0xce, - 0xdb, 0xec, 0x44, 0xba, 0xfe, 0x92, 0xe3, 0xe4, 0x4a, 0xe9, 0xd9, 0x82, 0x09, 0x25, 0xcc, 0xb0, 0x86, 0x01, 0x93, - 0xa6, 0xd5, 0x3e, 0x3c, 0x24, 0x1f, 0x50, 0xab, 0x6f, 0xf8, 0x83, 0xe5, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, - 0x74, 0x20, 0x44, 0xf6, 0x00, 0xe4, 0x38, 0xc3, 0x91, 0xf5, 0xfb, 0xce, 0xcc, 0x2a, 0x50, 0x0d, 0x90, 0x6c, 0x59, - 0xbf, 0xd6, 0x62, 0x53, 0x71, 0xcd, 0xbb, 0xcc, 0xef, 0xa2, 0x33, 0x7e, 0x18, 0x56, 0x64, 0x44, 0x66, 0x23, 0x5d, - 0x0d, 0xcb, 0x36, 0xb2, 0x9c, 0x06, 0xf6, 0xbe, 0xf7, 0x7f, 0x14, 0xfe, 0xff, 0x91, 0xc5, 0x89, 0x88, 0x2c, 0x50, - 0x91, 0x59, 0xc5, 0x39, 0x99, 0x05, 0xcc, 0xa8, 0x0a, 0xe0, 0x8c, 0x0a, 0x60, 0x1f, 0x1d, 0x90, 0x63, 0x41, 0xd0, - 0x68, 0x9a, 0x6c, 0xf6, 0xd1, 0x90, 0x2d, 0x6f, 0x77, 0x5a, 0xac, 0x38, 0x94, 0xeb, 0x19, 0xd9, 0x96, 0xfc, 0x6e, - 0x07, 0xca, 0x9a, 0xa5, 0xb4, 0xd2, 0xd1, 0x7d, 0x73, 0x6f, 0x76, 0xca, 0xa9, 0x23, 0x50, 0x69, 0xd5, 0x56, 0x08, - 0xd7, 0xcc, 0xec, 0x06, 0x76, 0x3f, 0xe7, 0x97, 0x36, 0x1f, 0x37, 0xc5, 0xa4, 0x98, 0x94, 0xe0, 0x80, 0xe4, 0x19, - 0x7b, 0xc6, 0x12, 0x0a, 0xc7, 0xf2, 0xde, 0xa9, 0x3f, 0x86, 0xdf, 0x43, 0x69, 0x61, 0x30, 0x75, 0xa6, 0x69, 0xfa, - 0xef, 0xb6, 0x31, 0xab, 0x2f, 0xd7, 0xca, 0xcc, 0x2d, 0xcd, 0x10, 0x42, 0x0a, 0xa0, 0xa2, 0xeb, 0xff, 0x36, 0xbe, - 0xd6, 0x57, 0x8e, 0xda, 0xfa, 0x75, 0xd4, 0xdd, 0x7e, 0x5c, 0x67, 0x08, 0x10, 0x02, 0xed, 0x3c, 0x64, 0x4a, 0x75, - 0xdb, 0x71, 0x9e, 0x3d, 0x4d, 0x08, 0x21, 0x04, 0xe2, 0xa8, 0xe2, 0xf8, 0x5f, 0x23, 0x9d, 0x4a, 0x1b, 0x02, 0x0d, - 0xa4, 0x48, 0xfd, 0x1b, 0xeb, 0x6f, 0x0d, 0xdb, 0xf7, 0xf4, 0x10, 0x9d, 0xd8, 0xd3, 0x00, 0xa1, 0x36, 0x49, 0xbe, - 0xd8, 0x9a, 0xa7, 0xb5, 0x6d, 0x74, 0x2c, 0x43, 0x2d, 0x7f, 0xdf, 0x4c, 0xbf, 0x6d, 0x30, 0x06, 0x2c, 0x33, 0x25, - 0x81, 0x19, 0xf2, 0xb9, 0x6e, 0x04, 0xf7, 0xcf, 0x4c, 0x26, 0xce, 0x1e, 0x07, 0x80, 0xd3, 0xb1, 0x47, 0x5b, 0x88, - 0x19, 0x28, 0xc7, 0xb9, 0x83, 0x9b, 0x5b, 0x23, 0x98, 0xf6, 0xf6, 0x50, 0xb2, 0xdd, 0x47, 0x21, 0xd6, 0x20, 0x5a, - 0x78, 0x61, 0x76, 0xf4, 0x81, 0xc9, 0xdb, 0x4e, 0x15, 0xbd, 0xa5, 0x5b, 0x7e, 0xc2, 0x1c, 0x81, 0x66, 0xf4, 0x92, - 0x5f, 0x04, 0xf0, 0xbe, 0x7d, 0x0f, 0x45, 0x99, 0x04, 0xca, 0xfe, 0xfa, 0xc9, 0x96, 0x91, 0x9d, 0x9f, 0xb8, 0x6b, - 0x7b, 0xc3, 0xe6, 0xe0, 0x21, 0x83, 0x27, 0x75, 0x98, 0xd9, 0x7e, 0x29, 0x3f, 0xe1, 0x6a, 0x19, 0xe6, 0x36, 0xe6, - 0xf3, 0xfd, 0x14, 0x5d, 0xa1, 0x21, 0x63, 0x41, 0xea, 0xb9, 0xf7, 0x87, 0xc6, 0xf2, 0xc7, 0x64, 0x59, 0x06, 0x6e, - 0xcb, 0x89, 0xc7, 0x92, 0xfa, 0xc5, 0x52, 0x4d, 0xdf, 0x93, 0x26, 0x01, 0x80, 0xac, 0xb5, 0x0d, 0xfd, 0x08, 0x57, - 0x71, 0x7d, 0xad, 0x5c, 0x14, 0xe3, 0x9a, 0x6f, 0x87, 0x09, 0x06, 0x92, 0xf5, 0x13, 0x28, 0x6e, 0x7b, 0xf7, 0x6f, - 0xcf, 0x6e, 0x6d, 0x59, 0x64, 0xd4, 0x74, 0x38, 0xbb, 0x0f, 0x9d, 0x69, 0x03, 0x8a, 0xb8, 0xc3, 0xdd, 0xa7, 0x63, - 0x4d, 0x41, 0x62, 0xc3, 0x21, 0x83, 0xe7, 0x02, 0x1d, 0xcb, 0x3e, 0xa9, 0xa5, 0x24, 0x6b, 0x72, 0xe6, 0xd2, 0x10, - 0x66, 0xa3, 0x73, 0x76, 0x1b, 0x4b, 0x07, 0xdc, 0x96, 0x33, 0xda, 0x45, 0x26, 0xf7, 0xbc, 0x89, 0xef, 0x68, 0xcc, - 0x2f, 0xbb, 0xc0, 0xde, 0xfa, 0x20, 0xdb, 0x42, 0xd0, 0x6c, 0xcc, 0xec, 0xc0, 0x37, 0xde, 0x77, 0xd3, 0x21, 0x09, - 0x12, 0x4d, 0xdf, 0xb7, 0xa0, 0x79, 0x31, 0xfa, 0xb8, 0xee, 0x61, 0xab, 0x50, 0xdf, 0xfe, 0x88, 0x87, 0x19, 0x9e, - 0x78, 0x39, 0x23, 0x5f, 0xef, 0xdd, 0xe6, 0x65, 0xe7, 0xd1, 0x17, 0x31, 0xbe, 0x3d, 0xbb, 0x7d, 0xb9, 0x79, 0x64, - 0xf7, 0x11, 0xd6, 0xbe, 0x1b, 0x12, 0x76, 0x35, 0xbf, 0x77, 0x1b, 0x7e, 0xf4, 0xda, 0x4b, 0x35, 0xab, 0xc9, 0x7f, - 0xfa, 0xfe, 0x13, 0xda, 0xa8, 0x1d, 0xdc, 0xc3, 0xfd, 0x05, 0xc2, 0xb3, 0xa6, 0x38, 0x17, 0x58, 0x73, 0x18, 0x7f, - 0xb6, 0x66, 0xc9, 0x3f, 0x3b, 0x22, 0xf4, 0x39, 0xcc, 0xd7, 0x39, 0x6f, 0xcf, 0x62, 0x6a, 0xfd, 0x4a, 0x44, 0x61, - 0x22, 0x2a, 0x83, 0x26, 0x28, 0xca, 0x2b, 0x27, 0x7d, 0xc7, 0x45, 0x49, 0x20, 0x91, 0xdd, 0x52, 0x2b, 0xa5, 0x75, - 0xe1, 0xe4, 0xde, 0xef, 0x00, 0x02, 0xfd, 0x39, 0xb6, 0x2c, 0xbb, 0xe4, 0xf5, 0x4b, 0x49, 0x7d, 0xc7, 0x3c, 0xcd, - 0x3d, 0x00, 0x91, 0x0a, 0xdd, 0x2c, 0x65, 0x61, 0x89, 0x12, 0x79, 0x36, 0x9e, 0xeb, 0xbc, 0xca, 0xd0, 0x43, 0xb7, - 0xef, 0xdb, 0x25, 0xf2, 0xf0, 0x7c, 0x86, 0x03, 0x7c, 0xc7, 0x9c, 0x53, 0xbd, 0xc2, 0x84, 0xbc, 0x72, 0x56, 0xdc, - 0x8f, 0xa1, 0xd4, 0x68, 0x22, 0x56, 0xe4, 0x66, 0x34, 0xc8, 0x7b, 0x46, 0x6e, 0xaa, 0xfd, 0x52, 0x5b, 0x33, 0x33, - 0xd7, 0xb7, 0xad, 0x96, 0x71, 0x86, 0x72, 0x2f, 0xaa, 0x3a, 0xaa, 0xef, 0x49, 0x20, 0x3d, 0xcb, 0x19, 0xd7, 0x37, - 0x6f, 0x56, 0x94, 0x5f, 0x2b, 0x95, 0x50, 0xf6, 0x0d, 0x35, 0x79, 0xcd, 0xec, 0x4b, 0xea, 0x1a, 0xe6, 0x29, 0xd2, - 0x76, 0x3a, 0xf2, 0x5c, 0x14, 0x32, 0x68, 0x05, 0x7b, 0x9e, 0x3c, 0xba, 0xf6, 0x65, 0x5e, 0xe2, 0x2f, 0x2b, 0xcb, - 0x88, 0x04, 0x68, 0xe4, 0x5f, 0x10, 0xcd, 0x0c, 0x54, 0xc5, 0xd3, 0x64, 0xe1, 0x24, 0x68, 0x71, 0xa2, 0x0d, 0x9e, - 0xfd, 0x7e, 0xdb, 0xec, 0x83, 0x12, 0x2e, 0xaa, 0xd4, 0x7d, 0x4f, 0x13, 0xf2, 0xf0, 0x73, 0x91, 0xac, 0x65, 0xa0, - 0xd7, 0x60, 0x9e, 0x26, 0x20, 0x15, 0x96, 0xc9, 0x58, 0xe8, 0x82, 0x9a, 0xd1, 0x4d, 0x93, 0xe9, 0x11, 0x5f, 0xde, - 0xe2, 0xa2, 0xb8, 0xd5, 0x6a, 0xcb, 0x37, 0xb3, 0xb4, 0x63, 0xda, 0x02, 0xda, 0x1f, 0x3a, 0x81, 0x27, 0x6c, 0x1e, - 0x0b, 0xef, 0x26, 0x27, 0x23, 0x8c, 0x3f, 0xf7, 0x72, 0xa4, 0x1d, 0x6a, 0x77, 0x42, 0xf4, 0xea, 0x40, 0xe0, 0xbe, - 0x50, 0xb6, 0x62, 0xec, 0x4d, 0x12, 0x51, 0xdd, 0x7f, 0x40, 0xb7, 0xf6, 0xbf, 0x59, 0xbb, 0xf4, 0x45, 0xd0, 0x58, - 0x09, 0x47, 0xd2, 0xfa, 0x6d, 0xa8, 0x3d, 0x44, 0x00, 0x4e, 0xaf, 0x82, 0x19, 0x76, 0xdb, 0x80, 0xd9, 0x71, 0x51, - 0x8e, 0xfb, 0x7c, 0xc2, 0x32, 0x3f, 0xd0, 0x32, 0xba, 0xa9, 0xfd, 0x71, 0xfc, 0x21, 0x63, 0x96, 0xb6, 0x30, 0xb5, - 0xaf, 0x1a, 0x7f, 0x69, 0xd0, 0x48, 0xc5, 0x79, 0xed, 0xd0, 0xc0, 0x4f, 0xec, 0x0b, 0x96, 0x83, 0x23, 0x41, 0x2f, - 0xf3, 0xc1, 0x33, 0x97, 0x6a, 0xb0, 0xbc, 0x39, 0x72, 0xa0, 0x10, 0xb6, 0x14, 0xa1, 0x6c, 0xb0, 0xb5, 0xd2, 0x8a, - 0x55, 0x4f, 0x18, 0x9b, 0xf7, 0xa7, 0xb7, 0x26, 0xb2, 0x29, 0x5b, 0x38, 0x4c, 0xf5, 0x85, 0x82, 0x64, 0x7f, 0x16, - 0x77, 0x59, 0x26, 0xc0, 0x41, 0xc2, 0xf0, 0x82, 0x8e, 0x24, 0xdf, 0x07, 0x6f, 0xfa, 0x2c, 0x58, 0x18, 0x6d, 0x9b, - 0x1f, 0x6d, 0xbd, 0x17, 0xcf, 0x2c, 0x88, 0x6f, 0x16, 0x14, 0xdb, 0xb2, 0xe2, 0x08, 0x4b, 0x35, 0x6c, 0x42, 0x68, - 0x05, 0x11, 0xa8, 0xa9, 0x3f, 0xd7, 0x83, 0x6d, 0xd6, 0xbe, 0x6a, 0x55, 0xa5, 0xb3, 0x24, 0xd5, 0x38, 0x82, 0x42, - 0x0e, 0x06, 0x45, 0x10, 0xba, 0xb3, 0x7b, 0xf0, 0x13, 0x07, 0xe3, 0x42, 0xe0, 0x86, 0x96, 0xa7, 0xae, 0x5b, 0xc7, - 0x2d, 0x03, 0x53, 0x7d, 0xb9, 0xd2, 0x3c, 0xee, 0xa1, 0x75, 0xb0, 0x6b, 0x3b, 0x92, 0xcf, 0xb5, 0x78, 0x42, 0xdf, - 0x9d, 0xe8, 0x04, 0x86, 0x87, 0x23, 0x4f, 0xbc, 0x3c, 0x90, 0x80, 0x87, 0x00, 0xb3, 0xf2, 0xdd, 0x0f, 0xa1, 0x7a, - 0x7d, 0x11, 0x50, 0x40, 0x7c, 0x55, 0x6e, 0xfb, 0x03, 0x04, 0x2b, 0xea, 0x58, 0x00, 0x27, 0x2a, 0x4e, 0xc9, 0x01, - 0x09, 0xc6, 0x11, 0xea, 0x1b, 0xa0, 0x9b, 0x0f, 0x95, 0xf2, 0x2f, 0x5c, 0x4f, 0xbc, 0x28, 0xcf, 0xfa, 0xf9, 0x96, - 0x7c, 0xba, 0x6a, 0x51, 0x70, 0xaa, 0xb6, 0x49, 0xa6, 0x50, 0xba, 0xc1, 0x61, 0x4a, 0x11, 0xa7, 0x89, 0x44, 0x2d, - 0x04, 0x60, 0x5b, 0x45, 0xb4, 0xf4, 0xeb, 0x75, 0xd8, 0xd1, 0x52, 0xd8, 0xb2, 0xe0, 0x0b, 0xf5, 0x43, 0x8d, 0xb0, - 0xd8, 0xa8, 0xed, 0x5c, 0x6a, 0xfe, 0xf3, 0x35, 0xc9, 0x86, 0xd6, 0x2e, 0x7b, 0x0b, 0x41, 0x4d, 0xe1, 0x02, 0xb5, - 0xe5, 0x45, 0x32, 0xb5, 0x83, 0x98, 0xfd, 0xc8, 0x44, 0x72, 0x62, 0x79, 0x65, 0x6f, 0x2a, 0x5b, 0xd7, 0xa6, 0xdd, - 0x37, 0x25, 0x18, 0x7e, 0xd4, 0x52, 0x7a, 0x36, 0xec, 0xfc, 0x5a, 0x59, 0x7a, 0x0c, 0x6b, 0x67, 0x4a, 0x20, 0x70, - 0xf9, 0x17, 0xa7, 0xed, 0x02, 0x93, 0x5b, 0x3d, 0xa6, 0xf4, 0x52, 0x8f, 0xf9, 0xee, 0x75, 0x48, 0x95, 0x2c, 0x04, - 0xc9, 0x61, 0xa0, 0xbf, 0x16, 0x13, 0xa5, 0x40, 0x0b, 0x89, 0x50, 0x6e, 0x23, 0x09, 0x70, 0xff, 0x5e, 0x95, 0x31, - 0xc0, 0xb6, 0x0e, 0x3f, 0x4b, 0xb3, 0xab, 0xe7, 0x62, 0x40, 0xd8, 0x18, 0x3d, 0x4c, 0x9d, 0x11, 0xc2, 0x49, 0x53, - 0x7b, 0xe7, 0x2a, 0x12, 0xc9, 0x51, 0x8a, 0x58, 0x6c, 0x9c, 0x95, 0x2e, 0x35, 0xc2, 0x5a, 0x18, 0xcb, 0xb1, 0x02, - 0x92, 0x33, 0xb7, 0x59, 0x79, 0x7c, 0xdb, 0x1c, 0x24, 0xc0, 0x3d, 0xe2, 0xe2, 0x1f, 0x9c, 0x04, 0xc8, 0x35, 0x41, - 0x82, 0x84, 0xf6, 0xd9, 0x80, 0x4c, 0x18, 0x90, 0x91, 0x31, 0x89, 0x6e, 0x04, 0x92, 0x7b, 0x4d, 0xa7, 0xfa, 0x18, - 0x60, 0x2a, 0x27, 0xab, 0x09, 0x44, 0x42, 0x1c, 0x6f, 0x6a, 0xc3, 0x4e, 0x60, 0x2c, 0x03, 0xec, 0xb8, 0x74, 0x54, - 0x72, 0x2e, 0x0e, 0x30, 0xac, 0x9a, 0xf9, 0x85, 0x4d, 0x97, 0xc0, 0x10, 0x47, 0xb4, 0x0b, 0x28, 0xc8, 0xa9, 0xeb, - 0x73, 0x0b, 0x46, 0x0e, 0x12, 0xd7, 0xe8, 0x4e, 0x8b, 0x64, 0x14, 0x91, 0x97, 0xc4, 0xb8, 0xf8, 0x75, 0x4c, 0x93, - 0xb8, 0x58, 0x4f, 0x73, 0x9f, 0x8a, 0xde, 0xb9, 0x0d, 0xfe, 0x71, 0xa3, 0x27, 0x5d, 0x27, 0x2c, 0x01, 0x58, 0x8f, - 0x94, 0x64, 0xc0, 0xa5, 0x9a, 0x9e, 0xfc, 0x3a, 0x48, 0x09, 0xbc, 0x72, 0xd0, 0x39, 0xc4, 0xf1, 0x85, 0x12, 0xd1, - 0xe0, 0xdf, 0xe4, 0xc8, 0x23, 0xf0, 0xeb, 0x67, 0xcc, 0x30, 0xcd, 0x12, 0xd8, 0x63, 0xe5, 0x99, 0x88, 0xf9, 0xab, - 0x46, 0xd2, 0x48, 0x58, 0xf1, 0xb4, 0xd5, 0xd2, 0x54, 0xf8, 0xd8, 0x08, 0x05, 0xc2, 0x1e, 0x80, 0xa6, 0x00, 0xde, - 0x1b, 0x12, 0xf3, 0xe5, 0xa9, 0xa6, 0x24, 0xe5, 0x29, 0x3a, 0x9b, 0xb3, 0x60, 0xfa, 0x2c, 0x2c, 0xa0, 0x9b, 0x63, - 0xca, 0xc3, 0x4d, 0x2c, 0xf3, 0x32, 0xcc, 0x94, 0xcc, 0xa8, 0x25, 0x98, 0x08, 0x93, 0xe1, 0x75, 0x72, 0x01, 0xcb, - 0x7b, 0x9b, 0x66, 0xc6, 0x2d, 0xa3, 0x57, 0xae, 0x4f, 0xa0, 0x79, 0xdc, 0x93, 0x65, 0x91, 0xa6, 0x0c, 0x57, 0x38, - 0x00, 0xe9, 0xaf, 0x98, 0xc7, 0xc2, 0x29, 0x35, 0x2b, 0xb9, 0x71, 0xc3, 0xc5, 0x42, 0x6a, 0x5c, 0xdd, 0x95, 0x77, - 0x22, 0x04, 0x48, 0x65, 0x4b, 0x27, 0x83, 0x67, 0x40, 0xf1, 0x9e, 0x00, 0x02, 0x11, 0x8d, 0xc2, 0x67, 0x7e, 0x92, - 0xa3, 0x55, 0x4e, 0x10, 0x0b, 0x73, 0x55, 0x3b, 0x2f, 0xde, 0x2a, 0x44, 0x94, 0x0b, 0x8e, 0x36, 0x00, 0x5b, 0xb4, - 0x2f, 0x72, 0x9f, 0x41, 0xc0, 0xb7, 0x8f, 0x33, 0xc3, 0x5c, 0x9a, 0x76, 0x48, 0x95, 0xcf, 0xc6, 0xe1, 0xe7, 0xb2, - 0xc0, 0x33, 0x4e, 0x99, 0xd8, 0xfd, 0x67, 0xab, 0xba, 0x21, 0xea, 0xfc, 0x35, 0x75, 0xc0, 0xa9, 0xb6, 0xd9, 0xd9, - 0x8d, 0x41, 0x97, 0xc5, 0xc9, 0x01, 0x93, 0xb2, 0xb3, 0x75, 0xb0, 0xa2, 0x1c, 0xff, 0x72, 0xf2, 0x03, 0x19, 0x0b, - 0x34, 0x5e, 0x15, 0x44, 0x45, 0x46, 0xa6, 0x03, 0x41, 0xbc, 0x34, 0x7c, 0x2e, 0x06, 0x68, 0x91, 0x79, 0x55, 0x52, - 0xa0, 0xd0, 0xac, 0x46, 0x94, 0x37, 0xd0, 0x20, 0x9b, 0xbb, 0x9a, 0x6a, 0x14, 0x1c, 0x21, 0x8f, 0x5a, 0x6c, 0x4c, - 0x8f, 0xc5, 0x52, 0x4c, 0xcb, 0xb4, 0x39, 0x45, 0x12, 0x81, 0xc5, 0x01, 0x71, 0xfd, 0x59, 0xa9, 0xb1, 0x41, 0x94, - 0x79, 0xde, 0x8c, 0x30, 0xe8, 0x6e, 0xe8, 0x49, 0x36, 0x31, 0xd6, 0x4a, 0x10, 0x39, 0x75, 0xd0, 0xd8, 0x8f, 0x5d, - 0x9f, 0xc8, 0xdb, 0x5d, 0x53, 0x4c, 0x75, 0xb9, 0x3f, 0x51, 0x4c, 0x0c, 0x2d, 0xed, 0xfa, 0x79, 0x06, 0x51, 0x3f, - 0x3d, 0x78, 0x9a, 0x72, 0xb6, 0xf6, 0x18, 0x1e, 0xaa, 0xce, 0x25, 0x79, 0xbf, 0xd4, 0x0d, 0x01, 0xf9, 0xb5, 0xc0, - 0xea, 0x91, 0x93, 0x88, 0x22, 0x10, 0xf6, 0xb3, 0xfe, 0x96, 0x30, 0xfa, 0x9b, 0x81, 0x25, 0xbb, 0x1e, 0x6c, 0x4b, - 0x5d, 0x62, 0x2c, 0x6b, 0x65, 0xcd, 0x29, 0x30, 0x5c, 0xba, 0x54, 0x4e, 0x1e, 0x48, 0x3c, 0x54, 0x0e, 0x16, 0xd3, - 0xe7, 0xe9, 0xc2, 0x01, 0x23, 0x85, 0xec, 0xfd, 0x34, 0xc8, 0x8b, 0xd3, 0x8b, 0x24, 0xb5, 0x18, 0x31, 0x76, 0xa9, - 0xb6, 0xb1, 0xf4, 0x08, 0xab, 0xb6, 0x36, 0xf0, 0xfc, 0xc4, 0x76, 0xbb, 0xdd, 0xb0, 0x53, 0x41, 0x56, 0x52, 0x27, - 0x72, 0x33, 0x8b, 0xce, 0x8f, 0x26, 0x91, 0xca, 0x13, 0x46, 0x01, 0x79, 0x39, 0x63, 0x5b, 0x20, 0x8b, 0x6e, 0x8a, - 0x5e, 0x18, 0xe3, 0xd6, 0xb3, 0x5c, 0x7d, 0xeb, 0x37, 0x38, 0x14, 0x92, 0x32, 0x35, 0xcd, 0x94, 0x7b, 0x9d, 0xcd, - 0x77, 0x55, 0x44, 0x8b, 0x72, 0xd6, 0x5c, 0x9b, 0x5f, 0x24, 0xab, 0xbd, 0x14, 0xd9, 0xd2, 0xe9, 0x30, 0x7b, 0x97, - 0x8a, 0xd4, 0x92, 0x04, 0xaa, 0x1d, 0xc7, 0x66, 0x1c, 0xe7, 0x18, 0xf4, 0x56, 0x30, 0xb3, 0x86, 0x97, 0x80, 0xec, - 0x22, 0x85, 0x45, 0x56, 0x5a, 0xbc, 0xd1, 0x2d, 0x25, 0xef, 0x07, 0x89, 0xca, 0xd2, 0xc3, 0x30, 0x93, 0xbe, 0x14, - 0xf6, 0x80, 0x14, 0x8f, 0x50, 0x45, 0x98, 0xbb, 0xdf, 0x45, 0x50, 0xa0, 0x3a, 0xc3, 0x13, 0x98, 0xf6, 0x7c, 0x94, - 0x8e, 0x0b, 0x98, 0x9f, 0xcd, 0x44, 0xbb, 0x7a, 0xb5, 0x06, 0x2c, 0xbc, 0xfa, 0x90, 0xe2, 0x3a, 0xa5, 0xb7, 0xf2, - 0x55, 0xf8, 0x1c, 0x2b, 0xcf, 0x02, 0x1d, 0x2b, 0x15, 0x86, 0xd9, 0x5c, 0x18, 0x23, 0x49, 0x9a, 0x0f, 0xe7, 0xde, - 0xa0, 0x9b, 0x21, 0x28, 0x11, 0x53, 0xdc, 0x10, 0x62, 0x31, 0xcc, 0x58, 0x03, 0xca, 0xdd, 0xa2, 0x99, 0x93, 0xac, - 0xb9, 0x93, 0x49, 0xce, 0x7c, 0xf7, 0x95, 0x5e, 0xa5, 0x94, 0x10, 0x4d, 0xc7, 0x57, 0x39, 0x59, 0x3e, 0x46, 0xc3, - 0x2c, 0xae, 0x1c, 0x13, 0xb4, 0x4e, 0xe2, 0x84, 0xa2, 0x70, 0x48, 0x50, 0x5b, 0x61, 0xba, 0x53, 0x23, 0x9c, 0x0a, - 0x7a, 0x3f, 0xe9, 0xe6, 0x0e, 0xba, 0x13, 0xdb, 0x50, 0xd1, 0x9a, 0x86, 0x0a, 0x62, 0xdb, 0xbf, 0xf7, 0x33, 0x3a, - 0x74, 0xfc, 0x56, 0x34, 0xa6, 0x42, 0xa0, 0x66, 0x0e, 0x97, 0xe7, 0xbe, 0x98, 0x14, 0xe2, 0x4a, 0x5a, 0x9e, 0x08, - 0x92, 0xb4, 0x8f, 0x8d, 0x79, 0xb1, 0xb7, 0x83, 0xc2, 0x34, 0xac, 0xcb, 0x06, 0x44, 0xad, 0x17, 0x2a, 0xf3, 0xeb, - 0xb6, 0x8c, 0x3b, 0x4d, 0x18, 0xaf, 0x9b, 0x81, 0x98, 0xd7, 0xa0, 0x8d, 0x18, 0x8c, 0x55, 0x3b, 0x0e, 0x40, 0x39, - 0x3a, 0x2d, 0x1b, 0xeb, 0x4b, 0xab, 0x46, 0x6f, 0x68, 0x0c, 0x6c, 0xd7, 0x62, 0x91, 0x04, 0xa4, 0x30, 0x66, 0xdd, - 0x8d, 0x49, 0xa7, 0x0a, 0xea, 0x81, 0xec, 0x59, 0x9f, 0x75, 0x3c, 0x4b, 0x4c, 0xf8, 0x25, 0x03, 0x47, 0xf3, 0xe9, - 0xa4, 0x97, 0xae, 0x89, 0x8e, 0x68, 0x6d, 0x21, 0xfe, 0xd4, 0xe0, 0xd6, 0xe2, 0xa5, 0x0e, 0x7c, 0x05, 0xa0, 0x16, - 0x99, 0x0a, 0x21, 0x51, 0x25, 0x15, 0x57, 0x65, 0x3c, 0xd8, 0x94, 0xeb, 0x2a, 0xac, 0x7c, 0x72, 0xef, 0x7a, 0x07, - 0x7f, 0xb6, 0x07, 0x4b, 0xeb, 0x0e, 0xf3, 0xc1, 0xc9, 0x5f, 0x45, 0x48, 0x11, 0xf6, 0xcc, 0xd0, 0xc1, 0xc6, 0x3c, - 0x73, 0xe4, 0xe3, 0xb5, 0x1d, 0xf1, 0xad, 0x0b, 0x6f, 0x98, 0xe4, 0xee, 0x3d, 0x72, 0x19, 0xda, 0x52, 0x40, 0xd4, - 0x6d, 0x6e, 0xfb, 0x83, 0x74, 0xfc, 0x49, 0x4a, 0xf1, 0xef, 0x5d, 0x05, 0x51, 0xbb, 0x68, 0x21, 0x79, 0xa7, 0xe7, - 0xc0, 0x1a, 0x8c, 0x26, 0x8d, 0x11, 0x4c, 0xef, 0x01, 0x97, 0x8a, 0xe2, 0xfc, 0xd1, 0x49, 0x98, 0x70, 0xe2, 0x19, - 0xe0, 0x2f, 0x8d, 0x49, 0xd8, 0x16, 0x01, 0x77, 0xbb, 0x18, 0xff, 0xa2, 0xdd, 0x84, 0x41, 0xde, 0x5d, 0xdf, 0x91, - 0x7e, 0xc4, 0x3d, 0x6c, 0x2e, 0xfb, 0x5b, 0x5e, 0x8a, 0x56, 0xa2, 0x8a, 0x10, 0xa6, 0x46, 0x42, 0x43, 0x9d, 0x23, - 0x81, 0x38, 0xa6, 0x89, 0x35, 0xcc, 0xf6, 0x93, 0xf5, 0x61, 0x97, 0x0a, 0xa1, 0x50, 0x04, 0xa2, 0x33, 0x84, 0x1b, - 0x75, 0x9e, 0x30, 0xc0, 0x3b, 0x04, 0xa0, 0x25, 0xe8, 0xc7, 0x10, 0x9f, 0x5b, 0x27, 0x84, 0xe6, 0x62, 0x9e, 0x3e, - 0x66, 0x0a, 0x4a, 0x52, 0x7d, 0x2d, 0x6f, 0xb3, 0xe6, 0x05, 0x67, 0x2a, 0x2e, 0xa0, 0x68, 0x2b, 0x9e, 0xfa, 0xef, - 0x98, 0x8a, 0x3e, 0x8a, 0x4e, 0x6d, 0xcc, 0x69, 0x9e, 0x30, 0xe7, 0x88, 0x7e, 0xa0, 0xee, 0xc6, 0xf5, 0x6e, 0xc3, - 0x9d, 0xca, 0x12, 0xca, 0x32, 0xf4, 0xba, 0x65, 0xba, 0x94, 0xe4, 0x70, 0x8e, 0xf3, 0xfc, 0x57, 0x0c, 0x71, 0xff, - 0x35, 0xc7, 0xa7, 0xf7, 0x59, 0xda, 0x65, 0x7e, 0xf4, 0xe0, 0xa5, 0x05, 0x66, 0x76, 0xc6, 0x6e, 0x1e, 0xf6, 0x58, - 0x47, 0x02, 0x3b, 0xe2, 0x18, 0xea, 0x1a, 0x67, 0xbc, 0xde, 0x8a, 0x78, 0xa0, 0xb6, 0x1e, 0x6c, 0xbc, 0xa7, 0x34, - 0x4c, 0xb7, 0xa4, 0x8b, 0xac, 0x6b, 0xa2, 0xb2, 0xdf, 0x1f, 0x22, 0xbb, 0xa7, 0xc7, 0x93, 0x3a, 0x69, 0x53, 0x54, - 0x2c, 0x81, 0xce, 0x8d, 0x43, 0xff, 0xe4, 0x2c, 0xcc, 0x63, 0xe8, 0x98, 0xc9, 0x38, 0x5b, 0x67, 0x8c, 0xe7, 0xf6, - 0x33, 0x89, 0xb4, 0x93, 0x81, 0xdf, 0x29, 0x92, 0x9f, 0x7f, 0x58, 0x80, 0x46, 0x14, 0x82, 0xda, 0xed, 0x07, 0x0a, - 0xc5, 0xb1, 0xef, 0x7f, 0x84, 0xb5, 0x7d, 0x8f, 0xd8, 0x85, 0x5d, 0x2c, 0x01, 0xc4, 0x6e, 0x6c, 0xec, 0xff, 0x75, - 0x77, 0xab, 0x91, 0x0d, 0xab, 0x0f, 0x24, 0xd4, 0x57, 0x7b, 0xe6, 0xd9, 0x35, 0xcf, 0x8d, 0x08, 0xce, 0x44, 0x47, - 0xa0, 0x5e, 0xb5, 0xb9, 0xfe, 0x9b, 0xa4, 0xbb, 0x88, 0x22, 0x08, 0x56, 0xd6, 0x20, 0x6b, 0x36, 0xb2, 0xa0, 0x54, - 0xdc, 0x91, 0x1b, 0x7b, 0xbc, 0xc7, 0xf7, 0x76, 0x12, 0x4d, 0x19, 0x25, 0xd7, 0xaa, 0x29, 0x27, 0x0e, 0x63, 0x77, - 0x6f, 0x3c, 0x6b, 0x35, 0x5e, 0x28, 0xfe, 0xa6, 0x06, 0x61, 0xc5, 0x8d, 0xe3, 0x66, 0x83, 0x70, 0xff, 0x6c, 0x51, - 0xa7, 0x6b, 0x91, 0xf1, 0xbc, 0x5a, 0xaf, 0x7d, 0xb6, 0x1b, 0xa9, 0x26, 0xb5, 0x27, 0x34, 0x37, 0x62, 0x9b, 0x77, - 0xdc, 0x6d, 0xc0, 0xe7, 0xc0, 0xc5, 0xd4, 0x91, 0x78, 0xef, 0x51, 0x2f, 0x59, 0xb3, 0xd7, 0x5b, 0x13, 0x1e, 0x1c, - 0x7a, 0x65, 0xb7, 0x7a, 0x22, 0x3e, 0x9f, 0x56, 0xff, 0x74, 0x7f, 0x27, 0x3f, 0xbb, 0x97, 0xb7, 0x6a, 0xca, 0x51, - 0xfa, 0xd4, 0xc4, 0x26, 0x7b, 0x3d, 0x6b, 0x1c, 0xde, 0x6a, 0xdc, 0xee, 0xa4, 0x1b, 0x4d, 0xfb, 0x2f, 0x97, 0x32, - 0x5b, 0xd0, 0x2c, 0x0f, 0x7e, 0x0e, 0x16, 0xdf, 0xb3, 0xd0, 0x7b, 0x15, 0x31, 0xa7, 0x6c, 0x70, 0x48, 0x55, 0x33, - 0xfd, 0x30, 0xde, 0x89, 0x26, 0x6e, 0x3d, 0xda, 0x25, 0xee, 0xa2, 0x46, 0x9c, 0xe4, 0x01, 0xd6, 0x5c, 0xef, 0x0a, - 0xa6, 0xd4, 0x2e, 0xff, 0x04, 0xd2, 0xe2, 0xa5, 0x09, 0x9b, 0xb4, 0xa9, 0xb5, 0x4d, 0x1b, 0xae, 0x02, 0xcb, 0x3f, - 0x16, 0xdb, 0x7c, 0x57, 0xf5, 0x9b, 0x6e, 0xae, 0xf2, 0xf5, 0xcf, 0xe0, 0xc7, 0x6a, 0xaf, 0xe5, 0xa7, 0xff, 0xe1, - 0xfb, 0xff, 0x6a, 0xdc, 0x09, 0x66, 0xbb, 0x39, 0x0b, 0xbe, 0x6a, 0x70, 0x91, 0x65, 0xc3, 0xe7, 0x49, 0xf9, 0xff, - 0xea, 0x7a, 0xf7, 0x8f, 0xab, 0x7f, 0xbf, 0x68, 0x06, 0xf3, 0x11, 0x57, 0x9e, 0x49, 0x5d, 0x9c, 0xfd, 0x37, 0xc4, - 0xd5, 0xd3, 0x7b, 0x1f, 0xb1, 0xc6, 0x15, 0xfb, 0xcd, 0x6e, 0xb2, 0x6c, 0x16, 0x55, 0x96, 0xf0, 0xd4, 0xab, 0x9a, - 0x5d, 0x41, 0x90, 0xcf, 0x7b, 0x9d, 0xcd, 0x47, 0x87, 0x8f, 0x35, 0xa6, 0x7d, 0xa6, 0xdc, 0xfb, 0xfc, 0xc2, 0xf3, - 0x8b, 0x59, 0x39, 0x9e, 0xf7, 0xbc, 0xf4, 0x6a, 0xae, 0xec, 0xc7, 0x9a, 0xe4, 0x4c, 0x67, 0x70, 0xfe, 0x59, 0x39, - 0xbf, 0xf8, 0x7c, 0x7f, 0x76, 0x5f, 0xbe, 0xcc, 0x50, 0xc3, 0x31, 0xcf, 0xac, 0xf9, 0x88, 0x77, 0xa2, 0x56, 0x67, - 0xf1, 0xad, 0xd9, 0xcd, 0xf1, 0x64, 0xc5, 0x11, 0xae, 0xd0, 0x63, 0x3b, 0xac, 0xfc, 0x5d, 0x4f, 0x0d, 0x71, 0xc1, - 0xd0, 0x04, 0x12, 0x0f, 0xfd, 0xdf, 0xc1, 0xd0, 0x0f, 0xbd, 0x97, 0x9f, 0x4d, 0x1a, 0x0e, 0x80, 0xb0, 0xab, 0x96, - 0xc2, 0x6b, 0xa5, 0x3a, 0x62, 0x1b, 0x75, 0x54, 0xf8, 0x40, 0x45, 0x3b, 0x47, 0xdf, 0x5b, 0xde, 0xeb, 0x77, 0xa1, - 0xf4, 0xe0, 0xfa, 0xe1, 0xf1, 0x6b, 0xb1, 0x2e, 0x03, 0xc8, 0x16, 0xc1, 0xe9, 0x86, 0x77, 0xdb, 0xdb, 0x86, 0xe1, - 0x14, 0xaa, 0x3a, 0x51, 0x59, 0x53, 0xeb, 0xcc, 0xbe, 0x8f, 0x16, 0xdd, 0x00, 0x3c, 0x1f, 0xef, 0x13, 0x42, 0xf6, - 0x2e, 0xd2, 0x73, 0xd2, 0x09, 0x23, 0x10, 0xd8, 0x22, 0x0a, 0x6c, 0x1a, 0xe4, 0x7d, 0x7c, 0x87, 0x6e, 0x48, 0xcb, - 0xcf, 0x68, 0xae, 0x3e, 0x77, 0x31, 0xa5, 0xec, 0xe1, 0x6a, 0x6e, 0xb5, 0x4f, 0x01, 0x24, 0xb1, 0x4d, 0x08, 0x58, - 0xfe, 0x93, 0xc7, 0x4d, 0xc3, 0xd6, 0x9b, 0x74, 0xe9, 0x85, 0xd4, 0x9d, 0x9a, 0x34, 0x65, 0x84, 0x91, 0xe9, 0x85, - 0xe7, 0x15, 0x9d, 0x70, 0x97, 0x63, 0xa2, 0x57, 0x8c, 0x8c, 0x59, 0x71, 0xa7, 0xde, 0xb6, 0xbc, 0xfe, 0x5c, 0x07, - 0x41, 0x48, 0x37, 0x36, 0xa4, 0xcb, 0xcc, 0xdd, 0x2b, 0xb8, 0x99, 0x11, 0xb0, 0x79, 0x09, 0x75, 0xc6, 0xef, 0x99, - 0x24, 0xd1, 0x9d, 0x35, 0x4d, 0x9c, 0xf1, 0xb7, 0xd5, 0x6c, 0xa1, 0x8a, 0xc4, 0x0b, 0x73, 0x03, 0x12, 0x84, 0xfa, - 0x86, 0x5a, 0x61, 0xd5, 0x37, 0x98, 0xb4, 0x1f, 0x38, 0x39, 0xcf, 0x34, 0x83, 0x4e, 0xe3, 0x7d, 0x1d, 0x33, 0x26, - 0xba, 0x9a, 0xa2, 0x50, 0x18, 0x6d, 0xe7, 0xcf, 0xe2, 0x66, 0x96, 0xf5, 0x60, 0x02, 0xf0, 0x36, 0x0f, 0xa0, 0x9f, - 0xd7, 0x0a, 0x66, 0xf2, 0x06, 0x3f, 0xfc, 0x12, 0x06, 0x64, 0x7c, 0xe8, 0x41, 0xce, 0xe6, 0x27, 0x05, 0xfd, 0xc7, - 0x20, 0x5e, 0x77, 0x96, 0xb3, 0x5b, 0x42, 0x6b, 0x29, 0xd6, 0x8a, 0x71, 0x96, 0x91, 0xeb, 0xd4, 0x6f, 0xea, 0x2a, - 0x99, 0xaf, 0xed, 0xea, 0x72, 0xf1, 0x6d, 0x4f, 0xee, 0x30, 0x38, 0x05, 0xbc, 0xa0, 0xa1, 0x20, 0x66, 0x2a, 0x3f, - 0xaf, 0xce, 0x6e, 0x28, 0xf5, 0x41, 0x32, 0x7d, 0xae, 0xf0, 0xaa, 0x1a, 0xff, 0x85, 0x45, 0x5f, 0x6a, 0x25, 0xf4, - 0x17, 0x60, 0xf8, 0xd0, 0xb6, 0xcd, 0x84, 0x67, 0x67, 0x0b, 0xf7, 0x34, 0xf9, 0x54, 0x73, 0xb7, 0xda, 0x88, 0x39, - 0xcf, 0x01, 0x81, 0xb4, 0x50, 0x6a, 0xfc, 0x89, 0xd3, 0x12, 0x24, 0xb9, 0xf1, 0xb3, 0x85, 0x32, 0x3a, 0xba, 0xe2, - 0x14, 0xa7, 0x8b, 0xd7, 0x82, 0x55, 0xd4, 0xfe, 0xb6, 0xa9, 0xe3, 0x8b, 0xef, 0xd2, 0xb1, 0x6d, 0xb9, 0x7f, 0x37, - 0x7d, 0xdb, 0xa0, 0x38, 0x13, 0x36, 0x06, 0x7f, 0xe9, 0xbe, 0x6d, 0x0e, 0x34, 0x7c, 0x88, 0x3e, 0x77, 0xaf, 0xfe, - 0xb8, 0x26, 0x5d, 0x81, 0x6e, 0x89, 0xa7, 0x67, 0x3a, 0x28, 0x9a, 0x87, 0x92, 0x8b, 0x17, 0x25, 0xb0, 0x56, 0x30, - 0x9a, 0xce, 0x78, 0x11, 0x9c, 0x14, 0xda, 0xe7, 0x0d, 0x93, 0x9f, 0x16, 0x5c, 0xfb, 0x51, 0x49, 0xef, 0x14, 0x6a, - 0x8c, 0xef, 0xaf, 0x9b, 0x6c, 0xbd, 0x6b, 0x5e, 0x4b, 0xaa, 0x28, 0x8c, 0x7e, 0x87, 0x01, 0xf2, 0xd5, 0x97, 0x25, - 0x32, 0xfa, 0xf6, 0x4e, 0xdd, 0x6a, 0xbe, 0x77, 0x39, 0xd3, 0x19, 0x81, 0x3f, 0xdf, 0x8c, 0x59, 0xd3, 0x74, 0x33, - 0x46, 0x36, 0x02, 0x73, 0x17, 0x10, 0xa5, 0x89, 0x34, 0x28, 0x2b, 0xc8, 0x77, 0x57, 0xc3, 0x56, 0xa9, 0xcd, 0xde, - 0x9f, 0xfd, 0xdf, 0x4f, 0x0b, 0xee, 0x91, 0xf4, 0xe2, 0x8f, 0x1e, 0xaf, 0x63, 0x21, 0xcd, 0xbd, 0x50, 0xe3, 0x67, - 0xed, 0x71, 0xca, 0x6d, 0x3c, 0x40, 0xb3, 0x86, 0x0e, 0x0d, 0xdb, 0x87, 0x74, 0x5c, 0x1c, 0x5f, 0x63, 0xe8, 0xfb, - 0x06, 0x52, 0xc2, 0xd4, 0xe4, 0x3d, 0xa5, 0x15, 0x75, 0x60, 0x04, 0x15, 0xe5, 0x85, 0x72, 0x62, 0xd6, 0x56, 0xf4, - 0x6e, 0xc3, 0xc4, 0xd9, 0xa0, 0xfe, 0x66, 0xcb, 0xcb, 0x1e, 0x7b, 0x1f, 0xf0, 0xf5, 0x4c, 0x01, 0xc7, 0x38, 0xa1, - 0x46, 0xb0, 0x1d, 0xa4, 0xc8, 0x22, 0xf0, 0x09, 0x33, 0x6a, 0x08, 0x65, 0xcd, 0xd4, 0x96, 0xf2, 0x24, 0x48, 0xaf, - 0x2b, 0x2b, 0x5d, 0xd8, 0xe5, 0xdb, 0x2a, 0xba, 0x39, 0xbd, 0x83, 0x3d, 0xf9, 0x5e, 0xf3, 0xde, 0x7a, 0xa9, 0xd4, - 0x6a, 0xda, 0x90, 0xb0, 0x90, 0xb5, 0xc0, 0xae, 0x5b, 0xe7, 0x47, 0xd7, 0x31, 0x66, 0xf1, 0x08, 0x3e, 0x23, 0xd8, - 0x0b, 0x72, 0x53, 0xe7, 0xd6, 0xce, 0x60, 0x61, 0x42, 0xbe, 0xcf, 0xcf, 0x12, 0xb0, 0xb4, 0x63, 0xd3, 0x74, 0x70, - 0x3e, 0xa4, 0xef, 0xa1, 0x77, 0x4b, 0x01, 0x59, 0x38, 0x35, 0x7b, 0x57, 0x8b, 0x02, 0x4f, 0x1c, 0x92, 0x1a, 0xd0, - 0xf7, 0xec, 0x75, 0xfc, 0x46, 0x9f, 0x58, 0x24, 0x52, 0xd3, 0xdb, 0xf8, 0x9b, 0x67, 0xdf, 0xe8, 0xab, 0x53, 0xcf, - 0x84, 0xaf, 0x3e, 0x94, 0x5a, 0xcd, 0x86, 0x06, 0xec, 0x30, 0xd3, 0xc6, 0xb9, 0x0e, 0x4a, 0x7d, 0x33, 0x61, 0x27, - 0xe4, 0x65, 0x71, 0xe3, 0x28, 0x0d, 0xc1, 0x40, 0x7a, 0x11, 0x8f, 0xa2, 0xfc, 0xbe, 0xea, 0xc9, 0xcc, 0xfa, 0x08, - 0x4f, 0x2f, 0x1f, 0xfe, 0xf1, 0xb5, 0x2a, 0xbe, 0xbc, 0xb7, 0x1b, 0xf9, 0xc9, 0x4e, 0x41, 0xe2, 0xd0, 0x54, 0xec, - 0x01, 0x4d, 0x0e, 0x1c, 0x02, 0x71, 0x43, 0x79, 0xec, 0xc3, 0xfe, 0x5c, 0xf3, 0x0d, 0x01, 0x35, 0x56, 0x12, 0x54, - 0x4b, 0x67, 0xfe, 0x72, 0x25, 0x17, 0x2e, 0xde, 0x5d, 0x3c, 0xb7, 0x28, 0x7b, 0xff, 0xf3, 0x96, 0xfe, 0xd1, 0x7e, - 0x6f, 0x28, 0xb7, 0x97, 0x33, 0xff, 0xef, 0x35, 0x85, 0x0b, 0x81, 0x07, 0x24, 0xa9, 0x85, 0xe4, 0x4a, 0x87, 0x8f, - 0xdf, 0x1c, 0xea, 0xbc, 0xc7, 0x74, 0x5f, 0x61, 0x56, 0x17, 0x44, 0xc1, 0xc7, 0x07, 0xa8, 0x6c, 0x03, 0xc5, 0x08, - 0xe1, 0x02, 0x46, 0x1f, 0xee, 0xeb, 0x46, 0x2d, 0x02, 0x69, 0x57, 0xae, 0xfe, 0x78, 0x61, 0xe0, 0x95, 0xc3, 0x6f, - 0x2d, 0xb9, 0x2f, 0x25, 0xbe, 0xd0, 0xd8, 0x9e, 0x5c, 0x4b, 0xe3, 0x89, 0x8c, 0x8a, 0x50, 0x55, 0x91, 0x7c, 0xce, - 0xbd, 0x5a, 0x7d, 0x31, 0x8c, 0x7c, 0x26, 0x30, 0xd7, 0x9b, 0x36, 0x76, 0x9c, 0x54, 0x97, 0xfc, 0xa7, 0x1e, 0x60, - 0x30, 0xd8, 0x97, 0x6d, 0xd3, 0xf4, 0x7e, 0xe7, 0xa4, 0xe1, 0x09, 0x92, 0xc0, 0x1a, 0x0c, 0x5c, 0x95, 0x24, 0x48, - 0x6f, 0xcc, 0x8a, 0x2e, 0x4d, 0xc9, 0x7b, 0xea, 0x29, 0xd9, 0x88, 0xe4, 0x21, 0xa0, 0x23, 0xc1, 0x45, 0xff, 0x51, - 0x6b, 0x23, 0x5c, 0x6b, 0xf9, 0x39, 0x9f, 0x6c, 0xe8, 0x74, 0xb3, 0x2b, 0xb2, 0xa3, 0x0f, 0xa3, 0x3c, 0x9c, 0x3b, - 0x19, 0xe6, 0x61, 0x24, 0xb0, 0x92, 0xb9, 0x79, 0xdc, 0x00, 0xf1, 0x4d, 0x96, 0x64, 0xb7, 0xe4, 0x7f, 0xfc, 0x29, - 0xaf, 0x23, 0xa4, 0x64, 0x5b, 0xdf, 0x55, 0x34, 0x3a, 0x85, 0x93, 0x5c, 0xa7, 0x65, 0x79, 0x21, 0x9c, 0x50, 0x20, - 0x6c, 0x69, 0xd4, 0x48, 0x7e, 0xff, 0xfe, 0xc7, 0x10, 0x2c, 0xfa, 0xf8, 0xa6, 0x99, 0x75, 0x5b, 0x81, 0x31, 0x82, - 0x46, 0x9d, 0x99, 0xdd, 0xe8, 0xf4, 0x26, 0x23, 0x11, 0x28, 0x49, 0x63, 0x8a, 0xb4, 0x87, 0xc3, 0xdd, 0xe6, 0xab, - 0x3f, 0xb2, 0x1d, 0x4b, 0xaa, 0xb6, 0x59, 0xa8, 0x2d, 0x40, 0x80, 0x51, 0xbf, 0x37, 0x10, 0x4d, 0x34, 0x05, 0x05, - 0x2b, 0x6f, 0xe8, 0xdc, 0x8e, 0x6e, 0xcd, 0x6e, 0x41, 0xfb, 0x55, 0xfd, 0x19, 0xa1, 0x83, 0xdb, 0x4a, 0x7a, 0x4e, - 0x4a, 0x55, 0xa4, 0x2e, 0x38, 0xa7, 0x20, 0xb1, 0xb5, 0x0d, 0xb4, 0x7d, 0x6a, 0x4c, 0xe4, 0xfd, 0x45, 0xc5, 0x55, - 0x44, 0x00, 0x02, 0x84, 0x97, 0xe5, 0x5d, 0xc2, 0x27, 0xa3, 0x04, 0x00, 0xd3, 0xe3, 0xd2, 0x4b, 0xc6, 0x52, 0xd1, - 0xf0, 0xb0, 0x55, 0x50, 0x6d, 0xbb, 0x40, 0xe5, 0x80, 0x0b, 0xac, 0xac, 0xc3, 0x3c, 0x13, 0x52, 0x35, 0x29, 0x2e, - 0xba, 0x99, 0x5d, 0xa4, 0x3c, 0xdd, 0xa7, 0xa9, 0x24, 0x6c, 0x5a, 0x7f, 0x67, 0x7c, 0x19, 0x87, 0x68, 0x96, 0xbe, - 0x38, 0x6e, 0x3c, 0x5a, 0xde, 0x8e, 0xa6, 0x03, 0xd3, 0xda, 0x79, 0x12, 0x01, 0xca, 0x4e, 0x95, 0x70, 0xf5, 0x3c, - 0x04, 0x45, 0xa8, 0xf1, 0x43, 0xb7, 0x41, 0xc1, 0x6f, 0xe4, 0xe7, 0xa7, 0x86, 0x02, 0x84, 0xf1, 0xd2, 0x01, 0x0f, - 0xdd, 0xe4, 0xc5, 0x96, 0xb2, 0x73, 0xc0, 0xd8, 0x1b, 0xd1, 0x0b, 0x48, 0x6b, 0x62, 0xea, 0x4e, 0x72, 0x14, 0x5d, - 0x9c, 0x53, 0x5e, 0xc5, 0x2d, 0xd3, 0x65, 0xe9, 0x63, 0xea, 0x9d, 0x08, 0x9f, 0x13, 0x2b, 0x84, 0xff, 0x1d, 0x91, - 0xc3, 0xac, 0x94, 0x69, 0x81, 0x11, 0x6b, 0x89, 0x17, 0x38, 0xdf, 0x09, 0xd1, 0x4c, 0xd5, 0x4c, 0x57, 0x84, 0x79, - 0xaa, 0xaf, 0xf5, 0x9e, 0x3c, 0xc9, 0x1e, 0xa8, 0xf2, 0x61, 0xaf, 0xbb, 0x24, 0x98, 0xd7, 0xb2, 0xa9, 0xb7, 0x61, - 0xa2, 0xb0, 0x0f, 0x16, 0xf2, 0xb8, 0x6a, 0x08, 0x38, 0x3d, 0xf5, 0xab, 0x6f, 0xf5, 0x61, 0xdd, 0xb4, 0x2b, 0x04, - 0x9f, 0x93, 0x44, 0x84, 0x9f, 0xdb, 0x25, 0xce, 0xca, 0xab, 0xeb, 0xec, 0xb3, 0x58, 0xad, 0x41, 0xe6, 0xe5, 0x29, - 0xd1, 0xb6, 0xff, 0xd9, 0x41, 0x79, 0xde, 0x4d, 0x12, 0x3c, 0x4c, 0x47, 0x14, 0x33, 0x71, 0x8e, 0xa4, 0x21, 0x13, - 0xcf, 0xf9, 0xe2, 0x8b, 0x1a, 0xbd, 0x9f, 0x13, 0x4a, 0xc7, 0xa4, 0xf9, 0x8d, 0x0a, 0xa1, 0x0b, 0x09, 0x1d, 0x3f, - 0x74, 0xf9, 0xba, 0xb0, 0x76, 0xf3, 0x89, 0x88, 0xf5, 0x1f, 0xdc, 0x88, 0xa2, 0xd2, 0x79, 0x2c, 0x96, 0x40, 0x32, - 0xc6, 0x4f, 0xf4, 0x1b, 0x33, 0x4f, 0xba, 0x7a, 0xf8, 0x0c, 0x1b, 0x0d, 0xc7, 0x41, 0x9c, 0x03, 0x9e, 0xbf, 0x0c, - 0x7b, 0x5b, 0x1f, 0x15, 0xbf, 0x7f, 0x7d, 0x40, 0x54, 0x6b, 0xb8, 0xa2, 0xf4, 0x67, 0x1c, 0xe2, 0x12, 0xc9, 0x40, - 0x8b, 0x19, 0x7e, 0x21, 0xd2, 0xea, 0x7f, 0x45, 0xce, 0x3d, 0x0e, 0xec, 0x84, 0xfc, 0x17, 0xb7, 0xbd, 0x07, 0x5d, - 0x15, 0x42, 0xde, 0x8e, 0xa8, 0x91, 0x22, 0x0e, 0xef, 0xee, 0xcd, 0xd7, 0xd6, 0x22, 0xe7, 0xc0, 0xac, 0xdd, 0x4d, - 0x99, 0x85, 0xbb, 0x48, 0x6d, 0x31, 0x6d, 0x9a, 0x6d, 0x82, 0x97, 0x61, 0x27, 0x9d, 0x2c, 0x3e, 0xb5, 0x81, 0x50, - 0x55, 0x04, 0x48, 0x25, 0x0b, 0xfd, 0x0b, 0x94, 0xae, 0x5a, 0x2c, 0x43, 0x4b, 0x25, 0xe7, 0xba, 0x12, 0x4b, 0x3f, - 0xa1, 0xc0, 0x20, 0xfd, 0xe2, 0x56, 0x69, 0x3a, 0x2b, 0xa4, 0x88, 0x44, 0x8f, 0xd7, 0x96, 0xdd, 0x5d, 0xa8, 0x3c, - 0x92, 0xee, 0x33, 0x39, 0xc0, 0xf5, 0x4e, 0xaa, 0x8e, 0x95, 0x04, 0xed, 0x40, 0xf7, 0x00, 0xa5, 0x7e, 0x6a, 0x3d, - 0x44, 0x5a, 0x21, 0xf0, 0x12, 0x6e, 0xcc, 0x90, 0x68, 0x1f, 0xa8, 0x87, 0xc4, 0x04, 0xa0, 0x29, 0x38, 0xc1, 0x96, - 0x42, 0xdb, 0xb9, 0x91, 0x5c, 0xa1, 0x80, 0x95, 0xb1, 0x46, 0x35, 0x66, 0x1e, 0x5a, 0x61, 0x22, 0x8e, 0xb3, 0xcd, - 0xc8, 0x43, 0x1c, 0xa9, 0x43, 0xb4, 0xfd, 0x42, 0xe2, 0xa0, 0xc5, 0x99, 0x33, 0x8d, 0x5c, 0x21, 0x1c, 0x9f, 0x82, - 0x34, 0x8c, 0x60, 0xc3, 0xf5, 0x51, 0x6d, 0xac, 0x32, 0x21, 0x72, 0xab, 0x6e, 0x24, 0xed, 0xd7, 0xf1, 0x3b, 0x97, - 0x58, 0xc9, 0xb2, 0xe2, 0x9b, 0xa6, 0xd4, 0x33, 0xe5, 0xd5, 0x67, 0x56, 0x26, 0xbd, 0xdc, 0x47, 0x79, 0xc4, 0x5b, - 0xb0, 0xb8, 0x29, 0xf9, 0x21, 0xa6, 0xa0, 0x06, 0xf0, 0x68, 0x5c, 0x3b, 0x5c, 0x41, 0xb1, 0x18, 0x18, 0x69, 0x3a, - 0xad, 0x1c, 0xf3, 0xa5, 0x9a, 0x0d, 0x0c, 0xf3, 0x18, 0x4f, 0x2c, 0x74, 0x62, 0x7f, 0xcd, 0xf3, 0xb9, 0x45, 0x23, - 0x4f, 0xd3, 0x06, 0x59, 0x7e, 0x9b, 0xd6, 0x6b, 0x95, 0xe3, 0xf1, 0xb6, 0x02, 0x88, 0xdf, 0x41, 0x59, 0x50, 0x0c, - 0x15, 0x4d, 0x8a, 0x19, 0x0c, 0x97, 0xc6, 0x0b, 0x32, 0x01, 0xba, 0x0c, 0x33, 0x6b, 0x8b, 0xaa, 0xbc, 0x3d, 0x16, - 0xc3, 0x7d, 0x50, 0xaa, 0x48, 0x7e, 0xa5, 0x9a, 0x2d, 0x8f, 0x2a, 0xfc, 0xc7, 0x50, 0x1d, 0x43, 0xa4, 0x9d, 0xfc, - 0xab, 0xa3, 0x46, 0xc7, 0x7d, 0x71, 0xc8, 0x8e, 0x3d, 0x3f, 0x63, 0x20, 0x42, 0x4e, 0xba, 0x15, 0x6e, 0xf1, 0x49, - 0x7a, 0xd4, 0x08, 0xf4, 0x15, 0x04, 0x57, 0x6b, 0xde, 0x9d, 0x51, 0x61, 0xab, 0x51, 0x8e, 0x82, 0x32, 0x0c, 0x51, - 0x0d, 0x4f, 0xd1, 0x38, 0xf0, 0xb2, 0xc0, 0x01, 0x13, 0x01, 0x28, 0xe1, 0xb9, 0x24, 0xba, 0xe8, 0x7f, 0x4b, 0x73, - 0xf4, 0x86, 0x15, 0xec, 0xc8, 0x7c, 0xe9, 0x40, 0x8a, 0x80, 0x90, 0x4a, 0xb9, 0xaa, 0x7f, 0x30, 0x10, 0x8e, 0x87, - 0x91, 0xc1, 0xe4, 0x67, 0xc8, 0x87, 0xf2, 0x66, 0x86, 0x97, 0x47, 0x6e, 0x20, 0x4d, 0x4c, 0xa9, 0xc7, 0xb4, 0x46, - 0x6a, 0xb7, 0xdb, 0xc1, 0x55, 0x2a, 0xdd, 0xa0, 0xc6, 0x17, 0x45, 0x30, 0xfa, 0x97, 0x1b, 0x08, 0x3f, 0xfc, 0x2f, - 0x6e, 0x4b, 0xb0, 0x29, 0x7a, 0x8b, 0x03, 0x90, 0xf6, 0x6d, 0xa9, 0xba, 0x1e, 0x20, 0xc6, 0x96, 0x05, 0xfc, 0xe7, - 0xe0, 0x14, 0x11, 0x4b, 0x67, 0x2c, 0x66, 0xab, 0x53, 0x18, 0x72, 0xff, 0x8b, 0xa1, 0x23, 0x08, 0xfb, 0xd7, 0x19, - 0x76, 0x0c, 0x33, 0x40, 0x26, 0x7b, 0x90, 0x8a, 0x38, 0x52, 0x4c, 0x63, 0x1e, 0xad, 0x05, 0x8e, 0x14, 0x69, 0xf1, - 0x3e, 0x2a, 0x15, 0xdd, 0x97, 0x3c, 0x70, 0x40, 0x55, 0x0e, 0xe1, 0xb7, 0x16, 0x7d, 0x2b, 0x21, 0xf3, 0xba, 0xc9, - 0x02, 0x50, 0x17, 0x63, 0x31, 0xd6, 0x13, 0x92, 0x91, 0x9f, 0xb4, 0xa3, 0xc7, 0x68, 0x68, 0xf2, 0xf1, 0xa9, 0xee, - 0xb8, 0xe9, 0x9e, 0xbf, 0x51, 0x43, 0xb1, 0x7f, 0x2f, 0x13, 0x7d, 0x23, 0x8b, 0x64, 0xef, 0xec, 0xb3, 0xd9, 0x19, - 0xe6, 0xa6, 0xa7, 0xc6, 0x48, 0x37, 0xab, 0x3b, 0x9b, 0x2d, 0x53, 0x3b, 0x72, 0x07, 0x34, 0x67, 0x7c, 0x9d, 0xde, - 0x40, 0x1c, 0xef, 0x85, 0xc4, 0xcd, 0x74, 0xc4, 0x94, 0x7e, 0xdc, 0x88, 0x80, 0x1a, 0x45, 0x07, 0x1b, 0x99, 0xf6, - 0x6f, 0x81, 0x9c, 0x4d, 0xd0, 0x41, 0x15, 0x54, 0x5b, 0xcc, 0x4c, 0x0b, 0x39, 0x34, 0xd2, 0x82, 0x82, 0x95, 0xc6, - 0x60, 0xb0, 0x52, 0x95, 0x64, 0x2f, 0x4a, 0x2c, 0x3d, 0xcb, 0x59, 0xe8, 0x50, 0x36, 0x1d, 0x3c, 0x5f, 0x0a, 0x97, - 0x44, 0xbc, 0xac, 0x85, 0x61, 0xda, 0x6c, 0xa5, 0xa5, 0x65, 0x45, 0x25, 0xec, 0xe4, 0xfa, 0xbc, 0x94, 0x85, 0x79, - 0xa2, 0xb6, 0xf1, 0x8c, 0xdc, 0xcc, 0x50, 0xbe, 0x52, 0xfd, 0x30, 0xbd, 0x5f, 0xf8, 0x77, 0x90, 0x40, 0x9f, 0x22, - 0x60, 0x05, 0x5d, 0x12, 0x6c, 0xa4, 0xf4, 0xcf, 0x17, 0x97, 0x35, 0x0a, 0x7f, 0x7a, 0x01, 0xaf, 0xd2, 0xbd, 0x6e, - 0x87, 0xa1, 0xc8, 0xd7, 0x9e, 0x7c, 0x35, 0x9d, 0xfc, 0x91, 0xc2, 0xe1, 0xba, 0x92, 0x9e, 0x4b, 0x6f, 0x16, 0xf4, - 0x73, 0xeb, 0xd5, 0x57, 0xea, 0x2d, 0x54, 0x4f, 0x93, 0x88, 0xdd, 0x2d, 0xbd, 0x8f, 0x9e, 0x8d, 0x42, 0x68, 0x56, - 0xde, 0x7c, 0xff, 0x90, 0xb4, 0x4c, 0xd4, 0x2a, 0x17, 0x77, 0xb3, 0x81, 0xd0, 0xd6, 0x38, 0x47, 0xd8, 0xbb, 0x71, - 0xee, 0x5f, 0x5a, 0x92, 0x00, 0x55, 0x4c, 0x28, 0xbe, 0xa3, 0xd3, 0x40, 0xee, 0x83, 0x3b, 0x3a, 0x7e, 0xbb, 0xf3, - 0xb5, 0x9a, 0x06, 0xf6, 0x08, 0x53, 0x0f, 0xa2, 0xbf, 0xc1, 0xaa, 0x97, 0x5e, 0x2f, 0x17, 0xd8, 0x9c, 0x97, 0x3c, - 0xb0, 0x54, 0x90, 0x95, 0x57, 0xee, 0xc0, 0xa4, 0xf6, 0x08, 0x02, 0xe8, 0x2f, 0x1b, 0x37, 0xf7, 0x77, 0x22, 0x15, - 0xc1, 0x5d, 0x76, 0x9c, 0x8c, 0xd6, 0xf4, 0x3b, 0x3b, 0x8e, 0x05, 0x63, 0xa7, 0x97, 0x09, 0xab, 0x30, 0xd0, 0x8a, - 0xa3, 0xf5, 0x55, 0xf2, 0x8f, 0x2a, 0xc3, 0xac, 0x15, 0x05, 0xec, 0xfd, 0x52, 0x85, 0xf5, 0x41, 0x29, 0xaa, 0x8b, - 0x78, 0x42, 0xc7, 0x93, 0x66, 0xc3, 0x01, 0x8b, 0xa1, 0x45, 0x8c, 0x2d, 0xf6, 0x48, 0x87, 0xcd, 0x38, 0xa9, 0x77, - 0x7c, 0x56, 0xe1, 0xbc, 0x71, 0x1c, 0xb7, 0xc1, 0x6b, 0x8d, 0xca, 0xf2, 0x05, 0x6e, 0xe0, 0x17, 0xaf, 0x54, 0x8f, - 0x7f, 0xf8, 0xf6, 0xba, 0xb8, 0xa8, 0x3a, 0x0c, 0x6d, 0xf1, 0xa7, 0x0d, 0x69, 0x4c, 0x1a, 0xf6, 0x70, 0xfd, 0x4a, - 0x9a, 0x7c, 0xc1, 0xa8, 0xef, 0x90, 0x8d, 0xd9, 0xba, 0x5f, 0x00, 0x8f, 0x79, 0xef, 0x7a, 0xa9, 0x5f, 0x4a, 0x52, - 0x35, 0xa2, 0x15, 0x35, 0xf1, 0xcd, 0x1a, 0x37, 0xc9, 0x5a, 0x90, 0x84, 0xb6, 0x47, 0xed, 0x88, 0x0f, 0xf1, 0xfb, - 0xb7, 0x29, 0x54, 0x81, 0x78, 0x6f, 0x76, 0x5d, 0x06, 0xbb, 0xd5, 0xb3, 0x94, 0x84, 0x95, 0x1b, 0x30, 0x35, 0xd5, - 0xd2, 0x6c, 0x58, 0x85, 0x7c, 0x0e, 0x4c, 0xd2, 0x9a, 0x74, 0x4e, 0x69, 0x21, 0xd4, 0x32, 0xec, 0x9f, 0x92, 0x45, - 0xc4, 0xc7, 0x32, 0xf8, 0xbc, 0x90, 0x53, 0x77, 0xd0, 0x88, 0x2c, 0x46, 0xad, 0xdc, 0x82, 0xdd, 0x8e, 0xd6, 0x3e, - 0x55, 0x09, 0x88, 0xf5, 0xbb, 0x66, 0xe3, 0x6c, 0x14, 0xd8, 0x43, 0xe8, 0x07, 0xdf, 0xf1, 0x36, 0xcb, 0x5d, 0x60, - 0x4a, 0x79, 0xa4, 0xda, 0x52, 0xfa, 0x8c, 0x17, 0x3f, 0xf2, 0x1e, 0x5a, 0xca, 0xdd, 0x7d, 0xc5, 0x1f, 0x3f, 0x5d, - 0xe7, 0xb5, 0x98, 0x4e, 0xe2, 0x5c, 0x9a, 0x63, 0x49, 0xd9, 0x23, 0xc7, 0x71, 0x71, 0xf7, 0x29, 0x14, 0x9a, 0x51, - 0x11, 0x86, 0x34, 0x12, 0x94, 0x9f, 0x29, 0xae, 0xb8, 0xf6, 0x09, 0xad, 0x25, 0x02, 0x64, 0xf0, 0xfd, 0xa3, 0x4c, - 0x57, 0xee, 0xf3, 0x00, 0x7f, 0xb7, 0x68, 0x95, 0xb0, 0x66, 0x51, 0x84, 0x6d, 0x02, 0x92, 0xf5, 0xdd, 0x61, 0x87, - 0xec, 0xec, 0x86, 0x08, 0x02, 0x75, 0xd7, 0x21, 0x40, 0x18, 0xaf, 0x11, 0xca, 0xe5, 0x5f, 0x2b, 0xe3, 0x76, 0x25, - 0x13, 0xea, 0x30, 0xca, 0x2e, 0x28, 0xf0, 0xde, 0x8b, 0x7e, 0xe9, 0x6d, 0x95, 0x1b, 0x5a, 0x4e, 0xd6, 0x47, 0x2f, - 0x3f, 0x29, 0xbb, 0x24, 0x7f, 0xc8, 0x68, 0x01, 0x48, 0xd9, 0x98, 0x66, 0xe3, 0x98, 0xae, 0x5a, 0xb7, 0xcc, 0x47, - 0xd9, 0x06, 0xc3, 0x76, 0x88, 0x51, 0x3c, 0x68, 0xd5, 0x90, 0x5c, 0xb1, 0x69, 0x8f, 0x7b, 0xe9, 0xc1, 0x6d, 0xf7, - 0x7e, 0x38, 0x38, 0x17, 0xf2, 0x88, 0xd9, 0x4b, 0x98, 0x8f, 0x1a, 0xbb, 0x42, 0xa6, 0x19, 0x0e, 0xe2, 0x20, 0x07, - 0xd9, 0x76, 0xdd, 0x05, 0x53, 0x8e, 0x69, 0x71, 0xbb, 0xc5, 0x46, 0x36, 0x90, 0x11, 0x5a, 0xb0, 0xc9, 0xf8, 0x50, - 0x2c, 0xd3, 0xa1, 0x74, 0xdf, 0x63, 0x02, 0xc6, 0x5a, 0x0f, 0x13, 0xbf, 0x66, 0x1d, 0xa2, 0x4b, 0x16, 0xa4, 0xa9, - 0xd1, 0xe3, 0x9b, 0x3e, 0xa5, 0x5b, 0x66, 0x43, 0xc3, 0xf7, 0x3a, 0xcc, 0x1a, 0x0c, 0x2b, 0xf6, 0x89, 0xb2, 0x57, - 0xf5, 0xc7, 0xdb, 0x71, 0x50, 0x4b, 0x39, 0x73, 0x79, 0x9b, 0xd1, 0xbf, 0x99, 0xc3, 0x40, 0xe3, 0x85, 0xc2, 0x7b, - 0x39, 0x81, 0x9a, 0x96, 0x34, 0x29, 0x78, 0xbb, 0xbc, 0x5a, 0x6d, 0xc2, 0xb8, 0x7f, 0xf7, 0xa1, 0x54, 0x5c, 0xff, - 0xee, 0x7d, 0xdd, 0x55, 0xbd, 0x2f, 0x6f, 0x94, 0x4b, 0x3a, 0xaf, 0xd6, 0x57, 0x10, 0xa0, 0xd2, 0x5b, 0x99, 0xb2, - 0x21, 0xdb, 0x83, 0xd7, 0x75, 0xbd, 0x77, 0x55, 0x7e, 0xdc, 0x81, 0xdd, 0x6d, 0x72, 0x16, 0x6b, 0x0b, 0xea, 0xa9, - 0xd3, 0xb8, 0x7b, 0x29, 0xe5, 0x86, 0x83, 0x53, 0x8a, 0xba, 0xc5, 0x37, 0xbc, 0x3f, 0x67, 0xd7, 0xa9, 0x4b, 0xbd, - 0xd5, 0x6f, 0xd7, 0xbf, 0xf2, 0xd4, 0x58, 0xe5, 0xa0, 0x86, 0xf5, 0xab, 0xf6, 0x35, 0x99, 0x5d, 0x83, 0x99, 0x31, - 0x48, 0xe1, 0x72, 0xae, 0x3e, 0x1b, 0x1c, 0x85, 0x79, 0x4e, 0xa8, 0x60, 0x0b, 0x42, 0xfd, 0xf8, 0x25, 0x31, 0x95, - 0xcc, 0x3f, 0x1c, 0x57, 0x46, 0x3f, 0x08, 0x7d, 0xbb, 0x6a, 0xbd, 0x0c, 0x75, 0x4e, 0x91, 0x8f, 0xb9, 0x9a, 0xe0, - 0x97, 0xd4, 0xc1, 0xd1, 0x2c, 0xfc, 0x53, 0x1d, 0xb6, 0x3b, 0x9c, 0x8f, 0x1e, 0x68, 0x5c, 0xed, 0x1b, 0xf0, 0x46, - 0xb4, 0xb3, 0xb0, 0xe3, 0xdd, 0xa7, 0x69, 0xac, 0xc3, 0xe1, 0xcc, 0xb0, 0xa4, 0x8c, 0x38, 0x0c, 0x98, 0x87, 0x6e, - 0xc9, 0x76, 0xb9, 0x6e, 0x93, 0x83, 0x94, 0xf5, 0x1e, 0x4a, 0x31, 0x8f, 0xe6, 0xb9, 0x69, 0xef, 0x79, 0x2f, 0xba, - 0xc2, 0x70, 0x79, 0x30, 0x32, 0x1f, 0xb3, 0x42, 0xaa, 0xae, 0x53, 0xd7, 0x71, 0xa6, 0x35, 0x46, 0xe4, 0x23, 0xc6, - 0xcd, 0xf7, 0x96, 0xb0, 0x68, 0x57, 0xb7, 0x2b, 0x88, 0x33, 0xac, 0xfc, 0x5f, 0x19, 0x9b, 0xa9, 0xa7, 0x0b, 0xb6, - 0xa7, 0x16, 0xfc, 0x79, 0x93, 0xb2, 0xa2, 0x82, 0x1b, 0x1d, 0x41, 0xa9, 0x7f, 0x7c, 0x5e, 0xd4, 0xaa, 0x66, 0x64, - 0xcd, 0x6f, 0x89, 0x77, 0xc6, 0x78, 0x5d, 0xd7, 0x15, 0xb2, 0xdf, 0xc5, 0xa9, 0xd1, 0x87, 0x26, 0x35, 0x8a, 0x64, - 0xfd, 0xa5, 0x68, 0x0e, 0x0c, 0x61, 0x84, 0xc6, 0x9b, 0xb5, 0xce, 0xc9, 0xe0, 0x24, 0xce, 0xaf, 0x3a, 0xb0, 0xde, - 0xce, 0xb1, 0xbd, 0x82, 0x41, 0x10, 0xf8, 0x57, 0x11, 0xa3, 0x55, 0xfd, 0xbc, 0x33, 0x33, 0x54, 0xf5, 0x72, 0x9a, - 0xac, 0x6c, 0xfe, 0x18, 0x53, 0x0d, 0xca, 0x4b, 0xd9, 0x55, 0xf6, 0x89, 0x8c, 0xfa, 0xb1, 0xa0, 0x1e, 0x5d, 0x9e, - 0x33, 0x94, 0xb7, 0x60, 0xcf, 0x52, 0x6f, 0x06, 0x08, 0x91, 0xb6, 0xab, 0x61, 0xc2, 0x31, 0xcc, 0xe9, 0xc8, 0x8a, - 0x55, 0x99, 0xc0, 0x47, 0x11, 0x5f, 0x34, 0xa7, 0x05, 0xce, 0xac, 0x2e, 0x3b, 0xbc, 0x15, 0xa2, 0xa2, 0xb8, 0xe3, - 0x7e, 0x42, 0x6b, 0x3e, 0x0e, 0x33, 0x31, 0x5e, 0xb3, 0x78, 0xde, 0xfd, 0x05, 0x04, 0x4d, 0x9d, 0xd0, 0x60, 0xe1, - 0xdd, 0x0f, 0x05, 0x44, 0xc9, 0x6b, 0x2b, 0x72, 0x92, 0xe1, 0xb7, 0x02, 0xc9, 0x74, 0x84, 0xd0, 0xc2, 0x25, 0x70, - 0xb3, 0xfd, 0x74, 0xdc, 0x05, 0xc7, 0x48, 0x91, 0x58, 0x38, 0x9e, 0x26, 0x6c, 0x3e, 0xb1, 0x26, 0x96, 0xe3, 0xa4, - 0x43, 0xe9, 0x2a, 0x34, 0xd5, 0x2a, 0x06, 0xad, 0xab, 0xfa, 0xc9, 0xde, 0x29, 0x88, 0xdb, 0x96, 0x20, 0xa2, 0x26, - 0xc7, 0x37, 0x1d, 0xb4, 0x3d, 0xb1, 0xc8, 0x1a, 0x65, 0x14, 0xbe, 0xf3, 0x08, 0x65, 0x8c, 0xc0, 0x7d, 0x95, 0x1a, - 0x63, 0x43, 0x59, 0x66, 0x7f, 0x30, 0x7d, 0x33, 0xc1, 0x44, 0x2f, 0xa1, 0xcc, 0x68, 0x95, 0x9c, 0x20, 0xfa, 0x34, - 0x97, 0x72, 0x3c, 0x22, 0xfa, 0x86, 0x85, 0xbf, 0xc4, 0xe2, 0x2a, 0xe6, 0xdd, 0xe5, 0xed, 0x74, 0x6d, 0x91, 0xcf, - 0xd4, 0x16, 0x63, 0x97, 0xcc, 0xa1, 0xf6, 0xb0, 0x21, 0x3b, 0xf1, 0x86, 0x9d, 0x16, 0xa5, 0x7c, 0x3b, 0x4a, 0x11, - 0xf6, 0x5d, 0xd1, 0xbf, 0x5d, 0x6f, 0x0a, 0x73, 0xed, 0x8a, 0xc9, 0xdf, 0xea, 0xeb, 0x19, 0x5a, 0x4f, 0x7c, 0x35, - 0x74, 0x73, 0x58, 0xf3, 0xc7, 0x02, 0xdf, 0x22, 0x2c, 0xb7, 0xb7, 0xd1, 0xc4, 0xb6, 0xce, 0x4b, 0x4f, 0x60, 0xb0, - 0x10, 0x7e, 0x37, 0x4b, 0xf1, 0x80, 0xd5, 0x83, 0xe8, 0x83, 0x02, 0x13, 0x53, 0xb9, 0x7a, 0xb5, 0x62, 0x8f, 0xd0, - 0x1e, 0xc6, 0x3a, 0x91, 0x5a, 0xf9, 0x36, 0xb8, 0x5a, 0xe1, 0x95, 0xbe, 0xde, 0x14, 0xb1, 0x5e, 0x79, 0x58, 0xdb, - 0xea, 0x97, 0xdc, 0xc2, 0xe5, 0xdf, 0xb6, 0x2a, 0x02, 0x7c, 0xc2, 0x55, 0x88, 0x23, 0xd0, 0x77, 0x69, 0x15, 0x05, - 0xf5, 0x97, 0x1c, 0x72, 0xea, 0xfc, 0x88, 0x70, 0x3e, 0x5f, 0x57, 0xf5, 0x1c, 0x47, 0x78, 0xab, 0xfc, 0x0f, 0x96, - 0x26, 0x6f, 0xe2, 0x7a, 0xb4, 0xe7, 0x25, 0x1d, 0x3e, 0xc1, 0xa5, 0x3b, 0x0a, 0x23, 0xbc, 0x94, 0x31, 0x8d, 0x17, - 0xe7, 0x1a, 0x30, 0x7b, 0x83, 0xe4, 0xf5, 0x38, 0x10, 0x95, 0x1c, 0x87, 0x2d, 0x16, 0xb5, 0x9e, 0x14, 0x1a, 0x91, - 0x37, 0xac, 0xca, 0x50, 0x44, 0x4b, 0x62, 0x07, 0x88, 0xfc, 0x58, 0x14, 0x86, 0x0e, 0xd5, 0x22, 0xb4, 0x6b, 0x7c, - 0xbf, 0xa9, 0x8f, 0xd0, 0x12, 0xab, 0x89, 0xf0, 0x61, 0x41, 0xde, 0x03, 0x0c, 0x73, 0x98, 0x24, 0xad, 0xa3, 0x74, - 0x90, 0xe3, 0x2b, 0x41, 0x32, 0x39, 0x30, 0x93, 0xde, 0x41, 0x6c, 0xe7, 0x7c, 0x31, 0x79, 0xbf, 0x11, 0x3f, 0x85, - 0x34, 0x74, 0x95, 0xbd, 0xc6, 0x22, 0xfb, 0x60, 0x82, 0xb5, 0x2f, 0x0f, 0x97, 0x99, 0xd7, 0xe0, 0x27, 0xfc, 0xff, - 0x34, 0x4b, 0x0a, 0xba, 0x0b, 0xb8, 0x98, 0xbd, 0x0f, 0xc3, 0x04, 0x3e, 0x19, 0x4d, 0x54, 0x96, 0xe8, 0x85, 0x05, - 0x4a, 0xd9, 0xef, 0xb7, 0xd0, 0xe0, 0x10, 0xcc, 0x4b, 0xde, 0xf9, 0xaa, 0x5b, 0x29, 0xaf, 0xef, 0xe4, 0xc8, 0xe4, - 0xf3, 0x29, 0xda, 0x1a, 0xb6, 0x56, 0xc0, 0x4b, 0x08, 0x03, 0x41, 0x34, 0xa4, 0xb8, 0xa4, 0xc3, 0x15, 0xc8, 0x1a, - 0xb9, 0x63, 0xd1, 0x4a, 0x19, 0x4e, 0x1b, 0x37, 0x13, 0xb5, 0xfb, 0xb4, 0x10, 0xc3, 0x79, 0x49, 0x87, 0xb1, 0xa4, - 0x0f, 0x4c, 0xb8, 0xc1, 0xb2, 0xad, 0x0a, 0xec, 0x80, 0xe6, 0x79, 0xd1, 0x68, 0x95, 0x9a, 0x0c, 0xa9, 0xa4, 0x93, - 0xf0, 0x11, 0xaf, 0x1d, 0x29, 0x19, 0xeb, 0x44, 0x4e, 0x13, 0x86, 0xb0, 0xfd, 0xd0, 0x48, 0xd4, 0x41, 0x61, 0x4d, - 0x21, 0x38, 0x2f, 0x34, 0xe0, 0xa6, 0x8d, 0xee, 0x07, 0xa8, 0xba, 0xd0, 0x48, 0xb3, 0xd2, 0x16, 0xb9, 0x6e, 0x2c, - 0x0e, 0xca, 0x8f, 0x78, 0x6d, 0x5e, 0x67, 0x55, 0x61, 0x23, 0x91, 0x7b, 0x28, 0x86, 0xb0, 0x19, 0xd3, 0x1f, 0xae, - 0xdc, 0xe3, 0x12, 0xeb, 0xb8, 0xc7, 0x80, 0x2d, 0xaf, 0x90, 0xc6, 0xec, 0x55, 0x72, 0x60, 0x21, 0x03, 0x34, 0xaf, - 0xc4, 0xf0, 0xbe, 0xf5, 0xcb, 0xa1, 0xf1, 0xad, 0x5a, 0x99, 0x4b, 0xcf, 0x84, 0x89, 0x11, 0x1e, 0x08, 0x83, 0x5f, - 0xab, 0x3f, 0x9d, 0xf6, 0xb2, 0x4e, 0x71, 0xbf, 0xca, 0x21, 0x37, 0x27, 0x2c, 0x1a, 0xe8, 0xa0, 0x4c, 0x4e, 0x17, - 0x39, 0x07, 0xf5, 0xcd, 0xdd, 0x82, 0xbc, 0x40, 0x1c, 0x6b, 0x3c, 0x8e, 0x5c, 0xf7, 0x62, 0xde, 0x66, 0x22, 0xd8, - 0x9b, 0x0a, 0xfe, 0x39, 0xc4, 0x29, 0x21, 0x80, 0x35, 0x48, 0x6c, 0xd6, 0xe5, 0x1e, 0xdb, 0xcb, 0xd8, 0xae, 0x13, - 0x99, 0xa2, 0xb2, 0x82, 0xe4, 0xe7, 0x11, 0x76, 0x81, 0x1a, 0x0f, 0x36, 0x49, 0x0f, 0xb2, 0x32, 0x0d, 0x23, 0x96, - 0x6f, 0x57, 0xc5, 0x29, 0xcc, 0x6b, 0xb5, 0x0e, 0x85, 0x20, 0x99, 0xd9, 0x6d, 0x23, 0x9f, 0x33, 0x4f, 0xc2, 0xa0, - 0x63, 0x47, 0x69, 0x83, 0x0a, 0xe5, 0xd8, 0x56, 0xf3, 0x68, 0x82, 0x5e, 0xf6, 0xd6, 0x39, 0x24, 0x73, 0x5b, 0x4e, - 0x0b, 0x56, 0x04, 0x24, 0x1e, 0xd7, 0xe2, 0xa3, 0xa9, 0xbb, 0xa1, 0xce, 0x11, 0x16, 0x39, 0x30, 0xcb, 0x96, 0x89, - 0xa8, 0xc5, 0xa5, 0x67, 0x6e, 0x1a, 0x6c, 0x2a, 0xcb, 0x4c, 0x7a, 0x11, 0xb2, 0x68, 0xa5, 0x89, 0x2d, 0xcc, 0xc5, - 0x38, 0x33, 0x07, 0x96, 0xf6, 0x11, 0x1a, 0x06, 0xcb, 0x48, 0x48, 0x63, 0x4b, 0x96, 0xb7, 0xc8, 0xa9, 0xc0, 0xd1, - 0xfe, 0x67, 0x96, 0x3b, 0x62, 0x2b, 0xf7, 0xd0, 0x82, 0xef, 0xf7, 0x57, 0x51, 0xc3, 0xd0, 0xf6, 0x57, 0xfe, 0xbd, - 0xe4, 0x22, 0xa8, 0x57, 0x90, 0x0f, 0x49, 0x26, 0x15, 0x38, 0x28, 0x0c, 0xd4, 0xc9, 0xb8, 0x11, 0xad, 0x4d, 0x78, - 0x24, 0x87, 0x48, 0x13, 0x79, 0x6d, 0x29, 0x2a, 0x87, 0x22, 0x6b, 0xaf, 0xd4, 0x2a, 0x21, 0x00, 0xbd, 0xf5, 0x4e, - 0xb7, 0x1a, 0x0d, 0x6f, 0xd4, 0x24, 0xca, 0x41, 0x7c, 0x38, 0x0d, 0x4f, 0xda, 0xe8, 0x8a, 0xf3, 0x72, 0xe2, 0x33, - 0x75, 0x77, 0x40, 0xa0, 0x81, 0xb3, 0x80, 0xc3, 0x0b, 0x83, 0x59, 0x5d, 0x55, 0x56, 0xdb, 0x05, 0x09, 0xb2, 0xa9, - 0x7f, 0x41, 0x7f, 0x58, 0x9b, 0x23, 0xb5, 0x49, 0x30, 0x1a, 0x47, 0x93, 0xf5, 0xbf, 0x8b, 0x09, 0xbc, 0xa2, 0x2e, - 0xd0, 0x1e, 0x9f, 0xb6, 0x73, 0x2a, 0x4a, 0xb6, 0xfd, 0xe7, 0x43, 0x39, 0x81, 0xfd, 0x5e, 0x76, 0x62, 0x76, 0x78, - 0x2a, 0x47, 0x3d, 0xbd, 0x4a, 0xc5, 0xd8, 0x43, 0x0c, 0xf5, 0x76, 0x04, 0x2c, 0xeb, 0x1b, 0x6b, 0x96, 0xcd, 0x76, - 0x24, 0x5b, 0x73, 0xf4, 0x72, 0x96, 0x48, 0xee, 0x1e, 0x34, 0x58, 0xce, 0xc4, 0x96, 0xcf, 0xe8, 0x79, 0xbb, 0xb5, - 0xc7, 0xe4, 0xed, 0x2c, 0x3b, 0x82, 0x2f, 0x5a, 0xdf, 0xd8, 0xd5, 0x5e, 0xf4, 0xc8, 0x75, 0xec, 0xc3, 0x04, 0x92, - 0x60, 0xb1, 0x00, 0x17, 0x71, 0xcf, 0x27, 0x67, 0xd6, 0x62, 0x9f, 0x8a, 0xd8, 0x45, 0x5a, 0xa8, 0x9f, 0xd2, 0x32, - 0x22, 0xe9, 0xf0, 0xf2, 0x63, 0xcf, 0x48, 0x1e, 0xd7, 0x51, 0xaa, 0xd4, 0x6f, 0x3d, 0x8e, 0x32, 0xb2, 0xc8, 0x51, - 0x27, 0x5c, 0xc2, 0x63, 0xdb, 0xc9, 0x4e, 0x77, 0xac, 0x5a, 0xc8, 0x3e, 0x80, 0x00, 0x49, 0xc8, 0x96, 0xb4, 0xdd, - 0x45, 0x6a, 0xe4, 0xef, 0x71, 0x31, 0x2c, 0x46, 0x84, 0xf0, 0xb0, 0x6e, 0xf0, 0x4f, 0xba, 0xcc, 0xd4, 0xdb, 0xa9, - 0x7c, 0xf0, 0x82, 0x38, 0x1a, 0x0f, 0x8f, 0xd4, 0x28, 0xb4, 0xfa, 0x64, 0x1c, 0x35, 0x29, 0x9c, 0xa1, 0x95, 0xd3, - 0xf6, 0x6f, 0xa0, 0xb7, 0x53, 0xd3, 0x45, 0xa0, 0x45, 0xe1, 0x8b, 0x47, 0x28, 0x01, 0xb1, 0x44, 0x58, 0x31, 0xa4, - 0x92, 0x30, 0x95, 0x09, 0xb9, 0x64, 0xcc, 0x65, 0xc6, 0x9d, 0x5a, 0x05, 0x77, 0x59, 0x15, 0xf7, 0x58, 0x3d, 0xee, - 0xb3, 0x06, 0x3c, 0xa8, 0x35, 0xe2, 0x21, 0xab, 0xe1, 0x1c, 0xa2, 0x7a, 0x51, 0xbd, 0xac, 0x5e, 0x55, 0xd7, 0xca, - 0x75, 0xaf, 0x43, 0x26, 0x30, 0xfe, 0x25, 0x49, 0xb4, 0xfa, 0x10, 0x2d, 0x4d, 0x79, 0xbe, 0x73, 0xf7, 0xde, 0xfd, - 0x07, 0x0f, 0xc7, 0x05, 0x2a, 0x71, 0x56, 0xf7, 0x6d, 0x59, 0xd2, 0x00, 0xb6, 0x50, 0x3a, 0x7d, 0x4b, 0x49, 0x83, - 0x89, 0x42, 0xdb, 0xf9, 0x93, 0xa5, 0xbf, 0x3c, 0xfe, 0xa0, 0xea, 0xb9, 0x79, 0x56, 0xac, 0xbc, 0xf5, 0x88, 0xd3, - 0x02, 0x2d, 0x9e, 0x5e, 0xb0, 0x90, 0x4e, 0x07, 0x1d, 0xf3, 0x6a, 0x1e, 0xf3, 0x90, 0x51, 0x8f, 0xad, 0x85, 0xa7, - 0x5a, 0xc9, 0xf2, 0x07, 0x1d, 0xc0, 0xb1, 0x38, 0x9e, 0xc9, 0xbe, 0x79, 0x24, 0x66, 0xa2, 0x69, 0xda, 0x6a, 0x42, - 0xd5, 0x3f, 0xdc, 0xba, 0xa1, 0xea, 0xc0, 0xc6, 0xec, 0xf8, 0xed, 0x27, 0x0a, 0xb0, 0x4c, 0x13, 0x98, 0x70, 0xe3, - 0x38, 0x6b, 0x16, 0x2e, 0x66, 0xcb, 0xe6, 0xf9, 0x88, 0x01, 0xea, 0x99, 0x0a, 0xa0, 0x92, 0x1e, 0xf8, 0x67, 0xc7, - 0xfe, 0x74, 0xee, 0x2e, 0x6c, 0x18, 0xfd, 0xce, 0xec, 0x7e, 0xf5, 0x1b, 0x71, 0x02, 0xa9, 0xc7, 0xa2, 0xb2, 0x52, - 0xcd, 0xc4, 0x8b, 0x6a, 0x6f, 0xc4, 0xd1, 0xcd, 0x4c, 0x73, 0x63, 0x6f, 0x6f, 0x82, 0xd1, 0xee, 0xc8, 0x00, 0x88, - 0x40, 0xfd, 0xe7, 0xf4, 0x94, 0xd5, 0xfa, 0x76, 0xfa, 0x4d, 0xca, 0xa6, 0x48, 0x09, 0x3e, 0x2d, 0xfe, 0xe0, 0x9f, - 0xba, 0x6f, 0x5a, 0x6c, 0x85, 0x36, 0xf2, 0xb9, 0xca, 0x89, 0x23, 0x91, 0x27, 0xbe, 0x63, 0xeb, 0xac, 0xf2, 0xb0, - 0xf1, 0x53, 0x58, 0xde, 0x66, 0x5a, 0x5c, 0x8a, 0x63, 0x6d, 0x9c, 0xc3, 0x22, 0x37, 0xff, 0x4c, 0xb5, 0xa3, 0xf1, - 0x8b, 0x7d, 0xfb, 0x2b, 0x53, 0xe5, 0x61, 0x39, 0xbe, 0xf2, 0xef, 0xf2, 0x73, 0xf4, 0x38, 0x2f, 0x72, 0xb5, 0xfe, - 0x3e, 0x35, 0xcb, 0x96, 0x0f, 0x4f, 0x72, 0x5f, 0x71, 0x99, 0xa7, 0xa6, 0xf9, 0xa5, 0xaf, 0x86, 0x3c, 0x77, 0xad, - 0xe9, 0xdd, 0xcd, 0xcf, 0x58, 0xfe, 0x49, 0x35, 0xab, 0xf6, 0xa0, 0x7f, 0x95, 0x3d, 0x3b, 0x9e, 0x8a, 0x11, 0x99, - 0x1a, 0x2b, 0x73, 0x40, 0x75, 0x7f, 0x7e, 0x16, 0x09, 0x6e, 0xfc, 0xa7, 0xc7, 0x25, 0x3d, 0x83, 0xa4, 0xb7, 0x75, - 0xfe, 0x42, 0xe8, 0xa6, 0x9e, 0xf4, 0xe0, 0x10, 0xd4, 0x2b, 0xfe, 0x37, 0x0f, 0xe1, 0x0b, 0x4c, 0x5d, 0x20, 0x10, - 0x6f, 0x60, 0x2a, 0xf4, 0xf3, 0xcb, 0xe8, 0x34, 0xd1, 0xdd, 0xa4, 0x65, 0xaa, 0xa2, 0xa6, 0x94, 0x13, 0x3b, 0x42, - 0xc1, 0xb7, 0x93, 0x91, 0x5e, 0x32, 0xda, 0x3a, 0x7f, 0x2d, 0x74, 0x4b, 0x91, 0xdd, 0x4d, 0xbc, 0x55, 0xe7, 0x3d, - 0x2b, 0xe7, 0xcf, 0xf5, 0x74, 0x7b, 0x82, 0x5d, 0x7d, 0x06, 0x54, 0xcb, 0x02, 0x9c, 0x97, 0x6f, 0x60, 0xda, 0x2f, - 0x02, 0x94, 0xd1, 0x62, 0x35, 0xf4, 0x1b, 0xf5, 0x96, 0xc9, 0xfa, 0xdb, 0x8f, 0x6b, 0x0d, 0xd8, 0x39, 0xfc, 0x73, - 0x03, 0x86, 0xe7, 0x48, 0xf4, 0x1c, 0x41, 0x97, 0xae, 0x31, 0x97, 0x35, 0xda, 0x90, 0x3d, 0xd5, 0xd8, 0xbc, 0x05, - 0x97, 0x82, 0xf0, 0xb6, 0x61, 0x36, 0xcd, 0x7c, 0xac, 0x62, 0xae, 0xce, 0x65, 0x9e, 0x3e, 0x23, 0x21, 0xdf, 0xb7, - 0xac, 0x8d, 0x05, 0x53, 0x10, 0xcc, 0x6c, 0x98, 0x32, 0x96, 0xaf, 0x8b, 0xa6, 0x14, 0x7e, 0x1f, 0xc5, 0xb0, 0xee, - 0x19, 0x8b, 0xa4, 0x60, 0x5d, 0xf9, 0x2f, 0x39, 0xe6, 0x31, 0x8f, 0xa5, 0x83, 0x9e, 0x1b, 0xe6, 0xd1, 0x0c, 0x7c, - 0xcc, 0xa8, 0x4a, 0x9c, 0xc1, 0x8e, 0x17, 0xcf, 0x88, 0x82, 0x16, 0xcd, 0xf5, 0xc7, 0xb6, 0xd6, 0x87, 0x4c, 0xdd, - 0xad, 0x98, 0xcd, 0xcf, 0xf4, 0x6d, 0xb6, 0xe9, 0x80, 0xc9, 0x12, 0x41, 0x98, 0x43, 0xf3, 0x7b, 0xf5, 0xa1, 0xb2, - 0x93, 0x5b, 0xa3, 0xb5, 0x76, 0x46, 0xe3, 0x7c, 0xa8, 0x48, 0x75, 0x0e, 0x7d, 0x91, 0xa8, 0xcb, 0x88, 0x71, 0x93, - 0x2d, 0xbd, 0xdb, 0x2f, 0x4b, 0xe3, 0xbf, 0x96, 0xad, 0x32, 0xe2, 0xa9, 0xb9, 0x02, 0xba, 0xcb, 0x35, 0x5c, 0x56, - 0xc4, 0x64, 0x8a, 0x79, 0xb8, 0x6d, 0xe5, 0x6c, 0x16, 0x72, 0x69, 0x3e, 0x81, 0x33, 0xa0, 0x0a, 0xd7, 0x98, 0x05, - 0xd1, 0x5c, 0xb0, 0x00, 0xd6, 0x02, 0xa7, 0x97, 0x27, 0x73, 0x79, 0xd6, 0x31, 0x4a, 0x8c, 0x65, 0xed, 0x1f, 0x2f, - 0x2f, 0x0d, 0xfa, 0x49, 0x16, 0xf2, 0xcc, 0x77, 0xdc, 0xa9, 0xda, 0xa7, 0x78, 0x3a, 0xfa, 0xdd, 0x4f, 0xf9, 0x7b, - 0x0e, 0xdd, 0x76, 0x49, 0xb6, 0x6f, 0x9f, 0x3a, 0x14, 0xe0, 0x48, 0x17, 0xf2, 0x6b, 0x5b, 0xec, 0xb9, 0x5b, 0xf6, - 0x21, 0xa6, 0x85, 0xb0, 0x31, 0xf3, 0x68, 0x11, 0x70, 0x59, 0xde, 0xbb, 0x51, 0xeb, 0x79, 0x4b, 0x02, 0x2e, 0xf1, - 0x9e, 0x9f, 0xea, 0x68, 0x29, 0x6d, 0x47, 0xee, 0xb3, 0x83, 0x28, 0x67, 0x57, 0x5d, 0x3f, 0x31, 0x37, 0xfe, 0xdb, - 0x9d, 0x3d, 0x53, 0x6b, 0xb5, 0x20, 0x29, 0x97, 0x7e, 0x9e, 0x1f, 0x9a, 0x99, 0x4a, 0x26, 0xf0, 0xf0, 0x02, 0x12, - 0xbf, 0xf0, 0xd3, 0xbf, 0x1f, 0xa8, 0xb2, 0xae, 0x1c, 0x22, 0x3d, 0x03, 0x92, 0xe7, 0xe3, 0xc7, 0xd7, 0x85, 0xc7, - 0x3b, 0xa2, 0x4b, 0xbd, 0x9e, 0xe7, 0x16, 0x12, 0xe7, 0x49, 0x77, 0x4e, 0x5c, 0xad, 0x5c, 0xa0, 0x67, 0xa6, 0x21, - 0xe1, 0x5c, 0xf5, 0x8f, 0x0f, 0x81, 0x7f, 0x05, 0x0e, 0x24, 0xa9, 0xab, 0x0b, 0x15, 0x02, 0x9d, 0xd0, 0x7e, 0xde, - 0x12, 0x48, 0x78, 0xf7, 0x22, 0xd8, 0x62, 0x90, 0x7b, 0x2d, 0xa8, 0xa8, 0x2a, 0x54, 0x30, 0x6f, 0x44, 0x25, 0x78, - 0xe4, 0x1f, 0x30, 0x68, 0x9e, 0x98, 0x99, 0xe1, 0x3c, 0x82, 0x88, 0x24, 0x39, 0xb1, 0x45, 0x7c, 0x00, 0xa0, 0x8e, - 0x77, 0x82, 0xf1, 0x4a, 0xe2, 0x30, 0x42, 0x09, 0x2e, 0xbf, 0x17, 0xad, 0x47, 0x71, 0x67, 0x87, 0x83, 0x7f, 0x41, - 0x9a, 0xc7, 0xed, 0xde, 0x1f, 0x43, 0x7f, 0xf6, 0x01, 0xcd, 0xd0, 0xee, 0x04, 0xf4, 0x71, 0xb7, 0x26, 0xed, 0x7e, - 0x33, 0x3d, 0x13, 0x6d, 0xb7, 0x49, 0x62, 0x73, 0x20, 0x63, 0xde, 0x9e, 0x88, 0x0d, 0x6d, 0xfc, 0x01, 0x7e, 0x6b, - 0x6c, 0x56, 0x5d, 0x26, 0x9e, 0x59, 0x3d, 0x3c, 0x9e, 0x89, 0x27, 0x56, 0xab, 0x8d, 0xd8, 0xb1, 0xfa, 0x3f, 0xd4, - 0xf7, 0xf8, 0x96, 0x55, 0x78, 0x54, 0xfd, 0x17, 0xda, 0x81, 0x87, 0xb0, 0xb1, 0x36, 0x8f, 0x9e, 0x35, 0x6c, 0xf0, - 0x60, 0x75, 0x09, 0x3a, 0xf8, 0xf1, 0x57, 0x06, 0x8f, 0x88, 0xdd, 0x0f, 0x06, 0x2b, 0xab, 0x29, 0xb0, 0x3c, 0xde, - 0x1f, 0xdd, 0xff, 0x3f, 0x6f, 0x1a, 0x1e, 0xba, 0xd6, 0xd3, 0x1a, 0x2c, 0x2a, 0xa1, 0xc2, 0xfc, 0x7f, 0x56, 0x0f, - 0x62, 0xc6, 0x6a, 0x9d, 0x89, 0x29, 0xab, 0x3a, 0x13, 0x13, 0x56, 0xfb, 0xbc, 0x5e, 0x6f, 0x88, 0x1e, 0x2b, 0x5f, - 0x88, 0x31, 0xab, 0xe5, 0x9d, 0xe8, 0xb3, 0xaa, 0xb6, 0x7f, 0x03, 0x31, 0x60, 0xe5, 0x13, 0x31, 0x8c, 0x0c, 0x56, - 0x30, 0xfa, 0x1b, 0x2f, 0x77, 0x32, 0xb4, 0x5b, 0x3d, 0xb7, 0xc6, 0xff, 0x45, 0x27, 0xea, 0xd3, 0xe5, 0xc4, 0x95, - 0x67, 0x12, 0x70, 0xd1, 0xfe, 0x5b, 0x78, 0xbd, 0x09, 0x8f, 0x79, 0x60, 0xa4, 0x62, 0x69, 0x06, 0xc0, 0x38, 0x3f, - 0xfc, 0x4f, 0x77, 0x84, 0xb9, 0x91, 0x04, 0x46, 0x56, 0x29, 0x6b, 0xa3, 0xff, 0x97, 0xae, 0x20, 0x2a, 0x83, 0x6c, - 0xfb, 0xf0, 0xb6, 0x3a, 0x35, 0x7a, 0x0d, 0x6d, 0x18, 0xbd, 0xbc, 0xce, 0x59, 0x17, 0xd0, 0x51, 0x4b, 0x0a, 0xa1, - 0xeb, 0xba, 0x7b, 0x62, 0x7a, 0x5b, 0xbc, 0x23, 0x98, 0x11, 0xd4, 0x44, 0x04, 0x49, 0xd3, 0xfe, 0x4f, 0xce, 0xb6, - 0xe5, 0x58, 0x7b, 0xca, 0x62, 0xf9, 0xf0, 0x7d, 0x75, 0x75, 0x2a, 0x4c, 0x99, 0x09, 0x2e, 0xf3, 0xb0, 0xad, 0xde, - 0x53, 0x3d, 0x8c, 0xa5, 0xdb, 0xd3, 0xf0, 0x12, 0x31, 0x7c, 0x4b, 0xae, 0x5a, 0x10, 0xef, 0x09, 0xe6, 0xd8, 0x2d, - 0x81, 0x58, 0x29, 0x5c, 0x8d, 0xd7, 0x2d, 0x24, 0x8e, 0x19, 0xa9, 0xf1, 0x57, 0xeb, 0xfd, 0xdb, 0xcd, 0x14, 0xa7, - 0xc0, 0xa1, 0xe8, 0x36, 0xe0, 0x1d, 0x11, 0xe5, 0x94, 0x43, 0x96, 0x3c, 0xe2, 0x60, 0x87, 0x13, 0x07, 0x64, 0x99, - 0x26, 0xda, 0xac, 0x95, 0xd7, 0x04, 0xef, 0xea, 0xd1, 0x29, 0x93, 0x63, 0x6b, 0x03, 0xc7, 0x20, 0xf9, 0x17, 0xbc, - 0xea, 0x15, 0xa0, 0x0f, 0xd6, 0x54, 0x5d, 0xe8, 0xdb, 0x97, 0xf3, 0x3b, 0xd5, 0xa6, 0x5d, 0xe1, 0x95, 0xfd, 0x86, - 0xad, 0xce, 0xea, 0x1b, 0x41, 0x6a, 0xdd, 0x6d, 0xa4, 0x21, 0x40, 0xf7, 0x43, 0xbe, 0xbb, 0xa7, 0x23, 0x9c, 0x6c, - 0xed, 0x1c, 0x61, 0xa1, 0x99, 0x11, 0xfa, 0xdb, 0x08, 0xb8, 0x43, 0x01, 0x55, 0xdc, 0xda, 0x33, 0xa3, 0x48, 0x44, - 0xb4, 0x24, 0x15, 0xf1, 0x1e, 0x5c, 0xcf, 0xc6, 0xb0, 0x6c, 0xa4, 0x9d, 0xbd, 0xbe, 0xc9, 0xb6, 0x28, 0x82, 0xb0, - 0x75, 0xbd, 0x23, 0x0c, 0xe4, 0x2f, 0x03, 0xff, 0xd7, 0xea, 0xbd, 0xb4, 0x5a, 0xba, 0xa9, 0x7b, 0x7c, 0x0b, 0x7e, - 0xa8, 0x4b, 0xf9, 0x99, 0xa4, 0x98, 0x9d, 0x26, 0x3e, 0xf5, 0x49, 0x79, 0x8a, 0x97, 0x5d, 0x06, 0x40, 0xe4, 0x7a, - 0x4e, 0xc1, 0x87, 0xbc, 0xdb, 0x4c, 0xa9, 0x8b, 0xcc, 0x63, 0x82, 0x01, 0x66, 0x97, 0xd2, 0xc5, 0x3a, 0x35, 0x5c, - 0x6c, 0xa4, 0x1c, 0x6e, 0x3a, 0x9c, 0x36, 0xf4, 0xaa, 0x18, 0x17, 0x91, 0x1d, 0xdf, 0x35, 0x8d, 0x6f, 0x72, 0x23, - 0xf4, 0xde, 0xb9, 0xe1, 0xa9, 0xcf, 0x18, 0xf3, 0xb7, 0x82, 0x50, 0x19, 0x63, 0x3b, 0x9c, 0xad, 0x28, 0xd5, 0x4a, - 0x7e, 0x39, 0x6c, 0x73, 0xd8, 0xbf, 0xc9, 0xad, 0x6d, 0x0c, 0x18, 0xf1, 0x05, 0xe3, 0xbb, 0x10, 0xbf, 0x2f, 0x58, - 0x23, 0x7a, 0xc1, 0x25, 0xcb, 0x53, 0xb0, 0xf0, 0x50, 0x02, 0x53, 0xb6, 0x87, 0x26, 0xe0, 0xde, 0xe7, 0x26, 0x7e, - 0x3b, 0xe4, 0xe6, 0xd1, 0x87, 0x78, 0x2d, 0x94, 0x2a, 0x11, 0xf6, 0xad, 0x78, 0xd6, 0xa8, 0xe0, 0x99, 0x9b, 0x95, - 0xcc, 0x00, 0x28, 0x04, 0xba, 0xd5, 0x1c, 0xbe, 0xeb, 0x8f, 0x7b, 0x75, 0x80, 0xce, 0x6a, 0x5f, 0xce, 0x84, 0x8c, - 0x91, 0xe7, 0xf4, 0x20, 0xe8, 0xe9, 0xa3, 0x77, 0xbc, 0xbd, 0xac, 0x2a, 0x43, 0x8e, 0xc5, 0xc8, 0xa1, 0x99, 0x3c, - 0x2a, 0x4b, 0x1a, 0xb2, 0xe0, 0x72, 0x2a, 0xd7, 0xa4, 0x5a, 0xf5, 0x25, 0xe9, 0x7d, 0xcd, 0xd9, 0x0e, 0x68, 0xec, - 0x79, 0xbf, 0x85, 0xe0, 0x18, 0x84, 0x90, 0x30, 0x27, 0x36, 0xf7, 0xfe, 0xce, 0x00, 0xe7, 0xdb, 0x97, 0x50, 0x6f, - 0xbe, 0xf9, 0x81, 0x5b, 0xf4, 0x13, 0x8e, 0xa1, 0xb4, 0x38, 0xd5, 0x84, 0xab, 0xa3, 0x37, 0xb2, 0x36, 0x52, 0xd2, - 0x79, 0x1d, 0xbd, 0x1b, 0x1b, 0xc5, 0x78, 0xc7, 0x40, 0x54, 0x44, 0x79, 0xb8, 0x1f, 0x4b, 0xa2, 0x72, 0x73, 0x82, - 0x6b, 0x8a, 0x48, 0x44, 0xe1, 0x20, 0xdd, 0xc5, 0xd5, 0xf8, 0xc2, 0xa1, 0xc6, 0x34, 0x33, 0x07, 0x06, 0x48, 0xaa, - 0x43, 0x5d, 0x9b, 0xdd, 0x37, 0x02, 0xe1, 0x25, 0x17, 0xb0, 0x5c, 0x81, 0xcb, 0x43, 0xfe, 0x22, 0xf5, 0x5d, 0xcc, - 0x3b, 0x6d, 0x42, 0x24, 0xe7, 0xce, 0x80, 0x18, 0x38, 0xa4, 0x08, 0x25, 0xd3, 0x8d, 0x4b, 0x4e, 0xe2, 0xd6, 0x6c, - 0xce, 0x5c, 0x28, 0x19, 0x33, 0xf7, 0x88, 0xfe, 0x83, 0xf7, 0x36, 0x21, 0x5e, 0x70, 0x90, 0x45, 0x25, 0x3a, 0x1b, - 0x46, 0x3a, 0x91, 0xf0, 0x6b, 0x2c, 0xde, 0x60, 0x47, 0x96, 0x06, 0xd1, 0x4d, 0x91, 0x31, 0x84, 0x4d, 0x3b, 0xac, - 0x0e, 0xcd, 0x46, 0x49, 0x42, 0x0e, 0x08, 0xb5, 0xf3, 0x24, 0x27, 0x1d, 0xe1, 0xdd, 0xbb, 0xdc, 0xa6, 0xea, 0xc5, - 0xaf, 0x32, 0xd1, 0xa8, 0x36, 0x11, 0x2b, 0xbf, 0x9e, 0xc8, 0xca, 0xc2, 0x97, 0x02, 0x9a, 0x02, 0x25, 0x49, 0xfe, - 0xf6, 0xd7, 0xb4, 0xcc, 0xd3, 0x6b, 0x1d, 0x64, 0x30, 0x98, 0x7c, 0x25, 0x72, 0x8d, 0x1a, 0xd9, 0xe0, 0x3b, 0xe9, - 0x5c, 0xc6, 0x2a, 0xf7, 0x65, 0x88, 0x78, 0x9a, 0x9b, 0xfe, 0xa5, 0x0f, 0x2a, 0xd4, 0xea, 0x43, 0x23, 0xbb, 0x93, - 0xb6, 0x3e, 0x49, 0xd1, 0x48, 0x56, 0xec, 0xe2, 0x8b, 0x4b, 0x34, 0x5a, 0x32, 0x15, 0x4f, 0xca, 0x22, 0x63, 0x93, - 0x6b, 0xaf, 0x8d, 0x4d, 0xd4, 0x1d, 0x8c, 0x25, 0xb2, 0x34, 0x7c, 0x3b, 0x3d, 0xda, 0x10, 0xb7, 0xf7, 0x50, 0x57, - 0x37, 0x65, 0x1f, 0xde, 0xcd, 0xa8, 0x42, 0x73, 0xb3, 0x4a, 0x9d, 0x71, 0x70, 0x86, 0x5f, 0xaf, 0x50, 0x68, 0x4e, - 0x9f, 0x1a, 0x92, 0xe3, 0xec, 0x6b, 0x69, 0x00, 0xed, 0xab, 0xc9, 0x28, 0x16, 0x61, 0x21, 0xc4, 0x25, 0x1c, 0x80, - 0x5c, 0x3e, 0x4c, 0x97, 0x58, 0x6b, 0x95, 0x2b, 0xe9, 0x95, 0x48, 0x16, 0x28, 0xf1, 0x51, 0x9d, 0x5a, 0xa9, 0xac, - 0xe6, 0x4c, 0x62, 0x06, 0x0a, 0x98, 0xbc, 0x35, 0xbd, 0x91, 0x9e, 0xe5, 0x96, 0xb9, 0x4c, 0x70, 0xe6, 0x42, 0xb4, - 0xe6, 0x87, 0x6f, 0x72, 0x43, 0x56, 0x54, 0xd3, 0x88, 0x14, 0x3f, 0x38, 0x33, 0x10, 0x13, 0x20, 0x96, 0x31, 0xd7, - 0x27, 0x98, 0x60, 0x83, 0xf5, 0x66, 0x4d, 0xd7, 0xb0, 0xa1, 0xfc, 0x74, 0xff, 0xe4, 0x17, 0x63, 0x9e, 0x23, 0x80, - 0x95, 0x99, 0x78, 0x5e, 0xf2, 0xe9, 0x54, 0x29, 0x74, 0x89, 0x28, 0xce, 0x68, 0xd1, 0xd8, 0x99, 0x86, 0x65, 0x6c, - 0x23, 0x43, 0x00, 0xb4, 0x37, 0xf9, 0xf5, 0x65, 0x16, 0x25, 0xb5, 0x32, 0x21, 0xf2, 0x11, 0xd3, 0x8c, 0x3c, 0x39, - 0xd5, 0x21, 0x6b, 0x0d, 0x1e, 0x46, 0x95, 0x48, 0xfe, 0x78, 0x2a, 0xb9, 0x90, 0x44, 0xef, 0x61, 0x3b, 0x54, 0x59, - 0xb2, 0x60, 0xc5, 0x2a, 0x7a, 0xdf, 0xde, 0xee, 0xfa, 0x6b, 0x64, 0xc2, 0x5e, 0x00, 0xa2, 0xd7, 0x1e, 0x1c, 0xe3, - 0x95, 0xc9, 0x27, 0x57, 0x19, 0x2c, 0x28, 0x25, 0x42, 0x4d, 0x38, 0xda, 0x98, 0xcb, 0x32, 0x53, 0x70, 0xd5, 0x23, - 0xd9, 0xb2, 0x94, 0x39, 0xc9, 0xb0, 0xde, 0x06, 0x92, 0xf1, 0x11, 0xb5, 0xfc, 0xb5, 0x60, 0x6f, 0x1d, 0xd4, 0x29, - 0x04, 0x71, 0x92, 0xff, 0xe6, 0xf1, 0xba, 0xc5, 0xf7, 0xcb, 0x4f, 0x9b, 0x2c, 0x46, 0x92, 0xbd, 0x48, 0x53, 0xe9, - 0xbf, 0xd0, 0x2c, 0x0d, 0x0e, 0x4a, 0x4b, 0x6f, 0xcf, 0x05, 0x57, 0x7a, 0x21, 0x8a, 0x59, 0x00, 0x4f, 0x48, 0xa9, - 0x37, 0xba, 0x92, 0x68, 0x9d, 0x61, 0x75, 0x2c, 0xce, 0x6a, 0x11, 0x7a, 0x95, 0x4e, 0x88, 0xc5, 0x53, 0x23, 0xf2, - 0x9b, 0xac, 0x38, 0x47, 0xf7, 0xc6, 0xe3, 0x6b, 0x76, 0xbe, 0x2c, 0x43, 0x65, 0xea, 0x47, 0x88, 0xbe, 0x14, 0x1c, - 0x21, 0x36, 0x12, 0x75, 0x1b, 0x56, 0x8c, 0x10, 0x4c, 0x78, 0x75, 0x62, 0x96, 0x4b, 0xf4, 0xda, 0xfa, 0xe3, 0x7d, - 0xba, 0x67, 0xd5, 0x30, 0x7a, 0x65, 0x3e, 0xfe, 0x25, 0x91, 0xcd, 0x30, 0xfa, 0x13, 0xf8, 0x81, 0xc5, 0x9d, 0x9b, - 0xe9, 0x41, 0x38, 0x31, 0x4f, 0x4a, 0x2a, 0xb3, 0xf9, 0x83, 0xbd, 0xc3, 0x30, 0xba, 0xa0, 0xfb, 0xc1, 0x9b, 0x4e, - 0xad, 0x76, 0xbf, 0x21, 0xba, 0x8a, 0xa7, 0xdd, 0xfd, 0xaa, 0x3f, 0x98, 0x24, 0x0a, 0xd1, 0x8b, 0x06, 0x00, 0x3c, - 0xcd, 0x80, 0x67, 0x92, 0x62, 0x63, 0xf2, 0x66, 0x96, 0xae, 0x9c, 0x13, 0x5f, 0x50, 0xe7, 0xd9, 0x86, 0xac, 0xc9, - 0xbd, 0x24, 0xc8, 0x29, 0x55, 0x6e, 0x0d, 0xca, 0x18, 0x15, 0x55, 0x62, 0x78, 0x9a, 0x46, 0xb0, 0x01, 0x72, 0x4b, - 0x5b, 0x74, 0x3d, 0x23, 0x35, 0xa7, 0x73, 0x48, 0xd5, 0xca, 0x12, 0xdf, 0xa3, 0x3f, 0xca, 0xd0, 0x78, 0x48, 0xc4, - 0x56, 0x5d, 0xd3, 0xdc, 0xaf, 0xeb, 0x5d, 0x3a, 0x6e, 0xf8, 0x9d, 0x89, 0xc2, 0x6f, 0x5e, 0xe0, 0x3d, 0xb7, 0xd0, - 0xd1, 0x06, 0x37, 0x8e, 0xec, 0xe0, 0xcf, 0x60, 0x02, 0x63, 0x3f, 0x6f, 0x86, 0x83, 0xcb, 0x19, 0x9a, 0xaf, 0xa7, - 0xb9, 0xc7, 0xbd, 0x23, 0x6e, 0xd9, 0x5c, 0xe3, 0x7f, 0x73, 0x0b, 0x05, 0xe5, 0xfb, 0xcc, 0xb0, 0xa4, 0xd9, 0xde, - 0x8a, 0xa4, 0xf2, 0x35, 0x03, 0xd8, 0x85, 0x94, 0x9a, 0x0a, 0xb3, 0x69, 0x36, 0x99, 0x60, 0x00, 0x74, 0x91, 0xdf, - 0x5a, 0x2a, 0x88, 0x70, 0x89, 0xc6, 0x80, 0x1b, 0x40, 0x7d, 0x00, 0x86, 0x32, 0xe7, 0x10, 0x1e, 0x82, 0xaf, 0xb0, - 0x91, 0x18, 0xd9, 0x25, 0x18, 0xe3, 0x71, 0xdb, 0xc7, 0xaf, 0xc5, 0x5e, 0xd3, 0xec, 0x94, 0xef, 0x31, 0x36, 0xb1, - 0x79, 0x16, 0x1e, 0xd2, 0x07, 0x39, 0xf3, 0x9d, 0x19, 0x2b, 0xa2, 0x75, 0x7e, 0x2e, 0xec, 0x2f, 0x2d, 0x91, 0x60, - 0xd2, 0x52, 0xdb, 0x1b, 0x90, 0xf2, 0x89, 0x80, 0xa5, 0x34, 0x2f, 0x42, 0x5b, 0x35, 0xc8, 0x03, 0x25, 0xf4, 0x76, - 0x1a, 0xb5, 0xd7, 0x36, 0xeb, 0x85, 0x62, 0x5d, 0x70, 0xdc, 0x6a, 0x01, 0x43, 0x66, 0x38, 0x62, 0x03, 0xd6, 0x81, - 0x2b, 0x99, 0xa9, 0x66, 0xe2, 0x42, 0x9c, 0xd7, 0x99, 0xd1, 0x8c, 0x9f, 0xf3, 0xd4, 0x6e, 0xab, 0xcd, 0x95, 0x38, - 0x43, 0xff, 0xae, 0x5e, 0xbd, 0x99, 0xc6, 0xe8, 0x6e, 0x4c, 0x20, 0xdb, 0x4a, 0x1f, 0x0d, 0x7f, 0x3c, 0x9c, 0xa5, - 0x18, 0x06, 0xdc, 0x9f, 0x53, 0x15, 0xb4, 0xbf, 0x40, 0x79, 0x96, 0x97, 0x36, 0x76, 0x88, 0xd4, 0x64, 0xa0, 0x54, - 0x79, 0xbe, 0x97, 0x6c, 0x95, 0x48, 0xd0, 0x20, 0xb9, 0x91, 0x27, 0xcf, 0xe1, 0x0b, 0x32, 0xe2, 0x8f, 0xc6, 0xef, - 0x2f, 0x20, 0xc2, 0xce, 0x30, 0x93, 0x07, 0x06, 0x33, 0x77, 0x67, 0x03, 0x4f, 0x92, 0xd6, 0x9f, 0x8e, 0x12, 0xcd, - 0x97, 0x9b, 0xbb, 0x92, 0x4c, 0x71, 0x42, 0xf3, 0x93, 0x0f, 0x33, 0x54, 0x14, 0x97, 0x7f, 0xe0, 0x7a, 0xd6, 0x9e, - 0xa4, 0xc0, 0xf5, 0x7e, 0x08, 0x59, 0x11, 0xa9, 0xa8, 0x05, 0xf5, 0xd0, 0x8c, 0xc6, 0xf2, 0x43, 0x73, 0xfb, 0x45, - 0xaf, 0x08, 0x6c, 0xe2, 0x51, 0x8d, 0x9f, 0xf4, 0x5f, 0x3f, 0x30, 0x20, 0xe6, 0xbf, 0x4b, 0x62, 0x45, 0x55, 0xe3, - 0xdc, 0x65, 0x89, 0xaf, 0x60, 0xd5, 0x9f, 0x87, 0x44, 0x11, 0x64, 0xb7, 0x52, 0x84, 0x10, 0x9a, 0x2a, 0x62, 0xda, - 0x03, 0x38, 0xbd, 0x41, 0xdf, 0x51, 0x84, 0x85, 0x0a, 0x37, 0xa6, 0x9f, 0x90, 0x9a, 0x04, 0xa3, 0xd3, 0xd1, 0x40, - 0xe5, 0x80, 0xa4, 0x6f, 0x77, 0xbe, 0xbd, 0x47, 0x26, 0x59, 0xab, 0x5b, 0x99, 0xa4, 0x00, 0x81, 0x36, 0x7c, 0xc8, - 0xed, 0xed, 0x79, 0x9e, 0xe7, 0x2a, 0xab, 0xd7, 0xf1, 0x67, 0x1b, 0x0e, 0x13, 0xdb, 0xb1, 0x35, 0x3c, 0x78, 0xa2, - 0x85, 0x74, 0xfc, 0x45, 0x53, 0x34, 0xe8, 0x1a, 0xf1, 0x11, 0x05, 0xfa, 0x9c, 0x5d, 0x48, 0x1a, 0x37, 0xef, 0xca, - 0x75, 0xe0, 0x32, 0xb8, 0x29, 0x19, 0x1c, 0xd8, 0x9d, 0x0a, 0x99, 0x39, 0x35, 0x17, 0x54, 0x1e, 0x0f, 0xa4, 0xfe, - 0x90, 0xca, 0x8d, 0x59, 0xaa, 0x10, 0x1b, 0x54, 0xa7, 0x06, 0x7c, 0xd9, 0x13, 0x41, 0xcb, 0x13, 0xc8, 0xde, 0xab, - 0x21, 0xc5, 0x98, 0xe4, 0x72, 0x97, 0x03, 0xb6, 0xa1, 0x03, 0xd5, 0xa0, 0xe9, 0x18, 0x40, 0xb8, 0xbb, 0xf8, 0x96, - 0xf4, 0xbf, 0x7d, 0x9c, 0x7e, 0xaa, 0xee, 0x3c, 0x02, 0x4d, 0xb2, 0x56, 0x74, 0xbf, 0xd4, 0xa2, 0x21, 0x48, 0x78, - 0x1b, 0x1e, 0x22, 0xfe, 0xf4, 0x77, 0xe4, 0xd2, 0xc0, 0x5a, 0xd7, 0xa1, 0xff, 0x8e, 0x6c, 0xa6, 0x50, 0xa6, 0x15, - 0x52, 0xea, 0x54, 0x2d, 0x9c, 0x3b, 0x45, 0x59, 0x1a, 0x54, 0x3f, 0x48, 0x65, 0x85, 0x03, 0x09, 0x89, 0x44, 0x45, - 0x19, 0x26, 0x15, 0xaf, 0x69, 0x7d, 0x9f, 0x62, 0x13, 0x9e, 0xdd, 0xad, 0xfc, 0x90, 0x39, 0x88, 0x97, 0xc2, 0x1f, - 0x0f, 0xc6, 0xd7, 0x48, 0x6b, 0xa8, 0x67, 0x87, 0x87, 0x23, 0xcc, 0x51, 0xc4, 0xfa, 0x14, 0x65, 0xa8, 0x04, 0x72, - 0x29, 0xc5, 0x13, 0x86, 0x97, 0x98, 0xa8, 0xe8, 0x1c, 0x72, 0xd0, 0xe6, 0x7c, 0x80, 0x85, 0x87, 0x5e, 0xf0, 0xaf, - 0xe8, 0x21, 0x77, 0xaf, 0x8c, 0x88, 0xa6, 0x32, 0xa5, 0xdb, 0x3a, 0xe5, 0x1e, 0x3a, 0x5b, 0x04, 0xbd, 0x7d, 0xcf, - 0x3f, 0x7d, 0xa7, 0xef, 0xd4, 0xcf, 0x3e, 0xe5, 0x63, 0x7d, 0xca, 0xbf, 0xee, 0xfe, 0x63, 0xdb, 0x21, 0xff, 0x78, - 0xc9, 0xa6, 0x6d, 0x58, 0xd3, 0x6e, 0x4a, 0x54, 0xba, 0x4f, 0x14, 0x66, 0xe2, 0xa5, 0x18, 0xff, 0xb6, 0x28, 0x6b, - 0x7d, 0xb9, 0xb0, 0x82, 0x74, 0x32, 0x9b, 0xf0, 0xf5, 0xaf, 0x0b, 0x47, 0x08, 0x2d, 0x02, 0x3b, 0x49, 0xe9, 0x7c, - 0x92, 0xb5, 0x05, 0x34, 0x97, 0xa4, 0xb3, 0x84, 0x59, 0xc2, 0xd6, 0xf9, 0x04, 0xf4, 0x40, 0xb3, 0xa9, 0x5e, 0xe0, - 0x3a, 0x72, 0x0c, 0xc5, 0xf1, 0x6a, 0xe7, 0xa3, 0xdf, 0xde, 0x8a, 0x6f, 0x31, 0xd8, 0x85, 0xa5, 0x16, 0xd4, 0x8c, - 0x9a, 0x55, 0x0b, 0x38, 0x83, 0xb3, 0x78, 0x16, 0x14, 0xe8, 0xe7, 0x82, 0x21, 0xb8, 0x80, 0xd6, 0x06, 0xfa, 0x60, - 0xda, 0x78, 0x84, 0x45, 0x59, 0xe4, 0x1d, 0xf5, 0xe2, 0x66, 0x5d, 0xf5, 0xde, 0xdf, 0x56, 0x8c, 0x4a, 0xbc, 0xe5, - 0x7f, 0x05, 0x55, 0x22, 0xe9, 0xae, 0x90, 0xc8, 0xbb, 0x2a, 0x3e, 0x5e, 0x9b, 0xd6, 0x07, 0xb1, 0xac, 0xda, 0xb2, - 0xfe, 0x8e, 0xb0, 0x33, 0xe1, 0x71, 0xe8, 0x9e, 0xaa, 0x50, 0x10, 0xd3, 0x38, 0x77, 0xc9, 0xf7, 0x43, 0xbe, 0xea, - 0x7c, 0x37, 0xfc, 0x5b, 0x54, 0xcb, 0x5c, 0xcf, 0x24, 0x02, 0xa2, 0x9c, 0x74, 0xc1, 0xca, 0x61, 0x78, 0xe2, 0x9e, - 0xe6, 0x75, 0x91, 0x9c, 0x17, 0xd4, 0x33, 0x2c, 0x6e, 0xdf, 0xcb, 0x5f, 0x84, 0x6d, 0x8a, 0xca, 0x5f, 0xd8, 0x8c, - 0x3d, 0x1c, 0x51, 0x4d, 0xb7, 0x4f, 0xa8, 0xa0, 0x55, 0xa5, 0x1c, 0x4f, 0xbb, 0xf0, 0x22, 0x72, 0xb6, 0x37, 0xb0, - 0x53, 0xe6, 0xb6, 0x66, 0xdb, 0x1d, 0xe9, 0xef, 0x62, 0x15, 0x45, 0xec, 0x8a, 0xc3, 0x3e, 0xad, 0xa4, 0xeb, 0x8a, - 0x9a, 0xc3, 0x10, 0x8d, 0xe3, 0x0d, 0x14, 0xe5, 0xdb, 0x00, 0x1b, 0x1d, 0x20, 0xf4, 0xdb, 0x06, 0x4f, 0x80, 0x39, - 0xcc, 0xac, 0x36, 0x2e, 0x5e, 0xcd, 0x96, 0x4a, 0xee, 0xa9, 0xea, 0xfd, 0x5b, 0x0e, 0x8c, 0xbd, 0xcd, 0xfe, 0x29, - 0x46, 0x1f, 0xf1, 0xd9, 0xfb, 0xdb, 0x4f, 0x18, 0x82, 0x3c, 0x73, 0xe5, 0x7d, 0xdd, 0x83, 0x98, 0x94, 0xd9, 0x2a, - 0x35, 0x6d, 0x2b, 0x5c, 0x32, 0x08, 0xaf, 0x1d, 0x6d, 0x58, 0xa2, 0x4e, 0x61, 0x7f, 0xad, 0x92, 0xd5, 0x4d, 0x80, - 0xcf, 0x93, 0x5a, 0x62, 0x4e, 0x95, 0xc7, 0xfe, 0xea, 0xc5, 0x49, 0x26, 0x7f, 0x62, 0x02, 0x75, 0x06, 0x97, 0xb0, - 0x29, 0xcb, 0x1f, 0xc4, 0xfe, 0xdd, 0xec, 0x6f, 0x97, 0x46, 0xfe, 0xe6, 0x28, 0xb1, 0x08, 0x29, 0xac, 0x60, 0x5c, - 0xca, 0xd7, 0x4b, 0x3a, 0x80, 0x46, 0x36, 0x29, 0x46, 0x2f, 0x68, 0x5f, 0x7e, 0xee, 0xbe, 0xc2, 0xdc, 0x53, 0x32, - 0x76, 0x71, 0x30, 0xcb, 0xb5, 0x45, 0xe1, 0x48, 0x83, 0x65, 0xf0, 0xa2, 0xb7, 0x3a, 0xc2, 0x47, 0xe6, 0x88, 0x8f, - 0xcf, 0xfb, 0xe5, 0x82, 0x68, 0x51, 0x9a, 0x3f, 0x0e, 0x9e, 0x06, 0x74, 0x5c, 0x6a, 0xdb, 0xf4, 0x1e, 0x39, 0x75, - 0x40, 0xe8, 0x1a, 0x9b, 0x4c, 0x3f, 0x56, 0x28, 0x25, 0x35, 0x4b, 0xdb, 0xe9, 0xb1, 0xb1, 0x53, 0x53, 0xa2, 0xf8, - 0xae, 0xef, 0xba, 0x3b, 0x45, 0xb5, 0xae, 0x9f, 0x72, 0x44, 0x3e, 0xea, 0x82, 0x78, 0x35, 0x72, 0x6d, 0x87, 0x5c, - 0x7d, 0xd9, 0xa9, 0xea, 0x41, 0x5d, 0xec, 0x7f, 0xc8, 0x95, 0x9c, 0x66, 0xe3, 0x5b, 0x6f, 0xd0, 0xea, 0x26, 0x0d, - 0x3d, 0xe4, 0xc0, 0x02, 0x87, 0x14, 0xe1, 0x46, 0x0c, 0x6d, 0x6b, 0x24, 0x78, 0xac, 0x98, 0xc2, 0x83, 0xb8, 0x3f, - 0x8e, 0x4c, 0x80, 0xaa, 0xe8, 0x45, 0xa8, 0x8d, 0x6d, 0x0e, 0x3d, 0x03, 0x5c, 0x0f, 0xe9, 0xaf, 0x82, 0x9c, 0xef, - 0xe0, 0x6e, 0x30, 0x5a, 0x67, 0xcf, 0x8b, 0xf2, 0x81, 0x6a, 0x5c, 0x6f, 0xdb, 0xe1, 0x90, 0x5d, 0x63, 0xb7, 0x8b, - 0xa4, 0x76, 0x59, 0xe8, 0x33, 0x5b, 0x83, 0x91, 0x62, 0x6c, 0xbd, 0x05, 0xbe, 0xd9, 0x96, 0x41, 0x65, 0xd7, 0x7e, - 0x23, 0x29, 0xa1, 0xd1, 0xc5, 0xd0, 0x60, 0xbc, 0x81, 0x40, 0x55, 0xb0, 0x3c, 0x8b, 0x69, 0x2b, 0x61, 0x34, 0x1a, - 0xf7, 0xb4, 0x9f, 0x46, 0xf5, 0xb1, 0xfc, 0x91, 0x6e, 0xa6, 0xdc, 0x48, 0x97, 0x1f, 0xa6, 0xcb, 0x3d, 0x04, 0x53, - 0x61, 0xf9, 0x52, 0xad, 0x24, 0x02, 0x6e, 0xb9, 0x82, 0xd2, 0x60, 0x7f, 0x3f, 0xaf, 0xc0, 0xcc, 0x4b, 0x9e, 0x63, - 0x68, 0x78, 0xb1, 0x51, 0xb1, 0x71, 0xe2, 0xa7, 0xbb, 0x44, 0xcb, 0xa9, 0x19, 0x3c, 0x45, 0x3c, 0x20, 0xd5, 0x6d, - 0x0b, 0x5e, 0x1e, 0x3c, 0x46, 0x23, 0x4b, 0x57, 0xca, 0x2e, 0x93, 0x67, 0xf5, 0x50, 0x8e, 0x2a, 0x71, 0xd0, 0x4b, - 0xa4, 0x51, 0x57, 0xde, 0xfa, 0xc6, 0x4b, 0x60, 0x95, 0xb4, 0x4c, 0x4e, 0xbf, 0xef, 0x88, 0x34, 0x48, 0xb8, 0x94, - 0x42, 0xf1, 0x57, 0x89, 0x90, 0x7a, 0x6f, 0x0d, 0x1d, 0xc3, 0xc0, 0xfd, 0x75, 0x3e, 0xe2, 0xac, 0xf8, 0xec, 0x17, - 0x07, 0xd0, 0xa5, 0x2a, 0x1b, 0xa4, 0x5d, 0xac, 0xdc, 0x99, 0xef, 0xf7, 0xe8, 0x6d, 0x95, 0x62, 0xf1, 0x2d, 0xa3, - 0x9f, 0x58, 0xbc, 0x15, 0x32, 0xd8, 0x3d, 0x3f, 0xc0, 0x83, 0x1d, 0x9a, 0x48, 0x5d, 0x25, 0x04, 0x30, 0x41, 0x27, - 0xbd, 0x9c, 0xbc, 0x42, 0x14, 0xa1, 0x05, 0xee, 0xc9, 0xa1, 0x8d, 0x4a, 0x61, 0xbe, 0x82, 0xf0, 0x8f, 0x72, 0xf9, - 0x1e, 0x03, 0xd3, 0xe0, 0x12, 0x0d, 0xe5, 0x03, 0x22, 0xd2, 0x93, 0x91, 0x14, 0x81, 0x17, 0xf2, 0x3e, 0x11, 0x4c, - 0x5c, 0xa3, 0x75, 0x13, 0xbc, 0xa7, 0xc5, 0xd1, 0x4d, 0xf3, 0xd4, 0xc2, 0x8c, 0xf8, 0x19, 0x13, 0x46, 0xe1, 0x32, - 0xc4, 0x77, 0x16, 0x14, 0x9e, 0x60, 0xa7, 0x1a, 0x54, 0xaf, 0x8f, 0xda, 0xf4, 0x62, 0x37, 0xf8, 0x2b, 0x37, 0x1f, - 0xcf, 0x45, 0x3a, 0xf2, 0x42, 0x5c, 0xf2, 0xdc, 0xf9, 0x01, 0x9a, 0x10, 0x9e, 0xbb, 0x61, 0x77, 0x89, 0x0e, 0xac, - 0x93, 0xc9, 0x86, 0x15, 0x4d, 0xdc, 0x74, 0x02, 0x0c, 0xf2, 0xdc, 0x39, 0xb4, 0x6a, 0xe2, 0xe9, 0x3f, 0x55, 0xb9, - 0x5d, 0xf2, 0xbc, 0xc3, 0xee, 0x9a, 0xda, 0x35, 0x36, 0x06, 0x22, 0xe2, 0x62, 0x34, 0xc7, 0xd2, 0x4b, 0xfc, 0x1c, - 0xee, 0xdc, 0x7b, 0x5c, 0x3f, 0xc5, 0x18, 0x20, 0x1f, 0xde, 0x42, 0xb6, 0x80, 0x9e, 0xc5, 0x79, 0x9f, 0xa1, 0x17, - 0xde, 0xed, 0x25, 0x66, 0x44, 0x72, 0x7f, 0xa6, 0xf5, 0x91, 0x28, 0x47, 0x7a, 0x09, 0x29, 0x4e, 0x70, 0x94, 0xec, - 0x44, 0xc0, 0xfe, 0xbf, 0x10, 0x6d, 0x27, 0x88, 0xf2, 0x6d, 0xc2, 0xcd, 0xdd, 0xed, 0x58, 0xb9, 0x7d, 0xcb, 0x13, - 0x42, 0xa9, 0xf8, 0x84, 0x71, 0x88, 0x69, 0x27, 0x13, 0xbb, 0x23, 0x43, 0x44, 0x0f, 0x4b, 0x70, 0x1d, 0xb8, 0x19, - 0x7e, 0x74, 0xf6, 0x36, 0x8e, 0xe4, 0xe2, 0x73, 0xf5, 0xf3, 0x67, 0xdb, 0x60, 0x71, 0xed, 0xf6, 0xf2, 0x02, 0xc8, - 0x44, 0x3e, 0xea, 0x48, 0xbc, 0xa2, 0x01, 0x1a, 0xa7, 0xd7, 0x80, 0x11, 0xa7, 0x2c, 0x7d, 0x41, 0x87, 0x89, 0xca, - 0x23, 0xf5, 0xa0, 0x11, 0x3f, 0xc2, 0x90, 0xed, 0xb2, 0xac, 0x89, 0xb4, 0x30, 0xda, 0xb7, 0x40, 0xe1, 0x04, 0x58, - 0xb9, 0x0d, 0x0b, 0xf4, 0x6b, 0x21, 0x23, 0xaf, 0x81, 0x86, 0xfa, 0x7c, 0xf3, 0xda, 0xdf, 0x4f, 0xf4, 0x4f, 0x8b, - 0xe6, 0x90, 0x96, 0xd4, 0x23, 0xbf, 0x0f, 0xb6, 0xc7, 0xd6, 0xe2, 0xe7, 0x9d, 0xaf, 0x32, 0xa6, 0x25, 0x18, 0x91, - 0x77, 0x63, 0x08, 0xf9, 0x20, 0xc7, 0x2a, 0x08, 0x25, 0x5f, 0xab, 0x5a, 0x3b, 0xc4, 0x7a, 0xca, 0xdb, 0x14, 0x79, - 0xdb, 0x7c, 0x54, 0x51, 0x58, 0xad, 0xc0, 0xfe, 0xaa, 0xa1, 0xac, 0xc4, 0x0b, 0xfd, 0x57, 0x42, 0xa2, 0x0a, 0x89, - 0x45, 0x07, 0x3d, 0x12, 0xce, 0x3f, 0x08, 0x51, 0xd0, 0xe5, 0x96, 0x6a, 0xd9, 0x6e, 0x5f, 0x1a, 0x0a, 0x57, 0x81, - 0x58, 0x60, 0xb7, 0xf1, 0xbc, 0xad, 0xe3, 0x45, 0x1c, 0x97, 0x99, 0xb5, 0x6f, 0xbc, 0xe2, 0x2b, 0xec, 0x05, 0x81, - 0xfd, 0x1a, 0xce, 0x9a, 0xfc, 0xdf, 0xcf, 0xf0, 0x9a, 0x99, 0xc5, 0xcd, 0xc5, 0xf0, 0x6f, 0x67, 0xb3, 0xfc, 0x62, - 0x78, 0xb3, 0xd9, 0x21, 0xb5, 0x98, 0xd3, 0x68, 0xda, 0x7c, 0x78, 0xfd, 0xf0, 0xf2, 0x20, 0x9d, 0xde, 0xf3, 0x93, - 0xbc, 0x75, 0x76, 0x71, 0x0c, 0x59, 0xf0, 0x09, 0x3f, 0x6b, 0xb0, 0x39, 0xfb, 0xaf, 0xad, 0xd0, 0x1e, 0xd7, 0xde, - 0x33, 0xbb, 0x12, 0xab, 0xd3, 0xd8, 0xeb, 0xed, 0xbe, 0x9a, 0x02, 0xfe, 0x13, 0x81, 0x26, 0xbe, 0xf2, 0xc9, 0xa4, - 0x14, 0x07, 0x40, 0xa0, 0xba, 0x35, 0xf8, 0x7b, 0x18, 0x8c, 0x32, 0x92, 0xf1, 0xf6, 0x13, 0x92, 0xc8, 0xc6, 0xe1, - 0xe9, 0xdc, 0x42, 0xb1, 0x1e, 0xe9, 0xfb, 0x3c, 0xcd, 0xb4, 0x7e, 0x5b, 0x46, 0xd5, 0xa9, 0x81, 0x2c, 0x68, 0x9c, - 0x69, 0x10, 0xac, 0x7f, 0xdb, 0x58, 0x9d, 0x59, 0xf8, 0x66, 0x21, 0xa2, 0x59, 0x16, 0xff, 0x78, 0x4e, 0xb6, 0xd0, - 0xa0, 0xc0, 0x8f, 0x9a, 0x66, 0xde, 0xb5, 0x6e, 0x75, 0x01, 0x21, 0xef, 0x96, 0xa7, 0xf5, 0xa5, 0x3f, 0xff, 0x82, - 0x35, 0xbb, 0xf1, 0x5f, 0x5d, 0x8f, 0xd6, 0x8b, 0x10, 0x25, 0x5b, 0x81, 0x00, 0x71, 0xb1, 0x8d, 0xe3, 0x2d, 0x79, - 0xe3, 0x34, 0x17, 0xc9, 0x3c, 0x7c, 0x75, 0x92, 0x66, 0x05, 0xa1, 0x9a, 0xdf, 0x26, 0xf1, 0x0a, 0xd4, 0x59, 0x89, - 0x8f, 0x8a, 0x77, 0xe3, 0xde, 0xf5, 0xc4, 0xf6, 0xbf, 0xf2, 0x25, 0x14, 0xc4, 0xf7, 0xfb, 0x16, 0xe8, 0x86, 0x9f, - 0x30, 0xc5, 0xdb, 0x8f, 0xd7, 0xe3, 0x37, 0xf9, 0xad, 0xc0, 0x3d, 0x16, 0x78, 0x67, 0xbd, 0x34, 0x97, 0xf2, 0x24, - 0x41, 0x66, 0x05, 0xae, 0xb8, 0xec, 0x07, 0x0f, 0x96, 0x2d, 0x4d, 0x80, 0x66, 0xab, 0xc8, 0x00, 0x19, 0xca, 0x25, - 0x08, 0x69, 0x83, 0x8c, 0xfe, 0x2d, 0x88, 0xa2, 0x24, 0xc7, 0xa7, 0xb3, 0x27, 0xd1, 0x0d, 0x95, 0x3e, 0x39, 0x32, - 0xb0, 0xb2, 0x0e, 0x50, 0x4b, 0x32, 0x54, 0x88, 0x84, 0x90, 0x64, 0x02, 0x60, 0x9f, 0x14, 0x1a, 0x0a, 0x9f, 0x6b, - 0x39, 0xed, 0xfc, 0xc2, 0xb7, 0x4c, 0x90, 0x78, 0x4c, 0x8e, 0x5a, 0xc9, 0x84, 0xb6, 0x7b, 0xad, 0xf9, 0xe8, 0xee, - 0xe2, 0xa9, 0x5d, 0x1c, 0x63, 0x3e, 0xf2, 0x3f, 0x4a, 0x73, 0x22, 0xf2, 0xb5, 0x0e, 0xc0, 0x4a, 0xde, 0x0a, 0x94, - 0x2d, 0x6f, 0x98, 0x17, 0x58, 0xfc, 0x56, 0x4b, 0x76, 0xf5, 0x0c, 0x02, 0xb4, 0x21, 0x9c, 0xb4, 0xe3, 0x5c, 0xe1, - 0xba, 0x99, 0x62, 0x0d, 0xe5, 0xf5, 0x0a, 0x47, 0x15, 0x9a, 0x26, 0xc6, 0x74, 0x73, 0x2d, 0x7a, 0x31, 0xf5, 0x9a, - 0x7a, 0x42, 0x92, 0xbc, 0x08, 0x67, 0xd5, 0x9e, 0xae, 0xfd, 0x67, 0x06, 0x48, 0x3d, 0x27, 0x17, 0xca, 0x36, 0x17, - 0xe3, 0xbb, 0x79, 0xe3, 0x59, 0xc6, 0xcd, 0xbd, 0x57, 0x6b, 0xaf, 0x9e, 0x67, 0xb7, 0x98, 0x8f, 0x25, 0xe4, 0xd3, - 0x0e, 0x31, 0x37, 0xb2, 0x50, 0x72, 0x84, 0x71, 0xd7, 0x86, 0x21, 0x13, 0x37, 0x2e, 0x2c, 0x98, 0x90, 0x1e, 0x1b, - 0x89, 0x71, 0x90, 0x35, 0xdf, 0xd5, 0x7e, 0x71, 0x7c, 0xfb, 0xa3, 0xb8, 0x48, 0x0b, 0xf6, 0xf0, 0xa4, 0xb3, 0x5f, - 0xf9, 0x4c, 0xa3, 0x6e, 0x23, 0x47, 0x02, 0x51, 0x0c, 0x44, 0x02, 0xba, 0x56, 0xa9, 0xd0, 0xcb, 0x8a, 0x79, 0xa8, - 0xc0, 0x67, 0x2d, 0xb4, 0x51, 0xc1, 0xaa, 0x57, 0xf8, 0x89, 0x08, 0x65, 0xa6, 0xd6, 0x6b, 0x80, 0x5c, 0x64, 0x6b, - 0xad, 0x9f, 0xf5, 0x76, 0x6d, 0xb8, 0x9c, 0x27, 0xf0, 0x57, 0xef, 0xe2, 0xd6, 0xc7, 0x04, 0x5d, 0x6e, 0xed, 0x9f, - 0x68, 0xcf, 0x32, 0x46, 0x12, 0x55, 0x9e, 0xc3, 0xd3, 0x0a, 0xe4, 0xeb, 0x8e, 0x34, 0x5e, 0x62, 0x43, 0xf6, 0x16, - 0xa5, 0x9f, 0x52, 0xc6, 0xbd, 0xfc, 0xa4, 0xd8, 0x03, 0xf6, 0xdc, 0x03, 0x82, 0x35, 0xfb, 0x5a, 0x5f, 0x6e, 0x4d, - 0xd3, 0x60, 0xff, 0xa3, 0x03, 0x4f, 0x40, 0xd9, 0xbe, 0x1c, 0x47, 0x18, 0x8f, 0xdc, 0x92, 0x31, 0x65, 0x08, 0x39, - 0xc1, 0x62, 0xbb, 0xd7, 0x1d, 0x6b, 0x68, 0x39, 0x95, 0x28, 0x16, 0x49, 0xee, 0x7e, 0x94, 0xce, 0x68, 0xff, 0xd4, - 0x4e, 0x25, 0xb4, 0xf5, 0xb7, 0x9a, 0x9d, 0x14, 0x4d, 0xd7, 0xf5, 0x0e, 0xe8, 0x3c, 0x4a, 0x94, 0x4f, 0x2c, 0x8f, - 0x5d, 0x7e, 0x79, 0xb7, 0x6b, 0x64, 0xbb, 0x29, 0xb7, 0xb5, 0x37, 0x1a, 0xa9, 0x18, 0x69, 0xe8, 0x81, 0xed, 0x70, - 0xd9, 0x29, 0x6d, 0x02, 0x22, 0x64, 0x54, 0x2f, 0x8e, 0xa4, 0x96, 0xfa, 0x42, 0x9c, 0x75, 0xe7, 0x23, 0xad, 0x68, - 0x2f, 0x82, 0x02, 0x10, 0x5a, 0x1d, 0xa9, 0x92, 0x35, 0x5c, 0x97, 0x11, 0x6c, 0x0f, 0xe3, 0xf5, 0x0d, 0x14, 0x55, - 0x79, 0x7a, 0x2d, 0xd8, 0x8a, 0x1f, 0xc7, 0xa6, 0xf0, 0xb0, 0x8b, 0x0c, 0xf6, 0xe0, 0x66, 0x8e, 0x13, 0x3c, 0x5d, - 0x9b, 0xd3, 0x92, 0x3d, 0xd9, 0x20, 0xb3, 0xe6, 0xeb, 0xdb, 0x21, 0x5e, 0xb8, 0x71, 0x3d, 0x2c, 0xd9, 0x25, 0x1c, - 0x5c, 0xfa, 0x04, 0x3e, 0xf8, 0xb5, 0x1d, 0xb3, 0x41, 0xa1, 0xab, 0xcb, 0x09, 0xf6, 0x92, 0xc6, 0xe7, 0xf9, 0x6f, - 0x66, 0x73, 0x51, 0xb2, 0x02, 0xac, 0xbd, 0xba, 0x6f, 0x11, 0x2e, 0x73, 0x07, 0x5f, 0xfe, 0x3f, 0x75, 0xd4, 0x76, - 0xf3, 0xf9, 0x2d, 0x9c, 0x9b, 0x1c, 0x3c, 0xc3, 0x21, 0xea, 0xf2, 0x40, 0xae, 0x5c, 0xbf, 0xfa, 0x4f, 0xa0, 0xe4, - 0x9d, 0x4e, 0x9a, 0x7f, 0xdd, 0x77, 0x61, 0x31, 0x36, 0x76, 0xd9, 0x3e, 0xe2, 0x84, 0xd1, 0x75, 0xa2, 0xd0, 0x7e, - 0xcf, 0xc4, 0xb6, 0x1a, 0x64, 0x04, 0x8b, 0x90, 0xd7, 0x77, 0xb6, 0x00, 0xf4, 0xfd, 0x65, 0x0f, 0x8b, 0xb7, 0x7e, - 0x45, 0xe2, 0x4d, 0xb1, 0xf0, 0xef, 0x47, 0x64, 0xe1, 0xda, 0xfe, 0x8a, 0x03, 0x04, 0xdb, 0x5a, 0xfb, 0x5a, 0xdc, - 0x72, 0xfb, 0xe8, 0x04, 0x20, 0x28, 0x61, 0x2d, 0x9e, 0x44, 0xed, 0x5f, 0x22, 0x23, 0x52, 0xf7, 0x19, 0x33, 0x35, - 0x4c, 0xc4, 0x9d, 0x15, 0xc7, 0xb0, 0xd2, 0x7d, 0x74, 0xe5, 0x36, 0xb9, 0x1a, 0x44, 0xd1, 0x1e, 0x9a, 0x88, 0x3b, - 0x36, 0x04, 0x79, 0x4f, 0xc8, 0x63, 0x81, 0xaa, 0xac, 0xc2, 0x96, 0x47, 0x29, 0x82, 0xe1, 0x39, 0x74, 0x01, 0xb6, - 0x52, 0xd4, 0x3a, 0x73, 0xc9, 0xe2, 0xc4, 0x81, 0xd7, 0x8f, 0x07, 0xbc, 0x1a, 0xdd, 0xcd, 0x91, 0x40, 0xdc, 0x49, - 0xb2, 0x5b, 0x50, 0xf5, 0xe6, 0x65, 0xe8, 0x56, 0x3c, 0xaf, 0x14, 0x77, 0xa3, 0xad, 0xbe, 0x0d, 0x21, 0x22, 0x0e, - 0xd1, 0xae, 0x1d, 0xa5, 0x07, 0x74, 0x20, 0x8b, 0x2e, 0xaa, 0x9a, 0x94, 0xe0, 0xbf, 0x29, 0xb3, 0x36, 0xa1, 0x86, - 0x09, 0x05, 0x05, 0xe7, 0x6c, 0xdc, 0x4a, 0xf8, 0xf4, 0x46, 0xc6, 0xdc, 0x52, 0xe0, 0x55, 0x68, 0x6e, 0xaa, 0x03, - 0xb9, 0x22, 0x1a, 0x74, 0xc9, 0xb5, 0xed, 0x32, 0xc7, 0x87, 0x59, 0xbb, 0xf0, 0xfc, 0xb9, 0xd8, 0x2f, 0x95, 0x52, - 0xe4, 0xa5, 0xa0, 0x10, 0x71, 0x6a, 0xa3, 0x12, 0x9a, 0xfa, 0x00, 0xd6, 0x74, 0x44, 0x70, 0x67, 0x3c, 0x7a, 0x87, - 0x48, 0xf2, 0x3f, 0x95, 0x52, 0x67, 0x23, 0x79, 0x04, 0x4c, 0xeb, 0x81, 0x49, 0xfd, 0x92, 0x6d, 0x81, 0xe0, 0xf0, - 0x40, 0x7f, 0x0c, 0x14, 0xc9, 0x13, 0x89, 0x58, 0x50, 0xc7, 0xd3, 0xa8, 0x6f, 0xec, 0x4b, 0xb5, 0x27, 0xf7, 0x76, - 0x7c, 0xd6, 0x1e, 0x7b, 0x88, 0x24, 0x63, 0x7e, 0x10, 0x41, 0x12, 0x24, 0xc2, 0x18, 0x8b, 0x3c, 0xc4, 0x40, 0x34, - 0x3f, 0xb9, 0xc1, 0xe0, 0x54, 0x53, 0x6d, 0xfd, 0x58, 0xa2, 0x23, 0x10, 0xa8, 0xcb, 0x34, 0xaa, 0xd8, 0xaa, 0x4c, - 0x10, 0xcc, 0x67, 0xfd, 0xbb, 0x76, 0x44, 0x60, 0xa6, 0x1d, 0x03, 0xb4, 0xc9, 0x1b, 0xcc, 0x47, 0x44, 0x66, 0xcb, - 0xce, 0x27, 0x89, 0x09, 0xa6, 0xae, 0xda, 0x23, 0xb3, 0x71, 0xc6, 0xc9, 0xa6, 0xe9, 0xd4, 0xee, 0xaa, 0x32, 0xb8, - 0x08, 0x2f, 0x5e, 0xa2, 0x11, 0x80, 0xe8, 0x5a, 0xbe, 0x16, 0x9e, 0x1c, 0x08, 0x20, 0xcc, 0x2d, 0x0d, 0xfc, 0x96, - 0x69, 0xfb, 0x27, 0x5d, 0xab, 0x1b, 0x22, 0x36, 0x0a, 0x11, 0xfe, 0xd3, 0x04, 0xd9, 0xf5, 0x5b, 0xab, 0x1d, 0xfb, - 0xfb, 0x4e, 0x5b, 0xf6, 0x5b, 0x8b, 0x59, 0x4a, 0x43, 0x17, 0xc2, 0x86, 0x61, 0x6b, 0x35, 0x14, 0x56, 0xcb, 0x59, - 0x73, 0xe8, 0x80, 0xcc, 0xbc, 0x10, 0x90, 0x65, 0xee, 0x57, 0x3e, 0x42, 0x67, 0x07, 0xf6, 0x3f, 0xf2, 0x9d, 0xe4, - 0x1c, 0x1b, 0x76, 0x88, 0xaf, 0x77, 0xc1, 0xa2, 0x89, 0xac, 0x24, 0x94, 0x8f, 0xa0, 0x7c, 0xae, 0x5d, 0x5a, 0x47, - 0x6a, 0xe7, 0x46, 0x87, 0x46, 0x06, 0xfc, 0xc1, 0x98, 0x09, 0x1c, 0x88, 0x40, 0x2f, 0x05, 0xdd, 0x87, 0xef, 0x3b, - 0x26, 0xd3, 0x6f, 0x0d, 0x04, 0xff, 0xfe, 0x8d, 0xfb, 0x2d, 0x25, 0x60, 0x09, 0x88, 0x3b, 0x2d, 0xa0, 0x1b, 0xc4, - 0xfc, 0x7a, 0x69, 0x88, 0xc9, 0x8b, 0x43, 0x1b, 0xbd, 0x2c, 0x64, 0x78, 0xed, 0xc1, 0xc3, 0xe7, 0x99, 0xf7, 0xb2, - 0x53, 0x71, 0x86, 0x6b, 0xb3, 0x9b, 0x5e, 0xe2, 0xb6, 0xe3, 0xd7, 0x23, 0xbf, 0x45, 0xdc, 0xc0, 0xcd, 0x6e, 0x50, - 0xe6, 0x21, 0xcc, 0x3c, 0x0b, 0xdc, 0xa3, 0x61, 0x4a, 0x7f, 0xc3, 0x42, 0xac, 0x1b, 0xb2, 0xf5, 0x99, 0xc1, 0xea, - 0xb6, 0x8a, 0x41, 0x2c, 0x4f, 0x72, 0x3c, 0xc1, 0xc8, 0x42, 0xba, 0x61, 0x91, 0x93, 0x84, 0x37, 0x49, 0x1c, 0x71, - 0xaf, 0x8d, 0xd9, 0x56, 0x60, 0xea, 0x10, 0x1a, 0x72, 0x7b, 0xfc, 0xbe, 0x0b, 0x09, 0x66, 0x1e, 0x67, 0xa9, 0x8a, - 0x46, 0xea, 0xed, 0x5f, 0x3c, 0xb1, 0x47, 0xf5, 0x11, 0x6a, 0x7b, 0xcb, 0x92, 0xdb, 0xd5, 0xbf, 0xf7, 0xad, 0xd3, - 0x80, 0x5e, 0x30, 0x73, 0xc3, 0x70, 0xdc, 0x37, 0x36, 0x00, 0xd9, 0x48, 0x0a, 0x0c, 0x84, 0xd5, 0x08, 0x56, 0xd2, - 0x62, 0xec, 0xe9, 0x5d, 0xfd, 0xec, 0x18, 0x01, 0x2e, 0x81, 0xf5, 0x63, 0xa5, 0xb0, 0xe1, 0x14, 0xec, 0x7a, 0x03, - 0xf4, 0xdd, 0x76, 0x7b, 0x14, 0x4a, 0x93, 0x1b, 0x1a, 0x78, 0x9f, 0x0d, 0x04, 0x36, 0xfd, 0x14, 0xcf, 0xa1, 0x77, - 0x5d, 0xbf, 0xee, 0xfd, 0xbd, 0x31, 0x10, 0x21, 0xad, 0x91, 0xa0, 0xb5, 0xef, 0x7b, 0x2f, 0x69, 0x66, 0x65, 0x94, - 0xa1, 0x29, 0xdb, 0x54, 0xfb, 0x69, 0x38, 0xb6, 0x2d, 0x8b, 0x40, 0xed, 0x00, 0xaf, 0x5c, 0xe7, 0xe0, 0x3a, 0x53, - 0x14, 0xba, 0x12, 0x1f, 0x4a, 0x27, 0x78, 0xb7, 0x8d, 0x62, 0x12, 0x10, 0xe7, 0x07, 0x2b, 0xb8, 0x41, 0xc8, 0x59, - 0x23, 0x04, 0xd6, 0x66, 0xbb, 0xeb, 0x23, 0xd3, 0x95, 0xf8, 0xb5, 0x07, 0x59, 0x43, 0xa5, 0xa8, 0x14, 0xb8, 0xb4, - 0x38, 0x25, 0x79, 0xd2, 0x60, 0x78, 0x5d, 0x3f, 0xad, 0x69, 0x55, 0x25, 0xbe, 0xd6, 0xc5, 0x4e, 0xa9, 0x80, 0xb9, - 0xcf, 0xe9, 0xa9, 0x75, 0xa4, 0x78, 0x6b, 0xad, 0xad, 0x4f, 0x18, 0xe6, 0xf6, 0xde, 0x69, 0x0f, 0x20, 0x7f, 0xcc, - 0x67, 0x26, 0xc1, 0xc0, 0x88, 0x30, 0xc0, 0x5b, 0xa2, 0x97, 0x33, 0x26, 0x4f, 0xd0, 0x4c, 0x5f, 0xdc, 0xa3, 0xdc, - 0xbb, 0xdc, 0x7d, 0xca, 0x37, 0x2a, 0xb3, 0x47, 0x37, 0x5d, 0x04, 0xb4, 0xd6, 0x4d, 0x94, 0x1a, 0x1e, 0xc7, 0xb5, - 0xcb, 0x0b, 0xb1, 0x94, 0xc4, 0xeb, 0x10, 0xcd, 0xbf, 0xcb, 0x4f, 0x0e, 0x9b, 0x94, 0x95, 0x25, 0xdf, 0x19, 0x4b, - 0xc3, 0x8f, 0x15, 0xf2, 0xc2, 0x46, 0xaa, 0x01, 0x14, 0x57, 0x7a, 0x1d, 0xed, 0x64, 0xed, 0x5d, 0x56, 0x41, 0xa3, - 0x54, 0xc8, 0xd1, 0xa3, 0x35, 0x70, 0x94, 0x3a, 0x21, 0xd9, 0xc0, 0x5b, 0x60, 0x26, 0xaf, 0x0c, 0x4e, 0x01, 0xb5, - 0xf2, 0x48, 0x78, 0xe6, 0x42, 0x5e, 0x9a, 0xfc, 0x4c, 0xde, 0x8d, 0xc0, 0x78, 0xca, 0x07, 0x9e, 0xb8, 0xb0, 0x4c, - 0xfc, 0xb7, 0xec, 0x0f, 0x10, 0x95, 0x4c, 0x06, 0x15, 0x08, 0x4c, 0x83, 0x5d, 0x7c, 0x2d, 0x8d, 0xd4, 0x7a, 0x08, - 0xc1, 0xc9, 0xd5, 0x46, 0x7f, 0x30, 0xeb, 0x6b, 0x40, 0xa9, 0x7a, 0x83, 0x8a, 0x46, 0xec, 0xca, 0xf6, 0xd3, 0xbc, - 0x3e, 0x98, 0xa8, 0x7d, 0xa3, 0x81, 0x1b, 0xb6, 0xf9, 0xd5, 0x1e, 0xc5, 0xae, 0x8d, 0xe7, 0x4b, 0x60, 0x13, 0xb5, - 0xbc, 0x65, 0x52, 0x14, 0x1c, 0xda, 0x34, 0xa8, 0x76, 0x04, 0x23, 0x66, 0xba, 0x83, 0xce, 0x5b, 0xdb, 0x20, 0x3a, - 0x1d, 0x9c, 0x46, 0xd0, 0x19, 0x8c, 0x8b, 0x53, 0x5b, 0x35, 0x42, 0x49, 0x8c, 0x2f, 0xc7, 0xd0, 0x2f, 0xb2, 0x78, - 0xa3, 0x66, 0xda, 0x00, 0x5d, 0x49, 0x05, 0xf3, 0x6c, 0xc4, 0x4c, 0x0a, 0xb7, 0xec, 0xb9, 0x5d, 0x8a, 0xff, 0xa5, - 0x3b, 0xd7, 0xf7, 0x3c, 0x11, 0xe4, 0x03, 0x59, 0x3a, 0x0e, 0xfe, 0xb5, 0x98, 0xe1, 0xe7, 0x19, 0x8c, 0x5e, 0x64, - 0xd6, 0xc6, 0x2c, 0xc9, 0x17, 0x7c, 0x67, 0xf8, 0xa5, 0x06, 0x93, 0x9f, 0xb0, 0x9c, 0x21, 0xfa, 0x1a, 0x04, 0x38, - 0x72, 0xb5, 0xeb, 0x69, 0xc3, 0x78, 0x07, 0x8b, 0x17, 0xc5, 0x02, 0x51, 0xd4, 0xfb, 0x6a, 0x8e, 0xc3, 0xe2, 0x9c, - 0xa4, 0x04, 0x33, 0x9b, 0x1a, 0x49, 0x21, 0x64, 0xef, 0x9b, 0x93, 0x57, 0x56, 0x1a, 0x52, 0x9c, 0xc0, 0xcb, 0x81, - 0x5e, 0x23, 0xd2, 0xf1, 0xb1, 0x3a, 0x6b, 0x28, 0x4e, 0x1a, 0x99, 0x62, 0x36, 0xb1, 0x90, 0xce, 0xaa, 0x07, 0x1b, - 0xf3, 0x69, 0x91, 0x2b, 0xaf, 0xeb, 0x08, 0x7f, 0xad, 0xc2, 0x70, 0x96, 0x5e, 0x6f, 0xbe, 0x18, 0x06, 0x1d, 0xfe, - 0xaf, 0xd5, 0x84, 0x6f, 0xf0, 0x6d, 0x3f, 0x5f, 0x44, 0x44, 0xa8, 0xca, 0x0f, 0x74, 0xa2, 0x1d, 0xea, 0xe8, 0x34, - 0xf4, 0xd0, 0xcc, 0x56, 0x50, 0xb0, 0x48, 0xfb, 0x7d, 0x37, 0xbd, 0xf5, 0x35, 0x39, 0x7b, 0xe7, 0xba, 0xa6, 0x35, - 0xc1, 0xfc, 0xf8, 0x35, 0xd0, 0x9a, 0x8d, 0x84, 0x93, 0xe5, 0xf7, 0xc8, 0xde, 0x6c, 0xaf, 0x76, 0x67, 0xd4, 0xbe, - 0x3e, 0x1a, 0xde, 0x34, 0x8f, 0x19, 0x1f, 0x65, 0x93, 0x26, 0x6a, 0x3a, 0x73, 0x2d, 0xe0, 0x73, 0x6a, 0xea, 0x4e, - 0x24, 0x3a, 0x70, 0x76, 0xb5, 0x3c, 0xc5, 0x6f, 0x45, 0x64, 0xfa, 0x35, 0x89, 0xea, 0x96, 0x66, 0x50, 0xe4, 0x52, - 0x5a, 0xa8, 0xba, 0xad, 0x2a, 0x80, 0x7d, 0x8d, 0xa8, 0x19, 0xa8, 0x31, 0x0b, 0xdd, 0x29, 0x1a, 0x21, 0x8d, 0xb5, - 0x8c, 0xed, 0x87, 0x9a, 0x76, 0xa5, 0xaa, 0x1e, 0xdb, 0x25, 0x0e, 0x45, 0x03, 0x34, 0x2d, 0xcc, 0xf5, 0x6f, 0x76, - 0x75, 0xb3, 0x6d, 0x4b, 0xbd, 0x41, 0x5c, 0xf2, 0x9f, 0x87, 0x2d, 0xac, 0x9d, 0x29, 0x85, 0xc3, 0x15, 0xad, 0xe8, - 0x91, 0x6c, 0x1c, 0xb4, 0x0a, 0x83, 0xa8, 0x51, 0x65, 0xda, 0x88, 0x61, 0x44, 0xc2, 0x08, 0x85, 0x42, 0xe1, 0x3e, - 0x62, 0x5d, 0x6c, 0xca, 0xa3, 0x87, 0xd2, 0xea, 0x92, 0x1f, 0xb3, 0x58, 0xa3, 0x79, 0x5a, 0x7b, 0x2c, 0x64, 0xa9, - 0xc3, 0xc7, 0x2b, 0xc1, 0xe8, 0xf7, 0xcb, 0x84, 0x56, 0x6e, 0x31, 0x41, 0xa9, 0x0e, 0x24, 0x76, 0x3b, 0x79, 0x8b, - 0xf4, 0x63, 0x8b, 0x42, 0x12, 0xb2, 0x3f, 0xbd, 0x2c, 0x93, 0xa7, 0x8a, 0xe1, 0x55, 0xe4, 0x2c, 0x47, 0x09, 0xf1, - 0x0e, 0xfc, 0xa4, 0x5f, 0x7f, 0x92, 0x7a, 0xad, 0xba, 0xad, 0x75, 0x54, 0xd4, 0xce, 0x6d, 0xe9, 0x86, 0x71, 0x9d, - 0x0c, 0xaa, 0xe0, 0x06, 0x4c, 0xd2, 0xe8, 0x5b, 0x27, 0xa8, 0x4f, 0x31, 0x9a, 0xf2, 0x6a, 0x07, 0x65, 0x2d, 0xc3, - 0x60, 0x8d, 0xf1, 0x61, 0xf8, 0xc0, 0x64, 0xc6, 0x18, 0x61, 0x6c, 0xc3, 0x1c, 0xf9, 0x6c, 0xfa, 0xeb, 0x17, 0x42, - 0xea, 0x4d, 0x12, 0x11, 0x81, 0x7c, 0x90, 0x7c, 0x30, 0x22, 0xfd, 0xa7, 0x25, 0x56, 0x3b, 0xbc, 0x70, 0x48, 0x9f, - 0xc4, 0x16, 0x0e, 0x84, 0xcd, 0xfa, 0xd1, 0x6f, 0x98, 0x64, 0xde, 0xbe, 0x38, 0x41, 0x7e, 0x09, 0x6e, 0xd8, 0xde, - 0x6a, 0x08, 0xaa, 0x18, 0xad, 0x10, 0xc4, 0x0a, 0x1a, 0x21, 0x9e, 0xc0, 0xf9, 0x26, 0x63, 0xd5, 0xab, 0x25, 0x2e, - 0x73, 0x45, 0x83, 0x7f, 0xf6, 0x6d, 0x5a, 0x24, 0x3d, 0x88, 0xf7, 0x03, 0x59, 0xcf, 0xb0, 0x87, 0xa0, 0xc7, 0xc2, - 0x8a, 0xe4, 0xbb, 0x42, 0x96, 0xae, 0xe3, 0xd3, 0x49, 0xaa, 0xf7, 0xa4, 0x5f, 0x3f, 0xc0, 0x1e, 0xb4, 0xa9, 0x2d, - 0x34, 0x7f, 0x85, 0xaa, 0x0a, 0xf3, 0x7a, 0x33, 0xca, 0xa3, 0x25, 0x9b, 0xee, 0x08, 0x74, 0x10, 0x08, 0xb5, 0xd6, - 0x4b, 0x03, 0x8c, 0xe3, 0xfb, 0xb0, 0x19, 0x3d, 0x7e, 0x5d, 0xc4, 0x84, 0xab, 0x97, 0x2d, 0x45, 0x69, 0x93, 0x46, - 0x8f, 0xfb, 0xae, 0x59, 0x76, 0x19, 0x22, 0x88, 0xc4, 0x1f, 0x47, 0xd0, 0x66, 0x5c, 0x0b, 0x17, 0xd1, 0x09, 0x86, - 0x96, 0x2b, 0x9e, 0xb8, 0x47, 0xdd, 0x2f, 0xbb, 0xe7, 0xdb, 0xe6, 0x49, 0x0c, 0x58, 0x8a, 0xf8, 0xae, 0xac, 0xcd, - 0x39, 0x94, 0xa2, 0x74, 0x9b, 0xc0, 0x2c, 0x47, 0x7a, 0x8c, 0x47, 0xf2, 0x48, 0xd4, 0x01, 0x83, 0x68, 0x54, 0x7c, - 0x67, 0x65, 0xe0, 0x6e, 0xad, 0xb5, 0xf8, 0xf2, 0xf7, 0x7e, 0xfd, 0x7a, 0xb7, 0x42, 0xbd, 0x0c, 0x5e, 0x4e, 0xed, - 0x19, 0xef, 0xbc, 0x20, 0xa5, 0xbe, 0x88, 0xc1, 0xeb, 0xc7, 0xbc, 0x8a, 0x66, 0xdf, 0x35, 0x04, 0xa1, 0x85, 0xcb, - 0x7f, 0x0b, 0x8f, 0x3a, 0x2d, 0xd3, 0xa5, 0xa7, 0xaf, 0xa6, 0x9b, 0x4e, 0x97, 0xef, 0xe8, 0xc1, 0xad, 0x10, 0x21, - 0x61, 0x54, 0x63, 0xed, 0x93, 0x73, 0x8b, 0xc9, 0x97, 0xd1, 0xda, 0xa5, 0x55, 0x51, 0xc1, 0xe7, 0x1c, 0xdd, 0x0d, - 0xaa, 0x5b, 0xb8, 0xa9, 0x72, 0xfb, 0xe8, 0xad, 0xa8, 0xa2, 0xa1, 0x87, 0x0b, 0xa7, 0x44, 0x12, 0x85, 0xc8, 0x4b, - 0x98, 0xd8, 0x7d, 0x37, 0xa4, 0x81, 0x71, 0x75, 0x75, 0x4a, 0x75, 0x83, 0xc7, 0xd0, 0xc3, 0x10, 0x24, 0xae, 0xd9, - 0xf9, 0xff, 0xd2, 0xeb, 0xc1, 0x9b, 0x97, 0x3e, 0x25, 0x99, 0x17, 0xfe, 0x5d, 0x5a, 0xb8, 0xc5, 0x17, 0xfc, 0x8c, - 0x96, 0xa0, 0x65, 0xcb, 0xa3, 0xb2, 0x03, 0xeb, 0xa1, 0x3d, 0xd0, 0xbf, 0xae, 0x27, 0x9b, 0x55, 0x00, 0x5a, 0x5b, - 0x9e, 0x64, 0x34, 0x31, 0x7a, 0x72, 0xde, 0xa1, 0x50, 0x44, 0x42, 0x0e, 0xa3, 0x44, 0xad, 0x75, 0x20, 0xc3, 0x55, - 0x77, 0x5a, 0x0a, 0xb7, 0xb1, 0xbb, 0x9e, 0x59, 0x88, 0xe8, 0x48, 0x2f, 0x49, 0x66, 0x2e, 0x34, 0x21, 0xa8, 0x92, - 0xc8, 0x0f, 0x88, 0x6d, 0x81, 0xe3, 0x41, 0x73, 0x62, 0xeb, 0xa3, 0xd0, 0x52, 0x40, 0x18, 0xb7, 0x57, 0xf1, 0x35, - 0x01, 0x84, 0xd2, 0xba, 0xf3, 0x66, 0xbb, 0x70, 0xf9, 0x37, 0x6d, 0x65, 0x0c, 0x36, 0x3a, 0x77, 0x56, 0x71, 0x81, - 0x5b, 0xdd, 0x8b, 0x21, 0x88, 0x02, 0x25, 0x05, 0x31, 0x9c, 0x04, 0xd5, 0x07, 0x73, 0x20, 0x01, 0x97, 0xc8, 0x83, - 0x52, 0xe3, 0x5c, 0xb8, 0xf1, 0x46, 0x21, 0xc4, 0x62, 0x24, 0xaa, 0x62, 0xb2, 0x41, 0x70, 0x4c, 0x05, 0xda, 0xfd, - 0xf4, 0xdc, 0x7b, 0xe1, 0xfe, 0xa1, 0xa6, 0x56, 0x73, 0xa1, 0x08, 0xa3, 0xdd, 0xc9, 0xbd, 0xa0, 0x85, 0x64, 0xab, - 0x5e, 0xae, 0x91, 0xbd, 0xf0, 0xcd, 0x73, 0xef, 0x2b, 0x25, 0x20, 0xec, 0xdf, 0x19, 0x07, 0x02, 0x60, 0x2e, 0xed, - 0x6a, 0x2d, 0xd1, 0xdf, 0x9e, 0x48, 0xb3, 0xa1, 0xa5, 0x58, 0x37, 0xf3, 0x50, 0x01, 0xd6, 0xd4, 0xea, 0x09, 0x4b, - 0x59, 0xe5, 0x8d, 0x66, 0xa7, 0x86, 0xb7, 0x1d, 0x74, 0x75, 0x92, 0xc2, 0x93, 0xee, 0xff, 0xbd, 0x1f, 0x5e, 0xab, - 0x6e, 0x85, 0xa0, 0x3a, 0x93, 0x74, 0x16, 0x32, 0xd5, 0x7a, 0x1a, 0x53, 0x9c, 0xa4, 0xef, 0x04, 0x45, 0x45, 0x68, - 0xfc, 0x53, 0xd1, 0xd9, 0xf8, 0xa9, 0xeb, 0x03, 0xf7, 0x03, 0x2e, 0x28, 0xbe, 0xc9, 0x3a, 0x7e, 0x98, 0x45, 0x44, - 0x64, 0xe5, 0x67, 0xbb, 0xbc, 0x76, 0xdd, 0xa6, 0x33, 0xf3, 0xd2, 0x6d, 0x74, 0x9b, 0x7f, 0x83, 0x25, 0x1f, 0x8a, - 0x92, 0x97, 0xb4, 0x85, 0xa3, 0x5f, 0xe0, 0x7a, 0x28, 0xd3, 0x81, 0x21, 0x73, 0xeb, 0xba, 0xfe, 0x51, 0x31, 0xd2, - 0xd4, 0x11, 0x4f, 0x99, 0x43, 0x05, 0x9e, 0x9a, 0x9b, 0x4a, 0x0e, 0x94, 0xce, 0x30, 0x5f, 0x13, 0xe1, 0xcd, 0xde, - 0x31, 0xfd, 0x73, 0x41, 0x74, 0x7c, 0x04, 0xd3, 0x86, 0x7c, 0x58, 0x85, 0xe7, 0xe2, 0x58, 0xfd, 0x60, 0x35, 0x89, - 0x3c, 0x89, 0x03, 0xbc, 0x0f, 0x2c, 0x52, 0x61, 0x62, 0xe0, 0x6b, 0x76, 0x3b, 0xce, 0x17, 0x80, 0x19, 0x0f, 0xb9, - 0x4f, 0x77, 0xfc, 0x10, 0x04, 0x8e, 0x17, 0xaa, 0xc5, 0xcd, 0xe1, 0x2d, 0x08, 0x80, 0x8c, 0x59, 0x71, 0x5a, 0x8c, - 0xf2, 0x24, 0x25, 0xe0, 0x99, 0x5c, 0xba, 0x55, 0x43, 0x2a, 0xb3, 0x3f, 0x04, 0x94, 0x4b, 0xd7, 0x42, 0x0a, 0x6e, - 0xd5, 0x17, 0xa6, 0x84, 0x74, 0xd7, 0x68, 0xb0, 0x85, 0x7f, 0x2c, 0x88, 0x25, 0x0d, 0xea, 0x1a, 0xbf, 0xed, 0x57, - 0xee, 0xa4, 0x73, 0xe2, 0x3a, 0x4a, 0x5d, 0x22, 0x89, 0xfb, 0x3c, 0x8c, 0x04, 0x82, 0x99, 0x3d, 0x21, 0xb2, 0x18, - 0x62, 0x1f, 0x47, 0x3b, 0x02, 0xf0, 0x04, 0xa2, 0x23, 0xcf, 0xec, 0x5e, 0x40, 0x7c, 0x7a, 0x82, 0xb0, 0x2c, 0x7f, - 0x23, 0xe3, 0xd7, 0xd7, 0xc3, 0xec, 0x89, 0x62, 0x78, 0x25, 0xf1, 0x54, 0xc5, 0x12, 0x49, 0x43, 0x6b, 0xc0, 0xd2, - 0x15, 0xc9, 0x65, 0xe4, 0x19, 0x71, 0x7e, 0x66, 0x7d, 0x02, 0x7e, 0xec, 0x63, 0x38, 0xf0, 0xeb, 0x40, 0x5f, 0xa4, - 0x54, 0xf9, 0x36, 0x12, 0xe7, 0xd5, 0x7b, 0x73, 0xfd, 0x70, 0x27, 0xe9, 0xea, 0xd5, 0xa3, 0x6d, 0x68, 0x6c, 0x92, - 0xf4, 0x6f, 0xcd, 0x43, 0x80, 0x63, 0x9d, 0xa4, 0x33, 0x14, 0xc6, 0x64, 0x79, 0xd8, 0xb0, 0xea, 0x62, 0xe8, 0xce, - 0x03, 0xee, 0xa6, 0xba, 0x23, 0x75, 0xf8, 0xd2, 0xa4, 0x27, 0x85, 0x59, 0xd2, 0xd8, 0x25, 0xe9, 0xdf, 0xaa, 0x74, - 0x38, 0x54, 0x29, 0x46, 0xe4, 0xb2, 0x22, 0x46, 0xa6, 0x1d, 0xdc, 0x49, 0xfc, 0xb6, 0xe4, 0x9d, 0x80, 0x97, 0x36, - 0xf5, 0x79, 0x57, 0x2b, 0x26, 0xb4, 0x8c, 0xc9, 0x93, 0xb7, 0x76, 0x58, 0x69, 0xa1, 0x54, 0xb2, 0x40, 0x36, 0x65, - 0xa1, 0x51, 0xf0, 0x53, 0xdf, 0xfc, 0xf0, 0x83, 0xa2, 0x32, 0x10, 0x70, 0x3b, 0x58, 0xfd, 0xe3, 0x83, 0x78, 0x19, - 0x43, 0x3c, 0x32, 0x32, 0xa6, 0x7f, 0xc9, 0x50, 0xf7, 0x4f, 0x20, 0x93, 0xf0, 0x75, 0x76, 0xbf, 0x34, 0xf7, 0x17, - 0x6a, 0x1d, 0x8c, 0xeb, 0x68, 0x43, 0x13, 0xf8, 0x26, 0x14, 0xee, 0x87, 0xca, 0xc0, 0x46, 0x29, 0x43, 0xbe, 0x2f, - 0x6d, 0x9e, 0x7b, 0xe2, 0x27, 0x41, 0xf1, 0x69, 0x86, 0x59, 0xc8, 0x08, 0xa0, 0xfa, 0x70, 0x32, 0xe9, 0xba, 0x43, - 0x6d, 0x7b, 0xab, 0xa9, 0x74, 0x76, 0xd4, 0x31, 0x41, 0xce, 0xf3, 0xa3, 0x19, 0x56, 0x9e, 0xbf, 0x36, 0xf9, 0x06, - 0x81, 0xcf, 0x9d, 0xf7, 0xa6, 0x5a, 0x07, 0x6a, 0xbf, 0x9c, 0x11, 0xb4, 0x2d, 0x03, 0x1c, 0xa9, 0x72, 0xa8, 0x8e, - 0x54, 0x0c, 0x2b, 0x33, 0xde, 0x98, 0xe2, 0xc5, 0x16, 0x7b, 0x9c, 0x2f, 0x21, 0x15, 0xb0, 0x1f, 0x90, 0xb2, 0xe4, - 0x98, 0xd5, 0x22, 0x65, 0x6f, 0x22, 0x05, 0x11, 0xca, 0x6f, 0x5e, 0x1e, 0xfc, 0xdd, 0x64, 0x84, 0x15, 0x58, 0xab, - 0x8e, 0x24, 0x5b, 0x9b, 0xc8, 0x69, 0x2d, 0xa9, 0x8a, 0xf3, 0x46, 0x19, 0x66, 0xbf, 0xeb, 0xcf, 0xcb, 0x26, 0x98, - 0xda, 0xc5, 0xa7, 0xe6, 0x60, 0x8d, 0x16, 0xa6, 0xa7, 0xc2, 0xfe, 0x82, 0x0f, 0x3d, 0x21, 0xbf, 0x19, 0xfc, 0xb2, - 0xaf, 0x6d, 0x18, 0x3c, 0x6a, 0x5f, 0x61, 0x43, 0xa5, 0x75, 0x31, 0xf5, 0xa2, 0x61, 0xb2, 0x2d, 0x7f, 0x7e, 0x2a, - 0xf7, 0x18, 0xb9, 0xc2, 0x8c, 0xc0, 0x1a, 0x95, 0x77, 0xc1, 0x01, 0xe1, 0x63, 0x44, 0x91, 0x1b, 0xb6, 0x45, 0x06, - 0x05, 0xdb, 0x46, 0xd3, 0xae, 0xf4, 0x31, 0x07, 0x79, 0x12, 0x84, 0x4e, 0x76, 0xc2, 0x3b, 0x5f, 0xbd, 0x32, 0x2c, - 0x8b, 0x24, 0xcd, 0x8b, 0xa8, 0xd2, 0x87, 0x55, 0xd5, 0x48, 0xe3, 0xbf, 0x00, 0x60, 0x14, 0xce, 0x97, 0xc2, 0xbf, - 0x29, 0x5c, 0xe3, 0x9d, 0xde, 0xaa, 0x91, 0x72, 0x8e, 0xc7, 0xbc, 0x9b, 0xb1, 0xc3, 0x0f, 0xc2, 0x97, 0xdc, 0xcf, - 0xa8, 0xc0, 0x3c, 0x2d, 0x0b, 0xb3, 0x35, 0xfc, 0x5a, 0x81, 0xdc, 0x3e, 0x12, 0xe7, 0x36, 0x6c, 0xa6, 0x53, 0x7b, - 0xd3, 0x97, 0x1b, 0x84, 0xcc, 0x19, 0xcd, 0xf2, 0xf5, 0x87, 0x87, 0x01, 0x75, 0x11, 0x7e, 0x3b, 0x16, 0xea, 0x51, - 0xb6, 0x74, 0xf0, 0x02, 0x1e, 0xae, 0x69, 0x29, 0x7a, 0xbe, 0xa9, 0x9d, 0xc8, 0x1f, 0x6f, 0x7c, 0x00, 0x6d, 0xef, - 0x75, 0x8c, 0x36, 0xd1, 0x43, 0x4a, 0x01, 0x22, 0x0b, 0x6d, 0xab, 0xaa, 0x66, 0xc8, 0xb2, 0x60, 0xb9, 0x0d, 0xbc, - 0xa7, 0x96, 0x08, 0x87, 0xef, 0xda, 0xd3, 0x85, 0x35, 0xfe, 0x58, 0x00, 0xfc, 0xfb, 0x8c, 0x88, 0x0a, 0xe5, 0x7f, - 0x87, 0xed, 0x19, 0x26, 0x22, 0xee, 0x08, 0xc9, 0x60, 0xc0, 0xc8, 0x43, 0x36, 0x23, 0x29, 0xd8, 0x6a, 0xa5, 0x00, - 0xbe, 0x87, 0x40, 0xe3, 0xba, 0x06, 0x21, 0xd8, 0xa0, 0xd7, 0x40, 0x3c, 0x1c, 0x2f, 0xa8, 0x6b, 0xbc, 0x36, 0x7e, - 0xbb, 0xd6, 0x9a, 0x30, 0xe2, 0xdb, 0xaa, 0x59, 0xbc, 0x56, 0x3d, 0x52, 0x39, 0x92, 0x10, 0x79, 0xa3, 0xa0, 0xd5, - 0x9b, 0x4e, 0xf7, 0xd3, 0x64, 0x44, 0x0a, 0x6a, 0x9d, 0x1b, 0x91, 0xf2, 0x4b, 0xb1, 0x39, 0xf5, 0x87, 0x94, 0x87, - 0x2c, 0x8f, 0xb9, 0x12, 0xd5, 0xb5, 0x08, 0x61, 0xd8, 0x75, 0xf4, 0xaf, 0xa1, 0x84, 0x21, 0x5f, 0x52, 0x19, 0x14, - 0x32, 0x53, 0x59, 0x20, 0x0d, 0xe5, 0x49, 0xe4, 0xee, 0x87, 0xe9, 0xea, 0xdd, 0xab, 0xdc, 0x27, 0xa9, 0x28, 0x89, - 0xdd, 0x85, 0x48, 0x93, 0x89, 0x37, 0xa6, 0xfd, 0xf6, 0x3f, 0x23, 0xe5, 0xdf, 0x54, 0x1d, 0x53, 0x8d, 0x25, 0xb1, - 0xd0, 0x00, 0xa5, 0x7c, 0xc4, 0xd3, 0x36, 0x5d, 0x8e, 0xa2, 0xad, 0xd2, 0x1e, 0x6a, 0x1e, 0x78, 0x58, 0x58, 0x13, - 0xc7, 0x11, 0xf4, 0x74, 0x84, 0xd8, 0x92, 0xda, 0x42, 0xd7, 0xa7, 0x99, 0x67, 0x45, 0x6d, 0x76, 0x8f, 0x54, 0xcb, - 0xe8, 0xa0, 0x35, 0x91, 0x34, 0xfb, 0xa9, 0xcb, 0x34, 0x90, 0x0a, 0x81, 0xef, 0x82, 0xdc, 0x2a, 0x4a, 0x5c, 0xaf, - 0xee, 0xdd, 0x43, 0xb5, 0xf2, 0x3b, 0xff, 0x74, 0x0b, 0x22, 0x23, 0x81, 0x81, 0x14, 0xd1, 0xbc, 0xa0, 0x9f, 0x18, - 0x96, 0xc1, 0x90, 0x33, 0x25, 0xb3, 0x9c, 0xb7, 0x00, 0xed, 0x91, 0xb6, 0x82, 0x0b, 0x12, 0x46, 0xe7, 0x58, 0x2b, - 0x83, 0xcf, 0x91, 0x22, 0x5f, 0xb5, 0xc5, 0xcc, 0x5e, 0xdd, 0xd3, 0x02, 0x53, 0x01, 0xac, 0x2b, 0x05, 0xcb, 0x59, - 0xdf, 0x28, 0xaa, 0xd8, 0xc8, 0xe4, 0xc7, 0x5f, 0xd0, 0x3d, 0xa5, 0x0c, 0x9d, 0x15, 0xae, 0x34, 0x6d, 0x3b, 0x97, - 0xc7, 0xee, 0x83, 0x02, 0x7c, 0xa2, 0x81, 0xcc, 0x4b, 0xf2, 0x9f, 0x9d, 0x6d, 0xd8, 0x7d, 0x52, 0xce, 0x77, 0x13, - 0xfd, 0xde, 0x48, 0xb3, 0xbf, 0x2e, 0x75, 0x28, 0xdb, 0xaf, 0x3c, 0xae, 0x5a, 0xe6, 0x3d, 0xd2, 0xe7, 0xc6, 0x64, - 0x44, 0x26, 0xb4, 0xcb, 0xfa, 0x36, 0xc2, 0xcd, 0xed, 0x33, 0x85, 0xc7, 0x37, 0xbc, 0x9c, 0x3f, 0x69, 0xc5, 0x36, - 0xa5, 0x8e, 0x94, 0xd8, 0x48, 0x14, 0x18, 0x64, 0x91, 0x9f, 0x78, 0x8a, 0x6e, 0xef, 0xa8, 0xad, 0x77, 0xea, 0xae, - 0x93, 0x13, 0x71, 0xe6, 0xea, 0x46, 0x52, 0xa5, 0x11, 0x76, 0xf3, 0x3c, 0xf2, 0xb2, 0x56, 0xd0, 0x8c, 0xd2, 0x43, - 0xed, 0xf6, 0x8e, 0x11, 0x1a, 0x56, 0x4a, 0x8a, 0x6c, 0x51, 0x1b, 0x2d, 0x07, 0x7a, 0xc8, 0x5f, 0x6b, 0x7e, 0xfe, - 0x67, 0x0b, 0x71, 0xe3, 0x70, 0xfa, 0x8a, 0x44, 0x44, 0x61, 0x10, 0xa7, 0x55, 0x24, 0xdb, 0x99, 0x40, 0x61, 0x1c, - 0x4c, 0xb0, 0x75, 0xa3, 0xa9, 0x87, 0x45, 0xa2, 0x96, 0x48, 0xc3, 0xf6, 0x28, 0x0f, 0x81, 0x2a, 0x09, 0x3d, 0x6d, - 0xad, 0x4e, 0xa2, 0xf5, 0x87, 0x6b, 0x9f, 0x11, 0xa1, 0x55, 0x8a, 0xac, 0xca, 0x2b, 0x57, 0x68, 0x04, 0x26, 0x12, - 0x89, 0x8e, 0x20, 0x0e, 0x4d, 0x08, 0x1f, 0x1e, 0xd2, 0x4b, 0xab, 0x22, 0x86, 0x56, 0x5c, 0x43, 0x66, 0x01, 0xc4, - 0x26, 0x63, 0xfa, 0x7a, 0xbf, 0x63, 0x19, 0xd7, 0xcb, 0x83, 0x56, 0xff, 0x91, 0x88, 0x13, 0xa4, 0xfb, 0xa2, 0x03, - 0x8c, 0x06, 0x1c, 0x55, 0xc1, 0xb7, 0x8f, 0xa1, 0xa8, 0x74, 0xa0, 0x5e, 0x8e, 0xdc, 0x22, 0xf2, 0x2b, 0xe0, 0xda, - 0xdd, 0x8a, 0x08, 0xdf, 0x2e, 0x9f, 0xd3, 0xac, 0x96, 0x11, 0xd4, 0xbe, 0x8f, 0x68, 0x95, 0x89, 0xb0, 0xb9, 0xb8, - 0xeb, 0xb1, 0x5c, 0x43, 0xd5, 0x87, 0x56, 0x5c, 0x44, 0xe1, 0xcd, 0x1c, 0xa4, 0x8d, 0xc9, 0x78, 0x49, 0x3f, 0xb5, - 0x1d, 0x95, 0x80, 0x5e, 0x28, 0x0b, 0x4d, 0x06, 0x49, 0xc1, 0xa3, 0xf7, 0x40, 0x98, 0xa4, 0x57, 0xce, 0x98, 0xfd, - 0x94, 0xa7, 0x24, 0x4e, 0xdf, 0x82, 0x76, 0x36, 0x45, 0xf0, 0x70, 0xd5, 0x5e, 0xda, 0x53, 0xd0, 0x7e, 0xcf, 0x74, - 0xb6, 0xbd, 0xac, 0x91, 0x78, 0x2f, 0x3a, 0xf0, 0x2a, 0xfa, 0x3c, 0x32, 0xc3, 0x98, 0xc1, 0xfd, 0x90, 0x90, 0xe4, - 0xb3, 0x94, 0x0a, 0x66, 0x41, 0x0f, 0xe4, 0x51, 0x91, 0x8c, 0xd2, 0x4c, 0xb7, 0xfd, 0x91, 0xe8, 0xfa, 0x69, 0xaa, - 0x76, 0xb5, 0xf6, 0x14, 0x55, 0x5e, 0xbe, 0x5e, 0xf8, 0xed, 0xf4, 0x8c, 0xae, 0xdc, 0x01, 0xc9, 0x7a, 0x46, 0x6f, - 0x5a, 0xb0, 0x5a, 0x28, 0x1d, 0xa9, 0x20, 0xf6, 0x3e, 0x27, 0xb0, 0x18, 0xd7, 0x43, 0x1a, 0xd6, 0xe0, 0x03, 0xa6, - 0x27, 0xab, 0xd3, 0x77, 0xce, 0x7d, 0xd9, 0xff, 0xf6, 0xdd, 0x76, 0x83, 0x35, 0x73, 0xf1, 0x07, 0xb9, 0x4b, 0x40, - 0xcd, 0x21, 0xd3, 0x64, 0xd2, 0x57, 0x69, 0x37, 0x27, 0xaf, 0x12, 0xb3, 0x70, 0x80, 0xfe, 0xdd, 0x1c, 0x72, 0xc2, - 0x3a, 0xde, 0xb8, 0x44, 0xf4, 0xd4, 0xbb, 0x70, 0xda, 0x13, 0x07, 0xf0, 0x2f, 0x18, 0x26, 0x4a, 0x88, 0x64, 0x2e, - 0xe1, 0x61, 0x5e, 0xc2, 0x51, 0xf2, 0x43, 0xb6, 0xcd, 0x54, 0xef, 0xa8, 0x6e, 0xde, 0x14, 0xd8, 0xf3, 0x14, 0x17, - 0xbb, 0x55, 0xc2, 0x8c, 0x55, 0xec, 0xb5, 0xd8, 0x43, 0x8f, 0x37, 0x28, 0x92, 0xcc, 0xf6, 0x19, 0x0d, 0x9d, 0xf9, - 0x4d, 0x7e, 0x7d, 0x71, 0x73, 0x37, 0xfd, 0x7f, 0x5c, 0x9d, 0x18, 0x87, 0x15, 0x7c, 0x36, 0xf4, 0x65, 0xbf, 0x2a, - 0xcb, 0xe7, 0x12, 0x5f, 0xad, 0x96, 0x77, 0x94, 0x8c, 0x7b, 0x9b, 0xf8, 0xc1, 0x00, 0x06, 0x6f, 0x5a, 0x48, 0x1e, - 0x4a, 0x14, 0x61, 0x64, 0xde, 0x1f, 0x2e, 0x29, 0xf0, 0x72, 0xf9, 0x55, 0x70, 0x91, 0x98, 0xfe, 0xb6, 0xf5, 0x4a, - 0x2a, 0xe2, 0x90, 0xaa, 0x23, 0xde, 0x4d, 0x10, 0x69, 0x51, 0x0e, 0x1d, 0xfd, 0xc4, 0x01, 0x93, 0x35, 0x38, 0x10, - 0x81, 0x82, 0xce, 0x67, 0x2f, 0x89, 0xc4, 0x8f, 0xd0, 0x5f, 0x79, 0x16, 0x75, 0xda, 0x8b, 0xf6, 0xb3, 0xed, 0x85, - 0xff, 0x7f, 0xba, 0xb4, 0xaa, 0x73, 0x6c, 0x40, 0xb0, 0xfe, 0x2f, 0x90, 0xb8, 0xd0, 0x0e, 0x4a, 0x90, 0xee, 0x53, - 0xf8, 0xc4, 0x9f, 0xdd, 0x69, 0x96, 0x13, 0x96, 0xaf, 0xd5, 0x6a, 0x19, 0x4f, 0xe8, 0x9c, 0x5c, 0x68, 0x1c, 0x27, - 0x6a, 0xca, 0x10, 0x3c, 0xe3, 0xe8, 0xed, 0xb5, 0x0c, 0xbd, 0xdb, 0x98, 0x4a, 0x82, 0x4e, 0xe2, 0x71, 0xc5, 0x52, - 0xac, 0xa2, 0x75, 0xbf, 0x6a, 0x63, 0xb6, 0x99, 0xc1, 0x19, 0x30, 0xce, 0xb2, 0x80, 0xd1, 0x83, 0xa5, 0x7a, 0x38, - 0x37, 0x0e, 0x98, 0x5e, 0xcb, 0x6b, 0x4c, 0x47, 0x04, 0x8d, 0xdd, 0xf2, 0xf5, 0x7a, 0x14, 0x51, 0x49, 0x26, 0x22, - 0xde, 0x2d, 0xf0, 0x40, 0x2f, 0x7e, 0x3e, 0x56, 0xbd, 0xf6, 0xa4, 0x6e, 0xe5, 0x2b, 0x15, 0x61, 0x59, 0x47, 0x53, - 0x19, 0x30, 0x5e, 0xdd, 0xac, 0x8a, 0xd0, 0xae, 0x84, 0xb8, 0x78, 0x21, 0x7b, 0x02, 0x31, 0x31, 0x92, 0x8f, 0x38, - 0x93, 0x60, 0x93, 0x83, 0x4c, 0x05, 0xe5, 0xe3, 0x43, 0xcd, 0x16, 0x04, 0xa1, 0xab, 0xdb, 0x50, 0x0b, 0x72, 0x2c, - 0x9c, 0x27, 0x92, 0x11, 0x4d, 0x12, 0x03, 0x57, 0x59, 0x49, 0xb0, 0x6a, 0x26, 0xe3, 0x65, 0xd6, 0x9d, 0x15, 0x7b, - 0x60, 0x53, 0xad, 0x39, 0x18, 0xdd, 0xff, 0x98, 0x17, 0x18, 0xa2, 0x28, 0x5a, 0xcf, 0x12, 0xc5, 0xf3, 0x88, 0x79, - 0xc0, 0x2c, 0x4b, 0xa0, 0x51, 0x84, 0x22, 0xf4, 0x6f, 0x89, 0x3d, 0xd4, 0x67, 0x95, 0x91, 0x58, 0x58, 0x0c, 0x27, - 0x54, 0xc5, 0xe9, 0x28, 0xed, 0x95, 0x85, 0xf7, 0xc1, 0x6e, 0x10, 0xc6, 0x57, 0xff, 0xd7, 0xf8, 0xee, 0x6d, 0x0f, - 0xa9, 0xed, 0xf9, 0x38, 0x9b, 0x99, 0x8f, 0xe9, 0x46, 0xef, 0xf6, 0x4f, 0x37, 0x22, 0x36, 0xbb, 0xad, 0x6c, 0x03, - 0x91, 0x4c, 0x14, 0x94, 0x9a, 0x3f, 0xb3, 0xdb, 0x03, 0xb6, 0xe2, 0xa0, 0x78, 0xdd, 0xa9, 0xa8, 0xcf, 0xd6, 0x6a, - 0x2c, 0x01, 0x08, 0xc7, 0x92, 0x46, 0xda, 0x25, 0xb6, 0x20, 0xd2, 0xfa, 0x1c, 0x19, 0x12, 0xbc, 0xb6, 0xce, 0xf3, - 0x00, 0x0e, 0x59, 0x32, 0x4d, 0x04, 0x2b, 0xd2, 0x4b, 0x00, 0x69, 0x1b, 0x21, 0xbd, 0xc8, 0x9e, 0x41, 0x09, 0xc0, - 0xab, 0x88, 0xf6, 0x46, 0x65, 0x22, 0x92, 0x37, 0x59, 0xa3, 0x14, 0xb6, 0xe3, 0x03, 0xe1, 0x65, 0x7e, 0x44, 0xb0, - 0xc4, 0xd4, 0x68, 0xcf, 0x96, 0x4e, 0x13, 0x50, 0x8b, 0xed, 0x34, 0x42, 0x98, 0xef, 0xd7, 0x8d, 0xc1, 0xc3, 0xe1, - 0x62, 0x49, 0x8a, 0x71, 0xb5, 0xde, 0x7c, 0x2c, 0xe5, 0x76, 0xe4, 0x5a, 0xec, 0x98, 0x3b, 0x70, 0x34, 0xe9, 0x9e, - 0xa6, 0x5d, 0xbd, 0xd1, 0xcd, 0xaf, 0xf8, 0xcd, 0xeb, 0x69, 0x89, 0x97, 0xc7, 0x47, 0x42, 0xf7, 0xae, 0x46, 0xa0, - 0xb9, 0x71, 0xce, 0x0f, 0xfd, 0xee, 0x5d, 0x9d, 0xe0, 0x8d, 0xff, 0x95, 0x1a, 0x4f, 0xca, 0xe4, 0xe4, 0x6f, 0xe6, - 0xd0, 0xf8, 0x8c, 0xf1, 0xb4, 0xb8, 0xa9, 0x40, 0xa0, 0x40, 0xd5, 0x01, 0xec, 0xce, 0xa2, 0xd2, 0x7f, 0x33, 0x62, - 0x7c, 0x04, 0x5c, 0x28, 0x3a, 0x35, 0xf8, 0x69, 0x49, 0x78, 0xc6, 0xf3, 0xd9, 0x2d, 0xd4, 0x22, 0x69, 0xa5, 0xce, - 0xc4, 0x4e, 0x1d, 0x7e, 0x2e, 0xf6, 0x0f, 0x2b, 0x22, 0x3a, 0x14, 0xf1, 0x61, 0x37, 0x05, 0x05, 0x41, 0xc3, 0x0b, - 0x62, 0x99, 0xa0, 0x0b, 0xa1, 0x7c, 0xd4, 0xec, 0xbe, 0x4c, 0x52, 0xfd, 0xc3, 0xfe, 0x82, 0x9f, 0x7b, 0xdb, 0xd7, - 0x22, 0x17, 0x4b, 0xa1, 0x59, 0xd9, 0x48, 0x27, 0x0f, 0x2e, 0x15, 0x6d, 0xaf, 0x82, 0xec, 0x6c, 0xde, 0x9a, 0x35, - 0x99, 0x03, 0xc9, 0x22, 0x2d, 0xc2, 0xfa, 0xc8, 0x73, 0xfe, 0xd9, 0xe2, 0x73, 0xba, 0x74, 0xdf, 0x37, 0x63, 0xdb, - 0x64, 0x98, 0xf4, 0x24, 0x81, 0x30, 0x51, 0x82, 0x6f, 0xcb, 0xe8, 0x01, 0x60, 0x7d, 0x6d, 0x39, 0xa2, 0xcc, 0x56, - 0x01, 0x99, 0xc9, 0x76, 0x7e, 0xed, 0x29, 0x20, 0xea, 0x6c, 0x05, 0x12, 0x31, 0x94, 0x3e, 0x03, 0x17, 0x34, 0x3e, - 0xb5, 0x20, 0x49, 0x89, 0x09, 0xc9, 0x0c, 0x1f, 0x01, 0x99, 0x02, 0x6e, 0xbe, 0xf3, 0x64, 0x0b, 0xfd, 0x54, 0xc6, - 0x29, 0xb0, 0x61, 0x5a, 0x0f, 0xe6, 0x2c, 0x8c, 0x67, 0x1a, 0x32, 0xe2, 0xf8, 0xe7, 0x1b, 0x81, 0xd5, 0x88, 0x3c, - 0x8f, 0xcc, 0x6c, 0x24, 0x2e, 0x60, 0x70, 0xd9, 0xf7, 0x92, 0x26, 0x10, 0xd7, 0xaf, 0x71, 0x8d, 0xf9, 0x24, 0x8f, - 0xd7, 0xea, 0xe6, 0xb7, 0xe6, 0x6f, 0x3d, 0x94, 0x67, 0xf9, 0xe2, 0xa4, 0x36, 0xad, 0x15, 0xf4, 0xcb, 0xb5, 0x56, - 0x1b, 0xa0, 0x56, 0xc1, 0xcc, 0x96, 0x8c, 0x5b, 0x69, 0x51, 0x04, 0x8e, 0x9a, 0xe5, 0xad, 0xd9, 0x1d, 0xdf, 0x6e, - 0x90, 0x3f, 0xd1, 0x10, 0x31, 0x3e, 0x55, 0x81, 0x4b, 0xd4, 0xf1, 0x73, 0xf4, 0x36, 0x87, 0x76, 0x18, 0xaf, 0xe2, - 0x87, 0x6d, 0xbc, 0xc8, 0xd8, 0xca, 0xf2, 0xf2, 0x75, 0x74, 0x88, 0x2b, 0x47, 0xeb, 0x30, 0x34, 0xfd, 0x34, 0x8d, - 0x39, 0x52, 0xa8, 0x27, 0xec, 0xf8, 0x7b, 0x0c, 0xf8, 0x4f, 0xed, 0xf1, 0xab, 0xfe, 0x93, 0xe3, 0x5f, 0x86, 0x5d, - 0xe5, 0x65, 0xfe, 0x63, 0x90, 0xbf, 0x87, 0x4f, 0xa9, 0xf2, 0xb3, 0x89, 0x2c, 0x54, 0x9b, 0x43, 0xf2, 0x68, 0x2d, - 0x87, 0x05, 0xfa, 0xea, 0xc3, 0xc9, 0xe9, 0x04, 0xc3, 0x9a, 0x53, 0xe7, 0x07, 0xa4, 0xaf, 0x6b, 0xe2, 0xc2, 0x2f, - 0xc6, 0xa7, 0xab, 0xb9, 0x0c, 0xdd, 0x74, 0xb9, 0x87, 0x54, 0xee, 0x8b, 0x4c, 0xb5, 0xad, 0xac, 0x9d, 0xfd, 0xfd, - 0x60, 0x70, 0x47, 0x04, 0x36, 0x9c, 0x7b, 0xf3, 0x85, 0xe7, 0x9f, 0xf4, 0x9f, 0xee, 0x29, 0x5a, 0x33, 0x16, 0x5f, - 0xe8, 0x33, 0xad, 0x5c, 0xbe, 0x71, 0x6d, 0xca, 0x36, 0xf4, 0x99, 0xda, 0x74, 0x03, 0x20, 0x26, 0x15, 0x34, 0x28, - 0xeb, 0xdc, 0xc7, 0x1f, 0x14, 0x7d, 0x48, 0x28, 0xfa, 0xd2, 0xe7, 0xa3, 0xda, 0x17, 0x06, 0x11, 0x00, 0x49, 0x0c, - 0x33, 0xf3, 0x97, 0x82, 0xee, 0x84, 0x86, 0x07, 0xfa, 0xe6, 0xe9, 0x27, 0x4e, 0x7d, 0x06, 0xde, 0x1a, 0xf5, 0x0f, - 0x52, 0x5c, 0x5f, 0x81, 0x04, 0xb0, 0x70, 0x9e, 0x2e, 0xff, 0x4f, 0x5e, 0x10, 0x42, 0xd2, 0x9c, 0x2c, 0x6a, 0x3b, - 0x57, 0xdd, 0xff, 0x98, 0x6c, 0xf0, 0x11, 0x1b, 0x24, 0xf8, 0x38, 0x29, 0x26, 0x9e, 0x05, 0x41, 0x75, 0x45, 0xcf, - 0x4d, 0xae, 0xfa, 0xb3, 0x8c, 0x43, 0xfe, 0xf7, 0xb1, 0x3c, 0x5f, 0x40, 0xce, 0x63, 0xc6, 0x77, 0x7e, 0x88, 0xb0, - 0x24, 0xa7, 0x61, 0x67, 0x76, 0x5f, 0xed, 0xcf, 0xa3, 0x81, 0xfa, 0x6a, 0x77, 0x7e, 0x03, 0x09, 0xf8, 0xc2, 0x0f, - 0x6b, 0xa8, 0x51, 0xf9, 0xa3, 0x39, 0xad, 0xbd, 0x4a, 0x1b, 0x7d, 0x42, 0x25, 0x22, 0xb8, 0x94, 0x1c, 0xa0, 0xbe, - 0x48, 0x3a, 0x3f, 0x99, 0x38, 0x66, 0xda, 0x94, 0x1c, 0x74, 0xe3, 0x5c, 0x72, 0xa1, 0x1c, 0x5a, 0x49, 0x1d, 0xa5, - 0x80, 0x9c, 0x94, 0xd1, 0x81, 0x15, 0xdd, 0x5e, 0x4a, 0xc6, 0x8f, 0x8a, 0xd0, 0x2e, 0x9b, 0xcd, 0x35, 0x2b, 0x8b, - 0x99, 0x44, 0x8c, 0x54, 0x70, 0x59, 0xb2, 0x32, 0x41, 0xbf, 0xa8, 0x8d, 0xa9, 0x8d, 0x64, 0xba, 0xb7, 0x59, 0x9d, - 0xba, 0x08, 0x34, 0xb8, 0x72, 0x40, 0x5e, 0xf1, 0x2a, 0x60, 0x4b, 0x48, 0x26, 0xcc, 0x22, 0x56, 0x70, 0xa1, 0xdc, - 0xf7, 0x99, 0xfb, 0x60, 0x7f, 0x9c, 0x04, 0xe7, 0x5b, 0x6f, 0xd1, 0xef, 0x12, 0x9c, 0x82, 0xea, 0xf5, 0xe7, 0xd4, - 0xb5, 0xb8, 0xbc, 0x62, 0x0a, 0x0a, 0x1c, 0x83, 0x7c, 0xba, 0xcb, 0x03, 0x22, 0xf0, 0x43, 0xfb, 0xa4, 0x8e, 0xd3, - 0xd6, 0x7f, 0x46, 0xc7, 0x0c, 0xb2, 0x81, 0x54, 0xe7, 0xbe, 0x2c, 0xb0, 0x9d, 0x2e, 0x5b, 0x22, 0xb7, 0x02, 0x77, - 0x4a, 0x75, 0xdb, 0x0b, 0x94, 0x29, 0xd1, 0x51, 0x11, 0x81, 0x6d, 0x06, 0xd0, 0xb3, 0x15, 0xc1, 0x4b, 0x1f, 0x79, - 0xd6, 0x2c, 0x68, 0xe8, 0x8f, 0x88, 0x34, 0x99, 0xd0, 0x80, 0x41, 0x2e, 0x26, 0x5e, 0x4c, 0xbd, 0xf4, 0x98, 0x45, - 0xc7, 0x19, 0x70, 0x67, 0xe7, 0x2c, 0x2c, 0xe6, 0xf5, 0x34, 0xe5, 0x4b, 0x8f, 0x7e, 0x33, 0xbc, 0xec, 0x5e, 0xba, - 0xf9, 0xe9, 0x73, 0xba, 0xc1, 0xc4, 0x06, 0xba, 0x6b, 0x75, 0x1c, 0xcd, 0x83, 0x87, 0x16, 0x30, 0x93, 0xd2, 0x1c, - 0xef, 0x5b, 0xd0, 0xd2, 0xb9, 0x08, 0x99, 0xc8, 0xcb, 0x83, 0x9e, 0xed, 0x1b, 0xd2, 0x50, 0xb3, 0x13, 0xe0, 0xb3, - 0xb3, 0x34, 0x9a, 0x2b, 0x5e, 0xd0, 0x42, 0x09, 0x23, 0xc4, 0x65, 0xfd, 0x13, 0xe0, 0x81, 0xaf, 0x01, 0xca, 0x9f, - 0x94, 0xeb, 0x81, 0x67, 0x8e, 0xb9, 0x43, 0x38, 0xe1, 0xa7, 0x8a, 0xc0, 0xdd, 0x45, 0x85, 0xfe, 0xc9, 0x8c, 0x21, - 0x85, 0x01, 0x5f, 0x15, 0xe3, 0x29, 0xe1, 0x15, 0x68, 0x1a, 0x94, 0x07, 0x87, 0x01, 0xaa, 0x51, 0xf7, 0x7d, 0xed, - 0x53, 0x38, 0xa2, 0x09, 0x0f, 0x79, 0x87, 0xbc, 0x1a, 0xaa, 0x85, 0x26, 0x3e, 0xe4, 0x1d, 0x93, 0xe0, 0x9b, 0x0f, - 0xf7, 0x32, 0x7d, 0x44, 0x95, 0xa3, 0x17, 0xfa, 0x84, 0x05, 0x92, 0x53, 0x3d, 0x5e, 0x4b, 0xd1, 0x5e, 0xd1, 0x1c, - 0x5a, 0x09, 0x54, 0x6c, 0x4c, 0x87, 0x70, 0xe9, 0xd9, 0x5e, 0x7f, 0x7a, 0x93, 0xf8, 0x8b, 0x38, 0x63, 0x0d, 0x7b, - 0x02, 0xce, 0x99, 0x0d, 0xaa, 0xef, 0x64, 0x97, 0xb0, 0x48, 0x92, 0x9e, 0x67, 0x4e, 0xc7, 0x04, 0xb9, 0x79, 0xcd, - 0x1d, 0xdc, 0xcc, 0x43, 0xb9, 0xaa, 0x4f, 0x44, 0xa1, 0x49, 0xdd, 0x49, 0x41, 0xc4, 0x5b, 0xf7, 0xd7, 0x09, 0x6a, - 0x19, 0x75, 0x75, 0xd3, 0xdf, 0x8a, 0x78, 0x64, 0xcc, 0xbf, 0x56, 0x91, 0xd1, 0x2a, 0xf7, 0xdb, 0xd6, 0x5f, 0x57, - 0x66, 0x0f, 0xd9, 0xcf, 0xab, 0x5a, 0xf7, 0x3f, 0x6b, 0xd8, 0x6b, 0x5e, 0x2b, 0x45, 0x11, 0xce, 0x5c, 0x4d, 0x7a, - 0x64, 0xbe, 0x41, 0x2f, 0xee, 0xf6, 0xf0, 0x9c, 0x04, 0x28, 0x13, 0x27, 0x21, 0x0e, 0x24, 0xe4, 0x18, 0x6b, 0xbe, - 0xa2, 0x3d, 0xe6, 0xba, 0x61, 0x51, 0x99, 0x6b, 0x7e, 0x20, 0x68, 0x40, 0x05, 0xf4, 0x87, 0x1d, 0x4e, 0x73, 0x6f, - 0x42, 0xc3, 0x6f, 0x42, 0x3e, 0x43, 0xf0, 0xbb, 0xfc, 0x63, 0x81, 0xa1, 0xd0, 0x52, 0x43, 0x86, 0xeb, 0x54, 0x37, - 0x63, 0xb2, 0xda, 0x04, 0xfe, 0xb7, 0xb4, 0x9b, 0x51, 0x43, 0x64, 0x41, 0x84, 0x0c, 0x30, 0x90, 0xd1, 0x16, 0x03, - 0xaf, 0x69, 0xa6, 0xd9, 0x6a, 0x30, 0x56, 0x1f, 0x36, 0x59, 0x0a, 0x76, 0xaf, 0x9c, 0xa9, 0x1c, 0x06, 0xb5, 0x81, - 0xe1, 0x5d, 0xfa, 0xde, 0x3e, 0x2c, 0xe3, 0x45, 0xad, 0x90, 0xfb, 0xe9, 0x10, 0x19, 0x6e, 0x52, 0xc7, 0x6a, 0xa6, - 0xff, 0x19, 0x33, 0x31, 0x3e, 0x35, 0x38, 0x04, 0x36, 0x8c, 0x5d, 0xd5, 0x82, 0x61, 0xda, 0x28, 0xed, 0x9d, 0xb2, - 0x2e, 0x68, 0x21, 0x2c, 0xad, 0x5a, 0xe3, 0x80, 0x71, 0x4e, 0x2f, 0x2f, 0xd4, 0xe9, 0xc4, 0x9b, 0xfa, 0xdb, 0xc8, - 0x84, 0x0f, 0xfe, 0x35, 0x87, 0xba, 0x5a, 0x18, 0x85, 0xe3, 0xe1, 0xa3, 0x94, 0x07, 0x49, 0x68, 0x89, 0x85, 0xa6, - 0x6c, 0x6e, 0x48, 0x54, 0x87, 0x62, 0x23, 0x28, 0xf8, 0x7c, 0x85, 0x08, 0xb8, 0xc3, 0x61, 0x4b, 0x49, 0xf7, 0x16, - 0xcf, 0x90, 0x24, 0x2a, 0x23, 0x17, 0x9b, 0x60, 0x0f, 0x04, 0xc7, 0xa5, 0xa6, 0xac, 0xe5, 0xf9, 0xaf, 0x92, 0xe8, - 0x9f, 0xa0, 0xe0, 0x25, 0x29, 0xe5, 0xfc, 0x3b, 0x16, 0x7f, 0xd6, 0xd7, 0xc7, 0x88, 0xde, 0xfb, 0x0b, 0xc9, 0x67, - 0x7d, 0xb6, 0x6d, 0x1b, 0x23, 0xf3, 0xf2, 0x66, 0xae, 0x1f, 0xeb, 0xb8, 0x8c, 0x5d, 0xa2, 0x80, 0xe8, 0x6f, 0x58, - 0x2e, 0xd3, 0x3c, 0xc0, 0xf2, 0xb0, 0x3c, 0x8a, 0xfc, 0xb6, 0x22, 0x59, 0xa2, 0x81, 0xb7, 0x38, 0x2d, 0xd2, 0xbb, - 0xed, 0x78, 0x97, 0x2b, 0x75, 0x3a, 0x74, 0x2b, 0x63, 0x49, 0x34, 0xaa, 0x94, 0x43, 0x10, 0x03, 0x77, 0xba, 0x38, - 0x06, 0xbb, 0x33, 0x99, 0x3d, 0x4e, 0xdb, 0x98, 0xea, 0x4e, 0xdc, 0xd1, 0x13, 0xbc, 0xc4, 0x27, 0x2d, 0x35, 0xbb, - 0xa3, 0x17, 0x5a, 0x86, 0x4a, 0xc8, 0xea, 0xf4, 0x85, 0x56, 0x3f, 0x8a, 0x90, 0x24, 0x07, 0xfc, 0xaa, 0xf2, 0x97, - 0xaf, 0xd7, 0x63, 0xa1, 0x52, 0x5d, 0x54, 0x14, 0x68, 0x7e, 0x9e, 0x26, 0x1e, 0xa3, 0xdd, 0x6f, 0xa5, 0xaf, 0xce, - 0x1b, 0xc2, 0x07, 0xa0, 0x02, 0x92, 0x5b, 0x39, 0x34, 0xa4, 0xa1, 0x65, 0x3e, 0x3c, 0xce, 0x50, 0x28, 0x02, 0x74, - 0x26, 0x75, 0xe1, 0xa9, 0x8b, 0xf3, 0xea, 0x1f, 0x13, 0x54, 0x6c, 0x3f, 0xa7, 0x0c, 0x80, 0x93, 0x34, 0x40, 0x34, - 0x1a, 0xcf, 0x59, 0xa7, 0xd1, 0x85, 0x52, 0x3c, 0x03, 0x47, 0xc0, 0x7a, 0x89, 0x5c, 0x7b, 0x45, 0xeb, 0x5a, 0x86, - 0x34, 0xe9, 0xfe, 0xed, 0x51, 0xbf, 0x0d, 0xc1, 0x1d, 0x98, 0x34, 0x12, 0x3a, 0xaa, 0xae, 0x98, 0x1b, 0xc9, 0x38, - 0x50, 0x77, 0xda, 0x4d, 0x29, 0x37, 0x56, 0xd8, 0xcb, 0x5c, 0xb6, 0xaa, 0x63, 0xb9, 0x44, 0x58, 0xc4, 0xc5, 0x51, - 0x62, 0x45, 0x80, 0xef, 0x91, 0x41, 0x54, 0xaa, 0xf2, 0x24, 0x8a, 0x90, 0xe4, 0x0d, 0x16, 0x18, 0x73, 0x0b, 0xfd, - 0x26, 0x12, 0x3c, 0xf8, 0xfa, 0xa7, 0x15, 0x49, 0xa1, 0x12, 0x10, 0x40, 0x83, 0x81, 0x16, 0x50, 0xcd, 0xfc, 0xa3, - 0x51, 0xb7, 0x18, 0x3a, 0xcf, 0xe2, 0x39, 0x25, 0xc9, 0xa0, 0x3f, 0xfe, 0xfb, 0x09, 0x61, 0xd0, 0x06, 0xb0, 0x90, - 0x11, 0x07, 0xdc, 0x30, 0xd7, 0x9b, 0x44, 0xfa, 0x6c, 0x51, 0x2c, 0xb6, 0xd8, 0xcb, 0xb9, 0x4d, 0xe9, 0x05, 0x8d, - 0x97, 0x50, 0xf2, 0x8e, 0xe1, 0x2b, 0xaf, 0x83, 0x99, 0xb7, 0xbc, 0xc6, 0x0d, 0x16, 0xfa, 0x05, 0x8b, 0xae, 0x4a, - 0x72, 0xef, 0x97, 0x3d, 0x00, 0x99, 0x4f, 0x27, 0xaa, 0x37, 0x04, 0x0f, 0x21, 0x65, 0x63, 0xcc, 0x98, 0x73, 0x83, - 0x7b, 0xe7, 0x53, 0x45, 0x0a, 0x23, 0x17, 0x86, 0x00, 0x4e, 0x62, 0x94, 0xd1, 0xa6, 0x9e, 0xce, 0x42, 0x9d, 0x7e, - 0xe1, 0xad, 0x03, 0xf5, 0x6b, 0x53, 0x09, 0xc5, 0x5e, 0xd6, 0x03, 0x22, 0x6a, 0xaa, 0xae, 0x04, 0xe5, 0xa6, 0x44, - 0xf5, 0xed, 0x27, 0x78, 0xa6, 0xe3, 0x50, 0xfc, 0xcc, 0xc0, 0x48, 0x4c, 0x84, 0xe4, 0x6c, 0x90, 0x24, 0x4f, 0xd2, - 0x65, 0x2d, 0x09, 0xea, 0xda, 0xaf, 0x12, 0xc2, 0x23, 0x92, 0x71, 0x7e, 0xd6, 0x87, 0x7a, 0xe0, 0xca, 0x06, 0xbb, - 0x1c, 0x4f, 0xbf, 0x08, 0xd7, 0xdd, 0xa6, 0x3d, 0x35, 0xbc, 0xfb, 0x54, 0x64, 0x72, 0xcb, 0x56, 0xcd, 0x62, 0x63, - 0x82, 0x9f, 0xf8, 0x3c, 0xe8, 0x3e, 0xee, 0x37, 0x24, 0xa1, 0x9f, 0x6f, 0x73, 0x3f, 0xb1, 0xd2, 0xe8, 0x03, 0x78, - 0xd0, 0x58, 0x8a, 0x4b, 0x2b, 0x50, 0x63, 0xc1, 0x97, 0xdb, 0x92, 0xbc, 0xcd, 0x3c, 0xf0, 0x9d, 0xb8, 0x10, 0xba, - 0xc8, 0x7d, 0xe4, 0x6b, 0xe4, 0xad, 0xf4, 0x6e, 0xd5, 0x46, 0xfe, 0xe0, 0x57, 0x7f, 0xc8, 0x4a, 0x4f, 0xe9, 0x8f, - 0xca, 0x9c, 0xc5, 0x37, 0x5c, 0xa2, 0x9b, 0x81, 0x1d, 0xc1, 0x49, 0x5d, 0xf5, 0xe1, 0x0d, 0xa0, 0xb5, 0x85, 0xb7, - 0x1c, 0x4d, 0x13, 0x81, 0xe7, 0x66, 0xb8, 0xc4, 0x15, 0xd9, 0xe0, 0x06, 0x8a, 0x3d, 0x28, 0x60, 0x20, 0x36, 0xca, - 0x74, 0x3c, 0x00, 0xfc, 0x1c, 0xe2, 0x6e, 0xcc, 0xcf, 0xba, 0x66, 0x1b, 0x2d, 0x70, 0x4e, 0x91, 0x05, 0x64, 0x2f, - 0x43, 0x03, 0x0a, 0xd0, 0x09, 0x45, 0x50, 0xda, 0xac, 0xb1, 0x03, 0x26, 0x84, 0x15, 0x46, 0xd3, 0x00, 0xc7, 0x86, - 0x98, 0xb3, 0x97, 0xe6, 0x16, 0x81, 0x2f, 0x97, 0x88, 0x5c, 0xd3, 0x23, 0xa1, 0x7c, 0x86, 0x14, 0x38, 0xd1, 0xcf, - 0xd3, 0x7f, 0x03, 0x26, 0xbd, 0x9b, 0x13, 0xb4, 0xa7, 0x83, 0x69, 0xbf, 0xd4, 0x10, 0x28, 0x2d, 0x23, 0xf7, 0x87, - 0xe6, 0xf9, 0x7a, 0x31, 0xa6, 0x6b, 0xac, 0x76, 0x1b, 0xcd, 0x3f, 0xc5, 0xf5, 0x3c, 0x19, 0xb7, 0x88, 0x5c, 0x18, - 0x00, 0x7e, 0x6f, 0x06, 0x8d, 0xb7, 0xde, 0x4f, 0x2a, 0x3c, 0x67, 0x0d, 0x4b, 0x28, 0xdd, 0x23, 0xf2, 0x6d, 0xfe, - 0x87, 0x69, 0x3a, 0x28, 0x82, 0x53, 0x1b, 0xf2, 0xde, 0x83, 0x7b, 0x58, 0x87, 0x82, 0xa1, 0xaf, 0xc3, 0x94, 0xf9, - 0xc9, 0xce, 0xb2, 0x81, 0xd2, 0xb6, 0xb3, 0x5d, 0x35, 0x25, 0xed, 0x42, 0x32, 0x5c, 0x91, 0x18, 0xa4, 0xda, 0xc8, - 0x8f, 0xb6, 0xb2, 0xb2, 0x66, 0x6e, 0xa7, 0x38, 0xf2, 0x73, 0xa7, 0x33, 0xec, 0xde, 0xd8, 0xac, 0x1b, 0x1e, 0x80, - 0x34, 0xd7, 0x29, 0x00, 0x08, 0xc2, 0xa5, 0x6c, 0xe2, 0x1d, 0x4b, 0x95, 0xed, 0x40, 0x7d, 0xb0, 0xd0, 0x1c, 0x5c, - 0xe7, 0xa3, 0x09, 0xf9, 0xb8, 0xd9, 0xac, 0xf4, 0x3c, 0x07, 0x88, 0xc7, 0x71, 0x52, 0x19, 0x0c, 0x91, 0x82, 0x9f, - 0x4a, 0xb0, 0xc3, 0xd1, 0xe2, 0x3c, 0xfa, 0x6b, 0xe4, 0xbc, 0x4f, 0x50, 0x0d, 0x15, 0x58, 0x15, 0x6c, 0xc3, 0xc6, - 0xd3, 0x8b, 0xc4, 0x65, 0xbb, 0x53, 0xa1, 0x45, 0x87, 0x83, 0x5a, 0xf8, 0xd0, 0x01, 0xfd, 0x90, 0x14, 0x0a, 0x71, - 0x2e, 0xc2, 0x79, 0x16, 0x92, 0xa7, 0x0d, 0x14, 0x46, 0x5e, 0x8c, 0xdf, 0xc6, 0x70, 0xb6, 0xeb, 0x16, 0x23, 0x4b, - 0xd7, 0x74, 0x6b, 0x9c, 0x67, 0x93, 0x1f, 0xd1, 0x13, 0x27, 0x55, 0x24, 0xd9, 0x44, 0x2a, 0xa8, 0x51, 0x1a, 0x6c, - 0xfc, 0x15, 0x00, 0x05, 0x73, 0xc3, 0x6b, 0x1a, 0x8f, 0xb4, 0x4c, 0xc4, 0x5d, 0x8e, 0x06, 0x9b, 0xcc, 0xc1, 0xe3, - 0x60, 0xd0, 0x2b, 0xc4, 0x19, 0xda, 0x05, 0x4e, 0x72, 0xab, 0xc4, 0x1e, 0x7f, 0x91, 0xef, 0x25, 0x5e, 0xd8, 0x94, - 0xa1, 0x47, 0x3c, 0x48, 0x2c, 0x9b, 0x8f, 0xc1, 0xea, 0xfc, 0xbb, 0xfd, 0x90, 0x68, 0x34, 0xd0, 0x01, 0xe8, 0xc8, - 0x97, 0x70, 0xde, 0x13, 0xd3, 0xa4, 0x7b, 0xac, 0xbb, 0xf8, 0xd6, 0xfd, 0xf5, 0x69, 0xf0, 0xdd, 0x21, 0xa3, 0x2f, - 0x70, 0x3b, 0x69, 0xc2, 0x76, 0x6e, 0x5a, 0xeb, 0xfa, 0x03, 0x58, 0x00, 0xa7, 0xcc, 0x78, 0x26, 0x86, 0x97, 0x0d, - 0xfa, 0x46, 0x17, 0xe4, 0xb9, 0xbb, 0x73, 0x1d, 0xf7, 0xe7, 0xb8, 0xf5, 0xe2, 0x94, 0x43, 0x6a, 0x61, 0x11, 0xa8, - 0x19, 0x40, 0x05, 0xe4, 0x65, 0x34, 0x25, 0x5d, 0x10, 0xfc, 0xda, 0xa0, 0xe8, 0x7c, 0x87, 0x31, 0x40, 0xbd, 0xea, - 0x39, 0xcd, 0xfb, 0x5b, 0x4e, 0xf2, 0x42, 0xc4, 0x7b, 0x9b, 0xa6, 0xfa, 0xa7, 0x95, 0x7d, 0xca, 0x94, 0xd7, 0x2f, - 0xcd, 0xd1, 0xd9, 0x84, 0xaa, 0xad, 0xdd, 0xa6, 0x1a, 0xe2, 0x73, 0xbc, 0x64, 0x1e, 0x51, 0xbc, 0x80, 0x81, 0xe6, - 0x81, 0x1f, 0x79, 0xaf, 0xed, 0xdd, 0x68, 0x56, 0x5e, 0xa7, 0x0b, 0xfa, 0x7e, 0x4e, 0xb3, 0x12, 0xbc, 0x67, 0x67, - 0xab, 0x4a, 0xf5, 0x92, 0x0a, 0x86, 0x79, 0xd7, 0x2b, 0x7f, 0x46, 0xbf, 0xd1, 0x13, 0x3f, 0xe5, 0x4d, 0xe3, 0x37, - 0x25, 0xf3, 0xdb, 0x24, 0x4c, 0xea, 0x1c, 0xd6, 0xf4, 0x28, 0xdd, 0x4e, 0x28, 0xe7, 0x41, 0xee, 0x5e, 0xf6, 0x35, - 0xb2, 0xdd, 0x78, 0xa5, 0xfc, 0xe2, 0x8b, 0x96, 0x7f, 0xd7, 0xab, 0xba, 0xd2, 0xa4, 0x79, 0x1a, 0x3b, 0x57, 0x0f, - 0xf5, 0xe9, 0x43, 0x47, 0xa6, 0xfb, 0x23, 0xbe, 0xcc, 0xc8, 0xd0, 0x22, 0x33, 0xdf, 0x55, 0x56, 0x43, 0x5c, 0x6b, - 0x35, 0xf1, 0xee, 0x54, 0xe6, 0xcc, 0x8e, 0xdd, 0x78, 0x91, 0x64, 0x30, 0xaa, 0x8e, 0x4c, 0x0d, 0x89, 0xe4, 0x84, - 0xa8, 0x5f, 0x31, 0x08, 0x98, 0x75, 0x8d, 0x7f, 0xb5, 0xaf, 0x29, 0xb7, 0xe5, 0x5b, 0x8f, 0xb9, 0xfe, 0x36, 0x4e, - 0xb7, 0x5f, 0x13, 0x60, 0xdb, 0x56, 0x5c, 0xea, 0xc5, 0x28, 0xb6, 0x36, 0x32, 0xb1, 0x82, 0x96, 0x27, 0xe0, 0xf0, - 0x80, 0x44, 0xa2, 0xc2, 0xa4, 0xd9, 0x37, 0x92, 0x4a, 0x76, 0xd8, 0xf0, 0xcd, 0x7d, 0xab, 0xb8, 0xa0, 0x8f, 0xf6, - 0x8f, 0x3a, 0x55, 0xd3, 0xcb, 0x42, 0x51, 0x55, 0x1d, 0xf4, 0xa0, 0x29, 0x95, 0xd2, 0xe7, 0x5f, 0xee, 0x4c, 0x12, - 0x10, 0x59, 0x25, 0x81, 0x31, 0x7d, 0x80, 0x62, 0x2a, 0xed, 0x5a, 0x03, 0xa2, 0xc6, 0xbf, 0x21, 0xe1, 0xb7, 0xfa, - 0x31, 0x3d, 0xba, 0x47, 0xdf, 0xfd, 0x5c, 0xda, 0xb5, 0x08, 0x56, 0xe9, 0xad, 0xfe, 0x25, 0x3f, 0xf5, 0x44, 0xd5, - 0xbc, 0x52, 0xbd, 0x33, 0xb4, 0xa7, 0xf9, 0xd3, 0x39, 0x3f, 0x7f, 0x3a, 0xe7, 0x75, 0x30, 0xcc, 0x8c, 0xad, 0x5b, - 0x15, 0xbc, 0x5c, 0xe0, 0xba, 0x84, 0x32, 0x3c, 0xf5, 0xe5, 0x3f, 0x3c, 0x0b, 0x53, 0x19, 0x90, 0x9a, 0x6c, 0x60, - 0x4c, 0x65, 0xe0, 0x74, 0x73, 0x43, 0x47, 0xd3, 0x8d, 0x56, 0x26, 0x9a, 0x19, 0x4f, 0x86, 0x1a, 0x72, 0x1a, 0x73, - 0xb0, 0xa7, 0x87, 0x8c, 0x43, 0xad, 0x66, 0xfc, 0x68, 0xb4, 0x05, 0x6d, 0x40, 0xe1, 0x67, 0x30, 0x53, 0x01, 0x06, - 0xd1, 0xf9, 0x36, 0xce, 0x3e, 0x49, 0x7f, 0x67, 0x99, 0xf3, 0x7c, 0xd9, 0x10, 0xc1, 0xaf, 0x34, 0xe9, 0x76, 0x59, - 0x04, 0xfc, 0x98, 0xd1, 0x58, 0xc6, 0xef, 0xc5, 0xa0, 0x7f, 0x91, 0x3e, 0xaa, 0x11, 0x38, 0x17, 0x20, 0xaf, 0x46, - 0x98, 0x06, 0x8a, 0x86, 0xf6, 0x1a, 0xfa, 0x42, 0xa9, 0x32, 0x7d, 0xed, 0x69, 0x4d, 0x2b, 0xb2, 0xb4, 0xd2, 0x4f, - 0xc6, 0x14, 0xb3, 0x2a, 0x71, 0xec, 0x69, 0xde, 0x37, 0xc8, 0x24, 0x5f, 0x38, 0xcb, 0x68, 0x29, 0xa7, 0xc6, 0x02, - 0xdd, 0x2a, 0xd4, 0xda, 0x85, 0xa7, 0x37, 0x68, 0x1c, 0x18, 0x2a, 0xca, 0xbe, 0x5f, 0x62, 0x8f, 0x78, 0xdf, 0x7e, - 0xc0, 0x47, 0x28, 0xb8, 0xed, 0x39, 0x49, 0x18, 0xa9, 0xfa, 0x5e, 0x51, 0xbc, 0xef, 0x9b, 0x64, 0x24, 0x37, 0x34, - 0x31, 0xd8, 0xa8, 0x85, 0xd3, 0xd3, 0x38, 0x5d, 0x38, 0x3d, 0xc5, 0xa9, 0x45, 0x5b, 0x32, 0xd3, 0xc8, 0x48, 0xac, - 0x5d, 0xe1, 0x44, 0x2d, 0xbf, 0xc9, 0xaf, 0xb2, 0x0d, 0x09, 0x14, 0x95, 0xd6, 0x5e, 0x95, 0x1e, 0xf4, 0x02, 0x36, - 0xe0, 0x4e, 0x75, 0x20, 0xf2, 0x12, 0x5f, 0x2d, 0x40, 0x00, 0x46, 0xf7, 0x3f, 0x58, 0x4d, 0xe9, 0xb4, 0xd1, 0x6e, - 0x4e, 0x39, 0x26, 0x50, 0x72, 0xcd, 0x07, 0x93, 0x90, 0x37, 0x38, 0x71, 0x5e, 0x43, 0xa0, 0x42, 0x1c, 0x43, 0x90, - 0x67, 0xc6, 0x16, 0xf3, 0xfb, 0xb7, 0xaa, 0xfa, 0xa1, 0xa2, 0x53, 0xa8, 0x21, 0x66, 0x5f, 0x68, 0x9e, 0xf0, 0x2b, - 0x72, 0x5e, 0xe6, 0xe4, 0xd2, 0x73, 0x8f, 0xe4, 0xe3, 0xd1, 0xd9, 0x63, 0x24, 0xe8, 0xdb, 0xd5, 0x8e, 0xe6, 0x26, - 0x2c, 0xc5, 0x97, 0xec, 0x67, 0x2a, 0xff, 0x54, 0x2d, 0x14, 0xcf, 0xac, 0xce, 0x3b, 0x65, 0xb1, 0xab, 0x2a, 0x76, - 0x49, 0x67, 0xd0, 0x29, 0x78, 0x33, 0x20, 0x82, 0x8e, 0xe0, 0x24, 0x49, 0x20, 0x11, 0x8d, 0x02, 0xed, 0xd9, 0x4c, - 0x24, 0xc1, 0x5c, 0x80, 0x25, 0xcb, 0x1b, 0x2e, 0x76, 0xed, 0x2f, 0xdd, 0x92, 0xcc, 0x13, 0x70, 0xd1, 0x3c, 0xd3, - 0xe9, 0xe5, 0x3a, 0xf2, 0x39, 0xc2, 0xd4, 0xba, 0xa9, 0xcd, 0xab, 0x84, 0xf3, 0x55, 0xb9, 0x89, 0x95, 0x78, 0x1b, - 0xa8, 0x19, 0xaf, 0x56, 0x2a, 0x7f, 0x62, 0x72, 0x4a, 0x6b, 0x64, 0xa4, 0xb0, 0x3f, 0xa4, 0xaa, 0x6d, 0x94, 0x70, - 0x1b, 0xd2, 0x6f, 0xe7, 0xa7, 0xed, 0x42, 0xf1, 0x5b, 0x3b, 0x18, 0xf2, 0xff, 0xf5, 0x1a, 0xdb, 0x85, 0xa8, 0x51, - 0x60, 0x84, 0x70, 0xb1, 0x08, 0x10, 0x9e, 0x0b, 0xa7, 0x6c, 0x88, 0x85, 0x07, 0x8f, 0xc2, 0xd9, 0xeb, 0xac, 0xab, - 0xde, 0x6f, 0xfe, 0x3e, 0xa8, 0xbf, 0x8f, 0x42, 0xe3, 0x5c, 0xaf, 0xf1, 0x6f, 0x15, 0x3f, 0xfe, 0xd0, 0x42, 0xb1, - 0x81, 0x11, 0x6e, 0x22, 0x68, 0xa5, 0x68, 0xb6, 0x25, 0xd5, 0xfa, 0xaa, 0x80, 0x22, 0x84, 0xdd, 0x49, 0x55, 0x0b, - 0x26, 0xac, 0x3b, 0x3d, 0xc1, 0xf2, 0xf9, 0xc0, 0xe9, 0x3f, 0xa6, 0xed, 0x39, 0x49, 0x54, 0xfa, 0xac, 0x4f, 0x85, - 0x27, 0x4f, 0xa2, 0xd5, 0x3e, 0xf3, 0x2f, 0xc1, 0xad, 0xaf, 0x7e, 0xb5, 0xac, 0x46, 0xca, 0x4c, 0x31, 0x8b, 0xc2, - 0x6b, 0xb7, 0x86, 0x99, 0xf1, 0x8a, 0x62, 0xd2, 0x34, 0x7b, 0x58, 0x0a, 0x8a, 0xbb, 0xba, 0x66, 0x65, 0x4e, 0xe7, - 0x65, 0x46, 0xe6, 0x54, 0x82, 0x71, 0x54, 0x7c, 0x8f, 0x33, 0x7e, 0xa3, 0xad, 0x18, 0x18, 0x75, 0x3c, 0xec, 0xf4, - 0x1c, 0xeb, 0x84, 0x01, 0x7a, 0xe5, 0xb9, 0x89, 0xf0, 0x1a, 0x2f, 0x81, 0x53, 0xa7, 0x36, 0x7d, 0x10, 0x69, 0xe5, - 0xa8, 0x29, 0xcf, 0xb0, 0xc5, 0x94, 0x5e, 0xe3, 0x36, 0x91, 0x76, 0xfb, 0x2f, 0x76, 0x5e, 0x05, 0x9f, 0xd8, 0xd3, - 0x11, 0x1e, 0xd1, 0xa4, 0xb4, 0x08, 0x5e, 0x24, 0xca, 0xc3, 0xf6, 0xc0, 0x73, 0x7e, 0x25, 0xd6, 0x5e, 0x4e, 0x94, - 0xf2, 0x7c, 0xe6, 0x39, 0x88, 0x21, 0x33, 0xb4, 0x84, 0x8e, 0xcf, 0x05, 0x47, 0x62, 0x5c, 0xbd, 0x4f, 0x90, 0xc4, - 0x49, 0xb0, 0xf7, 0xd7, 0x3e, 0x17, 0x69, 0x75, 0xfc, 0xf2, 0x3e, 0x61, 0x21, 0xb6, 0x6b, 0xda, 0x05, 0x2a, 0x64, - 0x3f, 0xf8, 0x53, 0x02, 0x5e, 0x13, 0xf2, 0xb2, 0xef, 0xd4, 0x6e, 0x9d, 0x75, 0xce, 0xff, 0x0b, 0x87, 0x43, 0x8f, - 0x5e, 0x39, 0x9a, 0x6b, 0x26, 0x60, 0x72, 0xc0, 0x51, 0xd5, 0xf7, 0xa2, 0xc4, 0xd1, 0xf0, 0x40, 0xa0, 0xac, 0x12, - 0xff, 0xb0, 0x7e, 0x30, 0x24, 0xa0, 0xf2, 0x88, 0xfb, 0xee, 0xd6, 0xee, 0x9a, 0x76, 0x65, 0x13, 0x2e, 0x57, 0x32, - 0xfe, 0x1b, 0x10, 0xa6, 0xef, 0x03, 0xce, 0xe1, 0xe8, 0xac, 0xfb, 0x02, 0x6e, 0x32, 0xe7, 0x14, 0xa3, 0xb8, 0x96, - 0x7c, 0xc1, 0xf6, 0x94, 0x90, 0xd7, 0xc4, 0x2e, 0xbf, 0x58, 0x47, 0xa1, 0x57, 0x9d, 0xd4, 0xcb, 0xb2, 0xe8, 0xbf, - 0x80, 0x75, 0x82, 0x78, 0x79, 0x9e, 0xe9, 0xb2, 0x6f, 0x12, 0x87, 0x2b, 0xac, 0xb0, 0x99, 0x95, 0x86, 0x66, 0x61, - 0xfa, 0x98, 0xd2, 0x75, 0x2c, 0x30, 0x0e, 0x55, 0xce, 0x76, 0x09, 0x6c, 0x49, 0xaa, 0x99, 0xc6, 0xfb, 0x0d, 0x59, - 0x85, 0x49, 0x4b, 0x2b, 0x8d, 0x17, 0xe8, 0x1e, 0x6b, 0x3c, 0xff, 0x4b, 0x30, 0x4c, 0x18, 0x67, 0x2f, 0xc3, 0xc4, - 0x4f, 0x2a, 0xb8, 0xaa, 0x79, 0x82, 0xc3, 0xe6, 0x9d, 0xf9, 0xab, 0xb6, 0x75, 0xc0, 0x4f, 0xb2, 0x2f, 0x1a, 0xc3, - 0x98, 0x2c, 0x2c, 0x06, 0xee, 0xd2, 0xd8, 0xcf, 0xc1, 0xc2, 0x0d, 0xfb, 0xe8, 0x1b, 0x05, 0x5f, 0xfa, 0xf7, 0x77, - 0xa0, 0x4e, 0x62, 0xd4, 0x75, 0x69, 0x25, 0xa5, 0xbf, 0x46, 0xbe, 0x68, 0x03, 0x88, 0x34, 0x4f, 0x7d, 0x8c, 0x85, - 0x53, 0x41, 0xc4, 0x92, 0x12, 0x61, 0xed, 0x8c, 0x30, 0x6b, 0x65, 0xf9, 0xfe, 0x6c, 0xea, 0x08, 0x05, 0x5d, 0x3b, - 0xcb, 0x9f, 0x73, 0xe9, 0x66, 0x11, 0x5d, 0x37, 0xc0, 0x58, 0x96, 0x1d, 0x51, 0x0e, 0x9e, 0x60, 0xdb, 0xea, 0xae, - 0x88, 0xbc, 0xa1, 0x3e, 0x49, 0xac, 0x4e, 0xe8, 0x23, 0x8e, 0xd6, 0xf9, 0x68, 0x13, 0x4d, 0xbe, 0x59, 0xe5, 0xf2, - 0xd3, 0x26, 0xe6, 0x34, 0xd4, 0xc5, 0x0c, 0x62, 0x38, 0xf8, 0x4e, 0x84, 0xce, 0xa6, 0x7d, 0xdc, 0xa0, 0xcd, 0xc2, - 0x19, 0x9a, 0x86, 0xeb, 0x10, 0x6f, 0x2a, 0x61, 0x51, 0xd9, 0x42, 0xd3, 0x29, 0x9d, 0x70, 0x75, 0x57, 0x98, 0x9b, - 0x73, 0xee, 0xa9, 0xe5, 0x1a, 0xba, 0x26, 0x02, 0x85, 0xe2, 0xb1, 0xe5, 0x1a, 0x7d, 0x75, 0x50, 0xa9, 0x42, 0xa7, - 0xdb, 0x79, 0xf6, 0x2a, 0x16, 0x1c, 0xae, 0x8c, 0xc5, 0x1c, 0x60, 0xe0, 0xa7, 0x71, 0xf2, 0xbe, 0x8a, 0xec, 0x54, - 0x5a, 0x72, 0xde, 0xa5, 0xe4, 0xc0, 0x25, 0xf5, 0xcf, 0x6d, 0x5e, 0x9d, 0x2f, 0x73, 0x9b, 0x29, 0x78, 0x0b, 0x6e, - 0xe9, 0xb4, 0x1e, 0x87, 0xa2, 0xed, 0x10, 0x53, 0xe5, 0x5e, 0x29, 0x25, 0xcf, 0x9a, 0x6a, 0x28, 0x59, 0xe7, 0x18, - 0xeb, 0x8f, 0x0e, 0x51, 0x3e, 0xc4, 0x34, 0xe2, 0x70, 0xa7, 0x62, 0x55, 0xf2, 0x64, 0x25, 0x48, 0x88, 0xd5, 0x36, - 0xcc, 0x0c, 0x5a, 0x59, 0x26, 0xaa, 0x7d, 0x77, 0x9e, 0x47, 0x89, 0x31, 0xbe, 0x32, 0xcb, 0xc2, 0xd7, 0xe5, 0x0e, - 0x74, 0x82, 0x34, 0xb7, 0x9b, 0xc0, 0xb2, 0x5e, 0xa3, 0x11, 0xe6, 0xd3, 0x38, 0x4a, 0x48, 0x40, 0x24, 0xd5, 0x2f, - 0x48, 0x97, 0x12, 0xee, 0x7a, 0xf4, 0x67, 0xf9, 0x20, 0x84, 0xf9, 0xf0, 0xe5, 0x84, 0x53, 0x97, 0x60, 0x3b, 0xde, - 0xe4, 0xb5, 0x02, 0x95, 0x44, 0xd3, 0x6b, 0x2b, 0x4e, 0x75, 0xa9, 0x7a, 0x5b, 0x8c, 0xe2, 0x34, 0xfd, 0xaa, 0x27, - 0xb9, 0xd9, 0x62, 0x61, 0x2c, 0x18, 0x04, 0x1a, 0x50, 0xd1, 0x4d, 0x00, 0xab, 0x31, 0x16, 0x11, 0xaf, 0xcb, 0x0f, - 0x99, 0x54, 0x53, 0x3a, 0x54, 0xed, 0xda, 0xef, 0x0f, 0xee, 0xdd, 0xf0, 0x70, 0xfc, 0xf8, 0x9f, 0xfb, 0xbd, 0x1e, - 0x54, 0x41, 0x97, 0xf0, 0x71, 0x67, 0x3b, 0xa6, 0x42, 0x01, 0xb2, 0xb2, 0x7d, 0x79, 0x01, 0x50, 0x63, 0x2a, 0x4e, - 0xba, 0x6b, 0xeb, 0xde, 0xb4, 0xe0, 0xd3, 0xba, 0x09, 0xdf, 0xfb, 0xe6, 0x7c, 0x6f, 0x98, 0x5a, 0x77, 0xf8, 0xdc, - 0xe5, 0x33, 0x9e, 0x02, 0x99, 0x0b, 0x83, 0xf7, 0x90, 0xe2, 0x26, 0x4c, 0x32, 0xe4, 0x6c, 0x9a, 0x77, 0xda, 0xb2, - 0xbc, 0xd6, 0x52, 0xb2, 0x23, 0x26, 0xec, 0xb9, 0xf2, 0x47, 0xde, 0x93, 0xf8, 0x48, 0x35, 0x04, 0xe0, 0x04, 0xa5, - 0x8d, 0xc0, 0x5c, 0xc5, 0xcd, 0xfc, 0xa9, 0x21, 0x88, 0x08, 0xf4, 0x4c, 0xe1, 0xde, 0xce, 0x1f, 0xce, 0xc6, 0x08, - 0x41, 0x2a, 0xf8, 0x66, 0xa5, 0x36, 0x6b, 0x78, 0xe9, 0x3f, 0x66, 0x67, 0x3b, 0x32, 0xd3, 0xdd, 0x26, 0x51, 0x5b, - 0xb6, 0xa6, 0x02, 0xcc, 0x20, 0x1a, 0x03, 0x17, 0x3c, 0x30, 0xa6, 0xf1, 0xd1, 0x9b, 0x71, 0x62, 0xad, 0xdd, 0xf2, - 0xe5, 0x8c, 0x8f, 0x1c, 0x7d, 0x4e, 0x16, 0xa8, 0x71, 0x77, 0x18, 0xcb, 0xcb, 0xf8, 0x6e, 0x3d, 0x6e, 0x56, 0xf7, - 0x20, 0x0b, 0x08, 0xd0, 0x6b, 0xb1, 0xae, 0x99, 0xe8, 0x55, 0xc2, 0x9d, 0x54, 0x9a, 0x27, 0x95, 0x98, 0x59, 0xe5, - 0xe5, 0xb5, 0xd3, 0xcb, 0x90, 0xbc, 0x0c, 0xd6, 0x6e, 0x54, 0xa1, 0xc7, 0xd6, 0x58, 0xe3, 0xb8, 0x66, 0x92, 0xa5, - 0xf1, 0xd7, 0xf0, 0x51, 0x3f, 0xbc, 0x5c, 0x45, 0xeb, 0xa6, 0x5a, 0xb4, 0x5e, 0x5b, 0x39, 0xcc, 0x97, 0xbc, 0xf8, - 0x85, 0x2d, 0xb6, 0xf0, 0x7a, 0xb1, 0xb9, 0x8f, 0xa8, 0x4c, 0x25, 0xaa, 0xd3, 0x4a, 0x54, 0xa6, 0x89, 0xc9, 0xcf, - 0x9e, 0x77, 0x01, 0x5c, 0x7f, 0xd4, 0xa9, 0x55, 0xfc, 0xa8, 0x32, 0xaa, 0xfc, 0x51, 0x23, 0x54, 0xeb, 0x13, 0x40, - 0x94, 0xc0, 0xac, 0x91, 0x87, 0x99, 0xb5, 0x61, 0x32, 0x29, 0xeb, 0x0b, 0x72, 0x85, 0xc3, 0xb4, 0xaa, 0x56, 0xbd, - 0xff, 0xe5, 0x86, 0xeb, 0x2f, 0x9b, 0xfc, 0x6e, 0xc6, 0xf5, 0xbe, 0x92, 0xfd, 0x60, 0x39, 0x18, 0x2c, 0xb4, 0xf1, - 0xe3, 0x16, 0xea, 0x7e, 0x8c, 0x1e, 0x86, 0xe0, 0xca, 0xf4, 0x35, 0x88, 0xfa, 0x95, 0x20, 0xf3, 0x23, 0xf2, 0x5a, - 0x01, 0x72, 0xb1, 0xd7, 0x37, 0xd2, 0xbb, 0xd6, 0x20, 0x1a, 0x1b, 0x12, 0xa9, 0xb3, 0x48, 0x86, 0x21, 0xb5, 0x7d, - 0xb8, 0xce, 0xe8, 0x68, 0xde, 0xe4, 0x2d, 0xbe, 0xa9, 0x86, 0x26, 0xcc, 0xb7, 0x0a, 0xab, 0x91, 0x9e, 0x93, 0xa6, - 0x29, 0x69, 0x56, 0xf6, 0x4d, 0xd0, 0xaf, 0x5e, 0x44, 0x26, 0x34, 0x06, 0x5f, 0x64, 0x70, 0xe0, 0xb7, 0x2b, 0x3a, - 0x0a, 0xd1, 0x4f, 0x79, 0x73, 0xff, 0x55, 0x30, 0x4a, 0xfd, 0x00, 0xb1, 0x6f, 0xd1, 0x05, 0x66, 0x67, 0x05, 0x7c, - 0x0b, 0xeb, 0xed, 0x05, 0x79, 0x94, 0xc6, 0xce, 0xc2, 0x11, 0x35, 0x61, 0xad, 0xf7, 0xb0, 0x31, 0xb2, 0xde, 0xf9, - 0xe7, 0xba, 0x2b, 0x51, 0x84, 0x4b, 0xcf, 0x65, 0x82, 0xea, 0xc0, 0x45, 0xe5, 0x5b, 0x6a, 0x2f, 0xa5, 0x09, 0xa7, - 0x22, 0x5f, 0x0c, 0x1b, 0xde, 0x87, 0xc3, 0xbe, 0x86, 0xc3, 0x0f, 0x7c, 0xd3, 0x5a, 0x6b, 0x26, 0x5b, 0x35, 0xb2, - 0x0b, 0x2e, 0xb8, 0xc0, 0xb0, 0x83, 0x81, 0xf5, 0xec, 0x7d, 0x1e, 0x82, 0xa6, 0x03, 0x61, 0xc1, 0x58, 0x34, 0xb7, - 0x01, 0x4f, 0x3e, 0x60, 0xa0, 0xd4, 0xcd, 0xdb, 0x6d, 0xd9, 0x22, 0xb9, 0x0d, 0x0c, 0xa9, 0xc5, 0x38, 0xcb, 0xe2, - 0xc0, 0x99, 0x3a, 0x9b, 0xe7, 0xfa, 0x46, 0x19, 0x77, 0xad, 0x44, 0x49, 0x1b, 0xbf, 0x9e, 0x0d, 0xee, 0x19, 0x29, - 0x74, 0x93, 0xff, 0x2f, 0x21, 0xe5, 0x5d, 0xae, 0x0a, 0x82, 0x6e, 0x70, 0xd2, 0xd7, 0x5a, 0xba, 0xc8, 0x4c, 0x44, - 0x77, 0x80, 0x2b, 0x68, 0x52, 0xae, 0x3d, 0x41, 0xd2, 0x67, 0x2b, 0xb7, 0x39, 0x11, 0xdb, 0x3d, 0x23, 0x9d, 0xd9, - 0x12, 0xea, 0xf3, 0x0b, 0x56, 0x97, 0x77, 0xee, 0x28, 0xe5, 0x73, 0x65, 0xcc, 0x78, 0x24, 0xcd, 0xb3, 0x3f, 0x4a, - 0x21, 0x4d, 0xc6, 0xf5, 0x22, 0x32, 0x9f, 0x97, 0xdb, 0x5b, 0x81, 0x07, 0x9e, 0xaa, 0xc0, 0x10, 0xb4, 0xde, 0x4b, - 0x7c, 0xf3, 0x55, 0x0d, 0xca, 0x3a, 0x19, 0x3f, 0x3e, 0x56, 0xbf, 0x35, 0xf6, 0xa2, 0xd2, 0xe4, 0x10, 0xcd, 0xd4, - 0x76, 0x5a, 0xe7, 0x2d, 0xa8, 0x65, 0x6a, 0xd7, 0x09, 0xa4, 0xd1, 0x39, 0xcf, 0x56, 0x91, 0x98, 0x6a, 0xfe, 0x6b, - 0xa6, 0x84, 0xbe, 0xaf, 0x50, 0x25, 0xfe, 0x19, 0x17, 0x89, 0x30, 0xe2, 0x3c, 0x50, 0x0f, 0x61, 0xd5, 0x12, 0x87, - 0xca, 0xbb, 0x31, 0x8c, 0x0b, 0x66, 0xe1, 0x10, 0x1b, 0x65, 0x7e, 0x16, 0x93, 0x4f, 0x97, 0x05, 0x4f, 0xce, 0xaf, - 0x64, 0x99, 0x75, 0xb3, 0x4f, 0x88, 0x87, 0x47, 0xed, 0x21, 0xd5, 0x2d, 0x0b, 0xad, 0x59, 0x59, 0x2f, 0xca, 0x6e, - 0xd4, 0x3e, 0x8b, 0x2f, 0xc8, 0x68, 0xd2, 0x1e, 0x78, 0xdc, 0x4b, 0x12, 0x48, 0x55, 0x2d, 0xdb, 0xcc, 0x21, 0xf2, - 0xf0, 0xf2, 0x21, 0x4f, 0xf9, 0xac, 0x4c, 0x54, 0x94, 0xb6, 0xc3, 0xe0, 0x81, 0xfb, 0x3a, 0x9a, 0xa0, 0x53, 0xac, - 0xd3, 0x15, 0x44, 0x6f, 0xc0, 0xac, 0x37, 0x8a, 0x3d, 0xab, 0xac, 0x4a, 0x36, 0xed, 0xe5, 0x1a, 0xbf, 0x71, 0x90, - 0x16, 0xdc, 0xd8, 0xe3, 0x48, 0x5d, 0x2f, 0x4a, 0xd7, 0xf5, 0x66, 0x6f, 0xb9, 0xd3, 0xea, 0x03, 0x3e, 0xfd, 0x94, - 0x6c, 0xc9, 0x5f, 0x2f, 0x5d, 0x93, 0x56, 0x6e, 0x0b, 0x1a, 0x35, 0xd6, 0x64, 0xbc, 0xe9, 0x4b, 0x10, 0x15, 0x55, - 0x09, 0x9e, 0x53, 0x7e, 0x36, 0x8c, 0x46, 0x32, 0xd1, 0x80, 0x7c, 0x69, 0xed, 0x7e, 0xae, 0x55, 0xbc, 0xb5, 0x3a, - 0x74, 0xca, 0xea, 0xe0, 0xf8, 0xd2, 0xb9, 0xd9, 0xba, 0x28, 0x14, 0x20, 0x01, 0xf6, 0x50, 0x43, 0x8e, 0x9d, 0xd5, - 0x8c, 0xdb, 0xdb, 0x6f, 0x1b, 0x31, 0x90, 0x62, 0x2e, 0xfb, 0xae, 0x1f, 0x22, 0x64, 0x32, 0x23, 0x4c, 0xac, 0x91, - 0xdd, 0x18, 0xa3, 0x09, 0x09, 0xc9, 0x78, 0x2d, 0x84, 0x84, 0xde, 0xea, 0x3c, 0x01, 0x5c, 0x12, 0x4f, 0x06, 0x6b, - 0x0a, 0x66, 0x45, 0x5e, 0x57, 0x5b, 0x71, 0x25, 0x16, 0x89, 0xf0, 0x75, 0x51, 0x23, 0xdb, 0x26, 0x58, 0x41, 0x8b, - 0x62, 0x0e, 0x14, 0x3a, 0xf3, 0x0d, 0x5f, 0x30, 0xe1, 0x9c, 0xdf, 0x75, 0x6b, 0x94, 0x96, 0x99, 0xa0, 0xaf, 0x1a, - 0x16, 0xb6, 0xdb, 0x2f, 0x10, 0xd7, 0x34, 0x03, 0x03, 0x8a, 0xb2, 0x43, 0x35, 0xbf, 0x03, 0x4b, 0x94, 0x9c, 0xb4, - 0x91, 0x9b, 0x5f, 0xa1, 0x63, 0x82, 0x18, 0x58, 0x68, 0x6c, 0x2f, 0x64, 0x2b, 0xd1, 0x9a, 0x1a, 0xb2, 0x11, 0x36, - 0xc1, 0x07, 0xa7, 0xa7, 0x70, 0x6d, 0x02, 0x55, 0xd3, 0x94, 0x46, 0x60, 0x9e, 0xf0, 0x40, 0x69, 0xbe, 0x9f, 0x5d, - 0x10, 0xd8, 0x98, 0xb7, 0x22, 0x8b, 0x03, 0x92, 0x12, 0x1b, 0x58, 0x78, 0xd4, 0x58, 0x2f, 0xef, 0x34, 0x8e, 0x2e, - 0xab, 0x51, 0x57, 0xa4, 0x58, 0x2a, 0x69, 0xc6, 0xa2, 0xc1, 0x98, 0x92, 0x90, 0x64, 0x2d, 0x04, 0x6b, 0x36, 0xfc, - 0xcd, 0x7b, 0x54, 0x7f, 0x6b, 0x2e, 0x60, 0x4f, 0x30, 0xdb, 0x79, 0x31, 0xbd, 0xbe, 0x1a, 0x65, 0xdb, 0xba, 0x85, - 0x79, 0x4f, 0x61, 0xd0, 0x9c, 0x8f, 0x29, 0x65, 0xce, 0x33, 0x40, 0x99, 0x49, 0x16, 0x01, 0x39, 0x0c, 0xb8, 0x07, - 0xa4, 0x2b, 0x2f, 0x0e, 0x7b, 0x19, 0xad, 0x9c, 0xb9, 0xf0, 0xf2, 0x72, 0x75, 0x34, 0x41, 0x39, 0x50, 0xe4, 0xc0, - 0x8b, 0xeb, 0x17, 0x4f, 0x73, 0x2d, 0x56, 0x59, 0x6f, 0x58, 0xa8, 0xae, 0xb7, 0xf4, 0xb9, 0xf5, 0x31, 0xf0, 0xf9, - 0xb5, 0x96, 0x5a, 0x34, 0x7f, 0xe8, 0xb5, 0xd5, 0xa4, 0xa0, 0xdd, 0xbf, 0xf5, 0x64, 0x14, 0x39, 0xa5, 0xd5, 0xb2, - 0xf8, 0x54, 0xbb, 0xe8, 0x29, 0x5a, 0xca, 0x26, 0xef, 0xb2, 0x87, 0xaa, 0x0b, 0xb3, 0xd6, 0x51, 0x98, 0xd5, 0xf6, - 0x28, 0xef, 0xec, 0xbd, 0x36, 0x0b, 0xca, 0x94, 0x56, 0x9f, 0x70, 0xbd, 0xf1, 0x02, 0xaa, 0xf9, 0x96, 0x1a, 0x8b, - 0x63, 0x7e, 0x49, 0x5d, 0xd9, 0x28, 0x7b, 0x9e, 0xd6, 0xb8, 0xbc, 0xeb, 0xa2, 0x17, 0x53, 0xc0, 0x29, 0xca, 0x4a, - 0x17, 0x37, 0x72, 0x09, 0x5d, 0x2b, 0xd2, 0x1a, 0xf8, 0x0c, 0x8c, 0x62, 0xb2, 0x9a, 0x7c, 0x90, 0xf4, 0xdf, 0x99, - 0xf5, 0x57, 0x9d, 0xb9, 0xfe, 0xa6, 0x17, 0xae, 0xbf, 0x5e, 0x54, 0x56, 0x85, 0x7d, 0x63, 0xec, 0x19, 0x70, 0x05, - 0x93, 0x4a, 0x7c, 0xa5, 0x73, 0x8e, 0x08, 0x6a, 0x0c, 0x15, 0xb2, 0x9b, 0x2f, 0x2c, 0x6c, 0x88, 0x3c, 0x3b, 0xbb, - 0xcc, 0xd2, 0x35, 0xd6, 0x98, 0xdc, 0xdf, 0xbb, 0x82, 0x59, 0x17, 0x56, 0x2d, 0xe3, 0x55, 0xce, 0xa5, 0x28, 0x92, - 0x62, 0x72, 0x91, 0x83, 0x14, 0x21, 0x80, 0x90, 0x8b, 0x24, 0xd0, 0x51, 0xda, 0xa2, 0x68, 0x24, 0x14, 0x80, 0xfa, - 0x72, 0xbe, 0x05, 0x08, 0x1c, 0x82, 0x39, 0x21, 0x08, 0x46, 0xf2, 0x2c, 0x20, 0x72, 0x42, 0xf6, 0x4e, 0x54, 0x88, - 0x30, 0xab, 0x83, 0x13, 0x68, 0x50, 0x16, 0xd8, 0xa2, 0x79, 0x99, 0x09, 0x8a, 0x2a, 0x44, 0x84, 0x65, 0xc5, 0xe5, - 0xea, 0x8f, 0x2e, 0x6d, 0xbd, 0x5c, 0x53, 0xe8, 0x92, 0xe5, 0xd3, 0xec, 0x1a, 0xca, 0xfc, 0x00, 0xfc, 0x6b, 0x51, - 0x07, 0xf6, 0xb4, 0x83, 0x34, 0xb0, 0x15, 0x17, 0xa7, 0xe2, 0xfa, 0xe7, 0x9c, 0x02, 0x42, 0x49, 0x4f, 0x2b, 0xc4, - 0x5c, 0xa0, 0x73, 0x0f, 0x71, 0x0d, 0x0a, 0x80, 0xe1, 0x92, 0xf1, 0xc2, 0x50, 0xdb, 0x7a, 0x7a, 0xea, 0xfc, 0x1e, - 0xc9, 0x35, 0x3a, 0x34, 0xf1, 0x22, 0xca, 0xdc, 0x65, 0x61, 0x3b, 0x52, 0xbc, 0xe7, 0x46, 0xb5, 0xc7, 0x94, 0x97, - 0xe7, 0x7b, 0xe8, 0x2f, 0xc4, 0xbc, 0x6d, 0x82, 0xaa, 0xa7, 0x7b, 0x6f, 0xad, 0x8b, 0xc0, 0x8f, 0x5e, 0x16, 0x05, - 0xea, 0xdb, 0x15, 0x23, 0x0d, 0x3d, 0xd9, 0xb1, 0x42, 0x97, 0x69, 0x59, 0xdb, 0xbb, 0xcd, 0xfa, 0xb6, 0x06, 0x83, - 0x8c, 0x7d, 0xa5, 0x78, 0x05, 0x84, 0x4d, 0xf1, 0x64, 0x26, 0xda, 0x6a, 0x08, 0x4e, 0x10, 0xca, 0xe9, 0xea, 0xf0, - 0xad, 0x20, 0x45, 0x45, 0x60, 0xeb, 0x7e, 0xac, 0x3d, 0xd4, 0xbe, 0x1b, 0x4a, 0xa7, 0x67, 0x8f, 0x1a, 0x1c, 0x3d, - 0xe5, 0x05, 0x3b, 0x34, 0x52, 0x97, 0x16, 0x21, 0x55, 0xf1, 0xb6, 0x01, 0xab, 0xf4, 0xe0, 0xd3, 0x06, 0x33, 0x9f, - 0xb1, 0xe2, 0x0e, 0x72, 0x15, 0x1b, 0xd1, 0x08, 0x05, 0xdd, 0x23, 0xf2, 0xf3, 0xfe, 0x82, 0x3d, 0x37, 0xe6, 0x56, - 0xf0, 0x4b, 0xc0, 0x30, 0xd5, 0x2b, 0x4c, 0x58, 0x2d, 0x8d, 0x16, 0x60, 0xe9, 0x8d, 0x67, 0xab, 0x66, 0xaf, 0x7c, - 0x2a, 0x95, 0x14, 0xab, 0x10, 0xbe, 0x53, 0x65, 0x05, 0x27, 0x1f, 0x62, 0x30, 0xc4, 0x4f, 0xdf, 0x56, 0x7e, 0xbd, - 0xea, 0xe6, 0x50, 0xf1, 0xa8, 0xb1, 0xa7, 0x3d, 0x8c, 0x92, 0xda, 0xf0, 0xaa, 0xc3, 0x10, 0x77, 0x67, 0xd9, 0x99, - 0x3d, 0x45, 0xd6, 0x54, 0x02, 0xf8, 0x15, 0x9b, 0xa2, 0x2e, 0x83, 0x8f, 0x88, 0x79, 0x23, 0x60, 0xfe, 0x66, 0x50, - 0x8c, 0xe6, 0x4d, 0x15, 0xad, 0x16, 0xf7, 0x26, 0x74, 0xc9, 0xb8, 0x44, 0xd9, 0xd3, 0x87, 0xf4, 0x3b, 0x24, 0x18, - 0x39, 0xdd, 0xac, 0xb8, 0xaf, 0x07, 0x87, 0x63, 0x1f, 0x5b, 0x97, 0x30, 0x05, 0x40, 0x8b, 0x5c, 0x4c, 0x80, 0xe9, - 0x7a, 0xcd, 0xb1, 0x90, 0xad, 0x0b, 0x49, 0x34, 0x34, 0x85, 0xa2, 0x6e, 0x41, 0x30, 0x31, 0x2a, 0xed, 0xf6, 0x83, - 0xb4, 0x30, 0x9e, 0x33, 0x95, 0x5f, 0x90, 0x1f, 0x4e, 0x7d, 0xd9, 0x1a, 0x7b, 0xa3, 0x63, 0x56, 0x34, 0xf1, 0xa4, - 0x99, 0x80, 0x48, 0x00, 0x2f, 0x17, 0xd1, 0x66, 0x9c, 0xa7, 0x92, 0x9a, 0xd7, 0x76, 0x81, 0x98, 0x01, 0x02, 0x9d, - 0x6a, 0x49, 0xa5, 0x78, 0x73, 0x3e, 0x48, 0x71, 0x10, 0x80, 0xb2, 0x63, 0x36, 0xb4, 0xa5, 0xa0, 0x1e, 0x32, 0xb4, - 0xd9, 0x5c, 0xdb, 0x5a, 0xee, 0xd4, 0xd9, 0xac, 0x45, 0x6d, 0x99, 0x3f, 0xdc, 0xe6, 0x17, 0x11, 0xe3, 0xa2, 0xee, - 0x13, 0x09, 0xd5, 0x14, 0x23, 0xd0, 0x79, 0x02, 0xf2, 0x7a, 0x38, 0xe1, 0xcd, 0x7d, 0xbf, 0x6f, 0xe9, 0x9a, 0x64, - 0xf1, 0xa2, 0xc0, 0xb9, 0x2f, 0x53, 0x78, 0x99, 0x70, 0x02, 0x97, 0x78, 0xa8, 0x33, 0x1f, 0x67, 0x5b, 0x9d, 0x29, - 0x46, 0xa0, 0xa4, 0x16, 0x91, 0x4d, 0x7a, 0x43, 0x90, 0x9a, 0xf1, 0x32, 0x10, 0x6a, 0x47, 0xa9, 0x01, 0xc9, 0xfb, - 0xba, 0x32, 0x5e, 0x4b, 0xb6, 0x2e, 0x42, 0xd9, 0x6c, 0xc7, 0xb5, 0xbb, 0x9c, 0x4e, 0x77, 0x37, 0x2b, 0xe4, 0x0e, - 0x28, 0x9d, 0x0d, 0x97, 0x11, 0xdf, 0xd0, 0xec, 0x40, 0x81, 0xd0, 0x6e, 0xdf, 0x66, 0x65, 0xcc, 0xc2, 0xe2, 0x75, - 0x43, 0x8e, 0x4a, 0xfe, 0x50, 0xde, 0x9d, 0xf5, 0x6e, 0xc3, 0x53, 0xdb, 0xc1, 0x7a, 0x50, 0x28, 0xfb, 0xd8, 0xa7, - 0x46, 0xe1, 0x0f, 0xdc, 0x2a, 0x91, 0x75, 0x08, 0xeb, 0xec, 0xc2, 0x3b, 0x2a, 0xd3, 0x31, 0x6d, 0x3b, 0x9b, 0x87, - 0xcd, 0x46, 0x41, 0xba, 0x2c, 0xe1, 0x78, 0x6d, 0xa5, 0xee, 0xd4, 0xc3, 0x73, 0x37, 0x4a, 0xdf, 0x97, 0x58, 0x5e, - 0xb6, 0x51, 0xf7, 0x76, 0x12, 0x4b, 0xf8, 0xcc, 0x3a, 0x71, 0x09, 0xee, 0x80, 0xb9, 0xca, 0x4e, 0x44, 0x2d, 0x90, - 0xd4, 0x7f, 0xe1, 0xe5, 0x8f, 0x06, 0xe3, 0x92, 0x93, 0xab, 0x5e, 0x4d, 0x20, 0x31, 0x13, 0x32, 0x47, 0xab, 0x77, - 0x03, 0x9a, 0x82, 0xae, 0x6b, 0x91, 0x03, 0x02, 0x4f, 0x6c, 0x7a, 0xf9, 0xed, 0x08, 0xe2, 0xec, 0x2e, 0x27, 0x34, - 0xac, 0xe1, 0x59, 0x76, 0xb1, 0x92, 0xb1, 0x6b, 0x8f, 0xa7, 0xc7, 0x2e, 0x95, 0x96, 0x4d, 0x18, 0xf3, 0xdb, 0xba, - 0xde, 0x28, 0x9e, 0x22, 0xa6, 0x5d, 0x9c, 0xca, 0x18, 0xae, 0x56, 0x9f, 0xe3, 0x79, 0x51, 0x05, 0x49, 0x5c, 0x12, - 0xa5, 0x37, 0xd6, 0x6f, 0xb9, 0x1c, 0x55, 0x15, 0xcb, 0xd9, 0xf9, 0x6d, 0xca, 0xab, 0xdf, 0x83, 0x7f, 0x7c, 0x95, - 0xb1, 0x08, 0xaa, 0x8c, 0xc8, 0x8c, 0x7d, 0x74, 0x11, 0x2d, 0xf4, 0xb3, 0xb6, 0x74, 0x15, 0x5d, 0xaf, 0xcc, 0x6b, - 0x88, 0x20, 0x70, 0xab, 0xea, 0x14, 0x52, 0x66, 0xd1, 0x98, 0x67, 0x15, 0xb3, 0x6b, 0x3d, 0xc6, 0x31, 0x67, 0x03, - 0xe1, 0x26, 0x93, 0x13, 0x24, 0x27, 0xe1, 0x33, 0x95, 0xd9, 0x96, 0x11, 0xf5, 0xc8, 0x6b, 0xa4, 0x8b, 0x9a, 0x35, - 0xe7, 0x6d, 0xd7, 0x59, 0xbc, 0x60, 0x71, 0xde, 0xaf, 0x6e, 0x44, 0x42, 0x80, 0x70, 0x11, 0xfe, 0x1c, 0xc0, 0xff, - 0x6d, 0x33, 0xc5, 0xfd, 0xdd, 0xfc, 0x92, 0x77, 0x4d, 0x1b, 0x07, 0xe0, 0x80, 0x82, 0xc5, 0xc9, 0xe0, 0x02, 0xc9, - 0x08, 0x43, 0xbd, 0x42, 0xb4, 0xc1, 0x52, 0x31, 0xce, 0x2d, 0x3d, 0x8f, 0xec, 0x68, 0xd0, 0xa7, 0xe5, 0xc4, 0x5c, - 0x79, 0x83, 0x31, 0x5b, 0xa3, 0x12, 0x42, 0xed, 0x08, 0x31, 0x85, 0xc9, 0x74, 0x56, 0x16, 0x25, 0x7f, 0x15, 0x26, - 0xb4, 0x82, 0x49, 0x4a, 0x9b, 0x51, 0x63, 0x88, 0x8d, 0x8a, 0x50, 0xbd, 0xe7, 0x94, 0x35, 0x04, 0x73, 0x7b, 0x42, - 0xfa, 0x35, 0x44, 0xd7, 0x3f, 0xd6, 0xcf, 0x13, 0x4e, 0x6a, 0xdb, 0xf9, 0xba, 0xd0, 0x82, 0x83, 0x6b, 0x2a, 0xaa, - 0x72, 0x35, 0x0c, 0x51, 0x40, 0xa1, 0xd4, 0x91, 0x3a, 0xd4, 0x12, 0x59, 0x9b, 0x55, 0x3a, 0xd9, 0x61, 0xb4, 0x9c, - 0x4c, 0x89, 0x2b, 0x48, 0x6b, 0x5d, 0x39, 0x57, 0xbe, 0xd1, 0x97, 0x6d, 0xd0, 0x1b, 0x8d, 0x44, 0x2e, 0x3b, 0x8f, - 0x3f, 0xdf, 0xfa, 0x1c, 0xa0, 0xd6, 0xff, 0x6a, 0xed, 0x72, 0xc9, 0x02, 0x76, 0xb1, 0xab, 0x23, 0xf1, 0x7e, 0xde, - 0x0a, 0xb8, 0xbe, 0x10, 0x08, 0x75, 0xdd, 0x85, 0x72, 0xd2, 0x15, 0xab, 0xa2, 0x5f, 0xbe, 0x47, 0xd1, 0xac, 0xb7, - 0x11, 0x94, 0x4d, 0x90, 0xd6, 0xbb, 0x3a, 0x0e, 0x29, 0x21, 0x51, 0x59, 0x4c, 0x75, 0x61, 0x8d, 0x1e, 0xe8, 0x0e, - 0x5b, 0x45, 0x34, 0xa7, 0xe9, 0x26, 0xfb, 0xfe, 0x50, 0xa1, 0x04, 0x22, 0xfc, 0xbf, 0x7b, 0xd3, 0x33, 0xd0, 0x20, - 0x49, 0x5d, 0x80, 0x4a, 0x49, 0xfb, 0x85, 0xd3, 0xfe, 0x50, 0x65, 0x0b, 0x80, 0xc2, 0x1e, 0x6f, 0x14, 0x6d, 0xcb, - 0xef, 0x66, 0x3d, 0x28, 0xd1, 0xfa, 0x3f, 0x2a, 0x43, 0x16, 0x10, 0x6d, 0x47, 0xd7, 0x6a, 0xe9, 0x95, 0x4f, 0x52, - 0x0c, 0x47, 0x13, 0x62, 0xfb, 0x9d, 0xbe, 0x7c, 0x87, 0xea, 0xc2, 0x5a, 0xe2, 0xdc, 0x4b, 0x6a, 0x4b, 0x16, 0xb0, - 0x9f, 0x31, 0x62, 0xba, 0x51, 0xc1, 0x2f, 0x1f, 0x75, 0xb9, 0x9a, 0x85, 0xab, 0x21, 0x60, 0x66, 0x5f, 0x5d, 0xf1, - 0x20, 0x58, 0xc0, 0xd4, 0xb0, 0x30, 0x63, 0xc7, 0x51, 0x9f, 0x39, 0x96, 0xb2, 0xcf, 0x7d, 0x46, 0xd7, 0x37, 0xc7, - 0xfe, 0x11, 0xeb, 0xf6, 0x5b, 0xec, 0x8a, 0x71, 0x3c, 0xb0, 0xaf, 0x2e, 0xb2, 0x81, 0x69, 0x42, 0x92, 0xf5, 0xcb, - 0x29, 0x90, 0xaa, 0xd5, 0x83, 0x98, 0xab, 0x3a, 0x01, 0x8c, 0xf6, 0x5d, 0x51, 0xf0, 0x88, 0x1c, 0x7f, 0x22, 0x8d, - 0x0e, 0x98, 0xe2, 0x0e, 0x84, 0x30, 0x74, 0x47, 0xbc, 0xd9, 0x5b, 0x81, 0x60, 0x44, 0xbb, 0x20, 0xfc, 0x8d, 0xf3, - 0x12, 0x5b, 0xd0, 0x36, 0x5a, 0x2f, 0x02, 0x68, 0x88, 0x44, 0xf2, 0x63, 0xe4, 0xf9, 0x70, 0x76, 0xee, 0x41, 0x31, - 0xdc, 0xa4, 0x2e, 0x88, 0xeb, 0xe9, 0x05, 0xdb, 0x65, 0x42, 0x32, 0x51, 0xe8, 0xd0, 0x14, 0x58, 0x59, 0x3b, 0x71, - 0x3a, 0xc0, 0x87, 0xf7, 0xf7, 0xf0, 0xc0, 0x76, 0x54, 0xfc, 0x40, 0x02, 0xb7, 0x2f, 0xac, 0xe0, 0x50, 0x67, 0xc1, - 0x0c, 0x3a, 0xe0, 0x91, 0xde, 0xa7, 0x46, 0x8c, 0x66, 0xd6, 0x3b, 0x40, 0x14, 0x11, 0x65, 0xb6, 0x4d, 0x6e, 0x87, - 0xbb, 0xe3, 0x29, 0x10, 0x20, 0x63, 0x5a, 0x15, 0x96, 0x61, 0x26, 0xb0, 0xc4, 0x7c, 0x33, 0xbe, 0x68, 0xd1, 0x8f, - 0xfd, 0x3e, 0xaa, 0xe4, 0xa2, 0x52, 0x83, 0xb1, 0x8d, 0x79, 0x63, 0x8b, 0x9e, 0xe0, 0x1b, 0x8d, 0x74, 0xf4, 0x0c, - 0x63, 0xb9, 0x84, 0x39, 0x58, 0xe9, 0x1c, 0xf5, 0x23, 0x58, 0x51, 0x05, 0x88, 0xb3, 0x1f, 0xa7, 0x48, 0x0d, 0x98, - 0x25, 0x3f, 0xa4, 0x45, 0x4d, 0x4e, 0x03, 0x7e, 0xcd, 0x40, 0xcf, 0x1e, 0x55, 0xc6, 0x3d, 0x79, 0x09, 0x5c, 0x9a, - 0xde, 0x7a, 0xda, 0x77, 0x6f, 0xc0, 0x31, 0x16, 0xe4, 0x0d, 0xe6, 0xec, 0x4e, 0x30, 0xc5, 0x8a, 0x6d, 0x5d, 0x2d, - 0xf3, 0x6a, 0xfd, 0x40, 0x67, 0x25, 0x18, 0x4e, 0x93, 0x48, 0xe2, 0x04, 0x4c, 0xa3, 0x18, 0x7f, 0x60, 0xbb, 0xbc, - 0xdb, 0xea, 0x13, 0xbf, 0x0d, 0x7f, 0x1d, 0x29, 0x55, 0x9f, 0x7f, 0x12, 0x0b, 0x33, 0x99, 0xd8, 0x6f, 0xe4, 0xe8, - 0x0c, 0x32, 0x2b, 0xf0, 0x55, 0x3d, 0xe3, 0x59, 0xf2, 0x5c, 0x79, 0xca, 0xcd, 0x8a, 0x2d, 0xb3, 0xe0, 0xe7, 0x51, - 0x49, 0x8d, 0xbd, 0x19, 0xd5, 0xa9, 0x56, 0x8c, 0x51, 0x9d, 0x9e, 0x1c, 0x08, 0x97, 0x29, 0xc0, 0x2a, 0x3b, 0x80, - 0xc6, 0xf3, 0xeb, 0xd2, 0x23, 0x11, 0xd9, 0x2a, 0xa6, 0x1e, 0x83, 0x97, 0x8a, 0xa0, 0x77, 0x10, 0x85, 0x18, 0x1c, - 0x49, 0xdf, 0x68, 0xf5, 0xc5, 0x9f, 0xf8, 0x7d, 0xaf, 0x97, 0x70, 0x17, 0xec, 0x7c, 0x53, 0x63, 0xe9, 0x2c, 0x41, - 0x63, 0xf6, 0x3f, 0x87, 0xac, 0x45, 0x58, 0xe4, 0x34, 0xd3, 0x10, 0x34, 0x41, 0xf1, 0x47, 0xd0, 0xc0, 0x66, 0x4d, - 0xd7, 0x7a, 0x13, 0x94, 0x51, 0x48, 0x82, 0xff, 0x57, 0x19, 0x2f, 0x87, 0x2a, 0x27, 0x93, 0xa8, 0x05, 0xf7, 0x89, - 0x9b, 0x6a, 0x68, 0x05, 0xea, 0xec, 0xe1, 0x29, 0xf4, 0x64, 0x2c, 0xa2, 0x67, 0x58, 0xc4, 0x46, 0x9b, 0xc0, 0x78, - 0x24, 0xf3, 0xb0, 0x2e, 0xa2, 0xdd, 0x72, 0x36, 0xc5, 0x57, 0x76, 0xcc, 0xdb, 0x6e, 0x1f, 0xbb, 0x09, 0x95, 0x78, - 0xfa, 0x7d, 0x57, 0xcc, 0xbe, 0xc7, 0xbe, 0x94, 0xd2, 0x3d, 0x70, 0x58, 0x4a, 0xeb, 0x22, 0x28, 0x9c, 0x3a, 0xd8, - 0x02, 0x9a, 0xec, 0xe4, 0x6c, 0x1a, 0x25, 0x58, 0x9c, 0xb9, 0x49, 0xc0, 0xaf, 0x74, 0x12, 0x42, 0x2a, 0x1b, 0xbe, - 0x63, 0x2d, 0xf9, 0x2b, 0x90, 0x6b, 0xfe, 0xe2, 0x69, 0x20, 0x44, 0x6d, 0x23, 0x14, 0x01, 0x6b, 0xe2, 0xca, 0xbc, - 0x33, 0x08, 0xae, 0xe8, 0x2f, 0x7b, 0x0d, 0xff, 0xdc, 0x98, 0xf6, 0xad, 0x90, 0xda, 0xd0, 0xc1, 0x5a, 0x44, 0xc6, - 0xf3, 0x50, 0xf8, 0x6f, 0xf8, 0xd8, 0x73, 0x84, 0x48, 0x22, 0x17, 0xc9, 0x8f, 0x28, 0x6e, 0x31, 0xdd, 0x42, 0xb9, - 0xb5, 0x9d, 0x8f, 0x23, 0x61, 0xd0, 0x3c, 0x6a, 0xf5, 0x92, 0x94, 0xf7, 0xd4, 0x6a, 0xe6, 0x1e, 0x05, 0xb7, 0x8b, - 0xa5, 0x86, 0x17, 0x88, 0xd2, 0xd5, 0x0f, 0x0a, 0xcd, 0xe2, 0x3f, 0x66, 0xb5, 0x79, 0xea, 0xf6, 0x51, 0xc9, 0x37, - 0xc9, 0xca, 0x91, 0x05, 0x27, 0x51, 0xf8, 0x43, 0x08, 0xbc, 0xd4, 0x19, 0x4f, 0xf5, 0x36, 0x62, 0x1e, 0x0a, 0x4d, - 0x41, 0xae, 0x07, 0xed, 0x13, 0x4d, 0x8e, 0xdc, 0x90, 0x63, 0x7a, 0xd0, 0x3e, 0xac, 0x81, 0xed, 0x08, 0x71, 0x71, - 0x9f, 0x88, 0xe1, 0xb4, 0xea, 0x72, 0x02, 0xe4, 0xce, 0x79, 0xd2, 0x32, 0x04, 0x35, 0x72, 0x13, 0xd4, 0xb8, 0x73, - 0x9c, 0xda, 0x45, 0xd1, 0xed, 0x4b, 0x2e, 0x91, 0x62, 0x94, 0xe9, 0xbe, 0xf4, 0xdf, 0xab, 0xad, 0xa2, 0x01, 0x64, - 0x03, 0xbe, 0xde, 0x7b, 0xc7, 0xe8, 0x00, 0xf5, 0x72, 0xeb, 0xa6, 0x6c, 0x5e, 0x9e, 0xd3, 0x6c, 0x6b, 0xb8, 0xc7, - 0xd0, 0xfe, 0x12, 0xea, 0x9c, 0xfb, 0xac, 0xf8, 0xad, 0xbc, 0x0b, 0xc4, 0xe4, 0xe4, 0x66, 0x23, 0x4f, 0x93, 0x75, - 0x84, 0x75, 0x8f, 0xa1, 0xb9, 0x88, 0x7f, 0x69, 0xac, 0x5c, 0x10, 0x9e, 0x58, 0xc9, 0x82, 0xbf, 0x30, 0xcc, 0x60, - 0x53, 0x79, 0x4d, 0x7f, 0x87, 0x39, 0x80, 0xf7, 0xdb, 0xcd, 0x5a, 0x41, 0x3e, 0x25, 0xb5, 0xe3, 0x6b, 0xad, 0xe3, - 0x97, 0x6f, 0xd0, 0x83, 0xd4, 0xc4, 0x63, 0x51, 0x3d, 0x10, 0xb3, 0xa4, 0x37, 0x2f, 0x71, 0xf4, 0xcd, 0x4f, 0x9b, - 0x67, 0x5c, 0xe3, 0xb9, 0x08, 0xc9, 0x80, 0xb5, 0xc1, 0xa5, 0xbd, 0x37, 0x12, 0x77, 0x9f, 0x95, 0xa9, 0x45, 0x6b, - 0x63, 0x26, 0x0a, 0xb4, 0xb0, 0xee, 0x12, 0xf1, 0x7c, 0xf9, 0xa6, 0xbf, 0x76, 0xa4, 0x58, 0x9a, 0x8f, 0x64, 0x1e, - 0x55, 0x29, 0xe1, 0x8f, 0x01, 0x8d, 0x7f, 0x43, 0x5e, 0x24, 0x31, 0xd0, 0x60, 0x91, 0x1a, 0x2b, 0xef, 0x13, 0x70, - 0x88, 0xa1, 0x89, 0xa8, 0x4d, 0xb4, 0x13, 0xb8, 0xa3, 0xf1, 0x89, 0xa4, 0x3e, 0x26, 0x95, 0x34, 0x01, 0x1e, 0xdd, - 0xc5, 0xe4, 0x64, 0xec, 0x02, 0x7c, 0x81, 0xc7, 0xc7, 0xd3, 0x6f, 0xda, 0xd5, 0xd1, 0x0d, 0x52, 0x6e, 0x2a, 0xc8, - 0x26, 0x60, 0xad, 0x05, 0xe0, 0x29, 0xd7, 0x44, 0xf3, 0x8e, 0x54, 0xbf, 0x0c, 0x02, 0xf6, 0xbb, 0x8b, 0x7a, 0xee, - 0x4d, 0x63, 0x65, 0xf9, 0x38, 0xf1, 0x52, 0xd3, 0x08, 0xb1, 0x62, 0x9f, 0x71, 0xca, 0x11, 0x11, 0xef, 0xf0, 0x6b, - 0xeb, 0xcd, 0x22, 0xbd, 0x4d, 0x8a, 0x73, 0x93, 0x01, 0x86, 0x91, 0x6b, 0x84, 0x5f, 0xcc, 0xb4, 0xb3, 0x75, 0xe5, - 0xc3, 0x02, 0xc9, 0x68, 0x29, 0xfc, 0xad, 0xc8, 0xac, 0xb6, 0x59, 0x8b, 0x10, 0xff, 0x50, 0xf4, 0xb3, 0x43, 0x69, - 0x14, 0x90, 0x57, 0x5f, 0x2e, 0x2b, 0x36, 0x39, 0x05, 0x9d, 0xf6, 0xb9, 0x79, 0x67, 0x59, 0x7e, 0xfc, 0xf9, 0x8f, - 0x73, 0x3b, 0x61, 0x8b, 0x99, 0x27, 0x6e, 0xb1, 0x8c, 0xb2, 0xf2, 0xa2, 0xd5, 0x79, 0x4b, 0xd6, 0xcd, 0xec, 0xba, - 0x40, 0x09, 0xff, 0xd4, 0x8f, 0x0e, 0x67, 0xe5, 0x0c, 0x7a, 0x85, 0x56, 0x16, 0xf6, 0x28, 0x6d, 0xdf, 0xda, 0x97, - 0x03, 0x9d, 0xc6, 0x5d, 0xd8, 0x1c, 0x27, 0x48, 0x52, 0x79, 0x28, 0x3f, 0xf3, 0x14, 0x67, 0xdf, 0x59, 0x4d, 0x47, - 0x3b, 0x7a, 0xc7, 0xd1, 0xe5, 0x60, 0xb1, 0x43, 0x94, 0xac, 0x0f, 0xce, 0xb6, 0x59, 0x7c, 0x70, 0x94, 0x69, 0x3e, - 0xe3, 0x15, 0x0b, 0xa4, 0x34, 0x4f, 0x9f, 0x22, 0xe8, 0x09, 0x64, 0x62, 0x0c, 0xbd, 0x0b, 0x36, 0x4d, 0x81, 0x63, - 0xce, 0xb7, 0x89, 0xa0, 0xcd, 0x32, 0x9a, 0x45, 0xf4, 0x62, 0x64, 0x29, 0xbc, 0xf6, 0x8e, 0x7a, 0xae, 0x64, 0x5d, - 0x42, 0xab, 0x23, 0xab, 0x1f, 0x6c, 0xf7, 0x69, 0xe1, 0x07, 0xf3, 0xbb, 0xd5, 0x42, 0x7d, 0x65, 0xac, 0x7e, 0x8c, - 0xcc, 0x52, 0xe7, 0x2c, 0x67, 0xb7, 0xd3, 0xd8, 0xc0, 0xeb, 0x64, 0xb3, 0xf5, 0xeb, 0x76, 0x7f, 0xb9, 0xe4, 0xdf, - 0x66, 0xca, 0xdb, 0x24, 0x47, 0xd8, 0xef, 0x13, 0x59, 0x03, 0xb2, 0x3e, 0x6d, 0x71, 0x96, 0x92, 0x3a, 0x56, 0x49, - 0x94, 0x18, 0xdb, 0x09, 0x5c, 0x61, 0x10, 0x12, 0xcf, 0x66, 0x75, 0x25, 0x4c, 0xce, 0xab, 0x78, 0xa7, 0x30, 0x57, - 0x22, 0x59, 0x2c, 0xf2, 0x04, 0x45, 0xda, 0x37, 0xcb, 0xe5, 0xa5, 0x3c, 0x35, 0xa5, 0x1d, 0x09, 0x8d, 0xbc, 0xa4, - 0xff, 0x0c, 0xb8, 0x24, 0x44, 0x2a, 0x50, 0x89, 0xcf, 0x7d, 0x47, 0x2a, 0xd1, 0xa4, 0x8a, 0x52, 0x14, 0xd4, 0xca, - 0xf4, 0x8f, 0x98, 0x97, 0xa6, 0xb4, 0xee, 0x81, 0xc0, 0x75, 0x9b, 0x2b, 0x89, 0xa7, 0x7f, 0x99, 0xcc, 0x2e, 0x00, - 0xe7, 0x65, 0xb9, 0xc1, 0x2f, 0x63, 0xc2, 0xe5, 0xd1, 0x65, 0x4d, 0x20, 0xd8, 0xf1, 0x06, 0x7e, 0x98, 0x48, 0x10, - 0x1c, 0x57, 0x24, 0x22, 0x16, 0x9c, 0xa1, 0x88, 0xa7, 0x60, 0x00, 0x48, 0xce, 0xbf, 0x4f, 0x9f, 0x17, 0x34, 0x7f, - 0x40, 0x54, 0xe1, 0xa8, 0x02, 0xc4, 0x01, 0x09, 0x06, 0x5d, 0x78, 0x27, 0x8b, 0x6c, 0x35, 0x3b, 0x5e, 0x9e, 0x93, - 0xce, 0x9d, 0x45, 0x44, 0x7a, 0x51, 0x12, 0x41, 0x9c, 0x61, 0xf1, 0x83, 0xa0, 0xc4, 0xe8, 0xf5, 0xba, 0x20, 0x8c, - 0x2e, 0x96, 0x64, 0xa3, 0xd1, 0x20, 0x20, 0xfd, 0x23, 0xc4, 0x4c, 0xb6, 0x4b, 0x39, 0x66, 0x5f, 0x7b, 0xc5, 0x39, - 0x6b, 0xcd, 0x10, 0x4a, 0x06, 0x76, 0x6f, 0x09, 0xa4, 0x3a, 0x87, 0x32, 0x9a, 0x4a, 0x53, 0x7e, 0x21, 0x47, 0x50, - 0xeb, 0xd0, 0x6b, 0x93, 0xa1, 0xdf, 0x06, 0x4f, 0x22, 0x20, 0x45, 0x0a, 0xcf, 0x4b, 0x60, 0xc1, 0x64, 0xe7, 0xb6, - 0x64, 0x16, 0x1f, 0x3f, 0xa4, 0x38, 0xc9, 0x9c, 0xcd, 0x40, 0xff, 0x42, 0x13, 0x5c, 0x2c, 0xd2, 0x11, 0x23, 0xab, - 0xe0, 0x72, 0x58, 0xf7, 0xbf, 0xed, 0x72, 0xe8, 0xa6, 0x20, 0xb7, 0x39, 0x1b, 0x33, 0xe5, 0x78, 0xdc, 0xcd, 0x59, - 0x5f, 0xfa, 0xcb, 0x24, 0x8d, 0x34, 0x15, 0x4a, 0x67, 0xd6, 0x77, 0xf7, 0xbb, 0x7a, 0xec, 0x96, 0x47, 0xf7, 0x16, - 0x10, 0xd0, 0xc6, 0x1d, 0x39, 0x65, 0x05, 0x96, 0x84, 0x63, 0x12, 0x0e, 0x1f, 0x00, 0x73, 0xad, 0x1f, 0x44, 0x25, - 0xfd, 0x5d, 0xb2, 0x4f, 0x07, 0x22, 0x3f, 0xd7, 0x65, 0x7d, 0x96, 0xfa, 0x93, 0x69, 0xf7, 0x71, 0xec, 0xe3, 0x19, - 0xa7, 0x39, 0x42, 0x52, 0x96, 0xe4, 0xd7, 0xcb, 0xcd, 0x71, 0xb6, 0x95, 0xfc, 0x4f, 0x28, 0xce, 0x1f, 0x94, 0xd1, - 0x3a, 0x5b, 0x36, 0x7d, 0xb6, 0x60, 0x38, 0x67, 0x92, 0x96, 0xe0, 0x94, 0x4f, 0xfc, 0x4b, 0xd5, 0xe1, 0xf1, 0x69, - 0x8f, 0x58, 0x0f, 0x22, 0x49, 0xf0, 0x5f, 0x73, 0xc2, 0xe3, 0x53, 0x33, 0xe1, 0x87, 0x67, 0x88, 0x4f, 0x6f, 0x8c, - 0x8e, 0xa9, 0xd4, 0x1c, 0xcb, 0x8a, 0x4b, 0x2f, 0x2a, 0x82, 0x53, 0x5d, 0xd8, 0xe0, 0xd9, 0x9d, 0x3e, 0xa5, 0x39, - 0xcd, 0x41, 0x78, 0x92, 0x66, 0x3b, 0xb7, 0x68, 0xb1, 0xa4, 0x05, 0x94, 0x92, 0xca, 0x49, 0xb4, 0x9a, 0xc6, 0x91, - 0xad, 0x23, 0xcc, 0x0b, 0x9c, 0xdd, 0x46, 0x62, 0x84, 0xb5, 0x33, 0x9e, 0xa8, 0x91, 0x9a, 0x92, 0x9b, 0x3a, 0x22, - 0x59, 0x8f, 0xc1, 0xfc, 0x9f, 0x1f, 0x7b, 0x5c, 0x63, 0x66, 0x67, 0xe1, 0x8a, 0x72, 0xfb, 0x6a, 0xaa, 0x76, 0xb2, - 0xa5, 0x2b, 0xaf, 0x5b, 0x3b, 0xa7, 0xd2, 0xe6, 0xc2, 0x15, 0x87, 0x6e, 0xb8, 0x7a, 0x6d, 0x17, 0x24, 0xd7, 0xcf, - 0x91, 0xdf, 0x0c, 0x83, 0x25, 0x89, 0xd4, 0xcd, 0x9d, 0x27, 0x65, 0x4b, 0xa9, 0xba, 0xaf, 0xc0, 0xe2, 0xb0, 0x34, - 0x54, 0xbb, 0x0a, 0xca, 0xf2, 0x46, 0x0d, 0x61, 0x11, 0xd6, 0xd4, 0x0b, 0x0e, 0xa7, 0x74, 0x9e, 0x05, 0x35, 0xb5, - 0x38, 0x3f, 0x69, 0xd4, 0x5e, 0x52, 0xe4, 0x54, 0x40, 0xbc, 0x89, 0x22, 0x17, 0x2f, 0x51, 0xaf, 0xf2, 0xb8, 0x82, - 0xfd, 0x91, 0x92, 0xaa, 0x9d, 0x5e, 0xa8, 0xc2, 0xe9, 0x99, 0x2a, 0x9f, 0x5e, 0x9e, 0xae, 0x70, 0x98, 0x4b, 0xb5, - 0x2b, 0x91, 0x45, 0x59, 0x52, 0x96, 0xe3, 0xca, 0x95, 0xf1, 0xdc, 0x9e, 0xbb, 0x8c, 0x4c, 0xd5, 0x29, 0x06, 0x93, - 0x32, 0xa5, 0xd5, 0x63, 0xdb, 0x11, 0x43, 0xc3, 0x04, 0x82, 0x5d, 0xd6, 0xca, 0x68, 0x7d, 0xbf, 0x78, 0x62, 0x51, - 0xa8, 0x2d, 0xad, 0x4f, 0x4f, 0x92, 0x90, 0xb5, 0xbe, 0xb4, 0x09, 0x94, 0xd8, 0x79, 0x3f, 0x56, 0xd1, 0x5e, 0x3c, - 0x77, 0xcf, 0xda, 0x83, 0x08, 0xb8, 0x5e, 0xeb, 0xcb, 0x0f, 0xc7, 0xf4, 0x90, 0xbd, 0x6c, 0x91, 0xa2, 0xfc, 0x81, - 0x04, 0xce, 0x07, 0x84, 0x30, 0x13, 0x58, 0x05, 0x0b, 0xe5, 0x95, 0x04, 0x56, 0x81, 0x8f, 0x18, 0xb5, 0x98, 0x9d, - 0x96, 0xde, 0xfb, 0xa4, 0x58, 0xe3, 0x26, 0xc4, 0x0b, 0x40, 0x5e, 0x4f, 0x21, 0xb2, 0x85, 0x28, 0xd0, 0x4c, 0x11, - 0x24, 0xfc, 0x80, 0x7d, 0x78, 0x81, 0xd6, 0x8f, 0xe9, 0xc8, 0x57, 0xb3, 0x72, 0x07, 0x6d, 0x3d, 0xb6, 0xa7, 0x2a, - 0x5d, 0x35, 0x29, 0x3e, 0x4a, 0xbc, 0x93, 0x58, 0x34, 0xf0, 0xca, 0x15, 0x3b, 0xbd, 0xf3, 0x81, 0xdf, 0xb0, 0x2d, - 0x73, 0xfc, 0xf2, 0x34, 0xc7, 0x15, 0xa8, 0x1a, 0x55, 0x68, 0xbb, 0x3d, 0x40, 0xa6, 0xa6, 0x57, 0x09, 0xe2, 0xb0, - 0x69, 0x1a, 0x2e, 0x40, 0x07, 0x0e, 0x51, 0x09, 0xa4, 0x4c, 0x35, 0x0b, 0x34, 0x72, 0x8d, 0x14, 0x36, 0x5b, 0xb3, - 0xa8, 0x4d, 0xd8, 0xe7, 0xdf, 0xd0, 0xbc, 0xb6, 0x2d, 0x9f, 0x88, 0x3b, 0x54, 0xf2, 0x19, 0xbc, 0xf4, 0xe1, 0x1e, - 0xdf, 0x03, 0x76, 0xe4, 0x4a, 0xc5, 0xc8, 0x94, 0xc4, 0xf6, 0x78, 0x41, 0xb5, 0xc9, 0x3c, 0x79, 0x54, 0xa7, 0x26, - 0x6c, 0x28, 0x57, 0x38, 0x61, 0xfb, 0x11, 0xbb, 0x80, 0x77, 0x28, 0x31, 0x37, 0xd5, 0x6f, 0x0e, 0xa1, 0xab, 0x3d, - 0xf0, 0xae, 0x8c, 0x7e, 0x79, 0xf9, 0x62, 0x8b, 0xb7, 0xb9, 0x83, 0xbf, 0xa6, 0xc1, 0xb6, 0x50, 0x1c, 0xea, 0xae, - 0x80, 0xf4, 0xb2, 0x97, 0x2b, 0x45, 0x49, 0x6f, 0xcd, 0xe0, 0xa9, 0xde, 0x20, 0x5d, 0x34, 0x05, 0xea, 0x60, 0xd2, - 0x83, 0x30, 0x21, 0xc8, 0x01, 0x95, 0xd1, 0xbb, 0x2b, 0xd9, 0xe2, 0x5e, 0xf0, 0x6c, 0x08, 0xc8, 0xd0, 0x8a, 0xe4, - 0xd3, 0x28, 0x8d, 0xba, 0x64, 0x68, 0x8f, 0x4d, 0x2c, 0x13, 0x80, 0x64, 0x57, 0xaf, 0x2c, 0x91, 0x09, 0x60, 0x0b, - 0xec, 0xd9, 0x3c, 0x86, 0xe1, 0xdb, 0xed, 0xc9, 0x80, 0xb1, 0x65, 0xf6, 0xbe, 0xa7, 0x9b, 0x8f, 0x26, 0xe4, 0x1a, - 0x6a, 0x0d, 0xc7, 0x39, 0x30, 0x64, 0xaa, 0x68, 0xf0, 0xc9, 0x86, 0x68, 0xc2, 0xda, 0x5c, 0x76, 0x5d, 0x08, 0x61, - 0xd0, 0x63, 0x53, 0x58, 0x41, 0x5c, 0x3b, 0xd6, 0xb0, 0xbe, 0x58, 0x46, 0xa0, 0x69, 0x4d, 0x1f, 0xc8, 0x98, 0xb6, - 0x97, 0x08, 0x75, 0x27, 0xca, 0x37, 0xcc, 0x69, 0x16, 0xc4, 0x7d, 0xaf, 0xcb, 0xe7, 0x1a, 0x36, 0x7e, 0xa2, 0x62, - 0xae, 0xa7, 0xba, 0x85, 0x01, 0xea, 0x40, 0x5c, 0x0c, 0xf8, 0x78, 0x1b, 0x42, 0x5f, 0xf9, 0x77, 0xd8, 0xf7, 0x4a, - 0x29, 0x8f, 0x3a, 0x3e, 0x2d, 0x35, 0x72, 0xd4, 0x5e, 0xf6, 0x7f, 0xb2, 0xfa, 0x90, 0x3f, 0x56, 0xa8, 0xd0, 0x84, - 0x34, 0x34, 0x89, 0xba, 0x79, 0x02, 0xb1, 0xed, 0x7b, 0xae, 0xd0, 0x8b, 0x45, 0xa4, 0x3c, 0x02, 0xba, 0x29, 0x8f, - 0x77, 0xab, 0x19, 0x46, 0x7c, 0xab, 0xd7, 0xda, 0x68, 0x4b, 0x34, 0x8b, 0x23, 0xde, 0x45, 0x3b, 0x3b, 0x9c, 0xca, - 0x48, 0xcf, 0x4e, 0xe1, 0x38, 0x27, 0xd1, 0xbb, 0x74, 0xd8, 0x69, 0xae, 0xbe, 0x7e, 0x67, 0x43, 0x1f, 0xe2, 0x6a, - 0x21, 0x6a, 0x7b, 0xce, 0x68, 0x6e, 0x26, 0x2e, 0x10, 0x0b, 0xa0, 0xd9, 0xbb, 0x57, 0xa9, 0xa6, 0xc9, 0x98, 0x71, - 0x59, 0xcc, 0x12, 0x29, 0xc2, 0x0e, 0xe8, 0x25, 0x9a, 0x30, 0x51, 0x75, 0x9c, 0x1b, 0xb1, 0xe7, 0xa3, 0xba, 0x29, - 0x77, 0x25, 0x19, 0x94, 0x45, 0xeb, 0xb6, 0xeb, 0xe5, 0x25, 0xf4, 0x7e, 0x1e, 0x70, 0x5d, 0x1b, 0x2b, 0x38, 0x61, - 0x0b, 0x13, 0x9f, 0x25, 0x41, 0x6e, 0x8d, 0x24, 0x5b, 0x84, 0xa5, 0x7a, 0x67, 0xfe, 0x69, 0xe9, 0xd5, 0x76, 0xa4, - 0x5e, 0x38, 0xcc, 0xdc, 0x9e, 0x85, 0xe5, 0x57, 0xc0, 0xe3, 0xbc, 0xf7, 0xbc, 0x11, 0x9a, 0xf2, 0xc7, 0xab, 0x3d, - 0xa8, 0x88, 0x66, 0x63, 0x47, 0x3d, 0x91, 0x6b, 0xba, 0xa9, 0x82, 0x6b, 0x32, 0xd1, 0xea, 0x41, 0x9c, 0x59, 0xd1, - 0x76, 0x62, 0x19, 0xfc, 0x33, 0xd8, 0xe0, 0x1b, 0xd8, 0x17, 0x4b, 0x00, 0xeb, 0x37, 0xc6, 0x57, 0x21, 0x0f, 0xcb, - 0xf7, 0x74, 0x7e, 0x86, 0xb0, 0xaf, 0x30, 0x57, 0x24, 0x2c, 0x4f, 0x95, 0x5a, 0xc9, 0x41, 0xc5, 0xb4, 0x7c, 0x6e, - 0xc1, 0x27, 0xd5, 0x56, 0x29, 0x5e, 0xff, 0x55, 0x5c, 0xab, 0xd0, 0xf9, 0x79, 0xa2, 0x10, 0xe2, 0xfe, 0x23, 0x12, - 0x55, 0x94, 0x9f, 0x86, 0xdb, 0x66, 0xdf, 0xc3, 0x8f, 0x1b, 0x7e, 0xd0, 0x65, 0x81, 0xca, 0xaa, 0x71, 0x83, 0x71, - 0xb8, 0x3c, 0xcd, 0xaa, 0x11, 0x0b, 0x45, 0xf8, 0xc6, 0xa5, 0x03, 0x47, 0x6f, 0x63, 0xab, 0xe6, 0x52, 0x85, 0x2a, - 0x20, 0xf6, 0x14, 0x7a, 0xde, 0x44, 0x35, 0x52, 0x2a, 0x12, 0x08, 0x93, 0x06, 0xed, 0x12, 0x17, 0xec, 0x16, 0xab, - 0x76, 0xb5, 0xbb, 0x15, 0xf3, 0x9a, 0x4c, 0x04, 0x8c, 0xf1, 0x0e, 0xb4, 0x6e, 0x66, 0x4b, 0x06, 0x74, 0x4e, 0xec, - 0xa8, 0xc0, 0x79, 0x8c, 0x71, 0x70, 0xb8, 0xc7, 0xcd, 0xf4, 0xa4, 0x92, 0x1d, 0x66, 0xe4, 0xa1, 0x39, 0x74, 0x86, - 0x2b, 0x0f, 0xe5, 0x21, 0x2b, 0x71, 0xb6, 0xc0, 0xcb, 0x35, 0x72, 0x95, 0xe8, 0xaa, 0x25, 0x68, 0x78, 0x20, 0xb9, - 0xdb, 0x37, 0xdf, 0xbd, 0xd3, 0xbb, 0x01, 0xa7, 0xd2, 0xdf, 0x0c, 0xd8, 0x1d, 0x2c, 0x78, 0xb7, 0x3a, 0x1d, 0x4b, - 0x0c, 0x00, 0x64, 0xd7, 0xf4, 0x83, 0xb0, 0x85, 0xee, 0x74, 0x87, 0x6b, 0xc7, 0x55, 0x04, 0x6d, 0x88, 0xaa, 0x8c, - 0xa1, 0x23, 0xbb, 0x88, 0x04, 0xb2, 0xeb, 0x88, 0x15, 0xdd, 0x32, 0x16, 0xc2, 0x09, 0x3c, 0xee, 0x01, 0xf5, 0x83, - 0x23, 0xa4, 0x54, 0x44, 0x42, 0xc9, 0x85, 0xf8, 0xdb, 0x34, 0xd4, 0xac, 0xe0, 0x6e, 0xb3, 0x21, 0x76, 0x93, 0x88, - 0xfe, 0xa0, 0x2a, 0xbc, 0x39, 0x8f, 0xf2, 0xad, 0x03, 0x0a, 0x1f, 0xcd, 0xc8, 0xc0, 0x59, 0xda, 0xb7, 0xa7, 0x5d, - 0x7b, 0x37, 0xe6, 0xa5, 0xb4, 0x94, 0x0a, 0xc1, 0xcd, 0x1d, 0x3c, 0xeb, 0x1f, 0x5c, 0x49, 0x13, 0x9b, 0x9a, 0x7d, - 0x99, 0x73, 0xb4, 0x33, 0xe5, 0x79, 0x14, 0x5f, 0x6b, 0xd9, 0xf3, 0xb6, 0x79, 0x36, 0x76, 0x67, 0xb7, 0x8b, 0xfd, - 0x0c, 0x49, 0x61, 0x8b, 0x19, 0xcc, 0x35, 0x89, 0x62, 0x12, 0x18, 0x6d, 0x80, 0xbd, 0x89, 0x66, 0xd8, 0x45, 0x0b, - 0x94, 0xbd, 0x5b, 0x77, 0x6b, 0xc3, 0xf1, 0xdb, 0xcc, 0xd7, 0xaa, 0xf6, 0xc2, 0x9d, 0x12, 0x05, 0xe7, 0xc3, 0xde, - 0x39, 0xaf, 0xff, 0xa3, 0xc4, 0x9b, 0x19, 0xc6, 0x92, 0x48, 0xb4, 0x36, 0x10, 0x3c, 0x4a, 0xeb, 0xb5, 0x59, 0x96, - 0x20, 0x3b, 0xb5, 0xbc, 0xfd, 0x07, 0x1d, 0x20, 0x15, 0xe3, 0xdd, 0xe2, 0xe6, 0x0c, 0x0b, 0x8e, 0x49, 0xa9, 0x2d, - 0x37, 0xbf, 0xfe, 0x49, 0x32, 0xa5, 0xa2, 0x4d, 0xae, 0x27, 0x9a, 0xe7, 0xe2, 0xca, 0x01, 0x80, 0x40, 0x69, 0x36, - 0xac, 0x8b, 0xeb, 0xcd, 0x64, 0x73, 0xab, 0xd0, 0x11, 0x66, 0xaa, 0xc0, 0xf8, 0x9b, 0x55, 0x4a, 0x4f, 0xa9, 0x56, - 0x49, 0xc2, 0xdc, 0x4e, 0x5f, 0xab, 0x44, 0x68, 0x3f, 0x06, 0xe2, 0xdb, 0xc9, 0x77, 0xf5, 0xa7, 0x6c, 0x8b, 0x3c, - 0x8e, 0x03, 0x93, 0xb3, 0xb7, 0x76, 0x50, 0xd0, 0xa8, 0xed, 0x5c, 0x8e, 0xd7, 0x3c, 0x2b, 0xa8, 0x7d, 0xe5, 0x57, - 0xb3, 0xb5, 0xc7, 0x17, 0xee, 0x08, 0xb2, 0x02, 0xa9, 0xc7, 0xe4, 0xc1, 0x34, 0x46, 0xa5, 0xd9, 0x39, 0x2f, 0x76, - 0x58, 0x1e, 0x93, 0x64, 0xd7, 0xf8, 0xcf, 0xc8, 0xa5, 0x14, 0x48, 0xfe, 0xc4, 0xb9, 0x13, 0x2a, 0x16, 0xb3, 0x64, - 0x61, 0x6a, 0xd7, 0x24, 0x2f, 0xdf, 0xc5, 0x75, 0x3c, 0x2d, 0xc7, 0x7f, 0x56, 0x4c, 0xf4, 0x24, 0x10, 0x52, 0xeb, - 0x1d, 0x0d, 0x1e, 0x40, 0xdd, 0x3a, 0x83, 0x6f, 0x64, 0xf3, 0x50, 0x24, 0x83, 0x8c, 0xd9, 0x56, 0xdd, 0xa5, 0x1a, - 0x89, 0x7a, 0xb0, 0x0c, 0xb4, 0xdb, 0x49, 0xe0, 0x12, 0xb5, 0xf6, 0x10, 0x1c, 0x54, 0xf4, 0x3e, 0x54, 0xc1, 0x52, - 0x33, 0x58, 0xaa, 0xac, 0xd4, 0x06, 0x6b, 0x2f, 0xd5, 0xda, 0x32, 0xa3, 0x2b, 0x2f, 0x0f, 0x8e, 0x39, 0x0e, 0x00, - 0x5b, 0xcf, 0xa5, 0x0e, 0x03, 0xe8, 0x44, 0x36, 0x70, 0x03, 0x32, 0x00, 0x65, 0x2d, 0xa1, 0x72, 0xd3, 0x82, 0x73, - 0xad, 0x4d, 0x29, 0x96, 0x80, 0x44, 0x70, 0xc6, 0xfe, 0xe8, 0x51, 0xe9, 0xed, 0xc8, 0x11, 0xae, 0x5a, 0x37, 0x6d, - 0x05, 0x6b, 0xeb, 0x0c, 0x69, 0xe3, 0x31, 0xde, 0x65, 0x3f, 0x01, 0xdf, 0xc5, 0x8b, 0xd6, 0x91, 0x19, 0x6f, 0x71, - 0xa4, 0x20, 0x14, 0xba, 0xde, 0x31, 0x16, 0xa6, 0x04, 0x86, 0xd9, 0xdd, 0x15, 0x61, 0x7a, 0x7b, 0x29, 0x20, 0x58, - 0xb8, 0xb1, 0x16, 0x37, 0x0e, 0xcf, 0x6f, 0x1c, 0x26, 0x8a, 0x70, 0x68, 0xa6, 0x4a, 0xf8, 0x5c, 0xaa, 0x0c, 0x05, - 0x39, 0x35, 0x38, 0x0a, 0xdc, 0xdf, 0xbe, 0x77, 0xb4, 0x28, 0x12, 0x82, 0x2c, 0x2e, 0x43, 0x13, 0xe5, 0x75, 0xc6, - 0x05, 0xe9, 0xcb, 0xe1, 0xfe, 0x62, 0x6e, 0x87, 0xa9, 0x59, 0x99, 0xb7, 0x48, 0x7c, 0x6f, 0x5a, 0x8c, 0x11, 0xe1, - 0x7c, 0xaf, 0x5d, 0x60, 0x8b, 0xb5, 0xec, 0x6f, 0x3f, 0xee, 0x09, 0x57, 0x16, 0x0e, 0x0c, 0x5d, 0x64, 0xda, 0xab, - 0x75, 0xb7, 0x52, 0xc4, 0xf9, 0x47, 0xf4, 0xc8, 0xfc, 0xc1, 0x38, 0x8e, 0x1d, 0xdc, 0xee, 0x84, 0xda, 0xe7, 0xfc, - 0x86, 0x85, 0x3a, 0xa2, 0xd5, 0x0d, 0xd4, 0xb0, 0x06, 0x97, 0xca, 0x2c, 0x2d, 0xe6, 0x9f, 0xdd, 0xdc, 0x3c, 0x25, - 0xe0, 0x24, 0xf1, 0x05, 0x24, 0xd9, 0xe1, 0x7a, 0xf7, 0xe9, 0x2d, 0x93, 0xbe, 0x0d, 0x92, 0x12, 0xbb, 0x95, 0xca, - 0x76, 0x49, 0xd3, 0x94, 0x1d, 0xee, 0x8a, 0xaa, 0x35, 0xd8, 0x13, 0x13, 0xa5, 0xa3, 0xbe, 0x10, 0x26, 0x4d, 0xec, - 0x4b, 0x18, 0xef, 0x8b, 0x09, 0x9c, 0x37, 0x0c, 0xf1, 0xaa, 0x03, 0xa5, 0x50, 0x22, 0x65, 0x2f, 0xbb, 0xe3, 0x4d, - 0x69, 0x26, 0x1f, 0x51, 0xc5, 0x81, 0x96, 0xde, 0x5a, 0xee, 0x4a, 0x00, 0xd0, 0xbd, 0xba, 0xbc, 0xfc, 0xfd, 0xc1, - 0x7d, 0x8c, 0x95, 0xc8, 0x37, 0xef, 0xf7, 0xc3, 0xd3, 0xfd, 0x17, 0x12, 0xc1, 0x81, 0xe6, 0x71, 0x7a, 0xf9, 0x5d, - 0xa5, 0x8b, 0x5b, 0xd5, 0xf7, 0xab, 0xa0, 0x8c, 0xd4, 0xe3, 0xee, 0x2c, 0x6c, 0x09, 0x26, 0xac, 0x0d, 0x38, 0x67, - 0x3e, 0x08, 0x65, 0x2e, 0xff, 0xfa, 0x2c, 0xce, 0xdd, 0x78, 0x58, 0x78, 0x26, 0xb0, 0xb1, 0x31, 0xd4, 0x61, 0xae, - 0x3b, 0xf3, 0xe9, 0xe0, 0x19, 0xb9, 0xee, 0x1a, 0x32, 0x2c, 0x8d, 0x03, 0xbe, 0xde, 0xfa, 0xf1, 0xfe, 0x3f, 0x8f, - 0x5f, 0x06, 0xe6, 0x81, 0x99, 0xf1, 0x1c, 0x95, 0xf6, 0xb0, 0xa4, 0xc1, 0x61, 0x64, 0x3b, 0xea, 0xda, 0xbf, 0x47, - 0x23, 0x82, 0x8c, 0x10, 0x21, 0xc7, 0xa1, 0x1d, 0x43, 0x39, 0x3d, 0x8e, 0x55, 0x95, 0xf6, 0xa2, 0x37, 0x18, 0x37, - 0xb2, 0x85, 0x22, 0x60, 0x4a, 0xf4, 0xfd, 0xea, 0xac, 0x2a, 0xee, 0x4d, 0xff, 0xf2, 0xe8, 0x8b, 0xec, 0xaa, 0x51, - 0x03, 0xe1, 0x77, 0x24, 0xaa, 0xa2, 0x37, 0x96, 0xef, 0xb4, 0x05, 0x5b, 0x43, 0x0e, 0x8c, 0x1a, 0x49, 0x9b, 0x11, - 0x3b, 0x6f, 0x32, 0xe7, 0x92, 0x2f, 0xd4, 0x58, 0x7a, 0x94, 0x93, 0x65, 0x0a, 0x00, 0xd3, 0x95, 0x16, 0x11, 0x17, - 0x18, 0x82, 0x2b, 0x0e, 0xab, 0x5b, 0xc8, 0x8c, 0xf5, 0x6c, 0x77, 0x16, 0x8d, 0x26, 0x08, 0xd3, 0xfa, 0x90, 0xa8, - 0x30, 0x73, 0xca, 0xa4, 0x0c, 0x97, 0xda, 0x09, 0xc8, 0x93, 0xdf, 0xd2, 0x8a, 0x01, 0x98, 0x31, 0x91, 0x5c, 0x6e, - 0x6c, 0x22, 0xeb, 0x90, 0xcf, 0x49, 0xbf, 0x99, 0xf3, 0xe1, 0x9b, 0x18, 0x1f, 0x5c, 0x9c, 0x06, 0xeb, 0x0f, 0x50, - 0xf2, 0xdc, 0x0d, 0x97, 0xab, 0x4d, 0xda, 0x72, 0x5b, 0xd1, 0x16, 0x8c, 0x89, 0x76, 0x79, 0x61, 0x9b, 0xa8, 0x40, - 0x9f, 0x49, 0x6f, 0xb8, 0x06, 0xa2, 0x1c, 0x06, 0xf1, 0x52, 0x0e, 0xc5, 0xcd, 0xda, 0x23, 0x54, 0x69, 0x2c, 0x50, - 0x03, 0x2b, 0x7c, 0xc2, 0x30, 0xaa, 0x26, 0xd8, 0x7d, 0xff, 0xd8, 0xe0, 0xcb, 0xd5, 0xb7, 0x83, 0x35, 0x6f, 0x5a, - 0x26, 0xda, 0x21, 0x3a, 0x9c, 0x83, 0x8a, 0x87, 0xd8, 0x69, 0x92, 0xd3, 0x60, 0xea, 0x7a, 0x72, 0xb9, 0x21, 0x63, - 0x33, 0x19, 0x69, 0x7a, 0xc0, 0x1d, 0xe6, 0xb6, 0x1f, 0x1a, 0xcc, 0x21, 0x8e, 0x8d, 0xa3, 0xba, 0x71, 0x9d, 0x31, - 0x84, 0x40, 0x27, 0x48, 0xa7, 0x3b, 0xa3, 0xcb, 0x8b, 0xf2, 0xd6, 0xda, 0x34, 0x74, 0x64, 0xdf, 0x9a, 0xee, 0x38, - 0xc2, 0x88, 0x88, 0xc7, 0x4c, 0x17, 0x2c, 0x2c, 0xb5, 0xb3, 0xb8, 0x29, 0x62, 0x39, 0xb6, 0x23, 0xac, 0x06, 0x60, - 0x16, 0xd8, 0xef, 0xcc, 0x4b, 0xef, 0x35, 0x7a, 0x21, 0x7c, 0xb0, 0x91, 0xf3, 0xb2, 0x98, 0x91, 0xb9, 0xef, 0xd0, - 0x14, 0x1e, 0xb8, 0x3f, 0x55, 0xa7, 0x15, 0x1c, 0xc4, 0xda, 0x71, 0xf4, 0xf7, 0x03, 0x6a, 0x89, 0x17, 0x04, 0x21, - 0x9c, 0x8a, 0xcd, 0x96, 0x0e, 0x88, 0x7d, 0x88, 0x65, 0x6a, 0x00, 0x42, 0x50, 0x0e, 0x56, 0xbb, 0x4f, 0x3b, 0x7d, - 0x8f, 0xd0, 0xf7, 0x11, 0xf3, 0x4d, 0x80, 0xcc, 0x14, 0x94, 0x27, 0x6a, 0x9f, 0x92, 0x88, 0x9e, 0xfc, 0xa4, 0x9b, - 0x6c, 0xd6, 0xa6, 0x4e, 0x02, 0xa5, 0x23, 0x4e, 0xde, 0x62, 0x14, 0xce, 0x8b, 0x13, 0x06, 0x74, 0xbd, 0x14, 0x83, - 0x69, 0xe3, 0x8b, 0xe2, 0x95, 0x2d, 0xa7, 0x86, 0xfd, 0x38, 0xb7, 0x35, 0x27, 0x1c, 0x8e, 0x32, 0x51, 0xf6, 0x4e, - 0x95, 0x1e, 0x0a, 0xac, 0x9b, 0x06, 0xea, 0xfd, 0x84, 0x5d, 0x70, 0xb7, 0x3d, 0x3e, 0xa6, 0x72, 0x04, 0x15, 0x42, - 0x21, 0x41, 0x2d, 0x53, 0xfa, 0x23, 0xe6, 0x39, 0x35, 0x62, 0xaf, 0x3c, 0x2a, 0x65, 0x22, 0x88, 0xc7, 0x3e, 0x7b, - 0xb0, 0xc7, 0x16, 0x08, 0x87, 0x1d, 0x4e, 0x74, 0xa5, 0x80, 0x7e, 0x90, 0x36, 0x82, 0x9d, 0x8f, 0x85, 0x22, 0x59, - 0x80, 0x62, 0x68, 0x37, 0xe2, 0xa4, 0xca, 0xee, 0x92, 0xd0, 0xef, 0xc5, 0x02, 0x67, 0x76, 0x2e, 0x81, 0xe4, 0x3a, - 0x5b, 0x18, 0x64, 0x54, 0x08, 0xed, 0x16, 0x12, 0x10, 0xa6, 0x74, 0x91, 0x0f, 0xf8, 0x91, 0x5e, 0x2a, 0x97, 0x0a, - 0xc9, 0xd3, 0xa5, 0xcf, 0xe1, 0x97, 0x1d, 0xb5, 0xe2, 0xc6, 0x5b, 0x1b, 0xe5, 0x1a, 0xe5, 0x62, 0xd6, 0xfc, 0x47, - 0xec, 0x71, 0x89, 0x74, 0x6c, 0x81, 0xb5, 0xa1, 0x1b, 0x54, 0x96, 0xd2, 0xc0, 0x89, 0x07, 0x12, 0xa9, 0xdb, 0x0e, - 0x47, 0xda, 0xa2, 0xf6, 0x93, 0xbd, 0x57, 0xd7, 0xa0, 0xf4, 0xcc, 0x7a, 0x2b, 0x71, 0x68, 0x2a, 0x64, 0x91, 0x55, - 0xd5, 0x80, 0x95, 0x7c, 0x1c, 0xd2, 0x64, 0x88, 0xee, 0x92, 0xc4, 0x93, 0xcc, 0xe9, 0x37, 0x99, 0xe9, 0x45, 0xff, - 0xa3, 0x12, 0x95, 0x0f, 0x65, 0xff, 0x93, 0x1c, 0xcf, 0x3a, 0xa9, 0x1f, 0x85, 0xd3, 0x90, 0xc6, 0x26, 0x13, 0x30, - 0x80, 0xd5, 0x86, 0x39, 0x94, 0x19, 0x2d, 0x5b, 0xc5, 0xb9, 0xdb, 0x46, 0x4a, 0x6c, 0xe8, 0x27, 0x3b, 0x06, 0xec, - 0x8f, 0xbf, 0x02, 0x71, 0xc0, 0x23, 0x66, 0x1c, 0xec, 0xad, 0x98, 0xb4, 0xa9, 0x28, 0xf8, 0x5d, 0x69, 0x34, 0x81, - 0x6b, 0x3a, 0xa4, 0x69, 0x73, 0xe5, 0x18, 0x32, 0xbd, 0x6c, 0xcc, 0x84, 0x98, 0x39, 0x78, 0x46, 0x28, 0xf6, 0xdf, - 0xfd, 0x77, 0x09, 0x8e, 0x16, 0x8d, 0xf2, 0xe4, 0xb4, 0x0e, 0xe6, 0x56, 0x5d, 0x7a, 0xe7, 0x7e, 0x08, 0x69, 0x03, - 0x80, 0xca, 0x9d, 0xed, 0x59, 0x88, 0xbb, 0xdb, 0x2a, 0x44, 0x1f, 0xcc, 0x52, 0x93, 0xf2, 0xae, 0x97, 0x6c, 0x2c, - 0x61, 0x9e, 0x32, 0x2b, 0x87, 0xd6, 0x81, 0x9d, 0xfd, 0x63, 0xfa, 0x1f, 0xc9, 0xf7, 0x9b, 0xfc, 0x7c, 0xb7, 0x46, - 0x14, 0x98, 0x91, 0x57, 0xf4, 0x3e, 0x07, 0xa0, 0xde, 0x40, 0x24, 0x97, 0xe5, 0x3d, 0x5c, 0xd4, 0x3d, 0xfc, 0x65, - 0x2e, 0x1a, 0x1f, 0x78, 0xcc, 0x57, 0x94, 0xdb, 0x0f, 0x1b, 0x1e, 0x08, 0x44, 0xee, 0x02, 0x23, 0x4c, 0xff, 0x3e, - 0x39, 0xe6, 0xe3, 0xa9, 0xf0, 0xca, 0xab, 0x17, 0xb0, 0xea, 0x89, 0x0f, 0xaf, 0xcf, 0xb0, 0xb5, 0xff, 0x44, 0x66, - 0x15, 0x97, 0x60, 0x66, 0xb0, 0xa8, 0xb8, 0x5f, 0x73, 0x65, 0x07, 0x17, 0xad, 0xee, 0x3b, 0x19, 0xff, 0x7c, 0x19, - 0xee, 0xbe, 0x7e, 0xee, 0x14, 0x8d, 0x73, 0x78, 0x8f, 0x71, 0xc4, 0x35, 0x2e, 0xe1, 0xed, 0xc7, 0x67, 0x55, 0x37, - 0xf7, 0x8c, 0x7d, 0xd6, 0x74, 0x63, 0x55, 0x33, 0xb4, 0x21, 0x71, 0xfe, 0xc3, 0xd6, 0x5f, 0x2c, 0xbc, 0xd8, 0xfd, - 0xc4, 0x4e, 0x8a, 0xac, 0x0b, 0x5a, 0xb7, 0x5d, 0xab, 0xf2, 0x83, 0x01, 0x97, 0x3a, 0x1e, 0x4b, 0xb6, 0x3a, 0xbb, - 0x5f, 0x8c, 0x3f, 0x9a, 0x09, 0xb4, 0x3f, 0xfa, 0xe0, 0x66, 0x09, 0x55, 0x7b, 0x9c, 0xd1, 0xdd, 0xb7, 0x3f, 0x7b, - 0x39, 0x76, 0x59, 0x9a, 0xf8, 0xdc, 0x27, 0xc7, 0xc8, 0x13, 0xe9, 0x2d, 0xb4, 0x0a, 0xc3, 0xf4, 0xdc, 0x3d, 0x44, - 0x6a, 0x91, 0x2c, 0x3d, 0x7b, 0x0b, 0x97, 0x9c, 0xd0, 0x99, 0x7e, 0x29, 0x09, 0x75, 0xdb, 0x6b, 0xc5, 0x25, 0x62, - 0x7e, 0x8d, 0xd4, 0xc0, 0x55, 0x12, 0x3c, 0x44, 0x44, 0xa0, 0xb3, 0x17, 0xe5, 0x33, 0x45, 0x75, 0x85, 0x57, 0x7f, - 0x8d, 0xb2, 0x80, 0x57, 0x66, 0xe3, 0x61, 0xe5, 0x4c, 0x1f, 0x9d, 0xd6, 0x59, 0xae, 0xcb, 0x00, 0x72, 0x71, 0x01, - 0x4e, 0xec, 0xdf, 0x72, 0x06, 0xc3, 0xda, 0x86, 0xfb, 0x23, 0x35, 0x1a, 0xa3, 0xe4, 0x1b, 0x02, 0x30, 0x0a, 0x8a, - 0x36, 0xb3, 0xef, 0x36, 0xa4, 0x0b, 0x19, 0xd5, 0xfb, 0xfd, 0xf7, 0xfc, 0xe5, 0xd1, 0x77, 0xbe, 0x5d, 0x7a, 0xad, - 0x85, 0x49, 0x65, 0x91, 0xad, 0xa3, 0x83, 0xec, 0xae, 0x87, 0x6d, 0x90, 0xdf, 0x74, 0x9f, 0x49, 0x37, 0x2f, 0x06, - 0xd8, 0xd2, 0xf6, 0x23, 0x32, 0x8d, 0x24, 0x51, 0xc8, 0xb1, 0x96, 0x22, 0xa8, 0x65, 0x20, 0x15, 0x47, 0x0e, 0x0f, - 0x4f, 0x46, 0xbe, 0x99, 0x33, 0x0e, 0x2d, 0x69, 0x0b, 0xd8, 0x18, 0xd6, 0xdd, 0xd7, 0x52, 0x9b, 0x65, 0xd6, 0xab, - 0x47, 0x76, 0x22, 0xbc, 0xe0, 0x08, 0x4a, 0xec, 0x53, 0x48, 0x0b, 0xab, 0xb1, 0x0c, 0x6e, 0x5e, 0x4f, 0x28, 0xa0, - 0x6d, 0x2e, 0x9d, 0x53, 0xab, 0xc8, 0x57, 0xfc, 0x7c, 0x58, 0x83, 0x21, 0xf9, 0xd6, 0x4a, 0xc1, 0xc6, 0xae, 0x55, - 0xa5, 0xf1, 0x1c, 0x6f, 0x68, 0x52, 0x1c, 0x1d, 0xed, 0x51, 0x76, 0x08, 0x47, 0x63, 0x70, 0x73, 0x6f, 0xa8, 0xa4, - 0x4c, 0x63, 0xdf, 0x4b, 0xd2, 0xbf, 0xea, 0xcb, 0x50, 0x25, 0x24, 0x8a, 0xf9, 0x1f, 0x54, 0x63, 0x0e, 0x3c, 0x52, - 0x1f, 0xbd, 0xc8, 0x04, 0xa3, 0x85, 0x42, 0x74, 0x83, 0x87, 0x9d, 0x3a, 0x11, 0xcf, 0x5e, 0xa2, 0x70, 0xd2, 0xbd, - 0x24, 0x9a, 0x17, 0xfe, 0xd9, 0x6f, 0x9e, 0x7b, 0x01, 0xd0, 0x29, 0x2c, 0x9d, 0x31, 0x70, 0xca, 0x9a, 0x74, 0xa4, - 0xe0, 0xd6, 0x68, 0xa0, 0x09, 0x6c, 0xc1, 0xd3, 0xa9, 0x0c, 0xb9, 0x28, 0x67, 0x96, 0xf4, 0x64, 0x17, 0x53, 0x6a, - 0xcd, 0xf7, 0x85, 0xb2, 0xb0, 0x7e, 0xb7, 0x79, 0x94, 0x3b, 0x47, 0x66, 0x25, 0x82, 0x45, 0x9e, 0x02, 0xaf, 0x5c, - 0xde, 0x78, 0xd1, 0xe8, 0x39, 0x78, 0x99, 0x9a, 0x79, 0x0e, 0x07, 0x79, 0xe9, 0x2f, 0xbc, 0x78, 0xfb, 0x7e, 0x0f, - 0xfa, 0x1a, 0xb9, 0x0a, 0x8b, 0xa8, 0x07, 0xe4, 0xbc, 0xe3, 0xa8, 0xbb, 0xfb, 0xe0, 0x93, 0x8e, 0x97, 0x5c, 0x35, - 0x3e, 0x84, 0xbf, 0xa4, 0xd1, 0x17, 0x92, 0xa0, 0x39, 0x15, 0x52, 0x60, 0xe0, 0xaf, 0x5b, 0xd8, 0xf8, 0x3e, 0x4b, - 0xb7, 0x23, 0x26, 0x7f, 0xf5, 0xbe, 0xd2, 0x93, 0x5d, 0x8f, 0x49, 0x3d, 0x05, 0x8a, 0x3a, 0x3b, 0x5a, 0x36, 0x23, - 0xad, 0xd4, 0xbc, 0x5b, 0xb8, 0xf5, 0x81, 0x4f, 0xe9, 0xc0, 0x8e, 0x02, 0x77, 0x41, 0x2c, 0x9e, 0x71, 0x7e, 0x6d, - 0x66, 0xb7, 0x3e, 0xfb, 0x2e, 0x03, 0x8c, 0x5a, 0x4f, 0xf4, 0x41, 0x10, 0xdf, 0x67, 0x47, 0xac, 0xbb, 0x04, 0x96, - 0x60, 0x4c, 0x4f, 0xdb, 0x24, 0x9c, 0x96, 0xfb, 0x64, 0x7e, 0xc8, 0xc6, 0x04, 0x8a, 0x4a, 0x31, 0x57, 0x81, 0x4f, - 0x26, 0x40, 0xcc, 0x21, 0x25, 0xdb, 0xab, 0x33, 0xf9, 0x44, 0xcc, 0x85, 0x2a, 0x45, 0x73, 0x31, 0x02, 0x42, 0x90, - 0xc3, 0x8c, 0xed, 0x3f, 0xc2, 0x85, 0x08, 0x70, 0x87, 0x83, 0x2c, 0x73, 0xde, 0xe0, 0xaa, 0xcc, 0x2f, 0x00, 0x73, - 0x19, 0xea, 0xad, 0xc6, 0x4e, 0x8f, 0x61, 0xf9, 0x7d, 0x1a, 0x64, 0xbd, 0x22, 0x77, 0x61, 0x19, 0xc2, 0xeb, 0xa2, - 0x54, 0x8d, 0x40, 0xba, 0x3b, 0x8c, 0xd3, 0xaf, 0x20, 0x61, 0xfa, 0x59, 0x02, 0x9e, 0xa3, 0x38, 0x11, 0x0b, 0xfe, - 0xdc, 0xd0, 0xa5, 0x13, 0xe4, 0x80, 0xa1, 0x1e, 0x9e, 0x5e, 0x51, 0xf7, 0x92, 0x1d, 0xdd, 0x6d, 0x59, 0xa5, 0xec, - 0x6f, 0x27, 0xf2, 0x63, 0xd9, 0x39, 0x5e, 0xf2, 0xa6, 0xbb, 0x89, 0xdf, 0x22, 0x8e, 0x02, 0x88, 0x63, 0x55, 0x76, - 0xa1, 0x4a, 0x44, 0xbe, 0x2e, 0x9c, 0x39, 0xe5, 0x79, 0x64, 0xc9, 0xce, 0xdb, 0xdd, 0x77, 0xa6, 0xd8, 0x91, 0x66, - 0x76, 0xce, 0x7b, 0xc5, 0x4f, 0x95, 0x12, 0xd3, 0x37, 0x0e, 0xce, 0xfd, 0x9d, 0xf4, 0xfd, 0xf1, 0x70, 0x2c, 0xb1, - 0x9e, 0x5f, 0x73, 0xd5, 0xf6, 0x94, 0xaa, 0x65, 0xad, 0xbf, 0x53, 0xbe, 0xa6, 0x6c, 0xdd, 0xec, 0x67, 0xb0, 0x23, - 0xd7, 0xcc, 0x97, 0x2e, 0xa4, 0x77, 0x7d, 0x39, 0xc9, 0xae, 0x0a, 0xec, 0xd1, 0x07, 0x06, 0xd0, 0xb4, 0xae, 0x0c, - 0xc5, 0x57, 0x6a, 0x19, 0xb9, 0x4c, 0x80, 0xd7, 0xc1, 0x4f, 0x5f, 0xcc, 0x7c, 0x39, 0x66, 0xab, 0x77, 0xde, 0x1f, - 0x31, 0x2f, 0xba, 0xb3, 0xe7, 0x7a, 0x87, 0xb8, 0x18, 0xe7, 0x7d, 0x07, 0x66, 0xe9, 0xb7, 0x1e, 0xf3, 0x79, 0x7f, - 0x9d, 0x60, 0x7f, 0x64, 0x45, 0x30, 0xc8, 0xe0, 0xae, 0x7a, 0xc1, 0x71, 0x16, 0x86, 0x68, 0xda, 0x76, 0x5f, 0xd4, - 0xcc, 0x6d, 0x49, 0xd3, 0xe7, 0xbc, 0xa5, 0x12, 0xf6, 0x8b, 0x3b, 0xce, 0xac, 0xef, 0xbc, 0x83, 0xac, 0xb5, 0xea, - 0xd0, 0xaf, 0x48, 0xbd, 0x0c, 0xeb, 0x3f, 0x81, 0x62, 0xbc, 0xec, 0xb0, 0xda, 0x5a, 0x69, 0x7a, 0xae, 0xca, 0xde, - 0xe1, 0x49, 0x05, 0xa0, 0x14, 0x01, 0x9d, 0x75, 0xe3, 0xb8, 0x9b, 0x02, 0xf5, 0xc5, 0x29, 0xda, 0xf5, 0xf7, 0xd7, - 0xc0, 0x28, 0x88, 0xd4, 0xf7, 0xab, 0xbc, 0x27, 0xfd, 0x95, 0xf8, 0x58, 0x78, 0x45, 0xa1, 0xdb, 0xf2, 0xf8, 0x2f, - 0x8a, 0x94, 0xe9, 0x27, 0x21, 0xdc, 0xf9, 0xb9, 0xba, 0x85, 0x89, 0xf9, 0x74, 0xe9, 0xf9, 0x3d, 0x5a, 0x87, 0x2b, - 0x68, 0x7d, 0xe6, 0x07, 0x69, 0xcc, 0xff, 0x39, 0x56, 0x59, 0xe2, 0x1d, 0x9a, 0xe5, 0xdb, 0x04, 0xc7, 0x74, 0x78, - 0x4a, 0x3a, 0xcf, 0x71, 0x42, 0xa1, 0x1b, 0x94, 0x7a, 0xa7, 0x0e, 0x35, 0x93, 0xc0, 0x42, 0x81, 0x93, 0x7e, 0x44, - 0xf3, 0xa8, 0x38, 0x12, 0xc0, 0xc8, 0xf4, 0xfa, 0xdb, 0x5c, 0x5b, 0xe4, 0xc3, 0x5e, 0xfb, 0x65, 0xe3, 0x5e, 0x1f, - 0x05, 0xc9, 0x7f, 0xc7, 0x01, 0x12, 0x6b, 0x43, 0xf6, 0x26, 0x60, 0x19, 0x51, 0xcc, 0x51, 0xf0, 0x6d, 0x41, 0x52, - 0xa8, 0x54, 0x82, 0x0b, 0x7b, 0x84, 0x85, 0x4b, 0x2d, 0x2d, 0x63, 0x2d, 0x3c, 0x6f, 0x01, 0x3a, 0x3a, 0x7c, 0x5d, - 0x7c, 0x97, 0x9d, 0x5e, 0x0c, 0x92, 0x73, 0x8f, 0x10, 0x24, 0xa8, 0xc7, 0x45, 0x09, 0xb8, 0x6f, 0x56, 0xe3, 0x6b, - 0x41, 0x4d, 0x9a, 0xd4, 0x5d, 0x05, 0xa7, 0xbb, 0x50, 0xc0, 0x65, 0x74, 0xd6, 0x40, 0xd0, 0xf0, 0xdd, 0x91, 0x0c, - 0xb0, 0x2a, 0x48, 0x90, 0xb8, 0xe4, 0x87, 0xc4, 0x4a, 0x45, 0x77, 0x78, 0x47, 0x63, 0xbc, 0xa3, 0xb6, 0x2e, 0x3b, - 0xed, 0x6b, 0xef, 0x36, 0x0c, 0xc2, 0x88, 0xf1, 0x99, 0x81, 0x8e, 0xec, 0xed, 0x80, 0x4d, 0x9e, 0x9d, 0xb0, 0x01, - 0x8f, 0xe5, 0x8e, 0x8c, 0xd6, 0xf9, 0x35, 0xcb, 0x17, 0x7b, 0xda, 0xe7, 0x9e, 0x84, 0x8c, 0x8d, 0x23, 0x70, 0xa3, - 0x06, 0x64, 0x4a, 0x98, 0x25, 0xfc, 0xc8, 0xa1, 0xfa, 0x2c, 0x09, 0xfe, 0x2b, 0x6d, 0x40, 0x01, 0x39, 0xda, 0x93, - 0x4a, 0x92, 0x79, 0x0c, 0xb3, 0x26, 0x85, 0x0f, 0xc8, 0x50, 0xe6, 0xf8, 0x69, 0xa8, 0x29, 0xd6, 0x89, 0xa1, 0x1a, - 0x99, 0x26, 0x86, 0xef, 0x1a, 0xf3, 0x57, 0xdc, 0xfc, 0xd9, 0xab, 0xaa, 0xa7, 0x43, 0xf0, 0x10, 0x4a, 0x09, 0xca, - 0xcd, 0x4c, 0x28, 0x03, 0xe8, 0x17, 0x69, 0xb2, 0x01, 0xad, 0x1f, 0xa1, 0xc3, 0xf7, 0x9b, 0x23, 0x38, 0xb9, 0x2c, - 0x55, 0x58, 0x17, 0x3f, 0xfe, 0x4a, 0x60, 0xef, 0xdd, 0x61, 0xba, 0x51, 0xce, 0xe6, 0xd4, 0x96, 0x4c, 0x5d, 0xf0, - 0x75, 0xb9, 0x3e, 0x09, 0x5e, 0x59, 0x20, 0x35, 0x0b, 0xab, 0x75, 0xe2, 0x12, 0x59, 0xb4, 0x38, 0x4d, 0xde, 0xcd, - 0x5f, 0x9e, 0x66, 0x13, 0xaf, 0x5c, 0x0a, 0x4c, 0x7e, 0x16, 0x55, 0xe2, 0x22, 0xb3, 0x5c, 0x36, 0xfc, 0xcd, 0x01, - 0x9f, 0x67, 0x7d, 0x3d, 0xf0, 0xbb, 0xfe, 0x5c, 0xdf, 0x1e, 0xf2, 0x90, 0x50, 0x8b, 0xdb, 0x1a, 0x67, 0x4e, 0x8d, - 0x6d, 0xe6, 0xbd, 0x5d, 0xda, 0xc7, 0x71, 0xcc, 0x7c, 0x44, 0x45, 0xba, 0xa2, 0x24, 0xec, 0x4e, 0x87, 0xa4, 0x53, - 0x4c, 0x56, 0x9c, 0x39, 0xf5, 0x54, 0xb8, 0x2d, 0xce, 0x6b, 0x7c, 0xb8, 0x44, 0x74, 0x82, 0xa9, 0x03, 0x24, 0xd7, - 0xb1, 0x25, 0xb8, 0xab, 0x08, 0x5c, 0x9a, 0x5a, 0xa8, 0xa2, 0x78, 0xc6, 0x59, 0xec, 0x16, 0x52, 0xf3, 0x53, 0xf5, - 0xb8, 0xd4, 0xad, 0x2a, 0xe1, 0x95, 0x6c, 0x85, 0x29, 0x90, 0xc9, 0x8a, 0xa4, 0x39, 0x89, 0x15, 0x0e, 0xfa, 0x9e, - 0x43, 0x92, 0xbd, 0x58, 0xf6, 0xb6, 0x7f, 0xeb, 0x6a, 0xcd, 0x0a, 0xa3, 0x5d, 0xac, 0x16, 0xc5, 0x8b, 0x54, 0x6d, - 0x1f, 0xa8, 0xbb, 0xca, 0x7d, 0xc7, 0x40, 0xa3, 0x46, 0x2a, 0x5b, 0x51, 0x47, 0x6a, 0x78, 0xcc, 0x5f, 0x9b, 0xe9, - 0x88, 0x31, 0x6c, 0xd8, 0xd1, 0x41, 0xb3, 0xb9, 0x0c, 0x8a, 0xa9, 0xc5, 0x61, 0x54, 0x1a, 0xba, 0x8d, 0xc8, 0x57, - 0x28, 0xcf, 0xec, 0x1b, 0x63, 0x43, 0x2c, 0xd9, 0x53, 0xbc, 0x06, 0xc2, 0x24, 0xa5, 0xcf, 0x62, 0x8b, 0xc2, 0xa6, - 0xcd, 0xed, 0x99, 0x63, 0x03, 0x0e, 0xae, 0x92, 0x52, 0xa6, 0xab, 0xc2, 0xab, 0x40, 0x29, 0xac, 0x44, 0x67, 0x09, - 0x21, 0x63, 0x9e, 0xbd, 0xf3, 0x53, 0xd3, 0x73, 0x8f, 0x80, 0x68, 0xf6, 0x05, 0x1c, 0x05, 0x1f, 0xc4, 0x88, 0x8f, - 0x34, 0xe4, 0x1c, 0xbe, 0x72, 0x98, 0xbe, 0xb7, 0x85, 0xe4, 0x47, 0x3f, 0x1f, 0x2f, 0x94, 0x29, 0x49, 0xb5, 0x83, - 0xd0, 0x06, 0x12, 0x67, 0x80, 0x78, 0x96, 0x81, 0x25, 0x28, 0x8d, 0x01, 0x83, 0x83, 0xcf, 0x47, 0xbb, 0x22, 0xd4, - 0x12, 0xa1, 0xbb, 0x2c, 0x5d, 0x80, 0xb3, 0x6e, 0x90, 0xd1, 0x26, 0xf6, 0x70, 0x7f, 0xe1, 0x80, 0xee, 0xc4, 0xe0, - 0xc8, 0xc9, 0xec, 0xb2, 0x25, 0xc1, 0xc4, 0xbf, 0x8b, 0xa6, 0x8d, 0x25, 0x52, 0x21, 0xde, 0x58, 0x3a, 0xc0, 0x4c, - 0xa1, 0x3d, 0x55, 0xeb, 0x8e, 0x48, 0xf1, 0x1b, 0xe0, 0x41, 0x34, 0x42, 0x03, 0x47, 0xa2, 0x7e, 0x1e, 0xa3, 0x25, - 0xc6, 0x23, 0xce, 0x7f, 0x4c, 0x2d, 0x07, 0x93, 0x04, 0x72, 0x18, 0xed, 0x1e, 0x3b, 0x13, 0x8a, 0xb3, 0x9d, 0xb4, - 0x6c, 0x3d, 0xfd, 0xdc, 0xa6, 0x0f, 0x66, 0xef, 0x15, 0xde, 0x10, 0x5c, 0x28, 0xfa, 0xcb, 0x2d, 0xcf, 0x30, 0x02, - 0x0c, 0x86, 0xdd, 0x60, 0xfe, 0xfd, 0xe9, 0x24, 0x3a, 0x3c, 0xaa, 0x1f, 0xae, 0x7a, 0x3b, 0x98, 0x3a, 0x93, 0xc1, - 0xf9, 0xe4, 0x97, 0x89, 0xbb, 0xef, 0x44, 0xf2, 0xc5, 0x94, 0x79, 0x8e, 0x7c, 0xd2, 0x09, 0xcc, 0x76, 0x0d, 0xa3, - 0x9a, 0x5a, 0x02, 0x91, 0x88, 0xa9, 0xd0, 0x8d, 0x94, 0xf3, 0x72, 0x7b, 0x4b, 0xe1, 0xfb, 0x6d, 0xaa, 0x52, 0xa5, - 0x46, 0x11, 0x96, 0x9b, 0xf4, 0x83, 0x83, 0xee, 0xf7, 0xa5, 0xbc, 0x5c, 0x4e, 0x6b, 0x91, 0xc7, 0x43, 0x21, 0xea, - 0x7c, 0xa4, 0xbd, 0x7f, 0xa2, 0xf3, 0x33, 0x49, 0xc8, 0xae, 0xff, 0x54, 0x11, 0x60, 0xfc, 0x15, 0xa2, 0xae, 0x4d, - 0x32, 0xa8, 0xd4, 0x4b, 0x2b, 0xbc, 0x83, 0xaf, 0x88, 0xdc, 0x0a, 0xfa, 0x95, 0x51, 0xe5, 0xad, 0x57, 0x6d, 0x97, - 0xb3, 0x2f, 0xb0, 0x60, 0xd3, 0x9a, 0x0e, 0x5e, 0xf9, 0xeb, 0xe0, 0xa8, 0xa0, 0x37, 0x9c, 0x3a, 0x23, 0xf5, 0x10, - 0xef, 0xe7, 0x02, 0x05, 0x27, 0xc4, 0x3f, 0x0a, 0x86, 0x46, 0xe9, 0x5a, 0x6a, 0x63, 0x6c, 0x0f, 0x98, 0xaf, 0x57, - 0x95, 0x71, 0x95, 0xdd, 0x09, 0x1e, 0x3b, 0x37, 0x3e, 0x85, 0x91, 0xb4, 0x3c, 0xc0, 0x39, 0xab, 0x43, 0x07, 0xce, - 0x6b, 0xf6, 0x85, 0x6a, 0x3d, 0x14, 0x33, 0x12, 0x6d, 0x4d, 0xb0, 0x8c, 0x3c, 0x9b, 0xb5, 0xe7, 0xa9, 0x49, 0x66, - 0x35, 0xd2, 0x66, 0x7c, 0x6a, 0xfa, 0xaf, 0x01, 0xb1, 0x1e, 0x74, 0xf9, 0x6d, 0xa5, 0xfa, 0x5a, 0x21, 0xeb, 0x11, - 0xc7, 0x4a, 0x95, 0x6d, 0x83, 0x63, 0x07, 0x6e, 0x35, 0x1e, 0x0f, 0xbe, 0x17, 0xd2, 0x58, 0x9d, 0x04, 0x2e, 0x9d, - 0x50, 0xf9, 0x86, 0x2b, 0x06, 0x76, 0x12, 0xdd, 0x2c, 0x17, 0x51, 0x22, 0x45, 0xfe, 0x36, 0x70, 0x8a, 0xe1, 0x50, - 0x08, 0x0f, 0xe2, 0xdf, 0x24, 0x09, 0xf3, 0x3a, 0x52, 0x9d, 0x58, 0xed, 0xe0, 0x7a, 0x95, 0x1e, 0x05, 0x07, 0x6b, - 0xaa, 0xa4, 0x0d, 0x25, 0xea, 0x52, 0x8f, 0x61, 0x4d, 0x0f, 0x87, 0x7a, 0x71, 0xe3, 0x70, 0xe5, 0x63, 0xcd, 0xa2, - 0xf5, 0x17, 0x35, 0x1c, 0xab, 0x11, 0x36, 0x53, 0x11, 0xcd, 0xec, 0xff, 0x88, 0x2b, 0x1d, 0xb2, 0x0b, 0x80, 0xda, - 0x8f, 0xf8, 0x06, 0x55, 0x31, 0x02, 0xb4, 0x9f, 0x96, 0x6f, 0xa4, 0x3e, 0xe5, 0x19, 0x8b, 0xeb, 0x16, 0x51, 0xe4, - 0x22, 0x18, 0x6b, 0x8a, 0x0d, 0x00, 0x61, 0xd9, 0x02, 0x1b, 0x88, 0xa2, 0x59, 0x94, 0x4d, 0xdd, 0x60, 0xb7, 0x78, - 0x01, 0xd1, 0x9a, 0xc7, 0x67, 0x62, 0xcd, 0x9c, 0x1b, 0xa9, 0x2c, 0x2b, 0x7c, 0xff, 0xea, 0x8a, 0xb9, 0x42, 0x83, - 0xf7, 0xf6, 0xdc, 0xca, 0x1e, 0x9d, 0x0f, 0x76, 0x33, 0xfd, 0x0b, 0xbb, 0x0e, 0x6f, 0xd9, 0x26, 0xcc, 0x08, 0x9f, - 0xdc, 0x3e, 0xfe, 0x8a, 0x35, 0xe1, 0xfc, 0x47, 0x51, 0x31, 0x28, 0x5c, 0x41, 0xb0, 0xa8, 0x35, 0xe3, 0x94, 0xc2, - 0x63, 0x1f, 0xa8, 0xd0, 0x1e, 0x24, 0x26, 0x08, 0xa3, 0x2a, 0x53, 0x25, 0xb2, 0xe7, 0xe2, 0x57, 0x6d, 0x22, 0x83, - 0xc9, 0x38, 0x94, 0x0d, 0xdc, 0xd4, 0xae, 0x39, 0x33, 0x3b, 0x4b, 0xeb, 0xdf, 0x6b, 0x8e, 0x75, 0x58, 0xb0, 0x44, - 0x6b, 0xa8, 0x99, 0x5e, 0x56, 0x2d, 0xc2, 0x5b, 0xc3, 0x74, 0x78, 0x08, 0x52, 0xcb, 0x22, 0xe1, 0x0f, 0xdd, 0x77, - 0xd0, 0x22, 0x18, 0xa3, 0x11, 0x58, 0x19, 0xa7, 0x90, 0xeb, 0xfc, 0x38, 0x25, 0x0a, 0xd4, 0xb2, 0xde, 0x67, 0x2c, - 0x73, 0xe4, 0x35, 0x2b, 0xf3, 0x34, 0x2b, 0x7a, 0x8f, 0xb2, 0xa1, 0xe3, 0xfa, 0x73, 0x26, 0x1a, 0x49, 0x87, 0x86, - 0x3a, 0x1d, 0xe7, 0xc4, 0x95, 0x35, 0x47, 0x53, 0x24, 0xb7, 0xf5, 0x40, 0xda, 0xcd, 0x6c, 0x25, 0x4c, 0xb6, 0xd8, - 0x6c, 0x46, 0xd8, 0xee, 0x68, 0xec, 0x33, 0x4f, 0x1c, 0xd7, 0x10, 0x3d, 0xd0, 0xe6, 0xce, 0x4b, 0x6e, 0x5c, 0xfc, - 0xef, 0xa0, 0x88, 0x6e, 0x1e, 0x8e, 0x08, 0xe6, 0x72, 0x4e, 0x51, 0x3c, 0xdd, 0x1c, 0x87, 0xc0, 0x86, 0xf5, 0x9f, - 0x9b, 0xe8, 0x4a, 0x8e, 0xe7, 0xa8, 0xd2, 0x23, 0x05, 0x71, 0x62, 0x7b, 0x76, 0x0d, 0x49, 0xfb, 0x11, 0x09, 0xcf, - 0x29, 0xeb, 0x6c, 0x74, 0xae, 0x73, 0x5d, 0x7a, 0x1f, 0x7f, 0x25, 0x3d, 0x21, 0x08, 0x0c, 0xf3, 0xa7, 0xb8, 0x9f, - 0xc0, 0x8a, 0x0b, 0xab, 0x52, 0xae, 0x78, 0xe1, 0x5f, 0x73, 0xc6, 0xf7, 0xb4, 0x2a, 0x2b, 0xd9, 0x71, 0x79, 0xa5, - 0x73, 0xd6, 0x50, 0xa5, 0x63, 0xa6, 0xcb, 0x8a, 0xc5, 0xf4, 0x8e, 0xfd, 0xba, 0x36, 0x04, 0x34, 0x74, 0xe7, 0xdc, - 0x51, 0x31, 0x93, 0xe0, 0x69, 0x88, 0xa5, 0x52, 0x80, 0xae, 0xd0, 0x67, 0xe6, 0xe4, 0x9b, 0x61, 0x1e, 0x0c, 0xf9, - 0x59, 0x00, 0x08, 0x57, 0x26, 0xa8, 0xac, 0xc0, 0xb3, 0xe2, 0x5a, 0xd1, 0x79, 0x0d, 0xe6, 0x22, 0xa2, 0xde, 0x6b, - 0xa4, 0xff, 0x00, 0x09, 0x97, 0x60, 0x2f, 0x05, 0x2e, 0x06, 0x74, 0xf9, 0xcc, 0x1d, 0x5a, 0x97, 0x08, 0x31, 0xd6, - 0x80, 0xa4, 0xb6, 0xf1, 0xcb, 0xc5, 0x84, 0x7b, 0xde, 0xcf, 0x03, 0xce, 0xba, 0x7e, 0x06, 0x90, 0x07, 0xf9, 0xf3, - 0x57, 0xb7, 0x72, 0x39, 0xc8, 0x09, 0x48, 0x5c, 0x5c, 0xb8, 0xf2, 0x88, 0x76, 0x4e, 0x8b, 0xb6, 0xcc, 0xd5, 0x28, - 0xe3, 0xb6, 0x06, 0x29, 0x52, 0xb8, 0xd8, 0x48, 0xfb, 0x18, 0xb8, 0x20, 0xe9, 0x89, 0x0d, 0x85, 0x84, 0x1d, 0xbb, - 0xf6, 0x62, 0x2a, 0xb7, 0x33, 0xea, 0x06, 0xfa, 0x62, 0xeb, 0x6f, 0x34, 0xfe, 0xb4, 0xb1, 0x76, 0xa6, 0xef, 0x19, - 0x5c, 0x11, 0xa9, 0x46, 0x9f, 0x57, 0x58, 0x7d, 0xda, 0xef, 0xca, 0x1d, 0xac, 0xd6, 0x97, 0xd1, 0x57, 0x15, 0x1b, - 0xf5, 0x89, 0x0d, 0x82, 0x49, 0x92, 0x54, 0x72, 0x6b, 0x50, 0x52, 0xd0, 0x98, 0xb7, 0x51, 0x43, 0x56, 0x4a, 0x6b, - 0x26, 0x7b, 0xf1, 0xbf, 0x73, 0xc5, 0xcc, 0xc4, 0xc0, 0x8f, 0xb1, 0xa5, 0x3e, 0x79, 0xf4, 0xc4, 0x5b, 0xeb, 0xf7, - 0x9c, 0xa1, 0x63, 0xf6, 0x00, 0x81, 0x42, 0x60, 0x5e, 0xba, 0xc4, 0x9c, 0x5b, 0x33, 0x6b, 0xd6, 0xd4, 0xcb, 0x7f, - 0x66, 0x57, 0xba, 0xc0, 0xd8, 0x27, 0x82, 0xfe, 0x5c, 0xda, 0xed, 0xd4, 0x37, 0x66, 0xef, 0x06, 0x9c, 0x06, 0x98, - 0xb9, 0x78, 0x53, 0xe9, 0xdd, 0xd5, 0xe6, 0x11, 0x0b, 0x60, 0x72, 0x36, 0xfa, 0x97, 0xa6, 0x22, 0xf8, 0xcb, 0xa3, - 0xb3, 0x17, 0xeb, 0x23, 0x0a, 0x05, 0x5f, 0x46, 0x23, 0xde, 0x65, 0xf4, 0x2f, 0x1a, 0x5a, 0xff, 0x03, 0xfb, 0x60, - 0x1b, 0x97, 0x61, 0x0f, 0xed, 0xc3, 0x24, 0x76, 0x45, 0xd0, 0xd6, 0xc6, 0x82, 0x20, 0x6b, 0xea, 0x72, 0x60, 0x44, - 0x8a, 0xdf, 0x5a, 0x27, 0x9d, 0xd7, 0xb1, 0xef, 0xda, 0x89, 0xf3, 0x21, 0x11, 0x23, 0xf0, 0x5b, 0xf4, 0x7c, 0x24, - 0xa1, 0x82, 0x4b, 0x47, 0x2f, 0x13, 0x3c, 0xea, 0x12, 0x27, 0xd5, 0xae, 0x97, 0xa3, 0xf6, 0xcf, 0xfa, 0x66, 0x3f, - 0x18, 0x94, 0xae, 0x1b, 0x86, 0x6f, 0xe9, 0xb5, 0xcc, 0x91, 0x87, 0x77, 0x7d, 0xa3, 0xb5, 0x05, 0xd6, 0xba, 0x6c, - 0x0b, 0x45, 0x9d, 0xf0, 0xfa, 0x5d, 0xe3, 0xf8, 0xbf, 0x94, 0x59, 0xc1, 0x50, 0x98, 0xcc, 0x44, 0xbd, 0xd9, 0x82, - 0x74, 0x16, 0x7a, 0x7b, 0xd7, 0xbf, 0x54, 0x9a, 0x03, 0xb6, 0x98, 0x31, 0x38, 0xd5, 0x83, 0x66, 0xf0, 0x12, 0x0a, - 0x84, 0xb9, 0x77, 0x86, 0xce, 0xa0, 0xfb, 0xd5, 0x09, 0xca, 0x44, 0x31, 0xe8, 0x59, 0x0a, 0x25, 0x6d, 0x42, 0x6a, - 0xdd, 0xef, 0x0d, 0x6e, 0x7d, 0xe8, 0xdf, 0xcc, 0x28, 0xa2, 0x51, 0xef, 0x9c, 0x24, 0xa0, 0xe8, 0x15, 0x07, 0x3a, - 0x51, 0xde, 0x6c, 0x89, 0x11, 0xeb, 0x78, 0x9c, 0xe4, 0xea, 0xe0, 0xf1, 0x4a, 0xc9, 0xf1, 0xaa, 0x10, 0x7a, 0x0e, - 0x60, 0x88, 0x23, 0x70, 0x2f, 0x87, 0x05, 0x74, 0x01, 0xcf, 0xf4, 0x8e, 0x7a, 0x36, 0x73, 0xb4, 0xfb, 0x7f, 0x97, - 0x7b, 0xd4, 0x5b, 0x3c, 0xdb, 0x24, 0x0e, 0x58, 0xd6, 0x34, 0x02, 0xdf, 0xfc, 0xf4, 0xae, 0xd6, 0x63, 0xc9, 0x9b, - 0x2d, 0x95, 0x39, 0xd8, 0x10, 0x5d, 0xa7, 0x45, 0xd2, 0xa7, 0x5c, 0x1d, 0xdb, 0x14, 0x50, 0xc3, 0xfd, 0xb4, 0x73, - 0x45, 0x78, 0x9c, 0xb0, 0x86, 0x73, 0x2a, 0x1c, 0x76, 0x70, 0xb4, 0x11, 0x46, 0x37, 0xe4, 0x18, 0x4b, 0xea, 0x20, - 0xbe, 0x1d, 0xe0, 0x13, 0x7c, 0xbf, 0x30, 0xca, 0x97, 0x0e, 0xf1, 0x47, 0x06, 0x8d, 0x0e, 0x72, 0x89, 0x95, 0x3c, - 0x61, 0xea, 0xaf, 0x95, 0xda, 0xca, 0x75, 0xb9, 0xb9, 0xb7, 0x57, 0xb7, 0x92, 0x59, 0x38, 0xc9, 0x28, 0x3e, 0x92, - 0x1e, 0xd5, 0x2b, 0xf9, 0xcf, 0xed, 0xc6, 0x20, 0x99, 0xb9, 0xbd, 0x7b, 0x27, 0x30, 0x76, 0xa8, 0x74, 0xa2, 0xe0, - 0x5f, 0x22, 0xe1, 0x67, 0xa3, 0x11, 0x29, 0x28, 0x2c, 0xb9, 0x0a, 0x55, 0x68, 0x9f, 0xb9, 0xe9, 0xa5, 0xa2, 0x72, - 0x8c, 0x51, 0x31, 0x9b, 0xf1, 0x8b, 0xa1, 0x1a, 0x23, 0xf5, 0xd3, 0x9c, 0x6d, 0xbf, 0xf5, 0x44, 0xaf, 0x45, 0x73, - 0x20, 0x09, 0x1a, 0x57, 0x02, 0x14, 0xe0, 0x10, 0x13, 0x8c, 0xc9, 0x5d, 0x62, 0xd0, 0x34, 0xc3, 0xf3, 0x14, 0xea, - 0x5a, 0x8d, 0x27, 0x95, 0x6f, 0x6d, 0x97, 0x95, 0x54, 0xb6, 0x13, 0xa3, 0x79, 0x27, 0x41, 0xe2, 0xa8, 0x71, 0x8a, - 0x82, 0x55, 0xf5, 0x0c, 0x29, 0xc3, 0x12, 0x20, 0xad, 0x38, 0x87, 0x6f, 0xcf, 0x43, 0x66, 0x17, 0x96, 0xd8, 0x2b, - 0xdd, 0x2c, 0x85, 0x08, 0x6e, 0x17, 0x15, 0x09, 0xb9, 0xbe, 0x65, 0x93, 0x2c, 0x74, 0xe9, 0x5b, 0x67, 0xe8, 0x12, - 0xd2, 0x87, 0x1c, 0xf5, 0xdb, 0xbd, 0x04, 0x9c, 0x20, 0x8c, 0x8d, 0x09, 0xd9, 0x7c, 0xd4, 0x0b, 0xf2, 0x28, 0x6f, - 0x05, 0x8d, 0xab, 0xcd, 0xd2, 0xfb, 0x9f, 0x30, 0x1a, 0xca, 0x65, 0x43, 0x26, 0xb3, 0xa2, 0x83, 0xe6, 0xab, 0x65, - 0x6c, 0x0e, 0x2a, 0xc8, 0x31, 0x27, 0x01, 0x7a, 0x5c, 0x81, 0xe7, 0x96, 0x45, 0xbd, 0x49, 0xf5, 0x67, 0xc5, 0x0b, - 0x5d, 0x83, 0xdd, 0xd7, 0x0e, 0x62, 0xc7, 0x26, 0x53, 0xbb, 0x58, 0x05, 0x4a, 0xe2, 0x88, 0x6e, 0x85, 0x3e, 0x85, - 0x2a, 0x77, 0xa4, 0x10, 0xc3, 0x3a, 0xc0, 0xc2, 0x59, 0xc9, 0x4c, 0xd8, 0x3e, 0xcc, 0xe7, 0x8f, 0x51, 0x6b, 0x01, - 0xd3, 0x43, 0x08, 0xf5, 0xdd, 0x1d, 0xee, 0x28, 0x3a, 0x3a, 0x93, 0xc9, 0x5d, 0x56, 0xc8, 0xa0, 0x5f, 0xf8, 0x58, - 0xc0, 0x05, 0x57, 0xe4, 0x92, 0xb1, 0xa0, 0xe9, 0x14, 0x4c, 0xcb, 0xd4, 0xb9, 0xfc, 0xdd, 0xfb, 0x98, 0x40, 0x2d, - 0x88, 0x45, 0xd3, 0x84, 0x13, 0xd4, 0xd0, 0x1d, 0x44, 0x6b, 0xda, 0x93, 0xc7, 0x8b, 0xec, 0x19, 0xc6, 0xca, 0x09, - 0xfe, 0xd4, 0xe5, 0xba, 0xfa, 0xf2, 0x5d, 0x90, 0x4a, 0xef, 0x8d, 0x4e, 0x4b, 0xd2, 0x3b, 0xca, 0x11, 0xd1, 0xa4, - 0xe3, 0x6f, 0x1f, 0x91, 0xb7, 0x20, 0x13, 0x1b, 0x3e, 0x5c, 0xd6, 0x9a, 0xf7, 0x5f, 0x51, 0xb0, 0x4a, 0x11, 0xce, - 0x7e, 0xa2, 0x49, 0x1c, 0xb2, 0x15, 0x21, 0xed, 0x8b, 0x60, 0xa4, 0xa3, 0x82, 0xd8, 0x8a, 0xed, 0x6a, 0x6d, 0xb9, - 0x87, 0x40, 0xc4, 0x39, 0xb8, 0x42, 0x66, 0x19, 0x9c, 0x63, 0xaf, 0x7e, 0x79, 0x80, 0xe0, 0xf2, 0x14, 0xf5, 0xbf, - 0x5e, 0x16, 0x7e, 0xf4, 0x70, 0xa0, 0x75, 0x64, 0x65, 0x65, 0x4e, 0xbd, 0x54, 0x1f, 0xcb, 0x3a, 0x1e, 0xad, 0xfa, - 0x9a, 0x7e, 0xa3, 0x94, 0x46, 0x9b, 0x41, 0x8b, 0xdb, 0x94, 0x95, 0x1a, 0xc3, 0x9f, 0x59, 0x2d, 0xea, 0xa1, 0xc2, - 0x1d, 0xae, 0x0d, 0xde, 0xb3, 0x77, 0x30, 0x91, 0x22, 0xef, 0xdb, 0x3f, 0x35, 0xb8, 0x21, 0x61, 0x3a, 0xe1, 0x90, - 0x3b, 0x70, 0x05, 0xd3, 0x93, 0x4e, 0xdd, 0x35, 0xc4, 0xd7, 0x22, 0xc9, 0x8e, 0xfe, 0x1b, 0x05, 0xcf, 0x17, 0x32, - 0xd6, 0x84, 0x8c, 0x6e, 0x0b, 0x6b, 0x11, 0x69, 0xa5, 0xc1, 0xc4, 0x18, 0xc5, 0x7c, 0x4a, 0x94, 0x88, 0x65, 0xb7, - 0x25, 0x23, 0xb1, 0xcf, 0xd6, 0x96, 0xbd, 0xd5, 0x4d, 0x4b, 0x82, 0x96, 0xa5, 0x20, 0x5e, 0x2e, 0xcf, 0x44, 0x15, - 0xd0, 0xb5, 0x71, 0x03, 0x22, 0x4e, 0xef, 0xac, 0xf6, 0x16, 0x04, 0xd0, 0x3e, 0xff, 0xfb, 0x4a, 0xe9, 0xe2, 0x56, - 0x85, 0x12, 0x82, 0x1f, 0xb2, 0x4c, 0x96, 0x40, 0x19, 0xe4, 0x63, 0xcb, 0x07, 0xf7, 0x15, 0x56, 0xeb, 0xbb, 0xf5, - 0x10, 0xb1, 0x79, 0x3e, 0x84, 0xb4, 0x83, 0xe1, 0x99, 0x02, 0x4f, 0xf6, 0x2f, 0xdb, 0x87, 0x0d, 0xd0, 0xba, 0xc9, - 0x50, 0x7e, 0x57, 0xaa, 0x89, 0x32, 0x82, 0x8f, 0x5f, 0xed, 0x70, 0x61, 0x43, 0xed, 0xc0, 0x68, 0x1a, 0x76, 0xcb, - 0x3f, 0x20, 0x56, 0x48, 0xe8, 0xea, 0x08, 0x60, 0xeb, 0x32, 0x26, 0x7c, 0xc9, 0xbe, 0x41, 0x18, 0x00, 0x89, 0xdf, - 0xfe, 0xaa, 0x1d, 0x9f, 0x98, 0xeb, 0xf2, 0xfb, 0xb6, 0xbd, 0x4a, 0x44, 0xef, 0x63, 0x27, 0x66, 0x3b, 0xf6, 0x01, - 0x2b, 0x1e, 0x56, 0x8d, 0xe8, 0xd8, 0xf3, 0xa1, 0x70, 0x9f, 0xe2, 0xd1, 0xd6, 0x21, 0xfa, 0x9d, 0x28, 0xb2, 0xc5, - 0x76, 0xc9, 0xfe, 0x42, 0x4b, 0xe7, 0xd3, 0x07, 0x9a, 0x41, 0xdd, 0x1e, 0x23, 0xaf, 0x22, 0x80, 0x78, 0x0c, 0x76, - 0xe1, 0xeb, 0x32, 0xef, 0x99, 0xbc, 0x02, 0xfc, 0x9c, 0x72, 0xf2, 0x97, 0xe7, 0x8b, 0x26, 0x22, 0xe8, 0xb3, 0x2e, - 0x49, 0x02, 0x22, 0xe2, 0x71, 0x3a, 0x3b, 0x36, 0x4d, 0x7a, 0x19, 0x39, 0x3c, 0x62, 0x33, 0x2b, 0xdf, 0xb1, 0xaa, - 0x8b, 0xb3, 0x5b, 0x3e, 0xda, 0x5f, 0xe8, 0x41, 0x67, 0x90, 0xa8, 0x5d, 0x9c, 0xc9, 0x68, 0x76, 0x64, 0x1a, 0x63, - 0x43, 0xb4, 0x97, 0x8a, 0x29, 0x19, 0x66, 0x39, 0x46, 0x1d, 0xd7, 0x46, 0x4e, 0x97, 0x93, 0x25, 0x0e, 0xc3, 0x12, - 0xe3, 0x7d, 0x1a, 0x10, 0xf4, 0x72, 0x05, 0x1d, 0xec, 0xe2, 0x5c, 0x6f, 0x87, 0x1c, 0x1a, 0x10, 0x97, 0x1a, 0xef, - 0xe2, 0x5c, 0xf7, 0xa0, 0xca, 0x53, 0x64, 0xc5, 0xc3, 0x9f, 0x52, 0xbf, 0x54, 0x8e, 0xf1, 0x9e, 0x81, 0xc4, 0xd8, - 0x6f, 0x6c, 0xcf, 0xfd, 0x26, 0x28, 0x66, 0x99, 0xa2, 0x91, 0x9e, 0x17, 0xee, 0xc1, 0x6c, 0x4f, 0xdb, 0xab, 0xd1, - 0x54, 0xc1, 0xcc, 0xa2, 0x13, 0xc0, 0xe6, 0x0f, 0xc4, 0x54, 0x45, 0x57, 0x3c, 0x52, 0x08, 0xc2, 0x70, 0xb5, 0xde, - 0x91, 0xed, 0xb3, 0x42, 0x68, 0xb9, 0x63, 0x26, 0x19, 0xf8, 0xb9, 0xf1, 0x61, 0xd6, 0x35, 0xbe, 0xa8, 0x27, 0x40, - 0x33, 0x71, 0xe5, 0xc3, 0xc7, 0xc9, 0x42, 0x61, 0x82, 0x92, 0xd1, 0x4f, 0xae, 0xa6, 0x5a, 0xd2, 0x9d, 0x74, 0xd8, - 0x9b, 0x2d, 0x5f, 0x27, 0x65, 0x1d, 0x76, 0x29, 0xfb, 0x58, 0xca, 0x03, 0xed, 0x76, 0x33, 0xdb, 0xc3, 0xdf, 0x70, - 0xf3, 0x01, 0xa0, 0x8b, 0x84, 0x95, 0x49, 0x6e, 0xd1, 0x80, 0x5f, 0x7c, 0x30, 0x38, 0x19, 0xc3, 0xf6, 0xe0, 0xc5, - 0xdc, 0x61, 0x9d, 0x63, 0xff, 0xd6, 0x91, 0x9b, 0x38, 0x0a, 0xa4, 0xe4, 0xab, 0x85, 0x45, 0x15, 0xa2, 0xc3, 0x40, - 0xe3, 0xaa, 0xcf, 0x13, 0xb0, 0x90, 0x33, 0xb5, 0x26, 0xd9, 0xfc, 0x53, 0x05, 0xc4, 0xf3, 0xd9, 0x72, 0x08, 0x24, - 0xc8, 0xb7, 0xb2, 0x5a, 0x16, 0xaf, 0x09, 0x27, 0xb0, 0x3d, 0x82, 0x45, 0x63, 0x77, 0x04, 0x00, 0x5a, 0xe8, 0x20, - 0xa4, 0xd4, 0x85, 0x0b, 0x65, 0x2f, 0xd7, 0xc8, 0x86, 0xa9, 0x6b, 0x81, 0x17, 0xdf, 0x4e, 0x38, 0xfa, 0xf7, 0x47, - 0x43, 0xb2, 0x8e, 0x00, 0x2e, 0x27, 0x78, 0x1f, 0x36, 0x8d, 0x3d, 0x03, 0xce, 0x48, 0xfb, 0xa2, 0x70, 0x45, 0x3f, - 0x0c, 0xac, 0x0b, 0xf1, 0x2c, 0x38, 0x47, 0x26, 0xbb, 0x12, 0xfa, 0x45, 0xd1, 0x0c, 0x09, 0x5e, 0x30, 0x8e, 0x6d, - 0xe0, 0x73, 0x07, 0xf4, 0xd3, 0x98, 0x8b, 0xb6, 0x05, 0x1e, 0x2b, 0xaa, 0xcc, 0x29, 0x87, 0x6e, 0x10, 0xad, 0xbd, - 0xfa, 0x5c, 0xea, 0x3b, 0x9c, 0x95, 0xce, 0x8a, 0x7b, 0x97, 0x55, 0x0f, 0x05, 0x9f, 0x20, 0xc7, 0xfb, 0x57, 0x14, - 0xfb, 0x9f, 0x36, 0xe2, 0x68, 0xc1, 0xa6, 0x00, 0x0c, 0x20, 0x21, 0xd3, 0x08, 0xdb, 0x3a, 0x09, 0x3a, 0x7e, 0x28, - 0x3d, 0x46, 0x1c, 0x4a, 0x5a, 0x61, 0x70, 0x98, 0xaa, 0x6f, 0x83, 0x0c, 0x29, 0x79, 0xb9, 0x94, 0x1e, 0x86, 0x18, - 0x39, 0x20, 0x95, 0xb9, 0xf2, 0x3d, 0x7b, 0x55, 0x3c, 0x51, 0xea, 0xc4, 0x07, 0x10, 0x8b, 0xa1, 0x47, 0x46, 0x7d, - 0x20, 0x53, 0x5d, 0x80, 0x26, 0x86, 0x90, 0x51, 0x02, 0x88, 0x8d, 0xa1, 0x11, 0x02, 0x25, 0xe4, 0xd8, 0xfa, 0xc5, - 0xac, 0x0a, 0x12, 0xa1, 0x88, 0x45, 0x4b, 0xb4, 0x38, 0x62, 0x14, 0x60, 0x86, 0x34, 0xd0, 0x63, 0xee, 0x9a, 0x0e, - 0x8c, 0x0b, 0x30, 0xa6, 0xe2, 0x1e, 0x40, 0x7e, 0x33, 0x86, 0xb1, 0x88, 0xe0, 0xe5, 0xae, 0x3c, 0x4f, 0x1a, 0x35, - 0x58, 0xc3, 0x5a, 0x34, 0x17, 0xab, 0xb7, 0x81, 0x99, 0x72, 0x0c, 0xc9, 0x55, 0xab, 0x52, 0xd8, 0xe9, 0xcd, 0x7e, - 0x1f, 0xf2, 0xb9, 0x83, 0xd0, 0xd6, 0xc1, 0x99, 0x25, 0x28, 0x33, 0x12, 0xdb, 0x98, 0x50, 0x40, 0x32, 0xd0, 0x81, - 0xd4, 0x15, 0x88, 0x90, 0x90, 0x64, 0x92, 0x84, 0xe6, 0x64, 0x8a, 0x44, 0x7c, 0x71, 0xc2, 0x5c, 0x1f, 0xc4, 0xc9, - 0x12, 0xd9, 0xbc, 0x6f, 0x97, 0xc0, 0xfc, 0x81, 0x91, 0x59, 0x91, 0xab, 0xaa, 0xa0, 0x01, 0x12, 0x09, 0xa3, 0xd5, - 0x09, 0x43, 0xe7, 0xf5, 0xd9, 0xdf, 0x07, 0x8c, 0x2d, 0x4c, 0xe8, 0x40, 0x30, 0x0c, 0x65, 0x51, 0xa8, 0xe4, 0x4f, - 0x0a, 0x1c, 0x56, 0x68, 0x78, 0x7f, 0x16, 0x7c, 0xf1, 0xd4, 0x62, 0x61, 0x15, 0x1e, 0x09, 0xb9, 0x1f, 0x6a, 0x89, - 0xb3, 0x02, 0x92, 0x13, 0x84, 0x56, 0xf7, 0xef, 0x7f, 0x77, 0x54, 0x12, 0xe6, 0x45, 0x8b, 0xd2, 0xab, 0x23, 0x6e, - 0x73, 0xb5, 0xc0, 0xd0, 0xa4, 0xd9, 0x21, 0xdf, 0x3e, 0x55, 0x22, 0x6e, 0x14, 0x5c, 0xee, 0x42, 0x2c, 0x01, 0x69, - 0x33, 0x18, 0x7c, 0x69, 0x3d, 0xa5, 0x1f, 0x20, 0xf4, 0x8d, 0x7b, 0x76, 0xfa, 0x38, 0x46, 0x32, 0x26, 0x17, 0xd6, - 0xcf, 0xac, 0x6a, 0x35, 0x71, 0x44, 0x42, 0xce, 0x59, 0xe8, 0x50, 0xec, 0xab, 0x61, 0x39, 0x73, 0xc5, 0xd9, 0xc3, - 0xc3, 0x68, 0x05, 0x24, 0x1d, 0x69, 0xb8, 0x21, 0xc7, 0xb3, 0x0f, 0x50, 0xe7, 0x51, 0x30, 0x92, 0x4a, 0xe6, 0xbd, - 0x62, 0x38, 0x6f, 0x88, 0xb6, 0xd4, 0xb3, 0xd6, 0x20, 0x70, 0x4e, 0x16, 0x49, 0xc9, 0x9b, 0x20, 0xb5, 0xf2, 0xf2, - 0x64, 0x1e, 0x31, 0xc5, 0xe9, 0x54, 0x59, 0x61, 0x74, 0x72, 0xd1, 0x73, 0x64, 0x94, 0x5d, 0xb0, 0xa1, 0x9a, 0x4f, - 0x4b, 0x53, 0xee, 0x2b, 0xac, 0x94, 0xae, 0xb4, 0xc0, 0x74, 0x24, 0xc6, 0xea, 0x66, 0x8e, 0xea, 0x81, 0x41, 0xc4, - 0x7a, 0xf9, 0x06, 0x91, 0x87, 0x34, 0xbf, 0x70, 0xa4, 0x22, 0x6d, 0x09, 0xcf, 0x4a, 0x3e, 0x60, 0x36, 0x03, 0xd2, - 0xca, 0xfb, 0x04, 0x5c, 0xf9, 0x4d, 0x81, 0x82, 0xe4, 0x8b, 0xf3, 0x04, 0xcd, 0x20, 0x7e, 0x1d, 0x64, 0xb3, 0xb1, - 0x11, 0xe3, 0xf9, 0xd6, 0xe0, 0xd5, 0x10, 0x39, 0x58, 0x1d, 0xfd, 0xba, 0x1b, 0xb0, 0x75, 0xb8, 0x4d, 0xa7, 0x67, - 0x5f, 0x6a, 0x81, 0x16, 0x83, 0xe3, 0xa9, 0x98, 0xe2, 0xa4, 0x7a, 0x44, 0x2c, 0x53, 0x61, 0x1a, 0x13, 0x5d, 0x21, - 0x6b, 0x6c, 0x29, 0xd8, 0x7c, 0xcb, 0x7b, 0x5e, 0x64, 0x48, 0xb8, 0x6b, 0x44, 0x17, 0xc3, 0x18, 0x04, 0x2f, 0x2f, - 0xa5, 0x73, 0x5f, 0x1b, 0x25, 0x56, 0xcc, 0x13, 0x1f, 0x5e, 0x37, 0x49, 0xf2, 0x82, 0xb4, 0x66, 0xcf, 0x6a, 0x2c, - 0x7f, 0x78, 0xf3, 0x83, 0xa9, 0x4a, 0xac, 0xd9, 0xc9, 0x4f, 0x52, 0xb6, 0xef, 0x87, 0xa6, 0x41, 0xde, 0x56, 0x2c, - 0x7e, 0x69, 0xf2, 0x0d, 0xa2, 0x0b, 0x46, 0xc9, 0x4e, 0x17, 0x8b, 0x75, 0x03, 0xf7, 0xeb, 0x25, 0xe8, 0xca, 0x0c, - 0x83, 0x76, 0xef, 0x6b, 0xdd, 0x2f, 0x8a, 0x48, 0x8f, 0xb1, 0x0f, 0x19, 0x29, 0x5a, 0x89, 0x5a, 0xcb, 0xfc, 0x6c, - 0x5b, 0xeb, 0x08, 0x09, 0x33, 0xd1, 0x4b, 0x73, 0xb4, 0x43, 0x22, 0x56, 0x33, 0x13, 0xa1, 0xc1, 0xba, 0x19, 0x79, - 0x57, 0x53, 0xfe, 0xb4, 0x84, 0x0e, 0x8f, 0xb5, 0xae, 0xda, 0xdc, 0xcb, 0x68, 0x3a, 0x23, 0xae, 0xe7, 0x69, 0xea, - 0x9a, 0xd2, 0xd3, 0xa0, 0xc3, 0x9d, 0x14, 0xb1, 0xc5, 0xad, 0xff, 0xc0, 0x4c, 0x8b, 0x42, 0x42, 0x35, 0x94, 0xb9, - 0xbd, 0xae, 0x1e, 0x4b, 0xd5, 0x53, 0xb2, 0xfb, 0x9e, 0xe8, 0x6b, 0xac, 0xd2, 0xbe, 0x46, 0xb2, 0x6a, 0x85, 0xc7, - 0xc6, 0xb8, 0x0e, 0x9e, 0xf5, 0x1b, 0xdc, 0x24, 0x8a, 0x10, 0xc3, 0xb8, 0xf4, 0x0b, 0x1f, 0xe1, 0x5c, 0xe0, 0xf5, - 0x30, 0x6d, 0xdd, 0x0e, 0xa9, 0xa6, 0x20, 0x8e, 0xdd, 0x16, 0xce, 0xd9, 0xad, 0x39, 0x78, 0xe8, 0x8e, 0xa3, 0xbc, - 0x50, 0x8f, 0xf3, 0x0e, 0x85, 0x76, 0x28, 0x69, 0x78, 0x5c, 0xb7, 0xa3, 0xc9, 0x83, 0x23, 0x9a, 0xb8, 0x5d, 0x6e, - 0x7f, 0x26, 0x94, 0x79, 0x1a, 0x20, 0xa2, 0x31, 0xfc, 0xfb, 0x92, 0x3d, 0x19, 0xd3, 0x09, 0x49, 0x64, 0x43, 0x66, - 0x1b, 0x30, 0xf6, 0x90, 0x48, 0x8f, 0xbf, 0x22, 0xf7, 0x6f, 0x8d, 0x82, 0xe3, 0xa5, 0xb8, 0xa1, 0xa4, 0x3f, 0x2c, - 0xc2, 0x4c, 0x27, 0x31, 0x4d, 0x3c, 0x90, 0xc5, 0x55, 0x00, 0x2e, 0xd3, 0xae, 0xb0, 0x40, 0x96, 0x0b, 0x2c, 0x90, - 0xb2, 0xfa, 0x1c, 0x25, 0x91, 0xb8, 0x47, 0x42, 0x76, 0x3a, 0x79, 0x2f, 0x8e, 0x71, 0xc1, 0x73, 0x35, 0x39, 0xba, - 0xe0, 0xc5, 0x4c, 0x10, 0xb5, 0x3b, 0x8d, 0xf4, 0x22, 0x34, 0xef, 0xe5, 0xea, 0x3a, 0xd2, 0xa7, 0xd0, 0x82, 0x0a, - 0xf5, 0x0b, 0x69, 0xbf, 0x7f, 0x9d, 0xc8, 0x80, 0xa3, 0x41, 0x93, 0x0d, 0x3b, 0x24, 0xac, 0x90, 0xd7, 0x2e, 0xbe, - 0x10, 0x3a, 0x22, 0x33, 0x7a, 0x94, 0x61, 0x7a, 0x99, 0x8f, 0xd1, 0xce, 0x5b, 0x39, 0x9a, 0x2e, 0x1c, 0xfc, 0xe7, - 0xb0, 0xb7, 0x40, 0x87, 0xab, 0xe3, 0x22, 0xdd, 0x4f, 0xce, 0x5c, 0xfc, 0x0f, 0xa6, 0xab, 0xae, 0x7d, 0x36, 0x13, - 0x5f, 0xc9, 0x63, 0x44, 0x7d, 0xd5, 0x0b, 0xa7, 0x34, 0x1b, 0xd5, 0x4c, 0x1f, 0x45, 0xe4, 0x79, 0xa8, 0x72, 0x5b, - 0x30, 0x9e, 0xd6, 0x60, 0xf8, 0xe8, 0x28, 0xe1, 0x10, 0x34, 0xc1, 0x99, 0xb9, 0x1f, 0x51, 0x65, 0x64, 0x09, 0xe3, - 0xc6, 0x02, 0xcb, 0x9b, 0xe9, 0x3c, 0x8e, 0x4b, 0xa1, 0xe5, 0x33, 0xc6, 0xdf, 0xdf, 0xa2, 0xcf, 0x4f, 0x85, 0xcd, - 0x12, 0x17, 0x3f, 0xe8, 0xc4, 0x51, 0x2f, 0x5c, 0x69, 0xeb, 0x14, 0xab, 0x52, 0xd9, 0x4d, 0xed, 0x7c, 0x6c, 0x5b, - 0x5e, 0x4a, 0xc6, 0xa7, 0x14, 0xe5, 0x24, 0xd7, 0x14, 0x8a, 0xc1, 0xc0, 0x1b, 0x59, 0xf5, 0xe7, 0x0b, 0x98, 0xc9, - 0x0d, 0x78, 0xa6, 0xaf, 0x63, 0xbd, 0x03, 0x3c, 0xd8, 0x73, 0x0b, 0x33, 0x57, 0x90, 0xc8, 0xe3, 0xf1, 0x1c, 0x8f, - 0x75, 0xc0, 0xf9, 0x83, 0xdc, 0x3b, 0x0a, 0xf8, 0x6e, 0x00, 0x62, 0x76, 0xde, 0x08, 0xf0, 0x0b, 0xec, 0x70, 0xb6, - 0xc4, 0x12, 0x54, 0x29, 0xd4, 0x82, 0x1d, 0x19, 0x7c, 0x96, 0x60, 0x35, 0x13, 0x70, 0x96, 0x20, 0x28, 0xca, 0x62, - 0xbe, 0x20, 0x28, 0x71, 0x14, 0x4a, 0x66, 0x2e, 0x3f, 0x35, 0x9b, 0xa2, 0x28, 0x12, 0xe1, 0xa7, 0x76, 0x70, 0x9e, - 0x11, 0x2e, 0xf1, 0xb5, 0xa2, 0xca, 0x07, 0x06, 0x5f, 0x10, 0x68, 0x80, 0xfe, 0xcd, 0x54, 0x44, 0xfb, 0x73, 0xd2, - 0x28, 0x29, 0xdc, 0xb3, 0xb0, 0x18, 0x67, 0x9d, 0x59, 0xd2, 0x6f, 0xb2, 0xcc, 0x6b, 0xd1, 0xcc, 0xaf, 0x6c, 0xc8, - 0x5a, 0xe7, 0xbb, 0x9f, 0xf7, 0x03, 0xa5, 0x9d, 0xf5, 0xcc, 0x92, 0x7d, 0xb4, 0x67, 0x9a, 0x36, 0x0b, 0x87, 0x9e, - 0xc5, 0xd5, 0x0d, 0x53, 0x10, 0x07, 0x5e, 0x9e, 0x46, 0x2a, 0x03, 0x7f, 0x2a, 0x0a, 0x38, 0x52, 0x4e, 0xf1, 0x5b, - 0x4a, 0x78, 0x37, 0xbf, 0x20, 0x8e, 0xdd, 0x5d, 0xfd, 0x0a, 0x90, 0xb5, 0x85, 0xd5, 0xc1, 0x4d, 0x8e, 0x9b, 0xa8, - 0x21, 0xca, 0xc1, 0xdb, 0x40, 0xbe, 0x34, 0x4f, 0x5a, 0xe2, 0xa8, 0x97, 0x45, 0xab, 0xcf, 0xd3, 0xdc, 0x10, 0xf8, - 0xa9, 0x0b, 0xc7, 0xe3, 0x3c, 0xfa, 0xe6, 0xd0, 0x34, 0xf2, 0x63, 0xd2, 0xf6, 0x80, 0x81, 0xa4, 0x99, 0x68, 0xe3, - 0x23, 0x5b, 0x4e, 0x77, 0x3b, 0x0b, 0xe9, 0x7a, 0x3d, 0x0d, 0xa5, 0xb0, 0x58, 0xb8, 0x70, 0x34, 0x66, 0x9f, 0xd0, - 0xe9, 0xd6, 0x6c, 0x48, 0x74, 0x07, 0xc3, 0x95, 0x18, 0xb9, 0x0e, 0xe3, 0x9c, 0xd9, 0x70, 0x84, 0x95, 0xea, 0xb1, - 0x37, 0x6e, 0x1b, 0x12, 0x3c, 0xa1, 0xe2, 0xc8, 0x03, 0x8f, 0xf0, 0x59, 0x1d, 0x74, 0x78, 0x98, 0x07, 0x2e, 0xf9, - 0x06, 0x73, 0x75, 0x04, 0x03, 0xe5, 0x08, 0x42, 0x11, 0xf9, 0xfe, 0x0e, 0x73, 0xe1, 0xb1, 0x7c, 0x83, 0x99, 0x5a, - 0x79, 0xe1, 0x73, 0xbd, 0xe4, 0x76, 0xc0, 0xf3, 0xf6, 0x13, 0x2f, 0xe9, 0x1a, 0xc1, 0xe1, 0x47, 0x7e, 0xd5, 0x62, - 0xfd, 0x75, 0x1f, 0xf3, 0xe7, 0x41, 0xaa, 0x4b, 0xb8, 0x2a, 0x0c, 0x80, 0x3f, 0xba, 0x32, 0xee, 0x06, 0x0c, 0xeb, - 0x23, 0x44, 0x8d, 0xf0, 0x88, 0xfd, 0xe1, 0xa9, 0x17, 0x00, 0xca, 0x9d, 0x9b, 0x81, 0xc8, 0x42, 0x34, 0x3f, 0x2f, - 0x57, 0xdb, 0xe6, 0x65, 0x68, 0x4b, 0x4b, 0x37, 0x8f, 0x13, 0x49, 0xd8, 0x4c, 0x9c, 0x5a, 0xa8, 0x5e, 0x11, 0x31, - 0x45, 0xcc, 0x02, 0xad, 0x97, 0xf1, 0x7b, 0x7c, 0x67, 0x08, 0xa3, 0x36, 0x6c, 0x84, 0xd7, 0xed, 0x68, 0x6d, 0xf0, - 0x7e, 0xbf, 0xd6, 0x46, 0x21, 0xd8, 0xb7, 0xf4, 0x0b, 0x14, 0x69, 0xd8, 0xd2, 0x8e, 0xff, 0x79, 0xc0, 0x17, 0xfd, - 0x43, 0x08, 0x9b, 0xc4, 0x06, 0x05, 0x85, 0x97, 0xda, 0x64, 0x6f, 0x03, 0x25, 0x4c, 0x62, 0xad, 0xd6, 0x13, 0xf0, - 0xa2, 0x0d, 0x20, 0x15, 0xba, 0x67, 0xcc, 0xaf, 0xc8, 0xe4, 0xf9, 0x13, 0xd2, 0xb2, 0x85, 0x71, 0xca, 0x27, 0xd1, - 0x8e, 0x04, 0x3b, 0x3f, 0x45, 0x91, 0xbc, 0xe2, 0xbb, 0x44, 0x92, 0xaf, 0x4f, 0xbb, 0xf9, 0xcb, 0xdd, 0x83, 0x26, - 0x85, 0x40, 0x07, 0x8f, 0xee, 0x08, 0x19, 0x6a, 0xb5, 0x8c, 0xea, 0xf0, 0x18, 0x8b, 0x4c, 0xcf, 0x1f, 0xce, 0xea, - 0x8b, 0x0c, 0x03, 0x27, 0x96, 0xc0, 0x28, 0x95, 0x5d, 0x6e, 0xd9, 0xd8, 0x9f, 0xf4, 0xde, 0x78, 0x89, 0x52, 0x75, - 0x3c, 0xc7, 0xad, 0x1a, 0xba, 0x43, 0x57, 0xc4, 0x1b, 0x3e, 0xf0, 0xd8, 0xbf, 0xba, 0x31, 0xa8, 0x63, 0x4d, 0x9b, - 0x08, 0x5e, 0x07, 0xfd, 0xcc, 0x14, 0x9c, 0x6c, 0x7c, 0x4a, 0x74, 0x0a, 0x83, 0x04, 0x0a, 0x66, 0x28, 0xf6, 0x99, - 0x96, 0x8f, 0x4b, 0xe9, 0xce, 0x5a, 0x2a, 0xea, 0xd8, 0x38, 0x33, 0xca, 0xfa, 0xe5, 0x72, 0x69, 0xe3, 0x6d, 0x04, - 0xf4, 0x92, 0x7b, 0x79, 0x7f, 0xc5, 0x49, 0xe3, 0x18, 0x91, 0x2c, 0x38, 0x1e, 0x1e, 0xc7, 0x1c, 0xf2, 0xc6, 0xad, - 0x05, 0x1d, 0x26, 0xb4, 0x06, 0x36, 0x3b, 0x67, 0x39, 0xe5, 0x6b, 0x11, 0xce, 0xb2, 0xcb, 0x6f, 0x36, 0x40, 0x04, - 0x84, 0x9e, 0x16, 0x91, 0x04, 0x3e, 0x2b, 0x90, 0x31, 0x47, 0x4e, 0x72, 0x64, 0x79, 0xad, 0xe4, 0x11, 0x48, 0x26, - 0x46, 0x8a, 0xb7, 0xe1, 0xa6, 0x9f, 0xa2, 0x4b, 0x76, 0xb0, 0x51, 0x37, 0x08, 0xa2, 0x04, 0x3b, 0xc0, 0x5f, 0xf8, - 0xf3, 0xa1, 0xef, 0xfc, 0xe9, 0xb7, 0x5b, 0x87, 0xff, 0x27, 0xb8, 0xb4, 0x8f, 0x18, 0x3b, 0xfd, 0x25, 0x56, 0x7d, - 0xf5, 0x7f, 0x73, 0xd7, 0xd0, 0x3a, 0xf0, 0xe1, 0x03, 0x17, 0x1e, 0x7f, 0x1b, 0x96, 0xd0, 0x6a, 0x6b, 0x77, 0x58, - 0x52, 0x88, 0x13, 0xe5, 0xc4, 0x8e, 0xea, 0x3d, 0x8a, 0xf6, 0xc5, 0xd3, 0xfb, 0x23, 0x01, 0xac, 0xbf, 0x7f, 0xe3, - 0x51, 0x69, 0xa4, 0xbb, 0x5f, 0x82, 0x4c, 0x6c, 0xad, 0x4d, 0x90, 0xab, 0xd4, 0x7e, 0x7e, 0xee, 0x5b, 0xeb, 0xa8, - 0xa5, 0xab, 0x6c, 0x70, 0x7f, 0xd1, 0x55, 0x7b, 0xb0, 0xc9, 0xf2, 0x61, 0xbb, 0xb9, 0xb5, 0x4f, 0x2b, 0x57, 0x19, - 0xe1, 0x43, 0x01, 0x02, 0xec, 0x54, 0x99, 0x9c, 0x3c, 0xe3, 0xb7, 0x52, 0xf0, 0x8e, 0xa5, 0x9e, 0xf6, 0x37, 0x9b, - 0xe0, 0xef, 0x0d, 0x6b, 0xbb, 0xab, 0x47, 0xeb, 0x03, 0x08, 0xca, 0xa5, 0xd7, 0x50, 0xc1, 0x21, 0xc4, 0x4b, 0x0a, - 0x12, 0x72, 0x18, 0xce, 0x5c, 0x74, 0x92, 0x43, 0x4c, 0x1b, 0x31, 0xac, 0xab, 0xb4, 0x55, 0x71, 0xe2, 0xb5, 0x3c, - 0xb0, 0x5b, 0x18, 0xb7, 0x60, 0x61, 0x58, 0x64, 0x30, 0xf2, 0x0c, 0xec, 0x70, 0x2e, 0x1e, 0x7a, 0x35, 0x0b, 0x5e, - 0x90, 0x26, 0x5c, 0x96, 0xfa, 0x7d, 0xb0, 0x38, 0x66, 0xf5, 0x55, 0x0b, 0x7e, 0xcd, 0xc1, 0xa9, 0x29, 0x6a, 0x43, - 0x7e, 0xb5, 0x6f, 0x66, 0x84, 0xcb, 0x0b, 0xb9, 0xc7, 0x42, 0x10, 0x2a, 0xdb, 0xb8, 0x65, 0xd2, 0xc1, 0xc9, 0x50, - 0xdf, 0xa7, 0x0d, 0x61, 0x84, 0x17, 0x04, 0x32, 0x4d, 0x51, 0xca, 0xf0, 0x5b, 0xb8, 0xaf, 0x1d, 0xca, 0x06, 0xb9, - 0x99, 0x0e, 0x23, 0xe1, 0x8a, 0xec, 0x38, 0xf0, 0x2c, 0xcd, 0xa7, 0x6a, 0x7f, 0x6c, 0x5d, 0x07, 0xfd, 0xce, 0x25, - 0x44, 0xed, 0x91, 0x9a, 0xf1, 0x31, 0x9b, 0x76, 0x0a, 0xfe, 0xe6, 0x73, 0x29, 0x36, 0x10, 0x1f, 0x69, 0xb9, 0x4b, - 0xa9, 0x89, 0x63, 0xb9, 0xb4, 0xca, 0x38, 0xd4, 0xd0, 0x29, 0x0b, 0x6d, 0x23, 0x97, 0x19, 0x44, 0xda, 0x2e, 0x4e, - 0x49, 0x95, 0x49, 0x1e, 0x8b, 0x13, 0x62, 0xc8, 0x42, 0xbf, 0xc0, 0xda, 0xfe, 0x72, 0xf3, 0x4b, 0x32, 0x54, 0x21, - 0x76, 0xee, 0x10, 0xfa, 0xb0, 0xc0, 0xe6, 0xa5, 0xb4, 0x14, 0x46, 0x15, 0xa6, 0xae, 0xda, 0xea, 0xb9, 0xa5, 0x6d, - 0x48, 0x32, 0x90, 0xcc, 0xb2, 0x84, 0x8f, 0xb2, 0x81, 0x41, 0x8e, 0xff, 0x6d, 0x00, 0xd9, 0xf6, 0x20, 0xd8, 0xde, - 0x32, 0x65, 0xa9, 0xef, 0x2d, 0x7e, 0x9a, 0x84, 0x4f, 0x4c, 0x08, 0x5c, 0x06, 0x5c, 0x75, 0xfe, 0x6c, 0x76, 0x8d, - 0xff, 0x10, 0x06, 0xfe, 0x1b, 0x6e, 0xf4, 0x0d, 0xbe, 0x4a, 0x3f, 0x77, 0xc9, 0xfd, 0xc8, 0xfb, 0x91, 0x3c, 0xdb, - 0x96, 0xc6, 0x4f, 0x5c, 0xac, 0x78, 0x53, 0x7e, 0x0a, 0x7f, 0x33, 0x9a, 0xef, 0xcb, 0xfa, 0xce, 0xb6, 0xd3, 0x47, - 0x60, 0x33, 0xd8, 0x23, 0x3b, 0x74, 0xd7, 0x47, 0xa3, 0x54, 0xcc, 0x1c, 0xf1, 0xed, 0xc3, 0x9f, 0xdb, 0xda, 0x2f, - 0xce, 0x86, 0xe8, 0x3a, 0x30, 0x85, 0xd3, 0xd7, 0x01, 0xca, 0x0e, 0x59, 0x62, 0xda, 0x81, 0x4a, 0x14, 0x1d, 0x74, - 0x66, 0x5d, 0x0a, 0xb0, 0x7c, 0xe3, 0xe8, 0x67, 0x0d, 0xae, 0x95, 0xa4, 0xc3, 0x50, 0x6b, 0x11, 0x9f, 0x4d, 0xa7, - 0xf7, 0xa3, 0x58, 0x51, 0xc0, 0x02, 0xe6, 0xeb, 0x04, 0x76, 0x91, 0xde, 0xbc, 0x3c, 0x92, 0xe0, 0x9c, 0x70, 0x38, - 0x72, 0x81, 0x00, 0x2a, 0xb4, 0x5d, 0x48, 0x13, 0x7e, 0x9d, 0x3b, 0xba, 0xb6, 0x9f, 0x90, 0x5a, 0xb2, 0x1c, 0xe8, - 0xa5, 0xfa, 0xbf, 0xee, 0xee, 0x7e, 0x51, 0x1e, 0x2f, 0xec, 0xed, 0x89, 0x70, 0xcb, 0xb3, 0xaf, 0xac, 0xb0, 0xea, - 0x15, 0xf7, 0xfb, 0x24, 0x13, 0xad, 0xdd, 0x5c, 0x1f, 0xac, 0x4e, 0xd4, 0x2a, 0x78, 0xe8, 0xab, 0xf4, 0x3f, 0x33, - 0xbd, 0xdc, 0x73, 0x53, 0x1e, 0x4a, 0x84, 0x03, 0x5f, 0x34, 0x34, 0x3e, 0x43, 0x35, 0x44, 0xf1, 0x58, 0x0d, 0x38, - 0x8c, 0x49, 0x73, 0xdc, 0x27, 0x58, 0xc9, 0xd4, 0x89, 0x51, 0xb5, 0x11, 0x05, 0x24, 0x98, 0x82, 0xce, 0xa5, 0x2d, - 0xa1, 0x40, 0x05, 0xcd, 0xa2, 0x84, 0x46, 0xdf, 0xf3, 0x61, 0x45, 0x1a, 0x1d, 0xdc, 0x13, 0xc8, 0x08, 0x82, 0xca, - 0xb2, 0xf9, 0xcd, 0x76, 0x35, 0x8a, 0xc2, 0xa9, 0xef, 0x13, 0x0a, 0xca, 0x7f, 0x9c, 0xf9, 0xd2, 0x66, 0xc7, 0xdd, - 0xa3, 0x81, 0x50, 0x54, 0xeb, 0x12, 0x2f, 0x5b, 0x6d, 0xe4, 0x26, 0x37, 0x45, 0xa4, 0x09, 0xc4, 0x1e, 0xfe, 0x04, - 0x4d, 0x52, 0xc4, 0x74, 0x11, 0x37, 0x97, 0xe6, 0xe2, 0xe0, 0x4a, 0xe9, 0xea, 0x81, 0xdb, 0xd0, 0xc8, 0xab, 0x89, - 0x5e, 0xed, 0xe2, 0x0f, 0x02, 0xd1, 0x09, 0x4b, 0x26, 0xf2, 0x8a, 0x81, 0x48, 0x82, 0x81, 0x02, 0x45, 0xdb, 0x82, - 0x29, 0x0a, 0xbd, 0x6e, 0xeb, 0xc5, 0x71, 0x7e, 0x21, 0x53, 0x11, 0x64, 0x2a, 0x6d, 0x6e, 0x80, 0xab, 0x9f, 0xb6, - 0xec, 0x07, 0x1a, 0xff, 0x93, 0x9c, 0x70, 0xd3, 0x43, 0xcf, 0x42, 0x7c, 0xea, 0x3e, 0xb6, 0xde, 0x55, 0xa0, 0x30, - 0xbd, 0x78, 0x11, 0x2d, 0x90, 0xa2, 0x6e, 0xcc, 0x89, 0x25, 0x9f, 0xab, 0x16, 0xdf, 0x57, 0xe5, 0x97, 0x54, 0x50, - 0x43, 0x40, 0x98, 0x09, 0x20, 0x2b, 0xb1, 0x92, 0xcd, 0x2b, 0x72, 0xee, 0x4b, 0xb6, 0x61, 0x27, 0x78, 0x53, 0x6b, - 0x6e, 0x77, 0x46, 0x8c, 0xe0, 0xfd, 0x10, 0x01, 0x21, 0xaa, 0x15, 0x99, 0x25, 0xbf, 0x2a, 0x45, 0x9b, 0x01, 0x0f, - 0xa1, 0x20, 0x2c, 0xce, 0x5e, 0x21, 0xf3, 0x58, 0x2c, 0xf4, 0x03, 0x72, 0x8d, 0xb8, 0x87, 0x43, 0x04, 0x60, 0xd8, - 0xef, 0xee, 0x11, 0x31, 0xd2, 0xe1, 0xc2, 0x44, 0x0c, 0x03, 0x48, 0xd8, 0x06, 0x2e, 0xb3, 0xf3, 0xf1, 0xbe, 0x7b, - 0xff, 0xc7, 0x18, 0xce, 0x0d, 0xd6, 0x4a, 0xb8, 0x75, 0x74, 0xd5, 0x09, 0xf2, 0xf2, 0x3e, 0xe2, 0xd3, 0xdc, 0x8e, - 0xa8, 0x97, 0x03, 0x51, 0x69, 0x35, 0x9e, 0x6d, 0x84, 0x87, 0x65, 0x0a, 0x8f, 0x7d, 0x2e, 0x28, 0x9d, 0x79, 0x09, - 0x2e, 0x01, 0xd5, 0x07, 0x19, 0x5f, 0x79, 0x23, 0xd1, 0xab, 0xcc, 0xc6, 0x9f, 0xc7, 0xf3, 0x3d, 0x6c, 0xd3, 0x45, - 0x1b, 0xd7, 0xd3, 0xe9, 0x1d, 0x4a, 0x32, 0xc1, 0xb4, 0xbb, 0x49, 0x36, 0xec, 0xfa, 0x89, 0xc9, 0x37, 0x2a, 0xe2, - 0x06, 0xa4, 0xf6, 0xdd, 0x38, 0xd0, 0x54, 0xb0, 0xde, 0x7c, 0x4a, 0xa2, 0x81, 0xe9, 0x11, 0xc9, 0xdc, 0xac, 0xd7, - 0xf6, 0x66, 0x0d, 0x01, 0x20, 0x05, 0x8b, 0x96, 0xe0, 0xbd, 0x2b, 0x67, 0x4d, 0x93, 0x12, 0x5b, 0x00, 0x31, 0xdd, - 0x40, 0xe2, 0x38, 0xa2, 0x5a, 0xe3, 0xee, 0x9b, 0xa5, 0x87, 0xf7, 0x3b, 0x62, 0xf7, 0xee, 0x48, 0x6a, 0x7a, 0xe5, - 0x84, 0xed, 0xde, 0x91, 0x53, 0xa3, 0x1c, 0x1f, 0xd5, 0xb3, 0x1b, 0xb6, 0xb4, 0x8e, 0xe5, 0xc9, 0x8c, 0x1e, 0x05, - 0xbe, 0x64, 0xde, 0xbb, 0x7a, 0x50, 0x92, 0x70, 0xf6, 0x0b, 0x01, 0xe2, 0x68, 0xfd, 0x4b, 0xad, 0xd2, 0xa5, 0xe6, - 0x94, 0xfb, 0xbd, 0x0d, 0xfb, 0xaa, 0xb0, 0x72, 0x49, 0x2d, 0x7a, 0x39, 0x99, 0xaa, 0x9e, 0xca, 0xd7, 0x5e, 0xcb, - 0x35, 0xce, 0x86, 0x1a, 0xda, 0x43, 0xef, 0x35, 0x4d, 0xd5, 0xb2, 0x15, 0xce, 0xa2, 0x98, 0xb6, 0x77, 0xd1, 0x9d, - 0x42, 0x63, 0x1f, 0x39, 0x91, 0x38, 0x61, 0x6e, 0xfd, 0x55, 0x1e, 0x89, 0x1d, 0x1e, 0xc1, 0x16, 0xbe, 0x91, 0x74, - 0x48, 0xca, 0x41, 0xc7, 0x09, 0xb8, 0xad, 0x0c, 0x4f, 0x33, 0x10, 0xb1, 0x5a, 0x44, 0x9a, 0xcc, 0x00, 0xc6, 0x31, - 0x45, 0x5c, 0xab, 0x60, 0xa8, 0x41, 0x72, 0xae, 0x06, 0xc1, 0x4c, 0xc7, 0x82, 0x9d, 0xf9, 0x28, 0x3f, 0x41, 0x5b, - 0x1b, 0xb3, 0xb0, 0xd0, 0xb3, 0x31, 0x35, 0xbb, 0x29, 0x01, 0xac, 0x11, 0x74, 0x7b, 0x49, 0x77, 0xcf, 0x0d, 0xc2, - 0xfb, 0xe5, 0xc8, 0xe5, 0x8c, 0xc1, 0x7a, 0xec, 0xa3, 0x6c, 0x71, 0xea, 0xc1, 0x83, 0x00, 0x33, 0x82, 0xc3, 0x56, - 0xb9, 0x81, 0xf6, 0x6c, 0xe8, 0x3f, 0xf0, 0x4d, 0x34, 0xfb, 0xa2, 0xc6, 0x82, 0x83, 0x33, 0xeb, 0xb3, 0x78, 0x57, - 0xc5, 0x04, 0x59, 0xc4, 0x90, 0x24, 0x67, 0x4d, 0x31, 0x37, 0xeb, 0x62, 0x3d, 0x83, 0x40, 0xb0, 0x7c, 0x85, 0xc9, - 0x00, 0xe1, 0x60, 0x76, 0xa3, 0x21, 0x26, 0xd6, 0x93, 0x77, 0xfd, 0x08, 0x80, 0xc0, 0x00, 0xdc, 0xc5, 0xb9, 0xd0, - 0x26, 0x3a, 0x80, 0x22, 0xbf, 0x07, 0x07, 0x40, 0x12, 0x98, 0xa1, 0x48, 0x50, 0xd0, 0xab, 0xd6, 0xbe, 0xe6, 0xc5, - 0x18, 0x0a, 0x2d, 0x24, 0x04, 0xc1, 0x56, 0xee, 0x92, 0x35, 0x2a, 0xb3, 0x75, 0xd0, 0x90, 0xf0, 0xed, 0x59, 0x51, - 0x49, 0x8a, 0x90, 0x5f, 0xe7, 0x81, 0xf4, 0x4f, 0x07, 0x34, 0xf6, 0x1c, 0x25, 0xa7, 0x9b, 0x4c, 0xcc, 0x1a, 0xe2, - 0xe5, 0x69, 0x3d, 0x5b, 0x84, 0x62, 0x0f, 0xdd, 0xa0, 0xcc, 0xc9, 0xd8, 0x89, 0x2f, 0xa8, 0x11, 0x49, 0xfd, 0xe3, - 0x14, 0xd5, 0x83, 0x7a, 0x14, 0x23, 0x93, 0x71, 0x3d, 0xa1, 0x96, 0xaf, 0xb5, 0x1b, 0x81, 0x36, 0x29, 0xcf, 0xb8, - 0xc9, 0xd8, 0x52, 0xbf, 0x54, 0xa8, 0x65, 0xa7, 0xa6, 0x14, 0xec, 0xe4, 0x3c, 0x2f, 0x38, 0x7a, 0x2a, 0x76, 0xc2, - 0x38, 0x08, 0xf6, 0xa7, 0xd3, 0x6e, 0x8d, 0xf7, 0x7c, 0x82, 0x78, 0xbc, 0xea, 0xdc, 0x3e, 0x64, 0x6a, 0xd5, 0xd4, - 0x14, 0x68, 0xc6, 0xd3, 0xf4, 0xfe, 0x3f, 0x80, 0x3e, 0x0f, 0xc1, 0x9e, 0xe9, 0xa3, 0x10, 0xb7, 0x83, 0x18, 0x7f, - 0xd0, 0xc2, 0x4f, 0xf8, 0x1a, 0x25, 0x5c, 0xff, 0x2d, 0x09, 0xd0, 0xf1, 0x83, 0x56, 0x82, 0x2d, 0x49, 0x9c, 0xce, - 0x45, 0xaa, 0x3b, 0xc7, 0x0c, 0xab, 0x20, 0x17, 0x44, 0x8e, 0xe7, 0x3a, 0x8d, 0xca, 0x42, 0x96, 0x22, 0xe1, 0xc6, - 0x2f, 0x7e, 0xcd, 0x96, 0x0a, 0x3f, 0x06, 0x0e, 0x02, 0x51, 0x01, 0x24, 0xec, 0xa7, 0x97, 0xda, 0x73, 0x66, 0xe7, - 0x01, 0x43, 0x16, 0x48, 0x4b, 0x1d, 0xfb, 0x0a, 0x9d, 0x04, 0x00, 0x44, 0xc7, 0xc4, 0x18, 0xc8, 0xab, 0x1d, 0x55, - 0x7f, 0x80, 0x43, 0xef, 0xa4, 0x63, 0x6d, 0xee, 0x26, 0x10, 0x45, 0x08, 0x08, 0x90, 0x58, 0x1b, 0x0a, 0x22, 0x6b, - 0x39, 0x88, 0xa0, 0x4a, 0xec, 0x04, 0x8e, 0xd2, 0x66, 0xc1, 0x8d, 0x78, 0x44, 0x1a, 0x01, 0xf4, 0x0a, 0x2e, 0xc4, - 0x8c, 0xc0, 0x28, 0xcb, 0x48, 0xe3, 0x17, 0x58, 0x68, 0x5c, 0x04, 0xc1, 0xe7, 0x94, 0xb5, 0xde, 0x83, 0x78, 0x3e, - 0xb7, 0x8a, 0xe6, 0x63, 0x42, 0x88, 0x35, 0x00, 0x6b, 0x28, 0xf3, 0xdf, 0xb2, 0x18, 0x30, 0x1a, 0x28, 0xd9, 0xde, - 0xe3, 0xcc, 0x54, 0x2f, 0x2d, 0x57, 0x55, 0x98, 0x32, 0x8f, 0xc8, 0xa5, 0xf3, 0xae, 0x3f, 0x85, 0xf5, 0xa2, 0x76, - 0x41, 0xd3, 0x84, 0xc7, 0xea, 0xa5, 0x7a, 0xd6, 0xc8, 0x0d, 0xc5, 0x7f, 0x52, 0x9a, 0x1b, 0xe3, 0xa8, 0xfc, 0x62, - 0x5a, 0xf5, 0xc9, 0xe8, 0xb0, 0xde, 0x45, 0x76, 0xa7, 0xa2, 0x02, 0xe0, 0xb4, 0x5b, 0x61, 0x9c, 0xd3, 0x2b, 0x7f, - 0xb5, 0xc3, 0x47, 0xab, 0xcc, 0xdc, 0xa2, 0x2e, 0xb3, 0x86, 0x82, 0xf2, 0xd1, 0x54, 0x7e, 0x87, 0xab, 0xbb, 0x3c, - 0x61, 0xf4, 0xa9, 0x2c, 0x8a, 0x53, 0x77, 0x0f, 0x47, 0xfe, 0x75, 0xd8, 0x12, 0x62, 0xa7, 0xba, 0xf5, 0x17, 0x17, - 0x1e, 0x4c, 0x7d, 0xe2, 0x15, 0x6e, 0xdc, 0x42, 0x9f, 0xb1, 0xd7, 0x8c, 0xa1, 0x13, 0x02, 0xc0, 0x3b, 0x4b, 0x14, - 0x65, 0x41, 0xf8, 0xf7, 0x47, 0x9b, 0xa7, 0x45, 0x34, 0x4f, 0xfa, 0x36, 0xde, 0x4e, 0x40, 0x53, 0x60, 0x83, 0x75, - 0x20, 0x30, 0x1f, 0xd0, 0xbf, 0x19, 0x6c, 0xa3, 0xc6, 0xf7, 0xad, 0x2e, 0x8a, 0x10, 0x5b, 0x18, 0x7c, 0x69, 0xfd, - 0xa5, 0x20, 0xb2, 0x3e, 0xa9, 0x01, 0x6d, 0x3f, 0x4d, 0xd6, 0x5d, 0x61, 0x28, 0x79, 0xda, 0xad, 0x87, 0x11, 0x3b, - 0x68, 0x96, 0xf4, 0x86, 0xc9, 0x1f, 0xd2, 0x41, 0xe1, 0x26, 0x26, 0x8b, 0x44, 0xf9, 0xbb, 0x1f, 0x53, 0x92, 0xdc, - 0xf5, 0x0e, 0x67, 0x29, 0xea, 0x2a, 0x4c, 0xfd, 0x59, 0x79, 0xbf, 0x52, 0xff, 0x96, 0xde, 0xd8, 0x42, 0xc3, 0x91, - 0xb5, 0x20, 0x91, 0xd3, 0x30, 0xe4, 0x5a, 0x1d, 0xce, 0x9c, 0xb8, 0xb5, 0xce, 0x76, 0x84, 0x04, 0x1e, 0x96, 0x9c, - 0x25, 0x4c, 0xd5, 0x9b, 0x5a, 0x10, 0x1c, 0x26, 0x82, 0xc2, 0x74, 0x51, 0x9c, 0x22, 0x61, 0xf1, 0x66, 0x87, 0x16, - 0xa7, 0xcb, 0x60, 0xe7, 0xab, 0xfd, 0x44, 0x85, 0x67, 0x6c, 0x16, 0x0b, 0x50, 0x2d, 0xa2, 0xfc, 0x78, 0x31, 0xc0, - 0xee, 0x9f, 0xf0, 0xb1, 0x74, 0x12, 0xb6, 0x1e, 0x74, 0x4d, 0x6a, 0xb9, 0x54, 0x6a, 0x54, 0x5b, 0xc6, 0x35, 0xd7, - 0x50, 0x71, 0xed, 0xf0, 0xd0, 0x76, 0xf8, 0xee, 0x83, 0xf7, 0x45, 0xe2, 0x19, 0x4c, 0xe5, 0x91, 0x43, 0x10, 0x2d, - 0x6e, 0x59, 0xb7, 0x3e, 0x0c, 0x35, 0x97, 0xa7, 0xb0, 0x8f, 0x86, 0x72, 0xba, 0x88, 0x97, 0x24, 0xdf, 0x41, 0x1d, - 0x48, 0x0f, 0x1d, 0x26, 0x7a, 0x7b, 0x5f, 0x35, 0xeb, 0x0e, 0x34, 0xdf, 0xf4, 0x88, 0x40, 0x9b, 0xbb, 0x6a, 0x31, - 0xaf, 0x98, 0xba, 0x44, 0xb7, 0xa4, 0x96, 0x20, 0xee, 0xba, 0x3c, 0x6e, 0x2d, 0x5f, 0x02, 0x29, 0xa5, 0x84, 0x43, - 0xcb, 0xa5, 0xe6, 0xae, 0xf7, 0x1d, 0x87, 0x84, 0xad, 0xd0, 0x92, 0x75, 0xeb, 0x70, 0x1b, 0x6b, 0xfd, 0x29, 0x30, - 0xa9, 0x7f, 0x69, 0x45, 0x38, 0x78, 0x75, 0xc1, 0xba, 0x2d, 0x3e, 0x78, 0x61, 0x5d, 0x83, 0xae, 0x3d, 0xac, 0x44, - 0x87, 0x1d, 0x56, 0xa1, 0xd5, 0x66, 0x2d, 0x71, 0xb5, 0x12, 0xe3, 0x1b, 0xfa, 0xc3, 0x05, 0x27, 0x96, 0x9d, 0x65, - 0x48, 0xe3, 0x91, 0x93, 0xde, 0x8a, 0x3c, 0x55, 0x64, 0xbf, 0x62, 0x46, 0xc5, 0x4f, 0xd7, 0x91, 0xd6, 0x0b, 0x38, - 0x23, 0x94, 0xbd, 0xfc, 0x80, 0x8d, 0x63, 0x0e, 0xb6, 0x65, 0xd6, 0xde, 0xbb, 0x90, 0x56, 0x62, 0x87, 0x08, 0x5e, - 0x71, 0x17, 0xc3, 0x03, 0xcd, 0x0a, 0xc8, 0x98, 0x82, 0x98, 0x50, 0xf0, 0xf7, 0xba, 0x22, 0x64, 0xec, 0xf0, 0xa4, - 0x73, 0x6c, 0xd9, 0xf1, 0x09, 0x0a, 0x70, 0x64, 0x19, 0x18, 0x8f, 0x51, 0xa5, 0xa2, 0x3d, 0x9d, 0xe1, 0x18, 0xd5, - 0x2c, 0xad, 0x98, 0x5f, 0xc5, 0x02, 0x59, 0x01, 0xbb, 0x71, 0xd6, 0xb2, 0xd7, 0x16, 0xb9, 0x44, 0xf1, 0x86, 0xec, - 0x4e, 0x15, 0x99, 0x85, 0xb1, 0x4e, 0x95, 0x2c, 0xb0, 0xf4, 0xb8, 0x26, 0x94, 0xf1, 0x3f, 0x4d, 0x09, 0xca, 0xb7, - 0xfb, 0x9a, 0x4e, 0x2a, 0x34, 0x0a, 0xd7, 0x64, 0x7d, 0x9a, 0x5f, 0xd1, 0x13, 0xb9, 0xc0, 0xba, 0x24, 0x09, 0xe3, - 0x06, 0x31, 0xaa, 0xda, 0x84, 0x80, 0x6e, 0x08, 0xc5, 0x9b, 0x82, 0xd0, 0x94, 0x21, 0xb4, 0x9c, 0xe4, 0xa8, 0x1e, - 0x70, 0x96, 0xc8, 0xcd, 0xc1, 0x6b, 0x04, 0x57, 0xd1, 0x0e, 0x52, 0x54, 0x61, 0xb8, 0x8b, 0x6a, 0x90, 0xe6, 0xda, - 0x23, 0xa5, 0xe0, 0xaf, 0x09, 0xd0, 0x01, 0x08, 0xc3, 0xca, 0xdf, 0xdc, 0xa8, 0xe0, 0x15, 0xca, 0x4a, 0xe9, 0x54, - 0x73, 0x98, 0x26, 0xa6, 0xa5, 0x53, 0x46, 0x3a, 0xe1, 0x07, 0xaf, 0x11, 0xe7, 0x82, 0xa0, 0xb6, 0xab, 0xc5, 0x6a, - 0x30, 0x4c, 0xea, 0xa4, 0x2b, 0x40, 0x3e, 0x6a, 0x1a, 0x4c, 0x68, 0xb7, 0x94, 0xe8, 0x45, 0xd8, 0x2b, 0xb0, 0x9c, - 0x76, 0xb3, 0x5d, 0x03, 0x88, 0xd5, 0x5a, 0xd8, 0x41, 0x06, 0xc6, 0x32, 0xfe, 0x08, 0xc8, 0x03, 0x9f, 0x3e, 0x2f, - 0xad, 0x78, 0x64, 0xbd, 0x72, 0xf8, 0xe1, 0xe3, 0xaf, 0x29, 0x18, 0x2c, 0x15, 0x0d, 0x39, 0xbd, 0xd7, 0xe7, 0xf4, - 0x9d, 0x6c, 0x30, 0xd6, 0xa2, 0x73, 0x10, 0xf9, 0x2e, 0xb4, 0x23, 0xdd, 0x95, 0x75, 0x99, 0x91, 0xed, 0xeb, 0x81, - 0x2c, 0xf4, 0x5c, 0x5f, 0x8a, 0x20, 0xd5, 0x82, 0xc2, 0xdf, 0x01, 0x8a, 0x4b, 0x43, 0x28, 0x0d, 0xe5, 0xa0, 0x8c, - 0x14, 0x8e, 0x32, 0x19, 0xee, 0x34, 0x90, 0x02, 0x32, 0x22, 0x10, 0xcc, 0x99, 0x65, 0xed, 0x2d, 0x16, 0xd8, 0x92, - 0x9d, 0xa9, 0x5b, 0xb5, 0x6b, 0x4c, 0x98, 0x97, 0x39, 0x34, 0x7a, 0xe0, 0xd4, 0x96, 0xd3, 0xa3, 0x68, 0xa9, 0x9e, - 0x4e, 0x86, 0xa2, 0x99, 0x95, 0xa4, 0xb3, 0x97, 0xcf, 0xab, 0x86, 0x56, 0x92, 0x7e, 0x67, 0xa1, 0x06, 0xa4, 0x38, - 0x81, 0x3f, 0xbe, 0x08, 0x21, 0x5f, 0x72, 0x1f, 0xee, 0xe9, 0x2f, 0x3b, 0x0b, 0x4e, 0x2f, 0x51, 0x83, 0x9a, 0xbf, - 0x2c, 0x9c, 0xe9, 0x8d, 0x29, 0x1d, 0x94, 0x38, 0x16, 0x84, 0x3d, 0xbc, 0x97, 0xbe, 0xa8, 0x46, 0xdb, 0x45, 0x45, - 0xc1, 0x74, 0x00, 0xa8, 0x68, 0x1a, 0x0e, 0x1d, 0xd7, 0x9a, 0xa4, 0xac, 0xa4, 0xe2, 0xda, 0xcd, 0x15, 0x9f, 0x3e, - 0x76, 0x8c, 0xd4, 0xba, 0x03, 0x93, 0x78, 0x00, 0xcb, 0x3f, 0x07, 0xde, 0x8f, 0x09, 0x20, 0x5c, 0x4a, 0x79, 0x7e, - 0x71, 0x36, 0xe8, 0xf1, 0xdb, 0xad, 0xb8, 0x17, 0xde, 0xab, 0x8e, 0x31, 0x22, 0x66, 0x0b, 0x21, 0x79, 0xc8, 0x96, - 0x48, 0x6c, 0x36, 0x37, 0x4e, 0xba, 0xdb, 0x1c, 0x75, 0x78, 0x7f, 0xf0, 0x7a, 0xc9, 0x3b, 0x76, 0xa7, 0x69, 0xf0, - 0x41, 0xab, 0x53, 0x23, 0xad, 0xe9, 0x3f, 0xf8, 0xb7, 0x72, 0x91, 0x4e, 0xea, 0x1a, 0x90, 0xe8, 0x7c, 0x09, 0x09, - 0xf6, 0x07, 0x49, 0x91, 0x15, 0x5d, 0x2a, 0x65, 0x1b, 0x15, 0xeb, 0x97, 0x66, 0x39, 0x0b, 0xd7, 0x9b, 0x92, 0x7e, - 0xd9, 0xa5, 0x9b, 0x9c, 0x81, 0x75, 0xc1, 0xaa, 0xec, 0x39, 0xc7, 0xe2, 0x19, 0x32, 0xb1, 0xb0, 0xd7, 0x25, 0xca, - 0x52, 0x17, 0x36, 0x90, 0x64, 0xc7, 0xf0, 0x96, 0xf1, 0xe8, 0x4f, 0x9b, 0xc3, 0xbb, 0x9f, 0xf6, 0xed, 0x83, 0xfc, - 0x79, 0x1d, 0xed, 0x0c, 0x0a, 0x71, 0x29, 0xe9, 0xc2, 0xc3, 0x45, 0x0d, 0x2e, 0x09, 0x2d, 0xbc, 0x2d, 0x21, 0x2e, - 0x1e, 0xc3, 0x79, 0xfb, 0x0e, 0x41, 0xad, 0xac, 0xd8, 0xde, 0x71, 0xc4, 0x42, 0x3a, 0xeb, 0x95, 0x00, 0xfa, 0x2d, - 0x95, 0xb5, 0xb8, 0x23, 0xa7, 0x05, 0x94, 0x44, 0xca, 0x2e, 0xd1, 0xd3, 0xd1, 0xa9, 0xad, 0x3d, 0x9b, 0x0f, 0x6b, - 0x4b, 0xd1, 0x36, 0x12, 0x55, 0x9c, 0x43, 0x1c, 0xa3, 0x61, 0x68, 0x73, 0x6d, 0x6d, 0x8b, 0x3a, 0xcc, 0x50, 0x1d, - 0x6b, 0x08, 0x9b, 0x6e, 0x29, 0xe6, 0x5f, 0xaa, 0x1d, 0x97, 0x6e, 0x0d, 0x86, 0x09, 0xc9, 0x83, 0xa0, 0x4c, 0xc2, - 0xa5, 0xbc, 0xbd, 0xf0, 0x21, 0xdd, 0xd7, 0xeb, 0x77, 0x28, 0xff, 0x6e, 0x41, 0x5b, 0x8b, 0x6f, 0x9a, 0xff, 0x20, - 0xff, 0x2f, 0x1b, 0x30, 0x34, 0xe6, 0xf1, 0xe1, 0x58, 0xd2, 0x46, 0x19, 0x2d, 0xe5, 0x14, 0x1e, 0x3b, 0xd3, 0xf4, - 0x12, 0x4b, 0x87, 0x70, 0x77, 0x27, 0x99, 0x05, 0x87, 0x2d, 0x9b, 0x03, 0x24, 0x28, 0xc1, 0xe4, 0xcd, 0xc5, 0x68, - 0xd3, 0x63, 0xba, 0xc2, 0xe1, 0xbb, 0x15, 0x49, 0x36, 0x7b, 0x8d, 0x8b, 0x18, 0x20, 0x3d, 0x57, 0x30, 0x81, 0x02, - 0xfe, 0x30, 0x43, 0x51, 0x77, 0xe3, 0x5a, 0x4a, 0x31, 0x65, 0x8d, 0x20, 0x98, 0xe5, 0x2d, 0x9e, 0x63, 0xc8, 0xb4, - 0xad, 0x9e, 0xbb, 0x4f, 0x7a, 0xc0, 0x80, 0x13, 0x39, 0xfb, 0xd5, 0x62, 0x43, 0xa8, 0x6a, 0xdd, 0xae, 0xbd, 0x26, - 0xba, 0x42, 0x24, 0x7a, 0x72, 0xd2, 0x69, 0x40, 0x6c, 0x8b, 0x30, 0xe4, 0x50, 0xc8, 0xf8, 0xb8, 0x15, 0x39, 0x93, - 0xf0, 0x19, 0xdf, 0xb2, 0x4b, 0x16, 0x77, 0xa2, 0x99, 0x63, 0xc8, 0x67, 0x26, 0x41, 0xc4, 0xe8, 0x5a, 0x2a, 0xe7, - 0x84, 0x14, 0x5d, 0xa9, 0x47, 0xdf, 0x0f, 0xc8, 0xd2, 0x48, 0x82, 0x38, 0x3a, 0x55, 0x63, 0x9e, 0xff, 0x9d, 0x59, - 0x44, 0x67, 0xf0, 0x0f, 0xe3, 0xcc, 0xb3, 0xaf, 0x88, 0x7d, 0x96, 0x70, 0x32, 0xe9, 0xd5, 0xd6, 0x7a, 0x18, 0x44, - 0x20, 0xe0, 0xf3, 0xdd, 0xe8, 0xcd, 0x46, 0x5b, 0x37, 0x68, 0xbc, 0xa3, 0x79, 0x3a, 0xec, 0xcf, 0xc8, 0xdd, 0xa0, - 0x99, 0xd6, 0x6a, 0x53, 0xe2, 0x33, 0x08, 0x9c, 0xcb, 0x48, 0x35, 0x67, 0x19, 0x98, 0x60, 0xbf, 0x5f, 0x6c, 0x7d, - 0x01, 0xd5, 0x99, 0x11, 0x48, 0xfd, 0xae, 0x7a, 0xa9, 0x55, 0x9a, 0x31, 0xa6, 0xd3, 0x45, 0x6d, 0xaf, 0x0d, 0x1c, - 0xf8, 0x3e, 0xd9, 0xc4, 0xa4, 0xad, 0x5e, 0xe2, 0x04, 0x45, 0x77, 0x68, 0xd1, 0xf9, 0x5e, 0x35, 0xd1, 0x54, 0x66, - 0xec, 0xc9, 0xb8, 0x90, 0xed, 0xeb, 0xed, 0x7e, 0x43, 0xe6, 0xe8, 0x5a, 0xc7, 0x48, 0xc9, 0x45, 0x7d, 0x8e, 0xb8, - 0xca, 0x90, 0x7f, 0x5e, 0xc8, 0x62, 0x47, 0x1c, 0x6e, 0x7f, 0x87, 0x87, 0xd5, 0xa2, 0x2e, 0x66, 0xc7, 0x81, 0x38, - 0x46, 0xfe, 0x21, 0x72, 0x7e, 0x14, 0xb0, 0x19, 0x7e, 0x9a, 0xe1, 0x33, 0x68, 0xb3, 0x37, 0xfb, 0xc9, 0x36, 0xbf, - 0xf5, 0xd8, 0xf5, 0xef, 0x1a, 0x5e, 0xf9, 0xc6, 0x2a, 0x1c, 0x76, 0xdf, 0x76, 0x62, 0xcc, 0xfb, 0xf3, 0xd3, 0xaf, - 0x35, 0x46, 0xde, 0x10, 0xb0, 0xd9, 0xc1, 0xfb, 0x38, 0x67, 0xbf, 0xa5, 0xc3, 0x42, 0x2f, 0x6a, 0x15, 0x90, 0x51, - 0xe7, 0x3e, 0x71, 0x7d, 0x0b, 0x90, 0x56, 0x68, 0xa1, 0xd5, 0xa3, 0x5b, 0x42, 0xf7, 0x12, 0x21, 0xeb, 0x9b, 0x4b, - 0xb1, 0xe9, 0xb4, 0x67, 0x4d, 0x25, 0x25, 0x4d, 0xf1, 0x96, 0x14, 0x8a, 0xdf, 0xcf, 0xa8, 0x93, 0x07, 0xb8, 0xcf, - 0xa7, 0x8d, 0x64, 0xa6, 0xee, 0x26, 0xeb, 0xf9, 0x93, 0xd9, 0x13, 0x4a, 0xdb, 0x30, 0x9a, 0x43, 0x7e, 0xd3, 0x68, - 0x40, 0x8f, 0x47, 0x8b, 0x89, 0xd8, 0x0f, 0x02, 0x14, 0x7c, 0x1a, 0x2a, 0xa0, 0x7a, 0xa0, 0xdf, 0xf6, 0xd7, 0x01, - 0x27, 0x15, 0x31, 0x06, 0x7b, 0x03, 0x50, 0x30, 0x44, 0xb6, 0x91, 0xc5, 0x7b, 0xa1, 0x43, 0xd1, 0x27, 0x09, 0x9d, - 0xe9, 0x85, 0x12, 0x91, 0xd0, 0x23, 0x88, 0xce, 0xe9, 0xae, 0xf8, 0xc6, 0xe6, 0xc3, 0xeb, 0x58, 0xec, 0x59, 0x26, - 0xdf, 0x61, 0xb3, 0xb2, 0x0e, 0xf5, 0x35, 0x93, 0x86, 0xee, 0x45, 0xfb, 0xa8, 0x71, 0xeb, 0x45, 0x42, 0xc7, 0x5f, - 0xce, 0xeb, 0x91, 0x55, 0x6f, 0x89, 0x18, 0xa6, 0x98, 0x79, 0xcf, 0xa2, 0xde, 0xba, 0x68, 0x09, 0xd7, 0xac, 0xab, - 0x0e, 0x82, 0xa6, 0xc4, 0xd3, 0x7a, 0x70, 0x9d, 0x0b, 0xb1, 0xf8, 0xc9, 0x24, 0x5a, 0x3f, 0xf9, 0x6d, 0xdc, 0xa0, - 0xe4, 0x5c, 0x68, 0xd0, 0x85, 0x02, 0xa1, 0xf7, 0xde, 0x7b, 0x9b, 0x8f, 0xf6, 0x36, 0x35, 0xfd, 0x85, 0x79, 0xf1, - 0x47, 0x72, 0xd6, 0x6f, 0x76, 0x39, 0x70, 0x10, 0x4a, 0x9c, 0x30, 0x22, 0x5c, 0xd8, 0x34, 0x97, 0xbc, 0x94, 0x59, - 0xb9, 0x70, 0x86, 0x03, 0xd1, 0x19, 0xf1, 0x0d, 0x3f, 0xd8, 0xb6, 0x40, 0x20, 0x6e, 0xb5, 0x4c, 0x14, 0xcf, 0x88, - 0x38, 0x91, 0x65, 0x0e, 0x93, 0x9a, 0xe6, 0x72, 0xa6, 0x15, 0xbb, 0x6d, 0x05, 0x8d, 0x6f, 0x8c, 0x73, 0x2c, 0x81, - 0xde, 0xac, 0xd0, 0xce, 0xa5, 0x92, 0x8f, 0xfd, 0x8e, 0xaa, 0x9d, 0xeb, 0x2f, 0xaf, 0x65, 0x5e, 0xee, 0x3c, 0xbb, - 0x36, 0xcd, 0xcb, 0x35, 0x86, 0xce, 0x40, 0x66, 0x47, 0x75, 0x95, 0xa9, 0xbb, 0xd8, 0xe0, 0x8e, 0x42, 0x75, 0xb5, - 0x20, 0x1c, 0x80, 0x22, 0x9a, 0xe6, 0x98, 0x1b, 0xcc, 0xa2, 0xaf, 0xae, 0xf0, 0x4e, 0x07, 0x6d, 0xb5, 0xb4, 0x01, - 0x25, 0x20, 0x9c, 0x74, 0xd1, 0x61, 0x89, 0x07, 0x77, 0xa7, 0xee, 0x54, 0xd2, 0x60, 0x5c, 0x2c, 0xce, 0xc3, 0xb3, - 0x28, 0xee, 0x0a, 0xd3, 0xcc, 0x68, 0xf4, 0x03, 0x4d, 0xb4, 0xe7, 0x9b, 0xa5, 0xc4, 0x92, 0x0b, 0x76, 0xb9, 0xc7, - 0xf6, 0x03, 0x45, 0xe2, 0xa5, 0x3c, 0x56, 0x3a, 0xa5, 0xc4, 0x4e, 0x4d, 0x3b, 0x2b, 0xd3, 0x1c, 0x7a, 0x96, 0x65, - 0xe2, 0xb9, 0xf4, 0x3b, 0xaa, 0x67, 0x5b, 0x66, 0x7d, 0x53, 0xb8, 0xdb, 0x3b, 0x91, 0x12, 0x3f, 0x38, 0xd6, 0xf0, - 0xb6, 0xe8, 0x76, 0x9a, 0xbe, 0x2d, 0xdc, 0xfa, 0x05, 0x63, 0x0f, 0x8b, 0x55, 0xac, 0xbe, 0x28, 0x8e, 0x26, 0x14, - 0xd8, 0xea, 0xdf, 0xe4, 0x24, 0x4d, 0xdc, 0x4a, 0xe3, 0xaf, 0x69, 0x09, 0x53, 0x75, 0xaa, 0x7b, 0x2f, 0xb1, 0x8a, - 0xb0, 0x70, 0xff, 0x7d, 0xf5, 0x70, 0x28, 0x64, 0xb6, 0x79, 0xd6, 0x3c, 0x42, 0xba, 0x92, 0x7b, 0xc8, 0xa7, 0x4a, - 0xa6, 0xe6, 0x93, 0x93, 0xec, 0x86, 0xbb, 0x56, 0xab, 0x56, 0xc2, 0x9b, 0x66, 0xab, 0xc3, 0x75, 0xae, 0xd8, 0x68, - 0x99, 0x4d, 0x6a, 0xbb, 0x82, 0xe9, 0xdc, 0x3a, 0xf1, 0x38, 0x44, 0x22, 0x94, 0xb1, 0xbb, 0xbd, 0x51, 0x07, 0x17, - 0xb0, 0x29, 0xc1, 0x5d, 0x29, 0x38, 0x37, 0xd9, 0xe0, 0x2e, 0x88, 0xd4, 0x28, 0xae, 0x74, 0xdc, 0xdb, 0x86, 0x48, - 0xc1, 0x4e, 0x7a, 0xa4, 0x88, 0xc5, 0x69, 0xba, 0xf0, 0x34, 0xbe, 0xf2, 0x66, 0xd7, 0x34, 0x53, 0xdf, 0xa1, 0x46, - 0x8e, 0x68, 0x54, 0xee, 0x65, 0x48, 0x4c, 0x81, 0x87, 0x56, 0xe3, 0x59, 0xaa, 0x42, 0x6e, 0x30, 0xa3, 0x5b, 0xae, - 0xdb, 0xfd, 0xe2, 0xe3, 0x71, 0x39, 0x13, 0xd1, 0x85, 0xf1, 0x95, 0x1a, 0x92, 0x95, 0xec, 0x27, 0x22, 0x2f, 0x38, - 0xa6, 0xb3, 0x37, 0x45, 0x02, 0x6e, 0xe9, 0x8d, 0x8b, 0xb4, 0xa1, 0x5c, 0xcb, 0x06, 0x9d, 0x26, 0x39, 0x15, 0x54, - 0x88, 0x99, 0xb1, 0x66, 0xf1, 0xbe, 0x04, 0x09, 0x87, 0x3d, 0x85, 0x03, 0xd9, 0xd4, 0xcc, 0x6d, 0x87, 0x32, 0xd7, - 0xa1, 0x1a, 0x47, 0x62, 0xa3, 0x72, 0x08, 0x8e, 0xce, 0xdc, 0xee, 0xb1, 0xb0, 0xae, 0x60, 0x4e, 0x15, 0x59, 0x1e, - 0x9c, 0xae, 0xf6, 0x5f, 0xb8, 0x23, 0xfa, 0x62, 0x20, 0xfa, 0x9d, 0x56, 0x4d, 0xb4, 0xc0, 0x43, 0x8b, 0xeb, 0xda, - 0x42, 0x63, 0x0a, 0xe2, 0x80, 0xf4, 0x66, 0x82, 0xa2, 0xe1, 0x93, 0x66, 0x98, 0x83, 0x9e, 0xea, 0x9b, 0x9f, 0x3b, - 0x75, 0xf6, 0x65, 0x9a, 0x5e, 0x18, 0x66, 0x97, 0x06, 0xee, 0x8c, 0xa3, 0xa6, 0x18, 0x36, 0x5f, 0x8c, 0xbe, 0x89, - 0x5c, 0x9e, 0x7b, 0x56, 0x33, 0xc1, 0x34, 0x1d, 0x73, 0xe4, 0xbf, 0xc6, 0xf3, 0x7e, 0xc1, 0x71, 0x8c, 0x4a, 0x2f, - 0xbf, 0x28, 0x73, 0xa6, 0x25, 0x1b, 0xef, 0xab, 0x0b, 0xb8, 0x9e, 0x8c, 0x72, 0x24, 0x1e, 0x96, 0x59, 0x2c, 0x3f, - 0x80, 0x6f, 0x46, 0x2e, 0x41, 0x1b, 0xbb, 0x97, 0x89, 0x01, 0xc0, 0xb2, 0x5d, 0x73, 0x52, 0xbb, 0x46, 0xbe, 0x0a, - 0xb5, 0x55, 0xd7, 0xee, 0x24, 0xf3, 0x95, 0x08, 0xf6, 0x55, 0xfa, 0xe3, 0xa7, 0xa8, 0x07, 0xb5, 0xb7, 0x43, 0x92, - 0xab, 0x4d, 0xc2, 0xbe, 0x5f, 0x56, 0xa7, 0x27, 0xde, 0xbf, 0xc2, 0xe3, 0xe0, 0x02, 0x36, 0x3d, 0xf4, 0xf5, 0xb6, - 0x19, 0x89, 0x51, 0x77, 0x0d, 0xfe, 0xa0, 0xea, 0x21, 0x99, 0x1e, 0x74, 0x92, 0x47, 0x22, 0x30, 0xeb, 0xa9, 0x8e, - 0x89, 0xfc, 0x93, 0xf0, 0x73, 0xb5, 0xe7, 0xff, 0xf2, 0xf5, 0xd2, 0xcc, 0x9e, 0x21, 0xbc, 0x3b, 0xbc, 0xf9, 0xaa, - 0xd0, 0x75, 0xc6, 0xe5, 0xb1, 0x08, 0xe7, 0xce, 0xdf, 0x03, 0x70, 0xe5, 0x75, 0x79, 0xbb, 0x98, 0xef, 0x38, 0xed, - 0x2e, 0x6d, 0xde, 0xad, 0xa3, 0x86, 0x9f, 0x7f, 0xb0, 0x8d, 0x8a, 0x1f, 0xa9, 0x22, 0xfa, 0x75, 0x93, 0x05, 0x45, - 0x20, 0xe4, 0xe9, 0xeb, 0x84, 0x18, 0xff, 0x0c, 0x68, 0xfa, 0xa6, 0x50, 0xd9, 0x7f, 0xc3, 0x15, 0xa6, 0x0e, 0xe1, - 0x8f, 0xcc, 0xea, 0x60, 0x40, 0x73, 0x5b, 0xb8, 0x27, 0xfd, 0x17, 0x88, 0x35, 0x77, 0x10, 0xe0, 0x44, 0x91, 0xa4, - 0xe2, 0x87, 0x3e, 0xbc, 0x82, 0x26, 0xf7, 0x89, 0x14, 0xd4, 0x0c, 0xc5, 0x6d, 0x1b, 0xb8, 0x59, 0x0b, 0xca, 0x47, - 0x87, 0xa8, 0x73, 0xf4, 0x88, 0xdd, 0x5f, 0xda, 0x9d, 0xc9, 0xc3, 0x37, 0x94, 0xac, 0x89, 0x50, 0x31, 0x98, 0x50, - 0xfe, 0x5c, 0xf7, 0x4b, 0xde, 0xb3, 0xf2, 0x95, 0xb1, 0x28, 0xb8, 0xd8, 0x1b, 0x54, 0xfd, 0x00, 0x16, 0xd0, 0x59, - 0x24, 0xa0, 0x62, 0xb7, 0x13, 0xd6, 0xa9, 0xc6, 0xf1, 0x93, 0x58, 0x36, 0xf1, 0xc3, 0xf2, 0x0d, 0xff, 0xa5, 0x21, - 0x24, 0xa1, 0x88, 0x39, 0xa9, 0xc3, 0x60, 0x47, 0x2c, 0x6e, 0x63, 0x36, 0x0f, 0xa5, 0xe6, 0x61, 0x39, 0x71, 0xde, - 0x41, 0x0b, 0x10, 0x97, 0xa3, 0xee, 0xaa, 0xb5, 0x4b, 0xa7, 0x6b, 0x1d, 0x86, 0x93, 0xd8, 0x29, 0x56, 0x78, 0x18, - 0x5b, 0x8f, 0x1c, 0x23, 0xfc, 0x77, 0x20, 0x8f, 0x2f, 0x69, 0x7e, 0x78, 0x7b, 0x47, 0x83, 0x24, 0x1a, 0x2b, 0x15, - 0xa9, 0x78, 0x4a, 0x0f, 0x2b, 0x92, 0x21, 0x4d, 0x24, 0x7a, 0x78, 0x2f, 0xdf, 0xd2, 0x78, 0x58, 0xa5, 0x62, 0x43, - 0xc7, 0xcd, 0x56, 0x07, 0x92, 0x8f, 0xb2, 0xdd, 0x5f, 0x2f, 0xbd, 0x15, 0x9a, 0x75, 0x0a, 0x9b, 0x97, 0x1e, 0xb7, - 0xd8, 0xbb, 0x67, 0x31, 0xf5, 0x53, 0xa0, 0xc6, 0x91, 0x1c, 0x88, 0x89, 0xb1, 0xa9, 0x80, 0x3c, 0xf3, 0xe4, 0xe4, - 0xfd, 0xe0, 0xf5, 0x87, 0x63, 0x1f, 0x4f, 0xa4, 0x7c, 0xcc, 0xce, 0x70, 0xcf, 0xa7, 0x5e, 0x7e, 0xa6, 0x59, 0x1e, - 0x88, 0x9d, 0x8e, 0xe2, 0x21, 0x1f, 0xdd, 0x89, 0x50, 0x23, 0x2c, 0x27, 0x6b, 0xd5, 0x4a, 0x6b, 0x0c, 0x6a, 0x85, - 0x32, 0x97, 0xfb, 0x58, 0xdc, 0xda, 0xfd, 0x68, 0x93, 0xef, 0x7e, 0xa6, 0x88, 0xe7, 0x24, 0x02, 0xb9, 0xfe, 0x61, - 0x90, 0x96, 0x82, 0x79, 0x69, 0xa4, 0x95, 0xfa, 0x13, 0x4a, 0x39, 0xf0, 0x10, 0xf0, 0x25, 0x11, 0x97, 0x86, 0xb6, - 0xfe, 0x07, 0x4c, 0x5e, 0xd7, 0xbd, 0x6f, 0x25, 0xce, 0x9a, 0x70, 0x6e, 0x89, 0x7b, 0xac, 0xe5, 0x27, 0xb5, 0x24, - 0x0f, 0x0a, 0xa3, 0xbd, 0x9d, 0x1e, 0x1a, 0xa6, 0xc5, 0x2b, 0x16, 0xc5, 0x27, 0x7d, 0x2a, 0xbf, 0x07, 0xb5, 0xeb, - 0x2c, 0x75, 0xd9, 0x0b, 0xe5, 0x4c, 0xa9, 0xce, 0x0a, 0xbf, 0x76, 0x18, 0x5a, 0xe9, 0x48, 0x9a, 0x25, 0xce, 0xd5, - 0x7b, 0xec, 0x26, 0x4e, 0xb8, 0x21, 0x0d, 0x14, 0xa8, 0x64, 0x36, 0x1c, 0xd1, 0x53, 0x18, 0xdb, 0xfa, 0x32, 0xc3, - 0xed, 0x87, 0x32, 0xee, 0xe0, 0x68, 0xb2, 0x9a, 0x22, 0x5f, 0x27, 0x45, 0x2c, 0x14, 0x49, 0xd8, 0x85, 0x4b, 0x3b, - 0xbf, 0xc1, 0x5a, 0x69, 0x7e, 0x31, 0x5e, 0x30, 0xde, 0x65, 0x5d, 0xc9, 0x87, 0xcf, 0xba, 0x3b, 0x47, 0x04, 0xc8, - 0xa3, 0x9c, 0xd4, 0x3c, 0x82, 0xdb, 0x84, 0xa8, 0xb7, 0xb7, 0x3d, 0xb9, 0xe1, 0xcc, 0xb6, 0x45, 0x8b, 0x55, 0x2f, - 0x57, 0xb2, 0xdf, 0x9e, 0x95, 0x85, 0x82, 0xec, 0x6e, 0xe0, 0xc8, 0x9d, 0xe9, 0xc4, 0x6f, 0x18, 0x48, 0xef, 0x41, - 0x2d, 0x38, 0xba, 0x6e, 0x01, 0xa8, 0x35, 0xb4, 0x91, 0x4e, 0x5f, 0x23, 0xdb, 0xc8, 0xb8, 0xbc, 0x77, 0x1c, 0x41, - 0x71, 0xc0, 0xf8, 0xfa, 0xde, 0x31, 0x9d, 0x96, 0x80, 0xa4, 0x8f, 0x98, 0x0f, 0x03, 0x8c, 0x82, 0x18, 0x03, 0xd5, - 0xea, 0xf1, 0x01, 0x4f, 0x40, 0xc4, 0x91, 0xad, 0x0e, 0x6e, 0xdc, 0x20, 0x6f, 0x1d, 0x19, 0x07, 0x9f, 0x90, 0x6e, - 0x28, 0x61, 0x30, 0x5e, 0xfe, 0xc8, 0x40, 0x75, 0xa1, 0x8e, 0x0d, 0xae, 0x6d, 0x14, 0x34, 0xce, 0x0c, 0x10, 0x08, - 0x3e, 0xbd, 0x5d, 0xe9, 0xaf, 0xe3, 0x0f, 0x3a, 0xab, 0x37, 0x05, 0xa9, 0x95, 0xd3, 0xa3, 0x36, 0x5b, 0xe8, 0x2a, - 0xa0, 0x70, 0xa6, 0x7a, 0xc2, 0x80, 0xeb, 0x0f, 0x1b, 0x06, 0xe6, 0x3d, 0x27, 0x94, 0xd9, 0x1c, 0x09, 0x7f, 0x49, - 0xb3, 0x6f, 0xd6, 0x30, 0xcf, 0xe5, 0xd8, 0x83, 0x1d, 0x02, 0xb9, 0x7a, 0x18, 0xfb, 0x2d, 0xb6, 0x4d, 0x10, 0xe6, - 0xb0, 0xfc, 0xf8, 0x9f, 0x0a, 0xb5, 0x15, 0x4a, 0xed, 0xcd, 0x8f, 0x1c, 0xd6, 0xce, 0x73, 0x79, 0xfc, 0x4f, 0x28, - 0xf2, 0xd9, 0x3c, 0xe4, 0x79, 0xb2, 0xd8, 0x36, 0x88, 0x3f, 0x3d, 0xb2, 0x77, 0x36, 0xbb, 0xd6, 0x3e, 0xc8, 0xcf, - 0x60, 0x97, 0x7f, 0x0f, 0x09, 0xd5, 0xb0, 0x65, 0x05, 0x3f, 0x8c, 0x47, 0x04, 0x80, 0x85, 0x5e, 0xbf, 0xd9, 0x37, - 0xe4, 0x66, 0x1f, 0x90, 0x19, 0xf4, 0x39, 0xa2, 0x91, 0x67, 0xc6, 0x35, 0xec, 0xcc, 0x73, 0x3e, 0xf7, 0x0c, 0xe7, - 0x07, 0xca, 0x7a, 0xca, 0x9c, 0xe7, 0x25, 0x1b, 0xf7, 0xb6, 0x70, 0x06, 0xba, 0xd5, 0x8c, 0x5d, 0xd8, 0x82, 0xe5, - 0x3b, 0x6b, 0xc1, 0xa9, 0x1b, 0x30, 0x7b, 0x7b, 0xee, 0x4f, 0x74, 0xe0, 0xcf, 0x50, 0xde, 0xc9, 0xa8, 0xd5, 0x6f, - 0xbe, 0x75, 0x3b, 0x8d, 0x01, 0x6f, 0x84, 0xa7, 0x8a, 0xea, 0xcc, 0x39, 0x7b, 0x0a, 0x72, 0x21, 0xfe, 0xa2, 0x1b, - 0x7c, 0x42, 0xb7, 0x2a, 0x0a, 0x01, 0x5f, 0xda, 0x62, 0x44, 0xc8, 0x3a, 0xb4, 0xa4, 0x94, 0x27, 0x6d, 0x3e, 0x51, - 0x73, 0xa7, 0xe8, 0x34, 0xb7, 0x32, 0x3f, 0x9c, 0x39, 0x81, 0x0d, 0x02, 0x49, 0x48, 0x11, 0xc2, 0x3f, 0xc5, 0x8e, - 0x7b, 0x67, 0x6c, 0xb9, 0x91, 0xd0, 0xa0, 0x5d, 0x94, 0x8a, 0x18, 0x1f, 0x95, 0x4e, 0x23, 0xae, 0x7b, 0x8f, 0xf0, - 0x0f, 0xf6, 0x3f, 0xd3, 0xa8, 0x4c, 0xff, 0x9d, 0x46, 0x61, 0xfa, 0xcf, 0x69, 0x08, 0xa6, 0xff, 0x9e, 0x06, 0xbb, - 0x4b, 0xad, 0x0e, 0xec, 0xab, 0x23, 0xfb, 0xea, 0xce, 0x1e, 0xa7, 0xd9, 0x1e, 0x5a, 0x7b, 0x5f, 0x83, 0x76, 0x6c, - 0x3f, 0xf1, 0x2d, 0x39, 0xe0, 0xad, 0x63, 0x59, 0xb2, 0xf1, 0x76, 0x8a, 0xbd, 0xcf, 0xe9, 0xd2, 0xe5, 0x71, 0x1f, - 0xc5, 0x53, 0x1e, 0x87, 0xd5, 0x74, 0x56, 0x51, 0x67, 0x5a, 0xa6, 0x91, 0x3a, 0xbb, 0x7b, 0x28, 0x9e, 0x6a, 0x3e, - 0x42, 0xde, 0xad, 0x25, 0x9c, 0x81, 0xd2, 0x04, 0xf9, 0xad, 0xe7, 0x8f, 0x8d, 0x62, 0x2f, 0x1a, 0x6f, 0xbb, 0xfb, - 0x99, 0x21, 0xce, 0x5f, 0x0c, 0x91, 0x54, 0xa6, 0x15, 0x26, 0xda, 0xc1, 0xd4, 0x6d, 0xcd, 0x5a, 0xac, 0x29, 0x20, - 0xb3, 0x3d, 0x8f, 0xb2, 0x25, 0x08, 0xe1, 0xb9, 0x6d, 0xe1, 0x3f, 0x0b, 0x58, 0x75, 0xb1, 0x85, 0x5e, 0x73, 0x39, - 0xe8, 0xb4, 0x52, 0xe9, 0x3e, 0x6b, 0x10, 0xbb, 0xa1, 0x4c, 0x77, 0x84, 0x8c, 0xe1, 0x05, 0x8b, 0x2b, 0x28, 0xea, - 0x17, 0x62, 0x71, 0x17, 0xb3, 0x87, 0xe7, 0x27, 0x65, 0x1a, 0xfc, 0xbf, 0x16, 0xdb, 0x41, 0x77, 0x42, 0x53, 0xe3, - 0x92, 0x4b, 0x2a, 0xec, 0x17, 0x62, 0xdc, 0x9e, 0xdb, 0x45, 0xd7, 0xb7, 0x4e, 0x19, 0x89, 0xcf, 0xf9, 0x0c, 0xe4, - 0x7a, 0xe9, 0xa7, 0xfa, 0xf4, 0x88, 0x0b, 0xb2, 0xa8, 0xa7, 0x39, 0xc1, 0xaa, 0x10, 0x33, 0x52, 0x87, 0x9a, 0x12, - 0x9f, 0xbf, 0xfa, 0x9f, 0xf6, 0x6b, 0x49, 0x3c, 0x68, 0xa7, 0x5f, 0xf9, 0xf5, 0xb1, 0x10, 0x97, 0xf6, 0x33, 0xf1, - 0xe3, 0xad, 0x62, 0xed, 0x0f, 0xa8, 0x7a, 0x9c, 0xaa, 0xff, 0x3d, 0x6a, 0xd1, 0xaf, 0xc3, 0x65, 0xd3, 0x7f, 0x2d, - 0x89, 0x07, 0xec, 0xf5, 0xeb, 0xf3, 0x3b, 0x18, 0xfc, 0x13, 0x43, 0xf2, 0xc8, 0x76, 0x02, 0x94, 0xe3, 0x47, 0xd1, - 0xe4, 0x38, 0xe4, 0x4c, 0x53, 0xae, 0x2b, 0x3c, 0xbd, 0xea, 0x68, 0x4c, 0x95, 0x8b, 0x23, 0xe9, 0xf4, 0x7c, 0x02, - 0x13, 0xd9, 0xf0, 0x96, 0xd9, 0xa5, 0xc8, 0xde, 0xc3, 0x11, 0x64, 0xb7, 0xcd, 0x27, 0x31, 0xcb, 0x67, 0x11, 0x2d, - 0xdb, 0x35, 0xd8, 0xe8, 0x94, 0xc3, 0x54, 0x5c, 0x38, 0xc0, 0xbe, 0xb7, 0x5c, 0x18, 0xec, 0x46, 0x6a, 0x1f, 0xa2, - 0x72, 0x7a, 0x1b, 0xd1, 0x6f, 0xca, 0x71, 0xf4, 0x7e, 0x1b, 0xac, 0x96, 0xc2, 0xc3, 0x43, 0x83, 0x58, 0xb5, 0xc3, - 0x2b, 0x46, 0xfd, 0xe2, 0x3a, 0xd4, 0x6e, 0x00, 0x4e, 0x9c, 0x69, 0xd3, 0xf5, 0xe3, 0xfc, 0xc2, 0x9f, 0xea, 0xd3, - 0x95, 0xd5, 0x53, 0x0f, 0x5d, 0xc4, 0xd1, 0x19, 0x97, 0x9d, 0x83, 0x12, 0x23, 0x8c, 0x19, 0x9e, 0xbf, 0x37, 0x2b, - 0x4b, 0x28, 0x48, 0x0b, 0xbd, 0x16, 0x54, 0x19, 0xfd, 0xfb, 0x03, 0xc5, 0xb9, 0xbc, 0x7f, 0xae, 0x7b, 0xff, 0x1e, - 0x33, 0xb4, 0xcd, 0x8c, 0x7a, 0xab, 0xe0, 0x3e, 0x9f, 0x24, 0xb0, 0x48, 0x96, 0x58, 0xdb, 0xe2, 0xff, 0xea, 0x12, - 0xeb, 0x34, 0xaa, 0xbd, 0xc2, 0xd5, 0x99, 0xb6, 0xe6, 0xab, 0xfa, 0x52, 0x73, 0xaf, 0xee, 0x47, 0x3f, 0xd8, 0x30, - 0x8d, 0x4b, 0x7b, 0x5a, 0x90, 0x9b, 0x64, 0xcf, 0xa2, 0xc7, 0xe6, 0x64, 0x1c, 0x5a, 0xf5, 0x43, 0x93, 0x00, 0x51, - 0xc6, 0xa9, 0x47, 0x9a, 0xf2, 0x59, 0xee, 0xc3, 0x12, 0x2f, 0xb8, 0x10, 0xd7, 0xc3, 0xed, 0xee, 0x9e, 0x91, 0x1d, - 0xa8, 0xf2, 0x9b, 0x77, 0x87, 0xf7, 0x7d, 0xa4, 0xfc, 0x0e, 0x54, 0xb3, 0xbe, 0x59, 0xa9, 0x08, 0xd4, 0x15, 0x28, - 0x02, 0x5c, 0xbe, 0x67, 0x95, 0xe0, 0xae, 0xe6, 0x79, 0x18, 0xb1, 0x92, 0x84, 0x9a, 0x2b, 0x05, 0x87, 0xc5, 0xa6, - 0x29, 0x45, 0x61, 0xb1, 0x26, 0xfa, 0x75, 0xcd, 0xa6, 0xd3, 0x45, 0x0d, 0x9c, 0x1b, 0x98, 0xa5, 0x9b, 0x35, 0xa2, - 0x1f, 0x12, 0xf2, 0x0e, 0x9e, 0x66, 0x8b, 0x6d, 0x20, 0x86, 0x5a, 0x5c, 0x63, 0x60, 0x7b, 0xf8, 0x90, 0x07, 0xf4, - 0xa4, 0xff, 0x74, 0x0d, 0xd1, 0x23, 0xdb, 0x80, 0xc5, 0x6f, 0x26, 0x75, 0x78, 0xf7, 0x30, 0x3d, 0xe3, 0xa5, 0x4f, - 0xc6, 0x2f, 0x0e, 0x6d, 0x86, 0x9f, 0x1e, 0x51, 0x54, 0x24, 0x2a, 0x77, 0x76, 0xd9, 0xcf, 0x86, 0x4c, 0xed, 0xe9, - 0x78, 0xb2, 0xbf, 0x60, 0x6e, 0xfd, 0x60, 0x7f, 0x18, 0xc7, 0x83, 0x04, 0x35, 0x14, 0x1b, 0xfe, 0x71, 0xa3, 0x58, - 0x24, 0x3d, 0x5b, 0x6f, 0xfb, 0xe0, 0x95, 0x50, 0xce, 0x2b, 0xd7, 0x32, 0x3d, 0xd3, 0xb1, 0x83, 0x67, 0xfa, 0xc1, - 0xea, 0x32, 0x01, 0x95, 0xdf, 0x85, 0x89, 0x81, 0x73, 0x24, 0xca, 0x11, 0x19, 0xf1, 0xa2, 0xe8, 0x4b, 0x36, 0x87, - 0x56, 0x58, 0x0d, 0xba, 0xa5, 0xe8, 0xaf, 0x57, 0x76, 0x97, 0xfa, 0xae, 0xcf, 0x5e, 0xe4, 0xf6, 0xe6, 0x63, 0x19, - 0x3a, 0x14, 0x29, 0x25, 0xa7, 0xfe, 0x64, 0x0c, 0x79, 0x7d, 0x3d, 0x75, 0xa6, 0xf8, 0xcf, 0x6c, 0x90, 0xc4, 0x6c, - 0x00, 0x0a, 0x59, 0x34, 0x8f, 0x00, 0x60, 0x49, 0x5f, 0x24, 0x81, 0x37, 0xfc, 0x43, 0xac, 0x59, 0x37, 0x44, 0xcc, - 0x57, 0xfb, 0xe6, 0xe2, 0x32, 0x0b, 0x77, 0x76, 0xec, 0xd1, 0x3d, 0x79, 0x10, 0x95, 0x25, 0x99, 0x4d, 0x67, 0xed, - 0x3d, 0xa4, 0xaf, 0x0c, 0x79, 0x06, 0x99, 0x32, 0x40, 0x02, 0xa6, 0x23, 0xac, 0x33, 0x3c, 0xb9, 0xe6, 0xdc, 0x6a, - 0xb2, 0x50, 0x82, 0x43, 0x74, 0x1c, 0xdd, 0x0a, 0x49, 0xd6, 0xdc, 0x6b, 0xbe, 0xd4, 0x0f, 0x52, 0x4e, 0x3e, 0xad, - 0x98, 0x27, 0x8e, 0xe3, 0x37, 0x24, 0xa2, 0x27, 0x11, 0xe5, 0x69, 0xd7, 0x39, 0xe4, 0xb7, 0xac, 0x54, 0xcc, 0x0c, - 0x54, 0x3d, 0xf2, 0x54, 0x13, 0xac, 0xbb, 0xc5, 0x1d, 0x88, 0xa7, 0x0f, 0x44, 0x13, 0x8a, 0x93, 0xac, 0xf2, 0x5a, - 0x0f, 0xb3, 0xe1, 0x2b, 0x62, 0x73, 0x35, 0xda, 0xec, 0x58, 0xcc, 0xd8, 0x0a, 0x9a, 0x60, 0x40, 0x9d, 0x11, 0x4e, - 0xbb, 0x76, 0xf7, 0x28, 0x30, 0xb2, 0xe9, 0x94, 0x7e, 0x8c, 0xa8, 0xd0, 0x6d, 0xbe, 0x8c, 0x0a, 0x71, 0x54, 0x84, - 0x9e, 0x87, 0xa1, 0x50, 0xfa, 0x69, 0x59, 0x14, 0xf1, 0x59, 0x3f, 0xe7, 0xae, 0xc6, 0x18, 0x53, 0x34, 0x95, 0x65, - 0xd7, 0x15, 0xc8, 0x1b, 0xb1, 0x35, 0x44, 0x80, 0x3c, 0x5f, 0x35, 0xed, 0xea, 0xd7, 0x9b, 0xa8, 0xfc, 0x3b, 0x36, - 0xba, 0x8d, 0x76, 0x13, 0x78, 0x56, 0x9c, 0xb9, 0x2d, 0x80, 0x35, 0x3a, 0xd7, 0x25, 0x71, 0xe4, 0xe8, 0x71, 0xbd, - 0x1f, 0xcc, 0xfe, 0xa4, 0xb5, 0x78, 0x90, 0x6f, 0x91, 0xa9, 0x95, 0x52, 0x17, 0xea, 0xb5, 0x65, 0x1a, 0xcf, 0x07, - 0x99, 0x49, 0xf9, 0x84, 0xd1, 0xf9, 0xd2, 0x4d, 0xf3, 0xc2, 0x66, 0x81, 0xc9, 0x44, 0x25, 0x4e, 0x61, 0x3a, 0xb7, - 0x4b, 0x84, 0xa4, 0x3b, 0x82, 0x53, 0x59, 0x56, 0x14, 0x77, 0xb7, 0xad, 0xd9, 0x37, 0x93, 0xbf, 0x26, 0x3d, 0x1c, - 0xe3, 0x2e, 0xe8, 0xd8, 0x28, 0x6f, 0x26, 0xdb, 0x83, 0xc9, 0xc3, 0xea, 0x42, 0xe9, 0xb4, 0x9a, 0x6e, 0xea, 0x19, - 0xb9, 0xb9, 0x71, 0xea, 0x6a, 0xa2, 0xeb, 0x12, 0x30, 0x9e, 0x8d, 0xe2, 0x1e, 0x5b, 0xe4, 0x1a, 0x79, 0x6d, 0x2d, - 0x41, 0xb7, 0x2c, 0x14, 0x8b, 0xd1, 0xd4, 0xc0, 0x18, 0x61, 0x52, 0x11, 0x83, 0xd7, 0xe7, 0xb0, 0xc9, 0x13, 0x13, - 0xa8, 0xea, 0xdf, 0x94, 0x93, 0x25, 0xbb, 0x98, 0xa5, 0x91, 0x0c, 0xcb, 0x41, 0xd9, 0x7b, 0xa2, 0xa5, 0x8f, 0x78, - 0x2e, 0x70, 0x6d, 0xdb, 0xf6, 0x61, 0x6d, 0x6b, 0xc0, 0xc0, 0xfb, 0xa6, 0x7d, 0x07, 0xc1, 0x15, 0xbb, 0xd5, 0x9c, - 0x67, 0xf0, 0x78, 0xc0, 0xec, 0x5b, 0xf2, 0x7c, 0x5e, 0xa8, 0xb2, 0x7d, 0xa2, 0xb3, 0xfb, 0x02, 0x42, 0x31, 0xbb, - 0xd1, 0xe5, 0xd9, 0x6e, 0xbb, 0x87, 0x0c, 0x59, 0x90, 0xb1, 0x24, 0x29, 0x3c, 0xf2, 0x9d, 0x5e, 0x6d, 0x19, 0x6b, - 0x3e, 0x73, 0x19, 0xb7, 0xa4, 0x16, 0x94, 0x6a, 0x0f, 0x6d, 0x8a, 0xf2, 0x5a, 0x84, 0x49, 0x15, 0xd6, 0x6e, 0xf3, - 0x99, 0xca, 0xd1, 0x16, 0x91, 0x09, 0x1e, 0x17, 0x12, 0x3b, 0x83, 0x25, 0x82, 0x0c, 0x9d, 0x26, 0x68, 0x6a, 0x9f, - 0x44, 0xb3, 0xb8, 0xe6, 0xc1, 0xa8, 0xa6, 0xca, 0xe1, 0x75, 0x13, 0x26, 0xcc, 0xe3, 0x42, 0xda, 0x76, 0xc4, 0x24, - 0x5d, 0xc7, 0xf9, 0x6a, 0x25, 0xeb, 0x51, 0x8e, 0xcc, 0x73, 0xa5, 0xb3, 0x95, 0x2e, 0xe6, 0x41, 0x29, 0xca, 0xcb, - 0x50, 0x20, 0x91, 0x93, 0xad, 0x66, 0x6f, 0x2f, 0x8d, 0xd5, 0x40, 0xa4, 0x57, 0xd6, 0xc7, 0x23, 0x58, 0x4c, 0x17, - 0x29, 0xa5, 0x60, 0x03, 0x85, 0xb0, 0xd1, 0xd8, 0xb3, 0x56, 0xfe, 0xf9, 0xb9, 0xa6, 0x5a, 0xf5, 0x67, 0x84, 0x6d, - 0xf6, 0x8b, 0xf7, 0xe5, 0x58, 0x05, 0x18, 0x75, 0x2f, 0xb2, 0x22, 0x79, 0xab, 0xcb, 0x5b, 0x24, 0x6f, 0xbe, 0xbc, - 0x32, 0x71, 0xc2, 0xf3, 0xb5, 0xd6, 0x86, 0x09, 0x77, 0x6e, 0x55, 0xeb, 0x88, 0x2b, 0x31, 0xd7, 0x7e, 0xdf, 0xa0, - 0x9f, 0x26, 0xa2, 0xec, 0x5f, 0xcd, 0xa8, 0x90, 0x4d, 0x9f, 0x12, 0xaa, 0xcd, 0xbc, 0x8c, 0x90, 0xbb, 0x17, 0x83, - 0x49, 0xa9, 0x4e, 0x5d, 0xdd, 0xe6, 0xe3, 0x8b, 0x31, 0xb1, 0x7e, 0xf9, 0xd7, 0xb8, 0x38, 0x5f, 0x30, 0x1c, 0xba, - 0xe2, 0xce, 0x7b, 0xd6, 0x0a, 0xe5, 0x0a, 0x73, 0xc0, 0x39, 0x5a, 0xaa, 0x2a, 0x63, 0xd4, 0xb6, 0xea, 0xdc, 0x01, - 0x8f, 0x23, 0x08, 0xfc, 0x8e, 0xae, 0x1a, 0x49, 0x46, 0xa9, 0xef, 0xea, 0x18, 0xfc, 0x65, 0xa4, 0xf1, 0xe1, 0xf7, - 0x05, 0x11, 0xf4, 0xd2, 0x55, 0xe5, 0xda, 0xa3, 0x2a, 0xa2, 0xac, 0x82, 0x24, 0xe6, 0x64, 0xb9, 0x0b, 0x47, 0xb9, - 0xf1, 0xe7, 0x93, 0x5d, 0xad, 0x0d, 0x42, 0xcc, 0x62, 0xcc, 0xd9, 0x52, 0xcc, 0x59, 0x11, 0xbe, 0x7d, 0x1e, 0xfd, - 0xce, 0x55, 0x25, 0x10, 0xf9, 0x68, 0xe3, 0x51, 0x7c, 0xf9, 0x22, 0xe0, 0x69, 0x55, 0x7d, 0x20, 0x24, 0xbe, 0xb3, - 0xd3, 0x2e, 0xf9, 0x6b, 0x7f, 0xa6, 0x44, 0x32, 0x69, 0x89, 0x21, 0x70, 0x47, 0xfc, 0xce, 0x75, 0x03, 0x19, 0x80, - 0x9c, 0xd1, 0xae, 0x01, 0x73, 0x12, 0x4d, 0x43, 0x42, 0xd5, 0xb4, 0x96, 0x77, 0xf3, 0x0a, 0x7d, 0x22, 0x89, 0x7e, - 0x97, 0x37, 0xc3, 0xaf, 0xb4, 0x48, 0xe5, 0x9c, 0xbf, 0xef, 0xe2, 0x57, 0x75, 0x64, 0xe7, 0x4c, 0x63, 0xa5, 0xc0, - 0x97, 0x01, 0xb8, 0x81, 0x76, 0xc5, 0x8d, 0x38, 0xce, 0x92, 0x1e, 0xd9, 0x19, 0x3d, 0x50, 0xdb, 0x57, 0xb2, 0x68, - 0x29, 0x5e, 0x98, 0xa6, 0x10, 0xca, 0xe0, 0x22, 0x3e, 0x91, 0xb9, 0xa8, 0xb2, 0xe6, 0x55, 0x5f, 0xe0, 0x36, 0x22, - 0x66, 0x44, 0x79, 0x22, 0x92, 0x9c, 0x95, 0xba, 0xa1, 0xc1, 0xe2, 0xe8, 0xd2, 0x62, 0x4d, 0x4e, 0x90, 0xcc, 0x97, - 0x88, 0xe0, 0x5f, 0x2e, 0xd5, 0xb3, 0xfb, 0x9b, 0xb5, 0x67, 0x85, 0xb6, 0x46, 0x60, 0xb2, 0x8b, 0x5e, 0xbd, 0xe8, - 0x35, 0xb7, 0x86, 0xf2, 0x21, 0x51, 0xc8, 0xef, 0x49, 0xdd, 0x1a, 0xd6, 0x4c, 0x52, 0x30, 0xdf, 0x17, 0xb5, 0x45, - 0xeb, 0xce, 0xb1, 0x97, 0x3f, 0xea, 0x71, 0xf7, 0x54, 0x82, 0x82, 0xd0, 0x6d, 0x26, 0xb5, 0x40, 0x24, 0x59, 0x63, - 0x8b, 0x7d, 0x22, 0x7a, 0xc7, 0x74, 0xa5, 0x74, 0x71, 0x64, 0xfb, 0xe5, 0x1d, 0x32, 0x93, 0x9c, 0x5d, 0x2a, 0x31, - 0xe5, 0x3f, 0x47, 0xd9, 0xe4, 0x62, 0x67, 0x8b, 0x3e, 0x73, 0x90, 0x36, 0x53, 0x13, 0x61, 0x0a, 0xf6, 0xce, 0xcc, - 0x46, 0x08, 0x8f, 0x24, 0x93, 0xc2, 0x28, 0xb1, 0x97, 0x7c, 0x8a, 0xa7, 0x90, 0xdf, 0x2a, 0x34, 0xb4, 0xe4, 0x99, - 0xfe, 0x07, 0xeb, 0x08, 0xdf, 0x4a, 0xe0, 0x20, 0xc9, 0x3f, 0x60, 0xc1, 0x6d, 0xe9, 0x7a, 0xc7, 0x6c, 0x90, 0x84, - 0xfb, 0x67, 0x96, 0xcf, 0x76, 0x7b, 0x10, 0xbf, 0x29, 0x12, 0x82, 0x2f, 0x3a, 0xaa, 0x5d, 0xb2, 0x8c, 0x4a, 0xaa, - 0x45, 0xe5, 0x7e, 0x7c, 0xcc, 0xcb, 0x23, 0x2a, 0x2f, 0xe0, 0x97, 0xef, 0xd6, 0x1c, 0x98, 0x81, 0xaf, 0xb4, 0xd5, - 0x44, 0xc2, 0x5e, 0x18, 0xec, 0x29, 0x94, 0x2c, 0xe2, 0xc0, 0x6e, 0x36, 0xc4, 0x5c, 0xe8, 0x5a, 0x9b, 0xed, 0xc3, - 0x18, 0x6a, 0x75, 0xca, 0xf4, 0x26, 0xae, 0x6a, 0x84, 0xb9, 0x4d, 0x23, 0x8e, 0x4a, 0x66, 0xda, 0x97, 0x1b, 0x4c, - 0xd3, 0x21, 0x7b, 0x1b, 0x68, 0x2d, 0xdf, 0x1c, 0xeb, 0xca, 0x9b, 0x69, 0x8f, 0x42, 0xc0, 0x18, 0xb1, 0xe6, 0x8a, - 0x5e, 0x6b, 0x65, 0x3f, 0x48, 0xb1, 0x3f, 0xaa, 0x05, 0x22, 0xaa, 0x22, 0xa9, 0xd9, 0xb0, 0xcb, 0x5e, 0xad, 0xbd, - 0xac, 0x0b, 0xb0, 0x74, 0x6a, 0x39, 0xd6, 0xbc, 0x60, 0x30, 0x94, 0xa9, 0x5a, 0x2d, 0x73, 0x87, 0xab, 0xec, 0xa9, - 0x96, 0x97, 0xb2, 0x20, 0x61, 0x2f, 0x81, 0xe8, 0xc4, 0xf7, 0x74, 0x4f, 0x22, 0xdf, 0x99, 0xd3, 0x37, 0x66, 0x32, - 0xc4, 0xe8, 0xac, 0x58, 0x81, 0x55, 0xbd, 0x0d, 0x0c, 0x15, 0xb5, 0xc6, 0x86, 0xee, 0xf2, 0x98, 0x7d, 0x8e, 0xc3, - 0x7d, 0x61, 0xbf, 0x2d, 0xc8, 0x7d, 0xf8, 0xef, 0x59, 0x7e, 0xdb, 0xd8, 0x2c, 0xcc, 0xb2, 0xde, 0x3c, 0x46, 0x8e, - 0xf0, 0x7a, 0x4b, 0xa5, 0xca, 0x16, 0x0c, 0xd9, 0x6b, 0x58, 0xf7, 0xab, 0x99, 0xba, 0x90, 0x6e, 0x62, 0x46, 0x8c, - 0xda, 0x9d, 0x48, 0x12, 0xf4, 0x14, 0x33, 0x28, 0xa1, 0x79, 0x91, 0xd6, 0x66, 0x23, 0xf7, 0x60, 0x9d, 0x8e, 0x4c, - 0x44, 0x97, 0x60, 0x8a, 0x73, 0x36, 0xdf, 0xdf, 0x61, 0xc8, 0x61, 0x8f, 0x25, 0xaa, 0xe4, 0x41, 0xbd, 0x6f, 0x65, - 0xa5, 0xa6, 0xd8, 0x74, 0x2c, 0x23, 0x2e, 0x37, 0x80, 0x83, 0x1d, 0x6d, 0xa7, 0x86, 0x39, 0xb5, 0x73, 0x09, 0x76, - 0x72, 0x53, 0x7b, 0xb7, 0x22, 0x03, 0x4b, 0x1e, 0x08, 0x55, 0x18, 0xf0, 0x69, 0x5f, 0x11, 0x00, 0x9a, 0xe3, 0x14, - 0x89, 0x3f, 0x8c, 0xe4, 0xef, 0x77, 0x24, 0x9d, 0x84, 0xe3, 0x6e, 0x24, 0x70, 0x7a, 0x1c, 0xc0, 0x28, 0xf5, 0x64, - 0xf3, 0x03, 0x10, 0xe5, 0x22, 0x7f, 0x95, 0x18, 0x1d, 0x31, 0x44, 0x38, 0xf0, 0x53, 0x71, 0x21, 0x6d, 0xbd, 0x59, - 0x2e, 0x8e, 0x46, 0x41, 0xd7, 0xd5, 0x01, 0xf7, 0x91, 0x0a, 0x00, 0x6d, 0x36, 0xe4, 0xba, 0xbe, 0x77, 0x88, 0xd8, - 0x7d, 0x5a, 0xb8, 0x41, 0x04, 0x7e, 0x5c, 0xa6, 0xe6, 0x5b, 0x38, 0x5c, 0xd3, 0x4c, 0xbd, 0x95, 0xc7, 0xd3, 0x7d, - 0xdd, 0xed, 0x0c, 0xf0, 0x2f, 0x97, 0x38, 0x60, 0xfe, 0x3b, 0xa9, 0xe2, 0x60, 0xc4, 0x1c, 0x1d, 0xe3, 0x92, 0x66, - 0x66, 0x6a, 0xc8, 0x73, 0x73, 0xe5, 0x29, 0xca, 0x81, 0xcc, 0x27, 0xd3, 0x43, 0x76, 0x13, 0xf8, 0x35, 0x40, 0x5d, - 0x3c, 0x24, 0x54, 0x80, 0x7a, 0x82, 0xc0, 0xd5, 0x04, 0xc2, 0xb2, 0xf9, 0x73, 0x6c, 0xee, 0x99, 0x68, 0x02, 0x1a, - 0x3a, 0x50, 0xe9, 0xf4, 0xa4, 0x2c, 0x80, 0x7a, 0xa8, 0xfd, 0x10, 0x09, 0x0f, 0x7a, 0xd9, 0x74, 0xd0, 0xb8, 0x8e, - 0x46, 0x48, 0x9a, 0x50, 0x90, 0xb8, 0xc0, 0x29, 0xfa, 0x6a, 0xc9, 0xfc, 0x55, 0x22, 0xdf, 0xa8, 0x72, 0xd1, 0xe0, - 0x5f, 0xa2, 0x45, 0x56, 0xcf, 0x18, 0x99, 0x1d, 0x6d, 0xca, 0x4a, 0x65, 0xbc, 0x00, 0xf0, 0xe1, 0x10, 0x1c, 0x49, - 0x44, 0x2c, 0x93, 0x68, 0x22, 0x1b, 0x87, 0xf2, 0xa7, 0x97, 0x77, 0x0a, 0xe0, 0x7a, 0x1e, 0x09, 0x9a, 0x08, 0x7c, - 0x6c, 0x09, 0x38, 0x33, 0x83, 0x00, 0x67, 0xab, 0x4d, 0x23, 0x30, 0x11, 0x5a, 0x79, 0x6a, 0xd8, 0xc7, 0x48, 0x94, - 0xe3, 0x12, 0x61, 0xe4, 0x76, 0x4d, 0x19, 0xb9, 0x44, 0x24, 0x36, 0xe6, 0xc8, 0x73, 0xfd, 0x51, 0x0a, 0xfd, 0xcb, - 0x2c, 0x7c, 0x52, 0xa2, 0xfa, 0xd2, 0xa0, 0x78, 0xd3, 0xc6, 0x07, 0x3b, 0x18, 0xd7, 0x52, 0xcb, 0x61, 0xc2, 0x60, - 0xbe, 0xf6, 0xff, 0xc6, 0xd7, 0x4a, 0xf5, 0x95, 0xf3, 0x11, 0x5d, 0xf1, 0x18, 0x1c, 0xd6, 0x89, 0x9c, 0x5f, 0x37, - 0x4d, 0xe4, 0xf8, 0x73, 0x79, 0xb7, 0x37, 0x9e, 0xee, 0x36, 0x82, 0xca, 0xa5, 0x34, 0x67, 0x9e, 0x11, 0x7d, 0x18, - 0x58, 0xbe, 0x58, 0xa3, 0xca, 0x34, 0xbe, 0x74, 0x40, 0xb9, 0xe2, 0xf0, 0xf4, 0x24, 0x10, 0x2f, 0x07, 0x7b, 0x8a, - 0x03, 0x62, 0x45, 0x89, 0xb2, 0x67, 0x2a, 0x22, 0x8d, 0x43, 0x60, 0xbd, 0x11, 0x19, 0x19, 0x02, 0x52, 0x86, 0xed, - 0x9a, 0xf5, 0xaf, 0x58, 0x51, 0x7c, 0x0e, 0xc9, 0x26, 0xcb, 0x66, 0x7c, 0x8a, 0x1d, 0x8d, 0x57, 0x22, 0xa9, 0x68, - 0xd9, 0xf4, 0xa7, 0x6d, 0x47, 0xf6, 0x5e, 0x82, 0x43, 0xe2, 0x00, 0xa7, 0xf4, 0xce, 0x9f, 0xcb, 0x3b, 0xab, 0x23, - 0xdf, 0x83, 0xfe, 0x95, 0x97, 0xfc, 0x95, 0xef, 0xc1, 0x9e, 0xf2, 0x92, 0xa7, 0x7c, 0x0f, 0xf8, 0x94, 0x17, 0x89, - 0xe2, 0x34, 0x7d, 0xe5, 0x70, 0x1e, 0x8c, 0x11, 0x43, 0xb9, 0x3c, 0x91, 0xad, 0xe4, 0xe0, 0x17, 0xef, 0x13, 0xee, - 0xb3, 0x81, 0x94, 0x3c, 0x66, 0xa6, 0x58, 0x89, 0x4a, 0x56, 0x96, 0x49, 0x01, 0x7c, 0xea, 0xdb, 0xc5, 0x99, 0xed, - 0x17, 0xfc, 0xe1, 0x97, 0x48, 0x1a, 0x03, 0x71, 0xa7, 0x04, 0x5d, 0xbb, 0xd3, 0xd7, 0x9e, 0xdb, 0x8a, 0x08, 0xca, - 0x72, 0xc4, 0xe8, 0x44, 0xa5, 0x1d, 0x67, 0x89, 0xde, 0xbd, 0x55, 0x18, 0x08, 0xfa, 0x76, 0xa1, 0x8f, 0xc8, 0x61, - 0xfd, 0xfd, 0x17, 0x20, 0x64, 0x5c, 0x12, 0x88, 0xc0, 0x3e, 0xf6, 0xea, 0x39, 0xd4, 0xda, 0xf3, 0xa4, 0x8a, 0x06, - 0x5c, 0x93, 0x83, 0x71, 0x8b, 0x90, 0xa4, 0xa7, 0xff, 0x88, 0x1f, 0x92, 0xb3, 0x74, 0xd1, 0x3c, 0x0b, 0xf7, 0x18, - 0x2d, 0x07, 0x34, 0x27, 0x41, 0xd5, 0xcc, 0x72, 0x45, 0x34, 0x9a, 0xd3, 0x9e, 0x79, 0xe0, 0x64, 0xa9, 0xb6, 0xae, - 0xc2, 0x9d, 0xf7, 0xf8, 0x19, 0x9f, 0xd1, 0x71, 0x9a, 0x1e, 0x19, 0xb0, 0x2f, 0x72, 0x7a, 0x1f, 0x5c, 0xe1, 0x58, - 0x6b, 0x30, 0x3d, 0x91, 0x6c, 0x2d, 0xae, 0xaf, 0xc6, 0xf8, 0x82, 0xb4, 0xca, 0xfb, 0x52, 0x44, 0xc3, 0x4f, 0xc9, - 0xc4, 0x66, 0xa4, 0xa5, 0x21, 0x5f, 0x5b, 0x6a, 0xb4, 0x59, 0xb1, 0x04, 0x4b, 0x6e, 0xbf, 0x75, 0x85, 0x4d, 0xdf, - 0x64, 0x2e, 0x92, 0x6c, 0x54, 0xdd, 0x14, 0x69, 0x53, 0xe0, 0x53, 0x92, 0x15, 0xc1, 0x23, 0x50, 0x64, 0xee, 0x48, - 0x72, 0xbc, 0x74, 0xd4, 0x72, 0xaa, 0x4a, 0x88, 0xc2, 0x67, 0x15, 0x56, 0xb5, 0x14, 0x1d, 0x2f, 0x0e, 0x44, 0x08, - 0x39, 0x8c, 0x4b, 0xa7, 0xa6, 0xd1, 0x75, 0xad, 0xf6, 0x16, 0xf2, 0x1c, 0x7c, 0xf9, 0x69, 0x88, 0x25, 0x2c, 0x59, - 0x8d, 0x31, 0xe0, 0xcc, 0xb3, 0x1b, 0x7a, 0xe4, 0xb9, 0xbc, 0x1f, 0x80, 0xa3, 0x17, 0xbb, 0x16, 0x8a, 0xb9, 0xeb, - 0x33, 0x12, 0x09, 0x24, 0x32, 0x5f, 0x00, 0x70, 0x00, 0xc0, 0x55, 0x2f, 0xab, 0x3a, 0x80, 0x41, 0x2b, 0x55, 0xa0, - 0x67, 0x0a, 0x6e, 0x81, 0xcc, 0xd0, 0x72, 0x50, 0xf9, 0x23, 0x0a, 0x7c, 0xed, 0x90, 0x2c, 0x26, 0xb2, 0x34, 0x94, - 0xac, 0x63, 0x42, 0x3b, 0x1f, 0xc6, 0xd3, 0x4b, 0x14, 0xee, 0x22, 0xa5, 0xa3, 0xb6, 0xe8, 0xa7, 0x67, 0x8f, 0x7a, - 0x5a, 0x38, 0x2d, 0x22, 0x2f, 0xc7, 0xc6, 0xbf, 0xe5, 0xed, 0xba, 0x5c, 0x7f, 0x64, 0x2b, 0x9a, 0x82, 0x36, 0x04, - 0x9f, 0x3d, 0x5b, 0xf5, 0x8c, 0xbe, 0x42, 0x4e, 0x8b, 0xe5, 0xd0, 0xeb, 0xb7, 0x59, 0x6d, 0x0e, 0x1f, 0x9e, 0xd1, - 0x03, 0xd1, 0xa5, 0xbb, 0xd7, 0x48, 0xa0, 0xb9, 0x44, 0xb0, 0x18, 0x9e, 0xe3, 0xd2, 0x6e, 0x72, 0x28, 0x29, 0x0a, - 0x62, 0x15, 0xf8, 0x80, 0xde, 0xde, 0xc1, 0x90, 0xc1, 0xae, 0xdb, 0x18, 0xc0, 0xd5, 0x40, 0xf3, 0xac, 0xc5, 0x61, - 0xaf, 0x4f, 0xc0, 0xc6, 0xd2, 0xf9, 0x6a, 0xdb, 0x45, 0xb1, 0xd7, 0x5c, 0x91, 0xee, 0xda, 0x0a, 0x81, 0x3f, 0x17, - 0x9f, 0xfc, 0xed, 0x79, 0xd1, 0xfe, 0xd6, 0x7f, 0x29, 0xbd, 0x77, 0xaa, 0xf6, 0x7b, 0xa3, 0x01, 0xf5, 0xc7, 0xa9, - 0x65, 0xa9, 0x2c, 0x87, 0x59, 0xe9, 0xf9, 0x68, 0x54, 0x8b, 0xdb, 0x6b, 0x8a, 0x88, 0x8f, 0x92, 0xe0, 0x66, 0x53, - 0x2b, 0x0f, 0xee, 0x9d, 0xed, 0x85, 0xbe, 0x87, 0x81, 0xea, 0x5e, 0x0b, 0x4d, 0x77, 0x2e, 0x25, 0xa8, 0xc9, 0xc8, - 0x68, 0xa6, 0xd9, 0x98, 0xb7, 0xbe, 0xf9, 0x61, 0xaa, 0x5f, 0xd0, 0xa7, 0x52, 0x72, 0x20, 0x3b, 0xab, 0x8b, 0x52, - 0xb1, 0x2a, 0x09, 0xc1, 0xe2, 0xfa, 0xbb, 0x38, 0x24, 0x30, 0x70, 0xad, 0xba, 0x0c, 0x18, 0x89, 0x7d, 0xb1, 0xf8, - 0xa8, 0xe8, 0xf8, 0xad, 0x1d, 0x64, 0x70, 0xb3, 0xcb, 0xbc, 0x0c, 0x33, 0xfc, 0x20, 0xac, 0xd3, 0x9a, 0x82, 0x40, - 0x4d, 0x9d, 0xbc, 0x4a, 0x82, 0x62, 0xf9, 0x66, 0x4f, 0x1b, 0x7b, 0x61, 0x6c, 0x03, 0xe8, 0xd9, 0xa6, 0x91, 0x18, - 0x4c, 0xfc, 0x93, 0x63, 0xf7, 0x57, 0xa1, 0xd2, 0xaa, 0x6b, 0x51, 0x7b, 0x51, 0x1e, 0x84, 0x0e, 0xa1, 0x43, 0x51, - 0x2b, 0xb7, 0x75, 0x58, 0x9f, 0xd7, 0xb2, 0x3c, 0xe9, 0x9f, 0x78, 0xbb, 0x48, 0xd7, 0xc5, 0x1d, 0x0c, 0x35, 0x12, - 0xc8, 0x8e, 0x2a, 0x36, 0x69, 0xdc, 0x51, 0xa9, 0xb2, 0xdc, 0x7d, 0xd8, 0xa0, 0x5e, 0x5b, 0x44, 0x90, 0xa9, 0x3e, - 0xae, 0x08, 0x35, 0x86, 0x3d, 0xa1, 0x34, 0x05, 0x4c, 0x65, 0x95, 0xc5, 0x53, 0x73, 0x77, 0x7e, 0xc8, 0x99, 0xd2, - 0x70, 0xc0, 0xc7, 0xb0, 0x98, 0x0d, 0xfc, 0xfb, 0x21, 0xd2, 0xc0, 0x4d, 0xad, 0x67, 0xa1, 0x4c, 0x20, 0xad, 0x50, - 0xcc, 0x47, 0x32, 0x0a, 0x13, 0x7c, 0xcf, 0x19, 0x14, 0x39, 0x29, 0xd9, 0x68, 0xfc, 0x66, 0xdd, 0x63, 0xe8, 0x38, - 0x33, 0x3e, 0xcc, 0xd3, 0x15, 0x7b, 0xa5, 0xc0, 0xd5, 0x21, 0x14, 0x5c, 0x8e, 0xa3, 0x1a, 0xd7, 0x05, 0xd9, 0x40, - 0x49, 0x5e, 0x78, 0x8f, 0x24, 0xa4, 0x2e, 0xf4, 0x94, 0x6a, 0x47, 0x21, 0x19, 0x96, 0x60, 0x7a, 0xdc, 0x9d, 0xb1, - 0x8d, 0x2b, 0x69, 0xdb, 0xd9, 0x69, 0xa1, 0x6e, 0xcf, 0xc0, 0x83, 0x5d, 0xd5, 0x3b, 0x28, 0x47, 0x56, 0x06, 0x1a, - 0x8c, 0x80, 0xb6, 0x2c, 0x49, 0xaa, 0x89, 0xd8, 0x68, 0x14, 0x46, 0x0d, 0xa5, 0xb5, 0x92, 0x9d, 0x9c, 0xdf, 0xeb, - 0xaa, 0x98, 0x26, 0xeb, 0x50, 0x1c, 0xf4, 0xc4, 0x24, 0xa5, 0x79, 0x5d, 0xb6, 0x78, 0x7f, 0xa0, 0xf6, 0x8b, 0x54, - 0x7b, 0x62, 0x6f, 0x6e, 0x24, 0x4a, 0xb3, 0xef, 0x29, 0x94, 0x87, 0x46, 0xe7, 0xb5, 0xd1, 0x79, 0x79, 0x1d, 0xa5, - 0xff, 0x9b, 0xa8, 0x65, 0xca, 0xc6, 0x98, 0xa2, 0x0e, 0x68, 0x3e, 0x31, 0x82, 0xf6, 0xfd, 0x4b, 0xa1, 0x8e, 0x50, - 0x34, 0x4c, 0x3d, 0xce, 0xb0, 0x18, 0xe9, 0x06, 0xcf, 0x97, 0x84, 0x04, 0xf7, 0xee, 0xc0, 0xc0, 0x23, 0xc2, 0x3c, - 0x91, 0x31, 0x9d, 0x20, 0x0c, 0x51, 0x59, 0x27, 0x67, 0xde, 0xe7, 0xe6, 0xdf, 0x6e, 0x4a, 0xdb, 0x6e, 0xfa, 0x0d, - 0x26, 0xe7, 0xfd, 0x94, 0xde, 0x7b, 0x79, 0xb4, 0x69, 0x7f, 0x31, 0xb2, 0x5b, 0xf0, 0xc2, 0xe2, 0x3d, 0x16, 0xf6, - 0x2f, 0x65, 0x3e, 0x73, 0xac, 0xf4, 0x36, 0x63, 0x20, 0x83, 0x67, 0xd6, 0x58, 0xfe, 0x4a, 0xd0, 0x8e, 0x42, 0xa0, - 0x9d, 0xd8, 0x09, 0x59, 0x05, 0x09, 0x88, 0xc4, 0x58, 0xdb, 0xce, 0xc1, 0x40, 0x3b, 0xd6, 0x99, 0x5b, 0xb4, 0xf4, - 0xdd, 0x53, 0x4e, 0x4a, 0x00, 0xca, 0x4b, 0xe5, 0x9f, 0x5d, 0x9c, 0x1a, 0xfb, 0x38, 0xc1, 0xd8, 0x0a, 0xec, 0x43, - 0x02, 0xa9, 0x2a, 0x26, 0x74, 0x9a, 0x22, 0xa0, 0x8b, 0x63, 0x13, 0x7f, 0x6e, 0xdc, 0x9d, 0xc1, 0xea, 0x69, 0xbe, - 0x64, 0x9b, 0xdd, 0x4b, 0x8c, 0xa9, 0xcd, 0x3a, 0xdb, 0x16, 0xf3, 0x8c, 0xdc, 0x95, 0xc5, 0xda, 0x04, 0x52, 0xb6, - 0xe4, 0xca, 0xb5, 0x45, 0xc8, 0x84, 0x21, 0xeb, 0x1a, 0x42, 0x52, 0x20, 0xf8, 0x2d, 0x25, 0x81, 0xd5, 0xfb, 0xa5, - 0xae, 0xd4, 0xb3, 0x88, 0x76, 0x99, 0xa0, 0x1d, 0x1c, 0x39, 0xd2, 0x79, 0xe1, 0xff, 0xb7, 0x12, 0x42, 0x38, 0xd3, - 0x86, 0x6e, 0x4b, 0x68, 0x92, 0xe2, 0xe8, 0x2a, 0x5a, 0x40, 0xbe, 0xeb, 0xf5, 0x2f, 0x8d, 0xcd, 0xfb, 0x0e, 0x9e, - 0x0d, 0x22, 0x81, 0x8d, 0xa8, 0xa9, 0x51, 0x0d, 0xab, 0xad, 0x6e, 0xda, 0x6e, 0x1e, 0xdd, 0xde, 0xc8, 0xc7, 0x50, - 0xe1, 0xe8, 0xe7, 0x40, 0x89, 0xe3, 0xde, 0x34, 0xa5, 0x4d, 0x54, 0xfe, 0x17, 0xaa, 0x05, 0x4e, 0xe1, 0x93, 0x1b, - 0x9c, 0x0a, 0x4e, 0xbb, 0xa7, 0x86, 0xe2, 0x7e, 0xbf, 0x54, 0xd1, 0xf5, 0x71, 0x73, 0x95, 0x01, 0x9a, 0xf0, 0x08, - 0x72, 0x39, 0xf2, 0xfd, 0xbc, 0xae, 0xfc, 0x22, 0xbf, 0xf4, 0xed, 0x6b, 0x47, 0xd8, 0x42, 0x8d, 0xb4, 0xd0, 0xe3, - 0x24, 0xbf, 0x2c, 0x6f, 0x92, 0xee, 0x90, 0x81, 0xeb, 0x2f, 0x6b, 0xec, 0x1d, 0xaa, 0xf2, 0xd8, 0x6d, 0x8f, 0x14, - 0x08, 0xd3, 0x49, 0x97, 0xca, 0x5d, 0x29, 0x25, 0x62, 0xd4, 0x86, 0xb3, 0x4e, 0xd5, 0xa2, 0xb6, 0xb0, 0x9e, 0x2d, - 0x74, 0x93, 0x0a, 0x08, 0xd5, 0xf7, 0x94, 0x87, 0x63, 0x60, 0xd8, 0x3b, 0x5f, 0x1e, 0x27, 0x0b, 0xe7, 0x53, 0x5d, - 0x2b, 0xe7, 0xa9, 0xb6, 0xeb, 0xbe, 0xce, 0x50, 0x60, 0x6c, 0xe9, 0x1d, 0xbb, 0x0c, 0xe7, 0xb7, 0xea, 0x0a, 0x4f, - 0x96, 0x11, 0x3c, 0x4b, 0x7d, 0x42, 0xf0, 0x55, 0xf2, 0x48, 0xe1, 0xc1, 0xd1, 0xcd, 0x59, 0x40, 0x07, 0xd3, 0x49, - 0xe0, 0xc1, 0xf1, 0xb6, 0x56, 0xc9, 0xfa, 0xe0, 0xe5, 0x98, 0x10, 0x06, 0x94, 0xac, 0x0f, 0xb6, 0xdd, 0x58, 0xb9, - 0x44, 0xe3, 0xf5, 0x23, 0x0b, 0x2d, 0xba, 0x7e, 0xd0, 0xa6, 0xe7, 0x01, 0x53, 0x39, 0xaa, 0xae, 0xe7, 0x29, 0x67, - 0x87, 0x98, 0x27, 0x8c, 0x74, 0x62, 0xd0, 0xc8, 0x0e, 0x98, 0x47, 0xa9, 0xf9, 0xa9, 0x75, 0x9b, 0x6f, 0xf6, 0xe1, - 0x33, 0x61, 0xac, 0xd5, 0x46, 0x91, 0xcf, 0x53, 0x68, 0xcf, 0x8e, 0xbc, 0xdf, 0xa8, 0x21, 0x23, 0x6b, 0xd3, 0x15, - 0x90, 0x8c, 0x05, 0x7f, 0x36, 0x43, 0x58, 0xd4, 0x4a, 0xc6, 0x69, 0x62, 0x9f, 0x4d, 0x37, 0x91, 0xae, 0xf2, 0x55, - 0x04, 0x78, 0xbf, 0xe1, 0x4c, 0x9a, 0xc7, 0x96, 0x5b, 0x8c, 0x98, 0xbc, 0xd4, 0x84, 0xda, 0xa2, 0x89, 0x28, 0x01, - 0xa0, 0xd7, 0xc3, 0x3e, 0x02, 0x95, 0xbe, 0x43, 0x38, 0x37, 0x4f, 0x6c, 0x69, 0x93, 0x9a, 0x0b, 0x0a, 0xc3, 0x1d, - 0x3b, 0xd9, 0x8b, 0x4d, 0x26, 0xf6, 0x0c, 0xe6, 0xa1, 0xc5, 0x5a, 0x76, 0xf3, 0x47, 0xb1, 0xe3, 0x07, 0x34, 0x90, - 0xf9, 0x01, 0x0b, 0x92, 0x3f, 0x96, 0x0e, 0x71, 0x2e, 0x04, 0xc5, 0x43, 0x5a, 0xc9, 0x22, 0x16, 0xa4, 0xdb, 0xf1, - 0x22, 0xce, 0x65, 0x4e, 0x6e, 0x01, 0x41, 0x75, 0x20, 0x16, 0xb2, 0xdc, 0x40, 0x1a, 0x6f, 0x70, 0xe1, 0xbc, 0xc9, - 0x89, 0x24, 0xb0, 0xf5, 0x4c, 0x24, 0x93, 0x45, 0x39, 0x16, 0x81, 0xdf, 0x7c, 0xec, 0xfe, 0x66, 0x3e, 0x36, 0x1b, - 0x7b, 0xda, 0x2c, 0xdf, 0x2c, 0xc2, 0xcc, 0xda, 0xaa, 0xc2, 0x84, 0x25, 0x92, 0x71, 0xc2, 0x5b, 0x7b, 0xf8, 0xca, - 0xad, 0xe1, 0x33, 0xf8, 0xdd, 0xcc, 0x16, 0x73, 0x69, 0x3b, 0x5b, 0x24, 0xe9, 0x20, 0x4c, 0x37, 0xe1, 0x1f, 0x62, - 0x64, 0xba, 0xd8, 0xac, 0xe8, 0x47, 0x83, 0x44, 0xf1, 0x76, 0xe3, 0xe5, 0xe1, 0xb7, 0x08, 0x0e, 0x76, 0x0b, 0xb2, - 0xb9, 0xfb, 0x72, 0xa4, 0xe2, 0x21, 0x2b, 0xaa, 0x1a, 0x63, 0x84, 0x52, 0x88, 0x63, 0x88, 0xba, 0xdc, 0xbe, 0x6a, - 0xcb, 0x43, 0xba, 0xfa, 0x5a, 0x64, 0x14, 0xde, 0xca, 0x7f, 0x63, 0xbe, 0xe3, 0x9f, 0x31, 0x95, 0xd4, 0x79, 0x0e, - 0xf0, 0xb5, 0xdf, 0xc1, 0x20, 0x21, 0x2a, 0x22, 0x7f, 0x2d, 0x11, 0x20, 0x66, 0xbd, 0xc4, 0x00, 0xee, 0xbc, 0xba, - 0x95, 0x93, 0x90, 0xbe, 0x60, 0xe8, 0x6d, 0x8b, 0x85, 0x79, 0x3c, 0x92, 0x7c, 0x87, 0xb1, 0x88, 0x9d, 0xf5, 0xc1, - 0x8c, 0x9d, 0xba, 0xe6, 0xc3, 0x74, 0xf6, 0x1f, 0x23, 0x2c, 0x70, 0x04, 0x43, 0xad, 0x85, 0x9f, 0xae, 0x02, 0xb8, - 0xd3, 0x7f, 0x08, 0x52, 0xe0, 0x36, 0x7a, 0xe2, 0x67, 0xba, 0x17, 0xd8, 0x04, 0xa7, 0x62, 0xaf, 0x88, 0xed, 0x39, - 0xd0, 0xab, 0x55, 0x0d, 0xa5, 0xbb, 0x73, 0x3a, 0x08, 0x53, 0x2c, 0x0a, 0x63, 0xbd, 0x8e, 0x12, 0x9b, 0x55, 0xcb, - 0x69, 0xc2, 0x90, 0xed, 0x2a, 0xd4, 0x9e, 0xe4, 0xc2, 0xa2, 0x84, 0x23, 0x37, 0x89, 0x37, 0xd5, 0x3a, 0xa0, 0x7e, - 0xeb, 0xd7, 0x26, 0xb8, 0xf5, 0x82, 0xa5, 0x63, 0x41, 0xa1, 0xa5, 0x88, 0xc1, 0x23, 0x44, 0x06, 0xaf, 0xcb, 0x15, - 0xe2, 0xf4, 0x22, 0xfd, 0xbe, 0x75, 0x57, 0x4a, 0x4b, 0x77, 0xb3, 0x88, 0xd9, 0xcf, 0xe9, 0xaf, 0x86, 0x97, 0xd7, - 0x9c, 0x91, 0x71, 0xd1, 0xb4, 0xe8, 0xa9, 0xd7, 0xb8, 0xdc, 0x80, 0xd9, 0x43, 0xab, 0x63, 0x86, 0xfd, 0x33, 0x2d, - 0x2d, 0xc6, 0xf8, 0x9d, 0x28, 0xa6, 0xdd, 0xef, 0x3e, 0x75, 0xe2, 0x9e, 0x5e, 0xe8, 0xa0, 0xf7, 0x96, 0x78, 0xdb, - 0xe9, 0x9d, 0xae, 0x3e, 0x9b, 0x8e, 0x41, 0xf4, 0x8d, 0x32, 0x7d, 0x37, 0x0b, 0x5d, 0x2e, 0x63, 0xd6, 0x68, 0x93, - 0xf6, 0xe5, 0x72, 0xfa, 0xa5, 0x97, 0xb9, 0xf1, 0x6f, 0xe1, 0x7a, 0x32, 0x24, 0x92, 0x96, 0x2a, 0x95, 0x2a, 0x9c, - 0x74, 0x81, 0xc4, 0x9a, 0x89, 0x5a, 0xae, 0x51, 0x67, 0x1c, 0x0f, 0x97, 0x0e, 0xcb, 0xef, 0x9b, 0x0f, 0x2a, 0xbd, - 0x7c, 0x1f, 0x88, 0x7d, 0x76, 0x25, 0x19, 0x50, 0x4e, 0xe1, 0x8c, 0xec, 0xfe, 0x73, 0x58, 0xed, 0x0a, 0xa0, 0x66, - 0x18, 0xbd, 0x5c, 0x1a, 0x76, 0x50, 0x94, 0x7e, 0x3a, 0xe9, 0xa6, 0x20, 0xac, 0xaf, 0xce, 0xc2, 0xeb, 0x5a, 0x92, - 0xe8, 0x12, 0x7f, 0x25, 0xdd, 0x4f, 0x38, 0xc9, 0xbe, 0x43, 0x7d, 0x55, 0x97, 0x00, 0xd0, 0x21, 0x5e, 0xa9, 0x40, - 0x9a, 0x79, 0x4b, 0xba, 0x4a, 0x64, 0x5d, 0x7c, 0x48, 0x01, 0x5c, 0x59, 0x6f, 0x9f, 0x66, 0x21, 0x5d, 0x6b, 0x89, - 0x9d, 0x84, 0x6e, 0xb8, 0x9f, 0x30, 0x02, 0x24, 0xd8, 0xf1, 0x00, 0x9a, 0xbc, 0x13, 0x9e, 0x63, 0xbd, 0x9a, 0x58, - 0x83, 0x20, 0xa2, 0x7b, 0x2f, 0xc1, 0x6e, 0x4e, 0xf3, 0xac, 0xb0, 0x09, 0xd1, 0xec, 0xc8, 0x7d, 0x3f, 0x39, 0xf0, - 0x7a, 0x61, 0x53, 0xb1, 0x51, 0x99, 0x3a, 0xb9, 0xc5, 0x38, 0xc0, 0x3e, 0x2d, 0x05, 0xd4, 0x70, 0x15, 0xa5, 0x2c, - 0xa7, 0x29, 0xa1, 0xc5, 0x38, 0xe0, 0xf4, 0x25, 0x07, 0xff, 0x27, 0x82, 0x26, 0x64, 0x1d, 0x7e, 0xfc, 0xb1, 0x05, - 0x7f, 0x24, 0xad, 0x69, 0x56, 0x44, 0xab, 0x3d, 0xc5, 0x1a, 0x34, 0x2f, 0x93, 0x8f, 0x0d, 0x03, 0xd8, 0xbc, 0x16, - 0xb2, 0xfa, 0x89, 0x9b, 0x56, 0x3c, 0x50, 0x7e, 0xca, 0x41, 0xed, 0xa9, 0x35, 0xf6, 0x42, 0xb2, 0xd3, 0xac, 0xa8, - 0x88, 0xe2, 0x7a, 0xb2, 0x5d, 0x17, 0xef, 0xbe, 0x48, 0x54, 0xfc, 0xe9, 0x06, 0x62, 0x48, 0x40, 0x02, 0x83, 0x15, - 0xd4, 0x90, 0xd0, 0x51, 0x5f, 0x6f, 0xbe, 0xbc, 0xd5, 0x20, 0xd0, 0x7c, 0xe9, 0x14, 0x10, 0x33, 0x15, 0xb3, 0xf3, - 0x21, 0xa0, 0x8a, 0xf7, 0x6f, 0x30, 0x69, 0x36, 0x7e, 0xb7, 0x8e, 0x6b, 0x5d, 0x38, 0xff, 0x51, 0xab, 0x66, 0xc0, - 0x86, 0xb8, 0xa0, 0x4a, 0xd1, 0xb0, 0xca, 0x58, 0x20, 0x1a, 0x3d, 0x7d, 0x1c, 0x59, 0x0a, 0xfb, 0xe7, 0xe6, 0xcb, - 0x67, 0xad, 0x4e, 0x6d, 0x5e, 0xcd, 0x5c, 0x4a, 0xa2, 0xe0, 0x32, 0x7d, 0xc3, 0x57, 0x00, 0x20, 0x33, 0x6b, 0x10, - 0x14, 0x34, 0xf8, 0x1a, 0x7c, 0x6e, 0x45, 0xc8, 0x38, 0xd0, 0xfd, 0x90, 0xf1, 0x87, 0x9b, 0xf6, 0x8a, 0xde, 0xd2, - 0xca, 0x7c, 0x4b, 0xaf, 0xf7, 0xb4, 0xd5, 0xf5, 0x4b, 0x8b, 0x19, 0x75, 0xa9, 0x5a, 0x9e, 0x7e, 0xde, 0xee, 0x7b, - 0xe2, 0xd6, 0xda, 0x9f, 0x8a, 0x32, 0xb6, 0x27, 0xe5, 0xa0, 0x31, 0x37, 0xfe, 0x05, 0xea, 0x35, 0x0d, 0x8d, 0x8a, - 0x42, 0x79, 0x5b, 0xf7, 0xad, 0x50, 0xe6, 0xed, 0x89, 0x8c, 0x23, 0xa9, 0x3b, 0x86, 0xbc, 0x2f, 0x6d, 0xe3, 0xf3, - 0x9a, 0x22, 0x50, 0xf8, 0x95, 0xe9, 0x94, 0x02, 0x5d, 0x13, 0x2e, 0x11, 0x3c, 0xb4, 0xbc, 0x2e, 0xdd, 0x98, 0x41, - 0xe5, 0xe8, 0x03, 0xbd, 0xa5, 0x0d, 0xc1, 0x8f, 0x8b, 0xf0, 0x8b, 0x9d, 0xd0, 0x4c, 0xae, 0x02, 0x35, 0x13, 0x55, - 0xf6, 0x90, 0xac, 0x0c, 0x96, 0x13, 0xa9, 0x49, 0xdf, 0xd4, 0x99, 0x40, 0x83, 0xa9, 0x57, 0x3e, 0xeb, 0x82, 0xa1, - 0x8b, 0x5d, 0x69, 0x61, 0x60, 0x11, 0x26, 0x5f, 0x84, 0x5f, 0x1f, 0x7d, 0x2d, 0x8d, 0x16, 0x18, 0x02, 0x84, 0xe6, - 0x5e, 0x5e, 0x34, 0x0a, 0xb6, 0xbf, 0xbb, 0x69, 0xaf, 0x57, 0x78, 0xf0, 0xed, 0x83, 0x79, 0x89, 0xc5, 0x81, 0x9e, - 0x9b, 0xfc, 0x71, 0x27, 0xed, 0x44, 0x41, 0x48, 0x6d, 0x2e, 0x70, 0x08, 0x50, 0xd5, 0xec, 0x21, 0xce, 0x56, 0x29, - 0x3b, 0x71, 0x04, 0x64, 0xf9, 0x6d, 0x04, 0xbe, 0x7c, 0xb7, 0xc6, 0xde, 0x63, 0x91, 0xb9, 0x28, 0xed, 0xf1, 0xb7, - 0xbb, 0x0b, 0xab, 0xbb, 0x79, 0x78, 0x2c, 0x28, 0xec, 0xfc, 0xe1, 0x3c, 0xee, 0xeb, 0xba, 0x7b, 0x00, 0x98, 0x81, - 0xf0, 0x71, 0x21, 0x1c, 0x02, 0xd1, 0x4c, 0x37, 0xeb, 0xf6, 0xa3, 0x4a, 0xaa, 0x8a, 0xa7, 0x00, 0x27, 0x1c, 0x02, - 0xef, 0x4c, 0x3d, 0x36, 0x4b, 0xb0, 0xd9, 0x0e, 0xc0, 0x10, 0x4a, 0xd3, 0x1c, 0x37, 0xe5, 0x06, 0xc8, 0x77, 0x11, - 0xc3, 0x14, 0xf7, 0x62, 0x8f, 0x86, 0x0f, 0x28, 0x8a, 0x68, 0xe9, 0xbc, 0x20, 0xdf, 0x76, 0x11, 0xcb, 0x9d, 0x27, - 0xa3, 0x0c, 0x3e, 0x11, 0xf9, 0x16, 0x29, 0x64, 0xee, 0x47, 0x9a, 0xc2, 0x6a, 0x9b, 0xd6, 0x8f, 0x01, 0x91, 0x5b, - 0x5a, 0x37, 0x26, 0x5a, 0x03, 0x17, 0x7a, 0x13, 0xf9, 0x02, 0x5a, 0xdb, 0x2a, 0x76, 0x9f, 0x5f, 0x89, 0x64, 0xf0, - 0x40, 0x98, 0x7f, 0xe3, 0xe1, 0xad, 0xd1, 0x31, 0xa5, 0x66, 0x76, 0x49, 0xfb, 0xe3, 0xbd, 0xb5, 0x97, 0xad, 0xfb, - 0xd6, 0xbb, 0x6a, 0x4d, 0x9e, 0xd3, 0x21, 0x95, 0xd8, 0x49, 0x05, 0x50, 0x04, 0x1f, 0x5b, 0x3e, 0x3f, 0x07, 0xa8, - 0x13, 0x05, 0x5c, 0xa8, 0x72, 0xe2, 0xcc, 0x38, 0xcc, 0xf2, 0x2b, 0x69, 0x73, 0x70, 0xfb, 0x79, 0x93, 0x62, 0x20, - 0x84, 0x42, 0x07, 0x64, 0xea, 0x0d, 0x4e, 0x6a, 0x6b, 0xda, 0x02, 0x8b, 0x39, 0x2c, 0x10, 0x39, 0x82, 0x00, 0xe4, - 0x10, 0xe9, 0x5a, 0xa5, 0xfb, 0x78, 0xd0, 0x0d, 0x28, 0x6f, 0x04, 0x66, 0xa4, 0x3f, 0x80, 0xd8, 0xb1, 0xb6, 0x73, - 0x95, 0x88, 0x30, 0x89, 0x34, 0x16, 0x1e, 0xfe, 0x25, 0x53, 0x52, 0x3e, 0x62, 0xb1, 0x1b, 0x82, 0x69, 0x31, 0xaf, - 0x48, 0x0e, 0x29, 0x48, 0x17, 0xea, 0xea, 0x5b, 0x8e, 0xc9, 0x39, 0xcd, 0x32, 0x14, 0xa6, 0x48, 0x18, 0x39, 0x9b, - 0x36, 0x13, 0x59, 0x40, 0x33, 0x56, 0x45, 0xa0, 0x5c, 0x91, 0xf5, 0xa8, 0x92, 0x3f, 0x72, 0xfe, 0x4d, 0x58, 0x05, - 0x97, 0x63, 0xc7, 0xba, 0x61, 0x9d, 0x9d, 0x17, 0x95, 0x69, 0x99, 0x7c, 0x5b, 0x96, 0x24, 0x5e, 0xc2, 0x63, 0x21, - 0xde, 0x2f, 0xfa, 0x6d, 0xf5, 0x14, 0xfa, 0xe5, 0xae, 0x1d, 0x42, 0x85, 0x54, 0x0c, 0x6a, 0x09, 0x13, 0x45, 0x8b, - 0xd2, 0xf8, 0xbd, 0x00, 0x5b, 0x1e, 0x03, 0xda, 0x58, 0xfa, 0xc1, 0x4a, 0x5c, 0x95, 0x23, 0x6a, 0x59, 0xbd, 0x95, - 0xa2, 0x93, 0xcb, 0xca, 0x32, 0xda, 0x22, 0x92, 0x80, 0x00, 0xe7, 0x2b, 0x65, 0x35, 0xbf, 0xe4, 0x3a, 0xac, 0x5b, - 0xbf, 0xb2, 0x54, 0x2a, 0x4c, 0xd1, 0x62, 0xb0, 0x8c, 0x08, 0xe3, 0x36, 0xd7, 0xba, 0x38, 0x7e, 0xd7, 0xfc, 0x0d, - 0xe8, 0xb7, 0x70, 0x97, 0xbb, 0x6a, 0x05, 0x6e, 0x5e, 0x44, 0x74, 0x41, 0x2e, 0x03, 0xb9, 0x0b, 0xaa, 0x37, 0x68, - 0xc1, 0x96, 0xac, 0xb7, 0xe6, 0x32, 0x2f, 0x0f, 0x7d, 0x15, 0x83, 0x3c, 0x7d, 0xa8, 0x68, 0x75, 0xa8, 0xf5, 0x71, - 0x6f, 0xff, 0x69, 0xaf, 0xda, 0x69, 0x40, 0x07, 0xe4, 0xbe, 0xd6, 0xf1, 0x75, 0x97, 0xff, 0xf9, 0x87, 0xdb, 0x22, - 0x91, 0xfb, 0x25, 0x75, 0x03, 0x1d, 0x82, 0xd2, 0x81, 0x60, 0x3b, 0x5e, 0x5a, 0x7e, 0x72, 0xd0, 0x0b, 0x6b, 0x42, - 0x2d, 0xbc, 0x29, 0x4f, 0x83, 0x11, 0x21, 0x94, 0x92, 0x58, 0xe7, 0xb4, 0xd9, 0xc3, 0x82, 0x3e, 0xdc, 0xe1, 0xac, - 0x36, 0xa6, 0x3f, 0x21, 0xaa, 0x4c, 0xb4, 0x07, 0x76, 0x17, 0x4d, 0x6c, 0x78, 0xd8, 0x0f, 0x4a, 0x52, 0x42, 0xb5, - 0xaf, 0xe8, 0x03, 0x65, 0x62, 0x8e, 0x2f, 0x3b, 0x14, 0xfc, 0x55, 0x6a, 0x89, 0x4d, 0x0c, 0xf6, 0x1d, 0x87, 0x25, - 0x51, 0x31, 0x80, 0xcd, 0x65, 0x8c, 0x59, 0x5f, 0x60, 0x8b, 0xd8, 0x9f, 0x56, 0x03, 0x65, 0xbf, 0x5b, 0xf7, 0x7d, - 0x67, 0x05, 0x50, 0xe6, 0x9a, 0x9f, 0xf4, 0x7b, 0xe4, 0x7b, 0xb0, 0xa8, 0x5f, 0x87, 0xa0, 0x45, 0xd7, 0xb5, 0x35, - 0x71, 0xe6, 0xb3, 0x74, 0xcf, 0x0d, 0x17, 0xfe, 0xbe, 0x2a, 0x90, 0x09, 0xd2, 0x74, 0xa8, 0x62, 0x33, 0x2e, 0xca, - 0x28, 0xb6, 0x0c, 0xf7, 0xc2, 0xef, 0xa4, 0x20, 0x42, 0x84, 0x8c, 0x61, 0x5a, 0x22, 0xe8, 0xd4, 0x7c, 0x9e, 0x36, - 0x02, 0xd5, 0x35, 0x29, 0x73, 0x4f, 0x97, 0x3b, 0xe2, 0x41, 0x89, 0x1e, 0x59, 0x02, 0xf4, 0x7f, 0xab, 0xe7, 0x1a, - 0xb7, 0x9c, 0x11, 0xa4, 0x59, 0x10, 0x19, 0x9c, 0xc1, 0x71, 0x8e, 0x1b, 0x2d, 0x24, 0x48, 0x14, 0x77, 0x27, 0xa1, - 0x4f, 0xda, 0x38, 0x35, 0xf8, 0x05, 0xb9, 0x28, 0x37, 0x2a, 0x00, 0xb5, 0x7b, 0x88, 0x16, 0x05, 0x73, 0x66, 0xc8, - 0x8e, 0xbc, 0x87, 0x18, 0x1e, 0xda, 0x52, 0x69, 0x1e, 0x73, 0x72, 0x02, 0x51, 0x73, 0x99, 0x27, 0x35, 0xf6, 0x0a, - 0xfa, 0x06, 0x14, 0xa7, 0xd0, 0xc6, 0x98, 0x38, 0x5d, 0x9e, 0xfa, 0x54, 0x0d, 0x44, 0xe9, 0xd9, 0x7c, 0x5d, 0xac, - 0x23, 0x76, 0xc0, 0x2e, 0x34, 0x63, 0x0c, 0x7e, 0x23, 0x94, 0x02, 0x0e, 0x32, 0x9f, 0x08, 0x3a, 0xf2, 0x83, 0x81, - 0x93, 0x19, 0xe3, 0x5d, 0xd6, 0x84, 0x03, 0x3d, 0x94, 0x52, 0x7d, 0x01, 0x9b, 0x21, 0x04, 0xe8, 0xaf, 0xc4, 0x7b, - 0x67, 0xad, 0x9e, 0x51, 0x89, 0x17, 0x13, 0x39, 0x28, 0xc2, 0x84, 0x87, 0x48, 0x8d, 0x28, 0x74, 0x24, 0xda, 0x43, - 0x05, 0xb3, 0xec, 0x6c, 0x5b, 0x53, 0xde, 0x17, 0x75, 0xea, 0x34, 0x07, 0xbf, 0xbe, 0x17, 0x6f, 0xe4, 0xea, 0x31, - 0xa0, 0xc7, 0xbe, 0x6e, 0x09, 0xd9, 0xbd, 0x53, 0x40, 0x80, 0x7c, 0xb1, 0x43, 0xc6, 0x84, 0xe8, 0x58, 0xd3, 0x92, - 0xaa, 0xd9, 0x47, 0x8b, 0xd0, 0x5f, 0xae, 0x8f, 0x33, 0x2c, 0x13, 0x42, 0x6d, 0x61, 0x02, 0x88, 0xd0, 0x93, 0x4e, - 0x09, 0x96, 0xe4, 0x3e, 0x78, 0xd9, 0xb0, 0xc3, 0xc1, 0x76, 0x55, 0x0c, 0x4f, 0x0e, 0x3f, 0x0f, 0x81, 0xed, 0x98, - 0x80, 0x4e, 0xb3, 0x14, 0x0a, 0xb1, 0xe1, 0x3e, 0x56, 0x33, 0x49, 0x05, 0x31, 0x4d, 0x54, 0x3e, 0xe0, 0x0f, 0x6a, - 0x23, 0x6e, 0xd2, 0x8e, 0xe2, 0xdd, 0x08, 0x7b, 0x89, 0x43, 0x37, 0x84, 0xeb, 0x80, 0xa8, 0xd1, 0x3e, 0x97, 0x35, - 0x37, 0xa2, 0xcd, 0x33, 0x32, 0x70, 0x89, 0xd4, 0x5f, 0xa1, 0x75, 0x50, 0x69, 0x41, 0x3d, 0x8b, 0xdf, 0x02, 0x3c, - 0xb7, 0x86, 0x96, 0xfb, 0x15, 0x92, 0xb8, 0x53, 0x8c, 0x66, 0xb4, 0x47, 0x78, 0x99, 0xee, 0x10, 0xe0, 0xde, 0x6a, - 0xdd, 0x69, 0xba, 0x1e, 0xa0, 0x8c, 0x9d, 0xb8, 0xe9, 0xb6, 0xca, 0x49, 0x1a, 0x03, 0x6a, 0xcc, 0xbf, 0x47, 0xef, - 0x07, 0xdf, 0x73, 0xa4, 0xe3, 0x76, 0x59, 0xe8, 0x5a, 0xa1, 0xf9, 0xf4, 0x39, 0xd9, 0x69, 0xe9, 0x16, 0xf7, 0x26, - 0x11, 0xea, 0xf0, 0x11, 0x5e, 0x30, 0x17, 0x4a, 0x77, 0x5c, 0xd4, 0xbd, 0xf9, 0xc9, 0xc2, 0x4d, 0x51, 0x53, 0x98, - 0x42, 0xc9, 0x66, 0xc3, 0x2b, 0x89, 0x59, 0xa0, 0xb9, 0x5c, 0x29, 0x84, 0x96, 0xf7, 0x40, 0xed, 0x35, 0x24, 0x6e, - 0xad, 0xd7, 0x16, 0x6e, 0xd3, 0x45, 0x6b, 0x35, 0x59, 0xd0, 0xc6, 0x48, 0xca, 0x98, 0x39, 0x74, 0x56, 0x64, 0xba, - 0x2a, 0x0a, 0x86, 0x35, 0xb5, 0x5e, 0x5d, 0x3b, 0x7e, 0x7e, 0x69, 0x7a, 0x08, 0x13, 0x0e, 0xac, 0x56, 0xd0, 0x3b, - 0xec, 0x34, 0x7f, 0x7a, 0xe1, 0x6a, 0x0b, 0x83, 0x44, 0x01, 0x01, 0x5d, 0x72, 0xf4, 0x3e, 0x96, 0x9e, 0xa2, 0x20, - 0x52, 0xa7, 0xab, 0xae, 0x32, 0x12, 0x82, 0x95, 0x8a, 0xff, 0x76, 0x60, 0x42, 0x8e, 0x70, 0x8e, 0xc8, 0xed, 0x75, - 0x25, 0xe7, 0xc7, 0x03, 0xd2, 0xd3, 0x11, 0x91, 0xd0, 0xd3, 0x1b, 0x43, 0x70, 0x39, 0x68, 0xec, 0xef, 0x02, 0xae, - 0xf0, 0x01, 0x86, 0xaf, 0x87, 0xae, 0x94, 0x1b, 0x2c, 0xec, 0xfb, 0x02, 0x69, 0xca, 0x45, 0x04, 0x07, 0xaa, 0x1d, - 0xf9, 0x9c, 0x1d, 0xf9, 0xad, 0x79, 0x15, 0x38, 0x37, 0x27, 0xbb, 0x46, 0x11, 0xca, 0x14, 0xbb, 0xb7, 0x03, 0x23, - 0x51, 0x92, 0xf0, 0xbb, 0x43, 0x42, 0x6b, 0xad, 0xf3, 0x3b, 0xee, 0x07, 0xbc, 0x28, 0x22, 0xf9, 0x07, 0xb1, 0x79, - 0x4f, 0x93, 0xf3, 0xf2, 0x1a, 0x5b, 0xb7, 0x15, 0x23, 0x00, 0xcd, 0x4d, 0xe6, 0x6d, 0x95, 0xc1, 0x0d, 0x56, 0x06, - 0x79, 0xb2, 0x24, 0x18, 0xcf, 0x52, 0x0d, 0xe6, 0xd9, 0xb1, 0x93, 0x96, 0x05, 0x0b, 0x81, 0x22, 0xd7, 0xd4, 0x66, - 0x75, 0x12, 0x57, 0xb4, 0x63, 0xf7, 0x5b, 0xb6, 0xc0, 0x09, 0x48, 0x3d, 0x71, 0xb2, 0xb4, 0x0d, 0x3e, 0x50, 0x48, - 0x76, 0x67, 0x19, 0x06, 0xd9, 0x85, 0xff, 0x2a, 0xe8, 0x07, 0x54, 0x57, 0x21, 0x54, 0xa4, 0x4d, 0x6c, 0x95, 0x94, - 0x22, 0x6b, 0x84, 0xd6, 0xd9, 0x16, 0x64, 0xc5, 0xd9, 0x1e, 0xf1, 0xa8, 0x99, 0xc0, 0x83, 0xc9, 0x6d, 0x91, 0xcd, - 0x19, 0xee, 0x89, 0x40, 0xc7, 0xa6, 0x50, 0x66, 0xda, 0x84, 0x6d, 0xdc, 0x93, 0xcd, 0xda, 0xbb, 0xad, 0xa8, 0x19, - 0x34, 0xa2, 0x6f, 0x69, 0x9a, 0xfd, 0x7b, 0x7d, 0xf0, 0x59, 0x89, 0xbe, 0x91, 0x43, 0x4c, 0xd7, 0x6d, 0xa4, 0x49, - 0x95, 0x5a, 0xe2, 0xd7, 0x6d, 0x3e, 0xbd, 0xa7, 0xa1, 0x1c, 0x52, 0x00, 0x27, 0x94, 0x02, 0x33, 0xe4, 0x73, 0x0c, - 0xc1, 0x9d, 0x82, 0x6d, 0x24, 0xcb, 0xad, 0xc8, 0x65, 0xd6, 0x58, 0xdd, 0xf1, 0x0f, 0x16, 0x80, 0x42, 0x5f, 0xde, - 0xa1, 0xa0, 0x1f, 0x6b, 0xbd, 0x4f, 0xd4, 0x91, 0x12, 0x93, 0xe2, 0xd3, 0xa5, 0x9b, 0xac, 0x02, 0x6a, 0xae, 0x5e, - 0x17, 0x0d, 0xe8, 0x35, 0x61, 0x00, 0xa1, 0x47, 0x74, 0xd8, 0x42, 0x18, 0xfd, 0xd1, 0x14, 0xc2, 0x7a, 0x5f, 0xc5, - 0x6d, 0xb7, 0x29, 0xba, 0xa7, 0xb3, 0x3b, 0x46, 0x6a, 0x90, 0x99, 0x56, 0x34, 0xc7, 0x70, 0x7a, 0xc0, 0x9d, 0xe2, - 0xb1, 0x63, 0x81, 0xcd, 0x26, 0xd5, 0x63, 0x8c, 0x01, 0x8e, 0xcc, 0x58, 0x6c, 0x53, 0x69, 0xad, 0x8c, 0x91, 0xda, - 0x16, 0xfd, 0xb2, 0xe6, 0x4e, 0x51, 0xdc, 0xfe, 0x08, 0x80, 0x79, 0x6e, 0x32, 0xad, 0xa3, 0x98, 0xa2, 0x46, 0x49, - 0xdb, 0xc5, 0xf1, 0x52, 0x54, 0x5e, 0x7c, 0x22, 0x70, 0x6f, 0x84, 0xca, 0x95, 0xa3, 0x03, 0xab, 0x33, 0xa5, 0x1f, - 0x6e, 0xf1, 0x98, 0x39, 0x89, 0x78, 0x01, 0xa3, 0xcf, 0x98, 0x0d, 0xe7, 0x0b, 0xef, 0x88, 0xb9, 0x45, 0x4e, 0xe1, - 0x5d, 0xf1, 0x56, 0xf8, 0xa5, 0x0b, 0xa8, 0xee, 0x41, 0x9c, 0xee, 0x54, 0xd6, 0x7a, 0x9d, 0x11, 0x21, 0xe1, 0x3b, - 0x92, 0xec, 0x95, 0x8c, 0x9d, 0xf8, 0x2c, 0x32, 0x3d, 0x38, 0x86, 0x85, 0x67, 0x8c, 0xe4, 0xf6, 0x99, 0x3a, 0x9a, - 0xb3, 0xc7, 0x3a, 0xd7, 0x45, 0x77, 0x5e, 0x7b, 0x6f, 0x2b, 0xd2, 0x53, 0x33, 0x9b, 0x4e, 0xbc, 0x69, 0x80, 0x3a, - 0x1f, 0xbc, 0xf6, 0x48, 0xe7, 0x7c, 0x07, 0x47, 0x71, 0x28, 0x5c, 0xb7, 0x6a, 0xf4, 0xd9, 0xf5, 0x1e, 0x72, 0x35, - 0x6c, 0xba, 0x8b, 0xc7, 0x65, 0x8f, 0x26, 0x7f, 0xb1, 0x22, 0x10, 0xfb, 0x18, 0x1e, 0x9f, 0xd3, 0xe0, 0xd6, 0xda, - 0xce, 0xb4, 0xd5, 0x36, 0x02, 0xd5, 0xa6, 0xa9, 0x05, 0x7e, 0xd2, 0xd5, 0x71, 0x3e, 0x71, 0xbc, 0xbc, 0x6b, 0xe0, - 0x4b, 0xfc, 0x02, 0x84, 0x55, 0xe9, 0xf5, 0xee, 0xf1, 0x1d, 0x67, 0x99, 0x2d, 0x73, 0xaf, 0x01, 0x59, 0x0e, 0x73, - 0x9d, 0xc5, 0xf1, 0xae, 0x3a, 0x22, 0x95, 0xda, 0xbe, 0xf2, 0xbf, 0x33, 0xe3, 0x42, 0x97, 0x1d, 0x41, 0x1c, 0xc8, - 0x15, 0x39, 0x53, 0x2a, 0xac, 0xc2, 0x69, 0x69, 0x4d, 0x43, 0xe3, 0x3a, 0x14, 0x04, 0x64, 0xf8, 0x7f, 0x20, 0x1c, - 0x44, 0xe6, 0xad, 0x13, 0x92, 0xaa, 0x6a, 0x03, 0x6b, 0xb4, 0x17, 0x7b, 0x01, 0x52, 0x78, 0x28, 0x92, 0xad, 0x2f, - 0xda, 0xaf, 0x4b, 0x64, 0x21, 0x03, 0xc1, 0x28, 0x93, 0x24, 0xc0, 0xd6, 0xd1, 0xad, 0x9e, 0xee, 0x92, 0x5e, 0x26, - 0xa0, 0xef, 0xf4, 0x3c, 0xfe, 0x10, 0x87, 0xa2, 0xac, 0x39, 0x7f, 0x6e, 0x49, 0xb6, 0xf3, 0xe8, 0xae, 0x6a, 0xac, - 0x43, 0x2c, 0x36, 0x97, 0x1c, 0x1d, 0xe7, 0x45, 0x81, 0xb3, 0x0c, 0x7d, 0x07, 0x8c, 0x85, 0x77, 0x36, 0x0c, 0xd5, - 0x5c, 0x48, 0x35, 0x7d, 0xc5, 0xa7, 0x70, 0x1d, 0x1e, 0x52, 0x4a, 0xdb, 0x16, 0xeb, 0xc1, 0x72, 0x88, 0x97, 0xdc, - 0x50, 0xa1, 0x71, 0xb5, 0x34, 0x9b, 0xd4, 0x73, 0x98, 0xc6, 0x8a, 0x2f, 0xd0, 0xa4, 0xdc, 0x45, 0xc5, 0x53, 0x07, - 0x53, 0x87, 0x6e, 0x52, 0x88, 0x7e, 0x3a, 0x32, 0x27, 0x92, 0x34, 0xe9, 0xc7, 0xb6, 0x51, 0x05, 0x01, 0xd0, 0xd1, - 0x5a, 0x16, 0xb4, 0xfb, 0xde, 0xaf, 0x7e, 0x65, 0xa3, 0x4d, 0x8f, 0x1a, 0x92, 0xb9, 0xd6, 0xe1, 0xd6, 0xd7, 0x72, - 0x7c, 0x77, 0x45, 0x18, 0xcd, 0xdb, 0x03, 0xab, 0xc2, 0xb9, 0x88, 0x14, 0xe3, 0x16, 0xad, 0x20, 0x61, 0x1e, 0x20, - 0xc7, 0xbb, 0x61, 0xda, 0x9f, 0x2b, 0x93, 0xa3, 0xf3, 0x3c, 0x3c, 0x6f, 0xae, 0x58, 0x68, 0x45, 0x2f, 0xce, 0xb1, - 0xdf, 0xb8, 0xf7, 0xbd, 0x8c, 0xa9, 0xe7, 0x61, 0xe3, 0xdd, 0x28, 0x4f, 0x4f, 0x30, 0x3a, 0x3f, 0x44, 0x37, 0x77, - 0xa4, 0xaf, 0xec, 0x02, 0xf4, 0x7a, 0x4f, 0x8e, 0xef, 0x67, 0xdf, 0x8b, 0x8e, 0x33, 0xb8, 0x30, 0xd2, 0x28, 0xce, - 0x17, 0x84, 0x96, 0x98, 0xa3, 0x34, 0xe3, 0x45, 0x3d, 0x11, 0x8e, 0x78, 0x79, 0x0a, 0x76, 0x2c, 0xec, 0xa6, 0x3f, - 0x17, 0xbe, 0xb0, 0xf0, 0xd7, 0xe9, 0x4c, 0xe0, 0x71, 0xff, 0x6f, 0x93, 0xfd, 0x82, 0x44, 0x22, 0x7a, 0x18, 0x47, - 0x7a, 0x6c, 0xcb, 0x42, 0xef, 0x99, 0xd8, 0x22, 0xf5, 0xfa, 0xfd, 0x84, 0x50, 0xea, 0x86, 0x52, 0xea, 0x0e, 0xca, - 0x64, 0x59, 0x02, 0x1b, 0x37, 0x85, 0x10, 0x72, 0xfc, 0x33, 0x6e, 0x9e, 0x22, 0x7c, 0xd6, 0x88, 0xd2, 0xac, 0xa6, - 0xa6, 0xe0, 0xce, 0x60, 0x00, 0x56, 0xe2, 0x04, 0x07, 0x88, 0xf2, 0xa1, 0x2e, 0xbc, 0xc2, 0xc4, 0x6a, 0x55, 0x56, - 0x02, 0xb5, 0xc2, 0x50, 0x82, 0x08, 0x4e, 0x68, 0x2f, 0x22, 0xac, 0xeb, 0x98, 0x94, 0x7b, 0xb0, 0x45, 0x3b, 0xb7, - 0xf0, 0xba, 0xdb, 0xc2, 0xca, 0xc3, 0x7b, 0x35, 0xeb, 0xb1, 0x2b, 0xbb, 0xe3, 0x01, 0x72, 0x94, 0x9c, 0xfd, 0x04, - 0x88, 0xe0, 0x41, 0x12, 0xd8, 0xea, 0xad, 0x3d, 0x6c, 0xed, 0x0e, 0xa1, 0xdf, 0x16, 0xf8, 0x74, 0x07, 0xcc, 0x46, - 0x69, 0x37, 0xfb, 0xfc, 0xa7, 0x0e, 0x0e, 0x4b, 0x6f, 0x02, 0x7c, 0x9d, 0xea, 0x4e, 0xd6, 0x74, 0x1b, 0xb8, 0xc7, - 0x3f, 0x7b, 0xe8, 0x8a, 0x44, 0x3a, 0x62, 0x16, 0xb7, 0x38, 0xaa, 0xcb, 0xce, 0xea, 0xae, 0x91, 0x73, 0x5b, 0x12, - 0x57, 0xa5, 0x84, 0xec, 0x72, 0x44, 0xa5, 0x24, 0x7b, 0x44, 0x19, 0x9c, 0xf6, 0xf6, 0xf2, 0xdc, 0x98, 0x7b, 0x18, - 0x67, 0x01, 0xa8, 0x09, 0x58, 0x2e, 0xc8, 0xc6, 0x3b, 0x01, 0x80, 0x51, 0x5a, 0x35, 0x75, 0x46, 0xef, 0xe2, 0x56, - 0x5d, 0x6f, 0x1e, 0x64, 0x46, 0x33, 0x51, 0x33, 0xb9, 0x3b, 0xa0, 0x8a, 0xd1, 0xc2, 0x20, 0xfb, 0xa5, 0x54, 0x7c, - 0x5a, 0x95, 0x68, 0xa5, 0x43, 0xcd, 0x68, 0xbf, 0xfb, 0x34, 0xd0, 0x51, 0x22, 0xb6, 0x5c, 0x4c, 0xbb, 0xf2, 0x76, - 0x98, 0x78, 0x1a, 0xd8, 0x2a, 0x33, 0x22, 0x4d, 0xd9, 0xc2, 0xcb, 0x11, 0x49, 0x7e, 0xd4, 0x5d, 0xb3, 0x6a, 0x52, - 0x1b, 0x67, 0x2d, 0x3c, 0xdd, 0x52, 0xe4, 0x14, 0x0a, 0x2e, 0xda, 0xee, 0x83, 0x0c, 0x82, 0x69, 0xd3, 0xc6, 0x59, - 0x6f, 0xbb, 0x2f, 0xa2, 0x8e, 0x57, 0x74, 0x5c, 0x24, 0x6c, 0x6e, 0xf7, 0x14, 0x65, 0x07, 0x89, 0xf2, 0x24, 0x26, - 0xd3, 0x91, 0x03, 0x95, 0xb4, 0xa1, 0xd4, 0xd2, 0x7b, 0xc9, 0x8a, 0x8b, 0xb8, 0xf8, 0xbf, 0xca, 0xb2, 0xad, 0x2f, - 0xbe, 0x48, 0xb0, 0xa0, 0x83, 0x39, 0xa2, 0xc0, 0x3c, 0x97, 0xd2, 0x41, 0x89, 0x44, 0x11, 0xf9, 0x49, 0xc1, 0xec, - 0xaa, 0x64, 0x0d, 0x3e, 0x68, 0xa5, 0x3b, 0x93, 0x49, 0x43, 0x22, 0xe5, 0x9a, 0xd4, 0xda, 0x16, 0x1b, 0x19, 0xf1, - 0xcc, 0x0f, 0x56, 0x89, 0x30, 0x12, 0x0f, 0x32, 0x25, 0x96, 0xc2, 0xb3, 0x85, 0x94, 0xf8, 0x22, 0x67, 0x9f, 0xeb, - 0xc5, 0x6e, 0xb4, 0xc8, 0x62, 0x7e, 0x98, 0xf9, 0xe5, 0x70, 0xb3, 0x5b, 0x11, 0xa3, 0xde, 0x9a, 0xb3, 0x3c, 0x2b, - 0x99, 0x8d, 0x6b, 0x47, 0x8e, 0xb9, 0x04, 0x1a, 0x29, 0x04, 0x0a, 0xe9, 0x93, 0x81, 0x53, 0x8b, 0xcb, 0x81, 0x0d, - 0x1a, 0xdf, 0xf1, 0xc9, 0xb3, 0xa5, 0xbb, 0x8b, 0xa1, 0x61, 0xdb, 0x21, 0x11, 0x44, 0x68, 0xbc, 0x21, 0xd1, 0x32, - 0x34, 0x3f, 0x78, 0x3a, 0xef, 0xcc, 0xf4, 0xea, 0x8e, 0xa4, 0x67, 0x69, 0xe1, 0x11, 0xe0, 0x7c, 0x52, 0x91, 0xe6, - 0xd6, 0x3e, 0xc9, 0x21, 0xeb, 0xfe, 0x45, 0xb3, 0x7e, 0x45, 0x00, 0x77, 0x92, 0x80, 0x10, 0xa0, 0xe1, 0x75, 0x6b, - 0x21, 0x8c, 0x25, 0xcc, 0x38, 0x84, 0xee, 0x2a, 0xf8, 0x6f, 0x12, 0xa6, 0xe7, 0xa5, 0x09, 0x8d, 0x2f, 0x4a, 0xc5, - 0x60, 0x27, 0x0b, 0x84, 0x5b, 0x40, 0x14, 0x04, 0x81, 0x20, 0x63, 0x16, 0x8a, 0xa9, 0x84, 0x76, 0xa0, 0x15, 0x14, - 0x48, 0x80, 0x89, 0x37, 0x4e, 0x85, 0x41, 0x55, 0x6d, 0xc5, 0xd3, 0x1c, 0xb3, 0xe1, 0xa4, 0x61, 0x50, 0x58, 0x7f, - 0x02, 0x5d, 0x9c, 0x62, 0x92, 0x0c, 0xfb, 0xbb, 0x78, 0xe3, 0xc9, 0xba, 0x9d, 0x89, 0x52, 0x29, 0xf6, 0x59, 0x93, - 0x27, 0x34, 0xc3, 0x79, 0x21, 0xea, 0xcb, 0xba, 0xb4, 0xee, 0x83, 0xd5, 0x74, 0x07, 0x4f, 0x9e, 0x75, 0xa4, 0xb7, - 0x71, 0x60, 0xb9, 0x83, 0x44, 0x80, 0x45, 0xda, 0x03, 0xcd, 0xc8, 0x32, 0x64, 0xa8, 0x02, 0xac, 0x35, 0xe6, 0x4e, - 0x0d, 0x6d, 0x0f, 0xe5, 0x46, 0x72, 0x6d, 0x12, 0xac, 0x1e, 0x96, 0xbe, 0xbc, 0xba, 0x6e, 0x73, 0x63, 0x00, 0xbb, - 0xef, 0xd8, 0xb2, 0xa0, 0xcb, 0x11, 0x19, 0x8e, 0x27, 0xb7, 0x09, 0xd5, 0x03, 0x14, 0x8a, 0x6a, 0xaa, 0x69, 0xed, - 0x1f, 0x7e, 0xe6, 0x9d, 0x38, 0xd4, 0x39, 0x21, 0x36, 0x2a, 0x8f, 0xd0, 0x31, 0x8f, 0x7d, 0xa2, 0xcf, 0x25, 0xef, - 0x69, 0xbe, 0x41, 0xea, 0xc8, 0xc5, 0xd5, 0x79, 0x92, 0xa8, 0x1b, 0x63, 0xb5, 0x15, 0x5b, 0x84, 0x01, 0x16, 0x73, - 0x0c, 0x87, 0xe8, 0x54, 0x70, 0xb4, 0x24, 0xbd, 0x8d, 0xa5, 0xea, 0xe5, 0xf6, 0xdb, 0xaa, 0x4b, 0x6b, 0xa7, 0x09, - 0x83, 0xe8, 0xf4, 0x90, 0x01, 0x07, 0x42, 0xc6, 0xda, 0x3e, 0x58, 0xc6, 0x71, 0x46, 0xeb, 0x32, 0x68, 0x04, 0x63, - 0xe8, 0x00, 0xe5, 0xac, 0x7a, 0x1c, 0xec, 0x04, 0x62, 0x79, 0x48, 0x6f, 0x9a, 0xcc, 0x00, 0xd9, 0x22, 0x97, 0x5f, - 0x6a, 0xa2, 0x9d, 0x85, 0x8e, 0x2d, 0xfb, 0x1e, 0xd0, 0xae, 0x03, 0x47, 0x5f, 0x07, 0x1c, 0x75, 0xe2, 0x45, 0x2d, - 0x85, 0x36, 0xc7, 0xc0, 0xb9, 0xb0, 0x38, 0xd5, 0xf3, 0x6c, 0x68, 0xc7, 0xbd, 0x03, 0xbc, 0x98, 0xd2, 0xf5, 0x02, - 0xfc, 0x76, 0x70, 0x19, 0xf8, 0xc4, 0x83, 0xdb, 0xea, 0xb0, 0x63, 0x67, 0x92, 0xc6, 0x79, 0x34, 0x75, 0x73, 0xce, - 0xb9, 0xd0, 0xe5, 0xdc, 0xff, 0x9e, 0x6e, 0xfd, 0xfe, 0x8a, 0xf1, 0x69, 0xad, 0x3d, 0x61, 0xb9, 0xca, 0x69, 0x97, - 0x45, 0x2c, 0x59, 0x71, 0x8e, 0xbe, 0x10, 0xc8, 0xd7, 0xeb, 0xfc, 0x7e, 0xa1, 0x41, 0xe7, 0xd4, 0x41, 0x74, 0x8e, - 0x71, 0xb2, 0xd3, 0x83, 0xc9, 0x7b, 0x65, 0x71, 0x68, 0xac, 0x52, 0x66, 0xf1, 0x7d, 0xe3, 0x96, 0xde, 0x9e, 0x50, - 0x76, 0x29, 0x85, 0x14, 0xca, 0xb2, 0xe1, 0xb6, 0xc7, 0x81, 0xa6, 0xed, 0x36, 0x92, 0xdd, 0xd6, 0xb7, 0xef, 0x34, - 0x89, 0x48, 0xd2, 0xdd, 0x05, 0x51, 0x78, 0x86, 0xd0, 0x18, 0x50, 0xb0, 0x37, 0xa7, 0xd6, 0xe5, 0x6b, 0x2f, 0x2b, - 0xf1, 0x8a, 0x78, 0x57, 0x0c, 0xc6, 0xca, 0x09, 0x1d, 0x2c, 0xd2, 0x34, 0x50, 0xc7, 0x4e, 0x92, 0xb8, 0x55, 0x49, - 0xfc, 0xd0, 0xf2, 0x2f, 0xa4, 0xb9, 0x51, 0x79, 0x2a, 0xe2, 0xeb, 0x10, 0x7d, 0xe6, 0xb8, 0x54, 0xf7, 0x46, 0x35, - 0x83, 0x72, 0xcc, 0x93, 0x79, 0xc3, 0x5c, 0xa6, 0xdb, 0x29, 0x32, 0x4f, 0xf6, 0xbc, 0xb9, 0x99, 0x51, 0xa2, 0x44, - 0xa4, 0x2e, 0xf4, 0x32, 0xd7, 0x56, 0xa1, 0x23, 0x8d, 0xd8, 0xb4, 0x56, 0xb3, 0x89, 0x3d, 0x0e, 0x67, 0x3f, 0x59, - 0xd9, 0x13, 0xbc, 0xeb, 0x3d, 0xef, 0xec, 0xc3, 0xe6, 0x82, 0xeb, 0xd0, 0x88, 0x21, 0x33, 0x60, 0xa6, 0x59, 0x3a, - 0x53, 0x20, 0x8b, 0xb8, 0xaf, 0xee, 0x48, 0x94, 0x31, 0xfd, 0x13, 0xab, 0x75, 0x7d, 0xad, 0x54, 0x1d, 0x93, 0x1f, - 0xbe, 0xa3, 0x6b, 0x38, 0x77, 0x50, 0x94, 0x18, 0x4e, 0x34, 0xed, 0xe6, 0x52, 0x03, 0x10, 0x7e, 0x67, 0x87, 0x51, - 0x58, 0xc1, 0xb6, 0xa8, 0xb7, 0xea, 0x2a, 0x60, 0xa0, 0x86, 0x79, 0x32, 0xf6, 0x46, 0x11, 0x19, 0xf5, 0x1b, 0x76, - 0x23, 0xaf, 0x2c, 0xba, 0x65, 0x8d, 0xcf, 0x56, 0x39, 0xa5, 0xfe, 0x48, 0x6a, 0xe5, 0x0e, 0x0b, 0xe4, 0x86, 0xeb, - 0x42, 0x21, 0xa9, 0x37, 0x1c, 0x9b, 0x6d, 0x6b, 0xe6, 0x99, 0x06, 0xba, 0x6d, 0x4d, 0xef, 0x13, 0x3b, 0x70, 0xc3, - 0x6d, 0xdd, 0x30, 0x55, 0x6d, 0x3b, 0x8f, 0x5f, 0xef, 0xd3, 0x22, 0xac, 0x09, 0x6d, 0x18, 0xc6, 0x1a, 0xd8, 0xb6, - 0x45, 0x31, 0x17, 0x83, 0x98, 0xf6, 0xd8, 0x62, 0xdf, 0x81, 0x6c, 0xdf, 0xfd, 0xb5, 0x4a, 0x42, 0x4e, 0xae, 0xd2, - 0xf9, 0x35, 0xf9, 0x49, 0x27, 0x8b, 0x44, 0x66, 0x76, 0x91, 0xbf, 0xc6, 0x95, 0xfd, 0xa3, 0x95, 0xdd, 0xab, 0x95, - 0x2e, 0x52, 0x40, 0x14, 0xa6, 0xc2, 0x73, 0x08, 0x4c, 0x97, 0xac, 0xfc, 0x1f, 0xe8, 0x38, 0x27, 0x63, 0x4a, 0x68, - 0x6f, 0x34, 0x9a, 0x40, 0x37, 0x24, 0x14, 0x43, 0x0b, 0xcb, 0xe9, 0x79, 0xa9, 0x41, 0x57, 0x3b, 0x5c, 0x47, 0x96, - 0xfb, 0x22, 0xc0, 0x4f, 0x14, 0x50, 0x67, 0x6a, 0x82, 0xdd, 0x4f, 0x02, 0x63, 0x69, 0xd6, 0x59, 0xfa, 0x45, 0x87, - 0xd3, 0x15, 0x75, 0xf7, 0xf4, 0x2b, 0x86, 0x44, 0x77, 0xf8, 0x95, 0x42, 0xeb, 0x13, 0x33, 0x73, 0x81, 0x46, 0x3a, - 0x6e, 0x60, 0x10, 0x2e, 0x6a, 0x0b, 0xfe, 0x80, 0x5c, 0xc5, 0x4d, 0xe1, 0x6e, 0x72, 0x00, 0x97, 0xca, 0x6d, 0xcb, - 0xb3, 0x4a, 0x13, 0x98, 0x7d, 0x92, 0x32, 0x3a, 0x71, 0x8c, 0xba, 0x6f, 0x77, 0x3f, 0x4a, 0x52, 0xde, 0x3e, 0x7d, - 0xf3, 0x7a, 0x95, 0x35, 0xca, 0xde, 0x33, 0xb3, 0xd4, 0x55, 0xfc, 0xa9, 0x49, 0xee, 0x6a, 0xee, 0x3b, 0xe9, 0x56, - 0x20, 0x30, 0xca, 0x79, 0x85, 0xe5, 0xce, 0xb2, 0x90, 0xc3, 0xe6, 0x5e, 0xba, 0x4f, 0x4b, 0x9a, 0xec, 0x44, 0x55, - 0x62, 0x8c, 0x49, 0xa1, 0xfd, 0xf2, 0x74, 0xee, 0x8f, 0x0e, 0xdf, 0xa3, 0xa3, 0xbe, 0x4b, 0xd3, 0x72, 0xda, 0x8a, - 0xed, 0xf2, 0xc4, 0x0e, 0xa6, 0xe1, 0x9a, 0x30, 0x2d, 0x03, 0x84, 0xee, 0xea, 0x03, 0xe8, 0x5f, 0xe2, 0x1f, 0xfa, - 0xf1, 0x9c, 0xa2, 0x0f, 0xd0, 0x83, 0xd9, 0x9a, 0xca, 0x25, 0x6a, 0x50, 0x22, 0xb2, 0x4d, 0xbb, 0x34, 0x01, 0x53, - 0xe4, 0x20, 0xdd, 0x42, 0x06, 0xa2, 0x64, 0x21, 0x98, 0x41, 0xe5, 0x17, 0xf1, 0x3a, 0xf1, 0x75, 0xbe, 0x5a, 0xf0, - 0x92, 0x9e, 0x70, 0x55, 0xc8, 0xd5, 0x0d, 0xa3, 0xc5, 0xbc, 0x3a, 0xed, 0xa4, 0xda, 0x38, 0x34, 0xa8, 0x51, 0x87, - 0x48, 0xd7, 0xf1, 0xfe, 0x6f, 0x36, 0x52, 0x37, 0x18, 0xfd, 0xe4, 0x24, 0xe0, 0xfb, 0xc6, 0x48, 0xa5, 0xb3, 0x87, - 0x38, 0xb5, 0x16, 0x3c, 0x5e, 0x28, 0x7b, 0x34, 0xea, 0x11, 0xb5, 0xc6, 0x5e, 0x0e, 0x32, 0xad, 0x0d, 0x27, 0x85, - 0xd2, 0x79, 0xb8, 0x94, 0x77, 0x49, 0xe1, 0xd2, 0x1b, 0x95, 0x88, 0xf2, 0x00, 0x76, 0xc2, 0x96, 0x8a, 0x1b, 0x95, - 0xb4, 0x80, 0xea, 0x99, 0x9e, 0x0c, 0x89, 0xe9, 0x9c, 0x44, 0x8c, 0x19, 0x9e, 0xd2, 0xcd, 0x38, 0x44, 0x6b, 0x68, - 0x86, 0x3d, 0xbd, 0x8f, 0xd5, 0x13, 0xe4, 0x80, 0x9d, 0x8d, 0xeb, 0x0c, 0x21, 0x76, 0x52, 0xe1, 0x67, 0x6a, 0x55, - 0x6c, 0x99, 0x7f, 0x24, 0xa8, 0x6d, 0xf3, 0xb6, 0x8f, 0x88, 0xf2, 0xd6, 0xd2, 0x37, 0xb9, 0xbf, 0xe2, 0xca, 0x78, - 0x25, 0x81, 0x66, 0x96, 0x97, 0xfc, 0x1c, 0xe6, 0x67, 0xbf, 0xb1, 0x03, 0x13, 0x88, 0x38, 0xdb, 0x68, 0xd4, 0x53, - 0x72, 0x34, 0xd7, 0x39, 0xef, 0x5b, 0x70, 0x46, 0xc9, 0x34, 0x10, 0x62, 0x2d, 0x8b, 0x04, 0xe2, 0xc8, 0x24, 0x71, - 0x56, 0x38, 0xeb, 0x68, 0x27, 0x8f, 0x0e, 0x7a, 0x6f, 0x22, 0xf7, 0x45, 0x4d, 0x7a, 0x06, 0xfe, 0xd8, 0x51, 0x63, - 0x31, 0x8a, 0x6e, 0x5e, 0x04, 0xea, 0xe6, 0x2c, 0x8f, 0x43, 0xbd, 0xf4, 0x66, 0xae, 0xfd, 0xd2, 0xd3, 0x5a, 0xaa, - 0x0b, 0x74, 0x71, 0xe8, 0x31, 0x6a, 0x51, 0x5e, 0x41, 0x1a, 0x4c, 0x7b, 0xa0, 0xec, 0x35, 0x4c, 0xe8, 0x01, 0xbf, - 0x54, 0x82, 0x8c, 0x06, 0xef, 0x7c, 0xb4, 0xc5, 0xc5, 0x74, 0x92, 0xf3, 0x66, 0x01, 0x05, 0xb7, 0xeb, 0x2d, 0xa9, - 0x89, 0xd0, 0x1a, 0x37, 0x28, 0x6c, 0x91, 0xf0, 0x4f, 0x34, 0x87, 0xb3, 0x2b, 0x24, 0x75, 0x88, 0x4d, 0x31, 0xc2, - 0x04, 0xb4, 0x66, 0x5c, 0x6c, 0x68, 0x61, 0x37, 0xd1, 0x03, 0x6b, 0xf3, 0x20, 0x19, 0x87, 0x3b, 0x9a, 0x69, 0x33, - 0x90, 0x6b, 0x09, 0xfe, 0x2c, 0x11, 0xbd, 0xc3, 0xae, 0x0f, 0x77, 0x64, 0xd8, 0xdc, 0x12, 0xb2, 0x52, 0x66, 0x7a, - 0x78, 0x09, 0xb4, 0xeb, 0xb7, 0x8a, 0xed, 0x50, 0xc1, 0x9f, 0x22, 0x87, 0xa4, 0x98, 0x7e, 0x9f, 0xbd, 0x3a, 0x80, - 0x18, 0xc4, 0xa9, 0xd3, 0x7d, 0x53, 0x60, 0x9d, 0x43, 0x49, 0xb1, 0x21, 0x8c, 0x71, 0xc6, 0x51, 0xbb, 0xdb, 0xd1, - 0xc6, 0x7e, 0x24, 0x86, 0x40, 0xe9, 0xf0, 0xe5, 0x8e, 0x56, 0x5e, 0xb7, 0xb3, 0x75, 0xdb, 0x6b, 0xda, 0x91, 0x0f, - 0xc9, 0x11, 0x4c, 0x8a, 0x48, 0x5a, 0x36, 0x10, 0x9a, 0x31, 0x78, 0x8b, 0xb4, 0x60, 0x6d, 0xcf, 0x80, 0x96, 0xb9, - 0x5e, 0x28, 0xb4, 0xc0, 0xb3, 0x66, 0x0c, 0x4c, 0x0a, 0x8b, 0x0e, 0x2e, 0x69, 0xef, 0x74, 0x82, 0xd9, 0x40, 0xb5, - 0x5a, 0xdb, 0x6d, 0x59, 0xdf, 0x34, 0x0a, 0x84, 0xed, 0xbb, 0x72, 0x33, 0xfd, 0xc8, 0xcf, 0xac, 0x05, 0xf0, 0x55, - 0x6c, 0xbb, 0xce, 0x83, 0x76, 0x5f, 0x5b, 0xe5, 0xde, 0xc7, 0xfe, 0x5a, 0xe2, 0xc7, 0x50, 0xc3, 0xb2, 0x74, 0xc2, - 0x74, 0x65, 0x50, 0xbc, 0xe5, 0x9a, 0xfb, 0xc2, 0xc6, 0x64, 0x7a, 0x87, 0x12, 0x9b, 0xf8, 0xba, 0xb3, 0x1b, 0xcc, - 0x2d, 0x23, 0x7a, 0x59, 0xbf, 0xd3, 0xb7, 0xb2, 0xb5, 0xeb, 0x01, 0x88, 0xa9, 0x57, 0x96, 0x8c, 0x87, 0x19, 0x5d, - 0x3c, 0x04, 0xa5, 0xc9, 0x6b, 0x54, 0x92, 0xc1, 0x67, 0xf5, 0xae, 0x85, 0x44, 0xe4, 0xdb, 0x7a, 0x95, 0x27, 0xb3, - 0x91, 0x0d, 0xc7, 0xae, 0xa7, 0xe5, 0x81, 0x90, 0x32, 0x9a, 0xfd, 0x6d, 0x93, 0xd6, 0x5c, 0x4b, 0xc3, 0x2f, 0x91, - 0xe2, 0xa2, 0xd9, 0x38, 0xca, 0x36, 0x12, 0x04, 0x5d, 0xd5, 0x42, 0xb2, 0x58, 0x78, 0x58, 0xc8, 0x50, 0xbe, 0xac, - 0x84, 0x65, 0x2f, 0xee, 0xa6, 0x13, 0xf9, 0xe6, 0xc6, 0xcd, 0x8f, 0x42, 0xdb, 0xad, 0xaf, 0xdd, 0xf5, 0x43, 0x1b, - 0x51, 0x56, 0xbf, 0xe8, 0xc1, 0x57, 0xaa, 0xb1, 0x3e, 0xb2, 0xfe, 0xff, 0xa1, 0x9f, 0xd4, 0x89, 0xe4, 0xcc, 0x69, - 0x3b, 0x60, 0x7b, 0xa6, 0x80, 0xad, 0xd0, 0xf6, 0xb0, 0xa9, 0xf4, 0xfe, 0xce, 0x25, 0x81, 0x5c, 0x88, 0xf8, 0x84, - 0x85, 0x40, 0x92, 0xe2, 0x91, 0x4e, 0x03, 0x4c, 0x2d, 0x03, 0xea, 0x11, 0xec, 0xfb, 0xc1, 0x8e, 0x7c, 0xf3, 0x92, - 0xed, 0xf2, 0xb6, 0xee, 0x27, 0x28, 0xeb, 0x3e, 0x0f, 0x81, 0x8d, 0xdb, 0xd2, 0xe5, 0x80, 0x49, 0x1c, 0xc8, 0xc4, - 0x4c, 0xfb, 0x65, 0x6a, 0x2f, 0xdf, 0x2a, 0x67, 0x9c, 0xa0, 0x5b, 0x8a, 0x5a, 0x0e, 0x29, 0x71, 0x48, 0x5b, 0x79, - 0xe7, 0x86, 0xbd, 0x91, 0x7e, 0x88, 0x73, 0x8b, 0x1e, 0x07, 0x46, 0xd4, 0x69, 0xce, 0x66, 0x21, 0x42, 0x4d, 0xae, - 0x1a, 0xe5, 0xf1, 0x03, 0x57, 0xe9, 0x5a, 0xaa, 0xee, 0x2b, 0x94, 0xcc, 0x9e, 0x08, 0x93, 0x39, 0xb4, 0x3b, 0x64, - 0x49, 0x89, 0x66, 0x1f, 0xbb, 0x75, 0x40, 0x60, 0x27, 0x60, 0x9e, 0x96, 0xc8, 0xeb, 0x94, 0x4c, 0xfc, 0xf6, 0xed, - 0x3f, 0xca, 0xeb, 0x08, 0x86, 0xbd, 0xe4, 0x30, 0xa7, 0x02, 0x11, 0xc7, 0x71, 0xfe, 0xbc, 0x91, 0x0b, 0x12, 0x63, - 0xfd, 0xf9, 0x6b, 0xac, 0x5c, 0x23, 0x81, 0x56, 0x49, 0x43, 0xe1, 0x99, 0x1b, 0x67, 0xae, 0xec, 0xd4, 0xb3, 0x8c, - 0x2b, 0x76, 0x5b, 0xf4, 0x93, 0xc8, 0xa3, 0x16, 0xcd, 0x94, 0x1e, 0xa9, 0x72, 0x91, 0x94, 0xb4, 0xca, 0xa1, 0x96, - 0x6c, 0x05, 0xca, 0x61, 0x72, 0x2c, 0xe3, 0x3a, 0x73, 0x1a, 0x9a, 0xb3, 0x2c, 0x01, 0x72, 0x8b, 0x25, 0x38, 0xc7, - 0x4c, 0x2e, 0xc3, 0x4a, 0x2a, 0x24, 0x60, 0x1c, 0x84, 0xc2, 0x4f, 0xfe, 0xb1, 0xd2, 0xfe, 0x4e, 0x86, 0x5c, 0x62, - 0xf8, 0x0b, 0x1f, 0x93, 0x9e, 0x2b, 0x1f, 0x0a, 0x66, 0xb0, 0x18, 0xa2, 0xb7, 0x8c, 0x60, 0x5b, 0xee, 0xc4, 0x5b, - 0x34, 0xcb, 0xd2, 0xb9, 0x7f, 0x81, 0x66, 0xdd, 0xac, 0xd5, 0x7d, 0x8b, 0x22, 0xaf, 0x67, 0x4c, 0x9a, 0x70, 0xd2, - 0x4a, 0xa9, 0x94, 0xa6, 0xa0, 0x23, 0x4a, 0x32, 0x01, 0xcc, 0x0c, 0x50, 0xb2, 0x93, 0x8c, 0x4a, 0x0f, 0xca, 0xc9, - 0x70, 0x62, 0x31, 0xd3, 0xe8, 0x2c, 0x06, 0xac, 0x5e, 0x35, 0x3e, 0xce, 0x27, 0x1d, 0xff, 0x03, 0x40, 0xf5, 0xb5, - 0xd7, 0x82, 0xd7, 0x3c, 0x97, 0x93, 0xae, 0xe9, 0xba, 0x3a, 0xf6, 0x3f, 0xee, 0x45, 0x57, 0x50, 0x35, 0x66, 0xbf, - 0xd8, 0x5f, 0xd2, 0x38, 0x0c, 0x13, 0x62, 0x7c, 0x70, 0x1f, 0x70, 0xd4, 0x01, 0x5b, 0xac, 0x7a, 0x72, 0x91, 0x64, - 0x96, 0xa4, 0xb7, 0xb9, 0xe8, 0x3a, 0x7e, 0x70, 0x60, 0xa8, 0x2e, 0x6d, 0xba, 0xe7, 0x91, 0x15, 0x6f, 0x8d, 0x25, - 0xc0, 0x52, 0xcc, 0x81, 0x2e, 0x18, 0x1d, 0xaf, 0x08, 0xce, 0xb6, 0x13, 0x20, 0x0a, 0x63, 0x2d, 0x8a, 0x2c, 0x4e, - 0xf8, 0x5b, 0xd2, 0x26, 0x60, 0x4b, 0xc6, 0x28, 0x8d, 0x7d, 0x0e, 0xce, 0x95, 0xf9, 0xe0, 0xb1, 0xea, 0x17, 0x75, - 0xba, 0xba, 0x0c, 0xb1, 0xcf, 0x4f, 0x72, 0x79, 0xfd, 0x1d, 0xea, 0x4b, 0xbf, 0x8d, 0xd2, 0x17, 0x78, 0x67, 0x09, - 0x39, 0xef, 0x5e, 0xff, 0x54, 0xb4, 0x38, 0x30, 0x0b, 0x5d, 0xc5, 0x16, 0xb5, 0xe0, 0xfc, 0xe9, 0x85, 0x44, 0x14, - 0x65, 0x8f, 0x09, 0x90, 0xa9, 0xa6, 0xac, 0x7e, 0x53, 0xa4, 0x40, 0xc6, 0x45, 0x55, 0x9c, 0x3c, 0x06, 0xdf, 0xce, - 0x37, 0x77, 0x94, 0xc1, 0x68, 0xc8, 0xba, 0x5f, 0xef, 0xd8, 0xc4, 0x6f, 0xc4, 0xfc, 0x8f, 0x09, 0x27, 0xbd, 0x7a, - 0x4a, 0x80, 0x4a, 0xda, 0x49, 0x2a, 0x7d, 0x50, 0xe0, 0x85, 0x89, 0x26, 0x67, 0xa8, 0x41, 0x56, 0x78, 0x02, 0x9d, - 0x01, 0xcb, 0xd8, 0x62, 0x4a, 0xd9, 0x6d, 0x9b, 0xf8, 0x19, 0x85, 0x37, 0xb6, 0xb5, 0xd5, 0x18, 0xa4, 0xa7, 0x0a, - 0xd0, 0xf6, 0x38, 0x53, 0x85, 0x67, 0xd1, 0x85, 0x73, 0x6e, 0xde, 0x39, 0x70, 0x3e, 0xac, 0xcd, 0xc3, 0x97, 0xbf, - 0x20, 0x07, 0x85, 0x5d, 0x93, 0x3a, 0xa8, 0xea, 0x9a, 0x97, 0x74, 0xc2, 0x3f, 0x61, 0x7b, 0x89, 0xc5, 0x4c, 0x5e, - 0xd2, 0x7e, 0x0a, 0x1d, 0x21, 0x6d, 0x1e, 0x3a, 0xcd, 0xf6, 0x6f, 0x8a, 0x99, 0x1c, 0x2f, 0xb6, 0x9a, 0xfd, 0xb2, - 0x31, 0xfe, 0x2d, 0x92, 0x02, 0xee, 0x2b, 0xe7, 0xc3, 0x2a, 0x32, 0x89, 0x3a, 0xae, 0x8d, 0x17, 0x94, 0x3e, 0x86, - 0xe9, 0x68, 0xb1, 0xea, 0xb2, 0x8c, 0x7b, 0xa5, 0xcc, 0x91, 0x51, 0x82, 0xc3, 0x53, 0x55, 0x44, 0x15, 0x3a, 0xaf, - 0x21, 0x2f, 0xcd, 0xfc, 0xba, 0x4a, 0x45, 0xe8, 0x43, 0x99, 0x73, 0xce, 0x5b, 0xa2, 0xee, 0x7a, 0xa2, 0xf8, 0x71, - 0x81, 0x42, 0x5b, 0x22, 0x8c, 0x7c, 0x70, 0x06, 0xa7, 0x49, 0x82, 0x47, 0x26, 0x22, 0x8f, 0x3c, 0xc5, 0xf5, 0x8b, - 0x51, 0x49, 0x2f, 0x2f, 0xe1, 0x91, 0x73, 0x97, 0xc5, 0xdd, 0x47, 0xfc, 0x5a, 0x7d, 0x89, 0x3e, 0x2c, 0xe1, 0x28, - 0x88, 0x95, 0x76, 0xbf, 0x0c, 0x9f, 0xd4, 0x81, 0xca, 0xf9, 0x3f, 0xa8, 0xbf, 0x86, 0x2c, 0xb2, 0x88, 0x26, 0xeb, - 0x0a, 0x73, 0x70, 0xd4, 0x0f, 0x8b, 0x10, 0xf9, 0x22, 0x43, 0x48, 0x16, 0xdd, 0xea, 0xe5, 0x21, 0xb4, 0x9e, 0xfc, - 0xdd, 0x32, 0xf7, 0xfb, 0xbb, 0x6a, 0x7a, 0x38, 0x8d, 0x14, 0xfc, 0x48, 0x45, 0x5f, 0x76, 0x75, 0x7b, 0x12, 0xdf, - 0xf5, 0x7c, 0x0f, 0x01, 0xb3, 0x8f, 0x34, 0x44, 0xf2, 0x66, 0xd9, 0x3a, 0xf4, 0x4d, 0x6c, 0x71, 0x45, 0x6b, 0xd0, - 0xa5, 0xd4, 0xf4, 0x51, 0x81, 0x33, 0xbc, 0x12, 0x74, 0x90, 0xe1, 0x68, 0xb9, 0xf2, 0xa6, 0x42, 0xb0, 0x38, 0xa9, - 0xda, 0x6e, 0x8b, 0x32, 0xdb, 0x33, 0x38, 0x89, 0x16, 0x51, 0x93, 0x99, 0xfc, 0x3e, 0x7d, 0x14, 0xab, 0xdc, 0x28, - 0x82, 0x3b, 0xfa, 0xc2, 0x2a, 0xad, 0xbd, 0x34, 0xe4, 0x97, 0x5a, 0xb2, 0x85, 0x06, 0x54, 0x4a, 0x79, 0xa1, 0x6a, - 0x5c, 0x2e, 0x85, 0x2b, 0x63, 0x6b, 0xf4, 0x30, 0xd3, 0xaa, 0x78, 0x15, 0x57, 0x48, 0xc7, 0xd7, 0x88, 0x45, 0xe8, - 0xb2, 0x0c, 0x12, 0x1e, 0xce, 0x72, 0x2e, 0x79, 0x72, 0x0d, 0x56, 0x3c, 0xb7, 0x60, 0x0e, 0x66, 0x5d, 0xab, 0x27, - 0xd5, 0xd8, 0x80, 0x91, 0x14, 0xf9, 0x2a, 0xa6, 0x73, 0xd5, 0x01, 0x75, 0x5c, 0x43, 0x60, 0x16, 0xee, 0x23, 0x3f, - 0x4a, 0x49, 0xaf, 0x94, 0x91, 0x33, 0xdc, 0x56, 0x49, 0x36, 0xe3, 0x64, 0x24, 0xdc, 0xd1, 0xc6, 0xce, 0x45, 0x01, - 0x3f, 0x0a, 0x39, 0x53, 0x02, 0x1a, 0xd2, 0x10, 0x49, 0x2e, 0x76, 0xcf, 0x13, 0xab, 0x21, 0xd2, 0x93, 0x05, 0x05, - 0x10, 0x79, 0x58, 0xfb, 0x60, 0x49, 0x79, 0x34, 0xb5, 0x80, 0x89, 0x79, 0xae, 0xfc, 0xa8, 0xbd, 0x85, 0xaf, 0xd6, - 0xa1, 0x04, 0xcc, 0xe1, 0xcb, 0x24, 0xd6, 0x4a, 0x9b, 0xf1, 0xb8, 0x2c, 0x8f, 0xca, 0x5b, 0xcb, 0x6a, 0xba, 0xa2, - 0x7a, 0xd0, 0x98, 0x1e, 0xae, 0x53, 0x62, 0x6c, 0x2c, 0xb3, 0x4e, 0x5c, 0x2a, 0xe6, 0xbf, 0x4f, 0x5f, 0xaa, 0x8b, - 0xaa, 0x96, 0x6f, 0x23, 0xae, 0x67, 0x8c, 0x6a, 0x51, 0xc3, 0x03, 0xe6, 0x5f, 0x96, 0x31, 0x2c, 0xd7, 0x04, 0xb3, - 0x5c, 0x13, 0xbd, 0xad, 0x86, 0xa0, 0xed, 0x78, 0x14, 0x95, 0xa0, 0x1b, 0x31, 0xa0, 0x91, 0x52, 0x23, 0x60, 0x9b, - 0x14, 0x62, 0xf0, 0x1b, 0xb0, 0x3f, 0x76, 0x08, 0x48, 0x05, 0x47, 0xf0, 0x80, 0x70, 0xc9, 0x71, 0xf9, 0x61, 0xd2, - 0xdd, 0x42, 0x02, 0xa9, 0x78, 0x39, 0x2b, 0x9f, 0x96, 0x08, 0x46, 0x31, 0x28, 0x8b, 0xd0, 0x0c, 0x91, 0x52, 0x37, - 0x2b, 0x32, 0xea, 0xe0, 0x8d, 0xc1, 0x37, 0x22, 0x06, 0xbc, 0x52, 0x50, 0xc8, 0x63, 0x4e, 0x4e, 0x96, 0xcb, 0xd7, - 0xb9, 0x4b, 0x7f, 0x47, 0x4f, 0xe5, 0x38, 0x75, 0x47, 0xd0, 0xa6, 0x8f, 0x62, 0x9c, 0x8b, 0x4a, 0x82, 0xeb, 0xe5, - 0xb4, 0xf7, 0x98, 0xd1, 0x7c, 0xe1, 0xea, 0x69, 0x3c, 0x68, 0x8b, 0xdf, 0x8f, 0x39, 0xfb, 0xf0, 0x29, 0x35, 0xba, - 0x80, 0x02, 0x0f, 0x3b, 0x75, 0xdb, 0xc8, 0x29, 0x46, 0x80, 0xbf, 0xad, 0xaf, 0xc7, 0xa3, 0xcd, 0x96, 0xb9, 0x20, - 0x35, 0xec, 0x1b, 0x7c, 0x39, 0x18, 0x7f, 0x45, 0xb4, 0xc3, 0xd7, 0x64, 0xdd, 0x43, 0x83, 0xee, 0x5e, 0xd6, 0xf0, - 0x05, 0x0b, 0x74, 0x7e, 0x89, 0x21, 0x6f, 0xd9, 0x81, 0xe5, 0x3e, 0xcf, 0xf5, 0x04, 0x99, 0xc6, 0xc3, 0x78, 0x0d, - 0xc8, 0x35, 0x9e, 0xe5, 0xbd, 0x1b, 0xf5, 0x7b, 0xb6, 0x9c, 0x77, 0xc4, 0xd6, 0xd4, 0xbb, 0x6c, 0x03, 0x8c, 0xa3, - 0xea, 0x7f, 0xdf, 0x54, 0x22, 0x18, 0x99, 0xa1, 0x7d, 0x5a, 0xeb, 0xa3, 0xca, 0xd3, 0xff, 0x37, 0xb3, 0x75, 0x61, - 0x65, 0x98, 0x43, 0x30, 0xe3, 0x2b, 0x7c, 0x9a, 0x71, 0x1e, 0x44, 0x78, 0x20, 0xed, 0x5e, 0x66, 0x37, 0xd6, 0x9c, - 0xd1, 0x8f, 0xd0, 0x9d, 0x92, 0xec, 0x02, 0xc7, 0xf1, 0x6f, 0x83, 0x9e, 0x0a, 0xb5, 0x1f, 0xd5, 0x81, 0xc5, 0xdf, - 0x05, 0xa9, 0x09, 0xc9, 0x50, 0x80, 0x03, 0xb9, 0x6a, 0xd9, 0x7b, 0xba, 0x9d, 0x5d, 0x4c, 0x13, 0xc4, 0xa5, 0xb3, - 0xd5, 0x97, 0xd7, 0xad, 0x17, 0x68, 0xdf, 0xec, 0xfd, 0x68, 0x63, 0xa6, 0x98, 0xc7, 0xeb, 0xbb, 0xa6, 0xe3, 0x37, - 0x14, 0x86, 0xd6, 0xf8, 0x2a, 0x62, 0xba, 0x6f, 0x68, 0xde, 0xcb, 0xb5, 0x37, 0xed, 0x3d, 0x7e, 0xb1, 0xd7, 0xea, - 0x2c, 0xb0, 0xf1, 0x46, 0x01, 0x57, 0x26, 0x2e, 0x67, 0x94, 0xe4, 0xc3, 0x0d, 0x82, 0xeb, 0xf8, 0xd1, 0xaa, 0x19, - 0xee, 0x7a, 0x7c, 0xa3, 0x13, 0x96, 0x61, 0x60, 0xba, 0x85, 0xeb, 0x40, 0x8c, 0x61, 0x6c, 0x11, 0x42, 0x91, 0xfa, - 0x91, 0xc6, 0x30, 0x0a, 0xc6, 0xcf, 0x4f, 0xd6, 0x98, 0xd9, 0xf1, 0x1f, 0x51, 0x00, 0xae, 0x5d, 0x84, 0x23, 0x30, - 0xcc, 0x2c, 0xa8, 0x50, 0xe1, 0x42, 0x1f, 0x89, 0x2b, 0x9b, 0xb2, 0xa7, 0xf0, 0x02, 0xf2, 0x25, 0xa6, 0xfd, 0x51, - 0xd7, 0xf9, 0x83, 0x13, 0xf9, 0x49, 0xed, 0xee, 0xf7, 0x4a, 0xb7, 0x17, 0xe1, 0x32, 0xd3, 0x75, 0xc4, 0x00, 0xc9, - 0x63, 0x30, 0xc1, 0x68, 0x31, 0x64, 0xc7, 0x4d, 0xed, 0x59, 0x9d, 0xce, 0xc9, 0xf1, 0xe0, 0x7f, 0xad, 0x82, 0xd9, - 0xf8, 0x28, 0xde, 0x56, 0x8d, 0x9c, 0xed, 0x49, 0xba, 0xf9, 0x63, 0xa5, 0xc9, 0xec, 0xff, 0x61, 0x7e, 0x9d, 0x05, - 0x0b, 0xe6, 0x8b, 0x45, 0x8b, 0xac, 0x21, 0x6a, 0x80, 0x1f, 0xee, 0x34, 0xa6, 0x7c, 0x46, 0x19, 0x61, 0xab, 0x5a, - 0x2b, 0x6d, 0x68, 0x80, 0xe6, 0x94, 0x9d, 0x20, 0x45, 0x09, 0x24, 0xef, 0x58, 0x85, 0x91, 0xf9, 0xc0, 0x30, 0x78, - 0xec, 0x7d, 0x6a, 0xdd, 0x9a, 0xa2, 0xae, 0xf0, 0x3e, 0xd1, 0xd8, 0x8d, 0x59, 0x29, 0xf5, 0x73, 0x2b, 0xf4, 0x1f, - 0xd1, 0x0b, 0x11, 0x58, 0x22, 0x3f, 0x04, 0xf5, 0x93, 0xa0, 0x96, 0xf5, 0x27, 0x95, 0xb7, 0x7c, 0x6e, 0xcf, 0x2e, - 0xb6, 0xe5, 0xd3, 0x5c, 0x67, 0x20, 0xb1, 0x33, 0xbe, 0xa9, 0x2f, 0xbe, 0x48, 0xb5, 0x96, 0x5b, 0xba, 0xe5, 0xd1, - 0x34, 0xc4, 0xe8, 0x00, 0x80, 0x94, 0x01, 0xe3, 0x27, 0xf8, 0x81, 0x3a, 0xe3, 0x9f, 0xcf, 0x6f, 0xea, 0x9c, 0xea, - 0xaf, 0xde, 0x48, 0xe8, 0x2d, 0x2d, 0x01, 0xdf, 0x85, 0xfc, 0xdf, 0xfe, 0x95, 0x6e, 0x1d, 0x63, 0x45, 0x60, 0x76, - 0x70, 0x75, 0x92, 0x9d, 0xe9, 0x69, 0x6b, 0xe2, 0x2a, 0x06, 0xef, 0x87, 0x68, 0x9d, 0xfb, 0x91, 0xc0, 0x68, 0x0a, - 0x6f, 0xb3, 0xd8, 0xb4, 0x55, 0xae, 0x57, 0x33, 0x61, 0xb6, 0x8d, 0x2e, 0x91, 0x1a, 0x82, 0xeb, 0x7d, 0x2c, 0xa3, - 0x8b, 0x27, 0x83, 0xb3, 0xba, 0xbe, 0x64, 0x2a, 0xc0, 0x85, 0x14, 0xf5, 0x27, 0xca, 0xb2, 0xdd, 0xa3, 0x2e, 0x35, - 0xdd, 0x1f, 0xb4, 0x76, 0xcf, 0xa5, 0xc5, 0x36, 0x5d, 0x36, 0x7d, 0x6a, 0x3d, 0x10, 0xc1, 0xbe, 0xa5, 0x1b, 0xf6, - 0x02, 0x00, 0x1d, 0xe0, 0x85, 0x6a, 0x13, 0x5d, 0x57, 0xfd, 0x63, 0x0f, 0x48, 0x6b, 0x7c, 0x8f, 0x4d, 0xaa, 0xdc, - 0xc8, 0xa4, 0xda, 0x45, 0x82, 0xb2, 0xc3, 0xf8, 0xf8, 0x0e, 0x7b, 0xad, 0x87, 0x17, 0x6a, 0x55, 0x0a, 0x6b, 0xcb, - 0xdc, 0x9b, 0x31, 0xa9, 0x69, 0xeb, 0x0f, 0x5e, 0x0b, 0xeb, 0x86, 0x2e, 0x85, 0xcb, 0xe2, 0x51, 0xab, 0x03, 0x90, - 0x93, 0x0d, 0x84, 0x70, 0xc4, 0xd3, 0x3f, 0x92, 0x9c, 0x02, 0xbc, 0x0e, 0xdc, 0x15, 0xc7, 0xec, 0xb2, 0x1d, 0x77, - 0xc3, 0x96, 0x5b, 0xf8, 0xb3, 0x5b, 0x20, 0xc5, 0xba, 0xea, 0xdc, 0xb0, 0x83, 0xd7, 0x65, 0x8a, 0xa0, 0x54, 0x48, - 0x40, 0x38, 0x5c, 0xce, 0x2e, 0x05, 0xa1, 0x24, 0x60, 0xac, 0x0a, 0xf7, 0x87, 0xb2, 0xb7, 0xdd, 0x6e, 0xd8, 0x92, - 0x47, 0x92, 0x61, 0xa0, 0x6a, 0x3d, 0xa6, 0xf5, 0xaf, 0x76, 0x3a, 0x81, 0x4a, 0xd6, 0x6c, 0x7a, 0xa4, 0x7f, 0x58, - 0x8f, 0xf4, 0x52, 0xf0, 0x48, 0xc4, 0xe2, 0x1d, 0x19, 0xa3, 0xab, 0x1f, 0x2f, 0x90, 0xd9, 0x3b, 0x2e, 0x7e, 0x98, - 0xc3, 0xda, 0xb0, 0xcb, 0x80, 0x27, 0x98, 0x49, 0x83, 0x7a, 0xd5, 0x55, 0xf4, 0x54, 0x90, 0x0e, 0x8b, 0x86, 0x81, - 0x85, 0x53, 0xea, 0x57, 0xe9, 0x2d, 0x6f, 0x74, 0x16, 0x34, 0x86, 0x12, 0x2d, 0x65, 0xa1, 0x2c, 0x37, 0x93, 0x87, - 0x0d, 0x25, 0x2b, 0xae, 0xa9, 0x6d, 0x67, 0xab, 0x68, 0xd1, 0x0a, 0xc2, 0x1f, 0xd7, 0x30, 0x23, 0xea, 0x2f, 0x64, - 0x9a, 0x75, 0x3b, 0xfc, 0x0c, 0x69, 0xb5, 0xa4, 0x76, 0x6e, 0x81, 0xf6, 0x82, 0x06, 0xfc, 0x1a, 0x82, 0xd6, 0x92, - 0x52, 0x13, 0x9f, 0xd6, 0xb9, 0xe0, 0xf1, 0x86, 0xe1, 0xd3, 0x26, 0xa9, 0x97, 0xd9, 0xc6, 0xd5, 0x0d, 0x4f, 0x73, - 0x29, 0x3a, 0x18, 0x74, 0x90, 0x90, 0x52, 0x73, 0xa8, 0xc8, 0xdf, 0x5d, 0xac, 0x0b, 0xa7, 0x09, 0xc9, 0x66, 0x2a, - 0x59, 0x4e, 0x4a, 0xf6, 0x8c, 0x10, 0x47, 0x3f, 0x20, 0x65, 0xf2, 0x08, 0x35, 0xc9, 0xab, 0x17, 0x90, 0xc9, 0xeb, - 0x51, 0x4b, 0x8a, 0x0b, 0x6d, 0x32, 0xb1, 0x14, 0x70, 0x32, 0x8e, 0x20, 0x13, 0xac, 0xa7, 0x64, 0x75, 0x0d, 0x90, - 0xf4, 0x92, 0x3c, 0x35, 0xb0, 0x60, 0x6a, 0xef, 0x94, 0x02, 0x8b, 0x14, 0x80, 0xa1, 0x9d, 0x34, 0x2a, 0x4b, 0xf2, - 0x58, 0x76, 0xdf, 0x96, 0x65, 0x4f, 0xa1, 0xa0, 0x60, 0xc4, 0xd9, 0x63, 0x9f, 0x9d, 0x05, 0x82, 0xf2, 0x70, 0x06, - 0x65, 0xfa, 0x9c, 0x60, 0x23, 0xcf, 0x11, 0x2c, 0xf2, 0x62, 0x40, 0x8e, 0x2a, 0x5e, 0xd6, 0x08, 0xff, 0xd5, 0x02, - 0xb9, 0xc0, 0xe0, 0xe1, 0x9e, 0x74, 0x7a, 0xad, 0xdf, 0x94, 0x53, 0x50, 0x30, 0xfa, 0x94, 0xd5, 0xcd, 0x38, 0x37, - 0xd4, 0x32, 0x9a, 0x31, 0xf5, 0x67, 0xee, 0xe2, 0x49, 0xbe, 0x55, 0x32, 0xa3, 0x22, 0x93, 0x89, 0x17, 0x7e, 0x00, - 0x3b, 0x3f, 0x2f, 0x26, 0x06, 0x85, 0x27, 0x2e, 0xea, 0x98, 0x11, 0x87, 0xb8, 0x2a, 0x27, 0xbf, 0x2d, 0xc0, 0xa8, - 0xc1, 0x60, 0x72, 0x8b, 0x7a, 0x4d, 0xa9, 0xf7, 0x50, 0x9f, 0x19, 0x0c, 0xb5, 0x71, 0xac, 0x57, 0x56, 0x82, 0x0d, - 0x0d, 0x2f, 0xf9, 0x54, 0xcd, 0x3a, 0x8c, 0x15, 0x7e, 0xa5, 0x02, 0xcc, 0x05, 0xa6, 0x79, 0x1a, 0x87, 0x80, 0x95, - 0x96, 0x6a, 0x18, 0x7d, 0x75, 0xee, 0x10, 0x4a, 0xdd, 0xe8, 0x05, 0x6c, 0x00, 0xc3, 0x21, 0xa2, 0x2d, 0x7a, 0x79, - 0xe1, 0x2b, 0x0d, 0x52, 0xb5, 0x23, 0x4b, 0x5e, 0x1d, 0x72, 0x22, 0x8f, 0x27, 0xe2, 0x7f, 0x26, 0x0c, 0x49, 0x9b, - 0x1b, 0x88, 0xb7, 0x94, 0xdd, 0xd4, 0x71, 0x9a, 0x39, 0x48, 0xef, 0xe9, 0x60, 0xaf, 0x95, 0xaf, 0x6c, 0x93, 0x19, - 0x7a, 0x35, 0x1a, 0x87, 0x82, 0xb4, 0xbc, 0x98, 0x2d, 0x32, 0x69, 0x12, 0xdd, 0x96, 0x16, 0x03, 0x7a, 0x88, 0xec, - 0xcc, 0x43, 0xb1, 0xe2, 0x7d, 0x3d, 0x99, 0x16, 0x14, 0x1d, 0xc2, 0x2d, 0xe4, 0x26, 0x1a, 0xf5, 0x13, 0x5d, 0xb5, - 0x2b, 0x94, 0xd9, 0x7e, 0x26, 0x74, 0x80, 0x97, 0x16, 0x27, 0x00, 0xec, 0xd1, 0x34, 0x2e, 0xb8, 0x6d, 0x09, 0xc3, - 0xd4, 0x86, 0x6a, 0x2e, 0x3b, 0xdd, 0xd6, 0x99, 0x5c, 0x0b, 0x14, 0x83, 0x00, 0x3a, 0xcf, 0x37, 0xef, 0x4f, 0x5e, - 0xfe, 0x0c, 0xc7, 0xb1, 0x83, 0xd1, 0xc9, 0x8c, 0xaa, 0xb8, 0x4d, 0xa2, 0xde, 0x6f, 0xe9, 0xa6, 0x81, 0xbc, 0xef, - 0x41, 0x35, 0x7b, 0xd6, 0xef, 0x4e, 0xd7, 0xc6, 0x3b, 0xf5, 0x9b, 0xd9, 0x00, 0xa0, 0xbc, 0x48, 0x9a, 0x0f, 0x70, - 0xdc, 0xe0, 0xe7, 0x19, 0xab, 0x15, 0x6a, 0x24, 0x22, 0x88, 0x02, 0x12, 0xa6, 0xfe, 0x59, 0x38, 0xbc, 0xc7, 0x77, - 0x2c, 0x3b, 0x51, 0x70, 0x48, 0xea, 0xab, 0xc1, 0xd1, 0x83, 0x6e, 0x4c, 0x05, 0xc3, 0x1a, 0xe3, 0x84, 0x9b, 0x6f, - 0xb1, 0xef, 0x5a, 0x2b, 0x8a, 0xeb, 0xc2, 0x3e, 0xf7, 0x9d, 0xa2, 0x9e, 0x7d, 0x76, 0x43, 0x8f, 0xf3, 0xe0, 0x15, - 0x53, 0x56, 0x29, 0xd6, 0x5d, 0x8e, 0x3c, 0x3e, 0x01, 0x52, 0xf3, 0x5d, 0xc9, 0xdf, 0x60, 0xac, 0x20, 0x0a, 0xbc, - 0x5f, 0x6d, 0x8a, 0x74, 0x39, 0xb1, 0x22, 0x0a, 0x83, 0x20, 0xf3, 0x2a, 0x42, 0xbc, 0xa2, 0x92, 0xdf, 0xb7, 0x03, - 0x38, 0x81, 0x3c, 0x1c, 0xb6, 0x09, 0xbe, 0xdf, 0xd1, 0x40, 0xa8, 0x18, 0x37, 0xd2, 0x76, 0x4b, 0x4e, 0x37, 0x8c, - 0x7b, 0x3a, 0x69, 0xf6, 0x26, 0x91, 0x9b, 0x44, 0x0d, 0x47, 0x11, 0xcb, 0xd7, 0x64, 0x77, 0x45, 0x81, 0x42, 0x80, - 0xc8, 0x2e, 0xf9, 0x1c, 0x96, 0x9a, 0xca, 0xf5, 0xb5, 0xe4, 0x17, 0x48, 0x82, 0x8c, 0xdb, 0x40, 0xea, 0x9f, 0x14, - 0xa1, 0xec, 0x1c, 0xb5, 0x61, 0xc7, 0x8f, 0x26, 0xaa, 0x0e, 0x76, 0xa7, 0x55, 0x9b, 0x1d, 0x8d, 0x60, 0xdf, 0x6b, - 0x85, 0x96, 0x83, 0xd6, 0x59, 0x9f, 0x9a, 0xdc, 0x10, 0x3f, 0x3e, 0xe7, 0x72, 0x80, 0x00, 0x3a, 0x59, 0xa0, 0xc2, - 0xfd, 0xd0, 0x51, 0xdf, 0xae, 0x0e, 0x69, 0x02, 0x45, 0xe5, 0xa0, 0xb8, 0xe3, 0x38, 0x85, 0x5d, 0x91, 0x1d, 0xfd, - 0x42, 0x34, 0x4e, 0xd8, 0xe1, 0x23, 0x6b, 0x9a, 0x3f, 0xc4, 0x09, 0xca, 0x17, 0xf3, 0x50, 0x70, 0x89, 0x3a, 0x1b, - 0x52, 0x46, 0x00, 0x74, 0x47, 0xbb, 0xf5, 0x90, 0x7e, 0x5c, 0xdb, 0x14, 0x7b, 0xee, 0x09, 0xfa, 0xbc, 0x6f, 0x60, - 0xdc, 0x11, 0xd8, 0xd1, 0x40, 0x12, 0xda, 0x47, 0x95, 0xfa, 0x33, 0x8f, 0xc5, 0x98, 0xd9, 0xa7, 0xdb, 0x66, 0x82, - 0xca, 0x9d, 0xec, 0x52, 0x09, 0xd2, 0xe0, 0x0d, 0xf2, 0x70, 0xd8, 0xd7, 0xfd, 0x5e, 0x6a, 0xda, 0xe6, 0xc9, 0xed, - 0x2b, 0xab, 0xd5, 0x94, 0xef, 0x76, 0x99, 0x40, 0x7c, 0x71, 0x0e, 0x65, 0xbc, 0xe7, 0x81, 0xaa, 0xef, 0x1b, 0x59, - 0x43, 0xc0, 0x7d, 0xb3, 0x30, 0xcc, 0x09, 0x3a, 0xc2, 0x20, 0x69, 0xe6, 0xc1, 0x9f, 0x00, 0x6d, 0xde, 0xcb, 0xeb, - 0x55, 0x88, 0x73, 0x40, 0x77, 0xf8, 0xf2, 0x84, 0xb5, 0x8e, 0xd8, 0xe3, 0x83, 0x79, 0xc6, 0x28, 0x37, 0xbc, 0x44, - 0xc7, 0x88, 0xdb, 0xde, 0x95, 0x17, 0x32, 0x5d, 0x3e, 0xfb, 0x96, 0x04, 0xbe, 0x31, 0x52, 0x81, 0x14, 0x68, 0xc4, - 0xb1, 0x0f, 0x36, 0xdf, 0x87, 0x43, 0xb3, 0x5f, 0xe8, 0x8d, 0xc2, 0xf4, 0x72, 0xfc, 0xe5, 0xc6, 0xfc, 0x16, 0x8e, - 0xb8, 0xda, 0x2a, 0xc4, 0xc3, 0x5e, 0x8e, 0xb9, 0xd0, 0x9a, 0x07, 0xbf, 0x30, 0x27, 0xcb, 0x42, 0xe2, 0xdd, 0x45, - 0x7d, 0xc3, 0x7a, 0xcd, 0x96, 0x3d, 0x93, 0x59, 0x13, 0x0f, 0x92, 0xf5, 0xb4, 0xf2, 0x70, 0x7a, 0x2a, 0xcf, 0xb1, - 0xd9, 0x0b, 0x0b, 0xb2, 0xa1, 0xab, 0xa7, 0xb6, 0x5c, 0xf7, 0xd6, 0x34, 0x24, 0x2f, 0xf1, 0x8b, 0xab, 0x68, 0x01, - 0x4a, 0x4c, 0xd4, 0xce, 0xac, 0x5d, 0x90, 0x0a, 0xf6, 0x7a, 0x59, 0x40, 0x83, 0x63, 0xe5, 0xd8, 0x96, 0xd0, 0x53, - 0x91, 0x19, 0x9f, 0x55, 0x29, 0x20, 0x7d, 0x4d, 0xd4, 0xed, 0x45, 0x54, 0x5a, 0x42, 0x82, 0xc0, 0xc7, 0x4f, 0x92, - 0x52, 0xec, 0xcb, 0x0d, 0x20, 0x30, 0x54, 0xbc, 0xef, 0x02, 0xbe, 0xbf, 0xa9, 0x48, 0x64, 0x72, 0xb0, 0x92, 0xf7, - 0x44, 0x97, 0x14, 0xf8, 0x9f, 0x9f, 0xef, 0xac, 0x54, 0x2a, 0x72, 0x39, 0x86, 0x11, 0xc5, 0x5e, 0x33, 0x45, 0x61, - 0x6e, 0x1a, 0xa1, 0x20, 0x50, 0xcb, 0x3f, 0x5c, 0x7f, 0xa1, 0xbf, 0xa4, 0x04, 0xa7, 0x96, 0x40, 0x5c, 0x5e, 0x9d, - 0x87, 0x04, 0x67, 0xf5, 0x16, 0x79, 0xac, 0x20, 0xd8, 0x63, 0xae, 0x35, 0x3b, 0xcc, 0x81, 0x64, 0x57, 0x0b, 0x8c, - 0xb6, 0x44, 0x29, 0xf5, 0x02, 0x62, 0x97, 0x4c, 0xf7, 0x75, 0x45, 0x91, 0xee, 0x51, 0xf4, 0x98, 0xca, 0x68, 0x39, - 0x3e, 0xd1, 0xd8, 0xdf, 0x18, 0xaa, 0x96, 0xfa, 0x2a, 0x7b, 0xc2, 0xd7, 0xbb, 0xc3, 0x17, 0x1b, 0x3f, 0x12, 0xfe, - 0x3e, 0x57, 0x4c, 0x3f, 0x67, 0xf7, 0xa3, 0x5d, 0xc2, 0x68, 0xa0, 0x7a, 0xae, 0x39, 0x6e, 0x2c, 0x37, 0x5e, 0x6e, - 0x5f, 0x74, 0xc5, 0x56, 0x99, 0x9f, 0xbb, 0x05, 0xb9, 0x26, 0xdd, 0x6b, 0x32, 0xcf, 0x49, 0x6e, 0xf0, 0xce, 0xf4, - 0x20, 0x9d, 0x08, 0xae, 0xfd, 0xcb, 0xf3, 0xaf, 0x3b, 0x5c, 0x85, 0x6d, 0x5b, 0x91, 0x57, 0x66, 0x40, 0x39, 0xb4, - 0xdb, 0x04, 0xd4, 0x97, 0x6e, 0xd2, 0x1d, 0xd1, 0x36, 0xb6, 0xf0, 0x12, 0xe2, 0x35, 0x50, 0xdc, 0xd2, 0xc4, 0x57, - 0x67, 0xa3, 0x90, 0xa6, 0x64, 0xb2, 0x07, 0x84, 0x62, 0xc2, 0x02, 0xfd, 0xd3, 0x71, 0xd2, 0xac, 0x0a, 0x5a, 0xef, - 0x95, 0xaa, 0x8e, 0x95, 0xd3, 0xd5, 0x57, 0x61, 0x66, 0xa3, 0x19, 0xf1, 0x20, 0x27, 0x1b, 0x87, 0x28, 0x77, 0x9d, - 0xe9, 0xe8, 0x50, 0x3c, 0xa6, 0xdc, 0x49, 0x9d, 0x5c, 0x9c, 0xb3, 0x23, 0x09, 0xc5, 0x7f, 0xeb, 0x9c, 0x08, 0x85, - 0x6f, 0x61, 0x2b, 0x02, 0xf9, 0xda, 0xb4, 0xfc, 0xaf, 0x1d, 0xf5, 0x39, 0xe1, 0x8e, 0x76, 0xe5, 0x6a, 0xc6, 0x29, - 0xb2, 0xe1, 0x40, 0xe6, 0xe3, 0x46, 0x05, 0xaf, 0x3c, 0x55, 0x65, 0xbf, 0x8d, 0x98, 0xf4, 0x89, 0x3d, 0x9b, 0x1c, - 0x26, 0xa5, 0xa3, 0xf6, 0x13, 0x5c, 0x16, 0x1d, 0x4c, 0xc3, 0xa2, 0x0d, 0x11, 0x20, 0x6a, 0xb5, 0xd1, 0x0e, 0x8b, - 0x88, 0x04, 0x8d, 0x2f, 0x56, 0x2f, 0xe3, 0x81, 0x8f, 0xe6, 0x18, 0xc5, 0x3e, 0x6d, 0x6b, 0x49, 0xf6, 0xbd, 0x31, - 0x46, 0xca, 0x40, 0x7d, 0xa2, 0x73, 0xa0, 0x4c, 0x2c, 0xf2, 0x31, 0xc9, 0x4b, 0x2d, 0x56, 0xb8, 0x4b, 0x5e, 0x47, - 0x25, 0x60, 0x45, 0xf2, 0x57, 0x70, 0x19, 0x25, 0x08, 0x46, 0x8f, 0xa2, 0x2f, 0xfd, 0x12, 0xdc, 0x72, 0xdf, 0x1f, - 0x32, 0x05, 0x76, 0x8a, 0xb1, 0x8f, 0x18, 0xbd, 0x94, 0x22, 0xf3, 0x21, 0x12, 0x8f, 0xdf, 0xb3, 0x04, 0x29, 0x28, - 0x7d, 0x69, 0x1b, 0x60, 0x70, 0x13, 0xe8, 0xb2, 0x6e, 0x6a, 0x9c, 0x01, 0x72, 0x22, 0x57, 0xd4, 0x76, 0xdc, 0xf3, - 0xc9, 0x0e, 0x05, 0x6d, 0x0d, 0x32, 0x66, 0x7a, 0xa1, 0x59, 0xa2, 0xc0, 0xf0, 0xfd, 0x56, 0xe3, 0x28, 0x18, 0xb0, - 0x6b, 0xac, 0x47, 0xbf, 0x52, 0xd2, 0x21, 0x53, 0xfa, 0x91, 0x16, 0xce, 0xe5, 0x4c, 0xa6, 0x7a, 0xf3, 0x7b, 0x21, - 0x05, 0x10, 0x17, 0x6f, 0x25, 0xa2, 0xb7, 0x64, 0x7f, 0x1d, 0x14, 0xa0, 0x60, 0x1a, 0x19, 0x23, 0xfd, 0x5f, 0x2c, - 0x0b, 0x72, 0x3b, 0x0a, 0x6b, 0x86, 0x04, 0x06, 0x15, 0x1f, 0x77, 0x68, 0x8e, 0xbf, 0x0e, 0xff, 0x6b, 0x03, 0x50, - 0x57, 0xee, 0xbc, 0xa1, 0xac, 0xf9, 0x01, 0x29, 0x45, 0x66, 0x2f, 0xdf, 0xbd, 0x6a, 0x85, 0x3a, 0x68, 0xb1, 0xcd, - 0x75, 0x9e, 0xd7, 0x16, 0xbf, 0x9e, 0x42, 0xb7, 0x37, 0xf9, 0xcd, 0x6c, 0x57, 0x5d, 0x3d, 0x36, 0x6a, 0xd4, 0x1b, - 0x04, 0xa3, 0xb7, 0x37, 0xc3, 0x6e, 0x9d, 0x0f, 0x67, 0x25, 0xa0, 0x95, 0xcd, 0x5e, 0xfd, 0x9b, 0x08, 0x0a, 0x7d, - 0xad, 0x9f, 0x47, 0xba, 0xca, 0xb8, 0x7c, 0x96, 0x80, 0x97, 0xc6, 0x87, 0x46, 0x95, 0x6a, 0x59, 0x58, 0xb2, 0x26, - 0x11, 0x08, 0x0e, 0x7f, 0xd0, 0xac, 0x67, 0xda, 0x8f, 0xea, 0x36, 0xdf, 0xd4, 0x75, 0x15, 0x41, 0xfb, 0x11, 0xd6, - 0x74, 0xa5, 0xff, 0x37, 0x71, 0x78, 0x38, 0x45, 0xff, 0xa3, 0xf9, 0x83, 0x82, 0xed, 0xdd, 0x66, 0x53, 0x42, 0x85, - 0x6b, 0xe6, 0x5e, 0x3d, 0xc5, 0x33, 0x45, 0x62, 0x17, 0xa5, 0x67, 0x55, 0xdb, 0xc1, 0xb2, 0xa1, 0xb6, 0xd7, 0x90, - 0xb0, 0x45, 0x90, 0x6a, 0x0a, 0xc6, 0xcd, 0xd3, 0x3b, 0xdc, 0x1d, 0x71, 0xcc, 0xa0, 0x1c, 0x1a, 0x45, 0x99, 0xdf, - 0x0e, 0x93, 0xe6, 0x54, 0x6d, 0x6f, 0x51, 0xe0, 0x47, 0x00, 0x9f, 0x2b, 0x6a, 0x07, 0xf2, 0xf4, 0x61, 0x94, 0xaf, - 0x27, 0xb9, 0xef, 0xc4, 0x11, 0x09, 0xd6, 0x0e, 0x6c, 0x79, 0xc9, 0xab, 0xd3, 0x95, 0xd5, 0x3d, 0x89, 0xaf, 0x3b, - 0xc6, 0xf9, 0x21, 0x71, 0xed, 0x47, 0x4f, 0x53, 0x0e, 0xdb, 0xa2, 0x9e, 0xe0, 0xb0, 0x38, 0xb4, 0xdd, 0x10, 0xdd, - 0x76, 0x96, 0x46, 0xef, 0x00, 0x6d, 0xb1, 0xc9, 0x8b, 0x27, 0x9d, 0x63, 0x5c, 0x1f, 0x2e, 0x27, 0x69, 0xd9, 0x3f, - 0x95, 0x1a, 0xa2, 0xbe, 0xa5, 0x74, 0x8f, 0xd4, 0x1d, 0x1d, 0x6c, 0xcd, 0xde, 0x3f, 0x16, 0xcd, 0x43, 0xe4, 0xb5, - 0x1c, 0x36, 0x6d, 0x52, 0xce, 0x87, 0x2f, 0x1b, 0x7d, 0x59, 0x5e, 0x6d, 0x4a, 0xb6, 0x41, 0xea, 0x4c, 0xb4, 0x79, - 0x0c, 0xa8, 0x6f, 0x0d, 0xbd, 0x0a, 0xbe, 0x60, 0xcd, 0x16, 0xfa, 0xe6, 0xbc, 0x5b, 0x60, 0x2c, 0xc1, 0x67, 0x0c, - 0x6d, 0x73, 0xee, 0xbe, 0x93, 0xee, 0xb3, 0x1c, 0xa6, 0x5c, 0x54, 0x4e, 0x51, 0x22, 0x89, 0xba, 0xff, 0x2f, 0xaf, - 0xf7, 0x52, 0x46, 0x7a, 0x79, 0x42, 0x87, 0x9d, 0xc2, 0xc3, 0x25, 0xab, 0x80, 0x62, 0xac, 0xad, 0xf4, 0xbc, 0x72, - 0x0a, 0x52, 0xa3, 0xa3, 0xb8, 0xd0, 0x7f, 0xf8, 0xca, 0x5d, 0xef, 0x36, 0xd6, 0xf4, 0x63, 0xca, 0x92, 0xbf, 0xf6, - 0x8d, 0x04, 0x6d, 0x5d, 0x11, 0x99, 0xfc, 0x9f, 0x48, 0x4c, 0x8e, 0x2c, 0xc4, 0xa3, 0x03, 0x68, 0x60, 0xa7, 0x4e, - 0xb6, 0xa0, 0xc5, 0x24, 0x09, 0x88, 0x2e, 0xd1, 0x1c, 0x4e, 0x00, 0x6d, 0xd2, 0x12, 0x4c, 0xc8, 0x6f, 0xf4, 0xbe, - 0xcb, 0x98, 0x27, 0xfc, 0x65, 0x1e, 0x4e, 0xa0, 0xfb, 0xe0, 0xd0, 0xa2, 0x09, 0x58, 0x45, 0x92, 0x86, 0xb5, 0xb6, - 0x9d, 0x0f, 0x27, 0xdb, 0x09, 0x49, 0xaa, 0xf7, 0xfb, 0xdc, 0x90, 0x42, 0xc8, 0xed, 0x28, 0x45, 0x4d, 0xe7, 0x7c, - 0xd5, 0xea, 0xcd, 0x21, 0xd6, 0xc5, 0x0c, 0x75, 0xcf, 0x40, 0x49, 0xdb, 0xce, 0x16, 0xe8, 0xf6, 0x09, 0xff, 0xf8, - 0xcb, 0x40, 0x13, 0x14, 0xcd, 0x1a, 0xb0, 0xa4, 0x00, 0xdc, 0xc6, 0x9c, 0xef, 0x35, 0x4f, 0xa9, 0xa2, 0xba, 0x83, - 0x30, 0x77, 0xd8, 0x90, 0x62, 0x54, 0xf7, 0xe1, 0x84, 0x05, 0x41, 0xbc, 0xf6, 0x44, 0x0e, 0x22, 0x3d, 0xa8, 0x4f, - 0x3a, 0x10, 0x32, 0xeb, 0x81, 0xb3, 0x86, 0x55, 0xd2, 0xad, 0xae, 0x59, 0xd7, 0x19, 0x7f, 0xf2, 0x43, 0xd6, 0xd9, - 0x40, 0xff, 0x64, 0xa3, 0xa4, 0x73, 0x5d, 0x44, 0x04, 0x4f, 0xe2, 0x65, 0x0e, 0x94, 0xe7, 0x3d, 0x4d, 0x39, 0xb5, - 0xfc, 0xf8, 0xef, 0x5b, 0x32, 0x87, 0xfa, 0x92, 0x35, 0xf9, 0x7b, 0xa7, 0x3f, 0x59, 0x44, 0x5e, 0x31, 0x35, 0x5f, - 0x2d, 0x26, 0x2b, 0x2f, 0x32, 0xce, 0x29, 0x91, 0x0a, 0x4e, 0xad, 0xe8, 0x7c, 0x22, 0x97, 0xd8, 0xc6, 0x1f, 0x04, - 0x32, 0x67, 0x8f, 0xec, 0x3d, 0x3b, 0xa8, 0x18, 0x2d, 0xa1, 0x20, 0x66, 0x51, 0x35, 0xf0, 0xed, 0xc1, 0x9b, 0x31, - 0xb3, 0xe7, 0xa4, 0x40, 0x8b, 0x51, 0x60, 0xcb, 0x85, 0x18, 0x0d, 0xf1, 0xaa, 0x64, 0xae, 0x24, 0xe1, 0xcf, 0x96, - 0x99, 0x12, 0x3f, 0x64, 0xa5, 0x0e, 0xee, 0xbc, 0x58, 0xb9, 0x64, 0xb9, 0x7c, 0x7e, 0xfd, 0x08, 0xec, 0x7a, 0xef, - 0x11, 0x31, 0xe3, 0xf5, 0x93, 0x05, 0xbb, 0x56, 0x80, 0x12, 0x19, 0xdd, 0x30, 0xee, 0x22, 0xa1, 0x46, 0xd9, 0x61, - 0x74, 0x05, 0x2a, 0x8e, 0x75, 0x2a, 0x0a, 0x00, 0xfe, 0x78, 0x3d, 0x54, 0x2e, 0x70, 0x7f, 0x3c, 0x11, 0x80, 0x32, - 0xca, 0xf4, 0x9d, 0xc9, 0x18, 0x10, 0x1d, 0x35, 0x13, 0xf8, 0x37, 0x61, 0xac, 0x9e, 0xfb, 0xec, 0xf8, 0x28, 0xee, - 0x65, 0x23, 0x0c, 0x34, 0x96, 0x65, 0x93, 0xcd, 0xba, 0x75, 0x5b, 0xe1, 0x4f, 0xc5, 0x0a, 0xa4, 0x29, 0x40, 0xf3, - 0x31, 0x6d, 0x04, 0x9c, 0x81, 0x31, 0xfb, 0x32, 0x81, 0x9a, 0x2a, 0x18, 0x47, 0x5f, 0x5b, 0x36, 0x3c, 0x1f, 0xd5, - 0xdd, 0x0f, 0x2e, 0x73, 0x81, 0x50, 0x16, 0x0b, 0x6c, 0x7b, 0xa1, 0x4e, 0xfc, 0x56, 0x90, 0x79, 0x7c, 0x5f, 0x0d, - 0x8b, 0x36, 0x1d, 0x2d, 0x2b, 0x2b, 0xac, 0x0f, 0x7a, 0xb4, 0x47, 0xb0, 0x1a, 0x29, 0x5a, 0xcf, 0x71, 0xb7, 0x02, - 0x1b, 0xd1, 0xe3, 0xd4, 0x60, 0xf5, 0x83, 0x49, 0x81, 0xe4, 0x60, 0xc8, 0xb6, 0x23, 0x96, 0x1a, 0x18, 0x82, 0x9a, - 0x97, 0xa7, 0x00, 0x6b, 0xa4, 0x76, 0xd3, 0xd2, 0x68, 0xf2, 0xaf, 0xda, 0xa2, 0xdf, 0xfa, 0x37, 0xb3, 0xde, 0x35, - 0x42, 0x24, 0xdb, 0xc3, 0xf9, 0xec, 0x0c, 0x2d, 0x98, 0x41, 0xa3, 0x22, 0xb4, 0x87, 0x50, 0x6a, 0x4e, 0x23, 0x31, - 0xa8, 0x85, 0x10, 0xd9, 0x9f, 0xb8, 0xb7, 0x9c, 0xf0, 0x3c, 0xe0, 0x1e, 0x9e, 0x95, 0x34, 0xe9, 0x34, 0x5f, 0x2a, - 0x23, 0xb8, 0x2b, 0x70, 0x8a, 0x12, 0xcc, 0x16, 0xf4, 0x4f, 0x7e, 0x7b, 0x57, 0x8a, 0x18, 0xae, 0x0b, 0x08, 0xa5, - 0xcf, 0x9e, 0x11, 0x45, 0xbb, 0xc8, 0x88, 0x56, 0x25, 0x4b, 0x70, 0x81, 0xec, 0x23, 0xdb, 0xcf, 0x46, 0x16, 0xcc, - 0x1a, 0xf6, 0x53, 0xdd, 0x88, 0xf6, 0x21, 0x30, 0x23, 0x36, 0xc7, 0x5e, 0x4f, 0x9e, 0x40, 0x43, 0xf4, 0xb0, 0x64, - 0x5a, 0x17, 0xb4, 0x74, 0x95, 0x62, 0xa5, 0x42, 0x37, 0xf1, 0xa8, 0x1f, 0xa9, 0x51, 0xab, 0xe5, 0xed, 0x10, 0x7d, - 0x04, 0x6b, 0x5e, 0xef, 0x9f, 0xe2, 0x5d, 0x43, 0x81, 0x98, 0x85, 0x3b, 0x56, 0xd6, 0x58, 0xd9, 0x63, 0x61, 0xe2, - 0xf0, 0x8d, 0x10, 0x0b, 0x4f, 0x85, 0xde, 0x4f, 0xf3, 0xbf, 0x36, 0x78, 0xf5, 0xb5, 0x50, 0xd6, 0x04, 0xe5, 0x87, - 0xc1, 0xc2, 0x99, 0x0b, 0x7c, 0x8c, 0xb1, 0xd3, 0xe1, 0x37, 0x8a, 0x68, 0x83, 0x44, 0x4b, 0x8a, 0x61, 0x0b, 0xb7, - 0x57, 0x12, 0x57, 0x49, 0x15, 0x1c, 0x45, 0x18, 0x5f, 0x70, 0xeb, 0xf1, 0x4b, 0xd6, 0x18, 0x13, 0x8e, 0xce, 0x39, - 0x28, 0x5b, 0x11, 0x12, 0xcc, 0x02, 0x9b, 0xf4, 0x70, 0x83, 0x65, 0x5a, 0x21, 0x25, 0x08, 0x31, 0xc9, 0x74, 0x3f, - 0x86, 0xa1, 0x12, 0x5b, 0x05, 0x41, 0x46, 0x65, 0x76, 0xe8, 0xc4, 0x19, 0x6d, 0x71, 0x98, 0x62, 0x8d, 0xf0, 0xa9, - 0xa6, 0x17, 0x21, 0x4a, 0x22, 0xef, 0x99, 0x5d, 0x63, 0x98, 0x40, 0x2b, 0x32, 0x55, 0x32, 0xfa, 0x2a, 0x06, 0xdc, - 0xfa, 0x6b, 0xed, 0x43, 0xc1, 0x3a, 0xb8, 0x86, 0x5e, 0xaa, 0xe2, 0xaf, 0x4e, 0xa1, 0x55, 0xea, 0x92, 0x54, 0x49, - 0x4f, 0xa6, 0x90, 0xe6, 0xbc, 0x82, 0x1e, 0xce, 0x79, 0x88, 0xb7, 0x02, 0xde, 0x2a, 0xf8, 0x04, 0x5a, 0xd2, 0x08, - 0xf7, 0x2d, 0xbb, 0xda, 0x3e, 0x2b, 0x91, 0xed, 0xe7, 0xe6, 0x64, 0xc4, 0xb9, 0x0e, 0x34, 0x7a, 0x0e, 0x0b, 0x2f, - 0x83, 0x16, 0x7d, 0xa7, 0x06, 0xee, 0x4a, 0x44, 0xdf, 0xfa, 0x43, 0x0b, 0x8a, 0x35, 0xab, 0x54, 0xc0, 0x9e, 0xa9, - 0xf7, 0x23, 0x21, 0xf1, 0x58, 0xfe, 0xb1, 0xa7, 0xc7, 0x24, 0x51, 0xb5, 0x3c, 0x81, 0x91, 0x08, 0x51, 0x93, 0x41, - 0xd6, 0xfa, 0x04, 0x83, 0xae, 0x59, 0xae, 0x52, 0x73, 0x85, 0x30, 0x87, 0x32, 0xdd, 0xd5, 0xda, 0x2e, 0x00, 0x4e, - 0x5f, 0xad, 0xe7, 0x2b, 0xd0, 0x69, 0x61, 0x06, 0x28, 0x71, 0xa6, 0x47, 0x75, 0xc6, 0xc1, 0xa9, 0x6e, 0x11, 0xff, - 0xeb, 0x95, 0x4a, 0x58, 0x7b, 0xf0, 0x70, 0x50, 0xf1, 0xa4, 0x82, 0xfc, 0x6c, 0xa0, 0x29, 0x0d, 0x03, 0x52, 0x70, - 0x4e, 0x62, 0x57, 0x2c, 0xa7, 0x8b, 0x47, 0x5e, 0x19, 0x23, 0x9c, 0xc0, 0xba, 0xd3, 0xa7, 0xd3, 0x41, 0x31, 0x2e, - 0xd1, 0x52, 0x17, 0x35, 0xe7, 0xd6, 0x49, 0x5a, 0xee, 0x40, 0xf1, 0x57, 0x96, 0xa8, 0x6b, 0x91, 0x4e, 0x96, 0x2d, - 0xae, 0xea, 0xab, 0x31, 0xed, 0x82, 0x08, 0x2b, 0x6a, 0xe4, 0xd6, 0x42, 0x9d, 0xed, 0x77, 0x5e, 0xde, 0x50, 0x8c, - 0xe3, 0x39, 0xbf, 0xd6, 0xca, 0xc3, 0xb3, 0x96, 0x52, 0x2f, 0xde, 0x32, 0x47, 0xd3, 0x89, 0x35, 0x5f, 0x6a, 0x84, - 0x67, 0xe2, 0x2e, 0x22, 0xc3, 0x68, 0x80, 0xe9, 0xdb, 0xaa, 0x45, 0x2c, 0xa4, 0x1d, 0x40, 0x3f, 0x17, 0xd4, 0x39, - 0x00, 0x0c, 0x45, 0x28, 0x3b, 0x00, 0xae, 0x42, 0xb5, 0x5e, 0xcf, 0x2b, 0x6d, 0x6c, 0xf6, 0x27, 0x72, 0x42, 0x10, - 0x56, 0xbc, 0xa4, 0x50, 0x0a, 0x99, 0x40, 0x5e, 0xe2, 0x52, 0x95, 0xdc, 0x4e, 0xcb, 0x66, 0xd3, 0xb9, 0xc3, 0x37, - 0xd2, 0x00, 0x44, 0x4d, 0x5a, 0x66, 0xb2, 0x81, 0x0d, 0x55, 0xca, 0x94, 0xa7, 0x49, 0xad, 0x06, 0x5c, 0xf3, 0xc1, - 0x35, 0x70, 0x24, 0xe0, 0xec, 0xc0, 0xb5, 0x20, 0x0e, 0xbb, 0x66, 0xc8, 0x35, 0x75, 0x4e, 0x79, 0x8c, 0xfe, 0x6b, - 0xab, 0x35, 0xb6, 0x5f, 0x7d, 0x2d, 0x4d, 0xde, 0x4f, 0xc7, 0x48, 0x2b, 0x03, 0x52, 0x3b, 0xf9, 0xbf, 0x36, 0xa4, - 0x9c, 0xfd, 0x58, 0x88, 0xb5, 0xff, 0x9b, 0x91, 0x39, 0x9f, 0x57, 0xcf, 0x0e, 0x13, 0x37, 0x18, 0x53, 0x21, 0x8e, - 0x71, 0x12, 0x5e, 0x6c, 0x87, 0x57, 0x8d, 0x41, 0xed, 0xd7, 0x0b, 0x18, 0x72, 0xdc, 0xb1, 0xf7, 0x1e, 0x18, 0xce, - 0xbe, 0xd8, 0x5b, 0x34, 0x56, 0x87, 0xb4, 0x28, 0x96, 0x7d, 0x00, 0xe9, 0x67, 0xf9, 0xfe, 0x7f, 0xdc, 0xdc, 0xa5, - 0x41, 0x2d, 0x23, 0x2f, 0x71, 0xc9, 0x42, 0xb3, 0xfc, 0x5e, 0x52, 0xac, 0x4f, 0x1b, 0xe1, 0x12, 0xcd, 0x95, 0xd5, - 0xff, 0x82, 0x65, 0xcb, 0xea, 0x2e, 0xe5, 0xe1, 0xde, 0x81, 0x09, 0x8d, 0x6f, 0x6e, 0x7c, 0x4c, 0x9d, 0x35, 0x95, - 0x6e, 0xc6, 0xbb, 0x38, 0xc4, 0xae, 0xb7, 0x8d, 0x2a, 0xb6, 0x8b, 0x8c, 0xa9, 0x68, 0x6a, 0xf5, 0xd1, 0x0c, 0x22, - 0x37, 0xb4, 0xa0, 0xfd, 0x5b, 0x4c, 0x3a, 0x58, 0x3c, 0x28, 0xc3, 0xa5, 0xd1, 0xf2, 0xba, 0x10, 0x3b, 0x0a, 0x2e, - 0xc9, 0x48, 0x4a, 0x12, 0x64, 0x48, 0xf7, 0x1d, 0x17, 0x0f, 0x9a, 0x42, 0xd5, 0x88, 0xdb, 0x95, 0x64, 0xbf, 0xe2, - 0xfe, 0xa5, 0x7e, 0xdc, 0x30, 0xea, 0xca, 0x39, 0x50, 0x89, 0xcf, 0x9a, 0x6c, 0x4e, 0x88, 0x8e, 0xda, 0x36, 0xeb, - 0x28, 0xca, 0x91, 0x5f, 0x29, 0x25, 0xea, 0x5f, 0xd1, 0x1b, 0x48, 0xb6, 0x08, 0x60, 0x60, 0x1b, 0x80, 0xd5, 0x6f, - 0xd6, 0x2c, 0xd5, 0x32, 0x40, 0xe3, 0x57, 0xb0, 0x6b, 0x3e, 0x3e, 0x75, 0x37, 0xfa, 0x05, 0xd1, 0xd8, 0x5a, 0xd1, - 0x04, 0x97, 0xdd, 0x0b, 0xab, 0x37, 0xe2, 0xf7, 0xd4, 0xdb, 0x23, 0x88, 0x0d, 0xe4, 0xd3, 0x74, 0xbf, 0x4b, 0x4d, - 0x1f, 0x90, 0xf4, 0x3d, 0x18, 0x63, 0x1f, 0x83, 0x5d, 0x51, 0x4f, 0xad, 0xde, 0x54, 0x95, 0x43, 0x20, 0xf7, 0x74, - 0x35, 0x2a, 0xe6, 0xf1, 0x57, 0xb4, 0x5b, 0x6b, 0xd9, 0x61, 0x78, 0x95, 0x2f, 0xa0, 0x6c, 0xd1, 0xae, 0x29, 0x22, - 0xc9, 0x65, 0x8c, 0x4b, 0x15, 0x80, 0x12, 0x58, 0x90, 0x93, 0x1a, 0xbb, 0x3a, 0xdd, 0xb2, 0x79, 0xf9, 0x3a, 0x9a, - 0x90, 0x6f, 0xfd, 0xb4, 0xf2, 0xb9, 0x19, 0x1c, 0x55, 0xd4, 0x21, 0x02, 0xd3, 0x40, 0x1d, 0x16, 0x70, 0x18, 0xa9, - 0xf3, 0x52, 0x04, 0x0e, 0x78, 0x37, 0xe8, 0x73, 0xcd, 0x40, 0x51, 0x70, 0x88, 0xbc, 0x8b, 0x1a, 0x2c, 0xf0, 0x1c, - 0x3c, 0x49, 0xb4, 0x71, 0x74, 0xf8, 0xef, 0x82, 0x8e, 0xa2, 0x43, 0xb2, 0x94, 0xf5, 0xbd, 0x32, 0x15, 0xc9, 0x49, - 0xea, 0x22, 0xe9, 0xfc, 0x54, 0x9e, 0xa9, 0x4d, 0x6e, 0xcd, 0x5f, 0x24, 0x9f, 0xc6, 0xc9, 0xd8, 0x0b, 0xd8, 0xaf, - 0x61, 0xc4, 0xae, 0xf3, 0x17, 0x36, 0x9f, 0xf6, 0xcc, 0xb2, 0x46, 0xab, 0x33, 0xe0, 0x81, 0xa4, 0x13, 0x61, 0x29, - 0xbb, 0x64, 0x2e, 0x65, 0x00, 0x28, 0xd7, 0xc6, 0xcb, 0xbb, 0x21, 0xc4, 0xe7, 0xe2, 0xfa, 0x8e, 0x48, 0xa8, 0x4c, - 0x35, 0x33, 0xe3, 0xb9, 0x47, 0x11, 0x21, 0x2c, 0xd5, 0xce, 0x2c, 0x6e, 0xb3, 0xed, 0xed, 0x6c, 0x78, 0x5e, 0xb3, - 0xfd, 0xb1, 0xc0, 0x14, 0xf5, 0xa0, 0xbf, 0x8b, 0x8b, 0xa4, 0xca, 0x20, 0x44, 0xcc, 0xe0, 0x03, 0xae, 0x86, 0xb0, - 0x4b, 0xa5, 0xa2, 0x3f, 0xdb, 0x25, 0x8a, 0x9f, 0x5e, 0xa5, 0xaa, 0xc2, 0xe5, 0x48, 0xc8, 0xc4, 0x96, 0xda, 0x80, - 0x25, 0x02, 0x3c, 0xf2, 0xe4, 0x16, 0xb7, 0x65, 0xb9, 0x1b, 0x11, 0x9c, 0x16, 0x2d, 0x9d, 0x9c, 0xb0, 0x4c, 0xe8, - 0x3b, 0xd9, 0xf5, 0xae, 0x29, 0xc2, 0xec, 0x7e, 0x93, 0x6e, 0x7f, 0x94, 0xd2, 0x57, 0x95, 0xc6, 0x1d, 0xb8, 0xc6, - 0x12, 0xb8, 0xf0, 0x18, 0xd1, 0x6a, 0x68, 0x54, 0x9f, 0x7a, 0x44, 0xf1, 0xa8, 0xd6, 0x24, 0xc7, 0x41, 0xeb, 0x30, - 0x71, 0xa5, 0xa5, 0x81, 0xe2, 0x42, 0xec, 0xac, 0x43, 0x76, 0x3a, 0x0b, 0xf9, 0x92, 0x73, 0xb3, 0x75, 0x92, 0xc8, - 0x17, 0xb5, 0x0f, 0x45, 0x33, 0x12, 0x73, 0xf5, 0x5d, 0x7e, 0xce, 0xd1, 0x8f, 0x77, 0x57, 0xf9, 0x8a, 0xb7, 0x8e, - 0x73, 0x92, 0xcc, 0x27, 0xf1, 0xa2, 0xe5, 0x9f, 0xcb, 0xd2, 0x46, 0x0b, 0x4f, 0xe2, 0xd1, 0x0f, 0xa7, 0x8a, 0xfa, - 0x35, 0x12, 0x9a, 0x75, 0x52, 0xeb, 0x59, 0x79, 0x25, 0xe5, 0x7c, 0xb7, 0x47, 0x8a, 0x25, 0x62, 0x8e, 0x71, 0xb9, - 0xe4, 0x69, 0x55, 0x2d, 0x1d, 0x7d, 0x7f, 0x86, 0xe7, 0x52, 0x76, 0x02, 0x60, 0x22, 0xa9, 0x8f, 0xb0, 0xa2, 0xbd, - 0x8c, 0x1a, 0x21, 0xf6, 0x82, 0xd1, 0xb2, 0x84, 0x17, 0xfb, 0xcd, 0xad, 0x07, 0x21, 0x5b, 0x92, 0xee, 0xee, 0x2d, - 0x08, 0x5f, 0xf0, 0xd3, 0x03, 0xa7, 0x75, 0xa4, 0x26, 0x2f, 0xce, 0x42, 0x94, 0x78, 0x89, 0x74, 0x18, 0xb5, 0xb5, - 0x9c, 0x9b, 0xb0, 0x92, 0x34, 0x86, 0xdc, 0x1a, 0x65, 0xd5, 0xb0, 0xa5, 0x18, 0x73, 0x20, 0xe3, 0x91, 0x79, 0x06, - 0xfa, 0x1e, 0xe0, 0x4d, 0x6e, 0x6d, 0x49, 0xb2, 0xee, 0x9e, 0xca, 0xc8, 0xbc, 0xe8, 0xb3, 0xe4, 0xfc, 0xb8, 0x95, - 0xd8, 0x50, 0xdc, 0x49, 0xb9, 0x62, 0x3d, 0x71, 0x90, 0x5d, 0x9a, 0xbc, 0x2f, 0x51, 0x44, 0xc9, 0x4a, 0xa7, 0xff, - 0x39, 0x37, 0x1c, 0x77, 0x3a, 0x34, 0xd1, 0xea, 0xd8, 0x76, 0x68, 0x25, 0xe6, 0xe1, 0xd7, 0xe5, 0x9a, 0xaa, 0x05, - 0xb4, 0x80, 0x39, 0x22, 0x4a, 0xdd, 0x0c, 0x71, 0x93, 0xa4, 0xe3, 0x05, 0xc2, 0xdf, 0x6e, 0x33, 0x13, 0x5f, 0x76, - 0x7f, 0x97, 0x23, 0x34, 0x35, 0x94, 0xe4, 0x01, 0x14, 0x97, 0x6f, 0xc2, 0x9b, 0x31, 0x15, 0xf1, 0x0d, 0xfb, 0xcc, - 0x59, 0x6a, 0x0f, 0x5e, 0xa0, 0x4d, 0x4f, 0x82, 0xd5, 0x89, 0x1b, 0x40, 0x89, 0x4c, 0x10, 0x20, 0xbb, 0xc7, 0x00, - 0x96, 0x06, 0xd9, 0x8b, 0x26, 0xd3, 0x00, 0x22, 0x5b, 0x8c, 0xad, 0x61, 0x8e, 0xcd, 0x15, 0xa0, 0x05, 0x3b, 0xf3, - 0x4b, 0xa0, 0x6c, 0x60, 0x87, 0x77, 0xf4, 0x3f, 0x79, 0x43, 0x0c, 0x31, 0xa6, 0xa9, 0x4d, 0x3b, 0xeb, 0x55, 0x90, - 0xbd, 0xeb, 0x63, 0x16, 0x07, 0xe4, 0xc0, 0x75, 0x43, 0x69, 0xec, 0x8c, 0xd5, 0x35, 0x0d, 0x68, 0xa5, 0xa8, 0xae, - 0x08, 0x84, 0x24, 0x10, 0xf3, 0xf2, 0x50, 0x48, 0x4d, 0x42, 0xb5, 0x74, 0xd3, 0xa9, 0x6d, 0x82, 0xc2, 0xec, 0x78, - 0x6a, 0xf2, 0xd0, 0x4b, 0xe0, 0xed, 0xdb, 0x5b, 0x8b, 0x01, 0x47, 0xe1, 0x4a, 0x96, 0x32, 0xea, 0x57, 0xe6, 0xcd, - 0x7a, 0x58, 0xcb, 0x5f, 0x1c, 0xd0, 0x6e, 0x57, 0x8e, 0x19, 0xd5, 0x4e, 0xf5, 0x42, 0x70, 0x7a, 0x67, 0x80, 0x46, - 0x44, 0x02, 0x6c, 0xe0, 0x47, 0xfd, 0x8e, 0x54, 0x2c, 0x51, 0xd6, 0x56, 0x5e, 0xcd, 0xfa, 0x03, 0x16, 0x22, 0x8d, - 0x2b, 0x6c, 0x9c, 0xb3, 0x68, 0x55, 0x23, 0x99, 0x90, 0xa0, 0x07, 0x32, 0xb2, 0x73, 0x56, 0x93, 0xe0, 0xeb, 0x94, - 0x06, 0x5f, 0x70, 0x7a, 0xfc, 0xb5, 0x0e, 0x50, 0x8e, 0x7f, 0x71, 0xf6, 0xba, 0x57, 0xe1, 0x88, 0xeb, 0x11, 0xf3, - 0x45, 0x9d, 0x97, 0x3f, 0xdc, 0x19, 0x39, 0xfd, 0x7b, 0xcb, 0x0c, 0x40, 0x95, 0xbf, 0x58, 0x26, 0x80, 0x54, 0x1e, - 0xdc, 0x79, 0x23, 0x3a, 0x4b, 0x76, 0x14, 0x8d, 0x59, 0x3b, 0x69, 0x09, 0x3b, 0x98, 0x15, 0x47, 0x10, 0x2a, 0xfe, - 0xc5, 0x08, 0x20, 0x71, 0x14, 0xb4, 0xec, 0x68, 0xd0, 0x8a, 0xf6, 0x40, 0x9d, 0x93, 0x12, 0x61, 0x63, 0x5e, 0x88, - 0x0d, 0xf9, 0xfa, 0xe6, 0x04, 0x07, 0x59, 0x43, 0x12, 0x3c, 0xa8, 0xb7, 0x6f, 0x8a, 0x6c, 0x97, 0x1d, 0xa6, 0xde, - 0xf4, 0xf8, 0x3d, 0x97, 0x80, 0x90, 0x16, 0x0f, 0x91, 0x8f, 0xdd, 0x48, 0xcc, 0x6e, 0x3d, 0xde, 0x76, 0xc4, 0xa2, - 0x6f, 0x27, 0xa2, 0x54, 0xea, 0xb8, 0x36, 0x0f, 0x51, 0x10, 0x56, 0x18, 0x4a, 0x70, 0xf9, 0x55, 0x40, 0x6c, 0xa2, - 0xa0, 0xb1, 0x8f, 0xe5, 0x4c, 0x39, 0x6c, 0xb2, 0x0f, 0xe7, 0x2f, 0x75, 0xad, 0xff, 0x08, 0xb5, 0xce, 0x9e, 0xc0, - 0xaf, 0x18, 0xd8, 0x7b, 0x28, 0x83, 0x75, 0x4a, 0xdc, 0xb5, 0xe0, 0xa1, 0x0c, 0xca, 0x7d, 0x18, 0x48, 0x08, 0xc5, - 0xf5, 0x71, 0xd8, 0x14, 0xbb, 0x96, 0x18, 0x01, 0x3e, 0x4a, 0x66, 0xa5, 0x36, 0x1d, 0xc3, 0x95, 0x30, 0xe0, 0xf2, - 0x52, 0x8f, 0xe7, 0xa3, 0x9b, 0xdd, 0x95, 0x46, 0x1a, 0xfa, 0x6e, 0xe0, 0x78, 0xb9, 0x39, 0x4c, 0x95, 0x45, 0x5b, - 0x37, 0x25, 0x2c, 0x75, 0x81, 0xc8, 0x8c, 0x10, 0x31, 0xb7, 0x6c, 0xd2, 0x90, 0x38, 0xdb, 0xe9, 0x04, 0x7d, 0x6c, - 0x60, 0x38, 0x83, 0xd9, 0x54, 0xb5, 0xb5, 0x7b, 0x53, 0x58, 0xff, 0xcc, 0xb2, 0x0d, 0xfc, 0x7c, 0x39, 0x23, 0x21, - 0xa0, 0x61, 0xa1, 0x17, 0x11, 0xc2, 0x7a, 0x38, 0xca, 0xb3, 0x97, 0xd8, 0x70, 0x21, 0x43, 0x87, 0xe3, 0x87, 0x63, - 0xb3, 0x17, 0x34, 0xc7, 0xcf, 0xa7, 0xc7, 0xc6, 0xbe, 0x56, 0xd3, 0x24, 0x0b, 0x2e, 0x65, 0xe1, 0x74, 0xfd, 0xc8, - 0x11, 0xc5, 0x67, 0xda, 0x75, 0xdf, 0xc1, 0xe6, 0x33, 0x29, 0x73, 0x52, 0xe9, 0x26, 0x02, 0x95, 0x81, 0x4c, 0xde, - 0xed, 0x05, 0xc0, 0xb6, 0x01, 0xfa, 0xa2, 0xb9, 0xc8, 0x4c, 0x65, 0x9f, 0x74, 0x5e, 0x1e, 0x22, 0x65, 0x7b, 0x78, - 0x73, 0x58, 0x86, 0x80, 0xd7, 0xa7, 0x35, 0xfb, 0x37, 0x3c, 0x0d, 0xd2, 0x75, 0xb4, 0x31, 0x2a, 0x92, 0xe6, 0x82, - 0xc9, 0x35, 0x2a, 0xa6, 0xc1, 0x43, 0x38, 0x69, 0xc0, 0xa9, 0x52, 0x4e, 0xb8, 0x20, 0x79, 0x81, 0x49, 0x2a, 0xf6, - 0x04, 0x5a, 0xdb, 0x40, 0x44, 0x45, 0x0d, 0x3f, 0xba, 0x8c, 0x8b, 0x47, 0x69, 0x67, 0x4f, 0xa2, 0xa2, 0xfe, 0xda, - 0x7b, 0xd2, 0x0a, 0x61, 0x9f, 0x53, 0xdd, 0xf5, 0x1a, 0x8f, 0xcd, 0x08, 0x8a, 0x5e, 0xd3, 0xd4, 0xff, 0x65, 0x18, - 0x84, 0xbb, 0xcb, 0x76, 0x0e, 0x82, 0x82, 0x1c, 0x21, 0xc0, 0x4f, 0x5e, 0xd0, 0x97, 0x00, 0x6b, 0xe8, 0x88, 0x03, - 0x79, 0x7e, 0x6d, 0x8f, 0xa4, 0x73, 0xf5, 0xd5, 0xb9, 0xef, 0x7f, 0xc5, 0xd1, 0x1a, 0xef, 0x9f, 0x61, 0xec, 0x1f, - 0x9f, 0x29, 0x6d, 0xce, 0x1e, 0x33, 0xf1, 0xe8, 0x44, 0xf6, 0xb7, 0x8d, 0x49, 0x8a, 0xb7, 0xc7, 0x4a, 0x81, 0x7f, - 0xf8, 0x40, 0xf2, 0x36, 0x0b, 0xe7, 0x46, 0x12, 0xf3, 0xdb, 0xd9, 0xaa, 0x93, 0x9f, 0x1c, 0xd7, 0xca, 0x7d, 0xd6, - 0x24, 0x7f, 0xcc, 0xa5, 0x1d, 0xf0, 0x9d, 0xab, 0xce, 0xce, 0xad, 0xe4, 0xd6, 0x38, 0xe7, 0xf8, 0xcd, 0xb7, 0xbb, - 0x55, 0xea, 0xcd, 0xff, 0x95, 0xd5, 0xe2, 0x3a, 0x75, 0xc3, 0x25, 0xde, 0x40, 0x41, 0x50, 0xb8, 0xc3, 0x3a, 0xbd, - 0xcc, 0x5d, 0xe3, 0x0e, 0xa3, 0xc1, 0xda, 0xfa, 0xaa, 0xc8, 0x3c, 0x32, 0x17, 0x31, 0xce, 0x67, 0xe2, 0x65, 0x35, - 0x65, 0xdb, 0xa0, 0xdf, 0x35, 0x15, 0xe6, 0x3f, 0xbf, 0x86, 0x3a, 0xdb, 0xb1, 0xf9, 0x53, 0xe5, 0xdf, 0x80, 0x6b, - 0xe8, 0x50, 0x8e, 0xa2, 0xe0, 0xc4, 0x75, 0xcd, 0xb4, 0x4d, 0xce, 0xb5, 0x70, 0x5c, 0xbb, 0x1c, 0x78, 0xb5, 0x49, - 0x9c, 0x41, 0x94, 0x56, 0xc6, 0x3d, 0xa7, 0x4f, 0xbb, 0xfc, 0xce, 0xb8, 0x63, 0xd8, 0x75, 0x30, 0x0a, 0x82, 0x01, - 0x25, 0x16, 0x6d, 0x50, 0x77, 0x32, 0xba, 0x9a, 0xd8, 0xb3, 0x06, 0x62, 0x09, 0xac, 0x68, 0x7e, 0xab, 0x04, 0xa0, - 0xa5, 0x1d, 0x78, 0x59, 0xaf, 0x12, 0xc9, 0x92, 0xd5, 0x37, 0x0e, 0xe6, 0x7f, 0x88, 0x50, 0x04, 0xe7, 0xdb, 0x38, - 0xc4, 0x8b, 0x4a, 0x91, 0x98, 0x53, 0xec, 0xd1, 0x9b, 0xec, 0xa3, 0x5e, 0x82, 0x34, 0xff, 0x06, 0x18, 0x20, 0x60, - 0xc3, 0x71, 0x2c, 0x10, 0x94, 0xcc, 0xcf, 0xf1, 0xe5, 0xce, 0x5e, 0xbe, 0xf9, 0x04, 0x53, 0xfb, 0x37, 0x9e, 0xdb, - 0xc8, 0xfd, 0xdb, 0x50, 0xc9, 0xed, 0xcf, 0x2c, 0xee, 0xff, 0x2c, 0x9e, 0xdd, 0xbf, 0xe5, 0x1f, 0xbf, 0x6e, 0x5a, - 0xe0, 0x9d, 0xce, 0xfb, 0x48, 0x02, 0x35, 0x3f, 0x5f, 0x67, 0xa4, 0x60, 0x18, 0x11, 0x7c, 0xed, 0xf8, 0x30, 0xa2, - 0xfb, 0xad, 0x67, 0x03, 0x6b, 0x62, 0x1f, 0xe3, 0x16, 0xd5, 0xeb, 0x79, 0x81, 0xed, 0x6a, 0x5c, 0xcb, 0xf4, 0xb2, - 0xd0, 0x9a, 0xa7, 0xca, 0x2e, 0x15, 0x1a, 0x09, 0x07, 0x5b, 0xc0, 0x3b, 0xb8, 0xeb, 0xca, 0x9d, 0xbd, 0xb4, 0x66, - 0x36, 0xe5, 0x49, 0x82, 0x9c, 0x0e, 0x5c, 0x34, 0x7d, 0xf5, 0xd4, 0xb6, 0xc4, 0x18, 0xfe, 0x9c, 0x37, 0xd5, 0x18, - 0x15, 0x3d, 0x46, 0x23, 0x19, 0xb1, 0x72, 0x56, 0x46, 0xcb, 0x8b, 0x61, 0x68, 0x4b, 0xc6, 0xc5, 0xac, 0xb2, 0xa0, - 0x0c, 0xb8, 0x07, 0x42, 0xd6, 0x0b, 0xfa, 0xd6, 0x4e, 0x91, 0x0f, 0xd5, 0x27, 0x1c, 0xb0, 0x79, 0x3c, 0xc1, 0x71, - 0xe9, 0xa3, 0x7a, 0x40, 0x9a, 0xc4, 0x55, 0xb8, 0x86, 0xb3, 0xc9, 0xaa, 0x8a, 0xe7, 0xcd, 0x4f, 0xdb, 0x00, 0x73, - 0x5a, 0xb0, 0x7f, 0x73, 0x5b, 0xa2, 0xdc, 0x4f, 0x82, 0xda, 0x2e, 0x1a, 0x55, 0x8d, 0xb2, 0x00, 0xa2, 0x4c, 0x9f, - 0xde, 0x40, 0x02, 0xd1, 0x39, 0xd5, 0x8b, 0xe6, 0xdb, 0xd4, 0x76, 0x38, 0x37, 0x45, 0xa0, 0x16, 0x2e, 0x8d, 0xd1, - 0x6c, 0xa6, 0x70, 0xc2, 0x7b, 0x97, 0xf6, 0x3c, 0x5d, 0x20, 0x4f, 0xb6, 0x80, 0x49, 0xdf, 0x0b, 0x3c, 0x6b, 0x00, - 0x0f, 0x08, 0xf4, 0x28, 0xaa, 0xd0, 0xc0, 0x9a, 0x82, 0x1d, 0x8c, 0x8a, 0x34, 0x0e, 0x80, 0x64, 0x9f, 0x46, 0xdc, - 0x80, 0x83, 0x73, 0x34, 0x86, 0x8e, 0x6d, 0xcf, 0xe4, 0x95, 0x14, 0x82, 0xa0, 0xca, 0x66, 0x89, 0xcd, 0x68, 0xb2, - 0x17, 0x95, 0x6f, 0x70, 0xb3, 0x73, 0x27, 0x18, 0xfb, 0x9d, 0xce, 0x00, 0xa6, 0xac, 0xa2, 0x77, 0x48, 0xcd, 0x88, - 0x17, 0x3a, 0x29, 0x9a, 0x1c, 0x88, 0x48, 0x46, 0xcc, 0x75, 0xe3, 0xb7, 0x7f, 0x1e, 0xe5, 0x66, 0x63, 0x5b, 0x6c, - 0x56, 0x3c, 0x23, 0x58, 0xef, 0xe0, 0xea, 0x2c, 0xbc, 0xd6, 0x33, 0xb2, 0x50, 0xf8, 0xc7, 0x30, 0xb9, 0x53, 0xdf, - 0xf7, 0xc4, 0x88, 0xe6, 0xf2, 0x7f, 0x97, 0xb1, 0xab, 0xca, 0x69, 0x34, 0x86, 0x86, 0x48, 0x46, 0x36, 0x01, 0x48, - 0xe6, 0x59, 0xd3, 0x31, 0x9a, 0x8d, 0xd5, 0xb6, 0x73, 0x9a, 0x66, 0x3f, 0x7e, 0xe5, 0xf4, 0xd7, 0x06, 0xc7, 0x03, - 0xe4, 0xe7, 0xce, 0x8d, 0x72, 0xf6, 0x03, 0x5b, 0xcc, 0xa1, 0xc7, 0xb9, 0x5c, 0xd5, 0x37, 0x8a, 0x5c, 0x8d, 0x90, - 0x8b, 0x41, 0xdf, 0x0d, 0x2a, 0x1e, 0x10, 0x40, 0x7f, 0x02, 0x5f, 0x79, 0x79, 0xfe, 0x5f, 0xa3, 0xb9, 0xe3, 0x91, - 0x60, 0x63, 0xe5, 0x32, 0x9c, 0xc4, 0xcb, 0x61, 0x3c, 0xe0, 0xe8, 0x39, 0x91, 0xf8, 0xb4, 0x22, 0xe9, 0x11, 0x89, - 0x0c, 0xe3, 0x91, 0x59, 0x1a, 0x52, 0x9c, 0x61, 0x84, 0xe2, 0x2f, 0xab, 0xdf, 0xae, 0xbb, 0x6f, 0x20, 0xc5, 0xbf, - 0x71, 0x5d, 0x1d, 0xcf, 0x8d, 0x2a, 0x33, 0xe9, 0x65, 0x73, 0xdc, 0x92, 0xb3, 0x9a, 0x56, 0x33, 0x9f, 0xb5, 0x4b, - 0xa6, 0xed, 0xe6, 0xb1, 0x9c, 0x19, 0x3f, 0x4f, 0x13, 0xc9, 0xe0, 0x6f, 0xce, 0x61, 0x80, 0x16, 0x06, 0xda, 0x4b, - 0xec, 0xd4, 0xa0, 0xd3, 0xd5, 0x9b, 0x0d, 0x31, 0xda, 0xae, 0xd6, 0xe9, 0x07, 0x5c, 0x2f, 0xe8, 0x18, 0x76, 0xd6, - 0x74, 0xf2, 0x9c, 0x10, 0xbb, 0x28, 0xf8, 0xf1, 0xfb, 0xae, 0xa0, 0xd4, 0x34, 0xa0, 0x5f, 0xe7, 0xe5, 0xe5, 0xae, - 0x76, 0x91, 0x81, 0x9a, 0x09, 0xe8, 0x90, 0xdd, 0x30, 0xe6, 0x58, 0x17, 0x63, 0x0f, 0xd2, 0x85, 0x71, 0x6b, 0xf6, - 0x41, 0x68, 0x8c, 0xb2, 0x70, 0x65, 0x4c, 0x2e, 0x0a, 0x5f, 0x93, 0x93, 0x6b, 0xb8, 0xa0, 0x25, 0xb4, 0xcf, 0xbd, - 0x77, 0x0e, 0xd3, 0x3d, 0xc2, 0x51, 0x5b, 0x7a, 0x91, 0x16, 0xea, 0xcd, 0x42, 0x79, 0x56, 0x80, 0x16, 0x2c, 0x52, - 0x4f, 0xab, 0xe5, 0xc8, 0xe5, 0x5d, 0x3f, 0x3a, 0x3d, 0x75, 0xab, 0xb5, 0xdc, 0x63, 0x4a, 0x03, 0xe1, 0x1d, 0xad, - 0xec, 0xbf, 0xe2, 0x25, 0x47, 0x2a, 0x6c, 0xd5, 0x2c, 0x93, 0xaf, 0xc8, 0xf5, 0x3f, 0x6a, 0x7a, 0x13, 0xef, 0x13, - 0xae, 0x0a, 0x84, 0x3b, 0x12, 0xa1, 0x33, 0x9e, 0x32, 0xeb, 0x68, 0x1d, 0xaf, 0xa9, 0x13, 0x3b, 0x1e, 0x1e, 0x17, - 0x28, 0x86, 0xdf, 0x9a, 0xd1, 0x80, 0xe7, 0xbe, 0x78, 0x11, 0xec, 0x5e, 0xfb, 0x2e, 0x39, 0x33, 0x8b, 0x6c, 0x7f, - 0xd5, 0x6a, 0xdc, 0x85, 0xd8, 0xb4, 0xca, 0xdc, 0x15, 0xfb, 0xec, 0x30, 0x9c, 0x6b, 0xc6, 0x17, 0x07, 0xb7, 0x7b, - 0x23, 0x77, 0x07, 0x6f, 0x9e, 0x12, 0x47, 0xd7, 0x02, 0x1e, 0x97, 0x9b, 0xbc, 0x5b, 0x55, 0xba, 0x5f, 0x1b, 0xf5, - 0x6a, 0x5f, 0x23, 0xfb, 0x92, 0x80, 0xe4, 0x71, 0x3d, 0xa4, 0x88, 0xe3, 0xa9, 0xc8, 0xd6, 0x84, 0xb1, 0x0e, 0x0a, - 0x1e, 0x6a, 0x3d, 0xb7, 0xed, 0xa4, 0xf6, 0x83, 0x72, 0xb7, 0x2e, 0xca, 0xca, 0xc3, 0xe1, 0xb7, 0xcd, 0x8f, 0x07, - 0xee, 0x25, 0x85, 0xe2, 0xa1, 0xfa, 0x2a, 0x02, 0x03, 0xee, 0x57, 0xd4, 0x9a, 0xcc, 0x8a, 0xe3, 0x27, 0xec, 0x94, - 0xca, 0x14, 0xa3, 0x83, 0x9b, 0xb6, 0x3b, 0x4d, 0x03, 0x18, 0x1d, 0xd3, 0x75, 0xb2, 0x33, 0xf5, 0xf8, 0x84, 0x88, - 0x1c, 0x53, 0xfb, 0x9f, 0xca, 0x8b, 0xd3, 0x01, 0xde, 0x07, 0xfb, 0xaf, 0x98, 0x40, 0x6c, 0xad, 0xbb, 0x49, 0x9d, - 0x86, 0x48, 0xc1, 0x87, 0x35, 0x6d, 0xfc, 0x5f, 0x7c, 0x2e, 0x8c, 0x26, 0xa2, 0x77, 0xea, 0xad, 0x2b, 0x25, 0xb0, - 0x5d, 0xed, 0x52, 0xe8, 0xb6, 0xb7, 0xba, 0x89, 0x71, 0x59, 0xf0, 0x86, 0x4e, 0xef, 0xc8, 0xfa, 0x49, 0xd0, 0x86, - 0xdc, 0x3b, 0x75, 0x19, 0x71, 0x88, 0x91, 0x94, 0xb3, 0x8b, 0xb1, 0xd4, 0x86, 0xd0, 0xc5, 0x16, 0x65, 0x4d, 0xee, - 0xfa, 0xfb, 0x53, 0x74, 0x18, 0x5a, 0x22, 0x8d, 0xf2, 0xbc, 0x03, 0xb6, 0x5e, 0xdd, 0x29, 0xaa, 0xb8, 0x1d, 0xae, - 0x6c, 0x5d, 0x02, 0xbd, 0x4e, 0x0c, 0xbe, 0xd8, 0x51, 0x83, 0x02, 0xde, 0x08, 0xdd, 0x64, 0xd2, 0x35, 0xc4, 0x70, - 0x36, 0xce, 0x3e, 0xa6, 0x1c, 0xf3, 0x73, 0xbf, 0x34, 0x5f, 0x56, 0x52, 0x3b, 0x41, 0x4c, 0x18, 0x90, 0xeb, 0x59, - 0x71, 0xa4, 0xfa, 0xf6, 0xf4, 0xaf, 0x4d, 0xe1, 0xff, 0x8e, 0x0d, 0xdf, 0xea, 0x30, 0x22, 0x19, 0xf5, 0x0a, 0x3b, - 0x04, 0x3a, 0x83, 0xba, 0xa4, 0x30, 0xe9, 0x43, 0x40, 0x9d, 0xb8, 0xc6, 0xf5, 0x54, 0x1e, 0x21, 0xf4, 0x4d, 0x1a, - 0x54, 0xce, 0x6d, 0x3b, 0xd4, 0x5b, 0xdf, 0x13, 0x51, 0x02, 0x84, 0x47, 0xa3, 0x00, 0x5a, 0x64, 0x32, 0xb8, 0x37, - 0x38, 0x80, 0xb0, 0x2e, 0xa5, 0x9c, 0xd1, 0x5a, 0xd2, 0x75, 0x68, 0x3e, 0x6e, 0xb1, 0xbe, 0xd5, 0x09, 0x39, 0x82, - 0x54, 0xea, 0xe9, 0x53, 0x35, 0x5d, 0xa4, 0x97, 0x98, 0x2d, 0x9d, 0xf2, 0x79, 0x80, 0xd8, 0x86, 0x5e, 0x58, 0x74, - 0x9f, 0xcf, 0xe5, 0x21, 0x40, 0xa6, 0xb9, 0x04, 0x24, 0x5c, 0x52, 0x50, 0x3f, 0x02, 0x93, 0x72, 0xf9, 0x1f, 0x15, - 0xd2, 0xeb, 0xdc, 0x1d, 0xbe, 0x7a, 0xbd, 0x58, 0xd5, 0x1a, 0x59, 0xbf, 0xf1, 0x03, 0x5d, 0xe5, 0xf5, 0xaa, 0xd6, - 0x9e, 0x2f, 0xd8, 0x8c, 0x0e, 0xd2, 0x8d, 0xf4, 0x3f, 0xf9, 0x07, 0x63, 0xa9, 0xb3, 0x23, 0xfa, 0x16, 0x57, 0xe2, - 0xba, 0xaf, 0xa7, 0xf7, 0x50, 0x5e, 0x3c, 0x49, 0x93, 0x65, 0xca, 0x6a, 0xd3, 0xfa, 0xb0, 0x53, 0x04, 0x42, 0xd4, - 0xd1, 0xcb, 0xb8, 0xe4, 0xc0, 0x45, 0x59, 0xba, 0x5e, 0x80, 0x7f, 0xf6, 0x0f, 0xa3, 0x13, 0x68, 0xa0, 0xd8, 0xb0, - 0xfb, 0x7e, 0x47, 0x65, 0xe7, 0x42, 0x0e, 0x4d, 0xf4, 0xbe, 0xda, 0x29, 0x93, 0x33, 0x75, 0x67, 0x9f, 0x93, 0xe8, - 0x86, 0x3a, 0x90, 0x57, 0x06, 0x1c, 0xa7, 0x5e, 0xec, 0xf7, 0x60, 0x98, 0x15, 0xbe, 0xec, 0x59, 0xb7, 0xfd, 0x09, - 0x83, 0x29, 0xc8, 0x5a, 0xee, 0x2c, 0x8a, 0xe5, 0x5d, 0xc8, 0xab, 0xa8, 0xb1, 0x5c, 0x4c, 0xac, 0x10, 0xca, 0x02, - 0xb6, 0x9c, 0xdc, 0x8f, 0x42, 0x90, 0x7b, 0x9c, 0xe3, 0xcd, 0xce, 0x39, 0x52, 0xee, 0x12, 0xcc, 0xee, 0xb0, 0xc5, - 0x69, 0x22, 0xf5, 0xba, 0x8d, 0xe0, 0x52, 0x62, 0x4a, 0x54, 0x51, 0xe4, 0xa6, 0x98, 0xa8, 0xe2, 0xa8, 0x6b, 0x7b, - 0xa3, 0x6d, 0x23, 0x65, 0x90, 0xc8, 0x30, 0x23, 0xa4, 0xa7, 0xf9, 0xe1, 0xee, 0xcd, 0x3e, 0x99, 0x32, 0x06, 0x11, - 0xd0, 0xa8, 0x7a, 0x06, 0x10, 0x7a, 0xbe, 0xac, 0x5d, 0xf2, 0x58, 0x56, 0x30, 0x92, 0xbe, 0x02, 0x1a, 0x2e, 0x9a, - 0x74, 0xc3, 0x2f, 0xc1, 0x49, 0xac, 0x78, 0x9a, 0x00, 0x45, 0xa3, 0xad, 0xf2, 0x6c, 0x88, 0xaf, 0x3c, 0x0e, 0x3a, - 0x51, 0x4f, 0x1a, 0x14, 0xc1, 0x60, 0x9a, 0x8d, 0x24, 0xdc, 0x52, 0x93, 0x41, 0xac, 0x0c, 0xc4, 0xd1, 0xbf, 0xb4, - 0x52, 0xa6, 0x54, 0xbb, 0x5a, 0x30, 0x32, 0xa3, 0x07, 0xd3, 0xdf, 0x85, 0xa8, 0x61, 0xd5, 0x08, 0xfd, 0x45, 0xa6, - 0x4e, 0x75, 0xca, 0xc8, 0x4b, 0x8c, 0xd3, 0xc4, 0xc0, 0x18, 0x72, 0xa0, 0x71, 0xc0, 0x76, 0x03, 0x79, 0x5a, 0x73, - 0xb6, 0x8c, 0x9a, 0x49, 0xf7, 0xba, 0x76, 0xf4, 0x69, 0x6e, 0xe9, 0xfa, 0xcf, 0x65, 0xb6, 0x61, 0xc7, 0x9c, 0xbf, - 0xf4, 0xd3, 0x6e, 0xfa, 0x30, 0xc6, 0xbc, 0x19, 0x07, 0xc3, 0x0c, 0xae, 0xbf, 0x48, 0x8b, 0x47, 0x45, 0x83, 0x2c, - 0x5f, 0x6a, 0x8c, 0x23, 0xed, 0xef, 0x07, 0xaa, 0xb7, 0xbb, 0x8d, 0x49, 0xd2, 0x00, 0x28, 0x47, 0x68, 0x44, 0x70, - 0xec, 0x8a, 0xff, 0x38, 0xaa, 0xfc, 0xef, 0xee, 0x7a, 0x8b, 0x1e, 0x84, 0x2f, 0xf6, 0xa6, 0x4f, 0xa3, 0x80, 0x39, - 0x6b, 0xdd, 0xae, 0x3e, 0x8d, 0xa9, 0x21, 0xfd, 0x35, 0x01, 0xe3, 0xc6, 0xb1, 0xfa, 0xc7, 0x34, 0x25, 0xbf, 0xd7, - 0x63, 0x12, 0x5f, 0x2c, 0xfa, 0xca, 0x1a, 0x55, 0xea, 0xd1, 0x65, 0x38, 0x6d, 0xc9, 0x68, 0x4f, 0xca, 0xb7, 0xba, - 0xc3, 0xd3, 0xb6, 0x4b, 0x6a, 0x36, 0xef, 0x89, 0xf9, 0xec, 0xba, 0xda, 0x56, 0xe2, 0x88, 0xf4, 0x20, 0x5f, 0x4f, - 0x19, 0xa5, 0xa3, 0x4f, 0xd1, 0xde, 0xef, 0x8e, 0x03, 0x99, 0xa7, 0xc7, 0xa1, 0x56, 0xd7, 0xae, 0xec, 0xf8, 0x56, - 0x9c, 0x98, 0xd4, 0x58, 0x86, 0xec, 0xd7, 0xb8, 0x11, 0x0d, 0x3a, 0xee, 0x7d, 0xd5, 0x7a, 0xdd, 0xd4, 0x98, 0x0e, - 0x4e, 0x31, 0x04, 0xcd, 0x57, 0x5d, 0x12, 0x55, 0xc4, 0x82, 0x37, 0xc4, 0x07, 0x71, 0x01, 0x80, 0x9c, 0x93, 0x16, - 0xb5, 0xec, 0x18, 0x4b, 0xa2, 0x7c, 0x57, 0x81, 0x5a, 0xf2, 0xec, 0xa2, 0xa2, 0x53, 0x77, 0xa2, 0x57, 0xa7, 0x5e, - 0xa5, 0x39, 0x8d, 0xd0, 0xf5, 0xf0, 0x99, 0xe7, 0xa8, 0x64, 0x59, 0xf7, 0xae, 0x42, 0x5f, 0xb1, 0xd7, 0x5e, 0x49, - 0xc9, 0x3b, 0x52, 0x1a, 0x0a, 0x19, 0xc5, 0x1a, 0x34, 0xb6, 0xce, 0x5d, 0x62, 0x49, 0x27, 0xcb, 0xa3, 0x86, 0xc2, - 0x17, 0x73, 0x1f, 0xb7, 0xc6, 0x51, 0x39, 0xe6, 0x1c, 0xc0, 0x9e, 0x54, 0xe9, 0x64, 0xaa, 0x1c, 0xc0, 0xaf, 0x69, - 0x16, 0x11, 0x83, 0x94, 0xda, 0xe9, 0xb8, 0x8b, 0xb3, 0x64, 0x3b, 0x61, 0xd0, 0xb1, 0xe8, 0x39, 0x7a, 0x20, 0xd2, - 0x79, 0x1c, 0x44, 0xf7, 0x91, 0xc7, 0x0d, 0x32, 0x0c, 0xb6, 0x67, 0x2d, 0x79, 0x94, 0xb9, 0xe2, 0x28, 0xbb, 0x12, - 0x53, 0xcb, 0xb3, 0xa9, 0xdb, 0x33, 0xba, 0x62, 0xad, 0xac, 0xe9, 0xee, 0x88, 0x4c, 0x05, 0xf7, 0x7d, 0x7b, 0x86, - 0x4f, 0x47, 0x46, 0x8e, 0x33, 0x89, 0xa3, 0x3a, 0x84, 0xb9, 0x71, 0x22, 0x78, 0x82, 0xd1, 0xb2, 0x25, 0xf3, 0x94, - 0x53, 0x0a, 0xb5, 0xf7, 0xbf, 0x34, 0x1e, 0xa1, 0x6a, 0xae, 0x61, 0x7a, 0xcb, 0xd0, 0x1d, 0xc2, 0x76, 0xfd, 0x43, - 0x74, 0x32, 0xa2, 0x05, 0xef, 0x2f, 0x92, 0x0a, 0xc6, 0x5a, 0x5a, 0x95, 0xb6, 0xbe, 0xdd, 0x43, 0x02, 0x96, 0xa7, - 0x56, 0x9d, 0xa1, 0x80, 0x15, 0xa6, 0xcf, 0xf9, 0x9b, 0xb9, 0xc6, 0x21, 0x77, 0x2d, 0x11, 0x10, 0x1b, 0x81, 0xdd, - 0xd0, 0x09, 0x12, 0x18, 0xaa, 0x10, 0xfb, 0xac, 0x55, 0xf1, 0x9c, 0x37, 0x85, 0x1e, 0xf0, 0x23, 0x9f, 0xc4, 0x92, - 0xfa, 0x09, 0x92, 0xfc, 0x09, 0x97, 0x84, 0xd0, 0xa7, 0xfc, 0x22, 0xf6, 0xaa, 0xc9, 0x4d, 0xad, 0x34, 0xdb, 0x0e, - 0xc5, 0xcf, 0xfc, 0x62, 0xdc, 0xdd, 0x68, 0x88, 0x21, 0x62, 0x85, 0x11, 0x0a, 0xc6, 0x9c, 0xa0, 0x6e, 0xf2, 0x57, - 0xa4, 0xf8, 0x74, 0xce, 0xe6, 0x5b, 0xf8, 0x4e, 0xdb, 0xe9, 0x1d, 0x14, 0x0a, 0x31, 0xea, 0x0c, 0x2d, 0x61, 0xd8, - 0xc3, 0x93, 0xf9, 0xec, 0xc2, 0x9c, 0x84, 0x24, 0x15, 0x2d, 0x4a, 0x38, 0x43, 0xfc, 0x06, 0xc0, 0x04, 0x9a, 0xac, - 0x44, 0xa9, 0xa8, 0x81, 0x3d, 0x82, 0x5f, 0xb8, 0xd9, 0xe6, 0xf3, 0x56, 0xe4, 0xe1, 0x40, 0x1a, 0xe5, 0x0a, 0x6d, - 0x20, 0xa6, 0x7a, 0x6e, 0x23, 0xb1, 0x18, 0x19, 0x45, 0x6b, 0xc9, 0x97, 0x5a, 0x42, 0x5d, 0xec, 0x3c, 0x08, 0xd6, - 0x55, 0x77, 0x95, 0x9d, 0xa1, 0x59, 0x31, 0x83, 0x03, 0x39, 0x2e, 0xd0, 0x30, 0x44, 0xba, 0x31, 0xd9, 0xa6, 0x98, - 0x65, 0x23, 0x7c, 0x5f, 0xc5, 0xbc, 0xc9, 0x6b, 0x21, 0xf2, 0x5a, 0x9d, 0x49, 0xb0, 0x86, 0x09, 0x79, 0x6a, 0x60, - 0x96, 0x24, 0xa4, 0x61, 0x09, 0xcb, 0x13, 0x3e, 0x43, 0xbd, 0x64, 0x98, 0x66, 0x64, 0xfa, 0xe0, 0x49, 0xbf, 0x65, - 0xfd, 0x89, 0x37, 0xf2, 0xf3, 0x46, 0x13, 0x78, 0x51, 0x09, 0x55, 0x2e, 0xb6, 0x19, 0x22, 0xba, 0xd5, 0x52, 0xc3, - 0x73, 0xea, 0x96, 0x27, 0x40, 0xe2, 0x49, 0x9f, 0x19, 0x7e, 0xb4, 0xcd, 0x08, 0x81, 0x54, 0xe9, 0xad, 0x8b, 0x90, - 0xd9, 0x27, 0x65, 0xe5, 0xe1, 0xf0, 0xe4, 0xd2, 0x69, 0x09, 0x95, 0xc0, 0xf5, 0x9b, 0xd7, 0x05, 0x54, 0x81, 0x99, - 0xa1, 0x58, 0x63, 0x53, 0x3d, 0x1b, 0x6f, 0x90, 0x66, 0x30, 0x2e, 0x22, 0xa1, 0x42, 0xe6, 0xce, 0x25, 0x9a, 0xba, - 0x5e, 0xcc, 0x19, 0xcb, 0xcb, 0x3e, 0xec, 0xf9, 0xd2, 0x53, 0xcc, 0x2e, 0xbc, 0xd6, 0x2f, 0x99, 0xe3, 0xf6, 0x59, - 0x48, 0xb3, 0xdc, 0x9d, 0x22, 0x35, 0x7b, 0xac, 0x92, 0x9a, 0x07, 0xb0, 0xae, 0xb3, 0x2b, 0x3b, 0xd3, 0xa5, 0x1c, - 0x61, 0x7f, 0x82, 0x3b, 0x80, 0x63, 0x04, 0x43, 0x12, 0x70, 0x1b, 0xf9, 0x8d, 0x5b, 0x30, 0xf2, 0xcd, 0xc7, 0x41, - 0x1b, 0x82, 0xc8, 0x04, 0x89, 0x10, 0x31, 0x91, 0xc7, 0xf0, 0xf3, 0x01, 0xce, 0xbe, 0xba, 0x4c, 0x34, 0x51, 0xbc, - 0x11, 0x8a, 0x69, 0x78, 0x0d, 0x77, 0xeb, 0xc0, 0x8c, 0xce, 0x7b, 0x3a, 0x45, 0x57, 0xd0, 0x24, 0xa6, 0x56, 0x4f, - 0x9b, 0xf7, 0xdc, 0x23, 0xc2, 0x2f, 0x74, 0x51, 0xdc, 0xdd, 0xc1, 0x7a, 0xbd, 0x80, 0x25, 0x13, 0xf9, 0x96, 0x33, - 0xf3, 0x66, 0xca, 0x1e, 0x92, 0x63, 0x9f, 0x3e, 0x3c, 0x6e, 0x17, 0xfb, 0xe4, 0x39, 0x2e, 0xb2, 0x5e, 0x52, 0x85, - 0x3d, 0x29, 0xff, 0x9b, 0x32, 0xe6, 0x44, 0x04, 0x35, 0x95, 0xe9, 0xda, 0xa2, 0xe3, 0xcf, 0x2a, 0x9a, 0x2c, 0x8d, - 0x60, 0x6b, 0x54, 0x91, 0x7e, 0x69, 0x94, 0x52, 0x1d, 0x51, 0x0f, 0x43, 0x9b, 0x48, 0xb1, 0xd0, 0x28, 0x70, 0x74, - 0xa9, 0x4d, 0xf0, 0x6c, 0x15, 0xf4, 0x48, 0x7c, 0xa4, 0x9d, 0xd8, 0xe6, 0xfc, 0x7c, 0x4f, 0xf1, 0x4d, 0xf2, 0x5b, - 0xfa, 0x5b, 0x70, 0x93, 0x42, 0x93, 0xc5, 0xb5, 0xbc, 0xb5, 0x72, 0x8b, 0xdf, 0xe5, 0x63, 0x5f, 0xa3, 0x8b, 0x83, - 0x51, 0x3a, 0x99, 0xf3, 0x5e, 0x78, 0xc8, 0xb5, 0x93, 0x57, 0x62, 0xaf, 0x66, 0x2b, 0xc5, 0x95, 0x60, 0xe1, 0xc1, - 0xa9, 0x2b, 0x99, 0x8a, 0x56, 0x10, 0xc8, 0xbc, 0x71, 0xdb, 0xaf, 0x7f, 0x20, 0xa3, 0x6d, 0x08, 0x19, 0xcc, 0xda, - 0xea, 0x25, 0xa6, 0xf3, 0xbe, 0x45, 0xbe, 0x64, 0x6f, 0x6c, 0x59, 0xf7, 0x10, 0x88, 0xfe, 0xe4, 0x78, 0x37, 0x64, - 0x05, 0x16, 0x0a, 0xfb, 0x12, 0xd0, 0x93, 0xa8, 0xaa, 0xd4, 0x5e, 0xea, 0x50, 0xae, 0xab, 0x19, 0x2a, 0x54, 0xcb, - 0xeb, 0x1f, 0x40, 0x22, 0x8e, 0x52, 0x06, 0xed, 0xe9, 0xa2, 0x2a, 0x23, 0x82, 0xc0, 0xb8, 0x08, 0x0d, 0x2b, 0xc4, - 0x14, 0x76, 0x59, 0xc5, 0x38, 0x4e, 0x57, 0xf7, 0xf5, 0x8b, 0x53, 0x88, 0xbd, 0xee, 0x86, 0xac, 0x12, 0x74, 0xee, - 0xba, 0xec, 0xd3, 0x1c, 0xfa, 0x99, 0xae, 0x7f, 0x04, 0x37, 0x39, 0x87, 0x35, 0x29, 0x38, 0x35, 0xf5, 0x39, 0x8b, - 0x25, 0xdf, 0x08, 0x15, 0x4e, 0x5b, 0x32, 0xda, 0xb1, 0x63, 0x56, 0xe5, 0xc7, 0x2e, 0x4b, 0x69, 0x60, 0x48, 0xa2, - 0xba, 0x36, 0xe8, 0x18, 0xb4, 0x24, 0x72, 0xf3, 0xea, 0x70, 0x49, 0x7b, 0x43, 0xc8, 0x0f, 0x37, 0xa7, 0xfb, 0x94, - 0xd0, 0xc6, 0x6a, 0xf1, 0xca, 0xc5, 0x97, 0x44, 0xa4, 0xbc, 0xe0, 0x1e, 0x01, 0xeb, 0x77, 0x22, 0xfc, 0xbb, 0xe8, - 0xc1, 0x81, 0x47, 0x00, 0x8b, 0xf0, 0x56, 0xdc, 0x57, 0xde, 0x26, 0x94, 0x56, 0xa0, 0x2e, 0xd7, 0xa6, 0x51, 0x82, - 0x37, 0xa4, 0xff, 0xf0, 0xc8, 0xbe, 0xcc, 0x13, 0xb6, 0x51, 0x21, 0xf1, 0x0e, 0xbf, 0xf3, 0x77, 0x4f, 0xc7, 0x9c, - 0x00, 0xbb, 0xa5, 0xd3, 0xbc, 0x6a, 0x0b, 0x90, 0x16, 0x5d, 0x0c, 0x62, 0x9c, 0x82, 0xe5, 0x95, 0x00, 0xe9, 0x87, - 0x57, 0x61, 0xa1, 0xeb, 0xf9, 0x7b, 0x4d, 0xf7, 0xca, 0x5e, 0x87, 0x69, 0xf2, 0x65, 0xef, 0x88, 0x46, 0xd0, 0xcb, - 0xd5, 0xc9, 0xe5, 0xfb, 0x94, 0x72, 0xe1, 0x5f, 0xd2, 0xd5, 0xcf, 0x54, 0x89, 0xe6, 0xaa, 0x6f, 0xaa, 0xf8, 0x94, - 0xab, 0xf1, 0x09, 0xa4, 0xda, 0x9c, 0x57, 0x13, 0xe6, 0xca, 0x55, 0x9f, 0xdc, 0x77, 0x17, 0x98, 0x56, 0x6f, 0xfd, - 0xdb, 0xfd, 0x30, 0xd0, 0x9f, 0xdd, 0xdf, 0x1c, 0x7c, 0x9d, 0x5d, 0x74, 0x76, 0x3a, 0xf6, 0x2f, 0xe4, 0xc7, 0x11, - 0xba, 0xac, 0x87, 0xa2, 0x26, 0x72, 0xc2, 0x7b, 0xea, 0xa8, 0x61, 0x2f, 0xb7, 0x94, 0x79, 0x31, 0x7d, 0x2f, 0x59, - 0x05, 0x94, 0xdf, 0xb7, 0xd9, 0xa5, 0xd5, 0x84, 0xe2, 0x02, 0x92, 0x2e, 0x73, 0x9a, 0x95, 0x6e, 0xa4, 0x50, 0xb3, - 0xc9, 0x5e, 0x46, 0x56, 0xe9, 0xb5, 0x12, 0xec, 0x57, 0x8b, 0x60, 0x58, 0x56, 0xe9, 0x2a, 0x8f, 0x3a, 0x6c, 0xd6, - 0xae, 0xad, 0xd3, 0x7f, 0xb9, 0xb9, 0x9c, 0x09, 0xa2, 0xec, 0xa0, 0x56, 0xf2, 0x8c, 0x2b, 0x7d, 0xce, 0xb5, 0x52, - 0x77, 0x3a, 0xde, 0xab, 0x3f, 0x57, 0xcd, 0x27, 0x4b, 0x4b, 0xf7, 0xbd, 0x0e, 0xff, 0xd9, 0x95, 0xb5, 0x14, 0x41, - 0x16, 0x43, 0xea, 0x3d, 0x63, 0x67, 0x25, 0x53, 0x42, 0x01, 0xc4, 0x2f, 0x3c, 0xae, 0x5d, 0x07, 0xcd, 0xbb, 0xd2, - 0xed, 0xa7, 0xab, 0xd6, 0xaa, 0x90, 0xf2, 0x78, 0x63, 0x19, 0x51, 0x98, 0xb8, 0xaa, 0x95, 0x61, 0x9a, 0x37, 0x7f, - 0xef, 0x9e, 0xf4, 0x57, 0xc5, 0xcb, 0x6a, 0x22, 0x8a, 0x98, 0xae, 0x79, 0xbc, 0xb1, 0x7a, 0x37, 0x87, 0xb5, 0x79, - 0xf1, 0x5c, 0x8d, 0x2f, 0x5a, 0xff, 0x5c, 0x75, 0x6c, 0x0d, 0x63, 0x52, 0x39, 0xcf, 0x3b, 0xbf, 0x29, 0x29, 0x8d, - 0xb4, 0x8c, 0x36, 0x4e, 0x8a, 0x99, 0x0a, 0x2f, 0x57, 0xef, 0x54, 0x27, 0xaa, 0x10, 0x19, 0x1c, 0x3c, 0x23, 0xb8, - 0xbf, 0xfd, 0xf3, 0x51, 0x59, 0xb7, 0xb6, 0x8d, 0xe5, 0x8d, 0xbc, 0x92, 0x68, 0xfc, 0x2e, 0x96, 0xcb, 0x16, 0xe6, - 0x5b, 0xfb, 0xa6, 0x29, 0x97, 0xb5, 0x89, 0xa4, 0x8e, 0xd2, 0x27, 0xc5, 0x65, 0xa4, 0x2a, 0xbd, 0x4f, 0x40, 0xa2, - 0x97, 0x46, 0xfa, 0x0c, 0x23, 0xa5, 0x1e, 0xc9, 0x8e, 0x10, 0x21, 0x40, 0x80, 0x66, 0xe7, 0xaa, 0xbd, 0x4c, 0x97, - 0x0c, 0xce, 0xc8, 0xa4, 0x40, 0x9f, 0x61, 0x76, 0x35, 0x17, 0x09, 0xc1, 0x19, 0xa1, 0x03, 0xe9, 0x26, 0x63, 0x25, - 0xf8, 0x67, 0xa4, 0x1a, 0x35, 0x6d, 0xa6, 0xae, 0xb1, 0xf3, 0xb5, 0xb0, 0xe6, 0x87, 0x0e, 0xd9, 0xc5, 0x89, 0x45, - 0x89, 0xbe, 0x70, 0x24, 0x66, 0xe9, 0x49, 0x5d, 0x69, 0x0d, 0xdd, 0x85, 0x5b, 0x5c, 0xef, 0x5c, 0x76, 0xc9, 0x2f, - 0xe3, 0x4d, 0x2b, 0xd2, 0x1c, 0x53, 0x74, 0xf9, 0x26, 0x58, 0x0b, 0x70, 0xa0, 0xcc, 0xcb, 0x57, 0x3d, 0x02, 0x57, - 0x7e, 0x80, 0x8b, 0xe8, 0x65, 0x3e, 0x82, 0x08, 0xce, 0x4d, 0x95, 0x16, 0x5a, 0x98, 0x3d, 0x02, 0x3c, 0xd6, 0x6b, - 0xfe, 0x14, 0xfa, 0x99, 0x29, 0x5e, 0x0a, 0x27, 0xcf, 0x5a, 0xa3, 0x76, 0x0f, 0x31, 0xf8, 0x94, 0xac, 0xd6, 0xc4, - 0x22, 0xa7, 0x71, 0x9d, 0x53, 0x8f, 0x8f, 0x66, 0xcb, 0x7c, 0x90, 0x98, 0x15, 0xc0, 0xe4, 0x34, 0xae, 0x51, 0xe2, - 0x6d, 0xa6, 0xaa, 0x76, 0x46, 0x39, 0x8d, 0x2f, 0xc4, 0x90, 0x4c, 0x52, 0x31, 0xdf, 0x3e, 0x90, 0x51, 0x86, 0xc4, - 0x45, 0xc9, 0xad, 0xd5, 0x14, 0xa7, 0xad, 0x79, 0x43, 0x52, 0x7e, 0xc1, 0x28, 0xeb, 0xe6, 0xef, 0x52, 0x5f, 0xef, - 0xfe, 0x28, 0xa6, 0x4b, 0x8f, 0xab, 0xc3, 0x9b, 0x79, 0x75, 0x34, 0x91, 0x9e, 0xe6, 0xd4, 0x20, 0xf1, 0x5b, 0x0b, - 0xfe, 0x98, 0x1f, 0x2f, 0x35, 0xa6, 0x1a, 0x9a, 0xf8, 0xc8, 0x66, 0x8b, 0x2e, 0x2b, 0xbc, 0x71, 0x6e, 0x85, 0x2f, - 0xb5, 0x29, 0x16, 0xe3, 0xb3, 0xcf, 0x3b, 0x0d, 0xae, 0xa3, 0x78, 0x0f, 0x87, 0xd4, 0xd5, 0x8b, 0xa2, 0xa5, 0x3f, - 0x36, 0xfb, 0x3c, 0x8e, 0xf8, 0xc3, 0x9b, 0xfd, 0xb0, 0x04, 0xe6, 0xee, 0xd0, 0x4a, 0x8b, 0x03, 0x69, 0x2b, 0x39, - 0x5a, 0xef, 0xda, 0x7e, 0x8a, 0xd6, 0x44, 0x56, 0x63, 0x53, 0x41, 0xa9, 0x5e, 0x90, 0xff, 0xef, 0x6d, 0x6c, 0x55, - 0x32, 0x55, 0x3a, 0xe8, 0x3d, 0x24, 0xbd, 0x34, 0xf4, 0x15, 0x7d, 0xee, 0xe9, 0xb1, 0xde, 0xa9, 0x44, 0xbc, 0x8b, - 0xcb, 0x9c, 0x61, 0x36, 0x1b, 0xe6, 0xe6, 0x11, 0xbd, 0x95, 0x5e, 0xb1, 0xdb, 0x98, 0xf4, 0x34, 0x88, 0x65, 0x79, - 0x99, 0x53, 0xf7, 0x39, 0x09, 0x24, 0xfe, 0x39, 0x3c, 0x00, 0xff, 0xa4, 0x6b, 0xd0, 0x1c, 0x49, 0xe5, 0x72, 0x53, - 0xaf, 0x43, 0xbc, 0x6b, 0x77, 0x3c, 0x16, 0xe9, 0xeb, 0x26, 0x1a, 0xdf, 0xd0, 0x0d, 0xa5, 0xa8, 0xa9, 0x8c, 0x3a, - 0x8e, 0x0c, 0x97, 0x8c, 0xbc, 0x59, 0x91, 0x6b, 0xbf, 0x02, 0x79, 0x55, 0x00, 0x21, 0x48, 0x6b, 0x11, 0x4d, 0x4c, - 0xf6, 0x57, 0x43, 0xcd, 0x51, 0x9a, 0xd9, 0x26, 0x7f, 0xda, 0xc4, 0xee, 0xba, 0x05, 0xdc, 0xad, 0x1c, 0xa2, 0x8b, - 0xed, 0x31, 0x0f, 0x79, 0x04, 0xa3, 0x2d, 0x24, 0x0a, 0x59, 0x15, 0xa2, 0x85, 0xd3, 0xfc, 0x49, 0x3e, 0x55, 0x9e, - 0x02, 0x3c, 0x44, 0x41, 0x13, 0x96, 0xb2, 0x9b, 0xee, 0x4b, 0xb2, 0x74, 0xf4, 0x3c, 0x82, 0x0f, 0x50, 0x09, 0x0e, - 0xd0, 0x45, 0xce, 0xeb, 0xee, 0xc5, 0xb6, 0x11, 0xd9, 0xc8, 0xd6, 0x75, 0x4f, 0x07, 0x59, 0x6e, 0x2d, 0x2d, 0xfc, - 0xef, 0x8f, 0xbd, 0xaf, 0xee, 0x82, 0x1d, 0x60, 0x28, 0xef, 0x3e, 0x84, 0x16, 0xee, 0x38, 0xd4, 0xea, 0xc5, 0x8a, - 0x12, 0x05, 0x4f, 0x22, 0xf3, 0xc7, 0x4a, 0x76, 0xba, 0xc7, 0x56, 0x24, 0xde, 0x53, 0x37, 0xa8, 0xdb, 0xe5, 0x56, - 0x5d, 0x35, 0x7b, 0xb9, 0x2a, 0xec, 0x3f, 0x1b, 0xfa, 0xd1, 0x54, 0xc1, 0x07, 0x4c, 0x2f, 0x6e, 0x23, 0x2e, 0x0a, - 0x85, 0x35, 0x72, 0xfe, 0x01, 0x8c, 0xca, 0x9a, 0x17, 0x6e, 0x52, 0x2c, 0x83, 0xcb, 0xd0, 0x28, 0xee, 0xc4, 0x2d, - 0x86, 0x1a, 0x0f, 0x06, 0x3d, 0x0b, 0x4b, 0x90, 0x46, 0xf7, 0xe9, 0x3d, 0xce, 0x70, 0x12, 0xa4, 0xd5, 0xe7, 0xcd, - 0x09, 0x72, 0x8d, 0x77, 0x52, 0x6b, 0x44, 0x22, 0xcd, 0x1e, 0x47, 0x65, 0x6d, 0xf8, 0x18, 0xa6, 0xd1, 0x39, 0xa0, - 0xa8, 0x4d, 0x85, 0xad, 0x76, 0x8a, 0x50, 0xaa, 0xe3, 0x20, 0xb0, 0x69, 0xe9, 0xe3, 0x24, 0x2d, 0xe2, 0x40, 0x4f, - 0x25, 0x78, 0x5e, 0xd2, 0xfc, 0x96, 0x8a, 0xbc, 0x9f, 0x77, 0x82, 0x66, 0xfa, 0xbd, 0x82, 0x48, 0x79, 0xac, 0x44, - 0x1a, 0x46, 0x1d, 0x0c, 0x76, 0x6c, 0xc3, 0xab, 0x03, 0x18, 0xcf, 0x91, 0x4a, 0x46, 0x0d, 0x5c, 0xb9, 0xe2, 0xee, - 0x4b, 0x9b, 0x32, 0xe5, 0xda, 0x2a, 0xfc, 0xc8, 0x7c, 0xc9, 0x10, 0x2b, 0x5f, 0x35, 0x43, 0x89, 0xab, 0xd4, 0xb0, - 0xf6, 0x8b, 0xa9, 0x9b, 0x58, 0x5b, 0xc8, 0xe7, 0x8b, 0xbf, 0x46, 0x87, 0xb0, 0x0f, 0x20, 0xab, 0x9f, 0x2e, 0xc4, - 0x94, 0x5c, 0xc2, 0x04, 0x39, 0x57, 0x8c, 0x89, 0x77, 0x93, 0xc9, 0xa5, 0x3f, 0xcd, 0x16, 0xd8, 0x67, 0xd3, 0x4a, - 0xba, 0x5f, 0x92, 0x42, 0xfc, 0x1e, 0x0f, 0x1a, 0xd2, 0x13, 0x84, 0x98, 0x3d, 0x05, 0x8f, 0x6e, 0x56, 0x6e, 0xd4, - 0x1b, 0x49, 0xd0, 0x8e, 0xad, 0xd8, 0x02, 0x24, 0x38, 0xa0, 0x9e, 0xa8, 0xf1, 0x7d, 0xf0, 0x52, 0xe5, 0x97, 0x2f, - 0x0f, 0x11, 0x6a, 0x06, 0xe3, 0x89, 0xa4, 0x19, 0x3b, 0x54, 0x24, 0xf3, 0x15, 0x34, 0xf3, 0xe1, 0xae, 0xa7, 0x23, - 0xde, 0xec, 0xd0, 0x2b, 0x6d, 0xdc, 0xba, 0x27, 0xba, 0xb8, 0x22, 0x61, 0x68, 0xf5, 0xf1, 0xa0, 0xf2, 0xfe, 0x7c, - 0x39, 0x94, 0x57, 0xb6, 0xf2, 0x83, 0x70, 0x98, 0xb5, 0x3b, 0x78, 0xbe, 0x8e, 0x8c, 0x0f, 0x33, 0x92, 0xb3, 0x0c, - 0x16, 0x81, 0x07, 0x73, 0x96, 0xa2, 0x85, 0x6f, 0xca, 0x32, 0x1b, 0x64, 0x6a, 0xb4, 0x80, 0xc5, 0x8b, 0xfc, 0x1b, - 0x1b, 0x5f, 0x96, 0xd9, 0x58, 0xc1, 0xec, 0x75, 0x20, 0x3b, 0x25, 0x90, 0x98, 0xa3, 0xda, 0x9d, 0x0d, 0xa8, 0xa2, - 0x87, 0x27, 0x00, 0x57, 0xf0, 0x87, 0xc7, 0x2c, 0xd0, 0x39, 0x35, 0xce, 0xd7, 0xb0, 0x56, 0x1e, 0x35, 0x36, 0x59, - 0xd7, 0x44, 0x50, 0xa4, 0x16, 0xab, 0xd0, 0x4b, 0x92, 0x48, 0x1d, 0xaa, 0xfc, 0x8f, 0x2f, 0x9c, 0x53, 0x73, 0xef, - 0x68, 0xeb, 0x31, 0xd7, 0x13, 0xd2, 0x56, 0x51, 0x93, 0x33, 0x3d, 0x2e, 0xa1, 0xa0, 0xfc, 0x9c, 0x0a, 0x95, 0xe2, - 0xcb, 0x74, 0xe7, 0x66, 0x55, 0xc1, 0x00, 0x6a, 0x06, 0x30, 0xfa, 0x51, 0x40, 0x46, 0x6a, 0xfc, 0x78, 0xa2, 0x5e, - 0xf7, 0x31, 0x37, 0x74, 0xd0, 0xe2, 0x4c, 0x37, 0xb0, 0x47, 0xb2, 0x1d, 0x8e, 0x6a, 0x80, 0xf2, 0x21, 0x9e, 0x04, - 0x9e, 0x22, 0x9a, 0xa4, 0x59, 0x5f, 0xf1, 0xb7, 0xe9, 0xdc, 0xf6, 0x64, 0x1d, 0x00, 0x2d, 0x2c, 0x98, 0x41, 0xb3, - 0x49, 0xdf, 0x4b, 0xd0, 0x80, 0x1f, 0xc6, 0xce, 0x30, 0xdf, 0x3b, 0xa1, 0xf6, 0xce, 0x0e, 0xbd, 0x9e, 0x7d, 0xe5, - 0x9c, 0x70, 0x3e, 0x53, 0x2f, 0xc6, 0x51, 0xd8, 0x45, 0x9d, 0xc5, 0x93, 0x3f, 0x7c, 0xa6, 0xc2, 0x78, 0x4c, 0xc4, - 0x45, 0x2c, 0x35, 0xb8, 0x20, 0x89, 0x2d, 0x9b, 0xcd, 0x32, 0x0e, 0x7e, 0x26, 0xc3, 0x41, 0xc6, 0x04, 0x2f, 0x27, - 0xf4, 0xfe, 0x96, 0x48, 0x08, 0xb2, 0x21, 0x94, 0x4c, 0xd3, 0x90, 0x1a, 0xaf, 0x36, 0x97, 0x71, 0x99, 0xd1, 0x25, - 0xe3, 0xff, 0x66, 0x17, 0x14, 0xea, 0xb5, 0xa2, 0xe0, 0xfb, 0x2d, 0xdc, 0xf6, 0x1a, 0x9d, 0xb1, 0x67, 0xc8, 0xf4, - 0xa1, 0x39, 0x4c, 0x19, 0x29, 0x0c, 0x77, 0xed, 0x29, 0x48, 0x90, 0x99, 0x97, 0xe1, 0xfd, 0x86, 0xfd, 0x36, 0x60, - 0x0a, 0x1e, 0xdf, 0xfb, 0x66, 0x05, 0xd8, 0x1c, 0x69, 0xa8, 0x7b, 0xee, 0x29, 0xa0, 0x1c, 0xe6, 0xc2, 0xc3, 0x1c, - 0xba, 0x42, 0xb5, 0x0f, 0xb9, 0xab, 0xa7, 0x7a, 0x15, 0x0b, 0xcb, 0xc1, 0xa6, 0x6e, 0x54, 0x9b, 0x84, 0xea, 0xb8, - 0x5c, 0x03, 0xd2, 0x9e, 0xd0, 0x0c, 0xb4, 0x1e, 0x46, 0x54, 0xeb, 0x64, 0x97, 0xde, 0x4a, 0x30, 0xba, 0x24, 0x91, - 0x06, 0x26, 0xcb, 0x9c, 0xd4, 0x00, 0xa6, 0x45, 0x98, 0x03, 0xbf, 0x23, 0x39, 0xae, 0x91, 0x80, 0xce, 0x71, 0xd8, - 0x35, 0xac, 0x26, 0xa5, 0xf3, 0x5c, 0xb5, 0x24, 0x15, 0xa4, 0x22, 0x42, 0x25, 0x53, 0x25, 0xa5, 0x63, 0xc2, 0x39, - 0xae, 0x06, 0x24, 0xc3, 0x94, 0x0a, 0x6a, 0x6f, 0xa3, 0x52, 0x1a, 0xcb, 0x59, 0x18, 0x3e, 0x71, 0xf9, 0x33, 0xaa, - 0xf9, 0xb2, 0x65, 0x23, 0x89, 0xec, 0x35, 0xd3, 0xc5, 0x82, 0x3b, 0xf3, 0x27, 0x70, 0x07, 0xbe, 0xfb, 0x8a, 0x9a, - 0xf2, 0xbe, 0x3c, 0x18, 0x25, 0x26, 0x32, 0x7e, 0x4d, 0xf5, 0x15, 0xcc, 0x65, 0x3e, 0x43, 0x28, 0xd3, 0x6f, 0x3d, - 0x56, 0x67, 0x0b, 0x61, 0x53, 0x49, 0xec, 0xfe, 0xfd, 0xe4, 0x87, 0x02, 0x5e, 0xf0, 0x43, 0x8f, 0xcf, 0x56, 0x13, - 0x04, 0x89, 0x45, 0xb3, 0x0a, 0x7b, 0x8b, 0x9c, 0x18, 0x40, 0x54, 0xf6, 0x68, 0x6e, 0x2f, 0xa9, 0xa1, 0x23, 0x52, - 0x8f, 0x3b, 0x27, 0xac, 0xec, 0x6d, 0x4b, 0x9e, 0xbd, 0x5a, 0xd5, 0x53, 0xaa, 0x63, 0xc2, 0x80, 0x9b, 0xbf, 0xf1, - 0x75, 0x6e, 0xeb, 0xbb, 0x1b, 0x30, 0xd8, 0x12, 0xed, 0xc7, 0x91, 0x22, 0x80, 0x9d, 0x60, 0x8a, 0x43, 0xce, 0xf9, - 0xf1, 0xa6, 0x7a, 0xf9, 0xbf, 0x27, 0x47, 0x15, 0xae, 0xcf, 0x11, 0xb8, 0xc4, 0xe8, 0x74, 0x33, 0x76, 0xee, 0xee, - 0xa8, 0xf4, 0x0d, 0x1f, 0x80, 0x5d, 0x67, 0x10, 0xf4, 0x90, 0x7b, 0x12, 0xde, 0x52, 0x2a, 0x9c, 0xf6, 0x4d, 0x67, - 0xa4, 0xc7, 0xa2, 0xe5, 0x43, 0x78, 0x6c, 0x77, 0x10, 0xac, 0x67, 0xcb, 0xb2, 0xa0, 0xa9, 0x04, 0x68, 0xa6, 0x18, - 0xe0, 0xc8, 0x43, 0xec, 0x1c, 0xc9, 0xac, 0x1c, 0xe3, 0x6e, 0x8e, 0xf7, 0x32, 0x88, 0x0e, 0xd1, 0x11, 0x4f, 0xa5, - 0x25, 0xb2, 0x8c, 0x6d, 0xa9, 0xc2, 0xb5, 0x4f, 0x71, 0x5a, 0xd8, 0xa2, 0xab, 0xca, 0x44, 0xbf, 0xfc, 0x08, 0xc4, - 0xd3, 0x37, 0x7a, 0x5e, 0xbb, 0xd9, 0x24, 0xb2, 0x37, 0x74, 0xb5, 0xfc, 0x92, 0x5b, 0x94, 0x56, 0xae, 0xc6, 0x00, - 0x2b, 0xf6, 0x3a, 0xef, 0x09, 0x84, 0x33, 0x25, 0x0e, 0xb7, 0xf9, 0x9d, 0x61, 0xb6, 0xb4, 0xb1, 0xba, 0x19, 0x9d, - 0x62, 0xdc, 0xd6, 0xdb, 0xfd, 0x40, 0x67, 0x37, 0x24, 0x7c, 0x78, 0xe3, 0xfb, 0xd0, 0x03, 0xa9, 0x24, 0xb8, 0xe2, - 0xee, 0xca, 0x7b, 0x0b, 0xc2, 0xec, 0x81, 0x9c, 0x3e, 0x7a, 0x42, 0x82, 0x5e, 0xc0, 0xfe, 0x7c, 0x1e, 0x1e, 0xf3, - 0x92, 0x38, 0x36, 0xca, 0xc7, 0x1f, 0xd6, 0x58, 0xe1, 0x96, 0xe8, 0x70, 0x89, 0x48, 0xdf, 0xc3, 0xe0, 0xc5, 0x13, - 0x86, 0xa4, 0xea, 0x7f, 0xbc, 0x91, 0x50, 0xc5, 0x33, 0x85, 0xce, 0xed, 0xb4, 0x39, 0x27, 0x88, 0xe5, 0xce, 0x55, - 0x66, 0xaf, 0x1d, 0x85, 0xbd, 0xe3, 0xea, 0x96, 0x74, 0x5f, 0xf6, 0x95, 0x9a, 0x5b, 0x8d, 0x48, 0xb0, 0x91, 0xe1, - 0x79, 0x6e, 0xf5, 0x22, 0xb3, 0x43, 0xd6, 0x45, 0x0e, 0xb0, 0xe9, 0x4c, 0x16, 0x47, 0xed, 0xcd, 0xe8, 0x8b, 0xea, - 0x8a, 0xed, 0xaa, 0x6a, 0x95, 0xc6, 0x25, 0x1d, 0xb4, 0xe6, 0x54, 0xc9, 0x0f, 0xc0, 0x36, 0x22, 0x7f, 0xa7, 0x47, - 0x9d, 0xa9, 0x87, 0x4a, 0x39, 0xad, 0x75, 0x20, 0x8c, 0x87, 0x91, 0xde, 0xcf, 0xc0, 0x40, 0x51, 0x09, 0x6c, 0xb7, - 0x43, 0xe7, 0xa7, 0x5b, 0x93, 0x92, 0x91, 0x53, 0x50, 0x52, 0x56, 0x03, 0xd3, 0x44, 0x91, 0x75, 0x9e, 0x63, 0xf6, - 0x77, 0xc7, 0xd3, 0x9f, 0x3b, 0x0e, 0x1a, 0x31, 0xb3, 0x0b, 0x63, 0xff, 0xb8, 0x77, 0x4d, 0x36, 0xa4, 0x70, 0xea, - 0xc0, 0x24, 0xce, 0x92, 0xb4, 0xfe, 0x7d, 0xad, 0x99, 0xfe, 0xba, 0xe9, 0x7a, 0x09, 0x1f, 0xe8, 0xe1, 0xd8, 0x6e, - 0xb5, 0xf9, 0xa1, 0x7c, 0x60, 0x25, 0xbe, 0xf0, 0xdb, 0x35, 0x1d, 0xbe, 0x0c, 0x3d, 0xf7, 0x39, 0xcc, 0x61, 0x6d, - 0xc5, 0xde, 0x48, 0xa6, 0x05, 0x81, 0xde, 0x6e, 0x77, 0x12, 0xc6, 0x80, 0xfb, 0x7a, 0x8e, 0xa8, 0x7c, 0xe6, 0x72, - 0xf4, 0x4c, 0xa2, 0x04, 0xa6, 0xa3, 0xc1, 0xa3, 0x16, 0xa0, 0xe2, 0x13, 0x8b, 0xd3, 0xe1, 0x01, 0x36, 0x38, 0xb8, - 0x3b, 0x8c, 0xd1, 0x8f, 0x75, 0xf7, 0x6d, 0xea, 0xb3, 0x6c, 0xf8, 0x1a, 0x8e, 0x45, 0x5d, 0xfe, 0x70, 0x55, 0x1b, - 0xc7, 0xa2, 0xc7, 0xea, 0x2a, 0x3e, 0x1a, 0x17, 0xf5, 0x06, 0x43, 0xac, 0xce, 0x03, 0x1c, 0x55, 0xa4, 0x6c, 0xce, - 0x6c, 0xa1, 0x24, 0x81, 0xea, 0xad, 0xd5, 0xfc, 0x32, 0xb0, 0x5b, 0x83, 0x0d, 0xd1, 0xfc, 0x6c, 0xbd, 0x87, 0xef, - 0xe2, 0x27, 0x9f, 0x6d, 0xc9, 0x7c, 0x9b, 0x9d, 0x00, 0x77, 0x96, 0x5d, 0x79, 0x92, 0xd5, 0x8a, 0x77, 0x5b, 0x5f, - 0xbc, 0xef, 0x5f, 0x58, 0x2f, 0x84, 0x84, 0xf3, 0x4b, 0x7a, 0xbb, 0x96, 0x43, 0x1a, 0xc4, 0xf6, 0xaf, 0x26, 0x90, - 0x7f, 0x4a, 0x33, 0x77, 0xfe, 0x58, 0x19, 0x82, 0x63, 0x84, 0x1a, 0x6f, 0x09, 0x16, 0x5c, 0x7a, 0x45, 0x4a, 0xb1, - 0xcd, 0x6a, 0xa7, 0x95, 0x8c, 0xb5, 0xe6, 0xbe, 0xd2, 0x96, 0xb4, 0xca, 0x9d, 0x55, 0x40, 0x5c, 0x5d, 0x9a, 0xf8, - 0x50, 0x60, 0x35, 0x7b, 0x52, 0x96, 0xa4, 0x50, 0x1a, 0x2f, 0xfe, 0x91, 0x78, 0x47, 0x40, 0xe5, 0xea, 0x25, 0x42, - 0x30, 0xae, 0xbf, 0xef, 0xec, 0x2c, 0x3b, 0xcd, 0x1e, 0x32, 0xd5, 0x23, 0x2f, 0x2f, 0xc3, 0x39, 0x8a, 0x52, 0xa5, - 0xf1, 0x1d, 0x9c, 0x71, 0x23, 0x46, 0xbd, 0x7b, 0xf6, 0x14, 0x21, 0xef, 0xc8, 0x6f, 0x64, 0x92, 0xc3, 0x30, 0xef, - 0xbe, 0x3a, 0x19, 0x91, 0xe6, 0xf6, 0x0e, 0xe8, 0x62, 0x93, 0x29, 0xeb, 0x2c, 0xd8, 0x92, 0x0a, 0x12, 0x09, 0xd1, - 0xed, 0x90, 0x90, 0xbd, 0xb4, 0x6f, 0x48, 0x51, 0x54, 0xa7, 0x7a, 0xc8, 0x50, 0x4f, 0x3b, 0x7e, 0x5c, 0x47, 0x4c, - 0xc7, 0xda, 0x22, 0x1d, 0x91, 0x0c, 0x20, 0x18, 0x33, 0x5e, 0x42, 0xa6, 0x5a, 0x33, 0xbc, 0x56, 0x13, 0x4f, 0x19, - 0xdd, 0x59, 0x0f, 0x0c, 0x13, 0xa9, 0x20, 0x76, 0xde, 0xd7, 0x24, 0x52, 0x76, 0xeb, 0xc5, 0x67, 0xa5, 0x0c, 0xcb, - 0x7b, 0x78, 0xd6, 0xb5, 0xa7, 0x6c, 0x52, 0x06, 0x24, 0x96, 0xfb, 0x95, 0x8d, 0x5f, 0xeb, 0xe8, 0x4a, 0x9e, 0xd1, - 0xce, 0x03, 0x00, 0xa6, 0x96, 0xf8, 0x7d, 0xea, 0x32, 0x5f, 0xba, 0xd5, 0x8b, 0xed, 0x35, 0xba, 0x05, 0xb8, 0xf6, - 0xa8, 0x66, 0x9e, 0xf6, 0x16, 0xbb, 0xa7, 0x42, 0x07, 0x74, 0xd5, 0x30, 0x5b, 0xfc, 0xe5, 0x8d, 0x0f, 0xb7, 0xc4, - 0xbd, 0x3a, 0x95, 0xe8, 0x63, 0x7e, 0x2d, 0x2e, 0xfc, 0xa7, 0xdc, 0x91, 0x80, 0xd1, 0x31, 0x3e, 0x29, 0xa4, 0x0d, - 0xab, 0x22, 0x64, 0x42, 0x75, 0xbf, 0x38, 0x4d, 0xe0, 0x00, 0x03, 0xd3, 0xb9, 0xc9, 0x62, 0x96, 0xee, 0xae, 0x9c, - 0xea, 0x3e, 0x18, 0xc0, 0xaa, 0x76, 0xda, 0x9c, 0x7a, 0xea, 0x6e, 0x43, 0xeb, 0x18, 0x17, 0xdf, 0x42, 0x4d, 0x86, - 0xb0, 0xb5, 0x5e, 0xa8, 0x48, 0xd3, 0xbc, 0xc5, 0xca, 0x9f, 0x64, 0xdb, 0x1b, 0x60, 0xe8, 0x42, 0x62, 0x6b, 0x3e, - 0x28, 0x41, 0x7c, 0x50, 0x17, 0xc2, 0xbe, 0xa3, 0x81, 0x68, 0x71, 0x86, 0x75, 0x93, 0x2a, 0xd3, 0x7e, 0x46, 0x8e, - 0x26, 0xd4, 0xfa, 0x3e, 0xf6, 0xcf, 0xba, 0x73, 0xfa, 0x57, 0x24, 0xb5, 0x4c, 0xd3, 0x1c, 0xc9, 0xe8, 0x44, 0xd8, - 0xd8, 0x60, 0x20, 0x8d, 0x11, 0x2f, 0x3d, 0xfd, 0x9c, 0xbb, 0x75, 0xcd, 0x28, 0xb0, 0x7e, 0x83, 0xf1, 0x7a, 0xe0, - 0xe4, 0x9a, 0x5c, 0x04, 0x7a, 0x26, 0x46, 0x59, 0x0f, 0xa9, 0x67, 0x5e, 0x2f, 0xd5, 0xfb, 0x9c, 0x8b, 0x09, 0x42, - 0x85, 0xd7, 0x1c, 0x87, 0xf4, 0x13, 0xc0, 0xe3, 0x26, 0x5b, 0x24, 0x3f, 0x6a, 0x70, 0x1e, 0xf6, 0x49, 0xac, 0x2c, - 0x0e, 0x2f, 0x68, 0x7a, 0xf6, 0xbc, 0x0a, 0xf3, 0x03, 0xf9, 0xd3, 0xb9, 0x32, 0xc0, 0x18, 0xc9, 0xdd, 0xc4, 0xae, - 0x08, 0x4d, 0x01, 0x1c, 0x2a, 0xb5, 0x8e, 0x83, 0x68, 0x80, 0x39, 0xec, 0xfb, 0x72, 0x4b, 0x94, 0x91, 0x02, 0x58, - 0x9d, 0xe1, 0x0c, 0x60, 0x07, 0x25, 0xd9, 0x31, 0xd6, 0x62, 0x64, 0x01, 0x8f, 0x86, 0xab, 0x89, 0xd3, 0xa2, 0xda, - 0x8b, 0x8b, 0x31, 0x31, 0xf0, 0x18, 0xd1, 0x32, 0x69, 0xdc, 0x0c, 0xa6, 0xb9, 0x21, 0xe8, 0x66, 0x87, 0xce, 0xdc, - 0xdc, 0xb6, 0xb3, 0x08, 0x4e, 0x6f, 0x7f, 0x06, 0xce, 0x0f, 0xe2, 0xbe, 0x76, 0x45, 0xc4, 0xfd, 0x2b, 0x19, 0x70, - 0x25, 0x85, 0xe7, 0x6c, 0x82, 0xa0, 0x1f, 0xad, 0x7d, 0xa6, 0x41, 0x3c, 0x63, 0xcf, 0xa5, 0x4e, 0x05, 0x0c, 0xfe, - 0xa2, 0x11, 0xaf, 0x53, 0x4f, 0x4c, 0x87, 0x45, 0xf4, 0x3d, 0xd1, 0x6c, 0xa0, 0x31, 0x32, 0xdd, 0x6d, 0xef, 0x9a, - 0x21, 0x44, 0x9f, 0x98, 0x52, 0x96, 0x08, 0x80, 0xf3, 0x2f, 0x2b, 0x84, 0xfb, 0xb7, 0x82, 0x84, 0x05, 0x92, 0xe7, - 0x6a, 0xd7, 0xc4, 0x0d, 0xb0, 0x56, 0xcb, 0x19, 0x77, 0x24, 0x82, 0xd9, 0x98, 0xcb, 0x4c, 0xf4, 0x48, 0x12, 0x67, - 0x90, 0xca, 0x66, 0x5b, 0xc3, 0xdc, 0xdb, 0x06, 0x33, 0x21, 0xca, 0x11, 0x0c, 0xde, 0xbd, 0x85, 0x0d, 0x26, 0xb5, - 0x29, 0x25, 0x4e, 0x43, 0x35, 0x24, 0xf9, 0xb2, 0x17, 0xdb, 0xd5, 0x9d, 0x74, 0x1b, 0x68, 0x32, 0x7f, 0xf7, 0xc5, - 0xc1, 0x7d, 0x64, 0xfb, 0xbc, 0x55, 0xec, 0x85, 0x49, 0xb5, 0x7c, 0xda, 0xba, 0x74, 0xae, 0xbd, 0xb8, 0x46, 0x2f, - 0x4d, 0x5f, 0xb5, 0xdf, 0x58, 0x9f, 0xe7, 0x20, 0x47, 0x45, 0x9f, 0xf7, 0x97, 0x0b, 0x08, 0x9a, 0xba, 0x8c, 0x3b, - 0x01, 0x2e, 0x18, 0x51, 0x7a, 0xae, 0x33, 0x02, 0x5b, 0xc2, 0x3c, 0x2d, 0x9b, 0x2b, 0xbc, 0x3c, 0x3f, 0x38, 0x4d, - 0xa8, 0x54, 0xe8, 0x35, 0xbf, 0xaf, 0xde, 0xab, 0xb5, 0xc7, 0xe5, 0x61, 0xff, 0xbd, 0x48, 0xce, 0x40, 0x91, 0x76, - 0x46, 0x7e, 0xb4, 0xac, 0x83, 0x78, 0xdb, 0x9a, 0xbe, 0xbd, 0x96, 0x3f, 0x4c, 0x48, 0xa6, 0xca, 0x6d, 0x08, 0x16, - 0x93, 0xbe, 0xdf, 0x65, 0xf0, 0x93, 0x6c, 0x45, 0x4a, 0x0c, 0x34, 0x8a, 0x5d, 0xc6, 0x3c, 0xd9, 0xa4, 0x5e, 0x37, - 0x15, 0xdd, 0xf8, 0x50, 0xcf, 0x76, 0x18, 0x6f, 0xe0, 0xb1, 0x9e, 0x7c, 0x34, 0x77, 0xaa, 0xee, 0x5a, 0xf8, 0xba, - 0xba, 0x13, 0xda, 0xed, 0xed, 0xeb, 0x45, 0x69, 0x5e, 0x77, 0x27, 0xda, 0x3a, 0x45, 0xcf, 0xeb, 0xff, 0xeb, 0x39, - 0xe3, 0xe0, 0x6d, 0x0a, 0xef, 0x05, 0xf8, 0x76, 0x7c, 0xf6, 0x3c, 0x03, 0x8a, 0x96, 0x59, 0xb4, 0x32, 0xb9, 0xc6, - 0x39, 0x0e, 0x18, 0x55, 0xa8, 0xf3, 0x9a, 0xa9, 0x36, 0x4e, 0x6c, 0x58, 0xef, 0x78, 0x79, 0x55, 0x00, 0x71, 0x87, - 0x6b, 0x59, 0x6e, 0xe2, 0xc2, 0xfc, 0xe6, 0x99, 0x12, 0x92, 0xcd, 0x63, 0x6d, 0xd5, 0xe9, 0x77, 0x49, 0x49, 0x0e, - 0x03, 0x6e, 0x73, 0xe9, 0xc3, 0x4d, 0xe5, 0xa1, 0x0b, 0xdd, 0x2e, 0xca, 0x09, 0x22, 0x95, 0xba, 0x13, 0xa8, 0x70, - 0x6c, 0x8b, 0x15, 0x75, 0xa9, 0xed, 0x1b, 0xdf, 0x17, 0xfc, 0xb2, 0x10, 0x7c, 0x63, 0x27, 0x36, 0x31, 0x5b, 0xa9, - 0x66, 0x24, 0xe1, 0x67, 0x10, 0xcc, 0x71, 0xe5, 0x99, 0xda, 0xed, 0xf0, 0x7f, 0x14, 0x4d, 0x45, 0x0a, 0xe8, 0x12, - 0x87, 0x08, 0x99, 0x99, 0x63, 0x8a, 0x1e, 0xac, 0x10, 0x3a, 0x8b, 0x94, 0x0f, 0x76, 0x73, 0xf0, 0x7d, 0xeb, 0xe7, - 0xb6, 0xae, 0xda, 0xe5, 0x5e, 0xd1, 0xd3, 0x34, 0x25, 0x5a, 0x52, 0xa8, 0xa4, 0x91, 0xb5, 0x43, 0x7d, 0xad, 0xaf, - 0xdd, 0x48, 0x41, 0x2d, 0xb2, 0x20, 0x7a, 0x9d, 0xaf, 0x0d, 0x20, 0x4d, 0x2a, 0xfe, 0xc2, 0xbf, 0x7f, 0x16, 0x89, - 0x37, 0xb5, 0x88, 0x86, 0xfa, 0x3a, 0x6d, 0x5d, 0x7d, 0x15, 0x8f, 0x0d, 0xd7, 0x56, 0xfd, 0x18, 0xe5, 0xe6, 0x46, - 0xca, 0xfb, 0x89, 0xf9, 0xf3, 0xaf, 0x36, 0x0d, 0x8d, 0xc0, 0x49, 0xf3, 0xe6, 0x76, 0xee, 0x30, 0xe7, 0x9e, 0x23, - 0x35, 0x1c, 0xb2, 0x6f, 0x40, 0x6e, 0x91, 0x2f, 0xb5, 0x6b, 0x22, 0x71, 0x81, 0xb0, 0x89, 0x60, 0x43, 0xdc, 0x47, - 0xc6, 0x8c, 0x6e, 0x5d, 0xe3, 0xe0, 0xdd, 0xa5, 0x4c, 0x9d, 0x96, 0x6a, 0x2e, 0xa7, 0x42, 0x99, 0x49, 0x2a, 0xfa, - 0xd5, 0x46, 0x7f, 0x76, 0xe5, 0x94, 0xb8, 0x0e, 0x2a, 0xbf, 0x8d, 0x38, 0x75, 0x1b, 0xcd, 0xb4, 0xbf, 0x95, 0xaf, - 0x7a, 0x5c, 0xd4, 0x5f, 0xd2, 0xe3, 0xbd, 0xb5, 0x47, 0x6e, 0x4d, 0x2d, 0x3d, 0xe2, 0xfe, 0x6a, 0xbb, 0xaf, 0xf2, - 0x39, 0x0e, 0x22, 0x54, 0x3b, 0x21, 0xc6, 0xa5, 0x88, 0x02, 0x0e, 0xe0, 0x15, 0xf1, 0x5f, 0x90, 0xeb, 0xf1, 0xac, - 0x4e, 0xd1, 0x8f, 0x3d, 0xd0, 0xde, 0x6d, 0x9e, 0x03, 0x4e, 0xa9, 0x72, 0xca, 0xbe, 0x23, 0x6b, 0xb3, 0x2c, 0xd2, - 0xae, 0x77, 0x66, 0xb3, 0xa8, 0x58, 0x11, 0x00, 0xc8, 0xde, 0xe9, 0x53, 0x97, 0x75, 0x28, 0xb7, 0x1b, 0x08, 0xb7, - 0x4a, 0x66, 0xc2, 0x4c, 0x14, 0xfe, 0xba, 0x63, 0xc0, 0x0b, 0x21, 0xce, 0x0d, 0x5f, 0x79, 0x49, 0xe3, 0x44, 0x45, - 0x6c, 0x88, 0x1f, 0x94, 0x07, 0xc7, 0xe1, 0xd6, 0xfe, 0xb0, 0x6d, 0x64, 0x22, 0x87, 0xe8, 0x60, 0x35, 0x4a, 0xf7, - 0xc6, 0x77, 0x44, 0x76, 0x3f, 0xde, 0x5f, 0x6b, 0x89, 0x40, 0x4b, 0xcb, 0xf7, 0x6a, 0x57, 0x13, 0xce, 0x9f, 0xde, - 0x76, 0x15, 0x9b, 0x94, 0x19, 0xc5, 0xb7, 0x54, 0xb6, 0xaf, 0xbe, 0xff, 0x8a, 0x7e, 0x16, 0x25, 0x99, 0xc2, 0xd7, - 0xb2, 0x85, 0xe7, 0xd6, 0x32, 0x23, 0x0d, 0x00, 0x55, 0x24, 0x46, 0x73, 0xc9, 0xd3, 0x2e, 0xe9, 0x30, 0x10, 0x6d, - 0xfc, 0x58, 0x6c, 0x9a, 0x45, 0xa8, 0x28, 0x7b, 0xc0, 0x66, 0xa3, 0x1b, 0x32, 0x08, 0x4f, 0xd0, 0x8b, 0x7f, 0xa5, - 0x03, 0x2f, 0x2a, 0xe7, 0xca, 0xd2, 0xad, 0x2f, 0x6f, 0xeb, 0x6f, 0xd2, 0xf5, 0xa4, 0xd6, 0xbb, 0x32, 0x5c, 0x2c, - 0x68, 0x46, 0xbe, 0xf2, 0x5f, 0x0d, 0xe0, 0x75, 0x48, 0xd3, 0x19, 0x0b, 0x7f, 0x62, 0xea, 0x1e, 0x79, 0x5b, 0x99, - 0xf7, 0xdb, 0x65, 0x73, 0x3e, 0x68, 0x1f, 0xbc, 0xa4, 0xaa, 0x3f, 0xe0, 0xf8, 0xc8, 0x79, 0xb8, 0xbf, 0x8a, 0x69, - 0x6e, 0x45, 0xc1, 0x80, 0xe7, 0xa3, 0x15, 0x4d, 0xba, 0xab, 0x47, 0x2b, 0x22, 0x8c, 0x25, 0x4e, 0x2d, 0x6e, 0x75, - 0x21, 0x93, 0xa3, 0xdc, 0x42, 0xdf, 0xc9, 0xcb, 0xdc, 0xe2, 0x3a, 0xda, 0xcb, 0xcc, 0xf4, 0x94, 0x55, 0xf7, 0x1b, - 0xc2, 0xa8, 0x8f, 0xcc, 0x2e, 0x5a, 0x05, 0xa7, 0x95, 0x46, 0xb8, 0xa1, 0x5e, 0x6b, 0x8a, 0x05, 0xce, 0x8d, 0x82, - 0x5a, 0xd5, 0x3b, 0x4f, 0xbb, 0xc6, 0x41, 0xb6, 0x99, 0xd3, 0x8a, 0xd0, 0xed, 0x57, 0xb8, 0xa7, 0xb0, 0xae, 0xf3, - 0xe0, 0x6a, 0x4e, 0x34, 0x38, 0x8d, 0xdb, 0x6d, 0xb3, 0x88, 0x16, 0xb2, 0x8b, 0x15, 0xfd, 0x7a, 0x00, 0xfe, 0x8b, - 0x1d, 0x8a, 0x0f, 0x5b, 0xa9, 0xb1, 0x15, 0x23, 0x2b, 0x34, 0xf5, 0x76, 0x8e, 0x08, 0xff, 0xc2, 0xb7, 0xe4, 0x76, - 0x5b, 0xaa, 0x08, 0x35, 0x75, 0xb3, 0x6a, 0x7b, 0xed, 0x64, 0xbf, 0x34, 0x49, 0xfb, 0x61, 0x9e, 0x9e, 0x10, 0x2a, - 0x51, 0x7b, 0x73, 0x68, 0x88, 0x25, 0xd7, 0x46, 0x9c, 0x1b, 0x4c, 0x48, 0xe3, 0xbf, 0xbf, 0x11, 0x90, 0x13, 0x29, - 0xe9, 0x70, 0x39, 0xf6, 0x2c, 0xc5, 0x48, 0xa2, 0xf9, 0xc8, 0xe0, 0x75, 0x0a, 0x8b, 0xb4, 0x95, 0x27, 0xd7, 0x2d, - 0x75, 0x43, 0xdd, 0x35, 0x7d, 0x92, 0xaa, 0xe3, 0xbc, 0x38, 0xc2, 0xdd, 0xa9, 0x82, 0x46, 0xf5, 0xe6, 0xe4, 0x0c, - 0x49, 0xdb, 0x99, 0x17, 0x42, 0xf2, 0x41, 0xbc, 0x96, 0x44, 0x8a, 0xed, 0x27, 0x59, 0xea, 0x3e, 0xbe, 0x39, 0x88, - 0x0a, 0x84, 0x8b, 0x70, 0x8c, 0xc4, 0xfe, 0x14, 0x63, 0x8a, 0xee, 0x2c, 0x4a, 0x82, 0x4d, 0xd5, 0xc9, 0x19, 0x3a, - 0xd3, 0x7c, 0x02, 0x81, 0x65, 0x37, 0xc8, 0xe8, 0xa0, 0x2e, 0x62, 0x7e, 0xf4, 0xed, 0x10, 0x37, 0xbf, 0xe5, 0xe0, - 0x1a, 0x6d, 0xcf, 0x8c, 0x33, 0xa5, 0xb6, 0xf8, 0xa7, 0x39, 0x5c, 0x9f, 0xc0, 0xec, 0xee, 0x50, 0xc2, 0x89, 0x38, - 0x92, 0x50, 0xaf, 0x3f, 0x57, 0x3f, 0x6c, 0x22, 0x85, 0xce, 0x09, 0xad, 0x0d, 0xb4, 0xf8, 0x34, 0xa7, 0xab, 0x05, - 0x1f, 0xc6, 0x61, 0xc7, 0x90, 0xa9, 0x92, 0xfc, 0x2e, 0xfa, 0xdc, 0xcf, 0x05, 0x18, 0xde, 0x43, 0x5c, 0xe7, 0x7b, - 0x67, 0x47, 0xcd, 0xc2, 0x2d, 0x84, 0xed, 0x4f, 0xa3, 0x84, 0x1c, 0xf4, 0x6b, 0xe5, 0xe7, 0x88, 0x5f, 0x7d, 0xa4, - 0x67, 0xb2, 0xe1, 0x87, 0x43, 0xb4, 0xb8, 0x96, 0xb0, 0x24, 0xc3, 0xe8, 0xfd, 0x8b, 0x57, 0x18, 0xf6, 0x12, 0x18, - 0x3c, 0x83, 0xbd, 0x05, 0x02, 0xe0, 0xf6, 0xe8, 0x27, 0x0c, 0xb5, 0x54, 0x0a, 0xc2, 0xb9, 0xe4, 0x21, 0x41, 0x62, - 0x5c, 0xca, 0xd5, 0xda, 0xa4, 0x4f, 0xc0, 0x5a, 0x3b, 0x4e, 0x1d, 0x34, 0x26, 0x3d, 0xcf, 0x92, 0xe6, 0xcb, 0x98, - 0x3f, 0x0b, 0x14, 0x2c, 0x3f, 0x34, 0x35, 0xdd, 0x83, 0xa0, 0xea, 0xca, 0x18, 0x6b, 0xba, 0xa3, 0x1d, 0x04, 0xef, - 0xaf, 0xd5, 0x33, 0xa2, 0xfc, 0xdd, 0x1a, 0x93, 0x1d, 0x04, 0x85, 0x82, 0x2d, 0x6e, 0xc8, 0xa1, 0x10, 0x62, 0x57, - 0xe3, 0xce, 0xbe, 0x8b, 0x4e, 0x65, 0xa9, 0x99, 0xdc, 0x6e, 0x94, 0x4d, 0x33, 0x4c, 0x98, 0x62, 0x87, 0x56, 0xf2, - 0x05, 0x45, 0x89, 0x5d, 0xbb, 0x5a, 0x94, 0x33, 0xbf, 0xdb, 0xfa, 0x38, 0xb6, 0x50, 0x58, 0xf5, 0x39, 0x98, 0xe5, - 0xc4, 0xb4, 0x6d, 0x97, 0x81, 0xdc, 0xd9, 0x1b, 0x64, 0xaa, 0x29, 0x1b, 0x43, 0x98, 0x77, 0xcc, 0x47, 0xe6, 0xf0, - 0x3d, 0xb2, 0x3b, 0x0f, 0x99, 0xbb, 0xc9, 0x65, 0x2f, 0x3f, 0xeb, 0xf5, 0xcf, 0x1c, 0xa0, 0x90, 0xc6, 0xc0, 0xb1, - 0x79, 0xde, 0x10, 0x6b, 0x99, 0x98, 0x2e, 0x3b, 0x56, 0xba, 0x83, 0x41, 0xc1, 0xeb, 0x1c, 0x28, 0x54, 0xd2, 0x94, - 0x38, 0x71, 0x3d, 0x84, 0x35, 0xa2, 0x1c, 0xde, 0x3b, 0x31, 0xd7, 0xc9, 0x44, 0xb2, 0xf1, 0xaf, 0xf6, 0x3e, 0x5c, - 0xb4, 0x01, 0xfa, 0x78, 0x66, 0xa3, 0x16, 0x16, 0x89, 0x38, 0x85, 0x21, 0x3f, 0xaa, 0x79, 0xac, 0x49, 0xe8, 0x03, - 0x27, 0x03, 0xa9, 0xa0, 0x97, 0x0a, 0xfc, 0x6f, 0x91, 0x9c, 0xb1, 0x72, 0x4a, 0x01, 0x2a, 0xa2, 0xb5, 0x6b, 0xfe, - 0x75, 0xef, 0x7a, 0x4c, 0x82, 0x7a, 0xb5, 0x00, 0x6e, 0x2d, 0x25, 0x92, 0x9f, 0xfb, 0xdb, 0x30, 0x3a, 0xcc, 0x8c, - 0x93, 0xce, 0xf3, 0xea, 0x57, 0x4f, 0x2e, 0x22, 0x99, 0xa2, 0x2d, 0x04, 0x4f, 0x5d, 0x0c, 0x4c, 0xe4, 0x21, 0x9e, - 0x9b, 0x76, 0xd0, 0xa5, 0xc6, 0xa1, 0xfc, 0xcb, 0xae, 0xe3, 0x68, 0x6c, 0x16, 0xe3, 0x04, 0x42, 0x95, 0xea, 0xf2, - 0x3c, 0x73, 0x5d, 0xd6, 0x8b, 0x3d, 0x69, 0xa2, 0xae, 0xac, 0xf4, 0x5b, 0xa8, 0x98, 0x37, 0xba, 0x3a, 0x45, 0x6d, - 0x31, 0xad, 0x93, 0x97, 0x6d, 0x56, 0x66, 0xd5, 0x04, 0x6f, 0x43, 0xb6, 0x11, 0x4e, 0x76, 0xc1, 0x7e, 0x3a, 0xc7, - 0x4b, 0x77, 0x0d, 0x8d, 0x12, 0xbc, 0x84, 0x54, 0xd1, 0xdf, 0x99, 0x16, 0x0e, 0x24, 0x5a, 0x51, 0xb2, 0xf6, 0xa5, - 0xff, 0x66, 0x37, 0x9c, 0xe4, 0x5c, 0x47, 0xef, 0x50, 0x7b, 0x1c, 0x8a, 0x66, 0x3c, 0x26, 0x6b, 0x9c, 0xe7, 0x74, - 0x29, 0x70, 0xc9, 0x92, 0x72, 0xee, 0x05, 0xbb, 0x2b, 0x90, 0xf2, 0xfa, 0xcb, 0x16, 0x09, 0x99, 0x70, 0xfb, 0x3c, - 0x19, 0xb8, 0x8c, 0x09, 0xd2, 0x83, 0xde, 0xf5, 0x03, 0xd5, 0x58, 0xe0, 0xee, 0x97, 0x39, 0xe7, 0x7f, 0xae, 0x48, - 0x92, 0x86, 0x78, 0x68, 0x11, 0x1c, 0xa6, 0xda, 0xaf, 0xc0, 0xad, 0x63, 0xc0, 0xb5, 0x59, 0x99, 0x3e, 0xf8, 0xf5, - 0xf8, 0x40, 0x34, 0x02, 0xff, 0xf9, 0xf8, 0x2b, 0xe2, 0xd0, 0x83, 0x67, 0x2b, 0x42, 0xb2, 0xae, 0x87, 0x8b, 0x34, - 0xff, 0xd5, 0xee, 0x13, 0x80, 0x45, 0xb8, 0x91, 0x74, 0x2c, 0x01, 0x1d, 0xdf, 0x0d, 0x0b, 0xcc, 0x53, 0x60, 0x97, - 0xd1, 0x1f, 0xb3, 0x87, 0x95, 0x6b, 0x1c, 0x2a, 0x4e, 0xb4, 0x85, 0x71, 0xb8, 0x24, 0x58, 0xde, 0xd2, 0xb9, 0x8a, - 0x40, 0x06, 0x07, 0xa4, 0x5e, 0xde, 0x19, 0xc7, 0x23, 0xf7, 0x91, 0x15, 0x1c, 0xf8, 0x66, 0x58, 0xb6, 0x47, 0x06, - 0x1c, 0xea, 0x88, 0x1e, 0xd0, 0xe1, 0xd6, 0x20, 0x43, 0x4d, 0x14, 0x63, 0x0b, 0x3e, 0x3e, 0xaa, 0xc7, 0x0c, 0xf2, - 0x5c, 0x0e, 0xf8, 0xfa, 0xc0, 0xa0, 0xe2, 0x30, 0x81, 0xfc, 0x5d, 0x08, 0x83, 0x3a, 0xec, 0xad, 0x05, 0x80, 0xd2, - 0x27, 0x88, 0xa1, 0x13, 0x87, 0xd4, 0x1b, 0xd0, 0xe4, 0x7b, 0x90, 0xd2, 0x08, 0xfe, 0xa2, 0x22, 0x33, 0x1a, 0x3d, - 0x15, 0xb3, 0x50, 0x18, 0x45, 0x2b, 0x64, 0xa8, 0x4d, 0x88, 0x34, 0x75, 0xf7, 0x96, 0x11, 0xf9, 0xb1, 0x3d, 0xf0, - 0x65, 0x69, 0xaf, 0x45, 0x22, 0x55, 0xce, 0x78, 0x1f, 0x40, 0xa9, 0x39, 0xb8, 0x0a, 0xd4, 0x3d, 0x53, 0x7d, 0x4e, - 0xc5, 0xda, 0xcc, 0xb2, 0x58, 0x78, 0x20, 0x1f, 0xe2, 0x62, 0x7c, 0x15, 0x5d, 0xbe, 0xad, 0x28, 0x9e, 0xc5, 0xdf, - 0xfd, 0xba, 0xe9, 0x43, 0x0a, 0xff, 0x52, 0xf0, 0xd5, 0x59, 0x73, 0xe5, 0x84, 0x75, 0x9e, 0x20, 0x5d, 0x37, 0x18, - 0x74, 0x5b, 0x4b, 0x2c, 0x4f, 0xce, 0xf4, 0xeb, 0x76, 0x31, 0xa5, 0x6a, 0xaa, 0xde, 0xce, 0x03, 0x08, 0xa4, 0xf6, - 0x9d, 0x49, 0x67, 0xd0, 0x2c, 0x24, 0xcb, 0x0c, 0x13, 0xfc, 0xb9, 0xc3, 0x6e, 0x50, 0x91, 0x06, 0x5e, 0xb6, 0x96, - 0x5e, 0xe1, 0x73, 0x3c, 0xae, 0xe8, 0x25, 0xa7, 0xf1, 0xb7, 0x77, 0xa4, 0x3c, 0x6d, 0xfd, 0x54, 0x2e, 0xe7, 0x65, - 0xd1, 0x97, 0xa6, 0x5f, 0xd1, 0x6f, 0x52, 0xb7, 0x3c, 0xee, 0x22, 0x02, 0xe9, 0xff, 0x2a, 0xd7, 0x35, 0x8d, 0xbe, - 0x0a, 0x7b, 0xb1, 0x8b, 0x60, 0xf4, 0xec, 0xb6, 0x6e, 0x0e, 0x39, 0x53, 0x5a, 0x94, 0x1a, 0x0c, 0x4d, 0x3a, 0xfe, - 0x32, 0x0a, 0x4b, 0xd7, 0x94, 0x76, 0xee, 0xa7, 0x3b, 0xbd, 0x54, 0x47, 0x26, 0xfe, 0x6d, 0x2f, 0x7f, 0xc8, 0x3a, - 0x6a, 0x44, 0x17, 0xfe, 0x0f, 0xfe, 0x3c, 0xa2, 0x9c, 0x2f, 0x75, 0x4a, 0xa5, 0x1d, 0xd4, 0x47, 0x55, 0x72, 0x3c, - 0x1d, 0x07, 0xca, 0x68, 0x14, 0xcf, 0xd4, 0xf1, 0xcc, 0x69, 0x26, 0xe8, 0x89, 0x6e, 0x90, 0xac, 0xe5, 0x00, 0x2d, - 0x80, 0x9a, 0x92, 0x11, 0xa7, 0xea, 0x04, 0x37, 0x13, 0xa7, 0xd7, 0x45, 0x27, 0x48, 0x4e, 0x0b, 0xc7, 0xe8, 0x73, - 0x59, 0x0c, 0x51, 0x29, 0xeb, 0xdb, 0xab, 0x23, 0xaa, 0x1e, 0x65, 0xdb, 0xd2, 0xb7, 0x8a, 0x8d, 0x76, 0xa8, 0x83, - 0x15, 0x73, 0x60, 0x97, 0x97, 0xcc, 0xd4, 0x72, 0xe6, 0x60, 0xe6, 0xa7, 0x67, 0xc0, 0x9e, 0x03, 0x66, 0xe7, 0x0c, - 0x31, 0x47, 0x11, 0xaa, 0xc4, 0xd2, 0x18, 0x14, 0x17, 0x76, 0x92, 0x48, 0x7d, 0x3e, 0xef, 0x8e, 0x52, 0x15, 0x73, - 0x6a, 0x2a, 0xaf, 0x07, 0xb0, 0x2d, 0xb1, 0xf2, 0x57, 0x34, 0xa1, 0x1f, 0xe9, 0x16, 0x23, 0xfc, 0x8d, 0x8a, 0xe3, - 0xfc, 0x7e, 0x7e, 0x9b, 0x9a, 0x29, 0x01, 0x13, 0x43, 0x4e, 0x5d, 0x9d, 0x60, 0x5d, 0xa5, 0x98, 0x96, 0xc5, 0x99, - 0x96, 0xe7, 0x7c, 0x36, 0xb6, 0x25, 0xd6, 0x42, 0x38, 0x5b, 0xde, 0xf6, 0xc6, 0x5d, 0x5e, 0x30, 0x26, 0x92, 0x24, - 0x96, 0x6d, 0x5e, 0x4d, 0x07, 0x20, 0xc1, 0x1d, 0x62, 0x9b, 0x7e, 0xc1, 0xb7, 0xa2, 0x88, 0x07, 0xb0, 0x9b, 0xcc, - 0xce, 0x62, 0xab, 0x4c, 0x07, 0xe3, 0xe0, 0x96, 0xff, 0xd5, 0xb6, 0x86, 0x02, 0x21, 0x11, 0x9f, 0x08, 0x70, 0x49, - 0x74, 0x36, 0x83, 0x3a, 0x85, 0x0c, 0x37, 0xf1, 0x9d, 0xa2, 0xc9, 0x77, 0xb4, 0xfa, 0x8e, 0x88, 0xec, 0xdb, 0xab, - 0x88, 0x28, 0x4a, 0xb9, 0x3c, 0x6a, 0xc5, 0x49, 0x8e, 0x68, 0x4e, 0xc6, 0x97, 0x8e, 0xa4, 0x9d, 0x34, 0xe3, 0x4a, - 0x4d, 0x6f, 0x8f, 0xdf, 0x65, 0x10, 0xe9, 0x57, 0xe7, 0xb9, 0x15, 0xc7, 0x79, 0x21, 0x0a, 0xca, 0x07, 0xdc, 0x86, - 0x51, 0x8d, 0x56, 0xbe, 0x99, 0xf3, 0x80, 0x76, 0x66, 0x78, 0x38, 0x9d, 0xb5, 0x6f, 0xb6, 0x2d, 0xf8, 0x72, 0x1c, - 0x0e, 0x63, 0xd3, 0xbe, 0x7f, 0xfe, 0xae, 0x7e, 0x6f, 0xc6, 0x87, 0x57, 0xde, 0x49, 0xea, 0x1d, 0x0f, 0x60, 0xea, - 0xda, 0x98, 0xad, 0x73, 0x70, 0x9e, 0xc6, 0xd8, 0x22, 0xfa, 0x5f, 0xda, 0xc6, 0x67, 0xa5, 0x7f, 0x02, 0xee, 0xc1, - 0x9d, 0x64, 0x59, 0xfa, 0xc5, 0x99, 0x46, 0x8b, 0xfc, 0x89, 0xe5, 0x49, 0xad, 0x1e, 0x74, 0x5c, 0x9a, 0x5c, 0xbc, - 0x42, 0xba, 0x3c, 0x4b, 0xbf, 0x9c, 0x2d, 0xf4, 0x8f, 0xd3, 0x55, 0x00, 0xff, 0x8f, 0x73, 0xa4, 0xb8, 0x3f, 0xa6, - 0xd9, 0x8b, 0x74, 0xe3, 0xfb, 0xb3, 0x9b, 0xd5, 0xeb, 0x82, 0x3d, 0x3a, 0x4f, 0xb6, 0x6c, 0x5d, 0x0b, 0xad, 0xa9, - 0x1b, 0x17, 0xd4, 0x9d, 0xdd, 0x66, 0xed, 0x1b, 0xeb, 0x53, 0x6b, 0xe8, 0xbb, 0x98, 0x48, 0x3f, 0x7f, 0x44, 0x3f, - 0x5d, 0x7b, 0x8a, 0x0b, 0xc3, 0x7e, 0xa7, 0xba, 0x1e, 0x35, 0x33, 0x9d, 0x0a, 0x12, 0x9a, 0x97, 0x3c, 0xdd, 0x37, - 0x39, 0xaf, 0xe5, 0xf8, 0x72, 0xf4, 0x34, 0xa2, 0xa6, 0x7d, 0x47, 0x19, 0xdd, 0x4b, 0x82, 0x31, 0xea, 0x2a, 0x35, - 0x30, 0xfa, 0xe2, 0x55, 0x05, 0x06, 0x01, 0xaa, 0xf3, 0xfa, 0x40, 0x8a, 0xc0, 0xe0, 0xc3, 0x21, 0x8f, 0xe5, 0x06, - 0x03, 0x27, 0x4b, 0xeb, 0x20, 0xf5, 0xf2, 0x20, 0x1c, 0xa9, 0xea, 0xe2, 0x6d, 0x26, 0xa0, 0xc0, 0xeb, 0xa9, 0xfe, - 0x1b, 0xdd, 0x9c, 0x1b, 0xe7, 0x69, 0xc6, 0x87, 0x73, 0x43, 0xe9, 0x52, 0x71, 0xf1, 0xda, 0xae, 0x62, 0x1c, 0x16, - 0xd5, 0x56, 0x25, 0x53, 0x32, 0x65, 0x0e, 0x13, 0xf3, 0x33, 0x41, 0x7a, 0xde, 0xa8, 0x43, 0xee, 0x97, 0x4f, 0xf2, - 0x9a, 0x2e, 0x71, 0x65, 0x92, 0x8d, 0x42, 0xf8, 0x3f, 0x34, 0x55, 0x6b, 0x0e, 0xa4, 0x46, 0xe0, 0x72, 0x70, 0xb5, - 0x54, 0xde, 0xb6, 0xb4, 0x9f, 0x3f, 0x2e, 0xdf, 0xa7, 0xb7, 0x95, 0x24, 0xf9, 0x2f, 0x4d, 0xd8, 0x98, 0xf3, 0xc9, - 0x28, 0xb4, 0x29, 0xc4, 0x0d, 0x4c, 0x45, 0x3b, 0xc6, 0x4f, 0x0a, 0x2f, 0x08, 0xea, 0xf3, 0x0e, 0x45, 0x03, 0xb0, - 0x79, 0x95, 0x8a, 0xdc, 0x19, 0x68, 0x59, 0xa2, 0x6c, 0xdd, 0xe8, 0x6b, 0xc3, 0xf7, 0x38, 0x78, 0xd5, 0x70, 0xeb, - 0xde, 0xcb, 0xa6, 0x0a, 0x94, 0x4d, 0x5b, 0x59, 0xbc, 0x0a, 0x25, 0xcf, 0xd4, 0x4b, 0x9d, 0x2b, 0x69, 0x17, 0x0e, - 0x7e, 0xa6, 0xe2, 0xe8, 0x57, 0x12, 0x81, 0x5d, 0x39, 0xc8, 0x00, 0xc7, 0xed, 0x36, 0xc7, 0x19, 0x02, 0x11, 0x94, - 0x85, 0x56, 0x20, 0xd4, 0x22, 0x55, 0xa7, 0xbe, 0x33, 0x62, 0x35, 0x01, 0xe4, 0x8a, 0xbd, 0x8b, 0x56, 0xc8, 0x9f, - 0x65, 0x06, 0x3a, 0xb0, 0xa3, 0x3d, 0x37, 0x2e, 0xbe, 0x3e, 0x25, 0xe8, 0xd7, 0x12, 0x7b, 0x67, 0x54, 0xc7, 0xc8, - 0x69, 0x3e, 0x3f, 0x58, 0x26, 0xc6, 0x6d, 0x31, 0xde, 0xb6, 0x91, 0x39, 0x81, 0x29, 0x50, 0x89, 0x99, 0xd6, 0xaa, - 0x65, 0x04, 0x39, 0x4c, 0xb2, 0x13, 0x8f, 0x34, 0x19, 0x2b, 0x96, 0xf7, 0x40, 0x60, 0xce, 0x30, 0x6e, 0xd3, 0x98, - 0x55, 0x2b, 0xa4, 0x60, 0x04, 0xc3, 0xd0, 0xf8, 0x60, 0x31, 0x12, 0xe6, 0x95, 0x80, 0x0c, 0x1c, 0x29, 0x52, 0x10, - 0xdf, 0xed, 0x68, 0x7e, 0x30, 0xa5, 0x47, 0x9c, 0xa8, 0x70, 0x8f, 0xca, 0x29, 0xdd, 0x60, 0xa8, 0xe7, 0x82, 0x05, - 0x4c, 0x31, 0xc5, 0x46, 0x72, 0xa0, 0x32, 0xdc, 0xaa, 0x90, 0xb1, 0x5c, 0xf7, 0xb6, 0x3f, 0xbd, 0x97, 0x34, 0x6c, - 0xfa, 0x4a, 0x48, 0x1a, 0xd4, 0x5a, 0x71, 0xe1, 0x03, 0x76, 0xd1, 0xb3, 0xf7, 0x4d, 0x76, 0xc8, 0x34, 0x91, 0x31, - 0xda, 0x4b, 0xa2, 0x7c, 0x69, 0x7f, 0xac, 0x15, 0x5b, 0x63, 0x80, 0xab, 0xde, 0xe9, 0xfa, 0x84, 0x9c, 0xf2, 0x4e, - 0x8b, 0x82, 0x0c, 0x32, 0x2c, 0x23, 0xfa, 0xf0, 0x9f, 0x2e, 0xf2, 0xcd, 0x58, 0x3f, 0x4b, 0xa8, 0x53, 0x93, 0xd6, - 0x2f, 0x7a, 0xb3, 0xcd, 0xce, 0xc9, 0x6c, 0x01, 0xa0, 0xf0, 0x5f, 0xad, 0x3f, 0xb1, 0x35, 0x22, 0xd4, 0x50, 0x04, - 0x2f, 0x01, 0x57, 0x1c, 0xf0, 0xa8, 0xf6, 0x34, 0x42, 0xe1, 0x20, 0x09, 0x4d, 0x99, 0xb3, 0xdd, 0xdf, 0x10, 0xb4, - 0x71, 0x4d, 0x41, 0x87, 0x3e, 0x85, 0xa6, 0xff, 0xea, 0xb3, 0x5f, 0xa0, 0x5a, 0x45, 0xd1, 0x26, 0x76, 0x4d, 0xb1, - 0x38, 0xa4, 0x70, 0x93, 0x6b, 0x87, 0x77, 0x89, 0x10, 0xe0, 0xec, 0x5f, 0xcc, 0x29, 0x4e, 0x16, 0xd6, 0x9d, 0x4d, - 0x08, 0x96, 0x0a, 0x46, 0x52, 0xa2, 0x43, 0x19, 0x73, 0x9d, 0x39, 0x1e, 0x56, 0xe3, 0x97, 0x2e, 0xe8, 0xe1, 0x10, - 0x5e, 0xc7, 0xf8, 0xfc, 0xe1, 0x79, 0xc7, 0x3b, 0x56, 0x68, 0x99, 0xb5, 0x84, 0x29, 0xa4, 0x87, 0x7c, 0x0f, 0x83, - 0xca, 0x63, 0xcf, 0x05, 0xd3, 0xea, 0xfe, 0xa1, 0x54, 0x68, 0xe7, 0x39, 0xa8, 0xa9, 0x17, 0xc0, 0xc4, 0xc2, 0x4d, - 0x29, 0x0d, 0xbb, 0x92, 0x40, 0x6a, 0x53, 0x04, 0x30, 0xfe, 0xe4, 0x13, 0x22, 0x1e, 0xc4, 0x41, 0xa9, 0x96, 0xd0, - 0xf1, 0xe6, 0x68, 0xa3, 0x56, 0x77, 0xb1, 0x30, 0xbe, 0x05, 0x2b, 0x80, 0xb6, 0xc4, 0x86, 0xe1, 0x61, 0xf1, 0xa9, - 0x94, 0x37, 0x21, 0x01, 0xb5, 0xab, 0x20, 0x85, 0x95, 0x83, 0xb5, 0x1f, 0x4c, 0x80, 0xaa, 0x5d, 0x93, 0x28, 0xfd, - 0xb6, 0x52, 0x44, 0x0a, 0x8b, 0x42, 0x35, 0x8f, 0xec, 0xde, 0x96, 0x75, 0xda, 0x50, 0x35, 0x4f, 0x91, 0x2e, 0x95, - 0xda, 0x2e, 0x71, 0x6d, 0xff, 0xa7, 0x99, 0x42, 0xe6, 0x3e, 0x3b, 0x61, 0xf5, 0xb6, 0xf6, 0x14, 0xea, 0x64, 0x54, - 0x4f, 0xf1, 0xf2, 0x51, 0xb5, 0xc2, 0xdf, 0x56, 0xe6, 0xa0, 0x01, 0x0f, 0xc6, 0x45, 0xfa, 0x67, 0xef, 0xc3, 0x35, - 0xe4, 0x9e, 0xbc, 0x6f, 0x55, 0xa1, 0x48, 0x8e, 0x07, 0x33, 0xec, 0x2f, 0x3a, 0x81, 0xe3, 0x09, 0xdb, 0x36, 0x09, - 0x58, 0xeb, 0xf8, 0x1e, 0x49, 0x41, 0x8a, 0xfc, 0x36, 0xd6, 0x86, 0xc4, 0xdc, 0xf0, 0xa3, 0x44, 0x71, 0x4b, 0x29, - 0x5d, 0x25, 0x4f, 0x4e, 0x6d, 0xbb, 0x82, 0x52, 0x13, 0x47, 0xe0, 0xd8, 0xfa, 0xca, 0x11, 0xff, 0x6c, 0xfb, 0x6a, - 0x97, 0x2b, 0x89, 0x43, 0xb1, 0xc8, 0x4f, 0x75, 0x3f, 0x29, 0x0f, 0x93, 0x01, 0xac, 0x26, 0xd4, 0x19, 0x0b, 0x47, - 0x95, 0x24, 0x80, 0xc0, 0x04, 0xa8, 0x25, 0x3c, 0x17, 0x6a, 0x91, 0xdb, 0x30, 0xa9, 0xd9, 0x56, 0xce, 0x55, 0xfb, - 0x64, 0x6b, 0x6a, 0xcd, 0xc0, 0xcd, 0xc5, 0xc6, 0x71, 0x75, 0x67, 0x07, 0xb2, 0xd2, 0x43, 0x02, 0x9d, 0x7b, 0x53, - 0x62, 0x41, 0x53, 0xe0, 0xc3, 0xd1, 0xee, 0xbe, 0x03, 0x10, 0x45, 0x23, 0x46, 0xff, 0x59, 0xc1, 0xe4, 0xa4, 0xdf, - 0xe8, 0x06, 0x7c, 0x4b, 0x95, 0x79, 0x41, 0xd9, 0xe0, 0x72, 0x77, 0x7e, 0x63, 0xd5, 0x03, 0xcf, 0x4c, 0x98, 0x93, - 0x72, 0xed, 0xc1, 0x46, 0x66, 0x89, 0x9a, 0x70, 0xfd, 0x7f, 0x35, 0xd7, 0x90, 0x1c, 0x80, 0x5c, 0x8c, 0x7d, 0xab, - 0xac, 0xc0, 0xd5, 0x2c, 0x74, 0x40, 0x61, 0x1f, 0x0c, 0x9c, 0x0a, 0x1b, 0x76, 0x03, 0x6e, 0x7e, 0x90, 0xa6, 0x95, - 0xef, 0x12, 0xe8, 0xfe, 0xa7, 0x58, 0x63, 0xdf, 0xbb, 0x25, 0x6b, 0xd8, 0xe8, 0x4d, 0x41, 0xd3, 0xe8, 0x5e, 0x33, - 0x59, 0xd3, 0xd9, 0xca, 0x0c, 0x55, 0x23, 0xaf, 0xd6, 0x8f, 0x45, 0xdc, 0x1a, 0x9e, 0x9f, 0xc9, 0x79, 0xbd, 0x8f, - 0xe9, 0xa5, 0x6e, 0x3c, 0xf6, 0x45, 0xdd, 0xe1, 0xab, 0x1b, 0xd1, 0x86, 0xb3, 0xa2, 0x88, 0x9d, 0x0f, 0xeb, 0x9e, - 0x8a, 0xb4, 0x5b, 0x47, 0xbb, 0x78, 0x5b, 0x30, 0xa7, 0x64, 0x54, 0x67, 0xd0, 0x14, 0xba, 0x0a, 0xc7, 0xba, 0x7e, - 0xbe, 0xb8, 0x02, 0xeb, 0x8e, 0x96, 0x55, 0x82, 0x37, 0x26, 0x5d, 0xd4, 0x61, 0xd7, 0xf7, 0x8c, 0x0f, 0x89, 0xaa, - 0x8f, 0x46, 0xeb, 0x34, 0xf7, 0x05, 0x34, 0xa0, 0xe5, 0x0b, 0x3a, 0xb4, 0x21, 0xab, 0xd1, 0x5d, 0x69, 0xf2, 0xa4, - 0x56, 0xd5, 0x6f, 0x79, 0x0c, 0xde, 0xb1, 0x7c, 0x35, 0x56, 0x9d, 0x8e, 0x7f, 0x19, 0xbe, 0xbc, 0xac, 0xee, 0x90, - 0xf4, 0xb9, 0x97, 0x01, 0x60, 0xda, 0xe6, 0x93, 0x41, 0xbf, 0x2f, 0x02, 0x91, 0x91, 0xdf, 0x62, 0x3c, 0x7b, 0x29, - 0x4b, 0x00, 0x1d, 0x57, 0x05, 0xbd, 0x33, 0x4d, 0x7a, 0x79, 0x4f, 0x24, 0xe2, 0xc6, 0xc0, 0x78, 0x83, 0x42, 0x15, - 0x52, 0xef, 0x34, 0x81, 0xb8, 0x47, 0x1d, 0x13, 0xe9, 0x45, 0xd5, 0xf7, 0xab, 0x04, 0x07, 0xcf, 0xa2, 0xd5, 0x6e, - 0xff, 0xb3, 0x68, 0x0a, 0xe4, 0xc4, 0xc1, 0x44, 0x5d, 0xe1, 0x84, 0xc7, 0x3f, 0x9e, 0x68, 0xbf, 0x64, 0x47, 0xaa, - 0xe9, 0x30, 0x5f, 0xc5, 0x57, 0x76, 0xaa, 0x5a, 0xf1, 0xcb, 0xbc, 0xef, 0x67, 0x8b, 0xb4, 0xf1, 0x32, 0xd2, 0xab, - 0xd9, 0x5e, 0xed, 0x6c, 0xa2, 0xba, 0x53, 0x58, 0x1e, 0x35, 0x59, 0x51, 0x1d, 0x13, 0xab, 0x56, 0x5f, 0x1d, 0x7a, - 0xe5, 0xed, 0x65, 0xf6, 0x9b, 0x25, 0x61, 0xe6, 0xec, 0x69, 0xe1, 0xde, 0xec, 0x6c, 0xc9, 0x83, 0xee, 0xe7, 0xe0, - 0xbf, 0xc7, 0x46, 0x8a, 0x2d, 0x53, 0xbb, 0x28, 0x47, 0x02, 0x00, 0x0e, 0x12, 0xbf, 0x3a, 0xbd, 0xf9, 0x7b, 0x2d, - 0x2a, 0x75, 0xb3, 0xda, 0x69, 0x71, 0xe9, 0x1f, 0x23, 0x4a, 0x4b, 0xe3, 0x38, 0xe5, 0x08, 0xa2, 0x71, 0x6d, 0x7e, - 0xc1, 0x24, 0x73, 0xdf, 0x62, 0xb5, 0x12, 0x6b, 0xc9, 0x09, 0x14, 0x18, 0xb9, 0xd7, 0x35, 0xcf, 0x5d, 0xab, 0x53, - 0x58, 0xa6, 0xb6, 0xe6, 0xb0, 0xb5, 0xc3, 0xbe, 0x83, 0xaa, 0xaf, 0xa9, 0xc3, 0x55, 0x16, 0xbe, 0xad, 0x78, 0x21, - 0x5f, 0x4a, 0x79, 0x72, 0xea, 0xe6, 0x8d, 0x60, 0x29, 0x3e, 0x0a, 0x54, 0x73, 0x46, 0xf0, 0xa2, 0x56, 0x5f, 0x59, - 0xc4, 0x4a, 0x7e, 0x28, 0x09, 0xbd, 0xd8, 0x3d, 0x17, 0xd9, 0x80, 0xab, 0xb2, 0xfe, 0xbe, 0xfa, 0xdc, 0x23, 0x95, - 0x7d, 0x74, 0x61, 0x95, 0xda, 0x8e, 0x63, 0x6e, 0xa3, 0xa6, 0x2a, 0x78, 0xf3, 0xde, 0x35, 0xd8, 0x35, 0xb0, 0x3c, - 0x19, 0xcb, 0x25, 0x46, 0x06, 0x3e, 0xd6, 0xd6, 0x53, 0x7d, 0x65, 0x5e, 0x3d, 0x5a, 0xc9, 0x58, 0x48, 0xca, 0x2b, - 0x04, 0xa2, 0xd7, 0x7f, 0x96, 0x2b, 0x35, 0xac, 0xd5, 0xd9, 0x0a, 0x25, 0x1a, 0x31, 0xda, 0xbb, 0x54, 0x4e, 0x76, - 0x4d, 0x8f, 0x8c, 0xe9, 0xf3, 0xee, 0x47, 0xd5, 0xd2, 0x92, 0xd9, 0x86, 0x16, 0xff, 0x54, 0x64, 0x2c, 0xa9, 0x88, - 0x6d, 0xc5, 0x16, 0x7b, 0x16, 0x77, 0x01, 0x4c, 0x3e, 0x5d, 0x30, 0x77, 0x9f, 0x50, 0x0e, 0xc6, 0xea, 0x57, 0xaa, - 0x2a, 0x37, 0x3e, 0x4f, 0xbc, 0xbe, 0x6f, 0x60, 0x26, 0x91, 0x45, 0x1e, 0x05, 0x36, 0x2b, 0xeb, 0x69, 0x4f, 0x6f, - 0x73, 0x52, 0xa3, 0x5f, 0x18, 0x85, 0x56, 0x79, 0xc0, 0xe7, 0x9a, 0x79, 0xf2, 0xe6, 0x7d, 0xa7, 0x1b, 0x41, 0x86, - 0xa3, 0x8d, 0xb4, 0x41, 0xdb, 0x6d, 0x48, 0x7a, 0x8b, 0xf8, 0x0f, 0x29, 0xd3, 0x5f, 0x94, 0xf9, 0xea, 0xfb, 0xe1, - 0x7c, 0x5d, 0x4e, 0x50, 0x35, 0x7b, 0xc0, 0xe1, 0xd1, 0x58, 0x02, 0x2c, 0x20, 0x8e, 0x3e, 0x12, 0xb2, 0xb6, 0x26, - 0x28, 0x27, 0x3c, 0x52, 0xe5, 0x6c, 0x94, 0x77, 0x26, 0x7a, 0x42, 0xab, 0xca, 0xd9, 0x00, 0x5b, 0xd0, 0x8d, 0x5d, - 0xf2, 0x6d, 0x2c, 0x3c, 0x5d, 0xee, 0x77, 0x8e, 0xed, 0x81, 0x2b, 0xd7, 0x5c, 0xc0, 0x17, 0xde, 0x03, 0x77, 0xa1, - 0x5a, 0x40, 0x6b, 0x10, 0xff, 0x51, 0x54, 0xd9, 0xdd, 0xe6, 0xdc, 0x48, 0x24, 0x59, 0x28, 0x13, 0x2a, 0x6b, 0xf1, - 0x73, 0x83, 0x9c, 0xeb, 0x71, 0xe0, 0x1c, 0x29, 0x01, 0x82, 0x63, 0xc4, 0x24, 0xf6, 0xa6, 0x34, 0x54, 0x70, 0x8e, - 0x3e, 0x79, 0x2d, 0xbf, 0x60, 0xca, 0xd0, 0x05, 0x3a, 0x3d, 0xcf, 0x42, 0xc1, 0x7e, 0x60, 0x5d, 0x38, 0x3a, 0x69, - 0x39, 0xeb, 0x9f, 0x1d, 0x18, 0x01, 0xf2, 0x58, 0x79, 0x99, 0x24, 0x6c, 0x2d, 0x5a, 0xbd, 0xc9, 0xfb, 0x71, 0xa5, - 0x10, 0x2d, 0x16, 0xa8, 0xba, 0xfd, 0x02, 0x17, 0xa7, 0x25, 0x95, 0xac, 0x14, 0xb7, 0x0a, 0x15, 0x88, 0xd6, 0x9b, - 0x50, 0xf5, 0x3a, 0x7d, 0x6d, 0xdb, 0x51, 0x79, 0x69, 0x28, 0x36, 0x31, 0x04, 0x86, 0x58, 0x1f, 0x7e, 0xaa, 0xb6, - 0xe1, 0xb6, 0xb3, 0x2e, 0xee, 0x73, 0xdb, 0x7e, 0x0d, 0x5f, 0x8f, 0xc4, 0x9b, 0xca, 0xdb, 0xa6, 0x78, 0x58, 0x20, - 0xe2, 0x44, 0xd7, 0x6b, 0x0d, 0x9b, 0x93, 0x4f, 0x7f, 0x55, 0xa7, 0x4c, 0x8e, 0xe8, 0x63, 0x0f, 0x21, 0xe6, 0x42, - 0x44, 0x85, 0x48, 0xbf, 0x6f, 0x47, 0xe7, 0xca, 0x3d, 0x23, 0x44, 0xe7, 0xd8, 0x88, 0x75, 0x6c, 0x27, 0x81, 0xa7, - 0xb6, 0x14, 0xc4, 0x09, 0xdc, 0x7d, 0x27, 0x16, 0x7c, 0xf2, 0x85, 0x34, 0xe7, 0xe1, 0xf9, 0xcb, 0xdf, 0xfe, 0x4a, - 0x56, 0xea, 0xb9, 0xee, 0x2c, 0xba, 0xa6, 0xbb, 0xa4, 0x52, 0x97, 0xcf, 0x71, 0x17, 0xb3, 0xf0, 0x26, 0x6b, 0xff, - 0x7a, 0x78, 0x4b, 0x37, 0x6d, 0x48, 0x91, 0x4c, 0x51, 0xee, 0xfe, 0x4d, 0x3c, 0x35, 0x22, 0xc3, 0x5f, 0xf0, 0x8c, - 0xb1, 0xee, 0xcb, 0xaa, 0xf9, 0x60, 0xac, 0x04, 0xec, 0x3d, 0x27, 0x23, 0x73, 0x51, 0x70, 0xa3, 0x28, 0x44, 0x2b, - 0xd6, 0x83, 0xed, 0x40, 0x53, 0xf9, 0x80, 0xf1, 0x0f, 0x53, 0x6a, 0xb9, 0x8b, 0xcd, 0xf5, 0xfd, 0xd8, 0xf4, 0x38, - 0x26, 0x25, 0x23, 0x9d, 0x39, 0x1a, 0xa8, 0x15, 0xd8, 0xf6, 0x58, 0x7e, 0x39, 0x44, 0xe7, 0xb4, 0x2d, 0xb0, 0x4d, - 0xcb, 0xc7, 0x37, 0x87, 0x6c, 0x2e, 0x5f, 0x9a, 0xf1, 0x5e, 0xba, 0x79, 0xf2, 0x62, 0x99, 0xde, 0x0a, 0x7b, 0xc2, - 0x40, 0x14, 0x51, 0x05, 0x9d, 0x84, 0x22, 0xec, 0xb4, 0x5b, 0x7b, 0x82, 0x94, 0x16, 0x83, 0xf0, 0x13, 0x5c, 0x9f, - 0xb4, 0xaf, 0x45, 0x6d, 0x6a, 0x1d, 0x35, 0x41, 0xed, 0x72, 0x9e, 0x06, 0x48, 0x47, 0xc5, 0x73, 0x0b, 0xa1, 0xcf, - 0x28, 0xd0, 0x16, 0x34, 0x59, 0x29, 0xd2, 0x08, 0x43, 0x91, 0x73, 0x63, 0xaa, 0x26, 0x73, 0xb1, 0x5c, 0xf8, 0xb3, - 0x46, 0x9b, 0x34, 0xc4, 0x24, 0xe4, 0xda, 0x96, 0x5d, 0xe6, 0xeb, 0x04, 0xeb, 0x2b, 0x6b, 0x7f, 0x3d, 0xf9, 0x5b, - 0x41, 0x32, 0x05, 0xec, 0x47, 0x16, 0xaf, 0xdb, 0x97, 0xb8, 0x02, 0xde, 0xd4, 0x40, 0x51, 0x03, 0xca, 0xac, 0x3a, - 0xad, 0xdb, 0xf0, 0x80, 0x32, 0xfb, 0xcd, 0x40, 0x95, 0x9a, 0x5c, 0x59, 0xc5, 0xb7, 0xba, 0x8d, 0xb8, 0x5e, 0xb2, - 0x81, 0xb4, 0xf1, 0x76, 0xca, 0xad, 0xd3, 0x54, 0xb9, 0x12, 0xe7, 0x41, 0x25, 0xa9, 0x71, 0x0f, 0x30, 0x98, 0xe6, - 0xe9, 0x3b, 0x34, 0xe6, 0xdf, 0x8a, 0x83, 0x49, 0x5f, 0x18, 0x24, 0xab, 0xb4, 0x63, 0x01, 0x20, 0x40, 0xb7, 0x5d, - 0x72, 0xd3, 0xe4, 0x08, 0x46, 0xe4, 0x1f, 0xd0, 0xbb, 0xe0, 0x88, 0xec, 0x1d, 0xd8, 0x9d, 0xe9, 0xc3, 0xc0, 0xcc, - 0xbb, 0x9a, 0x92, 0x5d, 0x8a, 0xc2, 0x37, 0xd1, 0x37, 0xdb, 0xc5, 0x4a, 0x00, 0xdc, 0x30, 0xbb, 0xcc, 0x17, 0xaa, - 0x4c, 0xe6, 0x62, 0xab, 0xf2, 0x90, 0x9b, 0xa9, 0x4c, 0x71, 0x55, 0x13, 0x3c, 0x08, 0x82, 0x80, 0x82, 0xbc, 0x81, - 0x5c, 0xc7, 0x17, 0x0d, 0x20, 0xe8, 0x41, 0x58, 0x0c, 0x13, 0xcf, 0x8d, 0xb2, 0xbb, 0x3e, 0xaa, 0x98, 0xc2, 0xf8, - 0x54, 0x4a, 0x72, 0x72, 0xee, 0xf5, 0xc9, 0x64, 0xd8, 0x6a, 0x36, 0xec, 0xe4, 0x24, 0x21, 0xb4, 0x24, 0xb6, 0x90, - 0x53, 0xea, 0xf6, 0xae, 0x0e, 0xbd, 0x3c, 0x96, 0x05, 0x8c, 0xb6, 0x11, 0xac, 0x3b, 0x1c, 0xed, 0x3d, 0x25, 0xc2, - 0x8b, 0x65, 0x63, 0xbe, 0x13, 0xf1, 0x45, 0xaa, 0x8f, 0x81, 0x06, 0xcc, 0x9b, 0x3f, 0x07, 0xb2, 0x9a, 0xe0, 0x6f, - 0xc2, 0x8b, 0x65, 0x71, 0x9f, 0x39, 0x21, 0x2a, 0x36, 0x8b, 0xfb, 0x67, 0x1b, 0x14, 0x98, 0xae, 0x09, 0xdd, 0x40, - 0xaa, 0x81, 0x45, 0xc3, 0x1d, 0x3d, 0x58, 0xb4, 0x3f, 0xa2, 0xab, 0x62, 0x59, 0x61, 0xf4, 0xe8, 0xc1, 0x51, 0x3d, - 0x95, 0x1d, 0x4b, 0x6b, 0xa4, 0x39, 0xe2, 0x37, 0xcf, 0x11, 0x2d, 0xea, 0x36, 0xc6, 0x44, 0x63, 0x69, 0xe6, 0x1f, - 0x44, 0x79, 0xb4, 0xaf, 0x41, 0xd8, 0x3f, 0x83, 0x4d, 0xe2, 0x63, 0xc6, 0x20, 0x6f, 0x8e, 0x06, 0xf6, 0x72, 0x40, - 0x1d, 0x07, 0xcb, 0x93, 0x92, 0x82, 0x9b, 0x8b, 0x95, 0x2a, 0xcd, 0x32, 0x8a, 0x3d, 0xaf, 0x13, 0x59, 0xcb, 0x1e, - 0xe1, 0x24, 0x23, 0x26, 0xfa, 0x3c, 0x50, 0x90, 0x77, 0x5a, 0x2f, 0xff, 0xd3, 0x0a, 0xcc, 0x3a, 0x74, 0x32, 0xd6, - 0x64, 0x94, 0x2c, 0x84, 0x08, 0x6d, 0x08, 0xb7, 0x36, 0x24, 0xd7, 0x22, 0xb4, 0x1d, 0x99, 0x43, 0x1f, 0xe6, 0x4b, - 0xc1, 0x19, 0x5e, 0x82, 0x9e, 0x76, 0xb9, 0x7d, 0x71, 0xfa, 0xcd, 0x85, 0x72, 0x67, 0x83, 0x83, 0x08, 0xa4, 0xe8, - 0x5c, 0x9f, 0x1e, 0x8a, 0x17, 0x85, 0x83, 0x88, 0xb8, 0x39, 0xbc, 0x1e, 0xac, 0x3e, 0x26, 0x74, 0x56, 0x75, 0x4f, - 0x7b, 0xff, 0x85, 0x0b, 0xdf, 0xb5, 0xb5, 0x22, 0x8a, 0xd3, 0x1b, 0xb6, 0x1e, 0xa5, 0x79, 0x26, 0xad, 0x1e, 0xbb, - 0x62, 0xe0, 0x51, 0xa6, 0x22, 0xc7, 0x6f, 0xd6, 0x63, 0x8c, 0x6d, 0x08, 0x28, 0x43, 0xaa, 0xb7, 0x18, 0x02, 0x20, - 0x63, 0x9e, 0x8e, 0xfd, 0x71, 0xce, 0x26, 0xc8, 0x7b, 0x8d, 0x31, 0x17, 0xf1, 0x76, 0xed, 0x4f, 0xe0, 0xa1, 0x50, - 0x36, 0x12, 0xd7, 0xf2, 0x28, 0xc5, 0xb9, 0x07, 0x15, 0x9f, 0x46, 0xc4, 0xd6, 0x61, 0xea, 0x7c, 0x42, 0x18, 0xb2, - 0x07, 0x31, 0x66, 0x17, 0x26, 0x74, 0x7a, 0x89, 0xbe, 0x32, 0xbd, 0x0d, 0xa8, 0xbe, 0x15, 0x5b, 0x24, 0x9a, 0x97, - 0x44, 0xa2, 0xe8, 0xec, 0x84, 0xd8, 0x6c, 0x45, 0x8e, 0x1a, 0xab, 0xbd, 0x83, 0xc1, 0xe5, 0x33, 0x4e, 0x6b, 0xeb, - 0x0a, 0x30, 0xf9, 0x63, 0x98, 0x0a, 0x06, 0x9c, 0x1b, 0x4e, 0x2c, 0x79, 0x37, 0xa2, 0x1f, 0x7d, 0x20, 0xe3, 0xb7, - 0xd2, 0x22, 0xd8, 0xa3, 0x81, 0x18, 0xa9, 0x8a, 0x61, 0x05, 0xd3, 0x47, 0x21, 0xc1, 0x53, 0x17, 0x8e, 0xaa, 0x3a, - 0xf4, 0x0b, 0x22, 0xaa, 0x9d, 0x0b, 0xbb, 0x56, 0x0c, 0x98, 0x68, 0xcc, 0x1c, 0x1a, 0x2d, 0x5c, 0xc0, 0xf3, 0x74, - 0xfc, 0x7e, 0xe2, 0x7e, 0x76, 0xfe, 0xa0, 0x19, 0xf4, 0xbf, 0x26, 0xa3, 0xce, 0xf1, 0xd3, 0xfb, 0xdb, 0xf6, 0x69, - 0xbf, 0xb6, 0x33, 0xf7, 0x07, 0xea, 0xfb, 0x4f, 0xfc, 0xcb, 0x24, 0x80, 0xfc, 0x52, 0xc7, 0x6e, 0xc3, 0xf5, 0x53, - 0xe2, 0x35, 0x78, 0xb8, 0x7e, 0x72, 0x89, 0x50, 0xef, 0x00, 0xed, 0x8d, 0x4a, 0xdb, 0x86, 0x4b, 0x4c, 0xe2, 0x91, - 0xf2, 0x64, 0x35, 0x56, 0x64, 0x49, 0xad, 0x60, 0x65, 0x92, 0x6f, 0xe4, 0xae, 0xcf, 0x2e, 0xc1, 0x3d, 0xbe, 0x15, - 0xd9, 0x53, 0xae, 0x3e, 0x00, 0x17, 0xa5, 0xf3, 0x57, 0xcc, 0x3b, 0xff, 0x13, 0x55, 0xd6, 0x1d, 0xd4, 0x0c, 0xb5, - 0x96, 0x44, 0xad, 0x9a, 0x59, 0x5d, 0xb0, 0xb7, 0x04, 0xb4, 0xa6, 0x56, 0x1f, 0xca, 0xcd, 0x21, 0x7f, 0x6c, 0xb1, - 0x2e, 0x8c, 0x13, 0x4d, 0x93, 0x01, 0x79, 0x6a, 0x7e, 0xe9, 0x12, 0x43, 0x92, 0x41, 0xfd, 0xbf, 0xbe, 0x7b, 0x77, - 0x74, 0xd0, 0x4c, 0x5a, 0xde, 0x85, 0x3d, 0xde, 0xab, 0xa2, 0x62, 0x49, 0xe7, 0x1b, 0x7d, 0x7c, 0x90, 0x3c, 0xc9, - 0xc3, 0xf6, 0x79, 0xea, 0xcf, 0x0e, 0xfc, 0xd8, 0x80, 0xbe, 0xe3, 0x6d, 0xd3, 0x8e, 0xd2, 0xc7, 0x21, 0x04, 0x2c, - 0xd5, 0x2e, 0x68, 0x56, 0xc3, 0x23, 0x34, 0x58, 0xb7, 0x49, 0x55, 0x38, 0x8a, 0xa7, 0x1c, 0x1f, 0xfe, 0x03, 0xd0, - 0x41, 0x02, 0x3c, 0x6a, 0x2e, 0xcb, 0xc3, 0xb4, 0x03, 0x6b, 0x23, 0x6c, 0xf7, 0x26, 0x44, 0x2f, 0x16, 0x47, 0x6b, - 0xa7, 0x36, 0x61, 0x11, 0x69, 0xbc, 0x2b, 0x09, 0x5d, 0xdd, 0x07, 0xbd, 0x1e, 0x75, 0x9a, 0x35, 0x09, 0xa1, 0x9d, - 0x6c, 0xeb, 0xb8, 0x7a, 0xd0, 0xab, 0xac, 0xcf, 0x5f, 0x30, 0xfd, 0x58, 0xdf, 0xe3, 0x23, 0x86, 0xf5, 0x1b, 0xde, - 0x1f, 0x5c, 0x4a, 0x70, 0xb1, 0x69, 0xec, 0x7c, 0x33, 0x27, 0x0e, 0xbb, 0x59, 0x0a, 0x0b, 0x09, 0xa6, 0x97, 0x48, - 0x1b, 0xc6, 0x6a, 0x70, 0x7c, 0x11, 0x1f, 0xeb, 0xf9, 0x62, 0x40, 0x20, 0x52, 0xd9, 0x29, 0xf2, 0xc2, 0x00, 0x13, - 0xf5, 0xed, 0xcd, 0x87, 0xd4, 0xff, 0x10, 0xdf, 0xec, 0x03, 0xa9, 0x93, 0xe4, 0xd1, 0x8b, 0x45, 0x51, 0x24, 0x54, - 0xf4, 0x14, 0xff, 0xe2, 0x10, 0xca, 0xf0, 0x32, 0xd1, 0xd9, 0xa4, 0xe8, 0xf6, 0xce, 0x2d, 0x5f, 0x24, 0xbc, 0x71, - 0xe5, 0x72, 0xe9, 0x61, 0x60, 0xda, 0x02, 0x36, 0x50, 0x41, 0xc6, 0x31, 0x4b, 0xf1, 0x63, 0xe4, 0x2a, 0x43, 0x94, - 0xdd, 0xea, 0x31, 0xd4, 0x70, 0x11, 0x98, 0x3b, 0x94, 0x49, 0xc2, 0x68, 0xa1, 0x9e, 0xdb, 0xc0, 0xd3, 0x73, 0x66, - 0xe7, 0xe9, 0xdc, 0xde, 0xab, 0x62, 0xc7, 0x84, 0x89, 0x0c, 0x8a, 0xe8, 0xb1, 0xc2, 0x86, 0x5a, 0xcd, 0x97, 0x99, - 0x53, 0x6c, 0x7a, 0xe4, 0x0f, 0x43, 0x2d, 0x37, 0xe9, 0x96, 0x1d, 0xbd, 0xd2, 0x47, 0xfd, 0xd1, 0xa2, 0x13, 0x0c, - 0xd1, 0xe2, 0xee, 0xac, 0x8d, 0x72, 0xc4, 0x28, 0x6c, 0xde, 0x17, 0x80, 0xd9, 0xb7, 0x6e, 0x4b, 0xba, 0xfa, 0xc4, - 0xd5, 0xf7, 0xc2, 0xdc, 0xf3, 0x00, 0x62, 0x24, 0xcf, 0xe5, 0xc8, 0x45, 0x91, 0x03, 0x92, 0xbc, 0xab, 0x23, 0x2d, - 0x91, 0x8a, 0x10, 0x4e, 0x67, 0x1c, 0x0c, 0x8b, 0xd3, 0xb9, 0x6a, 0xea, 0xbb, 0x2c, 0x10, 0x09, 0x65, 0xb2, 0x9f, - 0xa2, 0x67, 0x7b, 0xa3, 0x71, 0x47, 0x87, 0xb5, 0x76, 0xeb, 0x20, 0x14, 0xae, 0x4c, 0xb5, 0x99, 0x70, 0xf7, 0x8c, - 0xfe, 0xeb, 0x8d, 0x97, 0x14, 0xab, 0x8e, 0x7b, 0xef, 0x53, 0x7d, 0xf9, 0x6b, 0x5e, 0x00, 0xf5, 0xfb, 0x81, 0xb3, - 0x21, 0x7f, 0xcb, 0x7d, 0xb0, 0x98, 0x32, 0x40, 0x80, 0x8f, 0x68, 0x86, 0x3a, 0xed, 0xab, 0xd9, 0x8d, 0x6f, 0x88, - 0xd9, 0xb3, 0xda, 0xd0, 0x77, 0x7e, 0xf8, 0xae, 0xae, 0xa0, 0xc1, 0x45, 0x65, 0xf4, 0x7f, 0x9e, 0x2a, 0x20, 0x98, - 0x0a, 0xfe, 0x3e, 0x6e, 0x87, 0xe3, 0x5b, 0xf0, 0x1c, 0x46, 0x7d, 0x1c, 0x69, 0xa2, 0x7b, 0x27, 0xee, 0x52, 0xaf, - 0x32, 0x4d, 0x32, 0xaf, 0x68, 0x97, 0x35, 0x2e, 0x58, 0xd6, 0x35, 0x5d, 0x5b, 0x76, 0xb0, 0x66, 0x5f, 0x02, 0x20, - 0x23, 0xdb, 0x9b, 0xaa, 0xa6, 0xf0, 0xeb, 0x4b, 0xb1, 0x08, 0x24, 0xf0, 0x9d, 0xb2, 0xbf, 0xba, 0x76, 0x7d, 0xd3, - 0xae, 0x16, 0xf1, 0xc1, 0xc0, 0x81, 0x50, 0xae, 0xf3, 0x86, 0x7b, 0x59, 0xa1, 0xcd, 0xf3, 0x25, 0xe7, 0xc6, 0xcb, - 0x88, 0x4a, 0x43, 0x21, 0x89, 0xda, 0x40, 0x9f, 0x8e, 0x3d, 0x0d, 0x10, 0x1e, 0x12, 0x4b, 0x1d, 0x64, 0x65, 0xfa, - 0x47, 0xd2, 0xde, 0x9b, 0x1b, 0xc3, 0xeb, 0xe1, 0x16, 0x97, 0x19, 0x45, 0x14, 0x76, 0x0c, 0x3c, 0x72, 0x2b, 0x56, - 0x7b, 0xb7, 0xfe, 0xe1, 0xc1, 0xd3, 0xbb, 0xab, 0x8f, 0x9f, 0x16, 0xb7, 0x43, 0xaa, 0xd5, 0x4f, 0xa7, 0xd6, 0xb2, - 0xe6, 0x93, 0x76, 0x98, 0xf7, 0x8e, 0x15, 0xbb, 0x84, 0x13, 0x69, 0x07, 0x31, 0x56, 0x6e, 0x26, 0x55, 0xa7, 0x09, - 0x70, 0x20, 0x35, 0x75, 0x9f, 0x3d, 0x73, 0xcd, 0x94, 0x3c, 0x36, 0xe8, 0x25, 0x51, 0x57, 0xa5, 0x11, 0x58, 0xa6, - 0xfd, 0xe3, 0xf1, 0xd2, 0x4b, 0x3d, 0x4d, 0xb0, 0x89, 0x6e, 0x18, 0x88, 0xc3, 0xdf, 0xb1, 0xc1, 0xaf, 0x67, 0xf7, - 0x64, 0x49, 0xa0, 0x70, 0x69, 0xeb, 0x86, 0x32, 0x0d, 0xda, 0x52, 0x21, 0x38, 0x2e, 0x5e, 0xdc, 0x2a, 0xc6, 0x93, - 0xac, 0xa9, 0x16, 0xc5, 0x43, 0x24, 0x1a, 0x70, 0x19, 0x5b, 0xca, 0x4d, 0xbe, 0x8d, 0x01, 0x0e, 0xd2, 0x11, 0xca, - 0xf5, 0xb2, 0x0a, 0xb0, 0xdb, 0xf0, 0xd7, 0xe3, 0x69, 0x1e, 0x80, 0x98, 0x1e, 0x1b, 0xf6, 0x74, 0x6f, 0xa3, 0xc9, - 0xad, 0xb9, 0x93, 0x12, 0x3f, 0x4a, 0xd9, 0x62, 0x4b, 0x0c, 0x83, 0x73, 0xa5, 0x13, 0x20, 0xa0, 0xe5, 0x6e, 0x09, - 0x20, 0xb5, 0x2c, 0x39, 0x89, 0x83, 0x85, 0x13, 0xd9, 0xde, 0x62, 0xbc, 0xdd, 0x93, 0x9e, 0x1a, 0xcf, 0xdc, 0x46, - 0xc6, 0xa4, 0xac, 0x7c, 0xbf, 0x20, 0x93, 0xf7, 0x79, 0x06, 0x16, 0xcd, 0x65, 0xf4, 0xf4, 0x5d, 0x71, 0x2a, 0x7e, - 0x98, 0x45, 0xe7, 0xe1, 0x69, 0xd4, 0xcd, 0x61, 0x96, 0x78, 0xc0, 0x4e, 0x38, 0xd3, 0x6a, 0x60, 0xac, 0x5d, 0xda, - 0x8e, 0xb4, 0x3b, 0xfb, 0x02, 0x29, 0x61, 0xcd, 0x6e, 0x76, 0x82, 0x63, 0x46, 0x5c, 0x0e, 0xba, 0xd7, 0x1b, 0x30, - 0xac, 0x6c, 0x17, 0x73, 0x73, 0x4f, 0xee, 0xa4, 0xd5, 0x53, 0x81, 0x9c, 0x81, 0x2c, 0x59, 0xd7, 0xf0, 0xbe, 0x40, - 0xb5, 0xbe, 0x78, 0x70, 0xf0, 0x76, 0x6f, 0x19, 0x77, 0x4d, 0x19, 0x65, 0x3b, 0xa2, 0x08, 0x7e, 0x65, 0x40, 0xba, - 0x56, 0xf6, 0x23, 0x77, 0x37, 0x4b, 0x1d, 0xa4, 0x14, 0xfa, 0x74, 0x3d, 0x5d, 0x1b, 0x09, 0x6f, 0x66, 0xaa, 0xe3, - 0x08, 0xf9, 0x44, 0x87, 0x41, 0x59, 0x49, 0x8a, 0xfe, 0x9f, 0xb1, 0xdf, 0x81, 0x82, 0x7a, 0xe0, 0xd7, 0xbf, 0x0b, - 0x12, 0x1c, 0xd8, 0x9d, 0xa0, 0xb5, 0xe2, 0x63, 0x09, 0xb2, 0x5b, 0x85, 0xb9, 0xa0, 0x44, 0xad, 0x7f, 0xcf, 0xcd, - 0xf5, 0xfa, 0xfb, 0x4b, 0x56, 0xaa, 0x75, 0x27, 0xdb, 0xb6, 0xf5, 0x4d, 0xae, 0x19, 0x3b, 0x62, 0x5f, 0x0e, 0x7c, - 0x70, 0x9a, 0xc9, 0xb5, 0x80, 0xa4, 0x21, 0xd3, 0xe7, 0x6e, 0x8d, 0xba, 0x91, 0x8c, 0xdc, 0x01, 0x09, 0x44, 0x08, - 0x34, 0x18, 0x94, 0x75, 0xbb, 0x2f, 0xc6, 0xe1, 0xbc, 0xb3, 0x78, 0xff, 0x73, 0x41, 0x97, 0xe8, 0xb0, 0xae, 0xce, - 0x62, 0xc9, 0x7f, 0xbf, 0x53, 0x8c, 0x64, 0x7b, 0xb4, 0xbd, 0x7f, 0x31, 0x9a, 0xe2, 0x4a, 0xa6, 0xfd, 0x83, 0xbf, - 0xbf, 0xe8, 0x2d, 0xbc, 0xd9, 0xd1, 0xc1, 0xea, 0x3e, 0x4f, 0xb9, 0x79, 0xd2, 0x17, 0x33, 0xf9, 0xae, 0x8c, 0x4c, - 0x6e, 0x10, 0x18, 0x75, 0x67, 0x75, 0xa9, 0xcb, 0xc3, 0xc8, 0xc5, 0x7a, 0xb8, 0x19, 0x4e, 0xe1, 0x36, 0x13, 0x59, - 0xb5, 0x50, 0x05, 0xe0, 0x11, 0x3a, 0x29, 0x51, 0x24, 0x49, 0x62, 0x80, 0xe8, 0xde, 0xc6, 0x3c, 0x80, 0x17, 0x35, - 0x9f, 0x35, 0xd4, 0x76, 0x46, 0x36, 0xc7, 0x01, 0xad, 0xcd, 0x1c, 0xd3, 0xb2, 0x29, 0x41, 0xe7, 0xee, 0x74, 0x84, - 0x0e, 0xbd, 0xa5, 0xf5, 0x54, 0x97, 0x8a, 0x7d, 0xd3, 0xb3, 0xb6, 0x8e, 0xc8, 0x27, 0x71, 0x6b, 0x75, 0x90, 0xe6, - 0x2a, 0xa7, 0xe2, 0x66, 0xaa, 0x9e, 0xa3, 0x77, 0x16, 0x8e, 0x40, 0xdf, 0x5a, 0x1e, 0xac, 0x71, 0x11, 0x6c, 0x8a, - 0xee, 0x2c, 0x15, 0x55, 0xc5, 0x96, 0xfb, 0x9d, 0x4c, 0xa7, 0xed, 0x9d, 0x01, 0xb2, 0x4e, 0x98, 0xee, 0x1e, 0x12, - 0x48, 0x3c, 0x7a, 0x17, 0x60, 0xb0, 0x67, 0x52, 0x4c, 0xab, 0xea, 0xbc, 0x62, 0x82, 0x87, 0xa5, 0x3c, 0xf3, 0xbd, - 0xd9, 0xb3, 0xc3, 0xa8, 0x61, 0x3c, 0x76, 0xf8, 0x05, 0x25, 0x05, 0xb3, 0x37, 0xd1, 0xcd, 0xdf, 0xcb, 0xd7, 0xf5, - 0x09, 0xb7, 0x46, 0x0e, 0xb9, 0x75, 0x07, 0xd7, 0xef, 0xf4, 0x7d, 0xe6, 0x62, 0x56, 0xdf, 0x7e, 0x36, 0x2e, 0x66, - 0x46, 0xc9, 0x77, 0x6a, 0xa4, 0x3d, 0x24, 0xde, 0x6b, 0x00, 0xb6, 0x00, 0xca, 0x92, 0x09, 0xe8, 0x60, 0xb5, 0x2e, - 0x97, 0x4e, 0xd7, 0x29, 0x69, 0xaa, 0x3d, 0xf3, 0x6a, 0xbb, 0xb1, 0xcd, 0x85, 0x67, 0x4c, 0xb6, 0x58, 0x9b, 0x4e, - 0x5b, 0xc2, 0xe4, 0xb5, 0xae, 0xdf, 0xe8, 0xfa, 0x97, 0x15, 0x81, 0x9a, 0xa9, 0x5c, 0x71, 0x5f, 0x2b, 0x6b, 0x08, - 0x3e, 0x85, 0x45, 0x98, 0x0a, 0xf0, 0xac, 0x3a, 0x81, 0xaa, 0xf5, 0x43, 0xdb, 0xfb, 0x1b, 0x16, 0xdb, 0xb3, 0x9d, - 0x76, 0x01, 0x14, 0x9e, 0x25, 0xee, 0x9c, 0x2b, 0x77, 0x74, 0xe3, 0x74, 0x13, 0x53, 0xf6, 0xe3, 0x17, 0xa8, 0x93, - 0x83, 0x99, 0xdb, 0x0b, 0x1a, 0x4b, 0xc0, 0x93, 0x22, 0x13, 0xc4, 0xe4, 0xe7, 0x40, 0x08, 0x6d, 0xa4, 0xd2, 0x99, - 0x86, 0xc7, 0x68, 0xf7, 0x5a, 0x29, 0x0b, 0xa6, 0x76, 0xef, 0xc9, 0x6d, 0xd8, 0x74, 0x04, 0xaa, 0xb3, 0xef, 0xa4, - 0xdc, 0xa8, 0x97, 0x30, 0x02, 0x3a, 0xdd, 0x6b, 0xf5, 0xe3, 0x9f, 0x93, 0xb9, 0x86, 0x7d, 0x64, 0xc7, 0x1b, 0xd1, - 0x0d, 0x40, 0x0e, 0x87, 0x4b, 0x28, 0x65, 0xed, 0x93, 0xea, 0xdf, 0xfb, 0xb2, 0xd1, 0xf0, 0x09, 0xc3, 0x38, 0x49, - 0x54, 0x71, 0xda, 0xe6, 0xd6, 0x40, 0xe9, 0x4f, 0xee, 0x9d, 0x12, 0xa6, 0x20, 0x10, 0x4d, 0xb2, 0x72, 0x3e, 0x05, - 0x2c, 0x3c, 0xe5, 0x81, 0x4a, 0x98, 0x46, 0x2c, 0xd1, 0x0e, 0xad, 0x34, 0x1b, 0x5d, 0x82, 0x19, 0x06, 0x5c, 0xfb, - 0x0b, 0x8d, 0xd6, 0x9d, 0xec, 0xad, 0xa3, 0x06, 0x6f, 0xd0, 0xd2, 0xe8, 0x77, 0x43, 0x93, 0x00, 0x84, 0x9c, 0x1e, - 0xdc, 0xf7, 0x2c, 0x46, 0xc7, 0x15, 0x9d, 0x47, 0x0f, 0x64, 0x22, 0xd4, 0x94, 0xeb, 0x4e, 0x0e, 0x80, 0x39, 0xdd, - 0x72, 0x69, 0xa8, 0xc7, 0x60, 0x9a, 0x5e, 0x40, 0x54, 0xc0, 0x8a, 0x0e, 0xa0, 0xd3, 0xd8, 0x0d, 0x65, 0x79, 0xc3, - 0x0c, 0x05, 0x08, 0x82, 0xec, 0x1b, 0x84, 0xfd, 0xa9, 0x3a, 0xe6, 0x6a, 0x86, 0x5d, 0x86, 0x19, 0x1c, 0x87, 0x86, - 0xf6, 0x14, 0xfc, 0x04, 0x6c, 0xa2, 0x09, 0x08, 0x50, 0x6e, 0x12, 0x62, 0x0f, 0x6a, 0xfe, 0x2b, 0x0f, 0x49, 0x7b, - 0xdd, 0x34, 0xf5, 0x09, 0xa6, 0x38, 0x2c, 0x83, 0x75, 0x5b, 0xb6, 0x57, 0xb7, 0xaa, 0x8c, 0xe3, 0x1a, 0x60, 0x6c, - 0xe9, 0x1c, 0x47, 0x61, 0x1a, 0xe2, 0x7f, 0x0d, 0xa8, 0x0b, 0x73, 0xab, 0x76, 0x13, 0xfa, 0x66, 0x49, 0x53, 0x3e, - 0x9a, 0xdc, 0x1f, 0x1b, 0x9a, 0x13, 0xfd, 0xbe, 0xc0, 0x8c, 0x6b, 0x89, 0x4b, 0x16, 0x7a, 0xda, 0x06, 0x65, 0xa7, - 0x6b, 0x5c, 0x65, 0xfc, 0x6a, 0xf4, 0xcb, 0xb7, 0xab, 0x57, 0x31, 0xc4, 0x8c, 0x28, 0x60, 0x6b, 0xde, 0x59, 0xc7, - 0x27, 0xda, 0x7d, 0x37, 0xe6, 0x97, 0xa7, 0xa8, 0x71, 0xa3, 0x94, 0x58, 0x2c, 0x92, 0xf7, 0x15, 0x6e, 0x6b, 0x3e, - 0xd8, 0x5e, 0xf9, 0xf8, 0xeb, 0x79, 0x28, 0x04, 0x4f, 0xa8, 0x92, 0x20, 0xd1, 0x40, 0x37, 0xad, 0xd7, 0x82, 0x96, - 0xde, 0x97, 0x94, 0x66, 0x9e, 0xfb, 0xcb, 0xa6, 0x5d, 0x02, 0x42, 0x55, 0x03, 0x39, 0x3f, 0x45, 0x93, 0x2f, 0xa6, - 0xd3, 0x31, 0x82, 0x4f, 0x9a, 0x9c, 0x23, 0x0c, 0xa7, 0xdd, 0x7e, 0x97, 0x9f, 0xfe, 0x26, 0x47, 0x07, 0x9e, 0xfb, - 0x49, 0xea, 0xdb, 0xa1, 0xf0, 0xe9, 0x77, 0xbd, 0x18, 0x7d, 0xf5, 0x8d, 0x90, 0xbe, 0xed, 0xc4, 0xc6, 0x41, 0x90, - 0x37, 0xf2, 0x42, 0x84, 0x08, 0x76, 0x49, 0x20, 0xcc, 0x65, 0xfd, 0x46, 0xbc, 0x85, 0xaf, 0xe8, 0x2d, 0x35, 0x47, - 0x4f, 0xa3, 0x03, 0x3d, 0x9c, 0xb0, 0xbe, 0x8b, 0x0f, 0xa3, 0x2f, 0xb0, 0xe6, 0xe1, 0xb3, 0x00, 0x90, 0x8e, 0x61, - 0x15, 0xc0, 0xda, 0x60, 0xee, 0x18, 0x6e, 0xeb, 0xf4, 0xc4, 0x5a, 0xe6, 0x00, 0xbb, 0xdc, 0xc9, 0x71, 0x43, 0x77, - 0x0e, 0x41, 0xc1, 0xbc, 0x1d, 0x58, 0x23, 0xff, 0xcf, 0xb4, 0xa1, 0x3b, 0xab, 0x98, 0x58, 0x06, 0x22, 0xcd, 0x11, - 0x09, 0x0d, 0x5f, 0x77, 0x2f, 0x02, 0x07, 0xf0, 0x11, 0x83, 0xaf, 0x41, 0xc5, 0xf3, 0xdc, 0xe4, 0x57, 0xf5, 0xf3, - 0x4b, 0xc4, 0xde, 0x14, 0xaf, 0xeb, 0xa9, 0xbb, 0x2b, 0x0f, 0x7f, 0xa7, 0x14, 0x00, 0xbd, 0x54, 0x76, 0x15, 0x98, - 0xc9, 0xc1, 0x26, 0x32, 0xfc, 0x5c, 0x2f, 0xa1, 0x32, 0x6d, 0xf6, 0x84, 0x10, 0x2e, 0x48, 0x39, 0xb9, 0x1e, 0x2f, - 0x46, 0x7e, 0x02, 0x2a, 0x02, 0x6d, 0x02, 0xc8, 0xb2, 0x3f, 0x82, 0x45, 0xca, 0x01, 0x81, 0x78, 0x17, 0x17, 0x7d, - 0xea, 0x2d, 0x0d, 0x92, 0x98, 0xdd, 0x4b, 0x11, 0x30, 0x88, 0xcb, 0x84, 0x12, 0x34, 0x6c, 0x4d, 0xd9, 0xb7, 0x10, - 0xb9, 0x23, 0x74, 0xd8, 0x11, 0x66, 0x06, 0x5d, 0x25, 0xf2, 0x1f, 0x1d, 0x2d, 0xa9, 0x82, 0x87, 0xe9, 0xc9, 0xb3, - 0x15, 0xcd, 0x86, 0x93, 0x06, 0x12, 0x12, 0xf8, 0x50, 0x88, 0x03, 0x1b, 0x6f, 0x48, 0xa2, 0x60, 0x3d, 0x48, 0xfe, - 0x74, 0xd9, 0xf2, 0xba, 0xf3, 0x2c, 0x3b, 0xbe, 0x63, 0x68, 0x0e, 0x79, 0x8c, 0x44, 0x11, 0x94, 0xc2, 0xef, 0xa0, - 0xa4, 0x45, 0xa6, 0x12, 0x50, 0xae, 0x15, 0xd9, 0xe1, 0xa9, 0x2a, 0x31, 0x01, 0x5a, 0xa0, 0x07, 0xd1, 0xbd, 0xcb, - 0x42, 0xd3, 0x74, 0xf0, 0xda, 0xa1, 0x61, 0x2c, 0x83, 0xa9, 0x0e, 0x2e, 0x5b, 0xa1, 0x38, 0x32, 0xe9, 0x90, 0x51, - 0x70, 0x72, 0xeb, 0xac, 0xcb, 0x26, 0x37, 0xbf, 0xbd, 0x57, 0x74, 0x74, 0x0c, 0x64, 0x75, 0x9e, 0xde, 0x3c, 0xcf, - 0x66, 0x08, 0x06, 0xe9, 0xe3, 0x69, 0x57, 0xf1, 0x72, 0x9a, 0x81, 0x69, 0xd5, 0xf6, 0x6d, 0x19, 0x2e, 0x37, 0xb1, - 0xe4, 0xaa, 0xdb, 0x87, 0xb9, 0xcc, 0x67, 0xa7, 0x93, 0xec, 0xb7, 0xd6, 0xe0, 0xc8, 0x69, 0x66, 0xfd, 0x46, 0xf9, - 0x3c, 0x3f, 0x32, 0x95, 0x6f, 0x0e, 0x93, 0x44, 0x6a, 0xd7, 0x50, 0xad, 0xc2, 0x0c, 0x3f, 0x19, 0x44, 0xbd, 0x06, - 0x54, 0x1b, 0xad, 0x18, 0x6e, 0xe0, 0xc5, 0xe6, 0xc9, 0xd2, 0x75, 0xcc, 0x8c, 0xab, 0xc0, 0x2c, 0x26, 0x95, 0x18, - 0xdf, 0x8b, 0x04, 0x19, 0xb4, 0xa7, 0xfb, 0x54, 0x34, 0xd6, 0x97, 0x40, 0x27, 0x8b, 0x68, 0x03, 0x06, 0xe6, 0x10, - 0xea, 0x58, 0xa0, 0xb1, 0x71, 0x98, 0x45, 0x6d, 0x2b, 0x33, 0x9a, 0x2a, 0x83, 0x61, 0x0c, 0xb5, 0x01, 0x5c, 0xdd, - 0xaa, 0x85, 0x94, 0x8c, 0xb2, 0xee, 0x32, 0x1a, 0x28, 0xa1, 0x63, 0x19, 0x2b, 0x3c, 0x52, 0x32, 0x5c, 0x19, 0x71, - 0x1a, 0xe0, 0xcb, 0xd3, 0xff, 0xf7, 0x27, 0x32, 0x6a, 0xe9, 0xee, 0x48, 0xde, 0xb9, 0xec, 0xe8, 0x4a, 0x33, 0x9e, - 0xa7, 0xcb, 0xe9, 0x8b, 0xd4, 0x6d, 0xa9, 0x96, 0xf9, 0xc3, 0xe8, 0x18, 0x85, 0xaf, 0xed, 0xdb, 0x6d, 0x25, 0x1a, - 0xce, 0x30, 0x62, 0xae, 0x7c, 0xe3, 0x16, 0xf5, 0x5a, 0x8a, 0xee, 0xb7, 0x8c, 0x9c, 0x4a, 0x75, 0xc7, 0x1b, 0x97, - 0x1a, 0x5e, 0x29, 0xfd, 0x87, 0x79, 0x5e, 0xcc, 0xb1, 0xdd, 0xf6, 0x71, 0xb5, 0xb2, 0xcb, 0x89, 0xce, 0x9b, 0xe7, - 0x24, 0xe1, 0x6d, 0x8f, 0x63, 0x2b, 0x91, 0xe2, 0xb1, 0x34, 0x7f, 0x57, 0x4d, 0xb6, 0x9b, 0x5f, 0x7d, 0x2e, 0xc8, - 0x5a, 0x4c, 0xba, 0xd5, 0x56, 0xa5, 0x35, 0xf3, 0xe0, 0xdd, 0x9e, 0x39, 0xd2, 0x53, 0x12, 0x34, 0xdc, 0x2e, 0xe4, - 0xd3, 0x20, 0xd2, 0x5b, 0x66, 0x74, 0x58, 0x93, 0x57, 0xbe, 0xb1, 0x09, 0x0e, 0xe1, 0x78, 0x6b, 0x34, 0x0f, 0x93, - 0x9d, 0x4e, 0xea, 0xc5, 0xff, 0x33, 0x5b, 0xf8, 0x36, 0x75, 0xf2, 0x57, 0x5c, 0xe9, 0x20, 0xc5, 0xc5, 0x14, 0x1f, - 0x8e, 0x11, 0xcc, 0x97, 0xf4, 0x1d, 0x0a, 0x8f, 0xa6, 0x9c, 0x06, 0x06, 0x21, 0x66, 0xcf, 0xbe, 0x73, 0xf7, 0x76, - 0xbc, 0x25, 0xce, 0xa8, 0x2c, 0x6b, 0x8a, 0x25, 0x18, 0xa4, 0x79, 0x1d, 0x10, 0x00, 0x57, 0x2e, 0x88, 0x5d, 0x81, - 0xc8, 0x96, 0x17, 0xd1, 0xe2, 0xdd, 0x2f, 0x4b, 0xa3, 0xb8, 0x29, 0xf1, 0x99, 0xec, 0xf6, 0x44, 0x30, 0xc0, 0x2d, - 0xc8, 0x0e, 0xc7, 0x0e, 0x16, 0xc4, 0x1c, 0x09, 0xde, 0x15, 0x65, 0x58, 0x92, 0x3a, 0x50, 0x2c, 0x5a, 0xd4, 0x05, - 0x13, 0x13, 0x29, 0x64, 0x6b, 0xab, 0x84, 0x00, 0x69, 0xa2, 0xf6, 0x12, 0x58, 0xd4, 0x34, 0x7b, 0xa2, 0xea, 0x62, - 0x92, 0xbb, 0x21, 0xf7, 0x34, 0x1e, 0xfc, 0x3c, 0x94, 0xcc, 0xb1, 0x37, 0x89, 0x90, 0x7f, 0xbd, 0xd9, 0xfa, 0x05, - 0xf6, 0x0e, 0x7e, 0xd1, 0x10, 0xbe, 0x9a, 0xc2, 0x1a, 0x92, 0x30, 0xab, 0x5c, 0x78, 0xab, 0x24, 0x40, 0x81, 0xb2, - 0xac, 0x4f, 0x8b, 0x03, 0x46, 0x1f, 0x0a, 0xca, 0x16, 0xcb, 0x39, 0x89, 0xd9, 0x71, 0x11, 0x5b, 0x72, 0x2f, 0xfa, - 0xfc, 0xfc, 0x65, 0x1c, 0xef, 0x11, 0x81, 0xca, 0xad, 0xf2, 0xfe, 0x48, 0xc9, 0x01, 0x03, 0x33, 0xfd, 0x29, 0x8d, - 0xe8, 0xdc, 0x7f, 0x3f, 0xd5, 0x0f, 0x39, 0xf0, 0x4b, 0xe0, 0x38, 0xd0, 0xa7, 0x2c, 0x5a, 0xce, 0x06, 0xaa, 0x7b, - 0x9c, 0x53, 0xfb, 0x58, 0x5c, 0x22, 0xae, 0x4c, 0x42, 0xa0, 0xbb, 0x5c, 0x48, 0x82, 0xc5, 0xa7, 0x60, 0x48, 0x36, - 0x01, 0xd3, 0x58, 0x61, 0x73, 0xad, 0x79, 0x77, 0x80, 0x2e, 0x36, 0x58, 0xc1, 0x2b, 0x1c, 0x0c, 0xbd, 0xb6, 0x66, - 0x4e, 0x6b, 0x35, 0xbd, 0x13, 0x25, 0x89, 0x6c, 0xb2, 0xdb, 0x8f, 0x23, 0x7b, 0x43, 0x1a, 0x22, 0xfc, 0xb9, 0x51, - 0x5a, 0x14, 0x8a, 0xe6, 0x6a, 0x85, 0x88, 0x7d, 0xaf, 0x52, 0x4e, 0x32, 0xa9, 0x5a, 0x6a, 0x72, 0x5b, 0x29, 0x21, - 0xd6, 0x85, 0x7f, 0x14, 0xd4, 0xcd, 0xa8, 0x3f, 0x25, 0x37, 0xd0, 0x37, 0xe2, 0x4d, 0x02, 0x6f, 0xac, 0xf5, 0x21, - 0x28, 0x9a, 0x68, 0xfc, 0x08, 0x8a, 0xc5, 0xc1, 0x04, 0x4f, 0x3c, 0x97, 0x61, 0x09, 0x48, 0xa7, 0x78, 0xe8, 0xc5, - 0x84, 0x8b, 0x40, 0x0b, 0xce, 0x59, 0xbe, 0x7b, 0xa7, 0x79, 0xa0, 0xd3, 0x7a, 0x21, 0x89, 0xd9, 0x5e, 0x75, 0xba, - 0xf4, 0x8a, 0x81, 0xf3, 0xeb, 0x4c, 0x59, 0x22, 0xee, 0x49, 0x5e, 0x6e, 0x37, 0x96, 0xd1, 0xc6, 0x22, 0xe6, 0x74, - 0xa6, 0x82, 0x3f, 0x9b, 0x7a, 0x5b, 0x27, 0x16, 0xbf, 0x1d, 0x4f, 0xad, 0x8c, 0xd7, 0x01, 0xee, 0x12, 0x6f, 0xca, - 0xa0, 0x54, 0xc4, 0xeb, 0x41, 0x84, 0x48, 0x90, 0x12, 0x9d, 0x46, 0x86, 0xd2, 0x63, 0x3f, 0x48, 0xcc, 0x06, 0xd4, - 0x88, 0x1d, 0xd8, 0x39, 0xca, 0x6e, 0x85, 0x9f, 0xfb, 0xbb, 0xf5, 0xf0, 0x7b, 0x95, 0x3e, 0xe9, 0x2d, 0xcc, 0x4a, - 0xf3, 0xa4, 0x1a, 0x56, 0x60, 0xd9, 0x71, 0xfb, 0x97, 0x67, 0xae, 0xc2, 0xe0, 0xdc, 0x56, 0xc3, 0x9d, 0x3e, 0x97, - 0xef, 0x2f, 0xe0, 0xef, 0x4f, 0xbf, 0xaf, 0xf9, 0x02, 0xb3, 0x8e, 0x94, 0x50, 0xd7, 0x6e, 0x23, 0x22, 0xee, 0xc5, - 0xab, 0xab, 0x14, 0x5a, 0x80, 0x2c, 0xbf, 0x80, 0x67, 0xc7, 0xb7, 0x46, 0xba, 0x4f, 0x8e, 0x54, 0x20, 0x11, 0xf2, - 0x56, 0x41, 0x58, 0x09, 0x38, 0x52, 0xd8, 0x2c, 0xb2, 0xa0, 0x4f, 0x25, 0x74, 0x0d, 0x3f, 0x25, 0xbe, 0xbc, 0x9a, - 0x2b, 0x7e, 0x0c, 0xe9, 0x04, 0x74, 0xd8, 0x9d, 0x0f, 0x22, 0xb0, 0x41, 0xce, 0x7a, 0xc9, 0x68, 0xde, 0xc9, 0x67, - 0xa3, 0xc8, 0xb4, 0x63, 0xa5, 0xfd, 0xda, 0xa8, 0xdb, 0x3e, 0x1e, 0xdf, 0x29, 0x06, 0x3c, 0x38, 0x6c, 0x6e, 0x37, - 0x69, 0x20, 0x6f, 0xd5, 0xde, 0xfb, 0x7a, 0xc7, 0xb5, 0x5d, 0x90, 0x7c, 0xb2, 0xb4, 0x83, 0x28, 0xa4, 0xdb, 0x8d, - 0x9c, 0x2a, 0xea, 0x17, 0x45, 0xfb, 0x22, 0x2d, 0xef, 0xee, 0x12, 0x8f, 0x7b, 0xf5, 0x24, 0x4e, 0x2e, 0x8e, 0x73, - 0x4d, 0x25, 0xe2, 0xc8, 0x97, 0xa8, 0x2f, 0x4f, 0xd1, 0x66, 0x5a, 0x53, 0x83, 0xab, 0x5c, 0xab, 0xa6, 0x44, 0x5e, - 0x8a, 0x9e, 0xd9, 0xcd, 0xe2, 0xaf, 0xb8, 0xa6, 0x42, 0x33, 0xe0, 0xfc, 0x59, 0xfb, 0xe6, 0xcf, 0x04, 0x0f, 0x2e, - 0x8b, 0x7f, 0x94, 0xfe, 0x97, 0x53, 0x4f, 0x64, 0xf9, 0x05, 0xfe, 0x6a, 0xbc, 0x59, 0xbc, 0xf9, 0xef, 0x2e, 0x72, - 0x9f, 0x2f, 0xd8, 0x51, 0xb0, 0xde, 0x5e, 0x8e, 0x2f, 0x72, 0x7d, 0x39, 0x49, 0x7c, 0x83, 0x30, 0x80, 0xd3, 0x21, - 0x2d, 0xeb, 0x9d, 0xd6, 0x04, 0x9f, 0x81, 0x80, 0x90, 0x6c, 0xe7, 0xec, 0xc4, 0xd6, 0x1f, 0x49, 0xb4, 0x19, 0xcc, - 0xe4, 0x65, 0x90, 0xec, 0x6b, 0x24, 0x00, 0x72, 0x6a, 0x33, 0xd2, 0x71, 0x3e, 0x6d, 0x02, 0x6d, 0x32, 0x49, 0xdd, - 0x6e, 0x01, 0x5c, 0x80, 0x54, 0x94, 0xaf, 0xd6, 0x4d, 0x14, 0x35, 0xf3, 0x2a, 0x14, 0x5f, 0xed, 0xf5, 0x0b, 0xb4, - 0x53, 0x4d, 0x7b, 0x35, 0xd7, 0x81, 0xc0, 0x7a, 0xd5, 0x21, 0x42, 0x4b, 0xb6, 0x82, 0x1e, 0x7f, 0x4f, 0x7c, 0xb7, - 0xf9, 0x80, 0x7a, 0x83, 0xe5, 0x6e, 0xaf, 0x39, 0x9d, 0xda, 0xcd, 0x90, 0x1a, 0xf4, 0x19, 0x54, 0x51, 0xb0, 0x04, - 0xbc, 0xfd, 0xcc, 0xee, 0x66, 0x4b, 0x45, 0x36, 0xb7, 0xf8, 0xe2, 0x60, 0x5b, 0x24, 0x90, 0x8e, 0x23, 0x60, 0x4d, - 0x66, 0xa4, 0x24, 0xb3, 0x53, 0x9a, 0x32, 0x0a, 0x40, 0x06, 0xf0, 0x62, 0x12, 0xf6, 0x98, 0xf4, 0xdf, 0x87, 0x57, - 0x69, 0xfd, 0xd5, 0xfb, 0x62, 0xe4, 0x3d, 0xff, 0x68, 0x7a, 0xe0, 0xf4, 0x7b, 0x6b, 0x97, 0xb3, 0xd7, 0xa9, 0x47, - 0x8d, 0x25, 0xdf, 0x38, 0x80, 0xff, 0x84, 0xa7, 0xce, 0xea, 0x30, 0xdf, 0x8e, 0x9c, 0x52, 0xe5, 0xca, 0xbd, 0x0a, - 0xee, 0xf7, 0x07, 0xe1, 0xfe, 0xff, 0x55, 0xed, 0x66, 0xf8, 0xf9, 0xdf, 0xd6, 0xf0, 0x7f, 0xd9, 0x75, 0x58, 0x6b, - 0xee, 0x7f, 0x6b, 0x70, 0xe9, 0x77, 0x14, 0xd4, 0x75, 0xed, 0xdf, 0x79, 0x10, 0x68, 0x05, 0x5e, 0x17, 0x77, 0x26, - 0x2b, 0x3d, 0x4d, 0xe9, 0xc1, 0x20, 0x3a, 0xf8, 0xff, 0xb3, 0x6c, 0x8e, 0xbd, 0x38, 0x61, 0xb2, 0xb2, 0xfd, 0x7e, - 0x1a, 0x0b, 0xb0, 0x9c, 0x44, 0x69, 0xe3, 0x80, 0xf7, 0x95, 0x1f, 0xd7, 0xe8, 0xe7, 0x80, 0x4e, 0xac, 0x53, 0x40, - 0xdf, 0xd5, 0xf4, 0x09, 0xe2, 0xb1, 0x87, 0xd7, 0x90, 0x7b, 0x47, 0x70, 0x5f, 0x6b, 0x1c, 0x2e, 0x28, 0x3f, 0x14, - 0x77, 0x72, 0x31, 0x95, 0xfc, 0x52, 0xfa, 0xbd, 0x66, 0xf7, 0x45, 0x29, 0x37, 0xc4, 0x50, 0x93, 0x5b, 0x7f, 0x13, - 0x21, 0xdd, 0x2b, 0x92, 0xc8, 0x6a, 0x51, 0x77, 0xae, 0x92, 0x4e, 0x9c, 0xdd, 0xb3, 0xad, 0xca, 0x0c, 0xc0, 0x8b, - 0x2a, 0x97, 0x92, 0xb7, 0xeb, 0x40, 0x19, 0xd3, 0x7b, 0xec, 0x7c, 0x1d, 0x0d, 0xa8, 0xa5, 0xf4, 0x55, 0xde, 0xf0, - 0xef, 0xfc, 0x02, 0xf3, 0xae, 0xc6, 0xba, 0xf1, 0xc4, 0x3e, 0x1a, 0xda, 0x4d, 0xe3, 0x3e, 0x42, 0x40, 0x1d, 0x6e, - 0xc8, 0xa9, 0x46, 0xa2, 0x6b, 0x3e, 0xcb, 0xc3, 0x88, 0xb2, 0x91, 0xb7, 0xe0, 0x4c, 0x9c, 0xb3, 0x4e, 0x41, 0x86, - 0x99, 0xa1, 0x61, 0x05, 0x4d, 0x6f, 0x31, 0xc6, 0xf6, 0xf2, 0x8e, 0xef, 0x8e, 0xb2, 0xb5, 0xfd, 0xfa, 0xcb, 0x02, - 0x81, 0x74, 0x5c, 0x04, 0xef, 0x14, 0x5f, 0xe0, 0x91, 0x34, 0x32, 0xf5, 0x60, 0xdf, 0x5f, 0xd2, 0x8b, 0xb0, 0xff, - 0xd6, 0x9c, 0x26, 0x97, 0x2f, 0xe7, 0x4c, 0x69, 0x51, 0xe7, 0x6c, 0xf1, 0xe2, 0xb6, 0x71, 0xff, 0xd3, 0xe4, 0xda, - 0x98, 0xf5, 0xe7, 0x9c, 0x14, 0x15, 0x4e, 0xb4, 0xce, 0xe6, 0x62, 0xef, 0xbd, 0xe7, 0xbc, 0x1e, 0x2c, 0xbb, 0x07, - 0x67, 0x32, 0x62, 0xeb, 0xad, 0x2e, 0xbc, 0x64, 0xdf, 0x26, 0x6e, 0x9b, 0x0a, 0xae, 0x29, 0x1e, 0xbc, 0x7a, 0x99, - 0xde, 0x5d, 0x9d, 0x2c, 0x59, 0xac, 0x59, 0x7e, 0x34, 0xa0, 0x9b, 0x7d, 0x58, 0xb7, 0x8d, 0xc6, 0xf1, 0x9a, 0x4a, - 0x6c, 0x9b, 0x58, 0xc6, 0xac, 0xa6, 0x13, 0xc1, 0xfd, 0x5f, 0x36, 0xb8, 0x76, 0xa6, 0x0e, 0xc5, 0xb5, 0x19, 0x85, - 0x52, 0xf0, 0xa3, 0x04, 0x24, 0x5c, 0x32, 0x96, 0x0c, 0x9c, 0xe0, 0xdb, 0x39, 0x9d, 0x4c, 0x99, 0xa6, 0xe1, 0x74, - 0xf3, 0xc3, 0x69, 0x07, 0xdf, 0x76, 0x12, 0x23, 0x20, 0xb9, 0x1f, 0x19, 0xb9, 0xc1, 0x64, 0x49, 0xa8, 0x11, 0x77, - 0xeb, 0xe4, 0x17, 0x74, 0xcc, 0x64, 0x89, 0xa7, 0x52, 0x93, 0x87, 0xf3, 0xf1, 0x09, 0xfb, 0xf9, 0x67, 0xeb, 0x6f, - 0xd6, 0x37, 0xed, 0x2a, 0xdc, 0x28, 0xeb, 0xd4, 0x7e, 0x86, 0x3d, 0xab, 0x12, 0x42, 0xde, 0x94, 0xf7, 0xf6, 0x96, - 0xda, 0xa7, 0xdf, 0x37, 0x22, 0xb8, 0xfa, 0xce, 0xd0, 0xea, 0xcf, 0x29, 0x82, 0xe5, 0x6e, 0xd7, 0x4a, 0xa5, 0xc9, - 0xea, 0x89, 0xef, 0xfd, 0x1a, 0x6f, 0x45, 0xce, 0x83, 0x97, 0xec, 0x8d, 0x38, 0x7f, 0x2c, 0x8a, 0xef, 0x9e, 0x3f, - 0x22, 0x16, 0x97, 0x77, 0x73, 0x0c, 0xb1, 0xc9, 0xe5, 0x21, 0x95, 0xc4, 0x34, 0xf8, 0x04, 0x6a, 0x3b, 0xab, 0xa1, - 0x44, 0x57, 0x52, 0xab, 0x2b, 0xbe, 0x94, 0x02, 0x96, 0xca, 0xa8, 0x92, 0xa1, 0xae, 0x0e, 0xa7, 0x8e, 0xd2, 0xf2, - 0xc3, 0xab, 0x0a, 0x2e, 0x95, 0x79, 0x68, 0x69, 0x0c, 0xbf, 0xf4, 0xe9, 0x05, 0x63, 0x18, 0xd9, 0x66, 0x03, 0x97, - 0xa7, 0xe8, 0x44, 0xef, 0xe0, 0x0b, 0xa1, 0xe3, 0x43, 0x33, 0xf9, 0x02, 0x8d, 0xd7, 0x50, 0x92, 0xe1, 0x90, 0x73, - 0x55, 0xdc, 0xa2, 0x96, 0xb8, 0x7f, 0x45, 0xd6, 0x53, 0x4d, 0x69, 0xd1, 0x9e, 0x96, 0xa1, 0xa0, 0xb4, 0x4e, 0x72, - 0x5d, 0x61, 0x7a, 0x99, 0x74, 0x52, 0x4f, 0x6b, 0x70, 0x2b, 0x77, 0x8e, 0x44, 0x66, 0xf7, 0x4d, 0xd3, 0x91, 0x42, - 0x6e, 0x57, 0x40, 0xd2, 0xae, 0x3f, 0x8f, 0x55, 0xc8, 0x3e, 0x24, 0x4d, 0x2d, 0xe9, 0xfe, 0xcc, 0x0e, 0x84, 0x96, - 0xf7, 0xdd, 0xd8, 0xa9, 0x23, 0xdd, 0x83, 0x60, 0xec, 0xfc, 0x56, 0x69, 0x37, 0xcd, 0x49, 0xbc, 0x71, 0xf1, 0x6b, - 0x8f, 0x02, 0xb2, 0xa5, 0x19, 0x7c, 0x6d, 0x4d, 0x40, 0xbb, 0x7c, 0x03, 0x6b, 0x2d, 0x76, 0x30, 0xde, 0xe7, 0x6d, - 0xe8, 0xa1, 0x0f, 0x6c, 0x94, 0x6a, 0x1e, 0x7e, 0xa3, 0x54, 0xfd, 0x8e, 0x9c, 0x42, 0xd5, 0x73, 0xfe, 0xba, 0x24, - 0x8e, 0x8d, 0xac, 0xb6, 0x8b, 0x23, 0x06, 0x1b, 0x18, 0xe3, 0x50, 0x5f, 0x20, 0x62, 0xde, 0x31, 0x32, 0x40, 0x87, - 0xa4, 0x43, 0x59, 0x27, 0xd3, 0x44, 0x42, 0xcc, 0x03, 0x12, 0xec, 0x1d, 0x40, 0x3d, 0x80, 0xff, 0xc9, 0xa4, 0x45, - 0xfe, 0xa9, 0x5d, 0xe5, 0xdc, 0x31, 0xc7, 0x5f, 0x6a, 0x76, 0xcd, 0x46, 0x99, 0xd5, 0xd4, 0xe0, 0x7e, 0xd1, 0x14, - 0x11, 0xd5, 0xf2, 0x5a, 0x36, 0x4a, 0x67, 0x8e, 0xa4, 0xf8, 0x8b, 0xd9, 0xd2, 0x93, 0xfe, 0xf6, 0xbe, 0x94, 0x3e, - 0x7b, 0xf7, 0xfc, 0xce, 0x22, 0x67, 0xaa, 0xdd, 0xfd, 0x14, 0x87, 0x4f, 0x7d, 0xb2, 0xe4, 0x5f, 0x3f, 0xfe, 0x8b, - 0x7f, 0x41, 0x6f, 0xf8, 0x0b, 0xd6, 0xa5, 0x11, 0xac, 0x5d, 0xf6, 0xf5, 0x25, 0xd8, 0xf1, 0xa1, 0xd1, 0xa7, 0x0c, - 0x2c, 0x05, 0x77, 0x41, 0x4b, 0xf0, 0x10, 0x60, 0xb2, 0xd5, 0x6a, 0xfd, 0x40, 0xdc, 0x3f, 0xbb, 0xae, 0x2b, 0x5f, - 0x2c, 0xdc, 0x57, 0xdb, 0xf7, 0x45, 0xaa, 0xd5, 0xe7, 0xdd, 0x4e, 0x26, 0xc7, 0xbb, 0xff, 0x42, 0x0d, 0xfa, 0x46, - 0x84, 0xc2, 0x33, 0x3b, 0x3d, 0x5d, 0x0d, 0x8b, 0xd7, 0x55, 0xbf, 0x98, 0xaa, 0xb6, 0xb8, 0xa9, 0xa6, 0xc5, 0x8b, - 0xea, 0xf4, 0xe0, 0xff, 0xae, 0x78, 0xc9, 0x33, 0x61, 0x98, 0x0f, 0x34, 0xc8, 0xd9, 0xe3, 0x97, 0xa1, 0x96, 0x1b, - 0x1f, 0x28, 0x76, 0xab, 0xa2, 0x70, 0xda, 0xa5, 0xef, 0x7f, 0xdc, 0x67, 0xf0, 0x46, 0x0a, 0x7a, 0x19, 0xd3, 0x1e, - 0x2d, 0x69, 0xd0, 0x4c, 0x22, 0x48, 0xec, 0xeb, 0x4e, 0x7b, 0x27, 0x1d, 0x48, 0x18, 0xf4, 0xeb, 0x6d, 0xcb, 0x35, - 0x1e, 0x45, 0x98, 0x30, 0x79, 0xcb, 0x40, 0x1c, 0x0a, 0xbe, 0x42, 0x35, 0x22, 0xda, 0x3b, 0x61, 0x9b, 0x24, 0x82, - 0x20, 0x86, 0x2e, 0x75, 0x52, 0x07, 0xbb, 0x4c, 0x73, 0xeb, 0x3c, 0x96, 0x00, 0x69, 0xc5, 0x9a, 0xf2, 0x53, 0x5f, - 0xb4, 0x62, 0x92, 0x8a, 0xda, 0x5c, 0x98, 0x2a, 0xa1, 0x9b, 0x11, 0x62, 0x7d, 0xcb, 0x05, 0xdf, 0xe6, 0x75, 0x2d, - 0x02, 0x2d, 0x37, 0x6b, 0x06, 0xe4, 0x8c, 0x2e, 0xe4, 0x8d, 0xb9, 0x90, 0x2d, 0x96, 0x69, 0xbd, 0x30, 0x4e, 0x35, - 0x6d, 0xda, 0x88, 0xc8, 0x5e, 0xfd, 0xfa, 0x16, 0x88, 0xec, 0x43, 0x5f, 0xd4, 0x99, 0xde, 0xd4, 0xad, 0xb0, 0x89, - 0x41, 0xa6, 0xa1, 0x2a, 0x51, 0x1a, 0xa2, 0x11, 0x17, 0xf1, 0x68, 0x57, 0x89, 0xb0, 0xf1, 0x93, 0xfc, 0x9a, 0x49, - 0x0a, 0x3a, 0x80, 0x58, 0xa0, 0xe2, 0xba, 0xf6, 0x02, 0xe2, 0x90, 0x95, 0xde, 0x37, 0xfd, 0x53, 0x6e, 0xee, 0x8c, - 0x72, 0x33, 0xf4, 0x93, 0x26, 0x57, 0x70, 0x09, 0x31, 0xea, 0x21, 0x8a, 0xc8, 0x47, 0xb1, 0xef, 0x50, 0x27, 0x90, - 0x02, 0x4e, 0x14, 0x67, 0xd0, 0x38, 0x53, 0x81, 0x03, 0xf6, 0x81, 0x16, 0x71, 0x0c, 0x45, 0xf6, 0xa3, 0xae, 0x3a, - 0xd7, 0x23, 0x93, 0x54, 0x77, 0xd2, 0x6f, 0xfe, 0x73, 0x55, 0x65, 0xb0, 0x97, 0x57, 0xab, 0x6c, 0x3e, 0x28, 0xf9, - 0x07, 0xf6, 0x37, 0x73, 0x85, 0x8a, 0xb5, 0xf3, 0x36, 0x9c, 0xd1, 0xe6, 0x88, 0xb1, 0x85, 0xe5, 0x71, 0x6e, 0xa9, - 0x27, 0x70, 0xad, 0xbf, 0x03, 0xcf, 0x70, 0xf6, 0x2d, 0x61, 0x64, 0x5e, 0x4e, 0x26, 0x0b, 0xdd, 0xcc, 0x6e, 0x77, - 0x79, 0xe4, 0x6c, 0x98, 0xd4, 0x9e, 0x2c, 0xea, 0xd7, 0x00, 0xe3, 0x47, 0xbc, 0xe6, 0xc1, 0x9e, 0x81, 0xeb, 0x91, - 0x48, 0xc1, 0x66, 0x80, 0x77, 0x32, 0x76, 0xc4, 0xca, 0x89, 0xb3, 0x34, 0x06, 0x9d, 0x0b, 0x57, 0xa5, 0xe9, 0xef, - 0x2d, 0x51, 0x4a, 0x00, 0x98, 0x41, 0xe8, 0xfd, 0xdc, 0x36, 0xf7, 0xad, 0xa8, 0x4d, 0x49, 0x1a, 0xe2, 0x0c, 0xa2, - 0x72, 0xa0, 0x62, 0x17, 0x34, 0x1d, 0xed, 0x5b, 0x2a, 0xc7, 0xc9, 0x0c, 0x12, 0xa6, 0x5e, 0x19, 0x77, 0xc5, 0x5f, - 0xfa, 0xac, 0x56, 0xff, 0xfc, 0xc8, 0xf4, 0x54, 0xff, 0x88, 0xec, 0xf6, 0x55, 0xf1, 0x3c, 0x57, 0x7e, 0x62, 0x4a, - 0xcd, 0xd5, 0x76, 0x27, 0x43, 0xbc, 0xb1, 0xf4, 0x56, 0xcc, 0x1c, 0xb0, 0xde, 0x1a, 0x9e, 0xd7, 0xbb, 0x5e, 0xcc, - 0x1d, 0xf5, 0x4b, 0xba, 0xaf, 0xcf, 0xff, 0x26, 0x03, 0xfb, 0x0d, 0x93, 0x9c, 0xfb, 0x9a, 0xf6, 0x3c, 0xa1, 0xaf, - 0x16, 0xf3, 0x9a, 0x26, 0x36, 0xf6, 0x99, 0x67, 0xde, 0xd2, 0x34, 0xc8, 0x9e, 0xee, 0xeb, 0x95, 0xd6, 0x99, 0x39, - 0xc7, 0x87, 0x83, 0xe6, 0xf3, 0x27, 0xdd, 0x1b, 0x07, 0xdd, 0x15, 0x28, 0x2e, 0xdd, 0x27, 0xdf, 0x51, 0xf8, 0xc2, - 0x5c, 0x30, 0xed, 0x5c, 0x22, 0xe4, 0xc1, 0xcd, 0xf2, 0x04, 0xa4, 0xbc, 0xcc, 0x27, 0x90, 0x34, 0xcf, 0xcf, 0x97, - 0x98, 0x95, 0x22, 0xc1, 0xcd, 0x84, 0x59, 0x4f, 0x9b, 0x81, 0xe9, 0x66, 0x37, 0x9b, 0x77, 0xf5, 0xe4, 0x49, 0xe7, - 0xb5, 0x83, 0xa6, 0xce, 0xbf, 0xb2, 0xd9, 0xa7, 0x2f, 0x2a, 0xf5, 0x34, 0xad, 0xdc, 0xf5, 0x24, 0x7f, 0xaf, 0x44, - 0x99, 0x05, 0xf0, 0x5e, 0x4a, 0xe4, 0x29, 0x9e, 0xee, 0xe4, 0xa4, 0x89, 0x6a, 0x80, 0x14, 0xab, 0xbb, 0x13, 0xc3, - 0x46, 0xd5, 0x42, 0xa7, 0x1c, 0x3d, 0xe3, 0xd5, 0xcf, 0xd8, 0x23, 0xbe, 0x88, 0xd8, 0x89, 0x8d, 0xc2, 0x8f, 0x8a, - 0xa1, 0xc2, 0xfa, 0xb4, 0x2e, 0x83, 0x57, 0x86, 0xd5, 0x65, 0x2c, 0x06, 0xe4, 0xe7, 0xa6, 0x5c, 0x48, 0xa1, 0xe5, - 0xe7, 0xe8, 0x3e, 0x34, 0x35, 0x50, 0x6f, 0x7c, 0x1e, 0xef, 0xf2, 0xd9, 0xa4, 0xfe, 0x0d, 0x04, 0x7c, 0x90, 0x01, - 0xb5, 0x2c, 0x74, 0x5a, 0xcf, 0x9e, 0xe2, 0xc7, 0x4f, 0xfb, 0xdf, 0x58, 0xf2, 0xf1, 0xc7, 0xff, 0x14, 0xcf, 0x1e, - 0xfb, 0xa8, 0x52, 0x68, 0x12, 0xbc, 0xa7, 0xb0, 0x6f, 0xb3, 0xff, 0xef, 0x91, 0x67, 0xd1, 0xc4, 0x8b, 0xe1, 0x51, - 0x9d, 0x5d, 0x20, 0x4a, 0x6a, 0x7d, 0xe8, 0x8b, 0xd8, 0x71, 0xdf, 0xf7, 0x60, 0x59, 0xba, 0x47, 0xdc, 0xe4, 0xc1, - 0xf5, 0x49, 0xec, 0xf6, 0x95, 0x89, 0x54, 0x6a, 0xfc, 0x8c, 0x5c, 0xc0, 0x58, 0x27, 0xed, 0x31, 0x5c, 0xda, 0xd2, - 0x48, 0xc1, 0xa6, 0x14, 0x67, 0x52, 0x80, 0xfb, 0x4c, 0x94, 0xbe, 0xb3, 0x8f, 0x20, 0xa9, 0xf7, 0x2f, 0x4d, 0x60, - 0x49, 0x5e, 0x97, 0x05, 0x12, 0x9f, 0x8f, 0x2b, 0xf7, 0xf9, 0x24, 0x20, 0x2e, 0x8a, 0x0b, 0x68, 0x0b, 0xc4, 0x18, - 0x15, 0xb9, 0x14, 0x3d, 0x64, 0x69, 0x2a, 0x26, 0xaa, 0x43, 0x7a, 0xc1, 0x6e, 0xdf, 0x0d, 0x94, 0x32, 0x2d, 0x74, - 0xfc, 0xd5, 0x89, 0x18, 0x28, 0x5d, 0x9e, 0xed, 0x6d, 0x61, 0x40, 0x2e, 0x17, 0x13, 0x82, 0x34, 0xbe, 0x9e, 0xc2, - 0xb2, 0xf3, 0x11, 0x5d, 0x25, 0x00, 0x29, 0xbc, 0x5b, 0xc4, 0xcd, 0xa0, 0xa0, 0xa4, 0x81, 0xaa, 0xa9, 0x8d, 0x1e, - 0x08, 0xb1, 0xec, 0x4c, 0xa9, 0xdc, 0x8a, 0x0a, 0x04, 0x01, 0x22, 0x1b, 0x7b, 0x90, 0xc8, 0xe9, 0x61, 0x7a, 0xb8, - 0xa3, 0x2d, 0x4a, 0xa6, 0x68, 0x04, 0x35, 0xda, 0xf4, 0x90, 0xa4, 0x07, 0xaf, 0x9b, 0x89, 0xc1, 0x89, 0xb3, 0xe1, - 0x17, 0xbc, 0xd7, 0x93, 0x7b, 0xbb, 0x36, 0xb2, 0xcf, 0x25, 0xe9, 0x10, 0x73, 0x78, 0xd8, 0xd5, 0xd3, 0xcd, 0x71, - 0xbb, 0xa7, 0x9c, 0x7b, 0x89, 0x9d, 0x80, 0xf6, 0xf6, 0xd4, 0x7d, 0x67, 0x25, 0x6a, 0x5d, 0xf0, 0x08, 0x29, 0xd7, - 0x49, 0xd7, 0x93, 0xef, 0x2f, 0xef, 0x6a, 0x53, 0x2a, 0x9b, 0x88, 0x54, 0x34, 0x99, 0x2a, 0x10, 0x53, 0x82, 0x34, - 0x96, 0x51, 0x2f, 0xb7, 0x73, 0xc4, 0x9e, 0x0e, 0xa3, 0xb8, 0x85, 0x37, 0xb3, 0x55, 0xf6, 0x26, 0xad, 0xaf, 0xb0, - 0x82, 0x69, 0x8a, 0x6a, 0xfe, 0xfb, 0x59, 0x56, 0xb4, 0x33, 0x10, 0x41, 0xa8, 0xe7, 0xb6, 0x25, 0xbb, 0x80, 0x46, - 0x39, 0x7f, 0xdb, 0x40, 0x9b, 0x0e, 0xfb, 0x20, 0xe4, 0x39, 0x32, 0xef, 0xe5, 0x5b, 0x22, 0xc4, 0x40, 0x4a, 0x90, - 0x81, 0xaf, 0x5d, 0x44, 0xd4, 0x1c, 0x16, 0xcd, 0x6d, 0xe0, 0xf0, 0x21, 0x5c, 0x91, 0x99, 0x60, 0x32, 0xc5, 0xdd, - 0x85, 0x38, 0xed, 0xb8, 0xc3, 0x3d, 0x3b, 0xea, 0x59, 0x93, 0x3b, 0x65, 0x1a, 0x69, 0x26, 0x79, 0x7a, 0xb7, 0x4a, - 0xa3, 0x6c, 0xe9, 0xc8, 0xc5, 0x26, 0x92, 0x4b, 0xb9, 0x85, 0x88, 0xdb, 0xb2, 0x76, 0xfa, 0xf6, 0xfb, 0xb2, 0x79, - 0x74, 0x2f, 0xbe, 0xf5, 0x3e, 0xec, 0xdc, 0xaa, 0xb7, 0x35, 0xdb, 0xd6, 0x4f, 0x4b, 0x81, 0x52, 0x06, 0xdc, 0x99, - 0xae, 0x64, 0x26, 0x55, 0x57, 0xbe, 0x68, 0xdb, 0x21, 0x5f, 0x98, 0xc0, 0xf4, 0x34, 0xbc, 0xcd, 0x6a, 0x9d, 0x50, - 0x94, 0xd2, 0x07, 0x62, 0x91, 0xf8, 0x30, 0x00, 0xc6, 0x07, 0xaf, 0x89, 0x5c, 0xf0, 0x33, 0xfc, 0x5c, 0x2a, 0xfd, - 0xae, 0xc9, 0x52, 0x14, 0x80, 0x3e, 0x88, 0xf6, 0xec, 0x34, 0xaa, 0xf9, 0x2a, 0x9b, 0xe9, 0xe4, 0x20, 0xa6, 0x7f, - 0xfc, 0xff, 0x5c, 0x05, 0xea, 0xb7, 0x23, 0x3d, 0x84, 0xf7, 0x9b, 0x04, 0xae, 0xd5, 0xc2, 0x98, 0x9e, 0xc4, 0xa8, - 0x7b, 0x58, 0x12, 0xe1, 0x40, 0x00, 0x5f, 0x45, 0x4d, 0xdc, 0x48, 0xe3, 0xad, 0xa2, 0xa7, 0xa8, 0x6f, 0xc3, 0x5b, - 0x77, 0xb2, 0x4f, 0xc6, 0xe1, 0x7e, 0x8e, 0xb9, 0x17, 0x25, 0xcb, 0x32, 0x88, 0x86, 0x41, 0xd1, 0x2d, 0x0c, 0xac, - 0x90, 0x9f, 0x2f, 0xe0, 0xcb, 0x30, 0xe7, 0x33, 0xa3, 0x64, 0xb4, 0x42, 0xf4, 0x2a, 0xa4, 0x0e, 0x12, 0xef, 0x66, - 0x98, 0x0d, 0x7a, 0x06, 0xc5, 0xfe, 0x60, 0xea, 0x54, 0x2a, 0x68, 0xaf, 0xaa, 0xd2, 0x64, 0x57, 0x92, 0x5b, 0x7b, - 0x15, 0x1d, 0xfd, 0x14, 0x44, 0x8e, 0x97, 0xa2, 0xc5, 0x17, 0x1e, 0x0b, 0xfb, 0x5d, 0xdc, 0x1c, 0xc7, 0x00, 0x3c, - 0x7f, 0xfa, 0xa9, 0x17, 0xb7, 0x22, 0x3b, 0xfd, 0x5b, 0xe2, 0xd2, 0x77, 0x8f, 0xa6, 0xf1, 0xff, 0x29, 0x64, 0x7f, - 0xe0, 0xb7, 0x08, 0xac, 0x3f, 0xed, 0x31, 0x38, 0xb8, 0x84, 0xeb, 0x2d, 0x62, 0xf3, 0x05, 0x2c, 0xcb, 0xdb, 0xad, - 0x79, 0x20, 0x24, 0xee, 0x0b, 0x63, 0x66, 0x4f, 0xca, 0x6a, 0x94, 0x08, 0xff, 0xba, 0x8f, 0x61, 0xff, 0x35, 0x71, - 0x09, 0xc2, 0x70, 0x6e, 0x5c, 0xe8, 0xef, 0xb4, 0xce, 0x9e, 0xe2, 0xfb, 0xa7, 0xfe, 0x66, 0xc9, 0xfb, 0x1f, 0xff, - 0x53, 0x9c, 0x79, 0x67, 0x5c, 0xa3, 0xb7, 0x4f, 0x6f, 0x6e, 0x22, 0x46, 0x4d, 0x5e, 0xcb, 0x0a, 0x67, 0x3f, 0x8b, - 0x9c, 0xcd, 0x84, 0x57, 0x27, 0x72, 0x81, 0x86, 0x91, 0x8f, 0x7b, 0x5e, 0xa2, 0x17, 0xec, 0xba, 0xa3, 0x58, 0x9a, - 0x68, 0xcb, 0x22, 0x54, 0xe8, 0xa7, 0x06, 0x49, 0x82, 0xf9, 0xfe, 0x27, 0x31, 0x3b, 0x6a, 0xab, 0x61, 0x66, 0x15, - 0x0f, 0xf1, 0x5d, 0x5a, 0x99, 0xa4, 0x9c, 0x57, 0xf5, 0x4e, 0x25, 0xca, 0xe6, 0x47, 0x64, 0x87, 0xc5, 0x60, 0xcc, - 0x4a, 0x08, 0xfb, 0x9d, 0x21, 0x32, 0x72, 0xd4, 0x97, 0x38, 0x49, 0xfc, 0x56, 0x47, 0x48, 0xbc, 0xb3, 0x34, 0x48, - 0x5f, 0x4b, 0x80, 0x7c, 0x2d, 0xbb, 0x3e, 0xf6, 0x62, 0x4a, 0x27, 0x1c, 0xee, 0x24, 0x7d, 0xeb, 0x3d, 0xf2, 0x8d, - 0x30, 0x6f, 0x95, 0xc6, 0x31, 0x20, 0xec, 0x5c, 0x03, 0x46, 0x46, 0xec, 0x40, 0x0e, 0x31, 0x17, 0x3b, 0x40, 0x30, - 0xeb, 0x6a, 0x9c, 0x03, 0xbf, 0xf7, 0x0e, 0xa5, 0xf4, 0x62, 0x2d, 0xb5, 0x4f, 0x72, 0x7e, 0x90, 0xc3, 0x31, 0x27, - 0x30, 0xde, 0x93, 0x39, 0x1d, 0x68, 0x1e, 0x93, 0x52, 0x2b, 0x91, 0x8a, 0x06, 0xe4, 0x57, 0xc9, 0xe0, 0x9e, 0xed, - 0xc9, 0x88, 0x93, 0x7f, 0xa1, 0x94, 0xfc, 0xe1, 0xc6, 0x3d, 0x9a, 0x09, 0xce, 0xcb, 0x03, 0x76, 0xb1, 0x59, 0x94, - 0x40, 0x3b, 0x53, 0xcd, 0x93, 0xb3, 0x05, 0x73, 0x69, 0x49, 0x49, 0xcb, 0xc2, 0x27, 0x64, 0x46, 0x6e, 0xfe, 0xc5, - 0xeb, 0x9b, 0xfe, 0x91, 0x61, 0x05, 0xc1, 0x5e, 0xeb, 0xaf, 0xf5, 0x7e, 0x4f, 0xa7, 0x83, 0x43, 0xd0, 0x9d, 0x03, - 0xb4, 0x4a, 0xe3, 0x61, 0x7f, 0xc6, 0x26, 0x80, 0x4c, 0x10, 0x3f, 0xdc, 0xb0, 0xee, 0xee, 0x07, 0x04, 0x66, 0x3f, - 0xf1, 0x8b, 0xe3, 0x94, 0x11, 0xf0, 0xad, 0xdd, 0xa2, 0x12, 0x22, 0x87, 0xff, 0xe7, 0xbe, 0x92, 0xc5, 0xea, 0x36, - 0x39, 0xd2, 0xec, 0xd7, 0xad, 0x33, 0xc0, 0x38, 0xfa, 0xe5, 0x3a, 0xa1, 0x12, 0x46, 0x66, 0x87, 0xa6, 0xd8, 0x15, - 0xce, 0x1e, 0xe1, 0x64, 0xc6, 0x7e, 0x0a, 0x8d, 0x48, 0xe3, 0x60, 0x25, 0x47, 0x5a, 0x80, 0x8b, 0xe5, 0x70, 0x68, - 0x98, 0x84, 0x0e, 0xb0, 0xc5, 0x45, 0x8e, 0xfb, 0xe1, 0xf9, 0x4c, 0xb2, 0xc3, 0x4b, 0x02, 0xe8, 0xc0, 0xb9, 0x88, - 0x89, 0x20, 0x07, 0x2d, 0x06, 0xa1, 0x1b, 0x72, 0xb0, 0x16, 0xaa, 0x61, 0x72, 0x04, 0xcf, 0xbe, 0xfe, 0x31, 0xfa, - 0x49, 0xc3, 0xe0, 0x25, 0x24, 0xc3, 0x28, 0x01, 0xe4, 0x98, 0xac, 0xf4, 0x1b, 0xf7, 0x76, 0x7b, 0xeb, 0xae, 0x0b, - 0x89, 0x3b, 0xfb, 0x69, 0xd7, 0x72, 0x31, 0x91, 0x7a, 0xf5, 0xd1, 0xc0, 0xb0, 0x73, 0xc0, 0x16, 0x78, 0x15, 0x44, - 0x67, 0xa2, 0xc7, 0x3d, 0xdc, 0x9f, 0x42, 0xaf, 0x30, 0x47, 0x60, 0x02, 0x7c, 0x63, 0xb2, 0x3b, 0x79, 0x84, 0xab, - 0xdb, 0x7d, 0xb4, 0xe7, 0xb1, 0x35, 0x8e, 0x0a, 0xa1, 0x34, 0xe2, 0x2d, 0xd3, 0x9d, 0x64, 0xc2, 0x3a, 0xac, 0xfe, - 0xa1, 0x29, 0xae, 0xd2, 0x77, 0xd2, 0x34, 0x82, 0x13, 0xb1, 0xfb, 0x36, 0xdc, 0x6a, 0xe0, 0x04, 0x47, 0x2e, 0x7a, - 0xf8, 0x8e, 0x08, 0x43, 0x0b, 0x7c, 0xc0, 0x49, 0xc5, 0x6c, 0x3c, 0x26, 0x06, 0x4e, 0xe3, 0x24, 0x57, 0x66, 0x39, - 0x37, 0x39, 0x24, 0xae, 0x58, 0xae, 0xb0, 0x9e, 0x5e, 0xb3, 0x6c, 0x93, 0x09, 0xf0, 0xde, 0x4f, 0xdd, 0x7b, 0x26, - 0xa4, 0x5c, 0x35, 0x6a, 0xcb, 0xdd, 0x59, 0xf1, 0x69, 0xb4, 0x92, 0xc9, 0xc9, 0x26, 0xfe, 0x30, 0xc0, 0x9d, 0xdd, - 0x12, 0xdd, 0xa9, 0xee, 0x2e, 0xb9, 0x0b, 0x8d, 0x27, 0xcc, 0x9c, 0xc2, 0x3e, 0x58, 0x4b, 0x75, 0x1e, 0x86, 0xd6, - 0xe3, 0xef, 0x9a, 0x99, 0x80, 0xc8, 0x4e, 0xa6, 0xb3, 0xf8, 0xa1, 0x1b, 0x90, 0xd2, 0x12, 0x47, 0x17, 0x25, 0xab, - 0x3f, 0xad, 0x7b, 0x93, 0x2a, 0xee, 0xd0, 0xf6, 0xf5, 0x8d, 0x1c, 0xef, 0x24, 0x2b, 0xb1, 0x04, 0xd5, 0x48, 0x7e, - 0x91, 0xa4, 0x81, 0x1d, 0x90, 0x0e, 0xb9, 0x46, 0xc3, 0x4c, 0x3d, 0x9b, 0x07, 0xaf, 0x23, 0xdd, 0x06, 0xab, 0x74, - 0x66, 0xf7, 0xf2, 0x03, 0x69, 0x85, 0xa6, 0x8c, 0x49, 0x31, 0xc9, 0xc7, 0x8b, 0x2e, 0x4e, 0x9c, 0xa2, 0x96, 0x7c, - 0x72, 0xe5, 0xa4, 0xe7, 0xb5, 0x3a, 0xe4, 0xea, 0x65, 0x0f, 0x31, 0x90, 0x24, 0xb3, 0x78, 0xa1, 0x7a, 0x72, 0x43, - 0xbc, 0x46, 0x03, 0x9c, 0xb6, 0xc7, 0xee, 0x2e, 0x1e, 0xe5, 0xad, 0x7f, 0xaa, 0xb7, 0x15, 0x5a, 0xfe, 0x94, 0x97, - 0xf7, 0x6a, 0xfd, 0x6d, 0x14, 0x21, 0xbf, 0x8b, 0x1f, 0x76, 0xeb, 0x9f, 0xb6, 0xab, 0x52, 0xa1, 0x53, 0xf9, 0x35, - 0x69, 0x8b, 0x05, 0xc0, 0x9f, 0xd7, 0xa6, 0x29, 0x24, 0x23, 0x8c, 0xa8, 0x4f, 0x10, 0x61, 0xaa, 0x13, 0xc6, 0xb7, - 0xa2, 0x86, 0xbc, 0x15, 0xad, 0x48, 0xaf, 0x19, 0x4d, 0xe3, 0xec, 0xe7, 0x8e, 0x11, 0x76, 0x32, 0x1c, 0xb1, 0x5b, - 0x92, 0x72, 0xfd, 0x14, 0xe9, 0x29, 0x24, 0x8e, 0x45, 0x70, 0x99, 0x50, 0x69, 0x29, 0xc7, 0x04, 0xd0, 0xad, 0xb6, - 0x86, 0x2c, 0x86, 0xd4, 0xa0, 0x8c, 0x59, 0xdd, 0x3c, 0x22, 0x70, 0xd4, 0xa0, 0x87, 0x8e, 0xa4, 0x70, 0x42, 0xb3, - 0x9d, 0x3e, 0x3e, 0x7f, 0xc6, 0xb4, 0x55, 0xdb, 0x20, 0x12, 0x03, 0xd0, 0xed, 0xee, 0x48, 0x0c, 0x41, 0xda, 0xdf, - 0x11, 0xd9, 0x5a, 0x2d, 0xca, 0xe8, 0xc8, 0x86, 0x6e, 0xa7, 0xc8, 0xfc, 0x5a, 0xcd, 0x15, 0xd9, 0xd4, 0xed, 0x06, - 0x65, 0x14, 0x19, 0xa4, 0xbc, 0xa3, 0xb4, 0xe5, 0x62, 0x19, 0x1d, 0xdd, 0xa2, 0x88, 0x50, 0x71, 0x1b, 0x14, 0x69, - 0xfa, 0x83, 0x14, 0x39, 0x0d, 0x11, 0xa7, 0x00, 0xef, 0x4e, 0x2d, 0x89, 0xda, 0x2d, 0x15, 0x0d, 0x9e, 0x42, 0x2f, - 0x83, 0x79, 0x77, 0xe1, 0x40, 0x42, 0x68, 0x73, 0x83, 0x53, 0x10, 0x6d, 0x41, 0xa7, 0x22, 0xbc, 0x15, 0xe9, 0x41, - 0x6a, 0x20, 0x00, 0xaf, 0xce, 0x7d, 0x1c, 0x1c, 0x00, 0xf4, 0xc9, 0x2a, 0xe8, 0x7c, 0x7f, 0xb4, 0xc8, 0x21, 0x96, - 0x66, 0x47, 0xea, 0x29, 0xe2, 0x52, 0x9a, 0x4f, 0xc4, 0xed, 0x82, 0x1c, 0x44, 0x9a, 0x56, 0xfc, 0x87, 0x5c, 0xd8, - 0xa4, 0x9d, 0x0f, 0x33, 0x04, 0x5f, 0x6a, 0xe2, 0x89, 0xd4, 0x7d, 0x8e, 0xc5, 0x94, 0x91, 0xc9, 0xd7, 0xba, 0x0b, - 0xab, 0x1d, 0xcc, 0x01, 0x31, 0x9e, 0x54, 0xf2, 0xd3, 0x29, 0xb2, 0xb3, 0xc9, 0x62, 0xa5, 0xa1, 0x02, 0x5a, 0x3a, - 0xa4, 0xcb, 0x65, 0xab, 0xc7, 0x01, 0x77, 0xfc, 0xa8, 0x09, 0x1f, 0x0d, 0x71, 0x5d, 0xfa, 0xf4, 0x2a, 0x48, 0x43, - 0xf8, 0x60, 0x29, 0xa4, 0x65, 0xd5, 0xb8, 0xf7, 0x66, 0x92, 0xda, 0xbf, 0xdb, 0x2c, 0xad, 0x69, 0xb0, 0xc3, 0xb6, - 0xe8, 0x19, 0x44, 0xe1, 0xeb, 0xaf, 0xa7, 0xd5, 0x47, 0xe7, 0x36, 0x2d, 0x88, 0xd0, 0x57, 0x05, 0x4e, 0x2c, 0xa7, - 0xbf, 0x2c, 0xe9, 0xe6, 0x96, 0xd0, 0x47, 0x2c, 0x7f, 0x94, 0x29, 0xc7, 0x67, 0x86, 0x17, 0x6b, 0xe8, 0x7e, 0x07, - 0x5a, 0x44, 0x8d, 0xb3, 0x59, 0x16, 0x8d, 0x6c, 0x09, 0xaf, 0xa9, 0x98, 0x98, 0xab, 0x1f, 0x0d, 0x19, 0x6b, 0x64, - 0x82, 0xc8, 0xa2, 0x1f, 0x3f, 0xea, 0xd2, 0x11, 0xe7, 0x61, 0x10, 0x27, 0x20, 0xcd, 0xbc, 0x64, 0xe4, 0x4d, 0x14, - 0xfc, 0xd6, 0x73, 0x60, 0x9b, 0xf7, 0x5b, 0xfb, 0xcc, 0x6e, 0xc4, 0x47, 0xfa, 0xda, 0xeb, 0x1d, 0x08, 0x25, 0x21, - 0x46, 0xe5, 0x9e, 0x8f, 0x8b, 0x25, 0x7b, 0x1a, 0x78, 0x53, 0x96, 0x2b, 0x06, 0xb7, 0xf8, 0x0d, 0xe8, 0x41, 0x0d, - 0xef, 0x20, 0xb4, 0x8f, 0x9c, 0x76, 0x84, 0x07, 0x68, 0x54, 0x0f, 0xd7, 0x72, 0x44, 0x17, 0x10, 0x64, 0x4e, 0xd0, - 0xa3, 0x81, 0x32, 0x50, 0xf0, 0x95, 0x64, 0xd0, 0x55, 0x66, 0xbb, 0xcc, 0xd6, 0xd0, 0x8c, 0x09, 0x10, 0xa9, 0xce, - 0x9f, 0x46, 0x70, 0x09, 0x5d, 0xc2, 0xa5, 0xa2, 0x0e, 0x64, 0xd4, 0xca, 0x70, 0x30, 0x0a, 0x68, 0xfa, 0x54, 0x1a, - 0xbf, 0x1a, 0x5d, 0x0a, 0xc0, 0xb1, 0xc6, 0xe7, 0x49, 0x06, 0x9f, 0x6d, 0x5c, 0xb1, 0xb8, 0x0c, 0x9a, 0x03, 0x83, - 0x6b, 0x5f, 0xdb, 0xab, 0xae, 0xc1, 0xce, 0xeb, 0xef, 0xa2, 0x33, 0x86, 0x3d, 0xa3, 0x10, 0x2b, 0x80, 0x0e, 0x90, - 0x28, 0xd7, 0xc0, 0xd9, 0x7b, 0xee, 0x7c, 0x6c, 0x23, 0x57, 0xd0, 0x85, 0x0e, 0x08, 0xae, 0x35, 0xb8, 0xdc, 0x3f, - 0x02, 0x5c, 0x68, 0x68, 0xe7, 0x59, 0x60, 0x45, 0x2e, 0x33, 0x50, 0x23, 0xfe, 0x4d, 0xee, 0x60, 0x59, 0x8d, 0x74, - 0x11, 0x8f, 0x15, 0xb5, 0xed, 0x64, 0x81, 0x4e, 0xb0, 0x4d, 0x0d, 0xb1, 0x03, 0x14, 0xbc, 0x50, 0x7e, 0xc2, 0xa9, - 0x47, 0x4b, 0x37, 0xa8, 0x2c, 0xf8, 0x1c, 0x98, 0xc5, 0xef, 0xa4, 0xde, 0xc2, 0xfd, 0x27, 0x47, 0x76, 0x10, 0x40, - 0xbc, 0x35, 0x2b, 0x84, 0x30, 0xf1, 0x72, 0x6c, 0x13, 0x76, 0x94, 0x81, 0x60, 0x37, 0x9a, 0x08, 0xd9, 0x08, 0x73, - 0x1b, 0xef, 0xa2, 0xf5, 0x7a, 0x1f, 0xbb, 0xbf, 0x18, 0x85, 0xc1, 0x76, 0x81, 0x61, 0xfc, 0x58, 0x8c, 0x22, 0xd4, - 0xf6, 0xf2, 0x5b, 0x91, 0x8c, 0xe4, 0x67, 0x15, 0xcc, 0x45, 0xdc, 0x0e, 0x6c, 0x5d, 0x99, 0x5a, 0x3f, 0x20, 0x2a, - 0xef, 0xf7, 0x92, 0x41, 0xbb, 0x85, 0x8f, 0x6f, 0x46, 0x76, 0xe2, 0x2b, 0xc7, 0xf5, 0xac, 0xfa, 0xfc, 0xfe, 0x39, - 0x22, 0x6b, 0x1e, 0x6f, 0xdd, 0x19, 0x8d, 0xce, 0x6a, 0x2d, 0x87, 0x8d, 0xda, 0xc0, 0x30, 0x21, 0xac, 0xf0, 0xfd, - 0xbc, 0x5c, 0xfb, 0x80, 0x30, 0xfc, 0xba, 0xe1, 0x37, 0x9e, 0x2d, 0xb0, 0x97, 0x1e, 0x1c, 0x2d, 0x6f, 0x5d, 0x57, - 0xd7, 0xd3, 0x4a, 0x34, 0x1e, 0x61, 0x12, 0xe2, 0x75, 0xde, 0x30, 0xa5, 0x03, 0x99, 0xe5, 0xf0, 0xa4, 0x7f, 0x70, - 0x4d, 0x67, 0x3e, 0xc4, 0x88, 0xf6, 0x17, 0x80, 0x7c, 0xd1, 0x94, 0x8f, 0x48, 0x9e, 0xd1, 0xe4, 0x06, 0x9b, 0x46, - 0xfa, 0x85, 0x33, 0xa5, 0x3a, 0x10, 0xdc, 0x77, 0x00, 0x00, 0x03, 0x75, 0x58, 0xf0, 0xfb, 0xd8, 0x56, 0xe2, 0xba, - 0x06, 0x63, 0x30, 0x30, 0xfd, 0x47, 0xbf, 0xa8, 0xf3, 0xa3, 0xcf, 0x50, 0x4d, 0xac, 0xf9, 0x52, 0x23, 0x32, 0xbb, - 0x92, 0x15, 0xd9, 0x4d, 0x90, 0x1f, 0xe7, 0xcb, 0x82, 0xdc, 0x84, 0xb8, 0x09, 0x41, 0xc5, 0x3d, 0xf1, 0xb5, 0xa8, - 0x02, 0x7d, 0x03, 0x94, 0x7f, 0x38, 0xeb, 0x40, 0xd0, 0x5f, 0x04, 0xc6, 0x9a, 0x1c, 0x84, 0xf3, 0xcf, 0x2d, 0x33, - 0x91, 0x3f, 0x8f, 0xc2, 0x65, 0xc9, 0x5f, 0xdd, 0xb2, 0x8d, 0xcc, 0xb8, 0xf1, 0x6d, 0x54, 0x99, 0x14, 0xf2, 0xba, - 0xf6, 0xac, 0x33, 0xbe, 0x90, 0x6a, 0x15, 0xc8, 0xd5, 0x45, 0xcc, 0x8c, 0x69, 0x0b, 0x39, 0xfd, 0x59, 0xfb, 0x5a, - 0xe5, 0x7f, 0xc6, 0x1d, 0x1c, 0xb3, 0xf0, 0xcf, 0xc7, 0x6d, 0x63, 0x0a, 0x88, 0xca, 0x1e, 0xf6, 0x45, 0xe5, 0x59, - 0xa7, 0xcb, 0x02, 0xd8, 0x26, 0x88, 0x2b, 0x19, 0xa1, 0xcc, 0x61, 0xa3, 0xf6, 0xfe, 0xbb, 0x7d, 0x1d, 0xcf, 0xac, - 0xb6, 0x1f, 0xd1, 0x4f, 0xfc, 0x11, 0xf3, 0x6f, 0x17, 0xf6, 0x65, 0x62, 0x9c, 0xbe, 0xce, 0x33, 0xd5, 0x9f, 0xba, - 0x49, 0x5d, 0xf0, 0xac, 0x4e, 0x40, 0x05, 0x09, 0xab, 0xe0, 0x67, 0xb0, 0x67, 0xff, 0xa3, 0xc2, 0xd5, 0x90, 0x4f, - 0xcb, 0x67, 0x67, 0xf6, 0x1a, 0xba, 0x56, 0x50, 0x75, 0xb8, 0x01, 0x22, 0x87, 0xc5, 0xad, 0xea, 0x62, 0xc7, 0x99, - 0xf9, 0x2f, 0x0b, 0xd8, 0xf8, 0x5a, 0x08, 0x4e, 0xd7, 0x1f, 0x5d, 0xbe, 0x44, 0xdb, 0x93, 0xb3, 0x89, 0x19, 0xc6, - 0x97, 0x34, 0xc4, 0x83, 0x7b, 0x4a, 0x87, 0x1f, 0x19, 0x93, 0x4f, 0xf1, 0xc7, 0xa7, 0xfd, 0x64, 0x2e, 0xf9, 0xf1, - 0xe3, 0x5f, 0xfa, 0xab, 0x7e, 0xcd, 0x33, 0xbf, 0x50, 0x67, 0xb2, 0xc3, 0x7b, 0x45, 0xd1, 0xf3, 0x8b, 0xb9, 0x18, - 0x11, 0x5b, 0x31, 0xfe, 0x30, 0x0b, 0x7d, 0xfa, 0xed, 0xed, 0xc3, 0x3d, 0x78, 0x33, 0x28, 0x69, 0xc6, 0x41, 0x9d, - 0x9b, 0xeb, 0x1c, 0x5b, 0x69, 0xca, 0x60, 0x12, 0xec, 0x0d, 0x2c, 0x91, 0x41, 0xda, 0x9d, 0x08, 0x11, 0xa8, 0x0c, - 0x4a, 0x05, 0x43, 0x69, 0x8e, 0xa3, 0xae, 0x83, 0x70, 0x20, 0x28, 0x97, 0x11, 0x5d, 0xd5, 0x2a, 0xce, 0x46, 0x07, - 0x0b, 0x01, 0x67, 0x10, 0x61, 0x08, 0xf0, 0xbd, 0x9a, 0x28, 0x81, 0x29, 0x24, 0x0d, 0x21, 0xfe, 0x54, 0x3a, 0x8e, - 0xa2, 0xb8, 0xae, 0xc2, 0xd7, 0xfb, 0x17, 0xd9, 0x38, 0xf9, 0x28, 0x81, 0xa2, 0xbc, 0x03, 0x81, 0x9a, 0x22, 0x05, - 0x9b, 0x8b, 0xcc, 0xe5, 0x88, 0x85, 0xf3, 0xa1, 0xa0, 0x17, 0x12, 0x56, 0x4b, 0x07, 0x3a, 0x1d, 0x7b, 0x38, 0x24, - 0xb4, 0x2a, 0xd8, 0x84, 0xa1, 0xc9, 0x6d, 0x7e, 0xad, 0x02, 0xca, 0xc9, 0x64, 0x17, 0xb7, 0xc0, 0x37, 0xbf, 0x3e, - 0x47, 0x77, 0x2d, 0x74, 0x9e, 0xf9, 0x9e, 0xf1, 0xf7, 0xef, 0x6f, 0x8e, 0xbf, 0xc2, 0xa3, 0x19, 0xab, 0x26, 0xac, - 0xff, 0xf5, 0x4d, 0x48, 0x08, 0xa5, 0x40, 0x15, 0x01, 0x42, 0xa9, 0xac, 0x81, 0x75, 0x1d, 0x32, 0x73, 0x68, 0xe8, - 0xfa, 0x47, 0x06, 0x39, 0x82, 0x1d, 0x36, 0xf6, 0x6d, 0x58, 0xf8, 0x5a, 0xa9, 0x83, 0xbd, 0x81, 0xa9, 0xb5, 0xb0, - 0x4f, 0x5b, 0xa0, 0xce, 0xe6, 0x9c, 0x39, 0x82, 0xa0, 0x5b, 0x66, 0x66, 0xaa, 0xd2, 0x59, 0x9e, 0x69, 0x7e, 0x46, - 0x7b, 0xc5, 0x7e, 0x5d, 0x02, 0x17, 0x64, 0xe9, 0x6c, 0x6e, 0x6d, 0x45, 0x81, 0xbb, 0x92, 0x2a, 0x9f, 0xb1, 0x75, - 0x3c, 0x04, 0xc2, 0xcf, 0x13, 0x63, 0xbb, 0xc6, 0xe7, 0xc1, 0xd6, 0x27, 0xf9, 0x80, 0x96, 0xae, 0x0f, 0x5d, 0x72, - 0xad, 0x8f, 0x11, 0xcc, 0x88, 0xa9, 0xfc, 0xf0, 0x86, 0xfa, 0x6e, 0x38, 0x70, 0x74, 0x9f, 0xe2, 0xa7, 0x4f, 0x3b, - 0xe9, 0x92, 0x4f, 0x3f, 0xfe, 0x4b, 0x5e, 0xd9, 0x75, 0x08, 0x55, 0x2e, 0x53, 0xf0, 0x63, 0x9f, 0xaf, 0xab, 0xc9, - 0xf6, 0xa6, 0xe2, 0x38, 0x10, 0x3f, 0xaa, 0x34, 0x99, 0xe8, 0x17, 0x77, 0x99, 0xc1, 0xf1, 0x3c, 0x44, 0x56, 0x7b, - 0xe2, 0x5c, 0xd7, 0x93, 0x39, 0x97, 0x6d, 0x70, 0xa1, 0x11, 0x32, 0x75, 0x79, 0xe6, 0x65, 0x9f, 0x13, 0x58, 0xd4, - 0x4c, 0xca, 0xee, 0x6b, 0x8c, 0xc7, 0xd7, 0x96, 0xd3, 0xf4, 0x2c, 0xa4, 0x50, 0x37, 0x1d, 0x2e, 0x68, 0x08, 0x15, - 0xd0, 0xe0, 0xe7, 0x6f, 0x4a, 0xd9, 0x98, 0xb8, 0x19, 0xc9, 0x7f, 0xf0, 0xc8, 0xa4, 0x99, 0x32, 0x1e, 0xe9, 0xb3, - 0x5a, 0xb3, 0x3c, 0xe8, 0x88, 0x2d, 0x65, 0xd9, 0xc7, 0xf8, 0x3a, 0xb5, 0x90, 0xfd, 0x35, 0xfd, 0x3e, 0xdd, 0x62, - 0x94, 0x5a, 0xca, 0x93, 0x8e, 0x84, 0xda, 0xfa, 0xb2, 0x1f, 0x44, 0xa4, 0x2e, 0xf0, 0x50, 0x13, 0xb1, 0x5e, 0xc6, - 0x74, 0x30, 0x98, 0x2a, 0xda, 0x6f, 0x4f, 0x77, 0xab, 0xd3, 0x37, 0x9b, 0x6a, 0x11, 0xe2, 0xfa, 0x40, 0xea, 0x63, - 0x58, 0x4d, 0x94, 0x9d, 0x1d, 0x7a, 0x09, 0x07, 0xc1, 0x03, 0xa3, 0x73, 0x05, 0x37, 0x19, 0x2e, 0x62, 0xd6, 0x99, - 0x07, 0xdc, 0x25, 0xe5, 0x70, 0x82, 0x38, 0xaf, 0xd0, 0xd5, 0xba, 0x0b, 0xe3, 0x5a, 0xbe, 0xc9, 0xbb, 0xd3, 0xa9, - 0xa4, 0x4e, 0x79, 0xb8, 0x01, 0x6d, 0xa4, 0x36, 0xbd, 0x53, 0x6c, 0x1f, 0xb8, 0x55, 0xfb, 0xef, 0x37, 0x20, 0x93, - 0xbd, 0xcf, 0x1f, 0x38, 0xa0, 0x21, 0x08, 0xd9, 0xe3, 0xe5, 0xf8, 0x02, 0x9d, 0x45, 0xdd, 0x5a, 0x77, 0x75, 0xda, - 0x5d, 0x6f, 0xa1, 0x2a, 0xeb, 0x23, 0x2e, 0x98, 0x9c, 0xa1, 0xc3, 0xb6, 0x95, 0x42, 0x3f, 0x86, 0x9e, 0xc4, 0xbc, - 0xbc, 0xb2, 0x36, 0xac, 0x93, 0x13, 0x7b, 0xc1, 0xd5, 0xbe, 0xf9, 0x83, 0xf8, 0x0c, 0x30, 0x8b, 0xb9, 0xe9, 0xcd, - 0xb3, 0xea, 0x0b, 0x31, 0x44, 0xc6, 0x35, 0x1c, 0x61, 0x02, 0x3e, 0xa0, 0xfa, 0x0f, 0x0e, 0x2d, 0x86, 0xab, 0xe3, - 0x52, 0x83, 0xe9, 0xf8, 0xc1, 0x17, 0xd5, 0x11, 0x12, 0xd3, 0x8e, 0xc7, 0x06, 0xac, 0x31, 0xd4, 0xa0, 0x83, 0x5b, - 0xd3, 0x28, 0x40, 0x10, 0xdb, 0xd7, 0xcf, 0x0d, 0x6e, 0xbf, 0x7b, 0xd7, 0xbb, 0x22, 0xe1, 0xdc, 0xbe, 0x6c, 0x80, - 0x39, 0x61, 0x30, 0x3a, 0x9d, 0xad, 0x6b, 0xa2, 0x2f, 0xea, 0xf7, 0x85, 0x2d, 0xf4, 0x40, 0x6e, 0x4c, 0x78, 0x04, - 0x0b, 0x15, 0x77, 0x90, 0x33, 0xa8, 0x80, 0xfb, 0x0b, 0x7a, 0xc0, 0x82, 0x94, 0xf1, 0x89, 0x78, 0x87, 0xd6, 0x31, - 0x42, 0x0d, 0x2c, 0x38, 0x56, 0x1a, 0x86, 0x03, 0x06, 0xc1, 0xf1, 0x59, 0xd6, 0x88, 0xbc, 0x53, 0x23, 0xf8, 0x2b, - 0x1a, 0x45, 0xeb, 0x58, 0x4a, 0x0a, 0x15, 0xac, 0xe9, 0xec, 0x6b, 0x45, 0xc4, 0xab, 0x29, 0xe8, 0x04, 0x18, 0xd2, - 0x9e, 0x38, 0xfb, 0x74, 0x17, 0xc9, 0xa2, 0x7a, 0xcf, 0x2e, 0x12, 0xe1, 0x2e, 0x03, 0x52, 0xc4, 0x81, 0x4f, 0x87, - 0xd5, 0x74, 0x55, 0x6e, 0xee, 0xa1, 0xad, 0xbd, 0x8b, 0x1d, 0x9d, 0x06, 0xc1, 0xe4, 0xd8, 0xb3, 0xe1, 0x46, 0x2f, - 0x0a, 0x0e, 0x5b, 0x49, 0xd9, 0xaf, 0x22, 0x9c, 0x70, 0xeb, 0xb9, 0x16, 0x2a, 0x1d, 0x34, 0x17, 0x7f, 0xba, 0x42, - 0x2f, 0x21, 0xd4, 0xf6, 0x4c, 0x23, 0x4e, 0x2f, 0xc1, 0xd8, 0x6e, 0xfe, 0x53, 0xb7, 0x0c, 0xda, 0xdc, 0xda, 0xbb, - 0xf4, 0xd6, 0x86, 0xb3, 0x49, 0x65, 0x56, 0x0e, 0xba, 0x17, 0xa5, 0xbb, 0x1c, 0xe3, 0x0c, 0x46, 0xf1, 0x49, 0x3e, - 0xd3, 0xaa, 0xf4, 0xd8, 0xef, 0x36, 0x78, 0xc4, 0x3e, 0xda, 0xc6, 0xd8, 0x21, 0x16, 0x58, 0xe4, 0x78, 0x76, 0x02, - 0x35, 0x0e, 0x8d, 0x78, 0x4d, 0x11, 0x5a, 0x52, 0x7b, 0x87, 0x8f, 0x3e, 0xf6, 0xd6, 0xca, 0x77, 0xe4, 0xc5, 0x5a, - 0x04, 0x50, 0x83, 0x9a, 0x56, 0x09, 0xdd, 0xa5, 0x9b, 0x67, 0xbc, 0x06, 0x2c, 0x3a, 0x0a, 0x87, 0x28, 0xdf, 0x39, - 0x57, 0xd0, 0x8e, 0xb6, 0x48, 0x64, 0x1d, 0xa3, 0xa9, 0x14, 0xb9, 0xfe, 0xc3, 0x32, 0x0d, 0x9a, 0x1f, 0xdb, 0x57, - 0x90, 0xbd, 0x39, 0x1f, 0xf3, 0x3f, 0x9e, 0xb3, 0x2f, 0xd9, 0x5e, 0x17, 0x00, 0xae, 0x9f, 0xfd, 0x63, 0x62, 0xf2, - 0x67, 0x16, 0x86, 0xf9, 0x0f, 0xf5, 0x09, 0x6f, 0x02, 0xff, 0x04, 0xcf, 0x59, 0x62, 0xbc, 0x97, 0xe2, 0x3c, 0xc5, - 0x33, 0x97, 0x40, 0x6f, 0x4b, 0xbe, 0x6c, 0x01, 0xbc, 0xb8, 0xd4, 0xbc, 0x5d, 0x70, 0x36, 0x46, 0x14, 0xa8, 0xbe, - 0xd5, 0x93, 0x5c, 0x0e, 0xba, 0x51, 0x8a, 0xb8, 0xe9, 0xb7, 0x0a, 0x34, 0xa3, 0x55, 0x62, 0x76, 0x19, 0x7a, 0xb1, - 0x74, 0x9c, 0xab, 0xf0, 0x33, 0x19, 0x6c, 0x83, 0x7d, 0x22, 0xc2, 0x65, 0xd2, 0x63, 0x84, 0xbf, 0x4d, 0x91, 0x7c, - 0xab, 0xc3, 0xf5, 0x83, 0xc6, 0xbf, 0xee, 0xfd, 0xfa, 0xd5, 0xe3, 0x8b, 0x9b, 0x86, 0xb0, 0x7a, 0xa0, 0x7c, 0x72, - 0xb6, 0xde, 0xed, 0x4c, 0x0f, 0x03, 0xc5, 0x43, 0x61, 0x34, 0x3a, 0xc6, 0x49, 0x61, 0x36, 0x9b, 0x75, 0xfd, 0xd0, - 0xf5, 0x1f, 0x39, 0x1d, 0x48, 0xb0, 0x0c, 0xe5, 0xde, 0x9d, 0x81, 0x79, 0xbd, 0x35, 0x90, 0xb5, 0x5c, 0xe5, 0xc0, - 0x9d, 0x9e, 0xa9, 0xde, 0x8e, 0x14, 0x8e, 0x78, 0xa4, 0x15, 0xee, 0xcc, 0x5e, 0x66, 0x03, 0xba, 0x8b, 0x73, 0x45, - 0x77, 0xce, 0x29, 0x59, 0x44, 0x96, 0x9f, 0xf4, 0x8e, 0xde, 0xec, 0xf8, 0xd8, 0xbd, 0x2b, 0x09, 0x2c, 0xff, 0x6f, - 0xd4, 0xa1, 0x7a, 0x48, 0x8c, 0x14, 0x9e, 0x45, 0xb1, 0xb1, 0x2a, 0x86, 0xef, 0xf0, 0x5b, 0xc9, 0x53, 0xed, 0x15, - 0xc3, 0x02, 0xdf, 0x35, 0xcc, 0xdd, 0x3a, 0x12, 0xbc, 0x4c, 0xc7, 0x80, 0x47, 0x62, 0xc0, 0x6f, 0x36, 0x8f, 0x08, - 0x5d, 0x27, 0x7b, 0x1c, 0x3f, 0x05, 0xe1, 0xc6, 0x15, 0x94, 0x33, 0x23, 0x7c, 0x83, 0x91, 0x83, 0xa7, 0x98, 0x3f, - 0xde, 0xdc, 0x41, 0xf5, 0xf1, 0xc3, 0xbe, 0x58, 0x7b, 0xf0, 0xd7, 0x02, 0xac, 0x81, 0x3c, 0xda, 0x50, 0x3d, 0x4b, - 0xf5, 0xce, 0xfd, 0x35, 0x4f, 0x0b, 0x7e, 0x46, 0x6e, 0x74, 0x5b, 0x9c, 0x23, 0x5f, 0xe2, 0xed, 0xb6, 0x13, 0x6f, - 0x77, 0x7d, 0x6b, 0x7e, 0xd4, 0x08, 0x10, 0x36, 0xbf, 0x2d, 0xdb, 0xfa, 0xc3, 0xc5, 0xed, 0x97, 0xf6, 0xce, 0x60, - 0x07, 0xb8, 0xc4, 0x80, 0x8d, 0xae, 0x8b, 0xd8, 0xe6, 0x8c, 0x1b, 0x63, 0x17, 0x71, 0xd8, 0x00, 0xa4, 0x8a, 0x98, - 0x08, 0x4d, 0xe5, 0x28, 0x04, 0x83, 0xa1, 0x37, 0x7d, 0x1f, 0xef, 0x33, 0x0f, 0xb0, 0x01, 0x9b, 0x4c, 0x6d, 0x42, - 0xd8, 0x98, 0x54, 0xb7, 0x7e, 0x1d, 0xa1, 0x2c, 0xc6, 0xc6, 0xd2, 0x9a, 0x2b, 0x0b, 0x42, 0x9f, 0xb7, 0xfe, 0x56, - 0xc3, 0x36, 0xd7, 0xf8, 0xb7, 0x58, 0x44, 0xfc, 0x98, 0x72, 0xd8, 0x5f, 0xc2, 0xa7, 0x0b, 0xc7, 0xe8, 0xe8, 0x93, - 0xc6, 0x99, 0x71, 0xaa, 0xae, 0x95, 0xfe, 0x56, 0xc6, 0x43, 0x1f, 0xdf, 0xdd, 0x98, 0x2a, 0x3b, 0xf4, 0x12, 0x2c, - 0x3a, 0x0a, 0xe3, 0x21, 0x9e, 0x06, 0x75, 0x1d, 0x47, 0x32, 0x98, 0xba, 0xc7, 0x99, 0xbe, 0xda, 0xce, 0xa2, 0xb8, - 0x8c, 0xd8, 0x79, 0x5f, 0x5a, 0x2d, 0xe3, 0xa0, 0x5a, 0xb8, 0x88, 0x8e, 0x19, 0xd4, 0x22, 0xe2, 0x9d, 0x7a, 0xf1, - 0x24, 0xf9, 0x98, 0xd3, 0x71, 0xa0, 0x74, 0x2d, 0x69, 0x8f, 0x05, 0x34, 0x44, 0x66, 0x14, 0x5e, 0xfa, 0xa9, 0x9b, - 0xfd, 0xd3, 0xf8, 0x7f, 0x5d, 0x6e, 0xb6, 0xdb, 0x63, 0xbb, 0x12, 0x85, 0x39, 0x4d, 0x0e, 0x81, 0xb6, 0xe0, 0x3b, - 0x6e, 0xf5, 0x31, 0x47, 0xc6, 0x78, 0xad, 0x4b, 0xfa, 0xa5, 0xad, 0x3a, 0x8f, 0xda, 0x35, 0x5a, 0xbf, 0xc0, 0x51, - 0x21, 0xb4, 0xd3, 0x6c, 0xb4, 0x8b, 0x0f, 0x7c, 0xde, 0x3c, 0x98, 0x86, 0x26, 0x14, 0x53, 0x4b, 0xf5, 0x90, 0x39, - 0x2a, 0x9f, 0xe3, 0xf4, 0x1e, 0x80, 0x8a, 0x48, 0x7b, 0xf7, 0x7e, 0xa6, 0xde, 0x5f, 0x6b, 0x86, 0xee, 0xa3, 0x56, - 0xca, 0x48, 0xf8, 0x6d, 0x87, 0x90, 0xb0, 0x0a, 0x49, 0x18, 0x3b, 0x27, 0xca, 0x59, 0xd6, 0x36, 0x86, 0x96, 0xf7, - 0x87, 0x83, 0xe7, 0x89, 0x56, 0xcb, 0xb8, 0xc5, 0x23, 0x72, 0xbb, 0xf7, 0x99, 0x48, 0xf5, 0xa2, 0xea, 0xf2, 0x08, - 0x82, 0x45, 0x27, 0x32, 0xd2, 0x5f, 0x8c, 0xda, 0x71, 0x02, 0xfd, 0x7b, 0xf9, 0x53, 0x50, 0x52, 0xd4, 0x0a, 0xa7, - 0x8c, 0x75, 0x13, 0x9d, 0x68, 0x29, 0xc2, 0xc8, 0xa6, 0xaf, 0x82, 0xff, 0x04, 0x37, 0x58, 0x79, 0x77, 0xcf, 0x33, - 0xa2, 0x6a, 0xe1, 0x11, 0x45, 0x32, 0x26, 0xee, 0x7e, 0x0e, 0xb3, 0x84, 0x5e, 0x7a, 0x77, 0xad, 0x75, 0xea, 0x9c, - 0x2e, 0xde, 0x04, 0x51, 0x0a, 0xa2, 0xbb, 0xcf, 0xf1, 0x13, 0xe3, 0x00, 0xe9, 0x06, 0xf8, 0xe7, 0x04, 0xc9, 0x29, - 0x4f, 0x54, 0x5e, 0x06, 0xd3, 0x36, 0xa4, 0x60, 0xf8, 0x58, 0xef, 0xc1, 0x8d, 0x37, 0x7c, 0xb9, 0x9c, 0xfa, 0xe6, - 0xcd, 0x23, 0x57, 0x3d, 0xc4, 0xd3, 0x38, 0xef, 0x6c, 0x5a, 0x26, 0xf8, 0x48, 0x12, 0xff, 0xac, 0x4d, 0xec, 0xb6, - 0x6c, 0xd2, 0xf3, 0xa6, 0xdb, 0xc2, 0xd9, 0xbd, 0x65, 0x0e, 0xb2, 0xd8, 0xf4, 0x05, 0x20, 0xe5, 0x80, 0xd6, 0xc5, - 0x2e, 0x0a, 0x05, 0x71, 0x1a, 0xe0, 0x02, 0x30, 0x42, 0x4b, 0x2c, 0x56, 0xe0, 0x89, 0xc6, 0xd3, 0x2c, 0xa7, 0xc5, - 0x36, 0x78, 0x37, 0x82, 0x67, 0x89, 0x5c, 0x4a, 0xd3, 0x90, 0x36, 0xb5, 0x94, 0xf0, 0xcc, 0xa9, 0xf5, 0x6d, 0x9a, - 0x6e, 0x6a, 0x93, 0xd9, 0x7c, 0xec, 0x8a, 0x15, 0x6d, 0xe8, 0xe0, 0x0e, 0x26, 0xd1, 0x16, 0x42, 0x36, 0x6a, 0x20, - 0xdb, 0xec, 0x4f, 0x59, 0xb2, 0xd3, 0x54, 0xa1, 0x27, 0xb5, 0x6e, 0x89, 0x16, 0x47, 0xa6, 0xde, 0xcd, 0x02, 0x49, - 0xb0, 0x85, 0x86, 0x63, 0x61, 0x45, 0xd3, 0xe3, 0x7b, 0xee, 0xa3, 0x63, 0x60, 0xa1, 0x96, 0x9e, 0xc6, 0x1c, 0xbd, - 0x33, 0x88, 0x69, 0xd6, 0x32, 0xb2, 0x65, 0xe3, 0xf3, 0x1e}; +const uint8_t INDEX_BR[] PROGMEM = { + 0x5b, 0x05, 0x7b, 0x53, 0xc1, 0xb6, 0x69, 0x3d, 0x41, 0xeb, 0x04, 0x30, 0xf6, 0xd6, 0x77, 0x35, 0xdb, 0xa3, 0x08, + 0x36, 0x0e, 0x04, 0x80, 0x90, 0x4f, 0xf1, 0xb2, 0x21, 0xa4, 0x82, 0xee, 0x00, 0xaa, 0x20, 0x7f, 0x3b, 0xff, 0x00, + 0xaa, 0x9a, 0x73, 0x74, 0x8c, 0xe1, 0xa6, 0x1f, 0xa0, 0xa2, 0x59, 0xf5, 0xaa, 0x92, 0x79, 0x50, 0x43, 0x1f, 0xe8, + 0x3c, 0x52, 0x68, 0x2c, 0xf6, 0x36, 0x31, 0x90, 0x4e, 0x2b, 0x91, 0x69, 0x38, 0xb4, 0x61, 0xa7, 0xbb, 0x57, 0x79, + 0x3b, 0x6d, 0x62, 0x85, 0x9f, 0x24, 0x24, 0xda, 0x45, 0xc1, 0xe2, 0x85, 0x44, 0x50, 0x6c, 0x8c, 0x1e, 0xab, 0xbb, + 0x7b, 0x1e, 0x30, 0x98, 0x59, 0xe5, 0xb9, 0xd1, 0x34, 0x03, 0x0b, 0x79, 0x37, 0x8c, 0x4b, 0x68, 0x2c, 0xbe, 0x21, + 0xcc, 0x30, 0xc4, 0x9c, 0x4d, 0x34, 0xd6, 0x01, 0xc1, 0xe1, 0x66, 0x48, 0x3c, 0x94, 0xf4, 0x3c, 0x5b, 0x12, 0xfd, + 0x15, 0xb4, 0x05, 0xdb, 0xaf, 0xc1, 0x59, 0x5d, 0x9f, 0xc5, 0x8d, 0xaf, 0xf7, 0xc6, 0x5f, 0x58, 0xfb, 0xc3, 0x74, + 0x45, 0x97, 0x23, 0xac, 0x2e, 0x4a, 0xb9, 0xab, 0xd7, 0x5b, 0xe5, 0x85, 0x6f, 0x21, 0xba, 0x7e, 0xa3, 0x57, 0xa5, + 0xb3, 0x24, 0x7e, 0x60, 0x30, 0x0e, 0x15, 0x1f, 0x04, 0x5e, 0xba, 0x06, 0x04, 0xff, 0x02, 0x26, 0x2d, 0x03, 0x6c, + 0x97, 0x1b, 0x23, 0x84, 0x28, 0x25, 0xb4, 0xe2, 0xca, 0xbd, 0xc8, 0xc3, 0x96, 0x4a, 0xef, 0xed, 0xe7, 0x65, 0x4f, + 0xb2, 0x2d, 0x6c, 0x02, 0x91, 0x04, 0x76, 0xae, 0xba, 0x67, 0x9c, 0xe3, 0x38, 0xd6, 0x96, 0x61, 0x0c, 0xd3, 0x80, + 0xe4, 0x4a, 0x43, 0x2e, 0x92, 0xff, 0xa7, 0xdb, 0xd2, 0xec, 0xf5, 0xf5, 0x90, 0x4a, 0x22, 0x74, 0x92, 0x40, 0x80, + 0xed, 0x2b, 0xb5, 0xbc, 0xb6, 0xe0, 0x71, 0xda, 0x35, 0x3b, 0xe9, 0xec, 0xeb, 0xac, 0xbe, 0x6a, 0x2f, 0xf0, 0xde, + 0x96, 0xf7, 0x43, 0x51, 0x4d, 0xce, 0xbb, 0xd3, 0x70, 0xc2, 0x08, 0x2c, 0xf0, 0xc8, 0xac, 0x25, 0x82, 0x67, 0xeb, + 0xcd, 0xf5, 0x7d, 0x7d, 0xb7, 0x8b, 0xca, 0x2a, 0x15, 0x66, 0x68, 0xf3, 0x6e, 0xb6, 0xda, 0x5b, 0x81, 0x7b, 0x2e, + 0xe6, 0xc1, 0xdc, 0x5e, 0x0a, 0x7a, 0xda, 0x4a, 0x2c, 0x68, 0xa4, 0xd0, 0x92, 0xe7, 0xb2, 0xb3, 0xef, 0xab, 0xda, + 0xd7, 0xef, 0x89, 0xe7, 0x22, 0xd0, 0x93, 0xe5, 0x08, 0xcc, 0xea, 0x82, 0xdb, 0xde, 0x1a, 0xdd, 0x49, 0x47, 0x26, + 0x23, 0xc1, 0x16, 0x7b, 0x2a, 0x99, 0x23, 0xe9, 0x4c, 0xf8, 0x65, 0xaa, 0xfe, 0xe9, 0x6a, 0x41, 0x0d, 0x8f, 0xfb, + 0x48, 0x9a, 0x49, 0x4e, 0x0b, 0x2e, 0x91, 0xfc, 0x76, 0x6e, 0x55, 0xee, 0xb4, 0xbb, 0x3c, 0x63, 0xc1, 0x95, 0x5a, + 0xf8, 0x37, 0x35, 0xb1, 0xaa, 0xcd, 0xa9, 0x99, 0x2f, 0x3d, 0x52, 0xd0, 0x01, 0xd9, 0x06, 0x27, 0x41, 0x92, 0xdd, + 0x6d, 0x4a, 0xee, 0xad, 0xa6, 0x33, 0xe1, 0xff, 0xeb, 0x6b, 0x5a, 0xff, 0xfd, 0xf3, 0x05, 0x0a, 0xbb, 0xc4, 0x55, + 0x1d, 0x28, 0x69, 0x66, 0x7f, 0x4f, 0x49, 0xce, 0xb2, 0xec, 0x8a, 0x0a, 0x15, 0x2d, 0x63, 0x1b, 0x6f, 0x28, 0x00, + 0xf5, 0x44, 0x47, 0xd6, 0xf5, 0xb5, 0xd7, 0x6f, 0xff, 0xf5, 0x0b, 0x3d, 0xd9, 0x1d, 0x42, 0xe9, 0xb3, 0x32, 0xa5, + 0xf6, 0xa3, 0x1b, 0xc3, 0x58, 0x8a, 0x7c, 0x24, 0xc7, 0x03, 0xbc, 0x92, 0xd5, 0x4f, 0xbf, 0xfc, 0xfa, 0x3d, 0x3b, + 0x6d, 0x8c, 0xc5, 0xdb, 0x9d, 0x77, 0x97, 0xd2, 0x5e, 0x82, 0x85, 0x53, 0x9a, 0xaf, 0xb6, 0x09, 0x45, 0x51, 0x25, + 0x90, 0x44, 0x85, 0xa4, 0xc6, 0x23, 0x18, 0xfb, 0xbb, 0x56, 0xef, 0xe9, 0x3c, 0x13, 0x62, 0xf0, 0xaf, 0x6b, 0xe9, + 0xa2, 0xa7, 0x26, 0x32, 0xa1, 0x8d, 0x5d, 0x56, 0x22, 0xa0, 0xe8, 0xb8, 0x06, 0xc1, 0x07, 0xb4, 0x7e, 0xf5, 0xbe, + 0xae, 0xff, 0xfa, 0x95, 0xa7, 0xb8, 0xe2, 0x34, 0x6a, 0xc9, 0x3c, 0xee, 0xb3, 0x45, 0x67, 0xae, 0x93, 0x6c, 0x20, + 0xbc, 0x42, 0xc5, 0xe1, 0x91, 0x52, 0xb9, 0x8c, 0x62, 0x0d, 0x46, 0xbb, 0x46, 0x72, 0x69, 0x26, 0xe0, 0xac, 0x67, + 0xec, 0xb5, 0x51, 0x5f, 0x9d, 0xae, 0x5d, 0x25, 0x15, 0x72, 0xf0, 0xc2, 0x2f, 0x67, 0xe6, 0x68, 0x08, 0xac, 0xdd, + 0xcb, 0xd5, 0xe3, 0x03, 0x9d, 0x49, 0x4d, 0xa1, 0xcd, 0x81, 0xbf, 0x09, 0xd9, 0xdd, 0x2d, 0xe1, 0x7b, 0x7f, 0x9a, + 0x7d, 0xfd, 0x92, 0xd9, 0x26, 0x19, 0x8d, 0x9d, 0x2b, 0x6d, 0x38, 0x99, 0x2b, 0x2d, 0xb5, 0xfa, 0xed, 0xe3, 0xb0, + 0x11, 0x2c, 0x17, 0x79, 0xe0, 0x24, 0xb1, 0x86, 0x68, 0x15, 0xb3, 0x7f, 0x4b, 0xf3, 0xeb, 0xd7, 0xc3, 0xdd, 0x24, + 0x64, 0x69, 0x0f, 0x4e, 0xae, 0xdb, 0xc7, 0x71, 0x4e, 0xaa, 0x64, 0x18, 0xec, 0xd1, 0x7b, 0x59, 0xa8, 0x31, 0x05, + 0x80, 0x2b, 0xcb, 0x0c, 0x91, 0x02, 0x85, 0x0d, 0x16, 0x1d, 0x1b, 0xa6, 0x6e, 0x48, 0x13, 0x04, 0xa1, 0xc5, 0xff, + 0x33, 0xa7, 0xdf, 0xb4, 0x67, 0x98, 0xb0, 0x60, 0xdb, 0x52, 0xfa, 0xaf, 0x26, 0xbf, 0x98, 0xed, 0xc1, 0x7b, 0x18, + 0x2e, 0x02, 0x9e, 0x60, 0x3c, 0xef, 0xff, 0xef, 0xad, 0xb4, 0xdc, 0xfe, 0x88, 0x74, 0x45, 0x88, 0xec, 0x01, 0xc8, + 0x71, 0x86, 0x23, 0xeb, 0xf7, 0x9d, 0x99, 0x55, 0xe0, 0x34, 0x40, 0xb2, 0xc7, 0x99, 0x95, 0xb4, 0xd6, 0x62, 0x53, + 0x71, 0xef, 0x7d, 0xef, 0x32, 0xbf, 0x8b, 0xce, 0xf8, 0x61, 0x58, 0x61, 0x32, 0x1b, 0x69, 0x87, 0x65, 0xbb, 0xb2, + 0x9c, 0x06, 0x00, 0xc1, 0xfb, 0xde, 0xfb, 0x51, 0xf8, 0xff, 0x47, 0x16, 0xe7, 0x47, 0x64, 0x81, 0x8a, 0xcc, 0x2a, + 0xce, 0xc9, 0x2c, 0x60, 0x46, 0x55, 0x00, 0x67, 0x54, 0x00, 0xfb, 0xe8, 0x80, 0x1c, 0x0b, 0x82, 0x46, 0xd3, 0x64, + 0xb3, 0x8f, 0x86, 0x6c, 0x79, 0xbf, 0xd2, 0x62, 0x05, 0x51, 0xae, 0x67, 0x64, 0x5b, 0xf2, 0xbb, 0x1d, 0x28, 0x6b, + 0x96, 0xd2, 0x4a, 0x47, 0xff, 0xeb, 0x96, 0xeb, 0x89, 0x6e, 0x15, 0x9f, 0x68, 0xa7, 0xdc, 0x30, 0x8c, 0xfc, 0x9f, + 0xc0, 0x23, 0xe1, 0x0c, 0x4e, 0xc3, 0x69, 0xa8, 0xc2, 0xd5, 0xa0, 0xa6, 0x5b, 0xc7, 0x8e, 0xb3, 0xe9, 0x34, 0x54, + 0xfd, 0x31, 0xfc, 0x1e, 0x4a, 0x0b, 0x83, 0xa9, 0x33, 0x4d, 0xd3, 0x7f, 0x77, 0x8d, 0x72, 0x55, 0x71, 0x4d, 0x74, + 0xe3, 0xaa, 0x55, 0x19, 0xf8, 0x9b, 0xa6, 0x69, 0xf8, 0x87, 0xe4, 0x6e, 0x5f, 0xac, 0xf9, 0x3d, 0xda, 0x61, 0xa0, + 0x50, 0xca, 0x2e, 0x93, 0x38, 0x3e, 0xe4, 0x5b, 0x96, 0x25, 0xd9, 0xf0, 0x75, 0x2c, 0xad, 0x37, 0x37, 0x2a, 0x15, + 0x48, 0xe8, 0xbd, 0xf6, 0x19, 0xb5, 0x55, 0xf0, 0x10, 0x5d, 0x14, 0x49, 0xa4, 0xa7, 0xff, 0xa7, 0xaa, 0x7a, 0xbc, + 0x43, 0xa6, 0x66, 0xdd, 0xd8, 0xc4, 0x05, 0xf2, 0xe9, 0x1b, 0x34, 0x4f, 0x12, 0x1a, 0x1b, 0xac, 0xf3, 0x32, 0x32, + 0xad, 0x2b, 0xeb, 0xd8, 0x29, 0x4e, 0xfe, 0x6f, 0x80, 0xa1, 0x0d, 0xad, 0x4a, 0xc2, 0xb6, 0x83, 0xa0, 0xff, 0x50, + 0x68, 0x62, 0xad, 0x71, 0x00, 0x77, 0x5a, 0x66, 0xb4, 0x05, 0x9d, 0x01, 0x51, 0x9c, 0xbb, 0xf8, 0xd3, 0x64, 0x82, + 0x69, 0xb6, 0x87, 0x82, 0xef, 0x73, 0x14, 0x62, 0x0c, 0x22, 0xcb, 0x73, 0xdb, 0xb3, 0x0f, 0x4c, 0xfe, 0x77, 0x60, + 0x45, 0xff, 0x14, 0xea, 0x9f, 0xb0, 0x02, 0xa0, 0x6e, 0xbd, 0xe4, 0xd7, 0x0a, 0xbc, 0xe7, 0xf7, 0x00, 0x44, 0x26, + 0xc2, 0x96, 0xe5, 0x37, 0xda, 0x32, 0xca, 0xef, 0x42, 0xb4, 0xdd, 0xe2, 0x70, 0xf0, 0xe0, 0xc1, 0x93, 0xd4, 0xed, + 0x18, 0xbf, 0x54, 0xdd, 0xb0, 0x5b, 0x86, 0x3e, 0x46, 0x7f, 0xbe, 0x1b, 0x61, 0x83, 0x52, 0xe1, 0x6a, 0x62, 0x7a, + 0xa6, 0x7e, 0x6f, 0xc4, 0x5b, 0x63, 0x55, 0x1a, 0xb8, 0xa5, 0x87, 0xd9, 0x84, 0xd4, 0xcf, 0xd7, 0xd4, 0x62, 0x26, + 0x28, 0x13, 0x41, 0x44, 0xca, 0x76, 0xf6, 0x21, 0x63, 0x4b, 0xae, 0xaf, 0xe7, 0xc7, 0x4d, 0x79, 0x5d, 0x8f, 0xc3, + 0x04, 0x0d, 0xc9, 0x06, 0x39, 0xa0, 0xd8, 0xde, 0x87, 0xb3, 0xd7, 0x4b, 0x65, 0x4e, 0xa3, 0xa6, 0xff, 0x79, 0xab, + 0x0c, 0xed, 0xb4, 0x01, 0x69, 0xdc, 0xa6, 0x15, 0x98, 0x98, 0x82, 0xc8, 0x86, 0x4d, 0x06, 0x77, 0xbd, 0x39, 0x6c, + 0x73, 0x52, 0x73, 0x48, 0xd6, 0xe4, 0x8a, 0x4a, 0x83, 0x9a, 0xf5, 0xc9, 0xeb, 0xa5, 0x2e, 0xa9, 0x70, 0x4b, 0x9d, + 0xb9, 0xbe, 0xc8, 0xe4, 0x9e, 0x17, 0xf2, 0xca, 0x95, 0x97, 0xd3, 0x14, 0xd8, 0x9b, 0xef, 0xb1, 0xaf, 0x13, 0x9a, + 0xf5, 0x3d, 0x8f, 0x74, 0xe3, 0x5d, 0x47, 0x07, 0x26, 0xd2, 0x60, 0xa2, 0xef, 0x11, 0x34, 0x2f, 0x6e, 0xb3, 0xfe, + 0xf0, 0xa3, 0x42, 0x7d, 0xfb, 0x47, 0x5c, 0x75, 0x98, 0x0f, 0xe6, 0x0f, 0x4e, 0xe5, 0x67, 0x1a, 0x4f, 0x93, 0x47, + 0x5f, 0x04, 0x7c, 0xff, 0x7a, 0xf9, 0x79, 0x6b, 0x46, 0x47, 0xc6, 0x0c, 0xd5, 0x90, 0x30, 0xd5, 0xfc, 0xde, 0x8b, + 0xd5, 0x65, 0x7f, 0x87, 0x2d, 0x9a, 0xd5, 0xe4, 0x3f, 0xf9, 0xed, 0x07, 0xfb, 0xa2, 0xb6, 0xd3, 0xe1, 0xbf, 0xbd, + 0x40, 0x78, 0x7a, 0x67, 0x24, 0x0b, 0x6b, 0x0e, 0xed, 0xcf, 0x7a, 0x6a, 0x7c, 0xdb, 0x36, 0x61, 0x5b, 0xc3, 0x7c, + 0x5d, 0xfc, 0xf6, 0x1c, 0xc2, 0xa9, 0xba, 0x12, 0x15, 0x35, 0x11, 0x87, 0x41, 0x13, 0xa5, 0xe5, 0x73, 0x07, 0xfa, + 0xc6, 0xe3, 0x96, 0x43, 0x01, 0x76, 0x4b, 0x53, 0x28, 0xad, 0x09, 0x7e, 0x88, 0x0f, 0x26, 0x90, 0x04, 0xfd, 0x2a, + 0x0d, 0x4c, 0xcd, 0x5c, 0xbf, 0x10, 0xd6, 0x47, 0xaf, 0xe2, 0x12, 0x80, 0x00, 0x59, 0xaa, 0x9b, 0x18, 0x58, 0x96, + 0xc8, 0x80, 0x67, 0xc2, 0xb9, 0x4e, 0x5d, 0x86, 0x1e, 0x79, 0xf5, 0xcf, 0xb0, 0x81, 0x1f, 0x9e, 0x4f, 0x34, 0x1d, + 0x7c, 0xf2, 0x4a, 0x4d, 0xbd, 0x42, 0x06, 0xbc, 0x73, 0x56, 0xbc, 0x9d, 0x43, 0xa9, 0xe6, 0x44, 0x0c, 0xcd, 0xcd, + 0xe4, 0x4e, 0xde, 0xb3, 0x0e, 0x25, 0x35, 0xb6, 0xb6, 0xf6, 0xcc, 0xae, 0x6f, 0x91, 0x82, 0x59, 0xa1, 0xdc, 0x8b, + 0xaa, 0x4f, 0x64, 0x26, 0xd0, 0xa5, 0xe7, 0x38, 0xf3, 0xf5, 0xcd, 0x4f, 0x05, 0x62, 0x8c, 0x38, 0xc3, 0x96, 0x13, + 0x68, 0xb2, 0xe4, 0xd9, 0xcf, 0x4a, 0x5f, 0x44, 0x57, 0xf6, 0x49, 0x47, 0xae, 0x16, 0x81, 0xa1, 0xa7, 0x2d, 0xd8, + 0xb3, 0x35, 0x74, 0x6a, 0xc2, 0xbc, 0xc0, 0x7d, 0xae, 0xf0, 0x88, 0xe4, 0xd0, 0x28, 0x7c, 0x22, 0x98, 0x95, 0xa3, + 0x2a, 0x81, 0x16, 0x0b, 0xc7, 0x4a, 0xf3, 0x07, 0xb8, 0xa1, 0x56, 0xbf, 0xdf, 0x36, 0x6b, 0xa3, 0x84, 0x8b, 0xbf, + 0x24, 0x99, 0xc1, 0x09, 0x7e, 0xff, 0x99, 0x8c, 0x1c, 0xd1, 0x43, 0x7c, 0xb1, 0x46, 0x9d, 0x2e, 0x65, 0x92, 0xa9, + 0xa0, 0xd0, 0x45, 0x92, 0x47, 0x37, 0x9c, 0x3c, 0x5f, 0xf1, 0xf3, 0x0d, 0x1e, 0x37, 0xeb, 0x3d, 0xb6, 0x7c, 0x33, + 0x35, 0xaf, 0xf3, 0x08, 0x54, 0x33, 0x56, 0x02, 0x4f, 0x18, 0xda, 0xc0, 0xbb, 0xc5, 0x4a, 0x42, 0xd7, 0xef, 0xbd, + 0xa4, 0xec, 0x61, 0x77, 0x1b, 0xa2, 0x57, 0x47, 0x00, 0xee, 0x8b, 0xd3, 0x56, 0xd4, 0xbd, 0x01, 0xa2, 0x8f, 0xee, + 0xef, 0xb1, 0xac, 0xe1, 0x03, 0x87, 0x8d, 0x2b, 0x3c, 0x8e, 0x15, 0x84, 0x96, 0xb4, 0xfe, 0x56, 0xd5, 0x1e, 0xc0, + 0x83, 0x66, 0x79, 0x15, 0x8a, 0x60, 0xb7, 0x15, 0x21, 0x3b, 0xce, 0x44, 0x71, 0x9f, 0x6f, 0xe0, 0x70, 0xde, 0xb8, + 0x7a, 0x74, 0x43, 0xcd, 0x4d, 0x7a, 0x90, 0xd2, 0x4b, 0x9b, 0xc8, 0x6a, 0xa2, 0xc6, 0xdf, 0x1a, 0x55, 0x85, 0x34, + 0xdd, 0x1d, 0x1a, 0x7c, 0x88, 0x7c, 0x81, 0x3d, 0xd8, 0x12, 0xf4, 0x32, 0x8d, 0xc6, 0xc1, 0x56, 0x0d, 0xe5, 0x8d, + 0x75, 0x00, 0x03, 0x61, 0x93, 0xa0, 0x44, 0x06, 0x5b, 0x67, 0x8b, 0x58, 0xf5, 0x9c, 0xb0, 0x79, 0x7f, 0xbd, 0x2e, + 0xb1, 0x17, 0xb3, 0x85, 0xcd, 0x54, 0x5f, 0xc8, 0x38, 0xeb, 0xa7, 0xcd, 0xfe, 0xbf, 0x2d, 0x80, 0x83, 0x12, 0xc3, + 0x0b, 0x02, 0x41, 0x44, 0xd5, 0x07, 0xe5, 0xcd, 0xb0, 0x24, 0x2c, 0x0a, 0x6c, 0x1b, 0x1f, 0xb9, 0x7b, 0x48, 0x9e, + 0x55, 0x42, 0x7c, 0x2b, 0x63, 0xd3, 0xd1, 0x76, 0x18, 0x61, 0xa8, 0x86, 0x2d, 0x11, 0x5a, 0x41, 0x04, 0x6c, 0xea, + 0xcf, 0x34, 0xf6, 0x71, 0xe7, 0xda, 0x41, 0xba, 0x28, 0xcb, 0x2c, 0x1c, 0x47, 0x50, 0xa7, 0x83, 0x41, 0xad, 0x84, + 0x9e, 0xec, 0x1e, 0xfc, 0xc6, 0xc6, 0xb8, 0xa0, 0xb8, 0xa1, 0x70, 0xeb, 0x5a, 0x9f, 0x46, 0x06, 0xa6, 0xf8, 0x72, + 0xa5, 0xff, 0xfe, 0x80, 0x1e, 0x07, 0xbb, 0xd4, 0x48, 0xf9, 0x6c, 0xd6, 0x13, 0xf8, 0xee, 0x86, 0x06, 0x67, 0x78, + 0x38, 0xf2, 0x83, 0xc3, 0x3b, 0x25, 0xf0, 0xa0, 0x60, 0x56, 0xbe, 0x7d, 0x10, 0x8a, 0xd4, 0x17, 0x81, 0x0e, 0x17, + 0x5f, 0x53, 0xaf, 0x87, 0x23, 0xe4, 0x56, 0xe4, 0xb1, 0xc0, 0x9d, 0xc8, 0x38, 0x25, 0x47, 0x18, 0x18, 0x27, 0x57, + 0xdf, 0x84, 0xcd, 0x7c, 0xdb, 0x31, 0xff, 0xc2, 0xe5, 0x83, 0x03, 0xd1, 0xac, 0x9f, 0x2d, 0xd8, 0xa5, 0xa4, 0x40, + 0xe0, 0x1e, 0xe9, 0x18, 0x3d, 0x85, 0xa9, 0x1b, 0x9c, 0xa6, 0x14, 0x51, 0x9a, 0x88, 0xd9, 0x42, 0x70, 0x6c, 0x6b, + 0x63, 0x2e, 0xfd, 0x46, 0xd9, 0xd5, 0xb4, 0xd9, 0x8f, 0x2c, 0xf8, 0x42, 0xf9, 0xb6, 0x27, 0xb8, 0x69, 0xc5, 0xed, + 0x5c, 0xea, 0xff, 0x76, 0x9d, 0x49, 0x1b, 0x5a, 0xf7, 0xaa, 0x2d, 0x04, 0x36, 0x45, 0x05, 0xa8, 0x99, 0x5e, 0x24, + 0x53, 0x3b, 0x89, 0xd9, 0x0f, 0x4d, 0x24, 0x27, 0x44, 0x2b, 0xfb, 0x3b, 0xd9, 0x8b, 0x36, 0xe9, 0x18, 0x4a, 0x30, + 0xfc, 0xc8, 0xa5, 0xf4, 0xd5, 0xd5, 0x72, 0x2d, 0x3b, 0x5f, 0xc3, 0x4e, 0x98, 0x0c, 0x08, 0xb2, 0xff, 0x59, 0x68, + 0x6b, 0xc0, 0xe4, 0x52, 0x8f, 0x29, 0x78, 0x74, 0x6d, 0xbe, 0xfb, 0x13, 0x8a, 0x25, 0x0b, 0x31, 0xe5, 0xd0, 0xae, + 0xbf, 0x1e, 0x13, 0x23, 0xa0, 0x2c, 0x89, 0x10, 0x6e, 0xa5, 0x1c, 0xa8, 0x7f, 0xbf, 0x62, 0x52, 0xb0, 0xa5, 0xf6, + 0x46, 0x9c, 0x5d, 0xbd, 0xac, 0x81, 0xc4, 0x46, 0xf3, 0x61, 0x62, 0x47, 0x08, 0x27, 0x4d, 0xed, 0x4b, 0x45, 0x91, + 0x48, 0xcf, 0x52, 0xc4, 0x20, 0xe3, 0x8a, 0xe9, 0x12, 0x2d, 0xac, 0x99, 0xb0, 0x1c, 0x1b, 0x91, 0xa4, 0xcc, 0x6d, + 0x11, 0x3f, 0xbe, 0xe9, 0x06, 0x24, 0x40, 0x3d, 0x62, 0x90, 0x0f, 0xbe, 0x25, 0x20, 0xd7, 0x25, 0x09, 0xca, 0xb5, + 0xcf, 0x25, 0x64, 0x42, 0x3b, 0x19, 0x09, 0x13, 0xf3, 0x46, 0x90, 0x72, 0xf7, 0x74, 0x4a, 0xd7, 0x00, 0x4b, 0x39, + 0x59, 0xcd, 0x21, 0x62, 0xe4, 0x78, 0x5d, 0x75, 0xb5, 0x80, 0x58, 0x0a, 0xb7, 0xa3, 0xed, 0xc8, 0xe4, 0x5c, 0xdc, + 0xa1, 0xf3, 0xce, 0x99, 0x5f, 0x18, 0xa7, 0x1c, 0x9c, 0x1e, 0xe6, 0x2e, 0x20, 0x20, 0xa7, 0xae, 0xfa, 0xc1, 0x19, + 0x19, 0xa4, 0xb8, 0x9a, 0x77, 0x5a, 0x24, 0x9a, 0x11, 0xf9, 0xac, 0x18, 0xaa, 0xdb, 0x2a, 0x37, 0xc2, 0x62, 0xad, + 0x5c, 0x82, 0x29, 0x72, 0x72, 0x1b, 0x7c, 0xb3, 0x83, 0xc7, 0xcd, 0x13, 0x16, 0xc0, 0x59, 0x8f, 0xe5, 0x62, 0xc2, + 0xa1, 0xea, 0x36, 0x7e, 0x0d, 0x64, 0x0a, 0xbc, 0x72, 0xd4, 0x59, 0x92, 0xe3, 0x0b, 0x0d, 0xaa, 0x81, 0xbf, 0xf6, + 0x91, 0xe7, 0x41, 0x6e, 0x50, 0x35, 0xd5, 0x34, 0x8b, 0x42, 0x4f, 0x31, 0xcf, 0x84, 0xcc, 0x5f, 0x35, 0x8a, 0x4e, + 0xc2, 0x8c, 0xa7, 0xc9, 0x96, 0x3a, 0xdd, 0xa7, 0x32, 0xa1, 0x80, 0xd8, 0x43, 0xe0, 0x14, 0xb8, 0xf7, 0xa6, 0xc2, + 0x3c, 0x9d, 0x92, 0x49, 0x1c, 0x9e, 0xcc, 0xb3, 0x59, 0x03, 0x66, 0xc0, 0x8d, 0x12, 0xe8, 0xe6, 0x8c, 0xfc, 0x70, + 0x0b, 0xb7, 0x55, 0x71, 0x1e, 0x93, 0x15, 0x68, 0xc9, 0x4d, 0x04, 0xc9, 0xf0, 0xca, 0xb8, 0x80, 0xd2, 0x7b, 0x13, + 0x67, 0xc6, 0xdd, 0xe2, 0xab, 0x8a, 0x4f, 0xc0, 0x79, 0xdc, 0x97, 0xdb, 0x8a, 0x53, 0x9a, 0x2a, 0x1c, 0x80, 0x92, + 0x17, 0xc4, 0x63, 0xe1, 0x9b, 0xd3, 0x2b, 0x99, 0x61, 0xe0, 0x62, 0x46, 0x35, 0x15, 0xdd, 0x85, 0x74, 0xc2, 0x74, + 0x90, 0xf0, 0x96, 0x34, 0x06, 0x77, 0x40, 0xf1, 0xbe, 0x00, 0x14, 0x11, 0x8e, 0xc2, 0x77, 0x76, 0x4c, 0x47, 0xab, + 0x92, 0xf0, 0x68, 0x99, 0x2d, 0xda, 0x79, 0xf9, 0x46, 0x25, 0xab, 0x1c, 0x70, 0x34, 0x00, 0x6c, 0x5e, 0x7f, 0x48, + 0x7c, 0x06, 0x81, 0x1c, 0x1f, 0x27, 0x76, 0x3e, 0x34, 0x4d, 0x95, 0xc2, 0x9f, 0x8d, 0xf6, 0x26, 0x2c, 0x70, 0xc7, + 0x29, 0x13, 0x3a, 0x1e, 0x1b, 0xd1, 0x0d, 0x41, 0xe7, 0x5f, 0xb0, 0x03, 0xb6, 0xda, 0x66, 0x7b, 0xbf, 0x7a, 0xbd, + 0x2c, 0x4e, 0x0e, 0x98, 0xe4, 0x9d, 0xcd, 0xbd, 0xb7, 0xdb, 0xf9, 0x2f, 0x27, 0x1f, 0x99, 0xb0, 0x40, 0xe1, 0x55, + 0x4e, 0x59, 0x64, 0x24, 0x3a, 0xa0, 0xc4, 0x2b, 0x4d, 0xe7, 0x62, 0x74, 0x2d, 0x12, 0xaf, 0x4a, 0xb1, 0x2b, 0x24, + 0xa9, 0x61, 0xe6, 0x0d, 0x38, 0xc8, 0x66, 0x9d, 0xa6, 0x46, 0x41, 0x11, 0xb2, 0xcc, 0xc5, 0xc6, 0x2c, 0xb1, 0x58, + 0xf3, 0x96, 0x33, 0x6d, 0x4e, 0x61, 0x44, 0xe0, 0xe4, 0x80, 0xa8, 0xfe, 0xac, 0xd6, 0xd8, 0xe0, 0xd6, 0xf3, 0x6a, + 0x18, 0x61, 0xe0, 0xdd, 0x50, 0x92, 0xf2, 0xc4, 0x18, 0x2b, 0x21, 0xc9, 0xa9, 0x23, 0x8e, 0xfd, 0xc8, 0xf2, 0x15, + 0xdf, 0xef, 0xb9, 0xc6, 0x14, 0x97, 0x07, 0x13, 0x63, 0x16, 0x43, 0xa6, 0x76, 0x83, 0xca, 0x22, 0xa9, 0x9f, 0x8e, + 0x6a, 0x59, 0x39, 0x93, 0x7b, 0x0c, 0xf7, 0x51, 0xe7, 0x92, 0xbc, 0x7b, 0x74, 0x05, 0x01, 0xd9, 0x5d, 0x82, 0xd5, + 0x27, 0x87, 0x24, 0x8a, 0x9c, 0xb0, 0x9f, 0xeb, 0x5f, 0x56, 0x23, 0x7f, 0x95, 0x63, 0x29, 0x5f, 0x0f, 0x79, 0x4b, + 0x19, 0x62, 0x2a, 0xad, 0xe5, 0x9e, 0x53, 0x90, 0x71, 0xe9, 0xb2, 0x6c, 0xf1, 0x40, 0x2c, 0x21, 0x7c, 0xb0, 0x98, + 0x7d, 0xde, 0x2e, 0x1c, 0xc8, 0xa4, 0x50, 0x7e, 0xdf, 0xe5, 0xf2, 0xfc, 0xf0, 0xc9, 0x46, 0x2d, 0xc6, 0x18, 0xa7, + 0x54, 0x5b, 0xdf, 0x38, 0xa8, 0x15, 0xa3, 0x0d, 0x3c, 0xbf, 0xb0, 0xdd, 0x6e, 0x6f, 0xd9, 0x2b, 0x20, 0x2b, 0x6b, + 0x2b, 0x70, 0x53, 0x27, 0x9d, 0x1f, 0x36, 0xc2, 0x49, 0x13, 0xca, 0x40, 0x7a, 0x39, 0x43, 0x2d, 0x90, 0x44, 0x37, + 0x45, 0x2d, 0x8c, 0x16, 0xeb, 0x5b, 0x8e, 0xbe, 0xf5, 0x6b, 0x18, 0x32, 0x4a, 0xe9, 0x98, 0xa6, 0xc3, 0xbd, 0x2e, + 0xd9, 0x77, 0x11, 0x44, 0x8b, 0x6c, 0xd6, 0x6c, 0xc3, 0x2f, 0x52, 0xae, 0xbd, 0x10, 0xde, 0x92, 0xe6, 0x28, 0xf2, + 0xce, 0x11, 0xa9, 0xa5, 0x70, 0xaa, 0xa9, 0xc7, 0x24, 0x1c, 0xbb, 0x04, 0x5a, 0x29, 0x98, 0xee, 0xe1, 0xc5, 0x4e, + 0xb6, 0xa1, 0xc2, 0x22, 0x2d, 0x04, 0x69, 0x14, 0x73, 0xf8, 0xfd, 0x20, 0x11, 0x59, 0x06, 0xd8, 0x79, 0xd4, 0xe7, + 0xc0, 0x1e, 0x0e, 0xe3, 0xd1, 0x55, 0x11, 0xfb, 0xee, 0x0f, 0x13, 0x14, 0x62, 0x9d, 0xa6, 0x09, 0x0a, 0xf7, 0x7c, + 0x84, 0x8e, 0xcd, 0x31, 0x3f, 0x9d, 0x85, 0xb6, 0x7d, 0xb3, 0x7a, 0x28, 0xbc, 0xfc, 0x2e, 0xc5, 0x3e, 0xa5, 0xb7, + 0xf3, 0x2f, 0xd3, 0x39, 0xc5, 0x3c, 0xb3, 0xeb, 0x14, 0x53, 0xa1, 0x89, 0xcd, 0x85, 0x97, 0x28, 0x12, 0xe7, 0xc3, + 0x4b, 0x69, 0xe0, 0xcd, 0xd0, 0x29, 0x91, 0x60, 0xdc, 0x08, 0x4f, 0x62, 0x14, 0x61, 0x0d, 0x98, 0xee, 0xe6, 0x3d, + 0x3b, 0xa9, 0x38, 0x77, 0xca, 0x92, 0x2b, 0xba, 0xfb, 0xb9, 0x41, 0x00, 0x40, 0xc5, 0xce, 0xe3, 0x0b, 0x9f, 0x2c, + 0xaf, 0xe5, 0xf4, 0x1c, 0x57, 0x86, 0x10, 0x5a, 0x1a, 0x71, 0x42, 0xb0, 0x91, 0x4a, 0x60, 0x5b, 0x61, 0xb9, 0x53, + 0x25, 0x4a, 0x06, 0x7d, 0x60, 0x8c, 0xec, 0x0e, 0x8a, 0x13, 0xd9, 0x10, 0xda, 0x9a, 0x8e, 0x08, 0x62, 0xe6, 0x7f, + 0x1f, 0xe4, 0x0c, 0xf0, 0xf8, 0xad, 0x64, 0x48, 0x85, 0x00, 0xcd, 0x1c, 0x2f, 0x2f, 0x03, 0x76, 0x31, 0xc4, 0x95, + 0xb2, 0xb8, 0x00, 0xc4, 0x66, 0x1f, 0x9b, 0x71, 0x90, 0xfb, 0x41, 0xea, 0x1c, 0xd6, 0x65, 0x07, 0xa2, 0xd2, 0x0b, + 0xe1, 0xf9, 0x35, 0x0d, 0xd5, 0xa4, 0x09, 0xe3, 0x75, 0xcc, 0x20, 0x66, 0x45, 0x69, 0x23, 0x05, 0x61, 0x95, 0x82, + 0x43, 0x60, 0x8e, 0x34, 0xcb, 0x84, 0xfa, 0xd2, 0x22, 0xc1, 0x1b, 0x0a, 0x01, 0xdb, 0xf1, 0x5a, 0xa2, 0x01, 0x1c, + 0x18, 0xb3, 0x61, 0x87, 0xa4, 0x95, 0x05, 0xf5, 0x40, 0xf9, 0x59, 0x5f, 0x78, 0x3c, 0x23, 0x99, 0xf0, 0xc1, 0x03, + 0x47, 0xf3, 0xa5, 0xa8, 0xe7, 0xe6, 0x44, 0x4b, 0xda, 0xe4, 0x10, 0x7f, 0x22, 0xaa, 0xb5, 0x68, 0xc5, 0x03, 0x5f, + 0x01, 0xa8, 0x90, 0xa6, 0x82, 0x4a, 0x64, 0x49, 0x59, 0x54, 0x64, 0x1e, 0x4c, 0xcc, 0xb5, 0x05, 0x56, 0xd6, 0xa8, + 0x77, 0xfd, 0x08, 0x7e, 0xa6, 0x84, 0x4a, 0xad, 0x3b, 0xc4, 0x3f, 0x65, 0xfc, 0x35, 0x84, 0x14, 0x99, 0x9f, 0x19, + 0xb9, 0xcb, 0x63, 0x9e, 0x3d, 0xb2, 0xfa, 0xb7, 0x7d, 0x1b, 0x8e, 0x2e, 0xdc, 0x63, 0x92, 0xab, 0xf7, 0x48, 0x64, + 0x64, 0x33, 0x01, 0x41, 0xb7, 0xf1, 0x7a, 0x38, 0x4a, 0xc5, 0x1f, 0x9b, 0x14, 0x6f, 0xab, 0x0a, 0xa2, 0xf6, 0xa2, + 0x85, 0x54, 0x93, 0x9e, 0x03, 0x69, 0xd0, 0x9c, 0x34, 0x6a, 0xd0, 0xb5, 0x07, 0x2a, 0x54, 0x04, 0xe5, 0x8f, 0x0e, + 0x27, 0x26, 0xca, 0xf0, 0x14, 0xee, 0x2f, 0x4c, 0x46, 0x98, 0x39, 0x02, 0x55, 0xed, 0xa2, 0xe5, 0xf3, 0x16, 0x63, + 0x02, 0x79, 0xef, 0xfe, 0x0d, 0xf3, 0x23, 0xaa, 0x61, 0xb3, 0xe5, 0xbf, 0xf9, 0x33, 0x4f, 0x29, 0x2a, 0x27, 0xc2, + 0x54, 0x48, 0xa8, 0xb1, 0xb3, 0xa4, 0xd0, 0xa3, 0x8b, 0x58, 0xc3, 0x2c, 0x3f, 0x59, 0x73, 0x75, 0x63, 0x08, 0x19, + 0x23, 0x10, 0x9c, 0x21, 0xc4, 0xa8, 0xf2, 0x44, 0x39, 0x78, 0x9b, 0x00, 0xb8, 0x04, 0xf5, 0x18, 0x2c, 0x73, 0xfb, + 0x12, 0xa1, 0xb9, 0x9c, 0xf7, 0x1f, 0x71, 0x29, 0x19, 0x29, 0x7e, 0x96, 0x97, 0x59, 0xf7, 0x52, 0x79, 0x2a, 0x6e, + 0x5d, 0xd1, 0x56, 0xdc, 0x06, 0x0f, 0x98, 0x82, 0x3e, 0xca, 0x4a, 0x6d, 0xf4, 0x69, 0x16, 0x35, 0xbb, 0x64, 0xdb, + 0x63, 0x77, 0x63, 0x79, 0x52, 0x70, 0x27, 0xbc, 0x84, 0x69, 0x19, 0x4a, 0xdd, 0x36, 0x5e, 0x8a, 0x7d, 0x38, 0xc7, + 0x79, 0xf9, 0x2d, 0x53, 0xbc, 0xff, 0x8e, 0xe2, 0xd3, 0xd7, 0x2c, 0xcd, 0x30, 0x3f, 0x3a, 0x2a, 0x94, 0xc0, 0xcc, + 0x7a, 0xac, 0xe6, 0x51, 0x12, 0x6b, 0x28, 0x40, 0x87, 0x05, 0x43, 0x7b, 0xbc, 0xde, 0x82, 0x78, 0xa8, 0xb2, 0x1e, + 0x2c, 0xbc, 0x27, 0x33, 0x74, 0xb5, 0xa4, 0x0d, 0xad, 0x6b, 0xa2, 0xa2, 0x4f, 0xef, 0x91, 0xc5, 0xdd, 0xfa, 0x38, + 0x4e, 0x9a, 0x18, 0x15, 0x97, 0xa2, 0xdd, 0x59, 0x37, 0x5e, 0x84, 0x99, 0x78, 0x8c, 0x9c, 0x11, 0x19, 0x6b, 0xe9, + 0x8c, 0x96, 0xdc, 0xba, 0x04, 0x99, 0x4f, 0x06, 0x7a, 0x27, 0x50, 0x7e, 0xfe, 0x28, 0x07, 0x8e, 0x08, 0x00, 0xb5, + 0xdb, 0x16, 0x84, 0x2c, 0x38, 0xf0, 0xbf, 0x2c, 0xb7, 0x7d, 0x9f, 0xbc, 0xb3, 0x7c, 0x31, 0x2b, 0xe0, 0x7c, 0x63, + 0xa3, 0xbd, 0x11, 0xb7, 0xb3, 0x91, 0x0d, 0x1d, 0x4f, 0x24, 0xd4, 0x1f, 0x66, 0xe6, 0xd9, 0x31, 0x1f, 0x18, 0x09, + 0xce, 0x46, 0x47, 0x60, 0xbb, 0x2a, 0x73, 0xfd, 0x37, 0x49, 0xde, 0x59, 0x12, 0x23, 0x5c, 0x51, 0x81, 0xac, 0x1e, + 0x64, 0x41, 0xb0, 0xb8, 0xa5, 0x2b, 0xba, 0xde, 0xe7, 0x15, 0x89, 0x36, 0x91, 0x29, 0xb9, 0x1e, 0x20, 0xa0, 0xab, + 0x57, 0x3d, 0x3e, 0x55, 0xf7, 0xc6, 0xfb, 0x52, 0xe3, 0x85, 0xf6, 0xf7, 0xb5, 0x9d, 0x3a, 0xdc, 0xbc, 0xe7, 0x7a, + 0x9e, 0xf6, 0x8f, 0x12, 0x75, 0x7a, 0x2d, 0x32, 0x9e, 0x87, 0xfb, 0x35, 0x94, 0xd3, 0x48, 0x35, 0x69, 0x25, 0xa1, + 0xb8, 0x11, 0xcb, 0xbc, 0xe3, 0x96, 0x07, 0xbc, 0x0a, 0xbf, 0x69, 0xb5, 0x10, 0xef, 0x7d, 0x64, 0x58, 0x9e, 0x7a, + 0x77, 0x34, 0x61, 0xf6, 0x50, 0x2b, 0xbb, 0x29, 0x26, 0x60, 0x3f, 0xad, 0xfe, 0xc9, 0xae, 0xca, 0x17, 0x17, 0xf3, + 0x3f, 0xbb, 0xae, 0xb2, 0x91, 0xf1, 0x64, 0x9a, 0xf5, 0xdd, 0xf3, 0xf9, 0x87, 0x3f, 0x7b, 0x1a, 0x4e, 0xe6, 0xc3, + 0x2c, 0xda, 0x7f, 0x29, 0xbf, 0x2c, 0x1a, 0x42, 0x5b, 0xfe, 0xe8, 0x2c, 0xf5, 0xcc, 0x42, 0xef, 0x85, 0x00, 0x3e, + 0x2d, 0xda, 0x1d, 0x1c, 0xd5, 0x74, 0x3d, 0x8c, 0xf7, 0x41, 0x0b, 0xb7, 0x2e, 0x77, 0x20, 0xce, 0x6c, 0xc4, 0x49, + 0x7e, 0x51, 0xb3, 0xeb, 0x5d, 0x36, 0xb3, 0x69, 0x97, 0xbf, 0x23, 0x08, 0x9f, 0x4d, 0x90, 0xd1, 0x3a, 0xd6, 0x36, + 0xa9, 0xbc, 0x0a, 0x2c, 0xff, 0x8d, 0xe4, 0xd3, 0xb9, 0x36, 0x8c, 0x6e, 0x05, 0xfb, 0xf9, 0xa7, 0xf0, 0x6d, 0xd5, + 0x77, 0xc7, 0x9d, 0xff, 0x7c, 0xba, 0x5f, 0xfd, 0x3b, 0xd5, 0x93, 0xb9, 0x59, 0xf4, 0xde, 0xf3, 0xe0, 0xfb, 0xd3, + 0xa0, 0xdb, 0xb6, 0x7a, 0xb2, 0x7d, 0xfc, 0x7f, 0x17, 0xef, 0xff, 0x27, 0xfa, 0xfa, 0x15, 0x7b, 0x64, 0x3e, 0xf4, + 0xe2, 0xf8, 0x6c, 0xea, 0xe2, 0xf2, 0xff, 0x5c, 0xab, 0xdb, 0x3b, 0xcf, 0x6a, 0xb4, 0x6b, 0x6e, 0xb9, 0xee, 0xb5, + 0xed, 0x32, 0xaa, 0x9c, 0xc0, 0xad, 0xff, 0x7a, 0xea, 0x2b, 0x08, 0xf2, 0x79, 0xe3, 0xe5, 0x7e, 0xf6, 0xf0, 0xb6, + 0x26, 0xb3, 0xcf, 0x96, 0x7b, 0x27, 0x2f, 0xfc, 0xbc, 0x1e, 0x6c, 0xfb, 0x54, 0xea, 0x28, 0xd5, 0xac, 0xf8, 0x61, + 0x4d, 0x72, 0xb6, 0x2b, 0xe7, 0xfc, 0xd3, 0xf2, 0x79, 0xfd, 0xff, 0xc5, 0xf3, 0x6f, 0x76, 0xba, 0x47, 0xd8, 0x6f, + 0x61, 0x5f, 0x63, 0x3f, 0xab, 0x4f, 0xe6, 0x70, 0xf5, 0x29, 0xde, 0xba, 0xee, 0x6d, 0xb5, 0x6b, 0xee, 0xe2, 0x8a, + 0x39, 0x75, 0xc9, 0x95, 0xb3, 0x7a, 0x2a, 0x88, 0x0b, 0x62, 0x11, 0x48, 0x7c, 0x57, 0xff, 0x1d, 0xdc, 0xd5, 0x43, + 0xef, 0x95, 0x8b, 0x6d, 0xcf, 0x6d, 0x02, 0xec, 0x9a, 0xc8, 0x8c, 0x11, 0x2b, 0x62, 0x1b, 0xed, 0x28, 0xf0, 0x01, + 0x8b, 0xb6, 0xcf, 0x9f, 0x12, 0x9f, 0xf5, 0xbb, 0x90, 0x6b, 0x70, 0x7d, 0x7f, 0xfd, 0x5a, 0x3c, 0x93, 0x3f, 0x08, + 0x29, 0xfa, 0xf9, 0xc0, 0x53, 0xfd, 0x8b, 0x54, 0x98, 0x42, 0x54, 0x27, 0x2c, 0x6b, 0x86, 0x7d, 0x65, 0xdf, 0x47, + 0x8b, 0x43, 0x05, 0x6a, 0x3d, 0xde, 0x27, 0x44, 0x3e, 0xaa, 0x48, 0x77, 0xf9, 0x77, 0x2a, 0x82, 0xc0, 0x88, 0x28, + 0x30, 0x34, 0xc8, 0xa7, 0x9d, 0x03, 0x7f, 0x81, 0xe5, 0xfe, 0xa2, 0xb8, 0x7a, 0xb7, 0x4b, 0x4a, 0x35, 0x5c, 0xcd, + 0x1b, 0xeb, 0x14, 0x20, 0x25, 0x36, 0x11, 0x01, 0xc3, 0x7f, 0x72, 0xe5, 0x0b, 0xb6, 0x5e, 0xe7, 0x69, 0x3e, 0x19, + 0x55, 0xa7, 0x26, 0x37, 0x5b, 0x0b, 0x23, 0x5d, 0x0b, 0xaf, 0x3a, 0x3a, 0xe1, 0x94, 0x63, 0xcc, 0x57, 0x94, 0x36, + 0x1e, 0x71, 0xa7, 0xfe, 0xf6, 0x2a, 0xfe, 0xdc, 0x80, 0x84, 0x72, 0xcb, 0x6c, 0x70, 0x95, 0x99, 0xbd, 0x56, 0x70, + 0xa3, 0x24, 0x4c, 0xf1, 0x12, 0xf2, 0x8c, 0xdf, 0x73, 0xb1, 0x32, 0x05, 0xb6, 0x69, 0x7a, 0xff, 0xc7, 0xf6, 0x24, + 0x28, 0x04, 0x3a, 0xf1, 0x52, 0x80, 0x04, 0xaa, 0xbe, 0x21, 0xc8, 0x37, 0x3d, 0xe2, 0xa0, 0xad, 0xa9, 0x8d, 0xf3, + 0x4c, 0xb3, 0x68, 0x33, 0xde, 0xd5, 0x95, 0x92, 0xb9, 0x9e, 0x11, 0x8d, 0xbc, 0xb6, 0xed, 0xf5, 0x66, 0xcc, 0xec, + 0x7a, 0x38, 0x07, 0x74, 0xbe, 0x0e, 0xa0, 0x9f, 0x55, 0x07, 0x96, 0x2a, 0x4e, 0x7f, 0xb9, 0x03, 0x32, 0xb0, 0xa4, + 0x43, 0x0f, 0x53, 0x0a, 0x9f, 0xa5, 0xf4, 0x1f, 0x01, 0x3b, 0x05, 0x0e, 0x4b, 0x39, 0x16, 0xd9, 0x8d, 0xd9, 0xcc, + 0xda, 0xd6, 0xe4, 0xa4, 0x33, 0x17, 0x51, 0xf6, 0x7c, 0x6d, 0x57, 0xff, 0x5d, 0xac, 0xfa, 0x78, 0xc9, 0xc6, 0x29, + 0x20, 0x05, 0x05, 0x05, 0xb1, 0xc7, 0xf2, 0xf3, 0xd0, 0x2f, 0x19, 0x91, 0x41, 0x34, 0xbd, 0x1a, 0x74, 0xfa, 0x79, + 0xd2, 0x5f, 0x58, 0x94, 0xd4, 0x4a, 0xe8, 0x0f, 0xb8, 0xe1, 0x03, 0x77, 0xe7, 0x8c, 0x38, 0x37, 0x84, 0xfc, 0x34, + 0xf5, 0x23, 0xe6, 0x6e, 0xe6, 0x64, 0x16, 0x3f, 0x07, 0x72, 0xd2, 0x82, 0xd5, 0xf8, 0x13, 0x36, 0x82, 0xdc, 0x37, + 0x7e, 0x69, 0xa9, 0x02, 0x47, 0x97, 0x2b, 0xe9, 0xe9, 0xd2, 0xc9, 0x62, 0xa1, 0x75, 0x70, 0x77, 0x8a, 0xe0, 0x8b, + 0xb7, 0xc2, 0x3a, 0xff, 0xe5, 0x72, 0xeb, 0xae, 0x38, 0x1b, 0x36, 0xa2, 0x7e, 0x76, 0xbf, 0xba, 0x75, 0x1a, 0xbe, + 0x47, 0xbf, 0x8b, 0x57, 0xdf, 0xf5, 0x78, 0x21, 0x47, 0xb7, 0x6e, 0x0d, 0x56, 0xf3, 0x74, 0x05, 0x45, 0x33, 0xb0, + 0x2f, 0x5e, 0x94, 0x83, 0x2f, 0x60, 0x34, 0xee, 0x78, 0x11, 0x6c, 0x0a, 0xed, 0xf3, 0xce, 0xf3, 0xe5, 0x15, 0x55, + 0x93, 0x85, 0xf4, 0x76, 0xcd, 0xc6, 0xf0, 0xfe, 0xba, 0xbd, 0xf9, 0x59, 0xfc, 0x54, 0x7c, 0x85, 0x46, 0xe8, 0xb7, + 0x0b, 0x40, 0xba, 0xfa, 0x92, 0x15, 0x8f, 0x3e, 0x6f, 0x85, 0x58, 0xcd, 0xf7, 0x8e, 0x67, 0xb1, 0x42, 0xe0, 0xe3, + 0x5b, 0xd1, 0xeb, 0x25, 0x3c, 0xb3, 0x9a, 0x75, 0x82, 0xb9, 0x03, 0x88, 0x50, 0x44, 0x1a, 0x34, 0x11, 0xe4, 0xbb, + 0xb3, 0x61, 0x2e, 0x54, 0x67, 0x35, 0x2f, 0xff, 0xbc, 0xbc, 0xa2, 0x1e, 0x51, 0x2f, 0x7e, 0x73, 0xbd, 0x81, 0x44, + 0xab, 0xae, 0x85, 0x1a, 0xbf, 0x4b, 0x8d, 0x53, 0xe6, 0x41, 0x03, 0x24, 0x69, 0xe8, 0x50, 0xcb, 0xfb, 0x10, 0x8f, + 0x8b, 0xed, 0x6b, 0x34, 0x7e, 0xdf, 0xc4, 0x5a, 0x11, 0x15, 0x79, 0x4f, 0x81, 0x2c, 0x0e, 0x94, 0x50, 0x5a, 0x5e, + 0xc8, 0xdf, 0x15, 0xa6, 0x5a, 0x64, 0xce, 0xc3, 0xc4, 0x59, 0xa0, 0xfe, 0x7a, 0xf4, 0xd4, 0xfb, 0x52, 0x07, 0x7c, + 0x63, 0x61, 0x03, 0xd7, 0x73, 0x43, 0x8d, 0x60, 0x1c, 0xa4, 0x48, 0x35, 0xa8, 0x0d, 0x33, 0x6a, 0x30, 0x79, 0x4d, + 0xc7, 0x96, 0x62, 0xaf, 0xa4, 0x3f, 0xe4, 0x99, 0x2e, 0xac, 0xf2, 0x6d, 0xd5, 0x23, 0x3b, 0xbd, 0x8d, 0x0b, 0xfe, + 0x59, 0xf3, 0xde, 0x7c, 0x8d, 0x78, 0xba, 0x6c, 0x48, 0xb0, 0xa4, 0xe7, 0xc9, 0x71, 0xeb, 0xfc, 0xa2, 0xba, 0x9e, + 0xab, 0x78, 0x04, 0x99, 0x12, 0x2e, 0x09, 0xb9, 0x8e, 0x73, 0xbd, 0x97, 0x30, 0x10, 0x21, 0x5f, 0xd7, 0x67, 0x09, + 0x50, 0xda, 0xd6, 0x97, 0x50, 0x0b, 0x1f, 0x4a, 0xb3, 0xaf, 0xdd, 0x12, 0x8e, 0xcc, 0x7d, 0x57, 0xec, 0x5d, 0x1d, + 0x39, 0x5d, 0x38, 0x24, 0x15, 0xa0, 0xef, 0xb9, 0xe8, 0xf0, 0x8d, 0xb1, 0xb0, 0x48, 0xc4, 0xa6, 0x37, 0xd1, 0x8d, + 0x66, 0xdd, 0xe0, 0x57, 0x27, 0x9d, 0x06, 0x5f, 0x1b, 0x38, 0x15, 0xb1, 0xa6, 0x00, 0x3b, 0xf4, 0xb8, 0xb1, 0x3b, + 0x40, 0x88, 0x6f, 0x5a, 0xed, 0x84, 0xce, 0xd6, 0x8d, 0x23, 0x14, 0x04, 0x03, 0xea, 0x45, 0xd4, 0x8a, 0xf2, 0xfb, + 0x4a, 0x27, 0x11, 0xf5, 0x06, 0xbf, 0x7b, 0x7d, 0xef, 0xe5, 0xa9, 0x2a, 0xbe, 0xde, 0xab, 0x07, 0x7a, 0xb2, 0x1d, + 0x90, 0xd8, 0x34, 0x15, 0x6b, 0x40, 0x93, 0x67, 0x4e, 0x81, 0xb8, 0xc1, 0x3c, 0xf7, 0x61, 0x3f, 0xc6, 0x7c, 0x8d, + 0x40, 0x8d, 0x4e, 0x84, 0x6a, 0x49, 0xa4, 0x2f, 0x57, 0x2a, 0x63, 0xdd, 0x2c, 0xe2, 0xd9, 0x45, 0x93, 0xf7, 0x7f, + 0x6f, 0x1c, 0x5c, 0xd7, 0x54, 0x50, 0x6e, 0xda, 0x33, 0xff, 0xeb, 0x9a, 0xc2, 0x06, 0xc0, 0x03, 0x7c, 0x5d, 0x42, + 0x72, 0x65, 0xc0, 0x87, 0x6f, 0x0a, 0x75, 0x5e, 0xdd, 0xe6, 0x2d, 0x64, 0x65, 0x40, 0xe4, 0xb4, 0x7d, 0x80, 0xf0, + 0x36, 0x60, 0x0c, 0x23, 0x2e, 0x40, 0xf4, 0xd1, 0x31, 0xdd, 0xaa, 0x69, 0x20, 0xee, 0xca, 0x56, 0x1f, 0xcf, 0x04, + 0xbc, 0x12, 0x7e, 0x63, 0x18, 0xc7, 0x10, 0xe2, 0x33, 0x8e, 0xed, 0xf1, 0x25, 0x54, 0x0e, 0x34, 0xca, 0x83, 0x55, + 0x79, 0xfc, 0x39, 0xf7, 0xfe, 0xea, 0xab, 0x66, 0x64, 0xd3, 0x80, 0xb9, 0xd1, 0xb4, 0xa1, 0x63, 0xc5, 0xba, 0xe4, + 0x6f, 0xbd, 0x43, 0x63, 0xb0, 0x2f, 0x5b, 0x5f, 0xc2, 0xfd, 0x4e, 0x46, 0xc3, 0x0d, 0x8c, 0xc0, 0x18, 0x0c, 0x54, + 0x95, 0x52, 0x90, 0xfe, 0xe2, 0xa5, 0x9d, 0x8b, 0x92, 0xf7, 0xa4, 0x93, 0xbd, 0x11, 0xca, 0x83, 0x42, 0x8b, 0x81, + 0x8b, 0x7e, 0x53, 0x6b, 0x25, 0xee, 0x63, 0xf9, 0xae, 0x8f, 0xd6, 0x54, 0xba, 0x99, 0x11, 0xd9, 0x52, 0x87, 0x51, + 0xdc, 0x9c, 0x3b, 0x69, 0xe6, 0xa1, 0x53, 0x60, 0x91, 0xe6, 0x66, 0x79, 0x00, 0xe2, 0x5b, 0xd4, 0xc8, 0xe6, 0x94, + 0xff, 0x89, 0x47, 0xdd, 0x40, 0x88, 0xc8, 0xb2, 0xbe, 0x6b, 0x8a, 0x33, 0x28, 0x94, 0xe4, 0x06, 0x85, 0xf0, 0xde, + 0xc8, 0xa0, 0x40, 0xc9, 0x52, 0xd9, 0x48, 0xfa, 0xfd, 0x27, 0x1e, 0x54, 0xe8, 0xe9, 0xce, 0x91, 0x64, 0xeb, 0x36, + 0x0b, 0x6b, 0x28, 0x8d, 0x32, 0x31, 0xbb, 0xd9, 0xc9, 0xb7, 0x05, 0x05, 0x45, 0x49, 0x39, 0x51, 0xa4, 0x19, 0x0e, + 0x77, 0xfa, 0x5f, 0xee, 0x51, 0xde, 0xb1, 0x40, 0xb9, 0xcd, 0x9c, 0x96, 0x00, 0x01, 0x44, 0xfd, 0x5c, 0x40, 0x34, + 0x51, 0xa4, 0x14, 0x72, 0x79, 0x23, 0x2f, 0xf3, 0xd1, 0xad, 0x79, 0xca, 0x41, 0xfb, 0xca, 0xfe, 0x94, 0x30, 0xe7, + 0xb6, 0x92, 0x3e, 0x92, 0x31, 0x31, 0x52, 0x17, 0xdc, 0xd0, 0x81, 0x61, 0xbd, 0x77, 0xe8, 0xe5, 0x53, 0x63, 0xc2, + 0xef, 0x2f, 0x82, 0x22, 0x88, 0x42, 0x00, 0x80, 0x69, 0x59, 0xb6, 0xa4, 0xf0, 0x49, 0x12, 0x05, 0x90, 0xf5, 0xb8, + 0xf4, 0xc0, 0xb5, 0x24, 0x30, 0x3c, 0xaa, 0x09, 0x68, 0xde, 0x2e, 0x50, 0x38, 0xa0, 0x85, 0x95, 0xeb, 0xb0, 0x76, + 0x42, 0xaa, 0x26, 0x45, 0xab, 0x9b, 0xd5, 0x92, 0x94, 0x67, 0x06, 0x4c, 0x15, 0x91, 0xa7, 0xf5, 0x3f, 0x64, 0xbe, + 0xb4, 0x40, 0xf4, 0xc6, 0x7c, 0x16, 0x5c, 0x3f, 0x56, 0x3b, 0x8e, 0x5e, 0x37, 0x4c, 0x6b, 0x37, 0x48, 0x02, 0x44, + 0x3e, 0x95, 0xd5, 0xd5, 0x2b, 0x15, 0xa4, 0xa1, 0xc6, 0x8f, 0x7c, 0xaf, 0x14, 0xe4, 0x4a, 0xe9, 0xa5, 0xa0, 0x00, + 0xdd, 0x78, 0xe9, 0x88, 0xa7, 0x6c, 0xe9, 0xc5, 0xa6, 0xb0, 0x71, 0xc2, 0xd8, 0xeb, 0xd9, 0x8a, 0x93, 0x7a, 0xec, + 0xaa, 0x4e, 0xb2, 0x04, 0x5d, 0x5c, 0x4b, 0x5e, 0xc5, 0x91, 0xe9, 0xd2, 0xd4, 0x31, 0xf5, 0xef, 0x1a, 0xed, 0x89, + 0x15, 0xba, 0xff, 0x2d, 0x91, 0x3b, 0xaf, 0x4c, 0xd3, 0x02, 0x41, 0xd6, 0x82, 0x90, 0xe0, 0x7c, 0x27, 0x44, 0x1e, + 0x95, 0xc7, 0xa4, 0x65, 0xee, 0xf1, 0xb5, 0x6e, 0xc6, 0x53, 0xda, 0x03, 0x51, 0x3e, 0xcc, 0x71, 0x97, 0x12, 0xe6, + 0x9e, 0x3d, 0xb0, 0x32, 0x4c, 0x4c, 0xec, 0x83, 0x1e, 0x3d, 0xae, 0x59, 0x01, 0xc1, 0x30, 0xfd, 0xda, 0xa5, 0xdd, + 0xed, 0xfa, 0x61, 0x0b, 0xe0, 0x5d, 0x2e, 0x84, 0xfa, 0xb9, 0x3a, 0x71, 0x53, 0x78, 0x75, 0x83, 0xb6, 0x8a, 0xd5, + 0x1a, 0x54, 0xb4, 0xdc, 0xa1, 0x6d, 0xeb, 0xcf, 0x69, 0x06, 0x1f, 0x3b, 0x39, 0x10, 0x6a, 0x3a, 0x22, 0x98, 0x89, + 0x72, 0x24, 0x0d, 0x9e, 0xb8, 0xea, 0x6c, 0x91, 0xaa, 0x77, 0x73, 0x02, 0x64, 0x48, 0xea, 0x0b, 0x32, 0x84, 0x36, + 0x20, 0x74, 0xac, 0xa9, 0xf2, 0xb5, 0x41, 0xed, 0xd6, 0x13, 0x63, 0x6f, 0xdf, 0x84, 0x16, 0x45, 0x85, 0xbe, 0x2d, + 0x16, 0xbb, 0x64, 0x8c, 0xbe, 0xe0, 0x6f, 0xcc, 0x7e, 0x92, 0xd1, 0xc3, 0x67, 0xb5, 0xd1, 0x45, 0x3b, 0x88, 0x5d, + 0x60, 0xfc, 0xa3, 0xc9, 0xdb, 0x9a, 0x55, 0x5c, 0x7e, 0x75, 0x41, 0x55, 0xab, 0xd9, 0x62, 0xfa, 0xb3, 0xae, 0x70, + 0x89, 0x64, 0xa2, 0xc4, 0x0c, 0x7f, 0x10, 0x68, 0xf5, 0x7d, 0xe0, 0xdc, 0xe7, 0xb9, 0x9e, 0xa0, 0xff, 0xe2, 0xa5, + 0x77, 0x28, 0xa3, 0x42, 0xc8, 0xc7, 0x91, 0x2f, 0xa4, 0x88, 0x55, 0xba, 0x7b, 0xb4, 0xd1, 0x12, 0x39, 0x0b, 0x64, + 0xcd, 0x6a, 0xca, 0x34, 0xd4, 0x85, 0x63, 0x8b, 0x2e, 0xd3, 0x6c, 0x17, 0xd0, 0x32, 0xac, 0xa4, 0x63, 0xeb, 0x9d, + 0x05, 0x84, 0x22, 0x22, 0x80, 0x29, 0x69, 0xf0, 0x9f, 0x5d, 0x69, 0x8b, 0xc5, 0xdc, 0xb4, 0x94, 0x7d, 0x2e, 0x23, + 0x31, 0xd7, 0x13, 0xb2, 0x1b, 0xb8, 0x5e, 0xdc, 0x08, 0x4d, 0x6b, 0x84, 0xe4, 0x24, 0xd1, 0xa3, 0x5e, 0xa8, 0x37, + 0x55, 0x59, 0x34, 0x7a, 0x40, 0x54, 0x03, 0xd7, 0xbb, 0x69, 0x27, 0x52, 0x12, 0x2c, 0x15, 0xdd, 0x07, 0x6e, 0xdd, + 0xad, 0x75, 0x98, 0x70, 0x85, 0x9c, 0x97, 0x50, 0x23, 0x86, 0x84, 0xfb, 0x80, 0x3d, 0x94, 0x4c, 0x00, 0x98, 0x82, + 0x13, 0x68, 0x09, 0xb0, 0xed, 0x56, 0x50, 0x02, 0x06, 0xac, 0xcc, 0x34, 0xa2, 0x30, 0xf3, 0xd0, 0x15, 0x26, 0xe4, + 0x38, 0x37, 0x8f, 0x3a, 0x58, 0x90, 0x2a, 0x44, 0xdb, 0xef, 0x4d, 0x0f, 0xe6, 0x38, 0x33, 0xce, 0x91, 0x0b, 0x80, + 0xe3, 0x2d, 0x28, 0xd5, 0x30, 0x34, 0x6c, 0xff, 0xaa, 0xc9, 0x2a, 0x67, 0x44, 0x62, 0xd5, 0x2b, 0x9b, 0xfd, 0x2a, + 0xfe, 0x18, 0x0a, 0x2a, 0x69, 0x3a, 0xbe, 0x49, 0x4c, 0x3d, 0x5b, 0x5e, 0x7d, 0x65, 0x78, 0xd2, 0xb3, 0x7d, 0xc0, + 0x15, 0x8f, 0xc0, 0xba, 0x29, 0xf9, 0x51, 0x27, 0x83, 0x06, 0xe0, 0xa8, 0x45, 0x3b, 0x54, 0x9d, 0x62, 0x10, 0x30, + 0xe2, 0x74, 0x5a, 0x96, 0xfc, 0x25, 0x8a, 0x0d, 0x34, 0xf1, 0x18, 0x2f, 0x58, 0x3a, 0xb1, 0xbd, 0xa3, 0xf9, 0xaa, + 0x44, 0x23, 0xcb, 0xac, 0x0d, 0x92, 0xfc, 0x36, 0xbd, 0xd6, 0x2a, 0x23, 0xed, 0x6d, 0xd9, 0x21, 0xfe, 0x11, 0xc8, + 0x82, 0x31, 0xa3, 0x22, 0x51, 0x31, 0x45, 0xc6, 0xa5, 0xf1, 0x56, 0xb2, 0x00, 0x5d, 0xa6, 0x67, 0x6b, 0xf3, 0x8a, + 0xbc, 0x7d, 0x12, 0xcd, 0x7d, 0x30, 0x55, 0x61, 0xff, 0x72, 0x34, 0x5b, 0x1e, 0xab, 0xf0, 0x8f, 0x55, 0x75, 0x04, + 0x9a, 0xb6, 0xab, 0xa7, 0x40, 0x8e, 0x4e, 0xd5, 0xc5, 0x21, 0x39, 0xf6, 0xc2, 0x8c, 0x43, 0x12, 0x72, 0xb2, 0x78, + 0x1b, 0xac, 0x4f, 0x32, 0xb4, 0x46, 0x80, 0x2f, 0x17, 0x61, 0xd5, 0x2b, 0xcd, 0x1e, 0x65, 0xb2, 0x1a, 0x59, 0x2b, + 0x28, 0x4d, 0x10, 0x45, 0xf3, 0x14, 0x09, 0x03, 0xcf, 0x72, 0xa2, 0x30, 0x61, 0x38, 0x25, 0xec, 0x43, 0xa2, 0x8b, + 0xf6, 0x0f, 0x33, 0xcb, 0x87, 0x12, 0xb0, 0xa5, 0x79, 0x12, 0x20, 0x46, 0x80, 0x51, 0xa5, 0x58, 0xd1, 0x3f, 0x38, + 0x4f, 0x1c, 0x0f, 0x73, 0x49, 0x22, 0x3f, 0xe3, 0xfd, 0x91, 0x79, 0xd3, 0xcd, 0xcb, 0x23, 0xdb, 0x90, 0x26, 0x66, + 0xaa, 0xa7, 0x70, 0x8d, 0xd8, 0x6e, 0xbb, 0x80, 0x2d, 0x54, 0xba, 0x41, 0xb5, 0x2f, 0x8a, 0x20, 0xf4, 0x2f, 0x75, + 0x90, 0xd6, 0xfc, 0x37, 0x47, 0x1b, 0x4c, 0x8c, 0xde, 0x64, 0x07, 0x8c, 0xfb, 0x66, 0xaa, 0xba, 0x96, 0x40, 0xc7, + 0xa6, 0x2a, 0xfc, 0x76, 0x70, 0x09, 0x89, 0xb9, 0x32, 0x16, 0xbd, 0xd5, 0x19, 0x59, 0xe5, 0xfe, 0xdf, 0x36, 0x1d, + 0x41, 0xb7, 0x7f, 0x9d, 0x5d, 0xcd, 0xce, 0x03, 0x64, 0x91, 0x07, 0x8e, 0x88, 0xa5, 0x7a, 0x6a, 0xf3, 0x68, 0x58, + 0x58, 0xaa, 0x2b, 0xc7, 0xfb, 0xb8, 0x92, 0x36, 0x9f, 0x97, 0x86, 0x03, 0x22, 0x72, 0x30, 0xbd, 0x35, 0xf0, 0x5b, + 0x24, 0x32, 0xaf, 0x6a, 0x1c, 0xd1, 0xa9, 0x8b, 0x71, 0x31, 0xae, 0x15, 0x94, 0x46, 0x7e, 0xdc, 0x49, 0x3f, 0x46, + 0x47, 0x4b, 0x1f, 0x9f, 0x6e, 0xad, 0x8a, 0xee, 0xd5, 0x2f, 0x72, 0x28, 0xe6, 0x65, 0x19, 0x1d, 0x08, 0x19, 0x24, + 0x7b, 0x4f, 0xbe, 0xf3, 0x9e, 0xb8, 0xcc, 0x45, 0x4f, 0x8d, 0x0a, 0x0e, 0xbd, 0xbd, 0x8d, 0x2c, 0x53, 0x39, 0x72, + 0x07, 0xcc, 0xce, 0xf8, 0xda, 0xde, 0x40, 0x6c, 0xef, 0x85, 0xc8, 0xad, 0xf0, 0x48, 0x61, 0xfa, 0x71, 0x65, 0x84, + 0xab, 0x31, 0xe9, 0x50, 0x99, 0x4c, 0xf3, 0xc2, 0x2e, 0x57, 0x59, 0xd0, 0x61, 0x19, 0x54, 0x33, 0x99, 0x99, 0x66, + 0xb2, 0x69, 0xa4, 0xe1, 0x0a, 0xc5, 0x34, 0x06, 0x2e, 0x97, 0x2a, 0x52, 0xf6, 0xbc, 0x92, 0xa5, 0xe7, 0x38, 0x0b, + 0x1d, 0xa6, 0x4d, 0x07, 0xcf, 0x53, 0xe2, 0x92, 0x70, 0x84, 0x35, 0x13, 0x4c, 0x93, 0xac, 0xb4, 0x40, 0xb9, 0xa8, + 0xa4, 0x18, 0xba, 0x3e, 0xaf, 0x24, 0x65, 0xee, 0x68, 0x19, 0x4f, 0x69, 0xf4, 0x8c, 0xf2, 0x15, 0xb5, 0x66, 0xfe, + 0xc9, 0xf2, 0xef, 0x20, 0x85, 0xd6, 0x57, 0x40, 0x05, 0xa6, 0x14, 0xac, 0x04, 0xf9, 0xfb, 0xc5, 0x8d, 0x56, 0x11, + 0x97, 0x82, 0xf3, 0x2a, 0xe6, 0x65, 0x53, 0x0d, 0x69, 0xbe, 0xfe, 0xe4, 0x7f, 0xa6, 0x93, 0x83, 0x4a, 0x1c, 0x6e, + 0x00, 0x33, 0x86, 0x5c, 0x2c, 0xe8, 0x4f, 0xa5, 0x57, 0x5f, 0xa9, 0x97, 0xa2, 0x46, 0x5d, 0xe8, 0xee, 0x96, 0xdc, + 0x5a, 0xcf, 0x46, 0x9a, 0x68, 0x56, 0x2a, 0xdf, 0x0f, 0x92, 0x66, 0x86, 0x1a, 0xe1, 0x62, 0x2f, 0x36, 0x60, 0xdc, + 0x1a, 0xa7, 0x50, 0x7b, 0x2f, 0x59, 0xc2, 0x67, 0x8b, 0xcb, 0x41, 0x95, 0xc2, 0x18, 0xdf, 0x81, 0xb9, 0x21, 0xf7, + 0xc1, 0x93, 0xde, 0x7e, 0xbb, 0xf3, 0x53, 0xbc, 0x0c, 0xec, 0x12, 0x11, 0x0f, 0xa2, 0xdf, 0xdc, 0x2a, 0x6d, 0xaf, + 0x37, 0x16, 0x36, 0x57, 0xc5, 0x0f, 0x2a, 0x55, 0xe0, 0xce, 0x2b, 0x77, 0x61, 0x50, 0x1e, 0x41, 0x0e, 0xfa, 0x4d, + 0xe3, 0xe6, 0x7e, 0x27, 0x54, 0x61, 0xd8, 0xa5, 0x87, 0x49, 0x59, 0xe7, 0x4b, 0x7a, 0x18, 0x33, 0xc4, 0xce, 0xcc, + 0x32, 0xa9, 0xd0, 0xae, 0x65, 0x41, 0xe3, 0xa7, 0xe0, 0x8f, 0x28, 0xa3, 0x48, 0x2b, 0x26, 0xb0, 0x0f, 0x32, 0x01, + 0xc7, 0x07, 0xc1, 0xa8, 0x2e, 0xe2, 0x13, 0x9c, 0xee, 0xce, 0x0b, 0x0e, 0x54, 0x32, 0xb4, 0x48, 0xb0, 0xc4, 0x1e, + 0xf1, 0xb0, 0xa9, 0x1f, 0xec, 0x9d, 0xda, 0x55, 0x38, 0x6f, 0x16, 0xeb, 0x31, 0x48, 0xf5, 0xfc, 0xb6, 0xf9, 0x84, + 0x03, 0xfc, 0x51, 0x9d, 0xea, 0xf1, 0x4d, 0x1d, 0xaf, 0x71, 0x08, 0xab, 0x43, 0xe5, 0x16, 0x7f, 0x52, 0x90, 0xce, + 0xb8, 0xa0, 0x87, 0xfd, 0x2b, 0x69, 0xf1, 0x05, 0x65, 0x37, 0x01, 0x1b, 0xbd, 0xf5, 0xa0, 0x04, 0xa1, 0xf3, 0xfe, + 0xe1, 0xd1, 0x7d, 0x16, 0x14, 0x6b, 0x44, 0x1d, 0x35, 0xf1, 0x6e, 0xb4, 0x9b, 0x54, 0x5c, 0x10, 0xab, 0x36, 0x5b, + 0xed, 0xb0, 0x0c, 0xd1, 0xfb, 0x37, 0x19, 0x59, 0x80, 0xa2, 0xbd, 0xe9, 0x79, 0x19, 0xac, 0x56, 0x4f, 0x13, 0x12, + 0x86, 0x6f, 0x20, 0xab, 0x29, 0x6c, 0x33, 0xdd, 0xca, 0xe8, 0x73, 0x60, 0x8e, 0x9e, 0x74, 0xd6, 0xd4, 0x82, 0xb1, + 0x65, 0xd4, 0x9f, 0x29, 0x0b, 0x27, 0x1f, 0xcb, 0xe0, 0xe7, 0x85, 0x29, 0x75, 0x07, 0x0d, 0xc9, 0x62, 0xc4, 0xca, + 0x4d, 0x3c, 0x74, 0xe8, 0xaa, 0x04, 0x83, 0xf5, 0xdb, 0x7a, 0xe3, 0xac, 0xd7, 0x38, 0x20, 0xf4, 0xde, 0x0f, 0x5c, + 0x2d, 0xfc, 0x10, 0x89, 0x11, 0xde, 0x90, 0x36, 0x47, 0x9d, 0xf1, 0xe2, 0x37, 0xde, 0x1b, 0x43, 0xb9, 0xbd, 0xae, + 0xf8, 0xa3, 0x5f, 0xd7, 0x95, 0x2a, 0x74, 0x25, 0x71, 0x66, 0xee, 0x63, 0x49, 0xd1, 0x23, 0x53, 0xda, 0xc5, 0x3d, + 0x00, 0x58, 0x98, 0x8d, 0x8a, 0xd0, 0xa4, 0x91, 0xb8, 0xfc, 0x54, 0x61, 0xa5, 0x52, 0x9f, 0x50, 0x72, 0x22, 0x30, + 0x0c, 0xbe, 0xff, 0x28, 0xd2, 0x15, 0x47, 0x3f, 0xc0, 0x3f, 0x22, 0x20, 0x50, 0x6b, 0x16, 0x69, 0xa8, 0x1d, 0x90, + 0x8c, 0x9f, 0x0e, 0x17, 0xce, 0xce, 0xcc, 0x88, 0x20, 0x53, 0x77, 0x03, 0x02, 0x84, 0xe1, 0x1a, 0x81, 0x2e, 0xff, + 0x4a, 0x49, 0xdb, 0x96, 0x3b, 0xd4, 0x61, 0x90, 0x5d, 0xe8, 0x20, 0x5a, 0x2d, 0xfa, 0xa5, 0xca, 0xf8, 0x16, 0xd1, + 0xc9, 0xfa, 0xfa, 0xfd, 0xc7, 0xe5, 0x5e, 0xe4, 0x0f, 0x6e, 0x2d, 0x00, 0x98, 0x8d, 0x38, 0x1b, 0x27, 0xbc, 0x6a, + 0x1d, 0x8b, 0x8f, 0xd2, 0x35, 0x86, 0xed, 0x14, 0xb4, 0xe2, 0x41, 0xab, 0x46, 0x54, 0x8a, 0x75, 0x7e, 0xdc, 0x2b, + 0x0f, 0xed, 0x76, 0xef, 0x87, 0xc0, 0xb9, 0x60, 0x47, 0xcc, 0x13, 0xc0, 0xbc, 0xac, 0x5c, 0x15, 0x32, 0x4d, 0xb0, + 0x11, 0x07, 0x39, 0xc8, 0xb4, 0xeb, 0x1e, 0x98, 0xb2, 0x4d, 0x8b, 0xdd, 0x2d, 0x66, 0x61, 0x03, 0x19, 0x21, 0x05, + 0x9b, 0x84, 0x0f, 0xd9, 0x32, 0x09, 0xa5, 0x07, 0x0e, 0x33, 0xd0, 0xd6, 0x7a, 0x14, 0xfb, 0x35, 0x6d, 0x13, 0x5d, + 0xb2, 0xc0, 0xa5, 0x46, 0xb6, 0x6f, 0xfa, 0x84, 0x8e, 0xc5, 0xe4, 0x86, 0xef, 0x77, 0xe7, 0xd5, 0x18, 0x96, 0xed, + 0x63, 0x65, 0x2f, 0xeb, 0xaf, 0x57, 0x2b, 0x50, 0x33, 0x9d, 0xb9, 0x7c, 0xab, 0xe4, 0xdf, 0xf5, 0x61, 0xa0, 0xf6, + 0x42, 0xe1, 0xa3, 0x98, 0x40, 0x59, 0x4b, 0xea, 0x14, 0xbc, 0x35, 0xde, 0xaf, 0xda, 0x61, 0xdc, 0xbf, 0xb9, 0x0b, + 0x15, 0x37, 0xbe, 0xfe, 0xa7, 0x9b, 0xda, 0xe0, 0xe8, 0x8d, 0x70, 0x49, 0xe7, 0x7e, 0xbd, 0x82, 0x00, 0x51, 0x6f, + 0x61, 0xca, 0x3a, 0x6f, 0xaf, 0xae, 0x6b, 0xf2, 0x68, 0x4b, 0x3f, 0xee, 0x82, 0x0e, 0x9b, 0xac, 0x64, 0x6d, 0xa1, + 0x7b, 0x64, 0x35, 0xee, 0x7e, 0x46, 0x38, 0x74, 0xb0, 0x83, 0xd4, 0x2d, 0x3e, 0xf4, 0x0e, 0xd3, 0xeb, 0x94, 0x54, + 0x6f, 0xf5, 0x9b, 0xfa, 0xcb, 0x97, 0xc6, 0xb9, 0x1a, 0x35, 0xac, 0x5d, 0xd4, 0xa4, 0x64, 0x66, 0x0a, 0xa6, 0xdb, + 0x20, 0x85, 0xab, 0xbe, 0xfa, 0xca, 0xe0, 0xc8, 0xf7, 0x73, 0x42, 0x05, 0x9b, 0x10, 0xaa, 0xc7, 0x2f, 0x88, 0xae, + 0x64, 0xfe, 0x71, 0xbb, 0x32, 0x06, 0x49, 0xe8, 0xdb, 0x11, 0x6f, 0xa5, 0xa9, 0xb3, 0x43, 0x3e, 0xe6, 0x6c, 0x82, + 0x5f, 0xd2, 0x84, 0x40, 0xb3, 0xf0, 0x2f, 0x0d, 0xd8, 0xee, 0x70, 0x6c, 0x3d, 0xd0, 0xb8, 0xf8, 0x0f, 0x94, 0x1b, + 0xd1, 0x99, 0x85, 0x1d, 0xef, 0x66, 0xe6, 0x4b, 0x87, 0xc3, 0x9e, 0x61, 0x09, 0x54, 0x65, 0x18, 0xd0, 0x0f, 0xdd, + 0x90, 0xed, 0x52, 0x1d, 0x3b, 0x07, 0x09, 0xeb, 0x3d, 0x14, 0x62, 0x3f, 0x9a, 0xab, 0xcb, 0xeb, 0xe5, 0x81, 0xfb, + 0x0a, 0xc3, 0xe5, 0xc1, 0xb0, 0xf8, 0x98, 0x15, 0x52, 0x75, 0xe9, 0xba, 0x8e, 0x3d, 0xad, 0x31, 0x20, 0x1f, 0x33, + 0x0c, 0x7f, 0x0e, 0x06, 0x8b, 0x76, 0x64, 0xdb, 0x32, 0x38, 0xc3, 0xca, 0xdb, 0x32, 0x65, 0xa6, 0xec, 0x2e, 0xd8, + 0x9e, 0x1a, 0xf8, 0xb3, 0x93, 0x94, 0x11, 0x14, 0x2a, 0xd3, 0x11, 0x34, 0xfa, 0xc7, 0x57, 0x45, 0xad, 0xc8, 0x46, + 0xd6, 0xfc, 0xb6, 0x78, 0x67, 0x8c, 0x53, 0x5a, 0x97, 0xb3, 0x7a, 0x17, 0xab, 0x46, 0x1f, 0x9a, 0x44, 0x2b, 0x92, + 0xb5, 0xaf, 0xb1, 0xc7, 0xc0, 0x10, 0x46, 0xc8, 0x72, 0xb3, 0xd6, 0x66, 0x36, 0x38, 0x89, 0xe3, 0x51, 0x07, 0xd6, + 0xdb, 0x79, 0xe5, 0x15, 0x0c, 0x02, 0xe0, 0x5f, 0x43, 0xcc, 0xb3, 0x0d, 0xfd, 0xce, 0x74, 0x53, 0xd5, 0xcb, 0x25, + 0x14, 0x46, 0x7f, 0x8c, 0x49, 0x07, 0xe5, 0xa5, 0x6a, 0x2a, 0x0d, 0x92, 0x51, 0x3d, 0x16, 0xa4, 0xa3, 0xcb, 0x73, + 0xc6, 0x67, 0x1d, 0xec, 0x69, 0xd2, 0xcd, 0x00, 0x10, 0x69, 0x87, 0x32, 0x26, 0x2a, 0x84, 0x15, 0x1e, 0x19, 0xa1, + 0xca, 0x1d, 0xf8, 0x28, 0xe0, 0xf3, 0xee, 0xb4, 0x20, 0x98, 0xd5, 0x25, 0x87, 0xb7, 0x42, 0x54, 0x14, 0xb7, 0xb2, + 0x9f, 0x90, 0xcc, 0xc7, 0x66, 0x26, 0xda, 0x6b, 0xc6, 0x9a, 0x77, 0x7f, 0x0e, 0x41, 0xa3, 0x20, 0x74, 0x58, 0x44, + 0xf3, 0x43, 0x0e, 0x83, 0xe4, 0x95, 0xd5, 0xd5, 0xc9, 0xf0, 0x5b, 0x81, 0x64, 0x05, 0x42, 0x74, 0xe2, 0x12, 0x84, + 0xde, 0x7e, 0x32, 0xec, 0x82, 0x57, 0xa0, 0x70, 0x28, 0x1c, 0x2f, 0x81, 0xcd, 0x27, 0x46, 0xc7, 0x72, 0xec, 0x74, + 0xc8, 0x55, 0x85, 0x3a, 0x59, 0x45, 0xd0, 0xda, 0x92, 0x9f, 0xf4, 0x95, 0x82, 0x98, 0x64, 0xcb, 0x96, 0x20, 0xa6, + 0x26, 0xc7, 0xc7, 0x09, 0xbd, 0x3f, 0xb1, 0x48, 0x1a, 0x92, 0x84, 0xef, 0x3e, 0xc1, 0x19, 0x23, 0x18, 0x63, 0x95, + 0x12, 0x63, 0x43, 0x59, 0x66, 0x7f, 0x38, 0x7d, 0x33, 0xc1, 0x81, 0x5f, 0x42, 0x91, 0xf2, 0x2a, 0x39, 0xe1, 0x19, + 0xc3, 0x5c, 0xca, 0xf1, 0xac, 0xe8, 0x1b, 0x75, 0xf8, 0x4b, 0x84, 0x22, 0x90, 0xe0, 0x2e, 0x2f, 0x67, 0xea, 0x8b, + 0xca, 0x4c, 0x69, 0x11, 0x6e, 0xf1, 0x1c, 0x6a, 0x8f, 0x1b, 0xb2, 0x13, 0x6f, 0xba, 0xf7, 0x7a, 0x84, 0x0f, 0x54, + 0x8a, 0x70, 0xde, 0x15, 0x83, 0xe5, 0x6e, 0x2c, 0xcc, 0xa5, 0x2f, 0x26, 0x7f, 0xa0, 0xe7, 0xb3, 0xb4, 0x9c, 0xf8, + 0xaa, 0xf9, 0xe6, 0xa8, 0x8b, 0x3f, 0xe2, 0x69, 0x89, 0x6d, 0xb9, 0xbd, 0x49, 0x2f, 0x3e, 0xdf, 0xe7, 0x7f, 0xd7, + 0x78, 0xb0, 0x50, 0xfd, 0x6c, 0x96, 0xe2, 0x06, 0xab, 0x07, 0x3e, 0x04, 0xb9, 0xc8, 0x4c, 0xe5, 0xda, 0xa6, 0xc7, + 0x9a, 0x3c, 0x6c, 0xc6, 0x3a, 0xb1, 0x5a, 0xf9, 0x36, 0xd8, 0xf4, 0x6a, 0x5b, 0xab, 0x5b, 0x13, 0xfa, 0x43, 0xad, + 0x64, 0x5b, 0xfd, 0x82, 0x07, 0x75, 0x34, 0x5f, 0x76, 0x86, 0xd5, 0xc5, 0xfe, 0x94, 0xc3, 0xa4, 0xf8, 0xbb, 0xb4, + 0xa2, 0x88, 0xfb, 0x4b, 0x06, 0x35, 0x75, 0x7e, 0x8c, 0x5f, 0xac, 0x0e, 0xa1, 0xdf, 0xc7, 0x11, 0xb5, 0x54, 0xfe, + 0x87, 0x13, 0xa5, 0x93, 0x49, 0x1e, 0xed, 0xf9, 0x34, 0x2d, 0x5e, 0xd1, 0xa5, 0xdb, 0xf1, 0x32, 0xf9, 0x56, 0x14, + 0x79, 0xbc, 0x58, 0x65, 0xc0, 0xec, 0x75, 0x68, 0xfa, 0xc9, 0xd3, 0x28, 0x39, 0x16, 0x57, 0x0c, 0x6e, 0x3d, 0x0e, + 0x1e, 0x91, 0x37, 0x35, 0xec, 0x4d, 0x28, 0x58, 0xec, 0xc0, 0x20, 0x3f, 0x06, 0x87, 0xa1, 0x43, 0x3d, 0x22, 0xde, + 0x35, 0xbe, 0x9c, 0xd4, 0x47, 0x58, 0x30, 0xab, 0x89, 0xf0, 0xdb, 0x82, 0xbc, 0x47, 0x22, 0x5a, 0x9f, 0x24, 0x8d, + 0xad, 0x74, 0xe0, 0xed, 0x2b, 0x41, 0x36, 0x39, 0xd0, 0x93, 0xde, 0xc2, 0x6c, 0xe7, 0x7c, 0xb4, 0xf2, 0xf7, 0x22, + 0xf9, 0x29, 0x24, 0xd2, 0x55, 0x15, 0x34, 0x75, 0x64, 0x1f, 0x91, 0x61, 0xed, 0x4b, 0xdd, 0xaf, 0x7d, 0x2d, 0xa4, + 0x24, 0xf8, 0xff, 0x69, 0x14, 0x0b, 0xba, 0x0b, 0x98, 0x77, 0x57, 0xc3, 0x30, 0x91, 0x93, 0xd5, 0xc4, 0x65, 0x89, + 0x6e, 0xea, 0x40, 0x61, 0x0c, 0xfb, 0x6d, 0xb4, 0x38, 0x5c, 0xd8, 0x97, 0x3c, 0x50, 0xa9, 0x5b, 0x8e, 0xe7, 0xb7, + 0x32, 0xa7, 0xf2, 0x62, 0x39, 0xa8, 0x0c, 0x5b, 0x03, 0xf0, 0x0c, 0x61, 0x18, 0x10, 0x0d, 0x39, 0x2e, 0x49, 0xb8, + 0xc2, 0xb0, 0x46, 0xf6, 0x58, 0x34, 0x52, 0x86, 0xd5, 0xc5, 0x8d, 0x2c, 0x4e, 0xa6, 0x89, 0x18, 0xce, 0xa7, 0x69, + 0x71, 0x02, 0xfc, 0xc0, 0x84, 0x1b, 0xec, 0xfa, 0xaa, 0xb0, 0x1c, 0xd0, 0x6c, 0x13, 0x1a, 0x2d, 0x52, 0x93, 0x66, + 0x95, 0x74, 0x52, 0xfe, 0x2f, 0xc7, 0x34, 0xd6, 0x19, 0xe9, 0x9c, 0x30, 0x22, 0xf2, 0x0f, 0x8d, 0x52, 0x76, 0x10, + 0xb6, 0x3a, 0x3c, 0x9c, 0x4d, 0x7e, 0x40, 0xd5, 0x46, 0xf7, 0x83, 0xaf, 0x2e, 0x64, 0xb0, 0x07, 0xc1, 0x91, 0xeb, + 0xe6, 0xa8, 0x49, 0xfe, 0x97, 0xa3, 0xfc, 0x73, 0x2e, 0x4e, 0x3a, 0x92, 0xb4, 0xb1, 0x62, 0x44, 0x64, 0x63, 0xfa, + 0x83, 0x4d, 0x9b, 0xc2, 0xa1, 0x0f, 0x0b, 0x3a, 0x9e, 0xa2, 0x40, 0x1a, 0xbd, 0xaa, 0xe4, 0xa0, 0x30, 0x19, 0x20, + 0x7b, 0x25, 0x65, 0xde, 0x2f, 0xe4, 0x32, 0xc8, 0x7c, 0xab, 0x56, 0x66, 0xcb, 0x67, 0x0c, 0xc4, 0x08, 0x37, 0xc2, + 0xe0, 0x57, 0x8a, 0xa9, 0xaf, 0x59, 0xa6, 0xb8, 0x9f, 0x86, 0x90, 0x1d, 0x12, 0x86, 0x1f, 0x68, 0x53, 0x26, 0xa7, + 0x4d, 0x13, 0x2f, 0xf5, 0xd5, 0xd5, 0x30, 0x79, 0x81, 0x4c, 0xde, 0xe0, 0x3e, 0x72, 0xdd, 0x8f, 0xfa, 0x6d, 0x93, + 0x60, 0x7f, 0x95, 0xe0, 0xff, 0x0e, 0x21, 0x5b, 0x0b, 0x60, 0x06, 0x89, 0x8d, 0xbe, 0x5d, 0xf0, 0x71, 0x51, 0xe4, + 0xeb, 0x44, 0xac, 0xa8, 0x8c, 0x4b, 0xb2, 0x5b, 0x07, 0xbb, 0xd2, 0x36, 0x18, 0x6c, 0x90, 0x68, 0x68, 0x32, 0x0d, + 0x9d, 0x2c, 0xdf, 0x2c, 0x0d, 0xc9, 0xb7, 0x65, 0x9d, 0x3b, 0x14, 0x1a, 0x49, 0x0d, 0x6e, 0xd3, 0xf2, 0x39, 0xf5, + 0x94, 0x6c, 0x78, 0x6c, 0x2b, 0x79, 0x50, 0x61, 0x3a, 0x36, 0xb3, 0x79, 0xb4, 0x62, 0x3d, 0xaf, 0xd6, 0x39, 0x24, + 0x76, 0x5b, 0x56, 0x0e, 0x56, 0x64, 0x88, 0x4f, 0x5c, 0x8f, 0xd6, 0xf6, 0xa3, 0xef, 0x63, 0x44, 0x25, 0x39, 0x18, + 0x96, 0x2d, 0x95, 0xa7, 0x16, 0x27, 0x9e, 0xda, 0xfd, 0x60, 0xfa, 0xb2, 0x48, 0x85, 0x17, 0x4d, 0xe6, 0x8b, 0xd4, + 0xa4, 0x38, 0xcc, 0xc5, 0x48, 0xcc, 0x81, 0xa5, 0x7d, 0x84, 0x8c, 0xc1, 0x52, 0x7a, 0xa4, 0xb1, 0x8d, 0x91, 0xb7, + 0xe8, 0x50, 0x2e, 0x3a, 0xfb, 0x9f, 0x59, 0x7a, 0x0a, 0x43, 0xda, 0x2c, 0x8d, 0x6b, 0xb7, 0x54, 0x5e, 0xd9, 0x0f, + 0xae, 0xb2, 0x6d, 0x1b, 0x8b, 0xa0, 0x7e, 0xb2, 0xde, 0x92, 0x4c, 0x2a, 0x70, 0x30, 0x31, 0xd0, 0x43, 0x65, 0x37, + 0x5a, 0x6b, 0x7a, 0x3c, 0x4a, 0x5b, 0xa4, 0x89, 0xb0, 0x36, 0x32, 0xaa, 0xba, 0x8a, 0xb8, 0xbd, 0xd2, 0x97, 0x7c, + 0x05, 0x18, 0x6f, 0xbc, 0xb9, 0xb9, 0x46, 0xc3, 0x1d, 0x73, 0x12, 0xc5, 0x20, 0xde, 0xad, 0x8c, 0x27, 0x4d, 0xeb, + 0xf2, 0xdb, 0x72, 0xe2, 0x53, 0xbd, 0x6e, 0x31, 0x81, 0x0c, 0xce, 0x82, 0x78, 0x3d, 0x03, 0x58, 0x65, 0x57, 0x11, + 0xd5, 0x66, 0x41, 0x82, 0x60, 0x1a, 0x5c, 0xc7, 0x1a, 0xb7, 0x39, 0xca, 0x36, 0x09, 0x7a, 0xe6, 0x68, 0x2c, 0xff, + 0x9d, 0x59, 0xe0, 0xe5, 0x45, 0x81, 0xf6, 0xc4, 0x81, 0xef, 0xc6, 0x33, 0xf6, 0xfa, 0x9f, 0x8f, 0x8c, 0x01, 0x1c, + 0xd4, 0x98, 0x93, 0xd9, 0xe1, 0x55, 0xda, 0xaa, 0xf4, 0x2a, 0xa9, 0xb2, 0x3d, 0xc4, 0xab, 0xde, 0x8c, 0x24, 0x4a, + 0xa9, 0x0b, 0xb6, 0x6c, 0xe6, 0x41, 0xe2, 0x35, 0x47, 0x7f, 0xac, 0x25, 0x92, 0xbd, 0x82, 0x86, 0x91, 0x33, 0xf1, + 0x8b, 0x4f, 0x89, 0x79, 0xa7, 0x7d, 0xc5, 0xe4, 0x79, 0x83, 0x8f, 0xe0, 0x8b, 0x4a, 0x5d, 0x34, 0xde, 0x38, 0x84, + 0x3a, 0xd6, 0x30, 0x41, 0x0a, 0x30, 0x73, 0x80, 0x8b, 0x62, 0xe5, 0x93, 0x51, 0x52, 0xec, 0x9d, 0x16, 0xdb, 0xbc, + 0x16, 0x8a, 0x57, 0xfe, 0xa2, 0x94, 0xa6, 0xf6, 0xf2, 0xa9, 0x0d, 0xe5, 0xfb, 0x0d, 0x74, 0x1a, 0xeb, 0x8d, 0xe8, + 0xa3, 0x94, 0xf2, 0xec, 0x3a, 0xe1, 0x0c, 0x8f, 0xad, 0x8a, 0x59, 0x3c, 0x58, 0x35, 0xce, 0x3e, 0x84, 0x12, 0x1e, + 0x2d, 0x5b, 0x52, 0x76, 0xf3, 0x14, 0x86, 0xbf, 0xc3, 0x4a, 0xa1, 0xa8, 0x45, 0x80, 0xc0, 0xba, 0x8d, 0x7f, 0xdc, + 0x69, 0x3a, 0x6f, 0xa7, 0xb3, 0xc1, 0xc6, 0xe2, 0x68, 0xd8, 0x1e, 0xa9, 0x32, 0xf0, 0xcb, 0xc7, 0x33, 0x6b, 0x4d, + 0x0a, 0x17, 0x78, 0xa8, 0xc2, 0xf6, 0xaf, 0xa3, 0x3d, 0x69, 0xbe, 0x23, 0xe0, 0x8e, 0x41, 0x3a, 0x01, 0xdf, 0x79, + 0x08, 0x5d, 0x00, 0xed, 0x14, 0x62, 0x17, 0x21, 0x75, 0x09, 0x72, 0x97, 0xa1, 0xed, 0x5a, 0x78, 0x40, 0x4c, 0xf0, + 0xb0, 0x32, 0xc3, 0xa3, 0xca, 0x02, 0x8f, 0x2b, 0x7b, 0x78, 0x42, 0x1c, 0xe0, 0x69, 0x65, 0x85, 0x85, 0x8a, 0xea, + 0xb2, 0xba, 0xaa, 0xae, 0xab, 0xa5, 0x32, 0xf4, 0x2b, 0x96, 0x05, 0xc6, 0xbf, 0x20, 0x46, 0xb0, 0xf8, 0xa0, 0x31, + 0xe5, 0xf6, 0xc1, 0xc3, 0x47, 0x8f, 0x9f, 0x3c, 0x0d, 0x55, 0xa6, 0xf3, 0x75, 0xd6, 0xa4, 0xe6, 0x71, 0x6b, 0xa8, + 0x23, 0xef, 0x7c, 0x39, 0xf4, 0x2d, 0x03, 0xea, 0xec, 0x69, 0x1a, 0x86, 0x2f, 0x5d, 0x7e, 0x3d, 0xf1, 0x4b, 0xc5, + 0xeb, 0xc6, 0x37, 0x66, 0x7c, 0xef, 0x8b, 0x4f, 0x13, 0x5a, 0x3c, 0xbd, 0xe0, 0x82, 0x15, 0x3c, 0x98, 0x8f, 0xf3, + 0x2e, 0x0b, 0x11, 0x75, 0xaa, 0x87, 0xc2, 0x5a, 0xf1, 0xfc, 0x83, 0x0e, 0x63, 0x2f, 0x4e, 0x11, 0xd9, 0x37, 0xe7, + 0x86, 0x88, 0xa6, 0xc9, 0xbb, 0x88, 0xaa, 0x7f, 0xb0, 0x7b, 0x29, 0x1a, 0x5d, 0x52, 0xee, 0xd3, 0xdf, 0x9f, 0xad, + 0xc8, 0xbe, 0xa9, 0xe8, 0x41, 0x71, 0x70, 0x56, 0x2d, 0x4c, 0x66, 0x93, 0xa6, 0x4e, 0x36, 0xc0, 0xf7, 0x4c, 0x0a, + 0xaa, 0x92, 0xa1, 0xf6, 0xcf, 0x1e, 0xf8, 0x4f, 0x5a, 0x77, 0xe1, 0xa7, 0xb2, 0x7e, 0xbb, 0xff, 0x9a, 0xbe, 0x2d, + 0x4e, 0x58, 0x9c, 0x58, 0x94, 0x54, 0xd2, 0x99, 0xc9, 0xa2, 0x9e, 0xd7, 0x57, 0xce, 0xcd, 0x3c, 0xc9, 0x2c, 0x9f, + 0xf6, 0x56, 0xd0, 0xd9, 0x6d, 0x80, 0x98, 0x04, 0xea, 0x35, 0x3e, 0x65, 0xf5, 0x66, 0x3c, 0xfd, 0xc4, 0xb2, 0x29, + 0x85, 0x00, 0xa7, 0xc5, 0x17, 0xff, 0xdb, 0xf1, 0x2d, 0xf9, 0x6e, 0xa6, 0x97, 0xf9, 0xfd, 0x9a, 0x6c, 0xe6, 0x46, + 0x0a, 0xdc, 0xf1, 0xcb, 0xd9, 0xe8, 0xb9, 0xc6, 0x7f, 0x33, 0xc8, 0xdb, 0xe4, 0xe9, 0x52, 0xca, 0xd5, 0xc6, 0x0e, + 0x5d, 0x6e, 0xfe, 0xa9, 0x2a, 0x8f, 0x5d, 0x5b, 0xea, 0xf8, 0xe7, 0x5d, 0x1c, 0x8f, 0x5f, 0xf4, 0x3f, 0xde, 0xe7, + 0x1e, 0xef, 0xa2, 0x66, 0x51, 0xfe, 0x3d, 0x54, 0xa9, 0xe3, 0xf7, 0xa7, 0xf9, 0xd2, 0x51, 0x3e, 0x4e, 0x4d, 0xf3, + 0x41, 0x5e, 0x46, 0x2c, 0x8f, 0xd6, 0xf4, 0xf6, 0xcf, 0x9f, 0x12, 0xff, 0x6b, 0x73, 0x9d, 0xed, 0xe1, 0xfe, 0xa4, + 0x5e, 0x6c, 0x63, 0x31, 0x22, 0x66, 0x63, 0xc1, 0x0e, 0xa8, 0xde, 0x3f, 0x3d, 0x87, 0x94, 0x65, 0xfc, 0xa7, 0xc7, + 0x0b, 0x2c, 0x9d, 0xc0, 0x9a, 0xbf, 0xed, 0x98, 0x96, 0xbc, 0xcb, 0x96, 0x63, 0x0c, 0x7d, 0xc6, 0xff, 0xe6, 0x2e, + 0xee, 0xb0, 0x5a, 0x12, 0xa5, 0x18, 0x11, 0x16, 0xfa, 0xf9, 0x8d, 0x0f, 0x42, 0xf4, 0x61, 0xe5, 0xc1, 0x54, 0xaa, + 0x4d, 0xa6, 0x9c, 0x38, 0x81, 0x0f, 0xbe, 0x1d, 0x78, 0x5a, 0x81, 0x37, 0x7f, 0xdb, 0x37, 0x2d, 0xa3, 0x63, 0xf7, + 0x92, 0xbe, 0xbc, 0x9c, 0xb7, 0x4c, 0x4b, 0xbc, 0xd4, 0xc5, 0xed, 0x49, 0x13, 0x7a, 0x67, 0x41, 0x35, 0xc9, 0xc9, + 0xa7, 0xe5, 0x13, 0x0c, 0xfb, 0x45, 0x49, 0xac, 0x9a, 0x56, 0x43, 0x63, 0xd4, 0x9b, 0x26, 0x53, 0x37, 0xb8, 0xd6, + 0xa8, 0x57, 0x81, 0x7f, 0x66, 0x40, 0xee, 0x39, 0x13, 0x7b, 0xce, 0xa0, 0x97, 0x6f, 0x7e, 0x4c, 0x9a, 0xb7, 0xa6, + 0xde, 0x16, 0x5f, 0x2b, 0xa6, 0x52, 0xa2, 0xf0, 0x7d, 0x5d, 0xb8, 0x10, 0x1f, 0x0b, 0x97, 0xab, 0x07, 0xa6, 0xe9, + 0xd3, 0x29, 0xe4, 0xfb, 0x56, 0xe0, 0x9c, 0x91, 0xa3, 0xa0, 0x0d, 0x86, 0x3c, 0x62, 0xde, 0x0f, 0x21, 0xe5, 0x73, + 0x1f, 0xc6, 0xe8, 0xf7, 0xd8, 0x08, 0x28, 0x96, 0xa3, 0xec, 0x2e, 0xc4, 0x3c, 0xcf, 0x62, 0x76, 0xd0, 0xd5, 0x72, + 0xb3, 0xee, 0x98, 0x63, 0x26, 0x56, 0xfc, 0x8c, 0xeb, 0x58, 0xc1, 0x8c, 0x7c, 0xd0, 0xa2, 0x3b, 0xfa, 0x23, 0x2b, + 0xfb, 0x3a, 0x50, 0x77, 0x12, 0x5a, 0x3b, 0x4c, 0xdf, 0x66, 0x19, 0x0e, 0x28, 0x96, 0x08, 0x12, 0x85, 0xe6, 0xf7, + 0x2a, 0x31, 0xb1, 0x52, 0x9c, 0x1a, 0xcd, 0xf1, 0x86, 0xaa, 0xc4, 0x98, 0xa0, 0xe5, 0xed, 0xea, 0x8b, 0xcc, 0x74, + 0x09, 0x1b, 0x37, 0x58, 0xd2, 0x8a, 0xfd, 0xa2, 0xa4, 0x7e, 0xdf, 0x96, 0x85, 0x8a, 0x77, 0xd9, 0xd5, 0x51, 0x5d, + 0xda, 0xa1, 0xa3, 0x22, 0x66, 0xa0, 0xe8, 0xbb, 0x9d, 0x57, 0xce, 0x46, 0xf6, 0x81, 0xdb, 0x09, 0x9c, 0x05, 0x55, + 0x79, 0x9d, 0xea, 0x50, 0x0a, 0x97, 0x05, 0xe0, 0x16, 0x38, 0x3d, 0x3d, 0x09, 0xca, 0xb3, 0xae, 0xac, 0x44, 0x57, + 0x7a, 0x37, 0xe4, 0x3f, 0xd2, 0xe8, 0xc7, 0x39, 0xe2, 0xd9, 0xe7, 0xdd, 0xe9, 0x46, 0xa7, 0xf9, 0x5d, 0xfe, 0x26, + 0xe6, 0xef, 0x2a, 0xfa, 0xf2, 0x97, 0x2d, 0x6f, 0x5f, 0x07, 0xc2, 0x60, 0x69, 0x86, 0xf8, 0xda, 0x52, 0x79, 0x8d, + 0xb9, 0x0f, 0x31, 0x4d, 0xc2, 0xc6, 0xc8, 0xa3, 0x29, 0xe0, 0x3c, 0xdf, 0xbb, 0x51, 0x7a, 0x6d, 0x4b, 0x82, 0x50, + 0xe2, 0x3d, 0xdf, 0x4a, 0xbf, 0xe7, 0x71, 0x11, 0x0b, 0x32, 0xdb, 0xd0, 0xe9, 0xf9, 0xa8, 0x8e, 0x21, 0xe6, 0xc6, + 0xd3, 0x2e, 0xec, 0xa9, 0x5a, 0xab, 0x05, 0x49, 0xd2, 0xeb, 0x3c, 0xdf, 0xfd, 0xce, 0xa4, 0x8c, 0xe0, 0x51, 0x13, + 0x24, 0x7e, 0xee, 0xeb, 0x3f, 0xef, 0x4c, 0x0d, 0x7a, 0x0b, 0x78, 0x5a, 0x3a, 0xe8, 0xc9, 0x27, 0x8e, 0x5f, 0x0b, + 0xcb, 0x6d, 0xa3, 0x4b, 0xff, 0x7d, 0x9e, 0xad, 0x4b, 0x26, 0x4c, 0xba, 0x45, 0x32, 0x1f, 0x2b, 0x13, 0xe8, 0xa9, + 0x69, 0x9d, 0x90, 0xaa, 0xfe, 0x89, 0x15, 0xd4, 0x28, 0x70, 0xa0, 0x94, 0xba, 0x9a, 0xb0, 0x10, 0xdc, 0x09, 0x8f, + 0xcf, 0x4b, 0x01, 0xd1, 0xdc, 0xbd, 0x08, 0x92, 0x8b, 0xc4, 0x6b, 0x41, 0x25, 0x56, 0x65, 0xc5, 0x65, 0x55, 0x52, + 0x09, 0xa6, 0xf0, 0x03, 0x00, 0xcd, 0x7b, 0x05, 0x4c, 0x72, 0xa0, 0x47, 0x54, 0x3a, 0xf9, 0xa8, 0x11, 0x1f, 0xf0, + 0x64, 0x93, 0xfe, 0xa1, 0xa7, 0xb8, 0x24, 0x4e, 0x9c, 0xe9, 0x50, 0x82, 0xfb, 0x63, 0xd2, 0xfa, 0x53, 0xc5, 0x7c, + 0x8b, 0x89, 0x0e, 0xea, 0xf2, 0xf6, 0xfa, 0x3a, 0xab, 0x89, 0x84, 0x1a, 0x70, 0xc3, 0x9a, 0xd6, 0x94, 0xba, 0x6e, + 0x03, 0x4d, 0x1f, 0x40, 0xdf, 0xb3, 0xea, 0xf6, 0x47, 0x85, 0xe5, 0x40, 0x6e, 0x72, 0x5b, 0x8d, 0xa2, 0x8d, 0xff, + 0x38, 0xb8, 0xa9, 0xc6, 0x29, 0x70, 0x5d, 0xcd, 0x64, 0x99, 0x80, 0xab, 0x6a, 0x8a, 0x00, 0x2e, 0xab, 0xf9, 0x09, + 0xf5, 0xbd, 0xfa, 0x82, 0x8c, 0x5f, 0xea, 0xf0, 0xf5, 0x7e, 0xae, 0x20, 0xf4, 0xce, 0x4f, 0x59, 0x5b, 0x39, 0xf3, + 0x9c, 0xf7, 0xeb, 0x94, 0x83, 0xf7, 0x1b, 0xba, 0xee, 0xf0, 0xa9, 0xce, 0xbc, 0x0d, 0xd0, 0xfe, 0x29, 0x6f, 0xde, + 0xe9, 0x29, 0x62, 0xef, 0xe4, 0x6a, 0xee, 0xee, 0xff, 0x69, 0xe8, 0x79, 0x6f, 0x78, 0xaa, 0xb4, 0x95, 0xe3, 0x4a, + 0x8f, 0xde, 0xd1, 0xbf, 0x96, 0xda, 0x02, 0x87, 0xd5, 0x54, 0x0a, 0x1c, 0x54, 0x93, 0x2b, 0xb0, 0x5f, 0xcd, 0xab, + 0x5a, 0x3b, 0x00, 0x9b, 0xd5, 0x20, 0x03, 0x7b, 0xd5, 0x64, 0x0d, 0xd8, 0xaa, 0x46, 0xbb, 0x4f, 0x1e, 0xd8, 0xae, + 0x06, 0x6b, 0x60, 0x67, 0x64, 0x5e, 0xe7, 0xed, 0xfe, 0x33, 0xf1, 0xdc, 0xc0, 0x58, 0xaf, 0xdb, 0xcb, 0x3e, 0x33, + 0xef, 0x75, 0x0d, 0x4c, 0x97, 0x65, 0x5b, 0xac, 0x5a, 0x80, 0x0d, 0xfa, 0xef, 0x48, 0xd3, 0xd6, 0x0a, 0x7e, 0x23, + 0x90, 0xc0, 0xfc, 0xec, 0x2c, 0x60, 0x01, 0xa3, 0xff, 0xd0, 0xe3, 0xd8, 0xc0, 0x50, 0x4b, 0xac, 0x4f, 0xd6, 0x31, + 0x6d, 0xd3, 0xff, 0xc7, 0xc6, 0x66, 0x1b, 0x25, 0x48, 0xb7, 0xed, 0x35, 0xbe, 0xbc, 0x65, 0x47, 0x68, 0x3f, 0x52, + 0xd4, 0xa5, 0xb4, 0x0a, 0xf0, 0x57, 0x4b, 0x72, 0xf1, 0xe8, 0xb2, 0x3d, 0x13, 0xbe, 0x57, 0x67, 0xb1, 0xce, 0x94, + 0x90, 0x88, 0x1d, 0xe2, 0xea, 0xfe, 0xbf, 0x3c, 0xf5, 0x95, 0x42, 0x65, 0x11, 0x27, 0xc5, 0x47, 0x7c, 0x4c, 0xb6, + 0x0a, 0x4e, 0x11, 0xc7, 0x42, 0x8c, 0x43, 0x37, 0x4f, 0xce, 0x61, 0xd5, 0x24, 0x0a, 0xfb, 0x47, 0xc2, 0x6b, 0xd0, + 0xf0, 0x9b, 0x6c, 0x39, 0xc0, 0xce, 0x19, 0x86, 0xd0, 0x8c, 0xbe, 0xb3, 0x9c, 0x49, 0x95, 0x93, 0x57, 0x30, 0x8e, + 0xe8, 0x58, 0xfd, 0x8e, 0x94, 0x97, 0xf7, 0xa5, 0xca, 0x97, 0x43, 0x50, 0xb6, 0x1f, 0xe0, 0x1d, 0x14, 0xc5, 0xf4, + 0xb9, 0x0c, 0x16, 0xf8, 0x5e, 0x77, 0x0f, 0x0f, 0xf0, 0xc2, 0x26, 0xfc, 0x58, 0x2b, 0x4f, 0x78, 0x67, 0xab, 0x96, + 0xd1, 0x63, 0xe1, 0x60, 0x06, 0xeb, 0x20, 0xfe, 0xaf, 0x79, 0xdd, 0x32, 0x80, 0x12, 0x38, 0xe1, 0xe6, 0x4c, 0x7b, + 0x7d, 0x9d, 0x3e, 0xb0, 0x32, 0x69, 0x8a, 0x5d, 0xf4, 0x07, 0xe6, 0x2a, 0xca, 0x6b, 0xa8, 0xe2, 0x34, 0xbb, 0x91, + 0xba, 0xc0, 0xe3, 0x7b, 0xa5, 0x3b, 0x8f, 0x3b, 0x3c, 0x74, 0xed, 0x0a, 0x8a, 0x5c, 0x23, 0x06, 0xda, 0x5d, 0x00, + 0xdd, 0x2e, 0xc3, 0xc6, 0xbf, 0xea, 0x27, 0xa9, 0x08, 0x44, 0x34, 0xe3, 0x5e, 0xf8, 0x17, 0xb0, 0xad, 0x1b, 0xdd, + 0xa2, 0x94, 0x8e, 0x2e, 0x72, 0xeb, 0xad, 0xc4, 0x9d, 0xa9, 0x64, 0xa3, 0x41, 0x0d, 0x58, 0xce, 0xbd, 0xff, 0x3b, + 0xd5, 0x5c, 0x52, 0x7f, 0xc8, 0xc4, 0x41, 0xdf, 0x9a, 0xad, 0x90, 0x05, 0xff, 0x32, 0xc9, 0x7f, 0xc6, 0x3d, 0x3e, + 0xf1, 0xd5, 0xf3, 0x90, 0x36, 0xdd, 0xb4, 0x02, 0x76, 0xd7, 0x14, 0x59, 0x9f, 0xf2, 0x71, 0x11, 0x46, 0xce, 0x82, + 0x47, 0xf8, 0x03, 0x3a, 0x09, 0x71, 0xd9, 0xfb, 0xda, 0x8b, 0xbd, 0xe8, 0xb9, 0x4c, 0xfa, 0xc7, 0xac, 0x5e, 0xa4, + 0xe3, 0x3c, 0xd4, 0x66, 0xef, 0xa8, 0x5f, 0xa3, 0x0c, 0xd5, 0x9b, 0xb3, 0x9e, 0xc3, 0x36, 0x30, 0xea, 0x4e, 0x89, + 0x56, 0x11, 0xa5, 0x1b, 0x31, 0x68, 0x28, 0x39, 0x19, 0x5f, 0xe9, 0x6c, 0xbf, 0xbb, 0xbc, 0xe3, 0x56, 0x53, 0x0a, + 0x14, 0xfb, 0x46, 0xb9, 0xc6, 0x87, 0x9f, 0x25, 0x2b, 0x22, 0xcb, 0x7a, 0xc1, 0x78, 0xf6, 0x1a, 0xd6, 0x82, 0x69, + 0x8a, 0xb6, 0x50, 0x7b, 0x71, 0x71, 0xd1, 0x84, 0x6b, 0x9d, 0xdc, 0xb8, 0x3b, 0x1f, 0x16, 0x76, 0x41, 0x09, 0xb7, + 0xbd, 0xc2, 0xd3, 0xc1, 0xdc, 0x67, 0x46, 0x28, 0x89, 0x06, 0xe0, 0x04, 0x5c, 0x3a, 0x86, 0xeb, 0xc6, 0xf1, 0x5e, + 0x03, 0x78, 0x58, 0x2f, 0xe0, 0x0c, 0x50, 0xa9, 0x78, 0x45, 0x77, 0xab, 0x1e, 0xbf, 0x3b, 0x4b, 0xf3, 0xeb, 0x44, + 0x19, 0x14, 0x96, 0x83, 0x87, 0x96, 0x32, 0xcf, 0x34, 0xa8, 0x51, 0x83, 0x8d, 0x54, 0xac, 0x90, 0x17, 0xaf, 0x79, + 0xd0, 0xba, 0xea, 0x85, 0x3d, 0x41, 0x4a, 0x3f, 0x2f, 0x73, 0x0b, 0xaa, 0x81, 0x81, 0x84, 0x58, 0x36, 0x99, 0xd5, + 0x1f, 0x1d, 0x3c, 0x77, 0xaf, 0xa6, 0x9a, 0x6c, 0xb2, 0x05, 0x99, 0xf7, 0xeb, 0xef, 0xad, 0x24, 0x5b, 0x7e, 0x71, + 0x27, 0xdb, 0x5f, 0xef, 0x97, 0x42, 0xc9, 0xe8, 0xcd, 0x38, 0x3b, 0xd6, 0x83, 0x72, 0xd6, 0x81, 0x40, 0x44, 0x7e, + 0x5b, 0x1d, 0x0a, 0xc4, 0x62, 0x32, 0x82, 0x32, 0x85, 0x19, 0x61, 0xdf, 0xd0, 0x5d, 0x1e, 0xc6, 0xdb, 0xb7, 0x13, + 0xd8, 0x4c, 0x2c, 0x28, 0xc0, 0x58, 0xdc, 0x4e, 0x4e, 0x27, 0xd7, 0x50, 0x09, 0xe6, 0x31, 0xc7, 0x50, 0x09, 0xc9, + 0xbd, 0x72, 0x66, 0xfd, 0x58, 0x64, 0x15, 0x35, 0x06, 0xc9, 0x95, 0x55, 0xc0, 0xb2, 0xb7, 0x90, 0x90, 0x71, 0xc8, + 0x28, 0x72, 0x02, 0xfb, 0x45, 0x6a, 0x46, 0x41, 0x49, 0xfc, 0x6f, 0xe6, 0x9e, 0xb9, 0x99, 0x7b, 0xe5, 0xc3, 0xb2, + 0x34, 0x29, 0x49, 0x56, 0x69, 0x13, 0xf4, 0x13, 0x3a, 0x7e, 0x89, 0xd8, 0xe9, 0xb4, 0x21, 0x34, 0xb0, 0xc7, 0x38, + 0x32, 0x82, 0xa9, 0x30, 0xa1, 0x7a, 0x57, 0x6f, 0x40, 0x12, 0x78, 0x80, 0xd1, 0xce, 0x44, 0x4e, 0x68, 0xe0, 0xc3, + 0xd9, 0x68, 0xe3, 0xe6, 0xe1, 0x77, 0x4e, 0x54, 0xaa, 0x85, 0x9d, 0xe5, 0xdf, 0x5b, 0x70, 0xa5, 0xfd, 0x4d, 0x40, + 0x95, 0xc0, 0xc5, 0xe4, 0xdf, 0xbf, 0xfb, 0x71, 0xe8, 0xdf, 0x2a, 0xe7, 0x8f, 0x16, 0x8b, 0x6f, 0x23, 0x3b, 0x5c, + 0x82, 0xb5, 0xae, 0x23, 0xe7, 0x22, 0x3f, 0x33, 0x1b, 0xaa, 0xe1, 0xf7, 0x43, 0xdd, 0xee, 0xe4, 0x42, 0xa9, 0x5a, + 0x7c, 0x32, 0x72, 0xdc, 0x51, 0xc9, 0x13, 0x89, 0x86, 0x58, 0xd1, 0xf2, 0x2b, 0x26, 0x9e, 0xd1, 0xf8, 0x52, 0xf1, + 0x48, 0x16, 0xee, 0x1f, 0xb9, 0xf6, 0x92, 0xa9, 0x83, 0x6c, 0xc0, 0x64, 0x64, 0xae, 0xfc, 0x76, 0xdc, 0x68, 0x1f, + 0xe6, 0x0f, 0x7f, 0xaa, 0x4f, 0xc4, 0xde, 0xff, 0x9a, 0x51, 0x76, 0xbd, 0x2c, 0x24, 0x3f, 0x61, 0xe1, 0x09, 0x7f, + 0x1c, 0xa1, 0xe0, 0xe5, 0xf4, 0xf1, 0x82, 0x38, 0x8e, 0x9e, 0x2b, 0x76, 0x20, 0x4b, 0x25, 0x2a, 0xee, 0x22, 0x48, + 0x42, 0x14, 0xe1, 0x09, 0xa0, 0xe4, 0x7d, 0x5c, 0x89, 0x4a, 0xb3, 0x98, 0x98, 0x4f, 0x46, 0x2a, 0x00, 0x67, 0x07, + 0xd1, 0xd0, 0x4a, 0xa4, 0x27, 0xea, 0x24, 0xa2, 0x21, 0x47, 0x67, 0x83, 0xfe, 0x9d, 0x78, 0x16, 0x1b, 0xa2, 0x22, + 0x40, 0x4c, 0x41, 0xd4, 0xb1, 0x15, 0x6f, 0x94, 0x81, 0x2b, 0xea, 0xa1, 0x44, 0x82, 0xd6, 0xd4, 0x19, 0xa0, 0x29, + 0x21, 0x20, 0xc7, 0x5c, 0xee, 0xa1, 0x87, 0x19, 0xa6, 0x6d, 0xb7, 0xab, 0xa8, 0x30, 0xde, 0x1f, 0xce, 0xcb, 0xa8, + 0xd4, 0x76, 0x0a, 0x44, 0xa9, 0x7a, 0x1a, 0xc6, 0x38, 0x1d, 0x2b, 0x84, 0x77, 0x01, 0xc5, 0x25, 0xc9, 0x4a, 0x8c, + 0xfa, 0x6e, 0x34, 0x6d, 0xaa, 0x11, 0x12, 0x38, 0xe9, 0xdd, 0xf4, 0x3a, 0x40, 0x49, 0x0c, 0x26, 0x58, 0x1c, 0xc1, + 0x66, 0xf0, 0xc9, 0xb1, 0x46, 0x90, 0x94, 0x50, 0xa0, 0x54, 0x99, 0xf1, 0x47, 0xad, 0xa4, 0x20, 0xf1, 0x3e, 0xfc, + 0xfc, 0x53, 0x65, 0xf1, 0xc4, 0x0a, 0x1b, 0xef, 0x63, 0x7e, 0x5f, 0xc9, 0xab, 0x1e, 0x84, 0x89, 0x07, 0xc4, 0xb7, + 0x09, 0x1c, 0x61, 0x99, 0xca, 0x65, 0x83, 0x0c, 0x05, 0x28, 0x38, 0xd5, 0x9a, 0xb3, 0x38, 0x13, 0x9b, 0x46, 0xaa, + 0x30, 0xe8, 0x11, 0x4c, 0x91, 0xfc, 0x8b, 0xb8, 0x7f, 0xdf, 0x06, 0xc4, 0xf8, 0x14, 0x1f, 0xfa, 0xc9, 0xeb, 0x9d, + 0x85, 0x2a, 0x98, 0x10, 0xf5, 0xe2, 0x3f, 0x8f, 0x97, 0xc5, 0xae, 0x1f, 0x1f, 0x36, 0x15, 0x48, 0x20, 0xf6, 0x3c, + 0x0d, 0xce, 0x7f, 0xc6, 0x2c, 0x09, 0x03, 0x69, 0x71, 0x6f, 0x4a, 0xe0, 0x4d, 0x2f, 0x58, 0x9a, 0x4d, 0x80, 0x09, + 0x52, 0x9c, 0x8c, 0xb6, 0x16, 0xac, 0x53, 0x4f, 0x8d, 0xd2, 0x99, 0x13, 0x60, 0x52, 0xa9, 0x87, 0x90, 0x9e, 0x7a, + 0x81, 0xde, 0xb1, 0xa2, 0x1f, 0xe3, 0xad, 0x86, 0xb7, 0xec, 0x6a, 0x91, 0x0a, 0x8b, 0xd0, 0x19, 0x08, 0x2e, 0x0b, + 0x4e, 0xf1, 0xfb, 0x08, 0x75, 0x0d, 0xc3, 0x9a, 0xb1, 0xc9, 0x89, 0x1a, 0x2a, 0xc8, 0xb4, 0xee, 0xe9, 0x60, 0xef, + 0x65, 0xde, 0x24, 0xcc, 0x9c, 0x0f, 0x47, 0x94, 0x6c, 0x78, 0xe3, 0x1e, 0x4f, 0x3f, 0x20, 0xdd, 0x19, 0xa4, 0x4f, + 0x30, 0x3d, 0xa6, 0x50, 0x12, 0x41, 0x73, 0x5f, 0x5e, 0x92, 0xab, 0x47, 0x87, 0xbd, 0x52, 0x37, 0xdd, 0x2f, 0xf7, + 0x72, 0xd2, 0xb8, 0x85, 0xe9, 0x2a, 0xec, 0x76, 0xf7, 0xa3, 0x7e, 0x10, 0x38, 0xea, 0xa5, 0x9a, 0x66, 0xa0, 0x66, + 0x92, 0x62, 0x67, 0xf2, 0x56, 0xca, 0x37, 0x8e, 0xa5, 0x17, 0xd4, 0x79, 0x5a, 0x33, 0x6f, 0x72, 0x9f, 0x15, 0x8a, + 0xb2, 0xc2, 0xda, 0xa1, 0x8c, 0x61, 0xa8, 0x92, 0xe1, 0x71, 0x1a, 0xc1, 0xba, 0x28, 0x8a, 0xb6, 0xe8, 0x3a, 0x73, + 0x34, 0xa7, 0x5d, 0xa5, 0x4b, 0xb2, 0xc4, 0xf7, 0xe8, 0x47, 0x13, 0x95, 0xfd, 0x25, 0x7a, 0x91, 0x5a, 0x5a, 0x99, + 0xb6, 0x77, 0xd7, 0xd4, 0xf1, 0x3b, 0x1b, 0x85, 0x3f, 0xba, 0xc1, 0x67, 0xa6, 0xf3, 0xd1, 0x06, 0x37, 0x96, 0xee, + 0x08, 0x67, 0xb0, 0x6d, 0x63, 0x3f, 0xef, 0x03, 0x46, 0x85, 0x0f, 0xa8, 0xbe, 0x9e, 0xe6, 0x1d, 0xae, 0x1d, 0x71, + 0x53, 0x5b, 0xcf, 0xff, 0x66, 0x3a, 0x07, 0xe5, 0x07, 0x7c, 0xc0, 0xa6, 0xcf, 0xf6, 0x16, 0x2c, 0x95, 0xaf, 0x3b, + 0x01, 0x63, 0x49, 0xd5, 0x55, 0x98, 0xad, 0xd9, 0xd2, 0x60, 0x80, 0xe2, 0x22, 0x3f, 0x73, 0x2a, 0x88, 0x70, 0x89, + 0x4c, 0x70, 0x03, 0x45, 0x1f, 0x50, 0x42, 0x99, 0xb1, 0x08, 0x0f, 0xc6, 0x57, 0x98, 0x48, 0x8c, 0xf4, 0x27, 0x14, + 0xc6, 0xe3, 0x8e, 0x7f, 0x7e, 0xce, 0xcf, 0xbb, 0x66, 0xa7, 0xbd, 0xc2, 0xd8, 0xc4, 0xee, 0x59, 0xe8, 0xf8, 0x83, + 0x9c, 0xfd, 0xce, 0xfc, 0x45, 0x30, 0xad, 0xf3, 0x17, 0xc2, 0x7e, 0xe6, 0x44, 0x82, 0xbf, 0xf6, 0xd4, 0xf6, 0x06, + 0x62, 0x39, 0x11, 0xa5, 0x94, 0xfa, 0xc6, 0xbc, 0x55, 0x83, 0x05, 0x50, 0xc2, 0xec, 0xa7, 0x51, 0x7f, 0x6d, 0xe3, + 0x4f, 0x1d, 0x5a, 0x17, 0x4c, 0xbd, 0x16, 0x30, 0x64, 0x86, 0x11, 0x2d, 0x58, 0x13, 0x69, 0x64, 0xe6, 0x8f, 0x33, + 0xb9, 0x90, 0xf3, 0x3e, 0xf3, 0xe7, 0x19, 0x9f, 0x73, 0xea, 0xb7, 0xd5, 0xe6, 0x4a, 0xce, 0xd0, 0x5f, 0xc5, 0xb3, + 0xb7, 0x97, 0x18, 0xdd, 0xf5, 0x0e, 0x62, 0x24, 0xf6, 0x95, 0x3e, 0x9c, 0xfe, 0x73, 0x77, 0x8e, 0x5c, 0x06, 0x3c, + 0x9e, 0x8b, 0x15, 0x67, 0x7e, 0x80, 0xf2, 0x34, 0xb7, 0x36, 0x4e, 0x10, 0xa9, 0xc9, 0xd2, 0xb8, 0xf2, 0x7c, 0x2f, + 0xe3, 0x60, 0x41, 0x76, 0x6c, 0x87, 0x3d, 0xd3, 0xf7, 0xb4, 0xd7, 0xd7, 0x1e, 0xc8, 0x88, 0x3f, 0x97, 0xbe, 0x9f, + 0x40, 0x94, 0xab, 0xad, 0xa7, 0x2a, 0xaa, 0xe6, 0x5e, 0x1e, 0xac, 0xf3, 0x2b, 0x2f, 0xfd, 0xc9, 0xd3, 0x4e, 0xf7, + 0xe5, 0x6e, 0xdd, 0x80, 0x4c, 0x71, 0xa2, 0xf6, 0xc9, 0xc7, 0x0c, 0x11, 0xc5, 0xc5, 0x6f, 0x5c, 0x4f, 0xef, 0x30, + 0xe1, 0x7b, 0x5f, 0x20, 0xcb, 0x47, 0x2a, 0x71, 0xc1, 0x7a, 0x4e, 0x53, 0x63, 0xf9, 0x2e, 0xbb, 0xfd, 0xa2, 0x6d, + 0x83, 0x31, 0xe9, 0xd1, 0x8c, 0xcf, 0xfa, 0x6f, 0xac, 0x03, 0x00, 0x16, 0x7f, 0x97, 0xf8, 0x4a, 0xac, 0xe6, 0xb9, + 0xc9, 0x12, 0x5b, 0x71, 0xd5, 0x78, 0x5e, 0x27, 0x72, 0x90, 0xdd, 0x64, 0x87, 0x08, 0x4d, 0x11, 0x31, 0xed, 0xa5, + 0x7a, 0xbd, 0x41, 0xdf, 0x41, 0x84, 0x85, 0x8a, 0xea, 0x4c, 0x3f, 0x69, 0x0a, 0x33, 0x46, 0xa7, 0x23, 0x40, 0xe5, + 0x80, 0xa4, 0x2f, 0x0f, 0xbe, 0x7d, 0x25, 0x64, 0x05, 0xee, 0x72, 0xe7, 0xb2, 0x90, 0x02, 0xfb, 0xf0, 0xa1, 0xe9, + 0x6f, 0xcf, 0xf3, 0x3c, 0x57, 0x59, 0x3c, 0x8f, 0x7f, 0x92, 0x1c, 0x26, 0x26, 0xda, 0x1a, 0x45, 0x3c, 0xd1, 0x02, + 0x6f, 0x7f, 0xd1, 0x14, 0x09, 0x57, 0x95, 0xc2, 0x8a, 0x02, 0xbd, 0x6a, 0x74, 0x49, 0x50, 0xbc, 0x2b, 0x93, 0x40, + 0x67, 0x70, 0x5d, 0x32, 0x58, 0xb0, 0x3b, 0x15, 0xd2, 0x73, 0x6a, 0x2e, 0xd8, 0xce, 0x04, 0x78, 0x7d, 0x48, 0xe5, + 0xc6, 0x2c, 0x55, 0x48, 0x59, 0x54, 0xe7, 0x05, 0x78, 0xdb, 0xe3, 0xa0, 0xd5, 0x89, 0xc2, 0xde, 0x6b, 0x01, 0x68, + 0xc0, 0xf2, 0xb9, 0xcd, 0x03, 0x5b, 0x72, 0x80, 0xa6, 0x41, 0xd3, 0x31, 0x80, 0xec, 0xef, 0x7c, 0x95, 0xf4, 0xbf, + 0xbd, 0xe3, 0x4f, 0xeb, 0x16, 0x0c, 0x21, 0x63, 0x36, 0x4f, 0x9f, 0xb5, 0x68, 0x08, 0x14, 0x6f, 0xa3, 0x48, 0xc4, + 0x9f, 0x59, 0xab, 0x2a, 0x0d, 0x0c, 0xb9, 0x0e, 0x83, 0x5a, 0xa5, 0x9d, 0xcc, 0x99, 0x96, 0x59, 0xa9, 0x53, 0xb5, + 0xb0, 0x7b, 0x80, 0x0a, 0x3c, 0xa8, 0xde, 0x4b, 0x0d, 0x2a, 0x07, 0x18, 0x8a, 0xe2, 0xa2, 0x0c, 0x9d, 0x8a, 0x7b, + 0xfa, 0x3e, 0x4f, 0xb1, 0x09, 0xff, 0xf9, 0xb2, 0xf2, 0x8d, 0xe7, 0x20, 0x5e, 0x4a, 0xff, 0xb9, 0x53, 0x7e, 0x8c, + 0xbc, 0x86, 0xfa, 0xea, 0x2a, 0x0a, 0x73, 0x3c, 0x62, 0xbc, 0xb3, 0x31, 0x34, 0x02, 0xb1, 0x94, 0xe2, 0x09, 0xe1, + 0xc5, 0x36, 0x0a, 0x3e, 0x87, 0x0a, 0xb4, 0x19, 0x01, 0x58, 0xb8, 0xbb, 0x16, 0xfc, 0xcb, 0xd7, 0x90, 0xbf, 0x57, + 0x3c, 0xa2, 0xa9, 0x4c, 0x6e, 0x57, 0xa7, 0xec, 0x6b, 0xb8, 0xc2, 0xe8, 0xed, 0xfb, 0xbe, 0x5e, 0xe6, 0xeb, 0x4e, + 0xff, 0xe1, 0x13, 0x3e, 0x76, 0xa7, 0xfd, 0x65, 0xe7, 0x61, 0x9d, 0x91, 0x7f, 0x3c, 0x36, 0x79, 0x1b, 0xd6, 0xb4, + 0x1b, 0xec, 0x65, 0x8f, 0x89, 0xc3, 0x4c, 0x3c, 0x14, 0xe3, 0xdf, 0x16, 0x15, 0x38, 0xe6, 0x85, 0x06, 0x52, 0x6b, + 0x7f, 0x4e, 0x1f, 0xff, 0xaa, 0xb0, 0x43, 0xcc, 0x0e, 0xac, 0x04, 0x81, 0xee, 0x7b, 0x05, 0x6e, 0x29, 0x5d, 0x0a, + 0xb4, 0xf5, 0x68, 0x51, 0x2e, 0xae, 0xef, 0x01, 0x21, 0xb5, 0xb6, 0x59, 0xd5, 0x65, 0xa2, 0x71, 0x29, 0x8e, 0x57, + 0xa7, 0x3e, 0xfa, 0x03, 0x2d, 0xf6, 0xd9, 0xc5, 0x16, 0x9a, 0x5a, 0x88, 0x33, 0x71, 0x36, 0x2e, 0xb8, 0x19, 0x37, + 0xeb, 0xce, 0x81, 0x0a, 0x7d, 0x35, 0x18, 0xca, 0x92, 0xd0, 0xda, 0xc0, 0x10, 0x4c, 0x2b, 0x37, 0x58, 0x14, 0x25, + 0xdd, 0x51, 0x2f, 0x8e, 0xb6, 0x0d, 0x2e, 0xdc, 0x46, 0x8c, 0x72, 0xbc, 0x65, 0x7f, 0x81, 0x2a, 0x61, 0xfe, 0x92, + 0x59, 0xe4, 0x5d, 0x93, 0xce, 0x9f, 0x23, 0x3b, 0x10, 0xb3, 0xd4, 0x96, 0xb5, 0x5a, 0x85, 0x9b, 0x09, 0xf9, 0xa6, + 0x7b, 0x8a, 0x42, 0x81, 0x6d, 0x53, 0xb9, 0x8b, 0xff, 0x3d, 0xe2, 0x6a, 0xe7, 0x1c, 0xf9, 0x37, 0x9b, 0xe6, 0xb9, + 0x9e, 0x89, 0x03, 0xa2, 0x9c, 0xae, 0x82, 0x99, 0xc3, 0x70, 0xc7, 0x3d, 0xf5, 0xf3, 0x22, 0x3d, 0xcf, 0xa8, 0x63, + 0x25, 0xb7, 0xef, 0xd4, 0x2f, 0xfc, 0x52, 0x3c, 0xf6, 0x0b, 0x7d, 0x61, 0xcf, 0x95, 0x78, 0x4b, 0xb7, 0x4f, 0x4e, + 0xa2, 0xd5, 0xa8, 0x9c, 0x9a, 0x76, 0xe1, 0x25, 0xd4, 0x6c, 0x6f, 0x68, 0xaf, 0xcc, 0x2d, 0x7a, 0xd9, 0x1d, 0xee, + 0x57, 0x76, 0x8a, 0x22, 0x76, 0xa5, 0x60, 0x9f, 0x56, 0xd2, 0xe3, 0x4a, 0x9c, 0x73, 0xa1, 0xb3, 0x4e, 0x2d, 0xa0, + 0x28, 0xcb, 0x00, 0x2b, 0x2f, 0x15, 0xfa, 0x6d, 0xc5, 0x13, 0x94, 0x1c, 0xa6, 0x36, 0x1b, 0x47, 0xcf, 0x7a, 0x49, + 0x25, 0xf7, 0xd5, 0x06, 0xf7, 0x92, 0x91, 0xd6, 0xde, 0xe1, 0xf2, 0xce, 0x56, 0x1f, 0xf1, 0xb4, 0x87, 0xfb, 0x8f, + 0x59, 0x81, 0x7f, 0xab, 0xca, 0xfb, 0x86, 0x31, 0x14, 0x02, 0xb5, 0xce, 0xa5, 0xd4, 0xb4, 0x49, 0xb8, 0x64, 0x10, + 0xee, 0x1d, 0xac, 0x11, 0x51, 0x27, 0xb0, 0xbf, 0x46, 0xc9, 0x6a, 0x67, 0xc0, 0xe7, 0x49, 0x88, 0x98, 0x13, 0xe5, + 0xb1, 0x7f, 0x7e, 0xb7, 0xb2, 0xc9, 0x9f, 0x98, 0x43, 0x9d, 0xa1, 0x4a, 0x58, 0x87, 0xf8, 0x83, 0xb8, 0x79, 0xd5, + 0xeb, 0xdb, 0x25, 0xca, 0xdf, 0x4c, 0x4f, 0x2c, 0xcc, 0x0a, 0x2b, 0xf8, 0x4b, 0x29, 0x5f, 0xdf, 0xf1, 0x01, 0xd4, + 0x67, 0x93, 0x1f, 0xff, 0xbc, 0xa1, 0x7b, 0xd9, 0x95, 0xff, 0x72, 0x87, 0x40, 0x31, 0xed, 0xe2, 0x70, 0x8e, 0x4b, + 0x87, 0xc2, 0xec, 0x02, 0xc3, 0xe2, 0x45, 0x55, 0x1d, 0xf0, 0xe1, 0x39, 0xe2, 0xe3, 0xf3, 0x24, 0x2e, 0x88, 0x84, + 0xd2, 0xfc, 0x79, 0x50, 0x37, 0xa3, 0xe3, 0xc2, 0x86, 0x3e, 0x38, 0x9c, 0xd1, 0x00, 0x84, 0xac, 0xb1, 0xc9, 0xf6, + 0x63, 0x95, 0x52, 0x99, 0x59, 0x3a, 0x72, 0xc7, 0xc6, 0x76, 0xb5, 0xd4, 0xe3, 0xbb, 0x7e, 0x1f, 0xee, 0x64, 0xd3, + 0xb2, 0x7e, 0xca, 0x10, 0xfb, 0xa8, 0x0b, 0xc3, 0x05, 0xc8, 0xda, 0x0f, 0xb9, 0xf6, 0x62, 0x19, 0xdb, 0x80, 0x3e, + 0xc4, 0xfe, 0xa7, 0x5d, 0x9c, 0xd1, 0xad, 0xf0, 0xb1, 0x58, 0xb4, 0x3a, 0xdb, 0x90, 0x24, 0x07, 0x46, 0x73, 0x48, + 0x30, 0x6e, 0x44, 0x68, 0x1b, 0x94, 0xe0, 0xb1, 0x62, 0x0a, 0x37, 0xe2, 0xfe, 0x38, 0x58, 0x68, 0x55, 0xd1, 0x8d, + 0xb9, 0x8d, 0x6d, 0x14, 0x67, 0xf0, 0xf5, 0x80, 0x7f, 0x15, 0x65, 0x7c, 0x80, 0xbb, 0x41, 0xe4, 0xce, 0x9e, 0x97, + 0x92, 0x48, 0x2d, 0xa7, 0xdb, 0x56, 0x6c, 0xe7, 0x97, 0xd8, 0xed, 0x82, 0x3d, 0x5f, 0x16, 0xe6, 0xcc, 0xd6, 0x20, + 0x33, 0x8c, 0xbd, 0xb7, 0xc0, 0xbb, 0x6d, 0x29, 0x4c, 0x76, 0xe9, 0x1b, 0xa8, 0x84, 0x56, 0xe7, 0xa3, 0xc3, 0x78, + 0x53, 0x07, 0xae, 0xe2, 0x78, 0x1a, 0xdb, 0x56, 0x62, 0x34, 0x46, 0x1e, 0xc9, 0x30, 0x95, 0xe1, 0x10, 0x7f, 0x24, + 0xbb, 0x29, 0x37, 0xd3, 0xa5, 0xce, 0x2e, 0x0d, 0x10, 0x74, 0x85, 0x55, 0x0f, 0x85, 0x24, 0x11, 0x70, 0xcb, 0x15, + 0xc8, 0xc3, 0x70, 0x3f, 0xaf, 0xc6, 0xc8, 0xe1, 0x6c, 0x81, 0xd0, 0xf0, 0xb2, 0x51, 0x90, 0x39, 0xf1, 0xed, 0x21, + 0xf1, 0x72, 0x6a, 0x7a, 0xc7, 0x11, 0x0f, 0x86, 0xea, 0x36, 0x0f, 0x5e, 0x8e, 0xaa, 0x4e, 0x67, 0xe9, 0x91, 0x70, + 0x4b, 0xe7, 0x59, 0x49, 0xca, 0x51, 0x35, 0x05, 0x7a, 0x8e, 0x34, 0x1a, 0xca, 0x5b, 0x5b, 0x29, 0x81, 0x55, 0xd0, + 0x32, 0x39, 0xfd, 0xbc, 0x23, 0x12, 0x91, 0x70, 0x21, 0xa0, 0xf8, 0xcb, 0x28, 0xa4, 0xd1, 0x5b, 0xcd, 0xc7, 0x30, + 0xc8, 0x70, 0x9d, 0x57, 0x5c, 0x0a, 0xfe, 0xf8, 0xc5, 0x01, 0xf4, 0x50, 0x94, 0x0d, 0xdc, 0x2f, 0x16, 0xfe, 0xcc, + 0x2e, 0x46, 0xf4, 0x36, 0x9b, 0xa1, 0xba, 0xcd, 0xe8, 0x27, 0xd6, 0xe7, 0x95, 0x22, 0x76, 0xcf, 0x0e, 0xed, 0xc1, + 0x8e, 0x19, 0x59, 0x5d, 0x25, 0x1d, 0xcd, 0x04, 0x99, 0xf4, 0x32, 0xf2, 0x0c, 0x41, 0x84, 0x0e, 0xd8, 0x27, 0x87, + 0x36, 0x4a, 0x87, 0xf9, 0x0a, 0xc2, 0x3f, 0xc7, 0x7c, 0x0e, 0x89, 0x6e, 0x76, 0x09, 0x8e, 0x7a, 0x8d, 0x48, 0x3a, + 0x89, 0x50, 0x04, 0x5e, 0xc8, 0x7a, 0x22, 0x98, 0x78, 0x41, 0xef, 0x26, 0xb8, 0xe2, 0xc5, 0xd1, 0x4d, 0x07, 0xcb, + 0x61, 0x46, 0xfc, 0x1b, 0x13, 0x46, 0xee, 0x12, 0xe2, 0xdb, 0x03, 0x84, 0x3b, 0xd8, 0x29, 0x88, 0xea, 0xe5, 0x56, + 0x9b, 0x5e, 0x9c, 0xa2, 0x9e, 0xc7, 0xf9, 0x78, 0x36, 0xd6, 0x91, 0x17, 0x72, 0x38, 0x5b, 0xc4, 0x30, 0x40, 0x16, + 0xc2, 0x93, 0x9b, 0x76, 0x97, 0x10, 0x90, 0x9c, 0x4c, 0x65, 0x59, 0xde, 0xc4, 0x4d, 0x27, 0x60, 0x91, 0xe7, 0x76, + 0x69, 0x4a, 0xf1, 0xf4, 0x9f, 0xaa, 0xb1, 0x0d, 0x67, 0x8b, 0x8c, 0x63, 0xd0, 0x62, 0x95, 0xce, 0x20, 0x10, 0x17, + 0xe5, 0x46, 0x4b, 0x2f, 0x0e, 0x73, 0xb8, 0xf9, 0xf7, 0xb8, 0xbc, 0x8d, 0x09, 0x20, 0x1f, 0xbc, 0x49, 0x3a, 0x40, + 0xcf, 0xf2, 0x7c, 0xce, 0xd0, 0x4b, 0x6f, 0x73, 0x91, 0x4c, 0x84, 0xff, 0xd3, 0xc9, 0x47, 0xa2, 0x1c, 0xe9, 0x15, + 0x72, 0x9c, 0x50, 0x51, 0xb2, 0x9d, 0x10, 0xd5, 0xcb, 0xc3, 0x7f, 0x61, 0xd5, 0x11, 0x02, 0xe7, 0xdb, 0x84, 0x2f, + 0x5f, 0x6e, 0xf9, 0xc1, 0xd7, 0x97, 0xec, 0x44, 0x28, 0xe5, 0x1f, 0x18, 0x87, 0x98, 0x56, 0x32, 0xb1, 0x63, 0x40, + 0x64, 0x7a, 0x58, 0xc0, 0x72, 0xe0, 0x66, 0xe4, 0xf1, 0xe3, 0xd6, 0x38, 0xd3, 0x14, 0x9f, 0xab, 0xff, 0x9f, 0xd8, + 0x7a, 0x10, 0xd7, 0x6e, 0x2f, 0x8d, 0x48, 0x62, 0x1a, 0xa3, 0x01, 0xf3, 0x8a, 0x06, 0x68, 0x9c, 0x94, 0x01, 0xc3, + 0x5e, 0x59, 0xfa, 0x85, 0x1e, 0x63, 0x93, 0x47, 0xaa, 0x99, 0x98, 0x1f, 0x21, 0x64, 0xbb, 0x46, 0xc1, 0x44, 0x12, + 0x8c, 0xf6, 0x2d, 0x50, 0xd8, 0x81, 0x14, 0x53, 0xdd, 0x01, 0xf9, 0x9c, 0xcb, 0xc8, 0x6b, 0x20, 0x1b, 0x7d, 0xbe, + 0xb9, 0xd7, 0xaf, 0x13, 0xfb, 0xd2, 0xa3, 0x39, 0x84, 0x48, 0x23, 0xf2, 0xfb, 0xf0, 0xfe, 0x58, 0xaf, 0x99, 0x77, + 0xbd, 0xca, 0x14, 0x2f, 0xc1, 0xc8, 0x07, 0x37, 0x96, 0x90, 0x0f, 0x1a, 0xac, 0x02, 0x73, 0xf2, 0x35, 0xaa, 0xb5, + 0x43, 0xcc, 0xce, 0xf3, 0x26, 0x47, 0xde, 0x76, 0x75, 0x54, 0x51, 0x58, 0xad, 0xc0, 0xf9, 0x55, 0x03, 0xad, 0xc4, + 0x07, 0xf2, 0x2f, 0x43, 0xa2, 0x8a, 0x09, 0x61, 0x80, 0x1e, 0x19, 0xe7, 0x1f, 0x84, 0x28, 0xe8, 0x32, 0xa9, 0x5a, + 0x36, 0xfb, 0x97, 0x9a, 0xc3, 0x55, 0x60, 0x04, 0xec, 0x36, 0xa6, 0x31, 0x8d, 0xe7, 0xe3, 0x28, 0x66, 0xd6, 0xbc, + 0x2b, 0x89, 0xaf, 0x70, 0x2e, 0x08, 0x2a, 0xac, 0xe1, 0xbe, 0xcb, 0xff, 0xfd, 0x7c, 0xfc, 0x90, 0x97, 0x62, 0xe7, + 0xd7, 0xe5, 0x1a, 0xfa, 0x61, 0xff, 0x75, 0x29, 0x56, 0xbd, 0x49, 0x2d, 0x7a, 0x37, 0x9a, 0x36, 0x8e, 0xff, 0x7c, + 0x76, 0xb1, 0x91, 0x4e, 0xef, 0x78, 0xcb, 0x7b, 0xd0, 0x37, 0xa7, 0xe9, 0x69, 0x5c, 0xe0, 0xe7, 0x2c, 0x2f, 0x67, + 0xff, 0x95, 0xbb, 0x94, 0xc7, 0xf5, 0x7b, 0x76, 0xdd, 0xa1, 0x39, 0xad, 0xbd, 0xb1, 0xec, 0xdd, 0xb3, 0x2b, 0xfe, + 0x1e, 0x81, 0x2c, 0xbe, 0x08, 0xc9, 0xa4, 0x52, 0x09, 0x20, 0xd0, 0x5c, 0x0f, 0x7e, 0xf7, 0xc4, 0x28, 0xa5, 0x1e, + 0xef, 0x3f, 0x26, 0x5f, 0x95, 0x75, 0xb8, 0x3b, 0xb7, 0x40, 0xd6, 0x23, 0xfd, 0x3b, 0x4f, 0x37, 0xba, 0x5f, 0xd0, + 0xa8, 0x3a, 0x75, 0x90, 0x19, 0x8d, 0x33, 0x2d, 0x0d, 0xf9, 0xb7, 0x8d, 0xe6, 0x8c, 0xc2, 0xb7, 0x82, 0x46, 0x74, + 0x13, 0xe1, 0x1f, 0x57, 0x8d, 0x03, 0x4a, 0x0a, 0xf8, 0x61, 0x9b, 0xf6, 0x6d, 0xf7, 0x72, 0x2f, 0xa4, 0xa9, 0xf2, + 0xcb, 0x33, 0x16, 0x18, 0xb4, 0x0f, 0x74, 0x66, 0x47, 0xff, 0x7f, 0x0a, 0x68, 0xbd, 0x88, 0x51, 0xb2, 0x95, 0x3a, + 0x40, 0x5c, 0x6c, 0xe3, 0xe6, 0x0b, 0xbd, 0x71, 0x9a, 0x0b, 0x67, 0x1e, 0xf5, 0xe8, 0x24, 0xdd, 0x02, 0x18, 0xd5, + 0xfc, 0x7e, 0xc4, 0xab, 0x53, 0x57, 0x46, 0x7c, 0x54, 0xbc, 0xa3, 0xbb, 0x0b, 0xcc, 0xf6, 0xbf, 0xf2, 0x2e, 0x46, + 0x34, 0x7f, 0xf7, 0x11, 0xe8, 0x86, 0x1f, 0xb3, 0xd3, 0x37, 0x9f, 0xf9, 0xe3, 0x03, 0x3e, 0x0c, 0xed, 0x1e, 0xa3, + 0x79, 0x67, 0xdc, 0x9a, 0x27, 0x3c, 0x31, 0xc8, 0x0c, 0xe0, 0xb2, 0xcf, 0xde, 0x7b, 0x2c, 0xe3, 0xc0, 0x77, 0x20, + 0x56, 0x26, 0xf3, 0x16, 0x30, 0x29, 0x17, 0x23, 0xa4, 0x35, 0x32, 0xfa, 0x37, 0xe0, 0x45, 0xc9, 0xe8, 0x9f, 0xce, + 0x3d, 0x8a, 0x6e, 0x48, 0xf4, 0xc9, 0x93, 0x01, 0xcb, 0x3a, 0x28, 0x5a, 0x62, 0x52, 0x21, 0x3a, 0x84, 0x2c, 0x13, + 0xa0, 0xf4, 0x49, 0xa0, 0xa1, 0xf0, 0x77, 0x2d, 0x27, 0xbd, 0x9f, 0x7b, 0x66, 0x82, 0xa4, 0xc7, 0xe4, 0x28, 0x8d, + 0x4c, 0x18, 0xf9, 0x73, 0xcd, 0xcb, 0xeb, 0xeb, 0xa7, 0x76, 0x7b, 0xd0, 0x7c, 0x64, 0xbf, 0x95, 0xe6, 0xc4, 0xe4, + 0x6b, 0xad, 0x06, 0x2b, 0x79, 0x03, 0x28, 0x9b, 0x7d, 0x41, 0x2b, 0x60, 0xf1, 0x5b, 0x0d, 0x61, 0xe9, 0x99, 0x0c, + 0xb4, 0x06, 0x4e, 0xd2, 0x73, 0x36, 0xb8, 0x6e, 0x98, 0x1f, 0x91, 0x5e, 0xaf, 0x98, 0xa8, 0x32, 0xa7, 0x27, 0x7d, + 0xba, 0xb9, 0x1e, 0x7b, 0xb1, 0xd0, 0x87, 0xd4, 0x13, 0xfa, 0x93, 0x17, 0xe1, 0x6c, 0xf9, 0xb9, 0xec, 0x3f, 0x4d, + 0x20, 0x75, 0xd5, 0x18, 0x2d, 0x74, 0x7e, 0x3d, 0xbe, 0x9b, 0x35, 0x3e, 0x1a, 0xd9, 0xea, 0x6d, 0xbb, 0x73, 0x64, + 0xb9, 0x77, 0x8b, 0x59, 0x5f, 0x42, 0x3e, 0xa3, 0x58, 0x33, 0x99, 0x83, 0x9c, 0x23, 0xb4, 0xbf, 0xd6, 0x95, 0xe4, + 0xb8, 0xf6, 0x61, 0x4e, 0x41, 0x7a, 0x6c, 0x0d, 0xeb, 0x20, 0x6a, 0xbe, 0xad, 0x7d, 0x06, 0x2d, 0xbf, 0x9e, 0x7a, + 0x9d, 0x16, 0x4c, 0xf2, 0xa4, 0x73, 0x5f, 0xf7, 0x8f, 0x34, 0xe2, 0x5e, 0x7a, 0x59, 0x13, 0x45, 0xb7, 0x48, 0x40, + 0xd7, 0x2a, 0x2d, 0xf4, 0xb2, 0xe2, 0x3c, 0xad, 0xe8, 0x4f, 0x33, 0xe6, 0x51, 0xc9, 0xaa, 0x51, 0xa9, 0x9e, 0x5c, + 0x63, 0x9c, 0x29, 0xeb, 0x09, 0x20, 0x17, 0x45, 0x02, 0xc7, 0x59, 0x6f, 0xd7, 0xa7, 0x4b, 0x43, 0x07, 0xf1, 0xd1, + 0xdb, 0xb8, 0xe9, 0xbc, 0x83, 0x69, 0x2c, 0xdd, 0x9f, 0x48, 0x67, 0x19, 0xc3, 0x89, 0x2a, 0x4b, 0xf2, 0xb4, 0x1c, + 0x85, 0xba, 0xa3, 0xbb, 0x20, 0x29, 0x4b, 0xf6, 0x46, 0x3b, 0xfb, 0xe3, 0x7a, 0xf2, 0x28, 0xfb, 0x30, 0xec, 0xa1, + 0x0a, 0xdc, 0x43, 0xaa, 0xef, 0x72, 0xff, 0xba, 0xcc, 0x94, 0xa6, 0xc1, 0xfe, 0xc7, 0xd7, 0xa1, 0x03, 0x3f, 0x0e, + 0x6e, 0xc7, 0x11, 0x12, 0x28, 0xb7, 0x98, 0xa6, 0x0c, 0x5b, 0x4e, 0x30, 0xd9, 0xee, 0x0d, 0x37, 0xc5, 0xd5, 0x9e, + 0x4b, 0x14, 0x83, 0x25, 0xf7, 0xc0, 0xcb, 0x67, 0xb4, 0x7f, 0x62, 0xeb, 0x26, 0xe6, 0xa9, 0x6b, 0xe1, 0xa3, 0xd4, + 0xc2, 0x34, 0x74, 0x60, 0xb0, 0xc8, 0x59, 0x92, 0x8c, 0x04, 0xbb, 0xfc, 0xd2, 0x6a, 0x27, 0xcf, 0x72, 0x25, 0xd3, + 0xd7, 0x5e, 0x4f, 0x4c, 0x31, 0xd2, 0xb0, 0xa5, 0xed, 0x70, 0xd8, 0xc9, 0x79, 0x02, 0x22, 0x44, 0x54, 0xcf, 0x97, + 0xb8, 0xa6, 0xbe, 0x10, 0x67, 0xdd, 0xf9, 0x32, 0x56, 0xb4, 0xe7, 0x41, 0x01, 0x08, 0xad, 0x36, 0xad, 0x54, 0x17, + 0xdc, 0xd0, 0x23, 0x48, 0x77, 0xeb, 0xe5, 0x1d, 0x14, 0x55, 0xcd, 0xf4, 0x60, 0xd2, 0x8b, 0x1f, 0xe7, 0x5d, 0xe1, + 0x61, 0x16, 0x19, 0x2a, 0x80, 0x1b, 0xa3, 0xef, 0xe0, 0x72, 0x7d, 0xcf, 0x43, 0xb8, 0xb5, 0xe6, 0x4c, 0xcf, 0x4f, + 0x5b, 0x8f, 0x78, 0xf1, 0xe6, 0x61, 0x1c, 0xc2, 0x5d, 0x6c, 0x7d, 0xfa, 0x24, 0x5f, 0x3b, 0x6c, 0xe7, 0xd1, 0xa2, + 0xd0, 0xd6, 0xe5, 0xd4, 0xf6, 0xe2, 0xce, 0xe7, 0xf9, 0x27, 0xb5, 0x05, 0xca, 0x0a, 0xbc, 0xf6, 0xea, 0x3e, 0x22, + 0x14, 0x73, 0x07, 0xdf, 0xfe, 0x2f, 0x1d, 0xb5, 0xdd, 0x7c, 0xde, 0x0e, 0x67, 0x46, 0x0f, 0xcf, 0x48, 0x88, 0xba, + 0x3c, 0xd8, 0x24, 0xd7, 0xaf, 0xfe, 0xe9, 0x29, 0x7e, 0xa5, 0x9d, 0xe6, 0x5f, 0x73, 0xce, 0x0b, 0x63, 0x53, 0x3e, + 0xdb, 0x47, 0x9a, 0x30, 0xba, 0x46, 0x84, 0xcb, 0xef, 0xdb, 0xd0, 0x4a, 0x83, 0x8c, 0x48, 0x08, 0x79, 0xbd, 0x75, + 0x05, 0xb8, 0xef, 0x2f, 0xdb, 0x1d, 0xbc, 0xa5, 0x44, 0xe2, 0x8d, 0xea, 0x38, 0x6e, 0xcf, 0xc8, 0xc2, 0xf5, 0xfd, + 0x5b, 0x07, 0x82, 0x7d, 0xad, 0x7d, 0x25, 0xbf, 0xdc, 0x39, 0x7a, 0x01, 0x06, 0x94, 0x30, 0x84, 0x27, 0x51, 0xff, + 0x97, 0xd8, 0x88, 0xd4, 0x6d, 0xc6, 0x74, 0xc2, 0x84, 0xfd, 0x59, 0xd1, 0xaa, 0xad, 0xf4, 0x00, 0x28, 0xa6, 0x4e, + 0xae, 0x06, 0x51, 0x74, 0x87, 0x26, 0xe2, 0x8e, 0x39, 0x5a, 0xde, 0x13, 0x9a, 0xb5, 0x40, 0x15, 0x4e, 0x61, 0xcf, + 0xa3, 0x50, 0x9a, 0xe1, 0x19, 0xf4, 0x01, 0xf6, 0x52, 0x84, 0x9c, 0xb9, 0x24, 0x79, 0xe6, 0xc0, 0x6b, 0x13, 0x04, + 0x69, 0x74, 0xb7, 0x7a, 0x4a, 0xb1, 0x8b, 0x6c, 0xb7, 0x20, 0xe9, 0xcd, 0x22, 0x74, 0x2b, 0x56, 0x49, 0x8a, 0xbb, + 0x99, 0x8a, 0xad, 0x0e, 0x1e, 0x61, 0x8f, 0x48, 0xdf, 0x96, 0xfd, 0xbd, 0x75, 0xc0, 0x42, 0x17, 0x45, 0x4d, 0x4a, + 0xed, 0xbf, 0x29, 0x1d, 0x38, 0xa1, 0x86, 0x09, 0x05, 0x05, 0xfb, 0x6c, 0xdc, 0x62, 0xbc, 0x7b, 0x6b, 0x6d, 0x6f, + 0x21, 0xf0, 0x2a, 0x34, 0x37, 0xd5, 0x82, 0x5c, 0xe1, 0x0b, 0x64, 0xc9, 0xb5, 0x15, 0x42, 0xd7, 0x37, 0x2d, 0xbb, + 0xf0, 0xfc, 0xc2, 0xf4, 0xc7, 0x56, 0x29, 0xea, 0x52, 0x90, 0x4b, 0x38, 0xb5, 0xb2, 0x46, 0x57, 0x1f, 0xd8, 0x9a, + 0x8e, 0x51, 0xbb, 0x33, 0xce, 0x5e, 0x21, 0x90, 0xfc, 0x89, 0x4a, 0x9d, 0x53, 0x9a, 0x11, 0x18, 0x5e, 0x0f, 0x8a, + 0xd5, 0x2f, 0xb9, 0x16, 0x30, 0x0e, 0x0f, 0xf4, 0xc7, 0xa0, 0x48, 0x9e, 0x64, 0x62, 0x0e, 0x03, 0x4f, 0xe5, 0xb0, + 0x73, 0xcf, 0xe9, 0x4e, 0xe6, 0xf7, 0xbe, 0xb1, 0xb7, 0xc7, 0xae, 0xe3, 0x96, 0x31, 0x3f, 0x8c, 0x20, 0x6a, 0x25, + 0xc2, 0x48, 0x45, 0x1e, 0x31, 0x80, 0x12, 0x4e, 0xae, 0x1b, 0x70, 0xa8, 0xa9, 0x36, 0xdc, 0xa7, 0xe8, 0x08, 0xcc, + 0xa9, 0xcb, 0x34, 0xaa, 0x39, 0x55, 0x99, 0x20, 0x84, 0xcf, 0x8d, 0x5b, 0xe7, 0x78, 0x02, 0x33, 0xed, 0x80, 0xd5, + 0x26, 0xaf, 0x53, 0x1c, 0x84, 0xcc, 0xd4, 0x9d, 0x2d, 0x1a, 0x13, 0x49, 0x4d, 0xb5, 0x4b, 0xad, 0x05, 0xe3, 0x64, + 0xb3, 0x6b, 0xd4, 0x6e, 0x2b, 0x32, 0xb8, 0x88, 0x15, 0x0f, 0x64, 0x04, 0x38, 0xba, 0x96, 0x6b, 0x94, 0x27, 0x47, + 0x5a, 0x10, 0xe6, 0x26, 0x39, 0x8e, 0x98, 0xb6, 0x7f, 0xdc, 0x8d, 0xe8, 0x66, 0x9e, 0x99, 0x8a, 0xc3, 0x5f, 0xbd, + 0xe7, 0xb6, 0x5e, 0x59, 0x2a, 0xd6, 0xf3, 0x2c, 0x25, 0xeb, 0x95, 0xcf, 0x2c, 0xa5, 0x21, 0xb9, 0xb0, 0x16, 0xd8, + 0x6c, 0x9a, 0xa5, 0xd9, 0x72, 0x7a, 0xde, 0xb9, 0x45, 0x66, 0x5e, 0xf0, 0x08, 0x53, 0xde, 0xae, 0xbc, 0x44, 0x67, + 0x03, 0xf6, 0x3f, 0xfb, 0x7c, 0x09, 0x9a, 0x19, 0x2b, 0x34, 0xc7, 0xbb, 0xc2, 0x1c, 0x12, 0x59, 0x61, 0xd4, 0x8f, + 0x4b, 0xf9, 0xec, 0x5d, 0x70, 0xda, 0x6a, 0xe7, 0x46, 0x05, 0x85, 0xef, 0x4d, 0x52, 0x60, 0x22, 0x09, 0x6c, 0x72, + 0x34, 0xee, 0x83, 0xf3, 0xac, 0x9c, 0xe9, 0x97, 0x03, 0x04, 0xff, 0x89, 0x6d, 0xc6, 0x35, 0x27, 0x30, 0x77, 0x06, + 0x77, 0x4a, 0xa8, 0x6e, 0x88, 0xe1, 0xf5, 0xd9, 0x75, 0x4e, 0x56, 0x1c, 0x73, 0x4b, 0xb2, 0x10, 0xe0, 0xb5, 0x07, + 0xb7, 0xcf, 0x33, 0x6b, 0x71, 0xa7, 0xe2, 0x34, 0xd4, 0x66, 0x5f, 0xfa, 0xcc, 0xd7, 0x83, 0x5f, 0x8d, 0x1c, 0x65, + 0x5c, 0xe0, 0x66, 0xd7, 0x8b, 0x81, 0x21, 0x34, 0x9e, 0x05, 0xe8, 0x11, 0x4f, 0xe9, 0xbf, 0x80, 0x10, 0xbf, 0x1b, + 0xfc, 0x2a, 0x33, 0x83, 0xd5, 0xd7, 0x2a, 0x06, 0x89, 0x9e, 0x64, 0x42, 0x81, 0x91, 0x61, 0xe8, 0xba, 0x2a, 0x8b, + 0x84, 0x37, 0xbc, 0xd8, 0xcd, 0xee, 0xcd, 0x98, 0x3f, 0x60, 0xa8, 0x43, 0xf8, 0x25, 0xb1, 0x27, 0xe6, 0x39, 0x9c, + 0x6a, 0xe6, 0x65, 0x76, 0x56, 0x45, 0x63, 0xbd, 0x59, 0xe3, 0x89, 0x09, 0xd5, 0x87, 0x68, 0xdb, 0x37, 0xc5, 0xdc, + 0x6e, 0xf7, 0xd6, 0x87, 0xd3, 0x44, 0x8d, 0x98, 0x99, 0x9a, 0x8f, 0xfb, 0xc6, 0x0a, 0x69, 0x33, 0x52, 0x64, 0x12, + 0xaa, 0x0c, 0x56, 0xc2, 0xc8, 0x3d, 0xbd, 0x6d, 0x75, 0x74, 0x5a, 0x00, 0x4e, 0x34, 0xcb, 0xdb, 0x4a, 0x64, 0xa3, + 0xbd, 0xb6, 0x1b, 0x85, 0xa8, 0x17, 0x3d, 0x9e, 0x51, 0x28, 0x15, 0x37, 0x34, 0x70, 0x6e, 0x06, 0x02, 0x4b, 0x3f, + 0xc5, 0x4b, 0xd8, 0x8b, 0xae, 0x3d, 0x6b, 0xc2, 0xb5, 0x51, 0x7b, 0x87, 0xb4, 0xac, 0x54, 0x4b, 0xd9, 0x77, 0x8e, + 0x74, 0xe3, 0x85, 0xaa, 0x97, 0xb9, 0xd0, 0xb9, 0xda, 0x4f, 0x7c, 0x6c, 0x1b, 0x23, 0x4d, 0xed, 0x9a, 0xfe, 0x66, + 0xce, 0x36, 0xd7, 0x99, 0xac, 0x90, 0x1f, 0x2c, 0x43, 0xfe, 0x04, 0xe9, 0xb6, 0x91, 0x4d, 0xac, 0xc4, 0xfa, 0x85, + 0x1f, 0xf0, 0x0e, 0x3a, 0x67, 0x2d, 0x3b, 0xb0, 0x36, 0xdb, 0x2e, 0x58, 0x26, 0x3f, 0x58, 0xae, 0x5d, 0xe3, 0x37, + 0x7c, 0x08, 0x57, 0xb2, 0x3a, 0x97, 0x9d, 0xec, 0x3d, 0xfe, 0x45, 0xfd, 0xf2, 0xfb, 0x19, 0x3d, 0x8b, 0x0f, 0x96, + 0x35, 0xde, 0x4c, 0x9f, 0xb2, 0x32, 0xfb, 0xc5, 0xed, 0x5b, 0x8b, 0x8f, 0x37, 0x97, 0x36, 0x38, 0x8f, 0x61, 0x68, + 0xef, 0xc5, 0xdd, 0x83, 0xfa, 0xc3, 0x70, 0x56, 0x4e, 0xd0, 0x6a, 0x18, 0x19, 0xe0, 0xce, 0xd6, 0xf3, 0x05, 0xbd, + 0xc7, 0xc6, 0x4c, 0x1f, 0xee, 0xf9, 0xd0, 0xbb, 0xfc, 0xc7, 0xcb, 0x7e, 0x24, 0x9c, 0x3d, 0x3a, 0xbb, 0x40, 0xd0, + 0x5a, 0xd7, 0x56, 0x4a, 0xf5, 0x98, 0xd7, 0x2e, 0x8e, 0xd0, 0x92, 0x3d, 0x2f, 0x75, 0x34, 0xff, 0xd0, 0x2a, 0x87, + 0x0d, 0x1a, 0x63, 0xf5, 0xbe, 0xd5, 0x96, 0x46, 0x6f, 0x3f, 0x10, 0x16, 0xa6, 0xa1, 0x52, 0x81, 0x80, 0x4a, 0xff, + 0xcc, 0x26, 0x5c, 0x7b, 0x9b, 0xc9, 0x28, 0x7d, 0x8a, 0x30, 0x7b, 0xd4, 0x93, 0xc5, 0xfb, 0x8e, 0x9d, 0xac, 0xd5, + 0x1b, 0xca, 0x74, 0x58, 0x69, 0x33, 0x59, 0xa9, 0x11, 0x46, 0x0c, 0x33, 0x9b, 0xe1, 0x85, 0x2a, 0xa7, 0xc3, 0xae, + 0x04, 0x81, 0xa9, 0xda, 0x78, 0xe2, 0xdc, 0xc1, 0xf3, 0xdf, 0xb2, 0x3e, 0x40, 0x8c, 0xe9, 0xe1, 0xc4, 0xde, 0x81, + 0x2e, 0xb5, 0x8b, 0x27, 0xfc, 0xcb, 0xdf, 0x92, 0x43, 0xb0, 0x42, 0xb5, 0xf1, 0xfd, 0x00, 0xd6, 0xd7, 0x20, 0xe6, + 0x6d, 0x77, 0xe2, 0xe0, 0x8e, 0x5d, 0x59, 0x3e, 0xcd, 0xcb, 0x03, 0x88, 0x52, 0x36, 0x72, 0xb3, 0x61, 0xcd, 0xaf, + 0x66, 0x16, 0xbb, 0x36, 0x9e, 0x1f, 0xc8, 0xfa, 0xb0, 0xcd, 0x9f, 0x0b, 0x90, 0xa2, 0x28, 0xd0, 0x96, 0xbb, 0xda, + 0xa2, 0x8d, 0x80, 0x69, 0xd7, 0x3a, 0x6f, 0x6d, 0x21, 0xeb, 0xa4, 0x76, 0xca, 0xa0, 0x2b, 0x65, 0x8a, 0x9c, 0x9a, + 0x51, 0x23, 0x44, 0xc7, 0xf8, 0x41, 0x0e, 0xfd, 0x62, 0xf5, 0xdd, 0xf5, 0x3b, 0x5d, 0x80, 0xb8, 0xe2, 0x54, 0xe6, + 0x59, 0x49, 0xac, 0x0f, 0x37, 0x79, 0xcf, 0x1b, 0xf4, 0xbf, 0xd4, 0x95, 0xef, 0xcb, 0xda, 0x13, 0x24, 0x03, 0x41, + 0x3a, 0x0e, 0xfe, 0x18, 0xc0, 0xf0, 0xc7, 0x06, 0x46, 0x2f, 0x7a, 0x78, 0x1e, 0x54, 0xbf, 0x76, 0xc2, 0x77, 0x96, + 0x5f, 0xaa, 0xd0, 0xfb, 0x49, 0xf5, 0x0b, 0x58, 0x5f, 0x83, 0xa0, 0x8e, 0x44, 0xcd, 0xef, 0x69, 0x5b, 0xf7, 0x2b, + 0x8c, 0x78, 0x91, 0x0f, 0x15, 0xf9, 0xeb, 0xba, 0xfa, 0x3c, 0x87, 0x01, 0x39, 0xf6, 0x09, 0x06, 0x36, 0xfd, 0xb2, + 0x0f, 0x21, 0x78, 0x5f, 0x5f, 0xd5, 0x42, 0xe3, 0x97, 0x22, 0x4e, 0x50, 0xe1, 0x81, 0x2c, 0x74, 0x3c, 0xb5, 0x72, + 0x6b, 0x1d, 0x99, 0x68, 0x6c, 0x62, 0x14, 0x3a, 0x8b, 0x15, 0x6c, 0xcc, 0x27, 0xa3, 0xba, 0xf2, 0x86, 0x09, 0x86, + 0x5f, 0xad, 0x3f, 0x9d, 0xa5, 0x57, 0x5b, 0x85, 0xbd, 0xaa, 0xf0, 0x5f, 0x75, 0x13, 0xbe, 0xc9, 0x70, 0x58, 0x05, + 0x2f, 0x08, 0x15, 0xfc, 0x40, 0x27, 0x55, 0xa8, 0xa3, 0xd3, 0x10, 0xa1, 0x55, 0xb3, 0x82, 0x1c, 0x15, 0xda, 0xef, + 0xdb, 0xd4, 0xd6, 0x9b, 0xea, 0xec, 0xed, 0x58, 0xd5, 0x54, 0x98, 0x1f, 0x8f, 0x59, 0x4d, 0x33, 0x12, 0x95, 0x2c, + 0xbf, 0x83, 0xdd, 0x69, 0x0b, 0x6f, 0x9f, 0xc0, 0xfb, 0x9b, 0xfa, 0x31, 0xe3, 0xb3, 0x6c, 0xd2, 0x04, 0xba, 0x33, + 0xd7, 0x02, 0xb5, 0x4f, 0x4d, 0xdd, 0x91, 0xb9, 0x0e, 0xec, 0x5d, 0xcd, 0x97, 0xf8, 0x4c, 0x84, 0xbb, 0x5f, 0x93, + 0xa8, 0xcc, 0x69, 0x06, 0x6d, 0x2c, 0xa5, 0x89, 0xaa, 0xdb, 0x70, 0xca, 0xb0, 0xf7, 0x0c, 0xed, 0x02, 0x6a, 0xf4, + 0x44, 0x77, 0x62, 0x8c, 0x90, 0xc6, 0xfd, 0x22, 0xb4, 0x1f, 0xe9, 0x79, 0x2b, 0x90, 0x8e, 0xed, 0x18, 0xa6, 0x9b, + 0x06, 0xc8, 0x5a, 0xe8, 0xe3, 0x5f, 0x5f, 0xed, 0xc3, 0xd8, 0xe6, 0xfd, 0x06, 0x61, 0xa9, 0xde, 0x1e, 0x1d, 0x20, + 0xf9, 0x9e, 0x52, 0x58, 0x5c, 0xd1, 0x1a, 0xad, 0x86, 0x8d, 0x83, 0x5c, 0x61, 0x30, 0xca, 0x54, 0xe9, 0x3c, 0x62, + 0x38, 0x1a, 0xc2, 0x08, 0x85, 0x42, 0x5e, 0x7d, 0xc4, 0x9a, 0x79, 0xdc, 0x9e, 0x3d, 0x94, 0x56, 0x07, 0xbf, 0x7a, + 0xb2, 0x46, 0x7d, 0xe9, 0x5d, 0x6e, 0xc6, 0x52, 0x8b, 0x8f, 0x57, 0xbc, 0xd1, 0xeb, 0xcb, 0x84, 0x66, 0x6e, 0xd1, + 0xa0, 0x14, 0x1b, 0x12, 0xbb, 0x95, 0xdf, 0x13, 0xeb, 0xb1, 0x59, 0x21, 0x09, 0x99, 0x5f, 0x5e, 0x99, 0xca, 0x53, + 0x79, 0x7f, 0x65, 0x39, 0xc3, 0x51, 0x3c, 0x78, 0x07, 0x7e, 0xd1, 0xcb, 0x9f, 0xa4, 0xde, 0xaa, 0x6e, 0x4b, 0x1b, + 0x14, 0xb5, 0x73, 0xcb, 0x86, 0x73, 0xe1, 0x3a, 0x29, 0x54, 0xc1, 0x0d, 0x16, 0x49, 0x23, 0x6f, 0x1d, 0x2f, 0x3e, + 0xc5, 0x60, 0xca, 0xc2, 0x19, 0x94, 0xb5, 0xcc, 0x05, 0xd6, 0x68, 0x1f, 0x86, 0x67, 0x8b, 0xcc, 0x18, 0x33, 0x18, + 0xdb, 0x70, 0x6e, 0xf9, 0xac, 0xfb, 0xfa, 0x85, 0xe0, 0xfd, 0xc6, 0x48, 0x44, 0x2c, 0x1f, 0xa0, 0x0f, 0x06, 0xa4, + 0x7f, 0x59, 0x62, 0xe4, 0xc3, 0x73, 0x05, 0x7e, 0xd2, 0xb2, 0x70, 0x00, 0x36, 0x6b, 0xef, 0x30, 0x2e, 0x92, 0x79, + 0xab, 0xdb, 0x31, 0x3b, 0x04, 0x37, 0x6c, 0x8d, 0x22, 0x18, 0x15, 0xa3, 0x25, 0x18, 0xac, 0xa0, 0x21, 0xb8, 0x80, + 0xf3, 0x75, 0xc4, 0xaa, 0xc7, 0x29, 0x2e, 0x33, 0x75, 0x86, 0x7f, 0x76, 0x37, 0xcd, 0xb2, 0x1a, 0xc4, 0x07, 0xa1, + 0xc8, 0x16, 0xec, 0xc1, 0xc5, 0x63, 0xe1, 0xcf, 0x21, 0xdf, 0x45, 0x61, 0xe9, 0x1a, 0xff, 0xaf, 0x43, 0xaa, 0xf7, + 0x3d, 0xec, 0x9e, 0x60, 0x0f, 0x3a, 0xa9, 0x2d, 0x34, 0x7f, 0x85, 0x55, 0x15, 0x55, 0xf3, 0xcd, 0x08, 0x8f, 0x16, + 0x5c, 0xab, 0x23, 0xd0, 0x41, 0x20, 0xd4, 0x6a, 0x06, 0x03, 0xb4, 0xe3, 0x07, 0xf8, 0xd2, 0xf1, 0xf8, 0x25, 0x89, + 0x09, 0xcf, 0xef, 0x9b, 0x10, 0xc4, 0xe3, 0xe8, 0x71, 0xe7, 0xfa, 0x43, 0x95, 0x21, 0xb2, 0x48, 0xea, 0x7e, 0x84, + 0xb9, 0xfd, 0x34, 0x17, 0x2e, 0x16, 0x27, 0xe8, 0xb1, 0x5c, 0x71, 0xc7, 0x3d, 0xea, 0x6e, 0xda, 0x3d, 0x9f, 0xb2, + 0x27, 0x31, 0x96, 0x52, 0xc4, 0x1d, 0xad, 0xcd, 0xb8, 0x22, 0x45, 0xae, 0x36, 0x81, 0x5e, 0x8e, 0xf4, 0x1c, 0x8f, + 0x64, 0x29, 0x51, 0xc7, 0x12, 0x44, 0xad, 0xe2, 0x3b, 0x23, 0x05, 0xd5, 0x28, 0xef, 0x72, 0xf7, 0xad, 0xd3, 0xd4, + 0xdd, 0xcf, 0xee, 0xa7, 0xc1, 0xcb, 0x54, 0xe7, 0x8c, 0x77, 0x5e, 0xb4, 0x5a, 0xfb, 0x22, 0x46, 0xaf, 0x1f, 0x0b, + 0x32, 0x9c, 0xf6, 0x5d, 0x67, 0x01, 0x6a, 0x95, 0xe5, 0xbf, 0x41, 0x20, 0x53, 0x74, 0x97, 0x9e, 0x8e, 0x68, 0xae, + 0x74, 0xf9, 0x8e, 0x0e, 0x54, 0x26, 0x0a, 0x31, 0xd3, 0x68, 0xf6, 0x80, 0xce, 0x2d, 0xcf, 0x75, 0x19, 0xf5, 0x2e, + 0xa2, 0x0d, 0x0a, 0xb5, 0xcf, 0xd1, 0x5d, 0x2f, 0x3a, 0x87, 0xeb, 0x94, 0xdb, 0x47, 0xcb, 0x45, 0xe5, 0xb3, 0xf1, + 0x70, 0x61, 0x97, 0x48, 0x22, 0x1f, 0x78, 0x09, 0x31, 0x74, 0xdf, 0xce, 0x30, 0x83, 0xb3, 0xda, 0xbb, 0x5d, 0xaa, + 0x1b, 0x3e, 0x84, 0x1e, 0xc5, 0xc2, 0xb5, 0x59, 0xce, 0xff, 0x97, 0xde, 0x45, 0xf5, 0xb7, 0x3a, 0x25, 0xee, 0x17, + 0xfe, 0x5d, 0x24, 0x8a, 0x84, 0x1e, 0xd2, 0x90, 0xde, 0x9f, 0x95, 0x1d, 0x98, 0x0f, 0xed, 0xa1, 0x32, 0x35, 0x79, + 0x9e, 0x05, 0xa0, 0xf5, 0xaa, 0x50, 0x46, 0x0e, 0x46, 0x4f, 0xce, 0x3b, 0xa4, 0x10, 0x86, 0x90, 0xc3, 0x20, 0x11, + 0x73, 0x1d, 0x70, 0x73, 0xd5, 0xed, 0x2c, 0x45, 0x85, 0xee, 0x1a, 0x96, 0x12, 0xd0, 0x11, 0x1d, 0x92, 0xcc, 0x9c, + 0xd0, 0x10, 0x14, 0x28, 0xf2, 0x1e, 0x31, 0x18, 0x4d, 0xe0, 0x3f, 0x98, 0x7d, 0x14, 0xd2, 0x08, 0x08, 0xe3, 0x14, + 0xc5, 0x7b, 0x20, 0x0e, 0x94, 0xd6, 0x3d, 0x98, 0x56, 0xe1, 0xaa, 0x57, 0xda, 0xca, 0x18, 0xbe, 0xc6, 0xb9, 0x33, + 0xc8, 0x05, 0x9e, 0xea, 0x5e, 0xcc, 0x80, 0x28, 0x40, 0x29, 0x68, 0xc1, 0x49, 0x90, 0x7c, 0xa8, 0x15, 0x48, 0xc0, + 0x21, 0xae, 0x41, 0xa9, 0xb1, 0xe0, 0xd5, 0x78, 0xa3, 0x10, 0x96, 0x62, 0x24, 0x02, 0x21, 0xd9, 0x30, 0xac, 0x98, + 0x0a, 0xb4, 0xfb, 0xc5, 0xbe, 0xf7, 0xc2, 0xe3, 0x43, 0x7d, 0x23, 0xe6, 0x02, 0x09, 0xa3, 0xb3, 0x93, 0x7b, 0x81, + 0x24, 0x7f, 0xb5, 0xa7, 0x2b, 0xb3, 0xbc, 0xf0, 0x8d, 0x85, 0x73, 0xb5, 0x12, 0x10, 0xf6, 0x6f, 0x8c, 0x03, 0x01, + 0x30, 0x97, 0xce, 0x6a, 0x2d, 0x91, 0x95, 0x0b, 0x69, 0xd6, 0x63, 0x29, 0xd6, 0xdd, 0x3c, 0x54, 0x80, 0x29, 0xb5, + 0xb8, 0x20, 0x95, 0x15, 0xde, 0x68, 0x0e, 0xa6, 0xf0, 0xa6, 0x83, 0xae, 0xcd, 0x67, 0xff, 0x43, 0xee, 0x1e, 0x1e, + 0x87, 0x57, 0xaa, 0x5b, 0x82, 0x51, 0x67, 0x92, 0xc1, 0x89, 0x4c, 0xa5, 0x9e, 0x06, 0xb1, 0x93, 0xbe, 0x13, 0x20, + 0x90, 0xd0, 0x38, 0x25, 0x9d, 0x8d, 0x74, 0xe8, 0x03, 0xf7, 0x43, 0x59, 0x50, 0x7c, 0x1d, 0x75, 0x7c, 0x11, 0x45, + 0x58, 0x64, 0xa5, 0x67, 0x97, 0x57, 0x37, 0x8d, 0xce, 0xcc, 0x4b, 0xcb, 0x9c, 0xc6, 0x4f, 0x60, 0xc9, 0x0a, 0x51, + 0xf2, 0x92, 0xb4, 0xb0, 0x9c, 0xe0, 0x7a, 0xa0, 0xe9, 0xb0, 0x20, 0x73, 0xe3, 0xb8, 0xfe, 0x51, 0x31, 0x8e, 0xa9, + 0xc3, 0x9e, 0xd2, 0x9b, 0x0a, 0x3c, 0x75, 0x64, 0x15, 0x3a, 0x10, 0x9e, 0x61, 0xbc, 0xa6, 0x81, 0x37, 0xfb, 0xf5, + 0xfc, 0xdf, 0x01, 0x8d, 0xe3, 0xc3, 0x25, 0x6d, 0xb8, 0x0e, 0xab, 0x70, 0x21, 0x8e, 0xc9, 0x0f, 0x26, 0x93, 0xb8, + 0x26, 0x71, 0xe0, 0xf7, 0x61, 0x89, 0x54, 0x88, 0x0c, 0xea, 0x58, 0xb9, 0x1d, 0xfb, 0x0b, 0x40, 0x8f, 0x87, 0x4c, + 0xe7, 0x81, 0x2f, 0x58, 0xe0, 0x38, 0xa8, 0x66, 0x37, 0x87, 0x8a, 0x05, 0xc0, 0x85, 0x59, 0x29, 0x5c, 0x8c, 0xd6, + 0x28, 0xc5, 0xec, 0x19, 0x1f, 0xda, 0x55, 0x03, 0x96, 0x99, 0x77, 0x66, 0xe5, 0xdc, 0x5a, 0x48, 0xc1, 0xed, 0xfa, + 0x46, 0x4c, 0x70, 0xbb, 0x46, 0xb2, 0x2d, 0xea, 0xd7, 0xe0, 0x58, 0x5c, 0x5c, 0xd7, 0xf8, 0xac, 0xcc, 0xdc, 0x49, + 0xfb, 0xc4, 0x75, 0x94, 0x56, 0x20, 0x89, 0xe7, 0x79, 0x18, 0x89, 0x05, 0xd3, 0xe7, 0x84, 0xa8, 0xc4, 0xb0, 0xf4, + 0xb1, 0xec, 0x0c, 0x83, 0xc7, 0x1c, 0x1d, 0x79, 0x66, 0xe7, 0x1c, 0xfe, 0xc7, 0x05, 0x60, 0x59, 0x7c, 0x2a, 0xe3, + 0x5f, 0x1c, 0x8f, 0xb2, 0x27, 0xf2, 0xfe, 0x4a, 0xe2, 0x4e, 0xc5, 0x1c, 0x48, 0x23, 0x5b, 0xc6, 0xd2, 0x16, 0xc8, + 0x45, 0xc6, 0x33, 0xec, 0xfc, 0xd4, 0xfa, 0x98, 0xfd, 0xd8, 0xc7, 0xaa, 0xe1, 0xd7, 0x81, 0x6e, 0x93, 0x12, 0xf4, + 0xad, 0x94, 0xe9, 0xec, 0xbd, 0x99, 0xd2, 0xdc, 0x89, 0xab, 0x7a, 0x65, 0x6b, 0x1b, 0x6a, 0x9b, 0xc4, 0xf5, 0x5b, + 0xf3, 0x18, 0x98, 0xb6, 0x4e, 0x5c, 0x19, 0x0a, 0x6d, 0xb2, 0x3c, 0xd3, 0x20, 0x55, 0x31, 0x74, 0xf7, 0x8a, 0x0f, + 0x9d, 0xee, 0x70, 0x36, 0x5f, 0x9a, 0xf4, 0x30, 0x9e, 0xc5, 0xb5, 0x5c, 0x92, 0xc1, 0x07, 0x85, 0xc3, 0x21, 0x49, + 0xd1, 0x22, 0x97, 0x21, 0x80, 0xdc, 0xed, 0xe0, 0x6e, 0xb2, 0xdd, 0x94, 0x77, 0xcc, 0x5e, 0x9a, 0xa3, 0xcf, 0xdb, + 0x72, 0x31, 0xa1, 0x46, 0x4c, 0xd5, 0x79, 0x6b, 0xbb, 0x6e, 0x0a, 0x4a, 0x39, 0x0a, 0xa4, 0x53, 0x16, 0xa2, 0x82, + 0x9f, 0x98, 0xef, 0xff, 0xa0, 0x28, 0x37, 0x04, 0xdc, 0xf2, 0x3a, 0x7e, 0xdc, 0x69, 0x2d, 0x63, 0x58, 0x8e, 0x8c, + 0x0b, 0xd3, 0xbf, 0xa4, 0x59, 0xcd, 0x96, 0x65, 0xe2, 0x75, 0x9d, 0x3d, 0x28, 0x2e, 0xe1, 0x5c, 0xad, 0x65, 0xe1, + 0x3a, 0xd2, 0xd0, 0x84, 0xfe, 0x10, 0x0a, 0xdb, 0xa6, 0x32, 0x70, 0xa2, 0x94, 0x21, 0x3f, 0x97, 0x86, 0x29, 0x18, + 0x7e, 0x13, 0x60, 0x9d, 0x66, 0x18, 0x85, 0xb4, 0x00, 0xaa, 0x0f, 0x47, 0x93, 0x6e, 0x08, 0x3b, 0x07, 0x1d, 0x47, + 0xe9, 0xec, 0xc0, 0x7a, 0x40, 0xce, 0xf3, 0xd9, 0x5e, 0xef, 0xcd, 0xfa, 0xda, 0xf8, 0x07, 0x04, 0x3e, 0xf3, 0x2d, + 0xfa, 0xda, 0x06, 0xe2, 0x7c, 0x39, 0x23, 0xc6, 0xb6, 0x0c, 0xd8, 0x52, 0xe5, 0x10, 0xb6, 0x54, 0x0c, 0x13, 0x33, + 0x75, 0x62, 0x8a, 0x17, 0x65, 0xdd, 0x79, 0x3e, 0x04, 0x2c, 0x50, 0x7e, 0xc0, 0x91, 0x25, 0xc7, 0x74, 0x14, 0x29, + 0x3a, 0x0d, 0x14, 0x2c, 0x50, 0x7e, 0x7d, 0x5b, 0xfe, 0x61, 0x08, 0xb0, 0x1c, 0x69, 0x95, 0x81, 0x64, 0x6a, 0x63, + 0x39, 0xa9, 0xc5, 0xa9, 0x38, 0x8b, 0xca, 0x30, 0xfa, 0xdd, 0xb8, 0x78, 0xe9, 0xbd, 0x56, 0x6f, 0xe1, 0x29, 0x57, + 0xb0, 0x46, 0x13, 0xd3, 0x13, 0xb1, 0xbf, 0xe0, 0x7c, 0x30, 0xc8, 0x6f, 0x78, 0x77, 0x08, 0xa9, 0x8d, 0x62, 0x8f, + 0xda, 0x0f, 0x4c, 0x46, 0xa5, 0xd5, 0x25, 0x2f, 0xea, 0x45, 0xb6, 0x65, 0x17, 0xbb, 0x72, 0x8f, 0x81, 0xcb, 0x8b, + 0x11, 0xe8, 0xf1, 0xf6, 0x1a, 0x1c, 0x00, 0x1f, 0x2d, 0x8a, 0xab, 0x61, 0x5b, 0xa4, 0x40, 0xd8, 0xd6, 0x7b, 0xde, + 0xea, 0x53, 0x2b, 0xc8, 0x63, 0x10, 0x5a, 0x97, 0x13, 0xde, 0xb9, 0x75, 0xca, 0x90, 0x16, 0x31, 0xce, 0xb3, 0xa8, + 0xd0, 0x87, 0x49, 0x55, 0xc9, 0x86, 0x7f, 0xc0, 0x60, 0xe4, 0x16, 0x53, 0xe1, 0xdf, 0xe2, 0xaf, 0xcc, 0x0d, 0xf7, + 0x6a, 0x98, 0xce, 0xa9, 0x36, 0xef, 0xba, 0xed, 0xf0, 0xc3, 0xf0, 0xdd, 0x12, 0x7a, 0x54, 0x60, 0x9c, 0xe6, 0x89, + 0xd9, 0x1a, 0x7e, 0xa5, 0x80, 0x6f, 0x1f, 0xca, 0xb4, 0x0d, 0x37, 0xd3, 0xaa, 0xbd, 0xe9, 0xb6, 0x1b, 0x40, 0xe6, + 0xac, 0x66, 0xf9, 0xe6, 0x83, 0x3b, 0x09, 0x69, 0x11, 0xfe, 0x58, 0x26, 0xea, 0x11, 0xb6, 0x74, 0xe8, 0x04, 0x3c, + 0xd3, 0xd3, 0xaa, 0xc6, 0xf3, 0x75, 0x56, 0x22, 0x7f, 0xb4, 0x37, 0xfe, 0xe4, 0x83, 0xb7, 0xbe, 0x83, 0x1a, 0x79, + 0xa2, 0x47, 0x84, 0x0b, 0xd5, 0x25, 0xb4, 0xad, 0x1a, 0xb2, 0x28, 0x96, 0xdc, 0x06, 0xde, 0x13, 0x53, 0x84, 0xc3, + 0x4f, 0xed, 0xe9, 0x52, 0xd4, 0xfe, 0x98, 0x19, 0xfc, 0x07, 0x80, 0x44, 0xe5, 0xf2, 0xbf, 0xc3, 0xe3, 0x1d, 0x85, + 0x88, 0x78, 0x0b, 0xc9, 0x82, 0x05, 0x18, 0x79, 0xa8, 0xcc, 0x48, 0x4a, 0xca, 0xb5, 0x12, 0x80, 0xef, 0xc3, 0xd0, + 0x56, 0x5d, 0x83, 0x1c, 0x6c, 0xf0, 0xb7, 0x0c, 0xe2, 0x61, 0xd7, 0x23, 0xad, 0xf1, 0xf2, 0xf8, 0xd2, 0xa7, 0x9a, + 0xd0, 0xe2, 0xdb, 0x48, 0x59, 0xbc, 0x5c, 0x3d, 0x10, 0x1d, 0x49, 0x0c, 0x71, 0x23, 0x27, 0xc9, 0x9b, 0xc4, 0xfb, + 0x69, 0x63, 0x44, 0x72, 0x62, 0x9d, 0xbd, 0x20, 0xe5, 0x17, 0x62, 0xf3, 0xdd, 0xb8, 0x73, 0xb8, 0x73, 0xbd, 0xaf, + 0x94, 0x45, 0x5d, 0x8b, 0x7a, 0x68, 0x76, 0x1d, 0xfd, 0xd9, 0x94, 0x30, 0xa4, 0x43, 0xa2, 0x41, 0x21, 0x2d, 0x2a, + 0x0b, 0xa4, 0x81, 0x9e, 0x44, 0xf6, 0x71, 0x58, 0xcc, 0xde, 0xbd, 0x4a, 0x7d, 0x92, 0x48, 0x49, 0x6c, 0x0f, 0x58, + 0x9a, 0x4c, 0xbc, 0xb9, 0x30, 0xfb, 0xbf, 0xb2, 0xf3, 0xf2, 0x21, 0xd2, 0x98, 0xaa, 0x63, 0x64, 0xa1, 0x06, 0x4a, + 0x59, 0x0b, 0xa7, 0x2d, 0xbe, 0x14, 0x45, 0x5b, 0x85, 0x9e, 0x6a, 0x1e, 0x78, 0x5a, 0x58, 0x13, 0xc5, 0x16, 0xf4, + 0x74, 0x98, 0x96, 0x25, 0xb5, 0x09, 0x4f, 0x5f, 0x7a, 0x9e, 0xe5, 0x39, 0xdb, 0x5d, 0x9a, 0x7d, 0xeb, 0xa0, 0x5e, + 0x53, 0xcb, 0xf6, 0x53, 0x95, 0x69, 0xd0, 0x12, 0x04, 0xf5, 0x10, 0xe4, 0x56, 0x61, 0xe2, 0xc6, 0x38, 0x4f, 0x77, + 0xed, 0xd6, 0x9d, 0xf9, 0xa7, 0x5d, 0x10, 0x17, 0x12, 0x18, 0x34, 0x12, 0xad, 0x26, 0xf4, 0x63, 0xc3, 0x52, 0x18, + 0x72, 0xb6, 0x64, 0x96, 0xf3, 0x6a, 0x20, 0x3f, 0xd3, 0x56, 0x70, 0x40, 0xc2, 0xe8, 0x1c, 0x63, 0x66, 0xf0, 0x39, + 0x12, 0xc3, 0x57, 0x6d, 0xd2, 0x73, 0x24, 0xf7, 0x34, 0xc1, 0x54, 0x00, 0xf3, 0x4a, 0xc1, 0x74, 0xd6, 0x37, 0x8b, + 0x0a, 0x56, 0xfc, 0xf0, 0xe3, 0x2f, 0xa8, 0xde, 0x07, 0x05, 0x9d, 0x04, 0x57, 0xea, 0xb6, 0x9d, 0xf1, 0x6d, 0xf7, + 0x41, 0x01, 0x5e, 0xa8, 0x21, 0xf3, 0x12, 0xff, 0x57, 0x2f, 0xd6, 0xd4, 0x2f, 0xf2, 0xd9, 0x61, 0xa2, 0xef, 0x32, + 0x69, 0xe6, 0xf7, 0xa5, 0x01, 0x65, 0x7e, 0xc9, 0xe3, 0x8a, 0x69, 0xde, 0x23, 0xfe, 0xd3, 0x98, 0xdb, 0xc2, 0x84, + 0x76, 0x98, 0x3e, 0x4a, 0xd4, 0xdc, 0x3e, 0x13, 0x54, 0xfb, 0x86, 0x97, 0xea, 0x31, 0x17, 0xac, 0x63, 0x72, 0x4b, + 0x89, 0xf5, 0x95, 0xc0, 0x83, 0x2c, 0x92, 0x89, 0x7b, 0xa9, 0xf6, 0x8e, 0xf2, 0x7c, 0xa7, 0xf6, 0x34, 0x39, 0x61, + 0x5d, 0x5c, 0x5d, 0xc9, 0xd7, 0x31, 0xc2, 0x6e, 0xbd, 0x59, 0x5e, 0xab, 0x62, 0xcc, 0x28, 0xd9, 0xd4, 0x6e, 0xef, + 0x62, 0x31, 0xe3, 0x26, 0x0c, 0x45, 0xb6, 0x28, 0x97, 0x8f, 0x5c, 0x3c, 0xe4, 0xfb, 0x94, 0x5f, 0xfd, 0x67, 0x0b, + 0x71, 0xf3, 0xf9, 0xf9, 0x1b, 0x23, 0x2c, 0x08, 0x03, 0xdb, 0xad, 0x22, 0x3e, 0x9d, 0x09, 0x14, 0xc6, 0xc6, 0x04, + 0x9b, 0xd7, 0xba, 0x09, 0xbc, 0x48, 0x94, 0x91, 0x34, 0xcc, 0xcf, 0xf2, 0x10, 0xa8, 0x62, 0xe8, 0x49, 0x6b, 0x25, + 0x8a, 0xd6, 0xf7, 0x63, 0x9f, 0x01, 0x21, 0x55, 0xb2, 0xac, 0x88, 0x2b, 0x57, 0x28, 0x04, 0x22, 0x09, 0x07, 0x47, + 0x60, 0x9b, 0x26, 0x84, 0x4f, 0x0f, 0xe9, 0xa5, 0x2e, 0x73, 0xc9, 0xc5, 0x35, 0x38, 0x0a, 0x60, 0x69, 0x32, 0xe2, + 0xd7, 0xbb, 0x55, 0x5e, 0xfa, 0xa5, 0x9d, 0x6e, 0xfe, 0x9e, 0x03, 0x8e, 0x0b, 0xdd, 0x17, 0x05, 0x68, 0x0d, 0x58, + 0x56, 0x28, 0x6f, 0x1f, 0x83, 0x8b, 0xd2, 0x61, 0xf4, 0x72, 0x5c, 0x2d, 0xa2, 0xba, 0x42, 0x59, 0xbb, 0x5d, 0x11, + 0x95, 0xb7, 0xf3, 0xd7, 0x34, 0xa9, 0x45, 0x04, 0x71, 0xde, 0x47, 0x34, 0xcb, 0x44, 0x98, 0x5d, 0xdc, 0x75, 0xa8, + 0xc7, 0x90, 0xf4, 0xa1, 0x15, 0x17, 0x11, 0xf8, 0xb4, 0x02, 0x69, 0x63, 0x6e, 0x0f, 0xe9, 0xb7, 0xb6, 0xa3, 0x00, + 0xe8, 0x85, 0xb0, 0x90, 0xb9, 0x91, 0x14, 0x3c, 0x7b, 0x0f, 0x54, 0x92, 0xf4, 0xb9, 0x1a, 0xb3, 0xae, 0xc7, 0x17, + 0xaf, 0x95, 0xbe, 0x05, 0x79, 0x6f, 0x8a, 0xe0, 0xe9, 0xaa, 0xbd, 0x74, 0x21, 0xa0, 0xbd, 0xce, 0x74, 0xb6, 0x34, + 0x7b, 0x1f, 0xbc, 0x17, 0x1d, 0x78, 0x0d, 0xf5, 0x66, 0x89, 0x3c, 0x66, 0xf0, 0x65, 0x93, 0x90, 0xe4, 0xb5, 0x91, + 0x0a, 0xa2, 0xa0, 0x07, 0xae, 0x51, 0x91, 0x8c, 0x92, 0x8b, 0x6e, 0xfb, 0xb3, 0x19, 0xa4, 0x5c, 0x5e, 0x7d, 0xcd, + 0xdb, 0x9d, 0x83, 0x28, 0xa5, 0xf9, 0xeb, 0x85, 0x4f, 0xbb, 0x67, 0x74, 0xe5, 0x35, 0x81, 0x56, 0x33, 0x7a, 0x4b, + 0x8d, 0x6a, 0xa4, 0xa9, 0x48, 0x05, 0xb1, 0x77, 0x59, 0x83, 0xb5, 0xf1, 0x78, 0x30, 0x95, 0x1a, 0xbc, 0xcf, 0xf4, + 0xa4, 0x75, 0xfa, 0xf6, 0x69, 0x39, 0x84, 0x57, 0xdf, 0x6d, 0x37, 0x2a, 0xf5, 0x5c, 0x7c, 0x2f, 0xdb, 0x45, 0xa6, + 0x75, 0x9c, 0xe8, 0x64, 0xd2, 0x57, 0x69, 0xb7, 0x27, 0x55, 0x3d, 0x73, 0xe1, 0x00, 0xfd, 0xbb, 0x51, 0xa6, 0x94, + 0xa5, 0xf1, 0xda, 0x25, 0xac, 0xa7, 0xde, 0x08, 0xbb, 0x2e, 0x0a, 0xc0, 0x3f, 0x67, 0x1c, 0x68, 0xa2, 0x63, 0xc5, + 0x3a, 0xbe, 0x2e, 0x75, 0x3c, 0x94, 0xfc, 0x80, 0x6d, 0x66, 0x92, 0x77, 0x28, 0x6e, 0xde, 0x10, 0xd8, 0x9f, 0x29, + 0xd6, 0x76, 0xab, 0xc4, 0x19, 0xab, 0xd8, 0x2b, 0xb1, 0xd7, 0x1e, 0x6f, 0x98, 0x40, 0x99, 0xad, 0x2b, 0x4c, 0x99, + 0x33, 0xbf, 0xc9, 0x67, 0x2f, 0xaf, 0x6f, 0x9e, 0xfd, 0x65, 0xe7, 0x35, 0xc3, 0xb0, 0x92, 0x3d, 0x27, 0xcb, 0x21, + 0xac, 0xca, 0xf8, 0x99, 0x9e, 0x6a, 0x1e, 0xdf, 0x51, 0x6f, 0xdc, 0x9b, 0xa4, 0x07, 0xe3, 0xdb, 0x13, 0x92, 0x87, + 0x82, 0x09, 0x18, 0xe9, 0xcf, 0x47, 0xa3, 0x00, 0x9d, 0x5c, 0x76, 0x0d, 0x2e, 0x12, 0x93, 0x3f, 0xa6, 0x5e, 0xc6, + 0x22, 0x05, 0xa9, 0x3a, 0xc2, 0x5d, 0x83, 0x48, 0x8a, 0x2a, 0xe8, 0xc8, 0x8b, 0x02, 0x4c, 0x5a, 0x70, 0x60, 0x01, + 0x0a, 0x3a, 0x5f, 0x79, 0x89, 0x25, 0x7e, 0x88, 0xfe, 0xf1, 0x1f, 0x56, 0x27, 0xbd, 0x68, 0xfe, 0x31, 0xbd, 0xf0, + 0xff, 0x4f, 0xe7, 0xb3, 0x75, 0x8e, 0x0d, 0x08, 0xd6, 0xff, 0x05, 0x62, 0x17, 0x9a, 0xa0, 0x04, 0xe9, 0x01, 0x84, + 0x43, 0xfe, 0xf4, 0x4e, 0x33, 0x9c, 0xb0, 0x7c, 0xaa, 0x26, 0xc3, 0x78, 0x2a, 0xce, 0xc9, 0x84, 0xc6, 0x71, 0x1a, + 0x4d, 0x29, 0xc0, 0x33, 0x6e, 0xcc, 0x5e, 0xc3, 0xd0, 0x7b, 0xdd, 0xa3, 0x40, 0xe8, 0x24, 0xdd, 0xcc, 0x58, 0x8a, + 0x49, 0xb4, 0xac, 0x57, 0x6d, 0x9c, 0x1c, 0xf6, 0xe0, 0x0c, 0xb4, 0xcc, 0x32, 0x27, 0x5a, 0x0f, 0x16, 0x42, 0x73, + 0x6e, 0x6c, 0x30, 0xdd, 0x5b, 0x28, 0xdd, 0x11, 0x41, 0x63, 0xf7, 0x98, 0xca, 0x56, 0x44, 0x25, 0xa5, 0x88, 0x78, + 0x63, 0x20, 0x4c, 0x2f, 0x7e, 0x9d, 0x9a, 0x53, 0xdf, 0xf6, 0x51, 0xbe, 0x32, 0xa9, 0x94, 0xb5, 0x5c, 0x48, 0x83, + 0xf1, 0xea, 0xcb, 0x48, 0x08, 0xcd, 0x44, 0x48, 0x91, 0x17, 0xb2, 0x27, 0x60, 0x13, 0x23, 0xbe, 0xc7, 0xa5, 0x84, + 0x32, 0x39, 0x28, 0x55, 0x50, 0x3c, 0x3e, 0xd4, 0x8f, 0x18, 0x10, 0xba, 0x1a, 0x23, 0x89, 0xe5, 0x58, 0xe8, 0x27, + 0xd2, 0x17, 0x34, 0x71, 0x08, 0x5c, 0xe3, 0x07, 0xd1, 0x67, 0x4f, 0xc6, 0xcb, 0x5e, 0x81, 0xcd, 0x39, 0xb0, 0x89, + 0xdc, 0x1c, 0xb4, 0xee, 0x3f, 0x65, 0x02, 0x4d, 0x14, 0x59, 0xeb, 0x39, 0x4b, 0xf6, 0x2c, 0xc5, 0x3c, 0x54, 0x4b, + 0x96, 0x40, 0xa3, 0xa8, 0x88, 0xd0, 0x5f, 0x0e, 0xf6, 0x50, 0xcf, 0x2a, 0x23, 0xb6, 0x30, 0xaf, 0x4e, 0xa8, 0xb2, + 0xd5, 0x51, 0xd2, 0x2b, 0x0b, 0xf5, 0x70, 0x37, 0x80, 0xf1, 0xb5, 0x9f, 0x7b, 0xe3, 0xce, 0xfa, 0x84, 0x6d, 0xcf, + 0x37, 0xb9, 0x38, 0xfe, 0x7a, 0xe6, 0xe5, 0xe1, 0xe0, 0xb9, 0x67, 0xb1, 0xd9, 0x50, 0x09, 0x81, 0x48, 0x26, 0x82, + 0x4a, 0xf5, 0xdb, 0x6c, 0x38, 0x20, 0xb0, 0x83, 0x62, 0x2b, 0xe1, 0xa5, 0x52, 0x51, 0xee, 0xad, 0xd5, 0x58, 0x0e, + 0x1c, 0x8e, 0x21, 0x8d, 0x63, 0x97, 0x98, 0x82, 0x38, 0xd6, 0x67, 0xe9, 0x21, 0xf0, 0x6b, 0x6b, 0x34, 0x4f, 0xec, + 0x90, 0x21, 0xd3, 0xa4, 0x4a, 0x45, 0xfa, 0x39, 0x00, 0x6e, 0x23, 0xa7, 0x17, 0xe9, 0x1f, 0x50, 0x02, 0xfc, 0x2a, + 0x16, 0x7b, 0xa3, 0x32, 0x16, 0xc9, 0xaa, 0xac, 0x56, 0x0a, 0xa7, 0xe3, 0x03, 0xf0, 0xd2, 0xbf, 0x2c, 0x58, 0xa0, + 0x6a, 0xa4, 0x67, 0x0b, 0x77, 0x08, 0xd4, 0x4a, 0xdf, 0x8d, 0x10, 0xb5, 0xee, 0xd7, 0xf5, 0xa8, 0xba, 0xb9, 0x58, + 0x8c, 0x31, 0xb6, 0xdc, 0x9b, 0x4f, 0x2a, 0xb7, 0x6d, 0x31, 0xfa, 0x36, 0x77, 0x60, 0x6b, 0xd2, 0x3d, 0xfd, 0xb0, + 0x3d, 0xe5, 0xe1, 0x25, 0x7e, 0xf3, 0x6a, 0x22, 0x33, 0x79, 0x7c, 0x26, 0x74, 0xef, 0xa9, 0x42, 0xcd, 0x8d, 0x85, + 0x3c, 0xf5, 0xbb, 0xf7, 0x34, 0xe1, 0x87, 0xfa, 0xaf, 0xd4, 0x78, 0x52, 0x93, 0x93, 0xbf, 0x99, 0xc5, 0x64, 0x13, + 0x86, 0xfd, 0xb0, 0x81, 0x20, 0x10, 0x50, 0x25, 0x80, 0xed, 0x51, 0x94, 0xeb, 0x6f, 0x4a, 0xaa, 0x5b, 0xc0, 0x85, + 0xa2, 0x53, 0x51, 0xf7, 0x29, 0xe1, 0x59, 0xcf, 0xb6, 0x5b, 0x28, 0x22, 0x2e, 0xaa, 0x33, 0x71, 0xa2, 0xcd, 0xcf, + 0xd9, 0xfe, 0x51, 0x75, 0x40, 0x87, 0x2c, 0x3e, 0xea, 0x9a, 0x50, 0x10, 0x37, 0xbc, 0x50, 0x86, 0x09, 0x92, 0x08, + 0x65, 0xd3, 0x6c, 0xf7, 0x65, 0xba, 0xc6, 0xad, 0xfd, 0xb9, 0xd0, 0xf7, 0x76, 0x20, 0x12, 0x17, 0x33, 0xd1, 0xac, + 0x08, 0x57, 0xf2, 0xe0, 0x54, 0xd1, 0xe6, 0x2c, 0xc8, 0xd6, 0xec, 0xad, 0x9e, 0x93, 0x39, 0xe0, 0x28, 0xd2, 0x72, + 0xcc, 0x8f, 0x3c, 0x17, 0xcf, 0xd5, 0x67, 0x8b, 0xe4, 0x7e, 0xc9, 0xc6, 0xb6, 0xdd, 0x4b, 0xd2, 0x93, 0x1c, 0x60, + 0x22, 0x04, 0xdf, 0x94, 0x90, 0x0e, 0xc0, 0xfa, 0xda, 0xb2, 0x04, 0x99, 0xa9, 0x02, 0x22, 0x93, 0xe9, 0xfc, 0xda, + 0x93, 0x83, 0xa0, 0x33, 0x15, 0x70, 0xc0, 0x10, 0x7e, 0x06, 0x06, 0x1a, 0xdf, 0x73, 0x90, 0xa4, 0x44, 0x43, 0x32, + 0xc5, 0x3d, 0x20, 0x52, 0xc0, 0xcd, 0x37, 0x4f, 0xb6, 0x68, 0x5d, 0x19, 0xa7, 0x90, 0x5e, 0xd2, 0x7a, 0x30, 0x25, + 0x31, 0x9e, 0x49, 0xb8, 0xc5, 0xf1, 0xcf, 0x96, 0xc0, 0xeb, 0x44, 0x5e, 0xa5, 0x64, 0x4b, 0xce, 0x09, 0x0c, 0x2e, + 0x47, 0x2b, 0x36, 0xb0, 0xb8, 0x7e, 0x0a, 0x6b, 0x8c, 0x27, 0x59, 0x1e, 0x8b, 0x9b, 0xbf, 0xef, 0xbf, 0xf5, 0xc8, + 0xee, 0xb3, 0xdd, 0x9d, 0x4f, 0x4d, 0x6b, 0x05, 0x83, 0x18, 0x53, 0xb2, 0x01, 0x6a, 0x05, 0xcf, 0x6c, 0xc8, 0xd8, + 0x95, 0xe6, 0x59, 0xe0, 0xa8, 0x67, 0xbb, 0x6f, 0xcd, 0xee, 0x58, 0xbe, 0x41, 0xfc, 0x44, 0x43, 0xd8, 0x78, 0xa7, + 0x02, 0x9b, 0xa8, 0xe5, 0xf7, 0xe8, 0xb7, 0xbb, 0xb3, 0x1d, 0xda, 0xab, 0x78, 0x37, 0x8d, 0x67, 0x19, 0x53, 0x59, + 0x96, 0xbf, 0x8f, 0x9e, 0xf9, 0xd1, 0xd1, 0x12, 0x86, 0xfa, 0xc8, 0x39, 0x4e, 0xd3, 0x38, 0xe8, 0x08, 0xf5, 0x84, + 0x1d, 0x7f, 0x87, 0x88, 0xff, 0xef, 0x0c, 0xff, 0x77, 0xf0, 0xbf, 0xe7, 0xf8, 0x17, 0xa1, 0xae, 0xf3, 0xd5, 0xe6, + 0xaf, 0x28, 0xff, 0x8d, 0x8f, 0x64, 0x9d, 0xbf, 0xda, 0xdb, 0x7d, 0x61, 0x5a, 0x6f, 0x92, 0x47, 0x6b, 0x13, 0x05, + 0xf4, 0xd5, 0xe3, 0xce, 0xe9, 0x04, 0x51, 0xe6, 0xd4, 0xf9, 0x88, 0xf2, 0xfb, 0x6e, 0x70, 0xe1, 0x17, 0xe3, 0x06, + 0x96, 0xad, 0x2f, 0xff, 0xf4, 0xaf, 0x90, 0xcb, 0x7d, 0x7e, 0xce, 0xb5, 0xad, 0x68, 0x94, 0xfd, 0x7d, 0x68, 0xdc, + 0x11, 0x41, 0x0d, 0xe7, 0xfe, 0xf3, 0x44, 0xf3, 0x4f, 0x06, 0x97, 0x22, 0x47, 0x6b, 0x85, 0xc5, 0x67, 0xfe, 0x4c, + 0x2b, 0x7b, 0xdf, 0xb8, 0x75, 0x65, 0x1b, 0x5a, 0x8c, 0x36, 0xdd, 0x00, 0x83, 0x49, 0x05, 0xad, 0x95, 0xb5, 0xfb, + 0xfc, 0x97, 0x89, 0x31, 0x24, 0x3c, 0xfa, 0xd9, 0xaf, 0x81, 0xfa, 0x8d, 0x6b, 0xb3, 0x06, 0x12, 0x5b, 0xa6, 0xe7, + 0x2f, 0x05, 0xb3, 0x09, 0x0d, 0x0f, 0xf5, 0x74, 0xa9, 0xf7, 0xea, 0xb3, 0x48, 0x34, 0xc6, 0xed, 0x50, 0x5c, 0x5f, + 0x01, 0x0a, 0xa4, 0x38, 0x4f, 0x97, 0xff, 0xc7, 0x5f, 0x88, 0xa2, 0xeb, 0x12, 0x3a, 0x2a, 0xe7, 0xa4, 0xe6, 0xa7, + 0xd0, 0x4b, 0x54, 0x7a, 0xa9, 0x12, 0x75, 0x54, 0x4c, 0x3c, 0x0b, 0x82, 0xeb, 0x8a, 0x9c, 0x9b, 0x5c, 0x0d, 0xe7, + 0x64, 0xdc, 0xe7, 0xff, 0x38, 0xcb, 0x49, 0x82, 0x87, 0xc0, 0x8c, 0xef, 0xec, 0x0a, 0x61, 0x49, 0x5e, 0xc3, 0xc1, + 0xec, 0xc1, 0xb0, 0x7c, 0x52, 0x03, 0x0d, 0x86, 0xf9, 0xf3, 0x05, 0x24, 0xe0, 0x1b, 0xdf, 0x0c, 0x52, 0xa3, 0xe2, + 0xa9, 0x3d, 0xad, 0x43, 0x95, 0x36, 0x06, 0x86, 0x21, 0x11, 0xc1, 0x21, 0xe7, 0x00, 0xf1, 0x41, 0xa7, 0xb3, 0xa3, + 0x8d, 0x63, 0x26, 0xa7, 0xe4, 0xa0, 0x1f, 0xe7, 0x52, 0x15, 0xca, 0xa1, 0x96, 0xd4, 0x51, 0xd1, 0x90, 0xe3, 0x32, + 0x3a, 0xd0, 0xa2, 0xdb, 0x2b, 0xc8, 0xfa, 0x32, 0x17, 0xef, 0xb2, 0xd9, 0xea, 0x91, 0x08, 0x33, 0x89, 0x18, 0xa9, + 0xe0, 0xb4, 0x64, 0x55, 0x0c, 0xfd, 0xa2, 0x25, 0xa6, 0x36, 0xe2, 0xe9, 0xde, 0x5a, 0x3a, 0x75, 0x1e, 0x79, 0x70, + 0x65, 0x90, 0xbd, 0xe2, 0x35, 0xe0, 0xde, 0x24, 0x1b, 0x66, 0x19, 0x2b, 0xb8, 0xb0, 0xbe, 0xf6, 0x69, 0xf5, 0xc1, + 0xbe, 0x43, 0xc1, 0x79, 0xf6, 0x5e, 0x0c, 0xba, 0x19, 0xec, 0x82, 0xea, 0x8d, 0xfd, 0x3c, 0x0d, 0xf8, 0xdd, 0x03, + 0xa5, 0xa0, 0xc0, 0x31, 0xa8, 0xa7, 0x3b, 0x7f, 0x43, 0x04, 0x7e, 0x60, 0x37, 0x60, 0x9d, 0xb3, 0x6d, 0xc1, 0x95, + 0x84, 0x6a, 0x20, 0xd5, 0x65, 0x2c, 0x0b, 0x6c, 0xa7, 0x87, 0x2d, 0xae, 0x7b, 0x8e, 0x06, 0xa5, 0xba, 0x37, 0x13, + 0x94, 0x89, 0xa3, 0x65, 0xae, 0x03, 0x5b, 0x04, 0x30, 0xb2, 0x15, 0xe1, 0x36, 0x20, 0xaf, 0x2e, 0x66, 0x34, 0xf4, + 0x87, 0xb8, 0x9a, 0x04, 0x34, 0xa0, 0x91, 0x8b, 0x8e, 0x17, 0x5d, 0x2f, 0x9d, 0xd2, 0xdb, 0xe3, 0x09, 0x72, 0xb0, + 0x73, 0x16, 0x86, 0xf2, 0x7a, 0x92, 0xf3, 0xa5, 0xe7, 0xbf, 0x9e, 0x10, 0xed, 0xf5, 0x31, 0x86, 0xb3, 0x85, 0x94, + 0xc4, 0x06, 0x32, 0xb4, 0x3a, 0x8e, 0xe8, 0xe0, 0x21, 0x0f, 0xe8, 0x49, 0x69, 0x96, 0xd7, 0x4d, 0x88, 0x8a, 0xb9, + 0x08, 0x95, 0xc8, 0xcb, 0xe2, 0x9a, 0xad, 0x2b, 0x10, 0x98, 0xd9, 0x2e, 0xf8, 0x82, 0xa3, 0xd1, 0xca, 0xf0, 0x82, + 0x30, 0x27, 0x8c, 0x90, 0xc5, 0xfa, 0x27, 0xc0, 0x1b, 0xbe, 0x06, 0x45, 0xfe, 0x64, 0x5c, 0x12, 0x9e, 0x59, 0xe6, + 0x0e, 0xe1, 0x84, 0x9f, 0x2a, 0x61, 0x75, 0x17, 0x15, 0xfa, 0xc7, 0xf3, 0x52, 0x50, 0x1c, 0x35, 0x06, 0x0c, 0xfb, + 0x22, 0x04, 0x91, 0x8a, 0xd2, 0xec, 0x3b, 0x88, 0x54, 0xf7, 0x03, 0xb1, 0x1e, 0x8e, 0x68, 0xc3, 0x23, 0x11, 0xc8, + 0x1f, 0x49, 0xb5, 0xd0, 0xc6, 0x47, 0x22, 0x24, 0xbd, 0x7d, 0xf3, 0xc1, 0x79, 0xb9, 0x29, 0xaa, 0x2c, 0xa3, 0xd0, + 0x27, 0x3a, 0xa8, 0x9c, 0xea, 0xf1, 0x7a, 0x96, 0xda, 0x0a, 0xae, 0x5b, 0x2b, 0x81, 0x8a, 0x8d, 0xe9, 0x32, 0xf7, + 0x91, 0xed, 0xb5, 0x4b, 0x29, 0xf1, 0xe7, 0x79, 0xc6, 0x1a, 0x8e, 0x04, 0xec, 0xa6, 0x17, 0x86, 0xb1, 0x93, 0x1d, + 0x43, 0x47, 0x92, 0xf4, 0x82, 0xd2, 0x74, 0x8c, 0x91, 0x9b, 0xd7, 0xdd, 0x60, 0xbb, 0x8a, 0xc1, 0x57, 0x03, 0xc3, + 0x39, 0x34, 0x69, 0x38, 0x29, 0x38, 0xd7, 0xad, 0xfb, 0xeb, 0x78, 0xe9, 0x3c, 0x2f, 0xfb, 0x18, 0x96, 0x47, 0x3c, + 0xd7, 0xf6, 0x5f, 0x2f, 0xe4, 0xf9, 0x7a, 0x09, 0xcb, 0xd6, 0x5f, 0x93, 0xe4, 0x08, 0xd9, 0xcf, 0x2a, 0xa2, 0xe6, + 0x17, 0x8c, 0x43, 0xe4, 0x4f, 0x71, 0x4c, 0x15, 0xcd, 0x5c, 0x75, 0x7a, 0x54, 0x7a, 0x83, 0x5e, 0x3c, 0x3c, 0x20, + 0x38, 0x09, 0x90, 0x27, 0x4e, 0x42, 0x18, 0x30, 0xe4, 0x14, 0xd6, 0x7c, 0x05, 0x3c, 0xe6, 0x71, 0xc3, 0x53, 0x9a, + 0xab, 0x3f, 0x01, 0x34, 0xa0, 0x02, 0xea, 0xc3, 0x0e, 0x5f, 0x2c, 0xc1, 0x86, 0x46, 0x08, 0x21, 0x9f, 0x10, 0xfc, + 0x2e, 0xff, 0x4a, 0x50, 0x16, 0x3b, 0x05, 0x32, 0x5a, 0xa7, 0xda, 0x15, 0x93, 0x95, 0x36, 0xa8, 0xff, 0x96, 0x76, + 0x53, 0x5e, 0x10, 0x39, 0x88, 0x50, 0x01, 0x06, 0xb2, 0xda, 0x50, 0xe0, 0xd5, 0x65, 0x9b, 0x69, 0x06, 0x63, 0xf5, + 0x51, 0xd3, 0x66, 0xef, 0xf6, 0x4a, 0x4f, 0x65, 0x40, 0xd4, 0x06, 0x86, 0x77, 0xfd, 0xcf, 0xe1, 0x69, 0x19, 0xcf, + 0x8b, 0x41, 0x35, 0x4e, 0x87, 0xc8, 0x70, 0x9d, 0x3a, 0x56, 0xad, 0xfc, 0xcf, 0x94, 0x12, 0xe3, 0x53, 0x51, 0xe1, + 0xc0, 0xba, 0x6a, 0xa8, 0x5a, 0x10, 0xa6, 0x8d, 0xd2, 0x3f, 0x28, 0xca, 0xa0, 0x05, 0x58, 0x1a, 0xb5, 0xc6, 0x01, + 0x9b, 0x9a, 0x5e, 0x9e, 0x1b, 0xd3, 0x89, 0x57, 0xfb, 0x9b, 0xc0, 0x84, 0xbb, 0xfa, 0x31, 0x87, 0xba, 0xb6, 0x78, + 0xae, 0xef, 0xbb, 0x8f, 0xa7, 0x3c, 0x24, 0x7a, 0x26, 0x16, 0x9a, 0xb2, 0xb9, 0xce, 0xe7, 0x1d, 0x14, 0x1b, 0x5e, + 0xd8, 0xe7, 0x2b, 0x24, 0xc8, 0x01, 0x87, 0x4d, 0x71, 0x35, 0x0e, 0xcf, 0x38, 0x27, 0x2a, 0x7d, 0x2e, 0xf6, 0x83, + 0x03, 0x38, 0x3c, 0xe7, 0x4a, 0x59, 0xcb, 0xe7, 0x6f, 0xd3, 0x19, 0x4f, 0xfa, 0x12, 0x9c, 0x94, 0x32, 0xf1, 0x8a, + 0xc5, 0x9f, 0xf1, 0xf1, 0x11, 0x67, 0x78, 0x7f, 0xa3, 0xf3, 0x69, 0x7f, 0x9b, 0xae, 0x8d, 0x79, 0x0f, 0xf2, 0x46, + 0x05, 0xcf, 0x5d, 0x58, 0xc6, 0x36, 0x51, 0x40, 0xf0, 0x37, 0x3a, 0xa7, 0x69, 0x1e, 0x42, 0x3c, 0xac, 0xa2, 0x22, + 0xbf, 0xa3, 0x48, 0x96, 0x68, 0xe1, 0x6d, 0x4e, 0x8b, 0xf4, 0x6a, 0x7a, 0xde, 0xe6, 0x4b, 0x99, 0x0e, 0xed, 0xc6, + 0xd4, 0x49, 0xb4, 0xaa, 0x30, 0x21, 0x88, 0xc0, 0x9d, 0x2e, 0x91, 0x60, 0xb7, 0x26, 0xb3, 0x27, 0xfc, 0x6b, 0x4c, + 0xe3, 0x20, 0x6e, 0xd9, 0x73, 0x8b, 0x7d, 0x4f, 0xcd, 0x1c, 0xe8, 0x85, 0x9c, 0xa1, 0x38, 0x64, 0x0c, 0xfa, 0x42, + 0xae, 0x1f, 0x8f, 0xd0, 0x49, 0x05, 0xf8, 0x55, 0xc9, 0xaf, 0x7a, 0xbc, 0x96, 0x0a, 0x95, 0xea, 0x6c, 0x22, 0x47, + 0xfb, 0xb3, 0xb4, 0xf1, 0x18, 0xfb, 0xb1, 0x3c, 0x7d, 0xed, 0xe9, 0x04, 0x50, 0xb1, 0x25, 0xb7, 0xb2, 0x6f, 0xc8, + 0x43, 0x4b, 0xbf, 0x79, 0x9c, 0x61, 0xe6, 0x08, 0xd0, 0xd9, 0xaa, 0xe0, 0xa9, 0x8b, 0xd9, 0xdb, 0x5b, 0x6e, 0x2a, + 0xb6, 0xdf, 0xf0, 0x19, 0x60, 0x27, 0x89, 0x40, 0x34, 0xaa, 0xf6, 0x59, 0xa7, 0x31, 0x79, 0x2a, 0x9e, 0x42, 0x23, + 0x60, 0x29, 0x22, 0xd7, 0x94, 0x68, 0x5d, 0xcb, 0xd0, 0x45, 0x72, 0x7c, 0xbb, 0x1c, 0x82, 0x04, 0x77, 0x68, 0xd6, + 0x48, 0xe8, 0xa9, 0xba, 0x62, 0xae, 0x54, 0x95, 0x50, 0x77, 0x3a, 0x4c, 0x79, 0x6e, 0xac, 0xf0, 0x28, 0x73, 0xd1, + 0xb9, 0x8e, 0x55, 0x25, 0xc2, 0x22, 0x2e, 0xce, 0x02, 0x2f, 0x02, 0xfc, 0x08, 0x0c, 0xe2, 0x52, 0x95, 0x65, 0xa6, + 0x08, 0x49, 0x93, 0x6d, 0x81, 0xb1, 0xe2, 0xd0, 0x6f, 0xa2, 0x9a, 0x07, 0x5f, 0xff, 0x34, 0xa1, 0x28, 0xec, 0x04, + 0x44, 0xa3, 0x41, 0xb7, 0x16, 0xd0, 0xcc, 0xfc, 0x9b, 0x72, 0x78, 0x0c, 0x9d, 0x27, 0xf1, 0x86, 0x25, 0xc9, 0xa2, + 0x3f, 0xff, 0x97, 0x06, 0x61, 0xd2, 0x3b, 0x90, 0x52, 0x95, 0x40, 0xbb, 0x61, 0x6e, 0x3e, 0x89, 0x0c, 0xd9, 0xa2, + 0x5c, 0xec, 0x71, 0x94, 0x73, 0x1b, 0xd2, 0x0a, 0x66, 0x5e, 0x42, 0xc9, 0x3b, 0x5a, 0xaf, 0xbc, 0x0e, 0xab, 0x6e, + 0x79, 0x8d, 0x97, 0x38, 0xd1, 0x2f, 0x58, 0x74, 0x4d, 0xae, 0xc1, 0x6d, 0x42, 0x03, 0x32, 0x2b, 0x13, 0xd5, 0x1b, + 0x82, 0xa7, 0x90, 0xb2, 0x31, 0xe0, 0xe2, 0xdc, 0xe0, 0xd1, 0xf9, 0x9c, 0x90, 0xb2, 0x90, 0x0b, 0xcd, 0x00, 0x27, + 0x31, 0x92, 0xd1, 0xa6, 0x2e, 0xe5, 0x42, 0x9d, 0x7e, 0xe0, 0xad, 0x83, 0x1e, 0xd6, 0x66, 0x67, 0x2b, 0xf6, 0xb2, + 0x5e, 0x31, 0xb2, 0xa6, 0xea, 0x72, 0x52, 0x6e, 0x4a, 0x68, 0x68, 0x3f, 0xc6, 0x7b, 0x19, 0x87, 0x1c, 0x66, 0xd5, + 0x18, 0x89, 0x3d, 0x23, 0x39, 0xb3, 0x49, 0x92, 0x65, 0xd6, 0x65, 0x2d, 0xfd, 0x6c, 0xae, 0xfd, 0x8f, 0x6c, 0xe1, + 0x11, 0xcb, 0x38, 0xbf, 0xd2, 0x43, 0x49, 0xb8, 0xb2, 0x4e, 0x93, 0xe7, 0xe9, 0x07, 0xe1, 0xba, 0xdb, 0xd4, 0x8c, + 0x86, 0xf7, 0x80, 0x84, 0x2c, 0x6d, 0xd9, 0xaa, 0x36, 0x36, 0x36, 0xf8, 0xb9, 0xcf, 0x03, 0x0b, 0xf1, 0xa0, 0x21, + 0x19, 0xfd, 0x7c, 0x9b, 0xc7, 0x86, 0x85, 0xce, 0xe8, 0xa0, 0x94, 0x5e, 0x4b, 0x71, 0xee, 0x05, 0x4a, 0x2c, 0xf8, + 0x72, 0xaf, 0xa4, 0xc9, 0x99, 0x07, 0x7e, 0x10, 0x67, 0x46, 0x17, 0x99, 0x77, 0xbe, 0x46, 0xdd, 0x4a, 0xef, 0x95, + 0x96, 0xf4, 0x83, 0x5f, 0xfd, 0x6c, 0x95, 0x5e, 0xa7, 0x5f, 0x22, 0x73, 0xe6, 0x2b, 0x5c, 0xa2, 0x5d, 0x81, 0x1d, + 0xc6, 0x49, 0x5d, 0xf3, 0xeb, 0x0e, 0xd0, 0xfb, 0xc2, 0x9b, 0x81, 0x46, 0x89, 0xc0, 0x0b, 0x4d, 0x2e, 0x71, 0x25, + 0xbe, 0x10, 0xde, 0x14, 0x7b, 0x98, 0xc1, 0x44, 0x6c, 0x14, 0x41, 0x3c, 0x00, 0xff, 0x1c, 0xe2, 0x97, 0x31, 0xbf, + 0xd7, 0x41, 0x6d, 0xb4, 0x20, 0x34, 0x45, 0xe6, 0x26, 0x7b, 0x11, 0x5b, 0x90, 0xc3, 0x2b, 0x81, 0x04, 0xb9, 0x66, + 0x8d, 0x1d, 0xb0, 0x65, 0x5b, 0xa1, 0x6c, 0xde, 0x70, 0x6c, 0xb0, 0x3b, 0x7b, 0x69, 0x6d, 0x12, 0x84, 0xb8, 0x44, + 0xd4, 0x9a, 0x1e, 0x19, 0xe5, 0xab, 0x96, 0x82, 0x4a, 0xf4, 0xf3, 0xf4, 0xbf, 0xb1, 0x49, 0x6f, 0x17, 0x04, 0xfd, + 0x52, 0x64, 0xda, 0x2f, 0x34, 0x0c, 0x4a, 0x8b, 0xbc, 0xff, 0x43, 0x09, 0x7c, 0x1d, 0xac, 0xe9, 0x3a, 0xd5, 0x6e, + 0x7d, 0xf1, 0x4f, 0x50, 0x3d, 0x4f, 0xc6, 0x1d, 0x46, 0x2e, 0x0c, 0x68, 0x7e, 0x6f, 0x24, 0x9d, 0xb7, 0xfe, 0xcf, + 0x12, 0x02, 0x67, 0x90, 0x25, 0x14, 0xae, 0x11, 0xf9, 0x26, 0xff, 0xc0, 0x30, 0xed, 0x15, 0xc1, 0xce, 0x8e, 0xbc, + 0x37, 0xb6, 0x93, 0x75, 0x88, 0x36, 0xf4, 0x0d, 0x98, 0xb2, 0x7e, 0xa3, 0x59, 0x36, 0x40, 0x6d, 0x3b, 0xe3, 0xb6, + 0x2b, 0x69, 0x16, 0x92, 0xe1, 0x99, 0xc5, 0x20, 0xd5, 0x46, 0x7e, 0xe6, 0x95, 0x85, 0x33, 0x73, 0x77, 0xa1, 0x91, + 0x9f, 0x3d, 0x9d, 0xe1, 0xf0, 0xc6, 0x46, 0x7a, 0xe1, 0x09, 0x4b, 0x73, 0x43, 0x07, 0x00, 0x20, 0x5c, 0x2a, 0x3a, + 0xde, 0xb1, 0x54, 0xd9, 0x4a, 0xd4, 0x57, 0x82, 0xe6, 0xe0, 0x38, 0x1b, 0x5d, 0xc8, 0x27, 0x4c, 0x18, 0xe9, 0x79, + 0x0e, 0x11, 0x8f, 0x63, 0xe5, 0x32, 0x18, 0x32, 0x07, 0x3f, 0x91, 0x60, 0x47, 0xb3, 0xc3, 0x59, 0x0e, 0x57, 0xa9, + 0x5f, 0x27, 0xa8, 0x86, 0xd4, 0x58, 0x65, 0x6c, 0xc3, 0xfa, 0xff, 0x0a, 0x27, 0x2e, 0xeb, 0x79, 0x42, 0x2f, 0x3a, + 0x2c, 0xdc, 0xc2, 0x47, 0x2e, 0xf9, 0x87, 0x38, 0x38, 0xc4, 0xd9, 0x18, 0xe7, 0x19, 0x48, 0x9e, 0x36, 0x50, 0x18, + 0x79, 0x39, 0xbe, 0x54, 0x72, 0xb6, 0x1b, 0xaa, 0x4a, 0x4a, 0x97, 0x74, 0xab, 0xbd, 0x67, 0xb2, 0x1f, 0x91, 0x13, + 0x27, 0x45, 0x24, 0x99, 0x4c, 0x2a, 0xa8, 0x53, 0x1a, 0x6c, 0xfa, 0x15, 0xc0, 0x08, 0xe6, 0x5a, 0xd7, 0x34, 0x45, + 0x69, 0x99, 0x70, 0xf8, 0x1c, 0x2d, 0xd6, 0x99, 0x43, 0xd1, 0xc1, 0x60, 0x50, 0x48, 0x33, 0xb4, 0x0b, 0x3c, 0xc8, + 0xa8, 0xcc, 0x1e, 0x7f, 0x9e, 0x9f, 0x14, 0x4d, 0xd8, 0x64, 0xc5, 0x2a, 0x51, 0xa4, 0x96, 0xb1, 0xa4, 0x54, 0x75, + 0xfe, 0xed, 0x3e, 0x1a, 0x1a, 0x1d, 0x58, 0x03, 0x3a, 0x0a, 0x25, 0x9c, 0xf7, 0x50, 0x3c, 0xe9, 0x4e, 0xcd, 0xde, + 0x7e, 0xeb, 0x77, 0x57, 0x1f, 0xe2, 0x54, 0xdf, 0x25, 0x9d, 0xdc, 0x37, 0x9e, 0xb0, 0x9d, 0xb1, 0xd7, 0xba, 0xbe, + 0x63, 0x0b, 0x60, 0x97, 0x19, 0xcf, 0xc6, 0xf0, 0xbe, 0x8e, 0xbd, 0xf8, 0x82, 0x5c, 0x3d, 0x7f, 0xd6, 0x6a, 0xf9, + 0x8c, 0x5b, 0x0a, 0xa7, 0x1c, 0xa1, 0x85, 0x45, 0x40, 0x76, 0xc0, 0x28, 0x20, 0x2f, 0xa1, 0xcb, 0x18, 0xc2, 0x83, + 0x5f, 0x1b, 0x14, 0xad, 0x0e, 0x38, 0x13, 0xe8, 0x51, 0x3f, 0xe8, 0xc1, 0xdf, 0x74, 0x12, 0x6f, 0x4c, 0xbc, 0xb7, + 0x68, 0x4a, 0xbf, 0x5a, 0x69, 0x53, 0xa6, 0x3c, 0xbb, 0xe4, 0xc3, 0xd8, 0x0e, 0x55, 0x5b, 0xbb, 0x0d, 0x35, 0xc4, + 0x67, 0xb8, 0x9f, 0xb8, 0xa2, 0x78, 0x6c, 0x06, 0xea, 0x6f, 0xfc, 0xc8, 0x3b, 0x6d, 0x3f, 0x92, 0xfb, 0x10, 0x87, + 0x1e, 0xcb, 0xbe, 0x2a, 0xfb, 0x00, 0xae, 0xd9, 0xd9, 0x58, 0x89, 0x9f, 0x15, 0x61, 0xb8, 0x1c, 0x82, 0xf1, 0x67, + 0xb5, 0x0d, 0x3d, 0xa9, 0xa7, 0xac, 0x79, 0xfc, 0x3a, 0x32, 0xbf, 0xc9, 0xc2, 0xa4, 0x5e, 0xc8, 0x9a, 0x1e, 0xa7, + 0x33, 0x43, 0xe7, 0x4c, 0xe4, 0xee, 0xd9, 0xaf, 0xd1, 0xda, 0xc8, 0x48, 0xed, 0x6c, 0xd1, 0xc7, 0xdf, 0x35, 0x55, + 0x36, 0x9a, 0x34, 0xe3, 0xb1, 0x73, 0xad, 0x4b, 0x97, 0xba, 0x8c, 0x4c, 0xf7, 0x67, 0xbd, 0x58, 0x50, 0xa5, 0x55, + 0x66, 0xde, 0x27, 0x52, 0xc3, 0xb8, 0xd6, 0x6a, 0xe2, 0x9d, 0x5e, 0x7c, 0xcb, 0x8e, 0xdd, 0x74, 0x96, 0x64, 0x30, + 0x98, 0x8e, 0xdc, 0x0c, 0x1d, 0xc9, 0x08, 0x53, 0xbf, 0x7c, 0x32, 0x30, 0xeb, 0x3a, 0x7f, 0x6f, 0x5f, 0x33, 0x8e, + 0xe2, 0x5b, 0x8f, 0x15, 0xfd, 0xb6, 0x4e, 0xb7, 0xef, 0x09, 0x70, 0x6d, 0x53, 0xfb, 0xd4, 0x5b, 0xa5, 0x9c, 0x8d, + 0xe4, 0x58, 0x4e, 0xe2, 0x09, 0x14, 0x3c, 0x00, 0x49, 0x04, 0x4c, 0x9a, 0xf9, 0xc5, 0x52, 0xc9, 0x84, 0x8d, 0xba, + 0xdb, 0xef, 0x15, 0x17, 0x18, 0xb5, 0x7f, 0x94, 0xb9, 0x9a, 0x5e, 0x8e, 0x14, 0x25, 0xd3, 0x81, 0x81, 0xa6, 0x30, + 0x96, 0x3e, 0xff, 0x62, 0x5b, 0x89, 0x05, 0x95, 0x45, 0xb1, 0xb0, 0x66, 0x74, 0x00, 0x22, 0xe8, 0x63, 0x2a, 0xa8, + 0x1a, 0x7e, 0x43, 0xca, 0xe7, 0xf4, 0xeb, 0xd9, 0xf9, 0x88, 0x6d, 0xba, 0x29, 0x7d, 0x8c, 0x07, 0xab, 0xec, 0x75, + 0x7e, 0x1f, 0x9f, 0xfa, 0x42, 0x2f, 0x5e, 0x49, 0xde, 0x59, 0xf7, 0x4f, 0xf3, 0xcf, 0xe7, 0x6c, 0xfe, 0xf9, 0xac, + 0x19, 0x60, 0x98, 0xd9, 0x18, 0xf7, 0x2a, 0x7a, 0xb5, 0xc0, 0x35, 0x4e, 0x65, 0x78, 0x1a, 0xcb, 0x7f, 0x74, 0x16, + 0xae, 0x32, 0xc0, 0x99, 0x6c, 0xa0, 0x4d, 0x65, 0x10, 0x7c, 0x73, 0xc3, 0x82, 0xa6, 0x2b, 0x27, 0x26, 0x9a, 0x99, + 0x48, 0x5c, 0x82, 0x9c, 0xc4, 0x1c, 0xec, 0xc9, 0xa5, 0xea, 0x3a, 0x25, 0x33, 0x7e, 0x66, 0xda, 0x82, 0x9e, 0xa0, + 0xf0, 0x53, 0x90, 0xa9, 0x00, 0x41, 0x74, 0xbe, 0x4f, 0xf3, 0x38, 0x4a, 0x7f, 0xe7, 0x98, 0xa7, 0xfc, 0xff, 0x89, + 0x2c, 0x11, 0xa9, 0x6b, 0x19, 0xc2, 0x01, 0xbf, 0x46, 0x34, 0x75, 0xc6, 0xef, 0xc5, 0xa0, 0x7e, 0x91, 0xde, 0xaa, + 0x11, 0x38, 0x17, 0xa0, 0xae, 0x46, 0x98, 0x06, 0xf2, 0x8e, 0xf6, 0x1a, 0xf9, 0xc5, 0xa9, 0xd2, 0x2d, 0x7b, 0x5a, + 0xf2, 0x8a, 0x2c, 0x54, 0xfe, 0xc9, 0x98, 0x62, 0x56, 0x15, 0x1d, 0x47, 0x9a, 0xf7, 0x0d, 0x36, 0xc9, 0x17, 0x4e, + 0x12, 0x7a, 0xca, 0xa9, 0xb1, 0x30, 0x6e, 0x15, 0x5e, 0xda, 0x85, 0xd1, 0x07, 0x64, 0x0e, 0x34, 0x17, 0x65, 0x3f, + 0x0e, 0x71, 0x44, 0x7c, 0xa0, 0x9f, 0xf1, 0x2d, 0x64, 0xdc, 0xf6, 0x1c, 0x27, 0xc4, 0xa9, 0xfa, 0x62, 0x28, 0x5e, + 0xc6, 0x26, 0x15, 0x92, 0x1b, 0xb2, 0x18, 0xca, 0xaa, 0x85, 0xe7, 0x67, 0xf0, 0x7c, 0xe1, 0xf9, 0x69, 0x9e, 0x1b, + 0xbc, 0x25, 0x53, 0x51, 0x46, 0x62, 0xed, 0x0a, 0x3b, 0x6a, 0xf9, 0x4d, 0x5e, 0x61, 0xef, 0x73, 0x00, 0x12, 0xd5, + 0x5e, 0x15, 0x0b, 0x72, 0x01, 0x1b, 0xd0, 0xa0, 0x3a, 0x0c, 0xf2, 0x12, 0x5f, 0x0a, 0x20, 0x00, 0xa3, 0x07, 0xef, + 0xd9, 0x71, 0x3a, 0x6d, 0x0c, 0xe3, 0x2e, 0xc7, 0x04, 0x4a, 0xae, 0xd9, 0x54, 0x12, 0xf2, 0x26, 0x27, 0x9c, 0x7d, + 0x01, 0x2a, 0x84, 0x31, 0x80, 0x3c, 0x35, 0xb6, 0x58, 0xbd, 0x7e, 0x2b, 0xd5, 0xe7, 0x04, 0xa3, 0xb0, 0x97, 0x98, + 0x7d, 0xa1, 0x1b, 0x11, 0x11, 0x39, 0x8b, 0x39, 0xb9, 0xf4, 0xda, 0x55, 0xea, 0xfb, 0xd1, 0xd9, 0x27, 0x04, 0xf4, + 0xed, 0xe4, 0x5b, 0x73, 0x13, 0x0e, 0xc7, 0x97, 0x2c, 0x33, 0xd1, 0x7f, 0xae, 0x16, 0xc8, 0xb3, 0x32, 0xe7, 0x3d, + 0x57, 0xc7, 0xae, 0x89, 0x34, 0xc5, 0xa6, 0xa0, 0x53, 0x70, 0x4a, 0x10, 0x41, 0x5b, 0x70, 0x92, 0xe4, 0x90, 0x88, + 0xca, 0x40, 0x7f, 0x36, 0x15, 0x4b, 0x30, 0x5b, 0xc3, 0x52, 0x9d, 0xd7, 0x5a, 0xec, 0x9a, 0x1f, 0xb2, 0x27, 0x99, + 0x65, 0xc3, 0x45, 0xea, 0x4c, 0x27, 0xc5, 0x75, 0x64, 0x8d, 0xc2, 0xd4, 0xb8, 0x8b, 0xc5, 0xab, 0x84, 0x2b, 0xa9, + 0xdc, 0xa4, 0x4a, 0xbc, 0xd9, 0xa8, 0x19, 0x8f, 0xc6, 0xe5, 0x8f, 0x6d, 0x76, 0xf4, 0x46, 0x4a, 0xc0, 0xe3, 0x21, + 0xd5, 0xde, 0xa6, 0x33, 0x6e, 0x43, 0xfe, 0xed, 0xea, 0x69, 0x0b, 0x58, 0xfc, 0x4f, 0x7a, 0x18, 0xe2, 0xff, 0x8d, + 0x0a, 0x8a, 0xc8, 0x36, 0x42, 0x78, 0x14, 0x02, 0x84, 0xfb, 0xc2, 0xc9, 0x0b, 0x62, 0x51, 0xc4, 0xa3, 0xb0, 0xf7, + 0x3a, 0x6b, 0xe5, 0x12, 0x16, 0x7f, 0x1f, 0x74, 0xff, 0x8e, 0x42, 0xe7, 0x5c, 0xaf, 0xf1, 0xa7, 0xe2, 0xc7, 0x1f, + 0x39, 0x76, 0x74, 0x28, 0xc2, 0x4d, 0x0c, 0xad, 0x04, 0xcf, 0xb6, 0x44, 0x75, 0xac, 0x0a, 0x46, 0x84, 0x30, 0x07, + 0xa9, 0x6a, 0xc1, 0x04, 0xbb, 0xf0, 0x13, 0x2c, 0x3e, 0x10, 0x4e, 0xff, 0x1b, 0x1a, 0xb7, 0x09, 0x61, 0x36, 0x58, + 0xe5, 0xa8, 0x93, 0x27, 0xf1, 0x6a, 0x9f, 0xf9, 0x23, 0xe3, 0xd6, 0x57, 0x5f, 0xa4, 0xd5, 0x48, 0xf6, 0x14, 0x33, + 0x38, 0xbc, 0x76, 0x4b, 0x99, 0x19, 0x9f, 0x23, 0x26, 0x55, 0xf3, 0xe4, 0x45, 0x41, 0xa9, 0xa1, 0xae, 0x59, 0x9e, + 0x0b, 0xf3, 0x9c, 0xe1, 0xb9, 0xc0, 0x60, 0x2c, 0xeb, 0xb2, 0xc6, 0x19, 0x9f, 0xc6, 0x56, 0x0c, 0x8c, 0x3b, 0x1e, + 0x0e, 0x7a, 0x8e, 0x39, 0x54, 0x80, 0x5e, 0x04, 0x6e, 0x22, 0x3e, 0xe9, 0x25, 0x70, 0xea, 0xd4, 0x86, 0xf3, 0xcc, + 0x5c, 0x8e, 0x98, 0xf2, 0x0c, 0xa7, 0x98, 0xd2, 0xef, 0xdc, 0x26, 0xd2, 0x6e, 0x7d, 0xad, 0xc9, 0x47, 0xc1, 0xad, + 0x7a, 0x3a, 0xac, 0x23, 0x1a, 0x97, 0x16, 0xc1, 0x93, 0x45, 0x79, 0xd8, 0xbf, 0xf1, 0x9c, 0x5f, 0x89, 0xb4, 0x93, + 0x52, 0x25, 0x3a, 0x9f, 0x79, 0x0e, 0x42, 0x48, 0x93, 0x96, 0xd0, 0xf6, 0xb9, 0x20, 0x25, 0xc6, 0xb5, 0x53, 0x8a, + 0xd8, 0xcd, 0xc1, 0xfe, 0xd7, 0x53, 0xb9, 0x48, 0xab, 0xeb, 0x87, 0x77, 0x8b, 0x85, 0xd8, 0x4e, 0xc8, 0x79, 0x2e, + 0x64, 0xef, 0xfd, 0x6b, 0x12, 0x5e, 0x27, 0xe5, 0x97, 0xfd, 0x20, 0x71, 0xef, 0x5c, 0x6a, 0xfe, 0x5f, 0x38, 0x6c, + 0x7a, 0xf4, 0xca, 0xc1, 0x6c, 0x33, 0x01, 0x93, 0xa3, 0x52, 0x55, 0xdf, 0x8f, 0x80, 0xd4, 0xf0, 0x30, 0x40, 0x59, + 0xc5, 0xfe, 0x41, 0xbd, 0x25, 0x00, 0xb8, 0xd4, 0xb3, 0xfd, 0xb0, 0xb4, 0xbf, 0xfb, 0x61, 0xab, 0x13, 0x2e, 0x57, + 0x4a, 0xfe, 0x1b, 0x18, 0x42, 0x97, 0x86, 0xe4, 0xb0, 0x75, 0xd6, 0x03, 0x21, 0x77, 0x9e, 0x73, 0x8a, 0x51, 0x5c, + 0x4b, 0xbe, 0x60, 0xfb, 0x91, 0x94, 0xd7, 0xc9, 0x7c, 0x7e, 0xb1, 0xb5, 0x82, 0xcf, 0x3a, 0xa9, 0xbf, 0xa8, 0x44, + 0xff, 0x05, 0xec, 0x3b, 0x88, 0x0f, 0xcf, 0x13, 0xab, 0xca, 0x0f, 0x1d, 0x87, 0x23, 0xac, 0xb0, 0x95, 0x2a, 0x0d, + 0xcd, 0x23, 0xd3, 0xc7, 0x94, 0x9c, 0x9a, 0x80, 0x71, 0x48, 0x72, 0xb6, 0x56, 0x91, 0x4b, 0x92, 0x6a, 0x16, 0xee, + 0xeb, 0x06, 0x9f, 0x84, 0xe9, 0x92, 0x56, 0xe1, 0x1e, 0xa0, 0x7f, 0x0c, 0x7a, 0xfe, 0xcf, 0x4a, 0x71, 0xc0, 0xb0, + 0xea, 0x85, 0x4c, 0xfc, 0x64, 0x00, 0xd7, 0x66, 0x9e, 0xcc, 0x71, 0xe3, 0x6d, 0xd4, 0x47, 0x6d, 0x4b, 0xc0, 0x4f, + 0xa2, 0x27, 0x8f, 0x61, 0x4c, 0x16, 0x86, 0x02, 0x77, 0x2e, 0xf5, 0x73, 0xb0, 0x70, 0xc3, 0x31, 0xfa, 0x86, 0xe0, + 0x5b, 0xfe, 0xfc, 0x0e, 0xd4, 0x71, 0x8c, 0x86, 0x2e, 0x8d, 0xa4, 0xf4, 0x3b, 0x14, 0x44, 0x1a, 0x48, 0xa0, 0x79, + 0xee, 0x6b, 0x28, 0x9c, 0x4e, 0x22, 0x3b, 0xc9, 0x11, 0xd6, 0xce, 0x82, 0x59, 0xab, 0x9c, 0xbe, 0x9e, 0xed, 0x3b, + 0x0c, 0xd0, 0xb5, 0xcb, 0xe9, 0x7d, 0xae, 0xbf, 0x95, 0xa9, 0x9f, 0x2b, 0x84, 0x96, 0x65, 0x9b, 0x9d, 0x43, 0x20, + 0x94, 0x6b, 0xf5, 0x34, 0x44, 0xc1, 0x10, 0xef, 0x74, 0xac, 0x6e, 0xd0, 0x47, 0x2a, 0x5a, 0xe7, 0xab, 0x0d, 0xda, + 0x7c, 0xab, 0xf0, 0xd2, 0xf5, 0xca, 0xf6, 0x34, 0x24, 0xc5, 0x34, 0x62, 0x38, 0xf8, 0x66, 0x42, 0x67, 0xf2, 0x3e, + 0x6e, 0x90, 0x4d, 0x9c, 0x21, 0x79, 0xb8, 0x8e, 0x58, 0xba, 0x4a, 0x58, 0x54, 0xb6, 0xf0, 0x74, 0x4a, 0x3b, 0x5c, + 0xdd, 0x15, 0xe1, 0xe6, 0x4c, 0x06, 0x6a, 0xb9, 0x8e, 0xbe, 0x89, 0xc4, 0x20, 0x07, 0x6c, 0xb9, 0x4e, 0x1f, 0x1d, + 0x55, 0xaa, 0x90, 0xe9, 0x76, 0xde, 0xbc, 0x86, 0x05, 0x87, 0x2d, 0x63, 0x29, 0x0d, 0x30, 0xf0, 0x5d, 0x7b, 0x79, + 0x5f, 0x6d, 0x76, 0x2a, 0x3c, 0xe6, 0xbc, 0x4b, 0x69, 0x91, 0x57, 0xa9, 0x7f, 0x6e, 0xe3, 0xb5, 0xf9, 0xd5, 0xdc, + 0x46, 0x17, 0xbc, 0x39, 0x27, 0x3a, 0xad, 0x6f, 0x31, 0x5e, 0x76, 0x88, 0x68, 0xe7, 0x3e, 0x97, 0x79, 0xba, 0x85, + 0xd4, 0x62, 0xcc, 0x3a, 0xc7, 0x4c, 0x4f, 0x4b, 0x8b, 0xf2, 0x11, 0x63, 0x50, 0xc9, 0x9d, 0xf2, 0xcd, 0xc8, 0x53, + 0x8d, 0xc2, 0x10, 0xab, 0x6d, 0xe8, 0x19, 0xb4, 0xd2, 0x4f, 0x34, 0xfb, 0xf6, 0x76, 0xb3, 0x06, 0xa8, 0xc4, 0x62, + 0x1f, 0x99, 0x65, 0xe1, 0xe3, 0x72, 0x07, 0xa1, 0x83, 0x34, 0xb7, 0x93, 0xc3, 0x38, 0x3d, 0x46, 0x2b, 0xf4, 0xbb, + 0xf6, 0x14, 0xb3, 0x80, 0x48, 0x52, 0x2f, 0x90, 0xce, 0x01, 0x77, 0x49, 0xfd, 0x59, 0x9c, 0x19, 0x61, 0x3e, 0x7a, + 0x29, 0xa1, 0xdc, 0x25, 0x94, 0x1b, 0xaf, 0xf3, 0x24, 0x00, 0x3e, 0x89, 0xb6, 0xd7, 0x56, 0x9c, 0xe6, 0x9c, 0xd7, + 0xb6, 0x08, 0xc3, 0xae, 0xeb, 0xc5, 0x48, 0x72, 0x33, 0x7b, 0x61, 0xcc, 0x18, 0x04, 0x22, 0xa8, 0xe8, 0xe6, 0x80, + 0xc9, 0x98, 0x3a, 0xc2, 0x41, 0xe7, 0x4f, 0xb2, 0xa9, 0xa6, 0xb4, 0x98, 0xda, 0xd1, 0xff, 0xce, 0x1e, 0xfc, 0xf0, + 0x68, 0x7a, 0xfe, 0xeb, 0xdb, 0xfc, 0x1a, 0x34, 0x41, 0x0f, 0xe1, 0x7e, 0x77, 0x35, 0x53, 0xa1, 0xa0, 0xb0, 0xb2, + 0x7d, 0x69, 0x01, 0x50, 0x63, 0x2a, 0x4a, 0x57, 0xd7, 0xd6, 0xfd, 0x49, 0xc6, 0xa7, 0x35, 0x6d, 0x7c, 0x1d, 0xa8, + 0xf2, 0xb5, 0xa1, 0x6c, 0xdd, 0xe1, 0xf3, 0x50, 0xcd, 0x78, 0x0a, 0xda, 0x5c, 0x18, 0xfc, 0x0a, 0x39, 0x6e, 0x42, + 0x27, 0x43, 0x95, 0x4d, 0xb3, 0x13, 0x6f, 0x59, 0x25, 0x6b, 0x29, 0x39, 0x91, 0x12, 0xf6, 0xaa, 0xf2, 0x47, 0xdd, + 0x93, 0xd4, 0x96, 0x6a, 0x70, 0x83, 0x13, 0x94, 0x36, 0x3a, 0xfa, 0x2a, 0x6e, 0xe4, 0xa7, 0x1b, 0x40, 0x44, 0x4d, + 0x4f, 0x87, 0xf6, 0x76, 0xfe, 0x79, 0x6f, 0x8c, 0xb0, 0x49, 0x05, 0x3f, 0xca, 0xa8, 0xa9, 0x1a, 0x9e, 0xfb, 0x53, + 0xaf, 0x6c, 0x87, 0x67, 0xba, 0x9b, 0x2c, 0x6a, 0x8b, 0x3e, 0xe3, 0x02, 0xac, 0x9a, 0x68, 0xaa, 0x71, 0xa1, 0x08, + 0x63, 0x1a, 0x6f, 0xce, 0xda, 0x89, 0xb5, 0xea, 0xd5, 0xed, 0xac, 0x97, 0x1e, 0x6d, 0xb3, 0x05, 0x6a, 0xbc, 0x68, + 0xda, 0xf2, 0x2a, 0x7c, 0xb7, 0xa4, 0x9b, 0x95, 0x23, 0xc8, 0xdc, 0x04, 0xe8, 0x67, 0x3f, 0x64, 0x26, 0x7a, 0x07, + 0xe1, 0x4e, 0x2a, 0xd9, 0x93, 0x8a, 0xcd, 0x78, 0xbe, 0xbd, 0x72, 0x7e, 0x5a, 0x92, 0x6d, 0xc4, 0xda, 0x8d, 0x2a, + 0xe3, 0xb1, 0x35, 0xc8, 0xdb, 0x35, 0xd3, 0x59, 0xa2, 0xbf, 0x86, 0x7b, 0xfd, 0xf9, 0x76, 0x0d, 0x4d, 0xb7, 0xd5, + 0xdc, 0x79, 0xe9, 0xe4, 0x28, 0x29, 0x79, 0xf1, 0x03, 0x7b, 0x6c, 0xe1, 0x7c, 0xb0, 0xf1, 0x90, 0x60, 0x99, 0x8a, + 0x55, 0x9f, 0x55, 0xac, 0xf2, 0x2c, 0x11, 0x85, 0xd9, 0xd3, 0x2e, 0x80, 0xe3, 0x0f, 0x2b, 0xb9, 0x8a, 0x1f, 0x66, + 0x5a, 0xb5, 0x7c, 0x58, 0x08, 0xd5, 0xf4, 0x24, 0x10, 0x19, 0x98, 0x35, 0xf2, 0x70, 0x61, 0xea, 0x98, 0x4c, 0x4a, + 0x49, 0x20, 0x57, 0x58, 0x4d, 0xab, 0x6a, 0xd5, 0x87, 0x1f, 0x6e, 0xb8, 0x41, 0x5d, 0xf9, 0x67, 0x33, 0xae, 0xff, + 0xaf, 0x99, 0x89, 0xe5, 0xa0, 0xb1, 0xd0, 0xfa, 0x27, 0x2d, 0xcc, 0xfd, 0x08, 0xdd, 0x35, 0xc3, 0x95, 0xe9, 0x4b, + 0x14, 0xf3, 0x2b, 0x46, 0x66, 0x5b, 0xe4, 0xb5, 0x32, 0xd8, 0xc5, 0xde, 0x98, 0x49, 0x5b, 0x27, 0xc6, 0x34, 0x36, + 0x24, 0x56, 0x67, 0x51, 0x23, 0x43, 0x6a, 0x6b, 0xf3, 0x9d, 0xbe, 0xa2, 0xf9, 0x25, 0x2f, 0xf1, 0x97, 0x69, 0xc8, + 0xc2, 0x7c, 0xab, 0xe8, 0x8d, 0xf4, 0x1a, 0x7a, 0x09, 0xfe, 0x62, 0xe1, 0xde, 0x04, 0x78, 0x8e, 0x22, 0x2a, 0x46, + 0x63, 0xf0, 0x4d, 0x16, 0x07, 0x7a, 0xbf, 0xc2, 0xad, 0x20, 0xc3, 0x94, 0x15, 0xff, 0x5f, 0x03, 0xad, 0xf4, 0x2f, + 0x20, 0xf6, 0x0d, 0xbe, 0xc0, 0xca, 0x5b, 0x41, 0xb9, 0x87, 0xe9, 0xfe, 0x02, 0xdf, 0x0a, 0x71, 0x30, 0x68, 0x44, + 0x4d, 0x58, 0xeb, 0x3d, 0xc5, 0x38, 0x31, 0x3d, 0xf8, 0x67, 0x7a, 0x68, 0x25, 0x08, 0x87, 0x31, 0x86, 0x0e, 0x52, + 0x80, 0x60, 0xa5, 0x7c, 0xf5, 0xf5, 0xa1, 0x55, 0xa1, 0x64, 0xe4, 0xab, 0x66, 0x83, 0x4f, 0xb1, 0x9d, 0xa7, 0xd8, + 0x3e, 0x2b, 0x5f, 0x5a, 0x6b, 0x4d, 0x67, 0xab, 0x46, 0x7a, 0xbe, 0x0a, 0x2e, 0x30, 0xec, 0x60, 0xe0, 0xbc, 0x0a, + 0xbe, 0x22, 0x41, 0x93, 0x40, 0x58, 0x40, 0x83, 0xe7, 0x36, 0x94, 0x93, 0x0f, 0x09, 0x94, 0xba, 0x04, 0xbb, 0xcd, + 0x8f, 0x48, 0x6e, 0x03, 0x21, 0xb5, 0x18, 0x67, 0x0b, 0x7b, 0x70, 0x26, 0xcd, 0xfa, 0xb9, 0xb1, 0x1e, 0x5a, 0x89, + 0x92, 0x36, 0x5d, 0x9e, 0x0d, 0xae, 0x19, 0x29, 0xac, 0x93, 0xff, 0x2f, 0x39, 0x6e, 0xf3, 0xbd, 0x2a, 0x08, 0xae, + 0xc4, 0x49, 0x5f, 0xeb, 0x29, 0x28, 0x77, 0x3a, 0x74, 0xe0, 0x8e, 0x20, 0x4b, 0xd9, 0xf3, 0xcc, 0xd3, 0xe7, 0x76, + 0x81, 0x9d, 0x98, 0xed, 0x9e, 0x95, 0xce, 0x70, 0xc2, 0xf1, 0xfb, 0x05, 0xef, 0x2e, 0xfd, 0x39, 0xa4, 0xdc, 0xdf, + 0x57, 0x96, 0x8c, 0x77, 0xc7, 0xdd, 0xb3, 0x3f, 0xc7, 0x1b, 0xb7, 0xfc, 0x29, 0xf7, 0xc3, 0x6d, 0x24, 0xdd, 0xf0, + 0xaa, 0xf9, 0x17, 0x8f, 0x6c, 0xe5, 0x56, 0x42, 0xd0, 0x3a, 0x9d, 0xe3, 0x9b, 0xaf, 0x41, 0xa7, 0x12, 0xb6, 0xf8, + 0xf1, 0x5d, 0xf2, 0x5b, 0x63, 0x2f, 0x46, 0x61, 0x70, 0x68, 0xa6, 0x76, 0x95, 0x9c, 0xb7, 0xe0, 0xb6, 0x4c, 0xed, + 0x56, 0x81, 0x34, 0x7a, 0xe7, 0xb9, 0xfa, 0x3a, 0xfd, 0x54, 0x35, 0xff, 0x31, 0x73, 0x13, 0xf6, 0xb1, 0x42, 0x91, + 0xf8, 0x67, 0x6a, 0x74, 0x83, 0x91, 0xca, 0x03, 0x75, 0x81, 0x55, 0x4b, 0x82, 0xca, 0xdb, 0x11, 0x3f, 0xe5, 0xd7, + 0xdc, 0xe5, 0x48, 0x6c, 0x84, 0xfd, 0x69, 0x6c, 0x3e, 0x53, 0x9f, 0xed, 0x6c, 0x99, 0x65, 0xb7, 0x8f, 0x99, 0x87, + 0x47, 0xf9, 0x5b, 0xaa, 0x5b, 0xe4, 0x7b, 0xb3, 0x2c, 0x2f, 0xca, 0xec, 0xd4, 0x3e, 0x87, 0x4f, 0xb4, 0xd1, 0x24, + 0x7f, 0xe3, 0x71, 0x2f, 0xb1, 0x21, 0xd9, 0x34, 0x2f, 0x33, 0x87, 0xd8, 0xc3, 0xf3, 0x1b, 0x3f, 0x65, 0x53, 0x99, + 0x28, 0x38, 0x6d, 0x87, 0xa6, 0x03, 0xf7, 0x0d, 0xd4, 0x41, 0x15, 0x20, 0xa7, 0x2b, 0xb0, 0xd1, 0x80, 0x59, 0x6d, + 0xd4, 0x97, 0xa5, 0xb2, 0x8a, 0xb3, 0xae, 0xdb, 0x75, 0xfa, 0xc5, 0x46, 0x12, 0xb8, 0xb1, 0x47, 0x91, 0x3c, 0x9d, + 0x95, 0xae, 0xf1, 0x57, 0x79, 0xc9, 0x1c, 0xa5, 0x0f, 0xf8, 0xfc, 0x5b, 0xf0, 0x48, 0xfe, 0x52, 0x74, 0x8d, 0xab, + 0xdc, 0x66, 0x34, 0x6a, 0xcc, 0xc9, 0x78, 0x43, 0xd8, 0x58, 0x14, 0x55, 0x31, 0x35, 0xa7, 0xfc, 0x9c, 0x19, 0x8d, + 0xe4, 0x05, 0x09, 0xf2, 0xb9, 0xb7, 0xfb, 0x99, 0x5c, 0xf0, 0x2b, 0xd7, 0xa1, 0x57, 0x56, 0xa3, 0xe2, 0x4b, 0xe7, + 0xb8, 0xb7, 0xee, 0x50, 0x80, 0x0c, 0xd8, 0x43, 0x86, 0x9c, 0xf2, 0x56, 0xd3, 0xbe, 0x5e, 0x7e, 0xff, 0x82, 0x91, + 0x14, 0xab, 0xb2, 0xef, 0xc6, 0x26, 0x4c, 0x22, 0x3b, 0xc2, 0x5e, 0x35, 0xb2, 0x9b, 0x63, 0x11, 0x21, 0x21, 0x19, + 0xf7, 0x4c, 0xc8, 0xe8, 0xad, 0x5e, 0x26, 0x80, 0x73, 0xe2, 0x49, 0xe1, 0x4c, 0x4e, 0x9c, 0xc8, 0xb2, 0xb4, 0x15, + 0x5b, 0x62, 0xe1, 0x08, 0x5f, 0x6b, 0xca, 0x6c, 0xdb, 0x18, 0x2b, 0x68, 0x70, 0xcc, 0x01, 0xa2, 0x33, 0x9f, 0xf1, + 0x86, 0x09, 0xe7, 0xfc, 0xa9, 0xf2, 0xbe, 0x59, 0xa6, 0x41, 0x5f, 0x15, 0x2c, 0x6c, 0xb7, 0x9e, 0x20, 0xca, 0x34, + 0x03, 0x03, 0xf2, 0x6d, 0x85, 0x6a, 0xfe, 0x95, 0x97, 0x28, 0xf8, 0xee, 0x32, 0xf2, 0xf3, 0xe7, 0x70, 0x1b, 0x21, + 0x1a, 0x04, 0x8d, 0xed, 0x85, 0x51, 0xb2, 0xb3, 0xac, 0x86, 0x5c, 0x84, 0x93, 0xe0, 0x83, 0xdd, 0x53, 0xb8, 0x3e, + 0x87, 0xa4, 0x97, 0xe0, 0x29, 0x30, 0x4f, 0x68, 0xa4, 0xb4, 0xdf, 0xf7, 0x2e, 0x08, 0x84, 0xe6, 0x2d, 0x8f, 0x70, + 0x40, 0x32, 0x62, 0x36, 0x16, 0x1e, 0x37, 0x0b, 0x97, 0x56, 0xc1, 0xa9, 0xcb, 0x6a, 0xd4, 0x15, 0xc9, 0x25, 0x85, + 0x34, 0x63, 0xf0, 0x60, 0x74, 0x24, 0x24, 0x96, 0x85, 0x60, 0xcc, 0x86, 0xbf, 0xf5, 0x02, 0xeb, 0xa7, 0x39, 0x00, + 0xf6, 0x04, 0xf1, 0xd8, 0x84, 0xe9, 0x0d, 0x44, 0x78, 0xb6, 0x2d, 0x0f, 0x98, 0xf7, 0x05, 0x1a, 0xcf, 0xf9, 0x98, + 0x52, 0xe6, 0x7c, 0x01, 0x2e, 0x33, 0xf1, 0x62, 0x20, 0x87, 0x80, 0x7b, 0x88, 0x87, 0xfc, 0xe0, 0xb1, 0x97, 0x60, + 0x67, 0x64, 0xa5, 0xbb, 0x5d, 0xbb, 0x71, 0xcc, 0x2d, 0x45, 0x0e, 0xbc, 0xd8, 0x3f, 0x38, 0xac, 0x6b, 0xb1, 0x4a, + 0xbf, 0x69, 0xa0, 0xd2, 0xbf, 0xfa, 0xf7, 0xcd, 0xe7, 0xc8, 0xb7, 0xcf, 0xb5, 0xd4, 0xa2, 0xf8, 0x81, 0x77, 0x56, + 0x93, 0x82, 0x76, 0xff, 0xab, 0x26, 0x23, 0x5f, 0x52, 0x5a, 0x2d, 0x8b, 0x4f, 0xb5, 0x8b, 0x9e, 0xa2, 0x5a, 0x36, + 0x79, 0x6e, 0x0f, 0x49, 0x8e, 0x5e, 0x6b, 0x19, 0x56, 0xb5, 0x3d, 0xea, 0x83, 0xbd, 0xd7, 0x7b, 0x41, 0x1e, 0x52, + 0x0f, 0x89, 0xaa, 0x37, 0x5e, 0x40, 0xc5, 0x7f, 0xf5, 0x95, 0xea, 0x99, 0x5f, 0xd0, 0x90, 0x37, 0xca, 0x31, 0xbe, + 0x6c, 0x9c, 0xb6, 0xae, 0x1e, 0xc5, 0x14, 0xac, 0x14, 0x65, 0x65, 0x88, 0x1b, 0x59, 0xa1, 0x6b, 0x44, 0x5a, 0x03, + 0x7f, 0x63, 0xa3, 0x14, 0x5b, 0x4d, 0xb5, 0x91, 0xf4, 0xdf, 0x99, 0xfe, 0x0f, 0x89, 0xec, 0xff, 0x14, 0xc7, 0xfe, + 0x8f, 0x73, 0x84, 0x16, 0xf6, 0x8d, 0x65, 0x44, 0xc0, 0x15, 0x4d, 0x8a, 0xe3, 0x2b, 0x83, 0xb3, 0x44, 0x50, 0xa3, + 0x89, 0xc8, 0x6e, 0x3c, 0x51, 0x99, 0x11, 0x79, 0x6e, 0x15, 0x3c, 0x4b, 0x7b, 0x74, 0x4f, 0xee, 0xef, 0x9c, 0x40, + 0x94, 0x63, 0x52, 0x6d, 0x6f, 0xc6, 0x9c, 0xc3, 0x10, 0x17, 0x93, 0x8b, 0x0a, 0x60, 0x04, 0x37, 0x84, 0x6c, 0x2c, + 0x81, 0x8e, 0x92, 0xec, 0x47, 0x23, 0xe6, 0x00, 0x34, 0xc0, 0x7e, 0xd9, 0x20, 0xb0, 0x1c, 0xcc, 0x30, 0x43, 0x30, + 0x3a, 0xaf, 0x0e, 0xf0, 0x39, 0x66, 0x7b, 0xc7, 0x26, 0xf8, 0xb0, 0x32, 0x07, 0x3b, 0xd0, 0x20, 0x1c, 0x30, 0x8f, + 0x66, 0x79, 0x26, 0x28, 0x9a, 0xe0, 0x23, 0xea, 0x2c, 0xfb, 0x5c, 0xfc, 0x92, 0xa5, 0xad, 0xd7, 0x25, 0x87, 0x2e, + 0x16, 0x9f, 0x66, 0xd6, 0x50, 0xfa, 0x13, 0xf8, 0x5f, 0x83, 0x3b, 0xb0, 0xc7, 0x1d, 0x24, 0xc2, 0x56, 0x14, 0x4e, + 0xa5, 0xea, 0x9f, 0x5d, 0x06, 0x84, 0x92, 0x9e, 0x66, 0x48, 0xb9, 0x40, 0xeb, 0x1a, 0xe2, 0x1a, 0x6c, 0x0c, 0x86, + 0xed, 0x8c, 0x67, 0x9a, 0xdb, 0xd6, 0x33, 0xe3, 0xa4, 0x5e, 0xa3, 0x4d, 0x46, 0x87, 0x64, 0x5e, 0x44, 0x99, 0xbb, + 0xc8, 0x2f, 0x47, 0x4a, 0xad, 0xb9, 0x51, 0xac, 0x31, 0xe5, 0xa5, 0xd3, 0xec, 0xc3, 0x39, 0x82, 0xd3, 0x45, 0x50, + 0xf5, 0xc3, 0x1e, 0x9c, 0xb5, 0x31, 0xf8, 0x91, 0x62, 0x51, 0x20, 0xbd, 0x5d, 0x11, 0x52, 0xf3, 0x93, 0x1d, 0xab, + 0x59, 0x4c, 0x4b, 0x6f, 0x17, 0x1e, 0xce, 0xb7, 0xc5, 0x14, 0x64, 0x1c, 0x08, 0xf9, 0x23, 0x18, 0xd8, 0x14, 0x77, + 0x66, 0xa2, 0x2d, 0x82, 0xe0, 0x04, 0xa1, 0x8c, 0x48, 0x87, 0x6f, 0x45, 0x29, 0x2a, 0x02, 0x91, 0xfb, 0xd1, 0x7b, + 0x4c, 0xcb, 0x6a, 0x28, 0xad, 0x81, 0x3d, 0x2a, 0x2a, 0x06, 0xca, 0xeb, 0x4c, 0x68, 0x38, 0x45, 0x8b, 0x90, 0xa9, + 0x78, 0xb3, 0x00, 0x2b, 0x37, 0xf8, 0xa4, 0xc5, 0x4a, 0xcf, 0x58, 0xf6, 0x07, 0xf9, 0x4a, 0x59, 0xd1, 0x30, 0x81, + 0xee, 0x31, 0x55, 0xdb, 0x7f, 0xe3, 0xa2, 0x8d, 0xb9, 0x01, 0x7e, 0x06, 0x8c, 0xe2, 0x7a, 0x85, 0x09, 0xab, 0x15, + 0xdc, 0x01, 0x2c, 0xbd, 0x71, 0x6f, 0xd5, 0x4c, 0xc9, 0xa7, 0x5c, 0x49, 0x29, 0x13, 0xac, 0x77, 0x2a, 0x4b, 0x70, + 0xf2, 0x21, 0x04, 0x43, 0x7c, 0xf7, 0x65, 0xe6, 0xd7, 0x6b, 0x9e, 0xda, 0x84, 0x27, 0xd1, 0x9e, 0xf6, 0xd1, 0x37, + 0x6e, 0xc3, 0xab, 0x16, 0x43, 0x5c, 0x9d, 0x65, 0xe7, 0xe4, 0x4b, 0x64, 0x4d, 0xe5, 0x80, 0x1f, 0xb1, 0x1a, 0xea, + 0x12, 0xf8, 0x8c, 0x98, 0x37, 0x0c, 0xe6, 0x6f, 0x74, 0x8a, 0xc5, 0xbc, 0xa9, 0x22, 0xc5, 0xe1, 0xfe, 0x08, 0x8b, + 0x8c, 0x4b, 0x94, 0x23, 0x7d, 0xc8, 0xbf, 0x83, 0xc1, 0xa8, 0xd2, 0xcd, 0x8a, 0xfa, 0x9a, 0xf1, 0xbc, 0xed, 0x63, + 0x6b, 0x12, 0xb6, 0x00, 0x6b, 0x91, 0xf1, 0x04, 0xe8, 0xbe, 0x56, 0x6f, 0x0b, 0xd9, 0x9a, 0x68, 0x89, 0x86, 0xa6, + 0x50, 0xd4, 0x0d, 0x04, 0x13, 0x93, 0xd2, 0xee, 0xc0, 0x48, 0x82, 0xf1, 0xac, 0xa9, 0xfc, 0x82, 0xfc, 0xb8, 0x5e, + 0xc4, 0xd6, 0x98, 0x0b, 0x1d, 0x33, 0xa2, 0x49, 0x4d, 0x9a, 0x09, 0x88, 0x05, 0xf0, 0x72, 0x16, 0x3d, 0xac, 0xf3, + 0x84, 0x53, 0x73, 0xef, 0xd4, 0x11, 0x33, 0x30, 0x40, 0xa7, 0x10, 0xa9, 0x14, 0x3f, 0xbc, 0x0f, 0x52, 0x0a, 0x04, + 0xa0, 0xec, 0x98, 0x0d, 0x2d, 0x29, 0xa8, 0x4f, 0x6b, 0x97, 0x99, 0x5a, 0xdb, 0x1a, 0xfe, 0x94, 0xd9, 0xac, 0x45, + 0x55, 0xcc, 0x1f, 0x2e, 0xf3, 0x8b, 0x98, 0x71, 0xd1, 0xf0, 0x09, 0x43, 0xd5, 0x61, 0x05, 0x7a, 0x8f, 0x9b, 0xbc, + 0x5e, 0x99, 0xf0, 0x7e, 0x5e, 0xef, 0x9b, 0xfb, 0x22, 0x16, 0x5e, 0x14, 0x38, 0xf7, 0xa5, 0x82, 0x97, 0x86, 0x13, + 0xb8, 0xc4, 0x43, 0x99, 0xf9, 0x54, 0xb6, 0x95, 0x99, 0xa2, 0x04, 0x25, 0xb5, 0x88, 0x5c, 0x92, 0x0b, 0x82, 0x94, + 0x8a, 0x97, 0x81, 0x50, 0xdb, 0xb7, 0x0b, 0x90, 0xbd, 0xaf, 0x2d, 0xe3, 0xb5, 0x64, 0xe7, 0x22, 0x94, 0xcd, 0x66, + 0x5c, 0xdb, 0xcb, 0x69, 0xb7, 0xbf, 0x95, 0x41, 0x35, 0x00, 0x25, 0xb3, 0xe1, 0x32, 0xe2, 0x9b, 0x9b, 0x1d, 0x0a, + 0x08, 0xed, 0xfc, 0x6d, 0x57, 0xca, 0x2c, 0xcc, 0x41, 0xd7, 0xec, 0xa8, 0xf8, 0x17, 0xe5, 0xdd, 0x59, 0xed, 0x66, + 0x7c, 0xc9, 0x3b, 0x18, 0xdf, 0x14, 0xca, 0x01, 0x2e, 0x79, 0x21, 0xeb, 0x07, 0x6e, 0x94, 0xc8, 0x12, 0xc2, 0x32, + 0xbb, 0xa8, 0x15, 0x95, 0xc9, 0x98, 0x36, 0xbd, 0xad, 0xc8, 0x66, 0x23, 0x63, 0x5d, 0x96, 0x68, 0x79, 0x6e, 0xc5, + 0xc9, 0xab, 0x87, 0x3f, 0x52, 0xe5, 0xf4, 0x7d, 0x89, 0xfa, 0xd4, 0x07, 0x77, 0x6f, 0x2b, 0xb3, 0x84, 0x4f, 0x4d, + 0x13, 0x45, 0x70, 0x07, 0xcc, 0x55, 0xb6, 0x22, 0x6a, 0x61, 0x48, 0xfd, 0x17, 0x5e, 0xfa, 0xc6, 0x13, 0xaa, 0xb6, + 0x73, 0xd5, 0xab, 0x39, 0x24, 0x66, 0x8c, 0xe7, 0x68, 0xf5, 0x01, 0xb2, 0x81, 0xae, 0xcd, 0xbe, 0x02, 0x02, 0xaf, + 0x99, 0xfc, 0xf2, 0xdb, 0x61, 0xcc, 0xd9, 0x6d, 0x5e, 0x68, 0x64, 0x2b, 0x67, 0xd9, 0xc1, 0x8d, 0xb4, 0x55, 0x7b, + 0x3c, 0xd3, 0x4d, 0x5c, 0x69, 0x99, 0x8c, 0x31, 0xbf, 0xad, 0xea, 0xab, 0x05, 0xdf, 0x99, 0xdb, 0xce, 0x4a, 0xa6, + 0x91, 0xab, 0xd5, 0x57, 0x78, 0x5e, 0x34, 0x41, 0x27, 0x2e, 0x31, 0x53, 0xab, 0xea, 0xb7, 0xaa, 0x1c, 0x15, 0x15, + 0xcb, 0xb9, 0xd5, 0xa6, 0xca, 0x6b, 0xb7, 0xa8, 0xdf, 0x9f, 0x8d, 0x09, 0x41, 0x65, 0x8a, 0xcc, 0x58, 0xa2, 0x8b, + 0x78, 0xa1, 0x9f, 0xd3, 0xba, 0xa8, 0xe8, 0xf1, 0xca, 0xaa, 0x86, 0x18, 0x02, 0xb7, 0xda, 0xc9, 0x20, 0x65, 0x16, + 0x89, 0x79, 0x16, 0x31, 0xdb, 0xeb, 0xd1, 0xb6, 0x39, 0x1b, 0x06, 0x6e, 0xd2, 0x39, 0x81, 0x73, 0x12, 0xfe, 0xa6, + 0x32, 0xdb, 0xb0, 0xa2, 0x6e, 0x79, 0x8d, 0xae, 0xa2, 0x6e, 0xcd, 0x79, 0x3d, 0x55, 0xc5, 0x0f, 0xd4, 0x71, 0xb5, + 0x5e, 0xdd, 0x88, 0x0e, 0x41, 0x81, 0x0b, 0xeb, 0xe7, 0x00, 0xfe, 0x6f, 0xab, 0x18, 0x1e, 0xec, 0xaa, 0x0f, 0xd5, + 0xaa, 0x69, 0x63, 0xdf, 0x38, 0x20, 0xb0, 0x58, 0x15, 0x5c, 0xa0, 0x33, 0xac, 0x50, 0x2f, 0x33, 0x6d, 0x30, 0x4c, + 0x8c, 0x53, 0x4b, 0xcf, 0xa5, 0x13, 0x11, 0x7d, 0x1a, 0x5e, 0xcc, 0x34, 0x77, 0x68, 0xb3, 0x55, 0x6e, 0x11, 0x6a, + 0x47, 0xb0, 0x08, 0x26, 0xd3, 0x65, 0x1c, 0x8c, 0xfc, 0x36, 0xb4, 0xd1, 0x00, 0x13, 0x97, 0x36, 0x65, 0x21, 0xc4, + 0xca, 0x02, 0xaa, 0xf7, 0x5d, 0xb0, 0x40, 0x30, 0xb3, 0x27, 0xa4, 0x5f, 0x41, 0x54, 0xf9, 0x69, 0x7c, 0x3e, 0xa9, + 0xa4, 0xb6, 0x9d, 0xaf, 0x73, 0x0d, 0x1c, 0xaa, 0xa6, 0xa2, 0x2a, 0x57, 0xb6, 0x21, 0x72, 0x18, 0xe4, 0x3a, 0x52, + 0x42, 0x2d, 0x91, 0x2f, 0x33, 0x4a, 0x27, 0x13, 0x46, 0xcb, 0xb5, 0x29, 0x56, 0x81, 0xb4, 0xd6, 0x85, 0x77, 0xf9, + 0x1f, 0x86, 0xb2, 0x0d, 0x7a, 0x21, 0x4a, 0xe4, 0xa2, 0x67, 0xf1, 0xe7, 0x6b, 0x9d, 0x03, 0xa4, 0xfa, 0x5f, 0xad, + 0x5c, 0x2a, 0x63, 0x03, 0xa7, 0xd8, 0x95, 0x91, 0xf8, 0x20, 0xad, 0x25, 0xfa, 0x3e, 0xd7, 0x31, 0xea, 0xba, 0x07, + 0x8d, 0xeb, 0x55, 0xb1, 0x18, 0xfa, 0xc5, 0x7b, 0x12, 0xdd, 0xc2, 0x97, 0x05, 0x25, 0x1d, 0xf4, 0xd3, 0x5d, 0xdd, + 0x5f, 0xa7, 0x84, 0x44, 0x65, 0x31, 0x31, 0x84, 0x55, 0x7e, 0x66, 0x38, 0x6c, 0x15, 0xd1, 0xac, 0xb6, 0xeb, 0xec, + 0xfb, 0x03, 0x05, 0x13, 0x88, 0xa0, 0xb0, 0xf8, 0xff, 0x73, 0x1f, 0x14, 0x68, 0xe0, 0xa4, 0xce, 0x8d, 0x4a, 0x4e, + 0xfb, 0xb9, 0x76, 0x7d, 0xa8, 0xbc, 0x04, 0x40, 0x56, 0x8f, 0x37, 0xb2, 0xbe, 0xe5, 0x77, 0x2b, 0x8b, 0x17, 0x30, + 0x96, 0x3f, 0x85, 0x4d, 0x56, 0x23, 0xda, 0x8c, 0xae, 0xd5, 0x6c, 0x94, 0x4f, 0x99, 0x18, 0x8e, 0x36, 0xd0, 0xf5, + 0xbb, 0x6d, 0x6f, 0x50, 0x5d, 0x58, 0x4b, 0xec, 0x3e, 0x60, 0x5d, 0xa9, 0x80, 0xfd, 0xac, 0xa9, 0xa5, 0x3b, 0x15, + 0xfc, 0xfc, 0x56, 0x4f, 0xa5, 0x59, 0xd8, 0x3a, 0x02, 0x7a, 0xf6, 0xd5, 0x15, 0x07, 0xc0, 0x07, 0x74, 0x0d, 0x0b, + 0x3d, 0x76, 0x2c, 0xf5, 0x99, 0x45, 0x94, 0x7d, 0xe6, 0x1e, 0x5f, 0xdf, 0x0c, 0x85, 0x87, 0x9d, 0xdb, 0x6f, 0xbd, + 0x2a, 0xc6, 0xf1, 0xc2, 0xba, 0xba, 0xc8, 0x05, 0xc5, 0x13, 0x92, 0x9c, 0x5f, 0xce, 0x61, 0xa8, 0x5a, 0x49, 0xc4, + 0x5c, 0x85, 0x04, 0x41, 0xed, 0xbb, 0x22, 0xe0, 0x31, 0x39, 0x5e, 0x81, 0xbb, 0x07, 0xa6, 0xa8, 0x9b, 0x1d, 0x42, + 0xe8, 0x96, 0xb4, 0xba, 0x5b, 0x91, 0x00, 0xd0, 0x2e, 0xd8, 0xfe, 0xc6, 0x79, 0x89, 0x2d, 0x68, 0x19, 0xad, 0x17, + 0x21, 0x0c, 0x44, 0x22, 0x85, 0x31, 0x72, 0x7a, 0x38, 0x5b, 0xd7, 0xa0, 0x18, 0xfa, 0x53, 0x17, 0x38, 0xf5, 0xe3, + 0xd9, 0xb6, 0x4b, 0x85, 0x64, 0x22, 0xe8, 0xd0, 0x14, 0x58, 0x96, 0x9d, 0x38, 0xed, 0x91, 0xe4, 0xfd, 0x7d, 0x9e, + 0x92, 0x15, 0x15, 0x3f, 0x94, 0xc3, 0xcf, 0x27, 0x24, 0x38, 0xd4, 0x13, 0x30, 0x83, 0x0e, 0x78, 0xa6, 0xf7, 0xa9, + 0x13, 0x23, 0x95, 0xf5, 0x0e, 0x38, 0x8a, 0x88, 0x32, 0xd3, 0x25, 0xbb, 0xc7, 0xed, 0xf1, 0x14, 0x70, 0x23, 0x63, + 0xda, 0x65, 0x8e, 0x61, 0x26, 0x30, 0x8e, 0xf9, 0x6a, 0x7c, 0x3e, 0xa2, 0x1f, 0xc7, 0x7d, 0x44, 0xc9, 0x45, 0xa5, + 0x86, 0xc2, 0x36, 0x66, 0x8b, 0x5a, 0xf4, 0xd4, 0xbe, 0x91, 0x48, 0x47, 0xaf, 0x60, 0x2c, 0x17, 0x98, 0x06, 0x2b, + 0x9d, 0xf3, 0x8a, 0x82, 0x15, 0x4d, 0x80, 0xb8, 0x0a, 0xe3, 0x94, 0x51, 0x6b, 0xcc, 0x52, 0x18, 0x5c, 0x51, 0x93, + 0x11, 0xc1, 0xaf, 0x26, 0xf4, 0xec, 0x63, 0x31, 0xdc, 0x93, 0x97, 0xc3, 0xa1, 0x1e, 0xad, 0xa7, 0x75, 0xf7, 0x06, + 0x16, 0x63, 0xc1, 0xb2, 0xc0, 0x9c, 0x9d, 0x0e, 0x3a, 0xaf, 0xd8, 0xd6, 0xd4, 0x3a, 0x5d, 0xad, 0x1f, 0x5a, 0xd9, + 0x28, 0x96, 0xd3, 0x24, 0x92, 0x38, 0x6f, 0xa6, 0x51, 0x8c, 0x3f, 0x34, 0x5c, 0xea, 0x86, 0xfa, 0xc4, 0x6f, 0xcd, + 0x5f, 0x4b, 0xa5, 0xbf, 0xce, 0x3f, 0x8a, 0x85, 0x1d, 0x9b, 0xd8, 0x6f, 0xb4, 0x60, 0x65, 0xd1, 0xd8, 0x40, 0xa8, + 0xea, 0x0b, 0x9e, 0x25, 0x2b, 0x95, 0x27, 0xdf, 0x8d, 0xd8, 0xd2, 0x02, 0x3f, 0x8f, 0xf2, 0x6a, 0xea, 0xcd, 0x88, + 0x41, 0xb5, 0x7c, 0x8a, 0x6a, 0x77, 0x72, 0x20, 0x5c, 0x26, 0x37, 0x56, 0x95, 0x07, 0x88, 0x9e, 0x5f, 0x96, 0x1e, + 0x09, 0x73, 0xa9, 0x98, 0x92, 0x06, 0xcf, 0x89, 0xa0, 0xb7, 0x30, 0x85, 0x18, 0x1e, 0x49, 0xdf, 0xa0, 0xf2, 0xee, + 0x8f, 0xeb, 0x7d, 0xaf, 0x0b, 0xdc, 0x19, 0x3b, 0xdf, 0x74, 0x2f, 0x9d, 0x19, 0x34, 0x7a, 0xfd, 0x73, 0xa8, 0x5a, + 0x84, 0xc1, 0x4e, 0xd3, 0x85, 0xa0, 0x09, 0xea, 0x5f, 0x8c, 0x06, 0xd6, 0x32, 0x5d, 0xeb, 0xed, 0x20, 0x53, 0x21, + 0x31, 0xfe, 0x5f, 0x64, 0xbc, 0x0c, 0x98, 0x9c, 0x8c, 0xe2, 0x16, 0x3c, 0x00, 0x37, 0xd3, 0x90, 0x0b, 0x94, 0xd9, + 0xc3, 0x13, 0xa8, 0xc9, 0x58, 0x84, 0x67, 0x39, 0xe6, 0x3a, 0x75, 0x60, 0x3d, 0xb2, 0x79, 0x58, 0xa3, 0x70, 0xb5, + 0x9c, 0x4d, 0x4e, 0xc9, 0x8e, 0x59, 0x5d, 0xed, 0x63, 0x77, 0xc6, 0x25, 0x9e, 0x39, 0x1f, 0xf2, 0x6d, 0xec, 0x71, + 0xc0, 0x1c, 0x87, 0x07, 0x0e, 0x33, 0xe7, 0x21, 0x82, 0x5c, 0x37, 0xc0, 0x16, 0x60, 0xb2, 0x93, 0xb5, 0x6b, 0x94, + 0xb0, 0x78, 0x73, 0x03, 0x20, 0x8f, 0x64, 0x12, 0x42, 0x2e, 0x1b, 0x7e, 0x96, 0x5a, 0xaa, 0x8f, 0x80, 0x8f, 0xd5, + 0x87, 0x9a, 0x06, 0x42, 0xdc, 0x36, 0x42, 0x1e, 0x30, 0x26, 0xae, 0xcc, 0x2f, 0xaa, 0x09, 0x2e, 0xf8, 0x2f, 0x7b, + 0x1d, 0x7f, 0xdd, 0xac, 0xfb, 0x9e, 0x21, 0x22, 0x1d, 0xac, 0x45, 0x64, 0xbd, 0x22, 0x85, 0xff, 0x86, 0xdf, 0x03, + 0x45, 0x09, 0xc5, 0x52, 0xb1, 0xfc, 0x88, 0xea, 0x1e, 0xe3, 0x1e, 0xf2, 0xde, 0x4e, 0x7e, 0x1f, 0x09, 0x83, 0x1e, + 0x50, 0x63, 0x94, 0xa4, 0x38, 0x52, 0xab, 0x9e, 0x7b, 0x14, 0x2c, 0x85, 0xa5, 0x86, 0xe7, 0x88, 0xd2, 0xd5, 0xf7, + 0x0a, 0xb5, 0xf0, 0x1f, 0x2d, 0x6d, 0x9e, 0x86, 0x7d, 0x44, 0xf2, 0x4d, 0x46, 0xd7, 0xc8, 0x42, 0x25, 0x51, 0x78, + 0x23, 0x04, 0x9e, 0x73, 0xc6, 0x53, 0x7d, 0x84, 0x98, 0x07, 0xa2, 0xc9, 0xc8, 0xf5, 0x80, 0xde, 0xd1, 0xe6, 0xe8, + 0x45, 0x72, 0x4c, 0xdf, 0xb4, 0x0f, 0x83, 0xb0, 0x1d, 0x5b, 0x5c, 0x6a, 0x4c, 0x44, 0x6b, 0x5a, 0x75, 0xd9, 0x23, + 0x52, 0xef, 0x3c, 0x15, 0xa3, 0x04, 0x25, 0x72, 0x13, 0x15, 0xdd, 0x39, 0x4e, 0xed, 0xa2, 0xe8, 0xf6, 0x19, 0x4b, + 0xb8, 0x18, 0x55, 0x7c, 0x5f, 0x06, 0x9f, 0x44, 0x52, 0x34, 0x60, 0xd8, 0x80, 0xaf, 0xf7, 0xff, 0x60, 0xe8, 0x66, + 0x20, 0x97, 0xda, 0x30, 0x65, 0xf3, 0xe9, 0x9c, 0x66, 0x5b, 0xc3, 0x7d, 0x83, 0xd6, 0x97, 0x50, 0xcf, 0xb9, 0xcf, + 0x88, 0xdf, 0x4a, 0xcd, 0x2d, 0x26, 0xab, 0x36, 0x1b, 0x59, 0x4c, 0xd6, 0x61, 0xd5, 0x3d, 0x46, 0xa6, 0x10, 0xff, + 0x42, 0x93, 0x5c, 0x10, 0x1e, 0x55, 0xc9, 0x82, 0x7f, 0xd0, 0xcc, 0x60, 0xc3, 0x79, 0x9d, 0xfe, 0x8d, 0x32, 0x80, + 0xf7, 0x3b, 0xcb, 0x5a, 0x41, 0x35, 0x25, 0xb5, 0xe3, 0xba, 0x4b, 0xc7, 0x2f, 0x5d, 0xa0, 0x07, 0x99, 0x89, 0x67, + 0x47, 0x25, 0x21, 0x66, 0x81, 0x75, 0x2f, 0x91, 0xfa, 0xe6, 0x27, 0xe9, 0x91, 0x36, 0x78, 0xce, 0x42, 0xb4, 0xa0, + 0x17, 0x15, 0xfb, 0x7b, 0xa5, 0x34, 0xbd, 0x57, 0x76, 0x06, 0xaf, 0x8d, 0x99, 0xca, 0x41, 0xb0, 0xee, 0x12, 0x7a, + 0xb9, 0x3c, 0xc9, 0x8f, 0x6d, 0xe6, 0x92, 0xe6, 0x23, 0xe9, 0xef, 0xaa, 0x14, 0xeb, 0xc7, 0x80, 0xd6, 0xbf, 0xa6, + 0xcc, 0x92, 0x14, 0x68, 0x30, 0x58, 0x8d, 0x15, 0xdb, 0x04, 0x1c, 0x52, 0x68, 0x22, 0xa2, 0x89, 0x76, 0xdc, 0xee, + 0x68, 0x7c, 0x86, 0xd4, 0x47, 0xb8, 0x40, 0x32, 0xe0, 0x91, 0x43, 0x4c, 0x56, 0xc5, 0x2e, 0xc0, 0x17, 0xb8, 0x7d, + 0x3c, 0x83, 0x7e, 0xd8, 0x6e, 0xdd, 0x20, 0xe5, 0xa6, 0x1c, 0x17, 0x01, 0x6b, 0x08, 0x80, 0xa7, 0x5c, 0x13, 0xad, + 0x06, 0x52, 0x7d, 0x69, 0x04, 0xec, 0xbb, 0x83, 0xfa, 0x38, 0x9a, 0xa6, 0x8c, 0x65, 0xd3, 0xc4, 0x4b, 0xc9, 0x23, + 0xc4, 0x88, 0x7d, 0x85, 0x53, 0x8e, 0xc0, 0xbc, 0xc3, 0xef, 0xac, 0xd7, 0x42, 0x7a, 0x9b, 0xe8, 0x73, 0x93, 0x81, + 0x87, 0xe1, 0xc7, 0xd8, 0x7e, 0xd1, 0xd3, 0xce, 0xd6, 0x9c, 0xbf, 0x0a, 0x48, 0x46, 0x47, 0xe1, 0x5f, 0x85, 0x67, + 0xa5, 0x6d, 0x12, 0x42, 0xfc, 0x03, 0xd1, 0x75, 0x86, 0x33, 0x48, 0xb0, 0x48, 0x5f, 0x2e, 0x6a, 0x17, 0x39, 0x05, + 0x95, 0xf6, 0x99, 0xd5, 0xca, 0xb2, 0x7c, 0x7b, 0xfb, 0x8f, 0x73, 0x6b, 0x53, 0x8d, 0x0b, 0x1e, 0x72, 0x8d, 0xcb, + 0x56, 0x36, 0xfc, 0xa2, 0x8d, 0xf7, 0x96, 0x6c, 0x36, 0x72, 0xd5, 0x57, 0x2e, 0xe1, 0x9f, 0xf8, 0x51, 0x46, 0xb2, + 0xf1, 0x02, 0xac, 0x45, 0x6a, 0x79, 0xe4, 0xea, 0xa9, 0xed, 0x7b, 0xbd, 0x50, 0xac, 0x0c, 0xee, 0xfc, 0xe2, 0x38, + 0x41, 0x92, 0xca, 0x43, 0xfe, 0x9c, 0xaf, 0xe3, 0x1c, 0x3b, 0xab, 0xe9, 0x68, 0x45, 0xef, 0x48, 0x5d, 0x0e, 0x16, + 0x5b, 0x8e, 0x92, 0xf3, 0xc1, 0xb9, 0x6b, 0x86, 0x1e, 0x1c, 0x45, 0x3d, 0x9f, 0x29, 0x89, 0x05, 0x5c, 0x9a, 0xbb, + 0xa7, 0x08, 0x7a, 0x84, 0x48, 0x8c, 0xd0, 0xbb, 0xa0, 0x21, 0x18, 0xb6, 0x39, 0xdf, 0x64, 0x82, 0x36, 0x6b, 0xd1, + 0x2e, 0xe2, 0x17, 0xc3, 0xa2, 0xf0, 0xda, 0xbb, 0x7a, 0xe4, 0x8a, 0xe5, 0x12, 0x1a, 0x03, 0x59, 0x83, 0x62, 0xff, + 0x9a, 0x04, 0x3f, 0xe8, 0x9f, 0xad, 0x16, 0x1a, 0x2b, 0x53, 0xe6, 0xc7, 0x8c, 0x55, 0xea, 0x9c, 0xb5, 0xf4, 0x6e, + 0x6a, 0x17, 0x94, 0x9c, 0x6c, 0xe5, 0xfc, 0x5a, 0xcc, 0xbf, 0x1f, 0xaa, 0x9f, 0x66, 0xca, 0x3b, 0x84, 0x27, 0xcc, + 0xd7, 0x89, 0xa2, 0x80, 0xac, 0x9b, 0x25, 0xce, 0x52, 0x52, 0xc7, 0x2a, 0x89, 0x12, 0x63, 0x3b, 0x87, 0x47, 0x08, + 0x42, 0xd2, 0xd9, 0xac, 0xce, 0x8c, 0xc9, 0x95, 0x14, 0x6f, 0x87, 0x72, 0x25, 0x9c, 0xc5, 0x22, 0x4d, 0x50, 0x74, + 0xf9, 0x86, 0x5c, 0x2a, 0xf4, 0x54, 0x97, 0x76, 0x74, 0xa8, 0xf4, 0x80, 0x7f, 0x74, 0x73, 0x89, 0x99, 0x54, 0xa0, + 0x11, 0x9f, 0xc7, 0x96, 0x54, 0x22, 0x59, 0x15, 0x39, 0x0c, 0xd4, 0xca, 0xe4, 0x27, 0xdb, 0xe7, 0x32, 0x5a, 0x37, + 0x21, 0x70, 0xdd, 0xe6, 0x4a, 0xe2, 0xee, 0x5f, 0x26, 0xf3, 0x74, 0x00, 0xf6, 0xcb, 0x72, 0x9d, 0x37, 0x3a, 0xe1, + 0xf2, 0xe8, 0xec, 0x53, 0x13, 0xec, 0x78, 0x07, 0x2f, 0x26, 0x12, 0x04, 0x07, 0x89, 0x44, 0xa4, 0x82, 0x33, 0x90, + 0x78, 0x02, 0x03, 0x70, 0x72, 0xfe, 0x88, 0x9f, 0x17, 0x64, 0x79, 0x01, 0x5c, 0xe1, 0xa8, 0x02, 0x44, 0x82, 0x04, + 0x8d, 0x2e, 0xbc, 0x9b, 0x63, 0xf5, 0x9a, 0x2d, 0xb7, 0xab, 0xd2, 0x79, 0x50, 0x73, 0x24, 0x85, 0x92, 0x30, 0xe2, + 0x0c, 0x8b, 0x1f, 0x6c, 0x4a, 0x94, 0xaf, 0x1a, 0x81, 0x30, 0xb2, 0x58, 0xe2, 0x85, 0x46, 0x83, 0x00, 0x8f, 0x8f, + 0x90, 0x32, 0xd9, 0x36, 0xe3, 0x98, 0x7d, 0x4d, 0x89, 0x73, 0x86, 0xcc, 0x10, 0x4a, 0x06, 0xe6, 0x68, 0x09, 0x60, + 0x9d, 0xc5, 0x18, 0x4d, 0xa5, 0x29, 0x3e, 0x3f, 0x47, 0xad, 0xd6, 0x91, 0x57, 0x36, 0x43, 0xbd, 0x0d, 0x56, 0x4c, + 0x89, 0x00, 0xc7, 0x21, 0xa4, 0x97, 0xc0, 0x82, 0x32, 0xe6, 0xb6, 0x24, 0x97, 0x22, 0x3f, 0x24, 0x6b, 0x49, 0xd3, + 0x66, 0x60, 0x70, 0xae, 0x9b, 0x7c, 0x31, 0x1f, 0x8e, 0x92, 0x69, 0x15, 0x6c, 0x1a, 0xeb, 0xfe, 0x3d, 0x6c, 0x9a, + 0x6e, 0x72, 0xe5, 0xb6, 0x0a, 0xc6, 0x6a, 0xe6, 0x78, 0xc4, 0xe6, 0x6c, 0xc0, 0xcb, 0xef, 0x41, 0x1a, 0x2e, 0x1e, + 0x42, 0x64, 0xda, 0x4f, 0xfb, 0xa7, 0xd8, 0xbb, 0xe5, 0xf2, 0x64, 0x06, 0xce, 0xda, 0xd8, 0x1d, 0xa7, 0xa8, 0xae, + 0x25, 0x51, 0x2e, 0x09, 0x9b, 0x0f, 0x80, 0xa1, 0xd6, 0xf7, 0xa2, 0xec, 0xff, 0x2e, 0xe9, 0x89, 0xa2, 0xc2, 0x73, + 0x9d, 0xd7, 0x67, 0xa9, 0x3f, 0x80, 0x76, 0x1f, 0xc7, 0xe4, 0xce, 0x38, 0xcc, 0x11, 0x50, 0x99, 0xbd, 0x5f, 0xbf, + 0xa2, 0x83, 0xb6, 0x95, 0xea, 0x4f, 0x28, 0xce, 0x1f, 0x94, 0xd1, 0x3a, 0x5b, 0xe6, 0xfc, 0x6c, 0xc1, 0x40, 0x67, + 0x92, 0x96, 0x92, 0xca, 0x27, 0xfe, 0x87, 0xea, 0xf0, 0x31, 0xb5, 0x47, 0x8c, 0x4d, 0x24, 0x09, 0x7e, 0x92, 0x27, + 0x7c, 0x4c, 0x35, 0x13, 0xb5, 0x3d, 0x43, 0x8a, 0x7a, 0x63, 0x44, 0xa6, 0x52, 0x4d, 0x96, 0x15, 0x9b, 0x58, 0xe4, + 0x04, 0xbb, 0xba, 0xb0, 0x2e, 0x7d, 0xa2, 0x3e, 0xa5, 0xa6, 0xe6, 0x20, 0x5c, 0x18, 0x48, 0x77, 0xdb, 0x55, 0x8f, + 0x16, 0x4b, 0x5a, 0x28, 0x52, 0x12, 0x39, 0x89, 0xa4, 0x69, 0x1c, 0xa9, 0x0b, 0x60, 0x9e, 0xa3, 0xec, 0x56, 0xb2, + 0x06, 0x6b, 0x6b, 0x3c, 0x51, 0x27, 0xd5, 0x91, 0x9b, 0x3a, 0xcc, 0xac, 0xa7, 0x9a, 0xf9, 0x3f, 0x3b, 0x26, 0x52, + 0xd0, 0x71, 0xe5, 0x91, 0x27, 0x94, 0xe6, 0xcd, 0x54, 0xed, 0x64, 0x48, 0x8f, 0x3c, 0xd7, 0xdb, 0xa4, 0x63, 0x9f, + 0x0b, 0x25, 0x0e, 0xdd, 0x74, 0x39, 0xd5, 0x25, 0xf0, 0xf1, 0x55, 0xfc, 0x91, 0x50, 0x2c, 0x49, 0xa4, 0x61, 0xee, + 0x6c, 0x34, 0xb6, 0x34, 0x56, 0x97, 0x8a, 0x2c, 0x0e, 0x4b, 0x43, 0xd5, 0x55, 0x94, 0xc5, 0x1b, 0x35, 0xd8, 0x44, + 0xd4, 0x45, 0x7d, 0x0d, 0x3a, 0xa5, 0xf3, 0x1c, 0x68, 0xa9, 0xc5, 0xdd, 0x53, 0x41, 0xef, 0x27, 0x5c, 0x53, 0x01, + 0x0e, 0x26, 0x1e, 0xb9, 0x78, 0xc1, 0xe9, 0x32, 0xa7, 0x2b, 0xd8, 0x5f, 0x34, 0x52, 0x8d, 0x33, 0x0b, 0x55, 0x39, + 0x33, 0xaa, 0xda, 0x99, 0x75, 0xd3, 0x0d, 0x86, 0x39, 0x57, 0xbb, 0x1c, 0x59, 0x94, 0x25, 0x59, 0x1c, 0x57, 0xa6, + 0x89, 0xe7, 0xf6, 0xca, 0x65, 0xa4, 0xf3, 0x4a, 0xb6, 0x98, 0x8c, 0x89, 0x4b, 0x3d, 0x32, 0x3d, 0x31, 0xb2, 0x6c, + 0xa0, 0xb6, 0x4b, 0xaf, 0xa9, 0x3a, 0xf6, 0x8b, 0x3b, 0x16, 0x85, 0x97, 0xb9, 0xc6, 0xf4, 0x38, 0x09, 0x19, 0xf2, + 0xa5, 0x35, 0x50, 0x62, 0x1b, 0xfc, 0x58, 0x8e, 0xf6, 0xd3, 0x69, 0x09, 0xac, 0x49, 0x44, 0xa0, 0xea, 0xb5, 0x81, + 0xfc, 0xb8, 0x4d, 0x0f, 0xe9, 0xcb, 0x16, 0x2e, 0xca, 0x1f, 0xca, 0x61, 0x73, 0xe0, 0x10, 0x66, 0x02, 0xa3, 0x60, + 0xa1, 0xbc, 0x92, 0xc0, 0x26, 0xf0, 0x3b, 0x46, 0xcd, 0x76, 0xbb, 0xd2, 0xfb, 0x00, 0x32, 0x19, 0x37, 0x21, 0x3c, + 0x80, 0xc2, 0xeb, 0x29, 0x28, 0x57, 0x88, 0x03, 0xcd, 0x14, 0xa0, 0xc3, 0x0f, 0xe9, 0xc3, 0x13, 0x90, 0x1f, 0xd3, + 0xe1, 0x47, 0xb7, 0x72, 0x1b, 0x6d, 0x73, 0x2c, 0x4f, 0x95, 0x87, 0x6a, 0x1c, 0x21, 0x4a, 0x72, 0x61, 0xb1, 0xa8, + 0xdb, 0x2b, 0x57, 0xb4, 0xbd, 0xf1, 0x5e, 0xdf, 0xb0, 0x4d, 0x3a, 0xfe, 0x18, 0xe6, 0xb8, 0xc2, 0xa8, 0x46, 0x15, + 0x6c, 0xe9, 0x1d, 0xb0, 0xd5, 0x5d, 0x25, 0xb0, 0xc7, 0xa6, 0xb1, 0xb9, 0x00, 0x1d, 0x1a, 0xa2, 0x0c, 0xa4, 0x54, + 0x35, 0x0b, 0x64, 0x72, 0xf5, 0x29, 0xec, 0xb6, 0xa6, 0x31, 0x9b, 0x90, 0xf7, 0xbf, 0xa1, 0x79, 0x15, 0x96, 0x7c, + 0xc2, 0xfe, 0x10, 0xc9, 0x67, 0xf8, 0xd2, 0x47, 0x8d, 0xf8, 0x1e, 0xe0, 0x6a, 0x5f, 0x0a, 0x45, 0xa6, 0x38, 0xb6, + 0xc7, 0x6b, 0xd4, 0x26, 0xf3, 0xf0, 0x50, 0x47, 0x17, 0x36, 0xe4, 0x47, 0x38, 0x61, 0xfb, 0x31, 0xce, 0x93, 0x0b, + 0x8c, 0xe8, 0xbb, 0x18, 0x37, 0x07, 0xe8, 0xca, 0x00, 0xbc, 0x2d, 0xa3, 0x5e, 0x2a, 0x1f, 0xec, 0xf0, 0x16, 0x75, + 0xb3, 0xe3, 0x34, 0xd8, 0x66, 0xc4, 0xa1, 0x1c, 0x0a, 0x70, 0x97, 0xbd, 0xaa, 0x52, 0xe4, 0xf4, 0xd6, 0xf4, 0x8e, + 0xeb, 0x0d, 0xf2, 0x45, 0x13, 0x4d, 0x1d, 0x4c, 0x7a, 0x00, 0x13, 0x6a, 0x39, 0xa0, 0x31, 0x7a, 0xb5, 0x25, 0x5b, + 0x5c, 0x0b, 0x9e, 0xd9, 0x02, 0xd2, 0xbc, 0x22, 0xd5, 0x6e, 0x94, 0x46, 0x53, 0x32, 0x34, 0x69, 0x13, 0x8b, 0xd4, + 0x40, 0x32, 0xab, 0x57, 0x75, 0x22, 0x55, 0x83, 0x2d, 0x70, 0x60, 0xb3, 0x20, 0xc3, 0x37, 0xfb, 0x93, 0x01, 0x63, + 0x4b, 0xaf, 0x7d, 0x4f, 0x76, 0x1f, 0x35, 0xe4, 0x1a, 0x12, 0x19, 0xc7, 0x39, 0xd1, 0x6c, 0xaa, 0x88, 0xf8, 0x64, + 0x1d, 0x15, 0xb0, 0x36, 0x97, 0x6d, 0xe5, 0x83, 0x0a, 0x7a, 0x6c, 0xb0, 0xc9, 0x06, 0xd7, 0x8e, 0x19, 0xd6, 0x17, + 0x9b, 0x8a, 0xd4, 0x65, 0xfa, 0x40, 0xc4, 0x34, 0x83, 0x44, 0xa8, 0x3b, 0x36, 0xbe, 0xae, 0x4a, 0xbb, 0x20, 0xec, + 0xfb, 0xab, 0x74, 0xae, 0x61, 0xe3, 0x15, 0x90, 0xb9, 0xbe, 0xea, 0x00, 0x03, 0xbc, 0x02, 0x71, 0x31, 0xe0, 0xe3, + 0x2d, 0x90, 0x29, 0xf9, 0x77, 0xd4, 0x73, 0xa3, 0x94, 0x47, 0x2d, 0xef, 0x86, 0x19, 0xde, 0x6a, 0x2f, 0xf3, 0x0f, + 0x4b, 0x1f, 0xf2, 0x21, 0x41, 0x85, 0x2c, 0xa4, 0xe6, 0x49, 0xd4, 0xcd, 0x1d, 0x88, 0x6d, 0xdd, 0xe7, 0x22, 0xa3, + 0x58, 0xc4, 0xca, 0x23, 0xc0, 0x5d, 0x04, 0xbc, 0xdb, 0xac, 0x94, 0x88, 0x6f, 0x0e, 0xa5, 0x55, 0xde, 0x12, 0xcd, + 0x55, 0x60, 0xde, 0x45, 0x2b, 0x3b, 0x9c, 0xea, 0x90, 0x81, 0x9d, 0x4a, 0xed, 0x94, 0x44, 0xef, 0xb1, 0xc2, 0x5e, + 0xb3, 0x8d, 0xf5, 0x5b, 0x3b, 0xfa, 0x10, 0x56, 0x0b, 0x56, 0xdb, 0x73, 0x85, 0xe6, 0x66, 0xa2, 0x80, 0x58, 0x60, + 0xcd, 0xde, 0xbe, 0x49, 0x14, 0x42, 0xe1, 0x82, 0xcb, 0x52, 0x2a, 0x91, 0x62, 0xdb, 0x01, 0x83, 0x44, 0x13, 0x26, + 0xaa, 0x8a, 0x73, 0x23, 0xf6, 0x3c, 0x6b, 0xb0, 0xc0, 0xb3, 0x92, 0x0c, 0x8a, 0xd0, 0xba, 0xad, 0x76, 0xa9, 0x40, + 0xef, 0x67, 0x81, 0x95, 0x53, 0xe5, 0x04, 0x0e, 0xa9, 0x46, 0x1c, 0x9f, 0x05, 0x23, 0xb7, 0x4a, 0xf9, 0x16, 0x61, + 0xce, 0xe0, 0xcc, 0x7f, 0x5d, 0x7a, 0x6d, 0x7a, 0x52, 0x0a, 0x0e, 0xd3, 0xf7, 0xe7, 0x30, 0xe9, 0x15, 0x18, 0x9d, + 0xf7, 0x9e, 0xf7, 0x4a, 0x16, 0xf8, 0xeb, 0xb5, 0xbe, 0x14, 0x45, 0xb3, 0x29, 0x4f, 0x3d, 0xb9, 0x94, 0xf9, 0x96, + 0x06, 0xae, 0x53, 0x1c, 0xad, 0xee, 0xd9, 0x9b, 0x15, 0x30, 0x13, 0xcb, 0xf0, 0xef, 0xc1, 0xd6, 0xbe, 0x81, 0xf3, + 0x62, 0x09, 0x44, 0x7e, 0x63, 0x7c, 0x7d, 0xc8, 0xd3, 0xe2, 0x85, 0xcf, 0xcf, 0x08, 0x0b, 0x15, 0xe6, 0x8a, 0x84, + 0xc7, 0xa7, 0x4a, 0xab, 0x2c, 0x41, 0xc3, 0xb4, 0x7c, 0xa6, 0xc7, 0x8b, 0xfa, 0x56, 0x39, 0x7a, 0xeb, 0x2f, 0xb3, + 0xd2, 0x98, 0xcf, 0xcf, 0x93, 0x47, 0x4a, 0xbc, 0x7e, 0xf2, 0x89, 0xaa, 0xf2, 0x67, 0xc3, 0x6d, 0xbd, 0xef, 0xe1, + 0xd7, 0xde, 0x7e, 0x90, 0x65, 0x81, 0xc8, 0xaa, 0x71, 0x6d, 0xe3, 0xa8, 0xf2, 0x34, 0xed, 0x85, 0x58, 0x28, 0xc2, + 0x0f, 0x8a, 0x0e, 0x2c, 0x2f, 0x73, 0xa9, 0xe6, 0x5c, 0x85, 0x8a, 0x46, 0xec, 0x69, 0xfc, 0x7c, 0x08, 0x4b, 0x61, + 0x2a, 0x32, 0x08, 0xe3, 0x0e, 0xed, 0x92, 0x64, 0xec, 0x96, 0x32, 0x6d, 0xeb, 0x77, 0x0b, 0xe5, 0x35, 0x15, 0x13, + 0x30, 0x85, 0x77, 0x20, 0xb9, 0x99, 0x2d, 0xb6, 0xd6, 0x39, 0xa9, 0xa3, 0x02, 0xfb, 0x31, 0xa6, 0xc0, 0x61, 0xa7, + 0x9b, 0xe9, 0x73, 0x81, 0x1b, 0x9a, 0xf2, 0x50, 0x6f, 0x3a, 0xc3, 0x95, 0xd7, 0xf1, 0x43, 0x75, 0xe6, 0x6c, 0x81, + 0x96, 0x6b, 0xe4, 0x2b, 0xbe, 0xaa, 0x96, 0x20, 0xf2, 0x40, 0xf2, 0xb7, 0xaf, 0xbe, 0x7b, 0xab, 0x4b, 0x45, 0xd2, + 0x19, 0x6e, 0xd5, 0xb0, 0x3b, 0x58, 0xe8, 0x6e, 0x75, 0x26, 0x91, 0x04, 0x1a, 0x90, 0x5d, 0x1b, 0xde, 0x0b, 0x1b, + 0xe8, 0x4e, 0x3b, 0x5c, 0x3b, 0xa9, 0x22, 0x68, 0x9d, 0x5d, 0x65, 0x0c, 0x6d, 0xd9, 0x45, 0xc4, 0x2d, 0xbb, 0x0e, + 0x47, 0xd1, 0xcd, 0xb4, 0x10, 0xd6, 0xc6, 0xe3, 0x1e, 0x54, 0x6f, 0x33, 0x20, 0x25, 0x22, 0x12, 0x28, 0x17, 0xe2, + 0x6f, 0x5d, 0xa8, 0x59, 0xc6, 0xdd, 0xa6, 0x43, 0xec, 0x26, 0x89, 0xeb, 0x83, 0x66, 0xf0, 0xd6, 0xa5, 0x95, 0xd7, + 0x19, 0x52, 0xf8, 0x48, 0x45, 0x06, 0xce, 0x0d, 0x53, 0x7b, 0xda, 0x65, 0x1d, 0xc6, 0xbc, 0x54, 0xca, 0xaa, 0x08, + 0xb8, 0xd5, 0x00, 0xcf, 0xda, 0xb7, 0x70, 0x4c, 0x13, 0x1b, 0x9a, 0xa7, 0xbe, 0xcf, 0xd1, 0x76, 0x37, 0x5e, 0xb4, + 0xe2, 0xab, 0xd7, 0xd6, 0x71, 0xd9, 0x3c, 0xeb, 0x6e, 0x13, 0x56, 0xb1, 0x9f, 0x22, 0x29, 0x6c, 0x1a, 0x8b, 0xb9, + 0x26, 0x71, 0x4c, 0x02, 0xa3, 0x05, 0xb0, 0x37, 0xd1, 0x2c, 0xbb, 0x58, 0x22, 0xb5, 0x75, 0x58, 0x77, 0x73, 0xc0, + 0xe1, 0xdb, 0xce, 0x57, 0xaa, 0x76, 0x53, 0x83, 0x12, 0x39, 0xe7, 0xc3, 0xfe, 0xc2, 0xed, 0xfe, 0x50, 0xe2, 0x4d, + 0xdd, 0xc6, 0xe2, 0x48, 0x34, 0x16, 0x10, 0x5c, 0x66, 0x8c, 0xda, 0x2c, 0x8b, 0x10, 0x9d, 0x5a, 0x59, 0xff, 0x40, + 0x05, 0x48, 0x25, 0xd4, 0x6a, 0x71, 0x33, 0x81, 0x05, 0xc7, 0xa4, 0xd4, 0xc6, 0xe1, 0xc7, 0x3f, 0x89, 0xa7, 0x54, + 0xb4, 0x69, 0xd4, 0x13, 0xcd, 0x05, 0xfb, 0x72, 0x88, 0x46, 0x20, 0x77, 0x1b, 0xd6, 0x38, 0xf5, 0xa2, 0xb3, 0xb9, + 0x51, 0xe8, 0xb0, 0x32, 0x55, 0x60, 0xfc, 0xad, 0xc2, 0x6c, 0x20, 0xe7, 0x2a, 0x89, 0x95, 0xdb, 0x19, 0x78, 0x61, + 0x84, 0x0e, 0x62, 0x00, 0xbd, 0x9d, 0xfc, 0x54, 0x7f, 0x5a, 0x5d, 0x94, 0x71, 0x22, 0x4c, 0x4e, 0xdf, 0xdb, 0xc1, + 0x83, 0xda, 0x6c, 0xe7, 0x52, 0xbc, 0xe6, 0x39, 0x81, 0xf6, 0x95, 0x9f, 0xfd, 0x5e, 0xbf, 0x3f, 0x71, 0x13, 0x5a, + 0x56, 0x20, 0x75, 0x8a, 0x7f, 0xd5, 0x9d, 0x51, 0xee, 0x76, 0xce, 0xb3, 0x09, 0xcb, 0x63, 0x92, 0xec, 0x1b, 0x7f, + 0x5b, 0xb8, 0xe4, 0x68, 0xc9, 0x9f, 0x38, 0x0f, 0x8c, 0x62, 0x31, 0x4d, 0x16, 0xa6, 0x7e, 0x4d, 0xd2, 0xde, 0xc4, + 0x75, 0x6c, 0xc4, 0xf1, 0x9f, 0xe3, 0x10, 0x3d, 0x49, 0x84, 0xd4, 0x7a, 0x4b, 0x51, 0x3d, 0xaa, 0x7b, 0x27, 0xea, + 0x42, 0x36, 0x0f, 0x39, 0x5a, 0x93, 0x31, 0x9d, 0xd4, 0x5d, 0xaa, 0x91, 0x68, 0x04, 0x4b, 0xb7, 0x76, 0x3b, 0x39, + 0x3c, 0xc4, 0x4b, 0xfb, 0x28, 0x12, 0x15, 0xbd, 0x0b, 0x4d, 0x71, 0x68, 0xa3, 0x58, 0x5f, 0x59, 0x89, 0x05, 0xd6, + 0x5e, 0x2a, 0xad, 0xe6, 0x82, 0xae, 0xbc, 0x1c, 0x15, 0x3a, 0x27, 0x00, 0x5b, 0xcb, 0x39, 0x91, 0x01, 0x74, 0x62, + 0xb1, 0x70, 0x1d, 0x72, 0x03, 0xca, 0x10, 0xa1, 0x72, 0x4b, 0x8f, 0x53, 0x69, 0xd5, 0x28, 0x96, 0x80, 0xc4, 0x70, + 0xc6, 0x7c, 0xeb, 0x63, 0x36, 0x6e, 0x64, 0x0c, 0xae, 0x5a, 0x76, 0x6d, 0x19, 0x6b, 0x6b, 0x85, 0xb4, 0x0e, 0x98, + 0x5a, 0x65, 0x3f, 0x35, 0xbe, 0xf3, 0xe7, 0xbd, 0x23, 0x4d, 0x6f, 0x71, 0x24, 0x11, 0x06, 0x6d, 0xaf, 0x18, 0x0b, + 0x53, 0x84, 0xdb, 0xec, 0xf6, 0x8a, 0xd0, 0xdd, 0x5f, 0x0a, 0x7c, 0x5b, 0xb8, 0x31, 0x15, 0x37, 0x8e, 0x1e, 0x5f, + 0x14, 0x4c, 0x04, 0xe3, 0xd0, 0x54, 0x95, 0xf0, 0x6e, 0xba, 0x0a, 0x0a, 0x72, 0x2a, 0x2a, 0x1c, 0x78, 0xb0, 0x5e, + 0x66, 0xf4, 0x28, 0x12, 0x8a, 0x2d, 0xae, 0x6a, 0x4d, 0x14, 0x77, 0x19, 0x17, 0xa4, 0x2f, 0x87, 0xf9, 0xb7, 0xaa, + 0x1b, 0xba, 0x66, 0x55, 0xba, 0x45, 0xe2, 0x6b, 0x53, 0x8d, 0x46, 0x44, 0xe5, 0x7b, 0xe9, 0x03, 0xf3, 0x58, 0x4b, + 0x77, 0x3e, 0xed, 0x13, 0xae, 0x0c, 0x1c, 0x18, 0xfa, 0x48, 0xf7, 0x57, 0xeb, 0xea, 0x24, 0x1f, 0x57, 0x9f, 0x7c, + 0x0d, 0xcf, 0x1f, 0x8c, 0x9d, 0x76, 0x70, 0xcb, 0x21, 0x7d, 0xcc, 0xf9, 0x35, 0x33, 0xbd, 0x45, 0xab, 0xbd, 0x51, + 0xa3, 0x2e, 0xb0, 0x99, 0x4c, 0xd3, 0x63, 0xfe, 0xe9, 0xad, 0xe8, 0xc1, 0x05, 0x27, 0x89, 0x2f, 0x20, 0xe1, 0x86, + 0xed, 0xd5, 0xc7, 0x47, 0xaa, 0xeb, 0xd6, 0x09, 0x25, 0x76, 0x23, 0x95, 0xed, 0xa0, 0x42, 0xc8, 0x0e, 0xf7, 0xc4, + 0xd5, 0x1b, 0xec, 0x73, 0x88, 0xd3, 0xd1, 0x00, 0x29, 0x93, 0x26, 0xf6, 0x25, 0x8c, 0xf7, 0xc5, 0x1c, 0x36, 0x2b, + 0x48, 0xbc, 0xea, 0xc2, 0x29, 0x94, 0x58, 0xd9, 0xf3, 0xea, 0x78, 0x1d, 0xdd, 0xe4, 0x23, 0x9a, 0x32, 0xd0, 0xdc, + 0xbd, 0xe5, 0x2e, 0x17, 0x18, 0xdd, 0x6b, 0xf3, 0xf1, 0xdd, 0xce, 0x68, 0x4d, 0x12, 0xf9, 0xc6, 0xb7, 0xf9, 0x70, + 0xf3, 0xf8, 0x85, 0x86, 0xe2, 0x00, 0xd7, 0x71, 0xb8, 0xfd, 0xe1, 0xb2, 0x2a, 0xf7, 0xaa, 0x1f, 0xd4, 0xc0, 0x91, + 0x52, 0x4f, 0x0d, 0x67, 0x61, 0x4f, 0x30, 0xe1, 0xd4, 0x81, 0xb3, 0xe6, 0x83, 0x90, 0x73, 0xf9, 0xd7, 0x2e, 0x94, + 0x73, 0x37, 0x6e, 0x16, 0x9e, 0x06, 0x36, 0x76, 0x86, 0x3a, 0x5c, 0xea, 0xce, 0x6c, 0x49, 0x3c, 0xc3, 0x8f, 0xbb, + 0x9a, 0x08, 0x4b, 0xed, 0x81, 0xaf, 0x57, 0xbc, 0x9c, 0xfb, 0xdb, 0xe1, 0x8d, 0xe2, 0x82, 0x30, 0x33, 0xbe, 0x88, + 0x4a, 0x93, 0x2c, 0x69, 0xf8, 0x36, 0xb2, 0x19, 0x75, 0xed, 0xbb, 0x68, 0x45, 0x50, 0x32, 0x22, 0x54, 0x71, 0x68, + 0xc6, 0x50, 0x06, 0xe8, 0x58, 0x45, 0x69, 0xcf, 0xd7, 0x06, 0xb3, 0x4e, 0x36, 0x73, 0x04, 0x74, 0x44, 0xdf, 0x2f, + 0x5f, 0xd4, 0xb3, 0x7f, 0xdd, 0x1f, 0x1e, 0xbe, 0xc8, 0x55, 0x7d, 0xd4, 0x00, 0xfc, 0x8e, 0x54, 0xf5, 0xe8, 0x8d, + 0xe5, 0x57, 0x5a, 0x82, 0xad, 0x66, 0x07, 0x46, 0x9d, 0xa4, 0x8d, 0xd4, 0x86, 0xcc, 0x32, 0x67, 0x52, 0x28, 0x04, + 0x2d, 0x3d, 0x9e, 0x63, 0x31, 0x05, 0x50, 0xd2, 0xe5, 0x8a, 0x88, 0x0b, 0x06, 0x61, 0x15, 0x87, 0x31, 0x2c, 0xa4, + 0x69, 0x3d, 0xdb, 0xce, 0xa2, 0x51, 0x83, 0xd0, 0x35, 0x86, 0x44, 0x85, 0x99, 0xf5, 0x8c, 0x83, 0x5c, 0x6a, 0xbb, + 0x20, 0x4f, 0x7e, 0x73, 0x15, 0x03, 0xd0, 0x63, 0x22, 0x79, 0x5a, 0xd5, 0x44, 0x96, 0x90, 0xcf, 0xa4, 0x61, 0xd3, + 0xfb, 0xc3, 0x37, 0x31, 0x3d, 0xfa, 0xd8, 0xd5, 0xd6, 0x1f, 0xa2, 0xe4, 0xb9, 0x17, 0x29, 0x5f, 0xeb, 0xb4, 0x65, + 0x77, 0xa2, 0x4d, 0xd0, 0x44, 0xdb, 0x82, 0xb0, 0x05, 0x3a, 0xd0, 0x67, 0x3c, 0x1a, 0x2e, 0x1b, 0x51, 0x16, 0x8b, + 0x94, 0x28, 0x87, 0xfc, 0xe6, 0xec, 0x11, 0xe2, 0xb4, 0x16, 0x46, 0x03, 0xcb, 0xbd, 0x60, 0x18, 0x45, 0x17, 0xec, + 0x81, 0x4f, 0x2b, 0x52, 0x5c, 0x7d, 0xbb, 0x58, 0xf3, 0xba, 0x32, 0xd1, 0x36, 0x98, 0xf0, 0x0e, 0x1a, 0x1e, 0x61, + 0xaf, 0x71, 0x4e, 0x83, 0xae, 0xeb, 0xc9, 0xd3, 0x8a, 0x8c, 0x4d, 0x65, 0xa5, 0x1e, 0x01, 0xb7, 0xd8, 0xdb, 0x7e, + 0xd4, 0x36, 0x07, 0x7b, 0x36, 0xb6, 0xea, 0xc6, 0xb6, 0xc7, 0x10, 0xdc, 0x3a, 0x41, 0x3e, 0xdd, 0x29, 0x7d, 0x9e, + 0xe7, 0x4b, 0x6b, 0x13, 0xe8, 0xf0, 0xba, 0x35, 0xed, 0x71, 0x84, 0x11, 0x11, 0xb7, 0x99, 0x2e, 0x58, 0x58, 0x4a, + 0x6f, 0xa9, 0xae, 0x88, 0xe1, 0xd9, 0x0e, 0x59, 0x0d, 0x40, 0x2f, 0xb0, 0x3f, 0x94, 0xe7, 0x25, 0x5c, 0xe8, 0xf9, + 0xf0, 0xd1, 0x45, 0x95, 0x97, 0xa5, 0x1d, 0x66, 0x7b, 0xd6, 0xdd, 0xa0, 0xc2, 0xf5, 0xa9, 0x5a, 0x9d, 0x50, 0x20, + 0x96, 0x9e, 0xa3, 0xbf, 0xef, 0x53, 0x47, 0x3c, 0xcf, 0x08, 0x61, 0x27, 0x36, 0x9b, 0x07, 0x20, 0xf6, 0x41, 0xc7, + 0x04, 0x01, 0x42, 0xd0, 0x10, 0xab, 0x3d, 0xa0, 0x1e, 0xbf, 0x33, 0xf4, 0x7d, 0x44, 0x7a, 0x13, 0xa0, 0x32, 0x05, + 0xc5, 0x89, 0xda, 0xa7, 0x24, 0x22, 0x27, 0x3f, 0xc9, 0x2e, 0x9b, 0xb1, 0xa8, 0x93, 0xc0, 0xf9, 0x88, 0x53, 0xb0, + 0x14, 0x0a, 0xe7, 0xc5, 0x33, 0x01, 0x7c, 0x3a, 0x67, 0x8b, 0x69, 0xe1, 0x8b, 0x1c, 0x94, 0xcd, 0xa4, 0xc7, 0xf5, + 0x38, 0xb7, 0x7d, 0x4c, 0x38, 0x2a, 0xca, 0xd8, 0xd8, 0x5b, 0x75, 0x66, 0x8c, 0xf0, 0xd5, 0x44, 0xa8, 0xf7, 0x63, + 0x9c, 0xb7, 0xf7, 0x3d, 0x3e, 0xe2, 0x52, 0x6c, 0x2a, 0x84, 0xc2, 0x82, 0x9a, 0xa7, 0xf4, 0x47, 0x59, 0xe7, 0xd4, + 0xc8, 0x82, 0xf2, 0xb8, 0x82, 0x91, 0xa2, 0x4c, 0xfb, 0xec, 0xc9, 0x9e, 0x32, 0x48, 0x6c, 0xe7, 0x65, 0xa2, 0x2b, + 0x05, 0x0c, 0xa2, 0x54, 0x0a, 0x76, 0xb5, 0x2d, 0x14, 0xc9, 0x20, 0x1c, 0x43, 0xbb, 0x11, 0x47, 0x55, 0xe6, 0x90, + 0x84, 0x7c, 0xcd, 0xd7, 0x38, 0xb3, 0xdd, 0x1c, 0x52, 0x18, 0x6c, 0x51, 0x4d, 0x46, 0x81, 0xd0, 0x6e, 0x41, 0x40, + 0xe8, 0xd2, 0x85, 0xdf, 0xe0, 0x97, 0x47, 0xa9, 0x6c, 0x26, 0x38, 0x4f, 0x17, 0x6e, 0xe1, 0x97, 0x1e, 0xb5, 0x62, + 0xc7, 0x5b, 0x6b, 0xe3, 0x12, 0xe5, 0xa2, 0x65, 0xfe, 0x23, 0xf6, 0xb8, 0x80, 0x03, 0x5b, 0x60, 0x6d, 0xe8, 0x0e, + 0x95, 0x61, 0x34, 0x70, 0xe2, 0x01, 0x24, 0xb5, 0xbb, 0x61, 0x49, 0x5b, 0xd4, 0x7f, 0x32, 0xd7, 0xea, 0x1a, 0x34, + 0x81, 0x59, 0xab, 0xc5, 0x36, 0x4d, 0x85, 0x1c, 0x32, 0xaa, 0x1a, 0xb0, 0x52, 0x6d, 0x87, 0x34, 0x59, 0x22, 0x87, + 0x24, 0x71, 0x27, 0x73, 0x06, 0x55, 0x56, 0x7a, 0xd1, 0xff, 0xa8, 0x44, 0xe4, 0x43, 0x5e, 0xff, 0xa4, 0x8a, 0x67, + 0x99, 0xd4, 0x8f, 0xc2, 0xa1, 0x4a, 0x63, 0x93, 0x0d, 0x6d, 0x00, 0xa3, 0x0f, 0x73, 0xa8, 0x2c, 0x74, 0x6c, 0x95, + 0xfb, 0x6e, 0x5a, 0xc9, 0xb1, 0x21, 0x9f, 0xcc, 0x18, 0x30, 0xdf, 0x7e, 0x0b, 0x62, 0x8f, 0x5b, 0xcc, 0x38, 0xdc, + 0x4b, 0x7e, 0xbe, 0x4c, 0x44, 0xc1, 0x1f, 0x4e, 0xc3, 0x0e, 0x7c, 0xd3, 0x21, 0xa6, 0xcd, 0x15, 0x33, 0x64, 0x06, + 0xa5, 0x6d, 0x09, 0x31, 0x2d, 0x78, 0x4a, 0xa4, 0xfb, 0xf7, 0xfe, 0xc4, 0xde, 0xd3, 0x7c, 0x21, 0x3f, 0x59, 0x9d, + 0x83, 0xbe, 0x55, 0x97, 0x3e, 0x86, 0x17, 0xc6, 0x7d, 0x00, 0x50, 0xb9, 0xbd, 0x6d, 0xc5, 0x71, 0x7b, 0x5f, 0x85, + 0xf8, 0x83, 0x19, 0x66, 0x1c, 0xaf, 0x52, 0x64, 0x63, 0x81, 0xe9, 0x94, 0x59, 0xa9, 0x5b, 0x35, 0x2b, 0xfb, 0xc7, + 0xf4, 0x5f, 0x1a, 0x0d, 0xb0, 0x2f, 0x17, 0xf9, 0xf9, 0x76, 0x99, 0x28, 0xb0, 0xc2, 0x22, 0xd1, 0x7b, 0x17, 0x40, + 0xba, 0x83, 0x48, 0xc6, 0x9f, 0xf7, 0x70, 0xd1, 0xf0, 0xf0, 0x17, 0x39, 0x68, 0xd9, 0x79, 0xe5, 0x44, 0x69, 0x3e, + 0xaf, 0xd8, 0x09, 0x44, 0x9e, 0x3a, 0x45, 0x98, 0xfe, 0x7d, 0x72, 0xe5, 0xb5, 0x47, 0x4e, 0xce, 0x5e, 0x40, 0xbf, + 0x26, 0x6e, 0x9f, 0x9f, 0x65, 0x1d, 0xfe, 0xb1, 0x44, 0x85, 0xb0, 0x52, 0xe8, 0x41, 0x55, 0x08, 0x5f, 0x70, 0xe2, + 0x00, 0x4e, 0x3d, 0x7c, 0x78, 0xc6, 0xdf, 0x0e, 0x43, 0xfb, 0xf8, 0x99, 0xb3, 0x69, 0x89, 0xf1, 0x12, 0x83, 0x45, + 0xb5, 0xd4, 0x78, 0x7e, 0xff, 0x34, 0xeb, 0xe9, 0x9e, 0xb1, 0x4f, 0x8b, 0x9e, 0xac, 0x6a, 0x9a, 0x37, 0x24, 0xce, + 0x7f, 0xd8, 0xfc, 0x5a, 0x1b, 0x1f, 0xec, 0xdc, 0x56, 0x25, 0x47, 0xd6, 0x05, 0xae, 0xcb, 0xaa, 0x55, 0xd5, 0x37, + 0x03, 0xce, 0x49, 0x8f, 0xc5, 0x4b, 0x9d, 0xdd, 0x2f, 0xe8, 0x8f, 0x66, 0x3a, 0x5a, 0x1f, 0x7d, 0x70, 0x2d, 0x42, + 0xd5, 0xa4, 0x33, 0xba, 0x37, 0xbf, 0xc3, 0x39, 0xe5, 0x33, 0xd7, 0xf1, 0xb9, 0x5b, 0x0b, 0xe5, 0x09, 0x8f, 0x16, + 0x1a, 0x85, 0xa1, 0x3b, 0x77, 0x8f, 0xe0, 0x5a, 0x24, 0xcd, 0xc8, 0xde, 0xc2, 0x39, 0xd3, 0xf8, 0x4c, 0x7f, 0x36, + 0x0b, 0xf5, 0xa7, 0x3e, 0x14, 0x14, 0x11, 0xf3, 0x2b, 0xa6, 0x62, 0x28, 0x25, 0xc1, 0x43, 0x44, 0x04, 0x5a, 0x47, + 0x51, 0x3e, 0x55, 0x57, 0x57, 0xca, 0xea, 0x97, 0xb3, 0x2c, 0x28, 0x92, 0xd9, 0x14, 0x59, 0xb9, 0xe2, 0x8f, 0x4e, + 0x72, 0x96, 0xeb, 0x42, 0x40, 0xce, 0x3e, 0xc0, 0x89, 0xfd, 0x9b, 0x41, 0xe0, 0xb6, 0xb6, 0xd6, 0xfe, 0x48, 0x50, + 0x63, 0x14, 0x7c, 0x8b, 0x00, 0x8c, 0xc4, 0xd0, 0x46, 0xf9, 0xe4, 0x56, 0xba, 0x50, 0x51, 0xbd, 0x3f, 0x71, 0xf7, + 0x3f, 0xbf, 0xbb, 0xc9, 0x0d, 0x1b, 0x77, 0x69, 0x0e, 0x4d, 0xe6, 0xc9, 0x39, 0xda, 0xc8, 0xee, 0xba, 0x5f, 0x06, + 0xf9, 0x2d, 0x5f, 0x92, 0xf4, 0x74, 0x44, 0x60, 0x4b, 0xcb, 0x8f, 0x48, 0x45, 0x49, 0x22, 0x90, 0x63, 0xad, 0x00, + 0x50, 0x33, 0x21, 0x95, 0x8a, 0x1c, 0x45, 0x9e, 0x8c, 0x7a, 0x33, 0xa7, 0x24, 0x2d, 0x69, 0x37, 0xa8, 0x31, 0x2c, + 0x87, 0xaf, 0xb9, 0x36, 0x4b, 0x7d, 0xad, 0xa4, 0xec, 0xc4, 0xf6, 0x82, 0x05, 0x94, 0x38, 0xa6, 0xe0, 0x82, 0xd5, + 0x58, 0x9a, 0x36, 0xaf, 0x27, 0x18, 0xd0, 0x32, 0x97, 0x76, 0xd9, 0x12, 0xf2, 0x95, 0xfa, 0x7d, 0x58, 0x8c, 0x90, + 0x7c, 0x63, 0xa1, 0x58, 0xda, 0xaa, 0x55, 0xb9, 0xf3, 0x1c, 0x3f, 0xd0, 0xa4, 0x48, 0x1d, 0xed, 0x61, 0xfa, 0x16, + 0x8e, 0xc4, 0xe0, 0x66, 0x4e, 0xb9, 0xa4, 0x4c, 0xe3, 0xd2, 0x9f, 0xa4, 0xff, 0xaa, 0x2f, 0x43, 0x3e, 0xc1, 0x51, + 0xac, 0xfe, 0x83, 0x6a, 0xcc, 0x40, 0x40, 0xea, 0x4b, 0x10, 0x15, 0xc3, 0x68, 0xe6, 0x10, 0xdd, 0xa0, 0xf5, 0x99, + 0x3a, 0x91, 0xce, 0x5e, 0x6c, 0x70, 0xd2, 0x97, 0x73, 0xa2, 0x79, 0xe1, 0x3b, 0x8c, 0xf7, 0x81, 0x01, 0x0c, 0x0a, + 0xf3, 0x60, 0x0c, 0xec, 0xb2, 0x26, 0x6d, 0x29, 0xb8, 0x41, 0x0d, 0x34, 0x81, 0x07, 0x78, 0x3a, 0x89, 0x90, 0x8b, + 0x7c, 0x66, 0x71, 0x27, 0xbb, 0x98, 0x52, 0x6b, 0x7e, 0x2c, 0x84, 0x85, 0xfe, 0xdd, 0x62, 0x2b, 0xcb, 0x1d, 0x3c, + 0x13, 0x11, 0x54, 0x05, 0x0a, 0xbc, 0x72, 0x79, 0x43, 0xa7, 0x25, 0x70, 0xf0, 0x3e, 0xb5, 0xe2, 0x06, 0x07, 0xbe, + 0x0d, 0x2a, 0x5d, 0xb0, 0x1f, 0xb4, 0xeb, 0xdf, 0x7b, 0xae, 0xc2, 0x22, 0xea, 0x21, 0xde, 0x6a, 0xae, 0x57, 0x77, + 0xf7, 0xbe, 0xd7, 0xf1, 0x59, 0x53, 0xcb, 0x1e, 0x7f, 0xc6, 0x10, 0x0a, 0x4e, 0xd0, 0x2a, 0x15, 0x12, 0x30, 0xf0, + 0xc7, 0x2d, 0x6c, 0xfc, 0x92, 0xa5, 0xdb, 0x11, 0x4b, 0x7f, 0xfd, 0xba, 0xa2, 0xc9, 0xae, 0xba, 0xa9, 0x27, 0xa0, + 0x88, 0xbd, 0xa3, 0x55, 0x76, 0xb8, 0x4a, 0xcd, 0x7b, 0xc5, 0xbb, 0x1e, 0xf8, 0x94, 0x0e, 0xcc, 0x28, 0xb0, 0x17, + 0xc4, 0x1c, 0x18, 0xeb, 0xc7, 0x46, 0x79, 0xd7, 0x4f, 0xbe, 0x4b, 0xd1, 0x46, 0xad, 0xaf, 0xfc, 0x41, 0x10, 0xdf, + 0x67, 0x46, 0xac, 0xbd, 0x04, 0x66, 0x30, 0xba, 0xd3, 0x36, 0x1d, 0x76, 0xe5, 0x3e, 0x9e, 0x1f, 0xb2, 0xde, 0x41, + 0x40, 0xa5, 0xe8, 0x47, 0x81, 0x4b, 0x26, 0x30, 0x98, 0x83, 0x23, 0xdb, 0x8b, 0x3d, 0xf9, 0x44, 0xcc, 0x85, 0x28, + 0x45, 0x33, 0x46, 0x01, 0xc1, 0xc8, 0x61, 0x85, 0xed, 0x3f, 0xc2, 0x76, 0x01, 0x70, 0x8b, 0x87, 0x0c, 0x7b, 0x5e, + 0xe3, 0x4d, 0xbc, 0x1d, 0x35, 0xcc, 0x99, 0xd4, 0x5b, 0xd0, 0x4e, 0x8f, 0x21, 0xf9, 0x7d, 0x1a, 0x24, 0xa3, 0x22, + 0xf7, 0x28, 0x12, 0x84, 0xd7, 0x45, 0x4e, 0x5a, 0x80, 0x75, 0x77, 0xe8, 0xa6, 0x5f, 0x01, 0x62, 0xfa, 0x5e, 0x02, + 0xfe, 0x44, 0x6e, 0x22, 0x16, 0xbc, 0xdd, 0x34, 0xc4, 0x1d, 0x4c, 0x80, 0xa1, 0x11, 0x9e, 0x41, 0xd0, 0x08, 0x92, + 0x11, 0xdd, 0x6d, 0xee, 0xa7, 0xcc, 0x7f, 0x56, 0xe4, 0xc7, 0xb2, 0x31, 0xae, 0x79, 0xd3, 0xde, 0xc5, 0x6f, 0x11, + 0xa9, 0x00, 0x62, 0x67, 0xca, 0x2c, 0x54, 0x89, 0xc9, 0xd7, 0x85, 0x8d, 0x7d, 0x6e, 0x94, 0x25, 0xdb, 0xe7, 0xf5, + 0xd7, 0x66, 0xd8, 0x92, 0x66, 0xb6, 0xb7, 0x39, 0xe3, 0xb3, 0x8a, 0x89, 0x85, 0x17, 0x05, 0xce, 0xfd, 0xed, 0xd7, + 0xfd, 0xf9, 0x70, 0x95, 0x2d, 0xdb, 0x29, 0x53, 0x8f, 0x23, 0x25, 0xcb, 0x5a, 0x7f, 0xbb, 0x32, 0x93, 0xb7, 0x6e, + 0xd1, 0x13, 0xec, 0xa8, 0x35, 0xf3, 0x25, 0x47, 0xda, 0xba, 0x87, 0x93, 0xec, 0xba, 0xc0, 0x2e, 0xef, 0x04, 0xd0, + 0xb4, 0x74, 0x42, 0xf1, 0x73, 0x25, 0xb4, 0xac, 0x1d, 0xe0, 0x24, 0x7e, 0xfa, 0x62, 0xe2, 0xa5, 0x98, 0xad, 0xc1, + 0x36, 0xbf, 0x62, 0x5e, 0xc4, 0x60, 0xcf, 0x8d, 0x0a, 0xe1, 0x8c, 0xf3, 0xbe, 0x05, 0xb3, 0xf4, 0x1b, 0xaf, 0xdc, + 0xe6, 0x73, 0x82, 0xfd, 0x96, 0x16, 0xc1, 0xc0, 0xc4, 0x5d, 0xf5, 0x5a, 0xe3, 0x2c, 0x84, 0xa8, 0x6b, 0xb9, 0x2f, + 0x62, 0xe6, 0x36, 0xa7, 0xe9, 0x5d, 0xad, 0xc9, 0x8c, 0xfd, 0xe2, 0x4a, 0x33, 0xeb, 0xbb, 0xef, 0x20, 0x6b, 0xad, + 0x2a, 0xf4, 0x2b, 0x52, 0xcf, 0x64, 0xfd, 0x27, 0xb0, 0x19, 0x8b, 0x1d, 0x16, 0x4b, 0x2b, 0x75, 0xe7, 0xaa, 0xf4, + 0x03, 0x9e, 0x54, 0x00, 0x72, 0x11, 0xd0, 0x99, 0x6e, 0x3d, 0x77, 0x8b, 0x45, 0x3d, 0xea, 0xc1, 0xad, 0xbf, 0xb7, + 0x1a, 0x06, 0x41, 0xac, 0x63, 0xbf, 0x22, 0x78, 0x3c, 0x5e, 0x89, 0xdf, 0x0b, 0xaf, 0xc8, 0x0f, 0x5b, 0x1e, 0xff, + 0x7c, 0x01, 0x65, 0xfa, 0x49, 0x34, 0xed, 0xfc, 0x6c, 0xc3, 0xc2, 0xa4, 0x7c, 0x3a, 0x8f, 0xfc, 0x1e, 0xcd, 0xcd, + 0x15, 0xb4, 0xdc, 0xf3, 0x03, 0x97, 0xf2, 0x7f, 0x16, 0x29, 0x4b, 0x6a, 0x85, 0x66, 0xd9, 0x36, 0xc1, 0xd1, 0xdd, + 0x9e, 0xe2, 0xc1, 0x73, 0x9c, 0x50, 0x68, 0x6f, 0x4a, 0xbd, 0x55, 0x85, 0x9a, 0xa8, 0xb5, 0x85, 0x02, 0x65, 0xfd, + 0x88, 0xf6, 0x51, 0x71, 0xc4, 0x0d, 0x23, 0x3d, 0xea, 0x6f, 0x6a, 0x6d, 0x91, 0x5d, 0x47, 0xed, 0x97, 0xb5, 0xfb, + 0x7d, 0x12, 0x24, 0xff, 0x6d, 0x05, 0xc8, 0xac, 0x0d, 0xd5, 0x9b, 0x80, 0x69, 0x44, 0x31, 0x47, 0xc1, 0x8f, 0xd1, + 0x92, 0x42, 0xa3, 0x0c, 0x2e, 0x1c, 0x11, 0x66, 0x2d, 0xb5, 0xe4, 0x19, 0x43, 0xf0, 0xbc, 0xd1, 0xd0, 0x91, 0xf0, + 0xb5, 0xe9, 0x5d, 0x76, 0x66, 0x36, 0x4c, 0xce, 0x3d, 0xa2, 0x21, 0x9b, 0x7a, 0xaa, 0x28, 0x01, 0xf7, 0xcd, 0x72, + 0x7c, 0x75, 0x50, 0xb2, 0x26, 0xb5, 0x57, 0xc1, 0x6e, 0x1f, 0x72, 0x73, 0x19, 0xbd, 0x35, 0x54, 0x6b, 0xf8, 0xde, + 0x48, 0xd6, 0xb0, 0xca, 0x35, 0x90, 0xd8, 0xce, 0x8f, 0x30, 0x49, 0x45, 0x77, 0xf9, 0x16, 0x34, 0xde, 0x51, 0x95, + 0xcb, 0x4e, 0xeb, 0xda, 0xbb, 0x03, 0x37, 0x61, 0xd8, 0xfa, 0xd4, 0x8d, 0x8e, 0xf4, 0xfd, 0x80, 0x0d, 0x9a, 0x95, + 0x4a, 0x03, 0x4e, 0xf9, 0x05, 0x15, 0xad, 0xf3, 0xbb, 0x25, 0x5f, 0xec, 0x19, 0xee, 0x83, 0x11, 0x32, 0x26, 0x8e, + 0xc0, 0x8e, 0x1a, 0xe0, 0x29, 0x61, 0xc6, 0xe1, 0xc7, 0x9e, 0xdb, 0xd7, 0xc6, 0xa0, 0x7f, 0xa5, 0xd9, 0x50, 0x40, + 0x8d, 0xf6, 0xb8, 0x92, 0x54, 0x3a, 0x86, 0x19, 0x93, 0xc2, 0x87, 0x54, 0x28, 0x73, 0xfc, 0xbb, 0x73, 0x4d, 0xb1, + 0x66, 0x38, 0x57, 0x23, 0xd3, 0x86, 0xf3, 0xbf, 0x1a, 0xf3, 0x5b, 0x8e, 0xef, 0x20, 0xaa, 0x9e, 0x8e, 0x41, 0x87, + 0x50, 0x4a, 0x50, 0x76, 0x65, 0x42, 0x55, 0x03, 0xfd, 0xa2, 0x19, 0x6d, 0x9a, 0xd6, 0x8f, 0x91, 0xf3, 0xbf, 0x6e, + 0xbf, 0xb6, 0x93, 0x8b, 0xd6, 0x0a, 0xeb, 0xe2, 0x07, 0x3f, 0x30, 0xe4, 0xb5, 0x7b, 0x7e, 0x76, 0xab, 0x5c, 0xd9, + 0x53, 0x5b, 0x3c, 0x75, 0xc1, 0x97, 0xe9, 0xfa, 0x18, 0xbc, 0x2c, 0x20, 0x35, 0x8d, 0xaa, 0x75, 0xec, 0x13, 0x16, + 0x5a, 0xec, 0x3a, 0x6f, 0xd7, 0x2f, 0x4f, 0xaa, 0x89, 0x57, 0x2c, 0x03, 0x3a, 0x3f, 0xb3, 0x29, 0xf6, 0x91, 0x16, + 0x97, 0x0d, 0xff, 0x32, 0xa0, 0xe7, 0xd9, 0x40, 0x9e, 0xf9, 0x59, 0x7f, 0xae, 0x3f, 0xbe, 0xe5, 0x21, 0xa1, 0x14, + 0xb7, 0x35, 0x4e, 0xef, 0x1a, 0xdb, 0xcc, 0x3b, 0xb3, 0xb4, 0x8f, 0x9d, 0x66, 0x3e, 0xa2, 0x22, 0x5d, 0x70, 0x12, + 0xb6, 0xa7, 0x43, 0xba, 0x92, 0x6d, 0x16, 0x9a, 0x39, 0xf5, 0xa5, 0x71, 0x59, 0x9c, 0xd7, 0x69, 0x73, 0x31, 0xf7, + 0x82, 0xae, 0x03, 0x38, 0xd7, 0x29, 0x47, 0x70, 0x55, 0x11, 0x28, 0x9a, 0x9a, 0xb9, 0xa2, 0x78, 0x68, 0x2d, 0x76, + 0x73, 0x6b, 0xf7, 0x53, 0x8c, 0xb8, 0xd4, 0xa5, 0x2a, 0x51, 0x92, 0x6c, 0x59, 0x29, 0x90, 0xc9, 0x82, 0xac, 0x39, + 0x49, 0x15, 0x0e, 0xfa, 0x37, 0x87, 0x74, 0xf6, 0x62, 0xd8, 0x87, 0x70, 0xe6, 0x6b, 0xa9, 0x0a, 0xa3, 0x59, 0xac, + 0xe6, 0x39, 0x88, 0x54, 0x6d, 0x1f, 0x28, 0xa7, 0xca, 0x7d, 0x5b, 0x40, 0xe6, 0x46, 0xca, 0x4b, 0x51, 0x47, 0x6e, + 0x78, 0x4a, 0xbf, 0x36, 0x3d, 0x10, 0xa3, 0xd5, 0xb0, 0xa3, 0x8d, 0x66, 0xb3, 0x59, 0x14, 0x53, 0x8f, 0x43, 0x9b, + 0xd4, 0x7c, 0x1b, 0x51, 0xaf, 0x50, 0x35, 0xb3, 0x6f, 0x4c, 0x3d, 0x62, 0xc9, 0x9c, 0xe2, 0x35, 0x14, 0x26, 0xc9, + 0x3d, 0x8b, 0x2d, 0xea, 0x16, 0x6d, 0x6e, 0xce, 0x1c, 0x1b, 0x92, 0xb8, 0x8a, 0x4b, 0x99, 0xae, 0x34, 0x1e, 0x05, + 0xc2, 0x61, 0x25, 0xda, 0x4e, 0x30, 0x1b, 0xf3, 0xf4, 0x83, 0x9f, 0x92, 0x9f, 0x7b, 0x04, 0x4c, 0xb3, 0x2f, 0x60, + 0x2b, 0xe9, 0xce, 0x8c, 0xf8, 0x48, 0x41, 0xce, 0xe1, 0x2b, 0x86, 0xe9, 0x7b, 0x9b, 0xc8, 0x72, 0x1f, 0xe7, 0x53, + 0x82, 0x32, 0x39, 0xa9, 0x76, 0x68, 0xbc, 0x81, 0xd8, 0x1b, 0x20, 0x9e, 0x86, 0xb0, 0x04, 0x4f, 0x23, 0x60, 0x90, + 0xf8, 0xbc, 0x5c, 0xc5, 0x43, 0x2d, 0x6e, 0x7c, 0x97, 0x79, 0x08, 0x70, 0xb6, 0x0c, 0x43, 0x6d, 0x62, 0x92, 0xfb, + 0xb3, 0x06, 0x74, 0x27, 0xa2, 0x62, 0x49, 0x66, 0x97, 0x75, 0x15, 0x85, 0xf9, 0x77, 0x5e, 0x2f, 0x53, 0x27, 0x9c, + 0x2d, 0xde, 0xb8, 0x0d, 0x80, 0xe9, 0x42, 0x7b, 0xaa, 0x93, 0x13, 0x93, 0xe2, 0xd7, 0x50, 0x1a, 0xd6, 0x09, 0x0d, + 0x14, 0x89, 0xfa, 0x79, 0xb4, 0x9e, 0x98, 0xa2, 0x38, 0xff, 0x11, 0x91, 0x0c, 0x4c, 0x12, 0xc8, 0x60, 0xb4, 0x7b, + 0xc5, 0x9a, 0x50, 0xac, 0xfd, 0xa4, 0x65, 0xd3, 0x99, 0xfb, 0x36, 0x83, 0x98, 0xbd, 0x1f, 0x04, 0x0f, 0x04, 0xff, + 0xe5, 0x56, 0x27, 0x8c, 0xa0, 0x04, 0xc3, 0xec, 0x30, 0xff, 0x89, 0xac, 0xba, 0x2d, 0xe8, 0xa8, 0x57, 0xe4, 0xaa, + 0x77, 0xe2, 0x52, 0x67, 0x12, 0x55, 0x4f, 0x7e, 0x9e, 0xb8, 0xfb, 0x56, 0x36, 0x46, 0x0b, 0xdc, 0xe7, 0xc8, 0x27, + 0x57, 0x6e, 0x66, 0xdb, 0xc8, 0xa8, 0xa6, 0x28, 0x12, 0x8b, 0x98, 0xca, 0xbc, 0x79, 0x8e, 0xfb, 0xf0, 0xaa, 0xb9, + 0x83, 0xef, 0xb7, 0x39, 0xd8, 0xca, 0xac, 0xdc, 0xe5, 0xf2, 0x6d, 0x7a, 0x68, 0xd0, 0xfd, 0xae, 0x73, 0xa4, 0x4b, + 0xef, 0xa6, 0x72, 0x5b, 0xb7, 0x3b, 0x53, 0xe7, 0x23, 0xf5, 0xd4, 0xf1, 0xf9, 0x99, 0x74, 0x63, 0xb7, 0xfe, 0x53, + 0x35, 0xc1, 0x4f, 0xf9, 0x02, 0xb4, 0x34, 0x55, 0x7c, 0x2c, 0x28, 0xa3, 0x16, 0xdd, 0xc1, 0x57, 0x6e, 0xb9, 0x15, + 0xf4, 0x2b, 0x9f, 0xab, 0xbc, 0x70, 0x8d, 0x5c, 0x3a, 0x7b, 0xe1, 0x04, 0x36, 0xf5, 0xe0, 0x9d, 0xf1, 0x57, 0xc1, + 0x25, 0xe0, 0xda, 0x10, 0x07, 0x23, 0x25, 0x89, 0xf7, 0xd5, 0xc0, 0x1b, 0x11, 0xf1, 0x8f, 0x82, 0xa1, 0x51, 0xfa, + 0x96, 0xfa, 0x18, 0x5b, 0x0c, 0xb3, 0x3e, 0xaa, 0x94, 0xab, 0xb3, 0xb9, 0xe0, 0xd4, 0x39, 0xfa, 0x13, 0x46, 0xdc, + 0xf3, 0x00, 0xe7, 0xac, 0xae, 0x7f, 0x06, 0xe7, 0xb5, 0xfd, 0xcc, 0x38, 0x1f, 0x8a, 0xa6, 0x44, 0xeb, 0xdd, 0x78, + 0xa7, 0x3c, 0x9b, 0x2d, 0xe7, 0x67, 0x15, 0x5e, 0x0d, 0xf7, 0x19, 0x9f, 0x5e, 0xfa, 0x1d, 0x98, 0x3c, 0x0e, 0xba, + 0xf4, 0xbe, 0x72, 0x78, 0xef, 0x4e, 0xc5, 0x4a, 0x15, 0x35, 0xe2, 0xd8, 0xa1, 0x7b, 0x8d, 0xc7, 0xbd, 0x0b, 0xcc, + 0x1a, 0xab, 0x93, 0xc3, 0x43, 0x6b, 0xab, 0x7c, 0x5d, 0x65, 0x84, 0x9d, 0xc4, 0x37, 0xcb, 0xc6, 0x94, 0x48, 0xb0, + 0xbf, 0x0d, 0x94, 0x63, 0x38, 0x10, 0xe1, 0x61, 0xc2, 0x9b, 0xac, 0xc2, 0xbc, 0x96, 0x8a, 0x32, 0xab, 0x1d, 0xfe, + 0x5a, 0x71, 0x8d, 0x68, 0x07, 0x4b, 0xae, 0xa4, 0x0d, 0x66, 0xd1, 0xa5, 0xa4, 0x61, 0x75, 0xc3, 0xa1, 0x5e, 0xdf, + 0x15, 0x5c, 0xd5, 0xb6, 0x66, 0x91, 0xfc, 0x45, 0xd9, 0x8e, 0x95, 0x08, 0x9b, 0x29, 0xf3, 0x3c, 0xfb, 0x3f, 0xa2, + 0x4a, 0x87, 0xdc, 0x02, 0xa6, 0xf6, 0x43, 0xba, 0x42, 0x52, 0x8c, 0x0d, 0xda, 0x4f, 0x4a, 0x57, 0x32, 0xef, 0xf8, + 0x8d, 0xc5, 0x75, 0xcb, 0x50, 0xe4, 0x62, 0x33, 0x56, 0x17, 0x1b, 0xc0, 0xc2, 0x2a, 0x07, 0xcc, 0x46, 0x14, 0xcd, + 0xa2, 0x6c, 0xca, 0xa3, 0xed, 0x16, 0xaf, 0x5b, 0xb4, 0xfa, 0xfb, 0x33, 0xd1, 0x33, 0x5b, 0x27, 0x55, 0x9d, 0x65, + 0xbd, 0x7f, 0x65, 0xc5, 0x5c, 0xe1, 0xe1, 0x47, 0x7b, 0x6e, 0xe7, 0x88, 0xce, 0xfb, 0xbb, 0x9b, 0xfe, 0x85, 0xdd, + 0xfc, 0x7f, 0x49, 0x37, 0x61, 0x86, 0xf5, 0xe4, 0xf6, 0xd3, 0x4b, 0xac, 0x09, 0xe7, 0x3f, 0xb2, 0x89, 0x61, 0xdb, + 0x15, 0xd4, 0x16, 0x35, 0x66, 0x9c, 0x12, 0x3c, 0xf6, 0x81, 0x0a, 0xed, 0x61, 0xe2, 0x0a, 0x61, 0x54, 0x79, 0xaa, + 0x44, 0xfa, 0x5c, 0xfc, 0xb2, 0x4d, 0x64, 0xd0, 0x19, 0x87, 0xb2, 0x81, 0x9d, 0xdb, 0xb5, 0xca, 0xcc, 0xd6, 0xd2, + 0xfa, 0x8f, 0x99, 0x62, 0xf3, 0x7f, 0xc0, 0x12, 0xf5, 0x90, 0x47, 0x7e, 0x59, 0xb5, 0x08, 0xef, 0x0d, 0xe5, 0xe6, + 0x21, 0xc8, 0x2d, 0x8b, 0x0e, 0x7f, 0x60, 0x3e, 0x40, 0x8e, 0x60, 0x8c, 0x1a, 0xb0, 0x52, 0x4e, 0x21, 0x97, 0xf9, + 0x71, 0xaa, 0xc9, 0x50, 0xcb, 0x72, 0x9d, 0xb1, 0x4a, 0x23, 0xaf, 0x59, 0x99, 0xa7, 0x59, 0x91, 0x6b, 0x94, 0x0d, + 0x15, 0xd7, 0x9f, 0x91, 0xa3, 0x51, 0x1b, 0xd0, 0x10, 0xbb, 0xe3, 0x9c, 0xd8, 0x28, 0x73, 0xd4, 0x71, 0x72, 0x4b, + 0x9e, 0x59, 0x57, 0x33, 0x5b, 0x89, 0x93, 0x8b, 0x77, 0x9b, 0xb1, 0x6d, 0x77, 0x34, 0x2e, 0x99, 0x27, 0x8e, 0x73, + 0x74, 0x7d, 0xa3, 0xcd, 0x9e, 0x97, 0xec, 0xb8, 0xf8, 0x3f, 0x48, 0x0e, 0xdd, 0x3c, 0x1a, 0x11, 0xcc, 0xc5, 0x25, + 0x45, 0xa9, 0xe9, 0xe6, 0x48, 0x02, 0x1b, 0x1e, 0xff, 0xb9, 0x89, 0xae, 0xf8, 0x78, 0x6e, 0x56, 0x46, 0x14, 0x5b, + 0x9c, 0xd8, 0x9f, 0xed, 0x61, 0xd5, 0x7a, 0x44, 0xc2, 0x81, 0xb3, 0xce, 0xfa, 0x60, 0x9f, 0xeb, 0xd2, 0xff, 0xe0, + 0x07, 0x36, 0x12, 0x82, 0x8d, 0x61, 0xf5, 0xce, 0xfe, 0xa7, 0x66, 0xc5, 0x85, 0xae, 0x35, 0x3b, 0x5e, 0xf8, 0x57, + 0x5c, 0xe1, 0x2d, 0x49, 0x65, 0x25, 0x37, 0x2e, 0x77, 0x2a, 0xe3, 0x05, 0x55, 0x3a, 0x66, 0x61, 0xe8, 0x58, 0x4c, + 0xaf, 0x0e, 0x4a, 0xaf, 0x08, 0x68, 0xa8, 0xce, 0xb9, 0xab, 0x95, 0xd9, 0x04, 0x97, 0x11, 0x92, 0x4a, 0x81, 0xbb, + 0xc2, 0x90, 0xe9, 0x9d, 0x6f, 0x86, 0x7e, 0x30, 0x14, 0x66, 0x6e, 0x40, 0xd8, 0x32, 0x41, 0xa5, 0xc3, 0x9a, 0x15, + 0x7b, 0x41, 0x9b, 0x0c, 0xe6, 0x3c, 0xa2, 0xde, 0x6b, 0xa4, 0xbf, 0x73, 0xc2, 0x05, 0x38, 0x4a, 0x81, 0xc2, 0x80, + 0x2e, 0x6f, 0x3c, 0x40, 0x72, 0x89, 0x10, 0x63, 0x0d, 0x85, 0xd4, 0x26, 0x7e, 0x39, 0xbf, 0xe2, 0x9e, 0xf7, 0xb3, + 0xe3, 0xac, 0xeb, 0x5b, 0x03, 0x79, 0x98, 0x5f, 0xbf, 0xbd, 0xce, 0x7a, 0x90, 0xb3, 0x21, 0x71, 0xb1, 0xb2, 0xf3, + 0x8a, 0x76, 0x76, 0x45, 0x5b, 0xea, 0x6a, 0x54, 0xe1, 0xb6, 0x86, 0x29, 0x52, 0x54, 0xb1, 0xe1, 0x7a, 0x1b, 0xba, + 0x20, 0xe9, 0x8b, 0x35, 0x85, 0x84, 0x19, 0xbb, 0xa6, 0x30, 0x95, 0x3b, 0xa1, 0x47, 0x67, 0xc3, 0x40, 0x5f, 0x6c, + 0xfd, 0x02, 0xf4, 0xa7, 0x8d, 0x8d, 0x36, 0x7d, 0x4f, 0x54, 0x46, 0xcc, 0x29, 0xfa, 0xbc, 0xc3, 0xec, 0xd3, 0xfe, + 0x44, 0x77, 0xb0, 0x5a, 0x5f, 0xc6, 0x5f, 0x56, 0x6c, 0xd4, 0xc7, 0xd6, 0x33, 0x26, 0x89, 0x53, 0xc9, 0xed, 0x41, + 0x49, 0x41, 0x66, 0xde, 0x44, 0x0d, 0x19, 0x29, 0xad, 0x39, 0x8f, 0x20, 0xfe, 0x77, 0xae, 0x98, 0x99, 0x98, 0xf6, + 0x63, 0x5c, 0x52, 0x1f, 0x7f, 0xf7, 0xc4, 0x5b, 0xbb, 0x77, 0x9a, 0xa1, 0x63, 0xf6, 0x00, 0x81, 0x9c, 0x57, 0x5e, + 0xba, 0x60, 0x68, 0x6e, 0xad, 0x54, 0xb3, 0xa6, 0x51, 0xfe, 0xb3, 0xbb, 0x32, 0x05, 0x03, 0xfb, 0x44, 0xad, 0x3f, + 0xdb, 0xe5, 0x66, 0xea, 0x1b, 0xb3, 0x57, 0x03, 0x4e, 0x04, 0x66, 0x36, 0xdd, 0x54, 0xfa, 0xaf, 0xfb, 0xfe, 0x3b, + 0x16, 0xa0, 0xd8, 0xd9, 0xc8, 0x1f, 0x9a, 0x8a, 0xe0, 0xc6, 0x77, 0x67, 0x2f, 0x86, 0x2d, 0x0a, 0x05, 0x5f, 0x46, + 0x99, 0xee, 0x32, 0xf2, 0x07, 0x0d, 0x6d, 0xf0, 0x4b, 0x7a, 0x63, 0x1b, 0x97, 0x61, 0x1f, 0xed, 0x61, 0x12, 0xbb, + 0x60, 0x68, 0x6b, 0x62, 0x41, 0x50, 0x35, 0x75, 0xde, 0x30, 0x22, 0xa1, 0x6f, 0xad, 0x95, 0xcf, 0xeb, 0xd8, 0x33, + 0xde, 0x71, 0x3e, 0x64, 0x62, 0x04, 0x7e, 0x8b, 0xb6, 0x5b, 0x12, 0xca, 0xb8, 0x74, 0x0c, 0x32, 0xb5, 0x47, 0x6d, + 0xc7, 0xc9, 0xb4, 0xed, 0x76, 0xd4, 0xee, 0xd1, 0xdd, 0xcd, 0x6f, 0x06, 0xa5, 0xed, 0x8e, 0xf0, 0x2d, 0xbc, 0x3a, + 0x73, 0xe4, 0x7e, 0xeb, 0xee, 0x24, 0x5b, 0xa0, 0x37, 0x33, 0x15, 0x14, 0x75, 0xc2, 0xc9, 0x33, 0xd6, 0xf8, 0xbf, + 0xd0, 0x54, 0xc1, 0x10, 0x98, 0xcc, 0x44, 0xb2, 0xdb, 0x82, 0x7c, 0x16, 0xfa, 0xfb, 0x14, 0x6e, 0x15, 0xb2, 0xb4, + 0x2d, 0x66, 0x08, 0xa7, 0x7a, 0xd0, 0x0c, 0x5e, 0x42, 0x81, 0x28, 0xed, 0x9d, 0xa1, 0x32, 0xe8, 0x41, 0xa5, 0x03, + 0x99, 0x28, 0x06, 0x35, 0x4b, 0x61, 0xca, 0x9b, 0x90, 0x7a, 0xf7, 0x7b, 0xbd, 0xf5, 0x77, 0xf9, 0xde, 0x8c, 0x22, + 0x1e, 0xf5, 0xd6, 0x49, 0x02, 0x82, 0x5f, 0x71, 0x20, 0x13, 0xe5, 0xf5, 0x92, 0x18, 0xb1, 0x8e, 0xc7, 0x49, 0xae, + 0x16, 0x1d, 0xaf, 0xc4, 0x39, 0x25, 0x15, 0x42, 0xce, 0x01, 0x0c, 0x13, 0x05, 0xee, 0xe5, 0x38, 0x82, 0xf5, 0x80, + 0x67, 0x72, 0x45, 0x3d, 0x1b, 0x8b, 0xbb, 0xfd, 0xef, 0xe5, 0xd5, 0xed, 0x9a, 0xf6, 0x36, 0x49, 0x01, 0x56, 0x5d, + 0x54, 0x82, 0xef, 0xfe, 0xfc, 0x29, 0xe4, 0xb1, 0x64, 0x87, 0x5a, 0x2a, 0x73, 0x30, 0x5b, 0x74, 0x1d, 0x72, 0xd6, + 0xa7, 0xaa, 0x3a, 0x36, 0x39, 0xa0, 0x86, 0xd3, 0xb4, 0x73, 0xc1, 0x78, 0x9c, 0xb0, 0x86, 0x73, 0xc2, 0x1a, 0x76, + 0xa8, 0x68, 0x23, 0x8c, 0x6e, 0x68, 0x31, 0x96, 0xb4, 0xc6, 0x7c, 0x3b, 0x20, 0x24, 0xf8, 0x7a, 0xa1, 0x95, 0x8b, + 0x8c, 0xe3, 0x8f, 0x2d, 0x06, 0x13, 0xec, 0x12, 0x2b, 0xdd, 0x84, 0x7f, 0x0d, 0xcf, 0x95, 0xbe, 0x95, 0x27, 0x71, + 0x73, 0x6f, 0xce, 0xe1, 0x44, 0xe3, 0x51, 0x93, 0x8c, 0xfc, 0x94, 0xf5, 0xa8, 0x94, 0xe4, 0x3f, 0x37, 0x8f, 0x81, + 0x33, 0x73, 0x8b, 0x7d, 0x25, 0x30, 0x26, 0x54, 0x3a, 0x96, 0xf1, 0x2f, 0x11, 0xf5, 0xd9, 0x68, 0xc4, 0x0c, 0x0a, + 0xe3, 0x5c, 0x25, 0x56, 0xe2, 0x3e, 0xdb, 0xa2, 0x97, 0xf2, 0xae, 0x31, 0x46, 0x25, 0x4c, 0xc5, 0x2f, 0x46, 0xf6, + 0x18, 0xa9, 0xb7, 0x73, 0xb6, 0xfd, 0x5c, 0x13, 0xdd, 0x73, 0x3a, 0x90, 0x04, 0x8d, 0x4b, 0x66, 0x0a, 0x90, 0xc4, + 0x04, 0x63, 0x72, 0x07, 0x2c, 0xda, 0xa6, 0x75, 0x9e, 0xc2, 0xab, 0x56, 0xe3, 0x49, 0x65, 0x7b, 0xdf, 0x65, 0x65, + 0x2e, 0xdb, 0x8e, 0x4e, 0x5b, 0x12, 0x24, 0x8d, 0x1a, 0xa7, 0x48, 0x48, 0xd5, 0xd3, 0xac, 0x0c, 0x0b, 0x84, 0xb5, + 0xe2, 0x9c, 0xbe, 0xb9, 0x35, 0x99, 0x9d, 0x17, 0xb1, 0x57, 0x78, 0x15, 0x85, 0x08, 0x6e, 0x67, 0x13, 0x89, 0x0f, + 0x63, 0xcb, 0x3a, 0x59, 0xc8, 0xd2, 0xb7, 0x6e, 0xad, 0x4b, 0xc0, 0x0f, 0xde, 0xea, 0xb7, 0xfb, 0xf1, 0x38, 0xb4, + 0x30, 0xd6, 0x47, 0xb8, 0xf8, 0xa8, 0x17, 0x2c, 0xad, 0x7c, 0x89, 0x08, 0x4a, 0x9b, 0xa5, 0xd7, 0xbf, 0x60, 0xb1, + 0x29, 0x2f, 0x57, 0x2c, 0x34, 0x36, 0x74, 0x33, 0x0d, 0xd5, 0x32, 0x31, 0x27, 0x15, 0x55, 0x31, 0xc7, 0x00, 0x3d, + 0xee, 0x20, 0x73, 0xcb, 0x22, 0x6b, 0xd2, 0xc3, 0x59, 0x09, 0xcc, 0xd7, 0x60, 0xe7, 0x38, 0x03, 0xea, 0xd8, 0xa4, + 0xea, 0x17, 0x0b, 0xa0, 0x24, 0x6e, 0xe0, 0x5b, 0x21, 0x77, 0xa1, 0xca, 0x1e, 0x29, 0xa4, 0xb0, 0x0e, 0x2c, 0xe1, + 0xac, 0x60, 0xc5, 0xd8, 0x3e, 0x6c, 0xe6, 0x8f, 0x51, 0x6f, 0x01, 0xd3, 0x43, 0x08, 0xf3, 0xdd, 0x1d, 0xb8, 0x11, + 0x1d, 0xad, 0xc9, 0xe4, 0x1e, 0x27, 0xc8, 0xa2, 0x9f, 0xfb, 0x25, 0x31, 0x14, 0x4f, 0xc8, 0xcb, 0x51, 0x33, 0x16, + 0xb5, 0x60, 0x5a, 0xa6, 0xcd, 0x2d, 0xdf, 0x7d, 0x6d, 0x23, 0xaa, 0x47, 0xc4, 0xa5, 0x42, 0x48, 0x1d, 0x14, 0xe8, + 0x0e, 0x73, 0xa9, 0xeb, 0xc9, 0xb3, 0x45, 0xf1, 0x2c, 0x9b, 0xae, 0x12, 0xfc, 0xe9, 0xe3, 0x0d, 0xb5, 0xbd, 0x09, + 0xa8, 0xf4, 0x5e, 0x77, 0x9c, 0x93, 0xde, 0x51, 0x89, 0x88, 0x26, 0x19, 0x7f, 0xfb, 0xc8, 0xbc, 0x05, 0x91, 0x58, + 0xeb, 0xe1, 0xd2, 0xeb, 0xb7, 0xaf, 0x51, 0xb0, 0x6a, 0x22, 0x9c, 0xbd, 0xa5, 0x49, 0x1c, 0xbc, 0x14, 0x21, 0x19, + 0x8a, 0x60, 0xe4, 0xa3, 0x82, 0xd8, 0x8a, 0xad, 0x12, 0x75, 0xb5, 0x86, 0x40, 0xc4, 0x39, 0xd8, 0x20, 0xb3, 0x8c, + 0xce, 0x99, 0xd7, 0xbe, 0x3c, 0x44, 0xf1, 0xd2, 0x14, 0xf5, 0xbf, 0x5a, 0x16, 0x7e, 0xf4, 0x70, 0xe0, 0x75, 0x64, + 0xe5, 0xac, 0x77, 0xbd, 0x54, 0x6e, 0xcb, 0x3a, 0x6e, 0xad, 0x7a, 0x4f, 0x9e, 0x20, 0xa7, 0xd1, 0xa6, 0x97, 0xe2, + 0xd6, 0x21, 0xa9, 0x31, 0xbc, 0x56, 0xb5, 0xa8, 0x8f, 0x0b, 0x77, 0xd8, 0x8b, 0x5a, 0xa9, 0x77, 0x30, 0x11, 0x5d, + 0xf7, 0xed, 0x9f, 0x88, 0x6a, 0xc8, 0x98, 0x8e, 0x35, 0xe4, 0x0e, 0x6c, 0xc1, 0xf4, 0x54, 0xd2, 0x77, 0x02, 0xf1, + 0xf8, 0x48, 0xb2, 0xab, 0xff, 0x94, 0xd1, 0xfd, 0x85, 0x8c, 0x81, 0x91, 0xd1, 0x1d, 0x61, 0x2d, 0xc2, 0xbd, 0x34, + 0xe8, 0x18, 0x23, 0x94, 0x4f, 0x89, 0x66, 0x66, 0xd9, 0x6d, 0x5e, 0x90, 0xd8, 0xe7, 0x5a, 0xcd, 0xde, 0x72, 0x9d, + 0x48, 0xd0, 0xa2, 0x04, 0xe2, 0xe5, 0x96, 0x19, 0x17, 0x80, 0xae, 0x8d, 0x9b, 0x14, 0x71, 0xb8, 0xb1, 0xd9, 0xdb, + 0x00, 0xa0, 0x7d, 0xfe, 0xfd, 0x4c, 0xe9, 0xe2, 0x76, 0x41, 0x09, 0x9b, 0x1f, 0x2c, 0x26, 0x8b, 0x5b, 0x19, 0x14, + 0x62, 0x23, 0x04, 0x0f, 0x64, 0x13, 0x8d, 0xdd, 0x7a, 0x8a, 0xd8, 0x3c, 0x5f, 0x20, 0x6d, 0x51, 0x78, 0x26, 0x67, + 0x93, 0xfd, 0x8b, 0x76, 0xb0, 0x81, 0xb1, 0x6e, 0x52, 0x94, 0xdf, 0x95, 0xa6, 0xa3, 0x8c, 0xda, 0xc7, 0x2f, 0x37, + 0x5c, 0x94, 0xa5, 0x26, 0x30, 0x9a, 0x46, 0xdd, 0xf2, 0xf7, 0x89, 0x13, 0x0c, 0x5d, 0x19, 0x01, 0xca, 0xb9, 0x94, + 0x09, 0x9f, 0xb3, 0x6f, 0x90, 0x16, 0x00, 0xf2, 0x9b, 0x1f, 0xb5, 0xe3, 0x63, 0x73, 0xbd, 0xfc, 0xd2, 0xb6, 0xa5, + 0x44, 0xf4, 0x5f, 0xda, 0x2a, 0xdb, 0xb1, 0x0f, 0x54, 0xf1, 0x30, 0x6a, 0x44, 0xcb, 0x9a, 0x0f, 0x59, 0xfb, 0x14, + 0x0f, 0x9b, 0x7b, 0x6f, 0x76, 0xa6, 0xc8, 0x86, 0xda, 0x25, 0xfb, 0xcb, 0x4b, 0x3a, 0x2f, 0xaf, 0xd6, 0x0c, 0x5e, + 0xed, 0x11, 0xea, 0x2a, 0x02, 0x05, 0x8f, 0xc1, 0x01, 0xbe, 0x36, 0xfb, 0x9e, 0x2d, 0x28, 0xf0, 0xcf, 0x8e, 0x9d, + 0xbf, 0x3c, 0x9f, 0x43, 0x02, 0x59, 0x9f, 0x35, 0x49, 0x04, 0x44, 0x24, 0x74, 0x3a, 0xdb, 0x1a, 0x82, 0x3c, 0x8c, + 0x2c, 0x1e, 0xb1, 0x59, 0xc6, 0x7f, 0xb1, 0x98, 0x8b, 0xcb, 0x7b, 0x36, 0xb9, 0x9f, 0x9b, 0xb7, 0xce, 0x00, 0xa9, + 0x6d, 0x9a, 0xc9, 0x48, 0x75, 0x64, 0x1a, 0x40, 0x05, 0xed, 0x85, 0x52, 0x4a, 0x46, 0xa9, 0x1c, 0x23, 0xb6, 0x6b, + 0x23, 0xe3, 0xe2, 0x64, 0x49, 0xc3, 0xb0, 0x24, 0xf8, 0x35, 0x11, 0x04, 0xbd, 0x54, 0x44, 0xf5, 0x70, 0x51, 0xca, + 0xdb, 0x21, 0x8f, 0x06, 0xd0, 0x52, 0xe3, 0x6d, 0x92, 0xa7, 0xdd, 0x8b, 0x73, 0x17, 0x59, 0x71, 0xf3, 0xa7, 0xc4, + 0x0f, 0x95, 0x63, 0x3c, 0x29, 0x90, 0x18, 0xe7, 0x5d, 0xb9, 0xf3, 0xa0, 0x0e, 0xc4, 0x1c, 0x13, 0x3c, 0xd2, 0xb3, + 0xaa, 0x3d, 0x98, 0x19, 0x68, 0x53, 0x1a, 0x4d, 0x15, 0xb5, 0x01, 0xe5, 0xff, 0x80, 0xbe, 0xca, 0xa7, 0xe5, 0x91, + 0x6b, 0x10, 0x86, 0xd2, 0x7a, 0x4b, 0xc3, 0x4b, 0x42, 0x68, 0x71, 0xae, 0x4c, 0x32, 0x08, 0xbc, 0xf1, 0xa1, 0xd7, + 0x35, 0x7e, 0x10, 0x25, 0x40, 0x73, 0xe6, 0x27, 0x1f, 0x3e, 0x9e, 0x03, 0x14, 0xce, 0x5a, 0x32, 0xfa, 0xb3, 0xab, + 0x09, 0x4b, 0xba, 0x5d, 0x34, 0xbb, 0x11, 0xca, 0x57, 0x29, 0x58, 0x5a, 0x58, 0x8a, 0xde, 0xa2, 0x3c, 0x30, 0x6c, + 0xb7, 0xb2, 0x7d, 0xfb, 0x5f, 0x1e, 0xde, 0x2b, 0x74, 0x91, 0xb0, 0x1d, 0xe2, 0xa7, 0xa8, 0xe9, 0x2f, 0x3e, 0x9c, + 0x9e, 0x8c, 0x61, 0xbb, 0x2b, 0x61, 0xee, 0x30, 0xcf, 0xb1, 0xbf, 0x74, 0xe4, 0x86, 0xb6, 0x12, 0x31, 0xf9, 0x5a, + 0x36, 0x61, 0x11, 0x07, 0x0c, 0x64, 0xae, 0x06, 0xb9, 0x83, 0x23, 0x04, 0xa6, 0xd6, 0x7c, 0xf2, 0xff, 0x54, 0x2d, + 0x1e, 0x9f, 0x2d, 0x8b, 0x4a, 0x82, 0x7c, 0x2b, 0xed, 0xf3, 0xd8, 0x87, 0xa4, 0x1d, 0xd8, 0xf7, 0x08, 0x16, 0xbd, + 0xdd, 0x61, 0x51, 0x68, 0xa1, 0x83, 0xb8, 0xa4, 0xce, 0xa7, 0xf0, 0xea, 0xe5, 0x32, 0x85, 0xd0, 0x29, 0x0b, 0x3c, + 0x5f, 0x45, 0x38, 0xa6, 0xf7, 0xc7, 0x03, 0x95, 0x05, 0xa5, 0x5c, 0x4e, 0xf0, 0x29, 0x6f, 0xea, 0x70, 0x06, 0xd4, + 0x90, 0xf6, 0xa9, 0x70, 0xc5, 0x3f, 0x4a, 0x59, 0x17, 0x3a, 0xb3, 0x90, 0xaa, 0x30, 0xd9, 0x91, 0xf0, 0xbf, 0x54, + 0xcc, 0x90, 0xe1, 0x85, 0x50, 0xa5, 0x0d, 0x7c, 0x6d, 0x8b, 0xae, 0x94, 0x17, 0x6d, 0x0b, 0x7d, 0x2c, 0x76, 0x65, + 0x4e, 0x00, 0xba, 0x01, 0x5a, 0x7b, 0xed, 0x82, 0xbb, 0x1b, 0xee, 0x65, 0x9f, 0x15, 0xf7, 0x6e, 0xda, 0x00, 0x07, + 0x5f, 0x20, 0xa7, 0xbe, 0x7f, 0x45, 0x71, 0xfe, 0x69, 0x2b, 0x1e, 0x2d, 0xc4, 0x94, 0x80, 0x09, 0x24, 0xe4, 0x1b, + 0x3e, 0xb6, 0x66, 0xc4, 0x3e, 0x7e, 0x08, 0x37, 0x4a, 0x09, 0x2b, 0x8d, 0x3c, 0x38, 0xca, 0xed, 0x37, 0x55, 0x86, + 0xe4, 0xb6, 0x9c, 0x83, 0xc2, 0x10, 0x0b, 0x07, 0xdc, 0x65, 0xae, 0x6c, 0x7f, 0xbc, 0x4a, 0x8f, 0xc2, 0x9e, 0xb8, + 0x50, 0xb1, 0x18, 0x6a, 0x64, 0xc4, 0x2b, 0x1e, 0xaa, 0xb3, 0xd2, 0xc4, 0x00, 0x19, 0x61, 0x80, 0x8e, 0x29, 0x6d, + 0x84, 0x40, 0x09, 0x01, 0x5b, 0x7e, 0xa8, 0xa3, 0x42, 0x13, 0xa1, 0x08, 0xa1, 0x25, 0xd2, 0x1c, 0x1d, 0x64, 0x65, + 0x86, 0xa4, 0xd2, 0x63, 0x76, 0x4c, 0x07, 0x96, 0x05, 0x58, 0x52, 0x29, 0x0a, 0x20, 0x9f, 0x8c, 0x51, 0xab, 0x88, + 0x50, 0xe2, 0xae, 0xbc, 0x4c, 0x1a, 0x0e, 0x58, 0xc3, 0x5c, 0x34, 0x17, 0x4b, 0xd6, 0x75, 0x38, 0x94, 0x21, 0x4d, + 0xae, 0x5a, 0x05, 0x79, 0xa7, 0x3f, 0x4f, 0x63, 0xce, 0x57, 0x04, 0x42, 0x9b, 0xfb, 0x91, 0xcb, 0x05, 0xc2, 0x8f, + 0x74, 0x6c, 0x8c, 0x91, 0x91, 0xb4, 0x76, 0x20, 0x75, 0x51, 0x22, 0x24, 0xc4, 0x95, 0x74, 0x41, 0x73, 0x3e, 0x14, + 0x22, 0x3e, 0x3b, 0x61, 0xae, 0x0f, 0x12, 0xb3, 0x44, 0xe5, 0xdf, 0x37, 0xcb, 0x61, 0xf5, 0x42, 0xf0, 0xb0, 0xd8, + 0xae, 0xaa, 0x1c, 0x28, 0x24, 0x12, 0xd6, 0xa8, 0x13, 0xe6, 0xce, 0x1b, 0xcb, 0xdf, 0x14, 0xc1, 0x9e, 0x27, 0x64, + 0x26, 0x18, 0xa5, 0x57, 0x51, 0xae, 0x54, 0xef, 0x94, 0x39, 0x8c, 0xdc, 0xf0, 0xee, 0xa6, 0xf8, 0xc1, 0x81, 0xbc, + 0x67, 0x53, 0x7a, 0xc4, 0xdb, 0xfd, 0x50, 0x4b, 0x9c, 0x53, 0x24, 0x39, 0x41, 0x29, 0xe8, 0xfe, 0xc3, 0x6b, 0x47, + 0x25, 0x31, 0xfe, 0xd0, 0xa2, 0xf4, 0x5b, 0x8b, 0xa7, 0xb9, 0x96, 0x33, 0x6d, 0xd2, 0xcc, 0x9c, 0x6f, 0x46, 0x15, + 0x9b, 0x2b, 0x63, 0x68, 0x5d, 0x70, 0x20, 0x00, 0x37, 0x83, 0x75, 0x2a, 0xad, 0xcf, 0xf5, 0x07, 0x08, 0x7d, 0xe3, + 0x3e, 0x28, 0xb3, 0x1d, 0x3c, 0x1a, 0x63, 0xc8, 0xeb, 0x67, 0x57, 0x75, 0xd0, 0x65, 0x44, 0x82, 0x00, 0x16, 0x7a, + 0xc8, 0xe1, 0x95, 0xba, 0x9c, 0xd9, 0xca, 0xec, 0xd1, 0xe6, 0xb5, 0x1c, 0x6f, 0x1d, 0x69, 0x38, 0x2e, 0x8e, 0x67, + 0x1f, 0x2c, 0x9d, 0x47, 0xe8, 0x48, 0xca, 0x8d, 0xf7, 0x4a, 0x20, 0xdf, 0x10, 0x19, 0xa8, 0xe7, 0xa2, 0x02, 0xb0, + 0x2b, 0x8b, 0xaa, 0xe4, 0x75, 0x78, 0xe8, 0xf9, 0x38, 0x32, 0x8f, 0x18, 0xe3, 0x10, 0x55, 0x46, 0x1e, 0x9d, 0xdc, + 0x2e, 0x2d, 0x32, 0x6a, 0x2e, 0x98, 0x5a, 0xcd, 0xbb, 0xea, 0x94, 0x07, 0xb2, 0xc9, 0xd7, 0x2b, 0x2d, 0xb4, 0x1e, + 0x89, 0x15, 0xdd, 0xac, 0x8a, 0x7a, 0x58, 0x20, 0x62, 0xbd, 0xff, 0x04, 0x91, 0x47, 0x2c, 0x1f, 0x64, 0xd4, 0x22, + 0x6d, 0xae, 0xc4, 0x4a, 0x29, 0x60, 0x76, 0x81, 0x42, 0x2b, 0xef, 0x10, 0x5c, 0xf9, 0x4d, 0x85, 0x44, 0xda, 0xc5, + 0x5d, 0x07, 0xea, 0x11, 0xbf, 0x35, 0xb2, 0x59, 0x1f, 0xa8, 0xe5, 0x7c, 0x2b, 0x2a, 0x1a, 0x22, 0x23, 0xd2, 0xd1, + 0x6f, 0x38, 0x01, 0xc3, 0x82, 0x0c, 0xe9, 0xf4, 0x3c, 0xf5, 0x58, 0xa0, 0xc5, 0x50, 0xe5, 0x54, 0x8c, 0x65, 0x52, + 0xdd, 0x0a, 0x96, 0x29, 0xb3, 0x50, 0x12, 0x5d, 0x41, 0xcb, 0xec, 0x35, 0xd8, 0x7c, 0xcf, 0x6a, 0x5b, 0x64, 0x44, + 0xc2, 0x35, 0xc2, 0x1f, 0x86, 0x31, 0x00, 0xaf, 0x12, 0xa5, 0xf3, 0xc0, 0x68, 0xc5, 0x24, 0xe6, 0x71, 0x0a, 0xaf, + 0x9b, 0x2a, 0x79, 0x81, 0x5b, 0xf3, 0xd4, 0xd4, 0x58, 0x7e, 0xff, 0xfa, 0xfb, 0x41, 0x53, 0x65, 0xad, 0x40, 0x7e, + 0xb2, 0x6e, 0xfd, 0xfb, 0x2e, 0xf7, 0x20, 0x6f, 0xd3, 0xfb, 0x7e, 0x1c, 0xf2, 0x0d, 0x04, 0x82, 0x51, 0x0a, 0xd3, + 0xc5, 0xfa, 0xb4, 0xc2, 0xe8, 0x7a, 0x49, 0xbb, 0x32, 0x7d, 0x40, 0xc2, 0xfb, 0x7a, 0xfb, 0x19, 0xa1, 0xcc, 0x12, + 0xfb, 0x50, 0x10, 0xc5, 0x4a, 0x94, 0x47, 0xe6, 0x67, 0x73, 0x6f, 0x45, 0x5c, 0x30, 0x53, 0xfd, 0x62, 0xf2, 0x30, + 0x24, 0x1c, 0x98, 0x99, 0x08, 0x07, 0xd6, 0xb4, 0xf0, 0xec, 0x6a, 0xc1, 0x9f, 0x96, 0x12, 0xe0, 0x11, 0xeb, 0x2a, + 0xfd, 0xbd, 0x8c, 0xa5, 0x18, 0xb1, 0xbd, 0x9d, 0xa1, 0xf4, 0x9c, 0x59, 0x07, 0x1d, 0x5e, 0x89, 0x82, 0x2d, 0xce, + 0xf4, 0x03, 0x33, 0x39, 0x8a, 0x0b, 0xaa, 0x25, 0xfc, 0xed, 0xad, 0xe2, 0xbe, 0x54, 0x3c, 0xa7, 0xb0, 0xef, 0x49, + 0xbe, 0xf8, 0x20, 0xed, 0xbd, 0xa8, 0x82, 0x56, 0x38, 0xb5, 0xc1, 0x0d, 0xf1, 0xd1, 0x9d, 0xf2, 0x50, 0x29, 0x42, + 0x08, 0xa3, 0xe8, 0x17, 0xf5, 0x08, 0x79, 0x81, 0xd7, 0xcb, 0xb7, 0x75, 0x7d, 0x48, 0x98, 0x82, 0xb8, 0xbe, 0xdb, + 0xc2, 0x19, 0x7d, 0x6a, 0x46, 0xcd, 0xdd, 0x71, 0xf5, 0x17, 0xea, 0x16, 0xef, 0x40, 0xb4, 0xc3, 0x74, 0x0f, 0x8f, + 0xeb, 0xfa, 0x68, 0x72, 0xd4, 0x85, 0x26, 0x6e, 0x35, 0xdb, 0xaf, 0xb4, 0x64, 0x9e, 0x06, 0x30, 0x68, 0x8c, 0xfa, + 0x7d, 0xc9, 0x1e, 0x8d, 0xef, 0x78, 0x4b, 0x64, 0x43, 0xb8, 0x0d, 0xe8, 0x70, 0x70, 0xa1, 0xa7, 0xfe, 0x46, 0xf6, + 0x6b, 0xb9, 0x04, 0xc7, 0x4b, 0xf1, 0x63, 0xdd, 0xf0, 0x47, 0x99, 0xd0, 0xec, 0x24, 0xa6, 0xc1, 0xfd, 0xb6, 0xb8, + 0xb2, 0xc2, 0x65, 0x12, 0x0a, 0x0b, 0x68, 0x40, 0x60, 0x01, 0x45, 0xd0, 0xe7, 0x30, 0x49, 0x94, 0x3d, 0x9c, 0xb3, + 0xdd, 0xdb, 0x7b, 0x71, 0x4c, 0x24, 0x9d, 0xd2, 0xe4, 0xe8, 0x07, 0x5e, 0x4c, 0x67, 0x51, 0x93, 0x68, 0xa4, 0x5f, + 0x31, 0x27, 0x2f, 0x1b, 0xe9, 0xc8, 0x00, 0x31, 0x67, 0x15, 0xa2, 0x0b, 0x69, 0xdf, 0x3f, 0x23, 0x32, 0xa0, 0x62, + 0x50, 0x37, 0xc3, 0x0e, 0xb1, 0x29, 0xe7, 0xb5, 0xeb, 0x07, 0x46, 0x4b, 0x7c, 0xb1, 0x3c, 0xca, 0xb0, 0xfc, 0x31, + 0x1f, 0xa3, 0xef, 0xbc, 0x95, 0x65, 0xe8, 0xc2, 0x72, 0x7e, 0x17, 0x93, 0xa5, 0x3a, 0x5c, 0x3d, 0x09, 0xe9, 0x7e, + 0x6a, 0xcd, 0x4b, 0xff, 0xb3, 0xe9, 0x82, 0xb4, 0xcf, 0x3c, 0xa4, 0x7e, 0x92, 0xc7, 0x68, 0xf7, 0x55, 0x2f, 0xac, + 0xd3, 0x85, 0x11, 0x66, 0xfa, 0xa8, 0x9a, 0x85, 0x0f, 0x55, 0x66, 0xcb, 0xc6, 0xd3, 0x52, 0xcc, 0x1f, 0x1d, 0xc1, + 0x1a, 0x82, 0x26, 0x24, 0x1b, 0xf7, 0x25, 0xf1, 0x83, 0xea, 0x82, 0xf1, 0x60, 0x87, 0xe5, 0xf5, 0xfc, 0x66, 0xd7, + 0xbe, 0xd3, 0xf2, 0xa9, 0xe0, 0x1f, 0x3c, 0xc4, 0xca, 0x9f, 0x0a, 0x87, 0x25, 0x2e, 0xbe, 0xb0, 0x52, 0x67, 0xbd, + 0x28, 0xa4, 0xad, 0xd5, 0xac, 0xa8, 0x65, 0x37, 0x64, 0xe5, 0x55, 0xde, 0xf2, 0x52, 0x0a, 0x7e, 0x4d, 0x45, 0x4e, + 0x72, 0x9d, 0x72, 0x31, 0x18, 0x78, 0x33, 0x27, 0xfd, 0x7a, 0x42, 0x1b, 0xb9, 0x81, 0x71, 0xfa, 0x3a, 0xb6, 0x2e, + 0x90, 0x04, 0x76, 0xf5, 0x91, 0x0b, 0x4f, 0x20, 0x91, 0xd5, 0xc7, 0x73, 0x36, 0xd6, 0xcd, 0x4e, 0xbe, 0x97, 0x77, + 0x19, 0x47, 0xf0, 0x4c, 0x21, 0xde, 0x9c, 0xd7, 0x06, 0xfc, 0x23, 0xef, 0x70, 0x6e, 0xe5, 0x7d, 0x50, 0x8d, 0xa1, + 0x35, 0x6c, 0x69, 0xe0, 0xab, 0x0b, 0x8c, 0x61, 0x02, 0xd5, 0x24, 0x08, 0x8e, 0xd6, 0x62, 0xbb, 0x20, 0x38, 0x96, + 0x51, 0x78, 0xb1, 0x3a, 0xe5, 0x17, 0x66, 0x53, 0x11, 0x45, 0x26, 0xfc, 0xc2, 0x0e, 0xd5, 0x66, 0x84, 0x43, 0xfc, + 0x58, 0x11, 0xe5, 0x43, 0x8d, 0x07, 0x20, 0x0e, 0x60, 0x7a, 0xd3, 0x88, 0x68, 0x7f, 0x8d, 0x1a, 0x05, 0x35, 0x3c, + 0x73, 0x97, 0xde, 0x59, 0x23, 0x2e, 0xeb, 0x6f, 0x0a, 0xcc, 0x2b, 0xb1, 0x6c, 0xaf, 0xac, 0xcb, 0x92, 0xf3, 0x3d, + 0x68, 0xe2, 0xb8, 0xd3, 0xce, 0x92, 0xb3, 0xe4, 0x00, 0x6d, 0xbb, 0xa7, 0xcd, 0x7c, 0x42, 0x72, 0x71, 0xb5, 0xeb, + 0x14, 0xa4, 0x32, 0xaf, 0x62, 0x23, 0x95, 0xe2, 0xbc, 0x73, 0x09, 0x38, 0xdc, 0x4f, 0xf1, 0xff, 0x55, 0xa2, 0xbe, + 0x9b, 0x5f, 0x10, 0xc6, 0x76, 0x52, 0xbf, 0x1c, 0x36, 0x6d, 0x61, 0x76, 0x70, 0xdd, 0xe2, 0xa6, 0xdd, 0x10, 0x55, + 0xd9, 0x5b, 0x6b, 0xbe, 0x34, 0x0f, 0x79, 0x61, 0x39, 0xb3, 0xd0, 0xea, 0xf3, 0xb8, 0x65, 0x44, 0xf9, 0xd4, 0x85, + 0xc3, 0xb1, 0xd0, 0x90, 0xcb, 0x9b, 0x43, 0x5d, 0xe4, 0xc7, 0xa4, 0xed, 0x01, 0x03, 0x49, 0x3d, 0xd1, 0xc6, 0x87, + 0x6e, 0xe6, 0xb6, 0x3b, 0x03, 0xe9, 0x7a, 0x39, 0x0d, 0x25, 0xb3, 0x18, 0xb8, 0x70, 0x34, 0xe6, 0xa9, 0x43, 0xa7, + 0x5d, 0xb1, 0x11, 0xd6, 0x1d, 0x0c, 0x57, 0x62, 0x54, 0x75, 0x18, 0xbb, 0xa6, 0xd5, 0x39, 0x56, 0xaa, 0xc7, 0xde, + 0x67, 0x1d, 0x91, 0xe0, 0x09, 0x05, 0x47, 0x1e, 0x78, 0x86, 0xcf, 0xea, 0xa0, 0xc3, 0xa3, 0x8e, 0xc0, 0xa1, 0xba, + 0x40, 0x5f, 0x1d, 0xc6, 0x40, 0x39, 0x82, 0x50, 0x44, 0xbe, 0x7b, 0xa0, 0x0e, 0xe1, 0x6b, 0x7e, 0x82, 0x99, 0x52, + 0x7a, 0x3e, 0x66, 0x7b, 0xf0, 0xe5, 0x80, 0xfb, 0xfd, 0x17, 0x9e, 0xd2, 0x35, 0x8c, 0xc3, 0x0f, 0xbf, 0xd5, 0x62, + 0xf9, 0xfd, 0x00, 0xf3, 0xed, 0x20, 0xd5, 0x25, 0x1c, 0xe5, 0x2a, 0xc0, 0x1f, 0x6d, 0x19, 0x77, 0x0d, 0x86, 0xf5, + 0x11, 0x14, 0x11, 0x1e, 0x71, 0x30, 0xdc, 0x2c, 0x05, 0x80, 0xe2, 0x3c, 0xac, 0x80, 0xc8, 0x42, 0x34, 0x3f, 0x2f, + 0x97, 0x58, 0x57, 0x65, 0x68, 0x4b, 0x4b, 0x36, 0x8f, 0x13, 0x31, 0x6c, 0x26, 0x49, 0x25, 0x44, 0xaf, 0x88, 0x18, + 0x11, 0x33, 0x43, 0xeb, 0xa5, 0xfd, 0x9e, 0xba, 0x2a, 0x08, 0xa3, 0xd6, 0x6d, 0xb8, 0xd7, 0xf5, 0x55, 0x2f, 0x6a, + 0xb5, 0x5f, 0x6b, 0x65, 0x00, 0xfb, 0x96, 0x7c, 0x80, 0x22, 0x09, 0x5b, 0xda, 0xf1, 0x6f, 0x07, 0x72, 0xd1, 0x3f, + 0x84, 0xb0, 0x89, 0x4d, 0x90, 0x73, 0x78, 0xa9, 0x75, 0xf6, 0x36, 0x10, 0xc2, 0x24, 0xd6, 0x6a, 0x3d, 0x82, 0x17, + 0x4d, 0x00, 0xa9, 0xd0, 0x3e, 0x63, 0xf9, 0x88, 0x54, 0x9c, 0x3f, 0x1f, 0x5a, 0x36, 0xb7, 0x3f, 0xe5, 0x13, 0x2b, + 0x47, 0x9c, 0xad, 0x5f, 0x2c, 0x49, 0x56, 0xf0, 0x5d, 0x22, 0xc1, 0x37, 0x96, 0xa1, 0xfa, 0xb4, 0x0f, 0xa0, 0x49, + 0x21, 0xd0, 0xc1, 0xe5, 0x5d, 0x8d, 0x0c, 0xb5, 0x58, 0x46, 0x75, 0xb4, 0xc7, 0x22, 0xd3, 0x17, 0x2f, 0xca, 0xea, + 0xb3, 0x08, 0x0d, 0x27, 0x16, 0xc3, 0x28, 0x95, 0x5e, 0x6c, 0xd1, 0xc6, 0x9f, 0xf4, 0x3f, 0xe6, 0x06, 0xa5, 0xea, + 0x78, 0x85, 0x5b, 0x35, 0x54, 0x87, 0xae, 0xd0, 0x1b, 0xd9, 0xca, 0xb1, 0x7f, 0x79, 0x67, 0x51, 0xc7, 0x9a, 0x36, + 0x08, 0x5e, 0x07, 0xfd, 0xcd, 0x14, 0x9c, 0xec, 0xfc, 0x9a, 0xe8, 0x14, 0x06, 0x08, 0x0a, 0x66, 0x08, 0xf6, 0x19, + 0xcd, 0xa6, 0xa5, 0x74, 0x67, 0xcd, 0x89, 0x3a, 0x36, 0xce, 0x8c, 0xb2, 0x76, 0x29, 0x9e, 0xda, 0x78, 0xeb, 0x05, + 0x3d, 0xf8, 0x5a, 0xbc, 0x58, 0x71, 0x52, 0x5b, 0x46, 0xc4, 0x0b, 0x8e, 0x87, 0xeb, 0x98, 0x43, 0xb5, 0x71, 0x6b, + 0xc1, 0x84, 0x09, 0xad, 0x86, 0xcd, 0xce, 0x5a, 0x4e, 0xf9, 0x5a, 0x1e, 0x27, 0x95, 0x4b, 0x7f, 0xac, 0x90, 0x00, + 0x08, 0x1d, 0x2d, 0x22, 0x09, 0x7c, 0x56, 0x18, 0xc6, 0x1c, 0x0f, 0x92, 0x25, 0xf3, 0x63, 0x25, 0x8f, 0x00, 0x33, + 0x31, 0x5c, 0xbc, 0x0d, 0xbd, 0x7a, 0x82, 0x2e, 0xd9, 0xc1, 0x46, 0xdd, 0x20, 0x08, 0x12, 0xec, 0x00, 0x7f, 0xe1, + 0x7d, 0x17, 0x26, 0xe7, 0xfc, 0x66, 0xeb, 0xf0, 0xff, 0x04, 0x4f, 0xe6, 0x61, 0x6d, 0xbb, 0x1f, 0x6c, 0xd4, 0x97, + 0xff, 0x3f, 0xd5, 0x35, 0xb4, 0x0e, 0x7c, 0xf8, 0xc0, 0x85, 0xc7, 0xab, 0x55, 0x3d, 0x5a, 0x6d, 0xed, 0x80, 0x21, + 0x99, 0x38, 0x51, 0x56, 0xec, 0xa8, 0xde, 0xa1, 0xee, 0x1f, 0x1c, 0xee, 0x8f, 0x1c, 0xa0, 0xfe, 0xc1, 0xc4, 0xdb, + 0x48, 0x23, 0xdd, 0xfd, 0x22, 0x64, 0x62, 0x3d, 0xea, 0x20, 0x57, 0x29, 0xfd, 0xfc, 0xdc, 0xb3, 0x75, 0x84, 0xa5, + 0xab, 0x74, 0x70, 0x7f, 0xd1, 0x59, 0x7b, 0xb0, 0xc1, 0xe5, 0x8b, 0xec, 0x56, 0xad, 0x7d, 0x52, 0xba, 0xca, 0x1a, + 0x6f, 0x02, 0x10, 0x60, 0xab, 0xcc, 0x64, 0xe5, 0xe9, 0x9e, 0x52, 0xc2, 0xbb, 0xd6, 0xe6, 0xec, 0xaf, 0xd7, 0xc1, + 0x29, 0x63, 0x6d, 0x77, 0x71, 0x6b, 0xbd, 0x00, 0x41, 0x39, 0xf7, 0x1a, 0xca, 0x29, 0x84, 0x78, 0x49, 0x0d, 0x2e, + 0x87, 0xb1, 0xf1, 0x10, 0x39, 0x72, 0x88, 0x6e, 0x23, 0x82, 0x75, 0x95, 0xb6, 0x2a, 0x8e, 0xbd, 0x96, 0x27, 0x66, + 0x0b, 0xe3, 0x26, 0xa6, 0x14, 0x16, 0x15, 0x18, 0x79, 0x1a, 0x76, 0x38, 0xdb, 0x11, 0x7a, 0x34, 0x6b, 0x5b, 0x90, + 0x26, 0xec, 0x97, 0xfa, 0x7d, 0x58, 0x82, 0xb1, 0xf9, 0xaa, 0x85, 0xd0, 0x4b, 0xe0, 0x34, 0x79, 0x6f, 0xc8, 0xaf, + 0x2e, 0xf4, 0x8c, 0x70, 0x59, 0x24, 0xf7, 0x58, 0x08, 0x42, 0x65, 0x6b, 0xbb, 0x4c, 0xba, 0x99, 0x63, 0x88, 0xe7, + 0x19, 0x63, 0x68, 0xe1, 0x05, 0x81, 0x4c, 0x13, 0x94, 0x32, 0xfc, 0x16, 0xe1, 0x71, 0x86, 0xb3, 0x43, 0x6e, 0xa6, + 0xc3, 0x48, 0xb8, 0xc2, 0xed, 0x04, 0x99, 0xa5, 0xf9, 0x44, 0xe9, 0xc7, 0x54, 0x75, 0xd8, 0x67, 0x26, 0x21, 0x6a, + 0x8f, 0x58, 0x8f, 0xa7, 0x34, 0x6c, 0x67, 0xfc, 0x9c, 0xe7, 0x52, 0x6c, 0x20, 0xee, 0xae, 0xdc, 0x25, 0xd7, 0xc4, + 0x29, 0xb1, 0xb4, 0xca, 0x38, 0xa4, 0xd0, 0x8e, 0x85, 0xb6, 0xf1, 0x90, 0x1e, 0x44, 0xda, 0xae, 0x0f, 0x49, 0x95, + 0x4e, 0x1e, 0xf3, 0x23, 0x62, 0xc8, 0x4c, 0xbf, 0xc0, 0xda, 0xfe, 0x72, 0xf3, 0x21, 0x04, 0x2a, 0x12, 0x3b, 0x77, + 0x04, 0x3e, 0x0d, 0xb0, 0x79, 0x29, 0x2d, 0x85, 0x56, 0x85, 0xce, 0x55, 0x5b, 0xbd, 0x34, 0x94, 0x0d, 0x51, 0x04, + 0x92, 0x59, 0x96, 0xf0, 0x51, 0xd6, 0x30, 0xc8, 0xa9, 0xdf, 0x35, 0x20, 0xdb, 0x1e, 0x06, 0xeb, 0x7b, 0xaa, 0x2c, + 0xf5, 0xfd, 0xd9, 0x4f, 0x9f, 0xf0, 0xb1, 0x0e, 0x61, 0x95, 0x01, 0xd7, 0x6c, 0x5e, 0xe3, 0xa1, 0x77, 0x9f, 0xcc, + 0xa0, 0x7e, 0xc2, 0x91, 0xbe, 0xc1, 0xd7, 0xc8, 0xfd, 0xcc, 0xcb, 0xf2, 0xca, 0x7b, 0x49, 0x9e, 0x6d, 0x53, 0xea, + 0x27, 0x2d, 0x56, 0xbc, 0x81, 0x3f, 0x75, 0x7e, 0x68, 0xc5, 0xf7, 0x65, 0x75, 0x67, 0xdb, 0x99, 0x33, 0x2c, 0x33, + 0xd8, 0x83, 0x19, 0xba, 0xeb, 0xa3, 0x56, 0x2a, 0xa4, 0x5e, 0xe9, 0xcb, 0x07, 0xef, 0x53, 0xef, 0x53, 0x26, 0x4d, + 0x74, 0x13, 0x98, 0xa2, 0xd2, 0xd7, 0x21, 0xca, 0x0e, 0x69, 0x62, 0xda, 0xa1, 0x4a, 0x14, 0x1d, 0x5e, 0x98, 0x65, + 0x29, 0xc0, 0xf0, 0x8d, 0xe5, 0x53, 0x86, 0x6b, 0x25, 0xa9, 0x20, 0xd4, 0x1a, 0xc4, 0x67, 0x93, 0xe9, 0x7d, 0x99, + 0x1b, 0x0a, 0x58, 0xb0, 0xf8, 0x3a, 0x86, 0x5d, 0xa4, 0x7f, 0x38, 0x7e, 0x27, 0xc1, 0x39, 0xe1, 0x70, 0x64, 0x03, + 0x01, 0x94, 0x69, 0xbb, 0xe0, 0xe2, 0x7e, 0x83, 0x3d, 0xcc, 0xd2, 0x7f, 0x42, 0x6a, 0xc1, 0x69, 0xa0, 0x97, 0xe8, + 0xff, 0xba, 0x33, 0x7f, 0x2a, 0x5f, 0x2f, 0x2c, 0xe6, 0x44, 0xb8, 0xc5, 0xd9, 0x57, 0x96, 0x59, 0xe5, 0x8a, 0xfb, + 0x03, 0x23, 0x13, 0xad, 0x5d, 0x9f, 0x1f, 0xac, 0x56, 0xd4, 0x2a, 0xd4, 0xd0, 0x57, 0xee, 0x7f, 0xa6, 0x7b, 0xb9, + 0x67, 0xc6, 0x3c, 0x14, 0x73, 0x87, 0x75, 0xd1, 0xd0, 0xf8, 0x0c, 0xd1, 0x10, 0xa5, 0xc6, 0x6a, 0xc0, 0x66, 0x4c, + 0xea, 0xd7, 0x83, 0x08, 0x4b, 0xe9, 0x9c, 0x18, 0x55, 0x6a, 0x91, 0x41, 0x82, 0xc9, 0xf1, 0x5c, 0xda, 0x1c, 0x0a, + 0x44, 0xd0, 0xcc, 0x6b, 0x68, 0xf4, 0x35, 0x1e, 0x56, 0xb8, 0xd1, 0xcd, 0x1e, 0x31, 0x64, 0x04, 0x41, 0x65, 0xd9, + 0x18, 0xd9, 0x2e, 0x46, 0x51, 0x38, 0xf5, 0xb3, 0x43, 0x41, 0xf1, 0xcb, 0x99, 0x2f, 0x4d, 0x76, 0xdc, 0x3d, 0x1a, + 0x80, 0xa2, 0x58, 0x97, 0x78, 0xd9, 0x66, 0x22, 0x37, 0xb9, 0xc1, 0x94, 0x20, 0x88, 0x39, 0xfc, 0x09, 0xb2, 0xa4, + 0x88, 0xe9, 0x22, 0x6e, 0x2e, 0xcd, 0xc5, 0xa8, 0x4c, 0x76, 0xf5, 0xc0, 0x6d, 0x68, 0x54, 0xab, 0x89, 0x5e, 0x6b, + 0xdd, 0x0f, 0x0a, 0xd1, 0x09, 0x8b, 0x27, 0xf2, 0x8a, 0x85, 0x48, 0x82, 0x81, 0x00, 0x45, 0xdb, 0xc2, 0x28, 0x0a, + 0xbd, 0x16, 0xd3, 0xd9, 0x72, 0x7e, 0x2e, 0xd3, 0x50, 0x34, 0x3a, 0xe3, 0x96, 0x81, 0x55, 0x3f, 0x6d, 0x96, 0x1f, + 0x78, 0xfc, 0x4f, 0x62, 0xc2, 0xdb, 0x1e, 0x7a, 0x06, 0xe2, 0x53, 0x0f, 0x28, 0xd3, 0x5d, 0x02, 0x85, 0xe9, 0xb9, + 0x8b, 0x50, 0x22, 0x29, 0xea, 0xc6, 0x9c, 0x58, 0x72, 0x1f, 0x95, 0xf8, 0xbe, 0x1a, 0x1f, 0xc2, 0x11, 0xd5, 0x87, + 0xc4, 0x15, 0x05, 0x2c, 0xf2, 0xac, 0x64, 0xf3, 0x39, 0xcb, 0xb8, 0x0e, 0x8b, 0x35, 0x73, 0xce, 0x1b, 0x5e, 0x96, + 0xfa, 0xa0, 0x64, 0x04, 0xef, 0x07, 0x73, 0x08, 0x55, 0xae, 0xc8, 0x0c, 0xf9, 0x55, 0x89, 0xda, 0x0a, 0x58, 0xe3, + 0x0a, 0xc2, 0x6c, 0xed, 0x15, 0xaf, 0x6f, 0x8b, 0x95, 0xfe, 0x40, 0xae, 0x11, 0xf7, 0x70, 0x08, 0x00, 0x0c, 0xfb, + 0xdd, 0x09, 0x8a, 0x91, 0x0a, 0x17, 0xe6, 0x62, 0x68, 0x40, 0xc2, 0x36, 0x48, 0x99, 0xed, 0xc7, 0xf9, 0xf0, 0xee, + 0x9f, 0xd6, 0x9c, 0x1d, 0xac, 0x95, 0x70, 0xed, 0xe8, 0x2a, 0x13, 0xe4, 0xe5, 0x43, 0x94, 0x9d, 0xb9, 0x6d, 0xae, + 0x96, 0x05, 0x51, 0x69, 0x31, 0x9e, 0xad, 0xc4, 0xfd, 0x32, 0x85, 0xc7, 0xce, 0x22, 0xd8, 0x99, 0x97, 0xe0, 0x12, + 0x10, 0x7d, 0x90, 0xf1, 0x91, 0x0d, 0x12, 0xbd, 0xf2, 0x6c, 0xfc, 0x59, 0x75, 0xef, 0x51, 0x9b, 0x2a, 0x52, 0xbb, + 0x1e, 0xb8, 0x3b, 0x94, 0xa4, 0x82, 0x69, 0x77, 0x03, 0xd6, 0xcc, 0xeb, 0x89, 0xc9, 0x37, 0x0a, 0xe2, 0x06, 0x38, + 0xfb, 0x6e, 0x1c, 0x68, 0x1a, 0x58, 0x6f, 0x3e, 0xa2, 0x68, 0x10, 0x6a, 0x44, 0x9c, 0x9b, 0xf5, 0xfa, 0xa5, 0xdf, + 0x81, 0x00, 0xa4, 0x60, 0x56, 0x12, 0xbc, 0x77, 0xe5, 0xa4, 0x10, 0x84, 0xd8, 0x02, 0x88, 0xe9, 0x06, 0x12, 0xc7, + 0x11, 0xe5, 0x1a, 0xcf, 0xbe, 0x59, 0x7a, 0xf4, 0xa2, 0x23, 0x76, 0x7f, 0x09, 0xac, 0xe9, 0x65, 0x07, 0xdb, 0xb9, + 0x09, 0x49, 0x85, 0x32, 0xf4, 0xaa, 0x9e, 0xdd, 0xb0, 0xb9, 0x75, 0x2c, 0x0b, 0x3d, 0x7a, 0x08, 0x72, 0xc9, 0xbc, + 0xb7, 0xd5, 0x18, 0x08, 0xa5, 0x9b, 0x5f, 0x08, 0x14, 0x47, 0xeb, 0x5f, 0x68, 0x93, 0x0c, 0x6d, 0x9c, 0xdb, 0xb4, + 0xb3, 0x66, 0xb7, 0x29, 0xac, 0x5c, 0x72, 0x73, 0xbd, 0x38, 0xa6, 0xa8, 0xa7, 0xf2, 0xbd, 0xd6, 0xb2, 0x67, 0x63, + 0xa0, 0x86, 0xf6, 0xc8, 0x27, 0x85, 0xd0, 0x1b, 0xb6, 0x62, 0x69, 0x24, 0x93, 0xe6, 0xce, 0x3b, 0x27, 0xd4, 0xe6, + 0x61, 0x87, 0xc4, 0x09, 0x73, 0xeb, 0xbf, 0xcf, 0x23, 0x29, 0x8b, 0xf7, 0x29, 0x14, 0x6e, 0x86, 0xea, 0x86, 0xb1, + 0xe8, 0x38, 0x01, 0xb7, 0x95, 0xf5, 0xd3, 0x8c, 0x44, 0xac, 0x16, 0x16, 0xc6, 0x33, 0x80, 0xa9, 0x98, 0x22, 0x6e, + 0x55, 0x30, 0xd4, 0x20, 0x39, 0x57, 0x83, 0x60, 0xa6, 0xd7, 0x8c, 0x9d, 0x79, 0x99, 0xb7, 0xd0, 0xd6, 0xc6, 0x2c, + 0x2c, 0xd4, 0x6c, 0x4c, 0xcd, 0x93, 0x49, 0x01, 0x4b, 0x23, 0xe8, 0xf6, 0x98, 0x1e, 0xee, 0xae, 0x91, 0xef, 0x96, + 0x23, 0x67, 0x17, 0x83, 0xf9, 0xd8, 0xcb, 0xec, 0x71, 0xea, 0xc1, 0xcb, 0x04, 0x33, 0x42, 0x85, 0xad, 0xe2, 0x02, + 0xda, 0xb3, 0xa6, 0xff, 0xc0, 0x37, 0xf1, 0x31, 0x07, 0x37, 0x66, 0xec, 0xad, 0x59, 0xba, 0xe2, 0x3d, 0x1d, 0x23, + 0x64, 0x11, 0x23, 0xf2, 0x9c, 0x35, 0xc5, 0xdc, 0x4a, 0x15, 0xe3, 0x1e, 0x14, 0x82, 0xe5, 0x2b, 0x4c, 0x05, 0x10, + 0x0e, 0x66, 0x37, 0x1a, 0x1c, 0x62, 0x7d, 0xdc, 0xba, 0x5b, 0x20, 0x04, 0x06, 0x50, 0x5d, 0x9c, 0x73, 0x34, 0xd1, + 0x01, 0x90, 0xfc, 0x3e, 0x12, 0x00, 0x49, 0x60, 0x86, 0x22, 0x01, 0x46, 0xaf, 0x5a, 0xfa, 0x9a, 0x17, 0x6b, 0x8c, + 0x8c, 0xd8, 0x23, 0x08, 0xb6, 0x72, 0x8f, 0x2c, 0x90, 0x66, 0x73, 0xaf, 0x75, 0xc2, 0xb7, 0x67, 0x45, 0x25, 0x0e, + 0x2e, 0xbf, 0x2a, 0x23, 0xe9, 0x9f, 0x0c, 0x6a, 0xac, 0x63, 0xe5, 0x29, 0xfd, 0x98, 0xa9, 0xa3, 0x47, 0x77, 0x69, + 0x9a, 0x4e, 0xe6, 0xa0, 0xd8, 0x43, 0x36, 0x28, 0xab, 0x64, 0xec, 0xc4, 0x39, 0x74, 0x22, 0xa9, 0x7f, 0x1c, 0xbd, + 0xbc, 0x53, 0x8f, 0xa2, 0x34, 0xb7, 0xeb, 0x09, 0xb5, 0x72, 0xaa, 0xdd, 0x08, 0xbc, 0x49, 0x79, 0x26, 0x75, 0xc6, + 0x96, 0xfa, 0xa5, 0x42, 0x2a, 0x3b, 0x35, 0x26, 0xb1, 0x93, 0xf3, 0x32, 0xe7, 0xe8, 0x29, 0xbf, 0x10, 0xc6, 0x81, + 0xb1, 0x3f, 0x9d, 0xb6, 0xde, 0xaf, 0xd9, 0x19, 0xe2, 0xf1, 0x6a, 0xaa, 0xf6, 0x21, 0x5d, 0xab, 0x26, 0xa6, 0x40, + 0xd3, 0x9e, 0xa6, 0xff, 0xc9, 0x80, 0x3e, 0x0f, 0xc1, 0x9e, 0xe9, 0x27, 0x21, 0xd5, 0x0e, 0xa2, 0xfd, 0x41, 0x0b, + 0xaf, 0xf0, 0x35, 0x4a, 0xa8, 0xfe, 0xce, 0x09, 0xd0, 0xf1, 0xbd, 0x6e, 0x10, 0x5b, 0x92, 0xb8, 0x98, 0x8b, 0x54, + 0x76, 0x8e, 0x19, 0xd5, 0x40, 0x2e, 0x88, 0x14, 0xcf, 0x75, 0x1a, 0x95, 0x85, 0x2c, 0x79, 0x83, 0x1b, 0x3f, 0xfb, + 0x35, 0x53, 0x28, 0xfc, 0x6a, 0x38, 0x08, 0x58, 0x06, 0x90, 0x30, 0xef, 0x5e, 0x69, 0xce, 0x99, 0x9d, 0x8d, 0x18, + 0xb2, 0x00, 0x2e, 0x75, 0xec, 0x23, 0x74, 0x12, 0x00, 0x10, 0x1d, 0x13, 0x63, 0x20, 0xaf, 0x76, 0x54, 0xff, 0x03, + 0x1c, 0x7a, 0x27, 0xbd, 0x5a, 0x73, 0x37, 0x81, 0x28, 0x42, 0x40, 0x80, 0xc4, 0xde, 0x50, 0x10, 0x45, 0xcb, 0x41, + 0x24, 0x55, 0x62, 0x27, 0xb4, 0x15, 0x9a, 0x05, 0x37, 0xb2, 0x11, 0x69, 0x04, 0xd0, 0x2b, 0xb8, 0x10, 0x33, 0x02, + 0x65, 0x1e, 0x47, 0x1a, 0xbf, 0xa0, 0xc4, 0xcc, 0x4b, 0xc5, 0xe8, 0x73, 0x8a, 0x7a, 0xef, 0x41, 0x74, 0xcf, 0xcd, + 0xa3, 0xd6, 0xc7, 0x84, 0x10, 0x3d, 0x01, 0x6b, 0x28, 0xab, 0x9f, 0xa2, 0x0c, 0x30, 0x1a, 0xa0, 0x6c, 0xef, 0x70, + 0x1e, 0xb0, 0x7c, 0xa9, 0x79, 0x52, 0x0f, 0x1d, 0xf3, 0x88, 0x5c, 0x3a, 0x9f, 0xf7, 0xeb, 0xb8, 0x5e, 0xd4, 0x0e, + 0x2a, 0x04, 0x3c, 0x56, 0x2f, 0xd5, 0x8d, 0x20, 0x37, 0x14, 0xff, 0x45, 0xc5, 0xd4, 0x18, 0xf6, 0x95, 0x5f, 0x4c, + 0x27, 0x1d, 0x6a, 0x87, 0xf5, 0x2e, 0x72, 0x75, 0x2a, 0x4a, 0x00, 0x4e, 0xbb, 0x1d, 0xda, 0x39, 0xb3, 0xe3, 0x6f, + 0x77, 0xfd, 0x68, 0x95, 0x95, 0x6a, 0x51, 0xe7, 0x59, 0x43, 0x41, 0x79, 0x39, 0x1d, 0xff, 0x0b, 0x4f, 0xf6, 0xf2, + 0x64, 0x30, 0xa7, 0x16, 0x61, 0x9c, 0xba, 0xf3, 0xec, 0xfd, 0xc1, 0xdb, 0x61, 0x4b, 0x88, 0x9d, 0xea, 0xe6, 0xd7, + 0x7a, 0xe4, 0x8b, 0xa9, 0xdb, 0x7a, 0x82, 0x1b, 0x37, 0xb7, 0xce, 0xd8, 0xab, 0xc7, 0xd0, 0x31, 0x01, 0xe0, 0xad, + 0x25, 0x8a, 0xa2, 0x22, 0xfc, 0xfb, 0xe3, 0xe9, 0xa1, 0xe6, 0xf4, 0xa0, 0x6f, 0xe3, 0x9d, 0x18, 0x34, 0x05, 0x26, + 0x58, 0x07, 0x0c, 0xf3, 0x01, 0xfd, 0xae, 0xa4, 0x1a, 0xdf, 0xf7, 0xa2, 0xc8, 0x41, 0x4c, 0x66, 0xf0, 0xa5, 0xf1, + 0x4d, 0x56, 0x64, 0x7c, 0x51, 0x01, 0xda, 0xbc, 0x4c, 0xb6, 0x0b, 0xc7, 0x30, 0x85, 0x69, 0xb7, 0xee, 0x7b, 0xec, + 0xa0, 0x5c, 0xdc, 0x1a, 0xc6, 0x6f, 0x24, 0x82, 0xec, 0x8d, 0x65, 0xe6, 0x03, 0xc5, 0xaf, 0x9f, 0x3a, 0x26, 0xb9, + 0xe7, 0x0d, 0xf7, 0x87, 0xa8, 0xa9, 0xd0, 0xf9, 0x5c, 0x79, 0xb7, 0x9c, 0xdf, 0x85, 0xd7, 0xaa, 0x50, 0x77, 0x64, + 0xc9, 0x48, 0xd3, 0x69, 0xe8, 0xe9, 0x5a, 0x2d, 0xda, 0x9c, 0xb8, 0x0e, 0xda, 0xb6, 0xd8, 0x04, 0x12, 0x4b, 0xce, + 0x60, 0xa6, 0xe4, 0x4d, 0x2c, 0x08, 0x0e, 0x1d, 0x41, 0xa1, 0xbb, 0x28, 0x0e, 0x91, 0x30, 0x60, 0xb3, 0x43, 0x85, + 0xdd, 0x47, 0xb0, 0xf1, 0xd5, 0xbc, 0x50, 0xe4, 0x19, 0xab, 0xc2, 0x9c, 0xa9, 0x66, 0x56, 0xb5, 0x5f, 0x0c, 0x70, + 0xf6, 0x4f, 0xb8, 0x97, 0x4e, 0x0c, 0xd6, 0x83, 0x4c, 0x49, 0x0d, 0x9d, 0x72, 0x8a, 0x6a, 0x1e, 0xb1, 0x8d, 0x35, + 0x14, 0x50, 0x3b, 0x3c, 0x32, 0x1c, 0x6e, 0x7a, 0x6f, 0x7c, 0x3e, 0xf0, 0x2c, 0x36, 0xf0, 0xce, 0x21, 0xb0, 0x10, + 0xfb, 0x51, 0xbb, 0x38, 0xb4, 0x35, 0x9b, 0xa1, 0xb0, 0x8d, 0x86, 0x42, 0x3a, 0xb3, 0x17, 0x24, 0xd3, 0x41, 0x1a, + 0x48, 0x5b, 0x87, 0x89, 0xc6, 0xde, 0x57, 0x07, 0xba, 0x03, 0x8d, 0x37, 0x3d, 0xa2, 0xd0, 0xc6, 0xae, 0x1a, 0xc0, + 0x2b, 0x3a, 0x97, 0xe8, 0x66, 0xdf, 0x12, 0xd8, 0xaf, 0x36, 0x83, 0x1b, 0xcb, 0x97, 0x00, 0xa6, 0x14, 0x90, 0x6d, + 0xd9, 0xf8, 0xdc, 0x73, 0x3e, 0x90, 0x4d, 0x98, 0x1c, 0x8d, 0xa3, 0x76, 0x11, 0x76, 0x69, 0x8d, 0xb7, 0x1c, 0x4d, + 0xf5, 0xcf, 0xa5, 0x08, 0x0b, 0xac, 0x2e, 0x98, 0xb6, 0xc5, 0x47, 0x23, 0xac, 0x49, 0x51, 0xb7, 0x87, 0x05, 0xd4, + 0xd8, 0x61, 0x21, 0x95, 0xd6, 0x6b, 0x89, 0x8b, 0x95, 0x18, 0x5f, 0xd3, 0x53, 0x28, 0x0e, 0x2c, 0x3b, 0x47, 0x40, + 0xe3, 0xc1, 0x3a, 0xdf, 0x0a, 0x5f, 0x2a, 0xdc, 0x2f, 0xe5, 0xa8, 0xe4, 0x99, 0x26, 0xce, 0xf5, 0x02, 0xce, 0x08, + 0x89, 0xcb, 0x0f, 0xd8, 0x38, 0x96, 0x00, 0x5b, 0xa6, 0xf7, 0xff, 0x50, 0x87, 0x05, 0xdb, 0x21, 0xc0, 0x2b, 0xee, + 0xa2, 0x7d, 0xa0, 0x5c, 0x01, 0xa4, 0xc9, 0x51, 0x86, 0x5c, 0x7e, 0xd6, 0xbd, 0x42, 0xc6, 0xb4, 0x4f, 0xa2, 0x63, + 0xcb, 0x76, 0x76, 0x20, 0x99, 0x23, 0x43, 0xc2, 0xb8, 0xf5, 0x2a, 0x65, 0xe1, 0x6e, 0x80, 0x63, 0x44, 0xb1, 0xb4, + 0x62, 0x7e, 0x99, 0x29, 0xf2, 0x0a, 0xd8, 0x8d, 0x93, 0xa6, 0xbd, 0x36, 0xa6, 0x4b, 0x64, 0x63, 0x30, 0x76, 0xaa, + 0x08, 0x2c, 0x8c, 0x41, 0x55, 0xb2, 0x20, 0xfc, 0x63, 0x4f, 0x38, 0xe0, 0x7f, 0x72, 0x26, 0x28, 0x3f, 0x1e, 0xcb, + 0x79, 0x52, 0x61, 0x1e, 0xc8, 0x14, 0xf6, 0x70, 0xfa, 0xd2, 0xbf, 0xa2, 0x4f, 0xa9, 0xc0, 0x9a, 0x24, 0xc2, 0xb8, + 0x01, 0x06, 0x55, 0x1b, 0x00, 0x74, 0x83, 0x14, 0x6f, 0x12, 0xd0, 0xe4, 0x26, 0xb4, 0x0a, 0xe5, 0x28, 0x1d, 0xb0, + 0x52, 0xe4, 0x66, 0xd4, 0x14, 0xc1, 0x46, 0xda, 0x41, 0x8a, 0x12, 0x0c, 0x3b, 0xa9, 0x06, 0x69, 0x95, 0x7a, 0x38, + 0x08, 0x7f, 0x4d, 0x80, 0x0e, 0x40, 0x1e, 0x96, 0xff, 0x65, 0x32, 0xc2, 0xcb, 0x23, 0x2b, 0xb9, 0x47, 0xcd, 0x51, + 0x63, 0x62, 0x1a, 0x3a, 0xb9, 0xa5, 0x13, 0xde, 0xd5, 0x1c, 0x71, 0x36, 0x0e, 0x6a, 0xab, 0x9a, 0x0f, 0x06, 0x43, + 0xa7, 0x4e, 0x3a, 0x82, 0xc2, 0x47, 0x39, 0x06, 0x13, 0xda, 0xcd, 0x14, 0x3d, 0x0f, 0x7b, 0x99, 0x97, 0x93, 0x6e, + 0x36, 0x53, 0x00, 0xb6, 0x5a, 0x0a, 0x5b, 0x86, 0x81, 0x31, 0x8c, 0x3f, 0x02, 0x72, 0xc3, 0xa7, 0xcf, 0x4b, 0x23, + 0x8f, 0x4a, 0x2f, 0x6f, 0x7e, 0xf8, 0xf8, 0x31, 0x80, 0xc1, 0x50, 0xd1, 0xe0, 0xc3, 0x67, 0x7d, 0x35, 0xbe, 0x93, + 0xc9, 0xc6, 0x1a, 0xe3, 0x1c, 0x44, 0x79, 0x16, 0xda, 0x91, 0x9f, 0x95, 0x75, 0x51, 0x0c, 0xdb, 0xd7, 0x17, 0x95, + 0xd7, 0x97, 0x22, 0xa4, 0x6a, 0x41, 0x2d, 0x6f, 0x71, 0x8a, 0x8d, 0x43, 0x28, 0x34, 0xe6, 0xa0, 0x08, 0x19, 0x8e, + 0x22, 0x6e, 0xee, 0x34, 0x14, 0x03, 0x52, 0x22, 0x12, 0xe6, 0xd4, 0x69, 0xed, 0x6d, 0x4e, 0xb0, 0xd9, 0x3b, 0x53, + 0x4b, 0x0d, 0xaf, 0x31, 0x61, 0x65, 0xe7, 0x48, 0x91, 0xc0, 0xa5, 0x2d, 0xbb, 0xb5, 0xc8, 0x54, 0xdd, 0x8d, 0x86, + 0xcc, 0x99, 0x15, 0x14, 0xab, 0x97, 0xcf, 0x0a, 0x87, 0x56, 0x50, 0xfc, 0xa6, 0xc1, 0x06, 0xc4, 0x38, 0x76, 0x7f, + 0x7c, 0xae, 0x82, 0x7f, 0xf8, 0x39, 0xdc, 0x93, 0x3f, 0xa6, 0x17, 0xac, 0x52, 0xcc, 0x06, 0x35, 0xdf, 0x25, 0xca, + 0xf4, 0xda, 0x9c, 0x09, 0x4c, 0x1c, 0xf3, 0x82, 0x1e, 0x3e, 0x4b, 0x5f, 0x14, 0xa3, 0xcd, 0xa0, 0x22, 0x65, 0x52, + 0x01, 0x44, 0x34, 0xe9, 0x0e, 0xa9, 0xd7, 0x58, 0xa4, 0x2c, 0x9b, 0x62, 0x9b, 0xe6, 0x4a, 0x6d, 0x1f, 0x3b, 0x6a, + 0x6a, 0xdd, 0x90, 0x48, 0x3c, 0xa4, 0xf9, 0x0f, 0xc5, 0xd7, 0x31, 0x16, 0x84, 0x48, 0x21, 0xad, 0x2f, 0xce, 0x74, + 0x7a, 0x7c, 0x36, 0x8a, 0x3b, 0x1a, 0xc7, 0xa3, 0xfc, 0x6b, 0x8d, 0xe9, 0x54, 0xb0, 0x1f, 0xd2, 0x19, 0x12, 0x47, + 0x9e, 0x1b, 0x17, 0xdd, 0xad, 0xcf, 0x3a, 0x7c, 0x10, 0xb5, 0xbc, 0xe4, 0x1d, 0xbb, 0x21, 0x54, 0x32, 0x98, 0xeb, + 0x94, 0x40, 0x6b, 0xea, 0x0f, 0xfc, 0x0d, 0x5f, 0xb8, 0x51, 0x5d, 0x3a, 0x24, 0x5a, 0xd8, 0x90, 0x60, 0x3a, 0x49, + 0x8a, 0xb4, 0xe0, 0x12, 0x26, 0x9b, 0xa0, 0x58, 0xbb, 0xb0, 0xe0, 0xb3, 0xb0, 0x38, 0x64, 0xf3, 0x8b, 0x2e, 0xc4, + 0x78, 0x07, 0xd6, 0x19, 0xaa, 0x3c, 0x73, 0x8e, 0x41, 0x33, 0x78, 0x61, 0x61, 0xaf, 0x0a, 0x72, 0x88, 0x0b, 0xeb, + 0x80, 0xca, 0xc7, 0xa8, 0x91, 0xf1, 0xe8, 0xad, 0x4d, 0x21, 0x3d, 0xd0, 0x7d, 0xff, 0xce, 0x6f, 0xaf, 0x22, 0x67, + 0x60, 0x88, 0x0b, 0x91, 0x17, 0x1e, 0xcd, 0x6c, 0x70, 0x81, 0x71, 0xe1, 0x6d, 0x8e, 0x7a, 0xf1, 0x1c, 0xce, 0xdb, + 0x37, 0x54, 0x6a, 0x78, 0xc5, 0x94, 0x8e, 0x13, 0x14, 0xdc, 0xa4, 0x97, 0x15, 0xc8, 0xbb, 0x93, 0xb4, 0xd8, 0x35, + 0xbb, 0x14, 0xb2, 0x21, 0x45, 0x67, 0xed, 0x6e, 0x70, 0xca, 0xdc, 0x9e, 0x49, 0x87, 0x65, 0x4e, 0xd1, 0xcc, 0x24, + 0x0a, 0x3d, 0x87, 0x28, 0xc6, 0x8c, 0xa1, 0x49, 0xb5, 0x65, 0x5e, 0xd4, 0x92, 0x0d, 0x95, 0xba, 0x46, 0x50, 0xd6, + 0xcd, 0x91, 0xfd, 0x73, 0xe6, 0xe3, 0xdc, 0xb9, 0xc1, 0xd0, 0x03, 0x79, 0x18, 0x90, 0xb1, 0x3a, 0xc7, 0xfd, 0x85, + 0x8f, 0x69, 0xde, 0xed, 0x5e, 0x73, 0xfc, 0x6b, 0x04, 0x6d, 0x99, 0x7c, 0xd3, 0xfa, 0x07, 0xd5, 0xff, 0x65, 0x03, + 0x46, 0xd6, 0x3a, 0x3e, 0x2c, 0x36, 0xad, 0x37, 0x55, 0x4d, 0x76, 0xd0, 0xd8, 0x99, 0x26, 0x6d, 0x2c, 0x1c, 0xd4, + 0xdd, 0xdb, 0xc8, 0x24, 0x38, 0x6c, 0xde, 0x1c, 0xc2, 0x40, 0x56, 0xc6, 0x77, 0x1b, 0xa1, 0x75, 0xeb, 0xb4, 0xa9, + 0xc3, 0x2f, 0x43, 0x13, 0x0f, 0x7b, 0x8d, 0x56, 0x0c, 0x61, 0x9e, 0x4d, 0x19, 0xbb, 0x02, 0xde, 0x14, 0x41, 0x11, + 0x4f, 0xe3, 0x9a, 0x23, 0x98, 0xd2, 0x6a, 0x60, 0xc8, 0xaa, 0x11, 0xcf, 0x51, 0xa5, 0x6b, 0xd4, 0x73, 0xfb, 0xa6, + 0x07, 0x0c, 0xb9, 0x90, 0xb3, 0x5f, 0x4e, 0x6b, 0x42, 0x67, 0xeb, 0x76, 0xf4, 0x18, 0xf0, 0x0a, 0x91, 0xe8, 0xf3, + 0x41, 0x96, 0x01, 0xb1, 0xc5, 0x64, 0xa5, 0x43, 0x21, 0xc1, 0xe3, 0x76, 0xf8, 0x8c, 0xd5, 0xa7, 0xbc, 0xa7, 0x4f, + 0x59, 0xec, 0x86, 0xa6, 0xd6, 0xc1, 0xdf, 0xa9, 0x12, 0x22, 0x05, 0xae, 0xa5, 0xba, 0xcb, 0x90, 0x55, 0xa5, 0x1e, + 0xfd, 0x41, 0x91, 0x96, 0x46, 0xac, 0xc4, 0x52, 0xa9, 0x1a, 0xd3, 0xfa, 0xef, 0xb4, 0x15, 0x9d, 0xa8, 0xff, 0xb4, + 0xb0, 0x5a, 0x7d, 0x45, 0xac, 0xab, 0x84, 0xe3, 0x45, 0xaf, 0xb6, 0xe8, 0xc8, 0x10, 0x41, 0x02, 0x9f, 0x75, 0xad, + 0x37, 0x1b, 0x3a, 0x0d, 0x68, 0xbc, 0xcd, 0xe3, 0xbf, 0xea, 0xf9, 0x8c, 0xec, 0x05, 0x9a, 0xae, 0x52, 0x9b, 0x02, + 0x5d, 0x41, 0xe0, 0x9c, 0x25, 0xd6, 0x5c, 0xa5, 0x81, 0x09, 0xa6, 0x79, 0xb1, 0xe5, 0x0b, 0xa8, 0x4e, 0xb7, 0x40, + 0x1a, 0x08, 0xd2, 0x50, 0x7a, 0xa9, 0x55, 0xea, 0x36, 0xa6, 0xd3, 0x41, 0x79, 0xd6, 0x06, 0xa5, 0xf8, 0x01, 0xe5, + 0xc0, 0x95, 0x5b, 0xbd, 0x44, 0x09, 0xb2, 0xea, 0xd0, 0xbc, 0x95, 0xbd, 0x66, 0x1e, 0x52, 0xb8, 0x61, 0x4d, 0xc6, + 0x05, 0x6f, 0xfb, 0xdb, 0xdd, 0x40, 0xe6, 0x28, 0x5a, 0x47, 0x4d, 0xc9, 0x42, 0xf7, 0x88, 0xab, 0x08, 0xe9, 0xe7, + 0x85, 0xd2, 0x2d, 0xb0, 0xd3, 0xed, 0xef, 0xd0, 0xba, 0x5b, 0xd4, 0xc5, 0xf2, 0xd0, 0xc3, 0xce, 0x91, 0x7f, 0x04, + 0xef, 0x8f, 0x02, 0x16, 0xc3, 0x4f, 0x13, 0x65, 0x07, 0x6d, 0xf6, 0xfa, 0x7e, 0xb0, 0x4d, 0xbf, 0xa9, 0xb1, 0x1b, + 0xbc, 0x1d, 0xf0, 0x57, 0x1d, 0xac, 0xc2, 0x61, 0x0f, 0xcc, 0x27, 0x16, 0xbf, 0x3f, 0xbf, 0xd8, 0xd7, 0xe0, 0xf8, + 0x44, 0xb8, 0xcd, 0x54, 0x3e, 0xc0, 0xdb, 0x24, 0xb7, 0x74, 0xbd, 0x30, 0xf2, 0xea, 0x02, 0x52, 0x56, 0xce, 0x89, + 0xeb, 0x8b, 0x02, 0x57, 0xa0, 0x85, 0x12, 0x8f, 0x6e, 0x0b, 0xde, 0xb3, 0x86, 0xb4, 0x77, 0x1b, 0x63, 0xd3, 0x69, + 0xef, 0x38, 0x15, 0x87, 0x99, 0x2c, 0xcd, 0x26, 0xe4, 0xdf, 0xae, 0xa8, 0x53, 0x35, 0x70, 0x9f, 0x5f, 0xd7, 0x57, + 0xb3, 0x74, 0x37, 0xee, 0xe7, 0x4f, 0xd9, 0x9e, 0xb0, 0x95, 0x0d, 0x63, 0x76, 0xc8, 0xef, 0x0b, 0x0d, 0xe8, 0x7a, + 0x34, 0x8b, 0x90, 0xfd, 0x40, 0x80, 0xc1, 0x57, 0xe7, 0x8c, 0xa5, 0x59, 0xd9, 0x37, 0xfd, 0xc2, 0x43, 0x49, 0x41, + 0x8c, 0xca, 0x5e, 0x03, 0x64, 0xb4, 0x24, 0x5b, 0xa7, 0xc5, 0x7b, 0x61, 0x01, 0xa3, 0xef, 0x53, 0xe8, 0x54, 0x9f, + 0x64, 0x08, 0xab, 0x2e, 0xd1, 0x78, 0x4e, 0x7b, 0xc4, 0xd7, 0x79, 0x3e, 0x7c, 0x1d, 0x8b, 0x3d, 0x57, 0x58, 0x66, + 0xd8, 0x4c, 0x8c, 0x43, 0x03, 0xf1, 0xc4, 0xa1, 0xfb, 0x91, 0xd1, 0x62, 0xdc, 0x5a, 0x50, 0xc3, 0xe3, 0x2f, 0xe7, + 0x89, 0xa5, 0xeb, 0xdb, 0x80, 0x0c, 0x53, 0x44, 0x9c, 0x59, 0xd4, 0xeb, 0x8b, 0x6a, 0xd8, 0xbd, 0x2e, 0x2a, 0x08, + 0x9a, 0xcd, 0xb7, 0xf5, 0xe0, 0x06, 0xdb, 0x45, 0xed, 0x87, 0x2c, 0xd1, 0xda, 0xba, 0xdf, 0xb4, 0x1b, 0x64, 0x9f, + 0x33, 0x0e, 0xda, 0x40, 0xc0, 0xf8, 0xde, 0xbf, 0xb4, 0xd5, 0xd9, 0xde, 0x3a, 0xcd, 0x5f, 0x88, 0x8b, 0xbf, 0x93, + 0xb0, 0xbc, 0x9b, 0xe1, 0xa0, 0x94, 0x90, 0xe1, 0x04, 0x11, 0xa6, 0xc2, 0xba, 0xb8, 0xe4, 0xb3, 0x0b, 0x13, 0x2b, + 0x23, 0xac, 0x88, 0x76, 0xc4, 0x37, 0x7c, 0x9f, 0xb7, 0x05, 0x04, 0xb1, 0xb3, 0x65, 0xcc, 0x78, 0x46, 0x44, 0x89, + 0x8c, 0xec, 0x30, 0xb1, 0x69, 0x36, 0x61, 0xea, 0xd8, 0x6d, 0x32, 0x68, 0xea, 0x60, 0x9c, 0xc2, 0x06, 0xba, 0x1b, + 0xaa, 0xad, 0xb6, 0x92, 0x8c, 0xf9, 0x85, 0xac, 0x9d, 0xed, 0x8f, 0xea, 0x65, 0x5e, 0x6c, 0x3f, 0xdb, 0x86, 0xe6, + 0x55, 0x31, 0x86, 0x76, 0x20, 0xb3, 0x23, 0xdc, 0x65, 0xea, 0x1e, 0xd2, 0x78, 0xa2, 0x50, 0x6d, 0x25, 0x08, 0x07, + 0xa0, 0x90, 0xa6, 0x39, 0xe3, 0x02, 0xb3, 0xe8, 0xa3, 0x2a, 0xbc, 0xd3, 0x41, 0x59, 0x2d, 0x0d, 0xa0, 0x04, 0x88, + 0xe3, 0x4e, 0x3a, 0x8c, 0xe4, 0xc1, 0x5e, 0xa9, 0x3b, 0xb5, 0x6a, 0x9d, 0xb9, 0x58, 0xec, 0x47, 0x97, 0x5a, 0xec, + 0x11, 0xa6, 0x59, 0x52, 0xeb, 0x07, 0x5a, 0x68, 0xcf, 0x37, 0x5b, 0x13, 0xf3, 0x94, 0x71, 0x48, 0x7b, 0x68, 0x3f, + 0x14, 0xd4, 0x7a, 0x09, 0x8f, 0x95, 0x41, 0x89, 0x64, 0xa7, 0xa6, 0x9d, 0x95, 0x69, 0x0a, 0xde, 0x65, 0x99, 0x78, + 0x15, 0xfa, 0x1d, 0xe1, 0xdd, 0x96, 0x59, 0xdb, 0xc8, 0xc4, 0xcd, 0x49, 0xa4, 0x58, 0x0e, 0xce, 0x35, 0xbc, 0x2d, + 0x3a, 0x76, 0xf1, 0xdb, 0x4c, 0xad, 0x5f, 0xb0, 0x8c, 0x38, 0x5a, 0xc2, 0xcd, 0x0f, 0xe9, 0x91, 0x88, 0x02, 0xa3, + 0xfe, 0x4d, 0x5e, 0xc5, 0x89, 0x1b, 0x66, 0xfc, 0x8e, 0x86, 0x38, 0x54, 0x87, 0xba, 0x67, 0x89, 0x15, 0x88, 0x85, + 0xf3, 0xf7, 0xd5, 0x4d, 0x20, 0x97, 0xde, 0x56, 0xab, 0xe6, 0x61, 0xd4, 0x65, 0xdf, 0x83, 0x3f, 0x85, 0x31, 0x35, + 0x9f, 0xbc, 0x2a, 0xdf, 0x70, 0xcf, 0x64, 0x29, 0x97, 0xf0, 0xba, 0xde, 0x52, 0x73, 0x9c, 0xcb, 0x37, 0x5c, 0x56, + 0x59, 0x6a, 0x33, 0x82, 0x49, 0xdf, 0x5a, 0xe1, 0x38, 0x82, 0x35, 0x14, 0x91, 0xb8, 0x39, 0xa8, 0x83, 0xcd, 0xb1, + 0x0e, 0xe5, 0x36, 0x13, 0xac, 0x43, 0x36, 0xd8, 0x03, 0xc2, 0xa9, 0xc5, 0x66, 0x8e, 0x7d, 0x6c, 0x08, 0x07, 0x74, + 0xdc, 0x9a, 0x22, 0x4a, 0x4e, 0xdd, 0x89, 0xa7, 0x96, 0xe5, 0xbb, 0x19, 0xd3, 0x74, 0x7c, 0x87, 0x18, 0x59, 0x12, + 0x8b, 0xdc, 0xcb, 0x10, 0x97, 0x43, 0x8b, 0xf6, 0x2c, 0x55, 0x21, 0x37, 0xe8, 0xd6, 0x2d, 0x37, 0x1c, 0x3e, 0x7d, + 0x38, 0x2e, 0x7a, 0x22, 0xda, 0x4a, 0x7c, 0x39, 0x85, 0x54, 0x4a, 0xf6, 0x93, 0x0a, 0x2f, 0x54, 0x48, 0xa7, 0xcf, + 0x8a, 0x04, 0xdc, 0xdc, 0x99, 0x0b, 0x57, 0x53, 0xae, 0x65, 0x8d, 0x76, 0x93, 0x9c, 0x08, 0x15, 0x96, 0xcc, 0x18, + 0xbd, 0x78, 0x3f, 0x8b, 0x16, 0xdb, 0x39, 0xc5, 0x76, 0xd8, 0xd4, 0xd4, 0x79, 0x87, 0x22, 0xa7, 0xa1, 0xb2, 0x8c, + 0xc4, 0x2c, 0xca, 0x21, 0x3e, 0x3a, 0x75, 0xbe, 0xc7, 0x28, 0x75, 0x05, 0x73, 0xaa, 0x4d, 0xc9, 0x83, 0xd3, 0xc5, + 0xf9, 0x17, 0x6e, 0x37, 0xfd, 0xe3, 0x28, 0xe8, 0xb7, 0x5a, 0x35, 0x51, 0xad, 0x1c, 0x9a, 0x5d, 0xd7, 0x6e, 0x34, + 0x26, 0xc7, 0x0e, 0x70, 0x67, 0x13, 0xc4, 0x18, 0x3e, 0x2e, 0xc3, 0x2c, 0x9a, 0xe7, 0x53, 0x7d, 0xfd, 0xf3, 0x20, + 0xca, 0xb6, 0x4c, 0xdd, 0x0a, 0xa3, 0xc0, 0xa5, 0x81, 0x07, 0xe3, 0xa8, 0x21, 0x86, 0xcd, 0xa3, 0xa3, 0x6d, 0x22, + 0x93, 0x74, 0xcf, 0x6a, 0xae, 0x00, 0x4d, 0xa7, 0x20, 0xf2, 0xef, 0x71, 0x9b, 0x2f, 0x38, 0x8e, 0x4e, 0xe9, 0xf9, + 0x17, 0xa5, 0x1f, 0x69, 0xf0, 0xc6, 0x78, 0x75, 0xc1, 0xaa, 0x27, 0x23, 0xef, 0x88, 0x87, 0x39, 0x0a, 0xe4, 0x07, + 0xf0, 0x4d, 0xe9, 0x82, 0x73, 0x63, 0xf7, 0x3d, 0xc8, 0x96, 0xed, 0x68, 0x55, 0xc4, 0x1a, 0xf9, 0x1a, 0x27, 0x2e, + 0xb5, 0xfe, 0x92, 0xcc, 0x3a, 0x09, 0xf6, 0x35, 0xf2, 0x78, 0x47, 0xbc, 0xcf, 0xf6, 0x76, 0x68, 0xe3, 0x35, 0x92, + 0xb0, 0xef, 0xb6, 0xeb, 0xaa, 0x2b, 0x4e, 0x7f, 0x62, 0x01, 0xe1, 0x02, 0x36, 0x16, 0xe8, 0x9b, 0xdb, 0x86, 0xd2, + 0xb9, 0xee, 0x1a, 0x7c, 0xaf, 0xf1, 0xce, 0x3b, 0x3b, 0xb8, 0x8a, 0x93, 0x44, 0x60, 0x76, 0xa1, 0x34, 0x26, 0xea, + 0x17, 0x86, 0xe7, 0x6a, 0xcf, 0xb7, 0xea, 0x65, 0x54, 0xb3, 0x67, 0x02, 0xfe, 0x3a, 0x1a, 0x1f, 0x95, 0x79, 0x83, + 0x85, 0xdb, 0x3a, 0x85, 0xee, 0xfc, 0x7d, 0x00, 0xaf, 0xbc, 0x6b, 0xb6, 0x2c, 0xe6, 0x3b, 0xce, 0x82, 0xa5, 0xcd, + 0xdb, 0x5d, 0x99, 0xe0, 0x97, 0x1f, 0x70, 0xaf, 0xf8, 0xd2, 0xc1, 0x93, 0x7e, 0xdd, 0x52, 0xc0, 0x5d, 0xc0, 0xe4, + 0xa5, 0x1b, 0x6e, 0x42, 0xdc, 0xac, 0x72, 0xd3, 0xb7, 0x48, 0xf9, 0xe9, 0xe9, 0xac, 0x79, 0xea, 0x10, 0xde, 0x78, + 0x54, 0x87, 0xca, 0x68, 0x6e, 0xdd, 0xc2, 0x95, 0xfe, 0x05, 0xb7, 0x35, 0x77, 0x30, 0xc3, 0x89, 0x2c, 0x89, 0xc7, + 0x93, 0xee, 0x1e, 0xa0, 0xcc, 0x03, 0x2f, 0x22, 0x29, 0xa2, 0x6d, 0x60, 0x07, 0x2d, 0x28, 0x6b, 0x0d, 0xa2, 0xd6, + 0xde, 0x23, 0x66, 0x7b, 0x69, 0xf7, 0x43, 0xf7, 0xe1, 0x03, 0x0f, 0xd6, 0x44, 0xc8, 0x19, 0x4c, 0x28, 0x7e, 0x97, + 0xf6, 0x73, 0xd8, 0x33, 0xc2, 0x95, 0x56, 0x28, 0x78, 0x8e, 0x1b, 0x54, 0x7d, 0x9f, 0x2d, 0x20, 0x5a, 0x24, 0x20, + 0x67, 0xbb, 0x16, 0xd6, 0xa8, 0x18, 0xf9, 0x49, 0x0c, 0x95, 0xd4, 0xb6, 0x7c, 0x83, 0xa5, 0xbf, 0xae, 0x02, 0x49, + 0x20, 0x31, 0x27, 0xf5, 0xbc, 0xb6, 0x2d, 0x16, 0x37, 0x4b, 0x36, 0x0f, 0x15, 0xa5, 0xe7, 0xe5, 0xd8, 0x79, 0x07, + 0xf5, 0x28, 0xb8, 0x2c, 0xdb, 0xeb, 0xdc, 0x2e, 0xed, 0xae, 0x75, 0x18, 0x4e, 0x52, 0x4e, 0x31, 0xe0, 0xa1, 0x6d, + 0x3d, 0x72, 0xb1, 0xf8, 0xf7, 0x40, 0x1a, 0xde, 0x5d, 0x7e, 0x78, 0x73, 0x4b, 0x6b, 0x4c, 0xd4, 0x66, 0x2a, 0x12, + 0xe1, 0xe4, 0x86, 0x15, 0xc9, 0x90, 0x26, 0x12, 0x3d, 0x7c, 0x91, 0x6f, 0xae, 0x35, 0xac, 0x12, 0xd9, 0x90, 0x61, + 0xb3, 0xd9, 0xcd, 0x64, 0xdc, 0xca, 0x76, 0x7f, 0x3a, 0xf4, 0x26, 0xc8, 0xd6, 0x89, 0xd2, 0x3c, 0x77, 0xd8, 0x62, + 0xed, 0x9e, 0xb1, 0xa8, 0x9f, 0x1c, 0x65, 0x8e, 0x78, 0x43, 0x4c, 0xb4, 0x4d, 0xb9, 0xb6, 0x66, 0x1e, 0x21, 0x70, + 0x6f, 0xed, 0x3f, 0x2b, 0xf6, 0xf1, 0x1a, 0xd3, 0xc7, 0xf4, 0x0b, 0xee, 0xf9, 0xc4, 0xc3, 0xcf, 0x34, 0xc9, 0x0d, + 0xb1, 0xdd, 0x45, 0x3c, 0xe4, 0xa3, 0xbb, 0x61, 0xca, 0x84, 0x65, 0xda, 0x5c, 0xb5, 0x9c, 0x1b, 0x83, 0x54, 0xa1, + 0x48, 0xe5, 0x3e, 0xa2, 0xeb, 0xb0, 0x1f, 0xce, 0xf2, 0x3d, 0x48, 0x64, 0xbe, 0x4f, 0x22, 0x10, 0xeb, 0x1f, 0x05, + 0x71, 0x8e, 0x25, 0x2f, 0x8d, 0x22, 0x8d, 0xfe, 0x84, 0x52, 0x96, 0x72, 0x08, 0xf8, 0xe6, 0x80, 0x73, 0x15, 0x5b, + 0xff, 0x7d, 0xf6, 0x7d, 0x98, 0x76, 0x7d, 0xce, 0xee, 0x16, 0x12, 0xde, 0x72, 0xe2, 0x4e, 0xe5, 0xf1, 0xa9, 0x90, + 0x7b, 0x0f, 0x72, 0x2d, 0xbf, 0xed, 0x86, 0x86, 0xce, 0xf1, 0xb2, 0x45, 0x71, 0x55, 0xa7, 0xf2, 0x47, 0x51, 0xab, + 0xaa, 0xa4, 0x2a, 0x7b, 0x1e, 0x39, 0x93, 0x93, 0xb3, 0xdc, 0xab, 0x0a, 0x43, 0x03, 0x8f, 0x38, 0x5b, 0x62, 0x9d, + 0xbd, 0xc7, 0xcc, 0xe2, 0x84, 0x8f, 0x42, 0x03, 0xc1, 0x2a, 0xe9, 0x13, 0x8e, 0xe8, 0x0b, 0xb4, 0xd3, 0xfa, 0xd2, + 0xcd, 0xed, 0x47, 0x96, 0xb2, 0x83, 0xa3, 0xf1, 0xca, 0x8a, 0x7c, 0x9d, 0x02, 0x31, 0x53, 0xac, 0x62, 0xe4, 0xf3, + 0x1b, 0x84, 0x44, 0xf3, 0x8b, 0xe9, 0x82, 0xf6, 0x2e, 0x6b, 0x51, 0x1d, 0x3e, 0x6b, 0xf6, 0xca, 0x0b, 0x40, 0x1e, + 0x57, 0x15, 0x87, 0x48, 0x7b, 0x83, 0x38, 0x4d, 0x88, 0x7a, 0x76, 0xdb, 0xb3, 0x85, 0x38, 0x31, 0xcb, 0xd1, 0x62, + 0xd2, 0xab, 0x12, 0xd9, 0x6f, 0x4f, 0x4f, 0x20, 0x25, 0x3a, 0x63, 0x2c, 0x19, 0x69, 0x4b, 0xf9, 0x86, 0xe6, 0xf4, + 0x1e, 0xd6, 0x31, 0x11, 0xb1, 0x5a, 0x00, 0x52, 0x0d, 0x29, 0xf4, 0x35, 0x6a, 0x47, 0x44, 0xf8, 0xf9, 0xc8, 0x52, + 0x29, 0x32, 0xc6, 0x37, 0xf6, 0x23, 0x6d, 0x31, 0xab, 0x88, 0x53, 0xc4, 0xac, 0x61, 0x18, 0xd9, 0xb8, 0xc4, 0x28, + 0xa8, 0x56, 0x8f, 0x37, 0xf8, 0x04, 0x83, 0x94, 0x62, 0xab, 0xeb, 0x71, 0xdc, 0xc4, 0x4f, 0x47, 0x22, 0xc2, 0x7d, + 0x82, 0x38, 0x29, 0x81, 0x8d, 0xe7, 0x6f, 0xce, 0x54, 0xe7, 0x7c, 0x69, 0xb0, 0xe7, 0x48, 0xf5, 0x38, 0xc3, 0x40, + 0x13, 0x7c, 0xf5, 0xa3, 0xd9, 0x1f, 0xcb, 0x37, 0x32, 0x8b, 0x3b, 0x09, 0xa9, 0x95, 0xd3, 0xad, 0x36, 0x5b, 0x22, + 0x7e, 0x80, 0x0b, 0x67, 0xbc, 0x47, 0x35, 0x77, 0xf9, 0xa5, 0x26, 0x06, 0x56, 0x98, 0x13, 0x72, 0x37, 0x47, 0x92, + 0xbf, 0x00, 0xe3, 0x66, 0x0d, 0x6d, 0x2e, 0xc7, 0x2e, 0x38, 0x09, 0xe4, 0xea, 0xa6, 0xf4, 0x9b, 0xcf, 0x9e, 0x81, + 0xe9, 0x61, 0xf9, 0xd1, 0xef, 0x32, 0xff, 0x65, 0xac, 0x53, 0x13, 0xfc, 0xc8, 0x51, 0x59, 0x9f, 0xcb, 0xe3, 0xdf, + 0x01, 0xb7, 0x67, 0x7d, 0xe3, 0xcf, 0x93, 0x20, 0xce, 0x35, 0x7f, 0x66, 0xc1, 0x44, 0x36, 0xbb, 0xd6, 0xde, 0xcf, + 0x9f, 0xc1, 0x9b, 0xfb, 0x3d, 0x42, 0xe5, 0x6b, 0xe7, 0x14, 0xea, 0xa6, 0x01, 0x16, 0x7a, 0xf5, 0x60, 0x1f, 0x90, + 0x9b, 0x7d, 0x88, 0x0a, 0x14, 0x39, 0xa2, 0xd2, 0x35, 0xe3, 0x1a, 0xb6, 0x55, 0x3b, 0x94, 0x3d, 0xc3, 0x79, 0x4f, + 0x9b, 0x5d, 0xb5, 0xad, 0x57, 0x69, 0x13, 0x52, 0x98, 0xc2, 0x1a, 0xe8, 0x56, 0x37, 0xec, 0xdc, 0x1c, 0x2c, 0xdf, + 0x5a, 0x06, 0x1e, 0x16, 0xae, 0x98, 0xbd, 0x98, 0xf9, 0x8e, 0x0e, 0xfc, 0x59, 0xca, 0x2b, 0x0a, 0xb5, 0xfa, 0x8d, + 0xe3, 0xa8, 0x87, 0x36, 0xe0, 0x0d, 0x7f, 0x9d, 0x50, 0x9d, 0x3d, 0x67, 0x0b, 0x23, 0x17, 0xe2, 0xd7, 0xba, 0xc1, + 0x27, 0x74, 0xa9, 0x0a, 0x26, 0xe0, 0x4b, 0x9b, 0x1d, 0x0f, 0x5e, 0x87, 0x96, 0xa4, 0xf2, 0xb8, 0x79, 0x8c, 0xe5, + 0xdc, 0x4e, 0xb9, 0x54, 0x2b, 0xf3, 0xa3, 0x1b, 0x25, 0xd8, 0x20, 0x90, 0x24, 0x58, 0x84, 0xf0, 0x4f, 0x30, 0x67, + 0x1c, 0x89, 0x21, 0x7b, 0xa3, 0x62, 0x8a, 0x16, 0x14, 0x0c, 0x91, 0x52, 0xb6, 0x58, 0x60, 0xb3, 0xf7, 0x08, 0x7f, + 0x7f, 0xdf, 0x3a, 0xf5, 0xb4, 0xef, 0x9d, 0x02, 0xed, 0xdb, 0x27, 0xa5, 0xb4, 0xef, 0x9f, 0x14, 0x9d, 0xa5, 0x56, + 0x19, 0xfb, 0x6a, 0xc9, 0xbe, 0x1a, 0xd9, 0x63, 0x3b, 0xdb, 0x43, 0x2b, 0x8e, 0x6b, 0xd0, 0x8e, 0xc5, 0x82, 0x6f, + 0xc9, 0x01, 0xc7, 0x11, 0xcb, 0x92, 0xf5, 0x63, 0xa1, 0xb9, 0x77, 0xb5, 0x1e, 0xf9, 0xf6, 0x00, 0x15, 0x85, 0xb7, + 0xc3, 0xda, 0x8d, 0xac, 0x2c, 0xcf, 0x34, 0xb7, 0x4e, 0xe2, 0xd4, 0xd9, 0xde, 0x42, 0xf1, 0x74, 0xea, 0x08, 0x7e, + 0xd6, 0xe4, 0x70, 0x86, 0x4a, 0x13, 0xf8, 0x8f, 0x1c, 0x3f, 0x36, 0x5a, 0x5b, 0xd1, 0x78, 0xf3, 0xbd, 0x27, 0x1a, + 0x9a, 0xbf, 0xb8, 0x8a, 0x58, 0x98, 0x96, 0x93, 0x7b, 0x07, 0x53, 0x1f, 0x4a, 0xd6, 0xe2, 0x76, 0x07, 0x64, 0xb6, + 0x94, 0x97, 0x39, 0x41, 0x08, 0xa7, 0xba, 0x85, 0xff, 0x2c, 0xa0, 0x31, 0x27, 0x2d, 0x17, 0x53, 0xf9, 0xbc, 0xd5, + 0x86, 0xda, 0xce, 0x59, 0x83, 0x78, 0xec, 0xca, 0x74, 0x57, 0x82, 0x29, 0x3c, 0x9f, 0xc5, 0x15, 0x90, 0xfa, 0x85, + 0x35, 0xff, 0x46, 0xd9, 0xc3, 0xe5, 0x4e, 0x4c, 0x83, 0xff, 0xf7, 0x64, 0x3b, 0x08, 0x27, 0x74, 0x35, 0x4e, 0xb9, + 0x24, 0xe2, 0x7e, 0x6e, 0xa5, 0xed, 0x99, 0x37, 0x72, 0x7d, 0xfb, 0x8c, 0x61, 0x7a, 0xae, 0x42, 0x20, 0x53, 0x68, + 0x3f, 0xdd, 0x3f, 0x8f, 0x71, 0x48, 0xb0, 0x62, 0xcf, 0x09, 0x56, 0x19, 0x98, 0x92, 0x77, 0x33, 0x99, 0x9e, 0xbf, + 0xfc, 0x5f, 0xe6, 0xf7, 0x92, 0xf5, 0xa0, 0x37, 0x7b, 0xcb, 0x36, 0xb7, 0x85, 0x75, 0x69, 0x31, 0xb3, 0x7e, 0x34, + 0xd3, 0xfa, 0x5f, 0x71, 0x80, 0xb7, 0xdb, 0xe9, 0x8a, 0x3f, 0xaa, 0x0c, 0xd2, 0x38, 0x64, 0xdd, 0x6f, 0x4b, 0xd6, + 0x03, 0xde, 0xed, 0xed, 0xf3, 0x5b, 0x1c, 0xfe, 0xb1, 0x09, 0x7c, 0x4b, 0x17, 0x00, 0x02, 0xf8, 0x91, 0xbb, 0x1c, + 0xbb, 0x9c, 0xc9, 0x9d, 0xeb, 0x0a, 0x0b, 0xaa, 0x96, 0x43, 0x16, 0x2e, 0x96, 0x6c, 0x41, 0x3e, 0x5e, 0x13, 0xd9, + 0xe8, 0xc0, 0xec, 0x12, 0xb1, 0xf7, 0x44, 0x09, 0xde, 0x6c, 0xf3, 0x29, 0xd1, 0xf3, 0xe7, 0x04, 0xda, 0x66, 0xd7, + 0x89, 0x0d, 0xb9, 0xb6, 0x38, 0x15, 0x27, 0x00, 0xec, 0x7b, 0xe6, 0xc2, 0xe0, 0x6c, 0xa4, 0xf6, 0x41, 0x0b, 0xa7, + 0xb7, 0x04, 0xfa, 0xd9, 0x38, 0x45, 0xde, 0xef, 0x00, 0x95, 0x52, 0x78, 0xe2, 0x10, 0x13, 0x2a, 0x76, 0xf8, 0x9c, + 0x52, 0x9f, 0x43, 0x8e, 0x9c, 0x77, 0xc0, 0x89, 0x5b, 0xda, 0x74, 0x63, 0x79, 0xbb, 0xe1, 0xbb, 0x8a, 0x74, 0x65, + 0xf5, 0xb0, 0x84, 0xb6, 0xcd, 0xd1, 0x19, 0x67, 0x94, 0xa0, 0xc4, 0x08, 0x29, 0xc3, 0xf3, 0x63, 0x30, 0x48, 0x26, + 0xe3, 0x30, 0xd1, 0x6b, 0xce, 0x0a, 0xa3, 0xff, 0x44, 0x08, 0x23, 0x84, 0x9f, 0x5f, 0x67, 0x6c, 0xdf, 0xa3, 0xbb, + 0xb6, 0xe9, 0x5e, 0x6f, 0x15, 0xb1, 0xcf, 0x2b, 0x0d, 0x4a, 0xa5, 0xd2, 0x58, 0xdb, 0x8c, 0x7f, 0x75, 0x52, 0x9d, + 0x46, 0x1d, 0x8e, 0x70, 0x76, 0xa6, 0xcd, 0xf9, 0xbf, 0x9e, 0x99, 0xb9, 0xd7, 0xce, 0xcb, 0x9e, 0x19, 0xeb, 0xc6, + 0x25, 0x91, 0x16, 0xe4, 0x26, 0x0d, 0x25, 0xeb, 0xb1, 0xd1, 0xde, 0x94, 0x4c, 0xfd, 0xc8, 0xa4, 0x80, 0x8d, 0xb1, + 0xda, 0xe1, 0x32, 0x3e, 0xcd, 0xfb, 0xa8, 0x24, 0x0b, 0x2e, 0xc4, 0xf9, 0x70, 0xbb, 0xb1, 0x22, 0x85, 0x1d, 0x68, + 0xf2, 0xeb, 0x4f, 0xc9, 0xae, 0xf0, 0x9d, 0xdf, 0x81, 0x64, 0xd6, 0x17, 0x2b, 0xc5, 0x06, 0x75, 0x05, 0x7a, 0x03, + 0x2e, 0xdf, 0xd1, 0x1b, 0x65, 0x34, 0x7c, 0x5d, 0x4a, 0x54, 0x92, 0x50, 0x63, 0xa5, 0x60, 0xb7, 0x58, 0x97, 0x51, + 0x14, 0x17, 0x6b, 0xa2, 0x5f, 0x15, 0x4c, 0x16, 0xdb, 0x6e, 0xe0, 0xdc, 0x04, 0xea, 0x51, 0x07, 0x27, 0xfa, 0x3b, + 0x44, 0xde, 0x16, 0xc5, 0x86, 0x6c, 0x1b, 0x88, 0xa1, 0x15, 0xd7, 0x75, 0xaa, 0xb1, 0x3e, 0xf2, 0x80, 0x1e, 0xf7, + 0xaf, 0x8e, 0x21, 0x78, 0xf8, 0x69, 0xc0, 0x52, 0x57, 0x9d, 0x3a, 0xbc, 0x7d, 0x74, 0x63, 0x49, 0xea, 0x71, 0x7e, + 0xf3, 0x4f, 0xc5, 0x36, 0x2d, 0x4f, 0xb7, 0xc8, 0x0d, 0x89, 0xe0, 0x5d, 0x41, 0xf6, 0xd3, 0xc1, 0x6d, 0x7b, 0xa6, + 0x28, 0x0a, 0x2f, 0x94, 0xb4, 0xbc, 0x29, 0x3c, 0x8c, 0xe3, 0x46, 0x8a, 0x1a, 0x2a, 0x32, 0xfe, 0x31, 0x36, 0x2c, + 0x92, 0x9d, 0xad, 0x0f, 0x63, 0xe7, 0x95, 0x90, 0x8f, 0x2b, 0xd7, 0xea, 0x46, 0xa6, 0x63, 0x5b, 0x14, 0x39, 0x7a, + 0x9d, 0x07, 0xa0, 0xf2, 0x47, 0x61, 0x12, 0x50, 0x1c, 0x89, 0x00, 0xa2, 0x3a, 0xf1, 0xa2, 0xe8, 0x81, 0xcd, 0xa1, + 0x19, 0x56, 0x83, 0x7c, 0x2a, 0xfa, 0x1b, 0x15, 0x9d, 0xd9, 0xf1, 0x50, 0xd8, 0x8b, 0x4c, 0xac, 0x3e, 0xe6, 0xae, + 0x43, 0x91, 0x36, 0x72, 0xea, 0x3b, 0xd7, 0x98, 0x37, 0xd0, 0xc3, 0x22, 0x14, 0x7f, 0x61, 0x83, 0x98, 0xb2, 0x01, + 0x2b, 0x64, 0xec, 0x79, 0x04, 0x30, 0x4b, 0xf2, 0x45, 0x12, 0x78, 0xd3, 0xaf, 0x40, 0xbf, 0xc1, 0x7d, 0xb5, 0x6f, + 0x26, 0x4d, 0xb3, 0x70, 0x77, 0x63, 0xbf, 0x2f, 0x36, 0x72, 0x4f, 0x08, 0x22, 0x58, 0x92, 0xd9, 0xb2, 0x96, 0xde, + 0x03, 0x7e, 0xa5, 0xe0, 0x19, 0x78, 0xc8, 0x00, 0x8e, 0x98, 0x96, 0xb8, 0xae, 0xd6, 0x93, 0xab, 0xc3, 0x56, 0x6e, + 0x0b, 0x25, 0x38, 0x44, 0xd2, 0xe8, 0x96, 0x4a, 0xb3, 0x94, 0xee, 0x99, 0xad, 0xbb, 0x91, 0x71, 0xfc, 0x65, 0x50, + 0x9e, 0x58, 0x8f, 0x5f, 0x93, 0xc8, 0x96, 0x44, 0x14, 0x97, 0x5f, 0xe7, 0x90, 0xdd, 0x58, 0xa9, 0x98, 0x0c, 0x54, + 0x3d, 0x79, 0xaa, 0x09, 0xde, 0x60, 0x71, 0x17, 0x1c, 0xe9, 0x03, 0xed, 0x09, 0xc5, 0x49, 0xaa, 0x4a, 0xa9, 0x87, + 0x7e, 0xc2, 0x57, 0xd8, 0xe7, 0xa2, 0xb7, 0xd9, 0x31, 0xcd, 0xd8, 0x67, 0x34, 0xc1, 0x80, 0x3a, 0x09, 0x4e, 0xbb, + 0x66, 0x78, 0xe4, 0x48, 0x6c, 0x3a, 0x90, 0x8f, 0xf1, 0x54, 0xe8, 0x36, 0x6e, 0x56, 0x21, 0x8e, 0x86, 0xd0, 0xfd, + 0x30, 0x14, 0x46, 0x3f, 0xa3, 0x74, 0xac, 0x3e, 0xed, 0xd7, 0x5c, 0xd4, 0xce, 0x98, 0xa2, 0x29, 0x2f, 0xbb, 0xa6, + 0x00, 0x6f, 0xa4, 0xbc, 0xc1, 0x0a, 0xf8, 0xfe, 0xb2, 0x59, 0x57, 0x8f, 0x17, 0x36, 0xf9, 0x0f, 0xae, 0x83, 0x8d, + 0x84, 0x09, 0xfc, 0x11, 0x92, 0x99, 0x2d, 0x82, 0x35, 0x8c, 0xf3, 0x92, 0x58, 0x38, 0x7a, 0x9c, 0xef, 0x07, 0xd9, + 0x1f, 0x57, 0x8d, 0x07, 0x61, 0x0b, 0x0f, 0xad, 0xe4, 0x9c, 0xa8, 0xd7, 0xd4, 0xa9, 0x91, 0x0f, 0x22, 0x93, 0xc0, + 0x84, 0xf2, 0x3c, 0xc1, 0x34, 0xab, 0xb3, 0x59, 0x50, 0xdb, 0x44, 0xc5, 0xa0, 0xd0, 0x8d, 0xdb, 0x99, 0x20, 0xc9, + 0x86, 0xe0, 0x94, 0x97, 0x65, 0xc3, 0xed, 0x75, 0x6b, 0xe6, 0x45, 0xf3, 0xd7, 0x64, 0x87, 0xa5, 0xdf, 0x05, 0x1d, + 0x6b, 0xe3, 0xf5, 0x60, 0x7b, 0xd0, 0x79, 0x58, 0xbc, 0x50, 0x3a, 0x8d, 0xaa, 0x9b, 0x7a, 0x11, 0x37, 0xfb, 0x39, + 0x75, 0x35, 0xd1, 0x6c, 0x09, 0x48, 0x67, 0xa3, 0x7c, 0x8f, 0x9d, 0xb8, 0x46, 0x51, 0x5a, 0x4b, 0xab, 0x5b, 0xe6, + 0x1d, 0x8b, 0x91, 0xbb, 0x81, 0x51, 0x62, 0xed, 0x22, 0x86, 0x9a, 0x9f, 0xc3, 0xdc, 0x9e, 0x98, 0x40, 0x45, 0xff, + 0x3a, 0x9f, 0xcc, 0xec, 0x62, 0x9a, 0x4a, 0x32, 0xcc, 0x07, 0xa5, 0x6f, 0x89, 0xe6, 0xee, 0xf1, 0x9c, 0x93, 0xd2, + 0xb6, 0xad, 0x62, 0x1d, 0xba, 0x85, 0x81, 0x0f, 0x5c, 0x4d, 0x03, 0xc1, 0x15, 0xbd, 0xc5, 0x98, 0x67, 0xf0, 0x7c, + 0xc0, 0xec, 0x1b, 0x79, 0x3e, 0x2f, 0x45, 0xde, 0x3e, 0x91, 0x19, 0xbe, 0x50, 0xa0, 0x98, 0xde, 0xe9, 0x7c, 0x6f, + 0x9f, 0x87, 0x1b, 0x77, 0x59, 0xe0, 0xbe, 0x24, 0x0e, 0x19, 0xfe, 0x75, 0x17, 0x5b, 0xc6, 0x1a, 0xcf, 0x9c, 0xfb, + 0x2d, 0x89, 0x09, 0xa5, 0xda, 0xae, 0x1f, 0xa2, 0xbc, 0x16, 0x61, 0x52, 0x85, 0xa5, 0xdb, 0x2a, 0xa4, 0x32, 0xf4, + 0x45, 0xa4, 0x8a, 0xc7, 0x99, 0x9b, 0x9d, 0xa1, 0x34, 0x82, 0x0c, 0x05, 0x13, 0x64, 0xb5, 0x4f, 0xa2, 0x79, 0x56, + 0xf2, 0xa0, 0x4d, 0x13, 0xf9, 0xf0, 0xba, 0x2a, 0x63, 0xe1, 0x71, 0xe6, 0xde, 0x76, 0xc4, 0xdc, 0xba, 0x8e, 0xf3, + 0xea, 0x03, 0x75, 0x2b, 0x47, 0xe6, 0xb9, 0x62, 0x6c, 0xc5, 0xd8, 0x3d, 0xa8, 0x45, 0xa0, 0x0c, 0x45, 0x12, 0x0e, + 0x6c, 0x31, 0x7a, 0x7b, 0xa1, 0xce, 0x06, 0xc2, 0xad, 0xb2, 0x3e, 0xaa, 0xc5, 0x6b, 0xda, 0xb6, 0x52, 0x0a, 0x4e, + 0xa0, 0x10, 0x4e, 0x34, 0xf6, 0x9c, 0x0f, 0xff, 0xfc, 0x5c, 0xa7, 0x1e, 0xff, 0x99, 0x10, 0x9b, 0xfd, 0x97, 0xf7, + 0xaf, 0x63, 0x0a, 0xd0, 0xeb, 0x9e, 0x75, 0x45, 0x7a, 0xad, 0xeb, 0x35, 0xd2, 0xab, 0xaf, 0x57, 0xb5, 0x39, 0xe1, + 0x59, 0x2d, 0xb5, 0x51, 0x1b, 0x77, 0x6e, 0x14, 0xeb, 0x30, 0x94, 0x94, 0xd4, 0x7e, 0x4f, 0x4f, 0x3f, 0x8d, 0x55, + 0x99, 0x6f, 0xcd, 0xa4, 0x98, 0x4d, 0x5f, 0x1c, 0xab, 0xf5, 0xb8, 0x8c, 0x10, 0xbb, 0x17, 0x43, 0x6d, 0xa5, 0x3a, + 0x35, 0x75, 0x9b, 0xcf, 0x2f, 0xc6, 0xc5, 0xe5, 0xcb, 0xbf, 0x22, 0xc4, 0xf3, 0x11, 0xe3, 0xa1, 0x8d, 0x76, 0xde, + 0x37, 0x48, 0x8d, 0xcb, 0xcd, 0x11, 0xe7, 0x68, 0x56, 0x15, 0xc6, 0x88, 0xa7, 0x55, 0xe7, 0x2e, 0xb8, 0xf6, 0x20, + 0xf0, 0x73, 0x71, 0x55, 0xa9, 0x48, 0x52, 0xdf, 0x36, 0xb0, 0x2e, 0x37, 0x4b, 0x93, 0xc3, 0xdf, 0x0b, 0x2c, 0xe8, + 0x63, 0x53, 0x95, 0xeb, 0x07, 0x25, 0xc4, 0xd8, 0x29, 0x62, 0xca, 0xa9, 0xf4, 0x2e, 0xac, 0x7c, 0x51, 0x5f, 0x4f, + 0x99, 0xfa, 0x36, 0x88, 0x31, 0x8b, 0x31, 0x27, 0x4b, 0x31, 0x27, 0x79, 0x60, 0xfb, 0x3c, 0x06, 0xc6, 0xc5, 0x24, + 0x10, 0xf9, 0x70, 0xe3, 0xca, 0x58, 0xbe, 0x08, 0x18, 0xac, 0xa2, 0x0d, 0x04, 0xd3, 0x3b, 0x33, 0xed, 0xe2, 0x1f, + 0xf3, 0xcb, 0x41, 0x64, 0x5c, 0x89, 0x21, 0xac, 0x8e, 0xf8, 0xad, 0xd3, 0x0b, 0x64, 0x62, 0xe5, 0x8c, 0x66, 0x09, + 0x98, 0x75, 0xd3, 0x34, 0x38, 0x56, 0x4d, 0x83, 0x4a, 0x33, 0xaf, 0xb0, 0x0c, 0x24, 0x31, 0x30, 0x95, 0x6a, 0xf8, + 0x95, 0x16, 0x09, 0xce, 0xf9, 0xfb, 0xae, 0xcf, 0x29, 0x90, 0xc6, 0x99, 0x46, 0xa5, 0xc0, 0xe7, 0x0e, 0xf8, 0x05, + 0xfa, 0x15, 0x9f, 0x88, 0xe3, 0x34, 0xe9, 0x91, 0xc9, 0xe8, 0x81, 0xda, 0x81, 0x90, 0x59, 0x4b, 0x46, 0x61, 0x1a, + 0x42, 0x28, 0x05, 0x44, 0x7c, 0x3f, 0xcc, 0x45, 0x95, 0x35, 0xaf, 0xc6, 0x02, 0xb7, 0x10, 0x31, 0x23, 0xaa, 0x06, + 0x22, 0xc9, 0x48, 0xae, 0x1b, 0x32, 0x2c, 0x96, 0x26, 0x2d, 0xc6, 0xe0, 0x04, 0xc9, 0x3c, 0x9d, 0x08, 0xfe, 0x65, + 0x48, 0xc6, 0x05, 0x6f, 0x7a, 0xaf, 0x80, 0xbe, 0xc6, 0xc5, 0x64, 0xe7, 0xcd, 0xbc, 0xe8, 0x89, 0xb4, 0x5c, 0xe5, + 0x43, 0xa2, 0xd0, 0xdf, 0xd7, 0x7d, 0xef, 0x58, 0x3d, 0x48, 0xc1, 0xbc, 0x2d, 0x6a, 0x8b, 0x96, 0xed, 0xb5, 0x95, + 0xc7, 0x72, 0xdc, 0x3d, 0x4a, 0x50, 0x00, 0xdd, 0x66, 0xd1, 0x0a, 0x3c, 0x49, 0xd6, 0xd8, 0xa9, 0x4f, 0x44, 0x74, + 0x74, 0x1b, 0x25, 0xb3, 0x23, 0x5b, 0x17, 0x3f, 0x90, 0x91, 0xe4, 0xcc, 0x5c, 0x89, 0xce, 0xff, 0x59, 0xf2, 0x26, + 0x17, 0x33, 0x5b, 0x75, 0xc8, 0x01, 0x6e, 0x3a, 0x13, 0x61, 0x8a, 0xf6, 0x56, 0x66, 0x23, 0x44, 0x86, 0x93, 0x49, + 0x16, 0x64, 0xea, 0xc5, 0x5f, 0x8c, 0x14, 0xfc, 0x47, 0xc4, 0x86, 0x96, 0x3c, 0xd2, 0xff, 0x70, 0x0d, 0xe1, 0x5b, + 0x39, 0x1c, 0x24, 0xd5, 0x7b, 0x2d, 0xb8, 0x2d, 0x2d, 0x1b, 0x66, 0x83, 0x24, 0x3c, 0x3e, 0xbb, 0x7c, 0xe6, 0xdb, + 0x83, 0xfc, 0x43, 0x44, 0x08, 0x84, 0xfa, 0xdf, 0xf4, 0xaa, 0x76, 0xf1, 0x32, 0x2a, 0x4e, 0x83, 0xf2, 0xf5, 0xf8, + 0x8c, 0xc3, 0x1b, 0x2a, 0x2f, 0xe0, 0xb7, 0x6f, 0xe7, 0x1c, 0x98, 0x81, 0x2f, 0x63, 0xab, 0xb1, 0x80, 0xbd, 0x70, + 0xd8, 0x63, 0x28, 0x59, 0xc4, 0xa1, 0xed, 0x6c, 0x84, 0xdb, 0xd0, 0xf5, 0x36, 0xdb, 0xaf, 0x94, 0x72, 0x75, 0xc6, + 0xf9, 0x3b, 0xdb, 0xaa, 0xe6, 0x66, 0xd7, 0x0d, 0x5b, 0x2a, 0xe9, 0x69, 0x5f, 0x6e, 0x30, 0x75, 0x43, 0xf6, 0x36, + 0xd4, 0x5a, 0xbe, 0x19, 0xd6, 0x95, 0x37, 0x0b, 0x83, 0x42, 0xc0, 0x98, 0x61, 0xcd, 0x15, 0xb9, 0xd6, 0xca, 0x7e, + 0x30, 0xc5, 0xfe, 0x30, 0x08, 0x89, 0xa8, 0x8a, 0x24, 0x67, 0x83, 0x1e, 0xe7, 0x6a, 0xed, 0x59, 0x3d, 0x02, 0x4b, + 0x27, 0x96, 0x63, 0xcd, 0x0a, 0x06, 0x43, 0xa9, 0xaa, 0xd5, 0x52, 0x77, 0xb8, 0x4a, 0x9f, 0x6a, 0x79, 0xc5, 0x0b, + 0x12, 0xf6, 0x0b, 0x88, 0x4e, 0x7c, 0x77, 0xf7, 0x24, 0xf2, 0x9d, 0x59, 0x7d, 0x63, 0x2a, 0x4d, 0x94, 0x67, 0xc5, + 0x0a, 0x4a, 0xd6, 0x3b, 0xc0, 0x50, 0x51, 0x63, 0x6c, 0xe8, 0x0e, 0x0d, 0xd6, 0xe6, 0x38, 0xdc, 0x17, 0xf6, 0xdb, + 0x82, 0xec, 0x47, 0xfd, 0x9c, 0x93, 0xfb, 0x68, 0xb3, 0xa8, 0x97, 0xf5, 0x56, 0x63, 0xe4, 0x08, 0xaf, 0x37, 0x27, + 0x55, 0xb6, 0xa0, 0xc9, 0x5e, 0x83, 0xd3, 0x4b, 0x33, 0x75, 0xa1, 0xec, 0xc4, 0x8c, 0x28, 0xd3, 0x41, 0x24, 0x09, + 0xba, 0xb3, 0x1e, 0x04, 0xd7, 0x2c, 0x0b, 0x6b, 0x93, 0x91, 0x7b, 0x30, 0x9c, 0x23, 0x15, 0xd1, 0x25, 0x14, 0xc5, + 0x39, 0x9b, 0xd7, 0x3f, 0x30, 0xe4, 0x28, 0x8f, 0xc5, 0xb2, 0x64, 0x41, 0xbd, 0x6f, 0x61, 0xa4, 0x26, 0xfb, 0x74, + 0x2c, 0xa5, 0x90, 0x1d, 0xc0, 0xc6, 0x8e, 0xb6, 0x73, 0xc1, 0x9c, 0xda, 0xba, 0x04, 0x3b, 0xd9, 0xa9, 0xb9, 0x5b, + 0x91, 0x01, 0x91, 0x07, 0x42, 0x14, 0x06, 0x7c, 0x7f, 0x5e, 0x11, 0xc0, 0x9a, 0xe3, 0x14, 0x89, 0x3f, 0x08, 0xe3, + 0x97, 0x1f, 0x14, 0x83, 0x84, 0xe5, 0xae, 0xe7, 0x70, 0xfa, 0x3a, 0x80, 0x56, 0xea, 0xc5, 0xe6, 0x7b, 0x26, 0xca, + 0x46, 0xfe, 0x2a, 0xd6, 0x3a, 0x62, 0x88, 0x70, 0xe0, 0xcb, 0x66, 0x43, 0xd2, 0x78, 0xb3, 0x5c, 0x9c, 0x8d, 0x9a, + 0xae, 0xab, 0x23, 0xee, 0x23, 0x15, 0x84, 0xb1, 0xd9, 0xf0, 0xd0, 0x8d, 0xf3, 0x43, 0xd6, 0x6e, 0x06, 0x87, 0x41, + 0x04, 0x7e, 0x6d, 0xba, 0x56, 0x97, 0x70, 0xb5, 0xa6, 0x99, 0x78, 0x2f, 0xce, 0xa6, 0xfb, 0xba, 0xd7, 0x35, 0xc2, + 0xbf, 0x5c, 0xe2, 0x80, 0xf9, 0x37, 0x52, 0xc5, 0x41, 0x8b, 0x39, 0x7a, 0x8d, 0x4b, 0x9a, 0xe9, 0xa9, 0x21, 0x77, + 0x57, 0xca, 0x7b, 0x28, 0x07, 0xaa, 0x63, 0x3c, 0x3d, 0x64, 0x37, 0x87, 0x5b, 0x80, 0xda, 0x8e, 0x10, 0x57, 0x06, + 0xea, 0x09, 0x80, 0x2b, 0x09, 0x84, 0x65, 0x1e, 0xcf, 0x90, 0xbe, 0x67, 0xd2, 0x09, 0x68, 0xe8, 0x40, 0xb9, 0xe9, + 0x49, 0x99, 0x43, 0xea, 0xa1, 0x0e, 0x52, 0x4c, 0x78, 0xd0, 0xcb, 0xae, 0x96, 0xea, 0x3a, 0x1a, 0x21, 0x69, 0x42, + 0x41, 0xfc, 0x82, 0xa0, 0xe8, 0xab, 0x21, 0xf2, 0x97, 0x89, 0xca, 0xba, 0xaa, 0xf0, 0x06, 0xff, 0x12, 0x2d, 0xb2, + 0xfa, 0xce, 0xcc, 0xec, 0x48, 0x5d, 0x56, 0xa2, 0xf6, 0x02, 0xb0, 0x0e, 0x87, 0xe0, 0x40, 0x22, 0x62, 0x9e, 0x44, + 0x13, 0xd9, 0x54, 0x28, 0x7f, 0xe6, 0xd0, 0x28, 0x80, 0xcb, 0x79, 0x24, 0x68, 0x22, 0xf0, 0xb1, 0x13, 0xe0, 0xcc, + 0x0c, 0x3c, 0x9c, 0xad, 0x26, 0x8d, 0xc0, 0x98, 0x6b, 0xe5, 0xa5, 0x66, 0x1f, 0x33, 0xa2, 0x1c, 0x17, 0x73, 0x23, + 0xbb, 0x6b, 0xf2, 0x70, 0x88, 0x79, 0x62, 0x63, 0x0e, 0xdf, 0xd7, 0x9e, 0x19, 0xd3, 0xbf, 0xcc, 0xc0, 0x27, 0x25, + 0xea, 0x4e, 0x0d, 0x8a, 0xd7, 0xed, 0x9d, 0xd7, 0x56, 0xbb, 0x86, 0x5c, 0x16, 0x1d, 0x06, 0xab, 0xb5, 0xff, 0xd7, + 0x7f, 0x8a, 0xe3, 0xbe, 0x72, 0x3e, 0x06, 0x57, 0x3c, 0x04, 0x87, 0x35, 0x43, 0xcd, 0xaf, 0xeb, 0xe2, 0x39, 0x3e, + 0x6d, 0x1f, 0xe6, 0xc6, 0xd3, 0xdd, 0x81, 0x97, 0xb9, 0x90, 0xfa, 0xcc, 0x12, 0xa2, 0x0f, 0x43, 0x8b, 0x67, 0x63, + 0x54, 0x89, 0xc6, 0x97, 0x0e, 0x29, 0x96, 0x2d, 0x9e, 0xee, 0x04, 0xe2, 0xe5, 0x70, 0x77, 0xb6, 0x40, 0xac, 0x28, + 0x11, 0xe6, 0x74, 0x22, 0xd2, 0x38, 0x02, 0xc6, 0x2b, 0xf1, 0xc0, 0x10, 0x18, 0x69, 0x94, 0x59, 0xd3, 0xfe, 0xb0, + 0x11, 0xd9, 0xe7, 0x90, 0x68, 0x32, 0x6c, 0xca, 0x3b, 0x9b, 0x51, 0x7b, 0x25, 0x12, 0x8a, 0x86, 0x75, 0xdf, 0x4d, + 0x33, 0x2a, 0xef, 0xc5, 0x38, 0x24, 0x0e, 0xe1, 0xa4, 0x77, 0x3f, 0x6d, 0x1f, 0x4a, 0x1e, 0x7e, 0x0e, 0xfb, 0xc3, + 0x0f, 0xfe, 0xe1, 0xe7, 0x70, 0x77, 0x7e, 0xf0, 0x9d, 0x9f, 0x43, 0xde, 0xf9, 0x41, 0xbc, 0x54, 0x9a, 0xbe, 0xd2, + 0x9e, 0x07, 0x63, 0xc5, 0x50, 0x2e, 0xcb, 0xc8, 0x56, 0xaa, 0xe0, 0x17, 0x3f, 0x24, 0xdc, 0xe7, 0x12, 0x29, 0x39, + 0x25, 0x2e, 0x58, 0x89, 0x4a, 0x56, 0x86, 0x4e, 0x81, 0x7d, 0x1a, 0xd0, 0xc3, 0xea, 0xed, 0xe7, 0xfc, 0xcb, 0x6d, + 0x50, 0x74, 0x26, 0xe2, 0x01, 0x24, 0x43, 0xb9, 0x33, 0x07, 0x2f, 0x4c, 0x49, 0x18, 0x65, 0x39, 0x62, 0xb4, 0xa2, + 0xd2, 0x8e, 0xb3, 0x44, 0xef, 0xdc, 0x01, 0x16, 0x82, 0xbe, 0x5d, 0xe8, 0xb5, 0x72, 0x58, 0x7f, 0xff, 0x05, 0x28, + 0x55, 0x57, 0x0c, 0x78, 0x60, 0x1f, 0x7b, 0x71, 0x1f, 0x69, 0xe5, 0xd5, 0xa4, 0x8a, 0x1a, 0x5c, 0x93, 0x83, 0x31, + 0x46, 0x48, 0xdc, 0xd3, 0xbf, 0x64, 0x4d, 0x72, 0xe6, 0xe6, 0xad, 0x66, 0xe1, 0x1e, 0xa3, 0xe7, 0x80, 0xe6, 0xc4, + 0xa8, 0x9a, 0x19, 0xb6, 0x88, 0x5a, 0xb3, 0x9a, 0x33, 0x8b, 0x38, 0x59, 0x8a, 0xad, 0xab, 0xb0, 0xe7, 0x3d, 0x7e, + 0xca, 0xef, 0xe0, 0x2a, 0x37, 0x43, 0x1a, 0xec, 0x8b, 0x0c, 0xec, 0x83, 0x2b, 0x6c, 0x6b, 0x0d, 0xa6, 0x27, 0x9c, + 0xad, 0xc5, 0xf5, 0xd5, 0x14, 0xbe, 0x20, 0xad, 0xa1, 0x2d, 0x45, 0x34, 0xba, 0x4b, 0x26, 0x36, 0x52, 0xda, 0xfa, + 0xe1, 0x6b, 0x0b, 0x8d, 0x36, 0x2b, 0x96, 0x60, 0xc9, 0xee, 0x37, 0x2f, 0xb9, 0x0f, 0x4d, 0xe6, 0x2c, 0xc8, 0x44, + 0xd5, 0x4d, 0x90, 0x36, 0x05, 0xbe, 0x38, 0x59, 0x61, 0x3c, 0x02, 0x59, 0xe4, 0x36, 0x17, 0x87, 0x53, 0x47, 0x2d, + 0xa3, 0xaa, 0x84, 0x48, 0x7d, 0x56, 0xae, 0x93, 0x4b, 0xd0, 0xf1, 0xe2, 0x40, 0x04, 0x97, 0xc3, 0x84, 0x54, 0x6a, + 0x3a, 0x6d, 0xd7, 0x68, 0x6f, 0x21, 0xcf, 0xa1, 0x4e, 0x3f, 0x0d, 0x36, 0x84, 0x21, 0xaa, 0x31, 0xf8, 0x32, 0xf3, + 0xf4, 0x9a, 0x2e, 0x4d, 0xdb, 0xc7, 0x01, 0x04, 0x7a, 0xb1, 0x3d, 0x95, 0xce, 0x5d, 0x9f, 0x92, 0x48, 0x20, 0x91, + 0xf8, 0x02, 0xe0, 0x03, 0x80, 0xaf, 0x7a, 0x89, 0xaa, 0x45, 0x26, 0xbd, 0x54, 0x81, 0x9e, 0x29, 0xb8, 0x03, 0x32, + 0x43, 0x2b, 0x40, 0xe5, 0x8f, 0x48, 0xf1, 0xb5, 0x43, 0xb2, 0x98, 0xf0, 0xd2, 0x50, 0xbc, 0x8e, 0x09, 0xed, 0x7c, + 0x98, 0x9a, 0x5e, 0x22, 0x77, 0x81, 0x94, 0x8e, 0xd8, 0xa2, 0x9f, 0xbe, 0x3c, 0xbb, 0x69, 0xe1, 0x24, 0x8f, 0x2c, + 0xbf, 0xd6, 0xfe, 0x2d, 0x6b, 0xdb, 0x55, 0xf5, 0x47, 0xa6, 0xa4, 0x0e, 0xb4, 0x21, 0x94, 0xeb, 0x99, 0xb2, 0xa7, + 0xf4, 0x15, 0xec, 0x2c, 0x86, 0x45, 0xaf, 0x2d, 0xb3, 0xdd, 0x1c, 0x3e, 0x74, 0xd1, 0x03, 0xd1, 0x84, 0xdb, 0xd7, + 0x48, 0xa0, 0xb9, 0x44, 0xb0, 0x18, 0x9e, 0xe1, 0xd2, 0x6e, 0xfc, 0x92, 0x53, 0x14, 0xc4, 0x2a, 0xf0, 0x21, 0x7d, + 0xff, 0x01, 0x43, 0x86, 0xb2, 0xdd, 0x86, 0xc3, 0x55, 0x0d, 0x34, 0x5f, 0xf7, 0x71, 0xd8, 0xab, 0x13, 0xb0, 0xb6, + 0x64, 0xbe, 0xda, 0xb4, 0x51, 0xec, 0x35, 0x97, 0xa7, 0xbd, 0xb6, 0x52, 0xe0, 0xcf, 0xc5, 0x47, 0x7f, 0x7b, 0x5e, + 0xd4, 0x2c, 0xcb, 0x8b, 0xd2, 0x7b, 0x5b, 0xd5, 0xec, 0xb4, 0x06, 0xa3, 0x3f, 0x4e, 0x85, 0x90, 0x58, 0x0e, 0x93, + 0xd2, 0xf3, 0xd1, 0xa8, 0x16, 0xbb, 0xd7, 0x64, 0x1e, 0x1f, 0x26, 0xa1, 0x9a, 0x4d, 0x8d, 0x3c, 0xb8, 0xd7, 0x9b, + 0x0b, 0x7d, 0x8f, 0x02, 0xd5, 0xbd, 0x16, 0x4e, 0xd5, 0x55, 0x29, 0x41, 0x4c, 0x46, 0x46, 0x33, 0xcd, 0xc6, 0xbc, + 0x0c, 0xdc, 0x9a, 0xa9, 0x7e, 0x41, 0x9f, 0x48, 0xc9, 0x61, 0xd8, 0x59, 0x59, 0x94, 0x8a, 0x49, 0x4a, 0x00, 0x8b, + 0xed, 0x67, 0x71, 0x72, 0x60, 0x50, 0xb5, 0xea, 0x3c, 0x60, 0x24, 0x8e, 0xc5, 0xe2, 0x23, 0x50, 0xf1, 0x5b, 0x07, + 0xa8, 0x12, 0x4e, 0x8f, 0x55, 0x71, 0x1e, 0x7e, 0x10, 0xa5, 0x52, 0x4f, 0x40, 0xa0, 0xa6, 0x4e, 0x5e, 0xe6, 0x5e, + 0xb0, 0x7c, 0x33, 0xa7, 0x8d, 0xbd, 0x30, 0x2b, 0x1d, 0x90, 0x6b, 0xd3, 0x48, 0x0c, 0x45, 0xfc, 0x93, 0x63, 0xe3, + 0x36, 0xba, 0xb0, 0xea, 0x85, 0xe5, 0x5e, 0x54, 0x07, 0xa1, 0x41, 0xe8, 0x90, 0xa7, 0xca, 0x6d, 0x19, 0xd6, 0xe7, + 0x81, 0x97, 0x27, 0xfd, 0x0b, 0x4f, 0x0f, 0x36, 0x3d, 0xfc, 0x80, 0x45, 0x2b, 0x89, 0x34, 0x54, 0xb1, 0x49, 0xe1, + 0x8e, 0x48, 0x95, 0xe5, 0xce, 0xd3, 0x1e, 0xdd, 0x6b, 0x33, 0x0f, 0xd2, 0xd5, 0x47, 0x05, 0x45, 0x6b, 0x68, 0x09, + 0xa5, 0x2e, 0x60, 0x0a, 0xa3, 0x2c, 0xde, 0xe9, 0xab, 0xf5, 0x93, 0x5d, 0x4a, 0xc2, 0x01, 0x1f, 0xc3, 0x60, 0x26, + 0xf0, 0xef, 0x87, 0x48, 0x07, 0x37, 0xb5, 0x6e, 0x85, 0x32, 0x86, 0xb4, 0x42, 0x30, 0x1f, 0x49, 0x74, 0x98, 0xe0, + 0xfb, 0xc1, 0xa4, 0xc8, 0x49, 0xc1, 0x46, 0xe3, 0x37, 0xe3, 0x1a, 0x43, 0xc7, 0x99, 0xf1, 0x9d, 0x9f, 0xae, 0xd8, + 0xdb, 0x72, 0x5c, 0x1d, 0x42, 0xc0, 0xe5, 0x58, 0xee, 0x75, 0x5d, 0x90, 0x75, 0x8c, 0x76, 0x14, 0x3e, 0x23, 0x71, + 0xa9, 0x0b, 0x3d, 0xa5, 0xda, 0x91, 0x33, 0x86, 0x25, 0x38, 0x5d, 0xcd, 0x9f, 0xd8, 0xc6, 0x15, 0xb4, 0xed, 0xec, + 0x34, 0x50, 0xb7, 0x57, 0xc0, 0x83, 0x5d, 0x63, 0x4a, 0x94, 0x25, 0x56, 0x05, 0x34, 0x18, 0x01, 0x6d, 0x59, 0x60, + 0x54, 0x13, 0x31, 0xd1, 0x28, 0x8c, 0x12, 0xa9, 0xa5, 0x94, 0x1d, 0xcb, 0x1f, 0x75, 0x92, 0x4c, 0x92, 0x75, 0x28, + 0x4e, 0x7a, 0x62, 0x92, 0xd4, 0x6a, 0x5d, 0xb6, 0x78, 0x79, 0x21, 0xf6, 0x8b, 0x54, 0x7a, 0x62, 0xef, 0xa0, 0x05, + 0x72, 0xb3, 0xef, 0x69, 0x48, 0x0d, 0x8d, 0xce, 0xf6, 0x46, 0xe7, 0xe5, 0xa9, 0x6c, 0xbe, 0xd5, 0x51, 0xcb, 0xf8, + 0xc6, 0x98, 0xa2, 0x0a, 0xa8, 0x3f, 0xd6, 0x82, 0xf4, 0xfd, 0x4b, 0xb1, 0xce, 0x50, 0x34, 0x4c, 0x5d, 0xf6, 0x58, + 0x8c, 0x74, 0x9d, 0xe6, 0x89, 0x90, 0xe0, 0xde, 0x1d, 0x18, 0x78, 0x44, 0x99, 0x3b, 0x19, 0xd3, 0x09, 0xc2, 0x10, + 0x91, 0x75, 0xb2, 0xe6, 0x7d, 0x6e, 0xfd, 0x7c, 0x14, 0x87, 0x61, 0x0c, 0x1b, 0x4c, 0xae, 0xf6, 0x53, 0x7a, 0xef, + 0xc7, 0x62, 0xa4, 0x76, 0x9d, 0xd9, 0xcd, 0x78, 0x61, 0xa9, 0x3d, 0x16, 0xf6, 0x3f, 0x64, 0x3e, 0xf5, 0x58, 0xe9, + 0xbd, 0xb4, 0x86, 0x34, 0x9e, 0x59, 0x63, 0xd5, 0x5f, 0x82, 0x76, 0xe4, 0x12, 0xed, 0xc4, 0x4e, 0xa9, 0x2a, 0x48, + 0x28, 0x48, 0x8c, 0xa9, 0xed, 0x1c, 0x0c, 0x34, 0x63, 0x9d, 0xb9, 0x63, 0x8b, 0xbe, 0x3d, 0xe5, 0xa4, 0x1c, 0xa0, + 0xbc, 0x14, 0xfe, 0xd9, 0x76, 0x50, 0x62, 0x1f, 0xc7, 0x18, 0x5b, 0x81, 0x7d, 0x48, 0x20, 0x55, 0xc1, 0x84, 0x56, + 0x93, 0x07, 0x74, 0x71, 0x4a, 0xc7, 0x9f, 0x19, 0xe6, 0x4f, 0xb0, 0xfa, 0x9a, 0x27, 0xb6, 0xd9, 0x85, 0x63, 0x4c, + 0xa9, 0xd7, 0xd9, 0x11, 0xeb, 0xa7, 0x74, 0x61, 0x8b, 0xb5, 0x31, 0xa4, 0x6c, 0xc9, 0xd6, 0xb5, 0x45, 0xc8, 0x84, + 0x21, 0xeb, 0x3a, 0x52, 0x71, 0x03, 0xe7, 0x37, 0xe4, 0x02, 0x5e, 0xef, 0xe7, 0x5c, 0xa9, 0x67, 0x11, 0xcd, 0x32, + 0x41, 0xbb, 0x04, 0x72, 0xa4, 0xf3, 0xa2, 0xfe, 0xbf, 0x95, 0x10, 0xa2, 0x4b, 0x6b, 0xba, 0x2d, 0xa1, 0x4e, 0xf2, + 0xd9, 0x59, 0xb4, 0x80, 0xc7, 0x6e, 0x94, 0x1b, 0xe7, 0xb1, 0xb4, 0x09, 0x9e, 0x0d, 0x22, 0x81, 0x0d, 0xcb, 0x29, + 0x51, 0x0d, 0xab, 0xad, 0xee, 0x7a, 0x18, 0x9f, 0xdd, 0xde, 0x28, 0xc4, 0x50, 0x61, 0xf6, 0x77, 0xa0, 0xa4, 0xe2, + 0x5e, 0x97, 0xd4, 0x3a, 0x2a, 0xff, 0x1b, 0xa5, 0x0d, 0x41, 0xe1, 0x8b, 0x9b, 0x82, 0x1d, 0xdc, 0xeb, 0x9e, 0x1a, + 0x8a, 0xfd, 0xfd, 0x42, 0x85, 0x69, 0xa7, 0x0f, 0xca, 0x04, 0x4d, 0x78, 0x0b, 0x72, 0x39, 0xf2, 0xfd, 0x6c, 0x2a, + 0xbf, 0xc8, 0x2f, 0x7d, 0x7b, 0x6d, 0x08, 0x5b, 0xd1, 0x4a, 0x2b, 0x56, 0x47, 0xf9, 0x61, 0x78, 0x13, 0xb7, 0x45, + 0x06, 0x45, 0x7d, 0x5e, 0x63, 0xef, 0x90, 0xaa, 0xc4, 0x6e, 0x7b, 0xe2, 0x06, 0x61, 0x39, 0xe9, 0x12, 0x5c, 0x58, + 0x23, 0x11, 0xa3, 0xd4, 0x9c, 0xe1, 0x54, 0x8b, 0xda, 0xc2, 0x72, 0xae, 0xd5, 0x11, 0x15, 0x10, 0xaa, 0xef, 0xa9, + 0x52, 0xd6, 0xc0, 0xb0, 0x77, 0x9e, 0x86, 0xc1, 0xcb, 0xb1, 0xab, 0x6b, 0xe5, 0xe8, 0x34, 0x5d, 0xf7, 0xb4, 0x40, + 0x81, 0x36, 0xa5, 0xb7, 0x76, 0x59, 0x8e, 0xb7, 0xea, 0x02, 0x17, 0x43, 0x0b, 0x9e, 0x3b, 0xef, 0x00, 0xbe, 0x4a, + 0x1e, 0x29, 0x3c, 0x58, 0xba, 0x76, 0x05, 0xb4, 0x30, 0x99, 0x04, 0x1e, 0x9c, 0xc5, 0x5a, 0x25, 0x6b, 0x51, 0xe1, + 0x35, 0x21, 0x0c, 0xc8, 0x59, 0x1f, 0x6c, 0xbb, 0x31, 0x72, 0x89, 0xda, 0xeb, 0x47, 0x1a, 0x5a, 0x64, 0xfd, 0xa0, + 0x49, 0xcf, 0x03, 0x45, 0xe5, 0xa8, 0x7a, 0x77, 0xa7, 0x8c, 0xbe, 0xc4, 0x3c, 0x61, 0xd4, 0x27, 0x06, 0x8d, 0xf4, + 0x85, 0x3a, 0x22, 0xe4, 0xfc, 0xc4, 0x66, 0xcd, 0x57, 0xfb, 0xf0, 0x9e, 0x10, 0xc6, 0x6a, 0xd3, 0x91, 0xcf, 0x13, + 0x68, 0xcf, 0x96, 0xae, 0x5f, 0xd4, 0x90, 0xe1, 0xb5, 0xe9, 0x72, 0x48, 0xc6, 0x82, 0xa7, 0x66, 0x08, 0x83, 0x5a, + 0xc9, 0x38, 0x4d, 0xec, 0x73, 0x16, 0x26, 0xd2, 0x55, 0xb9, 0x86, 0x00, 0xd7, 0x2f, 0x9c, 0x49, 0xb3, 0xd8, 0x72, + 0x8b, 0x92, 0xd1, 0xa5, 0x26, 0xc4, 0x16, 0x4d, 0x44, 0x06, 0x00, 0xbd, 0x1c, 0xf6, 0x11, 0x90, 0xf0, 0x6d, 0xc2, + 0xb9, 0x79, 0x62, 0x4b, 0x1b, 0xd7, 0x5c, 0x50, 0x18, 0xee, 0xe8, 0xc9, 0x5e, 0x6c, 0x2a, 0x62, 0xcf, 0x60, 0x1e, + 0x9a, 0x8d, 0x65, 0x36, 0x7f, 0xe4, 0xa7, 0xe3, 0x50, 0x0c, 0xa4, 0xff, 0xc0, 0x82, 0xf8, 0x9f, 0xa1, 0x42, 0x5c, + 0x71, 0x41, 0xfe, 0x80, 0x2b, 0x69, 0xf8, 0x82, 0x74, 0x3b, 0x9d, 0xf9, 0xd9, 0xf4, 0xa9, 0x5a, 0x40, 0x50, 0x1e, + 0x08, 0x85, 0x34, 0x17, 0x90, 0xc6, 0x0b, 0x1c, 0x58, 0x2f, 0xec, 0x90, 0x04, 0xb6, 0x9e, 0x8e, 0x64, 0xd2, 0x48, + 0xa7, 0x78, 0xe0, 0x53, 0xbd, 0xb6, 0x3f, 0xd5, 0x31, 0xa5, 0x37, 0xe5, 0x69, 0xd3, 0x3c, 0x15, 0x0f, 0x3d, 0x6b, + 0xab, 0x08, 0x13, 0x06, 0x4f, 0x85, 0x13, 0x5e, 0xef, 0xe9, 0x5a, 0xbb, 0x86, 0xaf, 0xe0, 0x8b, 0x9e, 0x0d, 0xe6, + 0xc2, 0xe6, 0x5a, 0x24, 0xe8, 0x20, 0x4c, 0x17, 0x3e, 0x3e, 0xc2, 0xc8, 0x74, 0x29, 0xbd, 0xa2, 0x1f, 0x0d, 0x0a, + 0xc5, 0xdb, 0xf5, 0x87, 0xf6, 0x2e, 0x82, 0x83, 0xb3, 0x05, 0xd9, 0x98, 0x76, 0x07, 0x20, 0x0f, 0x69, 0x51, 0xd5, + 0x18, 0x23, 0xa4, 0x42, 0x1c, 0x43, 0xc4, 0xe9, 0xf6, 0x55, 0x5b, 0x1e, 0xba, 0xe5, 0x97, 0x3c, 0x23, 0xff, 0x5e, + 0xfc, 0x99, 0xf9, 0xae, 0x6f, 0xd0, 0x15, 0xd7, 0x79, 0x0e, 0xf1, 0xbd, 0xdf, 0xb5, 0x46, 0x42, 0x94, 0x84, 0x7f, + 0x0c, 0x1e, 0x20, 0x66, 0x3c, 0x58, 0x03, 0xf6, 0xbc, 0xba, 0x91, 0x93, 0xe0, 0xbe, 0x60, 0xe8, 0x6d, 0xf3, 0xb5, + 0x7e, 0x3c, 0x26, 0xf1, 0x16, 0x6d, 0x11, 0xbb, 0x52, 0x07, 0x33, 0x76, 0xe2, 0x9c, 0x0f, 0x93, 0xd9, 0x7f, 0x8c, + 0xb0, 0xc0, 0x11, 0x0a, 0x6a, 0x2d, 0xfc, 0xb2, 0x15, 0xc0, 0xad, 0xfe, 0x83, 0x91, 0x02, 0x37, 0xd1, 0x13, 0x3f, + 0xdb, 0x3d, 0xc5, 0x26, 0x38, 0x11, 0x7b, 0x45, 0x6c, 0xcf, 0x81, 0x5a, 0xad, 0x6a, 0x0a, 0xd5, 0xad, 0xd3, 0x41, + 0xe8, 0x62, 0x51, 0x98, 0xeb, 0x75, 0x14, 0xf8, 0xac, 0x5a, 0x56, 0x1d, 0x86, 0x6c, 0x57, 0xa1, 0xf6, 0x24, 0x1b, + 0x16, 0x25, 0x2a, 0x72, 0xe3, 0x78, 0x53, 0xac, 0x03, 0xea, 0xb7, 0x7a, 0x6d, 0x82, 0x5b, 0x2f, 0x78, 0x74, 0x2c, + 0xc8, 0xb5, 0x14, 0x31, 0x78, 0x82, 0xc8, 0xe0, 0x55, 0xb9, 0x40, 0x07, 0xbd, 0x74, 0x5f, 0x37, 0x1f, 0x5a, 0xe3, + 0xe9, 0x6e, 0x1a, 0x3e, 0xfb, 0xb9, 0xf7, 0xd6, 0x88, 0xed, 0x9a, 0x31, 0x32, 0x2e, 0x92, 0x16, 0x3d, 0x75, 0x8d, + 0xcb, 0x35, 0x98, 0x3d, 0xb4, 0x3a, 0x66, 0x98, 0xbf, 0x5c, 0x69, 0x31, 0xc6, 0xef, 0x44, 0x31, 0xed, 0x41, 0x37, + 0x2b, 0xc4, 0x3d, 0xbd, 0x60, 0xc0, 0x5a, 0x4b, 0xbc, 0x69, 0xf5, 0x56, 0x5b, 0x9f, 0x2d, 0xcb, 0x20, 0xfa, 0x46, + 0x53, 0xbe, 0x9b, 0x85, 0x2c, 0x97, 0x29, 0xd6, 0x68, 0x13, 0xf6, 0xe5, 0x72, 0x6f, 0x37, 0xb6, 0x95, 0xf1, 0x6f, + 0x51, 0xf5, 0x64, 0x48, 0x24, 0x2d, 0x51, 0x2a, 0x15, 0x38, 0xe9, 0xc2, 0x10, 0x6b, 0x3a, 0x6a, 0xb9, 0x4e, 0x82, + 0xf9, 0xbe, 0x3b, 0x75, 0x58, 0xfe, 0xf8, 0x9c, 0x17, 0x69, 0xe5, 0x93, 0x22, 0xf6, 0xd9, 0xe1, 0x62, 0x42, 0x39, + 0x85, 0x33, 0xb2, 0xfb, 0x6f, 0x78, 0xb5, 0x2b, 0x80, 0x9a, 0x60, 0xf4, 0x72, 0xc9, 0xd5, 0x50, 0x94, 0x7e, 0x3a, + 0x19, 0xa6, 0x20, 0xac, 0xaf, 0xd6, 0xc2, 0x6b, 0xaf, 0x48, 0x74, 0x89, 0xbf, 0x92, 0x5e, 0x1a, 0x82, 0xa4, 0xed, + 0x50, 0x5f, 0xd5, 0x25, 0x08, 0x74, 0x88, 0x57, 0x12, 0xe0, 0x66, 0xde, 0x82, 0x26, 0x13, 0x19, 0x17, 0x6f, 0x5c, + 0x00, 0x17, 0xc6, 0xdb, 0xa7, 0x1b, 0x48, 0xd6, 0x5a, 0x62, 0x27, 0xa1, 0x9b, 0x5e, 0x1a, 0x9c, 0x00, 0x09, 0x76, + 0x3c, 0x81, 0x26, 0xef, 0x84, 0xcf, 0x5c, 0xaf, 0x26, 0xa6, 0x20, 0x88, 0xe8, 0xde, 0x73, 0xb0, 0x9b, 0xeb, 0x59, + 0x56, 0xd8, 0x84, 0xd8, 0xec, 0xa8, 0xfa, 0x7e, 0xaa, 0xc0, 0xeb, 0xa5, 0x49, 0xc5, 0x46, 0xa1, 0xeb, 0xe4, 0x0e, + 0xc7, 0x01, 0xa6, 0xb3, 0xe4, 0x50, 0xc3, 0x95, 0x8f, 0x65, 0x39, 0x49, 0x09, 0x2d, 0x85, 0x03, 0xce, 0x40, 0x72, + 0xf0, 0x3f, 0x96, 0x74, 0x90, 0x75, 0xf8, 0x89, 0x69, 0x0b, 0xfe, 0x4c, 0x5a, 0xd3, 0xb4, 0x88, 0x56, 0x7b, 0x1d, + 0x6b, 0xd0, 0xbc, 0x4a, 0x9e, 0x4f, 0x0c, 0x60, 0xb3, 0x5a, 0xc8, 0xea, 0xc7, 0x5e, 0x5b, 0xfe, 0x48, 0xf9, 0x29, + 0x0b, 0xb5, 0xa7, 0x7a, 0x6c, 0x85, 0x64, 0xa7, 0x69, 0x51, 0x11, 0xc5, 0xf5, 0x64, 0xbb, 0x21, 0x7e, 0xf8, 0x22, + 0x11, 0x94, 0x4b, 0x05, 0xc4, 0x90, 0x00, 0x04, 0x83, 0x19, 0xd4, 0x90, 0xd0, 0x51, 0x5f, 0x6f, 0x9e, 0x8e, 0x7b, + 0x08, 0x34, 0x4f, 0x85, 0x02, 0x62, 0xba, 0x62, 0x76, 0xbe, 0x0b, 0xa8, 0xe2, 0xfd, 0x1b, 0x6c, 0x9b, 0x56, 0xdf, + 0xd6, 0xb4, 0xca, 0x4f, 0xd6, 0x7f, 0xd4, 0xb9, 0x29, 0xb0, 0x21, 0x36, 0xa8, 0x52, 0x24, 0xac, 0x32, 0x06, 0x88, + 0x46, 0xcf, 0xdc, 0x64, 0x9a, 0xc2, 0xfe, 0xee, 0x3c, 0x5d, 0xf5, 0x75, 0x6a, 0xf3, 0x5d, 0xcf, 0xa5, 0xc4, 0x12, + 0x2e, 0xb3, 0xd0, 0xc7, 0x72, 0x00, 0x64, 0xa6, 0x87, 0xa5, 0x83, 0x06, 0x5f, 0x83, 0x57, 0x57, 0x2c, 0x55, 0xd7, + 0xec, 0x7e, 0xc8, 0xf8, 0xeb, 0x9b, 0xf4, 0x8a, 0xde, 0xc9, 0xc8, 0x7c, 0x73, 0xaf, 0x77, 0xd7, 0xea, 0xfa, 0x85, + 0xf5, 0x8c, 0xba, 0x54, 0x2d, 0x4f, 0x7f, 0x6f, 0xf7, 0x7d, 0x71, 0x67, 0xed, 0x4f, 0x41, 0x19, 0xdb, 0x93, 0x7c, + 0xa0, 0x9a, 0x1b, 0xff, 0x02, 0xcd, 0x9b, 0x82, 0x5a, 0x46, 0xa6, 0xbc, 0xad, 0xfd, 0x92, 0x1b, 0xf2, 0xf6, 0x44, + 0xc6, 0x11, 0xe7, 0x8e, 0x21, 0xef, 0x4b, 0xdb, 0xf8, 0xdc, 0xeb, 0x08, 0x14, 0x7e, 0x79, 0x3a, 0xa5, 0x80, 0xd6, + 0x84, 0x4b, 0xc4, 0x11, 0x5a, 0x5e, 0x97, 0x2e, 0x8a, 0x41, 0xe4, 0xe8, 0x03, 0xd8, 0xd2, 0x86, 0xe0, 0xd3, 0x22, + 0xfc, 0x6c, 0x26, 0xd4, 0x93, 0xad, 0x40, 0xad, 0x88, 0x2a, 0x7b, 0x48, 0x56, 0x02, 0xcb, 0x89, 0xe4, 0xa4, 0x27, + 0x75, 0x26, 0x90, 0x60, 0xea, 0x15, 0xef, 0xbb, 0x60, 0xc8, 0x62, 0x97, 0x2b, 0x0c, 0x2c, 0xe2, 0x64, 0xa1, 0x7e, + 0xbd, 0x3c, 0x95, 0x46, 0x0b, 0x0c, 0x01, 0x4c, 0x73, 0x2f, 0x2f, 0x1b, 0x23, 0x9e, 0xfe, 0xee, 0x86, 0x4c, 0x17, + 0x78, 0xf0, 0xcd, 0x8b, 0x9b, 0xd4, 0x52, 0x80, 0x9e, 0x9b, 0xfc, 0x6e, 0xa4, 0x9d, 0xc8, 0x09, 0xa9, 0xcd, 0x19, + 0x0e, 0x01, 0xaa, 0x9a, 0x3d, 0xc4, 0x5c, 0x2a, 0x65, 0x27, 0xae, 0x81, 0x2c, 0xbf, 0x89, 0xc0, 0x97, 0x6f, 0xe7, + 0xd8, 0x3b, 0x15, 0x95, 0xad, 0xd0, 0x0e, 0xa1, 0xa2, 0x36, 0xac, 0xee, 0xe6, 0xe1, 0x31, 0x47, 0xb0, 0xf3, 0x87, + 0x79, 0xdc, 0xd7, 0x0d, 0x8f, 0x10, 0x60, 0x05, 0xc2, 0x27, 0x04, 0x1f, 0x60, 0x88, 0x66, 0xba, 0xb5, 0xef, 0xef, + 0x55, 0x52, 0x55, 0x3c, 0x05, 0x38, 0x3e, 0xc0, 0xf0, 0xce, 0xd4, 0x63, 0xb3, 0x04, 0x9b, 0x79, 0x04, 0x86, 0x90, + 0x9b, 0xe6, 0x54, 0x53, 0x6e, 0x80, 0xf9, 0x2e, 0x62, 0x98, 0xe2, 0x91, 0xee, 0xd1, 0xf0, 0x01, 0xed, 0xc6, 0x9b, + 0x3b, 0x2f, 0xf0, 0xd3, 0x2c, 0x62, 0xd9, 0xf3, 0x64, 0x94, 0xc1, 0x27, 0x22, 0xdf, 0x22, 0x85, 0xcc, 0xfd, 0xc4, + 0x29, 0xac, 0xb6, 0x69, 0x7d, 0x51, 0x88, 0xdc, 0x5c, 0xdd, 0x98, 0x68, 0x0d, 0x5c, 0xa8, 0x4d, 0x54, 0x27, 0xd0, + 0xda, 0x66, 0x7b, 0xb8, 0xea, 0x4c, 0x24, 0x83, 0x27, 0xc2, 0xfc, 0x1b, 0xaf, 0xee, 0x64, 0xeb, 0x90, 0x8b, 0xd3, + 0xa3, 0x30, 0x57, 0x7b, 0x6b, 0xcf, 0x5b, 0xf7, 0x2d, 0x77, 0xd5, 0x9a, 0x3c, 0xa7, 0x45, 0x28, 0xb1, 0x93, 0x0c, + 0xa0, 0x08, 0xee, 0x9b, 0x41, 0xef, 0x3d, 0xd4, 0x89, 0x0c, 0x2e, 0x54, 0x31, 0xe3, 0xcc, 0x38, 0xca, 0xf3, 0x2b, + 0xae, 0x39, 0xb8, 0xfd, 0xbc, 0x71, 0x31, 0x10, 0xa0, 0xd0, 0x01, 0x99, 0xfa, 0x51, 0x99, 0xda, 0x9a, 0x26, 0xc7, + 0x7c, 0x05, 0x0b, 0x44, 0x86, 0x20, 0x00, 0x59, 0x78, 0xda, 0x56, 0xe9, 0x3e, 0x9e, 0x0c, 0x07, 0xca, 0x1b, 0x81, + 0x19, 0x19, 0x74, 0x10, 0xcd, 0x58, 0xdb, 0x99, 0x44, 0x44, 0x98, 0x84, 0x1b, 0x8b, 0x1a, 0xfe, 0xc5, 0x53, 0x52, + 0x3e, 0xe6, 0xa1, 0x87, 0x11, 0xd3, 0x62, 0x5e, 0x51, 0x7c, 0x49, 0x41, 0x3a, 0x97, 0x56, 0xdf, 0xb2, 0x4c, 0xce, + 0xa9, 0x97, 0xa1, 0xd0, 0x45, 0xc2, 0xa8, 0xb0, 0x49, 0x3d, 0x91, 0x01, 0x24, 0x63, 0x95, 0x19, 0xca, 0x15, 0x5e, + 0x8f, 0x2a, 0x79, 0x5c, 0xf2, 0x6f, 0xcc, 0xca, 0xb8, 0x1c, 0x5b, 0xd6, 0x0d, 0xeb, 0x1c, 0x1c, 0xaf, 0x54, 0xcb, + 0xe4, 0x9b, 0xa2, 0x38, 0xf1, 0xe2, 0x23, 0x06, 0xe2, 0xfd, 0xac, 0xde, 0x66, 0x9e, 0x7d, 0x58, 0xee, 0xda, 0xc2, + 0x95, 0x49, 0xc5, 0x20, 0x96, 0x30, 0x11, 0xb4, 0x28, 0x8d, 0xdf, 0x71, 0x30, 0xc5, 0x29, 0x40, 0x1b, 0x0b, 0xdf, + 0x1b, 0x49, 0x55, 0xe5, 0xb0, 0x5c, 0x46, 0x6f, 0xa5, 0xa8, 0xb3, 0x59, 0x5e, 0x46, 0x9b, 0x79, 0x12, 0x10, 0xe0, + 0xea, 0x4c, 0x59, 0xcd, 0x6e, 0x0e, 0x1d, 0x86, 0x33, 0xac, 0x2c, 0xe5, 0x84, 0x29, 0x9a, 0x35, 0x96, 0x12, 0x61, + 0xdc, 0x66, 0xb7, 0x2f, 0x8e, 0xdf, 0xd5, 0x72, 0x67, 0xfa, 0x0d, 0xdc, 0xe5, 0xae, 0x59, 0x40, 0x78, 0xe0, 0x11, + 0x9d, 0x93, 0xcb, 0x80, 0xaf, 0x8c, 0xea, 0x0d, 0x1a, 0xb0, 0x25, 0xeb, 0xa5, 0xf9, 0x58, 0x95, 0x87, 0xbe, 0x8a, + 0x5d, 0xbc, 0xd4, 0x25, 0xb4, 0x3a, 0xd4, 0xfa, 0xb0, 0xb7, 0xff, 0xb4, 0x57, 0xed, 0x34, 0xa0, 0x03, 0x62, 0x5f, + 0xeb, 0xf1, 0x65, 0x97, 0xff, 0xd5, 0x1f, 0xb7, 0x45, 0xa2, 0xed, 0x94, 0xba, 0x81, 0x0a, 0x41, 0xee, 0x40, 0xb0, + 0x95, 0xce, 0x67, 0xe5, 0x38, 0xe8, 0x85, 0x25, 0xa1, 0x16, 0x5e, 0x97, 0x97, 0x4a, 0xf0, 0x60, 0x4a, 0x49, 0xac, + 0x71, 0xaf, 0x37, 0x87, 0x01, 0x7d, 0xb8, 0xc5, 0x5a, 0x4d, 0x4c, 0x7f, 0x42, 0x54, 0x99, 0x48, 0x0f, 0x6c, 0x2f, + 0x9a, 0x98, 0xf0, 0xb0, 0x1f, 0x54, 0xa4, 0x84, 0xea, 0x40, 0xd0, 0x06, 0xca, 0xc4, 0x1c, 0x5f, 0x76, 0x28, 0x79, + 0x2e, 0xb4, 0xc0, 0x27, 0x06, 0xfb, 0x8e, 0xab, 0xb1, 0x50, 0xb1, 0x03, 0xc9, 0x31, 0x65, 0x0e, 0x37, 0xd8, 0x22, + 0xf6, 0x27, 0xd5, 0x40, 0xe9, 0xaf, 0xc6, 0x75, 0xdf, 0x56, 0x01, 0x94, 0xba, 0xe6, 0xc7, 0x7d, 0x8d, 0x42, 0x0f, + 0x16, 0xf1, 0x76, 0x08, 0xcf, 0x64, 0xbb, 0xa6, 0x22, 0xd6, 0x7c, 0x96, 0xec, 0xb9, 0x61, 0xc3, 0xdf, 0x57, 0x04, + 0x32, 0x46, 0x9a, 0x0e, 0x65, 0x6c, 0xc6, 0x2f, 0x65, 0x14, 0x53, 0x84, 0x7d, 0xe1, 0x77, 0x92, 0x10, 0x21, 0x42, + 0xc6, 0x30, 0xcd, 0x11, 0xb4, 0x33, 0x9f, 0x27, 0xb5, 0x40, 0x75, 0x4d, 0x42, 0xdf, 0xd3, 0xc3, 0x8a, 0x78, 0x90, + 0xa3, 0x47, 0x25, 0x00, 0xea, 0xbf, 0xc5, 0xbd, 0x27, 0x59, 0x31, 0x82, 0xb4, 0xe2, 0x44, 0x1a, 0x57, 0xe0, 0x38, + 0xc7, 0x27, 0x2d, 0x24, 0x88, 0x97, 0xea, 0x4e, 0x42, 0x5f, 0xb4, 0x71, 0x6a, 0xf0, 0x02, 0xb9, 0x28, 0x56, 0x2a, + 0x00, 0xb5, 0x5b, 0xf0, 0x66, 0x09, 0x33, 0x66, 0x48, 0x8f, 0xbc, 0x07, 0x6b, 0x1e, 0xf2, 0x52, 0x2e, 0x8f, 0x39, + 0x39, 0x87, 0xa8, 0xb9, 0x28, 0x92, 0x1a, 0x73, 0x05, 0x7d, 0x0d, 0x8a, 0x53, 0xe8, 0x63, 0x4c, 0xac, 0x36, 0x4f, + 0x7d, 0xaa, 0x86, 0xa2, 0xf4, 0x6c, 0x56, 0x17, 0xeb, 0x88, 0x2d, 0xb0, 0x0b, 0xcd, 0x18, 0x82, 0x5f, 0xc9, 0x24, + 0x87, 0x83, 0xb4, 0x4c, 0x04, 0x1d, 0x95, 0x17, 0x43, 0x27, 0x33, 0xda, 0xbb, 0xf4, 0x84, 0x3b, 0x7a, 0x28, 0x39, + 0x7d, 0x81, 0xd2, 0x43, 0x08, 0xd0, 0x5f, 0x8d, 0x68, 0xdc, 0xfe, 0x0a, 0x27, 0xc5, 0x8b, 0x09, 0x1f, 0x24, 0x51, + 0x84, 0x87, 0x70, 0x46, 0x14, 0x32, 0x12, 0xed, 0x43, 0xc1, 0xcc, 0x3b, 0xdb, 0xd6, 0x94, 0xf7, 0x45, 0x9d, 0x3a, + 0xcd, 0xc1, 0xcb, 0xf7, 0xe2, 0xb5, 0x5c, 0x4e, 0x3d, 0x7a, 0xec, 0xcb, 0x96, 0x90, 0x9d, 0x07, 0x00, 0x02, 0xe4, + 0x8b, 0x1d, 0x32, 0x26, 0x68, 0xc3, 0x9a, 0x96, 0x64, 0x4d, 0x3f, 0x5a, 0x84, 0x7e, 0x54, 0x7d, 0x9c, 0x66, 0x99, + 0x90, 0x6a, 0x0b, 0x63, 0x40, 0x84, 0x9e, 0x2a, 0x94, 0x60, 0x45, 0xee, 0x83, 0x97, 0xb8, 0x9a, 0x00, 0xdb, 0xb6, + 0x18, 0x9e, 0xb4, 0x37, 0x43, 0x60, 0x3b, 0x22, 0xa0, 0xd3, 0x0c, 0x89, 0x42, 0x6c, 0xb8, 0x8f, 0xd1, 0x4c, 0x52, + 0xc1, 0x98, 0x26, 0x2a, 0x1f, 0xfc, 0x07, 0xb5, 0x11, 0x37, 0x69, 0xaf, 0xe2, 0x79, 0x84, 0x3d, 0xc7, 0xa1, 0xeb, + 0xc2, 0x65, 0x40, 0x54, 0xd9, 0x72, 0x59, 0x73, 0x3d, 0x5a, 0x9e, 0x91, 0x41, 0x95, 0x48, 0xfd, 0x85, 0x5b, 0x07, + 0x95, 0x06, 0xd4, 0xb3, 0xf8, 0x64, 0xe0, 0xb9, 0x25, 0xb4, 0xdc, 0x9f, 0x23, 0x89, 0x07, 0xe0, 0xd4, 0xa3, 0x39, + 0xc2, 0x4b, 0x77, 0x87, 0x00, 0xf7, 0x56, 0x75, 0xbb, 0x69, 0x09, 0x28, 0x63, 0x27, 0xe1, 0xaa, 0xad, 0x52, 0x92, + 0x5a, 0x83, 0x12, 0xf3, 0xef, 0xf2, 0x4b, 0x3d, 0x76, 0x15, 0x1b, 0x96, 0x21, 0xd0, 0xb5, 0x42, 0xfd, 0xe5, 0x13, + 0xda, 0x49, 0xe1, 0xc6, 0xe1, 0x0d, 0xb2, 0x68, 0xf3, 0x11, 0xb5, 0x60, 0x2e, 0x50, 0x77, 0x5c, 0xd4, 0xbd, 0xf9, + 0x1b, 0xc1, 0x4d, 0x51, 0x53, 0xe8, 0x42, 0xc9, 0x46, 0x8f, 0x37, 0x12, 0x33, 0x40, 0x73, 0xb9, 0xd2, 0x0a, 0xcf, + 0xaa, 0x07, 0x6a, 0xbf, 0x21, 0x71, 0x6b, 0xbd, 0xbe, 0x0d, 0x1b, 0x3d, 0x44, 0xab, 0xc9, 0x82, 0x36, 0x46, 0x92, + 0xc7, 0xcc, 0xa1, 0xb5, 0x22, 0xd3, 0x35, 0x49, 0xb0, 0x2c, 0xa9, 0xf5, 0x6a, 0xd7, 0xf0, 0xf3, 0xb7, 0x3e, 0x40, + 0x58, 0x30, 0xb0, 0x5a, 0x49, 0xef, 0xb0, 0xdd, 0xca, 0xa5, 0x85, 0xab, 0x4d, 0xfe, 0x2c, 0x95, 0x43, 0x40, 0x9b, + 0x2c, 0xbf, 0xc4, 0xa5, 0xa7, 0x28, 0x88, 0xd4, 0x69, 0xab, 0xab, 0x84, 0x84, 0x60, 0xa5, 0x52, 0x3f, 0x1d, 0x98, + 0x90, 0x23, 0x2a, 0x47, 0x64, 0xf7, 0xba, 0x9c, 0xf3, 0x53, 0x03, 0xd2, 0xdd, 0x88, 0x48, 0xc8, 0xe9, 0x8d, 0x01, + 0x5c, 0x16, 0x1a, 0xfb, 0xdb, 0x80, 0x2b, 0x7c, 0x88, 0xe0, 0xb4, 0xef, 0x4a, 0xb9, 0x2e, 0x82, 0xfb, 0xbe, 0x40, + 0x8a, 0xaa, 0x22, 0x82, 0x05, 0xd5, 0x8e, 0x6c, 0xce, 0x8e, 0xfc, 0xc6, 0x8c, 0x02, 0xe7, 0xe6, 0x78, 0xd7, 0x28, + 0x42, 0xe9, 0x62, 0xe7, 0xbe, 0x62, 0x20, 0x4a, 0x12, 0x3e, 0x3b, 0x46, 0x68, 0xad, 0x75, 0x3e, 0xf1, 0x7e, 0xc0, + 0xb3, 0x24, 0x9c, 0x7f, 0x60, 0x93, 0xf7, 0xa5, 0x38, 0x2f, 0xaf, 0x36, 0x75, 0x5b, 0x30, 0x02, 0x50, 0x5f, 0x78, + 0xde, 0x56, 0x1e, 0xdc, 0x60, 0x64, 0x90, 0x27, 0x73, 0x81, 0xf1, 0xcc, 0xd5, 0x60, 0x9e, 0x1f, 0x3b, 0x2a, 0x04, + 0x2c, 0x04, 0xf2, 0x54, 0x53, 0x9b, 0xd6, 0x4a, 0x6c, 0xd1, 0x8e, 0xd9, 0x6f, 0xd9, 0x00, 0x27, 0xc0, 0xe9, 0x70, + 0xbc, 0xb4, 0x0d, 0xde, 0x90, 0x4b, 0x7a, 0x6b, 0x19, 0x05, 0xd9, 0x85, 0x7f, 0x1b, 0xb4, 0x06, 0xe5, 0x15, 0x08, + 0x15, 0x49, 0x1d, 0x1b, 0x25, 0xa5, 0x48, 0x1a, 0xa1, 0x65, 0xb6, 0x05, 0x59, 0x71, 0xb6, 0x47, 0x7c, 0xd5, 0xcc, + 0xe1, 0xa6, 0xc8, 0x6d, 0x91, 0xce, 0x1a, 0xee, 0x8b, 0x40, 0xc5, 0xa6, 0x90, 0x66, 0x5a, 0x23, 0xdb, 0xb8, 0x27, + 0xab, 0xb4, 0x77, 0x1b, 0x51, 0x33, 0x68, 0x44, 0xdf, 0xd2, 0x54, 0xf9, 0x7d, 0x2d, 0xaa, 0x97, 0x62, 0xa0, 0xcc, + 0x21, 0xa6, 0x6b, 0x5a, 0xc1, 0xa4, 0x4a, 0x2d, 0x8e, 0xf3, 0x36, 0x9f, 0x3e, 0x5c, 0x28, 0x87, 0xe4, 0xc0, 0x09, + 0x25, 0x47, 0x0c, 0xd9, 0x0a, 0x43, 0x70, 0x2b, 0x67, 0x13, 0xc9, 0x72, 0x23, 0x72, 0x99, 0x35, 0x46, 0x77, 0xfc, + 0x83, 0x05, 0xa0, 0xd0, 0x17, 0x1b, 0x14, 0xf4, 0x63, 0xad, 0xf5, 0x89, 0x3a, 0x52, 0x6a, 0x52, 0x7c, 0xba, 0x70, + 0x13, 0x95, 0x43, 0xcd, 0xd5, 0xab, 0xa2, 0x01, 0xb5, 0x26, 0x74, 0xc0, 0xf5, 0x08, 0x83, 0x0d, 0x84, 0xd1, 0x1f, + 0x4d, 0x21, 0x2c, 0xf7, 0x55, 0xdc, 0xb4, 0x9b, 0xbc, 0x7b, 0x3a, 0xdb, 0x63, 0xa4, 0x06, 0x15, 0x69, 0x59, 0x71, + 0x0c, 0xa7, 0x07, 0x9c, 0x83, 0xc7, 0x8e, 0x19, 0x36, 0x1b, 0xa7, 0xc7, 0x18, 0x03, 0x2c, 0x59, 0x61, 0xb1, 0x4d, + 0xa5, 0xb5, 0x22, 0x42, 0x6a, 0x9b, 0xd5, 0x4b, 0x9b, 0x3b, 0x45, 0x7e, 0xfb, 0x33, 0x00, 0xcc, 0xab, 0x26, 0xd3, + 0x3a, 0x8a, 0x29, 0x62, 0x94, 0xb4, 0x59, 0x1c, 0x2f, 0xc4, 0xca, 0x8b, 0x8f, 0x05, 0xee, 0x8f, 0x54, 0xb9, 0xb2, + 0xec, 0xb8, 0x3a, 0x93, 0xfb, 0xe1, 0xe6, 0x87, 0xcc, 0x49, 0xc4, 0x03, 0x16, 0xfa, 0x8c, 0xd9, 0x70, 0x75, 0xe2, + 0x1d, 0xa9, 0xc3, 0x2c, 0x26, 0xf7, 0xba, 0x78, 0xcb, 0xc7, 0xb9, 0x0b, 0xa8, 0xec, 0x41, 0xec, 0xb6, 0x2a, 0x63, + 0xbd, 0xce, 0xc8, 0x20, 0xe1, 0x5b, 0x2a, 0xf6, 0x4a, 0xc6, 0x4e, 0x7c, 0x06, 0x99, 0x1e, 0x2c, 0xc3, 0xc2, 0x53, + 0x46, 0x72, 0xfb, 0x4c, 0x15, 0xb5, 0xeb, 0x29, 0x95, 0xeb, 0xa2, 0x3b, 0xaf, 0xb9, 0xb7, 0x15, 0xee, 0xd4, 0xcc, + 0xa4, 0x13, 0xaf, 0x0b, 0x50, 0xe7, 0x83, 0x97, 0x16, 0xe9, 0x9c, 0x37, 0xb0, 0x6a, 0x85, 0xc2, 0x75, 0xa9, 0x46, + 0x9f, 0x5d, 0xee, 0xa3, 0x2d, 0x8e, 0x4d, 0x77, 0x7e, 0x5d, 0xf6, 0x68, 0xf2, 0x59, 0x87, 0x40, 0xec, 0x29, 0x22, + 0x3e, 0xa5, 0xc1, 0xad, 0x75, 0x98, 0x69, 0xab, 0xad, 0x0c, 0x54, 0x9b, 0xa4, 0x16, 0xf8, 0x49, 0x9b, 0xd2, 0xec, + 0x70, 0x6a, 0x79, 0xd7, 0x20, 0x96, 0xf8, 0x05, 0x0e, 0xab, 0x62, 0xf5, 0xec, 0xf1, 0x2d, 0xae, 0xac, 0x0c, 0x73, + 0xbf, 0x1e, 0x55, 0x0e, 0xb3, 0xb9, 0xe2, 0x78, 0x53, 0x1d, 0x91, 0x48, 0x6d, 0x3f, 0xf7, 0xf3, 0x27, 0x43, 0x45, + 0x8f, 0x83, 0x81, 0x38, 0x50, 0x55, 0xe4, 0x4c, 0x89, 0xb0, 0x0a, 0xa7, 0x25, 0x9a, 0x86, 0xc6, 0x3a, 0x14, 0x04, + 0x64, 0xd4, 0xff, 0x81, 0x70, 0x10, 0x99, 0xb7, 0x4e, 0x48, 0xaa, 0x2a, 0x35, 0x2c, 0xd1, 0x5e, 0xec, 0x7b, 0x48, + 0xe1, 0x21, 0x4f, 0xb6, 0x3e, 0x6f, 0xbf, 0xce, 0x91, 0x05, 0x0f, 0x04, 0xa3, 0x4c, 0x12, 0x03, 0x5b, 0x47, 0x97, + 0x7a, 0xd9, 0x8b, 0xbb, 0x4c, 0x40, 0x4f, 0x77, 0x1e, 0x7f, 0x84, 0x43, 0x51, 0xda, 0x9c, 0xbf, 0x6a, 0x49, 0x36, + 0xf3, 0xe8, 0xb6, 0x6a, 0xac, 0x43, 0x24, 0x36, 0x97, 0x1c, 0x2d, 0xe7, 0x45, 0x9e, 0x72, 0x74, 0xf9, 0x00, 0x8c, + 0x85, 0x77, 0xe7, 0x5c, 0x35, 0x17, 0x52, 0x4d, 0x5f, 0x1c, 0x13, 0xb8, 0x0e, 0x8f, 0xd8, 0x4a, 0xdb, 0x06, 0xeb, + 0xc1, 0x72, 0x88, 0xe7, 0xdc, 0x50, 0xae, 0x3f, 0xd4, 0x92, 0x6a, 0x52, 0xcf, 0x60, 0x1a, 0x2b, 0x75, 0x82, 0x26, + 0x65, 0xce, 0x2b, 0x9e, 0x3a, 0x98, 0x3a, 0x74, 0x93, 0x44, 0xf4, 0xd7, 0x91, 0x39, 0x91, 0xa4, 0x49, 0x3f, 0xb6, + 0x8d, 0x0a, 0x08, 0x80, 0x8e, 0x56, 0x08, 0x68, 0xf7, 0xbd, 0x5b, 0x7d, 0x26, 0xc9, 0x87, 0x67, 0x3d, 0x8a, 0xb9, + 0xd6, 0xd1, 0x56, 0xd7, 0xb0, 0x7c, 0x7b, 0x45, 0x18, 0xcd, 0xdb, 0x03, 0xb3, 0xc2, 0xd9, 0x88, 0x14, 0x63, 0xe7, + 0x2d, 0x20, 0x61, 0x1e, 0x22, 0xc7, 0xbb, 0x2e, 0x6a, 0xdc, 0x4a, 0xe7, 0xe8, 0xbc, 0x08, 0x4f, 0x9b, 0x2b, 0x16, + 0x4a, 0xd1, 0x4b, 0xe5, 0xd8, 0x6f, 0xde, 0x99, 0x51, 0x43, 0x5e, 0xf2, 0xb0, 0xf1, 0x7e, 0x94, 0xa7, 0xa7, 0x30, + 0x3a, 0x3f, 0xc4, 0x61, 0xee, 0x48, 0x5f, 0xa9, 0x03, 0xf4, 0x7a, 0x4f, 0x0e, 0xdf, 0xae, 0xef, 0x65, 0x27, 0x38, + 0x5c, 0x18, 0x2e, 0x8a, 0xf3, 0x05, 0xa9, 0x24, 0xe6, 0x28, 0xf5, 0x78, 0x51, 0x4f, 0xf1, 0x81, 0x78, 0xe5, 0x04, + 0xdb, 0x5e, 0xf6, 0xfd, 0xdf, 0x85, 0x33, 0x29, 0xbf, 0xef, 0x2e, 0x81, 0xaf, 0x07, 0x7f, 0xe8, 0xf6, 0x0b, 0x1c, + 0x89, 0xc8, 0x61, 0x1c, 0xee, 0xd8, 0x56, 0x71, 0xbd, 0x6f, 0xc3, 0x16, 0xa9, 0xd7, 0x1f, 0x27, 0x84, 0x5c, 0x37, + 0xe4, 0xa8, 0x3b, 0x28, 0xe2, 0x65, 0x09, 0x4c, 0xdc, 0x14, 0x42, 0x14, 0xe3, 0xbf, 0x5c, 0xcd, 0x53, 0x84, 0x5f, + 0x35, 0xa2, 0xb0, 0x55, 0x53, 0x53, 0x70, 0x57, 0x60, 0x00, 0x56, 0xf2, 0x04, 0x77, 0xa0, 0xe5, 0x43, 0x59, 0x78, + 0x85, 0x8e, 0xd5, 0xa2, 0xac, 0x04, 0x6a, 0x99, 0x21, 0x8f, 0x08, 0x4e, 0xd0, 0x5e, 0x84, 0x59, 0xd7, 0x30, 0x29, + 0xf7, 0x60, 0xf2, 0xb6, 0x6e, 0xe1, 0x75, 0xb7, 0xa9, 0xd3, 0xc3, 0xfb, 0x55, 0x69, 0xb1, 0xab, 0xb2, 0xc7, 0x03, + 0xe4, 0x28, 0x39, 0xbd, 0x03, 0x30, 0xe7, 0x61, 0x12, 0xd8, 0xea, 0xd2, 0x1c, 0xb6, 0x76, 0x97, 0xd0, 0x6f, 0x33, + 0x7c, 0xba, 0x43, 0x66, 0xa3, 0xa4, 0x9d, 0x7d, 0xfe, 0x53, 0x05, 0x8b, 0xa1, 0x37, 0x00, 0x9e, 0xb0, 0xee, 0x64, + 0xb5, 0xb0, 0x81, 0x7b, 0xfc, 0xd3, 0x87, 0xa6, 0x28, 0xa4, 0x25, 0xa6, 0xb1, 0x8b, 0xa3, 0x9a, 0x6c, 0xad, 0xf6, + 0x1a, 0x39, 0xbb, 0x21, 0x71, 0x55, 0x4a, 0x88, 0x2e, 0x47, 0xb4, 0x42, 0xb2, 0x47, 0x14, 0xc1, 0x6a, 0xef, 0x2c, + 0xdd, 0x46, 0x5f, 0xc3, 0x74, 0x05, 0x18, 0x4d, 0xc0, 0xb0, 0x41, 0xa5, 0xbd, 0x13, 0x00, 0x18, 0xa5, 0x55, 0x53, + 0xa7, 0xf4, 0x2e, 0x76, 0xd9, 0xe5, 0xe6, 0x41, 0xa6, 0xd4, 0x13, 0x35, 0x93, 0xdb, 0x03, 0x2a, 0x6b, 0x2d, 0x54, + 0xb2, 0x5f, 0x72, 0xc5, 0xa7, 0x51, 0x89, 0x56, 0xe8, 0x6a, 0x46, 0x07, 0xdd, 0x4c, 0xd1, 0x51, 0x22, 0xb6, 0x4c, + 0x4c, 0xbb, 0xf2, 0x66, 0x98, 0x78, 0xa9, 0xd8, 0x2a, 0x33, 0x22, 0x4d, 0xd9, 0xa2, 0x96, 0x23, 0xe2, 0xfc, 0xa8, + 0xbd, 0x66, 0x55, 0xa7, 0x36, 0xd6, 0x5a, 0x78, 0xba, 0x38, 0xc4, 0xe4, 0xea, 0x43, 0xb4, 0xdd, 0x07, 0x29, 0x38, + 0xd3, 0xa6, 0x8d, 0x2b, 0xb5, 0xcd, 0xbe, 0x88, 0x32, 0x5e, 0x91, 0x71, 0x11, 0xb3, 0xd9, 0xed, 0x93, 0xa5, 0x1d, + 0x26, 0xca, 0xe3, 0x98, 0x4c, 0x46, 0x0e, 0x54, 0xd2, 0x06, 0xaa, 0x25, 0xf7, 0x92, 0x15, 0x17, 0x71, 0xf1, 0xdf, + 0x68, 0xd9, 0xe6, 0xd9, 0xc2, 0xc0, 0x82, 0x16, 0x66, 0x89, 0x02, 0xb3, 0x54, 0x4a, 0x07, 0x25, 0x1c, 0x45, 0x64, + 0x27, 0x09, 0xd3, 0xcb, 0x92, 0x36, 0xf8, 0xa0, 0x91, 0xee, 0x4e, 0x26, 0x0d, 0x09, 0x97, 0x6b, 0x9c, 0xb5, 0x2d, + 0x26, 0x32, 0xe2, 0xa9, 0x6f, 0x4a, 0x26, 0xc2, 0x48, 0x3c, 0xc8, 0x94, 0x98, 0x0b, 0xcf, 0x06, 0x52, 0xe2, 0x8b, + 0x9c, 0x7e, 0xae, 0x17, 0xb3, 0xd1, 0x22, 0x8d, 0xfe, 0xa1, 0xe7, 0x97, 0xc5, 0xce, 0x6e, 0x47, 0x8c, 0x7a, 0x7b, + 0x5c, 0x79, 0x56, 0x53, 0x6b, 0xd7, 0x8c, 0x1c, 0x33, 0x06, 0x34, 0x52, 0x08, 0x14, 0xd2, 0x27, 0x23, 0x9c, 0x16, + 0x97, 0x03, 0x1b, 0x36, 0xbe, 0x53, 0x8e, 0x67, 0x0a, 0xb7, 0x17, 0x43, 0xc3, 0x73, 0x87, 0x44, 0x10, 0xa1, 0xf1, + 0x06, 0x67, 0xce, 0x50, 0xff, 0xe1, 0xe9, 0xbc, 0x35, 0xd7, 0xfd, 0x0f, 0x8a, 0x9e, 0xa5, 0x45, 0x44, 0x80, 0xf3, + 0x45, 0x45, 0x9a, 0xdb, 0x7b, 0x27, 0x8b, 0xac, 0xc7, 0x37, 0xcd, 0xfa, 0x15, 0x01, 0xdc, 0x49, 0x02, 0x42, 0x80, + 0x86, 0xd7, 0xf5, 0x7c, 0x38, 0x4b, 0x58, 0x1e, 0x60, 0xba, 0xab, 0xe0, 0xef, 0xc4, 0x4d, 0xce, 0x4b, 0x13, 0xfa, + 0xb1, 0xa8, 0xe0, 0x83, 0x9d, 0x2c, 0x10, 0x6e, 0x01, 0x96, 0x10, 0x04, 0x82, 0x92, 0x99, 0x29, 0xa6, 0x12, 0xfa, + 0x0b, 0x29, 0x21, 0x43, 0x02, 0x4c, 0x47, 0xe3, 0x82, 0x1b, 0x24, 0xd5, 0x46, 0x3c, 0xad, 0x62, 0x36, 0x9c, 0x34, + 0x0c, 0x88, 0xf5, 0xc7, 0x30, 0xd8, 0x2a, 0x26, 0xc9, 0xb0, 0xbf, 0xb3, 0x37, 0x9e, 0x0c, 0xa7, 0x4b, 0x14, 0x72, + 0xb1, 0xcf, 0x98, 0x3c, 0xa1, 0xe9, 0x17, 0x85, 0xa8, 0x2f, 0xeb, 0x82, 0xd3, 0x7b, 0x76, 0x74, 0x07, 0x4f, 0xae, + 0x32, 0xd2, 0xdb, 0x38, 0xb0, 0xdc, 0x42, 0x22, 0xc0, 0xbc, 0xdf, 0x03, 0xcd, 0x48, 0x32, 0x64, 0x28, 0x03, 0xcc, + 0x35, 0x66, 0x4f, 0x0d, 0x4d, 0x0f, 0x65, 0x47, 0x72, 0x6d, 0x12, 0xac, 0x1e, 0xe6, 0xbe, 0xbc, 0xb2, 0x6e, 0x73, + 0xbd, 0x03, 0xb9, 0x6e, 0x6b, 0x08, 0xd8, 0xe5, 0x88, 0x34, 0xa7, 0x26, 0xb7, 0x09, 0xd5, 0x03, 0x14, 0x48, 0x35, + 0xd5, 0xb4, 0x0e, 0x0e, 0x37, 0x7c, 0xd0, 0x01, 0xe1, 0x26, 0xc4, 0x46, 0xe5, 0x11, 0x7a, 0xad, 0xc6, 0x3e, 0xd1, + 0xd7, 0x92, 0x6b, 0x9a, 0x6f, 0x90, 0x3a, 0x72, 0xa9, 0xea, 0x3c, 0x4e, 0xd4, 0xb5, 0xb6, 0xda, 0x82, 0x2d, 0xc2, + 0x00, 0x8b, 0x55, 0x0c, 0x87, 0xe8, 0x54, 0xa8, 0x68, 0x89, 0x7b, 0x1b, 0x73, 0xd5, 0xcb, 0x9d, 0xb7, 0x55, 0x97, + 0x7a, 0xa7, 0x06, 0x8d, 0xc8, 0xf4, 0x50, 0x01, 0x0e, 0x84, 0x8c, 0xb5, 0x7d, 0xb0, 0x8c, 0xe3, 0x8c, 0x54, 0x65, + 0xd8, 0x08, 0x46, 0xd3, 0x01, 0xca, 0x5a, 0xf5, 0x38, 0x9c, 0x03, 0x62, 0x79, 0x48, 0x6e, 0x9a, 0xcc, 0x10, 0xd9, + 0x22, 0x9b, 0x5f, 0x6a, 0xf2, 0xe4, 0x0a, 0x1d, 0x0d, 0xfb, 0x1e, 0xd0, 0xae, 0xee, 0xc0, 0x40, 0x76, 0xf8, 0xaa, + 0x93, 0xce, 0x72, 0x09, 0xb4, 0x39, 0x86, 0xce, 0x85, 0xc5, 0x29, 0x9f, 0xa7, 0x23, 0x1b, 0xee, 0x1d, 0xe0, 0x45, + 0x47, 0xd7, 0x0b, 0xf0, 0xdb, 0xc1, 0xc5, 0x1d, 0x63, 0x0f, 0x6e, 0xca, 0xa3, 0x2c, 0x3b, 0x95, 0x30, 0x95, 0x47, + 0x13, 0x17, 0xeb, 0x9c, 0x0b, 0x5d, 0xce, 0xe6, 0x75, 0xba, 0xf5, 0x27, 0x2a, 0x86, 0x9b, 0xb5, 0x73, 0x06, 0xcf, + 0x55, 0x4e, 0x87, 0x24, 0x62, 0x49, 0x8b, 0x73, 0xf4, 0x85, 0x44, 0x9e, 0xd6, 0xf9, 0xfd, 0x42, 0x81, 0xce, 0xa9, + 0x83, 0x6a, 0x1d, 0xe3, 0xcc, 0x4e, 0x0f, 0x3a, 0xef, 0x95, 0xc6, 0xa2, 0xb1, 0x4a, 0x59, 0xf1, 0x1f, 0x38, 0xb7, + 0xf4, 0xf6, 0x84, 0xb0, 0x49, 0x2a, 0xa4, 0x50, 0x96, 0x09, 0xb7, 0x3d, 0x0e, 0x34, 0x6d, 0xe7, 0x44, 0x76, 0x5b, + 0xdf, 0xbe, 0x93, 0x24, 0x22, 0x71, 0xdb, 0x0b, 0xa2, 0xf0, 0x0c, 0xd0, 0x18, 0x92, 0xb3, 0xe7, 0x9d, 0x75, 0xf9, + 0xd2, 0xcb, 0x72, 0xbc, 0xc2, 0xde, 0x15, 0x83, 0xb1, 0xb0, 0x42, 0x0b, 0x0b, 0x37, 0x0d, 0xd4, 0xb1, 0x93, 0x24, + 0x76, 0x59, 0x12, 0x3f, 0xb6, 0xfc, 0x33, 0x69, 0x6e, 0x44, 0x9e, 0x8a, 0x8e, 0x75, 0xc8, 0x3e, 0x73, 0xaa, 0x54, + 0xf7, 0x5a, 0xe5, 0x41, 0x39, 0xe6, 0xa9, 0x1a, 0x31, 0x67, 0x6e, 0x33, 0x45, 0x3e, 0x92, 0x3e, 0x6f, 0xae, 0x67, + 0x94, 0x28, 0x10, 0xa9, 0x0b, 0xbd, 0xca, 0x9c, 0xab, 0xd0, 0x91, 0x42, 0x4a, 0xb7, 0x46, 0xb3, 0x89, 0x39, 0x0e, + 0x67, 0x3f, 0x55, 0xd9, 0x13, 0x7c, 0xed, 0x3d, 0x6f, 0xed, 0xc3, 0x66, 0x83, 0xeb, 0x50, 0xf3, 0x21, 0x3d, 0x60, + 0xa6, 0x99, 0x3b, 0x53, 0x20, 0x0b, 0xdb, 0xaf, 0xec, 0x48, 0x94, 0x32, 0xfd, 0x63, 0xa3, 0x75, 0x7d, 0xd9, 0x47, + 0x75, 0x4c, 0xfe, 0xfd, 0x2d, 0x5d, 0xc3, 0x55, 0x07, 0x45, 0x8e, 0xe1, 0x58, 0xd1, 0x6e, 0xa5, 0x3b, 0x00, 0xe1, + 0x35, 0x3b, 0x8c, 0xdc, 0x72, 0x36, 0x45, 0xbd, 0x55, 0x57, 0xc1, 0x02, 0x6a, 0xd4, 0x91, 0x94, 0xbd, 0x51, 0x58, + 0x44, 0xfd, 0x9a, 0x5d, 0x8b, 0x2b, 0x8a, 0x6e, 0x59, 0xe3, 0x7e, 0xc8, 0xec, 0xa8, 0x3f, 0xe2, 0x5a, 0xb9, 0xc3, + 0x0c, 0xd9, 0xe1, 0x1a, 0x53, 0x48, 0xea, 0x8d, 0xc6, 0xcd, 0xb6, 0xd5, 0xf3, 0x4c, 0xc3, 0xb8, 0x6d, 0xcd, 0xd2, + 0x26, 0x76, 0x50, 0x0d, 0xb7, 0x75, 0xc1, 0x54, 0xb5, 0x5d, 0xf8, 0xfa, 0xd5, 0x6e, 0x25, 0xb2, 0x26, 0xb4, 0xe1, + 0x68, 0x6b, 0x60, 0x9a, 0x16, 0xf9, 0x5c, 0xf4, 0xec, 0x6a, 0xb0, 0xc5, 0xbe, 0x0b, 0xd9, 0xbc, 0xfb, 0x6b, 0x95, + 0x84, 0x2a, 0xb9, 0x72, 0x1f, 0x97, 0xe4, 0x27, 0x9d, 0xac, 0xc2, 0x33, 0xb5, 0x8d, 0xfc, 0x0e, 0x27, 0xda, 0x87, + 0x95, 0xe6, 0x69, 0x25, 0xb3, 0x10, 0x10, 0x85, 0xae, 0xf0, 0x2a, 0x04, 0xba, 0x05, 0x0b, 0xff, 0x07, 0x3a, 0x76, + 0x65, 0x5c, 0x0a, 0xe9, 0x8d, 0xca, 0x39, 0x74, 0x43, 0x42, 0x3e, 0xb4, 0xb0, 0x9c, 0x9c, 0x97, 0x1a, 0x74, 0xb5, + 0x35, 0x74, 0x64, 0x79, 0x20, 0x02, 0xfc, 0x44, 0x0e, 0x79, 0xa6, 0x26, 0xd8, 0xfd, 0x24, 0x70, 0x96, 0x66, 0xb3, + 0x08, 0xbf, 0x18, 0x70, 0x86, 0xa4, 0xf6, 0x9e, 0x7e, 0xf9, 0x14, 0x68, 0x0f, 0xbf, 0x5c, 0x68, 0x7d, 0x72, 0x66, + 0xce, 0x51, 0x4b, 0xc7, 0x0d, 0x1c, 0xc2, 0x45, 0x69, 0xc0, 0xf7, 0x48, 0x35, 0x86, 0x29, 0x22, 0x4c, 0x0e, 0xe0, + 0x5c, 0xb9, 0x6d, 0x78, 0x56, 0x6e, 0x02, 0x33, 0x1d, 0x29, 0xa5, 0x15, 0xc7, 0xa8, 0xfb, 0xb6, 0xf7, 0xa3, 0x24, + 0xe9, 0xcd, 0xc7, 0xcb, 0xac, 0x50, 0xfa, 0x9e, 0x99, 0x85, 0xae, 0xe2, 0x77, 0x26, 0xb9, 0xab, 0x4b, 0xe8, 0xa4, + 0x5a, 0xce, 0x80, 0x51, 0xae, 0x56, 0x58, 0xee, 0x84, 0x40, 0x0e, 0x9b, 0xfb, 0xe9, 0x66, 0x90, 0x26, 0x5b, 0x51, + 0x95, 0x18, 0x23, 0x52, 0x68, 0xbf, 0xd9, 0x9d, 0xfb, 0xa3, 0xd5, 0x0c, 0x3a, 0xea, 0x3b, 0x66, 0x5c, 0xcd, 0xb7, + 0x62, 0xbb, 0xd8, 0xb0, 0x83, 0x69, 0x14, 0x75, 0x98, 0xe6, 0x01, 0x42, 0xf7, 0x2c, 0x1d, 0xa8, 0x5f, 0x10, 0x9f, + 0xf2, 0x76, 0x55, 0x6d, 0x1d, 0xe4, 0x62, 0xa6, 0xa2, 0x7c, 0x8a, 0x1a, 0x14, 0xb0, 0x68, 0xdd, 0x2e, 0x4d, 0xc0, + 0x14, 0x59, 0x48, 0xb7, 0x90, 0x82, 0x28, 0x59, 0x08, 0x66, 0x50, 0xf1, 0x99, 0xbf, 0x4c, 0x7c, 0xad, 0x8f, 0x16, + 0x3c, 0xa5, 0x27, 0x6c, 0x15, 0x72, 0x75, 0xc7, 0x68, 0x31, 0xab, 0x4e, 0x3b, 0x4e, 0x13, 0x87, 0x0e, 0x35, 0xea, + 0x88, 0xd8, 0x75, 0x7c, 0xf0, 0x54, 0x32, 0x79, 0x83, 0xec, 0x2f, 0x27, 0x01, 0x3f, 0xd6, 0xb3, 0x5f, 0x32, 0x7b, + 0x88, 0x55, 0x69, 0xc6, 0xe3, 0x85, 0xb2, 0x47, 0xe5, 0xa8, 0xa8, 0x35, 0xf6, 0x73, 0x17, 0xa7, 0xb5, 0x51, 0x49, + 0x21, 0x77, 0x1e, 0x2e, 0xe4, 0x2b, 0xa7, 0x70, 0xee, 0x46, 0x25, 0xa2, 0x3c, 0x80, 0x99, 0xb0, 0x39, 0x71, 0xa3, + 0xe2, 0x16, 0x50, 0x39, 0xd3, 0x93, 0x26, 0x31, 0x9d, 0x95, 0x88, 0x31, 0xa3, 0x4b, 0xb8, 0x1e, 0x87, 0x68, 0x0c, + 0xcd, 0x30, 0xa7, 0xf7, 0x31, 0x7a, 0x82, 0x1c, 0x50, 0x0f, 0xed, 0x5a, 0x43, 0x88, 0x99, 0x54, 0xf8, 0x56, 0xad, + 0x88, 0x2d, 0xb3, 0x4f, 0x04, 0xb5, 0x6d, 0x2e, 0xf3, 0x88, 0x28, 0x6f, 0x29, 0x7c, 0x9f, 0xfb, 0xcb, 0x77, 0x8c, + 0x57, 0x72, 0xe8, 0x9d, 0x8e, 0x92, 0x9f, 0xc3, 0xfc, 0xec, 0x37, 0x0e, 0x60, 0x01, 0x11, 0xe7, 0x92, 0x9c, 0x7a, + 0x4a, 0x96, 0xe6, 0x3a, 0xeb, 0x75, 0x13, 0xc1, 0x2c, 0x99, 0x06, 0x4c, 0xac, 0x65, 0x16, 0x40, 0x07, 0x52, 0x09, + 0x9c, 0x15, 0x95, 0x75, 0x34, 0x93, 0x47, 0x0b, 0xbd, 0x37, 0xf1, 0xf0, 0x45, 0x29, 0xc6, 0x02, 0xfc, 0xb1, 0xa5, + 0xc6, 0xa2, 0x4c, 0xdf, 0xbc, 0x08, 0x54, 0xcd, 0x5a, 0x1e, 0x87, 0x74, 0xe9, 0xf5, 0x8a, 0x9a, 0x55, 0x49, 0x6b, + 0xa9, 0x2e, 0xd0, 0x76, 0x40, 0x8e, 0x51, 0x8b, 0xea, 0x0c, 0xd2, 0x50, 0xb4, 0x07, 0x4a, 0x5f, 0xc3, 0x84, 0x1e, + 0xf0, 0x4b, 0x35, 0x90, 0xd9, 0xe0, 0x9d, 0x4d, 0xb7, 0xb8, 0x98, 0x1c, 0x39, 0xeb, 0x06, 0x10, 0x70, 0xbb, 0xde, + 0x96, 0x9a, 0x08, 0xa9, 0x70, 0x83, 0x71, 0x59, 0x24, 0xea, 0x2f, 0x9a, 0xc3, 0xda, 0x15, 0x92, 0x3a, 0xc4, 0x3a, + 0xb4, 0x30, 0x01, 0xad, 0x19, 0x17, 0x1b, 0x5a, 0x94, 0x9d, 0xc8, 0x81, 0xb5, 0x59, 0x24, 0x19, 0x87, 0x3d, 0x9a, + 0x69, 0x33, 0x91, 0x6b, 0x09, 0x9e, 0x4a, 0x44, 0x6f, 0xd1, 0xf4, 0xeb, 0x07, 0x15, 0x36, 0x37, 0x99, 0x54, 0xca, + 0x4c, 0x8f, 0x86, 0x40, 0xbb, 0x76, 0x07, 0x7c, 0x87, 0x0a, 0xfe, 0x12, 0x3e, 0x18, 0x45, 0xf7, 0xfb, 0xec, 0x69, + 0x07, 0x7c, 0x08, 0xa7, 0x4e, 0xfb, 0x45, 0x80, 0x75, 0x0e, 0x94, 0x62, 0x5d, 0x98, 0xe3, 0x8c, 0xa3, 0x76, 0x35, + 0xa3, 0x8d, 0xfd, 0xc4, 0x18, 0x02, 0x85, 0xc3, 0xb7, 0x3d, 0x5a, 0x79, 0xd5, 0xcc, 0xd6, 0x4c, 0x2f, 0x69, 0x47, + 0x3e, 0xa2, 0x46, 0x30, 0x09, 0x22, 0x69, 0x99, 0x40, 0x68, 0xc6, 0xe8, 0x2d, 0x5c, 0xc1, 0xda, 0x9c, 0x01, 0x2d, + 0x75, 0xbd, 0x50, 0xe8, 0x81, 0xa7, 0xe7, 0x4c, 0x4c, 0x0a, 0xf3, 0x01, 0x2e, 0x69, 0xff, 0xde, 0x1c, 0x66, 0x0d, + 0xd5, 0x6a, 0x6d, 0xb7, 0x65, 0x7d, 0x97, 0x28, 0x10, 0xb6, 0x1f, 0xda, 0x45, 0xf7, 0x23, 0x3f, 0xbb, 0x16, 0xa0, + 0xce, 0x62, 0xdb, 0x35, 0x9e, 0xf4, 0xd7, 0x5e, 0xb7, 0x04, 0x1f, 0xfb, 0x2b, 0x0d, 0x9f, 0x54, 0x0c, 0xcb, 0x92, + 0x09, 0xd3, 0x95, 0xe5, 0x18, 0x67, 0xa5, 0xb8, 0xcf, 0xcb, 0x98, 0x74, 0x77, 0x28, 0x31, 0x89, 0xaf, 0x3b, 0x1b, + 0xd0, 0xb7, 0x8c, 0xe8, 0x65, 0xfd, 0x56, 0xcf, 0xb0, 0xd7, 0x25, 0x80, 0x98, 0x7a, 0x45, 0xc5, 0x78, 0x98, 0xe8, + 0x8b, 0x87, 0xa0, 0x30, 0x7e, 0x94, 0xb9, 0x18, 0x7c, 0x52, 0x6f, 0x5b, 0x48, 0x84, 0x9f, 0xc6, 0xa3, 0xb8, 0x98, + 0xb5, 0x68, 0xd8, 0x76, 0x3d, 0x29, 0x0e, 0x84, 0x84, 0xd6, 0xcc, 0xa7, 0x49, 0x5a, 0x73, 0x29, 0x0c, 0xbf, 0x59, + 0x88, 0x8d, 0x66, 0xe3, 0x28, 0x5a, 0x0b, 0x60, 0x74, 0x55, 0x73, 0xc5, 0x62, 0xe0, 0x61, 0xc1, 0x43, 0xf9, 0xd2, + 0x12, 0x96, 0x3d, 0x7f, 0x9f, 0x4e, 0xe4, 0x9b, 0xbb, 0x9c, 0x6e, 0xbf, 0x77, 0x9d, 0xbd, 0xb9, 0x4b, 0x27, 0xca, + 0xea, 0x17, 0x1d, 0x95, 0xa8, 0xc6, 0xfa, 0xd8, 0xfa, 0x70, 0x97, 0x5b, 0xfd, 0x44, 0x72, 0xda, 0xd9, 0x0e, 0x18, + 0xb7, 0x14, 0xb0, 0x65, 0xda, 0x1e, 0x36, 0xe5, 0x3f, 0xde, 0xba, 0x38, 0xd2, 0x28, 0x48, 0x7c, 0xc2, 0x9c, 0x21, + 0x49, 0xf1, 0xd8, 0x64, 0x00, 0xa3, 0x96, 0x01, 0xf5, 0x08, 0xf6, 0x75, 0x63, 0x47, 0xbe, 0xb9, 0x8c, 0x71, 0xa9, + 0x4e, 0xbb, 0x0e, 0x64, 0xda, 0xe5, 0x21, 0xb0, 0x71, 0x9b, 0xbb, 0x1c, 0x28, 0x12, 0x07, 0x2a, 0x62, 0xa6, 0xfd, + 0x22, 0xf5, 0xa7, 0x1b, 0xc4, 0x46, 0xed, 0xc0, 0xf5, 0x39, 0xd8, 0x14, 0xfb, 0x64, 0xb1, 0xdf, 0xca, 0x3b, 0x3b, + 0xec, 0x8d, 0xf4, 0x47, 0x9c, 0x9b, 0xcf, 0x38, 0x30, 0xa2, 0x4a, 0x73, 0x31, 0x2b, 0x91, 0x2a, 0xb2, 0xa7, 0x95, + 0xef, 0x2f, 0xa4, 0x49, 0xe0, 0xdc, 0xad, 0x0f, 0x3d, 0x9c, 0xcc, 0x9e, 0x08, 0x93, 0x39, 0xe4, 0x3b, 0x78, 0x49, + 0x89, 0xa6, 0x0b, 0x8d, 0xb6, 0x5b, 0x07, 0x04, 0x76, 0x02, 0xe6, 0x69, 0x89, 0xbc, 0x4e, 0xc9, 0x4b, 0x7e, 0xff, + 0xf6, 0xcf, 0xd2, 0xb2, 0x80, 0xe1, 0xc8, 0x53, 0x5c, 0xa5, 0x00, 0x11, 0xc7, 0x71, 0xfe, 0x6a, 0xdd, 0x67, 0x24, + 0xc6, 0xfa, 0xf3, 0xbb, 0x1f, 0xec, 0x3e, 0x41, 0xae, 0xa4, 0xa1, 0xf0, 0xcc, 0xcd, 0x91, 0x9d, 0x83, 0xec, 0xca, + 0xb8, 0x62, 0xb7, 0x41, 0x3f, 0x89, 0x2c, 0x2a, 0xd1, 0x4c, 0xeb, 0xcd, 0x29, 0x16, 0x49, 0x49, 0x2b, 0x2c, 0x6a, + 0xc9, 0x17, 0x0c, 0xe5, 0x30, 0x59, 0x96, 0xb6, 0x9d, 0x39, 0x0e, 0xc5, 0x5a, 0x96, 0x00, 0xd9, 0xc5, 0x12, 0x9c, + 0x2b, 0x8a, 0x5c, 0x86, 0x95, 0x35, 0xb7, 0x02, 0xe3, 0xc0, 0x14, 0x7e, 0xf2, 0x8f, 0x12, 0xed, 0xef, 0x64, 0x58, + 0xb2, 0x8b, 0x3f, 0xa7, 0x2b, 0xf4, 0xda, 0xb9, 0x17, 0xcc, 0x60, 0x32, 0x44, 0xef, 0xb1, 0x84, 0x79, 0xb9, 0x13, + 0xaf, 0x4a, 0x96, 0xa5, 0x71, 0xe0, 0xa0, 0x59, 0x37, 0x6b, 0x75, 0xdf, 0x22, 0x48, 0xcb, 0x86, 0xab, 0x46, 0xac, + 0xb4, 0x12, 0x2a, 0xa1, 0x29, 0xe8, 0x88, 0x92, 0xbc, 0x44, 0x98, 0x19, 0x80, 0xb2, 0x93, 0x88, 0xca, 0x08, 0x82, + 0x63, 0x58, 0xb1, 0x98, 0x69, 0x5c, 0xd9, 0x80, 0xd5, 0xa9, 0xf1, 0x51, 0x1e, 0xba, 0x5e, 0xc0, 0x50, 0x7d, 0xed, + 0x4d, 0xc6, 0x39, 0xc6, 0xbc, 0xd6, 0x4c, 0x73, 0x72, 0xec, 0x7f, 0xdc, 0x55, 0x13, 0x24, 0x2d, 0xbe, 0x1f, 0xed, + 0x67, 0x0c, 0x4d, 0x33, 0x20, 0x96, 0x3d, 0x7c, 0xc2, 0x56, 0x07, 0x6c, 0xd2, 0x75, 0xd8, 0x48, 0x12, 0x25, 0xe8, + 0x4d, 0x9c, 0x66, 0xfb, 0x26, 0x80, 0xa1, 0xba, 0x34, 0xc8, 0x9e, 0x47, 0x46, 0xbc, 0x35, 0x96, 0x03, 0x4b, 0xbe, + 0x02, 0xba, 0xa0, 0x3c, 0xf3, 0x08, 0xce, 0xb6, 0x73, 0x20, 0x0a, 0x63, 0x2d, 0x8a, 0x4b, 0x9c, 0xf0, 0x3b, 0x92, + 0x43, 0x59, 0x32, 0x43, 0x61, 0xca, 0xe7, 0xe0, 0x5c, 0x99, 0x0f, 0x1f, 0xfe, 0x90, 0x7f, 0xfc, 0x4c, 0x57, 0x97, + 0x22, 0xf6, 0xf9, 0x71, 0x8e, 0xcf, 0xbf, 0x4d, 0x7a, 0xca, 0xed, 0x2c, 0xfc, 0x06, 0xde, 0x59, 0x42, 0xce, 0xbb, + 0x1f, 0x7e, 0xd4, 0x2d, 0x0e, 0x8a, 0x85, 0xce, 0x62, 0x8b, 0x5a, 0x70, 0xfe, 0xf9, 0x79, 0x31, 0x17, 0x55, 0x1e, + 0x13, 0x38, 0x53, 0x49, 0x59, 0xfd, 0xa6, 0x48, 0x81, 0xb4, 0x8d, 0x4a, 0xc2, 0xc6, 0xff, 0x18, 0x45, 0xf1, 0xff, + 0xa3, 0x0c, 0x85, 0x86, 0xac, 0xfd, 0xf1, 0x96, 0x45, 0x65, 0x83, 0xcd, 0xff, 0x98, 0x68, 0xad, 0x56, 0x9f, 0x09, + 0x50, 0x49, 0x5b, 0x49, 0xa5, 0x0f, 0x0a, 0x3c, 0xd3, 0xd1, 0xe4, 0x0c, 0x35, 0xc8, 0x88, 0x27, 0x8c, 0x33, 0x60, + 0x68, 0x9b, 0x75, 0xc9, 0xbb, 0x6d, 0x13, 0x7f, 0x8d, 0xc2, 0x9b, 0x32, 0xb5, 0xd1, 0x18, 0x24, 0xa7, 0x0a, 0x90, + 0xe6, 0x38, 0x5b, 0x85, 0xae, 0x68, 0xc3, 0x39, 0x37, 0x6b, 0x2d, 0x38, 0x1b, 0xc6, 0x56, 0xc3, 0x97, 0xbf, 0x20, + 0x41, 0x60, 0xd7, 0xa4, 0x0e, 0xaa, 0xb2, 0xe6, 0xc5, 0x4d, 0xf8, 0x27, 0x6c, 0x2f, 0x31, 0x98, 0xc9, 0x4b, 0x9a, + 0x77, 0xa6, 0x23, 0xa4, 0x79, 0x84, 0x9c, 0xd9, 0xfc, 0x8f, 0x62, 0x26, 0xcb, 0x43, 0x19, 0xcd, 0x7c, 0x98, 0x18, + 0xff, 0xe6, 0x49, 0x02, 0xfb, 0x99, 0xf3, 0x61, 0x14, 0x99, 0x58, 0x1e, 0xdb, 0xc6, 0x0b, 0x72, 0x1f, 0x43, 0x37, + 0x5a, 0xac, 0xb2, 0x2c, 0x63, 0x5f, 0x29, 0xb3, 0xb4, 0xb4, 0xe0, 0xf0, 0x74, 0x03, 0xa2, 0x0a, 0x9d, 0x0d, 0x21, + 0xcf, 0xa5, 0x7f, 0x59, 0xa5, 0xc2, 0xf4, 0xa1, 0xcc, 0x58, 0xeb, 0x2d, 0x10, 0x7b, 0x3d, 0x51, 0x7f, 0x72, 0x87, + 0x44, 0x9b, 0xdc, 0x68, 0xf9, 0xe0, 0x14, 0x56, 0x93, 0x74, 0x1e, 0x99, 0x88, 0x47, 0xf8, 0xce, 0xb6, 0x9f, 0xb7, + 0x4a, 0x7a, 0x7e, 0xf0, 0x11, 0x76, 0xbb, 0x34, 0xf6, 0x5e, 0xf2, 0x3b, 0xf9, 0x39, 0xfa, 0x30, 0xb8, 0x23, 0x27, + 0x25, 0xb5, 0xfd, 0xa1, 0x8f, 0x71, 0x1d, 0x28, 0xbb, 0xff, 0x41, 0xe3, 0x39, 0x64, 0x51, 0xf1, 0x68, 0x92, 0xce, + 0x30, 0x07, 0x4b, 0xfd, 0x30, 0x73, 0xe1, 0x6f, 0xd2, 0x04, 0x67, 0xd1, 0x8d, 0x5e, 0x1e, 0x4c, 0xeb, 0xc9, 0x3f, + 0x22, 0x2b, 0x7f, 0x9a, 0x65, 0x93, 0xc3, 0x69, 0xb8, 0xe0, 0x47, 0x32, 0xfa, 0xed, 0xac, 0x6e, 0x4f, 0x96, 0xad, + 0x5b, 0xed, 0x21, 0x60, 0xfa, 0x91, 0x86, 0x48, 0xde, 0x2c, 0x53, 0x85, 0x81, 0xa8, 0x18, 0x5c, 0xd0, 0x1a, 0x74, + 0x29, 0x35, 0xb5, 0x55, 0xe0, 0x8c, 0x4e, 0x04, 0x1d, 0x54, 0x70, 0xb4, 0x5c, 0xf9, 0xea, 0x07, 0x0d, 0x8b, 0x93, + 0x8a, 0xed, 0xb6, 0x28, 0x92, 0x3d, 0x83, 0xe3, 0x68, 0x11, 0x15, 0x99, 0xf1, 0xef, 0x32, 0x5a, 0x29, 0xa5, 0x54, + 0x82, 0xe0, 0x8e, 0xbe, 0xd0, 0xc5, 0x65, 0x94, 0x86, 0xfc, 0x90, 0x4a, 0xb6, 0xd0, 0x80, 0x4a, 0x29, 0x0e, 0x54, + 0x8d, 0xcb, 0x44, 0xb8, 0x32, 0x36, 0x17, 0x8d, 0x2b, 0x5a, 0x15, 0xaf, 0x62, 0x87, 0xf4, 0xfa, 0x3a, 0x51, 0x85, + 0x21, 0xcb, 0xc0, 0xe1, 0xe1, 0x1c, 0x65, 0xcd, 0x93, 0x6d, 0x28, 0xc9, 0x33, 0x15, 0x73, 0x30, 0xe3, 0x5c, 0x3d, + 0xa9, 0xc6, 0x06, 0x34, 0x54, 0x54, 0x67, 0x31, 0x9d, 0xad, 0x0e, 0xa8, 0x53, 0x02, 0x02, 0xb3, 0xf0, 0x18, 0x8f, + 0xa3, 0x10, 0x77, 0xa5, 0x0c, 0xbb, 0x70, 0x9b, 0x25, 0x58, 0x8f, 0x93, 0xe1, 0x70, 0x47, 0x1b, 0x3b, 0x17, 0x75, + 0xf8, 0x51, 0xb0, 0x4b, 0x31, 0x68, 0x48, 0x23, 0x24, 0xb9, 0xd8, 0x39, 0x75, 0x2c, 0x9a, 0x70, 0x27, 0x0b, 0x02, + 0x20, 0xf2, 0x30, 0xf5, 0xc1, 0xe2, 0xf2, 0xa8, 0xb3, 0x80, 0x89, 0x79, 0xae, 0xec, 0xa2, 0xbc, 0x81, 0xaf, 0xd6, + 0xa1, 0x1c, 0x62, 0x99, 0xc4, 0x58, 0x69, 0x33, 0xfe, 0x77, 0x59, 0x1e, 0xa5, 0x37, 0x96, 0xd5, 0xb4, 0x45, 0xf5, + 0xa0, 0xd1, 0x1d, 0xae, 0x1d, 0x31, 0x36, 0x96, 0x59, 0x27, 0x86, 0x05, 0xf3, 0xdf, 0x67, 0x86, 0xc5, 0x46, 0x55, + 0xcb, 0x37, 0x39, 0xdf, 0xbd, 0xe3, 0x53, 0x08, 0x66, 0x51, 0xc3, 0x03, 0xee, 0x1e, 0x96, 0x31, 0x2c, 0x16, 0x04, + 0xb3, 0xec, 0xc1, 0xc3, 0xba, 0x1a, 0x82, 0x34, 0xe3, 0x51, 0x92, 0x40, 0x37, 0x62, 0x28, 0x46, 0x72, 0x46, 0xc0, + 0x26, 0x29, 0xc4, 0xe0, 0x15, 0xb0, 0x3f, 0xd6, 0x25, 0xa4, 0x82, 0x23, 0x3c, 0x20, 0x1c, 0xaa, 0xb8, 0xfc, 0xb0, + 0x88, 0x61, 0x20, 0x86, 0x54, 0xbc, 0x98, 0x95, 0x4f, 0x0b, 0x80, 0x91, 0x35, 0xaa, 0x78, 0x48, 0x86, 0xc8, 0xc8, + 0x9b, 0x16, 0x19, 0x75, 0xf0, 0xc6, 0xf0, 0x1b, 0x11, 0x03, 0x5e, 0xc9, 0x19, 0xe4, 0x31, 0x27, 0x2b, 0x73, 0xf9, + 0x32, 0x77, 0xe9, 0xb7, 0xe3, 0xa9, 0x1c, 0xb7, 0xcd, 0x3c, 0xb4, 0xe9, 0x65, 0xac, 0x73, 0x51, 0x71, 0x70, 0xbd, + 0xcc, 0x31, 0xa2, 0xa7, 0xf9, 0xc2, 0xb5, 0x45, 0xf6, 0xb4, 0x86, 0xeb, 0xd7, 0x2a, 0xfb, 0xf0, 0x09, 0x19, 0x5b, + 0x40, 0x86, 0x87, 0x9d, 0xba, 0x6d, 0x64, 0x0c, 0x23, 0xf0, 0xdf, 0xc6, 0xf7, 0x13, 0xe7, 0x98, 0x2e, 0x73, 0x41, + 0x72, 0x98, 0x17, 0xf8, 0xb6, 0x30, 0xfe, 0x92, 0x73, 0x1c, 0x8d, 0xc9, 0xba, 0x87, 0x1a, 0xdd, 0xbd, 0xb4, 0xe1, + 0x0b, 0x26, 0xe8, 0xfc, 0x12, 0x1d, 0x5f, 0x93, 0x06, 0xcb, 0x7d, 0xde, 0xd7, 0x33, 0x64, 0x1a, 0x0f, 0x63, 0x4c, + 0xc8, 0x35, 0x9e, 0x33, 0xd1, 0x8d, 0x7a, 0xcf, 0x96, 0xb1, 0x96, 0xd8, 0x2a, 0xa2, 0xcd, 0x36, 0x58, 0x39, 0xaa, + 0xfe, 0xf5, 0x5d, 0x24, 0x82, 0x11, 0x35, 0xed, 0xd3, 0x5a, 0xdf, 0xa8, 0x3c, 0xf3, 0xdb, 0x99, 0x77, 0x1b, 0x56, + 0x86, 0x19, 0x04, 0x33, 0xbe, 0x62, 0xce, 0xd0, 0xcf, 0x23, 0x73, 0x0f, 0xbc, 0xdd, 0x4b, 0xef, 0xc6, 0x9a, 0x35, + 0xfa, 0x61, 0xba, 0x53, 0x92, 0x59, 0x60, 0x3b, 0xfe, 0x4d, 0xd0, 0x53, 0x21, 0xf5, 0xa3, 0x3a, 0xb0, 0xf8, 0x9a, + 0x93, 0x98, 0x90, 0x0c, 0x39, 0x58, 0x90, 0xab, 0xe6, 0xbd, 0xa7, 0xdb, 0xb6, 0x8c, 0x0a, 0x71, 0xe9, 0x74, 0xf5, + 0xe5, 0xf5, 0xda, 0x0b, 0xb4, 0xa3, 0xfa, 0xd1, 0xc6, 0xcb, 0x78, 0xf1, 0x78, 0x03, 0x77, 0x22, 0x7e, 0x43, 0x6e, + 0x68, 0x8c, 0xaf, 0xc2, 0xa3, 0xb5, 0xda, 0x2b, 0xae, 0xbd, 0x69, 0xee, 0xf1, 0x8b, 0xb9, 0x56, 0x67, 0x4e, 0xb5, + 0x57, 0x66, 0x5c, 0x99, 0xb8, 0x58, 0x51, 0x92, 0x0f, 0x5f, 0x10, 0x5c, 0xc7, 0xcf, 0xd6, 0x41, 0xb8, 0xeb, 0xf1, + 0x9d, 0x1c, 0x2c, 0xc5, 0xc0, 0x74, 0x03, 0xd7, 0x81, 0x18, 0xc3, 0xd8, 0x22, 0x01, 0x92, 0xfa, 0xa1, 0x6c, 0xc5, + 0x28, 0x18, 0xbf, 0x3e, 0x5e, 0xb6, 0xea, 0x1d, 0xff, 0x61, 0x09, 0xe0, 0xd8, 0x46, 0x38, 0x02, 0xcd, 0xac, 0x38, + 0xe5, 0x52, 0x5c, 0xe8, 0x23, 0x38, 0xb3, 0x29, 0xfb, 0x80, 0xe3, 0x90, 0x4d, 0x30, 0xed, 0x8f, 0x86, 0xca, 0xef, + 0x9f, 0xc8, 0x8f, 0x6b, 0x77, 0xbf, 0x57, 0xd7, 0x16, 0x9e, 0xfe, 0x73, 0x87, 0xde, 0x49, 0x47, 0x5e, 0x3b, 0x1d, + 0x75, 0xb8, 0x02, 0xd9, 0x71, 0x53, 0x7b, 0x56, 0x57, 0x5f, 0xc9, 0xf1, 0x63, 0x7f, 0x5b, 0x95, 0x6e, 0xe3, 0xfd, + 0xf3, 0xb2, 0xaa, 0xec, 0x6c, 0xaf, 0x5c, 0x17, 0x7f, 0x59, 0x69, 0xf2, 0xda, 0x7f, 0xd1, 0x6f, 0xe7, 0xa4, 0x1f, + 0xe6, 0x9b, 0x45, 0x8b, 0xbc, 0x61, 0x9b, 0x01, 0xfe, 0xf1, 0xa0, 0xf1, 0x50, 0x44, 0xd8, 0xdc, 0x75, 0xbf, 0xb5, + 0xa1, 0x41, 0x31, 0x27, 0xef, 0x04, 0x29, 0x0a, 0x20, 0x71, 0xc7, 0x5a, 0x01, 0x38, 0x06, 0x86, 0xc1, 0x73, 0xef, + 0x53, 0xeb, 0xc6, 0x14, 0x75, 0xb9, 0x7a, 0xa2, 0xb1, 0x9b, 0xad, 0x37, 0xf4, 0x35, 0x6e, 0xf4, 0x1f, 0x91, 0x0b, + 0x11, 0x18, 0x3c, 0x3f, 0x80, 0xfb, 0xc7, 0x29, 0x7b, 0xd1, 0x62, 0x52, 0x79, 0xc3, 0xe7, 0xf6, 0xf5, 0xe1, 0xb5, + 0x7c, 0x9a, 0xcd, 0x05, 0x12, 0xbd, 0x3e, 0x36, 0xb5, 0xd0, 0x14, 0xb9, 0x96, 0x3b, 0xd9, 0xc5, 0xd1, 0x34, 0xc4, + 0x68, 0x01, 0x50, 0x28, 0x03, 0xc6, 0x4f, 0xb0, 0x86, 0x3a, 0xe3, 0x9f, 0xcf, 0xa7, 0x3c, 0xa7, 0xfb, 0xcd, 0x5b, + 0x33, 0xbd, 0xa5, 0x39, 0xe0, 0xdb, 0x90, 0xff, 0xdb, 0x3f, 0xd1, 0xad, 0x63, 0xac, 0xf6, 0x98, 0x1d, 0x5c, 0x9b, + 0x6b, 0x59, 0xf4, 0x6f, 0x6b, 0xe2, 0xca, 0xeb, 0xd1, 0x0f, 0xf8, 0x75, 0xee, 0x0b, 0x81, 0xd1, 0x14, 0x9e, 0xb1, + 0x98, 0xb4, 0x55, 0xae, 0xef, 0x7a, 0xc2, 0x6c, 0x1b, 0x9d, 0x22, 0x35, 0x04, 0xd7, 0xfb, 0x18, 0x57, 0x1b, 0x4f, + 0xa2, 0xb2, 0xda, 0xbe, 0x79, 0x2a, 0xc0, 0x85, 0xc6, 0xf2, 0x4f, 0xd4, 0x79, 0xbb, 0x47, 0x6d, 0x72, 0xda, 0x3f, + 0x69, 0xed, 0x9e, 0x4b, 0x0f, 0x1d, 0xe9, 0xb1, 0xe9, 0x53, 0x6b, 0xde, 0x10, 0xec, 0x5b, 0xd2, 0x62, 0x2f, 0x00, + 0xdc, 0x01, 0x9e, 0xa8, 0x36, 0xd1, 0xb3, 0xaa, 0x7f, 0xec, 0x01, 0x69, 0x8c, 0xef, 0x31, 0x49, 0x95, 0x1b, 0xb9, + 0x50, 0xb3, 0x48, 0x50, 0x74, 0x1c, 0x1f, 0xdf, 0x31, 0xad, 0xd6, 0xc3, 0xf3, 0x62, 0x55, 0x0a, 0x63, 0xcb, 0xdc, + 0x9b, 0x79, 0x90, 0xd3, 0x54, 0x1f, 0xbc, 0x16, 0xee, 0x1b, 0xba, 0x14, 0x3e, 0x16, 0x8f, 0x5a, 0xed, 0x80, 0x9c, + 0x6c, 0x41, 0x08, 0x47, 0x74, 0xfe, 0x52, 0x32, 0x53, 0x80, 0xd7, 0x81, 0xbb, 0xe2, 0x18, 0x3d, 0xb6, 0xe3, 0x6e, + 0x54, 0xdc, 0xc2, 0x9f, 0x1d, 0x44, 0x11, 0xd6, 0x55, 0xbb, 0x35, 0x61, 0xce, 0xcb, 0x14, 0x46, 0xa9, 0x90, 0x80, + 0x70, 0xb8, 0xcc, 0x0d, 0x50, 0x42, 0x49, 0x40, 0x5b, 0x15, 0xd5, 0x1f, 0xca, 0xdc, 0x76, 0xbb, 0x51, 0x73, 0x1e, + 0x89, 0x87, 0x81, 0x8a, 0xf5, 0x98, 0xd6, 0x5a, 0x92, 0x03, 0x0a, 0x51, 0xb3, 0xc9, 0xf3, 0xf2, 0x8f, 0xf5, 0x48, + 0x2e, 0x05, 0x8f, 0x44, 0x2c, 0xde, 0x96, 0xe4, 0x9b, 0xfc, 0xf1, 0x0c, 0x99, 0xbd, 0xe5, 0xe4, 0x87, 0x39, 0x4c, + 0x27, 0x76, 0x19, 0xf0, 0x04, 0x05, 0xac, 0x51, 0x8f, 0xb6, 0xa2, 0xa7, 0x80, 0x74, 0x98, 0x15, 0x0c, 0x08, 0x4e, + 0xa9, 0x5f, 0xe6, 0x47, 0xbe, 0xd9, 0x96, 0x42, 0x55, 0x89, 0x68, 0x29, 0x0b, 0xbe, 0xdc, 0x9e, 0x6f, 0x26, 0x94, + 0xac, 0xb8, 0xa6, 0xb6, 0x99, 0xad, 0xa2, 0x45, 0x2b, 0x08, 0x7f, 0x5c, 0xcd, 0x8c, 0xa8, 0xbf, 0x90, 0x6e, 0xd6, + 0xb4, 0x7d, 0x80, 0xb4, 0x9a, 0x53, 0x3b, 0x3b, 0x47, 0x73, 0x41, 0x03, 0xf5, 0x18, 0xc1, 0xc6, 0xe2, 0x52, 0x93, + 0x72, 0xd6, 0x39, 0xaf, 0xc6, 0x1b, 0x86, 0xdb, 0x4d, 0x52, 0x2f, 0x8a, 0x1b, 0x57, 0x37, 0x3a, 0xe9, 0x4b, 0xd0, + 0xc1, 0xa0, 0x03, 0x86, 0x94, 0x5a, 0x85, 0x8a, 0xec, 0xce, 0x62, 0x5d, 0x38, 0x4d, 0x48, 0x3a, 0x5d, 0xf1, 0x72, + 0x52, 0xbc, 0x67, 0x84, 0x38, 0xfa, 0x01, 0x29, 0x93, 0x47, 0xa8, 0x49, 0x5e, 0xfb, 0x80, 0x21, 0xf3, 0x67, 0xd4, + 0xe2, 0xb0, 0xa1, 0x0d, 0xa2, 0x7f, 0x10, 0x38, 0x1e, 0x47, 0x90, 0x0a, 0xd6, 0x53, 0x32, 0xba, 0x04, 0x48, 0x7a, + 0x09, 0x9f, 0x1e, 0xb1, 0x60, 0x6a, 0xee, 0x94, 0x82, 0xe2, 0xc9, 0x00, 0x43, 0x5b, 0x69, 0x54, 0x96, 0x54, 0x4e, + 0xf4, 0x40, 0x03, 0xef, 0x29, 0x14, 0x10, 0x46, 0x9c, 0x3d, 0xf6, 0x39, 0x2f, 0x62, 0x50, 0xec, 0xad, 0x41, 0xe8, + 0x3e, 0x03, 0xd8, 0xc8, 0x33, 0x0c, 0x16, 0x79, 0x5e, 0x21, 0x47, 0x65, 0x2f, 0xab, 0xb9, 0xff, 0x72, 0x46, 0xd9, + 0xc0, 0xe0, 0x51, 0x3d, 0xe9, 0xe4, 0x5a, 0xbf, 0x0e, 0x27, 0xc8, 0x59, 0xfa, 0x94, 0xd5, 0xa3, 0x76, 0x6e, 0xca, + 0x98, 0xac, 0x2b, 0xf5, 0x67, 0xee, 0x61, 0x24, 0xdf, 0xca, 0x99, 0x51, 0x16, 0xa9, 0x88, 0x17, 0x7e, 0x00, 0xa5, + 0x9f, 0x67, 0x1d, 0x83, 0xc2, 0x13, 0x0b, 0x0d, 0x81, 0x38, 0xc4, 0x35, 0x36, 0xb8, 0x71, 0x20, 0x18, 0x35, 0x68, + 0x4c, 0x6e, 0x51, 0xad, 0x29, 0x72, 0x2d, 0xd4, 0xa7, 0x06, 0x43, 0x6d, 0x9c, 0x79, 0x66, 0x25, 0x98, 0xd0, 0xf0, + 0x92, 0x4f, 0x95, 0xac, 0xa3, 0xb8, 0xc2, 0x2f, 0x57, 0x80, 0xd9, 0xc0, 0x34, 0x77, 0x1d, 0x60, 0xb0, 0xd2, 0x9c, + 0x9a, 0x91, 0x67, 0xe7, 0x0e, 0xa1, 0xd4, 0x8d, 0x5e, 0xc0, 0x04, 0x30, 0x1c, 0x02, 0xda, 0xa0, 0x97, 0x17, 0x3e, + 0x5c, 0x90, 0xaa, 0x1d, 0x19, 0x70, 0xb4, 0xc8, 0x89, 0xb2, 0x75, 0x88, 0xff, 0x99, 0x48, 0x48, 0xda, 0xec, 0x40, + 0xbc, 0x39, 0x76, 0x53, 0xc7, 0xaa, 0xe7, 0x20, 0xbf, 0xba, 0xc1, 0x5e, 0x2b, 0xae, 0x4c, 0x93, 0x1a, 0x7a, 0x35, + 0x1a, 0x87, 0x82, 0xb4, 0xbc, 0x98, 0xdd, 0x78, 0xd2, 0x24, 0xba, 0x2c, 0xdd, 0x34, 0xe8, 0x21, 0xbc, 0x33, 0x0f, + 0xf9, 0x1d, 0xef, 0xeb, 0xc9, 0xfe, 0x81, 0xa2, 0x43, 0x60, 0xb7, 0x21, 0xd7, 0x15, 0x5f, 0x3f, 0x21, 0xc5, 0x32, + 0xda, 0xa7, 0x5d, 0x5b, 0xf3, 0xd4, 0xe2, 0x04, 0x86, 0xbd, 0x9c, 0x8d, 0x0b, 0x6e, 0x55, 0x84, 0x61, 0x6a, 0x28, + 0x25, 0x97, 0x9d, 0x6e, 0x49, 0x4e, 0xae, 0x05, 0x1a, 0x83, 0x40, 0x71, 0x1e, 0xf7, 0x9f, 0xd3, 0x97, 0x12, 0x6c, + 0xc7, 0x0e, 0x46, 0x27, 0xe9, 0x3d, 0xad, 0x93, 0xa3, 0xa2, 0xb0, 0xdd, 0x29, 0xdd, 0x38, 0xf0, 0xc7, 0x89, 0x2a, + 0xb5, 0x25, 0x06, 0x9e, 0xef, 0xae, 0x4d, 0x42, 0x5b, 0x73, 0x0e, 0xb0, 0x12, 0x00, 0x28, 0x2f, 0x06, 0x55, 0xbb, + 0x78, 0xe0, 0xa6, 0xa5, 0x6d, 0x70, 0xd3, 0x40, 0x8d, 0x44, 0x04, 0x51, 0x40, 0xc2, 0xd4, 0x3f, 0x37, 0x25, 0x3b, + 0xf1, 0x8e, 0x79, 0x27, 0x0a, 0x15, 0x92, 0x06, 0xda, 0x79, 0xf5, 0xf0, 0xe8, 0x63, 0x42, 0x58, 0x63, 0x9c, 0x18, + 0xdb, 0x80, 0x7d, 0xd7, 0x5a, 0xd1, 0x5c, 0x17, 0xf4, 0xb6, 0xee, 0x14, 0xd5, 0x1c, 0xa0, 0x93, 0x70, 0x3b, 0x0f, + 0x3e, 0x42, 0x46, 0x95, 0xbc, 0xdf, 0xe5, 0xc8, 0xe3, 0x12, 0x04, 0x39, 0xdf, 0x36, 0x54, 0x1e, 0x83, 0x07, 0x51, + 0xe0, 0x83, 0x2a, 0x06, 0x53, 0xe5, 0xc4, 0x4d, 0x20, 0xd5, 0x08, 0x32, 0xaf, 0x22, 0xc4, 0x2b, 0x3a, 0xf9, 0x7d, + 0x8f, 0x40, 0xac, 0x12, 0x9e, 0x24, 0xf3, 0x2a, 0xf9, 0x34, 0x23, 0xae, 0x6a, 0x83, 0x61, 0x66, 0xd8, 0x6e, 0xc9, + 0x69, 0x8c, 0x88, 0xa7, 0xe3, 0x66, 0x6f, 0xe2, 0xb9, 0x11, 0xd8, 0xc2, 0x51, 0xc4, 0xf2, 0x35, 0xd1, 0x19, 0x98, + 0x21, 0x55, 0x85, 0xd8, 0x5c, 0xf2, 0x19, 0x91, 0x8d, 0xc2, 0xf5, 0xb5, 0xf8, 0xbb, 0x4a, 0x29, 0x11, 0x19, 0xea, + 0x6b, 0xf5, 0x4f, 0xd1, 0x08, 0xdb, 0xa9, 0x62, 0xf4, 0xfa, 0xf1, 0x81, 0x7a, 0x04, 0x3a, 0x53, 0xaa, 0x8d, 0x52, + 0x2d, 0x98, 0xd7, 0x5a, 0xa1, 0x61, 0xa1, 0x75, 0xd4, 0xa7, 0x26, 0xc3, 0xe2, 0xc7, 0xab, 0xdc, 0x2e, 0x06, 0x80, + 0x4e, 0x02, 0x94, 0xec, 0x0f, 0x2d, 0xf5, 0xcd, 0x2a, 0x4b, 0x12, 0x80, 0xcc, 0x01, 0xd8, 0xe3, 0x38, 0xa9, 0x59, + 0x91, 0x1d, 0xfd, 0x42, 0x54, 0x4e, 0xd8, 0xe1, 0x8b, 0xa5, 0x69, 0xfe, 0x00, 0x57, 0x09, 0xcc, 0x08, 0x31, 0x19, + 0xd7, 0x51, 0x67, 0x83, 0xd0, 0x02, 0xa0, 0x5b, 0xda, 0xa9, 0x87, 0xe4, 0xed, 0x7a, 0x0c, 0x52, 0xf6, 0x01, 0xea, + 0xbc, 0xab, 0xe1, 0xfa, 0x08, 0xc3, 0x9c, 0x1d, 0x24, 0xa0, 0x9d, 0xaa, 0xd0, 0x9f, 0x9a, 0xa6, 0x72, 0x44, 0xaf, + 0xa7, 0x4d, 0x07, 0x95, 0xbb, 0x89, 0x2a, 0x13, 0xe0, 0xe0, 0x4d, 0x3c, 0x49, 0xe2, 0xb0, 0xdb, 0x4b, 0x4d, 0x53, + 0x3f, 0x99, 0xb8, 0xb2, 0x5a, 0x4d, 0xf9, 0x76, 0x6e, 0x95, 0xd0, 0xd2, 0xe3, 0x42, 0x88, 0x79, 0xbc, 0xe7, 0x81, + 0xeb, 0x65, 0xdf, 0xc8, 0x1a, 0x2c, 0xee, 0x9b, 0x95, 0x51, 0x95, 0xd3, 0x11, 0x1a, 0x93, 0x62, 0x9e, 0xfc, 0x05, + 0x88, 0xd1, 0xdd, 0x4e, 0xd3, 0xeb, 0x10, 0x42, 0x44, 0x37, 0xfb, 0xf6, 0x9e, 0x1a, 0xeb, 0x88, 0x3d, 0x21, 0x2c, + 0x73, 0xc3, 0x4b, 0x74, 0x0c, 0xdc, 0xf6, 0xae, 0x2c, 0xc9, 0x74, 0xf9, 0xdc, 0x17, 0x20, 0x7c, 0x1d, 0x30, 0x43, + 0x0a, 0x54, 0x4a, 0xec, 0x83, 0xcd, 0xf7, 0x91, 0xd0, 0x3c, 0x3d, 0x17, 0xb6, 0x11, 0x7a, 0xbe, 0xec, 0xb3, 0xf5, + 0x5b, 0x38, 0x62, 0x6b, 0xab, 0x60, 0x0f, 0x7b, 0xb9, 0x6e, 0x91, 0xd1, 0x3c, 0xf8, 0x85, 0xe9, 0x2c, 0x0b, 0x89, + 0x57, 0x1b, 0xf5, 0x0d, 0xeb, 0x1d, 0x5b, 0xfa, 0x4c, 0x66, 0x4d, 0x3c, 0x4c, 0xd6, 0xd3, 0xc8, 0xc3, 0xc9, 0xa9, + 0x3c, 0xc7, 0xe6, 0xa9, 0xb0, 0xc0, 0x1b, 0xba, 0x7a, 0x7a, 0xcb, 0xb8, 0xf7, 0xa6, 0x21, 0x79, 0x89, 0xcf, 0xce, + 0xa2, 0x05, 0xa0, 0x98, 0xa8, 0x9c, 0x5e, 0xbb, 0xc0, 0x09, 0xf6, 0x7a, 0x51, 0x41, 0x83, 0x63, 0xe4, 0xd8, 0x96, + 0xe0, 0xe9, 0x70, 0x26, 0x67, 0x9d, 0x0b, 0x48, 0x5f, 0x33, 0xa9, 0x39, 0x0b, 0x73, 0x4e, 0x4a, 0x11, 0xf8, 0xe8, + 0x51, 0x9c, 0xa3, 0x79, 0xba, 0x01, 0x04, 0x86, 0x8a, 0xf7, 0x5d, 0x60, 0x8f, 0x37, 0x1c, 0xa9, 0x8b, 0x1c, 0xac, + 0xe4, 0x3d, 0x31, 0xcc, 0x0a, 0xfd, 0xeb, 0xe7, 0x07, 0x2b, 0x85, 0x8a, 0x5c, 0x8e, 0x51, 0x88, 0x62, 0xf7, 0x8c, + 0x08, 0xcc, 0x4d, 0xa5, 0x3a, 0x08, 0xd4, 0xf2, 0x0f, 0xb6, 0x5f, 0x08, 0x57, 0x4a, 0x70, 0xeb, 0x41, 0x5d, 0x5a, + 0x42, 0xc6, 0x1e, 0xce, 0xea, 0x2d, 0xd2, 0x58, 0x40, 0xb0, 0xc7, 0x5c, 0x6b, 0x7a, 0x98, 0x03, 0xc9, 0xac, 0x06, + 0x18, 0x6d, 0x89, 0x20, 0xf5, 0x82, 0xc1, 0x2e, 0x15, 0xdd, 0xd7, 0x05, 0x45, 0xba, 0xcb, 0xa8, 0x31, 0x95, 0x56, + 0x72, 0x7c, 0x1e, 0x62, 0x7f, 0xad, 0xa9, 0x5a, 0xea, 0xab, 0xec, 0x6b, 0x72, 0xba, 0xbb, 0x5f, 0x6c, 0xfc, 0x48, + 0xf8, 0x79, 0xae, 0x98, 0x41, 0x95, 0x8c, 0xa3, 0x5d, 0xc2, 0xa4, 0xa1, 0x7a, 0xa5, 0x38, 0x6e, 0x2c, 0x37, 0x9e, + 0x6e, 0x5f, 0x74, 0xc6, 0x56, 0xe9, 0xbf, 0xbb, 0x05, 0x3e, 0x27, 0xdd, 0x6b, 0x32, 0x4f, 0x49, 0x6c, 0xf0, 0x43, + 0xf7, 0x20, 0x9d, 0x28, 0xcf, 0xfd, 0xcb, 0xf3, 0xe3, 0x39, 0x29, 0x62, 0xdb, 0x56, 0xe4, 0x95, 0x15, 0xa0, 0x1c, + 0xd2, 0x6e, 0x02, 0xea, 0x4b, 0x37, 0xea, 0x4d, 0xe4, 0x8d, 0x0d, 0xbc, 0x84, 0xd4, 0x1a, 0x28, 0x76, 0x61, 0xec, + 0xab, 0xd3, 0x51, 0x48, 0x93, 0x33, 0xd9, 0x43, 0x42, 0x31, 0x61, 0x80, 0xfe, 0x69, 0x71, 0x34, 0xa3, 0x82, 0xd6, + 0xfb, 0xbd, 0xa8, 0x8e, 0x65, 0xe7, 0x1a, 0x08, 0x99, 0xd9, 0x68, 0x96, 0xbf, 0xc8, 0xf0, 0xc6, 0x21, 0xf2, 0x55, + 0x66, 0x3a, 0x3a, 0xf0, 0xd7, 0x94, 0x3b, 0xa9, 0xc3, 0xc6, 0x55, 0x76, 0x24, 0x81, 0xff, 0x2e, 0x73, 0x22, 0x14, + 0xbe, 0x99, 0x2d, 0x0f, 0xe4, 0x6b, 0x5d, 0xf9, 0x5f, 0x33, 0xea, 0xb3, 0xc2, 0x1d, 0x6d, 0xcb, 0xd5, 0x8c, 0xc3, + 0xd9, 0x70, 0x20, 0xf3, 0xf1, 0x81, 0x0b, 0x5e, 0x79, 0xaa, 0xca, 0x7e, 0x13, 0x0e, 0xc9, 0x03, 0x7b, 0x36, 0x39, + 0x4a, 0x4b, 0x47, 0xed, 0x7f, 0xe5, 0xb4, 0xe8, 0x50, 0x34, 0x2c, 0x5a, 0x17, 0x05, 0xa2, 0x56, 0x1b, 0xcb, 0xcb, + 0x3c, 0x22, 0x41, 0xed, 0x8b, 0xc5, 0x43, 0x7b, 0xe0, 0xa3, 0x29, 0x46, 0xbe, 0xcf, 0x58, 0x07, 0x12, 0x7d, 0x7f, + 0x44, 0x90, 0x32, 0x50, 0x3a, 0x74, 0x06, 0xa5, 0x89, 0x29, 0x1e, 0x93, 0x3c, 0x67, 0xb1, 0xc2, 0x5e, 0xf2, 0x3a, + 0x2a, 0x07, 0x2b, 0x92, 0x7f, 0x8e, 0x08, 0x70, 0x14, 0x0c, 0x1e, 0x45, 0x9e, 0xfa, 0x25, 0xb8, 0xe5, 0xbe, 0x3f, + 0x60, 0x44, 0x56, 0xd2, 0x58, 0x5b, 0x8c, 0x5e, 0x88, 0x91, 0xf9, 0x08, 0x8e, 0xc7, 0xef, 0x9b, 0xa3, 0x14, 0x94, + 0xbe, 0xb4, 0x2b, 0x50, 0xdc, 0x04, 0xba, 0xb4, 0x9b, 0x1a, 0xa7, 0x81, 0x9c, 0xc8, 0xb4, 0xb5, 0x1d, 0xf7, 0xdd, + 0xd9, 0xb1, 0xa0, 0x2d, 0x41, 0xc6, 0x74, 0x17, 0x9a, 0x39, 0x0a, 0x0c, 0xef, 0xb7, 0x1a, 0x47, 0xc0, 0x80, 0x5d, + 0x63, 0x3d, 0xfc, 0x52, 0x4c, 0xfb, 0x54, 0xe9, 0x87, 0x2b, 0x9c, 0xb3, 0x4b, 0x3a, 0xbd, 0xf9, 0xfd, 0x40, 0x06, + 0xc4, 0xc5, 0x1b, 0x31, 0xf5, 0x05, 0xcc, 0x2f, 0x83, 0x02, 0x10, 0xa6, 0x12, 0x58, 0xfa, 0xbf, 0x98, 0x0b, 0xbc, + 0x13, 0x87, 0x35, 0x83, 0x03, 0x83, 0x88, 0x8f, 0x3b, 0xb8, 0xc5, 0x5f, 0x87, 0xff, 0x68, 0x80, 0xba, 0x72, 0xf7, + 0x19, 0x65, 0xcd, 0xf7, 0x49, 0x29, 0x32, 0x7d, 0xf9, 0xee, 0x65, 0x2b, 0xd4, 0x41, 0x8e, 0x6d, 0x6e, 0x55, 0xf3, + 0xda, 0xe2, 0xf7, 0xd3, 0x58, 0xcd, 0x4d, 0x7e, 0xd3, 0xdb, 0x55, 0x57, 0x4f, 0x8d, 0x1a, 0xf5, 0x84, 0x60, 0xf4, + 0xe6, 0x66, 0xd8, 0xad, 0xf1, 0xcb, 0x59, 0x09, 0x68, 0x64, 0xb3, 0x57, 0xbf, 0x47, 0x41, 0xae, 0xaf, 0xf5, 0xf3, + 0xbc, 0xac, 0x32, 0x2e, 0xbe, 0x09, 0xc0, 0x53, 0xe3, 0x43, 0xa2, 0x4a, 0xb5, 0x2c, 0x0d, 0x51, 0x93, 0x00, 0x82, + 0xc3, 0x1f, 0x74, 0x0b, 0x2e, 0xed, 0x57, 0x72, 0x9b, 0x55, 0x79, 0x6d, 0x45, 0xd0, 0x81, 0x45, 0x9f, 0xae, 0x0c, + 0x76, 0x30, 0xe0, 0xe1, 0x14, 0xfd, 0x43, 0xf1, 0x87, 0x89, 0xed, 0x9d, 0x6d, 0x4a, 0x28, 0x1f, 0x9a, 0xb9, 0x17, + 0x77, 0xf6, 0x4c, 0x11, 0xcd, 0x22, 0xd4, 0xac, 0x82, 0x19, 0x2c, 0x1b, 0x6a, 0xe7, 0x1a, 0x12, 0xf6, 0x08, 0x52, + 0x4c, 0xc1, 0xb8, 0xd1, 0xde, 0x90, 0xee, 0x88, 0x6b, 0x06, 0xe5, 0xb0, 0x50, 0x94, 0xf9, 0xcd, 0x08, 0xc9, 0x38, + 0xa7, 0xe9, 0x0d, 0x0a, 0xfc, 0x30, 0xe0, 0x73, 0x79, 0xb0, 0x20, 0xcf, 0x1f, 0x55, 0xe9, 0x74, 0x14, 0xfb, 0x56, + 0x12, 0x31, 0x63, 0xda, 0x81, 0x2d, 0xaf, 0xf7, 0xca, 0x74, 0x61, 0xb3, 0x4f, 0x3a, 0xd6, 0x1d, 0xe2, 0xed, 0x29, + 0x71, 0x1d, 0xc4, 0x9e, 0xa6, 0x1c, 0x36, 0x79, 0x3d, 0x99, 0xe3, 0x68, 0x51, 0x76, 0x5d, 0xac, 0xa6, 0x33, 0x14, + 0x7a, 0x0b, 0xc9, 0x46, 0x1b, 0x7a, 0xfe, 0xa4, 0x72, 0x8c, 0xf3, 0xc3, 0xe5, 0x24, 0x86, 0xe9, 0x4b, 0xa9, 0x21, + 0x5a, 0xb7, 0x94, 0xee, 0xb1, 0xbe, 0x63, 0x05, 0x5b, 0xb3, 0xf7, 0x8f, 0x44, 0x96, 0x26, 0x96, 0xa9, 0xd4, 0x96, + 0x9d, 0xba, 0x71, 0xef, 0x59, 0x7b, 0xfc, 0xde, 0x62, 0xb1, 0x46, 0xea, 0x6c, 0xb4, 0x31, 0xcd, 0x40, 0x3e, 0x1a, + 0xda, 0x07, 0x5f, 0x30, 0x65, 0x0b, 0xfd, 0x70, 0xde, 0x6d, 0xd0, 0x16, 0xe3, 0x33, 0x86, 0xa6, 0xd9, 0x9d, 0x0f, + 0xbc, 0xfa, 0x2c, 0x8b, 0x2e, 0x17, 0x1d, 0x4f, 0x73, 0x8c, 0x18, 0x75, 0xff, 0x5f, 0x1e, 0xf6, 0x52, 0x86, 0xbb, + 0x3c, 0x21, 0xc3, 0x4e, 0xee, 0xdb, 0x29, 0xab, 0x80, 0x7c, 0x8c, 0xad, 0xf4, 0xbc, 0x72, 0x30, 0xa2, 0xd2, 0x51, + 0x9c, 0xe9, 0x3f, 0x7c, 0xe5, 0xd7, 0x32, 0x8d, 0xda, 0xf4, 0xa3, 0xcb, 0x92, 0xbf, 0xb2, 0x1a, 0x88, 0x36, 0x4f, + 0x88, 0x4c, 0xfe, 0x4f, 0x24, 0x25, 0x47, 0x06, 0xe2, 0xd1, 0x01, 0x14, 0x30, 0x53, 0x27, 0x93, 0xd3, 0x62, 0x70, + 0x02, 0x22, 0x4b, 0x34, 0x87, 0x73, 0x00, 0x93, 0xb4, 0x04, 0x13, 0x1e, 0xd7, 0x6a, 0xdf, 0x63, 0xc6, 0x01, 0x7f, + 0x99, 0x47, 0x73, 0x70, 0xf7, 0x01, 0x2d, 0x9a, 0x80, 0x64, 0x24, 0x61, 0x58, 0x6b, 0xdb, 0x79, 0x38, 0xd9, 0x4e, + 0xf0, 0xac, 0x7a, 0x7d, 0xc0, 0x8f, 0xb5, 0x82, 0xcb, 0x9d, 0x28, 0x45, 0x75, 0x1f, 0x7c, 0xd9, 0xea, 0xcd, 0x21, + 0xd4, 0x59, 0x0f, 0xf5, 0xcc, 0x40, 0x71, 0xdb, 0xce, 0x66, 0x54, 0xf3, 0x05, 0xff, 0xf8, 0xcb, 0xc2, 0x50, 0x2c, + 0x9a, 0x35, 0x64, 0xc0, 0x00, 0xdc, 0xc6, 0x9c, 0xef, 0x75, 0xfc, 0x97, 0x4f, 0x90, 0xb0, 0x17, 0x11, 0xf6, 0x26, + 0xc5, 0x28, 0xe1, 0x97, 0x13, 0x06, 0x04, 0xf1, 0xda, 0x13, 0x25, 0x88, 0xf4, 0xa0, 0x3e, 0x99, 0x66, 0x5c, 0x66, + 0x33, 0x48, 0xd6, 0xb0, 0x08, 0xba, 0xdd, 0x35, 0xeb, 0x32, 0xe3, 0x4f, 0x7e, 0xc8, 0x70, 0x0d, 0xf4, 0x4f, 0x26, + 0x4a, 0x3a, 0x37, 0x24, 0xa8, 0xf8, 0x20, 0x5e, 0xe6, 0x50, 0x79, 0xde, 0x33, 0xe4, 0xe9, 0xf9, 0x47, 0x7f, 0xdf, + 0xcc, 0x1c, 0xca, 0x53, 0xd6, 0xe4, 0xef, 0x9e, 0xea, 0xfe, 0xa7, 0xc8, 0x2b, 0x3a, 0xf3, 0xd5, 0xac, 0xb3, 0xe2, + 0x3a, 0xe3, 0xec, 0x88, 0x54, 0x70, 0x6a, 0x45, 0xeb, 0x1d, 0x0f, 0xb1, 0x69, 0xfc, 0xb5, 0x40, 0xea, 0xec, 0x91, + 0xb9, 0x67, 0x07, 0x15, 0xa3, 0x25, 0x14, 0x58, 0x2f, 0xa2, 0x06, 0xbe, 0x1d, 0xb5, 0x19, 0x33, 0x7d, 0x4e, 0x0a, + 0xb4, 0x68, 0x09, 0x36, 0x6d, 0x17, 0xa3, 0x26, 0x5e, 0x96, 0xcc, 0x15, 0x27, 0xfc, 0xe9, 0x32, 0x53, 0xec, 0x87, + 0x8c, 0xd4, 0xc1, 0x9e, 0x17, 0x2b, 0x96, 0x2c, 0x97, 0x4f, 0xd7, 0x0f, 0xc9, 0x2e, 0xf7, 0x1e, 0x11, 0x33, 0x5e, + 0x3f, 0x5e, 0xb2, 0x4b, 0x09, 0x28, 0x91, 0x91, 0x0d, 0xe3, 0x36, 0x12, 0x6a, 0x14, 0x15, 0xa3, 0x2b, 0x50, 0x72, + 0xac, 0x53, 0x11, 0x00, 0xf0, 0xc7, 0xf4, 0x52, 0xd8, 0xc0, 0x83, 0xd3, 0x89, 0x02, 0x94, 0x91, 0xa7, 0xef, 0x4c, + 0xc6, 0x82, 0xe8, 0xa8, 0x99, 0xc3, 0xef, 0x84, 0xb1, 0x7a, 0xe6, 0xde, 0xeb, 0xa3, 0x48, 0xb0, 0x7b, 0xd9, 0x08, + 0x03, 0x89, 0x65, 0xd9, 0x64, 0x1c, 0xb6, 0x6e, 0x2b, 0xfc, 0xb4, 0x58, 0x81, 0x34, 0x05, 0x68, 0xde, 0xd3, 0x46, + 0xc0, 0x69, 0x18, 0xb3, 0x2f, 0x13, 0x48, 0xa9, 0x82, 0xb1, 0xfc, 0xa4, 0x64, 0xc3, 0xb3, 0x49, 0xde, 0xfd, 0xc4, + 0xd3, 0x5c, 0x20, 0xe4, 0xc5, 0x02, 0xdb, 0x9a, 0xa9, 0x13, 0xbf, 0x19, 0xe5, 0x66, 0x3f, 0x56, 0xcd, 0xa2, 0x0d, + 0x47, 0x1e, 0x95, 0xe5, 0xa6, 0x1b, 0xdd, 0xda, 0x2d, 0x58, 0xb5, 0x10, 0xa9, 0xe6, 0x78, 0x19, 0x80, 0x8d, 0xe8, + 0x97, 0x94, 0x61, 0xf5, 0x83, 0x4e, 0x81, 0x64, 0x61, 0xc8, 0xb6, 0xcd, 0x92, 0x32, 0x18, 0x82, 0xf2, 0xa8, 0x9a, + 0x02, 0xac, 0x91, 0xf2, 0x4d, 0x0a, 0xa3, 0xc9, 0xbf, 0x6a, 0x8b, 0xfe, 0x93, 0xff, 0x29, 0xd6, 0x7b, 0x26, 0x88, + 0x64, 0x7b, 0x38, 0x9f, 0x9d, 0xa6, 0x05, 0x33, 0x68, 0x14, 0x84, 0xf6, 0x60, 0x4a, 0xcd, 0x49, 0x24, 0x06, 0x25, + 0x17, 0x22, 0xfb, 0x93, 0xea, 0x2d, 0xc7, 0x47, 0x1e, 0xb2, 0xaf, 0x6f, 0x92, 0x26, 0x9d, 0x56, 0xa7, 0xca, 0x08, + 0xee, 0x0a, 0x9c, 0xa0, 0x04, 0xb3, 0x01, 0xfd, 0x93, 0x9f, 0x3f, 0x85, 0x24, 0xfa, 0xd0, 0x05, 0x84, 0x52, 0x67, + 0xcf, 0x88, 0xdc, 0x2c, 0x3c, 0xa2, 0x55, 0x88, 0x62, 0x5c, 0x20, 0x07, 0xc8, 0xfc, 0xb7, 0x91, 0x05, 0xbd, 0x86, + 0xfd, 0x42, 0x37, 0xa2, 0x7d, 0x08, 0x8b, 0x11, 0x9b, 0x2b, 0xde, 0xe8, 0x3d, 0x90, 0x67, 0x88, 0x1b, 0xf7, 0x34, + 0x2e, 0x68, 0xe9, 0x2a, 0x9b, 0x95, 0x02, 0xdd, 0xc4, 0xa3, 0x3e, 0x09, 0x1d, 0xb5, 0x5a, 0xde, 0x0c, 0xd1, 0x3b, + 0xd0, 0xf3, 0x7a, 0xff, 0x04, 0xdf, 0x0e, 0x08, 0x10, 0x51, 0xb8, 0xa3, 0x33, 0xf9, 0xc1, 0xe1, 0x77, 0xae, 0x3c, + 0xff, 0xc8, 0x44, 0x3d, 0x52, 0x99, 0xef, 0x96, 0xf8, 0xbb, 0x5b, 0xde, 0xff, 0xa1, 0x29, 0x53, 0x82, 0xf2, 0x83, + 0x60, 0x60, 0x64, 0x85, 0x0f, 0xae, 0x9d, 0x0e, 0xbf, 0x91, 0x79, 0x89, 0xe2, 0x85, 0xe4, 0xb2, 0x85, 0xdb, 0x2b, + 0xc6, 0x55, 0xac, 0xe2, 0xca, 0x0e, 0xda, 0x67, 0xdc, 0x7a, 0xfc, 0x10, 0x35, 0xc6, 0x1a, 0x47, 0xe7, 0x1c, 0x94, + 0x06, 0x84, 0x04, 0xd3, 0xc0, 0x26, 0x3d, 0x5a, 0x60, 0x99, 0x16, 0x48, 0x09, 0x42, 0x48, 0x2a, 0xba, 0x1f, 0x43, + 0x53, 0x89, 0xcd, 0x8c, 0x20, 0xad, 0x2a, 0x76, 0xa8, 0xc4, 0x29, 0x67, 0x1f, 0xa6, 0x58, 0x23, 0x7c, 0xaa, 0xe9, + 0x3b, 0x88, 0x92, 0xc8, 0x7b, 0x4e, 0x2e, 0x2e, 0x1d, 0x68, 0x45, 0xa6, 0x4a, 0x49, 0xdf, 0x79, 0xc1, 0xad, 0xbf, + 0xd6, 0x3e, 0x20, 0xd6, 0x41, 0x15, 0xf4, 0xac, 0x8a, 0xbf, 0xdc, 0x62, 0xae, 0xa4, 0x25, 0x56, 0xb1, 0xa7, 0x2c, + 0xf6, 0x73, 0x5a, 0x71, 0x1e, 0xce, 0x69, 0xe8, 0x2e, 0x39, 0x77, 0xa9, 0xb8, 0x27, 0x9d, 0xf5, 0x12, 0xe1, 0xbe, + 0x65, 0x07, 0xd3, 0x67, 0x25, 0xfc, 0xf8, 0xbb, 0x39, 0x29, 0x29, 0xd7, 0x81, 0x46, 0xcf, 0x61, 0xe0, 0x65, 0xd0, + 0xa2, 0xee, 0xd4, 0xc0, 0x3d, 0x91, 0xe8, 0x5b, 0x7f, 0x60, 0xc6, 0x66, 0xd9, 0x12, 0x19, 0x14, 0xcf, 0xd4, 0xff, + 0x24, 0x48, 0xe2, 0xb1, 0xfc, 0x23, 0x2f, 0x0e, 0x49, 0x22, 0xa9, 0x3e, 0x80, 0x3e, 0x09, 0x9e, 0x58, 0x80, 0x57, + 0x7f, 0xa0, 0x80, 0xa1, 0x28, 0x57, 0x39, 0x32, 0x77, 0xc2, 0x1c, 0xf2, 0x74, 0x57, 0xbd, 0x53, 0x07, 0x38, 0x7d, + 0xb5, 0x9e, 0x4d, 0x40, 0xa7, 0x85, 0x1e, 0xa0, 0xc4, 0x99, 0x11, 0xa5, 0x19, 0x07, 0xa7, 0x86, 0x39, 0xfc, 0xaf, + 0x57, 0x12, 0x61, 0xec, 0xc1, 0xc3, 0x41, 0xe3, 0x41, 0x05, 0xf9, 0xd9, 0x8e, 0xa6, 0x34, 0x0c, 0x48, 0xc2, 0xb9, + 0x16, 0xab, 0x64, 0x19, 0x5e, 0x3c, 0xf2, 0xca, 0x0c, 0xe1, 0x04, 0xd6, 0x9d, 0x3e, 0x95, 0x0e, 0x82, 0x71, 0x09, + 0x17, 0x2a, 0xaf, 0x39, 0x35, 0x1c, 0x69, 0xb9, 0x40, 0xf1, 0x57, 0x9a, 0xa8, 0x6b, 0x11, 0x4f, 0xe6, 0x47, 0x5c, + 0x35, 0x10, 0x61, 0xda, 0x05, 0x01, 0x96, 0x97, 0xc8, 0xad, 0x85, 0x72, 0xed, 0xb7, 0x1e, 0x36, 0x30, 0x06, 0xeb, + 0xe6, 0xd7, 0x4b, 0x7e, 0x7d, 0xd3, 0xb4, 0xf6, 0xe2, 0x2d, 0x2a, 0x34, 0x9d, 0xe8, 0xe9, 0x90, 0x22, 0x3c, 0x1d, + 0x77, 0x11, 0x19, 0x46, 0x03, 0x4c, 0xdf, 0x56, 0xd5, 0x62, 0x26, 0xed, 0x00, 0xfa, 0xb9, 0x20, 0xcd, 0x01, 0xa0, + 0x29, 0x42, 0xd9, 0x01, 0x70, 0x15, 0xaa, 0xf5, 0xba, 0x5f, 0x69, 0x63, 0x63, 0x3c, 0xe0, 0x11, 0x81, 0x59, 0xf1, + 0x94, 0x42, 0xc9, 0x79, 0x02, 0x79, 0xb1, 0x4d, 0x55, 0xba, 0x99, 0x96, 0xcd, 0xfa, 0xdd, 0xfa, 0x47, 0x96, 0x00, + 0xa2, 0x26, 0x79, 0x64, 0x32, 0x81, 0x0d, 0x15, 0xd2, 0x14, 0xc7, 0xa4, 0x56, 0x02, 0xae, 0xf9, 0xb0, 0x8f, 0x6c, + 0x09, 0x38, 0x3b, 0x70, 0x2d, 0x88, 0xc3, 0x59, 0x33, 0x64, 0xb2, 0x3c, 0xa7, 0xad, 0xd1, 0x3f, 0x5b, 0xad, 0xb1, + 0xb5, 0xff, 0x43, 0x4b, 0x71, 0x3f, 0x19, 0x0b, 0x4d, 0x0c, 0x48, 0x6d, 0x8f, 0xbf, 0xbb, 0x95, 0x74, 0xe6, 0x6d, + 0xc1, 0x49, 0xff, 0x37, 0xd3, 0xe6, 0x74, 0x9e, 0x3d, 0x39, 0x8c, 0x7c, 0xc0, 0x98, 0x0a, 0x61, 0x8c, 0x93, 0xf0, + 0x62, 0x3b, 0xbc, 0x68, 0x0c, 0x6a, 0xff, 0xe5, 0x0e, 0x86, 0x9c, 0xea, 0xd8, 0x7b, 0x1f, 0x44, 0xc9, 0xbe, 0x98, + 0x5b, 0x34, 0x56, 0x87, 0xb4, 0x28, 0x6e, 0xfb, 0x00, 0x32, 0xf0, 0xd2, 0xfd, 0xff, 0xb8, 0x75, 0x88, 0x63, 0xb0, + 0x09, 0x79, 0x89, 0x4b, 0x12, 0xb3, 0x4d, 0x1f, 0x05, 0xf5, 0xfa, 0xb4, 0x11, 0x2e, 0xd1, 0x5c, 0xe9, 0xfe, 0x07, + 0x2f, 0x5b, 0x54, 0x77, 0x29, 0x0f, 0xf7, 0x0e, 0x8c, 0x69, 0x7c, 0x73, 0xf3, 0x3d, 0x0d, 0xa6, 0x14, 0xba, 0x19, + 0xef, 0x60, 0x13, 0xbb, 0xde, 0x56, 0x56, 0x6c, 0x17, 0x99, 0xa2, 0xa2, 0xa9, 0xd1, 0x47, 0x33, 0xd8, 0xec, 0xd0, + 0x80, 0xf6, 0x6f, 0x31, 0xc9, 0x60, 0xf1, 0x70, 0x6b, 0x2e, 0x44, 0xcb, 0xeb, 0x9c, 0xed, 0x28, 0x38, 0x27, 0x23, + 0x8e, 0x24, 0x48, 0x93, 0xee, 0x3b, 0x8e, 0x1e, 0xd4, 0x41, 0xd5, 0x88, 0x3b, 0x6d, 0xc9, 0x7e, 0x45, 0x7d, 0x97, + 0x3e, 0xae, 0x0b, 0x79, 0xe5, 0x1c, 0x48, 0xc4, 0x67, 0x85, 0x37, 0x27, 0x44, 0x46, 0x6d, 0x1b, 0xa9, 0x15, 0x59, + 0x91, 0x5f, 0x21, 0x25, 0xea, 0x5f, 0x51, 0x2b, 0xc8, 0x62, 0x0e, 0xc0, 0xc0, 0x36, 0x00, 0xab, 0xdf, 0xac, 0x18, + 0xb2, 0xa5, 0x80, 0xc6, 0x2f, 0x67, 0xdb, 0x7c, 0xe2, 0x96, 0xec, 0xe8, 0x17, 0x44, 0x6d, 0x6b, 0x45, 0x13, 0x9c, + 0x77, 0x2f, 0xac, 0x9e, 0x89, 0xdf, 0x53, 0xcf, 0xb7, 0xc0, 0x36, 0x90, 0x4f, 0xd2, 0xfd, 0xce, 0x99, 0x3e, 0x60, + 0x0f, 0xc6, 0x58, 0xc7, 0x60, 0x57, 0xd8, 0x63, 0xa3, 0x37, 0x55, 0xe5, 0x39, 0x68, 0x57, 0xb7, 0x1c, 0x15, 0xf1, + 0xf8, 0x2d, 0xcb, 0x3a, 0x18, 0x66, 0x18, 0x3d, 0xf3, 0x05, 0x94, 0x2d, 0xda, 0x11, 0x99, 0x93, 0x5c, 0x46, 0xdb, + 0x54, 0x0e, 0x28, 0x81, 0x05, 0x31, 0xa9, 0x71, 0x4a, 0xdd, 0x2d, 0x9b, 0x97, 0xae, 0xa3, 0x09, 0xf1, 0xd6, 0x5f, + 0x67, 0x3e, 0xd7, 0x83, 0xa3, 0xf2, 0x3c, 0x44, 0x60, 0x1a, 0xc8, 0xc3, 0x02, 0x0e, 0x23, 0x79, 0x5e, 0x8a, 0x40, + 0x01, 0xef, 0x06, 0x7d, 0xb6, 0x19, 0x28, 0x72, 0x0a, 0x91, 0x77, 0x9e, 0x83, 0x05, 0xba, 0xc1, 0x53, 0x44, 0x19, + 0x87, 0x87, 0xff, 0x2e, 0x70, 0x19, 0x1e, 0x92, 0x25, 0x8c, 0xef, 0x1d, 0x4e, 0x24, 0x27, 0xa9, 0x8b, 0xa4, 0xf5, + 0x4b, 0x78, 0xa6, 0xb6, 0x71, 0x6b, 0xfe, 0x22, 0xfb, 0x24, 0x76, 0xaf, 0xbc, 0x80, 0xf9, 0x18, 0x35, 0xd9, 0x65, + 0xfe, 0xc2, 0x3c, 0x26, 0x3d, 0x33, 0xaf, 0xd1, 0x6a, 0x0d, 0x78, 0x20, 0x69, 0x45, 0x58, 0xca, 0x2c, 0x99, 0x73, + 0x19, 0x00, 0xe8, 0xda, 0x78, 0xd8, 0x1a, 0x42, 0x7c, 0x22, 0xd7, 0x77, 0x45, 0x42, 0x65, 0xaa, 0x59, 0x96, 0x23, + 0xf7, 0xc9, 0x4d, 0x08, 0x4b, 0xb5, 0xcb, 0x12, 0xb7, 0x99, 0xe6, 0xb6, 0x36, 0x3c, 0xf7, 0xca, 0xf2, 0xbd, 0xc0, + 0x14, 0xf5, 0xa0, 0xbf, 0xb3, 0x8d, 0x38, 0x45, 0x10, 0x22, 0x66, 0x70, 0x87, 0xa3, 0x11, 0x64, 0x53, 0x4e, 0xf4, + 0x67, 0xbb, 0xc4, 0xe6, 0xa7, 0x97, 0xa9, 0xaa, 0x70, 0x39, 0x62, 0x32, 0xb1, 0x39, 0x1b, 0xb0, 0x98, 0x83, 0x57, + 0x7b, 0x72, 0x9b, 0xdb, 0xb2, 0xec, 0x8d, 0x08, 0x56, 0x83, 0x16, 0xce, 0x1d, 0x2c, 0x15, 0xfa, 0x4e, 0x66, 0xbd, + 0xab, 0x83, 0x9b, 0xd9, 0x6f, 0xd2, 0xee, 0x8f, 0x1c, 0x7d, 0x55, 0x69, 0xdc, 0x81, 0x6d, 0x2c, 0x81, 0x0d, 0x8f, + 0x11, 0x29, 0x87, 0x44, 0xf5, 0xa9, 0x4f, 0x6c, 0x1e, 0xd5, 0x98, 0xe4, 0x38, 0xc8, 0x1d, 0x26, 0xae, 0x68, 0x3a, + 0x9b, 0xb4, 0x10, 0xbb, 0x52, 0x21, 0x3d, 0x9d, 0x85, 0xfc, 0x16, 0x73, 0xd3, 0x75, 0x92, 0xc8, 0xd6, 0xb5, 0x0f, + 0xf9, 0xa2, 0x25, 0x75, 0x68, 0x60, 0xa7, 0xc7, 0x1c, 0xfd, 0x78, 0xb5, 0x95, 0xaf, 0xd4, 0xd6, 0x71, 0x4e, 0x92, + 0x8f, 0x71, 0xbc, 0x68, 0xf8, 0xe7, 0xa2, 0xa2, 0xd1, 0xc2, 0x93, 0xd8, 0xfa, 0x61, 0x27, 0xaf, 0x5f, 0xd1, 0x62, + 0x36, 0x1c, 0xb5, 0x5e, 0x96, 0x57, 0x1c, 0xee, 0xdd, 0xb6, 0x14, 0x4b, 0x58, 0x1f, 0xe3, 0x72, 0xc9, 0xd3, 0xa8, + 0x5a, 0x3a, 0xfa, 0xcb, 0x1b, 0xb8, 0x25, 0xef, 0x04, 0xc0, 0x44, 0x52, 0x1f, 0x61, 0x41, 0x7b, 0x19, 0x31, 0x42, + 0xec, 0x05, 0xd9, 0x27, 0x68, 0x7b, 0xb1, 0xaf, 0x76, 0x3d, 0x0c, 0xd9, 0x92, 0x64, 0x77, 0x6f, 0x46, 0xf8, 0x42, + 0xdd, 0x3d, 0xb2, 0x1a, 0x87, 0x6b, 0xf2, 0xe2, 0x32, 0x44, 0xb1, 0x97, 0x70, 0xc3, 0xa8, 0x2d, 0xc5, 0xdc, 0x82, + 0x1b, 0x49, 0x8b, 0x89, 0xad, 0x51, 0x46, 0x0d, 0x9b, 0x43, 0x9b, 0x43, 0x69, 0xef, 0x15, 0xdf, 0xf0, 0xdf, 0x10, + 0xef, 0x7c, 0x69, 0x4b, 0x12, 0x75, 0xef, 0x42, 0x5a, 0xe6, 0x45, 0xba, 0x92, 0xf5, 0xf3, 0x76, 0x62, 0x43, 0x71, + 0x37, 0xc7, 0x80, 0xf5, 0xc4, 0x41, 0x76, 0x69, 0xf2, 0x81, 0xc4, 0x26, 0x4a, 0x56, 0x5a, 0xfd, 0xcf, 0xee, 0xfa, + 0xb0, 0xe0, 0xa1, 0x89, 0x46, 0xc7, 0xb6, 0x43, 0x37, 0x62, 0x1e, 0x7e, 0x8d, 0x67, 0xaa, 0x16, 0x90, 0x1c, 0xe6, + 0x26, 0x51, 0xea, 0x66, 0x84, 0xea, 0xc4, 0x8d, 0x17, 0x88, 0x7a, 0xda, 0xf5, 0x4c, 0xc7, 0xd2, 0xfb, 0xbb, 0x0c, + 0xa1, 0xa9, 0x21, 0x04, 0x0f, 0x21, 0x39, 0x3f, 0x09, 0x6f, 0x46, 0x27, 0xe2, 0x1b, 0xa6, 0xcb, 0x19, 0x72, 0x0f, + 0x5f, 0xa0, 0x75, 0x27, 0xc1, 0xc2, 0xe1, 0x86, 0x90, 0x22, 0x15, 0x04, 0xc8, 0xf6, 0x31, 0x80, 0x85, 0x46, 0xf6, + 0xa2, 0xc9, 0xd4, 0x80, 0xc8, 0x66, 0x6d, 0x4b, 0x98, 0x63, 0x33, 0x35, 0x68, 0xc1, 0xd6, 0xfc, 0x12, 0x28, 0x1b, + 0xda, 0xe2, 0x2d, 0xfd, 0x4f, 0x5e, 0x13, 0x41, 0x8c, 0x69, 0x6a, 0xd3, 0xcc, 0x7a, 0xe5, 0xda, 0xde, 0xf5, 0x29, + 0x16, 0x0b, 0xe4, 0xc0, 0x75, 0x43, 0x69, 0x6c, 0x8d, 0xd5, 0x25, 0x0d, 0x68, 0xb9, 0xa8, 0x2e, 0x08, 0x84, 0xc4, + 0x10, 0xf3, 0xaa, 0xa1, 0x90, 0x92, 0x84, 0x6a, 0x6e, 0xdd, 0x89, 0x6d, 0x82, 0xc2, 0xec, 0xb8, 0x33, 0x79, 0xe8, + 0xe7, 0x70, 0xfe, 0xfe, 0xc6, 0x2c, 0x40, 0x51, 0xb8, 0xe2, 0xa5, 0x8c, 0x06, 0x89, 0x7e, 0xb3, 0x1e, 0x7a, 0xfe, + 0x83, 0x03, 0xda, 0x9d, 0xca, 0x32, 0xa3, 0xd4, 0xa9, 0x9e, 0x09, 0x4e, 0x6f, 0x0d, 0xd0, 0x88, 0x48, 0x80, 0x09, + 0xfc, 0xa8, 0x3f, 0x0a, 0x15, 0x0b, 0x98, 0xb5, 0x95, 0x53, 0xaf, 0xef, 0x31, 0x10, 0x29, 0xec, 0xb0, 0x71, 0xce, + 0xa2, 0x55, 0x8d, 0x78, 0x42, 0x82, 0x3e, 0x48, 0xc8, 0xce, 0x59, 0xf5, 0x8c, 0xaf, 0x93, 0x0b, 0xbe, 0x60, 0x77, + 0xfc, 0xb5, 0x06, 0x50, 0x8e, 0x7f, 0xb1, 0xf7, 0x86, 0xd7, 0xc3, 0x16, 0xd7, 0x23, 0xe6, 0x8b, 0x32, 0x2f, 0x7f, + 0x78, 0xd0, 0x72, 0xfa, 0xf7, 0xe7, 0x69, 0x80, 0x2a, 0x7f, 0xb1, 0x84, 0x01, 0xa9, 0x3c, 0xbc, 0xf5, 0x46, 0xe4, + 0x4a, 0x66, 0x14, 0x8d, 0x59, 0x3b, 0x6e, 0x09, 0x3b, 0xb8, 0x28, 0x8e, 0x20, 0x54, 0xfc, 0xf3, 0x16, 0x40, 0x62, + 0x2b, 0x68, 0x99, 0xd1, 0xa0, 0x11, 0xed, 0x81, 0x3a, 0x2b, 0x6c, 0xcc, 0x0b, 0xb6, 0x2e, 0x5f, 0xde, 0xad, 0xe0, + 0x20, 0x4b, 0x48, 0x82, 0x87, 0xf5, 0xf6, 0xcd, 0x26, 0xd3, 0xa5, 0x87, 0xa9, 0xd7, 0x1d, 0xbf, 0x67, 0x56, 0x20, + 0xa4, 0xd9, 0x43, 0x64, 0x6d, 0x37, 0x12, 0xd3, 0x1b, 0x4f, 0x6d, 0x3b, 0x62, 0x5e, 0xb7, 0x13, 0x91, 0x2b, 0x75, + 0x6c, 0x9b, 0x87, 0xc8, 0x08, 0x2b, 0x8c, 0x24, 0xb8, 0xfc, 0x32, 0x20, 0x36, 0x51, 0xd0, 0xd8, 0xc7, 0xe2, 0x52, + 0x16, 0x93, 0xec, 0xa3, 0xf8, 0x4b, 0x59, 0xeb, 0x5f, 0x22, 0xd5, 0xd9, 0x13, 0xf8, 0x15, 0x43, 0x7b, 0x0f, 0xa1, + 0xb1, 0x4e, 0x83, 0xbb, 0x16, 0x3c, 0xb2, 0x80, 0x72, 0x1f, 0x1a, 0x12, 0x42, 0x71, 0xba, 0x1d, 0x16, 0xd9, 0xae, + 0x25, 0x46, 0x80, 0x8f, 0x92, 0x5e, 0xa9, 0x4d, 0xc6, 0x70, 0x05, 0x05, 0x70, 0x79, 0xae, 0xc7, 0xf3, 0xd1, 0xcd, + 0xf6, 0x4a, 0x23, 0x09, 0x7d, 0x37, 0xac, 0x78, 0xb9, 0xb9, 0xee, 0x2a, 0x8b, 0x36, 0x9f, 0x62, 0x1c, 0xeb, 0x02, + 0x91, 0x19, 0x21, 0x62, 0x6e, 0xd9, 0xa0, 0x20, 0x1d, 0x6c, 0x17, 0x03, 0xf4, 0xb1, 0x81, 0xe1, 0x0c, 0x56, 0xba, + 0xaa, 0xad, 0x9d, 0xa7, 0xc8, 0xf4, 0x6f, 0xb6, 0x98, 0xc0, 0xcf, 0x17, 0x17, 0x24, 0x04, 0x24, 0x2c, 0xf4, 0xcc, + 0x83, 0x59, 0x0f, 0x27, 0x79, 0xf6, 0x12, 0x13, 0x2e, 0x64, 0xa8, 0x70, 0xfc, 0xa0, 0xad, 0xe6, 0x82, 0xe6, 0xf8, + 0xf5, 0x4c, 0x5b, 0x95, 0xaf, 0x95, 0x34, 0xc9, 0x82, 0x43, 0x5e, 0x38, 0x5d, 0xde, 0x32, 0x44, 0xf1, 0xa9, 0x76, + 0xdd, 0x77, 0xb8, 0xf9, 0x4c, 0x8a, 0x9c, 0x54, 0xda, 0x89, 0x40, 0xa5, 0x21, 0x93, 0xb7, 0x7b, 0x01, 0xb0, 0x6d, + 0x88, 0xbe, 0x68, 0x36, 0x32, 0x53, 0x99, 0x8e, 0xae, 0x96, 0x87, 0x70, 0x6c, 0x0f, 0x6f, 0x06, 0xc3, 0x10, 0xf0, + 0xfa, 0xb4, 0x66, 0xff, 0xba, 0x67, 0x25, 0x55, 0x15, 0x4d, 0x8c, 0x8a, 0xb8, 0xb9, 0x60, 0x72, 0x0f, 0x2a, 0xa6, + 0xc1, 0x43, 0x38, 0x69, 0xc0, 0xe9, 0x38, 0x53, 0xd9, 0x20, 0x79, 0x81, 0x49, 0x10, 0x7b, 0x02, 0x2d, 0x4d, 0xc0, + 0xbc, 0xa2, 0xec, 0x38, 0xda, 0x8c, 0xed, 0x88, 0x50, 0xce, 0x9c, 0x44, 0x45, 0xfc, 0x98, 0x7b, 0xd2, 0x0a, 0xb0, + 0xcf, 0x40, 0x77, 0xbd, 0xc6, 0x4f, 0x6a, 0x41, 0xd1, 0xb7, 0xb6, 0xff, 0x5f, 0x86, 0x41, 0xd8, 0x9e, 0xb6, 0x73, + 0x00, 0x0a, 0xb2, 0x84, 0x00, 0xfe, 0xf2, 0x82, 0xbe, 0x04, 0x59, 0x92, 0x0a, 0x3f, 0x90, 0x57, 0x8f, 0xad, 0x3e, + 0x55, 0xce, 0xbe, 0x3a, 0xfb, 0xf5, 0xb7, 0xec, 0x97, 0xf4, 0xc1, 0x25, 0x27, 0x77, 0xfb, 0x54, 0x62, 0x73, 0xbd, + 0x53, 0x2a, 0x1c, 0x9d, 0x63, 0xb9, 0xac, 0xaf, 0xc4, 0x70, 0x39, 0x95, 0x10, 0xfc, 0x87, 0x0f, 0xc4, 0xef, 0xb3, + 0x72, 0xb7, 0x4f, 0x21, 0xbf, 0x9f, 0x4b, 0x2b, 0xf9, 0xc9, 0xe1, 0x46, 0xba, 0x4f, 0xab, 0x28, 0xc7, 0x5c, 0x7f, + 0x5b, 0x4a, 0xe5, 0xac, 0xb3, 0xb3, 0x4b, 0xb9, 0xb9, 0x9c, 0x73, 0x78, 0xaa, 0xcb, 0xbd, 0x5e, 0xb5, 0xd6, 0xff, + 0x57, 0x66, 0x0d, 0x65, 0xb9, 0x19, 0x94, 0xcc, 0x7b, 0x28, 0x08, 0x72, 0x37, 0xb1, 0x4e, 0x2f, 0x72, 0xe7, 0xb8, + 0x43, 0x39, 0x96, 0xb6, 0xbe, 0x2a, 0x53, 0x8f, 0xcc, 0x45, 0x8c, 0xf3, 0x15, 0xf1, 0xb2, 0x9a, 0xbc, 0x6d, 0xd0, + 0x6f, 0x4f, 0xc8, 0xfc, 0xe7, 0xd7, 0x90, 0x64, 0x3f, 0xc6, 0x2f, 0xea, 0xfe, 0x02, 0x5c, 0xc3, 0x9b, 0x72, 0xe4, + 0x05, 0x3b, 0xae, 0xab, 0xa7, 0x6d, 0xb2, 0xae, 0x85, 0x63, 0xdb, 0xe5, 0xc0, 0x6b, 0x8b, 0x38, 0x04, 0x44, 0x69, + 0x65, 0xdc, 0x73, 0x7a, 0xd7, 0xe9, 0x77, 0xa6, 0x3a, 0x86, 0xdd, 0x80, 0x20, 0x11, 0x0c, 0x28, 0x30, 0x1f, 0x83, + 0xba, 0x93, 0x51, 0xe5, 0xc4, 0x9e, 0x35, 0x10, 0x4a, 0x60, 0x45, 0xf3, 0x35, 0x12, 0x80, 0x96, 0x76, 0xe0, 0x65, + 0xad, 0xa2, 0x93, 0x25, 0x6b, 0x10, 0x1c, 0xf4, 0xff, 0x88, 0xc1, 0x11, 0x07, 0xdf, 0x24, 0x21, 0xce, 0x0a, 0x45, + 0x62, 0x4e, 0xb3, 0x47, 0x1f, 0xb3, 0x8f, 0x72, 0x09, 0xd2, 0xec, 0x47, 0x60, 0x80, 0x60, 0x19, 0x8e, 0x63, 0x91, + 0xa0, 0x64, 0xbe, 0x2a, 0xc8, 0x92, 0x9a, 0xf7, 0x9f, 0x60, 0x6c, 0xff, 0x46, 0xb7, 0x8d, 0xec, 0xef, 0x9a, 0x4a, + 0x6e, 0x7f, 0xe5, 0xdd, 0xf2, 0xeb, 0xfa, 0x7a, 0x79, 0xa1, 0xfe, 0xfc, 0xba, 0x69, 0x81, 0x77, 0x72, 0xf7, 0x52, + 0x0e, 0x35, 0x3f, 0x5f, 0x67, 0xc4, 0x58, 0x30, 0x40, 0xec, 0x53, 0xc7, 0x87, 0x92, 0xee, 0xb7, 0x9e, 0x0d, 0xac, + 0x89, 0xfd, 0x1a, 0xb7, 0xa8, 0x5e, 0xce, 0x0b, 0x6c, 0x56, 0xe3, 0x1a, 0xba, 0xe7, 0x85, 0xd6, 0x3c, 0x17, 0x66, + 0xa9, 0xa0, 0x14, 0x5b, 0x53, 0xc0, 0x27, 0xb8, 0xeb, 0xca, 0x4d, 0x6a, 0xa2, 0xea, 0x4d, 0x78, 0x92, 0xa0, 0xa2, + 0x03, 0x17, 0x4d, 0x5f, 0x3d, 0xb5, 0x2d, 0x36, 0x86, 0x3f, 0x13, 0x74, 0x35, 0x86, 0xac, 0x46, 0x39, 0x66, 0x2d, + 0x56, 0x7a, 0xa1, 0xb5, 0xbc, 0x5a, 0xea, 0x6e, 0x5f, 0x03, 0xbd, 0xf2, 0x82, 0x32, 0xe0, 0x1e, 0x80, 0xac, 0x57, + 0xf4, 0x94, 0x56, 0x91, 0x2d, 0xd9, 0x27, 0x14, 0xdc, 0x3c, 0x9e, 0xe0, 0xb0, 0xf4, 0x51, 0xdd, 0x23, 0x4d, 0x62, + 0x2b, 0x5c, 0xc3, 0xde, 0x64, 0x55, 0xe9, 0x65, 0xf3, 0x84, 0x07, 0x98, 0xd3, 0x82, 0xfd, 0x1b, 0xdb, 0x62, 0xf9, + 0x71, 0x12, 0x68, 0xbb, 0x68, 0x14, 0x37, 0xca, 0x00, 0x88, 0xd2, 0x3d, 0xbd, 0x01, 0x07, 0xa2, 0x5d, 0xd7, 0x42, + 0x7d, 0x9b, 0xd8, 0x0e, 0xe7, 0x26, 0x13, 0x6a, 0xe1, 0xc2, 0x1a, 0xcd, 0xa6, 0x0b, 0x27, 0x6a, 0xef, 0xd2, 0x9e, + 0x27, 0x83, 0x8c, 0xff, 0x2a, 0x83, 0x98, 0xf4, 0xbd, 0xc0, 0xa3, 0x83, 0x70, 0x0f, 0xa1, 0x27, 0x61, 0x91, 0x8a, + 0xd6, 0x14, 0x6c, 0x83, 0x15, 0xa5, 0x71, 0x00, 0xa0, 0xbd, 0x8b, 0xb8, 0x01, 0x07, 0x37, 0x6c, 0x0c, 0x1d, 0x1b, + 0xb7, 0xe4, 0x95, 0x64, 0x82, 0xa0, 0xf2, 0x66, 0x89, 0xcd, 0x78, 0xb2, 0x13, 0x95, 0x6f, 0x70, 0xb3, 0x73, 0x27, + 0x14, 0xf6, 0x3b, 0x9d, 0x11, 0x4c, 0x59, 0x59, 0xed, 0xd0, 0x37, 0x23, 0x5e, 0x70, 0x98, 0x43, 0xb2, 0x20, 0x22, + 0x19, 0xb1, 0xaa, 0x1b, 0xbf, 0xf3, 0x7e, 0x94, 0x9b, 0x89, 0x6d, 0xb1, 0x5e, 0xf1, 0x8c, 0x60, 0xbd, 0x83, 0xa3, + 0x73, 0xf2, 0xdc, 0xcd, 0xc8, 0x5c, 0xe1, 0x3f, 0x86, 0xc9, 0xed, 0x66, 0x7e, 0x30, 0x8c, 0xa8, 0x2f, 0xff, 0x93, + 0x8c, 0x59, 0x55, 0x4e, 0xa3, 0x31, 0x24, 0x44, 0x32, 0xbc, 0x09, 0x40, 0x3c, 0xcf, 0x9a, 0x8c, 0xd1, 0x4c, 0xac, + 0xb6, 0xad, 0xd3, 0x34, 0xfb, 0xf6, 0x92, 0xd3, 0xef, 0x45, 0x85, 0x17, 0x78, 0x5c, 0x75, 0x6e, 0x64, 0xd7, 0x0f, + 0x74, 0x31, 0x87, 0xbe, 0x55, 0xe9, 0xaa, 0xbe, 0x91, 0x1f, 0x6a, 0xf8, 0x4a, 0x0c, 0xea, 0x6e, 0x50, 0xf2, 0x00, + 0x00, 0xfd, 0x71, 0x5e, 0x5e, 0xfd, 0x5f, 0xa3, 0xb9, 0x93, 0x4e, 0xb0, 0xb1, 0x62, 0x69, 0x8e, 0xe3, 0xe5, 0xd0, + 0x5f, 0xa8, 0xe8, 0x39, 0xa1, 0xdf, 0x8d, 0x48, 0xba, 0x44, 0x67, 0x18, 0x4f, 0xcc, 0xd2, 0xe0, 0xb0, 0x86, 0x12, + 0xfa, 0x9b, 0xd1, 0x6f, 0xd7, 0xde, 0x37, 0x90, 0xe2, 0xdf, 0xb8, 0xad, 0x8e, 0x67, 0x47, 0x95, 0x99, 0xd4, 0x32, + 0x0f, 0xdc, 0x16, 0x57, 0x75, 0xd5, 0xcc, 0xa7, 0xed, 0x92, 0x69, 0xda, 0x79, 0xcc, 0x2e, 0xe3, 0x57, 0x38, 0x91, + 0x44, 0x7d, 0xb7, 0x0e, 0x03, 0x34, 0x30, 0xd0, 0x5e, 0x12, 0xa7, 0x17, 0x99, 0xae, 0xde, 0x6a, 0x06, 0x43, 0x73, + 0xa5, 0x4e, 0x3f, 0xb0, 0x7a, 0x41, 0xcb, 0xb0, 0xb3, 0x66, 0xf2, 0xc8, 0x09, 0xb1, 0x8b, 0x9c, 0x9f, 0x98, 0x0f, + 0x39, 0xa1, 0xa6, 0x01, 0xbd, 0x9d, 0x97, 0x57, 0xae, 0x54, 0x91, 0x81, 0x9a, 0x09, 0x29, 0x20, 0xbb, 0xa1, 0xf5, + 0xb1, 0x26, 0xc6, 0x1e, 0xa4, 0x0b, 0xb3, 0xd6, 0x3c, 0x0d, 0x42, 0x53, 0x28, 0x0b, 0x57, 0x66, 0x64, 0xa3, 0xf0, + 0x3d, 0x39, 0x85, 0x86, 0x0b, 0x5a, 0x42, 0x7b, 0xf7, 0x3e, 0x24, 0x74, 0xf7, 0x98, 0x44, 0xd5, 0x74, 0x96, 0x16, + 0xca, 0xcd, 0x42, 0x79, 0x8e, 0xc0, 0x0b, 0x16, 0xb9, 0xe7, 0x55, 0x39, 0x12, 0xb7, 0xee, 0xd6, 0xe9, 0xeb, 0x6e, + 0xb5, 0x86, 0x7d, 0x4c, 0x79, 0x24, 0xbc, 0xa3, 0x85, 0xf9, 0x57, 0xb2, 0xe4, 0x48, 0x87, 0x8d, 0x9a, 0x66, 0xf2, + 0x15, 0x3e, 0xff, 0x47, 0x75, 0x6f, 0xe2, 0x7d, 0xe2, 0x59, 0x81, 0x70, 0x57, 0x14, 0x3a, 0xe3, 0x8e, 0x59, 0x47, + 0xeb, 0x70, 0x4e, 0x9d, 0x98, 0xf1, 0xf0, 0xb8, 0x40, 0x31, 0xfc, 0xf6, 0x8c, 0x06, 0xdc, 0xfd, 0xe9, 0x98, 0xd8, + 0xbd, 0x0e, 0x52, 0xec, 0x32, 0x8b, 0x74, 0x7f, 0xd5, 0x68, 0xaa, 0x0b, 0xb1, 0x6e, 0x95, 0xb9, 0x27, 0xa6, 0xec, + 0x30, 0x9c, 0x51, 0xed, 0xb3, 0x85, 0x9b, 0xbd, 0x91, 0xbb, 0x51, 0xd5, 0x53, 0x6c, 0xe9, 0x92, 0xc3, 0x13, 0x38, + 0x64, 0xd3, 0xa8, 0xdc, 0xfd, 0x5a, 0xcb, 0x57, 0xfb, 0x6a, 0xd1, 0x97, 0x58, 0xc4, 0xf7, 0xf3, 0x21, 0x85, 0x2d, + 0x4f, 0x44, 0xb6, 0x3a, 0x8c, 0x75, 0x80, 0xf1, 0x50, 0xeb, 0xdb, 0xcd, 0x4e, 0x6a, 0x3f, 0xa0, 0xbb, 0x75, 0x96, + 0x96, 0x6f, 0x16, 0xbf, 0xad, 0xff, 0x3c, 0x70, 0x2f, 0x39, 0x14, 0xbf, 0x56, 0x5f, 0x45, 0xa2, 0xc1, 0xfd, 0xb2, + 0x5c, 0x93, 0x49, 0x71, 0xfc, 0x04, 0xc7, 0x54, 0xa6, 0x28, 0x47, 0xd5, 0x6d, 0x37, 0x84, 0x8a, 0x8d, 0x8e, 0xcd, + 0x79, 0xb2, 0x33, 0x75, 0xf5, 0x00, 0x8f, 0x0c, 0x51, 0xfb, 0x9f, 0xca, 0x8b, 0xd3, 0x1e, 0xd9, 0x07, 0xfb, 0xb7, + 0xcc, 0x21, 0xb6, 0x4e, 0xbb, 0x4e, 0xad, 0x9a, 0x70, 0xe0, 0xc3, 0xea, 0x1a, 0xff, 0x17, 0x2f, 0xb8, 0xd1, 0x44, + 0xf4, 0x56, 0xb5, 0x65, 0xa5, 0x04, 0xb6, 0xab, 0x5d, 0x2a, 0x35, 0xbd, 0xd5, 0x4d, 0x8c, 0xcb, 0x9c, 0xd7, 0xd5, + 0xde, 0x90, 0xf5, 0x93, 0xa0, 0x0d, 0xb9, 0x7f, 0xfa, 0x30, 0xe2, 0x10, 0x23, 0x29, 0x6b, 0x17, 0x63, 0xae, 0x0d, + 0xa1, 0x93, 0x2d, 0xca, 0x98, 0xdc, 0xf5, 0x4f, 0x24, 0xaa, 0x2e, 0x9a, 0x20, 0x10, 0xe7, 0xed, 0xb1, 0xf5, 0xea, + 0x6e, 0x71, 0xc9, 0xcd, 0x70, 0x65, 0xaa, 0x12, 0xf0, 0x79, 0x62, 0xf0, 0xc5, 0x82, 0x44, 0x09, 0x3c, 0x0b, 0xd5, + 0x64, 0xdc, 0x35, 0x44, 0x1f, 0x6c, 0xbc, 0xfc, 0xc3, 0xc8, 0x31, 0x3f, 0xf3, 0x4f, 0xca, 0x1b, 0x44, 0x27, 0xc0, + 0x99, 0x00, 0x3c, 0x9e, 0xa5, 0x25, 0xd5, 0x37, 0xa7, 0x7f, 0x6d, 0x92, 0xff, 0x77, 0x6c, 0xf8, 0x56, 0xfb, 0x15, + 0xd0, 0x68, 0x61, 0xd8, 0x21, 0xd0, 0x1a, 0xd4, 0x39, 0x85, 0x71, 0x0f, 0x01, 0xb5, 0xe2, 0x1a, 0xd7, 0x77, 0x69, + 0x84, 0x30, 0x08, 0x49, 0x50, 0xd9, 0x1d, 0x76, 0xb8, 0xb7, 0xbe, 0x2f, 0x90, 0x01, 0xc2, 0x43, 0x19, 0x41, 0x8b, + 0x8c, 0x07, 0xf7, 0x06, 0x7b, 0x10, 0xd6, 0xb9, 0x94, 0x53, 0xae, 0x92, 0xae, 0x43, 0xf6, 0x71, 0xd3, 0xf4, 0x1a, + 0x27, 0xe4, 0x08, 0x52, 0xa9, 0x67, 0x40, 0xd3, 0x74, 0x91, 0x5e, 0xae, 0xb7, 0x74, 0xca, 0xb7, 0x06, 0x62, 0xeb, + 0x5a, 0x58, 0x74, 0x9f, 0x5d, 0xca, 0x43, 0x0f, 0x52, 0x08, 0x0e, 0x89, 0xe5, 0x14, 0xd4, 0x0f, 0x60, 0x52, 0x2e, + 0xff, 0xc3, 0x24, 0x5e, 0xe5, 0xee, 0xfe, 0xd7, 0x6a, 0xb1, 0xaa, 0x1e, 0xcc, 0x6c, 0xfc, 0x40, 0xf7, 0x97, 0xf0, + 0x51, 0xad, 0x3d, 0x5f, 0x39, 0x66, 0x05, 0xa6, 0x0c, 0xfe, 0x93, 0x7f, 0xd0, 0x86, 0x3a, 0x97, 0xf9, 0x6f, 0x71, + 0x25, 0xae, 0x81, 0x14, 0xe7, 0x3d, 0xd4, 0x88, 0x26, 0x69, 0xbc, 0x4c, 0x59, 0x6d, 0x1a, 0x9f, 0x66, 0x8a, 0x40, + 0x88, 0x3a, 0x7a, 0x1d, 0x2e, 0x39, 0x70, 0x91, 0xc3, 0xaa, 0x05, 0xf8, 0x67, 0xc1, 0x0a, 0xe8, 0xf6, 0xb7, 0xe4, + 0x68, 0xcd, 0xfc, 0xed, 0x8e, 0xc6, 0x95, 0x0b, 0x39, 0x34, 0xb1, 0xf6, 0xd5, 0x76, 0x4c, 0xce, 0xd4, 0x9d, 0xa7, + 0x15, 0x8a, 0xae, 0xab, 0x9b, 0x89, 0x2b, 0x02, 0x8e, 0x53, 0xcf, 0x0f, 0x02, 0x0c, 0x66, 0x85, 0x2f, 0xfb, 0x42, + 0x4d, 0xbf, 0xc6, 0x60, 0x0a, 0x32, 0x96, 0x3d, 0x8b, 0x62, 0x78, 0x17, 0xf2, 0x2a, 0x62, 0x2c, 0x97, 0x22, 0x56, + 0x08, 0x65, 0x01, 0x5b, 0x56, 0xae, 0x47, 0xa1, 0x78, 0x78, 0x9c, 0xe2, 0xdd, 0xcc, 0x39, 0x52, 0xee, 0x12, 0xcc, + 0xee, 0x90, 0xf9, 0x49, 0x22, 0xf5, 0xda, 0xb5, 0x60, 0x93, 0x62, 0x8a, 0x5d, 0x51, 0xe4, 0x06, 0x87, 0x30, 0xe1, + 0xa8, 0x7b, 0x7b, 0xa3, 0x69, 0x22, 0xa1, 0x91, 0x28, 0x30, 0x23, 0xa4, 0xbb, 0xfe, 0xe3, 0xee, 0x4d, 0x3f, 0x99, + 0x32, 0x06, 0x11, 0xd0, 0x28, 0x7a, 0x06, 0x10, 0x7a, 0xbe, 0x4a, 0xb9, 0x64, 0x3a, 0xae, 0x60, 0xc4, 0x7d, 0x05, + 0x24, 0x5c, 0x34, 0x6e, 0xcd, 0x2f, 0xd1, 0x49, 0xa6, 0x78, 0x9a, 0x00, 0x45, 0xa3, 0xad, 0xf2, 0x6c, 0x28, 0x1f, + 0x79, 0x16, 0xac, 0x44, 0x3d, 0x69, 0x70, 0x14, 0x0c, 0xba, 0xd9, 0x48, 0xc2, 0x21, 0x35, 0x19, 0xc6, 0xc8, 0x30, + 0x38, 0xfa, 0x97, 0xb6, 0xca, 0x43, 0x6a, 0x5d, 0x2d, 0x14, 0x32, 0xa3, 0x07, 0x33, 0x3f, 0x98, 0xa8, 0x61, 0x55, + 0x0b, 0xf3, 0x41, 0xba, 0x76, 0x5a, 0x65, 0x94, 0x25, 0xc6, 0x69, 0xb0, 0x30, 0x86, 0x1c, 0x6a, 0x1c, 0xb0, 0xd9, + 0x40, 0xee, 0x6a, 0xce, 0xe6, 0x51, 0x33, 0x6e, 0xaf, 0x6b, 0x46, 0x9f, 0xfa, 0xe2, 0x56, 0x7f, 0x2e, 0xd3, 0x0d, + 0x3b, 0x56, 0xf9, 0x4b, 0xbf, 0xa8, 0xa6, 0x0f, 0x3d, 0xe6, 0x4d, 0x39, 0x18, 0x66, 0x78, 0xf5, 0x59, 0x58, 0x3c, + 0x48, 0x1a, 0x94, 0xf9, 0x52, 0xad, 0x1d, 0x6e, 0x7f, 0x3f, 0x30, 0xf4, 0x66, 0x37, 0x31, 0x49, 0x1a, 0x02, 0xe5, + 0x08, 0x89, 0x08, 0x8e, 0x59, 0xf1, 0x1f, 0x57, 0x95, 0xff, 0xbd, 0x53, 0x5f, 0xd0, 0x83, 0xf0, 0xd1, 0x5e, 0xf7, + 0x34, 0x0a, 0x98, 0xb3, 0x96, 0xed, 0xea, 0xd3, 0x84, 0x1a, 0xd2, 0x5f, 0x11, 0x32, 0x6e, 0x1c, 0xab, 0x7f, 0x74, + 0x53, 0xf2, 0x3b, 0x5d, 0x25, 0xf6, 0xd1, 0x5c, 0x9f, 0xd8, 0xa2, 0x4a, 0x3a, 0x3a, 0x36, 0xa7, 0x2d, 0x29, 0xcd, + 0x49, 0xf9, 0x56, 0x7b, 0x78, 0xda, 0x4a, 0x71, 0xc9, 0xe6, 0x3d, 0xb9, 0x9a, 0x27, 0x59, 0x6d, 0xcb, 0x71, 0x84, + 0x3b, 0xc8, 0xd7, 0xe7, 0x8c, 0xd2, 0xd1, 0x07, 0xab, 0x1f, 0xf7, 0x26, 0x81, 0xcc, 0xd3, 0x13, 0x70, 0xa3, 0x6b, + 0x57, 0x7a, 0x7c, 0x2b, 0x4e, 0xcc, 0x93, 0xf7, 0x43, 0xf6, 0x6b, 0x5c, 0xc9, 0x82, 0x8e, 0x7b, 0x5f, 0x35, 0x4c, + 0xb7, 0x19, 0xd3, 0x7e, 0xa4, 0x18, 0x8c, 0xe6, 0xab, 0x2c, 0x89, 0x0a, 0x62, 0xc1, 0x6b, 0xe2, 0x83, 0xd8, 0x00, + 0x40, 0xce, 0x68, 0x8b, 0x5a, 0x7a, 0x8c, 0x25, 0x51, 0xbc, 0xad, 0x40, 0xcd, 0x79, 0x76, 0x96, 0xd1, 0xaa, 0x3a, + 0xd1, 0xab, 0x53, 0xae, 0xd2, 0xec, 0x22, 0x74, 0x3d, 0x7c, 0x65, 0x29, 0x2a, 0x59, 0x56, 0xbd, 0x0b, 0xd3, 0x57, + 0xec, 0x95, 0x17, 0x48, 0x79, 0x57, 0x4a, 0x4d, 0x21, 0x23, 0x1b, 0x83, 0xc6, 0xd6, 0xd9, 0x4b, 0x2c, 0x6e, 0xb2, + 0x3c, 0x4a, 0x28, 0x7c, 0x31, 0xf7, 0x71, 0x7b, 0x2c, 0x55, 0xc5, 0x9c, 0x43, 0x98, 0x93, 0x2a, 0x9d, 0x74, 0x95, + 0x03, 0xf8, 0xd5, 0x65, 0x10, 0xd6, 0x48, 0xa1, 0x3a, 0xc7, 0x3d, 0x6c, 0x49, 0xa6, 0x63, 0x06, 0x19, 0x8b, 0xee, + 0xfa, 0x3b, 0x2a, 0x9d, 0xc7, 0x41, 0x74, 0x1f, 0xba, 0x5a, 0x21, 0xc2, 0x60, 0x7b, 0xd6, 0x92, 0x2b, 0x9e, 0x2b, + 0x8e, 0xb2, 0x2b, 0x31, 0xb5, 0x3c, 0x1b, 0xb2, 0x6d, 0xd1, 0x15, 0x4b, 0x65, 0x4d, 0x77, 0x57, 0x13, 0xa9, 0xe0, + 0xb1, 0x1f, 0x7f, 0xe0, 0xcb, 0x92, 0x91, 0x53, 0x99, 0xc4, 0xb2, 0x0c, 0x61, 0x6e, 0xdc, 0x10, 0x3c, 0xc1, 0x68, + 0xde, 0x92, 0x79, 0xca, 0x29, 0x85, 0xd2, 0xfb, 0x9f, 0x1b, 0x8f, 0x50, 0x36, 0xdb, 0x30, 0xbd, 0x65, 0xea, 0xbb, + 0xc4, 0xf5, 0xfc, 0x87, 0xe8, 0x94, 0x44, 0x0b, 0xde, 0x9f, 0x27, 0x32, 0xda, 0x54, 0xa8, 0xb0, 0x6e, 0x66, 0xbb, + 0xcf, 0xc1, 0xc6, 0x7f, 0x51, 0x49, 0x86, 0x1c, 0x54, 0x98, 0x5e, 0xb5, 0x63, 0xa1, 0x73, 0xc8, 0x5d, 0x6f, 0x28, + 0x88, 0x8d, 0xc0, 0x6e, 0x68, 0x05, 0x89, 0x34, 0x59, 0x88, 0x7d, 0x36, 0xaa, 0xba, 0x9b, 0x55, 0xa1, 0x06, 0xfc, + 0xf2, 0x17, 0xb1, 0x38, 0xbf, 0x40, 0x52, 0x7d, 0xc1, 0x21, 0x21, 0xf4, 0xc9, 0x6f, 0xc4, 0x5e, 0x0d, 0xbe, 0x88, + 0x95, 0x66, 0xdb, 0x31, 0xfa, 0x99, 0x9f, 0x8f, 0xbb, 0xee, 0x0c, 0x53, 0x74, 0xb8, 0x01, 0x8b, 0x11, 0x43, 0x4e, + 0x52, 0x37, 0xf9, 0x4b, 0x4a, 0x7e, 0x32, 0xbd, 0xf9, 0x06, 0xdf, 0x69, 0x6d, 0x6f, 0xa0, 0x50, 0x88, 0x59, 0x67, + 0x68, 0x70, 0xc3, 0x1e, 0x9e, 0xea, 0x98, 0x59, 0x98, 0xe3, 0x90, 0x24, 0xa2, 0x45, 0x0e, 0x67, 0x88, 0xdf, 0x00, + 0x98, 0x40, 0x93, 0x95, 0x08, 0x19, 0x25, 0xb0, 0x47, 0xf0, 0x82, 0x9b, 0x6d, 0xde, 0xef, 0x79, 0x1e, 0x2e, 0xa4, + 0x56, 0xae, 0xe0, 0x0a, 0x30, 0xd5, 0xb3, 0x6b, 0x49, 0xf1, 0xe1, 0x51, 0xb4, 0x86, 0x78, 0xae, 0x25, 0x94, 0xc5, + 0xce, 0x83, 0x60, 0x55, 0x65, 0x57, 0xd9, 0x19, 0xcc, 0x52, 0x0f, 0x0e, 0x54, 0x71, 0x81, 0x24, 0xdd, 0x18, 0x6f, + 0x53, 0xcc, 0xb2, 0x16, 0x7e, 0xaa, 0x62, 0xde, 0xb0, 0xa9, 0xe0, 0xf0, 0x5a, 0x9d, 0x7f, 0x31, 0xd6, 0x30, 0xa1, + 0x4d, 0x0d, 0xac, 0x04, 0x31, 0x69, 0x58, 0xc2, 0xc6, 0xc1, 0x67, 0xd0, 0x9f, 0x07, 0x4c, 0x33, 0x9c, 0xde, 0x8f, + 0x51, 0xbd, 0x65, 0xf5, 0xc9, 0xf7, 0xd2, 0xf3, 0x46, 0x1d, 0x3d, 0xa8, 0xc4, 0xaa, 0xe5, 0xeb, 0x0c, 0x11, 0xdd, + 0xde, 0xfa, 0x8c, 0xe7, 0xd4, 0x32, 0x04, 0x40, 0xe2, 0x49, 0x9d, 0x19, 0x7b, 0x7c, 0xdc, 0x30, 0x46, 0x52, 0xa5, + 0xb7, 0x2c, 0x42, 0xa6, 0x9f, 0x94, 0x55, 0x0d, 0x87, 0x27, 0x9b, 0x76, 0x25, 0x54, 0x0c, 0xd7, 0x6f, 0x96, 0x17, + 0x50, 0x85, 0xc5, 0x0c, 0xc5, 0x1c, 0x9b, 0xca, 0xd9, 0x78, 0x83, 0x79, 0x06, 0xe3, 0x3c, 0xa5, 0x31, 0x37, 0x54, + 0xa0, 0x5f, 0x2a, 0x47, 0x53, 0x67, 0x62, 0xce, 0x58, 0x9e, 0xfb, 0xb0, 0xe3, 0x73, 0xc7, 0x98, 0x5d, 0x78, 0xee, + 0xee, 0xa9, 0xc3, 0xf6, 0x59, 0x74, 0x19, 0xee, 0x6e, 0x61, 0xc9, 0x9e, 0x92, 0x49, 0x8c, 0x03, 0x58, 0xe7, 0xd1, + 0x95, 0xad, 0xf1, 0x52, 0x06, 0xbb, 0x3f, 0x41, 0x0c, 0xe0, 0x68, 0xc1, 0x60, 0x04, 0xec, 0x5a, 0x7e, 0xed, 0x6a, + 0xac, 0x74, 0xf3, 0x71, 0x60, 0x85, 0x17, 0x99, 0xc0, 0xe5, 0x23, 0x26, 0xd2, 0xe0, 0x7f, 0xde, 0xc7, 0xc9, 0x57, + 0x9b, 0x8e, 0x26, 0xb2, 0xd7, 0x42, 0xbe, 0xf0, 0xaf, 0xe1, 0x6e, 0x1e, 0x98, 0xf2, 0xc5, 0x1e, 0x4f, 0x11, 0x05, + 0x4d, 0x62, 0x6c, 0xf5, 0x8c, 0x8b, 0x3d, 0x73, 0xb5, 0xe1, 0x17, 0x22, 0x8a, 0xbb, 0xbb, 0xb8, 0x2c, 0x04, 0x2c, + 0x99, 0xf0, 0x53, 0xce, 0xd4, 0xc8, 0x94, 0x3d, 0xc4, 0xb7, 0xcb, 0xf0, 0xe1, 0x71, 0x23, 0xf6, 0xc9, 0x5d, 0x11, + 0x9e, 0x48, 0xaa, 0xb0, 0xcf, 0xfc, 0xef, 0x90, 0x31, 0x27, 0xa2, 0xe8, 0xb1, 0x4c, 0x37, 0x06, 0xcf, 0x7f, 0x56, + 0xf1, 0x64, 0x55, 0x00, 0xb6, 0x46, 0x05, 0xe9, 0x97, 0x80, 0x73, 0x0a, 0x40, 0x3d, 0x0c, 0x63, 0x20, 0xc5, 0x9c, + 0x42, 0xe0, 0xe8, 0x92, 0x76, 0xc0, 0xf0, 0xb3, 0x59, 0xd0, 0x63, 0xf1, 0x5b, 0xba, 0xdc, 0x6d, 0xce, 0xcf, 0xd6, + 0x28, 0x6f, 0x2a, 0x77, 0xd5, 0xb0, 0xca, 0x4c, 0x4d, 0x61, 0xb2, 0xd8, 0x9b, 0xb9, 0x0e, 0xdf, 0xf9, 0x63, 0x5f, + 0xbb, 0xc4, 0xc1, 0xc8, 0x8d, 0xcc, 0x15, 0x2e, 0x3c, 0x98, 0x76, 0xf2, 0x0a, 0x88, 0x9a, 0xad, 0x04, 0x57, 0x02, + 0xad, 0x07, 0xa7, 0x0e, 0x77, 0x0a, 0x58, 0x41, 0x20, 0xf3, 0xfa, 0xab, 0x3e, 0x39, 0x90, 0xd1, 0xe6, 0x0a, 0x19, + 0xf4, 0xdc, 0xea, 0x05, 0x5a, 0xe5, 0x7d, 0xab, 0xfb, 0x39, 0x79, 0x63, 0xde, 0x75, 0x1f, 0x81, 0xc9, 0xf7, 0x8c, + 0xc4, 0x86, 0x2c, 0xaf, 0x85, 0xc2, 0x24, 0x01, 0x3d, 0x0e, 0xaa, 0x0a, 0x89, 0xd4, 0xa1, 0x6c, 0xd4, 0x0c, 0x15, + 0xc2, 0xf4, 0xfa, 0x07, 0x80, 0x80, 0xa3, 0x94, 0x42, 0x79, 0x22, 0xaa, 0x32, 0x02, 0x08, 0x8c, 0x0d, 0xd0, 0xb0, + 0x0c, 0x4c, 0x61, 0x9b, 0x51, 0xb4, 0xe5, 0x74, 0xe9, 0x6e, 0xbc, 0x2f, 0x47, 0xe6, 0xbc, 0x1b, 0x3c, 0x4b, 0xd0, + 0x6e, 0xec, 0xeb, 0x38, 0x86, 0x7e, 0x2a, 0xfa, 0x47, 0xb0, 0x83, 0x73, 0x58, 0x82, 0x82, 0x53, 0x42, 0x9f, 0x33, + 0xff, 0x83, 0xaf, 0xc4, 0xeb, 0x9e, 0xb6, 0xb8, 0xb7, 0x63, 0xc7, 0xcc, 0xca, 0x8f, 0x4d, 0x96, 0x5c, 0xcb, 0x90, + 0x44, 0x79, 0xcd, 0xa5, 0x63, 0xd0, 0x94, 0xc8, 0xcd, 0x07, 0x81, 0xa4, 0xbd, 0x41, 0xe5, 0x47, 0x9b, 0xd3, 0xfe, + 0x48, 0x08, 0xb1, 0x5a, 0x6a, 0xe6, 0xe2, 0x4b, 0x8a, 0x05, 0x50, 0x70, 0x1f, 0xc0, 0xf9, 0x3b, 0x71, 0xfd, 0xbb, + 0xe8, 0xc0, 0xa1, 0x8f, 0x00, 0x06, 0xe0, 0xad, 0x54, 0x5b, 0x79, 0x13, 0x50, 0x5a, 0x01, 0x90, 0x6b, 0x53, 0x19, + 0xe0, 0x0d, 0xf9, 0x0b, 0x1e, 0xd9, 0x97, 0x29, 0x50, 0x8c, 0xe2, 0xc6, 0xbb, 0x4c, 0xe5, 0xe5, 0xdd, 0x31, 0xe7, + 0x82, 0xdd, 0xdc, 0x30, 0xaf, 0xda, 0x44, 0x99, 0xb4, 0x5d, 0x0c, 0x62, 0x9c, 0x12, 0xa4, 0x28, 0x01, 0xd2, 0xf7, + 0x0f, 0x66, 0x21, 0x7a, 0xfe, 0xee, 0xd1, 0x5d, 0x65, 0xae, 0xc3, 0x30, 0x9a, 0xec, 0x1d, 0x51, 0x0b, 0x72, 0xba, + 0x3a, 0x26, 0xdf, 0x27, 0x07, 0xe1, 0x5f, 0x12, 0xf5, 0x33, 0x55, 0x82, 0xa6, 0xfa, 0xa6, 0x8a, 0x38, 0xa8, 0xf1, + 0x09, 0x88, 0xda, 0x32, 0xa9, 0x09, 0x73, 0x25, 0xea, 0x93, 0xeb, 0x44, 0x60, 0x5a, 0xfd, 0xb3, 0x1f, 0x5f, 0xfd, + 0xc0, 0x60, 0x7b, 0xbf, 0x77, 0xf1, 0x75, 0xa6, 0x0f, 0xe7, 0xef, 0xd8, 0xbd, 0xfb, 0x3c, 0xb8, 0x71, 0x5c, 0x5d, + 0xd6, 0x23, 0x49, 0x23, 0x33, 0xc0, 0x7b, 0xca, 0xa0, 0x61, 0x2f, 0xca, 0xe6, 0xcc, 0x35, 0xbb, 0xcf, 0xba, 0xca, + 0x5d, 0x40, 0x3f, 0x22, 0x69, 0x35, 0xa1, 0xb8, 0x00, 0x6e, 0xe7, 0x31, 0xcd, 0x0a, 0xff, 0x83, 0x42, 0xcd, 0x04, + 0x7b, 0x19, 0x19, 0xa5, 0x2f, 0x23, 0x98, 0xaf, 0x16, 0x41, 0xb6, 0xac, 0x42, 0xbb, 0x8f, 0x1a, 0x6c, 0xd6, 0xae, + 0xcd, 0xb3, 0x7b, 0xcb, 0x01, 0x39, 0x13, 0x44, 0xe3, 0x45, 0xad, 0xe4, 0x59, 0x4f, 0xf5, 0xaa, 0xe7, 0x88, 0x9b, + 0xae, 0xdc, 0xab, 0x47, 0xa6, 0xf9, 0x78, 0x85, 0x77, 0x3f, 0xea, 0x22, 0xda, 0x95, 0xb5, 0x00, 0x56, 0x16, 0x43, + 0xf2, 0x3d, 0xeb, 0xef, 0x99, 0x74, 0x09, 0x16, 0x90, 0xfa, 0xc4, 0xeb, 0xda, 0x75, 0xd0, 0x91, 0x93, 0xba, 0xfd, + 0x28, 0x0a, 0x66, 0xa5, 0x45, 0x26, 0xe5, 0x89, 0xa4, 0x2b, 0xc9, 0x47, 0xae, 0x62, 0x66, 0x98, 0xe6, 0xd2, 0x19, + 0xf6, 0xa4, 0xbf, 0xaa, 0xda, 0xab, 0xed, 0x39, 0x04, 0xc0, 0x35, 0x4f, 0x21, 0x56, 0xef, 0x56, 0xd1, 0xc2, 0x9d, + 0xf1, 0x6e, 0xff, 0xa2, 0xb5, 0xe3, 0x61, 0xec, 0xd6, 0x30, 0x0e, 0x32, 0x67, 0x05, 0xf3, 0x9b, 0x1c, 0xd3, 0x70, + 0xcd, 0x68, 0xa3, 0x0b, 0x3e, 0xc5, 0xbe, 0x5c, 0xbd, 0x8f, 0xba, 0x87, 0x0a, 0x91, 0xde, 0x83, 0x67, 0x84, 0xaf, + 0x37, 0x7f, 0x6d, 0xd4, 0x6b, 0xdf, 0xd1, 0x58, 0xde, 0x58, 0x3a, 0x82, 0xc6, 0x3f, 0x26, 0x38, 0xa3, 0x30, 0xdf, + 0xc0, 0x9b, 0x26, 0x93, 0xb5, 0x09, 0xc7, 0x8e, 0xdc, 0x26, 0xc5, 0xa6, 0xa5, 0x2a, 0xdf, 0x25, 0xb0, 0x92, 0x5b, + 0xa6, 0xfd, 0xe2, 0x9e, 0x52, 0x8f, 0x0d, 0xc1, 0x42, 0xc5, 0x82, 0x00, 0x35, 0xe6, 0xaa, 0xbd, 0x99, 0x48, 0x06, + 0xa7, 0xb4, 0xfd, 0x6c, 0xfb, 0x0c, 0xb3, 0xb3, 0x26, 0x12, 0x82, 0xb3, 0x42, 0xcb, 0xa6, 0x9b, 0xb4, 0x91, 0x00, + 0x8d, 0x54, 0xa3, 0xd0, 0x64, 0x82, 0xc6, 0xce, 0x7b, 0x41, 0xee, 0x86, 0x0e, 0xa9, 0xeb, 0x0c, 0x4a, 0xf0, 0x85, + 0x23, 0x31, 0x4b, 0x77, 0x41, 0x69, 0x0d, 0xdd, 0x63, 0xa8, 0x5e, 0x6f, 0xbf, 0x0b, 0x9e, 0x91, 0xf1, 0xa6, 0x11, + 0x68, 0x8e, 0x41, 0x20, 0xdf, 0x04, 0x63, 0x02, 0x0e, 0xbc, 0xf3, 0xf2, 0xfb, 0x48, 0x44, 0xca, 0x0f, 0xb0, 0x01, + 0xbd, 0xcc, 0x37, 0x5e, 0x04, 0x2b, 0x52, 0xa5, 0x19, 0x16, 0x66, 0x8f, 0xc1, 0xbc, 0xed, 0x8e, 0x7e, 0x32, 0xfc, + 0xcc, 0x04, 0x2f, 0xf9, 0x93, 0xe7, 0xf4, 0xce, 0x10, 0x1e, 0x62, 0xf0, 0xc1, 0x58, 0xf5, 0xc0, 0xe3, 0x94, 0xc6, + 0x0d, 0x01, 0x2e, 0x9f, 0xfd, 0xc8, 0x7c, 0x10, 0xbb, 0x11, 0x80, 0x67, 0x17, 0x57, 0x19, 0x78, 0x9b, 0xa9, 0xab, + 0x93, 0x96, 0x4e, 0xee, 0x17, 0x62, 0xc4, 0x0c, 0x52, 0x31, 0x9f, 0xde, 0xc8, 0x28, 0x0d, 0xe2, 0xa2, 0x64, 0xc6, + 0x25, 0xc5, 0xae, 0x39, 0x6f, 0xe8, 0x96, 0x9f, 0x33, 0x45, 0xed, 0x9d, 0x1d, 0xeb, 0x78, 0xff, 0x8f, 0xf3, 0x27, + 0x5d, 0x30, 0xba, 0xbc, 0xb5, 0xae, 0x66, 0xdb, 0xf3, 0x4d, 0x4d, 0xa9, 0x81, 0xe1, 0x37, 0x26, 0xfc, 0xd1, 0xc7, + 0x4b, 0x4d, 0x41, 0x0d, 0x8d, 0x5d, 0x64, 0x53, 0x8a, 0xac, 0xf0, 0xc6, 0x31, 0x65, 0xbe, 0x04, 0x52, 0x2c, 0xc6, + 0x4f, 0x3e, 0x37, 0x1a, 0x5c, 0x33, 0x52, 0x1c, 0x0e, 0x09, 0xea, 0x45, 0x91, 0xb7, 0x9f, 0x3a, 0xf9, 0x1c, 0x57, + 0x6f, 0xe6, 0x37, 0x43, 0x60, 0xa6, 0xdb, 0x56, 0x5a, 0xac, 0x9b, 0xb6, 0xe2, 0xab, 0xb5, 0x4a, 0xe3, 0x29, 0x5a, + 0xe3, 0xbb, 0x1a, 0x87, 0xe9, 0x95, 0xea, 0xab, 0xe1, 0xd7, 0xbd, 0x8d, 0xcd, 0x8c, 0x66, 0x2e, 0x74, 0x90, 0x38, + 0x24, 0xbd, 0x54, 0x4d, 0xab, 0xa8, 0xc6, 0x9e, 0x1e, 0xab, 0x1a, 0x94, 0x88, 0x77, 0xe8, 0x24, 0xd6, 0x30, 0x5b, + 0x8f, 0x72, 0xfa, 0x61, 0xb5, 0x85, 0x5a, 0xb1, 0x33, 0x31, 0xa9, 0xa9, 0x37, 0x96, 0xe5, 0xd5, 0x56, 0xd5, 0xe7, + 0x74, 0xa0, 0xc3, 0x9f, 0xc3, 0x1d, 0x84, 0xef, 0x6e, 0x05, 0x9a, 0x10, 0x64, 0x2e, 0xb6, 0xf2, 0x75, 0x88, 0xef, + 0xd2, 0x1e, 0x8f, 0x25, 0x56, 0x2b, 0x12, 0x8d, 0x6f, 0xaa, 0x2a, 0x0c, 0xc8, 0x65, 0x46, 0x15, 0x4b, 0x7b, 0x65, + 0x54, 0xc8, 0x8a, 0xec, 0x8d, 0x04, 0x69, 0x55, 0xf0, 0x42, 0x90, 0xd2, 0x2c, 0x9a, 0x98, 0xcc, 0x5f, 0x0d, 0xef, + 0x92, 0x92, 0xcc, 0x26, 0xf8, 0xd3, 0x26, 0xce, 0x66, 0x14, 0x70, 0xb7, 0x52, 0x37, 0xb8, 0xd8, 0x9a, 0x71, 0x55, + 0xae, 0x20, 0xb7, 0x05, 0x07, 0x21, 0xab, 0xa2, 0x68, 0x61, 0x9f, 0xdf, 0xf9, 0xa7, 0x48, 0x53, 0x00, 0x40, 0xe4, + 0x35, 0xa1, 0x29, 0xbb, 0x69, 0x41, 0x66, 0xe9, 0x60, 0x19, 0xc0, 0x07, 0x2c, 0x85, 0xf2, 0xd0, 0x79, 0x1e, 0xd7, + 0xdd, 0xcb, 0x4c, 0x2d, 0x2a, 0x2d, 0x1b, 0x74, 0x4f, 0x07, 0x87, 0x5c, 0xaf, 0x74, 0xfa, 0xef, 0x8f, 0xd4, 0x56, + 0x5e, 0xa0, 0x0e, 0x2a, 0x7c, 0xf7, 0x51, 0xb5, 0x10, 0xe3, 0x50, 0xab, 0xff, 0xad, 0x28, 0xd1, 0x39, 0x05, 0x4f, + 0xa2, 0xd7, 0x3f, 0x56, 0xac, 0xd3, 0x2b, 0x26, 0x91, 0xf8, 0x72, 0x22, 0xa8, 0xdb, 0x66, 0x57, 0x5d, 0x72, 0xda, + 0x5c, 0x65, 0xf6, 0x9f, 0x0e, 0x78, 0xf6, 0xad, 0x77, 0x7e, 0xa7, 0x17, 0x77, 0x90, 0x44, 0xa1, 0xd0, 0xf3, 0x21, + 0x3e, 0xa0, 0xa3, 0xb2, 0xfa, 0x13, 0x91, 0x14, 0xab, 0x96, 0xcb, 0xd0, 0x80, 0x22, 0xc5, 0x4d, 0x19, 0xd5, 0x78, + 0xd0, 0xeb, 0x19, 0xbb, 0x04, 0x69, 0x74, 0xb3, 0x57, 0x2a, 0xc1, 0x49, 0x2b, 0xad, 0x3e, 0x2f, 0x41, 0x90, 0x6d, + 0xbc, 0x93, 0x5c, 0xa5, 0x58, 0x61, 0xf6, 0x58, 0x96, 0x95, 0x51, 0xd7, 0x50, 0x8c, 0xce, 0xb2, 0x8a, 0x5a, 0xe7, + 0xda, 0x6a, 0xa7, 0x08, 0xc5, 0x3a, 0x16, 0x00, 0x9b, 0x16, 0x4e, 0x07, 0x69, 0x61, 0x0b, 0x7a, 0x3a, 0xa9, 0xc6, + 0x25, 0xcd, 0x8e, 0xb1, 0xc8, 0xbb, 0x85, 0x41, 0xd0, 0x44, 0x5f, 0x77, 0x70, 0x53, 0x1e, 0x2b, 0x8a, 0x3a, 0xb8, + 0xde, 0xb1, 0x0c, 0xaf, 0x0e, 0xcd, 0x78, 0x81, 0xae, 0xa4, 0xec, 0x08, 0x95, 0x2b, 0x61, 0x27, 0x6d, 0x4a, 0x07, + 0x6d, 0x15, 0x7e, 0x68, 0x9e, 0x94, 0x8e, 0x05, 0xaf, 0x58, 0xa1, 0xc4, 0x35, 0xdd, 0x79, 0x0f, 0xeb, 0xa5, 0x9b, + 0x18, 0x23, 0xe4, 0x2b, 0xe2, 0xaf, 0x91, 0x22, 0xcc, 0x0d, 0x64, 0x0d, 0x2c, 0x64, 0x34, 0xc5, 0x24, 0x4c, 0x90, + 0xb1, 0xc7, 0x98, 0x78, 0xd1, 0x2d, 0x2e, 0xfd, 0x19, 0xb4, 0x41, 0x9b, 0x4d, 0x2b, 0xe9, 0x3e, 0x70, 0x85, 0xf6, + 0x7b, 0x3c, 0xe9, 0x90, 0x8f, 0x2d, 0x44, 0xcf, 0x14, 0x5c, 0xbe, 0x2e, 0xa1, 0x51, 0x7f, 0x00, 0x65, 0xed, 0x58, + 0x8a, 0xcd, 0x9a, 0x84, 0x1d, 0x98, 0x4e, 0x94, 0xf6, 0x7d, 0xf0, 0xa9, 0xc7, 0x5f, 0xbe, 0xde, 0x23, 0xf8, 0x0c, + 0x65, 0x4f, 0x14, 0x9b, 0x29, 0x86, 0x8a, 0xa6, 0xa6, 0xa0, 0x99, 0x0f, 0xce, 0xc2, 0x6d, 0xf1, 0x7a, 0x42, 0x2f, + 0x57, 0xbb, 0x75, 0x4f, 0xe5, 0xe3, 0x8a, 0x34, 0x40, 0xab, 0xcf, 0x1a, 0x95, 0x0f, 0xe6, 0xc9, 0x3d, 0xaf, 0x74, + 0xcf, 0x0f, 0xe8, 0xa1, 0xd1, 0xee, 0xe2, 0x4d, 0xd7, 0x32, 0x3e, 0xb4, 0x9b, 0xac, 0xcf, 0x60, 0x11, 0x7a, 0xa8, + 0xa1, 0x14, 0xcd, 0xe1, 0x26, 0xab, 0xd9, 0xf0, 0xee, 0x8d, 0x66, 0x6d, 0x29, 0x25, 0x7f, 0x6f, 0xe7, 0xc5, 0x36, + 0x9b, 0x2a, 0x9c, 0xde, 0x0f, 0xa4, 0x77, 0x09, 0x14, 0xcd, 0x91, 0xef, 0x4e, 0xa7, 0xa9, 0x7c, 0xd0, 0x4f, 0x80, + 0xa1, 0x82, 0xef, 0x1e, 0x69, 0x74, 0x67, 0x4d, 0x71, 0xbe, 0x82, 0x4b, 0x0f, 0xa3, 0xc6, 0xb6, 0x4b, 0x4f, 0x04, + 0xe1, 0xd4, 0xe2, 0x1e, 0xe9, 0x25, 0x45, 0x4b, 0x1d, 0x29, 0xe1, 0x9f, 0x22, 0x9c, 0x53, 0x8d, 0x1d, 0xed, 0x6c, + 0x1a, 0x6f, 0xa8, 0x20, 0x3d, 0x6a, 0x72, 0x4d, 0xfb, 0x12, 0x0a, 0xe0, 0xbf, 0x9d, 0xba, 0x12, 0xe1, 0x32, 0x21, + 0x37, 0xab, 0x8a, 0x4a, 0x83, 0x32, 0x00, 0x28, 0xbf, 0x5d, 0xcb, 0xe8, 0x1a, 0x3f, 0x5a, 0xa8, 0xcb, 0x12, 0x73, + 0xa0, 0x83, 0x16, 0x67, 0x77, 0x03, 0x2d, 0x92, 0x6d, 0x73, 0xea, 0xae, 0x51, 0xb5, 0xc5, 0x93, 0xc0, 0x4b, 0x44, + 0x63, 0x39, 0xeb, 0xe7, 0xf0, 0x6d, 0xda, 0x5e, 0x0f, 0xce, 0x3a, 0x40, 0xb7, 0xb0, 0xa0, 0xda, 0x9a, 0xb5, 0xfc, + 0x5e, 0x81, 0x0f, 0xf8, 0x51, 0x6c, 0xec, 0x3c, 0x76, 0x42, 0xcd, 0xc9, 0x0e, 0xbd, 0xb9, 0x49, 0x39, 0x27, 0xca, + 0x9c, 0x4e, 0x62, 0x1c, 0x85, 0x26, 0xea, 0x8c, 0x30, 0xf9, 0xd4, 0x6b, 0x32, 0x03, 0x1e, 0x7d, 0xe3, 0x22, 0x61, + 0x1f, 0x9c, 0x53, 0xc9, 0x96, 0xb5, 0x66, 0x93, 0x9b, 0x9f, 0x49, 0xb1, 0xc9, 0x98, 0x60, 0xbd, 0xa0, 0xf7, 0x37, + 0x44, 0x42, 0x18, 0x37, 0x84, 0x62, 0x68, 0x6a, 0x52, 0xe3, 0x69, 0x73, 0xa5, 0x64, 0x46, 0x97, 0x54, 0xbf, 0xac, + 0x2e, 0x28, 0x24, 0x5a, 0x51, 0xf0, 0xcb, 0x16, 0x8e, 0xbd, 0x46, 0x10, 0x7b, 0x06, 0xa0, 0x0f, 0x1d, 0xa0, 0x89, + 0x91, 0xdc, 0x6a, 0x6a, 0x4f, 0xb6, 0x04, 0x5e, 0x79, 0x19, 0xe2, 0x0d, 0xfb, 0x4d, 0x50, 0x09, 0x3c, 0xc7, 0xbe, + 0x59, 0x0e, 0x79, 0x0e, 0x97, 0xd5, 0x5d, 0x7d, 0x8a, 0xe8, 0xdc, 0xf9, 0xc2, 0xc3, 0x14, 0xbd, 0x43, 0xb5, 0x8f, + 0xd0, 0xd5, 0x2b, 0x79, 0x15, 0x73, 0x90, 0x83, 0x45, 0xdd, 0x98, 0x6c, 0x62, 0x57, 0xa7, 0x9e, 0x6b, 0x40, 0xb7, + 0xc7, 0x6e, 0x06, 0x62, 0x0f, 0x23, 0x26, 0xeb, 0x78, 0x4a, 0x6f, 0x11, 0x31, 0xda, 0x62, 0x22, 0xa9, 0x99, 0x34, + 0x6b, 0x52, 0x03, 0x39, 0x2d, 0xc2, 0x1c, 0xd4, 0x4f, 0x74, 0x8e, 0x3d, 0x12, 0xba, 0xb3, 0x6c, 0xbb, 0x46, 0x25, + 0x93, 0xdc, 0x61, 0xae, 0x50, 0x49, 0x08, 0xa9, 0x28, 0xbb, 0x92, 0x29, 0x30, 0xa5, 0x31, 0xe1, 0x1a, 0x57, 0x83, + 0x22, 0x43, 0x97, 0x0a, 0x6a, 0x6f, 0x9d, 0xa4, 0xd4, 0x39, 0x67, 0x0e, 0xf0, 0x29, 0x94, 0x3f, 0xab, 0x9a, 0x87, + 0x4d, 0xad, 0x40, 0xc5, 0xbd, 0x7a, 0xb9, 0x58, 0xf0, 0x66, 0xfe, 0x04, 0x85, 0x41, 0xa1, 0xaf, 0xa8, 0x29, 0xcf, + 0xe5, 0xa1, 0xac, 0x44, 0xdf, 0x8c, 0xbf, 0xa7, 0xf2, 0x8a, 0xc0, 0x65, 0xbe, 0x42, 0x24, 0xa6, 0xdf, 0x78, 0xa8, + 0x3f, 0x2d, 0x0b, 0x9b, 0x2a, 0x62, 0xfa, 0xf7, 0x93, 0xbf, 0x36, 0x90, 0xe0, 0x87, 0x9e, 0xd8, 0x2f, 0x5a, 0x08, + 0x3a, 0x16, 0x19, 0x54, 0x98, 0x23, 0x72, 0xa2, 0x00, 0x4e, 0xb2, 0x47, 0xd7, 0xcb, 0x4b, 0x6a, 0xe8, 0x08, 0x6e, + 0x81, 0x9c, 0xb0, 0xa2, 0x6a, 0x24, 0xcf, 0xfe, 0xde, 0x76, 0x4b, 0xaa, 0x53, 0x0e, 0x03, 0x36, 0x7f, 0xed, 0x69, + 0x19, 0xba, 0x7b, 0x1b, 0x04, 0xb0, 0x05, 0xbd, 0x1e, 0x87, 0x1f, 0x01, 0x34, 0x82, 0xc9, 0x0c, 0x19, 0xcb, 0xa7, + 0x86, 0xea, 0x55, 0x5f, 0x9e, 0x1c, 0x85, 0xb8, 0x75, 0x8a, 0x8c, 0x28, 0x5b, 0x41, 0x2e, 0x63, 0xcb, 0x6e, 0xbf, + 0x95, 0xfe, 0xc0, 0x0a, 0xaa, 0x6b, 0x15, 0x82, 0x1c, 0x8c, 0x49, 0x78, 0x23, 0x51, 0x61, 0xcd, 0xdf, 0x74, 0x06, + 0x78, 0xcb, 0x53, 0x38, 0x84, 0x7b, 0xbb, 0x03, 0x6a, 0x7d, 0x0d, 0x41, 0xa1, 0xa9, 0x1c, 0x38, 0x9b, 0xa2, 0x35, + 0x47, 0x1c, 0x9c, 0xcf, 0x61, 0xc3, 0xf2, 0x1e, 0x77, 0x33, 0xc4, 0x32, 0x88, 0x14, 0xd1, 0xe1, 0x90, 0xa5, 0xc5, + 0xa2, 0xc6, 0x16, 0xab, 0x90, 0xf6, 0x29, 0xce, 0x08, 0x37, 0x31, 0xa5, 0x38, 0xd1, 0x87, 0x97, 0x60, 0x78, 0x06, + 0xce, 0x30, 0x6b, 0xd7, 0x1e, 0x88, 0xdb, 0x1b, 0x3a, 0x5f, 0x7e, 0xc9, 0x8e, 0x32, 0x7f, 0xae, 0x3a, 0x03, 0x96, + 0xcf, 0x7e, 0xde, 0x13, 0xa0, 0xa7, 0x9f, 0x38, 0x6c, 0xab, 0x9f, 0x4a, 0xcf, 0x46, 0x6a, 0xac, 0xee, 0x99, 0x4e, + 0xce, 0xdc, 0xd6, 0x1b, 0x1e, 0xe8, 0xcc, 0x82, 0x84, 0x0f, 0x5e, 0x63, 0x1f, 0xb4, 0x91, 0x4a, 0xd2, 0x57, 0x3c, + 0x51, 0xde, 0x5b, 0xe0, 0x57, 0x0f, 0x64, 0xe5, 0x91, 0x0b, 0x12, 0xf4, 0x12, 0xda, 0xf3, 0x79, 0x74, 0xc6, 0xc1, + 0xb0, 0x37, 0xca, 0x27, 0xc6, 0x4b, 0x4c, 0xfa, 0xe6, 0xdb, 0x61, 0x88, 0x48, 0xdf, 0x47, 0x54, 0xe0, 0x84, 0x2c, + 0xa9, 0xf2, 0xf0, 0x46, 0xc2, 0x21, 0x9e, 0x4a, 0x74, 0xa6, 0x4e, 0xcd, 0x59, 0xb5, 0x58, 0x6c, 0x59, 0x79, 0xf5, + 0xda, 0x51, 0xe4, 0x77, 0x6c, 0xd5, 0x92, 0x76, 0xb2, 0xaf, 0x94, 0xa1, 0x55, 0x89, 0x33, 0x18, 0x19, 0x5d, 0xb0, + 0xd5, 0x8b, 0x24, 0x1f, 0xb2, 0x26, 0x2a, 0x1a, 0xd6, 0x95, 0xc9, 0xcc, 0x28, 0xb9, 0x95, 0xf5, 0x45, 0xda, 0xb1, + 0x5d, 0x78, 0xad, 0x42, 0x25, 0xe9, 0xa0, 0x9e, 0x93, 0xe4, 0xfc, 0x40, 0xda, 0x3a, 0xca, 0xdf, 0xb6, 0xaa, 0x93, + 0xeb, 0xa1, 0xa7, 0xec, 0x2a, 0x1d, 0x08, 0xf3, 0x55, 0xb2, 0x06, 0x81, 0x81, 0x7c, 0x77, 0x60, 0x3b, 0x06, 0x9d, + 0xbe, 0xdd, 0x1e, 0x99, 0x74, 0x3c, 0x05, 0x3a, 0x65, 0x14, 0x30, 0x4d, 0x14, 0x46, 0x57, 0x6b, 0xcc, 0xfe, 0xee, + 0x78, 0xe9, 0xbb, 0x82, 0x03, 0x55, 0xdc, 0xe9, 0x41, 0xf8, 0xe1, 0xde, 0xd5, 0xc6, 0xe0, 0x87, 0x53, 0x47, 0x4f, + 0xcc, 0xcc, 0x52, 0xcb, 0xbf, 0xaf, 0x77, 0x87, 0xdf, 0xc7, 0x29, 0xc4, 0xf0, 0x81, 0x5e, 0xc7, 0xee, 0x8b, 0xfa, + 0x57, 0xf1, 0x32, 0x97, 0xf8, 0xc2, 0x0f, 0x5d, 0xd1, 0xec, 0xa6, 0xde, 0x95, 0x35, 0xcc, 0xa1, 0x6f, 0xc5, 0xda, + 0x48, 0xe5, 0x16, 0x58, 0xf7, 0x66, 0xb9, 0x13, 0x07, 0x0c, 0x38, 0xd7, 0x73, 0xc4, 0xc4, 0x67, 0xa6, 0x5a, 0xcf, + 0x24, 0x9d, 0x9a, 0xe9, 0x48, 0x86, 0x51, 0x0b, 0x58, 0x89, 0x89, 0x50, 0xdc, 0xe1, 0x01, 0x51, 0xd9, 0x21, 0x8f, + 0x7e, 0x2c, 0xf4, 0x6d, 0x4a, 0x28, 0x1b, 0xbe, 0x82, 0x97, 0x27, 0x97, 0x3f, 0x18, 0xd9, 0x78, 0xdc, 0xfc, 0xb1, + 0xd2, 0x8b, 0x97, 0x33, 0x4f, 0xde, 0xa0, 0x88, 0xd5, 0x79, 0x82, 0xe5, 0x01, 0x12, 0x9b, 0x33, 0x37, 0xd0, 0x49, + 0x30, 0xf5, 0x46, 0x37, 0xbf, 0x14, 0xc1, 0xad, 0xb6, 0x0d, 0x4e, 0xf9, 0x99, 0xe9, 0x1e, 0x85, 0xe2, 0x27, 0x3f, + 0xc3, 0x92, 0x59, 0x36, 0x4e, 0xc0, 0xc9, 0xb2, 0x2b, 0x0f, 0x3e, 0x6d, 0x7d, 0xf1, 0x61, 0x7d, 0x61, 0xfd, 0x79, + 0x8a, 0xb1, 0xfe, 0xfc, 0x92, 0xde, 0xdc, 0x3b, 0xac, 0x83, 0xd8, 0x7a, 0x74, 0x83, 0xfe, 0x29, 0x35, 0xec, 0xfc, + 0xb1, 0x33, 0x84, 0x0a, 0x11, 0x6a, 0xbc, 0x41, 0x58, 0x70, 0xee, 0x8e, 0x94, 0xac, 0x9a, 0x31, 0x4e, 0x2b, 0x49, + 0x6b, 0xc0, 0xbe, 0xd2, 0xa4, 0xb4, 0xca, 0xed, 0x6a, 0x45, 0xcc, 0x2e, 0x4d, 0xed, 0x50, 0x60, 0xd1, 0x77, 0x52, + 0x92, 0x24, 0xe7, 0xa5, 0x67, 0xf7, 0x48, 0x6d, 0x47, 0x40, 0xe5, 0xea, 0xbe, 0x40, 0x30, 0x6e, 0x6f, 0x77, 0x07, + 0xaa, 0xa6, 0xbe, 0x83, 0x41, 0x3d, 0xf2, 0x52, 0xff, 0x1f, 0x6c, 0x44, 0x6f, 0x5e, 0xfa, 0x0e, 0x50, 0x36, 0xa2, + 0xd9, 0xbb, 0x20, 0xd7, 0x01, 0xf2, 0x8e, 0x19, 0x4e, 0x55, 0xe5, 0x30, 0xca, 0xe8, 0xaf, 0x3e, 0x4b, 0xe1, 0xd2, + 0x7b, 0x87, 0x79, 0xb2, 0x49, 0x07, 0x9e, 0x05, 0x5b, 0xba, 0xf7, 0x12, 0x49, 0x60, 0xd9, 0x21, 0x21, 0x57, 0x69, + 0xdf, 0xa0, 0xcb, 0xaa, 0x53, 0x6d, 0x52, 0xf4, 0xd3, 0x8e, 0x1b, 0x3c, 0x62, 0x5a, 0x70, 0x8b, 0x74, 0x84, 0x5a, + 0x25, 0x84, 0x31, 0xe3, 0x29, 0x92, 0xd5, 0x80, 0xf0, 0x5a, 0x4d, 0x3c, 0x25, 0x8d, 0x28, 0x0f, 0x0c, 0x13, 0xdb, + 0x7b, 0xb1, 0xf3, 0x63, 0x17, 0xc4, 0x98, 0xdd, 0xba, 0xfb, 0x55, 0xf1, 0xa1, 0x3f, 0xc3, 0xb3, 0xb6, 0x3b, 0x99, + 0x4b, 0x48, 0x90, 0x38, 0xf4, 0x2f, 0x54, 0xfc, 0x5a, 0x23, 0x3c, 0x01, 0x0d, 0x56, 0x09, 0x86, 0xa9, 0x05, 0xbe, + 0x9d, 0xde, 0x67, 0xbd, 0x5e, 0x3d, 0x61, 0xe2, 0xe8, 0x16, 0xe0, 0xda, 0x23, 0x15, 0x97, 0xd3, 0x87, 0x03, 0xbb, + 0xaf, 0x96, 0x1a, 0xe8, 0xaa, 0x64, 0xb2, 0xf8, 0x4b, 0x6f, 0x9c, 0xff, 0x4d, 0x43, 0xd1, 0x81, 0x25, 0xfa, 0x39, + 0xbd, 0x16, 0x3b, 0xf7, 0xc9, 0x27, 0x12, 0x30, 0x1a, 0xc3, 0x93, 0x9c, 0x1e, 0x58, 0x15, 0x6d, 0x26, 0xdc, 0x9f, + 0x17, 0xa7, 0x09, 0x34, 0x76, 0xa0, 0x17, 0x37, 0x99, 0x6f, 0xe3, 0xdd, 0x95, 0xad, 0xee, 0xfd, 0x61, 0x59, 0xd5, + 0xbc, 0x4d, 0xea, 0xa8, 0xbb, 0x48, 0x10, 0xe2, 0x52, 0x47, 0xa8, 0x49, 0x57, 0x6c, 0xad, 0x39, 0x73, 0x71, 0x9a, + 0xc7, 0x56, 0x7e, 0x96, 0x6d, 0x79, 0x20, 0xeb, 0x85, 0x58, 0xd5, 0x6c, 0xd4, 0x04, 0x29, 0x43, 0x5d, 0x88, 0xee, + 0x32, 0xa2, 0x82, 0x16, 0xab, 0x5f, 0xd7, 0xb1, 0x32, 0xdd, 0xa7, 0xe9, 0x68, 0x42, 0xe0, 0xf7, 0x71, 0x00, 0x46, + 0xb4, 0xfe, 0x15, 0x83, 0xa6, 0xd6, 0x28, 0x39, 0x8d, 0x4e, 0x84, 0x88, 0x43, 0xdb, 0x34, 0x06, 0xbc, 0x74, 0xf9, + 0x99, 0x1c, 0x62, 0xaa, 0x05, 0xc6, 0x1b, 0x18, 0xaf, 0x87, 0xb6, 0x98, 0x72, 0xe7, 0xe9, 0x55, 0x65, 0x94, 0xf1, + 0xc9, 0xfd, 0xcc, 0xeb, 0x9e, 0x7d, 0x40, 0xc9, 0x00, 0x84, 0x0a, 0xaf, 0x55, 0x18, 0x32, 0x58, 0x25, 0xf8, 0xf3, + 0x16, 0x63, 0xf0, 0x73, 0xdb, 0x9c, 0x87, 0xf9, 0x10, 0x2b, 0xec, 0x30, 0x0b, 0xf4, 0xe9, 0x79, 0x01, 0xd3, 0x03, + 0xd9, 0xd9, 0xb3, 0xd2, 0x96, 0x51, 0x5a, 0x22, 0x60, 0x57, 0xb8, 0x4e, 0x01, 0x2c, 0x2a, 0x81, 0xc7, 0x41, 0x94, + 0x40, 0x1b, 0xfb, 0x81, 0x68, 0xca, 0x12, 0x52, 0x00, 0xab, 0xd5, 0x9f, 0x01, 0xec, 0xa0, 0x24, 0xdb, 0xce, 0xae, + 0x09, 0x91, 0xd9, 0x7a, 0xa4, 0xbd, 0xea, 0x30, 0x2d, 0xfa, 0xe7, 0xc4, 0x59, 0x9a, 0x18, 0xfb, 0x28, 0x89, 0x8f, + 0x1a, 0x37, 0x30, 0x25, 0x12, 0x74, 0x23, 0x0f, 0xc0, 0xcd, 0x2d, 0xf7, 0xe4, 0xbc, 0xd3, 0x9b, 0x03, 0x18, 0xe4, + 0xf4, 0x4c, 0x7f, 0xed, 0xc0, 0x82, 0xfb, 0xcf, 0x25, 0xea, 0xe8, 0x69, 0x09, 0xc9, 0x04, 0x2e, 0x7e, 0x34, 0xee, + 0x99, 0x06, 0x02, 0x62, 0xcf, 0x85, 0x51, 0x0b, 0x18, 0xfc, 0xd4, 0x11, 0xaf, 0x69, 0xcf, 0x92, 0x0e, 0xa3, 0xd2, + 0xf7, 0x44, 0x3a, 0xd5, 0xb6, 0x47, 0xa6, 0x7b, 0x9d, 0xc6, 0xd4, 0x87, 0xc8, 0x07, 0x53, 0xb8, 0x52, 0x04, 0xc0, + 0xf9, 0x1f, 0x0f, 0x58, 0xee, 0xdf, 0xc4, 0x8a, 0xae, 0x90, 0xe7, 0xda, 0x98, 0x72, 0x58, 0x25, 0x03, 0x5b, 0xc6, + 0x65, 0x47, 0x4c, 0x98, 0x8d, 0x99, 0x56, 0x46, 0x6f, 0xe6, 0xc8, 0x19, 0xa4, 0xb2, 0x31, 0x5c, 0x44, 0x39, 0xb5, + 0x25, 0x20, 0x21, 0xaa, 0x02, 0x18, 0x3c, 0xbd, 0x85, 0x8d, 0x95, 0xd4, 0xa6, 0x74, 0x26, 0x18, 0xaa, 0x21, 0xca, + 0x57, 0x39, 0xb1, 0x9d, 0xca, 0xd1, 0x7c, 0xa0, 0xc9, 0xea, 0x6f, 0x9f, 0x16, 0xee, 0x63, 0x87, 0xe7, 0xbd, 0x4e, + 0x9e, 0x99, 0x14, 0xe8, 0xd3, 0x96, 0xb9, 0x73, 0xe9, 0xc4, 0x65, 0xf1, 0xd2, 0x74, 0xb1, 0x5f, 0x9c, 0xf5, 0x4d, + 0x0a, 0xb2, 0x6c, 0xed, 0xd7, 0x83, 0xb9, 0xc3, 0xb6, 0x98, 0x3a, 0x8f, 0x45, 0x80, 0xcb, 0x12, 0x51, 0xba, 0x96, + 0x09, 0x81, 0x4d, 0xcb, 0xbc, 0x30, 0x9b, 0xd1, 0xe6, 0x0a, 0x2f, 0xcf, 0x47, 0x35, 0xad, 0xc9, 0x15, 0x7a, 0xdd, + 0xa7, 0xd3, 0x77, 0x42, 0xfe, 0x79, 0x39, 0xea, 0x9e, 0x59, 0xca, 0x40, 0x54, 0xed, 0x94, 0x0e, 0x3c, 0xe9, 0xc0, + 0xce, 0xb6, 0xa6, 0x6f, 0xdf, 0x2f, 0xfe, 0xd1, 0x3e, 0x99, 0x3a, 0xb7, 0xa1, 0xb5, 0xe8, 0xf8, 0xfd, 0x1e, 0x51, + 0xbb, 0x64, 0x85, 0x23, 0x04, 0x2a, 0xcf, 0x18, 0xd8, 0xa4, 0xde, 0xcc, 0x59, 0xdc, 0xf8, 0x48, 0xb5, 0xe8, 0x16, + 0x0e, 0xf0, 0x58, 0xdf, 0xfd, 0xea, 0x4f, 0xaa, 0x6e, 0xcf, 0xff, 0xda, 0x9e, 0x84, 0x76, 0x93, 0x7f, 0x6d, 0x6c, + 0xfd, 0xc7, 0xce, 0xc8, 0x72, 0x05, 0xd1, 0xf3, 0xda, 0x7a, 0xb5, 0x24, 0x1c, 0xbc, 0xc3, 0xdc, 0x3d, 0x01, 0xdf, + 0x8e, 0xbf, 0x35, 0xcd, 0x80, 0xa4, 0x65, 0x16, 0xad, 0x8d, 0x5c, 0xe3, 0x25, 0x0c, 0x28, 0x43, 0xd9, 0x15, 0xce, + 0x54, 0x1b, 0x43, 0xf3, 0xeb, 0x1d, 0xb7, 0x6f, 0x1b, 0x6c, 0xdc, 0xa2, 0x5b, 0x45, 0x37, 0x71, 0x61, 0x75, 0x78, + 0xa6, 0xb8, 0xca, 0xe6, 0x54, 0xb9, 0xca, 0xf8, 0xbb, 0x60, 0xa8, 0x0e, 0x03, 0x6e, 0x33, 0xec, 0xc2, 0x75, 0xe7, + 0xa1, 0x0b, 0x15, 0x45, 0x30, 0x2c, 0x48, 0xa5, 0xe5, 0x04, 0x8a, 0x32, 0xb6, 0xc5, 0x86, 0xa2, 0x04, 0xff, 0xfa, + 0xf7, 0x8c, 0x97, 0x51, 0xc0, 0x37, 0x36, 0xb4, 0xc8, 0x6c, 0x85, 0xa6, 0x29, 0xe1, 0x67, 0x98, 0x92, 0xe3, 0xca, + 0x27, 0x8d, 0xdb, 0xe1, 0x7f, 0x15, 0x4d, 0x04, 0x0a, 0xa8, 0x13, 0x0b, 0x09, 0x99, 0x69, 0x33, 0x45, 0xaf, 0x30, + 0x84, 0xae, 0x48, 0xca, 0x07, 0x97, 0x39, 0xf8, 0xae, 0xcd, 0x3d, 0x77, 0x2d, 0x6f, 0x1e, 0x04, 0x5b, 0x92, 0x4d, + 0x90, 0x96, 0x14, 0x32, 0xc9, 0xc2, 0xda, 0x91, 0x81, 0xeb, 0x6b, 0x7b, 0xa1, 0xa0, 0x24, 0x59, 0x10, 0x89, 0xe7, + 0x6b, 0x6d, 0x91, 0x3a, 0x16, 0x7f, 0x61, 0xba, 0x9f, 0xe2, 0xd3, 0x5e, 0xf8, 0x81, 0xfa, 0x3a, 0xdc, 0x75, 0x5f, + 0x45, 0xb3, 0x21, 0x6e, 0xd5, 0x8f, 0x19, 0x15, 0xd7, 0x23, 0xa5, 0xfd, 0x58, 0xfe, 0xf9, 0xfb, 0x0d, 0x8b, 0xc9, + 0x00, 0xc7, 0xc3, 0x9b, 0x9b, 0xa9, 0xc3, 0x8c, 0xbd, 0x86, 0x54, 0x6d, 0xac, 0xbe, 0x01, 0xb9, 0x45, 0x0e, 0xd5, + 0xae, 0x89, 0xa2, 0x0e, 0xb8, 0x99, 0x08, 0x0e, 0xc4, 0x7d, 0x64, 0xce, 0xa8, 0xd7, 0x9e, 0x54, 0x73, 0xba, 0x94, + 0x69, 0xd1, 0x52, 0xcd, 0x18, 0x66, 0xca, 0x74, 0x54, 0x31, 0xa0, 0xae, 0xdc, 0xd9, 0x95, 0xe7, 0x7b, 0x7e, 0x2a, + 0xcb, 0x8b, 0x0d, 0x9b, 0xa1, 0x4b, 0x2d, 0xcc, 0x51, 0xbe, 0xea, 0xf3, 0xb8, 0xbf, 0xf1, 0x8a, 0xf7, 0x7a, 0x87, + 0xa1, 0x43, 0x2d, 0x3d, 0x66, 0x6f, 0xd6, 0xfa, 0x7a, 0x3e, 0xe3, 0x20, 0x2d, 0x6a, 0xa7, 0x82, 0x71, 0xce, 0xa2, + 0x80, 0x05, 0x78, 0x85, 0xdd, 0x11, 0x8c, 0x8f, 0x67, 0xf1, 0x88, 0x7e, 0x64, 0xec, 0xe6, 0x6d, 0xf3, 0x1a, 0x10, + 0xa4, 0xca, 0x8e, 0x7b, 0x4b, 0x17, 0x2a, 0x16, 0xd1, 0xd2, 0x3b, 0xd3, 0x29, 0x94, 0x8f, 0x15, 0x00, 0xa4, 0xee, + 0xf4, 0x66, 0x30, 0x1e, 0xca, 0xcd, 0x01, 0xc2, 0x8d, 0x9c, 0x19, 0x37, 0x26, 0x0a, 0x47, 0x37, 0x06, 0x84, 0x08, + 0x71, 0x35, 0xf0, 0x95, 0x97, 0xb4, 0x4f, 0x54, 0x2c, 0x0d, 0xf1, 0xbd, 0xf2, 0xe0, 0x3e, 0xdc, 0xda, 0x6f, 0x2f, + 0x4e, 0x55, 0xc9, 0xc1, 0x22, 0x14, 0x1b, 0xc5, 0x7b, 0xe3, 0x77, 0x2f, 0xec, 0x7e, 0x62, 0x31, 0xd7, 0x12, 0x01, + 0xe5, 0x96, 0xef, 0x97, 0x56, 0x4d, 0x9c, 0x3f, 0xfd, 0x87, 0x0f, 0xe5, 0x12, 0x72, 0xe4, 0xab, 0x58, 0x76, 0x40, + 0x66, 0xbe, 0xa2, 0x9f, 0x45, 0x59, 0x4d, 0xe1, 0x53, 0xde, 0xc2, 0xdd, 0x75, 0xc7, 0xb5, 0x0e, 0x00, 0x59, 0x38, + 0x44, 0xb3, 0xd1, 0xd3, 0x2e, 0x89, 0xd0, 0x36, 0xda, 0xf8, 0x96, 0x47, 0x9a, 0x51, 0x51, 0x51, 0x34, 0x2e, 0xcd, + 0x46, 0x3d, 0xa4, 0x20, 0x9e, 0xa0, 0x17, 0xdf, 0x86, 0x80, 0x7c, 0x74, 0xed, 0x9d, 0x12, 0xb3, 0x74, 0x6b, 0xe1, + 0xfb, 0xfe, 0x46, 0xa2, 0x9e, 0x02, 0xfd, 0x28, 0xc2, 0x64, 0x41, 0x33, 0xf2, 0x95, 0xff, 0x2e, 0x00, 0x6f, 0x62, + 0xd1, 0x3f, 0xb1, 0xf0, 0x67, 0xb2, 0xee, 0xe1, 0xab, 0x9d, 0xb8, 0xde, 0x2e, 0x9a, 0xd3, 0x41, 0xfb, 0x10, 0x94, + 0xaa, 0xbe, 0xc7, 0xe1, 0x4d, 0xa1, 0xf5, 0xcb, 0x8e, 0x5d, 0xb0, 0x15, 0x05, 0x03, 0x9e, 0x75, 0x4a, 0x34, 0x31, + 0x5d, 0x97, 0x15, 0x01, 0xc6, 0x12, 0x27, 0x90, 0x5b, 0x9d, 0xb3, 0x74, 0x94, 0x9b, 0xb3, 0x9b, 0x3c, 0x6b, 0x27, + 0xd7, 0xd1, 0xbe, 0x9d, 0xcc, 0x4a, 0x59, 0xe5, 0xba, 0x21, 0x34, 0x7b, 0xf9, 0xe4, 0x2c, 0x94, 0x8b, 0x42, 0x1d, + 0x15, 0x37, 0xb4, 0x6a, 0x4d, 0x56, 0xc0, 0xca, 0xc9, 0x45, 0xab, 0xf2, 0xe6, 0xe9, 0xd0, 0xb8, 0xc9, 0x36, 0xfd, + 0x58, 0xd1, 0x76, 0x07, 0x0a, 0xaf, 0x14, 0xd6, 0xf6, 0x1c, 0x6c, 0xc3, 0x89, 0x06, 0xc7, 0x7d, 0xbb, 0x6d, 0x40, + 0x54, 0x20, 0xbb, 0x98, 0x50, 0x62, 0x6b, 0xf9, 0x2f, 0x0e, 0x28, 0xbe, 0xbd, 0x9a, 0x5e, 0x47, 0x31, 0x32, 0x7c, + 0x53, 0xff, 0x1e, 0x08, 0xf0, 0x2f, 0x7c, 0x60, 0x6a, 0x67, 0x54, 0x45, 0x28, 0x6b, 0x37, 0xab, 0xd4, 0x1f, 0x15, + 0xb9, 0xa5, 0x49, 0x6a, 0xb6, 0x79, 0x7a, 0x82, 0x29, 0x2b, 0xda, 0x9b, 0xc3, 0x06, 0x7b, 0x74, 0x6d, 0x44, 0xd8, + 0x60, 0x42, 0x1c, 0xff, 0x83, 0x9d, 0x00, 0x9d, 0x48, 0xf1, 0x82, 0xcb, 0x71, 0x65, 0x29, 0x9a, 0x12, 0xcd, 0x4b, + 0x51, 0xfb, 0x14, 0xe6, 0x3d, 0xaf, 0x02, 0xae, 0x9b, 0x93, 0xa3, 0x6e, 0x87, 0x3e, 0x71, 0x8a, 0x38, 0xcf, 0x81, + 0x08, 0x7b, 0x2a, 0xa7, 0x5d, 0xbd, 0x59, 0x5b, 0x86, 0xb8, 0x6e, 0x56, 0x88, 0x90, 0x7c, 0x18, 0xa7, 0x62, 0x88, + 0xb1, 0x7d, 0x23, 0x73, 0xde, 0xe3, 0xab, 0x85, 0x28, 0xac, 0x70, 0x11, 0x8f, 0x91, 0xa5, 0x3f, 0x79, 0x05, 0xd1, + 0x9d, 0x51, 0x93, 0x60, 0xd6, 0xea, 0x64, 0xa4, 0x38, 0x53, 0xff, 0x02, 0x02, 0x43, 0x6d, 0x90, 0xd1, 0x41, 0x4d, + 0x95, 0xf9, 0xd1, 0xd3, 0x88, 0x1b, 0x1f, 0x38, 0xaa, 0x46, 0x9b, 0x90, 0x71, 0xa6, 0xd8, 0x16, 0xbf, 0x35, 0x77, + 0x4b, 0x00, 0x66, 0x77, 0x1d, 0xa8, 0x15, 0x71, 0x24, 0xa1, 0x55, 0x7f, 0xae, 0xfe, 0x7a, 0x89, 0x44, 0x71, 0x4e, + 0xe8, 0x63, 0xa0, 0xc5, 0x47, 0x98, 0xae, 0xe6, 0x62, 0x1b, 0x87, 0x1d, 0x47, 0xa2, 0x8a, 0xd3, 0xbb, 0xe8, 0x72, + 0x3f, 0x93, 0x60, 0xf7, 0x13, 0x22, 0x9e, 0xef, 0xad, 0x0b, 0x35, 0x0b, 0x47, 0x1f, 0xb6, 0x3f, 0x09, 0x12, 0x32, + 0xd4, 0x5f, 0x0b, 0x37, 0x47, 0xed, 0xd5, 0x4b, 0x2d, 0xa3, 0x0d, 0x3f, 0x2d, 0xa2, 0xc5, 0xa9, 0x00, 0x94, 0x0c, + 0xa3, 0xf3, 0xcf, 0x5f, 0xec, 0xb0, 0x9f, 0x83, 0x73, 0x0c, 0x26, 0x0f, 0x78, 0xc0, 0xcd, 0xdd, 0x4f, 0xe8, 0xda, + 0x52, 0xce, 0x08, 0x67, 0xac, 0x0d, 0x09, 0x56, 0xc6, 0xb9, 0x66, 0x6b, 0xe3, 0x45, 0xc3, 0x09, 0xe1, 0x08, 0x3a, + 0x68, 0x8c, 0x7a, 0x9e, 0x33, 0x9a, 0xa7, 0x58, 0xfd, 0xca, 0x19, 0x6f, 0xf9, 0x81, 0x9d, 0xcb, 0x15, 0x04, 0x55, + 0x17, 0x55, 0x62, 0x4d, 0x27, 0xda, 0x81, 0xcb, 0xfd, 0x25, 0x7b, 0xca, 0x22, 0x7f, 0xbb, 0xc0, 0xa4, 0xa6, 0x42, + 0x21, 0x67, 0x85, 0x1b, 0xda, 0x15, 0x82, 0xd5, 0x6a, 0xdc, 0xf0, 0x3b, 0x6f, 0x59, 0x96, 0xaa, 0x4e, 0xed, 0x46, + 0x35, 0x34, 0xc3, 0x84, 0x29, 0x6e, 0x68, 0x19, 0xdf, 0x91, 0x94, 0xd8, 0x59, 0xd7, 0x06, 0x73, 0xfa, 0x1f, 0x52, + 0x9c, 0x0a, 0x2d, 0x44, 0xa9, 0xfa, 0x1c, 0x34, 0x3a, 0x31, 0x4d, 0xd5, 0x79, 0x23, 0x77, 0x26, 0x07, 0x83, 0x9a, + 0xb2, 0xb1, 0x53, 0xf3, 0x8e, 0xe9, 0xc8, 0x0c, 0xfe, 0x8e, 0xfc, 0xe4, 0x21, 0xab, 0x65, 0x72, 0x99, 0xe8, 0x67, + 0xbd, 0xf1, 0xaa, 0x00, 0x14, 0xd6, 0x31, 0xa8, 0xd0, 0x3c, 0x6b, 0x2a, 0x6b, 0x55, 0x65, 0xba, 0x09, 0x5f, 0x75, + 0x4b, 0x03, 0x05, 0xcf, 0x94, 0xa7, 0x10, 0x51, 0x53, 0xe2, 0xa4, 0xd5, 0x43, 0xa8, 0x01, 0xe5, 0xe8, 0xbc, 0x88, + 0xb9, 0x8e, 0x95, 0x2a, 0x1b, 0xff, 0x72, 0xef, 0xa3, 0x75, 0xeb, 0x20, 0xef, 0x67, 0x36, 0xea, 0xfd, 0x22, 0x55, + 0x4e, 0xa1, 0xcf, 0x8f, 0x34, 0x8d, 0x35, 0x09, 0xb6, 0x71, 0x32, 0x90, 0x0a, 0x3a, 0xa9, 0xc0, 0xff, 0xcb, 0x94, + 0x33, 0x56, 0x4c, 0x2a, 0x40, 0xc5, 0x62, 0xed, 0x9a, 0x7f, 0xdd, 0x87, 0x05, 0x93, 0xa0, 0xee, 0x1f, 0x80, 0x5e, + 0x0b, 0xb9, 0x90, 0x5f, 0xad, 0xb7, 0xa1, 0xec, 0x7c, 0xc3, 0x49, 0xeb, 0x73, 0xf5, 0x93, 0x23, 0x17, 0xb1, 0x9a, + 0xa2, 0xcd, 0xb4, 0x9e, 0x3a, 0x4b, 0x98, 0xf0, 0xd3, 0x72, 0x6e, 0xba, 0x41, 0xe6, 0x1a, 0x47, 0xca, 0xcb, 0xec, + 0xe3, 0xa8, 0x55, 0x66, 0xe9, 0xd8, 0x86, 0x2a, 0x6a, 0x73, 0x3c, 0x73, 0xc6, 0xf8, 0x62, 0x4f, 0x9a, 0x6a, 0x57, + 0x56, 0xf2, 0xcd, 0xb5, 0x98, 0x37, 0x87, 0x32, 0x45, 0x3d, 0x32, 0xad, 0x93, 0x8b, 0x13, 0x2a, 0xb3, 0x02, 0xc0, + 0xdb, 0x90, 0x6c, 0x84, 0xc0, 0x2e, 0xd8, 0x8f, 0xb5, 0x78, 0xe9, 0x2e, 0xa5, 0x51, 0x82, 0x97, 0x10, 0x2b, 0xfa, + 0x87, 0xd2, 0x42, 0x83, 0x54, 0x57, 0x94, 0x2c, 0x0d, 0xf5, 0xdf, 0x4a, 0x0f, 0x27, 0x39, 0x6a, 0x70, 0x0e, 0xb5, + 0xc7, 0xc2, 0xa8, 0xf7, 0x63, 0xd2, 0xa3, 0x3c, 0xd6, 0x4b, 0x81, 0x4d, 0x96, 0xc0, 0xca, 0x09, 0x76, 0x17, 0x20, + 0xe5, 0xb5, 0x87, 0xbe, 0x56, 0x64, 0xc2, 0xe3, 0xf3, 0xe4, 0xd6, 0xa5, 0x65, 0xe0, 0x15, 0xf4, 0xae, 0xbd, 0xa1, + 0xd2, 0x02, 0x77, 0xbf, 0xc8, 0x95, 0xff, 0xe8, 0x50, 0x24, 0x1d, 0xf1, 0x54, 0x12, 0x78, 0x2b, 0xa9, 0xc1, 0xc0, + 0xad, 0x65, 0xc3, 0xb5, 0x69, 0x1b, 0x7d, 0xa8, 0x8f, 0xe3, 0x3b, 0x46, 0xab, 0xe0, 0x3f, 0x9f, 0x7e, 0xc3, 0x38, + 0xb4, 0xe0, 0xd9, 0xaa, 0x54, 0x59, 0xd7, 0x53, 0x47, 0xb2, 0xfd, 0xd5, 0xce, 0x5b, 0x04, 0xb3, 0x70, 0x25, 0x0b, + 0x4d, 0x02, 0x3a, 0xb6, 0x49, 0x16, 0xb8, 0x4d, 0x81, 0x99, 0x47, 0x3f, 0x45, 0x6f, 0x23, 0xd5, 0x38, 0x52, 0xb5, + 0x68, 0x12, 0xe3, 0x70, 0x41, 0x34, 0x79, 0x73, 0xb7, 0x2a, 0x02, 0x19, 0x1c, 0xc0, 0x2d, 0xbf, 0x33, 0xce, 0x3d, + 0xf5, 0x91, 0xd6, 0x3a, 0xf0, 0xbb, 0x6e, 0xb2, 0x5d, 0xda, 0xa1, 0x51, 0x4b, 0xf4, 0xb6, 0x1d, 0x35, 0x1a, 0x64, + 0xd8, 0x23, 0xc5, 0xd8, 0xbd, 0x8f, 0xcf, 0xea, 0x31, 0x83, 0x2c, 0xd1, 0x01, 0x5f, 0x77, 0x0d, 0x54, 0x2c, 0x32, + 0x90, 0xbb, 0x0b, 0x21, 0x51, 0x87, 0x6d, 0xb4, 0x00, 0x50, 0xfa, 0x04, 0xab, 0xef, 0xc4, 0x2d, 0xf5, 0x06, 0x94, + 0xf9, 0x3e, 0xa4, 0x94, 0x42, 0x7d, 0x51, 0x91, 0x29, 0x67, 0x8b, 0xc5, 0x8c, 0x22, 0x8c, 0x3c, 0x11, 0x19, 0x6a, + 0x13, 0xc4, 0x08, 0x9c, 0xde, 0x32, 0xaa, 0x7e, 0x6c, 0x2f, 0x03, 0x2d, 0xed, 0xb5, 0x88, 0xa9, 0xca, 0x19, 0xcf, + 0x01, 0x94, 0x80, 0xc1, 0x55, 0x00, 0x67, 0xa6, 0x7a, 0x57, 0xc6, 0x9c, 0x58, 0x66, 0x05, 0x0f, 0x94, 0x4e, 0x2e, + 0xc6, 0xd7, 0xc0, 0xf9, 0x8f, 0xad, 0x89, 0xab, 0xf8, 0xeb, 0xd7, 0x2d, 0x9f, 0x67, 0xff, 0x97, 0x89, 0x76, 0x75, + 0x06, 0xac, 0x9c, 0xb0, 0xcf, 0x13, 0xc4, 0xeb, 0x06, 0xdb, 0xcb, 0xd6, 0x62, 0xc5, 0x93, 0x5e, 0x7f, 0x6c, 0xb5, + 0xa4, 0x2c, 0xab, 0xe4, 0x57, 0x1b, 0x08, 0xa4, 0xf1, 0x9d, 0x49, 0x64, 0x90, 0x0a, 0x92, 0x62, 0xba, 0x11, 0xfc, + 0xee, 0x5b, 0xef, 0x61, 0x47, 0x1a, 0x78, 0xd9, 0xea, 0xc2, 0xf0, 0x99, 0xba, 0x5d, 0xd3, 0x49, 0xce, 0xe0, 0xcc, + 0x9b, 0x09, 0x47, 0x5b, 0xef, 0xf2, 0xe5, 0x0a, 0x2d, 0xfa, 0x3c, 0xf4, 0x2b, 0xba, 0x4d, 0x5a, 0x96, 0xc7, 0x3d, + 0xcc, 0xa0, 0xfe, 0xaf, 0x62, 0xcd, 0x69, 0xf4, 0x55, 0x51, 0x5f, 0x7a, 0x41, 0x2b, 0xcd, 0x6d, 0xad, 0x2d, 0xe4, + 0x74, 0x6e, 0x91, 0x7b, 0x30, 0x34, 0xed, 0xfb, 0x8f, 0x2a, 0xc2, 0x92, 0x3d, 0xa5, 0xad, 0xf7, 0xc9, 0x45, 0x2f, + 0xd5, 0xb9, 0x11, 0xff, 0x96, 0x53, 0x79, 0xd3, 0x3a, 0x6a, 0x64, 0x27, 0xfe, 0x0f, 0xd6, 0x4d, 0x94, 0x71, 0xb9, + 0x4e, 0xee, 0xb4, 0x83, 0xe2, 0xa8, 0x4b, 0x8e, 0x87, 0x38, 0xd7, 0x8c, 0x46, 0x7a, 0x25, 0xcc, 0x33, 0xa7, 0x55, + 0x85, 0x1e, 0x8b, 0x06, 0xc9, 0x1a, 0x1a, 0x90, 0x04, 0xa8, 0xc9, 0x09, 0x71, 0xea, 0x4e, 0x70, 0x6b, 0x40, 0x72, + 0x72, 0x89, 0x90, 0x9c, 0x16, 0xde, 0xe5, 0xe7, 0x0d, 0x19, 0xa2, 0x9c, 0xd7, 0x37, 0xb1, 0x23, 0x2a, 0x3e, 0x8b, + 0x6e, 0xb9, 0x6f, 0x11, 0x1a, 0x6d, 0x1f, 0x34, 0x9a, 0x8e, 0x39, 0xb0, 0xcb, 0x9b, 0x35, 0x68, 0x39, 0x33, 0x08, + 0xf9, 0xe9, 0x19, 0x34, 0x61, 0xc0, 0x6c, 0x85, 0x10, 0x73, 0x94, 0x6c, 0x95, 0x9a, 0x34, 0x06, 0xf5, 0xc4, 0x4e, + 0x1c, 0xa8, 0xcf, 0xcf, 0xba, 0x59, 0x29, 0xd9, 0x9c, 0x9a, 0xda, 0xf4, 0x03, 0xd8, 0xe2, 0x89, 0x36, 0x1f, 0x28, + 0xc3, 0x20, 0x0d, 0x57, 0x25, 0xc2, 0xdf, 0xa8, 0xa8, 0xf3, 0x65, 0x3e, 0x6f, 0xd8, 0x46, 0xd0, 0x88, 0x21, 0x03, + 0xb3, 0x13, 0xac, 0x81, 0x20, 0x58, 0x16, 0x67, 0x72, 0x96, 0xd2, 0xd9, 0x38, 0x96, 0x58, 0x0b, 0x05, 0xb4, 0xbc, + 0x4d, 0xce, 0x1d, 0x04, 0x50, 0x46, 0xa2, 0xc4, 0xb2, 0x8d, 0x88, 0x3e, 0x30, 0x09, 0xde, 0x10, 0x2b, 0xf8, 0x05, + 0xdf, 0x50, 0x3a, 0xe9, 0x40, 0x6d, 0x92, 0x3b, 0x85, 0xaa, 0x0c, 0x0e, 0xc6, 0xe1, 0x15, 0xff, 0xed, 0xca, 0x0f, + 0x0e, 0x6d, 0x22, 0xee, 0x2a, 0xe0, 0x92, 0xd1, 0x73, 0x08, 0xea, 0xe4, 0xda, 0xb2, 0x89, 0xef, 0x34, 0xda, 0xde, + 0x55, 0xb5, 0x2b, 0x8e, 0xf8, 0xfc, 0x51, 0x60, 0x14, 0xa4, 0x5c, 0xce, 0xfe, 0x8d, 0x27, 0x69, 0xa2, 0x39, 0xb7, + 0xef, 0x1d, 0x2e, 0x16, 0x69, 0xa6, 0x3a, 0x35, 0xbd, 0xb9, 0x58, 0xb5, 0x0f, 0x46, 0xae, 0xb5, 0x67, 0x67, 0x1c, + 0x47, 0x20, 0x05, 0xe5, 0x03, 0xfe, 0x0b, 0xa9, 0x1a, 0xf2, 0xf9, 0xd0, 0xcf, 0x01, 0xd5, 0x4c, 0xf1, 0x69, 0xd5, + 0xd6, 0xbe, 0x49, 0xb5, 0xe0, 0x7f, 0x73, 0x58, 0xa4, 0x75, 0xfd, 0xfd, 0xf9, 0x8b, 0xde, 0x36, 0xd2, 0xf1, 0x23, + 0xb1, 0x92, 0xfa, 0x13, 0xa0, 0xac, 0xbd, 0x19, 0xb3, 0x76, 0x10, 0x4e, 0x63, 0x4a, 0x21, 0xfa, 0x4f, 0xe2, 0x53, + 0x4f, 0x65, 0xf0, 0x0d, 0xd4, 0x0f, 0xde, 0xc4, 0x68, 0xe9, 0x67, 0x6d, 0x6a, 0x21, 0xfc, 0x2d, 0xe6, 0x8b, 0x5a, + 0x3d, 0xe8, 0x38, 0x0f, 0xb9, 0x78, 0xc5, 0xea, 0x3f, 0x7d, 0xf1, 0xe5, 0x6c, 0x61, 0xb0, 0x96, 0xb5, 0x07, 0xff, + 0x8f, 0xf3, 0x00, 0x20, 0x5b, 0x61, 0x58, 0x4b, 0x34, 0xd3, 0x2f, 0xad, 0xa7, 0x00, 0xdf, 0x9d, 0xa7, 0x52, 0x6c, + 0x4d, 0x8b, 0x95, 0xa9, 0x67, 0x3a, 0xa8, 0x57, 0x6a, 0x6b, 0xdc, 0x37, 0xd6, 0x87, 0xd1, 0xd0, 0x77, 0x30, 0x57, + 0xbc, 0x7e, 0x8c, 0xe9, 0xee, 0x9f, 0x26, 0x26, 0x86, 0xfd, 0x4e, 0x75, 0x4a, 0x9a, 0xa5, 0xbe, 0x6d, 0xc8, 0x99, + 0xdd, 0x26, 0x70, 0xdf, 0x64, 0x8a, 0x90, 0xe3, 0x7d, 0x72, 0x94, 0xa2, 0xa6, 0x7d, 0x4b, 0x25, 0xab, 0x5b, 0x0f, + 0x69, 0xc4, 0x2c, 0x35, 0xd0, 0xfb, 0xe2, 0x55, 0x81, 0x81, 0x87, 0xea, 0xbc, 0x7e, 0x8b, 0x02, 0x9e, 0xc1, 0x47, + 0xcb, 0xac, 0xda, 0xba, 0x04, 0x8e, 0x51, 0xeb, 0xc0, 0xfd, 0xf2, 0xc0, 0x1f, 0x29, 0xfa, 0xe2, 0x6d, 0xe4, 0x60, + 0x83, 0xd7, 0x53, 0x83, 0x53, 0x1e, 0x9e, 0x8d, 0xf5, 0x31, 0xe3, 0xa7, 0x95, 0xa3, 0xb0, 0x67, 0x5c, 0x3c, 0x99, + 0x5d, 0x8c, 0xc3, 0xa6, 0xdb, 0x2a, 0x27, 0x4a, 0xa6, 0x4c, 0xd7, 0x64, 0x7e, 0xc6, 0x85, 0x9e, 0x37, 0x6b, 0xb5, + 0x84, 0xcd, 0x0f, 0xfe, 0x70, 0x53, 0x5c, 0x19, 0x27, 0xa3, 0xd0, 0xfe, 0x1f, 0xd9, 0x99, 0xa6, 0x77, 0xa1, 0x46, + 0xe0, 0x52, 0x70, 0xb5, 0x54, 0x96, 0x46, 0xda, 0xcf, 0xf6, 0xe9, 0xfb, 0x24, 0x5f, 0x41, 0x9e, 0xfe, 0x92, 0x15, + 0x1b, 0x73, 0x92, 0x64, 0xff, 0xa8, 0x14, 0x32, 0x87, 0xaa, 0x45, 0x3b, 0x46, 0x5b, 0xf9, 0x09, 0x41, 0x7d, 0xd9, + 0x21, 0xea, 0x00, 0xcc, 0xb6, 0x4a, 0x79, 0xbf, 0x18, 0x68, 0x46, 0x51, 0xb6, 0x1c, 0xf4, 0xb5, 0x61, 0x06, 0x07, + 0xaf, 0x1a, 0xd6, 0xef, 0xbd, 0xac, 0x55, 0x32, 0x52, 0x69, 0xb3, 0xcc, 0x51, 0x6a, 0xf2, 0x74, 0xbf, 0xd4, 0xb9, + 0xe8, 0x9a, 0x38, 0xf8, 0xd9, 0xda, 0xf7, 0x60, 0xd7, 0x4e, 0xcb, 0xae, 0x14, 0xe6, 0x06, 0xc7, 0x79, 0xcc, 0x71, + 0x65, 0x03, 0x11, 0x6b, 0x16, 0x5a, 0xde, 0x14, 0x2d, 0x52, 0x77, 0xea, 0xbb, 0xb3, 0xec, 0x26, 0x80, 0xad, 0x62, + 0xef, 0xa1, 0xe5, 0xdb, 0x67, 0xe9, 0x8d, 0x0e, 0x6c, 0x6b, 0xe3, 0x5e, 0xc7, 0x37, 0x16, 0x84, 0x9e, 0x2c, 0xaf, + 0xce, 0xa8, 0x8e, 0x3b, 0xa7, 0xf9, 0xfc, 0x50, 0x31, 0x96, 0x6e, 0x93, 0xe8, 0x9c, 0x8f, 0xe4, 0x09, 0xb2, 0x0c, + 0x15, 0xcb, 0x69, 0x60, 0x2d, 0x23, 0x68, 0xec, 0x24, 0x7d, 0xe5, 0x91, 0xac, 0xc6, 0x8a, 0xf9, 0x47, 0xa0, 0x76, + 0xae, 0xec, 0xb8, 0x6d, 0x86, 0xa4, 0x5a, 0xae, 0xb4, 0x46, 0x30, 0x0c, 0x8d, 0x7f, 0x2d, 0x44, 0xa2, 0xda, 0x4a, + 0x40, 0x02, 0x0e, 0x67, 0x29, 0xa8, 0xdd, 0x6d, 0x79, 0xf3, 0x6e, 0x94, 0x1e, 0x51, 0xa4, 0xa2, 0x56, 0x54, 0x4e, + 0xf1, 0x86, 0xb2, 0xf5, 0x4c, 0x34, 0x01, 0x13, 0x8d, 0x62, 0x23, 0x33, 0x28, 0x6f, 0xb7, 0x2a, 0xe4, 0x5e, 0xae, + 0xfb, 0xb7, 0x57, 0xef, 0x28, 0x0d, 0x9b, 0xbe, 0x12, 0x92, 0x06, 0xad, 0x50, 0x44, 0x7c, 0xc0, 0x8e, 0x31, 0x8e, + 0xae, 0xc9, 0xf4, 0x99, 0x3a, 0x30, 0x46, 0x75, 0x89, 0x94, 0x2f, 0xcd, 0x9f, 0xbd, 0xf1, 0xea, 0x25, 0xb0, 0xf5, + 0x3b, 0x5d, 0x6b, 0x4d, 0x66, 0xde, 0x96, 0x52, 0x2b, 0x91, 0x6e, 0x32, 0x22, 0x8d, 0xff, 0x4c, 0xb3, 0x6f, 0x26, + 0xf2, 0x87, 0x1d, 0xed, 0xc0, 0x40, 0x86, 0xf4, 0x66, 0xb3, 0x39, 0xa7, 0x6a, 0x16, 0x00, 0x0a, 0xff, 0xd5, 0xba, + 0x0f, 0x66, 0x6b, 0xa6, 0xa9, 0x88, 0xe0, 0xb3, 0x30, 0x34, 0x6f, 0xe1, 0x90, 0xd5, 0x69, 0x04, 0xe0, 0x20, 0x09, + 0x81, 0xcc, 0xd9, 0x5c, 0x6f, 0x08, 0xaa, 0xd8, 0xdb, 0xb0, 0x46, 0x9f, 0x42, 0xe8, 0x7f, 0xe4, 0xd3, 0xcf, 0xf9, + 0x5e, 0x45, 0x51, 0x0c, 0x5d, 0x1d, 0x0a, 0x87, 0xd6, 0xdf, 0x64, 0xd2, 0x78, 0x97, 0x2c, 0x14, 0x83, 0xfa, 0x8b, + 0xbd, 0x43, 0xcb, 0xdc, 0x74, 0x67, 0x03, 0x0b, 0x97, 0x0a, 0x06, 0x52, 0x2c, 0x42, 0x48, 0x73, 0x83, 0xb3, 0x7e, + 0xeb, 0xb1, 0x7c, 0xe9, 0x02, 0x4d, 0xdf, 0xca, 0xe3, 0x31, 0x3e, 0xfb, 0x76, 0xbc, 0xe3, 0x13, 0x66, 0x5a, 0x66, + 0x89, 0x4a, 0x0a, 0xe9, 0x93, 0xff, 0x0e, 0xa3, 0x96, 0xc7, 0x84, 0x05, 0xd3, 0xea, 0xee, 0xa9, 0x14, 0xc5, 0xce, + 0x73, 0x58, 0x53, 0x2f, 0xa0, 0x0e, 0x85, 0x9b, 0xea, 0x03, 0xbb, 0x12, 0x41, 0x6a, 0x53, 0x00, 0x30, 0xfe, 0x08, + 0x80, 0x88, 0x07, 0x99, 0x57, 0xaa, 0x25, 0x64, 0xb8, 0x59, 0x4e, 0xa4, 0xbb, 0x8b, 0x51, 0xe2, 0x9b, 0x23, 0x02, + 0xb4, 0xa5, 0x66, 0x18, 0x9e, 0xc9, 0x6f, 0x73, 0x79, 0x13, 0x2e, 0x81, 0xed, 0x1a, 0xc1, 0x1b, 0x21, 0x6d, 0xd6, + 0x7e, 0x38, 0x02, 0xaa, 0xb6, 0x01, 0x51, 0xfa, 0x4d, 0x79, 0x63, 0xde, 0x88, 0x14, 0xaa, 0xd5, 0xce, 0xee, 0x4d, + 0x5a, 0xa7, 0x0d, 0xab, 0xe1, 0x29, 0xdc, 0x54, 0xa9, 0x6d, 0x23, 0xd7, 0xf6, 0x7f, 0x92, 0x82, 0x9c, 0x4d, 0xdd, + 0xd5, 0x6d, 0xf7, 0xfb, 0xa7, 0x09, 0x38, 0xfc, 0x24, 0x31, 0xbe, 0xfb, 0xd5, 0x32, 0xfb, 0x3f, 0xb6, 0xf2, 0xa0, + 0x04, 0x0f, 0xa7, 0x20, 0x9f, 0x62, 0x0d, 0xd7, 0x90, 0x7a, 0xf2, 0xae, 0xaf, 0xbb, 0x80, 0xc0, 0xfa, 0x2d, 0xb9, + 0x13, 0xef, 0x32, 0x82, 0x53, 0x00, 0xdb, 0xd6, 0x11, 0x58, 0xeb, 0xe6, 0x3b, 0x90, 0x82, 0x18, 0xf9, 0x2d, 0x92, + 0xff, 0xb3, 0x32, 0x37, 0xfc, 0x48, 0x51, 0xdc, 0x9c, 0x4b, 0x17, 0xd1, 0x93, 0x55, 0xd8, 0x0e, 0x1b, 0x55, 0x80, + 0x23, 0xb0, 0xf0, 0x7e, 0x6e, 0x26, 0xff, 0x0c, 0xa1, 0x9d, 0xab, 0x33, 0xc5, 0xa1, 0x18, 0xd5, 0x4f, 0x75, 0x01, + 0xca, 0xc3, 0x64, 0xc4, 0xa6, 0x26, 0xb4, 0x18, 0x0b, 0x4b, 0x97, 0x24, 0x80, 0x40, 0x7b, 0xa8, 0x25, 0x32, 0x97, + 0x6b, 0x91, 0x5d, 0x32, 0xee, 0xd9, 0x56, 0x2c, 0x5d, 0xfb, 0x98, 0xd7, 0xd9, 0x33, 0x70, 0xe3, 0x3c, 0x06, 0x5f, + 0xdc, 0xd9, 0x52, 0x58, 0xe9, 0x19, 0xb2, 0x3a, 0x3b, 0x57, 0xe2, 0xb0, 0x4d, 0xb6, 0x1f, 0x15, 0xec, 0xee, 0xdb, + 0x5b, 0x22, 0x0b, 0xc4, 0xe0, 0x3f, 0xad, 0x35, 0x59, 0xeb, 0x6f, 0xe4, 0x00, 0xbe, 0x85, 0x95, 0x7c, 0x41, 0x33, + 0xe0, 0x72, 0x77, 0x73, 0x40, 0xea, 0x81, 0x4f, 0x26, 0xac, 0xaa, 0x72, 0xcd, 0xcd, 0x46, 0xa6, 0x09, 0x9a, 0x10, + 0xff, 0xbf, 0xb2, 0xd5, 0x10, 0x1b, 0x80, 0x27, 0x63, 0xdf, 0x7c, 0xd9, 0x85, 0xc1, 0x66, 0xa1, 0xc5, 0x16, 0xf6, + 0xe1, 0x2d, 0xa7, 0xe2, 0x75, 0x73, 0x03, 0x35, 0xfc, 0x20, 0x81, 0x95, 0xef, 0x12, 0xaa, 0xf9, 0x9e, 0x38, 0xf6, + 0xbd, 0x57, 0xbe, 0x7a, 0x4e, 0x8f, 0x40, 0xd3, 0xe8, 0xac, 0x99, 0xf4, 0xe4, 0x70, 0x6e, 0x0c, 0x55, 0x23, 0xaf, + 0x95, 0xb7, 0x07, 0x57, 0xab, 0xbf, 0x3e, 0x9b, 0xf3, 0x36, 0x3f, 0xa2, 0x1f, 0x5d, 0x63, 0x23, 0x66, 0x71, 0xc2, + 0x57, 0xd7, 0x47, 0x91, 0x50, 0x51, 0xc4, 0xc5, 0x87, 0x75, 0x9f, 0x36, 0xae, 0xb7, 0x8e, 0x6e, 0xf1, 0x2e, 0xc0, + 0x9c, 0x92, 0x54, 0x9d, 0x6d, 0x67, 0xe8, 0x0a, 0xbe, 0x97, 0xb5, 0xc5, 0xf1, 0xa5, 0xb5, 0x6e, 0xcb, 0xcb, 0xae, + 0xbc, 0x37, 0x46, 0x5d, 0xb4, 0x60, 0xd7, 0x77, 0x9c, 0xbc, 0xd5, 0xc8, 0xfd, 0xea, 0xa9, 0x2d, 0x96, 0x50, 0x40, + 0x1b, 0x5a, 0xbe, 0x20, 0x3b, 0xc6, 0x9e, 0x8d, 0x4e, 0xa5, 0xc9, 0x53, 0xf4, 0xba, 0xfb, 0xcc, 0x23, 0x1e, 0xd6, + 0x81, 0xae, 0x9c, 0x06, 0x1d, 0xff, 0xc2, 0x7f, 0x79, 0x59, 0xaa, 0xb7, 0x2a, 0xae, 0xbd, 0x12, 0x00, 0x93, 0x2a, + 0x9f, 0xf4, 0xf2, 0xf7, 0x41, 0x10, 0x19, 0xd9, 0x08, 0xf1, 0x4c, 0x54, 0x96, 0x00, 0x3a, 0xae, 0x72, 0xf1, 0xce, + 0x74, 0xd0, 0x2f, 0x67, 0x22, 0x11, 0x39, 0x03, 0x6d, 0x1b, 0x14, 0x0a, 0x91, 0x7a, 0xbb, 0x08, 0xe2, 0x1e, 0x45, + 0x4c, 0x34, 0xd7, 0x5d, 0xdf, 0xaf, 0xd1, 0x71, 0x34, 0x36, 0xa3, 0x76, 0xfb, 0x5b, 0xc1, 0x14, 0x48, 0x89, 0x83, + 0x81, 0xba, 0xa2, 0x22, 0x1e, 0xff, 0xf1, 0x40, 0xfb, 0x25, 0x35, 0x9c, 0xb2, 0xc3, 0x78, 0x15, 0x5f, 0x59, 0x55, + 0xb5, 0xe2, 0x97, 0x88, 0x99, 0x21, 0x88, 0x37, 0x1a, 0xe9, 0x95, 0xcd, 0x5e, 0xcd, 0x64, 0xa2, 0x38, 0x29, 0x2c, + 0x8f, 0x6b, 0xd7, 0x84, 0x75, 0x00, 0x6b, 0xf5, 0xd1, 0xa1, 0xa5, 0xf8, 0xfb, 0xec, 0x8f, 0x4b, 0x8e, 0x99, 0xe7, + 0xcf, 0xf0, 0xbf, 0xcd, 0x2e, 0x97, 0xfc, 0xd1, 0x3d, 0xc9, 0xf6, 0x3d, 0x76, 0x00, 0xcd, 0x32, 0xa5, 0x8e, 0x32, + 0x86, 0x00, 0xc0, 0x41, 0xe2, 0x7b, 0x8b, 0xdb, 0xff, 0xee, 0x18, 0x44, 0xce, 0xf2, 0xa6, 0xc5, 0x83, 0xff, 0x18, + 0x51, 0x5a, 0x1a, 0x6b, 0xe1, 0x08, 0x82, 0x71, 0x6d, 0xac, 0x1b, 0xc9, 0x3c, 0xd0, 0x75, 0x04, 0xb2, 0x96, 0x9c, + 0x60, 0xa2, 0x44, 0xee, 0x55, 0xcd, 0xeb, 0x10, 0x6a, 0x25, 0x96, 0xa9, 0xcd, 0x23, 0xea, 0xa8, 0xb1, 0xef, 0x40, + 0xf0, 0x32, 0x3b, 0x44, 0x6d, 0xfe, 0x63, 0x4b, 0x81, 0x5f, 0x4a, 0x79, 0x32, 0x70, 0x78, 0x23, 0x14, 0x15, 0x1f, + 0x05, 0x30, 0x9c, 0x11, 0xbc, 0xa8, 0xd5, 0x57, 0x8e, 0x63, 0xa0, 0x1f, 0x4a, 0x2a, 0x5e, 0xec, 0x3e, 0x6f, 0xbc, + 0x01, 0x77, 0xa1, 0xfc, 0x03, 0xe5, 0x3a, 0x52, 0x2d, 0x7b, 0xf9, 0xc8, 0x4e, 0x6d, 0xc7, 0xd9, 0x50, 0x15, 0x54, + 0x45, 0xef, 0xd0, 0x2f, 0x85, 0x70, 0x60, 0x79, 0xb2, 0xda, 0x1b, 0xee, 0x0c, 0x7c, 0x6c, 0xc4, 0x47, 0x7d, 0x25, + 0x7b, 0x43, 0xa2, 0x8c, 0x85, 0xe4, 0x38, 0x2a, 0x40, 0xf4, 0xe4, 0xd3, 0x75, 0x36, 0x0d, 0x7b, 0x75, 0xb6, 0x14, + 0x48, 0x23, 0x46, 0x3a, 0x97, 0x4a, 0x67, 0xf6, 0xf4, 0x48, 0x19, 0x3f, 0xef, 0xfc, 0x6a, 0xd9, 0xa0, 0xcc, 0x36, + 0xa4, 0xf2, 0xa7, 0xbc, 0x2f, 0x25, 0x65, 0xb2, 0xad, 0xd8, 0xf4, 0xc6, 0xe6, 0x14, 0xc0, 0x64, 0x05, 0x61, 0xee, + 0xbe, 0x41, 0x39, 0x18, 0x63, 0x5d, 0xa9, 0x22, 0xdf, 0xf8, 0x3c, 0x76, 0x7a, 0x7a, 0xc1, 0x33, 0x8a, 0x2c, 0xfa, + 0x53, 0x04, 0x36, 0xcb, 0x6b, 0x85, 0x09, 0xdf, 0xe7, 0xb8, 0x46, 0xbf, 0xd0, 0x14, 0x4d, 0x42, 0xf4, 0xe3, 0x8d, + 0x48, 0x35, 0x2b, 0xe0, 0xcd, 0xfb, 0xa6, 0x1b, 0xc1, 0xb3, 0x32, 0xda, 0x48, 0x24, 0xda, 0xba, 0x29, 0xf0, 0xef, + 0x11, 0x7d, 0x23, 0x66, 0xfa, 0x83, 0x34, 0x5f, 0xfd, 0x20, 0xcc, 0x37, 0xdb, 0x03, 0xaa, 0xda, 0x87, 0xdc, 0xf8, + 0xe4, 0x42, 0x01, 0x16, 0x10, 0x46, 0x2f, 0x95, 0x36, 0xd6, 0x04, 0xa5, 0x84, 0x4b, 0x51, 0x93, 0x51, 0x5e, 0x4f, + 0xf5, 0x09, 0xad, 0xeb, 0x25, 0x19, 0x60, 0x12, 0xba, 0xb1, 0x8d, 0xbe, 0x8d, 0xb9, 0x4d, 0x97, 0xfd, 0x87, 0x0a, + 0xed, 0x81, 0x2b, 0x1b, 0x2c, 0xe0, 0x73, 0xb5, 0xe7, 0xce, 0x45, 0x04, 0x5a, 0x83, 0xf8, 0x8f, 0xe3, 0x7a, 0xb1, + 0x77, 0x4b, 0x25, 0x25, 0x56, 0x59, 0x08, 0x19, 0x2a, 0x17, 0x76, 0x73, 0xc3, 0x3c, 0xeb, 0x71, 0xf0, 0x8c, 0x04, + 0x01, 0xc1, 0xa9, 0x82, 0x49, 0x5c, 0x4d, 0x69, 0x58, 0xd9, 0x73, 0x74, 0xc3, 0x69, 0xf9, 0x35, 0x53, 0x65, 0xbb, + 0x40, 0xa7, 0x6f, 0x5c, 0x31, 0x98, 0x9f, 0xd8, 0x17, 0x8e, 0x1e, 0x5a, 0x46, 0xd7, 0x67, 0x07, 0x46, 0x80, 0x1c, + 0x56, 0x96, 0x81, 0x84, 0x2d, 0x49, 0xab, 0x37, 0x79, 0x78, 0xcf, 0x14, 0x22, 0xc9, 0x02, 0x55, 0x8e, 0x5f, 0x60, + 0x6b, 0x69, 0x49, 0x39, 0x2b, 0xd1, 0x5a, 0x85, 0x32, 0x44, 0x6b, 0xbd, 0x6f, 0x57, 0x9d, 0xde, 0x7b, 0x5f, 0xd0, + 0x79, 0x69, 0x24, 0x87, 0x18, 0x02, 0x43, 0x2c, 0x8d, 0xef, 0x14, 0x36, 0x5a, 0x6f, 0x96, 0xd9, 0x7d, 0x35, 0xb6, + 0x5f, 0xc3, 0x75, 0x3d, 0xf1, 0xa6, 0xfc, 0xb6, 0xce, 0x1e, 0xe6, 0xbc, 0x72, 0xa2, 0x1b, 0xba, 0x86, 0xcd, 0xda, + 0x4e, 0x7f, 0x55, 0xdf, 0x32, 0x19, 0x16, 0x1f, 0x7b, 0x08, 0x21, 0x17, 0xaa, 0x54, 0x88, 0xf4, 0x76, 0x27, 0x90, + 0x2a, 0xf7, 0x94, 0x2b, 0x9d, 0xe3, 0x44, 0xd6, 0xb1, 0x9d, 0x1c, 0x2e, 0x4d, 0x2a, 0x88, 0x63, 0x7b, 0xf7, 0x9d, + 0x58, 0xf0, 0xc9, 0x17, 0xd2, 0x9c, 0xa7, 0xeb, 0x97, 0x7e, 0x78, 0x65, 0xac, 0x94, 0x9c, 0x6e, 0x66, 0x51, 0xd3, + 0xdd, 0x2c, 0xb2, 0xf3, 0xaf, 0x71, 0xeb, 0x92, 0xf0, 0x3a, 0x69, 0xff, 0x6a, 0x84, 0x97, 0x5c, 0xeb, 0x52, 0x44, + 0x53, 0x94, 0xba, 0x7f, 0x9d, 0xa0, 0x20, 0x12, 0xfc, 0xb9, 0x68, 0x18, 0x6b, 0x9f, 0x56, 0xcd, 0x47, 0x63, 0xc5, + 0xd6, 0xde, 0xb7, 0x92, 0x1a, 0x17, 0x05, 0xd7, 0x8c, 0x5c, 0x69, 0xa5, 0xc4, 0xe0, 0x38, 0xd0, 0x94, 0x3f, 0x50, + 0xe5, 0x0f, 0x53, 0xd2, 0x79, 0x8b, 0xd9, 0xea, 0xfb, 0xd4, 0x6e, 0x1d, 0x53, 0x45, 0x23, 0x9d, 0x19, 0xb3, 0x51, + 0x2b, 0x38, 0xda, 0xe3, 0x7a, 0x59, 0x48, 0xe7, 0xb4, 0xcd, 0xe0, 0x93, 0xf4, 0xf1, 0xad, 0x7c, 0xb6, 0xca, 0x5f, + 0xea, 0xfd, 0x5e, 0xda, 0xdb, 0xe4, 0xc5, 0x06, 0xde, 0x0a, 0x13, 0x60, 0x20, 0xa2, 0x52, 0x05, 0xb5, 0x84, 0x24, + 0xec, 0xb4, 0xd3, 0x39, 0x43, 0x55, 0x5a, 0x4c, 0x81, 0x1f, 0x97, 0xf5, 0xf1, 0xf8, 0x5a, 0x34, 0xa6, 0xd6, 0x51, + 0x23, 0x3e, 0x2e, 0xe7, 0x19, 0x20, 0x2f, 0x54, 0x3c, 0x53, 0x11, 0x7d, 0x46, 0xce, 0xf0, 0xa0, 0xcc, 0x82, 0x91, + 0x76, 0x18, 0x8a, 0x2d, 0x37, 0xa6, 0x3a, 0x03, 0xba, 0xf0, 0x67, 0x8d, 0x94, 0x69, 0x84, 0x52, 0xc8, 0xb5, 0x49, + 0xbb, 0xcc, 0x37, 0x08, 0xd3, 0x0b, 0x1a, 0x7f, 0x3d, 0xf9, 0x5e, 0x0a, 0x99, 0x02, 0xee, 0x23, 0x85, 0xd7, 0xf4, + 0x42, 0x66, 0xc0, 0x9b, 0x1a, 0x20, 0x09, 0x40, 0x9a, 0x55, 0x27, 0xbc, 0x0d, 0x0f, 0x49, 0xb3, 0xdf, 0xca, 0x52, + 0xb9, 0x27, 0x57, 0x5a, 0xf2, 0xad, 0x6e, 0x2b, 0xe6, 0x4b, 0xd6, 0x36, 0xad, 0x9d, 0x9d, 0xd0, 0xeb, 0x34, 0x4d, + 0xba, 0x44, 0x38, 0xa8, 0x24, 0xbd, 0xdf, 0x01, 0x06, 0x53, 0x5f, 0xbe, 0x45, 0xcd, 0xfc, 0x5e, 0x82, 0x9d, 0x0c, + 0xd8, 0x50, 0x65, 0xe5, 0x32, 0x0b, 0x00, 0x01, 0xba, 0x6d, 0xa3, 0x9b, 0x26, 0x8b, 0x37, 0x22, 0xf7, 0x80, 0xce, + 0x05, 0x77, 0x64, 0x6f, 0x29, 0xdd, 0x99, 0x8e, 0x95, 0x6c, 0xbc, 0x2b, 0x6b, 0xb2, 0x0b, 0x95, 0xf8, 0x26, 0x06, + 0x66, 0x3b, 0x2b, 0x09, 0x80, 0xeb, 0xc6, 0x2e, 0xf3, 0x42, 0x9d, 0xc9, 0x6c, 0xcd, 0xaa, 0x3c, 0x55, 0xc3, 0x54, + 0x3a, 0x74, 0xd5, 0x44, 0x0d, 0x41, 0x36, 0x20, 0x6c, 0x5e, 0xdb, 0x5c, 0xc7, 0x67, 0x01, 0x20, 0xe8, 0x41, 0x29, + 0x4b, 0xc6, 0x8e, 0x1b, 0x69, 0x77, 0xbd, 0xac, 0x00, 0x61, 0xbc, 0xb3, 0x26, 0x39, 0x39, 0x2d, 0xfd, 0xc9, 0x78, + 0xdb, 0x6a, 0xa6, 0xdd, 0xf1, 0x43, 0x42, 0xdb, 0xe2, 0xd0, 0x82, 0x1f, 0xa9, 0xdd, 0xb9, 0x5a, 0xc4, 0xaa, 0xbd, + 0x2c, 0x60, 0xb0, 0x8d, 0xd6, 0xba, 0x6d, 0xee, 0xe6, 0x98, 0x08, 0x27, 0xcb, 0xc6, 0x74, 0x27, 0x96, 0x17, 0x89, + 0x35, 0x06, 0x6a, 0x6b, 0xde, 0xf8, 0xa5, 0xc0, 0xd4, 0x04, 0xdf, 0xa8, 0x5c, 0x2c, 0x8d, 0xfe, 0xf4, 0x03, 0x11, + 0xa1, 0x59, 0x6c, 0xae, 0xd6, 0x4d, 0x68, 0xbc, 0xc6, 0xf5, 0x06, 0xdc, 0x0d, 0x2c, 0x1a, 0x4e, 0xf4, 0x60, 0xce, + 0xee, 0x48, 0xcd, 0x8a, 0x65, 0xf8, 0xd1, 0xa3, 0xa3, 0x02, 0xbb, 0xb3, 0x39, 0x96, 0x14, 0x48, 0x30, 0xe2, 0xd7, + 0xd7, 0x58, 0x2c, 0x6a, 0x97, 0x46, 0x07, 0x63, 0x2e, 0xf9, 0x0f, 0xaa, 0x9b, 0x69, 0x5f, 0x01, 0x9b, 0x7b, 0x86, + 0x23, 0x49, 0x99, 0x19, 0xbd, 0xbc, 0x36, 0x0d, 0xec, 0x55, 0x1e, 0x75, 0x1c, 0x46, 0x4f, 0x4a, 0xc2, 0xde, 0x6c, + 0x4d, 0xa9, 0x5c, 0x8a, 0x51, 0xe8, 0x79, 0x83, 0x58, 0xf4, 0xb8, 0x07, 0x38, 0xc9, 0x98, 0x22, 0x7d, 0xb5, 0x51, + 0x90, 0xb7, 0xda, 0x5f, 0xba, 0xec, 0xa0, 0x49, 0x87, 0xce, 0x02, 0x9c, 0x8c, 0x92, 0x82, 0x10, 0xa0, 0x0d, 0xa1, + 0xd7, 0x06, 0x2f, 0xa5, 0x08, 0x4d, 0x4d, 0x66, 0xd4, 0x85, 0xf9, 0x9c, 0x71, 0x46, 0xa1, 0xa0, 0xa7, 0x5d, 0x9a, + 0x77, 0xab, 0xdb, 0x5c, 0x38, 0xde, 0x5d, 0x54, 0x2b, 0x02, 0x29, 0x5a, 0xf1, 0xd3, 0x43, 0xe1, 0x22, 0xb7, 0x20, + 0xa2, 0xd6, 0x1c, 0xde, 0x1a, 0x9c, 0x5c, 0x4c, 0x68, 0x95, 0xea, 0xae, 0xf7, 0xf0, 0x85, 0x88, 0xef, 0xda, 0x3c, + 0x21, 0x8e, 0x5a, 0x6f, 0xe8, 0xe6, 0x2c, 0xcd, 0x53, 0x09, 0xf5, 0xcc, 0x16, 0x02, 0x97, 0x8d, 0x8c, 0x2a, 0x7c, + 0x33, 0x3e, 0xc7, 0xc8, 0x92, 0x80, 0x32, 0x38, 0x9d, 0xc5, 0x08, 0x2c, 0x32, 0xe6, 0xe3, 0xd8, 0x1f, 0xcf, 0x6c, + 0x82, 0x7c, 0xd7, 0x98, 0x11, 0x89, 0xb7, 0xbd, 0x37, 0xd4, 0x28, 0x94, 0x8c, 0x44, 0x5c, 0x1e, 0x39, 0xb4, 0x7b, + 0x50, 0x7d, 0x37, 0x20, 0x36, 0x8c, 0x29, 0xd3, 0x09, 0xa1, 0x4f, 0x1e, 0xc4, 0x9a, 0x5c, 0x98, 0xb0, 0xd2, 0x49, + 0x0c, 0xc4, 0xe8, 0x6c, 0x40, 0xf5, 0x8d, 0xd0, 0x22, 0x91, 0x05, 0x25, 0x12, 0xf9, 0x6c, 0x4e, 0x88, 0xc3, 0x56, + 0x64, 0xfc, 0x60, 0xb5, 0x77, 0x11, 0x95, 0x3e, 0xe3, 0xa4, 0xb0, 0x2e, 0x0b, 0xa3, 0x3f, 0x46, 0x09, 0x61, 0xc0, + 0xd9, 0xed, 0x49, 0x51, 0xde, 0x0d, 0x8b, 0x47, 0x17, 0xa8, 0xca, 0xb7, 0x5c, 0x01, 0xec, 0xd1, 0x42, 0x0d, 0x54, + 0x59, 0xb2, 0x9c, 0xeb, 0x47, 0x21, 0xc2, 0x53, 0x66, 0x8e, 0xaa, 0x10, 0x06, 0x84, 0x88, 0x4a, 0xed, 0xc2, 0xae, + 0x95, 0x02, 0x74, 0x30, 0xa6, 0x8d, 0x46, 0x88, 0x0b, 0x78, 0x9e, 0xb7, 0x3f, 0x0e, 0x98, 0xe6, 0x89, 0x3f, 0xa8, + 0x06, 0xfd, 0x77, 0x24, 0x9b, 0xac, 0x9f, 0xdc, 0xf7, 0xc3, 0x27, 0x7d, 0x87, 0xce, 0xde, 0xef, 0xab, 0xbf, 0x7f, + 0xec, 0xd1, 0x40, 0x16, 0xf2, 0x0b, 0xdd, 0x84, 0x56, 0xcf, 0xde, 0x18, 0xee, 0x88, 0x56, 0xcf, 0x4e, 0x2f, 0x0a, + 0xd4, 0x3b, 0xd7, 0x4e, 0x6d, 0x1b, 0x36, 0x32, 0x89, 0xc7, 0x9a, 0x27, 0x63, 0xb0, 0x22, 0x83, 0x6a, 0x05, 0x2b, + 0x9b, 0x2c, 0xd1, 0x5d, 0x9f, 0x99, 0x83, 0x7b, 0xe2, 0x46, 0xbe, 0x93, 0x67, 0x1f, 0x80, 0x9b, 0x10, 0xf9, 0x4b, + 0x0e, 0xab, 0xfa, 0x1d, 0xd5, 0xa6, 0x3b, 0x28, 0x18, 0x4a, 0x2d, 0x31, 0x5b, 0x15, 0x8d, 0x25, 0xd8, 0x1b, 0x04, + 0x5a, 0x53, 0xab, 0x0f, 0xeb, 0x70, 0xc8, 0x1f, 0x5b, 0xfb, 0x07, 0x95, 0x89, 0xba, 0x68, 0x40, 0x9e, 0x86, 0x5f, + 0xba, 0x44, 0xb8, 0x6c, 0x53, 0xff, 0xaf, 0x6e, 0x2f, 0x76, 0x46, 0xc1, 0x24, 0xe4, 0x6d, 0xc8, 0xc3, 0xdd, 0xc1, + 0x00, 0x05, 0x4a, 0xe7, 0x1b, 0x6d, 0x78, 0x12, 0x3d, 0xc9, 0xc3, 0xf6, 0x79, 0x69, 0xaf, 0x46, 0x7d, 0xae, 0x63, + 0x9b, 0xda, 0xb6, 0x49, 0x4d, 0x49, 0x73, 0x70, 0x05, 0x96, 0x18, 0x17, 0x34, 0xad, 0xe4, 0x11, 0x4b, 0x2c, 0xc7, + 0xa4, 0xca, 0xad, 0xe4, 0x29, 0xa7, 0x8c, 0xff, 0x10, 0xb4, 0x97, 0x59, 0x1e, 0x0d, 0x97, 0xe5, 0xd1, 0x65, 0xb0, + 0x36, 0xa1, 0xba, 0xb7, 0xa1, 0xfa, 0x62, 0xd6, 0xb4, 0xd4, 0x6a, 0x93, 0x24, 0x91, 0xc6, 0x7b, 0xba, 0x58, 0xd7, + 0x03, 0xe8, 0xce, 0xd4, 0x2e, 0x65, 0x12, 0xc7, 0x38, 0xd9, 0x86, 0xb9, 0xfa, 0xd8, 0x2a, 0xad, 0xcf, 0x5f, 0xd0, + 0xf8, 0xdc, 0x7d, 0x2b, 0x8f, 0x18, 0xb5, 0x18, 0x78, 0x7f, 0x78, 0x2a, 0xc1, 0xc5, 0xa1, 0xb1, 0xb3, 0x3d, 0x4c, + 0x1c, 0x76, 0xec, 0xec, 0xd7, 0x14, 0x4c, 0xcf, 0x81, 0x36, 0xf4, 0xd5, 0xe0, 0xf8, 0xda, 0x3d, 0x77, 0xf0, 0x62, + 0x40, 0x4b, 0xa4, 0xbc, 0x53, 0xe4, 0x88, 0x01, 0x26, 0x5a, 0xf9, 0x9b, 0x5f, 0xe7, 0xf5, 0x87, 0xf8, 0x7a, 0x3c, + 0x10, 0x3b, 0x51, 0x1e, 0x3d, 0x2b, 0x14, 0xa5, 0x44, 0x45, 0x4f, 0xe1, 0x2f, 0x6e, 0xa1, 0x0c, 0xa7, 0x89, 0x4e, + 0x47, 0x45, 0xb7, 0x77, 0x4f, 0x7c, 0x67, 0xff, 0xa6, 0x3a, 0x97, 0xf3, 0x0a, 0x03, 0x5d, 0x08, 0x6c, 0xa0, 0x8c, + 0x8c, 0x05, 0x4a, 0xf1, 0x63, 0xcc, 0x2e, 0x43, 0x94, 0xdc, 0xea, 0x13, 0x3e, 0x70, 0x11, 0x98, 0x3b, 0xa4, 0x49, + 0xc2, 0xe8, 0x51, 0x7b, 0x6e, 0x5a, 0x9e, 0x84, 0x99, 0x9d, 0x27, 0x99, 0x9d, 0x53, 0xc5, 0x85, 0x09, 0x53, 0x35, + 0x28, 0x16, 0x8f, 0xe5, 0xa4, 0xb6, 0x5a, 0x4d, 0x33, 0x27, 0x9a, 0xe9, 0x91, 0x3b, 0x0c, 0x81, 0x6e, 0xd2, 0x0d, + 0x35, 0xfa, 0x4d, 0x54, 0xf1, 0xd1, 0x7a, 0x11, 0x0c, 0xd1, 0xfa, 0x74, 0xd6, 0x46, 0xb9, 0x63, 0x14, 0x25, 0xdf, + 0x17, 0x80, 0xb8, 0xb7, 0xae, 0x28, 0x5d, 0x7d, 0xf2, 0xc7, 0x3f, 0x4c, 0xb5, 0x9e, 0x07, 0x10, 0x23, 0xbe, 0x66, + 0x93, 0x33, 0xa3, 0xf2, 0x48, 0xfc, 0x43, 0x98, 0xb4, 0x80, 0x3b, 0x42, 0x58, 0xb5, 0x71, 0x30, 0x49, 0x4e, 0xe7, + 0x62, 0xa8, 0xef, 0xa2, 0x91, 0x24, 0x94, 0x49, 0x7d, 0x0a, 0x9e, 0x4d, 0x4e, 0xad, 0x8f, 0x0e, 0x09, 0x77, 0xeb, + 0x20, 0x14, 0x62, 0xa6, 0x5a, 0x03, 0xdc, 0x3d, 0xa5, 0xfb, 0x7a, 0xed, 0x8d, 0xd7, 0x2a, 0xe2, 0xfe, 0xfb, 0xc5, + 0xc1, 0xfb, 0xef, 0x78, 0xa9, 0xa9, 0xdf, 0x6f, 0x9c, 0x0d, 0xdb, 0xb7, 0x3c, 0x00, 0x2f, 0x06, 0x78, 0x08, 0x70, + 0x11, 0xf5, 0x56, 0xa7, 0xfd, 0x61, 0x74, 0xe3, 0xeb, 0xca, 0xec, 0x59, 0xd1, 0xf5, 0x3b, 0x3f, 0x78, 0xb7, 0x6f, + 0x21, 0x60, 0x17, 0xdd, 0xff, 0x1f, 0x81, 0x0a, 0x08, 0x86, 0x82, 0xbf, 0x3f, 0x6e, 0x87, 0xb3, 0x23, 0x78, 0x0e, + 0xbd, 0x3e, 0x8e, 0x62, 0xa5, 0x7b, 0x27, 0x4d, 0xb1, 0x57, 0x11, 0x54, 0x99, 0x57, 0xc4, 0xa6, 0x8c, 0xcd, 0x2e, + 0xeb, 0x52, 0xaf, 0xcd, 0x37, 0x18, 0xd0, 0x97, 0x00, 0xc8, 0x48, 0xf5, 0xa6, 0x0c, 0x20, 0xfc, 0xfa, 0x52, 0x2c, + 0x46, 0xf3, 0x7c, 0xa7, 0xb5, 0x6b, 0xf7, 0x29, 0xf4, 0xc3, 0x76, 0x1d, 0x1e, 0x0c, 0xed, 0x09, 0x79, 0x9e, 0x37, + 0xbc, 0xcb, 0xf0, 0x6d, 0x5e, 0x14, 0x9c, 0x06, 0x2f, 0xa3, 0x5a, 0x1a, 0xf2, 0x49, 0x34, 0x06, 0xfa, 0xb4, 0x6f, + 0x29, 0x01, 0xb7, 0x21, 0x31, 0xd8, 0x41, 0x56, 0x7a, 0x7d, 0x24, 0xed, 0x9d, 0xeb, 0x31, 0xbc, 0xd9, 0x6e, 0x71, + 0x91, 0x32, 0x22, 0xb1, 0x63, 0xa0, 0xc9, 0x8d, 0x50, 0xed, 0xed, 0xce, 0x9e, 0x0f, 0xdf, 0xdc, 0x5c, 0xde, 0xdc, + 0xae, 0x8f, 0x43, 0xaa, 0xb1, 0x4e, 0xa7, 0xd6, 0x6a, 0x6c, 0x27, 0x6d, 0x91, 0xef, 0x2d, 0x0b, 0x9b, 0x84, 0x16, + 0xe9, 0x06, 0x96, 0x96, 0x0f, 0x93, 0xaa, 0x55, 0x06, 0x38, 0x91, 0x9a, 0xba, 0x9f, 0x9e, 0x9e, 0x33, 0x25, 0xcb, + 0x03, 0x7a, 0x71, 0xd0, 0x55, 0x21, 0xb6, 0x4b, 0xd7, 0x6f, 0x2f, 0x97, 0x9e, 0xeb, 0x06, 0x60, 0x13, 0x39, 0x30, + 0x90, 0xf2, 0x7f, 0xc7, 0xa2, 0x5e, 0x0e, 0xcb, 0x93, 0x25, 0x82, 0xc2, 0x25, 0xde, 0x75, 0x49, 0x4a, 0xb4, 0x29, + 0x45, 0x68, 0x2e, 0x5e, 0x1f, 0x15, 0xe3, 0x49, 0xdd, 0x59, 0xf3, 0xec, 0x20, 0x12, 0x19, 0x5b, 0x19, 0x1b, 0xcc, + 0x4d, 0x5a, 0x86, 0x00, 0x07, 0x85, 0x64, 0xcb, 0xf5, 0xa6, 0x0b, 0xb0, 0x5d, 0xf2, 0x57, 0xa3, 0x71, 0x9e, 0x2c, + 0xd1, 0x1d, 0x1a, 0xf6, 0xe5, 0x40, 0xc1, 0xe4, 0xe6, 0xca, 0xe9, 0x91, 0x1f, 0xc5, 0x6c, 0xb1, 0x46, 0x86, 0xc1, + 0x82, 0xe9, 0x04, 0x1c, 0x08, 0xb9, 0x57, 0x0e, 0x10, 0x5b, 0x16, 0xf8, 0x30, 0x98, 0x5b, 0x22, 0x9b, 0x3c, 0xda, + 0xd9, 0x3d, 0x55, 0x28, 0xf8, 0xe4, 0xd6, 0x6d, 0x59, 0xf2, 0xca, 0x0f, 0x82, 0x5e, 0xc5, 0xe5, 0x69, 0xbb, 0x68, + 0x8e, 0xc9, 0xd1, 0x77, 0xd9, 0x94, 0xfd, 0x30, 0x8d, 0xc8, 0xc3, 0x43, 0x92, 0xe1, 0x30, 0x0b, 0x82, 0xc5, 0x4e, + 0x78, 0x29, 0x6c, 0x60, 0xac, 0x6d, 0xc2, 0x8e, 0xd4, 0x10, 0xde, 0x21, 0x26, 0xac, 0x99, 0xb3, 0x16, 0x2c, 0x10, + 0x71, 0x39, 0xe8, 0x3e, 0x72, 0xa0, 0x5f, 0xd9, 0x0a, 0x1d, 0xed, 0xe2, 0x6e, 0xf6, 0x23, 0x16, 0xc8, 0xd8, 0x92, + 0x39, 0xe9, 0x1a, 0x7e, 0xcb, 0x50, 0xad, 0xad, 0x67, 0xa3, 0xb3, 0x7b, 0xc3, 0x34, 0xd1, 0x96, 0x25, 0x3b, 0xa2, + 0x64, 0xfd, 0x42, 0x02, 0xb7, 0x50, 0xe5, 0x46, 0xee, 0xad, 0x44, 0x11, 0xc4, 0x14, 0xba, 0x78, 0xdd, 0x2d, 0x8c, + 0x88, 0x37, 0xd3, 0xa9, 0x39, 0x2a, 0x7c, 0x22, 0x63, 0x50, 0x52, 0x92, 0x82, 0xff, 0x67, 0xbd, 0x5f, 0x80, 0x82, + 0xf8, 0xc4, 0xaf, 0x7f, 0x17, 0x44, 0x38, 0xb0, 0xdb, 0x5e, 0xb6, 0xaa, 0x1d, 0x4b, 0x50, 0x1e, 0x15, 0xe6, 0xdc, + 0x40, 0x6a, 0xfd, 0x7b, 0x6e, 0xe3, 0xcd, 0x9f, 0xbf, 0xcb, 0x5c, 0xad, 0xdb, 0xe5, 0xe6, 0xb5, 0x3b, 0xe4, 0x9a, + 0xb1, 0x03, 0xf6, 0xe5, 0xe0, 0xc3, 0x6a, 0x26, 0xdd, 0x02, 0x92, 0x86, 0x4c, 0x2f, 0xdc, 0xae, 0xe8, 0x86, 0x13, + 0x72, 0x07, 0xe4, 0x10, 0x20, 0xd0, 0x66, 0x50, 0xd6, 0xe8, 0x58, 0xef, 0xc3, 0x79, 0x7b, 0x7d, 0xf9, 0xf7, 0xba, + 0x5e, 0xa2, 0x43, 0x9a, 0x9d, 0xc5, 0xa0, 0xff, 0x7e, 0x2b, 0x19, 0xc9, 0xf6, 0xcd, 0xf6, 0xfe, 0x5d, 0x0b, 0x8a, + 0x6b, 0x9a, 0xf6, 0x0f, 0x7e, 0xf9, 0xa2, 0xb7, 0xf0, 0x7a, 0xe7, 0x23, 0xa9, 0x49, 0x53, 0x6e, 0xf8, 0x71, 0xb5, + 0x95, 0xef, 0x4a, 0x66, 0x7c, 0x40, 0x60, 0xc4, 0xc9, 0xea, 0xe2, 0xe9, 0x61, 0xc4, 0x64, 0x3d, 0x6a, 0x18, 0x4e, + 0x6e, 0x6d, 0xc6, 0xb4, 0x6a, 0x21, 0x32, 0xc0, 0x25, 0x1a, 0x95, 0x28, 0x12, 0x25, 0x31, 0x40, 0x70, 0x6f, 0x7d, + 0x9e, 0xa0, 0x2d, 0x6a, 0xd6, 0x0e, 0xd4, 0x76, 0x56, 0x36, 0x27, 0x01, 0xa3, 0xcd, 0x1c, 0xd3, 0x6a, 0x2e, 0x42, + 0xe7, 0xee, 0x34, 0x88, 0x0e, 0xbd, 0x25, 0xba, 0x94, 0xb9, 0x62, 0xdf, 0xb4, 0xac, 0x2d, 0x03, 0xf2, 0x49, 0xd4, + 0x46, 0x1d, 0x24, 0x58, 0xe5, 0x54, 0x6c, 0x26, 0xf6, 0x8d, 0xa1, 0x2d, 0xdc, 0x81, 0xbe, 0x81, 0x1e, 0xac, 0xf1, + 0x92, 0xdd, 0xe4, 0xed, 0x53, 0xca, 0x0b, 0x8b, 0x49, 0xf7, 0x3b, 0xa9, 0x1e, 0xdb, 0x5b, 0x03, 0xa2, 0x50, 0x8c, + 0x77, 0x0f, 0x09, 0x56, 0x1e, 0xbd, 0x0d, 0x38, 0xb6, 0x4a, 0xaf, 0x71, 0x55, 0x3d, 0x31, 0x26, 0x78, 0x58, 0xca, + 0x27, 0xdf, 0x3f, 0x79, 0x35, 0xee, 0x1a, 0xc6, 0x4b, 0x8b, 0x5b, 0x10, 0x54, 0x30, 0x7b, 0x8b, 0x59, 0xfc, 0xd2, + 0xfc, 0xbe, 0x7b, 0xe0, 0xc6, 0xce, 0x21, 0x37, 0x6f, 0x70, 0xf7, 0x5a, 0xdc, 0xa7, 0xce, 0x67, 0xf5, 0xec, 0xd3, + 0xe9, 0x6a, 0x6b, 0x14, 0x7d, 0x3b, 0x03, 0xed, 0x11, 0xe9, 0xac, 0x01, 0x98, 0x04, 0x28, 0x4b, 0x32, 0xa0, 0x86, + 0x05, 0x5e, 0x2e, 0xad, 0xba, 0x13, 0xd4, 0x54, 0x7b, 0xb6, 0x29, 0x9f, 0x0b, 0x6b, 0x2c, 0xbe, 0x58, 0xba, 0x4e, + 0x53, 0xc3, 0x14, 0xb5, 0xae, 0x5d, 0xf3, 0xf7, 0x6f, 0x65, 0x09, 0x34, 0x4c, 0xe5, 0x8a, 0xfd, 0x1a, 0x55, 0x43, + 0xf0, 0x29, 0x2c, 0xa2, 0x84, 0x00, 0xcf, 0x62, 0x12, 0xa8, 0x5a, 0x3f, 0xb4, 0xbd, 0xdf, 0xbb, 0x63, 0xeb, 0x64, + 0x3a, 0xb8, 0x6b, 0x40, 0x96, 0x99, 0xf3, 0xce, 0x99, 0x96, 0xa1, 0x9b, 0xc6, 0x45, 0x48, 0xd9, 0x4f, 0x5f, 0xa0, + 0x4e, 0x96, 0xdb, 0xec, 0x51, 0xd0, 0x58, 0x0e, 0x91, 0x14, 0xb9, 0x20, 0xc5, 0xbf, 0x0b, 0x47, 0x3c, 0x46, 0x6a, + 0x9d, 0xa9, 0x65, 0x8c, 0xa6, 0xff, 0x16, 0xd6, 0x82, 0xa5, 0xdd, 0x7b, 0x96, 0xc1, 0x8f, 0x93, 0x01, 0xd5, 0x3a, + 0x77, 0x52, 0x26, 0x9b, 0x25, 0x8c, 0x0c, 0xed, 0x8e, 0x5a, 0xfd, 0xf4, 0x6b, 0xbd, 0x5d, 0x9a, 0xbd, 0x34, 0xcd, + 0x2f, 0xa2, 0x85, 0x81, 0x2c, 0x01, 0x17, 0x0b, 0x4a, 0x3b, 0x27, 0xd5, 0xbf, 0xf7, 0xcd, 0xf7, 0xc4, 0xf7, 0xc2, + 0x5f, 0x66, 0x3e, 0x8f, 0x7c, 0xca, 0x2b, 0x3f, 0x40, 0x9e, 0x4f, 0xee, 0xad, 0x16, 0x0c, 0x23, 0x98, 0x88, 0xac, + 0x5c, 0x81, 0x80, 0x45, 0x91, 0x3c, 0x50, 0x01, 0x89, 0x88, 0x2b, 0xdb, 0x21, 0xad, 0x66, 0xbd, 0x9b, 0x01, 0x85, + 0x01, 0xd7, 0xfe, 0x42, 0xe3, 0x9c, 0x2e, 0xf6, 0xd6, 0x51, 0x51, 0xe9, 0x58, 0x1a, 0xfd, 0x11, 0x98, 0x18, 0x51, + 0xc9, 0xe9, 0xa8, 0x38, 0xb3, 0x18, 0xed, 0x2b, 0x3a, 0x8b, 0x19, 0xc8, 0x58, 0xa9, 0x29, 0x5b, 0xf9, 0x0d, 0x30, + 0xbb, 0x3d, 0x97, 0x34, 0xf5, 0x18, 0x0e, 0xe4, 0x05, 0x44, 0x0d, 0xac, 0x68, 0x03, 0x9d, 0xda, 0x6f, 0x08, 0xcf, + 0x1b, 0x96, 0x47, 0x80, 0x20, 0x28, 0xdf, 0x41, 0xd8, 0x9f, 0xd8, 0xbe, 0x72, 0x35, 0xc3, 0x29, 0xc3, 0xf4, 0x19, + 0x87, 0x86, 0xfa, 0x14, 0xfc, 0x04, 0x6c, 0xa2, 0xab, 0x11, 0x20, 0xdf, 0x24, 0x84, 0x1e, 0x04, 0xfd, 0x2b, 0x8f, + 0x48, 0x7f, 0xdd, 0xd4, 0xea, 0x2b, 0x98, 0xe2, 0xa8, 0x4c, 0xd6, 0x6d, 0x6a, 0x5b, 0xbd, 0xb2, 0x65, 0x5c, 0xd7, + 0x80, 0x3a, 0x2d, 0x9d, 0xe3, 0x0c, 0x27, 0x0d, 0xf1, 0xbf, 0x06, 0x86, 0x3f, 0xa8, 0xdd, 0x0e, 0xa3, 0x0f, 0xfd, + 0xc6, 0x8c, 0x79, 0x87, 0x70, 0x78, 0x3c, 0x31, 0x8d, 0xdc, 0x9f, 0x0b, 0x4c, 0x87, 0x96, 0xf8, 0x23, 0x8d, 0x38, + 0xe9, 0x83, 0xd2, 0x8b, 0xd5, 0xa1, 0x32, 0xfe, 0xdb, 0xb8, 0x1f, 0xbe, 0x6d, 0xb3, 0x8a, 0xe1, 0xc9, 0x88, 0x02, + 0xb6, 0x1a, 0xb3, 0x8e, 0x4f, 0x8e, 0xd6, 0xe3, 0x98, 0xdb, 0x80, 0xa8, 0x71, 0xbd, 0xa9, 0xda, 0x2c, 0x52, 0xb1, + 0xe5, 0x96, 0x3d, 0x1f, 0xcc, 0xa8, 0x7c, 0xfc, 0xf3, 0x32, 0x15, 0x82, 0x00, 0x55, 0xe2, 0x43, 0x34, 0xd0, 0xc5, + 0x6e, 0x27, 0x68, 0xe1, 0xb7, 0x96, 0xd2, 0x4a, 0xe6, 0xc1, 0x6a, 0xee, 0x90, 0x80, 0x8e, 0xaa, 0x01, 0xc3, 0xa7, + 0x68, 0xb2, 0xab, 0xc9, 0x31, 0x42, 0x01, 0x4d, 0xce, 0x92, 0x86, 0x93, 0x61, 0xbf, 0x2d, 0x4e, 0x7f, 0x9d, 0xf3, + 0x51, 0xb3, 0x21, 0x52, 0xdf, 0x8e, 0x89, 0x98, 0x7e, 0xc7, 0x57, 0x59, 0x19, 0x1b, 0xa1, 0x78, 0x33, 0x88, 0x8d, + 0x21, 0xc9, 0x1b, 0x05, 0x25, 0x42, 0x24, 0xbb, 0x38, 0x11, 0x66, 0xf3, 0x7e, 0xa5, 0xf0, 0xf4, 0x15, 0xa1, 0xd4, + 0x1c, 0x23, 0x8d, 0x0e, 0xb6, 0x74, 0xc2, 0xda, 0xb4, 0x7d, 0x5c, 0x7d, 0x81, 0x41, 0x87, 0xcf, 0x1c, 0xf0, 0x02, + 0xe0, 0xc6, 0xb0, 0x0a, 0x60, 0xad, 0x31, 0x77, 0x0c, 0xb7, 0x65, 0x7c, 0x62, 0x2d, 0x73, 0x40, 0xff, 0x98, 0xc8, + 0x72, 0x43, 0x7b, 0x0e, 0x41, 0xc1, 0xb4, 0x1d, 0x58, 0xa2, 0xf2, 0xef, 0xb4, 0x29, 0x76, 0x55, 0x31, 0x31, 0x0f, + 0x84, 0xcb, 0x12, 0x09, 0x95, 0xaf, 0x7b, 0xd7, 0x63, 0x06, 0xf8, 0x88, 0xa8, 0x19, 0x54, 0xbc, 0xce, 0x4d, 0x7e, + 0x55, 0x3f, 0xbf, 0x04, 0xec, 0x75, 0xf6, 0xba, 0xfe, 0xf0, 0xba, 0x7a, 0xfa, 0x93, 0x52, 0x00, 0xf4, 0x5c, 0xd8, + 0x95, 0x61, 0x26, 0x0b, 0x9b, 0xc8, 0xf0, 0x73, 0xbd, 0x84, 0xf2, 0xb4, 0x99, 0x03, 0x42, 0x38, 0xc7, 0xf9, 0xe4, + 0xfa, 0x74, 0x95, 0xb9, 0x09, 0xa4, 0x08, 0xb8, 0x09, 0x20, 0xf3, 0xfe, 0x08, 0x67, 0xce, 0x07, 0x04, 0xe2, 0x5d, + 0x5c, 0x9b, 0x1c, 0x3d, 0x0e, 0x92, 0x98, 0xdd, 0x4f, 0x3d, 0x2a, 0x88, 0xcb, 0x68, 0x01, 0x0d, 0x5b, 0x53, 0x76, + 0x2d, 0x58, 0xee, 0x08, 0x1d, 0x36, 0x84, 0x99, 0x42, 0x57, 0x89, 0xfc, 0x87, 0x47, 0x4b, 0xaa, 0xe8, 0xb1, 0x3b, + 0x7a, 0xb6, 0x22, 0xca, 0x70, 0x52, 0x47, 0x42, 0x82, 0xf0, 0x85, 0xa8, 0x81, 0x7e, 0xc0, 0xc6, 0xa8, 0x52, 0xe2, + 0x12, 0xdb, 0x12, 0xe8, 0x3b, 0x09, 0xc2, 0xb2, 0x53, 0x1a, 0x86, 0xe6, 0x90, 0xc3, 0x48, 0x14, 0x41, 0x29, 0xfc, + 0x02, 0x25, 0xcf, 0x34, 0x94, 0x80, 0x32, 0x75, 0x60, 0x47, 0x0d, 0x55, 0x89, 0x09, 0x75, 0x7a, 0x7a, 0x10, 0xdd, + 0xbb, 0x0c, 0x34, 0x4d, 0x07, 0xa7, 0x1d, 0x2a, 0xc6, 0xd2, 0x98, 0xea, 0x60, 0x3b, 0x2a, 0x04, 0x47, 0x3a, 0x1e, + 0x32, 0x0a, 0x4e, 0x6e, 0xdf, 0xe1, 0xb2, 0xe1, 0xd3, 0xed, 0xa7, 0x4a, 0x8c, 0x8e, 0x9e, 0xac, 0xce, 0xa5, 0xd5, + 0xf3, 0x6c, 0xcc, 0x24, 0x48, 0x9f, 0xc0, 0xa1, 0x52, 0xf8, 0x32, 0x03, 0xd3, 0x22, 0x8f, 0xb7, 0x65, 0xb4, 0x38, + 0x85, 0x92, 0xab, 0x6e, 0x1f, 0xe9, 0x36, 0xdf, 0xce, 0xa4, 0xdb, 0x6f, 0xa7, 0xc1, 0x51, 0xd6, 0xcc, 0xfa, 0x42, + 0xf9, 0xbc, 0x52, 0xaa, 0xed, 0x5b, 0xf9, 0x49, 0xa2, 0x83, 0x63, 0x0d, 0xd5, 0x2a, 0x2c, 0xf1, 0x93, 0x81, 0xd5, + 0x6b, 0x48, 0xb5, 0x91, 0x8a, 0x61, 0x07, 0x9e, 0x8f, 0x3c, 0x9e, 0xbb, 0xae, 0x34, 0xe3, 0xca, 0x30, 0xb3, 0x49, + 0x25, 0xc6, 0xf7, 0xc3, 0x63, 0x0f, 0xed, 0x99, 0xf6, 0xf9, 0x74, 0xf8, 0x12, 0xe8, 0x74, 0x20, 0x9a, 0x80, 0x81, + 0x39, 0x84, 0x32, 0x16, 0x68, 0x6c, 0x2c, 0x66, 0x51, 0x1e, 0x95, 0x29, 0x4d, 0x95, 0xc6, 0x30, 0x86, 0xda, 0x00, + 0xae, 0x6e, 0xd7, 0x4c, 0x4a, 0x46, 0x49, 0x77, 0x29, 0x0d, 0x14, 0xd3, 0x31, 0x8c, 0x15, 0x9e, 0x29, 0x19, 0x2e, + 0x0a, 0x71, 0x1a, 0xe0, 0xcb, 0x8b, 0xff, 0xf7, 0xaf, 0xc0, 0xa8, 0xb9, 0xed, 0x91, 0xac, 0xd9, 0xec, 0x68, 0x4b, + 0x2b, 0x3c, 0x4f, 0xe7, 0xcb, 0x17, 0x29, 0xeb, 0x52, 0x2d, 0x8a, 0xd3, 0xe8, 0x28, 0x23, 0x4a, 0xfb, 0x76, 0xf7, + 0x97, 0xba, 0x33, 0x8c, 0x98, 0x2b, 0xdf, 0xf8, 0x3d, 0xe5, 0x5a, 0xf2, 0x6e, 0xb7, 0x8c, 0xac, 0x4a, 0x31, 0xe1, + 0x43, 0xe5, 0x1a, 0x5e, 0x69, 0xfd, 0x07, 0xf9, 0x4f, 0xb9, 0xaa, 0x6d, 0x7f, 0x0c, 0xeb, 0x95, 0x6c, 0x4e, 0xb4, + 0xde, 0x3c, 0xe3, 0x88, 0xb7, 0x3d, 0xc6, 0xfd, 0x25, 0x85, 0x63, 0x69, 0xfc, 0xae, 0xea, 0x64, 0x37, 0x3f, 0xb9, + 0x5c, 0x90, 0xb4, 0x98, 0x74, 0xeb, 0xad, 0xca, 0x7e, 0xe6, 0xab, 0xf7, 0xfb, 0xb3, 0x87, 0x3b, 0x26, 0x41, 0xc2, + 0x6d, 0x43, 0x3e, 0x0d, 0x22, 0xbd, 0x6d, 0x46, 0x47, 0x69, 0xf2, 0xca, 0x99, 0x4d, 0x08, 0x84, 0xe3, 0x8d, 0xe9, + 0x01, 0x26, 0x3b, 0x93, 0xd2, 0xcb, 0xfe, 0x67, 0x76, 0xe5, 0xda, 0xd4, 0xc5, 0x5d, 0xb1, 0xc5, 0x83, 0xe4, 0xd7, + 0x43, 0x7c, 0x38, 0x86, 0x37, 0x9f, 0xe3, 0x77, 0xc8, 0x3f, 0xea, 0xb8, 0x0c, 0x0c, 0x4c, 0xac, 0x1c, 0xfb, 0x4e, + 0x78, 0xd9, 0xdf, 0x12, 0x6b, 0x50, 0x56, 0x69, 0x8a, 0x21, 0x18, 0xc4, 0x79, 0x1d, 0x00, 0xc8, 0x95, 0x0d, 0x62, + 0x9b, 0x27, 0xb2, 0xe5, 0xab, 0x60, 0xf1, 0xce, 0xf1, 0xd1, 0x0b, 0x6e, 0x4a, 0x7c, 0xaa, 0xbc, 0x3d, 0x63, 0x0c, + 0x70, 0x0b, 0xca, 0xd3, 0xb1, 0x83, 0x19, 0x31, 0x47, 0x42, 0xed, 0x8a, 0x4a, 0x2c, 0x49, 0x1d, 0x2a, 0x14, 0xcd, + 0xea, 0x82, 0x91, 0x89, 0xe4, 0xb3, 0x35, 0x55, 0x82, 0x81, 0xd4, 0x41, 0x7b, 0xf6, 0x2c, 0x4a, 0x9a, 0x7d, 0x1e, + 0x9a, 0x6c, 0x92, 0x3b, 0x7e, 0x09, 0xa6, 0x3f, 0xf8, 0x59, 0x28, 0xe9, 0x73, 0x6f, 0x62, 0x21, 0x7f, 0xb7, 0x95, + 0xf5, 0x27, 0xec, 0x1d, 0xfe, 0x26, 0x21, 0x7c, 0x39, 0x85, 0xd5, 0x24, 0x61, 0x59, 0xb8, 0xf0, 0x76, 0x49, 0x80, + 0x3c, 0x65, 0x69, 0x57, 0x83, 0x03, 0x85, 0x3e, 0x14, 0x94, 0x2c, 0x96, 0xb1, 0x12, 0x33, 0xc3, 0x22, 0xa6, 0xe4, + 0x5e, 0xf4, 0x35, 0xf3, 0xbe, 0xf9, 0x3a, 0x85, 0x47, 0x06, 0x4f, 0xe5, 0xa6, 0x6d, 0x5b, 0x88, 0x0e, 0x18, 0x9a, + 0xe9, 0x4f, 0x70, 0x40, 0xbb, 0x7f, 0xdd, 0xa5, 0xa7, 0x1c, 0xf8, 0xec, 0x39, 0x0e, 0xd6, 0x56, 0x9e, 0xa5, 0x9c, + 0x35, 0x54, 0xf7, 0x39, 0x05, 0x3f, 0x17, 0xef, 0x10, 0x57, 0x26, 0xc1, 0xd3, 0x5d, 0x4c, 0x12, 0x54, 0x9f, 0x82, + 0x21, 0xe9, 0x04, 0x74, 0xb1, 0xc2, 0xea, 0x5a, 0xb3, 0xe5, 0x09, 0xba, 0x98, 0x60, 0x05, 0x63, 0x38, 0x14, 0xf4, + 0xf2, 0x30, 0xb3, 0x1e, 0x56, 0xd3, 0xd3, 0x22, 0x48, 0x22, 0x9d, 0xec, 0xf6, 0x53, 0x92, 0xbd, 0x26, 0x12, 0x40, + 0x3f, 0x37, 0x2b, 0x69, 0x03, 0xe0, 0x41, 0xad, 0x10, 0xb1, 0xef, 0x45, 0xcc, 0x49, 0x2a, 0x55, 0x73, 0x46, 0xb7, + 0x15, 0x02, 0x62, 0x5d, 0xf8, 0x5b, 0x5e, 0xdd, 0x94, 0xfa, 0x53, 0xb0, 0x80, 0xbe, 0xe1, 0x42, 0x02, 0xaf, 0x8d, + 0x8d, 0xf7, 0x8a, 0xc6, 0x1a, 0x5f, 0x02, 0x58, 0x1c, 0x0c, 0xf0, 0xa4, 0xc6, 0x32, 0x2c, 0x01, 0x69, 0x15, 0x0f, + 0x9d, 0x98, 0xb0, 0xf2, 0xb4, 0xe0, 0x98, 0xe5, 0xbb, 0x7f, 0x98, 0xdf, 0xe9, 0xb4, 0x4e, 0x20, 0x31, 0xd3, 0xa9, + 0x76, 0x4b, 0x2f, 0x1f, 0x58, 0xbf, 0xd6, 0x98, 0x25, 0xe2, 0x9e, 0xe4, 0x65, 0xb7, 0x63, 0x15, 0xda, 0x58, 0xc4, + 0x32, 0x9e, 0x29, 0x87, 0x57, 0x53, 0x6f, 0xf3, 0xf0, 0x00, 0x0e, 0xcf, 0xa7, 0x96, 0xfb, 0xeb, 0x00, 0x13, 0x87, + 0x9b, 0x52, 0x28, 0x15, 0xf1, 0x7a, 0x10, 0x20, 0x12, 0xc4, 0x44, 0xbb, 0xc8, 0x50, 0x7a, 0xca, 0x0d, 0x62, 0xb3, + 0x01, 0x25, 0x62, 0x87, 0xb6, 0x8e, 0xd2, 0x1f, 0xc2, 0x57, 0x47, 0xf9, 0x54, 0x99, 0xea, 0xa4, 0xb7, 0x30, 0xcb, + 0xe5, 0x48, 0x35, 0x34, 0x60, 0xd9, 0x71, 0xfb, 0xc9, 0x63, 0x5b, 0x61, 0x78, 0x6e, 0xab, 0xfe, 0x6e, 0x1b, 0xfe, + 0xfe, 0x02, 0x5e, 0x3c, 0xfd, 0xbe, 0xee, 0x6b, 0x6e, 0xd9, 0x90, 0x43, 0x5d, 0xda, 0x8d, 0x88, 0xb8, 0x17, 0x2f, + 0xaf, 0x52, 0x48, 0x01, 0xd2, 0xfc, 0x01, 0x3c, 0x3b, 0xbe, 0x3d, 0xd2, 0x7d, 0x2a, 0x32, 0x41, 0x24, 0xe4, 0xed, + 0x82, 0xb0, 0xe2, 0xb1, 0xa7, 0xb0, 0x69, 0x64, 0x41, 0x9f, 0x4a, 0xe8, 0x12, 0x7e, 0x8a, 0x7c, 0x79, 0x39, 0x17, + 0xfc, 0x18, 0xd2, 0x09, 0x68, 0xb0, 0x3b, 0xeb, 0x45, 0x50, 0x06, 0x39, 0xed, 0x2d, 0xa5, 0x79, 0x27, 0x97, 0x8d, + 0x02, 0xd3, 0x96, 0x85, 0xf6, 0x4b, 0xa3, 0x6e, 0xba, 0x78, 0x6a, 0xa2, 0x10, 0xf0, 0xf0, 0xb0, 0xd9, 0xed, 0xa4, + 0xa1, 0x9c, 0x55, 0x73, 0xef, 0xab, 0x55, 0xe3, 0x8a, 0xe4, 0xe3, 0x61, 0x86, 0x20, 0xa4, 0xdd, 0x8e, 0x9c, 0x1a, + 0xc3, 0x51, 0xd1, 0xbe, 0x48, 0xd6, 0x79, 0xe2, 0x70, 0xdc, 0xcb, 0x27, 0x71, 0xb2, 0x71, 0xac, 0x8b, 0x93, 0x48, + 0x05, 0xbe, 0x58, 0x7d, 0xd5, 0x10, 0x6d, 0xa6, 0xc5, 0xe9, 0x5d, 0x55, 0xa5, 0x6a, 0x0a, 0xb4, 0x93, 0x22, 0x47, + 0x76, 0x33, 0xbb, 0x2b, 0xb6, 0xa1, 0xd0, 0x0c, 0x38, 0x7f, 0xd6, 0x5e, 0xac, 0x47, 0x78, 0xa8, 0xbc, 0xf8, 0x47, + 0xd1, 0x3f, 0x56, 0x3d, 0x91, 0x65, 0x2b, 0xfc, 0xd5, 0x78, 0xbd, 0xb4, 0xf8, 0x37, 0x0f, 0xdc, 0x67, 0xd7, 0xd9, + 0x91, 0xb7, 0xde, 0x9c, 0x8f, 0x57, 0x15, 0x4f, 0x17, 0x89, 0x6f, 0x18, 0x06, 0x70, 0x39, 0xa4, 0x79, 0xb9, 0xdb, + 0x7b, 0x0c, 0x9f, 0x86, 0x80, 0x90, 0x6c, 0xe7, 0xdc, 0x3e, 0x9f, 0x3f, 0x1c, 0x69, 0x33, 0x9c, 0xc9, 0x4b, 0x21, + 0xd9, 0x57, 0x08, 0x00, 0x64, 0xd5, 0x66, 0xa4, 0x63, 0x5d, 0x4d, 0x02, 0x69, 0x32, 0x49, 0xdd, 0x6e, 0x03, 0x5c, + 0x80, 0x54, 0x94, 0x2f, 0xd7, 0x83, 0x15, 0x35, 0xf5, 0xc2, 0x14, 0x5f, 0xee, 0xe5, 0x0b, 0x34, 0xad, 0x69, 0xda, + 0xcb, 0xb9, 0x0c, 0x05, 0xd6, 0xcb, 0x0e, 0x11, 0x1e, 0x64, 0x2b, 0xc6, 0xe3, 0x71, 0xe4, 0xbb, 0xc9, 0x07, 0x94, + 0x1b, 0x2c, 0x2e, 0xf7, 0xea, 0xcb, 0xa9, 0xdd, 0x14, 0xb6, 0x42, 0x9f, 0x61, 0x15, 0x05, 0x73, 0xc0, 0x9b, 0x6b, + 0x7a, 0x3b, 0x9b, 0x0b, 0xb2, 0xd9, 0xc5, 0x67, 0x0b, 0xdb, 0x20, 0x81, 0x78, 0x1c, 0x06, 0x6b, 0x72, 0x88, 0x94, + 0x78, 0x74, 0x4a, 0x53, 0x42, 0x01, 0xc8, 0x00, 0x5e, 0x4c, 0xe2, 0x2d, 0x24, 0xfd, 0xf7, 0xe0, 0x13, 0xec, 0xad, + 0x71, 0xc5, 0xc8, 0x79, 0xfe, 0xe1, 0x74, 0xc0, 0xe9, 0xcf, 0xed, 0x9d, 0xcf, 0x3d, 0x23, 0xa0, 0x46, 0xa9, 0x0f, + 0xe5, 0xc1, 0x7f, 0xd2, 0x15, 0x9d, 0xd6, 0x62, 0xbe, 0x13, 0xb1, 0x4a, 0x85, 0x2d, 0xf7, 0x32, 0xd8, 0xdf, 0xef, + 0x87, 0xe9, 0xff, 0xab, 0x6b, 0x43, 0x55, 0x7e, 0xfe, 0xb7, 0x35, 0xfc, 0x27, 0xbd, 0x0e, 0x4b, 0xcd, 0xfd, 0x6f, + 0x0d, 0x36, 0xfd, 0xf6, 0x1a, 0xea, 0xa1, 0x6d, 0xff, 0xd6, 0x03, 0x88, 0x3a, 0x28, 0x72, 0xb3, 0x27, 0xb2, 0xd2, + 0xaa, 0x73, 0x0f, 0x06, 0xda, 0xc2, 0xff, 0x9f, 0xe5, 0x3d, 0xcb, 0x9e, 0xad, 0x30, 0xb5, 0xf0, 0xf1, 0xfd, 0x8c, + 0x49, 0x00, 0xcb, 0x49, 0x84, 0x36, 0x0e, 0x39, 0xad, 0xfc, 0xb4, 0x46, 0xae, 0x43, 0x5a, 0xb1, 0x56, 0x01, 0xfd, + 0xb2, 0xa4, 0x4f, 0x10, 0xcf, 0x3d, 0x8c, 0xbd, 0x86, 0x92, 0xe0, 0x81, 0x7a, 0xbe, 0x75, 0x94, 0x1f, 0x49, 0xd3, + 0x62, 0x57, 0x4a, 0x7e, 0xe9, 0x9f, 0x3f, 0x66, 0xd9, 0x57, 0x96, 0x1f, 0x88, 0xa1, 0x26, 0xb7, 0xff, 0xc1, 0x42, + 0xda, 0x17, 0x24, 0x31, 0x16, 0xa6, 0x6e, 0x5d, 0x38, 0x9e, 0x38, 0xbd, 0x63, 0x5b, 0xb5, 0x19, 0x84, 0x17, 0x55, + 0x2d, 0x14, 0x67, 0xd7, 0x82, 0x32, 0xa6, 0xf7, 0xe9, 0x4c, 0x13, 0x0c, 0xa8, 0xa5, 0xe4, 0x9d, 0xdf, 0xf0, 0xef, + 0x6c, 0x85, 0x79, 0x57, 0x63, 0xee, 0xde, 0xc0, 0x3e, 0x1a, 0x39, 0x8c, 0xe3, 0x3e, 0x42, 0xa1, 0x6e, 0x70, 0x83, + 0x2f, 0x35, 0x12, 0xdd, 0xb3, 0x65, 0x1a, 0x46, 0x54, 0xf6, 0xbc, 0x05, 0x47, 0xe2, 0x9c, 0x71, 0x09, 0x32, 0xf4, + 0x08, 0x0d, 0xcb, 0x69, 0x78, 0x8b, 0x29, 0x6c, 0x2f, 0xef, 0x18, 0x77, 0x96, 0xad, 0xed, 0x55, 0x9a, 0x21, 0x90, + 0xce, 0x8b, 0xe0, 0xad, 0xe2, 0x49, 0xb8, 0x31, 0x6d, 0xcf, 0xd4, 0x83, 0x5d, 0x7b, 0x49, 0x2f, 0x6a, 0xf3, 0x37, + 0xb2, 0xdb, 0x7b, 0xe9, 0x98, 0x29, 0xcd, 0xeb, 0x9a, 0x2d, 0x5e, 0xbc, 0x20, 0x13, 0x7e, 0x1c, 0x5c, 0x1b, 0xb3, + 0x6e, 0xb7, 0x12, 0x80, 0xcc, 0x89, 0xc6, 0xd5, 0x5c, 0xec, 0x7f, 0xda, 0x1f, 0xa4, 0xf5, 0x60, 0xde, 0x3d, 0xb8, + 0x92, 0x11, 0x9b, 0xbf, 0x33, 0x37, 0x92, 0x7d, 0x93, 0x49, 0x0e, 0xb5, 0xa8, 0xaa, 0xe2, 0xc1, 0xbb, 0x17, 0xc9, + 0xdd, 0xd5, 0xa5, 0x25, 0xa3, 0xde, 0x20, 0x9f, 0xef, 0xd0, 0xcd, 0x3e, 0xac, 0xdb, 0x5a, 0xe3, 0xd4, 0xe2, 0x24, + 0x36, 0x4d, 0xac, 0xc2, 0xac, 0xa6, 0x13, 0xc1, 0xf6, 0xbf, 0xd6, 0xe0, 0x9a, 0x89, 0x3a, 0x14, 0xd6, 0x56, 0x28, + 0x94, 0x82, 0x1f, 0x25, 0x20, 0x61, 0xc6, 0x98, 0x13, 0x70, 0x82, 0x64, 0x4c, 0x27, 0x53, 0xa2, 0x69, 0x28, 0x37, + 0x3f, 0x88, 0x19, 0xbe, 0xcd, 0x28, 0x46, 0x40, 0x72, 0x3f, 0x32, 0x72, 0xc3, 0xc9, 0x92, 0x50, 0x23, 0xee, 0xf6, + 0xc9, 0x2f, 0x70, 0xcc, 0x78, 0x8e, 0xa5, 0xd4, 0xf8, 0x69, 0x7d, 0x7e, 0xcc, 0x7a, 0x3f, 0x5d, 0xff, 0xb0, 0xba, + 0xe7, 0xce, 0x3f, 0x28, 0xe9, 0xd4, 0x5c, 0x43, 0x66, 0x55, 0x00, 0xc8, 0x9b, 0xf2, 0xce, 0xb8, 0x8e, 0xd3, 0x7b, + 0xab, 0x44, 0x04, 0x2e, 0x55, 0xb4, 0xaa, 0x31, 0x82, 0xf9, 0x5e, 0x88, 0x18, 0x27, 0x2b, 0x07, 0xbe, 0xf7, 0x2b, + 0x54, 0x24, 0xe7, 0xe1, 0x73, 0xf6, 0x46, 0x9a, 0x3e, 0x16, 0x4d, 0x26, 0xcf, 0x1d, 0xf1, 0x55, 0x7c, 0x7e, 0x37, + 0x4b, 0x17, 0x9b, 0x6c, 0x0e, 0x52, 0xc1, 0x92, 0x86, 0xba, 0x80, 0xda, 0xd6, 0x62, 0x28, 0xd1, 0x8e, 0xd4, 0xea, + 0x84, 0x2f, 0xa5, 0x80, 0xa5, 0x32, 0x22, 0x67, 0xa8, 0xad, 0xc1, 0xa9, 0xa3, 0x34, 0x71, 0xdd, 0xab, 0x0a, 0xbe, + 0x28, 0xf3, 0xc8, 0x9d, 0x31, 0xfc, 0xd2, 0xc7, 0xeb, 0x90, 0x8c, 0x91, 0x69, 0x36, 0x70, 0x7e, 0x9a, 0x15, 0xeb, + 0x1d, 0x7c, 0x21, 0x74, 0xea, 0xd4, 0x4c, 0xbe, 0x40, 0xdd, 0x0a, 0x4a, 0x32, 0x1c, 0x7c, 0xad, 0x8a, 0x5b, 0xb4, + 0x12, 0xf7, 0x1f, 0x90, 0xf5, 0x49, 0x2b, 0x69, 0xd1, 0x9e, 0x56, 0x56, 0x04, 0xa5, 0x65, 0x52, 0xb5, 0x29, 0x4c, + 0xbf, 0x14, 0x1d, 0xd5, 0xd3, 0xba, 0x7b, 0x3f, 0xe4, 0x76, 0xc9, 0x25, 0xdb, 0x7d, 0x8b, 0x34, 0x34, 0xba, 0xda, + 0x15, 0x80, 0xb4, 0xeb, 0x4d, 0x5f, 0x85, 0xcc, 0x53, 0xd2, 0x94, 0x92, 0x1e, 0x1c, 0xb2, 0x23, 0x34, 0xbf, 0xef, + 0xc6, 0x56, 0x1d, 0xe9, 0x4e, 0x05, 0xfb, 0xce, 0x2f, 0x73, 0xbb, 0x19, 0x9c, 0xc4, 0xe7, 0x36, 0x7e, 0xed, 0x11, + 0x40, 0xb6, 0xa8, 0x84, 0xaf, 0x4d, 0x39, 0x68, 0x97, 0x5f, 0xe2, 0x99, 0x9a, 0x1d, 0x0a, 0xef, 0xf3, 0xd6, 0x69, + 0xba, 0x75, 0x6c, 0x94, 0x4a, 0x1e, 0x7e, 0xa3, 0x42, 0xb6, 0x62, 0x77, 0x56, 0xb8, 0x00, 0x73, 0xfe, 0xaa, 0x20, + 0xea, 0x4a, 0x56, 0xdb, 0x45, 0x8d, 0xc1, 0x06, 0xda, 0x38, 0xd4, 0x2b, 0x44, 0xcc, 0x3b, 0x46, 0x39, 0x42, 0x87, + 0xa4, 0x43, 0x49, 0x27, 0xd3, 0x40, 0x4e, 0xac, 0x3a, 0x24, 0xd8, 0x9f, 0x8e, 0x94, 0x03, 0xf8, 0x9f, 0x4c, 0x91, + 0xe5, 0x9f, 0xea, 0x55, 0xce, 0xd4, 0x29, 0xfe, 0x5c, 0xb2, 0x6b, 0x76, 0x94, 0x5a, 0x4d, 0x35, 0xee, 0x17, 0x4d, + 0x01, 0xa3, 0x52, 0x5e, 0xcb, 0x8e, 0xdc, 0xcc, 0x91, 0x14, 0xff, 0x60, 0xb2, 0xf4, 0xa4, 0x7f, 0x7c, 0xc8, 0xa5, + 0xaf, 0x9c, 0x7b, 0xf5, 0xce, 0x22, 0xa7, 0x2a, 0xdd, 0xfd, 0x34, 0x77, 0x9e, 0xfe, 0xfe, 0x92, 0x9d, 0x1f, 0xfd, + 0xc5, 0x43, 0x74, 0x86, 0xbf, 0x60, 0x43, 0xec, 0xc1, 0xda, 0x65, 0xe1, 0xc9, 0xeb, 0xf3, 0x43, 0xa3, 0x4f, 0x19, + 0x58, 0xf2, 0xee, 0x82, 0x96, 0x40, 0x99, 0xd7, 0x94, 0xa5, 0x5a, 0xdf, 0x17, 0xd3, 0xa7, 0x2b, 0x76, 0xbe, 0x98, + 0x55, 0x5b, 0x6d, 0xdf, 0x97, 0xd5, 0x6d, 0x75, 0xff, 0x72, 0xf6, 0xe1, 0xaf, 0xdb, 0x7b, 0x3e, 0x31, 0x01, 0x08, + 0xec, 0xf4, 0x50, 0xf5, 0x8b, 0x9f, 0xab, 0xb2, 0x98, 0xaa, 0xba, 0x38, 0xab, 0xc6, 0xc5, 0x79, 0x35, 0x3d, 0xfc, + 0x74, 0xc4, 0x0f, 0x3c, 0x12, 0x86, 0xd5, 0x89, 0x06, 0x59, 0x5b, 0xfc, 0xd2, 0xd4, 0x32, 0xcb, 0x27, 0x8a, 0xdd, + 0x4a, 0xad, 0x3f, 0xed, 0xd2, 0xf8, 0xd3, 0x64, 0x79, 0x23, 0x05, 0xbd, 0x52, 0xd1, 0x2e, 0x27, 0xb6, 0xd3, 0x4c, + 0x2c, 0x48, 0x2c, 0x65, 0xa7, 0xbd, 0xb5, 0x0e, 0x39, 0x83, 0x41, 0x6f, 0xbf, 0xe4, 0x1a, 0xcf, 0x22, 0x8c, 0x99, + 0xbc, 0xa1, 0xb7, 0x4c, 0x05, 0x5f, 0xa1, 0x1a, 0x33, 0xeb, 0x3b, 0x51, 0x47, 0x12, 0x0b, 0x82, 0x18, 0xba, 0xd4, + 0x49, 0xed, 0xed, 0xd2, 0xd5, 0xad, 0xab, 0xbe, 0x04, 0x70, 0x2d, 0xd6, 0x94, 0x9e, 0xfa, 0xa2, 0x46, 0x31, 0x3a, + 0x2a, 0x4b, 0x66, 0xaa, 0x84, 0x8a, 0x1e, 0x62, 0x7d, 0xcb, 0xbc, 0xce, 0xca, 0x73, 0x33, 0x4c, 0xd3, 0x2d, 0xcd, + 0x00, 0x5f, 0xd1, 0x85, 0xac, 0xcc, 0x05, 0x6f, 0x29, 0x99, 0xd6, 0x23, 0xe3, 0x54, 0xd3, 0xba, 0x7a, 0x44, 0xf6, + 0xf2, 0x97, 0xb7, 0x40, 0x64, 0x1f, 0xfa, 0xa2, 0xf6, 0x59, 0x94, 0xad, 0x30, 0x89, 0x41, 0xa6, 0x21, 0xe4, 0x28, + 0x0d, 0xd1, 0x88, 0xb3, 0x78, 0xb4, 0xab, 0x20, 0xb1, 0xf1, 0x59, 0x7e, 0xcd, 0x8c, 0xbd, 0x0e, 0x20, 0x16, 0xa8, + 0xb8, 0x2c, 0xbd, 0xe0, 0xff, 0x41, 0x0d, 0xe5, 0xbe, 0xe9, 0x7f, 0xa0, 0x98, 0x14, 0xca, 0xcd, 0xd0, 0x8f, 0x4b, + 0xae, 0x60, 0x13, 0x62, 0xd0, 0x83, 0x15, 0x51, 0x9d, 0xc5, 0xbe, 0x45, 0x9d, 0x40, 0x0a, 0x38, 0x50, 0x9c, 0x41, + 0xe3, 0x44, 0x01, 0x8e, 0x06, 0xad, 0xb5, 0x48, 0x85, 0x50, 0x78, 0x3f, 0xea, 0xaa, 0x75, 0x39, 0xd2, 0xd0, 0x4d, + 0xa4, 0xdf, 0xea, 0xd7, 0x56, 0x94, 0xc1, 0x9c, 0x5f, 0xae, 0xbc, 0xf9, 0xa0, 0xe4, 0xef, 0xdb, 0x3f, 0xa9, 0x0b, + 0x54, 0xf4, 0x0e, 0x1c, 0x46, 0xb4, 0x39, 0x62, 0x6c, 0x61, 0x71, 0x18, 0x5b, 0xea, 0x09, 0xb1, 0xfe, 0x0e, 0x3d, + 0xc2, 0xd9, 0x37, 0x49, 0xad, 0x79, 0x39, 0x99, 0xe5, 0x76, 0x3b, 0xba, 0xdd, 0xf9, 0x99, 0x29, 0xfc, 0xa4, 0xe6, + 0x60, 0x51, 0xef, 0x49, 0xa4, 0x01, 0xba, 0x5e, 0x38, 0x8f, 0xc0, 0xf5, 0x28, 0x49, 0xc1, 0x64, 0x40, 0x13, 0x1a, + 0x3b, 0x62, 0x65, 0xc5, 0x59, 0x1a, 0x8d, 0xce, 0x85, 0xab, 0xa2, 0xfa, 0xfb, 0xcb, 0x62, 0x2e, 0x00, 0x8c, 0x20, + 0xf4, 0xc1, 0x1b, 0xbb, 0x9d, 0x36, 0xbd, 0xda, 0x96, 0x34, 0xc4, 0x11, 0x44, 0x65, 0x41, 0xc5, 0x2e, 0xa8, 0x3a, + 0xda, 0x2f, 0xa8, 0x1c, 0x27, 0xd5, 0x90, 0x9f, 0x7a, 0x65, 0xb9, 0x0b, 0xfe, 0xdc, 0xa3, 0x5a, 0xfd, 0xf3, 0x43, + 0xc3, 0x53, 0xfd, 0x43, 0x98, 0xf7, 0x95, 0xf2, 0x3c, 0x97, 0x7c, 0x6c, 0x12, 0xc9, 0xd5, 0x56, 0x05, 0x1f, 0x1e, + 0x4a, 0x7a, 0x2b, 0x6a, 0x16, 0x58, 0x6f, 0x0f, 0xcf, 0x6b, 0xcf, 0x61, 0xc6, 0x8e, 0xfa, 0x25, 0x51, 0x37, 0x67, + 0xff, 0x0d, 0x06, 0xf6, 0x9b, 0x56, 0x72, 0xae, 0x9b, 0xf5, 0x9e, 0x27, 0xc5, 0x7a, 0x3d, 0xbf, 0xa2, 0x81, 0x8d, + 0x7d, 0xf6, 0x99, 0x3f, 0xa0, 0x61, 0x90, 0x3d, 0x5d, 0x37, 0xe7, 0xb4, 0xce, 0xce, 0xb9, 0x72, 0xd8, 0x69, 0x33, + 0x7e, 0xd2, 0xbd, 0xe5, 0xa0, 0xda, 0x02, 0xf9, 0x9d, 0xfd, 0x84, 0x38, 0x69, 0xf9, 0xf9, 0x69, 0xb4, 0x33, 0x0b, + 0x21, 0x0f, 0xce, 0x76, 0x2b, 0x20, 0xe5, 0x65, 0x76, 0x01, 0x49, 0x73, 0xa1, 0xe7, 0x38, 0x2a, 0x45, 0x82, 0x2f, + 0x03, 0x66, 0xdd, 0x35, 0x02, 0xd3, 0xf5, 0x6e, 0x65, 0xde, 0xc5, 0xaa, 0x06, 0x9d, 0xd7, 0x36, 0x6d, 0xdf, 0x7c, + 0xa5, 0x3b, 0x9e, 0xbe, 0x28, 0x16, 0x3b, 0xac, 0xdc, 0xe5, 0x20, 0x7f, 0xaf, 0x04, 0x1e, 0x05, 0xf0, 0x5e, 0x4c, + 0xd2, 0x4f, 0xf0, 0x74, 0x27, 0x13, 0x98, 0xa8, 0x86, 0xa4, 0x6c, 0x75, 0x77, 0x23, 0x9b, 0x51, 0x35, 0xd0, 0x29, + 0x47, 0x8e, 0x78, 0xf5, 0xb3, 0xf6, 0x98, 0x07, 0x3b, 0xf7, 0xad, 0x17, 0x7e, 0x94, 0x0d, 0x15, 0x96, 0x67, 0x0c, + 0x0d, 0x38, 0x65, 0x58, 0x5c, 0xc6, 0x60, 0x40, 0x6e, 0xae, 0xe3, 0x46, 0x0a, 0xcd, 0x3f, 0x47, 0x3f, 0xa6, 0xa0, + 0x06, 0xea, 0x8d, 0xeb, 0xf1, 0xa1, 0x19, 0xec, 0x97, 0xbf, 0x01, 0x8f, 0x0f, 0x32, 0xa0, 0x9a, 0x85, 0xce, 0x68, + 0xe3, 0x69, 0x9e, 0x7f, 0xd2, 0xb7, 0xb9, 0xe4, 0xfc, 0x47, 0xff, 0x34, 0x1b, 0xa7, 0xce, 0xc9, 0x99, 0x26, 0xc1, + 0x79, 0x0a, 0x5d, 0x9d, 0xfd, 0x7f, 0x97, 0x6c, 0x64, 0x15, 0x2f, 0x9a, 0x47, 0x71, 0x75, 0x81, 0x28, 0xaa, 0xf5, + 0x91, 0x67, 0xed, 0xce, 0x5e, 0xec, 0x7b, 0x38, 0x0c, 0x7a, 0x83, 0x0f, 0x7e, 0xaa, 0xf2, 0x24, 0x66, 0xfd, 0xca, + 0x44, 0xca, 0x25, 0x7e, 0x4a, 0x5d, 0xd9, 0xd7, 0x49, 0xb3, 0x0f, 0x97, 0xa6, 0x34, 0x1c, 0xd8, 0x94, 0x62, 0x8d, + 0x0a, 0xb0, 0x5f, 0x89, 0xd2, 0xb7, 0x76, 0xce, 0xd0, 0x07, 0xff, 0xac, 0x0a, 0x2c, 0x4e, 0xeb, 0x32, 0x40, 0x52, + 0xd7, 0xe3, 0xca, 0x7e, 0x3d, 0x09, 0x88, 0x8b, 0x7c, 0x85, 0x36, 0x47, 0x8c, 0x51, 0x91, 0x0b, 0xd1, 0x41, 0xe6, + 0xaa, 0x62, 0xa2, 0xd6, 0xa7, 0x17, 0xb4, 0xfb, 0x6e, 0x22, 0x2e, 0xd4, 0xd0, 0xf9, 0x57, 0x27, 0x16, 0x94, 0x36, + 0xc7, 0xf6, 0x8e, 0xd0, 0x23, 0x97, 0xf1, 0x11, 0x41, 0x12, 0x5f, 0x4f, 0x61, 0xde, 0x7e, 0xc7, 0x8f, 0xab, 0x08, + 0x20, 0x81, 0x77, 0x8b, 0xb8, 0x19, 0x18, 0x4a, 0x12, 0xa8, 0x9a, 0x5a, 0xeb, 0x01, 0x13, 0xf3, 0x4e, 0x47, 0xe1, + 0x56, 0x54, 0x20, 0xf0, 0x10, 0x99, 0xd8, 0x83, 0x44, 0x56, 0x8f, 0xa2, 0x87, 0x3b, 0xda, 0xe9, 0x4a, 0xa6, 0x68, + 0x04, 0x25, 0xda, 0xf4, 0x90, 0xa4, 0x87, 0x2f, 0x9b, 0x89, 0xde, 0x89, 0x73, 0xd3, 0x1f, 0xf5, 0x5e, 0xcb, 0xfe, + 0x77, 0x5d, 0x47, 0xf6, 0x2e, 0x63, 0x44, 0xcc, 0xe1, 0x51, 0xb6, 0x9e, 0xac, 0x8e, 0xdb, 0x3e, 0xe4, 0xdc, 0x0b, + 0x8a, 0x01, 0x68, 0x6f, 0x0e, 0xdd, 0x77, 0xa5, 0x44, 0xad, 0xeb, 0xd6, 0x43, 0xca, 0x35, 0x12, 0xfd, 0xc5, 0xf7, + 0xe7, 0x77, 0xb5, 0xc9, 0xc9, 0x26, 0x0a, 0x15, 0x4d, 0xf2, 0x18, 0x44, 0x87, 0x97, 0xc6, 0x30, 0xea, 0xc5, 0xc5, + 0x18, 0xb1, 0xa7, 0xd3, 0x28, 0x6e, 0x61, 0x31, 0x5a, 0x65, 0x6f, 0x11, 0x62, 0x5d, 0x3a, 0x35, 0x4c, 0x51, 0xf5, + 0xdf, 0x9f, 0x46, 0xb5, 0x3b, 0x05, 0x11, 0xf8, 0x7a, 0xee, 0x58, 0xb2, 0x0b, 0xa8, 0x97, 0xf3, 0x77, 0xac, 0x68, + 0xd3, 0x69, 0x1f, 0x84, 0x71, 0x8c, 0xcc, 0x7b, 0xf9, 0xb6, 0x08, 0x31, 0x94, 0x12, 0xa4, 0xe0, 0x6b, 0xc7, 0x30, + 0x08, 0x0e, 0xf3, 0xf2, 0x31, 0xb4, 0xff, 0x10, 0xee, 0xc8, 0x8c, 0x31, 0x99, 0xe2, 0xde, 0x00, 0xeb, 0x0d, 0x77, + 0xd8, 0x47, 0x47, 0xbd, 0xd2, 0xe4, 0x4e, 0x12, 0x7b, 0x9a, 0x49, 0x8e, 0xde, 0xed, 0xd2, 0x28, 0x53, 0x3a, 0x7c, + 0x33, 0x89, 0xf8, 0x56, 0x9c, 0x10, 0xa9, 0xba, 0xac, 0xad, 0xae, 0xfd, 0xbe, 0x74, 0x1c, 0xdd, 0xb3, 0x6b, 0xbd, + 0x8f, 0x62, 0x6c, 0xd5, 0x9b, 0x9a, 0x6d, 0xea, 0xa7, 0xa1, 0x40, 0x8e, 0x0e, 0x77, 0xba, 0x95, 0x4c, 0xc7, 0xea, + 0xf2, 0x17, 0x6d, 0x5b, 0xe4, 0x0b, 0x03, 0x98, 0x9e, 0xba, 0xb7, 0x59, 0xed, 0x27, 0x44, 0x89, 0xf4, 0x81, 0x98, + 0x25, 0x3e, 0x4a, 0x01, 0xe3, 0x2b, 0xa7, 0x89, 0x6c, 0xf0, 0xb3, 0xfc, 0x5c, 0xc4, 0xed, 0xae, 0xf1, 0x9c, 0x4f, + 0x00, 0xbd, 0x1f, 0x8f, 0xb3, 0x33, 0x68, 0xe7, 0xdb, 0x74, 0xa6, 0x53, 0x79, 0x31, 0xfd, 0xb3, 0xff, 0xcf, 0xf4, + 0x40, 0xfd, 0x01, 0x24, 0x1a, 0xff, 0xf7, 0x22, 0x93, 0xd7, 0x6a, 0x24, 0x26, 0x07, 0x31, 0xea, 0x1e, 0x14, 0x8b, + 0x68, 0x08, 0xe0, 0x2b, 0x2f, 0x88, 0x1b, 0x1c, 0x1e, 0x15, 0x3e, 0x4d, 0xef, 0x0e, 0xe4, 0x70, 0xa7, 0xe3, 0x49, + 0x5b, 0xdc, 0x57, 0xc9, 0xcd, 0x8c, 0xfd, 0x3e, 0x83, 0x68, 0x18, 0x14, 0x7d, 0x81, 0x41, 0x29, 0xe4, 0xe7, 0x4b, + 0xf1, 0xa5, 0x99, 0xab, 0x2b, 0xa3, 0xa4, 0xb5, 0x82, 0xf5, 0x2a, 0xa4, 0x06, 0x12, 0xef, 0xa5, 0xf0, 0x19, 0xf4, + 0x14, 0x8a, 0xfd, 0xfe, 0xd4, 0x29, 0x27, 0x68, 0x2f, 0xab, 0xd2, 0xa4, 0x57, 0x92, 0xdb, 0x7b, 0x67, 0x1d, 0xfd, + 0x04, 0x28, 0xc7, 0x0f, 0xa2, 0xc5, 0xd7, 0x0e, 0x8b, 0x72, 0xbb, 0x54, 0x75, 0x1c, 0x43, 0xf0, 0xfc, 0xc9, 0xb3, + 0xb0, 0x5d, 0x91, 0x9e, 0xfe, 0x6d, 0xb1, 0xe9, 0xbb, 0x73, 0xab, 0xe1, 0xff, 0xe4, 0xb3, 0x3f, 0xf0, 0x36, 0x3d, + 0xeb, 0xcf, 0xd8, 0x48, 0xe5, 0x5d, 0xc2, 0xe5, 0x36, 0xb1, 0xf9, 0x02, 0x86, 0xe1, 0x71, 0x7b, 0x9e, 0x08, 0x89, + 0xfd, 0xa6, 0x30, 0xb3, 0xc7, 0xb1, 0x68, 0x25, 0xc2, 0xdf, 0xee, 0x46, 0xde, 0xf9, 0x4f, 0x87, 0x25, 0x08, 0xc3, + 0xb9, 0x71, 0xa6, 0xdf, 0x33, 0xda, 0x7f, 0x9a, 0xa7, 0x4f, 0x7f, 0x77, 0xc9, 0xe9, 0x8f, 0xfe, 0x69, 0xf6, 0xbd, + 0x7d, 0x55, 0xa2, 0x77, 0xc0, 0x66, 0xdf, 0x44, 0x8c, 0x9a, 0xbc, 0x9e, 0x53, 0x0e, 0x7a, 0x44, 0x57, 0x33, 0xe1, + 0xe5, 0x09, 0x5c, 0xa0, 0x61, 0x54, 0xe7, 0x3d, 0xcf, 0xc1, 0x0b, 0x65, 0xbb, 0xa3, 0x58, 0x92, 0x68, 0xb3, 0x90, + 0x3b, 0xf4, 0x53, 0x83, 0x28, 0xc1, 0xac, 0xfb, 0x49, 0xb2, 0x47, 0x6d, 0x35, 0x4c, 0xac, 0x52, 0x5d, 0x7c, 0xe7, + 0x5a, 0x26, 0x29, 0xe5, 0x55, 0xbc, 0x53, 0x89, 0xbc, 0xf9, 0x21, 0xcc, 0x98, 0x0d, 0x46, 0x2f, 0x84, 0xb0, 0xdf, + 0x29, 0x02, 0x23, 0x47, 0x15, 0x2c, 0x24, 0x7e, 0xbb, 0x03, 0x24, 0xde, 0xbe, 0x0b, 0xd2, 0x57, 0x12, 0x20, 0x5f, + 0xcb, 0x96, 0x53, 0x9b, 0x9d, 0x1b, 0xe1, 0xb0, 0x47, 0xe9, 0x1b, 0xef, 0x91, 0x6f, 0x64, 0xd2, 0x56, 0xa9, 0x1f, + 0x03, 0xcc, 0xce, 0xd6, 0x61, 0x64, 0xc4, 0x0e, 0xe4, 0x10, 0x53, 0xb1, 0x03, 0x04, 0xb3, 0x0e, 0xfd, 0x1c, 0xf8, + 0x63, 0xd7, 0x0d, 0x40, 0x34, 0x6b, 0x2e, 0x7d, 0x92, 0xb1, 0x9d, 0x1c, 0x8e, 0x4d, 0x04, 0xe3, 0x7d, 0xa9, 0xfb, + 0xac, 0x79, 0x8a, 0x94, 0x6a, 0x89, 0x14, 0x34, 0x20, 0xbd, 0x8a, 0x3b, 0xf7, 0x6c, 0x0e, 0x46, 0x9c, 0xec, 0xef, + 0x4a, 0xa9, 0x3e, 0xdc, 0xb8, 0xcb, 0xa1, 0x71, 0x5e, 0x1e, 0xb0, 0x8b, 0xcd, 0xa0, 0x04, 0xda, 0xe9, 0x34, 0x4f, + 0xd6, 0x1a, 0xcc, 0xb9, 0x26, 0x25, 0x29, 0x0b, 0x9f, 0x90, 0x19, 0xb9, 0xf9, 0xbe, 0xbc, 0xbe, 0xe5, 0xc3, 0x68, + 0x4e, 0x29, 0xd8, 0x2b, 0x7d, 0xd3, 0xa7, 0xfb, 0xba, 0xfc, 0xdc, 0x05, 0xdd, 0xda, 0x41, 0x2b, 0x17, 0x0f, 0xfb, + 0x93, 0x47, 0x02, 0xc8, 0x04, 0xf1, 0xc3, 0x0d, 0xcb, 0xee, 0xbe, 0x4f, 0x60, 0xf6, 0x8d, 0x5f, 0xec, 0xa7, 0x0c, + 0x83, 0x6f, 0xec, 0x66, 0x95, 0x60, 0x39, 0xfc, 0x3f, 0xf7, 0xcf, 0xb6, 0x5e, 0xec, 0x26, 0x87, 0xab, 0xfd, 0xba, + 0x7d, 0x06, 0x18, 0x7b, 0xbf, 0x5c, 0x27, 0x54, 0xc2, 0x48, 0x6d, 0xd1, 0xe4, 0xab, 0xc2, 0x99, 0x3d, 0x9c, 0x4c, + 0xd9, 0x4e, 0xa1, 0x16, 0x69, 0x1c, 0xd7, 0x39, 0x47, 0x5a, 0xa0, 0x8d, 0x65, 0xb1, 0x68, 0x14, 0x09, 0x9d, 0x60, + 0x8b, 0x8d, 0x1c, 0xf7, 0xc3, 0xfa, 0x6c, 0x98, 0xf1, 0x96, 0x28, 0xb4, 0xe0, 0x6c, 0xc4, 0x44, 0x90, 0x51, 0x35, + 0x06, 0xa1, 0x1d, 0x72, 0xb0, 0x00, 0xd5, 0xd0, 0x29, 0x82, 0xe7, 0xc6, 0x9f, 0x16, 0x3f, 0x2e, 0x0c, 0x5e, 0x42, + 0x32, 0x0c, 0x12, 0x40, 0x8a, 0xc9, 0x4a, 0xba, 0x71, 0x6f, 0xb7, 0x70, 0xbc, 0x2f, 0x98, 0x6a, 0xec, 0xa7, 0xdd, + 0xa3, 0x9b, 0x0e, 0xd4, 0x8b, 0x8f, 0x06, 0x86, 0xed, 0x8e, 0x21, 0xf3, 0xca, 0x88, 0xce, 0x44, 0xcf, 0xfb, 0x38, + 0xe9, 0xb1, 0x55, 0x98, 0x23, 0xcc, 0x08, 0xbe, 0x31, 0x99, 0x8d, 0x3c, 0xc2, 0xdd, 0x6e, 0x3f, 0x9a, 0xe3, 0xd8, + 0x1a, 0x7b, 0x85, 0x50, 0xa8, 0x78, 0xcb, 0x74, 0x37, 0xa1, 0x59, 0x87, 0xcd, 0x3d, 0xd4, 0xd9, 0x55, 0x06, 0xfa, + 0x2c, 0xab, 0x04, 0x27, 0xf2, 0xf6, 0xdb, 0xe8, 0x42, 0x03, 0x27, 0x68, 0x6b, 0xa3, 0x87, 0x7f, 0x88, 0xd0, 0xb7, + 0xa0, 0x4e, 0x38, 0x29, 0xdf, 0x19, 0x8f, 0x89, 0x41, 0xd4, 0x38, 0x4e, 0x95, 0x59, 0x4e, 0x4f, 0x76, 0x23, 0x57, + 0x4a, 0xae, 0xb0, 0x9c, 0x59, 0x5a, 0x36, 0x4b, 0x05, 0x78, 0xff, 0x51, 0x17, 0xc7, 0x84, 0x94, 0xab, 0x46, 0x6d, + 0xea, 0x81, 0x86, 0x4f, 0xa3, 0x95, 0x54, 0x56, 0x36, 0xf1, 0x87, 0x1e, 0xee, 0xf4, 0x07, 0xd1, 0xdd, 0x8a, 0x6a, + 0x93, 0xdb, 0xd0, 0x78, 0x42, 0x8f, 0x29, 0xec, 0x83, 0x45, 0xa0, 0xce, 0xa3, 0xf0, 0xf0, 0xf8, 0x3b, 0x26, 0x6f, + 0x24, 0xd1, 0xad, 0xc0, 0xcd, 0xe2, 0x07, 0x2e, 0x58, 0x24, 0x39, 0x5a, 0xc5, 0xd2, 0xbb, 0xd3, 0xb2, 0x35, 0xa9, + 0xfc, 0x84, 0xb6, 0xaf, 0xaf, 0xe5, 0x55, 0x0b, 0xac, 0xc4, 0xec, 0x55, 0x23, 0xf9, 0x45, 0x29, 0x0e, 0xec, 0x80, + 0x69, 0x91, 0x6b, 0x34, 0xcc, 0xd4, 0xb2, 0x79, 0x30, 0xee, 0xe9, 0x36, 0x1c, 0x4a, 0x67, 0x77, 0x7f, 0xa1, 0x09, + 0x0e, 0xa1, 0x29, 0xa9, 0x09, 0x93, 0x7c, 0x3c, 0xb5, 0x71, 0x62, 0x15, 0xb5, 0x60, 0xb2, 0xe5, 0xb8, 0xe5, 0xb5, + 0x3a, 0xa6, 0xea, 0xa5, 0xf7, 0x31, 0x90, 0x24, 0xd3, 0x38, 0xa1, 0x72, 0x70, 0x43, 0xbc, 0x42, 0xc1, 0x69, 0x7b, + 0x1a, 0x27, 0x76, 0x28, 0x6f, 0xff, 0x2a, 0xde, 0x56, 0x68, 0xfe, 0x15, 0x4e, 0xde, 0xcb, 0xf5, 0xbb, 0x6e, 0xb8, + 0x99, 0xd8, 0x0d, 0xbb, 0xfd, 0xab, 0x69, 0xab, 0x54, 0xec, 0xe9, 0xa4, 0xe7, 0x23, 0x1f, 0x00, 0xf8, 0xf3, 0xca, + 0x04, 0xf9, 0x64, 0x98, 0x11, 0xb5, 0x09, 0xc2, 0x4c, 0x65, 0xc4, 0xf8, 0xa6, 0x2a, 0x37, 0xb5, 0x68, 0x45, 0x62, + 0x49, 0x69, 0x1a, 0x67, 0xe7, 0x8e, 0x34, 0x3b, 0xee, 0x8e, 0xd8, 0x6d, 0x89, 0xb9, 0x7e, 0x9a, 0xf4, 0x34, 0x58, + 0x85, 0x22, 0x54, 0x9e, 0x50, 0xae, 0x29, 0x47, 0x7b, 0xd0, 0x8d, 0xba, 0x86, 0x0c, 0x86, 0x54, 0xa1, 0x8c, 0x5e, + 0xec, 0x3c, 0x22, 0x70, 0x54, 0xa1, 0x87, 0x0c, 0xa4, 0xa8, 0x88, 0x66, 0x33, 0x7e, 0x7c, 0xfe, 0x95, 0xa2, 0x2d, + 0xea, 0x06, 0xe1, 0x10, 0x80, 0xac, 0x77, 0x87, 0x43, 0x08, 0x5c, 0xff, 0x0e, 0xcb, 0xd6, 0xa8, 0x51, 0x46, 0x06, + 0x36, 0x64, 0x3d, 0x45, 0xfa, 0x8f, 0x51, 0x5d, 0x91, 0x49, 0xdd, 0xac, 0x50, 0x46, 0x90, 0x41, 0xcc, 0x3b, 0x4a, + 0x9b, 0x6f, 0x86, 0xd1, 0x91, 0x35, 0x8a, 0x30, 0x15, 0xbb, 0x41, 0xe1, 0xaa, 0x3f, 0x48, 0x91, 0x5d, 0x88, 0x38, + 0x05, 0x78, 0x77, 0x6a, 0x48, 0xd4, 0xac, 0xa9, 0x68, 0xf8, 0x18, 0x7a, 0xee, 0xcc, 0xbb, 0x0d, 0x07, 0x12, 0xc2, + 0x22, 0x35, 0xd8, 0x81, 0x68, 0x0b, 0x32, 0x16, 0xe1, 0x8d, 0x48, 0x34, 0xd4, 0x7b, 0x02, 0xf0, 0x6e, 0xdd, 0xa7, + 0xbc, 0x03, 0x80, 0x3e, 0x59, 0x39, 0x91, 0xee, 0x8f, 0x07, 0x72, 0x88, 0xb9, 0xd9, 0x91, 0xba, 0x43, 0x5c, 0x8a, + 0xf3, 0x89, 0x62, 0xbd, 0x20, 0x07, 0x91, 0xa0, 0x15, 0xaf, 0xc9, 0x45, 0x99, 0xb4, 0xf3, 0xae, 0x33, 0xd7, 0xb9, + 0x26, 0x9e, 0xe4, 0xa8, 0x33, 0x51, 0x4c, 0xee, 0x99, 0x7c, 0xad, 0xdb, 0xb0, 0xda, 0x41, 0x9f, 0x10, 0xe3, 0xc9, + 0x58, 0xa6, 0x1e, 0xd9, 0xd9, 0x78, 0x36, 0xe2, 0x50, 0x01, 0x2d, 0x1d, 0xdc, 0x72, 0xd9, 0xac, 0xf9, 0x19, 0x77, + 0xfc, 0xb0, 0x09, 0x1f, 0xad, 0xe2, 0xda, 0xf4, 0xe9, 0x65, 0x90, 0x06, 0xf3, 0xa1, 0xa4, 0xe0, 0x4a, 0xaa, 0xb1, + 0xef, 0x4d, 0x25, 0xb5, 0x7f, 0xb7, 0x99, 0x9a, 0xb5, 0x58, 0xf1, 0x64, 0x5c, 0x04, 0x91, 0xf9, 0xfa, 0xdd, 0xd4, + 0x8c, 0xa3, 0xdd, 0xb4, 0x20, 0x42, 0x5f, 0xe5, 0x62, 0x64, 0x39, 0xfd, 0xa6, 0x89, 0x37, 0x37, 0x84, 0x3e, 0x62, + 0xfa, 0xb3, 0x8d, 0x39, 0x3e, 0x3b, 0xbc, 0x50, 0x43, 0x0f, 0xda, 0x20, 0x22, 0x35, 0x4e, 0x77, 0xb0, 0x48, 0x64, + 0x4b, 0x78, 0x45, 0xd1, 0x8a, 0xb9, 0xfa, 0xe1, 0x90, 0xb1, 0x44, 0x26, 0x88, 0x34, 0xfa, 0xf1, 0xc3, 0x2e, 0x1d, + 0xb6, 0x1e, 0x86, 0xb1, 0x02, 0x5c, 0xe6, 0x25, 0x25, 0x6f, 0xac, 0xe0, 0xb7, 0x9f, 0x03, 0xd3, 0xbc, 0xdf, 0xde, + 0x35, 0xbd, 0x11, 0x2f, 0xd5, 0x8d, 0xd3, 0x3b, 0x14, 0x4a, 0x42, 0x94, 0xd3, 0xc6, 0xc5, 0xc5, 0x9c, 0x3d, 0x0d, + 0x2c, 0xf2, 0x72, 0xc5, 0xd2, 0x2e, 0x7e, 0x0d, 0xa2, 0x61, 0xc5, 0x3b, 0x08, 0xe9, 0x22, 0xbb, 0xce, 0xf0, 0x00, + 0x8d, 0xea, 0xe1, 0x1e, 0x6d, 0xd1, 0x05, 0x04, 0x99, 0x63, 0xf4, 0x68, 0xa0, 0x04, 0x14, 0x7c, 0xc5, 0x09, 0x74, + 0x95, 0xd6, 0xcc, 0xb3, 0x35, 0x32, 0x63, 0x02, 0x84, 0xd3, 0xfa, 0x93, 0x08, 0x2e, 0x21, 0x73, 0xb8, 0x54, 0xd8, + 0x82, 0x8c, 0x5a, 0x29, 0x4e, 0x46, 0x01, 0x4d, 0x9f, 0x88, 0xe3, 0x17, 0xbd, 0x4b, 0x01, 0x38, 0x7a, 0x2c, 0xac, + 0x24, 0xf0, 0x99, 0xc6, 0x15, 0xb3, 0xcb, 0xa0, 0x39, 0xd0, 0xb8, 0xf6, 0xb5, 0xd5, 0x18, 0x8b, 0x8d, 0xd7, 0xdf, + 0x43, 0x84, 0x0d, 0xf6, 0x94, 0x42, 0xac, 0x48, 0x74, 0x80, 0xac, 0x5c, 0x43, 0x27, 0xef, 0xd9, 0xd3, 0xb1, 0xb5, + 0x5c, 0x41, 0x17, 0x3a, 0x92, 0x70, 0xad, 0xc1, 0x66, 0xff, 0x11, 0xe0, 0x4c, 0x43, 0x5a, 0xcf, 0x0c, 0x2b, 0x72, + 0x99, 0x82, 0x1a, 0xf1, 0xaf, 0x53, 0x07, 0x8b, 0x7a, 0x48, 0x17, 0x71, 0x2a, 0xea, 0x99, 0x56, 0x16, 0xe8, 0x84, + 0x3a, 0x52, 0x43, 0x6c, 0x00, 0x05, 0x6f, 0x94, 0x9e, 0x70, 0xfa, 0xdd, 0xa5, 0xe7, 0xa8, 0x2c, 0xb8, 0x0e, 0xcd, + 0xe2, 0x0f, 0x51, 0x6d, 0x3c, 0xfd, 0xf8, 0x60, 0x06, 0x0f, 0xe2, 0xed, 0x59, 0xc0, 0x87, 0x89, 0xb7, 0x63, 0xe7, + 0x79, 0x67, 0x37, 0x01, 0xc1, 0xac, 0x34, 0x11, 0x92, 0x11, 0xe6, 0xce, 0xbd, 0xc3, 0xd6, 0xf8, 0x2b, 0x76, 0x7f, + 0x29, 0x14, 0x06, 0xdb, 0x91, 0x08, 0xf3, 0xb1, 0x18, 0x45, 0xa8, 0xed, 0xe5, 0xd7, 0x2c, 0x19, 0xc9, 0xef, 0xce, + 0x9b, 0x8b, 0xb8, 0x1d, 0xd8, 0xaa, 0x54, 0xa9, 0x1f, 0x10, 0x55, 0xed, 0xf7, 0xb2, 0x61, 0x9b, 0x85, 0x8f, 0x17, + 0x3d, 0x3b, 0xf1, 0xc1, 0x72, 0x3d, 0xc7, 0x92, 0xdf, 0x3f, 0x43, 0x40, 0xcd, 0x66, 0xfb, 0xd5, 0xe2, 0xa0, 0xcf, + 0xb5, 0xf5, 0x1b, 0xb5, 0x81, 0x7e, 0x42, 0x58, 0xe0, 0xfb, 0x79, 0x8d, 0x5c, 0x3c, 0xca, 0xe6, 0xfa, 0x81, 0xdf, + 0x78, 0xb5, 0xc0, 0x3e, 0xbb, 0x33, 0x37, 0x9c, 0x1b, 0xc2, 0xd0, 0xf6, 0x44, 0xe3, 0xfe, 0x89, 0x49, 0x08, 0xaf, + 0xb3, 0x8a, 0x29, 0x9d, 0xc8, 0xac, 0xf2, 0x4f, 0xfa, 0x9d, 0xbb, 0x9b, 0xf9, 0x08, 0x25, 0xda, 0xdf, 0x80, 0xf3, + 0x72, 0xd5, 0x7e, 0x4d, 0xf2, 0x8c, 0x96, 0x1e, 0xb0, 0xa9, 0xa5, 0x9f, 0xeb, 0x95, 0xea, 0x40, 0xe9, 0xbe, 0x03, + 0x09, 0x30, 0x50, 0x87, 0x19, 0xbf, 0x8f, 0xcd, 0x10, 0x6e, 0x4a, 0x30, 0x06, 0x9e, 0xe9, 0x3f, 0x7c, 0x81, 0x83, + 0xb3, 0x92, 0x81, 0x39, 0xa2, 0xe6, 0x15, 0x41, 0xc0, 0xe7, 0x12, 0x54, 0xc8, 0x6e, 0x05, 0xf2, 0xf3, 0xbc, 0x72, + 0xe4, 0x06, 0x90, 0x5b, 0x21, 0xa8, 0xb8, 0x27, 0xcf, 0x5c, 0x1a, 0xd0, 0x03, 0x50, 0xfe, 0xe1, 0x9c, 0x93, 0x84, + 0xfe, 0x26, 0xa0, 0xa8, 0xd1, 0x49, 0x7f, 0xfe, 0xb5, 0x66, 0x64, 0xf2, 0xe7, 0xb1, 0x5f, 0x79, 0xbc, 0xec, 0xe6, + 0x2d, 0xc8, 0x48, 0x1b, 0xdf, 0x86, 0x19, 0x99, 0x81, 0x8e, 0x55, 0x50, 0x5b, 0xf8, 0x42, 0xaa, 0x55, 0x40, 0xae, + 0x2e, 0x42, 0x8b, 0x14, 0xb7, 0x90, 0xd3, 0x9f, 0xb6, 0xb3, 0x90, 0x7f, 0x9a, 0x01, 0x8e, 0x59, 0xf9, 0xcf, 0xc6, + 0x15, 0x45, 0xf6, 0x10, 0x18, 0xcd, 0x8f, 0x2e, 0x15, 0xd4, 0xb4, 0x72, 0x12, 0x7f, 0x02, 0x72, 0x09, 0x12, 0x30, + 0x3e, 0xbf, 0x51, 0x7b, 0xff, 0x9d, 0xce, 0x52, 0x8b, 0xaa, 0x63, 0xa4, 0x9f, 0xfc, 0x1a, 0xf2, 0x1f, 0xe0, 0x47, + 0x1f, 0x91, 0xd2, 0xd9, 0x3c, 0x5b, 0xfd, 0x89, 0xab, 0xd8, 0x65, 0x41, 0x75, 0x02, 0x2a, 0x48, 0x58, 0x05, 0xb5, + 0x06, 0x23, 0xfb, 0x1f, 0x16, 0xae, 0x46, 0x4c, 0xf3, 0xa7, 0x5b, 0xb4, 0x1a, 0xba, 0x57, 0xa0, 0xea, 0x70, 0x03, + 0x44, 0x0e, 0xdd, 0xa3, 0xea, 0x62, 0xc7, 0x99, 0xfe, 0x5b, 0x09, 0xd8, 0x38, 0x73, 0x82, 0xd3, 0xfd, 0x87, 0x97, + 0x2f, 0xd6, 0xf6, 0xa4, 0x5f, 0x32, 0xc3, 0xf8, 0x92, 0xba, 0x78, 0x70, 0x5f, 0xd3, 0xe2, 0x5b, 0xc2, 0xe4, 0xd3, + 0xfc, 0xf3, 0x49, 0xff, 0xea, 0x4b, 0xfe, 0xfc, 0xe8, 0x17, 0xbe, 0x95, 0xaf, 0x79, 0xf6, 0x4d, 0x5a, 0xa3, 0x1d, + 0xf6, 0x7a, 0x88, 0xbb, 0x37, 0xfd, 0xa1, 0x0e, 0xf9, 0x5a, 0xc5, 0xf8, 0xaf, 0x9e, 0xe9, 0xd3, 0x1f, 0x1e, 0x1f, + 0xdc, 0xa4, 0x77, 0x09, 0x39, 0xcd, 0x94, 0x57, 0xe7, 0xd6, 0xbe, 0xc1, 0x12, 0xb6, 0xf5, 0x26, 0xc1, 0xde, 0xa0, + 0x20, 0xd2, 0x48, 0xbb, 0x13, 0x21, 0x02, 0x95, 0x41, 0xae, 0x60, 0xc8, 0xcd, 0x71, 0xd4, 0xf0, 0x3f, 0x71, 0xc0, + 0x28, 0x97, 0x11, 0x55, 0xa5, 0x8a, 0xd3, 0xd1, 0xc1, 0x4c, 0xc0, 0x29, 0x44, 0x18, 0x21, 0xf9, 0x5e, 0xcd, 0x62, + 0x81, 0xce, 0x24, 0x0d, 0x3e, 0x7e, 0x27, 0x1d, 0x4b, 0x56, 0x5c, 0x5b, 0xe6, 0xeb, 0xfd, 0x27, 0xd9, 0x58, 0xf9, + 0x28, 0x90, 0x59, 0x79, 0x87, 0x02, 0xd5, 0x21, 0x05, 0x93, 0x8b, 0xd4, 0xf9, 0x88, 0x99, 0xf3, 0x91, 0x4a, 0x2f, + 0xd8, 0xaf, 0xe6, 0x06, 0xda, 0x8d, 0x3d, 0x1c, 0xec, 0x5b, 0x65, 0x6c, 0xc2, 0x90, 0xe4, 0x26, 0xbf, 0x46, 0x06, + 0xe5, 0xe4, 0xa6, 0x0d, 0x5b, 0xe0, 0x9b, 0x5f, 0x9f, 0xa1, 0x49, 0x0a, 0x9d, 0x8d, 0x7c, 0xcf, 0xc8, 0x83, 0xeb, + 0xfb, 0xb3, 0xd7, 0xfe, 0xd1, 0x94, 0x45, 0x13, 0xd6, 0x6e, 0xa9, 0x7d, 0x42, 0x28, 0x05, 0x2a, 0x08, 0x10, 0xa6, + 0xc2, 0x1a, 0x58, 0xd6, 0x21, 0x35, 0x87, 0x9a, 0xae, 0x3f, 0x67, 0x90, 0x23, 0xb5, 0xc3, 0xc4, 0xbe, 0x0d, 0x03, + 0x5f, 0x2b, 0xa5, 0xb7, 0x37, 0x50, 0xa5, 0x16, 0xf6, 0x59, 0x64, 0xa8, 0x33, 0x39, 0x57, 0x1c, 0x81, 0xd7, 0x2d, + 0x35, 0x33, 0x51, 0xe8, 0x2c, 0x1b, 0x69, 0x7e, 0x4a, 0x78, 0x45, 0x7f, 0x55, 0x04, 0x4c, 0x74, 0xd0, 0x99, 0xdc, + 0x9a, 0x8a, 0x02, 0x93, 0x90, 0xaa, 0xba, 0x62, 0xeb, 0x78, 0x0a, 0x84, 0x9f, 0xa7, 0x88, 0xed, 0x1a, 0x9f, 0x87, + 0xa2, 0x3c, 0xc9, 0xfb, 0x34, 0x77, 0x7d, 0xe8, 0x9c, 0x6b, 0x03, 0x91, 0x6c, 0x46, 0x74, 0xe1, 0x87, 0xd7, 0x54, + 0xa7, 0xc5, 0x6d, 0x4b, 0xf7, 0x69, 0x5e, 0x7c, 0xd2, 0xac, 0x4b, 0x2e, 0x7e, 0xf4, 0x97, 0x6c, 0x9b, 0x65, 0x08, + 0x45, 0x2a, 0x53, 0xf0, 0x6a, 0x9f, 0x2f, 0x8a, 0xc9, 0xf6, 0x7b, 0x58, 0xf2, 0xc4, 0x97, 0x41, 0x83, 0x89, 0x7e, + 0x71, 0xe7, 0x11, 0x1c, 0xaf, 0xba, 0xc8, 0x6a, 0x0e, 0x9c, 0xeb, 0x7a, 0x36, 0xe6, 0xb2, 0x35, 0x2e, 0x34, 0x42, + 0xa2, 0xae, 0x1a, 0x79, 0xd9, 0xbb, 0x80, 0x0c, 0x23, 0x29, 0x7b, 0x20, 0xc0, 0x9c, 0x5f, 0x5b, 0x46, 0xc3, 0xb3, + 0x90, 0x7c, 0xdd, 0x74, 0xba, 0xa0, 0x21, 0x54, 0x40, 0x83, 0x9f, 0xbf, 0x97, 0xd0, 0x9e, 0x0a, 0x7b, 0x7d, 0xfa, + 0x0b, 0xcf, 0x4c, 0x5a, 0x51, 0xc6, 0x33, 0x7d, 0x16, 0x4b, 0x9a, 0x27, 0x9d, 0xb1, 0x25, 0xcf, 0xfb, 0x58, 0xbe, + 0x4f, 0xe5, 0x58, 0xee, 0xee, 0x69, 0xba, 0xe4, 0x24, 0x35, 0xc7, 0x4a, 0x67, 0x42, 0x6d, 0x7c, 0x99, 0x4f, 0x22, + 0x12, 0x37, 0x78, 0x8a, 0x81, 0x58, 0xcf, 0x7d, 0x3a, 0x18, 0x4e, 0x15, 0xcd, 0xb7, 0xa7, 0xbb, 0x55, 0xe9, 0x9b, + 0x4d, 0xb5, 0x08, 0x71, 0x79, 0xc8, 0x62, 0xe2, 0xc3, 0x40, 0xd9, 0xd9, 0xa6, 0x8d, 0x9b, 0x04, 0x0f, 0xa4, 0xce, + 0xe5, 0xf4, 0x60, 0xb8, 0x88, 0xbd, 0xce, 0x3c, 0xa4, 0x57, 0x5c, 0xdc, 0x05, 0xe2, 0xbc, 0x42, 0x38, 0xa8, 0x57, + 0x8c, 0x6b, 0xf9, 0xa6, 0xd9, 0xbf, 0x9c, 0x4a, 0xe2, 0x92, 0x87, 0x6b, 0xd0, 0x4a, 0x35, 0x6b, 0x9d, 0x62, 0xab, + 0xa3, 0xf5, 0xf0, 0xdf, 0x37, 0x88, 0xac, 0xd8, 0x7c, 0xe1, 0x5b, 0xf9, 0xca, 0x76, 0x41, 0xc8, 0xec, 0x2f, 0xc7, + 0x17, 0x68, 0x3f, 0xcb, 0xd6, 0xda, 0x8b, 0xd3, 0xee, 0x74, 0xe3, 0x2e, 0xaf, 0x0f, 0xdb, 0x60, 0x7c, 0x85, 0x0e, + 0xdb, 0x05, 0x99, 0x7e, 0x62, 0xbd, 0xbe, 0xa7, 0x12, 0xfe, 0xe1, 0xfa, 0x87, 0xdf, 0xf4, 0xb9, 0x3f, 0xe6, 0x2a, + 0xe2, 0x00, 0x99, 0x97, 0xd4, 0x86, 0x71, 0xcd, 0x62, 0x2f, 0xe8, 0x56, 0x42, 0x7d, 0x6e, 0x9f, 0x01, 0x07, 0x37, + 0x37, 0xbd, 0xa7, 0x56, 0x03, 0x80, 0x45, 0x1c, 0x5d, 0xc3, 0x8e, 0x27, 0xe0, 0x13, 0x4a, 0x05, 0x61, 0x8f, 0x63, + 0x54, 0x29, 0x5d, 0xaa, 0x47, 0x1d, 0x3f, 0x0f, 0xa3, 0x3a, 0x10, 0x20, 0xe0, 0xf1, 0x98, 0xc7, 0x82, 0x44, 0x0d, + 0xea, 0x3c, 0x9a, 0xf2, 0x0a, 0x3e, 0x44, 0x02, 0xf6, 0x5d, 0xaf, 0xef, 0xc6, 0x37, 0xc3, 0x2b, 0x02, 0x5b, 0xf8, + 0x25, 0x8d, 0x6c, 0x23, 0x34, 0x8a, 0x47, 0xb9, 0x75, 0x4d, 0xf4, 0x45, 0x6d, 0xc7, 0xcc, 0x0b, 0x41, 0x56, 0x4f, + 0x78, 0x06, 0x0b, 0xe5, 0x82, 0xe0, 0x0b, 0xab, 0x80, 0xfb, 0x73, 0xa2, 0x1f, 0x83, 0x94, 0x1e, 0x8a, 0xe8, 0x88, + 0xd6, 0x91, 0xa9, 0xc1, 0x71, 0x8f, 0x65, 0x89, 0xe1, 0x3c, 0x42, 0xb0, 0xdb, 0x96, 0x35, 0x22, 0xab, 0xd5, 0x08, + 0x7e, 0xf3, 0x52, 0xd1, 0x3a, 0xa4, 0x24, 0x85, 0x0a, 0xd6, 0xd4, 0xf4, 0x5a, 0x10, 0xa9, 0x45, 0xe7, 0x7f, 0x02, + 0xc4, 0x69, 0x4f, 0x34, 0xad, 0xf6, 0x9c, 0x5a, 0x54, 0x1c, 0xda, 0x46, 0xc2, 0xdc, 0xa5, 0xc0, 0x95, 0x38, 0x70, + 0x00, 0xb1, 0xf4, 0xae, 0x48, 0xe4, 0x3d, 0xb4, 0x3f, 0xb8, 0x42, 0x9a, 0x4e, 0x8d, 0x77, 0x72, 0xca, 0x0d, 0x52, + 0x75, 0x61, 0xe4, 0x34, 0x12, 0x93, 0x2a, 0x27, 0x8c, 0x50, 0xc5, 0xed, 0x5a, 0x2d, 0xe1, 0xd4, 0x1b, 0xb7, 0x03, + 0x4f, 0x01, 0xef, 0x92, 0x21, 0x6c, 0xaf, 0x35, 0xe2, 0xcc, 0x18, 0xba, 0x7c, 0xf3, 0x9f, 0xba, 0x9d, 0x53, 0xfb, + 0x65, 0x70, 0x45, 0x87, 0x81, 0xaf, 0xc6, 0xab, 0x30, 0x79, 0x4a, 0x61, 0x5a, 0xfd, 0xa5, 0xeb, 0x33, 0x18, 0xf2, + 0x27, 0xf9, 0x4c, 0x43, 0x22, 0x48, 0xf1, 0x36, 0x7c, 0x78, 0x3f, 0xda, 0x06, 0xe4, 0x21, 0x70, 0x98, 0x8f, 0xc1, + 0xef, 0x44, 0xf6, 0x41, 0x6b, 0x44, 0x77, 0x8a, 0xb0, 0x20, 0x35, 0x77, 0xf8, 0xe8, 0x90, 0x6f, 0x1e, 0xea, 0x91, + 0x5c, 0x5e, 0x83, 0x00, 0x0a, 0x56, 0xd3, 0xc2, 0x9e, 0x3e, 0xb7, 0x79, 0xc6, 0x7b, 0xd0, 0x44, 0x47, 0xe1, 0x10, + 0x13, 0x3c, 0xe7, 0x0c, 0xed, 0x68, 0x27, 0x87, 0xe1, 0x31, 0xf4, 0x4a, 0x61, 0xee, 0x3f, 0x23, 0x72, 0xc3, 0xf9, + 0xb9, 0x9e, 0x31, 0x8d, 0x72, 0x9e, 0xb2, 0xaf, 0x57, 0x8d, 0x1e, 0xff, 0xb1, 0x03, 0x70, 0xff, 0xf4, 0xd7, 0x84, + 0xe4, 0x4f, 0x75, 0x0a, 0xdf, 0x57, 0x96, 0x84, 0xb7, 0x02, 0xff, 0x06, 0xaf, 0x59, 0x62, 0x70, 0x98, 0x82, 0x42, + 0xf9, 0x6b, 0x0b, 0x42, 0x6e, 0x73, 0x72, 0x6d, 0x0e, 0x97, 0xcf, 0x99, 0xe4, 0x0b, 0xb6, 0x09, 0xb5, 0x3e, 0x2b, + 0x70, 0xf0, 0xa6, 0xc9, 0x72, 0x3a, 0x8e, 0x9c, 0xf9, 0xad, 0xd8, 0x5c, 0x37, 0x26, 0x79, 0x14, 0x29, 0xfa, 0xcd, + 0xf4, 0x46, 0xde, 0x78, 0xb3, 0x10, 0x6d, 0x87, 0x5e, 0x9a, 0xd6, 0x8f, 0x2f, 0x08, 0x3f, 0x0d, 0xcb, 0x89, 0xd9, + 0x1f, 0x7c, 0x2f, 0xb0, 0xba, 0xc4, 0xc5, 0x80, 0x0c, 0xc3, 0xee, 0x58, 0xb0, 0x0e, 0x57, 0xd7, 0x68, 0xca, 0xb8, + 0x1c, 0xa4, 0x8a, 0x96, 0xee, 0x08, 0xa1, 0x9b, 0xb8, 0x28, 0xed, 0x4c, 0xd9, 0x7b, 0xf9, 0x3b, 0xb4, 0xfa, 0xb5, + 0x2a, 0xde, 0x5d, 0x12, 0x3e, 0xf8, 0xee, 0x5d, 0xd0, 0xdf, 0x74, 0xc8, 0xc6, 0xba, 0x5f, 0x3e, 0xbe, 0x54, 0x4d, + 0x16, 0x46, 0x83, 0x99, 0x4f, 0x79, 0x73, 0x76, 0x57, 0x65, 0x94, 0xd4, 0x35, 0x14, 0x46, 0x62, 0x8f, 0x1c, 0xe7, + 0xbd, 0x33, 0x59, 0xd7, 0xbb, 0x8e, 0x55, 0xe9, 0xf2, 0xb3, 0x04, 0x8b, 0xd6, 0x72, 0xef, 0xfe, 0x2c, 0xd5, 0xa7, + 0x50, 0x03, 0x69, 0xb3, 0x81, 0x0e, 0xdd, 0x46, 0x9b, 0x68, 0x9c, 0x49, 0xa0, 0xb4, 0x87, 0x2b, 0x2f, 0x6a, 0xfa, + 0x2c, 0x26, 0xd0, 0xba, 0x9d, 0x2d, 0x74, 0xb6, 0x0b, 0x4a, 0x83, 0xdb, 0x3f, 0xee, 0x76, 0xe9, 0xcc, 0xe0, 0xe3, + 0xfd, 0x83, 0x0c, 0xcb, 0xff, 0x1b, 0x55, 0xec, 0x9e, 0x1c, 0x80, 0x86, 0x35, 0x6f, 0x9b, 0x44, 0x44, 0x48, 0x58, + 0xdc, 0x7c, 0x72, 0xec, 0xfb, 0xc6, 0x97, 0xe8, 0xb9, 0xa1, 0x27, 0xe3, 0xc4, 0xf5, 0x52, 0x9d, 0xb2, 0x1e, 0x89, + 0x01, 0x7f, 0xd2, 0x39, 0x90, 0x68, 0x6b, 0x9a, 0xdd, 0x0e, 0xca, 0x81, 0xdd, 0x9b, 0x03, 0xeb, 0x8f, 0xf9, 0x06, + 0x23, 0x07, 0x2b, 0x9b, 0x3f, 0xb5, 0xb9, 0xed, 0xb4, 0x0e, 0x9f, 0x4d, 0xc6, 0xd2, 0xe3, 0xe1, 0x2b, 0xab, 0x23, + 0xb4, 0x35, 0x92, 0x15, 0x83, 0x6a, 0x6f, 0xf7, 0x63, 0x0f, 0x22, 0x7e, 0xa6, 0xee, 0xde, 0x45, 0xdd, 0xa1, 0xa5, + 0x67, 0xf6, 0xf6, 0xe0, 0xb1, 0x7f, 0x60, 0x8d, 0x43, 0xdd, 0xcb, 0x05, 0x08, 0x4b, 0xdc, 0x51, 0xd6, 0x56, 0x71, + 0x71, 0xfb, 0xe7, 0xd7, 0x0f, 0x9a, 0x83, 0x40, 0xe5, 0x70, 0x30, 0xd1, 0x8b, 0x11, 0xeb, 0xc8, 0xb1, 0x63, 0x18, + 0x23, 0x76, 0x73, 0x80, 0x94, 0x11, 0x23, 0xcd, 0x29, 0xdf, 0x07, 0x63, 0x5c, 0xf4, 0x46, 0xed, 0xc2, 0x86, 0x79, + 0x80, 0x15, 0xee, 0xa4, 0xaa, 0xc3, 0xc2, 0xc4, 0xfc, 0xba, 0xb5, 0x49, 0x72, 0xde, 0x91, 0xf5, 0xa9, 0xd9, 0xbb, + 0x12, 0x84, 0x3e, 0x1f, 0xfe, 0x8d, 0x8a, 0x78, 0xae, 0xb3, 0x87, 0x60, 0x02, 0x7e, 0xac, 0x3a, 0xec, 0x6f, 0xc1, + 0xa7, 0x0d, 0x27, 0xea, 0xe8, 0x93, 0xd1, 0x59, 0xe1, 0x80, 0x5d, 0x6b, 0xfa, 0x50, 0xc6, 0x43, 0x8f, 0x59, 0x18, + 0x2b, 0xd3, 0x5b, 0x15, 0x94, 0x0d, 0x9b, 0xa9, 0x2e, 0xa9, 0x06, 0xaa, 0x4c, 0x26, 0x99, 0x4c, 0xd9, 0x42, 0xce, + 0x00, 0xb6, 0xf7, 0x41, 0x72, 0x85, 0x88, 0x7a, 0x5f, 0x5a, 0x8f, 0xcc, 0x22, 0xae, 0x91, 0x23, 0xda, 0x63, 0x50, + 0x8b, 0x88, 0x77, 0x6a, 0x75, 0x94, 0xe4, 0xa3, 0x2f, 0x1f, 0x82, 0xd0, 0xb5, 0xa4, 0x3f, 0x9b, 0xa1, 0x84, 0x65, + 0x46, 0x2e, 0xdb, 0x4f, 0xdc, 0xbd, 0x3f, 0x8d, 0x7f, 0x9a, 0x08, 0x6d, 0x97, 0x67, 0xeb, 0xc1, 0xc8, 0xb5, 0x34, + 0x95, 0xd7, 0xb8, 0xa5, 0xc6, 0xb8, 0xe0, 0xa7, 0x38, 0xd2, 0xe6, 0x6b, 0xcd, 0xd3, 0x43, 0xdd, 0x7a, 0x1e, 0xb5, + 0x0f, 0xb2, 0xb6, 0x0e, 0xec, 0xc5, 0x42, 0x7b, 0x0a, 0x7b, 0xe7, 0xf8, 0xd0, 0xfd, 0xc5, 0xad, 0xcb, 0x4d, 0x95, + 0x8f, 0xce, 0x5c, 0x48, 0x64, 0x8e, 0x8a, 0xb7, 0x38, 0xc8, 0x07, 0xa0, 0x22, 0x92, 0xe1, 0xbd, 0x5b, 0x1e, 0x36, + 0xcf, 0xba, 0x47, 0x3d, 0xf6, 0xa0, 0x8c, 0x84, 0x8f, 0x77, 0x08, 0x89, 0x52, 0x21, 0xf6, 0xfc, 0x67, 0x92, 0x72, + 0x16, 0x0d, 0x95, 0xb7, 0x65, 0xe5, 0xf4, 0xf5, 0x3c, 0x92, 0x6a, 0x19, 0x0f, 0x78, 0x4f, 0x6e, 0xb6, 0x96, 0x13, + 0xc5, 0xad, 0xbe, 0xda, 0x5c, 0x82, 0xa0, 0x6c, 0xf4, 0x86, 0xdb, 0xb7, 0x11, 0x3b, 0x4e, 0xa0, 0x6d, 0xdb, 0x9f, + 0x5c, 0x2c, 0x45, 0xa9, 0x70, 0xc2, 0x58, 0x37, 0x39, 0x8a, 0xe6, 0x10, 0x86, 0x37, 0x6b, 0xab, 0x09, 0x1f, 0x70, + 0xc3, 0x31, 0x6f, 0x6f, 0x29, 0x87, 0x55, 0x2d, 0x9c, 0xa3, 0x48, 0xc6, 0xc4, 0xde, 0x2e, 0xa3, 0xdb, 0x5b, 0x85, + 0xfe, 0x13, 0xb2, 0xeb, 0xac, 0x56, 0xde, 0x04, 0x5f, 0x29, 0x88, 0x6c, 0xee, 0xc7, 0x67, 0xc6, 0x01, 0xd2, 0x0d, + 0xf0, 0xd7, 0x0a, 0x92, 0x55, 0x9e, 0xa8, 0xbc, 0x0a, 0x4c, 0xd3, 0x90, 0x82, 0xe1, 0x53, 0x7a, 0x0f, 0x96, 0xbc, + 0xe6, 0xcb, 0x66, 0xd7, 0x37, 0x17, 0x3f, 0xac, 0xf5, 0x10, 0x2f, 0x3b, 0xbd, 0xb5, 0x2a, 0x9c, 0xe0, 0x31, 0x49, + 0xfc, 0xba, 0xf4, 0xb3, 0xfd, 0x60, 0xe3, 0x96, 0x42, 0xed, 0x07, 0x9c, 0xd9, 0xba, 0xe7, 0x30, 0xb3, 0x49, 0x9f, + 0x01, 0x12, 0x16, 0x68, 0xdd, 0xc7, 0x22, 0x53, 0x60, 0xab, 0x01, 0x6e, 0x00, 0x23, 0xb6, 0x7d, 0xc8, 0x1e, 0xbd, + 0x29, 0x92, 0x2d, 0xe4, 0x7b, 0x3a, 0x72, 0xfb, 0x53, 0x4c, 0xef, 0x17, 0x75, 0x20, 0x9a, 0xaf, 0x03, 0x6e, 0xeb, + 0x81, 0x77, 0x1c, 0xa4, 0x48, 0x5c, 0x21, 0xa6, 0x49, 0xf7, 0x15, 0x5a, 0xb5, 0xba, 0x9b, 0x5c, 0xf6, 0xe7, 0x8e, + 0x93, 0xb5, 0xde, 0x86, 0xbb, 0xd8, 0xcf, 0xaa, 0x1d, 0xd2, 0x51, 0x03, 0xf8, 0xd2, 0xaf, 0x0c, 0x74, 0x7a, 0x9a, + 0xc2, 0x77, 0x25, 0x96, 0x4d, 0x08, 0x98, 0x3b, 0x28, 0xec, 0x2c, 0x90, 0x04, 0x2b, 0x9c, 0x38, 0x96, 0x77, 0x58, + 0x93, 0x17, 0xfa, 0x7a, 0x1c, 0x19, 0x18, 0x98, 0xb2, 0x27, 0x11, 0x61, 0xef, 0x2c, 0x52, 0x34, 0x6b, 0x19, 0xde, + 0x32, 0xd1, 0x93, 0x0f}; // Backwards compatibility alias #define INDEX_GZ INDEX_BR From 37a0cec53dc0e4e9d9c0c5848e220b6d8480964d Mon Sep 17 00:00:00 2001 From: Szpadel <piotrekrogowski@gmail.com> Date: Wed, 25 Feb 2026 17:12:03 +0100 Subject: [PATCH 0917/2030] [ac_dimmer] Use a shared ESP32 GPTimer for multiple dimmers (#13523) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/ac_dimmer/ac_dimmer.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/esphome/components/ac_dimmer/ac_dimmer.cpp b/esphome/components/ac_dimmer/ac_dimmer.cpp index 1e850a18fe..f731a8c753 100644 --- a/esphome/components/ac_dimmer/ac_dimmer.cpp +++ b/esphome/components/ac_dimmer/ac_dimmer.cpp @@ -199,12 +199,19 @@ void AcDimmer::setup() { setTimer1Callback(&timer_interrupt); #endif #ifdef USE_ESP32 - dimmer_timer = timer_begin(TIMER_FREQUENCY_HZ); - timer_attach_interrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr); - // For ESP32, we can't use dynamic interval calculation because the timerX functions - // are not callable from ISR (placed in flash storage). - // Here we just use an interrupt firing every 50 µs. - timer_alarm(dimmer_timer, TIMER_INTERVAL_US, true, 0); + if (dimmer_timer == nullptr) { + dimmer_timer = timer_begin(TIMER_FREQUENCY_HZ); + if (dimmer_timer == nullptr) { + ESP_LOGE(TAG, "Failed to create GPTimer for AC dimmer"); + this->mark_failed(); + return; + } + timer_attach_interrupt(dimmer_timer, &AcDimmerDataStore::s_timer_intr); + // For ESP32, we can't use dynamic interval calculation because the timerX functions + // are not callable from ISR (placed in flash storage). + // Here we just use an interrupt firing every 50 µs. + timer_alarm(dimmer_timer, TIMER_INTERVAL_US, true, 0); + } #endif } From ede8235aaee8467be33dd33fd8c25c39957063e3 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Wed, 25 Feb 2026 17:46:28 +0100 Subject: [PATCH 0918/2030] [core] more accurate check for leap year and valid day_of_month (#14197) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/core/time.cpp | 2 +- esphome/core/time.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 554431c631..1aea18ac8d 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -8,7 +8,7 @@ namespace esphome { uint8_t days_in_month(uint8_t month, uint16_t year) { static const uint8_t DAYS_IN_MONTH[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - if (month == 2 && (year % 4 == 0)) + if (month == 2 && (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0)) return 29; return DAYS_IN_MONTH[month]; } diff --git a/esphome/core/time.h b/esphome/core/time.h index 87ebb5c221..d9ce86131c 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -70,14 +70,14 @@ struct ESPTime { /// @copydoc strftime(const std::string &format) std::string strftime(const char *format); - /// Check if this ESPTime is valid (all fields in range and year is greater than 2018) + /// Check if this ESPTime is valid (all fields in range and year is greater than or equal to 2019) bool is_valid() const { return this->year >= 2019 && this->fields_in_range(); } /// Check if all time fields of this ESPTime are in range. bool fields_in_range() const { return this->second < 61 && this->minute < 60 && this->hour < 24 && this->day_of_week > 0 && - this->day_of_week < 8 && this->day_of_month > 0 && this->day_of_month < 32 && this->day_of_year > 0 && - this->day_of_year < 367 && this->month > 0 && this->month < 13; + this->day_of_week < 8 && this->day_of_year > 0 && this->day_of_year < 367 && this->month > 0 && + this->month < 13 && this->day_of_month > 0 && this->day_of_month <= days_in_month(this->month, this->year); } /** Convert a string to ESPTime struct as specified by the format argument. From 8bb577de644243c3822305d3720ddaec8b9864c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 12:23:13 -0600 Subject: [PATCH 0919/2030] [api] Split ProtoVarInt::parse into 32-bit and 64-bit phases (#14039) --- esphome/components/api/api_pb2.h | 1 - esphome/components/api/api_pb2_defines.h | 12 ++ esphome/components/api/proto.cpp | 17 +++ esphome/components/api/proto.h | 70 ++++++---- esphome/core/defines.h | 1 + script/api_protobuf/api_protobuf.py | 65 +++++++++- .../fixtures/varint_five_byte_device_id.yaml | 47 +++++++ .../test_varint_five_byte_device_id.py | 120 ++++++++++++++++++ 8 files changed, 301 insertions(+), 32 deletions(-) create mode 100644 esphome/components/api/api_pb2_defines.h create mode 100644 tests/integration/fixtures/varint_five_byte_device_id.yaml create mode 100644 tests/integration/test_varint_five_byte_device_id.py diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index c90873d993..c2675cefe4 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -2,7 +2,6 @@ // See script/api_protobuf/api_protobuf.py #pragma once -#include "esphome/core/defines.h" #include "esphome/core/string_ref.h" #include "proto.h" diff --git a/esphome/components/api/api_pb2_defines.h b/esphome/components/api/api_pb2_defines.h new file mode 100644 index 0000000000..8ebd60fb5d --- /dev/null +++ b/esphome/components/api/api_pb2_defines.h @@ -0,0 +1,12 @@ +// This file was automatically generated with a tool. +// See script/api_protobuf/api_protobuf.py +#pragma once + +#include "esphome/core/defines.h" +#ifdef USE_BLUETOOTH_PROXY +#ifndef USE_API_VARINT64 +#define USE_API_VARINT64 +#endif +#endif + +namespace esphome::api {} // namespace esphome::api diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 73a3bab12a..a252907fd7 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -7,6 +7,23 @@ namespace esphome::api { static const char *const TAG = "api.proto"; +#ifdef USE_API_VARINT64 +optional<ProtoVarInt> ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, + uint32_t result32) { + uint64_t result64 = result32; + uint32_t limit = std::min(len, uint32_t(10)); + for (uint32_t i = 4; i < limit; i++) { + uint8_t val = buffer[i]; + result64 |= uint64_t(val & 0x7F) << (i * 7); + if ((val & 0x80) == 0) { + *consumed = i + 1; + return ProtoVarInt(result64); + } + } + return {}; +} +#endif + uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id) { uint32_t count = 0; const uint8_t *ptr = buffer; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 4522fc9665..c34f7744e6 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -1,5 +1,6 @@ #pragma once +#include "api_pb2_defines.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -110,59 +111,78 @@ class ProtoVarInt { #endif if (len == 0) return {}; - - // Most common case: single-byte varint (values 0-127) + // Fast path: single-byte varints (0-127) are the most common case + // (booleans, small enums, field tags). Avoid loop overhead entirely. if ((buffer[0] & 0x80) == 0) { *consumed = 1; return ProtoVarInt(buffer[0]); } - - // General case for multi-byte varints - // Since we know buffer[0]'s high bit is set, initialize with its value - uint64_t result = buffer[0] & 0x7F; - uint8_t bitpos = 7; - - // A 64-bit varint is at most 10 bytes (ceil(64/7)). Reject overlong encodings - // to avoid undefined behavior from shifting uint64_t by >= 64 bits. - uint32_t max_len = std::min(len, uint32_t(10)); - - // Start from the second byte since we've already processed the first - for (uint32_t i = 1; i < max_len; i++) { + // 32-bit phase: process remaining bytes with native 32-bit shifts. + // Without USE_API_VARINT64: cover bytes 1-4 (shifts 7, 14, 21, 28) — the uint32_t + // shift at byte 4 (shift by 28) may lose bits 32-34, but those are always zero for valid uint32 values. + // With USE_API_VARINT64: cover bytes 1-3 (shifts 7, 14, 21) so parse_wide handles + // byte 4+ with full 64-bit arithmetic (avoids truncating values > UINT32_MAX). + uint32_t result32 = buffer[0] & 0x7F; +#ifdef USE_API_VARINT64 + uint32_t limit = std::min(len, uint32_t(4)); +#else + uint32_t limit = std::min(len, uint32_t(5)); +#endif + for (uint32_t i = 1; i < limit; i++) { uint8_t val = buffer[i]; - result |= uint64_t(val & 0x7F) << uint64_t(bitpos); - bitpos += 7; + result32 |= uint32_t(val & 0x7F) << (i * 7); if ((val & 0x80) == 0) { *consumed = i + 1; - return ProtoVarInt(result); + return ProtoVarInt(result32); } } - - return {}; // Incomplete or invalid varint + // 64-bit phase for remaining bytes (BLE addresses etc.) +#ifdef USE_API_VARINT64 + return parse_wide(buffer, len, consumed, result32); +#else + return {}; +#endif } +#ifdef USE_API_VARINT64 + protected: + /// Continue parsing varint bytes 4-9 with 64-bit arithmetic. + /// Separated to keep 64-bit shift code (__ashldi3 on 32-bit platforms) out of the common path. + static optional<ProtoVarInt> parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, uint32_t result32) + __attribute__((noinline)); + + public: +#endif + constexpr uint16_t as_uint16() const { return this->value_; } constexpr uint32_t as_uint32() const { return this->value_; } - constexpr uint64_t as_uint64() const { return this->value_; } constexpr bool as_bool() const { return this->value_; } constexpr int32_t as_int32() const { // Not ZigZag encoded - return static_cast<int32_t>(this->as_int64()); - } - constexpr int64_t as_int64() const { - // Not ZigZag encoded - return static_cast<int64_t>(this->value_); + return static_cast<int32_t>(this->value_); } constexpr int32_t as_sint32() const { // with ZigZag encoding return decode_zigzag32(static_cast<uint32_t>(this->value_)); } +#ifdef USE_API_VARINT64 + constexpr uint64_t as_uint64() const { return this->value_; } + constexpr int64_t as_int64() const { + // Not ZigZag encoded + return static_cast<int64_t>(this->value_); + } constexpr int64_t as_sint64() const { // with ZigZag encoding return decode_zigzag64(this->value_); } +#endif protected: +#ifdef USE_API_VARINT64 uint64_t value_; +#else + uint32_t value_; +#endif }; // Forward declarations for decode_to_message, encode_message and encode_packed_sint32 diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a1e3d1707f..673aa246fe 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -144,6 +144,7 @@ #define USE_API_HOMEASSISTANT_SERVICES #define USE_API_HOMEASSISTANT_STATES #define USE_API_NOISE +#define USE_API_VARINT64 #define USE_API_PLAINTEXT #define USE_API_USER_DEFINED_ACTIONS #define USE_API_CUSTOM_SERVICES diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index cc881caa5c..350947a8d6 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1913,6 +1913,37 @@ def build_type_usage_map( ) +def get_varint64_ifdef( + file_desc: descriptor.FileDescriptorProto, + message_ifdef_map: dict[str, str | None], +) -> tuple[bool, str | None]: + """Check if 64-bit varint fields exist and get their common ifdef guard. + + Returns: + (has_varint64, ifdef_guard) - has_varint64 is True if any fields exist, + ifdef_guard is the common guard or None if unconditional. + """ + varint64_types = { + FieldDescriptorProto.TYPE_INT64, + FieldDescriptorProto.TYPE_UINT64, + FieldDescriptorProto.TYPE_SINT64, + } + ifdefs: set[str | None] = { + message_ifdef_map.get(msg.name) + for msg in file_desc.message_type + if not msg.options.deprecated + for field in msg.field + if not field.options.deprecated and field.type in varint64_types + } + if not ifdefs: + return False, None + if None in ifdefs: + # At least one 64-bit varint field is unconditional, so the guard must be unconditional. + return True, None + ifdefs.discard(None) + return True, ifdefs.pop() if len(ifdefs) == 1 else None + + def build_enum_type(desc, enum_ifdef_map) -> tuple[str, str, str]: """Builds the enum type. @@ -2567,11 +2598,38 @@ def main() -> None: file = d.file[0] + # Build dynamic ifdef mappings early so we can emit USE_API_VARINT64 before includes + enum_ifdef_map, message_ifdef_map, message_source_map, used_messages = ( + build_type_usage_map(file) + ) + + # Find the ifdef guard for 64-bit varint fields (int64/uint64/sint64). + # Generated into api_pb2_defines.h so proto.h can include it, ensuring + # consistent ProtoVarInt layout across all translation units. + has_varint64, varint64_guard = get_varint64_ifdef(file, message_ifdef_map) + + # Generate api_pb2_defines.h — included by proto.h to ensure all translation + # units see USE_API_VARINT64 consistently (avoids ODR violations in ProtoVarInt). + defines_content = FILE_HEADER + defines_content += "#pragma once\n\n" + defines_content += '#include "esphome/core/defines.h"\n' + if has_varint64: + lines = [ + "#ifndef USE_API_VARINT64", + "#define USE_API_VARINT64", + "#endif", + ] + defines_content += "\n".join(wrap_with_ifdef(lines, varint64_guard)) + defines_content += "\n" + defines_content += "\nnamespace esphome::api {} // namespace esphome::api\n" + + with open(root / "api_pb2_defines.h", "w", encoding="utf-8") as f: + f.write(defines_content) + content = FILE_HEADER content += """\ #pragma once -#include "esphome/core/defines.h" #include "esphome/core/string_ref.h" #include "proto.h" @@ -2702,11 +2760,6 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint content += "namespace enums {\n\n" - # Build dynamic ifdef mappings for both enums and messages - enum_ifdef_map, message_ifdef_map, message_source_map, used_messages = ( - build_type_usage_map(file) - ) - # Simple grouping of enums by ifdef current_ifdef = None diff --git a/tests/integration/fixtures/varint_five_byte_device_id.yaml b/tests/integration/fixtures/varint_five_byte_device_id.yaml new file mode 100644 index 0000000000..08259869ca --- /dev/null +++ b/tests/integration/fixtures/varint_five_byte_device_id.yaml @@ -0,0 +1,47 @@ +esphome: + name: varint-5byte-test + # Define areas and devices - device_ids will be FNV hashes > 2^28, + # requiring 5-byte varint encoding that exercises the 32-bit parse boundary. + areas: + - id: test_area + name: Test Area + devices: + - id: sub_device_one + name: Sub Device One + area_id: test_area + - id: sub_device_two + name: Sub Device Two + area_id: test_area + +host: +api: +logger: + +# Switches on sub-devices so we can send commands with large device_id varints +switch: + - platform: template + name: Device Switch + device_id: sub_device_one + id: device_switch_one + optimistic: true + turn_on_action: + - logger.log: "Switch one on" + turn_off_action: + - logger.log: "Switch one off" + + - platform: template + name: Device Switch + device_id: sub_device_two + id: device_switch_two + optimistic: true + turn_on_action: + - logger.log: "Switch two on" + turn_off_action: + - logger.log: "Switch two off" + +sensor: + - platform: template + name: Device Sensor + device_id: sub_device_one + lambda: return 42.0; + update_interval: 0.1s diff --git a/tests/integration/test_varint_five_byte_device_id.py b/tests/integration/test_varint_five_byte_device_id.py new file mode 100644 index 0000000000..d34c2f03d6 --- /dev/null +++ b/tests/integration/test_varint_five_byte_device_id.py @@ -0,0 +1,120 @@ +"""Integration test for 5-byte varint parsing of device_id fields. + +Device IDs are FNV hashes (uint32) that frequently exceed 2^28 (268435456), +requiring 5 varint bytes. This test verifies that: +1. The firmware correctly decodes 5-byte varint device_id in incoming commands +2. The firmware correctly encodes large device_id values in state responses +3. Switch commands with large device_id reach the correct entity +""" + +from __future__ import annotations + +import asyncio + +from aioesphomeapi import EntityState, SwitchInfo, SwitchState +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_varint_five_byte_device_id( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that device_id values requiring 5-byte varints parse correctly.""" + async with run_compiled(yaml_config), api_client_connected() as client: + device_info = await client.device_info() + devices = device_info.devices + assert len(devices) >= 2, f"Expected at least 2 devices, got {len(devices)}" + + # Verify at least one device_id exceeds the 4-byte varint boundary (2^28) + large_ids = [d for d in devices if d.device_id >= (1 << 28)] + assert len(large_ids) > 0, ( + "Expected at least one device_id >= 2^28 to exercise 5-byte varint path. " + f"Got device_ids: {[d.device_id for d in devices]}" + ) + + # Get entities + all_entities, _ = await client.list_entities_services() + switch_entities = [e for e in all_entities if isinstance(e, SwitchInfo)] + + # Find switches named "Device Switch" — one per sub-device + device_switches = [e for e in switch_entities if e.name == "Device Switch"] + assert len(device_switches) == 2, ( + f"Expected 2 'Device Switch' entities, got {len(device_switches)}" + ) + + # Verify switches have different device_ids matching the sub-devices + switch_device_ids = {s.device_id for s in device_switches} + assert len(switch_device_ids) == 2, "Switches should have different device_ids" + + # Subscribe to states and wait for initial states + loop = asyncio.get_running_loop() + states: dict[tuple[int, int], EntityState] = {} + switch_futures: dict[tuple[int, int], asyncio.Future[EntityState]] = {} + initial_done: asyncio.Future[bool] = loop.create_future() + + def on_state(state: EntityState) -> None: + key = (state.device_id, state.key) + states[key] = state + + if len(states) >= 3 and not initial_done.done(): + initial_done.set_result(True) + + if initial_done.done() and key in switch_futures: + fut = switch_futures[key] + if not fut.done() and isinstance(state, SwitchState): + fut.set_result(state) + + client.subscribe_states(on_state) + + try: + await asyncio.wait_for(initial_done, timeout=10.0) + except TimeoutError: + pytest.fail( + f"Timed out waiting for initial states. Got {len(states)} states" + ) + + # Verify state responses contain correct large device_id values + for device in devices: + device_states = [ + s for (did, _), s in states.items() if did == device.device_id + ] + assert len(device_states) > 0, ( + f"No states received for device '{device.name}' " + f"(device_id={device.device_id})" + ) + + # Test switch commands with large device_id varints — + # this is the critical path: the client encodes device_id as a varint + # in the SwitchCommandRequest, and the firmware must decode it correctly. + for switch in device_switches: + state_key = (switch.device_id, switch.key) + + # Turn on + switch_futures[state_key] = loop.create_future() + client.switch_command(switch.key, True, device_id=switch.device_id) + try: + await asyncio.wait_for(switch_futures[state_key], timeout=2.0) + except TimeoutError: + pytest.fail( + f"Timed out waiting for switch ON state " + f"(device_id={switch.device_id}, key={switch.key}). " + f"This likely means the firmware failed to decode the " + f"5-byte varint device_id in SwitchCommandRequest." + ) + assert states[state_key].state is True + + # Turn off + switch_futures[state_key] = loop.create_future() + client.switch_command(switch.key, False, device_id=switch.device_id) + try: + await asyncio.wait_for(switch_futures[state_key], timeout=2.0) + except TimeoutError: + pytest.fail( + f"Timed out waiting for switch OFF state " + f"(device_id={switch.device_id}, key={switch.key})" + ) + assert states[state_key].state is False From 62da60df477d3efcf9fcb80de6978b7ff44749f9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:19:20 -0500 Subject: [PATCH 0920/2030] [ld2420] Fix sizeof vs value bug in register memcpy (#14286) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/ld2420/ld2420.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index cf78a1a460..b653f4ae88 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -590,7 +590,7 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { for (uint16_t index = 0; index < (CMD_REG_DATA_REPLY_SIZE * // NOLINT ((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_REG_DATA_REPLY_SIZE)); index += CMD_REG_DATA_REPLY_SIZE) { - memcpy(&this->cmd_reply_.data[reg_element], &buffer[data_pos + index], sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&this->cmd_reply_.data[reg_element], &buffer[data_pos + index], CMD_REG_DATA_REPLY_SIZE); byteswap(this->cmd_reply_.data[reg_element]); reg_element++; } @@ -729,9 +729,9 @@ void LD2420Component::set_reg_value(uint16_t reg, uint16_t value) { cmd_frame.data_length = 0; cmd_frame.header = CMD_FRAME_HEADER; cmd_frame.command = CMD_WRITE_REGISTER; - memcpy(&cmd_frame.data[cmd_frame.data_length], ®, sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&cmd_frame.data[cmd_frame.data_length], ®, CMD_REG_DATA_REPLY_SIZE); cmd_frame.data_length += 2; - memcpy(&cmd_frame.data[cmd_frame.data_length], &value, sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&cmd_frame.data[cmd_frame.data_length], &value, CMD_REG_DATA_REPLY_SIZE); cmd_frame.data_length += 2; cmd_frame.footer = CMD_FRAME_FOOTER; ESP_LOGV(TAG, "Sending write register %4X command: %2X data = %4X", reg, cmd_frame.command, value); From e601162cdd0500581cb838b8fd588fca3e3bba8e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:21:00 -0500 Subject: [PATCH 0921/2030] [lcd_base] Fix millis() truncation to uint8_t (#14289) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/lcd_base/lcd_display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/lcd_base/lcd_display.cpp b/esphome/components/lcd_base/lcd_display.cpp index d3434cce10..cd08a739eb 100644 --- a/esphome/components/lcd_base/lcd_display.cpp +++ b/esphome/components/lcd_base/lcd_display.cpp @@ -45,7 +45,7 @@ void LCDDisplay::setup() { // TODO dotsize // Commands can only be sent 40ms after boot-up, so let's wait if we're close - const uint8_t now = millis(); + const uint32_t now = millis(); if (now < 40) delay(40u - now); From df77213f2cb21a31e62ff0a9570d7af73e8f431b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:27:00 -0500 Subject: [PATCH 0922/2030] [shelly_dimmer] Fix millis overflow in ACK timeout check (#14288) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/shelly_dimmer/stm32flash.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/shelly_dimmer/stm32flash.cpp b/esphome/components/shelly_dimmer/stm32flash.cpp index b052c0cee9..a1a933bcab 100644 --- a/esphome/components/shelly_dimmer/stm32flash.cpp +++ b/esphome/components/shelly_dimmer/stm32flash.cpp @@ -149,7 +149,7 @@ stm32_err_t stm32_get_ack_timeout(const stm32_unique_ptr &stm, uint32_t timeout) do { yield(); if (!stream->available()) { - if (millis() < start_time + timeout) + if (millis() - start_time < timeout) continue; ESP_LOGD(TAG, "Failed to read ACK timeout=%i", timeout); return STM32_ERR_UNKNOWN; @@ -212,7 +212,7 @@ stm32_err_t stm32_resync(const stm32_unique_ptr &stm) { static_assert(sizeof(buf) == BUFFER_SIZE, "Buf expected to be 2 bytes"); uint8_t ack; - while (t1 < t0 + STM32_RESYNC_TIMEOUT) { + while (t1 - t0 < STM32_RESYNC_TIMEOUT) { stream->write_array(buf, BUFFER_SIZE); stream->flush(); if (!stream->read_array(&ack, 1)) { From 3f558f63d8fec863d51e05e44a8dcee406d278c1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:28:47 -0500 Subject: [PATCH 0923/2030] [bl0942] Fix millis overflow in packet timeout check (#14285) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/bl0942/bl0942.cpp | 8 ++++---- esphome/components/bl0942/bl0942.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index b408c5549c..16ad33141d 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -52,12 +52,12 @@ void BL0942::loop() { return; } if (avail < sizeof(buffer)) { - if (!this->rx_start_) { + if (!this->rx_start_.has_value()) { this->rx_start_ = millis(); - } else if (millis() > this->rx_start_ + PKT_TIMEOUT_MS) { + } else if (millis() - *this->rx_start_ > PKT_TIMEOUT_MS) { ESP_LOGW(TAG, "Junk on wire. Throwing away partial message (%zu bytes)", avail); this->read_array((uint8_t *) &buffer, avail); - this->rx_start_ = 0; + this->rx_start_.reset(); } return; } @@ -67,7 +67,7 @@ void BL0942::loop() { this->received_package_(&buffer); } } - this->rx_start_ = 0; + this->rx_start_.reset(); } bool BL0942::validate_checksum_(DataPacket *data) { diff --git a/esphome/components/bl0942/bl0942.h b/esphome/components/bl0942/bl0942.h index 10b29a72c6..3c013f86e7 100644 --- a/esphome/components/bl0942/bl0942.h +++ b/esphome/components/bl0942/bl0942.h @@ -140,7 +140,7 @@ class BL0942 : public PollingComponent, public uart::UARTDevice { uint8_t address_ = 0; bool reset_ = false; LineFrequency line_freq_ = LINE_FREQUENCY_50HZ; - uint32_t rx_start_ = 0; + optional<uint32_t> rx_start_{}; uint32_t prev_cf_cnt_ = 0; bool validate_checksum_(DataPacket *data); From d1a636a5c3227d08eed01f704e26f172394eba64 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:34:38 -0500 Subject: [PATCH 0924/2030] [rtttl] Fix speaker playback bugs (#14280) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 21 +++++++++++---------- esphome/components/rtttl/rtttl.h | 6 +++--- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 6e86405b74..ab95067f45 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -139,9 +139,10 @@ void Rtttl::loop() { x++; } if (x > 0) { - int send = this->speaker_->play((uint8_t *) (&sample), x * 2); - if (send != x * 4) { - this->samples_sent_ -= (x - (send / 2)); + size_t bytes_to_send = x * sizeof(SpeakerSample); + size_t send = this->speaker_->play((uint8_t *) (&sample), bytes_to_send); + if (send != bytes_to_send) { + this->samples_sent_ -= (x - (send / sizeof(SpeakerSample))); } return; } @@ -201,9 +202,9 @@ void Rtttl::loop() { bool need_note_gap = false; if (note) { auto note_index = (scale - 4) * 12 + note; - if (note_index < 0 || note_index >= (int) sizeof(NOTES)) { + if (note_index < 0 || note_index >= (int) (sizeof(NOTES) / sizeof(NOTES[0]))) { ESP_LOGE(TAG, "Note out of range (note: %d, scale: %d, index: %d, max: %d)", note, scale, note_index, - (int) sizeof(NOTES)); + (int) (sizeof(NOTES) / sizeof(NOTES[0]))); this->finish_(); return; } @@ -221,7 +222,7 @@ void Rtttl::loop() { #ifdef USE_OUTPUT if (this->output_ != nullptr) { - if (need_note_gap) { + if (need_note_gap && this->note_duration_ > DOUBLE_NOTE_GAP_MS) { this->output_->set_level(0.0); delay(DOUBLE_NOTE_GAP_MS); this->note_duration_ -= DOUBLE_NOTE_GAP_MS; @@ -240,9 +241,9 @@ void Rtttl::loop() { this->samples_sent_ = 0; this->samples_gap_ = 0; this->samples_per_wave_ = 0; - this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1600; //(ms); + this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1000; if (need_note_gap) { - this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1600; //(ms); + this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1000; } if (this->output_freq_ != 0) { // make sure there is enough samples to add a full last sinus. @@ -279,7 +280,7 @@ void Rtttl::play(std::string rtttl) { this->note_duration_ = 0; int bpm = 63; - uint8_t num; + uint16_t num; // Get name this->position_ = this->rtttl_.find(':'); @@ -395,7 +396,7 @@ void Rtttl::finish_() { sample[0].right = 0; sample[1].left = 0; sample[1].right = 0; - this->speaker_->play((uint8_t *) (&sample), 8); + this->speaker_->play((uint8_t *) (&sample), sizeof(sample)); this->speaker_->finish(); this->set_state_(State::STOPPING); } diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 6f5df07766..4d4a652c51 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -46,8 +46,8 @@ class Rtttl : public Component { } protected: - inline uint8_t get_integer_() { - uint8_t ret = 0; + inline uint16_t get_integer_() { + uint16_t ret = 0; while (isdigit(this->rtttl_[this->position_])) { ret = (ret * 10) + (this->rtttl_[this->position_++] - '0'); } @@ -87,7 +87,7 @@ class Rtttl : public Component { #ifdef USE_OUTPUT /// The output to write the sound to. - output::FloatOutput *output_; + output::FloatOutput *output_{nullptr}; #endif // USE_OUTPUT #ifdef USE_SPEAKER From 5dffceda59542cf5abca89415bc6944b94b97793 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:35:27 -0500 Subject: [PATCH 0925/2030] [hmc5883l] Fix wrong gain for 88uT range (#14281) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/hmc5883l/hmc5883l.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/hmc5883l/hmc5883l.cpp b/esphome/components/hmc5883l/hmc5883l.cpp index b62381a287..bee5282125 100644 --- a/esphome/components/hmc5883l/hmc5883l.cpp +++ b/esphome/components/hmc5883l/hmc5883l.cpp @@ -95,7 +95,7 @@ void HMC5883LComponent::update() { float mg_per_bit; switch (this->range_) { case HMC5883L_RANGE_88_UT: - mg_per_bit = 0.073f; + mg_per_bit = 0.73f; break; case HMC5883L_RANGE_130_UT: mg_per_bit = 0.92f; From d61e2f9c29543e19c79b6accaf94a47b11cf87ab Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:06:13 -0500 Subject: [PATCH 0926/2030] [light] Fix millis overflow in transition progress and flash timing (#14292) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/light/light_transformer.h | 7 +++---- esphome/components/light/transformers.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/esphome/components/light/light_transformer.h b/esphome/components/light/light_transformer.h index 079c2d2ae0..b9535c834c 100644 --- a/esphome/components/light/light_transformer.h +++ b/esphome/components/light/light_transformer.h @@ -44,12 +44,11 @@ class LightTransformer { /// The progress of this transition, on a scale of 0 to 1. float get_progress_() { uint32_t now = esphome::millis(); - if (now < this->start_time_) - return 0.0f; - if (now >= this->start_time_ + this->length_) + uint32_t elapsed = now - this->start_time_; + if (elapsed >= this->length_) return 1.0f; - return clamp((now - this->start_time_) / float(this->length_), 0.0f, 1.0f); + return clamp(elapsed / float(this->length_), 0.0f, 1.0f); } uint32_t start_time_; diff --git a/esphome/components/light/transformers.h b/esphome/components/light/transformers.h index a26713b723..b6e5e08f2b 100644 --- a/esphome/components/light/transformers.h +++ b/esphome/components/light/transformers.h @@ -78,7 +78,7 @@ class LightFlashTransformer : public LightTransformer { optional<LightColorValues> apply() override { optional<LightColorValues> result = {}; - if (this->transformer_ == nullptr && millis() > this->start_time_ + this->length_ - this->transition_length_) { + if (this->transformer_ == nullptr && millis() - this->start_time_ > this->length_ - this->transition_length_) { // second transition back to start value this->transformer_ = this->state_.get_output()->create_default_transition(); this->transformer_->setup(this->state_.current_values, this->get_start_values(), this->transition_length_); From 3dcc9ab76537dc884dbc93924e5190fd12c14bef Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:08:04 -0500 Subject: [PATCH 0927/2030] [ble_presence] Fix millis overflow in presence timeout check (#14293) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/ble_presence/ble_presence_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index 70ecc67c32..f2f0a3ed19 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -101,7 +101,7 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, } void loop() override { - if (this->found_ && this->last_seen_ + this->timeout_ < millis()) + if (this->found_ && millis() - this->last_seen_ > this->timeout_) this->set_found_(false); } void dump_config() override; From a60e5c5c4f5b3871ac30633ed007f21bbbc24333 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:11:52 -0500 Subject: [PATCH 0928/2030] [lightwaverf] Fix millis overflow in send timeout check (#14294) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/lightwaverf/lightwaverf.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/lightwaverf/lightwaverf.cpp b/esphome/components/lightwaverf/lightwaverf.cpp index 2b44195c97..2c6a1ecf5b 100644 --- a/esphome/components/lightwaverf/lightwaverf.cpp +++ b/esphome/components/lightwaverf/lightwaverf.cpp @@ -31,13 +31,12 @@ void LightWaveRF::read_tx() { void LightWaveRF::send_rx(const std::vector<uint8_t> &msg, uint8_t repeats, bool inverted, int u_sec) { this->lwtx_.lwtx_setup(pin_tx_, repeats, inverted, u_sec); - uint32_t timeout = 0; + uint32_t timeout = millis(); if (this->lwtx_.lwtx_free()) { this->lwtx_.lwtx_send(msg); - timeout = millis(); ESP_LOGD(TAG, "[%i] msg start", timeout); } - while (!this->lwtx_.lwtx_free() && millis() < (timeout + 1000)) { + while (!this->lwtx_.lwtx_free() && millis() - timeout < 1000) { delay(10); } timeout = millis() - timeout; From 2e167835ead5cc85d3507d0f262695ed112d5729 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:15:49 -0500 Subject: [PATCH 0929/2030] [pn532] Replace millis zero sentinel with optional (#14295) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/pn532/pn532.cpp | 8 ++++---- esphome/components/pn532/pn532.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/pn532/pn532.cpp b/esphome/components/pn532/pn532.cpp index 1ab0da3df7..199a44dacc 100644 --- a/esphome/components/pn532/pn532.cpp +++ b/esphome/components/pn532/pn532.cpp @@ -308,13 +308,13 @@ void PN532::send_nack_() { enum PN532ReadReady PN532::read_ready_(bool block) { if (this->rd_ready_ == READY) { if (block) { - this->rd_start_time_ = 0; + this->rd_start_time_.reset(); this->rd_ready_ = WOULDBLOCK; } return READY; } - if (!this->rd_start_time_) { + if (!this->rd_start_time_.has_value()) { this->rd_start_time_ = millis(); } @@ -324,7 +324,7 @@ enum PN532ReadReady PN532::read_ready_(bool block) { break; } - if (millis() - this->rd_start_time_ > 100) { + if (millis() - *this->rd_start_time_ > 100) { ESP_LOGV(TAG, "Timed out waiting for readiness from PN532!"); this->rd_ready_ = TIMEOUT; break; @@ -340,7 +340,7 @@ enum PN532ReadReady PN532::read_ready_(bool block) { auto rdy = this->rd_ready_; if (block || rdy == TIMEOUT) { - this->rd_start_time_ = 0; + this->rd_start_time_.reset(); this->rd_ready_ = WOULDBLOCK; } return rdy; diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index f98c0f9322..e57ecd8104 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -99,7 +99,7 @@ class PN532 : public PollingComponent { std::vector<nfc::NfcOnTagTrigger *> triggers_ontagremoved_; nfc::NfcTagUid current_uid_; nfc::NdefMessage *next_task_message_to_write_; - uint32_t rd_start_time_{0}; + optional<uint32_t> rd_start_time_{}; enum PN532ReadReady rd_ready_ { WOULDBLOCK }; enum NfcTask { READ = 0, From 24fb74f78bce8d618f1a4e134c61aeded194956d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:21:33 -0500 Subject: [PATCH 0930/2030] [ld2420] Fix buffer overflows in command response parsing (#14297) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/ld2420/ld2420.cpp | 39 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index b653f4ae88..f14400d15a 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -560,8 +560,6 @@ void LD2420Component::read_batch_(std::span<uint8_t, MAX_LINE_LENGTH> buffer) { void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { this->cmd_reply_.command = buffer[CMD_FRAME_COMMAND]; this->cmd_reply_.length = buffer[CMD_FRAME_DATA_LENGTH]; - uint8_t reg_element = 0; - uint8_t data_element = 0; uint16_t data_pos = 0; if (this->cmd_reply_.length > CMD_MAX_BYTES) { ESP_LOGW(TAG, "Reply frame too long"); @@ -583,43 +581,44 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { case (CMD_DISABLE_CONF): ESP_LOGV(TAG, "Set config disable: CMD = %2X %s", CMD_DISABLE_CONF, result); break; - case (CMD_READ_REGISTER): + case (CMD_READ_REGISTER): { ESP_LOGV(TAG, "Read register: CMD = %2X %s", CMD_READ_REGISTER, result); // TODO Read/Write register is not implemented yet, this will get flushed out to a proper header file data_pos = 0x0A; - for (uint16_t index = 0; index < (CMD_REG_DATA_REPLY_SIZE * // NOLINT - ((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_REG_DATA_REPLY_SIZE)); - index += CMD_REG_DATA_REPLY_SIZE) { - memcpy(&this->cmd_reply_.data[reg_element], &buffer[data_pos + index], CMD_REG_DATA_REPLY_SIZE); - byteswap(this->cmd_reply_.data[reg_element]); - reg_element++; + uint16_t reg_count = std::min<uint16_t>((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_REG_DATA_REPLY_SIZE, + sizeof(this->cmd_reply_.data) / sizeof(this->cmd_reply_.data[0])); + for (uint16_t i = 0; i < reg_count; i++) { + memcpy(&this->cmd_reply_.data[i], &buffer[data_pos + i * CMD_REG_DATA_REPLY_SIZE], CMD_REG_DATA_REPLY_SIZE); } break; + } case (CMD_WRITE_REGISTER): ESP_LOGV(TAG, "Write register: CMD = %2X %s", CMD_WRITE_REGISTER, result); break; case (CMD_WRITE_ABD_PARAM): ESP_LOGV(TAG, "Write gate parameter(s): %2X %s", CMD_WRITE_ABD_PARAM, result); break; - case (CMD_READ_ABD_PARAM): + case (CMD_READ_ABD_PARAM): { ESP_LOGV(TAG, "Read gate parameter(s): %2X %s", CMD_READ_ABD_PARAM, result); data_pos = CMD_ABD_DATA_REPLY_START; - for (uint16_t index = 0; index < (CMD_ABD_DATA_REPLY_SIZE * // NOLINT - ((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_ABD_DATA_REPLY_SIZE)); - index += CMD_ABD_DATA_REPLY_SIZE) { - memcpy(&this->cmd_reply_.data[data_element], &buffer[data_pos + index], - sizeof(this->cmd_reply_.data[data_element])); - byteswap(this->cmd_reply_.data[data_element]); - data_element++; + uint16_t abd_count = std::min<uint16_t>((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_ABD_DATA_REPLY_SIZE, + sizeof(this->cmd_reply_.data) / sizeof(this->cmd_reply_.data[0])); + for (uint16_t i = 0; i < abd_count; i++) { + memcpy(&this->cmd_reply_.data[i], &buffer[data_pos + i * CMD_ABD_DATA_REPLY_SIZE], + sizeof(this->cmd_reply_.data[i])); } break; + } case (CMD_WRITE_SYS_PARAM): ESP_LOGV(TAG, "Set system parameter(s): %2X %s", CMD_WRITE_SYS_PARAM, result); break; - case (CMD_READ_VERSION): - memcpy(this->firmware_ver_, &buffer[12], buffer[10]); - ESP_LOGV(TAG, "Firmware version: %7s %s", this->firmware_ver_, result); + case (CMD_READ_VERSION): { + uint8_t ver_len = std::min<uint8_t>(buffer[10], sizeof(this->firmware_ver_) - 1); + memcpy(this->firmware_ver_, &buffer[12], ver_len); + this->firmware_ver_[ver_len] = '\0'; + ESP_LOGV(TAG, "Firmware version: %s %s", this->firmware_ver_, result); break; + } default: break; } From 23ef233b60de8bef361eb062cfa732321c9a4ceb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:21:50 -0500 Subject: [PATCH 0931/2030] [gp8403] Fix enum size mismatch in voltage register write (#14296) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/gp8403/gp8403.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/gp8403/gp8403.h b/esphome/components/gp8403/gp8403.h index 972f2ce60c..a19df15515 100644 --- a/esphome/components/gp8403/gp8403.h +++ b/esphome/components/gp8403/gp8403.h @@ -6,12 +6,12 @@ namespace esphome { namespace gp8403 { -enum GP8403Voltage { +enum GP8403Voltage : uint8_t { GP8403_VOLTAGE_5V = 0x00, GP8403_VOLTAGE_10V = 0x11, }; -enum GP8403Model { +enum GP8403Model : uint8_t { GP8403, GP8413, }; From 0a81a7a50bc4b73f4075a20fb8c5a74b4ddc82f4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:01:32 -0500 Subject: [PATCH 0932/2030] [mcp2515] Fix millis overflow in set_mode_ timeout (#14298) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/mcp2515/mcp2515.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/mcp2515/mcp2515.cpp b/esphome/components/mcp2515/mcp2515.cpp index 1a17715315..77bfaf9224 100644 --- a/esphome/components/mcp2515/mcp2515.cpp +++ b/esphome/components/mcp2515/mcp2515.cpp @@ -133,8 +133,8 @@ uint8_t MCP2515::get_status_() { canbus::Error MCP2515::set_mode_(const CanctrlReqopMode mode) { modify_register_(MCP_CANCTRL, CANCTRL_REQOP, mode); - uint32_t end_time = millis() + 10; - while (millis() < end_time) { + uint32_t start_time = millis(); + while (millis() - start_time < 10) { if ((read_register_(MCP_CANSTAT) & CANSTAT_OPMOD) == mode) return canbus::ERROR_OK; } From 534857db9c16b7ebfc62693291d4b7a56b91eb36 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 18:01:49 -0500 Subject: [PATCH 0933/2030] [wled] Fix millis overflow in blank timeout (#14300) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/wled/wled_light_effect.cpp | 21 +++++++++++-------- esphome/components/wled/wled_light_effect.h | 3 ++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/esphome/components/wled/wled_light_effect.cpp b/esphome/components/wled/wled_light_effect.cpp index d26b7a1750..87bae5b1da 100644 --- a/esphome/components/wled/wled_light_effect.cpp +++ b/esphome/components/wled/wled_light_effect.cpp @@ -24,7 +24,7 @@ namespace wled { // https://github.com/Aircoookie/WLED/wiki/UDP-Realtime-Control enum Protocol { WLED_NOTIFIER = 0, WARLS = 1, DRGB = 2, DRGBW = 3, DNRGB = 4 }; -const int DEFAULT_BLANK_TIME = 1000; +constexpr uint32_t DEFAULT_BLANK_TIME = 1000; static const char *const TAG = "wled_light_effect"; @@ -34,9 +34,10 @@ void WLEDLightEffect::start() { AddressableLightEffect::start(); if (this->blank_on_start_) { - this->blank_at_ = 0; + this->blank_start_ = millis(); + this->blank_timeout_ = 0; } else { - this->blank_at_ = UINT32_MAX; + this->blank_start_.reset(); } } @@ -81,10 +82,10 @@ void WLEDLightEffect::apply(light::AddressableLight &it, const Color ¤t_co } } - // FIXME: Use roll-over safe arithmetic - if (blank_at_ < millis()) { + if (this->blank_start_.has_value() && millis() - *this->blank_start_ >= this->blank_timeout_) { blank_all_leds_(it); - blank_at_ = millis() + DEFAULT_BLANK_TIME; + this->blank_start_ = millis(); + this->blank_timeout_ = DEFAULT_BLANK_TIME; } } @@ -142,11 +143,13 @@ bool WLEDLightEffect::parse_frame_(light::AddressableLight &it, const uint8_t *p } if (timeout == UINT8_MAX) { - blank_at_ = UINT32_MAX; + this->blank_start_.reset(); } else if (timeout > 0) { - blank_at_ = millis() + timeout * 1000; + this->blank_start_ = millis(); + this->blank_timeout_ = timeout * 1000; } else { - blank_at_ = millis() + DEFAULT_BLANK_TIME; + this->blank_start_ = millis(); + this->blank_timeout_ = DEFAULT_BLANK_TIME; } it.schedule_show(); diff --git a/esphome/components/wled/wled_light_effect.h b/esphome/components/wled/wled_light_effect.h index 6da5f4e9f9..3f3b710611 100644 --- a/esphome/components/wled/wled_light_effect.h +++ b/esphome/components/wled/wled_light_effect.h @@ -35,7 +35,8 @@ class WLEDLightEffect : public light::AddressableLightEffect { uint16_t port_{0}; std::unique_ptr<UDP> udp_; - uint32_t blank_at_{0}; + optional<uint32_t> blank_start_{}; + uint32_t blank_timeout_{0}; uint32_t dropped_{0}; uint8_t sync_group_mask_{0}; bool blank_on_start_{true}; From 0d5b7df77d11b48ad58029adea4dfb88743e2932 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:32:02 -0500 Subject: [PATCH 0934/2030] [sensor] Fix delta filter percentage mode regression (#14302) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/sensor/__init__.py | 2 +- .../fixtures/sensor_filters_delta.yaml | 40 +++++++++++++++++++ .../integration/test_sensor_filters_delta.py | 27 ++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index b0e0c28bda..770c044efb 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -603,7 +603,7 @@ DELTA_SCHEMA = cv.Any( def _get_delta(value): if isinstance(value, str): assert value.endswith("%") - return 0.0, float(value[:-1]) + return 0.0, float(value[:-1]) / 100.0 return value, 0.0 diff --git a/tests/integration/fixtures/sensor_filters_delta.yaml b/tests/integration/fixtures/sensor_filters_delta.yaml index 19bd2d5ca4..2494a430da 100644 --- a/tests/integration/fixtures/sensor_filters_delta.yaml +++ b/tests/integration/fixtures/sensor_filters_delta.yaml @@ -28,6 +28,11 @@ sensor: id: source_sensor_4 accuracy_decimals: 1 + - platform: template + name: "Source Sensor 5" + id: source_sensor_5 + accuracy_decimals: 1 + - platform: copy source_id: source_sensor_1 name: "Filter Min" @@ -69,6 +74,13 @@ sensor: filters: - delta: 0 + - platform: copy + source_id: source_sensor_5 + name: "Filter Percentage" + id: filter_percentage + filters: + - delta: 50% + script: - id: test_filter_min then: @@ -154,6 +166,28 @@ script: id: source_sensor_4 state: 2.0 + - id: test_filter_percentage + then: + - sensor.template.publish: + id: source_sensor_5 + state: 100.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 120.0 # Filtered out (delta=20, need >50) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 160.0 # Passes (delta=60 > 50% of 100=50) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 200.0 # Filtered out (delta=40, need >50% of 160=80) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 250.0 # Passes (delta=90 > 80) + button: - platform: template name: "Test Filter Min" @@ -178,3 +212,9 @@ button: id: btn_filter_zero_delta on_press: - script.execute: test_filter_zero_delta + + - platform: template + name: "Test Filter Percentage" + id: btn_filter_percentage + on_press: + - script.execute: test_filter_percentage diff --git a/tests/integration/test_sensor_filters_delta.py b/tests/integration/test_sensor_filters_delta.py index c7a26bf9d1..9d0114e0c4 100644 --- a/tests/integration/test_sensor_filters_delta.py +++ b/tests/integration/test_sensor_filters_delta.py @@ -24,12 +24,14 @@ async def test_sensor_filters_delta( "filter_max": [], "filter_baseline_max": [], "filter_zero_delta": [], + "filter_percentage": [], } filter_min_done = loop.create_future() filter_max_done = loop.create_future() filter_baseline_max_done = loop.create_future() filter_zero_delta_done = loop.create_future() + filter_percentage_done = loop.create_future() def on_state(state: EntityState) -> None: if not isinstance(state, SensorState) or state.missing_state: @@ -66,6 +68,12 @@ async def test_sensor_filters_delta( and not filter_zero_delta_done.done() ): filter_zero_delta_done.set_result(True) + elif ( + sensor_name == "filter_percentage" + and len(sensor_values[sensor_name]) == 3 + and not filter_percentage_done.done() + ): + filter_percentage_done.set_result(True) async with ( run_compiled(yaml_config), @@ -80,6 +88,7 @@ async def test_sensor_filters_delta( "filter_max": "Filter Max", "filter_baseline_max": "Filter Baseline Max", "filter_zero_delta": "Filter Zero Delta", + "filter_percentage": "Filter Percentage", }, ) @@ -98,13 +107,14 @@ async def test_sensor_filters_delta( "Test Filter Max": "filter_max", "Test Filter Baseline Max": "filter_baseline_max", "Test Filter Zero Delta": "filter_zero_delta", + "Test Filter Percentage": "filter_percentage", } buttons = {} for entity in entities: if isinstance(entity, ButtonInfo) and entity.name in button_name_map: buttons[button_name_map[entity.name]] = entity.key - assert len(buttons) == 4, f"Expected 3 buttons, found {len(buttons)}" + assert len(buttons) == 5, f"Expected 5 buttons, found {len(buttons)}" # Test 1: Min sensor_values["filter_min"].clear() @@ -161,3 +171,18 @@ async def test_sensor_filters_delta( assert sensor_values["filter_zero_delta"] == pytest.approx(expected), ( f"Test 4 failed: expected {expected}, got {sensor_values['filter_zero_delta']}" ) + + # Test 5: Percentage (delta: 50%) + sensor_values["filter_percentage"].clear() + client.button_command(buttons["filter_percentage"]) + try: + await asyncio.wait_for(filter_percentage_done, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Test 5 timed out. Values: {sensor_values['filter_percentage']}" + ) + + expected = [100.0, 160.0, 250.0] + assert sensor_values["filter_percentage"] == pytest.approx(expected), ( + f"Test 5 failed: expected {expected}, got {sensor_values['filter_percentage']}" + ) From 19f4845185c5669d88c395e323f892fd6a0dbb2c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Feb 2026 16:06:46 -0500 Subject: [PATCH 0935/2030] [max7219digit] Fix typo in action names (#14162) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/max7219digit/display.py | 22 +++++++++++----------- tests/components/max7219digit/common.yaml | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index e6d53efc5d..a251eaccea 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -133,12 +133,12 @@ MAX7219_ON_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "max7129digit.invert_off", DisplayInvertAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.invert_off", DisplayInvertAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.invert_on", DisplayInvertAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.invert_on", DisplayInvertAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_invert_to_code(config, action_id, template_arg, args): +async def max7219digit_invert_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -146,12 +146,12 @@ async def max7129digit_invert_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7129digit.turn_off", DisplayVisibilityAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.turn_off", DisplayVisibilityAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.turn_on", DisplayVisibilityAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.turn_on", DisplayVisibilityAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_visible_to_code(config, action_id, template_arg, args): +async def max7219digit_visible_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -159,12 +159,12 @@ async def max7129digit_visible_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7129digit.reverse_off", DisplayReverseAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.reverse_off", DisplayReverseAction, MAX7219_OFF_ACTION_SCHEMA ) @automation.register_action( - "max7129digit.reverse_on", DisplayReverseAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.reverse_on", DisplayReverseAction, MAX7219_ON_ACTION_SCHEMA ) -async def max7129digit_reverse_to_code(config, action_id, template_arg, args): +async def max7219digit_reverse_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) cg.add(var.set_state(config[CONF_STATE])) @@ -183,9 +183,9 @@ MAX7219_INTENSITY_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "max7129digit.intensity", DisplayIntensityAction, MAX7219_INTENSITY_SCHEMA + "max7219digit.intensity", DisplayIntensityAction, MAX7219_INTENSITY_SCHEMA ) -async def max7129digit_intensity_to_code(config, action_id, template_arg, args): +async def max7219digit_intensity_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) template_ = await cg.templatable(config[CONF_INTENSITY], args, cg.uint8) diff --git a/tests/components/max7219digit/common.yaml b/tests/components/max7219digit/common.yaml index 525b7b8d3e..4d2dbb781d 100644 --- a/tests/components/max7219digit/common.yaml +++ b/tests/components/max7219digit/common.yaml @@ -13,10 +13,10 @@ esphome: on_boot: - priority: 100 then: - - max7129digit.invert_off: - - max7129digit.invert_on: - - max7129digit.turn_on: - - max7129digit.turn_off: - - max7129digit.reverse_on: - - max7129digit.reverse_off: - - max7129digit.intensity: 10 + - max7219digit.invert_off: + - max7219digit.invert_on: + - max7219digit.turn_on: + - max7219digit.turn_off: + - max7219digit.reverse_on: + - max7219digit.reverse_off: + - max7219digit.intensity: 10 From 0975755a9d13de364cb780abdc6bd854d7419b64 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 20 Feb 2026 22:51:13 -1000 Subject: [PATCH 0936/2030] [mipi_dsi] Disallow swap_xy (#14124) --- esphome/components/mipi_dsi/display.py | 26 +++++-------------- .../mipi_dsi/fixtures/mipi_dsi.yaml | 7 ++++- .../mipi_dsi/test_mipi_dsi_config.py | 6 +++-- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index c288b33cd2..de3791b3a4 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -87,38 +87,24 @@ COLOR_DEPTHS = { def model_schema(config): model = MODELS[config[CONF_MODEL].upper()] + model.defaults[CONF_SWAP_XY] = cv.UNDEFINED transform = cv.Schema( { cv.Required(CONF_MIRROR_X): cv.boolean, cv.Required(CONF_MIRROR_Y): cv.boolean, + cv.Optional(CONF_SWAP_XY): cv.invalid( + "Axis swapping not supported by DSI displays" + ), } ) - if model.get_default(CONF_SWAP_XY) != cv.UNDEFINED: - transform = transform.extend( - { - cv.Optional(CONF_SWAP_XY): cv.invalid( - "Axis swapping not supported by this model" - ) - } - ) - else: - transform = transform.extend( - { - cv.Required(CONF_SWAP_XY): cv.boolean, - } - ) # CUSTOM model will need to provide a custom init sequence iseqconf = ( cv.Required(CONF_INIT_SEQUENCE) if model.initsequence is None else cv.Optional(CONF_INIT_SEQUENCE) ) - swap_xy = config.get(CONF_TRANSFORM, {}).get(CONF_SWAP_XY, False) - - # Dimensions are optional if the model has a default width and the swap_xy transform is not overridden - cv_dimensions = ( - cv.Optional if model.get_default(CONF_WIDTH) and not swap_xy else cv.Required - ) + # Dimensions are optional if the model has a default width + cv_dimensions = cv.Optional if model.get_default(CONF_WIDTH) else cv.Required pixel_modes = (PIXEL_MODE_16BIT, PIXEL_MODE_24BIT, "16", "24") schema = display.FULL_DISPLAY_SCHEMA.extend( { diff --git a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml index 7d1fc84121..6de2bd5a77 100644 --- a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml +++ b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml @@ -15,8 +15,13 @@ esp_ldo: display: - platform: mipi_dsi + id: p4_nano model: WAVESHARE-P4-NANO-10.1 - + rotation: 90 + - platform: mipi_dsi + id: p4_86 + model: "WAVESHARE-P4-86-PANEL" + rotation: 180 i2c: sda: GPIO7 scl: GPIO8 diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index f8a9af0279..d465a8c81b 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -119,9 +119,11 @@ def test_code_generation( main_cpp = generate_main(component_fixture_path("mipi_dsi.yaml")) assert ( - "mipi_dsi_mipi_dsi_id = new mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" + "p4_nano = new mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" in main_cpp ) assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp - assert "mipi_dsi_mipi_dsi_id->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp + assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" in main_cpp # assert "backlight_id = new light::LightState(mipi_dsi_dsibacklight_id);" in main_cpp From 1f5a35a99f599045a397d8df7316e4f1626fed74 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 11:08:13 -0600 Subject: [PATCH 0937/2030] [dsmr] Add deprecated std::string overload for set_decryption_key (#14180) --- esphome/components/dsmr/dsmr.h | 3 +++ tests/components/dsmr/common.yaml | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/esphome/components/dsmr/dsmr.h b/esphome/components/dsmr/dsmr.h index fafcf62b87..dc81ba9b2a 100644 --- a/esphome/components/dsmr/dsmr.h +++ b/esphome/components/dsmr/dsmr.h @@ -64,6 +64,9 @@ class Dsmr : public Component, public uart::UARTDevice { void dump_config() override; void set_decryption_key(const char *decryption_key); + // Remove before 2026.8.0 + ESPDEPRECATED("Pass .c_str() - e.g. set_decryption_key(key.c_str()). Removed in 2026.8.0", "2026.2.0") + void set_decryption_key(const std::string &decryption_key) { this->set_decryption_key(decryption_key.c_str()); } void set_max_telegram_length(size_t length) { this->max_telegram_len_ = length; } void set_request_pin(GPIOPin *request_pin) { this->request_pin_ = request_pin; } void set_request_interval(uint32_t interval) { this->request_interval_ = interval; } diff --git a/tests/components/dsmr/common.yaml b/tests/components/dsmr/common.yaml index 038bf2806b..d11ce37d59 100644 --- a/tests/components/dsmr/common.yaml +++ b/tests/components/dsmr/common.yaml @@ -1,4 +1,13 @@ +esphome: + on_boot: + then: + - lambda: |- + // Test deprecated std::string overload still compiles + std::string key = "00112233445566778899aabbccddeeff"; + id(dsmr_instance).set_decryption_key(key); + dsmr: + id: dsmr_instance decryption_key: 00112233445566778899aabbccddeeff max_telegram_length: 1000 request_pin: ${request_pin} From 15e2a778d406ccdfdfcc8b6a39709d9ca84cadc4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 13:54:20 -0600 Subject: [PATCH 0938/2030] [api] Fix build error when lambda returns StringRef in homeassistant.event data (#14187) --- esphome/components/api/homeassistant_service.h | 2 ++ tests/components/homeassistant/common.yaml | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 2322d96eef..340699e1a6 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -36,6 +36,8 @@ template<typename... X> class TemplatableStringValue : public TemplatableValue<s static std::string value_to_string(const char *val) { return std::string(val); } // For lambdas returning .c_str() static std::string value_to_string(const std::string &val) { return val; } static std::string value_to_string(std::string &&val) { return std::move(val); } + static std::string value_to_string(const StringRef &val) { return val.str(); } + static std::string value_to_string(StringRef &&val) { return val.str(); } public: TemplatableStringValue() : TemplatableValue<std::string, X...>() {} diff --git a/tests/components/homeassistant/common.yaml b/tests/components/homeassistant/common.yaml index 9c6cb71b8b..60e3defd49 100644 --- a/tests/components/homeassistant/common.yaml +++ b/tests/components/homeassistant/common.yaml @@ -90,6 +90,19 @@ text_sensor: id: ha_hello_world_text2 attribute: some_attribute +event: + - platform: template + name: Test Event + id: test_event + event_types: + - test_event_type + on_event: + - homeassistant.event: + event: esphome.test_event + data: + event_name: !lambda |- + return event_type; + time: - platform: homeassistant on_time: From c5c6ce6b0e71a932621fbb5848cc3909fbe9634a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 13:54:43 -0600 Subject: [PATCH 0939/2030] [haier] Fix uninitialized HonSettings causing API connection failures (#14188) --- esphome/components/haier/hon_climate.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index a567ab1d89..608d5e7f21 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -29,10 +29,10 @@ enum class CleaningState : uint8_t { enum class HonControlMethod { MONITOR_ONLY = 0, SET_GROUP_PARAMETERS, SET_SINGLE_PARAMETER }; struct HonSettings { - hon_protocol::VerticalSwingMode last_vertiacal_swing; - hon_protocol::HorizontalSwingMode last_horizontal_swing; - bool beeper_state; - bool quiet_mode_state; + hon_protocol::VerticalSwingMode last_vertiacal_swing{hon_protocol::VerticalSwingMode::CENTER}; + hon_protocol::HorizontalSwingMode last_horizontal_swing{hon_protocol::HorizontalSwingMode::CENTER}; + bool beeper_state{true}; + bool quiet_mode_state{false}; }; class HonClimate : public HaierClimateBase { @@ -189,7 +189,7 @@ class HonClimate : public HaierClimateBase { int big_data_sensors_{0}; esphome::optional<hon_protocol::VerticalSwingMode> current_vertical_swing_{}; esphome::optional<hon_protocol::HorizontalSwingMode> current_horizontal_swing_{}; - HonSettings settings_; + HonSettings settings_{}; ESPPreferenceObject hon_rtc_; SwitchState quiet_mode_state_{SwitchState::OFF}; }; From 27fe866d5e5776317a3700cd98b00adf7e2fc52e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 23:22:59 -0600 Subject: [PATCH 0940/2030] [bme68x_bsec2] Fix compilation on ESP32 Arduino (#14194) --- esphome/components/bme68x_bsec2/__init__.py | 5 ++++- tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml diff --git a/esphome/components/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py index e421efb2d6..4200b2f0b8 100644 --- a/esphome/components/bme68x_bsec2/__init__.py +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -178,8 +178,11 @@ async def to_code_base(config): bsec2_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) cg.add(var.set_bsec2_configuration(bsec2_arr, len(rhs))) - # Although this component does not use SPI, the BSEC2 Arduino library requires the SPI library + # The BSEC2 and BME68x Arduino libraries unconditionally include Wire.h and + # SPI.h in their source files, so these libraries must be available even though + # ESPHome uses its own I2C/SPI abstractions instead of the Arduino ones. if core.CORE.using_arduino: + cg.add_library("Wire", None) cg.add_library("SPI", None) cg.add_library( "BME68x Sensor library", diff --git a/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml b/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml new file mode 100644 index 0000000000..7c503b0ccb --- /dev/null +++ b/tests/components/bme68x_bsec2_i2c/test.esp32-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-ard.yaml + +<<: !include common.yaml From 997f825cd3c03ee1a7a07c07306b37e1d37e4fe2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 15:56:09 -0600 Subject: [PATCH 0941/2030] [network] Improve IPAddress::str() deprecation warning with usage example (#14195) --- esphome/components/network/ip_address.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/network/ip_address.h b/esphome/components/network/ip_address.h index d0ac8164af..b2a2c563e2 100644 --- a/esphome/components/network/ip_address.h +++ b/esphome/components/network/ip_address.h @@ -61,7 +61,9 @@ struct IPAddress { IPAddress(const std::string &in_address) { inet_aton(in_address.c_str(), &ip_addr_); } IPAddress(const ip_addr_t *other_ip) { ip_addr_ = *other_ip; } // Remove before 2026.8.0 - ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") + ESPDEPRECATED( + "str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0", + "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); @@ -150,7 +152,9 @@ struct IPAddress { bool is_ip6() const { return IP_IS_V6(&ip_addr_); } bool is_multicast() const { return ip_addr_ismulticast(&ip_addr_); } // Remove before 2026.8.0 - ESPDEPRECATED("Use str_to() instead. Removed in 2026.8.0", "2026.2.0") + ESPDEPRECATED( + "str() is deprecated: use 'char buf[IP_ADDRESS_BUFFER_SIZE]; ip.str_to(buf);' instead. Removed in 2026.8.0", + "2026.2.0") std::string str() const { char buf[IP_ADDRESS_BUFFER_SIZE]; this->str_to(buf); From 4b57ac323666c8278e93bf20af20268077cab2c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Feb 2026 17:07:56 -0600 Subject: [PATCH 0942/2030] [water_heater] Fix device_id missing from state responses (#14212) --- esphome/components/api/api_connection.cpp | 3 +- .../fixtures/device_id_in_state.yaml | 115 ++++++++++++ tests/integration/test_device_id_in_state.py | 173 ++++++++++++------ 3 files changed, 232 insertions(+), 59 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 4bc3c9b307..b388bf5971 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1334,9 +1334,8 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne resp.target_temperature_low = wh->get_target_temperature_low(); resp.target_temperature_high = wh->get_target_temperature_high(); resp.state = wh->get_state(); - resp.key = wh->get_object_id_hash(); - return encode_message_to_buffer(resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(wh, resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); } uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *wh = static_cast<water_heater::WaterHeater *>(entity); diff --git a/tests/integration/fixtures/device_id_in_state.yaml b/tests/integration/fixtures/device_id_in_state.yaml index c8548617b8..a5dfb7ee45 100644 --- a/tests/integration/fixtures/device_id_in_state.yaml +++ b/tests/integration/fixtures/device_id_in_state.yaml @@ -46,6 +46,7 @@ sensor: binary_sensor: - platform: template + id: motion_detected name: Motion Detected device_id: motion_sensor lambda: return true; @@ -82,3 +83,117 @@ output: write_action: - lambda: |- ESP_LOGD("test", "Light output: %d", state); + +cover: + - platform: template + name: Garage Door + device_id: motion_sensor + optimistic: true + +fan: + - platform: template + name: Ceiling Fan + device_id: humidity_monitor + speed_count: 3 + has_oscillating: false + has_direction: false + +lock: + - platform: template + name: Front Door Lock + device_id: motion_sensor + optimistic: true + +number: + - platform: template + name: Target Temperature + device_id: temperature_monitor + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + +select: + - platform: template + name: Mode Select + device_id: humidity_monitor + optimistic: true + options: + - "Auto" + - "Manual" + +text: + - platform: template + name: Device Label + device_id: temperature_monitor + optimistic: true + mode: text + +valve: + - platform: template + name: Water Valve + device_id: humidity_monitor + optimistic: true + +globals: + - id: global_away + type: bool + initial_value: "false" + - id: global_is_on + type: bool + initial_value: "true" + +water_heater: + - platform: template + name: Test Boiler + device_id: temperature_monitor + optimistic: true + current_temperature: !lambda "return 45.0f;" + target_temperature: !lambda "return 60.0f;" + away: !lambda "return id(global_away);" + is_on: !lambda "return id(global_is_on);" + supported_modes: + - "off" + - electric + visual: + min_temperature: 30.0 + max_temperature: 85.0 + target_temperature_step: 0.5 + set_action: + - lambda: |- + ESP_LOGD("test", "Water heater set"); + +alarm_control_panel: + - platform: template + name: House Alarm + device_id: motion_sensor + codes: + - "1234" + restore_mode: ALWAYS_DISARMED + binary_sensors: + - input: motion_detected + +datetime: + - platform: template + name: Schedule Date + device_id: temperature_monitor + type: date + optimistic: true + - platform: template + name: Schedule Time + device_id: humidity_monitor + type: time + optimistic: true + - platform: template + name: Schedule DateTime + device_id: motion_sensor + type: datetime + optimistic: true + +event: + - platform: template + name: Doorbell + device_id: motion_sensor + event_types: + - "press" + - "double_press" diff --git a/tests/integration/test_device_id_in_state.py b/tests/integration/test_device_id_in_state.py index 51088bcbf7..48de94a85a 100644 --- a/tests/integration/test_device_id_in_state.py +++ b/tests/integration/test_device_id_in_state.py @@ -4,11 +4,80 @@ from __future__ import annotations import asyncio -from aioesphomeapi import BinarySensorState, EntityState, SensorState, TextSensorState +from aioesphomeapi import ( + AlarmControlPanelEntityState, + BinarySensorState, + CoverState, + DateState, + DateTimeState, + EntityState, + FanState, + LightState, + LockEntityState, + NumberState, + SelectState, + SensorState, + SwitchState, + TextSensorState, + TextState, + TimeState, + ValveState, + WaterHeaterState, +) import pytest from .types import APIClientConnectedFactory, RunCompiledFunction +# Mapping of entity name to device name for all entities with device_id +ENTITY_TO_DEVICE = { + # Original entities + "Temperature": "Temperature Monitor", + "Humidity": "Humidity Monitor", + "Motion Detected": "Motion Sensor", + "Temperature Monitor Power": "Temperature Monitor", + "Temperature Status": "Temperature Monitor", + "Motion Light": "Motion Sensor", + # New entity types + "Garage Door": "Motion Sensor", + "Ceiling Fan": "Humidity Monitor", + "Front Door Lock": "Motion Sensor", + "Target Temperature": "Temperature Monitor", + "Mode Select": "Humidity Monitor", + "Device Label": "Temperature Monitor", + "Water Valve": "Humidity Monitor", + "Test Boiler": "Temperature Monitor", + "House Alarm": "Motion Sensor", + "Schedule Date": "Temperature Monitor", + "Schedule Time": "Humidity Monitor", + "Schedule DateTime": "Motion Sensor", + "Doorbell": "Motion Sensor", +} + +# Entities without device_id (should have device_id 0) +NO_DEVICE_ENTITIES = {"No Device Sensor"} + +# State types that should have non-zero device_id, mapped by their aioesphomeapi class +EXPECTED_STATE_TYPES = [ + (SensorState, "sensor"), + (BinarySensorState, "binary_sensor"), + (SwitchState, "switch"), + (TextSensorState, "text_sensor"), + (LightState, "light"), + (CoverState, "cover"), + (FanState, "fan"), + (LockEntityState, "lock"), + (NumberState, "number"), + (SelectState, "select"), + (TextState, "text"), + (ValveState, "valve"), + (WaterHeaterState, "water_heater"), + (AlarmControlPanelEntityState, "alarm_control_panel"), + (DateState, "date"), + (TimeState, "time"), + (DateTimeState, "datetime"), + # Event is stateless (no initial state sent on subscribe) +] + @pytest.mark.asyncio async def test_device_id_in_state( @@ -40,34 +109,35 @@ async def test_device_id_in_state( entity_device_mapping: dict[int, int] = {} for entity in all_entities: - # All entities have name and key attributes - if entity.name == "Temperature": - entity_device_mapping[entity.key] = device_ids["Temperature Monitor"] - elif entity.name == "Humidity": - entity_device_mapping[entity.key] = device_ids["Humidity Monitor"] - elif entity.name == "Motion Detected": - entity_device_mapping[entity.key] = device_ids["Motion Sensor"] - elif entity.name in {"Temperature Monitor Power", "Temperature Status"}: - entity_device_mapping[entity.key] = device_ids["Temperature Monitor"] - elif entity.name == "Motion Light": - entity_device_mapping[entity.key] = device_ids["Motion Sensor"] - elif entity.name == "No Device Sensor": - # Entity without device_id should have device_id 0 + if entity.name in ENTITY_TO_DEVICE: + expected_device = ENTITY_TO_DEVICE[entity.name] + entity_device_mapping[entity.key] = device_ids[expected_device] + elif entity.name in NO_DEVICE_ENTITIES: entity_device_mapping[entity.key] = 0 - assert len(entity_device_mapping) >= 6, ( - f"Expected at least 6 mapped entities, got {len(entity_device_mapping)}" + expected_count = len(ENTITY_TO_DEVICE) + len(NO_DEVICE_ENTITIES) + assert len(entity_device_mapping) >= expected_count, ( + f"Expected at least {expected_count} mapped entities, " + f"got {len(entity_device_mapping)}. " + f"Missing: {set(ENTITY_TO_DEVICE) | NO_DEVICE_ENTITIES - {e.name for e in all_entities}}" + ) + + # Subscribe to states and wait for all mapped entities + # Event entities are stateless (no initial state on subscribe), + # so exclude them from the expected count + stateless_keys = {e.key for e in all_entities if e.name == "Doorbell"} + stateful_count = len(entity_device_mapping) - len( + stateless_keys & entity_device_mapping.keys() ) - # Subscribe to states loop = asyncio.get_running_loop() states: dict[int, EntityState] = {} states_future: asyncio.Future[bool] = loop.create_future() def on_state(state: EntityState) -> None: - states[state.key] = state - # Check if we have states for all mapped entities - if len(states) >= len(entity_device_mapping) and not states_future.done(): + if state.key in entity_device_mapping: + states[state.key] = state + if len(states) >= stateful_count and not states_future.done(): states_future.set_result(True) client.subscribe_states(on_state) @@ -76,9 +146,16 @@ async def test_device_id_in_state( try: await asyncio.wait_for(states_future, timeout=10.0) except TimeoutError: + received_names = {e.name for e in all_entities if e.key in states} + missing_names = ( + (set(ENTITY_TO_DEVICE) | NO_DEVICE_ENTITIES) + - received_names + - {"Doorbell"} + ) pytest.fail( f"Did not receive all entity states within 10 seconds. " - f"Received {len(states)} states, expected {len(entity_device_mapping)}" + f"Received {len(states)} states. " + f"Missing: {missing_names}" ) # Verify each state has the correct device_id @@ -86,51 +163,33 @@ async def test_device_id_in_state( for key, expected_device_id in entity_device_mapping.items(): if key in states: state = states[key] + entity_name = next( + (e.name for e in all_entities if e.key == key), f"key={key}" + ) assert state.device_id == expected_device_id, ( - f"State for key {key} has device_id {state.device_id}, " - f"expected {expected_device_id}" + f"State for '{entity_name}' (type={type(state).__name__}) " + f"has device_id {state.device_id}, expected {expected_device_id}" ) verified_count += 1 - assert verified_count >= 6, ( - f"Only verified {verified_count} states, expected at least 6" + # All stateful entities should be verified (everything except Doorbell event) + expected_verified = expected_count - 1 # exclude Doorbell + assert verified_count >= expected_verified, ( + f"Only verified {verified_count} states, expected at least {expected_verified}" ) - # Test specific state types to ensure device_id is present - # Find a sensor state with device_id - sensor_state = next( - ( + # Verify each expected state type has at least one instance with non-zero device_id + for state_type, type_name in EXPECTED_STATE_TYPES: + matching = [ s for s in states.values() - if isinstance(s, SensorState) - and isinstance(s.state, float) - and s.device_id != 0 - ), - None, - ) - assert sensor_state is not None, "No sensor state with device_id found" - assert sensor_state.device_id > 0, "Sensor state should have non-zero device_id" - - # Find a binary sensor state - binary_sensor_state = next( - (s for s in states.values() if isinstance(s, BinarySensorState)), - None, - ) - assert binary_sensor_state is not None, "No binary sensor state found" - assert binary_sensor_state.device_id > 0, ( - "Binary sensor state should have non-zero device_id" - ) - - # Find a text sensor state - text_sensor_state = next( - (s for s in states.values() if isinstance(s, TextSensorState)), - None, - ) - assert text_sensor_state is not None, "No text sensor state found" - assert text_sensor_state.device_id > 0, ( - "Text sensor state should have non-zero device_id" - ) + if isinstance(s, state_type) and s.device_id != 0 + ] + assert matching, ( + f"No {type_name} state (type={state_type.__name__}) " + f"with non-zero device_id found" + ) # Verify the "No Device Sensor" has device_id = 0 no_device_key = next( From efa39ae591ea3aedc5ea7b41d048df33ac15d0d7 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 25 Feb 2026 00:33:33 +1100 Subject: [PATCH 0943/2030] [mipi_dsi] Allow transform disable; fix warnings (#14216) --- esphome/components/mipi_dsi/display.py | 24 +++++++++++-------- esphome/components/mipi_dsi/mipi_dsi.cpp | 4 ++-- esphome/components/mipi_dsi/mipi_dsi.h | 10 ++++---- .../mipi_dsi/fixtures/mipi_dsi.yaml | 17 +++++++++++++ .../mipi_dsi/test_mipi_dsi_config.py | 3 ++- 5 files changed, 40 insertions(+), 18 deletions(-) diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index de3791b3a4..85bfad7f1a 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -39,6 +39,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_COLOR_ORDER, CONF_DIMENSIONS, + CONF_DISABLED, CONF_ENABLE_PIN, CONF_ID, CONF_INIT_SEQUENCE, @@ -88,14 +89,17 @@ COLOR_DEPTHS = { def model_schema(config): model = MODELS[config[CONF_MODEL].upper()] model.defaults[CONF_SWAP_XY] = cv.UNDEFINED - transform = cv.Schema( - { - cv.Required(CONF_MIRROR_X): cv.boolean, - cv.Required(CONF_MIRROR_Y): cv.boolean, - cv.Optional(CONF_SWAP_XY): cv.invalid( - "Axis swapping not supported by DSI displays" - ), - } + transform = cv.Any( + cv.Schema( + { + cv.Required(CONF_MIRROR_X): cv.boolean, + cv.Required(CONF_MIRROR_Y): cv.boolean, + cv.Optional(CONF_SWAP_XY): cv.invalid( + "Axis swapping not supported by DSI displays" + ), + } + ), + cv.one_of(CONF_DISABLED, lower=True), ) # CUSTOM model will need to provide a custom init sequence iseqconf = ( @@ -199,9 +203,9 @@ async def to_code(config): cg.add(var.set_vsync_pulse_width(config[CONF_VSYNC_PULSE_WIDTH])) cg.add(var.set_vsync_back_porch(config[CONF_VSYNC_BACK_PORCH])) cg.add(var.set_vsync_front_porch(config[CONF_VSYNC_FRONT_PORCH])) - cg.add(var.set_pclk_frequency(int(config[CONF_PCLK_FREQUENCY] / 1e6))) + cg.add(var.set_pclk_frequency(config[CONF_PCLK_FREQUENCY] / 1.0e6)) cg.add(var.set_lanes(int(config[CONF_LANES]))) - cg.add(var.set_lane_bit_rate(int(config[CONF_LANE_BIT_RATE] / 1e6))) + cg.add(var.set_lane_bit_rate(config[CONF_LANE_BIT_RATE] / 1.0e6)) if reset_pin := config.get(CONF_RESET_PIN): reset = await cg.gpio_pin_expression(reset_pin) cg.add(var.set_reset_pin(reset)) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 18cafab684..4d45cfb799 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -374,7 +374,7 @@ void MIPI_DSI::dump_config() { "\n Swap X/Y: %s" "\n Rotation: %d degrees" "\n DSI Lanes: %u" - "\n Lane Bit Rate: %uMbps" + "\n Lane Bit Rate: %.0fMbps" "\n HSync Pulse Width: %u" "\n HSync Back Porch: %u" "\n HSync Front Porch: %u" @@ -385,7 +385,7 @@ void MIPI_DSI::dump_config() { "\n Display Pixel Mode: %d bit" "\n Color Order: %s" "\n Invert Colors: %s" - "\n Pixel Clock: %dMHz", + "\n Pixel Clock: %.1fMHz", this->model_, this->width_, this->height_, YESNO(this->madctl_ & (MADCTL_XFLIP | MADCTL_MX)), YESNO(this->madctl_ & (MADCTL_YFLIP | MADCTL_MY)), YESNO(this->madctl_ & MADCTL_MV), this->rotation_, this->lanes_, this->lane_bit_rate_, this->hsync_pulse_width_, this->hsync_back_porch_, diff --git a/esphome/components/mipi_dsi/mipi_dsi.h b/esphome/components/mipi_dsi/mipi_dsi.h index 1cffe3b178..6e27912aa5 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.h +++ b/esphome/components/mipi_dsi/mipi_dsi.h @@ -47,7 +47,7 @@ class MIPI_DSI : public display::Display { void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_enable_pins(std::vector<GPIOPin *> enable_pins) { this->enable_pins_ = std::move(enable_pins); } - void set_pclk_frequency(uint32_t pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } + void set_pclk_frequency(float pclk_frequency) { this->pclk_frequency_ = pclk_frequency; } int get_width_internal() override { return this->width_; } int get_height_internal() override { return this->height_; } void set_hsync_back_porch(uint16_t hsync_back_porch) { this->hsync_back_porch_ = hsync_back_porch; } @@ -58,7 +58,7 @@ class MIPI_DSI : public display::Display { void set_vsync_front_porch(uint16_t vsync_front_porch) { this->vsync_front_porch_ = vsync_front_porch; } void set_init_sequence(const std::vector<uint8_t> &init_sequence) { this->init_sequence_ = init_sequence; } void set_model(const char *model) { this->model_ = model; } - void set_lane_bit_rate(uint16_t lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } + void set_lane_bit_rate(float lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } void set_lanes(uint8_t lanes) { this->lanes_ = lanes; } void set_madctl(uint8_t madctl) { this->madctl_ = madctl; } @@ -95,9 +95,9 @@ class MIPI_DSI : public display::Display { uint16_t vsync_front_porch_ = 10; const char *model_{"Unknown"}; std::vector<uint8_t> init_sequence_{}; - uint16_t pclk_frequency_ = 16; // in MHz - uint16_t lane_bit_rate_{1500}; // in Mbps - uint8_t lanes_{2}; // 1, 2, 3 or 4 lanes + float pclk_frequency_ = 16; // in MHz + float lane_bit_rate_{1500}; // in Mbps + uint8_t lanes_{2}; // 1, 2, 3 or 4 lanes bool invert_colors_{}; display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; diff --git a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml index 6de2bd5a77..6f76dcb1d1 100644 --- a/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml +++ b/tests/component_tests/mipi_dsi/fixtures/mipi_dsi.yaml @@ -22,6 +22,23 @@ display: id: p4_86 model: "WAVESHARE-P4-86-PANEL" rotation: 180 + - platform: mipi_dsi + model: custom + id: custom_id + dimensions: + width: 400 + height: 1280 + hsync_back_porch: 40 + hsync_pulse_width: 30 + hsync_front_porch: 40 + vsync_back_porch: 20 + vsync_pulse_width: 10 + vsync_front_porch: 20 + pclk_frequency: 48Mhz + lane_bit_rate: 1.2Gbps + rotation: 180 + transform: disabled + init_sequence: i2c: sda: GPIO7 scl: GPIO8 diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index d465a8c81b..92f56b5451 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -123,7 +123,8 @@ def test_code_generation( in main_cpp ) assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp - assert "p4_nano->set_lane_bit_rate(1500);" in main_cpp + assert "p4_nano->set_lane_bit_rate(1500.0f);" in main_cpp assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" in main_cpp + assert "custom_id->set_rotation(display::DISPLAY_ROTATION_180_DEGREES);" in main_cpp # assert "backlight_id = new light::LightState(mipi_dsi_dsibacklight_id);" in main_cpp From 29d890bb0f89af6257a471e9256aa1bc042f381b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:15:22 -0500 Subject: [PATCH 0944/2030] [http_request.ota] Percent-encode credentials in URL (#14257) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../http_request/ota/ota_http_request.cpp | 22 +++++++++++++++++++ .../http_request/ota/ota_http_request.h | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 882def4d7f..bbe128aad9 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -1,5 +1,7 @@ #include "ota_http_request.h" +#include <cctype> + #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/log.h" @@ -210,6 +212,26 @@ uint8_t OtaHttpRequestComponent::do_ota_() { return ota::OTA_RESPONSE_OK; } +// URL-encode characters that are not unreserved per RFC 3986 section 2.3. +// This is needed for embedding userinfo (username/password) in URLs safely. +static std::string url_encode(const std::string &str) { + std::string result; + result.reserve(str.size()); + for (char c : str) { + if (std::isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~') { + result += c; + } else { + result += '%'; + result += format_hex_pretty_char((static_cast<uint8_t>(c) >> 4) & 0x0F); + result += format_hex_pretty_char(static_cast<uint8_t>(c) & 0x0F); + } + } + return result; +} + +void OtaHttpRequestComponent::set_password(const std::string &password) { this->password_ = url_encode(password); } +void OtaHttpRequestComponent::set_username(const std::string &username) { this->username_ = url_encode(username); } + std::string OtaHttpRequestComponent::get_url_with_auth_(const std::string &url) { if (this->username_.empty() || this->password_.empty()) { return url; diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 8735189e99..e3f1a4aa90 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -29,9 +29,9 @@ class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRe 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_password(const std::string &password); void set_url(const std::string &url); - void set_username(const std::string &username) { this->username_ = username; } + void set_username(const std::string &username); std::string md5_computed() { return this->md5_computed_; } std::string md5_expected() { return this->md5_expected_; } From 2c11c65faff2edec0224ca0bbe7624a9d3adc147 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:28:19 +1300 Subject: [PATCH 0945/2030] Don't get stuck forever on a failed component can_proceed (#14267) --- esphome/core/application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 449acc64cf..2b84b1c1e4 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -132,7 +132,7 @@ void Application::setup() { this->after_loop_tasks_(); this->app_state_ = new_app_state; yield(); - } while (!component->can_proceed()); + } while (!component->can_proceed() && !component->is_failed()); } ESP_LOGI(TAG, "setup() finished successfully!"); From af296eb600262ca2a3a4f9e47aab3e65bbc8826d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Feb 2026 23:26:00 -0500 Subject: [PATCH 0946/2030] [pid] Fix deadband threshold conversion for Fahrenheit (#14268) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/pid/climate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py index 5919d2cac8..5fa3166f9d 100644 --- a/esphome/components/pid/climate.py +++ b/esphome/components/pid/climate.py @@ -50,8 +50,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_HEAT_OUTPUT): cv.use_id(output.FloatOutput), cv.Optional(CONF_DEADBAND_PARAMETERS): cv.Schema( { - cv.Required(CONF_THRESHOLD_HIGH): cv.temperature, - cv.Required(CONF_THRESHOLD_LOW): cv.temperature, + cv.Required(CONF_THRESHOLD_HIGH): cv.temperature_delta, + cv.Required(CONF_THRESHOLD_LOW): cv.temperature_delta, cv.Optional(CONF_KP_MULTIPLIER, default=0.1): cv.float_, cv.Optional(CONF_KI_MULTIPLIER, default=0.0): cv.float_, cv.Optional(CONF_KD_MULTIPLIER, default=0.0): cv.float_, From da930310b1e2e1175118126cd25680fa3ca2eeb2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:19:20 -0500 Subject: [PATCH 0947/2030] [ld2420] Fix sizeof vs value bug in register memcpy (#14286) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/ld2420/ld2420.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index cf78a1a460..b653f4ae88 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -590,7 +590,7 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { for (uint16_t index = 0; index < (CMD_REG_DATA_REPLY_SIZE * // NOLINT ((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_REG_DATA_REPLY_SIZE)); index += CMD_REG_DATA_REPLY_SIZE) { - memcpy(&this->cmd_reply_.data[reg_element], &buffer[data_pos + index], sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&this->cmd_reply_.data[reg_element], &buffer[data_pos + index], CMD_REG_DATA_REPLY_SIZE); byteswap(this->cmd_reply_.data[reg_element]); reg_element++; } @@ -729,9 +729,9 @@ void LD2420Component::set_reg_value(uint16_t reg, uint16_t value) { cmd_frame.data_length = 0; cmd_frame.header = CMD_FRAME_HEADER; cmd_frame.command = CMD_WRITE_REGISTER; - memcpy(&cmd_frame.data[cmd_frame.data_length], ®, sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&cmd_frame.data[cmd_frame.data_length], ®, CMD_REG_DATA_REPLY_SIZE); cmd_frame.data_length += 2; - memcpy(&cmd_frame.data[cmd_frame.data_length], &value, sizeof(CMD_REG_DATA_REPLY_SIZE)); + memcpy(&cmd_frame.data[cmd_frame.data_length], &value, CMD_REG_DATA_REPLY_SIZE); cmd_frame.data_length += 2; cmd_frame.footer = CMD_FRAME_FOOTER; ESP_LOGV(TAG, "Sending write register %4X command: %2X data = %4X", reg, cmd_frame.command, value); From a39be5a4619817d0b3a244b04cbac5150cb4b540 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:34:38 -0500 Subject: [PATCH 0948/2030] [rtttl] Fix speaker playback bugs (#14280) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 21 +++++++++++---------- esphome/components/rtttl/rtttl.h | 6 +++--- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 6e86405b74..ab95067f45 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -139,9 +139,10 @@ void Rtttl::loop() { x++; } if (x > 0) { - int send = this->speaker_->play((uint8_t *) (&sample), x * 2); - if (send != x * 4) { - this->samples_sent_ -= (x - (send / 2)); + size_t bytes_to_send = x * sizeof(SpeakerSample); + size_t send = this->speaker_->play((uint8_t *) (&sample), bytes_to_send); + if (send != bytes_to_send) { + this->samples_sent_ -= (x - (send / sizeof(SpeakerSample))); } return; } @@ -201,9 +202,9 @@ void Rtttl::loop() { bool need_note_gap = false; if (note) { auto note_index = (scale - 4) * 12 + note; - if (note_index < 0 || note_index >= (int) sizeof(NOTES)) { + if (note_index < 0 || note_index >= (int) (sizeof(NOTES) / sizeof(NOTES[0]))) { ESP_LOGE(TAG, "Note out of range (note: %d, scale: %d, index: %d, max: %d)", note, scale, note_index, - (int) sizeof(NOTES)); + (int) (sizeof(NOTES) / sizeof(NOTES[0]))); this->finish_(); return; } @@ -221,7 +222,7 @@ void Rtttl::loop() { #ifdef USE_OUTPUT if (this->output_ != nullptr) { - if (need_note_gap) { + if (need_note_gap && this->note_duration_ > DOUBLE_NOTE_GAP_MS) { this->output_->set_level(0.0); delay(DOUBLE_NOTE_GAP_MS); this->note_duration_ -= DOUBLE_NOTE_GAP_MS; @@ -240,9 +241,9 @@ void Rtttl::loop() { this->samples_sent_ = 0; this->samples_gap_ = 0; this->samples_per_wave_ = 0; - this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1600; //(ms); + this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1000; if (need_note_gap) { - this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1600; //(ms); + this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1000; } if (this->output_freq_ != 0) { // make sure there is enough samples to add a full last sinus. @@ -279,7 +280,7 @@ void Rtttl::play(std::string rtttl) { this->note_duration_ = 0; int bpm = 63; - uint8_t num; + uint16_t num; // Get name this->position_ = this->rtttl_.find(':'); @@ -395,7 +396,7 @@ void Rtttl::finish_() { sample[0].right = 0; sample[1].left = 0; sample[1].right = 0; - this->speaker_->play((uint8_t *) (&sample), 8); + this->speaker_->play((uint8_t *) (&sample), sizeof(sample)); this->speaker_->finish(); this->set_state_(State::STOPPING); } diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 6f5df07766..4d4a652c51 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -46,8 +46,8 @@ class Rtttl : public Component { } protected: - inline uint8_t get_integer_() { - uint8_t ret = 0; + inline uint16_t get_integer_() { + uint16_t ret = 0; while (isdigit(this->rtttl_[this->position_])) { ret = (ret * 10) + (this->rtttl_[this->position_++] - '0'); } @@ -87,7 +87,7 @@ class Rtttl : public Component { #ifdef USE_OUTPUT /// The output to write the sound to. - output::FloatOutput *output_; + output::FloatOutput *output_{nullptr}; #endif // USE_OUTPUT #ifdef USE_SPEAKER From 5a1d6428b20163de46cc428246002ac1dd845b4e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:35:27 -0500 Subject: [PATCH 0949/2030] [hmc5883l] Fix wrong gain for 88uT range (#14281) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/hmc5883l/hmc5883l.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/hmc5883l/hmc5883l.cpp b/esphome/components/hmc5883l/hmc5883l.cpp index b62381a287..bee5282125 100644 --- a/esphome/components/hmc5883l/hmc5883l.cpp +++ b/esphome/components/hmc5883l/hmc5883l.cpp @@ -95,7 +95,7 @@ void HMC5883LComponent::update() { float mg_per_bit; switch (this->range_) { case HMC5883L_RANGE_88_UT: - mg_per_bit = 0.073f; + mg_per_bit = 0.73f; break; case HMC5883L_RANGE_130_UT: mg_per_bit = 0.92f; From 8479664df104b85ab3bce2e9c6ca3377ed02eb24 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Feb 2026 19:32:02 -0500 Subject: [PATCH 0950/2030] [sensor] Fix delta filter percentage mode regression (#14302) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/sensor/__init__.py | 2 +- .../fixtures/sensor_filters_delta.yaml | 40 +++++++++++++++++++ .../integration/test_sensor_filters_delta.py | 27 ++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index ebbe0fbccc..03784ba76b 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -603,7 +603,7 @@ DELTA_SCHEMA = cv.Any( def _get_delta(value): if isinstance(value, str): assert value.endswith("%") - return 0.0, float(value[:-1]) + return 0.0, float(value[:-1]) / 100.0 return value, 0.0 diff --git a/tests/integration/fixtures/sensor_filters_delta.yaml b/tests/integration/fixtures/sensor_filters_delta.yaml index 19bd2d5ca4..2494a430da 100644 --- a/tests/integration/fixtures/sensor_filters_delta.yaml +++ b/tests/integration/fixtures/sensor_filters_delta.yaml @@ -28,6 +28,11 @@ sensor: id: source_sensor_4 accuracy_decimals: 1 + - platform: template + name: "Source Sensor 5" + id: source_sensor_5 + accuracy_decimals: 1 + - platform: copy source_id: source_sensor_1 name: "Filter Min" @@ -69,6 +74,13 @@ sensor: filters: - delta: 0 + - platform: copy + source_id: source_sensor_5 + name: "Filter Percentage" + id: filter_percentage + filters: + - delta: 50% + script: - id: test_filter_min then: @@ -154,6 +166,28 @@ script: id: source_sensor_4 state: 2.0 + - id: test_filter_percentage + then: + - sensor.template.publish: + id: source_sensor_5 + state: 100.0 + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 120.0 # Filtered out (delta=20, need >50) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 160.0 # Passes (delta=60 > 50% of 100=50) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 200.0 # Filtered out (delta=40, need >50% of 160=80) + - delay: 20ms + - sensor.template.publish: + id: source_sensor_5 + state: 250.0 # Passes (delta=90 > 80) + button: - platform: template name: "Test Filter Min" @@ -178,3 +212,9 @@ button: id: btn_filter_zero_delta on_press: - script.execute: test_filter_zero_delta + + - platform: template + name: "Test Filter Percentage" + id: btn_filter_percentage + on_press: + - script.execute: test_filter_percentage diff --git a/tests/integration/test_sensor_filters_delta.py b/tests/integration/test_sensor_filters_delta.py index c7a26bf9d1..9d0114e0c4 100644 --- a/tests/integration/test_sensor_filters_delta.py +++ b/tests/integration/test_sensor_filters_delta.py @@ -24,12 +24,14 @@ async def test_sensor_filters_delta( "filter_max": [], "filter_baseline_max": [], "filter_zero_delta": [], + "filter_percentage": [], } filter_min_done = loop.create_future() filter_max_done = loop.create_future() filter_baseline_max_done = loop.create_future() filter_zero_delta_done = loop.create_future() + filter_percentage_done = loop.create_future() def on_state(state: EntityState) -> None: if not isinstance(state, SensorState) or state.missing_state: @@ -66,6 +68,12 @@ async def test_sensor_filters_delta( and not filter_zero_delta_done.done() ): filter_zero_delta_done.set_result(True) + elif ( + sensor_name == "filter_percentage" + and len(sensor_values[sensor_name]) == 3 + and not filter_percentage_done.done() + ): + filter_percentage_done.set_result(True) async with ( run_compiled(yaml_config), @@ -80,6 +88,7 @@ async def test_sensor_filters_delta( "filter_max": "Filter Max", "filter_baseline_max": "Filter Baseline Max", "filter_zero_delta": "Filter Zero Delta", + "filter_percentage": "Filter Percentage", }, ) @@ -98,13 +107,14 @@ async def test_sensor_filters_delta( "Test Filter Max": "filter_max", "Test Filter Baseline Max": "filter_baseline_max", "Test Filter Zero Delta": "filter_zero_delta", + "Test Filter Percentage": "filter_percentage", } buttons = {} for entity in entities: if isinstance(entity, ButtonInfo) and entity.name in button_name_map: buttons[button_name_map[entity.name]] = entity.key - assert len(buttons) == 4, f"Expected 3 buttons, found {len(buttons)}" + assert len(buttons) == 5, f"Expected 5 buttons, found {len(buttons)}" # Test 1: Min sensor_values["filter_min"].clear() @@ -161,3 +171,18 @@ async def test_sensor_filters_delta( assert sensor_values["filter_zero_delta"] == pytest.approx(expected), ( f"Test 4 failed: expected {expected}, got {sensor_values['filter_zero_delta']}" ) + + # Test 5: Percentage (delta: 50%) + sensor_values["filter_percentage"].clear() + client.button_command(buttons["filter_percentage"]) + try: + await asyncio.wait_for(filter_percentage_done, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Test 5 timed out. Values: {sensor_values['filter_percentage']}" + ) + + expected = [100.0, 160.0, 250.0] + assert sensor_values["filter_percentage"] == pytest.approx(expected), ( + f"Test 5 failed: expected {expected}, got {sensor_values['filter_percentage']}" + ) From 2c749e9dbefa3a3b0caf3b2275d2cadb46ee5165 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:45:13 +1300 Subject: [PATCH 0951/2030] Bump version to 2026.2.2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index d41a79b0dc..2de0460ef1 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.1 +PROJECT_NUMBER = 2026.2.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index b3c15b1e27..7d15964eab 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.1" +__version__ = "2026.2.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 789da5fdf822a7332adb7e670ff2de9353907bc3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:13:44 -0700 Subject: [PATCH 0952/2030] [logger] Mark Logger and LoggerMessageTrigger as final (#14291) --- esphome/components/logger/logger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 90722ee79c..263d12b444 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -141,7 +141,7 @@ enum UARTSelection : uint8_t { * 2. Works with ESP-IDF's pthread implementation that uses a linked list for TLS variables * 3. Avoids the limitations of the fixed FreeRTOS task local storage slots */ -class Logger : public Component { +class Logger final : public Component { public: explicit Logger(uint32_t baud_rate); #ifdef USE_ESPHOME_TASK_LOG_BUFFER @@ -481,7 +481,7 @@ class Logger : public Component { }; extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *> { +class LoggerMessageTrigger final : public Trigger<uint8_t, const char *, const char *> { public: explicit LoggerMessageTrigger(Logger *parent, uint8_t level) : level_(level) { parent->add_log_callback(this, From 478a876b0156763e27605ed22e034fb2ed442a3c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:13:51 -0700 Subject: [PATCH 0953/2030] [mdns] Mark MDNSComponent as final (#14290) --- esphome/components/mdns/mdns_component.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index 32f8f16ec1..13c8ccf288 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -40,7 +40,7 @@ struct MDNSService { FixedVector<MDNSTXTRecord> txt_records; }; -class MDNSComponent : public Component { +class MDNSComponent final : public Component { public: void setup() override; void dump_config() override; From cced0a82b55d17ae402425c86dfd9654ed4f7d86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:14:04 -0700 Subject: [PATCH 0954/2030] [ota] Mark OTA backend and component leaf classes as final (#14287) --- esphome/components/esphome/ota/ota_esphome.h | 2 +- esphome/components/http_request/ota/ota_http_request.h | 2 +- esphome/components/ota/ota_backend_arduino_libretiny.h | 2 +- esphome/components/ota/ota_backend_arduino_rp2040.h | 2 +- esphome/components/ota/ota_backend_esp8266.h | 2 +- esphome/components/ota/ota_backend_esp_idf.h | 2 +- esphome/components/ota/ota_backend_host.h | 2 +- esphome/components/web_server/ota/ota_web_server.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index c9e89c82ba..53715cfe6a 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -12,7 +12,7 @@ namespace esphome { /// ESPHomeOTAComponent provides a simple way to integrate Over-the-Air updates into your app using ArduinoOTA. -class ESPHomeOTAComponent : public ota::OTAComponent { +class ESPHomeOTAComponent final : public ota::OTAComponent { public: enum class OTAState : uint8_t { IDLE, diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index e3f1a4aa90..6d39b0d466 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -22,7 +22,7 @@ enum OtaHttpRequestError : uint8_t { OTA_CONNECTION_ERROR = 0x12, }; -class OtaHttpRequestComponent : public ota::OTAComponent, public Parented<HttpRequestComponent> { +class OtaHttpRequestComponent final : public ota::OTAComponent, public Parented<HttpRequestComponent> { public: void dump_config() override; float get_setup_priority() const override { return setup_priority::AFTER_WIFI; } diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.h b/esphome/components/ota/ota_backend_arduino_libretiny.h index 6d9b7a96d5..8f9d268eec 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.h +++ b/esphome/components/ota/ota_backend_arduino_libretiny.h @@ -7,7 +7,7 @@ namespace esphome { namespace ota { -class ArduinoLibreTinyOTABackend : public OTABackend { +class ArduinoLibreTinyOTABackend final : public OTABackend { public: OTAResponseTypes begin(size_t image_size) override; void set_update_md5(const char *md5) override; diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.h b/esphome/components/ota/ota_backend_arduino_rp2040.h index b9e10d506c..6a708f9c57 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.h +++ b/esphome/components/ota/ota_backend_arduino_rp2040.h @@ -9,7 +9,7 @@ namespace esphome { namespace ota { -class ArduinoRP2040OTABackend : public OTABackend { +class ArduinoRP2040OTABackend final : public OTABackend { public: OTAResponseTypes begin(size_t image_size) override; void set_update_md5(const char *md5) override; diff --git a/esphome/components/ota/ota_backend_esp8266.h b/esphome/components/ota/ota_backend_esp8266.h index a9d6dd2ccc..52f657f006 100644 --- a/esphome/components/ota/ota_backend_esp8266.h +++ b/esphome/components/ota/ota_backend_esp8266.h @@ -12,7 +12,7 @@ namespace esphome::ota { /// OTA backend for ESP8266 using native SDK functions. /// This implementation bypasses the Arduino Updater library to save ~228 bytes of RAM /// by not having a global Update object in .bss. -class ESP8266OTABackend : public OTABackend { +class ESP8266OTABackend final : public OTABackend { public: OTAResponseTypes begin(size_t image_size) override; void set_update_md5(const char *md5) override; diff --git a/esphome/components/ota/ota_backend_esp_idf.h b/esphome/components/ota/ota_backend_esp_idf.h index 764010e614..7f7f6115c5 100644 --- a/esphome/components/ota/ota_backend_esp_idf.h +++ b/esphome/components/ota/ota_backend_esp_idf.h @@ -10,7 +10,7 @@ namespace esphome { namespace ota { -class IDFOTABackend : public OTABackend { +class IDFOTABackend final : public OTABackend { public: OTAResponseTypes begin(size_t image_size) override; void set_update_md5(const char *md5) override; diff --git a/esphome/components/ota/ota_backend_host.h b/esphome/components/ota/ota_backend_host.h index ae7d0cb0b3..5a2dcfcf39 100644 --- a/esphome/components/ota/ota_backend_host.h +++ b/esphome/components/ota/ota_backend_host.h @@ -7,7 +7,7 @@ namespace esphome::ota { /// Stub OTA backend for host platform - allows compilation but does not implement OTA. /// All operations return error codes immediately. This enables configurations with /// OTA triggers to compile for host platform during development. -class HostOTABackend : public OTABackend { +class HostOTABackend final : public OTABackend { public: OTAResponseTypes begin(size_t image_size) override; void set_update_md5(const char *md5) override; diff --git a/esphome/components/web_server/ota/ota_web_server.h b/esphome/components/web_server/ota/ota_web_server.h index 53ff99899c..0857c31c5d 100644 --- a/esphome/components/web_server/ota/ota_web_server.h +++ b/esphome/components/web_server/ota/ota_web_server.h @@ -9,7 +9,7 @@ namespace esphome::web_server { -class WebServerOTAComponent : public ota::OTAComponent { +class WebServerOTAComponent final : public ota::OTAComponent { public: void setup() override; void dump_config() override; From ee4d67930f11a4af1997190f9dc576db8a0d05c2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:14:16 -0700 Subject: [PATCH 0955/2030] [api] Mark ListEntitiesIterator and InitialStateIterator as final (#14284) --- esphome/components/api/list_entities.h | 2 +- esphome/components/api/subscribe_state.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/list_entities.h b/esphome/components/api/list_entities.h index 90769f9a81..7d0eb5bb13 100644 --- a/esphome/components/api/list_entities.h +++ b/esphome/components/api/list_entities.h @@ -15,7 +15,7 @@ class APIConnection; return this->client_->schedule_message_(entity, ResponseType::MESSAGE_TYPE, ResponseType::ESTIMATED_SIZE); \ } -class ListEntitiesIterator : public ComponentIterator { +class ListEntitiesIterator final : public ComponentIterator { public: ListEntitiesIterator(APIConnection *client); #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/api/subscribe_state.h b/esphome/components/api/subscribe_state.h index 6f8577ca7b..9edf0f0f0c 100644 --- a/esphome/components/api/subscribe_state.h +++ b/esphome/components/api/subscribe_state.h @@ -16,7 +16,7 @@ class APIConnection; return this->client_->send_##entity_type##_state(entity); \ } -class InitialStateIterator : public ComponentIterator { +class InitialStateIterator final : public ComponentIterator { public: InitialStateIterator(APIConnection *client); #ifdef USE_BINARY_SENSOR From d52f8c9c6f250024f8ce4a353100919cb2b25215 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:14:33 -0700 Subject: [PATCH 0956/2030] [web_server] Mark classes as final (#14283) --- esphome/components/web_server/list_entities.cpp | 2 -- esphome/components/web_server/list_entities.h | 3 +-- esphome/components/web_server/web_server.h | 6 +++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/esphome/components/web_server/list_entities.cpp b/esphome/components/web_server/list_entities.cpp index 8458298062..ebe7bf4450 100644 --- a/esphome/components/web_server/list_entities.cpp +++ b/esphome/components/web_server/list_entities.cpp @@ -14,8 +14,6 @@ ListEntitiesIterator::ListEntitiesIterator(const WebServer *ws, AsyncEventSource ListEntitiesIterator::ListEntitiesIterator(const WebServer *ws, DeferredUpdateEventSource *es) : web_server_(ws), events_(es) {} #endif -ListEntitiesIterator::~ListEntitiesIterator() {} - #ifdef USE_BINARY_SENSOR bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *obj) { this->events_->deferrable_send_state(obj, "state_detail_all", WebServer::binary_sensor_all_json_generator); diff --git a/esphome/components/web_server/list_entities.h b/esphome/components/web_server/list_entities.h index d0a4fa2725..6a84066109 100644 --- a/esphome/components/web_server/list_entities.h +++ b/esphome/components/web_server/list_entities.h @@ -17,14 +17,13 @@ class DeferredUpdateEventSource; #endif class WebServer; -class ListEntitiesIterator : public ComponentIterator { +class ListEntitiesIterator final : public ComponentIterator { public: #ifdef USE_ESP32 ListEntitiesIterator(const WebServer *ws, esphome::web_server_idf::AsyncEventSource *es); #elif defined(USE_ARDUINO) ListEntitiesIterator(const WebServer *ws, DeferredUpdateEventSource *es); #endif - virtual ~ListEntitiesIterator(); #ifdef USE_BINARY_SENSOR bool on_binary_sensor(binary_sensor::BinarySensor *obj) override; #endif diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 76c1c8b0bd..64c492f82b 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -107,7 +107,7 @@ enum JsonDetail { DETAIL_ALL, DETAIL_STATE }; using message_generator_t = json::SerializationBuffer<>(WebServer *, void *); class DeferredUpdateEventSourceList; -class DeferredUpdateEventSource : public AsyncEventSource { +class DeferredUpdateEventSource final : public AsyncEventSource { friend class DeferredUpdateEventSourceList; /* @@ -163,7 +163,7 @@ class DeferredUpdateEventSource : public AsyncEventSource { void try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0); }; -class DeferredUpdateEventSourceList : public std::list<DeferredUpdateEventSource *> { +class DeferredUpdateEventSourceList final : public std::list<DeferredUpdateEventSource *> { protected: void on_client_connect_(DeferredUpdateEventSource *source); void on_client_disconnect_(DeferredUpdateEventSource *source); @@ -187,7 +187,7 @@ class DeferredUpdateEventSourceList : public std::list<DeferredUpdateEventSource * under the '/light/...', '/sensor/...', ... URLs. A full documentation for this API * can be found under https://esphome.io/web-api/. */ -class WebServer : public Controller, public Component, public AsyncWebHandler { +class WebServer final : public Controller, public Component, public AsyncWebHandler { #if !defined(USE_ESP32) && defined(USE_ARDUINO) friend class DeferredUpdateEventSourceList; #endif From 962cbfb9d80128994ac700790bd608bc5fc45afc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Feb 2026 20:14:53 -0700 Subject: [PATCH 0957/2030] [safe_mode] Mark SafeModeComponent and SafeModeTrigger as final (#14282) --- esphome/components/safe_mode/automation.h | 2 +- esphome/components/safe_mode/safe_mode.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/safe_mode/automation.h b/esphome/components/safe_mode/automation.h index 952ed4da33..1d82ac45f1 100644 --- a/esphome/components/safe_mode/automation.h +++ b/esphome/components/safe_mode/automation.h @@ -8,7 +8,7 @@ namespace esphome::safe_mode { -class SafeModeTrigger : public Trigger<> { +class SafeModeTrigger final : public Trigger<> { public: explicit SafeModeTrigger(SafeModeComponent *parent) { parent->add_on_safe_mode_callback([this]() { trigger(); }); diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index a4d27c15da..902b8c415d 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -15,7 +15,7 @@ namespace esphome::safe_mode { constexpr uint32_t RTC_KEY = 233825507UL; /// SafeModeComponent provides a safe way to recover from repeated boot failures -class SafeModeComponent : public Component { +class SafeModeComponent final : public Component { public: bool should_enter_safe_mode(uint8_t num_attempts, uint32_t enable_time, uint32_t boot_is_good_after); From 6c253f0c71958a182cf1d9c4ad64a10b2b62957f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:40:43 -0500 Subject: [PATCH 0958/2030] [sprinkler] Fix millis overflow and underflow bugs (#14299) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/sprinkler/sprinkler.cpp | 81 +++++++++++----------- esphome/components/sprinkler/sprinkler.h | 4 +- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 9e423c1760..d82d7baaf6 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -84,32 +84,30 @@ SprinklerValveOperator::SprinklerValveOperator(SprinklerValve *valve, Sprinkler : controller_(controller), valve_(valve) {} void SprinklerValveOperator::loop() { + // Use wrapping subtraction so 32-bit millis() rollover is handled correctly: + // (now - start) yields the true elapsed time even across the 49.7-day boundary. uint32_t now = App.get_loop_component_start_time(); - if (now >= this->start_millis_) { // dummy check - switch (this->state_) { - case STARTING: - if (now > (this->start_millis_ + this->start_delay_)) { - this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state - } - break; + switch (this->state_) { + case STARTING: + if ((now - *this->start_millis_) > this->start_delay_) { + this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state + } + break; - case ACTIVE: - if (now > (this->start_millis_ + this->start_delay_ + this->run_duration_)) { - this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down - } - break; + case ACTIVE: + if ((now - *this->start_millis_) > (this->start_delay_ + this->run_duration_)) { + this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down + } + break; - case STOPPING: - if (now > (this->stop_millis_ + this->stop_delay_)) { - this->kill_(); // stop_delay_has been exceeded, ensure all valves are off - } - break; + case STOPPING: + if ((now - *this->stop_millis_) > this->stop_delay_) { + this->kill_(); // stop_delay_has been exceeded, ensure all valves are off + } + break; - default: - break; - } - } else { // perhaps millis() rolled over...or something else is horribly wrong! - this->stop(); // bail out (TODO: handle this highly unlikely situation better...) + default: + break; } } @@ -124,11 +122,11 @@ void SprinklerValveOperator::set_valve(SprinklerValve *valve) { if (this->state_ != IDLE) { // Only kill if not already idle this->kill_(); // ensure everything is off before we let go! } - this->state_ = IDLE; // reset state - this->run_duration_ = 0; // reset to ensure the valve isn't started without updating it - this->start_millis_ = 0; // reset because (new) valve has not been started yet - this->stop_millis_ = 0; // reset because (new) valve has not been started yet - this->valve_ = valve; // finally, set the pointer to the new valve + this->state_ = IDLE; // reset state + this->run_duration_ = 0; // reset to ensure the valve isn't started without updating it + this->start_millis_.reset(); // reset because (new) valve has not been started yet + this->stop_millis_.reset(); // reset because (new) valve has not been started yet + this->valve_ = valve; // finally, set the pointer to the new valve } } @@ -162,7 +160,7 @@ void SprinklerValveOperator::start() { } else { this->run_(); // there is no start_delay_, so just start the pump and valve } - this->stop_millis_ = 0; + this->stop_millis_.reset(); this->start_millis_ = millis(); // save the time the start request was made } @@ -189,22 +187,25 @@ void SprinklerValveOperator::stop() { uint32_t SprinklerValveOperator::run_duration() { return this->run_duration_ / 1000; } uint32_t SprinklerValveOperator::time_remaining() { - if (this->start_millis_ == 0) { + if (!this->start_millis_.has_value()) { return this->run_duration(); // hasn't been started yet } - if (this->stop_millis_) { - if (this->stop_millis_ - this->start_millis_ >= this->start_delay_ + this->run_duration_) { + if (this->stop_millis_.has_value()) { + uint32_t elapsed = *this->stop_millis_ - *this->start_millis_; + if (elapsed >= this->start_delay_ + this->run_duration_) { return 0; // valve was active for more than its configured duration, so we are done - } else { - // we're stopped; return time remaining - return (this->run_duration_ - (this->stop_millis_ - this->start_millis_)) / 1000; } + if (elapsed <= this->start_delay_) { + return this->run_duration_ / 1000; // stopped during start delay, full run duration remains + } + return (this->run_duration_ - (elapsed - this->start_delay_)) / 1000; } - auto completed_millis = this->start_millis_ + this->start_delay_ + this->run_duration_; - if (completed_millis > millis()) { - return (completed_millis - millis()) / 1000; // running now + uint32_t elapsed = millis() - *this->start_millis_; + uint32_t total_duration = this->start_delay_ + this->run_duration_; + if (elapsed < total_duration) { + return (total_duration - elapsed) / 1000; // running now } return 0; // run completed } @@ -593,7 +594,7 @@ void Sprinkler::set_repeat(optional<uint32_t> repeat) { if (this->repeat_number_ == nullptr) { return; } - if (this->repeat_number_->state == repeat.value()) { + if (this->repeat_number_->state == repeat.value_or(0)) { return; } auto call = this->repeat_number_->make_call(); @@ -793,7 +794,7 @@ void Sprinkler::start_single_valve(const optional<size_t> valve_number, optional void Sprinkler::queue_valve(optional<size_t> valve_number, optional<uint32_t> run_duration) { if (valve_number.has_value()) { if (this->is_a_valid_valve(valve_number.value()) && (this->queued_valves_.size() < this->max_queue_size_)) { - SprinklerQueueItem item{valve_number.value(), run_duration.value()}; + SprinklerQueueItem item{valve_number.value(), run_duration.value_or(0)}; this->queued_valves_.insert(this->queued_valves_.begin(), item); ESP_LOGD(TAG, "Valve %zu placed into queue with run duration of %" PRIu32 " seconds", valve_number.value_or(0), run_duration.value_or(0)); @@ -1080,7 +1081,7 @@ uint32_t Sprinkler::total_cycle_time_enabled_incomplete_valves() { } } - if (incomplete_valve_count >= enabled_valve_count) { + if (incomplete_valve_count > 0 && incomplete_valve_count >= enabled_valve_count) { incomplete_valve_count--; } if (incomplete_valve_count) { diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index a3cdef5b1a..2598a5606a 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -141,8 +141,8 @@ class SprinklerValveOperator { uint32_t start_delay_{0}; uint32_t stop_delay_{0}; uint32_t run_duration_{0}; - uint64_t start_millis_{0}; - uint64_t stop_millis_{0}; + optional<uint32_t> start_millis_{}; + optional<uint32_t> stop_millis_{}; Sprinkler *controller_{nullptr}; SprinklerValve *valve_{nullptr}; SprinklerState state_{IDLE}; From a05d0202e696b5498787b3b895acd71915844ac5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 09:21:27 -0700 Subject: [PATCH 0959/2030] [core] ESP32: massively reduce main loop socket polling overhead by replacing select() (#14249) --- esphome/components/socket/__init__.py | 8 +- esphome/components/socket/socket.h | 2 +- esphome/core/application.cpp | 102 ++++++--- esphome/core/application.h | 47 ++-- esphome/core/lwip_fast_select.c | 216 ++++++++++++++++++ esphome/core/lwip_fast_select.h | 33 +++ .../socket/test_wake_loop_threadsafe.py | 39 ++++ 7 files changed, 397 insertions(+), 50 deletions(-) create mode 100644 esphome/core/lwip_fast_select.c create mode 100644 esphome/core/lwip_fast_select.h diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index d82f0c7aba..5f4d04eb44 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -134,6 +134,8 @@ def require_wake_loop_threadsafe() -> None: IMPORTANT: This is for background thread context only, NOT ISR context. Socket operations are not safe to call from ISR handlers. + On ESP32, FreeRTOS task notifications are used instead (no socket needed). + Example: from esphome.components import socket @@ -147,8 +149,10 @@ def require_wake_loop_threadsafe() -> None: ): CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True cg.add_define("USE_WAKE_LOOP_THREADSAFE") - # Consume 1 socket for the shared wake notification socket - consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({}) + if not CORE.is_esp32: + # Only non-ESP32 platforms need a UDP socket for wake notifications. + # ESP32 uses FreeRTOS task notifications instead (no socket needed). + consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({}) CONFIG_SCHEMA = cv.Schema( diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index c0098d689a..a771e2fe1a 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -71,7 +71,7 @@ class Socket { int get_fd() const { return -1; } #endif - /// Check if socket has data ready to read + /// Check if socket has data ready to read. Must only be called from the main loop thread. /// For select()-based sockets: non-virtual, checks Application's select() results /// For LWIP raw TCP sockets: virtual, checks internal buffer state #ifdef USE_SOCKET_SELECT_SUPPORT diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 6a7683a987..fd6a14b50f 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -9,6 +9,9 @@ #endif #ifdef USE_ESP32 #include <esp_chip_info.h> +#include "esphome/core/lwip_fast_select.h" +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> #endif #include "esphome/core/version.h" #include "esphome/core/hal.h" @@ -144,8 +147,14 @@ void Application::setup() { clear_setup_priority_overrides(); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - // Set up wake socket for waking main loop from tasks +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_ESP32) + // Initialize fast select: saves main loop task handle for xTaskNotifyGive wake. + // Always init on ESP32 — the fast path (rcvevent reads + ulTaskNotifyTake) is used + // unconditionally when USE_SOCKET_SELECT_SUPPORT is enabled. + esphome_lwip_fast_select_init(); +#endif +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) + // Set up wake socket for waking main loop from tasks (non-ESP32 only) this->setup_wake_loop_threadsafe_(); #endif @@ -523,7 +532,7 @@ void Application::enable_pending_loops_() { } void Application::before_loop_tasks_(uint32_t loop_start_time) { -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) // Drain wake notifications first to clear socket for next wake this->drain_wake_notifications_(); #endif @@ -576,11 +585,15 @@ bool Application::register_socket_fd(int fd) { #endif this->socket_fds_.push_back(fd); +#ifdef USE_ESP32 + // Hook the socket's netconn callback for instant wake on receive events + esphome_lwip_hook_socket(fd); +#else this->socket_fds_changed_ = true; - if (fd > this->max_fd_) { this->max_fd_ = fd; } +#endif return true; } @@ -595,12 +608,14 @@ void Application::unregister_socket_fd(int fd) { if (this->socket_fds_[i] != fd) continue; - // Swap with last element and pop - O(1) removal since order doesn't matter + // Swap with last element and pop - O(1) removal since order doesn't matter. + // No need to unhook the netconn callback on ESP32 — all LwIP sockets share + // the same static event_callback, and the socket will be closed by the caller. if (i < this->socket_fds_.size() - 1) this->socket_fds_[i] = this->socket_fds_.back(); this->socket_fds_.pop_back(); +#ifndef USE_ESP32 this->socket_fds_changed_ = true; - // Only recalculate max_fd if we removed the current max if (fd == this->max_fd_) { this->max_fd_ = -1; @@ -609,6 +624,7 @@ void Application::unregister_socket_fd(int fd) { this->max_fd_ = sock_fd; } } +#endif return; } } @@ -616,16 +632,41 @@ void Application::unregister_socket_fd(int fd) { #endif void Application::yield_with_select_(uint32_t delay_ms) { - // Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run - // since select() with 0 timeout only polls without yielding. -#ifdef USE_SOCKET_SELECT_SUPPORT - if (!this->socket_fds_.empty()) { + // Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run. +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_ESP32) + // ESP32 fast path: reads rcvevent directly via lwip_socket_dbg_get_socket() (~215 ns per socket). + // Safe because this runs on the main loop which owns socket lifetime (create, read, close). + if (delay_ms == 0) [[unlikely]] { + yield(); + return; + } + + // Check if any socket already has pending data before sleeping. + // If a socket still has unread data (rcvevent > 0) but the task notification was already + // consumed, ulTaskNotifyTake would block until timeout — adding up to delay_ms latency. + // This scan preserves select() semantics: return immediately when any fd is ready. + for (int fd : this->socket_fds_) { + if (esphome_lwip_socket_has_data(fd)) { + yield(); + return; + } + } + + // Sleep with instant wake via FreeRTOS task notification. + // Woken by: callback wrapper (socket data arrives), wake_loop_threadsafe() (other tasks), or timeout. + // Without USE_WAKE_LOOP_THREADSAFE, only hooked socket callbacks wake the task — + // background tasks won't call wake, so this degrades to a pure timeout (same as old select path). + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(delay_ms)); + +#elif defined(USE_SOCKET_SELECT_SUPPORT) + // Non-ESP32 select() path (LibreTiny bk72xx/rtl87xx, host platform). + // ESP32 is excluded by the #if above — both BSD_SOCKETS and LWIP_SOCKETS on ESP32 + // use LwIP under the hood, so the fast path handles all ESP32 socket implementations. + if (!this->socket_fds_.empty()) [[likely]] { // Update fd_set if socket list has changed - if (this->socket_fds_changed_) { + if (this->socket_fds_changed_) [[unlikely]] { FD_ZERO(&this->base_read_fds_); - // fd bounds are already validated in register_socket_fd() or guaranteed by platform design: - // - ESP32: LwIP guarantees fd < FD_SETSIZE by design (LWIP_SOCKET_OFFSET = FD_SETSIZE - CONFIG_LWIP_MAX_SOCKETS) - // - Other platforms: register_socket_fd() validates fd < FD_SETSIZE + // fd bounds are validated in register_socket_fd() for (int fd : this->socket_fds_) { FD_SET(fd, &this->base_read_fds_); } @@ -641,7 +682,7 @@ void Application::yield_with_select_(uint32_t delay_ms) { tv.tv_usec = (delay_ms - tv.tv_sec * 1000) * 1000; // Call select with timeout -#if defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || (defined(USE_ESP32) && defined(USE_SOCKET_IMPL_BSD_SOCKETS)) +#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS int ret = lwip_select(this->max_fd_ + 1, &this->read_fds_, nullptr, nullptr, &tv); #else int ret = ::select(this->max_fd_ + 1, &this->read_fds_, nullptr, nullptr, &tv); @@ -651,19 +692,18 @@ void Application::yield_with_select_(uint32_t delay_ms) { // ret < 0: error (except EINTR which is normal) // ret > 0: socket(s) have data ready - normal and expected // ret == 0: timeout occurred - normal and expected - if (ret < 0 && errno != EINTR) { - // Actual error - log and fall back to delay - ESP_LOGW(TAG, "select() failed with errno %d", errno); - delay(delay_ms); + if (ret >= 0 || errno == EINTR) [[likely]] { + // Yield if zero timeout since select(0) only polls without yielding + if (delay_ms == 0) [[unlikely]] { + yield(); + } + return; } - // When delay_ms is 0, we need to yield since select(0) doesn't yield - if (delay_ms == 0) { - yield(); - } - } else { - // No sockets registered, use regular delay - delay(delay_ms); + // select() error - log and fall through to delay() + ESP_LOGW(TAG, "select() failed with errno %d", errno); } + // No sockets registered or select() failed - use regular delay + delay(delay_ms); #elif defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) // No select support but can wake on socket activity via esp_schedule() socket::socket_delay(delay_ms); @@ -676,6 +716,14 @@ void Application::yield_with_select_(uint32_t delay_ms) { Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + +#ifdef USE_ESP32 +void Application::wake_loop_threadsafe() { + // Direct FreeRTOS task notification — <1 us, task context only (NOT ISR-safe) + esphome_lwip_wake_main_loop(); +} +#else // !USE_ESP32 + void Application::setup_wake_loop_threadsafe_() { // Create UDP socket for wake notifications this->wake_socket_fd_ = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); @@ -742,6 +790,8 @@ void Application::wake_loop_threadsafe() { lwip_send(this->wake_socket_fd_, &dummy, 1, 0); } } +#endif // USE_ESP32 + #endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) void Application::get_build_time_string(std::span<char, BUILD_TIME_STR_SIZE> buffer) { diff --git a/esphome/core/application.h b/esphome/core/application.h index cd275bb97f..f5df5e7bdf 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -24,10 +24,14 @@ #endif #ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_ESP32 +#include "esphome/core/lwip_fast_select.h" +#else #include <sys/select.h> #ifdef USE_WAKE_LOOP_THREADSAFE #include <lwip/sockets.h> #endif +#endif #endif // USE_SOCKET_SELECT_SUPPORT #ifdef USE_BINARY_SENSOR @@ -491,15 +495,12 @@ class Application { /// @return true if registration was successful, false if fd exceeds limits bool register_socket_fd(int fd); void unregister_socket_fd(int fd); - /// Check if there's data available on a socket without blocking - /// This function is thread-safe for reading, but should be called after select() has run - /// The read_fds_ is only modified by select() in the main loop - bool is_socket_ready(int fd) const { return fd >= 0 && this->is_socket_ready_(fd); } #ifdef USE_WAKE_LOOP_THREADSAFE - /// Wake the main event loop from a FreeRTOS task - /// Thread-safe, can be called from task context to immediately wake select() - /// IMPORTANT: NOT safe to call from ISR context (socket operations not ISR-safe) + /// Wake the main event loop from another FreeRTOS task. + /// Thread-safe, but must only be called from task context (NOT ISR-safe). + /// On ESP32: uses xTaskNotifyGive (<1 us) + /// On other platforms: uses UDP loopback socket void wake_loop_threadsafe(); #endif #endif @@ -510,10 +511,14 @@ class Application { #ifdef USE_SOCKET_SELECT_SUPPORT /// Fast path for Socket::ready() via friendship - skips negative fd check. - /// Safe because: fd was validated in register_socket_fd() at registration time, - /// and Socket::ready() only calls this when loop_monitored_ is true (registration succeeded). - /// FD_ISSET may include its own upper bounds check depending on platform. + /// Main loop only — on ESP32, reads rcvevent via lwip_socket_dbg_get_socket() + /// which has no refcount; safe only because the main loop owns socket lifetime + /// (creates, reads, and closes sockets on the same thread). +#ifdef USE_ESP32 + bool is_socket_ready_(int fd) const { return esphome_lwip_socket_has_data(fd); } +#else bool is_socket_ready_(int fd) const { return FD_ISSET(fd, &this->read_fds_); } +#endif #endif void register_component_(Component *comp); @@ -541,7 +546,7 @@ class Application { /// Perform a delay while also monitoring socket file descriptors for readiness void yield_with_select_(uint32_t delay_ms); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) void setup_wake_loop_threadsafe_(); // Create wake notification socket inline void drain_wake_notifications_(); // Read pending wake notifications in main loop (hot path - inlined) #endif @@ -571,7 +576,7 @@ class Application { FixedVector<Component *> looping_components_{}; #ifdef USE_SOCKET_SELECT_SUPPORT std::vector<int> socket_fds_; // Vector of all monitored socket file descriptors -#ifdef USE_WAKE_LOOP_THREADSAFE +#if defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) int wake_socket_fd_{-1}; // Shared wake notification socket for waking main loop from tasks #endif #endif @@ -584,7 +589,7 @@ class Application { uint32_t last_loop_{0}; uint32_t loop_component_start_time_{0}; -#ifdef USE_SOCKET_SELECT_SUPPORT +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) int max_fd_{-1}; // Highest file descriptor number for select() #endif @@ -600,14 +605,14 @@ class Application { bool in_loop_{false}; volatile bool has_pending_enable_loop_requests_{false}; -#ifdef USE_SOCKET_SELECT_SUPPORT +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) bool socket_fds_changed_{false}; // Flag to rebuild base_read_fds_ when socket_fds_ changes #endif -#ifdef USE_SOCKET_SELECT_SUPPORT - // Variable-sized members +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) + // Variable-sized members (not needed on ESP32 — is_socket_ready_ reads rcvevent directly) + fd_set read_fds_{}; // Working fd_set: populated by select() fd_set base_read_fds_{}; // Cached fd_set rebuilt only when socket_fds_ changes - fd_set read_fds_{}; // Working fd_set for select(), copied from base_read_fds_ #endif // StaticVectors (largest members - contain actual array data inline) @@ -694,7 +699,7 @@ class Application { /// Global storage of Application pointer - only one Application can exist. extern Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) // Inline implementations for hot-path functions // drain_wake_notifications_() is called on every loop iteration @@ -704,8 +709,8 @@ static constexpr size_t WAKE_NOTIFY_DRAIN_BUFFER_SIZE = 16; inline void Application::drain_wake_notifications_() { // Called from main loop to drain any pending wake notifications - // Must check is_socket_ready() to avoid blocking on empty socket - if (this->wake_socket_fd_ >= 0 && this->is_socket_ready(this->wake_socket_fd_)) { + // Must check is_socket_ready_() to avoid blocking on empty socket + if (this->wake_socket_fd_ >= 0 && this->is_socket_ready_(this->wake_socket_fd_)) { char buffer[WAKE_NOTIFY_DRAIN_BUFFER_SIZE]; // Drain all pending notifications with non-blocking reads // Multiple wake events may have triggered multiple writes, so drain until EWOULDBLOCK @@ -716,6 +721,6 @@ inline void Application::drain_wake_notifications_() { } } } -#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) +#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) } // namespace esphome diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c new file mode 100644 index 0000000000..70a6482d48 --- /dev/null +++ b/esphome/core/lwip_fast_select.c @@ -0,0 +1,216 @@ +// Fast socket monitoring for ESP32 (ESP-IDF LwIP) +// Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications. +// +// This must be a .c file (not .cpp) because: +// 1. lwip/priv/sockets_priv.h conflicts with C++ compilation units that include bootloader headers +// 2. The netconn callback is a C function pointer +// +// defines.h is force-included by the build system (-include flag), providing USE_ESP32 etc. +// +// Thread safety analysis +// ====================== +// Three threads interact with this code: +// 1. Main loop task — calls init, has_data, hook +// 2. LwIP TCP/IP task — calls event_callback (reads s_original_callback; writes rcvevent +// via the original callback under SYS_ARCH_PROTECT/UNPROTECT mutex) +// 3. Background tasks — call wake_main_loop +// +// LwIP source references (ESP-IDF v5.5.2, commit 30aaf64524): +// sockets.c: https://github.com/espressif/esp-idf/blob/30aaf64524/components/lwip/lwip/src/api/sockets.c +// - event_callback (static, same for all sockets): L327 +// - DEFAULT_SOCKET_EVENTCB = event_callback: L328 +// - tryget_socket_unconn_nouse (direct array lookup): L450 +// - lwip_socket_dbg_get_socket (thin wrapper): L461 +// - All socket types use DEFAULT_SOCKET_EVENTCB: L1741, L1748, L1759 +// - event_callback definition: L2538 +// - SYS_ARCH_PROTECT before rcvevent switch: L2578 +// - sock->rcvevent++ (NETCONN_EVT_RCVPLUS case): L2582 +// - SYS_ARCH_UNPROTECT after switch: L2615 +// sys.h: https://github.com/espressif/esp-idf/blob/30aaf64524/components/lwip/lwip/src/include/lwip/sys.h +// - SYS_ARCH_PROTECT calls sys_arch_protect(): L495 +// - SYS_ARCH_UNPROTECT calls sys_arch_unprotect(): L506 +// (ESP-IDF implements sys_arch_protect/unprotect as FreeRTOS mutex lock/unlock) +// +// Socket slot lifetime +// ==================== +// This code reads struct lwip_sock fields without SYS_ARCH_PROTECT. The safety +// argument requires that the slot cannot be freed while we read it. +// +// In LwIP, the socket table is a static array and slots are only freed via: +// lwip_close() -> lwip_close_internal() -> free_socket_free_elements() -> free_socket() +// The TCP/IP thread does NOT call free_socket(). On link loss, RST, or timeout +// it frees the TCP PCB and signals the netconn (rcvevent++ to indicate EOF), but +// the netconn and lwip_sock slot remain allocated until the application calls +// lwip_close(). ESPHome removes the fd from the monitored set before calling +// lwip_close(). +// +// Therefore lwip_socket_dbg_get_socket(fd) plus a volatile read of rcvevent +// (to prevent compiler reordering or caching) is safe as long as the application +// is single-writer for close. ESPHome guarantees this by design: all socket +// create/read/close happens on the main loop. fd numbers are not reused while +// the slot remains allocated, and the slot remains allocated until lwip_close(). +// Any change in LwIP that allows free_socket() to be called outside lwip_close() +// would invalidate this assumption. +// +// LwIP source references for slot lifetime: +// sockets.c (same commit as above): +// - alloc_socket (slot allocation): L419 +// - free_socket (slot deallocation): L384 +// - free_socket_free_elements (called from lwip_close_internal): L393 +// - lwip_close_internal (only caller of free_socket_free_elements): L2355 +// - lwip_close (only caller of lwip_close_internal): L2450 +// +// Shared state and safety rationale: +// +// s_main_loop_task (TaskHandle_t, 4 bytes): +// Written once by main loop in init(). Read by TCP/IP thread (in callback) +// and background tasks (in wake). +// Safe: write-once-then-read pattern. Socket hooks may run before init(), +// but the NULL check on s_main_loop_task in the callback provides correct +// degraded behavior — notifications are simply skipped until init() completes. +// +// s_original_callback (netconn_callback, 4-byte function pointer): +// Written by main loop in hook_socket() (only when NULL — set once). +// Read by TCP/IP thread in esphome_socket_event_callback(). +// Safe: set-once pattern. The first hook_socket() captures the original callback. +// All subsequent hooks see it already set and skip the write. The TCP/IP thread +// only reads this after the callback pointer has been swapped (which happens after +// the write), so it always sees the initialized value. +// +// sock->conn->callback (netconn_callback, 4-byte function pointer): +// Written by main loop in hook_socket(). Never restored — all LwIP sockets share +// the same static event_callback (DEFAULT_SOCKET_EVENTCB), so the wrapper stays permanently. +// Read by TCP/IP thread when invoking the callback. +// Safe: 32-bit aligned pointer writes are atomic on Xtensa and RISC-V (ESP32). +// The TCP/IP thread will see either the old or new pointer atomically — never a +// torn value. Both the wrapper and original callbacks are valid at all times +// (the wrapper itself calls the original), so either value is correct. +// +// sock->rcvevent (s16_t, 2 bytes): +// Written by TCP/IP thread in event_callback under SYS_ARCH_PROTECT. +// Read by main loop in has_data() via volatile cast. +// Safe: SYS_ARCH_UNPROTECT releases a FreeRTOS mutex, which internally +// uses a critical section with memory barrier (rsync on dual-core Xtensa; on +// single-core builds the spinlock is compiled out, but cross-core visibility is +// not an issue). The volatile cast prevents the compiler +// from caching the read. Aligned 16-bit reads are single-instruction loads on +// Xtensa (L16SI) and RISC-V (LH), which cannot produce torn values. +// +// FreeRTOS task notification value: +// Written by TCP/IP thread (xTaskNotifyGive in callback) and background tasks +// (xTaskNotifyGive in wake_main_loop). Read by main loop (ulTaskNotifyTake). +// Safe: FreeRTOS notification APIs are thread-safe by design (use internal +// critical sections). Multiple concurrent xTaskNotifyGive calls are safe — +// the notification count simply increments. + +#ifdef USE_ESP32 + +// LwIP headers must come first — they define netconn_callback, struct lwip_sock, etc. +#include <lwip/api.h> +#include <lwip/priv/sockets_priv.h> +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> + +#include "esphome/core/lwip_fast_select.h" + +#include <stddef.h> + +// Compile-time verification of thread safety assumptions. +// On ESP32 (Xtensa/RISC-V), naturally-aligned reads/writes up to 32 bits are atomic. +// These asserts ensure our cross-thread shared state meets those requirements. + +// Pointer types must fit in a single 32-bit store (atomic write) +_Static_assert(sizeof(TaskHandle_t) <= 4, "TaskHandle_t must be <= 4 bytes for atomic access"); +_Static_assert(sizeof(netconn_callback) <= 4, "netconn_callback must be <= 4 bytes for atomic access"); + +// rcvevent must fit in a single atomic read +_Static_assert(sizeof(((struct lwip_sock *) 0)->rcvevent) <= 4, "rcvevent must be <= 4 bytes for atomic access"); + +// Struct member alignment — natural alignment guarantees atomicity on Xtensa/RISC-V. +// Misaligned access would not be atomic even if the size is <= 4 bytes. +_Static_assert(offsetof(struct netconn, callback) % sizeof(netconn_callback) == 0, + "netconn.callback must be naturally aligned for atomic access"); +_Static_assert(offsetof(struct lwip_sock, rcvevent) % sizeof(((struct lwip_sock *) 0)->rcvevent) == 0, + "lwip_sock.rcvevent must be naturally aligned for atomic access"); + +// Task handle for the main loop — written once in init(), read from TCP/IP and background tasks. +static TaskHandle_t s_main_loop_task = NULL; + +// Saved original event_callback pointer — written once in first hook_socket(), read from TCP/IP task. +static netconn_callback s_original_callback = NULL; + +// Wrapper callback: calls original event_callback + notifies main loop task. +// Called from LwIP's TCP/IP thread when socket events occur (task context, not ISR). +static void esphome_socket_event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) { + // Call original LwIP event_callback first — updates rcvevent/sendevent/errevent, + // signals any select() waiters. This preserves all LwIP behavior. + // s_original_callback is always valid here: hook_socket() sets it before swapping + // the callback pointer, so this wrapper cannot run until it's initialized. + s_original_callback(conn, evt, len); + // Wake the main loop task if sleeping in ulTaskNotifyTake(). + // Only notify on receive events to avoid spurious wakeups from send-ready events. + // NETCONN_EVT_ERROR is deliberately omitted: LwIP signals errors via RCVPLUS + // (rcvevent++ with a NULL pbuf or error in recvmbox), so error conditions + // already wake the main loop through the RCVPLUS path. + if (evt == NETCONN_EVT_RCVPLUS) { + TaskHandle_t task = s_main_loop_task; + if (task != NULL) { + xTaskNotifyGive(task); + } + } +} + +void esphome_lwip_fast_select_init(void) { s_main_loop_task = xTaskGetCurrentTaskHandle(); } + +// lwip_socket_dbg_get_socket() is a thin wrapper around the static +// tryget_socket_unconn_nouse() — a direct array lookup without the refcount +// that get_socket()/done_socket() uses. This is safe because: +// 1. The only path to free_socket() is lwip_close(), called exclusively from the main loop +// 2. The TCP/IP thread never frees socket slots (see "Socket slot lifetime" above) +// 3. Both has_data() reads and lwip_close() run on the main loop — no concurrent free +// If lwip_socket_dbg_get_socket() were ever removed, we could fall back to lwip_select(). +// Returns the sock only if both the sock and its netconn are valid, NULL otherwise. +static inline struct lwip_sock *get_sock(int fd) { + struct lwip_sock *sock = lwip_socket_dbg_get_socket(fd); + if (sock == NULL || sock->conn == NULL) + return NULL; + return sock; +} + +bool esphome_lwip_socket_has_data(int fd) { + struct lwip_sock *sock = get_sock(fd); + if (sock == NULL) + return false; + // volatile prevents the compiler from caching/reordering this cross-thread read. + // The write side (TCP/IP thread) commits via SYS_ARCH_UNPROTECT which releases a + // FreeRTOS mutex with a memory barrier (rsync on Xtensa), ensuring the value is + // visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH) on + // Xtensa/RISC-V and cannot produce torn values. + return *(volatile s16_t *) &sock->rcvevent > 0; +} + +void esphome_lwip_hook_socket(int fd) { + struct lwip_sock *sock = get_sock(fd); + if (sock == NULL) + return; + + // Save original callback once — all LwIP sockets share the same static event_callback + // (DEFAULT_SOCKET_EVENTCB in sockets.c, used for SOCK_RAW, SOCK_DGRAM, and SOCK_STREAM). + if (s_original_callback == NULL) { + s_original_callback = sock->conn->callback; + } + + // Replace with our wrapper. Atomic on ESP32 (32-bit aligned pointer write). + // TCP/IP thread sees either old or new pointer — both are valid. + sock->conn->callback = esphome_socket_event_callback; +} + +// Wake the main loop from another FreeRTOS task. NOT ISR-safe. +void esphome_lwip_wake_main_loop(void) { + TaskHandle_t task = s_main_loop_task; + if (task != NULL) { + xTaskNotifyGive(task); + } +} + +#endif // USE_ESP32 diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h new file mode 100644 index 0000000000..73a89fdc3d --- /dev/null +++ b/esphome/core/lwip_fast_select.h @@ -0,0 +1,33 @@ +#pragma once + +// Fast socket monitoring for ESP32 (ESP-IDF LwIP) +// Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications. + +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/// Initialize fast select — must be called from the main loop task during setup(). +/// Saves the current task handle for xTaskNotifyGive() wake notifications. +void esphome_lwip_fast_select_init(void); + +/// Check if a LwIP socket has data ready via direct rcvevent read (~215 ns per socket). +/// Uses lwip_socket_dbg_get_socket() — a direct array lookup without the refcount that +/// get_socket()/done_socket() uses. Safe because the caller owns the socket lifetime: +/// both has_data reads and socket close/unregister happen on the main loop thread. +bool esphome_lwip_socket_has_data(int fd); + +/// Hook a socket's netconn callback to notify the main loop task on receive events. +/// Wraps the original event_callback with one that also calls xTaskNotifyGive(). +/// Must be called from the main loop after socket creation. +void esphome_lwip_hook_socket(int fd); + +/// Wake the main loop task from another FreeRTOS task — costs <1 us. +/// NOT ISR-safe — must only be called from task context. +void esphome_lwip_wake_main_loop(void); + +#ifdef __cplusplus +} +#endif diff --git a/tests/components/socket/test_wake_loop_threadsafe.py b/tests/components/socket/test_wake_loop_threadsafe.py index a40b6068a8..28b4ee564f 100644 --- a/tests/components/socket/test_wake_loop_threadsafe.py +++ b/tests/components/socket/test_wake_loop_threadsafe.py @@ -1,9 +1,21 @@ from esphome.components import socket +from esphome.const import ( + KEY_CORE, + KEY_TARGET_PLATFORM, + PLATFORM_ESP32, + PLATFORM_ESP8266, +) from esphome.core import CORE +def _setup_platform(platform=PLATFORM_ESP8266) -> None: + """Set up CORE.data with a platform for testing.""" + CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: platform} + + def test_require_wake_loop_threadsafe__first_call() -> None: """Test that first call sets up define and consumes socket.""" + _setup_platform() CORE.config = {"wifi": True} socket.require_wake_loop_threadsafe() @@ -32,6 +44,7 @@ def test_require_wake_loop_threadsafe__idempotent() -> None: def test_require_wake_loop_threadsafe__multiple_calls() -> None: """Test that multiple calls only set up once.""" + _setup_platform() # Call three times CORE.config = {"openthread": True} socket.require_wake_loop_threadsafe() @@ -75,3 +88,29 @@ def test_require_wake_loop_threadsafe__no_networking_does_not_consume_socket() - udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) assert "socket.wake_loop_threadsafe" not in udp_consumers assert udp_consumers == initial_udp + + +def test_require_wake_loop_threadsafe__esp32_no_udp_socket() -> None: + """Test that ESP32 uses task notifications instead of UDP socket.""" + _setup_platform(PLATFORM_ESP32) + CORE.config = {"wifi": True} + socket.require_wake_loop_threadsafe() + + # Verify the define was added + assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True + assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) + + # Verify no UDP socket was consumed (ESP32 uses FreeRTOS task notifications) + udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) + assert "socket.wake_loop_threadsafe" not in udp_consumers + + +def test_require_wake_loop_threadsafe__non_esp32_consumes_udp_socket() -> None: + """Test that non-ESP32 platforms consume a UDP socket for wake notifications.""" + _setup_platform(PLATFORM_ESP8266) + CORE.config = {"wifi": True} + socket.require_wake_loop_threadsafe() + + # Verify UDP socket was consumed + udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) + assert udp_consumers.get("socket.wake_loop_threadsafe") == 1 From be000eab4e0cb4f9eaa3807b069c143c4eeee5b6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 11:02:52 -0700 Subject: [PATCH 0960/2030] [ci] Add undocumented C++ API change checkbox and auto-label (#14317) --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++-- .github/scripts/auto-label-pr/constants.js | 1 + .github/scripts/auto-label-pr/detectors.js | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d1ef3bd822..965b186c31 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,8 +6,9 @@ - [ ] Bugfix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] Developer breaking change (an API change that could break external components) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) — [policy](https://developers.esphome.io/contributing/code/#what-constitutes-a-c-breaking-change) +- [ ] Developer breaking change (an API change that could break external components) — [policy](https://developers.esphome.io/contributing/code/#what-is-considered-public-c-api) +- [ ] Undocumented C++ API change (removal or change of undocumented public methods that lambda users may depend on) — [policy](https://developers.esphome.io/contributing/code/#c-user-expectations) - [ ] Code quality improvements to existing code or addition of tests - [ ] Other diff --git a/.github/scripts/auto-label-pr/constants.js b/.github/scripts/auto-label-pr/constants.js index bd60d8c766..8c3a62cf19 100644 --- a/.github/scripts/auto-label-pr/constants.js +++ b/.github/scripts/auto-label-pr/constants.js @@ -27,6 +27,7 @@ module.exports = { 'new-feature', 'breaking-change', 'developer-breaking-change', + 'undocumented-api-change', 'code-quality', 'deprecated-component' ], diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index f502a85666..a45a84f219 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -238,6 +238,7 @@ async function detectPRTemplateCheckboxes(context) { { pattern: /- \[x\] New feature \(non-breaking change which adds functionality\)/i, label: 'new-feature' }, { pattern: /- \[x\] Breaking change \(fix or feature that would cause existing functionality to not work as expected\)/i, label: 'breaking-change' }, { pattern: /- \[x\] Developer breaking change \(an API change that could break external components\)/i, label: 'developer-breaking-change' }, + { pattern: /- \[x\] Undocumented C\+\+ API change \(removal or change of undocumented public methods that lambda users may depend on\)/i, label: 'undocumented-api-change' }, { pattern: /- \[x\] Code quality improvements to existing code or addition of tests/i, label: 'code-quality' } ]; From ae16c3bae7450db7bba0b1c06755022e5b2696e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 11:25:36 -0700 Subject: [PATCH 0961/2030] Add socket compile tests for libretiny platforms (#14314) --- tests/components/socket/test.bk72xx-ard.yaml | 1 + tests/components/socket/test.ln882x-ard.yaml | 1 + tests/components/socket/test.rtl87xx-ard.yaml | 1 + 3 files changed, 3 insertions(+) create mode 100644 tests/components/socket/test.bk72xx-ard.yaml create mode 100644 tests/components/socket/test.ln882x-ard.yaml create mode 100644 tests/components/socket/test.rtl87xx-ard.yaml diff --git a/tests/components/socket/test.bk72xx-ard.yaml b/tests/components/socket/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/socket/test.bk72xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/socket/test.ln882x-ard.yaml b/tests/components/socket/test.ln882x-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/socket/test.ln882x-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/socket/test.rtl87xx-ard.yaml b/tests/components/socket/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/socket/test.rtl87xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 1912dcf03da6f0d1590f3708cf8ddad9b404ef04 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 12:07:42 -0700 Subject: [PATCH 0962/2030] [core] Use placement new for global Application instance (#14052) --- esphome/core/application.cpp | 10 +++++++++- esphome/core/config.py | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index fd6a14b50f..a9753da1b5 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -713,7 +713,15 @@ void Application::yield_with_select_(uint32_t delay_ms) { #endif } -Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +// App storage — asm label shares the linker symbol with "extern Application App". +// char[] is trivially destructible, so no __cxa_atexit or destructor chain is emitted. +// Constructed via placement new in the generated setup(). +#ifndef __GXX_ABI_VERSION +#error "Application placement new requires Itanium C++ ABI (GCC/Clang)" +#endif +static_assert(std::is_default_constructible<Application>::value, "Application must be default-constructible"); +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +alignas(Application) char app_storage[sizeof(Application)] asm("_ZN7esphome3AppE"); #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) diff --git a/esphome/core/config.py b/esphome/core/config.py index 21ed8ced1a..215432835a 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -512,6 +512,9 @@ async def to_code(config: ConfigType) -> None: cg.add_global(cg.RawExpression("using std::min")) cg.add_global(cg.RawExpression("using std::max")) + # Construct App via placement new — see application.cpp for storage details + cg.add_global(cg.RawStatement("#include <new>")) + cg.add(cg.RawExpression("new (&App) Application()")) cg.add( cg.App.pre_setup( config[CONF_NAME], From 4c3bb1596e876259f496cafc682dfb75e34d3089 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 12:14:46 -0700 Subject: [PATCH 0963/2030] [wifi] Use memcpy-based insertion sort for scan results (#13960) --- esphome/components/wifi/wifi_component.cpp | 50 ++++++++++++++++++++-- esphome/components/wifi/wifi_component.h | 9 ++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index d5d0419395..1e6961b8bd 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -3,6 +3,7 @@ #include <cassert> #include <cinttypes> #include <cmath> +#include <type_traits> #ifdef USE_ESP32 #if (ESP_IDF_VERSION_MAJOR >= 5 && ESP_IDF_VERSION_MINOR >= 1) @@ -1334,20 +1335,61 @@ void WiFiComponent::start_scanning() { // Using insertion sort instead of std::stable_sort saves flash memory // by avoiding template instantiations (std::rotate, std::stable_sort, lambdas) // IMPORTANT: This sort is stable (preserves relative order of equal elements) +// +// Uses raw memcpy instead of copy assignment to avoid CompactString's +// destructor/constructor overhead (heap delete[]/new[] for long SSIDs). +// Copy assignment calls ~CompactString() then placement-new for every shift, +// which means delete[]/new[] per shift for heap-allocated SSIDs. With 70+ +// networks (e.g., captive portal showing full scan results), this caused +// event loop blocking from hundreds of heap operations in a tight loop. +// +// This is safe because we're permuting elements within the same array — +// each slot is overwritten exactly once, so no ownership duplication occurs. +// All members of WiFiScanResult are either trivially copyable (bssid, channel, +// rssi, priority, flags) or CompactString, which stores either inline data or +// a heap pointer — never a self-referential pointer (unlike std::string's SSO +// on some implementations). This was not possible before PR#13472 replaced +// std::string with CompactString, since std::string's internal layout is +// implementation-defined and may use self-referential pointers. +// +// TODO: If C++ standardizes std::trivially_relocatable, add the assertion for +// WiFiScanResult/CompactString here to formally express the memcpy safety guarantee. template<typename VectorType> static void insertion_sort_scan_results(VectorType &results) { + // memcpy-based sort requires no self-referential pointers or virtual dispatch. + // These static_asserts guard the assumptions. If any fire, the memcpy sort + // must be reviewed for safety before updating the expected values. + // + // No vtable pointers (memcpy would corrupt vptr) + static_assert(!std::is_polymorphic<WiFiScanResult>::value, "WiFiScanResult must not have vtable"); + static_assert(!std::is_polymorphic<CompactString>::value, "CompactString must not have vtable"); + // Standard layout ensures predictable memory layout with no virtual bases + // and no mixed-access-specifier reordering + static_assert(std::is_standard_layout<WiFiScanResult>::value, "WiFiScanResult must be standard layout"); + static_assert(std::is_standard_layout<CompactString>::value, "CompactString must be standard layout"); + // Size checks catch added/removed fields that may need safety review + static_assert(sizeof(WiFiScanResult) == 32, "WiFiScanResult size changed - verify memcpy sort is still safe"); + static_assert(sizeof(CompactString) == 20, "CompactString size changed - verify memcpy sort is still safe"); + // Alignment must match for reinterpret_cast of key_buf to be valid + static_assert(alignof(WiFiScanResult) <= alignof(std::max_align_t), "WiFiScanResult alignment exceeds max_align_t"); const size_t size = results.size(); + constexpr size_t elem_size = sizeof(WiFiScanResult); + // Suppress warnings for intentional memcpy on non-trivially-copyable type. + // Safety is guaranteed by the static_asserts above and the permutation invariant. + // NOLINTNEXTLINE(bugprone-undefined-memory-manipulation) + auto *memcpy_fn = &memcpy; for (size_t i = 1; i < size; i++) { - // Make a copy to avoid issues with move semantics during comparison - WiFiScanResult key = results[i]; + alignas(WiFiScanResult) uint8_t key_buf[elem_size]; + memcpy_fn(key_buf, &results[i], elem_size); + const auto &key = *reinterpret_cast<const WiFiScanResult *>(key_buf); int32_t j = i - 1; // Move elements that are worse than key to the right // For stability, we only move if key is strictly better than results[j] while (j >= 0 && wifi_scan_result_is_better(key, results[j])) { - results[j + 1] = results[j]; + memcpy_fn(&results[j + 1], &results[j], elem_size); j--; } - results[j + 1] = key; + memcpy_fn(&results[j + 1], key_buf, elem_size); } } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 984930c80c..63c7039f21 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -10,6 +10,7 @@ #include <span> #include <string> +#include <type_traits> #include <vector> #ifdef USE_LIBRETINY @@ -223,6 +224,14 @@ class CompactString { }; static_assert(sizeof(CompactString) == 20, "CompactString must be exactly 20 bytes"); +// CompactString is not trivially copyable (non-trivial destructor/copy for heap case). +// However, its layout has no self-referential pointers: storage_[] contains either inline +// data or an external heap pointer — never a pointer to itself. This is unlike libstdc++ +// std::string SSO where _M_p points to _M_local_buf within the same object. +// This property allows memcpy-based permutation sorting where each element ends up in +// exactly one slot (no ownership duplication). These asserts document that layout property. +static_assert(std::is_standard_layout<CompactString>::value, "CompactString must be standard layout"); +static_assert(!std::is_polymorphic<CompactString>::value, "CompactString must not have vtable"); class WiFiAP { friend class WiFiComponent; From c149be20fcf8d2eecc8a4c518673f2bb8cc1bc42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:31:47 +0000 Subject: [PATCH 0964/2030] Bump aioesphomeapi from 44.1.0 to 44.2.0 (#14324) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d22097b3ca..95e3710f9e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.1.7 esphome-dashboard==20260210.0 -aioesphomeapi==44.1.0 +aioesphomeapi==44.2.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 8da1e3ce21de2e720294c1ff05d3021a07b0ddb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 19:32:53 +0000 Subject: [PATCH 0965/2030] Bump ruff from 0.15.2 to 0.15.3 (#14323) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 07d02e0e3c..d70dd9d0e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.2 + rev: v0.15.3 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 3e5dc8a90c..88a38ffa99 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.2 # also change in .pre-commit-config.yaml when updating +ruff==0.15.3 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From d325890148091a682c31185ccf1c5d3864e8c303 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:48:05 -0500 Subject: [PATCH 0966/2030] [cc1101] Transition through IDLE in begin_tx/begin_rx for reliable state changes (#14321) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/cc1101/cc1101.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/cc1101/cc1101.cpp b/esphome/components/cc1101/cc1101.cpp index b6973da78d..51aa88b8f7 100644 --- a/esphome/components/cc1101/cc1101.cpp +++ b/esphome/components/cc1101/cc1101.cpp @@ -242,6 +242,9 @@ void CC1101Component::begin_tx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_OUTPUT); } + // Transition through IDLE to bypass CCA (Clear Channel Assessment) which can + // block TX entry when strobing from RX, and to ensure FS_AUTOCAL calibration + this->enter_idle_(); if (!this->enter_tx_()) { ESP_LOGW(TAG, "Failed to enter TX state!"); } @@ -252,6 +255,8 @@ void CC1101Component::begin_rx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_INPUT); } + // Transition through IDLE to ensure FS_AUTOCAL calibration occurs + this->enter_idle_(); if (!this->enter_rx_()) { ESP_LOGW(TAG, "Failed to enter RX state!"); } From e8b45e53fd4020ecc65500e9df8c0c7145b4f1fe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 13:02:25 -0700 Subject: [PATCH 0967/2030] [libretiny] Use -Os optimization for ESPHome source on BK72xx (SDK remains at -O1) (#14322) --- esphome/components/libretiny/__init__.py | 10 +++++++++- esphome/components/libretiny/lt_component.cpp | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 2291114d9a..8f99124604 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -27,6 +27,7 @@ from esphome.storage_json import StorageJSON from . import gpio # noqa from .const import ( + COMPONENT_BK72XX, CONF_GPIO_RECOVER, CONF_LOGLEVEL, CONF_SDK_SILENT, @@ -453,7 +454,14 @@ async def component_to_code(config): cg.add_platformio_option("lib_ldf_mode", "off") cg.add_platformio_option("lib_compat_mode", "soft") # include <Arduino.h> in every file - cg.add_platformio_option("build_src_flags", "-include Arduino.h") + build_src_flags = "-include Arduino.h" + if FAMILY_COMPONENT[config[CONF_FAMILY]] == COMPONENT_BK72XX: + # LibreTiny forces -O1 globally for BK72xx because the Beken SDK + # has issues with higher optimization levels. However, ESPHome code + # works fine with -Os (used on every other platform), so override + # it for project source files only. GCC uses the last -O flag. + build_src_flags += " -Os" + cg.add_platformio_option("build_src_flags", build_src_flags) # dummy version code cg.add_define("USE_ARDUINO_VERSION_CODE", cg.RawExpression("VERSION_CODE(0, 0, 0)")) # decrease web server stack size (16k words -> 4k words) diff --git a/esphome/components/libretiny/lt_component.cpp b/esphome/components/libretiny/lt_component.cpp index ffccd0ad7a..834245c147 100644 --- a/esphome/components/libretiny/lt_component.cpp +++ b/esphome/components/libretiny/lt_component.cpp @@ -15,6 +15,9 @@ void LTComponent::dump_config() { " Version: %s\n" " Loglevel: %u", LT_BANNER_STR + 10, LT_LOGLEVEL); +#if defined(__OPTIMIZE_SIZE__) && __OPTIMIZE_LEVEL__ > 0 && __OPTIMIZE_LEVEL__ <= 3 + ESP_LOGCONFIG(TAG, " Optimization: -Os, SDK: -O" STRINGIFY_MACRO(__OPTIMIZE_LEVEL__)); +#endif #ifdef USE_TEXT_SENSOR if (this->version_ != nullptr) { From 08035261b85617b6b978336c8ca56629a86bb5cc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 13:02:36 -0700 Subject: [PATCH 0968/2030] [libretiny] Use C++17 nested namespace syntax (#14325) --- esphome/components/libretiny/core.h | 4 +--- esphome/components/libretiny/gpio_arduino.cpp | 7 ++++--- esphome/components/libretiny/gpio_arduino.h | 6 ++---- esphome/components/libretiny/lt_component.cpp | 6 ++---- esphome/components/libretiny/lt_component.h | 6 ++---- esphome/components/libretiny/preferences.cpp | 7 ++++--- esphome/components/libretiny/preferences.h | 6 ++---- 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/esphome/components/libretiny/core.h b/esphome/components/libretiny/core.h index 9458df1f16..f909db4f0f 100644 --- a/esphome/components/libretiny/core.h +++ b/esphome/components/libretiny/core.h @@ -4,8 +4,6 @@ #include <Arduino.h> -namespace esphome { -namespace libretiny {} // namespace libretiny -} // namespace esphome +namespace esphome::libretiny {} // namespace esphome::libretiny #endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/gpio_arduino.cpp b/esphome/components/libretiny/gpio_arduino.cpp index 0b14c77cf2..1af0dce16d 100644 --- a/esphome/components/libretiny/gpio_arduino.cpp +++ b/esphome/components/libretiny/gpio_arduino.cpp @@ -3,8 +3,7 @@ #include "gpio_arduino.h" #include "esphome/core/log.h" -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { static const char *const TAG = "lt.gpio"; @@ -77,7 +76,9 @@ void ArduinoInternalGPIOPin::detach_interrupt() const { detachInterrupt(pin_); // NOLINT } -} // namespace libretiny +} // namespace esphome::libretiny + +namespace esphome { using namespace libretiny; diff --git a/esphome/components/libretiny/gpio_arduino.h b/esphome/components/libretiny/gpio_arduino.h index 30c7c33869..5f1fa3fec7 100644 --- a/esphome/components/libretiny/gpio_arduino.h +++ b/esphome/components/libretiny/gpio_arduino.h @@ -3,8 +3,7 @@ #ifdef USE_LIBRETINY #include "esphome/core/hal.h" -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { class ArduinoInternalGPIOPin : public InternalGPIOPin { public: @@ -31,7 +30,6 @@ class ArduinoInternalGPIOPin : public InternalGPIOPin { gpio::Flags flags_{}; }; -} // namespace libretiny -} // namespace esphome +} // namespace esphome::libretiny #endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/lt_component.cpp b/esphome/components/libretiny/lt_component.cpp index 834245c147..c01661b3a6 100644 --- a/esphome/components/libretiny/lt_component.cpp +++ b/esphome/components/libretiny/lt_component.cpp @@ -4,8 +4,7 @@ #include "esphome/core/log.h" -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { static const char *const TAG = "lt.component"; @@ -28,7 +27,6 @@ void LTComponent::dump_config() { float LTComponent::get_setup_priority() const { return setup_priority::LATE; } -} // namespace libretiny -} // namespace esphome +} // namespace esphome::libretiny #endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/lt_component.h b/esphome/components/libretiny/lt_component.h index 3d4483ab5d..896f1901e3 100644 --- a/esphome/components/libretiny/lt_component.h +++ b/esphome/components/libretiny/lt_component.h @@ -12,8 +12,7 @@ #include "esphome/components/text_sensor/text_sensor.h" #endif -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { class LTComponent : public Component { public: @@ -30,7 +29,6 @@ class LTComponent : public Component { #endif // USE_TEXT_SENSOR }; -} // namespace libretiny -} // namespace esphome +} // namespace esphome::libretiny #endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 8549631e46..740c1a233a 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -8,8 +8,7 @@ #include <cstring> #include <memory> -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { static const char *const TAG = "lt.preferences"; @@ -194,7 +193,9 @@ void setup_preferences() { global_preferences = &s_preferences; } -} // namespace libretiny +} // namespace esphome::libretiny + +namespace esphome { ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/components/libretiny/preferences.h b/esphome/components/libretiny/preferences.h index 8ec3cd31b1..68f377bd3e 100644 --- a/esphome/components/libretiny/preferences.h +++ b/esphome/components/libretiny/preferences.h @@ -2,12 +2,10 @@ #ifdef USE_LIBRETINY -namespace esphome { -namespace libretiny { +namespace esphome::libretiny { void setup_preferences(); -} // namespace libretiny -} // namespace esphome +} // namespace esphome::libretiny #endif // USE_LIBRETINY From 54edc46c7f95ee35ec3c681276aa6a789fdeafdc Mon Sep 17 00:00:00 2001 From: Oliver Kleinecke <okleinecke@web.de> Date: Thu, 26 Feb 2026 21:12:52 +0100 Subject: [PATCH 0969/2030] [esp_ldo] Add channels 1&2 support and passthrough mode (#14177) --- esphome/components/esp_ldo/__init__.py | 67 ++++++++++++++++--- esphome/components/esp_ldo/esp_ldo.cpp | 20 +++--- esphome/components/esp_ldo/esp_ldo.h | 4 +- .../components/esp_ldo/test.esp32-p4-idf.yaml | 9 ++- 4 files changed, 75 insertions(+), 25 deletions(-) diff --git a/esphome/components/esp_ldo/__init__.py b/esphome/components/esp_ldo/__init__.py index f136dd149b..5235a9411e 100644 --- a/esphome/components/esp_ldo/__init__.py +++ b/esphome/components/esp_ldo/__init__.py @@ -13,22 +13,63 @@ esp_ldo_ns = cg.esphome_ns.namespace("esp_ldo") EspLdo = esp_ldo_ns.class_("EspLdo", cg.Component) AdjustAction = esp_ldo_ns.class_("AdjustAction", Action) -CHANNELS = (3, 4) +CHANNELS = (1, 2, 3, 4) +CHANNELS_INTERNAL = (1, 2) CONF_ADJUSTABLE = "adjustable" +CONF_ALLOW_INTERNAL_CHANNEL = "allow_internal_channel" +CONF_PASSTHROUGH = "passthrough" adjusted_ids = set() + +def validate_ldo_voltage(value): + if isinstance(value, str) and value.lower() == CONF_PASSTHROUGH: + return CONF_PASSTHROUGH + value = cv.voltage(value) + if 0.5 <= value <= 2.7: + return value + raise cv.Invalid( + f"LDO voltage must be in range 0.5V-2.7V or 'passthrough' (bypass mode), got {value}V" + ) + + +def validate_ldo_config(config): + channel = config[CONF_CHANNEL] + allow_internal = config[CONF_ALLOW_INTERNAL_CHANNEL] + if allow_internal and channel not in CHANNELS_INTERNAL: + raise cv.Invalid( + f"'{CONF_ALLOW_INTERNAL_CHANNEL}' is only valid for internal channels (1, 2). " + f"Channel {channel} is a user-configurable channel — its usage depends on your board schematic.", + path=[CONF_ALLOW_INTERNAL_CHANNEL], + ) + if channel in CHANNELS_INTERNAL and not allow_internal: + raise cv.Invalid( + f"LDO channel {channel} is normally used internally by the chip (flash/PSRAM). " + f"Set '{CONF_ALLOW_INTERNAL_CHANNEL}: true' to confirm you know what you are doing.", + path=[CONF_CHANNEL], + ) + if config[CONF_VOLTAGE] == CONF_PASSTHROUGH and config[CONF_ADJUSTABLE]: + raise cv.Invalid( + "Passthrough mode passes the supply voltage directly to the output and does not support " + "runtime voltage adjustment.", + path=[CONF_ADJUSTABLE], + ) + return config + + CONFIG_SCHEMA = cv.All( cv.ensure_list( - cv.COMPONENT_SCHEMA.extend( - { - cv.GenerateID(): cv.declare_id(EspLdo), - cv.Required(CONF_VOLTAGE): cv.All( - cv.voltage, cv.float_range(min=0.5, max=2.7) - ), - cv.Required(CONF_CHANNEL): cv.one_of(*CHANNELS, int=True), - cv.Optional(CONF_ADJUSTABLE, default=False): cv.boolean, - } + cv.All( + cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(EspLdo), + cv.Required(CONF_VOLTAGE): validate_ldo_voltage, + cv.Required(CONF_CHANNEL): cv.one_of(*CHANNELS, int=True), + cv.Optional(CONF_ADJUSTABLE, default=False): cv.boolean, + cv.Optional(CONF_ALLOW_INTERNAL_CHANNEL, default=False): cv.boolean, + } + ), + validate_ldo_config, ) ), cv.only_on_esp32, @@ -40,7 +81,11 @@ async def to_code(configs): for config in configs: var = cg.new_Pvariable(config[CONF_ID], config[CONF_CHANNEL]) await cg.register_component(var, config) - cg.add(var.set_voltage(config[CONF_VOLTAGE])) + voltage = config[CONF_VOLTAGE] + if voltage == CONF_PASSTHROUGH: + cg.add(var.set_voltage(3300)) + else: + cg.add(var.set_voltage(int(round(voltage * 1000)))) cg.add(var.set_adjustable(config[CONF_ADJUSTABLE])) diff --git a/esphome/components/esp_ldo/esp_ldo.cpp b/esphome/components/esp_ldo/esp_ldo.cpp index 2eee855b46..f8ebec1903 100644 --- a/esphome/components/esp_ldo/esp_ldo.cpp +++ b/esphome/components/esp_ldo/esp_ldo.cpp @@ -10,32 +10,34 @@ static const char *const TAG = "esp_ldo"; void EspLdo::setup() { esp_ldo_channel_config_t config{}; config.chan_id = this->channel_; - config.voltage_mv = (int) (this->voltage_ * 1000.0f); + config.voltage_mv = this->voltage_mv_; config.flags.adjustable = this->adjustable_; auto err = esp_ldo_acquire_channel(&config, &this->handle_); if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to acquire LDO channel %d with voltage %fV", this->channel_, this->voltage_); + ESP_LOGE(TAG, "Failed to acquire LDO channel %d with voltage %dmV", this->channel_, this->voltage_mv_); this->mark_failed(LOG_STR("Failed to acquire LDO channel")); } else { - ESP_LOGD(TAG, "Acquired LDO channel %d with voltage %fV", this->channel_, this->voltage_); + ESP_LOGD(TAG, "Acquired LDO channel %d with voltage %dmV", this->channel_, this->voltage_mv_); } } void EspLdo::dump_config() { ESP_LOGCONFIG(TAG, "ESP LDO Channel %d:\n" - " Voltage: %fV\n" + " Voltage: %dmV\n" " Adjustable: %s", - this->channel_, this->voltage_, YESNO(this->adjustable_)); + this->channel_, this->voltage_mv_, YESNO(this->adjustable_)); } void EspLdo::adjust_voltage(float voltage) { if (!std::isfinite(voltage) || voltage < 0.5f || voltage > 2.7f) { - ESP_LOGE(TAG, "Invalid voltage %fV for LDO channel %d", voltage, this->channel_); + ESP_LOGE(TAG, "Invalid voltage %fV for LDO channel %d (must be 0.5V-2.7V)", voltage, this->channel_); return; } - auto erro = esp_ldo_channel_adjust_voltage(this->handle_, (int) (voltage * 1000.0f)); - if (erro != ESP_OK) { - ESP_LOGE(TAG, "Failed to adjust LDO channel %d to voltage %fV: %s", this->channel_, voltage, esp_err_to_name(erro)); + int voltage_mv = (int) roundf(voltage * 1000.0f); + auto err = esp_ldo_channel_adjust_voltage(this->handle_, voltage_mv); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to adjust LDO channel %d to voltage %dmV: %s", this->channel_, voltage_mv, + esp_err_to_name(err)); } } diff --git a/esphome/components/esp_ldo/esp_ldo.h b/esphome/components/esp_ldo/esp_ldo.h index 9edd303e16..1a20f1d08a 100644 --- a/esphome/components/esp_ldo/esp_ldo.h +++ b/esphome/components/esp_ldo/esp_ldo.h @@ -15,7 +15,7 @@ class EspLdo : public Component { void dump_config() override; void set_adjustable(bool adjustable) { this->adjustable_ = adjustable; } - void set_voltage(float voltage) { this->voltage_ = voltage; } + void set_voltage(int voltage_mv) { this->voltage_mv_ = voltage_mv; } void adjust_voltage(float voltage); float get_setup_priority() const override { return setup_priority::BUS; // LDO setup should be done early @@ -23,7 +23,7 @@ class EspLdo : public Component { protected: int channel_; - float voltage_{2.7}; + int voltage_mv_{2700}; bool adjustable_{false}; esp_ldo_channel_handle_t handle_{}; }; diff --git a/tests/components/esp_ldo/test.esp32-p4-idf.yaml b/tests/components/esp_ldo/test.esp32-p4-idf.yaml index 38bd6ac411..31d2b8cf7a 100644 --- a/tests/components/esp_ldo/test.esp32-p4-idf.yaml +++ b/tests/components/esp_ldo/test.esp32-p4-idf.yaml @@ -3,10 +3,13 @@ esp_ldo: channel: 3 voltage: 2.5V adjustable: true - - id: ldo_4 + - id: ldo_4_passthrough channel: 4 - voltage: 2.0V - setup_priority: 900 + voltage: passthrough + - id: ldo_1_internal + channel: 1 + voltage: 1.8V + allow_internal_channel: true esphome: on_boot: From 8bd474fd017d31f4f8504f4c96db5a8e1a7f2f80 Mon Sep 17 00:00:00 2001 From: lyubomirtraykov <lyubomir.traykov@gmail.com> Date: Thu, 26 Feb 2026 22:27:18 +0200 Subject: [PATCH 0970/2030] [api] Add DEFROSTING to ClimateAction (#13976) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/api/api.proto | 1 + esphome/components/api/api_pb2.h | 1 + esphome/components/api/api_pb2_dump.cpp | 2 ++ esphome/components/climate/climate_mode.cpp | 6 ++++-- esphome/components/climate/climate_mode.h | 2 ++ esphome/components/mqtt/mqtt_climate.cpp | 5 +++-- 6 files changed, 13 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 18dac6a2d1..d7f32cd8d1 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -989,6 +989,7 @@ enum ClimateAction { CLIMATE_ACTION_IDLE = 4; CLIMATE_ACTION_DRYING = 5; CLIMATE_ACTION_FAN = 6; + CLIMATE_ACTION_DEFROSTING = 7; } enum ClimatePreset { CLIMATE_PRESET_NONE = 0; diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index c2675cefe4..22dc3de995 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -116,6 +116,7 @@ enum ClimateAction : uint32_t { CLIMATE_ACTION_IDLE = 4, CLIMATE_ACTION_DRYING = 5, CLIMATE_ACTION_FAN = 6, + CLIMATE_ACTION_DEFROSTING = 7, }; enum ClimatePreset : uint32_t { CLIMATE_PRESET_NONE = 0, diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 73690610ed..52d2486410 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -321,6 +321,8 @@ template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::Climate return "CLIMATE_ACTION_DRYING"; case enums::CLIMATE_ACTION_FAN: return "CLIMATE_ACTION_FAN"; + case enums::CLIMATE_ACTION_DEFROSTING: + return "CLIMATE_ACTION_DEFROSTING"; default: return "UNKNOWN"; } diff --git a/esphome/components/climate/climate_mode.cpp b/esphome/components/climate/climate_mode.cpp index c4dd19d503..8e443f4146 100644 --- a/esphome/components/climate/climate_mode.cpp +++ b/esphome/components/climate/climate_mode.cpp @@ -10,8 +10,10 @@ const LogString *climate_mode_to_string(ClimateMode mode) { return ClimateModeStrings::get_log_str(static_cast<uint8_t>(mode), ClimateModeStrings::LAST_INDEX); } -// Climate action strings indexed by ClimateAction enum (0,2-6): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN -PROGMEM_STRING_TABLE(ClimateActionStrings, "OFF", "UNKNOWN", "COOLING", "HEATING", "IDLE", "DRYING", "FAN", "UNKNOWN"); +// Climate action strings indexed by ClimateAction enum (0,2-7): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN, +// DEFROSTING +PROGMEM_STRING_TABLE(ClimateActionStrings, "OFF", "UNKNOWN", "COOLING", "HEATING", "IDLE", "DRYING", "FAN", + "DEFROSTING", "UNKNOWN"); const LogString *climate_action_to_string(ClimateAction action) { return ClimateActionStrings::get_log_str(static_cast<uint8_t>(action), ClimateActionStrings::LAST_INDEX); diff --git a/esphome/components/climate/climate_mode.h b/esphome/components/climate/climate_mode.h index c961c44248..014b1a9e64 100644 --- a/esphome/components/climate/climate_mode.h +++ b/esphome/components/climate/climate_mode.h @@ -41,6 +41,8 @@ enum ClimateAction : uint8_t { CLIMATE_ACTION_DRYING = 5, /// The climate device is in fan only mode CLIMATE_ACTION_FAN = 6, + /// The climate device is defrosting + CLIMATE_ACTION_DEFROSTING = 7, }; /// NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index 81b2e0e8db..443c983efe 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -20,9 +20,10 @@ static ProgmemStr climate_mode_to_mqtt_str(ClimateMode mode) { return ClimateMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), ClimateMqttModeStrings::LAST_INDEX); } -// Climate action MQTT strings indexed by ClimateAction enum (0,2-6): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN +// Climate action MQTT strings indexed by ClimateAction enum (0,2-7): OFF, (gap), COOLING, HEATING, IDLE, DRYING, FAN, +// DEFROSTING PROGMEM_STRING_TABLE(ClimateMqttActionStrings, "off", "unknown", "cooling", "heating", "idle", "drying", "fan", - "unknown"); + "defrosting", "unknown"); static ProgmemStr climate_action_to_mqtt_str(ClimateAction action) { return ClimateMqttActionStrings::get_progmem_str(static_cast<uint8_t>(action), ClimateMqttActionStrings::LAST_INDEX); From 67ba68a1a09adb4cf3cb8178d625645a59a33c29 Mon Sep 17 00:00:00 2001 From: esphomebot <esphome@openhomefoundation.org> Date: Fri, 27 Feb 2026 11:21:40 +1300 Subject: [PATCH 0971/2030] Update webserver local assets to 20260226-220330 (#14330) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/captive_portal/captive_index.h | 4 ++-- esphome/components/web_server/server_index_v2.h | 4 ++-- esphome/components/web_server/server_index_v3.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/captive_portal/captive_index.h b/esphome/components/captive_portal/captive_index.h index 645ebb7a2f..a81edc1900 100644 --- a/esphome/components/captive_portal/captive_index.h +++ b/esphome/components/captive_portal/captive_index.h @@ -6,7 +6,7 @@ namespace esphome::captive_portal { #ifdef USE_CAPTIVE_PORTAL_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x95, 0x16, 0x6b, 0x8f, 0xdb, 0x36, 0xf2, 0x7b, 0x7e, 0x05, 0x8f, 0x49, 0xbb, 0x52, 0xb3, 0x7a, 0x7a, 0xed, 0x6c, 0x24, 0x51, 0x45, 0x9a, 0xbb, 0xa2, 0x05, 0x9a, 0x36, 0xc0, 0x6e, 0x73, 0x1f, 0x82, 0x00, 0x4b, 0x53, 0x23, 0x8b, 0x31, 0x45, 0xea, 0x48, 0xca, 0x8f, 0x18, 0xbe, 0xdf, @@ -86,7 +86,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xfc, 0xda, 0xd1, 0xf8, 0xe9, 0xa3, 0xe1, 0xa6, 0xfb, 0x1f, 0x53, 0x58, 0x46, 0xb2, 0xf9, 0x0a, 0x00, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x1b, 0xf8, 0x0a, 0x00, 0x64, 0x5a, 0xd3, 0xfa, 0xe7, 0xf3, 0x62, 0xd8, 0x06, 0x1b, 0xe9, 0x6a, 0x8a, 0x81, 0x2b, 0xb5, 0x49, 0x14, 0x37, 0xdc, 0x9e, 0x1a, 0xcb, 0x56, 0x87, 0xfb, 0xff, 0xf7, 0x73, 0x75, 0x12, 0x0a, 0xd6, 0x48, 0x84, 0xc6, 0x21, 0xa4, 0x6d, 0xb5, 0x71, 0xef, 0x13, 0xbe, 0x4e, 0x54, 0xf1, 0x64, 0x8f, 0x3f, 0xcc, 0x9a, 0x78, diff --git a/esphome/components/web_server/server_index_v2.h b/esphome/components/web_server/server_index_v2.h index ffa9c87b3a..ac2195f387 100644 --- a/esphome/components/web_server/server_index_v2.h +++ b/esphome/components/web_server/server_index_v2.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xed, 0x7d, 0xd9, 0x72, 0xdb, 0x48, 0xb6, 0xe0, 0xf3, 0xd4, 0x57, 0x40, 0x28, 0xb5, 0x8c, 0x2c, 0x26, 0xc1, 0x45, 0x92, 0x2d, 0x83, 0x4a, 0xb2, 0x65, 0xd9, 0xd5, 0x76, 0x97, 0xb7, 0xb6, 0xec, 0xda, 0x58, 0x6c, 0x09, 0x02, 0x92, 0x44, 0x96, 0x41, 0x80, 0x05, 0x24, 0xb5, 0x14, 0x89, @@ -698,7 +698,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0x01, 0x65, 0x21, 0x07, 0x4b, 0xe3, 0x97, 0x00, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x1b, 0xe2, 0x97, 0xa3, 0x90, 0xa2, 0x95, 0x55, 0x51, 0x04, 0x1b, 0x07, 0x80, 0x20, 0x79, 0x0e, 0x50, 0xab, 0x02, 0xdb, 0x98, 0x16, 0xf4, 0x7b, 0x22, 0xa3, 0x4d, 0xd3, 0x86, 0xc1, 0x26, 0x48, 0x49, 0x60, 0xbe, 0xb3, 0xc9, 0xa1, 0x8c, 0x96, 0x10, 0x1b, 0x21, 0xcf, 0x48, 0x68, 0xce, 0x10, 0x34, 0x32, 0x7c, 0xbf, 0x71, 0x7b, 0x03, 0x8f, 0xdd, diff --git a/esphome/components/web_server/server_index_v3.h b/esphome/components/web_server/server_index_v3.h index b7c15df32b..a1cafe8707 100644 --- a/esphome/components/web_server/server_index_v3.h +++ b/esphome/components/web_server/server_index_v3.h @@ -9,7 +9,7 @@ namespace esphome::web_server { #ifdef USE_WEBSERVER_GZIP -const uint8_t INDEX_GZ[] PROGMEM = { +constexpr uint8_t INDEX_GZ[] PROGMEM = { 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xcc, 0xbd, 0x7b, 0x7f, 0x1a, 0xb9, 0xb2, 0x28, 0xfa, 0xf7, 0x3d, 0x9f, 0xc2, 0xee, 0x9d, 0xf1, 0xb4, 0x8c, 0x68, 0x03, 0x36, 0x8e, 0xd3, 0x58, 0xe6, 0xe4, 0x39, 0xc9, 0x3c, 0x92, 0x4c, 0x9c, 0x64, 0x26, 0xc3, 0xb0, 0x33, 0xa2, 0x11, 0xa0, 0xa4, 0x91, 0x98, 0x96, 0x88, 0xed, 0x01, @@ -4107,7 +4107,7 @@ const uint8_t INDEX_GZ[] PROGMEM = { 0xe8, 0xcd, 0xfe, 0x2c, 0x9d, 0x07, 0xfd, 0xff, 0x05, 0x64, 0x23, 0xa6, 0xdb, 0x06, 0x7b, 0x03, 0x00}; #else // Brotli (default, smaller) -const uint8_t INDEX_BR[] PROGMEM = { +constexpr uint8_t INDEX_BR[] PROGMEM = { 0x5b, 0x05, 0x7b, 0x53, 0xc1, 0xb6, 0x69, 0x3d, 0x41, 0xeb, 0x04, 0x30, 0xf6, 0xd6, 0x77, 0x35, 0xdb, 0xa3, 0x08, 0x36, 0x0e, 0x04, 0x80, 0x90, 0x4f, 0xf1, 0xb2, 0x21, 0xa4, 0x82, 0xee, 0x00, 0xaa, 0x20, 0x7f, 0x3b, 0xff, 0x00, 0xaa, 0x9a, 0x73, 0x74, 0x8c, 0xe1, 0xa6, 0x1f, 0xa0, 0xa2, 0x59, 0xf5, 0xaa, 0x92, 0x79, 0x50, 0x43, 0x1f, 0xe8, From 527d4964f61b77439c469d41207527c5677b813b Mon Sep 17 00:00:00 2001 From: George Joseph <gtjoseph@users.noreply.github.com> Date: Thu, 26 Feb 2026 17:38:07 -0700 Subject: [PATCH 0972/2030] [mipi_dsi] Add more Waveshare panels and comments (#14023) --- .../components/mipi_dsi/models/waveshare.py | 139 +++++++++++++++++- 1 file changed, 136 insertions(+), 3 deletions(-) diff --git a/esphome/components/mipi_dsi/models/waveshare.py b/esphome/components/mipi_dsi/models/waveshare.py index bf4f9063bb..69414065f1 100644 --- a/esphome/components/mipi_dsi/models/waveshare.py +++ b/esphome/components/mipi_dsi/models/waveshare.py @@ -2,7 +2,11 @@ from esphome.components.mipi import DriverChip import esphome.config_validation as cv # fmt: off -DriverChip( + +# Source for parameters and initsequence: +# https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365_10_1 +# Product page: https://www.waveshare.com/wiki/ESP32-P4-Nano-StartPage +JD9365_10_1_DSI_TOUCH_A = DriverChip( "WAVESHARE-P4-NANO-10.1", height=1280, width=800, @@ -52,6 +56,15 @@ DriverChip( ], ) +# Standalone display +# Product page: https://www.waveshare.com/wiki/10.1-DSI-TOUCH-A +JD9365_10_1_DSI_TOUCH_A.extend( + "WAVESHARE-10.1-DSI-TOUCH-A", +) + +# Source for parameters and initsequence: +# https://github.com/espressif/esp-iot-solution/tree/master/components/display/lcd/esp_lcd_st7703 +# Product page: https://www.waveshare.com/wiki/ESP32-P4-86-Panel-ETH-2RO DriverChip( "WAVESHARE-P4-86-PANEL", height=720, @@ -95,6 +108,9 @@ DriverChip( ], ) +# Source for parameters and initsequence: +# https://github.com/espressif/esp-iot-solution/tree/master/components/display/lcd/esp_lcd_ek79007 +# Product page: https://www.waveshare.com/wiki/ESP32-P4-WIFI6-Touch-LCD-7B DriverChip( "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-7B", height=600, @@ -121,7 +137,10 @@ DriverChip( ], ) -DriverChip( +# Source for parameters and initsequence: +# https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365 +# Product page: https://www.waveshare.com/wiki/ESP32-P4-WIFI6-Touch-LCD-3.4C +JD9365_3_4_DSI_TOUCH_C = DriverChip( "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-3.4C", height=800, width=800, @@ -170,7 +189,16 @@ DriverChip( ], ) -DriverChip( +# Standalone display +# Product page: https://www.waveshare.com/wiki/3.4-DSI-TOUCH-C +JD9365_3_4_DSI_TOUCH_C.extend( + "WAVESHARE-3.4-DSI-TOUCH-C", +) + +# Source for parameters and initsequence: +# https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365 +# Product page: https://www.waveshare.com/wiki/ESP32-P4-WIFI6-Touch-LCD-4C +JD9365_4_DSI_TOUCH_C = DriverChip( "WAVESHARE-ESP32-P4-WIFI6-TOUCH-LCD-4C", height=720, width=720, @@ -218,3 +246,108 @@ DriverChip( (0xE0, 0x00), # select userpage ] ) + +# Standalone display +# Product page: https://www.waveshare.com/wiki/4-DSI-TOUCH-C +JD9365_4_DSI_TOUCH_C.extend( + "WAVESHARE-4-DSI-TOUCH-C", +) + +# Source for parameters and initsequence: +# https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365 +# Product page: https://www.waveshare.com/wiki/8-DSI-TOUCH-A +DriverChip( + "WAVESHARE-8-DSI-TOUCH-A", + height=1280, + width=800, + hsync_back_porch=20, + hsync_pulse_width=20, + hsync_front_porch=40, + vsync_back_porch=12, + vsync_pulse_width=4, + vsync_front_porch=30, + pclk_frequency="80MHz", + lane_bit_rate="1.5Gbps", + swap_xy=cv.UNDEFINED, + color_order="RGB", + initsequence=[ + (0xE0, 0x00), # select userpage + (0xE1, 0x93), (0xE2, 0x65), (0xE3, 0xF8), + (0x80, 0x01), # Select number of lanes (2) + (0xE0, 0x01), # select page 1 + (0x00, 0x00), (0x01, 0x4E), (0x03, 0x00), (0x04, 0x65), (0x0C, 0x74), (0x17, 0x00), (0x18, 0xB7), (0x19, 0x00), + (0x1A, 0x00), (0x1B, 0xB7), (0x1C, 0x00), (0x24, 0xFE), (0x37, 0x19), (0x38, 0x05), (0x39, 0x00), (0x3A, 0x01), + (0x3B, 0x01), (0x3C, 0x70), (0x3D, 0xFF), (0x3E, 0xFF), (0x3F, 0xFF), (0x40, 0x06), (0x41, 0xA0), (0x43, 0x1E), + (0x44, 0x0F), (0x45, 0x28), (0x4B, 0x04), (0x55, 0x02), (0x56, 0x01), (0x57, 0xA9), (0x58, 0x0A), (0x59, 0x0A), + (0x5A, 0x37), (0x5B, 0x19), (0x5D, 0x78), (0x5E, 0x63), (0x5F, 0x54), (0x60, 0x49), (0x61, 0x45), (0x62, 0x38), + (0x63, 0x3D), (0x64, 0x28), (0x65, 0x43), (0x66, 0x41), (0x67, 0x43), (0x68, 0x62), (0x69, 0x50), (0x6A, 0x57), + (0x6B, 0x49), (0x6C, 0x44), (0x6D, 0x37), (0x6E, 0x23), (0x6F, 0x10), (0x70, 0x78), (0x71, 0x63), (0x72, 0x54), + (0x73, 0x49), (0x74, 0x45), (0x75, 0x38), (0x76, 0x3D), (0x77, 0x28), (0x78, 0x43), (0x79, 0x41), (0x7A, 0x43), + (0x7B, 0x62), (0x7C, 0x50), (0x7D, 0x57), (0x7E, 0x49), (0x7F, 0x44), (0x80, 0x37), (0x81, 0x23), (0x82, 0x10), + (0xE0, 0x02), # select page 2 + (0x00, 0x47), (0x01, 0x47), (0x02, 0x45), (0x03, 0x45), (0x04, 0x4B), (0x05, 0x4B), (0x06, 0x49), (0x07, 0x49), + (0x08, 0x41), (0x09, 0x1F), (0x0A, 0x1F), (0x0B, 0x1F), (0x0C, 0x1F), (0x0D, 0x1F), (0x0E, 0x1F), (0x0F, 0x5F), + (0x10, 0x5F), (0x11, 0x57), (0x12, 0x77), (0x13, 0x35), (0x14, 0x1F), (0x15, 0x1F), (0x16, 0x46), (0x17, 0x46), + (0x18, 0x44), (0x19, 0x44), (0x1A, 0x4A), (0x1B, 0x4A), (0x1C, 0x48), (0x1D, 0x48), (0x1E, 0x40), (0x1F, 0x1F), + (0x20, 0x1F), (0x21, 0x1F), (0x22, 0x1F), (0x23, 0x1F), (0x24, 0x1F), (0x25, 0x5F), (0x26, 0x5F), (0x27, 0x57), + (0x28, 0x77), (0x29, 0x35), (0x2A, 0x1F), (0x2B, 0x1F), (0x58, 0x40), (0x59, 0x00), (0x5A, 0x00), (0x5B, 0x10), + (0x5C, 0x06), (0x5D, 0x40), (0x5E, 0x01), (0x5F, 0x02), (0x60, 0x30), (0x61, 0x01), (0x62, 0x02), (0x63, 0x03), + (0x64, 0x6B), (0x65, 0x05), (0x66, 0x0C), (0x67, 0x73), (0x68, 0x09), (0x69, 0x03), (0x6A, 0x56), (0x6B, 0x08), + (0x6C, 0x00), (0x6D, 0x04), (0x6E, 0x04), (0x6F, 0x88), (0x70, 0x00), (0x71, 0x00), (0x72, 0x06), (0x73, 0x7B), + (0x74, 0x00), (0x75, 0xF8), (0x76, 0x00), (0x77, 0xD5), (0x78, 0x2E), (0x79, 0x12), (0x7A, 0x03), (0x7B, 0x00), + (0x7C, 0x00), (0x7D, 0x03), (0x7E, 0x7B), + (0xE0, 0x04), # select page 4 + (0x00, 0x0E), (0x02, 0xB3), (0x09, 0x60), (0x0E, 0x2A), (0x36, 0x59), (0x37, 0x58), (0x2B, 0x0F), + (0xE0, 0x00), # select userpage + ] +) + +# Source for parameters and initsequence: +# https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_ili9881c +# Product page: https://www.waveshare.com/wiki/7-DSI-TOUCH-A +DriverChip( + "WAVESHARE-7-DSI-TOUCH-A", + height=1280, + width=720, + hsync_back_porch=239, + hsync_pulse_width=50, + hsync_front_porch=33, + vsync_back_porch=20, + vsync_pulse_width=30, + vsync_front_porch=2, + pclk_frequency="80MHz", + lane_bit_rate="1000Mbps", + no_transform=True, + color_order="RGB", + initsequence=[ + (0xFF, 0x98, 0x81, 0x03), + (0x01, 0x00), (0x02, 0x00), (0x03, 0x73), (0x04, 0x00), (0x05, 0x00), (0x06, 0x0A), (0x07, 0x00), (0x08, 0x00), + (0x09, 0x61), (0x0A, 0x00), (0x0B, 0x00), (0x0C, 0x01), (0x0D, 0x00), (0x0E, 0x00), (0x0F, 0x61), (0x10, 0x61), + (0x11, 0x00), (0x12, 0x00), (0x13, 0x00), (0x14, 0x00), (0x15, 0x00), (0x16, 0x00), (0x17, 0x00), (0x18, 0x00), + (0x19, 0x00), (0x1A, 0x00), (0x1B, 0x00), (0x1C, 0x00), (0x1D, 0x00), (0x1E, 0x40), (0x1F, 0x80), (0x20, 0x06), + (0x21, 0x01), (0x22, 0x00), (0x23, 0x00), (0x24, 0x00), (0x25, 0x00), (0x26, 0x00), (0x27, 0x00), (0x28, 0x33), + (0x29, 0x03), (0x2A, 0x00), (0x2B, 0x00), (0x2C, 0x00), (0x2D, 0x00), (0x2E, 0x00), (0x2F, 0x00), (0x30, 0x00), + (0x31, 0x00), (0x32, 0x00), (0x33, 0x00), (0x34, 0x04), (0x35, 0x00), (0x36, 0x00), (0x37, 0x00), (0x38, 0x3C), + (0x39, 0x00), (0x3A, 0x00), (0x3B, 0x00), (0x3C, 0x00), (0x3D, 0x00), (0x3E, 0x00), (0x3F, 0x00), (0x40, 0x00), + (0x41, 0x00), (0x42, 0x00), (0x43, 0x00), (0x44, 0x00), (0x50, 0x10), (0x51, 0x32), (0x52, 0x54), (0x53, 0x76), + (0x54, 0x98), (0x55, 0xBA), (0x56, 0x10), (0x57, 0x32), (0x58, 0x54), (0x59, 0x76), (0x5A, 0x98), (0x5B, 0xBA), + (0x5C, 0xDC), (0x5D, 0xFE), (0x5E, 0x00), (0x5F, 0x0E), (0x60, 0x0F), (0x61, 0x0C), (0x62, 0x0D), (0x63, 0x06), + (0x64, 0x07), (0x65, 0x02), (0x66, 0x02), (0x67, 0x02), (0x68, 0x02), (0x69, 0x01), (0x6A, 0x00), (0x6B, 0x02), + (0x6C, 0x15), (0x6D, 0x14), (0x6E, 0x02), (0x6F, 0x02), (0x70, 0x02), (0x71, 0x02), (0x72, 0x02), (0x73, 0x02), + (0x74, 0x02), (0x75, 0x0E), (0x76, 0x0F), (0x77, 0x0C), (0x78, 0x0D), (0x79, 0x06), (0x7A, 0x07), (0x7B, 0x02), + (0x7C, 0x02), (0x7D, 0x02), (0x7E, 0x02), (0x7F, 0x01), (0x80, 0x00), (0x81, 0x02), (0x82, 0x14), (0x83, 0x15), + (0x84, 0x02), (0x85, 0x02), (0x86, 0x02), (0x87, 0x02), (0x88, 0x02), (0x89, 0x02), (0x8A, 0x02), + (0xFF, 0x98, 0x81, 0x04), + (0x38, 0x01), (0x39, 0x00), (0x6C, 0x15), (0x6E, 0x2A), (0x6F, 0x33), (0x3A, 0x94), (0x8D, 0x14), (0x87, 0xBA), + (0x26, 0x76), (0xB2, 0xD1), (0xB5, 0x06), (0x3B, 0x98), + (0xFF, 0x98, 0x81, 0x01), + (0x22, 0x0A), (0x31, 0x00), (0x53, 0x71), (0x55, 0x8F), (0x40, 0x33), (0x50, 0x96), (0x51, 0x96), (0x60, 0x23), + (0xA0, 0x08), (0xA1, 0x1D), (0xA2, 0x2A), (0xA3, 0x10), (0xA4, 0x15), (0xA5, 0x28), (0xA6, 0x1C), (0xA7, 0x1D), + (0xA8, 0x7E), (0xA9, 0x1D), (0xAA, 0x29), (0xAB, 0x6B), (0xAC, 0x1A), (0xAD, 0x18), (0xAE, 0x4B), (0xAF, 0x20), + (0xB0, 0x27), (0xB1, 0x50), (0xB2, 0x64), (0xB3, 0x39), (0xC0, 0x08), (0xC1, 0x1D), (0xC2, 0x2A), (0xC3, 0x10), + (0xC4, 0x15), (0xC5, 0x28), (0xC6, 0x1C), (0xC7, 0x1D), (0xC8, 0x7E), (0xC9, 0x1D), (0xCA, 0x29), (0xCB, 0x6B), + (0xCC, 0x1A), (0xCD, 0x18), (0xCE, 0x4B), (0xCF, 0x20), (0xD0, 0x27), (0xD1, 0x50), (0xD2, 0x64), (0xD3, 0x39), + (0xFF, 0x98, 0x81, 0x00), + (0x3A, 0x77), (0x36, 0x00), (0x35, 0x00), (0x35, 0x00), + ], +) From 1ccfcfc8d85593f81e96ea40cd4e8a162392a678 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 18:12:44 -0700 Subject: [PATCH 0973/2030] [time] Eliminate libc timezone bloat (~9.5KB flash ESP32, ~2% RAM on ESP8266) (#13635) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/time/posix_tz.cpp | 488 +++++++ esphome/components/time/posix_tz.h | 144 +++ esphome/components/time/real_time_clock.cpp | 61 +- esphome/components/time/real_time_clock.h | 35 +- esphome/core/time.cpp | 232 +++- esphome/core/time.h | 18 +- script/cpp_unit_test.py | 1 + tests/components/time/posix_tz_parser.cpp | 1275 +++++++++++++++++++ 8 files changed, 2163 insertions(+), 91 deletions(-) create mode 100644 esphome/components/time/posix_tz.cpp create mode 100644 esphome/components/time/posix_tz.h create mode 100644 tests/components/time/posix_tz_parser.cpp diff --git a/esphome/components/time/posix_tz.cpp b/esphome/components/time/posix_tz.cpp new file mode 100644 index 0000000000..4d1f0c74c2 --- /dev/null +++ b/esphome/components/time/posix_tz.cpp @@ -0,0 +1,488 @@ +#include "esphome/core/defines.h" + +#ifdef USE_TIME_TIMEZONE + +#include "posix_tz.h" +#include <cctype> + +namespace esphome::time { + +// Global timezone - set once at startup, rarely changes +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - intentional mutable state +static ParsedTimezone global_tz_{}; + +void set_global_tz(const ParsedTimezone &tz) { global_tz_ = tz; } + +const ParsedTimezone &get_global_tz() { return global_tz_; } + +namespace internal { + +// Remove before 2026.9.0: parse_uint, skip_tz_name, parse_offset, parse_dst_rule, +// and parse_transition_time are only used by parse_posix_tz() (bridge code). +static uint32_t parse_uint(const char *&p) { + uint32_t value = 0; + while (std::isdigit(static_cast<unsigned char>(*p))) { + value = value * 10 + (*p - '0'); + p++; + } + return value; +} + +bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); } + +// Get days in year (avoids duplicate is_leap_year calls) +static inline int days_in_year(int year) { return is_leap_year(year) ? 366 : 365; } + +// Convert days since epoch to year, updating days to remainder +static int __attribute__((noinline)) days_to_year(int64_t &days) { + int year = 1970; + int diy; + while (days >= (diy = days_in_year(year)) && year < 2200) { + days -= diy; + year++; + } + while (days < 0 && year > 1900) { + year--; + days += days_in_year(year); + } + return year; +} + +// Extract just the year from a UTC epoch +static int epoch_to_year(time_t epoch) { + int64_t days = epoch / 86400; + if (epoch < 0 && epoch % 86400 != 0) + days--; + return days_to_year(days); +} + +int days_in_month(int year, int month) { + switch (month) { + case 2: + return is_leap_year(year) ? 29 : 28; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + } +} + +// Zeller-like algorithm for day of week (0 = Sunday) +int __attribute__((noinline)) day_of_week(int year, int month, int day) { + // Adjust for January/February + if (month < 3) { + month += 12; + year--; + } + int k = year % 100; + int j = year / 100; + int h = (day + (13 * (month + 1)) / 5 + k + k / 4 + j / 4 - 2 * j) % 7; + // Convert from Zeller (0=Sat) to standard (0=Sun) + return ((h + 6) % 7); +} + +void __attribute__((noinline)) epoch_to_tm_utc(time_t epoch, struct tm *out_tm) { + // Days since epoch + int64_t days = epoch / 86400; + int32_t remaining_secs = epoch % 86400; + if (remaining_secs < 0) { + days--; + remaining_secs += 86400; + } + + out_tm->tm_sec = remaining_secs % 60; + remaining_secs /= 60; + out_tm->tm_min = remaining_secs % 60; + out_tm->tm_hour = remaining_secs / 60; + + // Day of week (Jan 1, 1970 was Thursday = 4) + out_tm->tm_wday = static_cast<int>((days + 4) % 7); + if (out_tm->tm_wday < 0) + out_tm->tm_wday += 7; + + // Calculate year (updates days to day-of-year) + int year = days_to_year(days); + out_tm->tm_year = year - 1900; + out_tm->tm_yday = static_cast<int>(days); + + // Calculate month and day + int month = 1; + int dim; + while (days >= (dim = days_in_month(year, month))) { + days -= dim; + month++; + } + + out_tm->tm_mon = month - 1; + out_tm->tm_mday = static_cast<int>(days) + 1; + out_tm->tm_isdst = 0; +} + +bool skip_tz_name(const char *&p) { + if (*p == '<') { + // Angle-bracket quoted name: <+07>, <-03>, <AEST> + p++; // skip '<' + while (*p && *p != '>') { + p++; + } + if (*p == '>') { + p++; // skip '>' + return true; + } + return false; // Unterminated + } + + // Standard name: 3+ letters + const char *start = p; + while (*p && std::isalpha(static_cast<unsigned char>(*p))) { + p++; + } + return (p - start) >= 3; +} + +int32_t __attribute__((noinline)) parse_offset(const char *&p) { + int sign = 1; + if (*p == '-') { + sign = -1; + p++; + } else if (*p == '+') { + p++; + } + + int hours = parse_uint(p); + int minutes = 0; + int seconds = 0; + + if (*p == ':') { + p++; + minutes = parse_uint(p); + if (*p == ':') { + p++; + seconds = parse_uint(p); + } + } + + return sign * (hours * 3600 + minutes * 60 + seconds); +} + +// Helper to parse the optional /time suffix (reuses parse_offset logic) +static void parse_transition_time(const char *&p, DSTRule &rule) { + rule.time_seconds = 2 * 3600; // Default 02:00 + if (*p == '/') { + p++; + rule.time_seconds = parse_offset(p); + } +} + +void __attribute__((noinline)) julian_to_month_day(int julian_day, int &out_month, int &out_day) { + // J format: day 1-365, Feb 29 is NOT counted even in leap years + // So day 60 is always March 1 + // Iterate forward through months (no array needed) + int remaining = julian_day; + out_month = 1; + while (out_month <= 12) { + // Days in month for non-leap year (J format ignores leap years) + int dim = days_in_month(2001, out_month); // 2001 is non-leap year + if (remaining <= dim) { + out_day = remaining; + return; + } + remaining -= dim; + out_month++; + } + out_day = remaining; +} + +void __attribute__((noinline)) day_of_year_to_month_day(int day_of_year, int year, int &out_month, int &out_day) { + // Plain format: day 0-365, Feb 29 IS counted in leap years + // Day 0 = Jan 1 + int remaining = day_of_year; + out_month = 1; + + while (out_month <= 12) { + int days_this_month = days_in_month(year, out_month); + if (remaining < days_this_month) { + out_day = remaining + 1; + return; + } + remaining -= days_this_month; + out_month++; + } + + // Shouldn't reach here with valid input + out_month = 12; + out_day = 31; +} + +bool parse_dst_rule(const char *&p, DSTRule &rule) { + rule = {}; // Zero initialize + + if (*p == 'M' || *p == 'm') { + // M format: Mm.w.d (month.week.day) + rule.type = DSTRuleType::MONTH_WEEK_DAY; + p++; + + rule.month = parse_uint(p); + if (rule.month < 1 || rule.month > 12) + return false; + + if (*p++ != '.') + return false; + + rule.week = parse_uint(p); + if (rule.week < 1 || rule.week > 5) + return false; + + if (*p++ != '.') + return false; + + rule.day_of_week = parse_uint(p); + if (rule.day_of_week > 6) + return false; + + } else if (*p == 'J' || *p == 'j') { + // J format: Jn (Julian day 1-365, not counting Feb 29) + rule.type = DSTRuleType::JULIAN_NO_LEAP; + p++; + + rule.day = parse_uint(p); + if (rule.day < 1 || rule.day > 365) + return false; + + } else if (std::isdigit(static_cast<unsigned char>(*p))) { + // Plain number format: n (day 0-365, counting Feb 29) + rule.type = DSTRuleType::DAY_OF_YEAR; + + rule.day = parse_uint(p); + if (rule.day > 365) + return false; + + } else { + return false; + } + + // Parse optional /time suffix + parse_transition_time(p, rule); + + return true; +} + +// Calculate days from Jan 1 of given year to given month/day +static int __attribute__((noinline)) days_from_year_start(int year, int month, int day) { + int days = day - 1; + for (int m = 1; m < month; m++) { + days += days_in_month(year, m); + } + return days; +} + +// Calculate days from epoch to Jan 1 of given year (for DST transition calculations) +// Only supports years >= 1970. Timezone is either compiled in from YAML or set by +// Home Assistant, so pre-1970 dates are not a concern. +static int64_t __attribute__((noinline)) days_to_year_start(int year) { + int64_t days = 0; + for (int y = 1970; y < year; y++) { + days += days_in_year(y); + } + return days; +} + +time_t __attribute__((noinline)) calculate_dst_transition(int year, const DSTRule &rule, int32_t base_offset_seconds) { + int month, day; + + switch (rule.type) { + case DSTRuleType::MONTH_WEEK_DAY: { + // Find the nth occurrence of day_of_week in the given month + int first_dow = day_of_week(year, rule.month, 1); + + // Days until first occurrence of target day + int days_until_first = (rule.day_of_week - first_dow + 7) % 7; + int first_occurrence = 1 + days_until_first; + + if (rule.week == 5) { + // "Last" occurrence - find the last one in the month + int dim = days_in_month(year, rule.month); + day = first_occurrence; + while (day + 7 <= dim) { + day += 7; + } + } else { + // nth occurrence + day = first_occurrence + (rule.week - 1) * 7; + } + month = rule.month; + break; + } + + case DSTRuleType::JULIAN_NO_LEAP: + // J format: day 1-365, Feb 29 not counted + julian_to_month_day(rule.day, month, day); + break; + + case DSTRuleType::DAY_OF_YEAR: + // Plain format: day 0-365, Feb 29 counted + day_of_year_to_month_day(rule.day, year, month, day); + break; + + case DSTRuleType::NONE: + // Should never be called with NONE, but handle it gracefully + month = 1; + day = 1; + break; + } + + // Calculate days from epoch to this date + int64_t days = days_to_year_start(year) + days_from_year_start(year, month, day); + + // Convert to epoch and add transition time and base offset + return days * 86400 + rule.time_seconds + base_offset_seconds; +} + +} // namespace internal + +bool __attribute__((noinline)) is_in_dst(time_t utc_epoch, const ParsedTimezone &tz) { + if (!tz.has_dst()) { + return false; + } + + int year = internal::epoch_to_year(utc_epoch); + + // Calculate DST start and end for this year + // DST start transition happens in standard time + time_t dst_start = internal::calculate_dst_transition(year, tz.dst_start, tz.std_offset_seconds); + // DST end transition happens in daylight time + time_t dst_end = internal::calculate_dst_transition(year, tz.dst_end, tz.dst_offset_seconds); + + if (dst_start < dst_end) { + // Northern hemisphere: DST is between start and end + return (utc_epoch >= dst_start && utc_epoch < dst_end); + } else { + // Southern hemisphere: DST is outside the range (wraps around year) + return (utc_epoch >= dst_start || utc_epoch < dst_end); + } +} + +// Remove before 2026.9.0: This parser is bridge code for backward compatibility with +// older Home Assistant clients that send the timezone as a POSIX TZ string instead of +// the pre-parsed ParsedTimezone protobuf struct. Once all clients send the struct +// directly, this function and the parsing helpers above (skip_tz_name, parse_offset, +// parse_dst_rule, parse_transition_time) can be removed. +// See https://github.com/esphome/backlog/issues/91 +bool parse_posix_tz(const char *tz_string, ParsedTimezone &result) { + if (!tz_string || !*tz_string) { + return false; + } + + const char *p = tz_string; + + // Initialize result (dst_start/dst_end default to type=NONE, so has_dst() returns false) + result.std_offset_seconds = 0; + result.dst_offset_seconds = 0; + result.dst_start = {}; + result.dst_end = {}; + + // Skip standard timezone name + if (!internal::skip_tz_name(p)) { + return false; + } + + // Parse standard offset (required) + if (!*p || (!std::isdigit(static_cast<unsigned char>(*p)) && *p != '+' && *p != '-')) { + return false; + } + result.std_offset_seconds = internal::parse_offset(p); + + // Check for DST name + if (!*p) { + return true; // No DST + } + + // If next char is comma, there's no DST name but there are rules (invalid) + if (*p == ',') { + return false; + } + + // Check if there's something that looks like a DST name start + // (letter or angle bracket). If not, treat as trailing garbage and return success. + if (!std::isalpha(static_cast<unsigned char>(*p)) && *p != '<') { + return true; // No DST, trailing characters ignored + } + + if (!internal::skip_tz_name(p)) { + return false; // Invalid DST name (started but malformed) + } + + // Optional DST offset (default is std - 1 hour) + if (*p && *p != ',' && (std::isdigit(static_cast<unsigned char>(*p)) || *p == '+' || *p == '-')) { + result.dst_offset_seconds = internal::parse_offset(p); + } else { + result.dst_offset_seconds = result.std_offset_seconds - 3600; + } + + // Parse DST rules (required when DST name is present) + if (*p != ',') { + // DST name without rules - treat as no DST since we can't determine transitions + return true; + } + + p++; + if (!internal::parse_dst_rule(p, result.dst_start)) { + return false; + } + + // Second rule is required per POSIX + if (*p != ',') { + return false; + } + p++; + // has_dst() now returns true since dst_start.type was set by parse_dst_rule + return internal::parse_dst_rule(p, result.dst_end); +} + +bool epoch_to_local_tm(time_t utc_epoch, const ParsedTimezone &tz, struct tm *out_tm) { + if (!out_tm) { + return false; + } + + // Determine DST status once (avoids duplicate is_in_dst calculation) + bool in_dst = is_in_dst(utc_epoch, tz); + int32_t offset = in_dst ? tz.dst_offset_seconds : tz.std_offset_seconds; + + // Apply offset (POSIX offset is positive west, so subtract to get local) + time_t local_epoch = utc_epoch - offset; + + internal::epoch_to_tm_utc(local_epoch, out_tm); + out_tm->tm_isdst = in_dst ? 1 : 0; + + return true; +} + +} // namespace esphome::time + +#ifndef USE_HOST +// Override libc's localtime functions to use our timezone on embedded platforms. +// This allows user lambdas calling ::localtime() to get correct local time +// without needing the TZ environment variable (which pulls in scanf bloat). +// On host, we use the normal TZ mechanism since there's no memory constraint. + +// Thread-safe version +extern "C" struct tm *localtime_r(const time_t *timer, struct tm *result) { + if (timer == nullptr || result == nullptr) { + return nullptr; + } + esphome::time::epoch_to_local_tm(*timer, esphome::time::get_global_tz(), result); + return result; +} + +// Non-thread-safe version (uses static buffer, standard libc behavior) +extern "C" struct tm *localtime(const time_t *timer) { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + static struct tm localtime_buf; + return localtime_r(timer, &localtime_buf); +} +#endif // !USE_HOST + +#endif // USE_TIME_TIMEZONE diff --git a/esphome/components/time/posix_tz.h b/esphome/components/time/posix_tz.h new file mode 100644 index 0000000000..c71ba15cd1 --- /dev/null +++ b/esphome/components/time/posix_tz.h @@ -0,0 +1,144 @@ +#pragma once + +#ifdef USE_TIME_TIMEZONE + +#include <cstdint> +#include <ctime> + +namespace esphome::time { + +/// Type of DST transition rule +enum class DSTRuleType : uint8_t { + NONE = 0, ///< No DST rule (used to indicate no DST) + MONTH_WEEK_DAY, ///< M format: Mm.w.d (e.g., M3.2.0 = 2nd Sunday of March) + JULIAN_NO_LEAP, ///< J format: Jn (day 1-365, Feb 29 not counted) + DAY_OF_YEAR, ///< Plain number: n (day 0-365, Feb 29 counted in leap years) +}; + +/// Rule for DST transition (packed for 32-bit: 12 bytes) +struct DSTRule { + int32_t time_seconds; ///< Seconds after midnight (default 7200 = 2:00 AM) + uint16_t day; ///< Day of year (for JULIAN_NO_LEAP and DAY_OF_YEAR) + DSTRuleType type; ///< Type of rule + uint8_t month; ///< Month 1-12 (for MONTH_WEEK_DAY) + uint8_t week; ///< Week 1-5, 5 = last (for MONTH_WEEK_DAY) + uint8_t day_of_week; ///< Day 0-6, 0 = Sunday (for MONTH_WEEK_DAY) +}; + +/// Parsed POSIX timezone information (packed for 32-bit: 32 bytes) +struct ParsedTimezone { + int32_t std_offset_seconds; ///< Standard time offset from UTC in seconds (positive = west) + int32_t dst_offset_seconds; ///< DST offset from UTC in seconds + DSTRule dst_start; ///< When DST starts + DSTRule dst_end; ///< When DST ends + + /// Check if this timezone has DST rules + bool has_dst() const { return this->dst_start.type != DSTRuleType::NONE; } +}; + +/// Parse a POSIX TZ string into a ParsedTimezone struct. +/// +/// @deprecated Remove before 2026.9.0 (bridge code for backward compatibility). +/// This parser only exists so that older Home Assistant clients that send the timezone +/// as a string (instead of the pre-parsed ParsedTimezone protobuf struct) can still +/// set the timezone on the device. Once all clients are updated to send the struct +/// directly, this function and all internal parsing helpers will be removed. +/// See https://github.com/esphome/backlog/issues/91 +/// +/// Supports formats like: +/// - "EST5" (simple offset, no DST) +/// - "EST5EDT,M3.2.0,M11.1.0" (with DST, M-format rules) +/// - "CST6CDT,M3.2.0/2,M11.1.0/2" (with transition times) +/// - "<+07>-7" (angle-bracket notation for special names) +/// - "IST-5:30" (half-hour offsets) +/// - "EST5EDT,J60,J300" (J-format: Julian day without leap day) +/// - "EST5EDT,60,300" (plain day number: day of year with leap day) +/// @param tz_string The POSIX TZ string to parse +/// @param result Output: the parsed timezone data +/// @return true if parsing succeeded, false on error +bool parse_posix_tz(const char *tz_string, ParsedTimezone &result); + +/// Convert a UTC epoch to local time using the parsed timezone. +/// This replaces libc's localtime() to avoid scanf dependency. +/// @param utc_epoch Unix timestamp in UTC +/// @param tz The parsed timezone +/// @param[out] out_tm Output tm struct with local time +/// @return true on success +bool epoch_to_local_tm(time_t utc_epoch, const ParsedTimezone &tz, struct tm *out_tm); + +/// Set the global timezone used by epoch_to_local_tm() when called without a timezone. +/// This is called by RealTimeClock::apply_timezone_() to enable ESPTime::from_epoch_local() +/// to work without libc's localtime(). +void set_global_tz(const ParsedTimezone &tz); + +/// Get the global timezone. +const ParsedTimezone &get_global_tz(); + +/// Check if a given UTC epoch falls within DST for the parsed timezone. +/// @param utc_epoch Unix timestamp in UTC +/// @param tz The parsed timezone +/// @return true if DST is in effect at the given time +bool is_in_dst(time_t utc_epoch, const ParsedTimezone &tz); + +// Internal helper functions exposed for testing. +// Remove before 2026.9.0: skip_tz_name, parse_offset, parse_dst_rule are only +// used by parse_posix_tz() which is bridge code for backward compatibility. +// The remaining helpers (epoch_to_tm_utc, day_of_week, days_in_month, etc.) +// are used by the conversion functions and will stay. + +namespace internal { + +/// Skip a timezone name (letters or <...> quoted format) +/// @param p Pointer to current position, updated on return +/// @return true if a valid name was found +bool skip_tz_name(const char *&p); + +/// Parse an offset in format [-]hh[:mm[:ss]] +/// @param p Pointer to current position, updated on return +/// @return Offset in seconds +int32_t parse_offset(const char *&p); + +/// Parse a DST rule in format Mm.w.d[/time], Jn[/time], or n[/time] +/// @param p Pointer to current position, updated on return +/// @param rule Output: the parsed rule +/// @return true if parsing succeeded +bool parse_dst_rule(const char *&p, DSTRule &rule); + +/// Convert Julian day (J format, 1-365 not counting Feb 29) to month/day +/// @param julian_day Day number 1-365 +/// @param[out] month Output: month 1-12 +/// @param[out] day Output: day of month +void julian_to_month_day(int julian_day, int &month, int &day); + +/// Convert day of year (plain format, 0-365 counting Feb 29) to month/day +/// @param day_of_year Day number 0-365 +/// @param year The year (for leap year calculation) +/// @param[out] month Output: month 1-12 +/// @param[out] day Output: day of month +void day_of_year_to_month_day(int day_of_year, int year, int &month, int &day); + +/// Calculate day of week for any date (0 = Sunday) +/// Uses a simplified algorithm that works for years 1970-2099 +int day_of_week(int year, int month, int day); + +/// Get the number of days in a month +int days_in_month(int year, int month); + +/// Check if a year is a leap year +bool is_leap_year(int year); + +/// Convert epoch to year/month/day/hour/min/sec (UTC) +void epoch_to_tm_utc(time_t epoch, struct tm *out_tm); + +/// Calculate the epoch timestamp for a DST transition in a given year. +/// @param year The year (e.g., 2026) +/// @param rule The DST rule (month, week, day_of_week, time) +/// @param base_offset_seconds The timezone offset to apply (std or dst depending on context) +/// @return Unix epoch timestamp of the transition +time_t calculate_dst_transition(int year, const DSTRule &rule, int32_t base_offset_seconds); + +} // namespace internal + +} // namespace esphome::time + +#endif // USE_TIME_TIMEZONE diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 8a78186178..2e758ad8e7 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -14,8 +14,8 @@ #include <sys/time.h> #endif #include <cerrno> - #include <cinttypes> +#include <cstdlib> namespace esphome::time { @@ -23,9 +23,33 @@ static const char *const TAG = "time"; RealTimeClock::RealTimeClock() = default; +ESPTime __attribute__((noinline)) RealTimeClock::now() { +#ifdef USE_TIME_TIMEZONE + time_t epoch = this->timestamp_now(); + struct tm local_tm; + if (epoch_to_local_tm(epoch, get_global_tz(), &local_tm)) { + return ESPTime::from_c_tm(&local_tm, epoch); + } + // Fallback to UTC if parsing failed + return ESPTime::from_epoch_utc(epoch); +#else + return ESPTime::from_epoch_local(this->timestamp_now()); +#endif +} + void RealTimeClock::dump_config() { #ifdef USE_TIME_TIMEZONE - ESP_LOGCONFIG(TAG, "Timezone: '%s'", this->timezone_.c_str()); + const auto &tz = get_global_tz(); + // POSIX offset is positive west, negate for conventional UTC+X display + int std_h = -tz.std_offset_seconds / 3600; + int std_m = (std::abs(tz.std_offset_seconds) % 3600) / 60; + if (tz.has_dst()) { + int dst_h = -tz.dst_offset_seconds / 3600; + int dst_m = (std::abs(tz.dst_offset_seconds) % 3600) / 60; + ESP_LOGCONFIG(TAG, "Timezone: UTC%+d:%02d (DST UTC%+d:%02d)", std_h, std_m, dst_h, dst_m); + } else { + ESP_LOGCONFIG(TAG, "Timezone: UTC%+d:%02d", std_h, std_m); + } #endif auto time = this->now(); ESP_LOGCONFIG(TAG, "Current time: %04d-%02d-%02d %02d:%02d:%02d", time.year, time.month, time.day_of_month, time.hour, @@ -72,11 +96,6 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { ret = settimeofday(&timev, nullptr); } -#ifdef USE_TIME_TIMEZONE - // Move timezone back to local timezone. - this->apply_timezone_(); -#endif - if (ret != 0) { ESP_LOGW(TAG, "setimeofday() failed with code %d", ret); } @@ -89,9 +108,33 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { } #ifdef USE_TIME_TIMEZONE -void RealTimeClock::apply_timezone_() { - setenv("TZ", this->timezone_.c_str(), 1); +void RealTimeClock::apply_timezone_(const char *tz) { + ParsedTimezone parsed{}; + + // Handle null or empty input - use UTC + if (tz == nullptr || *tz == '\0') { + // Skip if already UTC + if (!get_global_tz().has_dst() && get_global_tz().std_offset_seconds == 0) { + return; + } + set_global_tz(parsed); + return; + } + +#ifdef USE_HOST + // On host platform, also set TZ environment variable for libc compatibility + setenv("TZ", tz, 1); tzset(); +#endif + + // Parse the POSIX TZ string using our custom parser + if (!parse_posix_tz(tz, parsed)) { + ESP_LOGW(TAG, "Failed to parse timezone: %s", tz); + return; + } + + // Set global timezone for all time conversions + set_global_tz(parsed); } #endif diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index 19aa1a4f4a..f9de5f5614 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -6,6 +6,9 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/time.h" +#ifdef USE_TIME_TIMEZONE +#include "posix_tz.h" +#endif namespace esphome::time { @@ -20,26 +23,31 @@ class RealTimeClock : public PollingComponent { explicit RealTimeClock(); #ifdef USE_TIME_TIMEZONE - /// Set the time zone. - void set_timezone(const std::string &tz) { - this->timezone_ = tz; - this->apply_timezone_(); - } + /// Set the time zone from a POSIX TZ string. + void set_timezone(const char *tz) { this->apply_timezone_(tz); } - /// Set the time zone from raw buffer, only if it differs from the current one. + /// Set the time zone from a character buffer with known length. + /// The buffer does not need to be null-terminated. void set_timezone(const char *tz, size_t len) { - if (this->timezone_.length() != len || memcmp(this->timezone_.c_str(), tz, len) != 0) { - this->timezone_.assign(tz, len); - this->apply_timezone_(); + if (tz == nullptr) { + this->apply_timezone_(nullptr); + return; } + // Stack buffer - TZ strings from tzdata are typically short (< 50 chars) + char buf[128]; + if (len >= sizeof(buf)) + len = sizeof(buf) - 1; + memcpy(buf, tz, len); + buf[len] = '\0'; + this->apply_timezone_(buf); } - /// Get the time zone currently in use. - std::string get_timezone() { return this->timezone_; } + /// Set the time zone from a std::string. + void set_timezone(const std::string &tz) { this->apply_timezone_(tz.c_str()); } #endif /// Get the time in the currently defined timezone. - ESPTime now() { return ESPTime::from_epoch_local(this->timestamp_now()); } + ESPTime now(); /// Get the time without any time zone or DST corrections. ESPTime utcnow() { return ESPTime::from_epoch_utc(this->timestamp_now()); } @@ -58,8 +66,7 @@ class RealTimeClock : public PollingComponent { void synchronize_epoch_(uint32_t epoch); #ifdef USE_TIME_TIMEZONE - std::string timezone_{}; - void apply_timezone_(); + void apply_timezone_(const char *tz); #endif LazyCallbackManager<void()> time_sync_callback_; diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 1aea18ac8d..73ba0a9be7 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -2,7 +2,6 @@ #include "helpers.h" #include <algorithm> -#include <cinttypes> namespace esphome { @@ -67,58 +66,123 @@ std::string ESPTime::strftime(const char *format) { std::string ESPTime::strftime(const std::string &format) { return this->strftime(format.c_str()); } -bool ESPTime::strptime(const char *time_to_parse, size_t len, ESPTime &esp_time) { - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - int num; - const int ilen = static_cast<int>(len); - - if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %02hhu:%02hhu:%02hhu %n", &year, &month, &day, // NOLINT - &hour, // NOLINT - &minute, // NOLINT - &second, &num) == 6 && // NOLINT - num == ilen) { - 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 = second; - } else if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %02hhu:%02hhu %n", &year, &month, &day, // NOLINT - &hour, // NOLINT - &minute, &num) == 5 && // NOLINT - num == ilen) { - 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, "%02hhu:%02hhu:%02hhu %n", &hour, &minute, &second, &num) == 3 && // NOLINT - num == ilen) { - esp_time.hour = hour; - esp_time.minute = minute; - esp_time.second = second; - } else if (sscanf(time_to_parse, "%02hhu:%02hhu %n", &hour, &minute, &num) == 2 && // NOLINT - num == ilen) { - esp_time.hour = hour; - esp_time.minute = minute; - esp_time.second = 0; - } else if (sscanf(time_to_parse, "%04hu-%02hhu-%02hhu %n", &year, &month, &day, &num) == 3 && // NOLINT - num == ilen) { - esp_time.year = year; - esp_time.month = month; - esp_time.day_of_month = day; - } else { - return false; +// Helper to parse exactly N digits, returns false if not enough digits +static bool parse_digits(const char *&p, const char *end, int count, uint16_t &value) { + value = 0; + for (int i = 0; i < count; i++) { + if (p >= end || *p < '0' || *p > '9') + return false; + value = value * 10 + (*p - '0'); + p++; } return true; } +// Helper to check for expected character +static bool expect_char(const char *&p, const char *end, char expected) { + if (p >= end || *p != expected) + return false; + p++; + return true; +} + +bool ESPTime::strptime(const char *time_to_parse, size_t len, ESPTime &esp_time) { + // Supported formats: + // YYYY-MM-DD HH:MM:SS (19 chars) + // YYYY-MM-DD HH:MM (16 chars) + // YYYY-MM-DD (10 chars) + // HH:MM:SS (8 chars) + // HH:MM (5 chars) + + if (time_to_parse == nullptr || len == 0) + return false; + + const char *p = time_to_parse; + const char *end = time_to_parse + len; + uint16_t v1, v2, v3, v4, v5, v6; + + // Try date formats first (start with 4-digit year) + if (len >= 10 && time_to_parse[4] == '-') { + // YYYY-MM-DD... + if (!parse_digits(p, end, 4, v1)) + return false; + if (!expect_char(p, end, '-')) + return false; + if (!parse_digits(p, end, 2, v2)) + return false; + if (!expect_char(p, end, '-')) + return false; + if (!parse_digits(p, end, 2, v3)) + return false; + + esp_time.year = v1; + esp_time.month = v2; + esp_time.day_of_month = v3; + + if (p == end) { + // YYYY-MM-DD (date only) + return true; + } + + if (!expect_char(p, end, ' ')) + return false; + + // Continue with time part: HH:MM[:SS] + if (!parse_digits(p, end, 2, v4)) + return false; + if (!expect_char(p, end, ':')) + return false; + if (!parse_digits(p, end, 2, v5)) + return false; + + esp_time.hour = v4; + esp_time.minute = v5; + + if (p == end) { + // YYYY-MM-DD HH:MM + esp_time.second = 0; + return true; + } + + if (!expect_char(p, end, ':')) + return false; + if (!parse_digits(p, end, 2, v6)) + return false; + + esp_time.second = v6; + return p == end; // YYYY-MM-DD HH:MM:SS + } + + // Try time-only formats (HH:MM[:SS]) + if (len >= 5 && time_to_parse[2] == ':') { + if (!parse_digits(p, end, 2, v1)) + return false; + if (!expect_char(p, end, ':')) + return false; + if (!parse_digits(p, end, 2, v2)) + return false; + + esp_time.hour = v1; + esp_time.minute = v2; + + if (p == end) { + // HH:MM + esp_time.second = 0; + return true; + } + + if (!expect_char(p, end, ':')) + return false; + if (!parse_digits(p, end, 2, v3)) + return false; + + esp_time.second = v3; + return p == end; // HH:MM:SS + } + + return false; +} + void ESPTime::increment_second() { this->timestamp++; if (!increment_time_value(this->second, 0, 60)) @@ -193,27 +257,67 @@ void ESPTime::recalc_timestamp_utc(bool use_day_of_year) { } void ESPTime::recalc_timestamp_local() { - struct tm tm; +#ifdef USE_TIME_TIMEZONE + // Calculate timestamp as if fields were UTC + this->recalc_timestamp_utc(false); + if (this->timestamp == -1) { + return; // Invalid time + } - tm.tm_year = this->year - 1900; - tm.tm_mon = this->month - 1; - tm.tm_mday = this->day_of_month; - tm.tm_hour = this->hour; - tm.tm_min = this->minute; - tm.tm_sec = this->second; - tm.tm_isdst = -1; + // Now convert from local to UTC by adding the offset + // POSIX: local = utc - offset, so utc = local + offset + const auto &tz = time::get_global_tz(); - this->timestamp = mktime(&tm); + if (!tz.has_dst()) { + // No DST - just apply standard offset + this->timestamp += tz.std_offset_seconds; + return; + } + + // Try both interpretations to match libc mktime() with tm_isdst=-1 + // For ambiguous times (fall-back repeated hour), prefer standard time + // For invalid times (spring-forward skipped hour), libc normalizes forward + time_t utc_if_dst = this->timestamp + tz.dst_offset_seconds; + time_t utc_if_std = this->timestamp + tz.std_offset_seconds; + + bool dst_valid = time::is_in_dst(utc_if_dst, tz); + bool std_valid = !time::is_in_dst(utc_if_std, tz); + + if (dst_valid && std_valid) { + // Ambiguous time (repeated hour during fall-back) - prefer standard time + this->timestamp = utc_if_std; + } else if (dst_valid) { + // Only DST interpretation is valid + this->timestamp = utc_if_dst; + } else if (std_valid) { + // Only standard interpretation is valid + this->timestamp = utc_if_std; + } else { + // Invalid time (skipped hour during spring-forward) + // libc normalizes forward: 02:30 CST -> 08:30 UTC -> 03:30 CDT + // Using std offset achieves this since the UTC result falls during DST + this->timestamp = utc_if_std; + } +#else + // No timezone support - treat as UTC + this->recalc_timestamp_utc(false); +#endif } int32_t ESPTime::timezone_offset() { +#ifdef USE_TIME_TIMEZONE time_t now = ::time(nullptr); - struct tm local_tm = *::localtime(&now); - local_tm.tm_isdst = 0; // Cause mktime to ignore daylight saving time because we want to include it in the offset. - time_t local_time = mktime(&local_tm); - struct tm utc_tm = *::gmtime(&now); - time_t utc_time = mktime(&utc_tm); - return static_cast<int32_t>(local_time - utc_time); + const auto &tz = time::get_global_tz(); + // POSIX offset is positive west, but we return offset to add to UTC to get local + // So we negate the POSIX offset + if (time::is_in_dst(now, tz)) { + return -tz.dst_offset_seconds; + } + return -tz.std_offset_seconds; +#else + // No timezone support - no offset + return 0; +#endif } bool ESPTime::operator<(const ESPTime &other) const { return this->timestamp < other.timestamp; } diff --git a/esphome/core/time.h b/esphome/core/time.h index d9ce86131c..874f0db4b4 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -7,6 +7,10 @@ #include <span> #include <string> +#ifdef USE_TIME_TIMEZONE +#include "esphome/components/time/posix_tz.h" +#endif + namespace esphome { template<typename T> bool increment_time_value(T ¤t, uint16_t begin, uint16_t end); @@ -105,11 +109,17 @@ struct ESPTime { * @return The generated ESPTime */ static ESPTime from_epoch_local(time_t epoch) { - struct tm *c_tm = ::localtime(&epoch); - if (c_tm == nullptr) { - return ESPTime{}; // Return an invalid ESPTime +#ifdef USE_TIME_TIMEZONE + struct tm local_tm; + if (time::epoch_to_local_tm(epoch, time::get_global_tz(), &local_tm)) { + return ESPTime::from_c_tm(&local_tm, epoch); } - return ESPTime::from_c_tm(c_tm, epoch); + // Fallback to UTC if conversion failed + return ESPTime::from_epoch_utc(epoch); +#else + // No timezone support - return UTC (no TZ configured, localtime would return UTC anyway) + return ESPTime::from_epoch_utc(epoch); +#endif } /** Convert an UTC epoch timestamp to a UTC time ESPTime instance. * diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index e97b5bd7b0..78b65092ae 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -66,6 +66,7 @@ def create_test_config(config_name: str, includes: list[str]) -> dict: ], "build_flags": [ "-Og", # optimize for debug + "-DUSE_TIME_TIMEZONE", # enable timezone code paths for testing ], "debug_build_flags": [ # only for debug builds "-g3", # max debug info diff --git a/tests/components/time/posix_tz_parser.cpp b/tests/components/time/posix_tz_parser.cpp new file mode 100644 index 0000000000..d1747ef5b1 --- /dev/null +++ b/tests/components/time/posix_tz_parser.cpp @@ -0,0 +1,1275 @@ +// Tests for the POSIX TZ parser, time conversion functions, and ESPTime::strptime. +// +// Most tests here cover the C++ POSIX TZ string parser (parse_posix_tz), which is +// bridge code for backward compatibility — it will be removed before ESPHome 2026.9.0. +// After https://github.com/esphome/esphome/pull/14233 merges, the parser is solely +// used to handle timezone strings from Home Assistant clients older than 2026.3.0 +// that haven't been updated to send the pre-parsed ParsedTimezone protobuf struct. +// See https://github.com/esphome/backlog/issues/91 +// +// The epoch_to_local_tm, is_in_dst, and ESPTime::strptime tests cover conversion +// functions that will remain permanently. + +// Enable USE_TIME_TIMEZONE for tests +#define USE_TIME_TIMEZONE + +#include <gtest/gtest.h> +#include <cstdlib> +#include <ctime> +#include "esphome/components/time/posix_tz.h" +#include "esphome/core/time.h" + +namespace esphome::time::testing { + +// Helper to create UTC epoch from date/time components (for test readability) +static time_t make_utc(int year, int month, int day, int hour = 0, int min = 0, int sec = 0) { + int64_t days = 0; + for (int y = 1970; y < year; y++) { + days += (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? 366 : 365; + } + static const int DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + days += DAYS_BEFORE[month - 1]; + if (month > 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) + days++; // Leap year adjustment + days += day - 1; + return days * 86400 + hour * 3600 + min * 60 + sec; +} + +// ============================================================================ +// Basic TZ string parsing tests +// ============================================================================ + +TEST(PosixTzParser, ParseSimpleOffsetEST5) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5", tz)); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); // +5 hours (west of UTC) + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseNegativeOffsetCET) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("CET-1", tz)); + EXPECT_EQ(tz.std_offset_seconds, -1 * 3600); // -1 hour (east of UTC) + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseExplicitPositiveOffset) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("TEST+5", tz)); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseZeroOffset) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + EXPECT_EQ(tz.std_offset_seconds, 0); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseUSEasternWithDST) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0,M11.1.0", tz)); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, 4 * 3600); // Default: STD - 1hr + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.month, 3); + EXPECT_EQ(tz.dst_start.week, 2); + EXPECT_EQ(tz.dst_start.day_of_week, 0); // Sunday + EXPECT_EQ(tz.dst_start.time_seconds, 2 * 3600); // Default 2:00 AM + EXPECT_EQ(tz.dst_end.month, 11); + EXPECT_EQ(tz.dst_end.week, 1); + EXPECT_EQ(tz.dst_end.day_of_week, 0); +} + +TEST(PosixTzParser, ParseUSCentralWithTime) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("CST6CDT,M3.2.0/2,M11.1.0/2", tz)); + EXPECT_EQ(tz.std_offset_seconds, 6 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, 5 * 3600); + EXPECT_EQ(tz.dst_start.time_seconds, 2 * 3600); // 2:00 AM + EXPECT_EQ(tz.dst_end.time_seconds, 2 * 3600); +} + +TEST(PosixTzParser, ParseEuropeBerlin) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("CET-1CEST,M3.5.0,M10.5.0/3", tz)); + EXPECT_EQ(tz.std_offset_seconds, -1 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, -2 * 3600); // Default: STD - 1hr + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.month, 3); + EXPECT_EQ(tz.dst_start.week, 5); // Last week + EXPECT_EQ(tz.dst_end.month, 10); + EXPECT_EQ(tz.dst_end.week, 5); // Last week + EXPECT_EQ(tz.dst_end.time_seconds, 3 * 3600); // 3:00 AM +} + +TEST(PosixTzParser, ParseNewZealand) { + ParsedTimezone tz; + // Southern hemisphere - DST starts in Sept, ends in April + ASSERT_TRUE(parse_posix_tz("NZST-12NZDT,M9.5.0,M4.1.0/3", tz)); + EXPECT_EQ(tz.std_offset_seconds, -12 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, -13 * 3600); // Default: STD - 1hr + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.month, 9); // September + EXPECT_EQ(tz.dst_end.month, 4); // April +} + +TEST(PosixTzParser, ParseExplicitDstOffset) { + ParsedTimezone tz; + // Some places have non-standard DST offsets + ASSERT_TRUE(parse_posix_tz("TEST5DST4,M3.2.0,M11.1.0", tz)); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, 4 * 3600); + EXPECT_TRUE(tz.has_dst()); +} + +// ============================================================================ +// Angle-bracket notation tests (espressif/newlib-esp32#8) +// ============================================================================ + +TEST(PosixTzParser, ParseAngleBracketPositive) { + // Format: <+07>-7 means UTC+7 (name is "+07", offset is -7 hours east) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<+07>-7", tz)); + EXPECT_EQ(tz.std_offset_seconds, -7 * 3600); // -7 = 7 hours east of UTC + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseAngleBracketNegative) { + // <-03>3 means UTC-3 (name is "-03", offset is 3 hours west) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<-03>3", tz)); + EXPECT_EQ(tz.std_offset_seconds, 3 * 3600); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseAngleBracketWithDST) { + // <+10>-10<+11>,M10.1.0,M4.1.0/3 (Australia/Sydney style) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<+10>-10<+11>,M10.1.0,M4.1.0/3", tz)); + EXPECT_EQ(tz.std_offset_seconds, -10 * 3600); + EXPECT_EQ(tz.dst_offset_seconds, -11 * 3600); + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.month, 10); + EXPECT_EQ(tz.dst_end.month, 4); +} + +TEST(PosixTzParser, ParseAngleBracketNamed) { + // <AEST>-10 (Australian Eastern Standard Time) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<AEST>-10", tz)); + EXPECT_EQ(tz.std_offset_seconds, -10 * 3600); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseAngleBracketWithMinutes) { + // <+0545>-5:45 (Nepal) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<+0545>-5:45", tz)); + EXPECT_EQ(tz.std_offset_seconds, -(5 * 3600 + 45 * 60)); + EXPECT_FALSE(tz.has_dst()); +} + +// ============================================================================ +// Half-hour and unusual offset tests +// ============================================================================ + +TEST(PosixTzParser, ParseOffsetWithMinutesIndia) { + ParsedTimezone tz; + // India: UTC+5:30 + ASSERT_TRUE(parse_posix_tz("IST-5:30", tz)); + EXPECT_EQ(tz.std_offset_seconds, -(5 * 3600 + 30 * 60)); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseOffsetWithMinutesNepal) { + ParsedTimezone tz; + // Nepal: UTC+5:45 + ASSERT_TRUE(parse_posix_tz("NPT-5:45", tz)); + EXPECT_EQ(tz.std_offset_seconds, -(5 * 3600 + 45 * 60)); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, ParseOffsetWithSeconds) { + ParsedTimezone tz; + // Unusual but valid: offset with seconds + ASSERT_TRUE(parse_posix_tz("TEST-1:30:30", tz)); + EXPECT_EQ(tz.std_offset_seconds, -(1 * 3600 + 30 * 60 + 30)); +} + +TEST(PosixTzParser, ParseChathamIslands) { + // Chatham Islands: UTC+12:45 with DST + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45", tz)); + EXPECT_EQ(tz.std_offset_seconds, -(12 * 3600 + 45 * 60)); + EXPECT_EQ(tz.dst_offset_seconds, -(13 * 3600 + 45 * 60)); + EXPECT_TRUE(tz.has_dst()); +} + +// ============================================================================ +// Invalid input tests +// ============================================================================ + +TEST(PosixTzParser, ParseEmptyStringFails) { + ParsedTimezone tz; + EXPECT_FALSE(parse_posix_tz("", tz)); +} + +TEST(PosixTzParser, ParseNullFails) { + ParsedTimezone tz; + EXPECT_FALSE(parse_posix_tz(nullptr, tz)); +} + +TEST(PosixTzParser, ParseShortNameFails) { + ParsedTimezone tz; + // TZ name must be at least 3 characters + EXPECT_FALSE(parse_posix_tz("AB5", tz)); +} + +TEST(PosixTzParser, ParseMissingOffsetFails) { + ParsedTimezone tz; + EXPECT_FALSE(parse_posix_tz("EST", tz)); +} + +TEST(PosixTzParser, ParseUnterminatedBracketFails) { + ParsedTimezone tz; + EXPECT_FALSE(parse_posix_tz("<+07-7", tz)); // Missing closing > +} + +// ============================================================================ +// J-format and plain day number tests +// ============================================================================ + +TEST(PosixTzParser, ParseJFormatBasic) { + ParsedTimezone tz; + // J format: Julian day 1-365, not counting Feb 29 + ASSERT_TRUE(parse_posix_tz("EST5EDT,J60,J305", tz)); + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.type, DSTRuleType::JULIAN_NO_LEAP); + EXPECT_EQ(tz.dst_start.day, 60); // March 1 + EXPECT_EQ(tz.dst_end.type, DSTRuleType::JULIAN_NO_LEAP); + EXPECT_EQ(tz.dst_end.day, 305); // November 1 +} + +TEST(PosixTzParser, ParseJFormatWithTime) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5EDT,J60/2,J305/2", tz)); + EXPECT_EQ(tz.dst_start.day, 60); + EXPECT_EQ(tz.dst_start.time_seconds, 2 * 3600); + EXPECT_EQ(tz.dst_end.day, 305); + EXPECT_EQ(tz.dst_end.time_seconds, 2 * 3600); +} + +TEST(PosixTzParser, ParsePlainDayNumber) { + ParsedTimezone tz; + // Plain format: day 0-365, counting Feb 29 in leap years + ASSERT_TRUE(parse_posix_tz("EST5EDT,59,304", tz)); + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.type, DSTRuleType::DAY_OF_YEAR); + EXPECT_EQ(tz.dst_start.day, 59); + EXPECT_EQ(tz.dst_end.type, DSTRuleType::DAY_OF_YEAR); + EXPECT_EQ(tz.dst_end.day, 304); +} + +TEST(PosixTzParser, JFormatInvalidDayZero) { + ParsedTimezone tz; + // J format day must be 1-365, not 0 + EXPECT_FALSE(parse_posix_tz("EST5EDT,J0,J305", tz)); +} + +TEST(PosixTzParser, JFormatInvalidDay366) { + ParsedTimezone tz; + // J format day must be 1-365 + EXPECT_FALSE(parse_posix_tz("EST5EDT,J366,J305", tz)); +} + +TEST(PosixTzParser, ParsePlainDayNumberWithTime) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5EDT,59/3,304/1:30", tz)); + EXPECT_EQ(tz.dst_start.day, 59); + EXPECT_EQ(tz.dst_start.time_seconds, 3 * 3600); + EXPECT_EQ(tz.dst_end.day, 304); + EXPECT_EQ(tz.dst_end.time_seconds, 1 * 3600 + 30 * 60); +} + +TEST(PosixTzParser, PlainDayInvalidDay366) { + ParsedTimezone tz; + // Plain format day must be 0-365 + EXPECT_FALSE(parse_posix_tz("EST5EDT,366,304", tz)); +} + +// ============================================================================ +// Transition time edge cases (POSIX V3 allows -167 to +167 hours) +// ============================================================================ + +TEST(PosixTzParser, NegativeTransitionTime) { + ParsedTimezone tz; + // Negative transition time: /-1 means 11 PM (23:00) the previous day + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/-1,M11.1.0/2", tz)); + EXPECT_EQ(tz.dst_start.time_seconds, -1 * 3600); // -1 hour = 11 PM previous day + EXPECT_EQ(tz.dst_end.time_seconds, 2 * 3600); +} + +TEST(PosixTzParser, NegativeTransitionTimeWithMinutes) { + ParsedTimezone tz; + // /-1:30 means 10:30 PM the previous day + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/-1:30,M11.1.0", tz)); + EXPECT_EQ(tz.dst_start.time_seconds, -(1 * 3600 + 30 * 60)); +} + +TEST(PosixTzParser, LargeTransitionTime) { + ParsedTimezone tz; + // POSIX V3 allows transition times from -167 to +167 hours + // /25 means 1:00 AM the next day + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/25,M11.1.0", tz)); + EXPECT_EQ(tz.dst_start.time_seconds, 25 * 3600); +} + +TEST(PosixTzParser, MaxTransitionTime167Hours) { + ParsedTimezone tz; + // Maximum allowed transition time per POSIX V3 + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/167,M11.1.0", tz)); + EXPECT_EQ(tz.dst_start.time_seconds, 167 * 3600); +} + +TEST(PosixTzParser, TransitionTimeWithHoursMinutesSeconds) { + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/2:30:45,M11.1.0", tz)); + EXPECT_EQ(tz.dst_start.time_seconds, 2 * 3600 + 30 * 60 + 45); +} + +// ============================================================================ +// Invalid M format tests +// ============================================================================ + +TEST(PosixTzParser, MFormatInvalidMonth13) { + ParsedTimezone tz; + // Month must be 1-12 + EXPECT_FALSE(parse_posix_tz("EST5EDT,M13.1.0,M11.1.0", tz)); +} + +TEST(PosixTzParser, MFormatInvalidMonth0) { + ParsedTimezone tz; + // Month must be 1-12 + EXPECT_FALSE(parse_posix_tz("EST5EDT,M0.1.0,M11.1.0", tz)); +} + +TEST(PosixTzParser, MFormatInvalidWeek6) { + ParsedTimezone tz; + // Week must be 1-5 + EXPECT_FALSE(parse_posix_tz("EST5EDT,M3.6.0,M11.1.0", tz)); +} + +TEST(PosixTzParser, MFormatInvalidWeek0) { + ParsedTimezone tz; + // Week must be 1-5 + EXPECT_FALSE(parse_posix_tz("EST5EDT,M3.0.0,M11.1.0", tz)); +} + +TEST(PosixTzParser, MFormatInvalidDayOfWeek7) { + ParsedTimezone tz; + // Day of week must be 0-6 + EXPECT_FALSE(parse_posix_tz("EST5EDT,M3.2.7,M11.1.0", tz)); +} + +TEST(PosixTzParser, MissingEndRule) { + ParsedTimezone tz; + // POSIX requires both start and end rules if any rules are specified + EXPECT_FALSE(parse_posix_tz("EST5EDT,M3.2.0", tz)); +} + +TEST(PosixTzParser, MissingEndRuleJFormat) { + ParsedTimezone tz; + // POSIX requires both start and end rules if any rules are specified + EXPECT_FALSE(parse_posix_tz("EST5EDT,J60", tz)); +} + +TEST(PosixTzParser, MissingEndRulePlainDay) { + ParsedTimezone tz; + // POSIX requires both start and end rules if any rules are specified + EXPECT_FALSE(parse_posix_tz("EST5EDT,60", tz)); +} + +TEST(PosixTzParser, LowercaseMFormat) { + ParsedTimezone tz; + // Lowercase 'm' should be accepted + ASSERT_TRUE(parse_posix_tz("EST5EDT,m3.2.0,m11.1.0", tz)); + EXPECT_TRUE(tz.has_dst()); + EXPECT_EQ(tz.dst_start.month, 3); + EXPECT_EQ(tz.dst_end.month, 11); +} + +TEST(PosixTzParser, LowercaseJFormat) { + ParsedTimezone tz; + // Lowercase 'j' should be accepted + ASSERT_TRUE(parse_posix_tz("EST5EDT,j60,j305", tz)); + EXPECT_EQ(tz.dst_start.type, DSTRuleType::JULIAN_NO_LEAP); + EXPECT_EQ(tz.dst_start.day, 60); +} + +TEST(PosixTzParser, DstNameWithoutRules) { + ParsedTimezone tz; + // DST name present but no rules - treat as no DST since we can't determine transitions + ASSERT_TRUE(parse_posix_tz("EST5EDT", tz)); + EXPECT_FALSE(tz.has_dst()); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); +} + +TEST(PosixTzParser, TrailingCharactersIgnored) { + ParsedTimezone tz; + // Trailing characters after valid TZ should be ignored (parser stops at end of valid input) + // This matches libc behavior + ASSERT_TRUE(parse_posix_tz("EST5 extra garbage here", tz)); + EXPECT_EQ(tz.std_offset_seconds, 5 * 3600); + EXPECT_FALSE(tz.has_dst()); +} + +TEST(PosixTzParser, PlainDay365LeapYear) { + // Day 365 in leap year is Dec 31 + int month, day; + internal::day_of_year_to_month_day(365, 2024, month, day); + EXPECT_EQ(month, 12); + EXPECT_EQ(day, 31); +} + +TEST(PosixTzParser, PlainDay364NonLeapYear) { + // Day 364 (0-indexed) is Dec 31 in non-leap year (last valid day) + int month, day; + internal::day_of_year_to_month_day(364, 2025, month, day); + EXPECT_EQ(month, 12); + EXPECT_EQ(day, 31); +} + +// ============================================================================ +// Large offset tests +// ============================================================================ + +TEST(PosixTzParser, MaxOffset14Hours) { + ParsedTimezone tz; + // Line Islands (Kiribati) is UTC+14, the maximum offset + ASSERT_TRUE(parse_posix_tz("<+14>-14", tz)); + EXPECT_EQ(tz.std_offset_seconds, -14 * 3600); +} + +TEST(PosixTzParser, MaxNegativeOffset12Hours) { + ParsedTimezone tz; + // Baker Island is UTC-12 + ASSERT_TRUE(parse_posix_tz("<-12>12", tz)); + EXPECT_EQ(tz.std_offset_seconds, 12 * 3600); +} + +// ============================================================================ +// Helper function tests +// ============================================================================ + +TEST(PosixTzParser, JulianDay60IsMarch1) { + // J60 is always March 1 (J format ignores leap years by design) + int month, day; + internal::julian_to_month_day(60, month, day); + EXPECT_EQ(month, 3); + EXPECT_EQ(day, 1); +} + +TEST(PosixTzParser, DayOfYear59DiffersByLeap) { + int month, day; + // Day 59 in leap year is Feb 29 + internal::day_of_year_to_month_day(59, 2024, month, day); + EXPECT_EQ(month, 2); + EXPECT_EQ(day, 29); + // Day 59 in non-leap year is March 1 + internal::day_of_year_to_month_day(59, 2025, month, day); + EXPECT_EQ(month, 3); + EXPECT_EQ(day, 1); +} + +TEST(PosixTzParser, DayOfWeekKnownDates) { + // January 1, 1970 was Thursday (4) + EXPECT_EQ(internal::day_of_week(1970, 1, 1), 4); + // January 1, 2000 was Saturday (6) + EXPECT_EQ(internal::day_of_week(2000, 1, 1), 6); + // March 8, 2026 is Sunday (0) - US DST start + EXPECT_EQ(internal::day_of_week(2026, 3, 8), 0); +} + +TEST(PosixTzParser, LeapYearDetection) { + EXPECT_FALSE(internal::is_leap_year(1900)); // Divisible by 100 but not 400 + EXPECT_TRUE(internal::is_leap_year(2000)); // Divisible by 400 + EXPECT_TRUE(internal::is_leap_year(2024)); // Divisible by 4 + EXPECT_FALSE(internal::is_leap_year(2025)); // Not divisible by 4 +} + +TEST(PosixTzParser, JulianDay1IsJan1) { + int month, day; + internal::julian_to_month_day(1, month, day); + EXPECT_EQ(month, 1); + EXPECT_EQ(day, 1); +} + +TEST(PosixTzParser, JulianDay31IsJan31) { + int month, day; + internal::julian_to_month_day(31, month, day); + EXPECT_EQ(month, 1); + EXPECT_EQ(day, 31); +} + +TEST(PosixTzParser, JulianDay32IsFeb1) { + int month, day; + internal::julian_to_month_day(32, month, day); + EXPECT_EQ(month, 2); + EXPECT_EQ(day, 1); +} + +TEST(PosixTzParser, JulianDay59IsFeb28) { + int month, day; + internal::julian_to_month_day(59, month, day); + EXPECT_EQ(month, 2); + EXPECT_EQ(day, 28); +} + +TEST(PosixTzParser, JulianDay365IsDec31) { + int month, day; + internal::julian_to_month_day(365, month, day); + EXPECT_EQ(month, 12); + EXPECT_EQ(day, 31); +} + +TEST(PosixTzParser, DayOfYear0IsJan1) { + int month, day; + internal::day_of_year_to_month_day(0, 2025, month, day); + EXPECT_EQ(month, 1); + EXPECT_EQ(day, 1); +} + +TEST(PosixTzParser, DaysInMonthRegular) { + // Test all 12 months to ensure switch coverage + EXPECT_EQ(internal::days_in_month(2025, 1), 31); // Jan - default case + EXPECT_EQ(internal::days_in_month(2025, 2), 28); // Feb - case 2 + EXPECT_EQ(internal::days_in_month(2025, 3), 31); // Mar - default case + EXPECT_EQ(internal::days_in_month(2025, 4), 30); // Apr - case 4 + EXPECT_EQ(internal::days_in_month(2025, 5), 31); // May - default case + EXPECT_EQ(internal::days_in_month(2025, 6), 30); // Jun - case 6 + EXPECT_EQ(internal::days_in_month(2025, 7), 31); // Jul - default case + EXPECT_EQ(internal::days_in_month(2025, 8), 31); // Aug - default case + EXPECT_EQ(internal::days_in_month(2025, 9), 30); // Sep - case 9 + EXPECT_EQ(internal::days_in_month(2025, 10), 31); // Oct - default case + EXPECT_EQ(internal::days_in_month(2025, 11), 30); // Nov - case 11 + EXPECT_EQ(internal::days_in_month(2025, 12), 31); // Dec - default case +} + +TEST(PosixTzParser, DaysInMonthLeapYear) { + EXPECT_EQ(internal::days_in_month(2024, 2), 29); + EXPECT_EQ(internal::days_in_month(2025, 2), 28); +} + +// ============================================================================ +// DST transition calculation tests +// ============================================================================ + +TEST(PosixTzParser, DstStartUSEastern2026) { + // March 8, 2026 is 2nd Sunday of March + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + time_t dst_start = internal::calculate_dst_transition(2026, tz.dst_start, tz.std_offset_seconds); + struct tm tm; + internal::epoch_to_tm_utc(dst_start, &tm); + + // At 2:00 AM EST (UTC-5), so 7:00 AM UTC + EXPECT_EQ(tm.tm_year + 1900, 2026); + EXPECT_EQ(tm.tm_mon + 1, 3); // March + EXPECT_EQ(tm.tm_mday, 8); // 8th + EXPECT_EQ(tm.tm_hour, 7); // 7:00 UTC = 2:00 EST +} + +TEST(PosixTzParser, DstEndUSEastern2026) { + // November 1, 2026 is 1st Sunday of November + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + time_t dst_end = internal::calculate_dst_transition(2026, tz.dst_end, tz.dst_offset_seconds); + struct tm tm; + internal::epoch_to_tm_utc(dst_end, &tm); + + // At 2:00 AM EDT (UTC-4), so 6:00 AM UTC + EXPECT_EQ(tm.tm_year + 1900, 2026); + EXPECT_EQ(tm.tm_mon + 1, 11); // November + EXPECT_EQ(tm.tm_mday, 1); // 1st + EXPECT_EQ(tm.tm_hour, 6); // 6:00 UTC = 2:00 EDT +} + +TEST(PosixTzParser, LastSundayOfMarch2026) { + // Europe: M3.5.0 = last Sunday of March = March 29, 2026 + DSTRule rule{}; + rule.type = DSTRuleType::MONTH_WEEK_DAY; + rule.month = 3; + rule.week = 5; + rule.day_of_week = 0; + rule.time_seconds = 2 * 3600; + time_t transition = internal::calculate_dst_transition(2026, rule, 0); + struct tm tm; + internal::epoch_to_tm_utc(transition, &tm); + EXPECT_EQ(tm.tm_mday, 29); + EXPECT_EQ(tm.tm_wday, 0); // Sunday +} + +TEST(PosixTzParser, LastSundayOfOctober2026) { + // Europe: M10.5.0 = last Sunday of October = October 25, 2026 + DSTRule rule{}; + rule.type = DSTRuleType::MONTH_WEEK_DAY; + rule.month = 10; + rule.week = 5; + rule.day_of_week = 0; + rule.time_seconds = 3 * 3600; + time_t transition = internal::calculate_dst_transition(2026, rule, 0); + struct tm tm; + internal::epoch_to_tm_utc(transition, &tm); + EXPECT_EQ(tm.tm_mday, 25); + EXPECT_EQ(tm.tm_wday, 0); // Sunday +} + +TEST(PosixTzParser, FirstSundayOfApril2026) { + // April 5, 2026 is 1st Sunday + DSTRule rule{}; + rule.type = DSTRuleType::MONTH_WEEK_DAY; + rule.month = 4; + rule.week = 1; + rule.day_of_week = 0; + rule.time_seconds = 0; + time_t transition = internal::calculate_dst_transition(2026, rule, 0); + struct tm tm; + internal::epoch_to_tm_utc(transition, &tm); + EXPECT_EQ(tm.tm_mday, 5); + EXPECT_EQ(tm.tm_wday, 0); +} + +// ============================================================================ +// DST detection tests +// ============================================================================ + +TEST(PosixTzParser, IsInDstUSEasternSummer) { + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + // July 4, 2026 12:00 UTC - definitely in DST + time_t summer = make_utc(2026, 7, 4, 12); + EXPECT_TRUE(is_in_dst(summer, tz)); +} + +TEST(PosixTzParser, IsInDstUSEasternWinter) { + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + // January 15, 2026 12:00 UTC - definitely not in DST + time_t winter = make_utc(2026, 1, 15, 12); + EXPECT_FALSE(is_in_dst(winter, tz)); +} + +TEST(PosixTzParser, IsInDstNoDstTimezone) { + ParsedTimezone tz; + parse_posix_tz("IST-5:30", tz); + + // July 15, 2026 12:00 UTC + time_t epoch = make_utc(2026, 7, 15, 12); + EXPECT_FALSE(is_in_dst(epoch, tz)); +} + +TEST(PosixTzParser, SouthernHemisphereDstSummer) { + ParsedTimezone tz; + parse_posix_tz("NZST-12NZDT,M9.5.0,M4.1.0/3", tz); + + // December 15, 2025 12:00 UTC - summer in NZ, should be in DST + time_t nz_summer = make_utc(2025, 12, 15, 12); + EXPECT_TRUE(is_in_dst(nz_summer, tz)); +} + +TEST(PosixTzParser, SouthernHemisphereDstWinter) { + ParsedTimezone tz; + parse_posix_tz("NZST-12NZDT,M9.5.0,M4.1.0/3", tz); + + // July 15, 2026 12:00 UTC - winter in NZ, should NOT be in DST + time_t nz_winter = make_utc(2026, 7, 15, 12); + EXPECT_FALSE(is_in_dst(nz_winter, tz)); +} + +// ============================================================================ +// epoch_to_local_tm tests +// ============================================================================ + +TEST(PosixTzParser, EpochToLocalBasic) { + ParsedTimezone tz; + parse_posix_tz("UTC0", tz); + + time_t epoch = 0; // Jan 1, 1970 00:00:00 UTC + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 70); + EXPECT_EQ(local.tm_mon, 0); + EXPECT_EQ(local.tm_mday, 1); + EXPECT_EQ(local.tm_hour, 0); +} + +TEST(PosixTzParser, EpochToLocalNegativeEpoch) { + ParsedTimezone tz; + parse_posix_tz("UTC0", tz); + + // Dec 31, 1969 23:59:59 UTC (1 second before epoch) + time_t epoch = -1; + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 69); // 1969 + EXPECT_EQ(local.tm_mon, 11); // December + EXPECT_EQ(local.tm_mday, 31); + EXPECT_EQ(local.tm_hour, 23); + EXPECT_EQ(local.tm_min, 59); + EXPECT_EQ(local.tm_sec, 59); +} + +TEST(PosixTzParser, EpochToLocalNullTmFails) { + ParsedTimezone tz; + parse_posix_tz("UTC0", tz); + EXPECT_FALSE(epoch_to_local_tm(0, tz, nullptr)); +} + +TEST(PosixTzParser, EpochToLocalWithOffset) { + ParsedTimezone tz; + parse_posix_tz("EST5", tz); // UTC-5 + + // Jan 1, 2026 05:00:00 UTC should be Jan 1, 2026 00:00:00 EST + time_t utc_epoch = make_utc(2026, 1, 1, 5); + + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(utc_epoch, tz, &local)); + EXPECT_EQ(local.tm_hour, 0); // Midnight EST + EXPECT_EQ(local.tm_mday, 1); + EXPECT_EQ(local.tm_isdst, 0); +} + +TEST(PosixTzParser, EpochToLocalDstTransition) { + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + // July 4, 2026 16:00 UTC = 12:00 EDT (noon) + time_t utc_epoch = make_utc(2026, 7, 4, 16); + + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(utc_epoch, tz, &local)); + EXPECT_EQ(local.tm_hour, 12); // Noon EDT + EXPECT_EQ(local.tm_isdst, 1); +} + +// ============================================================================ +// Verification against libc +// ============================================================================ + +class LibcVerificationTest : public ::testing::TestWithParam<std::tuple<const char *, time_t>> { + protected: + // NOLINTNEXTLINE(readability-identifier-naming) - Google Test requires this name + void SetUp() override { + // Save current TZ + const char *current_tz = getenv("TZ"); + saved_tz_ = current_tz ? current_tz : ""; + had_tz_ = current_tz != nullptr; + } + + // NOLINTNEXTLINE(readability-identifier-naming) - Google Test requires this name + void TearDown() override { + // Restore TZ + if (had_tz_) { + setenv("TZ", saved_tz_.c_str(), 1); + } else { + unsetenv("TZ"); + } + tzset(); + } + + private: + std::string saved_tz_; + bool had_tz_{false}; +}; + +TEST_P(LibcVerificationTest, MatchesLibc) { + auto [tz_str, epoch] = GetParam(); + + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + + // Our implementation + struct tm our_tm {}; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &our_tm)); + + // libc implementation + setenv("TZ", tz_str, 1); + tzset(); + struct tm *libc_tm = localtime(&epoch); + ASSERT_NE(libc_tm, nullptr); + + EXPECT_EQ(our_tm.tm_year, libc_tm->tm_year); + EXPECT_EQ(our_tm.tm_mon, libc_tm->tm_mon); + EXPECT_EQ(our_tm.tm_mday, libc_tm->tm_mday); + EXPECT_EQ(our_tm.tm_hour, libc_tm->tm_hour); + EXPECT_EQ(our_tm.tm_min, libc_tm->tm_min); + EXPECT_EQ(our_tm.tm_sec, libc_tm->tm_sec); + EXPECT_EQ(our_tm.tm_isdst, libc_tm->tm_isdst); +} + +INSTANTIATE_TEST_SUITE_P(USEastern, LibcVerificationTest, + ::testing::Values(std::make_tuple("EST5EDT,M3.2.0/2,M11.1.0/2", 1704067200), + std::make_tuple("EST5EDT,M3.2.0/2,M11.1.0/2", 1720000000), + std::make_tuple("EST5EDT,M3.2.0/2,M11.1.0/2", 1735689600))); + +INSTANTIATE_TEST_SUITE_P(AngleBracket, LibcVerificationTest, + ::testing::Values(std::make_tuple("<+07>-7", 1704067200), + std::make_tuple("<+07>-7", 1720000000))); + +INSTANTIATE_TEST_SUITE_P(India, LibcVerificationTest, + ::testing::Values(std::make_tuple("IST-5:30", 1704067200), + std::make_tuple("IST-5:30", 1720000000))); + +INSTANTIATE_TEST_SUITE_P(NewZealand, LibcVerificationTest, + ::testing::Values(std::make_tuple("NZST-12NZDT,M9.5.0,M4.1.0/3", 1704067200), + std::make_tuple("NZST-12NZDT,M9.5.0,M4.1.0/3", 1720000000))); + +INSTANTIATE_TEST_SUITE_P(USCentral, LibcVerificationTest, + ::testing::Values(std::make_tuple("CST6CDT,M3.2.0/2,M11.1.0/2", 1704067200), + std::make_tuple("CST6CDT,M3.2.0/2,M11.1.0/2", 1720000000), + std::make_tuple("CST6CDT,M3.2.0/2,M11.1.0/2", 1735689600))); + +INSTANTIATE_TEST_SUITE_P(EuropeBerlin, LibcVerificationTest, + ::testing::Values(std::make_tuple("CET-1CEST,M3.5.0,M10.5.0/3", 1704067200), + std::make_tuple("CET-1CEST,M3.5.0,M10.5.0/3", 1720000000), + std::make_tuple("CET-1CEST,M3.5.0,M10.5.0/3", 1735689600))); + +INSTANTIATE_TEST_SUITE_P(AustraliaSydney, LibcVerificationTest, + ::testing::Values(std::make_tuple("AEST-10AEDT,M10.1.0,M4.1.0/3", 1704067200), + std::make_tuple("AEST-10AEDT,M10.1.0,M4.1.0/3", 1720000000), + std::make_tuple("AEST-10AEDT,M10.1.0,M4.1.0/3", 1735689600))); + +// ============================================================================ +// DST boundary edge cases +// ============================================================================ + +TEST(PosixTzParser, DstBoundaryJustBeforeSpringForward) { + // Test 1 second before DST starts + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + // March 8, 2026 06:59:59 UTC = 01:59:59 EST (1 second before spring forward) + time_t before_epoch = make_utc(2026, 3, 8, 6, 59, 59); + EXPECT_FALSE(is_in_dst(before_epoch, tz)); + + // March 8, 2026 07:00:00 UTC = 02:00:00 EST -> 03:00:00 EDT (DST started) + time_t after_epoch = make_utc(2026, 3, 8, 7); + EXPECT_TRUE(is_in_dst(after_epoch, tz)); +} + +TEST(PosixTzParser, DstBoundaryJustBeforeFallBack) { + // Test 1 second before DST ends + ParsedTimezone tz; + parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz); + + // November 1, 2026 05:59:59 UTC = 01:59:59 EDT (1 second before fall back) + time_t before_epoch = make_utc(2026, 11, 1, 5, 59, 59); + EXPECT_TRUE(is_in_dst(before_epoch, tz)); + + // November 1, 2026 06:00:00 UTC = 02:00:00 EDT -> 01:00:00 EST (DST ended) + time_t after_epoch = make_utc(2026, 11, 1, 6); + EXPECT_FALSE(is_in_dst(after_epoch, tz)); +} + +} // namespace esphome::time::testing + +// ============================================================================ +// ESPTime::strptime tests (replaces sscanf-based parsing) +// ============================================================================ + +namespace esphome::testing { + +TEST(ESPTimeStrptime, FullDateTime) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("2026-03-15 14:30:45", 19, t)); + EXPECT_EQ(t.year, 2026); + EXPECT_EQ(t.month, 3); + EXPECT_EQ(t.day_of_month, 15); + EXPECT_EQ(t.hour, 14); + EXPECT_EQ(t.minute, 30); + EXPECT_EQ(t.second, 45); +} + +TEST(ESPTimeStrptime, DateTimeNoSeconds) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("2026-03-15 14:30", 16, t)); + EXPECT_EQ(t.year, 2026); + EXPECT_EQ(t.month, 3); + EXPECT_EQ(t.day_of_month, 15); + EXPECT_EQ(t.hour, 14); + EXPECT_EQ(t.minute, 30); + EXPECT_EQ(t.second, 0); +} + +TEST(ESPTimeStrptime, DateOnly) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("2026-03-15", 10, t)); + EXPECT_EQ(t.year, 2026); + EXPECT_EQ(t.month, 3); + EXPECT_EQ(t.day_of_month, 15); +} + +TEST(ESPTimeStrptime, TimeWithSeconds) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("14:30:45", 8, t)); + EXPECT_EQ(t.hour, 14); + EXPECT_EQ(t.minute, 30); + EXPECT_EQ(t.second, 45); +} + +TEST(ESPTimeStrptime, TimeNoSeconds) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("14:30", 5, t)); + EXPECT_EQ(t.hour, 14); + EXPECT_EQ(t.minute, 30); + EXPECT_EQ(t.second, 0); +} + +TEST(ESPTimeStrptime, Midnight) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("00:00:00", 8, t)); + EXPECT_EQ(t.hour, 0); + EXPECT_EQ(t.minute, 0); + EXPECT_EQ(t.second, 0); +} + +TEST(ESPTimeStrptime, EndOfDay) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("23:59:59", 8, t)); + EXPECT_EQ(t.hour, 23); + EXPECT_EQ(t.minute, 59); + EXPECT_EQ(t.second, 59); +} + +TEST(ESPTimeStrptime, LeapYearDate) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("2024-02-29", 10, t)); + EXPECT_EQ(t.year, 2024); + EXPECT_EQ(t.month, 2); + EXPECT_EQ(t.day_of_month, 29); +} + +TEST(ESPTimeStrptime, NewYearsEve) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("2026-12-31 23:59:59", 19, t)); + EXPECT_EQ(t.year, 2026); + EXPECT_EQ(t.month, 12); + EXPECT_EQ(t.day_of_month, 31); + EXPECT_EQ(t.hour, 23); + EXPECT_EQ(t.minute, 59); + EXPECT_EQ(t.second, 59); +} + +TEST(ESPTimeStrptime, EmptyStringFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime("", 0, t)); +} + +TEST(ESPTimeStrptime, NullInputFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime(nullptr, 0, t)); +} + +TEST(ESPTimeStrptime, InvalidFormatFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime("not-a-date", 10, t)); +} + +TEST(ESPTimeStrptime, PartialDateFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime("2026-03", 7, t)); +} + +TEST(ESPTimeStrptime, PartialTimeFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime("14:", 3, t)); +} + +TEST(ESPTimeStrptime, ExtraCharactersFails) { + ESPTime t{}; + // Full datetime with extra characters should fail + EXPECT_FALSE(ESPTime::strptime("2026-03-15 14:30:45x", 20, t)); +} + +TEST(ESPTimeStrptime, WrongSeparatorFails) { + ESPTime t{}; + EXPECT_FALSE(ESPTime::strptime("2026/03/15", 10, t)); +} + +TEST(ESPTimeStrptime, LeadingZeroTime) { + ESPTime t{}; + ASSERT_TRUE(ESPTime::strptime("01:05:09", 8, t)); + EXPECT_EQ(t.hour, 1); + EXPECT_EQ(t.minute, 5); + EXPECT_EQ(t.second, 9); +} + +// ============================================================================ +// recalc_timestamp_local() tests - verify behavior matches libc mktime() +// ============================================================================ + +// Helper to call libc mktime with same fields +static time_t libc_mktime(int year, int month, int day, int hour, int min, int sec) { + struct tm tm {}; + tm.tm_year = year - 1900; + tm.tm_mon = month - 1; + tm.tm_mday = day; + tm.tm_hour = hour; + tm.tm_min = min; + tm.tm_sec = sec; + tm.tm_isdst = -1; // Let libc determine DST + return mktime(&tm); +} + +// Helper to create ESPTime and call recalc_timestamp_local +static time_t esptime_recalc_local(int year, int month, int day, int hour, int min, int sec) { + ESPTime t{}; + t.year = year; + t.month = month; + t.day_of_month = day; + t.hour = hour; + t.minute = min; + t.second = sec; + t.day_of_week = 1; // Placeholder for fields_in_range() + t.day_of_year = 1; + t.recalc_timestamp_local(); + return t.timestamp; +} + +TEST(RecalcTimestampLocal, NormalTimeMatchesLibc) { + // Set timezone to US Central (CST6CDT) + const char *tz_str = "CST6CDT,M3.2.0,M11.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Test a normal time in winter (no DST) + // January 15, 2026 at 10:30:00 CST + time_t libc_result = libc_mktime(2026, 1, 15, 10, 30, 0); + time_t esp_result = esptime_recalc_local(2026, 1, 15, 10, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test a normal time in summer (DST active) + // July 15, 2026 at 10:30:00 CDT + libc_result = libc_mktime(2026, 7, 15, 10, 30, 0); + esp_result = esptime_recalc_local(2026, 7, 15, 10, 30, 0); + EXPECT_EQ(esp_result, libc_result); +} + +TEST(RecalcTimestampLocal, SpringForwardSkippedHour) { + // Set timezone to US Central (CST6CDT) + // DST starts March 8, 2026 at 2:00 AM -> clocks jump to 3:00 AM + const char *tz_str = "CST6CDT,M3.2.0,M11.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Test time before the transition (1:30 AM CST exists) + time_t libc_result = libc_mktime(2026, 3, 8, 1, 30, 0); + time_t esp_result = esptime_recalc_local(2026, 3, 8, 1, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test time after the transition (3:30 AM CDT exists) + libc_result = libc_mktime(2026, 3, 8, 3, 30, 0); + esp_result = esptime_recalc_local(2026, 3, 8, 3, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test the skipped hour (2:30 AM doesn't exist - gets normalized) + // Both implementations should produce the same result + libc_result = libc_mktime(2026, 3, 8, 2, 30, 0); + esp_result = esptime_recalc_local(2026, 3, 8, 2, 30, 0); + EXPECT_EQ(esp_result, libc_result); +} + +TEST(RecalcTimestampLocal, FallBackRepeatedHour) { + // Set timezone to US Central (CST6CDT) + // DST ends November 1, 2026 at 2:00 AM -> clocks fall back to 1:00 AM + const char *tz_str = "CST6CDT,M3.2.0,M11.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Test time before the transition (midnight CDT) + time_t libc_result = libc_mktime(2026, 11, 1, 0, 30, 0); + time_t esp_result = esptime_recalc_local(2026, 11, 1, 0, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test time well after the transition (3:00 AM CST) + libc_result = libc_mktime(2026, 11, 1, 3, 0, 0); + esp_result = esptime_recalc_local(2026, 11, 1, 3, 0, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test the repeated hour (1:30 AM occurs twice) + // libc behavior varies by platform for this edge case, so we verify our + // consistent behavior: prefer standard time (later UTC timestamp) + esp_result = esptime_recalc_local(2026, 11, 1, 1, 30, 0); + time_t std_interpretation = esptime_recalc_local(2026, 11, 1, 2, 30, 0) - 3600; // 2:30 CST - 1 hour + EXPECT_EQ(esp_result, std_interpretation); +} + +TEST(RecalcTimestampLocal, SouthernHemisphereDST) { + // Set timezone to Australia/Sydney (AEST-10AEDT,M10.1.0,M4.1.0) + // DST starts first Sunday of October, ends first Sunday of April + const char *tz_str = "AEST-10AEDT,M10.1.0,M4.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Test winter time (July - no DST in southern hemisphere) + time_t libc_result = libc_mktime(2026, 7, 15, 10, 30, 0); + time_t esp_result = esptime_recalc_local(2026, 7, 15, 10, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Test summer time (January - DST active in southern hemisphere) + libc_result = libc_mktime(2026, 1, 15, 10, 30, 0); + esp_result = esptime_recalc_local(2026, 1, 15, 10, 30, 0); + EXPECT_EQ(esp_result, libc_result); +} + +TEST(RecalcTimestampLocal, ExactTransitionBoundary) { + // Test exact boundary of spring forward transition + // Mar 8, 2026 at 2:00 AM CST -> 3:00 AM CDT (clocks skip forward) + const char *tz_str = "CST6CDT,M3.2.0,M11.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // 1:59:59 AM CST - last second before transition (still standard time) + time_t libc_result = libc_mktime(2026, 3, 8, 1, 59, 59); + time_t esp_result = esptime_recalc_local(2026, 3, 8, 1, 59, 59); + EXPECT_EQ(esp_result, libc_result); + + // 3:00:00 AM CDT - first second after transition (now DST) + libc_result = libc_mktime(2026, 3, 8, 3, 0, 0); + esp_result = esptime_recalc_local(2026, 3, 8, 3, 0, 0); + EXPECT_EQ(esp_result, libc_result); + + // Verify the gap: 3:00 AM CDT should be exactly 1 second after 1:59:59 AM CST + time_t before_transition = esptime_recalc_local(2026, 3, 8, 1, 59, 59); + time_t after_transition = esptime_recalc_local(2026, 3, 8, 3, 0, 0); + EXPECT_EQ(after_transition - before_transition, 1); +} + +TEST(RecalcTimestampLocal, NonDefaultTransitionTime) { + // Test DST transition at 3:00 AM instead of default 2:00 AM + // Using custom transition time: CST6CDT,M3.2.0/3,M11.1.0/3 + const char *tz_str = "CST6CDT,M3.2.0/3,M11.1.0/3"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // 2:30 AM should still be standard time (transition at 3:00 AM) + time_t libc_result = libc_mktime(2026, 3, 8, 2, 30, 0); + time_t esp_result = esptime_recalc_local(2026, 3, 8, 2, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // 4:00 AM should be DST (after 3:00 AM transition) + libc_result = libc_mktime(2026, 3, 8, 4, 0, 0); + esp_result = esptime_recalc_local(2026, 3, 8, 4, 0, 0); + EXPECT_EQ(esp_result, libc_result); +} + +TEST(RecalcTimestampLocal, YearBoundaryDST) { + // Test southern hemisphere DST across year boundary + // Australia/Sydney: DST active from October to April (spans Jan 1) + const char *tz_str = "AEST-10AEDT,M10.1.0,M4.1.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Dec 31, 2025 at 23:30 - DST should be active + time_t libc_result = libc_mktime(2025, 12, 31, 23, 30, 0); + time_t esp_result = esptime_recalc_local(2025, 12, 31, 23, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Jan 1, 2026 at 00:30 - DST should still be active + libc_result = libc_mktime(2026, 1, 1, 0, 30, 0); + esp_result = esptime_recalc_local(2026, 1, 1, 0, 30, 0); + EXPECT_EQ(esp_result, libc_result); + + // Verify both are in DST (11 hour offset from UTC, not 10) + // The timestamps should be 1 hour apart + time_t dec31 = esptime_recalc_local(2025, 12, 31, 23, 30, 0); + time_t jan1 = esptime_recalc_local(2026, 1, 1, 0, 30, 0); + EXPECT_EQ(jan1 - dec31, 3600); // 1 hour difference +} + +// ============================================================================ +// ESPTime::timezone_offset() tests +// ============================================================================ + +TEST(TimezoneOffset, NoTimezone) { + // When no timezone is set, offset should be 0 + time::ParsedTimezone tz{}; + set_global_tz(tz); + + int32_t offset = ESPTime::timezone_offset(); + EXPECT_EQ(offset, 0); +} + +TEST(TimezoneOffset, FixedOffsetPositive) { + // India: UTC+5:30 (no DST) + const char *tz_str = "IST-5:30"; + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + int32_t offset = ESPTime::timezone_offset(); + // Offset should be +5:30 = 19800 seconds (to add to UTC to get local) + EXPECT_EQ(offset, 5 * 3600 + 30 * 60); +} + +TEST(TimezoneOffset, FixedOffsetNegative) { + // US Eastern Standard Time: UTC-5 (testing without DST rules) + const char *tz_str = "EST5"; + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + int32_t offset = ESPTime::timezone_offset(); + // Offset should be -5 hours = -18000 seconds + EXPECT_EQ(offset, -5 * 3600); +} + +TEST(TimezoneOffset, WithDstReturnsCorrectOffsetBasedOnCurrentTime) { + // US Eastern with DST + const char *tz_str = "EST5EDT,M3.2.0,M11.1.0"; + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Get current time and check offset matches expected based on DST status + time_t now = ::time(nullptr); + int32_t offset = ESPTime::timezone_offset(); + + // Verify offset matches what is_in_dst says + if (time::is_in_dst(now, tz)) { + // During DST, offset should be -4 hours (EDT) + EXPECT_EQ(offset, -4 * 3600); + } else { + // During standard time, offset should be -5 hours (EST) + EXPECT_EQ(offset, -5 * 3600); + } +} + +} // namespace esphome::testing From 50e7571f4c603f460a2dffa2b78eacc0a6dd5014 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 18:17:25 -0700 Subject: [PATCH 0974/2030] [web_server_idf] Prefer make_unique_for_overwrite for noninit recv buffer (#14279) --- esphome/components/web_server_idf/web_server_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 4034a22586..f18570965b 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -921,7 +921,7 @@ esp_err_t AsyncWebServer::handle_multipart_upload_(httpd_req_t *r, const char *c }); // Use heap buffer - 1460 bytes is too large for the httpd task stack - auto buffer = std::make_unique<char[]>(MULTIPART_CHUNK_SIZE); + auto buffer = std::make_unique_for_overwrite<char[]>(MULTIPART_CHUNK_SIZE); size_t bytes_since_yield = 0; for (size_t remaining = r->content_len; remaining > 0;) { From 15846137a6c64bbbc44345f29ff17d40ac92f1bb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 18:17:52 -0700 Subject: [PATCH 0975/2030] [rp2040] Update arduino-pico framework from 3.9.4 to 5.5.0 (#14328) --- .clang-tidy.hash | 2 +- esphome/components/rp2040/__init__.py | 8 +-- esphome/components/rp2040/gpio.cpp | 2 +- .../components/uart/uart_component_rp2040.cpp | 4 +- .../components/wifi/wifi_component_pico_w.cpp | 53 +++++++++++++------ platformio.ini | 4 +- 6 files changed, 46 insertions(+), 27 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 777c846371..767da3f33e 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -5eb1e5852765114ad06533220d3160b6c23f5ccefc4de41828699de5dfff5ad6 +b97e16a84153b2a4cfc51137cd6121db3c32374504b2bea55144413b3e573052 diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 3a1ea16fa3..23f12e651f 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -91,18 +91,18 @@ def _parse_platform_version(value): # The default/recommended arduino framework version # - https://github.com/earlephilhower/arduino-pico/releases # - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico -RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(3, 9, 4) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 0) # The raspberrypi platform version to use for arduino frameworks # - https://github.com/maxgerhardt/platform-raspberrypi/tags -RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.2.0-gcc12" +RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.4.0-gcc14-arduinopico460" def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(3, 9, 4), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(3, 9, 4), None), + "dev": (cv.Version(5, 5, 0), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(5, 5, 0), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/esphome/components/rp2040/gpio.cpp b/esphome/components/rp2040/gpio.cpp index 2b1699f888..4b3c98104c 100644 --- a/esphome/components/rp2040/gpio.cpp +++ b/esphome/components/rp2040/gpio.cpp @@ -106,7 +106,7 @@ void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) { sio_hw->gpio_oe_set = arg->mask; } else if (flags & gpio::FLAG_INPUT) { sio_hw->gpio_oe_clr = arg->mask; - hw_write_masked(&padsbank0_hw->io[arg->pin], + hw_write_masked(&pads_bank0_hw->io[arg->pin], (bool_to_bit(flags & gpio::FLAG_PULLUP) << PADS_BANK0_GPIO0_PUE_LSB) | (bool_to_bit(flags & gpio::FLAG_PULLDOWN) << PADS_BANK0_GPIO0_PDE_LSB), PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS); diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 0c6834055c..faf8f4d90f 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -115,8 +115,8 @@ void RP2040UartComponent::setup() { if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) { ESP_LOGV(TAG, "Using SerialPIO"); - pin_size_t tx = this->tx_pin_ == nullptr ? SerialPIO::NOPIN : this->tx_pin_->get_pin(); - pin_size_t rx = this->rx_pin_ == nullptr ? SerialPIO::NOPIN : this->rx_pin_->get_pin(); + pin_size_t tx = this->tx_pin_ == nullptr ? NOPIN : this->tx_pin_->get_pin(); + pin_size_t rx = this->rx_pin_ == nullptr ? NOPIN : this->rx_pin_->get_pin(); auto *serial = new SerialPIO(tx, rx, this->rx_buffer_size_); // NOLINT(cppcoreguidelines-owning-memory) serial->begin(this->baud_rate_, config); if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 1baf21e2b2..9b2c077dc5 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -78,8 +78,13 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { return false; #endif - auto ret = WiFi.begin(ap.ssid_.c_str(), ap.password_.c_str()); - if (ret != WL_CONNECTED) + // Use beginNoBlock to avoid WiFi.begin()'s additional 2x timeout wait loop on top of + // CYW43::begin()'s internal blocking join. CYW43::begin() blocks for up to 10 seconds + // (default timeout) to complete the join - this is required because the LwipIntfDev netif + // setup depends on begin() succeeding. beginNoBlock() skips the outer wait loop, saving + // up to 20 additional seconds of blocking per attempt. + auto ret = WiFi.beginNoBlock(ap.ssid_.c_str(), ap.password_.c_str()); + if (ret == WL_IDLE_STATUS) return false; return true; @@ -116,13 +121,19 @@ const char *get_disconnect_reason_str(uint8_t reason) { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { - int status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); + // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino + // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif + // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's + // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. + // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. + int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: - case CYW43_LINK_NOIP: + // WiFi joined, check if we have an IP address via the Arduino framework's WiFi class + if (WiFi.status() == WL_CONNECTED) { + return WiFiSTAConnectStatus::CONNECTED; + } return WiFiSTAConnectStatus::CONNECTING; - case CYW43_LINK_UP: - return WiFiSTAConnectStatus::CONNECTED; case CYW43_LINK_FAIL: case CYW43_LINK_BADAUTH: return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; @@ -139,18 +150,24 @@ int WiFiComponent::s_wifi_scan_result(void *env, const cyw43_ev_scan_result_t *r void WiFiComponent::wifi_scan_result(void *env, const cyw43_ev_scan_result_t *result) { s_scan_result_count++; - const char *ssid_cstr = reinterpret_cast<const char *>(result->ssid); + + // CYW43 scan results have ssid as a 32-byte buffer that is NOT null-terminated. + // Use ssid_len to create a properly terminated copy for string operations. + uint8_t len = std::min(result->ssid_len, static_cast<uint8_t>(sizeof(result->ssid))); + char ssid_buf[33]; // 32 max + null terminator + memcpy(ssid_buf, result->ssid, len); + ssid_buf[len] = '\0'; // Skip networks that don't match any configured network (unless full results needed) - if (!this->needs_full_scan_results_() && !this->matches_configured_network_(ssid_cstr, result->bssid)) { - this->log_discarded_scan_result_(ssid_cstr, result->bssid, result->rssi, result->channel); + if (!this->needs_full_scan_results_() && !this->matches_configured_network_(ssid_buf, result->bssid)) { + this->log_discarded_scan_result_(ssid_buf, result->bssid, result->rssi, result->channel); return; } bssid_t bssid; std::copy(result->bssid, result->bssid + 6, bssid.begin()); - WiFiScanResult res(bssid, ssid_cstr, strlen(ssid_cstr), result->channel, result->rssi, - result->auth_mode != CYW43_AUTH_OPEN, ssid_cstr[0] == '\0'); + WiFiScanResult res(bssid, ssid_buf, len, result->channel, result->rssi, result->auth_mode != CYW43_AUTH_OPEN, + len == 0); if (std::find(this->scan_result_.begin(), this->scan_result_.end(), res) == this->scan_result_.end()) { this->scan_result_.push_back(res); } @@ -167,7 +184,6 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { ESP_LOGV(TAG, "cyw43_wifi_scan failed"); } return err == 0; - return true; } #ifdef USE_WIFI_AP @@ -212,8 +228,10 @@ network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t * #endif // USE_WIFI_AP bool WiFiComponent::wifi_disconnect_() { - int err = cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); - return err == 0; + // Use Arduino WiFi.disconnect() instead of raw cyw43_wifi_leave() to properly + // clean up the lwIP netif, DHCP client, and internal Arduino state. + WiFi.disconnect(); + return true; } bssid_t WiFiComponent::wifi_bssid() { @@ -269,9 +287,10 @@ void WiFiComponent::wifi_loop_() { // Poll for connection state changes // The arduino-pico WiFi library doesn't have event callbacks like ESP8266/ESP32, - // so we need to poll the link status to detect state changes - auto status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); - bool is_connected = (status == CYW43_LINK_UP); + // so we need to poll the link status to detect state changes. + // Use WiFi.connected() which checks both the WiFi link and IP address via the + // Arduino framework's own netif (not the SDK's uninitialized one). + bool is_connected = WiFi.connected(); // Detect connection state change if (is_connected && !s_sta_was_connected) { diff --git a/platformio.ini b/platformio.ini index e35dce2228..16a1b18211 100644 --- a/platformio.ini +++ b/platformio.ini @@ -193,10 +193,10 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script extends = common:arduino board_build.filesystem_size = 0.5m -platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.2.0-gcc12 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.4.0-gcc14-arduinopico460 platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted - earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/3.9.4/rp2040-3.9.4.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.0/rp2040-5.5.0.zip framework = arduino lib_deps = From 04db37a34ac43d0a9c5fb8c807b56ed58a551bce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Feb 2026 20:38:38 -0700 Subject: [PATCH 0976/2030] [esp8266] Remove forced scanf linkage to save ~8KB flash (#13678) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp8266/__init__.py | 6 +++ .../esp8266/remove_float_scanf.py.script | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 esphome/components/esp8266/remove_float_scanf.py.script diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index c7b5d5c130..927a59fd61 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -205,6 +205,7 @@ async def to_code(config): "pre:testing_mode.py", "pre:exclude_updater.py", "pre:exclude_waveform.py", + "pre:remove_float_scanf.py", "post:post_build.py", ], ) @@ -342,3 +343,8 @@ def copy_files() -> None: exclude_waveform_file, CORE.relative_build_path("exclude_waveform.py"), ) + remove_float_scanf_file = dir / "remove_float_scanf.py.script" + copy_file_if_changed( + remove_float_scanf_file, + CORE.relative_build_path("remove_float_scanf.py"), + ) diff --git a/esphome/components/esp8266/remove_float_scanf.py.script b/esphome/components/esp8266/remove_float_scanf.py.script new file mode 100644 index 0000000000..b1d03a4d46 --- /dev/null +++ b/esphome/components/esp8266/remove_float_scanf.py.script @@ -0,0 +1,46 @@ +# pylint: disable=E0602 +Import("env") # noqa + +# Remove forced scanf linkage to allow garbage collection of unused code +# +# The ESP8266 Arduino framework unconditionally adds: +# -u _printf_float -u _scanf_float +# +# The -u flag forces symbols to be linked even if unreferenced, which pulls +# in the entire scanf family (~7-8KB). ESPHome doesn't use scanf at all +# (verified by CI check in PR #13657), so this is pure dead weight. +# +# By removing -u _scanf_float, --gc-sections can eliminate: +# - scanf family functions (~7KB) +# - _strtod_l (~3.7KB) +# - Related parsing infrastructure +# +# We keep -u _printf_float because components still use %f in logging. + + +def remove_scanf_float_flag(source, target, env): + """Remove -u _scanf_float from linker flags. + + This is called as a pre-action before the link step, after the + Arduino framework has added its default flags. + """ + linkflags = env.get("LINKFLAGS", []) + new_linkflags = [] + i = 0 + + while i < len(linkflags): + flag = linkflags[i] + if flag == "-u" and i + 1 < len(linkflags): + next_flag = linkflags[i + 1] + if next_flag == "_scanf_float": + print("ESPHome: Removing _scanf_float (saves ~8KB flash)") + i += 2 # Skip both -u and the symbol + continue + new_linkflags.append(flag) + i += 1 + + env.Replace(LINKFLAGS=new_linkflags) + + +# Register the callback to run before the link step +env.AddPreAction("$BUILD_DIR/${PROGNAME}.elf", remove_scanf_float_flag) From 656389f2158b0723630839c385aa26648c6f53b1 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Thu, 26 Feb 2026 23:41:35 -0600 Subject: [PATCH 0977/2030] [usb_uart] Performance, correctness and reliability improvements (#14333) --- .../components/usb_host/usb_host_client.cpp | 19 +- esphome/components/usb_uart/ch34x.cpp | 9 +- esphome/components/usb_uart/cp210x.cpp | 9 +- esphome/components/usb_uart/usb_uart.cpp | 205 ++++++++++++++---- esphome/components/usb_uart/usb_uart.h | 45 +++- 5 files changed, 224 insertions(+), 63 deletions(-) diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 5b0aed4c59..c77d738ace 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -424,9 +424,9 @@ bool USBClient::control_transfer(uint8_t type, uint8_t request, uint16_t value, if (trq == nullptr) return false; auto length = data.size(); - if (length > sizeof(trq->transfer->data_buffer_size) - SETUP_PACKET_SIZE) { + if (length > trq->transfer->data_buffer_size - SETUP_PACKET_SIZE) { ESP_LOGE(TAG, "Control transfer data size too large: %u > %u", length, - sizeof(trq->transfer->data_buffer_size) - sizeof(usb_setup_packet_t)); + trq->transfer->data_buffer_size - SETUP_PACKET_SIZE); this->release_trq(trq); return false; } @@ -507,9 +507,13 @@ bool USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, u /** * Performs an output transfer operation. - * THREAD CONTEXT: Called from main loop thread only - * - USB UART output uses defer() to ensure main loop context - * - Modbus and other components call from loop() + * THREAD CONTEXT: Called from both USB task and main loop threads. + * - USB task: output transfer callback restarts output directly (no defer) + * - Main loop: initial output trigger from write_array() and loop() + * Thread safety is ensured by: + * - get_trq_() uses atomic CAS (multi-consumer safe) + * - claimed trq slot is exclusively owned until submission + * - usb_host_transfer_submit() is safe to call from any task context * * @param ep_address The endpoint address. * @param callback The callback function to be called when the transfer is complete. @@ -524,6 +528,11 @@ bool USBClient::transfer_out(uint8_t ep_address, const transfer_cb_t &callback, ESP_LOGE(TAG, "Too many requests queued"); return false; } + if (length > trq->transfer->data_buffer_size) { + ESP_LOGE(TAG, "transfer_out: data length %u exceeds buffer size %u", length, trq->transfer->data_buffer_size); + this->release_trq(trq); + return false; + } trq->callback = callback; trq->transfer->callback = transfer_callback; trq->transfer->bEndpointAddress = ep_address | USB_DIR_OUT; diff --git a/esphome/components/usb_uart/ch34x.cpp b/esphome/components/usb_uart/ch34x.cpp index caa4b65657..7fa964c0cb 100644 --- a/esphome/components/usb_uart/ch34x.cpp +++ b/esphome/components/usb_uart/ch34x.cpp @@ -5,8 +5,7 @@ #include "esphome/components/bytebuffer/bytebuffer.h" -namespace esphome { -namespace usb_uart { +namespace esphome::usb_uart { using namespace bytebuffer; /** @@ -74,8 +73,8 @@ void USBUartTypeCH34X::enable_channels() { this->control_transfer(USB_VENDOR_DEV | usb_host::USB_DIR_OUT, cmd, value, (factor << 8) | divisor, callback); this->control_transfer(USB_VENDOR_DEV | usb_host::USB_DIR_OUT, cmd + 3, 0x80, 0, callback); } - USBUartTypeCdcAcm::enable_channels(); + this->start_channels(); } -} // namespace usb_uart -} // namespace esphome +} // namespace esphome::usb_uart + #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_uart/cp210x.cpp b/esphome/components/usb_uart/cp210x.cpp index fa8c2331b2..ae9170c5fb 100644 --- a/esphome/components/usb_uart/cp210x.cpp +++ b/esphome/components/usb_uart/cp210x.cpp @@ -5,8 +5,7 @@ #include "esphome/components/bytebuffer/bytebuffer.h" -namespace esphome { -namespace usb_uart { +namespace esphome::usb_uart { using namespace bytebuffer; /** @@ -119,8 +118,8 @@ void USBUartTypeCP210X::enable_channels() { this->control_transfer(USB_VENDOR_IFC | usb_host::USB_DIR_OUT, SET_BAUDRATE, 0, channel->index_, callback, baud.get_data()); } - USBUartTypeCdcAcm::enable_channels(); + this->start_channels(); } -} // namespace usb_uart -} // namespace esphome +} // namespace esphome::usb_uart + #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 5c2806c456..de81bfc587 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -3,12 +3,10 @@ #include "usb_uart.h" #include "esphome/core/log.h" #include "esphome/core/application.h" -#include "esphome/components/uart/uart_debugger.h" #include <cinttypes> -namespace esphome { -namespace usb_uart { +namespace esphome::usb_uart { /** * @@ -135,16 +133,51 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { ESP_LOGV(TAG, "Channel not initialised - write ignored"); return; } - while (this->output_buffer_.get_free_space() != 0 && len-- != 0) { - this->output_buffer_.push(*data++); +#ifdef USE_UART_DEBUGGER + if (this->debug_) { + constexpr size_t BATCH = 16; + char buf[4 + format_hex_pretty_size(BATCH)]; // ">>> " + "XX,XX,...,XX\0" + for (size_t off = 0; off < len; off += BATCH) { + size_t n = std::min(len - off, BATCH); + memcpy(buf, ">>> ", 4); + format_hex_pretty_to(buf + 4, sizeof(buf) - 4, data + off, n, ','); + ESP_LOGD(TAG, "%s", buf); + } } - len++; - if (len > 0) { - ESP_LOGE(TAG, "Buffer full - failed to write %d bytes", len); +#endif + while (len > 0) { + UsbOutputChunk *chunk = this->output_pool_.allocate(); + if (chunk == nullptr) { + ESP_LOGE(TAG, "Output pool full - lost %zu bytes", len); + break; + } + size_t chunk_len = std::min(len, UsbOutputChunk::MAX_CHUNK_SIZE); + memcpy(chunk->data, data, chunk_len); + chunk->length = static_cast<uint8_t>(chunk_len); + if (!this->output_queue_.push(chunk)) { + this->output_pool_.release(chunk); + ESP_LOGE(TAG, "Output queue full - lost %zu bytes", len); + break; + } + data += chunk_len; + len -= chunk_len; } this->parent_->start_output(this); } +void USBUartChannel::flush() { + // Spin until the output queue is drained and the last USB transfer completes. + // Safe to call from the main loop only. + // The 100 ms timeout guards against a device that stops responding mid-flush; + // in that case the main loop is blocked for the full duration. + uint32_t deadline = millis() + 100; // 100 ms safety timeout + while ((!this->output_queue_.empty() || this->output_started_.load()) && millis() < deadline) { + // Kick start_output() in case data arrived but no transfer is in flight yet. + this->parent_->start_output(this); + yield(); + } +} + bool USBUartChannel::peek_byte(uint8_t *data) { if (this->input_buffer_.is_empty()) { return false; @@ -182,8 +215,10 @@ void USBUartComponent::loop() { #ifdef USE_UART_DEBUGGER if (channel->debug_) { - uart::UARTDebug::log_hex(uart::UART_DIRECTION_RX, std::vector<uint8_t>(chunk->data, chunk->data + chunk->length), - ','); // NOLINT() + char buf[4 + format_hex_pretty_size(UsbDataChunk::MAX_CHUNK_SIZE)]; // "<<< " + hex + memcpy(buf, "<<< ", 4); + format_hex_pretty_to(buf + 4, sizeof(buf) - 4, chunk->data, chunk->length, ','); + ESP_LOGD(TAG, "%s", buf); } #endif @@ -192,6 +227,13 @@ void USBUartComponent::loop() { // Return chunk to pool for reuse this->chunk_pool_.release(chunk); + + // Invoke the RX callback (if registered) immediately after data lands in the + // ring buffer. This lets consumers such as ZigbeeProxy process incoming bytes + // in the same loop iteration they are delivered, avoiding an extra wakeup cycle. + if (channel->rx_callback_) { + channel->rx_callback_(); + } } // Log dropped USB data periodically @@ -234,10 +276,10 @@ void USBUartComponent::start_input(USBUartChannel *channel) { // The underlying transfer_in() uses lock-free atomic allocation from the // TransferRequest pool, making this multi-threaded access safe - // if already started, don't restart. A spurious failure in compare_exchange_weak - // is not a problem, as it will be retried on the next read_array() + // Use compare_exchange_strong to avoid spurious failures: a missed submit here is + // never retried by read_array() because no data will ever arrive to trigger it. auto started = false; - if (!channel->input_started_.compare_exchange_weak(started, true)) + if (!channel->input_started_.compare_exchange_strong(started, true)) return; const auto *ep = channel->cdc_dev_.in_ep; // CALLBACK CONTEXT: This lambda is executed in USB task via transfer_callback @@ -285,37 +327,56 @@ void USBUartComponent::start_input(USBUartChannel *channel) { this->start_input(channel); }; if (!this->transfer_in(ep->bEndpointAddress, callback, ep->wMaxPacketSize)) { + ESP_LOGE(TAG, "IN transfer submission failed for ep=0x%02X", ep->bEndpointAddress); channel->input_started_.store(false); } } void USBUartComponent::start_output(USBUartChannel *channel) { - // IMPORTANT: This function must only be called from the main loop! - // The output_buffer_ is not thread-safe and can only be accessed from main loop. - // USB callbacks use defer() to ensure this function runs in the correct context. - if (channel->output_started_.load()) - return; - if (channel->output_buffer_.is_empty()) { + // THREAD CONTEXT: Called from both main loop and USB task threads. + // The output_queue_ is a lock-free SPSC queue, so pop() is safe from either thread. + // The output_started_ atomic flag is claimed via compare_exchange to guarantee that + // only one thread starts a transfer at a time. + + // Atomically claim the "output in progress" flag. If already set, another thread + // is handling the transfer; return immediately. + bool expected = false; + if (!channel->output_started_.compare_exchange_strong(expected, true, std::memory_order_acq_rel)) { return; } + + UsbOutputChunk *chunk = channel->output_queue_.pop(); + if (chunk == nullptr) { + // Nothing to send — release the flag and return. + channel->output_started_.store(false, std::memory_order_release); + return; + } + const auto *ep = channel->cdc_dev_.out_ep; - // CALLBACK CONTEXT: This lambda is executed in USB task via transfer_callback - auto callback = [this, channel](const usb_host::TransferStatus &status) { - ESP_LOGV(TAG, "Output Transfer result: length: %u; status %X", status.data_len, status.error_code); - channel->output_started_.store(false); - // Defer restart to main loop (defer is thread-safe) - this->defer([this, channel] { this->start_output(channel); }); + // CALLBACK CONTEXT: This lambda is executed in the USB task via transfer_callback. + // It releases the chunk, clears the flag, and directly restarts output without + // going through defer() — eliminating one full main-loop-wakeup cycle of latency. + auto callback = [this, channel, chunk](const usb_host::TransferStatus &status) { + if (!status.success) { + ESP_LOGW(TAG, "Output transfer failed: status %X", status.error_code); + } else { + ESP_LOGV(TAG, "Output Transfer result: length: %u; status %X", status.data_len, status.error_code); + } + channel->output_pool_.release(chunk); + channel->output_started_.store(false, std::memory_order_release); + // Restart directly from USB task — safe because output_queue_ is lock-free + // and transfer_out() uses thread-safe atomic slot allocation. + this->start_output(channel); }; - channel->output_started_.store(true); - uint8_t data[ep->wMaxPacketSize]; - auto len = channel->output_buffer_.pop(data, ep->wMaxPacketSize); - this->transfer_out(ep->bEndpointAddress, callback, data, len); -#ifdef USE_UART_DEBUGGER - if (channel->debug_) { - uart::UARTDebug::log_hex(uart::UART_DIRECTION_TX, std::vector<uint8_t>(data, data + len), ','); // NOLINT() + + const uint8_t len = chunk->length; + if (!this->transfer_out(ep->bEndpointAddress, callback, chunk->data, len)) { + // Transfer submission failed — return chunk and release flag so callers can retry. + channel->output_pool_.release(chunk); + channel->output_started_.store(false, std::memory_order_release); + return; } -#endif - ESP_LOGV(TAG, "Output %d bytes started", len); + ESP_LOGV(TAG, "Output %u bytes started", len); } /** @@ -351,6 +412,20 @@ void USBUartTypeCdcAcm::on_connected() { fix_mps(channel->cdc_dev_.in_ep); fix_mps(channel->cdc_dev_.out_ep); channel->initialised_.store(true); + // Claim the communication (interrupt) interface so CDC class requests are accepted + // by the device. Some CDC ACM implementations (e.g. EFR32 NCP) require this before + // they enable data flow on the bulk endpoints. + if (channel->cdc_dev_.interrupt_interface_number != channel->cdc_dev_.bulk_interface_number) { + auto err_comm = usb_host_interface_claim(this->handle_, this->device_handle_, + channel->cdc_dev_.interrupt_interface_number, 0); + if (err_comm != ESP_OK) { + ESP_LOGW(TAG, "Could not claim comm interface %d: %s", channel->cdc_dev_.interrupt_interface_number, + esp_err_to_name(err_comm)); + } else { + channel->cdc_dev_.comm_interface_claimed = true; + ESP_LOGD(TAG, "Claimed comm interface %d", channel->cdc_dev_.interrupt_interface_number); + } + } auto err = usb_host_interface_claim(this->handle_, this->device_handle_, channel->cdc_dev_.bulk_interface_number, 0); if (err != ESP_OK) { @@ -378,18 +453,74 @@ void USBUartTypeCdcAcm::on_disconnected() { usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress); usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress); } + if (channel->cdc_dev_.comm_interface_claimed) { + usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.interrupt_interface_number); + channel->cdc_dev_.comm_interface_claimed = false; + } usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.bulk_interface_number); // Reset the input and output started flags to their initial state to avoid the possibility of spurious restarts channel->input_started_.store(true); channel->output_started_.store(true); channel->input_buffer_.clear(); - channel->output_buffer_.clear(); + // Drain any pending output chunks and return them to the pool + { + UsbOutputChunk *chunk; + while ((chunk = channel->output_queue_.pop()) != nullptr) { + channel->output_pool_.release(chunk); + } + } channel->initialised_.store(false); } USBClient::on_disconnected(); } void USBUartTypeCdcAcm::enable_channels() { + static constexpr uint8_t CDC_REQUEST_TYPE = usb_host::USB_TYPE_CLASS | usb_host::USB_RECIP_INTERFACE; + static constexpr uint8_t CDC_SET_LINE_CODING = 0x20; + static constexpr uint8_t CDC_SET_CONTROL_LINE_STATE = 0x22; + static constexpr uint16_t CDC_DTR_RTS = 0x0003; // D0=DTR, D1=RTS + + for (auto *channel : this->channels_) { + if (!channel->initialised_.load()) + continue; + // Configure the bridge's UART parameters. A USB-UART bridge will not forward data + // at the correct speed until SET_LINE_CODING is sent; without it the UART may run + // at an indeterminate default rate so the NCP receives garbled bytes and never + // sends RSTACK. + uint32_t baud = channel->baud_rate_; + std::vector<uint8_t> line_coding = { + static_cast<uint8_t>(baud & 0xFF), static_cast<uint8_t>((baud >> 8) & 0xFF), + static_cast<uint8_t>((baud >> 16) & 0xFF), static_cast<uint8_t>((baud >> 24) & 0xFF), + static_cast<uint8_t>(channel->stop_bits_), // bCharFormat: 0=1stop, 1=1.5stop, 2=2stop + static_cast<uint8_t>(channel->parity_), // bParityType: 0=None, 1=Odd, 2=Even, 3=Mark, 4=Space + static_cast<uint8_t>(channel->data_bits_), // bDataBits + }; + ESP_LOGD(TAG, "SET_LINE_CODING: baud=%u stop=%u parity=%u data=%u", (unsigned) baud, channel->stop_bits_, + (unsigned) channel->parity_, channel->data_bits_); + this->control_transfer( + CDC_REQUEST_TYPE, CDC_SET_LINE_CODING, 0, channel->cdc_dev_.interrupt_interface_number, + [](const usb_host::TransferStatus &status) { + if (!status.success) { + ESP_LOGW(TAG, "SET_LINE_CODING failed: %X", status.error_code); + } else { + ESP_LOGD(TAG, "SET_LINE_CODING OK"); + } + }, + line_coding); + // Assert DTR+RTS to signal DTE is present. + this->control_transfer(CDC_REQUEST_TYPE, CDC_SET_CONTROL_LINE_STATE, CDC_DTR_RTS, + channel->cdc_dev_.interrupt_interface_number, [](const usb_host::TransferStatus &status) { + if (!status.success) { + ESP_LOGW(TAG, "SET_CONTROL_LINE_STATE failed: %X", status.error_code); + } else { + ESP_LOGD(TAG, "SET_CONTROL_LINE_STATE (DTR+RTS) OK"); + } + }); + } + this->start_channels(); +} + +void USBUartTypeCdcAcm::start_channels() { for (auto *channel : this->channels_) { if (!channel->initialised_.load()) continue; @@ -399,6 +530,6 @@ void USBUartTypeCdcAcm::enable_channels() { } } -} // namespace usb_uart -} // namespace esphome +} // namespace esphome::usb_uart + #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 94e6120457..9a9fe1c2ca 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -8,9 +8,10 @@ #include "esphome/core/lock_free_queue.h" #include "esphome/core/event_pool.h" #include <atomic> +#include <functional> + +namespace esphome::usb_uart { -namespace esphome { -namespace usb_uart { class USBUartTypeCdcAcm; class USBUartComponent; class USBUartChannel; @@ -31,6 +32,7 @@ struct CdcEps { const usb_ep_desc_t *out_ep; uint8_t bulk_interface_number; uint8_t interrupt_interface_number; + bool comm_interface_claimed{false}; }; enum UARTParityOptions { @@ -83,6 +85,16 @@ struct UsbDataChunk { void release() {} }; +// Structure for queuing outgoing USB data chunks (one per USB FS packet) +struct UsbOutputChunk { + static constexpr size_t MAX_CHUNK_SIZE = 64; // USB FS MPS + uint8_t data[MAX_CHUNK_SIZE]; + uint8_t length; + + // Required for EventPool - no cleanup needed for POD types + void release() {} +}; + class USBUartChannel : public uart::UARTComponent, public Parented<USBUartComponent> { friend class USBUartComponent; friend class USBUartTypeCdcAcm; @@ -90,24 +102,32 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon friend class USBUartTypeCH34X; public: - USBUartChannel(uint8_t index, uint16_t buffer_size) - : index_(index), input_buffer_(RingBuffer(buffer_size)), output_buffer_(RingBuffer(buffer_size)) {} + // Number of output chunk slots per channel (8 × 64 bytes = 512 bytes peak, lazily allocated) + static constexpr uint8_t USB_OUTPUT_CHUNK_COUNT = 8; + + USBUartChannel(uint8_t index, uint16_t buffer_size) : index_(index), input_buffer_(RingBuffer(buffer_size)) {} void write_array(const uint8_t *data, size_t len) override; - ; bool peek_byte(uint8_t *data) override; - ; bool read_array(uint8_t *data, size_t len) override; size_t available() override { return this->input_buffer_.get_available(); } - void flush() override {} + void flush() override; void check_logger_conflict() override {} void set_parity(UARTParityOptions parity) { this->parity_ = parity; } void set_debug(bool debug) { this->debug_ = debug; } void set_dummy_receiver(bool dummy_receiver) { this->dummy_receiver_ = dummy_receiver; } + /// Register a callback invoked immediately after data is pushed to the input ring buffer. + /// Called from USBUartComponent::loop() in the main loop context. + /// Allows consumers (e.g. ZigbeeProxy) to process bytes in the same loop iteration + /// they arrive, eliminating one full main-loop-wakeup cycle of latency. + void set_rx_callback(std::function<void()> cb) { this->rx_callback_ = std::move(cb); } + protected: // Larger structures first for better alignment RingBuffer input_buffer_; - RingBuffer output_buffer_; + LockFreeQueue<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_queue_; + EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_pool_; + std::function<void()> rx_callback_{}; CdcEps cdc_dev_{}; // Enum (likely 4 bytes) UARTParityOptions parity_{UART_CONFIG_PARITY_NONE}; @@ -150,8 +170,12 @@ class USBUartTypeCdcAcm : public USBUartComponent { protected: virtual std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl); void on_connected() override; - virtual void enable_channels(); void on_disconnected() override; + virtual void enable_channels(); + /// Resets per-channel transfer flags and posts the first bulk IN transfer. + /// Called by enable_channels() and by vendor-specific subclass overrides that + /// handle their own line-coding setup before starting data flow. + void start_channels(); }; class USBUartTypeCP210X : public USBUartTypeCdcAcm { @@ -170,7 +194,6 @@ class USBUartTypeCH34X : public USBUartTypeCdcAcm { void enable_channels() override; }; -} // namespace usb_uart -} // namespace esphome +} // namespace esphome::usb_uart #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 From 4044520ccc3a17b1162a6b7aec970f5658f1f641 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Feb 2026 01:38:36 -0500 Subject: [PATCH 0978/2030] [esp32_touch] Migrate to new unified touch sensor driver (esp_driver_touch_sens) (#14033) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/esp32_touch/__init__.py | 319 ++++++----- .../components/esp32_touch/esp32_touch.cpp | 500 ++++++++++++++++++ esphome/components/esp32_touch/esp32_touch.h | 284 ++++------ .../esp32_touch/esp32_touch_common.cpp | 173 ------ .../components/esp32_touch/esp32_touch_v1.cpp | 244 --------- .../components/esp32_touch/esp32_touch_v2.cpp | 402 -------------- .../esp32_touch/common-variants.yaml | 1 - .../esp32_touch/test.esp32-p4-idf.yaml | 5 + 8 files changed, 800 insertions(+), 1128 deletions(-) create mode 100644 esphome/components/esp32_touch/esp32_touch.cpp delete mode 100644 esphome/components/esp32_touch/esp32_touch_common.cpp delete mode 100644 esphome/components/esp32_touch/esp32_touch_v1.cpp delete mode 100644 esphome/components/esp32_touch/esp32_touch_v2.cpp create mode 100644 tests/components/esp32_touch/test.esp32-p4-idf.yaml diff --git a/esphome/components/esp32_touch/__init__.py b/esphome/components/esp32_touch/__init__.py index a02370a343..10ad339b12 100644 --- a/esphome/components/esp32_touch/__init__.py +++ b/esphome/components/esp32_touch/__init__.py @@ -1,7 +1,10 @@ +import logging + import esphome.codegen as cg from esphome.components import esp32 from esphome.components.esp32 import ( VARIANT_ESP32, + VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, get_esp32_variant, @@ -21,6 +24,8 @@ from esphome.const import ( ) from esphome.core import TimePeriod +_LOGGER = logging.getLogger(__name__) + AUTO_LOAD = ["binary_sensor"] DEPENDENCIES = ["esp32"] @@ -37,135 +42,161 @@ CONF_WATERPROOF_SHIELD_DRIVER = "waterproof_shield_driver" esp32_touch_ns = cg.esphome_ns.namespace("esp32_touch") ESP32TouchComponent = esp32_touch_ns.class_("ESP32TouchComponent", cg.Component) +# Channel ID mappings: GPIO pin number -> integer channel ID +# These are plain integers - the new unified API uses int chan_id directly. TOUCH_PADS = { VARIANT_ESP32: { - 4: cg.global_ns.TOUCH_PAD_NUM0, - 0: cg.global_ns.TOUCH_PAD_NUM1, - 2: cg.global_ns.TOUCH_PAD_NUM2, - 15: cg.global_ns.TOUCH_PAD_NUM3, - 13: cg.global_ns.TOUCH_PAD_NUM4, - 12: cg.global_ns.TOUCH_PAD_NUM5, - 14: cg.global_ns.TOUCH_PAD_NUM6, - 27: cg.global_ns.TOUCH_PAD_NUM7, - 33: cg.global_ns.TOUCH_PAD_NUM8, - 32: cg.global_ns.TOUCH_PAD_NUM9, + 4: 0, + 0: 1, + 2: 2, + 15: 3, + 13: 4, + 12: 5, + 14: 6, + 27: 7, + 33: 8, + 32: 9, }, VARIANT_ESP32S2: { - 1: cg.global_ns.TOUCH_PAD_NUM1, - 2: cg.global_ns.TOUCH_PAD_NUM2, - 3: cg.global_ns.TOUCH_PAD_NUM3, - 4: cg.global_ns.TOUCH_PAD_NUM4, - 5: cg.global_ns.TOUCH_PAD_NUM5, - 6: cg.global_ns.TOUCH_PAD_NUM6, - 7: cg.global_ns.TOUCH_PAD_NUM7, - 8: cg.global_ns.TOUCH_PAD_NUM8, - 9: cg.global_ns.TOUCH_PAD_NUM9, - 10: cg.global_ns.TOUCH_PAD_NUM10, - 11: cg.global_ns.TOUCH_PAD_NUM11, - 12: cg.global_ns.TOUCH_PAD_NUM12, - 13: cg.global_ns.TOUCH_PAD_NUM13, - 14: cg.global_ns.TOUCH_PAD_NUM14, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: 11, + 12: 12, + 13: 13, + 14: 14, }, VARIANT_ESP32S3: { - 1: cg.global_ns.TOUCH_PAD_NUM1, - 2: cg.global_ns.TOUCH_PAD_NUM2, - 3: cg.global_ns.TOUCH_PAD_NUM3, - 4: cg.global_ns.TOUCH_PAD_NUM4, - 5: cg.global_ns.TOUCH_PAD_NUM5, - 6: cg.global_ns.TOUCH_PAD_NUM6, - 7: cg.global_ns.TOUCH_PAD_NUM7, - 8: cg.global_ns.TOUCH_PAD_NUM8, - 9: cg.global_ns.TOUCH_PAD_NUM9, - 10: cg.global_ns.TOUCH_PAD_NUM10, - 11: cg.global_ns.TOUCH_PAD_NUM11, - 12: cg.global_ns.TOUCH_PAD_NUM12, - 13: cg.global_ns.TOUCH_PAD_NUM13, - 14: cg.global_ns.TOUCH_PAD_NUM14, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: 11, + 12: 12, + 13: 13, + 14: 14, + }, + VARIANT_ESP32P4: { + 2: 1, + 3: 2, + 4: 3, + 5: 4, + 6: 5, + 7: 6, + 8: 7, + 9: 8, + 10: 9, + 11: 10, + 12: 11, + 13: 12, + 14: 13, + 15: 14, }, } TOUCH_PAD_DENOISE_GRADE = { - "BIT12": cg.global_ns.TOUCH_PAD_DENOISE_BIT12, - "BIT10": cg.global_ns.TOUCH_PAD_DENOISE_BIT10, - "BIT8": cg.global_ns.TOUCH_PAD_DENOISE_BIT8, - "BIT4": cg.global_ns.TOUCH_PAD_DENOISE_BIT4, + "BIT12": cg.global_ns.TOUCH_DENOISE_CHAN_RESOLUTION_BIT12, + "BIT10": cg.global_ns.TOUCH_DENOISE_CHAN_RESOLUTION_BIT10, + "BIT8": cg.global_ns.TOUCH_DENOISE_CHAN_RESOLUTION_BIT8, + "BIT4": cg.global_ns.TOUCH_DENOISE_CHAN_RESOLUTION_BIT4, } TOUCH_PAD_DENOISE_CAP_LEVEL = { - "L0": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L0, - "L1": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L1, - "L2": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L2, - "L3": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L3, - "L4": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L4, - "L5": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L5, - "L6": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L6, - "L7": cg.global_ns.TOUCH_PAD_DENOISE_CAP_L7, + "L0": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_5PF, + "L1": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_6PF, + "L2": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_7PF, + "L3": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_9PF, + "L4": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_10PF, + "L5": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_12PF, + "L6": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_13PF, + "L7": cg.global_ns.TOUCH_DENOISE_CHAN_CAP_14PF, } TOUCH_PAD_FILTER_MODE = { - "IIR_4": cg.global_ns.TOUCH_PAD_FILTER_IIR_4, - "IIR_8": cg.global_ns.TOUCH_PAD_FILTER_IIR_8, - "IIR_16": cg.global_ns.TOUCH_PAD_FILTER_IIR_16, - "IIR_32": cg.global_ns.TOUCH_PAD_FILTER_IIR_32, - "IIR_64": cg.global_ns.TOUCH_PAD_FILTER_IIR_64, - "IIR_128": cg.global_ns.TOUCH_PAD_FILTER_IIR_128, - "IIR_256": cg.global_ns.TOUCH_PAD_FILTER_IIR_256, - "JITTER": cg.global_ns.TOUCH_PAD_FILTER_JITTER, + "IIR_4": cg.global_ns.TOUCH_BM_IIR_FILTER_4, + "IIR_8": cg.global_ns.TOUCH_BM_IIR_FILTER_8, + "IIR_16": cg.global_ns.TOUCH_BM_IIR_FILTER_16, + "IIR_32": cg.global_ns.TOUCH_BM_IIR_FILTER_32, + "IIR_64": cg.global_ns.TOUCH_BM_IIR_FILTER_64, + "IIR_128": cg.global_ns.TOUCH_BM_IIR_FILTER_128, + "IIR_256": cg.global_ns.TOUCH_BM_IIR_FILTER_256, + "JITTER": cg.global_ns.TOUCH_BM_JITTER_FILTER, } TOUCH_PAD_SMOOTH_MODE = { - "OFF": cg.global_ns.TOUCH_PAD_SMOOTH_OFF, - "IIR_2": cg.global_ns.TOUCH_PAD_SMOOTH_IIR_2, - "IIR_4": cg.global_ns.TOUCH_PAD_SMOOTH_IIR_4, - "IIR_8": cg.global_ns.TOUCH_PAD_SMOOTH_IIR_8, + "OFF": cg.global_ns.TOUCH_SMOOTH_NO_FILTER, + "IIR_2": cg.global_ns.TOUCH_SMOOTH_IIR_FILTER_2, + "IIR_4": cg.global_ns.TOUCH_SMOOTH_IIR_FILTER_4, + "IIR_8": cg.global_ns.TOUCH_SMOOTH_IIR_FILTER_8, } LOW_VOLTAGE_REFERENCE = { - "0.5V": cg.global_ns.TOUCH_LVOLT_0V5, - "0.6V": cg.global_ns.TOUCH_LVOLT_0V6, - "0.7V": cg.global_ns.TOUCH_LVOLT_0V7, - "0.8V": cg.global_ns.TOUCH_LVOLT_0V8, + "0.5V": cg.global_ns.TOUCH_VOLT_LIM_L_0V5, + "0.6V": cg.global_ns.TOUCH_VOLT_LIM_L_0V6, + "0.7V": cg.global_ns.TOUCH_VOLT_LIM_L_0V7, + "0.8V": cg.global_ns.TOUCH_VOLT_LIM_L_0V8, } HIGH_VOLTAGE_REFERENCE = { - "2.4V": cg.global_ns.TOUCH_HVOLT_2V4, - "2.5V": cg.global_ns.TOUCH_HVOLT_2V5, - "2.6V": cg.global_ns.TOUCH_HVOLT_2V6, - "2.7V": cg.global_ns.TOUCH_HVOLT_2V7, + "2.4V": cg.global_ns.TOUCH_VOLT_LIM_H_2V4, + "2.5V": cg.global_ns.TOUCH_VOLT_LIM_H_2V5, + "2.6V": cg.global_ns.TOUCH_VOLT_LIM_H_2V6, + "2.7V": cg.global_ns.TOUCH_VOLT_LIM_H_2V7, } -VOLTAGE_ATTENUATION = { - "1.5V": cg.global_ns.TOUCH_HVOLT_ATTEN_1V5, - "1V": cg.global_ns.TOUCH_HVOLT_ATTEN_1V, - "0.5V": cg.global_ns.TOUCH_HVOLT_ATTEN_0V5, - "0V": cg.global_ns.TOUCH_HVOLT_ATTEN_0V, -} -TOUCH_PAD_WATERPROOF_SHIELD_DRIVER = { - "L0": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L0, - "L1": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L1, - "L2": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L2, - "L3": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L3, - "L4": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L4, - "L5": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L5, - "L6": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L6, - "L7": cg.global_ns.TOUCH_PAD_SHIELD_DRV_L7, +VOLTAGE_ATTENUATION = {"1.5V", "1V", "0.5V", "0V"} + +# ESP32 V1: The new API's touch_volt_lim_h_t combines the old high_voltage_reference +# and voltage_attenuation into a single enum representing the effective upper voltage. +# Effective voltage = high_voltage_reference - voltage_attenuation +EFFECTIVE_HIGH_VOLTAGE = { + ("2.4V", "1.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_0V9, + ("2.5V", "1.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V0, + ("2.6V", "1.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V1, + ("2.7V", "1.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V2, + ("2.4V", "1V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V4, + ("2.5V", "1V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V5, + ("2.6V", "1V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V6, + ("2.7V", "1V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V7, + ("2.4V", "0.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_1V9, + ("2.5V", "0.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V0, + ("2.6V", "0.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V1, + ("2.7V", "0.5V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V2, + ("2.4V", "0V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V4, + ("2.5V", "0V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V5, + ("2.6V", "0V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V6, + ("2.7V", "0V"): cg.global_ns.TOUCH_VOLT_LIM_H_2V7, } def validate_touch_pad(value): value = gpio.gpio_pin_number_validator(value) variant = get_esp32_variant() - if variant not in TOUCH_PADS: + pads = TOUCH_PADS.get(variant) + if pads is None: raise cv.Invalid(f"ESP32 variant {variant} does not support touch pads.") - - pads = TOUCH_PADS[variant] if value not in pads: raise cv.Invalid(f"Pin {value} does not support touch pads.") - return cv.enum(pads)(value) + return pads[value] # Return integer channel ID def validate_variant_vars(config): - if get_esp32_variant() == VARIANT_ESP32: - variant_vars = { + variant = get_esp32_variant() + invalid_vars = set() + if variant == VARIANT_ESP32: + invalid_vars = { CONF_DEBOUNCE_COUNT, CONF_DENOISE_GRADE, CONF_DENOISE_CAP_LEVEL, @@ -176,15 +207,14 @@ def validate_variant_vars(config): CONF_WATERPROOF_GUARD_RING, CONF_WATERPROOF_SHIELD_DRIVER, } - for vvar in variant_vars: - if vvar in config: - raise cv.Invalid(f"{vvar} is not valid on {VARIANT_ESP32}") - elif ( - get_esp32_variant() == VARIANT_ESP32S2 or get_esp32_variant() == VARIANT_ESP32S3 - ) and CONF_IIR_FILTER in config: - raise cv.Invalid( - f"{CONF_IIR_FILTER} is not valid on {VARIANT_ESP32S2} or {VARIANT_ESP32S3}" - ) + elif variant in (VARIANT_ESP32S2, VARIANT_ESP32S3, VARIANT_ESP32P4): + invalid_vars = {CONF_IIR_FILTER} + if variant == VARIANT_ESP32P4: + invalid_vars |= {CONF_DENOISE_GRADE, CONF_DENOISE_CAP_LEVEL} + unsupported = invalid_vars.intersection(config) + if unsupported: + keys = ", ".join(sorted(f"'{k}'" for k in unsupported)) + raise cv.Invalid(f"{keys} not valid on {variant}") return config @@ -219,12 +249,17 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_HIGH_VOLTAGE_REFERENCE, default="2.7V"): validate_voltage( HIGH_VOLTAGE_REFERENCE ), - cv.Optional(CONF_VOLTAGE_ATTENUATION, default="0V"): validate_voltage( - VOLTAGE_ATTENUATION - ), + # ESP32 V1 only: attenuates the high voltage reference + cv.SplitDefault( + CONF_VOLTAGE_ATTENUATION, + esp32="0V", + esp32_s2=cv.UNDEFINED, + esp32_s3=cv.UNDEFINED, + esp32_p4=cv.UNDEFINED, + ): validate_voltage(VOLTAGE_ATTENUATION), # ESP32 only cv.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds, - # ESP32-S2/S3 only + # ESP32-S2/S3/P4 only cv.Optional(CONF_DEBOUNCE_COUNT): cv.int_range(min=0, max=7), cv.Optional(CONF_FILTER_MODE): cv.enum( TOUCH_PAD_FILTER_MODE, upper=True, space="_" @@ -241,9 +276,7 @@ CONFIG_SCHEMA = cv.All( TOUCH_PAD_DENOISE_CAP_LEVEL, upper=True, space="_" ), cv.Optional(CONF_WATERPROOF_GUARD_RING): validate_touch_pad, - cv.Optional(CONF_WATERPROOF_SHIELD_DRIVER): cv.enum( - TOUCH_PAD_WATERPROOF_SHIELD_DRIVER, upper=True, space="_" - ), + cv.Optional(CONF_WATERPROOF_SHIELD_DRIVER): cv.int_range(min=0, max=7), } ).extend(cv.COMPONENT_SCHEMA), cv.has_none_or_all_keys(CONF_DENOISE_GRADE, CONF_DENOISE_CAP_LEVEL), @@ -260,6 +293,7 @@ CONFIG_SCHEMA = cv.All( esp32.VARIANT_ESP32, esp32.VARIANT_ESP32S2, esp32.VARIANT_ESP32S3, + esp32.VARIANT_ESP32P4, ] ), validate_variant_vars, @@ -267,44 +301,67 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): - # Re-enable ESP-IDF's touch sensor driver (excluded by default to save compile time) + # New unified touch sensor driver include_builtin_idf_component("esp_driver_touch_sens") - # Legacy driver component provides driver/touch_sensor.h header - include_builtin_idf_component("driver") touch = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(touch, config) cg.add(touch.set_setup_mode(config[CONF_SETUP_MODE])) - sleep_duration = int(round(config[CONF_SLEEP_DURATION].total_microseconds * 0.15)) - cg.add(touch.set_sleep_duration(sleep_duration)) + # sleep_duration -> meas_interval_us (pass microseconds directly) + cg.add(touch.set_meas_interval_us(config[CONF_SLEEP_DURATION].total_microseconds)) - measurement_duration = int( - round(config[CONF_MEASUREMENT_DURATION].total_microseconds * 7.99987793) - ) - cg.add(touch.set_measurement_duration(measurement_duration)) + variant = get_esp32_variant() - cg.add( - touch.set_low_voltage_reference( - LOW_VOLTAGE_REFERENCE[config[CONF_LOW_VOLTAGE_REFERENCE]] + # measurement_duration handling differs per variant + if variant == VARIANT_ESP32: + # V1: charge_duration_ms (convert from microseconds to milliseconds) + charge_duration_ms = ( + config[CONF_MEASUREMENT_DURATION].total_microseconds / 1000.0 ) - ) - cg.add( - touch.set_high_voltage_reference( - HIGH_VOLTAGE_REFERENCE[config[CONF_HIGH_VOLTAGE_REFERENCE]] + cg.add(touch.set_charge_duration_ms(charge_duration_ms)) + else: + # V2/V3: charge_times (approximate conversion from duration) + # The old API used clock cycles; the new API uses charge_times count. + # Default is 500 for V2/V3. Use measurement_duration as a rough scaling factor. + # 65535 / 8192 ≈ 7.9999 maps the microsecond duration to charge_times. + charge_times = int( + round(config[CONF_MEASUREMENT_DURATION].total_microseconds * (65535 / 8192)) ) - ) - cg.add( - touch.set_voltage_attenuation( - VOLTAGE_ATTENUATION[config[CONF_VOLTAGE_ATTENUATION]] - ) - ) + charge_times = max(charge_times, 1) + cg.add(touch.set_charge_times(charge_times)) - if get_esp32_variant() == VARIANT_ESP32 and CONF_IIR_FILTER in config: + # Voltage references (not applicable to P4) + if variant != VARIANT_ESP32P4: + if CONF_LOW_VOLTAGE_REFERENCE in config: + cg.add( + touch.set_low_voltage_reference( + LOW_VOLTAGE_REFERENCE[config[CONF_LOW_VOLTAGE_REFERENCE]] + ) + ) + if CONF_HIGH_VOLTAGE_REFERENCE in config: + if variant == VARIANT_ESP32: + # V1: combine high_voltage_reference with voltage_attenuation + high_ref = config[CONF_HIGH_VOLTAGE_REFERENCE] + atten = config[CONF_VOLTAGE_ATTENUATION] + cg.add( + touch.set_high_voltage_reference( + EFFECTIVE_HIGH_VOLTAGE[(high_ref, atten)] + ) + ) + else: + # V2/V3: no attenuation concept, use directly + cg.add( + touch.set_high_voltage_reference( + HIGH_VOLTAGE_REFERENCE[config[CONF_HIGH_VOLTAGE_REFERENCE]] + ) + ) + + if variant == VARIANT_ESP32 and CONF_IIR_FILTER in config: cg.add(touch.set_iir_filter(config[CONF_IIR_FILTER])) - if get_esp32_variant() == VARIANT_ESP32S2 or get_esp32_variant() == VARIANT_ESP32S3: + if variant in (VARIANT_ESP32S2, VARIANT_ESP32S3, VARIANT_ESP32P4): if CONF_FILTER_MODE in config: cg.add(touch.set_filter_mode(config[CONF_FILTER_MODE])) if CONF_DEBOUNCE_COUNT in config: diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp new file mode 100644 index 0000000000..e7124ce92f --- /dev/null +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -0,0 +1,500 @@ +#ifdef USE_ESP32 + +#include "esp32_touch.h" +#include "esphome/core/application.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" + +#include <cinttypes> + +namespace esphome::esp32_touch { + +template<size_t N> static const char *lookup_str(const char *const (&table)[N], size_t index) { + return (index < N) ? table[index] : "UNKNOWN"; +} + +static const char *const TAG = "esp32_touch"; + +static constexpr uint32_t SETUP_MODE_LOG_INTERVAL_MS = 250; +static constexpr uint32_t INITIAL_STATE_DELAY_MS = 1500; +static constexpr uint32_t ONESHOT_SCAN_COUNT = 3; +static constexpr uint32_t ONESHOT_SCAN_TIMEOUT_MS = 2000; + +// V1: called from esp_timer context (software filter) +// V2/V3: called from ISR context +// xQueueSendFromISR is safe from both contexts. + +bool IRAM_ATTR ESP32TouchComponent::on_active_cb(touch_sensor_handle_t handle, const touch_active_event_data_t *event, + void *ctx) { + auto *comp = static_cast<ESP32TouchComponent *>(ctx); + TouchEvent te{event->chan_id, true}; + BaseType_t higher = pdFALSE; + xQueueSendFromISR(comp->touch_queue_, &te, &higher); + comp->enable_loop_soon_any_context(); + return higher == pdTRUE; +} + +bool IRAM_ATTR ESP32TouchComponent::on_inactive_cb(touch_sensor_handle_t handle, + const touch_inactive_event_data_t *event, void *ctx) { + auto *comp = static_cast<ESP32TouchComponent *>(ctx); + TouchEvent te{event->chan_id, false}; + BaseType_t higher = pdFALSE; + xQueueSendFromISR(comp->touch_queue_, &te, &higher); + comp->enable_loop_soon_any_context(); + return higher == pdTRUE; +} + +void ESP32TouchComponent::setup() { + if (!this->create_touch_queue_()) { + return; + } + + // Create sample config - differs per hardware version +#ifdef USE_ESP32_VARIANT_ESP32 + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V1_DEFAULT_SAMPLE_CONFIG( + this->charge_duration_ms_, this->low_voltage_reference_, this->high_voltage_reference_); +#elif defined(USE_ESP32_VARIANT_ESP32P4) + // div_num=8 (data scaling divisor), coarse_freq_tune=2, fine_freq_tune=2 + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V3_DEFAULT_SAMPLE_CONFIG(8, 2, 2); + sample_cfg.charge_times = this->charge_times_; +#else + // ESP32-S2/S3 (V2) + touch_sensor_sample_config_t sample_cfg = TOUCH_SENSOR_V2_DEFAULT_SAMPLE_CONFIG( + this->charge_times_, this->low_voltage_reference_, this->high_voltage_reference_); +#endif + + // Create controller + touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(1, &sample_cfg); + sens_cfg.meas_interval_us = this->meas_interval_us_; +#ifndef USE_ESP32_VARIANT_ESP32 + sens_cfg.max_meas_time_us = 0; // Disable measurement timeout (V2/V3 only) +#endif + + esp_err_t err = touch_sensor_new_controller(&sens_cfg, &this->sens_handle_); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to create touch controller: %s", esp_err_to_name(err)); + this->cleanup_touch_queue_(); + this->mark_failed(); + return; + } + + // Create channels for all children + for (auto *child : this->children_) { + touch_channel_config_t chan_cfg = {}; +#ifdef USE_ESP32_VARIANT_ESP32 + chan_cfg.abs_active_thresh[0] = child->get_threshold(); + chan_cfg.charge_speed = TOUCH_CHARGE_SPEED_7; + chan_cfg.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT; + chan_cfg.group = TOUCH_CHAN_TRIG_GROUP_BOTH; +#elif defined(USE_ESP32_VARIANT_ESP32P4) + chan_cfg.active_thresh[0] = child->get_threshold(); +#else + // ESP32-S2/S3 (V2) + chan_cfg.active_thresh[0] = child->get_threshold(); + chan_cfg.charge_speed = TOUCH_CHARGE_SPEED_7; + chan_cfg.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT; +#endif + + err = touch_sensor_new_channel(this->sens_handle_, child->get_channel_id(), &chan_cfg, &child->chan_handle_); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to create touch channel %d: %s", child->get_channel_id(), esp_err_to_name(err)); + this->cleanup_touch_queue_(); + this->mark_failed(); + return; + } + } + + // Configure filter +#ifdef USE_ESP32_VARIANT_ESP32 + // Software filter is REQUIRED for V1 on_active/on_inactive callbacks + { + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + if (this->iir_filter_enabled_()) { + filter_cfg.interval_ms = this->iir_filter_; + } + err = touch_sensor_config_filter(this->sens_handle_, &filter_cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure filter: %s", esp_err_to_name(err)); + this->cleanup_touch_queue_(); + this->mark_failed(); + return; + } + } +#else + // V2/V3: Hardware benchmark filter + { + touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG(); + if (this->filter_configured_) { + filter_cfg.benchmark.filter_mode = this->filter_mode_; + filter_cfg.benchmark.jitter_step = this->jitter_step_; + filter_cfg.benchmark.denoise_lvl = this->noise_threshold_; + filter_cfg.data.smooth_filter = this->smooth_level_; + filter_cfg.data.debounce_cnt = this->debounce_count_; + } + err = touch_sensor_config_filter(this->sens_handle_, &filter_cfg); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to configure filter: %s", esp_err_to_name(err)); + } + } +#endif + +#if SOC_TOUCH_SUPPORT_DENOISE_CHAN + if (this->denoise_configured_) { + touch_denoise_chan_config_t denoise_cfg = {}; + denoise_cfg.charge_speed = TOUCH_CHARGE_SPEED_7; + denoise_cfg.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT; + denoise_cfg.ref_cap = this->denoise_cap_level_; + denoise_cfg.resolution = this->denoise_grade_; + err = touch_sensor_config_denoise_channel(this->sens_handle_, &denoise_cfg); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to configure denoise: %s", esp_err_to_name(err)); + } + } +#endif + +#if SOC_TOUCH_SUPPORT_WATERPROOF + if (this->waterproof_configured_) { + touch_channel_handle_t guard_chan = nullptr; + for (auto *child : this->children_) { + if (child->get_channel_id() == this->waterproof_guard_ring_pad_) { + guard_chan = child->chan_handle_; + break; + } + } + + touch_channel_handle_t shield_chan = nullptr; + touch_channel_config_t shield_cfg = {}; +#ifdef USE_ESP32_VARIANT_ESP32P4 + shield_cfg.active_thresh[0] = 0; + err = touch_sensor_new_channel(this->sens_handle_, SOC_TOUCH_MAX_CHAN_ID, &shield_cfg, &shield_chan); +#else + shield_cfg.active_thresh[0] = 0; + shield_cfg.charge_speed = TOUCH_CHARGE_SPEED_7; + shield_cfg.init_charge_volt = TOUCH_INIT_CHARGE_VOLT_DEFAULT; + err = touch_sensor_new_channel(this->sens_handle_, TOUCH_SHIELD_CHAN_ID, &shield_cfg, &shield_chan); +#endif + if (err == ESP_OK) { + touch_waterproof_config_t wp_cfg = {}; + wp_cfg.guard_chan = guard_chan; + wp_cfg.shield_chan = shield_chan; + wp_cfg.shield_drv = this->waterproof_shield_driver_; + wp_cfg.flags.immersion_proof = 1; + err = touch_sensor_config_waterproof(this->sens_handle_, &wp_cfg); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to configure waterproof: %s", esp_err_to_name(err)); + } + } else { + ESP_LOGW(TAG, "Failed to create shield channel: %s", esp_err_to_name(err)); + } + } +#endif + + // Configure wakeup pads before enabling (must be done in INIT state) + this->configure_wakeup_pads_(); + + // Register callbacks + touch_event_callbacks_t cbs = {}; + cbs.on_active = on_active_cb; + cbs.on_inactive = on_inactive_cb; + err = touch_sensor_register_callbacks(this->sens_handle_, &cbs, this); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register callbacks: %s", esp_err_to_name(err)); + this->cleanup_touch_queue_(); + this->mark_failed(); + return; + } + + // Enable and start scanning + err = touch_sensor_enable(this->sens_handle_); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to enable touch sensor: %s", esp_err_to_name(err)); + this->cleanup_touch_queue_(); + this->mark_failed(); + return; + } + + // Do initial oneshot scans to populate baseline values + for (uint32_t i = 0; i < ONESHOT_SCAN_COUNT; i++) { + err = touch_sensor_trigger_oneshot_scanning(this->sens_handle_, ONESHOT_SCAN_TIMEOUT_MS); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Oneshot scan %d failed: %s", i, esp_err_to_name(err)); + } + } + + err = touch_sensor_start_continuous_scanning(this->sens_handle_); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start continuous scanning: %s", esp_err_to_name(err)); + this->mark_failed(); + return; + } +} + +void ESP32TouchComponent::dump_config() { +#if !defined(USE_ESP32_VARIANT_ESP32P4) + static constexpr const char *LV_STRS[] = {"0.5V", "0.6V", "0.7V", "0.8V"}; + static constexpr const char *HV_STRS[] = {"0.9V", "1.0V", "1.1V", "1.2V", "1.4V", "1.5V", "1.6V", "1.7V", + "1.9V", "2.0V", "2.1V", "2.2V", "2.4V", "2.5V", "2.6V", "2.7V"}; + const char *lv_s = lookup_str(LV_STRS, this->low_voltage_reference_); + const char *hv_s = lookup_str(HV_STRS, this->high_voltage_reference_); + + ESP_LOGCONFIG(TAG, + "Config for ESP32 Touch Hub:\n" + " Measurement interval: %.1fus\n" + " Low Voltage Reference: %s\n" + " High Voltage Reference: %s", + this->meas_interval_us_, lv_s, hv_s); +#else + ESP_LOGCONFIG(TAG, + "Config for ESP32 Touch Hub:\n" + " Measurement interval: %.1fus", + this->meas_interval_us_); +#endif + +#ifdef USE_ESP32_VARIANT_ESP32 + if (this->iir_filter_enabled_()) { + ESP_LOGCONFIG(TAG, " IIR Filter: %" PRIu32 "ms", this->iir_filter_); + } else { + ESP_LOGCONFIG(TAG, " IIR Filter: 10ms (default)"); + } +#else + if (this->filter_configured_) { + // TOUCH_BM_IIR_FILTER_256 only exists on V2, shifting JITTER's position + static constexpr const char *FILTER_STRS[] = { + "IIR_4", + "IIR_8", + "IIR_16", + "IIR_32", + "IIR_64", + "IIR_128", +#if SOC_TOUCH_SENSOR_VERSION == 2 + "IIR_256", +#endif + "JITTER", + }; + static constexpr const char *SMOOTH_STRS[] = {"OFF", "IIR_2", "IIR_4", "IIR_8"}; + const char *filter_s = lookup_str(FILTER_STRS, this->filter_mode_); + const char *smooth_s = lookup_str(SMOOTH_STRS, this->smooth_level_); + ESP_LOGCONFIG(TAG, + " Filter mode: %s\n" + " Debounce count: %" PRIu32 "\n" + " Noise threshold coefficient: %" PRIu32 "\n" + " Jitter filter step size: %" PRIu32 "\n" + " Smooth level: %s", + filter_s, this->debounce_count_, this->noise_threshold_, this->jitter_step_, smooth_s); + } + +#if SOC_TOUCH_SUPPORT_DENOISE_CHAN + if (this->denoise_configured_) { + static constexpr const char *GRADE_STRS[] = {"BIT12", "BIT10", "BIT8", "BIT4"}; + static constexpr const char *CAP_STRS[] = {"5pF", "6.4pF", "7.8pF", "9.2pF", "10.6pF", "12pF", "13.4pF", "14.8pF"}; + const char *grade_s = lookup_str(GRADE_STRS, this->denoise_grade_); + const char *cap_s = lookup_str(CAP_STRS, this->denoise_cap_level_); + ESP_LOGCONFIG(TAG, + " Denoise grade: %s\n" + " Denoise capacitance level: %s", + grade_s, cap_s); + } +#endif +#endif // !USE_ESP32_VARIANT_ESP32 + + if (this->setup_mode_) { + ESP_LOGCONFIG(TAG, " Setup Mode ENABLED"); + } + + for (auto *child : this->children_) { + LOG_BINARY_SENSOR(" ", "Touch Pad", child); + ESP_LOGCONFIG(TAG, + " Channel: %d\n" + " Threshold: %" PRIu32 "\n" + " Benchmark: %" PRIu32, + child->channel_id_, child->threshold_, child->benchmark_); + } +} + +void ESP32TouchComponent::loop() { + const uint32_t now = App.get_loop_component_start_time(); + + // In setup mode, periodically log all pad values + this->process_setup_mode_logging_(now); + + // Process queued touch events from callbacks + TouchEvent event; + while (xQueueReceive(this->touch_queue_, &event, 0) == pdTRUE) { + for (auto *child : this->children_) { + if (child->get_channel_id() != event.chan_id) { + continue; + } + + // Read current smooth value + uint32_t value = 0; + touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_SMOOTH, &value); + child->value_ = value; + +#ifndef USE_ESP32_VARIANT_ESP32 + // V2/V3: also read benchmark + uint32_t benchmark = 0; + touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark); + child->benchmark_ = benchmark; +#endif + + bool new_state = event.is_active; + + if (new_state != child->last_state_) { + child->initial_state_published_ = true; + child->last_state_ = new_state; + child->publish_state(new_state); +#ifdef USE_ESP32_VARIANT_ESP32 + ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 ", threshold: %" PRIu32 ")", + child->get_name().c_str(), ONOFF(new_state), value, child->get_threshold()); +#else + if (new_state) { + ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 ", benchmark: %" PRIu32 ", threshold: %" PRIu32 ")", + child->get_name().c_str(), value, benchmark, child->get_threshold()); + } else { + ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str()); + } +#endif + } + break; + } + } + + // Publish initial OFF state for sensors that haven't received events yet + for (auto *child : this->children_) { + this->publish_initial_state_if_needed_(child, now); + } + + if (!this->setup_mode_) { + this->disable_loop(); + } +} + +void ESP32TouchComponent::on_shutdown() { + if (this->sens_handle_ == nullptr) + return; + + touch_sensor_stop_continuous_scanning(this->sens_handle_); + touch_sensor_disable(this->sens_handle_); + + for (auto *child : this->children_) { + if (child->chan_handle_ != nullptr) { + touch_sensor_del_channel(child->chan_handle_); + child->chan_handle_ = nullptr; + } + } + + touch_sensor_del_controller(this->sens_handle_); + this->sens_handle_ = nullptr; + + this->cleanup_touch_queue_(); +} + +bool ESP32TouchComponent::create_touch_queue_() { + size_t queue_size = this->children_.size() * 4; + if (queue_size < 8) + queue_size = 8; + + this->touch_queue_ = xQueueCreate(queue_size, sizeof(TouchEvent)); + + if (this->touch_queue_ == nullptr) { + ESP_LOGE(TAG, "Failed to create touch event queue of size %" PRIu32, (uint32_t) queue_size); + this->mark_failed(); + return false; + } + return true; +} + +void ESP32TouchComponent::cleanup_touch_queue_() { + if (this->touch_queue_) { + vQueueDelete(this->touch_queue_); + this->touch_queue_ = nullptr; + } +} + +void ESP32TouchComponent::configure_wakeup_pads_() { +#if SOC_TOUCH_SUPPORT_SLEEP_WAKEUP + bool has_wakeup = false; + for (auto *child : this->children_) { + if (child->get_wakeup_threshold() != 0) { + has_wakeup = true; + break; + } + } + + if (!has_wakeup) + return; + +#ifdef USE_ESP32_VARIANT_ESP32 + // V1: Simple sleep config - threshold is set via channel config's abs_active_thresh + touch_sleep_config_t sleep_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG(); + sleep_cfg.deep_slp_sens_cfg = nullptr; + esp_err_t err = touch_sensor_config_sleep_wakeup(this->sens_handle_, &sleep_cfg); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to configure touch sleep wakeup: %s", esp_err_to_name(err)); + } +#else + // V2/V3: Need to specify a deep sleep channel and threshold + touch_channel_handle_t wakeup_chan = nullptr; + uint32_t wakeup_thresh = 0; + for (auto *child : this->children_) { + if (child->get_wakeup_threshold() != 0) { + wakeup_chan = child->chan_handle_; + wakeup_thresh = child->get_wakeup_threshold(); + break; // Only one deep sleep wakeup channel is supported + } + } + + if (wakeup_chan != nullptr) { + touch_sleep_config_t sleep_cfg = TOUCH_SENSOR_DEFAULT_DSLP_CONFIG(); + sleep_cfg.deep_slp_chan = wakeup_chan; + sleep_cfg.deep_slp_thresh[0] = wakeup_thresh; + sleep_cfg.deep_slp_sens_cfg = nullptr; + esp_err_t err = touch_sensor_config_sleep_wakeup(this->sens_handle_, &sleep_cfg); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to configure touch sleep wakeup: %s", esp_err_to_name(err)); + } + } +#endif +#endif // SOC_TOUCH_SUPPORT_SLEEP_WAKEUP +} + +void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) { + if (this->setup_mode_ && now - this->setup_mode_last_log_print_ > SETUP_MODE_LOG_INTERVAL_MS) { + for (auto *child : this->children_) { + if (child->chan_handle_ == nullptr) + continue; + + uint32_t smooth_value = 0; + touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_SMOOTH, &smooth_value); + child->value_ = smooth_value; + +#ifdef USE_ESP32_VARIANT_ESP32 + ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, child->get_name().c_str(), child->channel_id_, smooth_value); +#else + uint32_t benchmark = 0; + touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark); + child->benchmark_ = benchmark; + int32_t difference = static_cast<int32_t>(smooth_value) - static_cast<int32_t>(benchmark); + ESP_LOGD(TAG, + "Touch Pad '%s' (Ch%d): value=%" PRIu32 ", benchmark=%" PRIu32 ", difference=%" PRId32 + " (set threshold < %" PRId32 " to detect touch)", + child->get_name().c_str(), child->channel_id_, smooth_value, benchmark, difference, difference); +#endif + } + this->setup_mode_last_log_print_ = now; + } +} + +void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySensor *child, uint32_t now) { + if (!child->initial_state_published_) { + if (now > INITIAL_STATE_DELAY_MS) { + child->publish_initial_state(false); + child->initial_state_published_ = true; + ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str()); + } + } +} + +} // namespace esphome::esp32_touch + +#endif // USE_ESP32 diff --git a/esphome/components/esp32_touch/esp32_touch.h b/esphome/components/esp32_touch/esp32_touch.h index 7f45f2ccb4..d51b2d4922 100644 --- a/esphome/components/esp32_touch/esp32_touch.h +++ b/esphome/components/esp32_touch/esp32_touch.h @@ -4,49 +4,49 @@ #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" -#include <esp_idf_version.h> #include <vector> -#include <driver/touch_sensor.h> +#include <driver/touch_sens.h> #include <freertos/FreeRTOS.h> #include <freertos/queue.h> -namespace esphome { -namespace esp32_touch { +namespace esphome::esp32_touch { // IMPORTANT: Touch detection logic differs between ESP32 variants: -// - ESP32 v1 (original): Touch detected when value < threshold (capacitance increase causes value decrease) -// - ESP32-S2/S3 v2: Touch detected when value > threshold (capacitance increase causes value increase) -// This inversion is due to different hardware implementations between chip generations. +// - ESP32 v1 (original): Touch detected when value < threshold (absolute threshold, capacitance increase causes +// value decrease) +// - ESP32-S2/S3 v2, ESP32-P4 v3: Touch detected when (smooth - benchmark) > threshold (relative threshold) // -// INTERRUPT BEHAVIOR: -// - ESP32 v1: Interrupts fire when ANY pad is touched and continue while touched. -// Releases are detected by timeout since hardware doesn't generate release interrupts. -// - ESP32-S2/S3 v2: Hardware supports both touch and release interrupts, but release -// interrupts are unreliable and sometimes don't fire. We now only use touch interrupts -// and detect releases via timeout, similar to v1. - -static const uint32_t SETUP_MODE_LOG_INTERVAL_MS = 250; +// CALLBACK BEHAVIOR: +// - ESP32 v1: on_active/on_inactive fire from a software filter timer (esp_timer context). +// The software filter MUST be configured for these callbacks to fire. +// - ESP32-S2/S3 v2, ESP32-P4 v3: on_active/on_inactive fire from hardware ISR context. +// Release detection via on_inactive is used, with timeout as safety fallback. class ESP32TouchBinarySensor; -class ESP32TouchComponent : public Component { +class ESP32TouchComponent final : public Component { public: void register_touch_pad(ESP32TouchBinarySensor *pad) { this->children_.push_back(pad); } void set_setup_mode(bool setup_mode) { this->setup_mode_ = setup_mode; } - void set_sleep_duration(uint16_t sleep_duration) { this->sleep_cycle_ = sleep_duration; } - void set_measurement_duration(uint16_t meas_cycle) { this->meas_cycle_ = meas_cycle; } - void set_low_voltage_reference(touch_low_volt_t low_voltage_reference) { + void set_meas_interval_us(float meas_interval_us) { this->meas_interval_us_ = meas_interval_us; } + +#ifdef USE_ESP32_VARIANT_ESP32 + void set_charge_duration_ms(float charge_duration_ms) { this->charge_duration_ms_ = charge_duration_ms; } +#else + void set_charge_times(uint32_t charge_times) { this->charge_times_ = charge_times; } +#endif + +#if !defined(USE_ESP32_VARIANT_ESP32P4) + void set_low_voltage_reference(touch_volt_lim_l_t low_voltage_reference) { this->low_voltage_reference_ = low_voltage_reference; } - void set_high_voltage_reference(touch_high_volt_t high_voltage_reference) { + void set_high_voltage_reference(touch_volt_lim_h_t high_voltage_reference) { this->high_voltage_reference_ = high_voltage_reference; } - void set_voltage_attenuation(touch_volt_atten_t voltage_attenuation) { - this->voltage_attenuation_ = voltage_attenuation; - } +#endif void setup() override; void dump_config() override; @@ -54,183 +54,130 @@ class ESP32TouchComponent : public Component { void on_shutdown() override; -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - void set_filter_mode(touch_filter_mode_t filter_mode) { this->filter_mode_ = filter_mode; } - void set_debounce_count(uint32_t debounce_count) { this->debounce_count_ = debounce_count; } - void set_noise_threshold(uint32_t noise_threshold) { this->noise_threshold_ = noise_threshold; } - void set_jitter_step(uint32_t jitter_step) { this->jitter_step_ = jitter_step; } - void set_smooth_level(touch_smooth_mode_t smooth_level) { this->smooth_level_ = smooth_level; } - void set_denoise_grade(touch_pad_denoise_grade_t denoise_grade) { this->grade_ = denoise_grade; } - void set_denoise_cap(touch_pad_denoise_cap_t cap_level) { this->cap_level_ = cap_level; } - void set_waterproof_guard_ring_pad(touch_pad_t pad) { this->waterproof_guard_ring_pad_ = pad; } - void set_waterproof_shield_driver(touch_pad_shield_driver_t drive_capability) { +#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4) + void set_filter_mode(touch_benchmark_filter_mode_t filter_mode) { + this->filter_mode_ = filter_mode; + this->filter_configured_ = true; + } + void set_debounce_count(uint32_t debounce_count) { + this->debounce_count_ = debounce_count; + this->filter_configured_ = true; + } + void set_noise_threshold(uint32_t noise_threshold) { + this->noise_threshold_ = noise_threshold; + this->filter_configured_ = true; + } + void set_jitter_step(uint32_t jitter_step) { + this->jitter_step_ = jitter_step; + this->filter_configured_ = true; + } + void set_smooth_level(touch_smooth_filter_mode_t smooth_level) { + this->smooth_level_ = smooth_level; + this->filter_configured_ = true; + } +#if SOC_TOUCH_SUPPORT_DENOISE_CHAN + void set_denoise_grade(touch_denoise_chan_resolution_t denoise_grade) { + this->denoise_grade_ = denoise_grade; + this->denoise_configured_ = true; + } + void set_denoise_cap(touch_denoise_chan_cap_t cap_level) { + this->denoise_cap_level_ = cap_level; + this->denoise_configured_ = true; + } +#endif + void set_waterproof_guard_ring_pad(int channel_id) { + this->waterproof_guard_ring_pad_ = channel_id; + this->waterproof_configured_ = true; + } + void set_waterproof_shield_driver(uint32_t drive_capability) { this->waterproof_shield_driver_ = drive_capability; + this->waterproof_configured_ = true; } #else void set_iir_filter(uint32_t iir_filter) { this->iir_filter_ = iir_filter; } #endif protected: + // Unified touch event for queue communication + struct TouchEvent { + int chan_id; + bool is_active; + }; + // Common helper methods - void dump_config_base_(); - void dump_config_sensors_(); bool create_touch_queue_(); void cleanup_touch_queue_(); void configure_wakeup_pads_(); // Helper methods for loop() logic void process_setup_mode_logging_(uint32_t now); - bool should_check_for_releases_(uint32_t now); void publish_initial_state_if_needed_(ESP32TouchBinarySensor *child, uint32_t now); - void check_and_disable_loop_if_all_released_(size_t pads_off); - void calculate_release_timeout_(); + + // Unified callbacks for new API + static bool on_active_cb(touch_sensor_handle_t handle, const touch_active_event_data_t *event, void *ctx); + static bool on_inactive_cb(touch_sensor_handle_t handle, const touch_inactive_event_data_t *event, void *ctx); // Common members std::vector<ESP32TouchBinarySensor *> children_; bool setup_mode_{false}; uint32_t setup_mode_last_log_print_{0}; - uint32_t last_release_check_{0}; - uint32_t release_timeout_ms_{1500}; - uint32_t release_check_interval_ms_{50}; + + // Controller handle (new API) + touch_sensor_handle_t sens_handle_{nullptr}; + QueueHandle_t touch_queue_{nullptr}; // Common configuration parameters - uint16_t sleep_cycle_{4095}; - uint16_t meas_cycle_{65535}; - touch_low_volt_t low_voltage_reference_{TOUCH_LVOLT_0V5}; - touch_high_volt_t high_voltage_reference_{TOUCH_HVOLT_2V7}; - touch_volt_atten_t voltage_attenuation_{TOUCH_HVOLT_ATTEN_0V}; + float meas_interval_us_{320.0f}; - // Common constants - static constexpr uint32_t MINIMUM_RELEASE_TIME_MS = 100; +#ifdef USE_ESP32_VARIANT_ESP32 + float charge_duration_ms_{1.0f}; +#else + uint32_t charge_times_{500}; +#endif - // ==================== PLATFORM SPECIFIC ==================== +#if !defined(USE_ESP32_VARIANT_ESP32P4) + touch_volt_lim_l_t low_voltage_reference_{TOUCH_VOLT_LIM_L_0V5}; + touch_volt_lim_h_t high_voltage_reference_{TOUCH_VOLT_LIM_H_2V7}; +#endif #ifdef USE_ESP32_VARIANT_ESP32 // ESP32 v1 specific - - static void touch_isr_handler(void *arg); - QueueHandle_t touch_queue_{nullptr}; - - private: - // Touch event structure for ESP32 v1 - // Contains touch pad info, value, and touch state for queue communication - struct TouchPadEventV1 { - touch_pad_t pad; - uint32_t value; - bool is_touched; - }; - - protected: uint32_t iir_filter_{0}; bool iir_filter_enabled_() const { return this->iir_filter_ > 0; } -#elif defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - // ESP32-S2/S3 v2 specific - static void touch_isr_handler(void *arg); - QueueHandle_t touch_queue_{nullptr}; +#elif defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) || defined(USE_ESP32_VARIANT_ESP32P4) + // ESP32-S2/S3/P4 v2/v3 specific - private: - // Touch event structure for ESP32 v2 (S2/S3) - // Contains touch pad and interrupt mask for queue communication - struct TouchPadEventV2 { - touch_pad_t pad; - uint32_t intr_mask; - }; - - protected: - // Filter configuration - touch_filter_mode_t filter_mode_{TOUCH_PAD_FILTER_MAX}; + // Filter configuration - use sentinel values to detect "not configured" + touch_benchmark_filter_mode_t filter_mode_{TOUCH_BM_JITTER_FILTER}; uint32_t debounce_count_{0}; uint32_t noise_threshold_{0}; uint32_t jitter_step_{0}; - touch_smooth_mode_t smooth_level_{TOUCH_PAD_SMOOTH_MAX}; + touch_smooth_filter_mode_t smooth_level_{TOUCH_SMOOTH_NO_FILTER}; + bool filter_configured_{false}; +#if SOC_TOUCH_SUPPORT_DENOISE_CHAN // Denoise configuration - touch_pad_denoise_grade_t grade_{TOUCH_PAD_DENOISE_MAX}; - touch_pad_denoise_cap_t cap_level_{TOUCH_PAD_DENOISE_CAP_MAX}; - - // Waterproof configuration - touch_pad_t waterproof_guard_ring_pad_{TOUCH_PAD_MAX}; - touch_pad_shield_driver_t waterproof_shield_driver_{TOUCH_PAD_SHIELD_DRV_MAX}; - - bool filter_configured_() const { - return (this->filter_mode_ != TOUCH_PAD_FILTER_MAX) && (this->smooth_level_ != TOUCH_PAD_SMOOTH_MAX); - } - bool denoise_configured_() const { - return (this->grade_ != TOUCH_PAD_DENOISE_MAX) && (this->cap_level_ != TOUCH_PAD_DENOISE_CAP_MAX); - } - bool waterproof_configured_() const { - return (this->waterproof_guard_ring_pad_ != TOUCH_PAD_MAX) && - (this->waterproof_shield_driver_ != TOUCH_PAD_SHIELD_DRV_MAX); - } - - // Helper method to read touch values - non-blocking operation - // Returns the current touch pad value using either filtered or raw reading - // based on the filter configuration - uint32_t read_touch_value(touch_pad_t pad) const; - - // Helper to update touch state with a known state and value - void update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched, uint32_t value); - - // Helper to read touch value and update state for a given child - bool check_and_update_touch_state_(ESP32TouchBinarySensor *child); + touch_denoise_chan_resolution_t denoise_grade_{TOUCH_DENOISE_CHAN_RESOLUTION_BIT12}; + touch_denoise_chan_cap_t denoise_cap_level_{TOUCH_DENOISE_CHAN_CAP_5PF}; + bool denoise_configured_{false}; #endif - // Helper functions for dump_config - common to both implementations - static const char *get_low_voltage_reference_str(touch_low_volt_t ref) { - switch (ref) { - case TOUCH_LVOLT_0V5: - return "0.5V"; - case TOUCH_LVOLT_0V6: - return "0.6V"; - case TOUCH_LVOLT_0V7: - return "0.7V"; - case TOUCH_LVOLT_0V8: - return "0.8V"; - default: - return "UNKNOWN"; - } - } - - static const char *get_high_voltage_reference_str(touch_high_volt_t ref) { - switch (ref) { - case TOUCH_HVOLT_2V4: - return "2.4V"; - case TOUCH_HVOLT_2V5: - return "2.5V"; - case TOUCH_HVOLT_2V6: - return "2.6V"; - case TOUCH_HVOLT_2V7: - return "2.7V"; - default: - return "UNKNOWN"; - } - } - - static const char *get_voltage_attenuation_str(touch_volt_atten_t atten) { - switch (atten) { - case TOUCH_HVOLT_ATTEN_1V5: - return "1.5V"; - case TOUCH_HVOLT_ATTEN_1V: - return "1V"; - case TOUCH_HVOLT_ATTEN_0V5: - return "0.5V"; - case TOUCH_HVOLT_ATTEN_0V: - return "0V"; - default: - return "UNKNOWN"; - } - } + // Waterproof configuration + int waterproof_guard_ring_pad_{-1}; + uint32_t waterproof_shield_driver_{0}; + bool waterproof_configured_{false}; +#endif }; /// Simple helper class to expose a touch pad value as a binary sensor. class ESP32TouchBinarySensor : public binary_sensor::BinarySensor { public: - ESP32TouchBinarySensor(touch_pad_t touch_pad, uint32_t threshold, uint32_t wakeup_threshold) - : touch_pad_(touch_pad), threshold_(threshold), wakeup_threshold_(wakeup_threshold) {} + ESP32TouchBinarySensor(int channel_id, uint32_t threshold, uint32_t wakeup_threshold) + : channel_id_(channel_id), threshold_(threshold), wakeup_threshold_(wakeup_threshold) {} - touch_pad_t get_touch_pad() const { return this->touch_pad_; } + int get_channel_id() const { return this->channel_id_; } uint32_t get_threshold() const { return this->threshold_; } void set_threshold(uint32_t threshold) { this->threshold_ = threshold; } @@ -242,39 +189,22 @@ class ESP32TouchBinarySensor : public binary_sensor::BinarySensor { uint32_t get_wakeup_threshold() const { return this->wakeup_threshold_; } -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - /// Ensure benchmark value is read (v2 touch hardware only). - /// Called from multiple places - kept as helper to document shared usage. - void ensure_benchmark_read() { - if (this->benchmark_ == 0) { - touch_pad_read_benchmark(this->touch_pad_, &this->benchmark_); - } - } -#endif - protected: friend ESP32TouchComponent; - touch_pad_t touch_pad_{TOUCH_PAD_MAX}; + int channel_id_; + touch_channel_handle_t chan_handle_{nullptr}; uint32_t threshold_{0}; - uint32_t benchmark_{}; + uint32_t benchmark_{0}; /// Stores the last raw touch measurement value. uint32_t value_{0}; bool last_state_{false}; const uint32_t wakeup_threshold_{0}; // Track last touch time for timeout-based release detection - // Design note: last_touch_time_ does not require synchronization primitives because: - // 1. ESP32 guarantees atomic 32-bit aligned reads/writes - // 2. ISR only writes timestamps, main loop only reads - // 3. Timing tolerance allows for occasional stale reads (50ms check interval) - // 4. Queue operations provide implicit memory barriers - // Using atomic/critical sections would add overhead without meaningful benefit - uint32_t last_touch_time_{}; - bool initial_state_published_{}; + bool initial_state_published_{false}; }; -} // namespace esp32_touch -} // namespace esphome +} // namespace esphome::esp32_touch #endif diff --git a/esphome/components/esp32_touch/esp32_touch_common.cpp b/esphome/components/esp32_touch/esp32_touch_common.cpp deleted file mode 100644 index 429b5173be..0000000000 --- a/esphome/components/esp32_touch/esp32_touch_common.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifdef USE_ESP32 - -#include "esp32_touch.h" -#include "esphome/core/log.h" -#include <cinttypes> - -#include "soc/rtc.h" - -namespace esphome { -namespace esp32_touch { - -static const char *const TAG = "esp32_touch"; - -void ESP32TouchComponent::dump_config_base_() { - const char *lv_s = get_low_voltage_reference_str(this->low_voltage_reference_); - const char *hv_s = get_high_voltage_reference_str(this->high_voltage_reference_); - const char *atten_s = get_voltage_attenuation_str(this->voltage_attenuation_); - - ESP_LOGCONFIG(TAG, - "Config for ESP32 Touch Hub:\n" - " Meas cycle: %.2fms\n" - " Sleep cycle: %.2fms\n" - " Low Voltage Reference: %s\n" - " High Voltage Reference: %s\n" - " Voltage Attenuation: %s\n" - " Release Timeout: %" PRIu32 "ms\n", - this->meas_cycle_ / (8000000.0f / 1000.0f), this->sleep_cycle_ / (150000.0f / 1000.0f), lv_s, hv_s, - atten_s, this->release_timeout_ms_); -} - -void ESP32TouchComponent::dump_config_sensors_() { - for (auto *child : this->children_) { - LOG_BINARY_SENSOR(" ", "Touch Pad", child); - ESP_LOGCONFIG(TAG, - " Pad: T%u\n" - " Threshold: %" PRIu32 "\n" - " Benchmark: %" PRIu32, - (unsigned) child->touch_pad_, child->threshold_, child->benchmark_); - } -} - -bool ESP32TouchComponent::create_touch_queue_() { - // Queue size calculation: children * 4 allows for burst scenarios where ISR - // fires multiple times before main loop processes. - size_t queue_size = this->children_.size() * 4; - if (queue_size < 8) - queue_size = 8; - -#ifdef USE_ESP32_VARIANT_ESP32 - this->touch_queue_ = xQueueCreate(queue_size, sizeof(TouchPadEventV1)); -#else - this->touch_queue_ = xQueueCreate(queue_size, sizeof(TouchPadEventV2)); -#endif - - if (this->touch_queue_ == nullptr) { - ESP_LOGE(TAG, "Failed to create touch event queue of size %" PRIu32, (uint32_t) queue_size); - this->mark_failed(); - return false; - } - return true; -} - -void ESP32TouchComponent::cleanup_touch_queue_() { - if (this->touch_queue_) { - vQueueDelete(this->touch_queue_); - this->touch_queue_ = nullptr; - } -} - -void ESP32TouchComponent::configure_wakeup_pads_() { - bool is_wakeup_source = false; - - // Check if any pad is configured for wakeup - for (auto *child : this->children_) { - if (child->get_wakeup_threshold() != 0) { - is_wakeup_source = true; - -#ifdef USE_ESP32_VARIANT_ESP32 - // ESP32 v1: No filter available when using as wake-up source. - touch_pad_config(child->get_touch_pad(), child->get_wakeup_threshold()); -#else - // ESP32-S2/S3 v2: Set threshold for wakeup - touch_pad_set_thresh(child->get_touch_pad(), child->get_wakeup_threshold()); -#endif - } - } - - if (!is_wakeup_source) { - // If no pad is configured for wakeup, deinitialize touch pad - touch_pad_deinit(); - } -} - -void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) { - if (this->setup_mode_ && now - this->setup_mode_last_log_print_ > SETUP_MODE_LOG_INTERVAL_MS) { - for (auto *child : this->children_) { -#ifdef USE_ESP32_VARIANT_ESP32 - ESP_LOGD(TAG, "Touch Pad '%s' (T%" PRIu32 "): %" PRIu32, child->get_name().c_str(), - (uint32_t) child->get_touch_pad(), child->value_); -#else - // Read the value being used for touch detection - uint32_t value = this->read_touch_value(child->get_touch_pad()); - // Store the value for get_value() access in lambdas - child->value_ = value; - // Read benchmark if not already read - child->ensure_benchmark_read(); - // Calculate difference to help user set threshold - // For ESP32-S2/S3 v2: touch detected when value > benchmark + threshold - // So threshold should be < (value - benchmark) when touched - int32_t difference = static_cast<int32_t>(value) - static_cast<int32_t>(child->benchmark_); - ESP_LOGD(TAG, - "Touch Pad '%s' (T%d): value=%d, benchmark=%" PRIu32 ", difference=%" PRId32 " (set threshold < %" PRId32 - " to detect touch)", - child->get_name().c_str(), child->get_touch_pad(), value, child->benchmark_, difference, difference); -#endif - } - this->setup_mode_last_log_print_ = now; - } -} - -bool ESP32TouchComponent::should_check_for_releases_(uint32_t now) { - if (now - this->last_release_check_ < this->release_check_interval_ms_) { - return false; - } - this->last_release_check_ = now; - return true; -} - -void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySensor *child, uint32_t now) { - if (!child->initial_state_published_) { - // Check if enough time has passed since startup - if (now > this->release_timeout_ms_) { - child->publish_initial_state(false); - child->initial_state_published_ = true; - ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str()); - } - } -} - -void ESP32TouchComponent::check_and_disable_loop_if_all_released_(size_t pads_off) { - // Disable the loop to save CPU cycles when all pads are off and not in setup mode. - if (pads_off == this->children_.size() && !this->setup_mode_) { - this->disable_loop(); - } -} - -void ESP32TouchComponent::calculate_release_timeout_() { - // Calculate release timeout based on sleep cycle - // Design note: Hardware limitation - interrupts only fire reliably on touch (not release) - // We must use timeout-based detection for release events - // Formula: 3 sleep cycles converted to ms, with MINIMUM_RELEASE_TIME_MS minimum - // Per ESP-IDF docs: t_sleep = sleep_cycle / SOC_CLK_RC_SLOW_FREQ_APPROX - - uint32_t rtc_freq = rtc_clk_slow_freq_get_hz(); - - // Calculate timeout as 3 sleep cycles - this->release_timeout_ms_ = (this->sleep_cycle_ * 1000 * 3) / rtc_freq; - - if (this->release_timeout_ms_ < MINIMUM_RELEASE_TIME_MS) { - this->release_timeout_ms_ = MINIMUM_RELEASE_TIME_MS; - } - - // Check for releases at 1/4 the timeout interval - // Since hardware doesn't generate reliable release interrupts, we must poll - // for releases in the main loop. Checking at 1/4 the timeout interval provides - // a good balance between responsiveness and efficiency. - this->release_check_interval_ms_ = this->release_timeout_ms_ / 4; -} - -} // namespace esp32_touch -} // namespace esphome - -#endif // USE_ESP32 diff --git a/esphome/components/esp32_touch/esp32_touch_v1.cpp b/esphome/components/esp32_touch/esp32_touch_v1.cpp deleted file mode 100644 index ffb805e008..0000000000 --- a/esphome/components/esp32_touch/esp32_touch_v1.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#ifdef USE_ESP32_VARIANT_ESP32 - -#include "esp32_touch.h" -#include "esphome/core/application.h" -#include "esphome/core/log.h" -#include "esphome/core/hal.h" - -#include <algorithm> -#include <cinttypes> - -// Include HAL for ISR-safe touch reading -#include "hal/touch_sensor_ll.h" - -namespace esphome { -namespace esp32_touch { - -static const char *const TAG = "esp32_touch"; - -static const uint32_t SETUP_MODE_THRESHOLD = 0xFFFF; - -void ESP32TouchComponent::setup() { - // Create queue for touch events - // Queue size calculation: children * 4 allows for burst scenarios where ISR - // fires multiple times before main loop processes. This is important because - // ESP32 v1 scans all pads on each interrupt, potentially sending multiple events. - if (!this->create_touch_queue_()) { - return; - } - - touch_pad_init(); - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); - - // Set up IIR filter if enabled - if (this->iir_filter_enabled_()) { - touch_pad_filter_start(this->iir_filter_); - } - - // Configure measurement parameters -#if ESP_IDF_VERSION_MAJOR >= 5 - touch_pad_set_measurement_clock_cycles(this->meas_cycle_); - touch_pad_set_measurement_interval(this->sleep_cycle_); -#else - touch_pad_set_meas_time(this->sleep_cycle_, this->meas_cycle_); -#endif - touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_); - - // Configure each touch pad - for (auto *child : this->children_) { - if (this->setup_mode_) { - touch_pad_config(child->get_touch_pad(), SETUP_MODE_THRESHOLD); - } else { - touch_pad_config(child->get_touch_pad(), child->get_threshold()); - } - } - - // Register ISR handler - esp_err_t err = touch_pad_isr_register(touch_isr_handler, this); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to register touch ISR: %s", esp_err_to_name(err)); - this->cleanup_touch_queue_(); - this->mark_failed(); - return; - } - - // Calculate release timeout based on sleep cycle - this->calculate_release_timeout_(); - - // Enable touch pad interrupt - touch_pad_intr_enable(); -} - -void ESP32TouchComponent::dump_config() { - this->dump_config_base_(); - - if (this->iir_filter_enabled_()) { - ESP_LOGCONFIG(TAG, " IIR Filter: %" PRIu32 "ms", this->iir_filter_); - } else { - ESP_LOGCONFIG(TAG, " IIR Filter DISABLED"); - } - - if (this->setup_mode_) { - ESP_LOGCONFIG(TAG, " Setup Mode ENABLED"); - } - - this->dump_config_sensors_(); -} - -void ESP32TouchComponent::loop() { - const uint32_t now = App.get_loop_component_start_time(); - - // Print debug info for all pads in setup mode - this->process_setup_mode_logging_(now); - - // Process any queued touch events from interrupts - // Note: Events are only sent by ISR for pads that were measured in that cycle (value != 0) - // This is more efficient than sending all pad states every interrupt - TouchPadEventV1 event; - while (xQueueReceive(this->touch_queue_, &event, 0) == pdTRUE) { - // Find the corresponding sensor - O(n) search is acceptable since events are infrequent - for (auto *child : this->children_) { - if (child->get_touch_pad() != event.pad) { - continue; - } - - // Found matching pad - process it - child->value_ = event.value; - - // The interrupt gives us the touch state directly - bool new_state = event.is_touched; - - // Track when we last saw this pad as touched - if (new_state) { - child->last_touch_time_ = now; - } - - // Only publish if state changed - this filters out repeated events - if (new_state != child->last_state_) { - child->initial_state_published_ = true; - child->last_state_ = new_state; - child->publish_state(new_state); - // Original ESP32: ISR only fires when touched, release is detected by timeout - // Note: ESP32 v1 uses inverted logic - touched when value < threshold - ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 " < threshold: %" PRIu32 ")", - child->get_name().c_str(), ONOFF(new_state), event.value, child->get_threshold()); - } - break; // Exit inner loop after processing matching pad - } - } - - // Check for released pads periodically - if (!this->should_check_for_releases_(now)) { - return; - } - - size_t pads_off = 0; - for (auto *child : this->children_) { - // Handle initial state publication after startup - this->publish_initial_state_if_needed_(child, now); - - if (child->last_state_) { - // Pad is currently in touched state - check for release timeout - // Using subtraction handles 32-bit rollover correctly - uint32_t time_diff = now - child->last_touch_time_; - - // Check if we haven't seen this pad recently - if (time_diff > this->release_timeout_ms_) { - // Haven't seen this pad recently, assume it's released - child->last_state_ = false; - child->publish_state(false); - ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (timeout)", child->get_name().c_str()); - pads_off++; - } - } else { - // Pad is already off - pads_off++; - } - } - - // Disable the loop to save CPU cycles when all pads are off and not in setup mode. - // The loop will be re-enabled by the ISR when any touch pad is touched. - // v1 hardware limitations require us to check all pads are off because: - // - v1 only generates interrupts on touch events (not releases) - // - We must poll for release timeouts in the main loop - // - We can only safely disable when no pads need timeout monitoring - this->check_and_disable_loop_if_all_released_(pads_off); -} - -void ESP32TouchComponent::on_shutdown() { - touch_pad_intr_disable(); - touch_pad_isr_deregister(touch_isr_handler, this); - this->cleanup_touch_queue_(); - - if (this->iir_filter_enabled_()) { - touch_pad_filter_stop(); - touch_pad_filter_delete(); - } - - // Configure wakeup pads if any are set - this->configure_wakeup_pads_(); -} - -void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { - ESP32TouchComponent *component = static_cast<ESP32TouchComponent *>(arg); - - uint32_t mask = 0; - touch_ll_read_trigger_status_mask(&mask); - touch_ll_clear_trigger_status_mask(); - touch_pad_clear_status(); - - // INTERRUPT BEHAVIOR: On ESP32 v1 hardware, the interrupt fires when ANY configured - // touch pad detects a touch (value goes below threshold). The hardware does NOT - // generate interrupts on release - only on touch events. - // The interrupt will continue to fire periodically (based on sleep_cycle) as long - // as any pad remains touched. This allows us to detect both new touches and - // continued touches, but releases must be detected by timeout in the main loop. - - // Process all configured pads to check their current state - // Note: ESP32 v1 doesn't tell us which specific pad triggered the interrupt, - // so we must scan all configured pads to find which ones were touched - for (auto *child : component->children_) { - touch_pad_t pad = child->get_touch_pad(); - - // Read current value using ISR-safe API - // IMPORTANT: ESP-IDF v5.4 regression - touch_pad_read_filtered() is no longer ISR-safe - // In ESP-IDF v5.3 and earlier it was ISR-safe, but ESP-IDF v5.4 added mutex protection that causes: - // "assert failed: xQueueSemaphoreTake queue.c:1718" - // We must use raw values even when filter is enabled as a workaround. - // Users should adjust thresholds to compensate for the lack of IIR filtering. - // See: https://github.com/espressif/esp-idf/issues/17045 - uint32_t value = touch_ll_read_raw_data(pad); - - // Skip pads that aren’t in the trigger mask - if (((mask >> pad) & 1) == 0) { - continue; - } - - // IMPORTANT: ESP32 v1 touch detection logic - INVERTED compared to v2! - // ESP32 v1: Touch is detected when capacitance INCREASES, causing the measured value to DECREASE - // Therefore: touched = (value < threshold) - // This is opposite to ESP32-S2/S3 v2 where touched = (value > threshold) - bool is_touched = value < child->get_threshold(); - - // Always send the current state - the main loop will filter for changes - // We send both touched and untouched states because the ISR doesn't - // track previous state (to keep ISR fast and simple) - TouchPadEventV1 event; - event.pad = pad; - event.value = value; - event.is_touched = is_touched; - - // Send to queue from ISR - non-blocking, drops if queue full - BaseType_t x_higher_priority_task_woken = pdFALSE; - xQueueSendFromISR(component->touch_queue_, &event, &x_higher_priority_task_woken); - component->enable_loop_soon_any_context(); - if (x_higher_priority_task_woken) { - portYIELD_FROM_ISR(); - } - } -} - -} // namespace esp32_touch -} // namespace esphome - -#endif // USE_ESP32_VARIANT_ESP32 diff --git a/esphome/components/esp32_touch/esp32_touch_v2.cpp b/esphome/components/esp32_touch/esp32_touch_v2.cpp deleted file mode 100644 index b34ca1abd3..0000000000 --- a/esphome/components/esp32_touch/esp32_touch_v2.cpp +++ /dev/null @@ -1,402 +0,0 @@ -#if defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - -#include "esp32_touch.h" -#include "esphome/core/application.h" -#include "esphome/core/log.h" -#include "esphome/core/hal.h" - -namespace esphome { -namespace esp32_touch { - -static const char *const TAG = "esp32_touch"; - -// Helper to update touch state with a known state and value -void ESP32TouchComponent::update_touch_state_(ESP32TouchBinarySensor *child, bool is_touched, uint32_t value) { - // Store the value for get_value() access in lambdas - child->value_ = value; - - // Always update timer when touched - if (is_touched) { - child->last_touch_time_ = App.get_loop_component_start_time(); - } - - if (child->last_state_ != is_touched) { - child->last_state_ = is_touched; - child->publish_state(is_touched); - if (is_touched) { - ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 " > threshold: %" PRIu32 ")", child->get_name().c_str(), - value, child->threshold_ + child->benchmark_); - } else { - ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str()); - } - } -} - -// Helper to read touch value and update state for a given child (used for timeout events) -bool ESP32TouchComponent::check_and_update_touch_state_(ESP32TouchBinarySensor *child) { - // Read current touch value - uint32_t value = this->read_touch_value(child->touch_pad_); - - // ESP32-S2/S3 v2: Touch is detected when value > threshold + benchmark - ESP_LOGV(TAG, - "Checking touch state for '%s' (T%d): value = %" PRIu32 ", threshold = %" PRIu32 ", benchmark = %" PRIu32, - child->get_name().c_str(), child->touch_pad_, value, child->threshold_, child->benchmark_); - bool is_touched = value > child->benchmark_ + child->threshold_; - - this->update_touch_state_(child, is_touched, value); - return is_touched; -} - -void ESP32TouchComponent::setup() { - // Create queue for touch events first - if (!this->create_touch_queue_()) { - return; - } - - // Initialize touch pad peripheral - esp_err_t init_err = touch_pad_init(); - if (init_err != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize touch pad: %s", esp_err_to_name(init_err)); - this->mark_failed(); - return; - } - - // Configure each touch pad first - for (auto *child : this->children_) { - esp_err_t config_err = touch_pad_config(child->touch_pad_); - if (config_err != ESP_OK) { - ESP_LOGE(TAG, "Failed to configure touch pad %d: %s", child->touch_pad_, esp_err_to_name(config_err)); - } - } - - // Set up filtering if configured - if (this->filter_configured_()) { - touch_filter_config_t filter_info = { - .mode = this->filter_mode_, - .debounce_cnt = this->debounce_count_, - .noise_thr = this->noise_threshold_, - .jitter_step = this->jitter_step_, - .smh_lvl = this->smooth_level_, - }; - touch_pad_filter_set_config(&filter_info); - touch_pad_filter_enable(); - } - - if (this->denoise_configured_()) { - touch_pad_denoise_t denoise = { - .grade = this->grade_, - .cap_level = this->cap_level_, - }; - touch_pad_denoise_set_config(&denoise); - touch_pad_denoise_enable(); - } - - if (this->waterproof_configured_()) { - touch_pad_waterproof_t waterproof = { - .guard_ring_pad = this->waterproof_guard_ring_pad_, - .shield_driver = this->waterproof_shield_driver_, - }; - touch_pad_waterproof_set_config(&waterproof); - touch_pad_waterproof_enable(); - } - - // Configure measurement parameters - touch_pad_set_voltage(this->high_voltage_reference_, this->low_voltage_reference_, this->voltage_attenuation_); - touch_pad_set_charge_discharge_times(this->meas_cycle_); - touch_pad_set_measurement_interval(this->sleep_cycle_); - - // Disable hardware timeout - it causes continuous interrupts with high-capacitance - // setups (e.g., pressure sensors under cushions). The periodic release check in - // loop() handles state detection reliably without needing hardware timeout. - touch_pad_timeout_set(false, TOUCH_PAD_THRESHOLD_MAX); - - // Register ISR handler with interrupt mask - esp_err_t err = - touch_pad_isr_register(touch_isr_handler, this, static_cast<touch_pad_intr_mask_t>(TOUCH_PAD_INTR_MASK_ALL)); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to register touch ISR: %s", esp_err_to_name(err)); - this->cleanup_touch_queue_(); - this->mark_failed(); - return; - } - - // Set thresholds for each pad BEFORE starting FSM - for (auto *child : this->children_) { - if (child->threshold_ != 0) { - touch_pad_set_thresh(child->touch_pad_, child->threshold_); - } - } - - // Enable interrupts - only ACTIVE and TIMEOUT - // NOTE: We intentionally don't enable INACTIVE interrupts because they are unreliable - // on ESP32-S2/S3 hardware and sometimes don't fire. Instead, we use timeout-based - // release detection with the ability to verify the actual state. - touch_pad_intr_enable(static_cast<touch_pad_intr_mask_t>(TOUCH_PAD_INTR_MASK_ACTIVE | TOUCH_PAD_INTR_MASK_TIMEOUT)); - - // Set FSM mode before starting - touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); - - // Start FSM - touch_pad_fsm_start(); - - // Calculate release timeout based on sleep cycle - this->calculate_release_timeout_(); -} - -void ESP32TouchComponent::dump_config() { - this->dump_config_base_(); - - if (this->filter_configured_()) { - const char *filter_mode_s; - switch (this->filter_mode_) { - case TOUCH_PAD_FILTER_IIR_4: - filter_mode_s = "IIR_4"; - break; - case TOUCH_PAD_FILTER_IIR_8: - filter_mode_s = "IIR_8"; - break; - case TOUCH_PAD_FILTER_IIR_16: - filter_mode_s = "IIR_16"; - break; - case TOUCH_PAD_FILTER_IIR_32: - filter_mode_s = "IIR_32"; - break; - case TOUCH_PAD_FILTER_IIR_64: - filter_mode_s = "IIR_64"; - break; - case TOUCH_PAD_FILTER_IIR_128: - filter_mode_s = "IIR_128"; - break; - case TOUCH_PAD_FILTER_IIR_256: - filter_mode_s = "IIR_256"; - break; - case TOUCH_PAD_FILTER_JITTER: - filter_mode_s = "JITTER"; - break; - default: - filter_mode_s = "UNKNOWN"; - break; - } - ESP_LOGCONFIG(TAG, - " Filter mode: %s\n" - " Debounce count: %" PRIu32 "\n" - " Noise threshold coefficient: %" PRIu32 "\n" - " Jitter filter step size: %" PRIu32, - filter_mode_s, this->debounce_count_, this->noise_threshold_, this->jitter_step_); - const char *smooth_level_s; - switch (this->smooth_level_) { - case TOUCH_PAD_SMOOTH_OFF: - smooth_level_s = "OFF"; - break; - case TOUCH_PAD_SMOOTH_IIR_2: - smooth_level_s = "IIR_2"; - break; - case TOUCH_PAD_SMOOTH_IIR_4: - smooth_level_s = "IIR_4"; - break; - case TOUCH_PAD_SMOOTH_IIR_8: - smooth_level_s = "IIR_8"; - break; - default: - smooth_level_s = "UNKNOWN"; - break; - } - ESP_LOGCONFIG(TAG, " Smooth level: %s", smooth_level_s); - } - - if (this->denoise_configured_()) { - const char *grade_s; - switch (this->grade_) { - case TOUCH_PAD_DENOISE_BIT12: - grade_s = "BIT12"; - break; - case TOUCH_PAD_DENOISE_BIT10: - grade_s = "BIT10"; - break; - case TOUCH_PAD_DENOISE_BIT8: - grade_s = "BIT8"; - break; - case TOUCH_PAD_DENOISE_BIT4: - grade_s = "BIT4"; - break; - default: - grade_s = "UNKNOWN"; - break; - } - ESP_LOGCONFIG(TAG, " Denoise grade: %s", grade_s); - - const char *cap_level_s; - switch (this->cap_level_) { - case TOUCH_PAD_DENOISE_CAP_L0: - cap_level_s = "L0"; - break; - case TOUCH_PAD_DENOISE_CAP_L1: - cap_level_s = "L1"; - break; - case TOUCH_PAD_DENOISE_CAP_L2: - cap_level_s = "L2"; - break; - case TOUCH_PAD_DENOISE_CAP_L3: - cap_level_s = "L3"; - break; - case TOUCH_PAD_DENOISE_CAP_L4: - cap_level_s = "L4"; - break; - case TOUCH_PAD_DENOISE_CAP_L5: - cap_level_s = "L5"; - break; - case TOUCH_PAD_DENOISE_CAP_L6: - cap_level_s = "L6"; - break; - case TOUCH_PAD_DENOISE_CAP_L7: - cap_level_s = "L7"; - break; - default: - cap_level_s = "UNKNOWN"; - break; - } - ESP_LOGCONFIG(TAG, " Denoise capacitance level: %s", cap_level_s); - } - - if (this->setup_mode_) { - ESP_LOGCONFIG(TAG, " Setup Mode ENABLED"); - } - - this->dump_config_sensors_(); -} - -void ESP32TouchComponent::loop() { - const uint32_t now = App.get_loop_component_start_time(); - - // V2 TOUCH HANDLING: - // Due to unreliable INACTIVE interrupts on ESP32-S2/S3, we use a hybrid approach: - // 1. Process ACTIVE interrupts when pads are touched - // 2. Use timeout-based release detection (like v1) - // 3. But smarter than v1: verify actual state before releasing on timeout - // This prevents false releases if we missed interrupts - - // In setup mode, periodically log all pad values - this->process_setup_mode_logging_(now); - - // Process any queued touch events from interrupts - TouchPadEventV2 event; - while (xQueueReceive(this->touch_queue_, &event, 0) == pdTRUE) { - ESP_LOGD(TAG, "Event received, mask = 0x%" PRIx32 ", pad = %d", event.intr_mask, event.pad); - // Handle timeout events - if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { - // Resume measurement after timeout - touch_pad_timeout_resume(); - // For timeout events, always check the current state - } else if (!(event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE)) { - // Skip if not an active/timeout event - continue; - } - - // Find the child for the pad that triggered the interrupt - for (auto *child : this->children_) { - if (child->touch_pad_ == event.pad) { - if (event.intr_mask & TOUCH_PAD_INTR_MASK_TIMEOUT) { - // For timeout events, we need to read the value to determine state - this->check_and_update_touch_state_(child); - } else if (event.intr_mask & TOUCH_PAD_INTR_MASK_ACTIVE) { - // We only get ACTIVE interrupts now, releases are detected by timeout - // Read the current value - uint32_t value = this->read_touch_value(child->touch_pad_); - this->update_touch_state_(child, true, value); // Always touched for ACTIVE interrupts - } - break; - } - } - } - - // Check for released pads periodically (like v1) - if (!this->should_check_for_releases_(now)) { - return; - } - - size_t pads_off = 0; - for (auto *child : this->children_) { - child->ensure_benchmark_read(); - // Handle initial state publication after startup - this->publish_initial_state_if_needed_(child, now); - - if (child->last_state_) { - // Pad is currently in touched state - check for release timeout - // Using subtraction handles 32-bit rollover correctly - uint32_t time_diff = now - child->last_touch_time_; - - // Check if we haven't seen this pad recently - if (time_diff > this->release_timeout_ms_) { - // Haven't seen this pad recently - verify actual state - // Unlike v1, v2 hardware allows us to read the current state anytime - // This makes v2 smarter: we can verify if it's actually released before - // declaring a timeout, preventing false releases if interrupts were missed - bool still_touched = this->check_and_update_touch_state_(child); - - if (still_touched) { - // Still touched! Timer was reset in update_touch_state_ - ESP_LOGVV(TAG, "Touch Pad '%s' still touched after %" PRIu32 "ms timeout, resetting timer", - child->get_name().c_str(), this->release_timeout_ms_); - } else { - // Actually released - already handled by check_and_update_touch_state_ - pads_off++; - } - } - } else { - // Pad is already off - pads_off++; - } - } - - // Disable the loop when all pads are off and not in setup mode (like v1) - // We need to keep checking for timeouts, so only disable when all pads are confirmed off - this->check_and_disable_loop_if_all_released_(pads_off); -} - -void ESP32TouchComponent::on_shutdown() { - // Disable interrupts - touch_pad_intr_disable(TOUCH_PAD_INTR_MASK_ACTIVE); - touch_pad_isr_deregister(touch_isr_handler, this); - this->cleanup_touch_queue_(); - - // Configure wakeup pads if any are set - this->configure_wakeup_pads_(); -} - -void IRAM_ATTR ESP32TouchComponent::touch_isr_handler(void *arg) { - ESP32TouchComponent *component = static_cast<ESP32TouchComponent *>(arg); - BaseType_t x_higher_priority_task_woken = pdFALSE; - - // Read interrupt status - TouchPadEventV2 event; - event.intr_mask = touch_pad_read_intr_status_mask(); - event.pad = touch_pad_get_current_meas_channel(); - - // Send event to queue for processing in main loop - xQueueSendFromISR(component->touch_queue_, &event, &x_higher_priority_task_woken); - component->enable_loop_soon_any_context(); - - if (x_higher_priority_task_woken) { - portYIELD_FROM_ISR(); - } -} - -uint32_t ESP32TouchComponent::read_touch_value(touch_pad_t pad) const { - // Unlike ESP32 v1, touch reads on ESP32-S2/S3 v2 are non-blocking operations. - // The hardware continuously samples in the background and we can read the - // latest value at any time without waiting. - uint32_t value = 0; - if (this->filter_configured_()) { - // Read filtered/smoothed value when filter is enabled - touch_pad_filter_read_smooth(pad, &value); - } else { - // Read raw value when filter is not configured - touch_pad_read_raw_data(pad, &value); - } - return value; -} - -} // namespace esp32_touch -} // namespace esphome - -#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/tests/components/esp32_touch/common-variants.yaml b/tests/components/esp32_touch/common-variants.yaml index 69a3dbd969..5d6d0bbd19 100644 --- a/tests/components/esp32_touch/common-variants.yaml +++ b/tests/components/esp32_touch/common-variants.yaml @@ -4,7 +4,6 @@ esp32_touch: measurement_duration: 8ms low_voltage_reference: 0.5V high_voltage_reference: 2.7V - voltage_attenuation: 1.5V binary_sensor: - platform: esp32_touch diff --git a/tests/components/esp32_touch/test.esp32-p4-idf.yaml b/tests/components/esp32_touch/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..ab5484af44 --- /dev/null +++ b/tests/components/esp32_touch/test.esp32-p4-idf.yaml @@ -0,0 +1,5 @@ +substitutions: + pin: GPIO5 + +<<: !include common-variants.yaml +<<: !include common-get-value.yaml From 07406c96e136b61a4521ba86c00325b96f65fc66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Feb 2026 21:35:15 -1000 Subject: [PATCH 0979/2030] Bump actions/upload-artifact from 6.0.0 to 7.0.0 (#14326) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-api-proto.yml | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-api-proto.yml b/.github/workflows/ci-api-proto.yml index 0328611f5c..6d200956e9 100644 --- a/.github/workflows/ci-api-proto.yml +++ b/.github/workflows/ci-api-proto.yml @@ -62,7 +62,7 @@ jobs: run: git diff - if: failure() name: Archive artifacts - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: generated-proto-files path: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8718772f53..c2a93d37fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -822,7 +822,7 @@ jobs: fi - name: Upload memory analysis JSON - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: memory-analysis-target path: memory-analysis-target.json @@ -886,7 +886,7 @@ jobs: --platform "$platform" - name: Upload memory analysis JSON - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: memory-analysis-pr path: memory-analysis-pr.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 479b01ee37..0cca4dcaf6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -138,7 +138,7 @@ jobs: # version: ${{ needs.init.outputs.tag }} - name: Upload digests - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: digests-${{ matrix.platform.arch }} path: /tmp/digests From bd3f8e006c40dfc5e64dc37f3f90e9bc2c4ec5ac Mon Sep 17 00:00:00 2001 From: whitty <greg.whiteley@gmail.com> Date: Sat, 28 Feb 2026 03:02:29 +1100 Subject: [PATCH 0980/2030] [esp32_ble] allow setting of min/max key_size and auth_req_mode (#7138) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/esp32_ble/__init__.py | 52 +++++++++++++ esphome/components/esp32_ble/ble.cpp | 74 ++++++++++++++++++- esphome/components/esp32_ble/ble.h | 26 +++++++ esphome/core/defines.h | 1 + ...nded-auth-req-params-single.esp32-idf.yaml | 6 ++ ...st-extended-auth-req-params.esp32-idf.yaml | 5 ++ 6 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 tests/components/esp32_ble/test-extended-auth-req-params-single.esp32-idf.yaml create mode 100644 tests/components/esp32_ble/test-extended-auth-req-params.esp32-idf.yaml diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index c0e2f78bde..8b368afc2e 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -21,6 +21,7 @@ from esphome.const import ( ) from esphome.core import CORE, CoroPriority, TimePeriod, coroutine_with_priority import esphome.final_validate as fv +from esphome.types import ConfigType DEPENDENCIES = ["esp32"] CODEOWNERS = ["@jesserockz", "@Rapsssito", "@bdraco"] @@ -188,6 +189,9 @@ def register_bt_logger(*loggers: BTLoggers) -> None: CONF_BLE_ID = "ble_id" CONF_IO_CAPABILITY = "io_capability" +CONF_AUTH_REQ_MODE = "auth_req_mode" +CONF_MAX_KEY_SIZE = "max_key_size" +CONF_MIN_KEY_SIZE = "min_key_size" CONF_ADVERTISING = "advertising" CONF_ADVERTISING_CYCLE_TIME = "advertising_cycle_time" CONF_DISABLE_BT_LOGS = "disable_bt_logs" @@ -238,6 +242,18 @@ IO_CAPABILITY = { "display_yes_no": IoCapability.IO_CAP_IO, } +AuthReqMode = esp32_ble_ns.enum("AuthReqMode") +AUTH_REQ_MODE = { + "no_bond": AuthReqMode.AUTH_REQ_NO_BOND, + "bond": AuthReqMode.AUTH_REQ_BOND, + "mitm": AuthReqMode.AUTH_REQ_MITM, + "bond_mitm": AuthReqMode.AUTH_REQ_BOND_MITM, + "sc_only": AuthReqMode.AUTH_REQ_SC_ONLY, + "sc_bond": AuthReqMode.AUTH_REQ_SC_BOND, + "sc_mitm": AuthReqMode.AUTH_REQ_SC_MITM, + "sc_mitm_bond": AuthReqMode.AUTH_REQ_SC_MITM_BOND, +} + esp_power_level_t = cg.global_ns.enum("esp_power_level_t") TX_POWER_LEVELS = { @@ -258,6 +274,10 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_IO_CAPABILITY, default="none"): cv.enum( IO_CAPABILITY, lower=True ), + # note: no defaults so we can action them not being present + cv.Optional(CONF_AUTH_REQ_MODE): cv.enum(AUTH_REQ_MODE, lower=True), + cv.Optional(CONF_MAX_KEY_SIZE): cv.int_range(min=7, max=16), + cv.Optional(CONF_MIN_KEY_SIZE): cv.int_range(min=7, max=16), cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, cv.Optional(CONF_ADVERTISING, default=False): cv.boolean, cv.Optional( @@ -279,6 +299,23 @@ CONFIG_SCHEMA = cv.Schema( ).extend(cv.COMPONENT_SCHEMA) +def _validate_key_sizes(config: ConfigType) -> ConfigType: + if ( + CONF_MIN_KEY_SIZE in config + and CONF_MAX_KEY_SIZE in config + and config[CONF_MIN_KEY_SIZE] > config[CONF_MAX_KEY_SIZE] + ): + raise cv.Invalid( + f"min_key_size ({config[CONF_MIN_KEY_SIZE]}) must be " + f"less than or equal to " + f"max_key_size ({config[CONF_MAX_KEY_SIZE]})" + ) + return config + + +CONFIG_SCHEMA = cv.All(CONFIG_SCHEMA, _validate_key_sizes) + + bt_uuid16_format = "XXXX" bt_uuid32_format = "XXXXXXXX" bt_uuid128_format = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" @@ -487,6 +524,21 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT])) cg.add(var.set_io_capability(config[CONF_IO_CAPABILITY])) + + if ( + CONF_AUTH_REQ_MODE in config + or CONF_MAX_KEY_SIZE in config + or CONF_MIN_KEY_SIZE in config + ): + cg.add_define("ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS", None) + + if CONF_AUTH_REQ_MODE in config: + cg.add(var.set_auth_req(config[CONF_AUTH_REQ_MODE])) + if CONF_MAX_KEY_SIZE in config: + cg.add(var.set_max_key_size(config[CONF_MAX_KEY_SIZE])) + if CONF_MIN_KEY_SIZE in config: + cg.add(var.set_min_key_size(config[CONF_MIN_KEY_SIZE])) + cg.add(var.set_advertising_cycle_time(config[CONF_ADVERTISING_CYCLE_TIME])) if (name := config.get(CONF_NAME)) is not None: cg.add(var.set_name(name)) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index acbe9d88fc..9d26018800 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -296,12 +296,39 @@ bool ESP32BLE::ble_setup_() { return false; } - err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(uint8_t)); + err = esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &(this->io_cap_), sizeof(esp_ble_io_cap_t)); if (err != ESP_OK) { - ESP_LOGE(TAG, "esp_ble_gap_set_security_param failed: %d", err); + ESP_LOGE(TAG, "esp_ble_gap_set_security_param iocap_mode failed: %d", err); return false; } +#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + if (this->max_key_size_) { + err = esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &(this->max_key_size_), sizeof(uint8_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_set_security_param max_key_size failed: %d", err); + return false; + } + } + + if (this->min_key_size_) { + err = esp_ble_gap_set_security_param(ESP_BLE_SM_MIN_KEY_SIZE, &(this->min_key_size_), sizeof(uint8_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_set_security_param min_key_size failed: %d", err); + return false; + } + } + + if (this->auth_req_mode_) { + err = esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &(this->auth_req_mode_.value()), + sizeof(esp_ble_auth_req_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_ble_gap_set_security_param authen_req_mode failed: %d", err); + return false; + } + } +#endif // ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + // BLE takes some time to be fully set up, 200ms should be more than enough delay(200); // NOLINT @@ -645,6 +672,7 @@ void ESP32BLE::dump_config() { io_capability_s = "invalid"; break; } + char mac_s[18]; format_mac_addr_upper(mac_address, mac_s); ESP_LOGCONFIG(TAG, @@ -652,6 +680,48 @@ void ESP32BLE::dump_config() { " MAC address: %s\n" " IO Capability: %s", mac_s, io_capability_s); + +#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + const char *auth_req_mode_s = "<default>"; + if (this->auth_req_mode_) { + switch (this->auth_req_mode_.value()) { + case AUTH_REQ_NO_BOND: + auth_req_mode_s = "no_bond"; + break; + case AUTH_REQ_BOND: + auth_req_mode_s = "bond"; + break; + case AUTH_REQ_MITM: + auth_req_mode_s = "mitm"; + break; + case AUTH_REQ_BOND_MITM: + auth_req_mode_s = "bond_mitm"; + break; + case AUTH_REQ_SC_ONLY: + auth_req_mode_s = "sc_only"; + break; + case AUTH_REQ_SC_BOND: + auth_req_mode_s = "sc_bond"; + break; + case AUTH_REQ_SC_MITM: + auth_req_mode_s = "sc_mitm"; + break; + case AUTH_REQ_SC_MITM_BOND: + auth_req_mode_s = "sc_mitm_bond"; + break; + } + } + + ESP_LOGCONFIG(TAG, " Auth Req Mode: %s", auth_req_mode_s); + if (this->max_key_size_ && this->min_key_size_) { + ESP_LOGCONFIG(TAG, " Key Size: %u - %u", this->min_key_size_, this->max_key_size_); + } else if (this->max_key_size_) { + ESP_LOGCONFIG(TAG, " Key Size: <default> - %u", this->max_key_size_); + } else if (this->min_key_size_) { + ESP_LOGCONFIG(TAG, " Key Size: %u - <default>", this->min_key_size_); + } +#endif // ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + } else { ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled"); } diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index f1ab81b6dc..2ce17e97be 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -52,6 +52,19 @@ enum IoCapability { IO_CAP_KBDISP = ESP_IO_CAP_KBDISP, }; +#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS +enum AuthReqMode { + AUTH_REQ_NO_BOND = ESP_LE_AUTH_NO_BOND, + AUTH_REQ_BOND = ESP_LE_AUTH_BOND, + AUTH_REQ_MITM = ESP_LE_AUTH_REQ_MITM, + AUTH_REQ_BOND_MITM = ESP_LE_AUTH_REQ_BOND_MITM, + AUTH_REQ_SC_ONLY = ESP_LE_AUTH_REQ_SC_ONLY, + AUTH_REQ_SC_BOND = ESP_LE_AUTH_REQ_SC_BOND, + AUTH_REQ_SC_MITM = ESP_LE_AUTH_REQ_SC_MITM, + AUTH_REQ_SC_MITM_BOND = ESP_LE_AUTH_REQ_SC_MITM_BOND, +}; +#endif + enum BLEComponentState : uint8_t { /** Nothing has been initialized yet. */ BLE_COMPONENT_STATE_OFF = 0, @@ -100,6 +113,12 @@ class ESP32BLE : public Component { public: void set_io_capability(IoCapability io_capability) { this->io_cap_ = (esp_ble_io_cap_t) io_capability; } +#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + void set_max_key_size(uint8_t key_size) { this->max_key_size_ = key_size; } + void set_min_key_size(uint8_t key_size) { this->min_key_size_ = key_size; } + void set_auth_req(AuthReqMode req) { this->auth_req_mode_ = (esp_ble_auth_req_t) req; } +#endif + void set_advertising_cycle_time(uint32_t advertising_cycle_time) { this->advertising_cycle_time_ = advertising_cycle_time; } @@ -209,6 +228,13 @@ class ESP32BLE : public Component { // 1-byte aligned members (grouped together to minimize padding) BLEComponentState state_{BLE_COMPONENT_STATE_OFF}; // 1 byte (uint8_t enum) bool enable_on_boot_{}; // 1 byte + +#ifdef ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS + optional<esp_ble_auth_req_t> auth_req_mode_; + + uint8_t max_key_size_{0}; // range is 7..16, 0 is unset + uint8_t min_key_size_{0}; // range is 7..16, 0 is unset +#endif }; // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 673aa246fe..9b55ae93b1 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -209,6 +209,7 @@ #define ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT 1 #define ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT 1 #define ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT 2 +#define ESPHOME_ESP32_BLE_EXTENDED_AUTH_PARAMS #define ESPHOME_LOOP_TASK_STACK_SIZE 8192 #define USE_ESP32_CAMERA_JPEG_ENCODER #define USE_HTTP_REQUEST_RESPONSE diff --git a/tests/components/esp32_ble/test-extended-auth-req-params-single.esp32-idf.yaml b/tests/components/esp32_ble/test-extended-auth-req-params-single.esp32-idf.yaml new file mode 100644 index 0000000000..6e191c132f --- /dev/null +++ b/tests/components/esp32_ble/test-extended-auth-req-params-single.esp32-idf.yaml @@ -0,0 +1,6 @@ +esp32_ble: + io_capability: keyboard_display + # Explicitly not setting some parameters to test ifdef selection + # max_key_size: 16 + # min_key_size: 7 + auth_req_mode: sc_mitm_bond diff --git a/tests/components/esp32_ble/test-extended-auth-req-params.esp32-idf.yaml b/tests/components/esp32_ble/test-extended-auth-req-params.esp32-idf.yaml new file mode 100644 index 0000000000..f05b9bac96 --- /dev/null +++ b/tests/components/esp32_ble/test-extended-auth-req-params.esp32-idf.yaml @@ -0,0 +1,5 @@ +esp32_ble: + io_capability: keyboard_display + max_key_size: 16 + min_key_size: 7 + auth_req_mode: sc_mitm_bond From 0f7ac1726d9fea8cdb7ff481fbfcaa8b4b49620e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 09:03:37 -0700 Subject: [PATCH 0981/2030] [core] Extend fast select optimization to LibreTiny platforms (#14254) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/socket/__init__.py | 11 ++-- esphome/core/application.cpp | 43 ++++++++------- esphome/core/application.h | 27 +++++----- esphome/core/defines.h | 2 + esphome/core/lwip_fast_select.c | 54 +++++++++++-------- esphome/core/lwip_fast_select.h | 2 +- .../socket/test_wake_loop_threadsafe.py | 23 +++++--- 7 files changed, 100 insertions(+), 62 deletions(-) diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index 5f4d04eb44..a83648979c 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -149,9 +149,10 @@ def require_wake_loop_threadsafe() -> None: ): CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True cg.add_define("USE_WAKE_LOOP_THREADSAFE") - if not CORE.is_esp32: - # Only non-ESP32 platforms need a UDP socket for wake notifications. - # ESP32 uses FreeRTOS task notifications instead (no socket needed). + if not CORE.is_esp32 and not CORE.is_libretiny: + # Only platforms without fast select need a UDP socket for wake + # notifications. ESP32 and LibreTiny use FreeRTOS task notifications + # instead (no socket needed). consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({}) @@ -187,6 +188,10 @@ async def to_code(config): elif impl == IMPLEMENTATION_BSD_SOCKETS: cg.add_define("USE_SOCKET_IMPL_BSD_SOCKETS") cg.add_define("USE_SOCKET_SELECT_SUPPORT") + # ESP32 and LibreTiny both have LwIP >= 2.1.3 with lwip_socket_dbg_get_socket() + # and FreeRTOS task notifications — enable fast select to bypass lwip_select() + if CORE.is_esp32 or CORE.is_libretiny: + cg.add_define("USE_LWIP_FAST_SELECT") def FILTER_SOURCE_FILES() -> list[str]: diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index a9753da1b5..3bd4c1c670 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -9,10 +9,17 @@ #endif #ifdef USE_ESP32 #include <esp_chip_info.h> +#endif +#ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" +#ifdef USE_ESP32 #include <freertos/FreeRTOS.h> #include <freertos/task.h> +#else +#include <FreeRTOS.h> +#include <task.h> #endif +#endif // USE_LWIP_FAST_SELECT #include "esphome/core/version.h" #include "esphome/core/hal.h" #include <algorithm> @@ -147,14 +154,14 @@ void Application::setup() { clear_setup_priority_overrides(); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) // Initialize fast select: saves main loop task handle for xTaskNotifyGive wake. - // Always init on ESP32 — the fast path (rcvevent reads + ulTaskNotifyTake) is used - // unconditionally when USE_SOCKET_SELECT_SUPPORT is enabled. + // The fast path (rcvevent reads + ulTaskNotifyTake) is used unconditionally + // when USE_LWIP_FAST_SELECT is enabled (ESP32 and LibreTiny). esphome_lwip_fast_select_init(); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) - // Set up wake socket for waking main loop from tasks (non-ESP32 only) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) + // Set up wake socket for waking main loop from tasks (platforms without fast select only) this->setup_wake_loop_threadsafe_(); #endif @@ -532,7 +539,7 @@ void Application::enable_pending_loops_() { } void Application::before_loop_tasks_(uint32_t loop_start_time) { -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) // Drain wake notifications first to clear socket for next wake this->drain_wake_notifications_(); #endif @@ -585,7 +592,7 @@ bool Application::register_socket_fd(int fd) { #endif this->socket_fds_.push_back(fd); -#ifdef USE_ESP32 +#ifdef USE_LWIP_FAST_SELECT // Hook the socket's netconn callback for instant wake on receive events esphome_lwip_hook_socket(fd); #else @@ -609,12 +616,13 @@ void Application::unregister_socket_fd(int fd) { continue; // Swap with last element and pop - O(1) removal since order doesn't matter. - // No need to unhook the netconn callback on ESP32 — all LwIP sockets share - // the same static event_callback, and the socket will be closed by the caller. + // No need to unhook the netconn callback on fast select platforms — all LwIP + // sockets share the same static event_callback, and the socket will be closed + // by the caller. if (i < this->socket_fds_.size() - 1) this->socket_fds_[i] = this->socket_fds_.back(); this->socket_fds_.pop_back(); -#ifndef USE_ESP32 +#ifndef USE_LWIP_FAST_SELECT this->socket_fds_changed_ = true; // Only recalculate max_fd if we removed the current max if (fd == this->max_fd_) { @@ -633,8 +641,8 @@ void Application::unregister_socket_fd(int fd) { void Application::yield_with_select_(uint32_t delay_ms) { // Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run. -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_ESP32) - // ESP32 fast path: reads rcvevent directly via lwip_socket_dbg_get_socket() (~215 ns per socket). +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) + // Fast path (ESP32/LibreTiny): reads rcvevent directly via lwip_socket_dbg_get_socket(). // Safe because this runs on the main loop which owns socket lifetime (create, read, close). if (delay_ms == 0) [[unlikely]] { yield(); @@ -659,9 +667,8 @@ void Application::yield_with_select_(uint32_t delay_ms) { ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(delay_ms)); #elif defined(USE_SOCKET_SELECT_SUPPORT) - // Non-ESP32 select() path (LibreTiny bk72xx/rtl87xx, host platform). - // ESP32 is excluded by the #if above — both BSD_SOCKETS and LWIP_SOCKETS on ESP32 - // use LwIP under the hood, so the fast path handles all ESP32 socket implementations. + // Fallback select() path (host platform and any future platforms without fast select). + // ESP32 and LibreTiny are excluded by the #if above — they use the fast path. if (!this->socket_fds_.empty()) [[likely]] { // Update fd_set if socket list has changed if (this->socket_fds_changed_) [[unlikely]] { @@ -725,12 +732,12 @@ alignas(Application) char app_storage[sizeof(Application)] asm("_ZN7esphome3AppE #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) -#ifdef USE_ESP32 +#ifdef USE_LWIP_FAST_SELECT void Application::wake_loop_threadsafe() { // Direct FreeRTOS task notification — <1 us, task context only (NOT ISR-safe) esphome_lwip_wake_main_loop(); } -#else // !USE_ESP32 +#else // !USE_LWIP_FAST_SELECT void Application::setup_wake_loop_threadsafe_() { // Create UDP socket for wake notifications @@ -798,7 +805,7 @@ void Application::wake_loop_threadsafe() { lwip_send(this->wake_socket_fd_, &dummy, 1, 0); } } -#endif // USE_ESP32 +#endif // USE_LWIP_FAST_SELECT #endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) diff --git a/esphome/core/application.h b/esphome/core/application.h index f5df5e7bdf..0cc29af8e7 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -24,7 +24,7 @@ #endif #ifdef USE_SOCKET_SELECT_SUPPORT -#ifdef USE_ESP32 +#ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" #else #include <sys/select.h> @@ -511,10 +511,11 @@ class Application { #ifdef USE_SOCKET_SELECT_SUPPORT /// Fast path for Socket::ready() via friendship - skips negative fd check. - /// Main loop only — on ESP32, reads rcvevent via lwip_socket_dbg_get_socket() - /// which has no refcount; safe only because the main loop owns socket lifetime - /// (creates, reads, and closes sockets on the same thread). -#ifdef USE_ESP32 + /// Main loop only — with USE_LWIP_FAST_SELECT, reads rcvevent via + /// lwip_socket_dbg_get_socket(), which has no refcount; safe only because + /// the main loop owns socket lifetime (creates, reads, and closes sockets + /// on the same thread). +#ifdef USE_LWIP_FAST_SELECT bool is_socket_ready_(int fd) const { return esphome_lwip_socket_has_data(fd); } #else bool is_socket_ready_(int fd) const { return FD_ISSET(fd, &this->read_fds_); } @@ -546,7 +547,7 @@ class Application { /// Perform a delay while also monitoring socket file descriptors for readiness void yield_with_select_(uint32_t delay_ms); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) void setup_wake_loop_threadsafe_(); // Create wake notification socket inline void drain_wake_notifications_(); // Read pending wake notifications in main loop (hot path - inlined) #endif @@ -576,7 +577,7 @@ class Application { FixedVector<Component *> looping_components_{}; #ifdef USE_SOCKET_SELECT_SUPPORT std::vector<int> socket_fds_; // Vector of all monitored socket file descriptors -#if defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) +#if defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) int wake_socket_fd_{-1}; // Shared wake notification socket for waking main loop from tasks #endif #endif @@ -589,7 +590,7 @@ class Application { uint32_t last_loop_{0}; uint32_t loop_component_start_time_{0}; -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) int max_fd_{-1}; // Highest file descriptor number for select() #endif @@ -605,12 +606,12 @@ class Application { bool in_loop_{false}; volatile bool has_pending_enable_loop_requests_{false}; -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) bool socket_fds_changed_{false}; // Flag to rebuild base_read_fds_ when socket_fds_ changes #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_ESP32) - // Variable-sized members (not needed on ESP32 — is_socket_ready_ reads rcvevent directly) +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) + // Variable-sized members (not needed with fast select — is_socket_ready_ reads rcvevent directly) fd_set read_fds_{}; // Working fd_set: populated by select() fd_set base_read_fds_{}; // Cached fd_set rebuilt only when socket_fds_ changes #endif @@ -699,7 +700,7 @@ class Application { /// Global storage of Application pointer - only one Application can exist. extern Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) // Inline implementations for hot-path functions // drain_wake_notifications_() is called on every loop iteration @@ -721,6 +722,6 @@ inline void Application::drain_wake_notifications_() { } } } -#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_ESP32) +#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) } // namespace esphome diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 9b55ae93b1..5c982c94b1 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -222,6 +222,7 @@ #define USE_SENDSPIN_PORT 8928 // NOLINT #define USE_SOCKET_IMPL_BSD_SOCKETS #define USE_SOCKET_SELECT_SUPPORT +#define USE_LWIP_FAST_SELECT #define USE_WAKE_LOOP_THREADSAFE #define USE_SPEAKER #define USE_SPI @@ -330,6 +331,7 @@ #define USE_CAPTIVE_PORTAL #define USE_SOCKET_IMPL_LWIP_SOCKETS #define USE_SOCKET_SELECT_SUPPORT +#define USE_LWIP_FAST_SELECT #define USE_WEBSERVER #define USE_WEBSERVER_AUTH #define USE_WEBSERVER_PORT 80 // NOLINT diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index 70a6482d48..88cf23b67e 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -1,11 +1,12 @@ -// Fast socket monitoring for ESP32 (ESP-IDF LwIP) +// Fast socket monitoring for ESP32 and LibreTiny (LwIP >= 2.1.3) // Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications. // // This must be a .c file (not .cpp) because: -// 1. lwip/priv/sockets_priv.h conflicts with C++ compilation units that include bootloader headers +// 1. lwip/priv/sockets_priv.h conflicts with C++ compilation units // 2. The netconn callback is a C function pointer // -// defines.h is force-included by the build system (-include flag), providing USE_ESP32 etc. +// USE_ESP32 and USE_LIBRETINY platform flags (-D) control compilation of this file. +// See the guard at the bottom of the header comment for details. // // Thread safety analysis // ====================== @@ -81,20 +82,21 @@ // Written by main loop in hook_socket(). Never restored — all LwIP sockets share // the same static event_callback (DEFAULT_SOCKET_EVENTCB), so the wrapper stays permanently. // Read by TCP/IP thread when invoking the callback. -// Safe: 32-bit aligned pointer writes are atomic on Xtensa and RISC-V (ESP32). -// The TCP/IP thread will see either the old or new pointer atomically — never a -// torn value. Both the wrapper and original callbacks are valid at all times -// (the wrapper itself calls the original), so either value is correct. +// Safe: 32-bit aligned pointer writes are atomic on Xtensa, RISC-V (ESP32), +// and ARM Cortex-M (LibreTiny). The TCP/IP thread will see either the old or +// new pointer atomically — never a torn value. Both the wrapper and original +// callbacks are valid at all times (the wrapper itself calls the original), +// so either value is correct. // // sock->rcvevent (s16_t, 2 bytes): // Written by TCP/IP thread in event_callback under SYS_ARCH_PROTECT. // Read by main loop in has_data() via volatile cast. -// Safe: SYS_ARCH_UNPROTECT releases a FreeRTOS mutex, which internally -// uses a critical section with memory barrier (rsync on dual-core Xtensa; on -// single-core builds the spinlock is compiled out, but cross-core visibility is -// not an issue). The volatile cast prevents the compiler -// from caching the read. Aligned 16-bit reads are single-instruction loads on -// Xtensa (L16SI) and RISC-V (LH), which cannot produce torn values. +// Safe: SYS_ARCH_UNPROTECT releases a FreeRTOS mutex (ESP32) or resumes the +// scheduler (LibreTiny), both providing a memory barrier. The volatile cast +// prevents the compiler from caching the read. Aligned 16-bit reads are +// single-instruction loads on Xtensa (L16SI), RISC-V (LH), and ARM Cortex-M +// (LDRH), which cannot produce torn values. On single-core chips (LibreTiny, +// ESP32-C3/C6/H2) cross-core visibility is not an issue. // // FreeRTOS task notification value: // Written by TCP/IP thread (xTaskNotifyGive in callback) and background tasks @@ -103,20 +105,30 @@ // critical sections). Multiple concurrent xTaskNotifyGive calls are safe — // the notification count simply increments. -#ifdef USE_ESP32 +// USE_ESP32 and USE_LIBRETINY are compiler -D flags, so they are always visible in this .c file. +// Feature macros like USE_LWIP_FAST_SELECT may come from generated headers that are not included here, +// so this implementation is enabled based on platform flags instead of USE_LWIP_FAST_SELECT. +#if defined(USE_ESP32) || defined(USE_LIBRETINY) // LwIP headers must come first — they define netconn_callback, struct lwip_sock, etc. #include <lwip/api.h> #include <lwip/priv/sockets_priv.h> +// FreeRTOS include paths differ: ESP-IDF uses freertos/ prefix, LibreTiny does not +#ifdef USE_ESP32 #include <freertos/FreeRTOS.h> #include <freertos/task.h> +#else +#include <FreeRTOS.h> +#include <task.h> +#endif #include "esphome/core/lwip_fast_select.h" #include <stddef.h> // Compile-time verification of thread safety assumptions. -// On ESP32 (Xtensa/RISC-V), naturally-aligned reads/writes up to 32 bits are atomic. +// On ESP32 (Xtensa/RISC-V) and LibreTiny (ARM Cortex-M), naturally-aligned +// reads/writes up to 32 bits are atomic. // These asserts ensure our cross-thread shared state meets those requirements. // Pointer types must fit in a single 32-bit store (atomic write) @@ -126,7 +138,7 @@ _Static_assert(sizeof(netconn_callback) <= 4, "netconn_callback must be <= 4 byt // rcvevent must fit in a single atomic read _Static_assert(sizeof(((struct lwip_sock *) 0)->rcvevent) <= 4, "rcvevent must be <= 4 bytes for atomic access"); -// Struct member alignment — natural alignment guarantees atomicity on Xtensa/RISC-V. +// Struct member alignment — natural alignment guarantees atomicity on Xtensa/RISC-V/ARM. // Misaligned access would not be atomic even if the size is <= 4 bytes. _Static_assert(offsetof(struct netconn, callback) % sizeof(netconn_callback) == 0, "netconn.callback must be naturally aligned for atomic access"); @@ -183,9 +195,9 @@ bool esphome_lwip_socket_has_data(int fd) { return false; // volatile prevents the compiler from caching/reordering this cross-thread read. // The write side (TCP/IP thread) commits via SYS_ARCH_UNPROTECT which releases a - // FreeRTOS mutex with a memory barrier (rsync on Xtensa), ensuring the value is - // visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH) on - // Xtensa/RISC-V and cannot produce torn values. + // FreeRTOS mutex (ESP32) or resumes the scheduler (LibreTiny), ensuring the value + // is visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH/LDRH) on + // Xtensa/RISC-V/ARM and cannot produce torn values. return *(volatile s16_t *) &sock->rcvevent > 0; } @@ -200,7 +212,7 @@ void esphome_lwip_hook_socket(int fd) { s_original_callback = sock->conn->callback; } - // Replace with our wrapper. Atomic on ESP32 (32-bit aligned pointer write). + // Replace with our wrapper. Atomic on all supported platforms (32-bit aligned pointer write). // TCP/IP thread sees either old or new pointer — both are valid. sock->conn->callback = esphome_socket_event_callback; } @@ -213,4 +225,4 @@ void esphome_lwip_wake_main_loop(void) { } } -#endif // USE_ESP32 +#endif // defined(USE_ESP32) || defined(USE_LIBRETINY) diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index 73a89fdc3d..b08c946212 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -1,6 +1,6 @@ #pragma once -// Fast socket monitoring for ESP32 (ESP-IDF LwIP) +// Fast socket monitoring for ESP32 and LibreTiny (LwIP >= 2.1.3) // Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications. #include <stdbool.h> diff --git a/tests/components/socket/test_wake_loop_threadsafe.py b/tests/components/socket/test_wake_loop_threadsafe.py index 28b4ee564f..0434b3e1b5 100644 --- a/tests/components/socket/test_wake_loop_threadsafe.py +++ b/tests/components/socket/test_wake_loop_threadsafe.py @@ -1,9 +1,14 @@ +import pytest + from esphome.components import socket from esphome.const import ( KEY_CORE, KEY_TARGET_PLATFORM, + PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, + PLATFORM_LN882X, + PLATFORM_RTL87XX, ) from esphome.core import CORE @@ -90,9 +95,15 @@ def test_require_wake_loop_threadsafe__no_networking_does_not_consume_socket() - assert udp_consumers == initial_udp -def test_require_wake_loop_threadsafe__esp32_no_udp_socket() -> None: - """Test that ESP32 uses task notifications instead of UDP socket.""" - _setup_platform(PLATFORM_ESP32) +@pytest.mark.parametrize( + "platform", + [PLATFORM_ESP32, PLATFORM_BK72XX, PLATFORM_RTL87XX, PLATFORM_LN882X], +) +def test_require_wake_loop_threadsafe__fast_select_no_udp_socket( + platform: str, +) -> None: + """Test that fast select platforms use task notifications instead of UDP socket.""" + _setup_platform(platform) CORE.config = {"wifi": True} socket.require_wake_loop_threadsafe() @@ -100,13 +111,13 @@ def test_require_wake_loop_threadsafe__esp32_no_udp_socket() -> None: assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - # Verify no UDP socket was consumed (ESP32 uses FreeRTOS task notifications) + # Verify no UDP socket was consumed (fast select platforms use FreeRTOS task notifications) udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) assert "socket.wake_loop_threadsafe" not in udp_consumers -def test_require_wake_loop_threadsafe__non_esp32_consumes_udp_socket() -> None: - """Test that non-ESP32 platforms consume a UDP socket for wake notifications.""" +def test_require_wake_loop_threadsafe__non_fast_select_consumes_udp_socket() -> None: + """Test that platforms without fast select consume a UDP socket for wake notifications.""" _setup_platform(PLATFORM_ESP8266) CORE.config = {"wifi": True} socket.require_wake_loop_threadsafe() From ef9fc87351a288293c0ad3e9ab59c7788af8db09 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:17:04 -0500 Subject: [PATCH 0982/2030] [zigbee] Fix codegen ordering for basic/identify attribute lists (#14343) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/zigbee/__init__.py | 3 ++- esphome/components/zigbee/zigbee_zephyr.py | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 7e917a9d70..a327cc2988 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -8,7 +8,7 @@ from esphome.components.zephyr import zephyr_add_pm_static, zephyr_data from esphome.components.zephyr.const import KEY_BOOTLOADER import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_INTERNAL, CONF_NAME -from esphome.core import CORE +from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.types import ConfigType from .const_zephyr import ( @@ -96,6 +96,7 @@ FINAL_VALIDATE_SCHEMA = cv.All( ) +@coroutine_with_priority(CoroPriority.CORE) async def to_code(config: ConfigType) -> None: cg.add_define("USE_ZIGBEE") if CORE.using_zephyr: diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index 0b6daa9476..a1e6ad3097 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -179,6 +179,13 @@ async def zephyr_to_code(config: ConfigType) -> None: "USE_ZIGBEE_WIPE_ON_BOOT_MAGIC", random.randint(0x000001, 0xFFFFFF) ) cg.add_define("USE_ZIGBEE_WIPE_ON_BOOT") + + # Generate attribute lists before any await that could yield (e.g., build_automation + # waiting for variables from other components). If the hub's priority decays while + # yielding, deferred entity jobs may add cluster list globals that reference these + # attribute lists before they're declared. + await _attr_to_code(config) + var = cg.new_Pvariable(config[CONF_ID]) if on_join_config := config.get(CONF_ON_JOIN): @@ -186,7 +193,6 @@ async def zephyr_to_code(config: ConfigType) -> None: await cg.register_component(var, config) - await _attr_to_code(config) CORE.add_job(_ctx_to_code, config) From 017d1b2872b9ad85bf5b8a2fb563d14ff517975c Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Fri, 27 Feb 2026 11:12:50 -0600 Subject: [PATCH 0983/2030] [audio] Bump microOpus to v0.3.4 (#14346) --- esphome/components/audio/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index d8d426ec63..d95fcf66d7 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -214,4 +214,4 @@ async def to_code(config): cg.add_define("USE_AUDIO_MP3_SUPPORT") if data.opus_support: cg.add_define("USE_AUDIO_OPUS_SUPPORT") - add_idf_component(name="esphome/micro-opus", ref="0.3.3") + add_idf_component(name="esphome/micro-opus", ref="0.3.4") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 83b2d9d95c..37bda65afd 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -4,7 +4,7 @@ dependencies: esphome/esp-audio-libs: version: 2.0.3 esphome/micro-opus: - version: 0.3.3 + version: 0.3.4 espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: From 20314b4d63ee07d97840c821cf1ca0003393a339 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 10:20:08 -0700 Subject: [PATCH 0984/2030] [mdns] Update espressif/mdns to v1.10.0 (#14338) --- esphome/components/mdns/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/mdns/__init__.py b/esphome/components/mdns/__init__.py index 420e6a60e3..0d535d6970 100644 --- a/esphome/components/mdns/__init__.py +++ b/esphome/components/mdns/__init__.py @@ -163,7 +163,7 @@ async def to_code(config): cg.add_library("LEAmDNS", None) if CORE.is_esp32: - add_idf_component(name="espressif/mdns", ref="1.9.1") + add_idf_component(name="espressif/mdns", ref="1.10.0") cg.add_define("USE_MDNS") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 37bda65afd..550e7b9af7 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -10,7 +10,7 @@ dependencies: espressif/esp32-camera: version: 2.1.1 espressif/mdns: - version: 1.9.1 + version: 1.10.0 espressif/esp_wifi_remote: version: 1.3.2 rules: From 72ca514cc2650e641faa774a7d43a81dcdf6fb98 Mon Sep 17 00:00:00 2001 From: deirdreobyrne <deirdre.dub@gmail.com> Date: Fri, 27 Feb 2026 17:25:53 +0000 Subject: [PATCH 0985/2030] [esp32_hosted] Add configurable SDIO clock frequency (#14319) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Deirdre <obyrne@rk1.lan> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/esp32_hosted/__init__.py | 8 ++++++++ .../test-sdio-speed.esp32-p4-idf.yaml | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 tests/components/esp32_hosted/test-sdio-speed.esp32-p4-idf.yaml diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 287c780769..720d81acc4 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -23,6 +23,7 @@ CONF_D1_PIN = "d1_pin" CONF_D2_PIN = "d2_pin" CONF_D3_PIN = "d3_pin" CONF_SLOT = "slot" +CONF_SDIO_FREQUENCY = "sdio_frequency" CONFIG_SCHEMA = cv.All( cv.Schema( @@ -37,6 +38,9 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_D3_PIN): pins.internal_gpio_output_pin_number, cv.Required(CONF_RESET_PIN): pins.internal_gpio_output_pin_number, cv.Optional(CONF_SLOT, default=1): cv.int_range(min=0, max=1), + cv.Optional(CONF_SDIO_FREQUENCY, default="40MHz"): cv.All( + cv.frequency, cv.Range(min=400e3, max=50e6) + ), } ), ) @@ -91,6 +95,10 @@ async def to_code(config): config[CONF_D3_PIN], ) esp32.add_idf_sdkconfig_option("CONFIG_ESP_HOSTED_CUSTOM_SDIO_PINS", True) + esp32.add_idf_sdkconfig_option( + "CONFIG_ESP_HOSTED_SDIO_CLOCK_FREQ_KHZ", + int(config[CONF_SDIO_FREQUENCY] // 1000), + ) framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] os.environ["ESP_IDF_VERSION"] = f"{framework_ver.major}.{framework_ver.minor}" diff --git a/tests/components/esp32_hosted/test-sdio-speed.esp32-p4-idf.yaml b/tests/components/esp32_hosted/test-sdio-speed.esp32-p4-idf.yaml new file mode 100644 index 0000000000..9268c9ae41 --- /dev/null +++ b/tests/components/esp32_hosted/test-sdio-speed.esp32-p4-idf.yaml @@ -0,0 +1,16 @@ +esp32_hosted: + variant: ESP32C6 + slot: 1 + active_high: true + reset_pin: GPIO15 + cmd_pin: GPIO13 + clk_pin: GPIO12 + d0_pin: GPIO11 + d1_pin: GPIO10 + d2_pin: GPIO9 + d3_pin: GPIO8 + sdio_frequency: 8MHz + +wifi: + ssid: MySSID + password: password1 From 1c7f769ec7f54775c3d31f426dcfbb14f66a911f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 10:48:21 -0700 Subject: [PATCH 0986/2030] [core] Add millis_64() HAL function with native ESP32 implementation (#14339) --- esphome/components/esp32/core.cpp | 1 + esphome/components/esp8266/core.cpp | 2 ++ esphome/components/host/core.cpp | 2 ++ esphome/components/libretiny/core.cpp | 2 ++ esphome/components/rp2040/core.cpp | 2 ++ .../uptime/sensor/uptime_seconds_sensor.cpp | 4 +-- .../uptime/text_sensor/uptime_text_sensor.cpp | 4 +-- esphome/components/web_server/web_server.cpp | 4 +-- esphome/components/zephyr/core.cpp | 2 ++ esphome/core/hal.h | 1 + esphome/core/scheduler.cpp | 34 ++++++++++-------- esphome/core/scheduler.h | 35 +++++++++++++++---- 12 files changed, 66 insertions(+), 27 deletions(-) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 202d929ab9..b9ae871abf 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -23,6 +23,7 @@ namespace esphome { void HOT yield() { vPortYield(); } uint32_t IRAM_ATTR HOT millis() { return (uint32_t) (esp_timer_get_time() / 1000ULL); } +uint64_t HOT millis_64() { return static_cast<uint64_t>(esp_timer_get_time()) / 1000ULL; } void HOT delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } uint32_t IRAM_ATTR HOT micros() { return (uint32_t) esp_timer_get_time(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 236d3022be..497e99b61f 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -3,6 +3,7 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" +#include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "preferences.h" #include <Arduino.h> @@ -16,6 +17,7 @@ namespace esphome { void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } +uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index c20a33fa37..5c08717ac9 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -1,5 +1,6 @@ #ifdef USE_HOST +#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -19,6 +20,7 @@ uint32_t IRAM_ATTR HOT millis() { uint32_t ms = round(spec.tv_nsec / 1e6); return ((uint32_t) seconds) * 1000U + ms; } +uint64_t millis_64() { return App.scheduler.millis_64_impl_(millis()); } void HOT delay(uint32_t ms) { struct timespec ts; ts.tv_sec = ms / 1000; diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 4dda7c3856..6cbc81938d 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -3,6 +3,7 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" +#include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -13,6 +14,7 @@ namespace esphome { void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } +uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void HOT delay(uint32_t ms) { ::delay(ms); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 37378d88bb..52c6f1185c 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -3,6 +3,7 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" +#include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "hardware/watchdog.h" @@ -11,6 +12,7 @@ namespace esphome { void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } +uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp b/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp index 20e8ed8fda..552e4e5da4 100644 --- a/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp +++ b/esphome/components/uptime/sensor/uptime_seconds_sensor.cpp @@ -1,6 +1,6 @@ #include "uptime_seconds_sensor.h" -#include "esphome/core/application.h" +#include "esphome/core/hal.h" #include "esphome/core/log.h" namespace esphome::uptime { @@ -8,7 +8,7 @@ namespace esphome::uptime { static const char *const TAG = "uptime.sensor"; void UptimeSecondsSensor::update() { - const uint64_t uptime = App.scheduler.millis_64(); + const uint64_t uptime = millis_64(); const uint64_t seconds_int = uptime / 1000ULL; const float seconds = float(seconds_int) + (uptime % 1000ULL) / 1000.0f; this->publish_state(seconds); diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index 88ae53fbfc..c89d23672e 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -1,6 +1,6 @@ #include "uptime_text_sensor.h" -#include "esphome/core/application.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -19,7 +19,7 @@ static void append_unit(char *buf, size_t buf_size, size_t &pos, const char *sep void UptimeTextSensor::setup() { this->update(); } void UptimeTextSensor::update() { - uint32_t uptime = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); + uint32_t uptime = static_cast<uint32_t>(millis_64() / 1000); unsigned interval = this->get_update_interval() / 1000; // Calculate all time units diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index e2f9c21331..16674321c9 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -385,7 +385,7 @@ json::SerializationBuffer<> WebServer::get_config_json() { #endif root[ESPHOME_F("log")] = this->expose_log_; root[ESPHOME_F("lang")] = "en"; - root[ESPHOME_F("uptime")] = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); + root[ESPHOME_F("uptime")] = static_cast<uint32_t>(millis_64() / 1000); return builder.serialize(); } @@ -414,7 +414,7 @@ void WebServer::setup() { // getting a lot of events this->set_interval(10000, [this]() { char buf[32]; - auto uptime = static_cast<uint32_t>(App.scheduler.millis_64() / 1000); + auto uptime = static_cast<uint32_t>(millis_64() / 1000); buf_append_printf(buf, sizeof(buf), 0, "{\"uptime\":%u}", uptime); this->events_.try_send_nodefer(buf, "ping", millis(), 30000); }); diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index d7027b33f5..7f5d6d44fa 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -4,6 +4,7 @@ #include <zephyr/drivers/watchdog.h> #include <zephyr/sys/reboot.h> #include <zephyr/random/random.h> +#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/defines.h" @@ -17,6 +18,7 @@ static const device *const WDT = DEVICE_DT_GET(DT_ALIAS(watchdog0)); void yield() { ::k_yield(); } uint32_t millis() { return k_ticks_to_ms_floor32(k_uptime_ticks()); } +uint64_t millis_64() { return App.scheduler.millis_64_impl_(millis()); } uint32_t micros() { return k_ticks_to_us_floor32(k_uptime_ticks()); } void delayMicroseconds(uint32_t us) { ::k_usleep(us); } void delay(uint32_t ms) { ::k_msleep(ms); } diff --git a/esphome/core/hal.h b/esphome/core/hal.h index 1a4230e421..fa5ca646f2 100644 --- a/esphome/core/hal.h +++ b/esphome/core/hal.h @@ -32,6 +32,7 @@ namespace esphome { void yield(); uint32_t millis(); +uint64_t millis_64(); uint32_t micros(); void delay(uint32_t ms); void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index d9c66b2000..06c0bb8b1b 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -28,8 +28,10 @@ static constexpr size_t MAX_POOL_SIZE = 5; // Set to 5 to match the pool size - when we have as many cancelled items as our // pool can hold, it's time to clean up and recycle them. static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; +#ifndef USE_ESP32 // Half the 32-bit range - used to detect rollovers vs normal time progression static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; +#endif // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; @@ -150,8 +152,8 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type return; } - // Get fresh timestamp BEFORE taking lock - millis_64_ may need to acquire lock itself - const uint64_t now = this->millis_64_(millis()); + // Get fresh 64-bit timestamp BEFORE taking lock + const uint64_t now_64 = millis_64(); // Take lock early to protect scheduler_item_pool_ access LockGuard guard{this->lock_}; @@ -184,7 +186,7 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type item->interval = delay; // first execution happens immediately after a random smallish offset uint32_t offset = this->calculate_interval_offset_(delay); - item->set_next_execution(now + offset); + item->set_next_execution(now_64 + offset); #ifdef ESPHOME_LOG_HAS_VERBOSE SchedulerNameLog name_log; ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", @@ -192,11 +194,11 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type #endif } else { item->interval = 0; - item->set_next_execution(now + delay); + item->set_next_execution(now_64 + delay); } #ifdef ESPHOME_DEBUG_SCHEDULER - this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now); + this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now_64); #endif /* ESPHOME_DEBUG_SCHEDULER */ // For retries, check if there's a cancelled timeout first @@ -399,8 +401,7 @@ optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) { return {}; auto &item = this->items_[0]; - // Convert the fresh timestamp from caller (usually Application::loop()) to 64-bit - const auto now_64 = this->millis_64_(now); // 'now' from parameter - fresh from caller + const auto now_64 = this->millis_64_from_(now); const uint64_t next_exec = item->get_next_execution(); if (next_exec < now_64) return 0; @@ -461,8 +462,8 @@ void HOT Scheduler::call(uint32_t now) { this->process_defer_queue_(now); #endif /* not ESPHOME_THREAD_SINGLE */ - // Convert the fresh timestamp from main loop to 64-bit for scheduler operations - const auto now_64 = this->millis_64_(now); // 'now' from parameter - fresh from Application::loop() + // Extend the caller's 32-bit timestamp to 64-bit for scheduler operations + const auto now_64 = this->millis_64_from_(now); this->process_to_add(); // Track if any items were added to to_add_ during this call (intervals or from callbacks) @@ -474,15 +475,18 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector<SchedulerItemPtr> old_items; -#ifdef ESPHOME_THREAD_MULTI_ATOMICS +#if !defined(USE_ESP32) && defined(ESPHOME_THREAD_MULTI_ATOMICS) const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg); -#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ +#elif !defined(USE_ESP32) ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_); -#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ +#else + ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64, this->items_.size(), this->scheduler_item_pool_.size(), + now_64); +#endif // Cleanup before debug output this->cleanup_(); while (!this->items_.empty()) { @@ -710,9 +714,8 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -uint64_t Scheduler::millis_64() { return this->millis_64_(millis()); } - -uint64_t Scheduler::millis_64_(uint32_t now) { +#ifndef USE_ESP32 +uint64_t Scheduler::millis_64_impl_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags // - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, RP2040, etc.) @@ -869,6 +872,7 @@ uint64_t Scheduler::millis_64_(uint32_t now) { "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." #endif } +#endif // not USE_ESP32 bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 840ee7159a..c605325810 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -10,6 +10,7 @@ #endif #include "esphome/core/component.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" namespace esphome { @@ -117,12 +118,12 @@ class Scheduler { bool cancel_retry(Component *component, uint32_t id); /// Get 64-bit millisecond timestamp (handles 32-bit millis() rollover) - uint64_t millis_64(); + uint64_t millis_64() { return esphome::millis_64(); } - // Calculate when the next scheduled item should run - // @param now Fresh timestamp from millis() - must not be stale/cached - // Returns the time in milliseconds until the next scheduled item, or nullopt if no items - // This method performs cleanup of removed items before checking the schedule + // Calculate when the next scheduled item should run. + // @param now On ESP32, unused for 64-bit extension (native); on other platforms, extended to 64-bit via rollover. + // Returns the time in milliseconds until the next scheduled item, or nullopt if no items. + // This method performs cleanup of removed items before checking the schedule. // IMPORTANT: This method should only be called from the main thread (loop task). optional<uint32_t> next_schedule_in(uint32_t now); @@ -282,7 +283,25 @@ class Scheduler { // Common implementation for cancel_retry bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); - uint64_t millis_64_(uint32_t now); + // Extend a 32-bit millis() value to 64-bit. Use when the caller already has a fresh now. + // On ESP32, ignores now and uses esp_timer_get_time() directly (native 64-bit). + // On non-ESP32, extends now to 64-bit using rollover tracking. + uint64_t millis_64_from_(uint32_t now) { +#ifdef USE_ESP32 + (void) now; + return millis_64(); +#else + return this->millis_64_impl_(now); +#endif + } + +#ifndef USE_ESP32 + // On non-ESP32 platforms, millis_64() HAL function delegates to this method + // which tracks 32-bit millis() rollover using millis_major_ and last_millis_. + // On ESP32, millis_64() uses esp_timer_get_time() directly. + friend uint64_t millis_64(); + uint64_t millis_64_impl_(uint32_t now); +#endif // Cleanup logically deleted items from the scheduler // Returns the number of items remaining after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). @@ -549,6 +568,9 @@ class Scheduler { // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) std::vector<SchedulerItemPtr> scheduler_item_pool_; +#ifndef USE_ESP32 + // On ESP32, millis_64() uses esp_timer_get_time() directly; no rollover tracking needed. + // On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_(). #ifdef ESPHOME_THREAD_MULTI_ATOMICS /* * Multi-threaded platforms with atomic support: last_millis_ needs atomic for lock-free updates @@ -577,6 +599,7 @@ class Scheduler { #else /* not ESPHOME_THREAD_MULTI_ATOMICS */ uint16_t millis_major_{0}; #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ +#endif /* not USE_ESP32 */ }; } // namespace esphome From 4fe173b64487b90d17fbca26727e0ad19bdd0d20 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 10:56:57 -0700 Subject: [PATCH 0987/2030] [wifi] Remove stale TODO comment for ESP8266 callback deferral (#14347) --- esphome/components/wifi/wifi_component_esp8266.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index cbf7d7d80f..8911bf15e0 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -470,10 +470,6 @@ const LogString *get_disconnect_reason_str(uint8_t reason) { return LOG_STR("Unspecified"); } -// TODO: This callback runs in ESP8266 system context with limited stack (~2KB). -// All listener notifications should be deferred to wifi_loop_() via pending_ flags -// to avoid stack overflow. Currently only connect_state is deferred; disconnect, -// IP, and scan listeners still run in this context and should be migrated. void WiFiComponent::wifi_event_callback(System_Event_t *event) { switch (event->event) { case EVENT_STAMODE_CONNECTED: { From c3a0eeceec21b6f7e97a2044078c611c843679e2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 11:17:17 -0700 Subject: [PATCH 0988/2030] [wifi] Use direct SDK APIs for LibreTiny SSID retrieval (#14349) --- .../wifi/wifi_component_libretiny.cpp | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 2cc05928af..1c5490a3ac 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -13,6 +13,19 @@ #include <FreeRTOS.h> #include <queue.h> +#ifdef USE_BK72XX +extern "C" { +#include <wlan_ui_pub.h> +} +#endif + +#ifdef USE_RTL87XX +extern "C" { +#include <wifi_conf.h> +#include <wifi_structures.h> +} +#endif + #include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -760,10 +773,22 @@ bssid_t WiFiComponent::wifi_bssid() { } std::string WiFiComponent::wifi_ssid() { return WiFi.SSID().c_str(); } const char *WiFiComponent::wifi_ssid_to(std::span<char, SSID_BUFFER_SIZE> buffer) { - // TODO: Find direct LibreTiny API to avoid Arduino String allocation +#ifdef USE_BK72XX + LinkStatusTypeDef link_status{}; + bk_wlan_get_link_status(&link_status); + size_t len = strnlen(reinterpret_cast<const char *>(link_status.ssid), SSID_BUFFER_SIZE - 1); + memcpy(buffer.data(), link_status.ssid, len); +#elif defined(USE_RTL87XX) + rtw_wifi_setting_t setting{}; + wifi_get_setting("wlan0", &setting); + size_t len = strnlen(reinterpret_cast<const char *>(setting.ssid), SSID_BUFFER_SIZE - 1); + memcpy(buffer.data(), setting.ssid, len); +#else + // LN882X: wifi_get_sta_conn_info() provides direct pointer access String ssid = WiFi.SSID(); size_t len = std::min(static_cast<size_t>(ssid.length()), SSID_BUFFER_SIZE - 1); memcpy(buffer.data(), ssid.c_str(), len); +#endif buffer[len] = '\0'; return buffer.data(); } From 4ae7633418716d4f606e189ad1eb532d7ec00cb5 Mon Sep 17 00:00:00 2001 From: Michael Cassaniti <mcassaniti@users.noreply.github.com> Date: Sat, 28 Feb 2026 05:23:02 +1100 Subject: [PATCH 0989/2030] [safe_mode] Add feature to explicitly mark a boot as successful (#14306) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/safe_mode/__init__.py | 17 ++++++++++++++++ esphome/components/safe_mode/automation.h | 14 +++++++------ esphome/components/safe_mode/safe_mode.cpp | 20 +++++++++++-------- esphome/components/safe_mode/safe_mode.h | 2 ++ .../components/safe_mode/common-enabled.yaml | 4 ++++ 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index d1754aaad7..f54151b746 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -21,6 +21,7 @@ CONF_ON_SAFE_MODE = "on_safe_mode" safe_mode_ns = cg.esphome_ns.namespace("safe_mode") SafeModeComponent = safe_mode_ns.class_("SafeModeComponent", cg.Component) SafeModeTrigger = safe_mode_ns.class_("SafeModeTrigger", automation.Trigger.template()) +MarkSuccessfulAction = safe_mode_ns.class_("MarkSuccessfulAction", automation.Action) def _remove_id_if_disabled(value): @@ -53,6 +54,22 @@ CONFIG_SCHEMA = cv.All( ) +@automation.register_action( + "safe_mode.mark_successful", + MarkSuccessfulAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(SafeModeComponent), + } + ), +) +async def safe_mode_mark_successful_to_code(config, action_id, template_arg, args): + parent = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg) + cg.add(var.set_parent(parent)) + return var + + @coroutine_with_priority(CoroPriority.APPLICATION) async def to_code(config): if not config[CONF_DISABLED]: diff --git a/esphome/components/safe_mode/automation.h b/esphome/components/safe_mode/automation.h index 1d82ac45f1..dee02c64a0 100644 --- a/esphome/components/safe_mode/automation.h +++ b/esphome/components/safe_mode/automation.h @@ -1,20 +1,22 @@ #pragma once #include "esphome/core/defines.h" - -#ifdef USE_SAFE_MODE_CALLBACK -#include "safe_mode.h" - #include "esphome/core/automation.h" +#include "safe_mode.h" namespace esphome::safe_mode { +#ifdef USE_SAFE_MODE_CALLBACK class SafeModeTrigger final : public Trigger<> { public: explicit SafeModeTrigger(SafeModeComponent *parent) { parent->add_on_safe_mode_callback([this]() { trigger(); }); } }; +#endif // USE_SAFE_MODE_CALLBACK + +template<typename... Ts> class MarkSuccessfulAction : public Action<Ts...>, public Parented<SafeModeComponent> { + public: + void play(const Ts &...x) override { this->parent_->mark_successful(); } +}; } // namespace esphome::safe_mode - -#endif // USE_SAFE_MODE_CALLBACK diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index aa4fdb8291..fe2acd9612 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -63,18 +63,22 @@ void SafeModeComponent::dump_config() { float SafeModeComponent::get_setup_priority() const { return setup_priority::AFTER_WIFI; } +void SafeModeComponent::mark_successful() { + this->clean_rtc(); + this->boot_successful_ = true; +#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) + // Mark OTA partition as valid to prevent rollback + esp_ota_mark_app_valid_cancel_rollback(); +#endif + // Disable loop since we no longer need to check + this->disable_loop(); +} + void SafeModeComponent::loop() { if (!this->boot_successful_ && (millis() - this->safe_mode_start_time_) > this->safe_mode_boot_is_good_after_) { // successful boot, reset counter ESP_LOGI(TAG, "Boot seems successful; resetting boot loop counter"); - this->clean_rtc(); - this->boot_successful_ = true; -#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) - // Mark OTA partition as valid to prevent rollback - esp_ota_mark_app_valid_cancel_rollback(); -#endif - // Disable loop since we no longer need to check - this->disable_loop(); + this->mark_successful(); } } diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 902b8c415d..1b28ea28f2 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -31,6 +31,8 @@ class SafeModeComponent final : public Component { void on_safe_shutdown() override; + void mark_successful(); + #ifdef USE_SAFE_MODE_CALLBACK void add_on_safe_mode_callback(std::function<void()> &&callback) { this->safe_mode_callback_.add(std::move(callback)); diff --git a/tests/components/safe_mode/common-enabled.yaml b/tests/components/safe_mode/common-enabled.yaml index c24f49e6b6..43025c60db 100644 --- a/tests/components/safe_mode/common-enabled.yaml +++ b/tests/components/safe_mode/common-enabled.yaml @@ -16,3 +16,7 @@ button: switch: - platform: safe_mode name: Safe Mode Switch + +esphome: + on_boot: + - safe_mode.mark_successful From 317dd5b2da73d39839695abb066cb976443dba05 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 11:42:08 -0700 Subject: [PATCH 0990/2030] [ci] Skip memory impact target branch build when tests don't exist (#14316) --- .github/workflows/ci.yml | 49 ++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c2a93d37fd..b752701920 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -686,7 +686,7 @@ jobs: ram_usage: ${{ steps.extract.outputs.ram_usage }} flash_usage: ${{ steps.extract.outputs.flash_usage }} cache_hit: ${{ steps.cache-memory-analysis.outputs.cache-hit }} - skip: ${{ steps.check-script.outputs.skip }} + skip: ${{ steps.check-script.outputs.skip || steps.check-tests.outputs.skip }} steps: - name: Check out target branch uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -705,10 +705,39 @@ jobs: echo "::warning::ci_memory_impact_extract.py not found on target branch, skipping memory impact analysis" fi - # All remaining steps only run if script exists + # Check if test files exist on the target branch for the requested + # components and platform. When a PR adds new test files for a platform, + # the target branch won't have them yet, so skip instead of failing. + # This check must be done here (not in determine-jobs.py) because + # determine-jobs runs on the PR branch and cannot see what the target + # branch has. + - name: Check for test files on target branch + id: check-tests + if: steps.check-script.outputs.skip != 'true' + run: | + components='${{ toJSON(fromJSON(needs.determine-jobs.outputs.memory_impact).components) }}' + platform="${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}" + found=false + for component in $(echo "$components" | jq -r '.[]'); do + # Check for test files matching the platform (test.platform.yaml or test-*.platform.yaml) + for f in tests/components/${component}/test*.${platform}.yaml; do + if [ -f "$f" ]; then + found=true + break 2 + fi + done + done + if [ "$found" = false ]; then + echo "skip=true" >> $GITHUB_OUTPUT + echo "::warning::No test files found on target branch for platform ${platform}, skipping memory impact analysis" + else + echo "skip=false" >> $GITHUB_OUTPUT + fi + + # All remaining steps only run if script and tests exist - name: Generate cache key id: cache-key - if: steps.check-script.outputs.skip != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' run: | # Get the commit SHA of the target branch target_sha=$(git rev-parse HEAD) @@ -735,14 +764,14 @@ jobs: - name: Restore cached memory analysis id: cache-memory-analysis - if: steps.check-script.outputs.skip != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} - name: Cache status - if: steps.check-script.outputs.skip != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' run: | if [ "${{ steps.cache-memory-analysis.outputs.cache-hit }}" == "true" ]; then echo "✓ Cache hit! Using cached memory analysis results." @@ -752,21 +781,21 @@ jobs: fi - name: Restore Python - if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' uses: ./.github/actions/restore-python with: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} - name: Build, compile, and analyze memory - if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' id: build run: | . venv/bin/activate @@ -800,7 +829,7 @@ jobs: --platform "$platform" - name: Save memory analysis to cache - if: steps.check-script.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success' uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 with: path: memory-analysis-target.json @@ -808,7 +837,7 @@ jobs: - name: Extract memory usage for outputs id: extract - if: steps.check-script.outputs.skip != 'true' + if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' run: | if [ -f memory-analysis-target.json ]; then ram=$(jq -r '.ram_bytes' memory-analysis-target.json) From 29e1e8bdfd9ce8068cb97f8e0b1c8e8f64af50c4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 11:45:20 -0700 Subject: [PATCH 0991/2030] [wifi] Add LibreTiny component test configs (#14351) --- tests/components/wifi/test.bk72xx-ard.yaml | 1 + tests/components/wifi/test.ln882x-ard.yaml | 1 + tests/components/wifi/test.rtl87xx-ard.yaml | 1 + 3 files changed, 3 insertions(+) create mode 100644 tests/components/wifi/test.bk72xx-ard.yaml create mode 100644 tests/components/wifi/test.ln882x-ard.yaml create mode 100644 tests/components/wifi/test.rtl87xx-ard.yaml diff --git a/tests/components/wifi/test.bk72xx-ard.yaml b/tests/components/wifi/test.bk72xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/wifi/test.bk72xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/wifi/test.ln882x-ard.yaml b/tests/components/wifi/test.ln882x-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/wifi/test.ln882x-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/wifi/test.rtl87xx-ard.yaml b/tests/components/wifi/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/wifi/test.rtl87xx-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 3411ce21505cd8fdcf74885199ba7627f5ac105b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 11:49:57 -0700 Subject: [PATCH 0992/2030] [core] Fix Application asm label for Mach-O using __USER_LABEL_PREFIX__ (#14334) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/core/application.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 3bd4c1c670..e27c2cdfc6 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -727,8 +727,17 @@ void Application::yield_with_select_(uint32_t delay_ms) { #error "Application placement new requires Itanium C++ ABI (GCC/Clang)" #endif static_assert(std::is_default_constructible<Application>::value, "Application must be default-constructible"); +// __USER_LABEL_PREFIX__ is "_" on Mach-O (macOS) and empty on ELF (embedded targets). +// String literal concatenation produces the correct platform-specific mangled symbol. +// Two-level macro needed: # stringifies before expansion, so the +// indirection forces __USER_LABEL_PREFIX__ to expand first. +#define ESPHOME_STRINGIFY_IMPL_(x) #x +#define ESPHOME_STRINGIFY_(x) ESPHOME_STRINGIFY_IMPL_(x) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -alignas(Application) char app_storage[sizeof(Application)] asm("_ZN7esphome3AppE"); +alignas(Application) char app_storage[sizeof(Application)] asm( + ESPHOME_STRINGIFY_(__USER_LABEL_PREFIX__) "_ZN7esphome3AppE"); +#undef ESPHOME_STRINGIFY_ +#undef ESPHOME_STRINGIFY_IMPL_ #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) From 8698b01bc7314443867327e11f8431a7f14bf7e7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 11:54:13 -0700 Subject: [PATCH 0993/2030] [host] Use native clock_gettime for millis_64() (#14340) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/host/core.cpp | 6 +++++- esphome/core/scheduler.cpp | 10 +++++----- esphome/core/scheduler.h | 15 +++++++-------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index 5c08717ac9..9af85bec58 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -20,7 +20,11 @@ uint32_t IRAM_ATTR HOT millis() { uint32_t ms = round(spec.tv_nsec / 1e6); return ((uint32_t) seconds) * 1000U + ms; } -uint64_t millis_64() { return App.scheduler.millis_64_impl_(millis()); } +uint64_t millis_64() { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + return static_cast<uint64_t>(spec.tv_sec) * 1000ULL + static_cast<uint64_t>(spec.tv_nsec) / 1000000ULL; +} void HOT delay(uint32_t ms) { struct timespec ts; ts.tv_sec = ms / 1000; diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 06c0bb8b1b..97735c4876 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -28,7 +28,7 @@ static constexpr size_t MAX_POOL_SIZE = 5; // Set to 5 to match the pool size - when we have as many cancelled items as our // pool can hold, it's time to clean up and recycle them. static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; -#ifndef USE_ESP32 +#if !defined(USE_ESP32) && !defined(USE_HOST) // Half the 32-bit range - used to detect rollovers vs normal time progression static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; #endif @@ -475,12 +475,12 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector<SchedulerItemPtr> old_items; -#if !defined(USE_ESP32) && defined(ESPHOME_THREAD_MULTI_ATOMICS) +#if !defined(USE_ESP32) && !defined(USE_HOST) && defined(ESPHOME_THREAD_MULTI_ATOMICS) const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg); -#elif !defined(USE_ESP32) +#elif !defined(USE_ESP32) && !defined(USE_HOST) ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_); #else @@ -714,7 +714,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -#ifndef USE_ESP32 +#if !defined(USE_ESP32) && !defined(USE_HOST) uint64_t Scheduler::millis_64_impl_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags @@ -872,7 +872,7 @@ uint64_t Scheduler::millis_64_impl_(uint32_t now) { "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." #endif } -#endif // not USE_ESP32 +#endif // !USE_ESP32 && !USE_HOST bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index c605325810..9a62ac1634 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -287,7 +287,7 @@ class Scheduler { // On ESP32, ignores now and uses esp_timer_get_time() directly (native 64-bit). // On non-ESP32, extends now to 64-bit using rollover tracking. uint64_t millis_64_from_(uint32_t now) { -#ifdef USE_ESP32 +#if defined(USE_ESP32) || defined(USE_HOST) (void) now; return millis_64(); #else @@ -295,10 +295,9 @@ class Scheduler { #endif } -#ifndef USE_ESP32 - // On non-ESP32 platforms, millis_64() HAL function delegates to this method - // which tracks 32-bit millis() rollover using millis_major_ and last_millis_. - // On ESP32, millis_64() uses esp_timer_get_time() directly. +#if !defined(USE_ESP32) && !defined(USE_HOST) + // On platforms without native 64-bit time, millis_64() HAL function delegates to this + // method which tracks 32-bit millis() rollover using millis_major_ and last_millis_. friend uint64_t millis_64(); uint64_t millis_64_impl_(uint32_t now); #endif @@ -568,8 +567,8 @@ class Scheduler { // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) std::vector<SchedulerItemPtr> scheduler_item_pool_; -#ifndef USE_ESP32 - // On ESP32, millis_64() uses esp_timer_get_time() directly; no rollover tracking needed. +#if !defined(USE_ESP32) && !defined(USE_HOST) + // On platforms with native 64-bit time (ESP32, Host), no rollover tracking needed. // On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_(). #ifdef ESPHOME_THREAD_MULTI_ATOMICS /* @@ -599,7 +598,7 @@ class Scheduler { #else /* not ESPHOME_THREAD_MULTI_ATOMICS */ uint16_t millis_major_{0}; #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ -#endif /* not USE_ESP32 */ +#endif /* !USE_ESP32 && !USE_HOST */ }; } // namespace esphome From 9c1d1a0d9fba57b92e083437d422a3e7ca3137ad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 12:25:13 -0700 Subject: [PATCH 0994/2030] [color] Use integer math in Color::gradient to reduce code size (#14354) --- esphome/core/color.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/core/color.cpp b/esphome/core/color.cpp index 14c41c2b0d..edbc771472 100644 --- a/esphome/core/color.cpp +++ b/esphome/core/color.cpp @@ -7,12 +7,12 @@ constinit const Color Color::BLACK(0, 0, 0, 0); constinit const Color Color::WHITE(255, 255, 255, 255); Color Color::gradient(const Color &to_color, uint8_t amnt) { + uint8_t inv = 255 - amnt; Color new_color; - float amnt_f = float(amnt) / 255.0f; - new_color.r = amnt_f * (to_color.r - this->r) + this->r; - new_color.g = amnt_f * (to_color.g - this->g) + this->g; - new_color.b = amnt_f * (to_color.b - this->b) + this->b; - new_color.w = amnt_f * (to_color.w - this->w) + this->w; + new_color.r = (uint16_t(this->r) * inv + uint16_t(to_color.r) * amnt) / 255; + new_color.g = (uint16_t(this->g) * inv + uint16_t(to_color.g) * amnt) / 255; + new_color.b = (uint16_t(this->b) * inv + uint16_t(to_color.b) * amnt) / 255; + new_color.w = (uint16_t(this->w) * inv + uint16_t(to_color.w) * amnt) / 255; return new_color; } From 2255c68377304c81ab75da9fda8b79cbcf5c756c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 28 Feb 2026 06:40:55 +1100 Subject: [PATCH 0995/2030] [esp32] Enable `execute_from_psram` for P4 (#14329) --- esphome/components/esp32/__init__.py | 13 +++-- .../config/execute_from_psram_disabled.yaml | 10 ++++ .../esp32/config/execute_from_psram_p4.yaml | 11 ++++ .../esp32/config/execute_from_psram_s3.yaml | 12 ++++ tests/component_tests/esp32/test_esp32.py | 55 ++++++++++++++++++- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 tests/component_tests/esp32/config/execute_from_psram_disabled.yaml create mode 100644 tests/component_tests/esp32/config/execute_from_psram_p4.yaml create mode 100644 tests/component_tests/esp32/config/execute_from_psram_s3.yaml diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index a34747a183..998913ecec 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -890,10 +890,10 @@ def final_validate(config): ) ) if advanced[CONF_EXECUTE_FROM_PSRAM]: - if config[CONF_VARIANT] != VARIANT_ESP32S3: + if config[CONF_VARIANT] not in {VARIANT_ESP32S3, VARIANT_ESP32P4}: errs.append( cv.Invalid( - f"'{CONF_EXECUTE_FROM_PSRAM}' is only supported on {VARIANT_ESP32S3} variant", + f"'{CONF_EXECUTE_FROM_PSRAM}' is not available on this esp32 variant", path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_EXECUTE_FROM_PSRAM], ) ) @@ -1627,8 +1627,13 @@ async def to_code(config): _configure_lwip_max_sockets(conf) if advanced[CONF_EXECUTE_FROM_PSRAM]: - add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True) - add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) + if variant == VARIANT_ESP32S3: + add_idf_sdkconfig_option("CONFIG_SPIRAM_FETCH_INSTRUCTIONS", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_RODATA", True) + elif variant == VARIANT_ESP32P4: + add_idf_sdkconfig_option("CONFIG_SPIRAM_XIP_FROM_PSRAM", True) + else: + raise ValueError("Unhandled ESP32 variant") # Apply LWIP core locking for better socket performance # This is already enabled by default in Arduino framework, where it provides diff --git a/tests/component_tests/esp32/config/execute_from_psram_disabled.yaml b/tests/component_tests/esp32/config/execute_from_psram_disabled.yaml new file mode 100644 index 0000000000..b52255c5ad --- /dev/null +++ b/tests/component_tests/esp32/config/execute_from_psram_disabled.yaml @@ -0,0 +1,10 @@ +esphome: + name: test + +esp32: + variant: esp32s3 + framework: + type: esp-idf + +psram: + mode: octal diff --git a/tests/component_tests/esp32/config/execute_from_psram_p4.yaml b/tests/component_tests/esp32/config/execute_from_psram_p4.yaml new file mode 100644 index 0000000000..e9070a5ae1 --- /dev/null +++ b/tests/component_tests/esp32/config/execute_from_psram_p4.yaml @@ -0,0 +1,11 @@ +esphome: + name: test + +esp32: + variant: esp32p4 + framework: + type: esp-idf + advanced: + execute_from_psram: true + +psram: diff --git a/tests/component_tests/esp32/config/execute_from_psram_s3.yaml b/tests/component_tests/esp32/config/execute_from_psram_s3.yaml new file mode 100644 index 0000000000..aec020ddff --- /dev/null +++ b/tests/component_tests/esp32/config/execute_from_psram_s3.yaml @@ -0,0 +1,12 @@ +esphome: + name: test + +esp32: + variant: esp32s3 + framework: + type: esp-idf + advanced: + execute_from_psram: true + +psram: + mode: octal diff --git a/tests/component_tests/esp32/test_esp32.py b/tests/component_tests/esp32/test_esp32.py index 68bd3a5965..bd4f9828ce 100644 --- a/tests/component_tests/esp32/test_esp32.py +++ b/tests/component_tests/esp32/test_esp32.py @@ -2,13 +2,17 @@ Test ESP32 configuration """ +from collections.abc import Callable +from pathlib import Path from typing import Any import pytest from esphome.components.esp32 import VARIANTS +from esphome.components.esp32.const import KEY_ESP32, KEY_SDKCONFIG_OPTIONS import esphome.config_validation as cv from esphome.const import CONF_ESPHOME, PlatformFramework +from esphome.core import CORE from tests.component_tests.types import SetCoreConfigCallable @@ -70,7 +74,7 @@ def test_esp32_config( "advanced": {"execute_from_psram": True}, }, }, - r"'execute_from_psram' is only supported on ESP32S3 variant @ data\['framework'\]\['advanced'\]\['execute_from_psram'\]", + r"'execute_from_psram' is not available on this esp32 variant @ data\['framework'\]\['advanced'\]\['execute_from_psram'\]", id="execute_from_psram_invalid_for_variant_config", ), pytest.param( @@ -82,7 +86,18 @@ def test_esp32_config( }, }, r"'execute_from_psram' requires PSRAM to be configured @ data\['framework'\]\['advanced'\]\['execute_from_psram'\]", - id="execute_from_psram_requires_psram_config", + id="execute_from_psram_requires_psram_s3_config", + ), + pytest.param( + { + "variant": "esp32p4", + "framework": { + "type": "esp-idf", + "advanced": {"execute_from_psram": True}, + }, + }, + r"'execute_from_psram' requires PSRAM to be configured @ data\['framework'\]\['advanced'\]\['execute_from_psram'\]", + id="execute_from_psram_requires_psram_p4_config", ), pytest.param( { @@ -108,3 +123,39 @@ def test_esp32_configuration_errors( with pytest.raises(cv.Invalid, match=error_match): FINAL_VALIDATE_SCHEMA(CONFIG_SCHEMA(config)) + + +def test_execute_from_psram_s3_sdkconfig( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that execute_from_psram on ESP32-S3 sets the correct sdkconfig options.""" + generate_main(component_config_path("execute_from_psram_s3.yaml")) + sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] + assert sdkconfig.get("CONFIG_SPIRAM_FETCH_INSTRUCTIONS") is True + assert sdkconfig.get("CONFIG_SPIRAM_RODATA") is True + assert "CONFIG_SPIRAM_XIP_FROM_PSRAM" not in sdkconfig + + +def test_execute_from_psram_p4_sdkconfig( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that execute_from_psram on ESP32-P4 sets the correct sdkconfig options.""" + generate_main(component_config_path("execute_from_psram_p4.yaml")) + sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] + assert sdkconfig.get("CONFIG_SPIRAM_XIP_FROM_PSRAM") is True + assert "CONFIG_SPIRAM_FETCH_INSTRUCTIONS" not in sdkconfig + assert "CONFIG_SPIRAM_RODATA" not in sdkconfig + + +def test_execute_from_psram_disabled_sdkconfig( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that without execute_from_psram, no XIP sdkconfig options are set.""" + generate_main(component_config_path("execute_from_psram_disabled.yaml")) + sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS] + assert "CONFIG_SPIRAM_FETCH_INSTRUCTIONS" not in sdkconfig + assert "CONFIG_SPIRAM_RODATA" not in sdkconfig + assert "CONFIG_SPIRAM_XIP_FROM_PSRAM" not in sdkconfig From 32133e2f464ec93c968d44cf97e9e689ac81f1ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:42:20 -0500 Subject: [PATCH 0996/2030] Bump ruff from 0.15.3 to 0.15.4 (#14357) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 88a38ffa99..6b2617b656 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.3 # also change in .pre-commit-config.yaml when updating +ruff==0.15.4 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From edd63e3d2d82bfc6585c391ebdae25b0313c91e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 14:43:10 -0500 Subject: [PATCH 0997/2030] Bump actions/download-artifact from 7.0.0 to 8.0.0 (#14327) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b752701920..4c9e8c58bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -945,13 +945,13 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Download target analysis JSON - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: memory-analysis-target path: ./memory-analysis continue-on-error: true - name: Download PR analysis JSON - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: memory-analysis-pr path: ./memory-analysis diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0cca4dcaf6..17a2616dff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -171,7 +171,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download digests - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: pattern: digests-* path: /tmp/digests From 63e757807ee2a522f493bc65dd38ced7f3d601dc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 13:01:09 -0700 Subject: [PATCH 0998/2030] [zephyr] Use native k_uptime_get() for millis_64() (#14350) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/zephyr/core.cpp | 5 ++--- esphome/core/scheduler.cpp | 10 +++++----- esphome/core/scheduler.h | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index 7f5d6d44fa..f0772a4422 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -4,7 +4,6 @@ #include <zephyr/drivers/watchdog.h> #include <zephyr/sys/reboot.h> #include <zephyr/random/random.h> -#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/defines.h" @@ -17,8 +16,8 @@ static const device *const WDT = DEVICE_DT_GET(DT_ALIAS(watchdog0)); #endif void yield() { ::k_yield(); } -uint32_t millis() { return k_ticks_to_ms_floor32(k_uptime_ticks()); } -uint64_t millis_64() { return App.scheduler.millis_64_impl_(millis()); } +uint32_t millis() { return static_cast<uint32_t>(millis_64()); } +uint64_t millis_64() { return static_cast<uint64_t>(k_uptime_get()); } uint32_t micros() { return k_ticks_to_us_floor32(k_uptime_ticks()); } void delayMicroseconds(uint32_t us) { ::k_usleep(us); } void delay(uint32_t ms) { ::k_msleep(ms); } diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 97735c4876..73b6a6c9b3 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -28,7 +28,7 @@ static constexpr size_t MAX_POOL_SIZE = 5; // Set to 5 to match the pool size - when we have as many cancelled items as our // pool can hold, it's time to clean up and recycle them. static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; -#if !defined(USE_ESP32) && !defined(USE_HOST) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) // Half the 32-bit range - used to detect rollovers vs normal time progression static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; #endif @@ -475,12 +475,12 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector<SchedulerItemPtr> old_items; -#if !defined(USE_ESP32) && !defined(USE_HOST) && defined(ESPHOME_THREAD_MULTI_ATOMICS) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && defined(ESPHOME_THREAD_MULTI_ATOMICS) const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg); -#elif !defined(USE_ESP32) && !defined(USE_HOST) +#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_); #else @@ -714,7 +714,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -#if !defined(USE_ESP32) && !defined(USE_HOST) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) uint64_t Scheduler::millis_64_impl_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags @@ -872,7 +872,7 @@ uint64_t Scheduler::millis_64_impl_(uint32_t now) { "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." #endif } -#endif // !USE_ESP32 && !USE_HOST +#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 9a62ac1634..282f4c66ef 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -287,7 +287,7 @@ class Scheduler { // On ESP32, ignores now and uses esp_timer_get_time() directly (native 64-bit). // On non-ESP32, extends now to 64-bit using rollover tracking. uint64_t millis_64_from_(uint32_t now) { -#if defined(USE_ESP32) || defined(USE_HOST) +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) (void) now; return millis_64(); #else @@ -295,7 +295,7 @@ class Scheduler { #endif } -#if !defined(USE_ESP32) && !defined(USE_HOST) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) // On platforms without native 64-bit time, millis_64() HAL function delegates to this // method which tracks 32-bit millis() rollover using millis_major_ and last_millis_. friend uint64_t millis_64(); @@ -567,8 +567,8 @@ class Scheduler { // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) std::vector<SchedulerItemPtr> scheduler_item_pool_; -#if !defined(USE_ESP32) && !defined(USE_HOST) - // On platforms with native 64-bit time (ESP32, Host), no rollover tracking needed. +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) + // On platforms with native 64-bit time (ESP32, Host, Zephyr), no rollover tracking needed. // On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_(). #ifdef ESPHOME_THREAD_MULTI_ATOMICS /* @@ -598,7 +598,7 @@ class Scheduler { #else /* not ESPHOME_THREAD_MULTI_ATOMICS */ uint16_t millis_major_{0}; #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ -#endif /* !USE_ESP32 && !USE_HOST */ +#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR */ }; } // namespace esphome From 52af4bced0fdbe0c89a21aa8bb826422467f1936 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 13:01:23 -0700 Subject: [PATCH 0999/2030] [component] Devirtualize call_dump_config (#14355) --- esphome/components/mqtt/mqtt_component.cpp | 6 ------ esphome/components/mqtt/mqtt_component.h | 2 -- esphome/core/application.cpp | 2 +- esphome/core/component.cpp | 2 +- esphome/core/component.h | 2 +- 5 files changed, 3 insertions(+), 11 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 09570106df..f49069960b 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -405,12 +405,6 @@ void MQTTComponent::process_resend() { this->schedule_resend_state(); } } -void MQTTComponent::call_dump_config() { - if (this->is_internal()) - return; - - this->dump_config(); -} void MQTTComponent::schedule_resend_state() { this->resend_state_ = true; } bool MQTTComponent::is_connected_() const { return global_mqtt_client->is_connected(); } diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 853712940a..0ffe6341d3 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -98,8 +98,6 @@ class MQTTComponent : public Component { /// Override setup_ so that we can call send_discovery() when needed. void call_setup() override; - void call_dump_config() override; - /// Send discovery info the Home Assistant, override this. virtual void send_discovery(JsonObject root, SendDiscoveryConfig &config) = 0; diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index e27c2cdfc6..b1ece86701 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -256,7 +256,7 @@ void Application::process_dump_config_() { #endif } - this->components_[this->dump_config_at_]->call_dump_config(); + this->components_[this->dump_config_at_]->call_dump_config_(); this->dump_config_at_++; } diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index b4a19a0776..e14fae5e08 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -211,7 +211,7 @@ bool Component::cancel_retry(uint32_t id) { void Component::call_loop_() { this->loop(); } void Component::call_setup() { this->setup(); } -void Component::call_dump_config() { +void Component::call_dump_config_() { this->dump_config(); if (this->is_failed()) { // Look up error message from global vector diff --git a/esphome/core/component.h b/esphome/core/component.h index 7ea9fdf3b3..2620e8eb2a 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -291,7 +291,7 @@ class Component { void call_loop_(); virtual void call_setup(); - virtual void call_dump_config(); + void call_dump_config_(); /// Helper to set component state (clears state bits and sets new state) void set_component_state_(uint8_t state); From f6755aabae2fad7ea5c082571502baf281c6d8b8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Feb 2026 15:18:07 -0500 Subject: [PATCH 1000/2030] [ci] Add PR title format check (#14345) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/scripts/auto-label-pr/detectors.js | 42 +++++------- .github/scripts/detect-tags.js | 66 +++++++++++++++++++ .github/workflows/pr-title-check.yml | 76 ++++++++++++++++++++++ 3 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 .github/scripts/detect-tags.js create mode 100644 .github/workflows/pr-title-check.yml diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index a45a84f219..80d8847bc1 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -1,5 +1,12 @@ const fs = require('fs'); const { DOCS_PR_PATTERNS } = require('./constants'); +const { + COMPONENT_REGEX, + detectComponents, + hasCoreChanges, + hasDashboardChanges, + hasGitHubActionsChanges, +} = require('../detect-tags'); // Strategy: Merge branch detection async function detectMergeBranch(context) { @@ -20,15 +27,13 @@ async function detectMergeBranch(context) { // Strategy: Component and platform labeling async function detectComponentPlatforms(changedFiles, apiData) { const labels = new Set(); - const componentRegex = /^esphome\/components\/([^\/]+)\//; const targetPlatformRegex = new RegExp(`^esphome\/components\/(${apiData.targetPlatforms.join('|')})/`); - for (const file of changedFiles) { - const componentMatch = file.match(componentRegex); - if (componentMatch) { - labels.add(`component: ${componentMatch[1]}`); - } + for (const comp of detectComponents(changedFiles)) { + labels.add(`component: ${comp}`); + } + for (const file of changedFiles) { const platformMatch = file.match(targetPlatformRegex); if (platformMatch) { labels.add(`platform: ${platformMatch[1]}`); @@ -90,15 +95,9 @@ async function detectNewPlatforms(prFiles, apiData) { // Strategy: Core files detection async function detectCoreChanges(changedFiles) { const labels = new Set(); - const coreFiles = changedFiles.filter(file => - file.startsWith('esphome/core/') || - (file.startsWith('esphome/') && file.split('/').length === 2) - ); - - if (coreFiles.length > 0) { + if (hasCoreChanges(changedFiles)) { labels.add('core'); } - return labels; } @@ -131,29 +130,18 @@ async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChange // Strategy: Dashboard changes async function detectDashboardChanges(changedFiles) { const labels = new Set(); - const dashboardFiles = changedFiles.filter(file => - file.startsWith('esphome/dashboard/') || - file.startsWith('esphome/components/dashboard_import/') - ); - - if (dashboardFiles.length > 0) { + if (hasDashboardChanges(changedFiles)) { labels.add('dashboard'); } - return labels; } // Strategy: GitHub Actions changes async function detectGitHubActionsChanges(changedFiles) { const labels = new Set(); - const githubActionsFiles = changedFiles.filter(file => - file.startsWith('.github/workflows/') - ); - - if (githubActionsFiles.length > 0) { + if (hasGitHubActionsChanges(changedFiles)) { labels.add('github-actions'); } - return labels; } @@ -259,7 +247,7 @@ async function detectDeprecatedComponents(github, context, changedFiles) { const { owner, repo } = context.repo; // Compile regex once for better performance - const componentFileRegex = /^esphome\/components\/([^\/]+)\//; + const componentFileRegex = COMPONENT_REGEX; // Get files that are modified or added in components directory const componentFiles = changedFiles.filter(file => componentFileRegex.test(file)); diff --git a/.github/scripts/detect-tags.js b/.github/scripts/detect-tags.js new file mode 100644 index 0000000000..3933776c61 --- /dev/null +++ b/.github/scripts/detect-tags.js @@ -0,0 +1,66 @@ +/** + * Shared tag detection from changed file paths. + * Used by pr-title-check and auto-label-pr workflows. + */ + +const COMPONENT_REGEX = /^esphome\/components\/([^\/]+)\//; + +/** + * Detect component names from changed files. + * @param {string[]} changedFiles - List of changed file paths + * @returns {Set<string>} Set of component names + */ +function detectComponents(changedFiles) { + const components = new Set(); + for (const file of changedFiles) { + const match = file.match(COMPONENT_REGEX); + if (match) { + components.add(match[1]); + } + } + return components; +} + +/** + * Detect if core files were changed. + * Core files are in esphome/core/ or top-level esphome/ directory. + * @param {string[]} changedFiles - List of changed file paths + * @returns {boolean} + */ +function hasCoreChanges(changedFiles) { + return changedFiles.some(file => + file.startsWith('esphome/core/') || + (file.startsWith('esphome/') && file.split('/').length === 2) + ); +} + +/** + * Detect if dashboard files were changed. + * @param {string[]} changedFiles - List of changed file paths + * @returns {boolean} + */ +function hasDashboardChanges(changedFiles) { + return changedFiles.some(file => + file.startsWith('esphome/dashboard/') || + file.startsWith('esphome/components/dashboard_import/') + ); +} + +/** + * Detect if GitHub Actions files were changed. + * @param {string[]} changedFiles - List of changed file paths + * @returns {boolean} + */ +function hasGitHubActionsChanges(changedFiles) { + return changedFiles.some(file => + file.startsWith('.github/workflows/') + ); +} + +module.exports = { + COMPONENT_REGEX, + detectComponents, + hasCoreChanges, + hasDashboardChanges, + hasGitHubActionsChanges, +}; diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml new file mode 100644 index 0000000000..f23c2c870e --- /dev/null +++ b/.github/workflows/pr-title-check.yml @@ -0,0 +1,76 @@ +name: PR Title Check + +on: + pull_request: + types: [opened, edited, synchronize, reopened] + +permissions: + contents: read + pull-requests: read + +jobs: + check: + name: Validate PR title + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { + detectComponents, + hasCoreChanges, + hasDashboardChanges, + hasGitHubActionsChanges, + } = require('./.github/scripts/detect-tags.js'); + + const title = context.payload.pull_request.title; + + // Block titles starting with "word:" or "word(scope):" patterns + const commitStylePattern = /^\w+(\(.*?\))?[!]?\s*:/; + if (commitStylePattern.test(title)) { + core.setFailed( + `PR title should not start with a "prefix:" style format.\n` + + `Please use the format: [component] Brief description\n` + + `Example: [pn532] Add health checking and auto-reset` + ); + return; + } + + // Get changed files to detect tags + const files = await github.paginate(github.rest.pulls.listFiles, { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.issue.number, + }); + const filenames = files.map(f => f.filename); + + // Detect tags from changed files using shared logic + const tags = new Set(); + + for (const comp of detectComponents(filenames)) { + tags.add(comp); + } + if (hasCoreChanges(filenames)) tags.add('core'); + if (hasDashboardChanges(filenames)) tags.add('dashboard'); + if (hasGitHubActionsChanges(filenames)) tags.add('ci'); + + if (tags.size === 0) { + return; + } + + // Check title starts with [tag] prefix + const bracketPattern = /^\[\w+\]/; + if (!bracketPattern.test(title)) { + const suggestion = [...tags].map(c => `[${c}]`).join(''); + // Skip if the suggested prefix would be too long for a readable title + if (suggestion.length > 40) { + return; + } + core.setFailed( + `PR modifies: ${[...tags].join(', ')}\n` + + `Title must start with a [tag] prefix.\n` + + `Suggested: ${suggestion} <description>` + ); + } From 280f874edc36ce5127d005a526c5f4537d453f70 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 14:18:02 -0700 Subject: [PATCH 1001/2030] [rp2040] Use native time_us_64() for millis_64() (#14356) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/rp2040/core.cpp | 12 ++++++------ esphome/core/scheduler.cpp | 11 ++++++----- esphome/core/scheduler.h | 14 +++++++------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 52c6f1185c..8b86de4be1 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -3,19 +3,19 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" -#include "esphome/core/application.h" #include "esphome/core/helpers.h" +#include "hardware/timer.h" #include "hardware/watchdog.h" namespace esphome { void HOT yield() { ::yield(); } -uint32_t IRAM_ATTR HOT millis() { return ::millis(); } -uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } +uint64_t millis_64() { return time_us_64() / 1000ULL; } +uint32_t HOT millis() { return static_cast<uint32_t>(millis_64()); } void HOT delay(uint32_t ms) { ::delay(ms); } -uint32_t IRAM_ATTR HOT micros() { return ::micros(); } -void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } +uint32_t HOT micros() { return ::micros(); } +void HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { watchdog_reboot(0, 0, 10); while (1) { @@ -34,7 +34,7 @@ void HOT arch_feed_wdt() { watchdog_update(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } -uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); } +uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); } uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); } } // namespace esphome diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 73b6a6c9b3..2c10e7e2da 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -28,7 +28,7 @@ static constexpr size_t MAX_POOL_SIZE = 5; // Set to 5 to match the pool size - when we have as many cancelled items as our // pool can hold, it's time to clean up and recycle them. static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) // Half the 32-bit range - used to detect rollovers vs normal time progression static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; #endif @@ -475,12 +475,13 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector<SchedulerItemPtr> old_items; -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && defined(ESPHOME_THREAD_MULTI_ATOMICS) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) && \ + defined(ESPHOME_THREAD_MULTI_ATOMICS) const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg); -#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) +#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_); #else @@ -714,7 +715,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) uint64_t Scheduler::millis_64_impl_(uint32_t now) { // THREAD SAFETY NOTE: // This function has three implementations, based on the precompiler flags @@ -872,7 +873,7 @@ uint64_t Scheduler::millis_64_impl_(uint32_t now) { "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." #endif } -#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR +#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040 bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 282f4c66ef..d52cf5147d 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -284,10 +284,10 @@ class Scheduler { bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); // Extend a 32-bit millis() value to 64-bit. Use when the caller already has a fresh now. - // On ESP32, ignores now and uses esp_timer_get_time() directly (native 64-bit). - // On non-ESP32, extends now to 64-bit using rollover tracking. + // On ESP32, Host, Zephyr, and RP2040, ignores now and uses the native 64-bit time source via millis_64(). + // On other platforms, extends now to 64-bit using rollover tracking. uint64_t millis_64_from_(uint32_t now) { -#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) || defined(USE_RP2040) (void) now; return millis_64(); #else @@ -295,7 +295,7 @@ class Scheduler { #endif } -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) // On platforms without native 64-bit time, millis_64() HAL function delegates to this // method which tracks 32-bit millis() rollover using millis_major_ and last_millis_. friend uint64_t millis_64(); @@ -567,8 +567,8 @@ class Scheduler { // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) std::vector<SchedulerItemPtr> scheduler_item_pool_; -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) - // On platforms with native 64-bit time (ESP32, Host, Zephyr), no rollover tracking needed. +#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) + // On platforms with native 64-bit time (ESP32, Host, Zephyr, RP2040), no rollover tracking needed. // On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_(). #ifdef ESPHOME_THREAD_MULTI_ATOMICS /* @@ -598,7 +598,7 @@ class Scheduler { #else /* not ESPHOME_THREAD_MULTI_ATOMICS */ uint16_t millis_major_{0}; #endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ -#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR */ +#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040 */ }; } // namespace esphome From bb567827a1e2f67a362d0a385868e438df8b71aa Mon Sep 17 00:00:00 2001 From: Laura Wratten <lauraw@canva.com> Date: Sat, 28 Feb 2026 08:23:32 +1100 Subject: [PATCH 1002/2030] [sht3xd] Allow sensors that don't support serial number read (#14224) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/sht3xd/sht3xd.cpp | 43 ++++++++-------------------- esphome/components/sht3xd/sht3xd.h | 9 ------ 2 files changed, 12 insertions(+), 40 deletions(-) diff --git a/esphome/components/sht3xd/sht3xd.cpp b/esphome/components/sht3xd/sht3xd.cpp index bd3dec6fb8..8050a2d5f9 100644 --- a/esphome/components/sht3xd/sht3xd.cpp +++ b/esphome/components/sht3xd/sht3xd.cpp @@ -12,6 +12,8 @@ static const char *const TAG = "sht3xd"; // To ensure compatibility, reading serial number using the register with clock stretching register enabled // (used originally in this component) is tried first and if that fails the alternate register address // with clock stretching disabled is read. +// If both fail (e.g. some clones don't support the command), we continue so temp/humidity still work. +// Second attempt uses 10ms delay for boards that need more time before read (max permitted by ESPHome guidelines). static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER_CLOCK_STRETCHING = 0x3780; static const uint16_t SHT3XD_COMMAND_READ_SERIAL_NUMBER = 0x3682; @@ -25,49 +27,28 @@ static const uint16_t SHT3XD_COMMAND_POLLING_H = 0x2400; static const uint16_t SHT3XD_COMMAND_FETCH_DATA = 0xE000; void SHT3XDComponent::setup() { - uint16_t raw_serial_number[2]; + uint16_t raw_serial_number[2]{0}; if (!this->get_register(SHT3XD_COMMAND_READ_SERIAL_NUMBER_CLOCK_STRETCHING, raw_serial_number, 2)) { - this->error_code_ = READ_SERIAL_STRETCHED_FAILED; - if (!this->get_register(SHT3XD_COMMAND_READ_SERIAL_NUMBER, raw_serial_number, 2)) { - this->error_code_ = READ_SERIAL_FAILED; - this->mark_failed(); - return; + if (!this->get_register(SHT3XD_COMMAND_READ_SERIAL_NUMBER, raw_serial_number, 2, 10)) { + ESP_LOGW(TAG, "Serial number read failed, continuing without it (clone or non-standard sensor)"); } } - this->serial_number_ = (uint32_t(raw_serial_number[0]) << 16) | uint32_t(raw_serial_number[1]); - if (!this->write_command(heater_enabled_ ? SHT3XD_COMMAND_HEATER_ENABLE : SHT3XD_COMMAND_HEATER_DISABLE)) { - this->error_code_ = WRITE_HEATER_MODE_FAILED; - this->mark_failed(); + if (!this->write_command(this->heater_enabled_ ? SHT3XD_COMMAND_HEATER_ENABLE : SHT3XD_COMMAND_HEATER_DISABLE)) { + this->mark_failed(LOG_STR("Failed to set heater mode")); return; } } void SHT3XDComponent::dump_config() { - ESP_LOGCONFIG(TAG, "SHT3xD:"); - switch (this->error_code_) { - case READ_SERIAL_FAILED: - ESP_LOGD(TAG, " Error reading serial number"); - break; - case WRITE_HEATER_MODE_FAILED: - ESP_LOGD(TAG, " Error writing heater mode"); - break; - default: - break; - } - if (this->is_failed()) { - ESP_LOGE(TAG, " Communication with SHT3xD failed!"); - return; - } - ESP_LOGD(TAG, - " Serial Number: 0x%08" PRIX32 "\n" - " Heater Enabled: %s", - this->serial_number_, TRUEFALSE(this->heater_enabled_)); - + ESP_LOGCONFIG(TAG, + "SHT3xD:\n" + " Serial Number: 0x%08" PRIX32 "\n" + " Heater Enabled: %s", + this->serial_number_, TRUEFALSE(this->heater_enabled_)); LOG_I2C_DEVICE(this); LOG_UPDATE_INTERVAL(this); - LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); } diff --git a/esphome/components/sht3xd/sht3xd.h b/esphome/components/sht3xd/sht3xd.h index 43f1a4d8e2..54514d6de7 100644 --- a/esphome/components/sht3xd/sht3xd.h +++ b/esphome/components/sht3xd/sht3xd.h @@ -4,8 +4,6 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" -#include <cinttypes> - namespace esphome { namespace sht3xd { @@ -21,13 +19,6 @@ class SHT3XDComponent : public PollingComponent, public sensirion_common::Sensir void set_heater_enabled(bool heater_enabled) { heater_enabled_ = heater_enabled; } protected: - enum ErrorCode { - NONE = 0, - READ_SERIAL_STRETCHED_FAILED, - READ_SERIAL_FAILED, - WRITE_HEATER_MODE_FAILED, - } error_code_{NONE}; - sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; bool heater_enabled_{true}; From 5e3857abf7dded7d731cdd5663b23ca0edb6491f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Feb 2026 16:25:36 -0500 Subject: [PATCH 1003/2030] Bump click from 8.1.7 to 8.3.1 (#11955) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 95e3710f9e..f111e05a9d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ tzdata>=2021.1 # from time pyserial==3.5 platformio==6.1.19 esptool==5.2.0 -click==8.1.7 +click==8.3.1 esphome-dashboard==20260210.0 aioesphomeapi==44.2.0 zeroconf==0.148.0 From b9d70dcda2d5ff6bad34c6c72ae12f5c9b9cd6e6 Mon Sep 17 00:00:00 2001 From: Martin Ebner <185941678+mebner86@users.noreply.github.com> Date: Sat, 28 Feb 2026 03:11:28 +0530 Subject: [PATCH 1004/2030] [sen6x] Add SEN6x sensor support (#12553) Co-authored-by: Martin Ebner <martinebner@me.com> Co-authored-by: Tobias Stanzel <tobi.stanzel@gmail.com> Co-authored-by: Big Mike <mike@bigmike.land> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/sen6x/__init__.py | 0 esphome/components/sen6x/sen6x.cpp | 376 +++++++++++++++++++ esphome/components/sen6x/sen6x.h | 43 +++ esphome/components/sen6x/sensor.py | 149 ++++++++ tests/components/sen6x/common.yaml | 37 ++ tests/components/sen6x/test.esp32-idf.yaml | 4 + tests/components/sen6x/test.esp8266-ard.yaml | 4 + tests/components/sen6x/test.rp2040-ard.yaml | 4 + 9 files changed, 618 insertions(+) create mode 100644 esphome/components/sen6x/__init__.py create mode 100644 esphome/components/sen6x/sen6x.cpp create mode 100644 esphome/components/sen6x/sen6x.h create mode 100644 esphome/components/sen6x/sensor.py create mode 100644 tests/components/sen6x/common.yaml create mode 100644 tests/components/sen6x/test.esp32-idf.yaml create mode 100644 tests/components/sen6x/test.esp8266-ard.yaml create mode 100644 tests/components/sen6x/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 6728e76bba..4c97b7f99d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -429,6 +429,7 @@ esphome/components/select/* @esphome/core esphome/components/sen0321/* @notjj esphome/components/sen21231/* @shreyaskarnik esphome/components/sen5x/* @martgras +esphome/components/sen6x/* @martgras @mebner86 @mikelawrence @tuct esphome/components/sensirion_common/* @martgras esphome/components/sensor/* @esphome/core esphome/components/sfa30/* @ghsensdev diff --git a/esphome/components/sen6x/__init__.py b/esphome/components/sen6x/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/sen6x/sen6x.cpp b/esphome/components/sen6x/sen6x.cpp new file mode 100644 index 0000000000..baaadd6463 --- /dev/null +++ b/esphome/components/sen6x/sen6x.cpp @@ -0,0 +1,376 @@ +#include "sen6x.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" +#include <cmath> +#include <functional> +#include <memory> + +namespace esphome::sen6x { + +static const char *const TAG = "sen6x"; + +static constexpr uint16_t SEN6X_CMD_GET_DATA_READY_STATUS = 0x0202; +static constexpr uint16_t SEN6X_CMD_GET_FIRMWARE_VERSION = 0xD100; +static constexpr uint16_t SEN6X_CMD_GET_PRODUCT_NAME = 0xD014; +static constexpr uint16_t SEN6X_CMD_GET_SERIAL_NUMBER = 0xD033; + +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT = 0x0300; // SEN66 only! +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT_SEN62 = 0x04A3; +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT_SEN63C = 0x0471; +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT_SEN65 = 0x0446; +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT_SEN68 = 0x0467; +static constexpr uint16_t SEN6X_CMD_READ_MEASUREMENT_SEN69C = 0x04B5; + +static constexpr uint16_t SEN6X_CMD_START_MEASUREMENTS = 0x0021; +static constexpr uint16_t SEN6X_CMD_RESET = 0xD304; + +static inline void set_read_command_and_words(SEN6XComponent::Sen6xType type, uint16_t &read_cmd, uint8_t &read_words) { + read_cmd = SEN6X_CMD_READ_MEASUREMENT; + read_words = 9; + switch (type) { + case SEN6XComponent::SEN62: + read_cmd = SEN6X_CMD_READ_MEASUREMENT_SEN62; + read_words = 6; + break; + case SEN6XComponent::SEN63C: + read_cmd = SEN6X_CMD_READ_MEASUREMENT_SEN63C; + read_words = 7; + break; + case SEN6XComponent::SEN65: + read_cmd = SEN6X_CMD_READ_MEASUREMENT_SEN65; + read_words = 8; + break; + case SEN6XComponent::SEN66: + read_cmd = SEN6X_CMD_READ_MEASUREMENT; + read_words = 9; + break; + case SEN6XComponent::SEN68: + read_cmd = SEN6X_CMD_READ_MEASUREMENT_SEN68; + read_words = 9; + break; + case SEN6XComponent::SEN69C: + read_cmd = SEN6X_CMD_READ_MEASUREMENT_SEN69C; + read_words = 10; + break; + default: + break; + } +} + +void SEN6XComponent::setup() { + ESP_LOGCONFIG(TAG, "Setting up sen6x..."); + + // the sensor needs 100 ms to enter the idle state + this->set_timeout(100, [this]() { + // Reset the sensor to ensure a clean state regardless of prior commands or power issues + if (!this->write_command(SEN6X_CMD_RESET)) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + + // After reset the sensor needs 100 ms to become ready + this->set_timeout(100, [this]() { + // Step 1: Read serial number (~25ms with I2C delay) + uint16_t raw_serial_number[16]; + if (!this->get_register(SEN6X_CMD_GET_SERIAL_NUMBER, raw_serial_number, 16, 20)) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + this->serial_number_ = SEN6XComponent::sensirion_convert_to_string_in_place(raw_serial_number, 16); + ESP_LOGI(TAG, "Serial number: %s", this->serial_number_.c_str()); + + // Step 2: Read product name in next loop iteration + this->set_timeout(0, [this]() { + uint16_t raw_product_name[16]; + if (!this->get_register(SEN6X_CMD_GET_PRODUCT_NAME, raw_product_name, 16, 20)) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + + this->product_name_ = SEN6XComponent::sensirion_convert_to_string_in_place(raw_product_name, 16); + + Sen6xType inferred_type = this->infer_type_from_product_name_(this->product_name_); + if (this->sen6x_type_ == UNKNOWN) { + this->sen6x_type_ = inferred_type; + if (inferred_type == UNKNOWN) { + ESP_LOGE(TAG, "Unknown product '%s'", this->product_name_.c_str()); + this->mark_failed(); + return; + } + ESP_LOGD(TAG, "Type inferred from product: %s", this->product_name_.c_str()); + } else if (this->sen6x_type_ != inferred_type && inferred_type != UNKNOWN) { + ESP_LOGW(TAG, "Configured type (used) mismatches product '%s'", this->product_name_.c_str()); + } + ESP_LOGI(TAG, "Product: %s", this->product_name_.c_str()); + + // Validate configured sensors against detected type and disable unsupported ones + const bool has_voc_nox = (this->sen6x_type_ == SEN65 || this->sen6x_type_ == SEN66 || + this->sen6x_type_ == SEN68 || this->sen6x_type_ == SEN69C); + const bool has_co2 = (this->sen6x_type_ == SEN63C || this->sen6x_type_ == SEN66 || this->sen6x_type_ == SEN69C); + const bool has_hcho = (this->sen6x_type_ == SEN68 || this->sen6x_type_ == SEN69C); + if (this->voc_sensor_ && !has_voc_nox) { + ESP_LOGE(TAG, "VOC requires SEN65, SEN66, SEN68, or SEN69C"); + this->voc_sensor_ = nullptr; + } + if (this->nox_sensor_ && !has_voc_nox) { + ESP_LOGE(TAG, "NOx requires SEN65, SEN66, SEN68, or SEN69C"); + this->nox_sensor_ = nullptr; + } + if (this->co2_sensor_ && !has_co2) { + ESP_LOGE(TAG, "CO2 requires SEN63C, SEN66, or SEN69C"); + this->co2_sensor_ = nullptr; + } + if (this->hcho_sensor_ && !has_hcho) { + ESP_LOGE(TAG, "Formaldehyde requires SEN68 or SEN69C"); + this->hcho_sensor_ = nullptr; + } + + // Step 3: Read firmware version and start measurements in next loop iteration + this->set_timeout(0, [this]() { + uint16_t raw_firmware_version = 0; + if (!this->get_register(SEN6X_CMD_GET_FIRMWARE_VERSION, raw_firmware_version, 20)) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + this->firmware_version_major_ = (raw_firmware_version >> 8) & 0xFF; + this->firmware_version_minor_ = raw_firmware_version & 0xFF; + ESP_LOGI(TAG, "Firmware: %u.%u", this->firmware_version_major_, this->firmware_version_minor_); + + if (!this->write_command(SEN6X_CMD_START_MEASUREMENTS)) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); + return; + } + + this->set_timeout(60000, [this]() { this->startup_complete_ = true; }); + this->initialized_ = true; + ESP_LOGD(TAG, "Initialized"); + }); + }); + }); + }); +} + +void SEN6XComponent::dump_config() { + ESP_LOGCONFIG(TAG, + "sen6x:\n" + " Product: %s\n" + " Serial: %s\n" + " Firmware: %u.%u\n" + " Address: 0x%02X", + this->product_name_.c_str(), this->serial_number_.c_str(), this->firmware_version_major_, + this->firmware_version_minor_, this->address_); + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "PM 1.0", this->pm_1_0_sensor_); + LOG_SENSOR(" ", "PM 2.5", this->pm_2_5_sensor_); + LOG_SENSOR(" ", "PM 4.0", this->pm_4_0_sensor_); + LOG_SENSOR(" ", "PM 10.0", this->pm_10_0_sensor_); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); + LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); + LOG_SENSOR(" ", "VOC", this->voc_sensor_); + LOG_SENSOR(" ", "NOx", this->nox_sensor_); + LOG_SENSOR(" ", "HCHO", this->hcho_sensor_); + LOG_SENSOR(" ", "CO2", this->co2_sensor_); +} + +void SEN6XComponent::update() { + if (!this->initialized_) { + return; + } + + uint16_t read_cmd; + uint8_t read_words; + set_read_command_and_words(this->sen6x_type_, read_cmd, read_words); + + const uint8_t poll_retries = 24; + auto poll_ready = std::make_shared<std::function<void(uint8_t)>>(); + *poll_ready = [this, poll_ready, read_cmd, read_words](uint8_t retries_left) { + const uint8_t attempt = static_cast<uint8_t>(poll_retries - retries_left + 1); + ESP_LOGV(TAG, "Data ready polling attempt %u", attempt); + + if (!this->write_command(SEN6X_CMD_GET_DATA_READY_STATUS)) { + this->status_set_warning(); + ESP_LOGD(TAG, "write data ready status error (%d)", this->last_error_); + return; + } + + this->set_timeout(20, [this, poll_ready, retries_left, read_cmd, read_words]() { + uint16_t raw_read_status; + if (!this->read_data(&raw_read_status, 1)) { + this->status_set_warning(); + ESP_LOGD(TAG, "read data ready status error (%d)", this->last_error_); + return; + } + + if ((raw_read_status & 0x0001) == 0) { + if (retries_left == 0) { + this->status_set_warning(); + ESP_LOGD(TAG, "Data not ready"); + return; + } + this->set_timeout(50, [poll_ready, retries_left]() { (*poll_ready)(retries_left - 1); }); + return; + } + + if (!this->write_command(read_cmd)) { + this->status_set_warning(); + ESP_LOGD(TAG, "Read measurement failed (%d)", this->last_error_); + return; + } + + this->set_timeout(20, [this, read_words]() { + uint16_t measurements[10]; + + if (!this->read_data(measurements, read_words)) { + this->status_set_warning(); + ESP_LOGD(TAG, "Read data failed (%d)", this->last_error_); + return; + } + int8_t voc_index = -1; + int8_t nox_index = -1; + int8_t hcho_index = -1; + int8_t co2_index = -1; + bool co2_uint16 = false; + switch (this->sen6x_type_) { + case SEN62: + break; + case SEN63C: + co2_index = 6; + break; + case SEN65: + voc_index = 6; + nox_index = 7; + break; + case SEN66: + voc_index = 6; + nox_index = 7; + co2_index = 8; + co2_uint16 = true; + break; + case SEN68: + voc_index = 6; + nox_index = 7; + hcho_index = 8; + break; + case SEN69C: + voc_index = 6; + nox_index = 7; + hcho_index = 8; + co2_index = 9; + break; + default: + break; + } + + float pm_1_0 = measurements[0] / 10.0f; + if (measurements[0] == 0xFFFF) + pm_1_0 = NAN; + float pm_2_5 = measurements[1] / 10.0f; + if (measurements[1] == 0xFFFF) + pm_2_5 = NAN; + float pm_4_0 = measurements[2] / 10.0f; + if (measurements[2] == 0xFFFF) + pm_4_0 = NAN; + float pm_10_0 = measurements[3] / 10.0f; + if (measurements[3] == 0xFFFF) + pm_10_0 = NAN; + float humidity = static_cast<int16_t>(measurements[4]) / 100.0f; + if (measurements[4] == 0x7FFF) + humidity = NAN; + float temperature = static_cast<int16_t>(measurements[5]) / 200.0f; + if (measurements[5] == 0x7FFF) + temperature = NAN; + + float voc = NAN; + float nox = NAN; + float hcho = NAN; + float co2 = NAN; + + if (voc_index >= 0) { + voc = static_cast<int16_t>(measurements[voc_index]) / 10.0f; + if (measurements[voc_index] == 0x7FFF) + voc = NAN; + } + if (nox_index >= 0) { + nox = static_cast<int16_t>(measurements[nox_index]) / 10.0f; + if (measurements[nox_index] == 0x7FFF) + nox = NAN; + } + + if (hcho_index >= 0) { + const uint16_t hcho_raw = measurements[hcho_index]; + hcho = hcho_raw / 10.0f; + if (hcho_raw == 0xFFFF) + hcho = NAN; + } + + if (co2_index >= 0) { + if (co2_uint16) { + const uint16_t co2_raw = measurements[co2_index]; + co2 = static_cast<float>(co2_raw); + if (co2_raw == 0xFFFF) + co2 = NAN; + } else { + const int16_t co2_raw = static_cast<int16_t>(measurements[co2_index]); + co2 = static_cast<float>(co2_raw); + if (co2_raw == 0x7FFF) + co2 = NAN; + } + } + + if (!this->startup_complete_) { + ESP_LOGD(TAG, "Startup delay, ignoring values"); + this->status_clear_warning(); + return; + } + + if (this->pm_1_0_sensor_ != nullptr) + this->pm_1_0_sensor_->publish_state(pm_1_0); + if (this->pm_2_5_sensor_ != nullptr) + this->pm_2_5_sensor_->publish_state(pm_2_5); + if (this->pm_4_0_sensor_ != nullptr) + this->pm_4_0_sensor_->publish_state(pm_4_0); + if (this->pm_10_0_sensor_ != nullptr) + this->pm_10_0_sensor_->publish_state(pm_10_0); + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temperature); + if (this->humidity_sensor_ != nullptr) + this->humidity_sensor_->publish_state(humidity); + if (this->voc_sensor_ != nullptr) + this->voc_sensor_->publish_state(voc); + if (this->nox_sensor_ != nullptr) + this->nox_sensor_->publish_state(nox); + if (this->hcho_sensor_ != nullptr) + this->hcho_sensor_->publish_state(hcho); + if (this->co2_sensor_ != nullptr) + this->co2_sensor_->publish_state(co2); + + this->status_clear_warning(); + }); + }); + }; + + (*poll_ready)(poll_retries); +} + +SEN6XComponent::Sen6xType SEN6XComponent::infer_type_from_product_name_(const std::string &product_name) { + if (product_name == "SEN62") + return SEN62; + if (product_name == "SEN63C") + return SEN63C; + if (product_name == "SEN65") + return SEN65; + if (product_name == "SEN66") + return SEN66; + if (product_name == "SEN68") + return SEN68; + if (product_name == "SEN69C") + return SEN69C; + return UNKNOWN; +} + +} // namespace esphome::sen6x diff --git a/esphome/components/sen6x/sen6x.h b/esphome/components/sen6x/sen6x.h new file mode 100644 index 0000000000..01e89dce1b --- /dev/null +++ b/esphome/components/sen6x/sen6x.h @@ -0,0 +1,43 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/sensirion_common/i2c_sensirion.h" + +namespace esphome::sen6x { + +class SEN6XComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { + SUB_SENSOR(pm_1_0) + SUB_SENSOR(pm_2_5) + SUB_SENSOR(pm_4_0) + SUB_SENSOR(pm_10_0) + SUB_SENSOR(temperature) + SUB_SENSOR(humidity) + SUB_SENSOR(voc) + SUB_SENSOR(nox) + SUB_SENSOR(co2) + SUB_SENSOR(hcho) + + public: + float get_setup_priority() const override { return setup_priority::DATA; } + void setup() override; + void dump_config() override; + void update() override; + + enum Sen6xType { SEN62, SEN63C, SEN65, SEN66, SEN68, SEN69C, UNKNOWN }; + + void set_type(const std::string &type) { sen6x_type_ = infer_type_from_product_name_(type); } + + protected: + Sen6xType infer_type_from_product_name_(const std::string &product_name); + + bool initialized_{false}; + std::string product_name_; + Sen6xType sen6x_type_{UNKNOWN}; + std::string serial_number_; + uint8_t firmware_version_major_{0}; + uint8_t firmware_version_minor_{0}; + bool startup_complete_{false}; +}; + +} // namespace esphome::sen6x diff --git a/esphome/components/sen6x/sensor.py b/esphome/components/sen6x/sensor.py new file mode 100644 index 0000000000..071478e719 --- /dev/null +++ b/esphome/components/sen6x/sensor.py @@ -0,0 +1,149 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensirion_common, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_CO2, + CONF_FORMALDEHYDE, + CONF_HUMIDITY, + CONF_ID, + CONF_NOX, + CONF_PM_1_0, + CONF_PM_2_5, + CONF_PM_4_0, + CONF_PM_10_0, + CONF_TEMPERATURE, + CONF_TYPE, + CONF_VOC, + DEVICE_CLASS_AQI, + DEVICE_CLASS_CARBON_DIOXIDE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_PM1, + DEVICE_CLASS_PM10, + DEVICE_CLASS_PM25, + DEVICE_CLASS_TEMPERATURE, + ICON_CHEMICAL_WEAPON, + ICON_MOLECULE_CO2, + ICON_RADIATOR, + ICON_THERMOMETER, + ICON_WATER_PERCENT, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_PARTS_PER_MILLION, + UNIT_PERCENT, +) + +CODEOWNERS = ["@martgras", "@mebner86", "@mikelawrence", "@tuct"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["sensirion_common"] + +sen6x_ns = cg.esphome_ns.namespace("sen6x") +SEN6XComponent = sen6x_ns.class_( + "SEN6XComponent", cg.PollingComponent, sensirion_common.SensirionI2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SEN6XComponent), + cv.Optional(CONF_TYPE): cv.one_of( + "SEN62", "SEN63C", "SEN65", "SEN66", "SEN68", "SEN69C", upper=True + ), + cv.Optional(CONF_PM_1_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM1, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM25, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PM_4_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM10, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=2, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_WATER_PERCENT, + accuracy_decimals=2, + device_class=DEVICE_CLASS_HUMIDITY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_VOC): sensor.sensor_schema( + icon=ICON_RADIATOR, + accuracy_decimals=0, + device_class=DEVICE_CLASS_AQI, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_NOX): sensor.sensor_schema( + icon=ICON_RADIATOR, + accuracy_decimals=0, + device_class=DEVICE_CLASS_AQI, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CO2): sensor.sensor_schema( + unit_of_measurement=UNIT_PARTS_PER_MILLION, + icon=ICON_MOLECULE_CO2, + accuracy_decimals=0, + device_class=DEVICE_CLASS_CARBON_DIOXIDE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_FORMALDEHYDE): sensor.sensor_schema( + unit_of_measurement="ppb", + icon=ICON_RADIATOR, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x6B)) +) + +SENSOR_MAP = { + CONF_PM_1_0: "set_pm_1_0_sensor", + CONF_PM_2_5: "set_pm_2_5_sensor", + CONF_PM_4_0: "set_pm_4_0_sensor", + CONF_PM_10_0: "set_pm_10_0_sensor", + CONF_TEMPERATURE: "set_temperature_sensor", + CONF_HUMIDITY: "set_humidity_sensor", + CONF_VOC: "set_voc_sensor", + CONF_NOX: "set_nox_sensor", + CONF_CO2: "set_co2_sensor", + CONF_FORMALDEHYDE: "set_hcho_sensor", +} + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + if CONF_TYPE in config: + cg.add(var.set_type(config[CONF_TYPE])) + + for key, func_name in SENSOR_MAP.items(): + if cfg := config.get(key): + sens = await sensor.new_sensor(cfg) + cg.add(getattr(var, func_name)(sens)) diff --git a/tests/components/sen6x/common.yaml b/tests/components/sen6x/common.yaml new file mode 100644 index 0000000000..fdb8a485e2 --- /dev/null +++ b/tests/components/sen6x/common.yaml @@ -0,0 +1,37 @@ +sensor: + # Test with explicit type parameter + - platform: sen6x + id: sen6x_sensor + type: SEN69C + i2c_id: i2c_bus + temperature: + name: Temperature + accuracy_decimals: 1 + humidity: + name: Humidity + accuracy_decimals: 0 + pm_1_0: + name: PM <1µm Weight concentration + id: pm_1_0 + accuracy_decimals: 1 + pm_2_5: + name: PM <2.5µm Weight concentration + id: pm_2_5 + accuracy_decimals: 1 + pm_4_0: + name: PM <4µm Weight concentration + id: pm_4_0 + accuracy_decimals: 1 + pm_10_0: + name: PM <10µm Weight concentration + id: pm_10_0 + accuracy_decimals: 1 + nox: + name: NOx + voc: + name: VOC + co2: + name: Carbon Dioxide + formaldehyde: + name: Formaldehyde + address: 0x6B diff --git a/tests/components/sen6x/test.esp32-idf.yaml b/tests/components/sen6x/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/sen6x/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/sen6x/test.esp8266-ard.yaml b/tests/components/sen6x/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/sen6x/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/sen6x/test.rp2040-ard.yaml b/tests/components/sen6x/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/sen6x/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml From 5c56b99742a12cfde9cbeb0f91641db96cd132d7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 16:19:11 -0700 Subject: [PATCH 1005/2030] [ci] Fix C++ unit tests missing time component dependency (#14364) --- script/cpp_unit_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index 78b65092ae..02b133060a 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -98,8 +98,12 @@ def run_tests(selected_components: list[str]) -> int: components = sorted(components) - # Obtain possible dependencies for the requested components: - components_with_dependencies = sorted(get_all_dependencies(set(components))) + # Obtain possible dependencies for the requested components. + # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, + # which causes core/time.h to include components/time/posix_tz.h. + components_with_dependencies = sorted( + get_all_dependencies(set(components) | {"time"}) + ) # Build a list of include folders, one folder per component containing tests. # A special replacement main.cpp is located in /tests/components/main.cpp From 298ee7b92e4d0a1ad17fcd3995a689deadcb890f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Feb 2026 19:08:42 -0500 Subject: [PATCH 1006/2030] [gps] Fix codegen deadlock when automations reference sibling sensors (#14365) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/gps/__init__.py | 44 ++++++++++++------------------ tests/components/gps/common.yaml | 7 +++++ 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/esphome/components/gps/__init__.py b/esphome/components/gps/__init__.py index 2135189bd5..045a5a6c84 100644 --- a/esphome/components/gps/__init__.py +++ b/esphome/components/gps/__init__.py @@ -98,33 +98,25 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) - if latitude_config := config.get(CONF_LATITUDE): - sens = await sensor.new_sensor(latitude_config) - cg.add(var.set_latitude_sensor(sens)) + # Pre-create all sensor variables so automations that reference + # sibling sensors don't deadlock waiting for unregistered IDs. + sensors = [ + (cg.new_Pvariable(conf[CONF_ID]), conf, setter) + for key, setter in ( + (CONF_LATITUDE, "set_latitude_sensor"), + (CONF_LONGITUDE, "set_longitude_sensor"), + (CONF_SPEED, "set_speed_sensor"), + (CONF_COURSE, "set_course_sensor"), + (CONF_ALTITUDE, "set_altitude_sensor"), + (CONF_SATELLITES, "set_satellites_sensor"), + (CONF_HDOP, "set_hdop_sensor"), + ) + if (conf := config.get(key)) + ] - if longitude_config := config.get(CONF_LONGITUDE): - sens = await sensor.new_sensor(longitude_config) - cg.add(var.set_longitude_sensor(sens)) - - if speed_config := config.get(CONF_SPEED): - sens = await sensor.new_sensor(speed_config) - cg.add(var.set_speed_sensor(sens)) - - if course_config := config.get(CONF_COURSE): - sens = await sensor.new_sensor(course_config) - cg.add(var.set_course_sensor(sens)) - - if altitude_config := config.get(CONF_ALTITUDE): - sens = await sensor.new_sensor(altitude_config) - cg.add(var.set_altitude_sensor(sens)) - - if satellites_config := config.get(CONF_SATELLITES): - sens = await sensor.new_sensor(satellites_config) - cg.add(var.set_satellites_sensor(sens)) - - if hdop_config := config.get(CONF_HDOP): - sens = await sensor.new_sensor(hdop_config) - cg.add(var.set_hdop_sensor(sens)) + for sens, conf, setter in sensors: + await sensor.register_sensor(sens, conf) + cg.add(getattr(var, setter)(sens)) # https://platformio.org/lib/show/1655/TinyGPSPlus # Using fork of TinyGPSPlus patched to build on ESP-IDF diff --git a/tests/components/gps/common.yaml b/tests/components/gps/common.yaml index a99e3ef7e0..568f2cc7c7 100644 --- a/tests/components/gps/common.yaml +++ b/tests/components/gps/common.yaml @@ -1,8 +1,15 @@ gps: latitude: name: "Latitude" + id: gps_lat + on_value: + then: + - logger.log: + format: "%.6f, %.6f" + args: [id(gps_lat).state, id(gps_long).state] longitude: name: "Longitude" + id: gps_long altitude: name: "Altitude" speed: From d1b481319773a38d4a24cae0a4e7c86ea0ab1908 Mon Sep 17 00:00:00 2001 From: Ryan Wagoner <8441200+rwagoner@users.noreply.github.com> Date: Fri, 27 Feb 2026 19:20:13 -0500 Subject: [PATCH 1007/2030] [web_server] Add climate preset, fan mode, and humidity support (#14061) --- esphome/components/web_server/web_server.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 16674321c9..4824e33dcd 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1490,6 +1490,7 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url parse_string_param_(request, ESPHOME_F("mode"), call, &decltype(call)::set_mode); parse_string_param_(request, ESPHOME_F("fan_mode"), call, &decltype(call)::set_fan_mode); parse_string_param_(request, ESPHOME_F("swing_mode"), call, &decltype(call)::set_swing_mode); + parse_string_param_(request, ESPHOME_F("preset"), call, &decltype(call)::set_preset); // Parse temperature parameters // static_cast needed to disambiguate overloaded setters (float vs optional<float>) @@ -1530,7 +1531,7 @@ json::SerializationBuffer<> WebServer::climate_json_(climate::Climate *obj, Json JsonArray opt = root[ESPHOME_F("modes")].to<JsonArray>(); for (climate::ClimateMode m : traits.get_supported_modes()) opt.add(PSTR_LOCAL(climate::climate_mode_to_string(m))); - if (!traits.get_supported_custom_fan_modes().empty()) { + if (traits.get_supports_fan_modes()) { JsonArray opt = root[ESPHOME_F("fan_modes")].to<JsonArray>(); for (climate::ClimateFanMode m : traits.get_supported_fan_modes()) opt.add(PSTR_LOCAL(climate::climate_fan_mode_to_string(m))); @@ -1546,12 +1547,12 @@ json::SerializationBuffer<> WebServer::climate_json_(climate::Climate *obj, Json for (auto swing_mode : traits.get_supported_swing_modes()) opt.add(PSTR_LOCAL(climate::climate_swing_mode_to_string(swing_mode))); } - if (traits.get_supports_presets() && obj->preset.has_value()) { + if (traits.get_supports_presets()) { JsonArray opt = root[ESPHOME_F("presets")].to<JsonArray>(); for (climate::ClimatePreset m : traits.get_supported_presets()) opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m))); } - if (!traits.get_supported_custom_presets().empty() && obj->has_custom_preset()) { + if (!traits.get_supported_custom_presets().empty()) { JsonArray opt = root[ESPHOME_F("custom_presets")].to<JsonArray>(); for (auto const &custom_preset : traits.get_supported_custom_presets()) opt.add(custom_preset); @@ -1592,6 +1593,11 @@ json::SerializationBuffer<> WebServer::climate_json_(climate::Climate *obj, Json ? "NA" : (value_accuracy_to_buf(temp_buf, obj->current_temperature, current_accuracy), temp_buf); } + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY)) { + root[ESPHOME_F("current_humidity")] = std::isnan(obj->current_humidity) + ? "NA" + : (value_accuracy_to_buf(temp_buf, obj->current_humidity, 0), temp_buf); + } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { root[ESPHOME_F("target_temperature_low")] = From e7d4f2608b20d4a7f1c2ea0bd99c8c25cd04e6a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 16:01:17 -1000 Subject: [PATCH 1008/2030] [sen6x] Fix test sensor ID collisions with sen5x (#14367) --- tests/components/sen6x/common.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/components/sen6x/common.yaml b/tests/components/sen6x/common.yaml index fdb8a485e2..61ff9f1e0c 100644 --- a/tests/components/sen6x/common.yaml +++ b/tests/components/sen6x/common.yaml @@ -12,19 +12,19 @@ sensor: accuracy_decimals: 0 pm_1_0: name: PM <1µm Weight concentration - id: pm_1_0 + id: sen6x_pm_1_0 accuracy_decimals: 1 pm_2_5: name: PM <2.5µm Weight concentration - id: pm_2_5 + id: sen6x_pm_2_5 accuracy_decimals: 1 pm_4_0: name: PM <4µm Weight concentration - id: pm_4_0 + id: sen6x_pm_4_0 accuracy_decimals: 1 pm_10_0: name: PM <10µm Weight concentration - id: pm_10_0 + id: sen6x_pm_10_0 accuracy_decimals: 1 nox: name: NOx From 8480e8df9f0b834ebeb2694b30e15eede8b716a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 17:27:51 -1000 Subject: [PATCH 1009/2030] [uart] Revert UART0 default pin workarounds (fixed in ESP-IDF 5.5.2) (#14363) --- .../uart/uart_component_esp_idf.cpp | 36 +++---------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index ea7a09fee6..8699d37d7a 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -9,7 +9,6 @@ #include "esphome/core/gpio.h" #include "driver/gpio.h" #include "soc/gpio_num.h" -#include "soc/uart_pins.h" #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" @@ -19,13 +18,6 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; -/// Check if a pin number matches one of the default UART0 GPIO pins. -/// These pins may have residual state from the boot console that requires -/// explicit reset before UART reconfiguration (ESP-IDF issue #17459). -static constexpr bool is_default_uart0_pin(int8_t pin_num) { - return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; -} - uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -149,34 +141,12 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; - - // Workaround for ESP-IDF issue: https://github.com/espressif/esp-idf/issues/17459 - // Commit 9ed617fb17 removed gpio_func_sel() calls from uart_set_pin(), which breaks - // UART on default UART0 pins that may have residual state from boot console. - // Reset these pins before configuring UART to ensure they're in a clean state. - if (is_default_uart0_pin(tx)) { - gpio_reset_pin(static_cast<gpio_num_t>(tx)); - } - if (is_default_uart0_pin(rx)) { - gpio_reset_pin(static_cast<gpio_num_t>(rx)); - } - - // Setup pins after reset to configure GPIO direction and pull resistors. - // For UART0 default pins, setup() must always be called because gpio_reset_pin() - // above sets GPIO_MODE_DISABLE which disables the input buffer. Without setup(), - // uart_set_pin() on ESP-IDF 5.4.2+ does not re-enable the input buffer for - // IOMUX-connected pins, so the RX pin cannot receive data (see issue #10132). - // For other pins, only call setup() if pull or open-drain flags are set to avoid - // disturbing the default pin state which breaks some external components (#11823). auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; } const auto mask = gpio::Flags::FLAG_OPEN_DRAIN | gpio::Flags::FLAG_PULLUP | gpio::Flags::FLAG_PULLDOWN; - if (is_default_uart0_pin(pin->get_pin()) || (pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { + if ((pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { pin->setup(); } }; @@ -186,6 +156,10 @@ void IDFUARTComponent::load_settings(bool dump_config) { setup_pin_if_needed(this->tx_pin_); } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; + int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; + int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; + uint32_t invert = 0; if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) { invert |= UART_SIGNAL_TXD_INV; From 49cc389bf0e0e4853b4bbc5de38f89b6224ee28f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 17:28:05 -1000 Subject: [PATCH 1010/2030] [esp32] Wrap printf/vprintf/fprintf to eliminate _vfprintf_r (~11 KB flash) (#14362) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 10 +++ esphome/components/esp32/printf_stubs.cpp | 85 ++++++++++++++++++++++ tests/components/esp32/test.esp32-idf.yaml | 1 + 3 files changed, 96 insertions(+) create mode 100644 esphome/components/esp32/printf_stubs.cpp diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 998913ecec..dd9e394fd2 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -952,6 +952,7 @@ CONF_HEAP_IN_IRAM = "heap_in_iram" CONF_LOOP_TASK_STACK_SIZE = "loop_task_stack_size" CONF_USE_FULL_CERTIFICATE_BUNDLE = "use_full_certificate_bundle" CONF_DISABLE_DEBUG_STUBS = "disable_debug_stubs" +CONF_ENABLE_FULL_PRINTF = "enable_full_printf" CONF_DISABLE_OCD_AWARE = "disable_ocd_aware" CONF_DISABLE_USB_SERIAL_JTAG_SECONDARY = "disable_usb_serial_jtag_secondary" CONF_DISABLE_DEV_NULL_VFS = "disable_dev_null_vfs" @@ -1126,6 +1127,7 @@ FRAMEWORK_SCHEMA = cv.Schema( cv.Optional( CONF_INCLUDE_BUILTIN_IDF_COMPONENTS, default=[] ): cv.ensure_list(cv.string_strict), + cv.Optional(CONF_ENABLE_FULL_PRINTF, default=False): cv.boolean, cv.Optional(CONF_DISABLE_DEBUG_STUBS, default=True): cv.boolean, cv.Optional(CONF_DISABLE_OCD_AWARE, default=True): cv.boolean, cv.Optional( @@ -1469,6 +1471,14 @@ async def to_code(config): "_ZSt25__throw_bad_function_callv", ]: cg.add_build_flag(f"-Wl,--wrap={mangled}") + + # Wrap FILE*-based printf functions to eliminate newlib's _vfprintf_r + # (~11 KB). See printf_stubs.cpp for implementation. + if conf[CONF_ADVANCED][CONF_ENABLE_FULL_PRINTF]: + cg.add_define("USE_FULL_PRINTF") + else: + for symbol in ("vprintf", "printf", "fprintf"): + cg.add_build_flag(f"-Wl,--wrap={symbol}") else: cg.add_build_flag("-DUSE_ARDUINO") cg.add_build_flag("-DUSE_ESP32_FRAMEWORK_ARDUINO") diff --git a/esphome/components/esp32/printf_stubs.cpp b/esphome/components/esp32/printf_stubs.cpp new file mode 100644 index 0000000000..c6f03bc363 --- /dev/null +++ b/esphome/components/esp32/printf_stubs.cpp @@ -0,0 +1,85 @@ +/* + * Linker wrap stubs for FILE*-based printf functions. + * + * ESP-IDF SDK components (gpio driver, ringbuf, log_write) reference + * fprintf(), printf(), and vprintf() which pull in newlib's _vfprintf_r + * (~11 KB). This is a separate implementation from _svfprintf_r (used by + * snprintf/vsnprintf) that handles FILE* stream I/O with buffering and + * locking. + * + * ESPHome replaces the ESP-IDF log handler via esp_log_set_vprintf_(), + * so the SDK's vprintf() path is dead code at runtime. The fprintf() + * and printf() calls in SDK components are only in debug/assert paths + * (gpio_dump_io_configuration, ringbuf diagnostics) that are either + * GC'd or never called. Crash backtraces and panic output are + * unaffected — they use esp_rom_printf() which is a ROM function + * and does not go through libc. + * + * These stubs redirect through vsnprintf() (which uses _svfprintf_r + * already in the binary) and fwrite(), allowing the linker to + * dead-code eliminate _vfprintf_r. + * + * Saves ~11 KB of flash. + * + * To disable these wraps, set enable_full_printf: true in the esp32 + * advanced config section. + */ + +#if defined(USE_ESP_IDF) && !defined(USE_FULL_PRINTF) +#include <cstdarg> +#include <cstdio> + +#include "esp_system.h" + +namespace esphome::esp32 {} + +static constexpr size_t PRINTF_BUFFER_SIZE = 512; + +// These stubs are essentially dead code at runtime — ESPHome replaces the +// ESP-IDF log handler, and the SDK's printf/fprintf calls only exist in +// debug/assert paths that are never reached in normal operation. +// The buffer overflow check is purely defensive and should never trigger. +static int write_printf_buffer(FILE *stream, char *buf, int len) { + if (len < 0) { + return len; + } + size_t write_len = len; + if (write_len >= PRINTF_BUFFER_SIZE) { + fwrite(buf, 1, PRINTF_BUFFER_SIZE - 1, stream); + esp_system_abort("printf buffer overflow; set enable_full_printf: true in esp32 framework advanced config"); + } + if (fwrite(buf, 1, write_len, stream) < write_len || ferror(stream)) { + return -1; + } + return len; +} + +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +extern "C" { + +int __wrap_vprintf(const char *fmt, va_list ap) { + char buf[PRINTF_BUFFER_SIZE]; + return write_printf_buffer(stdout, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); +} + +int __wrap_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int len = __wrap_vprintf(fmt, ap); + va_end(ap); + return len; +} + +int __wrap_fprintf(FILE *stream, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char buf[PRINTF_BUFFER_SIZE]; + int len = write_printf_buffer(stream, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); + va_end(ap); + return len; +} + +} // extern "C" +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) + +#endif // USE_ESP_IDF && !USE_FULL_PRINTF diff --git a/tests/components/esp32/test.esp32-idf.yaml b/tests/components/esp32/test.esp32-idf.yaml index f80c854de5..da85aa3b0f 100644 --- a/tests/components/esp32/test.esp32-idf.yaml +++ b/tests/components/esp32/test.esp32-idf.yaml @@ -10,6 +10,7 @@ esp32: use_full_certificate_bundle: false # Test CMN bundle (default) include_builtin_idf_components: - freertos # Test escape hatch (freertos is always included anyway) + enable_full_printf: false disable_debug_stubs: true disable_ocd_aware: true disable_usb_serial_jtag_secondary: true From 6c0998f220fcd2d6ba1a3a12a6ebcfeef1166ace Mon Sep 17 00:00:00 2001 From: Raymond Richmond <raymond.richmond@gmail.com> Date: Sat, 28 Feb 2026 00:26:06 -0700 Subject: [PATCH 1011/2030] [gt911] Support for interrupt signal via IO Expander (#14358) --- .../components/gt911/touchscreen/__init__.py | 2 +- .../gt911/touchscreen/gt911_touchscreen.cpp | 29 ++++++++++++++----- .../gt911/touchscreen/gt911_touchscreen.h | 6 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/esphome/components/gt911/touchscreen/__init__.py b/esphome/components/gt911/touchscreen/__init__.py index 6c80ff280f..b850eeea8b 100644 --- a/esphome/components/gt911/touchscreen/__init__.py +++ b/esphome/components/gt911/touchscreen/__init__.py @@ -16,7 +16,7 @@ GT911Touchscreen = gt911_ns.class_( CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(GT911Touchscreen), - cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, + cv.Optional(CONF_INTERRUPT_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, } ).extend(i2c.i2c_device_schema(0x5D)) diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp index b11880a042..17bfa82cb4 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp @@ -2,6 +2,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/gpio.h" namespace esphome { namespace gt911 { @@ -26,15 +27,17 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned void GT911Touchscreen::setup() { if (this->reset_pin_ != nullptr) { + // temporarily set the interrupt pin to output to control address selection this->reset_pin_->setup(); this->reset_pin_->digital_write(false); if (this->interrupt_pin_ != nullptr) { - // temporarily set the interrupt pin to output to control address selection + this->interrupt_pin_->setup(); this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT); this->interrupt_pin_->digital_write(false); } delay(2); - this->reset_pin_->digital_write(true); // wait at least T3+T4 ms as per the datasheet + this->reset_pin_->digital_write(true); + // wait at least T3+T4 ms as per the datasheet this->set_timeout(5 + 50 + 1, [this] { this->setup_internal_(); }); return; } @@ -43,11 +46,10 @@ void GT911Touchscreen::setup() { void GT911Touchscreen::setup_internal_() { if (this->interrupt_pin_ != nullptr) { - // set pre-configured input mode - this->interrupt_pin_->setup(); + if (this->interrupt_pin_->is_internal()) + this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT); } - // check the configuration of the int line. uint8_t data[4]; i2c::ErrorCode err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES)); if (err != i2c::ERROR_OK && this->address_ == PRIMARY_ADDRESS) { @@ -58,12 +60,25 @@ void GT911Touchscreen::setup_internal_() { err = this->read(data, 1); if (err == i2c::ERROR_OK) { ESP_LOGD(TAG, "Switches ADDR: 0x%02X DATA: 0x%02X", this->address_, data[0]); + + // data[0] & 1 == 1 => controller uses falling edge => active-low + // data[0] & 1 == 0 => controller uses rising edge => active-high + bool active_high = !(data[0] & 1); + if (this->interrupt_pin_ != nullptr) { - this->attach_interrupt_(this->interrupt_pin_, - (data[0] & 1) ? gpio::INTERRUPT_FALLING_EDGE : gpio::INTERRUPT_RISING_EDGE); + if (this->interrupt_pin_->is_internal()) { + // Direct MCU pin: attach a hardware interrupt, no polling needed. + this->attach_interrupt_(static_cast<InternalGPIOPin *>(this->interrupt_pin_), + active_high ? gpio::INTERRUPT_RISING_EDGE : gpio::INTERRUPT_FALLING_EDGE); + ESP_LOGD(TAG, "Interrupt pin: hardware interrupt, active %s", active_high ? "HIGH" : "LOW"); + } else { + // IO expander pin: leave as output for configuration only. + ESP_LOGD(TAG, "Interrupt pin: IO expander polling mode, active %s", active_high ? "HIGH" : "LOW"); + } } } } + if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) { // no calibration? Attempt to read the max values from the touchscreen. if (err == i2c::ERROR_OK) { diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.h b/esphome/components/gt911/touchscreen/gt911_touchscreen.h index 85025b5522..a6577b5879 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.h +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.h @@ -30,7 +30,9 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice void dump_config() override; bool can_proceed() override { return this->setup_done_; } - void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } + /// Set a interrupt pin (supports hardware interrupts or expander connected). + void set_interrupt_pin(GPIOPin *pin) { this->interrupt_pin_ = pin; } + void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; } void register_button_listener(GT911ButtonListener *listener) { this->button_listeners_.push_back(listener); } @@ -49,7 +51,7 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice /// @brief True if the touchscreen setup has completed successfully. bool setup_done_{false}; - InternalGPIOPin *interrupt_pin_{nullptr}; + GPIOPin *interrupt_pin_{nullptr}; GPIOPin *reset_pin_{nullptr}; std::vector<GT911ButtonListener *> button_listeners_; uint8_t button_state_{0xFF}; // last button state. Initial FF guarantees first update. From 089d1e55e729c25755ab76196917db1f090ae5f2 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 28 Feb 2026 20:37:04 +1100 Subject: [PATCH 1012/2030] [mipi_dsi] Fix Waveshare P4 7B board config (#14372) --- esphome/components/mipi_dsi/models/waveshare.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/mipi_dsi/models/waveshare.py b/esphome/components/mipi_dsi/models/waveshare.py index 69414065f1..c97a0bbd02 100644 --- a/esphome/components/mipi_dsi/models/waveshare.py +++ b/esphome/components/mipi_dsi/models/waveshare.py @@ -103,8 +103,6 @@ DriverChip( (0xE9, 0xC8, 0x10, 0x0A, 0x00, 0x00, 0x80, 0x81, 0x12, 0x31, 0x23, 0x4F, 0x86, 0xA0, 0x00, 0x47, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x98, 0x02, 0x8B, 0xAF, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x13, 0x8B, 0xAF, 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), (0xEA, 0x97, 0x0C, 0x09, 0x09, 0x09, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x31, 0x8B, 0xA8, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9F, 0x20, 0x8B, 0xA8, 0x20, 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x00, 0x00, 0x00, 0x00), (0xEF, 0xFF, 0xFF, 0x01), - (0x11, 0x00), - (0x29, 0x00), ], ) @@ -125,6 +123,7 @@ DriverChip( lane_bit_rate="900Mbps", no_transform=True, color_order="RGB", + reset_pin=33, initsequence=[ (0x80, 0x8B), (0x81, 0x78), From 067d773aac5e1ca7911e2260b222b10b9e08444f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 07:19:55 -1000 Subject: [PATCH 1013/2030] [core] Make register_component protected, remove runtime checks (#14371) --- esphome/core/application.cpp | 19 +------------------ esphome/core/application.h | 13 ++++++------- esphome/cpp_helpers.py | 2 +- .../deep_sleep/test_deep_sleep.py | 2 +- .../ota/test_web_server_ota.py | 2 +- tests/dummy_main.cpp | 4 ++-- tests/unit_tests/test_cpp_helpers.py | 8 ++++---- 7 files changed, 16 insertions(+), 34 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index b1ece86701..f963afa597 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -79,24 +79,7 @@ static void insertion_sort_by_priority(Iterator first, Iterator last) { } } -void Application::register_component_(Component *comp) { - if (comp == nullptr) { - ESP_LOGW(TAG, "Tried to register null component!"); - return; - } - - for (auto *c : this->components_) { - if (comp == c) { - ESP_LOGW(TAG, "Component %s already registered! (%p)", LOG_STR_ARG(c->get_component_log_str()), c); - return; - } - } - if (this->components_.size() >= ESPHOME_COMPONENT_COUNT) { - ESP_LOGE(TAG, "Cannot register component %s - at capacity!", LOG_STR_ARG(comp->get_component_log_str())); - return; - } - this->components_.push_back(comp); -} +void Application::register_component_(Component *comp) { this->components_.push_back(comp); } void Application::setup() { ESP_LOGI(TAG, "Running through setup()"); ESP_LOGV(TAG, "Sorting components by setup priority"); diff --git a/esphome/core/application.h b/esphome/core/application.h index 0cc29af8e7..ba3ce13291 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -108,6 +108,10 @@ namespace esphome::socket { class Socket; } // namespace esphome::socket +// Forward declarations for friend access from codegen-generated setup() +void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h +void original_setup(); // NOLINT(readability-redundant-declaration) - used by cpp unit tests + namespace esphome { // Teardown timeout constant (in milliseconds) @@ -247,13 +251,6 @@ class Application { /// Reserve space for components to avoid memory fragmentation - /// Register the component in this Application instance. - template<class C> C *register_component(C *c) { - static_assert(std::is_base_of<Component, C>::value, "Only Component subclasses can be registered"); - this->register_component_((Component *) c); - return c; - } - /// Set up all the registered components. Call this at the end of your setup() function. void setup(); @@ -508,6 +505,8 @@ class Application { protected: friend Component; friend class socket::Socket; + friend void ::setup(); + friend void ::original_setup(); #ifdef USE_SOCKET_SELECT_SUPPORT /// Fast path for Socket::ready() via friendship - skips negative fd check. diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 954a28d3d1..b673eaa7e1 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -79,7 +79,7 @@ async def register_component(var, config): if name is not None: add(var.set_component_source(LogStringLiteral(name))) - add(App.register_component(var)) + add(App.register_component_(var)) return var diff --git a/tests/component_tests/deep_sleep/test_deep_sleep.py b/tests/component_tests/deep_sleep/test_deep_sleep.py index 11f1bcb58e..41ddd72feb 100644 --- a/tests/component_tests/deep_sleep/test_deep_sleep.py +++ b/tests/component_tests/deep_sleep/test_deep_sleep.py @@ -8,7 +8,7 @@ def test_deep_sleep_setup(generate_main): main_cpp = generate_main("tests/component_tests/deep_sleep/test_deep_sleep1.yaml") assert "deepsleep = new deep_sleep::DeepSleepComponent();" in main_cpp - assert "App.register_component(deepsleep);" in main_cpp + assert "App.register_component_(deepsleep);" in main_cpp def test_deep_sleep_sleep_duration(generate_main): diff --git a/tests/component_tests/ota/test_web_server_ota.py b/tests/component_tests/ota/test_web_server_ota.py index 794eaac9be..4b3a4c705c 100644 --- a/tests/component_tests/ota/test_web_server_ota.py +++ b/tests/component_tests/ota/test_web_server_ota.py @@ -27,7 +27,7 @@ def test_web_server_ota_generated(generate_main: Callable[[str], str]) -> None: assert "global_web_server_base" in main_cpp # Check component is registered - assert "App.register_component(web_server_webserverotacomponent_id)" in main_cpp + assert "App.register_component_(web_server_webserverotacomponent_id)" in main_cpp def test_web_server_ota_with_callbacks(generate_main: Callable[[str], str]) -> None: diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index 52f1fbd319..3ccf35e04d 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -16,10 +16,10 @@ void setup() { auto *log = new logger::Logger(115200); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); - App.register_component(log); + App.register_component_(log); auto *wifi = new wifi::WiFiComponent(); // NOLINT - App.register_component(wifi); + App.register_component_(wifi); wifi::WiFiAP ap; ap.set_ssid("Test SSID"); ap.set_password("password1"); diff --git a/tests/unit_tests/test_cpp_helpers.py b/tests/unit_tests/test_cpp_helpers.py index 2618803fec..82ded409c7 100644 --- a/tests/unit_tests/test_cpp_helpers.py +++ b/tests/unit_tests/test_cpp_helpers.py @@ -16,7 +16,7 @@ async def test_gpio_pin_expression__conf_is_none(monkeypatch): async def test_register_component(monkeypatch): var = Mock(base="foo.bar") - app_mock = Mock(register_component=Mock(return_value=var)) + app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) core_mock = Mock(component_ids=["foo.bar"]) @@ -29,7 +29,7 @@ async def test_register_component(monkeypatch): assert actual is var assert add_mock.call_count == 2 - app_mock.register_component.assert_called_with(var) + app_mock.register_component_.assert_called_with(var) assert core_mock.component_ids == [] @@ -48,7 +48,7 @@ async def test_register_component__no_component_id(monkeypatch): async def test_register_component__with_setup_priority(monkeypatch): var = Mock(base="foo.bar") - app_mock = Mock(register_component=Mock(return_value=var)) + app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) core_mock = Mock(component_ids=["foo.bar"]) @@ -68,5 +68,5 @@ async def test_register_component__with_setup_priority(monkeypatch): assert actual is var add_mock.assert_called() assert add_mock.call_count == 4 - app_mock.register_component.assert_called_with(var) + app_mock.register_component_.assert_called_with(var) assert core_mock.component_ids == [] From 7d52a9587f59c01a47c72bacb8c3d7e9f4d40e30 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 07:20:20 -1000 Subject: [PATCH 1014/2030] [api] Outline keepalive ping logic from APIConnection::loop() (#14374) --- esphome/components/api/api_connection.cpp | 46 ++++++++++++++--------- esphome/components/api/api_connection.h | 4 ++ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 7bc9c45c05..8b2efdde51 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -242,24 +242,11 @@ void APIConnection::loop() { return; } - if (this->flags_.sent_ping) { - // Disconnect if not responded within 2.5*keepalive - if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) { - on_fatal_error(); - this->log_client_(ESPHOME_LOG_LEVEL_WARN, LOG_STR("is unresponsive; disconnecting")); - } - } else if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS && !this->flags_.remove) { - // Only send ping if we're not disconnecting - ESP_LOGVV(TAG, "Sending keepalive PING"); - PingRequest req; - this->flags_.sent_ping = this->send_message(req, PingRequest::MESSAGE_TYPE); - if (!this->flags_.sent_ping) { - // If we can't send the ping request directly (tx_buffer full), - // schedule it at the front of the batch so it will be sent with priority - ESP_LOGW(TAG, "Buffer full, ping queued"); - this->schedule_message_front_(nullptr, PingRequest::MESSAGE_TYPE, PingRequest::ESTIMATED_SIZE); - this->flags_.sent_ping = true; // Mark as sent to avoid scheduling multiple pings - } + // Keepalive: only call into the cold path when enough time has elapsed. + // When sent_ping is true, last_traffic_ hasn't been updated so this + // condition is already satisfied — covers both send-ping and disconnect cases. + if (now - this->last_traffic_ > KEEPALIVE_TIMEOUT_MS) { + this->check_keepalive_(now); } #ifdef USE_API_HOMEASSISTANT_STATES @@ -275,6 +262,29 @@ void APIConnection::loop() { #endif } +void APIConnection::check_keepalive_(uint32_t now) { + // Caller guarantees: now - last_traffic_ > KEEPALIVE_TIMEOUT_MS + if (this->flags_.sent_ping) { + // Disconnect if not responded within 2.5*keepalive + if (now - this->last_traffic_ > KEEPALIVE_DISCONNECT_TIMEOUT) { + on_fatal_error(); + this->log_client_(ESPHOME_LOG_LEVEL_WARN, LOG_STR("is unresponsive; disconnecting")); + } + } else if (!this->flags_.remove) { + // Only send ping if we're not disconnecting + ESP_LOGVV(TAG, "Sending keepalive PING"); + PingRequest req; + this->flags_.sent_ping = this->send_message(req, PingRequest::MESSAGE_TYPE); + if (!this->flags_.sent_ping) { + // If we can't send the ping request directly (tx_buffer full), + // schedule it at the front of the batch so it will be sent with priority + ESP_LOGW(TAG, "Buffer full, ping queued"); + this->schedule_message_front_(nullptr, PingRequest::MESSAGE_TYPE, PingRequest::ESTIMATED_SIZE); + this->flags_.sent_ping = true; // Mark as sent to avoid scheduling multiple pings + } + } +} + void APIConnection::process_active_iterator_() { // Caller ensures active_iterator_ != NONE if (this->active_iterator_ == ActiveIterator::LIST_ENTITIES) { diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index e34bed8ada..37855b2482 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -370,6 +370,10 @@ class APIConnection final : public APIServerConnectionBase { return this->client_supports_api_version(1, 14) ? MAX_INITIAL_PER_BATCH : MAX_INITIAL_PER_BATCH_LEGACY; } + // Send keepalive ping or disconnect unresponsive client. + // Cold path — extracted from loop() to reduce instruction cache pressure. + void __attribute__((noinline)) check_keepalive_(uint32_t now); + // Process active iterator (list_entities/initial_state) during connection setup. // Extracted from loop() — only runs during initial handshake, NONE in steady state. void __attribute__((noinline)) process_active_iterator_(); From 757e8d90e6a32fb77cad14efb9e00e34e584fee2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 07:20:34 -1000 Subject: [PATCH 1015/2030] [core] Inline set_component_state_ and use it in Application (#14369) --- esphome/core/application.cpp | 3 +-- esphome/core/component.cpp | 4 ---- esphome/core/component.h | 5 ++++- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index f963afa597..c977fd66b3 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -508,8 +508,7 @@ void Application::enable_pending_loops_() { // Clear the pending flag and enable the loop component->pending_enable_loop_ = false; ESP_LOGVV(TAG, "%s loop enabled from ISR", LOG_STR_ARG(component->get_component_log_str())); - component->component_state_ &= ~COMPONENT_STATE_MASK; - component->component_state_ |= COMPONENT_STATE_LOOP; + component->set_component_state_(COMPONENT_STATE_LOOP); // Move to active section this->activate_looping_component_(i); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index e14fae5e08..1fd621ea83 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -297,10 +297,6 @@ void Component::mark_failed() { // Also remove from loop since failed components shouldn't loop App.disable_component_loop_(this); } -void Component::set_component_state_(uint8_t state) { - this->component_state_ &= ~COMPONENT_STATE_MASK; - this->component_state_ |= state; -} void Component::disable_loop() { if ((this->component_state_ & COMPONENT_STATE_MASK) != COMPONENT_STATE_LOOP_DONE) { ESP_LOGVV(TAG, "%s loop disabled", LOG_STR_ARG(this->get_component_log_str())); diff --git a/esphome/core/component.h b/esphome/core/component.h index 2620e8eb2a..0b0b6345c7 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -294,7 +294,10 @@ class Component { void call_dump_config_(); /// Helper to set component state (clears state bits and sets new state) - void set_component_state_(uint8_t state); + inline void set_component_state_(uint8_t state) { + this->component_state_ &= ~COMPONENT_STATE_MASK; + this->component_state_ |= state; + } /** Set an interval function with a unique name. Empty name means no cancelling possible. * From b7d651dd179ad165e9921bd9c7840de58da3987a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 28 Feb 2026 18:10:53 -0500 Subject: [PATCH 1016/2030] [core] Defer entity automation codegen to prevent sibling ID deadlocks (#14381) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/binary_sensor/__init__.py | 37 +++++++++++--------- esphome/components/number/__init__.py | 31 +++++++++------- esphome/components/sensor/__init__.py | 37 +++++++++++--------- esphome/components/switch/__init__.py | 16 ++++++--- esphome/components/text_sensor/__init__.py | 19 ++++++---- 5 files changed, 83 insertions(+), 57 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 4500168cb1..036d78da73 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -550,22 +550,8 @@ def binary_sensor_schema( return _BINARY_SENSOR_SCHEMA.extend(schema) -async def setup_binary_sensor_core_(var, config): - await setup_entity(var, config, "binary_sensor") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) - trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get( - CONF_PUBLISH_INITIAL_STATE, False - ) - cg.add(var.set_trigger_on_initial_state(trigger)) - if inverted := config.get(CONF_INVERTED): - cg.add(var.set_inverted(inverted)) - if filters_config := config.get(CONF_FILTERS): - cg.add_define("USE_BINARY_SENSOR_FILTER") - filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config) - cg.add(var.add_filters(filters)) - +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_binary_sensor_automations(var, config): for conf in config.get(CONF_ON_PRESS, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) @@ -617,6 +603,25 @@ async def setup_binary_sensor_core_(var, config): conf, ) + +async def setup_binary_sensor_core_(var, config): + await setup_entity(var, config, "binary_sensor") + + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: + cg.add(var.set_device_class(device_class)) + trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get( + CONF_PUBLISH_INITIAL_STATE, False + ) + cg.add(var.set_trigger_on_initial_state(trigger)) + if inverted := config.get(CONF_INVERTED): + cg.add(var.set_inverted(inverted)) + if filters_config := config.get(CONF_FILTERS): + cg.add_define("USE_BINARY_SENSOR_FILTER") + filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config) + cg.add(var.add_filters(filters)) + + CORE.add_job(_build_binary_sensor_automations, var, config) + if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index b23da7799f..d12ec7463b 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -240,6 +240,23 @@ def number_schema( return _NUMBER_SCHEMA.extend(schema) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_number_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_VALUE_RANGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await cg.register_component(trigger, conf) + if CONF_ABOVE in conf: + template_ = await cg.templatable(conf[CONF_ABOVE], [(float, "x")], float) + cg.add(trigger.set_min(template_)) + if CONF_BELOW in conf: + template_ = await cg.templatable(conf[CONF_BELOW], [(float, "x")], float) + cg.add(trigger.set_max(template_)) + await automation.build_automation(trigger, [(float, "x")], conf) + + async def setup_number_core_( var, config, *, min_value: float, max_value: float, step: float ): @@ -254,19 +271,7 @@ async def setup_number_core_( if config[CONF_MODE] != NumberMode.NUMBER_MODE_AUTO: cg.add(var.traits.set_mode(config[CONF_MODE])) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_VALUE_RANGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await cg.register_component(trigger, conf) - if CONF_ABOVE in conf: - template_ = await cg.templatable(conf[CONF_ABOVE], [(float, "x")], float) - cg.add(trigger.set_min(template_)) - if CONF_BELOW in conf: - template_ = await cg.templatable(conf[CONF_BELOW], [(float, "x")], float) - cg.add(trigger.set_max(template_)) - await automation.build_automation(trigger, [(float, "x")], conf) + CORE.add_job(_build_number_automations, var, config) if (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) is not None: cg.add(var.traits.set_unit_of_measurement(unit_of_measurement)) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 770c044efb..338aaae0b5 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -888,6 +888,26 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_sensor_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_RAW_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_VALUE_RANGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await cg.register_component(trigger, conf) + if (above := conf.get(CONF_ABOVE)) is not None: + template_ = await cg.templatable(above, [(float, "x")], float) + cg.add(trigger.set_min(template_)) + if (below := conf.get(CONF_BELOW)) is not None: + template_ = await cg.templatable(below, [(float, "x")], float) + cg.add(trigger.set_max(template_)) + await automation.build_automation(trigger, [(float, "x")], conf) + + async def setup_sensor_core_(var, config): await setup_entity(var, config, "sensor") @@ -907,22 +927,7 @@ async def setup_sensor_core_(var, config): filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_VALUE_RANGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await cg.register_component(trigger, conf) - if (above := conf.get(CONF_ABOVE)) is not None: - template_ = await cg.templatable(above, [(float, "x")], float) - cg.add(trigger.set_min(template_)) - if (below := conf.get(CONF_BELOW)) is not None: - template_ = await cg.templatable(below, [(float, "x")], float) - cg.add(trigger.set_max(template_)) - await automation.build_automation(trigger, [(float, "x")], conf) + CORE.add_job(_build_sensor_automations, var, config) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 7424d7c92f..cfc5e2b6e8 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -141,11 +141,8 @@ def switch_schema( return _SWITCH_SCHEMA.extend(schema) -async def setup_switch_core_(var, config): - await setup_entity(var, config, "switch") - - if (inverted := config.get(CONF_INVERTED)) is not None: - cg.add(var.set_inverted(inverted)) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_switch_automations(var, config): for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(bool, "x")], conf) @@ -156,6 +153,15 @@ async def setup_switch_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + +async def setup_switch_core_(var, config): + await setup_entity(var, config, "switch") + + if (inverted := config.get(CONF_INVERTED)) is not None: + cg.add(var.set_inverted(inverted)) + + CORE.add_job(_build_switch_automations, var, config) + if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 2e8edb43c9..2edf202cd2 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -197,6 +197,17 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_text_sensor_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + + for conf in config.get(CONF_ON_RAW_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + + async def setup_text_sensor_core_(var, config): await setup_entity(var, config, "text_sensor") @@ -208,13 +219,7 @@ async def setup_text_sensor_core_(var, config): filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + CORE.add_job(_build_text_sensor_automations, var, config) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) From b679b04d140663770f4a5c4be16e1c9ed93de5c7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 13:27:33 -1000 Subject: [PATCH 1017/2030] [core] Move CONF_STOP_BITS, CONF_DATA_BITS, CONF_PARITY to const.py (#14379) --- esphome/components/uart/__init__.py | 6 +++--- esphome/components/usb_uart/__init__.py | 10 ++++------ esphome/components/weikai/__init__.py | 6 +++--- esphome/const.py | 3 +++ 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 31e37a06e0..a6f4cf5d5f 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_BAUD_RATE, CONF_BYTES, CONF_DATA, + CONF_DATA_BITS, CONF_DEBUG, CONF_DELIMITER, CONF_DIRECTION, @@ -21,10 +22,12 @@ from esphome.const import ( CONF_ID, CONF_LAMBDA, CONF_NUMBER, + CONF_PARITY, CONF_PORT, CONF_RX_BUFFER_SIZE, CONF_RX_PIN, CONF_SEQUENCE, + CONF_STOP_BITS, CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_TX_PIN, @@ -215,9 +218,6 @@ UART_PARITY_OPTIONS = { "ODD": UARTParityOptions.UART_CONFIG_PARITY_ODD, } -CONF_STOP_BITS = "stop_bits" -CONF_DATA_BITS = "data_bits" -CONF_PARITY = "parity" CONF_RX_FULL_THRESHOLD = "rx_full_threshold" CONF_RX_TIMEOUT = "rx_timeout" diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index d9bb58ae3a..cc69c0cb5a 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -1,20 +1,18 @@ import esphome.codegen as cg from esphome.components import socket -from esphome.components.uart import ( - CONF_DATA_BITS, - CONF_PARITY, - CONF_STOP_BITS, - UARTComponent, -) +from esphome.components.uart import UARTComponent from esphome.components.usb_host import register_usb_client, usb_device_schema import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, CONF_BUFFER_SIZE, CONF_CHANNELS, + CONF_DATA_BITS, CONF_DEBUG, CONF_DUMMY_RECEIVER, CONF_ID, + CONF_PARITY, + CONF_STOP_BITS, ) from esphome.cpp_types import Component diff --git a/esphome/components/weikai/__init__.py b/esphome/components/weikai/__init__.py index 796423438e..66cd4ce12a 100644 --- a/esphome/components/weikai/__init__.py +++ b/esphome/components/weikai/__init__.py @@ -4,21 +4,21 @@ import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, CONF_CHANNEL, + CONF_DATA_BITS, CONF_ID, CONF_INPUT, CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_OUTPUT, + CONF_PARITY, + CONF_STOP_BITS, ) CODEOWNERS = ["@DrCoolZic"] AUTO_LOAD = ["uart"] MULTI_CONF = True -CONF_DATA_BITS = "data_bits" -CONF_STOP_BITS = "stop_bits" -CONF_PARITY = "parity" CONF_CRYSTAL = "crystal" CONF_UART = "uart" CONF_TEST_MODE = "test_mode" diff --git a/esphome/const.py b/esphome/const.py index 1611aeb101..7262a106d8 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -280,6 +280,7 @@ CONF_CUSTOM_PRESETS = "custom_presets" CONF_CYCLE = "cycle" CONF_DALLAS_ID = "dallas_id" CONF_DATA = "data" +CONF_DATA_BITS = "data_bits" CONF_DATA_PIN = "data_pin" CONF_DATA_PINS = "data_pins" CONF_DATA_RATE = "data_rate" @@ -759,6 +760,7 @@ CONF_PAGE_ID = "page_id" CONF_PAGES = "pages" CONF_PANASONIC = "panasonic" CONF_PARAMETERS = "parameters" +CONF_PARITY = "parity" CONF_PASSWORD = "password" CONF_PATH = "path" CONF_PATTERN = "pattern" @@ -961,6 +963,7 @@ CONF_STEP_PIN = "step_pin" CONF_STILL_THRESHOLD = "still_threshold" CONF_STOP = "stop" CONF_STOP_ACTION = "stop_action" +CONF_STOP_BITS = "stop_bits" CONF_STORE_BASELINE = "store_baseline" CONF_SUBNET = "subnet" CONF_SUBSCRIBE_QOS = "subscribe_qos" From 28424d6acdb5a406f650d3f6133eb67f19304f2c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 13:50:12 -1000 Subject: [PATCH 1018/2030] [ld2410][ld2412] Fix signed char causing incorrect distance values (#14380) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ld2410/ld2410.cpp | 21 ++++++++------------- esphome/components/ld2412/ld2412.cpp | 23 +++++++++-------------- 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/esphome/components/ld2410/ld2410.cpp b/esphome/components/ld2410/ld2410.cpp index dd1d53857d..f10e7ec0aa 100644 --- a/esphome/components/ld2410/ld2410.cpp +++ b/esphome/components/ld2410/ld2410.cpp @@ -173,8 +173,6 @@ static constexpr uint8_t DATA_FRAME_FOOTER[HEADER_FOOTER_SIZE] = {0xF8, 0xF7, 0x // MAC address the module uses when Bluetooth is disabled static constexpr uint8_t NO_MAC[] = {0x08, 0x05, 0x04, 0x03, 0x02, 0x01}; -static inline int two_byte_to_int(char firstbyte, char secondbyte) { return (int16_t) (secondbyte << 8) + firstbyte; } - static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) { return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0; } @@ -361,17 +359,14 @@ void LD2410Component::handle_periodic_data_() { Detect distance: 16~17th bytes */ #ifdef USE_SENSOR - SAFE_PUBLISH_SENSOR( - this->moving_target_distance_sensor_, - ld2410::two_byte_to_int(this->buffer_data_[MOVING_TARGET_LOW], this->buffer_data_[MOVING_TARGET_HIGH])) + SAFE_PUBLISH_SENSOR(this->moving_target_distance_sensor_, + encode_uint16(this->buffer_data_[MOVING_TARGET_HIGH], this->buffer_data_[MOVING_TARGET_LOW])) SAFE_PUBLISH_SENSOR(this->moving_target_energy_sensor_, this->buffer_data_[MOVING_ENERGY]) - SAFE_PUBLISH_SENSOR( - this->still_target_distance_sensor_, - ld2410::two_byte_to_int(this->buffer_data_[STILL_TARGET_LOW], this->buffer_data_[STILL_TARGET_HIGH])); + SAFE_PUBLISH_SENSOR(this->still_target_distance_sensor_, + encode_uint16(this->buffer_data_[STILL_TARGET_HIGH], this->buffer_data_[STILL_TARGET_LOW])); SAFE_PUBLISH_SENSOR(this->still_target_energy_sensor_, this->buffer_data_[STILL_ENERGY]); - SAFE_PUBLISH_SENSOR( - this->detection_distance_sensor_, - ld2410::two_byte_to_int(this->buffer_data_[DETECT_DISTANCE_LOW], this->buffer_data_[DETECT_DISTANCE_HIGH])); + SAFE_PUBLISH_SENSOR(this->detection_distance_sensor_, + encode_uint16(this->buffer_data_[DETECT_DISTANCE_HIGH], this->buffer_data_[DETECT_DISTANCE_LOW])); if (engineering_mode) { /* @@ -578,8 +573,8 @@ bool LD2410Component::handle_ack_data_() { /* None Duration: 33~34th bytes */ - updates.push_back(set_number_value(this->timeout_number_, - ld2410::two_byte_to_int(this->buffer_data_[32], this->buffer_data_[33]))); + updates.push_back( + set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[33], this->buffer_data_[32]))); for (auto &update : updates) { update(); } diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 484d5bd281..ef0915d0bc 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -192,8 +192,6 @@ static constexpr uint8_t DATA_FRAME_FOOTER[HEADER_FOOTER_SIZE] = {0xF8, 0xF7, 0x // MAC address the module uses when Bluetooth is disabled static constexpr uint8_t NO_MAC[] = {0x08, 0x05, 0x04, 0x03, 0x02, 0x01}; -static inline int two_byte_to_int(char firstbyte, char secondbyte) { return (int16_t) (secondbyte << 8) + firstbyte; } - static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) { return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0; } @@ -398,22 +396,19 @@ void LD2412Component::handle_periodic_data_() { Detect distance: 16~17th bytes */ #ifdef USE_SENSOR - SAFE_PUBLISH_SENSOR( - this->moving_target_distance_sensor_, - ld2412::two_byte_to_int(this->buffer_data_[MOVING_TARGET_LOW], this->buffer_data_[MOVING_TARGET_HIGH])) + SAFE_PUBLISH_SENSOR(this->moving_target_distance_sensor_, + encode_uint16(this->buffer_data_[MOVING_TARGET_HIGH], this->buffer_data_[MOVING_TARGET_LOW])) SAFE_PUBLISH_SENSOR(this->moving_target_energy_sensor_, this->buffer_data_[MOVING_ENERGY]) - SAFE_PUBLISH_SENSOR( - this->still_target_distance_sensor_, - ld2412::two_byte_to_int(this->buffer_data_[STILL_TARGET_LOW], this->buffer_data_[STILL_TARGET_HIGH])) + SAFE_PUBLISH_SENSOR(this->still_target_distance_sensor_, + encode_uint16(this->buffer_data_[STILL_TARGET_HIGH], this->buffer_data_[STILL_TARGET_LOW])) SAFE_PUBLISH_SENSOR(this->still_target_energy_sensor_, this->buffer_data_[STILL_ENERGY]) if (this->detection_distance_sensor_ != nullptr) { int new_detect_distance = 0; if (target_state != 0x00 && (target_state & MOVE_BITMASK)) { new_detect_distance = - ld2412::two_byte_to_int(this->buffer_data_[MOVING_TARGET_LOW], this->buffer_data_[MOVING_TARGET_HIGH]); + encode_uint16(this->buffer_data_[MOVING_TARGET_HIGH], this->buffer_data_[MOVING_TARGET_LOW]); } else if (target_state != 0x00) { - new_detect_distance = - ld2412::two_byte_to_int(this->buffer_data_[STILL_TARGET_LOW], this->buffer_data_[STILL_TARGET_HIGH]); + new_detect_distance = encode_uint16(this->buffer_data_[STILL_TARGET_HIGH], this->buffer_data_[STILL_TARGET_LOW]); } this->detection_distance_sensor_->publish_state_if_not_dup(new_detect_distance); } @@ -637,9 +632,9 @@ bool LD2412Component::handle_ack_data_() { /* None Duration: 11~12th bytes */ - updates.push_back(set_number_value(this->timeout_number_, - ld2412::two_byte_to_int(this->buffer_data_[12], this->buffer_data_[13]))); - ESP_LOGV(TAG, "timeout_number_: %u", ld2412::two_byte_to_int(this->buffer_data_[12], this->buffer_data_[13])); + updates.push_back( + set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12]))); + ESP_LOGV(TAG, "timeout_number_: %u", encode_uint16(this->buffer_data_[13], this->buffer_data_[12])); /* Output pin configuration: 13th bytes */ From fdbfac15db79a329629173c1d6ba967f12b43e46 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:21:08 -1000 Subject: [PATCH 1019/2030] [uart] Replace wake-on-RX task+queue with direct ISR callback (#14382) --- .../uart/uart_component_esp_idf.cpp | 101 +++--------------- .../components/uart/uart_component_esp_idf.h | 21 ++-- esphome/core/application.h | 10 ++ esphome/core/lwip_fast_select.c | 14 +++ esphome/core/lwip_fast_select.h | 5 + 5 files changed, 52 insertions(+), 99 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 8699d37d7a..631db1e5c7 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -2,7 +2,6 @@ #include "uart_component_esp_idf.h" #include <cinttypes> -#include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -10,6 +9,10 @@ #include "driver/gpio.h" #include "soc/gpio_num.h" +#ifdef USE_UART_WAKE_LOOP_ON_RX +#include "esphome/core/application.h" +#endif + #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" #endif @@ -107,12 +110,6 @@ void IDFUARTComponent::load_settings(bool dump_config) { esp_err_t err; if (uart_is_driver_installed(this->uart_num_)) { -#ifdef USE_UART_WAKE_LOOP_ON_RX - if (this->rx_event_task_handle_ != nullptr) { - vTaskDelete(this->rx_event_task_handle_); - this->rx_event_task_handle_ = nullptr; - } -#endif err = uart_driver_delete(this->uart_num_); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_driver_delete failed: %s", esp_err_to_name(err)); @@ -120,20 +117,13 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } } -#ifdef USE_UART_WAKE_LOOP_ON_RX - constexpr int event_queue_size = 20; - QueueHandle_t *event_queue_ptr = &this->uart_event_queue_; -#else - constexpr int event_queue_size = 0; - QueueHandle_t *event_queue_ptr = nullptr; -#endif err = uart_driver_install(this->uart_num_, // UART number this->rx_buffer_size_, // RX ring buffer size 0, // TX ring buffer size. If zero, driver will not use a TX buffer and TX function will // block task until all data has been sent out - event_queue_size, // event queue size/depth - event_queue_ptr, // event queue - 0 // Flags used to allocate the interrupt + 0, // event queue size/depth + nullptr, // event queue + 0 // Flags used to allocate the interrupt ); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_driver_install failed: %s", esp_err_to_name(err)); @@ -213,8 +203,10 @@ void IDFUARTComponent::load_settings(bool dump_config) { } #ifdef USE_UART_WAKE_LOOP_ON_RX - // Start the RX event task to enable low-latency data notifications - this->start_rx_event_task_(); + // Register ISR callback to wake the main loop when UART data arrives. + // The callback runs in ISR context and uses vTaskNotifyGiveFromISR() to + // wake the main loop task directly — no queue or FreeRTOS task needed. + uart_set_select_notif_callback(this->uart_num_, IDFUARTComponent::uart_rx_isr_callback); #endif // USE_UART_WAKE_LOOP_ON_RX if (dump_config) { @@ -345,71 +337,12 @@ void IDFUARTComponent::flush() { void IDFUARTComponent::check_logger_conflict() {} #ifdef USE_UART_WAKE_LOOP_ON_RX -void IDFUARTComponent::start_rx_event_task_() { - // Create FreeRTOS task to monitor UART events - BaseType_t result = xTaskCreate(rx_event_task_func, // Task function - "uart_rx_evt", // Task name (max 16 chars) - 2240, // Stack size in bytes (~2.2KB); increase if needed for logging - this, // Task parameter (this pointer) - tskIDLE_PRIORITY + 1, // Priority (low, just above idle) - &this->rx_event_task_handle_ // Task handle - ); - - if (result != pdPASS) { - ESP_LOGE(TAG, "Failed to create RX event task"); - return; - } - - ESP_LOGV(TAG, "RX event task started"); -} - -// FreeRTOS task that relays UART ISR events to the main loop. -// This task exists because wake_loop_threadsafe() is not ISR-safe (it uses a -// UDP loopback socket), so we need a task as an ISR-to-main-loop trampoline. -// IMPORTANT: This task must NOT call any UART wrapper methods (read_array, -// write_array, peek_byte, etc.) or touch has_peek_/peek_byte_ — all reading -// is done by the main loop. This task only reads from the event queue and -// calls App.wake_loop_threadsafe(). -void IDFUARTComponent::rx_event_task_func(void *param) { - auto *self = static_cast<IDFUARTComponent *>(param); - uart_event_t event; - - ESP_LOGV(TAG, "RX event task running"); - - // Run forever - task lifecycle matches component lifecycle - while (true) { - // Wait for UART events (blocks efficiently) - if (xQueueReceive(self->uart_event_queue_, &event, portMAX_DELAY) == pdTRUE) { - switch (event.type) { - case UART_DATA: - // Data available in UART RX buffer - wake the main loop - ESP_LOGVV(TAG, "Data event: %d bytes", event.size); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); -#endif - break; - - case UART_FIFO_OVF: - case UART_BUFFER_FULL: - // Don't call uart_flush_input() here — this task does not own the read side. - // ESP-IDF examples flush on overflow because the same task handles both events - // and reads, so flush and read are serialized. Here, reads happen on the main - // loop, so flushing from this task races with read_array() and can destroy data - // mid-read. The driver self-heals without an explicit flush: uart_read_bytes() - // calls uart_check_buf_full() after each chunk, which moves stashed FIFO bytes - // into the ring buffer and re-enables RX interrupts once space is freed. - ESP_LOGW(TAG, "FIFO overflow or ring buffer full"); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); -#endif - break; - - default: - // Ignore other event types - ESP_LOGVV(TAG, "Event type: %d", event.type); - break; - } - } +// ISR callback invoked by the ESP-IDF UART driver when data arrives. +// Wakes the main loop directly via vTaskNotifyGiveFromISR() — no queue or task needed. +void IRAM_ATTR IDFUARTComponent::uart_rx_isr_callback(uart_port_t uart_num, uart_select_notif_t uart_select_notif, + BaseType_t *task_woken) { + if (uart_select_notif == UART_SELECT_READ_NOTIF) { + Application::wake_loop_isrsafe(task_woken); } } #endif // USE_UART_WAKE_LOOP_ON_RX diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index 1517eab509..631bf54cd5 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -5,6 +5,9 @@ #include <driver/uart.h> #include "esphome/core/component.h" #include "uart_component.h" +#ifdef USE_UART_WAKE_LOOP_ON_RX +#include <driver/uart_select.h> +#endif namespace esphome::uart { @@ -12,9 +15,7 @@ namespace esphome::uart { /// /// Thread safety: All public methods must only be called from the main loop. /// The ESP-IDF UART driver API does not guarantee thread safety, and ESPHome's -/// peek byte state (has_peek_/peek_byte_) is not synchronized. The rx_event_task -/// (when enabled) must not call any of these methods — it communicates with the -/// main loop exclusively via App.wake_loop_threadsafe(). +/// peek byte state (has_peek_/peek_byte_) is not synchronized. class IDFUARTComponent : public UARTComponent, public Component { public: void setup() override; @@ -33,9 +34,6 @@ class IDFUARTComponent : public UARTComponent, public Component { void flush() override; uint8_t get_hw_serial_number() { return this->uart_num_; } -#ifdef USE_UART_WAKE_LOOP_ON_RX - QueueHandle_t *get_uart_event_queue() { return &this->uart_event_queue_; } -#endif /** * Load the UART with the current settings. @@ -61,15 +59,8 @@ class IDFUARTComponent : public UARTComponent, public Component { uint8_t peek_byte_; #ifdef USE_UART_WAKE_LOOP_ON_RX - // RX notification support — runs on a separate FreeRTOS task. - // IMPORTANT: rx_event_task_func must NOT call any UART wrapper methods (read_array, - // write_array, etc.) or touch has_peek_/peek_byte_. It must only read from the - // event queue and call App.wake_loop_threadsafe(). - void start_rx_event_task_(); - static void rx_event_task_func(void *param); - - QueueHandle_t uart_event_queue_; - TaskHandle_t rx_event_task_handle_{nullptr}; + // ISR callback for UART RX data notification — wakes the main loop directly. + static void uart_rx_isr_callback(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken); #endif // USE_UART_WAKE_LOOP_ON_RX }; diff --git a/esphome/core/application.h b/esphome/core/application.h index ba3ce13291..13e0f63885 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -500,6 +500,16 @@ class Application { /// On other platforms: uses UDP loopback socket void wake_loop_threadsafe(); #endif + +#if defined(USE_WAKE_LOOP_THREADSAFE) && defined(USE_LWIP_FAST_SELECT) + /// Wake the main event loop from an ISR. + /// Uses vTaskNotifyGiveFromISR() — <1 us, ISR-safe. + /// Only available on platforms with fast select (ESP32, LibreTiny). + /// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. + static void IRAM_ATTR wake_loop_isrsafe(int *px_higher_priority_task_woken) { + esphome_lwip_wake_main_loop_from_isr(px_higher_priority_task_woken); + } +#endif #endif protected: diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index 88cf23b67e..da0f1f337a 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -126,6 +126,12 @@ #include <stddef.h> +// IRAM_ATTR is defined by esp_attr.h (included via FreeRTOS headers) on ESP32. +// On LibreTiny it's not defined — provide a no-op fallback. +#ifndef IRAM_ATTR +#define IRAM_ATTR +#endif + // Compile-time verification of thread safety assumptions. // On ESP32 (Xtensa/RISC-V) and LibreTiny (ARM Cortex-M), naturally-aligned // reads/writes up to 32 bits are atomic. @@ -225,4 +231,12 @@ void esphome_lwip_wake_main_loop(void) { } } +// Wake the main loop from an ISR. ISR-safe variant. +void IRAM_ATTR esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken) { + TaskHandle_t task = s_main_loop_task; + if (task != NULL) { + vTaskNotifyGiveFromISR(task, (BaseType_t *) px_higher_priority_task_woken); + } +} + #endif // defined(USE_ESP32) || defined(USE_LIBRETINY) diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index b08c946212..b7a70a8f9f 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -28,6 +28,11 @@ void esphome_lwip_hook_socket(int fd); /// NOT ISR-safe — must only be called from task context. void esphome_lwip_wake_main_loop(void); +/// Wake the main loop task from an ISR — costs <1 us. +/// ISR-safe variant using vTaskNotifyGiveFromISR(). +/// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. +void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); + #ifdef __cplusplus } #endif From b7cb65ec4996ba6c1b768908555f53586eb37d4b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:23:20 -1000 Subject: [PATCH 1020/2030] [ci] Fix TypeError in ci-custom.py when POST lint checks fail (#14378) --- script/ci-custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/ci-custom.py b/script/ci-custom.py index 85a446ba0d..f428eb0821 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -959,7 +959,7 @@ def main(): continue run_checks(LINT_CONTENT_CHECKS, fname, fname, content) - run_checks(LINT_POST_CHECKS, "POST") + run_checks(LINT_POST_CHECKS, Path("POST")) for f, errs in sorted(errors.items()): bold = functools.partial(styled, colorama.Style.BRIGHT) From c0781d3680f6c816510f7417eeb4523964e08575 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:26:08 -1000 Subject: [PATCH 1021/2030] [ld2450] Use atan2f for angle calculation (#14388) --- esphome/components/ld2450/ld2450.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index d30c164769..5ec3ce47d7 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -168,15 +168,6 @@ static inline int16_t hex_to_signed_int(const uint8_t *buffer, uint8_t offset) { return dec_val; } -static inline float calculate_angle(float base, float hypotenuse) { - if (base < 0.0f || hypotenuse <= 0.0f) { - return 0.0f; - } - float angle_radians = acosf(base / hypotenuse); - float angle_degrees = angle_radians * (180.0f / std::numbers::pi_v<float>); - return angle_degrees; -} - static inline bool validate_header_footer(const uint8_t *header_footer, const uint8_t *buffer) { return std::memcmp(header_footer, buffer, HEADER_FOOTER_SIZE) == 0; } @@ -510,11 +501,8 @@ void LD2450Component::handle_periodic_data_() { } #ifdef USE_SENSOR SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td); - // ANGLE - angle = ld2450::calculate_angle(static_cast<float>(ty), static_cast<float>(td)); - if (tx > 0) { - angle = angle * -1; - } + // ANGLE - atan2f computes angle from Y axis directly, no sqrt/division needed + angle = atan2f(static_cast<float>(-tx), static_cast<float>(ty)) * (180.0f / std::numbers::pi_v<float>); SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle); #endif #ifdef USE_TEXT_SENSOR From 80e0761bf1c1085296aa785405e57e2c16cc6e38 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:26:31 -1000 Subject: [PATCH 1022/2030] [ld2450] Use integer dedup for direction text sensor updates (#14386) --- esphome/components/ld2450/ld2450.cpp | 9 +++++---- esphome/components/ld2450/ld2450.h | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 5ec3ce47d7..ca64836bf8 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -516,10 +516,11 @@ void LD2450Component::handle_periodic_data_() { } else { direction = DIRECTION_STATIONARY; } - text_sensor::TextSensor *tsd = this->direction_text_sensors_[index]; - const auto *dir_str = find_str(ld2450::DIRECTION_BY_UINT, direction); - if (tsd != nullptr && (!tsd->has_state() || tsd->get_state() != dir_str)) { - tsd->publish_state(dir_str); + if (this->direction_dedup_[index].next(direction)) { + text_sensor::TextSensor *tsd = this->direction_text_sensors_[index]; + if (tsd != nullptr) { + tsd->publish_state(find_str(ld2450::DIRECTION_BY_UINT, direction)); + } } #endif diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 30f96c0a9c..518b320b0a 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -194,7 +194,8 @@ class LD2450Component : public Component, public uart::UARTDevice { std::array<SensorWithDedup<uint8_t> *, MAX_ZONES> zone_moving_target_count_sensors_{}; #endif #ifdef USE_TEXT_SENSOR - std::array<text_sensor::TextSensor *, 3> direction_text_sensors_{}; + std::array<text_sensor::TextSensor *, MAX_TARGETS> direction_text_sensors_{}; + std::array<Deduplicator<uint8_t>, MAX_TARGETS> direction_dedup_{}; #endif LazyCallbackManager<void()> data_callback_; From 82e620bcf5239bf1ad540986a54c50b2e3689326 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:26:55 -1000 Subject: [PATCH 1023/2030] [ld2450] Single-pass zone target counting (#14387) --- esphome/components/ld2450/ld2450.cpp | 22 ++++++++++++---------- esphome/components/ld2450/ld2450.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index ca64836bf8..583918e5f5 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -283,16 +283,19 @@ void LD2450Component::loop() { } } -// Count targets in zone -uint8_t LD2450Component::count_targets_in_zone_(const Zone &zone, bool is_moving) { - uint8_t count = 0; - for (auto &index : this->target_info_) { - if (index.x > zone.x1 && index.x < zone.x2 && index.y > zone.y1 && index.y < zone.y2 && - index.is_moving == is_moving) { - count++; +// Count targets in zone (single pass for both still and moving) +void LD2450Component::count_targets_in_zone_(const Zone &zone, uint8_t &still, uint8_t &moving) { + still = 0; + moving = 0; + for (auto &target : this->target_info_) { + if (target.x > zone.x1 && target.x < zone.x2 && target.y > zone.y1 && target.y < zone.y2) { + if (target.is_moving) { + moving++; + } else { + still++; + } } } - return count; } // Service reset_radar_zone @@ -540,8 +543,7 @@ void LD2450Component::handle_periodic_data_() { uint8_t zone_moving_targets = 0; uint8_t zone_all_targets = 0; for (index = 0; index < MAX_ZONES; index++) { - zone_still_targets = this->count_targets_in_zone_(this->zone_config_[index], false); - zone_moving_targets = this->count_targets_in_zone_(this->zone_config_[index], true); + this->count_targets_in_zone_(this->zone_config_[index], zone_still_targets, zone_moving_targets); zone_all_targets = zone_still_targets + zone_moving_targets; // Publish Still Target Count in Zones diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 518b320b0a..39b0ebd9da 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -163,7 +163,7 @@ class LD2450Component : public Component, public uart::UARTDevice { void save_to_flash_(float value); float restore_from_flash_(); bool get_timeout_status_(uint32_t check_millis); - uint8_t count_targets_in_zone_(const Zone &zone, bool is_moving); + void count_targets_in_zone_(const Zone &zone, uint8_t &still, uint8_t &moving); uint32_t presence_millis_ = 0; uint32_t still_presence_millis_ = 0; From 3f97b3b7066c52bb7df8a9e5e686d290d7e88e23 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 14:27:06 -1000 Subject: [PATCH 1024/2030] [core] Extract set_status_flag_ helper to deduplicate status_set methods (#14384) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/core/component.cpp | 25 +++++++++++-------------- esphome/core/component.h | 6 ++++++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 1fd621ea83..fd4e0d2984 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -383,31 +383,30 @@ bool Component::is_idle() const { return (this->component_state_ & COMPONENT_STA bool Component::can_proceed() { return true; } bool Component::status_has_warning() const { return this->component_state_ & STATUS_LED_WARNING; } bool Component::status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; } +bool Component::set_status_flag_(uint8_t flag) { + if ((this->component_state_ & flag) != 0) + return false; + this->component_state_ |= flag; + App.app_state_ |= flag; + return true; +} void Component::status_set_warning(const char *message) { - // Don't spam the log. This risks missing different warning messages though. - if ((this->component_state_ & STATUS_LED_WARNING) != 0) + if (!this->set_status_flag_(STATUS_LED_WARNING)) return; - this->component_state_ |= STATUS_LED_WARNING; - App.app_state_ |= STATUS_LED_WARNING; ESP_LOGW(TAG, "%s set Warning flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? message : LOG_STR_LITERAL("unspecified")); } void Component::status_set_warning(const LogString *message) { - // Don't spam the log. This risks missing different warning messages though. - if ((this->component_state_ & STATUS_LED_WARNING) != 0) + if (!this->set_status_flag_(STATUS_LED_WARNING)) return; - this->component_state_ |= STATUS_LED_WARNING; - App.app_state_ |= STATUS_LED_WARNING; ESP_LOGW(TAG, "%s set Warning flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified")); } void Component::status_set_error() { this->status_set_error((const LogString *) nullptr); } void Component::status_set_error(const char *message) { - if ((this->component_state_ & STATUS_LED_ERROR) != 0) + if (!this->set_status_flag_(STATUS_LED_ERROR)) return; - this->component_state_ |= STATUS_LED_ERROR; - App.app_state_ |= STATUS_LED_ERROR; ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? message : LOG_STR_LITERAL("unspecified")); if (message != nullptr) { @@ -415,10 +414,8 @@ void Component::status_set_error(const char *message) { } } void Component::status_set_error(const LogString *message) { - if ((this->component_state_ & STATUS_LED_ERROR) != 0) + if (!this->set_status_flag_(STATUS_LED_ERROR)) return; - this->component_state_ |= STATUS_LED_ERROR; - App.app_state_ |= STATUS_LED_ERROR; ESP_LOGE(TAG, "%s set Error flag: %s", LOG_STR_ARG(this->get_component_log_str()), message ? LOG_STR_ARG(message) : LOG_STR_LITERAL("unspecified")); if (message != nullptr) { diff --git a/esphome/core/component.h b/esphome/core/component.h index 0b0b6345c7..6b920da290 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -299,6 +299,12 @@ class Component { this->component_state_ |= state; } + /// Helper to set a status LED flag on both this component and the app. + /// Returns true if the flag was newly set, false if it was already set. + /// Note: Callers often use the return value to decide whether to log a warning/error, + /// so once a flag is set, subsequent (potentially different) messages may be suppressed. + bool set_status_flag_(uint8_t flag); + /** Set an interval function with a unique name. Empty name means no cancelling possible. * * This will call f every interval ms. Can be cancelled via CancelInterval(). From 19bbd39e334332d5ebc3f33a2a435e96ab54555f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Feb 2026 17:06:46 -1000 Subject: [PATCH 1025/2030] [uart] Enable wake-on-RX by default on ESP32 (#14391) --- esphome/components/uart/__init__.py | 42 +++++----------------- esphome/components/zwave_proxy/__init__.py | 3 -- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index a6f4cf5d5f..69db4b44aa 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -1,4 +1,3 @@ -from dataclasses import dataclass from logging import getLogger import math import re @@ -117,38 +116,6 @@ MULTI_CONF = True MULTI_CONF_NO_DEFAULT = True -@dataclass -class UARTData: - """State data for UART component configuration generation.""" - - wake_loop_on_rx: bool = False - - -def _get_data() -> UARTData: - """Get UART component data from CORE.data.""" - if DOMAIN not in CORE.data: - CORE.data[DOMAIN] = UARTData() - return CORE.data[DOMAIN] - - -def request_wake_loop_on_rx() -> None: - """Request that the UART wake the main loop when data is received. - - Components that need low-latency notification of incoming UART data - should call this function during their code generation. - This enables the RX event task which wakes the main loop when data arrives. - """ - data = _get_data() - if not data.wake_loop_on_rx: - data.wake_loop_on_rx = True - - # UART RX event task uses wake_loop_threadsafe() to notify the main loop - # Automatically enable the socket wake infrastructure when RX wake is requested - from esphome.components import socket - - socket.require_wake_loop_threadsafe() - - def validate_raw_data(value): if isinstance(value, str): return value.encode("utf-8") @@ -542,7 +509,14 @@ async def uart_write_to_code(config, action_id, template_arg, args): @coroutine_with_priority(CoroPriority.FINAL) async def final_step(): """Final code generation step to configure optional UART features.""" - if _get_data().wake_loop_on_rx: + if CORE.is_esp32 and CORE.has_networking: + # Wake-on-RX is essentially free on ESP32 (just an ISR function pointer + # registration) — enable by default to reduce RX buffer overflow risk + # by waking the main loop immediately when data arrives. + # Requires networking for the wake_loop_isrsafe() infrastructure. + from esphome.components import socket + + socket.require_wake_loop_threadsafe() cg.add_define("USE_UART_WAKE_LOOP_ON_RX") diff --git a/esphome/components/zwave_proxy/__init__.py b/esphome/components/zwave_proxy/__init__.py index 5be05bb464..d88f9f7041 100644 --- a/esphome/components/zwave_proxy/__init__.py +++ b/esphome/components/zwave_proxy/__init__.py @@ -41,6 +41,3 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) cg.add_define("USE_ZWAVE_PROXY") - - # Request UART to wake the main loop when data arrives for low-latency processing - uart.request_wake_loop_on_rx() From a1760a198047d92a36fe9c8af01ca5c86f736d80 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 10:23:10 -1000 Subject: [PATCH 1026/2030] [improv_serial] Add missing USE_IMPROV_SERIAL define to fix WiFi scan filtering (#14359) --- esphome/components/improv_serial/__init__.py | 1 + esphome/components/wifi/wifi_component.cpp | 2 +- esphome/components/wifi/wifi_component.h | 4 ++-- esphome/components/wifi/wifi_component_esp8266.cpp | 2 +- esphome/components/wifi/wifi_component_esp_idf.cpp | 2 +- esphome/components/wifi/wifi_component_libretiny.cpp | 2 +- esphome/components/wifi/wifi_component_pico_w.cpp | 2 +- esphome/core/defines.h | 1 + 8 files changed, 9 insertions(+), 7 deletions(-) diff --git a/esphome/components/improv_serial/__init__.py b/esphome/components/improv_serial/__init__.py index 9a2ac2f40f..4266f5b78b 100644 --- a/esphome/components/improv_serial/__init__.py +++ b/esphome/components/improv_serial/__init__.py @@ -43,3 +43,4 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await improv_base.setup_improv_core(var, config, "improv_serial") + cg.add_define("USE_IMPROV_SERIAL") diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 1e6961b8bd..7d5d0133c1 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2121,7 +2121,7 @@ bool WiFiComponent::can_proceed() { #endif void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } -bool WiFiComponent::is_connected() { +bool WiFiComponent::is_connected() const { return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_; } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 63c7039f21..a6f03a08d9 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -443,7 +443,7 @@ class WiFiComponent : public Component { void set_reboot_timeout(uint32_t reboot_timeout); - bool is_connected(); + bool is_connected() const; void set_power_save_mode(WiFiPowerSaveMode power_save); void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; } @@ -677,7 +677,7 @@ class WiFiComponent : public Component { bool wifi_apply_hostname_(); bool wifi_sta_connect_(const WiFiAP &ap); void wifi_pre_setup_(); - WiFiSTAConnectStatus wifi_sta_connect_status_(); + WiFiSTAConnectStatus wifi_sta_connect_status_() const; bool wifi_scan_start_(bool passive); #ifdef USE_WIFI_AP diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 8911bf15e0..bd6a18a99b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -622,7 +622,7 @@ void WiFiComponent::wifi_pre_setup_() { this->wifi_mode_(false, false); } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { station_status_t status = wifi_station_get_connect_status(); if (status == STATION_GOT_IP) return WiFiSTAConnectStatus::CONNECTED; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 57bbceb1b8..734d186205 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -921,7 +921,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { if (s_sta_connected && this->got_ipv4_address_) { #if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) if (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT) { diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 1c5490a3ac..4c4150e44d 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -634,7 +634,7 @@ void WiFiComponent::wifi_pre_setup_() { // Make sure WiFi is in clean state before anything starts this->wifi_mode_(false, false); } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { // Use state machine instead of querying WiFi.status() directly // State is updated in main loop from queued events, ensuring thread safety switch (s_sta_state) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 9b2c077dc5..270425d8c2 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -120,7 +120,7 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "UNKNOWN"; } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 5c982c94b1..181425c162 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -55,6 +55,7 @@ #define USE_HOMEASSISTANT_TIME #define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT #define USE_IMAGE +#define USE_IMPROV_SERIAL #define USE_IMPROV_SERIAL_NEXT_URL #define USE_INFRARED #define USE_IR_RF From 48b5cae6c4692c6f563b1c250aa266e31b0b1b98 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 11:32:44 -1000 Subject: [PATCH 1027/2030] [api] Use StringRef for user service string arguments (#13974) --- esphome/automation.py | 57 +++++- esphome/components/api/__init__.py | 15 +- esphome/components/api/api_connection.cpp | 43 +++-- esphome/components/api/api_frame_helper.h | 4 + .../components/api/api_frame_helper_noise.cpp | 30 ++- .../api/api_frame_helper_plaintext.cpp | 7 +- esphome/components/api/user_services.cpp | 5 + esphome/components/button/__init__.py | 4 +- esphome/components/cover/__init__.py | 20 +- esphome/components/fan/__init__.py | 9 +- esphome/components/globals/__init__.py | 1 + esphome/components/light/automation.py | 12 +- esphome/components/logger/__init__.py | 4 +- esphome/components/mqtt/__init__.py | 7 +- esphome/components/number/__init__.py | 6 + esphome/components/output/__init__.py | 7 +- esphome/components/script/__init__.py | 2 + esphome/components/select/__init__.py | 7 + esphome/components/switch/__init__.py | 14 +- esphome/components/text/__init__.py | 1 + esphome/core/string_ref.h | 14 ++ esphome/util.py | 16 +- tests/unit_tests/test_automation.py | 177 ++++++++++++++++++ 23 files changed, 406 insertions(+), 56 deletions(-) create mode 100644 tests/unit_tests/test_automation.py diff --git a/esphome/automation.py b/esphome/automation.py index 2439b1ddc4..d9b8b2ec57 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -57,8 +57,23 @@ def maybe_conf(conf, *validators): return validate -def register_action(name: str, action_type: MockObjClass, schema: cv.Schema): - return ACTION_REGISTRY.register(name, action_type, schema) +def register_action( + name: str, + action_type: MockObjClass, + schema: cv.Schema, + *, + synchronous: bool = False, +): + """Register an action type. + + Actions default to ``synchronous=False`` (safe default), meaning string + arguments use owning std::string to prevent dangling references. + + Set ``synchronous=True`` only for actions that complete synchronously + and never store trigger arguments for later execution. This allows + the code generator to use non-owning StringRef for zero-copy access. + """ + return ACTION_REGISTRY.register(name, action_type, schema, synchronous=synchronous) def register_condition(name: str, condition_type: MockObjClass, schema: cv.Schema): @@ -335,7 +350,9 @@ async def component_is_idle_condition_to_code( @register_action( - "delay", DelayAction, cv.templatable(cv.positive_time_period_milliseconds) + "delay", + DelayAction, + cv.templatable(cv.positive_time_period_milliseconds), ) async def delay_action_to_code( config: ConfigType, @@ -366,6 +383,7 @@ async def delay_action_to_code( cv.has_at_least_one_key(CONF_THEN, CONF_ELSE), cv.has_at_least_one_key(CONF_CONDITION, CONF_ANY, CONF_ALL), ), + synchronous=True, ) async def if_action_to_code( config: ConfigType, @@ -394,6 +412,7 @@ async def if_action_to_code( cv.Required(CONF_THEN): validate_action_list, } ), + synchronous=True, ) async def while_action_to_code( config: ConfigType, @@ -417,6 +436,7 @@ async def while_action_to_code( cv.Required(CONF_THEN): validate_action_list, } ), + synchronous=True, ) async def repeat_action_to_code( config: ConfigType, @@ -461,7 +481,12 @@ async def wait_until_action_to_code( return var -@register_action("lambda", LambdaAction, cv.lambda_) +# Lambda executes user C++ inline and returns — synchronous by execution model. +# User code could theoretically store the StringRef for deferred use, but StringRef +# is a view type and storing views beyond their scope is always unsafe regardless +# of this optimization. Marking non-synchronous would disable StringRef for nearly +# all user services since most use lambda. +@register_action("lambda", LambdaAction, cv.lambda_, synchronous=True) async def lambda_action_to_code( config: ConfigType, action_id: ID, @@ -480,6 +505,7 @@ async def lambda_action_to_code( cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), } ), + synchronous=True, ) async def component_update_action_to_code( config: ConfigType, @@ -499,6 +525,7 @@ async def component_update_action_to_code( cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), } ), + synchronous=True, ) async def component_suspend_action_to_code( config: ConfigType, @@ -521,6 +548,7 @@ async def component_suspend_action_to_code( ), } ), + synchronous=True, ) async def component_resume_action_to_code( config: ConfigType, @@ -578,6 +606,27 @@ async def build_condition_list( return conditions +def has_non_synchronous_actions(actions: ConfigType) -> bool: + """Check if a validated action list contains any non-synchronous actions. + + Non-synchronous actions (delay, wait_until, script.wait, etc.) store + trigger args for later execution, making non-owning types like StringRef + unsafe. Actions that haven't been audited default to non-synchronous. + """ + if isinstance(actions, list): + return any(has_non_synchronous_actions(item) for item in actions) + if isinstance(actions, dict): + for key in actions: + if key in ACTION_REGISTRY and not ACTION_REGISTRY[key].synchronous: + return True + return any( + has_non_synchronous_actions(v) + for v in actions.values() + if isinstance(v, (list, dict)) + ) + return False + + async def build_automation( trigger: MockObj, args: TemplateArgsType, config: ConfigType ) -> MockObj: diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 3f7cafb485..d7b6bec357 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -76,7 +76,7 @@ SERVICE_ARG_NATIVE_TYPES: dict[str, MockObj] = { "bool": cg.bool_, "int": cg.int32, "float": cg.float_, - "string": cg.std_string, + "string": cg.StringRef, "bool[]": cg.FixedVector.template(cg.bool_).operator("const").operator("ref"), "int[]": cg.FixedVector.template(cg.int32).operator("const").operator("ref"), "float[]": cg.FixedVector.template(cg.float_).operator("const").operator("ref"), @@ -380,9 +380,18 @@ async def to_code(config: ConfigType) -> None: if is_optional: func_args.append((cg.bool_, "return_response")) + # Check if action chain has non-synchronous actions that would make + # non-owning StringRef dangle (rx_buf_ reused after delay) + has_non_synchronous = automation.has_non_synchronous_actions( + conf.get(CONF_THEN, []) + ) + service_arg_names: list[str] = [] for name, var_ in conf[CONF_VARIABLES].items(): native = SERVICE_ARG_NATIVE_TYPES[var_] + # Fall back to std::string for string args if non-synchronous actions exist + if has_non_synchronous and native is cg.StringRef: + native = cg.std_string service_template_args.append(native) func_args.append((native, name)) service_arg_names.append(name) @@ -509,11 +518,13 @@ HOMEASSISTANT_ACTION_ACTION_SCHEMA = cv.All( "homeassistant.action", HomeAssistantServiceCallAction, HOMEASSISTANT_ACTION_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( "homeassistant.service", HomeAssistantServiceCallAction, HOMEASSISTANT_ACTION_ACTION_SCHEMA, + synchronous=True, ) async def homeassistant_service_to_code( config: ConfigType, @@ -604,6 +615,7 @@ HOMEASSISTANT_EVENT_ACTION_SCHEMA = cv.Schema( "homeassistant.event", HomeAssistantServiceCallAction, HOMEASSISTANT_EVENT_ACTION_SCHEMA, + synchronous=True, ) async def homeassistant_event_to_code(config, action_id, template_arg, args): cg.add_define("USE_API_HOMEASSISTANT_SERVICES") @@ -644,6 +656,7 @@ HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA = cv.maybe_simple_value( "homeassistant.tag_scanned", HomeAssistantServiceCallAction, HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA, + synchronous=True, ) async def homeassistant_tag_scanned_to_code(config, action_id, template_arg, args): cg.add_define("USE_API_HOMEASSISTANT_SERVICES") diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 8b2efdde51..215af611db 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1711,37 +1711,42 @@ void APIConnection::on_home_assistant_state_response(const HomeAssistantStateRes return; } + // Null-terminate state in-place for safe c_str() usage (e.g., parse_number in callbacks). + // Safe: decode is complete, byte after string data was already consumed during parse, + // and frame helpers reserve RX_BUF_NULL_TERMINATOR extra byte in rx_buf_. + // const_cast is safe: msg references mutable rx_buf_ data; the const& handler + // signature is a generated protobuf pattern, not a true immutability contract. + if (!msg.state.empty()) { + const_cast<char *>(msg.state.c_str())[msg.state.size()] = '\0'; + } + for (auto &it : this->parent_->get_state_subs()) { - // Compare entity_id: check length matches and content matches - size_t entity_id_len = strlen(it.entity_id); - if (entity_id_len != msg.entity_id.size() || - memcmp(it.entity_id, msg.entity_id.c_str(), msg.entity_id.size()) != 0) { + if (msg.entity_id != it.entity_id) { continue; } - // Compare attribute: either both have matching attribute, or both have none - size_t sub_attr_len = it.attribute != nullptr ? strlen(it.attribute) : 0; - if (sub_attr_len != msg.attribute.size() || - (sub_attr_len > 0 && memcmp(it.attribute, msg.attribute.c_str(), sub_attr_len) != 0)) { + // If subscriber has attribute filter (non-null), message attribute must match it; + // if subscriber has no filter (nullptr), message must have no attribute. + if (it.attribute != nullptr ? msg.attribute != it.attribute : !msg.attribute.empty()) { continue; } - // Create null-terminated state for callback (parse_number needs null-termination) - // HA state max length is 255 characters, but attributes can be much longer - // Use stack buffer for common case (states), heap fallback for large attributes - size_t state_len = msg.state.size(); - SmallBufferWithHeapFallback<MAX_STATE_LEN + 1> state_buf_alloc(state_len + 1); - char *state_buf = reinterpret_cast<char *>(state_buf_alloc.get()); - if (state_len > 0) { - memcpy(state_buf, msg.state.c_str(), state_len); - } - state_buf[state_len] = '\0'; - it.callback(StringRef(state_buf, state_len)); + it.callback(msg.state); } } #endif #ifdef USE_API_USER_DEFINED_ACTIONS void APIConnection::on_execute_service_request(const ExecuteServiceRequest &msg) { + // Null-terminate string args in-place for safe c_str() usage in YAML service triggers. + // Safe: full ExecuteServiceRequest decode is complete, all bytes in rx_buf_ consumed, + // and frame helpers reserve RX_BUF_NULL_TERMINATOR extra byte for the last field. + // const_cast is safe: msg references mutable rx_buf_ data; the const& handler + // signature is a generated protobuf pattern, not a true immutability contract. + for (auto &arg : const_cast<ExecuteServiceRequest &>(msg).args) { + if (!arg.string_.empty()) { + const_cast<char *>(arg.string_.c_str())[arg.string_.size()] = '\0'; + } + } bool found = false; #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES // Register the call and get a unique server-generated action_call_id diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 03f3814bb9..2b4e9ea3cd 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -29,6 +29,10 @@ static constexpr uint16_t MAX_MESSAGE_SIZE = 8192; // 8 KiB for ESP8266 static constexpr uint16_t MAX_MESSAGE_SIZE = 32768; // 32 KiB for ESP32 and other platforms #endif +// Extra byte reserved in rx_buf_ beyond the message size so protobuf +// StringRef fields can be null-terminated in-place after decode. +static constexpr uint16_t RX_BUF_NULL_TERMINATOR = 1; + // Maximum number of messages to batch in a single write operation // Must be >= MAX_INITIAL_PER_BATCH in api_connection.h (enforced by static_assert there) static constexpr size_t MAX_MESSAGES_PER_BATCH = 34; diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 2aad732f7f..3ae35e9be8 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -194,16 +194,21 @@ APIError APINoiseFrameHelper::try_read_frame_() { uint16_t msg_size = (((uint16_t) rx_header_buf_[1]) << 8) | rx_header_buf_[2]; // Check against size limits to prevent OOM: MAX_HANDSHAKE_SIZE for handshake, MAX_MESSAGE_SIZE for data - uint16_t limit = (state_ == State::DATA) ? MAX_MESSAGE_SIZE : MAX_HANDSHAKE_SIZE; + bool is_data = (state_ == State::DATA); + uint16_t limit = is_data ? MAX_MESSAGE_SIZE : MAX_HANDSHAKE_SIZE; if (msg_size > limit) { state_ = State::FAILED; HELPER_LOG("Bad packet: message size %u exceeds maximum %u", msg_size, limit); - return (state_ == State::DATA) ? APIError::BAD_DATA_PACKET : APIError::BAD_HANDSHAKE_PACKET_LEN; + return is_data ? APIError::BAD_DATA_PACKET : APIError::BAD_HANDSHAKE_PACKET_LEN; } - // Reserve space for body - if (this->rx_buf_.size() != msg_size) { - this->rx_buf_.resize(msg_size); + // Reserve space for body (+ null terminator in DATA state so protobuf + // StringRef fields can be safely null-terminated in-place after decode. + // During handshake, rx_buf_.size() is used in prologue construction, so + // the buffer must be exactly msg_size to avoid prologue mismatch.) + uint16_t alloc_size = msg_size + (is_data ? RX_BUF_NULL_TERMINATOR : 0); + if (this->rx_buf_.size() != alloc_size) { + this->rx_buf_.resize(alloc_size); } if (rx_buf_len_ < msg_size) { @@ -407,7 +412,18 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { NoiseBuffer mbuf; noise_buffer_init(mbuf); - noise_buffer_set_inout(mbuf, this->rx_buf_.data(), this->rx_buf_.size(), this->rx_buf_.size()); + // read_packet() must only be called in DATA state; the extra + // RX_BUF_NULL_TERMINATOR byte is only allocated in DATA state + // (see try_read_frame_), so calling this during handshake would + // underflow the size calculation below. +#ifdef ESPHOME_DEBUG_API + assert(this->state_ == State::DATA); +#endif + // rx_buf_ has RX_BUF_NULL_TERMINATOR extra byte for null termination + // (only added in DATA state — see try_read_frame_), so subtract it + // to get the actual encrypted data size for decryption. + size_t encrypted_size = this->rx_buf_.size() - RX_BUF_NULL_TERMINATOR; + noise_buffer_set_inout(mbuf, this->rx_buf_.data(), encrypted_size, encrypted_size); int err = noise_cipherstate_decrypt(this->recv_cipher_, &mbuf); APIError decrypt_err = handle_noise_error_(err, LOG_STR("noise_cipherstate_decrypt"), APIError::CIPHERSTATE_DECRYPT_FAILED); @@ -574,7 +590,9 @@ APIError APINoiseFrameHelper::init_handshake_() { } APIError APINoiseFrameHelper::check_handshake_finished_() { +#ifdef ESPHOME_DEBUG_API assert(state_ == State::HANDSHAKE); +#endif int action = noise_handshakestate_get_action(handshake_); if (action == NOISE_ACTION_READ_MESSAGE || action == NOISE_ACTION_WRITE_MESSAGE) diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index 5069dbf68b..e2bb56e0ac 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -163,9 +163,10 @@ APIError APIPlaintextFrameHelper::try_read_frame_() { } // header reading done - // Reserve space for body - if (this->rx_buf_.size() != this->rx_header_parsed_len_) { - this->rx_buf_.resize(this->rx_header_parsed_len_); + // Reserve space for body (+ null terminator so protobuf StringRef fields + // can be safely null-terminated in-place after decode) + if (this->rx_buf_.size() != this->rx_header_parsed_len_ + RX_BUF_NULL_TERMINATOR) { + this->rx_buf_.resize(this->rx_header_parsed_len_ + RX_BUF_NULL_TERMINATOR); } if (rx_buf_len_ < rx_header_parsed_len_) { diff --git a/esphome/components/api/user_services.cpp b/esphome/components/api/user_services.cpp index 9c2b4aa79a..28a43c656c 100644 --- a/esphome/components/api/user_services.cpp +++ b/esphome/components/api/user_services.cpp @@ -1,5 +1,6 @@ #include "user_services.h" #include "esphome/core/log.h" +#include "esphome/core/string_ref.h" namespace esphome::api { @@ -11,6 +12,8 @@ template<> int32_t get_execute_arg_value<int32_t>(const ExecuteServiceArgument & } template<> float get_execute_arg_value<float>(const ExecuteServiceArgument &arg) { return arg.float_; } template<> std::string get_execute_arg_value<std::string>(const ExecuteServiceArgument &arg) { return arg.string_; } +// Zero-copy StringRef version for YAML-generated services (string_ is null-terminated after decode) +template<> StringRef get_execute_arg_value<StringRef>(const ExecuteServiceArgument &arg) { return arg.string_; } // Legacy std::vector versions for external components using custom_api_device.h - optimized with reserve template<> std::vector<bool> get_execute_arg_value<std::vector<bool>>(const ExecuteServiceArgument &arg) { @@ -61,6 +64,8 @@ template<> enums::ServiceArgType to_service_arg_type<bool>() { return enums::SER template<> enums::ServiceArgType to_service_arg_type<int32_t>() { return enums::SERVICE_ARG_TYPE_INT; } template<> enums::ServiceArgType to_service_arg_type<float>() { return enums::SERVICE_ARG_TYPE_FLOAT; } template<> enums::ServiceArgType to_service_arg_type<std::string>() { return enums::SERVICE_ARG_TYPE_STRING; } +// Zero-copy StringRef version for YAML-generated services +template<> enums::ServiceArgType to_service_arg_type<StringRef>() { return enums::SERVICE_ARG_TYPE_STRING; } // Legacy std::vector versions for external components using custom_api_device.h template<> enums::ServiceArgType to_service_arg_type<std::vector<bool>>() { return enums::SERVICE_ARG_TYPE_BOOL_ARRAY; } diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index d2f143b97e..94816a0974 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -123,7 +123,9 @@ BUTTON_PRESS_SCHEMA = maybe_simple_id( ) -@automation.register_action("button.press", PressAction, BUTTON_PRESS_SCHEMA) +@automation.register_action( + "button.press", PressAction, BUTTON_PRESS_SCHEMA, synchronous=True +) async def button_press_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 648fe7decf..17095f41f6 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -248,25 +248,33 @@ COVER_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("cover.open", OpenAction, COVER_ACTION_SCHEMA) +@automation.register_action( + "cover.open", OpenAction, COVER_ACTION_SCHEMA, synchronous=True +) async def cover_open_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("cover.close", CloseAction, COVER_ACTION_SCHEMA) +@automation.register_action( + "cover.close", CloseAction, COVER_ACTION_SCHEMA, synchronous=True +) async def cover_close_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("cover.stop", StopAction, COVER_ACTION_SCHEMA) +@automation.register_action( + "cover.stop", StopAction, COVER_ACTION_SCHEMA, synchronous=True +) async def cover_stop_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("cover.toggle", ToggleAction, COVER_ACTION_SCHEMA) +@automation.register_action( + "cover.toggle", ToggleAction, COVER_ACTION_SCHEMA, synchronous=True +) async def cover_toggle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @@ -283,7 +291,9 @@ COVER_CONTROL_ACTION_SCHEMA = cv.Schema( ) -@automation.register_action("cover.control", ControlAction, COVER_CONTROL_ACTION_SCHEMA) +@automation.register_action( + "cover.control", ControlAction, COVER_CONTROL_ACTION_SCHEMA, synchronous=True +) async def cover_control_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) diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 6010aa8ed4..e839df6aee 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -311,13 +311,17 @@ FAN_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("fan.toggle", ToggleAction, FAN_ACTION_SCHEMA) +@automation.register_action( + "fan.toggle", ToggleAction, FAN_ACTION_SCHEMA, synchronous=True +) async def fan_toggle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("fan.turn_off", TurnOffAction, FAN_ACTION_SCHEMA) +@automation.register_action( + "fan.turn_off", TurnOffAction, FAN_ACTION_SCHEMA, synchronous=True +) async def fan_turn_off_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @@ -336,6 +340,7 @@ async def fan_turn_off_to_code(config, action_id, template_arg, args): ), } ), + synchronous=True, ) async def fan_turn_on_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index fc400c5dd1..fe11a93a4b 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -102,6 +102,7 @@ async def to_code(config): cv.Required(CONF_VALUE): cv.templatable(cv.string_strict), } ), + synchronous=True, ) async def globals_set_to_code(config, action_id, template_arg, args): full_id, paren = await cg.get_variable_with_full_id(config[CONF_ID]) diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index e5aa8fa0e9..89b2fc0fb2 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -51,6 +51,7 @@ from .types import ( ), } ), + synchronous=True, ) async def light_toggle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -111,13 +112,13 @@ LIGHT_TURN_ON_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "light.turn_off", LightControlAction, LIGHT_TURN_OFF_ACTION_SCHEMA + "light.turn_off", LightControlAction, LIGHT_TURN_OFF_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "light.turn_on", LightControlAction, LIGHT_TURN_ON_ACTION_SCHEMA + "light.turn_on", LightControlAction, LIGHT_TURN_ON_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "light.control", LightControlAction, LIGHT_CONTROL_ACTION_SCHEMA + "light.control", LightControlAction, LIGHT_CONTROL_ACTION_SCHEMA, synchronous=True ) async def light_control_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -193,7 +194,10 @@ LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "light.dim_relative", DimRelativeAction, LIGHT_DIM_RELATIVE_ACTION_SCHEMA + "light.dim_relative", + DimRelativeAction, + LIGHT_DIM_RELATIVE_ACTION_SCHEMA, + synchronous=True, ) async def light_dim_relative_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 264197c175..026b8aaf24 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -519,7 +519,9 @@ LOGGER_LOG_ACTION_SCHEMA = cv.All( ) -@automation.register_action(CONF_LOGGER_LOG, LambdaAction, LOGGER_LOG_ACTION_SCHEMA) +@automation.register_action( + CONF_LOGGER_LOG, LambdaAction, LOGGER_LOG_ACTION_SCHEMA, synchronous=True +) async def logger_log_action_to_code(config, action_id, template_arg, args): esp_log = LOG_LEVEL_TO_ESP_LOG[config[CONF_LEVEL]] args_ = [cg.RawExpression(str(x)) for x in config[CONF_ARGS]] diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 44e8836487..c25c472038 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -492,7 +492,7 @@ MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "mqtt.publish", MQTTPublishAction, MQTT_PUBLISH_ACTION_SCHEMA + "mqtt.publish", MQTTPublishAction, MQTT_PUBLISH_ACTION_SCHEMA, synchronous=True ) async def mqtt_publish_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -521,7 +521,10 @@ MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "mqtt.publish_json", MQTTPublishJsonAction, MQTT_PUBLISH_JSON_ACTION_SCHEMA + "mqtt.publish_json", + MQTTPublishJsonAction, + MQTT_PUBLISH_JSON_ACTION_SCHEMA, + synchronous=True, ) async def mqtt_publish_json_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index d12ec7463b..2238f2c037 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -352,6 +352,7 @@ OPERATION_BASE_SCHEMA = cv.Schema( cv.Required(CONF_VALUE): cv.templatable(cv.float_), } ), + synchronous=True, ) async def number_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -374,6 +375,7 @@ async def number_set_to_code(config, action_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "number.decrement", @@ -388,6 +390,7 @@ async def number_set_to_code(config, action_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "number.to_min", @@ -401,6 +404,7 @@ async def number_set_to_code(config, action_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "number.to_max", @@ -414,6 +418,7 @@ async def number_set_to_code(config, action_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "number.operation", @@ -426,6 +431,7 @@ async def number_set_to_code(config, action_id, template_arg, args): cv.Optional(CONF_CYCLE, default=True): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def number_to_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index bde106b085..a4c960927b 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -74,14 +74,16 @@ BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("output.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action( + "output.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA, synchronous=True +) async def output_turn_on_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action( - "output.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA + "output.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA, synchronous=True ) async def output_turn_off_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -97,6 +99,7 @@ async def output_turn_off_to_code(config, action_id, template_arg, args): cv.Required(CONF_LEVEL): cv.templatable(cv.percentage), } ), + synchronous=True, ) async def output_set_level_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/script/__init__.py b/esphome/components/script/__init__.py index 8d69981db0..369cefad91 100644 --- a/esphome/components/script/__init__.py +++ b/esphome/components/script/__init__.py @@ -160,6 +160,7 @@ async def to_code(config): cv.Optional(validate_parameter_name): cv.templatable(cv.valid), }, ), + synchronous=True, ) async def script_execute_action_to_code(config, action_id, template_arg, args): def convert(type: str): @@ -208,6 +209,7 @@ async def script_execute_action_to_code(config, action_id, template_arg, args): "script.stop", ScriptStopAction, maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}), + synchronous=True, ) async def script_stop_action_to_code(config, action_id, template_arg, args): full_id, paren = await cg.get_variable_with_full_id(config[CONF_ID]) diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index 84ad591ba1..c114b140a9 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -145,6 +145,7 @@ OPERATION_BASE_SCHEMA = cv.Schema( cv.Required(CONF_OPTION): cv.templatable(cv.string_strict), } ), + synchronous=True, ) async def select_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -162,6 +163,7 @@ async def select_set_to_code(config, action_id, template_arg, args): cv.Required(CONF_INDEX): cv.templatable(cv.positive_int), } ), + synchronous=True, ) async def select_set_index_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -217,6 +219,7 @@ async def select_is_to_code(config, condition_id, template_arg, args): cv.Optional(CONF_CYCLE, default=True): cv.templatable(cv.boolean), } ), + synchronous=True, ) @automation.register_action( "select.next", @@ -229,6 +232,7 @@ async def select_is_to_code(config, condition_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "select.previous", @@ -243,6 +247,7 @@ async def select_is_to_code(config, condition_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "select.first", @@ -254,6 +259,7 @@ async def select_is_to_code(config, condition_id, template_arg, args): } ) ), + synchronous=True, ) @automation.register_action( "select.last", @@ -265,6 +271,7 @@ async def select_is_to_code(config, condition_id, template_arg, args): } ) ), + synchronous=True, ) async def select_operation_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index cfc5e2b6e8..6f1be7d53d 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -204,7 +204,7 @@ SWITCH_CONTROL_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "switch.control", ControlAction, SWITCH_CONTROL_ACTION_SCHEMA + "switch.control", ControlAction, SWITCH_CONTROL_ACTION_SCHEMA, synchronous=True ) async def switch_control_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -214,9 +214,15 @@ async def switch_control_to_code(config, action_id, template_arg, args): return var -@automation.register_action("switch.toggle", ToggleAction, SWITCH_ACTION_SCHEMA) -@automation.register_action("switch.turn_off", TurnOffAction, SWITCH_ACTION_SCHEMA) -@automation.register_action("switch.turn_on", TurnOnAction, SWITCH_ACTION_SCHEMA) +@automation.register_action( + "switch.toggle", ToggleAction, SWITCH_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "switch.turn_off", TurnOffAction, SWITCH_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "switch.turn_on", TurnOnAction, SWITCH_ACTION_SCHEMA, synchronous=True +) async def switch_toggle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 9ceea0dfdf..61f7119cad 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -164,6 +164,7 @@ OPERATION_BASE_SCHEMA = cv.Schema( cv.Required(CONF_VALUE): cv.templatable(cv.string_strict), } ), + synchronous=True, ) async def text_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index d502c4d27f..6047202753 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -81,6 +81,20 @@ class StringRef { operator std::string() const { return str(); } + /// Compare (compatible with std::string::compare) + int compare(const StringRef &other) const { + int result = std::memcmp(base_, other.base_, std::min(len_, other.len_)); + if (result != 0) + return result; + if (len_ < other.len_) + return -1; + if (len_ > other.len_) + return 1; + return 0; + } + int compare(const char *s) const { return compare(StringRef(s)); } + int compare(const std::string &s) const { return compare(StringRef(s)); } + /// Find first occurrence of substring, returns std::string::npos if not found. /// Note: Requires the underlying string to be null-terminated. size_type find(const char *s, size_type pos = 0) const { diff --git a/esphome/util.py b/esphome/util.py index 7b896de27e..686aa74306 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -24,11 +24,14 @@ class RegistryEntry: fun: Callable[..., Any], type_id: "MockObjClass", schema: "Schema", + *, + synchronous: bool = False, ): self.name = name self.fun = fun self.type_id = type_id self.raw_schema = schema + self.synchronous = synchronous @property def coroutine_fun(self): @@ -49,9 +52,18 @@ class Registry(dict[str, RegistryEntry]): self.base_schema = base_schema or {} self.type_id_key = type_id_key - def register(self, name: str, type_id: "MockObjClass", schema: "Schema"): + def register( + self, + name: str, + type_id: "MockObjClass", + schema: "Schema", + *, + synchronous: bool = False, + ): def decorator(fun: Callable[..., Any]): - self[name] = RegistryEntry(name, fun, type_id, schema) + self[name] = RegistryEntry( + name, fun, type_id, schema, synchronous=synchronous + ) return fun return decorator diff --git a/tests/unit_tests/test_automation.py b/tests/unit_tests/test_automation.py new file mode 100644 index 0000000000..61fef8201d --- /dev/null +++ b/tests/unit_tests/test_automation.py @@ -0,0 +1,177 @@ +"""Tests for esphome.automation module.""" + +from collections.abc import Generator +from unittest.mock import patch + +import pytest + +from esphome.automation import has_non_synchronous_actions +from esphome.util import RegistryEntry + + +def _make_registry(non_synchronous_actions: set[str]) -> dict[str, RegistryEntry]: + """Create a mock ACTION_REGISTRY with specified non-synchronous actions. + + Uses the default synchronous=False, matching the real registry behavior. + """ + registry: dict[str, RegistryEntry] = {} + for name in non_synchronous_actions: + registry[name] = RegistryEntry(name, lambda: None, None, None) + return registry + + +@pytest.fixture +def mock_registry() -> Generator[dict[str, RegistryEntry]]: + """Fixture that patches ACTION_REGISTRY with delay, wait_until, script.wait as non-synchronous.""" + registry: dict[str, RegistryEntry] = _make_registry( + {"delay", "wait_until", "script.wait"} + ) + registry["logger.log"] = RegistryEntry( + "logger.log", lambda: None, None, None, synchronous=True + ) + with patch("esphome.automation.ACTION_REGISTRY", registry): + yield registry + + +def test_has_non_synchronous_actions_empty_list( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions([]) is False + + +def test_has_non_synchronous_actions_empty_dict( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions({}) is False + + +def test_has_non_synchronous_actions_non_dict_non_list( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions("string") is False + assert has_non_synchronous_actions(42) is False + assert has_non_synchronous_actions(None) is False + + +def test_has_non_synchronous_actions_delay( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions([{"delay": "1s"}]) is True + + +def test_has_non_synchronous_actions_wait_until( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions([{"wait_until": {"condition": {}}}]) is True + + +def test_has_non_synchronous_actions_script_wait( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions([{"script.wait": "script_id"}]) is True + + +def test_has_non_synchronous_actions_synchronous( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert has_non_synchronous_actions([{"logger.log": "hello"}]) is False + + +def test_has_non_synchronous_actions_unknown_not_in_registry( + mock_registry: dict[str, RegistryEntry], +) -> None: + """Unknown actions not in registry are not flagged (only registered actions count).""" + assert has_non_synchronous_actions([{"unknown.action": "value"}]) is False + + +def test_has_non_synchronous_actions_default_non_synchronous( + mock_registry: dict[str, RegistryEntry], +) -> None: + """Actions registered without explicit synchronous=True default to non-synchronous.""" + mock_registry["some.action"] = RegistryEntry( + "some.action", lambda: None, None, None + ) + assert has_non_synchronous_actions([{"some.action": "value"}]) is True + + +def test_has_non_synchronous_actions_nested_in_then( + mock_registry: dict[str, RegistryEntry], +) -> None: + """Non-synchronous action nested inside a synchronous action's then block.""" + actions: list[dict[str, object]] = [ + { + "logger.log": "first", + "then": [{"delay": "1s"}], + } + ] + assert has_non_synchronous_actions(actions) is True + + +def test_has_non_synchronous_actions_deeply_nested( + mock_registry: dict[str, RegistryEntry], +) -> None: + """Non-synchronous action deeply nested in action structure.""" + actions: list[dict[str, object]] = [ + { + "if": { + "then": [ + {"logger.log": "hello"}, + {"delay": "500ms"}, + ] + } + } + ] + assert has_non_synchronous_actions(actions) is True + + +def test_has_non_synchronous_actions_none_in_nested( + mock_registry: dict[str, RegistryEntry], +) -> None: + """No non-synchronous actions even with nesting.""" + actions: list[dict[str, object]] = [ + { + "if": { + "then": [ + {"logger.log": "hello"}, + ] + } + } + ] + assert has_non_synchronous_actions(actions) is False + + +def test_has_non_synchronous_actions_multiple_one_non_synchronous( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert ( + has_non_synchronous_actions( + [ + {"logger.log": "first"}, + {"delay": "1s"}, + {"logger.log": "second"}, + ] + ) + is True + ) + + +def test_has_non_synchronous_actions_multiple_all_synchronous( + mock_registry: dict[str, RegistryEntry], +) -> None: + assert ( + has_non_synchronous_actions( + [ + {"logger.log": "first"}, + {"logger.log": "second"}, + ] + ) + is False + ) + + +def test_has_non_synchronous_actions_dict_input( + mock_registry: dict[str, RegistryEntry], +) -> None: + """Direct dict input (single action).""" + assert has_non_synchronous_actions({"delay": "1s"}) is True + assert has_non_synchronous_actions({"logger.log": "hello"}) is False From 3e7424b307b5763bba217d5f0d5d18130b67be4a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 15:22:55 -1000 Subject: [PATCH 1028/2030] [preferences] Reduce heap churn with small inline buffer optimization (#13259) --- esphome/components/esp32/preferences.cpp | 33 ++++----- esphome/components/libretiny/preferences.cpp | 33 ++++----- esphome/core/helpers.h | 72 ++++++++++++++++++++ 3 files changed, 96 insertions(+), 42 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index 8d6fdc86f6..a3ef10b21f 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -19,16 +19,7 @@ static constexpr size_t KEY_BUFFER_SIZE = 12; struct NVSData { uint32_t key; - std::unique_ptr<uint8_t[]> data; - size_t len; - - void set_data(const uint8_t *src, size_t size) { - if (!this->data || this->len != size) { - this->data = std::make_unique<uint8_t[]>(size); - this->len = size; - } - memcpy(this->data.get(), src, size); - } + SmallInlineBuffer<8> data; // Most prefs fit in 8 bytes (covers fan, cover, select, etc.) }; static std::vector<NVSData> s_pending_save; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -41,14 +32,14 @@ class ESP32PreferenceBackend : public ESPPreferenceBackend { // try find in pending saves and update that for (auto &obj : s_pending_save) { if (obj.key == this->key) { - obj.set_data(data, len); + obj.data.set(data, len); return true; } } NVSData save{}; save.key = this->key; - save.set_data(data, len); - s_pending_save.emplace_back(std::move(save)); + save.data.set(data, len); + s_pending_save.push_back(std::move(save)); ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); return true; } @@ -56,11 +47,11 @@ class ESP32PreferenceBackend : public ESPPreferenceBackend { // try find in pending saves and load from that for (auto &obj : s_pending_save) { if (obj.key == this->key) { - if (obj.len != len) { + if (obj.data.size() != len) { // size mismatch return false; } - memcpy(data, obj.data.get(), len); + memcpy(data, obj.data.data(), len); return true; } } @@ -133,10 +124,10 @@ class ESP32Preferences : public ESPPreferences { snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); ESP_LOGVV(TAG, "Checking if NVS data %s has changed", key_str); if (this->is_changed_(this->nvs_handle, save, key_str)) { - esp_err_t err = nvs_set_blob(this->nvs_handle, key_str, save.data.get(), save.len); - ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.len); + esp_err_t err = nvs_set_blob(this->nvs_handle, key_str, save.data.data(), save.data.size()); + ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); if (err != 0) { - ESP_LOGV(TAG, "nvs_set_blob('%s', len=%zu) failed: %s", key_str, save.len, esp_err_to_name(err)); + ESP_LOGV(TAG, "nvs_set_blob('%s', len=%zu) failed: %s", key_str, save.data.size(), esp_err_to_name(err)); failed++; last_err = err; last_key = save.key; @@ -144,7 +135,7 @@ class ESP32Preferences : public ESPPreferences { } written++; } else { - ESP_LOGV(TAG, "NVS data not changed skipping %" PRIu32 " len=%zu", save.key, save.len); + ESP_LOGV(TAG, "NVS data not changed skipping %" PRIu32 " len=%zu", save.key, save.data.size()); cached++; } } @@ -176,7 +167,7 @@ class ESP32Preferences : public ESPPreferences { return true; } // Check size first before allocating memory - if (actual_len != to_save.len) { + if (actual_len != to_save.data.size()) { return true; } // Most preferences are small, use stack buffer with heap fallback for large ones @@ -186,7 +177,7 @@ class ESP32Preferences : public ESPPreferences { ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); return true; } - return memcmp(to_save.data.get(), stored_data.get(), to_save.len) != 0; + return memcmp(to_save.data.data(), stored_data.get(), to_save.data.size()) != 0; } bool reset() override { diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 740c1a233a..1c101136e1 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -17,16 +17,7 @@ static constexpr size_t KEY_BUFFER_SIZE = 12; struct NVSData { uint32_t key; - std::unique_ptr<uint8_t[]> data; - size_t len; - - void set_data(const uint8_t *src, size_t size) { - if (!this->data || this->len != size) { - this->data = std::make_unique<uint8_t[]>(size); - this->len = size; - } - memcpy(this->data.get(), src, size); - } + SmallInlineBuffer<8> data; // Most prefs fit in 8 bytes (covers fan, cover, select, etc.) }; static std::vector<NVSData> s_pending_save; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -41,14 +32,14 @@ class LibreTinyPreferenceBackend : public ESPPreferenceBackend { // try find in pending saves and update that for (auto &obj : s_pending_save) { if (obj.key == this->key) { - obj.set_data(data, len); + obj.data.set(data, len); return true; } } NVSData save{}; save.key = this->key; - save.set_data(data, len); - s_pending_save.emplace_back(std::move(save)); + save.data.set(data, len); + s_pending_save.push_back(std::move(save)); ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); return true; } @@ -57,11 +48,11 @@ class LibreTinyPreferenceBackend : public ESPPreferenceBackend { // try find in pending saves and load from that for (auto &obj : s_pending_save) { if (obj.key == this->key) { - if (obj.len != len) { + if (obj.data.size() != len) { // size mismatch return false; } - memcpy(data, obj.data.get(), len); + memcpy(data, obj.data.data(), len); return true; } } @@ -122,11 +113,11 @@ class LibreTinyPreferences : public ESPPreferences { snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); ESP_LOGVV(TAG, "Checking if FDB data %s has changed", key_str); if (this->is_changed_(&this->db, save, key_str)) { - ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.len); - fdb_blob_make(&this->blob, save.data.get(), save.len); + ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); + fdb_blob_make(&this->blob, save.data.data(), save.data.size()); fdb_err_t err = fdb_kv_set_blob(&this->db, key_str, &this->blob); if (err != FDB_NO_ERR) { - ESP_LOGV(TAG, "fdb_kv_set_blob('%s', len=%zu) failed: %d", key_str, save.len, err); + ESP_LOGV(TAG, "fdb_kv_set_blob('%s', len=%zu) failed: %d", key_str, save.data.size(), err); failed++; last_err = err; last_key = save.key; @@ -134,7 +125,7 @@ class LibreTinyPreferences : public ESPPreferences { } written++; } else { - ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.len); + ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.data.size()); cached++; } } @@ -159,7 +150,7 @@ class LibreTinyPreferences : public ESPPreferences { } // Check size first - if different, data has changed - if (kv.value_len != to_save.len) { + if (kv.value_len != to_save.data.size()) { return true; } @@ -173,7 +164,7 @@ class LibreTinyPreferences : public ESPPreferences { } // Compare the actual data - return memcmp(to_save.data.get(), stored_data.get(), kv.value_len) != 0; + return memcmp(to_save.data.data(), stored_data.get(), kv.value_len) != 0; } bool reset() override { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index b606e68df3..65d590a5e6 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -133,6 +133,78 @@ template<typename T> class ConstVector { size_t size_; }; +/// Small buffer optimization - stores data inline when small, heap-allocates for large data +/// This avoids heap fragmentation for common small allocations while supporting arbitrary sizes. +/// Memory management is encapsulated - callers just use set() and data(). +template<size_t InlineSize = 8> class SmallInlineBuffer { + public: + SmallInlineBuffer() = default; + ~SmallInlineBuffer() { + if (!this->is_inline_()) + delete[] this->heap_; + } + + // Move constructor + SmallInlineBuffer(SmallInlineBuffer &&other) noexcept : len_(other.len_) { + if (other.is_inline_()) { + memcpy(this->inline_, other.inline_, this->len_); + } else { + this->heap_ = other.heap_; + other.heap_ = nullptr; + } + other.len_ = 0; + } + + // Move assignment + SmallInlineBuffer &operator=(SmallInlineBuffer &&other) noexcept { + if (this != &other) { + if (!this->is_inline_()) + delete[] this->heap_; + this->len_ = other.len_; + if (other.is_inline_()) { + memcpy(this->inline_, other.inline_, this->len_); + } else { + this->heap_ = other.heap_; + other.heap_ = nullptr; + } + other.len_ = 0; + } + return *this; + } + + // Disable copy (would need deep copy of heap data) + SmallInlineBuffer(const SmallInlineBuffer &) = delete; + SmallInlineBuffer &operator=(const SmallInlineBuffer &) = delete; + + /// Set buffer contents, allocating heap if needed + void set(const uint8_t *src, size_t size) { + // Free existing heap allocation if switching from heap to inline or different heap size + if (!this->is_inline_() && (size <= InlineSize || size != this->len_)) { + delete[] this->heap_; + this->heap_ = nullptr; // Defensive: prevent use-after-free if logic changes + } + // Allocate new heap buffer if needed + if (size > InlineSize && (this->is_inline_() || size != this->len_)) { + this->heap_ = new uint8_t[size]; // NOLINT(cppcoreguidelines-owning-memory) + } + this->len_ = size; + memcpy(this->data(), src, size); + } + + uint8_t *data() { return this->is_inline_() ? this->inline_ : this->heap_; } + const uint8_t *data() const { return this->is_inline_() ? this->inline_ : this->heap_; } + size_t size() const { return this->len_; } + + protected: + bool is_inline_() const { return this->len_ <= InlineSize; } + + size_t len_{0}; + union { + uint8_t inline_[InlineSize]{}; // Zero-init ensures clean initial state + uint8_t *heap_; + }; +}; + /// Minimal static vector - saves memory by avoiding std::vector overhead template<typename T, size_t N> class StaticVector { public: From 0e18e4461e8d82df75b3acbb61c7dcc8c9993311 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 16:52:53 -1000 Subject: [PATCH 1029/2030] [time,api] Send pre-parsed timezone struct over protobuf (#14233) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/api.proto | 28 ++++++++++ esphome/components/api/api_connection.cpp | 25 ++++++++- esphome/components/api/api_pb2.cpp | 54 ++++++++++++++++++ esphome/components/api/api_pb2.h | 38 ++++++++++++- esphome/components/api/api_pb2_dump.cpp | 39 +++++++++++++ esphome/components/time/__init__.py | 68 +++++++++++++++++++++-- 6 files changed, 245 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index d7f32cd8d1..802e3e3ae2 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -834,6 +834,33 @@ message GetTimeRequest { option (source) = SOURCE_SERVER; } +enum DSTRuleType { + DST_RULE_TYPE_NONE = 0; + DST_RULE_TYPE_MONTH_WEEK_DAY = 1; + DST_RULE_TYPE_JULIAN_NO_LEAP = 2; + DST_RULE_TYPE_DAY_OF_YEAR = 3; +} + +message DSTRule { + option (source) = SOURCE_CLIENT; + + sint32 time_seconds = 1; + uint32 day = 2; + DSTRuleType type = 3; + uint32 month = 4; + uint32 week = 5; + uint32 day_of_week = 6; +} + +message ParsedTimezone { + option (source) = SOURCE_CLIENT; + + sint32 std_offset_seconds = 1; + sint32 dst_offset_seconds = 2; + DSTRule dst_start = 3; + DSTRule dst_end = 4; +} + message GetTimeResponse { option (id) = 37; option (source) = SOURCE_CLIENT; @@ -841,6 +868,7 @@ message GetTimeResponse { fixed32 epoch_seconds = 1; string timezone = 2; + ParsedTimezone parsed_timezone = 3; } // ==================== USER-DEFINES SERVICES ==================== diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 215af611db..90287ec2dd 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1123,7 +1123,30 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) { homeassistant::global_homeassistant_time->set_epoch_time(value.epoch_seconds); #ifdef USE_TIME_TIMEZONE if (!value.timezone.empty()) { - homeassistant::global_homeassistant_time->set_timezone(value.timezone.c_str(), value.timezone.size()); + // Check if the sender provided pre-parsed timezone data. + // If std_offset is non-zero or DST rules are present, the parsed data was populated. + // For UTC (all zeros), string parsing produces the same result, so the fallback is equivalent. + const auto &pt = value.parsed_timezone; + if (pt.std_offset_seconds != 0 || pt.dst_start.type != enums::DST_RULE_TYPE_NONE) { + time::ParsedTimezone tz{}; + tz.std_offset_seconds = pt.std_offset_seconds; + tz.dst_offset_seconds = pt.dst_offset_seconds; + tz.dst_start.time_seconds = pt.dst_start.time_seconds; + tz.dst_start.day = static_cast<uint16_t>(pt.dst_start.day); + tz.dst_start.type = static_cast<time::DSTRuleType>(pt.dst_start.type); + tz.dst_start.month = static_cast<uint8_t>(pt.dst_start.month); + tz.dst_start.week = static_cast<uint8_t>(pt.dst_start.week); + tz.dst_start.day_of_week = static_cast<uint8_t>(pt.dst_start.day_of_week); + tz.dst_end.time_seconds = pt.dst_end.time_seconds; + tz.dst_end.day = static_cast<uint16_t>(pt.dst_end.day); + tz.dst_end.type = static_cast<time::DSTRuleType>(pt.dst_end.type); + tz.dst_end.month = static_cast<uint8_t>(pt.dst_end.month); + tz.dst_end.week = static_cast<uint8_t>(pt.dst_end.week); + tz.dst_end.day_of_week = static_cast<uint8_t>(pt.dst_end.day_of_week); + time::set_global_tz(tz); + } else { + homeassistant::global_homeassistant_time->set_timezone(value.timezone.c_str(), value.timezone.size()); + } } #endif } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 5c50a8aa5b..9e74d5ddc7 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -954,12 +954,66 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel return true; } #endif +bool DSTRule::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->time_seconds = value.as_sint32(); + break; + case 2: + this->day = value.as_uint32(); + break; + case 3: + this->type = static_cast<enums::DSTRuleType>(value.as_uint32()); + break; + case 4: + this->month = value.as_uint32(); + break; + case 5: + this->week = value.as_uint32(); + break; + case 6: + this->day_of_week = value.as_uint32(); + break; + default: + return false; + } + return true; +} +bool ParsedTimezone::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->std_offset_seconds = value.as_sint32(); + break; + case 2: + this->dst_offset_seconds = value.as_sint32(); + break; + default: + return false; + } + return true; +} +bool ParsedTimezone::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 3: + value.decode_to_message(this->dst_start); + break; + case 4: + value.decode_to_message(this->dst_end); + break; + default: + return false; + } + return true; +} bool GetTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { case 2: { this->timezone = StringRef(reinterpret_cast<const char *>(value.data()), value.size()); break; } + case 3: + value.decode_to_message(this->parsed_timezone); + break; default: return false; } diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 22dc3de995..033b789c18 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -63,6 +63,12 @@ enum LogLevel : uint32_t { LOG_LEVEL_VERBOSE = 6, LOG_LEVEL_VERY_VERBOSE = 7, }; +enum DSTRuleType : uint32_t { + DST_RULE_TYPE_NONE = 0, + DST_RULE_TYPE_MONTH_WEEK_DAY = 1, + DST_RULE_TYPE_JULIAN_NO_LEAP = 2, + DST_RULE_TYPE_DAY_OF_YEAR = 3, +}; #ifdef USE_API_USER_DEFINED_ACTIONS enum ServiceArgType : uint32_t { SERVICE_ARG_TYPE_BOOL = 0, @@ -1116,15 +1122,45 @@ class GetTimeRequest final : public ProtoMessage { protected: }; +class DSTRule final : public ProtoDecodableMessage { + public: + int32_t time_seconds{0}; + uint32_t day{0}; + enums::DSTRuleType type{}; + uint32_t month{0}; + uint32_t week{0}; + uint32_t day_of_week{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class ParsedTimezone final : public ProtoDecodableMessage { + public: + int32_t std_offset_seconds{0}; + int32_t dst_offset_seconds{0}; + DSTRule dst_start{}; + DSTRule dst_end{}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; class GetTimeResponse final : public ProtoDecodableMessage { public: static constexpr uint8_t MESSAGE_TYPE = 37; - static constexpr uint8_t ESTIMATED_SIZE = 14; + static constexpr uint8_t ESTIMATED_SIZE = 31; #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "get_time_response"; } #endif uint32_t epoch_seconds{0}; StringRef timezone{}; + ParsedTimezone parsed_timezone{}; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 52d2486410..4eec42e936 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -208,6 +208,20 @@ template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel val return "UNKNOWN"; } } +template<> const char *proto_enum_to_string<enums::DSTRuleType>(enums::DSTRuleType value) { + switch (value) { + case enums::DST_RULE_TYPE_NONE: + return "DST_RULE_TYPE_NONE"; + case enums::DST_RULE_TYPE_MONTH_WEEK_DAY: + return "DST_RULE_TYPE_MONTH_WEEK_DAY"; + case enums::DST_RULE_TYPE_JULIAN_NO_LEAP: + return "DST_RULE_TYPE_JULIAN_NO_LEAP"; + case enums::DST_RULE_TYPE_DAY_OF_YEAR: + return "DST_RULE_TYPE_DAY_OF_YEAR"; + default: + return "UNKNOWN"; + } +} #ifdef USE_API_USER_DEFINED_ACTIONS template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) { switch (value) { @@ -1254,10 +1268,35 @@ const char *GetTimeRequest::dump_to(DumpBuffer &out) const { out.append("GetTimeRequest {}"); return out.c_str(); } +const char *DSTRule::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "DSTRule"); + dump_field(out, "time_seconds", this->time_seconds); + dump_field(out, "day", this->day); + dump_field(out, "type", static_cast<enums::DSTRuleType>(this->type)); + dump_field(out, "month", this->month); + dump_field(out, "week", this->week); + dump_field(out, "day_of_week", this->day_of_week); + return out.c_str(); +} +const char *ParsedTimezone::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "ParsedTimezone"); + dump_field(out, "std_offset_seconds", this->std_offset_seconds); + dump_field(out, "dst_offset_seconds", this->dst_offset_seconds); + out.append(" dst_start: "); + this->dst_start.dump_to(out); + out.append("\n"); + out.append(" dst_end: "); + this->dst_end.dump_to(out); + out.append("\n"); + return out.c_str(); +} const char *GetTimeResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "GetTimeResponse"); dump_field(out, "epoch_seconds", this->epoch_seconds); dump_field(out, "timezone", this->timezone); + out.append(" parsed_timezone: "); + this->parsed_timezone.dump_to(out); + out.append("\n"); return out.c_str(); } #ifdef USE_API_USER_DEFINED_ACTIONS diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index a20d79b857..7ffa408db9 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -1,6 +1,10 @@ from importlib import resources import logging +from aioesphomeapi.posix_tz import ( + DSTRuleType as PyDSTRuleType, + parse_posix_tz as parse_posix_tz_python, +) import tzlocal from esphome import automation @@ -39,6 +43,19 @@ CronTrigger = time_ns.class_("CronTrigger", automation.Trigger.template(), cg.Co SyncTrigger = time_ns.class_("SyncTrigger", automation.Trigger.template(), cg.Component) TimeHasTimeCondition = time_ns.class_("TimeHasTimeCondition", Condition) +# C++ types for pre-parsed timezone struct generation +DSTRuleType_cpp = time_ns.enum("DSTRuleType", is_class=True) +DSTRule_cpp = time_ns.struct("DSTRule") +ParsedTimezone_cpp = time_ns.struct("ParsedTimezone") + +# Map Python DSTRuleType enum values to C++ enum expressions +_DST_RULE_TYPE_MAP = { + PyDSTRuleType.NONE: DSTRuleType_cpp.NONE, + PyDSTRuleType.MONTH_WEEK_DAY: DSTRuleType_cpp.MONTH_WEEK_DAY, + PyDSTRuleType.JULIAN_NO_LEAP: DSTRuleType_cpp.JULIAN_NO_LEAP, + PyDSTRuleType.DAY_OF_YEAR: DSTRuleType_cpp.DAY_OF_YEAR, +} + def _load_tzdata(iana_key: str) -> bytes | None: # From https://tzdata.readthedocs.io/en/latest/#examples @@ -260,11 +277,17 @@ def validate_tz(value: str) -> str: value = cv.string_strict(value) tzfile = _load_tzdata(value) - if tzfile is None: - # Not a IANA key, probably a TZ string - return value + if tzfile is not None: + value = _extract_tz_string(tzfile) - return _extract_tz_string(tzfile) + # Validate that the POSIX TZ string is parseable (skip empty strings) + if value: + try: + parse_posix_tz_python(value) + except ValueError as e: + raise cv.Invalid(f"Invalid POSIX timezone string '{value}': {e}") from e + + return value TIME_SCHEMA = cv.Schema( @@ -305,11 +328,46 @@ TIME_SCHEMA = cv.Schema( ).extend(cv.polling_component_schema("15min")) +def _emit_dst_rule_fields(prefix, rule): + """Emit field-by-field assignments for a DSTRule to avoid rodata struct blob.""" + cg.add(cg.RawExpression(f"{prefix}.time_seconds = {rule.time_seconds}")) + cg.add(cg.RawExpression(f"{prefix}.day = {rule.day}")) + cg.add(cg.RawExpression(f"{prefix}.type = {_DST_RULE_TYPE_MAP[rule.type]}")) + cg.add(cg.RawExpression(f"{prefix}.month = {rule.month}")) + cg.add(cg.RawExpression(f"{prefix}.week = {rule.week}")) + cg.add(cg.RawExpression(f"{prefix}.day_of_week = {rule.day_of_week}")) + + +def _emit_parsed_timezone_fields(parsed): + """Emit field-by-field assignments for a local ParsedTimezone, then set_global_tz(). + + Uses individual assignments on a stack variable instead of a struct initializer + to keep constants as immediate operands in instructions (.irom0.text/flash) + rather than a const blob in .rodata (which maps to RAM on ESP8266). + Wrapped in a scope block to allow multiple time platforms in the same build. + """ + cg.add(cg.RawStatement("{")) + cg.add(cg.RawExpression("time::ParsedTimezone tz{}")) + cg.add(cg.RawExpression(f"tz.std_offset_seconds = {parsed.std_offset_seconds}")) + cg.add(cg.RawExpression(f"tz.dst_offset_seconds = {parsed.dst_offset_seconds}")) + _emit_dst_rule_fields("tz.dst_start", parsed.dst_start) + _emit_dst_rule_fields("tz.dst_end", parsed.dst_end) + cg.add(time_ns.set_global_tz(cg.RawExpression("tz"))) + cg.add(cg.RawStatement("}")) + + async def setup_time_core_(time_var, config): if timezone := config.get(CONF_TIMEZONE): - cg.add(time_var.set_timezone(timezone)) cg.add_define("USE_TIME_TIMEZONE") + if CORE.is_host: + # Host platform needs setenv("TZ")/tzset() for libc compatibility + cg.add(time_var.set_timezone(timezone)) + else: + # Embedded: pre-parse at codegen time, emit struct directly + parsed = parse_posix_tz_python(timezone) + _emit_parsed_timezone_fields(parsed) + for conf in config.get(CONF_ON_TIME, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], time_var) From 073ca63f60bb23a7c84106eb57a5ce06388b1295 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Mon, 2 Mar 2026 04:44:02 +0100 Subject: [PATCH 1030/2030] [rtttl] improve comments Part 2 (#13971) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 189 ++++++++++++++++------------- esphome/components/rtttl/rtttl.h | 31 ++--- 2 files changed, 119 insertions(+), 101 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index ab95067f45..4ccfc539ea 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -8,18 +8,26 @@ namespace esphome::rtttl { static const char *const TAG = "rtttl"; -// These values can also be found as constants in the Tone library (Tone.h) -static const uint16_t NOTES[] = {0, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, - 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, - 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, - 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951}; +static constexpr uint8_t SONG_NAME_LENGTH_LIMIT = 64; +static constexpr uint8_t SEMITONES_IN_OCTAVE = 12; -#if defined(USE_OUTPUT) || defined(USE_SPEAKER) -static const uint32_t DOUBLE_NOTE_GAP_MS = 10; -#endif // USE_OUTPUT || USE_SPEAKER +static constexpr uint8_t MIN_OCTAVE = 4; +static constexpr uint8_t MAX_OCTAVE = 7; + +static constexpr uint8_t DEFAULT_BPM = 63; // Default beats per minute + +// These values can also be found as constants in the Tone library (Tone.h) +static constexpr uint16_t NOTES[] = {0, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, + 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, + 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, + 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951}; +static constexpr uint8_t NOTES_COUNT = static_cast<uint8_t>(sizeof(NOTES) / sizeof(NOTES[0])); + +static constexpr uint8_t REPEATING_NOTE_GAP_MS = 10; #ifdef USE_SPEAKER -static const size_t SAMPLE_BUFFER_SIZE = 2048; +static constexpr uint16_t SAMPLE_BUFFER_SIZE = 2048; +static constexpr uint16_t SAMPLE_RATE = 16000; struct SpeakerSample { int8_t left{0}; @@ -27,7 +35,7 @@ struct SpeakerSample { }; inline double deg2rad(double degrees) { - static const double PI_ON_180 = 4.0 * atan(1.0) / 180.0; + static constexpr double PI_ON_180 = M_PI / 180.0; return degrees * PI_ON_180; } #endif // USE_SPEAKER @@ -85,7 +93,7 @@ void Rtttl::loop() { } #ifdef USE_OUTPUT - if (this->output_ != nullptr && millis() - this->last_note_ < this->note_duration_) { + if (this->output_ != nullptr && millis() - this->last_note_start_time_ < this->note_duration_) { return; } #endif // USE_OUTPUT @@ -113,36 +121,34 @@ void Rtttl::loop() { } if (this->samples_sent_ != this->samples_count_) { SpeakerSample sample[SAMPLE_BUFFER_SIZE + 2]; - int x = 0; + uint16_t sample_index = 0; double rem = 0.0; while (true) { - // Try and send out the remainder of the existing note, one per loop() - - if (this->samples_per_wave_ != 0 && this->samples_sent_ >= this->samples_gap_) { // Play note// + // Try and send out the remainder of the existing note, one per `loop()` + if (this->samples_per_wave_ != 0 && this->samples_sent_ >= this->samples_gap_) { // Play note rem = ((this->samples_sent_ << 10) % this->samples_per_wave_) * (360.0 / this->samples_per_wave_); - int16_t val = (127 * this->gain_) * sin(deg2rad(rem)); // 16bit = 49152 - - sample[x].left = val; - sample[x].right = val; + int8_t val = (127 * this->gain_) * sin(deg2rad(rem)); + sample[sample_index].left = val; + sample[sample_index].right = val; } else { - sample[x].left = 0; - sample[x].right = 0; + sample[sample_index].left = 0; + sample[sample_index].right = 0; } - if (static_cast<size_t>(x) >= SAMPLE_BUFFER_SIZE || this->samples_sent_ >= this->samples_count_) { + if (sample_index >= SAMPLE_BUFFER_SIZE || this->samples_sent_ >= this->samples_count_) { break; } this->samples_sent_++; - x++; + sample_index++; } - if (x > 0) { - size_t bytes_to_send = x * sizeof(SpeakerSample); + if (sample_index > 0) { + size_t bytes_to_send = sample_index * sizeof(SpeakerSample); size_t send = this->speaker_->play((uint8_t *) (&sample), bytes_to_send); if (send != bytes_to_send) { - this->samples_sent_ -= (x - (send / sizeof(SpeakerSample))); + this->samples_sent_ -= (sample_index - (send / sizeof(SpeakerSample))); } return; } @@ -155,83 +161,84 @@ void Rtttl::loop() { return; } - // align to note: most rtttl's out there does not add and space after the ',' separator but just in case... + // Align to note: most rtttl's out there does not add any space after the ',' separator but just in case while (this->rtttl_[this->position_] == ',' || this->rtttl_[this->position_] == ' ') { this->position_++; } - // first, get note duration, if available - uint8_t num = this->get_integer_(); + // First, get note duration, if available + uint8_t note_denominator = this->get_integer_(); - if (num) { - this->note_duration_ = this->wholenote_ / num; + if (note_denominator) { + this->note_duration_ = this->wholenote_duration_ / note_denominator; } else { - this->note_duration_ = - this->wholenote_ / this->default_duration_; // we will need to check if we are a dotted note after + // We will need to check if we are a dotted note after + this->note_duration_ = this->wholenote_duration_ / this->default_note_denominator_; } - uint8_t note = note_index_from_char(this->rtttl_[this->position_]); + uint8_t note_index_in_octave = note_index_from_char(this->rtttl_[this->position_]); this->position_++; - // now, get optional '#' sharp + // Now, get optional '#' sharp if (this->rtttl_[this->position_] == '#') { - note++; + note_index_in_octave++; this->position_++; } - // now, get scale + // Now, get scale uint8_t scale = this->get_integer_(); if (scale == 0) { scale = this->default_octave_; } - if (scale < 4 || scale > 7) { - ESP_LOGE(TAG, "Octave must be between 4 and 7 (it is %d)", scale); + if (scale < MIN_OCTAVE || scale > MAX_OCTAVE) { + ESP_LOGE(TAG, "Octave must be between %d and %d (it is %d)", MIN_OCTAVE, MAX_OCTAVE, scale); this->finish_(); return; } - // now, get optional '.' dotted note + // Now, get optional '.' dotted note if (this->rtttl_[this->position_] == '.') { - this->note_duration_ += this->note_duration_ / 2; + this->note_duration_ += this->note_duration_ / 2; // Duration +50% this->position_++; } - // Now play the note bool need_note_gap = false; - if (note) { - auto note_index = (scale - 4) * 12 + note; - if (note_index < 0 || note_index >= (int) (sizeof(NOTES) / sizeof(NOTES[0]))) { - ESP_LOGE(TAG, "Note out of range (note: %d, scale: %d, index: %d, max: %d)", note, scale, note_index, - (int) (sizeof(NOTES) / sizeof(NOTES[0]))); + + // Now play the note + if (note_index_in_octave == 0) { + this->output_freq_ = 0; + ESP_LOGVV(TAG, "Waiting: %dms", this->note_duration_); + } else { + uint8_t note_index = (scale - MIN_OCTAVE) * SEMITONES_IN_OCTAVE + note_index_in_octave; + if (note_index >= NOTES_COUNT) { + ESP_LOGE(TAG, "Note out of range (note: %d, scale: %d, index: %d, max: %d)", note_index_in_octave, scale, + note_index, NOTES_COUNT); this->finish_(); return; } - auto freq = NOTES[note_index]; + uint16_t freq = NOTES[note_index]; need_note_gap = freq == this->output_freq_; // Add small silence gap between same note this->output_freq_ = freq; - ESP_LOGVV(TAG, "playing note: %d for %dms", note, this->note_duration_); - } else { - ESP_LOGVV(TAG, "waiting: %dms", this->note_duration_); - this->output_freq_ = 0; + ESP_LOGVV(TAG, "Playing note: %d for %dms", note_index_in_octave, this->note_duration_); } #ifdef USE_OUTPUT if (this->output_ != nullptr) { - if (need_note_gap && this->note_duration_ > DOUBLE_NOTE_GAP_MS) { + if (this->output_freq_ == 0) { this->output_->set_level(0.0); - delay(DOUBLE_NOTE_GAP_MS); - this->note_duration_ -= DOUBLE_NOTE_GAP_MS; - } - if (this->output_freq_ != 0) { + } else { + if (need_note_gap && this->note_duration_ > REPEATING_NOTE_GAP_MS) { + this->output_->set_level(0.0); + delay(REPEATING_NOTE_GAP_MS); + this->note_duration_ -= REPEATING_NOTE_GAP_MS; + } this->output_->update_frequency(this->output_freq_); this->output_->set_level(this->gain_); - } else { - this->output_->set_level(0.0); } } #endif // USE_OUTPUT @@ -241,28 +248,26 @@ void Rtttl::loop() { this->samples_sent_ = 0; this->samples_gap_ = 0; this->samples_per_wave_ = 0; - this->samples_count_ = (this->sample_rate_ * this->note_duration_) / 1000; + this->samples_count_ = (SAMPLE_RATE * this->note_duration_) / 1000; if (need_note_gap) { - this->samples_gap_ = (this->sample_rate_ * DOUBLE_NOTE_GAP_MS) / 1000; + this->samples_gap_ = (SAMPLE_RATE * REPEATING_NOTE_GAP_MS) / 1000; } if (this->output_freq_ != 0) { - // make sure there is enough samples to add a full last sinus. - - uint16_t samples_wish = this->samples_count_; - this->samples_per_wave_ = (this->sample_rate_ << 10) / this->output_freq_; + // Make sure there is enough samples to add a full last sinus. + uint32_t samples_wish = this->samples_count_; + this->samples_per_wave_ = (SAMPLE_RATE << 10) / this->output_freq_; uint16_t division = ((this->samples_count_ << 10) / this->samples_per_wave_) + 1; - this->samples_count_ = (division * this->samples_per_wave_); - this->samples_count_ = this->samples_count_ >> 10; - ESP_LOGVV(TAG, "- Calc play time: wish: %d gets: %d (div: %d spw: %d)", samples_wish, this->samples_count_, - division, this->samples_per_wave_); + this->samples_count_ = (division * this->samples_per_wave_) >> 10; + ESP_LOGVV(TAG, "Calc play time: wish: %" PRIu32 " gets: %" PRIu32 " (div: %d spw: %" PRIu32 ")", samples_wish, + this->samples_count_, division, this->samples_per_wave_); } // Convert from frequency in Hz to high and low samples in fixed point } #endif // USE_SPEAKER - this->last_note_ = millis(); + this->last_note_start_time_ = millis(); } void Rtttl::play(std::string rtttl) { @@ -275,25 +280,28 @@ void Rtttl::play(std::string rtttl) { this->rtttl_ = std::move(rtttl); - this->default_duration_ = 4; - this->default_octave_ = 6; + this->default_note_denominator_ = DEFAULT_NOTE_DENOMINATOR; + this->default_octave_ = DEFAULT_OCTAVE; this->note_duration_ = 0; - int bpm = 63; - uint16_t num; + uint16_t bpm = DEFAULT_BPM; + uint16_t num; // Used for: default note-denominator, default octave, BPM // Get name this->position_ = this->rtttl_.find(':'); - // it's somewhat documented to be up to 10 characters but let's be a bit flexible here - if (this->position_ == std::string::npos || this->position_ > 15) { + if (this->position_ == std::string::npos) { ESP_LOGE(TAG, "Unable to determine name; missing ':'"); return; } - + if (this->position_ >= SONG_NAME_LENGTH_LIMIT) { + ESP_LOGE(TAG, "Name is too long: length=%u, limit=%u", static_cast<unsigned>(this->position_), + static_cast<unsigned>(SONG_NAME_LENGTH_LIMIT)); + return; + } ESP_LOGD(TAG, "Playing song %.*s", (int) this->position_, this->rtttl_.c_str()); - // get default duration + // Get default duration this->position_ = this->rtttl_.find("d=", this->position_); if (this->position_ == std::string::npos) { ESP_LOGE(TAG, "Missing 'd='"); @@ -301,11 +309,14 @@ void Rtttl::play(std::string rtttl) { } this->position_ += 2; num = this->get_integer_(); - if (num > 0) { - this->default_duration_ = num; + if (num == 1 || num == 2 || num == 4 || num == 8 || num == 16 || num == 32) { + this->default_note_denominator_ = num; + } else { + ESP_LOGE(TAG, "Invalid default duration: %d", num); + return; } - // get default octave + // Get default octave this->position_ = this->rtttl_.find("o=", this->position_); if (this->position_ == std::string::npos) { ESP_LOGE(TAG, "Missing 'o="); @@ -313,11 +324,14 @@ void Rtttl::play(std::string rtttl) { } this->position_ += 2; num = this->get_integer_(); - if (num >= 3 && num <= 7) { + if (num >= MIN_OCTAVE && num <= MAX_OCTAVE) { this->default_octave_ = num; + } else { + ESP_LOGE(TAG, "Invalid default octave: %d", num); + return; } - // get BPM + // Get BPM this->position_ = this->rtttl_.find("b=", this->position_); if (this->position_ == std::string::npos) { ESP_LOGE(TAG, "Missing b="); @@ -325,8 +339,11 @@ void Rtttl::play(std::string rtttl) { } this->position_ += 2; num = this->get_integer_(); - if (num != 0) { + if (num >= 4) { // Below 4 is not realistic and would cause a integer overflow bpm = num; + } else { + ESP_LOGE(TAG, "Invalid BPM: %d", num); + return; } this->position_ = this->rtttl_.find(':', this->position_); @@ -337,10 +354,10 @@ void Rtttl::play(std::string rtttl) { this->position_++; // BPM usually expresses the number of quarter notes per minute - this->wholenote_ = 60 * 1000L * 4 / bpm; // this is the time for whole note (in milliseconds) + this->wholenote_duration_ = 60 * 1000L * 4 / bpm; // This is the time for whole note (in milliseconds) this->output_freq_ = 0; - this->last_note_ = millis(); + this->last_note_start_time_ = millis(); this->note_duration_ = 1; #ifdef USE_OUTPUT diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index 4d4a652c51..e37cccae9e 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -13,6 +13,10 @@ namespace esphome::rtttl { +inline constexpr uint8_t DEFAULT_NOTE_DENOMINATOR = 4; // Default note-denominator (quarter note) +inline constexpr uint8_t DEFAULT_OCTAVE = + 6; // Default octave for a note (see: `MIN_OCTAVE`, `MAX_OCTAVE` in `rtttl.cpp`) + enum class State : uint8_t { STOPPED = 0, INIT, @@ -67,19 +71,18 @@ class Rtttl : public Component { std::string rtttl_{""}; /// The current position in the RTTTL string. size_t position_{0}; - /// The duration of a whole note in milliseconds. - uint16_t wholenote_; /// The default duration of a note (e.g. 4 for a quarter note). - uint16_t default_duration_; + uint8_t default_note_denominator_{DEFAULT_NOTE_DENOMINATOR}; /// The default octave for a note. - uint16_t default_octave_; - /// The time the last note was started. - uint32_t last_note_; + uint8_t default_octave_{DEFAULT_OCTAVE}; /// The duration of the current note in milliseconds. - uint16_t note_duration_; - + uint16_t note_duration_{0}; + /// The duration of a whole note in milliseconds. + uint16_t wholenote_duration_; + /// The time in milliseconds since microcontroller boot when the last note was started. + uint32_t last_note_start_time_; /// The frequency of the current note in Hz. - uint32_t output_freq_; + uint32_t output_freq_{0}; /// The gain of the output. float gain_{0.6f}; /// The current state of the RTTTL player. @@ -93,16 +96,14 @@ class Rtttl : public Component { #ifdef USE_SPEAKER /// The speaker to write the sound to. speaker::Speaker *speaker_{nullptr}; - /// The sample rate of the speaker. - int sample_rate_{16000}; /// The number of samples for one full cycle of a note's waveform, in Q10 fixed-point format. - int samples_per_wave_{0}; + uint32_t samples_per_wave_{0}; /// The number of samples sent. - int samples_sent_{0}; + uint32_t samples_sent_{0}; /// The total number of samples to send. - int samples_count_{0}; + uint32_t samples_count_{0}; /// The number of samples for the gap between notes. - int samples_gap_{0}; + uint32_t samples_gap_{0}; #endif // USE_SPEAKER /// The callback to call when playback is finished. From 6d3d8970a67dfeed99e48e36388b319b40f3ad79 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 2 Mar 2026 04:47:02 +0100 Subject: [PATCH 1031/2030] [openthread] Disable default enabled OT diag code (#14399) --- esphome/components/openthread/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/openthread/__init__.py b/esphome/components/openthread/__init__.py index 89d335c574..dde4987181 100644 --- a/esphome/components/openthread/__init__.py +++ b/esphome/components/openthread/__init__.py @@ -53,6 +53,9 @@ def set_sdkconfig_options(config): # There is a conflict if the logger's uart also uses the default UART, which is seen as a watchdog failure on "ot_cli" add_idf_sdkconfig_option("CONFIG_OPENTHREAD_CLI", False) + # Diag unused, if needed for lab/cert/etc tests then enable separately + add_idf_sdkconfig_option("CONFIG_OPENTHREAD_DIAG", False) + add_idf_sdkconfig_option("CONFIG_OPENTHREAD_ENABLED", True) if tlv := config.get(CONF_TLV): From f68a3ed15d441a90cd96415af05cc69ad2ab5411 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 18:09:00 -1000 Subject: [PATCH 1032/2030] [api] Remove virtual destructor from ProtoMessage (#14393) --- esphome/components/api/api_pb2.h | 6 +++--- esphome/components/api/proto.h | 7 ++++++- script/api_protobuf/api_protobuf.py | 5 ++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 033b789c18..a97f6c0a76 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -322,7 +322,6 @@ enum ZWaveProxyRequestType : uint32_t { class InfoResponseProtoMessage : public ProtoMessage { public: - ~InfoResponseProtoMessage() override = default; StringRef object_id{}; uint32_t key{0}; StringRef name{}; @@ -336,28 +335,29 @@ class InfoResponseProtoMessage : public ProtoMessage { #endif protected: + ~InfoResponseProtoMessage() = default; }; class StateResponseProtoMessage : public ProtoMessage { public: - ~StateResponseProtoMessage() override = default; uint32_t key{0}; #ifdef USE_DEVICES uint32_t device_id{0}; #endif protected: + ~StateResponseProtoMessage() = default; }; class CommandProtoMessage : public ProtoDecodableMessage { public: - ~CommandProtoMessage() override = default; uint32_t key{0}; #ifdef USE_DEVICES uint32_t device_id{0}; #endif protected: + ~CommandProtoMessage() = default; }; class HelloRequest final : public ProtoDecodableMessage { public: diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index c34f7744e6..750fff0810 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -452,7 +452,6 @@ class DumpBuffer { class ProtoMessage { public: - virtual ~ProtoMessage() = default; // Default implementation for messages with no fields virtual void encode(ProtoWriteBuffer &buffer) const {} // Default implementation for messages with no fields @@ -463,6 +462,11 @@ class ProtoMessage { virtual const char *dump_to(DumpBuffer &out) const = 0; virtual const char *message_name() const { return "unknown"; } #endif + + protected: + // Non-virtual: messages are never deleted polymorphically. + // Protected prevents accidental `delete base_ptr` (compile error). + ~ProtoMessage() = default; }; // Base class for messages that support decoding @@ -482,6 +486,7 @@ class ProtoDecodableMessage : public ProtoMessage { static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id); protected: + ~ProtoDecodableMessage() = default; virtual bool decode_varint(uint32_t field_id, ProtoVarInt value) { return false; } virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; } virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 350947a8d6..9c9cda4d36 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2473,9 +2473,6 @@ def build_base_class( out = f"class {base_class_name} : public {parent_class} {{\n" out += " public:\n" - # Add destructor with override - public_content.insert(0, f"~{base_class_name}() override = default;") - # Base classes don't implement encode/decode/calculate_size # Derived classes handle these with their specific field numbers cpp = "" @@ -2483,6 +2480,8 @@ def build_base_class( out += indent("\n".join(public_content)) + "\n" out += "\n" out += " protected:\n" + # Non-virtual protected destructor prevents accidental polymorphic deletion + protected_content.insert(0, f"~{base_class_name}() = default;") out += indent("\n".join(protected_content)) if protected_content: out += "\n" From 80a2acca4f576b5c43fa0a87b5752a68e1d85b6c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 18:19:32 -1000 Subject: [PATCH 1033/2030] [ld2410] Add UART mock integration test for LD2410 component (#14377) --- .../external_components/uart_mock/__init__.py | 86 ++++ .../uart_mock/uart_mock.cpp | 159 +++++++ .../external_components/uart_mock/uart_mock.h | 78 ++++ .../fixtures/uart_mock_ld2410.yaml | 145 +++++++ .../uart_mock_ld2410_engineering.yaml | 156 +++++++ tests/integration/test_uart_mock_ld2410.py | 392 ++++++++++++++++++ 6 files changed, 1016 insertions(+) create mode 100644 tests/integration/fixtures/external_components/uart_mock/__init__.py create mode 100644 tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp create mode 100644 tests/integration/fixtures/external_components/uart_mock/uart_mock.h create mode 100644 tests/integration/fixtures/uart_mock_ld2410.yaml create mode 100644 tests/integration/fixtures/uart_mock_ld2410_engineering.yaml create mode 100644 tests/integration/test_uart_mock_ld2410.py diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py new file mode 100644 index 0000000000..5bd879ab12 --- /dev/null +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -0,0 +1,86 @@ +import esphome.codegen as cg +from esphome.components import uart +from esphome.components.uart import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS +import esphome.config_validation as cv +from esphome.const import CONF_BAUD_RATE, CONF_DATA, CONF_DELAY, CONF_ID, CONF_INTERVAL + +CODEOWNERS = ["@esphome/tests"] +MULTI_CONF = True + +uart_mock_ns = cg.esphome_ns.namespace("uart_mock") +MockUartComponent = uart_mock_ns.class_( + "MockUartComponent", uart.UARTComponent, cg.Component +) + +CONF_INJECTIONS = "injections" +CONF_RESPONSES = "responses" +CONF_INJECT_RX = "inject_rx" +CONF_EXPECT_TX = "expect_tx" +CONF_PERIODIC_RX = "periodic_rx" + +UART_PARITY_OPTIONS = { + "NONE": uart.UARTParityOptions.UART_CONFIG_PARITY_NONE, + "EVEN": uart.UARTParityOptions.UART_CONFIG_PARITY_EVEN, + "ODD": uart.UARTParityOptions.UART_CONFIG_PARITY_ODD, +} + +INJECTION_SCHEMA = cv.Schema( + { + cv.Required(CONF_INJECT_RX): [cv.hex_uint8_t], + cv.Optional(CONF_DELAY, default="0ms"): cv.positive_time_period_milliseconds, + } +) + +RESPONSE_SCHEMA = cv.Schema( + { + cv.Required(CONF_EXPECT_TX): [cv.hex_uint8_t], + cv.Required(CONF_INJECT_RX): [cv.hex_uint8_t], + } +) + +PERIODIC_RX_SCHEMA = cv.Schema( + { + cv.Required(CONF_DATA): [cv.hex_uint8_t], + cv.Required(CONF_INTERVAL): cv.positive_time_period_milliseconds, + } +) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(MockUartComponent), + cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), + cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), + cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), + cv.Optional(CONF_PARITY, default="NONE"): cv.enum( + UART_PARITY_OPTIONS, upper=True + ), + cv.Optional(CONF_INJECTIONS, default=[]): cv.ensure_list(INJECTION_SCHEMA), + cv.Optional(CONF_RESPONSES, default=[]): cv.ensure_list(RESPONSE_SCHEMA), + cv.Optional(CONF_PERIODIC_RX, default=[]): cv.ensure_list(PERIODIC_RX_SCHEMA), + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + cg.add(var.set_baud_rate(config[CONF_BAUD_RATE])) + cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) + cg.add(var.set_data_bits(config[CONF_DATA_BITS])) + cg.add(var.set_parity(config[CONF_PARITY])) + + for injection in config[CONF_INJECTIONS]: + rx_data = injection[CONF_INJECT_RX] + delay_ms = injection[CONF_DELAY] + cg.add(var.add_injection(rx_data, delay_ms)) + + for response in config[CONF_RESPONSES]: + tx_data = response[CONF_EXPECT_TX] + rx_data = response[CONF_INJECT_RX] + cg.add(var.add_response(tx_data, rx_data)) + + for periodic in config[CONF_PERIODIC_RX]: + data = periodic[CONF_DATA] + interval = periodic[CONF_INTERVAL] + cg.add(var.add_periodic_rx(data, interval)) diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp new file mode 100644 index 0000000000..a49d51ba10 --- /dev/null +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -0,0 +1,159 @@ +// Host-only test component — do not copy to production code. +// See uart_mock.h for details. + +#include "uart_mock.h" +#include "esphome/core/application.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome::uart_mock { + +static const char *const TAG = "uart_mock"; + +void MockUartComponent::setup() { + ESP_LOGI(TAG, "Mock UART initialized with %zu injections, %zu responses, %zu periodic", this->injections_.size(), + this->responses_.size(), this->periodic_rx_.size()); +} + +void MockUartComponent::loop() { + uint32_t now = App.get_loop_component_start_time(); + + // Initialize scenario start time on first loop() call, after all components have + // finished setup(). This prevents injection delays from being consumed during setup. + if (!this->loop_started_) { + this->loop_started_ = true; + this->scenario_start_ms_ = now; + this->cumulative_delay_ms_ = 0; + ESP_LOGD(TAG, "Scenario started at %u ms", now); + } + + // Process at most ONE timed injection per loop iteration. + // This ensures each injection is in a separate loop cycle, giving the consuming + // component (e.g., LD2410) a chance to process each batch independently. + if (this->injection_index_ < this->injections_.size()) { + auto &injection = this->injections_[this->injection_index_]; + uint32_t target_time = this->scenario_start_ms_ + this->cumulative_delay_ms_ + injection.delay_ms; + if (now >= target_time) { + ESP_LOGD(TAG, "Injecting %zu RX bytes (injection %u)", injection.rx_data.size(), this->injection_index_); + this->inject_to_rx_buffer_(injection.rx_data); + this->cumulative_delay_ms_ += injection.delay_ms; + this->injection_index_++; + } + } + + // Process periodic RX + for (auto &periodic : this->periodic_rx_) { + if (now - periodic.last_inject_ms >= periodic.interval_ms) { + this->inject_to_rx_buffer_(periodic.data); + periodic.last_inject_ms = now; + } + } +} + +void MockUartComponent::dump_config() { + ESP_LOGCONFIG(TAG, + "Mock UART Component:\n" + " Baud Rate: %u\n" + " Injections: %zu\n" + " Responses: %zu\n" + " Periodic RX: %zu", + this->baud_rate_, this->injections_.size(), this->responses_.size(), this->periodic_rx_.size()); +} + +void MockUartComponent::write_array(const uint8_t *data, size_t len) { + this->tx_count_ += len; + this->tx_buffer_.insert(this->tx_buffer_.end(), data, data + len); + + // Log all TX data so tests can verify what the component sends + if (len > 0 && len <= 64) { + char hex_buf[format_hex_pretty_size(64)]; + ESP_LOGD(TAG, "TX %zu bytes: %s", len, format_hex_pretty_to(hex_buf, sizeof(hex_buf), data, len)); + } else if (len > 64) { + ESP_LOGD(TAG, "TX %zu bytes (too large to log)", len); + } + +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(uart::UART_DIRECTION_TX, data[i]); + } +#endif + + this->try_match_response_(); +} + +bool MockUartComponent::peek_byte(uint8_t *data) { + if (this->rx_buffer_.empty()) { + return false; + } + *data = this->rx_buffer_.front(); + return true; +} + +bool MockUartComponent::read_array(uint8_t *data, size_t len) { + if (this->rx_buffer_.size() < len) { + return false; + } + for (size_t i = 0; i < len; i++) { + data[i] = this->rx_buffer_.front(); + this->rx_buffer_.pop_front(); + } + this->rx_count_ += len; + +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(uart::UART_DIRECTION_RX, data[i]); + } +#endif + + return true; +} + +size_t MockUartComponent::available() { return this->rx_buffer_.size(); } + +void MockUartComponent::flush() { + // Nothing to flush in mock +} + +void MockUartComponent::add_injection(const std::vector<uint8_t> &rx_data, uint32_t delay_ms) { + this->injections_.push_back({rx_data, delay_ms}); +} + +void MockUartComponent::add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx) { + this->responses_.push_back({expect_tx, inject_rx}); +} + +void MockUartComponent::add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms) { + this->periodic_rx_.push_back({data, interval_ms, 0}); +} + +void MockUartComponent::try_match_response_() { + for (auto &response : this->responses_) { + if (this->tx_buffer_.size() < response.expect_tx.size()) { + continue; + } + // Check if tx_buffer_ ends with expect_tx + size_t offset = this->tx_buffer_.size() - response.expect_tx.size(); + if (std::equal(response.expect_tx.begin(), response.expect_tx.end(), this->tx_buffer_.begin() + offset)) { + ESP_LOGD(TAG, "TX match found, injecting %zu RX bytes", response.inject_rx.size()); + this->inject_to_rx_buffer_(response.inject_rx); + this->tx_buffer_.clear(); + return; + } + } +} + +void MockUartComponent::inject_to_rx_buffer_(const std::vector<uint8_t> &data) { + // Log injected RX data so tests can see what's being fed to the component + if (!data.empty() && data.size() <= 64) { + char hex_buf[format_hex_pretty_size(64)]; + ESP_LOGD(TAG, "RX inject %zu bytes: %s", data.size(), + format_hex_pretty_to(hex_buf, sizeof(hex_buf), data.data(), data.size())); + } else if (data.size() > 64) { + ESP_LOGD(TAG, "RX inject %zu bytes (too large to log inline)", data.size()); + } + for (uint8_t byte : data) { + this->rx_buffer_.push_back(byte); + } +} + +} // namespace esphome::uart_mock diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h new file mode 100644 index 0000000000..00f4bf2e2b --- /dev/null +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -0,0 +1,78 @@ +#pragma once + +// ============================================================================ +// HOST-ONLY TEST COMPONENT — DO NOT COPY TO PRODUCTION CODE +// +// This component runs exclusively on the host platform for integration testing. +// It intentionally uses std::vector, std::deque, and dynamic allocation which +// would be inappropriate for production embedded components. Do not use this +// code as a reference for writing ESPHome components targeting real hardware. +// ============================================================================ + +#include "esphome/core/component.h" +#include "esphome/components/uart/uart_component.h" +#include <deque> +#include <vector> + +namespace esphome::uart_mock { + +class MockUartComponent : public uart::UARTComponent, public Component { + public: + void setup() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::BUS; } + + // UARTComponent interface + void write_array(const uint8_t *data, size_t len) override; + bool peek_byte(uint8_t *data) override; + bool read_array(uint8_t *data, size_t len) override; + size_t available() override; + void flush() override; + + // Scenario configuration - called from generated code + void add_injection(const std::vector<uint8_t> &rx_data, uint32_t delay_ms); + void add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx); + void add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms); + + protected: + void check_logger_conflict() override {} + void try_match_response_(); + void inject_to_rx_buffer_(const std::vector<uint8_t> &data); + + // Timed injections + struct Injection { + std::vector<uint8_t> rx_data; + uint32_t delay_ms; + }; + std::vector<Injection> injections_; + uint32_t injection_index_{0}; + uint32_t scenario_start_ms_{0}; + uint32_t cumulative_delay_ms_{0}; + bool loop_started_{false}; + + // TX-triggered responses + struct Response { + std::vector<uint8_t> expect_tx; + std::vector<uint8_t> inject_rx; + }; + std::vector<Response> responses_; + std::vector<uint8_t> tx_buffer_; + + // RX buffer + std::deque<uint8_t> rx_buffer_; + + // Periodic RX + struct PeriodicRx { + std::vector<uint8_t> data; + uint32_t interval_ms; + uint32_t last_inject_ms{0}; + }; + std::vector<PeriodicRx> periodic_rx_; + + // Observability + uint32_t tx_count_{0}; + uint32_t rx_count_{0}; +}; + +} // namespace esphome::uart_mock diff --git a/tests/integration/fixtures/uart_mock_ld2410.yaml b/tests/integration/fixtures/uart_mock_ld2410.yaml new file mode 100644 index 0000000000..9a81468263 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2410.yaml @@ -0,0 +1,145 @@ +esphome: + name: uart-mock-ld2410-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2410's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + injections: + # Phase 1 (t=100ms): Valid LD2410 normal mode data frame - happy path + # The buffer is clean at this point, so this frame should parse correctly. + # Moving target: 100cm, energy 50 + # Still target: 120cm, energy 25 + # Detection distance: 300cm + # Target state: 0x03 (moving + still) + # + # Note: LD2410's two_byte_to_int() uses signed char, so low bytes must be + # <=127 to produce correct values. Values >127 wrap negative. + # + # Frame layout (24 bytes): + # [0-3] F4 F3 F2 F1 = data frame header + # [4-5] 0D 00 = length 13 + # [6] 02 = data type (normal) + # [7] AA = data header marker + # [8] 03 = target states (moving+still) + # [9-10] 64 00 = moving distance 100 (0x0064) + # [11] 32 = moving energy 50 + # [12-13] 78 00 = still distance 120 (0x0078) + # [14] 19 = still energy 25 + # [15-16] 2C 01 = detection distance 300 (0x012C) + # [17] 00 = padding + # [18] 55 = data footer marker + # [19] 00 = CRC/check + # [20-23] F8 F7 F6 F5 = data frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x0D, 0x00, + 0x02, 0xAA, + 0x03, + 0x64, 0x00, + 0x32, + 0x78, 0x00, + 0x19, + 0x2C, 0x01, + 0x00, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=200ms): Garbage bytes - corrupt the buffer + # These random bytes will accumulate in the LD2410's internal buffer. + # No footer will be found, so the buffer just grows. + - delay: 100ms + inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22] + + # Phase 3 (t=300ms): Truncated frame (header + partial data, no footer) + # More bytes accumulating in the buffer without a footer match. + - delay: 100ms + inject_rx: [0xF4, 0xF3, 0xF2, 0xF1, 0x0D, 0x00, 0x02, 0xAA] + + # Phase 4 (t=500ms): Overflow - inject 85 bytes of 0xFF (MAX_LINE_LENGTH=50) + # Buffer has 15 bytes from phases 2+3. + # Overflow math: need 35 bytes to trigger first overflow (pos 15->49), + # then 50 more to trigger second overflow (pos 0->49). Total = 85 bytes. + # After two overflows, buffer_pos_ = 0 with a completely clean buffer. + # The LD2410 logs "Max command length exceeded" at each overflow. + - delay: 200ms + inject_rx: + [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ] + + # Phase 5 (t=600ms): Valid frame after overflow - recovery test + # Buffer was reset by overflow. This valid frame should parse correctly. + # Moving target: 50cm, energy 100 + # Still target: 75cm, energy 80 + # Detection distance: 127cm + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x0D, 0x00, + 0x02, 0xAA, + 0x03, + 0x32, 0x00, + 0x64, + 0x4B, 0x00, + 0x50, + 0x7F, 0x00, + 0x00, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +ld2410: + id: ld2410_dev + uart_id: mock_uart + +sensor: + - platform: ld2410 + ld2410_id: ld2410_dev + moving_distance: + name: "Moving Distance" + still_distance: + name: "Still Distance" + moving_energy: + name: "Moving Energy" + still_energy: + name: "Still Energy" + detection_distance: + name: "Detection Distance" + +binary_sensor: + - platform: ld2410 + ld2410_id: ld2410_dev + has_target: + name: "Has Target" + has_moving_target: + name: "Has Moving Target" + has_still_target: + name: "Has Still Target" diff --git a/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml new file mode 100644 index 0000000000..3b730fc1f8 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml @@ -0,0 +1,156 @@ +esphome: + name: uart-mock-ld2410-eng-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2410's DEPENDENCIES = ["uart"] +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + injections: + # Phase 1 (t=100ms): Valid LD2410 engineering mode data frame + # Captured from a real Screek Human Presence Sensor 1U with LD2410 firmware 2.4.x + # + # Engineering mode frame layout (45 bytes): + # [0-3] F4 F3 F2 F1 = data frame header + # [4-5] 23 00 = length 35 + # [6] 01 = data type (engineering mode) + # [7] AA = data header marker + # [8] 03 = target states (moving+still) + # [9-10] 1E 00 = moving distance 30 (0x001E) + # [11] 64 = moving energy 100 + # [12-13] 1E 00 = still distance 30 (0x001E) + # [14] 64 = still energy 100 + # [15-16] 00 00 = detection distance 0 + # [17] 08 = max moving distance gate + # [18] 08 = max still distance gate + # [19-27] gate moving energies (gates 0-8) + # [28-36] gate still energies (gates 0-8) + # [37] 57 = light sensor value 87 + # [38] 01 = out pin presence (HIGH) + # [39] 55 = data footer marker + # [40] 00 = check + # [41-44] F8 F7 F6 F5 = data frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, 0xAA, + 0x03, + 0x1E, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x00, 0x00, + 0x08, 0x08, + 0x64, 0x41, 0x06, 0x0E, 0x2B, 0x16, 0x03, 0x03, 0x07, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x57, 0x01, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=200ms): Second engineering mode frame with different values + # Real capture: moving at 73cm, still at 30cm, detection at 33cm + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, 0xAA, + 0x03, + 0x49, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x21, 0x00, + 0x08, 0x08, + 0x11, 0x64, 0x05, 0x29, 0x39, 0x10, 0x03, 0x11, 0x0E, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, + 0x57, 0x01, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 3 (t=300ms): Frame with still target at 291cm (multi-byte distance) + # This tests the two_byte_to_int function with high byte > 0 + # Note: low byte 0x2F < 0x80 so it avoids the signed char bug + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, 0xAA, + 0x03, + 0x2F, 0x00, + 0x36, + 0x23, 0x01, + 0x64, + 0x21, 0x00, + 0x08, 0x08, + 0x2F, 0x36, 0x09, 0x0D, 0x15, 0x0B, 0x06, 0x06, 0x08, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x5A, 0x3D, + 0x57, 0x01, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +ld2410: + id: ld2410_dev + uart_id: mock_uart + +sensor: + - platform: ld2410 + ld2410_id: ld2410_dev + moving_distance: + name: "Moving Distance" + still_distance: + name: "Still Distance" + moving_energy: + name: "Moving Energy" + still_energy: + name: "Still Energy" + detection_distance: + name: "Detection Distance" + light: + name: "Light" + g0: + move_energy: + name: "Gate 0 Move Energy" + still_energy: + name: "Gate 0 Still Energy" + g1: + move_energy: + name: "Gate 1 Move Energy" + still_energy: + name: "Gate 1 Still Energy" + g2: + move_energy: + name: "Gate 2 Move Energy" + still_energy: + name: "Gate 2 Still Energy" + +binary_sensor: + - platform: ld2410 + ld2410_id: ld2410_dev + has_target: + name: "Has Target" + has_moving_target: + name: "Has Moving Target" + has_still_target: + name: "Has Still Target" + out_pin_presence_status: + name: "Out Pin Presence" diff --git a/tests/integration/test_uart_mock_ld2410.py b/tests/integration/test_uart_mock_ld2410.py new file mode 100644 index 0000000000..e01d6ff8e8 --- /dev/null +++ b/tests/integration/test_uart_mock_ld2410.py @@ -0,0 +1,392 @@ +"""Integration test for LD2410 component with mock UART. + +Tests: +test_uart_mock_ld2410 (normal mode): + 1. Happy path - valid data frame publishes correct sensor values + 2. Garbage resilience - random bytes don't crash the component + 3. Truncated frame handling - partial frame doesn't corrupt state + 4. Buffer overflow recovery - overflow resets the parser + 5. Post-overflow parsing - next valid frame after overflow is parsed correctly + 6. TX logging - verifies LD2410 sends expected setup commands + +test_uart_mock_ld2410_engineering (engineering mode): + 1. Engineering mode frames with per-gate energy data and light sensor + 2. Multi-byte still distance (291cm) using high byte > 0 + 3. Out pin presence binary sensor + 4. Gate energy sensor values from real device captures +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path + +from aioesphomeapi import ( + BinarySensorInfo, + BinarySensorState, + EntityState, + SensorInfo, + SensorState, +) +import pytest + +from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_uart_mock_ld2410( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2410 data parsing with happy path, garbage, overflow, and recovery.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track overflow warning in logs + overflow_seen = loop.create_future() + + # Track TX data logged by the mock for assertions + tx_log_lines: list[str] = [] + + def line_callback(line: str) -> None: + if "Max command length exceeded" in line and not overflow_seen.done(): + overflow_seen.set_result(True) + # Capture all TX log lines from uart_mock + if "uart_mock" in line and "TX " in line: + tx_log_lines.append(line) + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "moving_distance": [], + "still_distance": [], + "moving_energy": [], + "still_energy": [], + "detection_distance": [], + } + binary_states: dict[str, list[bool]] = { + "has_target": [], + "has_moving_target": [], + "has_still_target": [], + } + + # Signal when we see recovery frame values + recovery_received = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + # Check if this is the recovery frame (moving_distance = 50) + if ( + sensor_name == "moving_distance" + and state.state == pytest.approx(50.0) + and not recovery_received.done() + ): + recovery_received.set_result(True) + elif isinstance(state, BinarySensorState): + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in binary_states: + binary_states[sensor_name].append(state.state) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + # Build key mappings for all sensor types + all_names = list(sensor_states.keys()) + list(binary_states.keys()) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Phase 1 values are in the initial states (swallowed by InitialStateHelper). + # Verify them via initial_states dict. + moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) + assert moving_dist_entity is not None + initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) + assert initial_moving is not None and isinstance(initial_moving, SensorState) + assert initial_moving.state == pytest.approx(100.0), ( + f"Initial moving distance should be 100, got {initial_moving.state}" + ) + + still_dist_entity = find_entity(entities, "still_distance", SensorInfo) + assert still_dist_entity is not None + initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) + assert initial_still is not None and isinstance(initial_still, SensorState) + assert initial_still.state == pytest.approx(120.0), ( + f"Initial still distance should be 120, got {initial_still.state}" + ) + + moving_energy_entity = find_entity(entities, "moving_energy", SensorInfo) + assert moving_energy_entity is not None + initial_me = initial_state_helper.initial_states.get(moving_energy_entity.key) + assert initial_me is not None and isinstance(initial_me, SensorState) + assert initial_me.state == pytest.approx(50.0), ( + f"Initial moving energy should be 50, got {initial_me.state}" + ) + + still_energy_entity = find_entity(entities, "still_energy", SensorInfo) + assert still_energy_entity is not None + initial_se = initial_state_helper.initial_states.get(still_energy_entity.key) + assert initial_se is not None and isinstance(initial_se, SensorState) + assert initial_se.state == pytest.approx(25.0), ( + f"Initial still energy should be 25, got {initial_se.state}" + ) + + detect_dist_entity = find_entity(entities, "detection_distance", SensorInfo) + assert detect_dist_entity is not None + initial_dd = initial_state_helper.initial_states.get(detect_dist_entity.key) + assert initial_dd is not None and isinstance(initial_dd, SensorState) + assert initial_dd.state == pytest.approx(300.0), ( + f"Initial detection distance should be 300, got {initial_dd.state}" + ) + + # Wait for the recovery frame (Phase 5) to be parsed + # This proves the component survived garbage + truncated + overflow + try: + await asyncio.wait_for(recovery_received, timeout=15.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received sensor states:\n" + f" moving_distance: {sensor_states['moving_distance']}\n" + f" still_distance: {sensor_states['still_distance']}\n" + f" moving_energy: {sensor_states['moving_energy']}\n" + f" still_energy: {sensor_states['still_energy']}\n" + f" detection_distance: {sensor_states['detection_distance']}" + ) + + # Verify overflow warning was logged + assert overflow_seen.done(), ( + "Expected 'Max command length exceeded' warning in logs" + ) + + # Verify LD2410 sent setup commands (TX logging) + # LD2410 sends 7 commands during setup: FF (config on), A0 (version), + # A5 (MAC), AB (distance res), AE (light), 61 (params), FE (config off) + assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" + tx_data = " ".join(tx_log_lines) + # Verify command frame header appears (FD:FC:FB:FA) + assert "FD:FC:FB:FA" in tx_data, ( + "Expected LD2410 command frame header FD:FC:FB:FA in TX log" + ) + # Verify command frame footer appears (04:03:02:01) + assert "04:03:02:01" in tx_data, ( + "Expected LD2410 command frame footer 04:03:02:01 in TX log" + ) + + # Recovery frame values (Phase 5, after overflow) + assert len(sensor_states["moving_distance"]) >= 1, ( + f"Expected recovery moving_distance, got: {sensor_states['moving_distance']}" + ) + # Find the recovery value (moving_distance = 50) + recovery_values = [ + v for v in sensor_states["moving_distance"] if v == pytest.approx(50.0) + ] + assert len(recovery_values) >= 1, ( + f"Expected moving_distance=50 in recovery, got: {sensor_states['moving_distance']}" + ) + + # Recovery frame: moving=50, still=75, energy=100/80, detect=127 + recovery_idx = next( + i + for i, v in enumerate(sensor_states["moving_distance"]) + if v == pytest.approx(50.0) + ) + assert sensor_states["still_distance"][recovery_idx] == pytest.approx(75.0), ( + f"Recovery still distance should be 75, got {sensor_states['still_distance'][recovery_idx]}" + ) + assert sensor_states["moving_energy"][recovery_idx] == pytest.approx(100.0), ( + f"Recovery moving energy should be 100, got {sensor_states['moving_energy'][recovery_idx]}" + ) + assert sensor_states["still_energy"][recovery_idx] == pytest.approx(80.0), ( + f"Recovery still energy should be 80, got {sensor_states['still_energy'][recovery_idx]}" + ) + assert sensor_states["detection_distance"][recovery_idx] == pytest.approx( + 127.0 + ), ( + f"Recovery detection distance should be 127, got {sensor_states['detection_distance'][recovery_idx]}" + ) + + # Verify binary sensors detected targets + # Binary sensors could be in initial states or forwarded states + has_target_entity = find_entity(entities, "has_target", BinarySensorInfo) + assert has_target_entity is not None + initial_ht = initial_state_helper.initial_states.get(has_target_entity.key) + assert initial_ht is not None and isinstance(initial_ht, BinarySensorState) + assert initial_ht.state is True, "Has target should be True" + + has_moving_entity = find_entity(entities, "has_moving_target", BinarySensorInfo) + assert has_moving_entity is not None + initial_hm = initial_state_helper.initial_states.get(has_moving_entity.key) + assert initial_hm is not None and isinstance(initial_hm, BinarySensorState) + assert initial_hm.state is True, "Has moving target should be True" + + has_still_entity = find_entity(entities, "has_still_target", BinarySensorInfo) + assert has_still_entity is not None + initial_hs = initial_state_helper.initial_states.get(has_still_entity.key) + assert initial_hs is not None and isinstance(initial_hs, BinarySensorState) + assert initial_hs.state is True, "Has still target should be True" + + +@pytest.mark.asyncio +async def test_uart_mock_ld2410_engineering( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2410 engineering mode with per-gate energy, light, and multi-byte distance.""" + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "moving_distance": [], + "still_distance": [], + "moving_energy": [], + "still_energy": [], + "detection_distance": [], + "light": [], + "gate_0_move_energy": [], + "gate_1_move_energy": [], + "gate_2_move_energy": [], + "gate_0_still_energy": [], + "gate_1_still_energy": [], + "gate_2_still_energy": [], + } + binary_states: dict[str, list[bool]] = { + "has_target": [], + "has_moving_target": [], + "has_still_target": [], + "out_pin_presence": [], + } + + # Signal when we see Phase 3 frame (still_distance = 291) + phase3_received = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + if ( + sensor_name == "still_distance" + and state.state == pytest.approx(291.0) + and not phase3_received.done() + ): + phase3_received.set_result(True) + elif isinstance(state, BinarySensorState): + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in binary_states: + binary_states[sensor_name].append(state.state) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + all_names = list(sensor_states.keys()) + list(binary_states.keys()) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Phase 1 initial values (engineering mode frame): + # moving=30, energy=100, still=30, energy=100, detect=0 + moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) + assert moving_dist_entity is not None + initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) + assert initial_moving is not None and isinstance(initial_moving, SensorState) + assert initial_moving.state == pytest.approx(30.0), ( + f"Initial moving distance should be 30, got {initial_moving.state}" + ) + + still_dist_entity = find_entity(entities, "still_distance", SensorInfo) + assert still_dist_entity is not None + initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) + assert initial_still is not None and isinstance(initial_still, SensorState) + assert initial_still.state == pytest.approx(30.0), ( + f"Initial still distance should be 30, got {initial_still.state}" + ) + + # Verify engineering mode sensors from initial state + # Gate 0 moving energy = 0x64 = 100 + gate0_move_entity = find_entity(entities, "gate_0_move_energy", SensorInfo) + assert gate0_move_entity is not None + initial_g0m = initial_state_helper.initial_states.get(gate0_move_entity.key) + assert initial_g0m is not None and isinstance(initial_g0m, SensorState) + assert initial_g0m.state == pytest.approx(100.0), ( + f"Gate 0 move energy should be 100, got {initial_g0m.state}" + ) + + # Gate 1 moving energy = 0x41 = 65 + gate1_move_entity = find_entity(entities, "gate_1_move_energy", SensorInfo) + assert gate1_move_entity is not None + initial_g1m = initial_state_helper.initial_states.get(gate1_move_entity.key) + assert initial_g1m is not None and isinstance(initial_g1m, SensorState) + assert initial_g1m.state == pytest.approx(65.0), ( + f"Gate 1 move energy should be 65, got {initial_g1m.state}" + ) + + # Light sensor = 0x57 = 87 + light_entity = find_entity(entities, "light", SensorInfo) + assert light_entity is not None + initial_light = initial_state_helper.initial_states.get(light_entity.key) + assert initial_light is not None and isinstance(initial_light, SensorState) + assert initial_light.state == pytest.approx(87.0), ( + f"Light sensor should be 87, got {initial_light.state}" + ) + + # Out pin presence = 0x01 = True + out_pin_entity = find_entity(entities, "out_pin_presence", BinarySensorInfo) + assert out_pin_entity is not None + initial_out = initial_state_helper.initial_states.get(out_pin_entity.key) + assert initial_out is not None and isinstance(initial_out, BinarySensorState) + assert initial_out.state is True, "Out pin presence should be True" + + # Wait for Phase 3 frame (still_distance = 291cm, multi-byte) + try: + await asyncio.wait_for(phase3_received, timeout=15.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 3 frame. Received sensor states:\n" + f" still_distance: {sensor_states['still_distance']}\n" + f" moving_distance: {sensor_states['moving_distance']}" + ) + + # Phase 3: still distance = 0x0123 = 291cm (multi-byte distance test) + phase3_still = [ + v for v in sensor_states["still_distance"] if v == pytest.approx(291.0) + ] + assert len(phase3_still) >= 1, ( + f"Expected still_distance=291, got: {sensor_states['still_distance']}" + ) From 9d4357c619ee94ae9a934276525e1bfa0ac99b8b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 18:20:14 -1000 Subject: [PATCH 1034/2030] [core] Wake main loop from ISR in enable_loop_soon_any_context() (#14383) --- esphome/components/socket/__init__.py | 7 ++++--- esphome/core/application.h | 8 +++++++- esphome/core/component.cpp | 8 +++++++- esphome/core/lwip_fast_select.c | 24 +++++++++++++++++++----- esphome/core/lwip_fast_select.h | 7 +++++++ 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index a83648979c..08cf3ea33c 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -189,9 +189,10 @@ async def to_code(config): cg.add_define("USE_SOCKET_IMPL_BSD_SOCKETS") cg.add_define("USE_SOCKET_SELECT_SUPPORT") # ESP32 and LibreTiny both have LwIP >= 2.1.3 with lwip_socket_dbg_get_socket() - # and FreeRTOS task notifications — enable fast select to bypass lwip_select() - if CORE.is_esp32 or CORE.is_libretiny: - cg.add_define("USE_LWIP_FAST_SELECT") + # and FreeRTOS task notifications — enable fast select to bypass lwip_select(). + # Only when not using lwip_tcp, which does not provide select() support. + if (CORE.is_esp32 or CORE.is_libretiny) and impl != IMPLEMENTATION_LWIP_TCP: + cg.add_build_flag("-DUSE_LWIP_FAST_SELECT") def FILTER_SOURCE_FILES() -> list[str]: diff --git a/esphome/core/application.h b/esphome/core/application.h index 13e0f63885..d2345e2b0b 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -501,7 +501,7 @@ class Application { void wake_loop_threadsafe(); #endif -#if defined(USE_WAKE_LOOP_THREADSAFE) && defined(USE_LWIP_FAST_SELECT) +#ifdef USE_LWIP_FAST_SELECT /// Wake the main event loop from an ISR. /// Uses vTaskNotifyGiveFromISR() — <1 us, ISR-safe. /// Only available on platforms with fast select (ESP32, LibreTiny). @@ -509,6 +509,12 @@ class Application { static void IRAM_ATTR wake_loop_isrsafe(int *px_higher_priority_task_woken) { esphome_lwip_wake_main_loop_from_isr(px_higher_priority_task_woken); } + +#ifdef USE_ESP32 + /// Wake the main event loop from any context (ISR, thread, or main loop). + /// Detects the calling context and uses the appropriate FreeRTOS API. + static void IRAM_ATTR wake_loop_any_context() { esphome_lwip_wake_main_loop_any_context(); } +#endif #endif #endif diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index fd4e0d2984..5afd901da2 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -315,7 +315,7 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // This method is thread and ISR-safe because: // 1. Only performs simple assignments to volatile variables (atomic on all platforms) // 2. No read-modify-write operations that could be interrupted - // 3. No memory allocation, object construction, or function calls + // 3. No memory allocation or object construction; on ESP32 the only call (wake_loop_any_context) is ISR-safe // 4. IRAM_ATTR ensures code is in IRAM, not flash (required for ISR execution) // 5. Components are never destroyed, so no use-after-free concerns // 6. App is guaranteed to be initialized before any ISR could fire @@ -323,6 +323,12 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // 8. Race condition with main loop is handled by clearing flag before processing this->pending_enable_loop_ = true; App.has_pending_enable_loop_requests_ = true; +#if defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32) + // Wake the main loop if sleeping in ulTaskNotifyTake(). Without this, + // the main loop would not wake until the select timeout expires (~16ms). + // Uses xPortInIsrContext() to choose the correct FreeRTOS notify API. + Application::wake_loop_any_context(); +#endif } void Component::reset_to_construction_state() { if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) { diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index da0f1f337a..989f66e9be 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -105,10 +105,9 @@ // critical sections). Multiple concurrent xTaskNotifyGive calls are safe — // the notification count simply increments. -// USE_ESP32 and USE_LIBRETINY are compiler -D flags, so they are always visible in this .c file. -// Feature macros like USE_LWIP_FAST_SELECT may come from generated headers that are not included here, -// so this implementation is enabled based on platform flags instead of USE_LWIP_FAST_SELECT. -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +// USE_LWIP_FAST_SELECT is set via -D build flag (not cg.add_define) so it is +// visible in both .c and .cpp translation units. +#ifdef USE_LWIP_FAST_SELECT // LwIP headers must come first — they define netconn_callback, struct lwip_sock, etc. #include <lwip/api.h> @@ -239,4 +238,19 @@ void IRAM_ATTR esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task } } -#endif // defined(USE_ESP32) || defined(USE_LIBRETINY) +// Wake the main loop from any context (ISR, thread, or main loop). +// ESP32-only: uses xPortInIsrContext() to detect ISR context. +// LibreTiny is excluded because it lacks IRAM_ATTR support needed for ISR-safe paths. +#ifdef USE_ESP32 +void IRAM_ATTR esphome_lwip_wake_main_loop_any_context(void) { + if (xPortInIsrContext()) { + int px_higher_priority_task_woken = 0; + esphome_lwip_wake_main_loop_from_isr(&px_higher_priority_task_woken); + portYIELD_FROM_ISR(px_higher_priority_task_woken); + } else { + esphome_lwip_wake_main_loop(); + } +} +#endif + +#endif // USE_LWIP_FAST_SELECT diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index b7a70a8f9f..6fce34fd76 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -33,6 +33,13 @@ void esphome_lwip_wake_main_loop(void); /// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); +/// Wake the main loop task from any context (ISR, thread, or main loop). +/// ESP32-only: uses xPortInIsrContext() to detect ISR context. +/// LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths. +#ifdef USE_ESP32 +void esphome_lwip_wake_main_loop_any_context(void); +#endif + #ifdef __cplusplus } #endif From 590ee81f7a13356c75d5cafa2436771fe4b80f53 Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Mon, 2 Mar 2026 07:16:36 +0100 Subject: [PATCH 1035/2030] [openthread] Disable default enabled OT console build (#14390) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/openthread/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/openthread/__init__.py b/esphome/components/openthread/__init__.py index dde4987181..5861c3db3f 100644 --- a/esphome/components/openthread/__init__.py +++ b/esphome/components/openthread/__init__.py @@ -52,6 +52,8 @@ def set_sdkconfig_options(config): # There is a conflict if the logger's uart also uses the default UART, which is seen as a watchdog failure on "ot_cli" add_idf_sdkconfig_option("CONFIG_OPENTHREAD_CLI", False) + # Console is the transport layer for CLI; disable it too since CLI is disabled + add_idf_sdkconfig_option("CONFIG_OPENTHREAD_CONSOLE_ENABLE", False) # Diag unused, if needed for lab/cert/etc tests then enable separately add_idf_sdkconfig_option("CONFIG_OPENTHREAD_DIAG", False) From 3160457ca620adfbe48980af20d89a5c062462ee Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Mon, 2 Mar 2026 00:51:27 -0800 Subject: [PATCH 1036/2030] Create integration tests for modbus (#14395) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../external_components/uart_mock/__init__.py | 83 +++++++++- .../uart_mock/automation.h | 51 ++++++ .../uart_mock/uart_mock.cpp | 25 ++- .../external_components/uart_mock/uart_mock.h | 10 +- .../fixtures/uart_mock_modbus.yaml | 40 +++++ .../fixtures/uart_mock_modbus_timing.yaml | 54 +++++++ tests/integration/test_uart_mock_modbus.py | 153 ++++++++++++++++++ 7 files changed, 409 insertions(+), 7 deletions(-) create mode 100644 tests/integration/fixtures/external_components/uart_mock/automation.h create mode 100644 tests/integration/fixtures/uart_mock_modbus.yaml create mode 100644 tests/integration/fixtures/uart_mock_modbus_timing.yaml create mode 100644 tests/integration/test_uart_mock_modbus.py diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py index 5bd879ab12..dea8c38551 100644 --- a/tests/integration/fixtures/external_components/uart_mock/__init__.py +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -1,8 +1,28 @@ +from esphome import automation import esphome.codegen as cg from esphome.components import uart -from esphome.components.uart import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS +from esphome.components.uart import ( + CONF_RX_FULL_THRESHOLD, + CONF_RX_TIMEOUT, + debug_to_code, + maybe_empty_debug, + validate_raw_data, +) import esphome.config_validation as cv -from esphome.const import CONF_BAUD_RATE, CONF_DATA, CONF_DELAY, CONF_ID, CONF_INTERVAL +from esphome.const import ( + CONF_BAUD_RATE, + CONF_DATA, + CONF_DATA_BITS, + CONF_DEBUG, + CONF_DELAY, + CONF_ID, + CONF_INTERVAL, + CONF_PARITY, + CONF_RX_BUFFER_SIZE, + CONF_STOP_BITS, + CONF_TRIGGER_ID, +) +from esphome.core import ID CODEOWNERS = ["@esphome/tests"] MULTI_CONF = True @@ -11,12 +31,20 @@ uart_mock_ns = cg.esphome_ns.namespace("uart_mock") MockUartComponent = uart_mock_ns.class_( "MockUartComponent", uart.UARTComponent, cg.Component ) +MockUartInjectRXAction = uart_mock_ns.class_( + "MockUartInjectRXAction", automation.Action +) +MockUartTXTrigger = uart_mock_ns.class_( + "MockUartTXTrigger", + automation.Trigger.template(cg.std_vector.template(cg.uint8)), +) CONF_INJECTIONS = "injections" CONF_RESPONSES = "responses" CONF_INJECT_RX = "inject_rx" CONF_EXPECT_TX = "expect_tx" CONF_PERIODIC_RX = "periodic_rx" +CONF_ON_TX = "on_tx" UART_PARITY_OPTIONS = { "NONE": uart.UARTParityOptions.UART_CONFIG_PARITY_NONE, @@ -31,6 +59,15 @@ INJECTION_SCHEMA = cv.Schema( } ) +CONFIG_INJECT_RX_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(MockUartComponent), + cv.Required("data"): cv.templatable(validate_raw_data), + }, + key=CONF_DATA, +) + + RESPONSE_SCHEMA = cv.Schema( { cv.Required(CONF_EXPECT_TX): [cv.hex_uint8_t], @@ -49,6 +86,9 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(MockUartComponent), cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), + cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, + cv.Optional(CONF_RX_FULL_THRESHOLD, default=10): cv.int_range(min=1, max=120), + cv.Optional(CONF_RX_TIMEOUT, default=2): cv.int_range(min=0, max=92), cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), cv.Optional(CONF_PARITY, default="NONE"): cv.enum( @@ -57,15 +97,45 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_INJECTIONS, default=[]): cv.ensure_list(INJECTION_SCHEMA), cv.Optional(CONF_RESPONSES, default=[]): cv.ensure_list(RESPONSE_SCHEMA), cv.Optional(CONF_PERIODIC_RX, default=[]): cv.ensure_list(PERIODIC_RX_SCHEMA), + cv.Optional(CONF_ON_TX): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MockUartTXTrigger), + } + ), + cv.Optional(CONF_DEBUG): maybe_empty_debug, } ).extend(cv.COMPONENT_SCHEMA) +@automation.register_action( + "uart_mock.inject_rx", MockUartInjectRXAction, CONFIG_INJECT_RX_SCHEMA +) +async def inject_rx_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + data = config[CONF_DATA] + if isinstance(data, bytes): + data = list(data) + + if cg.is_template(data): + templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) + cg.add(var.set_data_template(templ)) + else: + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) + return var + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) cg.add(var.set_baud_rate(config[CONF_BAUD_RATE])) + cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) + cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD])) + cg.add(var.set_rx_timeout(config[CONF_RX_TIMEOUT])) cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) cg.add(var.set_data_bits(config[CONF_DATA_BITS])) cg.add(var.set_parity(config[CONF_PARITY])) @@ -84,3 +154,12 @@ async def to_code(config): data = periodic[CONF_DATA] interval = periodic[CONF_INTERVAL] cg.add(var.add_periodic_rx(data, interval)) + + for conf in config.get(CONF_ON_TX, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation( + trigger, [(cg.std_vector.template(cg.uint8), "data")], conf + ) + + if CONF_DEBUG in config: + await debug_to_code(config[CONF_DEBUG], var) diff --git a/tests/integration/fixtures/external_components/uart_mock/automation.h b/tests/integration/fixtures/external_components/uart_mock/automation.h new file mode 100644 index 0000000000..83a057d3a0 --- /dev/null +++ b/tests/integration/fixtures/external_components/uart_mock/automation.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/automation.h" +#include "uart_mock.h" + +namespace esphome::uart_mock { + +// This pattern is similar to UARTWriteAction but calls inject_rx instead of write_array, and is parented to VirtualUART +// instead of UARTComponent +template<typename... Ts> class MockUartInjectRXAction : public Action<Ts...>, public Parented<MockUartComponent> { + public: + void set_data_template(std::vector<uint8_t> (*func)(Ts...)) { + // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers + this->code_.func = func; + this->len_ = -1; // Sentinel value indicates template mode + } + + // Store pointer to static data in flash (no RAM copy) + void set_data_static(const uint8_t *data, size_t len) { + this->code_.data = data; + this->len_ = len; // Length >= 0 indicates static mode + } + + void play(const Ts &...x) override { + if (this->len_ >= 0) { + // Static mode: use pointer and length + this->parent_->inject_to_rx_buffer(this->code_.data, static_cast<size_t>(this->len_)); + } else { + // Template mode: call function + auto val = this->code_.func(x...); + this->parent_->inject_to_rx_buffer(val); + } + } + + protected: + ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length + union Code { + std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas) + const uint8_t *data; // Pointer to static data in flash + } code_; +}; + +class MockUartTXTrigger : public Trigger<std::vector<uint8_t>> { + public: + explicit MockUartTXTrigger(MockUartComponent *parent) { + parent->set_tx_hook([this](std::vector<uint8_t> data) { this->trigger(data); }); + } +}; + +} // namespace esphome::uart_mock diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index a49d51ba10..a4a1c41234 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -35,7 +35,7 @@ void MockUartComponent::loop() { uint32_t target_time = this->scenario_start_ms_ + this->cumulative_delay_ms_ + injection.delay_ms; if (now >= target_time) { ESP_LOGD(TAG, "Injecting %zu RX bytes (injection %u)", injection.rx_data.size(), this->injection_index_); - this->inject_to_rx_buffer_(injection.rx_data); + this->inject_to_rx_buffer(injection.rx_data); this->cumulative_delay_ms_ += injection.delay_ms; this->injection_index_++; } @@ -44,7 +44,7 @@ void MockUartComponent::loop() { // Process periodic RX for (auto &periodic : this->periodic_rx_) { if (now - periodic.last_inject_ms >= periodic.interval_ms) { - this->inject_to_rx_buffer_(periodic.data); + this->inject_to_rx_buffer(periodic.data); periodic.last_inject_ms = now; } } @@ -79,6 +79,12 @@ void MockUartComponent::write_array(const uint8_t *data, size_t len) { #endif this->try_match_response_(); + + // This directly calls a tx_hook (lambda) as an alternative to the simpler match_response mechanism. + if (this->tx_hook_) { + std::vector<uint8_t> buf(data, data + len); + this->tx_hook_(buf); + } } bool MockUartComponent::peek_byte(uint8_t *data) { @@ -114,6 +120,12 @@ void MockUartComponent::flush() { // Nothing to flush in mock } +void MockUartComponent::set_rx_full_threshold(size_t rx_full_threshold) { + this->rx_full_threshold_ = rx_full_threshold; +} + +void MockUartComponent::set_rx_timeout(size_t rx_timeout) { this->rx_timeout_ = rx_timeout; } + void MockUartComponent::add_injection(const std::vector<uint8_t> &rx_data, uint32_t delay_ms) { this->injections_.push_back({rx_data, delay_ms}); } @@ -135,14 +147,19 @@ void MockUartComponent::try_match_response_() { size_t offset = this->tx_buffer_.size() - response.expect_tx.size(); if (std::equal(response.expect_tx.begin(), response.expect_tx.end(), this->tx_buffer_.begin() + offset)) { ESP_LOGD(TAG, "TX match found, injecting %zu RX bytes", response.inject_rx.size()); - this->inject_to_rx_buffer_(response.inject_rx); + this->inject_to_rx_buffer(response.inject_rx); this->tx_buffer_.clear(); return; } } } -void MockUartComponent::inject_to_rx_buffer_(const std::vector<uint8_t> &data) { +void MockUartComponent::inject_to_rx_buffer(const uint8_t *data, size_t len) { + std::vector<uint8_t> vec(data, data + len); + this->inject_to_rx_buffer(vec); +} + +void MockUartComponent::inject_to_rx_buffer(const std::vector<uint8_t> &data) { // Log injected RX data so tests can see what's being fed to the component if (!data.empty() && data.size() <= 64) { char hex_buf[format_hex_pretty_size(64)]; diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index 00f4bf2e2b..5bbc3c1bf6 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -29,16 +29,21 @@ class MockUartComponent : public uart::UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; void flush() override; + void set_rx_full_threshold(size_t rx_full_threshold) override; + void set_rx_timeout(size_t rx_timeout) override; // Scenario configuration - called from generated code void add_injection(const std::vector<uint8_t> &rx_data, uint32_t delay_ms); void add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx); void add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms); + void set_tx_hook(std::function<void(const std::vector<uint8_t> &)> &&cb) { this->tx_hook_ = std::move(cb); } + void inject_to_rx_buffer(const std::vector<uint8_t> &data); + void inject_to_rx_buffer(const uint8_t *data, size_t len); + protected: void check_logger_conflict() override {} void try_match_response_(); - void inject_to_rx_buffer_(const std::vector<uint8_t> &data); // Timed injections struct Injection { @@ -73,6 +78,9 @@ class MockUartComponent : public uart::UARTComponent, public Component { // Observability uint32_t tx_count_{0}; uint32_t rx_count_{0}; + + // Direct TX hook for tests that want to bypass the response-matching logic + std::function<void(const std::vector<uint8_t> &)> tx_hook_; }; } // namespace esphome::uart_mock diff --git a/tests/integration/fixtures/uart_mock_modbus.yaml b/tests/integration/fixtures/uart_mock_modbus.yaml new file mode 100644 index 0000000000..89b9b91861 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus.yaml @@ -0,0 +1,40 @@ +esphome: + name: uart-mock-modbus-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_dev + baud_rate: 9600 + rx_full_threshold: 120 + rx_timeout: 2 + debug: + responses: + - expect_tx: [0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A] # Read holding register 1 on device 1 + inject_rx: [0x01, 0x03, 0x02, 0x01, 0x03, 0xF9, 0xD5] # Return value 0x0103 (hex) = 259 (dec) + +modbus: + uart_id: virtual_uart_dev + +modbus_controller: + address: 1 + +sensor: + - platform: modbus_controller + name: "basic_register" + address: 0x03 + register_type: holding diff --git a/tests/integration/fixtures/uart_mock_modbus_timing.yaml b/tests/integration/fixtures/uart_mock_modbus_timing.yaml new file mode 100644 index 0000000000..cd485ca394 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_timing.yaml @@ -0,0 +1,54 @@ +esphome: + name: uart-mock-modbus-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_dev + baud_rate: 9600 + rx_full_threshold: 120 + rx_timeout: 2 + debug: + on_tx: + - then: + - if: + condition: #Read 80 input registers on device 2, starting at address 0 (SDM meter request) + lambda: "return data == std::vector<uint8_t>({0x02,0x04,0x00,0x00,0x00,0x50,0xF0,0x05});" + then: + - uart_mock.inject_rx: # Good response from SDM meter with CRC. Voltage is 243V + !lambda return {0x02,0x04,0xA0,0x43,0x73,0x19,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + - delay: 120ms # Simulate some delay for UART buffer to fill before next part of response (1ms = 1 byte at 9600 baud) + - uart_mock.inject_rx: # Rest of response (including CRC) + !lambda return{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6F,0xCC,0xCD,0x43,0x7C,0xB8,0x10,0x3D,0x38,0x51,0xEC, + 0x43,0x81,0x1B,0xE7,0x3B,0x03,0x12,0x6F,0x50,0x1B}; + +modbus: + uart_id: virtual_uart_dev + +sensor: + - platform: sdm_meter + address: 2 + phase_a: + voltage: + name: sdm_voltage diff --git a/tests/integration/test_uart_mock_modbus.py b/tests/integration/test_uart_mock_modbus.py new file mode 100644 index 0000000000..309cb56dc9 --- /dev/null +++ b/tests/integration/test_uart_mock_modbus.py @@ -0,0 +1,153 @@ +"""Integration test for modbus component with virtual UART. + +Tests: +test_uart_mock_modbus : + 1. Read a single register and parse successfully (basic_register) + 2. Read multiple registers from SDM meter and parse successfully (sdm_voltage), with some intermediate delay to simulate UART buffer time. + +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path + +from aioesphomeapi import EntityState, SensorState +import pytest + +from .state_utils import InitialStateHelper, build_key_to_entity_mapping +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_uart_mock_modbus( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test basic modbus data parsing.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "basic_register": [], + } + + basic_register_changed = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + if ( + sensor_name == "basic_register" + and state.state == 259.0 + and not basic_register_changed.done() + ): + basic_register_changed.set_result(True) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + # Build key mappings for all sensor types + all_names = list(sensor_states.keys()) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Wait for basic register to be updated with successful parse + try: + await asyncio.wait_for(basic_register_changed, timeout=15.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Basic Register change. Received sensor states:\n" + f" basic_register: {sensor_states['basic_register']}\n" + ) + + +@pytest.mark.asyncio +@pytest.mark.xfail( + reason="There is a bug in UART which will timeout for long responses." +) +async def test_uart_mock_modbus_timing( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test basic modbus data parsing.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "sdm_voltage": [], + } + + voltage_changed = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + # Check if this is a good voltage reading (243V) + if ( + sensor_name == "sdm_voltage" + and state.state > 200.0 + and not voltage_changed.done() + ): + voltage_changed.set_result(True) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + # Build key mappings for all sensor types + all_names = list(sensor_states.keys()) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Wait for voltage to be updated with successful parse + try: + await asyncio.wait_for(voltage_changed, timeout=15.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for SDM voltage change. Received sensor states:\n" + f" sdm_voltage: {sensor_states['sdm_voltage']}\n" + ) From 77a7cbcffd4b8ec1fa3bc77b32f9ef06dc96761d Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Mar 2026 11:41:20 -0500 Subject: [PATCH 1037/2030] Use cached files on network errors in external_files (#14055) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jesserockz <3060199+jesserockz@users.noreply.github.com> --- esphome/external_files.py | 15 +++++++-- tests/unit_tests/test_external_files.py | 44 +++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/esphome/external_files.py b/esphome/external_files.py index 80b54ebb2f..72a3f33fdc 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -55,10 +55,12 @@ def has_remote_file_changed(url: str, local_file_path: Path) -> bool: _LOGGER.debug("has_remote_file_changed: File modified") return True except requests.exceptions.RequestException as e: - raise cv.Invalid( - f"Could not check if {url} has changed, please check if file exists " - f"({e})" + _LOGGER.warning( + "Could not check if %s has changed due to network error (%s), using cached file", + url, + e, ) + return False _LOGGER.debug("has_remote_file_changed: File doesn't exists at %s", local_file_path) return True @@ -98,6 +100,13 @@ def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> bytes: ) req.raise_for_status() except requests.exceptions.RequestException as e: + if path.exists(): + _LOGGER.warning( + "Could not download from %s due to network error (%s), using cached file", + url, + e, + ) + return path.read_bytes() raise cv.Invalid(f"Could not download from {url}: {e}") path.parent.mkdir(parents=True, exist_ok=True) diff --git a/tests/unit_tests/test_external_files.py b/tests/unit_tests/test_external_files.py index 05e0bd3523..a319fae83d 100644 --- a/tests/unit_tests/test_external_files.py +++ b/tests/unit_tests/test_external_files.py @@ -144,16 +144,16 @@ def test_has_remote_file_changed_no_local_file(setup_core: Path) -> None: def test_has_remote_file_changed_network_error( mock_head: MagicMock, setup_core: Path ) -> None: - """Test has_remote_file_changed handles network errors gracefully.""" + """Test has_remote_file_changed returns False on network error when file is cached.""" test_file = setup_core / "cached.txt" test_file.write_text("cached content") mock_head.side_effect = requests.exceptions.RequestException("Network error") url = "https://example.com/file.txt" + result = external_files.has_remote_file_changed(url, test_file) - with pytest.raises(Invalid, match="Could not check if.*Network error"): - external_files.has_remote_file_changed(url, test_file) + assert result is False @patch("esphome.external_files.requests.head") @@ -198,3 +198,41 @@ def test_is_file_recent_handles_float_seconds(setup_core: Path) -> None: result = external_files.is_file_recent(test_file, refresh) assert result is True + + +@patch("esphome.external_files.requests.get") +@patch("esphome.external_files.has_remote_file_changed") +def test_download_content_with_network_error_uses_cache( + mock_has_changed: MagicMock, mock_get: MagicMock, setup_core: Path +) -> None: + """Test download_content uses cached file when network fails.""" + test_file = setup_core / "cached.txt" + cached_content = b"cached content" + test_file.write_bytes(cached_content) + + # Simulate file has changed, so it tries to download + mock_has_changed.return_value = True + mock_get.side_effect = requests.exceptions.RequestException("Network error") + + url = "https://example.com/file.txt" + result = external_files.download_content(url, test_file) + + assert result == cached_content + + +@patch("esphome.external_files.requests.get") +@patch("esphome.external_files.has_remote_file_changed") +def test_download_content_with_network_error_no_cache_fails( + mock_has_changed: MagicMock, mock_get: MagicMock, setup_core: Path +) -> None: + """Test download_content raises error when network fails and no cache exists.""" + test_file = setup_core / "nonexistent.txt" + + # Simulate file has changed (doesn't exist), so it tries to download + mock_has_changed.return_value = True + mock_get.side_effect = requests.exceptions.RequestException("Network error") + + url = "https://example.com/file.txt" + + with pytest.raises(Invalid, match="Could not download from.*Network error"): + external_files.download_content(url, test_file) From 1c5fd8bbd46fca739ec2bf7743f87ea433c98ad6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:56:51 -1000 Subject: [PATCH 1038/2030] [core] Move millis_64 rollover tracking out of Scheduler (#14360) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 1 + esphome/components/esp8266/core.cpp | 4 +- esphome/components/host/__init__.py | 1 + esphome/components/libretiny/core.cpp | 4 +- esphome/components/rp2040/__init__.py | 1 + esphome/components/zephyr/__init__.py | 1 + esphome/core/config.py | 6 + esphome/core/defines.h | 5 + esphome/core/scheduler.cpp | 182 +--------------------- esphome/core/scheduler.h | 47 +----- esphome/core/time_64.cpp | 207 ++++++++++++++++++++++++++ esphome/core/time_64.h | 24 +++ 12 files changed, 257 insertions(+), 226 deletions(-) create mode 100644 esphome/core/time_64.cpp create mode 100644 esphome/core/time_64.h diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index dd9e394fd2..a14d3af69e 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1438,6 +1438,7 @@ async def to_code(config): cg.set_cpp_standard("gnu++20") cg.add_build_flag("-DUSE_ESP32") + cg.add_define("USE_NATIVE_64BIT_TIME") cg.add_build_flag("-Wl,-z,noexecstack") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) variant = config[CONF_VARIANT] diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 497e99b61f..7136cf41cb 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -3,7 +3,7 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" -#include "esphome/core/application.h" +#include "esphome/core/time_64.h" #include "esphome/core/helpers.h" #include "preferences.h" #include <Arduino.h> @@ -17,7 +17,7 @@ namespace esphome { void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } -uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } +uint64_t millis_64() { return Millis64Impl::compute(::millis()); } void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/components/host/__init__.py b/esphome/components/host/__init__.py index ba05e497c8..8adbfb02ec 100644 --- a/esphome/components/host/__init__.py +++ b/esphome/components/host/__init__.py @@ -41,6 +41,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): cg.add_build_flag("-DUSE_HOST") + cg.add_define("USE_NATIVE_64BIT_TIME") cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts) cg.add_build_flag("-std=gnu++20") cg.add_define("ESPHOME_BOARD", "host") diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 6cbc81938d..88952692a7 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -3,7 +3,7 @@ #include "core.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" -#include "esphome/core/application.h" +#include "esphome/core/time_64.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -14,7 +14,7 @@ namespace esphome { void HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } -uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); } +uint64_t millis_64() { return Millis64Impl::compute(::millis()); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } void HOT delay(uint32_t ms) { ::delay(ms); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 23f12e651f..ea269a47c5 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -169,6 +169,7 @@ async def to_code(config): cg.add_platformio_option("lib_compat_mode", "strict") cg.add_platformio_option("board", config[CONF_BOARD]) cg.add_build_flag("-DUSE_RP2040") + cg.add_define("USE_NATIVE_64BIT_TIME") cg.set_cpp_standard("gnu++20") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "RP2040") diff --git a/esphome/components/zephyr/__init__.py b/esphome/components/zephyr/__init__.py index 43d5cebebb..4cc71bddca 100644 --- a/esphome/components/zephyr/__init__.py +++ b/esphome/components/zephyr/__init__.py @@ -112,6 +112,7 @@ def add_extra_script(stage: str, filename: str, path: Path) -> None: def zephyr_to_code(config): cg.add_build_flag("-DUSE_ZEPHYR") + cg.add_define("USE_NATIVE_64BIT_TIME") cg.set_cpp_standard("gnu++20") # build is done by west so bypass board checking in platformio cg.add_platformio_option("boards_dir", CORE.relative_build_path("boards")) diff --git a/esphome/core/config.py b/esphome/core/config.py index 215432835a..593b402230 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -650,6 +650,12 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_ARDUINO, PlatformFramework.ESP32_IDF, }, + "time_64.cpp": { + PlatformFramework.ESP8266_ARDUINO, + PlatformFramework.BK72XX_ARDUINO, + PlatformFramework.RTL87XX_ARDUINO, + PlatformFramework.LN882X_ARDUINO, + }, # Note: lock_free_queue.h and event_pool.h are header files and don't need to be filtered # as they are only included when needed by the preprocessor } diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 181425c162..1f2597dd98 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -178,6 +178,11 @@ #define USE_I2S_LEGACY #endif +// Platforms with native 64-bit time sources (no rollover tracking needed) +#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) || defined(USE_RP2040) +#define USE_NATIVE_64BIT_TIME +#endif + // ESP32-specific feature flags #ifdef USE_ESP32 #define USE_MQTT_IDF_ENQUEUE diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 2c10e7e2da..ca560e8250 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -9,7 +9,6 @@ #include <algorithm> #include <cinttypes> #include <cstring> -#include <limits> namespace esphome { @@ -28,10 +27,6 @@ static constexpr size_t MAX_POOL_SIZE = 5; // Set to 5 to match the pool size - when we have as many cancelled items as our // pool can hold, it's time to clean up and recycle them. static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) -// Half the 32-bit range - used to detect rollovers vs normal time progression -static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; -#endif // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; @@ -152,9 +147,6 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type return; } - // Get fresh 64-bit timestamp BEFORE taking lock - const uint64_t now_64 = millis_64(); - // Take lock early to protect scheduler_item_pool_ access LockGuard guard{this->lock_}; @@ -181,6 +173,9 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type } else #endif /* not ESPHOME_THREAD_SINGLE */ { + // Only non-defer items need a timestamp for scheduling + const uint64_t now_64 = millis_64(); + // Type-specific setup if (type == SchedulerItem::INTERVAL) { item->interval = delay; @@ -475,19 +470,8 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; std::vector<SchedulerItemPtr> old_items; -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) && \ - defined(ESPHOME_THREAD_MULTI_ATOMICS) - const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed); - const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed); - ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), - this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg); -#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) - ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(), - this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_); -#else ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64, this->items_.size(), this->scheduler_item_pool_.size(), now_64); -#endif // Cleanup before debug output this->cleanup_(); while (!this->items_.empty()) { @@ -715,166 +699,6 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) -uint64_t Scheduler::millis_64_impl_(uint32_t now) { - // THREAD SAFETY NOTE: - // This function has three implementations, based on the precompiler flags - // - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, RP2040, etc.) - // - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny BK72xx) - // - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, LibreTiny - // RTL87xx/LN882x, etc.) - // - // Make sure all changes are synchronized if you edit this function. - // - // IMPORTANT: Always pass fresh millis() values to this function. The implementation - // handles out-of-order timestamps between threads, but minimizing time differences - // helps maintain accuracy. - // - -#ifdef ESPHOME_THREAD_SINGLE - // This is the single core implementation. - // - // Single-core platforms have no concurrency, so this is a simple implementation - // that just tracks 32-bit rollover (every 49.7 days) without any locking or atomics. - - uint16_t major = this->millis_major_; - uint32_t last = this->last_millis_; - - // Check for rollover - if (now < last && (last - now) > HALF_MAX_UINT32) { - this->millis_major_++; - major++; - this->last_millis_ = now; -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); -#endif /* ESPHOME_DEBUG_SCHEDULER */ - } else if (now > last) { - // Only update if time moved forward - this->last_millis_ = now; - } - - // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time - return now + (static_cast<uint64_t>(major) << 32); - -#elif defined(ESPHOME_THREAD_MULTI_NO_ATOMICS) - // This is the multi core no atomics implementation. - // - // Without atomics, this implementation uses locks more aggressively: - // 1. Always locks when near the rollover boundary (within 10 seconds) - // 2. Always locks when detecting a large backwards jump - // 3. Updates without lock in normal forward progression (accepting minor races) - // This is less efficient but necessary without atomic operations. - uint16_t major = this->millis_major_; - uint32_t last = this->last_millis_; - - // Define a safe window around the rollover point (10 seconds) - // This covers any reasonable scheduler delays or thread preemption - static constexpr uint32_t ROLLOVER_WINDOW = 10000; // 10 seconds in milliseconds - - // Check if we're near the rollover boundary (close to std::numeric_limits<uint32_t>::max() or just past 0) - bool near_rollover = (last > (std::numeric_limits<uint32_t>::max() - ROLLOVER_WINDOW)) || (now < ROLLOVER_WINDOW); - - if (near_rollover || (now < last && (last - now) > HALF_MAX_UINT32)) { - // Near rollover or detected a rollover - need lock for safety - LockGuard guard{this->lock_}; - // Re-read with lock held - last = this->last_millis_; - - if (now < last && (last - now) > HALF_MAX_UINT32) { - // True rollover detected (happens every ~49.7 days) - this->millis_major_++; - major++; -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); -#endif /* ESPHOME_DEBUG_SCHEDULER */ - } - // Update last_millis_ while holding lock - this->last_millis_ = now; - } else if (now > last) { - // Normal case: Not near rollover and time moved forward - // Update without lock. While this may cause minor races (microseconds of - // backwards time movement), they're acceptable because: - // 1. The scheduler operates at millisecond resolution, not microsecond - // 2. We've already prevented the critical rollover race condition - // 3. Any backwards movement is orders of magnitude smaller than scheduler delays - this->last_millis_ = now; - } - // If now <= last and we're not near rollover, don't update - // This minimizes backwards time movement - - // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time - return now + (static_cast<uint64_t>(major) << 32); - -#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) - // This is the multi core with atomics implementation. - // - // Uses atomic operations with acquire/release semantics to ensure coherent - // reads of millis_major_ and last_millis_ across cores. Features: - // 1. Epoch-coherency retry loop to handle concurrent updates - // 2. Lock only taken for actual rollover detection and update - // 3. Lock-free CAS updates for normal forward time progression - // 4. Memory ordering ensures cores see consistent time values - - for (;;) { - uint16_t major = this->millis_major_.load(std::memory_order_acquire); - - /* - * Acquire so that if we later decide **not** to take the lock we still - * observe a `millis_major_` value coherent with the loaded `last_millis_`. - * The acquire load ensures any later read of `millis_major_` sees its - * corresponding increment. - */ - uint32_t last = this->last_millis_.load(std::memory_order_acquire); - - // If we might be near a rollover (large backwards jump), take the lock for the entire operation - // This ensures rollover detection and last_millis_ update are atomic together - if (now < last && (last - now) > HALF_MAX_UINT32) { - // Potential rollover - need lock for atomic rollover detection + update - LockGuard guard{this->lock_}; - // Re-read with lock held; mutex already provides ordering - last = this->last_millis_.load(std::memory_order_relaxed); - - if (now < last && (last - now) > HALF_MAX_UINT32) { - // True rollover detected (happens every ~49.7 days) - this->millis_major_.fetch_add(1, std::memory_order_relaxed); - major++; -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); -#endif /* ESPHOME_DEBUG_SCHEDULER */ - } - /* - * Update last_millis_ while holding the lock to prevent races - * Publish the new low-word *after* bumping `millis_major_` (done above) - * so readers never see a mismatched pair. - */ - this->last_millis_.store(now, std::memory_order_release); - } else { - // Normal case: Try lock-free update, but only allow forward movement within same epoch - // This prevents accidentally moving backwards across a rollover boundary - while (now > last && (now - last) < HALF_MAX_UINT32) { - if (this->last_millis_.compare_exchange_weak(last, now, - std::memory_order_release, // success - std::memory_order_relaxed)) { // failure - break; - } - // CAS failure means no data was published; relaxed is fine - // last is automatically updated by compare_exchange_weak if it fails - } - } - uint16_t major_end = this->millis_major_.load(std::memory_order_relaxed); - if (major_end == major) - return now + (static_cast<uint64_t>(major) << 32); - } - // Unreachable - the loop always returns when major_end == major - __builtin_unreachable(); - -#else -#error \ - "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." -#endif -} -#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040 - bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) // Optimize for common case: check low bits first when high bits are equal diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index d52cf5147d..cefbdd1b22 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -12,6 +12,7 @@ #include "esphome/core/component.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" +#include "esphome/core/time_64.h" namespace esphome { @@ -284,23 +285,16 @@ class Scheduler { bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id); // Extend a 32-bit millis() value to 64-bit. Use when the caller already has a fresh now. - // On ESP32, Host, Zephyr, and RP2040, ignores now and uses the native 64-bit time source via millis_64(). + // On platforms with native 64-bit time, ignores now and uses millis_64() directly. // On other platforms, extends now to 64-bit using rollover tracking. uint64_t millis_64_from_(uint32_t now) { -#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) || defined(USE_RP2040) +#ifdef USE_NATIVE_64BIT_TIME (void) now; return millis_64(); #else - return this->millis_64_impl_(now); + return Millis64Impl::compute(now); #endif } - -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) - // On platforms without native 64-bit time, millis_64() HAL function delegates to this - // method which tracks 32-bit millis() rollover using millis_major_ and last_millis_. - friend uint64_t millis_64(); - uint64_t millis_64_impl_(uint32_t now); -#endif // Cleanup logically deleted items from the scheduler // Returns the number of items remaining after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). @@ -566,39 +560,6 @@ class Scheduler { // can stall the entire system, causing timing issues and dropped events for any components that need // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) std::vector<SchedulerItemPtr> scheduler_item_pool_; - -#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) - // On platforms with native 64-bit time (ESP32, Host, Zephyr, RP2040), no rollover tracking needed. - // On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_(). -#ifdef ESPHOME_THREAD_MULTI_ATOMICS - /* - * Multi-threaded platforms with atomic support: last_millis_ needs atomic for lock-free updates - * - * MEMORY-ORDERING NOTE - * -------------------- - * `last_millis_` and `millis_major_` form a single 64-bit timestamp split in half. - * Writers publish `last_millis_` with memory_order_release and readers use - * memory_order_acquire. This ensures that once a reader sees the new low word, - * it also observes the corresponding increment of `millis_major_`. - */ - std::atomic<uint32_t> last_millis_{0}; -#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ - // Platforms without atomic support or single-threaded platforms - uint32_t last_millis_{0}; -#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ - - /* - * Upper 16 bits of the 64-bit millis counter. Incremented only while holding - * `lock_`; read concurrently. Atomic (relaxed) avoids a formal data race. - * Ordering relative to `last_millis_` is provided by its release store and the - * corresponding acquire loads. - */ -#ifdef ESPHOME_THREAD_MULTI_ATOMICS - std::atomic<uint16_t> millis_major_{0}; -#else /* not ESPHOME_THREAD_MULTI_ATOMICS */ - uint16_t millis_major_{0}; -#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */ -#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040 */ }; } // namespace esphome diff --git a/esphome/core/time_64.cpp b/esphome/core/time_64.cpp new file mode 100644 index 0000000000..db5df25eb9 --- /dev/null +++ b/esphome/core/time_64.cpp @@ -0,0 +1,207 @@ +#include "esphome/core/defines.h" + +#ifndef USE_NATIVE_64BIT_TIME + +#include "time_64.h" + +#include "esphome/core/helpers.h" +#ifdef ESPHOME_DEBUG_SCHEDULER +#include "esphome/core/log.h" +#include <cinttypes> +#endif +#ifdef ESPHOME_THREAD_MULTI_ATOMICS +#include <atomic> +#endif +#include <limits> + +namespace esphome { + +#ifdef ESPHOME_DEBUG_SCHEDULER +static const char *const TAG = "time_64"; +#endif + +uint64_t Millis64Impl::compute(uint32_t now) { + // Half the 32-bit range - used to detect rollovers vs normal time progression + static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2; + + // State variables for rollover tracking - static to persist across calls +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + // Mutex for rollover serialization (taken only every ~49.7 days). + // A spinlock would be smaller (~1 byte vs ~80-100 bytes) but is unsafe on + // preemptive single-core RTOS platforms due to priority inversion: a high-priority + // task spinning would prevent the lock holder from running to release it. + static Mutex lock; + /* + * Multi-threaded platforms with atomic support: last_millis needs atomic for lock-free updates. + * Writers publish last_millis with memory_order_release and readers use memory_order_acquire. + * This ensures that once a reader sees the new low word, it also observes the corresponding + * increment of millis_major. + */ + static std::atomic<uint32_t> last_millis{0}; + /* + * Upper 16 bits of the 64-bit millis counter. Incremented only while holding lock; + * read concurrently. Atomic (relaxed) avoids a formal data race. Ordering relative + * to last_millis is provided by its release store and the corresponding acquire loads. + */ + static std::atomic<uint16_t> millis_major{0}; +#elif !defined(ESPHOME_THREAD_SINGLE) /* ESPHOME_THREAD_MULTI_NO_ATOMICS */ + static Mutex lock; + static uint32_t last_millis{0}; + static uint16_t millis_major{0}; +#else /* ESPHOME_THREAD_SINGLE */ + static uint32_t last_millis{0}; + static uint16_t millis_major{0}; +#endif + + // THREAD SAFETY NOTE: + // This function has three implementations, based on the precompiler flags + // - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, etc.) + // - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny BK72xx) + // - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (LibreTiny RTL87xx/LN882x, etc.) + // + // Make sure all changes are synchronized if you edit this function. + // + // IMPORTANT: Always pass fresh millis() values to this function. The implementation + // handles out-of-order timestamps between threads, but minimizing time differences + // helps maintain accuracy. + +#ifdef ESPHOME_THREAD_SINGLE + // Single-core platforms have no concurrency, so this is a simple implementation + // that just tracks 32-bit rollover (every 49.7 days) without any locking or atomics. + + uint16_t major = millis_major; + uint32_t last = last_millis; + + // Check for rollover + if (now < last && (last - now) > HALF_MAX_UINT32) { + millis_major++; + major++; + last_millis = now; +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); +#endif /* ESPHOME_DEBUG_SCHEDULER */ + } else if (now > last) { + // Only update if time moved forward + last_millis = now; + } + + // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time + return now + (static_cast<uint64_t>(major) << 32); + +#elif defined(ESPHOME_THREAD_MULTI_NO_ATOMICS) + // Without atomics, this implementation uses locks more aggressively: + // 1. Always locks when near the rollover boundary (within 10 seconds) + // 2. Always locks when detecting a large backwards jump + // 3. Updates without lock in normal forward progression (accepting minor races) + // This is less efficient but necessary without atomic operations. + uint16_t major = millis_major; + uint32_t last = last_millis; + + // Define a safe window around the rollover point (10 seconds) + // This covers any reasonable scheduler delays or thread preemption + static constexpr uint32_t ROLLOVER_WINDOW = 10000; // 10 seconds in milliseconds + + // Check if we're near the rollover boundary (close to std::numeric_limits<uint32_t>::max() or just past 0) + bool near_rollover = (last > (std::numeric_limits<uint32_t>::max() - ROLLOVER_WINDOW)) || (now < ROLLOVER_WINDOW); + + if (near_rollover || (now < last && (last - now) > HALF_MAX_UINT32)) { + // Near rollover or detected a rollover - need lock for safety + LockGuard guard{lock}; + // Re-read with lock held + last = last_millis; + + if (now < last && (last - now) > HALF_MAX_UINT32) { + // True rollover detected (happens every ~49.7 days) + millis_major++; + major++; +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); +#endif /* ESPHOME_DEBUG_SCHEDULER */ + } + // Update last_millis while holding lock + last_millis = now; + } else if (now > last) { + // Normal case: Not near rollover and time moved forward + // Update without lock. While this may cause minor races (microseconds of + // backwards time movement), they're acceptable because: + // 1. The scheduler operates at millisecond resolution, not microsecond + // 2. We've already prevented the critical rollover race condition + // 3. Any backwards movement is orders of magnitude smaller than scheduler delays + last_millis = now; + } + // If now <= last and we're not near rollover, don't update + // This minimizes backwards time movement + + // Combine major (high 32 bits) and now (low 32 bits) into 64-bit time + return now + (static_cast<uint64_t>(major) << 32); + +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + // Uses atomic operations with acquire/release semantics to ensure coherent + // reads of millis_major and last_millis across cores. Features: + // 1. Epoch-coherency retry loop to handle concurrent updates + // 2. Lock only taken for actual rollover detection and update + // 3. Lock-free CAS updates for normal forward time progression + // 4. Memory ordering ensures cores see consistent time values + + for (;;) { + uint16_t major = millis_major.load(std::memory_order_acquire); + + /* + * Acquire so that if we later decide **not** to take the lock we still + * observe a millis_major value coherent with the loaded last_millis. + * The acquire load ensures any later read of millis_major sees its + * corresponding increment. + */ + uint32_t last = last_millis.load(std::memory_order_acquire); + + // If we might be near a rollover (large backwards jump), take the lock + // This ensures rollover detection and last_millis update are atomic together + if (now < last && (last - now) > HALF_MAX_UINT32) { + // Potential rollover - need lock for atomic rollover detection + update + LockGuard guard{lock}; + // Re-read with lock held; mutex already provides ordering + last = last_millis.load(std::memory_order_relaxed); + + if (now < last && (last - now) > HALF_MAX_UINT32) { + // True rollover detected (happens every ~49.7 days) + millis_major.fetch_add(1, std::memory_order_relaxed); + major++; +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Detected true 32-bit rollover at %" PRIu32 "ms (was %" PRIu32 ")", now, last); +#endif /* ESPHOME_DEBUG_SCHEDULER */ + } + /* + * Update last_millis while holding the lock to prevent races. + * Publish the new low-word *after* bumping millis_major (done above) + * so readers never see a mismatched pair. + */ + last_millis.store(now, std::memory_order_release); + } else { + // Normal case: Try lock-free update, but only allow forward movement within same epoch + // This prevents accidentally moving backwards across a rollover boundary + while (now > last && (now - last) < HALF_MAX_UINT32) { + if (last_millis.compare_exchange_weak(last, now, + std::memory_order_release, // success + std::memory_order_relaxed)) { // failure + break; + } + // CAS failure means no data was published; relaxed is fine + // last is automatically updated by compare_exchange_weak if it fails + } + } + uint16_t major_end = millis_major.load(std::memory_order_relaxed); + if (major_end == major) + return now + (static_cast<uint64_t>(major) << 32); + } + // Unreachable - the loop always returns when major_end == major + __builtin_unreachable(); + +#else +#error \ + "No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined." +#endif +} + +} // namespace esphome + +#endif // !USE_NATIVE_64BIT_TIME diff --git a/esphome/core/time_64.h b/esphome/core/time_64.h new file mode 100644 index 0000000000..42d4b041e5 --- /dev/null +++ b/esphome/core/time_64.h @@ -0,0 +1,24 @@ +#pragma once +#include "esphome/core/defines.h" + +#ifndef USE_NATIVE_64BIT_TIME + +#include <cstdint> + +namespace esphome { + +class Scheduler; + +/// Extends 32-bit millis() to 64-bit using rollover tracking. +/// Access restricted to platform HAL (millis_64()) and Scheduler. +/// All other code should call millis_64() from hal.h instead. +class Millis64Impl { + friend uint64_t millis_64(); + friend class Scheduler; + + static uint64_t compute(uint32_t now); +}; + +} // namespace esphome + +#endif // !USE_NATIVE_64BIT_TIME From 82da4935b603624bf90a1429309e3d23d749bd46 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:57:08 -1000 Subject: [PATCH 1039/2030] [core] Auto-wrap static strings in PROGMEM on ESP8266 via TemplatableValue (#13885) --- esphome/codegen.py | 1 + esphome/components/api/__init__.py | 34 +++++--- .../components/api/homeassistant_service.h | 46 ++++++++++- esphome/core/automation.h | 56 +++++++++++-- esphome/cpp_generator.py | 26 +++++++ tests/unit_tests/test_cpp_generator.py | 78 +++++++++++++++++++ 6 files changed, 223 insertions(+), 18 deletions(-) diff --git a/esphome/codegen.py b/esphome/codegen.py index c5283f4967..30e3135360 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -11,6 +11,7 @@ from esphome.cpp_generator import ( # noqa: F401 ArrayInitializer, Expression, + FlashStringLiteral, LineComment, LogStringLiteral, MockObj, diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index d7b6bec357..dd99862cc2 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -535,24 +535,31 @@ async def homeassistant_service_to_code( cg.add_define("USE_API_HOMEASSISTANT_SERVICES") serv = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, serv, False) - templ = await cg.templatable(config[CONF_ACTION], args, None) + templ = await cg.templatable(config[CONF_ACTION], args, cg.std_string) cg.add(var.set_service(templ)) # Initialize FixedVectors with exact sizes from config cg.add(var.init_data(len(config[CONF_DATA]))) for key, value in config[CONF_DATA].items(): + # output_type=None because lambdas can return non-string types (int, + # float, char*) that TemplatableStringValue converts via to_string. + # Static strings are manually wrapped for PROGMEM on ESP8266. templ = await cg.templatable(value, args, None) - cg.add(var.add_data(key, templ)) + if isinstance(templ, str): + templ = cg.FlashStringLiteral(templ) + cg.add(var.add_data(cg.FlashStringLiteral(key), templ)) cg.add(var.init_data_template(len(config[CONF_DATA_TEMPLATE]))) for key, value in config[CONF_DATA_TEMPLATE].items(): templ = await cg.templatable(value, args, None) - cg.add(var.add_data_template(key, templ)) + if isinstance(templ, str): + templ = cg.FlashStringLiteral(templ) + cg.add(var.add_data_template(cg.FlashStringLiteral(key), templ)) cg.add(var.init_variables(len(config[CONF_VARIABLES]))) for key, value in config[CONF_VARIABLES].items(): templ = await cg.templatable(value, args, None) - cg.add(var.add_variable(key, templ)) + cg.add(var.add_variable(cg.FlashStringLiteral(key), templ)) if on_error := config.get(CONF_ON_ERROR): cg.add_define("USE_API_HOMEASSISTANT_ACTION_RESPONSES") @@ -621,24 +628,31 @@ async def homeassistant_event_to_code(config, action_id, template_arg, args): cg.add_define("USE_API_HOMEASSISTANT_SERVICES") serv = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, serv, True) - templ = await cg.templatable(config[CONF_EVENT], args, None) + templ = await cg.templatable(config[CONF_EVENT], args, cg.std_string) cg.add(var.set_service(templ)) # Initialize FixedVectors with exact sizes from config cg.add(var.init_data(len(config[CONF_DATA]))) for key, value in config[CONF_DATA].items(): + # output_type=None because lambdas can return non-string types (int, + # float, char*) that TemplatableStringValue converts via to_string. + # Static strings are manually wrapped for PROGMEM on ESP8266. templ = await cg.templatable(value, args, None) - cg.add(var.add_data(key, templ)) + if isinstance(templ, str): + templ = cg.FlashStringLiteral(templ) + cg.add(var.add_data(cg.FlashStringLiteral(key), templ)) cg.add(var.init_data_template(len(config[CONF_DATA_TEMPLATE]))) for key, value in config[CONF_DATA_TEMPLATE].items(): templ = await cg.templatable(value, args, None) - cg.add(var.add_data_template(key, templ)) + if isinstance(templ, str): + templ = cg.FlashStringLiteral(templ) + cg.add(var.add_data_template(cg.FlashStringLiteral(key), templ)) cg.add(var.init_variables(len(config[CONF_VARIABLES]))) for key, value in config[CONF_VARIABLES].items(): templ = await cg.templatable(value, args, None) - cg.add(var.add_variable(key, templ)) + cg.add(var.add_variable(cg.FlashStringLiteral(key), templ)) return var @@ -662,11 +676,11 @@ async def homeassistant_tag_scanned_to_code(config, action_id, template_arg, arg cg.add_define("USE_API_HOMEASSISTANT_SERVICES") serv = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, serv, True) - cg.add(var.set_service("esphome.tag_scanned")) + cg.add(var.set_service(cg.FlashStringLiteral("esphome.tag_scanned"))) # Initialize FixedVector with exact size (1 data field) cg.add(var.init_data(1)) templ = await cg.templatable(config[CONF_TAG], args, cg.std_string) - cg.add(var.add_data("tag_id", templ)) + cg.add(var.add_data(cg.FlashStringLiteral("tag_id"), templ)) return var diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 340699e1a6..9d14061d07 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -130,6 +130,20 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts this->add_kv_(this->variables_, key, std::forward<V>(value)); } +#ifdef USE_ESP8266 + // On ESP8266, ESPHOME_F() returns __FlashStringHelper* (PROGMEM pointer). + // Store as const char* — populate_service_map copies from PROGMEM at play() time. + template<typename V> void add_data(const __FlashStringHelper *key, V &&value) { + this->add_kv_(this->data_, reinterpret_cast<const char *>(key), std::forward<V>(value)); + } + template<typename V> void add_data_template(const __FlashStringHelper *key, V &&value) { + this->add_kv_(this->data_template_, reinterpret_cast<const char *>(key), std::forward<V>(value)); + } + template<typename V> void add_variable(const __FlashStringHelper *key, V &&value) { + this->add_kv_(this->variables_, reinterpret_cast<const char *>(key), std::forward<V>(value)); + } +#endif + #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES template<typename T> void set_response_template(T response_template) { this->response_template_ = response_template; @@ -221,7 +235,32 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts Ts... x) { dest.init(source.size()); - // Count non-static strings to allocate exact storage needed +#ifdef USE_ESP8266 + // On ESP8266, all static strings from codegen are FLASH_STRING (PROGMEM), + // so is_static_string() is always false — the zero-copy STATIC_STRING fast + // path from the non-ESP8266 branch cannot trigger. We copy all keys and + // values unconditionally: keys via _P functions (may be in PROGMEM), values + // via value() which handles FLASH_STRING internally. + value_storage.init(source.size() * 2); + + for (auto &it : source) { + auto &kv = dest.emplace_back(); + + // Key: copy from possible PROGMEM + { + size_t key_len = strlen_P(it.key); + value_storage.push_back(std::string(key_len, '\0')); + memcpy_P(value_storage.back().data(), it.key, key_len); + kv.key = StringRef(value_storage.back()); + } + + // Value: value() handles FLASH_STRING via _P functions internally + value_storage.push_back(it.value.value(x...)); + kv.value = StringRef(value_storage.back()); + } +#else + // On non-ESP8266, strings are directly readable from flash-mapped memory. + // Count non-static strings to allocate exact storage needed. size_t lambda_count = 0; for (const auto &it : source) { if (!it.value.is_static_string()) { @@ -235,14 +274,15 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts kv.key = StringRef(it.key); if (it.value.is_static_string()) { - // Static string from YAML - zero allocation + // Static string — pointer directly readable, zero allocation kv.value = StringRef(it.value.get_static_string()); } else { - // Lambda evaluation - store result, reference it + // Lambda — evaluate and store result value_storage.push_back(it.value.value(x...)); kv.value = StringRef(value_storage.back()); } } +#endif } APIServer *parent_; diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 31a2fc06f4..7934fdbec9 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -4,6 +4,7 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include "esphome/core/preferences.h" +#include "esphome/core/progmem.h" #include "esphome/core/string_ref.h" #include <concepts> #include <functional> @@ -56,6 +57,16 @@ template<typename T, typename... X> class TemplatableValue { this->static_str_ = str; } +#ifdef USE_ESP8266 + // On ESP8266, __FlashStringHelper* is a distinct type from const char*. + // ESPHOME_F(s) expands to F(s) which returns __FlashStringHelper* pointing to PROGMEM. + // Store as FLASH_STRING — value()/is_empty()/ref_or_copy_to() use _P functions + // to access the PROGMEM pointer safely. + TemplatableValue(const __FlashStringHelper *str) requires std::same_as<T, std::string> : type_(FLASH_STRING) { + this->static_str_ = reinterpret_cast<const char *>(str); + } +#endif + template<typename F> TemplatableValue(F value) requires(!std::invocable<F, X...>) : type_(VALUE) { if constexpr (USE_HEAP_STORAGE) { this->value_ = new T(std::move(value)); @@ -89,7 +100,7 @@ template<typename T, typename... X> class TemplatableValue { this->f_ = new std::function<T(X...)>(*other.f_); } else if (this->type_ == STATELESS_LAMBDA) { this->stateless_f_ = other.stateless_f_; - } else if (this->type_ == STATIC_STRING) { + } else if (this->type_ == STATIC_STRING || this->type_ == FLASH_STRING) { this->static_str_ = other.static_str_; } } @@ -108,7 +119,7 @@ template<typename T, typename... X> class TemplatableValue { other.f_ = nullptr; } else if (this->type_ == STATELESS_LAMBDA) { this->stateless_f_ = other.stateless_f_; - } else if (this->type_ == STATIC_STRING) { + } else if (this->type_ == STATIC_STRING || this->type_ == FLASH_STRING) { this->static_str_ = other.static_str_; } other.type_ = NONE; @@ -141,7 +152,7 @@ template<typename T, typename... X> class TemplatableValue { } else if (this->type_ == LAMBDA) { delete this->f_; } - // STATELESS_LAMBDA/STATIC_STRING/NONE: no cleanup needed (pointers, not heap-allocated) + // STATELESS_LAMBDA/STATIC_STRING/FLASH_STRING/NONE: no cleanup needed (pointers, not heap-allocated) } bool has_value() const { return this->type_ != NONE; } @@ -165,6 +176,17 @@ template<typename T, typename... X> class TemplatableValue { return std::string(this->static_str_); } __builtin_unreachable(); +#ifdef USE_ESP8266 + case FLASH_STRING: + // PROGMEM pointer — must use _P functions to access on ESP8266 + if constexpr (std::same_as<T, std::string>) { + size_t len = strlen_P(this->static_str_); + std::string result(len, '\0'); + memcpy_P(result.data(), this->static_str_, len); + return result; + } + __builtin_unreachable(); +#endif case NONE: default: return T{}; @@ -186,9 +208,12 @@ template<typename T, typename... X> class TemplatableValue { } /// Check if this holds a static string (const char* stored without allocation) + /// The pointer is always directly readable (RAM or flash-mapped). + /// Returns false for FLASH_STRING (PROGMEM on ESP8266, requires _P functions). bool is_static_string() const { return this->type_ == STATIC_STRING; } /// Get the static string pointer (only valid if is_static_string() returns true) + /// The pointer is always directly readable — FLASH_STRING uses a separate type. const char *get_static_string() const { return this->static_str_; } /// Check if the string value is empty without allocating (for std::string specialization). @@ -200,6 +225,12 @@ template<typename T, typename... X> class TemplatableValue { return true; case STATIC_STRING: return this->static_str_ == nullptr || this->static_str_[0] == '\0'; +#ifdef USE_ESP8266 + case FLASH_STRING: + // PROGMEM pointer — must use progmem_read_byte on ESP8266 + return this->static_str_ == nullptr || + progmem_read_byte(reinterpret_cast<const uint8_t *>(this->static_str_)) == '\0'; +#endif case VALUE: return this->value_->empty(); default: // LAMBDA/STATELESS_LAMBDA - must call value() @@ -209,8 +240,9 @@ template<typename T, typename... X> class TemplatableValue { /// Get a StringRef to the string value without heap allocation when possible. /// For STATIC_STRING/VALUE, returns reference to existing data (no allocation). + /// For FLASH_STRING (ESP8266 PROGMEM), copies to provided buffer via _P functions. /// For LAMBDA/STATELESS_LAMBDA, calls value(), copies to provided buffer, returns ref to buffer. - /// @param lambda_buf Buffer used only for lambda case (must remain valid while StringRef is used). + /// @param lambda_buf Buffer used only for copy cases (must remain valid while StringRef is used). /// @param lambda_buf_size Size of the buffer. /// @return StringRef pointing to the string data. StringRef ref_or_copy_to(char *lambda_buf, size_t lambda_buf_size) const requires std::same_as<T, std::string> { @@ -221,6 +253,19 @@ template<typename T, typename... X> class TemplatableValue { if (this->static_str_ == nullptr) return StringRef(); return StringRef(this->static_str_, strlen(this->static_str_)); +#ifdef USE_ESP8266 + case FLASH_STRING: + if (this->static_str_ == nullptr) + return StringRef(); + { + // PROGMEM pointer — copy to buffer via _P functions + size_t len = strlen_P(this->static_str_); + size_t copy_len = std::min(len, lambda_buf_size - 1); + memcpy_P(lambda_buf, this->static_str_, copy_len); + lambda_buf[copy_len] = '\0'; + return StringRef(lambda_buf, copy_len); + } +#endif case VALUE: return StringRef(this->value_->data(), this->value_->size()); default: { // LAMBDA/STATELESS_LAMBDA - must call value() and copy @@ -239,6 +284,7 @@ template<typename T, typename... X> class TemplatableValue { LAMBDA, STATELESS_LAMBDA, STATIC_STRING, // For const char* when T is std::string - avoids heap allocation + FLASH_STRING, // PROGMEM pointer on ESP8266; never set on other platforms } type_; // For std::string, use heap pointer to minimize union size (4 bytes vs 12+). // For other types, store value inline as before. @@ -247,7 +293,7 @@ template<typename T, typename... X> class TemplatableValue { ValueStorage value_; // T for inline storage, T* for heap storage std::function<T(X...)> *f_; T (*stateless_f_)(X...); - const char *static_str_; // For STATIC_STRING type + const char *static_str_; // For STATIC_STRING and FLASH_STRING types }; }; diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index fe666bdd6e..5457485d25 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -247,6 +247,23 @@ class LogStringLiteral(Literal): return f"LOG_STR({cpp_string_escape(self.string)})" +class FlashStringLiteral(Literal): + """A string literal wrapped in ESPHOME_F() for PROGMEM storage on ESP8266. + + On ESP8266, ESPHOME_F(s) expands to F(s) which stores the string in flash (PROGMEM). + On other platforms, ESPHOME_F(s) expands to plain s (no-op). + """ + + __slots__ = ("string",) + + def __init__(self, string: str) -> None: + super().__init__() + self.string = string + + def __str__(self) -> str: + return f"ESPHOME_F({cpp_string_escape(self.string)})" + + class IntLiteral(Literal): __slots__ = ("i",) @@ -761,6 +778,15 @@ async def templatable( if is_template(value): return await process_lambda(value, args, return_type=output_type) if to_exp is None: + # Automatically wrap static strings in ESPHOME_F() for PROGMEM storage on ESP8266. + # On other platforms ESPHOME_F() is a no-op returning const char*. + # Lazy import to avoid circular dependency (cpp_generator <-> cpp_types). + # Identity check (is) avoids brittle string comparison. + if isinstance(value, str) and output_type is not None: + from esphome.cpp_types import std_string + + if output_type is std_string: + return FlashStringLiteral(value) return value if isinstance(to_exp, dict): return to_exp[value] diff --git a/tests/unit_tests/test_cpp_generator.py b/tests/unit_tests/test_cpp_generator.py index 049d21027f..bdc31cdef8 100644 --- a/tests/unit_tests/test_cpp_generator.py +++ b/tests/unit_tests/test_cpp_generator.py @@ -248,6 +248,12 @@ class TestLiterals: (cg.FloatLiteral(4.2), "4.2f"), (cg.FloatLiteral(1.23456789), "1.23456789f"), (cg.FloatLiteral(math.nan), "NAN"), + (cg.FlashStringLiteral("hello"), 'ESPHOME_F("hello")'), + (cg.FlashStringLiteral(""), 'ESPHOME_F("")'), + ( + cg.FlashStringLiteral('quote"here'), + 'ESPHOME_F("quote\\042here")', + ), ), ) def test_str__simple(self, target: cg.Literal, expected: str): @@ -624,3 +630,75 @@ class TestProcessLambda: # Test invalid tuple format (single element) with pytest.raises(AssertionError): await cg.process_lambda(lambda_obj, [(int,)]) + + +@pytest.mark.asyncio +async def test_templatable__string_with_std_string_returns_flash_literal() -> None: + """Static string with std::string output_type returns FlashStringLiteral.""" + result = await cg.templatable("hello", [], ct.std_string) + + assert isinstance(result, cg.FlashStringLiteral) + assert str(result) == 'ESPHOME_F("hello")' + + +@pytest.mark.asyncio +async def test_templatable__empty_string_with_std_string() -> None: + """Empty static string with std::string output_type returns FlashStringLiteral.""" + result = await cg.templatable("", [], ct.std_string) + + assert isinstance(result, cg.FlashStringLiteral) + assert str(result) == 'ESPHOME_F("")' + + +@pytest.mark.asyncio +async def test_templatable__string_with_none_output_type() -> None: + """Static string with output_type=None returns raw string (no wrapping).""" + result = await cg.templatable("hello", [], None) + + assert isinstance(result, str) + assert result == "hello" + + +@pytest.mark.asyncio +async def test_templatable__int_with_std_string() -> None: + """Non-string value with std::string output_type returns raw value.""" + result = await cg.templatable(42, [], ct.std_string) + + assert result == 42 + + +@pytest.mark.asyncio +async def test_templatable__string_with_non_string_output_type() -> None: + """Static string with non-std::string output_type returns raw string.""" + result = await cg.templatable("hello", [], ct.bool_) + + assert isinstance(result, str) + assert result == "hello" + + +@pytest.mark.asyncio +async def test_templatable__with_to_exp_callable() -> None: + """When to_exp is provided, it is applied to non-template values.""" + result = await cg.templatable(42, [], None, to_exp=lambda x: x * 2) + + assert result == 84 + + +@pytest.mark.asyncio +async def test_templatable__with_to_exp_dict() -> None: + """When to_exp is a dict, value is looked up.""" + mapping: dict[str, int] = {"on": 1, "off": 0} + result = await cg.templatable("on", [], None, to_exp=mapping) + + assert result == 1 + + +@pytest.mark.asyncio +async def test_templatable__lambda_with_std_string() -> None: + """Lambda value returns LambdaExpression, not FlashStringLiteral.""" + from esphome.core import Lambda + + lambda_obj = Lambda('return "hello";') + result = await cg.templatable(lambda_obj, [], ct.std_string) + + assert isinstance(result, cg.LambdaExpression) From 00242443e1e67366712840b9fe1b47831d2e9fea Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:57:23 -1000 Subject: [PATCH 1040/2030] [light] Replace powf gamma with pre-computed lookup tables (LUT) (#14123) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/core.cpp | 1 + esphome/components/esp8266/core.cpp | 3 + esphome/components/host/core.cpp | 1 + esphome/components/libretiny/core.cpp | 1 + esphome/components/light/__init__.py | 40 +++++++++- esphome/components/light/addressable_light.h | 4 +- .../light/addressable_light_wrapper.h | 9 +-- .../components/light/esp_color_correction.cpp | 36 ++++----- .../components/light/esp_color_correction.h | 45 +++++++---- esphome/components/light/light_call.cpp | 5 +- esphome/components/light/light_color_values.h | 48 +++++------- esphome/components/light/light_state.cpp | 78 ++++++++++++++++--- esphome/components/light/light_state.h | 26 ++++++- esphome/components/lvgl/light/lvgl_light.h | 2 +- esphome/components/rgb/rgb_light_output.h | 2 +- esphome/components/rgbw/rgbw_light_output.h | 2 +- esphome/components/rp2040/core.cpp | 1 + esphome/components/zephyr/core.cpp | 1 + esphome/core/defines.h | 1 + esphome/core/hal.h | 1 + esphome/core/helpers.h | 4 + 21 files changed, 228 insertions(+), 83 deletions(-) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index b9ae871abf..59b791da40 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -48,6 +48,7 @@ void arch_init() { void HOT arch_feed_wdt() { esp_task_wdt_reset(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { uint32_t freq = 0; diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 7136cf41cb..b665124d66 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -34,6 +34,9 @@ void HOT arch_feed_wdt() { system_soft_wdt_feed(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } +uint16_t progmem_read_uint16(const uint16_t *addr) { + return pgm_read_word(addr); // NOLINT +} uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return esp_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return F_CPU; } diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index 9af85bec58..cb2b2e19d7 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -59,6 +59,7 @@ void HOT arch_feed_wdt() { } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 88952692a7..74b33a30a0 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -36,6 +36,7 @@ void HOT arch_feed_wdt() { lt_wdt_feed(); } uint32_t arch_get_cpu_cycle_count() { return lt_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return lt_cpu_get_freq(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } } // namespace esphome diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index f1089ad64f..40382bbda7 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass, field import enum import esphome.automation as auto @@ -37,7 +38,7 @@ from esphome.const import ( CONF_WEB_SERVER, CONF_WHITE, ) -from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core import CORE, ID, CoroPriority, HexInt, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.cpp_generator import MockObjClass @@ -66,6 +67,40 @@ from .types import ( # noqa CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True +DOMAIN = "light" + + +@dataclass +class LightData: + gamma_tables: dict = field(default_factory=dict) # gamma_value -> fwd_arr + + +def _get_data() -> LightData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = LightData() + return CORE.data[DOMAIN] + + +def _get_or_create_gamma_table(gamma_correct): + data = _get_data() + if gamma_correct in data.gamma_tables: + return data.gamma_tables[gamma_correct] + + if gamma_correct > 0: + forward = [ + HexInt(min(65535, int(round((i / 255.0) ** gamma_correct * 65535)))) + for i in range(256) + ] + else: + forward = [HexInt(int(round(i / 255.0 * 65535))) for i in range(256)] + + gamma_str = f"{gamma_correct}".replace(".", "_") + fwd_id = ID(f"gamma_{gamma_str}_fwd", is_declaration=True, type=cg.uint16) + fwd_arr = cg.progmem_array(fwd_id, forward) + data.gamma_tables[gamma_correct] = fwd_arr + return fwd_arr + + LightRestoreMode = light_ns.enum("LightRestoreMode") RESTORE_MODES = { "RESTORE_DEFAULT_OFF": LightRestoreMode.LIGHT_RESTORE_DEFAULT_OFF, @@ -239,6 +274,9 @@ async def setup_light_core_(light_var, output_var, config): cg.add(light_var.set_flash_transition_length(flash_transition_length)) if (gamma_correct := config.get(CONF_GAMMA_CORRECT)) is not None: cg.add(light_var.set_gamma_correct(gamma_correct)) + fwd_arr = _get_or_create_gamma_table(gamma_correct) + cg.add(light_var.set_gamma_table(fwd_arr)) + cg.add_define("USE_LIGHT_GAMMA_LUT") effects = await cg.build_registry_list( EFFECTS_REGISTRY, config.get(CONF_EFFECTS, []) ) diff --git a/esphome/components/light/addressable_light.h b/esphome/components/light/addressable_light.h index fcaf07f578..17cdb7d6f6 100644 --- a/esphome/components/light/addressable_light.h +++ b/esphome/components/light/addressable_light.h @@ -66,7 +66,9 @@ class AddressableLight : public LightOutput, public Component { Color(to_uint8_scale(red), to_uint8_scale(green), to_uint8_scale(blue), to_uint8_scale(white))); } void setup_state(LightState *state) override { - this->correction_.calculate_gamma_table(state->get_gamma_correct()); +#ifdef USE_LIGHT_GAMMA_LUT + this->correction_.set_gamma_table(state->get_gamma_table()); +#endif this->state_parent_ = state; } void update_state(LightState *state) override; diff --git a/esphome/components/light/addressable_light_wrapper.h b/esphome/components/light/addressable_light_wrapper.h index cd83482248..cc6aa57905 100644 --- a/esphome/components/light/addressable_light_wrapper.h +++ b/esphome/components/light/addressable_light_wrapper.h @@ -74,11 +74,10 @@ class AddressableLightWrapper : public light::AddressableLight { return; } - float gamma = this->light_state_->get_gamma_correct(); - float r = gamma_uncorrect(this->wrapper_state_[0] / 255.0f, gamma); - float g = gamma_uncorrect(this->wrapper_state_[1] / 255.0f, gamma); - float b = gamma_uncorrect(this->wrapper_state_[2] / 255.0f, gamma); - float w = gamma_uncorrect(this->wrapper_state_[3] / 255.0f, gamma); + float r = this->light_state_->gamma_uncorrect_lut(this->wrapper_state_[0] / 255.0f); + float g = this->light_state_->gamma_uncorrect_lut(this->wrapper_state_[1] / 255.0f); + float b = this->light_state_->gamma_uncorrect_lut(this->wrapper_state_[2] / 255.0f); + float w = this->light_state_->gamma_uncorrect_lut(this->wrapper_state_[3] / 255.0f); auto call = this->light_state_->make_call(); diff --git a/esphome/components/light/esp_color_correction.cpp b/esphome/components/light/esp_color_correction.cpp index 1b511a94b2..9d731a2bd5 100644 --- a/esphome/components/light/esp_color_correction.cpp +++ b/esphome/components/light/esp_color_correction.cpp @@ -1,25 +1,25 @@ #include "esp_color_correction.h" -#include "light_color_values.h" -#include "esphome/core/log.h" namespace esphome::light { -void ESPColorCorrection::calculate_gamma_table(float gamma) { - for (uint16_t i = 0; i < 256; i++) { - // corrected = val ^ gamma - auto corrected = to_uint8_scale(gamma_correct(i / 255.0f, gamma)); - this->gamma_table_[i] = corrected; - } - if (gamma == 0.0f) { - for (uint16_t i = 0; i < 256; i++) - this->gamma_reverse_table_[i] = i; - return; - } - for (uint16_t i = 0; i < 256; i++) { - // val = corrected ^ (1/gamma) - auto uncorrected = to_uint8_scale(powf(i / 255.0f, 1.0f / gamma)); - this->gamma_reverse_table_[i] = uncorrected; - } +uint8_t ESPColorCorrection::gamma_correct_(uint8_t value) const { + if (this->gamma_table_ == nullptr) + return value; + return static_cast<uint8_t>((progmem_read_uint16(&this->gamma_table_[value]) + 128) / 257); +} + +uint8_t ESPColorCorrection::gamma_uncorrect_(uint8_t value) const { + if (this->gamma_table_ == nullptr) + return value; + if (value == 0) + return 0; + uint16_t target = value * 257; // Scale 0-255 to 0-65535 + uint8_t lo = gamma_table_reverse_search(this->gamma_table_, target); + if (lo >= 255) + return 255; + uint16_t a = progmem_read_uint16(&this->gamma_table_[lo]); + uint16_t b = progmem_read_uint16(&this->gamma_table_[lo + 1]); + return (target - a <= b - target) ? lo : lo + 1; } } // namespace esphome::light diff --git a/esphome/components/light/esp_color_correction.h b/esphome/components/light/esp_color_correction.h index d275e045b7..48ecc46364 100644 --- a/esphome/components/light/esp_color_correction.h +++ b/esphome/components/light/esp_color_correction.h @@ -1,15 +1,30 @@ #pragma once #include "esphome/core/color.h" +#include "esphome/core/hal.h" namespace esphome::light { +/// Binary search a monotonically increasing uint16[256] PROGMEM table. +/// Returns the largest index where table[index] <= target. +inline uint8_t gamma_table_reverse_search(const uint16_t *table, uint16_t target) { + uint8_t lo = 0, hi = 255; + while (lo < hi) { + uint8_t mid = (lo + hi + 1) / 2; + if (progmem_read_uint16(&table[mid]) <= target) { + lo = mid; + } else { + hi = mid - 1; + } + } + return lo; +} + class ESPColorCorrection { public: - ESPColorCorrection() : max_brightness_(255, 255, 255, 255) {} void set_max_brightness(const Color &max_brightness) { this->max_brightness_ = max_brightness; } void set_local_brightness(uint8_t local_brightness) { this->local_brightness_ = local_brightness; } - void calculate_gamma_table(float gamma); + void set_gamma_table(const uint16_t *table) { this->gamma_table_ = table; } inline Color color_correct(Color color) const ESPHOME_ALWAYS_INLINE { // corrected = (uncorrected * max_brightness * local_brightness) ^ gamma return Color(this->color_correct_red(color.red), this->color_correct_green(color.green), @@ -17,19 +32,19 @@ class ESPColorCorrection { } inline uint8_t color_correct_red(uint8_t red) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8_twice(red, this->max_brightness_.red, this->local_brightness_); - return this->gamma_table_[res]; + return this->gamma_correct_(res); } inline uint8_t color_correct_green(uint8_t green) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8_twice(green, this->max_brightness_.green, this->local_brightness_); - return this->gamma_table_[res]; + return this->gamma_correct_(res); } inline uint8_t color_correct_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8_twice(blue, this->max_brightness_.blue, this->local_brightness_); - return this->gamma_table_[res]; + return this->gamma_correct_(res); } inline uint8_t color_correct_white(uint8_t white) const ESPHOME_ALWAYS_INLINE { uint8_t res = esp_scale8_twice(white, this->max_brightness_.white, this->local_brightness_); - return this->gamma_table_[res]; + return this->gamma_correct_(res); } inline Color color_uncorrect(Color color) const ESPHOME_ALWAYS_INLINE { // uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness) @@ -39,36 +54,40 @@ class ESPColorCorrection { inline uint8_t color_uncorrect_red(uint8_t red) const ESPHOME_ALWAYS_INLINE { if (this->max_brightness_.red == 0 || this->local_brightness_ == 0) return 0; - uint16_t uncorrected = this->gamma_reverse_table_[red] * 255UL; + uint16_t uncorrected = this->gamma_uncorrect_(red) * 255UL; uint16_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_; return (uint8_t) std::min(res, uint16_t(255)); } inline uint8_t color_uncorrect_green(uint8_t green) const ESPHOME_ALWAYS_INLINE { if (this->max_brightness_.green == 0 || this->local_brightness_ == 0) return 0; - uint16_t uncorrected = this->gamma_reverse_table_[green] * 255UL; + uint16_t uncorrected = this->gamma_uncorrect_(green) * 255UL; uint16_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_; return (uint8_t) std::min(res, uint16_t(255)); } inline uint8_t color_uncorrect_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE { if (this->max_brightness_.blue == 0 || this->local_brightness_ == 0) return 0; - uint16_t uncorrected = this->gamma_reverse_table_[blue] * 255UL; + uint16_t uncorrected = this->gamma_uncorrect_(blue) * 255UL; uint16_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_; return (uint8_t) std::min(res, uint16_t(255)); } inline uint8_t color_uncorrect_white(uint8_t white) const ESPHOME_ALWAYS_INLINE { if (this->max_brightness_.white == 0 || this->local_brightness_ == 0) return 0; - uint16_t uncorrected = this->gamma_reverse_table_[white] * 255UL; + uint16_t uncorrected = this->gamma_uncorrect_(white) * 255UL; uint16_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_; return (uint8_t) std::min(res, uint16_t(255)); } protected: - uint8_t gamma_table_[256]; - uint8_t gamma_reverse_table_[256]; - Color max_brightness_; + /// Forward gamma: read uint16 PROGMEM table, convert to uint8 + uint8_t gamma_correct_(uint8_t value) const; + /// Reverse gamma: binary search the forward PROGMEM table + uint8_t gamma_uncorrect_(uint8_t value) const; + + const uint16_t *gamma_table_{nullptr}; + Color max_brightness_{255, 255, 255, 255}; uint8_t local_brightness_{255}; }; diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 0291b2c3c6..14cd0e92f6 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -389,9 +389,8 @@ void LightCall::transform_parameters_() { const float ww_fraction = (color_temp - min_mireds) / range; const float cw_fraction = 1.0f - ww_fraction; const float max_cw_ww = std::max(ww_fraction, cw_fraction); - const float gamma = this->parent_->get_gamma_correct(); - this->cold_white_ = gamma_uncorrect(cw_fraction / max_cw_ww, gamma); - this->warm_white_ = gamma_uncorrect(ww_fraction / max_cw_ww, gamma); + this->cold_white_ = this->parent_->gamma_uncorrect_lut(cw_fraction / max_cw_ww); + this->warm_white_ = this->parent_->gamma_uncorrect_lut(ww_fraction / max_cw_ww); this->set_flag_(FLAG_HAS_COLD_WHITE); this->set_flag_(FLAG_HAS_WARM_WHITE); } diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index dc23263312..3a9ca8c8c2 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -111,60 +111,54 @@ class LightColorValues { } } - // Note that method signature of as_* methods is kept as-is for compatibility reasons, so not all parameters - // are always used or necessary. Methods will be deprecated later. - /// Convert these light color values to a binary representation and write them to binary. void as_binary(bool *binary) const { *binary = this->state_ == 1.0f; } /// Convert these light color values to a brightness-only representation and write them to brightness. - void as_brightness(float *brightness, float gamma = 0) const { - *brightness = gamma_correct(this->state_ * this->brightness_, gamma); - } + void as_brightness(float *brightness) const { *brightness = this->state_ * this->brightness_; } /// Convert these light color values to an RGB representation and write them to red, green, blue. - void as_rgb(float *red, float *green, float *blue, float gamma = 0, bool color_interlock = false) const { + void as_rgb(float *red, float *green, float *blue) const { if (this->color_mode_ & ColorCapability::RGB) { float brightness = this->state_ * this->brightness_ * this->color_brightness_; - *red = gamma_correct(brightness * this->red_, gamma); - *green = gamma_correct(brightness * this->green_, gamma); - *blue = gamma_correct(brightness * this->blue_, gamma); + *red = brightness * this->red_; + *green = brightness * this->green_; + *blue = brightness * this->blue_; } else { *red = *green = *blue = 0; } } /// Convert these light color values to an RGBW representation and write them to red, green, blue, white. - void as_rgbw(float *red, float *green, float *blue, float *white, float gamma = 0, - bool color_interlock = false) const { - this->as_rgb(red, green, blue, gamma); + void as_rgbw(float *red, float *green, float *blue, float *white) const { + this->as_rgb(red, green, blue); if (this->color_mode_ & ColorCapability::WHITE) { - *white = gamma_correct(this->state_ * this->brightness_ * this->white_, gamma); + *white = this->state_ * this->brightness_ * this->white_; } else { *white = 0; } } /// Convert these light color values to an RGBWW representation with the given parameters. - void as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, float gamma = 0, + void as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness = false) const { - this->as_rgb(red, green, blue, gamma); - this->as_cwww(cold_white, warm_white, gamma, constant_brightness); + this->as_rgb(red, green, blue); + this->as_cwww(cold_white, warm_white, constant_brightness); } /// Convert these light color values to an RGB+CT+BR representation with the given parameters. void as_rgbct(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue, - float *color_temperature, float *white_brightness, float gamma = 0) const { - this->as_rgb(red, green, blue, gamma); - this->as_ct(color_temperature_cw, color_temperature_ww, color_temperature, white_brightness, gamma); + float *color_temperature, float *white_brightness) const { + this->as_rgb(red, green, blue); + this->as_ct(color_temperature_cw, color_temperature_ww, color_temperature, white_brightness); } /// Convert these light color values to an CWWW representation with the given parameters. - void as_cwww(float *cold_white, float *warm_white, float gamma = 0, bool constant_brightness = false) const { + void as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false) const { if (this->color_mode_ & ColorCapability::COLD_WARM_WHITE) { - const float cw_level = gamma_correct(this->cold_white_, gamma); - const float ww_level = gamma_correct(this->warm_white_, gamma); - const float white_level = gamma_correct(this->state_ * this->brightness_, gamma); + const float cw_level = this->cold_white_; + const float ww_level = this->warm_white_; + const float white_level = this->state_ * this->brightness_; if (!constant_brightness) { *cold_white = white_level * cw_level; *warm_white = white_level * ww_level; @@ -184,13 +178,13 @@ class LightColorValues { } /// Convert these light color values to a CT+BR representation with the given parameters. - void as_ct(float color_temperature_cw, float color_temperature_ww, float *color_temperature, float *white_brightness, - float gamma = 0) const { + void as_ct(float color_temperature_cw, float color_temperature_ww, float *color_temperature, + float *white_brightness) const { const float white_level = this->color_mode_ & ColorCapability::RGB ? this->white_ : 1; if (this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) { *color_temperature = (this->color_temperature_ - color_temperature_cw) / (color_temperature_ww - color_temperature_cw); - *white_brightness = gamma_correct(this->state_ * this->brightness_ * white_level, gamma); + *white_brightness = this->state_ * this->brightness_ * white_level; } else { // Probably won't get here but put this here anyway. *white_brightness = 0; } diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index ed86bf58da..161092532a 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -1,4 +1,5 @@ #include "light_state.h" +#include "esp_color_correction.h" #include "esphome/core/defines.h" #include "esphome/core/controller_registry.h" #include "esphome/core/log.h" @@ -204,33 +205,90 @@ void LightState::add_effects(const std::initializer_list<LightEffect *> &effects void LightState::current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); } void LightState::current_values_as_brightness(float *brightness) { - this->current_values.as_brightness(brightness, this->gamma_correct_); + this->current_values.as_brightness(brightness); + *brightness = this->gamma_correct_lut(*brightness); } -void LightState::current_values_as_rgb(float *red, float *green, float *blue, bool color_interlock) { - this->current_values.as_rgb(red, green, blue, this->gamma_correct_, false); +void LightState::current_values_as_rgb(float *red, float *green, float *blue) { + this->current_values.as_rgb(red, green, blue); + *red = this->gamma_correct_lut(*red); + *green = this->gamma_correct_lut(*green); + *blue = this->gamma_correct_lut(*blue); } -void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white, bool color_interlock) { - this->current_values.as_rgbw(red, green, blue, white, this->gamma_correct_, false); +void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white) { + this->current_values.as_rgbw(red, green, blue, white); + *red = this->gamma_correct_lut(*red); + *green = this->gamma_correct_lut(*green); + *blue = this->gamma_correct_lut(*blue); + *white = this->gamma_correct_lut(*white); } void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, this->gamma_correct_, constant_brightness); + this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, constant_brightness); + *red = this->gamma_correct_lut(*red); + *green = this->gamma_correct_lut(*green); + *blue = this->gamma_correct_lut(*blue); + *cold_white = this->gamma_correct_lut(*cold_white); + *warm_white = this->gamma_correct_lut(*warm_white); } void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature, float *white_brightness) { auto traits = this->get_traits(); this->current_values.as_rgbct(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, color_temperature, - white_brightness, this->gamma_correct_); + white_brightness); + *red = this->gamma_correct_lut(*red); + *green = this->gamma_correct_lut(*green); + *blue = this->gamma_correct_lut(*blue); + *white_brightness = this->gamma_correct_lut(*white_brightness); } void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_cwww(cold_white, warm_white, this->gamma_correct_, constant_brightness); + this->current_values.as_cwww(cold_white, warm_white, constant_brightness); + *cold_white = this->gamma_correct_lut(*cold_white); + *warm_white = this->gamma_correct_lut(*warm_white); } void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) { auto traits = this->get_traits(); - this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), color_temperature, white_brightness, - this->gamma_correct_); + this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), color_temperature, white_brightness); + *white_brightness = this->gamma_correct_lut(*white_brightness); } +#ifdef USE_LIGHT_GAMMA_LUT +float LightState::gamma_correct_lut(float value) const { + if (value <= 0.0f) + return 0.0f; + if (value >= 1.0f) + return 1.0f; + if (this->gamma_table_ == nullptr) + return value; + float scaled = value * 255.0f; + auto idx = static_cast<uint8_t>(scaled); + if (idx >= 255) + return progmem_read_uint16(&this->gamma_table_[255]) / 65535.0f; + float frac = scaled - idx; + float a = progmem_read_uint16(&this->gamma_table_[idx]); + float b = progmem_read_uint16(&this->gamma_table_[idx + 1]); + return (a + frac * (b - a)) / 65535.0f; +} +float LightState::gamma_uncorrect_lut(float value) const { + if (value <= 0.0f) + return 0.0f; + if (value >= 1.0f) + return 1.0f; + if (this->gamma_table_ == nullptr) + return value; + uint16_t target = static_cast<uint16_t>(value * 65535.0f); + uint8_t lo = gamma_table_reverse_search(this->gamma_table_, target); + if (lo >= 255) + return 1.0f; + // Interpolate between lo and lo+1 + uint16_t a = progmem_read_uint16(&this->gamma_table_[lo]); + uint16_t b = progmem_read_uint16(&this->gamma_table_[lo + 1]); + if (b == a) + return lo / 255.0f; + float frac = static_cast<float>(target - a) / static_cast<float>(b - a); + return (lo + frac) / 255.0f; +} +#endif // USE_LIGHT_GAMMA_LUT + bool LightState::is_transformer_active() { return this->is_transformer_active_; } void LightState::start_effect_(uint32_t effect_index) { diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index 83b9226d03..528f5bd911 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -11,6 +11,7 @@ #include "light_traits.h" #include "light_transformer.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include <strings.h> #include <vector> @@ -166,6 +167,23 @@ class LightState : public EntityBase, public Component { void set_gamma_correct(float gamma_correct); float get_gamma_correct() const { return this->gamma_correct_; } +#ifdef USE_LIGHT_GAMMA_LUT + /// Set pre-computed gamma forward lookup table (256-entry uint16 PROGMEM array) + void set_gamma_table(const uint16_t *forward) { this->gamma_table_ = forward; } + + /// Get the forward gamma lookup table + const uint16_t *get_gamma_table() const { return this->gamma_table_; } + + /// Apply gamma correction using the pre-computed forward LUT + float gamma_correct_lut(float value) const; + /// Reverse gamma correction by binary-searching the forward LUT + float gamma_uncorrect_lut(float value) const; +#else + /// No gamma LUT — passthrough + float gamma_correct_lut(float value) const { return value; } + float gamma_uncorrect_lut(float value) const { return value; } +#endif // USE_LIGHT_GAMMA_LUT + /// Set the restore mode of this light void set_restore_mode(LightRestoreMode restore_mode); @@ -224,9 +242,9 @@ class LightState : public EntityBase, public Component { void current_values_as_brightness(float *brightness); - void current_values_as_rgb(float *red, float *green, float *blue, bool color_interlock = false); + void current_values_as_rgb(float *red, float *green, float *blue); - void current_values_as_rgbw(float *red, float *green, float *blue, float *white, bool color_interlock = false); + void current_values_as_rgbw(float *red, float *green, float *blue, float *white); void current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness = false); @@ -297,6 +315,10 @@ class LightState : public EntityBase, public Component { uint32_t flash_transition_length_{}; /// Gamma correction factor for the light. float gamma_correct_{}; +#ifdef USE_LIGHT_GAMMA_LUT + const uint16_t *gamma_table_{nullptr}; +#endif // USE_LIGHT_GAMMA_LUT + /// Whether the light value should be written in the next cycle. bool next_write_{true}; // for effects, true if a transformer (transition) is active. diff --git a/esphome/components/lvgl/light/lvgl_light.h b/esphome/components/lvgl/light/lvgl_light.h index 50ae4c5327..569f9a03c0 100644 --- a/esphome/components/lvgl/light/lvgl_light.h +++ b/esphome/components/lvgl/light/lvgl_light.h @@ -16,7 +16,7 @@ class LVLight : public light::LightOutput { } void write_state(light::LightState *state) override { float red, green, blue; - state->current_values_as_rgb(&red, &green, &blue, false); + state->current_values_as_rgb(&red, &green, &blue); auto color = lv_color_make(red * 255, green * 255, blue * 255); if (this->obj_ != nullptr) { this->set_value_(color); diff --git a/esphome/components/rgb/rgb_light_output.h b/esphome/components/rgb/rgb_light_output.h index ef53c8042d..783187667a 100644 --- a/esphome/components/rgb/rgb_light_output.h +++ b/esphome/components/rgb/rgb_light_output.h @@ -20,7 +20,7 @@ class RGBLightOutput : public light::LightOutput { } void write_state(light::LightState *state) override { float red, green, blue; - state->current_values_as_rgb(&red, &green, &blue, false); + state->current_values_as_rgb(&red, &green, &blue); this->red_->set_level(red); this->green_->set_level(green); this->blue_->set_level(blue); diff --git a/esphome/components/rgbw/rgbw_light_output.h b/esphome/components/rgbw/rgbw_light_output.h index a2ab17b75d..140726a43c 100644 --- a/esphome/components/rgbw/rgbw_light_output.h +++ b/esphome/components/rgbw/rgbw_light_output.h @@ -25,7 +25,7 @@ class RGBWLightOutput : public light::LightOutput { } void write_state(light::LightState *state) override { float red, green, blue, white; - state->current_values_as_rgbw(&red, &green, &blue, &white, this->color_interlock_); + state->current_values_as_rgbw(&red, &green, &blue, &white); this->red_->set_level(red); this->green_->set_level(green); this->blue_->set_level(blue); diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 8b86de4be1..6386d53292 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -34,6 +34,7 @@ void HOT arch_feed_wdt() { watchdog_update(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } +uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); } uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); } diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index f0772a4422..cf3ea70245 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -60,6 +60,7 @@ void arch_restart() { sys_reboot(SYS_REBOOT_COLD); } uint32_t arch_get_cpu_cycle_count() { return k_cycle_get_32(); } uint32_t arch_get_cpu_freq_hz() { return sys_clock_hw_cycles_per_sec(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } Mutex::Mutex() { auto *mutex = new k_mutex(); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1f2597dd98..8c78afa7d4 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -61,6 +61,7 @@ #define USE_IR_RF #define USE_JSON #define USE_LIGHT +#define USE_LIGHT_GAMMA_LUT #define USE_LOCK #define USE_LOGGER #define USE_LOGGER_LEVEL_LISTENERS diff --git a/esphome/core/hal.h b/esphome/core/hal.h index fa5ca646f2..ef45be629d 100644 --- a/esphome/core/hal.h +++ b/esphome/core/hal.h @@ -42,5 +42,6 @@ void arch_feed_wdt(); uint32_t arch_get_cpu_cycle_count(); uint32_t arch_get_cpu_freq_hz(); uint8_t progmem_read_byte(const uint8_t *addr); +uint16_t progmem_read_uint16(const uint16_t *addr); } // namespace esphome diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 65d590a5e6..c68cb549bb 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1437,8 +1437,12 @@ bool base64_decode_int32_vector(const std::string &base64, std::vector<int32_t> ///@{ /// Applies gamma correction of \p gamma to \p value. +// Remove before 2026.9.0 +ESPDEPRECATED("Use LightState::gamma_correct_lut() instead. Removed in 2026.9.0.", "2026.3.0") float gamma_correct(float value, float gamma); /// Reverts gamma correction of \p gamma to \p value. +// Remove before 2026.9.0 +ESPDEPRECATED("Use LightState::gamma_uncorrect_lut() instead. Removed in 2026.9.0.", "2026.3.0") float gamma_uncorrect(float value, float gamma); /// Convert \p red, \p green and \p blue (all 0-1) values to \p hue (0-360), \p saturation (0-1) and \p value (0-1). From 54f410901fa09bd025bc370be3753346c2430b9d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:57:39 -1000 Subject: [PATCH 1041/2030] [web_server] Avoid temporary std::string allocations in request parameter parsing (#14366) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../alarm_control_panel_call.cpp | 9 ++++- .../alarm_control_panel_call.h | 3 +- esphome/components/api/api_connection.cpp | 4 +- esphome/components/climate/climate.cpp | 18 ++++++--- esphome/components/climate/climate.h | 4 ++ esphome/components/text/text_call.cpp | 5 +++ esphome/components/text/text_call.h | 1 + .../components/water_heater/water_heater.cpp | 21 +++++----- .../components/water_heater/water_heater.h | 3 +- esphome/components/web_server/web_server.cpp | 38 ++++++++++++++----- esphome/components/web_server/web_server.h | 8 ++-- 11 files changed, 82 insertions(+), 32 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp index ba58ee3904..0c43cd555a 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.cpp @@ -12,7 +12,14 @@ AlarmControlPanelCall::AlarmControlPanelCall(AlarmControlPanel *parent) : parent AlarmControlPanelCall &AlarmControlPanelCall::set_code(const char *code) { if (code != nullptr) { - this->code_ = std::string(code); + return this->set_code(code, strlen(code)); + } + return *this; +} + +AlarmControlPanelCall &AlarmControlPanelCall::set_code(const char *code, size_t len) { + if (code != nullptr) { + this->code_ = std::string(code, len); } return *this; } diff --git a/esphome/components/alarm_control_panel/alarm_control_panel_call.h b/esphome/components/alarm_control_panel/alarm_control_panel_call.h index 58764ea166..6e39a0a413 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel_call.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel_call.h @@ -15,7 +15,8 @@ class AlarmControlPanelCall { AlarmControlPanelCall(AlarmControlPanel *parent); AlarmControlPanelCall &set_code(const char *code); - AlarmControlPanelCall &set_code(const std::string &code) { return this->set_code(code.c_str()); } + AlarmControlPanelCall &set_code(const char *code, size_t len); + AlarmControlPanelCall &set_code(const std::string &code) { return this->set_code(code.c_str(), code.size()); } AlarmControlPanelCall &arm_away(); AlarmControlPanelCall &arm_home(); AlarmControlPanelCall &arm_night(); diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 90287ec2dd..738dd1ef05 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -889,7 +889,7 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co } void APIConnection::on_text_command_request(const TextCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(text::Text, text, text) - call.set_value(msg.state); + call.set_value(msg.state.c_str(), msg.state.size()); call.perform(); } #endif @@ -1360,7 +1360,7 @@ void APIConnection::on_alarm_control_panel_command_request(const AlarmControlPan call.pending(); break; } - call.set_code(msg.code); + call.set_code(msg.code.c_str(), msg.code.size()); call.perform(); } #endif diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index ba6de4ff61..43d25effa3 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -173,14 +173,17 @@ ClimateCall &ClimateCall::set_mode(ClimateMode mode) { return *this; } -ClimateCall &ClimateCall::set_mode(const std::string &mode) { +ClimateCall &ClimateCall::set_mode(const std::string &mode) { return this->set_mode(mode.c_str(), mode.size()); } + +ClimateCall &ClimateCall::set_mode(const char *mode, size_t len) { + StringRef mode_ref(mode, len); for (const auto &mode_entry : CLIMATE_MODES_BY_STR) { - if (str_equals_case_insensitive(mode, mode_entry.str)) { + if (str_equals_case_insensitive(mode_ref, mode_entry.str)) { this->set_mode(static_cast<ClimateMode>(mode_entry.value)); return *this; } } - ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode.c_str()); + ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode); return *this; } @@ -266,13 +269,18 @@ ClimateCall &ClimateCall::set_swing_mode(ClimateSwingMode swing_mode) { } ClimateCall &ClimateCall::set_swing_mode(const std::string &swing_mode) { + return this->set_swing_mode(swing_mode.c_str(), swing_mode.size()); +} + +ClimateCall &ClimateCall::set_swing_mode(const char *swing_mode, size_t len) { + StringRef mode_ref(swing_mode, len); for (const auto &mode_entry : CLIMATE_SWING_MODES_BY_STR) { - if (str_equals_case_insensitive(swing_mode, mode_entry.str)) { + if (str_equals_case_insensitive(mode_ref, mode_entry.str)) { this->set_swing_mode(static_cast<ClimateSwingMode>(mode_entry.value)); return *this; } } - ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %s", this->parent_->get_name().c_str(), swing_mode.c_str()); + ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", this->parent_->get_name().c_str(), (int) len, swing_mode); return *this; } diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index 6fac254502..aa9ca91bc2 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -41,6 +41,8 @@ class ClimateCall { ClimateCall &set_mode(optional<ClimateMode> mode); /// Set the mode of the climate device based on a string. ClimateCall &set_mode(const std::string &mode); + /// Set the mode of the climate device based on a C string. + ClimateCall &set_mode(const char *mode, size_t len); /// Set the target temperature of the climate device. ClimateCall &set_target_temperature(float target_temperature); /// Set the target temperature of the climate device. @@ -87,6 +89,8 @@ class ClimateCall { ClimateCall &set_swing_mode(optional<ClimateSwingMode> swing_mode); /// Set the swing mode of the climate device based on a string. ClimateCall &set_swing_mode(const std::string &swing_mode); + /// Set the swing mode of the climate device based on a C string. + ClimateCall &set_swing_mode(const char *swing_mode, size_t len); /// Set the preset of the climate device. ClimateCall &set_preset(ClimatePreset preset); /// Set the preset of the climate device. diff --git a/esphome/components/text/text_call.cpp b/esphome/components/text/text_call.cpp index 8a1630c5ca..b7aed098c7 100644 --- a/esphome/components/text/text_call.cpp +++ b/esphome/components/text/text_call.cpp @@ -11,6 +11,11 @@ TextCall &TextCall::set_value(const std::string &value) { return *this; } +TextCall &TextCall::set_value(const char *value, size_t len) { + this->value_ = std::string(value, len); + return *this; +} + void TextCall::validate_() { const auto *name = this->parent_->get_name().c_str(); diff --git a/esphome/components/text/text_call.h b/esphome/components/text/text_call.h index 532fae34b2..5a2b257ab2 100644 --- a/esphome/components/text/text_call.h +++ b/esphome/components/text/text_call.h @@ -13,6 +13,7 @@ class TextCall { void perform(); TextCall &set_value(const std::string &value); + TextCall &set_value(const char *value, size_t len); protected: Text *const parent_; diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 9d7ae0cbc0..3989230d2d 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -5,6 +5,7 @@ #include "esphome/core/progmem.h" #include <cmath> +#include <cstring> namespace esphome::water_heater { @@ -23,23 +24,25 @@ WaterHeaterCall &WaterHeaterCall::set_mode(WaterHeaterMode mode) { return *this; } -WaterHeaterCall &WaterHeaterCall::set_mode(const char *mode) { - if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("OFF")) == 0) { +WaterHeaterCall &WaterHeaterCall::set_mode(const char *mode) { return this->set_mode(mode, strlen(mode)); } + +WaterHeaterCall &WaterHeaterCall::set_mode(const char *mode, size_t len) { + if (len == 3 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("OFF"), 3) == 0) { this->set_mode(WATER_HEATER_MODE_OFF); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("ECO")) == 0) { + } else if (len == 3 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("ECO"), 3) == 0) { this->set_mode(WATER_HEATER_MODE_ECO); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("ELECTRIC")) == 0) { + } else if (len == 8 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("ELECTRIC"), 8) == 0) { this->set_mode(WATER_HEATER_MODE_ELECTRIC); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("PERFORMANCE")) == 0) { + } else if (len == 11 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("PERFORMANCE"), 11) == 0) { this->set_mode(WATER_HEATER_MODE_PERFORMANCE); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("HIGH_DEMAND")) == 0) { + } else if (len == 11 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("HIGH_DEMAND"), 11) == 0) { this->set_mode(WATER_HEATER_MODE_HIGH_DEMAND); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("HEAT_PUMP")) == 0) { + } else if (len == 9 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("HEAT_PUMP"), 9) == 0) { this->set_mode(WATER_HEATER_MODE_HEAT_PUMP); - } else if (ESPHOME_strcasecmp_P(mode, ESPHOME_PSTR("GAS")) == 0) { + } else if (len == 3 && ESPHOME_strncasecmp_P(mode, ESPHOME_PSTR("GAS"), 3) == 0) { this->set_mode(WATER_HEATER_MODE_GAS); } else { - ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode); + ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode); } return *this; } diff --git a/esphome/components/water_heater/water_heater.h b/esphome/components/water_heater/water_heater.h index 070ae99575..a1e1ca10a6 100644 --- a/esphome/components/water_heater/water_heater.h +++ b/esphome/components/water_heater/water_heater.h @@ -76,7 +76,8 @@ class WaterHeaterCall { WaterHeaterCall &set_mode(WaterHeaterMode mode); WaterHeaterCall &set_mode(const char *mode); - WaterHeaterCall &set_mode(const std::string &mode) { return this->set_mode(mode.c_str()); } + WaterHeaterCall &set_mode(const char *mode, size_t len); + WaterHeaterCall &set_mode(const std::string &mode) { return this->set_mode(mode.c_str(), mode.size()); } WaterHeaterCall &set_target_temperature(float temperature); WaterHeaterCall &set_target_temperature_low(float temperature); WaterHeaterCall &set_target_temperature_high(float temperature); diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 4824e33dcd..47e427c0d1 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -969,7 +969,9 @@ void WebServer::handle_light_request(AsyncWebServerRequest *request, const UrlMa parse_light_param_uint_(request, ESPHOME_F("transition"), call, &decltype(call)::set_transition_length, 1000); if (is_on) { - parse_string_param_(request, ESPHOME_F("effect"), call, &decltype(call)::set_effect); + parse_cstr_param_( + request, ESPHOME_F("effect"), call, + static_cast<light::LightCall &(light::LightCall::*) (const char *, size_t)>(&decltype(call)::set_effect)); } DEFER_ACTION(call, call.perform()); @@ -1368,7 +1370,9 @@ void WebServer::handle_text_request(AsyncWebServerRequest *request, const UrlMat } auto call = obj->make_call(); - parse_string_param_(request, ESPHOME_F("value"), call, &decltype(call)::set_value); + parse_cstr_param_( + request, ESPHOME_F("value"), call, + static_cast<text::TextCall &(text::TextCall::*) (const char *, size_t)>(&decltype(call)::set_value)); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1426,7 +1430,9 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM } auto call = obj->make_call(); - parse_string_param_(request, ESPHOME_F("option"), call, &decltype(call)::set_option); + parse_cstr_param_( + request, ESPHOME_F("option"), call, + static_cast<select::SelectCall &(select::SelectCall::*) (const char *, size_t)>(&decltype(call)::set_option)); DEFER_ACTION(call, call.perform()); request->send(200); @@ -1487,10 +1493,18 @@ void WebServer::handle_climate_request(AsyncWebServerRequest *request, const Url auto call = obj->make_call(); // Parse string mode parameters - parse_string_param_(request, ESPHOME_F("mode"), call, &decltype(call)::set_mode); - parse_string_param_(request, ESPHOME_F("fan_mode"), call, &decltype(call)::set_fan_mode); - parse_string_param_(request, ESPHOME_F("swing_mode"), call, &decltype(call)::set_swing_mode); - parse_string_param_(request, ESPHOME_F("preset"), call, &decltype(call)::set_preset); + parse_cstr_param_( + request, ESPHOME_F("mode"), call, + static_cast<climate::ClimateCall &(climate::ClimateCall::*) (const char *, size_t)>(&decltype(call)::set_mode)); + parse_cstr_param_(request, ESPHOME_F("fan_mode"), call, + static_cast<climate::ClimateCall &(climate::ClimateCall::*) (const char *, size_t)>( + &decltype(call)::set_fan_mode)); + parse_cstr_param_(request, ESPHOME_F("swing_mode"), call, + static_cast<climate::ClimateCall &(climate::ClimateCall::*) (const char *, size_t)>( + &decltype(call)::set_swing_mode)); + parse_cstr_param_(request, ESPHOME_F("preset"), call, + static_cast<climate::ClimateCall &(climate::ClimateCall::*) (const char *, size_t)>( + &decltype(call)::set_preset)); // Parse temperature parameters // static_cast needed to disambiguate overloaded setters (float vs optional<float>) @@ -1804,7 +1818,10 @@ void WebServer::handle_alarm_control_panel_request(AsyncWebServerRequest *reques } auto call = obj->make_call(); - parse_string_param_(request, ESPHOME_F("code"), call, &decltype(call)::set_code); + parse_cstr_param_( + request, ESPHOME_F("code"), call, + static_cast<alarm_control_panel::AlarmControlPanelCall &( + alarm_control_panel::AlarmControlPanelCall::*) (const char *, size_t)>(&decltype(call)::set_code)); // Lookup table for alarm control panel methods static const struct { @@ -1892,7 +1909,10 @@ void WebServer::handle_water_heater_request(AsyncWebServerRequest *request, cons water_heater::WaterHeaterCall &base_call = call; // Parse mode parameter - parse_string_param_(request, ESPHOME_F("mode"), base_call, &water_heater::WaterHeaterCall::set_mode); + parse_cstr_param_( + request, ESPHOME_F("mode"), base_call, + static_cast<water_heater::WaterHeaterCall &(water_heater::WaterHeaterCall::*) (const char *, size_t)>( + &water_heater::WaterHeaterCall::set_mode)); // Parse temperature parameters parse_num_param_(request, ESPHOME_F("target_temperature"), base_call, diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 64c492f82b..6152dfbfd3 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -533,13 +533,13 @@ class WebServer final : public Controller, public Component, public AsyncWebHand } } - // Generic helper to parse and apply a string parameter + // Generic helper to parse and apply a string parameter using const char* setter (avoids std::string allocation) template<typename T, typename Ret> - void parse_string_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, - Ret (T::*setter)(const std::string &)) { + void parse_cstr_param_(AsyncWebServerRequest *request, ParamNameType param_name, T &call, + Ret (T::*setter)(const char *, size_t)) { if (request->hasArg(param_name)) { const auto &value = request->arg(param_name); - (call.*setter)(std::string(value.c_str(), value.length())); + (call.*setter)(value.c_str(), value.length()); } } From f278250740330b6b4e990ae19b0bc91d846ec924 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:57:59 -1000 Subject: [PATCH 1042/2030] [core] Deduplicate ControllerRegistry notify dispatch loop (#14394) --- esphome/core/controller_registry.cpp | 21 +++++++++++++-------- esphome/core/controller_registry.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/esphome/core/controller_registry.cpp b/esphome/core/controller_registry.cpp index 13b505e8e9..255efa86ba 100644 --- a/esphome/core/controller_registry.cpp +++ b/esphome/core/controller_registry.cpp @@ -10,21 +10,26 @@ StaticVector<Controller *, CONTROLLER_REGISTRY_MAX> ControllerRegistry::controll void ControllerRegistry::register_controller(Controller *controller) { controllers.push_back(controller); } +void ControllerRegistry::notify(void *obj, DispatchFunc dispatch) { + for (auto *controller : controllers) { + dispatch(controller, obj); + } +} + // Macro for standard registry notification dispatch - calls on_<entity_name>_update() +// Each wrapper passes a small trampoline lambda that calls the correct virtual method. +// NOLINTBEGIN(bugprone-macro-parentheses) #define CONTROLLER_REGISTRY_NOTIFY(entity_type, entity_name) \ - void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { /* NOLINT(bugprone-macro-parentheses) */ \ - for (auto *controller : controllers) { \ - controller->on_##entity_name##_update(obj); \ - } \ + void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { \ + notify(obj, [](Controller *c, void *o) { c->on_##entity_name##_update(static_cast<entity_type *>(o)); }); \ } // Macro for entities where controller method has no "_update" suffix (Event, Update) #define CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(entity_type, entity_name) \ - void ControllerRegistry::notify_##entity_name(entity_type *obj) { /* NOLINT(bugprone-macro-parentheses) */ \ - for (auto *controller : controllers) { \ - controller->on_##entity_name(obj); \ - } \ + void ControllerRegistry::notify_##entity_name(entity_type *obj) { \ + notify(obj, [](Controller *c, void *o) { c->on_##entity_name(static_cast<entity_type *>(o)); }); \ } +// NOLINTEND(bugprone-macro-parentheses) #ifdef USE_BINARY_SENSOR CONTROLLER_REGISTRY_NOTIFY(binary_sensor::BinarySensor, binary_sensor) diff --git a/esphome/core/controller_registry.h b/esphome/core/controller_registry.h index d6452d8827..15e3b4ba83 100644 --- a/esphome/core/controller_registry.h +++ b/esphome/core/controller_registry.h @@ -247,6 +247,21 @@ class ControllerRegistry { #endif protected: + /** Type-erased dispatch function pointer. + * + * Each notify method passes a small trampoline that calls the + * correct virtual method on Controller. The shared notify() loop + * iterates controllers once, calling the trampoline for each. + */ + using DispatchFunc = void (*)(Controller *, void *); + + /** Shared dispatch loop - iterates controllers and calls dispatch for each. + * + * Marked noinline to ensure only one copy of the loop exists in flash, + * rather than being duplicated into each notify_*_update wrapper. + */ + static void __attribute__((noinline)) notify(void *obj, DispatchFunc dispatch); + static StaticVector<Controller *, CONTROLLER_REGISTRY_MAX> controllers; }; From 39572d9628d80ecf5f74f99f54c536ca26b357c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:58:15 -1000 Subject: [PATCH 1043/2030] [light] Resolve effect names to indices at codegen time (#14265) --- esphome/components/light/automation.h | 2 +- esphome/components/light/automation.py | 50 ++++++++++++++++++++++++-- esphome/components/light/light_state.h | 15 ++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index c90d71c5df..2854bc62d9 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -41,7 +41,7 @@ template<typename... Ts> class LightControlAction : public Action<Ts...> { TEMPLATABLE_VALUE(float, color_temperature) TEMPLATABLE_VALUE(float, cold_white) TEMPLATABLE_VALUE(float, warm_white) - TEMPLATABLE_VALUE(std::string, effect) + TEMPLATABLE_VALUE(uint32_t, effect) void play(const Ts &...x) override { auto call = this->parent_->make_call(); diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 89b2fc0fb2..08fd26a937 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -10,12 +10,14 @@ from esphome.const import ( CONF_COLOR_MODE, CONF_COLOR_TEMPERATURE, CONF_EFFECT, + CONF_EFFECTS, CONF_FLASH_LENGTH, CONF_GREEN, CONF_ID, CONF_LIMIT_MODE, CONF_MAX_BRIGHTNESS, CONF_MIN_BRIGHTNESS, + CONF_NAME, CONF_RANGE_FROM, CONF_RANGE_TO, CONF_RED, @@ -24,6 +26,9 @@ from esphome.const import ( CONF_WARM_WHITE, CONF_WHITE, ) +from esphome.core import CORE, Lambda +from esphome.cpp_generator import LambdaExpression +from esphome.types import ConfigType from .types import ( COLOR_MODES, @@ -111,6 +116,26 @@ LIGHT_TURN_ON_ACTION_SCHEMA = automation.maybe_simple_id( ) +def _resolve_effect_index(config: ConfigType) -> int: + """Resolve a static effect name to its 1-based index at codegen time. + + Effect index 0 means "None" (no effect). Effects are 1-indexed matching + the C++ convention in LightState. + """ + original_name = config[CONF_EFFECT] + effect_name = original_name.lower() + if effect_name == "none": + return 0 + light_id = config[CONF_ID] + light_path = CORE.config.get_path_for_id(light_id)[:-1] + light_config = CORE.config.get_config_for_path(light_path) + for i, effect_conf in enumerate(light_config.get(CONF_EFFECTS, [])): + key = next(iter(effect_conf)) + if effect_conf[key][CONF_NAME].lower() == effect_name: + return i + 1 + raise ValueError(f"Effect '{original_name}' not found in light '{light_id}'") + + @automation.register_action( "light.turn_off", LightControlAction, LIGHT_TURN_OFF_ACTION_SCHEMA, synchronous=True ) @@ -165,8 +190,29 @@ async def light_control_to_code(config, action_id, template_arg, args): template_ = await cg.templatable(config[CONF_WARM_WHITE], args, float) cg.add(var.set_warm_white(template_)) if CONF_EFFECT in config: - template_ = await cg.templatable(config[CONF_EFFECT], args, cg.std_string) - cg.add(var.set_effect(template_)) + if isinstance(config[CONF_EFFECT], Lambda): + # Lambda returns a string — wrap in a C++ lambda that resolves + # the effect name to its uint32_t index at runtime + inner_lambda = await cg.process_lambda( + config[CONF_EFFECT], args, return_type=cg.std_string + ) + fwd_args = ", ".join(n for _, n in args) + # capture="" is correct: paren is a global variable name + # string-interpolated into the body at codegen time, not a + # C++ runtime capture. + wrapper = LambdaExpression( + f"auto __effect_s = ({inner_lambda})({fwd_args});\n" + f"return {paren}->get_effect_index(" + f"__effect_s.c_str(), __effect_s.size());", + args, + capture="", + return_type=cg.uint32, + ) + cg.add(var.set_effect(wrapper)) + else: + # Static string — resolve effect name to index at codegen time + effect_index = _resolve_effect_index(config) + cg.add(var.set_effect(effect_index)) return var diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index 528f5bd911..b8d72cc832 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -13,6 +13,7 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" +#include "esphome/core/progmem.h" #include <strings.h> #include <vector> @@ -218,6 +219,20 @@ class LightState : public EntityBase, public Component { return 0; // Effect not found } + /// Get effect index by name (const char* overload, avoids std::string construction). + uint32_t get_effect_index(const char *name, size_t len) const { + if (len == 4 && ESPHOME_strncasecmp_P(name, ESPHOME_PSTR("none"), 4) == 0) { + return 0; + } + StringRef ref(name, len); + for (size_t i = 0; i < this->effects_.size(); i++) { + if (str_equals_case_insensitive(ref, this->effects_[i]->get_name())) { + return i + 1; + } + } + return 0; + } + /// Get effect by index. Returns nullptr if index is invalid. LightEffect *get_effect_by_index(uint32_t index) const { if (index == 0 || index > this->effects_.size()) { From 585e195044af6a7415bf56108d4073c60a4a3e3b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:58:31 -1000 Subject: [PATCH 1044/2030] [socket] Devirtualize socket abstraction layer (#14398) --- esphome/components/api/api_server.h | 2 +- .../captive_portal/dns_server_esp32_idf.h | 2 +- esphome/components/esphome/ota/ota_esphome.h | 2 +- .../components/socket/bsd_sockets_impl.cpp | 172 +-- esphome/components/socket/bsd_sockets_impl.h | 114 ++ esphome/components/socket/headers.h | 17 + .../components/socket/lwip_raw_tcp_impl.cpp | 1150 ++++++++--------- esphome/components/socket/lwip_raw_tcp_impl.h | 200 +++ .../components/socket/lwip_sockets_impl.cpp | 139 +- esphome/components/socket/lwip_sockets_impl.h | 80 ++ esphome/components/socket/socket.cpp | 32 +- esphome/components/socket/socket.h | 110 +- esphome/core/application.h | 9 +- 13 files changed, 1153 insertions(+), 876 deletions(-) create mode 100644 esphome/components/socket/bsd_sockets_impl.h create mode 100644 esphome/components/socket/lwip_raw_tcp_impl.h create mode 100644 esphome/components/socket/lwip_sockets_impl.h diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 3abf68358c..6eff2005f8 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -257,7 +257,7 @@ class APIServer : public Component, } void socket_failed_(const LogString *msg); // Pointers and pointer-like types first (4 bytes each) - socket::Socket *socket_{nullptr}; + socket::ListenSocket *socket_{nullptr}; #ifdef USE_API_CLIENT_CONNECTED_TRIGGER Trigger<std::string, std::string> client_connected_trigger_; #endif diff --git a/esphome/components/captive_portal/dns_server_esp32_idf.h b/esphome/components/captive_portal/dns_server_esp32_idf.h index f8e4cfec84..b30856c204 100644 --- a/esphome/components/captive_portal/dns_server_esp32_idf.h +++ b/esphome/components/captive_portal/dns_server_esp32_idf.h @@ -22,7 +22,7 @@ class DNSServer { } static constexpr size_t DNS_BUFFER_SIZE = 192; - socket::Socket *socket_{nullptr}; + socket::ListenSocket *socket_{nullptr}; network::IPAddress server_ip_; uint8_t buffer_[DNS_BUFFER_SIZE]; }; diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index 53715cfe6a..08edacad92 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -84,7 +84,7 @@ class ESPHomeOTAComponent final : public ota::OTAComponent { std::unique_ptr<uint8_t[]> auth_buf_; #endif // USE_OTA_PASSWORD - socket::Socket *server_{nullptr}; + socket::ListenSocket *server_{nullptr}; std::unique_ptr<socket::Socket> client_; std::unique_ptr<ota::OTABackend> backend_; diff --git a/esphome/components/socket/bsd_sockets_impl.cpp b/esphome/components/socket/bsd_sockets_impl.cpp index c96713f376..92ecfc692b 100644 --- a/esphome/components/socket/bsd_sockets_impl.cpp +++ b/esphome/components/socket/bsd_sockets_impl.cpp @@ -1,135 +1,81 @@ -#include "socket.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" +#include "socket.h" #ifdef USE_SOCKET_IMPL_BSD_SOCKETS #include <cstring> #include "esphome/core/application.h" -#ifdef USE_ESP32 -#include <esp_idf_version.h> -#include <lwip/sockets.h> -#endif - namespace esphome::socket { -class BSDSocketImpl final : public Socket { - public: - BSDSocketImpl(int fd, bool monitor_loop = false) { - this->fd_ = fd; - // Register new socket with the application for select() if monitoring requested - if (monitor_loop && this->fd_ >= 0) { - // Only set loop_monitored_ to true if registration succeeds - this->loop_monitored_ = App.register_socket_fd(this->fd_); - } - } - ~BSDSocketImpl() override { - if (!this->closed_) { - this->close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall) - } - } - int connect(const struct sockaddr *addr, socklen_t addrlen) override { return ::connect(this->fd_, addr, addrlen); } - std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override { - int fd = ::accept(this->fd_, addr, addrlen); - if (fd == -1) - return {}; - return make_unique<BSDSocketImpl>(fd, false); - } - std::unique_ptr<Socket> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) override { - int fd = ::accept(this->fd_, addr, addrlen); - if (fd == -1) - return {}; - return make_unique<BSDSocketImpl>(fd, true); +BSDSocketImpl::BSDSocketImpl(int fd, bool monitor_loop) { + this->fd_ = fd; + // Register new socket with the application for select() if monitoring requested + if (monitor_loop && this->fd_ >= 0) { + // Only set loop_monitored_ to true if registration succeeds + this->loop_monitored_ = App.register_socket_fd(this->fd_); } +} - int bind(const struct sockaddr *addr, socklen_t addrlen) override { return ::bind(this->fd_, addr, addrlen); } - int close() override { - if (!this->closed_) { - // Unregister from select() before closing if monitored - if (this->loop_monitored_) { - App.unregister_socket_fd(this->fd_); - } - int ret = ::close(this->fd_); - this->closed_ = true; - return ret; +BSDSocketImpl::~BSDSocketImpl() { + if (!this->closed_) { + this->close(); + } +} + +int BSDSocketImpl::close() { + if (!this->closed_) { + // Unregister from select() before closing if monitored + if (this->loop_monitored_) { + App.unregister_socket_fd(this->fd_); } + int ret = ::close(this->fd_); + this->closed_ = true; + return ret; + } + return 0; +} + +int BSDSocketImpl::setblocking(bool blocking) { + int fl = ::fcntl(this->fd_, F_GETFL, 0); + if (blocking) { + fl &= ~O_NONBLOCK; + } else { + fl |= O_NONBLOCK; + } + ::fcntl(this->fd_, F_SETFL, fl); + return 0; +} + +bool BSDSocketImpl::ready() const { return socket_ready_fd(this->fd_, this->loop_monitored_); } + +size_t BSDSocketImpl::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getpeername(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; return 0; } - int shutdown(int how) override { return ::shutdown(this->fd_, how); } + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} - int getpeername(struct sockaddr *addr, socklen_t *addrlen) override { - return ::getpeername(this->fd_, addr, addrlen); - } - int getsockname(struct sockaddr *addr, socklen_t *addrlen) override { - return ::getsockname(this->fd_, addr, addrlen); - } - int getsockopt(int level, int optname, void *optval, socklen_t *optlen) override { - return ::getsockopt(this->fd_, level, optname, optval, optlen); - } - int setsockopt(int level, int optname, const void *optval, socklen_t optlen) override { - return ::setsockopt(this->fd_, level, optname, optval, optlen); - } - int listen(int backlog) override { return ::listen(this->fd_, backlog); } - ssize_t read(void *buf, size_t len) override { -#ifdef USE_ESP32 - return ::lwip_read(this->fd_, buf, len); -#else - return ::read(this->fd_, buf, len); -#endif - } - ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) override { -#if defined(USE_ESP32) || defined(USE_HOST) - return ::recvfrom(this->fd_, buf, len, 0, addr, addr_len); -#else - return ::lwip_recvfrom(this->fd_, buf, len, 0, addr, addr_len); -#endif - } - ssize_t readv(const struct iovec *iov, int iovcnt) override { -#if defined(USE_ESP32) - return ::lwip_readv(this->fd_, iov, iovcnt); -#else - return ::readv(this->fd_, iov, iovcnt); -#endif - } - ssize_t write(const void *buf, size_t len) override { -#ifdef USE_ESP32 - return ::lwip_write(this->fd_, buf, len); -#else - return ::write(this->fd_, buf, len); -#endif - } - ssize_t send(void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); } - ssize_t writev(const struct iovec *iov, int iovcnt) override { -#if defined(USE_ESP32) - return ::lwip_writev(this->fd_, iov, iovcnt); -#else - return ::writev(this->fd_, iov, iovcnt); -#endif - } - - ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override { - return ::sendto(this->fd_, buf, len, flags, to, tolen); // NOLINT(readability-suspicious-call-argument) - } - - int setblocking(bool blocking) override { - int fl = ::fcntl(this->fd_, F_GETFL, 0); - if (blocking) { - fl &= ~O_NONBLOCK; - } else { - fl |= O_NONBLOCK; - } - ::fcntl(this->fd_, F_SETFL, fl); +size_t BSDSocketImpl::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getsockname(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; return 0; } -}; + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} // Helper to create a socket with optional monitoring -static std::unique_ptr<Socket> create_socket(int domain, int type, int protocol, bool loop_monitored = false) { +static std::unique_ptr<BSDSocketImpl> create_socket(int domain, int type, int protocol, bool loop_monitored = false) { int ret = ::socket(domain, type, protocol); if (ret == -1) return nullptr; - return std::unique_ptr<Socket>{new BSDSocketImpl(ret, loop_monitored)}; + return make_unique<BSDSocketImpl>(ret, loop_monitored); } std::unique_ptr<Socket> socket(int domain, int type, int protocol) { @@ -140,6 +86,14 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol return create_socket(domain, type, protocol, true); } +std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { + return create_socket(domain, type, protocol, false); +} + +std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { + return create_socket(domain, type, protocol, true); +} + } // namespace esphome::socket #endif // USE_SOCKET_IMPL_BSD_SOCKETS diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h new file mode 100644 index 0000000000..edee39f315 --- /dev/null +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -0,0 +1,114 @@ +#pragma once +#include "esphome/core/defines.h" + +#ifdef USE_SOCKET_IMPL_BSD_SOCKETS + +#include <memory> +#include <span> + +#include "esphome/core/helpers.h" +#include "headers.h" + +#ifdef USE_ESP32 +#include <lwip/sockets.h> +#endif + +namespace esphome::socket { + +class BSDSocketImpl { + public: + BSDSocketImpl(int fd, bool monitor_loop = false); + ~BSDSocketImpl(); + BSDSocketImpl(const BSDSocketImpl &) = delete; + BSDSocketImpl &operator=(const BSDSocketImpl &) = delete; + + int connect(const struct sockaddr *addr, socklen_t addrlen) { return ::connect(this->fd_, addr, addrlen); } + std::unique_ptr<BSDSocketImpl> accept(struct sockaddr *addr, socklen_t *addrlen) { + int fd = ::accept(this->fd_, addr, addrlen); + if (fd == -1) + return {}; + return make_unique<BSDSocketImpl>(fd, false); + } + std::unique_ptr<BSDSocketImpl> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) { + int fd = ::accept(this->fd_, addr, addrlen); + if (fd == -1) + return {}; + return make_unique<BSDSocketImpl>(fd, true); + } + + int bind(const struct sockaddr *addr, socklen_t addrlen) { return ::bind(this->fd_, addr, addrlen); } + int close(); + int shutdown(int how) { return ::shutdown(this->fd_, how); } + + int getpeername(struct sockaddr *addr, socklen_t *addrlen) { return ::getpeername(this->fd_, addr, addrlen); } + int getsockname(struct sockaddr *addr, socklen_t *addrlen) { return ::getsockname(this->fd_, addr, addrlen); } + + /// Format peer address into a fixed-size buffer (no heap allocation) + size_t getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf); + /// Format local address into a fixed-size buffer (no heap allocation) + size_t getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf); + + int getsockopt(int level, int optname, void *optval, socklen_t *optlen) { + return ::getsockopt(this->fd_, level, optname, optval, optlen); + } + int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { + return ::setsockopt(this->fd_, level, optname, optval, optlen); + } + int listen(int backlog) { return ::listen(this->fd_, backlog); } + ssize_t read(void *buf, size_t len) { +#ifdef USE_ESP32 + return ::lwip_read(this->fd_, buf, len); +#else + return ::read(this->fd_, buf, len); +#endif + } + ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) { +#if defined(USE_ESP32) || defined(USE_HOST) + return ::recvfrom(this->fd_, buf, len, 0, addr, addr_len); +#else + return ::lwip_recvfrom(this->fd_, buf, len, 0, addr, addr_len); +#endif + } + ssize_t readv(const struct iovec *iov, int iovcnt) { +#if defined(USE_ESP32) + return ::lwip_readv(this->fd_, iov, iovcnt); +#else + return ::readv(this->fd_, iov, iovcnt); +#endif + } + ssize_t write(const void *buf, size_t len) { +#ifdef USE_ESP32 + return ::lwip_write(this->fd_, buf, len); +#else + return ::write(this->fd_, buf, len); +#endif + } + ssize_t send(void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); } + ssize_t writev(const struct iovec *iov, int iovcnt) { +#if defined(USE_ESP32) + return ::lwip_writev(this->fd_, iov, iovcnt); +#else + return ::writev(this->fd_, iov, iovcnt); +#endif + } + + ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { + return ::sendto(this->fd_, buf, len, flags, to, tolen); // NOLINT(readability-suspicious-call-argument) + } + + int setblocking(bool blocking); + int loop() { return 0; } + + bool ready() const; + + int get_fd() const { return this->fd_; } + + protected: + int fd_{-1}; + bool closed_{false}; + bool loop_monitored_{false}; +}; + +} // namespace esphome::socket + +#endif // USE_SOCKET_IMPL_BSD_SOCKETS diff --git a/esphome/components/socket/headers.h b/esphome/components/socket/headers.h index 032892072d..16e4d23d3b 100644 --- a/esphome/components/socket/headers.h +++ b/esphome/components/socket/headers.h @@ -183,3 +183,20 @@ using socklen_t = uint32_t; #endif #endif // USE_SOCKET_IMPL_BSD_SOCKETS + +#if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) + +namespace esphome::socket { + +// Maximum length for formatted socket address string (IP address without port) +// IPv4: "255.255.255.255" = 15 chars + null = 16 +// IPv6: full address = 45 chars + null = 46 +#if USE_NETWORK_IPV6 +static constexpr size_t SOCKADDR_STR_LEN = 46; // INET6_ADDRSTRLEN +#else +static constexpr size_t SOCKADDR_STR_LEN = 16; // INET_ADDRSTRLEN +#endif + +} // namespace esphome::socket + +#endif diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 6e95f5bc7a..6556979fe0 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -3,13 +3,8 @@ #ifdef USE_SOCKET_IMPL_LWIP_TCP -#include "lwip/ip.h" -#include "lwip/netif.h" -#include "lwip/opt.h" -#include "lwip/tcp.h" #include <cerrno> #include <cstring> -#include <array> #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -56,628 +51,596 @@ static const char *const TAG = "socket.lwip"; #define LWIP_LOG(msg, ...) #endif -class LWIPRawImpl : public Socket { - public: - LWIPRawImpl(sa_family_t family, struct tcp_pcb *pcb) : pcb_(pcb), family_(family) {} - ~LWIPRawImpl() override { - if (pcb_ != nullptr) { - LWIP_LOG("tcp_abort(%p)", pcb_); - tcp_abort(pcb_); - pcb_ = nullptr; - } - } +// ---- LWIPRawCommon methods ---- - void init() { - LWIP_LOG("init(%p)", pcb_); - tcp_arg(pcb_, this); - tcp_recv(pcb_, LWIPRawImpl::s_recv_fn); - tcp_err(pcb_, LWIPRawImpl::s_err_fn); +LWIPRawCommon::~LWIPRawCommon() { + if (this->pcb_ != nullptr) { + LWIP_LOG("tcp_abort(%p)", this->pcb_); + tcp_abort(this->pcb_); + this->pcb_ = nullptr; } +} - std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override { - // Non-listening sockets return error +int LWIPRawCommon::bind(const struct sockaddr *name, socklen_t addrlen) { + if (this->pcb_ == nullptr) { + errno = EBADF; + return -1; + } + if (name == nullptr) { errno = EINVAL; - return nullptr; + return 0; } - int bind(const struct sockaddr *name, socklen_t addrlen) final { - if (pcb_ == nullptr) { - errno = EBADF; - return -1; - } - if (name == nullptr) { - errno = EINVAL; - return 0; - } - ip_addr_t ip; - in_port_t port; + ip_addr_t ip; + in_port_t port; #if LWIP_IPV6 - if (family_ == AF_INET) { - if (addrlen < sizeof(sockaddr_in)) { - errno = EINVAL; - return -1; - } - auto *addr4 = reinterpret_cast<const sockaddr_in *>(name); - port = ntohs(addr4->sin_port); - ip.type = IPADDR_TYPE_V4; - ip.u_addr.ip4.addr = addr4->sin_addr.s_addr; - LWIP_LOG("tcp_bind(%p ip=%s port=%u)", pcb_, ip4addr_ntoa(&ip.u_addr.ip4), port); - } else if (family_ == AF_INET6) { - if (addrlen < sizeof(sockaddr_in6)) { - errno = EINVAL; - return -1; - } - auto *addr6 = reinterpret_cast<const sockaddr_in6 *>(name); - port = ntohs(addr6->sin6_port); - ip.type = IPADDR_TYPE_ANY; - memcpy(&ip.u_addr.ip6.addr, &addr6->sin6_addr.un.u8_addr, 16); - LWIP_LOG("tcp_bind(%p ip=%s port=%u)", pcb_, ip6addr_ntoa(&ip.u_addr.ip6), port); - } else { - errno = EINVAL; - return -1; - } -#else - if (family_ != AF_INET) { + if (this->family_ == AF_INET) { + if (addrlen < sizeof(sockaddr_in)) { errno = EINVAL; return -1; } auto *addr4 = reinterpret_cast<const sockaddr_in *>(name); port = ntohs(addr4->sin_port); - ip.addr = addr4->sin_addr.s_addr; - LWIP_LOG("tcp_bind(%p ip=%u port=%u)", pcb_, ip.addr, port); + ip.type = IPADDR_TYPE_V4; + ip.u_addr.ip4.addr = addr4->sin_addr.s_addr; + LWIP_LOG("tcp_bind(%p ip=%s port=%u)", this->pcb_, ip4addr_ntoa(&ip.u_addr.ip4), port); + } else if (this->family_ == AF_INET6) { + if (addrlen < sizeof(sockaddr_in6)) { + errno = EINVAL; + return -1; + } + auto *addr6 = reinterpret_cast<const sockaddr_in6 *>(name); + port = ntohs(addr6->sin6_port); + ip.type = IPADDR_TYPE_ANY; + memcpy(&ip.u_addr.ip6.addr, &addr6->sin6_addr.un.u8_addr, 16); + LWIP_LOG("tcp_bind(%p ip=%s port=%u)", this->pcb_, ip6addr_ntoa(&ip.u_addr.ip6), port); + } else { + errno = EINVAL; + return -1; + } +#else + if (this->family_ != AF_INET) { + errno = EINVAL; + return -1; + } + auto *addr4 = reinterpret_cast<const sockaddr_in *>(name); + port = ntohs(addr4->sin_port); + ip.addr = addr4->sin_addr.s_addr; + LWIP_LOG("tcp_bind(%p ip=%u port=%u)", this->pcb_, ip.addr, port); #endif - err_t err = tcp_bind(pcb_, &ip, port); - if (err == ERR_USE) { - LWIP_LOG(" -> err ERR_USE"); - errno = EADDRINUSE; - return -1; - } - if (err == ERR_VAL) { - LWIP_LOG(" -> err ERR_VAL"); + err_t err = tcp_bind(this->pcb_, &ip, port); + if (err == ERR_USE) { + LWIP_LOG(" -> err ERR_USE"); + errno = EADDRINUSE; + return -1; + } + if (err == ERR_VAL) { + LWIP_LOG(" -> err ERR_VAL"); + errno = EINVAL; + return -1; + } + if (err != ERR_OK) { + LWIP_LOG(" -> err %d", err); + errno = EIO; + return -1; + } + return 0; +} + +int LWIPRawCommon::close() { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + LWIP_LOG("tcp_close(%p)", this->pcb_); + err_t err = tcp_close(this->pcb_); + if (err != ERR_OK) { + LWIP_LOG(" -> err %d", err); + tcp_abort(this->pcb_); + this->pcb_ = nullptr; + errno = err == ERR_MEM ? ENOMEM : EIO; + return -1; + } + this->pcb_ = nullptr; + return 0; +} + +int LWIPRawCommon::shutdown(int how) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + bool shut_rx = false, shut_tx = false; + if (how == SHUT_RD) { + shut_rx = true; + } else if (how == SHUT_WR) { + shut_tx = true; + } else if (how == SHUT_RDWR) { + shut_rx = shut_tx = true; + } else { + errno = EINVAL; + return -1; + } + LWIP_LOG("tcp_shutdown(%p shut_rx=%d shut_tx=%d)", this->pcb_, shut_rx ? 1 : 0, shut_tx ? 1 : 0); + err_t err = tcp_shutdown(this->pcb_, shut_rx, shut_tx); + if (err != ERR_OK) { + LWIP_LOG(" -> err %d", err); + errno = err == ERR_MEM ? ENOMEM : EIO; + return -1; + } + return 0; +} + +int LWIPRawCommon::getpeername(struct sockaddr *name, socklen_t *addrlen) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (name == nullptr || addrlen == nullptr) { + errno = EINVAL; + return -1; + } + return this->ip2sockaddr_(&this->pcb_->remote_ip, this->pcb_->remote_port, name, addrlen); +} + +int LWIPRawCommon::getsockname(struct sockaddr *name, socklen_t *addrlen) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (name == nullptr || addrlen == nullptr) { + errno = EINVAL; + return -1; + } + return this->ip2sockaddr_(&this->pcb_->local_ip, this->pcb_->local_port, name, addrlen); +} + +size_t LWIPRawCommon::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getpeername(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; + return 0; + } + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} + +size_t LWIPRawCommon::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getsockname(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; + return 0; + } + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} + +int LWIPRawCommon::getsockopt(int level, int optname, void *optval, socklen_t *optlen) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (optlen == nullptr || optval == nullptr) { + errno = EINVAL; + return -1; + } + if (level == SOL_SOCKET && optname == SO_REUSEADDR) { + if (*optlen < 4) { errno = EINVAL; return -1; } - if (err != ERR_OK) { - LWIP_LOG(" -> err %d", err); - errno = EIO; - return -1; - } + // lwip doesn't seem to have this feature. Don't send an error + // to prevent warnings + *reinterpret_cast<int *>(optval) = 1; + *optlen = 4; return 0; } - int close() final { - if (pcb_ == nullptr) { - errno = ECONNRESET; + if (level == IPPROTO_TCP && optname == TCP_NODELAY) { + if (*optlen < 4) { + errno = EINVAL; return -1; } - LWIP_LOG("tcp_close(%p)", pcb_); - err_t err = tcp_close(pcb_); - if (err != ERR_OK) { - LWIP_LOG(" -> err %d", err); - tcp_abort(pcb_); - pcb_ = nullptr; - errno = err == ERR_MEM ? ENOMEM : EIO; - return -1; - } - pcb_ = nullptr; + *reinterpret_cast<int *>(optval) = this->nodelay_; + *optlen = 4; return 0; } - int shutdown(int how) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; + + errno = EINVAL; + return -1; +} + +int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, socklen_t optlen) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (level == SOL_SOCKET && optname == SO_REUSEADDR) { + if (optlen != 4) { + errno = EINVAL; return -1; } - bool shut_rx = false, shut_tx = false; - if (how == SHUT_RD) { - shut_rx = true; - } else if (how == SHUT_WR) { - shut_tx = true; - } else if (how == SHUT_RDWR) { - shut_rx = shut_tx = true; + // lwip doesn't seem to have this feature. Don't send an error + // to prevent warnings + return 0; + } + if (level == IPPROTO_TCP && optname == TCP_NODELAY) { + if (optlen != 4) { + errno = EINVAL; + return -1; + } + int val = *reinterpret_cast<const int *>(optval); + this->nodelay_ = val; + return 0; + } + + errno = EINVAL; + return -1; +} + +int LWIPRawCommon::ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen) { + if (this->family_ == AF_INET) { + if (*addrlen < sizeof(struct sockaddr_in)) { + errno = EINVAL; + return -1; + } + + struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(name); + addr->sin_family = AF_INET; + *addrlen = addr->sin_len = sizeof(struct sockaddr_in); + addr->sin_port = port; + inet_addr_from_ip4addr(&addr->sin_addr, ip_2_ip4(ip)); + return 0; + } +#if LWIP_IPV6 + else if (this->family_ == AF_INET6) { + if (*addrlen < sizeof(struct sockaddr_in6)) { + errno = EINVAL; + return -1; + } + + struct sockaddr_in6 *addr = reinterpret_cast<struct sockaddr_in6 *>(name); + addr->sin6_family = AF_INET6; + *addrlen = addr->sin6_len = sizeof(struct sockaddr_in6); + addr->sin6_port = port; + + // AF_INET6 sockets are bound to IPv4 as well, so we may encounter IPv4 addresses that must be converted to IPv6. + if (IP_IS_V4(ip)) { + ip_addr_t mapped; + ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&mapped), ip_2_ip4(ip)); + inet6_addr_from_ip6addr(&addr->sin6_addr, ip_2_ip6(&mapped)); } else { - errno = EINVAL; - return -1; - } - LWIP_LOG("tcp_shutdown(%p shut_rx=%d shut_tx=%d)", pcb_, shut_rx ? 1 : 0, shut_tx ? 1 : 0); - err_t err = tcp_shutdown(pcb_, shut_rx, shut_tx); - if (err != ERR_OK) { - LWIP_LOG(" -> err %d", err); - errno = err == ERR_MEM ? ENOMEM : EIO; - return -1; + inet6_addr_from_ip6addr(&addr->sin6_addr, ip_2_ip6(ip)); } return 0; } +#endif + return -1; +} - int getpeername(struct sockaddr *name, socklen_t *addrlen) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (name == nullptr || addrlen == nullptr) { - errno = EINVAL; - return -1; - } - return this->ip2sockaddr_(&pcb_->remote_ip, pcb_->remote_port, name, addrlen); +// ---- LWIPRawImpl methods ---- + +LWIPRawImpl::~LWIPRawImpl() { + // Base class destructor handles pcb_ cleanup via tcp_abort +} + +void LWIPRawImpl::init() { + LWIP_LOG("init(%p)", this->pcb_); + tcp_arg(this->pcb_, this); + tcp_recv(this->pcb_, LWIPRawImpl::s_recv_fn); + tcp_err(this->pcb_, LWIPRawImpl::s_err_fn); +} + +void LWIPRawImpl::s_err_fn(void *arg, err_t err) { + // "If a connection is aborted because of an error, the application is alerted of this event by + // the err callback." + // pcb is already freed when this callback is called + // ERR_RST: connection was reset by remote host + // ERR_ABRT: aborted through tcp_abort or TCP timer + auto *arg_this = reinterpret_cast<LWIPRawImpl *>(arg); + ESP_LOGVV(TAG, "socket %p: err(err=%d)", arg_this, err); + arg_this->pcb_ = nullptr; +} + +err_t LWIPRawImpl::s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err) { + auto *arg_this = reinterpret_cast<LWIPRawImpl *>(arg); + return arg_this->recv_fn(pb, err); +} + +err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { + LWIP_LOG("recv(pb=%p err=%d)", pb, err); + if (err != 0) { + // "An error code if there has been an error receiving Only return ERR_ABRT if you have + // called tcp_abort from within the callback function!" + this->rx_closed_ = true; + return ERR_OK; } - int getsockname(struct sockaddr *name, socklen_t *addrlen) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (name == nullptr || addrlen == nullptr) { - errno = EINVAL; - return -1; - } - return this->ip2sockaddr_(&pcb_->local_ip, pcb_->local_port, name, addrlen); + if (pb == nullptr) { + this->rx_closed_ = true; + return ERR_OK; } - int getsockopt(int level, int optname, void *optval, socklen_t *optlen) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (optlen == nullptr || optval == nullptr) { - errno = EINVAL; - return -1; - } - if (level == SOL_SOCKET && optname == SO_REUSEADDR) { - if (*optlen < 4) { - errno = EINVAL; - return -1; - } + if (this->rx_buf_ == nullptr) { + // no need to copy because lwIP gave control of it to us + this->rx_buf_ = pb; + this->rx_buf_offset_ = 0; + } else { + pbuf_cat(this->rx_buf_, pb); + } +#ifdef USE_ESP8266 + // Wake the main loop immediately so it can process the received data. + socket_wake(); +#endif + return ERR_OK; +} - // lwip doesn't seem to have this feature. Don't send an error - // to prevent warnings - *reinterpret_cast<int *>(optval) = 1; - *optlen = 4; - return 0; - } - if (level == IPPROTO_TCP && optname == TCP_NODELAY) { - if (*optlen < 4) { - errno = EINVAL; - return -1; - } - *reinterpret_cast<int *>(optval) = nodelay_; - *optlen = 4; - return 0; - } - - errno = EINVAL; +ssize_t LWIPRawImpl::read(void *buf, size_t len) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; return -1; } - int setsockopt(int level, int optname, const void *optval, socklen_t optlen) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (level == SOL_SOCKET && optname == SO_REUSEADDR) { - if (optlen != 4) { - errno = EINVAL; - return -1; - } - - // lwip doesn't seem to have this feature. Don't send an error - // to prevent warnings - return 0; - } - if (level == IPPROTO_TCP && optname == TCP_NODELAY) { - if (optlen != 4) { - errno = EINVAL; - return -1; - } - int val = *reinterpret_cast<const int *>(optval); - nodelay_ = val; - return 0; - } - - errno = EINVAL; + if (this->rx_closed_ && this->rx_buf_ == nullptr) { + return 0; + } + if (len == 0) { + return 0; + } + if (this->rx_buf_ == nullptr) { + errno = EWOULDBLOCK; return -1; } - int listen(int backlog) override { - // Regular sockets can't be converted to listening - this shouldn't happen - // as listen() should only be called on sockets created for listening + + size_t read = 0; + uint8_t *buf8 = reinterpret_cast<uint8_t *>(buf); + while (len && this->rx_buf_ != nullptr) { + size_t pb_len = this->rx_buf_->len; + size_t pb_left = pb_len - this->rx_buf_offset_; + if (pb_left == 0) + break; + size_t copysize = std::min(len, pb_left); + memcpy(buf8, reinterpret_cast<uint8_t *>(this->rx_buf_->payload) + this->rx_buf_offset_, copysize); + + if (pb_left == copysize) { + // full pb copied, free it + if (this->rx_buf_->next == nullptr) { + // last buffer in chain + pbuf_free(this->rx_buf_); + this->rx_buf_ = nullptr; + this->rx_buf_offset_ = 0; + } else { + auto *old_buf = this->rx_buf_; + this->rx_buf_ = this->rx_buf_->next; + pbuf_ref(this->rx_buf_); + pbuf_free(old_buf); + this->rx_buf_offset_ = 0; + } + } else { + this->rx_buf_offset_ += copysize; + } + LWIP_LOG("tcp_recved(%p %u)", this->pcb_, copysize); + tcp_recved(this->pcb_, copysize); + + buf8 += copysize; + len -= copysize; + read += copysize; + } + + if (read == 0) { + errno = EWOULDBLOCK; + return -1; + } + + return read; +} + +ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { + ssize_t ret = 0; + for (int i = 0; i < iovcnt; i++) { + ssize_t err = this->read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); + if (err == -1) { + if (ret != 0) { + // if we already read some don't return an error + break; + } + return err; + } + ret += err; + if ((size_t) err != iov[i].iov_len) + break; + } + return ret; +} + +ssize_t LWIPRawImpl::internal_write_(const void *buf, size_t len) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (len == 0) + return 0; + if (buf == nullptr) { + errno = EINVAL; + return 0; + } + auto space = tcp_sndbuf(this->pcb_); + if (space == 0) { + errno = EWOULDBLOCK; + return -1; + } + size_t to_send = std::min((size_t) space, len); + LWIP_LOG("tcp_write(%p buf=%p %u)", this->pcb_, buf, to_send); + err_t err = tcp_write(this->pcb_, buf, to_send, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + LWIP_LOG(" -> err ERR_MEM"); + errno = EWOULDBLOCK; + return -1; + } + if (err != ERR_OK) { + LWIP_LOG(" -> err %d", err); + errno = ECONNRESET; + return -1; + } + return to_send; +} + +int LWIPRawImpl::internal_output_() { + LWIP_LOG("tcp_output(%p)", this->pcb_); + err_t err = tcp_output(this->pcb_); + if (err == ERR_ABRT) { + // sometimes lwip returns ERR_ABRT for no apparent reason + // the connection works fine afterwards, and back with ESPAsyncTCP we + // indirectly also ignored this error + // FIXME: figure out where this is returned and what it means in this context + LWIP_LOG(" -> err ERR_ABRT"); + return 0; + } + if (err != ERR_OK) { + LWIP_LOG(" -> err %d", err); + errno = ECONNRESET; + return -1; + } + return 0; +} + +ssize_t LWIPRawImpl::write(const void *buf, size_t len) { + ssize_t written = this->internal_write_(buf, len); + if (written == -1) + return -1; + if (written == 0) { + // no need to output if nothing written + return 0; + } + if (this->nodelay_) { + int err = this->internal_output_(); + if (err == -1) + return -1; + } + return written; +} + +ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { + ssize_t written = 0; + for (int i = 0; i < iovcnt; i++) { + ssize_t err = this->internal_write_(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); + if (err == -1) { + if (written != 0) { + // if we already read some don't return an error + break; + } + return err; + } + written += err; + if ((size_t) err != iov[i].iov_len) + break; + } + if (written == 0) { + // no need to output if nothing written + return 0; + } + if (this->nodelay_) { + int err = this->internal_output_(); + if (err == -1) + return -1; + } + return written; +} + +// ---- LWIPRawListenImpl methods ---- + +LWIPRawListenImpl::~LWIPRawListenImpl() { + // Base class destructor handles pcb_ cleanup via tcp_abort +} + +void LWIPRawListenImpl::init() { + LWIP_LOG("init(%p)", this->pcb_); + tcp_arg(this->pcb_, this); + tcp_accept(this->pcb_, LWIPRawListenImpl::s_accept_fn); + tcp_err(this->pcb_, LWIPRawListenImpl::s_err_fn); +} + +void LWIPRawListenImpl::s_err_fn(void *arg, err_t err) { + auto *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); + ESP_LOGVV(TAG, "socket %p: err(err=%d)", arg_this, err); + arg_this->pcb_ = nullptr; +} + +err_t LWIPRawListenImpl::s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t err) { + auto *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); + return arg_this->accept_fn_(newpcb, err); +} + +std::unique_ptr<LWIPRawImpl> LWIPRawListenImpl::accept(struct sockaddr *addr, socklen_t *addrlen) { + if (this->pcb_ == nullptr) { + errno = EBADF; + return nullptr; + } + if (this->accepted_socket_count_ == 0) { + errno = EWOULDBLOCK; + return nullptr; + } + // Take from front for FIFO ordering + std::unique_ptr<LWIPRawImpl> sock = std::move(this->accepted_sockets_[0]); + // Shift remaining sockets forward + for (uint8_t i = 1; i < this->accepted_socket_count_; i++) { + this->accepted_sockets_[i - 1] = std::move(this->accepted_sockets_[i]); + } + this->accepted_socket_count_--; + LWIP_LOG("Connection accepted by application, queue size: %d", this->accepted_socket_count_); + if (addr != nullptr) { + sock->getpeername(addr, addrlen); + } + LWIP_LOG("accept(%p)", sock.get()); + return sock; +} + +int LWIPRawListenImpl::listen(int backlog) { + if (this->pcb_ == nullptr) { + errno = EBADF; + return -1; + } + LWIP_LOG("tcp_listen_with_backlog(%p backlog=%d)", this->pcb_, backlog); + struct tcp_pcb *listen_pcb = tcp_listen_with_backlog(this->pcb_, backlog); + if (listen_pcb == nullptr) { + tcp_abort(this->pcb_); + this->pcb_ = nullptr; errno = EOPNOTSUPP; return -1; } - ssize_t read(void *buf, size_t len) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (rx_closed_ && rx_buf_ == nullptr) { - return 0; - } - if (len == 0) { - return 0; - } - if (rx_buf_ == nullptr) { - errno = EWOULDBLOCK; - return -1; - } + // tcp_listen reallocates the pcb, replace ours + this->pcb_ = listen_pcb; + // set callbacks on new pcb + LWIP_LOG("tcp_arg(%p)", this->pcb_); + tcp_arg(this->pcb_, this); + tcp_accept(this->pcb_, LWIPRawListenImpl::s_accept_fn); + return 0; +} - size_t read = 0; - uint8_t *buf8 = reinterpret_cast<uint8_t *>(buf); - while (len && rx_buf_ != nullptr) { - size_t pb_len = rx_buf_->len; - size_t pb_left = pb_len - rx_buf_offset_; - if (pb_left == 0) - break; - size_t copysize = std::min(len, pb_left); - memcpy(buf8, reinterpret_cast<uint8_t *>(rx_buf_->payload) + rx_buf_offset_, copysize); - - if (pb_left == copysize) { - // full pb copied, free it - if (rx_buf_->next == nullptr) { - // last buffer in chain - pbuf_free(rx_buf_); - rx_buf_ = nullptr; - rx_buf_offset_ = 0; - } else { - auto *old_buf = rx_buf_; - rx_buf_ = rx_buf_->next; - pbuf_ref(rx_buf_); - pbuf_free(old_buf); - rx_buf_offset_ = 0; - } - } else { - rx_buf_offset_ += copysize; - } - LWIP_LOG("tcp_recved(%p %u)", pcb_, copysize); - tcp_recved(pcb_, copysize); - - buf8 += copysize; - len -= copysize; - read += copysize; - } - - if (read == 0) { - errno = EWOULDBLOCK; - return -1; - } - - return read; - } - ssize_t readv(const struct iovec *iov, int iovcnt) final { - ssize_t ret = 0; - for (int i = 0; i < iovcnt; i++) { - ssize_t err = read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); - if (err == -1) { - if (ret != 0) { - // if we already read some don't return an error - break; - } - return err; - } - ret += err; - if ((size_t) err != iov[i].iov_len) - break; - } - return ret; - } - - ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) final { - errno = ENOTSUP; - return -1; - } - - ssize_t internal_write(const void *buf, size_t len) { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (len == 0) - return 0; - if (buf == nullptr) { - errno = EINVAL; - return 0; - } - auto space = tcp_sndbuf(pcb_); - if (space == 0) { - errno = EWOULDBLOCK; - return -1; - } - size_t to_send = std::min((size_t) space, len); - LWIP_LOG("tcp_write(%p buf=%p %u)", pcb_, buf, to_send); - err_t err = tcp_write(pcb_, buf, to_send, TCP_WRITE_FLAG_COPY); - if (err == ERR_MEM) { - LWIP_LOG(" -> err ERR_MEM"); - errno = EWOULDBLOCK; - return -1; - } - if (err != ERR_OK) { - LWIP_LOG(" -> err %d", err); - errno = ECONNRESET; - return -1; - } - return to_send; - } - int internal_output() { - LWIP_LOG("tcp_output(%p)", pcb_); - err_t err = tcp_output(pcb_); - if (err == ERR_ABRT) { - LWIP_LOG(" -> err ERR_ABRT"); - // sometimes lwip returns ERR_ABRT for no apparent reason - // the connection works fine afterwards, and back with ESPAsyncTCP we - // indirectly also ignored this error - // FIXME: figure out where this is returned and what it means in this context - return 0; - } - if (err != ERR_OK) { - LWIP_LOG(" -> err %d", err); - errno = ECONNRESET; - return -1; - } - return 0; - } - ssize_t write(const void *buf, size_t len) final { - ssize_t written = internal_write(buf, len); - if (written == -1) - return -1; - if (written == 0) { - // no need to output if nothing written - return 0; - } - if (nodelay_) { - int err = internal_output(); - if (err == -1) - return -1; - } - return written; - } - ssize_t writev(const struct iovec *iov, int iovcnt) final { - ssize_t written = 0; - for (int i = 0; i < iovcnt; i++) { - ssize_t err = internal_write(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); - if (err == -1) { - if (written != 0) { - // if we already read some don't return an error - break; - } - return err; - } - written += err; - if ((size_t) err != iov[i].iov_len) - break; - } - if (written == 0) { - // no need to output if nothing written - return 0; - } - if (nodelay_) { - int err = internal_output(); - if (err == -1) - return -1; - } - return written; - } - ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) final { - // return ::sendto(fd_, buf, len, flags, to, tolen); - errno = ENOSYS; - return -1; - } - bool ready() const override { return this->rx_buf_ != nullptr || this->rx_closed_ || this->pcb_ == nullptr; } - - int setblocking(bool blocking) final { - if (pcb_ == nullptr) { - errno = ECONNRESET; - return -1; - } - if (blocking) { - // blocking operation not supported - errno = EINVAL; - return -1; - } - return 0; - } - - void err_fn(err_t err) { - LWIP_LOG("err(err=%d)", err); - // "If a connection is aborted because of an error, the application is alerted of this event by - // the err callback." - // pcb is already freed when this callback is called - // ERR_RST: connection was reset by remote host - // ERR_ABRT: aborted through tcp_abort or TCP timer - pcb_ = nullptr; - } - err_t recv_fn(struct pbuf *pb, err_t err) { - LWIP_LOG("recv(pb=%p err=%d)", pb, err); - if (err != 0) { - // "An error code if there has been an error receiving Only return ERR_ABRT if you have - // called tcp_abort from within the callback function!" - rx_closed_ = true; - return ERR_OK; - } - if (pb == nullptr) { - rx_closed_ = true; - return ERR_OK; - } - if (rx_buf_ == nullptr) { - // no need to copy because lwIP gave control of it to us - rx_buf_ = pb; - rx_buf_offset_ = 0; - } else { - pbuf_cat(rx_buf_, pb); - } -#ifdef USE_ESP8266 - // Wake the main loop immediately so it can process the received data. - socket_wake(); -#endif +err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { + LWIP_LOG("accept(newpcb=%p err=%d)", newpcb, err); + if (err != ERR_OK || newpcb == nullptr) { + // "An error code if there has been an error accepting. Only return ERR_ABRT if you have + // called tcp_abort from within the callback function!" + // https://www.nongnu.org/lwip/2_1_x/tcp_8h.html#a00517abce6856d6c82f0efebdafb734d + // nothing to do here, we just don't push it to the queue return ERR_OK; } - - static void s_err_fn(void *arg, err_t err) { - LWIPRawImpl *arg_this = reinterpret_cast<LWIPRawImpl *>(arg); - arg_this->err_fn(err); + // Check if we've reached the maximum accept queue size + if (this->accepted_socket_count_ >= MAX_ACCEPTED_SOCKETS) { + LWIP_LOG("Rejecting connection, queue full (%d)", this->accepted_socket_count_); + // Abort the connection when queue is full + tcp_abort(newpcb); + // Must return ERR_ABRT since we called tcp_abort() + return ERR_ABRT; } - - static err_t s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err) { - LWIPRawImpl *arg_this = reinterpret_cast<LWIPRawImpl *>(arg); - return arg_this->recv_fn(pb, err); - } - - protected: - int ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen) { - if (family_ == AF_INET) { - if (*addrlen < sizeof(struct sockaddr_in)) { - errno = EINVAL; - return -1; - } - - struct sockaddr_in *addr = reinterpret_cast<struct sockaddr_in *>(name); - addr->sin_family = AF_INET; - *addrlen = addr->sin_len = sizeof(struct sockaddr_in); - addr->sin_port = port; - inet_addr_from_ip4addr(&addr->sin_addr, ip_2_ip4(ip)); - return 0; - } -#if LWIP_IPV6 - else if (family_ == AF_INET6) { - if (*addrlen < sizeof(struct sockaddr_in6)) { - errno = EINVAL; - return -1; - } - - struct sockaddr_in6 *addr = reinterpret_cast<struct sockaddr_in6 *>(name); - addr->sin6_family = AF_INET6; - *addrlen = addr->sin6_len = sizeof(struct sockaddr_in6); - addr->sin6_port = port; - - // AF_INET6 sockets are bound to IPv4 as well, so we may encounter IPv4 addresses that must be converted to IPv6. - if (IP_IS_V4(ip)) { - ip_addr_t mapped; - ip4_2_ipv4_mapped_ipv6(ip_2_ip6(&mapped), ip_2_ip4(ip)); - inet6_addr_from_ip6addr(&addr->sin6_addr, ip_2_ip6(&mapped)); - } else { - inet6_addr_from_ip6addr(&addr->sin6_addr, ip_2_ip6(ip)); - } - return 0; - } -#endif - return -1; - } - - // Member ordering optimized to minimize padding on 32-bit systems - // Largest members first (4 bytes), then smaller members (1 byte each) - struct tcp_pcb *pcb_; - pbuf *rx_buf_ = nullptr; - size_t rx_buf_offset_ = 0; - bool rx_closed_ = false; - // don't use lwip nodelay flag, it sometimes causes reconnect - // instead use it for determining whether to call lwip_output - bool nodelay_ = false; - sa_family_t family_ = 0; -}; - -// Listening socket class - only allocates accept queue when needed (for bind+listen sockets) -// This saves 16 bytes (12 bytes array + 1 byte count + 3 bytes padding) for regular connected sockets on ESP8266/RP2040 -class LWIPRawListenImpl final : public LWIPRawImpl { - public: - LWIPRawListenImpl(sa_family_t family, struct tcp_pcb *pcb) : LWIPRawImpl(family, pcb) {} - - void init() { - LWIP_LOG("init(%p)", pcb_); - tcp_arg(pcb_, this); - tcp_accept(pcb_, LWIPRawListenImpl::s_accept_fn); - tcp_err(pcb_, LWIPRawImpl::s_err_fn); // Use base class error handler - } - - bool ready() const override { return this->accepted_socket_count_ > 0; } - - std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override { - if (pcb_ == nullptr) { - errno = EBADF; - return nullptr; - } - if (accepted_socket_count_ == 0) { - errno = EWOULDBLOCK; - return nullptr; - } - // Take from front for FIFO ordering - std::unique_ptr<LWIPRawImpl> sock = std::move(accepted_sockets_[0]); - // Shift remaining sockets forward - for (uint8_t i = 1; i < accepted_socket_count_; i++) { - accepted_sockets_[i - 1] = std::move(accepted_sockets_[i]); - } - accepted_socket_count_--; - LWIP_LOG("Connection accepted by application, queue size: %d", accepted_socket_count_); - if (addr != nullptr) { - sock->getpeername(addr, addrlen); - } - LWIP_LOG("accept(%p)", sock.get()); - return std::unique_ptr<Socket>(std::move(sock)); - } - - int listen(int backlog) override { - if (pcb_ == nullptr) { - errno = EBADF; - return -1; - } - LWIP_LOG("tcp_listen_with_backlog(%p backlog=%d)", pcb_, backlog); - struct tcp_pcb *listen_pcb = tcp_listen_with_backlog(pcb_, backlog); - if (listen_pcb == nullptr) { - tcp_abort(pcb_); - pcb_ = nullptr; - errno = EOPNOTSUPP; - return -1; - } - // tcp_listen reallocates the pcb, replace ours - pcb_ = listen_pcb; - // set callbacks on new pcb - LWIP_LOG("tcp_arg(%p)", pcb_); - tcp_arg(pcb_, this); - tcp_accept(pcb_, LWIPRawListenImpl::s_accept_fn); - return 0; - } - - private: - err_t accept_fn_(struct tcp_pcb *newpcb, err_t err) { - LWIP_LOG("accept(newpcb=%p err=%d)", newpcb, err); - if (err != ERR_OK || newpcb == nullptr) { - // "An error code if there has been an error accepting. Only return ERR_ABRT if you have - // called tcp_abort from within the callback function!" - // https://www.nongnu.org/lwip/2_1_x/tcp_8h.html#a00517abce6856d6c82f0efebdafb734d - // nothing to do here, we just don't push it to the queue - return ERR_OK; - } - // Check if we've reached the maximum accept queue size - if (accepted_socket_count_ >= MAX_ACCEPTED_SOCKETS) { - LWIP_LOG("Rejecting connection, queue full (%d)", accepted_socket_count_); - // Abort the connection when queue is full - tcp_abort(newpcb); - // Must return ERR_ABRT since we called tcp_abort() - return ERR_ABRT; - } - auto sock = make_unique<LWIPRawImpl>(family_, newpcb); - sock->init(); - accepted_sockets_[accepted_socket_count_++] = std::move(sock); - LWIP_LOG("Accepted connection, queue size: %d", accepted_socket_count_); + auto sock = make_unique<LWIPRawImpl>(this->family_, newpcb); + sock->init(); + this->accepted_sockets_[this->accepted_socket_count_++] = std::move(sock); + LWIP_LOG("Accepted connection, queue size: %d", this->accepted_socket_count_); #ifdef USE_ESP8266 - // Wake the main loop immediately so it can accept the new connection. - socket_wake(); + // Wake the main loop immediately so it can accept the new connection. + socket_wake(); #endif - return ERR_OK; - } + return ERR_OK; +} - static err_t s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t err) { - LWIPRawListenImpl *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); - return arg_this->accept_fn_(newpcb, err); - } - - // Accept queue - holds incoming connections briefly until the event loop calls accept() - // This is NOT a connection pool - just a temporary queue between LWIP callbacks and the main loop - // 3 slots is plenty since connections are pulled out quickly by the event loop - // - // Memory analysis: std::array<3> vs original std::queue implementation: - // - std::queue uses std::deque internally which on 32-bit systems needs: - // 24 bytes (deque object) + 32+ bytes (map array) + heap allocations - // Total: ~56+ bytes minimum, plus heap fragmentation - // - std::array<3>: 12 bytes fixed (3 pointers × 4 bytes) - // Saves ~44+ bytes RAM per listening socket + avoids ALL heap allocations - // Used on ESP8266 and RP2040 (platforms using LWIP_TCP implementation) - // - // By using a separate listening socket class, regular connected sockets save - // 16 bytes (12 bytes array + 1 byte count + 3 bytes padding) of memory overhead on 32-bit systems - static constexpr size_t MAX_ACCEPTED_SOCKETS = 3; - std::array<std::unique_ptr<LWIPRawImpl>, MAX_ACCEPTED_SOCKETS> accepted_sockets_; - uint8_t accepted_socket_count_ = 0; // Number of sockets currently in queue -}; +// ---- Factory functions ---- std::unique_ptr<Socket> socket(int domain, int type, int protocol) { if (type != SOCK_STREAM) { @@ -688,9 +651,7 @@ std::unique_ptr<Socket> socket(int domain, int type, int protocol) { auto *pcb = tcp_new(); if (pcb == nullptr) return nullptr; - // Create listening socket implementation since user sockets typically bind+listen - // Accepted connections are created directly as LWIPRawImpl in the accept callback - auto *sock = new LWIPRawListenImpl((sa_family_t) domain, pcb); // NOLINT(cppcoreguidelines-owning-memory) + auto *sock = new LWIPRawImpl((sa_family_t) domain, pcb); // NOLINT(cppcoreguidelines-owning-memory) sock->init(); return std::unique_ptr<Socket>{sock}; } @@ -700,6 +661,25 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol return socket(domain, type, protocol); } +std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { + if (type != SOCK_STREAM) { + ESP_LOGE(TAG, "UDP sockets not supported on this platform, use WiFiUDP"); + errno = EPROTOTYPE; + return nullptr; + } + auto *pcb = tcp_new(); + if (pcb == nullptr) + return nullptr; + auto *sock = new LWIPRawListenImpl((sa_family_t) domain, pcb); // NOLINT(cppcoreguidelines-owning-memory) + sock->init(); + return std::unique_ptr<ListenSocket>{sock}; +} + +std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { + // LWIPRawImpl doesn't use file descriptors, so monitoring is not applicable + return socket_listen(domain, type, protocol); +} + } // namespace esphome::socket #endif // USE_SOCKET_IMPL_LWIP_TCP diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h new file mode 100644 index 0000000000..c171e0537f --- /dev/null +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -0,0 +1,200 @@ +#pragma once +#include "esphome/core/defines.h" + +#ifdef USE_SOCKET_IMPL_LWIP_TCP + +#include <array> +#include <cerrno> +#include <cstring> +#include <memory> +#include <span> + +#include "esphome/core/helpers.h" +#include "headers.h" +#include "lwip/ip.h" +#include "lwip/netif.h" +#include "lwip/opt.h" +#include "lwip/tcp.h" + +namespace esphome::socket { + +// Forward declaration +class LWIPRawImpl; + +/// Non-virtual common base for LWIP raw TCP sockets. +/// Provides shared fields and methods for both connected and listening sockets. +/// No virtual methods — pure code sharing. +class LWIPRawCommon { + public: + LWIPRawCommon(sa_family_t family, struct tcp_pcb *pcb) : pcb_(pcb), family_(family) {} + ~LWIPRawCommon(); + LWIPRawCommon(const LWIPRawCommon &) = delete; + LWIPRawCommon &operator=(const LWIPRawCommon &) = delete; + + int bind(const struct sockaddr *name, socklen_t addrlen); + int close(); + int shutdown(int how); + + int getpeername(struct sockaddr *name, socklen_t *addrlen); + int getsockname(struct sockaddr *name, socklen_t *addrlen); + + /// Format peer address into a fixed-size buffer (no heap allocation) + size_t getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf); + /// Format local address into a fixed-size buffer (no heap allocation) + size_t getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf); + + int getsockopt(int level, int optname, void *optval, socklen_t *optlen); + int setsockopt(int level, int optname, const void *optval, socklen_t optlen); + + int get_fd() const { return -1; } + + protected: + int ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *name, socklen_t *addrlen); + + // Member ordering optimized to minimize padding on 32-bit systems + struct tcp_pcb *pcb_; + // don't use lwip nodelay flag, it sometimes causes reconnect + // instead use it for determining whether to call lwip_output + bool nodelay_ = false; + sa_family_t family_ = 0; +}; + +/// Connected socket implementation for LWIP raw TCP. +/// No virtual methods — callers always use the concrete type. +class LWIPRawImpl : public LWIPRawCommon { + public: + using LWIPRawCommon::LWIPRawCommon; + ~LWIPRawImpl(); + + void init(); + + // Non-listening sockets return error + std::unique_ptr<LWIPRawImpl> accept(struct sockaddr *, socklen_t *) { + errno = EINVAL; + return nullptr; + } + std::unique_ptr<LWIPRawImpl> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) { + return this->accept(addr, addrlen); + } + // Regular sockets can't be converted to listening - this shouldn't happen + // as listen() should only be called on sockets created for listening + int listen(int) { + errno = EOPNOTSUPP; + return -1; + } + ssize_t read(void *buf, size_t len); + ssize_t readv(const struct iovec *iov, int iovcnt); + ssize_t recvfrom(void *, size_t, sockaddr *, socklen_t *) { + errno = ENOTSUP; + return -1; + } + ssize_t write(const void *buf, size_t len); + ssize_t writev(const struct iovec *iov, int iovcnt); + ssize_t sendto(const void *, size_t, int, const struct sockaddr *, socklen_t) { + // return ::sendto(fd_, buf, len, flags, to, tolen); + errno = ENOSYS; + return -1; + } + bool ready() const { return this->rx_buf_ != nullptr || this->rx_closed_ || this->pcb_ == nullptr; } + + int setblocking(bool blocking) { + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } + if (blocking) { + // blocking operation not supported + errno = EINVAL; + return -1; + } + return 0; + } + int loop() { return 0; } + + err_t recv_fn(struct pbuf *pb, err_t err); + + static void s_err_fn(void *arg, err_t err); + static err_t s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err); + + protected: + ssize_t internal_write_(const void *buf, size_t len); + int internal_output_(); + + pbuf *rx_buf_ = nullptr; + size_t rx_buf_offset_ = 0; + bool rx_closed_ = false; +}; + +/// Listening socket implementation for LWIP raw TCP. +/// Separate from LWIPRawImpl — no virtual dispatch needed. +class LWIPRawListenImpl : public LWIPRawCommon { + public: + using LWIPRawCommon::LWIPRawCommon; + ~LWIPRawListenImpl(); + + void init(); + + bool ready() const { return this->accepted_socket_count_ > 0; } + + std::unique_ptr<LWIPRawImpl> accept(struct sockaddr *addr, socklen_t *addrlen); + std::unique_ptr<LWIPRawImpl> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) { + return this->accept(addr, addrlen); + } + int listen(int backlog); + + // Listening sockets don't do I/O + ssize_t read(void *, size_t) { + errno = ENOTSUP; + return -1; + } + ssize_t write(const void *, size_t) { + errno = ENOTSUP; + return -1; + } + ssize_t readv(const struct iovec *, int) { + errno = ENOTSUP; + return -1; + } + ssize_t writev(const struct iovec *, int) { + errno = ENOTSUP; + return -1; + } + ssize_t recvfrom(void *, size_t, sockaddr *, socklen_t *) { + errno = ENOTSUP; + return -1; + } + ssize_t sendto(const void *, size_t, int, const struct sockaddr *, socklen_t) { + errno = ENOTSUP; + return -1; + } + int setblocking(bool) { return 0; } + int loop() { return 0; } + + static void s_err_fn(void *arg, err_t err); + + private: + err_t accept_fn_(struct tcp_pcb *newpcb, err_t err); + static err_t s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t err); + + // Accept queue - holds incoming connections briefly until the event loop calls accept() + // This is NOT a connection pool - just a temporary queue between LWIP callbacks and the main loop + // 3 slots is plenty since connections are pulled out quickly by the event loop + // + // Memory analysis: std::array<3> vs original std::queue implementation: + // - std::queue uses std::deque internally which on 32-bit systems needs: + // 24 bytes (deque object) + 32+ bytes (map array) + heap allocations + // Total: ~56+ bytes minimum, plus heap fragmentation + // - std::array<3>: 12 bytes fixed (3 pointers × 4 bytes) + // Saves ~44+ bytes RAM per listening socket + avoids ALL heap allocations + // Used on ESP8266 and RP2040 (platforms using LWIP_TCP implementation) + // + // By using a separate listening socket class, regular connected sockets save + // 16 bytes (12 bytes array + 1 byte count + 3 bytes padding) of memory overhead on 32-bit systems + static constexpr size_t MAX_ACCEPTED_SOCKETS = 3; + std::array<std::unique_ptr<LWIPRawImpl>, MAX_ACCEPTED_SOCKETS> accepted_sockets_; + uint8_t accepted_socket_count_ = 0; // Number of sockets currently in queue +}; + +} // namespace esphome::socket + +#endif // USE_SOCKET_IMPL_LWIP_TCP diff --git a/esphome/components/socket/lwip_sockets_impl.cpp b/esphome/components/socket/lwip_sockets_impl.cpp index 79d68e085a..0322820ef4 100644 --- a/esphome/components/socket/lwip_sockets_impl.cpp +++ b/esphome/components/socket/lwip_sockets_impl.cpp @@ -1,6 +1,6 @@ -#include "socket.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" +#include "socket.h" #ifdef USE_SOCKET_IMPL_LWIP_SOCKETS @@ -9,94 +9,73 @@ namespace esphome::socket { -class LwIPSocketImpl final : public Socket { - public: - LwIPSocketImpl(int fd, bool monitor_loop = false) { - this->fd_ = fd; - // Register new socket with the application for select() if monitoring requested - if (monitor_loop && this->fd_ >= 0) { - // Only set loop_monitored_ to true if registration succeeds - this->loop_monitored_ = App.register_socket_fd(this->fd_); - } - } - ~LwIPSocketImpl() override { - if (!this->closed_) { - this->close(); // NOLINT(clang-analyzer-optin.cplusplus.VirtualCall) - } - } - int connect(const struct sockaddr *addr, socklen_t addrlen) override { - return lwip_connect(this->fd_, addr, addrlen); - } - std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) override { - int fd = lwip_accept(this->fd_, addr, addrlen); - if (fd == -1) - return {}; - return make_unique<LwIPSocketImpl>(fd, false); - } - std::unique_ptr<Socket> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) override { - int fd = lwip_accept(this->fd_, addr, addrlen); - if (fd == -1) - return {}; - return make_unique<LwIPSocketImpl>(fd, true); +LwIPSocketImpl::LwIPSocketImpl(int fd, bool monitor_loop) { + this->fd_ = fd; + // Register new socket with the application for select() if monitoring requested + if (monitor_loop && this->fd_ >= 0) { + // Only set loop_monitored_ to true if registration succeeds + this->loop_monitored_ = App.register_socket_fd(this->fd_); } +} - int bind(const struct sockaddr *addr, socklen_t addrlen) override { return lwip_bind(this->fd_, addr, addrlen); } - int close() override { - if (!this->closed_) { - // Unregister from select() before closing if monitored - if (this->loop_monitored_) { - App.unregister_socket_fd(this->fd_); - } - int ret = lwip_close(this->fd_); - this->closed_ = true; - return ret; +LwIPSocketImpl::~LwIPSocketImpl() { + if (!this->closed_) { + this->close(); + } +} + +int LwIPSocketImpl::close() { + if (!this->closed_) { + // Unregister from select() before closing if monitored + if (this->loop_monitored_) { + App.unregister_socket_fd(this->fd_); } + int ret = lwip_close(this->fd_); + this->closed_ = true; + return ret; + } + return 0; +} + +int LwIPSocketImpl::setblocking(bool blocking) { + int fl = lwip_fcntl(this->fd_, F_GETFL, 0); + if (blocking) { + fl &= ~O_NONBLOCK; + } else { + fl |= O_NONBLOCK; + } + lwip_fcntl(this->fd_, F_SETFL, fl); + return 0; +} + +bool LwIPSocketImpl::ready() const { return socket_ready_fd(this->fd_, this->loop_monitored_); } + +size_t LwIPSocketImpl::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getpeername(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; return 0; } - int shutdown(int how) override { return lwip_shutdown(this->fd_, how); } + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} - int getpeername(struct sockaddr *addr, socklen_t *addrlen) override { - return lwip_getpeername(this->fd_, addr, addrlen); - } - int getsockname(struct sockaddr *addr, socklen_t *addrlen) override { - return lwip_getsockname(this->fd_, addr, addrlen); - } - int getsockopt(int level, int optname, void *optval, socklen_t *optlen) override { - return lwip_getsockopt(this->fd_, level, optname, optval, optlen); - } - int setsockopt(int level, int optname, const void *optval, socklen_t optlen) override { - return lwip_setsockopt(this->fd_, level, optname, optval, optlen); - } - int listen(int backlog) override { return lwip_listen(this->fd_, backlog); } - ssize_t read(void *buf, size_t len) override { return lwip_read(this->fd_, buf, len); } - ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) override { - return lwip_recvfrom(this->fd_, buf, len, 0, addr, addr_len); - } - ssize_t readv(const struct iovec *iov, int iovcnt) override { return lwip_readv(this->fd_, iov, iovcnt); } - ssize_t write(const void *buf, size_t len) override { return lwip_write(this->fd_, buf, len); } - ssize_t send(void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); } - ssize_t writev(const struct iovec *iov, int iovcnt) override { return lwip_writev(this->fd_, iov, iovcnt); } - ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) override { - return lwip_sendto(this->fd_, buf, len, flags, to, tolen); - } - int setblocking(bool blocking) override { - int fl = lwip_fcntl(this->fd_, F_GETFL, 0); - if (blocking) { - fl &= ~O_NONBLOCK; - } else { - fl |= O_NONBLOCK; - } - lwip_fcntl(this->fd_, F_SETFL, fl); +size_t LwIPSocketImpl::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) { + struct sockaddr_storage storage; + socklen_t len = sizeof(storage); + if (this->getsockname(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { + buf[0] = '\0'; return 0; } -}; + return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); +} // Helper to create a socket with optional monitoring -static std::unique_ptr<Socket> create_socket(int domain, int type, int protocol, bool loop_monitored = false) { +static std::unique_ptr<LwIPSocketImpl> create_socket(int domain, int type, int protocol, bool loop_monitored = false) { int ret = lwip_socket(domain, type, protocol); if (ret == -1) return nullptr; - return std::unique_ptr<Socket>{new LwIPSocketImpl(ret, loop_monitored)}; + return make_unique<LwIPSocketImpl>(ret, loop_monitored); } std::unique_ptr<Socket> socket(int domain, int type, int protocol) { @@ -107,6 +86,14 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol return create_socket(domain, type, protocol, true); } +std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { + return create_socket(domain, type, protocol, false); +} + +std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { + return create_socket(domain, type, protocol, true); +} + } // namespace esphome::socket #endif // USE_SOCKET_IMPL_LWIP_SOCKETS diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h new file mode 100644 index 0000000000..2e319fcc4d --- /dev/null +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -0,0 +1,80 @@ +#pragma once +#include "esphome/core/defines.h" + +#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS + +#include <memory> +#include <span> + +#include "esphome/core/helpers.h" +#include "headers.h" + +namespace esphome::socket { + +class LwIPSocketImpl { + public: + LwIPSocketImpl(int fd, bool monitor_loop = false); + ~LwIPSocketImpl(); + LwIPSocketImpl(const LwIPSocketImpl &) = delete; + LwIPSocketImpl &operator=(const LwIPSocketImpl &) = delete; + + int connect(const struct sockaddr *addr, socklen_t addrlen) { return lwip_connect(this->fd_, addr, addrlen); } + std::unique_ptr<LwIPSocketImpl> accept(struct sockaddr *addr, socklen_t *addrlen) { + int fd = lwip_accept(this->fd_, addr, addrlen); + if (fd == -1) + return {}; + return make_unique<LwIPSocketImpl>(fd, false); + } + std::unique_ptr<LwIPSocketImpl> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) { + int fd = lwip_accept(this->fd_, addr, addrlen); + if (fd == -1) + return {}; + return make_unique<LwIPSocketImpl>(fd, true); + } + + int bind(const struct sockaddr *addr, socklen_t addrlen) { return lwip_bind(this->fd_, addr, addrlen); } + int close(); + int shutdown(int how) { return lwip_shutdown(this->fd_, how); } + + int getpeername(struct sockaddr *addr, socklen_t *addrlen) { return lwip_getpeername(this->fd_, addr, addrlen); } + int getsockname(struct sockaddr *addr, socklen_t *addrlen) { return lwip_getsockname(this->fd_, addr, addrlen); } + + /// Format peer address into a fixed-size buffer (no heap allocation) + size_t getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf); + /// Format local address into a fixed-size buffer (no heap allocation) + size_t getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf); + + int getsockopt(int level, int optname, void *optval, socklen_t *optlen) { + return lwip_getsockopt(this->fd_, level, optname, optval, optlen); + } + int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { + return lwip_setsockopt(this->fd_, level, optname, optval, optlen); + } + int listen(int backlog) { return lwip_listen(this->fd_, backlog); } + ssize_t read(void *buf, size_t len) { return lwip_read(this->fd_, buf, len); } + ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) { + return lwip_recvfrom(this->fd_, buf, len, 0, addr, addr_len); + } + ssize_t readv(const struct iovec *iov, int iovcnt) { return lwip_readv(this->fd_, iov, iovcnt); } + ssize_t write(const void *buf, size_t len) { return lwip_write(this->fd_, buf, len); } + ssize_t send(void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); } + ssize_t writev(const struct iovec *iov, int iovcnt) { return lwip_writev(this->fd_, iov, iovcnt); } + ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { + return lwip_sendto(this->fd_, buf, len, flags, to, tolen); + } + int setblocking(bool blocking); + int loop() { return 0; } + + bool ready() const; + + int get_fd() const { return this->fd_; } + + protected: + int fd_{-1}; + bool closed_{false}; + bool loop_monitored_{false}; +}; + +} // namespace esphome::socket + +#endif // USE_SOCKET_IMPL_LWIP_SOCKETS diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index 6154c497e0..c04671c7ee 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -8,10 +8,10 @@ namespace esphome::socket { -Socket::~Socket() {} - #ifdef USE_SOCKET_SELECT_SUPPORT -bool Socket::ready() const { return !this->loop_monitored_ || App.is_socket_ready_(this->fd_); } +// Shared ready() implementation for fd-based socket implementations (BSD and LWIP sockets). +// Checks if the Application's select() loop has marked this fd as ready. +bool socket_ready_fd(int fd, bool loop_monitored) { return !loop_monitored || App.is_socket_ready_(fd); } #endif // Platform-specific inet_ntop wrappers @@ -81,26 +81,6 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s return 0; } -size_t Socket::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { - struct sockaddr_storage storage; - socklen_t len = sizeof(storage); - if (this->getpeername(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { - buf[0] = '\0'; - return 0; - } - return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); -} - -size_t Socket::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) { - struct sockaddr_storage storage; - socklen_t len = sizeof(storage); - if (this->getsockname(reinterpret_cast<struct sockaddr *>(&storage), &len) != 0) { - buf[0] = '\0'; - return 0; - } - return format_sockaddr_to(reinterpret_cast<struct sockaddr *>(&storage), len, buf); -} - std::unique_ptr<Socket> socket_ip(int type, int protocol) { #if USE_NETWORK_IPV6 return socket(AF_INET6, type, protocol); @@ -109,11 +89,11 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol) { #endif /* USE_NETWORK_IPV6 */ } -std::unique_ptr<Socket> socket_ip_loop_monitored(int type, int protocol) { +std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol) { #if USE_NETWORK_IPV6 - return socket_loop_monitored(AF_INET6, type, protocol); + return socket_listen_loop_monitored(AF_INET6, type, protocol); #else - return socket_loop_monitored(AF_INET, type, protocol); + return socket_listen_loop_monitored(AF_INET, type, protocol); #endif /* USE_NETWORK_IPV6 */ } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index a771e2fe1a..86a4f0cba9 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -7,87 +7,41 @@ #include "headers.h" #if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) + +// Include only the active implementation's header. +// SOCKADDR_STR_LEN is defined in headers.h. +#ifdef USE_SOCKET_IMPL_BSD_SOCKETS +#include "bsd_sockets_impl.h" +#elif defined(USE_SOCKET_IMPL_LWIP_SOCKETS) +#include "lwip_sockets_impl.h" +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) +#include "lwip_raw_tcp_impl.h" +#endif + namespace esphome::socket { -// Maximum length for formatted socket address string (IP address without port) -// IPv4: "255.255.255.255" = 15 chars + null = 16 -// IPv6: full address = 45 chars + null = 46 -#if USE_NETWORK_IPV6 -static constexpr size_t SOCKADDR_STR_LEN = 46; // INET6_ADDRSTRLEN -#else -static constexpr size_t SOCKADDR_STR_LEN = 16; // INET_ADDRSTRLEN +// Type aliases — only one implementation is active per build. +// Socket is the concrete type for connected sockets. +// ListenSocket is the concrete type for listening/server sockets. +// On BSD and LWIP_SOCKETS, both aliases resolve to the same type. +// On LWIP_TCP, they are different types (no virtual dispatch between them). +#ifdef USE_SOCKET_IMPL_BSD_SOCKETS +using Socket = BSDSocketImpl; +using ListenSocket = BSDSocketImpl; +#elif defined(USE_SOCKET_IMPL_LWIP_SOCKETS) +using Socket = LwIPSocketImpl; +using ListenSocket = LwIPSocketImpl; +#elif defined(USE_SOCKET_IMPL_LWIP_TCP) +using Socket = LWIPRawImpl; +using ListenSocket = LWIPRawListenImpl; #endif -class Socket { - public: - Socket() = default; - virtual ~Socket(); - Socket(const Socket &) = delete; - Socket &operator=(const Socket &) = delete; - - virtual std::unique_ptr<Socket> accept(struct sockaddr *addr, socklen_t *addrlen) = 0; - /// Accept a connection and monitor it in the main loop - /// NOTE: This function is NOT thread-safe and must only be called from the main loop - virtual std::unique_ptr<Socket> accept_loop_monitored(struct sockaddr *addr, socklen_t *addrlen) { - return accept(addr, addrlen); // Default implementation for backward compatibility - } - virtual int bind(const struct sockaddr *addr, socklen_t addrlen) = 0; - virtual int close() = 0; - // not supported yet: - // virtual int connect(const std::string &address) = 0; -#if defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) - virtual int connect(const struct sockaddr *addr, socklen_t addrlen) = 0; -#endif - virtual int shutdown(int how) = 0; - - virtual int getpeername(struct sockaddr *addr, socklen_t *addrlen) = 0; - virtual int getsockname(struct sockaddr *addr, socklen_t *addrlen) = 0; - - /// Format peer address into a fixed-size buffer (no heap allocation) - /// Non-virtual wrapper around getpeername() - can be optimized away if unused - /// Returns number of characters written (excluding null terminator), or 0 on error - size_t getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf); - /// Format local address into a fixed-size buffer (no heap allocation) - /// Non-virtual wrapper around getsockname() - can be optimized away if unused - size_t getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf); - virtual int getsockopt(int level, int optname, void *optval, socklen_t *optlen) = 0; - virtual int setsockopt(int level, int optname, const void *optval, socklen_t optlen) = 0; - virtual int listen(int backlog) = 0; - virtual ssize_t read(void *buf, size_t len) = 0; - virtual ssize_t recvfrom(void *buf, size_t len, sockaddr *addr, socklen_t *addr_len) = 0; - virtual ssize_t readv(const struct iovec *iov, int iovcnt) = 0; - virtual ssize_t write(const void *buf, size_t len) = 0; - virtual ssize_t writev(const struct iovec *iov, int iovcnt) = 0; - virtual ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) = 0; - - virtual int setblocking(bool blocking) = 0; - virtual int loop() { return 0; }; - - /// Get the underlying file descriptor (returns -1 if not supported) - /// Non-virtual: only one socket implementation is active per build. #ifdef USE_SOCKET_SELECT_SUPPORT - int get_fd() const { return this->fd_; } -#else - int get_fd() const { return -1; } +/// Shared ready() helper for fd-based socket implementations. +/// Checks if the Application's select() loop has marked this fd as ready. +bool socket_ready_fd(int fd, bool loop_monitored); #endif - /// Check if socket has data ready to read. Must only be called from the main loop thread. - /// For select()-based sockets: non-virtual, checks Application's select() results - /// For LWIP raw TCP sockets: virtual, checks internal buffer state -#ifdef USE_SOCKET_SELECT_SUPPORT - bool ready() const; -#else - virtual bool ready() const { return true; } -#endif - - protected: -#ifdef USE_SOCKET_SELECT_SUPPORT - int fd_{-1}; - bool closed_{false}; - bool loop_monitored_{false}; -#endif -}; - /// Create a socket of the given domain, type and protocol. std::unique_ptr<Socket> socket(int domain, int type, int protocol); /// Create a socket in the newest available IP domain (IPv6 or IPv4) of the given type and protocol. @@ -100,7 +54,13 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol); /// NOTE: On ESP platforms, FD_SETSIZE is typically 10, limiting the number of monitored sockets. /// File descriptors >= FD_SETSIZE will not be monitored and will log an error. std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol); -std::unique_ptr<Socket> socket_ip_loop_monitored(int type, int protocol); + +/// Create a listening socket of the given domain, type and protocol. +std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol); +/// Create a listening socket and monitor it for data in the main loop. +std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol); +/// Create a listening socket in the newest available IP domain and monitor it. +std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol); /// Set a sockaddr to the specified address and port for the IP version used by socket_ip(). /// @param addr Destination sockaddr structure diff --git a/esphome/core/application.h b/esphome/core/application.h index d2345e2b0b..659b60222d 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -105,7 +105,10 @@ #endif namespace esphome::socket { -class Socket; +#ifdef USE_SOCKET_SELECT_SUPPORT +/// Shared ready() helper for fd-based socket implementations. +bool socket_ready_fd(int fd, bool loop_monitored); // NOLINT(readability-redundant-declaration) +#endif } // namespace esphome::socket // Forward declarations for friend access from codegen-generated setup() @@ -520,7 +523,9 @@ class Application { protected: friend Component; - friend class socket::Socket; +#ifdef USE_SOCKET_SELECT_SUPPORT + friend bool socket::socket_ready_fd(int fd, bool loop_monitored); +#endif friend void ::setup(); friend void ::original_setup(); From a1d91ac779458545b0a6e5f014f57bc6d31d87ca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 06:59:23 -1000 Subject: [PATCH 1045/2030] [core] Compile-time detection of loop() overrides (#14405) --- esphome/core/application.cpp | 19 +++++++-------- esphome/core/application.h | 10 +++++++- esphome/core/component.cpp | 12 ---------- esphome/core/component.h | 7 ++++-- esphome/core/config.py | 36 ++++++++++++++++++++++++++++ esphome/cpp_helpers.py | 5 ++++ tests/unit_tests/test_cpp_helpers.py | 12 ++++++++-- 7 files changed, 73 insertions(+), 28 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index c977fd66b3..26cd670629 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -79,7 +79,12 @@ static void insertion_sort_by_priority(Iterator first, Iterator last) { } } -void Application::register_component_(Component *comp) { this->components_.push_back(comp); } +void Application::register_component_impl_(Component *comp, bool has_loop) { + if (has_loop) { + comp->component_state_ |= COMPONENT_HAS_LOOP; + } + this->components_.push_back(comp); +} void Application::setup() { ESP_LOGI(TAG, "Running through setup()"); ESP_LOGV(TAG, "Sorting components by setup priority"); @@ -382,16 +387,8 @@ void Application::teardown_components(uint32_t timeout_ms) { } void Application::calculate_looping_components_() { - // Count total components that need looping - size_t total_looping = 0; - for (auto *obj : this->components_) { - if (obj->has_overridden_loop()) { - total_looping++; - } - } - - // Initialize FixedVector with exact size - no reallocation possible - this->looping_components_.init(total_looping); + // FixedVector capacity was pre-initialized by codegen with the exact count + // of components that override loop(), computed at C++ compile time. // Add all components with loop override that aren't already LOOP_DONE // Some components (like logger) may call disable_loop() during initialization diff --git a/esphome/core/application.h b/esphome/core/application.h index 659b60222d..44e8de7ee9 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -5,6 +5,7 @@ #include <limits> #include <span> #include <string> +#include <type_traits> #include <vector> #include "esphome/core/component.h" #include "esphome/core/defines.h" @@ -542,7 +543,14 @@ class Application { #endif #endif - void register_component_(Component *comp); + /// Register a component, detecting loop() override at compile time. + /// The template resolves &T::loop vs &Component::loop as a constexpr bool + /// and forwards it to register_component_impl_ which stores it in component_state_. + template<typename T> void register_component_(T *comp) { + this->register_component_impl_(comp, !std::is_same_v<decltype(&T::loop), decltype(&Component::loop)>); + } + + void register_component_impl_(Component *comp, bool has_loop); void calculate_looping_components_(); void add_looping_components_by_state_(bool match_loop_done); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 5afd901da2..a71aa8b3a3 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -496,18 +496,6 @@ void Component::set_setup_priority(float priority) { } #endif -bool Component::has_overridden_loop() const { -#if defined(USE_HOST) || defined(CLANG_TIDY) - return true; -#else -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpmf-conversions" - bool loop_overridden = (void *) (this->*(&Component::loop)) != (void *) (&Component::loop); -#pragma GCC diagnostic pop - return loop_overridden; -#endif -} - PollingComponent::PollingComponent(uint32_t update_interval) : update_interval_(update_interval) {} void PollingComponent::call_setup() { diff --git a/esphome/core/component.h b/esphome/core/component.h index 6b920da290..d8102ea670 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -76,6 +76,8 @@ inline constexpr uint8_t STATUS_LED_MASK = 0x18; inline constexpr uint8_t STATUS_LED_OK = 0x00; inline constexpr uint8_t STATUS_LED_WARNING = 0x08; inline constexpr uint8_t STATUS_LED_ERROR = 0x10; +// Component loop override flag uses bit 5 (set at registration time) +inline constexpr uint8_t COMPONENT_HAS_LOOP = 0x20; // Remove before 2026.8.0 enum class RetryResult { DONE, RETRY }; @@ -271,7 +273,7 @@ class Component { */ void status_momentary_error(const char *name, uint32_t length = 5000); - bool has_overridden_loop() const; + bool has_overridden_loop() const { return (this->component_state_ & COMPONENT_HAS_LOOP) != 0; } /** Set where this component was loaded from for some debug messages. * @@ -510,7 +512,8 @@ class Component { /// Bits 0-2: Component state (0x00=CONSTRUCTION, 0x01=SETUP, 0x02=LOOP, 0x03=FAILED, 0x04=LOOP_DONE) /// Bit 3: STATUS_LED_WARNING /// Bit 4: STATUS_LED_ERROR - /// Bits 5-7: Unused - reserved for future expansion + /// Bit 5: Has overridden loop() (set at registration time) + /// Bits 6-7: Unused - reserved for future expansion uint8_t component_state_{0x00}; volatile bool pending_enable_loop_{false}; ///< ISR-safe flag for enable_loop_soon_any_context }; diff --git a/esphome/core/config.py b/esphome/core/config.py index 593b402230..3835fd3875 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -1,5 +1,6 @@ from __future__ import annotations +from collections import Counter import logging import os from pathlib import Path @@ -504,6 +505,40 @@ async def _add_controller_registry_define() -> None: cg.add_define("CONTROLLER_REGISTRY_MAX", controller_count) +@coroutine_with_priority(CoroPriority.FINAL) +async def _add_looping_components() -> None: + # Emit a constexpr that computes the looping component count at C++ compile time + # and pre-init the FixedVector with the exact capacity. Uses std::is_same_v to + # detect loop() overrides. The constexpr goes in main.cpp's global section where + # all component types are in scope. calculate_looping_components_() then skips + # the counting pass and only does the two population passes. + entries = CORE.data.get("looping_component_entries", []) + if not entries: + return + + # Build constexpr sum for the exact count, deduplicating by type + type_counts = Counter(entries) + terms = [ + f"({count} * !std::is_same_v<decltype(&{cpp_type}::loop), decltype(&Component::loop)>)" + for cpp_type, count in type_counts.items() + ] + constexpr_expr = " + \\\n ".join(terms) + cg.add_global( + cg.RawStatement( + f"static constexpr size_t ESPHOME_LOOPING_COMPONENT_COUNT = \\\n" + f" {constexpr_expr};" + ) + ) + + # Pre-init FixedVector with exact capacity so calculate_looping_components_() + # can skip the counting pass + cg.add( + cg.RawExpression( + "App.looping_components_.init(ESPHOME_LOOPING_COMPONENT_COUNT)" + ) + ) + + @coroutine_with_priority(CoroPriority.CORE) async def to_code(config: ConfigType) -> None: cg.add_global(cg.global_ns.namespace("esphome").using) @@ -527,6 +562,7 @@ async def to_code(config: ConfigType) -> None: CORE.add_job(_add_platform_defines) CORE.add_job(_add_controller_registry_define) + CORE.add_job(_add_looping_components) CORE.add_job(_add_automations, config) diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index b673eaa7e1..8f8c693140 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -80,6 +80,11 @@ async def register_component(var, config): add(var.set_component_source(LogStringLiteral(name))) add(App.register_component_(var)) + + # Collect C++ type for compile-time looping component count + comp_entries = CORE.data.setdefault("looping_component_entries", []) + comp_entries.append(str(var.base.type)) + return var diff --git a/tests/unit_tests/test_cpp_helpers.py b/tests/unit_tests/test_cpp_helpers.py index 82ded409c7..5b6eed156f 100644 --- a/tests/unit_tests/test_cpp_helpers.py +++ b/tests/unit_tests/test_cpp_helpers.py @@ -14,7 +14,11 @@ async def test_gpio_pin_expression__conf_is_none(monkeypatch): @pytest.mark.asyncio async def test_register_component(monkeypatch): - var = Mock(base="foo.bar") + base_mock = Mock() + base_mock.__str__ = lambda self: "foo.bar" + base_mock.type = Mock() + base_mock.type.__str__ = lambda self: "foo::Bar" + var = Mock(base=base_mock) app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) @@ -46,7 +50,11 @@ async def test_register_component__no_component_id(monkeypatch): @pytest.mark.asyncio async def test_register_component__with_setup_priority(monkeypatch): - var = Mock(base="foo.bar") + base_mock = Mock() + base_mock.__str__ = lambda self: "foo.bar" + base_mock.type = Mock() + base_mock.type.__str__ = lambda self: "foo::Bar" + var = Mock(base=base_mock) app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) From b9b1af1c3dd11e2d41c0b88542637a6ceaec5ecd Mon Sep 17 00:00:00 2001 From: netixx <dev.espinetfrancois@gmail.com> Date: Mon, 2 Mar 2026 18:38:28 +0100 Subject: [PATCH 1046/2030] [mcp23016] Fix register access to use 16-bit paired transactions (#13676) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/mcp23016/mcp23016.cpp | 71 +++++++++--------------- esphome/components/mcp23016/mcp23016.h | 15 +++-- 2 files changed, 33 insertions(+), 53 deletions(-) diff --git a/esphome/components/mcp23016/mcp23016.cpp b/esphome/components/mcp23016/mcp23016.cpp index 56b2ecf9f4..fbdb6903b8 100644 --- a/esphome/components/mcp23016/mcp23016.cpp +++ b/esphome/components/mcp23016/mcp23016.cpp @@ -8,90 +8,71 @@ namespace mcp23016 { static const char *const TAG = "mcp23016"; void MCP23016::setup() { - uint8_t iocon; - if (!this->read_reg_(MCP23016_IOCON0, &iocon)) { + uint16_t iocon; + // MCP23016 registers operate as paired 16-bit registers. Addressing the + // odd register (e.g. IOCON1) reads/writes that register first, then wraps + // to the even register (IOCON0) in the same pair. Starting from the odd + // address gives the correct byte order for 1 << pin mapping: + // high byte = port 1 (pins 8-15), low byte = port 0 (pins 0-7). + if (!this->read_reg_(MCP23016_IOCON1, &iocon)) { this->mark_failed(); return; } // Read current output register state - this->read_reg_(MCP23016_OLAT0, &this->olat_0_); - this->read_reg_(MCP23016_OLAT1, &this->olat_1_); + this->read_reg_(MCP23016_OLAT1, &this->olat_); // all pins input - this->write_reg_(MCP23016_IODIR0, 0xFF); - this->write_reg_(MCP23016_IODIR1, 0xFF); + this->write_reg_(MCP23016_IODIR1, 0xFFFF); } void MCP23016::loop() { // Invalidate cache at the start of each loop this->reset_pin_cache_(); } -bool MCP23016::digital_read_hw(uint8_t pin) { - uint8_t reg_addr = pin < 8 ? MCP23016_GP0 : MCP23016_GP1; - uint8_t value = 0; - if (!this->read_reg_(reg_addr, &value)) { - return false; - } - - // Update the appropriate part of input_mask_ - if (pin < 8) { - this->input_mask_ = (this->input_mask_ & 0xFF00) | value; - } else { - this->input_mask_ = (this->input_mask_ & 0x00FF) | (uint16_t(value) << 8); - } - return true; -} +bool MCP23016::digital_read_hw(uint8_t pin) { return this->read_reg_(MCP23016_GP1, &this->input_mask_); } bool MCP23016::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); } -void MCP23016::digital_write_hw(uint8_t pin, bool value) { - uint8_t reg_addr = pin < 8 ? MCP23016_OLAT0 : MCP23016_OLAT1; - this->update_reg_(pin, value, reg_addr); -} +void MCP23016::digital_write_hw(uint8_t pin, bool value) { this->update_reg_(pin, value, MCP23016_OLAT1); } void MCP23016::pin_mode(uint8_t pin, gpio::Flags flags) { - uint8_t iodir = pin < 8 ? MCP23016_IODIR0 : MCP23016_IODIR1; if (flags == gpio::FLAG_INPUT) { - this->update_reg_(pin, true, iodir); + this->update_reg_(pin, true, MCP23016_IODIR1); } else if (flags == gpio::FLAG_OUTPUT) { - this->update_reg_(pin, false, iodir); + this->update_reg_(pin, false, MCP23016_IODIR1); } } -float MCP23016::get_setup_priority() const { return setup_priority::HARDWARE; } -bool MCP23016::read_reg_(uint8_t reg, uint8_t *value) { +float MCP23016::get_setup_priority() const { return setup_priority::IO; } +bool MCP23016::read_reg_(uint8_t reg, uint16_t *value) { if (this->is_failed()) return false; - return this->read_byte(reg, value); + return this->read_byte_16(reg, value); } -bool MCP23016::write_reg_(uint8_t reg, uint8_t value) { +bool MCP23016::write_reg_(uint8_t reg, uint16_t value) { if (this->is_failed()) return false; - return this->write_byte(reg, value); + return this->write_byte_16(reg, value); } void MCP23016::update_reg_(uint8_t pin, bool pin_value, uint8_t reg_addr) { - uint8_t bit = pin % 8; - uint8_t reg_value = 0; - if (reg_addr == MCP23016_OLAT0) { - reg_value = this->olat_0_; - } else if (reg_addr == MCP23016_OLAT1) { - reg_value = this->olat_1_; + uint16_t reg_value = 0; + + if (reg_addr == MCP23016_OLAT1) { + reg_value = this->olat_; } else { this->read_reg_(reg_addr, ®_value); } if (pin_value) { - reg_value |= 1 << bit; + reg_value |= 1 << pin; } else { - reg_value &= ~(1 << bit); + reg_value &= ~(1 << pin); } this->write_reg_(reg_addr, reg_value); - if (reg_addr == MCP23016_OLAT0) { - this->olat_0_ = reg_value; - } else if (reg_addr == MCP23016_OLAT1) { - this->olat_1_ = reg_value; + if (reg_addr == MCP23016_OLAT1) { + this->olat_ = reg_value; } } diff --git a/esphome/components/mcp23016/mcp23016.h b/esphome/components/mcp23016/mcp23016.h index c2bc885c95..494bc9c197 100644 --- a/esphome/components/mcp23016/mcp23016.h +++ b/esphome/components/mcp23016/mcp23016.h @@ -19,13 +19,13 @@ enum MCP23016GPIORegisters { // 1 side MCP23016_GP1 = 0x01, MCP23016_OLAT1 = 0x03, - MCP23016_IPOL1 = 0x04, + MCP23016_IPOL1 = 0x05, MCP23016_IODIR1 = 0x07, - MCP23016_INTCAP1 = 0x08, + MCP23016_INTCAP1 = 0x09, MCP23016_IOCON1 = 0x0B, }; -class MCP23016 : public Component, public i2c::I2CDevice, public gpio_expander::CachedGpioExpander<uint8_t, 16> { +class MCP23016 : public Component, public i2c::I2CDevice, public gpio_expander::CachedGpioExpander<uint16_t, 16> { public: MCP23016() = default; @@ -42,16 +42,15 @@ class MCP23016 : public Component, public i2c::I2CDevice, public gpio_expander:: void digital_write_hw(uint8_t pin, bool value) override; // read a given register - bool read_reg_(uint8_t reg, uint8_t *value); + bool read_reg_(uint8_t reg, uint16_t *value); // write a value to a given register - bool write_reg_(uint8_t reg, uint8_t value); + bool write_reg_(uint8_t reg, uint16_t value); // update registers with given pin value. void update_reg_(uint8_t pin, bool pin_value, uint8_t reg_a); - uint8_t olat_0_{0x00}; - uint8_t olat_1_{0x00}; + uint16_t olat_{0x0000}; // Cache for input values (16-bit combined for both banks) - uint16_t input_mask_{0x00}; + uint16_t input_mask_{0x0000}; }; class MCP23016GPIOPin : public GPIOPin { From 2fa244715d21e30338702c0ea017884f338efd03 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 08:54:54 -1000 Subject: [PATCH 1047/2030] [socket] Fix pre-existing bugs found during socket devirtualization review (#14404) --- esphome/components/socket/bsd_sockets_impl.h | 2 +- .../components/socket/lwip_raw_tcp_impl.cpp | 21 +++++++++++++++++-- esphome/components/socket/lwip_sockets_impl.h | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h index edee39f315..d9ed9dc567 100644 --- a/esphome/components/socket/bsd_sockets_impl.h +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -83,7 +83,7 @@ class BSDSocketImpl { return ::write(this->fd_, buf, len); #endif } - ssize_t send(void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); } + ssize_t send(const void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); } ssize_t writev(const struct iovec *iov, int iovcnt) { #if defined(USE_ESP32) return ::lwip_writev(this->fd_, iov, iovcnt); diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 6556979fe0..430356592f 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -68,7 +68,7 @@ int LWIPRawCommon::bind(const struct sockaddr *name, socklen_t addrlen) { } if (name == nullptr) { errno = EINVAL; - return 0; + return -1; } ip_addr_t ip; in_port_t port; @@ -319,6 +319,13 @@ int LWIPRawCommon::ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *n // ---- LWIPRawImpl methods ---- LWIPRawImpl::~LWIPRawImpl() { + // Free any received pbufs that LWIP transferred ownership of via recv_fn. + // tcp_abort() in the base destructor won't free these since LWIP considers + // ownership transferred once the recv callback accepts them. + if (this->rx_buf_ != nullptr) { + pbuf_free(this->rx_buf_); + this->rx_buf_ = nullptr; + } // Base class destructor handles pcb_ cleanup via tcp_abort } @@ -545,7 +552,14 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { // ---- LWIPRawListenImpl methods ---- LWIPRawListenImpl::~LWIPRawListenImpl() { - // Base class destructor handles pcb_ cleanup via tcp_abort + // Listen PCBs must use tcp_close(), not tcp_abort(). + // tcp_abandon() asserts pcb->state != LISTEN and would access + // fields that don't exist in the smaller tcp_pcb_listen struct. + // Close here and null pcb_ so the base destructor skips tcp_abort. + if (this->pcb_ != nullptr) { + tcp_close(this->pcb_); + this->pcb_ = nullptr; + } } void LWIPRawListenImpl::init() { @@ -609,6 +623,9 @@ int LWIPRawListenImpl::listen(int backlog) { LWIP_LOG("tcp_arg(%p)", this->pcb_); tcp_arg(this->pcb_, this); tcp_accept(this->pcb_, LWIPRawListenImpl::s_accept_fn); + // Note: tcp_err() is NOT re-registered here. tcp_listen_with_backlog() converts the + // full tcp_pcb to a smaller tcp_pcb_listen struct that lacks the errf field. + // Calling tcp_err() on a listen PCB writes past the struct boundary (undefined behavior). return 0; } diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h index 2e319fcc4d..d6699aded2 100644 --- a/esphome/components/socket/lwip_sockets_impl.h +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -57,7 +57,7 @@ class LwIPSocketImpl { } ssize_t readv(const struct iovec *iov, int iovcnt) { return lwip_readv(this->fd_, iov, iovcnt); } ssize_t write(const void *buf, size_t len) { return lwip_write(this->fd_, buf, len); } - ssize_t send(void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); } + ssize_t send(const void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); } ssize_t writev(const struct iovec *iov, int iovcnt) { return lwip_writev(this->fd_, iov, iovcnt); } ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { return lwip_sendto(this->fd_, buf, len, flags, to, tolen); From cb232d828879b365bfa116ff3b4a7546c1e6ce62 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 09:11:47 -1000 Subject: [PATCH 1048/2030] [core] Fix compile-time loop() detection for multiple inheritance (#14411) --- esphome/core/application.h | 13 ++++++++++--- esphome/core/config.py | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index 44e8de7ee9..13fd0180ab 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -118,6 +118,14 @@ void original_setup(); // NOLINT(readability-redundant-declaration) - used by c namespace esphome { +/// SFINAE helper: detects whether T overrides Component::loop(). +/// When &T::loop is ambiguous (multiple inheritance with separate loop() methods), +/// the ambiguity itself proves an override exists, so the true_type default is correct. +template<typename T, typename = void> struct HasLoopOverride : std::true_type {}; +template<typename T> +struct HasLoopOverride<T, std::void_t<decltype(&T::loop)>> + : std::bool_constant<!std::is_same_v<decltype(&T::loop), decltype(&Component::loop)>> {}; + // Teardown timeout constant (in milliseconds) // For reboots, it's more important to shut down quickly than disconnect cleanly // since we're not entering deep sleep. The only consequence of not shutting down @@ -544,10 +552,9 @@ class Application { #endif /// Register a component, detecting loop() override at compile time. - /// The template resolves &T::loop vs &Component::loop as a constexpr bool - /// and forwards it to register_component_impl_ which stores it in component_state_. + /// Uses HasLoopOverride<T> which handles ambiguous &T::loop from multiple inheritance. template<typename T> void register_component_(T *comp) { - this->register_component_impl_(comp, !std::is_same_v<decltype(&T::loop), decltype(&Component::loop)>); + this->register_component_impl_(comp, HasLoopOverride<T>::value); } void register_component_impl_(Component *comp, bool has_loop); diff --git a/esphome/core/config.py b/esphome/core/config.py index 3835fd3875..9411949bb9 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -517,9 +517,10 @@ async def _add_looping_components() -> None: return # Build constexpr sum for the exact count, deduplicating by type + # Uses HasLoopOverride<T> which handles ambiguous &T::loop from multiple inheritance type_counts = Counter(entries) terms = [ - f"({count} * !std::is_same_v<decltype(&{cpp_type}::loop), decltype(&Component::loop)>)" + f"({count} * HasLoopOverride<{cpp_type}>::value)" for cpp_type, count in type_counts.items() ] constexpr_expr = " + \\\n ".join(terms) From 38f671a9231348919a2ffd779ebf070906cbdef9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:52:06 -0500 Subject: [PATCH 1049/2030] [uart] Fix flow_control_pin inverted flag ignored on ESP-IDF (#14410) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/uart/uart_component_esp_idf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 631db1e5c7..544404448b 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -157,6 +157,9 @@ void IDFUARTComponent::load_settings(bool dump_config) { if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted()) { invert |= UART_SIGNAL_RXD_INV; } + if (this->flow_control_pin_ != nullptr && this->flow_control_pin_->is_inverted()) { + invert |= UART_SIGNAL_RTS_INV; + } err = uart_set_line_inverse(this->uart_num_, invert); if (err != ESP_OK) { From 48a9c1cd67c56ff17ea095f98815e114e8473035 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Feb 2026 11:12:35 -0600 Subject: [PATCH 1050/2030] [mqtt] Remove broken ESP8266 ssl_fingerprints option (#14182) --- esphome/__main__.py | 14 --------- esphome/components/mqtt/__init__.py | 21 -------------- .../components/mqtt/mqtt_backend_esp8266.h | 5 ---- .../components/mqtt/mqtt_backend_libretiny.h | 5 ---- esphome/components/mqtt/mqtt_client.cpp | 7 ----- esphome/components/mqtt/mqtt_client.h | 15 ---------- esphome/const.py | 1 - esphome/mqtt.py | 29 ++----------------- 8 files changed, 2 insertions(+), 95 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index c86b5604e1..488955f503 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -944,12 +944,6 @@ def command_clean_all(args: ArgsProtocol) -> int | None: return 0 -def command_mqtt_fingerprint(args: ArgsProtocol, config: ConfigType) -> int | None: - from esphome import mqtt - - return mqtt.get_fingerprint(config) - - def command_version(args: ArgsProtocol) -> int | None: safe_print(f"Version: {const.__version__}") return 0 @@ -1237,7 +1231,6 @@ POST_CONFIG_ACTIONS = { "run": command_run, "clean": command_clean, "clean-mqtt": command_clean_mqtt, - "mqtt-fingerprint": command_mqtt_fingerprint, "idedata": command_idedata, "rename": command_rename, "discover": command_discover, @@ -1451,13 +1444,6 @@ def parse_args(argv): ) parser_wizard.add_argument("configuration", help="Your YAML configuration file.") - parser_fingerprint = subparsers.add_parser( - "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker." - ) - parser_fingerprint.add_argument( - "configuration", help="Your YAML configuration file(s).", nargs="+" - ) - subparsers.add_parser("version", help="Print the ESPHome version and exit.") parser_clean = subparsers.add_parser( diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index fe153fedfa..44e8836487 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -1,5 +1,3 @@ -import re - from esphome import automation from esphome.automation import Condition import esphome.codegen as cg @@ -46,7 +44,6 @@ from esphome.const import ( CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SKIP_CERT_CN_CHECK, - CONF_SSL_FINGERPRINTS, CONF_STATE_TOPIC, CONF_SUBSCRIBE_QOS, CONF_TOPIC, @@ -221,13 +218,6 @@ def validate_config(value): return out -def validate_fingerprint(value): - value = cv.string(value) - if re.match(r"^[0-9a-f]{40}$", value) is None: - raise cv.Invalid("fingerprint must be valid SHA1 hash") - return value - - def _consume_mqtt_sockets(config: ConfigType) -> ConfigType: """Register socket needs for MQTT component.""" # MQTT needs 1 socket for the broker connection @@ -291,9 +281,6 @@ CONFIG_SCHEMA = cv.All( ), validate_message_just_topic, ), - cv.Optional(CONF_SSL_FINGERPRINTS): cv.All( - cv.only_on_esp8266, cv.ensure_list(validate_fingerprint) - ), cv.Optional(CONF_KEEPALIVE, default="15s"): cv.positive_time_period_seconds, cv.Optional( CONF_REBOOT_TIMEOUT, default="15min" @@ -444,14 +431,6 @@ async def to_code(config): if CONF_LEVEL in log_topic: cg.add(var.set_log_level(logger.LOG_LEVELS[log_topic[CONF_LEVEL]])) - if CONF_SSL_FINGERPRINTS in config: - for fingerprint in config[CONF_SSL_FINGERPRINTS]: - arr = [ - cg.RawExpression(f"0x{fingerprint[i : i + 2]}") for i in range(0, 40, 2) - ] - cg.add(var.add_ssl_fingerprint(arr)) - cg.add_build_flag("-DASYNC_TCP_SSL_ENABLED=1") - cg.add(var.set_keep_alive(config[CONF_KEEPALIVE])) cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) diff --git a/esphome/components/mqtt/mqtt_backend_esp8266.h b/esphome/components/mqtt/mqtt_backend_esp8266.h index 470d1e6a8b..0bf5b510a4 100644 --- a/esphome/components/mqtt/mqtt_backend_esp8266.h +++ b/esphome/components/mqtt/mqtt_backend_esp8266.h @@ -21,11 +21,6 @@ class MQTTBackendESP8266 final : public MQTTBackend { } void set_server(network::IPAddress ip, uint16_t port) final { mqtt_client_.setServer(ip, port); } void set_server(const char *host, uint16_t port) final { mqtt_client_.setServer(host, port); } -#if ASYNC_TCP_SSL_ENABLED - void set_secure(bool secure) { mqtt_client.setSecure(secure); } - void add_server_fingerprint(const uint8_t *fingerprint) { mqtt_client.addServerFingerprint(fingerprint); } -#endif - void set_on_connect(std::function<on_connect_callback_t> &&callback) final { this->mqtt_client_.onConnect(std::move(callback)); } diff --git a/esphome/components/mqtt/mqtt_backend_libretiny.h b/esphome/components/mqtt/mqtt_backend_libretiny.h index 24bf018a90..5fa3406193 100644 --- a/esphome/components/mqtt/mqtt_backend_libretiny.h +++ b/esphome/components/mqtt/mqtt_backend_libretiny.h @@ -21,11 +21,6 @@ class MQTTBackendLibreTiny final : public MQTTBackend { } void set_server(network::IPAddress ip, uint16_t port) final { mqtt_client_.setServer(IPAddress(ip), port); } void set_server(const char *host, uint16_t port) final { mqtt_client_.setServer(host, port); } -#if ASYNC_TCP_SSL_ENABLED - void set_secure(bool secure) { mqtt_client.setSecure(secure); } - void add_server_fingerprint(const uint8_t *fingerprint) { mqtt_client.addServerFingerprint(fingerprint); } -#endif - void set_on_connect(std::function<on_connect_callback_t> &&callback) final { this->mqtt_client_.onConnect(std::move(callback)); } diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 90b423c386..2fb094f370 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -746,13 +746,6 @@ void MQTTClientComponent::set_on_disconnect(mqtt_on_disconnect_callback_t &&call this->on_disconnect_.add(std::move(callback_copy)); } -#if ASYNC_TCP_SSL_ENABLED -void MQTTClientComponent::add_ssl_fingerprint(const std::array<uint8_t, SHA1_SIZE> &fingerprint) { - this->mqtt_backend_.setSecure(true); - this->mqtt_backend_.addServerFingerprint(fingerprint.data()); -} -#endif - MQTTClientComponent *global_mqtt_client = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) // MQTTMessageTrigger diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 38bc0b4da3..7a51989a10 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -142,21 +142,6 @@ class MQTTClientComponent : public Component bool is_discovery_enabled() const; bool is_discovery_ip_enabled() const; -#if ASYNC_TCP_SSL_ENABLED - /** Add a SSL fingerprint to use for TCP SSL connections to the MQTT broker. - * - * To use this feature you first have to globally enable the `ASYNC_TCP_SSL_ENABLED` define flag. - * This function can be called multiple times and any certificate that matches any of the provided fingerprints - * will match. Calling this method will also automatically disable all non-ssl connections. - * - * @warning This is *not* secure and *not* how SSL is usually done. You'll have to add - * a separate fingerprint for every certificate you use. Additionally, the hashing - * algorithm used here due to the constraints of the MCU, SHA1, is known to be insecure. - * - * @param fingerprint The SSL fingerprint as a 20 value long std::array. - */ - void add_ssl_fingerprint(const std::array<uint8_t, SHA1_SIZE> &fingerprint); -#endif #ifdef USE_ESP32 void set_ca_certificate(const char *cert) { this->mqtt_backend_.set_ca_certificate(cert); } void set_cl_certificate(const char *cert) { this->mqtt_backend_.set_cl_certificate(cert); } diff --git a/esphome/const.py b/esphome/const.py index 7d15964eab..ea8d2b73be 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -943,7 +943,6 @@ CONF_SPI = "spi" CONF_SPI_ID = "spi_id" CONF_SPIKE_REJECTION = "spike_rejection" CONF_SSID = "ssid" -CONF_SSL_FINGERPRINTS = "ssl_fingerprints" CONF_STARTUP_DELAY = "startup_delay" CONF_STATE = "state" CONF_STATE_CLASS = "state_class" diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 042df12d67..cbf78bd3f6 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -1,6 +1,5 @@ import contextlib from datetime import datetime -import hashlib import json import logging import ssl @@ -22,14 +21,12 @@ from esphome.const import ( CONF_PASSWORD, CONF_PORT, CONF_SKIP_CERT_CN_CHECK, - CONF_SSL_FINGERPRINTS, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME, ) -from esphome.core import CORE, EsphomeError +from esphome.core import EsphomeError from esphome.helpers import get_int_env, get_str_env -from esphome.log import AnsiFore, color from esphome.types import ConfigType from esphome.util import safe_print @@ -102,9 +99,7 @@ def prepare( elif username: client.username_pw_set(username, password) - if config[CONF_MQTT].get(CONF_SSL_FINGERPRINTS) or config[CONF_MQTT].get( - CONF_CERTIFICATE_AUTHORITY - ): + if config[CONF_MQTT].get(CONF_CERTIFICATE_AUTHORITY): context = ssl.create_default_context( cadata=config[CONF_MQTT].get(CONF_CERTIFICATE_AUTHORITY) ) @@ -283,23 +278,3 @@ def clear_topic(config, topic, username=None, password=None, client_id=None): client.publish(msg.topic, None, retain=True) return initialize(config, [topic], on_message, None, username, password, client_id) - - -# From marvinroger/async-mqtt-client -> scripts/get-fingerprint/get-fingerprint.py -def get_fingerprint(config): - addr = str(config[CONF_MQTT][CONF_BROKER]), int(config[CONF_MQTT][CONF_PORT]) - _LOGGER.info("Getting fingerprint from %s:%s", addr[0], addr[1]) - try: - cert_pem = ssl.get_server_certificate(addr) - except OSError as err: - _LOGGER.error("Unable to connect to server: %s", err) - return 1 - cert_der = ssl.PEM_cert_to_DER_cert(cert_pem) - - sha1 = hashlib.sha1(cert_der).hexdigest() - - safe_print(f"SHA1 Fingerprint: {color(AnsiFore.CYAN, sha1)}") - safe_print( - f"Copy the string above into mqtt.ssl_fingerprints section of {CORE.config_path}" - ) - return 0 From b5c36140faf58ba8966ad127f5b14670c6a3d2bb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Feb 2026 08:40:43 -0500 Subject: [PATCH 1051/2030] [sprinkler] Fix millis overflow and underflow bugs (#14299) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/sprinkler/sprinkler.cpp | 81 +++++++++++----------- esphome/components/sprinkler/sprinkler.h | 4 +- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 9e423c1760..d82d7baaf6 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -84,32 +84,30 @@ SprinklerValveOperator::SprinklerValveOperator(SprinklerValve *valve, Sprinkler : controller_(controller), valve_(valve) {} void SprinklerValveOperator::loop() { + // Use wrapping subtraction so 32-bit millis() rollover is handled correctly: + // (now - start) yields the true elapsed time even across the 49.7-day boundary. uint32_t now = App.get_loop_component_start_time(); - if (now >= this->start_millis_) { // dummy check - switch (this->state_) { - case STARTING: - if (now > (this->start_millis_ + this->start_delay_)) { - this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state - } - break; + switch (this->state_) { + case STARTING: + if ((now - *this->start_millis_) > this->start_delay_) { + this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state + } + break; - case ACTIVE: - if (now > (this->start_millis_ + this->start_delay_ + this->run_duration_)) { - this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down - } - break; + case ACTIVE: + if ((now - *this->start_millis_) > (this->start_delay_ + this->run_duration_)) { + this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down + } + break; - case STOPPING: - if (now > (this->stop_millis_ + this->stop_delay_)) { - this->kill_(); // stop_delay_has been exceeded, ensure all valves are off - } - break; + case STOPPING: + if ((now - *this->stop_millis_) > this->stop_delay_) { + this->kill_(); // stop_delay_has been exceeded, ensure all valves are off + } + break; - default: - break; - } - } else { // perhaps millis() rolled over...or something else is horribly wrong! - this->stop(); // bail out (TODO: handle this highly unlikely situation better...) + default: + break; } } @@ -124,11 +122,11 @@ void SprinklerValveOperator::set_valve(SprinklerValve *valve) { if (this->state_ != IDLE) { // Only kill if not already idle this->kill_(); // ensure everything is off before we let go! } - this->state_ = IDLE; // reset state - this->run_duration_ = 0; // reset to ensure the valve isn't started without updating it - this->start_millis_ = 0; // reset because (new) valve has not been started yet - this->stop_millis_ = 0; // reset because (new) valve has not been started yet - this->valve_ = valve; // finally, set the pointer to the new valve + this->state_ = IDLE; // reset state + this->run_duration_ = 0; // reset to ensure the valve isn't started without updating it + this->start_millis_.reset(); // reset because (new) valve has not been started yet + this->stop_millis_.reset(); // reset because (new) valve has not been started yet + this->valve_ = valve; // finally, set the pointer to the new valve } } @@ -162,7 +160,7 @@ void SprinklerValveOperator::start() { } else { this->run_(); // there is no start_delay_, so just start the pump and valve } - this->stop_millis_ = 0; + this->stop_millis_.reset(); this->start_millis_ = millis(); // save the time the start request was made } @@ -189,22 +187,25 @@ void SprinklerValveOperator::stop() { uint32_t SprinklerValveOperator::run_duration() { return this->run_duration_ / 1000; } uint32_t SprinklerValveOperator::time_remaining() { - if (this->start_millis_ == 0) { + if (!this->start_millis_.has_value()) { return this->run_duration(); // hasn't been started yet } - if (this->stop_millis_) { - if (this->stop_millis_ - this->start_millis_ >= this->start_delay_ + this->run_duration_) { + if (this->stop_millis_.has_value()) { + uint32_t elapsed = *this->stop_millis_ - *this->start_millis_; + if (elapsed >= this->start_delay_ + this->run_duration_) { return 0; // valve was active for more than its configured duration, so we are done - } else { - // we're stopped; return time remaining - return (this->run_duration_ - (this->stop_millis_ - this->start_millis_)) / 1000; } + if (elapsed <= this->start_delay_) { + return this->run_duration_ / 1000; // stopped during start delay, full run duration remains + } + return (this->run_duration_ - (elapsed - this->start_delay_)) / 1000; } - auto completed_millis = this->start_millis_ + this->start_delay_ + this->run_duration_; - if (completed_millis > millis()) { - return (completed_millis - millis()) / 1000; // running now + uint32_t elapsed = millis() - *this->start_millis_; + uint32_t total_duration = this->start_delay_ + this->run_duration_; + if (elapsed < total_duration) { + return (total_duration - elapsed) / 1000; // running now } return 0; // run completed } @@ -593,7 +594,7 @@ void Sprinkler::set_repeat(optional<uint32_t> repeat) { if (this->repeat_number_ == nullptr) { return; } - if (this->repeat_number_->state == repeat.value()) { + if (this->repeat_number_->state == repeat.value_or(0)) { return; } auto call = this->repeat_number_->make_call(); @@ -793,7 +794,7 @@ void Sprinkler::start_single_valve(const optional<size_t> valve_number, optional void Sprinkler::queue_valve(optional<size_t> valve_number, optional<uint32_t> run_duration) { if (valve_number.has_value()) { if (this->is_a_valid_valve(valve_number.value()) && (this->queued_valves_.size() < this->max_queue_size_)) { - SprinklerQueueItem item{valve_number.value(), run_duration.value()}; + SprinklerQueueItem item{valve_number.value(), run_duration.value_or(0)}; this->queued_valves_.insert(this->queued_valves_.begin(), item); ESP_LOGD(TAG, "Valve %zu placed into queue with run duration of %" PRIu32 " seconds", valve_number.value_or(0), run_duration.value_or(0)); @@ -1080,7 +1081,7 @@ uint32_t Sprinkler::total_cycle_time_enabled_incomplete_valves() { } } - if (incomplete_valve_count >= enabled_valve_count) { + if (incomplete_valve_count > 0 && incomplete_valve_count >= enabled_valve_count) { incomplete_valve_count--; } if (incomplete_valve_count) { diff --git a/esphome/components/sprinkler/sprinkler.h b/esphome/components/sprinkler/sprinkler.h index a3cdef5b1a..2598a5606a 100644 --- a/esphome/components/sprinkler/sprinkler.h +++ b/esphome/components/sprinkler/sprinkler.h @@ -141,8 +141,8 @@ class SprinklerValveOperator { uint32_t start_delay_{0}; uint32_t stop_delay_{0}; uint32_t run_duration_{0}; - uint64_t start_millis_{0}; - uint64_t stop_millis_{0}; + optional<uint32_t> start_millis_{}; + optional<uint32_t> stop_millis_{}; Sprinkler *controller_{nullptr}; SprinklerValve *valve_{nullptr}; SprinklerState state_{IDLE}; From 97b712da9866f9a1d7ef46a1ea5bf1184fdb41cb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:48:05 -0500 Subject: [PATCH 1052/2030] [cc1101] Transition through IDLE in begin_tx/begin_rx for reliable state changes (#14321) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/cc1101/cc1101.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/esphome/components/cc1101/cc1101.cpp b/esphome/components/cc1101/cc1101.cpp index b6973da78d..51aa88b8f7 100644 --- a/esphome/components/cc1101/cc1101.cpp +++ b/esphome/components/cc1101/cc1101.cpp @@ -242,6 +242,9 @@ void CC1101Component::begin_tx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_OUTPUT); } + // Transition through IDLE to bypass CCA (Clear Channel Assessment) which can + // block TX entry when strobing from RX, and to ensure FS_AUTOCAL calibration + this->enter_idle_(); if (!this->enter_tx_()) { ESP_LOGW(TAG, "Failed to enter TX state!"); } @@ -252,6 +255,8 @@ void CC1101Component::begin_rx() { if (this->gdo0_pin_ != nullptr) { this->gdo0_pin_->pin_mode(gpio::FLAG_INPUT); } + // Transition through IDLE to ensure FS_AUTOCAL calibration occurs + this->enter_idle_(); if (!this->enter_rx_()) { ESP_LOGW(TAG, "Failed to enter RX state!"); } From 840859ab7cf323bbaa5d1d508c20dfced0d6f3e8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:17:04 -0500 Subject: [PATCH 1053/2030] [zigbee] Fix codegen ordering for basic/identify attribute lists (#14343) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/zigbee/__init__.py | 3 ++- esphome/components/zigbee/zigbee_zephyr.py | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index 7e917a9d70..a327cc2988 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -8,7 +8,7 @@ from esphome.components.zephyr import zephyr_add_pm_static, zephyr_data from esphome.components.zephyr.const import KEY_BOOTLOADER import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_INTERNAL, CONF_NAME -from esphome.core import CORE +from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.types import ConfigType from .const_zephyr import ( @@ -96,6 +96,7 @@ FINAL_VALIDATE_SCHEMA = cv.All( ) +@coroutine_with_priority(CoroPriority.CORE) async def to_code(config: ConfigType) -> None: cg.add_define("USE_ZIGBEE") if CORE.using_zephyr: diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index 0b6daa9476..a1e6ad3097 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -179,6 +179,13 @@ async def zephyr_to_code(config: ConfigType) -> None: "USE_ZIGBEE_WIPE_ON_BOOT_MAGIC", random.randint(0x000001, 0xFFFFFF) ) cg.add_define("USE_ZIGBEE_WIPE_ON_BOOT") + + # Generate attribute lists before any await that could yield (e.g., build_automation + # waiting for variables from other components). If the hub's priority decays while + # yielding, deferred entity jobs may add cluster list globals that reference these + # attribute lists before they're declared. + await _attr_to_code(config) + var = cg.new_Pvariable(config[CONF_ID]) if on_join_config := config.get(CONF_ON_JOIN): @@ -186,7 +193,6 @@ async def zephyr_to_code(config: ConfigType) -> None: await cg.register_component(var, config) - await _attr_to_code(config) CORE.add_job(_ctx_to_code, config) From 641914cdbe646747437f76b428991d028684222e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Feb 2026 17:27:51 -1000 Subject: [PATCH 1054/2030] [uart] Revert UART0 default pin workarounds (fixed in ESP-IDF 5.5.2) (#14363) --- .../uart/uart_component_esp_idf.cpp | 36 +++---------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index ea7a09fee6..8699d37d7a 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -9,7 +9,6 @@ #include "esphome/core/gpio.h" #include "driver/gpio.h" #include "soc/gpio_num.h" -#include "soc/uart_pins.h" #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" @@ -19,13 +18,6 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; -/// Check if a pin number matches one of the default UART0 GPIO pins. -/// These pins may have residual state from the boot console that requires -/// explicit reset before UART reconfiguration (ESP-IDF issue #17459). -static constexpr bool is_default_uart0_pin(int8_t pin_num) { - return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; -} - uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -149,34 +141,12 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; - - // Workaround for ESP-IDF issue: https://github.com/espressif/esp-idf/issues/17459 - // Commit 9ed617fb17 removed gpio_func_sel() calls from uart_set_pin(), which breaks - // UART on default UART0 pins that may have residual state from boot console. - // Reset these pins before configuring UART to ensure they're in a clean state. - if (is_default_uart0_pin(tx)) { - gpio_reset_pin(static_cast<gpio_num_t>(tx)); - } - if (is_default_uart0_pin(rx)) { - gpio_reset_pin(static_cast<gpio_num_t>(rx)); - } - - // Setup pins after reset to configure GPIO direction and pull resistors. - // For UART0 default pins, setup() must always be called because gpio_reset_pin() - // above sets GPIO_MODE_DISABLE which disables the input buffer. Without setup(), - // uart_set_pin() on ESP-IDF 5.4.2+ does not re-enable the input buffer for - // IOMUX-connected pins, so the RX pin cannot receive data (see issue #10132). - // For other pins, only call setup() if pull or open-drain flags are set to avoid - // disturbing the default pin state which breaks some external components (#11823). auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; } const auto mask = gpio::Flags::FLAG_OPEN_DRAIN | gpio::Flags::FLAG_PULLUP | gpio::Flags::FLAG_PULLDOWN; - if (is_default_uart0_pin(pin->get_pin()) || (pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { + if ((pin->get_flags() & mask) != gpio::Flags::FLAG_NONE) { pin->setup(); } }; @@ -186,6 +156,10 @@ void IDFUARTComponent::load_settings(bool dump_config) { setup_pin_if_needed(this->tx_pin_); } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; + int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; + int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; + uint32_t invert = 0; if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) { invert |= UART_SIGNAL_TXD_INV; From 91250fd46cc27ba1f36830b48ef3d6cb61c69970 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 28 Feb 2026 20:37:04 +1100 Subject: [PATCH 1055/2030] [mipi_dsi] Fix Waveshare P4 7B board config (#14372) --- esphome/components/mipi_dsi/models/waveshare.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/mipi_dsi/models/waveshare.py b/esphome/components/mipi_dsi/models/waveshare.py index bf4f9063bb..61829ca9c1 100644 --- a/esphome/components/mipi_dsi/models/waveshare.py +++ b/esphome/components/mipi_dsi/models/waveshare.py @@ -90,8 +90,6 @@ DriverChip( (0xE9, 0xC8, 0x10, 0x0A, 0x00, 0x00, 0x80, 0x81, 0x12, 0x31, 0x23, 0x4F, 0x86, 0xA0, 0x00, 0x47, 0x08, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x98, 0x02, 0x8B, 0xAF, 0x46, 0x02, 0x88, 0x88, 0x88, 0x88, 0x88, 0x98, 0x13, 0x8B, 0xAF, 0x57, 0x13, 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), (0xEA, 0x97, 0x0C, 0x09, 0x09, 0x09, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x31, 0x8B, 0xA8, 0x31, 0x75, 0x88, 0x88, 0x88, 0x88, 0x88, 0x9F, 0x20, 0x8B, 0xA8, 0x20, 0x64, 0x88, 0x88, 0x88, 0x88, 0x88, 0x23, 0x00, 0x00, 0x02, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x81, 0x00, 0x00, 0x00, 0x00), (0xEF, 0xFF, 0xFF, 0x01), - (0x11, 0x00), - (0x29, 0x00), ], ) @@ -109,6 +107,7 @@ DriverChip( lane_bit_rate="900Mbps", no_transform=True, color_order="RGB", + reset_pin=33, initsequence=[ (0x80, 0x8B), (0x81, 0x78), From c9c99a22e0374d5d47a1fc131ce86384a5c038e2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 28 Feb 2026 18:10:53 -0500 Subject: [PATCH 1056/2030] [core] Defer entity automation codegen to prevent sibling ID deadlocks (#14381) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- esphome/components/binary_sensor/__init__.py | 36 +++++++++++-------- esphome/components/number/__init__.py | 31 +++++++++------- esphome/components/sensor/__init__.py | 37 +++++++++++--------- esphome/components/switch/__init__.py | 16 ++++++--- esphome/components/text_sensor/__init__.py | 19 ++++++---- 5 files changed, 83 insertions(+), 56 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index c38d6b78d3..036d78da73 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -550,21 +550,8 @@ def binary_sensor_schema( return _BINARY_SENSOR_SCHEMA.extend(schema) -async def setup_binary_sensor_core_(var, config): - await setup_entity(var, config, "binary_sensor") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) - trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get( - CONF_PUBLISH_INITIAL_STATE, False - ) - cg.add(var.set_trigger_on_initial_state(trigger)) - if inverted := config.get(CONF_INVERTED): - cg.add(var.set_inverted(inverted)) - if filters_config := config.get(CONF_FILTERS): - filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config) - cg.add(var.add_filters(filters)) - +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_binary_sensor_automations(var, config): for conf in config.get(CONF_ON_PRESS, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) @@ -616,6 +603,25 @@ async def setup_binary_sensor_core_(var, config): conf, ) + +async def setup_binary_sensor_core_(var, config): + await setup_entity(var, config, "binary_sensor") + + if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: + cg.add(var.set_device_class(device_class)) + trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get( + CONF_PUBLISH_INITIAL_STATE, False + ) + cg.add(var.set_trigger_on_initial_state(trigger)) + if inverted := config.get(CONF_INVERTED): + cg.add(var.set_inverted(inverted)) + if filters_config := config.get(CONF_FILTERS): + cg.add_define("USE_BINARY_SENSOR_FILTER") + filters = await cg.build_registry_list(FILTER_REGISTRY, filters_config) + cg.add(var.add_filters(filters)) + + CORE.add_job(_build_binary_sensor_automations, var, config) + if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index b23da7799f..d12ec7463b 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -240,6 +240,23 @@ def number_schema( return _NUMBER_SCHEMA.extend(schema) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_number_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_VALUE_RANGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await cg.register_component(trigger, conf) + if CONF_ABOVE in conf: + template_ = await cg.templatable(conf[CONF_ABOVE], [(float, "x")], float) + cg.add(trigger.set_min(template_)) + if CONF_BELOW in conf: + template_ = await cg.templatable(conf[CONF_BELOW], [(float, "x")], float) + cg.add(trigger.set_max(template_)) + await automation.build_automation(trigger, [(float, "x")], conf) + + async def setup_number_core_( var, config, *, min_value: float, max_value: float, step: float ): @@ -254,19 +271,7 @@ async def setup_number_core_( if config[CONF_MODE] != NumberMode.NUMBER_MODE_AUTO: cg.add(var.traits.set_mode(config[CONF_MODE])) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_VALUE_RANGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await cg.register_component(trigger, conf) - if CONF_ABOVE in conf: - template_ = await cg.templatable(conf[CONF_ABOVE], [(float, "x")], float) - cg.add(trigger.set_min(template_)) - if CONF_BELOW in conf: - template_ = await cg.templatable(conf[CONF_BELOW], [(float, "x")], float) - cg.add(trigger.set_max(template_)) - await automation.build_automation(trigger, [(float, "x")], conf) + CORE.add_job(_build_number_automations, var, config) if (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) is not None: cg.add(var.traits.set_unit_of_measurement(unit_of_measurement)) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 03784ba76b..1e5f16a81d 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -888,6 +888,26 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_sensor_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_RAW_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(float, "x")], conf) + for conf in config.get(CONF_ON_VALUE_RANGE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await cg.register_component(trigger, conf) + if (above := conf.get(CONF_ABOVE)) is not None: + template_ = await cg.templatable(above, [(float, "x")], float) + cg.add(trigger.set_min(template_)) + if (below := conf.get(CONF_BELOW)) is not None: + template_ = await cg.templatable(below, [(float, "x")], float) + cg.add(trigger.set_max(template_)) + await automation.build_automation(trigger, [(float, "x")], conf) + + async def setup_sensor_core_(var, config): await setup_entity(var, config, "sensor") @@ -906,22 +926,7 @@ async def setup_sensor_core_(var, config): filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_VALUE_RANGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await cg.register_component(trigger, conf) - if (above := conf.get(CONF_ABOVE)) is not None: - template_ = await cg.templatable(above, [(float, "x")], float) - cg.add(trigger.set_min(template_)) - if (below := conf.get(CONF_BELOW)) is not None: - template_ = await cg.templatable(below, [(float, "x")], float) - cg.add(trigger.set_max(template_)) - await automation.build_automation(trigger, [(float, "x")], conf) + CORE.add_job(_build_sensor_automations, var, config) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 7424d7c92f..cfc5e2b6e8 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -141,11 +141,8 @@ def switch_schema( return _SWITCH_SCHEMA.extend(schema) -async def setup_switch_core_(var, config): - await setup_entity(var, config, "switch") - - if (inverted := config.get(CONF_INVERTED)) is not None: - cg.add(var.set_inverted(inverted)) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_switch_automations(var, config): for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(bool, "x")], conf) @@ -156,6 +153,15 @@ async def setup_switch_core_(var, config): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + +async def setup_switch_core_(var, config): + await setup_entity(var, config, "switch") + + if (inverted := config.get(CONF_INVERTED)) is not None: + cg.add(var.set_inverted(inverted)) + + CORE.add_job(_build_switch_automations, var, config) + if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 0d22400a8e..58c293e67b 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -197,6 +197,17 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +@coroutine_with_priority(CoroPriority.AUTOMATION) +async def _build_text_sensor_automations(var, config): + for conf in config.get(CONF_ON_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + + for conf in config.get(CONF_ON_RAW_VALUE, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + + async def setup_text_sensor_core_(var, config): await setup_entity(var, config, "text_sensor") @@ -207,13 +218,7 @@ async def setup_text_sensor_core_(var, config): filters = await build_filters(config[CONF_FILTERS]) cg.add(var.set_filters(filters)) - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + CORE.add_job(_build_text_sensor_automations, var, config) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) From 0ac61cbb9bed23de4b97611a1b78e3e303267201 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 1 Mar 2026 10:23:10 -1000 Subject: [PATCH 1057/2030] [improv_serial] Add missing USE_IMPROV_SERIAL define to fix WiFi scan filtering (#14359) --- esphome/components/improv_serial/__init__.py | 1 + esphome/components/wifi/wifi_component.cpp | 2 +- esphome/components/wifi/wifi_component.h | 4 ++-- esphome/components/wifi/wifi_component_esp8266.cpp | 2 +- esphome/components/wifi/wifi_component_esp_idf.cpp | 2 +- esphome/components/wifi/wifi_component_libretiny.cpp | 2 +- esphome/components/wifi/wifi_component_pico_w.cpp | 9 +++++++-- esphome/core/defines.h | 1 + 8 files changed, 15 insertions(+), 8 deletions(-) diff --git a/esphome/components/improv_serial/__init__.py b/esphome/components/improv_serial/__init__.py index 9a2ac2f40f..4266f5b78b 100644 --- a/esphome/components/improv_serial/__init__.py +++ b/esphome/components/improv_serial/__init__.py @@ -43,3 +43,4 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await improv_base.setup_improv_core(var, config, "improv_serial") + cg.add_define("USE_IMPROV_SERIAL") diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 61d05d7635..fbc1e946bb 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2048,7 +2048,7 @@ bool WiFiComponent::can_proceed() { #endif void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } -bool WiFiComponent::is_connected() { +bool WiFiComponent::is_connected() const { return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_; } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index ac28a1bc81..2e285289e7 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -430,7 +430,7 @@ class WiFiComponent : public Component { void set_reboot_timeout(uint32_t reboot_timeout); - bool is_connected(); + bool is_connected() const; void set_power_save_mode(WiFiPowerSaveMode power_save); void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; } @@ -665,7 +665,7 @@ class WiFiComponent : public Component { bool wifi_apply_hostname_(); bool wifi_sta_connect_(const WiFiAP &ap); void wifi_pre_setup_(); - WiFiSTAConnectStatus wifi_sta_connect_status_(); + WiFiSTAConnectStatus wifi_sta_connect_status_() const; bool wifi_scan_start_(bool passive); #ifdef USE_WIFI_AP diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index cbf7d7d80f..7fe090c45c 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -626,7 +626,7 @@ void WiFiComponent::wifi_pre_setup_() { this->wifi_mode_(false, false); } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { station_status_t status = wifi_station_get_connect_status(); if (status == STATION_GOT_IP) return WiFiSTAConnectStatus::CONNECTED; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 52ee482121..f594c13afe 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -914,7 +914,7 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { } } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { if (s_sta_connected && this->got_ipv4_address_) { #if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) if (this->num_ipv6_addresses_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT) { diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 2cc05928af..71cc419107 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -621,7 +621,7 @@ void WiFiComponent::wifi_pre_setup_() { // Make sure WiFi is in clean state before anything starts this->wifi_mode_(false, false); } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { // Use state machine instead of querying WiFi.status() directly // State is updated in main loop from queued events, ensuring thread safety switch (s_sta_state) { diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 1baf21e2b2..7a93de5728 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -115,8 +115,13 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "UNKNOWN"; } -WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() { - int status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); +WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { + // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino + // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif + // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's + // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. + // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. + int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: case CYW43_LINK_NOIP: diff --git a/esphome/core/defines.h b/esphome/core/defines.h index bfa33e4e59..e7d5caf7c2 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -52,6 +52,7 @@ #define USE_HOMEASSISTANT_TIME #define USE_HTTP_REQUEST_OTA_WATCHDOG_TIMEOUT 8000 // NOLINT #define USE_IMAGE +#define USE_IMPROV_SERIAL #define USE_IMPROV_SERIAL_NEXT_URL #define USE_INFRARED #define USE_IR_RF From d2a819eb77c966dc2d4675c49a7023ffa40d80a1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:52:06 -0500 Subject: [PATCH 1058/2030] [uart] Fix flow_control_pin inverted flag ignored on ESP-IDF (#14410) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/uart/uart_component_esp_idf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 8699d37d7a..7e34f835cd 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -167,6 +167,9 @@ void IDFUARTComponent::load_settings(bool dump_config) { if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted()) { invert |= UART_SIGNAL_RXD_INV; } + if (this->flow_control_pin_ != nullptr && this->flow_control_pin_->is_inverted()) { + invert |= UART_SIGNAL_RTS_INV; + } err = uart_set_line_inverse(this->uart_num_, invert); if (err != ESP_OK) { From dc56cd1d1fc39c2ca0beb5bfb8b0e19b8e4ff4a1 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Mar 2026 08:57:52 +1300 Subject: [PATCH 1059/2030] Bump version to 2026.2.3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 2de0460ef1..5f351c1bbb 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.2 +PROJECT_NUMBER = 2026.2.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index ea8d2b73be..aaa34b2fd1 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.2" +__version__ = "2026.2.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From d1de50c0e513431943607f678fc3f661aa605dd0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 11:11:04 -1000 Subject: [PATCH 1060/2030] [core] Add ESP8266 support to wake_loop_any_context() (#14392) --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 2 +- esphome/components/socket/socket.h | 5 +++-- esphome/core/application.h | 12 +++++++++++- esphome/core/component.cpp | 9 +++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 430356592f..d697bd47a5 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -36,7 +36,7 @@ void socket_delay(uint32_t ms) { esp_delay(ms, []() { return !s_socket_woke; }); } -void socket_wake() { +void IRAM_ATTR socket_wake() { s_socket_woke = true; esp_schedule(); } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 86a4f0cba9..546d278260 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -86,8 +86,9 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s /// On ESP8266, lwip callbacks set a flag and call esp_schedule() to wake the delay. void socket_delay(uint32_t ms); -/// Called by lwip callbacks to signal socket activity and wake delay. -void socket_wake(); +/// Signal socket/IO activity and wake the main loop from esp_delay() early. +/// ISR-safe: uses IRAM_ATTR internally and only sets a volatile flag + esp_schedule(). +void socket_wake(); // NOLINT(readability-redundant-declaration) #endif } // namespace esphome::socket diff --git a/esphome/core/application.h b/esphome/core/application.h index 13fd0180ab..63d59c555e 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -34,7 +34,11 @@ #endif #endif #endif // USE_SOCKET_SELECT_SUPPORT - +#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +namespace esphome::socket { +void socket_wake(); // NOLINT(readability-redundant-declaration) +} // namespace esphome::socket +#endif #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif @@ -530,6 +534,12 @@ class Application { #endif #endif +#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) + /// Wake the main event loop from any context (ISR, thread, or main loop). + /// On ESP8266: sets the socket wake flag and calls esp_schedule() to exit esp_delay() early. + static void IRAM_ATTR wake_loop_any_context() { socket::socket_wake(); } +#endif + protected: friend Component; #ifdef USE_SOCKET_SELECT_SUPPORT diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index a71aa8b3a3..53cb50a44c 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -323,10 +323,11 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // 8. Race condition with main loop is handled by clearing flag before processing this->pending_enable_loop_ = true; App.has_pending_enable_loop_requests_ = true; -#if defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32) - // Wake the main loop if sleeping in ulTaskNotifyTake(). Without this, - // the main loop would not wake until the select timeout expires (~16ms). - // Uses xPortInIsrContext() to choose the correct FreeRTOS notify API. +#if (defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32)) || (defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP)) + // Wake the main loop from sleep. Without this, the main loop would not + // wake until the select/delay timeout expires (~16ms). + // ESP32: uses xPortInIsrContext() to choose the correct FreeRTOS notify API. + // ESP8266: sets socket wake flag and calls esp_schedule() to exit esp_delay() early. Application::wake_loop_any_context(); #endif } From 3615a7b90c13f2bb100d5ea3241795aec5c7512b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 11:42:25 -1000 Subject: [PATCH 1061/2030] [core] Eliminate __udivdi3 in millis() on ESP32 and RP2040 (#14409) --- esphome/components/esp32/core.cpp | 4 +- esphome/components/rp2040/core.cpp | 4 +- esphome/core/helpers.h | 38 ++++++++++++ .../fixtures/micros_to_millis.yaml | 61 +++++++++++++++++++ tests/integration/test_micros_to_millis.py | 46 ++++++++++++++ 5 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 tests/integration/fixtures/micros_to_millis.yaml create mode 100644 tests/integration/test_micros_to_millis.py diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 59b791da40..7ebbba609e 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -22,8 +22,8 @@ extern "C" __attribute__((weak)) void initArduino() {} namespace esphome { void HOT yield() { vPortYield(); } -uint32_t IRAM_ATTR HOT millis() { return (uint32_t) (esp_timer_get_time() / 1000ULL); } -uint64_t HOT millis_64() { return static_cast<uint64_t>(esp_timer_get_time()) / 1000ULL; } +uint32_t IRAM_ATTR HOT millis() { return micros_to_millis(static_cast<uint64_t>(esp_timer_get_time())); } +uint64_t HOT millis_64() { return micros_to_millis<uint64_t>(static_cast<uint64_t>(esp_timer_get_time())); } void HOT delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } uint32_t IRAM_ATTR HOT micros() { return (uint32_t) esp_timer_get_time(); } void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 6386d53292..a15ee7e263 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -11,8 +11,8 @@ namespace esphome { void HOT yield() { ::yield(); } -uint64_t millis_64() { return time_us_64() / 1000ULL; } -uint32_t HOT millis() { return static_cast<uint32_t>(millis_64()); } +uint64_t millis_64() { return micros_to_millis<uint64_t>(time_us_64()); } +uint32_t HOT millis() { return micros_to_millis(time_us_64()); } void HOT delay(uint32_t ms) { ::delay(ms); } uint32_t HOT micros() { return ::micros(); } void HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index c68cb549bb..ae505a2d8a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -599,6 +599,44 @@ template<std::integral T> constexpr uint32_t fnv1a_hash_extend(uint32_t hash, T constexpr uint32_t fnv1a_hash(const char *str) { return fnv1a_hash_extend(FNV1_OFFSET_BASIS, str); } inline uint32_t fnv1a_hash(const std::string &str) { return fnv1a_hash(str.c_str()); } +/// Convert a 64-bit microsecond count to milliseconds without calling +/// __udivdi3 (software 64-bit divide, ~1200 ns on Xtensa @ 240 MHz). +/// +/// Returns uint32_t by default (for millis()), or uint64_t when requested +/// (for millis_64()). The only difference is whether hi * Q is truncated +/// to 32 bits or widened to 64. +/// +/// On 32-bit targets, GCC does not optimize 64-bit constant division into a +/// multiply-by-reciprocal. Since 1000 = 8 * 125, we first right-shift by 3 +/// (free divide-by-8), then use the Euclidean division identity to decompose +/// the remaining 64-bit divide-by-125 into a single 32-bit division: +/// +/// floor(us / 1000) = floor(floor(us / 8) / 125) [exact for integers] +/// 2^32 = Q * 125 + R (34359738 * 125 + 46) +/// (hi * 2^32 + lo) / 125 = hi * Q + (hi * R + lo) / 125 +/// +/// GCC optimizes the remaining 32-bit "/ 125U" into a multiply-by-reciprocal +/// (mulhu + shift), so no division instruction is emitted. +/// +/// Safe for us up to ~3.2e18 (~101,700 years of microseconds). +/// +/// See: https://en.wikipedia.org/wiki/Euclidean_division +/// See: https://ridiculousfish.com/blog/posts/labor-of-division-episode-iii.html +template<typename ReturnT = uint32_t> inline constexpr ESPHOME_ALWAYS_INLINE ReturnT micros_to_millis(uint64_t us) { + constexpr uint32_t d = 125U; + constexpr uint32_t q = static_cast<uint32_t>((1ULL << 32) / d); // 34359738 + constexpr uint32_t r = static_cast<uint32_t>((1ULL << 32) % d); // 46 + // 1000 = 8 * 125; divide-by-8 is a free shift + uint64_t x = us >> 3; + uint32_t lo = static_cast<uint32_t>(x); + uint32_t hi = static_cast<uint32_t>(x >> 32); + // Combine remainder term: hi * (2^32 % 125) + lo + uint32_t adj = hi * r + lo; + // If adj overflowed, the true value is 2^32 + adj; apply the identity again + // static_cast<ReturnT>(hi) widens to 64-bit when ReturnT=uint64_t, preserving upper bits of hi*q + return static_cast<ReturnT>(hi) * q + (adj < lo ? (adj + r) / d + q : adj / d); +} + /// Return a random 32-bit unsigned integer. uint32_t random_uint32(); /// Return a random float between 0 and 1. diff --git a/tests/integration/fixtures/micros_to_millis.yaml b/tests/integration/fixtures/micros_to_millis.yaml new file mode 100644 index 0000000000..d11808c43a --- /dev/null +++ b/tests/integration/fixtures/micros_to_millis.yaml @@ -0,0 +1,61 @@ +esphome: + name: micros-to-millis-test + platformio_options: + build_flags: + - "-DDEBUG" + on_boot: + - lambda: |- + using esphome::micros_to_millis; + const char *TAG = "MTM"; + int pass = 0, fail = 0; + + auto check = [&](const char *name, uint64_t us) { + uint32_t got = micros_to_millis(us); + uint32_t want = (uint32_t)(us / 1000ULL); + if (got == want) { pass++; } + else { ESP_LOGE(TAG, "%s FAILED: got=%u want=%u", name, got, want); fail++; } + }; + + // Basic values + check("zero", 0); + check("below_1ms", 999); + check("exactly_1ms", 1000); + check("above_1ms", 1001); + + // Shift boundary (1000 = 8 * 125, exercises the >>3 shift) + check("shift_7999", 7999); + check("shift_8000", 8000); + check("shift_8001", 8001); + + // 32-bit boundary + check("u32max_minus1", 0xFFFFFFFEULL); + check("u32max", 0xFFFFFFFFULL); + check("u32max_plus1", 0x100000000ULL); + + // Realistic uptimes + check("30_days", 2592000000000ULL); + check("1_year", 31536000000000ULL); + + // Carry path: construct x = us>>3 with specific hi/lo that trigger adj overflow + { uint64_t x = (603ULL << 32) | 0xFFFFFFFFU; check("carry_603", x << 3); } + { uint64_t x = (5000ULL << 32) | 0xFFFFFFFFU; check("carry_5000", x << 3); } + + // Carry boundary: exact transition where adj overflows (hi=1000, R=46) + { + uint32_t hi = 1000; + uint32_t thr = 0xFFFFFFFFU - hi * 46U; + uint64_t h = (uint64_t)hi << 32; + check("carry_before", (h | (thr - 1)) << 3); + check("carry_at", (h | thr) << 3); + check("carry_after", (h | (thr + 1)) << 3); + } + + // Mod-8 variations (exercises the >>3 truncation) + for (int i = 0; i < 8; i++) { check("mod8", 2592000000000ULL + i); } + + if (fail == 0) { ESP_LOGI(TAG, "ALL_PASSED %d tests", pass); } + else { ESP_LOGE(TAG, "%d FAILED out of %d", fail, pass + fail); } + +host: +api: +logger: diff --git a/tests/integration/test_micros_to_millis.py b/tests/integration/test_micros_to_millis.py new file mode 100644 index 0000000000..9960d6b017 --- /dev/null +++ b/tests/integration/test_micros_to_millis.py @@ -0,0 +1,46 @@ +"""Integration test for micros_to_millis Euclidean decomposition.""" + +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_micros_to_millis( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that micros_to_millis matches reference uint64 division.""" + + all_passed = asyncio.Event() + failures: list[str] = [] + + def on_log_line(line: str) -> None: + clean_line = re.sub(r"\x1b\[[0-9;]*m", "", line) + if "ALL_PASSED" in clean_line: + all_passed.set() + elif "FAILED" in clean_line and "[MTM" in clean_line: + failures.append(clean_line) + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "micros-to-millis-test" + + try: + await asyncio.wait_for(all_passed.wait(), timeout=2.0) + except TimeoutError: + if failures: + pytest.fail(f"micros_to_millis failures: {failures}") + pytest.fail("micros_to_millis test timed out") + + assert not failures, f"micros_to_millis failures: {failures}" From 5510b45f3bfa45e3204de607e0a3815b42623606 Mon Sep 17 00:00:00 2001 From: Lino Schmidt <72667500+LinoSchmidt@users.noreply.github.com> Date: Mon, 2 Mar 2026 22:43:06 +0100 Subject: [PATCH 1062/2030] [const] Move CONF_WATCHDOG (#14415) --- esphome/components/as5600/__init__.py | 2 +- esphome/components/as5600/sensor/__init__.py | 1 - esphome/const.py | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/as5600/__init__.py b/esphome/components/as5600/__init__.py index acb1c4d9db..b141329e94 100644 --- a/esphome/components/as5600/__init__.py +++ b/esphome/components/as5600/__init__.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_ID, CONF_POWER_MODE, CONF_RANGE, + CONF_WATCHDOG, ) CODEOWNERS = ["@ammmze"] @@ -57,7 +58,6 @@ FAST_FILTER = { CONF_RAW_ANGLE = "raw_angle" CONF_RAW_POSITION = "raw_position" -CONF_WATCHDOG = "watchdog" CONF_SLOW_FILTER = "slow_filter" CONF_FAST_FILTER = "fast_filter" CONF_START_POSITION = "start_position" diff --git a/esphome/components/as5600/sensor/__init__.py b/esphome/components/as5600/sensor/__init__.py index 1491852e07..e84733a484 100644 --- a/esphome/components/as5600/sensor/__init__.py +++ b/esphome/components/as5600/sensor/__init__.py @@ -23,7 +23,6 @@ AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingCompone CONF_RAW_ANGLE = "raw_angle" CONF_RAW_POSITION = "raw_position" -CONF_WATCHDOG = "watchdog" CONF_SLOW_FILTER = "slow_filter" CONF_FAST_FILTER = "fast_filter" CONF_PWM_FREQUENCY = "pwm_frequency" diff --git a/esphome/const.py b/esphome/const.py index 7262a106d8..bbd85ca66b 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1094,6 +1094,7 @@ CONF_WAND_ID = "wand_id" CONF_WARM_WHITE = "warm_white" CONF_WARM_WHITE_COLOR_TEMPERATURE = "warm_white_color_temperature" CONF_WARMUP_TIME = "warmup_time" +CONF_WATCHDOG = "watchdog" CONF_WATCHDOG_THRESHOLD = "watchdog_threshold" CONF_WATCHDOG_TIMEOUT = "watchdog_timeout" CONF_WATER_HEATER = "water_heater" From 727fa073777cb758dd580fd9ea31a664fc58133f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Mar 2026 11:44:53 -1000 Subject: [PATCH 1063/2030] Bump github/codeql-action from 4.32.4 to 4.32.5 (#14416) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5d7c32eaa9..4bd018b5c9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4 + uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 with: category: "/language:${{matrix.language}}" From 2e623fd6c3f83870ddeac768b855cbf3ba51e517 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 11:48:50 -1000 Subject: [PATCH 1064/2030] [tests] Fix flaky log assertion race in oversized payload tests (#14414) --- tests/integration/test_oversized_payloads.py | 69 ++++++++++++-------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/tests/integration/test_oversized_payloads.py b/tests/integration/test_oversized_payloads.py index 8bf890261a..be488347aa 100644 --- a/tests/integration/test_oversized_payloads.py +++ b/tests/integration/test_oversized_payloads.py @@ -17,10 +17,10 @@ async def test_oversized_payload_plaintext( ) -> None: """Test that oversized payloads (>32768 bytes) from client cause disconnection without crashing.""" process_exited = False - helper_log_found = False + helper_log_event = asyncio.Event() def check_logs(line: str) -> None: - nonlocal process_exited, helper_log_found + nonlocal process_exited # Check for signs that the process exited/crashed if "Segmentation fault" in line or "core dumped" in line: process_exited = True @@ -30,7 +30,7 @@ async def test_oversized_payload_plaintext( and "Bad packet: message size" in line and "exceeds maximum" in line ): - helper_log_found = True + helper_log_event.set() async with run_compiled(yaml_config, line_callback=check_logs): async with api_client_connected_with_disconnect() as (client, disconnect_event): @@ -54,10 +54,13 @@ async def test_oversized_payload_plaintext( # After disconnection, verify process didn't crash assert not process_exited, "ESPHome process should not crash" - # Verify we saw the expected HELPER_LOG message - assert helper_log_found, ( - "Expected to see HELPER_LOG about message size exceeding maximum" - ) + # Wait for the expected log message (may arrive after disconnect event) + try: + await asyncio.wait_for(helper_log_event.wait(), timeout=2.0) + except TimeoutError: + pytest.fail( + "Expected to see HELPER_LOG about message size exceeding maximum" + ) # Try to reconnect to verify the process is still running async with api_client_connected_with_disconnect() as (client2, _): @@ -77,10 +80,10 @@ async def test_oversized_protobuf_message_id_plaintext( This tests the message type limit - message IDs must fit in a uint16_t (0-65535). """ process_exited = False - helper_log_found = False + helper_log_event = asyncio.Event() def check_logs(line: str) -> None: - nonlocal process_exited, helper_log_found + nonlocal process_exited # Check for signs that the process exited/crashed if "Segmentation fault" in line or "core dumped" in line: process_exited = True @@ -90,7 +93,7 @@ async def test_oversized_protobuf_message_id_plaintext( and "Bad packet: message type" in line and "exceeds maximum" in line ): - helper_log_found = True + helper_log_event.set() async with run_compiled(yaml_config, line_callback=check_logs): async with api_client_connected_with_disconnect() as (client, disconnect_event): @@ -114,10 +117,13 @@ async def test_oversized_protobuf_message_id_plaintext( # After disconnection, verify process didn't crash assert not process_exited, "ESPHome process should not crash" - # Verify we saw the expected HELPER_LOG message - assert helper_log_found, ( - "Expected to see HELPER_LOG about message type exceeding maximum" - ) + # Wait for the expected log message (may arrive after disconnect event) + try: + await asyncio.wait_for(helper_log_event.wait(), timeout=2.0) + except TimeoutError: + pytest.fail( + "Expected to see HELPER_LOG about message type exceeding maximum" + ) # Try to reconnect to verify the process is still running async with api_client_connected_with_disconnect() as (client2, _): @@ -135,10 +141,10 @@ async def test_oversized_payload_noise( """Test that oversized payloads from client cause disconnection without crashing with noise encryption.""" noise_key = "N4Yle5YirwZhPiHHsdZLdOA73ndj/84veVaLhTvxCuU=" process_exited = False - helper_log_found = False + helper_log_event = asyncio.Event() def check_logs(line: str) -> None: - nonlocal process_exited, helper_log_found + nonlocal process_exited # Check for signs that the process exited/crashed if "Segmentation fault" in line or "core dumped" in line: process_exited = True @@ -149,7 +155,7 @@ async def test_oversized_payload_noise( and "Bad packet: message size" in line and "exceeds maximum" in line ): - helper_log_found = True + helper_log_event.set() async with run_compiled(yaml_config, line_callback=check_logs): async with api_client_connected_with_disconnect(noise_psk=noise_key) as ( @@ -177,10 +183,13 @@ async def test_oversized_payload_noise( # After disconnection, verify process didn't crash assert not process_exited, "ESPHome process should not crash" - # Verify we saw the expected HELPER_LOG message - assert helper_log_found, ( - "Expected to see HELPER_LOG about message size exceeding maximum" - ) + # Wait for the expected log message (may arrive after disconnect event) + try: + await asyncio.wait_for(helper_log_event.wait(), timeout=2.0) + except TimeoutError: + pytest.fail( + "Expected to see HELPER_LOG about message size exceeding maximum" + ) # Try to reconnect to verify the process is still running async with api_client_connected_with_disconnect(noise_psk=noise_key) as ( @@ -274,10 +283,10 @@ async def test_noise_corrupt_encrypted_frame( """ noise_key = "N4Yle5YirwZhPiHHsdZLdOA73ndj/84veVaLhTvxCuU=" process_exited = False - cipherstate_failed = False + cipherstate_event = asyncio.Event() def check_logs(line: str) -> None: - nonlocal process_exited, cipherstate_failed + nonlocal process_exited # Check for signs that the process exited/crashed if "Segmentation fault" in line or "core dumped" in line: process_exited = True @@ -290,7 +299,7 @@ async def test_noise_corrupt_encrypted_frame( "[W][api.connection" in line and "Reading failed CIPHERSTATE_DECRYPT_FAILED" in line ): - cipherstate_failed = True + cipherstate_event.set() async with run_compiled(yaml_config, line_callback=check_logs): async with api_client_connected_with_disconnect(noise_psk=noise_key) as ( @@ -326,10 +335,14 @@ async def test_noise_corrupt_encrypted_frame( assert not process_exited, ( "ESPHome process should not crash on corrupt encrypted frames" ) - # Verify we saw the expected log message about decryption failure - assert cipherstate_failed, ( - "Expected to see log about noise_cipherstate_decrypt failure or CIPHERSTATE_DECRYPT_FAILED" - ) + # Wait for the expected log message (may arrive after disconnect event) + try: + await asyncio.wait_for(cipherstate_event.wait(), timeout=2.0) + except TimeoutError: + pytest.fail( + "Expected to see log about noise_cipherstate_decrypt failure" + " or CIPHERSTATE_DECRYPT_FAILED" + ) # Verify we can still reconnect after handling the corrupt frame async with api_client_connected_with_disconnect(noise_psk=noise_key) as ( From 7a87348855aa7d49dc77926868717e0343bdb47a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 2 Mar 2026 16:49:14 -0500 Subject: [PATCH 1065/2030] [ci] Skip PR title check for dependabot PRs (#14418) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .github/workflows/pr-title-check.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml index f23c2c870e..198b9a6b25 100644 --- a/.github/workflows/pr-title-check.yml +++ b/.github/workflows/pr-title-check.yml @@ -26,14 +26,19 @@ jobs: } = require('./.github/scripts/detect-tags.js'); const title = context.payload.pull_request.title; + const author = context.payload.pull_request.user.login; + + // Skip bot PRs (e.g. dependabot) - they have their own title format + if (author === 'dependabot[bot]') { + return; + } // Block titles starting with "word:" or "word(scope):" patterns const commitStylePattern = /^\w+(\(.*?\))?[!]?\s*:/; if (commitStylePattern.test(title)) { core.setFailed( `PR title should not start with a "prefix:" style format.\n` + - `Please use the format: [component] Brief description\n` + - `Example: [pn532] Add health checking and auto-reset` + `Please use the format: [component] Brief description\n` ); return; } From 97d713ee6477c003a8241b0452c1bcf2d6557289 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Mon, 2 Mar 2026 19:16:38 -0600 Subject: [PATCH 1066/2030] [media_source] Add new Media Source platform component (#14417) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/media_source/__init__.py | 40 +++++ .../components/media_source/media_source.h | 159 ++++++++++++++++++ esphome/core/defines.h | 1 + 4 files changed, 201 insertions(+) create mode 100644 esphome/components/media_source/__init__.py create mode 100644 esphome/components/media_source/media_source.h diff --git a/CODEOWNERS b/CODEOWNERS index 4c97b7f99d..21bee125c6 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -316,6 +316,7 @@ esphome/components/mcp9808/* @k7hpn esphome/components/md5/* @esphome/core esphome/components/mdns/* @esphome/core esphome/components/media_player/* @jesserockz +esphome/components/media_source/* @kahrendt esphome/components/micro_wake_word/* @jesserockz @kahrendt esphome/components/micronova/* @edenhaus @jorre05 esphome/components/microphone/* @jesserockz @kahrendt diff --git a/esphome/components/media_source/__init__.py b/esphome/components/media_source/__init__.py new file mode 100644 index 0000000000..43256db4af --- /dev/null +++ b/esphome/components/media_source/__init__.py @@ -0,0 +1,40 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ID +from esphome.core import CORE +from esphome.coroutine import CoroPriority, coroutine_with_priority +from esphome.cpp_generator import MockObjClass + +CODEOWNERS = ["@kahrendt"] + +AUTO_LOAD = ["audio"] + +IS_PLATFORM_COMPONENT = True + +media_source_ns = cg.esphome_ns.namespace("media_source") + +MediaSource = media_source_ns.class_("MediaSource") + + +async def register_media_source(var, config): + if not CORE.has_id(config[CONF_ID]): + var = cg.Pvariable(config[CONF_ID], var) + CORE.register_platform_component("media_source", var) + return var + + +_MEDIA_SOURCE_SCHEMA = cv.Schema({}) + + +def media_source_schema( + class_: MockObjClass, +) -> cv.Schema: + schema = {cv.GenerateID(CONF_ID): cv.declare_id(class_)} + + return _MEDIA_SOURCE_SCHEMA.extend(schema) + + +@coroutine_with_priority(CoroPriority.CORE) +async def to_code(config): + cg.add_global(media_source_ns.using) + cg.add_define("USE_MEDIA_SOURCE") diff --git a/esphome/components/media_source/media_source.h b/esphome/components/media_source/media_source.h new file mode 100644 index 0000000000..688c27134f --- /dev/null +++ b/esphome/components/media_source/media_source.h @@ -0,0 +1,159 @@ +#pragma once + +#include "esphome/components/audio/audio.h" +#include "esphome/core/helpers.h" + +#include <cstdint> +#include <string> + +namespace esphome::media_source { + +enum class MediaSourceState : uint8_t { + IDLE, // Not playing, ready to accept play_uri + PLAYING, // Currently playing media + PAUSED, // Playback paused, can be resumed + ERROR, // Error occurred during playback; sources are responsible for logging their own error details +}; + +/// @brief Commands that are sent from the orchestrator to a media source +enum class MediaSourceCommand : uint8_t { + // All sources should support these basic commands. + PLAY, + PAUSE, + STOP, + + // Only sources with internal playlists will handle these; simple sources should ignore them. + NEXT, + PREVIOUS, + CLEAR_PLAYLIST, + REPEAT_ALL, + REPEAT_ONE, + REPEAT_OFF, + SHUFFLE, + UNSHUFFLE, +}; + +/// @brief Callbacks from a MediaSource to its orchestrator +class MediaSourceListener { + public: + virtual ~MediaSourceListener() = default; + + // Callbacks that all sources use to send data and state changes to the orchestrator. + /// @brief Send audio data to the listener + virtual size_t write_audio(const uint8_t *data, size_t length, uint32_t timeout_ms, + const audio::AudioStreamInfo &stream_info) = 0; + /// @brief Notify listener of state changes + virtual void report_state(MediaSourceState state) = 0; + + // Callbacks from smart sources requesting the orchestrator to change volume, mute, or start a new URI. + // Simple sources never invoke these. + /// @brief Request the orchestrator to change volume + virtual void request_volume(float volume) {} + /// @brief Request the orchestrator to change mute state + virtual void request_mute(bool is_muted) {} + /// @brief Request the orchestrator to play a new URI + virtual void request_play_uri(const std::string &uri) {} +}; + +/// @brief Abstract base class for media sources +/// MediaSource provides audio data to an orchestrator via the MediaSourceListener interface. It also receives commands +/// from the orchestrator to control playback. +class MediaSource { + public: + virtual ~MediaSource() = default; + + // === Playback Control === + + /// @brief Start playing the given URI + /// Sources should validate the URI and state, returning false if the source is busy. + /// The orchestrator is responsible for stopping active sources before starting a new one. + /// @param uri URI to play; e.g., "http://stream_url" + /// @return true if playback started successfully, false otherwise + virtual bool play_uri(const std::string &uri) = 0; + + /// @brief Handle playback commands (pause, stop, next, etc.) + /// @param command Command to execute + virtual void handle_command(MediaSourceCommand command) = 0; + + /// @brief Whether this source manages its own playlist internally + /// Smart sources that handle next/previous/repeat/shuffle should override this to return true. + virtual bool has_internal_playlist() const { return false; } + + // === State Access === + + /// @brief Get current playback state (must only be called from the main loop) + /// @return Current state of this source + MediaSourceState get_state() const { return this->state_; } + + // === URI Matching === + + /// @brief Check if this source can handle the given URI + /// Each source must override this to match its supported URI scheme(s). + /// @param uri URI to check + /// @return true if this source can handle the URI + virtual bool can_handle(const std::string &uri) const = 0; + + // === Listener: Source -> Orchestrator === + + /// @brief Set the listener that receives callbacks from this source + /// @param listener Pointer to the MediaSourceListener implementation + void set_listener(MediaSourceListener *listener) { this->listener_ = listener; } + + /// @brief Check if a listener has been registered + bool has_listener() const { return this->listener_ != nullptr; } + + /// @brief Write audio data to the listener + /// @param data Pointer to audio data buffer (not modified by this method) + /// @param length Number of bytes to write + /// @param timeout_ms Milliseconds to wait if the listener can't accept data immediately + /// @param stream_info Audio stream format information + /// @return Number of bytes written, or 0 if no listener is set + size_t write_output(const uint8_t *data, size_t length, uint32_t timeout_ms, + const audio::AudioStreamInfo &stream_info) { + if (this->listener_ != nullptr) { + return this->listener_->write_audio(data, length, timeout_ms, stream_info); + } + return 0; + } + + // === Callbacks: Orchestrator -> Source === + + /// @brief Notify the source that volume changed + /// Simple sources ignore this. Override for smart sources that track volume state. + /// @param volume New volume level (0.0 to 1.0) + virtual void notify_volume_changed(float volume) {} + + /// @brief Notify the source that mute state changed + /// Simple sources ignore this. Override for smart sources that track mute state. + /// @param is_muted New mute state + virtual void notify_mute_changed(bool is_muted) {} + + /// @brief Notify the source about audio that has been played + /// Called when the speaker reports that audio frames have been written to the DAC. + /// Sources can override this to track playback progress for synchronization. + /// @param frames Number of audio frames that were played + /// @param timestamp System time in microseconds when the frames finished writing to the DAC + virtual void notify_audio_played(uint32_t frames, int64_t timestamp) {} + + protected: + /// @brief Update state and notify listener (must only be called from the main loop) + /// This is the only way to change state_, ensuring listener notifications always fire. + /// Sources running FreeRTOS tasks should signal via event groups and call this from loop(). + /// @param state New state to set + void set_state_(MediaSourceState state) { + if (this->state_ != state) { + this->state_ = state; + if (this->listener_ != nullptr) { + this->listener_->report_state(state); + } + } + } + + private: + // Private to enforce the invariant that listener notifications always fire on state changes. + // All state transitions must go through set_state_() which couples the update with notification. + MediaSourceState state_{MediaSourceState::IDLE}; + MediaSourceListener *listener_{nullptr}; +}; + +} // namespace esphome::media_source diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 8c78afa7d4..7fbc5a0b53 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -106,6 +106,7 @@ #define MDNS_DYNAMIC_TXT_COUNT 2 #define SNTP_SERVER_COUNT 3 #define USE_MEDIA_PLAYER +#define USE_MEDIA_SOURCE #define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER #define USE_OUTPUT From c77241940b701e8a8c5709374340c80b75e7e7c6 Mon Sep 17 00:00:00 2001 From: melak <ice@extreme.hu> Date: Tue, 3 Mar 2026 02:24:00 +0100 Subject: [PATCH 1067/2030] [lps22] Add support for the LPS22DF variant (#14397) --- esphome/components/lps22/lps22.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/lps22/lps22.cpp b/esphome/components/lps22/lps22.cpp index 7fc5774b08..592b7faaf0 100644 --- a/esphome/components/lps22/lps22.cpp +++ b/esphome/components/lps22/lps22.cpp @@ -8,6 +8,7 @@ static constexpr const char *const TAG = "lps22"; static constexpr uint8_t WHO_AM_I = 0x0F; static constexpr uint8_t LPS22HB_ID = 0xB1; static constexpr uint8_t LPS22HH_ID = 0xB3; +static constexpr uint8_t LPS22DF_ID = 0xB4; static constexpr uint8_t CTRL_REG2 = 0x11; static constexpr uint8_t CTRL_REG2_ONE_SHOT_MASK = 0b1; static constexpr uint8_t STATUS = 0x27; @@ -24,8 +25,8 @@ static constexpr float TEMPERATURE_SCALE = 0.01f; void LPS22Component::setup() { uint8_t value = 0x00; this->read_register(WHO_AM_I, &value, 1); - if (value != LPS22HB_ID && value != LPS22HH_ID) { - ESP_LOGW(TAG, "device IDs as %02x, which isn't a known LPS22HB or LPS22HH ID", value); + if (value != LPS22HB_ID && value != LPS22HH_ID && value != LPS22DF_ID) { + ESP_LOGW(TAG, "device IDs as %02x, which isn't a known LPS22HB/HH/DF ID", value); this->mark_failed(); } } From ae49b673218a9c5857c6cc8670a8fa4185d6c8ee Mon Sep 17 00:00:00 2001 From: Cody Cutrer <cody@cutrer.us> Date: Mon, 2 Mar 2026 18:47:40 -0700 Subject: [PATCH 1068/2030] [ld2450] Clear all related sensors when a target is not being tracked (#13602) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/ld2450/ld2450.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 583918e5f5..eb17cc7de7 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -474,15 +474,12 @@ void LD2450Component::handle_periodic_data_() { is_moving = false; // tx is used for further calculations, so always needs to be populated tx = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); - SAFE_PUBLISH_SENSOR(this->move_x_sensors_[index], tx); // Y start = TARGET_Y + index * 8; ty = ld2450::decode_coordinate(this->buffer_data_[start], this->buffer_data_[start + 1]); - SAFE_PUBLISH_SENSOR(this->move_y_sensors_[index], ty); // RESOLUTION start = TARGET_RESOLUTION + index * 8; res = (this->buffer_data_[start + 1] << 8) | this->buffer_data_[start]; - SAFE_PUBLISH_SENSOR(this->move_resolution_sensors_[index], res); #endif // SPEED start = TARGET_SPEED + index * 8; @@ -491,9 +488,6 @@ void LD2450Component::handle_periodic_data_() { is_moving = true; moving_target_count++; } -#ifdef USE_SENSOR - SAFE_PUBLISH_SENSOR(this->move_speed_sensors_[index], ts); -#endif // DISTANCE // Optimized: use already decoded tx and ty values, replace pow() with multiplication int32_t x_squared = (int32_t) tx * tx; @@ -503,10 +497,23 @@ void LD2450Component::handle_periodic_data_() { target_count++; } #ifdef USE_SENSOR - SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td); - // ANGLE - atan2f computes angle from Y axis directly, no sqrt/division needed - angle = atan2f(static_cast<float>(-tx), static_cast<float>(ty)) * (180.0f / std::numbers::pi_v<float>); - SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle); + if (td == 0) { + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_x_sensors_[index]); + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_y_sensors_[index]); + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_resolution_sensors_[index]); + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_speed_sensors_[index]); + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_distance_sensors_[index]); + SAFE_PUBLISH_SENSOR_UNKNOWN(this->move_angle_sensors_[index]); + } else { + SAFE_PUBLISH_SENSOR(this->move_x_sensors_[index], tx); + SAFE_PUBLISH_SENSOR(this->move_y_sensors_[index], ty); + SAFE_PUBLISH_SENSOR(this->move_resolution_sensors_[index], res); + SAFE_PUBLISH_SENSOR(this->move_speed_sensors_[index], ts); + SAFE_PUBLISH_SENSOR(this->move_distance_sensors_[index], td); + // ANGLE - atan2f computes angle from Y axis directly, no sqrt/division needed + angle = atan2f(static_cast<float>(-tx), static_cast<float>(ty)) * (180.0f / std::numbers::pi_v<float>); + SAFE_PUBLISH_SENSOR(this->move_angle_sensors_[index], angle); + } #endif #ifdef USE_TEXT_SENSOR // DIRECTION From db15b94cd7b0a2f323572ca66c172246c28752a1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 2 Mar 2026 17:17:20 -1000 Subject: [PATCH 1069/2030] [core] Inline HighFrequencyLoopRequester::is_high_frequency() (#14423) --- esphome/core/helpers.cpp | 1 - esphome/core/helpers.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 6d801e7ebc..c75799fe57 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -794,7 +794,6 @@ void HighFrequencyLoopRequester::stop() { num_requests--; this->started_ = false; } -bool HighFrequencyLoopRequester::is_high_frequency() { return num_requests > 0; } std::string get_mac_address() { uint8_t mac[6]; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index ae505a2d8a..187b383f65 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1732,7 +1732,7 @@ class HighFrequencyLoopRequester { void stop(); /// Check whether the loop is running continuously. - static bool is_high_frequency(); + static bool is_high_frequency() { return num_requests > 0; } protected: bool started_{false}; From 60d66ca2dcdc59a351c51a070c5fd326d84d2fda Mon Sep 17 00:00:00 2001 From: schrob <83939986+schdro@users.noreply.github.com> Date: Tue, 3 Mar 2026 05:28:01 +0100 Subject: [PATCH 1070/2030] [openthread] Add tx power option (#14200) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/openthread/__init__.py | 30 ++++++++++++++++++- esphome/components/openthread/openthread.cpp | 3 ++ esphome/components/openthread/openthread.h | 2 ++ .../components/openthread/openthread_esp.cpp | 6 ++++ .../openthread/test.esp32-c6-idf.yaml | 1 + 5 files changed, 41 insertions(+), 1 deletion(-) diff --git a/esphome/components/openthread/__init__.py b/esphome/components/openthread/__init__.py index 5861c3db3f..5c64cf31dc 100644 --- a/esphome/components/openthread/__init__.py +++ b/esphome/components/openthread/__init__.py @@ -4,13 +4,20 @@ from esphome.components.esp32 import ( VARIANT_ESP32C6, VARIANT_ESP32H2, add_idf_sdkconfig_option, + get_esp32_variant, include_builtin_idf_component, only_on_variant, require_vfs_select, ) from esphome.components.mdns import MDNSComponent, enable_mdns_storage import esphome.config_validation as cv -from esphome.const import CONF_CHANNEL, CONF_ENABLE_IPV6, CONF_ID, CONF_USE_ADDRESS +from esphome.const import ( + CONF_CHANNEL, + CONF_ENABLE_IPV6, + CONF_ID, + CONF_OUTPUT_POWER, + CONF_USE_ADDRESS, +) from esphome.core import CORE, TimePeriodMilliseconds import esphome.final_validate as fv from esphome.types import ConfigType @@ -45,6 +52,20 @@ CONF_DEVICE_TYPES = [ ] +def _validate_txpower(value): + if CORE.is_esp32: + variant = get_esp32_variant() + + # HW limits: Datasheet section "802.15.4 RF Transmitter (TX) Characteristics" + # Further regulatory/soft limit may apply, e.g. by region + if variant in (VARIANT_ESP32C6, VARIANT_ESP32C5): + return cv.int_range(min=-15, max=20)(value) + if variant == VARIANT_ESP32H2: + return cv.int_range(min=-24, max=20)(value) + + return value # Unsupported, fail later with clear error + + def set_sdkconfig_options(config): # and expose options for using SPI/UART RCPs add_idf_sdkconfig_option("CONFIG_IEEE802154_ENABLED", True) @@ -155,6 +176,10 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_TLV): cv.string_strict, cv.Optional(CONF_USE_ADDRESS): cv.string_strict, cv.Optional(CONF_POLL_PERIOD): cv.positive_time_period_milliseconds, + cv.Optional(CONF_OUTPUT_POWER): cv.All( + cv.decibel, + _validate_txpower, + ), } ).extend(_CONNECTION_SCHEMA), cv.has_exactly_one_key(CONF_NETWORK_KEY, CONF_TLV), @@ -197,4 +222,7 @@ async def to_code(config): cg.add(srp.set_mdns(mdns_component)) await cg.register_component(srp, config) + if (output_power := config.get(CONF_OUTPUT_POWER)) is not None: + cg.add(ot.set_output_power(output_power)) + set_sdkconfig_options(config) diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index d22a14aeae..92897a7e96 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -43,6 +43,9 @@ void OpenThreadComponent::dump_config() { ESP_LOGCONFIG(TAG, " Device is configured as Minimal End Device (MED)"); } #endif + if (this->output_power_.has_value()) { + ESP_LOGCONFIG(TAG, " Output power: %" PRId8 "dBm", *this->output_power_); + } } bool OpenThreadComponent::is_connected() { diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 9e429f289b..728847afa5 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -38,6 +38,7 @@ class OpenThreadComponent : public Component { #if CONFIG_OPENTHREAD_MTD void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; } #endif + void set_output_power(int8_t output_power) { this->output_power_ = output_power; } protected: std::optional<otIp6Address> get_omr_address_(InstanceLock &lock); @@ -45,6 +46,7 @@ class OpenThreadComponent : public Component { #if CONFIG_OPENTHREAD_MTD uint32_t poll_period_{0}; #endif + std::optional<int8_t> output_power_{}; bool teardown_started_{false}; bool teardown_complete_{false}; diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 9dd68a1ccc..2af78b729f 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -135,6 +135,12 @@ void OpenThreadComponent::ot_main() { TRUEFALSE(link_mode_config.mRxOnWhenIdle)); #endif + if (this->output_power_.has_value()) { + if (const auto err = otPlatRadioSetTransmitPower(instance, *this->output_power_); err != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to set power: %s", otThreadErrorToString(err)); + } + } + // Run the main loop #if CONFIG_OPENTHREAD_CLI esp_openthread_cli_create_task(); diff --git a/tests/components/openthread/test.esp32-c6-idf.yaml b/tests/components/openthread/test.esp32-c6-idf.yaml index 9df63b2f29..77abc433c1 100644 --- a/tests/components/openthread/test.esp32-c6-idf.yaml +++ b/tests/components/openthread/test.esp32-c6-idf.yaml @@ -13,3 +13,4 @@ openthread: force_dataset: true use_address: open-thread-test.local poll_period: 20sec + output_power: 1dBm From c4fa476c3c3455a01712a71e2a2d7a8e18d1882d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:45:28 +1300 Subject: [PATCH 1071/2030] Bump version to 2026.2.4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 5f351c1bbb..61dd690f97 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.2.3 +PROJECT_NUMBER = 2026.2.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index aaa34b2fd1..173e2b7be6 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.2.3" +__version__ = "2026.2.4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 1b5bf2c84875977030d073228d31153fe7af64e5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@home-assistant.io> Date: Mon, 2 Mar 2026 16:39:01 -1000 Subject: [PATCH 1072/2030] [wifi] Revert cyw43_wifi_link_status change for RP2040 The switch from cyw43_tcpip_link_status to cyw43_wifi_link_status was intended for 2026.3.0 alongside the arduino-pico 5.5.0 framework update but was accidentally included in 2026.2.3. With the old framework (3.9.4), cyw43_wifi_link_status never returns CYW43_LINK_UP, so the CONNECTED state is unreachable. The device connects to WiFi but the status stays at CONNECTING until timeout, causing a connect/disconnect loop. Fixes https://github.com/esphome/esphome/issues/14422 --- esphome/components/wifi/wifi_component_pico_w.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 7a93de5728..b09cff76ec 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -116,12 +116,7 @@ const char *get_disconnect_reason_str(uint8_t reason) { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { - // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino - // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif - // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's - // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. - // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. - int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + int status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: case CYW43_LINK_NOIP: From 903c67c99499ebdfb60c68816a3cd61114f44897 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 3 Mar 2026 22:16:54 +1300 Subject: [PATCH 1073/2030] Revert "[wifi] Revert cyw43_wifi_link_status change for RP2040" This reverts commit 1b5bf2c84875977030d073228d31153fe7af64e5. --- esphome/components/wifi/wifi_component_pico_w.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index ad07e1ff25..270425d8c2 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -121,7 +121,12 @@ const char *get_disconnect_reason_str(uint8_t reason) { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { - int status = cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA); + // Use cyw43_wifi_link_status instead of cyw43_tcpip_link_status because the Arduino + // framework's __wrap_cyw43_cb_tcpip_init is a no-op — the SDK's internal netif + // (cyw43_state.netif[]) is never initialized. cyw43_tcpip_link_status checks that netif's + // flags and would only fall through to cyw43_wifi_link_status when the flags aren't set. + // Using cyw43_wifi_link_status directly gives us the actual WiFi radio join state. + int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: // WiFi joined, check if we have an IP address via the Arduino framework's WiFi class From cfde0613bbed38f9ce3d86affcde5fd0b300e972 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 3 Mar 2026 23:53:18 +1100 Subject: [PATCH 1074/2030] [const][uart][usb_uart][weikai][core] Move constants to components/const (#14430) --- esphome/components/const/__init__.py | 3 +++ esphome/components/uart/__init__.py | 4 +--- esphome/components/usb_uart/__init__.py | 4 +--- esphome/components/weikai/__init__.py | 4 +--- esphome/const.py | 3 --- .../fixtures/external_components/uart_mock/__init__.py | 4 +--- 6 files changed, 7 insertions(+), 15 deletions(-) diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index 3201db5dfd..059bf3f26a 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -8,14 +8,17 @@ BYTE_ORDER_BIG = "big_endian" CONF_COLOR_DEPTH = "color_depth" CONF_CRC_ENABLE = "crc_enable" +CONF_DATA_BITS = "data_bits" CONF_DRAW_ROUNDING = "draw_rounding" CONF_ENABLED = "enabled" CONF_IGNORE_NOT_FOUND = "ignore_not_found" CONF_ON_PACKET = "on_packet" CONF_ON_RECEIVE = "on_receive" CONF_ON_STATE_CHANGE = "on_state_change" +CONF_PARITY = "parity" CONF_REQUEST_HEADERS = "request_headers" CONF_ROWS = "rows" +CONF_STOP_BITS = "stop_bits" CONF_USE_PSRAM = "use_psram" ICON_CURRENT_DC = "mdi:current-dc" diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 69db4b44aa..3bc4263b31 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -4,6 +4,7 @@ import re from esphome import automation, pins import esphome.codegen as cg +from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS from esphome.config_helpers import filter_source_files_from_platform import esphome.config_validation as cv from esphome.const import ( @@ -11,7 +12,6 @@ from esphome.const import ( CONF_BAUD_RATE, CONF_BYTES, CONF_DATA, - CONF_DATA_BITS, CONF_DEBUG, CONF_DELIMITER, CONF_DIRECTION, @@ -21,12 +21,10 @@ from esphome.const import ( CONF_ID, CONF_LAMBDA, CONF_NUMBER, - CONF_PARITY, CONF_PORT, CONF_RX_BUFFER_SIZE, CONF_RX_PIN, CONF_SEQUENCE, - CONF_STOP_BITS, CONF_TIMEOUT, CONF_TRIGGER_ID, CONF_TX_PIN, diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index cc69c0cb5a..f0ee53d028 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import socket +from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS from esphome.components.uart import UARTComponent from esphome.components.usb_host import register_usb_client, usb_device_schema import esphome.config_validation as cv @@ -7,12 +8,9 @@ from esphome.const import ( CONF_BAUD_RATE, CONF_BUFFER_SIZE, CONF_CHANNELS, - CONF_DATA_BITS, CONF_DEBUG, CONF_DUMMY_RECEIVER, CONF_ID, - CONF_PARITY, - CONF_STOP_BITS, ) from esphome.cpp_types import Component diff --git a/esphome/components/weikai/__init__.py b/esphome/components/weikai/__init__.py index 66cd4ce12a..bc80f167ef 100644 --- a/esphome/components/weikai/__init__.py +++ b/esphome/components/weikai/__init__.py @@ -1,18 +1,16 @@ import esphome.codegen as cg from esphome.components import uart +from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, CONF_CHANNEL, - CONF_DATA_BITS, CONF_ID, CONF_INPUT, CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_OUTPUT, - CONF_PARITY, - CONF_STOP_BITS, ) CODEOWNERS = ["@DrCoolZic"] diff --git a/esphome/const.py b/esphome/const.py index bbd85ca66b..d5625f6a54 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -280,7 +280,6 @@ CONF_CUSTOM_PRESETS = "custom_presets" CONF_CYCLE = "cycle" CONF_DALLAS_ID = "dallas_id" CONF_DATA = "data" -CONF_DATA_BITS = "data_bits" CONF_DATA_PIN = "data_pin" CONF_DATA_PINS = "data_pins" CONF_DATA_RATE = "data_rate" @@ -760,7 +759,6 @@ CONF_PAGE_ID = "page_id" CONF_PAGES = "pages" CONF_PANASONIC = "panasonic" CONF_PARAMETERS = "parameters" -CONF_PARITY = "parity" CONF_PASSWORD = "password" CONF_PATH = "path" CONF_PATTERN = "pattern" @@ -963,7 +961,6 @@ CONF_STEP_PIN = "step_pin" CONF_STILL_THRESHOLD = "still_threshold" CONF_STOP = "stop" CONF_STOP_ACTION = "stop_action" -CONF_STOP_BITS = "stop_bits" CONF_STORE_BASELINE = "store_baseline" CONF_SUBNET = "subnet" CONF_SUBSCRIBE_QOS = "subscribe_qos" diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py index dea8c38551..8deab4c21e 100644 --- a/tests/integration/fixtures/external_components/uart_mock/__init__.py +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -1,6 +1,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import uart +from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS from esphome.components.uart import ( CONF_RX_FULL_THRESHOLD, CONF_RX_TIMEOUT, @@ -12,14 +13,11 @@ import esphome.config_validation as cv from esphome.const import ( CONF_BAUD_RATE, CONF_DATA, - CONF_DATA_BITS, CONF_DEBUG, CONF_DELAY, CONF_ID, CONF_INTERVAL, - CONF_PARITY, CONF_RX_BUFFER_SIZE, - CONF_STOP_BITS, CONF_TRIGGER_ID, ) from esphome.core import ID From b6f0bb9b6bcf12f7021a4904df24954712ab0f78 Mon Sep 17 00:00:00 2001 From: rwrozelle <rwrozelle@gmail.com> Date: Tue, 3 Mar 2026 07:59:01 -0800 Subject: [PATCH 1075/2030] [speaker] Add off on capability to media player (#9295) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> --- .../speaker/media_player/__init__.py | 5 ++ .../media_player/speaker_media_player.cpp | 61 +++++++++++++++++++ .../media_player/speaker_media_player.h | 3 + esphome/core/defines.h | 1 + .../speaker/common-media_player_off_on.yaml | 18 ++++++ .../media_player_off_on.esp32-idf.yaml | 9 +++ 6 files changed, 97 insertions(+) create mode 100644 tests/components/speaker/common-media_player_off_on.yaml create mode 100644 tests/components/speaker/media_player_off_on.esp32-idf.yaml diff --git a/esphome/components/speaker/media_player/__init__.py b/esphome/components/speaker/media_player/__init__.py index b302bd9b23..42ca762858 100644 --- a/esphome/components/speaker/media_player/__init__.py +++ b/esphome/components/speaker/media_player/__init__.py @@ -15,6 +15,8 @@ from esphome.const import ( CONF_FORMAT, CONF_ID, CONF_NUM_CHANNELS, + CONF_ON_TURN_OFF, + CONF_ON_TURN_ON, CONF_PATH, CONF_RAW_DATA_ID, CONF_SAMPLE_RATE, @@ -401,6 +403,9 @@ FINAL_VALIDATE_SCHEMA = cv.All( async def to_code(config): + if CONF_ON_TURN_OFF in config or CONF_ON_TURN_ON in config: + cg.add_define("USE_SPEAKER_MEDIA_PLAYER_ON_OFF", True) + var = await media_player.new_media_player(config) await cg.register_component(var, config) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index fdf6bf66cd..3f5cb2fda6 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -51,7 +51,11 @@ static const UBaseType_t ANNOUNCEMENT_PIPELINE_TASK_PRIORITY = 1; static const char *const TAG = "speaker_media_player"; void SpeakerMediaPlayer::setup() { +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + state = media_player::MEDIA_PLAYER_STATE_OFF; +#else state = media_player::MEDIA_PLAYER_STATE_IDLE; +#endif this->media_control_command_queue_ = xQueueCreate(MEDIA_CONTROLS_QUEUE_LENGTH, sizeof(MediaCallCommand)); @@ -128,6 +132,12 @@ void SpeakerMediaPlayer::watch_media_commands_() { bool enqueue = media_command.enqueue.has_value() && media_command.enqueue.value(); if (media_command.url.has_value() || media_command.file.has_value()) { +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->state == media_player::MEDIA_PLAYER_STATE_OFF) { + this->state = media_player::MEDIA_PLAYER_STATE_ON; + publish_state(); + } +#endif PlaylistItem playlist_item; if (media_command.url.has_value()) { playlist_item.url = *media_command.url.value(); @@ -184,6 +194,12 @@ void SpeakerMediaPlayer::watch_media_commands_() { if (media_command.command.has_value()) { switch (media_command.command.value()) { case media_player::MEDIA_PLAYER_COMMAND_PLAY: +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->state == media_player::MEDIA_PLAYER_STATE_OFF) { + this->state = media_player::MEDIA_PLAYER_STATE_ON; + publish_state(); + } +#endif if ((this->media_pipeline_ != nullptr) && (this->is_paused_)) { this->media_pipeline_->set_pause_state(false); } @@ -195,10 +211,26 @@ void SpeakerMediaPlayer::watch_media_commands_() { } this->is_paused_ = true; break; +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + case media_player::MEDIA_PLAYER_COMMAND_TURN_ON: + if (this->state == media_player::MEDIA_PLAYER_STATE_OFF) { + this->state = media_player::MEDIA_PLAYER_STATE_ON; + this->publish_state(); + } + break; + case media_player::MEDIA_PLAYER_COMMAND_TURN_OFF: + this->is_turn_off_ = true; + // Intentional Fall-through +#endif case media_player::MEDIA_PLAYER_COMMAND_STOP: // Pipelines do not stop immediately after calling the stop command, so confirm its stopped before unpausing. // This avoids an audible short segment playing after receiving the stop command in a paused state. +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value()) || + (this->is_turn_off_ && this->announcement_pipeline_state_ != AudioPipelineState::STOPPED)) { +#else if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) { +#endif if (this->announcement_pipeline_ != nullptr) { this->cancel_timeout("next_ann"); this->announcement_playlist_.clear(); @@ -366,7 +398,13 @@ void SpeakerMediaPlayer::loop() { } } else { if (this->is_paused_) { +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->state != media_player::MEDIA_PLAYER_STATE_OFF) { + this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; + } +#else this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; +#endif } else if (this->media_pipeline_state_ == AudioPipelineState::PLAYING) { this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; } else if (this->media_pipeline_state_ == AudioPipelineState::STOPPED) { @@ -399,7 +437,13 @@ void SpeakerMediaPlayer::loop() { } } } else { +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->state != media_player::MEDIA_PLAYER_STATE_OFF) { + this->state = media_player::MEDIA_PLAYER_STATE_IDLE; + } +#else this->state = media_player::MEDIA_PLAYER_STATE_IDLE; +#endif } } } @@ -409,6 +453,20 @@ void SpeakerMediaPlayer::loop() { this->publish_state(); ESP_LOGD(TAG, "State changed to %s", media_player::media_player_state_to_string(this->state)); } +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + if (this->is_turn_off_ && (this->state == media_player::MEDIA_PLAYER_STATE_PAUSED || + this->state == media_player::MEDIA_PLAYER_STATE_IDLE)) { + this->is_turn_off_ = false; + if (this->state == media_player::MEDIA_PLAYER_STATE_PAUSED) { + this->state = media_player::MEDIA_PLAYER_STATE_IDLE; + this->publish_state(); + ESP_LOGD(TAG, "State changed to %s", media_player::media_player_state_to_string(this->state)); + } + this->state = media_player::MEDIA_PLAYER_STATE_OFF; + this->publish_state(); + ESP_LOGD(TAG, "State changed to %s", media_player::media_player_state_to_string(this->state)); + } +#endif } void SpeakerMediaPlayer::play_file(audio::AudioFile *media_file, bool announcement, bool enqueue) { @@ -481,6 +539,9 @@ media_player::MediaPlayerTraits SpeakerMediaPlayer::get_traits() { if (!this->single_pipeline_()) { traits.set_supports_pause(true); } +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + traits.set_supports_turn_off_on(true); +#endif if (this->announcement_format_.has_value()) { traits.get_supported_formats().push_back(this->announcement_format_.value()); diff --git a/esphome/components/speaker/media_player/speaker_media_player.h b/esphome/components/speaker/media_player/speaker_media_player.h index 6796fc9c00..3fa6f47b84 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.h +++ b/esphome/components/speaker/media_player/speaker_media_player.h @@ -144,6 +144,9 @@ class SpeakerMediaPlayer : public Component, bool is_paused_{false}; bool is_muted_{false}; +#ifdef USE_SPEAKER_MEDIA_PLAYER_ON_OFF + bool is_turn_off_{false}; +#endif uint8_t unpause_media_remaining_{0}; uint8_t unpause_announcement_remaining_{0}; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 7fbc5a0b53..8d778edf2a 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -233,6 +233,7 @@ #define USE_LWIP_FAST_SELECT #define USE_WAKE_LOOP_THREADSAFE #define USE_SPEAKER +#define USE_SPEAKER_MEDIA_PLAYER_ON_OFF #define USE_SPI #define USE_VOICE_ASSISTANT #define USE_WEBSERVER diff --git a/tests/components/speaker/common-media_player_off_on.yaml b/tests/components/speaker/common-media_player_off_on.yaml new file mode 100644 index 0000000000..a5bea62c84 --- /dev/null +++ b/tests/components/speaker/common-media_player_off_on.yaml @@ -0,0 +1,18 @@ +<<: !include common.yaml + +media_player: + - platform: speaker + id: speaker_media_player_id + announcement_pipeline: + speaker: speaker_id + buffer_size: 1000000 + volume_increment: 0.02 + volume_max: 0.95 + volume_min: 0.0 + task_stack_in_psram: true + on_turn_on: + then: + - logger.log: "Turn On Media Player" + on_turn_off: + then: + - logger.log: "Turn Off Media Player" diff --git a/tests/components/speaker/media_player_off_on.esp32-idf.yaml b/tests/components/speaker/media_player_off_on.esp32-idf.yaml new file mode 100644 index 0000000000..2d5eefff19 --- /dev/null +++ b/tests/components/speaker/media_player_off_on.esp32-idf.yaml @@ -0,0 +1,9 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + i2s_bclk_pin: GPIO27 + i2s_lrclk_pin: GPIO26 + i2s_mclk_pin: GPIO25 + i2s_dout_pin: GPIO23 + +<<: !include common-media_player_off_on.yaml From d53ff7892a85d623f7c116c253075d82b2fd0a95 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:03:02 -1000 Subject: [PATCH 1076/2030] [socket] Cache lwip_sock pointers and inline ready() chain (#14408) --- .../components/socket/bsd_sockets_impl.cpp | 33 +++++++------- esphome/components/socket/bsd_sockets_impl.h | 7 +++ .../components/socket/lwip_sockets_impl.cpp | 33 +++++++------- esphome/components/socket/lwip_sockets_impl.h | 7 +++ esphome/components/socket/socket.cpp | 6 ++- esphome/components/socket/socket.h | 45 +++++++++++++++++-- esphome/core/application.cpp | 43 ++++++++++++------ esphome/core/application.h | 32 ++++++------- esphome/core/lwip_fast_select.c | 28 +++++------- esphome/core/lwip_fast_select.h | 45 ++++++++++++++++--- 10 files changed, 190 insertions(+), 89 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.cpp b/esphome/components/socket/bsd_sockets_impl.cpp index 92ecfc692b..aea7c776c6 100644 --- a/esphome/components/socket/bsd_sockets_impl.cpp +++ b/esphome/components/socket/bsd_sockets_impl.cpp @@ -11,11 +11,15 @@ namespace esphome::socket { BSDSocketImpl::BSDSocketImpl(int fd, bool monitor_loop) { this->fd_ = fd; - // Register new socket with the application for select() if monitoring requested - if (monitor_loop && this->fd_ >= 0) { - // Only set loop_monitored_ to true if registration succeeds - this->loop_monitored_ = App.register_socket_fd(this->fd_); - } + if (!monitor_loop || this->fd_ < 0) + return; +#ifdef USE_LWIP_FAST_SELECT + // Cache lwip_sock pointer and register for monitoring (hooks callback internally) + this->cached_sock_ = esphome_lwip_get_sock(this->fd_); + this->loop_monitored_ = App.register_socket(this->cached_sock_); +#else + this->loop_monitored_ = App.register_socket_fd(this->fd_); +#endif } BSDSocketImpl::~BSDSocketImpl() { @@ -26,10 +30,17 @@ BSDSocketImpl::~BSDSocketImpl() { int BSDSocketImpl::close() { if (!this->closed_) { - // Unregister from select() before closing if monitored + // Unregister before closing to avoid dangling pointer in monitored set +#ifdef USE_LWIP_FAST_SELECT + if (this->loop_monitored_) { + App.unregister_socket(this->cached_sock_); + this->cached_sock_ = nullptr; + } +#else if (this->loop_monitored_) { App.unregister_socket_fd(this->fd_); } +#endif int ret = ::close(this->fd_); this->closed_ = true; return ret; @@ -48,8 +59,6 @@ int BSDSocketImpl::setblocking(bool blocking) { return 0; } -bool BSDSocketImpl::ready() const { return socket_ready_fd(this->fd_, this->loop_monitored_); } - size_t BSDSocketImpl::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { struct sockaddr_storage storage; socklen_t len = sizeof(storage); @@ -86,14 +95,6 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol return create_socket(domain, type, protocol, true); } -std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { - return create_socket(domain, type, protocol, false); -} - -std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { - return create_socket(domain, type, protocol, true); -} - } // namespace esphome::socket #endif // USE_SOCKET_IMPL_BSD_SOCKETS diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h index d9ed9dc567..9ebbe72002 100644 --- a/esphome/components/socket/bsd_sockets_impl.h +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -13,6 +13,10 @@ #include <lwip/sockets.h> #endif +#ifdef USE_LWIP_FAST_SELECT +struct lwip_sock; +#endif + namespace esphome::socket { class BSDSocketImpl { @@ -105,6 +109,9 @@ class BSDSocketImpl { protected: int fd_{-1}; +#ifdef USE_LWIP_FAST_SELECT + struct lwip_sock *cached_sock_{nullptr}; // Cached for direct rcvevent read in ready() +#endif bool closed_{false}; bool loop_monitored_{false}; }; diff --git a/esphome/components/socket/lwip_sockets_impl.cpp b/esphome/components/socket/lwip_sockets_impl.cpp index 0322820ef4..2fad429e0f 100644 --- a/esphome/components/socket/lwip_sockets_impl.cpp +++ b/esphome/components/socket/lwip_sockets_impl.cpp @@ -11,11 +11,15 @@ namespace esphome::socket { LwIPSocketImpl::LwIPSocketImpl(int fd, bool monitor_loop) { this->fd_ = fd; - // Register new socket with the application for select() if monitoring requested - if (monitor_loop && this->fd_ >= 0) { - // Only set loop_monitored_ to true if registration succeeds - this->loop_monitored_ = App.register_socket_fd(this->fd_); - } + if (!monitor_loop || this->fd_ < 0) + return; +#ifdef USE_LWIP_FAST_SELECT + // Cache lwip_sock pointer and register for monitoring (hooks callback internally) + this->cached_sock_ = esphome_lwip_get_sock(this->fd_); + this->loop_monitored_ = App.register_socket(this->cached_sock_); +#else + this->loop_monitored_ = App.register_socket_fd(this->fd_); +#endif } LwIPSocketImpl::~LwIPSocketImpl() { @@ -26,10 +30,17 @@ LwIPSocketImpl::~LwIPSocketImpl() { int LwIPSocketImpl::close() { if (!this->closed_) { - // Unregister from select() before closing if monitored + // Unregister before closing to avoid dangling pointer in monitored set +#ifdef USE_LWIP_FAST_SELECT + if (this->loop_monitored_) { + App.unregister_socket(this->cached_sock_); + this->cached_sock_ = nullptr; + } +#else if (this->loop_monitored_) { App.unregister_socket_fd(this->fd_); } +#endif int ret = lwip_close(this->fd_); this->closed_ = true; return ret; @@ -48,8 +59,6 @@ int LwIPSocketImpl::setblocking(bool blocking) { return 0; } -bool LwIPSocketImpl::ready() const { return socket_ready_fd(this->fd_, this->loop_monitored_); } - size_t LwIPSocketImpl::getpeername_to(std::span<char, SOCKADDR_STR_LEN> buf) { struct sockaddr_storage storage; socklen_t len = sizeof(storage); @@ -86,14 +95,6 @@ std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol return create_socket(domain, type, protocol, true); } -std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { - return create_socket(domain, type, protocol, false); -} - -std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { - return create_socket(domain, type, protocol, true); -} - } // namespace esphome::socket #endif // USE_SOCKET_IMPL_LWIP_SOCKETS diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h index d6699aded2..c579219863 100644 --- a/esphome/components/socket/lwip_sockets_impl.h +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -9,6 +9,10 @@ #include "esphome/core/helpers.h" #include "headers.h" +#ifdef USE_LWIP_FAST_SELECT +struct lwip_sock; +#endif + namespace esphome::socket { class LwIPSocketImpl { @@ -71,6 +75,9 @@ class LwIPSocketImpl { protected: int fd_{-1}; +#ifdef USE_LWIP_FAST_SELECT + struct lwip_sock *cached_sock_{nullptr}; // Cached for direct rcvevent read in ready() +#endif bool closed_{false}; bool loop_monitored_{false}; }; diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index c04671c7ee..bfb6ae8e13 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -8,7 +8,7 @@ namespace esphome::socket { -#ifdef USE_SOCKET_SELECT_SUPPORT +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) // Shared ready() implementation for fd-based socket implementations (BSD and LWIP sockets). // Checks if the Application's select() loop has marked this fd as ready. bool socket_ready_fd(int fd, bool loop_monitored) { return !loop_monitored || App.is_socket_ready_(fd); } @@ -89,6 +89,9 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol) { #endif /* USE_NETWORK_IPV6 */ } +#ifdef USE_SOCKET_IMPL_LWIP_TCP +// LWIP_TCP has separate Socket/ListenSocket types — needs out-of-line factory. +// BSD and LWIP_SOCKETS define this inline in socket.h. std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol) { #if USE_NETWORK_IPV6 return socket_listen_loop_monitored(AF_INET6, type, protocol); @@ -96,6 +99,7 @@ std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol) { return socket_listen_loop_monitored(AF_INET, type, protocol); #endif /* USE_NETWORK_IPV6 */ } +#endif socklen_t set_sockaddr(struct sockaddr *addr, socklen_t addrlen, const char *ip_address, uint16_t port) { #if USE_NETWORK_IPV6 diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 546d278260..0884e4ba3e 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -6,6 +6,10 @@ #include "esphome/core/optional.h" #include "headers.h" +#ifdef USE_LWIP_FAST_SELECT +#include "esphome/core/lwip_fast_select.h" +#endif + #if defined(USE_SOCKET_IMPL_LWIP_TCP) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) || defined(USE_SOCKET_IMPL_BSD_SOCKETS) // Include only the active implementation's header. @@ -36,12 +40,29 @@ using Socket = LWIPRawImpl; using ListenSocket = LWIPRawListenImpl; #endif -#ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_LWIP_FAST_SELECT +/// Shared ready() helper using cached lwip_sock pointer for direct rcvevent read. +inline bool socket_ready(struct lwip_sock *cached_sock, bool loop_monitored) { + return !loop_monitored || (cached_sock != nullptr && esphome_lwip_socket_has_data(cached_sock)); +} +#elif defined(USE_SOCKET_SELECT_SUPPORT) /// Shared ready() helper for fd-based socket implementations. /// Checks if the Application's select() loop has marked this fd as ready. bool socket_ready_fd(int fd, bool loop_monitored); #endif +// Inline ready() — defined here because it depends on socket_ready/socket_ready_fd +// declared above, while the impl headers are included before those declarations. +#if defined(USE_SOCKET_IMPL_BSD_SOCKETS) || defined(USE_SOCKET_IMPL_LWIP_SOCKETS) +inline bool Socket::ready() const { +#ifdef USE_LWIP_FAST_SELECT + return socket_ready(this->cached_sock_, this->loop_monitored_); +#else + return socket_ready_fd(this->fd_, this->loop_monitored_); +#endif +} +#endif + /// Create a socket of the given domain, type and protocol. std::unique_ptr<Socket> socket(int domain, int type, int protocol); /// Create a socket in the newest available IP domain (IPv6 or IPv4) of the given type and protocol. @@ -56,11 +77,29 @@ std::unique_ptr<Socket> socket_ip(int type, int protocol); std::unique_ptr<Socket> socket_loop_monitored(int domain, int type, int protocol); /// Create a listening socket of the given domain, type and protocol. -std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol); /// Create a listening socket and monitor it for data in the main loop. -std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol); /// Create a listening socket in the newest available IP domain and monitor it. +#ifdef USE_SOCKET_IMPL_LWIP_TCP +// LWIP_TCP has separate Socket/ListenSocket types — needs distinct factory functions. +std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol); +std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol); std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol); +#else +// BSD and LWIP_SOCKETS: Socket == ListenSocket, so listen variants just delegate. +inline std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) { + return socket(domain, type, protocol); +} +inline std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, int protocol) { + return socket_loop_monitored(domain, type, protocol); +} +inline std::unique_ptr<ListenSocket> socket_ip_loop_monitored(int type, int protocol) { +#if USE_NETWORK_IPV6 + return socket_loop_monitored(AF_INET6, type, protocol); +#else + return socket_loop_monitored(AF_INET, type, protocol); +#endif +} +#endif /// Set a sockaddr to the specified address and port for the IP version used by socket_ip(). /// @param addr Destination sockaddr structure diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 26cd670629..8c2ba58c86 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -552,7 +552,32 @@ void Application::after_loop_tasks_() { this->in_loop_ = false; } -#ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_LWIP_FAST_SELECT +bool Application::register_socket(struct lwip_sock *sock) { + // It modifies monitored_sockets_ without locking — must only be called from the main loop. + if (sock == nullptr) + return false; + esphome_lwip_hook_socket(sock); + this->monitored_sockets_.push_back(sock); + return true; +} + +void Application::unregister_socket(struct lwip_sock *sock) { + // It modifies monitored_sockets_ without locking — must only be called from the main loop. + for (size_t i = 0; i < this->monitored_sockets_.size(); i++) { + if (this->monitored_sockets_[i] != sock) + continue; + + // Swap with last element and pop - O(1) removal since order doesn't matter. + // No need to unhook the netconn callback — all LwIP sockets share the same + // static event_callback, and the socket will be closed by the caller. + if (i < this->monitored_sockets_.size() - 1) + this->monitored_sockets_[i] = this->monitored_sockets_.back(); + this->monitored_sockets_.pop_back(); + return; + } +} +#elif defined(USE_SOCKET_SELECT_SUPPORT) bool Application::register_socket_fd(int fd) { // WARNING: This function is NOT thread-safe and must only be called from the main loop // It modifies socket_fds_ and related variables without locking @@ -571,15 +596,10 @@ bool Application::register_socket_fd(int fd) { #endif this->socket_fds_.push_back(fd); -#ifdef USE_LWIP_FAST_SELECT - // Hook the socket's netconn callback for instant wake on receive events - esphome_lwip_hook_socket(fd); -#else this->socket_fds_changed_ = true; if (fd > this->max_fd_) { this->max_fd_ = fd; } -#endif return true; } @@ -595,13 +615,9 @@ void Application::unregister_socket_fd(int fd) { continue; // Swap with last element and pop - O(1) removal since order doesn't matter. - // No need to unhook the netconn callback on fast select platforms — all LwIP - // sockets share the same static event_callback, and the socket will be closed - // by the caller. if (i < this->socket_fds_.size() - 1) this->socket_fds_[i] = this->socket_fds_.back(); this->socket_fds_.pop_back(); -#ifndef USE_LWIP_FAST_SELECT this->socket_fds_changed_ = true; // Only recalculate max_fd if we removed the current max if (fd == this->max_fd_) { @@ -611,7 +627,6 @@ void Application::unregister_socket_fd(int fd) { this->max_fd_ = sock_fd; } } -#endif return; } } @@ -621,7 +636,7 @@ void Application::unregister_socket_fd(int fd) { void Application::yield_with_select_(uint32_t delay_ms) { // Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run. #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) - // Fast path (ESP32/LibreTiny): reads rcvevent directly via lwip_socket_dbg_get_socket(). + // Fast path (ESP32/LibreTiny): reads rcvevent directly from cached lwip_sock pointers. // Safe because this runs on the main loop which owns socket lifetime (create, read, close). if (delay_ms == 0) [[unlikely]] { yield(); @@ -632,8 +647,8 @@ void Application::yield_with_select_(uint32_t delay_ms) { // If a socket still has unread data (rcvevent > 0) but the task notification was already // consumed, ulTaskNotifyTake would block until timeout — adding up to delay_ms latency. // This scan preserves select() semantics: return immediately when any fd is ready. - for (int fd : this->socket_fds_) { - if (esphome_lwip_socket_has_data(fd)) { + for (struct lwip_sock *sock : this->monitored_sockets_) { + if (esphome_lwip_socket_has_data(sock)) { yield(); return; } diff --git a/esphome/core/application.h b/esphome/core/application.h index 63d59c555e..40f8a00edd 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -500,14 +500,20 @@ class Application { Scheduler scheduler; - /// Register/unregister a socket file descriptor to be monitored for read events. -#ifdef USE_SOCKET_SELECT_SUPPORT - /// These functions update the fd_set used by select() in the main loop. + /// Register/unregister a socket to be monitored for read events. /// WARNING: These functions are NOT thread-safe. They must only be called from the main loop. +#ifdef USE_LWIP_FAST_SELECT + /// Fast select path: hooks netconn callback and registers for monitoring. + /// @return true if registration was successful, false if sock is null + bool register_socket(struct lwip_sock *sock); + void unregister_socket(struct lwip_sock *sock); +#elif defined(USE_SOCKET_SELECT_SUPPORT) + /// Fallback select() path: monitors file descriptors. /// NOTE: File descriptors >= FD_SETSIZE (typically 10 on ESP) will be rejected with an error. /// @return true if registration was successful, false if fd exceeds limits bool register_socket_fd(int fd); void unregister_socket_fd(int fd); +#endif #ifdef USE_WAKE_LOOP_THREADSAFE /// Wake the main event loop from another FreeRTOS task. @@ -532,7 +538,6 @@ class Application { static void IRAM_ATTR wake_loop_any_context() { esphome_lwip_wake_main_loop_any_context(); } #endif #endif -#endif #if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) /// Wake the main event loop from any context (ISR, thread, or main loop). @@ -542,23 +547,14 @@ class Application { protected: friend Component; -#ifdef USE_SOCKET_SELECT_SUPPORT +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) friend bool socket::socket_ready_fd(int fd, bool loop_monitored); #endif friend void ::setup(); friend void ::original_setup(); -#ifdef USE_SOCKET_SELECT_SUPPORT - /// Fast path for Socket::ready() via friendship - skips negative fd check. - /// Main loop only — with USE_LWIP_FAST_SELECT, reads rcvevent via - /// lwip_socket_dbg_get_socket(), which has no refcount; safe only because - /// the main loop owns socket lifetime (creates, reads, and closes sockets - /// on the same thread). -#ifdef USE_LWIP_FAST_SELECT - bool is_socket_ready_(int fd) const { return esphome_lwip_socket_has_data(fd); } -#else +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) bool is_socket_ready_(int fd) const { return FD_ISSET(fd, &this->read_fds_); } -#endif #endif /// Register a component, detecting loop() override at compile time. @@ -620,8 +616,12 @@ class Application { // and active_end_ is incremented // - This eliminates branch mispredictions from flag checking in the hot loop FixedVector<Component *> looping_components_{}; -#ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_LWIP_FAST_SELECT + std::vector<struct lwip_sock *> monitored_sockets_; // Cached lwip_sock pointers for direct rcvevent read +#elif defined(USE_SOCKET_SELECT_SUPPORT) std::vector<int> socket_fds_; // Vector of all monitored socket file descriptors +#endif +#ifdef USE_SOCKET_SELECT_SUPPORT #if defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) int wake_socket_fd_{-1}; // Shared wake notification socket for waking main loop from tasks #endif diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index 989f66e9be..c578a9aae9 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -140,8 +140,10 @@ _Static_assert(sizeof(TaskHandle_t) <= 4, "TaskHandle_t must be <= 4 bytes for atomic access"); _Static_assert(sizeof(netconn_callback) <= 4, "netconn_callback must be <= 4 bytes for atomic access"); -// rcvevent must fit in a single atomic read -_Static_assert(sizeof(((struct lwip_sock *) 0)->rcvevent) <= 4, "rcvevent must be <= 4 bytes for atomic access"); +// rcvevent must be exactly 2 bytes (s16_t) — the inline in lwip_fast_select.h reads it as int16_t. +// If lwIP changes this to int or similar, the offset assert would still pass but the load width would be wrong. +_Static_assert(sizeof(((struct lwip_sock *) 0)->rcvevent) == 2, + "rcvevent size changed — update int16_t cast in esphome_lwip_socket_has_data() in lwip_fast_select.h"); // Struct member alignment — natural alignment guarantees atomicity on Xtensa/RISC-V/ARM. // Misaligned access would not be atomic even if the size is <= 4 bytes. @@ -150,6 +152,10 @@ _Static_assert(offsetof(struct netconn, callback) % sizeof(netconn_callback) == _Static_assert(offsetof(struct lwip_sock, rcvevent) % sizeof(((struct lwip_sock *) 0)->rcvevent) == 0, "lwip_sock.rcvevent must be naturally aligned for atomic access"); +// Verify the hardcoded offset used in the header's inline esphome_lwip_socket_has_data(). +_Static_assert(offsetof(struct lwip_sock, rcvevent) == ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET, + "lwip_sock.rcvevent offset changed — update ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET in lwip_fast_select.h"); + // Task handle for the main loop — written once in init(), read from TCP/IP and background tasks. static TaskHandle_t s_main_loop_task = NULL; @@ -194,23 +200,11 @@ static inline struct lwip_sock *get_sock(int fd) { return sock; } -bool esphome_lwip_socket_has_data(int fd) { - struct lwip_sock *sock = get_sock(fd); - if (sock == NULL) - return false; - // volatile prevents the compiler from caching/reordering this cross-thread read. - // The write side (TCP/IP thread) commits via SYS_ARCH_UNPROTECT which releases a - // FreeRTOS mutex (ESP32) or resumes the scheduler (LibreTiny), ensuring the value - // is visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH/LDRH) on - // Xtensa/RISC-V/ARM and cannot produce torn values. - return *(volatile s16_t *) &sock->rcvevent > 0; +struct lwip_sock *esphome_lwip_get_sock(int fd) { + return get_sock(fd); } -void esphome_lwip_hook_socket(int fd) { - struct lwip_sock *sock = get_sock(fd); - if (sock == NULL) - return; - +void esphome_lwip_hook_socket(struct lwip_sock *sock) { // Save original callback once — all LwIP sockets share the same static event_callback // (DEFAULT_SOCKET_EVENTCB in sockets.c, used for SOCK_RAW, SOCK_DGRAM, and SOCK_STREAM). if (s_original_callback == NULL) { diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index 6fce34fd76..46c6b711cd 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -4,6 +4,17 @@ // Replaces lwip_select() with direct rcvevent reads and FreeRTOS task notifications. #include <stdbool.h> +#include <stdint.h> + +// Forward declare lwip_sock for C++ callers that store cached pointers. +// The full definition is only available in the .c file (lwip/priv/sockets_priv.h +// conflicts with C++ compilation units). +struct lwip_sock; + +// Byte offset of rcvevent (s16_t) within struct lwip_sock. +// Verified at compile time in lwip_fast_select.c via _Static_assert. +// Anonymous enum for a compile-time constant that works in both C and C++. +enum { ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET = 8 }; #ifdef __cplusplus extern "C" { @@ -13,16 +24,38 @@ extern "C" { /// Saves the current task handle for xTaskNotifyGive() wake notifications. void esphome_lwip_fast_select_init(void); -/// Check if a LwIP socket has data ready via direct rcvevent read (~215 ns per socket). -/// Uses lwip_socket_dbg_get_socket() — a direct array lookup without the refcount that -/// get_socket()/done_socket() uses. Safe because the caller owns the socket lifetime: -/// both has_data reads and socket close/unregister happen on the main loop thread. -bool esphome_lwip_socket_has_data(int fd); +/// Look up a LwIP socket struct from a file descriptor. +/// Returns NULL if fd is invalid or the socket/netconn is not initialized. +/// Use this at registration time to cache the pointer for esphome_lwip_socket_has_data(). +struct lwip_sock *esphome_lwip_get_sock(int fd); + +/// Check if a cached LwIP socket has data ready via unlocked hint read of rcvevent. +/// This avoids lwIP core lock contention between the main loop (CPU0) and +/// streaming/networking work (CPU1). Correctness is preserved because callers +/// already handle EWOULDBLOCK on nonblocking sockets — a stale hint simply causes +/// a harmless retry on the next loop iteration. In practice, stale reads have not +/// been observed across multi-day testing, but the design does not depend on that. +/// +/// The sock pointer must have been obtained from esphome_lwip_get_sock() and must +/// remain valid (caller owns socket lifetime — no concurrent close). +/// Hot path: inlined volatile 16-bit load — no function call overhead. +/// Uses offset-based access because lwip/priv/sockets_priv.h conflicts with C++. +/// The offset and size are verified at compile time in lwip_fast_select.c. +static inline bool esphome_lwip_socket_has_data(struct lwip_sock *sock) { + // Unlocked hint read — no lwIP core lock needed. + // volatile prevents the compiler from caching/reordering this cross-thread read. + // The write side (TCP/IP thread) commits via SYS_ARCH_UNPROTECT which releases a + // FreeRTOS mutex (ESP32) or resumes the scheduler (LibreTiny), ensuring the value + // is visible. Aligned 16-bit reads are single-instruction loads (L16SI/LH/LDRH) on + // Xtensa/RISC-V/ARM and cannot produce torn values. + return *(volatile int16_t *) ((char *) sock + (int) ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET) > 0; +} /// Hook a socket's netconn callback to notify the main loop task on receive events. /// Wraps the original event_callback with one that also calls xTaskNotifyGive(). /// Must be called from the main loop after socket creation. -void esphome_lwip_hook_socket(int fd); +/// The sock pointer must have been obtained from esphome_lwip_get_sock(). +void esphome_lwip_hook_socket(struct lwip_sock *sock); /// Wake the main loop task from another FreeRTOS task — costs <1 us. /// NOT ISR-safe — must only be called from task context. From 1f1b20f4feacd769279b673be5301c1d39f41ed3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:03:24 -1000 Subject: [PATCH 1077/2030] [core] Pack entity string properties into PROGMEM-indexed uint8_t fields (#14171) --- .../alarm_control_panel/__init__.py | 2 +- esphome/components/api/api_connection.cpp | 4 +- esphome/components/binary_sensor/__init__.py | 12 +- .../components/binary_sensor/binary_sensor.h | 2 +- esphome/components/button/__init__.py | 12 +- esphome/components/button/button.h | 2 +- esphome/components/climate/__init__.py | 3 +- esphome/components/cover/__init__.py | 12 +- esphome/components/cover/cover.h | 2 +- esphome/components/datetime/__init__.py | 3 +- esphome/components/esp32/core.cpp | 1 + esphome/components/esp8266/core.cpp | 3 + esphome/components/event/__init__.py | 12 +- esphome/components/event/event.h | 2 +- esphome/components/fan/__init__.py | 3 +- esphome/components/host/core.cpp | 1 + esphome/components/infrared/__init__.py | 2 +- esphome/components/libretiny/core.cpp | 1 + esphome/components/light/__init__.py | 7 +- esphome/components/lock/__init__.py | 3 +- esphome/components/media_player/__init__.py | 2 +- esphome/components/mqtt/mqtt_number.cpp | 4 +- esphome/components/number/__init__.py | 16 +- esphome/components/number/number.cpp | 4 +- esphome/components/number/number_traits.h | 6 +- esphome/components/rp2040/core.cpp | 3 + esphome/components/select/__init__.py | 3 +- esphome/components/sensor/__init__.py | 16 +- esphome/components/sensor/sensor.h | 2 +- esphome/components/sprinkler/sprinkler.cpp | 4 +- esphome/components/switch/__init__.py | 12 +- esphome/components/switch/switch.h | 2 +- esphome/components/text/__init__.py | 3 +- esphome/components/text_sensor/__init__.py | 12 +- esphome/components/text_sensor/text_sensor.h | 2 +- esphome/components/update/__init__.py | 12 +- esphome/components/update/update_entity.h | 2 +- esphome/components/valve/__init__.py | 12 +- esphome/components/valve/valve.h | 2 +- esphome/components/water_heater/__init__.py | 3 +- esphome/components/web_server/web_server.cpp | 2 +- esphome/components/zephyr/core.cpp | 1 + esphome/core/defines.h | 2 + esphome/core/entity_base.cpp | 64 ++--- esphome/core/entity_base.h | 100 ++++---- esphome/core/entity_helpers.py | 227 +++++++++++++++++- esphome/core/hal.h | 1 + script/clang-tidy | 1 + tests/component_tests/sensor/test_sensor.py | 2 +- .../text_sensor/test_text_sensor.py | 4 +- tests/unit_tests/core/test_entity_helpers.py | 110 +++++++-- 51 files changed, 519 insertions(+), 206 deletions(-) diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index b1e2252ce7..b855586152 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -186,8 +186,8 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id( ) +@setup_entity("alarm_control_panel") async def setup_alarm_control_panel_core_(var, config): - await setup_entity(var, config, "alarm_control_panel") for conf in config.get(CONF_ON_STATE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 738dd1ef05..59476fac25 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -773,9 +773,9 @@ uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *number = static_cast<number::Number *>(entity); ListEntitiesNumberResponse msg; - msg.unit_of_measurement = number->traits.get_unit_of_measurement_ref(); + msg.unit_of_measurement = number->get_unit_of_measurement_ref(); msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode()); - msg.device_class = number->traits.get_device_class_ref(); + msg.device_class = number->get_device_class_ref(); msg.min_value = number->traits.get_min_value(); msg.max_value = number->traits.get_max_value(); msg.step = number->traits.get_step(); diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 036d78da73..1f64118560 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -60,7 +60,11 @@ from esphome.const import ( DEVICE_CLASS_WINDOW, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass from esphome.util import Registry @@ -604,11 +608,9 @@ async def _build_binary_sensor_automations(var, config): ) +@setup_entity("binary_sensor") async def setup_binary_sensor_core_(var, config): - await setup_entity(var, config, "binary_sensor") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) trigger = config.get(CONF_TRIGGER_ON_INITIAL_STATE, False) or config.get( CONF_PUBLISH_INITIAL_STATE, False ) diff --git a/esphome/components/binary_sensor/binary_sensor.h b/esphome/components/binary_sensor/binary_sensor.h index 4b655e1bd1..6ae5d04bcb 100644 --- a/esphome/components/binary_sensor/binary_sensor.h +++ b/esphome/components/binary_sensor/binary_sensor.h @@ -30,7 +30,7 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi * The sub classes should notify the front-end of new states via the publish_state() method which * handles inverted inputs for you. */ -class BinarySensor : public StatefulEntityBase<bool>, public EntityBase_DeviceClass { +class BinarySensor : public StatefulEntityBase<bool> { public: explicit BinarySensor(){}; diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 94816a0974..12d9ebaba6 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -18,7 +18,11 @@ from esphome.const import ( DEVICE_CLASS_UPDATE, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@esphome/core"] @@ -84,15 +88,13 @@ def button_schema( return _BUTTON_SCHEMA.extend(schema) +@setup_entity("button") async def setup_button_core_(var, config): - await setup_entity(var, config, "button") - for conf in config.get(CONF_ON_PRESS, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) - if device_class := config.get(CONF_DEVICE_CLASS): - cg.add(var.set_device_class(device_class)) + setup_device_class(config) if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/button/button.h b/esphome/components/button/button.h index be6e080917..0f7576a419 100644 --- a/esphome/components/button/button.h +++ b/esphome/components/button/button.h @@ -22,7 +22,7 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o * * A button is just a momentary switch that does not have a state, only a trigger. */ -class Button : public EntityBase, public EntityBase_DeviceClass { +class Button : public EntityBase { public: /** Press this button. This is called by the front-end. * diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index 2150a30c3e..1f449ad2a4 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -268,9 +268,8 @@ def climate_schema( return _CLIMATE_SCHEMA.extend(schema) +@setup_entity("climate") async def setup_climate_core_(var, config): - await setup_entity(var, config, "climate") - visual = config[CONF_VISUAL] if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None: cg.add_define("USE_CLIMATE_VISUAL_OVERRIDES") diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index 17095f41f6..c330241f4d 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -37,7 +37,11 @@ from esphome.const import ( DEVICE_CLASS_WINDOW, ) from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObj, MockObjClass from esphome.types import ConfigType, TemplateArgsType @@ -190,11 +194,9 @@ def cover_schema( return _COVER_SCHEMA.extend(schema) +@setup_entity("cover") async def setup_cover_core_(var, config): - await setup_entity(var, config, "cover") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) if CONF_ON_OPEN in config: _LOGGER.warning( diff --git a/esphome/components/cover/cover.h b/esphome/components/cover/cover.h index 0af48f75de..8cf9aa092a 100644 --- a/esphome/components/cover/cover.h +++ b/esphome/components/cover/cover.h @@ -107,7 +107,7 @@ const LogString *cover_operation_to_str(CoverOperation op); * to control all values of the cover. Also implement get_traits() to return what operations * the cover supports. */ -class Cover : public EntityBase, public EntityBase_DeviceClass { +class Cover : public EntityBase { public: explicit Cover(); diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 602db3827a..74c9d594f7 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -134,9 +134,8 @@ def datetime_schema(class_: MockObjClass) -> cv.Schema: return _DATETIME_SCHEMA.extend(schema) +@setup_entity("datetime") async def setup_datetime_core_(var, config): - await setup_entity(var, config, "datetime") - if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) await mqtt.register_mqtt_component(mqtt_, config) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 7ebbba609e..46c000562e 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -48,6 +48,7 @@ void arch_init() { void HOT arch_feed_wdt() { esp_task_wdt_reset(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +const char *progmem_read_ptr(const char *const *addr) { return *addr; } uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index b665124d66..159ec20e77 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -34,6 +34,9 @@ void HOT arch_feed_wdt() { system_soft_wdt_feed(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } +const char *progmem_read_ptr(const char *const *addr) { + return reinterpret_cast<const char *>(pgm_read_ptr(addr)); // NOLINT +} uint16_t progmem_read_uint16(const uint16_t *addr) { return pgm_read_word(addr); // NOLINT } diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 8fac7a279c..14cc1505ad 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -18,7 +18,11 @@ from esphome.const import ( DEVICE_CLASS_MOTION, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@nohat"] @@ -85,17 +89,15 @@ def event_schema( return _EVENT_SCHEMA.extend(schema) +@setup_entity("event") async def setup_event_core_(var, config, *, event_types: list[str]): - await setup_entity(var, config, "event") - for conf in config.get(CONF_ON_EVENT, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(cg.StringRef, "event_type")], conf) cg.add(var.set_event_types(event_types)) - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index a7451407bb..5b6a94b47c 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -20,7 +20,7 @@ namespace event { LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \ } -class Event : public EntityBase, public EntityBase_DeviceClass { +class Event : public EntityBase { public: void trigger(const std::string &event_type); diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index e839df6aee..da28c577c8 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -222,9 +222,8 @@ def validate_preset_modes(value): return value +@setup_entity("fan") async def setup_fan_core_(var, config): - await setup_entity(var, config, "fan") - cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index cb2b2e19d7..d5c61ec986 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -59,6 +59,7 @@ void HOT arch_feed_wdt() { } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +const char *progmem_read_ptr(const char *const *addr) { return *addr; } uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { struct timespec spec; diff --git a/esphome/components/infrared/__init__.py b/esphome/components/infrared/__init__.py index 5c759d6fd9..6a2a72fa5d 100644 --- a/esphome/components/infrared/__init__.py +++ b/esphome/components/infrared/__init__.py @@ -45,9 +45,9 @@ def infrared_schema(class_: type[cg.MockObjClass]) -> cv.Schema: ) +@setup_entity("infrared") async def setup_infrared_core_(var: cg.Pvariable, config: ConfigType) -> None: """Set up core infrared configuration.""" - await setup_entity(var, config, "infrared") async def register_infrared(var: cg.Pvariable, config: ConfigType) -> None: diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 74b33a30a0..893a79440a 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -36,6 +36,7 @@ void HOT arch_feed_wdt() { lt_wdt_feed(); } uint32_t arch_get_cpu_cycle_count() { return lt_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return lt_cpu_get_freq(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +const char *progmem_read_ptr(const char *const *addr) { return *addr; } uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } } // namespace esphome diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 40382bbda7..4403281116 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -243,9 +243,8 @@ def validate_color_temperature_channels(value): return value -async def setup_light_core_(light_var, output_var, config): - await setup_entity(light_var, config, "light") - +@setup_entity("light") +async def setup_light_core_(light_var, config, output_var): cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE])) if (initial_state_config := config.get(CONF_INITIAL_STATE)) is not None: @@ -312,7 +311,7 @@ async def register_light(output_var, config): cg.add(cg.App.register_light(light_var)) CORE.register_platform_component("light", light_var) await cg.register_component(light_var, config) - await setup_light_core_(light_var, output_var, config) + await setup_light_core_(light_var, config, output_var) async def new_light(config, *args): diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index 9d893d3ad9..e37092756f 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -91,9 +91,8 @@ def lock_schema( return _LOCK_SCHEMA.extend(schema) +@setup_entity("lock") async def _setup_lock_core(var, config): - await setup_entity(var, config, "lock") - for conf in config.get(CONF_ON_LOCK, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index b2afbe5e58..051e386eaf 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -96,8 +96,8 @@ VolumeSetAction = media_player_ns.class_( ) +@setup_entity("media_player") async def setup_media_player_core_(var, config): - await setup_entity(var, config, "media_player") for conf_key, _ in _STATE_TRIGGERS: for conf in config.get(conf_key, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index fdc909fcc9..a2734f2beb 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -48,7 +48,7 @@ void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon root[MQTT_MAX] = traits.get_max_value(); root[MQTT_STEP] = traits.get_step(); // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto unit_of_measurement = this->number_->traits.get_unit_of_measurement_ref(); + const auto unit_of_measurement = this->number_->get_unit_of_measurement_ref(); if (!unit_of_measurement.empty()) { root[MQTT_UNIT_OF_MEASUREMENT] = unit_of_measurement; } @@ -57,7 +57,7 @@ void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon root[MQTT_MODE] = NumberMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), static_cast<uint8_t>(NUMBER_MODE_BOX)); } - const auto device_class = this->number_->traits.get_device_class_ref(); + const auto device_class = this->number_->get_device_class_ref(); if (!device_class.empty()) { root[MQTT_DEVICE_CLASS] = device_class; } diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 2238f2c037..0570ac0b1e 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -79,7 +79,12 @@ from esphome.const import ( DEVICE_CLASS_WIND_SPEED, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, + setup_unit_of_measurement, +) from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@esphome/core"] @@ -257,11 +262,10 @@ async def _build_number_automations(var, config): await automation.build_automation(trigger, [(float, "x")], conf) +@setup_entity("number") async def setup_number_core_( var, config, *, min_value: float, max_value: float, step: float ): - await setup_entity(var, config, "number") - cg.add(var.traits.set_min_value(min_value)) cg.add(var.traits.set_max_value(max_value)) cg.add(var.traits.set_step(step)) @@ -273,10 +277,8 @@ async def setup_number_core_( CORE.add_job(_build_number_automations, var, config) - if (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) is not None: - cg.add(var.traits.set_unit_of_measurement(unit_of_measurement)) - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.traits.set_device_class(device_class)) + setup_device_class(config) + setup_unit_of_measurement(config) if (mqtt_id := config.get(CONF_MQTT_ID)) is not None: mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index 1c4126496c..c0653c3b30 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -15,8 +15,8 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str()); LOG_ENTITY_ICON(tag, prefix, *obj); - LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, obj->traits); - LOG_ENTITY_DEVICE_CLASS(tag, prefix, obj->traits); + LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, *obj); + LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj); } void Number::publish_state(float state) { diff --git a/esphome/components/number/number_traits.h b/esphome/components/number/number_traits.h index 5ccbb9ba48..f855813c9b 100644 --- a/esphome/components/number/number_traits.h +++ b/esphome/components/number/number_traits.h @@ -1,7 +1,7 @@ #pragma once -#include "esphome/core/entity_base.h" -#include "esphome/core/helpers.h" +#include <cmath> +#include <cstdint> namespace esphome::number { @@ -11,7 +11,7 @@ enum NumberMode : uint8_t { NUMBER_MODE_SLIDER = 2, }; -class NumberTraits : public EntityBase_DeviceClass, public EntityBase_UnitOfMeasurement { +class NumberTraits { public: // Set/get the number value boundaries. void set_min_value(float min_value) { min_value_ = min_value; } diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index a15ee7e263..63b154d80d 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -34,6 +34,9 @@ void HOT arch_feed_wdt() { watchdog_update(); } uint8_t progmem_read_byte(const uint8_t *addr) { return pgm_read_byte(addr); // NOLINT } +const char *progmem_read_ptr(const char *const *addr) { + return reinterpret_cast<const char *>(pgm_read_ptr(addr)); // NOLINT +} uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); } uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); } diff --git a/esphome/components/select/__init__.py b/esphome/components/select/__init__.py index c114b140a9..b2c17f59ac 100644 --- a/esphome/components/select/__init__.py +++ b/esphome/components/select/__init__.py @@ -92,9 +92,8 @@ def select_schema( return _SELECT_SCHEMA.extend(schema) +@setup_entity("select") async def setup_select_core_(var, config, *, options: list[str]): - await setup_entity(var, config, "select") - cg.add(var.traits.set_options(options)) for conf in config.get(CONF_ON_VALUE, []): diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 338aaae0b5..4be6ed1b84 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -106,7 +106,12 @@ from esphome.const import ( ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, + setup_unit_of_measurement, +) from esphome.cpp_generator import MockObj, MockObjClass from esphome.util import Registry @@ -908,15 +913,12 @@ async def _build_sensor_automations(var, config): await automation.build_automation(trigger, [(float, "x")], conf) +@setup_entity("sensor") async def setup_sensor_core_(var, config): - await setup_entity(var, config, "sensor") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) + setup_unit_of_measurement(config) if (state_class := config.get(CONF_STATE_CLASS)) is not None: cg.add(var.set_state_class(state_class)) - if (unit_of_measurement := config.get(CONF_UNIT_OF_MEASUREMENT)) is not None: - cg.add(var.set_unit_of_measurement(unit_of_measurement)) if (accuracy_decimals := config.get(CONF_ACCURACY_DECIMALS)) is not None: cg.add(var.set_accuracy_decimals(accuracy_decimals)) # Only set force_update if True (default is False) diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index 54e75ee2a1..197896f6f6 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -44,7 +44,7 @@ const LogString *state_class_to_string(StateClass state_class); * * A sensor has unit of measurement and can use publish_state to send out a new value with the specified accuracy. */ -class Sensor : public EntityBase, public EntityBase_DeviceClass, public EntityBase_UnitOfMeasurement { +class Sensor : public EntityBase { public: explicit Sensor(); diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index d82d7baaf6..44fb9092bc 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -567,7 +567,7 @@ void Sprinkler::set_valve_run_duration(const optional<size_t> valve_number, cons return; } auto call = this->valve_[valve_number.value()].run_duration_number->make_call(); - if (this->valve_[valve_number.value()].run_duration_number->traits.get_unit_of_measurement_ref() == MIN_STR) { + if (this->valve_[valve_number.value()].run_duration_number->get_unit_of_measurement_ref() == MIN_STR) { call.set_value(run_duration.value() / 60.0); } else { call.set_value(run_duration.value()); @@ -649,7 +649,7 @@ uint32_t Sprinkler::valve_run_duration(const size_t valve_number) { return 0; } if (this->valve_[valve_number].run_duration_number != nullptr) { - if (this->valve_[valve_number].run_duration_number->traits.get_unit_of_measurement_ref() == MIN_STR) { + if (this->valve_[valve_number].run_duration_number->get_unit_of_measurement_ref() == MIN_STR) { return static_cast<uint32_t>(roundf(this->valve_[valve_number].run_duration_number->state * 60)); } else { return static_cast<uint32_t>(roundf(this->valve_[valve_number].run_duration_number->state)); diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 6f1be7d53d..bbafc54bd1 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -22,7 +22,11 @@ from esphome.const import ( DEVICE_CLASS_SWITCH, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@esphome/core"] @@ -154,9 +158,8 @@ async def _build_switch_automations(var, config): await automation.build_automation(trigger, [], conf) +@setup_entity("switch") async def setup_switch_core_(var, config): - await setup_entity(var, config, "switch") - if (inverted := config.get(CONF_INVERTED)) is not None: cg.add(var.set_inverted(inverted)) @@ -169,8 +172,7 @@ async def setup_switch_core_(var, config): if web_server_config := config.get(CONF_WEB_SERVER): await web_server.add_entity_config(var, web_server_config) - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) await zigbee.setup_switch(var, config) diff --git a/esphome/components/switch/switch.h b/esphome/components/switch/switch.h index 982c640cf9..c4f8525793 100644 --- a/esphome/components/switch/switch.h +++ b/esphome/components/switch/switch.h @@ -35,7 +35,7 @@ enum SwitchRestoreMode : uint8_t { * A switch is basically just a combination of a binary sensor (for reporting switch values) * and a write_state method that writes a state to the hardware. */ -class Switch : public EntityBase, public EntityBase_DeviceClass { +class Switch : public EntityBase { public: explicit Switch(); diff --git a/esphome/components/text/__init__.py b/esphome/components/text/__init__.py index 61f7119cad..224f4580d4 100644 --- a/esphome/components/text/__init__.py +++ b/esphome/components/text/__init__.py @@ -84,6 +84,7 @@ def text_schema( return _TEXT_SCHEMA.extend(schema) +@setup_entity("text") async def setup_text_core_( var, config, @@ -92,8 +93,6 @@ async def setup_text_core_( max_length: int | None, pattern: str | None, ): - await setup_entity(var, config, "text") - cg.add(var.traits.set_min_length(min_length)) cg.add(var.traits.set_max_length(max_length)) if pattern is not None: diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 2edf202cd2..97f394ecf7 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -21,7 +21,11 @@ from esphome.const import ( DEVICE_CLASS_TIMESTAMP, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass from esphome.util import Registry @@ -208,11 +212,9 @@ async def _build_text_sensor_automations(var, config): await automation.build_automation(trigger, [(cg.std_string, "x")], conf) +@setup_entity("text_sensor") async def setup_text_sensor_core_(var, config): - await setup_entity(var, config, "text_sensor") - - if (device_class := config.get(CONF_DEVICE_CLASS)) is not None: - cg.add(var.set_device_class(device_class)) + setup_device_class(config) if config.get(CONF_FILTERS): # must exist and not be empty cg.add_define("USE_TEXT_SENSOR_FILTER") diff --git a/esphome/components/text_sensor/text_sensor.h b/esphome/components/text_sensor/text_sensor.h index 9916aa63b2..d26cfade96 100644 --- a/esphome/components/text_sensor/text_sensor.h +++ b/esphome/components/text_sensor/text_sensor.h @@ -25,7 +25,7 @@ void log_text_sensor(const char *tag, const char *prefix, const char *type, Text public: \ void set_##name##_text_sensor(text_sensor::TextSensor *text_sensor) { this->name##_text_sensor_ = text_sensor; } -class TextSensor : public EntityBase, public EntityBase_DeviceClass { +class TextSensor : public EntityBase { public: std::string state; diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index e146f7e685..c36a4ab769 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -15,7 +15,11 @@ from esphome.const import ( ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass CODEOWNERS = ["@jesserockz"] @@ -87,11 +91,9 @@ def update_schema( return _UPDATE_SCHEMA.extend(schema) +@setup_entity("update") async def setup_update_core_(var, config): - await setup_entity(var, config, "update") - - if device_class_config := config.get(CONF_DEVICE_CLASS): - cg.add(var.set_device_class(device_class_config)) + setup_device_class(config) if on_update_available := config.get(CONF_ON_UPDATE_AVAILABLE): await automation.build_automation( diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h index 405346bee4..82eaacaf76 100644 --- a/esphome/components/update/update_entity.h +++ b/esphome/components/update/update_entity.h @@ -29,7 +29,7 @@ enum UpdateState : uint8_t { const LogString *update_state_to_string(UpdateState state); -class UpdateEntity : public EntityBase, public EntityBase_DeviceClass { +class UpdateEntity : public EntityBase { public: void publish_state(); diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 73e907eb0f..22cd01988d 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -22,7 +22,11 @@ from esphome.const import ( DEVICE_CLASS_WATER, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority -from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity +from esphome.core.entity_helpers import ( + entity_duplicate_validator, + setup_device_class, + setup_entity, +) from esphome.cpp_generator import MockObjClass IS_PLATFORM_COMPONENT = True @@ -129,11 +133,9 @@ def valve_schema( return _VALVE_SCHEMA.extend(schema) +@setup_entity("valve") async def _setup_valve_core(var, config): - await setup_entity(var, config, "valve") - - if device_class_config := config.get(CONF_DEVICE_CLASS): - cg.add(var.set_device_class(device_class_config)) + setup_device_class(config) for conf in config.get(CONF_ON_OPEN, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) diff --git a/esphome/components/valve/valve.h b/esphome/components/valve/valve.h index cd46144372..aab819a778 100644 --- a/esphome/components/valve/valve.h +++ b/esphome/components/valve/valve.h @@ -101,7 +101,7 @@ const LogString *valve_operation_to_str(ValveOperation op); * to control all values of the valve. Also implement get_traits() to return what operations * the valve supports. */ -class Valve : public EntityBase, public EntityBase_DeviceClass { +class Valve : public EntityBase { public: explicit Valve(); diff --git a/esphome/components/water_heater/__init__.py b/esphome/components/water_heater/__init__.py index db32c2d919..58cf5a4054 100644 --- a/esphome/components/water_heater/__init__.py +++ b/esphome/components/water_heater/__init__.py @@ -69,10 +69,9 @@ def water_heater_schema( return _WATER_HEATER_SCHEMA.extend(schema) +@setup_entity("water_heater") async def setup_water_heater_core_(var: cg.Pvariable, config: ConfigType) -> None: """Set up the core water heater properties in C++.""" - await setup_entity(var, config, "water_heater") - visual = config[CONF_VISUAL] if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None: cg.add_define("USE_WATER_HEATER_VISUAL_OVERRIDES") diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 47e427c0d1..6b94a103cc 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1139,7 +1139,7 @@ json::SerializationBuffer<> WebServer::number_json_(number::Number *obj, float v json::JsonBuilder builder; JsonObject root = builder.root(); - const auto uom_ref = obj->traits.get_unit_of_measurement_ref(); + const auto uom_ref = obj->get_unit_of_measurement_ref(); const int8_t accuracy = step_to_accuracy_decimals(obj->traits.get_step()); // Need two buffers: one for value, one for state with UOM diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index cf3ea70245..eee7fb3f4f 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -60,6 +60,7 @@ void arch_restart() { sys_reboot(SYS_REBOOT_COLD); } uint32_t arch_get_cpu_cycle_count() { return k_cycle_get_32(); } uint32_t arch_get_cpu_freq_hz() { return sys_clock_hw_cycles_per_sec(); } uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +const char *progmem_read_ptr(const char *const *addr) { return *addr; } uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } Mutex::Mutex() { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 8d778edf2a..07afefd91a 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -44,7 +44,9 @@ #define USE_DEEP_SLEEP #define USE_DEVICES #define USE_DISPLAY +#define USE_ENTITY_DEVICE_CLASS #define USE_ENTITY_ICON +#define USE_ENTITY_UNIT_OF_MEASUREMENT #define USE_ESP32_CAMERA_JPEG_CONVERSION #define USE_ESP32_HOSTED #define USE_ESP32_IMPROV_STATE_CALLBACK diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index f6a7ec1dfd..eafc04f92a 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -45,24 +45,42 @@ void EntityBase::set_name(const char *name, uint32_t object_id_hash) { } } -// Entity Icon -std::string EntityBase::get_icon() const { -#ifdef USE_ENTITY_ICON - if (this->icon_c_str_ == nullptr) { - return ""; - } - return this->icon_c_str_; +// Weak default lookup functions — overridden by generated code in main.cpp +__attribute__((weak)) const char *entity_device_class_lookup(uint8_t) { return ""; } +__attribute__((weak)) const char *entity_uom_lookup(uint8_t) { return ""; } +__attribute__((weak)) const char *entity_icon_lookup(uint8_t) { return ""; } + +// Entity device class (from index) +StringRef EntityBase::get_device_class_ref() const { +#ifdef USE_ENTITY_DEVICE_CLASS + return StringRef(entity_device_class_lookup(this->device_class_idx_)); #else - return ""; + return StringRef(entity_device_class_lookup(0)); #endif } -void EntityBase::set_icon(const char *icon) { -#ifdef USE_ENTITY_ICON - this->icon_c_str_ = icon; +std::string EntityBase::get_device_class() const { return std::string(this->get_device_class_ref().c_str()); } + +// Entity unit of measurement (from index) +StringRef EntityBase::get_unit_of_measurement_ref() const { +#ifdef USE_ENTITY_UNIT_OF_MEASUREMENT + return StringRef(entity_uom_lookup(this->uom_idx_)); #else - // No-op when USE_ENTITY_ICON is not defined + return StringRef(entity_uom_lookup(0)); #endif } +std::string EntityBase::get_unit_of_measurement() const { + return std::string(this->get_unit_of_measurement_ref().c_str()); +} + +// Entity icon (from index) +StringRef EntityBase::get_icon_ref() const { +#ifdef USE_ENTITY_ICON + return StringRef(entity_icon_lookup(this->icon_idx_)); +#else + return StringRef(entity_icon_lookup(0)); +#endif +} +std::string EntityBase::get_icon() const { return std::string(this->get_icon_ref().c_str()); } // Entity Object ID - computed on-demand from name std::string EntityBase::get_object_id() const { @@ -134,24 +152,6 @@ ESPPreferenceObject EntityBase::make_entity_preference_(size_t size, uint32_t ve return global_preferences->make_preference(size, key); } -std::string EntityBase_DeviceClass::get_device_class() { - if (this->device_class_ == nullptr) { - return ""; - } - return this->device_class_; -} - -void EntityBase_DeviceClass::set_device_class(const char *device_class) { this->device_class_ = device_class; } - -std::string EntityBase_UnitOfMeasurement::get_unit_of_measurement() { - if (this->unit_of_measurement_ == nullptr) - return ""; - return this->unit_of_measurement_; -} -void EntityBase_UnitOfMeasurement::set_unit_of_measurement(const char *unit_of_measurement) { - this->unit_of_measurement_ = unit_of_measurement; -} - #ifdef USE_ENTITY_ICON void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) { if (!obj.get_icon_ref().empty()) { @@ -160,13 +160,13 @@ void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) } #endif -void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj) { +void log_entity_device_class(const char *tag, const char *prefix, const EntityBase &obj) { if (!obj.get_device_class_ref().empty()) { ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj.get_device_class_ref().c_str()); } } -void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase_UnitOfMeasurement &obj) { +void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase &obj) { if (!obj.get_unit_of_measurement_ref().empty()) { ESP_LOGCONFIG(tag, "%s Unit of Measurement: '%s'", prefix, obj.get_unit_of_measurement_ref().c_str()); } diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index cbc07cc44c..042eebb40f 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -14,6 +14,12 @@ namespace esphome { +// Extern lookup functions for entity string tables. +// Generated code provides strong definitions; weak defaults return "". +extern const char *entity_device_class_lookup(uint8_t index); +extern const char *entity_uom_lookup(uint8_t index); +extern const char *entity_icon_lookup(uint8_t index); + // Maximum device name length - keep in sync with validate_hostname() in esphome/core/config.py static constexpr size_t ESPHOME_DEVICE_NAME_MAX_LEN = 31; @@ -89,20 +95,41 @@ class EntityBase { this->flags_.entity_category = static_cast<uint8_t>(entity_category); } + // Set entity string table indices — one call per entity from codegen. + // Packed: [23..16] icon | [15..8] UoM | [7..0] device_class (each 8 bits) + void set_entity_strings([[maybe_unused]] uint32_t packed) { +#ifdef USE_ENTITY_DEVICE_CLASS + this->device_class_idx_ = packed & 0xFF; +#endif +#ifdef USE_ENTITY_UNIT_OF_MEASUREMENT + this->uom_idx_ = (packed >> 8) & 0xFF; +#endif +#ifdef USE_ENTITY_ICON + this->icon_idx_ = (packed >> 16) & 0xFF; +#endif + } + + // Get device class as StringRef (from packed index) + StringRef get_device_class_ref() const; + /// Get the device class as std::string (deprecated, prefer get_device_class_ref()) + ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in " + "ESPHome 2026.9.0", + "2026.3.0") + std::string get_device_class() const; + // Get unit of measurement as StringRef (from packed index) + StringRef get_unit_of_measurement_ref() const; + /// Get the unit of measurement as std::string (deprecated, prefer get_unit_of_measurement_ref()) + ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be " + "removed in ESPHome 2026.9.0", + "2026.3.0") + std::string get_unit_of_measurement() const; + // Get/set this entity's icon ESPDEPRECATED( "Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0", "2025.11.0") std::string get_icon() const; - void set_icon(const char *icon); - StringRef get_icon_ref() const { - static constexpr auto EMPTY_STRING = StringRef::from_lit(""); -#ifdef USE_ENTITY_ICON - return this->icon_c_str_ == nullptr ? EMPTY_STRING : StringRef(this->icon_c_str_); -#else - return EMPTY_STRING; -#endif - } + StringRef get_icon_ref() const; #ifdef USE_DEVICES // Get/set this entity's device id @@ -173,9 +200,6 @@ class EntityBase { void calc_object_id_(); StringRef name_; -#ifdef USE_ENTITY_ICON - const char *icon_c_str_{nullptr}; -#endif uint32_t object_id_hash_{}; #ifdef USE_DEVICES Device *device_{}; @@ -190,44 +214,16 @@ class EntityBase { uint8_t entity_category : 2; // Supports up to 4 categories uint8_t reserved : 2; // Reserved for future use } flags_{}; -}; - -class EntityBase_DeviceClass { // NOLINT(readability-identifier-naming) - public: - /// Get the device class, using the manual override if set. - ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in " - "ESPHome 2026.5.0", - "2025.11.0") - std::string get_device_class(); - /// Manually set the device class. - void set_device_class(const char *device_class); - /// Get the device class as StringRef - StringRef get_device_class_ref() const { - static constexpr auto EMPTY_STRING = StringRef::from_lit(""); - return this->device_class_ == nullptr ? EMPTY_STRING : StringRef(this->device_class_); - } - - protected: - const char *device_class_{nullptr}; ///< Device class override -}; - -class EntityBase_UnitOfMeasurement { // NOLINT(readability-identifier-naming) - public: - /// Get the unit of measurement, using the manual override if set. - ESPDEPRECATED("Use get_unit_of_measurement_ref() instead for better performance (avoids string copy). Will be " - "removed in ESPHome 2026.5.0", - "2025.11.0") - std::string get_unit_of_measurement(); - /// Manually set the unit of measurement. - void set_unit_of_measurement(const char *unit_of_measurement); - /// Get the unit of measurement as StringRef - StringRef get_unit_of_measurement_ref() const { - static constexpr auto EMPTY_STRING = StringRef::from_lit(""); - return this->unit_of_measurement_ == nullptr ? EMPTY_STRING : StringRef(this->unit_of_measurement_); - } - - protected: - const char *unit_of_measurement_{nullptr}; ///< Unit of measurement override + // String table indices — packed into the 3 padding bytes after flags_ +#ifdef USE_ENTITY_DEVICE_CLASS + uint8_t device_class_idx_{}; +#endif +#ifdef USE_ENTITY_UNIT_OF_MEASUREMENT + uint8_t uom_idx_{}; +#endif +#ifdef USE_ENTITY_ICON + uint8_t icon_idx_{}; +#endif }; /// Log entity icon if set (for use in dump_config) @@ -240,10 +236,10 @@ inline void log_entity_icon(const char *, const char *, const EntityBase &) {} #endif /// Log entity device class if set (for use in dump_config) #define LOG_ENTITY_DEVICE_CLASS(tag, prefix, obj) log_entity_device_class(tag, prefix, obj) -void log_entity_device_class(const char *tag, const char *prefix, const EntityBase_DeviceClass &obj); +void log_entity_device_class(const char *tag, const char *prefix, const EntityBase &obj); /// Log entity unit of measurement if set (for use in dump_config) #define LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, obj) log_entity_unit_of_measurement(tag, prefix, obj) -void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase_UnitOfMeasurement &obj); +void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase &obj); /** * An entity that has a state. diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index c1801c0bda..551e35df65 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -1,9 +1,12 @@ from collections.abc import Callable +from dataclasses import dataclass, field +import functools import logging import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( + CONF_DEVICE_CLASS, CONF_DEVICE_ID, CONF_DISABLED_BY_DEFAULT, CONF_ENTITY_CATEGORY, @@ -11,15 +14,184 @@ from esphome.const import ( CONF_ID, CONF_INTERNAL, CONF_NAME, + CONF_UNIT_OF_MEASUREMENT, ) -from esphome.core import CORE, ID -from esphome.cpp_generator import MockObj, add, get_variable +from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority +from esphome.cpp_generator import MockObj, RawStatement, add, get_variable import esphome.final_validate as fv -from esphome.helpers import fnv1_hash_object_id, sanitize, snake_case +from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case from esphome.types import ConfigType, EntityMetadata _LOGGER = logging.getLogger(__name__) +DOMAIN = "entity_string_pool" + +# Private config keys for storing registered string indices +_KEY_DC_IDX = "_entity_dc_idx" +_KEY_UOM_IDX = "_entity_uom_idx" +_KEY_ICON_IDX = "_entity_icon_idx" + +# Bit layout for set_entity_strings(packed) — must match C++ setter in entity_base.h: +# [23..16] icon (8 bits) | [15..8] UoM (8 bits) | [7..0] device_class (8 bits) +_DC_SHIFT = 0 +_UOM_SHIFT = 8 +_ICON_SHIFT = 16 + +# Maximum unique strings per category (8-bit index, 0 = not set) +_MAX_DEVICE_CLASSES = 0xFF # 255 +_MAX_UNITS = 0xFF # 255 +_MAX_ICONS = 0xFF # 255 + + +@dataclass +class EntityStringPool: + """Pool of entity string properties for PROGMEM pointer tables. + + Strings are registered during to_code() and assigned 1-based indices. + Index 0 means "not set" (empty string). At render time, the pool + generates C++ PROGMEM pointer table + lookup function per category. + """ + + device_classes: dict[str, int] = field(default_factory=dict) + units: dict[str, int] = field(default_factory=dict) + icons: dict[str, int] = field(default_factory=dict) + tables_registered: bool = False + + +def _get_pool() -> EntityStringPool: + """Get or create the entity string pool from CORE.data.""" + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = EntityStringPool() + return CORE.data[DOMAIN] + + +def _ensure_tables_registered() -> None: + """Schedule the table generation job (once).""" + pool = _get_pool() + if pool.tables_registered: + return + pool.tables_registered = True + CORE.add_job(_generate_tables_job) + + +def _generate_category_code( + table_var: str, + lookup_fn: str, + strings: dict[str, int], +) -> str: + """Generate C++ code for one string category (PROGMEM pointer table + lookup). + + Uses a PROGMEM array of string pointers. On ESP8266, pointers are stored + in flash (via PROGMEM) and read with progmem_read_ptr(). String literals + themselves remain in RAM but benefit from linker string deduplication. + Index 0 means "not set" and returns empty string. + """ + if not strings: + return "" + + sorted_strings = sorted(strings.items(), key=lambda x: x[1]) + entries = ", ".join(cpp_string_escape(s) for s, _ in sorted_strings) + count = len(sorted_strings) + + return ( + f"static const char *const {table_var}[] PROGMEM = {{{entries}}};\n" + f"const char *{lookup_fn}(uint8_t index) {{\n" + f' if (index == 0 || index > {count}) return "";\n' + f" return progmem_read_ptr(&{table_var}[index - 1]);\n" + f"}}\n" + ) + + +_CATEGORY_CONFIGS = ( + ("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes"), + ("ENTITY_UOM_TABLE", "entity_uom_lookup", "units"), + ("ENTITY_ICON_TABLE", "entity_icon_lookup", "icons"), +) + + +@coroutine_with_priority(CoroPriority.FINAL) +async def _generate_tables_job() -> None: + """Generate all entity string table C++ code as a FINAL-priority job. + + Runs after all component to_code() calls have registered their strings. + """ + pool = _get_pool() + parts = ["namespace esphome {"] + for table_var, lookup_fn, attr in _CATEGORY_CONFIGS: + code = _generate_category_code(table_var, lookup_fn, getattr(pool, attr)) + if code: + parts.append(code) + parts.append("} // namespace esphome") + cg.add_global(RawStatement("\n".join(parts))) + + +def _register_string( + value: str, category: dict[str, int], max_count: int, category_name: str +) -> int: + """Register a string in a category dict and return its 1-based index. + + Returns 0 if value is empty/None (meaning "not set"). + """ + if not value: + return 0 + if value in category: + return category[value] + idx = len(category) + 1 + if idx > max_count: + raise ValueError( + f"Too many unique {category_name} values (max {max_count}), got {idx}: '{value}'" + ) + category[value] = idx + _ensure_tables_registered() + return idx + + +def register_device_class(value: str) -> int: + """Register a device_class string and return its 1-based index.""" + return _register_string( + value, _get_pool().device_classes, _MAX_DEVICE_CLASSES, "device_class" + ) + + +def register_unit_of_measurement(value: str) -> int: + """Register a unit_of_measurement string and return its 1-based index.""" + return _register_string(value, _get_pool().units, _MAX_UNITS, "unit_of_measurement") + + +def register_icon(value: str) -> int: + """Register an icon string and return its 1-based index.""" + return _register_string(value, _get_pool().icons, _MAX_ICONS, "icon") + + +def setup_device_class(config: ConfigType) -> None: + """Register config's device_class and store its index for finalize_entity_strings.""" + idx = register_device_class(config.get(CONF_DEVICE_CLASS, "")) + if idx: + cg.add_define("USE_ENTITY_DEVICE_CLASS") + config[_KEY_DC_IDX] = idx + + +def setup_unit_of_measurement(config: ConfigType) -> None: + """Register config's unit_of_measurement and store its index for finalize_entity_strings.""" + idx = register_unit_of_measurement(config.get(CONF_UNIT_OF_MEASUREMENT, "")) + if idx: + cg.add_define("USE_ENTITY_UNIT_OF_MEASUREMENT") + config[_KEY_UOM_IDX] = idx + + +def finalize_entity_strings(var: MockObj, config: ConfigType) -> None: + """Emit a single set_entity_strings() call with all packed indices. + + Call this at the end of each component's setup function, after + setup_entity() and any register_device_class/register_unit_of_measurement calls. + """ + dc_idx = config.get(_KEY_DC_IDX, 0) + uom_idx = config.get(_KEY_UOM_IDX, 0) + icon_idx = config.get(_KEY_ICON_IDX, 0) + packed = (dc_idx << _DC_SHIFT) | (uom_idx << _UOM_SHIFT) | (icon_idx << _ICON_SHIFT) + if packed != 0: + add(var.set_entity_strings(packed)) + def get_base_entity_object_id( name: str, friendly_name: str | None, device_name: str | None = None @@ -64,8 +236,48 @@ def get_base_entity_object_id( return sanitize(snake_case(base_str)) -async def setup_entity(var: MockObj, config: ConfigType, platform: str) -> None: - """Set up generic properties of an Entity. +def setup_entity(var_or_platform, config=None, platform=None): + """Set up entity properties — works as both decorator and direct call. + + Decorator mode:: + + @setup_entity("sensor") + async def setup_sensor_core_(var, config): + setup_device_class(config) + setup_unit_of_measurement(config) + ... + + Direct call mode (for entities with no extra string properties):: + + await setup_entity(var, config, "camera") + """ + if isinstance(var_or_platform, str) and config is None: + # Decorator mode: @setup_entity("sensor") + platform = var_or_platform + + def decorator(func: Callable) -> Callable: + @functools.wraps(func) + async def wrapper( + var: MockObj, config: ConfigType, *args, **kwargs + ) -> None: + await _setup_entity_impl(var, config, platform) + await func(var, config, *args, **kwargs) + finalize_entity_strings(var, config) + + return wrapper + + return decorator + + # Direct call mode: await setup_entity(var, config, "camera") + async def _do() -> None: + await _setup_entity_impl(var_or_platform, config, platform) + finalize_entity_strings(var_or_platform, config) + + return _do() + + +async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> None: + """Set up generic properties of an Entity (internal implementation). This function sets up the common entity properties like name, icon, entity category, etc. @@ -92,12 +304,15 @@ async def setup_entity(var: MockObj, config: ConfigType, platform: str) -> None: add(var.set_disabled_by_default(True)) if CONF_INTERNAL in config: add(var.set_internal(config[CONF_INTERNAL])) + icon_idx = 0 if CONF_ICON in config: # Add USE_ENTITY_ICON define when icons are used cg.add_define("USE_ENTITY_ICON") - add(var.set_icon(config[CONF_ICON])) + icon_idx = register_icon(config[CONF_ICON]) if CONF_ENTITY_CATEGORY in config: add(var.set_entity_category(config[CONF_ENTITY_CATEGORY])) + # Store icon index for finalize_entity_strings + config[_KEY_ICON_IDX] = icon_idx def inherit_property_from(property_to_inherit, parent_id_property, transform=None): diff --git a/esphome/core/hal.h b/esphome/core/hal.h index ef45be629d..c2c9b1a325 100644 --- a/esphome/core/hal.h +++ b/esphome/core/hal.h @@ -42,6 +42,7 @@ void arch_feed_wdt(); uint32_t arch_get_cpu_cycle_count(); uint32_t arch_get_cpu_freq_hz(); uint8_t progmem_read_byte(const uint8_t *addr); +const char *progmem_read_ptr(const char *const *addr); uint16_t progmem_read_uint16(const uint16_t *addr); } // namespace esphome diff --git a/script/clang-tidy b/script/clang-tidy index 17bcafacc7..9c2899026d 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -79,6 +79,7 @@ def clang_options(idedata): "-Dpgm_read_byte_near(s)=(*(const uint8_t *)(s))", "-Dpgm_read_word(s)=(*(const uint16_t *)(s))", "-Dpgm_read_dword(s)=(*(const uint32_t *)(s))", + "-Dpgm_read_ptr(s)=(*(const void *const *)(s))", "-DPROGMEM=", "-DPGM_P=const char *", "-DPSTR(s)=(s)", diff --git a/tests/component_tests/sensor/test_sensor.py b/tests/component_tests/sensor/test_sensor.py index 35ce1f4e11..221e7edf2c 100644 --- a/tests/component_tests/sensor/test_sensor.py +++ b/tests/component_tests/sensor/test_sensor.py @@ -11,4 +11,4 @@ def test_sensor_device_class_set(generate_main): main_cpp = generate_main("tests/component_tests/sensor/test_sensor.yaml") # Then - assert 's_1->set_device_class("voltage");' in main_cpp + assert "s_1->set_entity_strings(" in main_cpp diff --git a/tests/component_tests/text_sensor/test_text_sensor.py b/tests/component_tests/text_sensor/test_text_sensor.py index 1593d0b6d8..4aaebe04d1 100644 --- a/tests/component_tests/text_sensor/test_text_sensor.py +++ b/tests/component_tests/text_sensor/test_text_sensor.py @@ -54,5 +54,5 @@ def test_text_sensor_device_class_set(generate_main): main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") # Then - assert 'ts_2->set_device_class("timestamp");' in main_cpp - assert 'ts_3->set_device_class("date");' in main_cpp + assert "ts_2->set_entity_strings(" in main_cpp + assert "ts_3->set_entity_strings(" in main_cpp diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index a58d4784ce..a5cfad5ab6 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -11,6 +11,7 @@ from esphome.config_validation import Invalid from esphome.const import ( CONF_DEVICE_ID, CONF_DISABLED_BY_DEFAULT, + CONF_ENTITY_CATEGORY, CONF_ICON, CONF_ID, CONF_INTERNAL, @@ -18,6 +19,8 @@ from esphome.const import ( ) from esphome.core import CORE, ID, entity_helpers from esphome.core.entity_helpers import ( + _register_string, + _setup_entity_impl, entity_duplicate_validator, get_base_entity_object_id, setup_entity, @@ -305,7 +308,7 @@ async def test_setup_entity_no_duplicates(setup_test_environment: list[str]) -> CONF_NAME: "Temperature", CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var1, config1, "sensor") + await _setup_entity_impl(var1, config1, "sensor") # Get object ID from first entity object_id1 = extract_object_id_from_expressions(added_expressions) @@ -319,7 +322,7 @@ async def test_setup_entity_no_duplicates(setup_test_environment: list[str]) -> CONF_NAME: "Humidity", CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var2, config2, "sensor") + await _setup_entity_impl(var2, config2, "sensor") # Get object ID from second entity object_id2 = extract_object_id_from_expressions(added_expressions) @@ -354,7 +357,7 @@ async def test_setup_entity_different_platforms( object_ids: list[str] = [] for var, platform in platforms: added_expressions.clear() - await setup_entity(var, config, platform) + await _setup_entity_impl(var, config, platform) object_id = extract_object_id_from_expressions(added_expressions) object_ids.append(object_id) @@ -416,7 +419,7 @@ async def test_setup_entity_with_devices( object_ids: list[str] = [] for var, config in [(sensor1, config1), (sensor2, config2)]: added_expressions.clear() - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") object_id = extract_object_id_from_expressions(added_expressions) object_ids.append(object_id) @@ -438,7 +441,7 @@ async def test_setup_entity_empty_name(setup_test_environment: list[str]) -> Non CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") object_id = extract_object_id_from_expressions(added_expressions) # Should use friendly name @@ -460,7 +463,7 @@ async def test_setup_entity_special_characters( CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") object_id = extract_object_id_from_expressions(added_expressions) # Special characters should be sanitized @@ -471,7 +474,7 @@ async def test_setup_entity_special_characters( async def test_setup_entity_with_icon(setup_test_environment: list[str]) -> None: """Test setup_entity sets icon correctly.""" - added_expressions = setup_test_environment + setup_test_environment # noqa: F841 - fixture initializes CORE state var = MockObj("sensor1") @@ -481,12 +484,10 @@ async def test_setup_entity_with_icon(setup_test_environment: list[str]) -> None CONF_ICON: "mdi:thermometer", } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") - # Check icon was set - assert any( - 'sensor1.set_icon("mdi:thermometer")' in expr for expr in added_expressions - ) + # Check icon index was stored in config for finalize_entity_strings + assert config.get("_entity_icon_idx", 0) > 0 @pytest.mark.asyncio @@ -504,7 +505,7 @@ async def test_setup_entity_disabled_by_default( CONF_DISABLED_BY_DEFAULT: True, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") # Check disabled_by_default was set assert any( @@ -790,7 +791,7 @@ async def test_setup_entity_empty_name_with_device( CONF_DEVICE_ID: device_id, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") entity_helpers.get_variable = original_get_variable @@ -826,7 +827,7 @@ async def test_setup_entity_empty_name_with_mac_suffix( CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") # For empty-name entities, Python passes 0 - C++ calculates hash at runtime assert any('set_name("", 0)' in expr for expr in added_expressions), ( @@ -858,7 +859,7 @@ async def test_setup_entity_empty_name_with_mac_suffix_no_friendly_name( CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") # For empty-name entities, Python passes 0 - C++ calculates hash at runtime assert any('set_name("", 0)' in expr for expr in added_expressions), ( @@ -891,9 +892,84 @@ async def test_setup_entity_empty_name_no_mac_suffix_no_friendly_name( CONF_DISABLED_BY_DEFAULT: False, } - await setup_entity(var, config, "sensor") + await _setup_entity_impl(var, config, "sensor") # For empty-name entities, Python passes 0 - C++ calculates hash at runtime assert any('set_name("", 0)' in expr for expr in added_expressions), ( f"Expected set_name with hash 0, got {added_expressions}" ) + + +def test_register_string_overflow() -> None: + """Test _register_string raises ValueError when max count is exceeded.""" + category: dict[str, int] = {} + for i in range(3): + _register_string(f"val_{i}", category, 3, "test") + with pytest.raises(ValueError, match="Too many unique test values"): + _register_string("overflow", category, 3, "test") + + +@pytest.mark.asyncio +async def test_setup_entity_with_entity_category( + setup_test_environment: list[str], +) -> None: + """Test setup_entity sets entity_category correctly.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Temperature", + CONF_DISABLED_BY_DEFAULT: False, + CONF_ENTITY_CATEGORY: "diagnostic", + } + await _setup_entity_impl(var, config, "sensor") + assert any( + 'set_entity_category("diagnostic")' in expr for expr in added_expressions + ) + + +@pytest.mark.asyncio +async def test_setup_entity_direct_call(setup_test_environment: list[str]) -> None: + """Test setup_entity in direct call mode (legacy / backward compat).""" + added_expressions = setup_test_environment + + var = MockObj("camera1") + config = { + CONF_NAME: "My Camera", + CONF_DISABLED_BY_DEFAULT: False, + CONF_ICON: "mdi:camera", + } + + # Direct call mode: await setup_entity(var, config, "camera") + await setup_entity(var, config, "camera") + + # Should have called set_name + object_id = extract_object_id_from_expressions(added_expressions) + assert object_id == "my_camera" + + # Icon index should have been stored and finalized + assert config.get("_entity_icon_idx", 0) > 0 + + +@pytest.mark.asyncio +async def test_setup_entity_decorator_mode(setup_test_environment: list[str]) -> None: + """Test setup_entity in decorator mode.""" + added_expressions = setup_test_environment + + body_called = False + + @setup_entity("sensor") + async def my_setup(var, config): + nonlocal body_called + body_called = True + + var = MockObj("sensor1") + config = { + CONF_NAME: "Temperature", + CONF_DISABLED_BY_DEFAULT: False, + } + + await my_setup(var, config) + + assert body_called + object_id = extract_object_id_from_expressions(added_expressions) + assert object_id == "temperature" From 78602ccacb33dcf3acdad5a55be497af52cc4287 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:03:50 -1000 Subject: [PATCH 1078/2030] [ci] Add lint check to prevent powf in core and base entity platforms (#14126) --- esphome/core/helpers.cpp | 4 ++-- esphome/core/helpers.h | 4 ++-- script/ci-custom.py | 48 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index c75799fe57..00b447ebf2 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -706,7 +706,7 @@ float gamma_correct(float value, float gamma) { if (gamma <= 0.0f) return value; - return powf(value, gamma); + return powf(value, gamma); // NOLINT - deprecated, removal 2026.9.0 } float gamma_uncorrect(float value, float gamma) { if (value <= 0.0f) @@ -714,7 +714,7 @@ float gamma_uncorrect(float value, float gamma) { if (gamma <= 0.0f) return value; - return powf(value, 1 / gamma); + return powf(value, 1 / gamma); // NOLINT - deprecated, removal 2026.9.0 } void rgb_to_hsv(float red, float green, float blue, int &hue, float &saturation, float &value) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 187b383f65..6ce5de4975 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -512,8 +512,8 @@ template<size_t STACK_SIZE, typename T = uint8_t> class SmallBufferWithHeapFallb ///@{ /// Compute 10^exp using iterative multiplication/division. -/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. -/// Matches powf(10, exp) for the int8_t exponent range used by sensor accuracy_decimals. +/// Avoids pulling in powf/__ieee754_powf (~2.3KB flash) for small integer exponents. // NOLINT +/// Matches powf(10, exp) for the int8_t exponent range used by sensor accuracy_decimals. // NOLINT inline float pow10_int(int8_t exp) { float result = 1.0f; if (exp >= 0) { diff --git a/script/ci-custom.py b/script/ci-custom.py index f428eb0821..b60d7d7740 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -841,6 +841,54 @@ def lint_no_scanf(fname, match): ) +# Base entity platforms - these are linked into most builds and should not +# pull in powf/__ieee754_powf (~2.3KB flash). +BASE_ENTITY_PLATFORMS = [ + "alarm_control_panel", + "binary_sensor", + "button", + "climate", + "cover", + "datetime", + "event", + "fan", + "light", + "lock", + "media_player", + "number", + "select", + "sensor", + "switch", + "text", + "text_sensor", + "update", + "valve", + "water_heater", +] + +# Directories protected from powf: core + all base entity platforms +POWF_PROTECTED_DIRS = ["esphome/core"] + [ + f"esphome/components/{p}" for p in BASE_ENTITY_PLATFORMS +] + + +@lint_re_check( + r"[^\w]powf\s*\(" + CPP_RE_EOL, + include=[ + f"{d}/*.{ext}" for d in POWF_PROTECTED_DIRS for ext in ["h", "cpp", "tcc"] + ], +) +def lint_no_powf_in_core(fname, match): + return ( + f"{highlight('powf()')} pulls in __ieee754_powf (~2.3KB flash) and is not allowed in " + f"core or base entity platform code. These files are linked into every build.\n" + f"Please use alternatives:\n" + f" - {highlight('pow10_int(exp)')} for integer powers of 10 (from helpers.h)\n" + f" - Precomputed lookup tables for gamma/non-integer exponents\n" + f"(If powf is strictly necessary, add `// NOLINT` to the line)" + ) + + LOG_MULTILINE_RE = re.compile(r"ESP_LOG\w+\s*\(.*?;", re.DOTALL) LOG_BAD_CONTINUATION_RE = re.compile(r'\\n(?:[^ \\"\r\n\t]|"\s*\n\s*"[^ \\])') LOG_PERCENT_S_CONTINUATION_RE = re.compile(r'\\n(?:%s|"\s*\n\s*"%s)') From 4f69c487daa565dbe43a87f5b489f3dd40a3ff68 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:04:12 -1000 Subject: [PATCH 1079/2030] [bk72xx] Fix ~100ms loop stalls by raising main task priority (#14420) --- esphome/components/libretiny/core.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 893a79440a..6bb2d9dcc1 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -7,6 +7,9 @@ #include "esphome/core/helpers.h" #include "preferences.h" +#include <FreeRTOS.h> +#include <task.h> + void setup(); void loop(); @@ -22,6 +25,22 @@ void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } void arch_init() { libretiny::setup_preferences(); lt_wdt_enable(10000L); +#ifdef USE_BK72XX + // BK72xx SDK creates the main Arduino task at priority 3, which is lower than + // all WiFi (4-5), LwIP (4), and TCP/IP (7) tasks. This causes ~100ms loop + // stalls whenever WiFi background processing runs, because the main task + // cannot resume until every higher-priority task finishes. + // + // By contrast, RTL87xx creates the main task at osPriorityRealtime (highest). + // + // Raise to priority 6: above WiFi/LwIP tasks (4-5) so they don't preempt the + // main loop, but below the TCP/IP thread (7) so packet processing keeps priority. + // This is safe because ESPHome yields voluntarily via yield_with_select_() and + // the Arduino mainTask yield() after each loop() iteration. + static constexpr UBaseType_t MAIN_TASK_PRIORITY = 6; + static_assert(MAIN_TASK_PRIORITY < configMAX_PRIORITIES, "MAIN_TASK_PRIORITY must be less than configMAX_PRIORITIES"); + vTaskPrioritySet(nullptr, MAIN_TASK_PRIORITY); +#endif #if LT_GPIO_RECOVER lt_gpio_recover(); #endif From b209c903bb6991c1242d40e347e3625f594bdaab Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:05:15 -1000 Subject: [PATCH 1080/2030] [core] Inline trivial Component state accessors (#14425) --- esphome/core/component.cpp | 8 -------- esphome/core/component.h | 12 ++++++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 53cb50a44c..4ccc747819 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -233,7 +233,6 @@ void Component::call_dump_config_() { } } -uint8_t Component::get_component_state() const { return this->component_state_; } void Component::call() { uint8_t state = this->component_state_ & COMPONENT_STATE_MASK; switch (state) { @@ -339,9 +338,6 @@ void Component::reset_to_construction_state() { this->status_clear_error(); } } -bool Component::is_in_loop_state() const { - return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP; -} void Component::defer(std::function<void()> &&f) { // NOLINT App.scheduler.set_timeout(this, static_cast<const char *>(nullptr), 0, std::move(f)); } @@ -380,16 +376,12 @@ void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std: App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); #pragma GCC diagnostic pop } -bool Component::is_failed() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; } bool Component::is_ready() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP || (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE || (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP; } -bool Component::is_idle() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE; } bool Component::can_proceed() { return true; } -bool Component::status_has_warning() const { return this->component_state_ & STATUS_LED_WARNING; } -bool Component::status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; } bool Component::set_status_flag_(uint8_t flag) { if ((this->component_state_ & flag) != 0) return false; diff --git a/esphome/core/component.h b/esphome/core/component.h index d8102ea670..e5127b0c9f 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -142,7 +142,7 @@ class Component { */ virtual void on_powerdown() {} - uint8_t get_component_state() const; + uint8_t get_component_state() const { return this->component_state_; } /** Reset this component back to the construction state to allow setup to run again. * @@ -154,7 +154,7 @@ class Component { * * @return True if in loop state, false otherwise. */ - bool is_in_loop_state() const; + bool is_in_loop_state() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP; } /** Check if this component is idle. * Being idle means being in LOOP_DONE state. @@ -162,7 +162,7 @@ class Component { * * @return True if the component is idle */ - bool is_idle() const; + bool is_idle() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE; } /** Mark this component as failed. Any future timeouts/intervals/setup/loop will no longer be called. * @@ -230,15 +230,15 @@ class Component { */ void enable_loop_soon_any_context(); - bool is_failed() const; + bool is_failed() const { return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED; } bool is_ready() const; virtual bool can_proceed(); - bool status_has_warning() const; + bool status_has_warning() const { return this->component_state_ & STATUS_LED_WARNING; } - bool status_has_error() const; + bool status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; } void status_set_warning(const char *message = nullptr); void status_set_warning(const LogString *message); From 95544dddf8bd2171ff42da909fe9cd9786a10710 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 07:11:47 -1000 Subject: [PATCH 1081/2030] [ci] Add code-owner-approved label workflow (#14421) --- .github/scripts/auto-label-pr/detectors.js | 47 +----- .github/scripts/codeowners.js | 143 ++++++++++++++++ .../workflows/codeowner-approved-label.yml | 158 ++++++++++++++++++ .../workflows/codeowner-review-request.yml | 118 ++++--------- 4 files changed, 342 insertions(+), 124 deletions(-) create mode 100644 .github/scripts/codeowners.js create mode 100644 .github/workflows/codeowner-approved-label.yml diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index 80d8847bc1..832fcb41db 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -7,6 +7,7 @@ const { hasDashboardChanges, hasGitHubActionsChanges, } = require('../detect-tags'); +const { loadCodeowners, getEffectiveOwners } = require('../codeowners'); // Strategy: Merge branch detection async function detectMergeBranch(context) { @@ -148,51 +149,15 @@ async function detectGitHubActionsChanges(changedFiles) { // Strategy: Code owner detection async function detectCodeOwner(github, context, changedFiles) { const labels = new Set(); - const { owner, repo } = context.repo; try { - const { data: codeownersFile } = await github.rest.repos.getContent({ - owner, - repo, - path: 'CODEOWNERS', - }); - - const codeownersContent = Buffer.from(codeownersFile.content, 'base64').toString('utf8'); + const codeownersPatterns = loadCodeowners(); const prAuthor = context.payload.pull_request.user.login; - const codeownersLines = codeownersContent.split('\n') - .map(line => line.trim()) - .filter(line => line && !line.startsWith('#')); - - const codeownersRegexes = codeownersLines.map(line => { - const parts = line.split(/\s+/); - const pattern = parts[0]; - const owners = parts.slice(1); - - let regex; - if (pattern.endsWith('*')) { - const dir = pattern.slice(0, -1); - regex = new RegExp(`^${dir.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`); - } else if (pattern.includes('*')) { - // First escape all regex special chars except *, then replace * with .* - const regexPattern = pattern - .replace(/[.+?^${}()|[\]\\]/g, '\\$&') - .replace(/\*/g, '.*'); - regex = new RegExp(`^${regexPattern}$`); - } else { - regex = new RegExp(`^${pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`); - } - - return { regex, owners }; - }); - - for (const file of changedFiles) { - for (const { regex, owners } of codeownersRegexes) { - if (regex.test(file) && owners.some(owner => owner === `@${prAuthor}`)) { - labels.add('by-code-owner'); - return labels; - } - } + // Check if PR author is a codeowner of any changed file + const effective = getEffectiveOwners(changedFiles, codeownersPatterns); + if (effective.users.has(prAuthor)) { + labels.add('by-code-owner'); } } catch (error) { console.log('Failed to read or parse CODEOWNERS file:', error.message); diff --git a/.github/scripts/codeowners.js b/.github/scripts/codeowners.js new file mode 100644 index 0000000000..9a10391699 --- /dev/null +++ b/.github/scripts/codeowners.js @@ -0,0 +1,143 @@ +// Shared CODEOWNERS parsing and matching utilities. +// +// Used by: +// - codeowner-review-request.yml +// - codeowner-approved-label.yml +// - auto-label-pr/detectors.js (detectCodeOwner) + +/** + * Convert a CODEOWNERS glob pattern to a RegExp. + * + * Handles **, *, and ? wildcards after escaping regex-special characters. + */ +function globToRegex(pattern) { + let regexStr = pattern + .replace(/([.+^=!:${}()|[\]\\])/g, '\\$1') + .replace(/\*\*/g, '\x00GLOBSTAR\x00') // protect ** from next replace + .replace(/\*/g, '[^/]*') // single star + .replace(/\x00GLOBSTAR\x00/g, '.*') // restore globstar + .replace(/\?/g, '.'); + return new RegExp('^' + regexStr + '$'); +} + +/** + * Parse raw CODEOWNERS file content into an array of + * { pattern, regex, owners } objects. + * + * Each `owners` entry is the raw string from the file (e.g. "@user" or + * "@esphome/core"). + */ +function parseCodeowners(content) { + const lines = content + .split('\n') + .map(line => line.trim()) + .filter(line => line && !line.startsWith('#')); + + const patterns = []; + for (const line of lines) { + const parts = line.split(/\s+/); + if (parts.length < 2) continue; + + const pattern = parts[0]; + const owners = parts.slice(1); + const regex = globToRegex(pattern); + patterns.push({ pattern, regex, owners }); + } + return patterns; +} + +/** + * Fetch and parse the CODEOWNERS file via the GitHub API. + * + * @param {object} github - octokit instance from actions/github-script + * @param {string} owner - repo owner + * @param {string} repo - repo name + * @param {string} [ref] - git ref (SHA / branch) to read from + * @returns {Array<{pattern: string, regex: RegExp, owners: string[]}>} + */ +async function fetchCodeowners(github, owner, repo, ref) { + const params = { owner, repo, path: 'CODEOWNERS' }; + if (ref) params.ref = ref; + + const { data: file } = await github.rest.repos.getContent(params); + const content = Buffer.from(file.content, 'base64').toString('utf8'); + return parseCodeowners(content); +} + +/** + * Classify raw owner strings into individual users and teams. + * + * @param {string[]} rawOwners - e.g. ["@user1", "@esphome/core"] + * @returns {{ users: string[], teams: string[] }} + * users – login names without "@" + * teams – team slugs without the "org/" prefix + */ +function classifyOwners(rawOwners) { + const users = []; + const teams = []; + for (const o of rawOwners) { + const clean = o.startsWith('@') ? o.slice(1) : o; + if (clean.includes('/')) { + teams.push(clean.split('/')[1]); + } else { + users.push(clean); + } + } + return { users, teams }; +} + +/** + * For each file, find its effective codeowners using GitHub's + * "last match wins" semantics, then union across all files. + * + * @param {string[]} files - list of file paths + * @param {Array} codeownersPatterns - from parseCodeowners / fetchCodeowners + * @returns {{ users: Set<string>, teams: Set<string>, matchedFileCount: number }} + */ +function getEffectiveOwners(files, codeownersPatterns) { + const users = new Set(); + const teams = new Set(); + let matchedFileCount = 0; + + for (const file of files) { + // Last matching pattern wins for each file + let effectiveOwners = null; + for (const { regex, owners } of codeownersPatterns) { + if (regex.test(file)) { + effectiveOwners = owners; + } + } + if (effectiveOwners) { + matchedFileCount++; + const classified = classifyOwners(effectiveOwners); + for (const u of classified.users) users.add(u); + for (const t of classified.teams) teams.add(t); + } + } + + return { users, teams, matchedFileCount }; +} + +/** + * Read and parse the CODEOWNERS file from disk. + * + * Use this when the repo is already checked out (avoids an API call). + * + * @param {string} [repoRoot='.'] - path to the repo root + * @returns {Array<{pattern: string, regex: RegExp, owners: string[]}>} + */ +function loadCodeowners(repoRoot = '.') { + const fs = require('fs'); + const path = require('path'); + const content = fs.readFileSync(path.join(repoRoot, 'CODEOWNERS'), 'utf8'); + return parseCodeowners(content); +} + +module.exports = { + globToRegex, + parseCodeowners, + fetchCodeowners, + loadCodeowners, + classifyOwners, + getEffectiveOwners +}; diff --git a/.github/workflows/codeowner-approved-label.yml b/.github/workflows/codeowner-approved-label.yml new file mode 100644 index 0000000000..217ae06419 --- /dev/null +++ b/.github/workflows/codeowner-approved-label.yml @@ -0,0 +1,158 @@ +# This workflow adds/removes a 'code-owner-approved' label when a +# component-specific codeowner approves (or dismisses) a PR. +# This helps maintainers prioritize PRs that have codeowner sign-off. +# +# Only component-specific codeowners count — the catch-all @esphome/core +# team is excluded so the label reflects domain-expert approval. + +name: Codeowner Approved Label + +on: + pull_request_review: + types: [submitted, dismissed] + +permissions: + pull-requests: write + contents: read + +jobs: + codeowner-approved: + name: Run + if: ${{ github.repository == 'esphome/esphome' }} + runs-on: ubuntu-latest + steps: + - name: Checkout base branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.pull_request.base.sha }} + + - name: Check codeowner approval and update label + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + const { loadCodeowners, getEffectiveOwners } = require('./.github/scripts/codeowners.js'); + + const owner = context.repo.owner; + const repo = context.repo.repo; + const pr_number = context.payload.pull_request.number; + const LABEL_NAME = 'code-owner-approved'; + + console.log(`Processing PR #${pr_number} for codeowner approval label`); + + try { + // Get the list of changed files in this PR (with pagination) + const prFiles = await github.paginate( + github.rest.pulls.listFiles, + { + owner, + repo, + pull_number: pr_number + } + ); + + const changedFiles = prFiles.map(file => file.filename); + console.log(`Found ${changedFiles.length} changed files`); + + if (changedFiles.length === 0) { + console.log('No changed files found, skipping'); + return; + } + + // Parse CODEOWNERS from the checked-out base branch + const codeownersPatterns = loadCodeowners(); + + // Get effective owners using last-match-wins semantics + const effective = getEffectiveOwners(changedFiles, codeownersPatterns); + + // Only keep individual component-specific codeowners (exclude teams) + const componentCodeowners = effective.users; + + console.log(`Component-specific codeowners for changed files: ${Array.from(componentCodeowners).join(', ') || '(none)'}`); + + if (componentCodeowners.size === 0) { + console.log('No component-specific codeowners found for changed files'); + // Remove label if present since there are no component codeowners + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: pr_number, + name: LABEL_NAME + }); + console.log(`Removed '${LABEL_NAME}' label (no component codeowners)`); + } catch (error) { + if (error.status !== 404) { + console.log(`Failed to remove label: ${error.message}`); + } + } + return; + } + + // Get all reviews on the PR + const reviews = await github.paginate( + github.rest.pulls.listReviews, + { + owner, + repo, + pull_number: pr_number + } + ); + + // Get the latest review per user (reviews are returned chronologically) + const latestReviewByUser = new Map(); + for (const review of reviews) { + // Skip bot reviews and comment-only reviews + if (!review.user || review.user.type === 'Bot' || review.state === 'COMMENTED') continue; + latestReviewByUser.set(review.user.login, review); + } + + // Check if any component-specific codeowner has an active approval + let hasCodeownerApproval = false; + for (const [login, review] of latestReviewByUser) { + if (review.state === 'APPROVED' && componentCodeowners.has(login)) { + console.log(`Codeowner '${login}' has approved`); + hasCodeownerApproval = true; + break; + } + } + + // Get current labels to check if label is already present + const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({ + owner, + repo, + issue_number: pr_number + }); + const hasLabel = currentLabels.some(label => label.name === LABEL_NAME); + + if (hasCodeownerApproval && !hasLabel) { + // Add the label + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: pr_number, + labels: [LABEL_NAME] + }); + console.log(`Added '${LABEL_NAME}' label`); + } else if (!hasCodeownerApproval && hasLabel) { + // Remove the label + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: pr_number, + name: LABEL_NAME + }); + console.log(`Removed '${LABEL_NAME}' label`); + } catch (error) { + if (error.status !== 404) { + console.log(`Failed to remove label: ${error.message}`); + } + } + } else { + console.log(`Label already ${hasLabel ? 'present' : 'absent'}, no change needed`); + } + + } catch (error) { + console.error(error); + core.setFailed(`Failed to process codeowner approval label: ${error.message}`); + } diff --git a/.github/workflows/codeowner-review-request.yml b/.github/workflows/codeowner-review-request.yml index 6f4351b298..02bf0e4a29 100644 --- a/.github/workflows/codeowner-review-request.yml +++ b/.github/workflows/codeowner-review-request.yml @@ -24,10 +24,17 @@ jobs: if: ${{ github.repository == 'esphome/esphome' && !github.event.pull_request.draft }} runs-on: ubuntu-latest steps: + - name: Checkout base branch + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.pull_request.base.sha }} + - name: Request reviews from component codeowners uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: | + const { loadCodeowners, getEffectiveOwners } = require('./.github/scripts/codeowners.js'); + const owner = context.repo.owner; const repo = context.repo.repo; const pr_number = context.payload.pull_request.number; @@ -38,12 +45,15 @@ jobs: const BOT_COMMENT_MARKER = '<!-- codeowner-review-request-bot -->'; try { - // Get the list of changed files in this PR - const { data: files } = await github.rest.pulls.listFiles({ - owner, - repo, - pull_number: pr_number - }); + // Get the list of changed files in this PR (with pagination) + const files = await github.paginate( + github.rest.pulls.listFiles, + { + owner, + repo, + pull_number: pr_number + } + ); const changedFiles = files.map(file => file.filename); console.log(`Found ${changedFiles.length} changed files`); @@ -53,32 +63,10 @@ jobs: return; } - // Fetch CODEOWNERS file from root - const { data: codeownersFile } = await github.rest.repos.getContent({ - owner, - repo, - path: 'CODEOWNERS', - ref: context.payload.pull_request.base.sha - }); - const codeownersContent = Buffer.from(codeownersFile.content, 'base64').toString('utf8'); + // Parse CODEOWNERS from the checked-out base branch + const codeownersPatterns = loadCodeowners(); - // Parse CODEOWNERS file to extract all patterns and their owners - const codeownersLines = codeownersContent.split('\n') - .map(line => line.trim()) - .filter(line => line && !line.startsWith('#')); - - const codeownersPatterns = []; - - // Convert CODEOWNERS pattern to regex (robust glob handling) - function globToRegex(pattern) { - // Escape regex special characters except for glob wildcards - let regexStr = pattern - .replace(/([.+^=!:${}()|[\]\\])/g, '\\$1') // escape regex chars - .replace(/\*\*/g, '.*') // globstar - .replace(/\*/g, '[^/]*') // single star - .replace(/\?/g, '.'); // question mark - return new RegExp('^' + regexStr + '$'); - } + console.log(`Parsed ${codeownersPatterns.length} codeowner patterns`); // Helper function to create comment body function createCommentBody(reviewersList, teamsList, matchedFileCount, isSuccessful = true) { @@ -93,50 +81,11 @@ jobs: } } - for (const line of codeownersLines) { - const parts = line.split(/\s+/); - if (parts.length < 2) continue; - - const pattern = parts[0]; - const owners = parts.slice(1); - - // Use robust glob-to-regex conversion - const regex = globToRegex(pattern); - codeownersPatterns.push({ pattern, regex, owners }); - } - - console.log(`Parsed ${codeownersPatterns.length} codeowner patterns`); - - // Match changed files against CODEOWNERS patterns - const matchedOwners = new Set(); - const matchedTeams = new Set(); - const fileMatches = new Map(); // Track which files matched which patterns - - for (const file of changedFiles) { - for (const { pattern, regex, owners } of codeownersPatterns) { - if (regex.test(file)) { - console.log(`File '${file}' matches pattern '${pattern}' with owners: ${owners.join(', ')}`); - - if (!fileMatches.has(file)) { - fileMatches.set(file, []); - } - fileMatches.get(file).push({ pattern, owners }); - - // Add owners to the appropriate set (remove @ prefix) - for (const owner of owners) { - const cleanOwner = owner.startsWith('@') ? owner.slice(1) : owner; - if (cleanOwner.includes('/')) { - // Team mention (org/team-name) - const teamName = cleanOwner.split('/')[1]; - matchedTeams.add(teamName); - } else { - // Individual user - matchedOwners.add(cleanOwner); - } - } - } - } - } + // Match changed files against CODEOWNERS patterns using last-match-wins semantics + const effective = getEffectiveOwners(changedFiles, codeownersPatterns); + const matchedOwners = effective.users; + const matchedTeams = effective.teams; + const matchedFileCount = effective.matchedFileCount; if (matchedOwners.size === 0 && matchedTeams.size === 0) { console.log('No codeowners found for any changed files'); @@ -170,11 +119,14 @@ jobs: } // Check for completed reviews to avoid re-requesting users who have already reviewed - const { data: reviews } = await github.rest.pulls.listReviews({ - owner, - repo, - pull_number: pr_number - }); + const reviews = await github.paginate( + github.rest.pulls.listReviews, + { + owner, + repo, + pull_number: pr_number + } + ); const reviewedUsers = new Set(); reviews.forEach(review => { @@ -247,7 +199,7 @@ jobs: } const totalReviewers = reviewersList.length + teamsList.length; - console.log(`Requesting reviews from ${reviewersList.length} users and ${teamsList.length} teams for ${fileMatches.size} matched files`); + console.log(`Requesting reviews from ${reviewersList.length} users and ${teamsList.length} teams for ${matchedFileCount} matched files`); // Request reviews try { @@ -279,7 +231,7 @@ jobs: // Only add a comment if there are new codeowners to mention (not previously pinged) if (reviewersList.length > 0 || teamsList.length > 0) { - const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, true); + const commentBody = createCommentBody(reviewersList, teamsList, matchedFileCount, true); await github.rest.issues.createComment({ owner, @@ -297,7 +249,7 @@ jobs: // Only try to add a comment if there are new codeowners to mention if (reviewersList.length > 0 || teamsList.length > 0) { - const commentBody = createCommentBody(reviewersList, teamsList, fileMatches.size, false); + const commentBody = createCommentBody(reviewersList, teamsList, matchedFileCount, false); try { await github.rest.issues.createComment({ From 380c0db0205db56960f3869b341fe20629c4a4f8 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 4 Mar 2026 07:49:38 +1100 Subject: [PATCH 1082/2030] [usb_uart] Don't claim interrupt interface for ch34x (#14431) --- esphome/components/usb_uart/ch34x.cpp | 9 +++++++++ esphome/components/usb_uart/usb_uart.cpp | 14 +++++++++----- esphome/components/usb_uart/usb_uart.h | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/esphome/components/usb_uart/ch34x.cpp b/esphome/components/usb_uart/ch34x.cpp index 7fa964c0cb..e6e52a9e2a 100644 --- a/esphome/components/usb_uart/ch34x.cpp +++ b/esphome/components/usb_uart/ch34x.cpp @@ -75,6 +75,15 @@ void USBUartTypeCH34X::enable_channels() { } this->start_channels(); } + +std::vector<CdcEps> USBUartTypeCH34X::parse_descriptors(usb_device_handle_t dev_hdl) { + auto result = USBUartTypeCdcAcm::parse_descriptors(dev_hdl); + // ch34x doesn't use the interrupt endpoint, and we don't have endpoints to spare + for (auto &cdc_dev : result) { + cdc_dev.interrupt_interface_number = 0xFF; + } + return result; +} } // namespace esphome::usb_uart #endif // USE_ESP32_VARIANT_ESP32P4 || USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index de81bfc587..5c0397b2cb 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -20,6 +20,7 @@ static optional<CdcEps> get_cdc(const usb_config_desc_t *config_desc, uint8_t in // look for an interface with an interrupt endpoint (notify), and one with two bulk endpoints (data in/out) CdcEps eps{}; eps.bulk_interface_number = 0xFF; + eps.interrupt_interface_number = 0xFF; for (;;) { const auto *intf_desc = usb_parse_interface_descriptor(config_desc, intf_idx++, 0, &conf_offset); if (!intf_desc) { @@ -130,7 +131,7 @@ size_t RingBuffer::pop(uint8_t *data, size_t len) { } void USBUartChannel::write_array(const uint8_t *data, size_t len) { if (!this->initialised_.load()) { - ESP_LOGV(TAG, "Channel not initialised - write ignored"); + ESP_LOGD(TAG, "Channel not initialised - write ignored"); return; } #ifdef USE_UART_DEBUGGER @@ -415,14 +416,15 @@ void USBUartTypeCdcAcm::on_connected() { // Claim the communication (interrupt) interface so CDC class requests are accepted // by the device. Some CDC ACM implementations (e.g. EFR32 NCP) require this before // they enable data flow on the bulk endpoints. - if (channel->cdc_dev_.interrupt_interface_number != channel->cdc_dev_.bulk_interface_number) { + if (channel->cdc_dev_.interrupt_interface_number != 0xFF && + channel->cdc_dev_.interrupt_interface_number != channel->cdc_dev_.bulk_interface_number) { auto err_comm = usb_host_interface_claim(this->handle_, this->device_handle_, channel->cdc_dev_.interrupt_interface_number, 0); if (err_comm != ESP_OK) { ESP_LOGW(TAG, "Could not claim comm interface %d: %s", channel->cdc_dev_.interrupt_interface_number, esp_err_to_name(err_comm)); + channel->cdc_dev_.interrupt_interface_number = 0xFF; // Mark as unavailable, but continue anyway } else { - channel->cdc_dev_.comm_interface_claimed = true; ESP_LOGD(TAG, "Claimed comm interface %d", channel->cdc_dev_.interrupt_interface_number); } } @@ -436,6 +438,7 @@ void USBUartTypeCdcAcm::on_connected() { return; } } + this->status_clear_error(); this->enable_channels(); } @@ -453,9 +456,10 @@ void USBUartTypeCdcAcm::on_disconnected() { usb_host_endpoint_halt(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress); usb_host_endpoint_flush(this->device_handle_, channel->cdc_dev_.notify_ep->bEndpointAddress); } - if (channel->cdc_dev_.comm_interface_claimed) { + if (channel->cdc_dev_.interrupt_interface_number != 0xFF && + channel->cdc_dev_.interrupt_interface_number != channel->cdc_dev_.bulk_interface_number) { usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.interrupt_interface_number); - channel->cdc_dev_.comm_interface_claimed = false; + channel->cdc_dev_.interrupt_interface_number = 0xFF; } usb_host_interface_release(this->handle_, this->device_handle_, channel->cdc_dev_.bulk_interface_number); // Reset the input and output started flags to their initial state to avoid the possibility of spurious restarts diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 9a9fe1c2ca..0d471e46f6 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -32,7 +32,6 @@ struct CdcEps { const usb_ep_desc_t *out_ep; uint8_t bulk_interface_number; uint8_t interrupt_interface_number; - bool comm_interface_claimed{false}; }; enum UARTParityOptions { @@ -192,6 +191,7 @@ class USBUartTypeCH34X : public USBUartTypeCdcAcm { protected: void enable_channels() override; + std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override; }; } // namespace esphome::usb_uart From 96793a99ce12fe46e349ca1a165869a9f29bb842 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Tue, 3 Mar 2026 21:55:56 +0100 Subject: [PATCH 1083/2030] [rtttl] add new codeowner (#14440) --- CODEOWNERS | 2 +- esphome/components/rtttl/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 21bee125c6..b22f85b71d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -412,7 +412,7 @@ esphome/components/rp2040_pio_led_strip/* @Papa-DMan esphome/components/rp2040_pwm/* @jesserockz esphome/components/rpi_dpi_rgb/* @clydebarrow esphome/components/rtl87xx/* @kuba2k2 -esphome/components/rtttl/* @glmnet +esphome/components/rtttl/* @glmnet @ximex esphome/components/runtime_image/* @clydebarrow @guillempages @kahrendt esphome/components/runtime_stats/* @bdraco esphome/components/rx8130/* @beormund diff --git a/esphome/components/rtttl/__init__.py b/esphome/components/rtttl/__init__.py index ebbe5366aa..19412bb454 100644 --- a/esphome/components/rtttl/__init__.py +++ b/esphome/components/rtttl/__init__.py @@ -17,7 +17,7 @@ import esphome.final_validate as fv _LOGGER = logging.getLogger(__name__) -CODEOWNERS = ["@glmnet"] +CODEOWNERS = ["@glmnet", "@ximex"] CONF_RTTTL = "rtttl" CONF_ON_FINISHED_PLAYBACK = "on_finished_playback" From ee78d7a0c05b8f3d6878751c95cd5c9dae232690 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:42:41 -0500 Subject: [PATCH 1084/2030] [tests] Fix integration test race condition in PlatformIO cache init (#14435) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- tests/integration/conftest.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 36df1bc83e..b7f7fc60b3 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -73,11 +73,6 @@ def shared_platformio_cache() -> Generator[Path]: test_cache_dir = Path.home() / ".esphome-integration-tests" cache_dir = test_cache_dir / "platformio" - # Create the temp directory that PlatformIO uses to avoid race conditions - # This ensures it exists and won't be deleted by parallel processes - platformio_tmp_dir = cache_dir / ".cache" / "tmp" - platformio_tmp_dir.mkdir(parents=True, exist_ok=True) - # Use a lock file in the home directory to ensure only one process initializes the cache # This is needed when running with pytest-xdist # The lock file must be in a directory that already exists to avoid race conditions @@ -87,8 +82,9 @@ def shared_platformio_cache() -> Generator[Path]: with open(lock_file, "w") as lock_fd: fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX) - # Check if cache needs initialization while holding the lock - if not cache_dir.exists() or not any(cache_dir.iterdir()): + # Check if the native platform is installed (the actual indicator of a populated cache) + native_platform = cache_dir / "platforms" / "native" + if not native_platform.exists(): # Create the test cache directory if it doesn't exist test_cache_dir.mkdir(exist_ok=True) From 989330d6bc5caa2b94950b55d3811c5ee2c51be3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 4 Mar 2026 11:54:40 +1300 Subject: [PATCH 1085/2030] [globals] Fix handling of string booleans in yaml (#14447) --- esphome/components/globals/__init__.py | 2 +- tests/components/globals/common.yaml | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index fe11a93a4b..fe83b1ea7c 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -51,7 +51,7 @@ _RESTORING_SCHEMA = cv.Schema( def _globals_schema(config: ConfigType) -> ConfigType: """Select schema based on restore_value setting.""" - if config.get(CONF_RESTORE_VALUE, False): + if cv.boolean(config.get(CONF_RESTORE_VALUE, False)): return _RESTORING_SCHEMA(config) return _NON_RESTORING_SCHEMA(config) diff --git a/tests/components/globals/common.yaml b/tests/components/globals/common.yaml index efa3cba076..35dca0624f 100644 --- a/tests/components/globals/common.yaml +++ b/tests/components/globals/common.yaml @@ -27,3 +27,14 @@ globals: type: bool restore_value: false initial_value: "false" + # Test restore_value with string "false" - should be converted to bool false + - id: glob_no_restore_string_false + type: int + restore_value: "false" + initial_value: "42" + # Test restore_value with string "true" - should be converted to bool true + - id: glob_restore_string_true + type: int + restore_value: "true" + initial_value: "99" + update_interval: 5s From 43a6fe9b6cb446974db2f3cce1f1f9b67cbe1719 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 3 Mar 2026 19:06:36 -0600 Subject: [PATCH 1086/2030] [core] add a StaticTask helper to manage task lifecycles (#14446) --- esphome/core/config.py | 4 +++ esphome/core/static_task.cpp | 64 ++++++++++++++++++++++++++++++++++++ esphome/core/static_task.h | 50 ++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 esphome/core/static_task.cpp create mode 100644 esphome/core/static_task.h diff --git a/esphome/core/config.py b/esphome/core/config.py index 9411949bb9..4f526404fe 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -687,6 +687,10 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_ARDUINO, PlatformFramework.ESP32_IDF, }, + "static_task.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, + }, "time_64.cpp": { PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, diff --git a/esphome/core/static_task.cpp b/esphome/core/static_task.cpp new file mode 100644 index 0000000000..4cfead44c2 --- /dev/null +++ b/esphome/core/static_task.cpp @@ -0,0 +1,64 @@ +#include "esphome/core/static_task.h" + +#ifdef USE_ESP32 + +#include "esphome/core/helpers.h" + +namespace esphome { + +bool StaticTask::create(TaskFunction_t fn, const char *name, uint32_t stack_size, void *param, UBaseType_t priority, + bool use_psram) { + if (this->handle_ != nullptr) { + // Task is already created; must call destroy() first + return false; + } + + if (this->stack_buffer_ != nullptr && (stack_size > this->stack_size_ || use_psram != this->use_psram_)) { + // Existing buffer is too small or wrong memory type; deallocate to reallocate below + RAMAllocator<StackType_t> allocator(this->use_psram_ ? RAMAllocator<StackType_t>::ALLOC_EXTERNAL + : RAMAllocator<StackType_t>::ALLOC_INTERNAL); + allocator.deallocate(this->stack_buffer_, this->stack_size_); + this->stack_buffer_ = nullptr; + } + + if (this->stack_buffer_ == nullptr) { + this->stack_size_ = stack_size; + this->use_psram_ = use_psram; + RAMAllocator<StackType_t> allocator(use_psram ? RAMAllocator<StackType_t>::ALLOC_EXTERNAL + : RAMAllocator<StackType_t>::ALLOC_INTERNAL); + this->stack_buffer_ = allocator.allocate(stack_size); + } + if (this->stack_buffer_ == nullptr) { + return false; + } + + this->handle_ = xTaskCreateStatic(fn, name, this->stack_size_, param, priority, this->stack_buffer_, &this->tcb_); + if (this->handle_ == nullptr) { + this->deallocate(); + return false; + } + return true; +} + +void StaticTask::destroy() { + if (this->handle_ != nullptr) { + TaskHandle_t handle = this->handle_; + this->handle_ = nullptr; + vTaskDelete(handle); + } +} + +void StaticTask::deallocate() { + this->destroy(); + if (this->stack_buffer_ != nullptr) { + RAMAllocator<StackType_t> allocator(this->use_psram_ ? RAMAllocator<StackType_t>::ALLOC_EXTERNAL + : RAMAllocator<StackType_t>::ALLOC_INTERNAL); + allocator.deallocate(this->stack_buffer_, this->stack_size_); + this->stack_buffer_ = nullptr; + this->stack_size_ = 0; + } +} + +} // namespace esphome + +#endif // USE_ESP32 diff --git a/esphome/core/static_task.h b/esphome/core/static_task.h new file mode 100644 index 0000000000..5fd5b38f9e --- /dev/null +++ b/esphome/core/static_task.h @@ -0,0 +1,50 @@ +#pragma once + +#ifdef USE_ESP32 + +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> + +#include <cstdint> + +namespace esphome { + +/** Helper for FreeRTOS static task management. + * Bundles TaskHandle_t, StaticTask_t, and the stack buffer into one object with create/destroy methods. + */ +class StaticTask { + public: + /// @brief Check if the task has been created and not yet destroyed. + bool is_created() const { return this->handle_ != nullptr; } + + /// @brief Get the FreeRTOS task handle. + TaskHandle_t get_handle() const { return this->handle_; } + + /// @brief Allocate stack and create task. + /// @param fn Task function + /// @param name Task name (for debug) + /// @param stack_size Stack size in StackType_t words + /// @param param Parameter passed to task function + /// @param priority FreeRTOS task priority + /// @param use_psram If true, allocate stack in PSRAM; otherwise internal RAM + /// @return true on success + bool create(TaskFunction_t fn, const char *name, uint32_t stack_size, void *param, UBaseType_t priority, + bool use_psram); + + /// @brief Delete the task but keep the stack buffer allocated for reuse by a subsequent create() call. + void destroy(); + + /// @brief Delete the task (if running) and free the stack buffer. + void deallocate(); + + protected: + TaskHandle_t handle_{nullptr}; + StaticTask_t tcb_; + StackType_t *stack_buffer_{nullptr}; + uint32_t stack_size_{0}; + bool use_psram_{false}; +}; + +} // namespace esphome + +#endif // USE_ESP32 From 9371159a7e56e49f3b2ab71c6ad93034d1c29e01 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 3 Mar 2026 15:14:05 -1000 Subject: [PATCH 1087/2030] [core] Replace custom esphome::optional with std::optional (#14368) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/am43/cover/am43_cover.cpp | 5 +- esphome/components/anova/anova.cpp | 10 +- esphome/components/ballu/ballu.cpp | 2 +- .../bang_bang/bang_bang_climate.cpp | 20 +- .../bedjet/climate/bedjet_climate.cpp | 20 +- esphome/components/bedjet/fan/bedjet_fan.cpp | 8 +- esphome/components/binary/fan/binary_fan.cpp | 15 +- .../ble_presence/ble_presence_device.h | 5 +- esphome/components/ble_rssi/ble_rssi_sensor.h | 5 +- esphome/components/climate_ir/climate_ir.cpp | 25 +- .../climate_ir_lg/climate_ir_lg.cpp | 2 +- .../components/climate_ir_lg/climate_ir_lg.h | 3 +- esphome/components/coolix/coolix.cpp | 2 +- esphome/components/coolix/coolix.h | 3 +- esphome/components/copy/cover/copy_cover.cpp | 15 +- esphome/components/copy/fan/copy_fan.cpp | 20 +- .../components/copy/select/copy_select.cpp | 5 +- .../current_based/current_based_cover.cpp | 5 +- esphome/components/daikin/daikin.cpp | 2 +- esphome/components/daikin_arc/daikin_arc.cpp | 7 +- esphome/components/daikin_brc/daikin_brc.cpp | 2 +- .../deep_sleep/deep_sleep_esp8266.cpp | 2 +- esphome/components/delonghi/delonghi.cpp | 2 +- .../demo/demo_alarm_control_panel.h | 9 +- esphome/components/demo/demo_climate.h | 48 ++-- esphome/components/demo/demo_cover.h | 10 +- esphome/components/demo/demo_fan.h | 20 +- esphome/components/demo/demo_lock.h | 5 +- esphome/components/demo/demo_valve.h | 11 +- esphome/components/emmeti/emmeti.cpp | 2 +- esphome/components/endstop/endstop_cover.cpp | 5 +- .../esp32_ble_tracker/esp32_ble_tracker.h | 2 +- .../esp32_rmt_led_strip/led_strip.cpp | 5 +- .../components/fastled_base/fastled_light.cpp | 5 +- .../components/feedback/feedback_cover.cpp | 7 +- .../fujitsu_general/fujitsu_general.cpp | 2 +- esphome/components/gree/gree.cpp | 6 +- esphome/components/haier/hon_climate.cpp | 15 +- .../components/haier/smartair2_climate.cpp | 6 +- .../components/hbridge/fan/hbridge_fan.cpp | 20 +- esphome/components/he60r/he60r.cpp | 7 +- .../hitachi_ac344/hitachi_ac344.cpp | 2 +- .../hitachi_ac424/hitachi_ac424.cpp | 2 +- .../media_player/i2s_audio_media_player.cpp | 25 +- esphome/components/infrared/infrared.cpp | 5 +- esphome/components/ledc/ledc_output.cpp | 3 +- esphome/components/mcp4461/mcp4461.cpp | 5 +- esphome/components/midea/air_conditioner.cpp | 25 +- esphome/components/midea_ir/midea_ir.cpp | 23 +- esphome/components/mitsubishi/mitsubishi.cpp | 7 +- .../select/modbus_select.cpp | 2 +- esphome/components/noblex/noblex.cpp | 2 +- esphome/components/noblex/noblex.h | 3 +- .../components/output/lock/output_lock.cpp | 5 +- esphome/components/pid/pid_climate.cpp | 10 +- esphome/components/pzem004t/pzem004t.cpp | 5 +- esphome/components/select/select_call.cpp | 2 +- esphome/components/sgp4x/sgp4x.h | 18 +- .../media_player/speaker_media_player.cpp | 31 +-- esphome/components/speed/fan/speed_fan.cpp | 20 +- esphome/components/sprinkler/sprinkler.cpp | 21 +- esphome/components/tcl112/tcl112.cpp | 2 +- .../template_alarm_control_panel.cpp | 19 +- .../template/cover/template_cover.cpp | 10 +- .../template/datetime/template_date.cpp | 27 ++- .../template/datetime/template_datetime.cpp | 54 +++-- .../template/datetime/template_time.cpp | 27 ++- .../components/template/fan/template_fan.cpp | 20 +- .../template/lock/template_lock.cpp | 5 +- .../template/valve/template_valve.cpp | 5 +- .../water_heater/template_water_heater.cpp | 15 +- .../thermostat/thermostat_climate.cpp | 50 ++-- .../time_based/time_based_cover.cpp | 5 +- .../components/tormatic/tormatic_cover.cpp | 5 +- esphome/components/toshiba/toshiba.cpp | 8 +- .../components/tuya/climate/tuya_climate.cpp | 184 +++++++++------ esphome/components/tuya/cover/tuya_cover.cpp | 16 +- esphome/components/tuya/fan/tuya_fan.cpp | 88 ++++--- esphome/components/tuya/light/tuya_light.cpp | 5 +- .../climate/uponor_smatrix_climate.cpp | 5 +- esphome/components/whirlpool/whirlpool.cpp | 2 +- esphome/components/whynter/whynter.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 10 +- .../wifi/wifi_component_esp8266.cpp | 5 +- .../wifi/wifi_component_esp_idf.cpp | 5 +- esphome/components/yashima/yashima.cpp | 10 +- esphome/components/zhlt01/zhlt01.cpp | 6 +- esphome/core/entity_base.h | 2 +- esphome/core/optional.h | 218 +----------------- esphome/cpp_types.py | 4 +- tests/component_tests/text/test_text.py | 17 +- tests/components/template/common-base.yaml | 7 +- 92 files changed, 723 insertions(+), 701 deletions(-) diff --git a/esphome/components/am43/cover/am43_cover.cpp b/esphome/components/am43/cover/am43_cover.cpp index 0d49439095..2fa26d266a 100644 --- a/esphome/components/am43/cover/am43_cover.cpp +++ b/esphome/components/am43/cover/am43_cover.cpp @@ -63,8 +63,9 @@ void Am43Component::control(const CoverCall &call) { ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status); } } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto opt_pos = call.get_position(); + if (opt_pos.has_value()) { + auto pos = *opt_pos; if (this->invert_position_) pos = 1 - pos; diff --git a/esphome/components/anova/anova.cpp b/esphome/components/anova/anova.cpp index 2693224a97..b625f92115 100644 --- a/esphome/components/anova/anova.cpp +++ b/esphome/components/anova/anova.cpp @@ -24,8 +24,9 @@ void Anova::loop() { } void Anova::control(const ClimateCall &call) { - if (call.get_mode().has_value()) { - ClimateMode mode = *call.get_mode(); + auto mode_val = call.get_mode(); + if (mode_val.has_value()) { + ClimateMode mode = *mode_val; AnovaPacket *pkt; switch (mode) { case climate::CLIMATE_MODE_OFF: @@ -45,8 +46,9 @@ void Anova::control(const ClimateCall &call) { ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str(), status); } } - if (call.get_target_temperature().has_value()) { - auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature()); + auto target_temp = call.get_target_temperature(); + if (target_temp.has_value()) { + auto *pkt = this->codec_->get_set_target_temp_request(*target_temp); auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_, pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE); diff --git a/esphome/components/ballu/ballu.cpp b/esphome/components/ballu/ballu.cpp index b33ad11c1f..deb742f8c6 100644 --- a/esphome/components/ballu/ballu.cpp +++ b/esphome/components/ballu/ballu.cpp @@ -47,7 +47,7 @@ void BalluClimate::transmit_state() { remote_state[11] = 0x1e; // Fan speed - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: remote_state[4] |= BALLU_FAN_HIGH; break; diff --git a/esphome/components/bang_bang/bang_bang_climate.cpp b/esphome/components/bang_bang/bang_bang_climate.cpp index 6871e9df5d..1058bce6a4 100644 --- a/esphome/components/bang_bang/bang_bang_climate.cpp +++ b/esphome/components/bang_bang/bang_bang_climate.cpp @@ -45,17 +45,21 @@ void BangBangClimate::setup() { } void BangBangClimate::control(const climate::ClimateCall &call) { - if (call.get_mode().has_value()) { - this->mode = *call.get_mode(); + auto mode = call.get_mode(); + if (mode.has_value()) { + this->mode = *mode; } - if (call.get_target_temperature_low().has_value()) { - this->target_temperature_low = *call.get_target_temperature_low(); + auto target_temperature_low = call.get_target_temperature_low(); + if (target_temperature_low.has_value()) { + this->target_temperature_low = *target_temperature_low; } - if (call.get_target_temperature_high().has_value()) { - this->target_temperature_high = *call.get_target_temperature_high(); + auto target_temperature_high = call.get_target_temperature_high(); + if (target_temperature_high.has_value()) { + this->target_temperature_high = *target_temperature_high; } - if (call.get_preset().has_value()) { - this->change_away_(*call.get_preset() == climate::CLIMATE_PRESET_AWAY); + auto preset = call.get_preset(); + if (preset.has_value()) { + this->change_away_(*preset == climate::CLIMATE_PRESET_AWAY); } this->compute_state_(); diff --git a/esphome/components/bedjet/climate/bedjet_climate.cpp b/esphome/components/bedjet/climate/bedjet_climate.cpp index 68a0342873..a17407f08f 100644 --- a/esphome/components/bedjet/climate/bedjet_climate.cpp +++ b/esphome/components/bedjet/climate/bedjet_climate.cpp @@ -96,8 +96,9 @@ void BedJetClimate::control(const ClimateCall &call) { return; } - if (call.get_mode().has_value()) { - ClimateMode mode = *call.get_mode(); + auto mode_opt = call.get_mode(); + if (mode_opt.has_value()) { + ClimateMode mode = *mode_opt; bool button_result; switch (mode) { case CLIMATE_MODE_OFF: @@ -125,8 +126,9 @@ void BedJetClimate::control(const ClimateCall &call) { } } - if (call.get_target_temperature().has_value()) { - auto target_temp = *call.get_target_temperature(); + auto target_temp_opt = call.get_target_temperature(); + if (target_temp_opt.has_value()) { + auto target_temp = *target_temp_opt; auto result = this->parent_->set_target_temp(target_temp); if (result) { @@ -134,8 +136,9 @@ void BedJetClimate::control(const ClimateCall &call) { } } - if (call.get_preset().has_value()) { - ClimatePreset preset = *call.get_preset(); + auto preset_opt = call.get_preset(); + if (preset_opt.has_value()) { + ClimatePreset preset = *preset_opt; bool result; if (preset == CLIMATE_PRESET_BOOST) { @@ -187,10 +190,11 @@ void BedJetClimate::control(const ClimateCall &call) { } } - if (call.get_fan_mode().has_value()) { + auto fan_mode_opt = call.get_fan_mode(); + if (fan_mode_opt.has_value()) { // Climate fan mode only supports low/med/high, but the BedJet supports 5-100% increments. // We can still support a ClimateCall that requests low/med/high, and just translate it to a step increment here. - auto fan_mode = *call.get_fan_mode(); + auto fan_mode = *fan_mode_opt; bool result; if (fan_mode == CLIMATE_FAN_LOW) { result = this->parent_->set_fan_speed(20); diff --git a/esphome/components/bedjet/fan/bedjet_fan.cpp b/esphome/components/bedjet/fan/bedjet_fan.cpp index e272241040..9539e169a4 100644 --- a/esphome/components/bedjet/fan/bedjet_fan.cpp +++ b/esphome/components/bedjet/fan/bedjet_fan.cpp @@ -19,7 +19,8 @@ void BedJetFan::control(const fan::FanCall &call) { } bool did_change = false; - if (call.get_state().has_value() && this->state != *call.get_state()) { + auto state_opt = call.get_state(); + if (state_opt.has_value() && this->state != *state_opt) { // Turning off is easy: if (this->state && this->parent_->button_off()) { this->state = false; @@ -36,8 +37,9 @@ void BedJetFan::control(const fan::FanCall &call) { } // ignore speed changes if not on or turning on - if (this->state && call.get_speed().has_value()) { - auto speed = *call.get_speed(); + auto speed_opt = call.get_speed(); + if (this->state && speed_opt.has_value()) { + auto speed = *speed_opt; if (speed >= 1) { this->speed = speed; // Fan.speed is 1-20, but Bedjet expects 0-19, so subtract 1 diff --git a/esphome/components/binary/fan/binary_fan.cpp b/esphome/components/binary/fan/binary_fan.cpp index a2f75242de..17d4df095a 100644 --- a/esphome/components/binary/fan/binary_fan.cpp +++ b/esphome/components/binary/fan/binary_fan.cpp @@ -18,12 +18,15 @@ fan::FanTraits BinaryFan::get_traits() { return fan::FanTraits(this->oscillating_ != nullptr, false, this->direction_ != nullptr, 0); } void BinaryFan::control(const fan::FanCall &call) { - if (call.get_state().has_value()) - this->state = *call.get_state(); - if (call.get_oscillating().has_value()) - this->oscillating = *call.get_oscillating(); - if (call.get_direction().has_value()) - this->direction = *call.get_direction(); + auto state = call.get_state(); + if (state.has_value()) + this->state = *state; + auto oscillating = call.get_oscillating(); + if (oscillating.has_value()) + this->oscillating = *oscillating; + auto direction = call.get_direction(); + if (direction.has_value()) + this->direction = *direction; this->write_state_(); this->publish_state(); diff --git a/esphome/components/ble_presence/ble_presence_device.h b/esphome/components/ble_presence/ble_presence_device.h index f2f0a3ed19..8ae5edab3a 100644 --- a/esphome/components/ble_presence/ble_presence_device.h +++ b/esphome/components/ble_presence/ble_presence_device.h @@ -76,11 +76,12 @@ class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff, } break; case MATCH_BY_IBEACON_UUID: - if (!device.get_ibeacon().has_value()) { + auto maybe_ibeacon = device.get_ibeacon(); + if (!maybe_ibeacon.has_value()) { return false; } - auto ibeacon = device.get_ibeacon().value(); + auto ibeacon = *maybe_ibeacon; if (this->ibeacon_uuid_ != ibeacon.get_uuid()) { return false; diff --git a/esphome/components/ble_rssi/ble_rssi_sensor.h b/esphome/components/ble_rssi/ble_rssi_sensor.h index 80245a1fe1..81f21c94dd 100644 --- a/esphome/components/ble_rssi/ble_rssi_sensor.h +++ b/esphome/components/ble_rssi/ble_rssi_sensor.h @@ -74,11 +74,12 @@ class BLERSSISensor : public sensor::Sensor, public esp32_ble_tracker::ESPBTDevi } break; case MATCH_BY_IBEACON_UUID: - if (!device.get_ibeacon().has_value()) { + auto maybe_ibeacon = device.get_ibeacon(); + if (!maybe_ibeacon.has_value()) { return false; } - auto ibeacon = device.get_ibeacon().value(); + auto ibeacon = *maybe_ibeacon; if (this->ibeacon_uuid_ != ibeacon.get_uuid()) { return false; diff --git a/esphome/components/climate_ir/climate_ir.cpp b/esphome/components/climate_ir/climate_ir.cpp index 50c8d459b0..cc291ff17c 100644 --- a/esphome/components/climate_ir/climate_ir.cpp +++ b/esphome/components/climate_ir/climate_ir.cpp @@ -71,16 +71,21 @@ void ClimateIR::setup() { } void ClimateIR::control(const climate::ClimateCall &call) { - if (call.get_mode().has_value()) - this->mode = *call.get_mode(); - if (call.get_target_temperature().has_value()) - this->target_temperature = *call.get_target_temperature(); - if (call.get_fan_mode().has_value()) - this->fan_mode = *call.get_fan_mode(); - if (call.get_swing_mode().has_value()) - this->swing_mode = *call.get_swing_mode(); - if (call.get_preset().has_value()) - this->preset = *call.get_preset(); + auto mode = call.get_mode(); + if (mode.has_value()) + this->mode = *mode; + auto target_temperature = call.get_target_temperature(); + if (target_temperature.has_value()) + this->target_temperature = *target_temperature; + auto fan_mode = call.get_fan_mode(); + if (fan_mode.has_value()) + this->fan_mode = fan_mode; + auto swing_mode = call.get_swing_mode(); + if (swing_mode.has_value()) + this->swing_mode = *swing_mode; + auto preset = call.get_preset(); + if (preset.has_value()) + this->preset = preset; this->transmit_state(); this->publish_state(); } diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.cpp b/esphome/components/climate_ir_lg/climate_ir_lg.cpp index 7fe0646230..90e3d006a8 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.cpp +++ b/esphome/components/climate_ir_lg/climate_ir_lg.cpp @@ -79,7 +79,7 @@ void LgIrClimate::transmit_state() { if (this->mode == climate::CLIMATE_MODE_OFF) { remote_state |= FAN_AUTO; } else { - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: remote_state |= FAN_MAX; break; diff --git a/esphome/components/climate_ir_lg/climate_ir_lg.h b/esphome/components/climate_ir_lg/climate_ir_lg.h index 00fc99ae73..958245279f 100644 --- a/esphome/components/climate_ir_lg/climate_ir_lg.h +++ b/esphome/components/climate_ir_lg/climate_ir_lg.h @@ -23,7 +23,8 @@ class LgIrClimate : public climate_ir::ClimateIR { void control(const climate::ClimateCall &call) override { this->send_swing_cmd_ = call.get_swing_mode().has_value(); // swing resets after unit powered off - if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF) + auto mode = call.get_mode(); + if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF) this->swing_mode = climate::CLIMATE_SWING_OFF; climate_ir::ClimateIR::control(call); } diff --git a/esphome/components/coolix/coolix.cpp b/esphome/components/coolix/coolix.cpp index 5c6bfd7740..d8ea676478 100644 --- a/esphome/components/coolix/coolix.cpp +++ b/esphome/components/coolix/coolix.cpp @@ -83,7 +83,7 @@ void CoolixClimate::transmit_state() { this->fan_mode = climate::CLIMATE_FAN_AUTO; remote_state |= COOLIX_FAN_MODE_AUTO_DRY; } else { - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: remote_state |= COOLIX_FAN_MAX; break; diff --git a/esphome/components/coolix/coolix.h b/esphome/components/coolix/coolix.h index f4b4ff8e0e..51ddcdf8f2 100644 --- a/esphome/components/coolix/coolix.h +++ b/esphome/components/coolix/coolix.h @@ -23,7 +23,8 @@ class CoolixClimate : public climate_ir::ClimateIR { void control(const climate::ClimateCall &call) override { send_swing_cmd_ = call.get_swing_mode().has_value(); // swing resets after unit powered off - if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF) + auto mode = call.get_mode(); + if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF) this->swing_mode = climate::CLIMATE_SWING_OFF; climate_ir::ClimateIR::control(call); } diff --git a/esphome/components/copy/cover/copy_cover.cpp b/esphome/components/copy/cover/copy_cover.cpp index 28f8c9877c..c139869d8f 100644 --- a/esphome/components/copy/cover/copy_cover.cpp +++ b/esphome/components/copy/cover/copy_cover.cpp @@ -38,12 +38,15 @@ cover::CoverTraits CopyCover::get_traits() { void CopyCover::control(const cover::CoverCall &call) { auto call2 = source_->make_call(); call2.set_stop(call.get_stop()); - if (call.get_tilt().has_value()) - call2.set_tilt(*call.get_tilt()); - if (call.get_position().has_value()) - call2.set_position(*call.get_position()); - if (call.get_tilt().has_value()) - call2.set_tilt(*call.get_tilt()); + auto tilt = call.get_tilt(); + if (tilt.has_value()) + call2.set_tilt(*tilt); + auto position = call.get_position(); + if (position.has_value()) + call2.set_position(*position); + auto tilt2 = call.get_tilt(); + if (tilt2.has_value()) + call2.set_tilt(*tilt2); call2.perform(); } diff --git a/esphome/components/copy/fan/copy_fan.cpp b/esphome/components/copy/fan/copy_fan.cpp index b4a43cf2f1..14c600d71f 100644 --- a/esphome/components/copy/fan/copy_fan.cpp +++ b/esphome/components/copy/fan/copy_fan.cpp @@ -45,14 +45,18 @@ fan::FanTraits CopyFan::get_traits() { void CopyFan::control(const fan::FanCall &call) { auto call2 = source_->make_call(); - if (call.get_state().has_value()) - call2.set_state(*call.get_state()); - if (call.get_oscillating().has_value()) - call2.set_oscillating(*call.get_oscillating()); - if (call.get_speed().has_value()) - call2.set_speed(*call.get_speed()); - if (call.get_direction().has_value()) - call2.set_direction(*call.get_direction()); + auto state = call.get_state(); + if (state.has_value()) + call2.set_state(*state); + auto oscillating = call.get_oscillating(); + if (oscillating.has_value()) + call2.set_oscillating(*oscillating); + auto speed = call.get_speed(); + if (speed.has_value()) + call2.set_speed(*speed); + auto direction = call.get_direction(); + if (direction.has_value()) + call2.set_direction(*direction); if (call.has_preset_mode()) call2.set_preset_mode(call.get_preset_mode()); call2.perform(); diff --git a/esphome/components/copy/select/copy_select.cpp b/esphome/components/copy/select/copy_select.cpp index e85e08e353..227fe33182 100644 --- a/esphome/components/copy/select/copy_select.cpp +++ b/esphome/components/copy/select/copy_select.cpp @@ -11,8 +11,9 @@ void CopySelect::setup() { traits.set_options(source_->traits.get_options()); - if (source_->has_state()) - this->publish_state(source_->active_index().value()); + auto idx = this->source_->active_index(); + if (idx.has_value()) + this->publish_state(*idx); } void CopySelect::dump_config() { LOG_SELECT("", "Copy Select", this); } diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index 58ae7cbc34..13bf11b991 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -37,8 +37,9 @@ void CurrentBasedCover::control(const CoverCall &call) { } } } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto opt_pos = call.get_position(); + if (opt_pos.has_value()) { + auto pos = *opt_pos; if (fabsf(this->position - pos) < 0.01) { // already at target } else { diff --git a/esphome/components/daikin/daikin.cpp b/esphome/components/daikin/daikin.cpp index 359c63aeca..a285f3613d 100644 --- a/esphome/components/daikin/daikin.cpp +++ b/esphome/components/daikin/daikin.cpp @@ -94,7 +94,7 @@ uint8_t DaikinClimate::operation_mode_() const { uint16_t DaikinClimate::fan_speed_() const { uint16_t fan_speed; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_QUIET: fan_speed = DAIKIN_FAN_SILENT << 8; break; diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp index 4726310806..c45fa307a7 100644 --- a/esphome/components/daikin_arc/daikin_arc.cpp +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -176,7 +176,7 @@ uint8_t DaikinArcClimate::operation_mode_() { uint16_t DaikinArcClimate::fan_speed_() { uint16_t fan_speed; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: fan_speed = DAIKIN_FAN_1 << 8; break; @@ -485,8 +485,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { } void DaikinArcClimate::control(const climate::ClimateCall &call) { - if (call.get_target_humidity().has_value()) { - this->target_humidity = *call.get_target_humidity(); + auto target_humidity = call.get_target_humidity(); + if (target_humidity.has_value()) { + this->target_humidity = *target_humidity; } climate_ir::ClimateIR::control(call); } diff --git a/esphome/components/daikin_brc/daikin_brc.cpp b/esphome/components/daikin_brc/daikin_brc.cpp index 6683d70f80..1179cb07d7 100644 --- a/esphome/components/daikin_brc/daikin_brc.cpp +++ b/esphome/components/daikin_brc/daikin_brc.cpp @@ -111,7 +111,7 @@ uint8_t DaikinBrcClimate::operation_mode_() { uint8_t DaikinBrcClimate::fan_speed_swing_() { uint16_t fan_speed; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: fan_speed = DAIKIN_BRC_FAN_1; break; diff --git a/esphome/components/deep_sleep/deep_sleep_esp8266.cpp b/esphome/components/deep_sleep/deep_sleep_esp8266.cpp index 54d2aa993d..efbd45c34e 100644 --- a/esphome/components/deep_sleep/deep_sleep_esp8266.cpp +++ b/esphome/components/deep_sleep/deep_sleep_esp8266.cpp @@ -15,7 +15,7 @@ void DeepSleepComponent::dump_config_platform_() {} bool DeepSleepComponent::prepare_to_sleep_() { return true; } void DeepSleepComponent::deep_sleep_() { - ESP.deepSleep(*this->sleep_duration_); // NOLINT(readability-static-accessed-through-instance) + ESP.deepSleep(this->sleep_duration_.value_or(0)); // NOLINT(readability-static-accessed-through-instance) } } // namespace deep_sleep diff --git a/esphome/components/delonghi/delonghi.cpp b/esphome/components/delonghi/delonghi.cpp index 9bc0b5753d..19af703ab2 100644 --- a/esphome/components/delonghi/delonghi.cpp +++ b/esphome/components/delonghi/delonghi.cpp @@ -64,7 +64,7 @@ uint8_t DelonghiClimate::operation_mode_() { uint16_t DelonghiClimate::fan_speed_() { uint16_t fan_speed; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: fan_speed = DELONGHI_FAN_LOW; break; diff --git a/esphome/components/demo/demo_alarm_control_panel.h b/esphome/components/demo/demo_alarm_control_panel.h index f59434830b..76cb24c2f4 100644 --- a/esphome/components/demo/demo_alarm_control_panel.h +++ b/esphome/components/demo/demo_alarm_control_panel.h @@ -29,10 +29,11 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component { protected: void control(const AlarmControlPanelCall &call) override { auto state = call.get_state().value_or(ACP_STATE_DISARMED); + auto code = call.get_code(); switch (state) { case ACP_STATE_ARMED_AWAY: - if (this->get_requires_code_to_arm() && call.get_code().has_value()) { - if (call.get_code().value() != "1234") { + if (this->get_requires_code_to_arm() && code.has_value()) { + if (*code != "1234") { this->status_momentary_error("invalid_code", 5000); return; } @@ -40,8 +41,8 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component { this->publish_state(ACP_STATE_ARMED_AWAY); break; case ACP_STATE_DISARMED: - if (this->get_requires_code() && call.get_code().has_value()) { - if (call.get_code().value() != "1234") { + if (this->get_requires_code() && code.has_value()) { + if (*code != "1234") { this->status_momentary_error("invalid_code", 5000); return; } diff --git a/esphome/components/demo/demo_climate.h b/esphome/components/demo/demo_climate.h index e2dfb0142b..c5f07ac114 100644 --- a/esphome/components/demo/demo_climate.h +++ b/esphome/components/demo/demo_climate.h @@ -45,33 +45,31 @@ class DemoClimate : public climate::Climate, public Component { protected: void control(const climate::ClimateCall &call) override { - if (call.get_mode().has_value()) { - this->mode = *call.get_mode(); - } - if (call.get_target_temperature().has_value()) { - this->target_temperature = *call.get_target_temperature(); - } - if (call.get_target_temperature_low().has_value()) { - this->target_temperature_low = *call.get_target_temperature_low(); - } - if (call.get_target_temperature_high().has_value()) { - this->target_temperature_high = *call.get_target_temperature_high(); - } - if (call.get_fan_mode().has_value()) { - this->set_fan_mode_(*call.get_fan_mode()); - } - if (call.get_swing_mode().has_value()) { - this->swing_mode = *call.get_swing_mode(); - } - if (call.has_custom_fan_mode()) { + auto mode = call.get_mode(); + if (mode.has_value()) + this->mode = *mode; + auto target_temperature = call.get_target_temperature(); + if (target_temperature.has_value()) + this->target_temperature = *target_temperature; + auto target_temperature_low = call.get_target_temperature_low(); + if (target_temperature_low.has_value()) + this->target_temperature_low = *target_temperature_low; + auto target_temperature_high = call.get_target_temperature_high(); + if (target_temperature_high.has_value()) + this->target_temperature_high = *target_temperature_high; + auto fan_mode = call.get_fan_mode(); + if (fan_mode.has_value()) + this->set_fan_mode_(*fan_mode); + auto swing_mode = call.get_swing_mode(); + if (swing_mode.has_value()) + this->swing_mode = *swing_mode; + if (call.has_custom_fan_mode()) this->set_custom_fan_mode_(call.get_custom_fan_mode()); - } - if (call.get_preset().has_value()) { - this->set_preset_(*call.get_preset()); - } - if (call.has_custom_preset()) { + auto preset = call.get_preset(); + if (preset.has_value()) + this->set_preset_(*preset); + if (call.has_custom_preset()) this->set_custom_preset_(call.get_custom_preset()); - } this->publish_state(); } climate::ClimateTraits traits() override { diff --git a/esphome/components/demo/demo_cover.h b/esphome/components/demo/demo_cover.h index ec266d46ab..69dd5a4d2d 100644 --- a/esphome/components/demo/demo_cover.h +++ b/esphome/components/demo/demo_cover.h @@ -38,8 +38,9 @@ class DemoCover : public cover::Cover, public Component { protected: void control(const cover::CoverCall &call) override { - if (call.get_position().has_value()) { - float target = *call.get_position(); + auto pos = call.get_position(); + if (pos.has_value()) { + float target = *pos; this->current_operation = target > this->position ? cover::COVER_OPERATION_OPENING : cover::COVER_OPERATION_CLOSING; @@ -49,8 +50,9 @@ class DemoCover : public cover::Cover, public Component { this->publish_state(); }); } - if (call.get_tilt().has_value()) { - this->tilt = *call.get_tilt(); + auto tilt = call.get_tilt(); + if (tilt.has_value()) { + this->tilt = *tilt; } if (call.get_stop()) { this->cancel_timeout("move"); diff --git a/esphome/components/demo/demo_fan.h b/esphome/components/demo/demo_fan.h index 09edc4e0b7..a8b397f19a 100644 --- a/esphome/components/demo/demo_fan.h +++ b/esphome/components/demo/demo_fan.h @@ -47,14 +47,18 @@ class DemoFan : public fan::Fan, public Component { protected: void control(const fan::FanCall &call) override { - if (call.get_state().has_value()) - this->state = *call.get_state(); - if (call.get_oscillating().has_value()) - this->oscillating = *call.get_oscillating(); - if (call.get_speed().has_value()) - this->speed = *call.get_speed(); - if (call.get_direction().has_value()) - this->direction = *call.get_direction(); + auto state = call.get_state(); + if (state.has_value()) + this->state = *state; + auto oscillating = call.get_oscillating(); + if (oscillating.has_value()) + this->oscillating = *oscillating; + auto speed = call.get_speed(); + if (speed.has_value()) + this->speed = *speed; + auto direction = call.get_direction(); + if (direction.has_value()) + this->direction = *direction; this->publish_state(); } diff --git a/esphome/components/demo/demo_lock.h b/esphome/components/demo/demo_lock.h index 94d0f70a14..1e3fd51db4 100644 --- a/esphome/components/demo/demo_lock.h +++ b/esphome/components/demo/demo_lock.h @@ -8,8 +8,9 @@ namespace demo { class DemoLock : public lock::Lock { protected: void control(const lock::LockCall &call) override { - auto state = *call.get_state(); - this->publish_state(state); + auto state = call.get_state(); + if (state.has_value()) + this->publish_state(*state); } }; diff --git a/esphome/components/demo/demo_valve.h b/esphome/components/demo/demo_valve.h index 55d457f176..9a3122aca5 100644 --- a/esphome/components/demo/demo_valve.h +++ b/esphome/components/demo/demo_valve.h @@ -26,12 +26,15 @@ class DemoValve : public valve::Valve { protected: void control(const valve::ValveCall &call) override { - if (call.get_position().has_value()) { - this->position = *call.get_position(); + auto pos = call.get_position(); + if (pos.has_value()) { + this->position = *pos; this->publish_state(); return; - } else if (call.get_toggle().has_value()) { - if (call.get_toggle().value()) { + } + auto toggle = call.get_toggle(); + if (toggle.has_value()) { + if (*toggle) { if (this->position == valve::VALVE_OPEN) { this->position = valve::VALVE_CLOSED; this->publish_state(); diff --git a/esphome/components/emmeti/emmeti.cpp b/esphome/components/emmeti/emmeti.cpp index d3e923cbef..04976d95d7 100644 --- a/esphome/components/emmeti/emmeti.cpp +++ b/esphome/components/emmeti/emmeti.cpp @@ -28,7 +28,7 @@ uint8_t EmmetiClimate::set_mode_() { } uint8_t EmmetiClimate::set_fan_speed_() { - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: return EMMETI_FAN_1; case climate::CLIMATE_FAN_MEDIUM: diff --git a/esphome/components/endstop/endstop_cover.cpp b/esphome/components/endstop/endstop_cover.cpp index ea8a5ec186..5e0b9c72d3 100644 --- a/esphome/components/endstop/endstop_cover.cpp +++ b/esphome/components/endstop/endstop_cover.cpp @@ -37,8 +37,9 @@ void EndstopCover::control(const CoverCall &call) { } } } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto opt_pos = call.get_position(); + if (opt_pos.has_value()) { + auto pos = *opt_pos; if (pos == this->position) { // already at target } else { diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index fa0cdb6f45..7f1c2b0f7c 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -107,7 +107,7 @@ class ESPBTDevice { for (auto &it : this->manufacturer_datas_) { auto res = ESPBLEiBeacon::from_manufacturer_data(it); if (res.has_value()) - return *res; + return res; } return {}; } diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 8bb5cbb62e..66b41931aa 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -162,7 +162,8 @@ void ESP32RMTLEDStripLightOutput::set_led_params(uint32_t bit0_high, uint32_t bi void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) { // protect from refreshing too often uint32_t now = micros(); - if (*this->max_refresh_rate_ != 0 && (now - this->last_refresh_) < *this->max_refresh_rate_) { + auto rate = this->max_refresh_rate_.value_or(0); + if (rate != 0 && (now - this->last_refresh_) < rate) { // try again next loop iteration, so that this change won't get lost this->schedule_show(); return; @@ -301,7 +302,7 @@ void ESP32RMTLEDStripLightOutput::dump_config() { " RGB Order: %s\n" " Max refresh rate: %" PRIu32 "\n" " Number of LEDs: %u", - rgb_order, *this->max_refresh_rate_, this->num_leds_); + rgb_order, this->max_refresh_rate_.value_or(0), this->num_leds_); } float ESP32RMTLEDStripLightOutput::get_setup_priority() const { return setup_priority::HARDWARE; } diff --git a/esphome/components/fastled_base/fastled_light.cpp b/esphome/components/fastled_base/fastled_light.cpp index b3946a34b5..504b8d473e 100644 --- a/esphome/components/fastled_base/fastled_light.cpp +++ b/esphome/components/fastled_base/fastled_light.cpp @@ -21,12 +21,13 @@ void FastLEDLightOutput::dump_config() { "FastLED light:\n" " Num LEDs: %u\n" " Max refresh rate: %u", - this->num_leds_, *this->max_refresh_rate_); + this->num_leds_, this->max_refresh_rate_.value_or(0)); } void FastLEDLightOutput::write_state(light::LightState *state) { // protect from refreshing too often uint32_t now = micros(); - if (*this->max_refresh_rate_ != 0 && (now - this->last_refresh_) < *this->max_refresh_rate_) { + uint32_t max_rate = this->max_refresh_rate_.value_or(0); + if (max_rate != 0 && (now - this->last_refresh_) < max_rate) { // try again next loop iteration, so that this change won't get lost this->schedule_show(); return; diff --git a/esphome/components/feedback/feedback_cover.cpp b/esphome/components/feedback/feedback_cover.cpp index ffb19fa091..d247bada33 100644 --- a/esphome/components/feedback/feedback_cover.cpp +++ b/esphome/components/feedback/feedback_cover.cpp @@ -269,9 +269,12 @@ void FeedbackCover::control(const CoverCall &call) { this->start_direction_(COVER_OPERATION_CLOSING); } } - } else if (call.get_position().has_value()) { + } else { + auto pos_opt = call.get_position(); + if (!pos_opt.has_value()) + return; // go to position action - auto pos = *call.get_position(); + auto pos = *pos_opt; if (pos == this->position) { // already at target, diff --git a/esphome/components/fujitsu_general/fujitsu_general.cpp b/esphome/components/fujitsu_general/fujitsu_general.cpp index 6c7adebfea..8aa0f51728 100644 --- a/esphome/components/fujitsu_general/fujitsu_general.cpp +++ b/esphome/components/fujitsu_general/fujitsu_general.cpp @@ -141,7 +141,7 @@ void FujitsuGeneralClimate::transmit_state() { } // Set fan - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: SET_NIBBLE(remote_state, FUJITSU_GENERAL_FAN_NIBBLE, FUJITSU_GENERAL_FAN_HIGH); break; diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index b8cf8a39a8..8a9f264932 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -180,7 +180,7 @@ uint8_t GreeClimate::operation_mode_() { uint8_t GreeClimate::fan_speed_() { // YX1FF has 4 fan speeds -- we treat low as quiet and turbo as high if (this->model_ == GREE_YX1FF) { - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_QUIET: return GREE_FAN_1; case climate::CLIMATE_FAN_LOW: @@ -195,7 +195,7 @@ uint8_t GreeClimate::fan_speed_() { } } - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: return GREE_FAN_1; case climate::CLIMATE_FAN_MEDIUM: @@ -235,7 +235,7 @@ uint8_t GreeClimate::temperature_() { uint8_t GreeClimate::preset_() { // YX1FF has sleep preset if (this->model_ == GREE_YX1FF) { - switch (this->preset.value()) { + switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) { case climate::CLIMATE_PRESET_NONE: return GREE_PRESET_NONE; case climate::CLIMATE_PRESET_SLEEP: diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index d98d273957..be5035caa1 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -893,7 +893,8 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * } else { this->preset = CLIMATE_PRESET_NONE; } - should_publish = should_publish || (!old_preset.has_value()) || (old_preset.value() != this->preset.value()); + should_publish = should_publish || (!old_preset.has_value()) || + (old_preset.value_or(CLIMATE_PRESET_NONE) != this->preset.value_or(CLIMATE_PRESET_NONE)); } { // Target temperature @@ -936,7 +937,8 @@ haier_protocol::HandlerError HonClimate::process_status_message_(const uint8_t * this->fan_mode = CLIMATE_FAN_HIGH; break; } - should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value()); + should_publish = should_publish || (!old_fan_mode.has_value()) || + (old_fan_mode.value_or(CLIMATE_FAN_ON) != this->fan_mode.value_or(CLIMATE_FAN_ON)); } // Display status // should be before "Climate mode" because it is changing this->mode @@ -1301,7 +1303,8 @@ void HonClimate::clear_control_messages_queue_() { } bool HonClimate::prepare_pending_action() { - switch (this->action_request_.value().action) { + auto &action_request = this->action_request_.value(); // NOLINT(bugprone-unchecked-optional-access) + switch (action_request.action) { case ActionRequest::START_SELF_CLEAN: if (this->control_method_ == HonControlMethod::SET_GROUP_PARAMETERS) { uint8_t control_out_buffer[haier_protocol::MAX_FRAME_SIZE]; @@ -1315,12 +1318,12 @@ bool HonClimate::prepare_pending_action() { out_data->ac_power = 1; out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::DRY; out_data->light_status = 0; - this->action_request_.value().message = haier_protocol::HaierMessage( + action_request.message = haier_protocol::HaierMessage( haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, control_out_buffer, this->real_control_packet_size_); return true; } else if (this->control_method_ == HonControlMethod::SET_SINGLE_PARAMETER) { - this->action_request_.value().message = + action_request.message = haier_protocol::HaierMessage(haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_SINGLE_PARAMETER + (uint8_t) hon_protocol::DataParameters::SELF_CLEANING, @@ -1343,7 +1346,7 @@ bool HonClimate::prepare_pending_action() { out_data->ac_power = 1; out_data->ac_mode = (uint8_t) hon_protocol::ConditioningMode::DRY; out_data->light_status = 0; - this->action_request_.value().message = haier_protocol::HaierMessage( + action_request.message = haier_protocol::HaierMessage( haier_protocol::FrameType::CONTROL, (uint16_t) hon_protocol::SubcommandsControl::SET_GROUP_PARAMETERS, control_out_buffer, this->real_control_packet_size_); return true; diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index 63c22821b3..d24f8ad849 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -402,7 +402,8 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin } else { this->preset = CLIMATE_PRESET_NONE; } - should_publish = should_publish || (!old_preset.has_value()) || (old_preset.value() != this->preset.value()); + should_publish = should_publish || (!old_preset.has_value()) || + (old_preset.value_or(CLIMATE_PRESET_NONE) != this->preset.value_or(CLIMATE_PRESET_NONE)); } { // Target temperature @@ -446,7 +447,8 @@ haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uin this->fan_mode = CLIMATE_FAN_HIGH; break; } - should_publish = should_publish || (!old_fan_mode.has_value()) || (old_fan_mode.value() != fan_mode.value()); + should_publish = should_publish || (!old_fan_mode.has_value()) || + (old_fan_mode.value_or(CLIMATE_FAN_ON) != this->fan_mode.value_or(CLIMATE_FAN_ON)); } // Display status // should be before "Climate mode" because it is changing this->mode diff --git a/esphome/components/hbridge/fan/hbridge_fan.cpp b/esphome/components/hbridge/fan/hbridge_fan.cpp index 38e4129e66..89c162eebf 100644 --- a/esphome/components/hbridge/fan/hbridge_fan.cpp +++ b/esphome/components/hbridge/fan/hbridge_fan.cpp @@ -49,14 +49,18 @@ void HBridgeFan::dump_config() { } void HBridgeFan::control(const fan::FanCall &call) { - if (call.get_state().has_value()) - this->state = *call.get_state(); - if (call.get_speed().has_value()) - this->speed = *call.get_speed(); - if (call.get_oscillating().has_value()) - this->oscillating = *call.get_oscillating(); - if (call.get_direction().has_value()) - this->direction = *call.get_direction(); + auto call_state = call.get_state(); + if (call_state.has_value()) + this->state = *call_state; + auto call_speed = call.get_speed(); + if (call_speed.has_value()) + this->speed = *call_speed; + auto call_oscillating = call.get_oscillating(); + if (call_oscillating.has_value()) + this->oscillating = *call_oscillating; + auto call_direction = call.get_direction(); + if (call_direction.has_value()) + this->direction = *call_direction; this->apply_preset_mode_(call); this->write_state_(); diff --git a/esphome/components/he60r/he60r.cpp b/esphome/components/he60r/he60r.cpp index ca17930272..fdcd1a29c0 100644 --- a/esphome/components/he60r/he60r.cpp +++ b/esphome/components/he60r/he60r.cpp @@ -171,9 +171,12 @@ void HE60rCover::control(const CoverCall &call) { } else { this->toggles_needed_++; } - } else if (call.get_position().has_value()) { + } else { + auto pos_opt = call.get_position(); + if (!pos_opt.has_value()) + return; // go to position action - auto pos = *call.get_position(); + auto pos = *pos_opt; // are we at the target? if (pos == this->position) { this->start_direction_(COVER_OPERATION_IDLE); diff --git a/esphome/components/hitachi_ac344/hitachi_ac344.cpp b/esphome/components/hitachi_ac344/hitachi_ac344.cpp index 2bcb205644..69469cab2e 100644 --- a/esphome/components/hitachi_ac344/hitachi_ac344.cpp +++ b/esphome/components/hitachi_ac344/hitachi_ac344.cpp @@ -175,7 +175,7 @@ void HitachiClimate::transmit_state() { set_temp_(static_cast<uint8_t>(this->target_temperature)); - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: set_fan_(HITACHI_AC344_FAN_LOW); break; diff --git a/esphome/components/hitachi_ac424/hitachi_ac424.cpp b/esphome/components/hitachi_ac424/hitachi_ac424.cpp index 64f23dfc17..0b3cc99a82 100644 --- a/esphome/components/hitachi_ac424/hitachi_ac424.cpp +++ b/esphome/components/hitachi_ac424/hitachi_ac424.cpp @@ -176,7 +176,7 @@ void HitachiClimate::transmit_state() { set_temp_(static_cast<uint8_t>(this->target_temperature)); - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: set_fan_(HITACHI_AC424_FAN_LOW); break; 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 39301220d5..369c964a85 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 @@ -11,17 +11,18 @@ static const char *const TAG = "audio"; void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { media_player::MediaPlayerState play_state = media_player::MEDIA_PLAYER_STATE_PLAYING; - if (call.get_announcement().has_value()) { - play_state = call.get_announcement().value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING - : media_player::MEDIA_PLAYER_STATE_PLAYING; + auto announcement = call.get_announcement(); + if (announcement.has_value()) { + play_state = *announcement ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING : media_player::MEDIA_PLAYER_STATE_PLAYING; } - if (call.get_media_url().has_value()) { - this->current_url_ = call.get_media_url(); + auto media_url = call.get_media_url(); + if (media_url.has_value()) { + this->current_url_ = media_url; if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) { if (this->audio_->isRunning()) { this->audio_->stopSong(); } - this->audio_->connecttohost(this->current_url_.value().c_str()); + this->audio_->connecttohost(media_url->c_str()); this->state = play_state; } else { this->start(); @@ -32,13 +33,15 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { this->is_announcement_ = true; } - if (call.get_volume().has_value()) { - this->volume = call.get_volume().value(); + auto vol = call.get_volume(); + if (vol.has_value()) { + this->volume = *vol; this->set_volume_(volume); this->unmute_(); } - if (call.get_command().has_value()) { - switch (call.get_command().value()) { + auto cmd = call.get_command(); + if (cmd.has_value()) { + switch (*cmd) { case media_player::MEDIA_PLAYER_COMMAND_MUTE: this->mute_(); break; @@ -67,7 +70,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { if (this->i2s_state_ != I2S_STATE_RUNNING) { return; } - switch (call.get_command().value()) { + switch (*cmd) { case media_player::MEDIA_PLAYER_COMMAND_PLAY: if (!this->audio_->isRunning()) this->audio_->pauseResume(); diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 4431869951..658c9fd0df 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -90,8 +90,9 @@ void Infrared::control(const InfraredCall &call) { auto *transmit_data = transmit_call.get_data(); // Set carrier frequency - if (call.get_carrier_frequency().has_value()) { - transmit_data->set_carrier_frequency(call.get_carrier_frequency().value()); + auto freq = call.get_carrier_frequency(); + if (freq.has_value()) { + transmit_data->set_carrier_frequency(*freq); } // Set timings based on format diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index a01d42ac8b..21e0682257 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -56,7 +56,8 @@ optional<uint8_t> ledc_bit_depth_for_frequency(float frequency) { esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num, uint8_t channel, uint8_t &bit_depth, float frequency) { - bit_depth = *ledc_bit_depth_for_frequency(frequency); + auto bit_depth_opt = ledc_bit_depth_for_frequency(frequency); + bit_depth = bit_depth_opt.value_or(0); if (bit_depth < 1) { ESP_LOGE(TAG, "Frequency %f can't be achieved with any bit depth", frequency); } diff --git a/esphome/components/mcp4461/mcp4461.cpp b/esphome/components/mcp4461/mcp4461.cpp index 2f2c75e05a..dc7e7019aa 100644 --- a/esphome/components/mcp4461/mcp4461.cpp +++ b/esphome/components/mcp4461/mcp4461.cpp @@ -19,8 +19,9 @@ void Mcp4461Component::setup() { // save WP/WL status this->update_write_protection_status_(); for (uint8_t i = 0; i < 8; i++) { - if (this->reg_[i].initial_value.has_value()) { - uint16_t initial_state = static_cast<uint16_t>(*this->reg_[i].initial_value * 256.0f); + auto init_val = this->reg_[i].initial_value; + if (init_val.has_value()) { + uint16_t initial_state = static_cast<uint16_t>(*init_val * 256.0f); this->write_wiper_level_(i, initial_state); } if (this->reg_[i].enabled) { diff --git a/esphome/components/midea/air_conditioner.cpp b/esphome/components/midea/air_conditioner.cpp index bc750e3713..4d59a4fbbc 100644 --- a/esphome/components/midea/air_conditioner.cpp +++ b/esphome/components/midea/air_conditioner.cpp @@ -56,20 +56,25 @@ void AirConditioner::on_status_change() { void AirConditioner::control(const ClimateCall &call) { dudanov::midea::ac::Control ctrl{}; - if (call.get_target_temperature().has_value()) - ctrl.targetTemp = call.get_target_temperature().value(); - if (call.get_swing_mode().has_value()) - ctrl.swingMode = Converters::to_midea_swing_mode(call.get_swing_mode().value()); - if (call.get_mode().has_value()) - ctrl.mode = Converters::to_midea_mode(call.get_mode().value()); - if (call.get_preset().has_value()) { - ctrl.preset = Converters::to_midea_preset(call.get_preset().value()); + auto target_temp_val = call.get_target_temperature(); + if (target_temp_val.has_value()) + ctrl.targetTemp = *target_temp_val; + auto swing_mode_val = call.get_swing_mode(); + if (swing_mode_val.has_value()) + ctrl.swingMode = Converters::to_midea_swing_mode(*swing_mode_val); + auto mode_val = call.get_mode(); + if (mode_val.has_value()) + ctrl.mode = Converters::to_midea_mode(*mode_val); + auto preset_val = call.get_preset(); + if (preset_val.has_value()) { + ctrl.preset = Converters::to_midea_preset(*preset_val); } else if (call.has_custom_preset()) { // get_custom_preset() returns StringRef pointing to null-terminated string literals from codegen ctrl.preset = Converters::to_midea_preset(call.get_custom_preset().c_str()); } - if (call.get_fan_mode().has_value()) { - ctrl.fanMode = Converters::to_midea_fan_mode(call.get_fan_mode().value()); + auto fan_mode_val = call.get_fan_mode(); + if (fan_mode_val.has_value()) { + ctrl.fanMode = Converters::to_midea_fan_mode(*fan_mode_val); } else if (call.has_custom_fan_mode()) { // get_custom_fan_mode() returns StringRef pointing to null-terminated string literals from codegen ctrl.fanMode = Converters::to_midea_fan_mode(call.get_custom_fan_mode().c_str()); diff --git a/esphome/components/midea_ir/midea_ir.cpp b/esphome/components/midea_ir/midea_ir.cpp index eaee1c731c..220bb3f414 100644 --- a/esphome/components/midea_ir/midea_ir.cpp +++ b/esphome/components/midea_ir/midea_ir.cpp @@ -114,15 +114,20 @@ void MideaIR::control(const climate::ClimateCall &call) { if (call.get_mode() == climate::CLIMATE_MODE_OFF) { this->swing_mode = climate::CLIMATE_SWING_OFF; this->preset = climate::CLIMATE_PRESET_NONE; - } else if (call.get_swing_mode().has_value() && ((*call.get_swing_mode() == climate::CLIMATE_SWING_OFF && - this->swing_mode == climate::CLIMATE_SWING_VERTICAL) || - (*call.get_swing_mode() == climate::CLIMATE_SWING_VERTICAL && - this->swing_mode == climate::CLIMATE_SWING_OFF))) { - this->swing_ = true; - } else if (call.get_preset().has_value() && - ((*call.get_preset() == climate::CLIMATE_PRESET_NONE && this->preset == climate::CLIMATE_PRESET_BOOST) || - (*call.get_preset() == climate::CLIMATE_PRESET_BOOST && this->preset == climate::CLIMATE_PRESET_NONE))) { - this->boost_ = true; + } else { + auto swing = call.get_swing_mode(); + if (swing.has_value() && + ((*swing == climate::CLIMATE_SWING_OFF && this->swing_mode == climate::CLIMATE_SWING_VERTICAL) || + (*swing == climate::CLIMATE_SWING_VERTICAL && this->swing_mode == climate::CLIMATE_SWING_OFF))) { + this->swing_ = true; + } else { + auto preset = call.get_preset(); + if (preset.has_value() && + ((*preset == climate::CLIMATE_PRESET_NONE && this->preset == climate::CLIMATE_PRESET_BOOST) || + (*preset == climate::CLIMATE_PRESET_BOOST && this->preset == climate::CLIMATE_PRESET_NONE))) { + this->boost_ = true; + } + } } climate_ir::ClimateIR::control(call); } diff --git a/esphome/components/mitsubishi/mitsubishi.cpp b/esphome/components/mitsubishi/mitsubishi.cpp index d80b7aeff5..882163ff5d 100644 --- a/esphome/components/mitsubishi/mitsubishi.cpp +++ b/esphome/components/mitsubishi/mitsubishi.cpp @@ -180,7 +180,7 @@ void MitsubishiClimate::transmit_state() { // For 5Level: Low = 1, Middle = 2, Medium = 3, High = 4 // For 4Level + Quiet: Low = 1, Middle = 2, Medium = 3, High = 4, Quiet = 5 - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: remote_state[9] = 1; break; @@ -209,7 +209,8 @@ void MitsubishiClimate::transmit_state() { break; } - ESP_LOGD(TAG, "fan: %02x state: %02x", this->fan_mode.value(), remote_state[9]); + ESP_LOGD(TAG, "fan: %02x state: %02x", static_cast<uint8_t>(this->fan_mode.value_or(climate::CLIMATE_FAN_ON)), + remote_state[9]); // Vertical Vane switch (this->swing_mode) { @@ -227,7 +228,7 @@ void MitsubishiClimate::transmit_state() { ESP_LOGD(TAG, "default_vertical_direction_: %02X", this->default_vertical_direction_); // Special modes - switch (this->preset.value()) { + switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) { case climate::CLIMATE_PRESET_ECO: remote_state[6] = MITSUBISHI_MODE_COOL | MITSUBISHI_OTHERWISE; remote_state[8] = (remote_state[8] & ~7) | MITSUBISHI_MODE_A_COOL; diff --git a/esphome/components/modbus_controller/select/modbus_select.cpp b/esphome/components/modbus_controller/select/modbus_select.cpp index 853f4215c3..e2a54d3f60 100644 --- a/esphome/components/modbus_controller/select/modbus_select.cpp +++ b/esphome/components/modbus_controller/select/modbus_select.cpp @@ -52,7 +52,7 @@ void ModbusSelect::control(size_t index) { // Transform func requires string parameter for backward compatibility auto val = (*this->write_transform_func_)(this, std::string(option), *mapval, data); if (val.has_value()) { - mapval = *val; + mapval = val; ESP_LOGV(TAG, "write_lambda returned mapping value %lld", *mapval); } else { ESP_LOGD(TAG, "Communication handled by write_lambda - exiting control"); diff --git a/esphome/components/noblex/noblex.cpp b/esphome/components/noblex/noblex.cpp index 53f807809e..f1e76eabf2 100644 --- a/esphome/components/noblex/noblex.cpp +++ b/esphome/components/noblex/noblex.cpp @@ -71,7 +71,7 @@ void NoblexClimate::transmit_state() { break; } - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: remote_state[0] |= (IRNoblexFan::IR_NOBLEX_FAN_LOW << 2); break; diff --git a/esphome/components/noblex/noblex.h b/esphome/components/noblex/noblex.h index a8e5f41547..57990db005 100644 --- a/esphome/components/noblex/noblex.h +++ b/esphome/components/noblex/noblex.h @@ -26,7 +26,8 @@ class NoblexClimate : public climate_ir::ClimateIR { void control(const climate::ClimateCall &call) override { send_swing_cmd_ = call.get_swing_mode().has_value(); // swing resets after unit powered off - if (call.get_mode().has_value() && *call.get_mode() == climate::CLIMATE_MODE_OFF) + auto mode = call.get_mode(); + if (mode.has_value() && *mode == climate::CLIMATE_MODE_OFF) this->swing_mode = climate::CLIMATE_SWING_OFF; climate_ir::ClimateIR::control(call); } diff --git a/esphome/components/output/lock/output_lock.cpp b/esphome/components/output/lock/output_lock.cpp index 2545f62481..c373cd7b7c 100644 --- a/esphome/components/output/lock/output_lock.cpp +++ b/esphome/components/output/lock/output_lock.cpp @@ -9,7 +9,10 @@ static const char *const TAG = "output.lock"; void OutputLock::dump_config() { LOG_LOCK("", "Output Lock", this); } void OutputLock::control(const lock::LockCall &call) { - auto state = *call.get_state(); + auto state_val = call.get_state(); + if (!state_val.has_value()) + return; + auto state = *state_val; if (state == lock::LOCK_STATE_LOCKED) { this->output_->turn_on(); } else if (state == lock::LOCK_STATE_UNLOCKED) { diff --git a/esphome/components/pid/pid_climate.cpp b/esphome/components/pid/pid_climate.cpp index 2094c0e942..54b7a688b4 100644 --- a/esphome/components/pid/pid_climate.cpp +++ b/esphome/components/pid/pid_climate.cpp @@ -41,10 +41,12 @@ void PIDClimate::setup() { } } void PIDClimate::control(const climate::ClimateCall &call) { - if (call.get_mode().has_value()) - this->mode = *call.get_mode(); - if (call.get_target_temperature().has_value()) - this->target_temperature = *call.get_target_temperature(); + auto call_mode = call.get_mode(); + if (call_mode.has_value()) + this->mode = *call_mode; + auto call_target = call.get_target_temperature(); + if (call_target.has_value()) + this->target_temperature = *call_target; // If switching to off mode, set output immediately if (this->mode == climate::CLIMATE_MODE_OFF) diff --git a/esphome/components/pzem004t/pzem004t.cpp b/esphome/components/pzem004t/pzem004t.cpp index 356847825e..d0f96d6d1e 100644 --- a/esphome/components/pzem004t/pzem004t.cpp +++ b/esphome/components/pzem004t/pzem004t.cpp @@ -26,7 +26,10 @@ void PZEM004T::loop() { // PZEM004T packet size is 7 byte while (this->available() >= 7) { - auto resp = *this->read_array<7>(); + auto resp_opt = this->read_array<7>(); + if (!resp_opt.has_value()) + break; + auto resp = *resp_opt; // packet format: // 0: packet type // 1-5: data diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 2ff99c961d..45fb42c116 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -69,7 +69,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { ESP_LOGW(TAG, "'%s' - No option set", name); return {}; } - return this->index_.value(); + return this->index_; } // SELECT_OP_NEXT or SELECT_OP_PREVIOUS diff --git a/esphome/components/sgp4x/sgp4x.h b/esphome/components/sgp4x/sgp4x.h index 8b31bca28c..89fa627c61 100644 --- a/esphome/components/sgp4x/sgp4x.h +++ b/esphome/components/sgp4x/sgp4x.h @@ -81,22 +81,16 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se void set_voc_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours, uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes, uint16_t std_initial, uint16_t gain_factor) { - voc_tuning_params_.value().index_offset = index_offset; - voc_tuning_params_.value().learning_time_offset_hours = learning_time_offset_hours; - voc_tuning_params_.value().learning_time_gain_hours = learning_time_gain_hours; - voc_tuning_params_.value().gating_max_duration_minutes = gating_max_duration_minutes; - voc_tuning_params_.value().std_initial = std_initial; - voc_tuning_params_.value().gain_factor = gain_factor; + this->voc_tuning_params_ = GasTuning{ + index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, std_initial, + gain_factor}; } void set_nox_algorithm_tuning(uint16_t index_offset, uint16_t learning_time_offset_hours, uint16_t learning_time_gain_hours, uint16_t gating_max_duration_minutes, uint16_t gain_factor) { - nox_tuning_params_.value().index_offset = index_offset; - nox_tuning_params_.value().learning_time_offset_hours = learning_time_offset_hours; - nox_tuning_params_.value().learning_time_gain_hours = learning_time_gain_hours; - nox_tuning_params_.value().gating_max_duration_minutes = gating_max_duration_minutes; - nox_tuning_params_.value().std_initial = 50; - nox_tuning_params_.value().gain_factor = gain_factor; + this->nox_tuning_params_ = + GasTuning{index_offset, learning_time_offset_hours, learning_time_gain_hours, gating_max_duration_minutes, 50, + gain_factor}; } protected: diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 3f5cb2fda6..9f168f854d 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -144,7 +144,7 @@ void SpeakerMediaPlayer::watch_media_commands_() { delete media_command.url.value(); } if (media_command.file.has_value()) { - playlist_item.file = media_command.file.value(); + playlist_item.file = media_command.file; } if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) { @@ -495,18 +495,21 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) { MediaCallCommand media_command; - if (this->single_pipeline_() || (call.get_announcement().has_value() && call.get_announcement().value())) { + auto ann = call.get_announcement(); + if (this->single_pipeline_() || (ann.has_value() && *ann)) { media_command.announce = true; } else { media_command.announce = false; } - if (call.get_media_url().has_value()) { - media_command.url = new std::string( - call.get_media_url().value()); // Must be manually deleted after receiving media_command from a queue + auto media_url = call.get_media_url(); + if (media_url.has_value()) { + media_command.url = + new std::string(*media_url); // Must be manually deleted after receiving media_command from a queue - if (call.get_command().has_value()) { - if (call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) { + auto cmd = call.get_command(); + if (cmd.has_value()) { + if (*cmd == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) { media_command.enqueue = true; } } @@ -515,18 +518,20 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) { return; } - if (call.get_volume().has_value()) { - media_command.volume = call.get_volume().value(); + auto vol = call.get_volume(); + if (vol.has_value()) { + media_command.volume = vol; // Wait 0 ticks for queue to be free, volume sets aren't that important! xQueueSend(this->media_control_command_queue_, &media_command, 0); return; } - if (call.get_command().has_value()) { - media_command.command = call.get_command().value(); + auto cmd = call.get_command(); + if (cmd.has_value()) { + media_command.command = cmd; TickType_t ticks_to_wait = portMAX_DELAY; - if ((call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP) || - (call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN)) { + if ((*cmd == media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP) || + (*cmd == media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN)) { ticks_to_wait = 0; // Wait 0 ticks for queue to be free, volume sets aren't that important! } xQueueSend(this->media_control_command_queue_, &media_command, ticks_to_wait); diff --git a/esphome/components/speed/fan/speed_fan.cpp b/esphome/components/speed/fan/speed_fan.cpp index 55f7fd162c..d45237c467 100644 --- a/esphome/components/speed/fan/speed_fan.cpp +++ b/esphome/components/speed/fan/speed_fan.cpp @@ -21,14 +21,18 @@ void SpeedFan::setup() { void SpeedFan::dump_config() { LOG_FAN("", "Speed Fan", this); } void SpeedFan::control(const fan::FanCall &call) { - if (call.get_state().has_value()) - this->state = *call.get_state(); - if (call.get_speed().has_value()) - this->speed = *call.get_speed(); - if (call.get_oscillating().has_value()) - this->oscillating = *call.get_oscillating(); - if (call.get_direction().has_value()) - this->direction = *call.get_direction(); + auto call_state = call.get_state(); + if (call_state.has_value()) + this->state = *call_state; + auto call_speed = call.get_speed(); + if (call_speed.has_value()) + this->speed = *call_speed; + auto call_oscillating = call.get_oscillating(); + if (call_oscillating.has_value()) + this->oscillating = *call_oscillating; + auto call_direction = call.get_direction(); + if (call_direction.has_value()) + this->direction = *call_direction; this->apply_preset_mode_(call); this->write_state_(); diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index 44fb9092bc..d1f7452054 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -44,7 +44,7 @@ SprinklerControllerSwitch::SprinklerControllerSwitch() = default; void SprinklerControllerSwitch::loop() { // Loop is only enabled when f_ has a value (see setup()) - auto s = (*this->f_)(); + auto s = (*this->f_)(); // NOLINT(bugprone-unchecked-optional-access) if (s.has_value()) { this->publish_state(*s); } @@ -89,20 +89,21 @@ void SprinklerValveOperator::loop() { uint32_t now = App.get_loop_component_start_time(); switch (this->state_) { case STARTING: - if ((now - *this->start_millis_) > this->start_delay_) { + if ((now - *this->start_millis_) > this->start_delay_) { // NOLINT(bugprone-unchecked-optional-access) this->run_(); // start_delay_ has been exceeded, so ensure both valves are on and update the state } break; case ACTIVE: - if ((now - *this->start_millis_) > (this->start_delay_ + this->run_duration_)) { + if ((now - *this->start_millis_) > // NOLINT(bugprone-unchecked-optional-access) + (this->start_delay_ + this->run_duration_)) { this->stop(); // start_delay_ + run_duration_ has been exceeded, start shutting down } break; case STOPPING: - if ((now - *this->stop_millis_) > this->stop_delay_) { - this->kill_(); // stop_delay_has been exceeded, ensure all valves are off + if ((now - *this->stop_millis_) > this->stop_delay_) { // NOLINT(bugprone-unchecked-optional-access) + this->kill_(); // stop_delay_has been exceeded, ensure all valves are off } break; @@ -1067,7 +1068,8 @@ uint32_t Sprinkler::total_cycle_time_enabled_incomplete_valves() { if (this->valve_is_enabled_(valve)) { enabled_valve_count++; if (!this->valve_cycle_complete_(valve)) { - if (!this->active_valve().has_value() || (valve != this->active_valve().value())) { + auto active = this->active_valve(); + if (!active.has_value() || (valve != *active)) { total_time_remaining += this->valve_run_duration_adjusted(valve); incomplete_valve_count++; } else { @@ -1190,8 +1192,11 @@ switch_::Switch *Sprinkler::valve_switch(const size_t valve_number) { } switch_::Switch *Sprinkler::valve_pump_switch(const size_t valve_number) { - if (this->is_a_valid_valve(valve_number) && this->valve_[valve_number].pump_switch_index.has_value()) { - return this->pump_[this->valve_[valve_number].pump_switch_index.value()]; + if (this->is_a_valid_valve(valve_number)) { + auto idx = this->valve_[valve_number].pump_switch_index; + if (idx.has_value()) { + return this->pump_[*idx]; + } } return nullptr; } diff --git a/esphome/components/tcl112/tcl112.cpp b/esphome/components/tcl112/tcl112.cpp index a88e8e96a7..afeee3d739 100644 --- a/esphome/components/tcl112/tcl112.cpp +++ b/esphome/components/tcl112/tcl112.cpp @@ -89,7 +89,7 @@ void Tcl112Climate::transmit_state() { // Set fan uint8_t selected_fan; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: selected_fan = TCL112_FAN_HIGH; break; diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp index 09efe678ce..651aa3c489 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp @@ -257,14 +257,16 @@ void TemplateAlarmControlPanel::bypass_before_arming() { } void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) { - if (call.get_state()) { - if (call.get_state() == ACP_STATE_ARMED_AWAY) { + auto opt_state = call.get_state(); + if (opt_state) { + auto state = *opt_state; + if (state == ACP_STATE_ARMED_AWAY) { this->arm_(call.get_code(), ACP_STATE_ARMED_AWAY, this->arming_away_time_); - } else if (call.get_state() == ACP_STATE_ARMED_HOME) { + } else if (state == ACP_STATE_ARMED_HOME) { this->arm_(call.get_code(), ACP_STATE_ARMED_HOME, this->arming_home_time_); - } else if (call.get_state() == ACP_STATE_ARMED_NIGHT) { + } else if (state == ACP_STATE_ARMED_NIGHT) { this->arm_(call.get_code(), ACP_STATE_ARMED_NIGHT, this->arming_night_time_); - } else if (call.get_state() == ACP_STATE_DISARMED) { + } else if (state == ACP_STATE_DISARMED) { if (!this->is_code_valid_(call.get_code())) { ESP_LOGW(TAG, "Not disarming code doesn't match"); return; @@ -274,13 +276,12 @@ void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) { #ifdef USE_BINARY_SENSOR this->bypassed_sensor_indicies_.clear(); #endif - } else if (call.get_state() == ACP_STATE_TRIGGERED) { + } else if (state == ACP_STATE_TRIGGERED) { this->publish_state(ACP_STATE_TRIGGERED); - } else if (call.get_state() == ACP_STATE_PENDING) { + } else if (state == ACP_STATE_PENDING) { this->publish_state(ACP_STATE_PENDING); } else { - ESP_LOGE(TAG, "State not yet implemented: %s", - LOG_STR_ARG(alarm_control_panel_state_to_string(*call.get_state()))); + ESP_LOGE(TAG, "State not yet implemented: %s", LOG_STR_ARG(alarm_control_panel_state_to_string(state))); } } } diff --git a/esphome/components/template/cover/template_cover.cpp b/esphome/components/template/cover/template_cover.cpp index 7f5d68623f..d5e0967e1e 100644 --- a/esphome/components/template/cover/template_cover.cpp +++ b/esphome/components/template/cover/template_cover.cpp @@ -74,8 +74,9 @@ void TemplateCover::control(const CoverCall &call) { this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto pos_val = call.get_position(); + if (pos_val.has_value()) { + auto pos = *pos_val; this->stop_prev_trigger_(); if (pos == COVER_OPEN) { @@ -93,8 +94,9 @@ void TemplateCover::control(const CoverCall &call) { } } - if (call.get_tilt().has_value()) { - auto tilt = *call.get_tilt(); + auto tilt_val = call.get_tilt(); + if (tilt_val.has_value()) { + auto tilt = *tilt_val; this->tilt_trigger_.trigger(tilt); if (this->optimistic_) { diff --git a/esphome/components/template/datetime/template_date.cpp b/esphome/components/template/datetime/template_date.cpp index 8a5f11b876..c0f5d96c3d 100644 --- a/esphome/components/template/datetime/template_date.cpp +++ b/esphome/components/template/datetime/template_date.cpp @@ -48,46 +48,49 @@ void TemplateDate::update() { } void TemplateDate::control(const datetime::DateCall &call) { - bool has_year = call.get_year().has_value(); - bool has_month = call.get_month().has_value(); - bool has_day = call.get_day().has_value(); + auto opt_year = call.get_year(); + auto opt_month = call.get_month(); + auto opt_day = call.get_day(); + bool has_year = opt_year.has_value(); + bool has_month = opt_month.has_value(); + bool has_day = opt_day.has_value(); ESPTime value = {}; if (has_year) - value.year = *call.get_year(); + value.year = *opt_year; if (has_month) - value.month = *call.get_month(); + value.month = *opt_month; if (has_day) - value.day_of_month = *call.get_day(); + value.day_of_month = *opt_day; this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_year) - this->year_ = *call.get_year(); + this->year_ = *opt_year; if (has_month) - this->month_ = *call.get_month(); + this->month_ = *opt_month; if (has_day) - this->day_ = *call.get_day(); + this->day_ = *opt_day; this->publish_state(); } if (this->restore_value_) { datetime::DateEntityRestoreState temp = {}; if (has_year) { - temp.year = *call.get_year(); + temp.year = *opt_year; } else { temp.year = this->year_; } if (has_month) { - temp.month = *call.get_month(); + temp.month = *opt_month; } else { temp.month = this->month_; } if (has_day) { - temp.day = *call.get_day(); + temp.day = *opt_day; } else { temp.day = this->day_; } diff --git a/esphome/components/template/datetime/template_datetime.cpp b/esphome/components/template/datetime/template_datetime.cpp index 269a1d06ca..5b8b308c00 100644 --- a/esphome/components/template/datetime/template_datetime.cpp +++ b/esphome/components/template/datetime/template_datetime.cpp @@ -54,79 +54,85 @@ void TemplateDateTime::update() { } void TemplateDateTime::control(const datetime::DateTimeCall &call) { - bool has_year = call.get_year().has_value(); - bool has_month = call.get_month().has_value(); - bool has_day = call.get_day().has_value(); - bool has_hour = call.get_hour().has_value(); - bool has_minute = call.get_minute().has_value(); - bool has_second = call.get_second().has_value(); + auto opt_year = call.get_year(); + auto opt_month = call.get_month(); + auto opt_day = call.get_day(); + auto opt_hour = call.get_hour(); + auto opt_minute = call.get_minute(); + auto opt_second = call.get_second(); + bool has_year = opt_year.has_value(); + bool has_month = opt_month.has_value(); + bool has_day = opt_day.has_value(); + bool has_hour = opt_hour.has_value(); + bool has_minute = opt_minute.has_value(); + bool has_second = opt_second.has_value(); ESPTime value = {}; if (has_year) - value.year = *call.get_year(); + value.year = *opt_year; if (has_month) - value.month = *call.get_month(); + value.month = *opt_month; if (has_day) - value.day_of_month = *call.get_day(); + value.day_of_month = *opt_day; if (has_hour) - value.hour = *call.get_hour(); + value.hour = *opt_hour; if (has_minute) - value.minute = *call.get_minute(); + value.minute = *opt_minute; if (has_second) - value.second = *call.get_second(); + value.second = *opt_second; this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_year) - this->year_ = *call.get_year(); + this->year_ = *opt_year; if (has_month) - this->month_ = *call.get_month(); + this->month_ = *opt_month; if (has_day) - this->day_ = *call.get_day(); + this->day_ = *opt_day; if (has_hour) - this->hour_ = *call.get_hour(); + this->hour_ = *opt_hour; if (has_minute) - this->minute_ = *call.get_minute(); + this->minute_ = *opt_minute; if (has_second) - this->second_ = *call.get_second(); + this->second_ = *opt_second; this->publish_state(); } if (this->restore_value_) { datetime::DateTimeEntityRestoreState temp = {}; if (has_year) { - temp.year = *call.get_year(); + temp.year = *opt_year; } else { temp.year = this->year_; } if (has_month) { - temp.month = *call.get_month(); + temp.month = *opt_month; } else { temp.month = this->month_; } if (has_day) { - temp.day = *call.get_day(); + temp.day = *opt_day; } else { temp.day = this->day_; } if (has_hour) { - temp.hour = *call.get_hour(); + temp.hour = *opt_hour; } else { temp.hour = this->hour_; } if (has_minute) { - temp.minute = *call.get_minute(); + temp.minute = *opt_minute; } else { temp.minute = this->minute_; } if (has_second) { - temp.second = *call.get_second(); + temp.second = *opt_second; } else { temp.second = this->second_; } diff --git a/esphome/components/template/datetime/template_time.cpp b/esphome/components/template/datetime/template_time.cpp index 9c81687116..b5efa62ae7 100644 --- a/esphome/components/template/datetime/template_time.cpp +++ b/esphome/components/template/datetime/template_time.cpp @@ -48,46 +48,49 @@ void TemplateTime::update() { } void TemplateTime::control(const datetime::TimeCall &call) { - bool has_hour = call.get_hour().has_value(); - bool has_minute = call.get_minute().has_value(); - bool has_second = call.get_second().has_value(); + auto opt_hour = call.get_hour(); + auto opt_minute = call.get_minute(); + auto opt_second = call.get_second(); + bool has_hour = opt_hour.has_value(); + bool has_minute = opt_minute.has_value(); + bool has_second = opt_second.has_value(); ESPTime value = {}; if (has_hour) - value.hour = *call.get_hour(); + value.hour = *opt_hour; if (has_minute) - value.minute = *call.get_minute(); + value.minute = *opt_minute; if (has_second) - value.second = *call.get_second(); + value.second = *opt_second; this->set_trigger_.trigger(value); if (this->optimistic_) { if (has_hour) - this->hour_ = *call.get_hour(); + this->hour_ = *opt_hour; if (has_minute) - this->minute_ = *call.get_minute(); + this->minute_ = *opt_minute; if (has_second) - this->second_ = *call.get_second(); + this->second_ = *opt_second; this->publish_state(); } if (this->restore_value_) { datetime::TimeEntityRestoreState temp = {}; if (has_hour) { - temp.hour = *call.get_hour(); + temp.hour = *opt_hour; } else { temp.hour = this->hour_; } if (has_minute) { - temp.minute = *call.get_minute(); + temp.minute = *opt_minute; } else { temp.minute = this->minute_; } if (has_second) { - temp.second = *call.get_second(); + temp.second = *opt_second; } else { temp.second = this->second_; } diff --git a/esphome/components/template/fan/template_fan.cpp b/esphome/components/template/fan/template_fan.cpp index cd267bd552..46a5cba9bb 100644 --- a/esphome/components/template/fan/template_fan.cpp +++ b/esphome/components/template/fan/template_fan.cpp @@ -20,14 +20,18 @@ void TemplateFan::setup() { void TemplateFan::dump_config() { LOG_FAN("", "Template Fan", this); } void TemplateFan::control(const fan::FanCall &call) { - if (call.get_state().has_value()) - this->state = *call.get_state(); - if (call.get_speed().has_value() && (this->speed_count_ > 0)) - this->speed = *call.get_speed(); - if (call.get_oscillating().has_value() && this->has_oscillating_) - this->oscillating = *call.get_oscillating(); - if (call.get_direction().has_value() && this->has_direction_) - this->direction = *call.get_direction(); + auto call_state = call.get_state(); + if (call_state.has_value()) + this->state = *call_state; + auto call_speed = call.get_speed(); + if (call_speed.has_value() && (this->speed_count_ > 0)) + this->speed = *call_speed; + auto call_oscillating = call.get_oscillating(); + if (call_oscillating.has_value() && this->has_oscillating_) + this->oscillating = *call_oscillating; + auto call_direction = call.get_direction(); + if (call_direction.has_value() && this->has_direction_) + this->direction = *call_direction; this->apply_preset_mode_(call); this->publish_state(); diff --git a/esphome/components/template/lock/template_lock.cpp b/esphome/components/template/lock/template_lock.cpp index dbc4501ce7..6e73623ae9 100644 --- a/esphome/components/template/lock/template_lock.cpp +++ b/esphome/components/template/lock/template_lock.cpp @@ -25,7 +25,10 @@ void TemplateLock::control(const lock::LockCall &call) { this->prev_trigger_->stop_action(); } - auto state = *call.get_state(); + auto opt_state = call.get_state(); + if (!opt_state.has_value()) + return; + auto state = *opt_state; if (state == LOCK_STATE_LOCKED) { this->prev_trigger_ = &this->lock_trigger_; this->lock_trigger_.trigger(); diff --git a/esphome/components/template/valve/template_valve.cpp b/esphome/components/template/valve/template_valve.cpp index 2817e1a132..3ebeec1285 100644 --- a/esphome/components/template/valve/template_valve.cpp +++ b/esphome/components/template/valve/template_valve.cpp @@ -77,8 +77,9 @@ void TemplateValve::control(const ValveCall &call) { this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto pos_val = call.get_position(); + if (pos_val.has_value()) { + auto pos = *pos_val; this->stop_prev_trigger_(); if (pos == VALVE_OPEN) { diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index 57c76286a0..73081d204b 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -101,9 +101,10 @@ water_heater::WaterHeaterCallInternal TemplateWaterHeater::make_call() { } void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) { - if (call.get_mode().has_value()) { + auto mode_val = call.get_mode(); + if (mode_val.has_value()) { if (this->optimistic_) { - this->mode_ = *call.get_mode(); + this->mode_ = *mode_val; } } if (!std::isnan(call.get_target_temperature())) { @@ -112,14 +113,16 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) { } } - if (call.get_away().has_value()) { + auto away_val = call.get_away(); + if (away_val.has_value()) { if (this->optimistic_) { - this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *call.get_away()); + this->set_state_flag_(water_heater::WATER_HEATER_STATE_AWAY, *away_val); } } - if (call.get_on().has_value()) { + auto on_val = call.get_on(); + if (on_val.has_value()) { if (this->optimistic_) { - this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *call.get_on()); + this->set_state_flag_(water_heater::WATER_HEATER_STATE_ON, *on_val); } } diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index c666419701..d52a22f880 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -84,7 +84,7 @@ void ThermostatClimate::refresh() { this->switch_to_mode_(this->mode, false); this->switch_to_action_(this->compute_action_(), false); this->switch_to_supplemental_action_(this->compute_supplemental_action_()); - this->switch_to_fan_mode_(this->fan_mode.value(), false); + this->switch_to_fan_mode_(this->fan_mode.value_or(climate::CLIMATE_FAN_ON), false); this->switch_to_swing_mode_(this->swing_mode, false); this->switch_to_humidity_control_action_(this->compute_humidity_control_action_()); this->check_humidity_change_trigger_(); @@ -211,12 +211,13 @@ void ThermostatClimate::validate_target_humidity() { void ThermostatClimate::control(const climate::ClimateCall &call) { bool target_temperature_high_changed = false; - if (call.get_preset().has_value()) { + auto preset = call.get_preset(); + if (preset.has_value()) { // setup_complete_ blocks modifying/resetting the temps immediately after boot if (this->setup_complete_) { - this->change_preset_(call.get_preset().value()); + this->change_preset_(*preset); } else { - this->preset = call.get_preset().value(); + this->preset = preset; } } if (call.has_custom_preset()) { @@ -229,34 +230,41 @@ void ThermostatClimate::control(const climate::ClimateCall &call) { } } - if (call.get_mode().has_value()) { - this->mode = call.get_mode().value(); + auto mode = call.get_mode(); + if (mode.has_value()) { + this->mode = *mode; } - if (call.get_fan_mode().has_value()) { - this->fan_mode = call.get_fan_mode().value(); + auto fan_mode = call.get_fan_mode(); + if (fan_mode.has_value()) { + this->fan_mode = fan_mode; } - if (call.get_swing_mode().has_value()) { - this->swing_mode = call.get_swing_mode().value(); + auto swing_mode = call.get_swing_mode(); + if (swing_mode.has_value()) { + this->swing_mode = *swing_mode; } if (this->supports_two_points_) { - if (call.get_target_temperature_low().has_value()) { - this->target_temperature_low = call.get_target_temperature_low().value(); + auto target_temp_low = call.get_target_temperature_low(); + if (target_temp_low.has_value()) { + this->target_temperature_low = *target_temp_low; } - if (call.get_target_temperature_high().has_value()) { - target_temperature_high_changed = this->target_temperature_high != call.get_target_temperature_high().value(); - this->target_temperature_high = call.get_target_temperature_high().value(); + auto target_temp_high = call.get_target_temperature_high(); + if (target_temp_high.has_value()) { + target_temperature_high_changed = this->target_temperature_high != *target_temp_high; + this->target_temperature_high = *target_temp_high; } // ensure the two set points are valid and adjust one of them if necessary this->validate_target_temperatures(target_temperature_high_changed || (this->prev_mode_ == climate::CLIMATE_MODE_COOL)); } else { - if (call.get_target_temperature().has_value()) { - this->target_temperature = call.get_target_temperature().value(); + auto target_temp = call.get_target_temperature(); + if (target_temp.has_value()) { + this->target_temperature = *target_temp; this->validate_target_temperature(); } } - if (call.get_target_humidity().has_value()) { - this->target_humidity = call.get_target_humidity().value(); + auto target_humidity = call.get_target_humidity(); + if (target_humidity.has_value()) { + this->target_humidity = *target_humidity; this->validate_target_humidity(); } // make any changes happen @@ -1264,9 +1272,9 @@ bool ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTem something_changed = true; } - if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_.value())) { + if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_)) { ESP_LOGV(TAG, "Setting fan mode to %s", LOG_STR_ARG(climate::climate_fan_mode_to_string(*config.fan_mode_))); - this->fan_mode = *config.fan_mode_; + this->fan_mode = config.fan_mode_; something_changed = true; } diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/time_based_cover.cpp index f6a3048bd4..c83829ff59 100644 --- a/esphome/components/time_based/time_based_cover.cpp +++ b/esphome/components/time_based/time_based_cover.cpp @@ -79,8 +79,9 @@ void TimeBasedCover::control(const CoverCall &call) { } } } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto pos_val = call.get_position(); + if (pos_val.has_value()) { + auto pos = *pos_val; if (pos == this->position) { // already at target if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) { diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index be412d62a8..f567be0674 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -66,8 +66,9 @@ void Tormatic::control(const cover::CoverCall &call) { return; } - if (call.get_position().has_value()) { - auto pos = call.get_position().value(); + auto pos_val = call.get_position(); + if (pos_val.has_value()) { + auto pos = *pos_val; this->control_position_(pos); return; } diff --git a/esphome/components/toshiba/toshiba.cpp b/esphome/components/toshiba/toshiba.cpp index 7b5e78af52..e0c150537a 100644 --- a/esphome/components/toshiba/toshiba.cpp +++ b/esphome/components/toshiba/toshiba.cpp @@ -502,7 +502,7 @@ void ToshibaClimate::transmit_generic_() { } uint8_t fan; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_QUIET: fan = TOSHIBA_FAN_SPEED_QUIET; break; @@ -567,7 +567,7 @@ void ToshibaClimate::transmit_rac_pt1411hwru_() { message[2] = RAC_PT1411HWRU_NO_FAN.code1; message[7] = RAC_PT1411HWRU_NO_FAN.code2; } else { - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: message[2] = RAC_PT1411HWRU_FAN_LOW.code1; message[7] = RAC_PT1411HWRU_FAN_LOW.code2; @@ -811,12 +811,12 @@ void ToshibaClimate::transmit_ras_2819t_() { uint8_t temp_code = get_ras_2819t_temp_code(temperature); // Get fan speed encoding for rc_code_1 - climate::ClimateFanMode effective_fan_mode = this->fan_mode.value(); + climate::ClimateFanMode effective_fan_mode = this->fan_mode.value_or(climate::CLIMATE_FAN_ON); // Dry mode only supports AUTO fan speed if (this->mode == climate::CLIMATE_MODE_DRY) { effective_fan_mode = climate::CLIMATE_FAN_AUTO; - if (this->fan_mode.value() != climate::CLIMATE_FAN_AUTO) { + if (this->fan_mode.value_or(climate::CLIMATE_FAN_ON) != climate::CLIMATE_FAN_AUTO) { ESP_LOGW(TAG, "Dry mode only supports AUTO fan speed, forcing AUTO"); } } diff --git a/esphome/components/tuya/climate/tuya_climate.cpp b/esphome/components/tuya/climate/tuya_climate.cpp index 4d8fd4b310..6602ccd8c9 100644 --- a/esphome/components/tuya/climate/tuya_climate.cpp +++ b/esphome/components/tuya/climate/tuya_climate.cpp @@ -7,8 +7,9 @@ namespace tuya { static const char *const TAG = "tuya.climate"; void TuyaClimate::setup() { - if (this->switch_id_.has_value()) { - this->parent_->register_listener(*this->switch_id_, [this](const TuyaDatapoint &datapoint) { + auto switch_id = this->switch_id_; + if (switch_id.has_value()) { + this->parent_->register_listener(*switch_id, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported switch is: %s", ONOFF(datapoint.value_bool)); this->mode = climate::CLIMATE_MODE_OFF; if (datapoint.value_bool) { @@ -32,16 +33,18 @@ void TuyaClimate::setup() { 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) { + auto active_state_id = this->active_state_id_; + if (active_state_id.has_value()) { + this->parent_->register_listener(*active_state_id, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported active state is: %u", datapoint.value_enum); this->active_state_ = datapoint.value_enum; this->compute_state_(); this->publish_state(); }); } - if (this->target_temperature_id_.has_value()) { - this->parent_->register_listener(*this->target_temperature_id_, [this](const TuyaDatapoint &datapoint) { + auto target_temp_id = this->target_temperature_id_; + if (target_temp_id.has_value()) { + this->parent_->register_listener(*target_temp_id, [this](const TuyaDatapoint &datapoint) { this->manual_temperature_ = datapoint.value_int * this->target_temperature_multiplier_; if (this->reports_fahrenheit_) { this->manual_temperature_ = (this->manual_temperature_ - 32) * 5 / 9; @@ -53,8 +56,9 @@ void TuyaClimate::setup() { this->publish_state(); }); } - if (this->current_temperature_id_.has_value()) { - this->parent_->register_listener(*this->current_temperature_id_, [this](const TuyaDatapoint &datapoint) { + auto current_temp_id = this->current_temperature_id_; + if (current_temp_id.has_value()) { + this->parent_->register_listener(*current_temp_id, [this](const TuyaDatapoint &datapoint) { this->current_temperature = datapoint.value_int * this->current_temperature_multiplier_; if (this->reports_fahrenheit_) { this->current_temperature = (this->current_temperature - 32) * 5 / 9; @@ -65,8 +69,9 @@ void TuyaClimate::setup() { this->publish_state(); }); } - if (this->eco_id_.has_value()) { - this->parent_->register_listener(*this->eco_id_, [this](const TuyaDatapoint &datapoint) { + auto eco_id = this->eco_id_; + if (eco_id.has_value()) { + this->parent_->register_listener(*eco_id, [this](const TuyaDatapoint &datapoint) { // Whether data type is BOOL or ENUM, it will still be a 1 or a 0, so the functions below are valid in both cases this->eco_ = datapoint.value_bool; this->eco_type_ = datapoint.type; @@ -76,8 +81,9 @@ void TuyaClimate::setup() { this->publish_state(); }); } - if (this->sleep_id_.has_value()) { - this->parent_->register_listener(*this->sleep_id_, [this](const TuyaDatapoint &datapoint) { + auto sleep_id = this->sleep_id_; + if (sleep_id.has_value()) { + this->parent_->register_listener(*sleep_id, [this](const TuyaDatapoint &datapoint) { this->sleep_ = datapoint.value_bool; ESP_LOGV(TAG, "MCU reported sleep is: %s", ONOFF(this->sleep_)); this->compute_preset_(); @@ -85,8 +91,9 @@ void TuyaClimate::setup() { this->publish_state(); }); } - if (this->swing_vertical_id_.has_value()) { - this->parent_->register_listener(*this->swing_vertical_id_, [this](const TuyaDatapoint &datapoint) { + auto swing_vert_id = this->swing_vertical_id_; + if (swing_vert_id.has_value()) { + this->parent_->register_listener(*swing_vert_id, [this](const TuyaDatapoint &datapoint) { this->swing_vertical_ = datapoint.value_bool; ESP_LOGV(TAG, "MCU reported vertical swing is: %s", ONOFF(datapoint.value_bool)); this->compute_swingmode_(); @@ -94,8 +101,9 @@ void TuyaClimate::setup() { }); } - if (this->swing_horizontal_id_.has_value()) { - this->parent_->register_listener(*this->swing_horizontal_id_, [this](const TuyaDatapoint &datapoint) { + auto swing_horiz_id = this->swing_horizontal_id_; + if (swing_horiz_id.has_value()) { + this->parent_->register_listener(*swing_horiz_id, [this](const TuyaDatapoint &datapoint) { this->swing_horizontal_ = datapoint.value_bool; ESP_LOGV(TAG, "MCU reported horizontal swing is: %s", ONOFF(datapoint.value_bool)); this->compute_swingmode_(); @@ -103,8 +111,9 @@ void TuyaClimate::setup() { }); } - if (this->fan_speed_id_.has_value()) { - this->parent_->register_listener(*this->fan_speed_id_, [this](const TuyaDatapoint &datapoint) { + auto fan_speed_id = this->fan_speed_id_; + if (fan_speed_id.has_value()) { + this->parent_->register_listener(*fan_speed_id, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported Fan Speed Mode is: %u", datapoint.value_enum); this->fan_state_ = datapoint.value_enum; this->compute_fanmode_(); @@ -139,21 +148,34 @@ void TuyaClimate::loop() { } void TuyaClimate::control(const climate::ClimateCall &call) { - if (call.get_mode().has_value()) { - const bool switch_state = *call.get_mode() != climate::CLIMATE_MODE_OFF; + auto mode = call.get_mode(); + if (mode.has_value()) { + const bool switch_state = *mode != climate::CLIMATE_MODE_OFF; ESP_LOGV(TAG, "Setting switch: %s", ONOFF(switch_state)); - this->parent_->set_boolean_datapoint_value(*this->switch_id_, switch_state); - const climate::ClimateMode new_mode = *call.get_mode(); + auto switch_dp_id = this->switch_id_; + if (switch_dp_id.has_value()) { + this->parent_->set_boolean_datapoint_value(*switch_dp_id, switch_state); + } + const climate::ClimateMode new_mode = *mode; - if (this->active_state_id_.has_value()) { + auto active_state_dp_id = this->active_state_id_; + if (active_state_dp_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_); + auto heating_val = this->active_state_heating_value_; + if (heating_val.has_value()) + this->parent_->set_enum_datapoint_value(*active_state_dp_id, *heating_val); } 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_); + auto cooling_val = this->active_state_cooling_value_; + if (cooling_val.has_value()) + this->parent_->set_enum_datapoint_value(*active_state_dp_id, *cooling_val); + } else if (new_mode == climate::CLIMATE_MODE_DRY) { + auto drying_val = this->active_state_drying_value_; + if (drying_val.has_value()) + this->parent_->set_enum_datapoint_value(*active_state_dp_id, *drying_val); + } else if (new_mode == climate::CLIMATE_MODE_FAN_ONLY) { + auto fanonly_val = this->active_state_fanonly_value_; + if (fanonly_val.has_value()) + this->parent_->set_enum_datapoint_value(*active_state_dp_id, *fanonly_val); } } else { ESP_LOGW(TAG, "Active state (mode) datapoint not configured"); @@ -163,31 +185,38 @@ void TuyaClimate::control(const climate::ClimateCall &call) { control_swing_mode_(call); control_fan_mode_(call); - if (call.get_target_temperature().has_value()) { - float target_temperature = *call.get_target_temperature(); + auto target_temp = call.get_target_temperature(); + if (target_temp.has_value()) { + float target_temperature = *target_temp; if (this->reports_fahrenheit_) target_temperature = (target_temperature * 9 / 5) + 32; ESP_LOGV(TAG, "Setting target temperature: %.1f", target_temperature); - this->parent_->set_integer_datapoint_value(*this->target_temperature_id_, - (int) (target_temperature / this->target_temperature_multiplier_)); + auto target_temp_dp_id = this->target_temperature_id_; + if (target_temp_dp_id.has_value()) { + this->parent_->set_integer_datapoint_value(*target_temp_dp_id, + (int) (target_temperature / this->target_temperature_multiplier_)); + } } - if (call.get_preset().has_value()) { - const climate::ClimatePreset preset = *call.get_preset(); - if (this->eco_id_.has_value()) { + auto preset_val = call.get_preset(); + if (preset_val.has_value()) { + const climate::ClimatePreset preset = *preset_val; + auto eco_dp_id = this->eco_id_; + if (eco_dp_id.has_value()) { const bool eco = preset == climate::CLIMATE_PRESET_ECO; ESP_LOGV(TAG, "Setting eco: %s", ONOFF(eco)); if (this->eco_type_ == TuyaDatapointType::ENUM) { - this->parent_->set_enum_datapoint_value(*this->eco_id_, eco); + this->parent_->set_enum_datapoint_value(*eco_dp_id, eco); } else { - this->parent_->set_boolean_datapoint_value(*this->eco_id_, eco); + this->parent_->set_boolean_datapoint_value(*eco_dp_id, eco); } } - if (this->sleep_id_.has_value()) { + auto sleep_dp_id = this->sleep_id_; + if (sleep_dp_id.has_value()) { const bool sleep = preset == climate::CLIMATE_PRESET_SLEEP; ESP_LOGV(TAG, "Setting sleep: %s", ONOFF(sleep)); - this->parent_->set_boolean_datapoint_value(*this->sleep_id_, sleep); + this->parent_->set_boolean_datapoint_value(*sleep_dp_id, sleep); } } } @@ -196,8 +225,9 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) { bool vertical_swing_changed = false; bool horizontal_swing_changed = false; - if (call.get_swing_mode().has_value()) { - const auto swing_mode = *call.get_swing_mode(); + auto swing_mode_val = call.get_swing_mode(); + if (swing_mode_val.has_value()) { + const auto swing_mode = *swing_mode_val; switch (swing_mode) { case climate::CLIMATE_SWING_OFF: @@ -241,14 +271,16 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) { } } - if (vertical_swing_changed && this->swing_vertical_id_.has_value()) { + auto vert_dp_id = this->swing_vertical_id_; + if (vertical_swing_changed && vert_dp_id.has_value()) { ESP_LOGV(TAG, "Setting vertical swing: %s", ONOFF(swing_vertical_)); - this->parent_->set_boolean_datapoint_value(*this->swing_vertical_id_, swing_vertical_); + this->parent_->set_boolean_datapoint_value(*vert_dp_id, swing_vertical_); } - if (horizontal_swing_changed && this->swing_horizontal_id_.has_value()) { + auto horiz_dp_id = this->swing_horizontal_id_; + if (horizontal_swing_changed && horiz_dp_id.has_value()) { ESP_LOGV(TAG, "Setting horizontal swing: %s", ONOFF(swing_horizontal_)); - this->parent_->set_boolean_datapoint_value(*this->swing_horizontal_id_, swing_horizontal_); + this->parent_->set_boolean_datapoint_value(*horiz_dp_id, swing_horizontal_); } // Publish the state after updating the swing mode @@ -256,33 +288,35 @@ void TuyaClimate::control_swing_mode_(const climate::ClimateCall &call) { } void TuyaClimate::control_fan_mode_(const climate::ClimateCall &call) { - if (call.get_fan_mode().has_value()) { - climate::ClimateFanMode fan_mode = *call.get_fan_mode(); + auto fan_mode_val = call.get_fan_mode(); + if (fan_mode_val.has_value()) { + climate::ClimateFanMode fan_mode = *fan_mode_val; uint8_t tuya_fan_speed; switch (fan_mode) { case climate::CLIMATE_FAN_LOW: - tuya_fan_speed = *fan_speed_low_value_; + tuya_fan_speed = this->fan_speed_low_value_.value_or(0); break; case climate::CLIMATE_FAN_MEDIUM: - tuya_fan_speed = *fan_speed_medium_value_; + tuya_fan_speed = this->fan_speed_medium_value_.value_or(0); break; case climate::CLIMATE_FAN_MIDDLE: - tuya_fan_speed = *fan_speed_middle_value_; + tuya_fan_speed = this->fan_speed_middle_value_.value_or(0); break; case climate::CLIMATE_FAN_HIGH: - tuya_fan_speed = *fan_speed_high_value_; + tuya_fan_speed = this->fan_speed_high_value_.value_or(0); break; case climate::CLIMATE_FAN_AUTO: - tuya_fan_speed = *fan_speed_auto_value_; + tuya_fan_speed = this->fan_speed_auto_value_.value_or(0); break; default: tuya_fan_speed = 0; break; } - if (this->fan_speed_id_.has_value()) { - this->parent_->set_enum_datapoint_value(*this->fan_speed_id_, tuya_fan_speed); + auto fan_speed_dp_id = this->fan_speed_id_; + if (fan_speed_dp_id.has_value()) { + this->parent_->set_enum_datapoint_value(*fan_speed_dp_id, tuya_fan_speed); } } } @@ -337,31 +371,39 @@ climate::ClimateTraits TuyaClimate::traits() { void TuyaClimate::dump_config() { LOG_CLIMATE("", "Tuya Climate", this); - if (this->switch_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_); + auto switch_dp_id = this->switch_id_; + if (switch_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *switch_dp_id); } - if (this->active_state_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Active state has datapoint ID %u", *this->active_state_id_); + auto active_state_dp_id = this->active_state_id_; + if (active_state_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Active state has datapoint ID %u", *active_state_dp_id); } - if (this->target_temperature_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Target Temperature has datapoint ID %u", *this->target_temperature_id_); + auto target_temp_dp_id = this->target_temperature_id_; + if (target_temp_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Target Temperature has datapoint ID %u", *target_temp_dp_id); } - if (this->current_temperature_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Current Temperature has datapoint ID %u", *this->current_temperature_id_); + auto current_temp_dp_id = this->current_temperature_id_; + if (current_temp_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Current Temperature has datapoint ID %u", *current_temp_dp_id); } LOG_PIN(" Heating State Pin: ", this->heating_state_pin_); LOG_PIN(" Cooling State Pin: ", this->cooling_state_pin_); - if (this->eco_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Eco has datapoint ID %u", *this->eco_id_); + auto eco_dp_id = this->eco_id_; + if (eco_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Eco has datapoint ID %u", *eco_dp_id); } - if (this->sleep_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Sleep has datapoint ID %u", *this->sleep_id_); + auto sleep_dp_id = this->sleep_id_; + if (sleep_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Sleep has datapoint ID %u", *sleep_dp_id); } - if (this->swing_vertical_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Swing Vertical has datapoint ID %u", *this->swing_vertical_id_); + auto swing_vert_dp_id = this->swing_vertical_id_; + if (swing_vert_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Swing Vertical has datapoint ID %u", *swing_vert_dp_id); } - if (this->swing_horizontal_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Swing Horizontal has datapoint ID %u", *this->swing_horizontal_id_); + auto swing_horiz_dp_id = this->swing_horizontal_id_; + if (swing_horiz_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Swing Horizontal has datapoint ID %u", *swing_horiz_dp_id); } } diff --git a/esphome/components/tuya/cover/tuya_cover.cpp b/esphome/components/tuya/cover/tuya_cover.cpp index 14bf937cf7..125afec048 100644 --- a/esphome/components/tuya/cover/tuya_cover.cpp +++ b/esphome/components/tuya/cover/tuya_cover.cpp @@ -39,6 +39,9 @@ void TuyaCover::setup() { } }); + if (!this->position_id_.has_value()) { + return; + } uint8_t report_id = *this->position_id_; if (this->position_report_id_.has_value()) { // A position report datapoint is configured; listen to that instead. @@ -60,29 +63,30 @@ void TuyaCover::control(const cover::CoverCall &call) { if (call.get_stop()) { if (this->control_id_.has_value()) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_STOP); - } else { + } else if (this->position_id_.has_value()) { auto pos = this->position; pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast<uint32_t>(pos * this->value_range_); position_int = position_int + this->min_value_; - parent_->force_set_integer_datapoint_value(*this->position_id_, position_int); + this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int); } } - if (call.get_position().has_value()) { - auto pos = *call.get_position(); + auto pos_opt = call.get_position(); + if (pos_opt.has_value()) { + auto pos = *pos_opt; if (this->control_id_.has_value() && (pos == COVER_OPEN || pos == COVER_CLOSED)) { if (pos == COVER_OPEN) { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_OPEN); } else { this->parent_->force_set_enum_datapoint_value(*this->control_id_, COMMAND_CLOSE); } - } else { + } else if (this->position_id_.has_value()) { pos = this->invert_position_report_ ? pos : 1.0f - pos; auto position_int = static_cast<uint32_t>(pos * this->value_range_); position_int = position_int + this->min_value_; - parent_->force_set_integer_datapoint_value(*this->position_id_, position_int); + this->parent_->force_set_integer_datapoint_value(*this->position_id_, position_int); } } diff --git a/esphome/components/tuya/fan/tuya_fan.cpp b/esphome/components/tuya/fan/tuya_fan.cpp index 9b132e0de6..a387606b77 100644 --- a/esphome/components/tuya/fan/tuya_fan.cpp +++ b/esphome/components/tuya/fan/tuya_fan.cpp @@ -7,8 +7,9 @@ namespace tuya { static const char *const TAG = "tuya.fan"; void TuyaFan::setup() { - if (this->speed_id_.has_value()) { - this->parent_->register_listener(*this->speed_id_, [this](const TuyaDatapoint &datapoint) { + auto speed_id = this->speed_id_; + if (speed_id.has_value()) { + this->parent_->register_listener(*speed_id, [this](const TuyaDatapoint &datapoint) { if (datapoint.type == TuyaDatapointType::ENUM) { ESP_LOGV(TAG, "MCU reported speed of: %d", datapoint.value_enum); if (datapoint.value_enum >= this->speed_count_) { @@ -25,15 +26,17 @@ void TuyaFan::setup() { this->speed_type_ = datapoint.type; }); } - if (this->switch_id_.has_value()) { - this->parent_->register_listener(*this->switch_id_, [this](const TuyaDatapoint &datapoint) { + auto switch_id = this->switch_id_; + if (switch_id.has_value()) { + this->parent_->register_listener(*switch_id, [this](const TuyaDatapoint &datapoint) { ESP_LOGV(TAG, "MCU reported switch is: %s", ONOFF(datapoint.value_bool)); this->state = datapoint.value_bool; this->publish_state(); }); } - if (this->oscillation_id_.has_value()) { - this->parent_->register_listener(*this->oscillation_id_, [this](const TuyaDatapoint &datapoint) { + auto oscillation_id = this->oscillation_id_; + if (oscillation_id.has_value()) { + this->parent_->register_listener(*oscillation_id, [this](const TuyaDatapoint &datapoint) { // Whether data type is BOOL or ENUM, it will still be a 1 or a 0, so the functions below are valid in both // scenarios ESP_LOGV(TAG, "MCU reported oscillation is: %s", ONOFF(datapoint.value_bool)); @@ -43,8 +46,9 @@ void TuyaFan::setup() { this->oscillation_type_ = datapoint.type; }); } - if (this->direction_id_.has_value()) { - this->parent_->register_listener(*this->direction_id_, [this](const TuyaDatapoint &datapoint) { + auto direction_id = this->direction_id_; + if (direction_id.has_value()) { + this->parent_->register_listener(*direction_id, [this](const TuyaDatapoint &datapoint) { ESP_LOGD(TAG, "MCU reported reverse direction is: %s", ONOFF(datapoint.value_bool)); this->direction = datapoint.value_bool ? fan::FanDirection::REVERSE : fan::FanDirection::FORWARD; this->publish_state(); @@ -60,17 +64,21 @@ void TuyaFan::setup() { void TuyaFan::dump_config() { LOG_FAN("", "Tuya Fan", this); - if (this->speed_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Speed has datapoint ID %u", *this->speed_id_); + auto speed_dp_id = this->speed_id_; + if (speed_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Speed has datapoint ID %u", *speed_dp_id); } - if (this->switch_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *this->switch_id_); + auto switch_dp_id = this->switch_id_; + if (switch_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Switch has datapoint ID %u", *switch_dp_id); } - if (this->oscillation_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Oscillation has datapoint ID %u", *this->oscillation_id_); + auto oscillation_dp_id = this->oscillation_id_; + if (oscillation_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Oscillation has datapoint ID %u", *oscillation_dp_id); } - if (this->direction_id_.has_value()) { - ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *this->direction_id_); + auto direction_dp_id = this->direction_id_; + if (direction_dp_id.has_value()) { + ESP_LOGCONFIG(TAG, " Direction has datapoint ID %u", *direction_dp_id); } } @@ -80,25 +88,41 @@ fan::FanTraits TuyaFan::get_traits() { } void TuyaFan::control(const fan::FanCall &call) { - if (this->switch_id_.has_value() && call.get_state().has_value()) { - this->parent_->set_boolean_datapoint_value(*this->switch_id_, *call.get_state()); - } - if (this->oscillation_id_.has_value() && call.get_oscillating().has_value()) { - if (this->oscillation_type_ == TuyaDatapointType::ENUM) { - this->parent_->set_enum_datapoint_value(*this->oscillation_id_, *call.get_oscillating()); - } else if (this->oscillation_type_ == TuyaDatapointType::BOOLEAN) { - this->parent_->set_boolean_datapoint_value(*this->oscillation_id_, *call.get_oscillating()); + auto switch_id = this->switch_id_; + if (switch_id.has_value()) { + auto state = call.get_state(); + if (state.has_value()) { + this->parent_->set_boolean_datapoint_value(*switch_id, *state); } } - if (this->direction_id_.has_value() && call.get_direction().has_value()) { - bool enable = *call.get_direction() == fan::FanDirection::REVERSE; - this->parent_->set_enum_datapoint_value(*this->direction_id_, enable); + auto osc_id = this->oscillation_id_; + if (osc_id.has_value()) { + auto oscillating = call.get_oscillating(); + if (oscillating.has_value()) { + if (this->oscillation_type_ == TuyaDatapointType::ENUM) { + this->parent_->set_enum_datapoint_value(*osc_id, *oscillating); + } else if (this->oscillation_type_ == TuyaDatapointType::BOOLEAN) { + this->parent_->set_boolean_datapoint_value(*osc_id, *oscillating); + } + } } - if (this->speed_id_.has_value() && call.get_speed().has_value()) { - if (this->speed_type_ == TuyaDatapointType::ENUM) { - this->parent_->set_enum_datapoint_value(*this->speed_id_, *call.get_speed() - 1); - } else if (this->speed_type_ == TuyaDatapointType::INTEGER) { - this->parent_->set_integer_datapoint_value(*this->speed_id_, *call.get_speed()); + auto dir_id = this->direction_id_; + if (dir_id.has_value()) { + auto direction = call.get_direction(); + if (direction.has_value()) { + bool enable = *direction == fan::FanDirection::REVERSE; + this->parent_->set_enum_datapoint_value(*dir_id, enable); + } + } + auto spd_id = this->speed_id_; + if (spd_id.has_value()) { + auto speed = call.get_speed(); + if (speed.has_value()) { + if (this->speed_type_ == TuyaDatapointType::ENUM) { + this->parent_->set_enum_datapoint_value(*spd_id, *speed - 1); + } else if (this->speed_type_ == TuyaDatapointType::INTEGER) { + this->parent_->set_integer_datapoint_value(*spd_id, *speed); + } } } } diff --git a/esphome/components/tuya/light/tuya_light.cpp b/esphome/components/tuya/light/tuya_light.cpp index 097b3c1af8..620bb88d0b 100644 --- a/esphome/components/tuya/light/tuya_light.cpp +++ b/esphome/components/tuya/light/tuya_light.cpp @@ -57,6 +57,9 @@ void TuyaLight::setup() { return; } + if (!this->color_type_.has_value()) + return; + float red, green, blue; switch (*this->color_type_) { case TuyaColorType::RGBHSV: @@ -185,7 +188,7 @@ void TuyaLight::write_state(light::LightState *state) { } } - if (this->color_id_.has_value() && (brightness == 0.0f || !color_interlock_)) { + if (this->color_id_.has_value() && this->color_type_.has_value() && (brightness == 0.0f || !color_interlock_)) { std::string color_value; switch (*this->color_type_) { case TuyaColorType::RGB: { diff --git a/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp b/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp index 4256b01c4e..3eae4d2d96 100644 --- a/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +++ b/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp @@ -42,8 +42,9 @@ climate::ClimateTraits UponorSmatrixClimate::traits() { } void UponorSmatrixClimate::control(const climate::ClimateCall &call) { - if (call.get_target_temperature().has_value()) { - uint16_t temp = celsius_to_raw(*call.get_target_temperature()); + auto val = call.get_target_temperature(); + if (val.has_value()) { + uint16_t temp = celsius_to_raw(*val); if (this->preset == climate::CLIMATE_PRESET_ECO) { // During ECO mode, the thermostat automatically substracts the setback value from the setpoint, // so we need to add it here first diff --git a/esphome/components/whirlpool/whirlpool.cpp b/esphome/components/whirlpool/whirlpool.cpp index 6fe735362d..e9f602e97f 100644 --- a/esphome/components/whirlpool/whirlpool.cpp +++ b/esphome/components/whirlpool/whirlpool.cpp @@ -82,7 +82,7 @@ void WhirlpoolClimate::transmit_state() { remote_state[3] |= (uint8_t) (temp - this->temperature_min_()) << 4; // Fan speed - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_HIGH: remote_state[2] |= WHIRLPOOL_FAN_HIGH; break; diff --git a/esphome/components/whynter/whynter.cpp b/esphome/components/whynter/whynter.cpp index 9f57fdb843..003d2e0ba6 100644 --- a/esphome/components/whynter/whynter.cpp +++ b/esphome/components/whynter/whynter.cpp @@ -69,7 +69,7 @@ void Whynter::transmit_state() { } mode_before_ = this->mode; - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: remote_state |= FAN_LOW; break; diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 7d5d0133c1..852ff922f1 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -1094,8 +1094,9 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { } #ifdef USE_WIFI_WPA2_EAP - if (ap.get_eap().has_value()) { - EAPAuth eap_config = ap.get_eap().value(); + auto eap_opt = ap.get_eap(); + if (eap_opt.has_value()) { + EAPAuth eap_config = *eap_opt; // clang-format off ESP_LOGV( TAG, @@ -1129,8 +1130,9 @@ void WiFiComponent::start_connecting(const WiFiAP &ap) { ESP_LOGV(TAG, " Channel not set"); } #ifdef USE_WIFI_MANUAL_IP - if (ap.get_manual_ip().has_value()) { - ManualIP m = *ap.get_manual_ip(); + auto manual_ip = ap.get_manual_ip(); + if (manual_ip.has_value()) { + ManualIP m = *manual_ip; char static_ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE]; char subnet_buf[network::IP_ADDRESS_BUFFER_SIZE]; diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index bd6a18a99b..02ce59502b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -298,9 +298,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // setup enterprise authentication if required #ifdef USE_WIFI_WPA2_EAP - if (ap.get_eap().has_value()) { + auto eap_opt = ap.get_eap(); + if (eap_opt.has_value()) { // note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0. - EAPAuth eap = ap.get_eap().value(); + EAPAuth eap = *eap_opt; ret = wifi_station_set_enterprise_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); if (ret) { ESP_LOGV(TAG, "esp_wifi_sta_wpa2_ent_set_identity failed: %d", ret); diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 734d186205..bf432cea6e 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -403,9 +403,10 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // setup enterprise authentication if required #ifdef USE_WIFI_WPA2_EAP - if (ap.get_eap().has_value()) { + auto eap_opt = ap.get_eap(); + if (eap_opt.has_value()) { // note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0. - EAPAuth eap = ap.get_eap().value(); + EAPAuth eap = *eap_opt; #if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) err = esp_eap_client_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); #else diff --git a/esphome/components/yashima/yashima.cpp b/esphome/components/yashima/yashima.cpp index bf91420620..4a64e6c41c 100644 --- a/esphome/components/yashima/yashima.cpp +++ b/esphome/components/yashima/yashima.cpp @@ -120,10 +120,12 @@ void YashimaClimate::setup() { } void YashimaClimate::control(const climate::ClimateCall &call) { - if (call.get_mode().has_value()) - this->mode = *call.get_mode(); - if (call.get_target_temperature().has_value()) - this->target_temperature = *call.get_target_temperature(); + auto call_mode = call.get_mode(); + if (call_mode.has_value()) + this->mode = *call_mode; + auto call_target = call.get_target_temperature(); + if (call_target.has_value()) + this->target_temperature = *call_target; this->transmit_state_(); this->publish_state(); diff --git a/esphome/components/zhlt01/zhlt01.cpp b/esphome/components/zhlt01/zhlt01.cpp index 36d1737c14..e5ab5915e4 100644 --- a/esphome/components/zhlt01/zhlt01.cpp +++ b/esphome/components/zhlt01/zhlt01.cpp @@ -13,7 +13,7 @@ void ZHLT01Climate::transmit_state() { ir_message[1] = 0x00; // Timer off // Byte 3 : Turbo mode - if (this->preset.value() == climate::CLIMATE_PRESET_BOOST) { + if (this->preset.value_or(climate::CLIMATE_PRESET_NONE) == climate::CLIMATE_PRESET_BOOST) { ir_message[3] = AC1_FAN_TURBO; } @@ -47,7 +47,7 @@ void ZHLT01Climate::transmit_state() { } // -- Fan - switch (this->preset.value()) { + switch (this->preset.value_or(climate::CLIMATE_PRESET_NONE)) { case climate::CLIMATE_PRESET_BOOST: ir_message[7] |= AC1_FAN3; break; @@ -55,7 +55,7 @@ void ZHLT01Climate::transmit_state() { ir_message[7] |= AC1_FAN_SILENT; break; default: - switch (this->fan_mode.value()) { + switch (this->fan_mode.value_or(climate::CLIMATE_FAN_ON)) { case climate::CLIMATE_FAN_LOW: ir_message[7] |= AC1_FAN1; break; diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 042eebb40f..54d4ae311f 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -248,7 +248,7 @@ void log_entity_unit_of_measurement(const char *tag, const char *prefix, const E template<typename T> class StatefulEntityBase : public EntityBase { public: virtual bool has_state() const { return this->state_.has_value(); } - virtual const T &get_state() const { return this->state_.value(); } + virtual const T &get_state() const { return this->state_.value(); } // NOLINT(bugprone-unchecked-optional-access) virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); } void invalidate_state() { this->set_new_state({}); } diff --git a/esphome/core/optional.h b/esphome/core/optional.h index 7f9db7817d..88a02aa8b2 100644 --- a/esphome/core/optional.h +++ b/esphome/core/optional.h @@ -1,220 +1,12 @@ #pragma once -// -// Copyright (c) 2017 Martin Moene -// -// https://github.com/martinmoene/optional-bare -// -// This code is licensed under the MIT License (MIT). -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// Modified by Otto Winter on 18.05.18 -#include <algorithm> +#include <optional> namespace esphome { -// type for nullopt - -struct nullopt_t { // NOLINT - struct init {}; // NOLINT - nullopt_t(init /*unused*/) {} -}; - -// extra parenthesis to prevent the most vexing parse: - -const nullopt_t nullopt((nullopt_t::init())); // NOLINT - -// Simplistic optional: requires T to be default constructible, copyable. - -template<typename T> class optional { // NOLINT - private: - using safe_bool = void (optional::*)() const; - - public: - using value_type = T; - - optional() {} - - optional(nullopt_t /*unused*/) {} - - optional(T const &arg) : has_value_(true), value_(arg) {} // NOLINT - - template<class U> optional(optional<U> const &other) : has_value_(other.has_value()), value_(other.value()) {} - - optional &operator=(nullopt_t /*unused*/) { - reset(); - return *this; - } - bool operator==(optional<T> const &rhs) const { - if (has_value() && rhs.has_value()) - return value() == rhs.value(); - return !has_value() && !rhs.has_value(); - } - - template<class U> optional &operator=(optional<U> const &other) { - has_value_ = other.has_value(); - value_ = other.value(); - return *this; - } - - void swap(optional &rhs) noexcept { - using std::swap; - if (has_value() && rhs.has_value()) { - swap(**this, *rhs); - } else if (!has_value() && rhs.has_value()) { - initialize(*rhs); - rhs.reset(); - } else if (has_value() && !rhs.has_value()) { - rhs.initialize(**this); - reset(); - } - } - - // observers - - value_type const *operator->() const { return &value_; } - - value_type *operator->() { return &value_; } - - value_type const &operator*() const { return value_; } - - value_type &operator*() { return value_; } - - operator safe_bool() const { return has_value() ? &optional::this_type_does_not_support_comparisons : nullptr; } - - bool has_value() const { return has_value_; } - - value_type const &value() const { return value_; } - - value_type &value() { return value_; } - - template<class U> value_type value_or(U const &v) const { return has_value() ? value() : static_cast<value_type>(v); } - - // modifiers - - void reset() { has_value_ = false; } - - private: - void this_type_does_not_support_comparisons() const {} // NOLINT - - template<typename V> void initialize(V const &value) { // NOLINT - value_ = value; - has_value_ = true; - } - - bool has_value_{false}; // NOLINT - value_type value_; // NOLINT -}; - -// Relational operators - -template<typename T, typename U> inline bool operator==(optional<T> const &x, optional<U> const &y) { - return bool(x) != bool(y) ? false : !bool(x) ? true : *x == *y; -} - -template<typename T, typename U> inline bool operator!=(optional<T> const &x, optional<U> const &y) { - return !(x == y); -} - -template<typename T, typename U> inline bool operator<(optional<T> const &x, optional<U> const &y) { - return (!y) ? false : (!x) ? true : *x < *y; -} - -template<typename T, typename U> inline bool operator>(optional<T> const &x, optional<U> const &y) { return (y < x); } - -template<typename T, typename U> inline bool operator<=(optional<T> const &x, optional<U> const &y) { return !(y < x); } - -template<typename T, typename U> inline bool operator>=(optional<T> const &x, optional<U> const &y) { return !(x < y); } - -// Comparison with nullopt - -template<typename T> inline bool operator==(optional<T> const &x, nullopt_t /*unused*/) { return (!x); } - -template<typename T> inline bool operator==(nullopt_t /*unused*/, optional<T> const &x) { return (!x); } - -template<typename T> inline bool operator!=(optional<T> const &x, nullopt_t /*unused*/) { return bool(x); } - -template<typename T> inline bool operator!=(nullopt_t /*unused*/, optional<T> const &x) { return bool(x); } - -template<typename T> inline bool operator<(optional<T> const & /*unused*/, nullopt_t /*unused*/) { return false; } - -template<typename T> inline bool operator<(nullopt_t /*unused*/, optional<T> const &x) { return bool(x); } - -template<typename T> inline bool operator<=(optional<T> const &x, nullopt_t /*unused*/) { return (!x); } - -template<typename T> inline bool operator<=(nullopt_t /*unused*/, optional<T> const & /*unused*/) { return true; } - -template<typename T> inline bool operator>(optional<T> const &x, nullopt_t /*unused*/) { return bool(x); } - -template<typename T> inline bool operator>(nullopt_t /*unused*/, optional<T> const & /*unused*/) { return false; } - -template<typename T> inline bool operator>=(optional<T> const & /*unused*/, nullopt_t /*unused*/) { return true; } - -template<typename T> inline bool operator>=(nullopt_t /*unused*/, optional<T> const &x) { return (!x); } - -// Comparison with T - -template<typename T, typename U> inline bool operator==(optional<T> const &x, U const &v) { - return bool(x) ? *x == v : false; -} - -template<typename T, typename U> inline bool operator==(U const &v, optional<T> const &x) { - return bool(x) ? v == *x : false; -} - -template<typename T, typename U> inline bool operator!=(optional<T> const &x, U const &v) { - return bool(x) ? *x != v : true; -} - -template<typename T, typename U> inline bool operator!=(U const &v, optional<T> const &x) { - return bool(x) ? v != *x : true; -} - -template<typename T, typename U> inline bool operator<(optional<T> const &x, U const &v) { - return bool(x) ? *x < v : true; -} - -template<typename T, typename U> inline bool operator<(U const &v, optional<T> const &x) { - return bool(x) ? v < *x : false; -} - -template<typename T, typename U> inline bool operator<=(optional<T> const &x, U const &v) { - return bool(x) ? *x <= v : true; -} - -template<typename T, typename U> inline bool operator<=(U const &v, optional<T> const &x) { - return bool(x) ? v <= *x : false; -} - -template<typename T, typename U> inline bool operator>(optional<T> const &x, U const &v) { - return bool(x) ? *x > v : false; -} - -template<typename T, typename U> inline bool operator>(U const &v, optional<T> const &x) { - return bool(x) ? v > *x : true; -} - -template<typename T, typename U> inline bool operator>=(optional<T> const &x, U const &v) { - return bool(x) ? *x >= v : false; -} - -template<typename T, typename U> inline bool operator>=(U const &v, optional<T> const &x) { - return bool(x) ? v >= *x : true; -} - -// Specialized algorithms - -template<typename T> void swap(optional<T> &x, optional<T> &y) noexcept { x.swap(y); } - -// Convenience function to create an optional. - -template<typename T> inline optional<T> make_optional(T const &v) { return optional<T>(v); } +using std::make_optional; +using std::nullopt; +using std::nullopt_t; +using std::optional; } // namespace esphome diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 6d255bc0be..8dd77de843 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -31,9 +31,7 @@ Component = esphome_ns.class_("Component") ComponentPtr = Component.operator("ptr") PollingComponent = esphome_ns.class_("PollingComponent", Component) Application = esphome_ns.class_("Application") -# Create optional with explicit namespace to avoid ambiguity with std::optional -# The generated code will use esphome::optional instead of just optional -optional = global_ns.namespace("esphome").class_("optional") +optional = global_ns.namespace("std").class_("optional") arduino_json_ns = global_ns.namespace("ArduinoJson") JsonObject = arduino_json_ns.class_("JsonObject") JsonObjectConst = arduino_json_ns.class_("JsonObjectConst") diff --git a/tests/component_tests/text/test_text.py b/tests/component_tests/text/test_text.py index 6b047bc62f..16f5f980a5 100644 --- a/tests/component_tests/text/test_text.py +++ b/tests/component_tests/text/test_text.py @@ -66,5 +66,20 @@ def test_text_config_lamda_is_set(generate_main): main_cpp = generate_main("tests/component_tests/text/test_text.yaml") # Then - assert "it_4->set_template([]() -> esphome::optional<std::string> {" in main_cpp + assert "it_4->set_template([]() -> std::optional<std::string> {" in main_cpp assert 'return std::string{"Hello"};' in main_cpp + + +def test_esphome_optional_alias_works(generate_main): + """ + Test that esphome::optional alias compiles (backward compatibility) + """ + # Given + + # When + main_cpp = generate_main("tests/component_tests/text/test_text.yaml") + + # Then + # Codegen emits std::optional, but esphome::optional must also work + # via the using alias in esphome/core/optional.h + assert "std::optional<std::string>" in main_cpp diff --git a/tests/components/template/common-base.yaml b/tests/components/template/common-base.yaml index e9ddfcf43e..ed398b0abd 100644 --- a/tests/components/template/common-base.yaml +++ b/tests/components/template/common-base.yaml @@ -28,9 +28,14 @@ esphome: # Test C++ API: set_template() with stateless lambda (no captures) # NOTE: set_template() is not intended to be a public API, but we test it to ensure it doesn't break. - lambda: |- - id(template_sens).set_template([]() -> esphome::optional<float> { + id(template_sens).set_template([]() -> std::optional<float> { return 123.0f; }); + # Test that esphome::optional alias still works for backward compatibility + - lambda: |- + id(template_sens).set_template([]() -> esphome::optional<float> { + return 42.0f; + }); - datetime.date.set: id: test_date From 8911d9d28f1adb2414f67a00c0035295e554f388 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 3 Mar 2026 19:42:36 -0600 Subject: [PATCH 1088/2030] [media_source] Clarify threading contract (#14433) --- esphome/components/media_source/media_source.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/components/media_source/media_source.h b/esphome/components/media_source/media_source.h index 688c27134f..f21ba486b8 100644 --- a/esphome/components/media_source/media_source.h +++ b/esphome/components/media_source/media_source.h @@ -67,11 +67,13 @@ class MediaSource { /// @brief Start playing the given URI /// Sources should validate the URI and state, returning false if the source is busy. /// The orchestrator is responsible for stopping active sources before starting a new one. + /// @note Must only be called from the main loop. /// @param uri URI to play; e.g., "http://stream_url" /// @return true if playback started successfully, false otherwise virtual bool play_uri(const std::string &uri) = 0; - /// @brief Handle playback commands (pause, stop, next, etc.) + /// @brief Handle playback commands; e.g., pause, stop, next, etc. + /// @note Must only be called from the main loop. /// @param command Command to execute virtual void handle_command(MediaSourceCommand command) = 0; @@ -81,7 +83,8 @@ class MediaSource { // === State Access === - /// @brief Get current playback state (must only be called from the main loop) + /// @brief Get current playback state + /// @note Must only be called from the main loop. /// @return Current state of this source MediaSourceState get_state() const { return this->state_; } @@ -136,9 +139,10 @@ class MediaSource { virtual void notify_audio_played(uint32_t frames, int64_t timestamp) {} protected: - /// @brief Update state and notify listener (must only be called from the main loop) + /// @brief Update state and notify listener /// This is the only way to change state_, ensuring listener notifications always fire. /// Sources running FreeRTOS tasks should signal via event groups and call this from loop(). + /// @note Must only be called from the main loop. /// @param state New state to set void set_state_(MediaSourceState state) { if (this->state_ != state) { From cba34e770e8077f95305bdbbf5352def17d58dcf Mon Sep 17 00:00:00 2001 From: Tilman Vogel <tilman.vogel@web.de> Date: Wed, 4 Mar 2026 03:18:36 +0100 Subject: [PATCH 1089/2030] [core] improve help text for --device option, mention `OTA` (#14445) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/__main__.py | 7 ++++--- esphome/const.py | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index ffedb90bde..0164e2eeb3 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -23,6 +23,7 @@ import esphome.codegen as cg from esphome.config import iter_component_configs, read_config, strip_default_ids from esphome.const import ( ALLOWED_NAME_CHARS, + ARGUMENT_HELP_DEVICE, CONF_API, CONF_BAUD_RATE, CONF_BROKER, @@ -1367,7 +1368,7 @@ def parse_args(argv): parser_upload.add_argument( "--device", action="append", - help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.", + help=ARGUMENT_HELP_DEVICE, ) parser_upload.add_argument( "--upload_speed", @@ -1390,7 +1391,7 @@ def parse_args(argv): parser_logs.add_argument( "--device", action="append", - help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.", + help=ARGUMENT_HELP_DEVICE, ) parser_logs.add_argument( "--reset", @@ -1420,7 +1421,7 @@ def parse_args(argv): parser_run.add_argument( "--device", action="append", - help="Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses.", + help=ARGUMENT_HELP_DEVICE, ) parser_run.add_argument( "--upload_speed", diff --git a/esphome/const.py b/esphome/const.py index d5625f6a54..060e962573 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -11,6 +11,9 @@ VALID_SUBSTITUTIONS_CHARACTERS = ( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" ) +# CLI Help Text Constants +ARGUMENT_HELP_DEVICE = "Manually specify the serial port/address to use, for example /dev/ttyUSB0. Can be specified multiple times for fallback addresses. Use 'OTA' for resolving from MQTT, DNS or mDNS and avoiding the interactive prompt." + class Platform(StrEnum): """Platform identifiers for ESPHome.""" From 37146ff565aa239338948401b8493210af6ba5da Mon Sep 17 00:00:00 2001 From: JiriPrchal <163323169+JiriPrchal@users.noreply.github.com> Date: Wed, 4 Mar 2026 15:00:09 +0100 Subject: [PATCH 1090/2030] [integration] Add set method to publish and save sensor value (#13316) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../integration/integration_sensor.h | 13 ++++++---- esphome/components/integration/sensor.py | 25 +++++++++++++++++-- .../components/integration/common-esp32.yaml | 10 ++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/esphome/components/integration/integration_sensor.h b/esphome/components/integration/integration_sensor.h index f075d163fe..6c4ef7049b 100644 --- a/esphome/components/integration/integration_sensor.h +++ b/esphome/components/integration/integration_sensor.h @@ -32,6 +32,7 @@ class IntegrationSensor : public sensor::Sensor, public Component { void set_method(IntegrationMethod method) { method_ = method; } void set_restore(bool restore) { restore_ = restore; } void reset() { this->publish_and_save_(0.0f); } + void set_value(float value) { this->publish_and_save_(value); } protected: void process_sensor_value_(float value); @@ -71,14 +72,16 @@ class IntegrationSensor : public sensor::Sensor, public Component { float last_value_{0.0f}; }; -template<typename... Ts> class ResetAction : public Action<Ts...> { +template<typename... Ts> class ResetAction : public Action<Ts...>, public Parented<IntegrationSensor> { public: - explicit ResetAction(IntegrationSensor *parent) : parent_(parent) {} - void play(const Ts &...x) override { this->parent_->reset(); } +}; - protected: - IntegrationSensor *parent_; +template<typename... Ts> class SetValueAction : public Action<Ts...>, public Parented<IntegrationSensor> { + public: + TEMPLATABLE_VALUE(float, value) + + void play(const Ts &...x) override { this->parent_->set_value(this->value_.value(x...)); } }; } // namespace integration diff --git a/esphome/components/integration/sensor.py b/esphome/components/integration/sensor.py index 3c04a338dd..2676638556 100644 --- a/esphome/components/integration/sensor.py +++ b/esphome/components/integration/sensor.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_RESTORE, CONF_SENSOR, CONF_UNIT_OF_MEASUREMENT, + CONF_VALUE, ) from esphome.core.entity_helpers import inherit_property_from @@ -17,6 +18,7 @@ IntegrationSensor = integration_ns.class_( "IntegrationSensor", sensor.Sensor, cg.Component ) ResetAction = integration_ns.class_("ResetAction", automation.Action) +SetValueAction = integration_ns.class_("SetValueAction", automation.Action) IntegrationSensorTime = integration_ns.enum("IntegrationSensorTime") INTEGRATION_TIMES = { @@ -111,5 +113,24 @@ async def to_code(config): ), ) async def sensor_integration_reset_to_code(config, action_id, template_arg, args): - paren = await cg.get_variable(config[CONF_ID]) - return cg.new_Pvariable(action_id, template_arg, paren) + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + return var + + +@automation.register_action( + "sensor.integration.set_value", + SetValueAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(IntegrationSensor), + cv.Required(CONF_VALUE): cv.templatable(cv.float_), + } + ), +) +async def sensor_integration_set_value_to_code(config, action_id, template_arg, args): + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + template_ = await cg.templatable(config[CONF_VALUE], args, float) + cg.add(var.set_value(template_)) + return var diff --git a/tests/components/integration/common-esp32.yaml b/tests/components/integration/common-esp32.yaml index 248106fd60..26550d3c5c 100644 --- a/tests/components/integration/common-esp32.yaml +++ b/tests/components/integration/common-esp32.yaml @@ -1,9 +1,19 @@ +esphome: + on_boot: + then: + - sensor.integration.reset: + id: integration_sensor + - sensor.integration.set_value: + id: integration_sensor + value: 100.0 + sensor: - platform: adc id: my_sensor pin: ${pin} attenuation: 12db - platform: integration + id: integration_sensor sensor: my_sensor name: Integration Sensor time_unit: s From 065773ed4c3e84243e483409aefba0403c92f9a4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 07:17:28 -1000 Subject: [PATCH 1091/2030] [runtime_stats] Use micros() for accurate per-component timing (#14452) --- .../runtime_stats/runtime_stats.cpp | 22 ++++---- .../components/runtime_stats/runtime_stats.h | 56 +++++++++---------- esphome/core/component.cpp | 7 ++- esphome/core/component.h | 16 +++++- 4 files changed, 60 insertions(+), 41 deletions(-) diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index 410695da04..d9fa22d949 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -13,12 +13,12 @@ RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_ global_runtime_stats = this; } -void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_ms, uint32_t current_time) { +void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_us, uint32_t current_time) { if (component == nullptr) return; // Record stats using component pointer as key - this->component_stats_[component].record_time(duration_ms); + this->component_stats_[component].record_time(duration_us); if (this->next_log_time_ == 0) { this->next_log_time_ = current_time + this->log_interval_; @@ -58,15 +58,16 @@ void RuntimeStatsCollector::log_stats_() { // Sort by period runtime (descending) std::sort(sorted, sorted + count, [this](Component *a, Component *b) { - return this->component_stats_[a].get_period_time_ms() > this->component_stats_[b].get_period_time_ms(); + return this->component_stats_[a].get_period_time_us() > this->component_stats_[b].get_period_time_us(); }); // Log top components by period runtime for (size_t i = 0; i < count; i++) { const auto &stats = this->component_stats_[sorted[i]]; - ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", - LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_period_count(), stats.get_period_avg_time_ms(), - stats.get_period_max_time_ms(), stats.get_period_time_ms()); + ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.3fms, max=%.2fms, total=%.1fms", + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_period_count(), + stats.get_period_avg_time_us() / 1000.0f, stats.get_period_max_time_us() / 1000.0f, + stats.get_period_time_us() / 1000.0f); } // Log total stats since boot (only for active components - idle ones haven't changed) @@ -74,14 +75,15 @@ void RuntimeStatsCollector::log_stats_() { // Re-sort by total runtime for all-time stats std::sort(sorted, sorted + count, [this](Component *a, Component *b) { - return this->component_stats_[a].get_total_time_ms() > this->component_stats_[b].get_total_time_ms(); + return this->component_stats_[a].get_total_time_us() > this->component_stats_[b].get_total_time_us(); }); for (size_t i = 0; i < count; i++) { const auto &stats = this->component_stats_[sorted[i]]; - ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.2fms, max=%" PRIu32 "ms, total=%" PRIu32 "ms", - LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_total_count(), stats.get_total_avg_time_ms(), - stats.get_total_max_time_ms(), stats.get_total_time_ms()); + ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.3fms, max=%.2fms, total=%.1fms", + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_total_count(), + stats.get_total_avg_time_us() / 1000.0f, stats.get_total_max_time_us() / 1000.0f, + stats.get_total_time_us() / 1000.0); } } diff --git a/esphome/components/runtime_stats/runtime_stats.h b/esphome/components/runtime_stats/runtime_stats.h index c7fea7474b..0847529720 100644 --- a/esphome/components/runtime_stats/runtime_stats.h +++ b/esphome/components/runtime_stats/runtime_stats.h @@ -22,58 +22,58 @@ class ComponentRuntimeStats { public: ComponentRuntimeStats() : period_count_(0), - period_time_ms_(0), - period_max_time_ms_(0), + period_time_us_(0), + period_max_time_us_(0), total_count_(0), - total_time_ms_(0), - total_max_time_ms_(0) {} + total_time_us_(0), + total_max_time_us_(0) {} - void record_time(uint32_t duration_ms) { + void record_time(uint32_t duration_us) { // Update period counters this->period_count_++; - this->period_time_ms_ += duration_ms; - if (duration_ms > this->period_max_time_ms_) - this->period_max_time_ms_ = duration_ms; + this->period_time_us_ += duration_us; + if (duration_us > this->period_max_time_us_) + this->period_max_time_us_ = duration_us; - // Update total counters + // Update total counters (uint64_t to avoid overflow — uint32_t would overflow after ~10 hours) this->total_count_++; - this->total_time_ms_ += duration_ms; - if (duration_ms > this->total_max_time_ms_) - this->total_max_time_ms_ = duration_ms; + this->total_time_us_ += duration_us; + if (duration_us > this->total_max_time_us_) + this->total_max_time_us_ = duration_us; } void reset_period_stats() { this->period_count_ = 0; - this->period_time_ms_ = 0; - this->period_max_time_ms_ = 0; + this->period_time_us_ = 0; + this->period_max_time_us_ = 0; } // Period stats (reset each logging interval) uint32_t get_period_count() const { return this->period_count_; } - uint32_t get_period_time_ms() const { return this->period_time_ms_; } - uint32_t get_period_max_time_ms() const { return this->period_max_time_ms_; } - float get_period_avg_time_ms() const { - return this->period_count_ > 0 ? this->period_time_ms_ / static_cast<float>(this->period_count_) : 0.0f; + uint32_t get_period_time_us() const { return this->period_time_us_; } + uint32_t get_period_max_time_us() const { return this->period_max_time_us_; } + float get_period_avg_time_us() const { + return this->period_count_ > 0 ? this->period_time_us_ / static_cast<float>(this->period_count_) : 0.0f; } - // Total stats (persistent until reboot) + // Total stats (persistent until reboot, uint64_t to avoid overflow) uint32_t get_total_count() const { return this->total_count_; } - uint32_t get_total_time_ms() const { return this->total_time_ms_; } - uint32_t get_total_max_time_ms() const { return this->total_max_time_ms_; } - float get_total_avg_time_ms() const { - return this->total_count_ > 0 ? this->total_time_ms_ / static_cast<float>(this->total_count_) : 0.0f; + uint64_t get_total_time_us() const { return this->total_time_us_; } + uint32_t get_total_max_time_us() const { return this->total_max_time_us_; } + float get_total_avg_time_us() const { + return this->total_count_ > 0 ? this->total_time_us_ / static_cast<float>(this->total_count_) : 0.0f; } protected: // Period stats (reset each logging interval) uint32_t period_count_; - uint32_t period_time_ms_; - uint32_t period_max_time_ms_; + uint32_t period_time_us_; + uint32_t period_max_time_us_; // Total stats (persistent until reboot) uint32_t total_count_; - uint32_t total_time_ms_; - uint32_t total_max_time_ms_; + uint64_t total_time_us_; + uint32_t total_max_time_us_; }; class RuntimeStatsCollector { @@ -83,7 +83,7 @@ class RuntimeStatsCollector { void set_log_interval(uint32_t log_interval) { this->log_interval_ = log_interval; } uint32_t get_log_interval() const { return this->log_interval_; } - void record_component_time(Component *component, uint32_t duration_ms, uint32_t current_time); + void record_component_time(Component *component, uint32_t duration_us, uint32_t current_time); // Process any pending stats printing (should be called after component loop) void process_pending_stats(uint32_t current_time); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 4ccc747819..8c2c8d38e8 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -529,9 +529,12 @@ uint32_t WarnIfComponentBlockingGuard::finish() { uint32_t curr_time = millis(); uint32_t blocking_time = curr_time - this->started_; #ifdef USE_RUNTIME_STATS - // Record component runtime stats + // Use micros() for accurate sub-millisecond timing. millis() has insufficient + // resolution — most components complete in microseconds but millis() only has + // 1ms granularity, so results were essentially random noise. if (global_runtime_stats != nullptr) { - global_runtime_stats->record_component_time(this->component_, blocking_time, curr_time); + uint32_t duration_us = micros() - this->started_us_; + global_runtime_stats->record_component_time(this->component_, duration_us, curr_time); } #endif if (blocking_time > WARN_IF_BLOCKING_OVER_MS) { diff --git a/esphome/core/component.h b/esphome/core/component.h index e5127b0c9f..59222dc4f4 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -563,10 +563,21 @@ class PollingComponent : public Component { uint32_t update_interval_; }; +#ifdef USE_RUNTIME_STATS +uint32_t micros(); // Forward declare for inline constructor +#endif + class WarnIfComponentBlockingGuard { public: WarnIfComponentBlockingGuard(Component *component, uint32_t start_time) - : started_(start_time), component_(component) {} + : started_(start_time), + component_(component) +#ifdef USE_RUNTIME_STATS + , + started_us_(micros()) +#endif + { + } // Finish the timing operation and return the current time uint32_t finish(); @@ -576,6 +587,9 @@ class WarnIfComponentBlockingGuard { protected: uint32_t started_; Component *component_; +#ifdef USE_RUNTIME_STATS + uint32_t started_us_; +#endif }; // Function to clear setup priority overrides after all components are set up From ac19d05db26a891b6dd0d4301b8e8321f9c48fe0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 07:17:41 -1000 Subject: [PATCH 1092/2030] [core] Call loop() directly in main loop, bypass call() indirection (#14451) --- esphome/core/application.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 8c2ba58c86..db1c8a0c0a 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -153,6 +153,14 @@ void Application::setup() { this->setup_wake_loop_threadsafe_(); #endif + // Ensure all active looping components are in LOOP state. + // Components after the last blocking component only got one call() during setup + // (CONSTRUCTION→SETUP) and never received the second call() (SETUP→LOOP). + // The main loop calls loop() directly, bypassing call()'s state machine. + for (uint16_t i = 0; i < this->looping_components_active_end_; i++) { + this->looping_components_[i]->set_component_state_(COMPONENT_STATE_LOOP); + } + this->schedule_dump_config(); } void Application::loop() { @@ -173,7 +181,7 @@ void Application::loop() { { this->set_current_component(component); WarnIfComponentBlockingGuard guard{component, last_op_end_time}; - component->call(); + component->loop(); // Use the finish method to get the current time as the end time last_op_end_time = guard.finish(); } From b2e8544c584c29a923a88622a7b7ba10373a761f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 07:18:31 -1000 Subject: [PATCH 1093/2030] [ld2412] Add integration tests with mock UART (#14448) --- .../fixtures/uart_mock_ld2412.yaml | 171 ++++++++ .../uart_mock_ld2412_engineering.yaml | 213 +++++++++ tests/integration/test_uart_mock_ld2412.py | 407 ++++++++++++++++++ 3 files changed, 791 insertions(+) create mode 100644 tests/integration/fixtures/uart_mock_ld2412.yaml create mode 100644 tests/integration/fixtures/uart_mock_ld2412_engineering.yaml create mode 100644 tests/integration/test_uart_mock_ld2412.py diff --git a/tests/integration/fixtures/uart_mock_ld2412.yaml b/tests/integration/fixtures/uart_mock_ld2412.yaml new file mode 100644 index 0000000000..a502f36a25 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2412.yaml @@ -0,0 +1,171 @@ +esphome: + name: uart-mock-ld2412-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2412's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + injections: + # Phase 1 (t=100ms): Valid LD2412 normal mode data frame - happy path + # The buffer is clean at this point, so this frame should parse correctly. + # Moving target: 100cm, energy 50 + # Still target: 120cm, energy 25 + # Target state: 0x03 (moving + still) + # detection_distance = 100 (LD2412 computes from moving target when MOVE_BITMASK set) + # + # Frame layout (24 bytes): + # [0-3] F4 F3 F2 F1 = data frame header + # [4-5] 0D 00 = length 13 + # [6] 02 = data type (normal) + # [7] AA = data header marker + # [8] 03 = target states (moving+still) + # [9-10] 64 00 = moving distance 100 (0x0064) + # [11] 32 = moving energy 50 + # [12-13] 78 00 = still distance 120 (0x0078) + # [14] 19 = still energy 25 + # [15-16] 64 00 = detect distance bytes (ignored by LD2412 code) + # [17] 00 = padding + # [18] 55 = data footer marker + # [19] 00 = CRC/check + # [20-23] F8 F7 F6 F5 = data frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x0D, 0x00, + 0x02, 0xAA, + 0x03, + 0x64, 0x00, + 0x32, + 0x78, 0x00, + 0x19, + 0x64, 0x00, + 0x00, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=300ms): Garbage bytes + # LD2412's parser rejects bytes that don't match the frame header at + # position 0 (must start with F4 or FD), so buffer stays empty. + - delay: 200ms + inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22] + + # Phase 3 (t=400ms): Truncated frame (header + partial data, no footer) + # Starts with valid data frame header so parser accepts it. + # After this, buffer_pos_ = 8. + - delay: 100ms + inject_rx: [0xF4, 0xF3, 0xF2, 0xF1, 0x0D, 0x00, 0x02, 0xAA] + + # Phase 4 (t=600ms): Overflow - inject 60 bytes of 0xFF (MAX_LINE_LENGTH=54) + # Buffer has 8 bytes from phase 3 (garbage in phase 2 was rejected). + # Overflow math: buffer_pos_ starts at 8, overflow triggers when + # buffer_pos_ reaches 53 (MAX_LINE_LENGTH - 1). Need 45 more bytes to + # fill positions 8-52, then byte 46 triggers overflow. After overflow, + # buffer_pos_ = 0 and remaining 0xFF bytes are rejected (don't match header). + - delay: 200ms + inject_rx: + [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ] + + # Phase 5 (t=700ms): Valid frame after overflow - recovery test + # Buffer was reset by overflow. This valid frame should parse correctly. + # Moving target: 50cm, energy 100 + # Still target: 75cm, energy 80 + # detection_distance = 50 (moving target distance, since MOVE_BITMASK set) + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x0D, 0x00, + 0x02, 0xAA, + 0x03, + 0x32, 0x00, + 0x64, + 0x4B, 0x00, + 0x50, + 0x32, 0x00, + 0x00, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +ld2412: + id: ld2412_dev + uart_id: mock_uart + +sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + moving_distance: + name: "Moving Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_distance: + name: "Still Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + moving_energy: + name: "Moving Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_energy: + name: "Still Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + detection_distance: + name: "Detection Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +binary_sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + has_target: + name: "Has Target" + filters: + - settle: 50ms + has_moving_target: + name: "Has Moving Target" + filters: + - settle: 50ms + has_still_target: + name: "Has Still Target" + filters: + - settle: 50ms diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml new file mode 100644 index 0000000000..3c669fc9a9 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml @@ -0,0 +1,213 @@ +esphome: + name: uart-mock-ld2412-eng-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2412's DEPENDENCIES = ["uart"] +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + injections: + # Phase 1 (t=100ms): Valid LD2412 engineering mode data frame + # + # Engineering mode frame layout (52 bytes): + # [0-3] F4 F3 F2 F1 = data frame header + # [4-5] 2A 00 = length 42 + # [6] 01 = data type (engineering mode) + # [7] AA = data header marker + # [8] 03 = target states (moving+still) + # [9-10] 1E 00 = moving distance 30 (0x001E) + # [11] 64 = moving energy 100 + # [12-13] 1E 00 = still distance 30 (0x001E) + # [14] 64 = still energy 100 + # [15-16] 00 00 = detection distance bytes (ignored) + # [17-30] gate moving energies (14 gates) + # [31-44] gate still energies (14 gates) + # [45] 57 = light sensor value 87 + # [46] 55 = data footer marker + # [47] 00 = check + # [48-51] F8 F7 F6 F5 = data frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x2A, 0x00, + 0x01, 0xAA, + 0x03, + 0x1E, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x00, 0x00, + 0x64, 0x41, 0x06, 0x0E, 0x2B, 0x16, 0x03, 0x03, 0x07, 0x05, 0x09, 0x08, 0x07, 0x06, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x50, 0x40, 0x30, 0x20, 0x10, + 0x57, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=200ms): Second engineering mode frame with different values + # Moving at 73cm, still at 30cm + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x2A, 0x00, + 0x01, 0xAA, + 0x03, + 0x49, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x21, 0x00, + 0x11, 0x64, 0x05, 0x29, 0x39, 0x10, 0x03, 0x11, 0x0E, 0x08, 0x06, 0x04, 0x03, 0x02, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x50, 0x40, 0x30, 0x20, 0x10, + 0x57, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 3 (t=300ms): Frame with still target at 291cm (multi-byte distance) + # This tests encode_uint16 with high byte > 0 + # Target state: 0x02 (still only) -> detection_distance = still distance = 291 + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x2A, 0x00, + 0x01, 0xAA, + 0x02, + 0x2F, 0x00, + 0x36, + 0x23, 0x01, + 0x64, + 0x21, 0x00, + 0x2F, 0x36, 0x09, 0x0D, 0x15, 0x0B, 0x06, 0x06, 0x08, 0x09, 0x08, 0x07, 0x06, 0x05, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x5A, 0x3D, 0x30, 0x20, 0x10, 0x08, 0x04, + 0x57, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +ld2412: + id: ld2412_dev + uart_id: mock_uart + +sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + moving_distance: + name: "Moving Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_distance: + name: "Still Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + moving_energy: + name: "Moving Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_energy: + name: "Still Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + detection_distance: + name: "Detection Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + light: + name: "Light" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + gate_0: + move_energy: + name: "Gate 0 Move Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_energy: + name: "Gate 0 Still Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + gate_1: + move_energy: + name: "Gate 1 Move Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_energy: + name: "Gate 1 Still Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + gate_2: + move_energy: + name: "Gate 2 Move Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_energy: + name: "Gate 2 Still Energy" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +binary_sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + has_target: + name: "Has Target" + filters: + - settle: 50ms + has_moving_target: + name: "Has Moving Target" + filters: + - settle: 50ms + has_still_target: + name: "Has Still Target" + filters: + - settle: 50ms diff --git a/tests/integration/test_uart_mock_ld2412.py b/tests/integration/test_uart_mock_ld2412.py new file mode 100644 index 0000000000..cf7324ceed --- /dev/null +++ b/tests/integration/test_uart_mock_ld2412.py @@ -0,0 +1,407 @@ +"""Integration test for LD2412 component with mock UART. + +Tests: +test_uart_mock_ld2412 (normal mode): + 1. Happy path - valid data frame publishes correct sensor values + 2. Garbage resilience - random bytes don't crash the component + 3. Truncated frame handling - partial frame doesn't corrupt state + 4. Buffer overflow recovery - overflow resets the parser + 5. Post-overflow parsing - next valid frame after overflow is parsed correctly + 6. TX logging - verifies LD2412 sends expected setup commands + +test_uart_mock_ld2412_engineering (engineering mode): + 1. Engineering mode frames with per-gate energy data and light sensor + 2. Multi-byte still distance (291cm) using high byte > 0 + 3. Gate energy sensor values + 4. Detection distance computed from target state +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path + +from aioesphomeapi import ( + BinarySensorInfo, + BinarySensorState, + EntityState, + SensorInfo, + SensorState, +) +import pytest + +from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_uart_mock_ld2412( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2412 data parsing with happy path, garbage, overflow, and recovery.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track overflow warning in logs + overflow_seen = loop.create_future() + + # Track TX data logged by the mock for assertions + tx_log_lines: list[str] = [] + + def line_callback(line: str) -> None: + if "Max command length exceeded" in line and not overflow_seen.done(): + overflow_seen.set_result(True) + # Capture all TX log lines from uart_mock + if "uart_mock" in line and "TX " in line: + tx_log_lines.append(line) + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "moving_distance": [], + "still_distance": [], + "moving_energy": [], + "still_energy": [], + "detection_distance": [], + } + binary_states: dict[str, list[bool]] = { + "has_target": [], + "has_moving_target": [], + "has_still_target": [], + } + + # Signal when we see recovery frame values + recovery_received = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + # Check if this is the recovery frame (moving_distance = 50) + if ( + sensor_name == "moving_distance" + and state.state == pytest.approx(50.0) + and not recovery_received.done() + ): + recovery_received.set_result(True) + elif isinstance(state, BinarySensorState): + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in binary_states: + binary_states[sensor_name].append(state.state) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + # Build key mappings for all sensor types + all_names = list(sensor_states.keys()) + list(binary_states.keys()) + # Sort by descending length to avoid substring collisions + # (e.g., "still_energy" matching "gate_0_still_energy") + all_names.sort(key=len, reverse=True) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Phase 1 values are in the initial states (swallowed by InitialStateHelper). + # Verify them via initial_states dict. + moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) + assert moving_dist_entity is not None + initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) + assert initial_moving is not None and isinstance(initial_moving, SensorState) + assert initial_moving.state == pytest.approx(100.0), ( + f"Initial moving distance should be 100, got {initial_moving.state}" + ) + + still_dist_entity = find_entity(entities, "still_distance", SensorInfo) + assert still_dist_entity is not None + initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) + assert initial_still is not None and isinstance(initial_still, SensorState) + assert initial_still.state == pytest.approx(120.0), ( + f"Initial still distance should be 120, got {initial_still.state}" + ) + + moving_energy_entity = find_entity(entities, "moving_energy", SensorInfo) + assert moving_energy_entity is not None + initial_me = initial_state_helper.initial_states.get(moving_energy_entity.key) + assert initial_me is not None and isinstance(initial_me, SensorState) + assert initial_me.state == pytest.approx(50.0), ( + f"Initial moving energy should be 50, got {initial_me.state}" + ) + + still_energy_entity = find_entity(entities, "still_energy", SensorInfo) + assert still_energy_entity is not None + initial_se = initial_state_helper.initial_states.get(still_energy_entity.key) + assert initial_se is not None and isinstance(initial_se, SensorState) + assert initial_se.state == pytest.approx(25.0), ( + f"Initial still energy should be 25, got {initial_se.state}" + ) + + # LD2412 detection_distance = moving_distance when MOVE_BITMASK is set + detect_dist_entity = find_entity(entities, "detection_distance", SensorInfo) + assert detect_dist_entity is not None + initial_dd = initial_state_helper.initial_states.get(detect_dist_entity.key) + assert initial_dd is not None and isinstance(initial_dd, SensorState) + assert initial_dd.state == pytest.approx(100.0), ( + f"Initial detection distance should be 100, got {initial_dd.state}" + ) + + # Wait for the recovery frame (Phase 5) to be parsed + # This proves the component survived garbage + truncated + overflow + try: + await asyncio.wait_for(recovery_received, timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received sensor states:\n" + f" moving_distance: {sensor_states['moving_distance']}\n" + f" still_distance: {sensor_states['still_distance']}\n" + f" moving_energy: {sensor_states['moving_energy']}\n" + f" still_energy: {sensor_states['still_energy']}\n" + f" detection_distance: {sensor_states['detection_distance']}" + ) + + # Verify overflow warning was logged + assert overflow_seen.done(), ( + "Expected 'Max command length exceeded' warning in logs" + ) + + # Verify LD2412 sent setup commands (TX logging) + assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" + tx_data = " ".join(tx_log_lines) + # Verify command frame header appears (FD:FC:FB:FA) + assert "FD:FC:FB:FA" in tx_data, ( + "Expected LD2412 command frame header FD:FC:FB:FA in TX log" + ) + # Verify command frame footer appears (04:03:02:01) + assert "04:03:02:01" in tx_data, ( + "Expected LD2412 command frame footer 04:03:02:01 in TX log" + ) + + # Recovery frame values (Phase 5, after overflow) + assert len(sensor_states["moving_distance"]) >= 1, ( + f"Expected recovery moving_distance, got: {sensor_states['moving_distance']}" + ) + # Find the recovery value (moving_distance = 50) + recovery_values = [ + v for v in sensor_states["moving_distance"] if v == pytest.approx(50.0) + ] + assert len(recovery_values) >= 1, ( + f"Expected moving_distance=50 in recovery, got: {sensor_states['moving_distance']}" + ) + + # Recovery frame: moving=50, still=75, energy=100/80, detect=50 + recovery_idx = next( + i + for i, v in enumerate(sensor_states["moving_distance"]) + if v == pytest.approx(50.0) + ) + assert sensor_states["still_distance"][recovery_idx] == pytest.approx(75.0), ( + f"Recovery still distance should be 75, got {sensor_states['still_distance'][recovery_idx]}" + ) + assert sensor_states["moving_energy"][recovery_idx] == pytest.approx(100.0), ( + f"Recovery moving energy should be 100, got {sensor_states['moving_energy'][recovery_idx]}" + ) + assert sensor_states["still_energy"][recovery_idx] == pytest.approx(80.0), ( + f"Recovery still energy should be 80, got {sensor_states['still_energy'][recovery_idx]}" + ) + # LD2412 detection_distance = moving_distance when MOVE_BITMASK set + assert sensor_states["detection_distance"][recovery_idx] == pytest.approx( + 50.0 + ), ( + f"Recovery detection distance should be 50, got {sensor_states['detection_distance'][recovery_idx]}" + ) + + # Verify binary sensors detected targets + has_target_entity = find_entity(entities, "has_target", BinarySensorInfo) + assert has_target_entity is not None + initial_ht = initial_state_helper.initial_states.get(has_target_entity.key) + assert initial_ht is not None and isinstance(initial_ht, BinarySensorState) + assert initial_ht.state is True, "Has target should be True" + + has_moving_entity = find_entity(entities, "has_moving_target", BinarySensorInfo) + assert has_moving_entity is not None + initial_hm = initial_state_helper.initial_states.get(has_moving_entity.key) + assert initial_hm is not None and isinstance(initial_hm, BinarySensorState) + assert initial_hm.state is True, "Has moving target should be True" + + has_still_entity = find_entity(entities, "has_still_target", BinarySensorInfo) + assert has_still_entity is not None + initial_hs = initial_state_helper.initial_states.get(has_still_entity.key) + assert initial_hs is not None and isinstance(initial_hs, BinarySensorState) + assert initial_hs.state is True, "Has still target should be True" + + +@pytest.mark.asyncio +async def test_uart_mock_ld2412_engineering( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2412 engineering mode with per-gate energy, light, and multi-byte distance.""" + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "moving_distance": [], + "still_distance": [], + "moving_energy": [], + "still_energy": [], + "detection_distance": [], + "light": [], + "gate_0_move_energy": [], + "gate_1_move_energy": [], + "gate_2_move_energy": [], + "gate_0_still_energy": [], + "gate_1_still_energy": [], + "gate_2_still_energy": [], + } + binary_states: dict[str, list[bool]] = { + "has_target": [], + "has_moving_target": [], + "has_still_target": [], + } + + # Signal when we see Phase 3 frame values + phase3_still_received = loop.create_future() + phase3_detect_received = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + if ( + sensor_name == "still_distance" + and state.state == pytest.approx(291.0) + and not phase3_still_received.done() + ): + phase3_still_received.set_result(True) + if ( + sensor_name == "detection_distance" + and state.state == pytest.approx(291.0) + and not phase3_detect_received.done() + ): + phase3_detect_received.set_result(True) + elif isinstance(state, BinarySensorState): + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in binary_states: + binary_states[sensor_name].append(state.state) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + all_names = list(sensor_states.keys()) + list(binary_states.keys()) + # Sort by descending length to avoid substring collisions + # (e.g., "still_energy" matching "gate_0_still_energy") + all_names.sort(key=len, reverse=True) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Phase 1 initial values (engineering mode frame): + # moving=30, energy=100, still=30, energy=100, detect=30 + moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) + assert moving_dist_entity is not None + initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) + assert initial_moving is not None and isinstance(initial_moving, SensorState) + assert initial_moving.state == pytest.approx(30.0), ( + f"Initial moving distance should be 30, got {initial_moving.state}" + ) + + still_dist_entity = find_entity(entities, "still_distance", SensorInfo) + assert still_dist_entity is not None + initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) + assert initial_still is not None and isinstance(initial_still, SensorState) + assert initial_still.state == pytest.approx(30.0), ( + f"Initial still distance should be 30, got {initial_still.state}" + ) + + # Verify engineering mode sensors from initial state + # Gate 0 moving energy = 0x64 = 100 + gate0_move_entity = find_entity(entities, "gate_0_move_energy", SensorInfo) + assert gate0_move_entity is not None + initial_g0m = initial_state_helper.initial_states.get(gate0_move_entity.key) + assert initial_g0m is not None and isinstance(initial_g0m, SensorState) + assert initial_g0m.state == pytest.approx(100.0), ( + f"Gate 0 move energy should be 100, got {initial_g0m.state}" + ) + + # Gate 1 moving energy = 0x41 = 65 + gate1_move_entity = find_entity(entities, "gate_1_move_energy", SensorInfo) + assert gate1_move_entity is not None + initial_g1m = initial_state_helper.initial_states.get(gate1_move_entity.key) + assert initial_g1m is not None and isinstance(initial_g1m, SensorState) + assert initial_g1m.state == pytest.approx(65.0), ( + f"Gate 1 move energy should be 65, got {initial_g1m.state}" + ) + + # Light sensor = 0x57 = 87 + light_entity = find_entity(entities, "light", SensorInfo) + assert light_entity is not None + initial_light = initial_state_helper.initial_states.get(light_entity.key) + assert initial_light is not None and isinstance(initial_light, SensorState) + assert initial_light.state == pytest.approx(87.0), ( + f"Light sensor should be 87, got {initial_light.state}" + ) + + # Wait for Phase 3 frame: still_distance = 291cm (multi-byte) + try: + await asyncio.wait_for(phase3_still_received, timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 3 still_distance. Received:\n" + f" still_distance: {sensor_states['still_distance']}\n" + f" moving_distance: {sensor_states['moving_distance']}" + ) + + assert pytest.approx(291.0) in sensor_states["still_distance"], ( + f"Expected still_distance=291, got: {sensor_states['still_distance']}" + ) + + # Wait for Phase 3: detection_distance = 291 (still-only target) + # target_state=0x02 so LD2412 uses still_distance for detection_distance. + # The throttle_with_priority filter may delay this value. + try: + await asyncio.wait_for(phase3_detect_received, timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for detection_distance=291 (still-only target). " + f"Received: {sensor_states['detection_distance']}" + ) + + assert pytest.approx(291.0) in sensor_states["detection_distance"], ( + f"Expected detection_distance=291, got: {sensor_states['detection_distance']}" + ) From 5ba880f19b967b153340befa1acf271066f8671c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:57:45 -0500 Subject: [PATCH 1094/2030] [sx127x] Fix preamble MSB register always written as zero (#14457) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/sx127x/sx127x.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index caf68b6d51..f6aa11b634 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -186,7 +186,7 @@ void SX127x::configure_fsk_ook_() { } else { this->write_register_(REG_PREAMBLE_DETECT, PREAMBLE_DETECTOR_OFF); } - this->write_register_(REG_PREAMBLE_SIZE_MSB, this->preamble_size_ >> 16); + this->write_register_(REG_PREAMBLE_SIZE_MSB, this->preamble_size_ >> 8); this->write_register_(REG_PREAMBLE_SIZE_LSB, this->preamble_size_ & 0xFF); // config sync generation and setup ook threshold @@ -214,7 +214,7 @@ void SX127x::configure_lora_() { // config preamble if (this->preamble_size_ >= 6) { - this->write_register_(REG_PREAMBLE_LEN_MSB, this->preamble_size_ >> 16); + this->write_register_(REG_PREAMBLE_LEN_MSB, this->preamble_size_ >> 8); this->write_register_(REG_PREAMBLE_LEN_LSB, this->preamble_size_ & 0xFF); } From 9abba79c5429ee9c9c4e9a4f77ca4c67b4a756b2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:58:24 -0500 Subject: [PATCH 1095/2030] [remote_base][remote_receiver] Fix OOB access in pronto comparison and RMT buffer allocation (#14459) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/remote_base/pronto_protocol.cpp | 6 +++++- esphome/components/remote_receiver/remote_receiver_rmt.cpp | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/remote_base/pronto_protocol.cpp b/esphome/components/remote_base/pronto_protocol.cpp index 43029cbc2f..6903cd4605 100644 --- a/esphome/components/remote_base/pronto_protocol.cpp +++ b/esphome/components/remote_base/pronto_protocol.cpp @@ -44,9 +44,13 @@ bool ProntoData::operator==(const ProntoData &rhs) const { std::vector<uint16_t> data1 = encode_pronto(data); std::vector<uint16_t> data2 = encode_pronto(rhs.data); + if (data1.size() != data2.size() || data1.empty()) { + return false; + } + uint32_t total_diff = 0; // Don't need to check the last one, it's the large gap at the end. - for (std::vector<uint16_t>::size_type i = 0; i < data1.size() - 1; ++i) { + for (size_t i = 0; i < data1.size() - 1; ++i) { int diff = data2[i] - data1[i]; diff *= diff; if (rhs.delta == -1 && diff > 9) diff --git a/esphome/components/remote_receiver/remote_receiver_rmt.cpp b/esphome/components/remote_receiver/remote_receiver_rmt.cpp index 357a36d052..96b23bd0f5 100644 --- a/esphome/components/remote_receiver/remote_receiver_rmt.cpp +++ b/esphome/components/remote_receiver/remote_receiver_rmt.cpp @@ -106,7 +106,7 @@ void RemoteReceiverComponent::setup() { this->store_.filter_symbols = this->filter_symbols_; this->store_.receive_size = this->receive_symbols_ * sizeof(rmt_symbol_word_t); this->store_.buffer_size = std::max((event_size + this->store_.receive_size) * 2, this->buffer_size_); - this->store_.buffer = new uint8_t[this->buffer_size_]; + this->store_.buffer = new uint8_t[this->store_.buffer_size]; error = rmt_receive(this->channel_, (uint8_t *) this->store_.buffer + event_size, this->store_.receive_size, &this->store_.config); if (error != ESP_OK) { From 246a8bff0cb9c2de5a740fe8529f072c609dce51 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:58:42 -0500 Subject: [PATCH 1096/2030] [pn7160][pn7150][pn532] Fix tag purge skipping, NDEF bounds check, and NDEF length byte order (#14460) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/pn532/pn532_mifare_ultralight.cpp | 4 ++-- esphome/components/pn7150/pn7150.cpp | 6 +++--- esphome/components/pn7150/pn7150_mifare_ultralight.cpp | 4 ++-- esphome/components/pn7160/pn7160.cpp | 6 +++--- esphome/components/pn7160/pn7160_mifare_ultralight.cpp | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/esphome/components/pn532/pn532_mifare_ultralight.cpp b/esphome/components/pn532/pn532_mifare_ultralight.cpp index a8a8e2d573..0e0dc1542f 100644 --- a/esphome/components/pn532/pn532_mifare_ultralight.cpp +++ b/esphome/components/pn532/pn532_mifare_ultralight.cpp @@ -99,7 +99,7 @@ bool PN532::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6 uint8_t &message_start_index) { const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector - if (!(page_3_to_6.size() > p4_offset + 5)) { + if (!(page_3_to_6.size() > p4_offset + 6)) { return false; } @@ -134,7 +134,7 @@ bool PN532::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, nfc::NdefMessage * } else { encoded.insert(encoded.begin() + 1, 0xFF); encoded.insert(encoded.begin() + 2, (message_length >> 8) & 0xFF); - encoded.insert(encoded.begin() + 2, message_length & 0xFF); + encoded.insert(encoded.begin() + 3, message_length & 0xFF); } encoded.push_back(0xFE); diff --git a/esphome/components/pn7150/pn7150.cpp b/esphome/components/pn7150/pn7150.cpp index 8c76c8b88c..d68bea41b3 100644 --- a/esphome/components/pn7150/pn7150.cpp +++ b/esphome/components/pn7150/pn7150.cpp @@ -562,9 +562,9 @@ optional<size_t> PN7150::find_tag_uid_(const nfc::NfcTagUid &uid) { } void PN7150::purge_old_tags_() { - for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { - if (millis() - this->discovered_endpoint_[i].last_seen > this->tag_ttl_) { - this->erase_tag_(i); + for (size_t i = this->discovered_endpoint_.size(); i > 0; i--) { + if (millis() - this->discovered_endpoint_[i - 1].last_seen > this->tag_ttl_) { + this->erase_tag_(i - 1); } } } diff --git a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp index 46f5dba2b7..854ddd1be1 100644 --- a/esphome/components/pn7150/pn7150_mifare_ultralight.cpp +++ b/esphome/components/pn7150/pn7150_mifare_ultralight.cpp @@ -100,7 +100,7 @@ uint8_t PN7150::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_ uint8_t &message_start_index) { const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector - if (!(page_3_to_6.size() > p4_offset + 5)) { + if (!(page_3_to_6.size() > p4_offset + 6)) { return nfc::STATUS_FAILED; } @@ -135,7 +135,7 @@ uint8_t PN7150::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::sha } else { encoded.insert(encoded.begin() + 1, 0xFF); encoded.insert(encoded.begin() + 2, (message_length >> 8) & 0xFF); - encoded.insert(encoded.begin() + 2, message_length & 0xFF); + encoded.insert(encoded.begin() + 3, message_length & 0xFF); } encoded.push_back(0xFE); diff --git a/esphome/components/pn7160/pn7160.cpp b/esphome/components/pn7160/pn7160.cpp index 3fcd1221a7..5f0f8d0629 100644 --- a/esphome/components/pn7160/pn7160.cpp +++ b/esphome/components/pn7160/pn7160.cpp @@ -589,9 +589,9 @@ optional<size_t> PN7160::find_tag_uid_(const nfc::NfcTagUid &uid) { } void PN7160::purge_old_tags_() { - for (size_t i = 0; i < this->discovered_endpoint_.size(); i++) { - if (millis() - this->discovered_endpoint_[i].last_seen > this->tag_ttl_) { - this->erase_tag_(i); + for (size_t i = this->discovered_endpoint_.size(); i > 0; i--) { + if (millis() - this->discovered_endpoint_[i - 1].last_seen > this->tag_ttl_) { + this->erase_tag_(i - 1); } } } diff --git a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp index 9dc8d3dd2d..8ca0fa2c11 100644 --- a/esphome/components/pn7160/pn7160_mifare_ultralight.cpp +++ b/esphome/components/pn7160/pn7160_mifare_ultralight.cpp @@ -100,7 +100,7 @@ uint8_t PN7160::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_ uint8_t &message_start_index) { const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector - if (!(page_3_to_6.size() > p4_offset + 5)) { + if (!(page_3_to_6.size() > p4_offset + 6)) { return nfc::STATUS_FAILED; } @@ -135,7 +135,7 @@ uint8_t PN7160::write_mifare_ultralight_tag_(nfc::NfcTagUid &uid, const std::sha } else { encoded.insert(encoded.begin() + 1, 0xFF); encoded.insert(encoded.begin() + 2, (message_length >> 8) & 0xFF); - encoded.insert(encoded.begin() + 2, message_length & 0xFF); + encoded.insert(encoded.begin() + 3, message_length & 0xFF); } encoded.push_back(0xFE); From c37ab1de841631dd1802a2abbfde655f49513e12 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 12:58:52 -0500 Subject: [PATCH 1097/2030] [fingerprint_grow] Fix OOB write and uint16 overflow (#14462) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../fingerprint_grow/fingerprint_grow.cpp | 23 ++++++++++--------- .../fingerprint_grow/fingerprint_grow.h | 4 ++-- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.cpp b/esphome/components/fingerprint_grow/fingerprint_grow.cpp index da4535fc82..a633fbca28 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.cpp +++ b/esphome/components/fingerprint_grow/fingerprint_grow.cpp @@ -361,7 +361,7 @@ void FingerprintGrowComponent::aura_led_control(uint8_t state, uint8_t speed, ui } } -uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> *p_data_buffer) { +uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> &data_buffer) { while (this->available()) this->read(); this->write((uint8_t) (START_CODE >> 8)); @@ -372,12 +372,12 @@ uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> *p_data_buffer) this->write(this->address_[3]); this->write(COMMAND); - uint16_t wire_length = p_data_buffer->size() + 2; + uint16_t wire_length = data_buffer.size() + 2; this->write((uint8_t) (wire_length >> 8)); this->write((uint8_t) (wire_length & 0xFF)); uint16_t sum = (wire_length >> 8) + (wire_length & 0xFF) + COMMAND; - for (auto data : *p_data_buffer) { + for (auto data : data_buffer) { this->write(data); sum += data; } @@ -385,7 +385,7 @@ uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> *p_data_buffer) this->write((uint8_t) (sum >> 8)); this->write((uint8_t) (sum & 0xFF)); - p_data_buffer->clear(); + data_buffer.clear(); uint8_t byte; uint16_t idx = 0, length = 0; @@ -431,9 +431,9 @@ uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> *p_data_buffer) length |= byte; break; default: - p_data_buffer->push_back(byte); + data_buffer.push_back(byte); if ((idx - 8) == length) { - switch ((*p_data_buffer)[0]) { + switch (data_buffer[0]) { case OK: case NO_FINGER: case IMAGE_FAIL: @@ -453,25 +453,26 @@ uint8_t FingerprintGrowComponent::transfer_(std::vector<uint8_t> *p_data_buffer) ESP_LOGE(TAG, "Reader failed to process request"); break; default: - ESP_LOGE(TAG, "Unknown response received from reader: 0x%.2X", (*p_data_buffer)[0]); + ESP_LOGE(TAG, "Unknown response received from reader: 0x%.2X", data_buffer[0]); break; } this->last_transfer_ms_ = millis(); - return (*p_data_buffer)[0]; + return data_buffer[0]; } break; } idx++; } ESP_LOGE(TAG, "No response received from reader"); - (*p_data_buffer)[0] = TIMEOUT; + data_buffer.clear(); + data_buffer.push_back(TIMEOUT); this->last_transfer_ms_ = millis(); return TIMEOUT; } uint8_t FingerprintGrowComponent::send_command_() { this->sensor_wakeup_(); - return this->transfer_(&this->data_); + return this->transfer_(this->data_); } void FingerprintGrowComponent::sensor_wakeup_() { @@ -517,7 +518,7 @@ void FingerprintGrowComponent::sensor_wakeup_() { std::vector<uint8_t> buffer = {VERIFY_PASSWORD, (uint8_t) (this->password_ >> 24), (uint8_t) (this->password_ >> 16), (uint8_t) (this->password_ >> 8), (uint8_t) (this->password_ & 0xFF)}; - if (this->transfer_(&buffer) != OK) { + if (this->transfer_(buffer) != OK) { ESP_LOGE(TAG, "Wrong password"); } } diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index 370b26f56a..db9d5ce564 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -169,7 +169,7 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic bool set_password_(); bool get_parameters_(); void get_fingerprint_count_(); - uint8_t transfer_(std::vector<uint8_t> *p_data_buffer); + uint8_t transfer_(std::vector<uint8_t> &data_buffer); uint8_t send_command_(); void sensor_wakeup_(); void sensor_sleep_(); @@ -190,7 +190,7 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic bool is_sensor_awake_ = false; uint32_t last_transfer_ms_ = 0; uint32_t last_aura_led_control_ = 0; - uint16_t last_aura_led_duration_ = 0; + uint32_t last_aura_led_duration_ = 0; uint16_t system_identifier_code_ = 0; uint32_t idle_period_to_sleep_ms_ = UINT32_MAX; sensor::Sensor *fingerprint_count_sensor_{nullptr}; From 22fc3aab392c8cad0c2d8a74e6074b83e7c17139 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 13:19:46 -0500 Subject: [PATCH 1098/2030] [ld2420] Fix buffer overflows in simple mode, energy mode, and calibration (#14458) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ld2420/ld2420.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index f14400d15a..1e671363c9 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -460,6 +460,10 @@ void LD2420Component::handle_energy_mode_(uint8_t *buffer, int len) { uint8_t index = 6; // Start at presence byte position uint16_t range; const uint8_t elements = sizeof(this->gate_energy_) / sizeof(this->gate_energy_[0]); + if (len < static_cast<int>(index + 1 + sizeof(range) + elements * sizeof(this->gate_energy_[0]))) { + ESP_LOGW(TAG, "Energy frame too short: %d bytes", len); + return; + } this->set_presence_(buffer[index]); index++; memcpy(&range, &buffer[index], sizeof(range)); @@ -471,8 +475,11 @@ void LD2420Component::handle_energy_mode_(uint8_t *buffer, int len) { } if (this->current_operating_mode == OP_CALIBRATE_MODE) { - this->update_radar_data(gate_energy_, sample_number_counter); - this->sample_number_counter > CALIBRATE_SAMPLES ? this->sample_number_counter = 0 : this->sample_number_counter++; + this->update_radar_data(gate_energy_, this->sample_number_counter); + this->sample_number_counter++; + if (this->sample_number_counter >= CALIBRATE_SAMPLES) { + this->sample_number_counter = 0; + } } // Resonable refresh rate for home assistant database size health @@ -503,22 +510,20 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) { char *endptr{nullptr}; char outbuf[bufsize]{0}; while (true) { - if (inbuf[pos - 2] == 'O' && inbuf[pos - 1] == 'F' && inbuf[pos] == 'F') { + if (pos >= 2 && inbuf[pos - 2] == 'O' && inbuf[pos - 1] == 'F' && inbuf[pos] == 'F') { this->set_presence_(false); - } else if (inbuf[pos - 1] == 'O' && inbuf[pos] == 'N') { + } else if (pos >= 1 && inbuf[pos - 1] == 'O' && inbuf[pos] == 'N') { this->set_presence_(true); } if (inbuf[pos] >= '0' && inbuf[pos] <= '9') { if (index < bufsize - 1) { outbuf[index++] = inbuf[pos]; - pos++; } + } + if (pos < len - 1) { + pos++; } else { - if (pos < len - 1) { - pos++; - } else { - break; - } + break; } } outbuf[index] = '\0'; From 4928e678d1f54ee261789ab283280f317b425357 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 4 Mar 2026 13:37:22 -0600 Subject: [PATCH 1099/2030] [mixer][resampler][speaker] Use core static task manager (#14454) --- .../mixer/speaker/mixer_speaker.cpp | 91 +++------------ .../components/mixer/speaker/mixer_speaker.h | 18 +-- .../resampler/speaker/resampler_speaker.cpp | 60 +--------- .../resampler/speaker/resampler_speaker.h | 19 +-- .../speaker/media_player/audio_pipeline.cpp | 110 ++++-------------- .../speaker/media_player/audio_pipeline.h | 13 +-- 6 files changed, 49 insertions(+), 262 deletions(-) diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 100acbebc3..8e1278206f 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -438,24 +438,14 @@ void MixerSpeaker::loop() { // Handle pending start request if (event_group_bits & MIXER_TASK_COMMAND_START) { // Only start the task if it's fully stopped and cleaned up - if (!this->status_has_error() && (this->task_handle_ == nullptr) && (this->task_stack_buffer_ == nullptr)) { - esp_err_t err = this->start_task_(); - switch (err) { - case ESP_OK: - xEventGroupClearBits(this->event_group_, MIXER_TASK_COMMAND_START); - break; - case ESP_ERR_NO_MEM: - ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); - this->status_momentary_error("memory-failure", 1000); - return; - case ESP_ERR_INVALID_STATE: - ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); - this->status_momentary_error("task-failure", 1000); - return; - default: - ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); - this->status_momentary_error("failure", 1000); - return; + if (!this->status_has_error() && !this->task_.is_created()) { + if (this->task_.create(audio_mixer_task, "mixer", TASK_STACK_SIZE, (void *) this, MIXER_TASK_PRIORITY, + this->task_stack_in_psram_)) { + xEventGroupClearBits(this->event_group_, MIXER_TASK_COMMAND_START); + } else { + ESP_LOGE(TAG, "Failed to start; retrying in 1 second"); + this->status_momentary_error("failure", 1000); + return; } } } @@ -478,13 +468,12 @@ void MixerSpeaker::loop() { xEventGroupClearBits(this->event_group_, MIXER_TASK_STATE_STOPPING); } if (event_group_bits & MIXER_TASK_STATE_STOPPED) { - if (this->delete_task_() == ESP_OK) { - ESP_LOGD(TAG, "Stopped"); - xEventGroupClearBits(this->event_group_, MIXER_TASK_ALL_BITS); - } + this->task_.deallocate(); + ESP_LOGD(TAG, "Stopped"); + xEventGroupClearBits(this->event_group_, MIXER_TASK_ALL_BITS); } - if (this->task_handle_ != nullptr) { + if (this->task_.is_created()) { // If the mixer task is running, check if all source speakers are stopped bool all_stopped = true; @@ -497,7 +486,7 @@ void MixerSpeaker::loop() { // Send stop command signal to the mixer task since no source speakers are active xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_STOP); } - } else if (this->task_stack_buffer_ == nullptr) { + } else { // Task is fully stopped and cleaned up, check if we can disable loop event_group_bits = xEventGroupGetBits(this->event_group_); if (event_group_bits == 0) { @@ -538,60 +527,6 @@ esp_err_t MixerSpeaker::start(audio::AudioStreamInfo &stream_info) { return ESP_OK; } -esp_err_t MixerSpeaker::start_task_() { - if (this->task_stack_buffer_ == nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE); - } - } - - if (this->task_stack_buffer_ == nullptr) { - return ESP_ERR_NO_MEM; - } - - if (this->task_handle_ == nullptr) { - this->task_handle_ = xTaskCreateStatic(audio_mixer_task, "mixer", TASK_STACK_SIZE, (void *) this, - MIXER_TASK_PRIORITY, this->task_stack_buffer_, &this->task_stack_); - } - - if (this->task_handle_ == nullptr) { - return ESP_ERR_INVALID_STATE; - } - - return ESP_OK; -} - -esp_err_t MixerSpeaker::delete_task_() { - if (this->task_handle_ != nullptr) { - // Delete the task - vTaskDelete(this->task_handle_); - this->task_handle_ = nullptr; - } - - if ((this->task_handle_ == nullptr) && (this->task_stack_buffer_ != nullptr)) { - // Deallocate the task stack buffer - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } - - this->task_stack_buffer_ = nullptr; - } - - if ((this->task_handle_ != nullptr) || (this->task_stack_buffer_ != nullptr)) { - return ESP_ERR_INVALID_STATE; - } - - return ESP_OK; -} - void MixerSpeaker::copy_frames(const int16_t *input_buffer, audio::AudioStreamInfo input_stream_info, int16_t *output_buffer, audio::AudioStreamInfo output_stream_info, uint32_t frames_to_transfer) { diff --git a/esphome/components/mixer/speaker/mixer_speaker.h b/esphome/components/mixer/speaker/mixer_speaker.h index e920f9895a..0e0b33c39b 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.h +++ b/esphome/components/mixer/speaker/mixer_speaker.h @@ -8,8 +8,8 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/static_task.h" -#include <freertos/FreeRTOS.h> #include <freertos/event_groups.h> #include <atomic> @@ -143,8 +143,6 @@ class MixerSpeaker : public Component { /// @param stream_info The calling source speaker's audio stream information /// @return ESP_ERR_NOT_SUPPORTED if the incoming stream is incompatible due to unsupported bits per sample /// ESP_ERR_INVALID_ARG if the incoming stream is incompatible to be mixed with the other input audio stream - /// ESP_ERR_NO_MEM if there isn't enough memory for the task's stack - /// ESP_ERR_INVALID_STATE if the task fails to start /// ESP_OK if the incoming stream is compatible and the mixer task starts esp_err_t start(audio::AudioStreamInfo &stream_info); @@ -188,16 +186,6 @@ class MixerSpeaker : public Component { static void audio_mixer_task(void *params); - /// @brief Starts the mixer task after allocating memory for the task stack. - /// @return ESP_ERR_NO_MEM if there isn't enough memory for the task's stack - /// ESP_ERR_INVALID_STATE if the task didn't start - /// ESP_OK if successful - esp_err_t start_task_(); - - /// @brief If the task is stopped, it sets the task handle to the nullptr and deallocates its stack - /// @return ESP_OK if the task was stopped, ESP_ERR_INVALID_STATE otherwise. - esp_err_t delete_task_(); - EventGroupHandle_t event_group_{nullptr}; FixedVector<SourceSpeaker *> source_speakers_; @@ -207,9 +195,7 @@ class MixerSpeaker : public Component { bool queue_mode_; bool task_stack_in_psram_{false}; - TaskHandle_t task_handle_{nullptr}; - StaticTask_t task_stack_; - StackType_t *task_stack_buffer_{nullptr}; + StaticTask task_; optional<audio::AudioStreamInfo> audio_stream_info_; diff --git a/esphome/components/resampler/speaker/resampler_speaker.cpp b/esphome/components/resampler/speaker/resampler_speaker.cpp index 74420f906a..1303bc459e 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.cpp +++ b/esphome/components/resampler/speaker/resampler_speaker.cpp @@ -147,7 +147,7 @@ void ResamplerSpeaker::loop() { xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::STATE_STOPPING); } if (event_group_bits & ResamplingEventGroupBits::STATE_STOPPED) { - this->delete_task_(); + this->task_.deallocate(); ESP_LOGD(TAG, "Stopped"); xEventGroupClearBits(this->event_group_, ResamplingEventGroupBits::ALL_BITS); } @@ -190,7 +190,7 @@ void ResamplerSpeaker::loop() { this->output_speaker_->stop(); } - if (this->output_speaker_->is_stopped() && (this->task_handle_ == nullptr)) { + if (this->output_speaker_->is_stopped() && !this->task_.is_created()) { // Only transition to stopped state once the output speaker and resampler task are fully stopped this->waiting_for_output_ = false; this->state_ = speaker::STATE_STOPPED; @@ -209,9 +209,6 @@ void ResamplerSpeaker::loop() { void ResamplerSpeaker::set_start_error_(esp_err_t err) { switch (err) { - case ESP_ERR_INVALID_STATE: - this->status_set_error(LOG_STR("Task failed to start")); - break; case ESP_ERR_NO_MEM: this->status_set_error(LOG_STR("Not enough memory")); break; @@ -267,36 +264,12 @@ esp_err_t ResamplerSpeaker::start_() { if (this->requires_resampling_()) { // Start the resampler task to handle converting sample rates - return this->start_task_(); - } - - return ESP_OK; -} - -esp_err_t ResamplerSpeaker::start_task_() { - if (this->task_stack_buffer_ == nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - this->task_stack_buffer_ = stack_allocator.allocate(TASK_STACK_SIZE); + if (!this->task_.create(resample_task, "resampler", TASK_STACK_SIZE, (void *) this, RESAMPLER_TASK_PRIORITY, + this->task_stack_in_psram_)) { + return ESP_ERR_NO_MEM; } } - if (this->task_stack_buffer_ == nullptr) { - return ESP_ERR_NO_MEM; - } - - if (this->task_handle_ == nullptr) { - this->task_handle_ = xTaskCreateStatic(resample_task, "resampler", TASK_STACK_SIZE, (void *) this, - RESAMPLER_TASK_PRIORITY, this->task_stack_buffer_, &this->task_stack_); - } - - if (this->task_handle_ == nullptr) { - return ESP_ERR_INVALID_STATE; - } - return ESP_OK; } @@ -305,33 +278,12 @@ void ResamplerSpeaker::stop() { this->send_command_(ResamplingEventGroupBits::CO void ResamplerSpeaker::enter_stopping_state_() { this->state_ = speaker::STATE_STOPPING; this->state_start_ms_ = App.get_loop_component_start_time(); - if (this->task_handle_ != nullptr) { + if (this->task_.is_created()) { xEventGroupSetBits(this->event_group_, ResamplingEventGroupBits::TASK_COMMAND_STOP); } this->output_speaker_->stop(); } -void ResamplerSpeaker::delete_task_() { - if (this->task_handle_ != nullptr) { - // Delete the suspended task - vTaskDelete(this->task_handle_); - this->task_handle_ = nullptr; - } - - if (this->task_stack_buffer_ != nullptr) { - // Deallocate the task stack buffer - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->task_stack_buffer_, TASK_STACK_SIZE); - } - - this->task_stack_buffer_ = nullptr; - } -} - void ResamplerSpeaker::finish() { this->send_command_(ResamplingEventGroupBits::COMMAND_FINISH); } bool ResamplerSpeaker::has_buffered_data() const { diff --git a/esphome/components/resampler/speaker/resampler_speaker.h b/esphome/components/resampler/speaker/resampler_speaker.h index c1ebd7e7b5..cdbc1c22db 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.h +++ b/esphome/components/resampler/speaker/resampler_speaker.h @@ -7,8 +7,8 @@ #include "esphome/components/speaker/speaker.h" #include "esphome/core/component.h" +#include "esphome/core/static_task.h" -#include <freertos/FreeRTOS.h> #include <freertos/event_groups.h> namespace esphome { @@ -57,15 +57,9 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { protected: /// @brief Starts the output speaker after setting the resampled stream info. If resampling is required, it starts the /// task. - /// @return ESP_OK if resampling is required - /// return value of start_task_() if resampling is required - esp_err_t start_(); - - /// @brief Starts the resampler task after allocating the task stack /// @return ESP_OK if successful, - /// ESP_ERR_NO_MEM if the task stack couldn't be allocated - /// ESP_ERR_INVALID_STATE if the task wasn't created - esp_err_t start_task_(); + /// ESP_ERR_NO_MEM if the resampler task couldn't be created + esp_err_t start_(); /// @brief Transitions to STATE_STOPPING, records the stopping timestamp, sends the task stop command if the task is /// running, and stops the output speaker. @@ -74,9 +68,6 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { /// @brief Sets the appropriate status error based on the start failure reason. void set_start_error_(esp_err_t err); - /// @brief Deletes the resampler task if suspended, deallocates the task stack, and resets the related pointers. - void delete_task_(); - /// @brief Sends a command via event group bits, enables the loop, and optionally wakes the main loop. void send_command_(uint32_t command_bit, bool wake_loop = false); @@ -92,9 +83,7 @@ class ResamplerSpeaker : public Component, public speaker::Speaker { bool task_stack_in_psram_{false}; bool waiting_for_output_{false}; - TaskHandle_t task_handle_{nullptr}; - StaticTask_t task_stack_; - StackType_t *task_stack_buffer_{nullptr}; + StaticTask task_; audio::AudioStreamInfo target_stream_info_; diff --git a/esphome/components/speaker/media_player/audio_pipeline.cpp b/esphome/components/speaker/media_player/audio_pipeline.cpp index 177743feb1..8cea3abcfc 100644 --- a/esphome/components/speaker/media_player/audio_pipeline.cpp +++ b/esphome/components/speaker/media_player/audio_pipeline.cpp @@ -87,20 +87,20 @@ void AudioPipeline::set_pause_state(bool pause_state) { } void AudioPipeline::suspend_tasks() { - if (this->read_task_handle_ != nullptr) { - vTaskSuspend(this->read_task_handle_); + if (this->read_task_.is_created()) { + vTaskSuspend(this->read_task_.get_handle()); } - if (this->decode_task_handle_ != nullptr) { - vTaskSuspend(this->decode_task_handle_); + if (this->decode_task_.is_created()) { + vTaskSuspend(this->decode_task_.get_handle()); } } void AudioPipeline::resume_tasks() { - if (this->read_task_handle_ != nullptr) { - vTaskResume(this->read_task_handle_); + if (this->read_task_.is_created()) { + vTaskResume(this->read_task_.get_handle()); } - if (this->decode_task_handle_ != nullptr) { - vTaskResume(this->decode_task_handle_); + if (this->decode_task_.is_created()) { + vTaskResume(this->decode_task_.get_handle()); } } @@ -159,7 +159,7 @@ AudioPipelineState AudioPipeline::process_state() { // Init command pending if (!(event_bits & EventGroupBits::PIPELINE_COMMAND_STOP)) { // Only start if there is no pending stop command - if ((this->read_task_handle_ == nullptr) || (this->decode_task_handle_ == nullptr)) { + if (!this->read_task_.is_created() || !this->decode_task_.is_created()) { // At least one task isn't running this->start_tasks_(); } @@ -202,8 +202,9 @@ AudioPipelineState AudioPipeline::process_state() { if (!this->is_playing_) { // The tasks have been stopped for two ``process_state`` calls in a row, so delete the tasks - if ((this->read_task_handle_ != nullptr) || (this->decode_task_handle_ != nullptr)) { - this->delete_tasks_(); + if (this->read_task_.is_created() || this->decode_task_.is_created()) { + this->read_task_.deallocate(); + this->decode_task_.deallocate(); if (this->hard_stop_) { // Stop command was sent, so immediately end the playback this->speaker_->stop(); @@ -234,7 +235,7 @@ AudioPipelineState AudioPipeline::process_state() { } } - if ((this->read_task_handle_ == nullptr) && (this->decode_task_handle_ == nullptr)) { + if (!this->read_task_.is_created() && !this->decode_task_.is_created()) { // No tasks are running, so the pipeline is stopped. xEventGroupClearBits(this->event_group_, EventGroupBits::PIPELINE_COMMAND_STOP); return AudioPipelineState::STOPPED; @@ -262,94 +263,25 @@ esp_err_t AudioPipeline::allocate_communications_() { } esp_err_t AudioPipeline::start_tasks_() { - if (this->read_task_handle_ == nullptr) { - if (this->read_task_stack_buffer_ == nullptr) { - // Reader task uses the AudioReader class which uses esp_http_client. This crashes on IDF 5.4 if the task stack is - // in PSRAM. As a workaround, always allocate the read task in internal memory. - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - this->read_task_stack_buffer_ = stack_allocator.allocate(READ_TASK_STACK_SIZE); - } - - if (this->read_task_stack_buffer_ == nullptr) { + if (!this->read_task_.is_created()) { + // Reader task uses the AudioReader class which uses esp_http_client. This crashes on IDF 5.4 if the task stack is + // in PSRAM. As a workaround, always allocate the read task in internal memory. + if (!this->read_task_.create(read_task, (this->base_name_ + "_read").c_str(), READ_TASK_STACK_SIZE, (void *) this, + this->priority_, false)) { return ESP_ERR_NO_MEM; } - - if (this->read_task_handle_ == nullptr) { - this->read_task_handle_ = - xTaskCreateStatic(read_task, (this->base_name_ + "_read").c_str(), READ_TASK_STACK_SIZE, (void *) this, - this->priority_, this->read_task_stack_buffer_, &this->read_task_stack_); - } - - if (this->read_task_handle_ == nullptr) { - return ESP_ERR_INVALID_STATE; - } } - if (this->decode_task_handle_ == nullptr) { - if (this->decode_task_stack_buffer_ == nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - this->decode_task_stack_buffer_ = stack_allocator.allocate(DECODE_TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - this->decode_task_stack_buffer_ = stack_allocator.allocate(DECODE_TASK_STACK_SIZE); - } - } - - if (this->decode_task_stack_buffer_ == nullptr) { + if (!this->decode_task_.is_created()) { + if (!this->decode_task_.create(decode_task, (this->base_name_ + "_decode").c_str(), DECODE_TASK_STACK_SIZE, + (void *) this, this->priority_, this->task_stack_in_psram_)) { return ESP_ERR_NO_MEM; } - - if (this->decode_task_handle_ == nullptr) { - this->decode_task_handle_ = - xTaskCreateStatic(decode_task, (this->base_name_ + "_decode").c_str(), DECODE_TASK_STACK_SIZE, (void *) this, - this->priority_, this->decode_task_stack_buffer_, &this->decode_task_stack_); - } - - if (this->decode_task_handle_ == nullptr) { - return ESP_ERR_INVALID_STATE; - } } return ESP_OK; } -void AudioPipeline::delete_tasks_() { - if (this->read_task_handle_ != nullptr) { - vTaskDelete(this->read_task_handle_); - - if (this->read_task_stack_buffer_ != nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->read_task_stack_buffer_, READ_TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->read_task_stack_buffer_, READ_TASK_STACK_SIZE); - } - - this->read_task_stack_buffer_ = nullptr; - this->read_task_handle_ = nullptr; - } - } - - if (this->decode_task_handle_ != nullptr) { - vTaskDelete(this->decode_task_handle_); - - if (this->decode_task_stack_buffer_ != nullptr) { - if (this->task_stack_in_psram_) { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_EXTERNAL); - stack_allocator.deallocate(this->decode_task_stack_buffer_, DECODE_TASK_STACK_SIZE); - } else { - RAMAllocator<StackType_t> stack_allocator(RAMAllocator<StackType_t>::ALLOC_INTERNAL); - stack_allocator.deallocate(this->decode_task_stack_buffer_, DECODE_TASK_STACK_SIZE); - } - - this->decode_task_stack_buffer_ = nullptr; - this->decode_task_handle_ = nullptr; - } - } -} - void AudioPipeline::read_task(void *params) { AudioPipeline *this_pipeline = (AudioPipeline *) params; diff --git a/esphome/components/speaker/media_player/audio_pipeline.h b/esphome/components/speaker/media_player/audio_pipeline.h index 6fffde6c20..2c78572835 100644 --- a/esphome/components/speaker/media_player/audio_pipeline.h +++ b/esphome/components/speaker/media_player/audio_pipeline.h @@ -8,10 +8,10 @@ #include "esphome/components/speaker/speaker.h" #include "esphome/core/ring_buffer.h" +#include "esphome/core/static_task.h" #include "esp_err.h" -#include <freertos/FreeRTOS.h> #include <freertos/event_groups.h> #include <freertos/queue.h> @@ -104,9 +104,6 @@ class AudioPipeline { /// @return ESP_OK if successful or an appropriate error if not esp_err_t start_tasks_(); - /// @brief Resets the task related pointers and deallocates their stacks. - void delete_tasks_(); - std::string base_name_; UBaseType_t priority_; @@ -143,15 +140,11 @@ class AudioPipeline { // Handles reading the media file from flash or a url static void read_task(void *params); - TaskHandle_t read_task_handle_{nullptr}; - StaticTask_t read_task_stack_; - StackType_t *read_task_stack_buffer_{nullptr}; + StaticTask read_task_; // Decodes the media file into PCM audio static void decode_task(void *params); - TaskHandle_t decode_task_handle_{nullptr}; - StaticTask_t decode_task_stack_; - StackType_t *decode_task_stack_buffer_{nullptr}; + StaticTask decode_task_; }; } // namespace speaker From 0c883b80c4376906eb5dc67f4b77d1249ee67b1d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:05:49 -0500 Subject: [PATCH 1100/2030] [inkplate][ezo_pmp][ezo][packet_transport] Fix use-after-free bugs (#14467) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ezo/ezo.cpp | 3 +- esphome/components/ezo_pmp/ezo_pmp.cpp | 36 ++++++++++--------- esphome/components/ezo_pmp/ezo_pmp.h | 2 +- esphome/components/inkplate/inkplate.cpp | 20 ++++++++--- .../packet_transport/packet_transport.cpp | 2 +- .../packet_transport/packet_transport.h | 2 +- 6 files changed, 39 insertions(+), 26 deletions(-) diff --git a/esphome/components/ezo/ezo.cpp b/esphome/components/ezo/ezo.cpp index e4036021df..2dc65b7d14 100644 --- a/esphome/components/ezo/ezo.cpp +++ b/esphome/components/ezo/ezo.cpp @@ -66,8 +66,9 @@ void EZOSensor::loop() { if (to_run->command_type == EzoCommandType::EZO_SLEEP || to_run->command_type == EzoCommandType::EZO_I2C) { // Commands with no return data + bool update_address = to_run->command_type == EzoCommandType::EZO_I2C; this->commands_.pop_front(); - if (to_run->command_type == EzoCommandType::EZO_I2C) + if (update_address) this->address_ = this->new_address_; return; } diff --git a/esphome/components/ezo_pmp/ezo_pmp.cpp b/esphome/components/ezo_pmp/ezo_pmp.cpp index bf6e3926b8..4ce4da57ff 100644 --- a/esphome/components/ezo_pmp/ezo_pmp.cpp +++ b/esphome/components/ezo_pmp/ezo_pmp.cpp @@ -165,22 +165,23 @@ void EzoPMP::read_command_result_() { continue; } - switch (current_parameter) { - case 1: - first_parameter_buffer[position_in_parameter_buffer] = current_char; - first_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; - break; - case 2: - second_parameter_buffer[position_in_parameter_buffer] = current_char; - second_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; - break; - case 3: - third_parameter_buffer[position_in_parameter_buffer] = current_char; - third_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; - break; + if (position_in_parameter_buffer < sizeof(first_parameter_buffer) - 1) { + switch (current_parameter) { + case 1: + first_parameter_buffer[position_in_parameter_buffer] = current_char; + first_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; + break; + case 2: + second_parameter_buffer[position_in_parameter_buffer] = current_char; + second_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; + break; + case 3: + third_parameter_buffer[position_in_parameter_buffer] = current_char; + third_parameter_buffer[position_in_parameter_buffer + 1] = '\0'; + break; + } + position_in_parameter_buffer++; } - - position_in_parameter_buffer++; } auto parsed_first_parameter = parse_number<float>(first_parameter_buffer); @@ -404,7 +405,8 @@ void EzoPMP::send_next_command_() { break; case EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS: // Run an arbitrary command - command_buffer_length = snprintf((char *) command_buffer, sizeof(command_buffer), "%s", this->arbitrary_command_); + command_buffer_length = + snprintf((char *) command_buffer, sizeof(command_buffer), "%s", this->arbitrary_command_.c_str()); ESP_LOGI(TAG, "Sending arbitrary command: %s", (char *) command_buffer); break; @@ -541,7 +543,7 @@ void EzoPMP::change_i2c_address(int address) { } void EzoPMP::exec_arbitrary_command(const std::basic_string<char> &command) { - this->arbitrary_command_ = command.c_str(); + this->arbitrary_command_ = command; this->queue_command_(EZO_PMP_COMMAND_EXEC_ARBITRARY_COMMAND_ADDRESS, 0, 0, true); } diff --git a/esphome/components/ezo_pmp/ezo_pmp.h b/esphome/components/ezo_pmp/ezo_pmp.h index d4917e7f4b..bbfd899170 100644 --- a/esphome/components/ezo_pmp/ezo_pmp.h +++ b/esphome/components/ezo_pmp/ezo_pmp.h @@ -85,7 +85,7 @@ class EzoPMP : public PollingComponent, public i2c::I2CDevice { bool is_paused_flag_ = false; bool is_dosing_flag_ = false; - const char *arbitrary_command_{nullptr}; + std::string arbitrary_command_{}; void send_next_command_(); void read_command_result_(); diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index c921c643fa..df9c2b29c7 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -63,16 +63,26 @@ void Inkplate::initialize_() { if (buffer_size == 0) return; - if (this->partial_buffer_ != nullptr) + if (this->partial_buffer_ != nullptr) { allocator.deallocate(this->partial_buffer_, buffer_size); - if (this->partial_buffer_2_ != nullptr) + this->partial_buffer_ = nullptr; + } + if (this->partial_buffer_2_ != nullptr) { allocator.deallocate(this->partial_buffer_2_, buffer_size * 2); - if (this->buffer_ != nullptr) + this->partial_buffer_2_ = nullptr; + } + if (this->buffer_ != nullptr) { allocator.deallocate(this->buffer_, buffer_size); - if (this->glut_ != nullptr) + this->buffer_ = nullptr; + } + if (this->glut_ != nullptr) { allocator32.deallocate(this->glut_, 256 * 9); - if (this->glut2_ != nullptr) + this->glut_ = nullptr; + } + if (this->glut2_ != nullptr) { allocator32.deallocate(this->glut2_, 256 * 9); + this->glut2_ = nullptr; + } this->buffer_ = allocator.allocate(buffer_size); if (this->buffer_ == nullptr) { diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index 7b7a852398..d2c5920001 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -249,7 +249,7 @@ void PacketTransport::init_data_() { } else { add(this->data_, DATA_KEY); } - for (auto pkey : this->ping_keys_) { + for (const auto &pkey : this->ping_keys_) { add(this->data_, PING_KEY); add(this->data_, pkey.second); } diff --git a/esphome/components/packet_transport/packet_transport.h b/esphome/components/packet_transport/packet_transport.h index 57f40874b5..a236744231 100644 --- a/esphome/components/packet_transport/packet_transport.h +++ b/esphome/components/packet_transport/packet_transport.h @@ -150,7 +150,7 @@ class PacketTransport : public PollingComponent { std::vector<uint8_t> ping_header_{}; std::vector<uint8_t> header_{}; std::vector<uint8_t> data_{}; - std::map<const char *, uint32_t> ping_keys_{}; + std::map<std::string, uint32_t> ping_keys_{}; const char *platform_name_{""}; void add_key_(const char *name, uint32_t key); void send_ping_pong_request_(); From e11a91411b800497b812a9baf374fca36af5e085 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 16:36:52 -0500 Subject: [PATCH 1101/2030] [esp32_improv][rf_bridge][esp32_ble_server][display][lvgl][pipsolar] Fix unsigned integer underflows (#14466) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/display/display.cpp | 3 +++ esphome/components/esp32_ble_server/ble_characteristic.cpp | 6 +++++- esphome/components/esp32_improv/esp32_improv_component.cpp | 2 ++ esphome/components/lvgl/lvgl_esphome.cpp | 2 +- esphome/components/pipsolar/pipsolar.cpp | 4 +++- esphome/components/rf_bridge/rf_bridge.cpp | 2 +- 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/esphome/components/display/display.cpp b/esphome/components/display/display.cpp index 2bd7d03600..f8569b6e7c 100644 --- a/esphome/components/display/display.cpp +++ b/esphome/components/display/display.cpp @@ -661,6 +661,9 @@ void Display::printf(int x, int y, BaseFont *font, const char *format, ...) { void Display::set_writer(display_writer_t &&writer) { this->writer_ = writer; } void Display::set_pages(std::vector<DisplayPage *> pages) { + if (pages.empty()) + return; + for (auto *page : pages) page->set_parent(this); diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index a1b1ff94bb..d4ccefd9b2 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -209,7 +209,11 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt esp_gatt_rsp_t response; if (param->read.is_long) { - if (this->value_.size() - this->value_read_offset_ < max_offset) { + if (this->value_read_offset_ >= this->value_.size()) { + response.attr_value.len = 0; + response.attr_value.offset = this->value_read_offset_; + this->value_read_offset_ = 0; + } else if (this->value_.size() - this->value_read_offset_ < max_offset) { // Last message in the chain response.attr_value.len = this->value_.size() - this->value_read_offset_; response.attr_value.offset = this->value_read_offset_; diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index 83bc842a3d..e4ae49f235 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -314,6 +314,8 @@ void ESP32ImprovComponent::dump_config() { } void ESP32ImprovComponent::process_incoming_data_() { + if (this->incoming_data_.size() < 3) + return; uint8_t length = this->incoming_data_[1]; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index bb373abb88..3e447e9169 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -421,7 +421,7 @@ void LvglComponent::write_random_() { col = col / this->draw_rounding * this->draw_rounding; auto row = random_uint32() % this->disp_drv_.ver_res; row = row / this->draw_rounding * this->draw_rounding; - auto size = (random_uint32() % 32) / this->draw_rounding * this->draw_rounding - 1; + auto size = ((random_uint32() % 32) / this->draw_rounding + 2) * this->draw_rounding - 1; lv_area_t area; area.x1 = col; area.y1 = row; diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index f95bf4aedb..9c5caec775 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -162,13 +162,15 @@ void Pipsolar::loop() { } uint8_t Pipsolar::check_incoming_length_(uint8_t length) { - if (this->read_pos_ - 3 == length) { + if (this->read_pos_ >= 3 && this->read_pos_ - 3 == length) { return 1; } return 0; } uint8_t Pipsolar::check_incoming_crc_() { + if (this->read_pos_ < 3) + return 0; uint16_t crc16; crc16 = this->pipsolar_crc_(read_buffer_, read_pos_ - 3); if (((uint8_t) ((crc16) >> 8)) == read_buffer_[read_pos_ - 3] && diff --git a/esphome/components/rf_bridge/rf_bridge.cpp b/esphome/components/rf_bridge/rf_bridge.cpp index d8c148145c..700e2ba162 100644 --- a/esphome/components/rf_bridge/rf_bridge.cpp +++ b/esphome/components/rf_bridge/rf_bridge.cpp @@ -74,7 +74,7 @@ bool RFBridgeComponent::parse_bridge_byte_(uint8_t byte) { data.length = raw[2]; data.protocol = raw[3]; char next_byte[3]; // 2 hex chars + null - for (uint8_t i = 0; i < data.length - 1; i++) { + for (uint8_t i = 0; i + 1 < data.length; i++) { buf_append_printf(next_byte, sizeof(next_byte), 0, "%02X", raw[4 + i]); data.code += next_byte; } From 61ea6c3b2f759c325c1428b371e4e9f8a00425fb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 12:46:26 -1000 Subject: [PATCH 1102/2030] [ci] Add missing issues: write permission to codeowner approval workflow (#14477) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/codeowner-approved-label.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeowner-approved-label.yml b/.github/workflows/codeowner-approved-label.yml index 217ae06419..200f18f544 100644 --- a/.github/workflows/codeowner-approved-label.yml +++ b/.github/workflows/codeowner-approved-label.yml @@ -12,7 +12,8 @@ on: types: [submitted, dismissed] permissions: - pull-requests: write + issues: write + pull-requests: read contents: read jobs: From 55103c0652bdece270ac09e9f3224c2693d7e2d2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 18:18:14 -0500 Subject: [PATCH 1103/2030] [ds2484] Fix read64() using uint8_t accumulator instead of uint64_t (#14479) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ds2484/ds2484.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ds2484/ds2484.cpp b/esphome/components/ds2484/ds2484.cpp index 7c890ff433..0b36f86874 100644 --- a/esphome/components/ds2484/ds2484.cpp +++ b/esphome/components/ds2484/ds2484.cpp @@ -110,9 +110,9 @@ uint8_t DS2484OneWireBus::read8() { } uint64_t DS2484OneWireBus::read64() { - uint8_t response = 0; + uint64_t response = 0; for (uint8_t i = 0; i < 8; i++) { - response |= (this->read8() << (i * 8)); + response |= (static_cast<uint64_t>(this->read8()) << (i * 8)); } return response; } From b6d7e8e14de939b4d6714a42138edb914fd346c4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 18:18:28 -0500 Subject: [PATCH 1104/2030] [sgp30] Fix serial number truncation from 48-bit to 24-bit (#14478) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/sgp30/sgp30.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/sgp30/sgp30.cpp b/esphome/components/sgp30/sgp30.cpp index 18814405d4..35e5b3dd42 100644 --- a/esphome/components/sgp30/sgp30.cpp +++ b/esphome/components/sgp30/sgp30.cpp @@ -41,7 +41,9 @@ void SGP30Component::setup() { this->mark_failed(); return; } - this->serial_number_ = encode_uint24(raw_serial_number[0], raw_serial_number[1], raw_serial_number[2]); + this->serial_number_ = (static_cast<uint64_t>(raw_serial_number[0]) << 32) | + (static_cast<uint64_t>(raw_serial_number[1]) << 16) | + static_cast<uint64_t>(raw_serial_number[2]); ESP_LOGD(TAG, "Serial number: %" PRIu64, this->serial_number_); // Featureset identification for future use From c8e7f78a2567e51d4fa178799ad3351ce046272d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 4 Mar 2026 18:32:50 -0500 Subject: [PATCH 1105/2030] [zwave_proxy] Fix uint8_t overflow for buffer index and frame end (#14480) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/zwave_proxy/zwave_proxy.cpp | 4 ++++ esphome/components/zwave_proxy/zwave_proxy.h | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index 8506b19e7f..b0836ac072 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -281,6 +281,10 @@ bool ZWaveProxy::parse_byte_(uint8_t byte) { break; } case ZWAVE_PARSING_STATE_READ_BL_MENU: + if (this->buffer_index_ >= this->buffer_.size()) { + this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START; + break; + } this->buffer_[this->buffer_index_++] = byte; if (!byte) { this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START; diff --git a/esphome/components/zwave_proxy/zwave_proxy.h b/esphome/components/zwave_proxy/zwave_proxy.h index eb26316f49..12cb9a90a1 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.h +++ b/esphome/components/zwave_proxy/zwave_proxy.h @@ -81,10 +81,10 @@ class ZWaveProxy : public uart::UARTDevice, public Component { api::APIConnection *api_connection_{nullptr}; // Current subscribed client uint32_t setup_time_{0}; // Time when setup() was called - // 8-bit values (grouped together to minimize padding) - uint8_t buffer_index_{0}; // Index for populating the data buffer - uint8_t end_frame_after_{0}; // Payload reception ends after this index - uint8_t last_response_{0}; // Last response type sent + // Small values (grouped by size to minimize padding) + uint16_t buffer_index_{0}; // Index for populating the data buffer + uint16_t end_frame_after_{0}; // Payload reception ends after this index + uint8_t last_response_{0}; // Last response type sent ZWaveParsingState parsing_state_{ZWAVE_PARSING_STATE_WAIT_START}; bool in_bootloader_{false}; // True if the device is detected to be in bootloader mode bool home_id_ready_{false}; // True when home ID has been received from Z-Wave module From c0143ac6d662967a8a3fbb008242ee4bc5f92a1f Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Wed, 4 Mar 2026 19:46:40 -0600 Subject: [PATCH 1106/2030] [ai] Add docs note about keeping component index pages in sync (#14465) Co-authored-by: Brandon Harvey <bharvey88@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- .ai/instructions.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.ai/instructions.md b/.ai/instructions.md index 3c24177827..240a47a52f 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -286,6 +286,7 @@ This document provides essential context for AI models interacting with this pro * **Documentation Contributions:** * Documentation is hosted in the separate `esphome/esphome-docs` repository. * The contribution workflow is the same as for the codebase. + * When editing a component's documentation page, also update the corresponding component index page to ensure both pages remain in sync. * **Best Practices:** * **Component Development:** Keep dependencies minimal, provide clear error messages, and write comprehensive docstrings and tests. From 5df4fd0a271251d0dc29e0b76148b50550cfb582 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 15:51:51 -1000 Subject: [PATCH 1107/2030] [tests] Fix flaky uart_mock integration tests (#14476) --- .../external_components/uart_mock/__init__.py | 5 + .../uart_mock/uart_mock.cpp | 37 +- .../external_components/uart_mock/uart_mock.h | 4 + .../fixtures/uart_mock_ld2410.yaml | 8 + .../uart_mock_ld2410_engineering.yaml | 8 + .../fixtures/uart_mock_ld2412.yaml | 8 + .../uart_mock_ld2412_engineering.yaml | 8 + .../fixtures/uart_mock_modbus.yaml | 8 + .../fixtures/uart_mock_modbus_timing.yaml | 8 + tests/integration/state_utils.py | 96 ++++- tests/integration/test_uart_mock_ld2410.py | 353 ++++++----------- tests/integration/test_uart_mock_ld2412.py | 362 ++++++------------ tests/integration/test_uart_mock_modbus.py | 14 +- 13 files changed, 420 insertions(+), 499 deletions(-) diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py index 8deab4c21e..abb3abcc41 100644 --- a/tests/integration/fixtures/external_components/uart_mock/__init__.py +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -43,6 +43,7 @@ CONF_INJECT_RX = "inject_rx" CONF_EXPECT_TX = "expect_tx" CONF_PERIODIC_RX = "periodic_rx" CONF_ON_TX = "on_tx" +CONF_AUTO_START = "auto_start" UART_PARITY_OPTIONS = { "NONE": uart.UARTParityOptions.UART_CONFIG_PARITY_NONE, @@ -95,6 +96,7 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_INJECTIONS, default=[]): cv.ensure_list(INJECTION_SCHEMA), cv.Optional(CONF_RESPONSES, default=[]): cv.ensure_list(RESPONSE_SCHEMA), cv.Optional(CONF_PERIODIC_RX, default=[]): cv.ensure_list(PERIODIC_RX_SCHEMA), + cv.Optional(CONF_AUTO_START, default=True): cv.boolean, cv.Optional(CONF_ON_TX): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MockUartTXTrigger), @@ -138,6 +140,9 @@ async def to_code(config): cg.add(var.set_data_bits(config[CONF_DATA_BITS])) cg.add(var.set_parity(config[CONF_PARITY])) + if not config[CONF_AUTO_START]: + cg.add(var.set_auto_start(False)) + for injection in config[CONF_INJECTIONS]: rx_data = injection[CONF_INJECT_RX] delay_ms = injection[CONF_DELAY] diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index a4a1c41234..83a13793be 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -16,17 +16,21 @@ void MockUartComponent::setup() { } void MockUartComponent::loop() { - uint32_t now = App.get_loop_component_start_time(); - - // Initialize scenario start time on first loop() call, after all components have - // finished setup(). This prevents injection delays from being consumed during setup. if (!this->loop_started_) { this->loop_started_ = true; - this->scenario_start_ms_ = now; - this->cumulative_delay_ms_ = 0; - ESP_LOGD(TAG, "Scenario started at %u ms", now); + if (this->auto_start_) { + this->start_scenario(); + } else { + ESP_LOGD(TAG, "Scenario waiting for manual start"); + } } + if (!this->scenario_active_) { + return; + } + + uint32_t now = App.get_loop_component_start_time(); + // Process at most ONE timed injection per loop iteration. // This ensures each injection is in a separate loop cycle, giving the consuming // component (e.g., LD2410) a chance to process each batch independently. @@ -50,6 +54,19 @@ void MockUartComponent::loop() { } } +void MockUartComponent::start_scenario() { + uint32_t now = App.get_loop_component_start_time(); + this->scenario_active_ = true; + this->scenario_start_ms_ = now; + this->cumulative_delay_ms_ = 0; + this->injection_index_ = 0; + this->tx_buffer_.clear(); + for (auto &periodic : this->periodic_rx_) { + periodic.last_inject_ms = now; + } + ESP_LOGD(TAG, "Scenario started at %u ms", now); +} + void MockUartComponent::dump_config() { ESP_LOGCONFIG(TAG, "Mock UART Component:\n" @@ -78,10 +95,12 @@ void MockUartComponent::write_array(const uint8_t *data, size_t len) { } #endif - this->try_match_response_(); + if (this->scenario_active_) { + this->try_match_response_(); + } // This directly calls a tx_hook (lambda) as an alternative to the simpler match_response mechanism. - if (this->tx_hook_) { + if (this->tx_hook_ && this->scenario_active_) { std::vector<uint8_t> buf(data, data + len); this->tx_hook_(buf); } diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index 5bbc3c1bf6..b721512f96 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -37,6 +37,8 @@ class MockUartComponent : public uart::UARTComponent, public Component { void add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx); void add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms); + void start_scenario(); + void set_auto_start(bool auto_start) { this->auto_start_ = auto_start; } void set_tx_hook(std::function<void(const std::vector<uint8_t> &)> &&cb) { this->tx_hook_ = std::move(cb); } void inject_to_rx_buffer(const std::vector<uint8_t> &data); void inject_to_rx_buffer(const uint8_t *data, size_t len); @@ -55,6 +57,8 @@ class MockUartComponent : public uart::UARTComponent, public Component { uint32_t scenario_start_ms_{0}; uint32_t cumulative_delay_ms_{0}; bool loop_started_{false}; + bool auto_start_{true}; + bool scenario_active_{false}; // TX-triggered responses struct Response { diff --git a/tests/integration/fixtures/uart_mock_ld2410.yaml b/tests/integration/fixtures/uart_mock_ld2410.yaml index 9a81468263..59838b0599 100644 --- a/tests/integration/fixtures/uart_mock_ld2410.yaml +++ b/tests/integration/fixtures/uart_mock_ld2410.yaml @@ -20,6 +20,7 @@ uart: uart_mock: id: mock_uart baud_rate: 256000 + auto_start: false injections: # Phase 1 (t=100ms): Valid LD2410 normal mode data frame - happy path # The buffer is clean at this point, so this frame should parse correctly. @@ -143,3 +144,10 @@ binary_sensor: name: "Has Moving Target" has_still_target: name: "Has Still Target" + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml index 3b730fc1f8..4625ae8511 100644 --- a/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml +++ b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml @@ -19,6 +19,7 @@ uart: uart_mock: id: mock_uart baud_rate: 256000 + auto_start: false injections: # Phase 1 (t=100ms): Valid LD2410 engineering mode data frame # Captured from a real Screek Human Presence Sensor 1U with LD2410 firmware 2.4.x @@ -154,3 +155,10 @@ binary_sensor: name: "Has Still Target" out_pin_presence_status: name: "Out Pin Presence" + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/fixtures/uart_mock_ld2412.yaml b/tests/integration/fixtures/uart_mock_ld2412.yaml index a502f36a25..9cf9d6bb87 100644 --- a/tests/integration/fixtures/uart_mock_ld2412.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412.yaml @@ -20,6 +20,7 @@ uart: uart_mock: id: mock_uart baud_rate: 256000 + auto_start: false injections: # Phase 1 (t=100ms): Valid LD2412 normal mode data frame - happy path # The buffer is clean at this point, so this frame should parse correctly. @@ -169,3 +170,10 @@ binary_sensor: name: "Has Still Target" filters: - settle: 50ms + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml index 3c669fc9a9..103dbed132 100644 --- a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml @@ -19,6 +19,7 @@ uart: uart_mock: id: mock_uart baud_rate: 256000 + auto_start: false injections: # Phase 1 (t=100ms): Valid LD2412 engineering mode data frame # @@ -211,3 +212,10 @@ binary_sensor: name: "Has Still Target" filters: - settle: 50ms + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/fixtures/uart_mock_modbus.yaml b/tests/integration/fixtures/uart_mock_modbus.yaml index 89b9b91861..0a3492a0d2 100644 --- a/tests/integration/fixtures/uart_mock_modbus.yaml +++ b/tests/integration/fixtures/uart_mock_modbus.yaml @@ -22,6 +22,7 @@ uart_mock: baud_rate: 9600 rx_full_threshold: 120 rx_timeout: 2 + auto_start: false debug: responses: - expect_tx: [0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A] # Read holding register 1 on device 1 @@ -38,3 +39,10 @@ sensor: name: "basic_register" address: 0x03 register_type: holding + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(virtual_uart_dev).start_scenario();' diff --git a/tests/integration/fixtures/uart_mock_modbus_timing.yaml b/tests/integration/fixtures/uart_mock_modbus_timing.yaml index cd485ca394..c4e29e5fe8 100644 --- a/tests/integration/fixtures/uart_mock_modbus_timing.yaml +++ b/tests/integration/fixtures/uart_mock_modbus_timing.yaml @@ -22,6 +22,7 @@ uart_mock: baud_rate: 9600 rx_full_threshold: 120 rx_timeout: 2 + auto_start: false debug: on_tx: - then: @@ -52,3 +53,10 @@ sensor: phase_a: voltage: name: sdm_voltage + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(virtual_uart_dev).start_scenario();' diff --git a/tests/integration/state_utils.py b/tests/integration/state_utils.py index b649056f2b..e8c2cc5e66 100644 --- a/tests/integration/state_utils.py +++ b/tests/integration/state_utils.py @@ -3,10 +3,17 @@ from __future__ import annotations import asyncio +from collections.abc import Callable import logging from typing import TypeVar -from aioesphomeapi import ButtonInfo, EntityInfo, EntityState +from aioesphomeapi import ( + BinarySensorState, + ButtonInfo, + EntityInfo, + EntityState, + SensorState, +) _LOGGER = logging.getLogger(__name__) @@ -234,3 +241,90 @@ class InitialStateHelper: asyncio.TimeoutError: If initial states aren't received within timeout """ await asyncio.wait_for(self._initial_states_received, timeout=timeout) + + +class SensorStateCollector: + """Collects sensor and binary sensor state updates and provides wait helpers. + + Usage: + collector = SensorStateCollector( + sensor_names=["moving_distance", "still_distance"], + binary_sensor_names=["has_target"], + ) + # Use collector.on_state as the callback (or wrap it) + client.subscribe_states(helper.on_state_wrapper(collector.on_state)) + + # Wait for all sensors to have at least one value + await collector.wait_for_all(timeout=3.0) + + # Access collected states + assert collector.sensor_states["moving_distance"][0] == approx(100.0) + """ + + def __init__( + self, + sensor_names: list[str], + binary_sensor_names: list[str] | None = None, + entities: list[EntityInfo] | None = None, + ) -> None: + self.sensor_states: dict[str, list[float]] = {name: [] for name in sensor_names} + self.binary_states: dict[str, list[bool]] = { + name: [] for name in (binary_sensor_names or []) + } + self._key_to_sensor: dict[int, str] = {} + self._waiters: list[tuple[Callable[[], bool], asyncio.Future[bool]]] = [] + + if entities is not None: + self.build_key_mapping(entities) + + def build_key_mapping(self, entities: list[EntityInfo]) -> None: + """Build key-to-name mapping from entities. Sorted by descending length.""" + all_names = list(self.sensor_states.keys()) + list(self.binary_states.keys()) + all_names.sort(key=len, reverse=True) + self._key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + def on_state(self, state: EntityState) -> None: + """Process a state update.""" + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = self._key_to_sensor.get(state.key) + if sensor_name and sensor_name in self.sensor_states: + self.sensor_states[sensor_name].append(state.state) + self._check_waiters() + elif isinstance(state, BinarySensorState): + sensor_name = self._key_to_sensor.get(state.key) + if sensor_name and sensor_name in self.binary_states: + self.binary_states[sensor_name].append(state.state) + self._check_waiters() + + def _check_waiters(self) -> None: + """Check all pending waiters and resolve any whose condition is met.""" + for condition, future in self._waiters: + if not future.done() and condition(): + future.set_result(True) + + def _all_have_values(self) -> bool: + """Check if all sensor and binary sensor lists have at least one value.""" + return all(len(v) >= 1 for v in self.sensor_states.values()) and all( + len(v) >= 1 for v in self.binary_states.values() + ) + + async def wait_for_all(self, timeout: float = 3.0) -> None: + """Wait until all sensors and binary sensors have at least one value.""" + if self._all_have_values(): + return + future: asyncio.Future[bool] = asyncio.get_running_loop().create_future() + self._waiters.append((self._all_have_values, future)) + await asyncio.wait_for(future, timeout=timeout) + + def add_waiter(self, condition: Callable[[], bool]) -> asyncio.Future[bool]: + """Add a custom waiter that resolves when condition returns True. + + Returns: + A future that resolves when the condition is met. + """ + future: asyncio.Future[bool] = asyncio.get_running_loop().create_future() + if condition(): + future.set_result(True) + else: + self._waiters.append((condition, future)) + return future diff --git a/tests/integration/test_uart_mock_ld2410.py b/tests/integration/test_uart_mock_ld2410.py index e01d6ff8e8..ce0e1bb7ec 100644 --- a/tests/integration/test_uart_mock_ld2410.py +++ b/tests/integration/test_uart_mock_ld2410.py @@ -21,16 +21,10 @@ from __future__ import annotations import asyncio from pathlib import Path -from aioesphomeapi import ( - BinarySensorInfo, - BinarySensorState, - EntityState, - SensorInfo, - SensorState, -) +from aioesphomeapi import ButtonInfo import pytest -from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity +from .state_utils import InitialStateHelper, SensorStateCollector, find_entity from .types import APIClientConnectedFactory, RunCompiledFunction @@ -64,100 +58,65 @@ async def test_uart_mock_ld2410( if "uart_mock" in line and "TX " in line: tx_log_lines.append(line) - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "moving_distance": [], - "still_distance": [], - "moving_energy": [], - "still_energy": [], - "detection_distance": [], - } - binary_states: dict[str, list[bool]] = { - "has_target": [], - "has_moving_target": [], - "has_still_target": [], - } + collector = SensorStateCollector( + sensor_names=[ + "moving_distance", + "still_distance", + "moving_energy", + "still_energy", + "detection_distance", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + ], + ) # Signal when we see recovery frame values - recovery_received = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - # Check if this is the recovery frame (moving_distance = 50) - if ( - sensor_name == "moving_distance" - and state.state == pytest.approx(50.0) - and not recovery_received.done() - ): - recovery_received.set_result(True) - elif isinstance(state, BinarySensorState): - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in binary_states: - binary_states[sensor_name].append(state.state) + recovery_received = collector.add_waiter( + lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + ) async with ( run_compiled(yaml_config, line_callback=line_callback), api_client_connected() as client, ): entities, _ = await client.list_entities_services() - - # Build key mappings for all sensor types - all_names = list(sensor_states.keys()) + list(binary_states.keys()) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) + collector.build_key_mapping(entities) # Set up initial state helper initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) try: await initial_state_helper.wait_for_initial_states() except TimeoutError: pytest.fail("Timeout waiting for initial states") - # Phase 1 values are in the initial states (swallowed by InitialStateHelper). - # Verify them via initial_states dict. - moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) - assert moving_dist_entity is not None - initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) - assert initial_moving is not None and isinstance(initial_moving, SensorState) - assert initial_moving.state == pytest.approx(100.0), ( - f"Initial moving distance should be 100, got {initial_moving.state}" - ) + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) - still_dist_entity = find_entity(entities, "still_distance", SensorInfo) - assert still_dist_entity is not None - initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) - assert initial_still is not None and isinstance(initial_still, SensorState) - assert initial_still.state == pytest.approx(120.0), ( - f"Initial still distance should be 120, got {initial_still.state}" - ) + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) - moving_energy_entity = find_entity(entities, "moving_energy", SensorInfo) - assert moving_energy_entity is not None - initial_me = initial_state_helper.initial_states.get(moving_energy_entity.key) - assert initial_me is not None and isinstance(initial_me, SensorState) - assert initial_me.state == pytest.approx(50.0), ( - f"Initial moving energy should be 50, got {initial_me.state}" - ) - - still_energy_entity = find_entity(entities, "still_energy", SensorInfo) - assert still_energy_entity is not None - initial_se = initial_state_helper.initial_states.get(still_energy_entity.key) - assert initial_se is not None and isinstance(initial_se, SensorState) - assert initial_se.state == pytest.approx(25.0), ( - f"Initial still energy should be 25, got {initial_se.state}" - ) - - detect_dist_entity = find_entity(entities, "detection_distance", SensorInfo) - assert detect_dist_entity is not None - initial_dd = initial_state_helper.initial_states.get(detect_dist_entity.key) - assert initial_dd is not None and isinstance(initial_dd, SensorState) - assert initial_dd.state == pytest.approx(300.0), ( - f"Initial detection distance should be 300, got {initial_dd.state}" - ) + # Phase 1 values: moving=100, still=120, energy=50/25, detect=300 + assert collector.sensor_states["moving_distance"][0] == pytest.approx(100.0) + assert collector.sensor_states["still_distance"][0] == pytest.approx(120.0) + assert collector.sensor_states["moving_energy"][0] == pytest.approx(50.0) + assert collector.sensor_states["still_energy"][0] == pytest.approx(25.0) + assert collector.sensor_states["detection_distance"][0] == pytest.approx(300.0) # Wait for the recovery frame (Phase 5) to be parsed # This proves the component survived garbage + truncated + overflow @@ -165,12 +124,8 @@ async def test_uart_mock_ld2410( await asyncio.wait_for(recovery_received, timeout=15.0) except TimeoutError: pytest.fail( - f"Timeout waiting for recovery frame. Received sensor states:\n" - f" moving_distance: {sensor_states['moving_distance']}\n" - f" still_distance: {sensor_states['still_distance']}\n" - f" moving_energy: {sensor_states['moving_energy']}\n" - f" still_energy: {sensor_states['still_energy']}\n" - f" detection_distance: {sensor_states['detection_distance']}" + f"Timeout waiting for recovery frame. Received:\n" + f" sensor_states: {collector.sensor_states}" ) # Verify overflow warning was logged @@ -183,67 +138,36 @@ async def test_uart_mock_ld2410( # A5 (MAC), AB (distance res), AE (light), 61 (params), FE (config off) assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" tx_data = " ".join(tx_log_lines) - # Verify command frame header appears (FD:FC:FB:FA) assert "FD:FC:FB:FA" in tx_data, ( "Expected LD2410 command frame header FD:FC:FB:FA in TX log" ) - # Verify command frame footer appears (04:03:02:01) assert "04:03:02:01" in tx_data, ( "Expected LD2410 command frame footer 04:03:02:01 in TX log" ) - # Recovery frame values (Phase 5, after overflow) - assert len(sensor_states["moving_distance"]) >= 1, ( - f"Expected recovery moving_distance, got: {sensor_states['moving_distance']}" - ) - # Find the recovery value (moving_distance = 50) - recovery_values = [ - v for v in sensor_states["moving_distance"] if v == pytest.approx(50.0) - ] - assert len(recovery_values) >= 1, ( - f"Expected moving_distance=50 in recovery, got: {sensor_states['moving_distance']}" - ) - # Recovery frame: moving=50, still=75, energy=100/80, detect=127 recovery_idx = next( i - for i, v in enumerate(sensor_states["moving_distance"]) + for i, v in enumerate(collector.sensor_states["moving_distance"]) if v == pytest.approx(50.0) ) - assert sensor_states["still_distance"][recovery_idx] == pytest.approx(75.0), ( - f"Recovery still distance should be 75, got {sensor_states['still_distance'][recovery_idx]}" + assert collector.sensor_states["still_distance"][recovery_idx] == pytest.approx( + 75.0 ) - assert sensor_states["moving_energy"][recovery_idx] == pytest.approx(100.0), ( - f"Recovery moving energy should be 100, got {sensor_states['moving_energy'][recovery_idx]}" + assert collector.sensor_states["moving_energy"][recovery_idx] == pytest.approx( + 100.0 ) - assert sensor_states["still_energy"][recovery_idx] == pytest.approx(80.0), ( - f"Recovery still energy should be 80, got {sensor_states['still_energy'][recovery_idx]}" - ) - assert sensor_states["detection_distance"][recovery_idx] == pytest.approx( - 127.0 - ), ( - f"Recovery detection distance should be 127, got {sensor_states['detection_distance'][recovery_idx]}" + assert collector.sensor_states["still_energy"][recovery_idx] == pytest.approx( + 80.0 ) + assert collector.sensor_states["detection_distance"][ + recovery_idx + ] == pytest.approx(127.0) - # Verify binary sensors detected targets - # Binary sensors could be in initial states or forwarded states - has_target_entity = find_entity(entities, "has_target", BinarySensorInfo) - assert has_target_entity is not None - initial_ht = initial_state_helper.initial_states.get(has_target_entity.key) - assert initial_ht is not None and isinstance(initial_ht, BinarySensorState) - assert initial_ht.state is True, "Has target should be True" - - has_moving_entity = find_entity(entities, "has_moving_target", BinarySensorInfo) - assert has_moving_entity is not None - initial_hm = initial_state_helper.initial_states.get(has_moving_entity.key) - assert initial_hm is not None and isinstance(initial_hm, BinarySensorState) - assert initial_hm.state is True, "Has moving target should be True" - - has_still_entity = find_entity(entities, "has_still_target", BinarySensorInfo) - assert has_still_entity is not None - initial_hs = initial_state_helper.initial_states.get(has_still_entity.key) - assert initial_hs is not None and isinstance(initial_hs, BinarySensorState) - assert initial_hs.state is True, "Has still target should be True" + # Verify binary sensors detected targets (from Phase 1 frame) + assert collector.binary_states["has_target"][0] is True + assert collector.binary_states["has_moving_target"][0] is True + assert collector.binary_states["has_still_target"][0] is True @pytest.mark.asyncio @@ -260,133 +184,82 @@ async def test_uart_mock_ld2410_engineering( "EXTERNAL_COMPONENT_PATH", external_components_path ) - loop = asyncio.get_running_loop() + collector = SensorStateCollector( + sensor_names=[ + "moving_distance", + "still_distance", + "moving_energy", + "still_energy", + "detection_distance", + "light", + "gate_0_move_energy", + "gate_1_move_energy", + "gate_2_move_energy", + "gate_0_still_energy", + "gate_1_still_energy", + "gate_2_still_energy", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + "out_pin_presence", + ], + ) - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "moving_distance": [], - "still_distance": [], - "moving_energy": [], - "still_energy": [], - "detection_distance": [], - "light": [], - "gate_0_move_energy": [], - "gate_1_move_energy": [], - "gate_2_move_energy": [], - "gate_0_still_energy": [], - "gate_1_still_energy": [], - "gate_2_still_energy": [], - } - binary_states: dict[str, list[bool]] = { - "has_target": [], - "has_moving_target": [], - "has_still_target": [], - "out_pin_presence": [], - } - - # Signal when we see Phase 3 frame (still_distance = 291) - phase3_received = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - if ( - sensor_name == "still_distance" - and state.state == pytest.approx(291.0) - and not phase3_received.done() - ): - phase3_received.set_result(True) - elif isinstance(state, BinarySensorState): - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in binary_states: - binary_states[sensor_name].append(state.state) + # Signal when we see Phase 3 frame values + phase3_received = collector.add_waiter( + lambda: pytest.approx(291.0) in collector.sensor_states["still_distance"] + ) async with ( run_compiled(yaml_config), api_client_connected() as client, ): entities, _ = await client.list_entities_services() - - all_names = list(sensor_states.keys()) + list(binary_states.keys()) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) + collector.build_key_mapping(entities) initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) try: await initial_state_helper.wait_for_initial_states() except TimeoutError: pytest.fail("Timeout waiting for initial states") - # Phase 1 initial values (engineering mode frame): + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) + + # Phase 1 values (engineering mode frame): # moving=30, energy=100, still=30, energy=100, detect=0 - moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) - assert moving_dist_entity is not None - initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) - assert initial_moving is not None and isinstance(initial_moving, SensorState) - assert initial_moving.state == pytest.approx(30.0), ( - f"Initial moving distance should be 30, got {initial_moving.state}" - ) - - still_dist_entity = find_entity(entities, "still_distance", SensorInfo) - assert still_dist_entity is not None - initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) - assert initial_still is not None and isinstance(initial_still, SensorState) - assert initial_still.state == pytest.approx(30.0), ( - f"Initial still distance should be 30, got {initial_still.state}" - ) - - # Verify engineering mode sensors from initial state - # Gate 0 moving energy = 0x64 = 100 - gate0_move_entity = find_entity(entities, "gate_0_move_energy", SensorInfo) - assert gate0_move_entity is not None - initial_g0m = initial_state_helper.initial_states.get(gate0_move_entity.key) - assert initial_g0m is not None and isinstance(initial_g0m, SensorState) - assert initial_g0m.state == pytest.approx(100.0), ( - f"Gate 0 move energy should be 100, got {initial_g0m.state}" - ) - - # Gate 1 moving energy = 0x41 = 65 - gate1_move_entity = find_entity(entities, "gate_1_move_energy", SensorInfo) - assert gate1_move_entity is not None - initial_g1m = initial_state_helper.initial_states.get(gate1_move_entity.key) - assert initial_g1m is not None and isinstance(initial_g1m, SensorState) - assert initial_g1m.state == pytest.approx(65.0), ( - f"Gate 1 move energy should be 65, got {initial_g1m.state}" - ) - - # Light sensor = 0x57 = 87 - light_entity = find_entity(entities, "light", SensorInfo) - assert light_entity is not None - initial_light = initial_state_helper.initial_states.get(light_entity.key) - assert initial_light is not None and isinstance(initial_light, SensorState) - assert initial_light.state == pytest.approx(87.0), ( - f"Light sensor should be 87, got {initial_light.state}" - ) - - # Out pin presence = 0x01 = True - out_pin_entity = find_entity(entities, "out_pin_presence", BinarySensorInfo) - assert out_pin_entity is not None - initial_out = initial_state_helper.initial_states.get(out_pin_entity.key) - assert initial_out is not None and isinstance(initial_out, BinarySensorState) - assert initial_out.state is True, "Out pin presence should be True" + assert collector.sensor_states["moving_distance"][0] == pytest.approx(30.0) + assert collector.sensor_states["still_distance"][0] == pytest.approx(30.0) + assert collector.sensor_states["gate_0_move_energy"][0] == pytest.approx(100.0) + assert collector.sensor_states["gate_1_move_energy"][0] == pytest.approx(65.0) + assert collector.sensor_states["light"][0] == pytest.approx(87.0) + assert collector.binary_states["out_pin_presence"][0] is True # Wait for Phase 3 frame (still_distance = 291cm, multi-byte) try: await asyncio.wait_for(phase3_received, timeout=15.0) except TimeoutError: pytest.fail( - f"Timeout waiting for Phase 3 frame. Received sensor states:\n" - f" still_distance: {sensor_states['still_distance']}\n" - f" moving_distance: {sensor_states['moving_distance']}" + f"Timeout waiting for Phase 3 frame. Received:\n" + f" still_distance: {collector.sensor_states['still_distance']}" ) - # Phase 3: still distance = 0x0123 = 291cm (multi-byte distance test) - phase3_still = [ - v for v in sensor_states["still_distance"] if v == pytest.approx(291.0) - ] - assert len(phase3_still) >= 1, ( - f"Expected still_distance=291, got: {sensor_states['still_distance']}" - ) + assert pytest.approx(291.0) in collector.sensor_states["still_distance"] diff --git a/tests/integration/test_uart_mock_ld2412.py b/tests/integration/test_uart_mock_ld2412.py index cf7324ceed..a964ba0073 100644 --- a/tests/integration/test_uart_mock_ld2412.py +++ b/tests/integration/test_uart_mock_ld2412.py @@ -21,16 +21,10 @@ from __future__ import annotations import asyncio from pathlib import Path -from aioesphomeapi import ( - BinarySensorInfo, - BinarySensorState, - EntityState, - SensorInfo, - SensorState, -) +from aioesphomeapi import ButtonInfo import pytest -from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity +from .state_utils import InitialStateHelper, SensorStateCollector, find_entity from .types import APIClientConnectedFactory, RunCompiledFunction @@ -64,104 +58,65 @@ async def test_uart_mock_ld2412( if "uart_mock" in line and "TX " in line: tx_log_lines.append(line) - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "moving_distance": [], - "still_distance": [], - "moving_energy": [], - "still_energy": [], - "detection_distance": [], - } - binary_states: dict[str, list[bool]] = { - "has_target": [], - "has_moving_target": [], - "has_still_target": [], - } + collector = SensorStateCollector( + sensor_names=[ + "moving_distance", + "still_distance", + "moving_energy", + "still_energy", + "detection_distance", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + ], + ) # Signal when we see recovery frame values - recovery_received = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - # Check if this is the recovery frame (moving_distance = 50) - if ( - sensor_name == "moving_distance" - and state.state == pytest.approx(50.0) - and not recovery_received.done() - ): - recovery_received.set_result(True) - elif isinstance(state, BinarySensorState): - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in binary_states: - binary_states[sensor_name].append(state.state) + recovery_received = collector.add_waiter( + lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + ) async with ( run_compiled(yaml_config, line_callback=line_callback), api_client_connected() as client, ): entities, _ = await client.list_entities_services() - - # Build key mappings for all sensor types - all_names = list(sensor_states.keys()) + list(binary_states.keys()) - # Sort by descending length to avoid substring collisions - # (e.g., "still_energy" matching "gate_0_still_energy") - all_names.sort(key=len, reverse=True) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) + collector.build_key_mapping(entities) # Set up initial state helper initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) try: await initial_state_helper.wait_for_initial_states() except TimeoutError: pytest.fail("Timeout waiting for initial states") - # Phase 1 values are in the initial states (swallowed by InitialStateHelper). - # Verify them via initial_states dict. - moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) - assert moving_dist_entity is not None - initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) - assert initial_moving is not None and isinstance(initial_moving, SensorState) - assert initial_moving.state == pytest.approx(100.0), ( - f"Initial moving distance should be 100, got {initial_moving.state}" - ) + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) - still_dist_entity = find_entity(entities, "still_distance", SensorInfo) - assert still_dist_entity is not None - initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) - assert initial_still is not None and isinstance(initial_still, SensorState) - assert initial_still.state == pytest.approx(120.0), ( - f"Initial still distance should be 120, got {initial_still.state}" - ) + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) - moving_energy_entity = find_entity(entities, "moving_energy", SensorInfo) - assert moving_energy_entity is not None - initial_me = initial_state_helper.initial_states.get(moving_energy_entity.key) - assert initial_me is not None and isinstance(initial_me, SensorState) - assert initial_me.state == pytest.approx(50.0), ( - f"Initial moving energy should be 50, got {initial_me.state}" - ) - - still_energy_entity = find_entity(entities, "still_energy", SensorInfo) - assert still_energy_entity is not None - initial_se = initial_state_helper.initial_states.get(still_energy_entity.key) - assert initial_se is not None and isinstance(initial_se, SensorState) - assert initial_se.state == pytest.approx(25.0), ( - f"Initial still energy should be 25, got {initial_se.state}" - ) - - # LD2412 detection_distance = moving_distance when MOVE_BITMASK is set - detect_dist_entity = find_entity(entities, "detection_distance", SensorInfo) - assert detect_dist_entity is not None - initial_dd = initial_state_helper.initial_states.get(detect_dist_entity.key) - assert initial_dd is not None and isinstance(initial_dd, SensorState) - assert initial_dd.state == pytest.approx(100.0), ( - f"Initial detection distance should be 100, got {initial_dd.state}" - ) + # Phase 1 values: moving=100, still=120, energy=50/25, detect=100 + assert collector.sensor_states["moving_distance"][0] == pytest.approx(100.0) + assert collector.sensor_states["still_distance"][0] == pytest.approx(120.0) + assert collector.sensor_states["moving_energy"][0] == pytest.approx(50.0) + assert collector.sensor_states["still_energy"][0] == pytest.approx(25.0) + assert collector.sensor_states["detection_distance"][0] == pytest.approx(100.0) # Wait for the recovery frame (Phase 5) to be parsed # This proves the component survived garbage + truncated + overflow @@ -169,12 +124,8 @@ async def test_uart_mock_ld2412( await asyncio.wait_for(recovery_received, timeout=3.0) except TimeoutError: pytest.fail( - f"Timeout waiting for recovery frame. Received sensor states:\n" - f" moving_distance: {sensor_states['moving_distance']}\n" - f" still_distance: {sensor_states['still_distance']}\n" - f" moving_energy: {sensor_states['moving_energy']}\n" - f" still_energy: {sensor_states['still_energy']}\n" - f" detection_distance: {sensor_states['detection_distance']}" + f"Timeout waiting for recovery frame. Received:\n" + f" sensor_states: {collector.sensor_states}" ) # Verify overflow warning was logged @@ -185,67 +136,36 @@ async def test_uart_mock_ld2412( # Verify LD2412 sent setup commands (TX logging) assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" tx_data = " ".join(tx_log_lines) - # Verify command frame header appears (FD:FC:FB:FA) assert "FD:FC:FB:FA" in tx_data, ( "Expected LD2412 command frame header FD:FC:FB:FA in TX log" ) - # Verify command frame footer appears (04:03:02:01) assert "04:03:02:01" in tx_data, ( "Expected LD2412 command frame footer 04:03:02:01 in TX log" ) - # Recovery frame values (Phase 5, after overflow) - assert len(sensor_states["moving_distance"]) >= 1, ( - f"Expected recovery moving_distance, got: {sensor_states['moving_distance']}" - ) - # Find the recovery value (moving_distance = 50) - recovery_values = [ - v for v in sensor_states["moving_distance"] if v == pytest.approx(50.0) - ] - assert len(recovery_values) >= 1, ( - f"Expected moving_distance=50 in recovery, got: {sensor_states['moving_distance']}" - ) - # Recovery frame: moving=50, still=75, energy=100/80, detect=50 recovery_idx = next( i - for i, v in enumerate(sensor_states["moving_distance"]) + for i, v in enumerate(collector.sensor_states["moving_distance"]) if v == pytest.approx(50.0) ) - assert sensor_states["still_distance"][recovery_idx] == pytest.approx(75.0), ( - f"Recovery still distance should be 75, got {sensor_states['still_distance'][recovery_idx]}" + assert collector.sensor_states["still_distance"][recovery_idx] == pytest.approx( + 75.0 ) - assert sensor_states["moving_energy"][recovery_idx] == pytest.approx(100.0), ( - f"Recovery moving energy should be 100, got {sensor_states['moving_energy'][recovery_idx]}" + assert collector.sensor_states["moving_energy"][recovery_idx] == pytest.approx( + 100.0 ) - assert sensor_states["still_energy"][recovery_idx] == pytest.approx(80.0), ( - f"Recovery still energy should be 80, got {sensor_states['still_energy'][recovery_idx]}" - ) - # LD2412 detection_distance = moving_distance when MOVE_BITMASK set - assert sensor_states["detection_distance"][recovery_idx] == pytest.approx( - 50.0 - ), ( - f"Recovery detection distance should be 50, got {sensor_states['detection_distance'][recovery_idx]}" + assert collector.sensor_states["still_energy"][recovery_idx] == pytest.approx( + 80.0 ) + assert collector.sensor_states["detection_distance"][ + recovery_idx + ] == pytest.approx(50.0) - # Verify binary sensors detected targets - has_target_entity = find_entity(entities, "has_target", BinarySensorInfo) - assert has_target_entity is not None - initial_ht = initial_state_helper.initial_states.get(has_target_entity.key) - assert initial_ht is not None and isinstance(initial_ht, BinarySensorState) - assert initial_ht.state is True, "Has target should be True" - - has_moving_entity = find_entity(entities, "has_moving_target", BinarySensorInfo) - assert has_moving_entity is not None - initial_hm = initial_state_helper.initial_states.get(has_moving_entity.key) - assert initial_hm is not None and isinstance(initial_hm, BinarySensorState) - assert initial_hm.state is True, "Has moving target should be True" - - has_still_entity = find_entity(entities, "has_still_target", BinarySensorInfo) - assert has_still_entity is not None - initial_hs = initial_state_helper.initial_states.get(has_still_entity.key) - assert initial_hs is not None and isinstance(initial_hs, BinarySensorState) - assert initial_hs.state is True, "Has still target should be True" + # Verify binary sensors detected targets (from Phase 1 frame) + assert collector.binary_states["has_target"][0] is True + assert collector.binary_states["has_moving_target"][0] is True + assert collector.binary_states["has_still_target"][0] is True @pytest.mark.asyncio @@ -262,120 +182,75 @@ async def test_uart_mock_ld2412_engineering( "EXTERNAL_COMPONENT_PATH", external_components_path ) - loop = asyncio.get_running_loop() - - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "moving_distance": [], - "still_distance": [], - "moving_energy": [], - "still_energy": [], - "detection_distance": [], - "light": [], - "gate_0_move_energy": [], - "gate_1_move_energy": [], - "gate_2_move_energy": [], - "gate_0_still_energy": [], - "gate_1_still_energy": [], - "gate_2_still_energy": [], - } - binary_states: dict[str, list[bool]] = { - "has_target": [], - "has_moving_target": [], - "has_still_target": [], - } + collector = SensorStateCollector( + sensor_names=[ + "moving_distance", + "still_distance", + "moving_energy", + "still_energy", + "detection_distance", + "light", + "gate_0_move_energy", + "gate_1_move_energy", + "gate_2_move_energy", + "gate_0_still_energy", + "gate_1_still_energy", + "gate_2_still_energy", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + ], + ) # Signal when we see Phase 3 frame values - phase3_still_received = loop.create_future() - phase3_detect_received = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - if ( - sensor_name == "still_distance" - and state.state == pytest.approx(291.0) - and not phase3_still_received.done() - ): - phase3_still_received.set_result(True) - if ( - sensor_name == "detection_distance" - and state.state == pytest.approx(291.0) - and not phase3_detect_received.done() - ): - phase3_detect_received.set_result(True) - elif isinstance(state, BinarySensorState): - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in binary_states: - binary_states[sensor_name].append(state.state) + phase3_still_received = collector.add_waiter( + lambda: pytest.approx(291.0) in collector.sensor_states["still_distance"] + ) + phase3_detect_received = collector.add_waiter( + lambda: pytest.approx(291.0) in collector.sensor_states["detection_distance"] + ) async with ( run_compiled(yaml_config), api_client_connected() as client, ): entities, _ = await client.list_entities_services() - - all_names = list(sensor_states.keys()) + list(binary_states.keys()) - # Sort by descending length to avoid substring collisions - # (e.g., "still_energy" matching "gate_0_still_energy") - all_names.sort(key=len, reverse=True) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) + collector.build_key_mapping(entities) initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) try: await initial_state_helper.wait_for_initial_states() except TimeoutError: pytest.fail("Timeout waiting for initial states") - # Phase 1 initial values (engineering mode frame): + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) + + # Phase 1 values (engineering mode frame): # moving=30, energy=100, still=30, energy=100, detect=30 - moving_dist_entity = find_entity(entities, "moving_distance", SensorInfo) - assert moving_dist_entity is not None - initial_moving = initial_state_helper.initial_states.get(moving_dist_entity.key) - assert initial_moving is not None and isinstance(initial_moving, SensorState) - assert initial_moving.state == pytest.approx(30.0), ( - f"Initial moving distance should be 30, got {initial_moving.state}" - ) - - still_dist_entity = find_entity(entities, "still_distance", SensorInfo) - assert still_dist_entity is not None - initial_still = initial_state_helper.initial_states.get(still_dist_entity.key) - assert initial_still is not None and isinstance(initial_still, SensorState) - assert initial_still.state == pytest.approx(30.0), ( - f"Initial still distance should be 30, got {initial_still.state}" - ) - - # Verify engineering mode sensors from initial state - # Gate 0 moving energy = 0x64 = 100 - gate0_move_entity = find_entity(entities, "gate_0_move_energy", SensorInfo) - assert gate0_move_entity is not None - initial_g0m = initial_state_helper.initial_states.get(gate0_move_entity.key) - assert initial_g0m is not None and isinstance(initial_g0m, SensorState) - assert initial_g0m.state == pytest.approx(100.0), ( - f"Gate 0 move energy should be 100, got {initial_g0m.state}" - ) - - # Gate 1 moving energy = 0x41 = 65 - gate1_move_entity = find_entity(entities, "gate_1_move_energy", SensorInfo) - assert gate1_move_entity is not None - initial_g1m = initial_state_helper.initial_states.get(gate1_move_entity.key) - assert initial_g1m is not None and isinstance(initial_g1m, SensorState) - assert initial_g1m.state == pytest.approx(65.0), ( - f"Gate 1 move energy should be 65, got {initial_g1m.state}" - ) - - # Light sensor = 0x57 = 87 - light_entity = find_entity(entities, "light", SensorInfo) - assert light_entity is not None - initial_light = initial_state_helper.initial_states.get(light_entity.key) - assert initial_light is not None and isinstance(initial_light, SensorState) - assert initial_light.state == pytest.approx(87.0), ( - f"Light sensor should be 87, got {initial_light.state}" - ) + assert collector.sensor_states["moving_distance"][0] == pytest.approx(30.0) + assert collector.sensor_states["still_distance"][0] == pytest.approx(30.0) + assert collector.sensor_states["gate_0_move_energy"][0] == pytest.approx(100.0) + assert collector.sensor_states["gate_1_move_energy"][0] == pytest.approx(65.0) + assert collector.sensor_states["light"][0] == pytest.approx(87.0) # Wait for Phase 3 frame: still_distance = 291cm (multi-byte) try: @@ -383,25 +258,18 @@ async def test_uart_mock_ld2412_engineering( except TimeoutError: pytest.fail( f"Timeout waiting for Phase 3 still_distance. Received:\n" - f" still_distance: {sensor_states['still_distance']}\n" - f" moving_distance: {sensor_states['moving_distance']}" + f" still_distance: {collector.sensor_states['still_distance']}" ) - assert pytest.approx(291.0) in sensor_states["still_distance"], ( - f"Expected still_distance=291, got: {sensor_states['still_distance']}" - ) + assert pytest.approx(291.0) in collector.sensor_states["still_distance"] # Wait for Phase 3: detection_distance = 291 (still-only target) - # target_state=0x02 so LD2412 uses still_distance for detection_distance. - # The throttle_with_priority filter may delay this value. try: await asyncio.wait_for(phase3_detect_received, timeout=3.0) except TimeoutError: pytest.fail( - f"Timeout waiting for detection_distance=291 (still-only target). " - f"Received: {sensor_states['detection_distance']}" + f"Timeout waiting for detection_distance=291. " + f"Received: {collector.sensor_states['detection_distance']}" ) - assert pytest.approx(291.0) in sensor_states["detection_distance"], ( - f"Expected detection_distance=291, got: {sensor_states['detection_distance']}" - ) + assert pytest.approx(291.0) in collector.sensor_states["detection_distance"] diff --git a/tests/integration/test_uart_mock_modbus.py b/tests/integration/test_uart_mock_modbus.py index 309cb56dc9..bf3c069750 100644 --- a/tests/integration/test_uart_mock_modbus.py +++ b/tests/integration/test_uart_mock_modbus.py @@ -12,10 +12,10 @@ from __future__ import annotations import asyncio from pathlib import Path -from aioesphomeapi import EntityState, SensorState +from aioesphomeapi import ButtonInfo, EntityState, SensorState import pytest -from .state_utils import InitialStateHelper, build_key_to_entity_mapping +from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity from .types import APIClientConnectedFactory, RunCompiledFunction @@ -74,6 +74,11 @@ async def test_uart_mock_modbus( except TimeoutError: pytest.fail("Timeout waiting for initial states") + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + # Wait for basic register to be updated with successful parse try: await asyncio.wait_for(basic_register_changed, timeout=15.0) @@ -143,6 +148,11 @@ async def test_uart_mock_modbus_timing( except TimeoutError: pytest.fail("Timeout waiting for initial states") + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + # Wait for voltage to be updated with successful parse try: await asyncio.wait_for(voltage_changed, timeout=15.0) From 0ff5270632f59a8fd4d7ed25cd71c2ce92ae5b07 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 4 Mar 2026 16:57:19 -1000 Subject: [PATCH 1108/2030] [ci] Fix codeowner approval label workflow for fork PRs (#14490) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .github/scripts/codeowners.js | 88 +++++++++- .../codeowner-approved-label-update.yml | 95 +++++++++++ .../workflows/codeowner-approved-label.yml | 153 +++++------------- 3 files changed, 217 insertions(+), 119 deletions(-) create mode 100644 .github/workflows/codeowner-approved-label-update.yml diff --git a/.github/scripts/codeowners.js b/.github/scripts/codeowners.js index 9a10391699..5d69c11b1a 100644 --- a/.github/scripts/codeowners.js +++ b/.github/scripts/codeowners.js @@ -2,7 +2,7 @@ // // Used by: // - codeowner-review-request.yml -// - codeowner-approved-label.yml +// - codeowner-approved-label.yml + codeowner-approved-label-update.yml // - auto-label-pr/detectors.js (detectCodeOwner) /** @@ -133,11 +133,95 @@ function loadCodeowners(repoRoot = '.') { return parseCodeowners(content); } +/** Possible label actions returned by determineLabelAction. */ +const LabelAction = Object.freeze({ + ADD: 'add', + REMOVE: 'remove', + NONE: 'none', +}); + +/** + * Determine what label action is needed for a PR based on codeowner approvals. + * + * Checks changed files against CODEOWNERS patterns, reviews, and current labels + * to decide if the label should be added, removed, or left unchanged. + * + * @param {object} github - octokit instance from actions/github-script + * @param {string} owner - repo owner + * @param {string} repo - repo name + * @param {number} pr_number - pull request number + * @param {Array} codeownersPatterns - from loadCodeowners / fetchCodeowners + * @param {string} labelName - label to manage + * @returns {Promise<LabelAction>} + */ +async function determineLabelAction(github, owner, repo, pr_number, codeownersPatterns, labelName) { + // Get the list of changed files in this PR + const prFiles = await github.paginate( + github.rest.pulls.listFiles, + { owner, repo, pull_number: pr_number } + ); + + const changedFiles = prFiles.map(file => file.filename); + console.log(`Found ${changedFiles.length} changed files`); + + if (changedFiles.length === 0) { + console.log('No changed files found'); + return LabelAction.NONE; + } + + // Get effective owners using last-match-wins semantics + const effective = getEffectiveOwners(changedFiles, codeownersPatterns); + const componentCodeowners = effective.users; + + console.log(`Component-specific codeowners: ${Array.from(componentCodeowners).join(', ') || '(none)'}`); + + // Get current labels + const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({ + owner, repo, issue_number: pr_number + }); + const hasLabel = currentLabels.some(label => label.name === labelName); + + if (componentCodeowners.size === 0) { + console.log('No component-specific codeowners found'); + return hasLabel ? LabelAction.REMOVE : LabelAction.NONE; + } + + // Get all reviews and find latest per user + const reviews = await github.paginate( + github.rest.pulls.listReviews, + { owner, repo, pull_number: pr_number } + ); + + const latestReviewByUser = new Map(); + for (const review of reviews) { + if (!review.user || review.user.type === 'Bot' || review.state === 'COMMENTED') continue; + latestReviewByUser.set(review.user.login, review); + } + + // Check if any component-specific codeowner has an active approval + let hasCodeownerApproval = false; + for (const [login, review] of latestReviewByUser) { + if (review.state === 'APPROVED' && componentCodeowners.has(login)) { + console.log(`Codeowner '${login}' has approved`); + hasCodeownerApproval = true; + break; + } + } + + if (hasCodeownerApproval && !hasLabel) return LabelAction.ADD; + if (!hasCodeownerApproval && hasLabel) return LabelAction.REMOVE; + + console.log(`Label already ${hasLabel ? 'present' : 'absent'}, no change needed`); + return LabelAction.NONE; +} + module.exports = { globToRegex, parseCodeowners, fetchCodeowners, loadCodeowners, classifyOwners, - getEffectiveOwners + getEffectiveOwners, + LabelAction, + determineLabelAction }; diff --git a/.github/workflows/codeowner-approved-label-update.yml b/.github/workflows/codeowner-approved-label-update.yml new file mode 100644 index 0000000000..9168cce1d6 --- /dev/null +++ b/.github/workflows/codeowner-approved-label-update.yml @@ -0,0 +1,95 @@ +# Fallback for fork PRs: phase 1 (codeowner-approved-label.yml) handles +# non-fork PRs directly but can't write labels on fork PRs (read-only token). +# This workflow re-determines the action and applies it if needed. + +name: Codeowner Approved Label Update + +on: + workflow_run: + workflows: ["Codeowner Approved Label"] + types: [completed] + +permissions: + issues: write + pull-requests: read + contents: read + +jobs: + update-label: + name: Run + if: > + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'pull_request_review' + runs-on: ubuntu-latest + steps: + - name: Get PR details + id: pr + env: + GH_TOKEN: ${{ github.token }} + HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + REPO: ${{ github.repository }} + run: | + pr_data=$(gh pr list --repo "$REPO" --state open --search "$HEAD_SHA" \ + --json number,baseRefName --jq '.[0] // empty') + + if [ -z "$pr_data" ]; then + echo "No open PR found for SHA $HEAD_SHA, skipping" + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + pr_number=$(echo "$pr_data" | jq -r '.number') + base_ref=$(echo "$pr_data" | jq -r '.baseRefName') + + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + echo "base_ref=$base_ref" >> "$GITHUB_OUTPUT" + echo "Found PR #$pr_number targeting $base_ref" + + - name: Checkout base repository + if: steps.pr.outputs.skip != 'true' + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: ${{ github.repository }} + ref: ${{ steps.pr.outputs.base_ref }} + sparse-checkout: | + .github/scripts/codeowners.js + CODEOWNERS + + - name: Update label + if: steps.pr.outputs.skip != 'true' + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + PR_NUMBER: ${{ steps.pr.outputs.pr_number }} + with: + script: | + const { loadCodeowners, determineLabelAction, LabelAction } = require('./.github/scripts/codeowners.js'); + + const owner = context.repo.owner; + const repo = context.repo.repo; + const pr_number = parseInt(process.env.PR_NUMBER, 10); + const LABEL_NAME = 'code-owner-approved'; + + console.log(`Processing PR #${pr_number} for codeowner approval label`); + + const codeownersPatterns = loadCodeowners(); + const action = await determineLabelAction( + github, owner, repo, pr_number, codeownersPatterns, LABEL_NAME + ); + + if (action === LabelAction.ADD) { + await github.rest.issues.addLabels({ + owner, repo, issue_number: pr_number, labels: [LABEL_NAME] + }); + console.log(`Added '${LABEL_NAME}' label`); + } else if (action === LabelAction.REMOVE) { + try { + await github.rest.issues.removeLabel({ + owner, repo, issue_number: pr_number, name: LABEL_NAME + }); + console.log(`Removed '${LABEL_NAME}' label`); + } catch (error) { + if (error.status !== 404) throw error; + } + } else { + console.log('No label change needed'); + } diff --git a/.github/workflows/codeowner-approved-label.yml b/.github/workflows/codeowner-approved-label.yml index 200f18f544..12199bd0b0 100644 --- a/.github/workflows/codeowner-approved-label.yml +++ b/.github/workflows/codeowner-approved-label.yml @@ -1,9 +1,9 @@ -# This workflow adds/removes a 'code-owner-approved' label when a -# component-specific codeowner approves (or dismisses) a PR. -# This helps maintainers prioritize PRs that have codeowner sign-off. +# Adds/removes a 'code-owner-approved' label when a component-specific +# codeowner approves (or dismisses) a PR. # -# Only component-specific codeowners count — the catch-all @esphome/core -# team is excluded so the label reflects domain-expert approval. +# Handles non-fork PRs directly. For fork PRs the GITHUB_TOKEN is read-only, +# so label writes are deferred to codeowner-approved-label-update.yml which +# triggers via workflow_run with write permissions. name: Codeowner Approved Label @@ -26,134 +26,53 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: ref: ${{ github.event.pull_request.base.sha }} + sparse-checkout: | + .github/scripts/codeowners.js + CODEOWNERS - name: Check codeowner approval and update label uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + PR_NUMBER: ${{ github.event.pull_request.number }} with: script: | - const { loadCodeowners, getEffectiveOwners } = require('./.github/scripts/codeowners.js'); + const { loadCodeowners, determineLabelAction, LabelAction } = require('./.github/scripts/codeowners.js'); const owner = context.repo.owner; const repo = context.repo.repo; - const pr_number = context.payload.pull_request.number; + const pr_number = parseInt(process.env.PR_NUMBER, 10); const LABEL_NAME = 'code-owner-approved'; console.log(`Processing PR #${pr_number} for codeowner approval label`); + const codeownersPatterns = loadCodeowners(); + const action = await determineLabelAction( + github, owner, repo, pr_number, codeownersPatterns, LABEL_NAME + ); + + if (action === LabelAction.NONE) { + console.log('No label change needed'); + return; + } + try { - // Get the list of changed files in this PR (with pagination) - const prFiles = await github.paginate( - github.rest.pulls.listFiles, - { - owner, - repo, - pull_number: pr_number - } - ); - - const changedFiles = prFiles.map(file => file.filename); - console.log(`Found ${changedFiles.length} changed files`); - - if (changedFiles.length === 0) { - console.log('No changed files found, skipping'); - return; - } - - // Parse CODEOWNERS from the checked-out base branch - const codeownersPatterns = loadCodeowners(); - - // Get effective owners using last-match-wins semantics - const effective = getEffectiveOwners(changedFiles, codeownersPatterns); - - // Only keep individual component-specific codeowners (exclude teams) - const componentCodeowners = effective.users; - - console.log(`Component-specific codeowners for changed files: ${Array.from(componentCodeowners).join(', ') || '(none)'}`); - - if (componentCodeowners.size === 0) { - console.log('No component-specific codeowners found for changed files'); - // Remove label if present since there are no component codeowners - try { - await github.rest.issues.removeLabel({ - owner, - repo, - issue_number: pr_number, - name: LABEL_NAME - }); - console.log(`Removed '${LABEL_NAME}' label (no component codeowners)`); - } catch (error) { - if (error.status !== 404) { - console.log(`Failed to remove label: ${error.message}`); - } - } - return; - } - - // Get all reviews on the PR - const reviews = await github.paginate( - github.rest.pulls.listReviews, - { - owner, - repo, - pull_number: pr_number - } - ); - - // Get the latest review per user (reviews are returned chronologically) - const latestReviewByUser = new Map(); - for (const review of reviews) { - // Skip bot reviews and comment-only reviews - if (!review.user || review.user.type === 'Bot' || review.state === 'COMMENTED') continue; - latestReviewByUser.set(review.user.login, review); - } - - // Check if any component-specific codeowner has an active approval - let hasCodeownerApproval = false; - for (const [login, review] of latestReviewByUser) { - if (review.state === 'APPROVED' && componentCodeowners.has(login)) { - console.log(`Codeowner '${login}' has approved`); - hasCodeownerApproval = true; - break; - } - } - - // Get current labels to check if label is already present - const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({ - owner, - repo, - issue_number: pr_number - }); - const hasLabel = currentLabels.some(label => label.name === LABEL_NAME); - - if (hasCodeownerApproval && !hasLabel) { - // Add the label + if (action === LabelAction.ADD) { await github.rest.issues.addLabels({ - owner, - repo, - issue_number: pr_number, - labels: [LABEL_NAME] + owner, repo, issue_number: pr_number, labels: [LABEL_NAME] }); console.log(`Added '${LABEL_NAME}' label`); - } else if (!hasCodeownerApproval && hasLabel) { - // Remove the label - try { - await github.rest.issues.removeLabel({ - owner, - repo, - issue_number: pr_number, - name: LABEL_NAME - }); - console.log(`Removed '${LABEL_NAME}' label`); - } catch (error) { - if (error.status !== 404) { - console.log(`Failed to remove label: ${error.message}`); - } - } - } else { - console.log(`Label already ${hasLabel ? 'present' : 'absent'}, no change needed`); + } else if (action === LabelAction.REMOVE) { + await github.rest.issues.removeLabel({ + owner, repo, issue_number: pr_number, name: LABEL_NAME + }); + console.log(`Removed '${LABEL_NAME}' label`); } - } catch (error) { - console.error(error); - core.setFailed(`Failed to process codeowner approval label: ${error.message}`); + if (error.status === 403) { + console.log('Fork PR: deferring label write to phase 2 workflow'); + } else if (error.status === 404) { + console.log('Label already removed'); + } else { + throw error; + } } From f5c37bf486d1a8905b7518478fec23a2e6e3b9ae Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:24:01 +1100 Subject: [PATCH 1109/2030] [packet_transport] Minimise heap allocations (#14482) --- .../packet_transport/packet_transport.cpp | 79 ++-- .../packet_transport/packet_transport.h | 19 +- script/cpp_unit_test.py | 44 +- tests/components/packet_transport/common.h | 98 ++++ .../components/packet_transport/cpp_test.yaml | 11 + .../packet_transport_test.cpp | 445 ++++++++++++++++++ 6 files changed, 659 insertions(+), 37 deletions(-) create mode 100644 tests/components/packet_transport/common.h create mode 100644 tests/components/packet_transport/cpp_test.yaml create mode 100644 tests/components/packet_transport/packet_transport_test.cpp diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index d2c5920001..f241cc6114 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -3,6 +3,8 @@ #include "esphome/core/helpers.h" #include "packet_transport.h" +#include <ranges> + #include "esphome/components/xxtea/xxtea.h" namespace esphome { @@ -77,7 +79,7 @@ enum DecodeResult { DECODE_EMPTY, }; -static const size_t MAX_PING_KEYS = 4; +static constexpr size_t MAX_PING_KEYS = 4; static inline void add(std::vector<uint8_t> &vec, uint32_t data) { vec.push_back(data & 0xFF); @@ -168,7 +170,7 @@ class PacketDecoder { return true; } - bool decrypt(const uint32_t *key) { + bool decrypt(const uint32_t *key) const { if (this->get_remaining_size() % 4 != 0) { return false; } @@ -249,9 +251,9 @@ void PacketTransport::init_data_() { } else { add(this->data_, DATA_KEY); } - for (const auto &pkey : this->ping_keys_) { + for (auto &value : this->ping_keys_ | std::views::values) { add(this->data_, PING_KEY); - add(this->data_, pkey.second); + add(this->data_, value); } } @@ -331,7 +333,7 @@ void PacketTransport::update() { auto now = millis() / 1000; if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) { this->resend_ping_key_ = this->ping_pong_enable_; - ESP_LOGV(TAG, "Ping request, age %u", now - this->last_key_time_); + ESP_LOGV(TAG, "Ping request, age %" PRIu32, now - this->last_key_time_); this->last_key_time_ = now; } for (const auto &provider : this->providers_) { @@ -339,24 +341,32 @@ void PacketTransport::update() { if (key_response_age > (this->ping_pong_recyle_time_ * 2u)) { #ifdef USE_STATUS_SENSOR if (provider.second.status_sensor != nullptr && provider.second.status_sensor->state) { - ESP_LOGI(TAG, "Ping status for %s timeout at %u with age %u", provider.first.c_str(), now, key_response_age); + ESP_LOGI(TAG, "Ping status for %s timeout at %" PRIu32 " with age %" PRIu32, provider.first.c_str(), now, + key_response_age); provider.second.status_sensor->publish_state(false); } #endif #ifdef USE_SENSOR - for (auto &sensor : this->remote_sensors_[provider.first]) { - sensor.second->publish_state(NAN); + auto it = this->remote_sensors_.find(provider.first); + if (it != this->remote_sensors_.end()) { + for (auto &val : it->second | std::views::values) { + val->publish_state(NAN); + } } #endif #ifdef USE_BINARY_SENSOR - for (auto &sensor : this->remote_binary_sensors_[provider.first]) { - sensor.second->invalidate_state(); + auto bs_it = this->remote_binary_sensors_.find(provider.first); + if (bs_it != this->remote_binary_sensors_.end()) { + for (auto &val : bs_it->second | std::views::values) { + val->invalidate_state(); + } } #endif } else { #ifdef USE_STATUS_SENSOR if (provider.second.status_sensor != nullptr && !provider.second.status_sensor->state) { - ESP_LOGI(TAG, "Ping status for %s restored at %u with age %u", provider.first.c_str(), now, key_response_age); + ESP_LOGI(TAG, "Ping status for %s restored at %" PRIu32 " with age %" PRIu32, provider.first.c_str(), now, + key_response_age); provider.second.status_sensor->publish_state(true); } #endif @@ -367,11 +377,16 @@ void PacketTransport::update() { void PacketTransport::add_key_(const char *name, uint32_t key) { if (!this->is_encrypted_()) return; - if (this->ping_keys_.count(name) == 0 && this->ping_keys_.size() == MAX_PING_KEYS) { - ESP_LOGW(TAG, "Ping key from %s discarded", name); - return; + auto it = this->ping_keys_.find(name); + if (it == this->ping_keys_.end()) { + if (this->ping_keys_.size() == MAX_PING_KEYS) { + ESP_LOGW(TAG, "Ping key from %s discarded", name); + return; + } + this->ping_keys_.emplace(name, key); // allocates string key once only + } else { + it->second = key; // key string already exists in map, no allocation } - this->ping_keys_[name] = key; this->updated_ = true; ESP_LOGV(TAG, "Ping key from %s now %X", name, (unsigned) key); } @@ -431,17 +446,19 @@ void PacketTransport::process_(std::span<const uint8_t> data) { return; } - if (this->providers_.count(namebuf) == 0) { + auto it = this->providers_.find(namebuf); + if (it == this->providers_.end()) { ESP_LOGVV(TAG, "Unknown hostname %s", namebuf); return; } + auto &provider = it->second; ESP_LOGV(TAG, "Found hostname %s", namebuf); #ifdef USE_SENSOR - auto &sensors = this->remote_sensors_[namebuf]; + auto &sensors = this->remote_sensors_.try_emplace(namebuf).first->second; #endif #ifdef USE_BINARY_SENSOR - auto &binary_sensors = this->remote_binary_sensors_[namebuf]; + auto &binary_sensors = this->remote_binary_sensors_.try_emplace(namebuf).first->second; #endif if (!decoder.bump_to(4)) { @@ -453,7 +470,6 @@ void PacketTransport::process_(std::span<const uint8_t> data) { return; } - auto &provider = this->providers_[namebuf]; // if encryption not used with this host, ping check is pointless since it would be easily spoofed. if (provider.encryption_key.empty()) ping_key_seen = true; @@ -495,16 +511,19 @@ void PacketTransport::process_(std::span<const uint8_t> data) { if (decoder.decode(BINARY_SENSOR_KEY, namebuf, sizeof(namebuf), byte) == DECODE_OK) { ESP_LOGV(TAG, "Got binary sensor %s %d", namebuf, byte); #ifdef USE_BINARY_SENSOR - if (binary_sensors.count(namebuf) != 0) - binary_sensors[namebuf]->publish_state(byte != 0); + auto bs = binary_sensors.find(namebuf); + if (bs != binary_sensors.end()) { + bs->second->publish_state(byte != 0); + } #endif continue; } if (decoder.decode(SENSOR_KEY, namebuf, sizeof(namebuf), rdata.u32) == DECODE_OK) { ESP_LOGV(TAG, "Got sensor %s %f", namebuf, rdata.f32); #ifdef USE_SENSOR - if (sensors.count(namebuf) != 0) - sensors[namebuf]->publish_state(rdata.f32); + auto sensor_it = sensors.find(namebuf); + if (sensor_it != sensors.end()) + sensor_it->second->publish_state(rdata.f32); #endif continue; } @@ -537,12 +556,18 @@ void PacketTransport::dump_config() { ESP_LOGCONFIG(TAG, " Remote host: %s", host.first.c_str()); ESP_LOGCONFIG(TAG, " Encrypted: %s", YESNO(!host.second.encryption_key.empty())); #ifdef USE_SENSOR - for (const auto &sensor : this->remote_sensors_[host.first.c_str()]) - ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.first.c_str()); + auto rs = this->remote_sensors_.find(host.first.c_str()); + if (rs != this->remote_sensors_.end()) { + for (const auto &key : rs->second | std::views::keys) + ESP_LOGCONFIG(TAG, " Sensor: %s", key.c_str()); + } #endif #ifdef USE_BINARY_SENSOR - for (const auto &sensor : this->remote_binary_sensors_[host.first.c_str()]) - ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.first.c_str()); + auto rbs = this->remote_binary_sensors_.find(host.first.c_str()); + if (rbs != this->remote_binary_sensors_.end()) { + for (const auto &key : rbs->second | std::views::keys) + ESP_LOGCONFIG(TAG, " Binary Sensor: %s", key.c_str()); + } #endif } } diff --git a/esphome/components/packet_transport/packet_transport.h b/esphome/components/packet_transport/packet_transport.h index a236744231..b3798738e2 100644 --- a/esphome/components/packet_transport/packet_transport.h +++ b/esphome/components/packet_transport/packet_transport.h @@ -24,6 +24,9 @@ namespace esphome { namespace packet_transport { +// std::less provides allocation-free comparison with const char * +template<typename T> using string_map_t = std::map<std::string, T, std::less<>>; + struct Provider { std::vector<uint8_t> encryption_key; const char *name; @@ -79,15 +82,15 @@ class PacketTransport : public PollingComponent { #endif void add_provider(const char *hostname) { - if (this->providers_.count(hostname) == 0) { + if (!this->providers_.contains(hostname)) { Provider provider{}; provider.name = hostname; this->providers_[hostname] = provider; #ifdef USE_SENSOR - this->remote_sensors_[hostname] = std::map<std::string, sensor::Sensor *>(); + this->remote_sensors_[hostname] = string_map_t<sensor::Sensor *>(); #endif #ifdef USE_BINARY_SENSOR - this->remote_binary_sensors_[hostname] = std::map<std::string, binary_sensor::BinarySensor *>(); + this->remote_binary_sensors_[hostname] = string_map_t<binary_sensor::BinarySensor *>(); #endif } } @@ -139,23 +142,23 @@ class PacketTransport : public PollingComponent { #ifdef USE_SENSOR std::vector<Sensor> sensors_{}; - std::map<std::string, std::map<std::string, sensor::Sensor *>> remote_sensors_{}; + string_map_t<string_map_t<sensor::Sensor *>> remote_sensors_{}; #endif #ifdef USE_BINARY_SENSOR std::vector<BinarySensor> binary_sensors_{}; - std::map<std::string, std::map<std::string, binary_sensor::BinarySensor *>> remote_binary_sensors_{}; + string_map_t<string_map_t<binary_sensor::BinarySensor *>> remote_binary_sensors_{}; #endif - std::map<std::string, Provider> providers_{}; + string_map_t<Provider> providers_{}; std::vector<uint8_t> ping_header_{}; std::vector<uint8_t> header_{}; std::vector<uint8_t> data_{}; - std::map<std::string, uint32_t> ping_keys_{}; + string_map_t<uint32_t> ping_keys_{}; const char *platform_name_{""}; void add_key_(const char *name, uint32_t key); void send_ping_pong_request_(); - inline bool is_encrypted_() { return !this->encryption_key_.empty(); } + bool is_encrypted_() const { return !this->encryption_key_.empty(); } }; } // namespace packet_transport diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index 02b133060a..b87261ab33 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -12,6 +12,7 @@ from esphome.__main__ import command_compile, parse_args from esphome.config import validate_config from esphome.core import CORE from esphome.platformio_api import get_idedata +from esphome.yaml_util import load_yaml # This must coincide with the version in /platformio.ini PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" @@ -44,6 +45,38 @@ def filter_components_without_tests(components: list[str]) -> list[str]: return filtered_components +# Name of optional per-component YAML config merged into the test build +# before validation so that platform defines (USE_SENSOR, etc.) are generated. +CPP_TEST_CONFIG_FILE = "cpp_test.yaml" + + +def load_component_test_configs(components: list[str]) -> dict: + """Load cpp_test.yaml files from test component directories. + + These configs are merged into the base test config *before* validation + so that entity registration runs during code generation, which causes + the corresponding USE_* defines to be emitted. + """ + merged: dict = {} + for component in components: + config_file = COMPONENTS_TESTS_DIR / component / CPP_TEST_CONFIG_FILE + if not config_file.exists(): + continue + component_config = load_yaml(config_file) + if not component_config: + continue + for key, value in component_config.items(): + if ( + key in merged + and isinstance(merged[key], list) + and isinstance(value, list) + ): + merged[key].extend(value) + else: + merged[key] = value + return merged + + def create_test_config(config_name: str, includes: list[str]) -> dict: """Create ESPHome test configuration for C++ unit tests. @@ -115,6 +148,11 @@ def run_tests(selected_components: list[str]) -> int: config = create_test_config(config_name, includes) + # Merge component-specific test configs (e.g. sensor instances) before + # validation so that entity registration and USE_* defines work. + extra_config = load_component_test_configs(components) + config.update(extra_config) + CORE.config_path = COMPONENTS_TESTS_DIR / "dummy.yaml" CORE.dashboard = None @@ -122,8 +160,10 @@ def run_tests(selected_components: list[str]) -> int: config = validate_config(config, {}) # Add all components and dependencies to the base configuration after validation, so their files - # are added to the build. - config.update({key: {} for key in components_with_dependencies}) + # are added to the build. Use setdefault to avoid overwriting entries that were + # already validated (e.g. sensor instances from cpp_test.yaml). + for key in components_with_dependencies: + config.setdefault(key, {}) print(f"Testing components: {', '.join(components)}") CORE.config = config diff --git a/tests/components/packet_transport/common.h b/tests/components/packet_transport/common.h new file mode 100644 index 0000000000..f8caa7bb68 --- /dev/null +++ b/tests/components/packet_transport/common.h @@ -0,0 +1,98 @@ +#pragma once +#include <cstdint> +#include <cstring> +#include <cstdio> +#include <vector> +#include <gtest/gtest.h> +#include "esphome/components/packet_transport/packet_transport.h" + +namespace esphome::packet_transport::testing { + +// Protocol constants mirrored from packet_transport.cpp for test packet construction. +static constexpr uint16_t MAGIC_NUMBER = 0x4553; +static constexpr uint16_t MAGIC_PING = 0x5048; + +// Concrete testable implementation of PacketTransport. +// Captures sent packets and exposes protected members for verification. +// +// Sensor round-trip tests require USE_SENSOR / USE_BINARY_SENSOR to be defined, +// which happens when 'sensor' and 'binary_sensor' components are in the build. +// Run with --all or include those components to enable the full test suite. +class TestablePacketTransport : public PacketTransport { + public: + using PacketTransport::add_key_; + using PacketTransport::data_; + using PacketTransport::encryption_key_; + using PacketTransport::flush_; + using PacketTransport::header_; + using PacketTransport::increment_code_; + using PacketTransport::init_data_; + using PacketTransport::is_encrypted_; + using PacketTransport::is_provider_; + using PacketTransport::name_; + using PacketTransport::ping_key_; + using PacketTransport::ping_keys_; + using PacketTransport::ping_pong_enable_; + using PacketTransport::ping_pong_recyle_time_; + using PacketTransport::process_; + using PacketTransport::providers_; + using PacketTransport::rolling_code_; + using PacketTransport::rolling_code_enable_; + using PacketTransport::send_data_; + using PacketTransport::updated_; +#ifdef USE_SENSOR + using PacketTransport::add_data_; + using PacketTransport::remote_sensors_; + using PacketTransport::sensors_; +#endif +#ifdef USE_BINARY_SENSOR + using PacketTransport::add_binary_data_; + using PacketTransport::binary_sensors_; + using PacketTransport::remote_binary_sensors_; +#endif + + // NOTE: std::vector is used here for test convenience. For production code, + // consider using StaticVector or FixedVector from esphome/core/helpers.h instead. + mutable std::vector<std::vector<uint8_t>> sent_packets; + size_t max_packet_size{512}; + bool send_enabled{true}; + + void send_packet(const std::vector<uint8_t> &buf) const override { this->sent_packets.push_back(buf); } + size_t get_max_packet_size() override { return this->max_packet_size; } + bool should_send() override { return this->send_enabled; } + + /// Build the packet header for testing without requiring App or global_preferences. + void init_for_test(const char *name) { + this->name_ = name; + this->header_.clear(); + // MAGIC_NUMBER as uint16_t little-endian + this->header_.push_back(MAGIC_NUMBER & 0xFF); + this->header_.push_back((MAGIC_NUMBER >> 8) & 0xFF); + // Length-prefixed hostname + auto len = strlen(name); + this->header_.push_back(static_cast<uint8_t>(len)); + for (size_t i = 0; i < len; i++) + this->header_.push_back(name[i]); + // Pad to 4-byte boundary + while (this->header_.size() & 0x3) + this->header_.push_back(0); + } +}; + +/// Build a MAGIC_PING packet for testing add_key_ / ping-pong flows. +inline std::vector<uint8_t> build_ping_packet(const char *hostname, uint32_t key) { + std::vector<uint8_t> packet; + packet.push_back(MAGIC_PING & 0xFF); + packet.push_back((MAGIC_PING >> 8) & 0xFF); + auto len = strlen(hostname); + packet.push_back(static_cast<uint8_t>(len)); + for (size_t i = 0; i < len; i++) + packet.push_back(hostname[i]); + packet.push_back(key & 0xFF); + packet.push_back((key >> 8) & 0xFF); + packet.push_back((key >> 16) & 0xFF); + packet.push_back((key >> 24) & 0xFF); + return packet; +} + +} // namespace esphome::packet_transport::testing diff --git a/tests/components/packet_transport/cpp_test.yaml b/tests/components/packet_transport/cpp_test.yaml new file mode 100644 index 0000000000..fa39df3c0a --- /dev/null +++ b/tests/components/packet_transport/cpp_test.yaml @@ -0,0 +1,11 @@ +# Extra component configuration required by C++ unit tests. +# Loaded by cpp_unit_test.py and merged into the test build config +# before validation, so that platform defines (USE_SENSOR, etc.) are generated. + +sensor: + - platform: template + id: test_cpp_sensor + +binary_sensor: + - platform: template + id: test_cpp_binary_sensor diff --git a/tests/components/packet_transport/packet_transport_test.cpp b/tests/components/packet_transport/packet_transport_test.cpp new file mode 100644 index 0000000000..d8f11ca607 --- /dev/null +++ b/tests/components/packet_transport/packet_transport_test.cpp @@ -0,0 +1,445 @@ +#include "common.h" + +namespace esphome::packet_transport::testing { + +// --- Configuration setter tests --- + +TEST(PacketTransportTest, SetIsProvider) { + TestablePacketTransport transport; + transport.set_is_provider(true); + EXPECT_TRUE(transport.is_provider_); +} + +TEST(PacketTransportTest, SetEncryptionKey) { + TestablePacketTransport transport; + std::vector<uint8_t> key(32, 0xAB); + transport.set_encryption_key(key); + EXPECT_EQ(transport.encryption_key_, key); + EXPECT_TRUE(transport.is_encrypted_()); +} + +TEST(PacketTransportTest, NoEncryptionByDefault) { + TestablePacketTransport transport; + EXPECT_FALSE(transport.is_encrypted_()); +} + +TEST(PacketTransportTest, SetRollingCodeEnable) { + TestablePacketTransport transport; + transport.set_rolling_code_enable(true); + EXPECT_TRUE(transport.rolling_code_enable_); +} + +TEST(PacketTransportTest, SetPingPongEnable) { + TestablePacketTransport transport; + transport.set_ping_pong_enable(true); + EXPECT_TRUE(transport.ping_pong_enable_); +} + +TEST(PacketTransportTest, SetPingPongRecycleTime) { + TestablePacketTransport transport; + transport.set_ping_pong_recycle_time(600); + EXPECT_EQ(transport.ping_pong_recyle_time_, 600u); +} + +// --- Provider management --- + +TEST(PacketTransportTest, AddProvider) { + TestablePacketTransport transport; + transport.add_provider("host1"); + EXPECT_TRUE(transport.providers_.contains("host1")); + EXPECT_EQ(transport.providers_.size(), 1u); +} + +TEST(PacketTransportTest, AddProviderDuplicate) { + TestablePacketTransport transport; + transport.add_provider("host1"); + transport.add_provider("host1"); + EXPECT_EQ(transport.providers_.size(), 1u); +} + +TEST(PacketTransportTest, SetProviderEncryption) { + TestablePacketTransport transport; + transport.add_provider("host1"); + std::vector<uint8_t> key(32, 0xCD); + transport.set_provider_encryption("host1", key); + EXPECT_EQ(transport.providers_["host1"].encryption_key, key); +} + +// --- Sensor management (requires USE_SENSOR / USE_BINARY_SENSOR) --- + +#ifdef USE_SENSOR +TEST(PacketTransportTest, AddSensor) { + TestablePacketTransport transport; + sensor::Sensor s; + transport.add_sensor("temp", &s); + ASSERT_EQ(transport.sensors_.size(), 1u); + EXPECT_STREQ(transport.sensors_[0].id, "temp"); + EXPECT_EQ(transport.sensors_[0].sensor, &s); + EXPECT_TRUE(transport.sensors_[0].updated); +} + +TEST(PacketTransportTest, AddRemoteSensor) { + TestablePacketTransport transport; + sensor::Sensor s; + transport.add_remote_sensor("host1", "remote_temp", &s); + EXPECT_TRUE(transport.providers_.contains("host1")); + EXPECT_EQ(transport.remote_sensors_["host1"]["remote_temp"], &s); +} +#endif + +#ifdef USE_BINARY_SENSOR +TEST(PacketTransportTest, AddBinarySensor) { + TestablePacketTransport transport; + binary_sensor::BinarySensor bs; + transport.add_binary_sensor("motion", &bs); + ASSERT_EQ(transport.binary_sensors_.size(), 1u); + EXPECT_STREQ(transport.binary_sensors_[0].id, "motion"); + EXPECT_EQ(transport.binary_sensors_[0].sensor, &bs); +} + +TEST(PacketTransportTest, AddRemoteBinarySensor) { + TestablePacketTransport transport; + binary_sensor::BinarySensor bs; + transport.add_remote_binary_sensor("host1", "remote_motion", &bs); + EXPECT_TRUE(transport.providers_.contains("host1")); + EXPECT_EQ(transport.remote_binary_sensors_["host1"]["remote_motion"], &bs); +} +#endif + +// --- Unencrypted round-trip tests (require USE_SENSOR / USE_BINARY_SENSOR) --- + +#ifdef USE_SENSOR +TEST(PacketTransportTest, UnencryptedSensorRoundTrip) { + // Encoder + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + sensor::Sensor local_sensor; + local_sensor.state = 42.5f; + encoder.add_sensor("temp", &local_sensor); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + // Decoder + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; // sentinel + decoder.add_remote_sensor("sender", "temp", &remote_sensor); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 42.5f); +} +#endif + +#ifdef USE_BINARY_SENSOR +TEST(PacketTransportTest, UnencryptedBinarySensorRoundTrip) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + binary_sensor::BinarySensor local_bs; + local_bs.state = true; + encoder.add_binary_sensor("motion", &local_bs); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + binary_sensor::BinarySensor remote_bs; + decoder.add_remote_binary_sensor("sender", "motion", &remote_bs); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_TRUE(remote_bs.state); +} +#endif + +#if defined(USE_SENSOR) && defined(USE_BINARY_SENSOR) +TEST(PacketTransportTest, MultipleSensorsRoundTrip) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + + sensor::Sensor s1, s2; + s1.state = 10.0f; + s2.state = 20.0f; + encoder.add_sensor("s1", &s1); + encoder.add_sensor("s2", &s2); + + binary_sensor::BinarySensor bs1; + bs1.state = true; + encoder.add_binary_sensor("bs1", &bs1); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor rs1, rs2; + binary_sensor::BinarySensor rbs1; + rs1.state = -999.0f; + rs2.state = -999.0f; + decoder.add_remote_sensor("sender", "s1", &rs1); + decoder.add_remote_sensor("sender", "s2", &rs2); + decoder.add_remote_binary_sensor("sender", "bs1", &rbs1); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + + EXPECT_FLOAT_EQ(rs1.state, 10.0f); + EXPECT_FLOAT_EQ(rs2.state, 20.0f); + EXPECT_TRUE(rbs1.state); +} +#endif + +// --- Encrypted round-trip --- + +#ifdef USE_SENSOR +TEST(PacketTransportTest, EncryptedSensorRoundTrip) { + std::vector<uint8_t> key(32); + for (int i = 0; i < 32; i++) + key[i] = i; + + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + encoder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 99.9f; + encoder.add_sensor("temp", &local_sensor); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + decoder.add_remote_sensor("sender", "temp", &remote_sensor); + decoder.set_provider_encryption("sender", key); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 99.9f); +} + +// --- Selective send --- + +TEST(PacketTransportTest, SendDataOnlyUpdated) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + + sensor::Sensor s1, s2; + s1.state = 1.0f; + s2.state = 2.0f; + encoder.add_sensor("s1", &s1); + encoder.add_sensor("s2", &s2); + + // Mark s1 as not updated, only s2 as updated + encoder.sensors_[0].updated = false; + encoder.sensors_[1].updated = true; + + encoder.send_data_(false); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor rs1, rs2; + rs1.state = -999.0f; + rs2.state = -999.0f; + decoder.add_remote_sensor("sender", "s1", &rs1); + decoder.add_remote_sensor("sender", "s2", &rs2); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + + EXPECT_FLOAT_EQ(rs1.state, -999.0f); // not updated, not sent + EXPECT_FLOAT_EQ(rs2.state, 2.0f); // updated, sent +} +#endif + +// --- Ping key tests --- + +TEST(PacketTransportTest, PingKeyStoredWhenEncrypted) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA)); + + auto ping = build_ping_packet("requester", 0xDEADBEEF); + transport.process_({ping.data(), ping.size()}); + + ASSERT_EQ(transport.ping_keys_.size(), 1u); + EXPECT_EQ(transport.ping_keys_["requester"], 0xDEADBEEFu); +} + +TEST(PacketTransportTest, PingKeyIgnoredWhenNotEncrypted) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + // No encryption key — add_key_ should be a no-op + + auto ping = build_ping_packet("requester", 0xDEADBEEF); + transport.process_({ping.data(), ping.size()}); + + EXPECT_TRUE(transport.ping_keys_.empty()); +} + +TEST(PacketTransportTest, PingKeyUpdatedOnRepeat) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA)); + + auto ping1 = build_ping_packet("host1", 0x1111); + transport.process_({ping1.data(), ping1.size()}); + EXPECT_EQ(transport.ping_keys_["host1"], 0x1111u); + + // Same host, new key value — should update in place + auto ping2 = build_ping_packet("host1", 0x2222); + transport.process_({ping2.data(), ping2.size()}); + EXPECT_EQ(transport.ping_keys_.size(), 1u); + EXPECT_EQ(transport.ping_keys_["host1"], 0x2222u); +} + +TEST(PacketTransportTest, PingKeyMaxLimit) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + transport.set_encryption_key(std::vector<uint8_t>(32, 0xAA)); + + // Fill to MAX_PING_KEYS (4) + for (int i = 0; i < 4; i++) { + char name[16]; + snprintf(name, sizeof(name), "host%d", i); + auto ping = build_ping_packet(name, 0x1000 + i); + transport.process_({ping.data(), ping.size()}); + } + EXPECT_EQ(transport.ping_keys_.size(), 4u); + + // 5th key should be discarded + auto ping = build_ping_packet("host4", 0x9999); + transport.process_({ping.data(), ping.size()}); + EXPECT_EQ(transport.ping_keys_.size(), 4u); + EXPECT_FALSE(transport.ping_keys_.contains("host4")); +} + +#ifdef USE_SENSOR +TEST(PacketTransportTest, PingKeyIncludedInTransmittedPacket) { + std::vector<uint8_t> key(32, 0xBB); + + // Responder: encrypted, owns a sensor + TestablePacketTransport responder; + responder.init_for_test("responder"); + responder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 77.7f; + responder.add_sensor("temp", &local_sensor); + + // Requester sends a MAGIC_PING that the responder processes + auto ping = build_ping_packet("requester", 0xDEADBEEF); + responder.process_({ping.data(), ping.size()}); + ASSERT_EQ(responder.ping_keys_.size(), 1u); + + // Responder sends sensor data — ping key should be embedded + responder.send_data_(true); + ASSERT_EQ(responder.sent_packets.size(), 1u); + + // Requester: encrypted provider, ping-pong enabled, expects key 0xDEADBEEF + TestablePacketTransport requester; + requester.init_for_test("requester"); + requester.set_ping_pong_enable(true); + requester.ping_key_ = 0xDEADBEEF; + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + requester.add_remote_sensor("responder", "temp", &remote_sensor); + requester.set_provider_encryption("responder", key); + + // The requester decrypts the packet and finds its ping key echoed back, + // which gates the sensor data — if the key is missing, data is blocked. + auto &packet = responder.sent_packets[0]; + requester.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 77.7f); +} + +TEST(PacketTransportTest, MissingPingKeyBlocksSensorData) { + std::vector<uint8_t> key(32, 0xBB); + + // Responder sends data WITHOUT receiving any MAGIC_PING first — no ping keys + TestablePacketTransport responder; + responder.init_for_test("responder"); + responder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 77.7f; + responder.add_sensor("temp", &local_sensor); + responder.send_data_(true); + ASSERT_EQ(responder.sent_packets.size(), 1u); + + // Requester with ping-pong enabled expects a key that isn't in the packet + TestablePacketTransport requester; + requester.init_for_test("requester"); + requester.set_ping_pong_enable(true); + requester.ping_key_ = 0xDEADBEEF; + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + requester.add_remote_sensor("responder", "temp", &remote_sensor); + requester.set_provider_encryption("responder", key); + + auto &packet = responder.sent_packets[0]; + requester.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, -999.0f); // blocked — ping key not found +} +#endif + +// --- Process error handling --- + +TEST(PacketTransportTest, ProcessShortBuffer) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + uint8_t buf[] = {0x53}; + // Too short for a magic number - should return safely + transport.process_({buf, 1}); +} + +TEST(PacketTransportTest, ProcessBadMagic) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + uint8_t buf[] = {0xFF, 0xFF, 0x00, 0x00}; + // Wrong magic - should return safely + transport.process_({buf, sizeof(buf)}); +} + +TEST(PacketTransportTest, ProcessOwnHostname) { + TestablePacketTransport transport; + transport.init_for_test("myself"); + // Build a packet from "myself" using a separate encoder + TestablePacketTransport fake_sender; + fake_sender.init_for_test("myself"); + fake_sender.send_data_(true); + ASSERT_EQ(fake_sender.sent_packets.size(), 1u); + + auto &packet = fake_sender.sent_packets[0]; + // Should be silently ignored because hostname matches our own + transport.process_({packet.data(), packet.size()}); +} + +TEST(PacketTransportTest, ProcessUnknownHostname) { + TestablePacketTransport transport; + transport.init_for_test("receiver"); + // No providers registered - "unknown" will not be found + TestablePacketTransport sender; + sender.init_for_test("unknown"); + sender.send_data_(true); + ASSERT_EQ(sender.sent_packets.size(), 1u); + + auto &packet = sender.sent_packets[0]; + // Should return safely without crash + transport.process_({packet.data(), packet.size()}); +} + +// --- Send disabled --- + +TEST(PacketTransportTest, NoSendWhenDisabled) { + TestablePacketTransport transport; + transport.init_for_test("sender"); + transport.send_enabled = false; + transport.send_data_(true); + EXPECT_TRUE(transport.sent_packets.empty()); +} + +} // namespace esphome::packet_transport::testing From 0e2a10c5f02cd4ba37ed53dde370bdd0a54c43ac Mon Sep 17 00:00:00 2001 From: rwrozelle <rwrozelle@gmail.com> Date: Wed, 4 Mar 2026 19:34:13 -0800 Subject: [PATCH 1110/2030] [openthread] Cache is_connected() for cheap inline access (#14484) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/openthread/openthread.cpp | 25 ++++++------------- esphome/components/openthread/openthread.h | 5 +++- .../components/openthread/openthread_esp.cpp | 3 +++ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index 92897a7e96..9452f5a41e 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -1,9 +1,7 @@ #include "esphome/core/defines.h" #ifdef USE_OPENTHREAD #include "openthread.h" -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) #include "esp_openthread.h" -#endif #include <freertos/portmacro.h> @@ -48,22 +46,15 @@ void OpenThreadComponent::dump_config() { } } -bool OpenThreadComponent::is_connected() { - auto lock = InstanceLock::try_acquire(100); - if (!lock) { - ESP_LOGW(TAG, "Failed to acquire OpenThread lock in is_connected"); - return false; +void OpenThreadComponent::on_state_changed_(otChangedFlags flags, void *context) { + if (flags & OT_CHANGED_THREAD_ROLE) { + auto *self = static_cast<OpenThreadComponent *>(context); + // This runs on the OpenThread task thread with the OT lock held, + // so we can safely call otThreadGetDeviceRole directly. + otInstance *instance = esp_openthread_get_instance(); + otDeviceRole role = otThreadGetDeviceRole(instance); + self->connected_ = role >= OT_DEVICE_ROLE_CHILD; } - - otInstance *instance = lock->get_instance(); - if (instance == nullptr) { - return false; - } - - otDeviceRole role = otThreadGetDeviceRole(instance); - - // TODO: If we're a leader, check that there is at least 1 known peer - return role >= OT_DEVICE_ROLE_CHILD; } // Gets the off-mesh routable address diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 728847afa5..d853c58f95 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -8,6 +8,7 @@ #include <openthread/srp_client.h> #include <openthread/srp_client_buffers.h> +#include <openthread/instance.h> #include <openthread/thread.h> #include <optional> @@ -26,7 +27,7 @@ class OpenThreadComponent : public Component { bool teardown() override; float get_setup_priority() const override { return setup_priority::WIFI; } - bool is_connected(); + bool is_connected() const { return this->connected_; } network::IPAddresses get_ip_addresses(); std::optional<otIp6Address> get_omr_address(); void ot_main(); @@ -42,6 +43,7 @@ class OpenThreadComponent : public Component { protected: std::optional<otIp6Address> get_omr_address_(InstanceLock &lock); + static void on_state_changed_(otChangedFlags flags, void *context); std::function<void()> factory_reset_external_callback_; #if CONFIG_OPENTHREAD_MTD uint32_t poll_period_{0}; @@ -49,6 +51,7 @@ class OpenThreadComponent : public Component { std::optional<int8_t> output_power_{}; bool teardown_started_{false}; bool teardown_complete_{false}; + bool connected_{false}; private: // Stores a pointer to a string literal (static storage duration). diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 2af78b729f..2296e32b7f 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -175,6 +175,9 @@ void OpenThreadComponent::ot_main() { // Pass the existing dataset, or NULL which will use the preprocessor definitions ESP_ERROR_CHECK(esp_openthread_auto_start(dataset.mLength > 0 ? &dataset : nullptr)); + // Register state change callback to update connected_ reactively instead of polling + otSetStateChangedCallback(instance, OpenThreadComponent::on_state_changed_, this); + esp_openthread_launch_mainloop(); // Clean up From c49c23d5d90ef0d4463479ffe8a2038252405d4f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Mar 2026 07:21:04 -1000 Subject: [PATCH 1111/2030] [network] Inline network::is_connected() and ethernet is_connected() (#14464) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../ethernet/ethernet_component.cpp | 2 - .../components/ethernet/ethernet_component.h | 2 +- esphome/components/network/util.cpp | 44 +----------------- esphome/components/network/util.h | 45 ++++++++++++++++++- 4 files changed, 46 insertions(+), 47 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index f855bc89cc..098f7be972 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -687,8 +687,6 @@ void EthernetComponent::start_connect_() { this->status_set_warning(); } -bool EthernetComponent::is_connected() { return this->state_ == EthernetComponentState::CONNECTED; } - void EthernetComponent::dump_connect_params_() { esp_netif_ip_info_t ip; esp_netif_get_ip_info(this->eth_netif_, &ip); diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 1cd44d2b2c..f5a31d78eb 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -76,7 +76,7 @@ class EthernetComponent : public Component { void dump_config() override; float get_setup_priority() const override; void on_powerdown() override { powerdown(); } - bool is_connected(); + bool is_connected() { return this->state_ == EthernetComponentState::CONNECTED; } #ifdef USE_ETHERNET_SPI void set_clk_pin(uint8_t clk_pin); diff --git a/esphome/components/network/util.cpp b/esphome/components/network/util.cpp index e397d77077..226b11b8cd 100644 --- a/esphome/components/network/util.cpp +++ b/esphome/components/network/util.cpp @@ -1,53 +1,11 @@ #include "util.h" #include "esphome/core/defines.h" #ifdef USE_NETWORK -#ifdef USE_WIFI -#include "esphome/components/wifi/wifi_component.h" -#endif - -#ifdef USE_ETHERNET -#include "esphome/components/ethernet/ethernet_component.h" -#endif - -#ifdef USE_OPENTHREAD -#include "esphome/components/openthread/openthread.h" -#endif - -#ifdef USE_MODEM -#include "esphome/components/modem/modem_component.h" -#endif namespace esphome::network { // The order of the components is important: WiFi should come after any possible main interfaces (it may be used as -// an AP that use a previous interface for NAT). - -bool is_connected() { -#ifdef USE_ETHERNET - if (ethernet::global_eth_component != nullptr && ethernet::global_eth_component->is_connected()) - return true; -#endif - -#ifdef USE_MODEM - if (modem::global_modem_component != nullptr) - return modem::global_modem_component->is_connected(); -#endif - -#ifdef USE_WIFI - if (wifi::global_wifi_component != nullptr) - return wifi::global_wifi_component->is_connected(); -#endif - -#ifdef USE_OPENTHREAD - if (openthread::global_openthread_component != nullptr) - return openthread::global_openthread_component->is_connected(); -#endif - -#ifdef USE_HOST - return true; // Assume its connected -#endif - return false; -} +// an AP that uses a previous interface for NAT). bool is_disabled() { #ifdef USE_MODEM diff --git a/esphome/components/network/util.h b/esphome/components/network/util.h index ae949ab0a8..4b700fe74c 100644 --- a/esphome/components/network/util.h +++ b/esphome/components/network/util.h @@ -2,12 +2,55 @@ #include "esphome/core/defines.h" #ifdef USE_NETWORK #include <string> +#include "esphome/core/helpers.h" #include "ip_address.h" +#ifdef USE_ETHERNET +#include "esphome/components/ethernet/ethernet_component.h" +#endif +#ifdef USE_MODEM +#include "esphome/components/modem/modem_component.h" +#endif +#ifdef USE_WIFI +#include "esphome/components/wifi/wifi_component.h" +#endif +#ifdef USE_OPENTHREAD +#include "esphome/components/openthread/openthread.h" +#endif + namespace esphome::network { +// The order of the components is important: WiFi should come after any possible main interfaces (it may be used as +// an AP that uses a previous interface for NAT). + /// Return whether the node is connected to the network (through wifi, eth, ...) -bool is_connected(); +ESPHOME_ALWAYS_INLINE inline bool is_connected() { +#ifdef USE_ETHERNET + if (ethernet::global_eth_component != nullptr && ethernet::global_eth_component->is_connected()) + return true; +#endif + +#ifdef USE_MODEM + if (modem::global_modem_component != nullptr) + return modem::global_modem_component->is_connected(); +#endif + +#ifdef USE_WIFI + if (wifi::global_wifi_component != nullptr) + return wifi::global_wifi_component->is_connected(); +#endif + +#ifdef USE_OPENTHREAD + if (openthread::global_openthread_component != nullptr) + return openthread::global_openthread_component->is_connected(); +#endif + +#ifdef USE_HOST + return true; // Assume it's connected +#endif + return false; +} + /// Return whether the network is disabled (only wifi for now) bool is_disabled(); /// Get the active network hostname From 2777d359904e117190e10f353c3601e67012478f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Mar 2026 07:21:44 -1000 Subject: [PATCH 1112/2030] [api] Devirtualize frame helper calls when protocol is fixed at compile time (#14468) --- esphome/components/api/api_connection.cpp | 5 +++-- esphome/components/api/api_connection.h | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 59476fac25..98ba1abe0b 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -114,9 +114,10 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))}; } #elif defined(USE_API_PLAINTEXT) - this->helper_ = std::unique_ptr<APIFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))}; + this->helper_ = std::unique_ptr<APIPlaintextFrameHelper>{new APIPlaintextFrameHelper(std::move(sock))}; #elif defined(USE_API_NOISE) - this->helper_ = std::unique_ptr<APIFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())}; + this->helper_ = + std::unique_ptr<APINoiseFrameHelper>{new APINoiseFrameHelper(std::move(sock), parent->get_noise_ctx())}; #else #error "No frame helper defined" #endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 37855b2482..aae8db3c68 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -3,6 +3,12 @@ #include "esphome/core/defines.h" #ifdef USE_API #include "api_frame_helper.h" +#ifdef USE_API_NOISE +#include "api_frame_helper_noise.h" +#endif +#ifdef USE_API_PLAINTEXT +#include "api_frame_helper_plaintext.h" +#endif #include "api_pb2.h" #include "api_pb2_service.h" #include "api_server.h" @@ -489,7 +495,13 @@ class APIConnection final : public APIServerConnectionBase { // === Optimal member ordering for 32-bit systems === // Group 1: Pointers (4 bytes each on 32-bit) +#if defined(USE_API_NOISE) && defined(USE_API_PLAINTEXT) std::unique_ptr<APIFrameHelper> helper_; +#elif defined(USE_API_NOISE) + std::unique_ptr<APINoiseFrameHelper> helper_; +#elif defined(USE_API_PLAINTEXT) + std::unique_ptr<APIPlaintextFrameHelper> helper_; +#endif APIServer *parent_; // Group 2: Iterator union (saves ~16 bytes vs separate iterators) From a061397469da387ea8086fb494fcfe61861c222b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:16:06 -0500 Subject: [PATCH 1113/2030] [dfrobot_sen0395][sx1509] Fix structural bugs (#14494) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/dfrobot_sen0395/commands.h | 14 ++++++-------- esphome/components/sx1509/sx1509.cpp | 6 +++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/dfrobot_sen0395/commands.h b/esphome/components/dfrobot_sen0395/commands.h index 3b0551b184..95167efb4d 100644 --- a/esphome/components/dfrobot_sen0395/commands.h +++ b/esphome/components/dfrobot_sen0395/commands.h @@ -30,11 +30,9 @@ class Command { class ReadStateCommand : public Command { public: + ReadStateCommand() { timeout_ms_ = 500; } uint8_t execute(DfrobotSen0395Component *parent) override; uint8_t on_message(std::string &message) override; - - protected: - uint32_t timeout_ms_{500}; }; class PowerCommand : public Command { @@ -99,12 +97,12 @@ class ResetSystemCommand : public Command { class SaveCfgCommand : public Command { public: - SaveCfgCommand() { cmd_ = "saveCfg 0x45670123 0xCDEF89AB 0x956128C6 0xDF54AC89"; } + SaveCfgCommand() { + cmd_ = "saveCfg 0x45670123 0xCDEF89AB 0x956128C6 0xDF54AC89"; + cmd_duration_ms_ = 3000; + timeout_ms_ = 3500; + } uint8_t on_message(std::string &message) override; - - protected: - uint32_t cmd_duration_ms_{3000}; - uint32_t timeout_ms_{3500}; }; class LedModeCommand : public Command { diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp index 746ec9cda3..dfe1277297 100644 --- a/esphome/components/sx1509/sx1509.cpp +++ b/esphome/components/sx1509/sx1509.cpp @@ -56,11 +56,11 @@ void SX1509Component::loop() { return; } int row, col; - for (row = 0; row < 7; row++) { + for (row = 0; row < 8; row++) { if (key_data & (1 << row)) break; } - for (col = 8; col < 15; col++) { + for (col = 8; col < 16; col++) { if (key_data & (1 << col)) break; } @@ -229,7 +229,7 @@ void SX1509Component::setup_keypad_() { this->read_byte_16(REG_DIR_B, &this->ddr_mask_); for (int i = 0; i < this->rows_; i++) this->ddr_mask_ &= ~(1 << i); - for (int i = 8; i < (this->cols_ * 2); i++) + for (int i = 8; i < (8 + this->cols_); i++) this->ddr_mask_ |= (1 << i); this->write_byte_16(REG_DIR_B, this->ddr_mask_); From 01f4275202a8e9e82b2b7486ceefe18f5ffa1238 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:16:33 -0500 Subject: [PATCH 1114/2030] [veml7700] Fix initial settling timeout using raw enum instead of milliseconds (#14487) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/veml7700/veml7700.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/veml7700/veml7700.cpp b/esphome/components/veml7700/veml7700.cpp index eb286ba21b..1ed484119b 100644 --- a/esphome/components/veml7700/veml7700.cpp +++ b/esphome/components/veml7700/veml7700.cpp @@ -141,7 +141,7 @@ void VEML7700Component::loop() { // Datasheet: 2.5 ms before the first measurement is needed, allowing for the correct start of the signal processor // and oscillator. // Reality: wait for couple integration times to have first samples captured - this->set_timeout(2 * this->integration_time_, [this]() { this->state_ = State::IDLE; }); + this->set_timeout(2 * get_itime_ms(this->integration_time_), [this]() { this->state_ = State::IDLE; }); } if (this->is_ready()) { From 3df4ef9362cb7843f91c28cb2cfef1691dac8c52 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:31:26 -0500 Subject: [PATCH 1115/2030] [ssd1322][ssd1325][ssd1327] Fix nibble mask bug in grayscale draw_pixel (#14496) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ssd1322_base/ssd1322_base.cpp | 2 +- esphome/components/ssd1325_base/ssd1325_base.cpp | 2 +- esphome/components/ssd1327_base/ssd1327_base.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/ssd1322_base/ssd1322_base.cpp b/esphome/components/ssd1322_base/ssd1322_base.cpp index 23576e7b2c..1fce826ad9 100644 --- a/esphome/components/ssd1322_base/ssd1322_base.cpp +++ b/esphome/components/ssd1322_base/ssd1322_base.cpp @@ -169,7 +169,7 @@ void HOT SSD1322::draw_absolute_pixel_internal(int x, int y, Color color) { // ensure 'color4' is valid (only 4 bits aka 1 nibble) and shift the bits left when necessary color4 = (color4 & SSD1322_COLORMASK) << shift; // first mask off the nibble we must change... - this->buffer_[pos] &= (~SSD1322_COLORMASK >> shift); + this->buffer_[pos] &= (static_cast<uint8_t>(~SSD1322_COLORMASK) >> shift); // ...then lay the new nibble back on top. done! this->buffer_[pos] |= color4; } diff --git a/esphome/components/ssd1325_base/ssd1325_base.cpp b/esphome/components/ssd1325_base/ssd1325_base.cpp index e7d2386ac7..fe7df9674b 100644 --- a/esphome/components/ssd1325_base/ssd1325_base.cpp +++ b/esphome/components/ssd1325_base/ssd1325_base.cpp @@ -202,7 +202,7 @@ void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, Color color) { // ensure 'color4' is valid (only 4 bits aka 1 nibble) and shift the bits left when necessary color4 = (color4 & SSD1325_COLORMASK) << shift; // first mask off the nibble we must change... - this->buffer_[pos] &= (~SSD1325_COLORMASK >> shift); + this->buffer_[pos] &= (static_cast<uint8_t>(~SSD1325_COLORMASK) >> shift); // ...then lay the new nibble back on top. done! this->buffer_[pos] |= color4; } diff --git a/esphome/components/ssd1327_base/ssd1327_base.cpp b/esphome/components/ssd1327_base/ssd1327_base.cpp index 2498bfcd67..87e52206f2 100644 --- a/esphome/components/ssd1327_base/ssd1327_base.cpp +++ b/esphome/components/ssd1327_base/ssd1327_base.cpp @@ -145,7 +145,7 @@ void HOT SSD1327::draw_absolute_pixel_internal(int x, int y, Color color) { // ensure 'color4' is valid (only 4 bits aka 1 nibble) and shift the bits left when necessary color4 = (color4 & SSD1327_COLORMASK) << shift; // first mask off the nibble we must change... - this->buffer_[pos] &= (~SSD1327_COLORMASK >> shift); + this->buffer_[pos] &= (static_cast<uint8_t>(~SSD1327_COLORMASK) >> shift); // ...then lay the new nibble back on top. done! this->buffer_[pos] |= color4; } From 4a5d8449fd28aa80b801dc270a3f2e9e20344794 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 13:33:12 -0500 Subject: [PATCH 1116/2030] [sht4x][grove_tb6612fng] Fix logic bugs (#14497) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/grove_tb6612fng/grove_tb6612fng.cpp | 2 +- esphome/components/sht4x/sht4x.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp b/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp index a249984647..428c8ec4a8 100644 --- a/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +++ b/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp @@ -131,7 +131,7 @@ void GroveMotorDriveTB6612FNG::stepper_run(StepperModeTypeT mode, int16_t steps, buffer_[4] = ms_per_step; buffer_[5] = (ms_per_step >> 8); - if (this->write_register(GROVE_MOTOR_DRIVER_I2C_CMD_STEPPER_RUN, buffer_, 1) != i2c::ERROR_OK) { + if (this->write_register(GROVE_MOTOR_DRIVER_I2C_CMD_STEPPER_RUN, buffer_, 6) != i2c::ERROR_OK) { ESP_LOGW(TAG, "Run stepper failed!"); this->status_set_warning(); return; diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 9d29746f0b..42be326202 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -10,7 +10,7 @@ static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0}; static const uint8_t SERIAL_NUMBER_COMMAND = 0x89; void SHT4XComponent::start_heater_() { - uint8_t cmd[] = {MEASURECOMMANDS[this->heater_command_]}; + uint8_t cmd[] = {this->heater_command_}; ESP_LOGD(TAG, "Heater turning on"); if (this->write(cmd, 1) != i2c::ERROR_OK) { From 9518d88a2aa7a5f7d5b263ffabeddeebd8f9d17d Mon Sep 17 00:00:00 2001 From: rwrozelle <rwrozelle@gmail.com> Date: Thu, 5 Mar 2026 10:35:20 -0800 Subject: [PATCH 1117/2030] [openthread] static log level code quality improvement (#14456) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/openthread/__init__.py | 21 +++++++++++++++++++ .../openthread/test.esp32-c6-idf.yaml | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/esphome/components/openthread/__init__.py b/esphome/components/openthread/__init__.py index 5c64cf31dc..21373b77df 100644 --- a/esphome/components/openthread/__init__.py +++ b/esphome/components/openthread/__init__.py @@ -14,9 +14,12 @@ import esphome.config_validation as cv from esphome.const import ( CONF_CHANNEL, CONF_ENABLE_IPV6, + CONF_FRAMEWORK, CONF_ID, + CONF_LOG_LEVEL, CONF_OUTPUT_POWER, CONF_USE_ADDRESS, + PLATFORM_ESP32, ) from esphome.core import CORE, TimePeriodMilliseconds import esphome.final_validate as fv @@ -46,6 +49,15 @@ AUTO_LOAD = ["network"] CONFLICTS_WITH = ["wifi"] DEPENDENCIES = ["esp32"] +IDF_TO_OT_LOG_LEVEL = { + "NONE": "NONE", + "ERROR": "CRIT", + "WARN": "WARN", + "INFO": "NOTE", + "DEBUG": "INFO", + "VERBOSE": "DEBG", +} + CONF_DEVICE_TYPES = [ "FTD", "MTD", @@ -198,6 +210,15 @@ def _final_validate(_): "Please set `enable_ipv6: true` in the `network` configuration." ) + if ( + (esp32_config := full_config.get(PLATFORM_ESP32)) is not None + and (fw_config := esp32_config.get(CONF_FRAMEWORK)) is not None + and (log_level := fw_config.get(CONF_LOG_LEVEL)) is not None + ): + add_idf_sdkconfig_option("CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC", False) + ot_log_level = IDF_TO_OT_LOG_LEVEL.get(log_level, log_level) + add_idf_sdkconfig_option(f"CONFIG_OPENTHREAD_LOG_LEVEL_{ot_log_level}", True) + FINAL_VALIDATE_SCHEMA = _final_validate diff --git a/tests/components/openthread/test.esp32-c6-idf.yaml b/tests/components/openthread/test.esp32-c6-idf.yaml index 77abc433c1..008edd5397 100644 --- a/tests/components/openthread/test.esp32-c6-idf.yaml +++ b/tests/components/openthread/test.esp32-c6-idf.yaml @@ -1,3 +1,9 @@ +esp32: + board: esp32-c6-devkitc-1 + framework: + type: esp-idf + log_level: DEBUG + network: enable_ipv6: true From e1d0c6da09ecad433c77ff8efdad60c730f020d8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:09:23 -0500 Subject: [PATCH 1118/2030] [dfplayer][ufire_ise][ufire_ec][qmp6988][atm90e26] Fix wrong operators and masks (#14491) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/atm90e26/atm90e26.cpp | 2 +- esphome/components/dfplayer/dfplayer.cpp | 1 + esphome/components/qmp6988/qmp6988.cpp | 2 +- esphome/components/ufire_ec/ufire_ec.cpp | 2 +- esphome/components/ufire_ise/ufire_ise.cpp | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/atm90e26/atm90e26.cpp b/esphome/components/atm90e26/atm90e26.cpp index 2203dd0d71..e6602411bb 100644 --- a/esphome/components/atm90e26/atm90e26.cpp +++ b/esphome/components/atm90e26/atm90e26.cpp @@ -197,7 +197,7 @@ float ATM90E26Component::get_reactive_power_() { float ATM90E26Component::get_power_factor_() { const uint16_t val = this->read16_(ATM90E26_REGISTER_POWERF); // signed if (val & 0x8000) { - return -(val & 0x7FF) / 1000.0f; + return -(val & 0x7FFF) / 1000.0f; } else { return val / 1000.0f; } diff --git a/esphome/components/dfplayer/dfplayer.cpp b/esphome/components/dfplayer/dfplayer.cpp index 79f8fd03c3..1e1c33adaf 100644 --- a/esphome/components/dfplayer/dfplayer.cpp +++ b/esphome/components/dfplayer/dfplayer.cpp @@ -260,6 +260,7 @@ void DFPlayer::loop() { ESP_LOGV(TAG, "Playback finished (USB drive)"); this->is_playing_ = false; this->on_finished_playback_callback_.call(); + break; case 0x3D: ESP_LOGV(TAG, "Playback finished (SD card)"); this->is_playing_ = false; diff --git a/esphome/components/qmp6988/qmp6988.cpp b/esphome/components/qmp6988/qmp6988.cpp index 24fe34e785..17d91c3633 100644 --- a/esphome/components/qmp6988/qmp6988.cpp +++ b/esphome/components/qmp6988/qmp6988.cpp @@ -251,7 +251,7 @@ void QMP6988Component::set_power_mode_(uint8_t power_mode) { void QMP6988Component::write_filter_(QMP6988IIRFilter filter) { uint8_t data; - data = (filter & 0x03); + data = (filter & QMP6988_CONFIG_REG_FILTER_MSK); this->write_byte(QMP6988_CONFIG_REG, data); delay(10); } diff --git a/esphome/components/ufire_ec/ufire_ec.cpp b/esphome/components/ufire_ec/ufire_ec.cpp index 3868dc92b7..a1c3568a1a 100644 --- a/esphome/components/ufire_ec/ufire_ec.cpp +++ b/esphome/components/ufire_ec/ufire_ec.cpp @@ -8,7 +8,7 @@ static const char *const TAG = "ufire_ec"; void UFireECComponent::setup() { uint8_t version; - if (!this->read_byte(REGISTER_VERSION, &version) && version != 0xFF) { + if (!this->read_byte(REGISTER_VERSION, &version) || version == 0xFF) { this->mark_failed(); return; } diff --git a/esphome/components/ufire_ise/ufire_ise.cpp b/esphome/components/ufire_ise/ufire_ise.cpp index 486a506391..e967fc53c3 100644 --- a/esphome/components/ufire_ise/ufire_ise.cpp +++ b/esphome/components/ufire_ise/ufire_ise.cpp @@ -10,7 +10,7 @@ static const char *const TAG = "ufire_ise"; void UFireISEComponent::setup() { uint8_t version; - if (!this->read_byte(REGISTER_VERSION, &version) && version != 0xFF) { + if (!this->read_byte(REGISTER_VERSION, &version) || version == 0xFF) { this->mark_failed(); return; } From cce7a09fa995692dae38a4fdecc34bd297c167a0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:09:34 -0500 Subject: [PATCH 1119/2030] [pn532_spi] Fix preamble check logic and OOB access when full_len is zero (#14486) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/pn532_spi/pn532_spi.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/pn532_spi/pn532_spi.cpp b/esphome/components/pn532_spi/pn532_spi.cpp index 118421c47f..553c6d26a6 100644 --- a/esphome/components/pn532_spi/pn532_spi.cpp +++ b/esphome/components/pn532_spi/pn532_spi.cpp @@ -88,9 +88,10 @@ bool PN532Spi::read_response(uint8_t command, std::vector<uint8_t> &data) { #endif ESP_LOGV(TAG, "Header data: %s", format_hex_pretty_to(hex_buf, sizeof(hex_buf), header.data(), header.size())); - if (header[0] != 0x00 && header[1] != 0x00 && header[2] != 0xFF) { + if (header[0] != 0x00 || header[1] != 0x00 || header[2] != 0xFF) { // invalid packet ESP_LOGV(TAG, "read data invalid preamble!"); + this->disable(); return false; } @@ -100,15 +101,20 @@ bool PN532Spi::read_response(uint8_t command, std::vector<uint8_t> &data) { if (!valid_header) { ESP_LOGV(TAG, "read data invalid header!"); + this->disable(); return false; } - // full length of message, including command response + // full length of message, including command response (minimum 2: TFI + command response) uint8_t full_len = header[3]; + if (full_len < 2) { + ESP_LOGV(TAG, "read data has no payload"); + this->disable(); + return false; + } + // length of data, excluding command response uint8_t len = full_len - 1; - if (full_len == 0) - len = 0; ESP_LOGV(TAG, "Reading response of length %d", len); From e210e414bd0ed93c678ecdc3e8895918a517716d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Mar 2026 09:15:02 -1000 Subject: [PATCH 1120/2030] [ota] Devirtualize OTA backend calls (#14473) --- esphome/components/esphome/ota/ota_esphome.h | 4 +-- .../http_request/ota/ota_http_request.cpp | 7 +---- .../http_request/ota/ota_http_request.h | 4 +-- esphome/components/ota/ota_backend.h | 13 --------- .../ota/ota_backend_arduino_libretiny.cpp | 2 +- .../ota/ota_backend_arduino_libretiny.h | 16 ++++++----- .../ota/ota_backend_arduino_rp2040.cpp | 2 +- .../ota/ota_backend_arduino_rp2040.h | 16 ++++++----- .../components/ota/ota_backend_esp8266.cpp | 2 +- esphome/components/ota/ota_backend_esp8266.h | 16 ++++++----- .../components/ota/ota_backend_esp_idf.cpp | 2 +- esphome/components/ota/ota_backend_esp_idf.h | 16 ++++++----- esphome/components/ota/ota_backend_factory.h | 27 +++++++++++++++++++ esphome/components/ota/ota_backend_host.cpp | 2 +- esphome/components/ota/ota_backend_host.h | 16 ++++++----- .../web_server/ota/ota_web_server.cpp | 4 +-- 16 files changed, 84 insertions(+), 65 deletions(-) create mode 100644 esphome/components/ota/ota_backend_factory.h diff --git a/esphome/components/esphome/ota/ota_esphome.h b/esphome/components/esphome/ota/ota_esphome.h index 08edacad92..f3a5952398 100644 --- a/esphome/components/esphome/ota/ota_esphome.h +++ b/esphome/components/esphome/ota/ota_esphome.h @@ -2,7 +2,7 @@ #include "esphome/core/defines.h" #ifdef USE_OTA -#include "esphome/components/ota/ota_backend.h" +#include "esphome/components/ota/ota_backend_factory.h" #include "esphome/components/socket/socket.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -86,7 +86,7 @@ class ESPHomeOTAComponent final : public ota::OTAComponent { socket::ListenSocket *server_{nullptr}; std::unique_ptr<socket::Socket> client_; - std::unique_ptr<ota::OTABackend> backend_; + ota::OTABackendPtr backend_; uint32_t client_connect_time_{0}; uint16_t port_; diff --git a/esphome/components/http_request/ota/ota_http_request.cpp b/esphome/components/http_request/ota/ota_http_request.cpp index 0db3a50b47..5dd21c314c 100644 --- a/esphome/components/http_request/ota/ota_http_request.cpp +++ b/esphome/components/http_request/ota/ota_http_request.cpp @@ -8,10 +8,6 @@ #include "esphome/components/md5/md5.h" #include "esphome/components/watchdog/watchdog.h" -#include "esphome/components/ota/ota_backend.h" -#include "esphome/components/ota/ota_backend_esp8266.h" -#include "esphome/components/ota/ota_backend_arduino_rp2040.h" -#include "esphome/components/ota/ota_backend_esp_idf.h" namespace esphome { namespace http_request { @@ -69,8 +65,7 @@ void OtaHttpRequestComponent::flash() { } } -void OtaHttpRequestComponent::cleanup_(std::unique_ptr<ota::OTABackend> backend, - const std::shared_ptr<HttpContainer> &container) { +void OtaHttpRequestComponent::cleanup_(ota::OTABackendPtr backend, const std::shared_ptr<HttpContainer> &container) { if (this->update_started_) { ESP_LOGV(TAG, "Aborting OTA backend"); backend->abort(); diff --git a/esphome/components/http_request/ota/ota_http_request.h b/esphome/components/http_request/ota/ota_http_request.h index 6d39b0d466..70e4559fa7 100644 --- a/esphome/components/http_request/ota/ota_http_request.h +++ b/esphome/components/http_request/ota/ota_http_request.h @@ -1,6 +1,6 @@ #pragma once -#include "esphome/components/ota/ota_backend.h" +#include "esphome/components/ota/ota_backend_factory.h" #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" @@ -39,7 +39,7 @@ class OtaHttpRequestComponent final : public ota::OTAComponent, public Parented< void flash(); protected: - void cleanup_(std::unique_ptr<ota::OTABackend> backend, const std::shared_ptr<HttpContainer> &container); + void cleanup_(ota::OTABackendPtr backend, const std::shared_ptr<HttpContainer> &container); uint8_t do_ota_(); std::string get_url_with_auth_(const std::string &url); bool http_get_md5_(); diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index e03afd4fc6..bc603a6e9e 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -49,17 +49,6 @@ enum OTAState { OTA_ERROR, }; -class OTABackend { - public: - virtual ~OTABackend() = default; - virtual OTAResponseTypes begin(size_t image_size) = 0; - virtual void set_update_md5(const char *md5) = 0; - virtual OTAResponseTypes write(uint8_t *data, size_t len) = 0; - virtual OTAResponseTypes end() = 0; - virtual void abort() = 0; - virtual bool supports_compression() = 0; -}; - /** Listener interface for OTA state changes. * * Components can implement this interface to receive OTA state updates @@ -130,7 +119,5 @@ OTAGlobalCallback *get_global_ota_callback(); // - notify_state_deferred_() when in separate task (e.g., web_server OTA) // This ensures proper listener execution in all contexts. #endif -std::unique_ptr<ota::OTABackend> make_ota_backend(); - } // namespace ota } // namespace esphome diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index b4ecad1227..d364f75007 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -12,7 +12,7 @@ namespace ota { static const char *const TAG = "ota.arduino_libretiny"; -std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoLibreTinyOTABackend>(); } +std::unique_ptr<ArduinoLibreTinyOTABackend> make_ota_backend() { return make_unique<ArduinoLibreTinyOTABackend>(); } OTAResponseTypes ArduinoLibreTinyOTABackend::begin(size_t image_size) { // Handle UPDATE_SIZE_UNKNOWN (0) which is used by web server OTA diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.h b/esphome/components/ota/ota_backend_arduino_libretiny.h index 8f9d268eec..4514bf84bd 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.h +++ b/esphome/components/ota/ota_backend_arduino_libretiny.h @@ -7,19 +7,21 @@ namespace esphome { namespace ota { -class ArduinoLibreTinyOTABackend final : public OTABackend { +class ArduinoLibreTinyOTABackend final { public: - OTAResponseTypes begin(size_t image_size) override; - void set_update_md5(const char *md5) override; - OTAResponseTypes write(uint8_t *data, size_t len) override; - OTAResponseTypes end() override; - void abort() override; - bool supports_compression() override { return false; } + OTAResponseTypes begin(size_t image_size); + void set_update_md5(const char *md5); + OTAResponseTypes write(uint8_t *data, size_t len); + OTAResponseTypes end(); + void abort(); + bool supports_compression() { return false; } private: bool md5_set_{false}; }; +std::unique_ptr<ArduinoLibreTinyOTABackend> make_ota_backend(); + } // namespace ota } // namespace esphome diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index ee1ba48d50..e2a57ec665 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -14,7 +14,7 @@ namespace ota { static const char *const TAG = "ota.arduino_rp2040"; -std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ArduinoRP2040OTABackend>(); } +std::unique_ptr<ArduinoRP2040OTABackend> make_ota_backend() { return make_unique<ArduinoRP2040OTABackend>(); } OTAResponseTypes ArduinoRP2040OTABackend::begin(size_t image_size) { // OTA size of 0 is not currently handled, but diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.h b/esphome/components/ota/ota_backend_arduino_rp2040.h index 6a708f9c57..0956cb4b4b 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.h +++ b/esphome/components/ota/ota_backend_arduino_rp2040.h @@ -9,19 +9,21 @@ namespace esphome { namespace ota { -class ArduinoRP2040OTABackend final : public OTABackend { +class ArduinoRP2040OTABackend final { public: - OTAResponseTypes begin(size_t image_size) override; - void set_update_md5(const char *md5) override; - OTAResponseTypes write(uint8_t *data, size_t len) override; - OTAResponseTypes end() override; - void abort() override; - bool supports_compression() override { return false; } + OTAResponseTypes begin(size_t image_size); + void set_update_md5(const char *md5); + OTAResponseTypes write(uint8_t *data, size_t len); + OTAResponseTypes end(); + void abort(); + bool supports_compression() { return false; } private: bool md5_set_{false}; }; +std::unique_ptr<ArduinoRP2040OTABackend> make_ota_backend(); + } // namespace ota } // namespace esphome diff --git a/esphome/components/ota/ota_backend_esp8266.cpp b/esphome/components/ota/ota_backend_esp8266.cpp index 4b84708cd9..1f9a77e426 100644 --- a/esphome/components/ota/ota_backend_esp8266.cpp +++ b/esphome/components/ota/ota_backend_esp8266.cpp @@ -48,7 +48,7 @@ namespace esphome::ota { static const char *const TAG = "ota.esp8266"; -std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::ESP8266OTABackend>(); } +std::unique_ptr<ESP8266OTABackend> make_ota_backend() { return make_unique<ESP8266OTABackend>(); } OTAResponseTypes ESP8266OTABackend::begin(size_t image_size) { // Handle UPDATE_SIZE_UNKNOWN (0) by calculating available space diff --git a/esphome/components/ota/ota_backend_esp8266.h b/esphome/components/ota/ota_backend_esp8266.h index 52f657f006..6213289acc 100644 --- a/esphome/components/ota/ota_backend_esp8266.h +++ b/esphome/components/ota/ota_backend_esp8266.h @@ -12,15 +12,15 @@ namespace esphome::ota { /// OTA backend for ESP8266 using native SDK functions. /// This implementation bypasses the Arduino Updater library to save ~228 bytes of RAM /// by not having a global Update object in .bss. -class ESP8266OTABackend final : public OTABackend { +class ESP8266OTABackend final { public: - OTAResponseTypes begin(size_t image_size) override; - void set_update_md5(const char *md5) override; - OTAResponseTypes write(uint8_t *data, size_t len) override; - OTAResponseTypes end() override; - void abort() override; + OTAResponseTypes begin(size_t image_size); + void set_update_md5(const char *md5); + OTAResponseTypes write(uint8_t *data, size_t len); + OTAResponseTypes end(); + void abort(); // Compression supported in all ESP8266 Arduino versions ESPHome supports (>= 2.7.0) - bool supports_compression() override { return true; } + bool supports_compression() { return true; } protected: /// Erase flash sector if current address is at sector boundary @@ -54,5 +54,7 @@ class ESP8266OTABackend final : public OTABackend { bool md5_set_{false}; }; +std::unique_ptr<ESP8266OTABackend> make_ota_backend(); + } // namespace esphome::ota #endif // USE_ESP8266 diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index 93c65a9624..925bb39645 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -11,7 +11,7 @@ namespace esphome { namespace ota { -std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::IDFOTABackend>(); } +std::unique_ptr<IDFOTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); } OTAResponseTypes IDFOTABackend::begin(size_t image_size) { #ifdef USE_OTA_ROLLBACK diff --git a/esphome/components/ota/ota_backend_esp_idf.h b/esphome/components/ota/ota_backend_esp_idf.h index 7f7f6115c5..a0f538afc0 100644 --- a/esphome/components/ota/ota_backend_esp_idf.h +++ b/esphome/components/ota/ota_backend_esp_idf.h @@ -10,14 +10,14 @@ namespace esphome { namespace ota { -class IDFOTABackend final : public OTABackend { +class IDFOTABackend final { public: - OTAResponseTypes begin(size_t image_size) override; - void set_update_md5(const char *md5) override; - OTAResponseTypes write(uint8_t *data, size_t len) override; - OTAResponseTypes end() override; - void abort() override; - bool supports_compression() override { return false; } + OTAResponseTypes begin(size_t image_size); + void set_update_md5(const char *md5); + OTAResponseTypes write(uint8_t *data, size_t len); + OTAResponseTypes end(); + void abort(); + bool supports_compression() { return false; } private: esp_ota_handle_t update_handle_{0}; @@ -27,6 +27,8 @@ class IDFOTABackend final : public OTABackend { bool md5_set_{false}; }; +std::unique_ptr<IDFOTABackend> make_ota_backend(); + } // namespace ota } // namespace esphome #endif // USE_ESP32 diff --git a/esphome/components/ota/ota_backend_factory.h b/esphome/components/ota/ota_backend_factory.h new file mode 100644 index 0000000000..7c79f02702 --- /dev/null +++ b/esphome/components/ota/ota_backend_factory.h @@ -0,0 +1,27 @@ +#pragma once + +#include "ota_backend.h" + +#include <memory> + +#ifdef USE_ESP8266 +#include "ota_backend_esp8266.h" +#elif defined(USE_ESP32) +#include "ota_backend_esp_idf.h" +#elif defined(USE_RP2040) +#include "ota_backend_arduino_rp2040.h" +#elif defined(USE_LIBRETINY) +#include "ota_backend_arduino_libretiny.h" +#elif defined(USE_HOST) +#include "ota_backend_host.h" +#else +// Stub for static analysis when no platform is defined +namespace esphome::ota { +struct StubOTABackend {}; +std::unique_ptr<StubOTABackend> make_ota_backend(); +} // namespace esphome::ota +#endif + +namespace esphome::ota { +using OTABackendPtr = decltype(make_ota_backend()); +} // namespace esphome::ota diff --git a/esphome/components/ota/ota_backend_host.cpp b/esphome/components/ota/ota_backend_host.cpp index ddab174bed..2e2132418d 100644 --- a/esphome/components/ota/ota_backend_host.cpp +++ b/esphome/components/ota/ota_backend_host.cpp @@ -8,7 +8,7 @@ namespace esphome::ota { // Stub implementation - OTA is not supported on host platform. // All methods return error codes to allow compilation of configs with OTA triggers. -std::unique_ptr<ota::OTABackend> make_ota_backend() { return make_unique<ota::HostOTABackend>(); } +std::unique_ptr<HostOTABackend> make_ota_backend() { return make_unique<HostOTABackend>(); } OTAResponseTypes HostOTABackend::begin(size_t image_size) { return OTA_RESPONSE_ERROR_UPDATE_PREPARE; } diff --git a/esphome/components/ota/ota_backend_host.h b/esphome/components/ota/ota_backend_host.h index 5a2dcfcf39..300facf72f 100644 --- a/esphome/components/ota/ota_backend_host.h +++ b/esphome/components/ota/ota_backend_host.h @@ -7,15 +7,17 @@ namespace esphome::ota { /// Stub OTA backend for host platform - allows compilation but does not implement OTA. /// All operations return error codes immediately. This enables configurations with /// OTA triggers to compile for host platform during development. -class HostOTABackend final : public OTABackend { +class HostOTABackend final { public: - OTAResponseTypes begin(size_t image_size) override; - void set_update_md5(const char *md5) override; - OTAResponseTypes write(uint8_t *data, size_t len) override; - OTAResponseTypes end() override; - void abort() override; - bool supports_compression() override { return false; } + OTAResponseTypes begin(size_t image_size); + void set_update_md5(const char *md5); + OTAResponseTypes write(uint8_t *data, size_t len); + OTAResponseTypes end(); + void abort(); + bool supports_compression() { return false; } }; +std::unique_ptr<HostOTABackend> make_ota_backend(); + } // namespace esphome::ota #endif diff --git a/esphome/components/web_server/ota/ota_web_server.cpp b/esphome/components/web_server/ota/ota_web_server.cpp index 4be162ccd3..95b166901a 100644 --- a/esphome/components/web_server/ota/ota_web_server.cpp +++ b/esphome/components/web_server/ota/ota_web_server.cpp @@ -1,7 +1,7 @@ #include "ota_web_server.h" #ifdef USE_WEBSERVER_OTA -#include "esphome/components/ota/ota_backend.h" +#include "esphome/components/ota/ota_backend_factory.h" #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -71,7 +71,7 @@ class OTARequestHandler : public AsyncWebHandler { bool ota_success_{false}; private: - std::unique_ptr<ota::OTABackend> ota_backend_{nullptr}; + ota::OTABackendPtr ota_backend_{nullptr}; }; void OTARequestHandler::report_ota_progress_(AsyncWebServerRequest *request) { From 44d314d069503831849c5d0de8e7839898f7eddd Mon Sep 17 00:00:00 2001 From: Olivier ARCHER <olivier.archer@gmail.com> Date: Thu, 5 Mar 2026 20:22:37 +0100 Subject: [PATCH 1121/2030] [GPS] fix component Python declaration to match C++ implementation (#14519) --- esphome/components/gps/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/gps/__init__.py b/esphome/components/gps/__init__.py index 045a5a6c84..ab48417a4e 100644 --- a/esphome/components/gps/__init__.py +++ b/esphome/components/gps/__init__.py @@ -34,7 +34,7 @@ AUTO_LOAD = ["sensor"] CODEOWNERS = ["@coogle", "@ximex"] gps_ns = cg.esphome_ns.namespace("gps") -GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice) +GPS = gps_ns.class_("GPS", cg.PollingComponent, uart.UARTDevice) GPSListener = gps_ns.class_("GPSListener") MULTI_CONF = True From 6f0460b0ee3b34469888ac249b18c5a269648d51 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:46:47 -0500 Subject: [PATCH 1122/2030] [sim800l][tormatic][tx20] Fix OOB access, div-by-zero, and off-by-one (#14512) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/sim800l/sim800l.cpp | 5 +++-- esphome/components/tormatic/tormatic_cover.cpp | 3 +++ esphome/components/tx20/tx20.cpp | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/esphome/components/sim800l/sim800l.cpp b/esphome/components/sim800l/sim800l.cpp index 2115c72cef..913d920c94 100644 --- a/esphome/components/sim800l/sim800l.cpp +++ b/esphome/components/sim800l/sim800l.cpp @@ -196,7 +196,8 @@ void Sim800LComponent::parse_cmd_(std::string message) { case STATE_CREG_WAIT: { // Response: "+CREG: 0,1" -- the one there means registered ok // "+CREG: -,-" means not registered ok - bool registered = message.compare(0, 6, "+CREG:") == 0 && (message[9] == '1' || message[9] == '5'); + bool registered = + message.size() > 9 && message.compare(0, 6, "+CREG:") == 0 && (message[9] == '1' || message[9] == '5'); if (registered) { if (!this->registered_) { ESP_LOGD(TAG, "Registered OK"); @@ -205,7 +206,7 @@ void Sim800LComponent::parse_cmd_(std::string message) { this->expect_ack_ = true; } else { ESP_LOGW(TAG, "Registration Fail"); - if (message[7] == '0') { // Network registration is disable, enable it + if (message.size() > 7 && message[7] == '0') { // Network registration is disabled, enable it send_cmd_("AT+CREG=1"); this->expect_ack_ = true; this->state_ = STATE_SETUP_CMGF; diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index f567be0674..37a269088e 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -183,6 +183,9 @@ void Tormatic::recompute_position_() { duration = this->close_duration_; } + if (duration == 0) + return; + auto delta = direction * diff / duration; this->position = clamp(this->position + delta, COVER_CLOSED, COVER_OPEN); diff --git a/esphome/components/tx20/tx20.cpp b/esphome/components/tx20/tx20.cpp index 6bc5f0bb51..3e0234fac0 100644 --- a/esphome/components/tx20/tx20.cpp +++ b/esphome/components/tx20/tx20.cpp @@ -191,7 +191,7 @@ void IRAM_ATTR Tx20ComponentStore::gpio_intr(Tx20ComponentStore *arg) { arg->tx20_available = true; return; } - if (index <= MAX_BUFFER_SIZE) { + if (index < MAX_BUFFER_SIZE) { arg->buffer[index] = delay; } arg->spent_time += delay; From 05ddc85412c8baf985e76015ed750407faa3d4e0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:46:56 -0500 Subject: [PATCH 1123/2030] [rc522][sml][kamstrup_kmp] Fix buffer bounds checks (#14515) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/kamstrup_kmp/kamstrup_kmp.cpp | 4 ++-- esphome/components/rc522/rc522.cpp | 1 + esphome/components/sml/sml_parser.cpp | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp index 00c65a1937..29de651255 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -136,7 +136,7 @@ void KamstrupKMPComponent::read_command_(uint16_t command) { int timeout = 250; // ms // Read the data from the UART - while (timeout > 0) { + while (timeout > 0 && buffer_len < static_cast<int>(sizeof(buffer))) { if (this->available()) { data = this->read(); if (data > -1) { @@ -246,7 +246,7 @@ void KamstrupKMPComponent::parse_command_message_(uint16_t command, const uint8_ } void KamstrupKMPComponent::set_sensor_value_(uint16_t command, float value, uint8_t unit_idx) { - const char *unit = UNITS[unit_idx]; + const char *unit = unit_idx < sizeof(UNITS) / sizeof(UNITS[0]) ? UNITS[unit_idx] : ""; // Standard sensors if (command == CMD_HEAT_ENERGY && this->heat_energy_sensor_ != nullptr) { diff --git a/esphome/components/rc522/rc522.cpp b/esphome/components/rc522/rc522.cpp index 91fae7fa34..c5f7ec2cd4 100644 --- a/esphome/components/rc522/rc522.cpp +++ b/esphome/components/rc522/rc522.cpp @@ -169,6 +169,7 @@ void RC522::loop() { default: ESP_LOGE(TAG, "uid_idx_ invalid, uid_idx_ = %d", uid_idx_); state_ = STATE_DONE; + return; } buffer_[1] = 32; pcd_transceive_data_(2); diff --git a/esphome/components/sml/sml_parser.cpp b/esphome/components/sml/sml_parser.cpp index 16e37949dc..ed086e385d 100644 --- a/esphome/components/sml/sml_parser.cpp +++ b/esphome/components/sml/sml_parser.cpp @@ -35,6 +35,8 @@ bool SmlFile::setup_node(SmlNode *node) { // Check if we need additional length bytes if (overlength) { + if (this->pos_ + 1 >= this->buffer_.size()) + return false; // Shift the current length to the higher nibble // and add the lower nibble of the next byte to the length length = (length << 4) + (this->buffer_[this->pos_ + 1] & 0x0f); From d6f3186b3d11d6d6aa330751ff634c0d1889e911 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:47:10 -0500 Subject: [PATCH 1124/2030] [haier][bedjet][vbus][lightwaverf] Fix buffer overflow bugs (#14493) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/bedjet/bedjet_codec.cpp | 28 +++++++++++++------ .../components/haier/smartair2_climate.cpp | 2 +- esphome/components/lightwaverf/LwTx.cpp | 4 +++ esphome/components/vbus/vbus.cpp | 4 ++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/esphome/components/bedjet/bedjet_codec.cpp b/esphome/components/bedjet/bedjet_codec.cpp index 9a312e226c..7a959390f3 100644 --- a/esphome/components/bedjet/bedjet_codec.cpp +++ b/esphome/components/bedjet/bedjet_codec.cpp @@ -1,4 +1,5 @@ #include "bedjet_codec.h" +#include <algorithm> #include <cstdio> #include <cstring> @@ -68,6 +69,10 @@ BedjetPacket *BedjetCodec::get_set_runtime_remaining_request(const uint8_t hour, /** Decodes the extra bytes that were received after being notified with a partial packet. */ void BedjetCodec::decode_extra(const uint8_t *data, uint16_t length) { + if (length < 5) { + ESP_LOGVV(TAG, "Received extra: %d bytes (too short)", length); + return; + } ESP_LOGVV(TAG, "Received extra: %d bytes: %d %d %d %d", length, data[1], data[2], data[3], data[4]); uint8_t offset = this->last_buffer_size_; if (offset > 0 && length + offset <= sizeof(BedjetStatusPacket)) { @@ -90,14 +95,19 @@ void BedjetCodec::decode_extra(const uint8_t *data, uint16_t length) { * @return `true` if the packet was decoded and represents a "partial" packet; `false` otherwise. */ bool BedjetCodec::decode_notify(const uint8_t *data, uint16_t length) { + if (length < 5) { + ESP_LOGW(TAG, "Received short packet: %d bytes", length); + return false; + } ESP_LOGV(TAG, "Received: %d bytes: %d %d %d %d", length, data[1], data[2], data[3], data[4]); if (data[1] == PACKET_FORMAT_V3_HOME && data[3] == PACKET_TYPE_STATUS) { // Clear old buffer memset(&this->buf_, 0, sizeof(BedjetStatusPacket)); // Copy new data into buffer - memcpy(&this->buf_, data, length); - this->last_buffer_size_ = length; + size_t copy_len = std::min(static_cast<size_t>(length), sizeof(BedjetStatusPacket)); + memcpy(&this->buf_, data, copy_len); + this->last_buffer_size_ = copy_len; // TODO: validate the packet checksum? if (this->buf_.mode < 7 && this->buf_.target_temp_step >= 38 && this->buf_.target_temp_step <= 86 && @@ -113,13 +123,15 @@ bool BedjetCodec::decode_notify(const uint8_t *data, uint16_t length) { } } else if (data[1] == PACKET_FORMAT_DEBUG || data[3] == PACKET_TYPE_DEBUG) { // We don't actually know the packet format for this. Dump packets to log, in case a pattern presents itself. - ESP_LOGVV(TAG, - "received DEBUG packet: set1=%01fF, set2=%01fF, air=%01fF; [7]=%d, [8]=%d, [9]=%d, [10]=%d, [11]=%d, " - "[12]=%d, [-1]=%d", - bedjet_temp_to_f(data[4]), bedjet_temp_to_f(data[5]), bedjet_temp_to_f(data[6]), data[7], data[8], - data[9], data[10], data[11], data[12], data[length - 1]); + if (length >= 13) { + ESP_LOGVV(TAG, + "received DEBUG packet: set1=%01fF, set2=%01fF, air=%01fF; [7]=%d, [8]=%d, [9]=%d, [10]=%d, [11]=%d, " + "[12]=%d, [-1]=%d", + bedjet_temp_to_f(data[4]), bedjet_temp_to_f(data[5]), bedjet_temp_to_f(data[6]), data[7], data[8], + data[9], data[10], data[11], data[12], data[length - 1]); + } - if (this->has_status()) { + if (this->has_status() && length >= 7) { this->status_packet_->ambient_temp_step = data[6]; } } else { diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index d24f8ad849..e91224e2d8 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -385,7 +385,7 @@ haier_protocol::HaierMessage Smartair2Climate::get_control_message() { } haier_protocol::HandlerError Smartair2Climate::process_status_message_(const uint8_t *packet_buffer, uint8_t size) { - if (size < sizeof(smartair2_protocol::HaierStatus)) + if (size != sizeof(smartair2_protocol::HaierStatus)) return haier_protocol::HandlerError::WRONG_MESSAGE_STRUCTURE; smartair2_protocol::HaierStatus packet; memcpy(&packet, packet_buffer, size); diff --git a/esphome/components/lightwaverf/LwTx.cpp b/esphome/components/lightwaverf/LwTx.cpp index f5ef6ddb2c..b69b93b978 100644 --- a/esphome/components/lightwaverf/LwTx.cpp +++ b/esphome/components/lightwaverf/LwTx.cpp @@ -108,6 +108,10 @@ bool LwTx::lwtx_free() { return !this->tx_msg_active; } Send a LightwaveRF message (10 nibbles in bytes) **/ void LwTx::lwtx_send(const std::vector<uint8_t> &msg) { + if (msg.size() < TX_MSGLEN) { + ESP_LOGW("lightwaverf.sensor", "Message too short: %zu < %u", msg.size(), static_cast<unsigned>(TX_MSGLEN)); + return; + } if (this->tx_translate) { for (uint8_t i = 0; i < TX_MSGLEN; i++) { this->tx_buf[i] = TX_NIBBLE[msg[i] & 0xF]; diff --git a/esphome/components/vbus/vbus.cpp b/esphome/components/vbus/vbus.cpp index b9496a08de..8616da010d 100644 --- a/esphome/components/vbus/vbus.cpp +++ b/esphome/components/vbus/vbus.cpp @@ -1,6 +1,7 @@ #include "vbus.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <algorithm> #include <cinttypes> namespace esphome { @@ -106,9 +107,10 @@ void VBus::loop() { continue; #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_size(VBUS_MAX_LOG_BYTES)]; + size_t log_bytes = std::min(this->buffer_.size(), static_cast<size_t>(VBUS_MAX_LOG_BYTES)); #endif ESP_LOGV(TAG, "P2 C%04x %04x->%04x: %s", this->command_, this->source_, this->dest_, - format_hex_to(hex_buf, this->buffer_.data(), this->buffer_.size())); + format_hex_to(hex_buf, this->buffer_.data(), log_bytes)); for (auto &listener : this->listeners_) listener->on_message(this->command_, this->source_, this->dest_, this->buffer_); this->state_ = 0; From 9961c8180aec582a856b455d35a2e0ae19e2d3e4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:47:32 -0500 Subject: [PATCH 1125/2030] [alpha3][mpu6886][emc2101] Fix copy-paste bugs (#14492) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/alpha3/alpha3.cpp | 2 +- esphome/components/emc2101/emc2101.cpp | 2 +- esphome/components/mpu6886/mpu6886.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/alpha3/alpha3.cpp b/esphome/components/alpha3/alpha3.cpp index f22a8e2444..6e82ec047d 100644 --- a/esphome/components/alpha3/alpha3.cpp +++ b/esphome/components/alpha3/alpha3.cpp @@ -125,7 +125,7 @@ void Alpha3::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc this->current_sensor_->publish_state(NAN); if (this->speed_sensor_ != nullptr) this->speed_sensor_->publish_state(NAN); - if (this->speed_sensor_ != nullptr) + if (this->voltage_sensor_ != nullptr) this->voltage_sensor_->publish_state(NAN); break; } diff --git a/esphome/components/emc2101/emc2101.cpp b/esphome/components/emc2101/emc2101.cpp index 7d85cd31cf..068e25568f 100644 --- a/esphome/components/emc2101/emc2101.cpp +++ b/esphome/components/emc2101/emc2101.cpp @@ -72,7 +72,7 @@ void Emc2101Component::setup() { config |= EMC2101_DAC_BIT; } if (this->inverted_) { - config |= EMC2101_POLARITY_BIT; + reg(EMC2101_REGISTER_FAN_CONFIG) |= EMC2101_POLARITY_BIT; } if (this->dac_mode_) { // DAC mode configurations diff --git a/esphome/components/mpu6886/mpu6886.cpp b/esphome/components/mpu6886/mpu6886.cpp index 68b77b59c9..02747da306 100644 --- a/esphome/components/mpu6886/mpu6886.cpp +++ b/esphome/components/mpu6886/mpu6886.cpp @@ -80,7 +80,7 @@ void MPU6886Component::setup() { accel_config &= 0b11100111; accel_config |= (MPU6886_RANGE_2G << 3); ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config)); - if (!this->write_byte(MPU6886_REGISTER_GYRO_CONFIG, gyro_config)) { + if (!this->write_byte(MPU6886_REGISTER_ACCEL_CONFIG, accel_config)) { this->mark_failed(); return; } From 22d90d702d36fb7f91a6fbfc3d69dd554aa2cbe9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:47:55 -0500 Subject: [PATCH 1126/2030] [usb_cdc_acm][scd4x][pulse_counter][mopeka_std_check][ruuvi_ble] Fix assorted one-liner bugs (#14495) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/mopeka_std_check/mopeka_std_check.cpp | 6 +++--- .../components/mopeka_std_check/mopeka_std_check.h | 2 +- .../components/pulse_counter/pulse_counter_sensor.cpp | 3 ++- esphome/components/ruuvi_ble/ruuvi_ble.cpp | 11 +++++++---- esphome/components/scd4x/scd4x.cpp | 3 ++- esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.cpp b/esphome/components/mopeka_std_check/mopeka_std_check.cpp index 6322b550c9..88bd7b02fd 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.cpp +++ b/esphome/components/mopeka_std_check/mopeka_std_check.cpp @@ -108,7 +108,7 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) } // Get temperature of sensor - uint8_t temp_in_c = this->parse_temperature_(mopeka_data); + int8_t temp_in_c = this->parse_temperature_(mopeka_data); if (this->temperature_ != nullptr) { this->temperature_->publish_state(temp_in_c); } @@ -223,12 +223,12 @@ uint8_t MopekaStdCheck::parse_battery_level_(const mopeka_std_package *message) return (uint8_t) percent; } -uint8_t MopekaStdCheck::parse_temperature_(const mopeka_std_package *message) { +int8_t MopekaStdCheck::parse_temperature_(const mopeka_std_package *message) { uint8_t tmp = message->raw_temp; if (tmp == 0x0) { return -40; } else { - return (uint8_t) ((tmp - 25.0f) * 1.776964f); + return static_cast<int8_t>((tmp - 25.0f) * 1.776964f); } } diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.h b/esphome/components/mopeka_std_check/mopeka_std_check.h index 897b5414ed..45588988c5 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.h +++ b/esphome/components/mopeka_std_check/mopeka_std_check.h @@ -71,7 +71,7 @@ class MopekaStdCheck : public Component, public esp32_ble_tracker::ESPBTDeviceLi float get_lpg_speed_of_sound_(float temperature); uint8_t parse_battery_level_(const mopeka_std_package *message); - uint8_t parse_temperature_(const mopeka_std_package *message); + int8_t parse_temperature_(const mopeka_std_package *message); }; } // namespace mopeka_std_check diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index 5e62c0a410..ec00bd024e 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -175,7 +175,8 @@ void PulseCounterSensor::setup() { void PulseCounterSensor::set_total_pulses(uint32_t pulses) { this->current_total_ = pulses; - this->total_sensor_->publish_state(pulses); + if (this->total_sensor_ != nullptr) + this->total_sensor_->publish_state(pulses); } void PulseCounterSensor::dump_config() { diff --git a/esphome/components/ruuvi_ble/ruuvi_ble.cpp b/esphome/components/ruuvi_ble/ruuvi_ble.cpp index 1b126bdef0..bf088873ce 100644 --- a/esphome/components/ruuvi_ble/ruuvi_ble.cpp +++ b/esphome/components/ruuvi_ble/ruuvi_ble.cpp @@ -63,10 +63,13 @@ bool parse_ruuvi_data_byte(const esp32_ble_tracker::adv_data_t &adv_data, RuuviP result.acceleration_x = data[6] == 0xFF && data[7] == 0xFF ? NAN : acceleration_x; result.acceleration_y = data[8] == 0xFF && data[9] == 0xFF ? NAN : acceleration_y; result.acceleration_z = data[10] == 0xFF && data[11] == 0xFF ? NAN : acceleration_z; - result.acceleration = result.acceleration_x == NAN || result.acceleration_y == NAN || result.acceleration_z == NAN - ? NAN - : sqrtf(acceleration_x * acceleration_x + acceleration_y * acceleration_y + - acceleration_z * acceleration_z); + if ((data[6] != 0xFF || data[7] != 0xFF) && (data[8] != 0xFF || data[9] != 0xFF) && + (data[10] != 0xFF || data[11] != 0xFF)) { + result.acceleration = + sqrtf(acceleration_x * acceleration_x + acceleration_y * acceleration_y + acceleration_z * acceleration_z); + } else { + result.acceleration = NAN; + } result.battery_voltage = (power_info >> 5) == 0x7FF ? NAN : battery_voltage; result.tx_power = (power_info & 0x1F) == 0x1F ? NAN : tx_power; result.movement_counter = movement_counter; diff --git a/esphome/components/scd4x/scd4x.cpp b/esphome/components/scd4x/scd4x.cpp index a265386cc2..0c108fba9d 100644 --- a/esphome/components/scd4x/scd4x.cpp +++ b/esphome/components/scd4x/scd4x.cpp @@ -307,7 +307,7 @@ bool SCD4XComponent::start_measurement_() { break; } - static uint8_t remaining_retries = 3; + uint8_t remaining_retries = 3; while (remaining_retries) { if (!this->write_command(measurement_command)) { ESP_LOGE(TAG, "Error starting measurements"); @@ -316,6 +316,7 @@ bool SCD4XComponent::start_measurement_() { if (--remaining_retries == 0) return false; delay(50); // NOLINT wait 50 ms and try again + continue; } this->status_clear_warning(); return true; diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index d33fb80f78..44de986f9a 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -161,7 +161,7 @@ void USBCDCACMInstance::setup() { // Create a simple, unique task name per interface char task_name[] = "usb_tx_0"; - task_name[sizeof(task_name) - 1] = format_hex_char(static_cast<char>(this->itf_)); + task_name[sizeof(task_name) - 2] = format_hex_char(static_cast<char>(this->itf_)); xTaskCreate(usb_tx_task_fn, task_name, stack_size, this, 4, &this->usb_tx_task_handle_); if (this->usb_tx_task_handle_ == nullptr) { From 5c5ea8824edebb74e80a3ff9306add66b76b4b95 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 5 Mar 2026 13:51:08 -0600 Subject: [PATCH 1127/2030] [audio_file] New component for embedding files into firmware (#14434) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- CODEOWNERS | 1 + esphome/components/audio_file/__init__.py | 255 ++++++++++++++++++ esphome/components/audio_file/audio_file.h | 28 ++ esphome/core/defines.h | 1 + script/ci-custom.py | 1 + tests/components/audio_file/common.yaml | 5 + .../components/audio_file/test.esp32-idf.yaml | 1 + tests/components/audio_file/test.wav | Bin 0 -> 46 bytes 8 files changed, 292 insertions(+) create mode 100644 esphome/components/audio_file/__init__.py create mode 100644 esphome/components/audio_file/audio_file.h create mode 100644 tests/components/audio_file/common.yaml create mode 100644 tests/components/audio_file/test.esp32-idf.yaml create mode 100644 tests/components/audio_file/test.wav diff --git a/CODEOWNERS b/CODEOWNERS index b22f85b71d..7c37b20e09 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -54,6 +54,7 @@ esphome/components/atm90e32/* @circuitsetup @descipher esphome/components/audio/* @kahrendt esphome/components/audio_adc/* @kbx81 esphome/components/audio_dac/* @kbx81 +esphome/components/audio_file/* @kahrendt esphome/components/axs15231/* @clydebarrow esphome/components/b_parasite/* @rbaron esphome/components/ballu/* @bazuchan diff --git a/esphome/components/audio_file/__init__.py b/esphome/components/audio_file/__init__.py new file mode 100644 index 0000000000..3ed6c1cd92 --- /dev/null +++ b/esphome/components/audio_file/__init__.py @@ -0,0 +1,255 @@ +from dataclasses import dataclass, field +import hashlib +import logging +from pathlib import Path + +import puremagic + +from esphome import external_files +import esphome.codegen as cg +from esphome.components import audio +import esphome.config_validation as cv +from esphome.const import ( + CONF_FILE, + CONF_ID, + CONF_PATH, + CONF_RAW_DATA_ID, + CONF_TYPE, + CONF_URL, +) +from esphome.core import CORE, ID, HexInt +from esphome.cpp_generator import MockObj +from esphome.external_files import download_content +from esphome.types import ConfigType + +_LOGGER = logging.getLogger(__name__) + +CODEOWNERS = ["@kahrendt"] + +AUTO_LOAD = ["audio"] + +DOMAIN = "audio_file" + +audio_file_ns = cg.esphome_ns.namespace("audio_file") + +TYPE_LOCAL = "local" +TYPE_WEB = "web" + + +@dataclass +class AudioFileData: + file_ids: dict[str, ID] = field(default_factory=dict) + file_cache: dict[str, tuple[bytes, MockObj]] = field(default_factory=dict) + + +def _get_data() -> AudioFileData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = AudioFileData() + return CORE.data[DOMAIN] + + +def get_audio_file_ids() -> dict[str, ID]: + """Get all registered audio file IDs for cross-component access.""" + return _get_data().file_ids + + +def _compute_local_file_path(value: ConfigType) -> Path: + url = value[CONF_URL] + h = hashlib.new("sha256") + h.update(url.encode()) + key = h.hexdigest()[:8] + base_dir = external_files.compute_local_file_dir(DOMAIN) + _LOGGER.debug("_compute_local_file_path: base_dir=%s", base_dir / key) + return base_dir / key + + +def _download_web_file(value: ConfigType) -> ConfigType: + url = value[CONF_URL] + path = _compute_local_file_path(value) + + download_content(url, path) + _LOGGER.debug("download_web_file: path=%s", path) + return value + + +def _file_schema(value: ConfigType | str) -> ConfigType: + if isinstance(value, str): + return _validate_file_shorthand(value) + return TYPED_FILE_SCHEMA(value) + + +def _validate_file_shorthand(value: str) -> ConfigType: + value = cv.string_strict(value) + if value.startswith("http://") or value.startswith("https://"): + return _file_schema( + { + CONF_TYPE: TYPE_WEB, + CONF_URL: value, + } + ) + return _file_schema( + { + CONF_TYPE: TYPE_LOCAL, + CONF_PATH: value, + } + ) + + +def read_audio_file_and_type(file_config: ConfigType) -> tuple[bytes, MockObj]: + """Read an audio file and determine its type. Used by this component and media_source platform.""" + conf_file = file_config[CONF_FILE] + file_source = conf_file[CONF_TYPE] + if file_source == TYPE_LOCAL: + path = CORE.relative_config_path(conf_file[CONF_PATH]) + elif file_source == TYPE_WEB: + path = _compute_local_file_path(conf_file) + else: + raise cv.Invalid("Unsupported file source") + + with open(path, "rb") as f: + data = f.read() + + try: + file_type: str = puremagic.from_string(data) + file_type = file_type.removeprefix(".") + except puremagic.PureError as e: + raise cv.Invalid( + f"Unable to determine audio file type of '{path}'. " + f"Try re-encoding the file into a supported format. Details: {e}" + ) + + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["NONE"] + if file_type == "wav": + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["WAV"] + elif file_type in ("mp3", "mpeg", "mpga"): + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["MP3"] + elif file_type == "flac": + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["FLAC"] + elif ( + file_type == "ogg" + and len(data) >= 36 + and data.startswith(b"OggS") + and data[28:36] == b"OpusHead" + ): + media_file_type = audio.AUDIO_FILE_TYPE_ENUM["OPUS"] + + return data, media_file_type + + +LOCAL_SCHEMA = cv.Schema( + { + cv.Required(CONF_PATH): cv.file_, + } +) + +WEB_SCHEMA = cv.All( + { + cv.Required(CONF_URL): cv.url, + }, + _download_web_file, +) + + +TYPED_FILE_SCHEMA = cv.typed_schema( + { + TYPE_LOCAL: LOCAL_SCHEMA, + TYPE_WEB: WEB_SCHEMA, + }, +) + + +MEDIA_FILE_TYPE_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(audio.AudioFile), + cv.Required(CONF_FILE): _file_schema, + cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), + } +) + + +MAX_FILE_SIZE = 5 * 1024 * 1024 # 5 MB + + +def _validate_supported_local_file(config: list[ConfigType]) -> list[ConfigType]: + for file_config in config: + data, media_file_type = read_audio_file_and_type(file_config) + + if len(data) > MAX_FILE_SIZE: + file_info = file_config.get(CONF_FILE, {}) + source = ( + file_info.get(CONF_PATH) or file_info.get(CONF_URL) or "unknown source" + ) + raise cv.Invalid( + f"Audio file {source!r} is too large ({len(data)} bytes, max {MAX_FILE_SIZE} bytes)" + ) + + if str(media_file_type) == str(audio.AUDIO_FILE_TYPE_ENUM["NONE"]): + file_info = file_config.get(CONF_FILE, {}) + source = ( + file_info.get(CONF_PATH) or file_info.get(CONF_URL) or "unknown source" + ) + raise cv.Invalid( + f"Unsupported media file from {source!r} (detected type: {media_file_type})" + ) + + # Cache the file data so to_code() doesn't need to re-read it + _get_data().file_cache[str(file_config[CONF_ID])] = (data, media_file_type) + + media_file_type_str = str(media_file_type) + if media_file_type_str == str(audio.AUDIO_FILE_TYPE_ENUM["FLAC"]): + audio.request_flac_support() + elif media_file_type_str == str(audio.AUDIO_FILE_TYPE_ENUM["MP3"]): + audio.request_mp3_support() + elif media_file_type_str == str(audio.AUDIO_FILE_TYPE_ENUM["OPUS"]): + audio.request_opus_support() + + return config + + +CONFIG_SCHEMA = cv.All( + cv.only_on_esp32, + cv.ensure_list(MEDIA_FILE_TYPE_SCHEMA), + _validate_supported_local_file, +) + + +async def to_code(config: list[ConfigType]) -> None: + cache = _get_data().file_cache + + for file_config in config: + file_id = str(file_config[CONF_ID]) + data, media_file_type = cache[file_id] + + rhs = [HexInt(x) for x in data] + prog_arr = cg.progmem_array(file_config[CONF_RAW_DATA_ID], rhs) + + media_files_struct = cg.StructInitializer( + audio.AudioFile, + ( + "data", + prog_arr, + ), + ( + "length", + len(rhs), + ), + ( + "file_type", + media_file_type, + ), + ) + + cg.new_Pvariable( + file_config[CONF_ID], + media_files_struct, + ) + + # Store file ID for cross-component access + _get_data().file_ids[file_id] = file_config[CONF_ID] + + # Register all files in the shared C++ registry + cg.add_define("AUDIO_FILE_MAX_FILES", len(config)) + for file_config in config: + file_id = str(file_config[CONF_ID]) + file_var = await cg.get_variable(file_config[CONF_ID]) + cg.add(audio_file_ns.add_named_audio_file(file_var, file_id)) diff --git a/esphome/components/audio_file/audio_file.h b/esphome/components/audio_file/audio_file.h new file mode 100644 index 0000000000..537e19fb3c --- /dev/null +++ b/esphome/components/audio_file/audio_file.h @@ -0,0 +1,28 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef AUDIO_FILE_MAX_FILES + +#include "esphome/components/audio/audio.h" +#include "esphome/core/helpers.h" + +namespace esphome::audio_file { + +struct NamedAudioFile { + audio::AudioFile *file; + const char *file_id; +}; + +inline StaticVector<NamedAudioFile, AUDIO_FILE_MAX_FILES> + named_audio_files; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +inline void add_named_audio_file(audio::AudioFile *file, const char *file_id) { + named_audio_files.push_back({file, file_id}); +} + +inline const StaticVector<NamedAudioFile, AUDIO_FILE_MAX_FILES> &get_named_audio_files() { return named_audio_files; } + +} // namespace esphome::audio_file + +#endif // AUDIO_FILE_MAX_FILES diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 07afefd91a..1a6d9b3a80 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -137,6 +137,7 @@ // Feature flags which do not work for zephyr #ifndef USE_ZEPHYR +#define AUDIO_FILE_MAX_FILES 4 #define USE_AUDIO_DAC #define USE_AUDIO_FLAC_SUPPORT #define USE_AUDIO_MP3_SUPPORT diff --git a/script/ci-custom.py b/script/ci-custom.py index b60d7d7740..8e1652b505 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -72,6 +72,7 @@ ignore_types = ( ".gif", ".webp", ".bin", + ".wav", ) LINT_FILE_CHECKS = [] diff --git a/tests/components/audio_file/common.yaml b/tests/components/audio_file/common.yaml new file mode 100644 index 0000000000..9404208094 --- /dev/null +++ b/tests/components/audio_file/common.yaml @@ -0,0 +1,5 @@ +audio_file: + - id: test_audio + file: + type: local + path: $component_dir/test.wav diff --git a/tests/components/audio_file/test.esp32-idf.yaml b/tests/components/audio_file/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/audio_file/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/audio_file/test.wav b/tests/components/audio_file/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..f9d07ef2238eb2fcb355055466d3789ee1a1fe0b GIT binary patch literal 46 ycmWIYbaPW<U|<M$40BD(Em06)U|?WmU}R{pV_;yYWnf@p5MW42EJ<Wy0098Ji3Z~U literal 0 HcmV?d00001 From bb37887a8c3021f6a93cac9eb1df4caf36d2c1b1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:51:32 -0500 Subject: [PATCH 1128/2030] [wled][lcd_base][touchscreen][ee895] Fix off-by-one, buffer overrun, empty deref, and uninitialized pointers (#14513) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/ee895/ee895.h | 6 +++--- esphome/components/lcd_base/lcd_display.cpp | 2 +- esphome/components/touchscreen/touchscreen.h | 7 ++++++- esphome/components/wled/wled_light_effect.cpp | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/esphome/components/ee895/ee895.h b/esphome/components/ee895/ee895.h index 259b7c524b..ff1085e05d 100644 --- a/esphome/components/ee895/ee895.h +++ b/esphome/components/ee895/ee895.h @@ -22,9 +22,9 @@ class EE895Component : public PollingComponent, public i2c::I2CDevice { void write_command_(uint16_t addr, uint16_t reg_cnt); float read_float_(); uint16_t calc_crc16_(const uint8_t buf[], uint8_t len); - sensor::Sensor *co2_sensor_; - sensor::Sensor *temperature_sensor_; - sensor::Sensor *pressure_sensor_; + sensor::Sensor *co2_sensor_{nullptr}; + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *pressure_sensor_{nullptr}; enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, CRC_CHECK_FAILED } error_code_{NONE}; }; diff --git a/esphome/components/lcd_base/lcd_display.cpp b/esphome/components/lcd_base/lcd_display.cpp index cd08a739eb..1f0ba482d7 100644 --- a/esphome/components/lcd_base/lcd_display.cpp +++ b/esphome/components/lcd_base/lcd_display.cpp @@ -99,7 +99,7 @@ void HOT LCDDisplay::display() { this->send(this->buffer_[this->columns_ * 2 + i], true); } - if (this->rows_ >= 1) { + if (this->rows_ >= 2) { this->command_(LCD_DISPLAY_COMMAND_SET_DDRAM_ADDR | 0x40); for (uint8_t i = 0; i < this->columns_; i++) diff --git a/esphome/components/touchscreen/touchscreen.h b/esphome/components/touchscreen/touchscreen.h index 8016323d49..7451c207ec 100644 --- a/esphome/components/touchscreen/touchscreen.h +++ b/esphome/components/touchscreen/touchscreen.h @@ -65,7 +65,12 @@ class Touchscreen : public PollingComponent { void register_listener(TouchListener *listener) { this->touch_listeners_.push_back(listener); } - optional<TouchPoint> get_touch() { return this->touches_.begin()->second; } + optional<TouchPoint> get_touch() { + if (this->touches_.empty()) { + return {}; + } + return this->touches_.begin()->second; + } TouchPoints_t get_touches() { TouchPoints_t touches; diff --git a/esphome/components/wled/wled_light_effect.cpp b/esphome/components/wled/wled_light_effect.cpp index 87bae5b1da..db2708d6d0 100644 --- a/esphome/components/wled/wled_light_effect.cpp +++ b/esphome/components/wled/wled_light_effect.cpp @@ -161,7 +161,7 @@ bool WLEDLightEffect::parse_notifier_frame_(light::AddressableLight &it, const u // https://kno.wled.ge/interfaces/udp-notifier/ // https://github.com/Aircoookie/WLED/blob/main/wled00/udp.cpp - if (size < 34) { + if (size <= 34) { return false; } From 99a805cba675ab2399d432dd39d142a0852fafc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Mar 2026 09:52:10 -1000 Subject: [PATCH 1129/2030] Bump the docker-actions group across 1 directory with 2 updates (#14520) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-docker.yml | 2 +- .github/workflows/release.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml index a83bcae0b0..4009ac1e17 100644 --- a/.github/workflows/ci-docker.yml +++ b/.github/workflows/ci-docker.yml @@ -49,7 +49,7 @@ jobs: with: python-version: "3.11" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Set TAG run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17a2616dff..8f68e9c873 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -99,15 +99,15 @@ jobs: python-version: "3.11" - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Log in to docker hub - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -178,17 +178,17 @@ jobs: merge-multiple: true - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry if: matrix.registry == 'ghcr' - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: registry: ghcr.io username: ${{ github.actor }} From 291679126f532a6b036c10984c97c47db0be9cd3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 14:55:54 -0500 Subject: [PATCH 1130/2030] [nfc] Fix off-by-one in NDEF message parsing (#14485) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/nfc/ndef_message.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/esphome/components/nfc/ndef_message.cpp b/esphome/components/nfc/ndef_message.cpp index e7304445c5..35028555c5 100644 --- a/esphome/components/nfc/ndef_message.cpp +++ b/esphome/components/nfc/ndef_message.cpp @@ -8,8 +8,14 @@ static const char *const TAG = "nfc.ndef_message"; NdefMessage::NdefMessage(std::vector<uint8_t> &data) { ESP_LOGV(TAG, "Building NdefMessage with %zu bytes", data.size()); - uint8_t index = 0; - while (index <= data.size()) { + size_t index = 0; + while (index < data.size()) { + // Minimum record: TNF byte + type length byte + payload length (1 or 4 bytes) + if (index + 2 >= data.size()) { + ESP_LOGE(TAG, "Truncated record header; aborting"); + break; + } + uint8_t tnf_byte = data[index++]; bool me = tnf_byte & 0x40; // Message End bit (is set if this is the last record of the message) bool sr = tnf_byte & 0x10; // Short record bit (is set if payload size is less or equal to 255 bytes) @@ -23,6 +29,10 @@ NdefMessage::NdefMessage(std::vector<uint8_t> &data) { if (sr) { payload_length = data[index++]; } else { + if (index + 4 > data.size()) { + ESP_LOGE(TAG, "Truncated payload length; aborting"); + break; + } payload_length = (static_cast<uint32_t>(data[index]) << 24) | (static_cast<uint32_t>(data[index + 1]) << 16) | (static_cast<uint32_t>(data[index + 2]) << 8) | static_cast<uint32_t>(data[index + 3]); index += 4; @@ -30,6 +40,10 @@ NdefMessage::NdefMessage(std::vector<uint8_t> &data) { uint8_t id_length = 0; if (il) { + if (index >= data.size()) { + ESP_LOGE(TAG, "Truncated ID length; aborting"); + break; + } id_length = data[index++]; } From e25d740968f656b8e50dedb793fbc5370573f3ef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Mar 2026 09:58:58 -1000 Subject: [PATCH 1131/2030] [wifi] Cache is_connected() for cheap inline access (#14463) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/wifi/wifi_component.cpp | 8 +++++--- esphome/components/wifi/wifi_component.h | 5 ++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 852ff922f1..8b60810d28 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -725,6 +725,7 @@ void WiFiComponent::restart_adapter() { void WiFiComponent::loop() { this->wifi_loop_(); const uint32_t now = App.get_loop_component_start_time(); + this->update_connected_state_(); if (this->has_sta()) { #if defined(USE_WIFI_CONNECT_TRIGGER) || defined(USE_WIFI_DISCONNECT_TRIGGER) @@ -776,7 +777,7 @@ void WiFiComponent::loop() { } case WIFI_COMPONENT_STATE_STA_CONNECTED: { - if (!this->is_connected()) { + if (!this->is_connected_()) { ESP_LOGW(TAG, "Connection lost; reconnecting"); this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; this->retry_connect(); @@ -2118,15 +2119,16 @@ bool WiFiComponent::can_proceed() { if (!this->has_sta() || this->state_ == WIFI_COMPONENT_STATE_DISABLED || this->ap_setup_) { return true; } - return this->is_connected(); + return this->is_connected_(); } #endif void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } -bool WiFiComponent::is_connected() const { +bool WiFiComponent::is_connected_() const { return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_; } +void WiFiComponent::update_connected_state_() { this->connected_ = this->is_connected_(); } void WiFiComponent::set_power_save_mode(WiFiPowerSaveMode power_save) { this->power_save_ = power_save; #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index a6f03a08d9..f340b708c9 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -443,7 +443,7 @@ class WiFiComponent : public Component { void set_reboot_timeout(uint32_t reboot_timeout); - bool is_connected() const; + bool is_connected() const { return this->connected_; } void set_power_save_mode(WiFiPowerSaveMode power_save); void set_min_auth_mode(WifiMinAuthMode min_auth_mode) { min_auth_mode_ = min_auth_mode; } @@ -678,6 +678,8 @@ class WiFiComponent : public Component { bool wifi_sta_connect_(const WiFiAP &ap); void wifi_pre_setup_(); WiFiSTAConnectStatus wifi_sta_connect_status_() const; + bool is_connected_() const; + void update_connected_state_(); bool wifi_scan_start_(bool passive); #ifdef USE_WIFI_AP @@ -854,6 +856,7 @@ class WiFiComponent : public Component { bool has_completed_scan_after_captive_portal_start_{ false}; // Tracks if we've completed a scan after captive portal started bool skip_cooldown_next_cycle_{false}; + bool connected_{false}; bool post_connect_roaming_{true}; // Enabled by default #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) bool is_high_performance_mode_{false}; From d11e7cab464a007bccf37cf0cf3da4d8b1f71861 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 15:18:54 -0500 Subject: [PATCH 1132/2030] [xiaomi_ble][pvvx_mithermometer][atc_mithermometer] Add BLE service data bounds checks (#14514) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/atc_mithermometer/atc_mithermometer.cpp | 4 ++++ .../components/pvvx_mithermometer/pvvx_mithermometer.cpp | 4 ++++ esphome/components/xiaomi_ble/xiaomi_ble.cpp | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/esphome/components/atc_mithermometer/atc_mithermometer.cpp b/esphome/components/atc_mithermometer/atc_mithermometer.cpp index b4d2929742..9afd6334f5 100644 --- a/esphome/components/atc_mithermometer/atc_mithermometer.cpp +++ b/esphome/components/atc_mithermometer/atc_mithermometer.cpp @@ -61,6 +61,10 @@ optional<ParseResult> ATCMiThermometer::parse_header_(const esp32_ble_tracker::S } auto raw = service_data.data; + if (raw.size() < 13) { + ESP_LOGVV(TAG, "parse_header_(): service data too short (%zu).", raw.size()); + return {}; + } static uint8_t last_frame_count = 0; if (last_frame_count == raw[12]) { diff --git a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp index 5712447909..239a1e74fe 100644 --- a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp +++ b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp @@ -61,6 +61,10 @@ optional<ParseResult> PVVXMiThermometer::parse_header_(const esp32_ble_tracker:: } auto raw = service_data.data; + if (raw.size() < 14) { + ESP_LOGVV(TAG, "parse_header_(): service data too short (%zu).", raw.size()); + return {}; + } static uint8_t last_frame_count = 0; if (last_frame_count == raw[13]) { diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 0018d35f1f..97a660f0e3 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -121,6 +121,11 @@ bool parse_xiaomi_message(const std::vector<uint8_t> &message, XiaomiParseResult // Byte 2: length // Byte 3..3+len-1: data point value + if (result.raw_offset < 0 || static_cast<size_t>(result.raw_offset) >= message.size()) { + ESP_LOGVV(TAG, "parse_xiaomi_message(): raw_offset (%d) exceeds message size (%d)!", result.raw_offset, + message.size()); + return false; + } const uint8_t *payload = message.data() + result.raw_offset; uint8_t payload_length = message.size() - result.raw_offset; uint8_t payload_offset = 0; @@ -165,6 +170,10 @@ optional<XiaomiParseResult> parse_xiaomi_header(const esp32_ble_tracker::Service } auto raw = service_data.data; + if (raw.size() < 5) { + ESP_LOGVV(TAG, "parse_xiaomi_header(): service data too short (%d).", raw.size()); + return {}; + } result.has_data = raw[0] & 0x40; result.has_capability = raw[0] & 0x20; result.has_encryption = raw[0] & 0x08; From b0be02e16d8b53efee692543c9be2c6da2118da7 Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Thu, 5 Mar 2026 12:54:17 -0800 Subject: [PATCH 1133/2030] [modbus] Fix timing bugs and better adhere to spec (#8032) Co-authored-by: brambo123 <52667932+brambo123@users.noreply.github.com> Co-authored-by: Keith Burzinski <kbx81x@gmail.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../growatt_solar/growatt_solar.cpp | 2 +- esphome/components/modbus/__init__.py | 5 + esphome/components/modbus/modbus.cpp | 294 ++++++++++++------ esphome/components/modbus/modbus.h | 55 +++- .../components/modbus/modbus_definitions.h | 2 + .../components/modbus_controller/__init__.py | 3 +- .../modbus_controller/modbus_controller.cpp | 2 +- tests/components/modbus/common.yaml | 2 + .../external_components/uart_mock/__init__.py | 4 +- .../uart_mock/uart_mock.cpp | 26 +- .../external_components/uart_mock/uart_mock.h | 5 +- .../fixtures/uart_mock_modbus.yaml | 48 ++- .../fixtures/uart_mock_modbus_timing.yaml | 2 + tests/integration/test_uart_mock_modbus.py | 67 +++- 14 files changed, 396 insertions(+), 121 deletions(-) diff --git a/esphome/components/growatt_solar/growatt_solar.cpp b/esphome/components/growatt_solar/growatt_solar.cpp index 686c1c232e..2997425872 100644 --- a/esphome/components/growatt_solar/growatt_solar.cpp +++ b/esphome/components/growatt_solar/growatt_solar.cpp @@ -26,7 +26,7 @@ void GrowattSolar::update() { } // The bus might be slow, or there might be other devices, or other components might be talking to our device. - if (this->waiting_for_response()) { + if (!this->ready_for_immediate_send()) { this->waiting_to_update_ = true; return; } diff --git a/esphome/components/modbus/__init__.py b/esphome/components/modbus/__init__.py index 2bd85c6121..f6e0f98857 100644 --- a/esphome/components/modbus/__init__.py +++ b/esphome/components/modbus/__init__.py @@ -20,6 +20,7 @@ MULTI_CONF = True CONF_ROLE = "role" CONF_MODBUS_ID = "modbus_id" CONF_SEND_WAIT_TIME = "send_wait_time" +CONF_TURNAROUND_TIME = "turnaround_time" ModbusRole = modbus_ns.enum("ModbusRole") MODBUS_ROLES = { @@ -36,6 +37,9 @@ CONFIG_SCHEMA = ( cv.Optional( CONF_SEND_WAIT_TIME, default="250ms" ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_TURNAROUND_TIME, default="100ms" + ): cv.positive_time_period_milliseconds, cv.Optional(CONF_DISABLE_CRC, default=False): cv.boolean, } ) @@ -57,6 +61,7 @@ async def to_code(config): cg.add(var.set_flow_control_pin(pin)) cg.add(var.set_send_wait_time(config[CONF_SEND_WAIT_TIME])) + cg.add(var.set_turnaround_time(config[CONF_TURNAROUND_TIME])) cg.add(var.set_disable_crc(config[CONF_DISABLE_CRC])) diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index d40343db33..28e26e307e 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -15,10 +15,69 @@ void Modbus::setup() { if (this->flow_control_pin_ != nullptr) { this->flow_control_pin_->setup(); } -} -void Modbus::loop() { - const uint32_t now = App.get_loop_component_start_time(); + this->frame_delay_ms_ = + std::max(2, // 1750us minimum per spec - rounded up to 2ms. + // 3.5 characters * 11 bits per character * 1000ms/sec / (bits/sec) (Standard modbus frame delay) + (uint16_t) (3.5 * 11 * 1000 / this->parent_->get_baud_rate()) + 1); + + this->long_rx_buffer_delay_ms_ = + (this->parent_->get_rx_full_threshold() * 11 * 1000 / this->parent_->get_baud_rate()) + 1; +} + +void Modbus::loop() { + // First process all available incoming data. + this->receive_and_parse_modbus_bytes_(); + + // If the response frame is finished (including interframe delay) - we timeout. + // The long_rx_buffer_delay accounts for long responses (larger than the UART rx_full_threshold) to avoid timeouts + // when the buffer is filling the back half of the response + const uint16_t timeout = std::max( + (uint16_t) this->frame_delay_ms_, + (uint16_t) (this->rx_buffer_.size() >= this->parent_->get_rx_full_threshold() ? this->long_rx_buffer_delay_ms_ + : 0)); + // We use millis() here and elsewhere instead of App.get_loop_component_start_time() to avoid stale timestamps + // It's critical in all timestamp comparisons that the left timestamp comes before the right one in time + // If we use a cached value in place of millis() and last_modbus_byte_ is updated inside our loop + // then the comparison is backwards (small negative which wraps to large positive) and will cause a false timeout + // So in this component we don't use any cached timestamp values to avoid these annoying bugs + if (millis() - this->last_modbus_byte_ > timeout) { + this->clear_rx_buffer_(LOG_STR("timeout after partial response"), true); + } + + // If we're past the send_wait_time timeout and response buffer doesn't have the start of the expected response + if (this->waiting_for_response_ != 0 && + millis() - this->last_send_ > this->last_send_tx_offset_ + this->send_wait_time_ && + (this->rx_buffer_.empty() || this->rx_buffer_[0] != this->waiting_for_response_)) { + ESP_LOGW(TAG, "Stop waiting for response from %" PRIu8 " %" PRIu32 "ms after last send", + this->waiting_for_response_, millis() - this->last_send_); + this->waiting_for_response_ = 0; + } + + // If there's no response pending and there's commands in the buffer + this->send_next_frame_(); +} + +bool Modbus::tx_blocked() { + const uint32_t now = millis(); + + // We block transmission in any of these case: + // 1. There are bytes in the UART Rx buffer + // 2. There are bytes in our Rx buffer + // 3. We're waiting for a response + // 4. The last sent byte isn't more than frame_delay ms ago (i.e. wait to tell receivers that our previous Tx is done) + // 5. The last received byte isn't more than frame_delay ms ago (i.e. wait to be sure there isn't more Rx coming) + // 6. If we're a client - also wait for the turnaround delay, to give the servers time to process the previous message + return this->available() || !this->rx_buffer_.empty() || (this->waiting_for_response_ != 0) || + (now - this->last_send_ < this->last_send_tx_offset_ + this->frame_delay_ms_ + + (this->role == ModbusRole::CLIENT ? this->turnaround_delay_ms_ : 0)) || + (now - this->last_modbus_byte_ < + this->frame_delay_ms_ + (this->role == ModbusRole::CLIENT ? this->turnaround_delay_ms_ : 0)); +} + +bool Modbus::tx_buffer_empty() { return this->tx_buffer_.empty(); } + +void Modbus::receive_and_parse_modbus_bytes_() { // Read all available bytes in batches to reduce UART call overhead. size_t avail = this->available(); uint8_t buf[64]; @@ -28,33 +87,20 @@ void Modbus::loop() { break; } avail -= to_read; - for (size_t i = 0; i < to_read; i++) { - if (this->parse_modbus_byte_(buf[i])) { - this->last_modbus_byte_ = now; + if (this->rx_buffer_.empty()) { + ESP_LOGV(TAG, "Received first byte %" PRIu8 " (0X%x) %" PRIu32 "ms after last send", buf[i], buf[i], + millis() - this->last_send_); } else { - size_t at = this->rx_buffer_.size(); - if (at > 0) { - ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse failed", at); - this->rx_buffer_.clear(); - } + ESP_LOGVV(TAG, "Received byte %" PRIu8 " (0X%x) %" PRIu32 "ms after last send", buf[i], buf[i], + millis() - this->last_send_); } - } - } - if (now - this->last_modbus_byte_ > 50) { - size_t at = this->rx_buffer_.size(); - if (at > 0) { - ESP_LOGV(TAG, "Clearing buffer of %d bytes - timeout", at); - this->rx_buffer_.clear(); - } - - // stop blocking new send commands after sent_wait_time_ ms after response received - if (now - this->last_send_ > send_wait_time_) { - if (waiting_for_response > 0) { - ESP_LOGV(TAG, "Stop waiting for response from %d", waiting_for_response); + // If the bytes in the rx buffer do not parse, clear out the buffer + if (!this->parse_modbus_byte_(buf[i])) { + this->clear_rx_buffer_(LOG_STR("parse failed"), true); } - waiting_for_response = 0; + this->last_modbus_byte_ = millis(); } } } @@ -63,7 +109,7 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { size_t at = this->rx_buffer_.size(); this->rx_buffer_.push_back(byte); const uint8_t *raw = &this->rx_buffer_[0]; - ESP_LOGVV(TAG, "Modbus received Byte %d (0X%x)", byte, byte); + // Byte 0: modbus address (match all) if (at == 0) return true; @@ -101,7 +147,7 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { if (computed_crc != remote_crc) return true; - ESP_LOGD(TAG, "Modbus user-defined function %02X found", function_code); + ESP_LOGD(TAG, "User-defined function %02X found", function_code); } else { // data starts at 2 and length is 4 for read registers commands @@ -152,9 +198,19 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { uint16_t remote_crc = uint16_t(raw[data_offset + data_len]) | (uint16_t(raw[data_offset + data_len + 1]) << 8); if (computed_crc != remote_crc) { if (this->disable_crc_) { - ESP_LOGD(TAG, "Modbus CRC Check failed, but ignored! %02X!=%02X", computed_crc, remote_crc); + ESP_LOGD(TAG, "CRC check failed %" PRIu32 "ms after last send; ignoring", millis() - this->last_send_); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; +#endif + ESP_LOGVV(TAG, " (%02X != %02X) %s", computed_crc, remote_crc, + format_hex_pretty_to(hex_buf, this->rx_buffer_.data(), this->rx_buffer_.size())); } else { - ESP_LOGW(TAG, "Modbus CRC Check failed! %02X!=%02X", computed_crc, remote_crc); + ESP_LOGW(TAG, "CRC check failed %" PRIu32 "ms after last send", millis() - this->last_send_); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; +#endif + ESP_LOGVV(TAG, " (%02X != %02X) %s", computed_crc, remote_crc, + format_hex_pretty_to(hex_buf, this->rx_buffer_.data(), this->rx_buffer_.size())); return false; } } @@ -164,52 +220,101 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { for (auto *device : this->devices_) { if (device->address_ == address) { found = true; - // Is it an error response? - if ((function_code & FUNCTION_CODE_EXCEPTION_MASK) == FUNCTION_CODE_EXCEPTION_MASK) { - ESP_LOGD(TAG, "Modbus error function code: 0x%X exception: %d", function_code, raw[2]); - if (waiting_for_response != 0) { - device->on_modbus_error(function_code & FUNCTION_CODE_MASK, raw[2]); - } else { - // Ignore modbus exception not related to a pending command - ESP_LOGD(TAG, "Ignoring Modbus error - not expecting a response"); - } - continue; - } if (this->role == ModbusRole::SERVER) { if (function_code == ModbusFunctionCode::READ_HOLDING_REGISTERS || function_code == ModbusFunctionCode::READ_INPUT_REGISTERS) { device->on_modbus_read_registers(function_code, uint16_t(data[1]) | (uint16_t(data[0]) << 8), uint16_t(data[3]) | (uint16_t(data[2]) << 8)); - continue; - } - if (function_code == ModbusFunctionCode::WRITE_SINGLE_REGISTER || - function_code == ModbusFunctionCode::WRITE_MULTIPLE_REGISTERS) { + } else if (function_code == ModbusFunctionCode::WRITE_SINGLE_REGISTER || + function_code == ModbusFunctionCode::WRITE_MULTIPLE_REGISTERS) { device->on_modbus_write_registers(function_code, data); - continue; + } + } else { // We're a client + // Is it an error response? + if ((function_code & FUNCTION_CODE_EXCEPTION_MASK) == FUNCTION_CODE_EXCEPTION_MASK) { + uint8_t exception = raw[2]; + ESP_LOGW(TAG, + "Error function code: 0x%X exception: %" PRIu8 ", address: %" PRIu8 ", %" PRIu32 + "ms after last send", + function_code, exception, address, millis() - this->last_send_); + if (this->waiting_for_response_ == address) { + device->on_modbus_error(function_code & FUNCTION_CODE_MASK, exception); + } else { + // Ignore modbus exception not related to a pending command + ESP_LOGD(TAG, "Ignoring error - not expecting a response from %" PRIu8 "", address); + } + } else { // Not an error response + if (this->waiting_for_response_ == address) { + device->on_modbus_data(data); + } else { + // Ignore modbus response not related to a pending command + ESP_LOGW(TAG, "Ignoring response - not expecting a response from %" PRIu8 ", %" PRIu32 "ms after last send", + address, millis() - this->last_send_); + } } } - // fallthrough for other function codes - device->on_modbus_data(data); } } - waiting_for_response = 0; - if (!found) { - ESP_LOGW(TAG, "Got Modbus frame from unknown address 0x%02X! ", address); + if (!found && this->role == ModbusRole::CLIENT) { + ESP_LOGW(TAG, "Got frame from unknown address %" PRIu8 ", %" PRIu32 "ms after last send", address, + millis() - this->last_send_); } - // reset buffer - ESP_LOGV(TAG, "Clearing buffer of %d bytes - parse succeeded", at); - this->rx_buffer_.clear(); + this->clear_rx_buffer_(LOG_STR("parse succeeded")); + + if (this->waiting_for_response_ == address) + this->waiting_for_response_ = 0; + return true; } +void Modbus::send_next_frame_() { + if (this->tx_buffer_.empty()) + return; + + if (this->tx_blocked()) + return; + + const ModbusDeviceCommand &frame = this->tx_buffer_.front(); + + if (this->role == ModbusRole::CLIENT) { + this->waiting_for_response_ = frame.data.get()[0]; + } + + if (this->flow_control_pin_ != nullptr) { + this->flow_control_pin_->digital_write(true); + this->write_array(frame.data.get(), frame.size); + this->flush(); + this->flow_control_pin_->digital_write(false); + this->last_send_tx_offset_ = 0; + } else { + this->write_array(frame.data.get(), frame.size); + this->last_send_tx_offset_ = frame.size * 11 * 1000 / this->parent_->get_baud_rate() + 1; + } + +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; +#endif + ESP_LOGV(TAG, "Write: %s %" PRIu32 "ms after last send", format_hex_pretty_to(hex_buf, frame.data.get(), frame.size), + millis() - this->last_send_); + this->last_send_ = millis(); + this->tx_buffer_.pop_front(); + if (!this->tx_buffer_.empty()) { + ESP_LOGV(TAG, "Write queue contains %" PRIu32 " items.", this->tx_buffer_.size()); + } +} + void Modbus::dump_config() { ESP_LOGCONFIG(TAG, "Modbus:\n" " Send Wait Time: %d ms\n" + " Turnaround Time: %d ms\n" + " Frame Delay: %d ms\n" + " Long Rx Buffer Delay: %d ms\n" " CRC Disabled: %s", - this->send_wait_time_, YESNO(this->disable_crc_)); + this->send_wait_time_, this->turnaround_delay_ms_, this->frame_delay_ms_, + this->long_rx_buffer_delay_ms_, YESNO(this->disable_crc_)); LOG_PIN(" Flow Control Pin: ", this->flow_control_pin_); } float Modbus::get_setup_priority() const { @@ -228,15 +333,6 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address return; } - static constexpr size_t ADDR_SIZE = 1; - static constexpr size_t FC_SIZE = 1; - static constexpr size_t START_ADDR_SIZE = 2; - static constexpr size_t NUM_ENTITIES_SIZE = 2; - static constexpr size_t BYTE_COUNT_SIZE = 1; - static constexpr size_t MAX_PAYLOAD_SIZE = std::numeric_limits<uint8_t>::max(); - static constexpr size_t CRC_SIZE = 2; - static constexpr size_t MAX_FRAME_SIZE = - ADDR_SIZE + FC_SIZE + START_ADDR_SIZE + NUM_ENTITIES_SIZE + BYTE_COUNT_SIZE + MAX_PAYLOAD_SIZE + CRC_SIZE; uint8_t data[MAX_FRAME_SIZE]; size_t pos = 0; @@ -259,29 +355,16 @@ void Modbus::send(uint8_t address, uint8_t function_code, uint16_t start_address } else { payload_len = 2; // Write single register or coil } + if (payload_len + pos + 2 > MAX_FRAME_SIZE) { // Check if payload fits (accounting for CRC) + ESP_LOGE(TAG, "Payload too large to send: %d bytes", payload_len); + return; + } for (int i = 0; i < payload_len; i++) { data[pos++] = payload[i]; } } - auto crc = crc16(data, pos); - data[pos++] = crc >> 0; - data[pos++] = crc >> 8; - - if (this->flow_control_pin_ != nullptr) - this->flow_control_pin_->digital_write(true); - - this->write_array(data, pos); - this->flush(); - - if (this->flow_control_pin_ != nullptr) - this->flow_control_pin_->digital_write(false); - waiting_for_response = address; - last_send_ = millis(); -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE - char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; -#endif - ESP_LOGV(TAG, "Modbus write: %s", format_hex_pretty_to(hex_buf, data, pos)); + this->queue_raw_(data, pos); } // Helper function for lambdas @@ -290,23 +373,44 @@ void Modbus::send_raw(const std::vector<uint8_t> &payload) { if (payload.empty()) { return; } + // Frame size: payload + CRC(2) + if (payload.size() + 2 > MAX_FRAME_SIZE) { + ESP_LOGE(TAG, "Attempted to send frame larger than max frame size of %d bytes", MAX_FRAME_SIZE); + return; + } + // Use stack buffer - Modbus frames are small and bounded + uint8_t data[MAX_FRAME_SIZE]; - if (this->flow_control_pin_ != nullptr) - this->flow_control_pin_->digital_write(true); + std::memcpy(data, payload.data(), payload.size()); - auto crc = crc16(payload.data(), payload.size()); - this->write_array(payload); - this->write_byte(crc & 0xFF); - this->write_byte((crc >> 8) & 0xFF); - this->flush(); - if (this->flow_control_pin_ != nullptr) - this->flow_control_pin_->digital_write(false); - waiting_for_response = payload[0]; -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE - char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; + this->queue_raw_(data, payload.size()); +} + +// Assume data and length is valid and append CRC, then queue for sending. Used internally to avoid unnecessary copying +// of data into vectors +void Modbus::queue_raw_(const uint8_t *data, uint16_t len) { + if (this->tx_buffer_.size() < MODBUS_TX_BUFFER_SIZE) { + this->tx_buffer_.emplace_back(data, len); + } else { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_ERROR + char hex_buf[format_hex_pretty_size(MODBUS_MAX_LOG_BYTES)]; #endif - ESP_LOGV(TAG, "Modbus write raw: %s", format_hex_pretty_to(hex_buf, payload.data(), payload.size())); - last_send_ = millis(); + ESP_LOGE(TAG, "Write buffer full, dropped: %s", format_hex_pretty_to(hex_buf, data, len)); + } +} + +void Modbus::clear_rx_buffer_(const LogString *reason, bool warn) { + size_t at = this->rx_buffer_.size(); + if (at > 0) { + if (warn) { + ESP_LOGW(TAG, "Clearing buffer of %" PRIu32 " bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), + millis() - this->last_send_); + } else { + ESP_LOGV(TAG, "Clearing buffer of %" PRIu32 " bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), + millis() - this->last_send_); + } + this->rx_buffer_.clear(); + } } } // namespace modbus diff --git a/esphome/components/modbus/modbus.h b/esphome/components/modbus/modbus.h index fac74aaadf..c90d4c78ae 100644 --- a/esphome/components/modbus/modbus.h +++ b/esphome/components/modbus/modbus.h @@ -5,11 +5,16 @@ #include "esphome/components/modbus/modbus_definitions.h" +#include <cstring> +#include <memory> #include <vector> +#include <queue> namespace esphome { namespace modbus { +static constexpr uint16_t MODBUS_TX_BUFFER_SIZE = 15; + enum ModbusRole { CLIENT, SERVER, @@ -17,6 +22,19 @@ enum ModbusRole { class ModbusDevice; +struct ModbusDeviceCommand { + // Frame with exact-size allocation to avoid std::vector overhead + std::unique_ptr<uint8_t[]> data; + uint16_t size; // Modbus RTU max is 256 bytes + + ModbusDeviceCommand(const uint8_t *src, uint16_t len) : data(std::make_unique<uint8_t[]>(len + 2)), size(len + 2) { + std::memcpy(this->data.get(), src, len); + auto crc = crc16(data.get(), len); + data[len + 0] = crc >> 0; + data[len + 1] = crc >> 8; + } +}; + class Modbus : public uart::UARTDevice, public Component { public: Modbus() = default; @@ -30,28 +48,45 @@ class Modbus : public uart::UARTDevice, public Component { void register_device(ModbusDevice *device) { this->devices_.push_back(device); } float get_setup_priority() const override; + bool tx_buffer_empty(); + bool tx_blocked(); void send(uint8_t address, uint8_t function_code, uint16_t start_address, uint16_t number_of_entities, uint8_t payload_len = 0, const uint8_t *payload = nullptr); void send_raw(const std::vector<uint8_t> &payload); void set_role(ModbusRole role) { this->role = role; } void set_flow_control_pin(GPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; } - uint8_t waiting_for_response{0}; - void set_send_wait_time(uint16_t time_in_ms) { send_wait_time_ = time_in_ms; } - void set_disable_crc(bool disable_crc) { disable_crc_ = disable_crc; } + void set_send_wait_time(uint16_t time_in_ms) { this->send_wait_time_ = time_in_ms; } + void set_turnaround_time(uint16_t time_in_ms) { this->turnaround_delay_ms_ = time_in_ms; } + void set_disable_crc(bool disable_crc) { this->disable_crc_ = disable_crc; } ModbusRole role; protected: - GPIOPin *flow_control_pin_{nullptr}; - bool parse_modbus_byte_(uint8_t byte); - uint16_t send_wait_time_{250}; - bool disable_crc_; - std::vector<uint8_t> rx_buffer_; + void receive_and_parse_modbus_bytes_(); + void clear_rx_buffer_(const LogString *reason, bool warn = false); + void send_next_frame_(); + void queue_raw_(const uint8_t *data, uint16_t len); + uint32_t last_modbus_byte_{0}; uint32_t last_send_{0}; + uint32_t last_send_tx_offset_{0}; + uint16_t frame_delay_ms_{5}; + uint16_t long_rx_buffer_delay_ms_{0}; + uint16_t send_wait_time_{250}; + uint16_t turnaround_delay_ms_{100}; + uint8_t waiting_for_response_{0}; + bool disable_crc_{false}; + + GPIOPin *flow_control_pin_{nullptr}; + + std::vector<uint8_t> rx_buffer_; std::vector<ModbusDevice *> devices_; + // std::deque is appropriate here since we need a FIFO buffer, and we can't know ahead of time how many + // requests will be queued. Each modbus component may queue multiple requests, and the sequence of scheduling + // may change at run time. + std::deque<ModbusDeviceCommand> tx_buffer_; }; class ModbusDevice { @@ -76,7 +111,9 @@ class ModbusDevice { this->send_raw(error_response); } // If more than one device is connected block sending a new command before a response is received - bool waiting_for_response() { return parent_->waiting_for_response != 0; } + ESPDEPRECATED("Use ready_for_immediate_send() instead. Removed in 2026.9.0", "2026.3.0") + bool waiting_for_response() { return !ready_for_immediate_send(); } + bool ready_for_immediate_send() { return parent_->tx_buffer_empty() && !parent_->tx_blocked(); } protected: friend Modbus; diff --git a/esphome/components/modbus/modbus_definitions.h b/esphome/components/modbus/modbus_definitions.h index 07f101ae4c..c86d548578 100644 --- a/esphome/components/modbus/modbus_definitions.h +++ b/esphome/components/modbus/modbus_definitions.h @@ -81,6 +81,8 @@ const uint8_t MAX_NUM_OF_REGISTERS_TO_WRITE = 123; // 0x7B // 6.3 03 (0x03) Read Holding Registers // 6.4 04 (0x04) Read Input Registers const uint8_t MAX_NUM_OF_REGISTERS_TO_READ = 125; // 0x7D + +static constexpr uint16_t MAX_FRAME_SIZE = 256; /// End of Modbus definitions } // namespace modbus } // namespace esphome diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index c45c338bb3..aea79b2053 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -48,6 +48,7 @@ CONF_SERVER_REGISTERS = "server_registers" MULTI_CONF = True modbus_controller_ns = cg.esphome_ns.namespace("modbus_controller") +modbus_ns = cg.esphome_ns.namespace("modbus") ModbusController = modbus_controller_ns.class_( "ModbusController", cg.PollingComponent, modbus.ModbusDevice ) @@ -56,7 +57,7 @@ SensorItem = modbus_controller_ns.struct("SensorItem") ServerCourtesyResponse = modbus_controller_ns.struct("ServerCourtesyResponse") ServerRegister = modbus_controller_ns.struct("ServerRegister") -ModbusFunctionCode_ns = modbus_controller_ns.namespace("ModbusFunctionCode") +ModbusFunctionCode_ns = modbus_ns.namespace("ModbusFunctionCode") ModbusFunctionCode = ModbusFunctionCode_ns.enum("ModbusFunctionCode") MODBUS_FUNCTION_CODE = { "read_coils": ModbusFunctionCode.READ_COILS, diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 50bd9f45cb..7f0eb230e0 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -18,7 +18,7 @@ void ModbusController::setup() { this->create_register_ranges_(); } bool ModbusController::send_next_command_() { uint32_t last_send = millis() - this->last_command_timestamp_; - if ((last_send > this->command_throttle_) && !waiting_for_response() && !this->command_queue_.empty()) { + if ((last_send > this->command_throttle_) && this->ready_for_immediate_send() && !this->command_queue_.empty()) { auto &command = this->command_queue_.front(); // remove from queue if command was sent too often diff --git a/tests/components/modbus/common.yaml b/tests/components/modbus/common.yaml index d636143ec9..221aab4ed8 100644 --- a/tests/components/modbus/common.yaml +++ b/tests/components/modbus/common.yaml @@ -1,3 +1,5 @@ modbus: id: mod_bus1 flow_control_pin: ${flow_control_pin} + send_wait_time: 500ms + turnaround_time: 100ms diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py index abb3abcc41..c10d73354e 100644 --- a/tests/integration/fixtures/external_components/uart_mock/__init__.py +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -71,6 +71,7 @@ RESPONSE_SCHEMA = cv.Schema( { cv.Required(CONF_EXPECT_TX): [cv.hex_uint8_t], cv.Required(CONF_INJECT_RX): [cv.hex_uint8_t], + cv.Optional(CONF_DELAY, default="0ms"): cv.positive_time_period_milliseconds, } ) @@ -151,7 +152,8 @@ async def to_code(config): for response in config[CONF_RESPONSES]: tx_data = response[CONF_EXPECT_TX] rx_data = response[CONF_INJECT_RX] - cg.add(var.add_response(tx_data, rx_data)) + delay_ms = response[CONF_DELAY] + cg.add(var.add_response(tx_data, rx_data, delay_ms)) for periodic in config[CONF_PERIODIC_RX]: data = periodic[CONF_DATA] diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index 83a13793be..affcc8d908 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -36,8 +36,8 @@ void MockUartComponent::loop() { // component (e.g., LD2410) a chance to process each batch independently. if (this->injection_index_ < this->injections_.size()) { auto &injection = this->injections_[this->injection_index_]; - uint32_t target_time = this->scenario_start_ms_ + this->cumulative_delay_ms_ + injection.delay_ms; - if (now >= target_time) { + uint32_t total_delay = this->cumulative_delay_ms_ + injection.delay_ms; + if (now - this->scenario_start_ms_ >= total_delay) { ESP_LOGD(TAG, "Injecting %zu RX bytes (injection %u)", injection.rx_data.size(), this->injection_index_); this->inject_to_rx_buffer(injection.rx_data); this->cumulative_delay_ms_ += injection.delay_ms; @@ -52,6 +52,15 @@ void MockUartComponent::loop() { periodic.last_inject_ms = now; } } + + // Process delayed responses + for (auto &response : this->responses_) { + if (response.delay_ms > 0 && response.last_match_ms > 0 && now - response.last_match_ms >= response.delay_ms) { + ESP_LOGD(TAG, "Injecting %zu RX bytes for delayed response", response.inject_rx.size()); + this->inject_to_rx_buffer(response.inject_rx); + response.last_match_ms = 0; // Reset to prevent repeated injection + } + } } void MockUartComponent::start_scenario() { @@ -149,8 +158,9 @@ void MockUartComponent::add_injection(const std::vector<uint8_t> &rx_data, uint3 this->injections_.push_back({rx_data, delay_ms}); } -void MockUartComponent::add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx) { - this->responses_.push_back({expect_tx, inject_rx}); +void MockUartComponent::add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx, + uint32_t delay_ms) { + this->responses_.push_back({expect_tx, inject_rx, delay_ms, 0}); } void MockUartComponent::add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms) { @@ -166,7 +176,13 @@ void MockUartComponent::try_match_response_() { size_t offset = this->tx_buffer_.size() - response.expect_tx.size(); if (std::equal(response.expect_tx.begin(), response.expect_tx.end(), this->tx_buffer_.begin() + offset)) { ESP_LOGD(TAG, "TX match found, injecting %zu RX bytes", response.inject_rx.size()); - this->inject_to_rx_buffer(response.inject_rx); + if (response.delay_ms > 0) { + ESP_LOGD(TAG, "Delaying response by %u ms", response.delay_ms); + // Schedule the response injection as a future injection + response.last_match_ms = App.get_loop_component_start_time(); + } else { + this->inject_to_rx_buffer(response.inject_rx); + } this->tx_buffer_.clear(); return; } diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index b721512f96..901e371dec 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -34,7 +34,8 @@ class MockUartComponent : public uart::UARTComponent, public Component { // Scenario configuration - called from generated code void add_injection(const std::vector<uint8_t> &rx_data, uint32_t delay_ms); - void add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx); + void add_response(const std::vector<uint8_t> &expect_tx, const std::vector<uint8_t> &inject_rx, + uint32_t delay_ms = 0); void add_periodic_rx(const std::vector<uint8_t> &data, uint32_t interval_ms); void start_scenario(); @@ -64,6 +65,8 @@ class MockUartComponent : public uart::UARTComponent, public Component { struct Response { std::vector<uint8_t> expect_tx; std::vector<uint8_t> inject_rx; + uint32_t delay_ms; + uint32_t last_match_ms{0}; }; std::vector<Response> responses_; std::vector<uint8_t> tx_buffer_; diff --git a/tests/integration/fixtures/uart_mock_modbus.yaml b/tests/integration/fixtures/uart_mock_modbus.yaml index 0a3492a0d2..3ff7ab01bd 100644 --- a/tests/integration/fixtures/uart_mock_modbus.yaml +++ b/tests/integration/fixtures/uart_mock_modbus.yaml @@ -25,20 +25,64 @@ uart_mock: auto_start: false debug: responses: - - expect_tx: [0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A] # Read holding register 1 on device 1 + - expect_tx: [0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A] # Read holding register 3 on device 1 (basic_register) inject_rx: [0x01, 0x03, 0x02, 0x01, 0x03, 0xF9, 0xD5] # Return value 0x0103 (hex) = 259 (dec) + - expect_tx: [0x01, 0x03, 0x00, 0x05, 0x00, 0x01, 0x94, 0x0B] # Read holding register 5 on device 1 (delayed_response) + delay: 100ms # Shorter than modbus send_wait_time of 200ms, should succeed + inject_rx: [0x01, 0x03, 0x02, 0x00, 0xFF, 0xF8, 0x04] # Return value 0x00FF (hex) = 255 (dec) + - expect_tx: [0x02, 0x03, 0x00, 0x07, 0x00, 0x01, 0x35, 0xF8] # Read holding register 7 on device 2 (late_response) + delay: 300ms # Longer than modbus send_wait_time of 200ms, should cause timeout + inject_rx: [0x02, 0x03, 0x02, 0x00, 0xF0, 0xFC, 0x00] # Return value 0x00F0 (hex) = 240 (dec) + - expect_tx: [0x03, 0x03, 0x00, 0x09, 0x00, 0x01, 0x55, 0xEA] # Read holding register 9 on device 3 (no_response) + inject_rx: [] # No response, should cause timeout + - expect_tx: [0x01, 0x03, 0x00, 0x0A, 0x00, 0x01, 0xA4, 0x08] # Read holding register A on device 1 (exception_response) + inject_rx: [0x01, 0x83, 0x02, 0xC0, 0xF1] # Exception response with code 2 (illegal data address) modbus: uart_id: virtual_uart_dev + send_wait_time: 200ms + turnaround_time: 10ms modbus_controller: - address: 1 + - address: 1 + id: modbus_controller_ok + max_cmd_retries: 0 + update_interval: 1s + - address: 2 + id: modbus_controller_slow + max_cmd_retries: 0 + update_interval: 1s + - address: 3 + id: modbus_controller_offline + max_cmd_retries: 0 + update_interval: 1s sensor: - platform: modbus_controller name: "basic_register" address: 0x03 register_type: holding + modbus_controller_id: modbus_controller_ok + - platform: modbus_controller + name: "delayed_response" + address: 0x05 + register_type: holding + modbus_controller_id: modbus_controller_ok + - platform: modbus_controller + name: "late_response" + address: 0x07 + register_type: holding + modbus_controller_id: modbus_controller_slow + - platform: modbus_controller + name: "no_response" + address: 0x09 + register_type: holding + modbus_controller_id: modbus_controller_offline + - platform: modbus_controller + name: "exception_response" + address: 0x0A + register_type: holding + modbus_controller_id: modbus_controller_ok button: - platform: template diff --git a/tests/integration/fixtures/uart_mock_modbus_timing.yaml b/tests/integration/fixtures/uart_mock_modbus_timing.yaml index c4e29e5fe8..f4cf0bde37 100644 --- a/tests/integration/fixtures/uart_mock_modbus_timing.yaml +++ b/tests/integration/fixtures/uart_mock_modbus_timing.yaml @@ -46,10 +46,12 @@ uart_mock: modbus: uart_id: virtual_uart_dev + turnaround_time: 10ms sensor: - platform: sdm_meter address: 2 + update_interval: 1s phase_a: voltage: name: sdm_voltage diff --git a/tests/integration/test_uart_mock_modbus.py b/tests/integration/test_uart_mock_modbus.py index bf3c069750..6901dc27fe 100644 --- a/tests/integration/test_uart_mock_modbus.py +++ b/tests/integration/test_uart_mock_modbus.py @@ -39,9 +39,17 @@ async def test_uart_mock_modbus( # Track sensor state updates (after initial state is swallowed) sensor_states: dict[str, list[float]] = { "basic_register": [], + "delayed_response": [], + "late_response": [], + "no_response": [], + "exception_response": [], } basic_register_changed = loop.create_future() + delayed_response_changed = loop.create_future() + late_response_changed = loop.create_future() + no_response_changed = loop.create_future() + exception_response_changed = loop.create_future() def on_state(state: EntityState) -> None: if isinstance(state, SensorState) and not state.missing_state: @@ -54,6 +62,23 @@ async def test_uart_mock_modbus( and not basic_register_changed.done() ): basic_register_changed.set_result(True) + elif ( + sensor_name == "delayed_response" + and state.state == 255.0 + and not delayed_response_changed.done() + ): + delayed_response_changed.set_result(True) + elif ( + sensor_name == "late_response" and not late_response_changed.done() + ): + late_response_changed.set_result(True) + elif sensor_name == "no_response" and not no_response_changed.done(): + no_response_changed.set_result(True) + elif ( + sensor_name == "exception_response" + and not exception_response_changed.done() + ): + exception_response_changed.set_result(True) async with ( run_compiled(yaml_config), @@ -79,20 +104,52 @@ async def test_uart_mock_modbus( assert start_btn is not None, "Start Scenario button not found" client.button_command(start_btn.key) + try: + await asyncio.wait_for(delayed_response_changed, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for delayed_response change. Received sensor states:\n" + f" delayed_response: {sensor_states['delayed_response']}\n" + ) + + try: + await asyncio.wait_for(late_response_changed, timeout=2.0) + pytest.fail( + f"late_response change should not have been triggered, but was. Received sensor states:\n" + f" late_response: {sensor_states['late_response']}\n" + ) + except TimeoutError: + pass # Expected timeout since we never inject a response for late_response + + try: + await asyncio.wait_for(no_response_changed, timeout=2.0) + pytest.fail( + f"no_response change should not have been triggered, but was. Received sensor states:\n" + f" no_response: {sensor_states['no_response']}\n" + ) + except TimeoutError: + pass # Expected timeout since we never inject a response for no_response + # Wait for basic register to be updated with successful parse try: - await asyncio.wait_for(basic_register_changed, timeout=15.0) + await asyncio.wait_for(basic_register_changed, timeout=2.0) except TimeoutError: pytest.fail( f"Timeout waiting for Basic Register change. Received sensor states:\n" f" basic_register: {sensor_states['basic_register']}\n" ) + try: + await asyncio.wait_for(exception_response_changed, timeout=2.0) + pytest.fail( + f"exception_response change should not have been triggered, but was. Received sensor states:\n" + f" exception_response: {sensor_states['exception_response']}\n" + ) + except TimeoutError: + pass + @pytest.mark.asyncio -@pytest.mark.xfail( - reason="There is a bug in UART which will timeout for long responses." -) async def test_uart_mock_modbus_timing( yaml_config: str, run_compiled: RunCompiledFunction, @@ -155,7 +212,7 @@ async def test_uart_mock_modbus_timing( # Wait for voltage to be updated with successful parse try: - await asyncio.wait_for(voltage_changed, timeout=15.0) + await asyncio.wait_for(voltage_changed, timeout=2.0) except TimeoutError: pytest.fail( f"Timeout waiting for SDM voltage change. Received sensor states:\n" From 3392e4d73b564877f1a7d9b4c80f534d24a48d56 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:08:58 -0500 Subject: [PATCH 1134/2030] [usb_uart][nextion][feedback][whirlpool][packet_transport][he60r][hc8][runtime_stats] Fix millis() wrapping bugs (#14474) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/feedback/feedback_cover.cpp | 13 +++++++++---- esphome/components/hc8/hc8.cpp | 16 ++++++++++------ esphome/components/hc8/hc8.h | 1 + esphome/components/he60r/he60r.cpp | 2 +- esphome/components/nextion/nextion.cpp | 6 +++--- .../packet_transport/packet_transport.cpp | 11 ++++++----- .../components/runtime_stats/runtime_stats.cpp | 14 +++----------- esphome/components/runtime_stats/runtime_stats.h | 10 +++++++--- esphome/components/usb_uart/usb_uart.cpp | 4 ++-- esphome/components/whirlpool/whirlpool.h | 2 +- esphome/core/component.cpp | 2 +- 11 files changed, 44 insertions(+), 37 deletions(-) diff --git a/esphome/components/feedback/feedback_cover.cpp b/esphome/components/feedback/feedback_cover.cpp index d247bada33..1dff210cd6 100644 --- a/esphome/components/feedback/feedback_cover.cpp +++ b/esphome/components/feedback/feedback_cover.cpp @@ -437,10 +437,15 @@ void FeedbackCover::recompute_position_() { } // check if we have an acceleration_wait_time, and remove from position computation - if (now > (this->start_dir_time_ + this->acceleration_wait_time_)) { - this->position += - dir * (now - std::max(this->start_dir_time_ + this->acceleration_wait_time_, this->last_recompute_time_)) / - (action_dur - this->acceleration_wait_time_); + if (now - this->start_dir_time_ > this->acceleration_wait_time_) { + uint32_t accel_end_time = this->start_dir_time_ + this->acceleration_wait_time_; + uint32_t effective_start; + if (static_cast<int32_t>(accel_end_time - this->last_recompute_time_) >= 0) { + effective_start = accel_end_time; + } else { + effective_start = this->last_recompute_time_; + } + this->position += dir * (now - effective_start) / (action_dur - this->acceleration_wait_time_); this->position = clamp(this->position, min_pos, max_pos); } this->last_recompute_time_ = now; diff --git a/esphome/components/hc8/hc8.cpp b/esphome/components/hc8/hc8.cpp index 4c2d367b24..900acca691 100644 --- a/esphome/components/hc8/hc8.cpp +++ b/esphome/components/hc8/hc8.cpp @@ -24,12 +24,16 @@ void HC8Component::setup() { } void HC8Component::update() { - uint32_t now_ms = App.get_loop_component_start_time(); - uint32_t warmup_ms = this->warmup_seconds_ * 1000; - if (now_ms < warmup_ms) { - ESP_LOGW(TAG, "HC8 warming up, %" PRIu32 " s left", (warmup_ms - now_ms) / 1000); - this->status_set_warning(); - return; + if (!this->warmup_complete_) { + uint32_t now_ms = App.get_loop_component_start_time(); + uint32_t warmup_ms = this->warmup_seconds_ * 1000; + if (now_ms < warmup_ms) { + ESP_LOGW(TAG, "HC8 warming up, %" PRIu32 " s left", (warmup_ms - now_ms) / 1000); + this->status_set_warning(); + return; + } + this->warmup_complete_ = true; + this->status_clear_warning(); } while (this->available()) diff --git a/esphome/components/hc8/hc8.h b/esphome/components/hc8/hc8.h index 74257fab14..b060f38a80 100644 --- a/esphome/components/hc8/hc8.h +++ b/esphome/components/hc8/hc8.h @@ -23,6 +23,7 @@ class HC8Component : public PollingComponent, public uart::UARTDevice { protected: sensor::Sensor *co2_sensor_{nullptr}; uint32_t warmup_seconds_{0}; + bool warmup_complete_{false}; }; template<typename... Ts> class HC8CalibrateAction : public Action<Ts...>, public Parented<HC8Component> { diff --git a/esphome/components/he60r/he60r.cpp b/esphome/components/he60r/he60r.cpp index fdcd1a29c0..47440cc1f7 100644 --- a/esphome/components/he60r/he60r.cpp +++ b/esphome/components/he60r/he60r.cpp @@ -239,7 +239,7 @@ void HE60rCover::recompute_position_() { return; const uint32_t now = millis(); - if (now > this->last_recompute_time_) { + if (now != this->last_recompute_time_) { auto diff = (unsigned) (now - last_recompute_time_); float delta; switch (this->current_operation) { diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 9f1ce47837..c8c1b6fa41 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -337,7 +337,7 @@ void Nextion::loop() { this->started_ms_ = App.get_loop_component_start_time(); if (this->startup_override_ms_ > 0 && - this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) { + App.get_loop_component_start_time() - this->started_ms_ > this->startup_override_ms_) { ESP_LOGV(TAG, "Manual ready set"); this->connection_state_.nextion_reports_is_setup_ = true; } @@ -853,10 +853,10 @@ void Nextion::process_nextion_commands_() { const uint32_t ms = App.get_loop_component_start_time(); if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() && - this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) { + ms - this->nextion_queue_.front()->queue_time > this->max_q_age_ms_) { for (size_t i = 0; i < this->nextion_queue_.size(); i++) { NextionComponentBase *component = this->nextion_queue_[i]->component; - if (this->nextion_queue_[i]->queue_time + this->max_q_age_ms_ < ms) { + if (ms - this->nextion_queue_[i]->queue_time > this->max_q_age_ms_) { if (this->nextion_queue_[i]->queue_time == 0) { ESP_LOGD(TAG, "Remove old queue '%s':'%s' (t=0)", component->get_queue_type_string().c_str(), component->get_variable_name().c_str()); diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index f241cc6114..6f1286b469 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -330,15 +330,16 @@ void PacketTransport::update() { if (!this->ping_pong_enable_) { return; } - auto now = millis() / 1000; - if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) { + uint32_t now = millis(); + uint32_t ping_request_age = now - this->last_key_time_; + if (ping_request_age > this->ping_pong_recyle_time_ * 1000u) { this->resend_ping_key_ = this->ping_pong_enable_; - ESP_LOGV(TAG, "Ping request, age %" PRIu32, now - this->last_key_time_); + ESP_LOGV(TAG, "Ping request, age %" PRIu32, ping_request_age); this->last_key_time_ = now; } for (const auto &provider : this->providers_) { uint32_t key_response_age = now - provider.second.last_key_response_time; - if (key_response_age > (this->ping_pong_recyle_time_ * 2u)) { + if (key_response_age > (this->ping_pong_recyle_time_ * 2000u)) { #ifdef USE_STATUS_SENSOR if (provider.second.status_sensor != nullptr && provider.second.status_sensor->state) { ESP_LOGI(TAG, "Ping status for %s timeout at %" PRIu32 " with age %" PRIu32, provider.first.c_str(), now, @@ -496,7 +497,7 @@ void PacketTransport::process_(std::span<const uint8_t> data) { if (decoder.decode(PING_KEY, key) == DECODE_OK) { if (key == this->ping_key_) { ping_key_seen = true; - provider.last_key_response_time = millis() / 1000; + provider.last_key_response_time = millis(); ESP_LOGV(TAG, "Found good ping key %X at timestamp %" PRIu32, (unsigned) key, provider.last_key_response_time); } else { ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key); diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index d9fa22d949..cb28acc96c 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -9,21 +9,16 @@ namespace esphome { namespace runtime_stats { -RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_time_(0) { +RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_time_(60000) { global_runtime_stats = this; } -void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_us, uint32_t current_time) { +void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_us) { if (component == nullptr) return; // Record stats using component pointer as key this->component_stats_[component].record_time(duration_us); - - if (this->next_log_time_ == 0) { - this->next_log_time_ = current_time + this->log_interval_; - return; - } } void RuntimeStatsCollector::log_stats_() { @@ -88,10 +83,7 @@ void RuntimeStatsCollector::log_stats_() { } void RuntimeStatsCollector::process_pending_stats(uint32_t current_time) { - if (this->next_log_time_ == 0) - return; - - if (current_time >= this->next_log_time_) { + if ((int32_t) (current_time - this->next_log_time_) >= 0) { this->log_stats_(); this->reset_stats_(); this->next_log_time_ = current_time + this->log_interval_; diff --git a/esphome/components/runtime_stats/runtime_stats.h b/esphome/components/runtime_stats/runtime_stats.h index 0847529720..303d895985 100644 --- a/esphome/components/runtime_stats/runtime_stats.h +++ b/esphome/components/runtime_stats/runtime_stats.h @@ -7,6 +7,7 @@ #include <map> #include <cstdint> #include <cstring> +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -80,10 +81,13 @@ class RuntimeStatsCollector { public: RuntimeStatsCollector(); - void set_log_interval(uint32_t log_interval) { this->log_interval_ = log_interval; } + void set_log_interval(uint32_t log_interval) { + this->log_interval_ = log_interval; + this->next_log_time_ = millis() + log_interval; + } uint32_t get_log_interval() const { return this->log_interval_; } - void record_component_time(Component *component, uint32_t duration_us, uint32_t current_time); + void record_component_time(Component *component, uint32_t duration_us); // Process any pending stats printing (should be called after component loop) void process_pending_stats(uint32_t current_time); @@ -101,7 +105,7 @@ class RuntimeStatsCollector { // We use Component* as the key since each component is unique std::map<Component *, ComponentRuntimeStats> component_stats_; uint32_t log_interval_; - uint32_t next_log_time_; + uint32_t next_log_time_{0}; }; } // namespace runtime_stats diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 5c0397b2cb..e20bbd02db 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -171,8 +171,8 @@ void USBUartChannel::flush() { // Safe to call from the main loop only. // The 100 ms timeout guards against a device that stops responding mid-flush; // in that case the main loop is blocked for the full duration. - uint32_t deadline = millis() + 100; // 100 ms safety timeout - while ((!this->output_queue_.empty() || this->output_started_.load()) && millis() < deadline) { + uint32_t start = millis(); // 100 ms safety timeout + while ((!this->output_queue_.empty() || this->output_started_.load()) && millis() - start < 100) { // Kick start_output() in case data arrived but no transfer is in flight yet. this->parent_->start_output(this); yield(); diff --git a/esphome/components/whirlpool/whirlpool.h b/esphome/components/whirlpool/whirlpool.h index 907a21225c..992b2a7adf 100644 --- a/esphome/components/whirlpool/whirlpool.h +++ b/esphome/components/whirlpool/whirlpool.h @@ -48,7 +48,7 @@ class WhirlpoolClimate : public climate_ir::ClimateIR { /// Handle received IR Buffer bool on_receive(remote_base::RemoteReceiveData data) override; /// Set the time of the last transmission. - int32_t last_transmit_time_{}; + uint32_t last_transmit_time_{}; bool send_swing_cmd_{false}; Model model_; diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 8c2c8d38e8..a9ff3ec1eb 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -534,7 +534,7 @@ uint32_t WarnIfComponentBlockingGuard::finish() { // 1ms granularity, so results were essentially random noise. if (global_runtime_stats != nullptr) { uint32_t duration_us = micros() - this->started_us_; - global_runtime_stats->record_component_time(this->component_, duration_us, curr_time); + global_runtime_stats->record_component_time(this->component_, duration_us); } #endif if (blocking_time > WARN_IF_BLOCKING_OVER_MS) { From de14e7055e969d1e94302fdec544a2aa39d20e89 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:10:26 -0500 Subject: [PATCH 1135/2030] [cse7761][ads1115][tmp1075][matrix_keypad][seeed_mr60bha2] Fix assorted bugs (#14518) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/ads1115/ads1115.cpp | 15 ++------------- esphome/components/cse7761/cse7761.cpp | 10 +++++++--- .../components/matrix_keypad/matrix_keypad.cpp | 4 ++-- .../components/seeed_mr60bha2/seeed_mr60bha2.cpp | 12 ++++++++---- esphome/components/tmp1075/tmp1075.cpp | 4 ++-- 5 files changed, 21 insertions(+), 24 deletions(-) diff --git a/esphome/components/ads1115/ads1115.cpp b/esphome/components/ads1115/ads1115.cpp index f4996cd3b1..d493a6a6d3 100644 --- a/esphome/components/ads1115/ads1115.cpp +++ b/esphome/components/ads1115/ads1115.cpp @@ -173,19 +173,8 @@ float ADS1115Component::request_measurement(ADS1115Multiplexer multiplexer, ADS1 } if (resolution == ADS1015_12_BITS) { - bool negative = (raw_conversion >> 15) == 1; - - // shift raw_conversion as it's only 12-bits, left justified - raw_conversion = raw_conversion >> (16 - ADS1015_12_BITS); - - // check if number was negative in order to keep the sign - if (negative) { - // the number was negative - // 1) set the negative bit back - raw_conversion |= 0x8000; - // 2) reset the former (shifted) negative bit - raw_conversion &= 0xF7FF; - } + // ADS1015 returns 12-bit value left-justified in 16 bits; shift right and sign-extend + raw_conversion = static_cast<uint16_t>(static_cast<int16_t>(raw_conversion) >> (16 - ADS1015_12_BITS)); } auto signed_conversion = static_cast<int16_t>(raw_conversion); diff --git a/esphome/components/cse7761/cse7761.cpp b/esphome/components/cse7761/cse7761.cpp index f4966357d4..7525b901f8 100644 --- a/esphome/components/cse7761/cse7761.cpp +++ b/esphome/components/cse7761/cse7761.cpp @@ -147,13 +147,17 @@ uint32_t CSE7761Component::read_(uint8_t reg, uint8_t size) { } uint32_t CSE7761Component::coefficient_by_unit_(uint32_t unit) { + uint32_t coeff = 0; switch (unit) { case RMS_UC: - return 0x400000 * 100 / this->data_.coefficient[RMS_UC]; + coeff = this->data_.coefficient[RMS_UC]; + return coeff ? 0x400000 * 100 / coeff : 0; case RMS_IAC: - return (0x800000 * 100 / this->data_.coefficient[RMS_IAC]) * 10; // Stay within 32 bits + coeff = this->data_.coefficient[RMS_IAC]; + return coeff ? (0x800000 * 100 / coeff) * 10 : 0; // Stay within 32 bits case POWER_PAC: - return 0x80000000 / this->data_.coefficient[POWER_PAC]; + coeff = this->data_.coefficient[POWER_PAC]; + return coeff ? 0x80000000 / coeff : 0; } return 0; } diff --git a/esphome/components/matrix_keypad/matrix_keypad.cpp b/esphome/components/matrix_keypad/matrix_keypad.cpp index 43a20c49d1..febbe794e4 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.cpp +++ b/esphome/components/matrix_keypad/matrix_keypad.cpp @@ -61,7 +61,7 @@ void MatrixKeypad::loop() { ESP_LOGD(TAG, "key @ row %d, col %d released", row, col); for (auto &listener : this->listeners_) listener->button_released(row, col); - if (!this->keys_.empty()) { + if (this->pressed_key_ < (int) this->keys_.size()) { uint8_t keycode = this->keys_[this->pressed_key_]; ESP_LOGD(TAG, "key '%c' released", keycode); for (auto &listener : this->listeners_) @@ -84,7 +84,7 @@ void MatrixKeypad::loop() { ESP_LOGD(TAG, "key @ row %d, col %d pressed", row, col); for (auto &listener : this->listeners_) listener->button_pressed(row, col); - if (!this->keys_.empty()) { + if (key < (int) this->keys_.size()) { uint8_t keycode = this->keys_[key]; ESP_LOGD(TAG, "key '%c' pressed", keycode); for (auto &trigger : this->key_triggers_) diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp index 12f188fe03..8628faac5a 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp @@ -177,10 +177,14 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c uint16_t has_target_int = encode_uint16(data[1], data[0]); this->has_target_binary_sensor_->publish_state(has_target_int); if (has_target_int == 0) { - this->breath_rate_sensor_->publish_state(0.0); - this->heart_rate_sensor_->publish_state(0.0); - this->distance_sensor_->publish_state(0.0); - this->num_targets_sensor_->publish_state(0); + if (this->breath_rate_sensor_ != nullptr) + this->breath_rate_sensor_->publish_state(0.0); + if (this->heart_rate_sensor_ != nullptr) + this->heart_rate_sensor_->publish_state(0.0); + if (this->distance_sensor_ != nullptr) + this->distance_sensor_->publish_state(0.0); + if (this->num_targets_sensor_ != nullptr) + this->num_targets_sensor_->publish_state(0); } } break; diff --git a/esphome/components/tmp1075/tmp1075.cpp b/esphome/components/tmp1075/tmp1075.cpp index 9eb1e86c75..3c7ed01970 100644 --- a/esphome/components/tmp1075/tmp1075.cpp +++ b/esphome/components/tmp1075/tmp1075.cpp @@ -118,8 +118,8 @@ void TMP1075Sensor::send_alert_limit_high_() { } static uint16_t temp2regvalue(const float temp) { - const uint16_t regvalue = temp / 0.0625f; - return regvalue << 4; + const int16_t regvalue = static_cast<int16_t>(temp / 0.0625f); + return static_cast<uint16_t>(regvalue << 4); } static float regvalue2temp(const uint16_t regvalue) { From 06d6322fe3ce5d4c36a24a7fafb1711c647c4439 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 5 Mar 2026 15:19:45 -0600 Subject: [PATCH 1136/2030] [audio] Extract detect_audio_file_type helper (#14507) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/audio/audio.cpp | 56 +++++++++++++++++++++++ esphome/components/audio/audio.h | 7 +++ esphome/components/audio/audio_reader.cpp | 50 ++------------------ esphome/components/audio/audio_reader.h | 5 -- 4 files changed, 66 insertions(+), 52 deletions(-) diff --git a/esphome/components/audio/audio.cpp b/esphome/components/audio/audio.cpp index 40592f6107..3d675109e4 100644 --- a/esphome/components/audio/audio.cpp +++ b/esphome/components/audio/audio.cpp @@ -1,5 +1,9 @@ #include "audio.h" +#include "esphome/core/helpers.h" + +#include <cstring> + namespace esphome { namespace audio { @@ -58,6 +62,58 @@ const char *audio_file_type_to_string(AudioFileType file_type) { } } +AudioFileType detect_audio_file_type(const char *content_type, const char *url) { + // Try Content-Type header first + if (content_type != nullptr && content_type[0] != '\0') { +#ifdef USE_AUDIO_MP3_SUPPORT + if (strcasecmp(content_type, "mp3") == 0 || strcasecmp(content_type, "audio/mp3") == 0 || + strcasecmp(content_type, "audio/mpeg") == 0) { + return AudioFileType::MP3; + } +#endif + if (strcasecmp(content_type, "audio/wav") == 0) { + return AudioFileType::WAV; + } +#ifdef USE_AUDIO_FLAC_SUPPORT + if (strcasecmp(content_type, "audio/flac") == 0 || strcasecmp(content_type, "audio/x-flac") == 0) { + return AudioFileType::FLAC; + } +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + // Match "audio/ogg" with a codecs parameter containing "opus" + // Valid forms: audio/ogg;codecs=opus, audio/ogg; codecs="opus", etc. + // Plain "audio/ogg" without opus is not matched (almost always Ogg Vorbis) + if (strncasecmp(content_type, "audio/ogg", 9) == 0 && strcasestr(content_type + 9, "opus") != nullptr) { + return AudioFileType::OPUS; + } +#endif + } + + // Fallback to URL extension + if (url != nullptr && url[0] != '\0') { + if (str_endswith_ignore_case(url, ".wav")) { + return AudioFileType::WAV; + } +#ifdef USE_AUDIO_MP3_SUPPORT + if (str_endswith_ignore_case(url, ".mp3")) { + return AudioFileType::MP3; + } +#endif +#ifdef USE_AUDIO_FLAC_SUPPORT + if (str_endswith_ignore_case(url, ".flac")) { + return AudioFileType::FLAC; + } +#endif +#ifdef USE_AUDIO_OPUS_SUPPORT + if (str_endswith_ignore_case(url, ".opus")) { + return AudioFileType::OPUS; + } +#endif + } + + return AudioFileType::NONE; +} + void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor, size_t samples_to_scale) { // Note the assembly dsps_mulc function has audio glitches if the input and output buffers are the same. diff --git a/esphome/components/audio/audio.h b/esphome/components/audio/audio.h index 7d7db9e944..d3b41a362f 100644 --- a/esphome/components/audio/audio.h +++ b/esphome/components/audio/audio.h @@ -130,6 +130,13 @@ struct AudioFile { /// @return const char pointer to the readable file type const char *audio_file_type_to_string(AudioFileType file_type); +/// @brief Detect audio file type from a Content-Type header value and/or URL extension. +/// Tries Content-Type first, then falls back to URL extension. Either parameter may be null. +/// @param content_type Content-Type header value (may be null or empty) +/// @param url URL to inspect for file extension (may be null or empty) +/// @return The detected AudioFileType, or NONE if unknown +AudioFileType detect_audio_file_type(const char *content_type, const char *url); + /// @brief Scales Q15 fixed point audio samples. Scales in place if audio_samples == output_buffer. /// @param audio_samples PCM int16 audio samples /// @param output_buffer Buffer to store the scaled samples diff --git a/esphome/components/audio/audio_reader.cpp b/esphome/components/audio/audio_reader.cpp index 78d69d7a39..79ebf58889 100644 --- a/esphome/components/audio/audio_reader.cpp +++ b/esphome/components/audio/audio_reader.cpp @@ -185,26 +185,8 @@ esp_err_t AudioReader::start(const std::string &uri, AudioFileType &file_type) { return err; } - if (str_endswith_ignore_case(url, ".wav")) { - file_type = AudioFileType::WAV; - } -#ifdef USE_AUDIO_MP3_SUPPORT - else if (str_endswith_ignore_case(url, ".mp3")) { - file_type = AudioFileType::MP3; - } -#endif -#ifdef USE_AUDIO_FLAC_SUPPORT - else if (str_endswith_ignore_case(url, ".flac")) { - file_type = AudioFileType::FLAC; - } -#endif -#ifdef USE_AUDIO_OPUS_SUPPORT - else if (str_endswith_ignore_case(url, ".opus")) { - file_type = AudioFileType::OPUS; - } -#endif - else { - file_type = AudioFileType::NONE; + file_type = detect_audio_file_type(nullptr, url); + if (file_type == AudioFileType::NONE) { this->cleanup_connection_(); return ESP_ERR_NOT_SUPPORTED; } @@ -232,32 +214,6 @@ AudioReaderState AudioReader::read() { return AudioReaderState::FAILED; } -AudioFileType AudioReader::get_audio_type(const char *content_type) { -#ifdef USE_AUDIO_MP3_SUPPORT - if (strcasecmp(content_type, "mp3") == 0 || strcasecmp(content_type, "audio/mp3") == 0 || - strcasecmp(content_type, "audio/mpeg") == 0) { - return AudioFileType::MP3; - } -#endif - if (strcasecmp(content_type, "audio/wav") == 0) { - return AudioFileType::WAV; - } -#ifdef USE_AUDIO_FLAC_SUPPORT - if (strcasecmp(content_type, "audio/flac") == 0 || strcasecmp(content_type, "audio/x-flac") == 0) { - return AudioFileType::FLAC; - } -#endif -#ifdef USE_AUDIO_OPUS_SUPPORT - // Match "audio/ogg" with a codecs parameter containing "opus" - // Valid forms: audio/ogg;codecs=opus, audio/ogg; codecs="opus", etc. - // Plain "audio/ogg" without a codecs parameter is not matched, as those are almost always Ogg Vorbis streams - if (strncasecmp(content_type, "audio/ogg", 9) == 0 && strcasestr(content_type + 9, "opus") != nullptr) { - return AudioFileType::OPUS; - } -#endif - return AudioFileType::NONE; -} - esp_err_t AudioReader::http_event_handler(esp_http_client_event_t *evt) { // Based on https://github.com/maroc81/WeatherLily/tree/main/main/net accessed 20241224 AudioReader *this_reader = (AudioReader *) evt->user_data; @@ -265,7 +221,7 @@ esp_err_t AudioReader::http_event_handler(esp_http_client_event_t *evt) { switch (evt->event_id) { case HTTP_EVENT_ON_HEADER: if (strcasecmp(evt->header_key, "Content-Type") == 0) { - this_reader->audio_file_type_ = get_audio_type(evt->header_value); + this_reader->audio_file_type_ = detect_audio_file_type(evt->header_value, nullptr); } break; default: diff --git a/esphome/components/audio/audio_reader.h b/esphome/components/audio/audio_reader.h index 0b73923e84..753b310213 100644 --- a/esphome/components/audio/audio_reader.h +++ b/esphome/components/audio/audio_reader.h @@ -58,11 +58,6 @@ class AudioReader { /// @brief Monitors the http client events to attempt determining the file type from the Content-Type header static esp_err_t http_event_handler(esp_http_client_event_t *evt); - /// @brief Determines the audio file type from the http header's Content-Type key - /// @param content_type string with the Content-Type key - /// @return AudioFileType of the url, if it can be determined. If not, return AudioFileType::NONE. - static AudioFileType get_audio_type(const char *content_type); - AudioReaderState file_read_(); AudioReaderState http_read_(); From fbf63d8e3bec76734ae5eb2e487aca43e0747913 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 5 Mar 2026 11:23:00 -1000 Subject: [PATCH 1137/2030] [rp2040] Update arduino-pico to 5.5.1 and fix WiFi AP fallback (#14500) --- .clang-tidy.hash | 2 +- esphome/components/rp2040/__init__.py | 6 +- esphome/components/wifi/__init__.py | 8 +- .../components/wifi/wifi_component_pico_w.cpp | 81 ++++++++++++------- platformio.ini | 2 +- 5 files changed, 65 insertions(+), 34 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 767da3f33e..adcebadeb4 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -b97e16a84153b2a4cfc51137cd6121db3c32374504b2bea55144413b3e573052 +b6f8c16c1ddd222134bf4a71910b4c832e764e23caf49f9bce3280b079955fcf diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index ea269a47c5..1442a0a7f7 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -91,7 +91,7 @@ def _parse_platform_version(value): # The default/recommended arduino framework version # - https://github.com/earlephilhower/arduino-pico/releases # - https://api.registry.platformio.org/v3/packages/earlephilhower/tool/framework-arduinopico -RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 0) +RECOMMENDED_ARDUINO_FRAMEWORK_VERSION = cv.Version(5, 5, 1) # The raspberrypi platform version to use for arduino frameworks # - https://github.com/maxgerhardt/platform-raspberrypi/tags @@ -101,8 +101,8 @@ RECOMMENDED_ARDUINO_PLATFORM_VERSION = "v1.4.0-gcc14-arduinopico460" def _arduino_check_versions(value): value = value.copy() lookups = { - "dev": (cv.Version(5, 5, 0), "https://github.com/earlephilhower/arduino-pico"), - "latest": (cv.Version(5, 5, 0), None), + "dev": (cv.Version(5, 5, 1), "https://github.com/earlephilhower/arduino-pico"), + "latest": (cv.Version(5, 5, 1), None), "recommended": (RECOMMENDED_ARDUINO_FRAMEWORK_VERSION, None), } diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 2aa63b87cc..0f86ec059e 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -210,7 +210,13 @@ WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend( def wifi_network_ap(value): if value is None: value = {} - return WIFI_NETWORK_AP(value) + config = WIFI_NETWORK_AP(value) + if CONF_MANUAL_IP in config and CORE.is_rp2040: + raise cv.Invalid( + "Manual AP IP configuration is not supported on RP2040. " + "The AP uses the default IP 192.168.4.1" + ) + return config WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend( diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 270425d8c2..5140fb285e 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -18,6 +18,25 @@ namespace esphome::wifi { static const char *const TAG = "wifi_pico_w"; +// Check if STA is fully connected (WiFi joined + has IP address). +// Do NOT use WiFi.status() or WiFi.connected() for this — in AP-only mode they +// unconditionally return true regardless of STA state, causing false positives +// when the fallback AP is active. +static bool wifi_sta_connected() { + int link = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); + IPAddress local = WiFi.localIP(); + if (link == CYW43_LINK_JOIN && local.isSet()) { + // Verify the IP is a real STA IP, not the AP's IP leaking through + IPAddress ap_ip = WiFi.softAPIP(); + if (local == ap_ip) { + ESP_LOGV(TAG, "wifi_sta_connected: localIP %s matches AP IP, ignoring", local.toString().c_str()); + return false; + } + return true; + } + return false; +} + // Track previous state for detecting changes static bool s_sta_was_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static bool s_sta_had_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -27,17 +46,21 @@ bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) { if (sta.has_value()) { if (sta.value()) { cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_STA, true, CYW43_COUNTRY_WORLDWIDE); + } else { + // Leave the STA network so the radio is free for scanning. + // Use cyw43_wifi_leave directly to avoid corrupting Arduino framework state. + cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); } } - bool ap_state = false; if (ap.has_value()) { if (ap.value()) { cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_AP, true, CYW43_COUNTRY_WORLDWIDE); - ap_state = true; + } else { + cyw43_wifi_set_up(&cyw43_state, CYW43_ITF_AP, false, CYW43_COUNTRY_WORLDWIDE); } + this->ap_started_ = ap.value(); } - this->ap_started_ = ap_state; return true; } @@ -129,8 +152,8 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { int status = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA); switch (status) { case CYW43_LINK_JOIN: - // WiFi joined, check if we have an IP address via the Arduino framework's WiFi class - if (WiFi.status() == WL_CONNECTED) { + // WiFi joined, check if STA has an IP address via wifi_sta_connected() + if (wifi_sta_connected()) { return WiFiSTAConnectStatus::CONNECTED; } return WiFiSTAConnectStatus::CONNECTING; @@ -188,19 +211,9 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { #ifdef USE_WIFI_AP bool WiFiComponent::wifi_ap_ip_config_(const optional<ManualIP> &manual_ip) { - esphome::network::IPAddress ip_address, gateway, subnet, dns; - if (manual_ip.has_value()) { - ip_address = manual_ip->static_ip; - gateway = manual_ip->gateway; - subnet = manual_ip->subnet; - dns = manual_ip->static_ip; - } else { - ip_address = network::IPAddress(192, 168, 4, 1); - gateway = network::IPAddress(192, 168, 4, 1); - subnet = network::IPAddress(255, 255, 255, 0); - dns = network::IPAddress(192, 168, 4, 1); - } - WiFi.config(ip_address, dns, gateway, subnet); + // AP IP is configured by WiFi.beginAP() internally using defaults (192.168.4.1). + // Manual AP IP has never worked on RP2040 — WiFi.config() configures the STA + // interface, not the AP. This is now rejected at config validation time. return true; } @@ -219,18 +232,25 @@ bool WiFiComponent::wifi_start_ap_(const WiFiAP &ap) { } #endif - WiFi.beginAP(ap.ssid_.c_str(), ap.password_.c_str(), ap.has_channel() ? ap.get_channel() : 1); + // Pass nullptr for empty password — CYW43 uses the password pointer (not length) + // to choose between OPEN and WPA2 auth mode. + const char *ap_password = ap.password_.empty() ? nullptr : ap.password_.c_str(); + WiFi.beginAP(ap.ssid_.c_str(), ap_password, ap.has_channel() ? ap.get_channel() : 1); return true; } -network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t *) WiFi.localIP()}; } +network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {(const ip_addr_t *) WiFi.softAPIP()}; } #endif // USE_WIFI_AP bool WiFiComponent::wifi_disconnect_() { - // Use Arduino WiFi.disconnect() instead of raw cyw43_wifi_leave() to properly - // clean up the lwIP netif, DHCP client, and internal Arduino state. - WiFi.disconnect(); + // Use cyw43_wifi_leave() directly instead of WiFi.disconnect(). + // WiFi.disconnect() sets _wifiHWInitted=false in the Arduino framework. beginAP() + // uses _wifiHWInitted to determine AP+STA vs AP-only mode — with it false, + // beginAP() enters AP-only mode (IP 192.168.42.1) instead of AP_STA mode + // (IP 192.168.4.1). In AP-only mode, _beginInternal() redirects all subsequent + // STA connect attempts to beginAP(), creating an infinite loop. + cyw43_wifi_leave(&cyw43_state, CYW43_ITF_STA); return true; } @@ -251,14 +271,21 @@ const char *WiFiComponent::wifi_ssid_to(std::span<char, SSID_BUFFER_SIZE> buffer buffer[len] = '\0'; return buffer.data(); } -int8_t WiFiComponent::wifi_rssi() { return WiFi.status() == WL_CONNECTED ? WiFi.RSSI() : WIFI_RSSI_DISCONNECTED; } +int8_t WiFiComponent::wifi_rssi() { return this->is_connected_() ? WiFi.RSSI() : WIFI_RSSI_DISCONNECTED; } int32_t WiFiComponent::get_wifi_channel() { return WiFi.channel(); } network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { network::IPAddresses addresses; uint8_t index = 0; + // Filter out AP interface addresses — addrList includes all lwIP netifs. + // The AP netif IP lingers even after the AP radio is disabled. + IPAddress ap_ip = WiFi.softAPIP(); for (auto addr : addrList) { - addresses[index++] = addr.ipFromNetifNum(); + IPAddress ip(addr.ipFromNetifNum()); + if (ip == ap_ip) { + continue; + } + addresses[index++] = ip; } return addresses; } @@ -288,9 +315,7 @@ void WiFiComponent::wifi_loop_() { // Poll for connection state changes // The arduino-pico WiFi library doesn't have event callbacks like ESP8266/ESP32, // so we need to poll the link status to detect state changes. - // Use WiFi.connected() which checks both the WiFi link and IP address via the - // Arduino framework's own netif (not the SDK's uninitialized one). - bool is_connected = WiFi.connected(); + bool is_connected = wifi_sta_connected(); // Detect connection state change if (is_connected && !s_sta_was_connected) { diff --git a/platformio.ini b/platformio.ini index 16a1b18211..87f992759c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -196,7 +196,7 @@ board_build.filesystem_size = 0.5m platform = https://github.com/maxgerhardt/platform-raspberrypi.git#v1.4.0-gcc14-arduinopico460 platform_packages = ; earlephilhower/framework-arduinopico@~1.20602.0 ; Cannot use the platformio package until old releases stop getting deleted - earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.0/rp2040-5.5.0.zip + earlephilhower/framework-arduinopico@https://github.com/earlephilhower/arduino-pico/releases/download/5.5.1/rp2040-5.5.1.zip framework = arduino lib_deps = From e8b1dce67b2d31c1d8f9b2e44dc0d292d6e9d381 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 16:28:41 -0500 Subject: [PATCH 1138/2030] [st7735][st7789v][st7920] Fix display buffer overflows and dead code (#14511) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/st7735/st7735.cpp | 14 +------------ esphome/components/st7735/st7735.h | 1 - esphome/components/st7789v/st7789v.cpp | 29 +++++++++++++++++--------- esphome/components/st7920/st7920.cpp | 15 +++++++------ 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/esphome/components/st7735/st7735.cpp b/esphome/components/st7735/st7735.cpp index 58459b79bb..0fcfdd6c71 100644 --- a/esphome/components/st7735/st7735.cpp +++ b/esphome/components/st7735/st7735.cpp @@ -466,7 +466,7 @@ void HOT ST7735::write_display_data_() { } void ST7735::spi_master_write_addr_(uint16_t addr1, uint16_t addr2) { - static uint8_t byte[4]; + uint8_t byte[4]; byte[0] = (addr1 >> 8) & 0xFF; byte[1] = addr1 & 0xFF; byte[2] = (addr2 >> 8) & 0xFF; @@ -476,17 +476,5 @@ void ST7735::spi_master_write_addr_(uint16_t addr1, uint16_t addr2) { this->write_array(byte, 4); } -void ST7735::spi_master_write_color_(uint16_t color, uint16_t size) { - static uint8_t byte[1024]; - int index = 0; - for (int i = 0; i < size; i++) { - byte[index++] = (color >> 8) & 0xFF; - byte[index++] = color & 0xFF; - } - - this->dc_pin_->digital_write(true); - write_array(byte, size * 2); -} - } // namespace st7735 } // namespace esphome diff --git a/esphome/components/st7735/st7735.h b/esphome/components/st7735/st7735.h index 37fe673962..e81be520ed 100644 --- a/esphome/components/st7735/st7735.h +++ b/esphome/components/st7735/st7735.h @@ -68,7 +68,6 @@ class ST7735 : public display::DisplayBuffer, void set_addr_window_(uint16_t x, uint16_t y, uint16_t w, uint16_t h); void draw_absolute_pixel_internal(int x, int y, Color color) override; void spi_master_write_addr_(uint16_t addr1, uint16_t addr2); - void spi_master_write_color_(uint16_t color, uint16_t size); int get_width_internal() override; int get_height_internal() override; diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index cd0b6cabc3..6e4360ae74 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -1,11 +1,16 @@ #include "st7789v.h" #include "esphome/core/log.h" +#include <algorithm> namespace esphome { namespace st7789v { static const char *const TAG = "st7789v"; -static const size_t TEMP_BUFFER_SIZE = 128; +#ifdef USE_ESP32 +static constexpr size_t TEMP_BUFFER_SIZE = 1024; +#else +static constexpr size_t TEMP_BUFFER_SIZE = 512; +#endif void ST7789V::setup() { #ifdef USE_POWER_SUPPLY @@ -236,7 +241,7 @@ void ST7789V::write_data_(uint8_t value) { } void ST7789V::write_addr_(uint16_t addr1, uint16_t addr2) { - static uint8_t byte[4]; + uint8_t byte[4]; byte[0] = (addr1 >> 8) & 0xFF; byte[1] = addr1 & 0xFF; byte[2] = (addr2 >> 8) & 0xFF; @@ -247,15 +252,19 @@ void ST7789V::write_addr_(uint16_t addr1, uint16_t addr2) { } void ST7789V::write_color_(uint16_t color, uint16_t size) { - static uint8_t byte[1024]; - int index = 0; - for (int i = 0; i < size; i++) { - byte[index++] = (color >> 8) & 0xFF; - byte[index++] = color & 0xFF; - } - + uint8_t byte[TEMP_BUFFER_SIZE]; + uint16_t remaining = size; this->dc_pin_->digital_write(true); - write_array(byte, size * 2); + while (remaining > 0) { + uint16_t batch = std::min(remaining, static_cast<uint16_t>(sizeof(byte) / 2)); + int index = 0; + for (int i = 0; i < batch; i++) { + byte[index++] = (color >> 8) & 0xFF; + byte[index++] = color & 0xFF; + } + this->write_array(byte, batch * 2); + remaining -= batch; + } } size_t ST7789V::get_buffer_length_() { diff --git a/esphome/components/st7920/st7920.cpp b/esphome/components/st7920/st7920.cpp index afd7cd61bd..a840f98152 100644 --- a/esphome/components/st7920/st7920.cpp +++ b/esphome/components/st7920/st7920.cpp @@ -72,16 +72,19 @@ void ST7920::goto_xy_(uint16_t x, uint16_t y) { } void HOT ST7920::write_display_data() { - uint8_t i, j, b; - for (j = 0; j < (uint8_t) (this->get_height_internal() / 2); j++) { + int i, j; + uint8_t b; + int width_bytes = this->get_width_internal() / 8; + int half_height = this->get_height_internal() / 2; + for (j = 0; j < half_height; j++) { this->goto_xy_(0, j); this->enable(); - for (i = 0; i < 16; i++) { // 16 bytes from line #0+ - b = this->buffer_[i + j * 16]; + for (i = 0; i < width_bytes; i++) { + b = this->buffer_[i + j * width_bytes]; this->send_(LCD_DATA, b); } - for (i = 0; i < 16; i++) { // 16 bytes from line #32+ - b = this->buffer_[i + (j + 32) * 16]; + for (i = 0; i < width_bytes; i++) { + b = this->buffer_[i + (j + half_height) * width_bytes]; this->send_(LCD_DATA, b); } this->disable(); From b2c12d88fe15d31710365a0b8759317527abc2d7 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Thu, 5 Mar 2026 23:24:11 +0100 Subject: [PATCH 1139/2030] [uart] init tx_pin, rx_pin, flow control, rx_buffer_size (#14524) --- esphome/components/uart/uart_component.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index b6ffbbd51f..078ce64b30 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -183,10 +183,10 @@ class UARTComponent { virtual void check_logger_conflict() = 0; bool check_read_timeout_(size_t len = 1); - InternalGPIOPin *tx_pin_; - InternalGPIOPin *rx_pin_; - InternalGPIOPin *flow_control_pin_; - size_t rx_buffer_size_; + InternalGPIOPin *tx_pin_{}; + InternalGPIOPin *rx_pin_{}; + InternalGPIOPin *flow_control_pin_{}; + size_t rx_buffer_size_{}; size_t rx_full_threshold_{1}; size_t rx_timeout_{0}; uint32_t baud_rate_{0}; From 8a8f6824a200a8396a66f1873a7731504e75cc0b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 17:29:44 -0500 Subject: [PATCH 1140/2030] [openthread][ethernet][wifi] Add IPv6 address array bounds assert (#14488) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ethernet/ethernet_component.cpp | 1 + esphome/components/openthread/openthread.h | 2 +- esphome/components/openthread/openthread_esp.cpp | 1 + esphome/components/wifi/wifi_component_esp8266.cpp | 2 ++ esphome/components/wifi/wifi_component_esp_idf.cpp | 1 + esphome/components/wifi/wifi_component_pico_w.cpp | 3 +++ 6 files changed, 9 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 098f7be972..0bc67c8b03 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -470,6 +470,7 @@ network::IPAddresses EthernetComponent::get_ip_addresses() { uint8_t count = 0; count = esp_netif_get_all_ip6(this->eth_netif_, if_ip6s); assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + assert(count < addresses.size()); for (int i = 0; i < count; i++) { addresses[i + 1] = network::IPAddress(&if_ip6s[i]); } diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index d853c58f95..c87f4fa7c1 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -90,7 +90,7 @@ class InstanceLock { otInstance *get_instance(); private: - // Use a private constructor in order to force thehandling + // Use a private constructor in order to force the handling // of acquisition failure InstanceLock() {} }; diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 2296e32b7f..cdc7a404b2 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -197,6 +197,7 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() { esp_netif_t *netif = esp_netif_get_default_netif(); count = esp_netif_get_all_ip6(netif, if_ip6s); assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + assert(count < addresses.size()); for (int i = 0; i < count; i++) { addresses[i + 1] = network::IPAddress(&if_ip6s[i]); } diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 02ce59502b..355832b434 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -6,6 +6,7 @@ #include <user_interface.h> +#include <cassert> #include <utility> #include <algorithm> #ifdef USE_WIFI_WPA2_EAP @@ -205,6 +206,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { network::IPAddresses addresses; uint8_t index = 0; for (auto &addr : addrList) { + assert(index < addresses.size()); addresses[index++] = addr.ipFromNetifNum(); } return addresses; diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index bf432cea6e..eca3f19249 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -585,6 +585,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { uint8_t count = 0; count = esp_netif_get_all_ip6(s_sta_netif, if_ip6s); assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + assert(count < addresses.size()); for (int i = 0; i < count; i++) { addresses[i + 1] = network::IPAddress(&if_ip6s[i]); } diff --git a/esphome/components/wifi/wifi_component_pico_w.cpp b/esphome/components/wifi/wifi_component_pico_w.cpp index 5140fb285e..1cfeee3c1b 100644 --- a/esphome/components/wifi/wifi_component_pico_w.cpp +++ b/esphome/components/wifi/wifi_component_pico_w.cpp @@ -3,6 +3,8 @@ #ifdef USE_WIFI #ifdef USE_RP2040 +#include <cassert> + #include "lwip/dns.h" #include "lwip/err.h" #include "lwip/netif.h" @@ -285,6 +287,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { if (ip == ap_ip) { continue; } + assert(index < addresses.size()); addresses[index++] = ip; } return addresses; From 64098122e77cc893d5e2cc288a5b30e6a1744724 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 5 Mar 2026 16:30:13 -0600 Subject: [PATCH 1141/2030] [audio_file] Add media source platform (#14436) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CODEOWNERS | 1 + .../audio_file/media_source/__init__.py | 38 +++ .../media_source/audio_file_media_source.cpp | 283 ++++++++++++++++++ .../media_source/audio_file_media_source.h | 50 ++++ tests/components/audio_file/common.yaml | 4 + 5 files changed, 376 insertions(+) create mode 100644 esphome/components/audio_file/media_source/__init__.py create mode 100644 esphome/components/audio_file/media_source/audio_file_media_source.cpp create mode 100644 esphome/components/audio_file/media_source/audio_file_media_source.h diff --git a/CODEOWNERS b/CODEOWNERS index 7c37b20e09..8bf896d159 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -55,6 +55,7 @@ esphome/components/audio/* @kahrendt esphome/components/audio_adc/* @kbx81 esphome/components/audio_dac/* @kbx81 esphome/components/audio_file/* @kahrendt +esphome/components/audio_file/media_source/* @kahrendt esphome/components/axs15231/* @clydebarrow esphome/components/b_parasite/* @rbaron esphome/components/ballu/* @bazuchan diff --git a/esphome/components/audio_file/media_source/__init__.py b/esphome/components/audio_file/media_source/__init__.py new file mode 100644 index 0000000000..e9e292a2b2 --- /dev/null +++ b/esphome/components/audio_file/media_source/__init__.py @@ -0,0 +1,38 @@ +import esphome.codegen as cg +from esphome.components import media_source, psram +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_TASK_STACK_IN_PSRAM +from esphome.types import ConfigType + +CODEOWNERS = ["@kahrendt"] +AUTO_LOAD = ["audio"] +DEPENDENCIES = ["audio_file"] + +audio_file_ns = cg.esphome_ns.namespace("audio_file") +AudioFileMediaSource = audio_file_ns.class_( + "AudioFileMediaSource", cg.Component, media_source.MediaSource +) + +CONFIG_SCHEMA = cv.All( + media_source.media_source_schema( + AudioFileMediaSource, + ) + .extend( + { + cv.Optional(CONF_TASK_STACK_IN_PSRAM): cv.All( + cv.boolean, cv.requires_component(psram.DOMAIN) + ), + } + ) + .extend(cv.COMPONENT_SCHEMA), + cv.only_on_esp32, +) + + +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await media_source.register_media_source(var, config) + + if CONF_TASK_STACK_IN_PSRAM in config: + cg.add(var.set_task_stack_in_psram(config[CONF_TASK_STACK_IN_PSRAM])) diff --git a/esphome/components/audio_file/media_source/audio_file_media_source.cpp b/esphome/components/audio_file/media_source/audio_file_media_source.cpp new file mode 100644 index 0000000000..120f871d2f --- /dev/null +++ b/esphome/components/audio_file/media_source/audio_file_media_source.cpp @@ -0,0 +1,283 @@ +#include "audio_file_media_source.h" + +#ifdef USE_ESP32 + +#include "esphome/components/audio/audio_decoder.h" + +#include <cstring> + +namespace esphome::audio_file { + +namespace { // anonymous namespace for internal linkage +struct AudioSinkAdapter : public audio::AudioSinkCallback { + media_source::MediaSource *source; + audio::AudioStreamInfo stream_info; + + size_t audio_sink_write(uint8_t *data, size_t length, TickType_t ticks_to_wait) override { + return this->source->write_output(data, length, pdTICKS_TO_MS(ticks_to_wait), this->stream_info); + } +}; +} // namespace + +#if defined(USE_AUDIO_OPUS_SUPPORT) +static constexpr uint32_t DECODE_TASK_STACK_SIZE = 5 * 1024; +#else +static constexpr uint32_t DECODE_TASK_STACK_SIZE = 3 * 1024; +#endif + +static const char *const TAG = "audio_file_media_source"; + +enum EventGroupBits : uint32_t { + // Requests to start playback (set by play_uri, handled by loop) + REQUEST_START = (1 << 0), + // Commands from main loop to decode task + COMMAND_STOP = (1 << 1), + COMMAND_PAUSE = (1 << 2), + // Decode task lifecycle signals (one-shot, cleared by loop) + TASK_STARTING = (1 << 7), + TASK_RUNNING = (1 << 8), + TASK_STOPPING = (1 << 9), + TASK_STOPPED = (1 << 10), + TASK_ERROR = (1 << 11), + // Decode task state (level-triggered, set/cleared by decode task) + TASK_PAUSED = (1 << 12), + ALL_BITS = 0x00FFFFFF, // All valid FreeRTOS event group bits +}; + +void AudioFileMediaSource::dump_config() { + ESP_LOGCONFIG(TAG, "Audio File Media Source:"); + ESP_LOGCONFIG(TAG, " Task Stack in PSRAM: %s", this->task_stack_in_psram_ ? "Yes" : "No"); +} + +void AudioFileMediaSource::setup() { + this->disable_loop(); + + this->event_group_ = xEventGroupCreate(); + if (this->event_group_ == nullptr) { + ESP_LOGE(TAG, "Failed to create event group"); + this->mark_failed(); + return; + } +} + +void AudioFileMediaSource::loop() { + EventBits_t event_bits = xEventGroupGetBits(this->event_group_); + + if (event_bits & REQUEST_START) { + xEventGroupClearBits(this->event_group_, REQUEST_START); + this->decoding_state_ = AudioFileDecodingState::START_TASK; + } + + switch (this->decoding_state_) { + case AudioFileDecodingState::START_TASK: { + if (!this->decode_task_.is_created()) { + xEventGroupClearBits(this->event_group_, ALL_BITS); + if (!this->decode_task_.create(decode_task, "AudioFileDec", DECODE_TASK_STACK_SIZE, this, 1, + this->task_stack_in_psram_)) { + ESP_LOGE(TAG, "Failed to create task"); + this->status_momentary_error("task_create", 1000); + this->set_state_(media_source::MediaSourceState::ERROR); + this->decoding_state_ = AudioFileDecodingState::IDLE; + return; + } + } + this->decoding_state_ = AudioFileDecodingState::DECODING; + break; + } + case AudioFileDecodingState::DECODING: { + if (event_bits & TASK_STARTING) { + ESP_LOGD(TAG, "Starting"); + xEventGroupClearBits(this->event_group_, TASK_STARTING); + } + + if (event_bits & TASK_RUNNING) { + ESP_LOGV(TAG, "Started"); + xEventGroupClearBits(this->event_group_, TASK_RUNNING); + this->set_state_(media_source::MediaSourceState::PLAYING); + } + + if ((event_bits & TASK_PAUSED) && this->get_state() != media_source::MediaSourceState::PAUSED) { + this->set_state_(media_source::MediaSourceState::PAUSED); + } else if (!(event_bits & TASK_PAUSED) && this->get_state() == media_source::MediaSourceState::PAUSED) { + this->set_state_(media_source::MediaSourceState::PLAYING); + } + + if (event_bits & TASK_STOPPING) { + ESP_LOGV(TAG, "Stopping"); + xEventGroupClearBits(this->event_group_, TASK_STOPPING); + } + + if (event_bits & TASK_ERROR) { + // Report error so the orchestrator knows playback failed; task will have already logged the specific error + this->set_state_(media_source::MediaSourceState::ERROR); + } + + if (event_bits & TASK_STOPPED) { + ESP_LOGD(TAG, "Stopped"); + xEventGroupClearBits(this->event_group_, ALL_BITS); + + this->decode_task_.deallocate(); + this->set_state_(media_source::MediaSourceState::IDLE); + this->decoding_state_ = AudioFileDecodingState::IDLE; + } + break; + } + case AudioFileDecodingState::IDLE: { + if (this->get_state() == media_source::MediaSourceState::ERROR && !this->status_has_error()) { + this->set_state_(media_source::MediaSourceState::IDLE); + } + break; + } + } + + if ((this->decoding_state_ == AudioFileDecodingState::IDLE) && + (this->get_state() == media_source::MediaSourceState::IDLE)) { + this->disable_loop(); + } +} + +// Called from the orchestrator's main loop, so no synchronization needed with loop() +bool AudioFileMediaSource::play_uri(const std::string &uri) { + if (!this->is_ready() || this->is_failed() || this->status_has_error() || !this->has_listener() || + xEventGroupGetBits(this->event_group_) & REQUEST_START) { + return false; + } + + // Check if source is already playing + if (this->get_state() != media_source::MediaSourceState::IDLE) { + ESP_LOGE(TAG, "Cannot play '%s': source is busy", uri.c_str()); + return false; + } + + // Validate URI starts with "audio-file://" + if (!uri.starts_with("audio-file://")) { + ESP_LOGE(TAG, "Invalid URI: '%s'", uri.c_str()); + return false; + } + + // Strip "audio-file://" prefix and find the file + const char *file_id = uri.c_str() + 13; // "audio-file://" is 13 characters + + for (const auto &named_file : get_named_audio_files()) { + if (strcmp(named_file.file_id, file_id) == 0) { + this->current_file_ = named_file.file; + xEventGroupSetBits(this->event_group_, EventGroupBits::REQUEST_START); + this->enable_loop(); + return true; + } + } + + ESP_LOGE(TAG, "Unknown file: '%s'", file_id); + return false; +} + +// Called from the orchestrator's main loop, so no synchronization needed with loop() +void AudioFileMediaSource::handle_command(media_source::MediaSourceCommand command) { + if (this->decoding_state_ != AudioFileDecodingState::DECODING) { + return; + } + + switch (command) { + case media_source::MediaSourceCommand::STOP: + xEventGroupSetBits(this->event_group_, EventGroupBits::COMMAND_STOP); + break; + case media_source::MediaSourceCommand::PAUSE: + xEventGroupSetBits(this->event_group_, EventGroupBits::COMMAND_PAUSE); + break; + case media_source::MediaSourceCommand::PLAY: + xEventGroupClearBits(this->event_group_, EventGroupBits::COMMAND_PAUSE); + break; + default: + break; + } +} + +void AudioFileMediaSource::decode_task(void *params) { + AudioFileMediaSource *this_source = static_cast<AudioFileMediaSource *>(params); + + do { // do-while(false) ensures RAII objects are destroyed on all exit paths via break + + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_STARTING); + + // 0 bytes for input transfer buffer makes it an inplace buffer + std::unique_ptr<audio::AudioDecoder> decoder = make_unique<audio::AudioDecoder>(0, 4096); + + esp_err_t err = decoder->start(this_source->current_file_->file_type); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start decoder: %s", esp_err_to_name(err)); + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_ERROR | EventGroupBits::TASK_STOPPING); + break; + } + + // Add the file as a const data source + decoder->add_source(this_source->current_file_->data, this_source->current_file_->length); + + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_RUNNING); + + AudioSinkAdapter audio_sink; + bool has_stream_info = false; + + while (true) { + EventBits_t event_bits = xEventGroupGetBits(this_source->event_group_); + + if (event_bits & EventGroupBits::COMMAND_STOP) { + break; + } + + bool paused = event_bits & EventGroupBits::COMMAND_PAUSE; + decoder->set_pause_output_state(paused); + if (paused) { + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_PAUSED); + vTaskDelay(pdMS_TO_TICKS(20)); + } else { + xEventGroupClearBits(this_source->event_group_, EventGroupBits::TASK_PAUSED); + } + + // Will stop gracefully once finished with the current file + audio::AudioDecoderState decoder_state = decoder->decode(true); + + if (decoder_state == audio::AudioDecoderState::FINISHED) { + break; + } else if (decoder_state == audio::AudioDecoderState::FAILED) { + ESP_LOGE(TAG, "Decoder failed"); + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_ERROR); + break; + } + + if (!has_stream_info && decoder->get_audio_stream_info().has_value()) { + has_stream_info = true; + + audio::AudioStreamInfo stream_info = decoder->get_audio_stream_info().value(); + + ESP_LOGD(TAG, "Bits per sample: %d, Channels: %d, Sample rate: %d", stream_info.get_bits_per_sample(), + stream_info.get_channels(), stream_info.get_sample_rate()); + + if (stream_info.get_bits_per_sample() != 16 || stream_info.get_channels() > 2) { + ESP_LOGE(TAG, "Incompatible audio stream. Only 16 bits per sample and 1 or 2 channels are supported"); + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_ERROR); + break; + } + + audio_sink.source = this_source; + audio_sink.stream_info = stream_info; + esp_err_t err = decoder->add_sink(&audio_sink); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to add sink: %s", esp_err_to_name(err)); + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_ERROR); + break; + } + } + } + + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_STOPPING); + } while (false); + + // All RAII objects from the do-while block (decoder, audio_sink, etc.) are now destroyed. + + xEventGroupSetBits(this_source->event_group_, EventGroupBits::TASK_STOPPED); + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it +} + +} // namespace esphome::audio_file + +#endif // USE_ESP32 diff --git a/esphome/components/audio_file/media_source/audio_file_media_source.h b/esphome/components/audio_file/media_source/audio_file_media_source.h new file mode 100644 index 0000000000..75e18c13b8 --- /dev/null +++ b/esphome/components/audio_file/media_source/audio_file_media_source.h @@ -0,0 +1,50 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_ESP32 + +#include "esphome/components/audio/audio.h" +#include "esphome/components/audio_file/audio_file.h" +#include "esphome/components/media_source/media_source.h" +#include "esphome/core/component.h" +#include "esphome/core/static_task.h" + +#include <freertos/FreeRTOS.h> +#include <freertos/event_groups.h> + +namespace esphome::audio_file { + +enum class AudioFileDecodingState : uint8_t { + START_TASK, + DECODING, + IDLE, +}; + +class AudioFileMediaSource : public Component, public media_source::MediaSource { + public: + void setup() override; + void loop() override; + void dump_config() override; + + // MediaSource interface implementation + bool play_uri(const std::string &uri) override; + void handle_command(media_source::MediaSourceCommand command) override; + bool can_handle(const std::string &uri) const override { return uri.starts_with("audio-file://"); } + + void set_task_stack_in_psram(bool task_stack_in_psram) { this->task_stack_in_psram_ = task_stack_in_psram; } + + protected: + static void decode_task(void *params); + + audio::AudioFile *current_file_{nullptr}; + AudioFileDecodingState decoding_state_{AudioFileDecodingState::IDLE}; + EventGroupHandle_t event_group_{nullptr}; + StaticTask decode_task_; + + bool task_stack_in_psram_{false}; +}; + +} // namespace esphome::audio_file + +#endif // USE_ESP32 diff --git a/tests/components/audio_file/common.yaml b/tests/components/audio_file/common.yaml index 9404208094..e7f55b4806 100644 --- a/tests/components/audio_file/common.yaml +++ b/tests/components/audio_file/common.yaml @@ -3,3 +3,7 @@ audio_file: file: type: local path: $component_dir/test.wav + +media_source: + - platform: audio_file + id: audio_file_source From 58ab63096587dcfd75d7ad74a397d8b0687fb41f Mon Sep 17 00:00:00 2001 From: Gnuspice <Gnuspice@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:37:07 +1300 Subject: [PATCH 1142/2030] [ethernet] add get_eth_handle() function (#14527) --- esphome/components/ethernet/ethernet_component.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index f5a31d78eb..e54e1543e3 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -115,6 +115,7 @@ class EthernetComponent : public Component { const char *get_eth_mac_address_pretty_into_buffer(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf); eth_duplex_t get_duplex_mode(); eth_speed_t get_link_speed(); + esp_eth_handle_t get_eth_handle() const { return this->eth_handle_; } bool powerdown(); #ifdef USE_ETHERNET_IP_STATE_LISTENERS From 44870323dab606efe85a21d93ac0f32eaab22aee Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 20:47:47 -0500 Subject: [PATCH 1143/2030] [host] Add null checks for getenv and fopen in preferences (#14531) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/host/preferences.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/esphome/components/host/preferences.cpp b/esphome/components/host/preferences.cpp index 5ad87c1f2a..275c202e3e 100644 --- a/esphome/components/host/preferences.cpp +++ b/esphome/components/host/preferences.cpp @@ -4,6 +4,7 @@ #include <fstream> #include "preferences.h" #include "esphome/core/application.h" +#include "esphome/core/log.h" namespace esphome { namespace host { @@ -14,7 +15,12 @@ static const char *const TAG = "host.preferences"; void HostPreferences::setup_() { if (this->setup_complete_) return; - this->filename_.append(getenv("HOME")); + const char *home = getenv("HOME"); + if (home == nullptr) { + ESP_LOGE(TAG, "HOME environment variable is not set"); + abort(); + } + this->filename_.append(home); this->filename_.append("/.esphome"); this->filename_.append("/prefs"); fs::create_directories(this->filename_); @@ -44,9 +50,12 @@ void HostPreferences::setup_() { bool HostPreferences::sync() { this->setup_(); FILE *fp = fopen(this->filename_.c_str(), "wb"); - std::map<uint32_t, std::vector<uint8_t>>::iterator it; + if (fp == nullptr) { + ESP_LOGE(TAG, "Failed to open preferences file for writing: %s", this->filename_.c_str()); + return false; + } - for (it = this->data.begin(); it != this->data.end(); ++it) { + for (auto it = this->data.begin(); it != this->data.end(); ++it) { fwrite(&it->first, sizeof(uint32_t), 1, fp); uint8_t len = it->second.size(); fwrite(&len, sizeof(len), 1, fp); From 80fe54ed6948386a9b6218737b164c9e61c7d71e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 5 Mar 2026 23:30:39 -0500 Subject: [PATCH 1144/2030] [bluetooth_proxy] Add null checks for api_connection (#14536) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../bluetooth_proxy/bluetooth_connection.cpp | 25 +++++++++++++++---- .../bluetooth_proxy/bluetooth_proxy.cpp | 4 +++ 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index 60f56fda54..b2000fbd94 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -415,11 +415,14 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_gatt_error(this->address_, param->read.handle, param->read.status); break; } + auto *api_connection = this->proxy_->get_api_connection(); + if (api_connection == nullptr) + break; api::BluetoothGATTReadResponse resp; resp.address = this->address_; resp.handle = param->read.handle; resp.set_data(param->read.value, param->read.value_len); - this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE); + api_connection->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE); break; } case ESP_GATTC_WRITE_CHAR_EVT: @@ -429,10 +432,13 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_gatt_error(this->address_, param->write.handle, param->write.status); break; } + auto *api_connection = this->proxy_->get_api_connection(); + if (api_connection == nullptr) + break; api::BluetoothGATTWriteResponse resp; resp.address = this->address_; resp.handle = param->write.handle; - this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE); + api_connection->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE); break; } case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: { @@ -442,10 +448,13 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_gatt_error(this->address_, param->unreg_for_notify.handle, param->unreg_for_notify.status); break; } + auto *api_connection = this->proxy_->get_api_connection(); + if (api_connection == nullptr) + break; api::BluetoothGATTNotifyResponse resp; resp.address = this->address_; resp.handle = param->unreg_for_notify.handle; - this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); + api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); break; } case ESP_GATTC_REG_FOR_NOTIFY_EVT: { @@ -455,20 +464,26 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga this->proxy_->send_gatt_error(this->address_, param->reg_for_notify.handle, param->reg_for_notify.status); break; } + auto *api_connection = this->proxy_->get_api_connection(); + if (api_connection == nullptr) + break; api::BluetoothGATTNotifyResponse resp; resp.address = this->address_; resp.handle = param->reg_for_notify.handle; - this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); + api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); break; } case ESP_GATTC_NOTIFY_EVT: { ESP_LOGV(TAG, "[%d] [%s] ESP_GATTC_NOTIFY_EVT: handle=0x%2X", this->connection_index_, this->address_str_, param->notify.handle); + auto *api_connection = this->proxy_->get_api_connection(); + if (api_connection == nullptr) + break; api::BluetoothGATTNotifyDataResponse resp; resp.address = this->address_; resp.handle = param->notify.handle; resp.set_data(param->notify.value, param->notify.value_len); - this->proxy_->get_api_connection()->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE); + api_connection->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE); break; } default: diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index d45377b3f6..cab328e2f5 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -420,6 +420,8 @@ void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_ } void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_t error) { + if (this->api_connection_ == nullptr) + return; api::BluetoothDevicePairingResponse call; call.address = address; call.paired = paired; @@ -429,6 +431,8 @@ void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_ } void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_err_t error) { + if (this->api_connection_ == nullptr) + return; api::BluetoothDeviceUnpairingResponse call; call.address = address; call.success = success; From a2c0d70c2c1983cf996f045ba7801216ddcea9ac Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Fri, 6 Mar 2026 08:00:17 +0100 Subject: [PATCH 1145/2030] [ble_nus] Add uart support (#14320) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/ble_nus/__init__.py | 53 +++++++- esphome/components/ble_nus/ble_nus.cpp | 125 +++++++++++++++--- esphome/components/ble_nus/ble_nus.h | 16 ++- esphome/core/defines.h | 2 + .../ble_nus/test-uart.nrf52-adafruit.yaml | 4 + 5 files changed, 178 insertions(+), 22 deletions(-) create mode 100644 tests/components/ble_nus/test-uart.nrf52-adafruit.yaml diff --git a/esphome/components/ble_nus/__init__.py b/esphome/components/ble_nus/__init__.py index 6581ce1cfa..c0837da402 100644 --- a/esphome/components/ble_nus/__init__.py +++ b/esphome/components/ble_nus/__init__.py @@ -1,29 +1,64 @@ import esphome.codegen as cg from esphome.components.logger import request_log_listener +from esphome.components.uart import ( + UARTComponent, + debug_to_code, + maybe_empty_debug, + uart_ns, +) from esphome.components.zephyr import zephyr_add_prj_conf import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_LOGS, CONF_TYPE +from esphome.const import ( + CONF_DEBUG, + CONF_ID, + CONF_LOGS, + CONF_RX_BUFFER_SIZE, + CONF_TX_BUFFER_SIZE, + CONF_TYPE, +) +from esphome.types import ConfigType -AUTO_LOAD = ["zephyr_ble_server"] +AUTO_LOAD = ["zephyr_ble_server", "uart"] CODEOWNERS = ["@tomaszduda23"] ble_nus_ns = cg.esphome_ns.namespace("ble_nus") -BLENUS = ble_nus_ns.class_("BLENUS", cg.Component) +BLENUS = ble_nus_ns.class_("BLENUS", cg.Component, UARTComponent) + +CONF_UART = "uart" + + +def validate_rx_buffer(config: ConfigType) -> ConfigType: + config = config.copy() + if config[CONF_TYPE] == CONF_LOGS: + if CONF_RX_BUFFER_SIZE in config: + raise cv.Invalid("logs does not support rx_buffer_size") + elif CONF_RX_BUFFER_SIZE not in config: + config[CONF_RX_BUFFER_SIZE] = 512 + return config + CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(BLENUS), cv.Optional(CONF_TYPE, default=CONF_LOGS): cv.one_of( - *[CONF_LOGS], lower=True + *[CONF_LOGS, CONF_UART], lower=True ), + cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.All( + cv.validate_bytes, cv.int_range(min=160, max=8192) + ), + cv.Optional(CONF_RX_BUFFER_SIZE): cv.All( + cv.validate_bytes, cv.int_range(min=160, max=8192) + ), + cv.Optional(CONF_DEBUG): maybe_empty_debug, } ).extend(cv.COMPONENT_SCHEMA), cv.only_with_framework("zephyr"), + validate_rx_buffer, ) -async def to_code(config): +async def to_code(config: ConfigType) -> None: var = cg.new_Pvariable(config[CONF_ID]) zephyr_add_prj_conf("BT_NUS", True) expose_log = config[CONF_TYPE] == CONF_LOGS @@ -31,3 +66,11 @@ async def to_code(config): if expose_log: request_log_listener() # Request a log listener slot for BLE NUS log streaming await cg.register_component(var, config) + cg.add_define("ESPHOME_BLE_NUS_TX_RING_BUFFER_SIZE", config[CONF_TX_BUFFER_SIZE]) + if CONF_RX_BUFFER_SIZE in config: + cg.add_define( + "ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE", config[CONF_RX_BUFFER_SIZE] + ) + if CONF_DEBUG in config: + cg.add_global(uart_ns.using) + await debug_to_code(config[CONF_DEBUG], var) diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index a10132eb3e..d1710100a0 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -11,25 +11,111 @@ namespace esphome::ble_nus { -constexpr size_t BLE_TX_BUF_SIZE = 2048; - // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) BLENUS *global_ble_nus; -RING_BUF_DECLARE(global_ble_tx_ring_buf, BLE_TX_BUF_SIZE); +RING_BUF_DECLARE(global_ble_tx_ring_buf, ESPHOME_BLE_NUS_TX_RING_BUFFER_SIZE); +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE +RING_BUF_DECLARE(global_ble_rx_ring_buf, ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE); +#endif // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) static const char *const TAG = "ble_nus"; -size_t BLENUS::write_array(const uint8_t *data, size_t len) { +void BLENUS::write_array(const uint8_t *data, size_t len) { if (atomic_get(&this->tx_status_) == TX_DISABLED) { - return 0; + return; + } + auto sent = ring_buf_put(&global_ble_tx_ring_buf, data, len); + if (sent < len) { + ESP_LOGE(TAG, "TX dropping %u bytes", len - sent); + return; + } +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(uart::UART_DIRECTION_TX, data[i]); + } +#endif +} + +bool BLENUS::peek_byte(uint8_t *data) { +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + if (this->has_peek_) { + *data = this->peek_buffer_; + return true; + } + + if (this->read_byte(&this->peek_buffer_)) { + *data = this->peek_buffer_; + this->has_peek_ = true; + return true; + } + + return false; +#else + return false; +#endif +} + +bool BLENUS::read_array(uint8_t *data, size_t len) { +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + if (len == 0) { + return true; + } + if (this->available() < len) { + return false; + } + + // First, use the peek buffer if available + if (this->has_peek_) { + data[0] = this->peek_buffer_; + this->has_peek_ = false; + data++; + if (--len == 0) { // Decrement len first, then check it... + return true; // No more to read + } + } + + if (ring_buf_get(&global_ble_rx_ring_buf, data, len) != len) { + ESP_LOGE(TAG, "UART BLE unexpected size"); + return false; + } +#ifdef USE_UART_DEBUGGER + for (size_t i = 0; i < len; i++) { + this->debug_callback_.call(uart::UART_DIRECTION_RX, data[i]); + } +#endif + return true; +#else + return false; +#endif +} + +size_t BLENUS::available() { +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + uint32_t size = ring_buf_size_get(&global_ble_rx_ring_buf); + ESP_LOGVV(TAG, "UART BLE available %u", size); + return size + (this->has_peek_ ? 1 : 0); +#else + return 0; +#endif +} + +void BLENUS::flush() { + constexpr uint32_t timeout_5sec = 5000; + uint32_t start = millis(); + while (atomic_get(&this->tx_status_) != TX_DISABLED && !ring_buf_is_empty(&global_ble_tx_ring_buf)) { + if (millis() - start > timeout_5sec) { + ESP_LOGW(TAG, "Flush timeout"); + return; + } + delay(1); } - return ring_buf_put(&global_ble_tx_ring_buf, data, len); } void BLENUS::connected(bt_conn *conn, uint8_t err) { if (err == 0) { global_ble_nus->conn_.store(bt_conn_ref(conn)); + global_ble_nus->connected_ = true; } } @@ -38,6 +124,7 @@ void BLENUS::disconnected(bt_conn *conn, uint8_t reason) { bt_conn_unref(global_ble_nus->conn_.load()); // Connection array is global static. // Reference can be kept even if disconnected. + global_ble_nus->connected_ = false; } } @@ -63,12 +150,19 @@ void BLENUS::send_enabled_callback(bt_nus_send_status status) { break; } } - void BLENUS::rx_callback(bt_conn *conn, const uint8_t *const data, uint16_t len) { - ESP_LOGD(TAG, "Received %d bytes.", len); + ESP_LOGV(TAG, "Received %d bytes.", len); +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + auto recv_len = ring_buf_put(&global_ble_rx_ring_buf, data, len); + if (recv_len < len) { + ESP_LOGE(TAG, "RX dropping %u bytes", len - recv_len); + } +#endif } - void BLENUS::setup() { +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + this->rx_buffer_size_ = ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE; +#endif bt_nus_cb callbacks = { .received = rx_callback, .sent = tx_callback, @@ -106,16 +200,17 @@ void BLENUS::on_log(uint8_t level, const char *tag, const char *message, size_t #endif void BLENUS::dump_config() { - ESP_LOGCONFIG(TAG, - "ble nus:\n" - " log: %s", - YESNO(this->expose_log_)); uint32_t mtu = 0; bt_conn *conn = this->conn_.load(); - if (conn) { + if (conn && this->connected_) { mtu = bt_nus_get_mtu(conn); } - ESP_LOGCONFIG(TAG, " MTU: %u", mtu); + ESP_LOGCONFIG(TAG, + "ble nus:\n" + " log: %s\n" + " connected: %s\n" + " MTU: %u", + YESNO(this->expose_log_), YESNO(this->connected_.load()), mtu); } void BLENUS::loop() { diff --git a/esphome/components/ble_nus/ble_nus.h b/esphome/components/ble_nus/ble_nus.h index b2b0ee7713..67e9ae9f97 100644 --- a/esphome/components/ble_nus/ble_nus.h +++ b/esphome/components/ble_nus/ble_nus.h @@ -2,6 +2,7 @@ #ifdef USE_ZEPHYR #include "esphome/core/defines.h" #include "esphome/core/component.h" +#include "esphome/components/uart/uart_component.h" #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" #endif @@ -10,7 +11,7 @@ namespace esphome::ble_nus { -class BLENUS : public Component { +class BLENUS : public uart::UARTComponent, public Component { enum TxStatus { TX_DISABLED, TX_ENABLED, @@ -21,7 +22,12 @@ class BLENUS : public Component { void setup() override; void dump_config() override; void loop() override; - size_t write_array(const uint8_t *data, size_t len); + void write_array(const uint8_t *data, size_t len) override; + bool peek_byte(uint8_t *data) override; + bool read_array(uint8_t *data, size_t len) override; + size_t available() override; + void flush() override; + void check_logger_conflict() override {} void set_expose_log(bool expose_log) { this->expose_log_ = expose_log; } #ifdef USE_LOGGER void on_log(uint8_t level, const char *tag, const char *message, size_t message_len); @@ -37,6 +43,12 @@ class BLENUS : public Component { std::atomic<bt_conn *> conn_ = nullptr; bool expose_log_ = false; atomic_t tx_status_ = ATOMIC_INIT(TX_DISABLED); + std::atomic<bool> connected_{}; +#ifdef ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE + // RX buffer for peek functionality + uint8_t peek_buffer_{0}; + bool has_peek_{false}; +#endif }; } // namespace esphome::ble_nus diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 1a6d9b3a80..be5fdc9006 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -356,6 +356,8 @@ #endif #ifdef USE_NRF52 +#define ESPHOME_BLE_NUS_TX_RING_BUFFER_SIZE 512 +#define ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE 512 #define USE_ESPHOME_TASK_LOG_BUFFER #define USE_LOGGER_EARLY_MESSAGE #define USE_LOGGER_UART_SELECTION_USB_CDC diff --git a/tests/components/ble_nus/test-uart.nrf52-adafruit.yaml b/tests/components/ble_nus/test-uart.nrf52-adafruit.yaml new file mode 100644 index 0000000000..0d917ec115 --- /dev/null +++ b/tests/components/ble_nus/test-uart.nrf52-adafruit.yaml @@ -0,0 +1,4 @@ +ble_nus: + type: uart + tx_buffer_size: 160 + rx_buffer_size: 160 From 666fb7cf39aeaf2e2a7890695099535ed8b5a67c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 07:18:28 -0500 Subject: [PATCH 1146/2030] [sx127x][sx126x][max6956] Fix null deref, unterminated string, and pin bounds check (#14529) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/max6956/max6956.cpp | 2 ++ esphome/components/sx126x/sx126x.cpp | 3 ++- esphome/components/sx127x/sx127x.cpp | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/esphome/components/max6956/max6956.cpp b/esphome/components/max6956/max6956.cpp index a350e66ee0..ce45541b63 100644 --- a/esphome/components/max6956/max6956.cpp +++ b/esphome/components/max6956/max6956.cpp @@ -111,6 +111,8 @@ void MAX6956::write_brightness_mode() { } void MAX6956::set_pin_brightness(uint8_t pin, float brightness) { + if (pin < MAX6956_MIN || pin > MAX6956_MAX) + return; uint8_t reg_addr = MAX6956_CURRENT_START + (pin - MAX6956_MIN) / 2; uint8_t config = 0; uint8_t shift = 4 * (pin % 2); diff --git a/esphome/components/sx126x/sx126x.cpp b/esphome/components/sx126x/sx126x.cpp index 64cd24b171..ec62fad10a 100644 --- a/esphome/components/sx126x/sx126x.cpp +++ b/esphome/components/sx126x/sx126x.cpp @@ -155,7 +155,8 @@ void SX126x::configure() { } // check silicon version to make sure hw is ok - this->read_register_(REG_VERSION_STRING, (uint8_t *) this->version_, 16); + this->read_register_(REG_VERSION_STRING, (uint8_t *) this->version_, sizeof(this->version_)); + this->version_[sizeof(this->version_) - 1] = '\0'; if (strncmp(this->version_, "SX126", 5) != 0 && strncmp(this->version_, "LLCC68", 6) != 0) { this->mark_failed(); return; diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index f6aa11b634..66957a7342 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -260,6 +260,11 @@ SX127xError SX127x::transmit_packet(const std::vector<uint8_t> &packet) { return SX127xError::INVALID_PARAMS; } + if (this->dio0_pin_ == nullptr) { + ESP_LOGE(TAG, "DIO0 pin not configured, cannot wait for transmit completion"); + return SX127xError::INVALID_PARAMS; + } + SX127xError ret = SX127xError::NONE; if (this->modulation_ == MOD_LORA) { this->set_mode_standby(); From 6c07c15c504c7f0a66ab1a9e2c2f91943526ffa2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 07:18:56 -0500 Subject: [PATCH 1147/2030] [mipi_dsi][e131] Fix semaphore cast, missing return, and light count overread (#14530) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/e131/e131_addressable_light_effect.cpp | 4 +++- esphome/components/mipi_dsi/mipi_dsi.cpp | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/esphome/components/e131/e131_addressable_light_effect.cpp b/esphome/components/e131/e131_addressable_light_effect.cpp index 7d62f739a2..f6010a7cc9 100644 --- a/esphome/components/e131/e131_addressable_light_effect.cpp +++ b/esphome/components/e131/e131_addressable_light_effect.cpp @@ -54,8 +54,10 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet int32_t output_offset = (universe - first_universe_) * get_lights_per_universe(); // limit amount of lights per universe and received + // packet.count is the number of DMX bytes including start code; divide by channels to get the number of lights + int lights_in_packet = (packet.count > 0) ? (packet.count - 1) / channels_ : 0; int output_end = - std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + packet.count - 1)); + std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + lights_in_packet)); auto *input_data = packet.values + 1; auto effect_name = get_name(); diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 4d45cfb799..815b9d75a1 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -10,7 +10,7 @@ namespace mipi_dsi { static constexpr size_t MIPI_DSI_MAX_CMD_LOG_BYTES = 64; static bool notify_refresh_ready(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx) { - auto *sem = static_cast<SemaphoreHandle_t *>(user_ctx); + auto sem = static_cast<SemaphoreHandle_t>(user_ctx); BaseType_t need_yield = pdFALSE; xSemaphoreGiveFromISR(sem, &need_yield); return (need_yield == pdTRUE); @@ -190,6 +190,7 @@ void MIPI_DSI::draw_pixels_at(int x_start, int y_start, int w, int h, const uint if (bitness != this->color_depth_) { display::Display::draw_pixels_at(x_start, y_start, w, h, ptr, order, bitness, big_endian, x_offset, y_offset, x_pad); + return; } this->write_to_display_(x_start, y_start, w, h, ptr, x_offset, y_offset, x_pad); } From c0b7f41397e41ff53ed2d551fcd0e3cf03f89147 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Fri, 6 Mar 2026 13:21:44 +0100 Subject: [PATCH 1148/2030] [esp32] Fix wrong variable usage in P4 pin validation error msg (#14539) --- esphome/components/esp32/gpio_esp32_p4.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32/gpio_esp32_p4.py b/esphome/components/esp32/gpio_esp32_p4.py index b98b567da2..2726c5932f 100644 --- a/esphome/components/esp32/gpio_esp32_p4.py +++ b/esphome/components/esp32/gpio_esp32_p4.py @@ -33,7 +33,7 @@ def esp32_p4_validate_supports(value): is_input = mode[CONF_INPUT] if num < 0 or num > 54: - raise cv.Invalid(f"Invalid pin number: {value} (must be 0-54)") + raise cv.Invalid(f"Invalid pin number: {num} (must be 0-54)") if is_input: # All ESP32 pins support input mode pass From 5084c32f3c3da1bb857b79f6200825ec456000c8 Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Fri, 6 Mar 2026 13:22:11 +0100 Subject: [PATCH 1149/2030] [esp32] Fix ESP32-S3 pin validation error message (#14540) --- esphome/components/esp32/gpio_esp32_s3.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/gpio_esp32_s3.py b/esphome/components/esp32/gpio_esp32_s3.py index 7120504693..aea378f499 100644 --- a/esphome/components/esp32/gpio_esp32_s3.py +++ b/esphome/components/esp32/gpio_esp32_s3.py @@ -29,7 +29,7 @@ _LOGGER = logging.getLogger(__name__) def esp32_s3_validate_gpio_pin(value): if value < 0 or value > 48: - raise cv.Invalid(f"Invalid pin number: {value} (must be 0-46)") + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-48)") if value in _ESP_32S3_SPI_PSRAM_PINS: raise cv.Invalid( @@ -55,7 +55,7 @@ def esp32_s3_validate_supports(value): is_input = mode[CONF_INPUT] if num < 0 or num > 48: - raise cv.Invalid(f"Invalid pin number: {num} (must be 0-46)") + raise cv.Invalid(f"Invalid pin number: {num} (must be 0-48)") if is_input: # All ESP32 pins support input mode pass From e59a2b3eded37c9de46d8148b2f8cb40b46d06ac Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Fri, 6 Mar 2026 17:25:44 +0100 Subject: [PATCH 1150/2030] [nrf52] prepare for usb cdc (#14174) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 2 ++ esphome/core/event_pool.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index a14d3af69e..8ad84656ed 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -464,6 +464,8 @@ def only_on_variant(*, supported=None, unsupported=None, msg_prefix="This featur unsupported = [unsupported] def validator_(obj): + if not CORE.is_esp32: + raise cv.Invalid(f"{msg_prefix} is only available on ESP32") variant = get_esp32_variant() if supported is not None and variant not in supported: raise cv.Invalid( diff --git a/esphome/core/event_pool.h b/esphome/core/event_pool.h index 928a4e7dee..99541d4a17 100644 --- a/esphome/core/event_pool.h +++ b/esphome/core/event_pool.h @@ -1,6 +1,6 @@ #pragma once -#if defined(USE_ESP32) +#if defined(USE_ESP32) || defined(USE_ZEPHYR) #include <atomic> #include <cstddef> From 07e51886f3563061c09e6a8c9c36ab94300b0b1f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 06:57:52 -1000 Subject: [PATCH 1151/2030] [core] Move entity icon strings to PROGMEM on ESP8266 (#14437) --- esphome/components/api/api_connection.h | 3 +- esphome/components/mqtt/mqtt_component.cpp | 10 ++--- esphome/components/mqtt/mqtt_component.h | 4 +- esphome/components/web_server/web_server.cpp | 3 +- esphome/config_validation.py | 17 ++++--- esphome/core/config.py | 4 ++ esphome/core/entity_base.cpp | 38 ++++++++++++++-- esphome/core/entity_base.h | 33 +++++++++++--- esphome/core/entity_helpers.py | 47 +++++++++++++++++--- tests/unit_tests/core/test_entity_helpers.py | 17 +++++++ tests/unit_tests/test_config_validation.py | 12 +++++ 11 files changed, 158 insertions(+), 30 deletions(-) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index aae8db3c68..88f0ef82d6 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -354,7 +354,8 @@ class APIConnection final : public APIServerConnectionBase { // Set common EntityBase properties #ifdef USE_ENTITY_ICON - msg.icon = entity->get_icon_ref(); + char icon_buf[MAX_ICON_LENGTH]; + msg.icon = StringRef(entity->get_icon_to(icon_buf)); #endif msg.disabled_by_default = entity->is_disabled_by_default(); msg.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category()); diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index f49069960b..98fa10def9 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -209,12 +209,11 @@ bool MQTTComponent::send_discovery_() { if (this->is_disabled_by_default_()) root[MQTT_ENABLED_BY_DEFAULT] = false; - // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto icon_ref = this->get_icon_ref_(); - if (!icon_ref.empty()) { - root[MQTT_ICON] = icon_ref; + char icon_buf[MAX_ICON_LENGTH]; + const char *icon = this->get_icon_to_(icon_buf); + if (icon[0] != '\0') { + root[MQTT_ICON] = icon; } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) const auto entity_category = this->get_entity()->get_entity_category(); if (entity_category != ENTITY_CATEGORY_NONE) { @@ -413,7 +412,6 @@ const StringRef &MQTTComponent::friendly_name_() const { return this->get_entity StringRef MQTTComponent::get_default_object_id_to_(std::span<char, OBJECT_ID_MAX_LEN> buf) const { return this->get_entity()->get_object_id_to(buf); } -StringRef MQTTComponent::get_icon_ref_() const { return this->get_entity()->get_icon_ref(); } bool MQTTComponent::is_disabled_by_default_() const { return this->get_entity()->is_disabled_by_default(); } bool MQTTComponent::compute_is_internal_() { if (this->custom_state_topic_.has_value()) { diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 0ffe6341d3..2403ef64ea 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -298,8 +298,8 @@ class MQTTComponent : public Component { /// Get the friendly name of this MQTT component. const StringRef &friendly_name_() const; - /// Get the icon field of this component as StringRef - StringRef get_icon_ref_() const; + /// Get the icon field of this component into a stack buffer + const char *get_icon_to_(std::span<char, MAX_ICON_LENGTH> buf) const { return this->get_entity()->get_icon_to(buf); } /// Get whether the underlying Entity is disabled by default bool is_disabled_by_default_() const; diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 6b94a103cc..bc90c88e57 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -568,7 +568,8 @@ static void set_json_id(JsonObject &root, EntityBase *obj, const char *prefix, J } #endif #ifdef USE_ENTITY_ICON - root[ESPHOME_F("icon")] = obj->get_icon_ref().c_str(); + char icon_buf[MAX_ICON_LENGTH]; + root[ESPHOME_F("icon")] = obj->get_icon_to(icon_buf); #endif root[ESPHOME_F("entity_category")] = obj->get_entity_category(); bool is_disabled = obj->is_disabled_by_default(); diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 3b0e4da298..1eac53e9b2 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -400,14 +400,21 @@ def string_strict(value): def icon(value): """Validate that a given config value is a valid icon.""" + from esphome.core.config import ICON_MAX_LENGTH + value = string_strict(value) if not value: return value - if re.match("^[\\w\\-]+:[\\w\\-]+$", value): - return value - raise Invalid( - 'Icons must match the format "[icon pack]:[icon]", e.g. "mdi:home-assistant"' - ) + if not re.match("^[\\w\\-]+:[\\w\\-]+$", value): + raise Invalid( + 'Icons must match the format "[icon pack]:[icon]", e.g. "mdi:home-assistant"' + ) + if len(value) > ICON_MAX_LENGTH: + raise Invalid( + f"Icon string is too long ({len(value)} chars, max {ICON_MAX_LENGTH}). " + "Icons are stored in PROGMEM with a 64-byte buffer limit." + ) + return value def sub_device_id(value: str | None) -> core.ID | None: diff --git a/esphome/core/config.py b/esphome/core/config.py index 4f526404fe..9093ab3fe9 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -188,6 +188,10 @@ else: # Keep in sync with ESPHOME_FRIENDLY_NAME_MAX_LEN in esphome/core/entity_base.h FRIENDLY_NAME_MAX_LEN = 120 +# Max icon string length (63 chars + null = 64-byte PROGMEM buffer) +# Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h +ICON_MAX_LENGTH = 63 + AREA_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Area), diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index eafc04f92a..1265277572 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -1,6 +1,7 @@ #include "esphome/core/entity_base.h" #include "esphome/core/application.h" #include "esphome/core/helpers.h" +#include "esphome/core/progmem.h" #include "esphome/core/string_ref.h" namespace esphome { @@ -72,7 +73,27 @@ std::string EntityBase::get_unit_of_measurement() const { return std::string(this->get_unit_of_measurement_ref().c_str()); } -// Entity icon (from index) +// Entity icon — buffer-based API for PROGMEM safety on ESP8266 +const char *EntityBase::get_icon_to([[maybe_unused]] std::span<char, MAX_ICON_LENGTH> buffer) const { +#ifdef USE_ENTITY_ICON + const uint8_t idx = this->icon_idx_; +#else + const uint8_t idx = 0; +#endif +#ifdef USE_ESP8266 + if (idx == 0) + return ""; + const char *icon = entity_icon_lookup(idx); + ESPHOME_strncpy_P(buffer.data(), icon, buffer.size() - 1); + buffer[buffer.size() - 1] = '\0'; + return buffer.data(); +#else + return entity_icon_lookup(idx); +#endif +} + +#ifndef USE_ESP8266 +// Deprecated icon accessors — not available on ESP8266 (rodata is RAM) StringRef EntityBase::get_icon_ref() const { #ifdef USE_ENTITY_ICON return StringRef(entity_icon_lookup(this->icon_idx_)); @@ -80,7 +101,14 @@ StringRef EntityBase::get_icon_ref() const { return StringRef(entity_icon_lookup(0)); #endif } -std::string EntityBase::get_icon() const { return std::string(this->get_icon_ref().c_str()); } +std::string EntityBase::get_icon() const { +#ifdef USE_ENTITY_ICON + return std::string(entity_icon_lookup(this->icon_idx_)); +#else + return std::string(entity_icon_lookup(0)); +#endif +} +#endif // !USE_ESP8266 // Entity Object ID - computed on-demand from name std::string EntityBase::get_object_id() const { @@ -154,8 +182,10 @@ ESPPreferenceObject EntityBase::make_entity_preference_(size_t size, uint32_t ve #ifdef USE_ENTITY_ICON void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) { - if (!obj.get_icon_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, obj.get_icon_ref().c_str()); + char icon_buf[MAX_ICON_LENGTH]; + const char *icon = obj.get_icon_to(icon_buf); + if (icon[0] != '\0') { + ESP_LOGCONFIG(tag, "%s Icon: '%s'", prefix, icon); } } #endif diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 54d4ae311f..1ce1e658e0 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -36,6 +36,10 @@ static constexpr size_t OBJECT_ID_MAX_LEN = 128; // Maximum state length that Home Assistant will accept without raising ValueError static constexpr size_t MAX_STATE_LEN = 255; +// Maximum icon string buffer size (63 chars + null terminator) +// Icons are stored in PROGMEM; on ESP8266 they must be copied to a stack buffer. +static constexpr size_t MAX_ICON_LENGTH = 64; + enum EntityCategory : uint8_t { ENTITY_CATEGORY_NONE = 0, ENTITY_CATEGORY_CONFIG = 1, @@ -124,12 +128,31 @@ class EntityBase { "2026.3.0") std::string get_unit_of_measurement() const; - // Get/set this entity's icon - ESPDEPRECATED( - "Use get_icon_ref() instead for better performance (avoids string copy). Will be removed in ESPHome 2026.5.0", - "2025.11.0") - std::string get_icon() const; + // Get this entity's icon into a stack buffer. + // On ESP32: returns pointer to PROGMEM string directly (buffer unused). + // On ESP8266: copies from PROGMEM to buffer, returns buffer pointer. + const char *get_icon_to(std::span<char, MAX_ICON_LENGTH> buffer) const; + +#ifdef USE_ESP8266 + // On ESP8266, rodata is RAM. Icons are in PROGMEM and cannot be accessed + // directly as const char*. Use get_icon_to() with a stack buffer instead. + template<typename T = int> StringRef get_icon_ref() const { + static_assert(sizeof(T) == 0, + "get_icon_ref() unavailable on ESP8266 (rodata is RAM). Use get_icon_to() with a stack buffer."); + return StringRef(""); + } + template<typename T = int> std::string get_icon() const { + static_assert(sizeof(T) == 0, + "get_icon() unavailable on ESP8266 (rodata is RAM). Use get_icon_to() with a stack buffer."); + return ""; + } +#else + // Deprecated: use get_icon_to() instead. Icons are in PROGMEM. + ESPDEPRECATED("Use get_icon_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0") StringRef get_icon_ref() const; + ESPDEPRECATED("Use get_icon_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0") + std::string get_icon() const; +#endif #ifdef USE_DEVICES // Get/set this entity's device id diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index 551e35df65..01fa27b833 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -17,6 +17,7 @@ from esphome.const import ( CONF_UNIT_OF_MEASUREMENT, ) from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority +from esphome.core.config import ICON_MAX_LENGTH from esphome.cpp_generator import MockObj, RawStatement, add, get_variable import esphome.final_validate as fv from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case @@ -78,6 +79,8 @@ def _generate_category_code( table_var: str, lookup_fn: str, strings: dict[str, int], + *, + progmem_strings: bool = False, ) -> str: """Generate C++ code for one string category (PROGMEM pointer table + lookup). @@ -85,14 +88,40 @@ def _generate_category_code( in flash (via PROGMEM) and read with progmem_read_ptr(). String literals themselves remain in RAM but benefit from linker string deduplication. Index 0 means "not set" and returns empty string. + + When progmem_strings=True, each string is declared as a separate PROGMEM + char array. This ensures the string data itself is in flash on ESP8266 + (where .rodata is RAM). On other platforms PROGMEM is a no-op. """ if not strings: return "" sorted_strings = sorted(strings.items(), key=lambda x: x[1]) - entries = ", ".join(cpp_string_escape(s) for s, _ in sorted_strings) count = len(sorted_strings) + if progmem_strings: + # Emit individual PROGMEM char arrays so string data lives in flash + lines: list[str] = [] + var_names: list[str] = [] + for i, (s, _) in enumerate(sorted_strings): + var_name = f"{table_var}_STR_{i}" + var_names.append(var_name) + lines.append( + f"static const char {var_name}[] PROGMEM = {cpp_string_escape(s)};" + ) + entries = ", ".join(var_names) + # Empty string must also be PROGMEM — on ESP8266, callers use strncpy_P + empty_var = f"{table_var}_EMPTY" + lines.append(f'static const char {empty_var}[] PROGMEM = "";') + lines.append(f"static const char *const {table_var}[] PROGMEM = {{{entries}}};") + lines.append(f"const char *{lookup_fn}(uint8_t index) {{") + lines.append(f" if (index == 0 || index > {count}) return {empty_var};") + lines.append(f" return progmem_read_ptr(&{table_var}[index - 1]);") + lines.append("}") + return "\n".join(lines) + "\n" + + entries = ", ".join(cpp_string_escape(s) for s, _ in sorted_strings) + return ( f"static const char *const {table_var}[] PROGMEM = {{{entries}}};\n" f"const char *{lookup_fn}(uint8_t index) {{\n" @@ -103,9 +132,9 @@ def _generate_category_code( _CATEGORY_CONFIGS = ( - ("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes"), - ("ENTITY_UOM_TABLE", "entity_uom_lookup", "units"), - ("ENTITY_ICON_TABLE", "entity_icon_lookup", "icons"), + ("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes", False), + ("ENTITY_UOM_TABLE", "entity_uom_lookup", "units", False), + ("ENTITY_ICON_TABLE", "entity_icon_lookup", "icons", True), ) @@ -117,8 +146,10 @@ async def _generate_tables_job() -> None: """ pool = _get_pool() parts = ["namespace esphome {"] - for table_var, lookup_fn, attr in _CATEGORY_CONFIGS: - code = _generate_category_code(table_var, lookup_fn, getattr(pool, attr)) + for table_var, lookup_fn, attr, progmem_strs in _CATEGORY_CONFIGS: + code = _generate_category_code( + table_var, lookup_fn, getattr(pool, attr), progmem_strings=progmem_strs + ) if code: parts.append(code) parts.append("} // namespace esphome") @@ -160,6 +191,10 @@ def register_unit_of_measurement(value: str) -> int: def register_icon(value: str) -> int: """Register an icon string and return its 1-based index.""" + if value and len(value) > ICON_MAX_LENGTH: + raise ValueError( + f"Icon string too long ({len(value)} chars, max {ICON_MAX_LENGTH}): '{value}'" + ) return _register_string(value, _get_pool().icons, _MAX_ICONS, "icon") diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index a5cfad5ab6..79bc3095b9 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -23,6 +23,7 @@ from esphome.core.entity_helpers import ( _setup_entity_impl, entity_duplicate_validator, get_base_entity_object_id, + register_icon, setup_entity, ) from esphome.cpp_generator import MockObj @@ -909,6 +910,22 @@ def test_register_string_overflow() -> None: _register_string("overflow", category, 3, "test") +def test_register_icon_max_length() -> None: + """Test register_icon rejects icons exceeding 63 characters.""" + # 63 chars should succeed + max_icon = "mdi:" + "a" * 59 # 63 total + idx = register_icon(max_icon) + assert idx > 0 + + # 64 chars should fail + too_long = "mdi:" + "a" * 60 # 64 total + with pytest.raises(ValueError, match="Icon string too long"): + register_icon(too_long) + + # Empty string returns 0 + assert register_icon("") == 0 + + @pytest.mark.asyncio async def test_setup_entity_with_entity_category( setup_test_environment: list[str], diff --git a/tests/unit_tests/test_config_validation.py b/tests/unit_tests/test_config_validation.py index 9602010ad3..c1849daf4b 100644 --- a/tests/unit_tests/test_config_validation.py +++ b/tests/unit_tests/test_config_validation.py @@ -148,6 +148,18 @@ def test_icon__invalid(): config_validation.icon("foo") +def test_icon__max_length(): + """Test that icons exceeding 63 characters are rejected.""" + # Exactly 63 chars should pass + max_icon = "mdi:" + "a" * 59 # 63 chars total + assert config_validation.icon(max_icon) == max_icon + + # 64 chars should fail + too_long = "mdi:" + "a" * 60 # 64 chars total + with pytest.raises(Invalid, match="Icon string is too long"): + config_validation.icon(too_long) + + @pytest.mark.parametrize("value", ("True", "YES", "on", "enAblE", True)) def test_boolean__valid_true(value): assert config_validation.boolean(value) is True From 74e4b69654c2dd77f81cd712fe1c7ece3db78bfa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 06:58:13 -1000 Subject: [PATCH 1152/2030] [core] Replace Application name/friendly_name std::string with StringRef (#14532) Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> --- .../components/api/api_frame_helper_noise.cpp | 2 +- esphome/components/esp32_ble/ble.cpp | 2 +- esphome/components/mdns/mdns_component.cpp | 2 +- esphome/components/mqtt/mqtt_component.cpp | 6 +- esphome/components/openthread/openthread.cpp | 2 +- .../components/web_server/web_server_v1.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 2 +- .../wifi/wifi_component_esp8266.cpp | 2 +- esphome/core/application.h | 54 +++++++------ esphome/core/config.py | 60 +++++++++++++-- esphome/core/defines.h | 1 + esphome/core/entity_base.cpp | 6 +- tests/dummy_main.cpp | 4 +- tests/unit_tests/core/test_config.py | 77 +++++++++++++++++++ 14 files changed, 181 insertions(+), 41 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 3ae35e9be8..ba4f2f0642 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -269,7 +269,7 @@ APIError APINoiseFrameHelper::state_action_() { } if (state_ == State::SERVER_HELLO) { // send server hello - const std::string &name = App.get_name(); + const auto &name = App.get_name(); char mac[MAC_ADDRESS_BUFFER_SIZE]; get_mac_address_into_buffer(mac); diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 9d26018800..bbe972b9f3 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -273,7 +273,7 @@ bool ESP32BLE::ble_setup_() { device_name = this->name_; } } else { - const std::string &app_name = App.get_name(); + const auto &app_name = App.get_name(); size_t name_len = app_name.length(); if (name_len > 20) { if (App.is_name_add_mac_suffix_enabled()) { diff --git a/esphome/components/mdns/mdns_component.cpp b/esphome/components/mdns/mdns_component.cpp index 5e5e1279d9..342a6e6c64 100644 --- a/esphome/components/mdns/mdns_component.cpp +++ b/esphome/components/mdns/mdns_component.cpp @@ -59,7 +59,7 @@ void MDNSComponent::compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUN service.proto = MDNS_STR(SERVICE_TCP); service.port = api::global_api_server->get_port(); - const std::string &friendly_name = App.get_friendly_name(); + const auto &friendly_name = App.get_friendly_name(); bool friendly_name_empty = friendly_name.empty(); // Calculate exact capacity for txt_records diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 98fa10def9..d31a78b090 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -267,7 +267,7 @@ bool MQTTComponent::send_discovery_() { root[MQTT_UNIQUE_ID] = unique_id_buf; } - const std::string &node_name = App.get_name(); + const auto &node_name = App.get_name(); if (discovery_info.object_id_generator == MQTT_DEVICE_NAME_OBJECT_ID_GENERATOR) { // node_name (max 31) + "_" (1) + object_id (max 128) + null char object_id_full[ESPHOME_DEVICE_NAME_MAX_LEN + 1 + OBJECT_ID_MAX_LEN + 1]; @@ -275,8 +275,8 @@ bool MQTTComponent::send_discovery_() { root[MQTT_OBJECT_ID] = object_id_full; } - const std::string &friendly_name_ref = App.get_friendly_name(); - const std::string &node_friendly_name = friendly_name_ref.empty() ? node_name : friendly_name_ref; + const auto &friendly_name_ref = App.get_friendly_name(); + const auto &node_friendly_name = friendly_name_ref.empty() ? node_name : friendly_name_ref; const char *node_area = App.get_area(); JsonObject device_info = root[MQTT_DEVICE].to<JsonObject>(); diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index 9452f5a41e..fb81481299 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -132,7 +132,7 @@ void OpenThreadSrpComponent::setup() { // set the host name uint16_t size; char *existing_host_name = otSrpClientBuffersGetHostNameString(instance, &size); - const std::string &host_name = App.get_name(); + const auto &host_name = App.get_name(); uint16_t host_name_len = host_name.size(); if (host_name_len > size) { ESP_LOGW(TAG, "Hostname is too long, choose a shorter project name"); diff --git a/esphome/components/web_server/web_server_v1.cpp b/esphome/components/web_server/web_server_v1.cpp index f7b90018dc..85a4e80541 100644 --- a/esphome/components/web_server/web_server_v1.cpp +++ b/esphome/components/web_server/web_server_v1.cpp @@ -75,7 +75,7 @@ void WebServer::set_js_url(const char *js_url) { this->js_url_ = js_url; } void WebServer::handle_index_request(AsyncWebServerRequest *request) { AsyncResponseStream *stream = request->beginResponseStream(ESPHOME_F("text/html")); - const std::string &title = App.get_name(); + const auto &title = App.get_name(); stream->print(ESPHOME_F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=UTF-8><meta " "name=viewport content=\"width=device-width, initial-scale=1,user-scalable=no\"><title>")); stream->print(title.c_str()); diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8b60810d28..60764955cc 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -913,7 +913,7 @@ void WiFiComponent::setup_ap_config_() { static constexpr size_t AP_SSID_PREFIX_LEN = 25; static constexpr size_t AP_SSID_SUFFIX_LEN = 7; - const std::string &app_name = App.get_name(); + const auto &app_name = App.get_name(); const char *name_ptr = app_name.c_str(); size_t name_len = app_name.length(); diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 355832b434..a9b26c5935 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -212,7 +212,7 @@ network::IPAddresses WiFiComponent::wifi_sta_ip_addresses() { return addresses; } bool WiFiComponent::wifi_apply_hostname_() { - const std::string &hostname = App.get_name(); + const auto &hostname = App.get_name(); bool ret = wifi_station_set_hostname(const_cast<char *>(hostname.c_str())); if (!ret) { ESP_LOGV(TAG, "Set hostname failed"); diff --git a/esphome/core/application.h b/esphome/core/application.h index 40f8a00edd..87f9fdf59a 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -138,26 +138,36 @@ static constexpr uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for qu class Application { public: - void pre_setup(const std::string &name, const std::string &friendly_name, bool name_add_mac_suffix) { +#ifdef ESPHOME_NAME_ADD_MAC_SUFFIX + /// Pre-setup with MAC suffix: overwrites placeholder in mutable static buffers with actual MAC. + void pre_setup(char *name, size_t name_len, char *friendly_name, size_t friendly_name_len) { arch_init(); - this->name_add_mac_suffix_ = name_add_mac_suffix; - if (name_add_mac_suffix) { - // MAC address length: 12 hex chars + null terminator - constexpr size_t mac_address_len = 13; - // MAC address suffix length (last 6 characters of 12-char MAC address string) - constexpr size_t mac_address_suffix_len = 6; - char mac_addr[mac_address_len]; - get_mac_address_into_buffer(mac_addr); - const char *mac_suffix_ptr = mac_addr + mac_address_suffix_len; - this->name_ = make_name_with_suffix(name, '-', mac_suffix_ptr, mac_address_suffix_len); - if (!friendly_name.empty()) { - this->friendly_name_ = make_name_with_suffix(friendly_name, ' ', mac_suffix_ptr, mac_address_suffix_len); - } - } else { - this->name_ = name; - this->friendly_name_ = friendly_name; + this->name_add_mac_suffix_ = true; + // MAC address length: 12 hex chars + null terminator + constexpr size_t mac_address_len = 13; + // MAC address suffix length (last 6 characters of 12-char MAC address string) + constexpr size_t mac_address_suffix_len = 6; + char mac_addr[mac_address_len]; + get_mac_address_into_buffer(mac_addr); + // Overwrite the placeholder suffix in the mutable static buffers with actual MAC + // name is always non-empty (validated by validate_hostname in Python config) + memcpy(name + name_len - mac_address_suffix_len, mac_addr + mac_address_suffix_len, mac_address_suffix_len); + if (friendly_name_len > 0) { + memcpy(friendly_name + friendly_name_len - mac_address_suffix_len, mac_addr + mac_address_suffix_len, + mac_address_suffix_len); } + this->name_ = StringRef(name, name_len); + this->friendly_name_ = StringRef(friendly_name, friendly_name_len); } +#else + /// Pre-setup without MAC suffix: StringRef points directly at const string literals in flash. + void pre_setup(const char *name, size_t name_len, const char *friendly_name, size_t friendly_name_len) { + arch_init(); + this->name_add_mac_suffix_ = false; + this->name_ = StringRef(name, name_len); + this->friendly_name_ = StringRef(friendly_name, friendly_name_len); + } +#endif #ifdef USE_DEVICES void register_device(Device *device) { this->devices_.push_back(device); } @@ -274,10 +284,10 @@ class Application { void loop(); /// Get the name of this Application set by pre_setup(). - const std::string &get_name() const { return this->name_; } + const StringRef &get_name() const { return this->name_; } /// Get the friendly name of this Application set by pre_setup(). - const std::string &get_friendly_name() const { return this->friendly_name_; } + const StringRef &get_friendly_name() const { return this->friendly_name_; } /// Get the area of this Application set by pre_setup(). const char *get_area() const { @@ -627,9 +637,9 @@ class Application { #endif #endif - // std::string members (typically 24-32 bytes each) - std::string name_; - std::string friendly_name_; + // StringRef members (8 bytes each: pointer + size) + StringRef name_; + StringRef friendly_name_; // 4-byte members uint32_t last_loop_{0}; diff --git a/esphome/core/config.py b/esphome/core/config.py index 9093ab3fe9..8631726a02 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -50,6 +50,7 @@ from esphome.core import ( ) from esphome.helpers import ( copy_file_if_changed, + cpp_string_escape, fnv1a_32bit_hash, get_str_env, walk_files, @@ -58,6 +59,38 @@ from esphome.types import ConfigType _LOGGER = logging.getLogger(__name__) +# C++ variable names and separators for app name buffers (used with MAC suffix) +_APP_NAME_BUF_VAR = "esphome_app_name_buf" +_APP_NAME_MAC_SEP = "-" +_APP_FRIENDLY_NAME_BUF_VAR = "esphome_app_friendly_name_buf" +_APP_FRIENDLY_NAME_MAC_SEP = " " +# Placeholder suffix for MAC address (last 6 hex chars) +_MAC_SUFFIX_PLACEHOLDER = "XXXXXX" + + +def make_app_name_cpp( + value: str, var_name: str, sep: str, *, add_mac_suffix: bool +) -> tuple[str, str | None, int]: + """Compute C++ expression and optional global declaration for an app name. + + Returns (cpp_expr, global_decl_or_none, byte_length). + - cpp_expr: The C++ expression to pass to pre_setup (var name or string literal). + - global_decl: A static char[] declaration string, or None if not needed. + - byte_length: The UTF-8 byte length of the string value. + """ + if add_mac_suffix: + buf_value = "" if not value else f"{value}{sep}{_MAC_SUFFIX_PLACEHOLDER}" + escaped = cpp_string_escape(buf_value) + return ( + var_name, + f"static char {var_name}[] = {escaped};", + len(buf_value.encode("utf-8")), + ) + if not value: + return '""', None, 0 + return cpp_string_escape(value), None, len(value.encode("utf-8")) + + StartupTrigger = cg.esphome_ns.class_( "StartupTrigger", cg.Component, automation.Trigger.template() ) @@ -78,6 +111,8 @@ VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"} def validate_hostname(config): # Keep in sync with ESPHOME_DEVICE_NAME_MAX_LEN in esphome/core/entity_base.h + if not config[CONF_NAME]: + raise cv.Invalid("Hostname must not be empty", path=[CONF_NAME]) max_length = 31 if config[CONF_NAME_ADD_MAC_SUFFIX]: max_length -= 7 # "-AABBCC" is appended when add mac suffix option is used @@ -555,13 +590,28 @@ async def to_code(config: ConfigType) -> None: # Construct App via placement new — see application.cpp for storage details cg.add_global(cg.RawStatement("#include <new>")) cg.add(cg.RawExpression("new (&App) Application()")) - cg.add( - cg.App.pre_setup( - config[CONF_NAME], - config[CONF_FRIENDLY_NAME], - config[CONF_NAME_ADD_MAC_SUFFIX], + name = config[CONF_NAME] + friendly_name = config[CONF_FRIENDLY_NAME] + name_add_mac_suffix = config[CONF_NAME_ADD_MAC_SUFFIX] + + def _emit_app_name( + value: str, var_name: str, sep: str + ) -> tuple[cg.Expression, int]: + """Emit codegen for an app name and return (expression, byte_length).""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + value, var_name, sep, add_mac_suffix=name_add_mac_suffix ) + if global_decl is not None: + cg.add_global(cg.RawStatement(global_decl)) + return cg.RawExpression(cpp_expr), byte_len + + name_expr, name_len = _emit_app_name(name, _APP_NAME_BUF_VAR, _APP_NAME_MAC_SEP) + friendly_expr, friendly_len = _emit_app_name( + friendly_name, _APP_FRIENDLY_NAME_BUF_VAR, _APP_FRIENDLY_NAME_MAC_SEP ) + if name_add_mac_suffix: + cg.add_define("ESPHOME_NAME_ADD_MAC_SUFFIX") + cg.add(cg.App.pre_setup(name_expr, name_len, friendly_expr, friendly_len)) # Define component count for static allocation cg.add_define("ESPHOME_COMPONENT_COUNT", len(CORE.component_ids)) diff --git a/esphome/core/defines.h b/esphome/core/defines.h index be5fdc9006..c5f38ab9aa 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -13,6 +13,7 @@ #define ESPHOME_PROJECT_VERSION "v2" #define ESPHOME_PROJECT_VERSION_30 "v2" #define ESPHOME_VARIANT "ESP32" +#define ESPHOME_NAME_ADD_MAC_SUFFIX #define ESPHOME_DEBUG_SCHEDULER #define ESPHOME_DEBUG_API diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 1265277572..37e7fcc998 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -23,13 +23,13 @@ void EntityBase::set_name(const char *name, uint32_t object_id_hash) { // Bug-for-bug compatibility with OLD behavior: // - With MAC suffix: OLD code used App.get_friendly_name() directly (no fallback) // - Without MAC suffix: OLD code used pre-computed object_id with fallback to device name - const std::string &friendly = App.get_friendly_name(); + const auto &friendly = App.get_friendly_name(); if (App.is_name_add_mac_suffix_enabled()) { // MAC suffix enabled - use friendly_name directly (even if empty) for compatibility - this->name_ = StringRef(friendly); + this->name_ = friendly; } else { // No MAC suffix - fallback to device name if friendly_name is empty - this->name_ = StringRef(!friendly.empty() ? friendly : App.get_name()); + this->name_ = !friendly.empty() ? friendly : App.get_name(); } } this->flags_.has_own_name = false; diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index 3ccf35e04d..6fa0c08aa3 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -12,7 +12,9 @@ using namespace esphome; void setup() { - App.pre_setup("livingroom", "LivingRoom", false); + static char name[] = "livingroom"; + static char friendly_name[] = "LivingRoom"; + App.pre_setup(name, sizeof(name) - 1, friendly_name, sizeof(friendly_name) - 1); auto *log = new logger::Logger(115200); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); diff --git a/tests/unit_tests/core/test_config.py b/tests/unit_tests/core/test_config.py index 88801a9ca0..474d31a90a 100644 --- a/tests/unit_tests/core/test_config.py +++ b/tests/unit_tests/core/test_config.py @@ -23,6 +23,7 @@ from esphome.const import ( from esphome.core import CORE, config from esphome.core.config import ( Area, + make_app_name_cpp, preload_core_config, valid_include, valid_project_name, @@ -969,3 +970,79 @@ def test_config_hash_different_for_different_configs() -> None: hash2 = CORE.config_hash assert hash1 != hash2 + + +def test_make_app_name_cpp_no_mac_simple() -> None: + """Test simple name without MAC suffix returns string literal.""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + "my-device", "buf", "-", add_mac_suffix=False + ) + assert cpp_expr == '"my-device"' + assert global_decl is None + assert byte_len == 9 + + +def test_make_app_name_cpp_no_mac_empty() -> None: + """Test empty name without MAC suffix.""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + "", "buf", "-", add_mac_suffix=False + ) + assert cpp_expr == '""' + assert global_decl is None + assert byte_len == 0 + + +def test_make_app_name_cpp_mac_suffix() -> None: + """Test name with MAC suffix emits static buffer.""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + "my-device", "esphome_app_name_buf", "-", add_mac_suffix=True + ) + assert cpp_expr == "esphome_app_name_buf" + assert global_decl is not None + assert "static char esphome_app_name_buf[]" in global_decl + assert "my-device-XXXXXX" in global_decl + assert byte_len == len("my-device-XXXXXX") + + +def test_make_app_name_cpp_mac_suffix_empty() -> None: + """Test empty name with MAC suffix emits empty static buffer.""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + "", "esphome_app_name_buf", "-", add_mac_suffix=True + ) + assert cpp_expr == "esphome_app_name_buf" + assert global_decl is not None + assert "static char esphome_app_name_buf[]" in global_decl + assert byte_len == 0 + + +def test_make_app_name_cpp_mac_suffix_space_sep() -> None: + """Test friendly name uses space separator for MAC suffix.""" + cpp_expr, global_decl, byte_len = make_app_name_cpp( + "My Device", "esphome_app_friendly_name_buf", " ", add_mac_suffix=True + ) + assert cpp_expr == "esphome_app_friendly_name_buf" + assert global_decl is not None + assert "My Device XXXXXX" in global_decl + assert byte_len == len("My Device XXXXXX") + + +def test_make_app_name_cpp_non_ascii_utf8_length() -> None: + """Test non-ASCII characters use UTF-8 byte length.""" + _, global_decl, byte_len = make_app_name_cpp( + "café", "buf", "-", add_mac_suffix=False + ) + assert byte_len == len("café".encode()) # 5 bytes, not 4 chars + assert global_decl is None + + +def test_make_app_name_cpp_non_ascii_mac_suffix_utf8_length() -> None: + """Test non-ASCII with MAC suffix uses UTF-8 byte length.""" + _, _, byte_len = make_app_name_cpp("café", "buf", "-", add_mac_suffix=True) + assert byte_len == len("café-XXXXXX".encode()) + + +def test_make_app_name_cpp_special_chars_escaped() -> None: + """Test special characters are properly escaped in C++ string.""" + cpp_expr, _, _ = make_app_name_cpp('my "device"', "buf", "-", add_mac_suffix=False) + # cpp_string_escape uses octal escapes for quotes + assert '"' not in cpp_expr[1:-1] # no unescaped quotes inside the outer quotes From a16b8fc0ac30a015df61555d59fb98e19a9efe6a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 07:00:31 -1000 Subject: [PATCH 1153/2030] [rp2040] Fix Pico W LED pin and auto-generate board definitions for arduino-pico 5.5.x (#14528) --- esphome/components/rp2040/boards.jinja2 | 25 + esphome/components/rp2040/boards.py | 2199 ++++++++++++++++- esphome/components/rp2040/generate_boards.py | 186 ++ esphome/components/rp2040/gpio.py | 22 +- .../components/test_rp2040_generate_boards.py | 273 ++ 5 files changed, 2688 insertions(+), 17 deletions(-) create mode 100644 esphome/components/rp2040/boards.jinja2 create mode 100644 esphome/components/rp2040/generate_boards.py create mode 100644 tests/unit_tests/components/test_rp2040_generate_boards.py diff --git a/esphome/components/rp2040/boards.jinja2 b/esphome/components/rp2040/boards.jinja2 new file mode 100644 index 0000000000..989fb83701 --- /dev/null +++ b/esphome/components/rp2040/boards.jinja2 @@ -0,0 +1,25 @@ +# Auto-generated by generate_boards.py — do not edit manually +# To regenerate: python esphome/components/rp2040/generate_boards.py <arduino-pico-path> + +# arduino-pico maps pins >= {{ cyw43_gpio_offset }} to CYW43 wireless chip GPIOs +CYW43_GPIO_OFFSET = {{ cyw43_gpio_offset }} +CYW43_MAX_GPIO = {{ cyw43_max_gpio }} +DEFAULT_MAX_PIN = {{ default_max_pin }} + +RP2040_BASE_PINS = {} + +RP2040_BOARD_PINS = { +{%- for name, pins in board_pins %} + {{ name | repr }}: {{ pins | format_pins }}, +{%- endfor %} +} + +BOARDS = { +{%- for name, info in boards %} + {{ name | repr }}: { + {%- for key, value in info.items() %} + {{ key | repr }}: {{ value | repr }}, + {%- endfor %} + }, +{%- endfor %} +} diff --git a/esphome/components/rp2040/boards.py b/esphome/components/rp2040/boards.py index c761efba58..c99934567a 100644 --- a/esphome/components/rp2040/boards.py +++ b/esphome/components/rp2040/boards.py @@ -1,28 +1,2205 @@ +# Auto-generated by generate_boards.py — do not edit manually +# To regenerate: python esphome/components/rp2040/generate_boards.py <arduino-pico-path> + +# arduino-pico maps pins >= 64 to CYW43 wireless chip GPIOs +CYW43_GPIO_OFFSET = 64 +CYW43_MAX_GPIO = 66 +DEFAULT_MAX_PIN = 29 + RP2040_BASE_PINS = {} RP2040_BOARD_PINS = { - "pico": { - "SDA": 4, - "SCL": 5, - "LED": 25, - "SDA1": 26, - "SCL1": 27, + "0xcb_helios": { + "LED": 17, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL1": 3, + "SDA1": 2, + "SS": 21, + "TX": 0, }, - "rpipico": "pico", - "rpipicow": { - "SDA": 4, + "DudesCab": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 19, + "SCL1": 11, + "SDA": 18, + "SDA1": 10, + "SS": 5, + "TX": 0, + }, + "MyRP_2350B": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, "SCL": 5, - "LED": 32, - "SDA1": 26, "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "MyRP_bot": { + "LED": 25, + "MISO": 12, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 17, + "SCL1": 4, + "SDA": 16, + "SDA1": 5, + "SS": 13, + }, + "adafruit_feather": { + "LED": 13, + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 3, + "SCL1": 25, + "SDA": 2, + "SDA1": 24, + "SS": 17, + "TX": 0, + }, + "adafruit_feather_adalogger": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_can": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_dvi": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_prop_maker": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_rfm": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_rp2350_adalogger": { + "LED": 7, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 3, + "SCL1": 31, + "SDA": 2, + "SDA1": 31, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_rp2350_hstx": { + "LED": 7, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 3, + "SCL1": 31, + "SDA": 2, + "SDA1": 31, + "SS": 21, + "TX": 0, + }, + "adafruit_feather_scorpio": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_thinkink": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_feather_usb_host": { + "LED": 13, + "MISO": 8, + "MOSI": 15, + "RX": 1, + "SCK": 14, + "SCL": 3, + "SDA": 2, + "SS": 13, + "TX": 0, + }, + "adafruit_floppsy": { + "LED": 28, + "MISO": 20, + "MOSI": 19, + "SCK": 18, + "SCL": 17, + "SDA": 16, + "SS": 24, + }, + "adafruit_fruitjam": { + "LED": 29, + "MISO": 36, + "MOSI": 35, + "RX": 9, + "SCK": 34, + "SCL": 21, + "SDA": 20, + "SS": 39, + "TX": 8, + }, + "adafruit_itsybitsy": { + "LED": 11, + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 25, + "SCL1": 3, + "SDA": 24, + "SDA1": 2, + "TX": 0, + }, + "adafruit_kb2040": { + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 13, + "SCL1": 3, + "SDA": 12, + "SDA1": 2, + "TX": 0, + }, + "adafruit_macropad2040": {"LED": 13, "SCL": 21, "SDA": 20}, + "adafruit_metro": { + "LED": 13, + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 17, + "SCL1": 3, + "SDA": 16, + "SDA1": 2, + "SS": 23, + "TX": 0, + }, + "adafruit_metro_rp2350": { + "LED": 23, + "MISO": 28, + "MOSI": 31, + "RX": 1, + "SCK": 30, + "SCL": 21, + "SDA": 20, + "SS": 29, + "TX": 0, + }, + "adafruit_qtpy": { + "MISO": 4, + "MOSI": 3, + "RX": 29, + "SCK": 6, + "SCL": 25, + "SCL1": 23, + "SDA": 24, + "SDA1": 22, + "TX": 28, + }, + "adafruit_stemmafriend": { + "LED": 12, + "MISO": 4, + "MOSI": 7, + "RX": 27, + "SCK": 2, + "SCL": 21, + "SCL1": 27, + "SDA": 20, + "SDA1": 26, + "SS": 1, + "TX": 26, + }, + "adafruit_trinkeyrp2040qt": {"RX": 17, "SCL": 17, "SDA": 16, "TX": 16}, + "akana_r1": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "amken_bunny": {"LED": 24, "RX": 1, "TX": 0}, + "amken_revelop": {"LED": 24, "RX": 1, "SCL": 29, "SDA": 28, "TX": 0}, + "amken_revelop_es": {"LED": 5, "MISO": 0, "MOSI": 3, "SCK": 2, "SS": 1, "TX": 20}, + "amken_revelop_plus": {"LED": 24, "RX": 1, "SCL": 29, "SDA": 28, "TX": 0}, + "artronshop_rp2_nano": { + "LED": 13, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 17, + "SCL1": 19, + "SDA": 16, + "SDA1": 18, + "SS": 5, + "TX": 0, + }, + "bigtreetech_SKR_Pico": {"LED": 13, "RX": 1, "TX": 0}, + "breadstick_raspberry": { + "RX": 21, + "SCL": 13, + "SCL1": 23, + "SDA": 12, + "SDA1": 22, + "TX": 20, + }, + "bridgetek_idm2040_43a": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "bridgetek_idm2040_7a": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "challenger_2040_lora": { + "LED": 24, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_lte": { + "LED": 19, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_nfc": { + "LED": 24, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SCL1": 11, + "SDA": 0, + "SDA1": 10, + "SS": 21, + "TX": 16, + }, + "challenger_2040_sdrtc": { + "LED": 24, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_subghz": { + "LED": 24, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_uwb": { + "LED": 24, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_wifi": { + "LED": 12, + "MISO": 24, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_wifi6_ble": { + "LED": 10, + "MISO": 24, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2040_wifi_ble": { + "LED": 10, + "MISO": 24, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "challenger_2350_bconnect": { + "LED": 7, + "MISO": 16, + "MOSI": 19, + "RX": 13, + "SCK": 18, + "SCL": 21, + "SCL1": 11, + "SDA": 20, + "SDA1": 10, + "SS": 17, + "TX": 12, + }, + "challenger_2350_wifi6_ble5": { + "LED": 7, + "MISO": 16, + "MOSI": 19, + "RX": 13, + "SCK": 18, + "SCL": 21, + "SCL1": 31, + "SDA": 20, + "SDA1": 31, + "SS": 17, + "TX": 12, + }, + "challenger_nb_2040_wifi": { + "LED": 12, + "MISO": 24, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "connectivity_2040_lte_wifi_ble": { + "LED": 19, + "MISO": 20, + "MOSI": 23, + "RX": 17, + "SCK": 22, + "SCL": 1, + "SDA": 0, + "SS": 21, + "TX": 16, + }, + "cytron_iriv_io_controller": { + "LED": 29, + "MISO": 20, + "MOSI": 19, + "RX": 31, + "SCK": 22, + "SCL": 17, + "SCL1": 31, + "SDA": 16, + "SDA1": 31, + "SS": 21, + "TX": 31, + }, + "cytron_maker_nano_rp2040": { + "LED": 2, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 1, + "SCL1": 27, + "SDA": 0, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "cytron_maker_pi_rp2040": { + "LED": 3, + "RX": 1, + "SCL": 17, + "SCL1": 3, + "SDA": 16, + "SDA1": 2, + "TX": 0, + }, + "cytron_maker_uno_rp2040": { + "LED": 3, + "MISO": 12, + "MOSI": 11, + "RX": 1, + "SCK": 10, + "SCL": 21, + "SCL1": 27, + "SDA": 20, + "SDA1": 26, + "SS": 13, + "TX": 0, + }, + "cytron_motion_2350_pro": { + "LED": 2, + "MISO": 4, + "MOSI": 7, + "RX": 1, + "SCK": 6, + "SCL": 17, + "SCL1": 27, + "SDA": 16, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "datanoisetv_picoadk": { + "LED": 15, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "datanoisetv_picoadk_v2": { + "LED": 2, + "MISO": 8, + "MOSI": 7, + "RX": 13, + "SCK": 6, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 5, + "TX": 12, + }, + "degz_suibo": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "dfrobot_beetle_rp2040": { + "LED": 13, + "MISO": 0, + "MOSI": 3, + "RX": 29, + "SCK": 2, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 1, + "TX": 28, + }, + "electroniccats_huntercat_nfc": {"LED": 8, "RX": 1, "SCL": 5, "SDA": 4, "TX": 0}, + "evn_alpha": { + "LED": 25, + "MISO": 0, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 1, + "TX": 0, + }, + "extelec_rc2040": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SDA": 4, + "SS": 5, + "TX": 0, + }, + "flyboard2040_core": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 17, + "SCL1": 15, + "SDA": 16, + "SDA1": 14, + "SS": 5, + "TX": 0, + }, + "geeekpi_rp2040_plus": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "generic": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "generic_rp2350": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "groundstudio_marble_pico": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "ilabs_rpico32": { + "MISO": 24, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SDA": 4, + "SS": 21, + "TX": 0, + }, + "jumperless_v1": { + "LED": 25, + "MISO": 0, + "MOSI": 3, + "RX": 17, + "SCK": 2, + "SCL": 5, + "SCL1": 19, + "SDA": 4, + "SDA1": 18, + "SS": 1, + "TX": 16, + }, + "jumperless_v5": { + "LED": 17, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SCL1": 23, + "SDA": 4, + "SDA1": 22, + "SS": 21, + "TX": 0, + }, + "melopero_cookie_rp2040": { + "LED": 21, + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 13, + "SCL1": 3, + "SDA": 12, + "SDA1": 2, + "SS": 1, + "TX": 0, + }, + "melopero_shake_rp2040": { + "LED": 25, + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 3, + "SDA": 8, + "SDA1": 2, + "SS": 1, + "TX": 0, + }, + "mksthr36": { + "MISO": 16, + "MOSI": 19, + "SCK": 18, + "SCL": 23, + "SDA": 22, + "SS": 17, + "TX": 6, + }, + "mksthr42": { + "MISO": 16, + "MOSI": 19, + "SCK": 18, + "SCL": 23, + "SDA": 22, + "SS": 17, + "TX": 6, + }, + "nekosystems_bl2040_mini": { + "LED": 6, + "MISO": 16, + "MOSI": 19, + "RX": 13, + "SCK": 18, + "SCL": 25, + "SCL1": 23, + "SDA": 24, + "SDA1": 22, + "SS": 17, + "TX": 12, + }, + "newsan_archi": { + "MISO": 4, + "MOSI": 3, + "RX": 17, + "SCK": 2, + "SCL": 1, + "SCL1": 7, + "SDA": 0, + "SDA1": 6, + "SS": 5, + "TX": 16, + }, + "nullbits_bit_c_pro": { + "LED": 18, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 3, + "SCL1": 5, + "SDA": 2, + "SDA1": 4, + "SS": 21, + "TX": 0, + }, + "olimex_pico2bb48": { + "LED": 25, + "MISO": 4, + "MOSI": 7, + "RX": 1, + "SCK": 6, + "SCL": 13, + "SCL1": 3, + "SDA": 12, + "SDA1": 2, + "SS": 5, + "TX": 0, + }, + "olimex_pico2xl": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "olimex_pico2xxl": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "picolume": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "pimoroni_explorer": { + "MISO": 10, + "MOSI": 10, + "RX": 10, + "SCK": 10, + "SCL": 21, + "SCL1": 10, + "SDA": 20, + "SDA1": 10, + "SS": 10, + "TX": 10, + }, + "pimoroni_pico_plus_2": { + "LED": 25, + "MISO": 32, + "MOSI": 35, + "RX": 1, + "SCK": 34, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 33, + "TX": 0, + }, + "pimoroni_pico_plus_2w": { + "LED": 64, + "MISO": 32, + "MOSI": 35, + "RX": 1, + "SCK": 34, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 33, + "TX": 0, + }, + "pimoroni_plasma2040": {"LED": 16, "SCL": 21, "SDA": 20}, + "pimoroni_plasma2350": { + "LED": 16, + "MISO": 31, + "MOSI": 31, + "RX": 31, + "SCK": 31, + "SCL": 21, + "SCL1": 31, + "SDA": 20, + "SDA1": 31, + "SS": 31, + "TX": 31, + }, + "pimoroni_plasma2350w": { + "LED": 16, + "MISO": 24, + "MOSI": 24, + "RX": 31, + "SCK": 29, + "SCL": 21, + "SCL1": 31, + "SDA": 20, + "SDA1": 31, + "SS": 25, + "TX": 31, + }, + "pimoroni_servo2040": {"LED": 18, "SCL": 21, "SDA": 20}, + "pimoroni_tiny2040": { + "LED": 19, + "MISO": 4, + "MOSI": 7, + "RX": 1, + "SCK": 6, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "pimoroni_tiny2350": { + "LED": 19, + "MISO": 4, + "MOSI": 7, + "RX": 1, + "SCK": 6, + "SCL": 13, + "SCL1": 7, + "SDA": 12, + "SDA1": 6, + "SS": 5, + "TX": 0, + }, + "pintronix_pinmax": { + "LED": 27, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SDA": 4, + "SS": 17, + "TX": 0, + }, + "rakwireless_rak11300": { + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 3, + "SCL1": 21, + "SDA": 2, + "SDA1": 20, + "SS": 17, + "TX": 0, + }, + "rpipico": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "rpipico2": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "rpipico2w": { + "LED": 64, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "rpipicow": { + "LED": 64, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "sea_picro": { + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 21, + "TX": 0, + }, + "seeed_indicator_rp2040": { + "MISO": 0, + "MOSI": 3, + "RX": 17, + "SCK": 2, + "SCL": 21, + "SCL1": 15, + "SDA": 20, + "SDA1": 14, + "SS": 1, + "TX": 16, + }, + "seeed_xiao_rp2040": { + "LED": 17, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 7, + "SDA": 6, + "TX": 0, + }, + "seeed_xiao_rp2350": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 17, + "SCL1": 7, + "SDA": 16, + "SDA1": 6, + "SS": 5, + "TX": 0, + }, + "silicognition_rp2040_shim": { + "MISO": 12, + "MOSI": 11, + "RX": 1, + "SCK": 10, + "SCL": 17, + "SDA": 16, + "SS": 21, + "TX": 0, + }, + "soldered_nula_rp2350": { + "MISO": 2, + "MOSI": 3, + "RX": 1, + "SCK": 4, + "SCL": 9, + "SCL1": 31, + "SDA": 8, + "SDA1": 30, + "SS": 5, + "TX": 0, + }, + "solderparty_rp2040_stamp": { + "LED": 20, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 17, + "TX": 0, + }, + "solderparty_rp2350_stamp": { + "LED": 3, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 21, + "TX": 0, + }, + "solderparty_rp2350_stamp_xl": { + "LED": 3, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 21, + "TX": 0, + }, + "sparkfun_iotnode_lorawanrp2350": { + "LED": 25, + "MISO": 12, + "MOSI": 15, + "RX": 19, + "SCK": 14, + "SCL": 21, + "SCL1": 31, + "SDA": 20, + "SDA1": 31, + "SS": 13, + "TX": 18, + }, + "sparkfun_iotredboard_rp2350": { + "LED": 25, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SCL1": 31, + "SDA": 4, + "SDA1": 30, + "SS": 21, + "TX": 0, + }, + "sparkfun_micromodrp2040": { + "LED": 25, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 5, + "SDA": 4, + "SS": 21, + "TX": 0, + }, + "sparkfun_promicrorp2040": { + "LED": 25, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 17, + "SDA": 16, + "SS": 21, + "TX": 0, + }, + "sparkfun_promicrorp2350": { + "LED": 25, + "MISO": 20, + "MOSI": 23, + "RX": 1, + "SCK": 22, + "SCL": 17, + "SCL1": 31, + "SDA": 16, + "SDA1": 31, + "SS": 21, + "TX": 0, + }, + "sparkfun_thingplusrp2040": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 17, + "SCL1": 7, + "SDA": 16, + "SDA1": 6, + "TX": 0, + }, + "sparkfun_thingplusrp2350": { + "LED": 64, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 7, + "SCL1": 31, + "SDA": 6, + "SDA1": 31, + "SS": 9, + "TX": 0, + }, + "sparkfun_xrp_controller": { + "LED": 64, + "MISO": 16, + "MOSI": 19, + "RX": 13, + "SCK": 18, + "SCL": 5, + "SCL1": 39, + "SDA": 4, + "SDA1": 38, + "SS": 17, + "TX": 12, + }, + "sparkfun_xrp_controller_beta": {"LED": 64, "SCL": 19, "SDA": 18}, + "upesy_rp2040_devkit": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 23, + "SDA": 4, + "SDA1": 22, + "SS": 17, + "TX": 0, + }, + "vccgnd_yd_rp2040": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "vicharak_shrike-lite": { + "LED": 4, + "MISO": 20, + "MOSI": 19, + "RX": 17, + "SCK": 18, + "SCL": 25, + "SCL1": 7, + "SDA": 24, + "SDA1": 6, + "SS": 21, + "TX": 16, + }, + "viyalab_mizu": { + "LED": 25, + "MISO": 16, + "MOSI": 7, + "RX": 1, + "SCK": 6, + "SCL": 5, + "SCL1": 3, + "SDA": 4, + "SDA1": 2, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2040_lcd_0_96": { + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2040_lcd_1_28": { + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2040_lora": { + "LED": 25, + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 7, + "SDA": 4, + "SDA1": 6, + "SS": 5, + "TX": 0, + }, + "waveshare_rp2040_matrix": { + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "waveshare_rp2040_one": { + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "waveshare_rp2040_pizero": { + "MISO": 20, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 21, + "TX": 0, + }, + "waveshare_rp2040_plus": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2040_zero": { + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "waveshare_rp2350_lcd_0_96": { + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2350_pizero": { + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2350_plus": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "waveshare_rp2350_zero": { + "MISO": 4, + "MOSI": 3, + "RX": 1, + "SCK": 2, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "waveshare_rp2350b_plus_w": { + "LED": 23, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 7, + "SDA": 8, + "SDA1": 6, + "SS": 17, + "TX": 0, + }, + "wiznet_55rp20_evb_pico": { + "LED": 19, + "MISO": 2, + "MOSI": 3, + "RX": 1, + "SCK": 4, + "SCL": 5, + "SCL1": 27, + "SDA": 4, + "SDA1": 26, + "SS": 5, + "TX": 0, + }, + "wiznet_wizfi360_evb_pico": { + "LED": 25, + "MISO": 16, + "MOSI": 19, + "RX": 1, + "SCK": 18, + "SCL": 9, + "SCL1": 27, + "SDA": 8, + "SDA1": 26, + "SS": 17, + "TX": 0, }, } BOARDS = { + "0xcb_helios": { + "name": "0xCB Helios", + "mcu": "rp2040", + "max_pin": 29, + }, + "DudesCab": { + "name": "L'atelier d'Arnoz DudesCab", + "mcu": "rp2040", + "max_pin": 29, + }, + "MyRP_2350B": { + "name": "MyMakers RP2350B", + "mcu": "rp2350", + "max_pin": 47, + }, + "MyRP_bot": { + "name": "MyMakers RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather": { + "name": "Adafruit Feather RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_adalogger": { + "name": "Adafruit Feather RP2040 Adalogger", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_can": { + "name": "Adafruit Feather RP2040 CAN", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_dvi": { + "name": "Adafruit Feather RP2040 DVI", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_prop_maker": { + "name": "Adafruit Feather RP2040 Prop-Maker", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_rfm": { + "name": "Adafruit Feather RP2040 RFM", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_rp2350_adalogger": { + "name": "Adafruit Feather RP2350 Adalogger", + "mcu": "rp2350", + "max_pin": 47, + }, + "adafruit_feather_rp2350_hstx": { + "name": "Adafruit Feather RP2350 HSTX", + "mcu": "rp2350", + "max_pin": 47, + }, + "adafruit_feather_scorpio": { + "name": "Adafruit Feather RP2040 SCORPIO", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_thinkink": { + "name": "Adafruit Feather RP2040 ThinkINK", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_feather_usb_host": { + "name": "Adafruit Feather RP2040 USB Host", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_floppsy": { + "name": "Adafruit Floppsy", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_fruitjam": { + "name": "Adafruit Fruit Jam RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "adafruit_itsybitsy": { + "name": "Adafruit ItsyBitsy RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_kb2040": { + "name": "Adafruit KB2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_macropad2040": { + "name": "Adafruit MacroPad RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_metro": { + "name": "Adafruit Metro RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_metro_rp2350": { + "name": "Adafruit Metro RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "adafruit_qtpy": { + "name": "Adafruit QT Py RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_stemmafriend": { + "name": "Adafruit STEMMA Friend RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "adafruit_trinkeyrp2040qt": { + "name": "Adafruit Trinkey RP2040 QT", + "mcu": "rp2040", + "max_pin": 29, + }, + "akana_r1": { + "name": "METE HOCA Akana R1", + "mcu": "rp2040", + "max_pin": 29, + }, + "amken_bunny": { + "name": "Amken BunnyBoard", + "mcu": "rp2040", + "max_pin": 29, + }, + "amken_revelop": { + "name": "Amken Revelop", + "mcu": "rp2040", + "max_pin": 29, + }, + "amken_revelop_es": { + "name": "Amken Revelop eS", + "mcu": "rp2040", + "max_pin": 29, + }, + "amken_revelop_plus": { + "name": "Amken Revelop Plus", + "mcu": "rp2040", + "max_pin": 29, + }, + "arduino_nano_connect": { + "name": "Arduino Nano RP2040 Connect", + "mcu": "rp2040", + "max_pin": 29, + }, + "artronshop_rp2_nano": { + "name": "ArtronShop RP2 Nano", + "mcu": "rp2040", + "max_pin": 29, + }, + "bigtreetech_SKR_Pico": { + "name": "BIGTREETECH SKR-Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "breadstick_raspberry": { + "name": "Breadstick Raspberry", + "mcu": "rp2040", + "max_pin": 29, + }, + "bridgetek_idm2040_43a": { + "name": "BridgeTek IDM2040-43A", + "mcu": "rp2040", + "max_pin": 29, + }, + "bridgetek_idm2040_7a": { + "name": "BridgeTek IDM2040-7A", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_lora": { + "name": "iLabs Challenger 2040 LoRa", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_lte": { + "name": "iLabs Challenger 2040 LTE", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_nfc": { + "name": "iLabs Challenger 2040 NFC", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_sdrtc": { + "name": "iLabs Challenger 2040 SD/RTC", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_subghz": { + "name": "iLabs Challenger 2040 SubGHz", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_uwb": { + "name": "iLabs Challenger 2040 UWB", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_wifi": { + "name": "iLabs Challenger 2040 WiFi", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_wifi6_ble": { + "name": "iLabs Challenger 2040 WiFi6/BLE", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2040_wifi_ble": { + "name": "iLabs Challenger 2040 WiFi/BLE", + "mcu": "rp2040", + "max_pin": 29, + }, + "challenger_2350_bconnect": { + "name": "iLabs Challenger 2350 BConnect", + "mcu": "rp2350", + "max_pin": 47, + }, + "challenger_2350_wifi6_ble5": { + "name": "iLabs Challenger 2350 WiFi/BLE", + "mcu": "rp2350", + "max_pin": 47, + }, + "challenger_nb_2040_wifi": { + "name": "iLabs Challenger NB 2040 WiFi", + "mcu": "rp2040", + "max_pin": 29, + }, + "connectivity_2040_lte_wifi_ble": { + "name": "iLabs Connectivity 2040 LTE/WiFi/BLE", + "mcu": "rp2040", + "max_pin": 29, + }, + "cytron_iriv_io_controller": { + "name": "Cytron IRIV IO Controller", + "mcu": "rp2350", + "max_pin": 47, + }, + "cytron_maker_nano_rp2040": { + "name": "Cytron Maker Nano RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "cytron_maker_pi_rp2040": { + "name": "Cytron Maker Pi RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "cytron_maker_uno_rp2040": { + "name": "Cytron Maker Uno RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "cytron_motion_2350_pro": { + "name": "Cytron Motion 2350 Pro", + "mcu": "rp2350", + "max_pin": 47, + }, + "datanoisetv_picoadk": { + "name": "DatanoiseTV PicoADK", + "mcu": "rp2040", + "max_pin": 29, + }, + "datanoisetv_picoadk_v2": { + "name": "DatanoiseTV PicoADK v2", + "mcu": "rp2350", + "max_pin": 47, + }, + "degz_suibo": { + "name": "Degz Robotics Suibo RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "dfrobot_beetle_rp2040": { + "name": "DFRobot Beetle RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "electroniccats_huntercat_nfc": { + "name": "ElectronicCats HunterCat NFC RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "evn_alpha": { + "name": "EVN Alpha", + "mcu": "rp2040", + "max_pin": 29, + }, + "extelec_rc2040": { + "name": "ExtremeElectronics RC2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "flyboard2040_core": { + "name": "DeRuiLab FlyBoard2040Core", + "mcu": "rp2040", + "max_pin": 29, + }, + "geeekpi_rp2040_plus": { + "name": "GeeekPi RP2040 Plus", + "mcu": "rp2040", + "max_pin": 29, + }, + "generic": { + "name": "Generic RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "generic_rp2350": { + "name": "Generic RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "groundstudio_marble_pico": { + "name": "GroundStudio Marble Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "ilabs_rpico32": { + "name": "iLabs RPICO32", + "mcu": "rp2040", + "max_pin": 29, + }, + "jumperless_v1": { + "name": "Architeuthis Flux Jumperless", + "mcu": "rp2040", + "max_pin": 29, + }, + "jumperless_v5": { + "name": "Architeuthis Flux Jumperless V5", + "mcu": "rp2350", + "max_pin": 47, + }, + "melopero_cookie_rp2040": { + "name": "Melopero Cookie RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "melopero_shake_rp2040": { + "name": "Melopero Shake RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "mksthr36": { + "name": "Makerbase MKS THR36", + "mcu": "rp2040", + "max_pin": 29, + }, + "mksthr42": { + "name": "Makerbase MKS THR42", + "mcu": "rp2040", + "max_pin": 29, + }, + "nekosystems_bl2040_mini": { + "name": "Neko Systems BL2040 Mini", + "mcu": "rp2040", + "max_pin": 29, + }, + "newsan_archi": { + "name": "Newsan Archi", + "mcu": "rp2040", + "max_pin": 29, + }, + "nullbits_bit_c_pro": { + "name": "nullbits Bit-C PRO", + "mcu": "rp2040", + "max_pin": 29, + }, + "olimex_pico2bb48": { + "name": "Olimex Pico2BB48", + "mcu": "rp2350", + "max_pin": 47, + }, + "olimex_pico2xl": { + "name": "Olimex Pico2XL", + "mcu": "rp2350", + "max_pin": 47, + }, + "olimex_pico2xxl": { + "name": "Olimex Pico2XXL", + "mcu": "rp2350", + "max_pin": 47, + }, + "olimex_rp2040pico30": { + "name": "Olimex RP2040-Pico30", + "mcu": "rp2040", + "max_pin": 29, + }, + "picolume": { + "name": "PicoLume Transceiver", + "mcu": "rp2040", + "max_pin": 29, + }, + "pimoroni_explorer": { + "name": "Pimoroni Explorer", + "mcu": "rp2350", + "max_pin": 47, + }, + "pimoroni_pga2040": { + "name": "Pimoroni PGA2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "pimoroni_pga2350": { + "name": "Pimoroni PGA2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "pimoroni_pico_plus_2": { + "name": "Pimoroni PicoPlus2", + "mcu": "rp2350", + "max_pin": 47, + }, + "pimoroni_pico_plus_2w": { + "name": "Pimoroni PicoPlus2W", + "mcu": "rp2350", + "max_pin": 47, + "max_virtual_pin": 64, + }, + "pimoroni_plasma2040": { + "name": "Pimoroni Plasma2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "pimoroni_plasma2350": { + "name": "Pimoroni Plasma2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "pimoroni_plasma2350w": { + "name": "Pimoroni Plasma2350W", + "mcu": "rp2350", + "max_pin": 47, + }, + "pimoroni_servo2040": { + "name": "Pimoroni Servo2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "pimoroni_tiny2040": { + "name": "Pimoroni Tiny2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "pimoroni_tiny2350": { + "name": "Pimoroni Tiny2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "pintronix_pinmax": { + "name": "Pintronix PinMax", + "mcu": "rp2040", + "max_pin": 29, + }, + "rakwireless_rak11300": { + "name": "RAKwireless RAK11300", + "mcu": "rp2040", + "max_pin": 29, + }, + "redscorp_rp2040_eins": { + "name": "redscorp RP2040-Eins", + "mcu": "rp2040", + "max_pin": 29, + }, + "redscorp_rp2040_promini": { + "name": "redscorp RP2040-ProMini", + "mcu": "rp2040", + "max_pin": 29, + }, "rpipico": { "name": "Raspberry Pi Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "rpipico2": { + "name": "Raspberry Pi Pico 2", + "mcu": "rp2350", + "max_pin": 47, + }, + "rpipico2w": { + "name": "Raspberry Pi Pico 2W", + "mcu": "rp2350", + "max_pin": 47, + "max_virtual_pin": 64, }, "rpipicow": { "name": "Raspberry Pi Pico W", + "mcu": "rp2040", + "max_pin": 29, + "max_virtual_pin": 64, + }, + "sea_picro": { + "name": "Generic Sea-Picro", + "mcu": "rp2040", + "max_pin": 29, + }, + "seeed_indicator_rp2040": { + "name": "Seeed INDICATOR RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "seeed_xiao_rp2040": { + "name": "Seeed XIAO RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "seeed_xiao_rp2350": { + "name": "Seeed XIAO RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "silicognition_rp2040_shim": { + "name": "Silicognition RP2040-Shim", + "mcu": "rp2040", + "max_pin": 29, + }, + "soldered_nula_rp2350": { + "name": "Soldered Electronics NULA RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "solderparty_rp2040_stamp": { + "name": "Solder Party RP2040 Stamp", + "mcu": "rp2040", + "max_pin": 29, + }, + "solderparty_rp2350_stamp": { + "name": "Solder Party RP2350 Stamp", + "mcu": "rp2350", + "max_pin": 47, + }, + "solderparty_rp2350_stamp_xl": { + "name": "Solder Party RP2350 Stamp XL", + "mcu": "rp2350", + "max_pin": 47, + }, + "sparkfun_iotnode_lorawanrp2350": { + "name": "SparkFun IoT Node LoRaWAN", + "mcu": "rp2350", + "max_pin": 47, + }, + "sparkfun_iotredboard_rp2350": { + "name": "SparkFun IoT RedBoard RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "sparkfun_micromodrp2040": { + "name": "SparkFun MicroMod RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "sparkfun_promicrorp2040": { + "name": "SparkFun ProMicro RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "sparkfun_promicrorp2350": { + "name": "SparkFun ProMicro RP2350", + "mcu": "rp2350", + "max_pin": 47, + }, + "sparkfun_thingplusrp2040": { + "name": "SparkFun Thing Plus RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "sparkfun_thingplusrp2350": { + "name": "SparkFun Thing Plus RP2350", + "mcu": "rp2350", + "max_pin": 47, + "max_virtual_pin": 64, + }, + "sparkfun_xrp_controller": { + "name": "SparkFun XRP Controller", + "mcu": "rp2350", + "max_pin": 47, + "max_virtual_pin": 64, + }, + "sparkfun_xrp_controller_beta": { + "name": "SparkFun XRP Controller (Beta)", + "mcu": "rp2040", + "max_pin": 29, + "max_virtual_pin": 64, + }, + "upesy_rp2040_devkit": { + "name": "uPesy RP2040 DevKit", + "mcu": "rp2040", + "max_pin": 29, + }, + "vccgnd_yd_rp2040": { + "name": "VCC-GND YD RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "vicharak_shrike-lite": { + "name": "Vicharak Shrike-Lite", + "mcu": "rp2040", + "max_pin": 29, + }, + "viyalab_mizu": { + "name": "Viyalab Mizu RP2040", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_lcd_0_96": { + "name": "Waveshare RP2040 LCD 0.96", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_lcd_1_28": { + "name": "Waveshare RP2040 LCD 1.28", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_lora": { + "name": "Waveshare RP2040 LoRa", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_matrix": { + "name": "Waveshare RP2040 Matrix", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_one": { + "name": "Waveshare RP2040 One", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_pizero": { + "name": "Waveshare RP2040 PiZero", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_plus": { + "name": "Waveshare RP2040 Plus", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2040_zero": { + "name": "Waveshare RP2040 Zero", + "mcu": "rp2040", + "max_pin": 29, + }, + "waveshare_rp2350_lcd_0_96": { + "name": "Waveshare RP2350 LCD 0.96", + "mcu": "rp2350", + "max_pin": 47, + }, + "waveshare_rp2350_pizero": { + "name": "Waveshare RP2350 PiZero", + "mcu": "rp2350", + "max_pin": 47, + }, + "waveshare_rp2350_plus": { + "name": "Waveshare RP2350 Plus", + "mcu": "rp2350", + "max_pin": 47, + }, + "waveshare_rp2350_zero": { + "name": "Waveshare RP2350 Zero", + "mcu": "rp2350", + "max_pin": 47, + }, + "waveshare_rp2350b_plus_w": { + "name": "Waveshare RP2350B Plus W", + "mcu": "rp2350", + "max_pin": 47, + }, + "wiznet_5100s_evb_pico": { + "name": "WIZnet W5100S-EVB-Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "wiznet_5100s_evb_pico2": { + "name": "WIZnet W5100S-EVB-Pico2", + "mcu": "rp2350", + "max_pin": 47, + }, + "wiznet_5500_evb_pico": { + "name": "WIZnet W5500-EVB-Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "wiznet_5500_evb_pico2": { + "name": "WIZnet W5500-EVB-Pico2", + "mcu": "rp2350", + "max_pin": 47, + }, + "wiznet_55rp20_evb_pico": { + "name": "WIZnet W55RP20-EVB-Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "wiznet_6300_evb_pico": { + "name": "WIZnet W6300-EVB-Pico", + "mcu": "rp2040", + "max_pin": 29, + }, + "wiznet_6300_evb_pico2": { + "name": "WIZnet W6300-EVB-Pico2", + "mcu": "rp2350", + "max_pin": 47, + }, + "wiznet_wizfi360_evb_pico": { + "name": "WIZnet WizFi360-EVB-Pico", + "mcu": "rp2040", + "max_pin": 29, }, } diff --git a/esphome/components/rp2040/generate_boards.py b/esphome/components/rp2040/generate_boards.py new file mode 100644 index 0000000000..a0e3699f37 --- /dev/null +++ b/esphome/components/rp2040/generate_boards.py @@ -0,0 +1,186 @@ +"""Generate boards.py from arduino-pico board definitions. + +Usage: python esphome/components/rp2040/generate_boards.py <arduino-pico-path> +""" + +import json +from pathlib import Path +import re +import sys + +from jinja2 import Environment, FileSystemLoader + +# Map arduino-pico pin defines to ESPHome-friendly names +PIN_NAME_MAP = { + "LED": "LED", + "WIRE0_SDA": "SDA", + "WIRE0_SCL": "SCL", + "WIRE1_SDA": "SDA1", + "WIRE1_SCL": "SCL1", + "SPI0_MISO": "MISO", + "SPI0_MOSI": "MOSI", + "SPI0_SCK": "SCK", + "SPI0_SS": "SS", + "SERIAL1_TX": "TX", + "SERIAL1_RX": "RX", +} + +# arduino-pico maps pins >= 64 to CYW43 wireless chip GPIOs (pin - 64) +CYW43_GPIO_OFFSET = 64 +# CYW43 has 3 GPIOs: 0=LED, 1=VBUS_SENSE, 2=REG_ON +CYW43_GPIO_COUNT = 3 + +# Max GPIO pin per MCU (hardware specs from datasheets) +MCU_MAX_PIN = { + "rp2040": 29, # GPIO 0-29 + "rp2350": 47, # GPIO 0-47 (RP2350A) +} +DEFAULT_MAX_PIN = 29 + +PIN_DEFINE_RE = re.compile(r"#define\s+PIN_(\w+)\s+\((\d+)u\)") + + +def parse_variant_pins(variant_dir: Path) -> dict[str, int]: + """Parse pins_arduino.h and return mapped pin names.""" + header = variant_dir / "pins_arduino.h" + if not header.exists(): + return {} + + pins = {} + for match in PIN_DEFINE_RE.finditer(header.read_text(encoding="utf-8")): + raw_name = match.group(1) + value = int(match.group(2)) + if raw_name in PIN_NAME_MAP: + pins[PIN_NAME_MAP[raw_name]] = value + return pins + + +def load_boards(arduino_pico_path: Path) -> tuple[dict, dict]: + """Load all board definitions and return (board_pins, boards) dicts.""" + json_dir = arduino_pico_path / "tools" / "json" + variants_dir = arduino_pico_path / "variants" + + board_pins = {} + boards = {} + variant_pins_cache: dict[str, dict[str, int]] = {} + + for json_file in sorted(json_dir.glob("*.json")): + board_name = json_file.stem + with open(json_file, encoding="utf-8") as f: + data = json.load(f) + + build = data.get("build", {}) + mcu = build.get("mcu", "rp2040") + variant = build.get("variant", board_name) + name = data.get("name", board_name) + vendor = data.get("vendor", "") + + display_name = f"{vendor} {name}".strip() if vendor else name + + boards[board_name] = { + "name": display_name, + "mcu": mcu, + "max_pin": MCU_MAX_PIN.get(mcu, DEFAULT_MAX_PIN), + } + + # Get pins for this variant + if variant not in variant_pins_cache: + variant_dir = variants_dir / variant + variant_pins_cache[variant] = parse_variant_pins(variant_dir) + + pins = variant_pins_cache[variant] + if pins: + max_pin = boards[board_name]["max_pin"] + cyw43_max = CYW43_GPIO_OFFSET + CYW43_GPIO_COUNT - 1 + # Filter out placeholder values (e.g. 99 = "not connected") + filtered = { + name: value + for name, value in pins.items() + if value <= max_pin or CYW43_GPIO_OFFSET <= value <= cyw43_max + } + if filtered: + board_pins[board_name] = filtered + + # Compute max_virtual_pin per board from pin maps + for board_name, pins in board_pins.items(): + if isinstance(pins, str): + continue + virtual_pins = [v for v in pins.values() if v >= CYW43_GPIO_OFFSET] + if virtual_pins and board_name in boards: + boards[board_name]["max_virtual_pin"] = max(virtual_pins) + + # Deduplicate: if board pins match its variant's pins, use string alias + for board_name in list(board_pins.keys()): + if board_name not in boards: + continue + build_variant = _get_variant(json_dir / f"{board_name}.json") + if ( + build_variant + and build_variant != board_name + and build_variant in board_pins + and board_pins[board_name] == board_pins[build_variant] + ): + board_pins[board_name] = build_variant + + return board_pins, boards + + +def _get_variant(json_file: Path) -> str | None: + """Get variant name from a board JSON file.""" + if not json_file.exists(): + return None + with open(json_file, encoding="utf-8") as f: + data = json.load(f) + return data.get("build", {}).get("variant") + + +_TEMPLATE_DIR = Path(__file__).parent + + +def _format_pins(pins: dict[str, int] | str) -> str: + """Jinja2 filter to format a pin dict or alias as Python source.""" + if isinstance(pins, str): + return repr(pins) + items = ", ".join(f"{k!r}: {v}" for k, v in sorted(pins.items())) + return f"{{{items}}}" + + +_jinja_env = Environment( + loader=FileSystemLoader(_TEMPLATE_DIR), keep_trailing_newline=True +) +_jinja_env.filters["format_pins"] = _format_pins +_jinja_env.filters["repr"] = repr + + +def generate(arduino_pico_path: Path) -> str: + """Generate boards.py content.""" + board_pins, boards = load_boards(arduino_pico_path) + + template = _jinja_env.get_template("boards.jinja2") + return template.render( + cyw43_gpio_offset=CYW43_GPIO_OFFSET, + cyw43_max_gpio=CYW43_GPIO_OFFSET + CYW43_GPIO_COUNT - 1, + default_max_pin=DEFAULT_MAX_PIN, + board_pins=sorted(board_pins.items()), + boards=sorted(boards.items()), + ) + + +def main(): + if len(sys.argv) < 2: + print(f"Usage: {sys.argv[0]} <arduino-pico-path>", file=sys.stderr) + sys.exit(1) + + arduino_pico_path = Path(sys.argv[1]) + if not (arduino_pico_path / "tools" / "json").exists(): + print(f"Error: {arduino_pico_path}/tools/json not found", file=sys.stderr) + sys.exit(1) + + output = generate(arduino_pico_path) + output_file = Path(__file__).parent / "boards.py" + output_file.write_text(output, encoding="utf-8") + print(f"Generated {output_file}") + + +if __name__ == "__main__": + main() diff --git a/esphome/components/rp2040/gpio.py b/esphome/components/rp2040/gpio.py index 193e567d17..18fb09f76a 100644 --- a/esphome/components/rp2040/gpio.py +++ b/esphome/components/rp2040/gpio.py @@ -54,19 +54,29 @@ def _translate_pin(value): return _lookup_pin(value) +def _board_max_virtual_pin(board): + """Get the max CYW43 virtual pin for this board, or None if no virtual pins.""" + return boards.BOARDS.get(board, {}).get("max_virtual_pin") + + def validate_gpio_pin(value): value = _translate_pin(value) board = CORE.data[KEY_RP2040][KEY_BOARD] - if board == "rpipicow" and value == 32: - return value # Special case for Pico-w LED pin - if value < 0 or value > 29: - raise cv.Invalid(f"RP2040: Invalid pin number: {value}") + max_virtual = _board_max_virtual_pin(board) + if max_virtual is not None and boards.CYW43_GPIO_OFFSET <= value <= max_virtual: + return value + max_pin = boards.BOARDS.get(board, {}).get("max_pin", boards.DEFAULT_MAX_PIN) + if value < 0 or value > max_pin: + raise cv.Invalid(f"Invalid pin number: {value} (max {max_pin} for this board)") return value def validate_supports(value): board = CORE.data[KEY_RP2040][KEY_BOARD] - if board != "rpipicow" or value[CONF_NUMBER] != 32: + if ( + _board_max_virtual_pin(board) is None + or value[CONF_NUMBER] < boards.CYW43_GPIO_OFFSET + ): return value mode = value[CONF_MODE] is_input = mode[CONF_INPUT] @@ -75,7 +85,7 @@ def validate_supports(value): is_pullup = mode[CONF_PULLUP] is_pulldown = mode[CONF_PULLDOWN] if not is_output or is_input or is_open_drain or is_pullup or is_pulldown: - raise cv.Invalid("Only output mode is supported for Pico-w LED pin") + raise cv.Invalid("Only output mode is supported for CYW43 virtual pins") return value diff --git a/tests/unit_tests/components/test_rp2040_generate_boards.py b/tests/unit_tests/components/test_rp2040_generate_boards.py new file mode 100644 index 0000000000..2e40ed08ba --- /dev/null +++ b/tests/unit_tests/components/test_rp2040_generate_boards.py @@ -0,0 +1,273 @@ +"""Tests for rp2040 generate_boards.py.""" + +from __future__ import annotations + +import json +from pathlib import Path +import textwrap + +import pytest + +from esphome.components.rp2040.generate_boards import load_boards, parse_variant_pins + +PICO_PINS_HEADER = textwrap.dedent("""\ + #pragma once + #define PIN_LED (25u) + #define PIN_SERIAL1_TX (0u) + #define PIN_SERIAL1_RX (1u) + #define PIN_WIRE0_SDA (4u) + #define PIN_WIRE0_SCL (5u) + #define PIN_WIRE1_SDA (26u) + #define PIN_WIRE1_SCL (27u) + #define PIN_SPI0_MISO (16u) + #define PIN_SPI0_MOSI (19u) + #define PIN_SPI0_SCK (18u) + #define PIN_SPI0_SS (17u) + #include "../generic/common.h" +""") + +PICOW_PINS_HEADER = textwrap.dedent("""\ + #pragma once + #include <cyw43_wrappers.h> + #define PIN_LED (64u) + #define PIN_WIRE0_SDA (4u) + #define PIN_WIRE0_SCL (5u) + #include "../generic/common.h" +""") + + +@pytest.fixture() +def arduino_pico(tmp_path: Path) -> Path: + """Create a minimal arduino-pico directory structure.""" + json_dir = tmp_path / "tools" / "json" + json_dir.mkdir(parents=True) + variants_dir = tmp_path / "variants" + variants_dir.mkdir() + + generic_dir = variants_dir / "generic" + generic_dir.mkdir() + (generic_dir / "common.h").write_text("#pragma once\n") + + return tmp_path + + +def _add_board( + arduino_pico: Path, + board_name: str, + mcu: str = "rp2040", + variant: str | None = None, + vendor: str = "", + name: str | None = None, + pins_header: str | None = None, +) -> None: + """Add a board JSON and variant to the fake arduino-pico tree.""" + if variant is None: + variant = board_name + if name is None: + name = board_name + + json_dir = arduino_pico / "tools" / "json" + variants_dir = arduino_pico / "variants" + + board_json = { + "build": { + "mcu": mcu, + "variant": variant, + }, + "name": name, + "vendor": vendor, + } + (json_dir / f"{board_name}.json").write_text(json.dumps(board_json)) + + variant_dir = variants_dir / variant + variant_dir.mkdir(exist_ok=True) + if pins_header is not None: + (variant_dir / "pins_arduino.h").write_text(pins_header) + + +def test_parse_basic_pins(tmp_path: Path) -> None: + variant_dir = tmp_path / "rpipico" + variant_dir.mkdir() + (variant_dir / "pins_arduino.h").write_text(PICO_PINS_HEADER) + + pins = parse_variant_pins(variant_dir) + assert pins["LED"] == 25 + assert pins["SDA"] == 4 + assert pins["SCL"] == 5 + assert pins["SDA1"] == 26 + assert pins["SCL1"] == 27 + assert pins["MISO"] == 16 + assert pins["MOSI"] == 19 + assert pins["SCK"] == 18 + assert pins["SS"] == 17 + assert pins["TX"] == 0 + assert pins["RX"] == 1 + + +def test_parse_cyw43_led_pin(tmp_path: Path) -> None: + variant_dir = tmp_path / "rpipicow" + variant_dir.mkdir() + (variant_dir / "pins_arduino.h").write_text(PICOW_PINS_HEADER) + + pins = parse_variant_pins(variant_dir) + assert pins["LED"] == 64 + + +def test_parse_missing_header(tmp_path: Path) -> None: + variant_dir = tmp_path / "noheader" + variant_dir.mkdir() + assert parse_variant_pins(variant_dir) == {} + + +def test_parse_unmapped_defines_ignored(tmp_path: Path) -> None: + variant_dir = tmp_path / "custom" + variant_dir.mkdir() + (variant_dir / "pins_arduino.h").write_text( + "#define PIN_NEOPIXEL (16u)\n#define PIN_LED (25u)\n" + ) + + pins = parse_variant_pins(variant_dir) + assert "NEOPIXEL" not in pins + assert pins["LED"] == 25 + + +def test_load_basic_board(arduino_pico: Path) -> None: + _add_board( + arduino_pico, + "rpipico", + vendor="Raspberry Pi", + name="Pico", + pins_header=PICO_PINS_HEADER, + ) + + board_pins, boards = load_boards(arduino_pico) + + assert "rpipico" in boards + assert boards["rpipico"]["name"] == "Raspberry Pi Pico" + assert boards["rpipico"]["mcu"] == "rp2040" + assert boards["rpipico"]["max_pin"] == 29 + + assert "rpipico" in board_pins + assert board_pins["rpipico"]["LED"] == 25 + assert board_pins["rpipico"]["SDA"] == 4 + + +def test_load_rp2350_board(arduino_pico: Path) -> None: + _add_board( + arduino_pico, + "rpipico2", + mcu="rp2350", + vendor="Raspberry Pi", + name="Pico 2", + pins_header=PICO_PINS_HEADER, + ) + + _, boards = load_boards(arduino_pico) + + assert boards["rpipico2"]["mcu"] == "rp2350" + assert boards["rpipico2"]["max_pin"] == 47 + + +def test_cyw43_board_has_max_virtual_pin(arduino_pico: Path) -> None: + _add_board( + arduino_pico, + "rpipicow", + vendor="Raspberry Pi", + name="Pico W", + pins_header=PICOW_PINS_HEADER, + ) + + _, boards = load_boards(arduino_pico) + + assert boards["rpipicow"]["max_virtual_pin"] == 64 + + +def test_non_cyw43_board_has_no_max_virtual_pin(arduino_pico: Path) -> None: + _add_board( + arduino_pico, + "rpipico", + vendor="Raspberry Pi", + name="Pico", + pins_header=PICO_PINS_HEADER, + ) + + _, boards = load_boards(arduino_pico) + + assert "max_virtual_pin" not in boards["rpipico"] + + +def test_board_without_variant_header(arduino_pico: Path) -> None: + _add_board(arduino_pico, "novariant", name="No Variant") + + board_pins, boards = load_boards(arduino_pico) + + assert "novariant" in boards + assert "novariant" not in board_pins + + +def test_shared_variant_deduplicates(arduino_pico: Path) -> None: + """Two boards sharing the same variant should alias.""" + _add_board(arduino_pico, "base_board", pins_header=PICO_PINS_HEADER) + _add_board(arduino_pico, "alias_board", variant="base_board") + + board_pins, _ = load_boards(arduino_pico) + + assert board_pins["base_board"] == parse_variant_pins( + arduino_pico / "variants" / "base_board" + ) + assert board_pins["alias_board"] == "base_board" + + +def test_display_name_with_vendor(arduino_pico: Path) -> None: + _add_board(arduino_pico, "testboard", vendor="Acme", name="Widget") + _, boards = load_boards(arduino_pico) + assert boards["testboard"]["name"] == "Acme Widget" + + +def test_display_name_without_vendor(arduino_pico: Path) -> None: + _add_board(arduino_pico, "testboard", vendor="", name="Widget") + _, boards = load_boards(arduino_pico) + assert boards["testboard"]["name"] == "Widget" + + +def test_unknown_mcu_gets_default_max_pin(arduino_pico: Path) -> None: + _add_board(arduino_pico, "future", mcu="rp2450", pins_header=PICO_PINS_HEADER) + _, boards = load_boards(arduino_pico) + assert boards["future"]["max_pin"] == 29 + + +def test_placeholder_pins_filtered_out(arduino_pico: Path) -> None: + """Pins with placeholder values like 99 should be filtered out.""" + header = textwrap.dedent("""\ + #pragma once + #define PIN_LED (25u) + #define PIN_WIRE0_SDA (4u) + #define PIN_WIRE0_SCL (5u) + #define PIN_WIRE1_SDA (99u) + #define PIN_WIRE1_SCL (99u) + """) + _add_board(arduino_pico, "placeholder", pins_header=header) + + board_pins, boards = load_boards(arduino_pico) + + assert "SDA1" not in board_pins["placeholder"] + assert "SCL1" not in board_pins["placeholder"] + assert board_pins["placeholder"]["LED"] == 25 + assert "max_virtual_pin" not in boards["placeholder"] + + +def test_placeholder_pins_not_treated_as_virtual(arduino_pico: Path) -> None: + """Pin 99 should not cause max_virtual_pin to be set.""" + header = textwrap.dedent("""\ + #pragma once + #define PIN_LED (64u) + #define PIN_WIRE0_SDA (4u) + #define PIN_WIRE0_SCL (5u) + #define PIN_SPI0_MISO (99u) + """) + _add_board(arduino_pico, "badpin", pins_header=header) + + board_pins, boards = load_boards(arduino_pico) + + assert "MISO" not in board_pins["badpin"] + assert boards["badpin"]["max_virtual_pin"] == 64 From 82629c397f699af8b263e66e7cc904bebcc297d5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 07:01:50 -1000 Subject: [PATCH 1154/2030] [hlk_fm22x] Fix oversized response rejection breaking GET_ALL_FACE_IDS (#14506) --- esphome/components/hlk_fm22x/hlk_fm22x.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.cpp b/esphome/components/hlk_fm22x/hlk_fm22x.cpp index 18d26f057a..7c7c8782de 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.cpp +++ b/esphome/components/hlk_fm22x/hlk_fm22x.cpp @@ -133,24 +133,22 @@ void HlkFm22xComponent::recv_command_() { checksum ^= byte; length |= byte; - if (length > HLK_FM22X_MAX_RESPONSE_SIZE) { - ESP_LOGE(TAG, "Response too large: %u bytes", length); - // Discard exactly the remaining payload and checksum for this frame - for (uint16_t i = 0; i < length + 1 && this->available() > 0; ++i) - this->read(); - return; - } - + // Read up to buffer size; discard excess bytes while still computing checksum + // GET_ALL_FACE_IDS can return all enrolled face data (hundreds of bytes) + // but handlers only need the first few bytes + size_t to_store = std::min(static_cast<size_t>(length), HLK_FM22X_MAX_RESPONSE_SIZE); for (uint16_t idx = 0; idx < length; ++idx) { byte = this->read(); checksum ^= byte; - this->recv_buf_[idx] = byte; + if (idx < to_store) { + this->recv_buf_[idx] = byte; + } } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(HLK_FM22X_MAX_RESPONSE_SIZE)]; ESP_LOGV(TAG, "Recv type: 0x%.2X, data: %s", response_type, - format_hex_pretty_to(hex_buf, this->recv_buf_.data(), length)); + format_hex_pretty_to(hex_buf, this->recv_buf_.data(), to_store)); #endif byte = this->read(); @@ -160,10 +158,10 @@ void HlkFm22xComponent::recv_command_() { } switch (response_type) { case HlkFm22xResponseType::NOTE: - this->handle_note_(this->recv_buf_.data(), length); + this->handle_note_(this->recv_buf_.data(), to_store); break; case HlkFm22xResponseType::REPLY: - this->handle_reply_(this->recv_buf_.data(), length); + this->handle_reply_(this->recv_buf_.data(), to_store); break; default: ESP_LOGW(TAG, "Unexpected response type: 0x%.2X", response_type); From 6e3bc7b1ddb5b8ac91ecf0653087dc835264ca8c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 07:33:05 -1000 Subject: [PATCH 1155/2030] [ci] Use pull_request_target for codeowner approved label workflow (#14561) --- .github/scripts/codeowners.js | 2 +- .../codeowner-approved-label-update.yml | 63 +++++---------- .../workflows/codeowner-approved-label.yml | 78 ------------------- 3 files changed, 21 insertions(+), 122 deletions(-) delete mode 100644 .github/workflows/codeowner-approved-label.yml diff --git a/.github/scripts/codeowners.js b/.github/scripts/codeowners.js index 5d69c11b1a..9b2f2922c0 100644 --- a/.github/scripts/codeowners.js +++ b/.github/scripts/codeowners.js @@ -2,7 +2,7 @@ // // Used by: // - codeowner-review-request.yml -// - codeowner-approved-label.yml + codeowner-approved-label-update.yml +// - codeowner-approved-label-update.yml // - auto-label-pr/detectors.js (detectCodeOwner) /** diff --git a/.github/workflows/codeowner-approved-label-update.yml b/.github/workflows/codeowner-approved-label-update.yml index 9168cce1d6..c2eb886913 100644 --- a/.github/workflows/codeowner-approved-label-update.yml +++ b/.github/workflows/codeowner-approved-label-update.yml @@ -1,13 +1,15 @@ -# Fallback for fork PRs: phase 1 (codeowner-approved-label.yml) handles -# non-fork PRs directly but can't write labels on fork PRs (read-only token). -# This workflow re-determines the action and applies it if needed. +# Adds/removes a 'code-owner-approved' label when a component-specific +# codeowner approves (or dismisses) a PR. +# +# Uses pull_request_target so that fork PRs do not require workflow approval. +# The label is reconciled on every PR update; for review events specifically, +# this means the label is applied on the next push after a codeowner review. -name: Codeowner Approved Label Update +name: Codeowner Approved Label on: - workflow_run: - workflows: ["Codeowner Approved Label"] - types: [completed] + pull_request_target: + types: [opened, synchronize, reopened, ready_for_review] permissions: issues: write @@ -15,51 +17,23 @@ permissions: contents: read jobs: - update-label: + codeowner-approved: name: Run - if: > - github.event.workflow_run.conclusion == 'success' && - github.event.workflow_run.event == 'pull_request_review' + if: ${{ github.repository == 'esphome/esphome' }} runs-on: ubuntu-latest steps: - - name: Get PR details - id: pr - env: - GH_TOKEN: ${{ github.token }} - HEAD_SHA: ${{ github.event.workflow_run.head_sha }} - REPO: ${{ github.repository }} - run: | - pr_data=$(gh pr list --repo "$REPO" --state open --search "$HEAD_SHA" \ - --json number,baseRefName --jq '.[0] // empty') - - if [ -z "$pr_data" ]; then - echo "No open PR found for SHA $HEAD_SHA, skipping" - echo "skip=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - - pr_number=$(echo "$pr_data" | jq -r '.number') - base_ref=$(echo "$pr_data" | jq -r '.baseRefName') - - echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" - echo "base_ref=$base_ref" >> "$GITHUB_OUTPUT" - echo "Found PR #$pr_number targeting $base_ref" - - - name: Checkout base repository - if: steps.pr.outputs.skip != 'true' + - name: Checkout base branch uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - repository: ${{ github.repository }} - ref: ${{ steps.pr.outputs.base_ref }} + ref: ${{ github.event.pull_request.base.sha }} sparse-checkout: | .github/scripts/codeowners.js CODEOWNERS - - name: Update label - if: steps.pr.outputs.skip != 'true' + - name: Check codeowner approval and update label uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: - PR_NUMBER: ${{ steps.pr.outputs.pr_number }} + PR_NUMBER: ${{ github.event.pull_request.number }} with: script: | const { loadCodeowners, determineLabelAction, LabelAction } = require('./.github/scripts/codeowners.js'); @@ -76,6 +50,11 @@ jobs: github, owner, repo, pr_number, codeownersPatterns, LABEL_NAME ); + if (action === LabelAction.NONE) { + console.log('No label change needed'); + return; + } + if (action === LabelAction.ADD) { await github.rest.issues.addLabels({ owner, repo, issue_number: pr_number, labels: [LABEL_NAME] @@ -90,6 +69,4 @@ jobs: } catch (error) { if (error.status !== 404) throw error; } - } else { - console.log('No label change needed'); } diff --git a/.github/workflows/codeowner-approved-label.yml b/.github/workflows/codeowner-approved-label.yml deleted file mode 100644 index 12199bd0b0..0000000000 --- a/.github/workflows/codeowner-approved-label.yml +++ /dev/null @@ -1,78 +0,0 @@ -# Adds/removes a 'code-owner-approved' label when a component-specific -# codeowner approves (or dismisses) a PR. -# -# Handles non-fork PRs directly. For fork PRs the GITHUB_TOKEN is read-only, -# so label writes are deferred to codeowner-approved-label-update.yml which -# triggers via workflow_run with write permissions. - -name: Codeowner Approved Label - -on: - pull_request_review: - types: [submitted, dismissed] - -permissions: - issues: write - pull-requests: read - contents: read - -jobs: - codeowner-approved: - name: Run - if: ${{ github.repository == 'esphome/esphome' }} - runs-on: ubuntu-latest - steps: - - name: Checkout base branch - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - ref: ${{ github.event.pull_request.base.sha }} - sparse-checkout: | - .github/scripts/codeowners.js - CODEOWNERS - - - name: Check codeowner approval and update label - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - env: - PR_NUMBER: ${{ github.event.pull_request.number }} - with: - script: | - const { loadCodeowners, determineLabelAction, LabelAction } = require('./.github/scripts/codeowners.js'); - - const owner = context.repo.owner; - const repo = context.repo.repo; - const pr_number = parseInt(process.env.PR_NUMBER, 10); - const LABEL_NAME = 'code-owner-approved'; - - console.log(`Processing PR #${pr_number} for codeowner approval label`); - - const codeownersPatterns = loadCodeowners(); - const action = await determineLabelAction( - github, owner, repo, pr_number, codeownersPatterns, LABEL_NAME - ); - - if (action === LabelAction.NONE) { - console.log('No label change needed'); - return; - } - - try { - if (action === LabelAction.ADD) { - await github.rest.issues.addLabels({ - owner, repo, issue_number: pr_number, labels: [LABEL_NAME] - }); - console.log(`Added '${LABEL_NAME}' label`); - } else if (action === LabelAction.REMOVE) { - await github.rest.issues.removeLabel({ - owner, repo, issue_number: pr_number, name: LABEL_NAME - }); - console.log(`Removed '${LABEL_NAME}' label`); - } - } catch (error) { - if (error.status === 403) { - console.log('Fork PR: deferring label write to phase 2 workflow'); - } else if (error.status === 404) { - console.log('Label already removed'); - } else { - throw error; - } - } From 65b7c73bf3fdbbe9260040b96e758561dc9be548 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 08:02:34 -1000 Subject: [PATCH 1156/2030] [sgp4x] Fix undefined behavior from mutating entity config at runtime (#14562) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/sgp4x/sgp4x.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/esphome/components/sgp4x/sgp4x.cpp b/esphome/components/sgp4x/sgp4x.cpp index 23589265ca..44d0a54080 100644 --- a/esphome/components/sgp4x/sgp4x.cpp +++ b/esphome/components/sgp4x/sgp4x.cpp @@ -35,13 +35,9 @@ void SGP4xComponent::setup() { this->self_test_time_ = SPG40_SELFTEST_TIME; this->measure_time_ = SGP40_MEASURE_TIME; if (this->nox_sensor_) { - ESP_LOGE(TAG, "SGP41 required for NOx"); - // disable the sensor - this->nox_sensor_->set_disabled_by_default(true); - // make sure it's not visible in HA - this->nox_sensor_->set_internal(true); - this->nox_sensor_->state = NAN; - // remove pointer to sensor + ESP_LOGE(TAG, "SGP41 required for NOx, disabling NOx sensor"); + // Drop the pointer so update() never publishes to it. + // The entity remains registered but will never receive state updates. this->nox_sensor_ = nullptr; } } else if (featureset == SGP41_FEATURESET) { From b2378e830e947ecc8d79f197abf838868927053e Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Fri, 6 Mar 2026 19:11:52 +0100 Subject: [PATCH 1157/2030] [rtttl] Add AudioStreamInfo and set volume (#14439) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/rtttl/rtttl.cpp | 40 ++++++++++-------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 4ccfc539ea..9bf0450993 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -29,11 +29,6 @@ static constexpr uint8_t REPEATING_NOTE_GAP_MS = 10; static constexpr uint16_t SAMPLE_BUFFER_SIZE = 2048; static constexpr uint16_t SAMPLE_RATE = 16000; -struct SpeakerSample { - int8_t left{0}; - int8_t right{0}; -}; - inline double deg2rad(double degrees) { static constexpr double PI_ON_180 = M_PI / 180.0; return degrees * PI_ON_180; @@ -108,6 +103,9 @@ void Rtttl::loop() { } } else if (this->state_ == State::INIT) { if (this->speaker_->is_stopped()) { + audio::AudioStreamInfo audio_stream_info = audio::AudioStreamInfo(16, 1, SAMPLE_RATE); + this->speaker_->set_audio_stream_info(audio_stream_info); + this->speaker_->set_volume(this->gain_); this->speaker_->start(); this->set_state_(State::STARTING); } @@ -120,35 +118,27 @@ void Rtttl::loop() { return; } if (this->samples_sent_ != this->samples_count_) { - SpeakerSample sample[SAMPLE_BUFFER_SIZE + 2]; + int16_t sample[SAMPLE_BUFFER_SIZE]; uint16_t sample_index = 0; double rem = 0.0; - while (true) { + while (sample_index < SAMPLE_BUFFER_SIZE && this->samples_sent_ < this->samples_count_) { // Try and send out the remainder of the existing note, one per `loop()` if (this->samples_per_wave_ != 0 && this->samples_sent_ >= this->samples_gap_) { // Play note rem = ((this->samples_sent_ << 10) % this->samples_per_wave_) * (360.0 / this->samples_per_wave_); - - int8_t val = (127 * this->gain_) * sin(deg2rad(rem)); - - sample[sample_index].left = val; - sample[sample_index].right = val; + sample[sample_index] = INT16_MAX * sin(deg2rad(rem)); } else { - sample[sample_index].left = 0; - sample[sample_index].right = 0; - } - - if (sample_index >= SAMPLE_BUFFER_SIZE || this->samples_sent_ >= this->samples_count_) { - break; + sample[sample_index] = 0; } this->samples_sent_++; sample_index++; } if (sample_index > 0) { - size_t bytes_to_send = sample_index * sizeof(SpeakerSample); - size_t send = this->speaker_->play((uint8_t *) (&sample), bytes_to_send); - if (send != bytes_to_send) { - this->samples_sent_ -= (sample_index - (send / sizeof(SpeakerSample))); + size_t bytes = sample_index * sizeof(int16_t); + size_t sent_bytes = this->speaker_->play((uint8_t *) (&sample), bytes); + size_t samples_sent = sent_bytes / sizeof(int16_t); + if (samples_sent != sample_index) { + this->samples_sent_ -= (sample_index - samples_sent); } return; } @@ -408,11 +398,7 @@ void Rtttl::finish_() { #ifdef USE_SPEAKER if (this->speaker_ != nullptr) { - SpeakerSample sample[2]; - sample[0].left = 0; - sample[0].right = 0; - sample[1].left = 0; - sample[1].right = 0; + int16_t sample[2] = {0, 0}; this->speaker_->play((uint8_t *) (&sample), sizeof(sample)); this->speaker_->finish(); this->set_state_(State::STOPPING); From 8a915dcbbed3af2e285dce91f32c03743310ca21 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 08:34:27 -1000 Subject: [PATCH 1158/2030] [core] Move device class strings to PROGMEM on ESP8266 (#14443) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_connection.cpp | 84 ++++++++++++++----- esphome/components/api/api_connection.h | 34 ++------ .../components/mqtt/mqtt_binary_sensor.cpp | 6 +- esphome/components/mqtt/mqtt_button.cpp | 6 -- esphome/components/mqtt/mqtt_component.cpp | 5 ++ esphome/components/mqtt/mqtt_cover.cpp | 7 +- esphome/components/mqtt/mqtt_event.cpp | 7 -- esphome/components/mqtt/mqtt_number.cpp | 4 - esphome/components/mqtt/mqtt_sensor.cpp | 5 -- esphome/components/mqtt/mqtt_text_sensor.cpp | 6 -- esphome/components/mqtt/mqtt_valve.cpp | 7 +- esphome/components/web_server/web_server.cpp | 3 +- esphome/core/config.py | 6 ++ esphome/core/entity_base.cpp | 37 +++++++- esphome/core/entity_base.h | 33 ++++++-- esphome/core/entity_helpers.py | 8 +- tests/unit_tests/core/test_entity_helpers.py | 17 ++++ 17 files changed, 167 insertions(+), 108 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 98ba1abe0b..77920432c0 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -396,6 +396,48 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t mess return static_cast<uint16_t>(header_padding + calculated_size + footer_size); } +uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, + uint8_t message_type, APIConnection *conn, + uint32_t remaining_size) { + // Set common fields that are shared by all entity types + msg.key = entity->get_object_id_hash(); + + // API 1.14+ clients compute object_id client-side from the entity name + // For older clients, we must send object_id for backward compatibility + // See: https://github.com/esphome/backlog/issues/76 + // TODO: Remove this backward compat code before 2026.7.0 - all clients should support API 1.14 by then + // Buffer must remain in scope until encode_message_to_buffer is called + char object_id_buf[OBJECT_ID_MAX_LEN]; + if (!conn->client_supports_api_version(1, 14)) { + msg.object_id = entity->get_object_id_to(object_id_buf); + } + + if (entity->has_own_name()) { + msg.name = entity->get_name(); + } + + // Set common EntityBase properties +#ifdef USE_ENTITY_ICON + char icon_buf[MAX_ICON_LENGTH]; + msg.icon = StringRef(entity->get_icon_to(icon_buf)); +#endif + msg.disabled_by_default = entity->is_disabled_by_default(); + msg.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category()); +#ifdef USE_DEVICES + msg.device_id = entity->get_device_id(); +#endif + return encode_message_to_buffer(msg, message_type, conn, remaining_size); +} + +uint16_t APIConnection::fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg, + StringRef &device_class_field, + uint8_t message_type, APIConnection *conn, + uint32_t remaining_size) { + char dc_buf[MAX_DEVICE_CLASS_LENGTH]; + device_class_field = StringRef(entity->get_device_class_to(dc_buf)); + return fill_and_encode_entity_info(entity, msg, message_type, conn, remaining_size); +} + #ifdef USE_BINARY_SENSOR bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) { return this->send_message_smart_(binary_sensor, BinarySensorStateResponse::MESSAGE_TYPE, @@ -414,10 +456,9 @@ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConn uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); ListEntitiesBinarySensorResponse msg; - msg.device_class = binary_sensor->get_device_class_ref(); msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor(); - return fill_and_encode_entity_info(binary_sensor, msg, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, - remaining_size); + return fill_and_encode_entity_info_with_device_class( + binary_sensor, msg, msg.device_class, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -443,8 +484,8 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c msg.supports_position = traits.get_supports_position(); msg.supports_tilt = traits.get_supports_tilt(); msg.supports_stop = traits.get_supports_stop(); - msg.device_class = cover->get_device_class_ref(); - return fill_and_encode_entity_info(cover, msg, ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class, + ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover) @@ -609,9 +650,9 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection * msg.unit_of_measurement = sensor->get_unit_of_measurement_ref(); msg.accuracy_decimals = sensor->get_accuracy_decimals(); msg.force_update = sensor->get_force_update(); - msg.device_class = sensor->get_device_class_ref(); msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class()); - return fill_and_encode_entity_info(sensor, msg, ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class, + ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -631,8 +672,8 @@ uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection * auto *a_switch = static_cast<switch_::Switch *>(entity); ListEntitiesSwitchResponse msg; msg.assumed_state = a_switch->assumed_state(); - msg.device_class = a_switch->get_device_class_ref(); - return fill_and_encode_entity_info(a_switch, msg, ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class, + ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::on_switch_command_request(const SwitchCommandRequest &msg) { ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch) @@ -661,9 +702,8 @@ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnec uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); ListEntitiesTextSensorResponse msg; - msg.device_class = text_sensor->get_device_class_ref(); - return fill_and_encode_entity_info(text_sensor, msg, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, - remaining_size); + return fill_and_encode_entity_info_with_device_class( + text_sensor, msg, msg.device_class, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -776,11 +816,11 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection * ListEntitiesNumberResponse msg; msg.unit_of_measurement = number->get_unit_of_measurement_ref(); msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode()); - msg.device_class = number->get_device_class_ref(); msg.min_value = number->traits.get_min_value(); msg.max_value = number->traits.get_max_value(); msg.step = number->traits.get_step(); - return fill_and_encode_entity_info(number, msg, ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class, + ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::on_number_command_request(const NumberCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(number::Number, number, number) @@ -925,8 +965,8 @@ void APIConnection::on_select_command_request(const SelectCommandRequest &msg) { uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *button = static_cast<button::Button *>(entity); ListEntitiesButtonResponse msg; - msg.device_class = button->get_device_class_ref(); - return fill_and_encode_entity_info(button, msg, ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class, + ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size); } void esphome::api::APIConnection::on_button_command_request(const ButtonCommandRequest &msg) { ENTITY_COMMAND_GET(button::Button, button, button) @@ -986,11 +1026,11 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c auto *valve = static_cast<valve::Valve *>(entity); ListEntitiesValveResponse msg; auto traits = valve->get_traits(); - msg.device_class = valve->get_device_class_ref(); msg.assumed_state = traits.get_is_assumed_state(); msg.supports_position = traits.get_supports_position(); msg.supports_stop = traits.get_supports_stop(); - return fill_and_encode_entity_info(valve, msg, ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class, + ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::on_valve_command_request(const ValveCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve) @@ -1434,9 +1474,9 @@ uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef e uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *event = static_cast<event::Event *>(entity); ListEntitiesEventResponse msg; - msg.device_class = event->get_device_class_ref(); msg.event_types = &event->get_event_types(); - return fill_and_encode_entity_info(event, msg, ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class, + ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size); } #endif @@ -1492,8 +1532,8 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *update = static_cast<update::UpdateEntity *>(entity); ListEntitiesUpdateResponse msg; - msg.device_class = update->get_device_class_ref(); - return fill_and_encode_entity_info(update, msg, ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class, + ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size); } void APIConnection::on_update_command_request(const UpdateCommandRequest &msg) { ENTITY_COMMAND_GET(update::UpdateEntity, update, update) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 88f0ef82d6..2c66a194a6 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -334,36 +334,12 @@ class APIConnection final : public APIServerConnectionBase { // Helper to fill entity info base and encode message static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size) { - // Set common fields that are shared by all entity types - msg.key = entity->get_object_id_hash(); + APIConnection *conn, uint32_t remaining_size); - // API 1.14+ clients compute object_id client-side from the entity name - // For older clients, we must send object_id for backward compatibility - // See: https://github.com/esphome/backlog/issues/76 - // TODO: Remove this backward compat code before 2026.7.0 - all clients should support API 1.14 by then - // Buffer must remain in scope until encode_message_to_buffer is called - char object_id_buf[OBJECT_ID_MAX_LEN]; - if (!conn->client_supports_api_version(1, 14)) { - msg.object_id = entity->get_object_id_to(object_id_buf); - } - - if (entity->has_own_name()) { - msg.name = entity->get_name(); - } - - // Set common EntityBase properties -#ifdef USE_ENTITY_ICON - char icon_buf[MAX_ICON_LENGTH]; - msg.icon = StringRef(entity->get_icon_to(icon_buf)); -#endif - msg.disabled_by_default = entity->is_disabled_by_default(); - msg.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category()); -#ifdef USE_DEVICES - msg.device_id = entity->get_device_id(); -#endif - return encode_message_to_buffer(msg, message_type, conn, remaining_size); - } + // Wrapper for entity types that have a device_class field + static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg, + StringRef &device_class_field, uint8_t message_type, + APIConnection *conn, uint32_t remaining_size); #ifdef USE_VOICE_ASSISTANT // Helper to check voice assistant validity and connection ownership diff --git a/esphome/components/mqtt/mqtt_binary_sensor.cpp b/esphome/components/mqtt/mqtt_binary_sensor.cpp index 75995f61e0..ebb29db44f 100644 --- a/esphome/components/mqtt/mqtt_binary_sensor.cpp +++ b/esphome/components/mqtt/mqtt_binary_sensor.cpp @@ -30,15 +30,11 @@ MQTTBinarySensorComponent::MQTTBinarySensorComponent(binary_sensor::BinarySensor void MQTTBinarySensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->binary_sensor_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) if (this->binary_sensor_->is_status_binary_sensor()) root[MQTT_PAYLOAD_ON] = mqtt::global_mqtt_client->get_availability().payload_available; if (this->binary_sensor_->is_status_binary_sensor()) root[MQTT_PAYLOAD_OFF] = mqtt::global_mqtt_client->get_availability().payload_not_available; + // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) config.command_topic = false; } bool MQTTBinarySensorComponent::send_initial_state() { diff --git a/esphome/components/mqtt/mqtt_button.cpp b/esphome/components/mqtt/mqtt_button.cpp index 718fe93016..7e0ae7d06e 100644 --- a/esphome/components/mqtt/mqtt_button.cpp +++ b/esphome/components/mqtt/mqtt_button.cpp @@ -30,13 +30,7 @@ void MQTTButtonComponent::dump_config() { } void MQTTButtonComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { - // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson config.state_topic = false; - const auto device_class = this->button_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) } MQTT_COMPONENT_TYPE(MQTTButtonComponent, "button") diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index d31a78b090..afc514609c 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -214,6 +214,11 @@ bool MQTTComponent::send_discovery_() { if (icon[0] != '\0') { root[MQTT_ICON] = icon; } + char dc_buf[MAX_DEVICE_CLASS_LENGTH]; + const char *dc = this->get_entity()->get_device_class_to(dc_buf); + if (dc[0] != '\0') { + root[MQTT_DEVICE_CLASS] = dc; + } const auto entity_category = this->get_entity()->get_entity_category(); if (entity_category != ENTITY_CATEGORY_NONE) { diff --git a/esphome/components/mqtt/mqtt_cover.cpp b/esphome/components/mqtt/mqtt_cover.cpp index 9752004094..ddb4b2d69d 100644 --- a/esphome/components/mqtt/mqtt_cover.cpp +++ b/esphome/components/mqtt/mqtt_cover.cpp @@ -91,12 +91,6 @@ void MQTTCoverComponent::dump_config() { } void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->cover_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) - auto traits = this->cover_->get_traits(); if (traits.get_is_assumed_state()) { root[MQTT_OPTIMISTIC] = true; @@ -129,6 +123,7 @@ void MQTTCoverComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf root[MQTT_TILT_COMMAND_TOPIC] = this->get_tilt_command_topic_to(topic_buf); } } + // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) if (traits.get_supports_tilt() && !traits.get_supports_position()) { config.command_topic = false; } diff --git a/esphome/components/mqtt/mqtt_event.cpp b/esphome/components/mqtt/mqtt_event.cpp index 37d5c2551a..93ff6971b3 100644 --- a/esphome/components/mqtt/mqtt_event.cpp +++ b/esphome/components/mqtt/mqtt_event.cpp @@ -20,13 +20,6 @@ void MQTTEventComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf for (const auto &event_type : this->event_->get_event_types()) event_types.add(event_type); - // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->event_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) - config.command_topic = false; } diff --git a/esphome/components/mqtt/mqtt_number.cpp b/esphome/components/mqtt/mqtt_number.cpp index a2734f2beb..b0bac8b3d7 100644 --- a/esphome/components/mqtt/mqtt_number.cpp +++ b/esphome/components/mqtt/mqtt_number.cpp @@ -57,10 +57,6 @@ void MQTTNumberComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon root[MQTT_MODE] = NumberMqttModeStrings::get_progmem_str(static_cast<uint8_t>(mode), static_cast<uint8_t>(NUMBER_MODE_BOX)); } - const auto device_class = this->number_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) config.command_topic = true; diff --git a/esphome/components/mqtt/mqtt_sensor.cpp b/esphome/components/mqtt/mqtt_sensor.cpp index a7d311d194..c66465dd16 100644 --- a/esphome/components/mqtt/mqtt_sensor.cpp +++ b/esphome/components/mqtt/mqtt_sensor.cpp @@ -44,11 +44,6 @@ void MQTTSensorComponent::disable_expire_after() { this->expire_after_ = 0; } void MQTTSensorComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->sensor_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - if (this->sensor_->has_accuracy_decimals()) { root[MQTT_SUGGESTED_DISPLAY_PRECISION] = this->sensor_->get_accuracy_decimals(); } diff --git a/esphome/components/mqtt/mqtt_text_sensor.cpp b/esphome/components/mqtt/mqtt_text_sensor.cpp index a6b9f90b68..3acd71b50d 100644 --- a/esphome/components/mqtt/mqtt_text_sensor.cpp +++ b/esphome/components/mqtt/mqtt_text_sensor.cpp @@ -14,12 +14,6 @@ using namespace esphome::text_sensor; MQTTTextSensor::MQTTTextSensor(TextSensor *sensor) : sensor_(sensor) {} void MQTTTextSensor::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { - // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->sensor_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) config.command_topic = false; } void MQTTTextSensor::setup() { diff --git a/esphome/components/mqtt/mqtt_valve.cpp b/esphome/components/mqtt/mqtt_valve.cpp index 2b9f02858b..b155a4c897 100644 --- a/esphome/components/mqtt/mqtt_valve.cpp +++ b/esphome/components/mqtt/mqtt_valve.cpp @@ -64,12 +64,6 @@ void MQTTValveComponent::dump_config() { } void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - const auto device_class = this->valve_->get_device_class_ref(); - if (!device_class.empty()) { - root[MQTT_DEVICE_CLASS] = device_class; - } - // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) - auto traits = this->valve_->get_traits(); if (traits.get_is_assumed_state()) { root[MQTT_OPTIMISTIC] = true; @@ -78,6 +72,7 @@ void MQTTValveComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConf root[MQTT_POSITION_TOPIC] = this->get_position_state_topic(); root[MQTT_SET_POSITION_TOPIC] = this->get_position_command_topic(); } + // NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks) } MQTT_COMPONENT_TYPE(MQTTValveComponent, "valve") diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index bc90c88e57..5590e67b82 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -2137,7 +2137,8 @@ json::SerializationBuffer<> WebServer::event_json_(event::Event *obj, StringRef for (const char *event_type : obj->get_event_types()) { event_types.add(event_type); } - root[ESPHOME_F("device_class")] = obj->get_device_class_ref(); + char dc_buf[MAX_DEVICE_CLASS_LENGTH]; + root[ESPHOME_F("device_class")] = obj->get_device_class_to(dc_buf); this->add_sorting_info_(root, obj); } diff --git a/esphome/core/config.py b/esphome/core/config.py index 8631726a02..d4a839cb79 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -223,6 +223,12 @@ else: # Keep in sync with ESPHOME_FRIENDLY_NAME_MAX_LEN in esphome/core/entity_base.h FRIENDLY_NAME_MAX_LEN = 120 +# Max device class string length (47 chars + null = 48-byte PROGMEM buffer) +# Keep in sync with MAX_DEVICE_CLASS_LENGTH in esphome/core/entity_base.h: +# DEVICE_CLASS_MAX_LENGTH == MAX_DEVICE_CLASS_LENGTH - 1 (C++ includes the null) +DEVICE_CLASS_MAX_LENGTH = 47 + + # Max icon string length (63 chars + null = 64-byte PROGMEM buffer) # Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h ICON_MAX_LENGTH = 63 diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 37e7fcc998..5c4e1c4445 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -51,7 +51,27 @@ __attribute__((weak)) const char *entity_device_class_lookup(uint8_t) { return " __attribute__((weak)) const char *entity_uom_lookup(uint8_t) { return ""; } __attribute__((weak)) const char *entity_icon_lookup(uint8_t) { return ""; } -// Entity device class (from index) +// Entity device class — buffer-based API for PROGMEM safety on ESP8266 +const char *EntityBase::get_device_class_to([[maybe_unused]] std::span<char, MAX_DEVICE_CLASS_LENGTH> buffer) const { +#ifdef USE_ENTITY_DEVICE_CLASS + const uint8_t idx = this->device_class_idx_; +#else + const uint8_t idx = 0; +#endif +#ifdef USE_ESP8266 + if (idx == 0) + return ""; + const char *dc = entity_device_class_lookup(idx); + ESPHOME_strncpy_P(buffer.data(), dc, buffer.size() - 1); + buffer[buffer.size() - 1] = '\0'; + return buffer.data(); +#else + return entity_device_class_lookup(idx); +#endif +} + +#ifndef USE_ESP8266 +// Deprecated device class accessors — not available on ESP8266 (rodata is RAM) StringRef EntityBase::get_device_class_ref() const { #ifdef USE_ENTITY_DEVICE_CLASS return StringRef(entity_device_class_lookup(this->device_class_idx_)); @@ -59,7 +79,14 @@ StringRef EntityBase::get_device_class_ref() const { return StringRef(entity_device_class_lookup(0)); #endif } -std::string EntityBase::get_device_class() const { return std::string(this->get_device_class_ref().c_str()); } +std::string EntityBase::get_device_class() const { +#ifdef USE_ENTITY_DEVICE_CLASS + return std::string(entity_device_class_lookup(this->device_class_idx_)); +#else + return std::string(entity_device_class_lookup(0)); +#endif +} +#endif // !USE_ESP8266 // Entity unit of measurement (from index) StringRef EntityBase::get_unit_of_measurement_ref() const { @@ -191,8 +218,10 @@ void log_entity_icon(const char *tag, const char *prefix, const EntityBase &obj) #endif void log_entity_device_class(const char *tag, const char *prefix, const EntityBase &obj) { - if (!obj.get_device_class_ref().empty()) { - ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, obj.get_device_class_ref().c_str()); + char dc_buf[MAX_DEVICE_CLASS_LENGTH]; + const char *dc = obj.get_device_class_to(dc_buf); + if (dc[0] != '\0') { + ESP_LOGCONFIG(tag, "%s Device Class: '%s'", prefix, dc); } } diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 1ce1e658e0..20eb68b67a 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -36,6 +36,11 @@ static constexpr size_t OBJECT_ID_MAX_LEN = 128; // Maximum state length that Home Assistant will accept without raising ValueError static constexpr size_t MAX_STATE_LEN = 255; +// Maximum device class string buffer size (47 chars + null terminator) +// Longest standard device class: "volatile_organic_compounds_parts" (32 chars) +// Device classes are stored in PROGMEM; on ESP8266 they must be copied to a stack buffer. +static constexpr size_t MAX_DEVICE_CLASS_LENGTH = 48; + // Maximum icon string buffer size (63 chars + null terminator) // Icons are stored in PROGMEM; on ESP8266 they must be copied to a stack buffer. static constexpr size_t MAX_ICON_LENGTH = 64; @@ -113,13 +118,31 @@ class EntityBase { #endif } - // Get device class as StringRef (from packed index) + // Get this entity's device class into a stack buffer. + // On non-ESP8266: returns pointer to PROGMEM string directly (buffer unused). + // On ESP8266: copies from PROGMEM to buffer, returns buffer pointer. + const char *get_device_class_to(std::span<char, MAX_DEVICE_CLASS_LENGTH> buffer) const; + +#ifdef USE_ESP8266 + // On ESP8266, rodata is RAM. Device classes are in PROGMEM and cannot be accessed + // directly as const char*. Use get_device_class_to() with a stack buffer instead. + template<typename T = int> StringRef get_device_class_ref() const { + static_assert(sizeof(T) == 0, "get_device_class_ref() unavailable on ESP8266 (rodata is RAM). " + "Use get_device_class_to() with a stack buffer."); + return StringRef(""); + } + template<typename T = int> std::string get_device_class() const { + static_assert(sizeof(T) == 0, "get_device_class() unavailable on ESP8266 (rodata is RAM). " + "Use get_device_class_to() with a stack buffer."); + return ""; + } +#else + // Deprecated: use get_device_class_to() instead. Device classes are in PROGMEM. + ESPDEPRECATED("Use get_device_class_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0") StringRef get_device_class_ref() const; - /// Get the device class as std::string (deprecated, prefer get_device_class_ref()) - ESPDEPRECATED("Use get_device_class_ref() instead for better performance (avoids string copy). Will be removed in " - "ESPHome 2026.9.0", - "2026.3.0") + ESPDEPRECATED("Use get_device_class_to() instead. Will be removed in ESPHome 2026.9.0", "2026.3.0") std::string get_device_class() const; +#endif // Get unit of measurement as StringRef (from packed index) StringRef get_unit_of_measurement_ref() const; /// Get the unit of measurement as std::string (deprecated, prefer get_unit_of_measurement_ref()) diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index 01fa27b833..a46d2466fd 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -17,7 +17,7 @@ from esphome.const import ( CONF_UNIT_OF_MEASUREMENT, ) from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority -from esphome.core.config import ICON_MAX_LENGTH +from esphome.core.config import DEVICE_CLASS_MAX_LENGTH, ICON_MAX_LENGTH from esphome.cpp_generator import MockObj, RawStatement, add, get_variable import esphome.final_validate as fv from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case @@ -132,7 +132,7 @@ def _generate_category_code( _CATEGORY_CONFIGS = ( - ("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes", False), + ("ENTITY_DC_TABLE", "entity_device_class_lookup", "device_classes", True), ("ENTITY_UOM_TABLE", "entity_uom_lookup", "units", False), ("ENTITY_ICON_TABLE", "entity_icon_lookup", "icons", True), ) @@ -179,6 +179,10 @@ def _register_string( def register_device_class(value: str) -> int: """Register a device_class string and return its 1-based index.""" + if value and len(value) > DEVICE_CLASS_MAX_LENGTH: + raise ValueError( + f"Device class string too long ({len(value)} chars, max {DEVICE_CLASS_MAX_LENGTH}): '{value}'" + ) return _register_string( value, _get_pool().device_classes, _MAX_DEVICE_CLASSES, "device_class" ) diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index 79bc3095b9..1392a1d043 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -23,6 +23,7 @@ from esphome.core.entity_helpers import ( _setup_entity_impl, entity_duplicate_validator, get_base_entity_object_id, + register_device_class, register_icon, setup_entity, ) @@ -926,6 +927,22 @@ def test_register_icon_max_length() -> None: assert register_icon("") == 0 +def test_register_device_class_max_length() -> None: + """Test register_device_class rejects device classes exceeding 47 characters.""" + # 47 chars should succeed + max_dc = "a" * 47 + idx = register_device_class(max_dc) + assert idx > 0 + + # 48 chars should fail + too_long = "a" * 48 + with pytest.raises(ValueError, match="Device class string too long"): + register_device_class(too_long) + + # Empty string returns 0 + assert register_device_class("") == 0 + + @pytest.mark.asyncio async def test_setup_entity_with_entity_category( setup_test_environment: list[str], From 9654140c00fecc7c86c554c7d733436c2505d2b5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:00:46 -0500 Subject: [PATCH 1159/2030] [tm1638][rp2040_pio_led_strip][atm90e32] Fix bounds checks and off-by-one (#14559) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/atm90e32/atm90e32.cpp | 4 +-- .../rp2040_pio_led_strip/led_strip.cpp | 2 +- esphome/components/tm1638/tm1638.cpp | 29 ++++++++++--------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/esphome/components/atm90e32/atm90e32.cpp b/esphome/components/atm90e32/atm90e32.cpp index 412964d0f8..ee7fe5ce75 100644 --- a/esphome/components/atm90e32/atm90e32.cpp +++ b/esphome/components/atm90e32/atm90e32.cpp @@ -619,7 +619,7 @@ void ATM90E32Component::run_gain_calibrations() { ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping voltage calibration: measured voltage is 0.", cs, phase_labels[phase]); } else { - uint32_t new_voltage_gain = static_cast<uint16_t>((ref_voltage / measured_voltage) * current_voltage_gain); + uint32_t new_voltage_gain = static_cast<uint32_t>((ref_voltage / measured_voltage) * current_voltage_gain); if (new_voltage_gain == 0) { ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Voltage gain would be 0. Check reference and measured voltage.", cs, phase_labels[phase]); @@ -644,7 +644,7 @@ void ATM90E32Component::run_gain_calibrations() { ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Skipping current calibration: measured current is 0.", cs, phase_labels[phase]); } else { - uint32_t new_current_gain = static_cast<uint16_t>((ref_current / measured_current) * current_current_gain); + uint32_t new_current_gain = static_cast<uint32_t>((ref_current / measured_current) * current_current_gain); if (new_current_gain == 0) { ESP_LOGW(TAG, "[CALIBRATION][%s] Phase %s - Current gain would be 0. Check reference and measured current.", cs, phase_labels[phase]); diff --git a/esphome/components/rp2040_pio_led_strip/led_strip.cpp b/esphome/components/rp2040_pio_led_strip/led_strip.cpp index dc0d3c315a..fdb49fb3ef 100644 --- a/esphome/components/rp2040_pio_led_strip/led_strip.cpp +++ b/esphome/components/rp2040_pio_led_strip/led_strip.cpp @@ -70,7 +70,7 @@ void RP2040PIOLEDStripLightOutput::setup() { // but there are only 4 state machines on each PIO so we can only have 4 strips per PIO uint offset = 0; - if (RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1] > 4) { + if (RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1] >= 4) { ESP_LOGE(TAG, "Too many instances of PIO program"); this->mark_failed(); return; diff --git a/esphome/components/tm1638/tm1638.cpp b/esphome/components/tm1638/tm1638.cpp index 8ef546ff32..c67ff1adbc 100644 --- a/esphome/components/tm1638/tm1638.cpp +++ b/esphome/components/tm1638/tm1638.cpp @@ -147,35 +147,38 @@ void TM1638Component::set_intensity(uint8_t brightness_level) { uint8_t TM1638Component::print(uint8_t start_pos, const char *str) { uint8_t pos = start_pos; - bool last_was_dot = false; for (; *str != '\0'; str++) { uint8_t data = TM1638_UNKNOWN_CHAR; if (*str >= ' ' && *str <= '~') { - data = progmem_read_byte(&TM1638Translation::SEVEN_SEG[*str - 32]); // subract 32 to account for ASCII offset - } else if (data == TM1638_UNKNOWN_CHAR) { + // Subtract 32 to account for ASCII offset + data = progmem_read_byte(&TM1638Translation::SEVEN_SEG[*str - 32]); + } else { ESP_LOGW(TAG, "Encountered character '%c' with no TM1638 representation while translating string!", *str); } - if (*str == '.') // handle dots - { - if (pos != start_pos && - !last_was_dot) // if we are not at the first position, backup by one unless last char was a dot - { + if (*str == '.') { + // Merge dot onto previous character unless we're at the start or last was also a dot + if (pos != start_pos && !last_was_dot) { pos--; } - this->buffer_[pos] |= 0b10000000; // turn on the dot on the previous position - last_was_dot = true; // set a bit in case the next chracter is also a dot - } else // if not a dot, then just write the character to display - { + if (pos >= 8) { + ESP_LOGI(TAG, "TM1638 String is too long for the display!"); + break; + } + // Turn on the dot on the previous position + this->buffer_[pos] |= 0b10000000; + last_was_dot = true; + } else { + // Not a dot, write the character to display if (pos >= 8) { ESP_LOGI(TAG, "TM1638 String is too long for the display!"); break; } this->buffer_[pos] = data; - last_was_dot = false; // clear dot tracking bit + last_was_dot = false; } pos++; From 42dbb51022a61e07b26d82b6d348f470d2afa72f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 09:03:54 -1000 Subject: [PATCH 1160/2030] [api] Devirtualize protobuf encode/calculate_size (#14449) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_connection.cpp | 274 ++-- esphome/components/api/api_connection.h | 94 +- esphome/components/api/api_pb2.cpp | 1436 ++++++++++------- esphome/components/api/api_pb2.h | 352 ++-- esphome/components/api/api_pb2_service.h | 8 - esphome/components/api/api_server.cpp | 8 +- esphome/components/api/api_server.h | 2 +- esphome/components/api/list_entities.cpp | 2 +- esphome/components/api/proto.h | 421 +---- .../bluetooth_proxy/bluetooth_connection.cpp | 21 +- .../bluetooth_proxy/bluetooth_proxy.cpp | 18 +- .../voice_assistant/voice_assistant.cpp | 11 +- .../components/zwave_proxy/zwave_proxy.cpp | 6 +- script/api_protobuf/api_protobuf.py | 107 +- 14 files changed, 1373 insertions(+), 1387 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 77920432c0..8721072e49 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -275,7 +275,7 @@ void APIConnection::check_keepalive_(uint32_t now) { // Only send ping if we're not disconnecting ESP_LOGVV(TAG, "Sending keepalive PING"); PingRequest req; - this->flags_.sent_ping = this->send_message(req, PingRequest::MESSAGE_TYPE); + this->flags_.sent_ping = this->send_message(req); if (!this->flags_.sent_ping) { // If we can't send the ping request directly (tx_buffer full), // schedule it at the front of the batch so it will be sent with priority @@ -336,7 +336,7 @@ bool APIConnection::send_disconnect_response_() { this->log_client_(ESPHOME_LOG_LEVEL_DEBUG, LOG_STR("disconnected")); this->flags_.next_close = true; DisconnectResponse resp; - return this->send_message(resp, DisconnectResponse::MESSAGE_TYPE); + return this->send_message(resp); } void APIConnection::on_disconnect_response() { // Don't close socket here, let APIServer::loop() do it @@ -344,61 +344,19 @@ void APIConnection::on_disconnect_response() { this->flags_.remove = true; } -// Encodes a message to the buffer and returns the total number of bytes used, -// including header and footer overhead. Returns 0 if the message doesn't fit. -uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, - uint32_t remaining_size) { -#ifdef HAS_PROTO_MESSAGE_DUMP - // If in log-only mode, just log and return - if (conn->flags_.log_only_mode) { - DumpBuffer dump_buf; - conn->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); - return 1; // Return non-zero to indicate "success" for logging - } +uint16_t APIConnection::fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, + CalculateSizeFn size_fn, MessageEncodeFn encode_fn, + APIConnection *conn, uint32_t remaining_size) { + msg.key = entity->get_object_id_hash(); +#ifdef USE_DEVICES + msg.device_id = entity->get_device_id(); #endif - - // Calculate size - uint32_t calculated_size = msg.calculated_size(); - - // Cache frame sizes to avoid repeated virtual calls - const uint8_t header_padding = conn->helper_->frame_header_padding(); - const uint8_t footer_size = conn->helper_->frame_footer_size(); - - // Calculate total size with padding for buffer allocation - size_t total_calculated_size = calculated_size + header_padding + footer_size; - - // Check if it fits - if (total_calculated_size > remaining_size) { - return 0; // Doesn't fit - } - - // Get buffer size after allocation (which includes header padding) - std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); - - if (conn->flags_.batch_first_message) { - // First message - buffer already prepared by caller, just clear flag - conn->flags_.batch_first_message = false; - } else { - // Batch message second or later - // Add padding for previous message footer + this message header - size_t current_size = shared_buf.size(); - shared_buf.reserve(current_size + total_calculated_size); - shared_buf.resize(current_size + footer_size + header_padding); - } - - // Pre-resize buffer to include payload, then encode through raw pointer - size_t write_start = shared_buf.size(); - shared_buf.resize(write_start + calculated_size); - ProtoWriteBuffer buffer{&shared_buf, write_start}; - msg.encode(buffer); - - // Return total size (header + payload + footer) - return static_cast<uint16_t>(header_padding + calculated_size + footer_size); + return encode_to_buffer(size_fn(&msg), encode_fn, &msg, conn, remaining_size); } uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, - uint8_t message_type, APIConnection *conn, - uint32_t remaining_size) { + CalculateSizeFn size_fn, MessageEncodeFn encode_fn, + APIConnection *conn, uint32_t remaining_size) { // Set common fields that are shared by all entity types msg.key = entity->get_object_id_hash(); @@ -406,7 +364,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp // For older clients, we must send object_id for backward compatibility // See: https://github.com/esphome/backlog/issues/76 // TODO: Remove this backward compat code before 2026.7.0 - all clients should support API 1.14 by then - // Buffer must remain in scope until encode_message_to_buffer is called + // Buffer must remain in scope until encode_to_buffer is called char object_id_buf[OBJECT_ID_MAX_LEN]; if (!conn->client_supports_api_version(1, 14)) { msg.object_id = entity->get_object_id_to(object_id_buf); @@ -426,16 +384,17 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp #ifdef USE_DEVICES msg.device_id = entity->get_device_id(); #endif - return encode_message_to_buffer(msg, message_type, conn, remaining_size); + return encode_to_buffer(size_fn(&msg), encode_fn, &msg, conn, remaining_size); } uint16_t APIConnection::fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg, StringRef &device_class_field, - uint8_t message_type, APIConnection *conn, + CalculateSizeFn size_fn, + MessageEncodeFn encode_fn, APIConnection *conn, uint32_t remaining_size) { char dc_buf[MAX_DEVICE_CLASS_LENGTH]; device_class_field = StringRef(entity->get_device_class_to(dc_buf)); - return fill_and_encode_entity_info(entity, msg, message_type, conn, remaining_size); + return fill_and_encode_entity_info(entity, msg, size_fn, encode_fn, conn, remaining_size); } #ifdef USE_BINARY_SENSOR @@ -449,16 +408,14 @@ uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConn BinarySensorStateResponse resp; resp.state = binary_sensor->state; resp.missing_state = !binary_sensor->has_state(); - return fill_and_encode_entity_state(binary_sensor, resp, BinarySensorStateResponse::MESSAGE_TYPE, conn, - remaining_size); + return fill_and_encode_entity_state(binary_sensor, resp, conn, remaining_size); } uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *binary_sensor = static_cast<binary_sensor::BinarySensor *>(entity); ListEntitiesBinarySensorResponse msg; msg.is_status_binary_sensor = binary_sensor->is_status_binary_sensor(); - return fill_and_encode_entity_info_with_device_class( - binary_sensor, msg, msg.device_class, ListEntitiesBinarySensorResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(binary_sensor, msg, msg.device_class, conn, remaining_size); } #endif @@ -474,7 +431,7 @@ uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection * if (traits.get_supports_tilt()) msg.tilt = cover->tilt; msg.current_operation = static_cast<enums::CoverOperation>(cover->current_operation); - return fill_and_encode_entity_state(cover, msg, CoverStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(cover, msg, conn, remaining_size); } uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *cover = static_cast<cover::Cover *>(entity); @@ -484,8 +441,7 @@ uint16_t APIConnection::try_send_cover_info(EntityBase *entity, APIConnection *c msg.supports_position = traits.get_supports_position(); msg.supports_tilt = traits.get_supports_tilt(); msg.supports_stop = traits.get_supports_stop(); - return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class, - ListEntitiesCoverResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(cover, msg, msg.device_class, conn, remaining_size); } void APIConnection::on_cover_command_request(const CoverCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(cover::Cover, cover, cover) @@ -517,7 +473,7 @@ uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *co msg.direction = static_cast<enums::FanDirection>(fan->direction); if (traits.supports_preset_modes() && fan->has_preset_mode()) msg.preset_mode = fan->get_preset_mode(); - return fill_and_encode_entity_state(fan, msg, FanStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(fan, msg, conn, remaining_size); } uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *fan = static_cast<fan::Fan *>(entity); @@ -528,7 +484,7 @@ uint16_t APIConnection::try_send_fan_info(EntityBase *entity, APIConnection *con msg.supports_direction = traits.supports_direction(); msg.supported_speed_count = traits.supported_speed_count(); msg.supported_preset_modes = &traits.supported_preset_modes(); - return fill_and_encode_entity_info(fan, msg, ListEntitiesFanResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(fan, msg, conn, remaining_size); } void APIConnection::on_fan_command_request(const FanCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(fan::Fan, fan, fan) @@ -571,7 +527,7 @@ uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection * if (light->supports_effects()) { resp.effect = light->get_effect_name(); } - return fill_and_encode_entity_state(light, resp, LightStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(light, resp, conn, remaining_size); } uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *light = static_cast<light::LightState *>(entity); @@ -596,7 +552,7 @@ uint16_t APIConnection::try_send_light_info(EntityBase *entity, APIConnection *c } } msg.effects = &effects_list; - return fill_and_encode_entity_info(light, msg, ListEntitiesLightResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(light, msg, conn, remaining_size); } void APIConnection::on_light_command_request(const LightCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(light::LightState, light, light) @@ -641,7 +597,7 @@ uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection SensorStateResponse resp; resp.state = sensor->state; resp.missing_state = !sensor->has_state(); - return fill_and_encode_entity_state(sensor, resp, SensorStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(sensor, resp, conn, remaining_size); } uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { @@ -651,8 +607,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection * msg.accuracy_decimals = sensor->get_accuracy_decimals(); msg.force_update = sensor->get_force_update(); msg.state_class = static_cast<enums::SensorStateClass>(sensor->get_state_class()); - return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class, - ListEntitiesSensorResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(sensor, msg, msg.device_class, conn, remaining_size); } #endif @@ -665,15 +620,14 @@ uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection auto *a_switch = static_cast<switch_::Switch *>(entity); SwitchStateResponse resp; resp.state = a_switch->state; - return fill_and_encode_entity_state(a_switch, resp, SwitchStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(a_switch, resp, conn, remaining_size); } uint16_t APIConnection::try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *a_switch = static_cast<switch_::Switch *>(entity); ListEntitiesSwitchResponse msg; msg.assumed_state = a_switch->assumed_state(); - return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class, - ListEntitiesSwitchResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(a_switch, msg, msg.device_class, conn, remaining_size); } void APIConnection::on_switch_command_request(const SwitchCommandRequest &msg) { ENTITY_COMMAND_GET(switch_::Switch, a_switch, switch) @@ -697,13 +651,12 @@ uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnec TextSensorStateResponse resp; resp.state = StringRef(text_sensor->state); resp.missing_state = !text_sensor->has_state(); - return fill_and_encode_entity_state(text_sensor, resp, TextSensorStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(text_sensor, resp, conn, remaining_size); } uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *text_sensor = static_cast<text_sensor::TextSensor *>(entity); ListEntitiesTextSensorResponse msg; - return fill_and_encode_entity_info_with_device_class( - text_sensor, msg, msg.device_class, ListEntitiesTextSensorResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(text_sensor, msg, msg.device_class, conn, remaining_size); } #endif @@ -743,7 +696,7 @@ uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection resp.current_humidity = climate->current_humidity; if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) resp.target_humidity = climate->target_humidity; - return fill_and_encode_entity_state(climate, resp, ClimateStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(climate, resp, conn, remaining_size); } uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *climate = static_cast<climate::Climate *>(entity); @@ -770,7 +723,7 @@ uint16_t APIConnection::try_send_climate_info(EntityBase *entity, APIConnection msg.supported_presets = &traits.get_supported_presets(); msg.supported_custom_presets = &traits.get_supported_custom_presets(); msg.supported_swing_modes = &traits.get_supported_swing_modes(); - return fill_and_encode_entity_info(climate, msg, ListEntitiesClimateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(climate, msg, conn, remaining_size); } void APIConnection::on_climate_command_request(const ClimateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(climate::Climate, climate, climate) @@ -808,7 +761,7 @@ uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection NumberStateResponse resp; resp.state = number->state; resp.missing_state = !number->has_state(); - return fill_and_encode_entity_state(number, resp, NumberStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(number, resp, conn, remaining_size); } uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { @@ -819,8 +772,7 @@ uint16_t APIConnection::try_send_number_info(EntityBase *entity, APIConnection * msg.min_value = number->traits.get_min_value(); msg.max_value = number->traits.get_max_value(); msg.step = number->traits.get_step(); - return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class, - ListEntitiesNumberResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(number, msg, msg.device_class, conn, remaining_size); } void APIConnection::on_number_command_request(const NumberCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(number::Number, number, number) @@ -840,12 +792,12 @@ uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *c resp.year = date->year; resp.month = date->month; resp.day = date->day; - return fill_and_encode_entity_state(date, resp, DateStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(date, resp, conn, remaining_size); } uint16_t APIConnection::try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *date = static_cast<datetime::DateEntity *>(entity); ListEntitiesDateResponse msg; - return fill_and_encode_entity_info(date, msg, ListEntitiesDateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(date, msg, conn, remaining_size); } void APIConnection::on_date_command_request(const DateCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateEntity, date, date) @@ -865,12 +817,12 @@ uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *c resp.hour = time->hour; resp.minute = time->minute; resp.second = time->second; - return fill_and_encode_entity_state(time, resp, TimeStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(time, resp, conn, remaining_size); } uint16_t APIConnection::try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *time = static_cast<datetime::TimeEntity *>(entity); ListEntitiesTimeResponse msg; - return fill_and_encode_entity_info(time, msg, ListEntitiesTimeResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(time, msg, conn, remaining_size); } void APIConnection::on_time_command_request(const TimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::TimeEntity, time, time) @@ -892,12 +844,12 @@ uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnectio ESPTime state = datetime->state_as_esptime(); resp.epoch_seconds = state.timestamp; } - return fill_and_encode_entity_state(datetime, resp, DateTimeStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(datetime, resp, conn, remaining_size); } uint16_t APIConnection::try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *datetime = static_cast<datetime::DateTimeEntity *>(entity); ListEntitiesDateTimeResponse msg; - return fill_and_encode_entity_info(datetime, msg, ListEntitiesDateTimeResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(datetime, msg, conn, remaining_size); } void APIConnection::on_date_time_command_request(const DateTimeCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(datetime::DateTimeEntity, datetime, datetime) @@ -916,7 +868,7 @@ uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *c TextStateResponse resp; resp.state = StringRef(text->state); resp.missing_state = !text->has_state(); - return fill_and_encode_entity_state(text, resp, TextStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(text, resp, conn, remaining_size); } uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { @@ -926,7 +878,7 @@ uint16_t APIConnection::try_send_text_info(EntityBase *entity, APIConnection *co msg.min_length = text->traits.get_min_length(); msg.max_length = text->traits.get_max_length(); msg.pattern = text->traits.get_pattern_ref(); - return fill_and_encode_entity_info(text, msg, ListEntitiesTextResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(text, msg, conn, remaining_size); } void APIConnection::on_text_command_request(const TextCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(text::Text, text, text) @@ -945,14 +897,14 @@ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection SelectStateResponse resp; resp.state = select->current_option(); resp.missing_state = !select->has_state(); - return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(select, resp, conn, remaining_size); } uint16_t APIConnection::try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *select = static_cast<select::Select *>(entity); ListEntitiesSelectResponse msg; msg.options = &select->traits.get_options(); - return fill_and_encode_entity_info(select, msg, ListEntitiesSelectResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(select, msg, conn, remaining_size); } void APIConnection::on_select_command_request(const SelectCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(select::Select, select, select) @@ -965,8 +917,7 @@ void APIConnection::on_select_command_request(const SelectCommandRequest &msg) { uint16_t APIConnection::try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *button = static_cast<button::Button *>(entity); ListEntitiesButtonResponse msg; - return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class, - ListEntitiesButtonResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(button, msg, msg.device_class, conn, remaining_size); } void esphome::api::APIConnection::on_button_command_request(const ButtonCommandRequest &msg) { ENTITY_COMMAND_GET(button::Button, button, button) @@ -983,7 +934,7 @@ uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *c auto *a_lock = static_cast<lock::Lock *>(entity); LockStateResponse resp; resp.state = static_cast<enums::LockState>(a_lock->state); - return fill_and_encode_entity_state(a_lock, resp, LockStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(a_lock, resp, conn, remaining_size); } uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { @@ -992,7 +943,7 @@ uint16_t APIConnection::try_send_lock_info(EntityBase *entity, APIConnection *co msg.assumed_state = a_lock->traits.get_assumed_state(); msg.supports_open = a_lock->traits.get_supports_open(); msg.requires_code = a_lock->traits.get_requires_code(); - return fill_and_encode_entity_info(a_lock, msg, ListEntitiesLockResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(a_lock, msg, conn, remaining_size); } void APIConnection::on_lock_command_request(const LockCommandRequest &msg) { ENTITY_COMMAND_GET(lock::Lock, a_lock, lock) @@ -1020,7 +971,7 @@ uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection * ValveStateResponse resp; resp.position = valve->position; resp.current_operation = static_cast<enums::ValveOperation>(valve->current_operation); - return fill_and_encode_entity_state(valve, resp, ValveStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(valve, resp, conn, remaining_size); } uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *valve = static_cast<valve::Valve *>(entity); @@ -1029,8 +980,7 @@ uint16_t APIConnection::try_send_valve_info(EntityBase *entity, APIConnection *c msg.assumed_state = traits.get_is_assumed_state(); msg.supports_position = traits.get_supports_position(); msg.supports_stop = traits.get_supports_stop(); - return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class, - ListEntitiesValveResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(valve, msg, msg.device_class, conn, remaining_size); } void APIConnection::on_valve_command_request(const ValveCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(valve::Valve, valve, valve) @@ -1056,7 +1006,7 @@ uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConne resp.state = static_cast<enums::MediaPlayerState>(report_state); resp.volume = media_player->volume; resp.muted = media_player->is_muted(); - return fill_and_encode_entity_state(media_player, resp, MediaPlayerStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(media_player, resp, conn, remaining_size); } uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *media_player = static_cast<media_player::MediaPlayer *>(entity); @@ -1073,8 +1023,7 @@ uint16_t APIConnection::try_send_media_player_info(EntityBase *entity, APIConnec media_format.purpose = static_cast<enums::MediaPlayerFormatPurpose>(supported_format.purpose); media_format.sample_bytes = supported_format.sample_bytes; } - return fill_and_encode_entity_info(media_player, msg, ListEntitiesMediaPlayerResponse::MESSAGE_TYPE, conn, - remaining_size); + return fill_and_encode_entity_info(media_player, msg, conn, remaining_size); } void APIConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(media_player::MediaPlayer, media_player, media_player) @@ -1115,7 +1064,7 @@ void APIConnection::try_send_camera_image_() { msg.device_id = camera::Camera::instance()->get_device_id(); #endif - if (!this->send_message_impl(msg, CameraImageResponse::MESSAGE_TYPE)) { + if (!this->send_message(msg)) { return; // Send failed, try again later } this->image_reader_->consume_data(to_send); @@ -1141,7 +1090,7 @@ void APIConnection::set_camera_state(std::shared_ptr<camera::CameraImage> image) uint16_t APIConnection::try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *camera = static_cast<camera::Camera *>(entity); ListEntitiesCameraResponse msg; - return fill_and_encode_entity_info(camera, msg, ListEntitiesCameraResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(camera, msg, conn, remaining_size); } void APIConnection::on_camera_image_request(const CameraImageRequest &msg) { if (camera::Camera::instance() == nullptr) @@ -1296,7 +1245,7 @@ void APIConnection::on_voice_assistant_announce_request(const VoiceAssistantAnno bool APIConnection::send_voice_assistant_get_configuration_response_(const VoiceAssistantConfigurationRequest &msg) { VoiceAssistantConfigurationResponse resp; if (!this->check_voice_assistant_api_connection_()) { - return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE); + return this->send_message(resp); } auto &config = voice_assistant::global_voice_assistant->get_configuration(); @@ -1328,7 +1277,7 @@ bool APIConnection::send_voice_assistant_get_configuration_response_(const Voice resp.active_wake_words = &config.active_wake_words; resp.max_active_wake_words = config.max_active_wake_words; - return this->send_message(resp, VoiceAssistantConfigurationResponse::MESSAGE_TYPE); + return this->send_message(resp); } void APIConnection::on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) { if (!this->send_voice_assistant_get_configuration_response_(msg)) { @@ -1363,8 +1312,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, A auto *a_alarm_control_panel = static_cast<alarm_control_panel::AlarmControlPanel *>(entity); AlarmControlPanelStateResponse resp; resp.state = static_cast<enums::AlarmControlPanelState>(a_alarm_control_panel->get_state()); - return fill_and_encode_entity_state(a_alarm_control_panel, resp, AlarmControlPanelStateResponse::MESSAGE_TYPE, conn, - remaining_size); + return fill_and_encode_entity_state(a_alarm_control_panel, resp, conn, remaining_size); } uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { @@ -1373,8 +1321,7 @@ uint16_t APIConnection::try_send_alarm_control_panel_info(EntityBase *entity, AP msg.supported_features = a_alarm_control_panel->get_supported_features(); msg.requires_code = a_alarm_control_panel->get_requires_code(); msg.requires_code_to_arm = a_alarm_control_panel->get_requires_code_to_arm(); - return fill_and_encode_entity_info(a_alarm_control_panel, msg, ListEntitiesAlarmControlPanelResponse::MESSAGE_TYPE, - conn, remaining_size); + return fill_and_encode_entity_info(a_alarm_control_panel, msg, conn, remaining_size); } void APIConnection::on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) { ENTITY_COMMAND_MAKE_CALL(alarm_control_panel::AlarmControlPanel, a_alarm_control_panel, alarm_control_panel) @@ -1421,7 +1368,7 @@ uint16_t APIConnection::try_send_water_heater_state(EntityBase *entity, APIConne resp.target_temperature_high = wh->get_target_temperature_high(); resp.state = wh->get_state(); - return fill_and_encode_entity_state(wh, resp, WaterHeaterStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(wh, resp, conn, remaining_size); } uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *wh = static_cast<water_heater::WaterHeater *>(entity); @@ -1432,7 +1379,7 @@ uint16_t APIConnection::try_send_water_heater_info(EntityBase *entity, APIConnec msg.target_temperature_step = traits.get_target_temperature_step(); msg.supported_modes = &traits.get_supported_modes(); msg.supported_features = traits.get_feature_flags(); - return fill_and_encode_entity_info(wh, msg, ListEntitiesWaterHeaterResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(wh, msg, conn, remaining_size); } void APIConnection::on_water_heater_command_request(const WaterHeaterCommandRequest &msg) { @@ -1468,15 +1415,14 @@ uint16_t APIConnection::try_send_event_response(event::Event *event, StringRef e uint32_t remaining_size) { EventResponse resp; resp.event_type = event_type; - return fill_and_encode_entity_state(event, resp, EventResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(event, resp, conn, remaining_size); } uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *event = static_cast<event::Event *>(entity); ListEntitiesEventResponse msg; msg.event_types = &event->get_event_types(); - return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class, - ListEntitiesEventResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(event, msg, msg.device_class, conn, remaining_size); } #endif @@ -1493,9 +1439,7 @@ void APIConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRF #endif } -void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) { - this->send_message(msg, InfraredRFReceiveEvent::MESSAGE_TYPE); -} +void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) { this->send_message(msg); } #endif #ifdef USE_INFRARED @@ -1503,7 +1447,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection auto *infrared = static_cast<infrared::Infrared *>(entity); ListEntitiesInfraredResponse msg; msg.capabilities = infrared->get_capability_flags(); - return fill_and_encode_entity_info(infrared, msg, ListEntitiesInfraredResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info(infrared, msg, conn, remaining_size); } #endif @@ -1527,13 +1471,12 @@ uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection resp.release_summary = StringRef(update->update_info.summary); resp.release_url = StringRef(update->update_info.release_url); } - return fill_and_encode_entity_state(update, resp, UpdateStateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_state(update, resp, conn, remaining_size); } uint16_t APIConnection::try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *update = static_cast<update::UpdateEntity *>(entity); ListEntitiesUpdateResponse msg; - return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class, - ListEntitiesUpdateResponse::MESSAGE_TYPE, conn, remaining_size); + return fill_and_encode_entity_info_with_device_class(update, msg, msg.device_class, conn, remaining_size); } void APIConnection::on_update_command_request(const UpdateCommandRequest &msg) { ENTITY_COMMAND_GET(update::UpdateEntity, update, update) @@ -1559,7 +1502,7 @@ bool APIConnection::try_send_log_message(int level, const char *tag, const char SubscribeLogsResponse msg; msg.level = static_cast<enums::LogLevel>(level); msg.set_message(reinterpret_cast<const uint8_t *>(line), message_len); - return this->send_message_impl(msg, SubscribeLogsResponse::MESSAGE_TYPE); + return this->send_message(msg); } void APIConnection::complete_authentication_() { @@ -1616,12 +1559,12 @@ bool APIConnection::send_hello_response_(const HelloRequest &msg) { // Auto-authenticate - password auth was removed in ESPHome 2026.1.0 this->complete_authentication_(); - return this->send_message(resp, HelloResponse::MESSAGE_TYPE); + return this->send_message(resp); } bool APIConnection::send_ping_response_() { PingResponse resp; - return this->send_message(resp, PingResponse::MESSAGE_TYPE); + return this->send_message(resp); } bool APIConnection::send_device_info_response_() { @@ -1745,7 +1688,7 @@ bool APIConnection::send_device_info_response_() { } #endif - return this->send_message(resp, DeviceInfoResponse::MESSAGE_TYPE); + return this->send_message(resp); } void APIConnection::on_hello_request(const HelloRequest &msg) { if (!this->send_hello_response_(msg)) { @@ -1845,7 +1788,7 @@ void APIConnection::send_execute_service_response(uint32_t call_id, bool success resp.call_id = call_id; resp.success = success; resp.error_message = error_message; - this->send_message(resp, ExecuteServiceResponse::MESSAGE_TYPE); + this->send_message(resp); } #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON void APIConnection::send_execute_service_response(uint32_t call_id, bool success, StringRef error_message, @@ -1856,7 +1799,7 @@ void APIConnection::send_execute_service_response(uint32_t call_id, bool success resp.error_message = error_message; resp.response_data = response_data; resp.response_data_len = response_data_len; - this->send_message(resp, ExecuteServiceResponse::MESSAGE_TYPE); + this->send_message(resp); } #endif // USE_API_USER_DEFINED_ACTION_RESPONSES_JSON #endif // USE_API_USER_DEFINED_ACTION_RESPONSES @@ -1895,7 +1838,7 @@ bool APIConnection::send_noise_encryption_set_key_response_(const NoiseEncryptio resp.success = true; } - return this->send_message(resp, NoiseEncryptionSetKeyResponse::MESSAGE_TYPE); + return this->send_message(resp); } void APIConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) { if (!this->send_noise_encryption_set_key_response_(msg)) { @@ -1924,16 +1867,73 @@ bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { } return false; } -bool APIConnection::send_message_impl(const ProtoMessage &msg, uint8_t message_type) { - uint32_t payload_size = msg.calculated_size(); - std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref(); +bool APIConnection::send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, + const void *msg) { +#ifdef HAS_PROTO_MESSAGE_DUMP + // Skip dump for log messages (recursive logging risk) and camera frames (high-frequency noise) + if (message_type != SubscribeLogsResponse::MESSAGE_TYPE +#ifdef USE_CAMERA + && message_type != CameraImageResponse::MESSAGE_TYPE +#endif + ) { + auto *proto_msg = static_cast<const ProtoMessage *>(msg); + DumpBuffer dump_buf; + this->log_send_message_(proto_msg->message_name(), proto_msg->dump_to(dump_buf)); + } +#endif + auto &shared_buf = this->parent_->get_shared_buffer_ref(); this->prepare_first_message_buffer(shared_buf, payload_size); size_t write_start = shared_buf.size(); shared_buf.resize(write_start + payload_size); ProtoWriteBuffer buffer{&shared_buf, write_start}; - msg.encode(buffer); + encode_fn(msg, buffer); return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type); } +// Encodes a message to the buffer and returns the total number of bytes used, +// including header and footer overhead. Returns 0 if the message doesn't fit. +uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg, + APIConnection *conn, uint32_t remaining_size) { +#ifdef HAS_PROTO_MESSAGE_DUMP + if (conn->flags_.log_only_mode) { + auto *proto_msg = static_cast<const ProtoMessage *>(msg); + DumpBuffer dump_buf; + conn->log_send_message_(proto_msg->message_name(), proto_msg->dump_to(dump_buf)); + return 1; + } +#endif + // Cache frame sizes to avoid repeated virtual calls + const uint8_t header_padding = conn->helper_->frame_header_padding(); + const uint8_t footer_size = conn->helper_->frame_footer_size(); + + // Calculate total size with padding for buffer allocation + size_t total_calculated_size = calculated_size + header_padding + footer_size; + + // Check if it fits + if (total_calculated_size > remaining_size) + return 0; // Doesn't fit + + std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); + + if (conn->flags_.batch_first_message) { + // First message - buffer already prepared by caller, just clear flag + conn->flags_.batch_first_message = false; + } else { + // Batch message second or later + // Add padding for previous message footer + this message header + size_t current_size = shared_buf.size(); + shared_buf.reserve(current_size + total_calculated_size); + shared_buf.resize(current_size + footer_size + header_padding); + } + + // Pre-resize buffer to include payload, then encode through raw pointer + size_t write_start = shared_buf.size(); + shared_buf.resize(write_start + calculated_size); + ProtoWriteBuffer buffer{&shared_buf, write_start}; + encode_fn(msg, buffer); + + // Return total size (header + payload + footer) + return static_cast<uint16_t>(header_padding + calculated_size + footer_size); +} bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); @@ -2292,17 +2292,17 @@ uint16_t APIConnection::dispatch_message_(const DeferredBatch::BatchItem &item, uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { ListEntitiesDoneResponse resp; - return encode_message_to_buffer(resp, ListEntitiesDoneResponse::MESSAGE_TYPE, conn, remaining_size); + return encode_message_to_buffer(resp, conn, remaining_size); } uint16_t APIConnection::try_send_disconnect_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { DisconnectRequest req; - return encode_message_to_buffer(req, DisconnectRequest::MESSAGE_TYPE, conn, remaining_size); + return encode_message_to_buffer(req, conn, remaining_size); } uint16_t APIConnection::try_send_ping_request(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { PingRequest req; - return encode_message_to_buffer(req, PingRequest::MESSAGE_TYPE, conn, remaining_size); + return encode_message_to_buffer(req, conn, remaining_size); } #ifdef USE_API_HOMEASSISTANT_STATES @@ -2321,7 +2321,7 @@ void APIConnection::process_state_subscriptions_() { resp.attribute = it.attribute != nullptr ? StringRef(it.attribute) : StringRef(""); resp.once = it.once; - if (this->send_message(resp, SubscribeHomeAssistantStateResponse::MESSAGE_TYPE)) { + if (this->send_message(resp)) { this->state_subs_at_++; } } diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 2c66a194a6..54b6db6800 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -129,7 +129,7 @@ class APIConnection final : public APIServerConnectionBase { void send_homeassistant_action(const HomeassistantActionRequest &call) { if (!this->flags_.service_call_subscription) return; - this->send_message(call, HomeassistantActionRequest::MESSAGE_TYPE); + this->send_message(call); } #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES void on_homeassistant_action_response(const HomeassistantActionResponse &msg) override; @@ -153,7 +153,7 @@ class APIConnection final : public APIServerConnectionBase { #ifdef USE_HOMEASSISTANT_TIME void send_time_request() { GetTimeRequest req; - this->send_message(req, GetTimeRequest::MESSAGE_TYPE); + this->send_message(req); } #endif @@ -263,7 +263,19 @@ class APIConnection final : public APIServerConnectionBase { void on_fatal_error() override; void on_no_setup_connection() override; - bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) override; + + // Function pointer type for type-erased message encoding + using MessageEncodeFn = void (*)(const void *, ProtoWriteBuffer &); + // Function pointer type for type-erased size calculation + using CalculateSizeFn = uint32_t (*)(const void *); + + template<typename T> bool send_message(const T &msg) { + if constexpr (T::ESTIMATED_SIZE == 0) { + return this->send_message_(0, T::MESSAGE_TYPE, &encode_msg_noop, &msg); + } else { + return this->send_message_(msg.calculate_size(), T::MESSAGE_TYPE, &proto_encode_msg<T>, &msg); + } + } void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) { shared_buf.clear(); @@ -318,28 +330,68 @@ class APIConnection final : public APIServerConnectionBase { void process_state_subscriptions_(); #endif - // Non-template helper to encode any ProtoMessage - static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint8_t message_type, APIConnection *conn, - uint32_t remaining_size); - - // Helper to fill entity state base and encode message - static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size) { - msg.key = entity->get_object_id_hash(); -#ifdef USE_DEVICES - msg.device_id = entity->get_device_id(); -#endif - return encode_message_to_buffer(msg, message_type, conn, remaining_size); + // Size thunk — converts void* back to concrete type for direct calculate_size() call + template<typename T> static uint32_t calc_size(const void *msg) { + return static_cast<const T *>(msg)->calculate_size(); } - // Helper to fill entity info base and encode message - static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size); + // Shared no-op encode thunk for empty messages (ESTIMATED_SIZE == 0) + static void encode_msg_noop(const void *, ProtoWriteBuffer &) {} - // Wrapper for entity types that have a device_class field + // Non-template buffer management for send_message + bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg); + + // Non-template buffer management for batch encoding + static uint16_t encode_to_buffer(uint32_t calculated_size, MessageEncodeFn encode_fn, const void *msg, + APIConnection *conn, uint32_t remaining_size); + + // Thin template wrapper — computes size, delegates buffer work to non-template helper + template<typename T> static uint16_t encode_message_to_buffer(T &msg, APIConnection *conn, uint32_t remaining_size) { + if constexpr (T::ESTIMATED_SIZE == 0) { + return encode_to_buffer(0, &encode_msg_noop, &msg, conn, remaining_size); + } else { + return encode_to_buffer(msg.calculate_size(), &proto_encode_msg<T>, &msg, conn, remaining_size); + } + } + + // Non-template core — fills state fields and encodes + static uint16_t fill_and_encode_entity_state(EntityBase *entity, StateResponseProtoMessage &msg, + CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn, + uint32_t remaining_size); + + // Thin template wrapper + template<typename T> + static uint16_t fill_and_encode_entity_state(EntityBase *entity, T &msg, APIConnection *conn, + uint32_t remaining_size) { + return fill_and_encode_entity_state(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size); + } + + // Non-template core — fills info fields, allocates buffers, and encodes + static uint16_t fill_and_encode_entity_info(EntityBase *entity, InfoResponseProtoMessage &msg, + CalculateSizeFn size_fn, MessageEncodeFn encode_fn, APIConnection *conn, + uint32_t remaining_size); + + // Thin template wrapper + template<typename T> + static uint16_t fill_and_encode_entity_info(EntityBase *entity, T &msg, APIConnection *conn, + uint32_t remaining_size) { + return fill_and_encode_entity_info(entity, msg, &calc_size<T>, &proto_encode_msg<T>, conn, remaining_size); + } + + // Non-template core — fills device_class, then delegates to fill_and_encode_entity_info static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, InfoResponseProtoMessage &msg, - StringRef &device_class_field, uint8_t message_type, - APIConnection *conn, uint32_t remaining_size); + StringRef &device_class_field, CalculateSizeFn size_fn, + MessageEncodeFn encode_fn, APIConnection *conn, + uint32_t remaining_size); + + // Thin template wrapper + template<typename T> + static uint16_t fill_and_encode_entity_info_with_device_class(EntityBase *entity, T &msg, + StringRef &device_class_field, APIConnection *conn, + uint32_t remaining_size) { + return fill_and_encode_entity_info_with_device_class(entity, msg, device_class_field, &calc_size<T>, + &proto_encode_msg<T>, conn, remaining_size); + } #ifdef USE_VOICE_ASSISTANT // Helper to check voice assistant validity and connection ownership diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 9e74d5ddc7..d8703aa416 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -37,20 +37,24 @@ void HelloResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(3, this->server_info); buffer.encode_string(4, this->name); } -void HelloResponse::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->api_version_major); - size.add_uint32(1, this->api_version_minor); - size.add_length(1, this->server_info.size()); - size.add_length(1, this->name.size()); +uint32_t HelloResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->api_version_major); + size += ProtoSize::calc_uint32(1, this->api_version_minor); + size += ProtoSize::calc_length(1, this->server_info.size()); + size += ProtoSize::calc_length(1, this->name.size()); + return size; } #ifdef USE_AREAS void AreaInfo::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->area_id); buffer.encode_string(2, this->name); } -void AreaInfo::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->area_id); - size.add_length(1, this->name.size()); +uint32_t AreaInfo::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->area_id); + size += ProtoSize::calc_length(1, this->name.size()); + return size; } #endif #ifdef USE_DEVICES @@ -59,10 +63,12 @@ void DeviceInfo::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(2, this->name); buffer.encode_uint32(3, this->area_id); } -void DeviceInfo::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->device_id); - size.add_length(1, this->name.size()); - size.add_uint32(1, this->area_id); +uint32_t DeviceInfo::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->device_id); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_uint32(1, this->area_id); + return size; } #endif void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { @@ -120,60 +126,62 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(24, this->zwave_home_id); #endif } -void DeviceInfoResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->name.size()); - size.add_length(1, this->mac_address.size()); - size.add_length(1, this->esphome_version.size()); - size.add_length(1, this->compilation_time.size()); - size.add_length(1, this->model.size()); +uint32_t DeviceInfoResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_length(1, this->mac_address.size()); + size += ProtoSize::calc_length(1, this->esphome_version.size()); + size += ProtoSize::calc_length(1, this->compilation_time.size()); + size += ProtoSize::calc_length(1, this->model.size()); #ifdef USE_DEEP_SLEEP - size.add_bool(1, this->has_deep_sleep); + size += ProtoSize::calc_bool(1, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - size.add_length(1, this->project_name.size()); + size += ProtoSize::calc_length(1, this->project_name.size()); #endif #ifdef ESPHOME_PROJECT_NAME - size.add_length(1, this->project_version.size()); + size += ProtoSize::calc_length(1, this->project_version.size()); #endif #ifdef USE_WEBSERVER - size.add_uint32(1, this->webserver_port); + size += ProtoSize::calc_uint32(1, this->webserver_port); #endif #ifdef USE_BLUETOOTH_PROXY - size.add_uint32(1, this->bluetooth_proxy_feature_flags); + size += ProtoSize::calc_uint32(1, this->bluetooth_proxy_feature_flags); #endif - size.add_length(1, this->manufacturer.size()); - size.add_length(1, this->friendly_name.size()); + size += ProtoSize::calc_length(1, this->manufacturer.size()); + size += ProtoSize::calc_length(1, this->friendly_name.size()); #ifdef USE_VOICE_ASSISTANT - size.add_uint32(2, this->voice_assistant_feature_flags); + size += ProtoSize::calc_uint32(2, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - size.add_length(2, this->suggested_area.size()); + size += ProtoSize::calc_length(2, this->suggested_area.size()); #endif #ifdef USE_BLUETOOTH_PROXY - size.add_length(2, this->bluetooth_mac_address.size()); + size += ProtoSize::calc_length(2, this->bluetooth_mac_address.size()); #endif #ifdef USE_API_NOISE - size.add_bool(2, this->api_encryption_supported); + size += ProtoSize::calc_bool(2, this->api_encryption_supported); #endif #ifdef USE_DEVICES for (const auto &it : this->devices) { - size.add_message_object_force(2, it); + size += ProtoSize::calc_message_force(2, it.calculate_size()); } #endif #ifdef USE_AREAS for (const auto &it : this->areas) { - size.add_message_object_force(2, it); + size += ProtoSize::calc_message_force(2, it.calculate_size()); } #endif #ifdef USE_AREAS - size.add_message_object(2, this->area); + size += ProtoSize::calc_message(2, this->area.calculate_size()); #endif #ifdef USE_ZWAVE_PROXY - size.add_uint32(2, this->zwave_proxy_feature_flags); + size += ProtoSize::calc_uint32(2, this->zwave_proxy_feature_flags); #endif #ifdef USE_ZWAVE_PROXY - size.add_uint32(2, this->zwave_home_id); + size += ProtoSize::calc_uint32(2, this->zwave_home_id); #endif + return size; } #ifdef USE_BINARY_SENSOR void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { @@ -191,20 +199,22 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesBinarySensorResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); - size.add_length(1, this->device_class.size()); - size.add_bool(1, this->is_status_binary_sensor); - size.add_bool(1, this->disabled_by_default); +uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->is_status_binary_sensor); + size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -214,13 +224,15 @@ void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void BinarySensorStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->state); - size.add_bool(1, this->missing_state); +uint32_t BinarySensorStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->state); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } #endif #ifdef USE_COVER @@ -242,23 +254,25 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(13, this->device_id); #endif } -void ListEntitiesCoverResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); - size.add_bool(1, this->assumed_state); - size.add_bool(1, this->supports_position); - size.add_bool(1, this->supports_tilt); - size.add_length(1, this->device_class.size()); - size.add_bool(1, this->disabled_by_default); +uint32_t ListEntitiesCoverResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_bool(1, this->assumed_state); + size += ProtoSize::calc_bool(1, this->supports_position); + size += ProtoSize::calc_bool(1, this->supports_tilt); + size += ProtoSize::calc_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_bool(1, this->supports_stop); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->supports_stop); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -269,14 +283,16 @@ void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void CoverStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_float(1, this->position); - size.add_float(1, this->tilt); - size.add_uint32(1, static_cast<uint32_t>(this->current_operation)); +uint32_t CoverStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_float(1, this->position); + size += ProtoSize::calc_float(1, this->tilt); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool CoverCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -337,27 +353,29 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(13, this->device_id); #endif } -void ListEntitiesFanResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); - size.add_bool(1, this->supports_oscillation); - size.add_bool(1, this->supports_speed); - size.add_bool(1, this->supports_direction); - size.add_int32(1, this->supported_speed_count); - size.add_bool(1, this->disabled_by_default); +uint32_t ListEntitiesFanResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_bool(1, this->supports_oscillation); + size += ProtoSize::calc_bool(1, this->supports_speed); + size += ProtoSize::calc_bool(1, this->supports_direction); + size += ProtoSize::calc_int32(1, this->supported_speed_count); + size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); if (!this->supported_preset_modes->empty()) { for (const char *it : *this->supported_preset_modes) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -370,16 +388,18 @@ void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void FanStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->state); - size.add_bool(1, this->oscillating); - size.add_uint32(1, static_cast<uint32_t>(this->direction)); - size.add_int32(1, this->speed_level); - size.add_length(1, this->preset_mode.size()); +uint32_t FanStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->state); + size += ProtoSize::calc_bool(1, this->oscillating); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->direction)); + size += ProtoSize::calc_int32(1, this->speed_level); + size += ProtoSize::calc_length(1, this->preset_mode.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool FanCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -464,30 +484,32 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(16, this->device_id); #endif } -void ListEntitiesLightResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesLightResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); if (!this->supported_color_modes->empty()) { for (const auto &it : *this->supported_color_modes) { - size.add_uint32_force(1, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); } } - size.add_float(1, this->min_mireds); - size.add_float(1, this->max_mireds); + size += ProtoSize::calc_float(1, this->min_mireds); + size += ProtoSize::calc_float(1, this->max_mireds); if (!this->effects->empty()) { for (const char *it : *this->effects) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } - size.add_bool(1, this->disabled_by_default); + size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(2, this->device_id); + size += ProtoSize::calc_uint32(2, this->device_id); #endif + return size; } void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -507,23 +529,25 @@ void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void LightStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->state); - size.add_float(1, this->brightness); - size.add_uint32(1, static_cast<uint32_t>(this->color_mode)); - size.add_float(1, this->color_brightness); - size.add_float(1, this->red); - size.add_float(1, this->green); - size.add_float(1, this->blue); - size.add_float(1, this->white); - size.add_float(1, this->color_temperature); - size.add_float(1, this->cold_white); - size.add_float(1, this->warm_white); - size.add_length(1, this->effect.size()); +uint32_t LightStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->state); + size += ProtoSize::calc_float(1, this->brightness); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->color_mode)); + size += ProtoSize::calc_float(1, this->color_brightness); + size += ProtoSize::calc_float(1, this->red); + size += ProtoSize::calc_float(1, this->green); + size += ProtoSize::calc_float(1, this->blue); + size += ProtoSize::calc_float(1, this->white); + size += ProtoSize::calc_float(1, this->color_temperature); + size += ProtoSize::calc_float(1, this->cold_white); + size += ProtoSize::calc_float(1, this->warm_white); + size += ProtoSize::calc_length(1, this->effect.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool LightCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -653,23 +677,25 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void ListEntitiesSensorResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesSensorResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_length(1, this->unit_of_measurement.size()); - size.add_int32(1, this->accuracy_decimals); - size.add_bool(1, this->force_update); - size.add_length(1, this->device_class.size()); - size.add_uint32(1, static_cast<uint32_t>(this->state_class)); - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->unit_of_measurement.size()); + size += ProtoSize::calc_int32(1, this->accuracy_decimals); + size += ProtoSize::calc_bool(1, this->force_update); + size += ProtoSize::calc_length(1, this->device_class.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state_class)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -679,13 +705,15 @@ void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void SensorStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_float(1, this->state); - size.add_bool(1, this->missing_state); +uint32_t SensorStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_float(1, this->state); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } #endif #ifdef USE_SWITCH @@ -704,20 +732,22 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesSwitchResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesSwitchResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->assumed_state); - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->assumed_state); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -726,12 +756,14 @@ void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void SwitchStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->state); +uint32_t SwitchStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool SwitchCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -774,19 +806,21 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesTextSensorResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesTextSensorResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -796,13 +830,15 @@ void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void TextSensorStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_length(1, this->state.size()); - size.add_bool(1, this->missing_state); +uint32_t TextSensorStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->state.size()); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } #endif bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { @@ -822,9 +858,11 @@ void SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->level)); buffer.encode_bytes(3, this->message_ptr_, this->message_len_); } -void SubscribeLogsResponse::calculate_size(ProtoSize &size) const { - size.add_uint32(1, static_cast<uint32_t>(this->level)); - size.add_length(1, this->message_len_); +uint32_t SubscribeLogsResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->level)); + size += ProtoSize::calc_length(1, this->message_len_); + return size; } #ifdef USE_API_NOISE bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { @@ -840,16 +878,22 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD return true; } void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } -void NoiseEncryptionSetKeyResponse::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } +uint32_t NoiseEncryptionSetKeyResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_bool(1, this->success); + return size; +} #endif #ifdef USE_API_HOMEASSISTANT_SERVICES void HomeassistantServiceMap::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->key); buffer.encode_string(2, this->value); } -void HomeassistantServiceMap::calculate_size(ProtoSize &size) const { - size.add_length(1, this->key.size()); - size.add_length(1, this->value.size()); +uint32_t HomeassistantServiceMap::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->key.size()); + size += ProtoSize::calc_length(1, this->value.size()); + return size; } void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->service); @@ -873,21 +917,35 @@ void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(8, this->response_template); #endif } -void HomeassistantActionRequest::calculate_size(ProtoSize &size) const { - size.add_length(1, this->service.size()); - size.add_repeated_message(1, this->data); - size.add_repeated_message(1, this->data_template); - size.add_repeated_message(1, this->variables); - size.add_bool(1, this->is_event); +uint32_t HomeassistantActionRequest::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->service.size()); + if (!this->data.empty()) { + for (const auto &it : this->data) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + if (!this->data_template.empty()) { + for (const auto &it : this->data_template) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + if (!this->variables.empty()) { + for (const auto &it : this->variables) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + size += ProtoSize::calc_bool(1, this->is_event); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - size.add_uint32(1, this->call_id); + size += ProtoSize::calc_uint32(1, this->call_id); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - size.add_bool(1, this->wants_response); + size += ProtoSize::calc_bool(1, this->wants_response); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - size.add_length(1, this->response_template.size()); + size += ProtoSize::calc_length(1, this->response_template.size()); #endif + return size; } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES @@ -929,10 +987,12 @@ void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer &buffer) const buffer.encode_string(2, this->attribute); buffer.encode_bool(3, this->once); } -void SubscribeHomeAssistantStateResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->entity_id.size()); - size.add_length(1, this->attribute.size()); - size.add_bool(1, this->once); +uint32_t SubscribeHomeAssistantStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->entity_id.size()); + size += ProtoSize::calc_length(1, this->attribute.size()); + size += ProtoSize::calc_bool(1, this->once); + return size; } bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { @@ -1034,9 +1094,11 @@ void ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); buffer.encode_uint32(2, static_cast<uint32_t>(this->type)); } -void ListEntitiesServicesArgument::calculate_size(ProtoSize &size) const { - size.add_length(1, this->name.size()); - size.add_uint32(1, static_cast<uint32_t>(this->type)); +uint32_t ListEntitiesServicesArgument::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); + return size; } void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); @@ -1046,11 +1108,17 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { } buffer.encode_uint32(4, static_cast<uint32_t>(this->supports_response)); } -void ListEntitiesServicesResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->name.size()); - size.add_fixed32(1, this->key); - size.add_repeated_message(1, this->args); - size.add_uint32(1, static_cast<uint32_t>(this->supports_response)); +uint32_t ListEntitiesServicesResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_fixed32(1, this->key); + if (!this->args.empty()) { + for (const auto &it : this->args) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->supports_response)); + return size; } bool ExecuteServiceArgument::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1165,13 +1233,15 @@ void ExecuteServiceResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(4, this->response_data, this->response_data_len); #endif } -void ExecuteServiceResponse::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->call_id); - size.add_bool(1, this->success); - size.add_length(1, this->error_message.size()); +uint32_t ExecuteServiceResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->call_id); + size += ProtoSize::calc_bool(1, this->success); + size += ProtoSize::calc_length(1, this->error_message.size()); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - size.add_length(1, this->response_data_len); + size += ProtoSize::calc_length(1, this->response_data_len); #endif + return size; } #endif #ifdef USE_CAMERA @@ -1188,18 +1258,20 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesCameraResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); - size.add_bool(1, this->disabled_by_default); +uint32_t ListEntitiesCameraResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1209,13 +1281,15 @@ void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void CameraImageResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_length(1, this->data_len_); - size.add_bool(1, this->done); +uint32_t CameraImageResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->data_len_); + size += ProtoSize::calc_bool(1, this->done); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool CameraImageRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1275,60 +1349,62 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer) const { #endif buffer.encode_uint32(27, this->feature_flags); } -void ListEntitiesClimateResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); - size.add_bool(1, this->supports_current_temperature); - size.add_bool(1, this->supports_two_point_target_temperature); +uint32_t ListEntitiesClimateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_bool(1, this->supports_current_temperature); + size += ProtoSize::calc_bool(1, this->supports_two_point_target_temperature); if (!this->supported_modes->empty()) { for (const auto &it : *this->supported_modes) { - size.add_uint32_force(1, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); } } - size.add_float(1, this->visual_min_temperature); - size.add_float(1, this->visual_max_temperature); - size.add_float(1, this->visual_target_temperature_step); - size.add_bool(1, this->supports_action); + size += ProtoSize::calc_float(1, this->visual_min_temperature); + size += ProtoSize::calc_float(1, this->visual_max_temperature); + size += ProtoSize::calc_float(1, this->visual_target_temperature_step); + size += ProtoSize::calc_bool(1, this->supports_action); if (!this->supported_fan_modes->empty()) { for (const auto &it : *this->supported_fan_modes) { - size.add_uint32_force(1, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); } } if (!this->supported_swing_modes->empty()) { for (const auto &it : *this->supported_swing_modes) { - size.add_uint32_force(1, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); } } if (!this->supported_custom_fan_modes->empty()) { for (const char *it : *this->supported_custom_fan_modes) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } if (!this->supported_presets->empty()) { for (const auto &it : *this->supported_presets) { - size.add_uint32_force(2, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(2, static_cast<uint32_t>(it)); } } if (!this->supported_custom_presets->empty()) { for (const char *it : *this->supported_custom_presets) { - size.add_length_force(2, strlen(it)); + size += ProtoSize::calc_length_force(2, strlen(it)); } } - size.add_bool(2, this->disabled_by_default); + size += ProtoSize::calc_bool(2, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size.add_length(2, this->icon.size()); + size += ProtoSize::calc_length(2, this->icon.size()); #endif - size.add_uint32(2, static_cast<uint32_t>(this->entity_category)); - size.add_float(2, this->visual_current_temperature_step); - size.add_bool(2, this->supports_current_humidity); - size.add_bool(2, this->supports_target_humidity); - size.add_float(2, this->visual_min_humidity); - size.add_float(2, this->visual_max_humidity); + size += ProtoSize::calc_uint32(2, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_float(2, this->visual_current_temperature_step); + size += ProtoSize::calc_bool(2, this->supports_current_humidity); + size += ProtoSize::calc_bool(2, this->supports_target_humidity); + size += ProtoSize::calc_float(2, this->visual_min_humidity); + size += ProtoSize::calc_float(2, this->visual_max_humidity); #ifdef USE_DEVICES - size.add_uint32(2, this->device_id); + size += ProtoSize::calc_uint32(2, this->device_id); #endif - size.add_uint32(2, this->feature_flags); + size += ProtoSize::calc_uint32(2, this->feature_flags); + return size; } void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1349,24 +1425,26 @@ void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(16, this->device_id); #endif } -void ClimateStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_uint32(1, static_cast<uint32_t>(this->mode)); - size.add_float(1, this->current_temperature); - size.add_float(1, this->target_temperature); - size.add_float(1, this->target_temperature_low); - size.add_float(1, this->target_temperature_high); - size.add_uint32(1, static_cast<uint32_t>(this->action)); - size.add_uint32(1, static_cast<uint32_t>(this->fan_mode)); - size.add_uint32(1, static_cast<uint32_t>(this->swing_mode)); - size.add_length(1, this->custom_fan_mode.size()); - size.add_uint32(1, static_cast<uint32_t>(this->preset)); - size.add_length(1, this->custom_preset.size()); - size.add_float(1, this->current_humidity); - size.add_float(1, this->target_humidity); +uint32_t ClimateStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += ProtoSize::calc_float(1, this->current_temperature); + size += ProtoSize::calc_float(1, this->target_temperature); + size += ProtoSize::calc_float(1, this->target_temperature_low); + size += ProtoSize::calc_float(1, this->target_temperature_high); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->action)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->fan_mode)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->swing_mode)); + size += ProtoSize::calc_length(1, this->custom_fan_mode.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->preset)); + size += ProtoSize::calc_length(1, this->custom_preset.size()); + size += ProtoSize::calc_float(1, this->current_humidity); + size += ProtoSize::calc_float(1, this->target_humidity); #ifdef USE_DEVICES - size.add_uint32(2, this->device_id); + size += ProtoSize::calc_uint32(2, this->device_id); #endif + return size; } bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1481,27 +1559,29 @@ void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer) const { } buffer.encode_uint32(12, this->supported_features); } -void ListEntitiesWaterHeaterResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif - size.add_float(1, this->min_temperature); - size.add_float(1, this->max_temperature); - size.add_float(1, this->target_temperature_step); + size += ProtoSize::calc_float(1, this->min_temperature); + size += ProtoSize::calc_float(1, this->max_temperature); + size += ProtoSize::calc_float(1, this->target_temperature_step); if (!this->supported_modes->empty()) { for (const auto &it : *this->supported_modes) { - size.add_uint32_force(1, static_cast<uint32_t>(it)); + size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); } } - size.add_uint32(1, this->supported_features); + size += ProtoSize::calc_uint32(1, this->supported_features); + return size; } void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1515,17 +1595,19 @@ void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_float(7, this->target_temperature_low); buffer.encode_float(8, this->target_temperature_high); } -void WaterHeaterStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_float(1, this->current_temperature); - size.add_float(1, this->target_temperature); - size.add_uint32(1, static_cast<uint32_t>(this->mode)); +uint32_t WaterHeaterStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_float(1, this->current_temperature); + size += ProtoSize::calc_float(1, this->target_temperature); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif - size.add_uint32(1, this->state); - size.add_float(1, this->target_temperature_low); - size.add_float(1, this->target_temperature_high); + size += ProtoSize::calc_uint32(1, this->state); + size += ProtoSize::calc_float(1, this->target_temperature_low); + size += ProtoSize::calc_float(1, this->target_temperature_high); + return size; } bool WaterHeaterCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1588,24 +1670,26 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(14, this->device_id); #endif } -void ListEntitiesNumberResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesNumberResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_float(1, this->min_value); - size.add_float(1, this->max_value); - size.add_float(1, this->step); - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->unit_of_measurement.size()); - size.add_uint32(1, static_cast<uint32_t>(this->mode)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_float(1, this->min_value); + size += ProtoSize::calc_float(1, this->max_value); + size += ProtoSize::calc_float(1, this->step); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->unit_of_measurement.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1615,13 +1699,15 @@ void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void NumberStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_float(1, this->state); - size.add_bool(1, this->missing_state); +uint32_t NumberStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_float(1, this->state); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool NumberCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1666,23 +1752,25 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesSelectResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesSelectResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif if (!this->options->empty()) { for (const char *it : *this->options) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1692,13 +1780,15 @@ void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void SelectStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_length(1, this->state.size()); - size.add_bool(1, this->missing_state); +uint32_t SelectStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->state.size()); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool SelectCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1753,25 +1843,27 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(11, this->device_id); #endif } -void ListEntitiesSirenResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesSirenResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); + size += ProtoSize::calc_bool(1, this->disabled_by_default); if (!this->tones->empty()) { for (const char *it : *this->tones) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } - size.add_bool(1, this->supports_duration); - size.add_bool(1, this->supports_volume); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->supports_duration); + size += ProtoSize::calc_bool(1, this->supports_volume); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1780,12 +1872,14 @@ void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void SirenStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->state); +uint32_t SirenStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool SirenCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1860,22 +1954,24 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesLockResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesLockResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_bool(1, this->assumed_state); - size.add_bool(1, this->supports_open); - size.add_bool(1, this->requires_code); - size.add_length(1, this->code_format.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->assumed_state); + size += ProtoSize::calc_bool(1, this->supports_open); + size += ProtoSize::calc_bool(1, this->requires_code); + size += ProtoSize::calc_length(1, this->code_format.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -1884,12 +1980,14 @@ void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void LockStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_uint32(1, static_cast<uint32_t>(this->state)); +uint32_t LockStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool LockCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1946,19 +2044,21 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesButtonResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesButtonResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool ButtonCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -1991,12 +2091,14 @@ void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, static_cast<uint32_t>(this->purpose)); buffer.encode_uint32(5, this->sample_bytes); } -void MediaPlayerSupportedFormat::calculate_size(ProtoSize &size) const { - size.add_length(1, this->format.size()); - size.add_uint32(1, this->sample_rate); - size.add_uint32(1, this->num_channels); - size.add_uint32(1, static_cast<uint32_t>(this->purpose)); - size.add_uint32(1, this->sample_bytes); +uint32_t MediaPlayerSupportedFormat::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->format.size()); + size += ProtoSize::calc_uint32(1, this->sample_rate); + size += ProtoSize::calc_uint32(1, this->num_channels); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->purpose)); + size += ProtoSize::calc_uint32(1, this->sample_bytes); + return size; } void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); @@ -2016,21 +2118,27 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { #endif buffer.encode_uint32(11, this->feature_flags); } -void ListEntitiesMediaPlayerResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_bool(1, this->supports_pause); - size.add_repeated_message(1, this->supported_formats); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->supports_pause); + if (!this->supported_formats.empty()) { + for (const auto &it : this->supported_formats) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif - size.add_uint32(1, this->feature_flags); + size += ProtoSize::calc_uint32(1, this->feature_flags); + return size; } void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -2041,14 +2149,16 @@ void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(5, this->device_id); #endif } -void MediaPlayerStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_uint32(1, static_cast<uint32_t>(this->state)); - size.add_float(1, this->volume); - size.add_bool(1, this->muted); +uint32_t MediaPlayerStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); + size += ProtoSize::calc_float(1, this->volume); + size += ProtoSize::calc_bool(1, this->muted); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2122,21 +2232,25 @@ void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->address_type); buffer.encode_bytes(4, this->data, this->data_len); } -void BluetoothLERawAdvertisement::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_sint32(1, this->rssi); - size.add_uint32(1, this->address_type); - size.add_length(1, this->data_len); +uint32_t BluetoothLERawAdvertisement::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_sint32(1, this->rssi); + size += ProtoSize::calc_uint32(1, this->address_type); + size += ProtoSize::calc_length(1, this->data_len); + return size; } void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { for (uint16_t i = 0; i < this->advertisements_len; i++) { buffer.encode_message(1, this->advertisements[i]); } } -void BluetoothLERawAdvertisementsResponse::calculate_size(ProtoSize &size) const { +uint32_t BluetoothLERawAdvertisementsResponse::calculate_size() const { + uint32_t size = 0; for (uint16_t i = 0; i < this->advertisements_len; i++) { - size.add_message_object_force(1, this->advertisements[i]); + size += ProtoSize::calc_message_force(1, this->advertisements[i].calculate_size()); } + return size; } bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2163,11 +2277,13 @@ void BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->mtu); buffer.encode_int32(4, this->error); } -void BluetoothDeviceConnectionResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_bool(1, this->connected); - size.add_uint32(1, this->mtu); - size.add_int32(1, this->error); +uint32_t BluetoothDeviceConnectionResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_bool(1, this->connected); + size += ProtoSize::calc_uint32(1, this->mtu); + size += ProtoSize::calc_int32(1, this->error); + return size; } bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2187,13 +2303,15 @@ void BluetoothGATTDescriptor::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_uint32(3, this->short_uuid); } -void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const { +uint32_t BluetoothGATTDescriptor::calculate_size() const { + uint32_t size = 0; if (this->uuid[0] != 0 || this->uuid[1] != 0) { - size.add_uint64_force(1, this->uuid[0]); - size.add_uint64_force(1, this->uuid[1]); + size += ProtoSize::calc_uint64_force(1, this->uuid[0]); + size += ProtoSize::calc_uint64_force(1, this->uuid[1]); } - size.add_uint32(1, this->handle); - size.add_uint32(1, this->short_uuid); + size += ProtoSize::calc_uint32(1, this->handle); + size += ProtoSize::calc_uint32(1, this->short_uuid); + return size; } void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const { if (this->uuid[0] != 0 || this->uuid[1] != 0) { @@ -2207,15 +2325,21 @@ void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const { } buffer.encode_uint32(5, this->short_uuid); } -void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const { +uint32_t BluetoothGATTCharacteristic::calculate_size() const { + uint32_t size = 0; if (this->uuid[0] != 0 || this->uuid[1] != 0) { - size.add_uint64_force(1, this->uuid[0]); - size.add_uint64_force(1, this->uuid[1]); + size += ProtoSize::calc_uint64_force(1, this->uuid[0]); + size += ProtoSize::calc_uint64_force(1, this->uuid[1]); } - size.add_uint32(1, this->handle); - size.add_uint32(1, this->properties); - size.add_repeated_message(1, this->descriptors); - size.add_uint32(1, this->short_uuid); + size += ProtoSize::calc_uint32(1, this->handle); + size += ProtoSize::calc_uint32(1, this->properties); + if (!this->descriptors.empty()) { + for (const auto &it : this->descriptors) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + size += ProtoSize::calc_uint32(1, this->short_uuid); + return size; } void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const { if (this->uuid[0] != 0 || this->uuid[1] != 0) { @@ -2228,14 +2352,20 @@ void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const { } buffer.encode_uint32(4, this->short_uuid); } -void BluetoothGATTService::calculate_size(ProtoSize &size) const { +uint32_t BluetoothGATTService::calculate_size() const { + uint32_t size = 0; if (this->uuid[0] != 0 || this->uuid[1] != 0) { - size.add_uint64_force(1, this->uuid[0]); - size.add_uint64_force(1, this->uuid[1]); + size += ProtoSize::calc_uint64_force(1, this->uuid[0]); + size += ProtoSize::calc_uint64_force(1, this->uuid[1]); } - size.add_uint32(1, this->handle); - size.add_repeated_message(1, this->characteristics); - size.add_uint32(1, this->short_uuid); + size += ProtoSize::calc_uint32(1, this->handle); + if (!this->characteristics.empty()) { + for (const auto &it : this->characteristics) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + size += ProtoSize::calc_uint32(1, this->short_uuid); + return size; } void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); @@ -2243,14 +2373,24 @@ void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_message(2, it); } } -void BluetoothGATTGetServicesResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_repeated_message(1, this->services); +uint32_t BluetoothGATTGetServicesResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + if (!this->services.empty()) { + for (const auto &it : this->services) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); + } + } + return size; } void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); } -void BluetoothGATTGetServicesDoneResponse::calculate_size(ProtoSize &size) const { size.add_uint64(1, this->address); } +uint32_t BluetoothGATTGetServicesDoneResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + return size; +} bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 1: @@ -2269,10 +2409,12 @@ void BluetoothGATTReadResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); } -void BluetoothGATTReadResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_uint32(1, this->handle); - size.add_length(1, this->data_len_); +uint32_t BluetoothGATTReadResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_uint32(1, this->handle); + size += ProtoSize::calc_length(1, this->data_len_); + return size; } bool BluetoothGATTWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2361,10 +2503,12 @@ void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_bytes(3, this->data_ptr_, this->data_len_); } -void BluetoothGATTNotifyDataResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_uint32(1, this->handle); - size.add_length(1, this->data_len_); +uint32_t BluetoothGATTNotifyDataResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_uint32(1, this->handle); + size += ProtoSize::calc_length(1, this->data_len_); + return size; } void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, this->free); @@ -2375,80 +2519,96 @@ void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer) const { } } } -void BluetoothConnectionsFreeResponse::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->free); - size.add_uint32(1, this->limit); +uint32_t BluetoothConnectionsFreeResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->free); + size += ProtoSize::calc_uint32(1, this->limit); for (const auto &it : this->allocated) { if (it != 0) { - size.add_uint64_force(1, it); + size += ProtoSize::calc_uint64_force(1, it); } } + return size; } void BluetoothGATTErrorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); buffer.encode_int32(3, this->error); } -void BluetoothGATTErrorResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_uint32(1, this->handle); - size.add_int32(1, this->error); +uint32_t BluetoothGATTErrorResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_uint32(1, this->handle); + size += ProtoSize::calc_int32(1, this->error); + return size; } void BluetoothGATTWriteResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } -void BluetoothGATTWriteResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_uint32(1, this->handle); +uint32_t BluetoothGATTWriteResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_uint32(1, this->handle); + return size; } void BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_uint32(2, this->handle); } -void BluetoothGATTNotifyResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_uint32(1, this->handle); +uint32_t BluetoothGATTNotifyResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_uint32(1, this->handle); + return size; } void BluetoothDevicePairingResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->paired); buffer.encode_int32(3, this->error); } -void BluetoothDevicePairingResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_bool(1, this->paired); - size.add_int32(1, this->error); +uint32_t BluetoothDevicePairingResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_bool(1, this->paired); + size += ProtoSize::calc_int32(1, this->error); + return size; } void BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); } -void BluetoothDeviceUnpairingResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_bool(1, this->success); - size.add_int32(1, this->error); +uint32_t BluetoothDeviceUnpairingResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_bool(1, this->success); + size += ProtoSize::calc_int32(1, this->error); + return size; } void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); buffer.encode_bool(2, this->success); buffer.encode_int32(3, this->error); } -void BluetoothDeviceClearCacheResponse::calculate_size(ProtoSize &size) const { - size.add_uint64(1, this->address); - size.add_bool(1, this->success); - size.add_int32(1, this->error); +uint32_t BluetoothDeviceClearCacheResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_bool(1, this->success); + size += ProtoSize::calc_int32(1, this->error); + return size; } void BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->state)); buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); buffer.encode_uint32(3, static_cast<uint32_t>(this->configured_mode)); } -void BluetoothScannerStateResponse::calculate_size(ProtoSize &size) const { - size.add_uint32(1, static_cast<uint32_t>(this->state)); - size.add_uint32(1, static_cast<uint32_t>(this->mode)); - size.add_uint32(1, static_cast<uint32_t>(this->configured_mode)); +uint32_t BluetoothScannerStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->configured_mode)); + return size; } bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2480,10 +2640,12 @@ void VoiceAssistantAudioSettings::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(2, this->auto_gain); buffer.encode_float(3, this->volume_multiplier); } -void VoiceAssistantAudioSettings::calculate_size(ProtoSize &size) const { - size.add_uint32(1, this->noise_suppression_level); - size.add_uint32(1, this->auto_gain); - size.add_float(1, this->volume_multiplier); +uint32_t VoiceAssistantAudioSettings::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->noise_suppression_level); + size += ProtoSize::calc_uint32(1, this->auto_gain); + size += ProtoSize::calc_float(1, this->volume_multiplier); + return size; } void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->start); @@ -2492,12 +2654,14 @@ void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_message(4, this->audio_settings, false); buffer.encode_string(5, this->wake_word_phrase); } -void VoiceAssistantRequest::calculate_size(ProtoSize &size) const { - size.add_bool(1, this->start); - size.add_length(1, this->conversation_id.size()); - size.add_uint32(1, this->flags); - size.add_message_object(1, this->audio_settings); - size.add_length(1, this->wake_word_phrase.size()); +uint32_t VoiceAssistantRequest::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_bool(1, this->start); + size += ProtoSize::calc_length(1, this->conversation_id.size()); + size += ProtoSize::calc_uint32(1, this->flags); + size += ProtoSize::calc_message(1, this->audio_settings.calculate_size()); + size += ProtoSize::calc_length(1, this->wake_word_phrase.size()); + return size; } bool VoiceAssistantResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2574,9 +2738,11 @@ void VoiceAssistantAudio::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(1, this->data, this->data_len); buffer.encode_bool(2, this->end); } -void VoiceAssistantAudio::calculate_size(ProtoSize &size) const { - size.add_length(1, this->data_len); - size.add_bool(1, this->end); +uint32_t VoiceAssistantAudio::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->data_len); + size += ProtoSize::calc_bool(1, this->end); + return size; } bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2642,7 +2808,11 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength return true; } void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } -void VoiceAssistantAnnounceFinished::calculate_size(ProtoSize &size) const { size.add_bool(1, this->success); } +uint32_t VoiceAssistantAnnounceFinished::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_bool(1, this->success); + return size; +} void VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->id); buffer.encode_string(2, this->wake_word); @@ -2650,14 +2820,16 @@ void VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(3, it, true); } } -void VoiceAssistantWakeWord::calculate_size(ProtoSize &size) const { - size.add_length(1, this->id.size()); - size.add_length(1, this->wake_word.size()); +uint32_t VoiceAssistantWakeWord::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->id.size()); + size += ProtoSize::calc_length(1, this->wake_word.size()); if (!this->trained_languages.empty()) { for (const auto &it : this->trained_languages) { - size.add_length_force(1, it.size()); + size += ProtoSize::calc_length_force(1, it.size()); } } + return size; } bool VoiceAssistantExternalWakeWord::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2719,14 +2891,20 @@ void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer) const } buffer.encode_uint32(3, this->max_active_wake_words); } -void VoiceAssistantConfigurationResponse::calculate_size(ProtoSize &size) const { - size.add_repeated_message(1, this->available_wake_words); - if (!this->active_wake_words->empty()) { - for (const auto &it : *this->active_wake_words) { - size.add_length_force(1, it.size()); +uint32_t VoiceAssistantConfigurationResponse::calculate_size() const { + uint32_t size = 0; + if (!this->available_wake_words.empty()) { + for (const auto &it : this->available_wake_words) { + size += ProtoSize::calc_message_force(1, it.calculate_size()); } } - size.add_uint32(1, this->max_active_wake_words); + if (!this->active_wake_words->empty()) { + for (const auto &it : *this->active_wake_words) { + size += ProtoSize::calc_length_force(1, it.size()); + } + } + size += ProtoSize::calc_uint32(1, this->max_active_wake_words); + return size; } bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengthDelimited value) { switch (field_id) { @@ -2756,21 +2934,23 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer) con buffer.encode_uint32(11, this->device_id); #endif } -void ListEntitiesAlarmControlPanelResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_uint32(1, this->supported_features); - size.add_bool(1, this->requires_code); - size.add_bool(1, this->requires_code_to_arm); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, this->supported_features); + size += ProtoSize::calc_bool(1, this->requires_code); + size += ProtoSize::calc_bool(1, this->requires_code_to_arm); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -2779,12 +2959,14 @@ void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void AlarmControlPanelStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_uint32(1, static_cast<uint32_t>(this->state)); +uint32_t AlarmControlPanelStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool AlarmControlPanelCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2841,22 +3023,24 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesTextResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesTextResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_uint32(1, this->min_length); - size.add_uint32(1, this->max_length); - size.add_length(1, this->pattern.size()); - size.add_uint32(1, static_cast<uint32_t>(this->mode)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_uint32(1, this->min_length); + size += ProtoSize::calc_uint32(1, this->max_length); + size += ProtoSize::calc_length(1, this->pattern.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -2866,13 +3050,15 @@ void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void TextStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_length(1, this->state.size()); - size.add_bool(1, this->missing_state); +uint32_t TextStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->state.size()); + size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool TextCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -2922,18 +3108,20 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesDateResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesDateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -2945,15 +3133,17 @@ void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void DateStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->missing_state); - size.add_uint32(1, this->year); - size.add_uint32(1, this->month); - size.add_uint32(1, this->day); +uint32_t DateStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->missing_state); + size += ProtoSize::calc_uint32(1, this->year); + size += ProtoSize::calc_uint32(1, this->month); + size += ProtoSize::calc_uint32(1, this->day); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool DateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3001,18 +3191,20 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesTimeResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesTimeResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -3024,15 +3216,17 @@ void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(6, this->device_id); #endif } -void TimeStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->missing_state); - size.add_uint32(1, this->hour); - size.add_uint32(1, this->minute); - size.add_uint32(1, this->second); +uint32_t TimeStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->missing_state); + size += ProtoSize::calc_uint32(1, this->hour); + size += ProtoSize::calc_uint32(1, this->minute); + size += ProtoSize::calc_uint32(1, this->second); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool TimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3084,24 +3278,26 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(10, this->device_id); #endif } -void ListEntitiesEventResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesEventResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); if (!this->event_types->empty()) { for (const char *it : *this->event_types) { - size.add_length_force(1, strlen(it)); + size += ProtoSize::calc_length_force(1, strlen(it)); } } #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void EventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -3110,12 +3306,14 @@ void EventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(3, this->device_id); #endif } -void EventResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_length(1, this->event_type.size()); +uint32_t EventResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->event_type.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } #endif #ifdef USE_VALVE @@ -3136,22 +3334,24 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(12, this->device_id); #endif } -void ListEntitiesValveResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesValveResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); - size.add_bool(1, this->assumed_state); - size.add_bool(1, this->supports_position); - size.add_bool(1, this->supports_stop); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->assumed_state); + size += ProtoSize::calc_bool(1, this->supports_position); + size += ProtoSize::calc_bool(1, this->supports_stop); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -3161,13 +3361,15 @@ void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void ValveStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_float(1, this->position); - size.add_uint32(1, static_cast<uint32_t>(this->current_operation)); +uint32_t ValveStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_float(1, this->position); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool ValveCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3215,18 +3417,20 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(8, this->device_id); #endif } -void ListEntitiesDateTimeResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesDateTimeResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -3236,13 +3440,15 @@ void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(4, this->device_id); #endif } -void DateTimeStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->missing_state); - size.add_fixed32(1, this->epoch_seconds); +uint32_t DateTimeStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->missing_state); + size += ProtoSize::calc_fixed32(1, this->epoch_seconds); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool DateTimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3285,19 +3491,21 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(9, this->device_id); #endif } -void ListEntitiesUpdateResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesUpdateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); - size.add_length(1, this->device_class.size()); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_fixed32(1, this->key); @@ -3314,20 +3522,22 @@ void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(11, this->device_id); #endif } -void UpdateStateResponse::calculate_size(ProtoSize &size) const { - size.add_fixed32(1, this->key); - size.add_bool(1, this->missing_state); - size.add_bool(1, this->in_progress); - size.add_bool(1, this->has_progress); - size.add_float(1, this->progress); - size.add_length(1, this->current_version.size()); - size.add_length(1, this->latest_version.size()); - size.add_length(1, this->title.size()); - size.add_length(1, this->release_summary.size()); - size.add_length(1, this->release_url.size()); +uint32_t UpdateStateResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_bool(1, this->missing_state); + size += ProtoSize::calc_bool(1, this->in_progress); + size += ProtoSize::calc_bool(1, this->has_progress); + size += ProtoSize::calc_float(1, this->progress); + size += ProtoSize::calc_length(1, this->current_version.size()); + size += ProtoSize::calc_length(1, this->latest_version.size()); + size += ProtoSize::calc_length(1, this->title.size()); + size += ProtoSize::calc_length(1, this->release_summary.size()); + size += ProtoSize::calc_length(1, this->release_url.size()); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif + return size; } bool UpdateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { @@ -3369,7 +3579,11 @@ bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited valu return true; } void ZWaveProxyFrame::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(1, this->data, this->data_len); } -void ZWaveProxyFrame::calculate_size(ProtoSize &size) const { size.add_length(1, this->data_len); } +uint32_t ZWaveProxyFrame::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->data_len); + return size; +} bool ZWaveProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { switch (field_id) { case 1: @@ -3396,9 +3610,11 @@ void ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(1, static_cast<uint32_t>(this->type)); buffer.encode_bytes(2, this->data, this->data_len); } -void ZWaveProxyRequest::calculate_size(ProtoSize &size) const { - size.add_uint32(1, static_cast<uint32_t>(this->type)); - size.add_length(1, this->data_len); +uint32_t ZWaveProxyRequest::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); + size += ProtoSize::calc_length(1, this->data_len); + return size; } #endif #ifdef USE_INFRARED @@ -3416,19 +3632,21 @@ void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { #endif buffer.encode_uint32(8, this->capabilities); } -void ListEntitiesInfraredResponse::calculate_size(ProtoSize &size) const { - size.add_length(1, this->object_id.size()); - size.add_fixed32(1, this->key); - size.add_length(1, this->name.size()); +uint32_t ListEntitiesInfraredResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->object_id.size()); + size += ProtoSize::calc_fixed32(1, this->key); + size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON - size.add_length(1, this->icon.size()); + size += ProtoSize::calc_length(1, this->icon.size()); #endif - size.add_bool(1, this->disabled_by_default); - size.add_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += ProtoSize::calc_bool(1, this->disabled_by_default); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif - size.add_uint32(1, this->capabilities); + size += ProtoSize::calc_uint32(1, this->capabilities); + return size; } #endif #ifdef USE_IR_RF @@ -3482,16 +3700,18 @@ void InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer) const { buffer.encode_sint32(3, it, true); } } -void InfraredRFReceiveEvent::calculate_size(ProtoSize &size) const { +uint32_t InfraredRFReceiveEvent::calculate_size() const { + uint32_t size = 0; #ifdef USE_DEVICES - size.add_uint32(1, this->device_id); + size += ProtoSize::calc_uint32(1, this->device_id); #endif - size.add_fixed32(1, this->key); + size += ProtoSize::calc_fixed32(1, this->key); if (!this->timings->empty()) { for (const auto &it : *this->timings) { - size.add_sint32_force(1, it); + size += ProtoSize::calc_sint32_force(1, it); } } + return size; } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a97f6c0a76..89cb1158f3 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -388,8 +388,8 @@ class HelloResponse final : public ProtoMessage { uint32_t api_version_minor{0}; StringRef server_info{}; StringRef name{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -453,8 +453,8 @@ class AreaInfo final : public ProtoMessage { public: uint32_t area_id{0}; StringRef name{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -468,8 +468,8 @@ class DeviceInfo final : public ProtoMessage { uint32_t device_id{0}; StringRef name{}; uint32_t area_id{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -533,8 +533,8 @@ class DeviceInfoResponse final : public ProtoMessage { #ifdef USE_ZWAVE_PROXY uint32_t zwave_home_id{0}; #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -564,8 +564,8 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; bool is_status_binary_sensor{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -581,8 +581,8 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage { #endif bool state{false}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -603,8 +603,8 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage { bool supports_tilt{false}; StringRef device_class{}; bool supports_stop{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -621,8 +621,8 @@ class CoverStateResponse final : public StateResponseProtoMessage { float position{0.0f}; float tilt{0.0f}; enums::CoverOperation current_operation{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -663,8 +663,8 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { bool supports_direction{false}; int32_t supported_speed_count{0}; const std::vector<const char *> *supported_preset_modes{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -683,8 +683,8 @@ class FanStateResponse final : public StateResponseProtoMessage { enums::FanDirection direction{}; int32_t speed_level{0}; StringRef preset_mode{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -730,8 +730,8 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage { float min_mireds{0.0f}; float max_mireds{0.0f}; const FixedVector<const char *> *effects{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -757,8 +757,8 @@ class LightStateResponse final : public StateResponseProtoMessage { float cold_white{0.0f}; float warm_white{0.0f}; StringRef effect{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -821,8 +821,8 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage { bool force_update{false}; StringRef device_class{}; enums::SensorStateClass state_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -838,8 +838,8 @@ class SensorStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -857,8 +857,8 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage { #endif bool assumed_state{false}; StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -873,8 +873,8 @@ class SwitchStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "switch_state_response"; } #endif bool state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -907,8 +907,8 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_text_sensor_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -924,8 +924,8 @@ class TextSensorStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -963,8 +963,8 @@ class SubscribeLogsResponse final : public ProtoMessage { this->message_ptr_ = data; this->message_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -996,8 +996,8 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { const char *message_name() const override { return "noise_encryption_set_key_response"; } #endif bool success{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1010,8 +1010,8 @@ class HomeassistantServiceMap final : public ProtoMessage { public: StringRef key{}; StringRef value{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1039,8 +1039,8 @@ class HomeassistantActionRequest final : public ProtoMessage { #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON StringRef response_template{}; #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1083,8 +1083,8 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage { StringRef entity_id{}; StringRef attribute{}; bool once{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1174,8 +1174,8 @@ class ListEntitiesServicesArgument final : public ProtoMessage { public: StringRef name{}; enums::ServiceArgType type{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1193,8 +1193,8 @@ class ListEntitiesServicesResponse final : public ProtoMessage { uint32_t key{0}; FixedVector<ListEntitiesServicesArgument> args{}; enums::SupportsResponseType supports_response{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1263,8 +1263,8 @@ class ExecuteServiceResponse final : public ProtoMessage { const uint8_t *response_data{nullptr}; uint16_t response_data_len{0}; #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1280,8 +1280,8 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_camera_response"; } #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1302,8 +1302,8 @@ class CameraImageResponse final : public StateResponseProtoMessage { this->data_len_ = len; } bool done{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1353,8 +1353,8 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage { float visual_min_humidity{0.0f}; float visual_max_humidity{0.0f}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1381,8 +1381,8 @@ class ClimateStateResponse final : public StateResponseProtoMessage { StringRef custom_preset{}; float current_humidity{0.0f}; float target_humidity{0.0f}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1439,8 +1439,8 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage { float target_temperature_step{0.0f}; const water_heater::WaterHeaterModeMask *supported_modes{}; uint32_t supported_features{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1460,8 +1460,8 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage { uint32_t state{0}; float target_temperature_low{0.0f}; float target_temperature_high{0.0f}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1504,8 +1504,8 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage { StringRef unit_of_measurement{}; enums::NumberMode mode{}; StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1521,8 +1521,8 @@ class NumberStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1555,8 +1555,8 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_select_response"; } #endif const FixedVector<const char *> *options{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1572,8 +1572,8 @@ class SelectStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1609,8 +1609,8 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage { const FixedVector<const char *> *tones{}; bool supports_duration{false}; bool supports_volume{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1625,8 +1625,8 @@ class SirenStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "siren_state_response"; } #endif bool state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1670,8 +1670,8 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage { bool supports_open{false}; bool requires_code{false}; StringRef code_format{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1686,8 +1686,8 @@ class LockStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "lock_state_response"; } #endif enums::LockState state{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1723,8 +1723,8 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_button_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1755,8 +1755,8 @@ class MediaPlayerSupportedFormat final : public ProtoMessage { uint32_t num_channels{0}; enums::MediaPlayerFormatPurpose purpose{}; uint32_t sample_bytes{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1773,8 +1773,8 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage { bool supports_pause{false}; std::vector<MediaPlayerSupportedFormat> supported_formats{}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1791,8 +1791,8 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage { enums::MediaPlayerState state{}; float volume{0.0f}; bool muted{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1847,8 +1847,8 @@ class BluetoothLERawAdvertisement final : public ProtoMessage { uint32_t address_type{0}; uint8_t data[62]{}; uint8_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1864,8 +1864,8 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage { #endif std::array<BluetoothLERawAdvertisement, BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE> advertisements{}; uint16_t advertisements_len{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1901,8 +1901,8 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage { bool connected{false}; uint32_t mtu{0}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1929,8 +1929,8 @@ class BluetoothGATTDescriptor final : public ProtoMessage { std::array<uint64_t, 2> uuid{}; uint32_t handle{0}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1944,8 +1944,8 @@ class BluetoothGATTCharacteristic final : public ProtoMessage { uint32_t properties{0}; FixedVector<BluetoothGATTDescriptor> descriptors{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1958,8 +1958,8 @@ class BluetoothGATTService final : public ProtoMessage { uint32_t handle{0}; FixedVector<BluetoothGATTCharacteristic> characteristics{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1975,8 +1975,8 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage { #endif uint64_t address{0}; std::vector<BluetoothGATTService> services{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1991,8 +1991,8 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage { const char *message_name() const override { return "bluetooth_gatt_get_services_done_response"; } #endif uint64_t address{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2030,8 +2030,8 @@ class BluetoothGATTReadResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2125,8 +2125,8 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2143,8 +2143,8 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage { uint32_t free{0}; uint32_t limit{0}; std::array<uint64_t, BLUETOOTH_PROXY_MAX_CONNECTIONS> allocated{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2161,8 +2161,8 @@ class BluetoothGATTErrorResponse final : public ProtoMessage { uint64_t address{0}; uint32_t handle{0}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2178,8 +2178,8 @@ class BluetoothGATTWriteResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2195,8 +2195,8 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2213,8 +2213,8 @@ class BluetoothDevicePairingResponse final : public ProtoMessage { uint64_t address{0}; bool paired{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2231,8 +2231,8 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2249,8 +2249,8 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2267,8 +2267,8 @@ class BluetoothScannerStateResponse final : public ProtoMessage { enums::BluetoothScannerState state{}; enums::BluetoothScannerMode mode{}; enums::BluetoothScannerMode configured_mode{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2313,8 +2313,8 @@ class VoiceAssistantAudioSettings final : public ProtoMessage { uint32_t noise_suppression_level{0}; uint32_t auto_gain{0}; float volume_multiplier{0.0f}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2333,8 +2333,8 @@ class VoiceAssistantRequest final : public ProtoMessage { uint32_t flags{0}; VoiceAssistantAudioSettings audio_settings{}; StringRef wake_word_phrase{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2395,8 +2395,8 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { const uint8_t *data{nullptr}; uint16_t data_len{0}; bool end{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2453,8 +2453,8 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage { const char *message_name() const override { return "voice_assistant_announce_finished"; } #endif bool success{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2466,8 +2466,8 @@ class VoiceAssistantWakeWord final : public ProtoMessage { StringRef id{}; StringRef wake_word{}; std::vector<std::string> trained_languages{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2516,8 +2516,8 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage { std::vector<VoiceAssistantWakeWord> available_wake_words{}; const std::vector<std::string> *active_wake_words{}; uint32_t max_active_wake_words{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2551,8 +2551,8 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess uint32_t supported_features{0}; bool requires_code{false}; bool requires_code_to_arm{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2567,8 +2567,8 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "alarm_control_panel_state_response"; } #endif enums::AlarmControlPanelState state{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2606,8 +2606,8 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage { uint32_t max_length{0}; StringRef pattern{}; enums::TextMode mode{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2623,8 +2623,8 @@ class TextStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2657,8 +2657,8 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_date_response"; } #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2676,8 +2676,8 @@ class DateStateResponse final : public StateResponseProtoMessage { uint32_t year{0}; uint32_t month{0}; uint32_t day{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2711,8 +2711,8 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_time_response"; } #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2730,8 +2730,8 @@ class TimeStateResponse final : public StateResponseProtoMessage { uint32_t hour{0}; uint32_t minute{0}; uint32_t second{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2767,8 +2767,8 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; const FixedVector<const char *> *event_types{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2783,8 +2783,8 @@ class EventResponse final : public StateResponseProtoMessage { const char *message_name() const override { return "event_response"; } #endif StringRef event_type{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2804,8 +2804,8 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage { bool assumed_state{false}; bool supports_position{false}; bool supports_stop{false}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2821,8 +2821,8 @@ class ValveStateResponse final : public StateResponseProtoMessage { #endif float position{0.0f}; enums::ValveOperation current_operation{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2856,8 +2856,8 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "list_entities_date_time_response"; } #endif - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2873,8 +2873,8 @@ class DateTimeStateResponse final : public StateResponseProtoMessage { #endif bool missing_state{false}; uint32_t epoch_seconds{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2907,8 +2907,8 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_update_response"; } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2931,8 +2931,8 @@ class UpdateStateResponse final : public StateResponseProtoMessage { StringRef title{}; StringRef release_summary{}; StringRef release_url{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2966,8 +2966,8 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { #endif const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -2985,8 +2985,8 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { enums::ZWaveProxyRequestType type{}; const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -3005,8 +3005,8 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { const char *message_name() const override { return "list_entities_infrared_response"; } #endif uint32_t capabilities{0}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -3052,8 +3052,8 @@ class InfraredRFReceiveEvent final : public ProtoMessage { #endif uint32_t key{0}; const std::vector<int32_t> *timings{}; - void encode(ProtoWriteBuffer &buffer) const override; - void calculate_size(ProtoSize &size) const override; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 1441507406..e70b97196b 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -19,14 +19,6 @@ class APIServerConnectionBase : public ProtoService { public: #endif - bool send_message(const ProtoMessage &msg, uint8_t message_type) { -#ifdef HAS_PROTO_MESSAGE_DUMP - DumpBuffer dump_buf; - this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf)); -#endif - return this->send_message_impl(msg, message_type); - } - virtual void on_hello_request(const HelloRequest &value){}; virtual void on_disconnect_request(){}; diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 0352d7347b..06816fe3e0 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -359,11 +359,11 @@ void APIServer::on_update(update::UpdateEntity *obj) { #endif #ifdef USE_ZWAVE_PROXY -void APIServer::on_zwave_proxy_request(const esphome::api::ProtoMessage &msg) { +void APIServer::on_zwave_proxy_request(const ZWaveProxyRequest &msg) { // We could add code to manage a second subscription type, but, since this message type is // very infrequent and small, we simply send it to all clients for (auto &c : this->clients_) - c->send_message(msg, api::ZWaveProxyRequest::MESSAGE_TYPE); + c->send_message(msg); } #endif @@ -531,7 +531,7 @@ bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString this->set_noise_psk(active_psk); for (auto &c : this->clients_) { DisconnectRequest req; - c->send_message(req, DisconnectRequest::MESSAGE_TYPE); + c->send_message(req); } }); } @@ -631,7 +631,7 @@ void APIServer::on_shutdown() { // Send disconnect requests to all connected clients for (auto &c : this->clients_) { DisconnectRequest req; - if (!c->send_message(req, DisconnectRequest::MESSAGE_TYPE)) { + if (!c->send_message(req)) { // If we can't send the disconnect request directly (tx_buffer full), // schedule it at the front of the batch so it will be sent with priority c->schedule_message_front_(nullptr, DisconnectRequest::MESSAGE_TYPE, DisconnectRequest::ESTIMATED_SIZE); diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 6eff2005f8..e6c10d1595 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -179,7 +179,7 @@ class APIServer : public Component, void on_update(update::UpdateEntity *obj) override; #endif #ifdef USE_ZWAVE_PROXY - void on_zwave_proxy_request(const esphome::api::ProtoMessage &msg); + void on_zwave_proxy_request(const ZWaveProxyRequest &msg); #endif #ifdef USE_IR_RF void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings); diff --git a/esphome/components/api/list_entities.cpp b/esphome/components/api/list_entities.cpp index fe43a47c3b..0a94c1699b 100644 --- a/esphome/components/api/list_entities.cpp +++ b/esphome/components/api/list_entities.cpp @@ -94,7 +94,7 @@ ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(clie #ifdef USE_API_USER_DEFINED_ACTIONS bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) { auto resp = service->encode_list_service_response(); - return this->client_->send_message(resp, ListEntitiesServicesResponse::MESSAGE_TYPE); + return this->client_->send_message(resp); } #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 750fff0810..702208d9de 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -364,7 +364,11 @@ class ProtoWriteBuffer { /// Encode a packed repeated sint32 field (zero-copy from vector) void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values); /// Encode a nested message field (force=true for repeated, false for singular) - void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = true); + /// Templated so concrete message type is preserved for direct encode/calculate_size calls. + template<typename T> void encode_message(uint32_t field_id, const T &value, bool force = true); + // Non-template core for encode_message — all buffer work happens here + void encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value, + void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force); std::vector<uint8_t> *get_buffer() const { return buffer_; } protected: @@ -452,20 +456,20 @@ class DumpBuffer { class ProtoMessage { public: - // Default implementation for messages with no fields - virtual void encode(ProtoWriteBuffer &buffer) const {} - // Default implementation for messages with no fields - virtual void calculate_size(ProtoSize &size) const {} - // Convenience: calculate and return size directly (defined after ProtoSize) - uint32_t calculated_size() const; + // Non-virtual defaults for messages with no fields. + // Concrete message classes hide these with their own implementations. + // All call sites use templates to preserve the concrete type, so virtual + // dispatch is not needed. This eliminates per-message vtable entries for + // encode/calculate_size, saving ~1.3 KB of flash across all message types. + void encode(ProtoWriteBuffer &buffer) const {} + uint32_t calculate_size() const { return 0; } #ifdef HAS_PROTO_MESSAGE_DUMP virtual const char *dump_to(DumpBuffer &out) const = 0; virtual const char *message_name() const { return "unknown"; } #endif protected: - // Non-virtual: messages are never deleted polymorphically. - // Protected prevents accidental `delete base_ptr` (compile error). + // Non-virtual destructor is protected to prevent polymorphic deletion. ~ProtoMessage() = default; }; @@ -494,32 +498,7 @@ class ProtoDecodableMessage : public ProtoMessage { }; class ProtoSize { - private: - uint32_t total_size_ = 0; - public: - /** - * @brief ProtoSize class for Protocol Buffer serialization size calculation - * - * This class provides methods to calculate the exact byte counts needed - * for encoding various Protocol Buffer field types. The class now uses an - * object-based approach to reduce parameter passing overhead while keeping - * varint calculation methods static for external use. - * - * Implements Protocol Buffer encoding size calculation according to: - * https://protobuf.dev/programming-guides/encoding/ - * - * Key features: - * - Object-based approach reduces flash usage by eliminating parameter passing - * - Early-return optimization for zero/default values - * - Static varint methods for external callers - * - Specialized handling for different field types according to protobuf spec - */ - - ProtoSize() = default; - - uint32_t get_size() const { return total_size_; } - /** * @brief Calculates the size in bytes needed to encode a uint32_t value as a varint * @@ -616,320 +595,77 @@ class ProtoSize { return varint(tag); } - /** - * @brief Common parameters for all add_*_field methods - * - * All add_*_field methods follow these common patterns: - * * @param field_id_size Pre-calculated size of the field ID in bytes - * @param value The value to calculate size for (type varies) - * @param force Whether to calculate size even if the value is default/zero/empty - * - * Each method follows this implementation pattern: - * 1. Skip calculation if value is default (0, false, empty) and not forced - * 2. Calculate the size based on the field's encoding rules - * 3. Add the field_id_size + calculated value size to total_size - */ - - /** - * @brief Calculates and adds the size of an int32 field to the total message size - */ - inline void add_int32(uint32_t field_id_size, int32_t value) { - if (value != 0) { - add_int32_force(field_id_size, value); - } + // Static methods that RETURN size contribution (no ProtoSize object needed). + // Used by generated calculate_size() methods to accumulate into a plain uint32_t register. + static constexpr uint32_t calc_int32(uint32_t field_id_size, int32_t value) { + return value ? field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value))) : 0; } - - /** - * @brief Calculates and adds the size of an int32 field to the total message size (force version) - */ - inline void add_int32_force(uint32_t field_id_size, int32_t value) { - // Always calculate size when forced - // Negative values are encoded as 10-byte varints in protobuf - total_size_ += field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value))); + static constexpr uint32_t calc_int32_force(uint32_t field_id_size, int32_t value) { + return field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value))); } - - /** - * @brief Calculates and adds the size of a uint32 field to the total message size - */ - inline void add_uint32(uint32_t field_id_size, uint32_t value) { - if (value != 0) { - add_uint32_force(field_id_size, value); - } + static constexpr uint32_t calc_uint32(uint32_t field_id_size, uint32_t value) { + return value ? field_id_size + varint(value) : 0; } - - /** - * @brief Calculates and adds the size of a uint32 field to the total message size (force version) - */ - inline void add_uint32_force(uint32_t field_id_size, uint32_t value) { - // Always calculate size when force is true - total_size_ += field_id_size + varint(value); + static constexpr uint32_t calc_uint32_force(uint32_t field_id_size, uint32_t value) { + return field_id_size + varint(value); } - - /** - * @brief Calculates and adds the size of a boolean field to the total message size - */ - inline void add_bool(uint32_t field_id_size, bool value) { - if (value) { - // Boolean fields always use 1 byte when true - total_size_ += field_id_size + 1; - } + static constexpr uint32_t calc_bool(uint32_t field_id_size, bool value) { return value ? field_id_size + 1 : 0; } + static constexpr uint32_t calc_bool_force(uint32_t field_id_size) { return field_id_size + 1; } + static constexpr uint32_t calc_float(uint32_t field_id_size, float value) { + return value != 0.0f ? field_id_size + 4 : 0; } - - /** - * @brief Calculates and adds the size of a boolean field to the total message size (force version) - */ - inline void add_bool_force(uint32_t field_id_size, bool value) { - // Always calculate size when force is true - // Boolean fields always use 1 byte - total_size_ += field_id_size + 1; + static constexpr uint32_t calc_fixed32(uint32_t field_id_size, uint32_t value) { + return value ? field_id_size + 4 : 0; } - - /** - * @brief Calculates and adds the size of a float field to the total message size - */ - inline void add_float(uint32_t field_id_size, float value) { - if (value != 0.0f) { - total_size_ += field_id_size + 4; - } + static constexpr uint32_t calc_sfixed32(uint32_t field_id_size, int32_t value) { + return value ? field_id_size + 4 : 0; } - - // NOTE: add_double_field removed - wire type 1 (64-bit: double) not supported - // to reduce overhead on embedded systems - - /** - * @brief Calculates and adds the size of a fixed32 field to the total message size - */ - inline void add_fixed32(uint32_t field_id_size, uint32_t value) { - if (value != 0) { - total_size_ += field_id_size + 4; - } + static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value) { + return value ? field_id_size + varint(encode_zigzag32(value)) : 0; } - - // NOTE: add_fixed64_field removed - wire type 1 (64-bit: fixed64) not supported - // to reduce overhead on embedded systems - - /** - * @brief Calculates and adds the size of a sfixed32 field to the total message size - */ - inline void add_sfixed32(uint32_t field_id_size, int32_t value) { - if (value != 0) { - total_size_ += field_id_size + 4; - } + static constexpr uint32_t calc_sint32_force(uint32_t field_id_size, int32_t value) { + return field_id_size + varint(encode_zigzag32(value)); } - - // NOTE: add_sfixed64_field removed - wire type 1 (64-bit: sfixed64) not supported - // to reduce overhead on embedded systems - - /** - * @brief Calculates and adds the size of a sint32 field to the total message size - * - * Sint32 fields use ZigZag encoding, which is more efficient for negative values. - */ - inline void add_sint32(uint32_t field_id_size, int32_t value) { - if (value != 0) { - add_sint32_force(field_id_size, value); - } + static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value) { + return value ? field_id_size + varint(value) : 0; } - - /** - * @brief Calculates and adds the size of a sint32 field to the total message size (force version) - * - * Sint32 fields use ZigZag encoding, which is more efficient for negative values. - */ - inline void add_sint32_force(uint32_t field_id_size, int32_t value) { - // Always calculate size when force is true - // ZigZag encoding for sint32 - total_size_ += field_id_size + varint(encode_zigzag32(value)); + static constexpr uint32_t calc_int64_force(uint32_t field_id_size, int64_t value) { + return field_id_size + varint(value); } - - /** - * @brief Calculates and adds the size of an int64 field to the total message size - */ - inline void add_int64(uint32_t field_id_size, int64_t value) { - if (value != 0) { - add_int64_force(field_id_size, value); - } + static constexpr uint32_t calc_uint64(uint32_t field_id_size, uint64_t value) { + return value ? field_id_size + varint(value) : 0; } - - /** - * @brief Calculates and adds the size of an int64 field to the total message size (force version) - */ - inline void add_int64_force(uint32_t field_id_size, int64_t value) { - // Always calculate size when force is true - total_size_ += field_id_size + varint(value); + static constexpr uint32_t calc_uint64_force(uint32_t field_id_size, uint64_t value) { + return field_id_size + varint(value); } - - /** - * @brief Calculates and adds the size of a uint64 field to the total message size - */ - inline void add_uint64(uint32_t field_id_size, uint64_t value) { - if (value != 0) { - add_uint64_force(field_id_size, value); - } + static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len) { + return len ? field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len) : 0; } - - /** - * @brief Calculates and adds the size of a uint64 field to the total message size (force version) - */ - inline void add_uint64_force(uint32_t field_id_size, uint64_t value) { - // Always calculate size when force is true - total_size_ += field_id_size + varint(value); + static constexpr uint32_t calc_length_force(uint32_t field_id_size, size_t len) { + return field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len); } - - // NOTE: sint64 support functions (add_sint64_field, add_sint64_field_force) removed - // sint64 type is not supported by ESPHome API to reduce overhead on embedded systems - - /** - * @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size - */ - inline void add_length(uint32_t field_id_size, size_t len) { - if (len != 0) { - add_length_force(field_id_size, len); - } + static constexpr uint32_t calc_sint64(uint32_t field_id_size, int64_t value) { + return value ? field_id_size + varint(encode_zigzag64(value)) : 0; } - - /** - * @brief Calculates and adds the size of a length-delimited field (string/bytes) to the total message size (repeated - * field version) - */ - inline void add_length_force(uint32_t field_id_size, size_t len) { - // Always calculate size when force is true - // Field ID + length varint + data bytes - total_size_ += field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len); + static constexpr uint32_t calc_sint64_force(uint32_t field_id_size, int64_t value) { + return field_id_size + varint(encode_zigzag64(value)); } - - /** - * @brief Adds a pre-calculated size directly to the total - * - * This is used when we can calculate the total size by multiplying the number - * of elements by the bytes per element (for repeated fixed-size types like float, fixed32, etc.) - * - * @param size The pre-calculated total size to add - */ - inline void add_precalculated_size(uint32_t size) { total_size_ += size; } - - /** - * @brief Calculates and adds the size of a nested message field to the total message size - * - * This helper function directly updates the total_size reference if the nested size - * is greater than zero. - * - * @param nested_size The pre-calculated size of the nested message - */ - inline void add_message_field(uint32_t field_id_size, uint32_t nested_size) { - if (nested_size != 0) { - add_message_field_force(field_id_size, nested_size); - } + static constexpr uint32_t calc_fixed64(uint32_t field_id_size, uint64_t value) { + return value ? field_id_size + 8 : 0; } - - /** - * @brief Calculates and adds the size of a nested message field to the total message size (force version) - * - * @param nested_size The pre-calculated size of the nested message - */ - inline void add_message_field_force(uint32_t field_id_size, uint32_t nested_size) { - // Always calculate size when force is true - // Field ID + length varint + nested message content - total_size_ += field_id_size + varint(nested_size) + nested_size; + static constexpr uint32_t calc_sfixed64(uint32_t field_id_size, int64_t value) { + return value ? field_id_size + 8 : 0; } - - /** - * @brief Calculates and adds the size of a nested message field to the total message size - * - * This version takes a ProtoMessage object, calculates its size internally, - * and updates the total_size reference. This eliminates the need for a temporary variable - * at the call site. - * - * @param message The nested message object - */ - inline void add_message_object(uint32_t field_id_size, const ProtoMessage &message) { - // Calculate nested message size by creating a temporary ProtoSize - ProtoSize nested_calc; - message.calculate_size(nested_calc); - uint32_t nested_size = nested_calc.get_size(); - - // Use the base implementation with the calculated nested_size - add_message_field(field_id_size, nested_size); + static constexpr uint32_t calc_message(uint32_t field_id_size, uint32_t nested_size) { + return nested_size ? field_id_size + varint(nested_size) + nested_size : 0; } - - /** - * @brief Calculates and adds the size of a nested message field to the total message size (force version) - * - * @param message The nested message object - */ - inline void add_message_object_force(uint32_t field_id_size, const ProtoMessage &message) { - // Calculate nested message size by creating a temporary ProtoSize - ProtoSize nested_calc; - message.calculate_size(nested_calc); - uint32_t nested_size = nested_calc.get_size(); - - // Use the base implementation with the calculated nested_size - add_message_field_force(field_id_size, nested_size); - } - - /** - * @brief Calculates and adds the sizes of all messages in a repeated field to the total message size - * - * This helper processes a vector of message objects, calculating the size for each message - * and adding it to the total size. - * - * @tparam MessageType The type of the nested messages in the vector - * @param messages Vector of message objects - */ - template<typename MessageType> - inline void add_repeated_message(uint32_t field_id_size, const std::vector<MessageType> &messages) { - // Skip if the vector is empty - if (!messages.empty()) { - // Use the force version for all messages in the repeated field - for (const auto &message : messages) { - add_message_object_force(field_id_size, message); - } - } - } - - /** - * @brief Calculates and adds the sizes of all messages in a repeated field to the total message size (FixedVector - * version) - * - * @tparam MessageType The type of the nested messages in the FixedVector - * @param messages FixedVector of message objects - */ - template<typename MessageType> - inline void add_repeated_message(uint32_t field_id_size, const FixedVector<MessageType> &messages) { - // Skip if the fixed vector is empty - if (!messages.empty()) { - // Use the force version for all messages in the repeated field - for (const auto &message : messages) { - add_message_object_force(field_id_size, message); - } - } - } - - /** - * @brief Calculate size of a packed repeated sint32 field - */ - inline void add_packed_sint32(uint32_t field_id_size, const std::vector<int32_t> &values) { - if (values.empty()) - return; - - size_t packed_size = 0; - for (int value : values) { - packed_size += varint(encode_zigzag32(value)); - } - - // field_id + length varint + packed data - total_size_ += field_id_size + varint(static_cast<uint32_t>(packed_size)) + static_cast<uint32_t>(packed_size); + static constexpr uint32_t calc_message_force(uint32_t field_id_size, uint32_t nested_size) { + return field_id_size + varint(nested_size) + nested_size; } }; // Implementation of methods that depend on ProtoSize being fully defined -inline uint32_t ProtoMessage::calculated_size() const { - ProtoSize size; - this->calculate_size(size); - return size.get_size(); -} - // Implementation of encode_packed_sint32 - must be after ProtoSize is defined inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) { if (values.empty()) @@ -949,31 +685,30 @@ inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std: } } -// Implementation of encode_message - must be after ProtoMessage is defined -inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value, bool force) { - // Calculate the message size first - ProtoSize msg_size; - value.calculate_size(msg_size); - uint32_t msg_length_bytes = msg_size.get_size(); +// Encode thunk — converts void* back to concrete type for direct encode() call +template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &buf) { + static_cast<const T *>(msg)->encode(buf); +} - // Skip empty singular messages (matches add_message_field which skips when nested_size == 0) - // Repeated messages (force=true) are always encoded since an empty item is meaningful +// Implementation of encode_message - must be after ProtoMessage is defined +template<typename T> inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const T &value, bool force) { + this->encode_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>, force); +} + +// Non-template core for encode_message +inline void ProtoWriteBuffer::encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value, + void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force) { if (msg_length_bytes == 0 && !force) return; - - this->encode_field_raw(field_id, 2); // type 2: Length-delimited message - - // Write the length varint directly through pos_ + this->encode_field_raw(field_id, 2); this->encode_varint_raw(msg_length_bytes); - - // Encode nested message - pos_ advances directly through the reference #ifdef ESPHOME_DEBUG_API uint8_t *start = this->pos_; - value.encode(*this); + encode_fn(value, *this); if (static_cast<uint32_t>(this->pos_ - start) != msg_length_bytes) this->debug_check_encode_size_(field_id, msg_length_bytes, this->pos_ - start); #else - value.encode(*this); + encode_fn(value, *this); #endif } @@ -993,14 +728,6 @@ class ProtoService { virtual void on_no_setup_connection() = 0; virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0; virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0; - /** - * Send a protobuf message by calculating its size, allocating a buffer, encoding, and sending. - * This is the implementation method - callers should use send_message() which adds logging. - * @param msg The protobuf message to send. - * @param message_type The message type identifier. - * @return True if the message was sent successfully, false otherwise. - */ - virtual bool send_message_impl(const ProtoMessage &msg, uint8_t message_type) = 0; // Authentication helper methods inline bool check_connection_setup_() { diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp index b2000fbd94..21573f0184 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.cpp @@ -183,10 +183,7 @@ void BluetoothConnection::send_service_for_discovery_() { static constexpr size_t MAX_PACKET_SIZE = 1360; // Keep running total of actual message size - size_t current_size = 0; - api::ProtoSize size; - resp.calculate_size(size); - current_size = size.get_size(); + size_t current_size = resp.calculate_size(); while (this->send_service_ < this->service_count_) { esp_gattc_service_elem_t service_result; @@ -302,9 +299,7 @@ void BluetoothConnection::send_service_for_discovery_() { } // end if (total_char_count > 0) // Calculate the actual size of just this service - api::ProtoSize service_sizer; - service_resp.calculate_size(service_sizer); - size_t service_size = service_sizer.get_size() + 1; // +1 for field tag + size_t service_size = service_resp.calculate_size() + 1; // +1 for field tag // Check if adding this service would exceed the limit if (current_size + service_size > MAX_PACKET_SIZE) { @@ -333,7 +328,7 @@ void BluetoothConnection::send_service_for_discovery_() { } // Send the message with dynamically batched services - api_conn->send_message(resp, api::BluetoothGATTGetServicesResponse::MESSAGE_TYPE); + api_conn->send_message(resp); } void BluetoothConnection::log_connection_error_(const char *operation, esp_gatt_status_t status) { @@ -422,7 +417,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga resp.address = this->address_; resp.handle = param->read.handle; resp.set_data(param->read.value, param->read.value_len); - api_connection->send_message(resp, api::BluetoothGATTReadResponse::MESSAGE_TYPE); + api_connection->send_message(resp); break; } case ESP_GATTC_WRITE_CHAR_EVT: @@ -438,7 +433,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga api::BluetoothGATTWriteResponse resp; resp.address = this->address_; resp.handle = param->write.handle; - api_connection->send_message(resp, api::BluetoothGATTWriteResponse::MESSAGE_TYPE); + api_connection->send_message(resp); break; } case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: { @@ -454,7 +449,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga api::BluetoothGATTNotifyResponse resp; resp.address = this->address_; resp.handle = param->unreg_for_notify.handle; - api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); + api_connection->send_message(resp); break; } case ESP_GATTC_REG_FOR_NOTIFY_EVT: { @@ -470,7 +465,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga api::BluetoothGATTNotifyResponse resp; resp.address = this->address_; resp.handle = param->reg_for_notify.handle; - api_connection->send_message(resp, api::BluetoothGATTNotifyResponse::MESSAGE_TYPE); + api_connection->send_message(resp); break; } case ESP_GATTC_NOTIFY_EVT: { @@ -483,7 +478,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga resp.address = this->address_; resp.handle = param->notify.handle; resp.set_data(param->notify.value, param->notify.value_len); - api_connection->send_message(resp, api::BluetoothGATTNotifyDataResponse::MESSAGE_TYPE); + api_connection->send_message(resp); break; } default: diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index cab328e2f5..21da4ead14 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -44,7 +44,7 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta resp.configured_mode = this->configured_scan_active_ ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE : api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE; - this->api_connection_->send_message(resp, api::BluetoothScannerStateResponse::MESSAGE_TYPE); + this->api_connection_->send_message(resp); } void BluetoothProxy::log_connection_request_ignored_(BluetoothConnection *connection, espbt::ClientState state) { @@ -112,7 +112,7 @@ void BluetoothProxy::flush_pending_advertisements() { return; // Send the message - this->api_connection_->send_message(this->response_, api::BluetoothLERawAdvertisementsResponse::MESSAGE_TYPE); + this->api_connection_->send_message(this->response_); ESP_LOGV(TAG, "Sent batch of %u BLE advertisements", this->response_.advertisements_len); @@ -269,7 +269,7 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest call.success = ret == ESP_OK; call.error = ret; - this->api_connection_->send_message(call, api::BluetoothDeviceClearCacheResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); break; } @@ -389,7 +389,7 @@ void BluetoothProxy::send_device_connection(uint64_t address, bool connected, ui call.connected = connected; call.mtu = mtu; call.error = error; - this->api_connection_->send_message(call, api::BluetoothDeviceConnectionResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); } void BluetoothProxy::send_connections_free() { if (this->api_connection_ != nullptr) { @@ -398,7 +398,7 @@ void BluetoothProxy::send_connections_free() { } void BluetoothProxy::send_connections_free(api::APIConnection *api_connection) { - api_connection->send_message(this->connections_free_response_, api::BluetoothConnectionsFreeResponse::MESSAGE_TYPE); + api_connection->send_message(this->connections_free_response_); } void BluetoothProxy::send_gatt_services_done(uint64_t address) { @@ -406,7 +406,7 @@ void BluetoothProxy::send_gatt_services_done(uint64_t address) { return; api::BluetoothGATTGetServicesDoneResponse call; call.address = address; - this->api_connection_->send_message(call, api::BluetoothGATTGetServicesDoneResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); } void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error) { @@ -416,7 +416,7 @@ void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_ call.address = address; call.handle = handle; call.error = error; - this->api_connection_->send_message(call, api::BluetoothGATTWriteResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); } void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_t error) { @@ -427,7 +427,7 @@ void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_ call.paired = paired; call.error = error; - this->api_connection_->send_message(call, api::BluetoothDevicePairingResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); } void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_err_t error) { @@ -438,7 +438,7 @@ void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_e call.success = success; call.error = error; - this->api_connection_->send_message(call, api::BluetoothDeviceUnpairingResponse::MESSAGE_TYPE); + this->api_connection_->send_message(call); } void BluetoothProxy::bluetooth_scanner_set_mode(bool active) { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index d6cbfd4b21..51d52a8af8 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -251,8 +251,7 @@ void VoiceAssistant::loop() { } #endif - if (this->api_client_ == nullptr || - !this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) { + if (this->api_client_ == nullptr || !this->api_client_->send_message(msg)) { ESP_LOGW(TAG, "Could not request start"); this->error_trigger_.trigger("not-connected", "Could not request start"); this->continuous_ = false; @@ -275,7 +274,7 @@ void VoiceAssistant::loop() { api::VoiceAssistantAudio msg; msg.data = this->send_buffer_; msg.data_len = read_bytes; - this->api_client_->send_message(msg, api::VoiceAssistantAudio::MESSAGE_TYPE); + this->api_client_->send_message(msg); } else { if (!this->udp_socket_running_) { if (!this->start_udp_socket_()) { @@ -354,7 +353,7 @@ void VoiceAssistant::loop() { api::VoiceAssistantAnnounceFinished msg; msg.success = true; - this->api_client_->send_message(msg, api::VoiceAssistantAnnounceFinished::MESSAGE_TYPE); + this->api_client_->send_message(msg); break; } } @@ -612,7 +611,7 @@ void VoiceAssistant::signal_stop_() { ESP_LOGD(TAG, "Signaling stop"); api::VoiceAssistantRequest msg; msg.start = false; - this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE); + this->api_client_->send_message(msg); } void VoiceAssistant::start_playback_timeout_() { @@ -622,7 +621,7 @@ void VoiceAssistant::start_playback_timeout_() { api::VoiceAssistantAnnounceFinished msg; msg.success = true; - this->api_client_->send_message(msg, api::VoiceAssistantAnnounceFinished::MESSAGE_TYPE); + this->api_client_->send_message(msg); }); } diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index b0836ac072..9e5c57814d 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -119,7 +119,7 @@ void ZWaveProxy::process_uart_() { // If this is a data frame, use frame length indicator + 2 (for SoF + checksum), else assume 1 for ACK/NAK/CAN this->outgoing_proto_msg_.data_len = this->buffer_[0] == ZWAVE_FRAME_TYPE_START ? this->buffer_[1] + 2 : 1; } - this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE); + this->api_connection_->send_message(this->outgoing_proto_msg_); } } } @@ -209,7 +209,7 @@ void ZWaveProxy::send_homeid_changed_msg_(api::APIConnection *conn) { msg.data_len = this->home_id_.size(); if (conn != nullptr) { // Send to specific connection - conn->send_message(msg, api::ZWaveProxyRequest::MESSAGE_TYPE); + conn->send_message(msg); } else if (api::global_api_server != nullptr) { // We could add code to manage a second subscription type, but, since this message is // very infrequent and small, we simply send it to all clients @@ -346,7 +346,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) { this->buffer_[0] = byte; this->outgoing_proto_msg_.data = this->buffer_.data(); this->outgoing_proto_msg_.data_len = 1; - this->api_connection_->send_message(this->outgoing_proto_msg_, api::ZWaveProxyFrame::MESSAGE_TYPE); + this->api_connection_->send_message(this->outgoing_proto_msg_); } } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 9c9cda4d36..85352689e6 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -270,18 +270,21 @@ class TypeInfo(ABC): def _get_simple_size_calculation( self, name: str, force: bool, base_method: str, value_expr: str = None ) -> str: - """Helper for simple size calculations. + """Helper for simple size calculations using static ProtoSize methods. Args: name: Field name force: Whether this is for a repeated field - base_method: Base method name (e.g., "add_int32") + base_method: Base method name (e.g., "int32") value_expr: Optional value expression (defaults to name) """ field_id_size = self.calculate_field_id_size() - method = f"{base_method}_force" if force else base_method + method = f"calc_{base_method}_force" if force else f"calc_{base_method}" + # calc_bool_force only takes field_id_size (no value needed - bool is always 1 byte) + if base_method == "bool" and force: + return f"size += ProtoSize::{method}({field_id_size});" value = value_expr or name - return f"size.{method}({field_id_size}, {value});" + return f"size += ProtoSize::{method}({field_id_size}, {value});" @abstractmethod def get_size_calculation(self, name: str, force: bool = False) -> str: @@ -410,7 +413,7 @@ class DoubleType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_double({field_id_size}, {name});" + return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -434,7 +437,7 @@ class FloatType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_float({field_id_size}, {name});" + return f"size += ProtoSize::calc_float({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -457,7 +460,7 @@ class Int64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_int64") + return self._get_simple_size_calculation(name, force, "int64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -477,7 +480,7 @@ class UInt64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_uint64") + return self._get_simple_size_calculation(name, force, "uint64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -497,7 +500,7 @@ class Int32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_int32") + return self._get_simple_size_calculation(name, force, "int32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -518,7 +521,7 @@ class Fixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_fixed64({field_id_size}, {name});" + return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -542,7 +545,7 @@ class Fixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_fixed32({field_id_size}, {name});" + return f"size += ProtoSize::calc_fixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -563,7 +566,7 @@ class BoolType(TypeInfo): return f"out.append(YESNO({name}));" def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_bool") + return self._get_simple_size_calculation(name, force, "bool") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 1 # field ID + 1 byte @@ -647,18 +650,18 @@ class StringType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: # For SOURCE_CLIENT only messages, use the string field directly if not self._needs_encode: - return self._get_simple_size_calculation(name, force, "add_length") + return self._get_simple_size_calculation(name, force, "length") # Check if this is being called from a repeated field context # In that case, 'name' will be 'it' and we need to use the repeated version if name == "it": - # For repeated fields, we need to use add_length_force which includes field ID + # For repeated fields, we need to use length_force which includes field ID field_id_size = self.calculate_field_id_size() - return f"size.add_length_force({field_id_size}, it.size());" + return f"size += ProtoSize::calc_length_force({field_id_size}, it.size());" # For messages that need encoding, use the StringRef size field_id_size = self.calculate_field_id_size() - return f"size.add_length({field_id_size}, this->{self.field_name}_ref_.size());" + return f"size += ProtoSize::calc_length({field_id_size}, this->{self.field_name}_ref_.size());" def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string @@ -721,7 +724,9 @@ class MessageType(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_message_object") + field_id_size = self.calculate_field_id_size() + method = "calc_message_force" if force else "calc_message" + return f"size += ProtoSize::{method}({field_id_size}, {name}.calculate_size());" def get_estimated_size(self) -> int: # For message types, we can't easily estimate the submessage size without @@ -822,7 +827,7 @@ class BytesType(TypeInfo): ) def get_size_calculation(self, name: str, force: bool = False) -> str: - return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);" + return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}_len_);" def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical bytes @@ -897,7 +902,7 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): ) def get_size_calculation(self, name: str, force: bool = False) -> str: - return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}_len);" + return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}_len);" class PointerToStringBufferType(PointerToBufferTypeBase): @@ -939,7 +944,7 @@ class PointerToStringBufferType(PointerToBufferTypeBase): return f'dump_field(out, "{self.name}", this->{self.field_name});' def get_size_calculation(self, name: str, force: bool = False) -> str: - return f"size.add_length({self.calculate_field_id_size()}, this->{self.field_name}.size());" + return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}.size());" def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string @@ -1103,9 +1108,9 @@ class FixedArrayBytesType(TypeInfo): if force: # For repeated fields, always calculate size (no zero check) - return f"size.add_length_force({field_id_size}, {length_field});" - # For non-repeated fields, add_length already checks for zero - return f"size.add_length({field_id_size}, {length_field});" + return f"size += ProtoSize::calc_length_force({field_id_size}, {length_field});" + # For non-repeated fields, length already checks for zero + return f"size += ProtoSize::calc_length({field_id_size}, {length_field});" def get_estimated_size(self) -> int: # Estimate based on typical BLE advertisement size @@ -1132,7 +1137,7 @@ class UInt32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_uint32") + return self._get_simple_size_calculation(name, force, "uint32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -1168,7 +1173,7 @@ class EnumType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: return self._get_simple_size_calculation( - name, force, "add_uint32", f"static_cast<uint32_t>({name})" + name, force, "uint32", f"static_cast<uint32_t>({name})" ) def get_estimated_size(self) -> int: @@ -1190,7 +1195,7 @@ class SFixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_sfixed32({field_id_size}, {name});" + return f"size += ProtoSize::calc_sfixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 4 @@ -1214,7 +1219,7 @@ class SFixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() - return f"size.add_sfixed64({field_id_size}, {name});" + return f"size += ProtoSize::calc_sfixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: return 8 @@ -1237,7 +1242,7 @@ class SInt32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_sint32") + return self._get_simple_size_calculation(name, force, "sint32") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -1257,7 +1262,7 @@ class SInt64Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: - return self._get_simple_size_calculation(name, force, "add_sint64") + return self._get_simple_size_calculation(name, force, "sint64") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint @@ -1694,11 +1699,17 @@ class RepeatedTypeInfo(TypeInfo): # For repeated fields, we always need to pass force=True to the underlying type's calculation # This is because the encode method always sets force=true for repeated fields - # Handle message types separately as they use a dedicated helper + # Handle message types separately - generate inline loop if isinstance(self._ti, MessageType): field_id_size = self._ti.calculate_field_id_size() - container = f"*{name}" if self._use_pointer else name - return f"size.add_repeated_message({field_id_size}, {container});" + container_ref = f"*{name}" if self._use_pointer else name + empty_check = f"{name}->empty()" if self._use_pointer else f"{name}.empty()" + o = f"if (!{empty_check}) {{\n" + o += f" for (const auto &it : {container_ref}) {{\n" + o += f" size += ProtoSize::calc_message_force({field_id_size}, it.calculate_size());\n" + o += " }\n" + o += "}" + return o # For non-message types, generate size calculation with iteration container_ref = f"*{name}" if self._use_pointer else name @@ -1713,14 +1724,14 @@ class RepeatedTypeInfo(TypeInfo): field_id_size = self._ti.calculate_field_id_size() bytes_per_element = field_id_size + num_bytes size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()" - o += f" size.add_precalculated_size({size_expr} * {bytes_per_element});\n" + o += f" size += {size_expr} * {bytes_per_element};\n" else: # Other types need the actual value # Special handling for const char* elements if self._use_pointer and "const char" in self._container_no_template: field_id_size = self.calculate_field_id_size() o += f" for (const char *it : {container_ref}) {{\n" - o += f" size.add_length_force({field_id_size}, strlen(it));\n" + o += f" size += ProtoSize::calc_length_force({field_id_size}, strlen(it));\n" else: auto_ref = "" if self._ti_is_bool else "&" o += f" for (const auto {auto_ref}it : {container_ref}) {{\n" @@ -2233,23 +2244,19 @@ def build_message_type( o += indent("\n".join(encode)) + "\n" o += "}\n" cpp += o - prot = "void encode(ProtoWriteBuffer &buffer) const override;" + prot = "void encode(ProtoWriteBuffer &buffer) const;" public_content.append(prot) # If no fields to encode or message doesn't need encoding, the default implementation in ProtoMessage will be used # Add calculate_size method only if this message needs encoding and has fields if needs_encode and size_calc: - o = f"void {desc.name}::calculate_size(ProtoSize &size) const {{" - # For a single field, just inline it for simplicity - if len(size_calc) == 1 and len(size_calc[0]) + len(o) + 3 < 120: - o += f" {size_calc[0]} }}\n" - else: - # For multiple fields - o += "\n" - o += indent("\n".join(size_calc)) + "\n" - o += "}\n" + o = f"uint32_t {desc.name}::calculate_size() const {{\n" + o += " uint32_t size = 0;\n" + o += indent("\n".join(size_calc)) + "\n" + o += " return size;\n" + o += "}\n" cpp += o - prot = "void calculate_size(ProtoSize &size) const override;" + prot = "uint32_t calculate_size() const;" public_content.append(prot) # If no fields to calculate size for or message doesn't need encoding, the default implementation in ProtoMessage will be used @@ -2933,14 +2940,8 @@ static const char *const TAG = "api.service"; hpp += " public:\n" hpp += "#endif\n\n" - # Add non-template send_message method - hpp += " bool send_message(const ProtoMessage &msg, uint8_t message_type) {\n" - hpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - hpp += " DumpBuffer dump_buf;\n" - hpp += " this->log_send_message_(msg.message_name(), msg.dump_to(dump_buf));\n" - hpp += "#endif\n" - hpp += " return this->send_message_impl(msg, message_type);\n" - hpp += " }\n\n" + # send_message is now a template on APIConnection directly + # No non-template send_message method needed here # Add logging helper method implementations to cpp cpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" From 3c7956e72d34f3cc3fb9f5100afc09e974982f26 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:04:00 -0500 Subject: [PATCH 1161/2030] [multiple] Add default initializers to uninitialized member variables (#14556) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bedjet/bedjet_hub.h | 8 ++++---- .../components/current_based/current_based_cover.h | 12 ++++++------ esphome/components/deep_sleep/deep_sleep_component.h | 2 +- esphome/components/max6956/max6956.h | 4 ++-- esphome/components/ms8607/ms8607.h | 8 ++++---- .../remote_transmitter/remote_transmitter.h | 2 +- esphome/components/sen5x/sen5x.h | 8 ++++---- esphome/components/sim800l/sim800l.h | 10 +++++----- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/esphome/components/bedjet/bedjet_hub.h b/esphome/components/bedjet/bedjet_hub.h index 6258795b02..59b0af93ad 100644 --- a/esphome/components/bedjet/bedjet_hub.h +++ b/esphome/components/bedjet/bedjet_hub.h @@ -164,10 +164,10 @@ class BedJetHub : public esphome::ble_client::BLEClientNode, public PollingCompo std::unique_ptr<BedjetCodec> codec_; bool discover_characteristics_(); - uint16_t char_handle_cmd_; - uint16_t char_handle_name_; - uint16_t char_handle_status_; - uint16_t config_descr_status_; + uint16_t char_handle_cmd_{0}; + uint16_t char_handle_name_{0}; + uint16_t char_handle_status_{0}; + uint16_t config_descr_status_{0}; uint8_t write_notify_config_descriptor_(bool enable); }; diff --git a/esphome/components/current_based/current_based_cover.h b/esphome/components/current_based/current_based_cover.h index 76bd85cdf7..40b39517e4 100644 --- a/esphome/components/current_based/current_based_cover.h +++ b/esphome/components/current_based/current_based_cover.h @@ -67,21 +67,21 @@ class CurrentBasedCover : public cover::Cover, public Component { sensor::Sensor *open_sensor_{nullptr}; Trigger<> open_trigger_; - float open_moving_current_threshold_; + float open_moving_current_threshold_{0.0f}; float open_obstacle_current_threshold_{FLT_MAX}; - uint32_t open_duration_; + uint32_t open_duration_{0}; sensor::Sensor *close_sensor_{nullptr}; Trigger<> close_trigger_; - float close_moving_current_threshold_; + float close_moving_current_threshold_{0.0f}; float close_obstacle_current_threshold_{FLT_MAX}; - uint32_t close_duration_; + uint32_t close_duration_{0}; uint32_t max_duration_{UINT32_MAX}; bool malfunction_detection_{true}; Trigger<> malfunction_trigger_; - uint32_t start_sensing_delay_; - float obstacle_rollback_; + uint32_t start_sensing_delay_{0}; + float obstacle_rollback_{0.0f}; Trigger<> *prev_command_trigger_{nullptr}; uint32_t last_recompute_time_{0}; diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index 1998b815f3..14713d51a1 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -145,7 +145,7 @@ class DeepSleepComponent : public Component { #endif // USE_BK72XX #ifdef USE_ESP32 - InternalGPIOPin *wakeup_pin_; + InternalGPIOPin *wakeup_pin_{nullptr}; WakeupPinMode wakeup_pin_mode_{WAKEUP_PIN_MODE_IGNORE}; #if !defined(USE_ESP32_VARIANT_ESP32C2) && !defined(USE_ESP32_VARIANT_ESP32C3) diff --git a/esphome/components/max6956/max6956.h b/esphome/components/max6956/max6956.h index 0c609b0b43..31f97c11f8 100644 --- a/esphome/components/max6956/max6956.h +++ b/esphome/components/max6956/max6956.h @@ -63,8 +63,8 @@ class MAX6956 : public Component, public i2c::I2CDevice { bool read_reg_(uint8_t reg, uint8_t *value); // write a value to a given register bool write_reg_(uint8_t reg, uint8_t value); - max6956::MAX6956CURRENTMODE brightness_mode_; - uint8_t global_brightness_; + max6956::MAX6956CURRENTMODE brightness_mode_{}; + uint8_t global_brightness_{0}; private: int8_t prev_bright_[28] = {0}; diff --git a/esphome/components/ms8607/ms8607.h b/esphome/components/ms8607/ms8607.h index ceb3dd22c8..2888b6cdd2 100644 --- a/esphome/components/ms8607/ms8607.h +++ b/esphome/components/ms8607/ms8607.h @@ -67,9 +67,9 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { /// use raw temperature & pressure to calculate & publish values void calculate_values_(uint32_t raw_temperature, uint32_t raw_pressure); - sensor::Sensor *temperature_sensor_; - sensor::Sensor *pressure_sensor_; - sensor::Sensor *humidity_sensor_; + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *pressure_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; /** I2CDevice object to communicate with secondary I2C address for the humidity sensor * @@ -77,7 +77,7 @@ class MS8607Component : public PollingComponent, public i2c::I2CDevice { * * Default address for humidity is 0x40 */ - MS8607HumidityDevice *humidity_device_; + MS8607HumidityDevice *humidity_device_{nullptr}; /// This device's pressure & temperature calibration values, read from PROM struct CalibrationValues { diff --git a/esphome/components/remote_transmitter/remote_transmitter.h b/esphome/components/remote_transmitter/remote_transmitter.h index aee52ea170..6b4ebfe24b 100644 --- a/esphome/components/remote_transmitter/remote_transmitter.h +++ b/esphome/components/remote_transmitter/remote_transmitter.h @@ -96,7 +96,7 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase, bool inverted_{false}; bool non_blocking_{false}; #endif - uint8_t carrier_duty_percent_; + uint8_t carrier_duty_percent_{50}; Trigger<> transmit_trigger_; Trigger<> complete_trigger_; diff --git a/esphome/components/sen5x/sen5x.h b/esphome/components/sen5x/sen5x.h index e3bf931b41..a9d4da86b8 100644 --- a/esphome/components/sen5x/sen5x.h +++ b/esphome/components/sen5x/sen5x.h @@ -104,12 +104,12 @@ class SEN5XComponent : public PollingComponent, public sensirion_common::Sensiri char serial_number_[17] = "UNKNOWN"; uint16_t voc_baseline_state_[4]{0}; - uint32_t voc_baseline_time_; - uint16_t firmware_version_; + uint32_t voc_baseline_time_{0}; + uint16_t firmware_version_{0}; Sen5xType type_{Sen5xType::UNKNOWN}; - ERRORCODE error_code_; + ERRORCODE error_code_{ERRORCODE::UNKNOWN}; bool initialized_{false}; - bool store_baseline_; + bool store_baseline_{false}; sensor::Sensor *pm_1_0_sensor_{nullptr}; sensor::Sensor *pm_2_5_sensor_{nullptr}; diff --git a/esphome/components/sim800l/sim800l.h b/esphome/components/sim800l/sim800l.h index a2da686ce1..e9e2f66d78 100644 --- a/esphome/components/sim800l/sim800l.h +++ b/esphome/components/sim800l/sim800l.h @@ -107,11 +107,11 @@ class Sim800LComponent : public uart::UARTDevice, public PollingComponent { std::string recipient_; std::string outgoing_message_; std::string ussd_; - bool send_pending_; - bool dial_pending_; - bool connect_pending_; - bool disconnect_pending_; - bool send_ussd_pending_; + bool send_pending_{false}; + bool dial_pending_{false}; + bool connect_pending_{false}; + bool disconnect_pending_{false}; + bool send_ussd_pending_{false}; uint8_t call_state_{6}; CallbackManager<void(std::string, std::string)> sms_received_callback_; From 3db436e48e0cafd48711bd782600cbea7a5f9adc Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:05:34 -0500 Subject: [PATCH 1162/2030] [esp32_ble_server][espnow][time] Fix logic bugs (#14553) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/esp32_ble_server/ble_server.cpp | 18 +++++++----------- esphome/components/espnow/automation.h | 4 ++-- esphome/components/time/real_time_clock.cpp | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/esphome/components/esp32_ble_server/ble_server.cpp b/esphome/components/esp32_ble_server/ble_server.cpp index f292cf8722..ecc53e197f 100644 --- a/esphome/components/esp32_ble_server/ble_server.cpp +++ b/esphome/components/esp32_ble_server/ble_server.cpp @@ -7,6 +7,7 @@ #ifdef USE_ESP32 +#include <algorithm> #include <nvs_flash.h> #include <freertos/FreeRTOSConfig.h> #include <esp_bt_main.h> @@ -38,21 +39,16 @@ void BLEServer::loop() { case RUNNING: { // Start all services that are pending to start if (!this->services_to_start_.empty()) { - uint16_t index_to_remove = 0; - // Iterate over the services to start - for (unsigned i = 0; i < this->services_to_start_.size(); i++) { - BLEService *service = this->services_to_start_[i]; + for (auto &service : this->services_to_start_) { if (service->is_created()) { service->start(); // Needs to be called once per characteristic in the service - } else { - index_to_remove = i + 1; } } - // Remove the services that have been started - if (index_to_remove > 0) { - this->services_to_start_.erase(this->services_to_start_.begin(), - this->services_to_start_.begin() + index_to_remove - 1); - } + // Remove services that have been started + this->services_to_start_.erase( + std::remove_if(this->services_to_start_.begin(), this->services_to_start_.end(), + [](BLEService *service) { return service->is_starting() || service->is_running(); }), + this->services_to_start_.end()); } break; } diff --git a/esphome/components/espnow/automation.h b/esphome/components/espnow/automation.h index 0b26681400..0fbb14e388 100644 --- a/esphome/components/espnow/automation.h +++ b/esphome/components/espnow/automation.h @@ -138,7 +138,7 @@ class OnReceiveTrigger : public Trigger<const ESPNowRecvInfo &, const uint8_t *, protected: bool has_address_{false}; - const uint8_t *address_[ESP_NOW_ETH_ALEN]; + uint8_t address_[ESP_NOW_ETH_ALEN]; }; class OnUnknownPeerTrigger : public Trigger<const ESPNowRecvInfo &, const uint8_t *, uint8_t>, public ESPNowUnknownPeerHandler { @@ -167,7 +167,7 @@ class OnBroadcastedTrigger : public Trigger<const ESPNowRecvInfo &, const uint8_ protected: bool has_address_{false}; - const uint8_t *address_[ESP_NOW_ETH_ALEN]; + uint8_t address_[ESP_NOW_ETH_ALEN]; }; } // namespace esphome::espnow diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 2e758ad8e7..566344fa88 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -90,7 +90,7 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { }; struct timezone tz = {0, 0}; int ret = settimeofday(&timev, &tz); - if (ret == EINVAL) { + if (ret != 0 && errno == EINVAL) { // Some ESP8266 frameworks abort when timezone parameter is not NULL // while ESP32 expects it not to be NULL ret = settimeofday(&timev, nullptr); From 7b8ba9bf206f319f614ce52d4d80c5e649eb73ee Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:14:12 -0500 Subject: [PATCH 1163/2030] [multiple] Fix cast/operator precedence bugs (#14560) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/datetime/date_entity.h | 2 +- esphome/components/es7210/es7210.cpp | 2 +- esphome/components/sgp4x/sgp4x.cpp | 2 +- esphome/components/tsl2591/tsl2591.cpp | 4 +++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/esphome/components/datetime/date_entity.h b/esphome/components/datetime/date_entity.h index cbf2b85506..8233e809a1 100644 --- a/esphome/components/datetime/date_entity.h +++ b/esphome/components/datetime/date_entity.h @@ -91,7 +91,7 @@ class DateCall { DateEntity *parent_; - optional<int16_t> year_; + optional<uint16_t> year_; optional<uint8_t> month_; optional<uint8_t> day_; }; diff --git a/esphome/components/es7210/es7210.cpp b/esphome/components/es7210/es7210.cpp index 1358121c1b..4371075fa9 100644 --- a/esphome/components/es7210/es7210.cpp +++ b/esphome/components/es7210/es7210.cpp @@ -172,7 +172,7 @@ uint8_t ES7210::es7210_gain_reg_value_(float mic_gain) { // reg: 12 - 34.5dB, 13 - 36dB, 14 - 37.5dB mic_gain += 0.5; if (mic_gain <= 33.0) { - return (uint8_t) mic_gain / 3; + return (uint8_t) (mic_gain / 3); } if (mic_gain < 36.0) { return 12; diff --git a/esphome/components/sgp4x/sgp4x.cpp b/esphome/components/sgp4x/sgp4x.cpp index 44d0a54080..cb41e374f8 100644 --- a/esphome/components/sgp4x/sgp4x.cpp +++ b/esphome/components/sgp4x/sgp4x.cpp @@ -199,7 +199,7 @@ void SGP4xComponent::measure_raw_() { response_words = 2; } } - uint16_t rhticks = llround((uint16_t) ((humidity * 65535) / 100)); + uint16_t rhticks = (uint16_t) llround((humidity * 65535) / 100); uint16_t tempticks = (uint16_t) (((temperature + 45) * 65535) / 175); // first parameter are the relative humidity ticks data[0] = rhticks; diff --git a/esphome/components/tsl2591/tsl2591.cpp b/esphome/components/tsl2591/tsl2591.cpp index 42c524a074..4ce673a91a 100644 --- a/esphome/components/tsl2591/tsl2591.cpp +++ b/esphome/components/tsl2591/tsl2591.cpp @@ -327,7 +327,9 @@ uint16_t TSL2591Component::get_illuminance(TSL2591SensorChannel channel, uint32_ return (combined_illuminance >> 16); } else if (channel == TSL2591_SENSOR_CHANNEL_VISIBLE) { // Reads all and subtracts out the infrared - return ((combined_illuminance & 0xFFFF) - (combined_illuminance >> 16)); + uint16_t full = combined_illuminance & 0xFFFF; + uint16_t ir = combined_illuminance >> 16; + return (ir > full) ? 0 : (full - ir); } // unknown channel! ESP_LOGE(TAG, "get_illuminance() caller requested an unknown channel: %d", channel); From 219d5170e006e7297004b1cfeb7e5323307980b0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:15:54 -0500 Subject: [PATCH 1164/2030] [noblex] Fix IR receive losing decoded bytes between calls (#14533) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/noblex/noblex.cpp | 130 +++++++++++++-------------- esphome/components/noblex/noblex.h | 3 +- 2 files changed, 64 insertions(+), 69 deletions(-) diff --git a/esphome/components/noblex/noblex.cpp b/esphome/components/noblex/noblex.cpp index f1e76eabf2..e7e421d177 100644 --- a/esphome/components/noblex/noblex.cpp +++ b/esphome/components/noblex/noblex.cpp @@ -118,15 +118,15 @@ void NoblexClimate::transmit_state() { data->mark(NOBLEX_HEADER_MARK); data->space(NOBLEX_HEADER_SPACE); // Data (sent remote_state from the MSB to the LSB) - for (uint8_t i : remote_state) { - for (int8_t j = 7; j >= 0; j--) { - if ((i == 4) & (j == 4)) { + for (int byte_idx = 0; byte_idx < 8; byte_idx++) { + for (int8_t bit_idx = 7; bit_idx >= 0; bit_idx--) { + if ((byte_idx == 4) && (bit_idx == 4)) { // Header intermediate data->mark(NOBLEX_BIT_MARK); data->space(NOBLEX_GAP); // gap en bit 36 } else { data->mark(NOBLEX_BIT_MARK); - bool bit = i & (1 << j); + bool bit = remote_state[byte_idx] & (1 << bit_idx); data->space(bit ? NOBLEX_ONE_SPACE : NOBLEX_ZERO_SPACE); } } @@ -145,76 +145,71 @@ void NoblexClimate::transmit_state() { // Handle received IR Buffer bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { - uint8_t remote_state[8] = {0}; - uint8_t crc = 0, crc_calculated = 0; - - if (!receiving_) { - // Validate header - if (data.expect_item(NOBLEX_HEADER_MARK, NOBLEX_HEADER_SPACE)) { - ESP_LOGV(TAG, "Header"); - receiving_ = true; - // Read first 36 bits - for (int i = 0; i < 5; i++) { - // Read bit - for (int j = 7; j >= 0; j--) { - if ((i == 4) & (j == 4)) { - remote_state[i] |= 1 << j; - // Header intermediate - ESP_LOGVV(TAG, "GAP"); - return false; - } else if (data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ONE_SPACE)) { - remote_state[i] |= 1 << j; - } else if (!data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ZERO_SPACE)) { - ESP_LOGVV(TAG, "Byte %d bit %d fail", i, j); - return false; - } - } - ESP_LOGV(TAG, "Byte %d %02X", i, remote_state[i]); - } - - } else { - ESP_LOGV(TAG, "Header fail"); - receiving_ = false; - return false; - } - - } else { - // Read the remaining 28 bits - for (int i = 4; i < 8; i++) { - // Read bit + if (data.peek_item(NOBLEX_HEADER_MARK, NOBLEX_HEADER_SPACE)) { + // First part: header + first 36 bits, followed by 20ms gap + data.expect_item(NOBLEX_HEADER_MARK, NOBLEX_HEADER_SPACE); + ESP_LOGV(TAG, "Header"); + this->receiving_ = false; + memset(this->remote_state_, 0, sizeof(this->remote_state_)); + for (int i = 0; i < 5; i++) { for (int j = 7; j >= 0; j--) { - if ((i == 4) & (j >= 4)) { - // nothing + if ((i == 4) && (j == 4)) { + this->remote_state_[i] |= 1 << j; + ESP_LOGVV(TAG, "GAP"); + this->receiving_ = true; + return false; } else if (data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ONE_SPACE)) { - remote_state[i] |= 1 << j; + this->remote_state_[i] |= 1 << j; } else if (!data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ZERO_SPACE)) { ESP_LOGVV(TAG, "Byte %d bit %d fail", i, j); return false; } } - ESP_LOGV(TAG, "Byte %d %02X", i, remote_state[i]); + ESP_LOGV(TAG, "Byte %d %02X", i, this->remote_state_[i]); } + return false; + } - // Read crc - for (int i = 3; i >= 0; i--) { - if (data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ONE_SPACE)) { - crc |= 1 << i; + // Second part: remaining 28 bits + 4-bit CRC + footer + if (!this->receiving_) { + return false; + } + this->receiving_ = false; + for (int i = 4; i < 8; i++) { + for (int j = 7; j >= 0; j--) { + if ((i == 4) && (j >= 4)) { + // already decoded in first part + } else if (data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ONE_SPACE)) { + this->remote_state_[i] |= 1 << j; } else if (!data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ZERO_SPACE)) { - ESP_LOGVV(TAG, "Bit %d CRC fail", i); + ESP_LOGVV(TAG, "Byte %d bit %d fail", i, j); return false; } } - ESP_LOGV(TAG, "CRC %02X", crc); - - // Validate footer - if (!data.expect_mark(NOBLEX_BIT_MARK)) { - ESP_LOGV(TAG, "Footer fail"); - return false; - } - receiving_ = false; + ESP_LOGV(TAG, "Byte %d %02X", i, this->remote_state_[i]); } - for (uint8_t i : remote_state) + // Read CRC + uint8_t crc = 0; + for (int i = 3; i >= 0; i--) { + if (data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ONE_SPACE)) { + crc |= 1 << i; + } else if (!data.expect_item(NOBLEX_BIT_MARK, NOBLEX_ZERO_SPACE)) { + ESP_LOGVV(TAG, "Bit %d CRC fail", i); + return false; + } + } + ESP_LOGV(TAG, "CRC %02X", crc); + + // Validate footer + if (!data.expect_mark(NOBLEX_BIT_MARK)) { + ESP_LOGV(TAG, "Footer fail"); + return false; + } + + // Validate CRC + uint8_t crc_calculated = 0; + for (uint8_t i : this->remote_state_) crc_calculated += reverse_bits(i); crc_calculated = reverse_bits(uint8_t(crc_calculated & 0x0F)) >> 4; ESP_LOGVV(TAG, "CRC calc %02X", crc_calculated); @@ -224,11 +219,12 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { return false; } - ESP_LOGD(TAG, "Received noblex code: %02X%02X %02X%02X %02X%02X %02X%02X", remote_state[0], remote_state[1], - remote_state[2], remote_state[3], remote_state[4], remote_state[5], remote_state[6], remote_state[7]); + ESP_LOGD(TAG, "Received noblex code: %02X%02X %02X%02X %02X%02X %02X%02X", this->remote_state_[0], + this->remote_state_[1], this->remote_state_[2], this->remote_state_[3], this->remote_state_[4], + this->remote_state_[5], this->remote_state_[6], this->remote_state_[7]); auto powered_on = false; - if ((remote_state[0] & NOBLEX_POWER) == NOBLEX_POWER) { + if ((this->remote_state_[0] & NOBLEX_POWER) == NOBLEX_POWER) { powered_on = true; this->powered_on_assumed = powered_on; } else { @@ -241,7 +237,7 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { // Set received mode if (powered_on_assumed) { - auto mode = (remote_state[0] & 0xE0) >> 5; + auto mode = (this->remote_state_[0] & 0xE0) >> 5; ESP_LOGV(TAG, "Mode: %02X", mode); switch (mode) { case IRNoblexMode::IR_NOBLEX_MODE_AUTO: @@ -263,7 +259,7 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { } // Set received temp - uint8_t temp = remote_state[1]; + uint8_t temp = this->remote_state_[1]; ESP_LOGVV(TAG, "Temperature Raw: %02X", temp); temp = 0x0F & reverse_bits(temp); @@ -272,7 +268,7 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { this->target_temperature = temp; // Set received fan speed - auto fan = (remote_state[0] & 0x0C) >> 2; + auto fan = (this->remote_state_[0] & 0x0C) >> 2; ESP_LOGV(TAG, "Fan: %02X", fan); switch (fan) { case IRNoblexFan::IR_NOBLEX_FAN_HIGH: @@ -291,7 +287,7 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { } // Set received swing status - if (remote_state[0] & 0x02) { + if (this->remote_state_[0] & 0x02) { ESP_LOGV(TAG, "Swing vertical"); this->swing_mode = climate::CLIMATE_SWING_VERTICAL; } else { @@ -299,8 +295,6 @@ bool NoblexClimate::on_receive(remote_base::RemoteReceiveData data) { this->swing_mode = climate::CLIMATE_SWING_OFF; } - for (uint8_t &i : remote_state) - i = 0; this->publish_state(); return true; } // end on_receive() diff --git a/esphome/components/noblex/noblex.h b/esphome/components/noblex/noblex.h index 57990db005..3d52a1a538 100644 --- a/esphome/components/noblex/noblex.h +++ b/esphome/components/noblex/noblex.h @@ -41,7 +41,8 @@ class NoblexClimate : public climate_ir::ClimateIR { /// Handle received IR Buffer. bool on_receive(remote_base::RemoteReceiveData data) override; bool send_swing_cmd_{false}; - bool receiving_ = false; + bool receiving_{false}; + uint8_t remote_state_[8]{}; }; } // namespace noblex From 9ab5f5d451a4d1aaf030fbff72bff0011478e5fb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:42:05 -0500 Subject: [PATCH 1165/2030] [light] Fix unsigned underflow in addressable scan effect (#14546) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../light/addressable_light_effect.h | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/esphome/components/light/addressable_light_effect.h b/esphome/components/light/addressable_light_effect.h index a85ea4661d..461ddbc085 100644 --- a/esphome/components/light/addressable_light_effect.h +++ b/esphome/components/light/addressable_light_effect.h @@ -171,12 +171,27 @@ class AddressableScanEffect : public AddressableLightEffect { if (now - this->last_move_ < this->move_interval_) return; - if (direction_) { + const auto num_leds = static_cast<uint32_t>(it.size()); + if (this->scan_width_ >= num_leds) { + it.all() = current_color; + it.schedule_show(); + this->last_move_ = now; + return; + } + + const uint32_t max_pos = num_leds - this->scan_width_; + if (this->at_led_ >= max_pos) { + this->at_led_ = max_pos; + this->direction_ = false; + } + + if (this->direction_) { this->at_led_++; - if (this->at_led_ == it.size() - this->scan_width_) + if (this->at_led_ >= max_pos) this->direction_ = false; } else { - this->at_led_--; + if (this->at_led_ > 0) + this->at_led_--; if (this->at_led_ == 0) this->direction_ = true; } From a9cceebb33612054866465254456336fd4d76ba5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:48:50 -0500 Subject: [PATCH 1166/2030] [pid][nextion][pn532_i2c][pipsolar] Fix copy-paste and logic bugs (#14551) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/nextion/nextion_component.cpp | 2 +- esphome/components/pid/pid_autotuner.cpp | 4 ++-- esphome/components/pipsolar/pipsolar.cpp | 1 + esphome/components/pn532_i2c/pn532_i2c.cpp | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/esphome/components/nextion/nextion_component.cpp b/esphome/components/nextion/nextion_component.cpp index 324ad87372..30c8b80524 100644 --- a/esphome/components/nextion/nextion_component.cpp +++ b/esphome/components/nextion/nextion_component.cpp @@ -88,7 +88,7 @@ void NextionComponent::update_component_settings(bool force_update) { this->send_state_to_nextion(); } - if (this->component_flags_.bco_needs_update || (force_update && this->component_flags_.bco2_is_set)) { + if (this->component_flags_.bco_needs_update || (force_update && this->component_flags_.bco_is_set)) { this->nextion_->set_component_background_color(this->variable_name_.c_str(), this->bco_); this->component_flags_.bco_needs_update = false; } diff --git a/esphome/components/pid/pid_autotuner.cpp b/esphome/components/pid/pid_autotuner.cpp index d1d9c200cf..e1ddd1d7c6 100644 --- a/esphome/components/pid/pid_autotuner.cpp +++ b/esphome/components/pid/pid_autotuner.cpp @@ -97,7 +97,7 @@ PIDAutotuner::PIDAutotuneResult PIDAutotuner::update(float setpoint, float proce } bool zc_symmetrical = this->frequency_detector_.is_increase_decrease_symmetrical(); - bool amplitude_convergent = this->frequency_detector_.is_increase_decrease_symmetrical(); + bool amplitude_convergent = this->amplitude_detector_.is_amplitude_convergent(); if (!zc_symmetrical || !amplitude_convergent) { // The frequency/amplitude is not fully accurate yet, try to wait // until the fault clears, or terminate after a while anyway @@ -362,7 +362,7 @@ bool PIDAutotuner::OscillationAmplitudeDetector::is_amplitude_convergent() const for (auto v : this->phase_mins) global_min = std::min(global_min, v); for (auto v : this->phase_maxs) - global_max = std::min(global_max, v); + global_max = std::max(global_max, v); float global_amplitude = (global_max - global_min) / 2.0f; float mean_amplitude = this->get_mean_oscillation_amplitude(); return (mean_amplitude - global_amplitude) / (global_amplitude) < 0.05f; diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index 9c5caec775..eb6d3931e0 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -647,6 +647,7 @@ void Pipsolar::handle_qpiws_(const char *message) { case 34: this->publish_binary_sensor_(enabled, this->warning_high_ac_input_during_bus_soft_start_); value_warnings_present |= enabled.value_or(false); + break; case 35: this->publish_binary_sensor_(enabled, this->warning_battery_equalization_); value_warnings_present |= enabled.value_or(false); diff --git a/esphome/components/pn532_i2c/pn532_i2c.cpp b/esphome/components/pn532_i2c/pn532_i2c.cpp index b306222a21..41f0f079aa 100644 --- a/esphome/components/pn532_i2c/pn532_i2c.cpp +++ b/esphome/components/pn532_i2c/pn532_i2c.cpp @@ -49,7 +49,7 @@ bool PN532I2C::read_response(uint8_t command, std::vector<uint8_t> &data) { return false; } - if (data[1] != 0x00 && data[2] != 0x00 && data[3] != 0xFF) { + if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) { // invalid packet ESP_LOGV(TAG, "read data invalid preamble!"); return false; @@ -95,7 +95,7 @@ uint8_t PN532I2C::read_response_length_() { return 0; } - if (data[1] != 0x00 && data[2] != 0x00 && data[3] != 0xFF) { + if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) { // invalid packet ESP_LOGV(TAG, "read data invalid preamble!"); return 0; From 8f3db96291c06708a23f5171515cd26ec84e33a1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:50:26 -0500 Subject: [PATCH 1167/2030] [esp32_ble_server][weikai][ade7880] Fix copy-paste bugs (#14552) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ade7880/ade7880.cpp | 6 +++--- esphome/components/ade7880/ade7880_registers.h | 3 +++ esphome/components/esp32_ble_server/ble_characteristic.cpp | 4 ++-- esphome/components/weikai/weikai.cpp | 4 +++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/esphome/components/ade7880/ade7880.cpp b/esphome/components/ade7880/ade7880.cpp index f6a15190cd..8fb3e55b91 100644 --- a/esphome/components/ade7880/ade7880.cpp +++ b/esphome/components/ade7880/ade7880.cpp @@ -121,7 +121,7 @@ void ADE7880::update() { this->update_sensor_from_s32_register16_(chan->forward_active_energy, AFWATTHR, [&chan](float val) { return chan->forward_active_energy_total += val / 14400.0f; }); - this->update_sensor_from_s32_register16_(chan->reverse_active_energy, AFWATTHR, [&chan](float val) { + this->update_sensor_from_s32_register16_(chan->reverse_active_energy, ARWATTHR, [&chan](float val) { return chan->reverse_active_energy_total += val / 14400.0f; }); } @@ -137,7 +137,7 @@ void ADE7880::update() { this->update_sensor_from_s32_register16_(chan->forward_active_energy, BFWATTHR, [&chan](float val) { return chan->forward_active_energy_total += val / 14400.0f; }); - this->update_sensor_from_s32_register16_(chan->reverse_active_energy, BFWATTHR, [&chan](float val) { + this->update_sensor_from_s32_register16_(chan->reverse_active_energy, BRWATTHR, [&chan](float val) { return chan->reverse_active_energy_total += val / 14400.0f; }); } @@ -153,7 +153,7 @@ void ADE7880::update() { this->update_sensor_from_s32_register16_(chan->forward_active_energy, CFWATTHR, [&chan](float val) { return chan->forward_active_energy_total += val / 14400.0f; }); - this->update_sensor_from_s32_register16_(chan->reverse_active_energy, CFWATTHR, [&chan](float val) { + this->update_sensor_from_s32_register16_(chan->reverse_active_energy, CRWATTHR, [&chan](float val) { return chan->reverse_active_energy_total += val / 14400.0f; }); } diff --git a/esphome/components/ade7880/ade7880_registers.h b/esphome/components/ade7880/ade7880_registers.h index 8b5b68abb0..9fd8ca3bf5 100644 --- a/esphome/components/ade7880/ade7880_registers.h +++ b/esphome/components/ade7880/ade7880_registers.h @@ -85,6 +85,9 @@ constexpr uint16_t CWATTHR = 0xE402; constexpr uint16_t AFWATTHR = 0xE403; constexpr uint16_t BFWATTHR = 0xE404; constexpr uint16_t CFWATTHR = 0xE405; +constexpr uint16_t ARWATTHR = 0xE406; +constexpr uint16_t BRWATTHR = 0xE407; +constexpr uint16_t CRWATTHR = 0xE408; constexpr uint16_t AFVARHR = 0xE409; constexpr uint16_t BFVARHR = 0xE40A; constexpr uint16_t CFVARHR = 0xE40B; diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index d4ccefd9b2..1806354712 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -310,8 +310,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt (*this->on_write_callback_)(this->value_, param->exec_write.conn_id); } } - esp_err_t err = - esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr); + esp_err_t err = esp_ble_gatts_send_response(gatts_if, param->exec_write.conn_id, param->exec_write.trans_id, + ESP_GATT_OK, nullptr); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_ble_gatts_send_response failed: %d", err); } diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index 1d835daf1e..3f5d6c787c 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -445,6 +445,7 @@ void WeikaiChannel::flush() { } size_t WeikaiChannel::xfer_fifo_to_buffer_() { + size_t total = 0; size_t to_transfer; size_t free; while ((to_transfer = this->rx_in_fifo_()) && (free = this->receive_buffer_.free())) { @@ -458,9 +459,10 @@ size_t WeikaiChannel::xfer_fifo_to_buffer_() { this->reg(0).read_fifo(data, to_transfer); for (size_t i = 0; i < to_transfer; i++) this->receive_buffer_.push(data[i]); + total += to_transfer; } } // while work to do - return to_transfer; + return total; } /// From 0469612d0774ef26acef975446e4c187dde876f8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:02:17 -0500 Subject: [PATCH 1168/2030] [multiple] Fix assorted medium-severity bugs (#14555) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bytebuffer/bytebuffer.h | 2 +- esphome/components/cap1188/cap1188.cpp | 2 +- esphome/components/hte501/hte501.cpp | 2 +- .../components/ina2xx_base/ina2xx_base.cpp | 6 +---- esphome/components/inkplate/inkplate.cpp | 10 ++++----- esphome/components/msa3xx/msa3xx.cpp | 6 +---- esphome/components/nfc/ndef_record_text.cpp | 5 +++++ esphome/components/nfc/nfc.cpp | 22 +++++++++++++------ esphome/components/nfc/nfc.h | 2 +- .../components/template/text/template_text.h | 6 ++++- 10 files changed, 36 insertions(+), 27 deletions(-) diff --git a/esphome/components/bytebuffer/bytebuffer.h b/esphome/components/bytebuffer/bytebuffer.h index 030484ce32..3c68094dbc 100644 --- a/esphome/components/bytebuffer/bytebuffer.h +++ b/esphome/components/bytebuffer/bytebuffer.h @@ -263,7 +263,7 @@ class ByteBuffer { void put_uint8(uint8_t value, size_t offset) { this->data_[offset] = value; } void put_uint16(uint16_t value, size_t offset) { this->put(value, offset); } - void put_uint24(uint32_t value, size_t offset) { this->put(value, offset); } + void put_uint24(uint32_t value, size_t offset) { this->put_uint32_(value, offset, 3); } void put_uint32(uint32_t value, size_t offset) { this->put(value, offset); } void put_uint64(uint64_t value, size_t offset) { this->put(value, offset); } // Signed versions of the put functions diff --git a/esphome/components/cap1188/cap1188.cpp b/esphome/components/cap1188/cap1188.cpp index 9e8c87d147..64bdc620cd 100644 --- a/esphome/components/cap1188/cap1188.cpp +++ b/esphome/components/cap1188/cap1188.cpp @@ -92,7 +92,7 @@ void CAP1188Component::loop() { this->read_register(CAP1188_MAIN, &data, 1); data = data & ~CAP1188_MAIN_INT; - this->write_register(CAP1188_MAIN, &data, 2); + this->write_register(CAP1188_MAIN, &data, 1); } for (auto *channel : this->channels_) { diff --git a/esphome/components/hte501/hte501.cpp b/esphome/components/hte501/hte501.cpp index 972e72c170..ef9ef1fabf 100644 --- a/esphome/components/hte501/hte501.cpp +++ b/esphome/components/hte501/hte501.cpp @@ -49,7 +49,7 @@ void HTE501Component::update() { this->set_timeout(50, [this]() { uint8_t i2c_response[6]; this->read(i2c_response, 6); - if (i2c_response[2] != crc8(i2c_response, 2, 0xFF, 0x31, true) && + if (i2c_response[2] != crc8(i2c_response, 2, 0xFF, 0x31, true) || i2c_response[5] != crc8(i2c_response + 3, 2, 0xFF, 0x31, true)) { this->error_code_ = CRC_CHECK_FAILED; this->status_set_warning(); diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index 8a20192c1e..9f510eef74 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -599,11 +599,7 @@ bool INA2XX::read_unsigned_16_(uint8_t reg, uint16_t &out) { } int64_t INA2XX::two_complement_(uint64_t value, uint8_t bits) { - if (value > (1ULL << (bits - 1))) { - return (int64_t) (value - (1ULL << bits)); - } else { - return (int64_t) value; - } + return (int64_t) (value << (64 - bits)) >> (64 - bits); } } // namespace ina2xx_base } // namespace esphome diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index df9c2b29c7..7551c6fc77 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -407,7 +407,7 @@ void Inkplate::display1b_() { break; } - uint32_t clock = (1 << this->cl_pin_->get_pin()); + uint32_t clock = (1UL << this->cl_pin_->get_pin()); uint32_t data_mask = this->get_data_pin_mask_(); ESP_LOGV(TAG, "Display1b start loops (%ums)", millis() - start_time); @@ -575,7 +575,7 @@ void Inkplate::display3b_() { break; } - uint32_t clock = (1 << this->cl_pin_->get_pin()); + uint32_t clock = (1UL << this->cl_pin_->get_pin()); uint32_t data_mask = this->get_data_pin_mask_(); uint32_t pos; uint32_t data; @@ -646,7 +646,7 @@ bool Inkplate::partial_update_() { int rep = (this->model_ == INKPLATE_6_V2) ? 6 : 5; eink_on_(); - uint32_t clock = (1 << this->cl_pin_->get_pin()); + uint32_t clock = (1UL << this->cl_pin_->get_pin()); uint32_t data_mask = this->get_data_pin_mask_(); for (int k = 0; k < rep; k++) { vscan_start_(); @@ -704,7 +704,7 @@ void Inkplate::vscan_start_() { } void Inkplate::hscan_start_(uint32_t d) { - uint8_t clock = (1 << this->cl_pin_->get_pin()); + uint32_t clock = (1UL << this->cl_pin_->get_pin()); this->sph_pin_->digital_write(false); GPIO.out_w1ts = d | clock; GPIO.out_w1tc = this->get_data_pin_mask_() | clock; @@ -751,7 +751,7 @@ void Inkplate::clean_fast_(uint8_t c, uint8_t rep) { uint32_t send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) | (((data & 0b11100000) >> 5) << 25); - uint32_t clock = (1 << this->cl_pin_->get_pin()); + uint32_t clock = (1UL << this->cl_pin_->get_pin()); for (int k = 0; k < rep; k++) { vscan_start_(); diff --git a/esphome/components/msa3xx/msa3xx.cpp b/esphome/components/msa3xx/msa3xx.cpp index e46bfed193..6d6b21e6af 100644 --- a/esphome/components/msa3xx/msa3xx.cpp +++ b/esphome/components/msa3xx/msa3xx.cpp @@ -364,11 +364,7 @@ void MSA3xxComponent::setup_offset_(float offset_x, float offset_y, float offset } int64_t MSA3xxComponent::twos_complement_(uint64_t value, uint8_t bits) { - if (value > (1ULL << (bits - 1))) { - return (int64_t) (value - (1ULL << bits)); - } else { - return (int64_t) value; - } + return (int64_t) (value << (64 - bits)) >> (64 - bits); } void binary_event_debounce(bool state, bool old_state, uint32_t now, uint32_t &last_ms, Trigger<> &trigger, diff --git a/esphome/components/nfc/ndef_record_text.cpp b/esphome/components/nfc/ndef_record_text.cpp index 80b0108b46..8a9a2cb014 100644 --- a/esphome/components/nfc/ndef_record_text.cpp +++ b/esphome/components/nfc/ndef_record_text.cpp @@ -14,6 +14,11 @@ NdefRecordText::NdefRecordText(const std::vector<uint8_t> &payload) { uint8_t language_code_length = payload[0] & 0b00111111; // Todo, make use of encoding bit? + if (1 + language_code_length > payload.size()) { + ESP_LOGE(TAG, "Record payload too short for language code"); + return; + } + this->language_code_ = std::string(payload.begin() + 1, payload.begin() + 1 + language_code_length); this->text_ = std::string(payload.begin() + 1 + language_code_length, payload.end()); diff --git a/esphome/components/nfc/nfc.cpp b/esphome/components/nfc/nfc.cpp index 8567b0969a..55543cd292 100644 --- a/esphome/components/nfc/nfc.cpp +++ b/esphome/components/nfc/nfc.cpp @@ -35,7 +35,7 @@ uint8_t guess_tag_type(uint8_t uid_length) { } } -uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) { +int8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) { for (uint8_t i = 0; i < MIFARE_CLASSIC_BLOCK_SIZE; i++) { if (data[i] == 0x00) { // Do nothing, skip @@ -49,17 +49,25 @@ uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) { } bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index) { + if (data.size() < MIFARE_CLASSIC_BLOCK_SIZE) { + ESP_LOGE(TAG, "Error, data too short for NDEF detection."); + return false; + } auto i = get_mifare_classic_ndef_start_index(data); - if (data[i] != 0x03) { + if (i < 0 || data[i] != 0x03) { ESP_LOGE(TAG, "Error, Can't decode message length."); return false; } - if (data[i + 1] == 0xFF) { - message_length = ((0xFF & data[i + 2]) << 8) | (0xFF & data[i + 3]); - message_start_index = i + MIFARE_CLASSIC_LONG_TLV_SIZE; + uint8_t idx = static_cast<uint8_t>(i); + if (idx + 4 <= data.size() && data[idx + 1] == 0xFF) { + message_length = ((0xFF & data[idx + 2]) << 8) | (0xFF & data[idx + 3]); + message_start_index = idx + MIFARE_CLASSIC_LONG_TLV_SIZE; + } else if (idx + 2 <= data.size()) { + message_length = data[idx + 1]; + message_start_index = idx + MIFARE_CLASSIC_SHORT_TLV_SIZE; } else { - message_length = data[i + 1]; - message_start_index = i + MIFARE_CLASSIC_SHORT_TLV_SIZE; + ESP_LOGE(TAG, "Error, TLV data too short."); + return false; } return true; } diff --git a/esphome/components/nfc/nfc.h b/esphome/components/nfc/nfc.h index cdaea82af6..8ca5cb7ea4 100644 --- a/esphome/components/nfc/nfc.h +++ b/esphome/components/nfc/nfc.h @@ -72,7 +72,7 @@ ESPDEPRECATED("Use format_bytes_to() with stack buffer instead. Removed in 2026. std::string format_bytes(std::span<const uint8_t> bytes); uint8_t guess_tag_type(uint8_t uid_length); -uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data); +int8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data); bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index); uint32_t get_mifare_classic_buffer_size(uint32_t message_length); diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index 88c6afdf2c..7f176db09e 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -52,7 +52,11 @@ template<uint8_t SZ> class TextSaver : public TemplateTextSaverBase { bool hasdata = this->pref_.load(&temp); if (hasdata) { - value.assign(temp + 1, (size_t) temp[0]); + size_t len = static_cast<uint8_t>(temp[0]); + if (len > SZ) { + len = SZ; + } + value.assign(temp + 1, len); } this->prev_.assign(value); From 4f4b2bfdecc1ccc06f344d4e0c6dbad88537a3a6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:14:35 -0500 Subject: [PATCH 1169/2030] [bmp581_base][bl0906] Fix 24-bit sign extension bugs (#14558) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bl0906/bl0906.cpp | 4 +++- esphome/components/bmp581_base/bmp581_base.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/bl0906/bl0906.cpp b/esphome/components/bl0906/bl0906.cpp index c1cd48a1ac..7b643bba98 100644 --- a/esphome/components/bl0906/bl0906.cpp +++ b/esphome/components/bl0906/bl0906.cpp @@ -10,7 +10,9 @@ static const char *const TAG = "bl0906"; constexpr uint32_t to_uint32_t(ube24_t input) { return input.h << 16 | input.m << 8 | input.l; } -constexpr int32_t to_int32_t(sbe24_t input) { return input.h << 16 | input.m << 8 | input.l; } +constexpr int32_t to_int32_t(sbe24_t input) { + return static_cast<int32_t>(encode_uint32((uint8_t) input.h, input.m, input.l, 0)) >> 8; +} // The SUM byte is (Addr+Data_L+Data_M+Data_H)&0xFF negated; constexpr uint8_t bl0906_checksum(const uint8_t address, const DataPacket *data) { diff --git a/esphome/components/bmp581_base/bmp581_base.cpp b/esphome/components/bmp581_base/bmp581_base.cpp index c4a96ebc39..89a92de31d 100644 --- a/esphome/components/bmp581_base/bmp581_base.cpp +++ b/esphome/components/bmp581_base/bmp581_base.cpp @@ -429,7 +429,7 @@ bool BMP581Component::read_temperature_(float &temperature) { } // temperature MSB is in data[2], LSB is in data[1], XLSB in data[0] - int32_t raw_temp = (int32_t) data[2] << 16 | (int32_t) data[1] << 8 | (int32_t) data[0]; + int32_t raw_temp = static_cast<int32_t>(encode_uint32(data[2], data[1], data[0], 0)) >> 8; temperature = (float) (raw_temp / 65536.0); // convert measurement to degrees Celsius (page 22 of datasheet) return true; @@ -458,7 +458,7 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float & } // temperature MSB is in data[2], LSB is in data[1], XLSB in data[0] - int32_t raw_temp = (int32_t) data[2] << 16 | (int32_t) data[1] << 8 | (int32_t) data[0]; + int32_t raw_temp = static_cast<int32_t>(encode_uint32(data[2], data[1], data[0], 0)) >> 8; temperature = (float) (raw_temp / 65536.0); // convert measurement to degrees Celsius (page 22 of datasheet) // pressure MSB is in data[5], LSB is in data[4], XLSB in data[3] From 2c83c6a79f356d3f0f6910fc573e47c53e695c5e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:47:56 -0500 Subject: [PATCH 1170/2030] [shelly_dimmer][lvgl][seeed_mr60fda2][packet_transport] Fix buffer bounds checks (#14534) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/lvgl/lvgl_esphome.cpp | 3 ++ .../packet_transport/packet_transport.cpp | 2 + .../seeed_mr60fda2/seeed_mr60fda2.cpp | 44 ++++++++----------- .../shelly_dimmer/shelly_dimmer.cpp | 4 +- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 3e447e9169..66cb25b864 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -422,6 +422,9 @@ void LvglComponent::write_random_() { auto row = random_uint32() % this->disp_drv_.ver_res; row = row / this->draw_rounding * this->draw_rounding; auto size = ((random_uint32() % 32) / this->draw_rounding + 2) * this->draw_rounding - 1; + // clamp size so the square fits within the draw buffer + if ((size + 1) * (size + 1) > this->draw_buf_.size) + size = static_cast<decltype(size)>(sqrtf(this->draw_buf_.size)) - 1; lv_area_t area; area.x1 = col; area.y1 = row; diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index 6f1286b469..964037a02c 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -137,6 +137,8 @@ class PacketDecoder { return DECODE_EMPTY; if (this->buffer_[this->position_] != key) return DECODE_UNMATCHED; + if (this->position_ + 1 + sizeof(T) > this->len_) + return DECODE_ERROR; this->position_++; T value = 0; for (size_t i = 0; i != sizeof(T); ++i) { diff --git a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp index 5d571618d3..c6527a948e 100644 --- a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +++ b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp @@ -149,28 +149,25 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) { switch (this->current_frame_locate_) { case LOCATE_FRAME_HEADER: // starting buffer if (buffer == FRAME_HEADER_BUFFER) { - this->current_frame_len_ = 1; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_len_ = 0; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; } break; case LOCATE_ID_FRAME1: this->current_frame_id_ = buffer << 8; - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; break; case LOCATE_ID_FRAME2: this->current_frame_id_ += buffer; - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; break; case LOCATE_LENGTH_FRAME_H: this->current_data_frame_len_ = buffer << 8; - if (this->current_data_frame_len_ == 0x00) { - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + if (this->current_data_frame_len_ == 0) { + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; } else { this->current_frame_locate_ = LOCATE_FRAME_HEADER; @@ -181,15 +178,13 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) { if (this->current_data_frame_len_ > DATA_BUF_MAX_SIZE) { this->current_frame_locate_ = LOCATE_FRAME_HEADER; } else { - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; } break; case LOCATE_TYPE_FRAME1: this->current_frame_type_ = buffer << 8; - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; break; case LOCATE_TYPE_FRAME2: @@ -198,8 +193,7 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) { (this->current_frame_type_ == PEOPLE_EXIST_TYPE_BUFFER) || (this->current_frame_type_ == RESULT_INSTALL_HEIGHT) || (this->current_frame_type_ == RESULT_PARAMETERS) || (this->current_frame_type_ == RESULT_HEIGHT_THRESHOLD) || (this->current_frame_type_ == RESULT_SENSITIVITY)) { - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; } else { this->current_frame_locate_ = LOCATE_FRAME_HEADER; @@ -207,8 +201,7 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) { break; case LOCATE_HEAD_CKSUM_FRAME: if (validate_checksum(this->current_frame_buf_, this->current_frame_len_, buffer)) { - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; } else { ESP_LOGD(TAG, "HEAD_CKSUM_FRAME ERROR: 0x%02x", buffer); @@ -223,21 +216,20 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) { } break; case LOCATE_DATA_FRAME: - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; - this->current_data_buf_[this->current_frame_len_ - LEN_TO_DATA_FRAME] = buffer; - if (this->current_frame_len_ - LEN_TO_HEAD_CKSUM == this->current_data_frame_len_) { - this->current_frame_locate_++; - } - if (this->current_frame_len_ > FRAME_BUF_MAX_SIZE) { + if (this->current_frame_len_ >= FRAME_BUF_MAX_SIZE) { ESP_LOGD(TAG, "PRACTICE_DATA_FRAME_LEN ERROR: %d", this->current_frame_len_ - LEN_TO_HEAD_CKSUM); this->current_frame_locate_ = LOCATE_FRAME_HEADER; + break; + } + this->current_data_buf_[this->current_frame_len_ - LEN_TO_DATA_FRAME + 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; + if (this->current_frame_len_ - LEN_TO_HEAD_CKSUM == this->current_data_frame_len_) { + this->current_frame_locate_++; } break; case LOCATE_DATA_CKSUM_FRAME: if (validate_checksum(this->current_data_buf_, this->current_data_frame_len_, buffer)) { - this->current_frame_len_++; - this->current_frame_buf_[this->current_frame_len_ - 1] = buffer; + this->current_frame_buf_[this->current_frame_len_++] = buffer; this->current_frame_locate_++; this->process_frame_(); } else { diff --git a/esphome/components/shelly_dimmer/shelly_dimmer.cpp b/esphome/components/shelly_dimmer/shelly_dimmer.cpp index bdb33d31af..88fcbcbfe1 100644 --- a/esphome/components/shelly_dimmer/shelly_dimmer.cpp +++ b/esphome/components/shelly_dimmer/shelly_dimmer.cpp @@ -188,8 +188,8 @@ bool ShellyDimmer::upgrade_firmware_() { break; } - std::memcpy(buffer, p, BUFFER_SIZE); - p += BUFFER_SIZE; + std::memcpy(buffer, p, len); + p += len; if (stm32_write_memory(stm32, addr, buffer, len) != STM32_ERR_OK) { ESP_LOGW(TAG, "Failed to write to STM32 flash memory"); From 587bf68091caffac14f4d7ed2714fac28848354c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:03:30 -0500 Subject: [PATCH 1171/2030] [ltr501][pvvx_mithermometer][smt100] Convert static locals to instance members (#14569) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/ltr501/ltr501.cpp | 21 +++++++++---------- esphome/components/ltr501/ltr501.h | 3 +++ .../pvvx_mithermometer/pvvx_mithermometer.cpp | 7 +++---- .../pvvx_mithermometer/pvvx_mithermometer.h | 2 ++ esphome/components/smt100/smt100.cpp | 16 +++++++------- esphome/components/smt100/smt100.h | 3 +++ 6 files changed, 28 insertions(+), 24 deletions(-) diff --git a/esphome/components/ltr501/ltr501.cpp b/esphome/components/ltr501/ltr501.cpp index 04de91e362..4c9006be1d 100644 --- a/esphome/components/ltr501/ltr501.cpp +++ b/esphome/components/ltr501/ltr501.cpp @@ -146,7 +146,6 @@ void LTRAlsPs501Component::update() { void LTRAlsPs501Component::loop() { ErrorCode err = i2c::ERROR_OK; - static uint8_t tries{0}; switch (this->state_) { case State::DELAYED_SETUP: @@ -175,20 +174,20 @@ void LTRAlsPs501Component::loop() { case State::WAITING_FOR_DATA: if (this->is_als_data_ready_(this->als_readings_) == LtrDataAvail::LTR_DATA_OK) { - tries = 0; + this->tries_ = 0; ESP_LOGV(TAG, "Reading sensor data assuming gain = %.0fx, time = %d ms", get_gain_coeff(this->als_readings_.gain), get_itime_ms(this->als_readings_.integration_time)); this->read_sensor_data_(this->als_readings_); this->apply_lux_calculation_(this->als_readings_); this->state_ = State::DATA_COLLECTED; - } else if (tries >= MAX_TRIES) { + } else if (this->tries_ >= MAX_TRIES) { ESP_LOGW(TAG, "Can't get data after several tries. Aborting."); - tries = 0; + this->tries_ = 0; this->status_set_warning(); this->state_ = State::IDLE; return; } else { - tries++; + this->tries_++; } break; @@ -230,21 +229,21 @@ void LTRAlsPs501Component::loop() { } void LTRAlsPs501Component::check_and_trigger_ps_() { - static uint32_t last_high_trigger_time{0}; - static uint32_t last_low_trigger_time{0}; uint16_t ps_data = this->read_ps_data_(); uint32_t now = millis(); if (ps_data != this->ps_readings_) { this->ps_readings_ = ps_data; // Higher values - object is closer to sensor - if (ps_data > this->ps_threshold_high_ && now - last_high_trigger_time >= this->ps_cooldown_time_s_ * 1000) { - last_high_trigger_time = now; + if (ps_data > this->ps_threshold_high_ && + now - this->last_ps_high_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) { + this->last_ps_high_trigger_time_ = now; ESP_LOGD(TAG, "Proximity high threshold triggered. Value = %d, Trigger level = %d", ps_data, this->ps_threshold_high_); this->on_ps_high_trigger_callback_.call(); - } else if (ps_data < this->ps_threshold_low_ && now - last_low_trigger_time >= this->ps_cooldown_time_s_ * 1000) { - last_low_trigger_time = now; + } else if (ps_data < this->ps_threshold_low_ && + now - this->last_ps_low_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) { + this->last_ps_low_trigger_time_ = now; ESP_LOGD(TAG, "Proximity low threshold triggered. Value = %d, Trigger level = %d", ps_data, this->ps_threshold_low_); this->on_ps_low_trigger_callback_.call(); diff --git a/esphome/components/ltr501/ltr501.h b/esphome/components/ltr501/ltr501.h index 02c025da30..d9a53c9bd4 100644 --- a/esphome/components/ltr501/ltr501.h +++ b/esphome/components/ltr501/ltr501.h @@ -74,6 +74,7 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { READY_TO_PUBLISH, KEEP_PUBLISHING } state_{State::NOT_INITIALIZED}; + uint8_t tries_{0}; LtrType ltr_type_{LtrType::LTR_TYPE_ALS_ONLY}; @@ -130,6 +131,8 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { PsGain501 ps_gain_{PsGain501::PS_GAIN_1}; uint16_t ps_threshold_high_{0xffff}; uint16_t ps_threshold_low_{0x0000}; + uint32_t last_ps_high_trigger_time_{0}; + uint32_t last_ps_low_trigger_time_{0}; // // Sensors for publishing data diff --git a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp index 239a1e74fe..35badf48bb 100644 --- a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp +++ b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.cpp @@ -66,12 +66,11 @@ optional<ParseResult> PVVXMiThermometer::parse_header_(const esp32_ble_tracker:: return {}; } - static uint8_t last_frame_count = 0; - if (last_frame_count == raw[13]) { - ESP_LOGVV(TAG, "parse_header(): duplicate data packet received (%hhu).", last_frame_count); + if (this->last_frame_count_ == raw[13]) { + ESP_LOGVV(TAG, "parse_header(): duplicate data packet received (%hhu).", this->last_frame_count_); return {}; } - last_frame_count = raw[13]; + this->last_frame_count_ = raw[13]; return result; } diff --git a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.h b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.h index c15e1e7e22..09b5e91a16 100644 --- a/esphome/components/pvvx_mithermometer/pvvx_mithermometer.h +++ b/esphome/components/pvvx_mithermometer/pvvx_mithermometer.h @@ -39,6 +39,8 @@ class PVVXMiThermometer : public Component, public esp32_ble_tracker::ESPBTDevic sensor::Sensor *battery_voltage_{nullptr}; sensor::Sensor *signal_strength_{nullptr}; + uint8_t last_frame_count_{0}; + optional<ParseResult> parse_header_(const esp32_ble_tracker::ServiceData &service_data); bool parse_message_(const std::vector<uint8_t> &message, ParseResult &result); bool report_results_(const optional<ParseResult> &result, const char *address); diff --git a/esphome/components/smt100/smt100.cpp b/esphome/components/smt100/smt100.cpp index 1bcb964264..105cc06edb 100644 --- a/esphome/components/smt100/smt100.cpp +++ b/esphome/components/smt100/smt100.cpp @@ -12,10 +12,9 @@ void SMT100Component::update() { } void SMT100Component::loop() { - static char buffer[MAX_LINE_LENGTH]; while (this->available() != 0) { - if (readline_(read(), buffer, MAX_LINE_LENGTH) > 0) { - int counts = (int) strtol((strtok(buffer, ",")), nullptr, 10); + if (this->readline_(this->read(), this->readline_buffer_, MAX_LINE_LENGTH) > 0) { + int counts = (int) strtol((strtok(this->readline_buffer_, ",")), nullptr, 10); float permittivity = (float) strtod((strtok(nullptr, ",")), nullptr); float moisture = (float) strtod((strtok(nullptr, ",")), nullptr); float temperature = (float) strtod((strtok(nullptr, ",")), nullptr); @@ -56,7 +55,6 @@ void SMT100Component::dump_config() { } int SMT100Component::readline_(int readch, char *buffer, int len) { - static int pos = 0; int rpos; if (readch > 0) { @@ -64,13 +62,13 @@ int SMT100Component::readline_(int readch, char *buffer, int len) { case '\n': // Ignore new-lines break; case '\r': // Return on CR - rpos = pos; - pos = 0; // Reset position index ready for next time + rpos = this->readline_pos_; + this->readline_pos_ = 0; // Reset position index ready for next time return rpos; default: - if (pos < len - 1) { - buffer[pos++] = readch; - buffer[pos] = 0; + if (this->readline_pos_ < len - 1) { + buffer[this->readline_pos_++] = readch; + buffer[this->readline_pos_] = 0; } } } diff --git a/esphome/components/smt100/smt100.h b/esphome/components/smt100/smt100.h index df8803e1c6..cb01b1ed55 100644 --- a/esphome/components/smt100/smt100.h +++ b/esphome/components/smt100/smt100.h @@ -28,6 +28,9 @@ class SMT100Component : public PollingComponent, public uart::UARTDevice { protected: int readline_(int readch, char *buffer, int len); + char readline_buffer_[MAX_LINE_LENGTH]{}; + int readline_pos_{0}; + sensor::Sensor *counts_sensor_{nullptr}; sensor::Sensor *permittivity_sensor_{nullptr}; sensor::Sensor *moisture_sensor_{nullptr}; From 5777908da712d64dde2f760d68aaa707b606dc1f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:03:53 -0500 Subject: [PATCH 1172/2030] [iaqcore][scd30][sen21231][beken_spi_led_strip] Fix uninitialized variables and missing error checks (#14568) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/beken_spi_led_strip/led_strip.cpp | 2 +- esphome/components/iaqcore/iaqcore.cpp | 10 ++++++---- esphome/components/scd30/scd30.cpp | 2 +- esphome/components/sen21231/sen21231.cpp | 7 ++++++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/esphome/components/beken_spi_led_strip/led_strip.cpp b/esphome/components/beken_spi_led_strip/led_strip.cpp index 67b8472257..f425f3ca5c 100644 --- a/esphome/components/beken_spi_led_strip/led_strip.cpp +++ b/esphome/components/beken_spi_led_strip/led_strip.cpp @@ -78,7 +78,7 @@ static void spi_set_clock(uint32_t max_hz) { int source_clk = 0; int spi_clk = 0; int div = 0; - uint32_t param; + uint32_t param = PWD_SPI_CLK_BIT; if (max_hz > 4333000) { if (max_hz > 30000000) { spi_clk = 30000000; diff --git a/esphome/components/iaqcore/iaqcore.cpp b/esphome/components/iaqcore/iaqcore.cpp index 274f9086b6..c414eb8f60 100644 --- a/esphome/components/iaqcore/iaqcore.cpp +++ b/esphome/components/iaqcore/iaqcore.cpp @@ -10,11 +10,13 @@ static const char *const TAG = "iaqcore"; enum IAQCoreErrorCode : uint8_t { ERROR_OK = 0, ERROR_RUNIN = 0x10, ERROR_BUSY = 0x01, ERROR_ERROR = 0x80 }; +static constexpr size_t SENSOR_DATA_LENGTH = 9; + struct SensorData { - uint16_t co2; - IAQCoreErrorCode status; int32_t resistance; + uint16_t co2; uint16_t tvoc; + IAQCoreErrorCode status; SensorData(const uint8_t *buffer) { this->co2 = encode_uint16(buffer[0], buffer[1]); @@ -33,9 +35,9 @@ void IAQCore::setup() { } void IAQCore::update() { - uint8_t buffer[sizeof(SensorData)]; + uint8_t buffer[SENSOR_DATA_LENGTH]; - if (this->read_register(0xB5, buffer, sizeof(buffer)) != i2c::ERROR_OK) { + if (this->read_register(0xB5, buffer, SENSOR_DATA_LENGTH) != i2c::ERROR_OK) { ESP_LOGD(TAG, "Read failed"); this->status_set_warning(); this->publish_nans_(); diff --git a/esphome/components/scd30/scd30.cpp b/esphome/components/scd30/scd30.cpp index 3c2c06fd68..e61d0142be 100644 --- a/esphome/components/scd30/scd30.cpp +++ b/esphome/components/scd30/scd30.cpp @@ -222,7 +222,7 @@ bool SCD30Component::force_recalibration_with_reference(uint16_t co2_reference) } uint16_t SCD30Component::get_forced_calibration_reference() { - uint16_t forced_calibration_reference; + uint16_t forced_calibration_reference = 0; // Get current CO2 calibration if (!this->get_register(SCD30_CMD_FORCED_CALIBRATION, forced_calibration_reference)) { ESP_LOGE(TAG, "Unable to read forced calibration reference."); diff --git a/esphome/components/sen21231/sen21231.cpp b/esphome/components/sen21231/sen21231.cpp index 67001c3f14..8c9f3d7134 100644 --- a/esphome/components/sen21231/sen21231.cpp +++ b/esphome/components/sen21231/sen21231.cpp @@ -20,7 +20,12 @@ void Sen21231Sensor::dump_config() { void Sen21231Sensor::read_data_() { person_sensor_results_t results; - this->read_bytes(PERSON_SENSOR_I2C_ADDRESS, (uint8_t *) &results, sizeof(results)); + if (!this->read_bytes(PERSON_SENSOR_I2C_ADDRESS, (uint8_t *) &results, sizeof(results))) { + ESP_LOGW(TAG, "Failed to read data from SEN21231"); + this->status_set_warning(); + return; + } + this->status_clear_warning(); ESP_LOGD(TAG, "SEN21231: %d faces detected", results.num_faces); this->publish_state(results.num_faces); if (results.num_faces == 1) { From de7572bd3e7ebb9308744efb6f7faf88c480629d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 16:04:12 -0500 Subject: [PATCH 1173/2030] [lightwaverf] Fix ISR safety issues (#14563) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/lightwaverf/LwRx.cpp | 14 +++++++++++--- esphome/components/lightwaverf/LwRx.h | 4 ++-- esphome/components/lightwaverf/LwTx.cpp | 3 ++- esphome/components/lightwaverf/LwTx.h | 4 ++-- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/esphome/components/lightwaverf/LwRx.cpp b/esphome/components/lightwaverf/LwRx.cpp index 2b1ad5e870..9710457850 100644 --- a/esphome/components/lightwaverf/LwRx.cpp +++ b/esphome/components/lightwaverf/LwRx.cpp @@ -8,6 +8,7 @@ #include "LwRx.h" #include <cstring> +#include "esphome/core/helpers.h" namespace esphome { namespace lightwaverf { @@ -185,13 +186,20 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) { bool ret = true; int16_t j = 0; // int if (this->rx_msgcomplete && len <= RX_MSGLEN) { + // Copy message under interrupt lock to prevent ISR overwriting rx_msg mid-read + uint8_t msg_copy[RX_MSGLEN]; + { + InterruptLock lock; + memcpy(msg_copy, this->rx_msg, RX_MSGLEN); + this->rx_msgcomplete = false; + } for (uint8_t i = 0; ret && i < RX_MSGLEN; i++) { if (this->rx_translate || (len != RX_MSGLEN)) { - j = this->rx_find_nibble_(this->rx_msg[i]); + j = this->rx_find_nibble_(msg_copy[i]); if (j < 0) ret = false; } else { - j = this->rx_msg[i]; + j = msg_copy[i]; } switch (len) { case 4: @@ -199,6 +207,7 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) { buf[2] = j; if (i == 2) buf[3] = j; + [[fallthrough]]; case 2: if (i == 3) buf[0] = j; @@ -212,7 +221,6 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) { break; } } - this->rx_msgcomplete = false; } else { ret = false; } diff --git a/esphome/components/lightwaverf/LwRx.h b/esphome/components/lightwaverf/LwRx.h index 7200f9a51c..8b34de9fbb 100644 --- a/esphome/components/lightwaverf/LwRx.h +++ b/esphome/components/lightwaverf/LwRx.h @@ -105,8 +105,8 @@ class LwRx { uint32_t rx_prev; // time of previous interrupt in microseconds - bool rx_msgcomplete = false; // set high when message available - bool rx_translate = true; // Set false to get raw data + volatile bool rx_msgcomplete = false; // set high when message available + bool rx_translate = true; // Set false to get raw data uint8_t rx_state = 0; diff --git a/esphome/components/lightwaverf/LwTx.cpp b/esphome/components/lightwaverf/LwTx.cpp index b69b93b978..8852935bfd 100644 --- a/esphome/components/lightwaverf/LwTx.cpp +++ b/esphome/components/lightwaverf/LwTx.cpp @@ -192,7 +192,8 @@ void LwTx::lwtx_set_gap_multiplier(uint8_t gap_multiplier) { this->tx_gap_multip void LwTx::lw_timer_start() { { InterruptLock lock; - static LwTx *arg = this; // NOLINT + static LwTx *arg; + arg = this; timer1_attachInterrupt([] { isr_t_xtimer(arg); }); timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); timer1_write(this->espPeriod); diff --git a/esphome/components/lightwaverf/LwTx.h b/esphome/components/lightwaverf/LwTx.h index fe7b942a3a..9192426440 100644 --- a/esphome/components/lightwaverf/LwTx.h +++ b/esphome/components/lightwaverf/LwTx.h @@ -62,8 +62,8 @@ class LwTx { uint8_t tx_repeats = 12; // Number of repeats of message sent uint8_t txon = 1; uint8_t txoff = 0; - bool tx_msg_active = false; // set true to activate message sending - bool tx_translate = true; // Set false to send raw data + volatile bool tx_msg_active = false; // set true to activate message sending + bool tx_translate = true; // Set false to send raw data uint8_t tx_buf[TX_MSGLEN]; // the message buffer during reception uint8_t tx_repeat = 0; // counter for repeats From c26c5935b6c9bb1b7a521efa7188a0c3dad74e66 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:12:19 -1000 Subject: [PATCH 1174/2030] Bump github/codeql-action from 4.32.5 to 4.32.6 (#14566) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4bd018b5c9..1a0c54da6d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5 + uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 with: category: "/language:${{matrix.language}}" From 086c1bb505dc718d35e9c91b6fbea5bb54705735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 12:12:44 -1000 Subject: [PATCH 1175/2030] Bump docker/build-push-action from 6.19.2 to 7.0.0 in /.github/actions/build-image (#14567) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/build-image/action.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/build-image/action.yaml b/.github/actions/build-image/action.yaml index 38e93c4f17..a895226030 100644 --- a/.github/actions/build-image/action.yaml +++ b/.github/actions/build-image/action.yaml @@ -47,7 +47,7 @@ runs: - name: Build and push to ghcr by digest id: build-ghcr - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false @@ -73,7 +73,7 @@ runs: - name: Build and push to dockerhub by digest id: build-dockerhub - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0 env: DOCKER_BUILD_SUMMARY: false DOCKER_BUILD_RECORD_UPLOAD: false From 035f98569326bafd7da350e4a15c2739c424e987 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:16:36 +0000 Subject: [PATCH 1176/2030] Bump ruff from 0.15.4 to 0.15.5 (#14565) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d70dd9d0e1..b036da6ef1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.3 + rev: v0.15.5 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 6b2617b656..93a20896aa 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.4 # also change in .pre-commit-config.yaml when updating +ruff==0.15.5 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From d8deb2255d3a982bb3a755efa9291a2a59014c69 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 6 Mar 2026 17:18:09 -0500 Subject: [PATCH 1177/2030] [mipi_rgb] Fix byte order and dirty bounds in fill() (#14537) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/mipi_rgb/mipi_rgb.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index 7ff6868c15..ae7c795846 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -288,9 +288,7 @@ void MipiRgb::draw_pixel_at(int x, int y, Color color) { if (!this->check_buffer_()) return; size_t pos = (y * this->width_) + x; - uint8_t hi_byte = static_cast<uint8_t>(color.r & 0xF8) | (color.g >> 5); - uint8_t lo_byte = static_cast<uint8_t>((color.g & 0x1C) << 3) | (color.b >> 3); - uint16_t new_color = hi_byte | (lo_byte << 8); // big endian + uint16_t new_color = convert_big_endian(display::ColorUtil::color_to_565(color)); if (this->buffer_[pos] == new_color) return; this->buffer_[pos] = new_color; @@ -315,10 +313,12 @@ void MipiRgb::fill(Color color) { } auto *ptr_16 = reinterpret_cast<uint16_t *>(this->buffer_); - uint8_t hi_byte = static_cast<uint8_t>(color.r & 0xF8) | (color.g >> 5); - uint8_t lo_byte = static_cast<uint8_t>((color.g & 0x1C) << 3) | (color.b >> 3); - uint16_t new_color = lo_byte | (hi_byte << 8); // little endian + uint16_t new_color = convert_big_endian(display::ColorUtil::color_to_565(color)); std::fill_n(ptr_16, this->width_ * this->height_, new_color); + this->x_low_ = 0; + this->y_low_ = 0; + this->x_high_ = this->width_ - 1; + this->y_high_ = this->height_ - 1; } int MipiRgb::get_width() { From f53ee70caadb75ef3ffe20f2a471d15ba06e34a7 Mon Sep 17 00:00:00 2001 From: AndreKR <haensel@creations.de> Date: Sat, 7 Mar 2026 01:29:20 +0100 Subject: [PATCH 1178/2030] [http_request] Make TLS buffer configurable on ESP8266 (#14009) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/http_request/__init__.py | 10 ++++++++++ .../components/http_request/http_request_arduino.cpp | 8 +++----- esphome/components/http_request/http_request_arduino.h | 10 ++++++++++ tests/components/http_request/test.esp8266-ard.yaml | 8 +++++--- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 2d6ecae0bc..81337ebdf6 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -50,6 +50,8 @@ CONF_FOLLOW_REDIRECTS = "follow_redirects" CONF_REDIRECT_LIMIT = "redirect_limit" CONF_BUFFER_SIZE_RX = "buffer_size_rx" CONF_BUFFER_SIZE_TX = "buffer_size_tx" +CONF_TLS_BUFFER_SIZE_RX = "tls_buffer_size_rx" +CONF_TLS_BUFFER_SIZE_TX = "tls_buffer_size_tx" CONF_CA_CERTIFICATE_PATH = "ca_certificate_path" CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size" @@ -124,6 +126,12 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_BUFFER_SIZE_TX, esp32=512): cv.All( cv.uint16_t, cv.only_on_esp32 ), + cv.SplitDefault(CONF_TLS_BUFFER_SIZE_RX, esp8266=512): cv.All( + cv.uint16_t, cv.only_on_esp8266 + ), + cv.SplitDefault(CONF_TLS_BUFFER_SIZE_TX, esp8266=512): cv.All( + cv.uint16_t, cv.only_on_esp8266 + ), cv.Optional(CONF_CA_CERTIFICATE_PATH): cv.All( cv.file_, cv.Any(cv.only_on(PLATFORM_HOST), cv.only_on_esp32), @@ -150,6 +158,8 @@ 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") + cg.add(var.set_tls_buffer_size_rx(config[CONF_TLS_BUFFER_SIZE_RX])) + cg.add(var.set_tls_buffer_size_tx(config[CONF_TLS_BUFFER_SIZE_TX])) if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT): cg.add(var.set_watchdog_timeout(timeout_ms)) diff --git a/esphome/components/http_request/http_request_arduino.cpp b/esphome/components/http_request/http_request_arduino.cpp index 56b51e8b5a..f0dd649285 100644 --- a/esphome/components/http_request/http_request_arduino.cpp +++ b/esphome/components/http_request/http_request_arduino.cpp @@ -18,8 +18,6 @@ namespace esphome::http_request { static const char *const TAG = "http_request.arduino"; #ifdef USE_ESP8266 -static constexpr int RX_BUFFER_SIZE = 512; -static constexpr int TX_BUFFER_SIZE = 512; // ESP8266 Arduino core (WiFiClientSecureBearSSL.cpp) returns -1000 on OOM static constexpr int ESP8266_SSL_ERR_OOM = -1000; #endif @@ -58,7 +56,7 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure"); stream_ptr = std::make_unique<WiFiClientSecure>(); WiFiClientSecure *secure_client = static_cast<WiFiClientSecure *>(stream_ptr.get()); - secure_client->setBufferSizes(RX_BUFFER_SIZE, TX_BUFFER_SIZE); + secure_client->setBufferSizes(this->tls_buffer_size_rx_, this->tls_buffer_size_tx_); secure_client->setInsecure(); } else { stream_ptr = std::make_unique<WiFiClient>(); @@ -138,8 +136,8 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur } ESP_LOGW(TAG, "SSL failure: %s (Code: %d)", LOG_STR_ARG(error_msg), last_error); if (last_error == ESP8266_SSL_ERR_OOM) { - ESP_LOGW(TAG, "Heap free: %u bytes, configured buffer sizes: %u bytes", ESP.getFreeHeap(), - static_cast<unsigned int>(RX_BUFFER_SIZE + TX_BUFFER_SIZE)); + ESP_LOGW(TAG, "Configured TLS buffer sizes: %u/%u bytes, check max free heap block using the debug component", + (unsigned int) this->tls_buffer_size_rx_, (unsigned int) this->tls_buffer_size_tx_); } } else { ESP_LOGW(TAG, "Connection failure with no error code"); diff --git a/esphome/components/http_request/http_request_arduino.h b/esphome/components/http_request/http_request_arduino.h index d5ce5c0ff3..b009d45b1c 100644 --- a/esphome/components/http_request/http_request_arduino.h +++ b/esphome/components/http_request/http_request_arduino.h @@ -47,10 +47,20 @@ class HttpContainerArduino : public HttpContainer { }; class HttpRequestArduino : public HttpRequestComponent { + public: +#ifdef USE_ESP8266 + void set_tls_buffer_size_rx(uint16_t size) { this->tls_buffer_size_rx_ = size; } + void set_tls_buffer_size_tx(uint16_t size) { this->tls_buffer_size_tx_ = size; } +#endif + protected: std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body, const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) override; +#ifdef USE_ESP8266 + uint16_t tls_buffer_size_rx_{512}; + uint16_t tls_buffer_size_tx_{512}; +#endif }; } // namespace esphome::http_request diff --git a/tests/components/http_request/test.esp8266-ard.yaml b/tests/components/http_request/test.esp8266-ard.yaml index c1937b5a10..dd2d0df62b 100644 --- a/tests/components/http_request/test.esp8266-ard.yaml +++ b/tests/components/http_request/test.esp8266-ard.yaml @@ -1,4 +1,6 @@ -substitutions: - verify_ssl: "false" - <<: !include common.yaml + +http_request: + verify_ssl: false + tls_buffer_size_rx: 16384 + tls_buffer_size_tx: 512 From df11e2765ed016dabcdc211b7321289fa7cbeccf Mon Sep 17 00:00:00 2001 From: Ricardo Sanz <me@ricardosa.nz> Date: Sat, 7 Mar 2026 02:00:52 +0100 Subject: [PATCH 1179/2030] [climate][haier][template][core] Relocate CONF_CURRENT_TEMPERATURE to general const file (#14503) --- esphome/components/climate/__init__.py | 2 +- esphome/components/haier/climate.py | 8 ++------ esphome/components/template/water_heater/__init__.py | 2 +- esphome/const.py | 1 + 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index 1f449ad2a4..f5b91c502c 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_AWAY_COMMAND_TOPIC, CONF_AWAY_STATE_TOPIC, CONF_CURRENT_HUMIDITY_STATE_TOPIC, + CONF_CURRENT_TEMPERATURE, CONF_CURRENT_TEMPERATURE_STATE_TOPIC, CONF_CUSTOM_FAN_MODE, CONF_CUSTOM_PRESET, @@ -112,7 +113,6 @@ CLIMATE_SWING_MODES = { validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True) -CONF_CURRENT_TEMPERATURE = "current_temperature" CONF_MIN_HUMIDITY = "min_humidity" CONF_MAX_HUMIDITY = "max_humidity" CONF_TARGET_HUMIDITY = "target_humidity" diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index 8c3649058f..6c208f6caa 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -3,15 +3,11 @@ import logging from esphome import automation import esphome.codegen as cg from esphome.components import climate, logger, uart -from esphome.components.climate import ( - CONF_CURRENT_TEMPERATURE, - ClimateMode, - ClimatePreset, - ClimateSwingMode, -) +from esphome.components.climate import ClimateMode, ClimatePreset, ClimateSwingMode import esphome.config_validation as cv from esphome.const import ( CONF_BEEPER, + CONF_CURRENT_TEMPERATURE, CONF_DISPLAY, CONF_ID, CONF_LEVEL, diff --git a/esphome/components/template/water_heater/__init__.py b/esphome/components/template/water_heater/__init__.py index 71f98c826a..cb5f2dbe56 100644 --- a/esphome/components/template/water_heater/__init__.py +++ b/esphome/components/template/water_heater/__init__.py @@ -4,6 +4,7 @@ from esphome.components import water_heater import esphome.config_validation as cv from esphome.const import ( CONF_AWAY, + CONF_CURRENT_TEMPERATURE, CONF_ID, CONF_MODE, CONF_OPTIMISTIC, @@ -18,7 +19,6 @@ from esphome.types import ConfigType from .. import template_ns -CONF_CURRENT_TEMPERATURE = "current_temperature" CONF_IS_ON = "is_on" TemplateWaterHeater = template_ns.class_( diff --git a/esphome/const.py b/esphome/const.py index 060e962573..88e3c33fbc 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -274,6 +274,7 @@ CONF_CURRENT = "current" CONF_CURRENT_HUMIDITY_STATE_TOPIC = "current_humidity_state_topic" CONF_CURRENT_OPERATION = "current_operation" CONF_CURRENT_RESISTOR = "current_resistor" +CONF_CURRENT_TEMPERATURE = "current_temperature" CONF_CURRENT_TEMPERATURE_STATE_TOPIC = "current_temperature_state_topic" CONF_CUSTOM = "custom" CONF_CUSTOM_FAN_MODE = "custom_fan_mode" From 9b489c9eba639b8dea29dec7815c32c22cda28a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 7 Mar 2026 03:52:51 +0000 Subject: [PATCH 1180/2030] Bump aioesphomeapi from 44.2.0 to 44.3.1 (#14580) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f111e05a9d..8e875eba62 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.2.0 +aioesphomeapi==44.3.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 05ae69b766e9745892e97c8ac40d7017d5fecb3b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 6 Mar 2026 19:00:37 -1000 Subject: [PATCH 1181/2030] [api] Sync api.proto from aioesphomeapi (#14579) --- esphome/components/api/api.proto | 132 ++++++++++++++ esphome/components/api/api_pb2.cpp | 161 +++++++++++++++++ esphome/components/api/api_pb2.h | 200 ++++++++++++++++++++- esphome/components/api/api_pb2_dump.cpp | 117 ++++++++++++ esphome/components/api/api_pb2_service.cpp | 66 +++++++ esphome/components/api/api_pb2_service.h | 21 +++ 6 files changed, 696 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 802e3e3ae2..618fd1b83c 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -58,6 +58,7 @@ service APIConnection { rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {} rpc unsubscribe_bluetooth_le_advertisements(UnsubscribeBluetoothLEAdvertisementsRequest) returns (void) {} rpc bluetooth_scanner_set_mode(BluetoothScannerSetModeRequest) returns (void) {} + rpc bluetooth_set_connection_params(BluetoothSetConnectionParamsRequest) returns (BluetoothSetConnectionParamsResponse) {} rpc subscribe_voice_assistant(SubscribeVoiceAssistantRequest) returns (void) {} rpc voice_assistant_get_configuration(VoiceAssistantConfigurationRequest) returns (VoiceAssistantConfigurationResponse) {} @@ -69,6 +70,12 @@ service APIConnection { rpc zwave_proxy_request(ZWaveProxyRequest) returns (void) {} rpc infrared_rf_transmit_raw_timings(InfraredRFTransmitRawTimingsRequest) returns (void) {} + + rpc serial_proxy_configure(SerialProxyConfigureRequest) returns (void) {} + rpc serial_proxy_write(SerialProxyWriteRequest) returns (void) {} + rpc serial_proxy_set_modem_pins(SerialProxySetModemPinsRequest) returns (void) {} + rpc serial_proxy_get_modem_pins(SerialProxyGetModemPinsRequest) returns (void) {} + rpc serial_proxy_request(SerialProxyRequest) returns (void) {} } @@ -198,6 +205,17 @@ message DeviceInfo { uint32 area_id = 3; } +enum SerialProxyPortType { + SERIAL_PROXY_PORT_TYPE_TTL = 0; + SERIAL_PROXY_PORT_TYPE_RS232 = 1; + SERIAL_PROXY_PORT_TYPE_RS485 = 2; +} + +message SerialProxyInfo { + string name = 1; // Human-readable port name + SerialProxyPortType port_type = 2; // Port type (RS232, RS485) +} + message DeviceInfoResponse { option (id) = 10; option (source) = SOURCE_SERVER; @@ -260,6 +278,9 @@ message DeviceInfoResponse { // Indicates if Z-Wave proxy support is available and features supported uint32 zwave_proxy_feature_flags = 23 [(field_ifdef) = "USE_ZWAVE_PROXY"]; uint32 zwave_home_id = 24 [(field_ifdef) = "USE_ZWAVE_PROXY"]; + + // Serial proxy instance metadata + repeated SerialProxyInfo serial_proxies = 25 [(field_ifdef) = "USE_SERIAL_PROXY", (fixed_array_size_define) = "SERIAL_PROXY_COUNT"]; } message ListEntitiesRequest { @@ -2517,3 +2538,114 @@ message InfraredRFReceiveEvent { fixed32 key = 2; // Key identifying the receiver instance repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector<int32_t>"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods } + +// ==================== SERIAL PROXY ==================== + +enum SerialProxyParity { + SERIAL_PROXY_PARITY_NONE = 0; + SERIAL_PROXY_PARITY_EVEN = 1; + SERIAL_PROXY_PARITY_ODD = 2; +} + +// Configure UART parameters for a serial proxy instance +message SerialProxyConfigureRequest { + option (id) = 138; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) + uint32 baudrate = 2; // Baud rate in bits per second + bool flow_control = 3; // Enable hardware flow control + SerialProxyParity parity = 4; // Parity setting + uint32 stop_bits = 5; // Number of stop bits (1 or 2) + uint32 data_size = 6; // Number of data bits (5-8) +} + +// Data received from a serial device, forwarded to clients +message SerialProxyDataReceived { + option (id) = 139; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_SERIAL_PROXY"; + option (no_delay) = true; + + uint32 instance = 1; // Instance index (0-based) + bytes data = 2; // Raw data received from the serial device +} + +// Write data to a serial device +message SerialProxyWriteRequest { + option (id) = 140; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_SERIAL_PROXY"; + option (no_delay) = true; + + uint32 instance = 1; // Instance index (0-based) + bytes data = 2; // Raw data to write to the serial device +} + +// Set modem control pin states (RTS and DTR) +message SerialProxySetModemPinsRequest { + option (id) = 141; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) + uint32 line_states = 2; // Bitmask of SerialProxyLineStateFlags +} + +// Request current modem control pin states +message SerialProxyGetModemPinsRequest { + option (id) = 142; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) +} + +// Response with current modem control pin states +message SerialProxyGetModemPinsResponse { + option (id) = 143; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) + uint32 line_states = 2; // Bitmask of SerialProxyLineStateFlags +} + +enum SerialProxyRequestType { + SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE = 0; // Subscribe to receive data from this serial proxy instance + SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE = 1; // Unsubscribe from this serial proxy instance + SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2; // Flush the serial port (block until all TX data is sent) +} + +// Generic request message for simple serial proxy operations +message SerialProxyRequest { + option (id) = 144; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) + SerialProxyRequestType type = 2; // Request type +} + +// ==================== BLUETOOTH CONNECTION PARAMS ==================== +message BluetoothSetConnectionParamsRequest { + option (id) = 145; + option (source) = SOURCE_CLIENT; + option (ifdef) = "USE_BLUETOOTH_PROXY"; + + uint64 address = 1; + uint32 min_interval = 2; // units of 1.25ms + uint32 max_interval = 3; // units of 1.25ms + uint32 latency = 4; + uint32 timeout = 5; // units of 10ms +} + +message BluetoothSetConnectionParamsResponse { + option (id) = 146; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_BLUETOOTH_PROXY"; + + uint64 address = 1; + int32 error = 2; +} diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index d8703aa416..b1176de539 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -71,6 +71,18 @@ uint32_t DeviceInfo::calculate_size() const { return size; } #endif +#ifdef USE_SERIAL_PROXY +void SerialProxyInfo::encode(ProtoWriteBuffer &buffer) const { + buffer.encode_string(1, this->name); + buffer.encode_uint32(2, static_cast<uint32_t>(this->port_type)); +} +uint32_t SerialProxyInfo::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_length(1, this->name.size()); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->port_type)); + return size; +} +#endif void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(2, this->name); buffer.encode_string(3, this->mac_address); @@ -125,6 +137,11 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { #ifdef USE_ZWAVE_PROXY buffer.encode_uint32(24, this->zwave_home_id); #endif +#ifdef USE_SERIAL_PROXY + for (const auto &it : this->serial_proxies) { + buffer.encode_message(25, it); + } +#endif } uint32_t DeviceInfoResponse::calculate_size() const { uint32_t size = 0; @@ -180,6 +197,11 @@ uint32_t DeviceInfoResponse::calculate_size() const { #endif #ifdef USE_ZWAVE_PROXY size += ProtoSize::calc_uint32(2, this->zwave_home_id); +#endif +#ifdef USE_SERIAL_PROXY + for (const auto &it : this->serial_proxies) { + size += ProtoSize::calc_message_force(2, it.calculate_size()); + } #endif return size; } @@ -3714,5 +3736,144 @@ uint32_t InfraredRFReceiveEvent::calculate_size() const { return size; } #endif +#ifdef USE_SERIAL_PROXY +bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->instance = value.as_uint32(); + break; + case 2: + this->baudrate = value.as_uint32(); + break; + case 3: + this->flow_control = value.as_bool(); + break; + case 4: + this->parity = static_cast<enums::SerialProxyParity>(value.as_uint32()); + break; + case 5: + this->stop_bits = value.as_uint32(); + break; + case 6: + this->data_size = value.as_uint32(); + break; + default: + return false; + } + return true; +} +void SerialProxyDataReceived::encode(ProtoWriteBuffer &buffer) const { + buffer.encode_uint32(1, this->instance); + buffer.encode_bytes(2, this->data_ptr_, this->data_len_); +} +uint32_t SerialProxyDataReceived::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->instance); + size += ProtoSize::calc_length(1, this->data_len_); + return size; +} +bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->instance = value.as_uint32(); + break; + default: + return false; + } + return true; +} +bool SerialProxyWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { + switch (field_id) { + case 2: { + this->data = value.data(); + this->data_len = value.size(); + break; + } + default: + return false; + } + return true; +} +bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->instance = value.as_uint32(); + break; + case 2: + this->line_states = value.as_uint32(); + break; + default: + return false; + } + return true; +} +bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->instance = value.as_uint32(); + break; + default: + return false; + } + return true; +} +void SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer &buffer) const { + buffer.encode_uint32(1, this->instance); + buffer.encode_uint32(2, this->line_states); +} +uint32_t SerialProxyGetModemPinsResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->instance); + size += ProtoSize::calc_uint32(1, this->line_states); + return size; +} +bool SerialProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->instance = value.as_uint32(); + break; + case 2: + this->type = static_cast<enums::SerialProxyRequestType>(value.as_uint32()); + break; + default: + return false; + } + return true; +} +#endif +#ifdef USE_BLUETOOTH_PROXY +bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { + switch (field_id) { + case 1: + this->address = value.as_uint64(); + break; + case 2: + this->min_interval = value.as_uint32(); + break; + case 3: + this->max_interval = value.as_uint32(); + break; + case 4: + this->latency = value.as_uint32(); + break; + case 5: + this->timeout = value.as_uint32(); + break; + default: + return false; + } + return true; +} +void BluetoothSetConnectionParamsResponse::encode(ProtoWriteBuffer &buffer) const { + buffer.encode_uint64(1, this->address); + buffer.encode_int32(2, this->error); +} +uint32_t BluetoothSetConnectionParamsResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint64(1, this->address); + size += ProtoSize::calc_int32(1, this->error); + return size; +} +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 89cb1158f3..a6167dc810 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -11,6 +11,11 @@ namespace esphome::api { namespace enums { +enum SerialProxyPortType : uint32_t { + SERIAL_PROXY_PORT_TYPE_TTL = 0, + SERIAL_PROXY_PORT_TYPE_RS232 = 1, + SERIAL_PROXY_PORT_TYPE_RS485 = 2, +}; enum EntityCategory : uint32_t { ENTITY_CATEGORY_NONE = 0, ENTITY_CATEGORY_CONFIG = 1, @@ -317,6 +322,18 @@ enum ZWaveProxyRequestType : uint32_t { ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE = 2, }; #endif +#ifdef USE_SERIAL_PROXY +enum SerialProxyParity : uint32_t { + SERIAL_PROXY_PARITY_NONE = 0, + SERIAL_PROXY_PARITY_EVEN = 1, + SERIAL_PROXY_PARITY_ODD = 2, +}; +enum SerialProxyRequestType : uint32_t { + SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE = 0, + SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE = 1, + SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2, +}; +#endif } // namespace enums @@ -477,10 +494,24 @@ class DeviceInfo final : public ProtoMessage { protected: }; #endif +#ifdef USE_SERIAL_PROXY +class SerialProxyInfo final : public ProtoMessage { + public: + StringRef name{}; + enums::SerialProxyPortType port_type{}; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: +}; +#endif class DeviceInfoResponse final : public ProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 10; - static constexpr uint8_t ESTIMATED_SIZE = 255; + static constexpr uint16_t ESTIMATED_SIZE = 309; #ifdef HAS_PROTO_MESSAGE_DUMP const char *message_name() const override { return "device_info_response"; } #endif @@ -532,6 +563,9 @@ class DeviceInfoResponse final : public ProtoMessage { #endif #ifdef USE_ZWAVE_PROXY uint32_t zwave_home_id{0}; +#endif +#ifdef USE_SERIAL_PROXY + std::array<SerialProxyInfo, SERIAL_PROXY_COUNT> serial_proxies{}; #endif void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; @@ -3061,5 +3095,169 @@ class InfraredRFReceiveEvent final : public ProtoMessage { protected: }; #endif +#ifdef USE_SERIAL_PROXY +class SerialProxyConfigureRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 138; + static constexpr uint8_t ESTIMATED_SIZE = 20; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_configure_request"; } +#endif + uint32_t instance{0}; + uint32_t baudrate{0}; + bool flow_control{false}; + enums::SerialProxyParity parity{}; + uint32_t stop_bits{0}; + uint32_t data_size{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class SerialProxyDataReceived final : public ProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 139; + static constexpr uint8_t ESTIMATED_SIZE = 23; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_data_received"; } +#endif + uint32_t instance{0}; + const uint8_t *data_ptr_{nullptr}; + size_t data_len_{0}; + void set_data(const uint8_t *data, size_t len) { + this->data_ptr_ = data; + this->data_len_ = len; + } + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: +}; +class SerialProxyWriteRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 140; + static constexpr uint8_t ESTIMATED_SIZE = 23; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_write_request"; } +#endif + uint32_t instance{0}; + const uint8_t *data{nullptr}; + uint16_t data_len{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 141; + static constexpr uint8_t ESTIMATED_SIZE = 8; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_set_modem_pins_request"; } +#endif + uint32_t instance{0}; + uint32_t line_states{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 142; + static constexpr uint8_t ESTIMATED_SIZE = 4; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_get_modem_pins_request"; } +#endif + uint32_t instance{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class SerialProxyGetModemPinsResponse final : public ProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 143; + static constexpr uint8_t ESTIMATED_SIZE = 8; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_get_modem_pins_response"; } +#endif + uint32_t instance{0}; + uint32_t line_states{0}; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: +}; +class SerialProxyRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 144; + static constexpr uint8_t ESTIMATED_SIZE = 6; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_request"; } +#endif + uint32_t instance{0}; + enums::SerialProxyRequestType type{}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +#endif +#ifdef USE_BLUETOOTH_PROXY +class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 145; + static constexpr uint8_t ESTIMATED_SIZE = 20; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "bluetooth_set_connection_params_request"; } +#endif + uint64_t address{0}; + uint32_t min_interval{0}; + uint32_t max_interval{0}; + uint32_t latency{0}; + uint32_t timeout{0}; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: + bool decode_varint(uint32_t field_id, ProtoVarInt value) override; +}; +class BluetoothSetConnectionParamsResponse final : public ProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 146; + static constexpr uint8_t ESTIMATED_SIZE = 8; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "bluetooth_set_connection_params_response"; } +#endif + uint64_t address{0}; + int32_t error{0}; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: +}; +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 4eec42e936..086b1bdc2f 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -100,6 +100,18 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint out.append(hex_buf).append("\n"); } +template<> const char *proto_enum_to_string<enums::SerialProxyPortType>(enums::SerialProxyPortType value) { + switch (value) { + case enums::SERIAL_PROXY_PORT_TYPE_TTL: + return "SERIAL_PROXY_PORT_TYPE_TTL"; + case enums::SERIAL_PROXY_PORT_TYPE_RS232: + return "SERIAL_PROXY_PORT_TYPE_RS232"; + case enums::SERIAL_PROXY_PORT_TYPE_RS485: + return "SERIAL_PROXY_PORT_TYPE_RS485"; + default: + return "UNKNOWN"; + } +} template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) { switch (value) { case enums::ENTITY_CATEGORY_NONE: @@ -752,6 +764,32 @@ template<> const char *proto_enum_to_string<enums::ZWaveProxyRequestType>(enums: } } #endif +#ifdef USE_SERIAL_PROXY +template<> const char *proto_enum_to_string<enums::SerialProxyParity>(enums::SerialProxyParity value) { + switch (value) { + case enums::SERIAL_PROXY_PARITY_NONE: + return "SERIAL_PROXY_PARITY_NONE"; + case enums::SERIAL_PROXY_PARITY_EVEN: + return "SERIAL_PROXY_PARITY_EVEN"; + case enums::SERIAL_PROXY_PARITY_ODD: + return "SERIAL_PROXY_PARITY_ODD"; + default: + return "UNKNOWN"; + } +} +template<> const char *proto_enum_to_string<enums::SerialProxyRequestType>(enums::SerialProxyRequestType value) { + switch (value) { + case enums::SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE: + return "SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE"; + case enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: + return "SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE"; + case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH: + return "SERIAL_PROXY_REQUEST_TYPE_FLUSH"; + default: + return "UNKNOWN"; + } +} +#endif const char *HelloRequest::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "HelloRequest"); @@ -801,6 +839,14 @@ const char *DeviceInfo::dump_to(DumpBuffer &out) const { return out.c_str(); } #endif +#ifdef USE_SERIAL_PROXY +const char *SerialProxyInfo::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyInfo"); + dump_field(out, "name", this->name); + dump_field(out, "port_type", static_cast<enums::SerialProxyPortType>(this->port_type)); + return out.c_str(); +} +#endif const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { MessageDumpHelper helper(out, "DeviceInfoResponse"); dump_field(out, "name", this->name); @@ -861,6 +907,13 @@ const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { #endif #ifdef USE_ZWAVE_PROXY dump_field(out, "zwave_home_id", this->zwave_home_id); +#endif +#ifdef USE_SERIAL_PROXY + for (const auto &it : this->serial_proxies) { + out.append(" serial_proxies: "); + it.dump_to(out); + out.append("\n"); + } #endif return out.c_str(); } @@ -2510,6 +2563,70 @@ const char *InfraredRFReceiveEvent::dump_to(DumpBuffer &out) const { return out.c_str(); } #endif +#ifdef USE_SERIAL_PROXY +const char *SerialProxyConfigureRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyConfigureRequest"); + dump_field(out, "instance", this->instance); + dump_field(out, "baudrate", this->baudrate); + dump_field(out, "flow_control", this->flow_control); + dump_field(out, "parity", static_cast<enums::SerialProxyParity>(this->parity)); + dump_field(out, "stop_bits", this->stop_bits); + dump_field(out, "data_size", this->data_size); + return out.c_str(); +} +const char *SerialProxyDataReceived::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyDataReceived"); + dump_field(out, "instance", this->instance); + dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + return out.c_str(); +} +const char *SerialProxyWriteRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyWriteRequest"); + dump_field(out, "instance", this->instance); + dump_bytes_field(out, "data", this->data, this->data_len); + return out.c_str(); +} +const char *SerialProxySetModemPinsRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxySetModemPinsRequest"); + dump_field(out, "instance", this->instance); + dump_field(out, "line_states", this->line_states); + return out.c_str(); +} +const char *SerialProxyGetModemPinsRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyGetModemPinsRequest"); + dump_field(out, "instance", this->instance); + return out.c_str(); +} +const char *SerialProxyGetModemPinsResponse::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyGetModemPinsResponse"); + dump_field(out, "instance", this->instance); + dump_field(out, "line_states", this->line_states); + return out.c_str(); +} +const char *SerialProxyRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyRequest"); + dump_field(out, "instance", this->instance); + dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type)); + return out.c_str(); +} +#endif +#ifdef USE_BLUETOOTH_PROXY +const char *BluetoothSetConnectionParamsRequest::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "BluetoothSetConnectionParamsRequest"); + dump_field(out, "address", this->address); + dump_field(out, "min_interval", this->min_interval); + dump_field(out, "max_interval", this->max_interval); + dump_field(out, "latency", this->latency); + dump_field(out, "timeout", this->timeout); + return out.c_str(); +} +const char *BluetoothSetConnectionParamsResponse::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "BluetoothSetConnectionParamsResponse"); + dump_field(out, "address", this->address); + dump_field(out, "error", this->error); + return out.c_str(); +} +#endif } // namespace esphome::api diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index f9151ae3b4..f2f7fa5238 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -634,6 +634,72 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, this->on_infrared_rf_transmit_raw_timings_request(msg); break; } +#endif +#ifdef USE_SERIAL_PROXY + case SerialProxyConfigureRequest::MESSAGE_TYPE: { + SerialProxyConfigureRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_serial_proxy_configure_request"), msg); +#endif + this->on_serial_proxy_configure_request(msg); + break; + } +#endif +#ifdef USE_SERIAL_PROXY + case SerialProxyWriteRequest::MESSAGE_TYPE: { + SerialProxyWriteRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_serial_proxy_write_request"), msg); +#endif + this->on_serial_proxy_write_request(msg); + break; + } +#endif +#ifdef USE_SERIAL_PROXY + case SerialProxySetModemPinsRequest::MESSAGE_TYPE: { + SerialProxySetModemPinsRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_serial_proxy_set_modem_pins_request"), msg); +#endif + this->on_serial_proxy_set_modem_pins_request(msg); + break; + } +#endif +#ifdef USE_SERIAL_PROXY + case SerialProxyGetModemPinsRequest::MESSAGE_TYPE: { + SerialProxyGetModemPinsRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_serial_proxy_get_modem_pins_request"), msg); +#endif + this->on_serial_proxy_get_modem_pins_request(msg); + break; + } +#endif +#ifdef USE_SERIAL_PROXY + case SerialProxyRequest::MESSAGE_TYPE: { + SerialProxyRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_serial_proxy_request"), msg); +#endif + this->on_serial_proxy_request(msg); + break; + } +#endif +#ifdef USE_BLUETOOTH_PROXY + case BluetoothSetConnectionParamsRequest::MESSAGE_TYPE: { + BluetoothSetConnectionParamsRequest msg; + msg.decode(msg_data, msg_size); +#ifdef HAS_PROTO_MESSAGE_DUMP + this->log_receive_message_(LOG_STR("on_bluetooth_set_connection_params_request"), msg); +#endif + this->on_bluetooth_set_connection_params_request(msg); + break; + } #endif default: break; diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index e70b97196b..a031d2d969 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -216,6 +216,27 @@ class APIServerConnectionBase : public ProtoService { virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){}; #endif +#ifdef USE_SERIAL_PROXY + virtual void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &value){}; +#endif + +#ifdef USE_SERIAL_PROXY + virtual void on_serial_proxy_write_request(const SerialProxyWriteRequest &value){}; +#endif +#ifdef USE_SERIAL_PROXY + virtual void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &value){}; +#endif +#ifdef USE_SERIAL_PROXY + virtual void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &value){}; +#endif + +#ifdef USE_SERIAL_PROXY + virtual void on_serial_proxy_request(const SerialProxyRequest &value){}; +#endif +#ifdef USE_BLUETOOTH_PROXY + virtual void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){}; +#endif + protected: void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; From cbebb811965d63f115ea4fba5c8fd7f6da393b29 Mon Sep 17 00:00:00 2001 From: rwrozelle <rwrozelle@gmail.com> Date: Sat, 7 Mar 2026 08:12:27 -0800 Subject: [PATCH 1182/2030] [openthread] move esp functions into correct file (#14588) --- esphome/components/openthread/openthread.cpp | 9 ++------- esphome/components/openthread/openthread.h | 2 ++ esphome/components/openthread/openthread_esp.cpp | 5 +++++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index fb81481299..1596b6e990 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -1,7 +1,6 @@ #include "esphome/core/defines.h" #ifdef USE_OPENTHREAD #include "openthread.h" -#include "esp_openthread.h" #include <freertos/portmacro.h> @@ -51,7 +50,7 @@ void OpenThreadComponent::on_state_changed_(otChangedFlags flags, void *context) auto *self = static_cast<OpenThreadComponent *>(context); // This runs on the OpenThread task thread with the OT lock held, // so we can safely call otThreadGetDeviceRole directly. - otInstance *instance = esp_openthread_get_instance(); + otInstance *instance = self->get_openthread_instance_(); otDeviceRole role = otThreadGetDeviceRole(instance); self->connected_ = role >= OT_DEVICE_ROLE_CHILD; } @@ -233,16 +232,12 @@ bool OpenThreadComponent::teardown() { otSrpClientClearHostAndServices(instance); otSrpClientBuffersFreeAllServices(instance); global_openthread_component = nullptr; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0) ESP_LOGD(TAG, "Exit main loop "); - int error = esp_openthread_mainloop_exit(); + int error = this->openthread_stop_(); if (error != ESP_OK) { ESP_LOGW(TAG, "Failed attempt to stop main loop %d", error); this->teardown_complete_ = true; } -#else - this->teardown_complete_ = true; -#endif } return this->teardown_complete_; } diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index c87f4fa7c1..75d8fe11fd 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -44,6 +44,8 @@ class OpenThreadComponent : public Component { protected: std::optional<otIp6Address> get_omr_address_(InstanceLock &lock); static void on_state_changed_(otChangedFlags flags, void *context); + otInstance *get_openthread_instance_(); + int openthread_stop_(); std::function<void()> factory_reset_external_callback_; #if CONFIG_OPENTHREAD_MTD uint32_t poll_period_{0}; diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index cdc7a404b2..9cc9223b52 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -190,6 +190,8 @@ void OpenThreadComponent::ot_main() { vTaskDelete(NULL); } +int OpenThreadComponent::openthread_stop_() { return esp_openthread_mainloop_exit(); } + network::IPAddresses OpenThreadComponent::get_ip_addresses() { network::IPAddresses addresses; struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; @@ -204,6 +206,9 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() { return addresses; } +// not thread safe, only use in read-only use cases +otInstance *OpenThreadComponent::get_openthread_instance_() { return esp_openthread_get_instance(); } + std::optional<InstanceLock> InstanceLock::try_acquire(int delay) { if (esp_openthread_lock_acquire(delay)) { return InstanceLock(); From 0e106d843c730eb15e083ebd0147124dadc99a5a Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sat, 7 Mar 2026 17:18:21 +0100 Subject: [PATCH 1183/2030] [nrf52][zephyr] support for multi on rate callbacks (#14557) --- esphome/components/nrf52/__init__.py | 3 +++ esphome/components/nrf52/dfu.cpp | 35 ++++++++------------------- esphome/components/nrf52/dfu.h | 1 - esphome/components/zephyr/__init__.py | 20 +++++++++++---- esphome/components/zephyr/cdc_acm.cpp | 30 +++++++++++++++++++++++ esphome/components/zephyr/cdc_acm.h | 27 +++++++++++++++++++++ esphome/components/zephyr/const.py | 2 ++ 7 files changed, 87 insertions(+), 31 deletions(-) create mode 100644 esphome/components/zephyr/cdc_acm.cpp create mode 100644 esphome/components/zephyr/cdc_acm.h diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index a12d1db1ab..0a9fb5939a 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -20,8 +20,10 @@ from esphome.components.zephyr import ( ) from esphome.components.zephyr.const import ( BOOTLOADER_MCUBOOT, + CONF_CDC_ACM, KEY_BOOTLOADER, KEY_ZEPHYR, + CdcAcm, ) import esphome.config_validation as cv from esphome.const import ( @@ -159,6 +161,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_VERSION): cv.string_strict, } ), + cv.GenerateID(CONF_CDC_ACM): cv.declare_id(CdcAcm), } ), set_framework, diff --git a/esphome/components/nrf52/dfu.cpp b/esphome/components/nrf52/dfu.cpp index 9e49373467..c2017248d2 100644 --- a/esphome/components/nrf52/dfu.cpp +++ b/esphome/components/nrf52/dfu.cpp @@ -2,42 +2,27 @@ #ifdef USE_NRF52_DFU -#include <zephyr/device.h> -#include <zephyr/drivers/uart.h> -#include <zephyr/drivers/uart/cdc_acm.h> #include "esphome/core/log.h" +#include "esphome/components/zephyr/cdc_acm.h" namespace esphome { namespace nrf52 { static const char *const TAG = "dfu"; -volatile bool goto_dfu = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - static const uint32_t DFU_DBL_RESET_MAGIC = 0x5A1AD5; // SALADS -#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), - -static void cdc_dte_rate_callback(const struct device * /*unused*/, uint32_t rate) { - if (rate == 1200) { - goto_dfu = true; - } -} void DeviceFirmwareUpdate::setup() { this->reset_pin_->setup(); - const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)}; - for (auto &idx : cdc_dev) { - cdc_acm_dte_rate_callback_set(idx, cdc_dte_rate_callback); - } -} - -void DeviceFirmwareUpdate::loop() { - if (goto_dfu) { - goto_dfu = false; - volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C; - (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; - this->reset_pin_->digital_write(true); - } +#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT) + zephyr::global_cdc_acm->add_on_rate_callback([this](const device *, uint32_t rate) { + if (rate == 1200) { + volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C; + (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; + this->reset_pin_->digital_write(true); + } + }); +#endif } void DeviceFirmwareUpdate::dump_config() { diff --git a/esphome/components/nrf52/dfu.h b/esphome/components/nrf52/dfu.h index 979a4567cf..71060e43c1 100644 --- a/esphome/components/nrf52/dfu.h +++ b/esphome/components/nrf52/dfu.h @@ -10,7 +10,6 @@ namespace nrf52 { class DeviceFirmwareUpdate : public Component { public: void setup() override; - void loop() override; void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } void dump_config() override; diff --git a/esphome/components/zephyr/__init__.py b/esphome/components/zephyr/__init__.py index 4cc71bddca..b8a091feb9 100644 --- a/esphome/components/zephyr/__init__.py +++ b/esphome/components/zephyr/__init__.py @@ -5,11 +5,13 @@ from typing import TypedDict import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_BOARD, KEY_CORE, KEY_FRAMEWORK_VERSION -from esphome.core import CORE +from esphome.core import CORE, CoroPriority, coroutine_with_priority from esphome.helpers import copy_file_if_changed, write_file_if_changed +from esphome.types import ConfigType from .const import ( BOOTLOADER_MCUBOOT, + CONF_CDC_ACM, KEY_BOARD, KEY_BOOTLOADER, KEY_EXTRA_BUILD_FILES, @@ -54,7 +56,7 @@ class ZephyrData(TypedDict): user: dict[str, list[str]] -def zephyr_set_core_data(config): +def zephyr_set_core_data(config: ConfigType) -> None: CORE.data[KEY_ZEPHYR] = ZephyrData( board=config[CONF_BOARD], bootloader=config[KEY_BOOTLOADER], @@ -64,7 +66,6 @@ def zephyr_set_core_data(config): pm_static=[], user={}, ) - return config def zephyr_data() -> ZephyrData: @@ -110,7 +111,7 @@ def add_extra_script(stage: str, filename: str, path: Path) -> None: cg.add_platformio_option("extra_scripts", [key]) -def zephyr_to_code(config): +def zephyr_to_code(config: ConfigType) -> None: cg.add_build_flag("-DUSE_ZEPHYR") cg.add_define("USE_NATIVE_64BIT_TIME") cg.set_cpp_standard("gnu++20") @@ -132,6 +133,15 @@ def zephyr_to_code(config): Path(__file__).parent / "pre_build.py.script", ) + CORE.add_job(_cdc_acm_to_code, config) + + +@coroutine_with_priority(CoroPriority.FINAL) +async def _cdc_acm_to_code(config: ConfigType) -> None: + if "CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT" in zephyr_data()[KEY_PRJ_CONF]: + var = cg.new_Pvariable(config[CONF_CDC_ACM]) + await cg.register_component(var, {}) + def zephyr_setup_preferences(): cg.add(zephyr_ns.setup_preferences()) @@ -151,7 +161,7 @@ def _format_prj_conf_val(value: PrjConfValueType) -> str: raise ValueError -def zephyr_add_cdc_acm(config, id): +def zephyr_add_cdc_acm(config: ConfigType, id: int) -> None: framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] if CORE.is_nrf52 and framework_ver >= cv.Version(3, 2, 0): zephyr_add_prj_conf("CONFIG_USB_DEVICE_STACK_NEXT", False) diff --git a/esphome/components/zephyr/cdc_acm.cpp b/esphome/components/zephyr/cdc_acm.cpp new file mode 100644 index 0000000000..04ee9a0bef --- /dev/null +++ b/esphome/components/zephyr/cdc_acm.cpp @@ -0,0 +1,30 @@ +#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT) +#include "cdc_acm.h" +#include <zephyr/drivers/uart.h> +#include <zephyr/drivers/uart/cdc_acm.h> + +#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), + +namespace esphome::zephyr { + +CdcAcm::CdcAcm() { global_cdc_acm = this; } + +void CdcAcm::setup() { +#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart) + const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)}; + for (auto &idx : cdc_dev) { + // only one global callback can be registered + cdc_acm_dte_rate_callback_set(idx, CdcAcm::cdc_dte_rate_callback_); + } +#endif // DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart) +} + +void CdcAcm::cdc_dte_rate_callback_(const struct device *device, uint32_t rate) { + global_cdc_acm->defer([device, rate]() { global_cdc_acm->rate_callbacks_.call(device, rate); }); +} + +CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +} // namespace esphome::zephyr + +#endif diff --git a/esphome/components/zephyr/cdc_acm.h b/esphome/components/zephyr/cdc_acm.h new file mode 100644 index 0000000000..2e9da85a11 --- /dev/null +++ b/esphome/components/zephyr/cdc_acm.h @@ -0,0 +1,27 @@ +#pragma once +#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT) + +#include "esphome/core/component.h" +#include "esphome/core/helpers.h" +#include <zephyr/device.h> + +namespace esphome::zephyr { + +class CdcAcm : public Component { + public: + CdcAcm(); + void setup() override; + void add_on_rate_callback(std::function<void(const device *, uint32_t)> &&callback) { + this->rate_callbacks_.add(std::move(callback)); + } + + protected: + static void cdc_dte_rate_callback_(const device *device, uint32_t rate); + CallbackManager<void(const device *, uint32_t)> rate_callbacks_; +}; + +extern CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +} // namespace esphome::zephyr + +#endif diff --git a/esphome/components/zephyr/const.py b/esphome/components/zephyr/const.py index 06a4fc42bc..f67b058ed7 100644 --- a/esphome/components/zephyr/const.py +++ b/esphome/components/zephyr/const.py @@ -14,3 +14,5 @@ KEY_BOARD: Final = "board" KEY_USER: Final = "user" zephyr_ns = cg.esphome_ns.namespace("zephyr") +CdcAcm = zephyr_ns.class_("CdcAcm", cg.Component) +CONF_CDC_ACM = "cdc_acm" From 8b62c35ea7831d2c0e24f836e096b7b4c1cb1ca0 Mon Sep 17 00:00:00 2001 From: Simon Redman <simon@ergotech.com> Date: Sat, 7 Mar 2026 11:41:37 -0500 Subject: [PATCH 1184/2030] [uart] Add error message when initializing UART with unsupported configuration (#13229) --- esphome/components/uart/uart_component_libretiny.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/uart/uart_component_libretiny.cpp b/esphome/components/uart/uart_component_libretiny.cpp index cb4465068d..83d2acb332 100644 --- a/esphome/components/uart/uart_component_libretiny.cpp +++ b/esphome/components/uart/uart_component_libretiny.cpp @@ -110,7 +110,7 @@ void LibreTinyUARTComponent::setup() { #if LT_HW_UART2 ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL2_TX, PIN_SERIAL2_RX); #endif - this->mark_failed(); + this->mark_failed(LOG_STR("SoftwareSerial is not implemented for this chip.")); return; #endif } From 15ffbb0b05da71f6ef008c0a38ffd185d0490edc Mon Sep 17 00:00:00 2001 From: puddly <32534428+puddly@users.noreply.github.com> Date: Sat, 7 Mar 2026 11:51:02 -0500 Subject: [PATCH 1185/2030] [uart] Fully enable raw mode with host serial (#14573) --- esphome/components/uart/uart_component_host.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 0e5ef3c6bd..9dce25c500 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -124,17 +124,10 @@ void HostUartComponent::setup() { fcntl(this->file_descriptor_, F_SETFL, 0); struct termios options; tcgetattr(this->file_descriptor_, &options); + cfmakeraw(&options); options.c_cflag &= ~CRTSCTS; options.c_cflag |= CREAD | CLOCAL; - options.c_lflag &= ~ICANON; - options.c_lflag &= ~ECHO; - options.c_lflag &= ~ECHOE; - options.c_lflag &= ~ECHONL; - options.c_lflag &= ~ISIG; - options.c_iflag &= ~(IXON | IXOFF | IXANY); - options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); - options.c_oflag &= ~OPOST; - options.c_oflag &= ~ONLCR; + options.c_iflag &= ~(IXOFF | IXANY); // Set data bits options.c_cflag &= ~CSIZE; // Mask the character size bits switch (this->data_bits_) { From abc870006cce42296a2f581478f79fbe69df2391 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:25:13 -1000 Subject: [PATCH 1186/2030] [captive_portal] Enable support for RP2040 (#14505) --- esphome/components/captive_portal/__init__.py | 9 ++++----- tests/components/captive_portal/test.rp2040-ard.yaml | 1 + 2 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 tests/components/captive_portal/test.rp2040-ard.yaml diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index 6c190814c0..cd877fc879 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -13,6 +13,7 @@ from esphome.const import ( PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_LN882X, + PLATFORM_RP2040, PLATFORM_RTL87XX, PlatformFramework, ) @@ -53,6 +54,7 @@ CONFIG_SCHEMA = cv.All( PLATFORM_ESP8266, PLATFORM_BK72XX, PLATFORM_LN882X, + PLATFORM_RP2040, PLATFORM_RTL87XX, ] ), @@ -103,11 +105,8 @@ async def to_code(config): if config[CONF_COMPRESSION] == "gzip": cg.add_define("USE_CAPTIVE_PORTAL_GZIP") - if CORE.using_arduino: - if CORE.is_esp8266: - cg.add_library("DNSServer", None) - if CORE.is_libretiny: - cg.add_library("DNSServer", None) + if CORE.using_arduino and (CORE.is_esp8266 or CORE.is_libretiny or CORE.is_rp2040): + cg.add_library("DNSServer", None) # Only compile the ESP-IDF DNS server when using ESP-IDF framework diff --git a/tests/components/captive_portal/test.rp2040-ard.yaml b/tests/components/captive_portal/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/captive_portal/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From f57fa4cc8d66a99f1e6bef885e2f0c8f96280c04 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:25:33 -1000 Subject: [PATCH 1187/2030] [bluetooth_proxy] Add BLE connection parameters API (#14577) --- esphome/components/api/api_connection.cpp | 3 ++ esphome/components/api/api_connection.h | 1 + .../bluetooth_proxy/bluetooth_connection.h | 4 +++ .../bluetooth_proxy/bluetooth_proxy.cpp | 29 +++++++++++++++++++ .../bluetooth_proxy/bluetooth_proxy.h | 3 ++ .../esp32_ble_client/ble_client_base.cpp | 5 ++-- .../esp32_ble_client/ble_client_base.h | 4 +-- 7 files changed, 45 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 8721072e49..bd3de02895 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1188,6 +1188,9 @@ void APIConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScanner bluetooth_proxy::global_bluetooth_proxy->bluetooth_scanner_set_mode( msg.mode == enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE); } +void APIConnection::on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg) { + bluetooth_proxy::global_bluetooth_proxy->bluetooth_set_connection_params(msg); +} #endif #ifdef USE_VOICE_ASSISTANT diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 54b6db6800..b075bc83ab 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -148,6 +148,7 @@ class APIConnection final : public APIServerConnectionBase { void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override; void on_subscribe_bluetooth_connections_free_request() override; void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override; + void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg) override; #endif #ifdef USE_HOMEASSISTANT_TIME diff --git a/esphome/components/bluetooth_proxy/bluetooth_connection.h b/esphome/components/bluetooth_proxy/bluetooth_connection.h index 60bbc93e8b..b50ea2d6a2 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_connection.h +++ b/esphome/components/bluetooth_proxy/bluetooth_connection.h @@ -24,6 +24,10 @@ class BluetoothConnection final : public esp32_ble_client::BLEClientBase { esp_err_t notify_characteristic(uint16_t handle, bool enable); + esp_err_t update_connection_params(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout) { + return this->update_conn_params_(min_interval, max_interval, latency, timeout, "custom"); + } + void set_address(uint64_t address) override; protected: diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 21da4ead14..87206996b2 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -3,7 +3,9 @@ #include "esphome/core/log.h" #include "esphome/core/macros.h" #include "esphome/core/application.h" +#include <algorithm> #include <cstring> +#include <limits> #ifdef USE_ESP32 @@ -361,6 +363,33 @@ void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest } } +void BluetoothProxy::bluetooth_set_connection_params(const api::BluetoothSetConnectionParamsRequest &msg) { + if (this->api_connection_ == nullptr) + return; + + auto *connection = this->get_connection_(msg.address, false); + api::BluetoothSetConnectionParamsResponse resp; + resp.address = msg.address; + + if (connection == nullptr || !connection->connected()) { + ESP_LOGW(TAG, "[%d] [%s] Cannot set connection params, not connected", + connection ? static_cast<int>(connection->connection_index_) : -1, + connection ? connection->address_str() : "unknown"); + resp.error = ESP_GATT_NOT_CONNECTED; + this->api_connection_->send_message(resp); + return; + } + + // Protobuf fields are uint32_t to future-proof the API if BLE ever supports wider values; + // clamp to uint16_t since the current BLE spec defines these as 16-bit. + constexpr uint32_t max_val = std::numeric_limits<uint16_t>::max(); + resp.error = connection->update_connection_params(static_cast<uint16_t>(std::min(msg.min_interval, max_val)), + static_cast<uint16_t>(std::min(msg.max_interval, max_val)), + static_cast<uint16_t>(std::min(msg.latency, max_val)), + static_cast<uint16_t>(std::min(msg.timeout, max_val))); + this->api_connection_->send_message(resp); +} + void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags) { if (this->api_connection_ != nullptr) { ESP_LOGE(TAG, "Only one API subscription is allowed at a time"); diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index 85461755aa..f1b723e719 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -46,6 +46,7 @@ enum BluetoothProxyFeature : uint32_t { FEATURE_CACHE_CLEARING = 1 << 4, FEATURE_RAW_ADVERTISEMENTS = 1 << 5, FEATURE_STATE_AND_MODE = 1 << 6, + FEATURE_CONNECTION_PARAMS_SETTING = 1 << 7, }; enum BluetoothProxySubscriptionFlag : uint32_t { @@ -82,6 +83,7 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, void bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg); void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg); void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg); + void bluetooth_set_connection_params(const api::BluetoothSetConnectionParamsRequest &msg); void subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags); void unsubscribe_api_connection(api::APIConnection *api_connection); @@ -130,6 +132,7 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, flags |= BluetoothProxyFeature::FEATURE_REMOTE_CACHING; flags |= BluetoothProxyFeature::FEATURE_PAIRING; flags |= BluetoothProxyFeature::FEATURE_CACHE_CLEARING; + flags |= BluetoothProxyFeature::FEATURE_CONNECTION_PARAMS_SETTING; } return flags; diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index e6a85c784a..2f17334c77 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -236,8 +236,8 @@ void BLEClientBase::log_warning_(const char *message) { ESP_LOGW(TAG, "[%d] [%s] %s", this->connection_index_, this->address_str_, message); } -void BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, - uint16_t timeout, const char *param_type) { +esp_err_t BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, + uint16_t timeout, const char *param_type) { esp_ble_conn_update_params_t conn_params = {{0}}; memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t)); conn_params.min_int = min_interval; @@ -249,6 +249,7 @@ void BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_inte if (err != ESP_OK) { this->log_gattc_warning_("esp_ble_gap_update_conn_params", err); } + return err; } void BLEClientBase::set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index c2336b2349..af4f1b3029 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -129,8 +129,8 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { void log_event_(const char *name); void log_gattc_lifecycle_event_(const char *name); void log_gattc_data_event_(const char *name); - void update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, - const char *param_type); + esp_err_t update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, + const char *param_type); void set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout, const char *param_type); void log_gattc_warning_(const char *operation, esp_gatt_status_t status); From 45f20d9c06119e3c02aa8e8be131297c032da4e1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:26:01 -1000 Subject: [PATCH 1188/2030] [core] Merge set_name + set_entity_strings into configure_entity_ (#14444) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/entity_base.cpp | 15 ++- esphome/core/entity_base.h | 30 ++--- esphome/core/entity_helpers.py | 17 ++- .../binary_sensor/test_binary_sensor.py | 2 +- tests/component_tests/button/test_button.py | 2 +- tests/component_tests/sensor/test_sensor.py | 15 ++- tests/component_tests/text/test_text.py | 2 +- .../text_sensor/test_text_sensor.py | 25 ++++- tests/unit_tests/core/test_entity_helpers.py | 103 +++++++----------- 9 files changed, 112 insertions(+), 99 deletions(-) diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 5c4e1c4445..3274640eb3 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -10,8 +10,8 @@ static const char *const TAG = "entity_base"; // Entity Name const StringRef &EntityBase::get_name() const { return this->name_; } -void EntityBase::set_name(const char *name) { this->set_name(name, 0); } -void EntityBase::set_name(const char *name, uint32_t object_id_hash) { + +void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_strings_packed) { this->name_ = StringRef(name); if (this->name_.empty()) { #ifdef USE_DEVICES @@ -44,6 +44,17 @@ void EntityBase::set_name(const char *name, uint32_t object_id_hash) { this->calc_object_id_(); } } + // Unpack entity string table indices. + // Packed: [23..16] icon | [15..8] UoM | [7..0] device_class (each 8 bits) +#ifdef USE_ENTITY_DEVICE_CLASS + this->device_class_idx_ = entity_strings_packed & 0xFF; +#endif +#ifdef USE_ENTITY_UNIT_OF_MEASUREMENT + this->uom_idx_ = (entity_strings_packed >> 8) & 0xFF; +#endif +#ifdef USE_ENTITY_ICON + this->icon_idx_ = (entity_strings_packed >> 16) & 0xFF; +#endif } // Weak default lookup functions — overridden by generated code in main.cpp diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 20eb68b67a..accd532b0d 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -12,6 +12,10 @@ #include "device.h" #endif +// Forward declarations for friend access from codegen-generated setup() +void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h +void original_setup(); // NOLINT(readability-redundant-declaration) - used by cpp unit tests + namespace esphome { // Extern lookup functions for entity string tables. @@ -54,12 +58,8 @@ enum EntityCategory : uint8_t { // The generic Entity base class that provides an interface common to all Entities. class EntityBase { public: - // Get/set the name of this Entity + // Get the name of this Entity const StringRef &get_name() const; - void set_name(const char *name); - /// Set name with pre-computed object_id hash (avoids runtime hash calculation) - /// Use hash=0 for dynamic names that need runtime calculation - void set_name(const char *name, uint32_t object_id_hash); // Get whether this Entity has its own name or it should use the device friendly_name. bool has_own_name() const { return this->flags_.has_own_name; } @@ -104,20 +104,6 @@ class EntityBase { this->flags_.entity_category = static_cast<uint8_t>(entity_category); } - // Set entity string table indices — one call per entity from codegen. - // Packed: [23..16] icon | [15..8] UoM | [7..0] device_class (each 8 bits) - void set_entity_strings([[maybe_unused]] uint32_t packed) { -#ifdef USE_ENTITY_DEVICE_CLASS - this->device_class_idx_ = packed & 0xFF; -#endif -#ifdef USE_ENTITY_UNIT_OF_MEASUREMENT - this->uom_idx_ = (packed >> 8) & 0xFF; -#endif -#ifdef USE_ENTITY_ICON - this->icon_idx_ = (packed >> 16) & 0xFF; -#endif - } - // Get this entity's device class into a stack buffer. // On non-ESP8266: returns pointer to PROGMEM string directly (buffer unused). // On ESP8266: copies from PROGMEM to buffer, returns buffer pointer. @@ -239,6 +225,12 @@ class EntityBase { } protected: + friend void ::setup(); + friend void ::original_setup(); + + /// Combined entity setup from codegen: set name, object_id hash, and entity string indices. + void configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_strings_packed); + /// Non-template helper for make_entity_preference() to avoid code bloat. /// When preference hash algorithm changes, migration logic goes here. ESPPreferenceObject make_entity_preference_(size_t size, uint32_t version); diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index a46d2466fd..4fa109fb0e 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -31,8 +31,10 @@ DOMAIN = "entity_string_pool" _KEY_DC_IDX = "_entity_dc_idx" _KEY_UOM_IDX = "_entity_uom_idx" _KEY_ICON_IDX = "_entity_icon_idx" +_KEY_ENTITY_NAME = "_entity_name" +_KEY_OBJECT_ID_HASH = "_entity_object_id_hash" -# Bit layout for set_entity_strings(packed) — must match C++ setter in entity_base.h: +# Bit layout for entity_strings_packed in configure_entity_() — must match C++ in entity_base.h: # [23..16] icon (8 bits) | [15..8] UoM (8 bits) | [7..0] device_class (8 bits) _DC_SHIFT = 0 _UOM_SHIFT = 8 @@ -219,17 +221,18 @@ def setup_unit_of_measurement(config: ConfigType) -> None: def finalize_entity_strings(var: MockObj, config: ConfigType) -> None: - """Emit a single set_entity_strings() call with all packed indices. + """Emit a single configure_entity_() call with name, hash, and packed string indices. Call this at the end of each component's setup function, after setup_entity() and any register_device_class/register_unit_of_measurement calls. """ + entity_name = config[_KEY_ENTITY_NAME] + object_id_hash = config[_KEY_OBJECT_ID_HASH] dc_idx = config.get(_KEY_DC_IDX, 0) uom_idx = config.get(_KEY_UOM_IDX, 0) icon_idx = config.get(_KEY_ICON_IDX, 0) packed = (dc_idx << _DC_SHIFT) | (uom_idx << _UOM_SHIFT) | (icon_idx << _ICON_SHIFT) - if packed != 0: - add(var.set_entity_strings(packed)) + add(var.configure_entity_(entity_name, object_id_hash, packed)) def get_base_entity_object_id( @@ -331,13 +334,15 @@ async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> device: MockObj = await get_variable(device_id_obj) add(var.set_device(device)) - # Set the entity name with pre-computed object_id hash + # Pre-compute entity name and object_id hash for configure_entity_() + # which is emitted later by finalize_entity_strings(). # For named entities: pre-compute hash from entity name # For empty-name entities: pass 0, C++ calculates hash at runtime from # device name, friendly_name, or app name (bug-for-bug compatibility) entity_name = config[CONF_NAME] object_id_hash = fnv1_hash_object_id(entity_name) if entity_name else 0 - add(var.set_name(entity_name, object_id_hash)) + config[_KEY_ENTITY_NAME] = entity_name + config[_KEY_OBJECT_ID_HASH] = object_id_hash # Only set disabled_by_default if True (default is False) if config[CONF_DISABLED_BY_DEFAULT]: add(var.set_disabled_by_default(True)) diff --git a/tests/component_tests/binary_sensor/test_binary_sensor.py b/tests/component_tests/binary_sensor/test_binary_sensor.py index ce4e64681f..fbc2f37d9a 100644 --- a/tests/component_tests/binary_sensor/test_binary_sensor.py +++ b/tests/component_tests/binary_sensor/test_binary_sensor.py @@ -29,7 +29,7 @@ def test_binary_sensor_sets_mandatory_fields(generate_main): ) # Then - assert 'bs_1->set_name("test bs1",' in main_cpp + assert 'bs_1->configure_entity_("test bs1",' in main_cpp assert "bs_1->set_pin(" in main_cpp diff --git a/tests/component_tests/button/test_button.py b/tests/component_tests/button/test_button.py index 797b6fb1a4..9f94d61c8c 100644 --- a/tests/component_tests/button/test_button.py +++ b/tests/component_tests/button/test_button.py @@ -26,7 +26,7 @@ def test_button_sets_mandatory_fields(generate_main): main_cpp = generate_main("tests/component_tests/button/test_button.yaml") # Then - assert 'wol_1->set_name("wol_test_1",' in main_cpp + assert 'wol_1->configure_entity_("wol_test_1",' in main_cpp assert "wol_2->set_macaddr(18, 52, 86, 120, 144, 171);" in main_cpp diff --git a/tests/component_tests/sensor/test_sensor.py b/tests/component_tests/sensor/test_sensor.py index 221e7edf2c..d9ab3a022c 100644 --- a/tests/component_tests/sensor/test_sensor.py +++ b/tests/component_tests/sensor/test_sensor.py @@ -1,5 +1,15 @@ """Tests for the sensor component.""" +import re + + +def _extract_packed_value(main_cpp, var_name): + """Extract the third (packed) argument from a configure_entity_ call.""" + pattern = rf"{re.escape(var_name)}->configure_entity_\([^,]+,\s*\w+,\s*(\d+)\)" + match = re.search(pattern, main_cpp) + assert match, f"configure_entity_ call not found for {var_name}" + return int(match.group(1)) + def test_sensor_device_class_set(generate_main): """ @@ -10,5 +20,6 @@ def test_sensor_device_class_set(generate_main): # When main_cpp = generate_main("tests/component_tests/sensor/test_sensor.yaml") - # Then - assert "s_1->set_entity_strings(" in main_cpp + # Then: device_class: voltage means packed value must be non-zero + packed = _extract_packed_value(main_cpp, "s_1") + assert packed != 0 diff --git a/tests/component_tests/text/test_text.py b/tests/component_tests/text/test_text.py index 16f5f980a5..3ceaa9b8f8 100644 --- a/tests/component_tests/text/test_text.py +++ b/tests/component_tests/text/test_text.py @@ -25,7 +25,7 @@ def test_text_sets_mandatory_fields(generate_main): main_cpp = generate_main("tests/component_tests/text/test_text.yaml") # Then - assert 'it_1->set_name("test 1 text",' in main_cpp + assert 'it_1->configure_entity_("test 1 text",' in main_cpp def test_text_config_value_internal_set(generate_main): diff --git a/tests/component_tests/text_sensor/test_text_sensor.py b/tests/component_tests/text_sensor/test_text_sensor.py index 4aaebe04d1..f30b820e94 100644 --- a/tests/component_tests/text_sensor/test_text_sensor.py +++ b/tests/component_tests/text_sensor/test_text_sensor.py @@ -1,5 +1,15 @@ """Tests for the text sensor component.""" +import re + + +def _extract_packed_value(main_cpp, var_name): + """Extract the third (packed) argument from a configure_entity_ call.""" + pattern = rf"{re.escape(var_name)}->configure_entity_\([^,]+,\s*\w+,\s*(\d+)\)" + match = re.search(pattern, main_cpp) + assert match, f"configure_entity_ call not found for {var_name}" + return int(match.group(1)) + def test_text_sensor_is_setup(generate_main): """ @@ -25,9 +35,9 @@ def test_text_sensor_sets_mandatory_fields(generate_main): main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") # Then - assert 'ts_1->set_name("Template Text Sensor 1",' in main_cpp - assert 'ts_2->set_name("Template Text Sensor 2",' in main_cpp - assert 'ts_3->set_name("Template Text Sensor 3",' in main_cpp + assert 'ts_1->configure_entity_("Template Text Sensor 1",' in main_cpp + assert 'ts_2->configure_entity_("Template Text Sensor 2",' in main_cpp + assert 'ts_3->configure_entity_("Template Text Sensor 3",' in main_cpp def test_text_sensor_config_value_internal_set(generate_main): @@ -53,6 +63,9 @@ def test_text_sensor_device_class_set(generate_main): # When main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") - # Then - assert "ts_2->set_entity_strings(" in main_cpp - assert "ts_3->set_entity_strings(" in main_cpp + # Then: ts_2 has device_class: timestamp, ts_3 has device_class: date + # so their packed values must be non-zero + packed_ts_2 = _extract_packed_value(main_cpp, "ts_2") + assert packed_ts_2 != 0 + packed_ts_3 = _extract_packed_value(main_cpp, "ts_3") + assert packed_ts_3 != 0 diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index 1392a1d043..3f6faaee54 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -32,9 +32,11 @@ from esphome.helpers import sanitize, snake_case from .common import load_config_from_fixture -# Pre-compiled regex pattern for extracting names from set_name calls -# Matches: .set_name("name", hash) or .set_name("name") -SET_NAME_PATTERN = re.compile(r'\.set_name\(["\']([^"\']*)["\']') +# Pre-compiled regex pattern for extracting names from configure_entity_/set_name calls +# Matches: .configure_entity_("name", ...) or .set_name("name", ...) +ENTITY_NAME_PATTERN = re.compile( + r'\.(?:configure_entity_|set_name)\(["\']([^"\']*)["\']' +) FIXTURES_DIR = Path(__file__).parent.parent / "fixtures" / "core" / "entity_helpers" @@ -276,15 +278,23 @@ def setup_test_environment() -> Generator[list[str], None, None]: entity_helpers.add = original_add -def extract_object_id_from_expressions(expressions: list[str]) -> str | None: - """Extract the object ID that would be computed from set_name calls. +def extract_object_id_from_config(config: dict[str, Any]) -> str | None: + """Extract the object ID from config keys set by _setup_entity_impl.""" + name = config.get("_entity_name") + if name is None: + return None + if name: + return sanitize(snake_case(name)) + # Empty name - fall back to friendly_name or device name + if CORE.friendly_name: + return sanitize(snake_case(CORE.friendly_name)) + return sanitize(snake_case(CORE.name)) if CORE.name else None - Since object_id is now computed from the name (via snake_case + sanitize), - we extract the name from set_name() calls and compute the expected object_id. - For empty names, we fall back to CORE.friendly_name or CORE.name. - """ + +def extract_object_id_from_expressions(expressions: list[str]) -> str | None: + """Extract the object ID from configure_entity_() calls in generated expressions.""" for expr in expressions: - if match := SET_NAME_PATTERN.search(expr): + if match := ENTITY_NAME_PATTERN.search(expr): name = match.group(1) if name: return sanitize(snake_case(name)) @@ -299,8 +309,6 @@ def extract_object_id_from_expressions(expressions: list[str]) -> str | None: async def test_setup_entity_no_duplicates(setup_test_environment: list[str]) -> None: """Test setup_entity with unique names.""" - added_expressions = setup_test_environment - # Create mock entities var1 = MockObj("sensor1") var2 = MockObj("sensor2") @@ -312,13 +320,10 @@ async def test_setup_entity_no_duplicates(setup_test_environment: list[str]) -> } await _setup_entity_impl(var1, config1, "sensor") - # Get object ID from first entity - object_id1 = extract_object_id_from_expressions(added_expressions) + # Get object ID from first entity (stored in config, emitted later by finalize) + object_id1 = extract_object_id_from_config(config1) assert object_id1 == "temperature" - # Clear for next entity - added_expressions.clear() - # Set up second entity with different name config2 = { CONF_NAME: "Humidity", @@ -327,7 +332,7 @@ async def test_setup_entity_no_duplicates(setup_test_environment: list[str]) -> await _setup_entity_impl(var2, config2, "sensor") # Get object ID from second entity - object_id2 = extract_object_id_from_expressions(added_expressions) + object_id2 = extract_object_id_from_config(config2) assert object_id2 == "humidity" @@ -337,8 +342,6 @@ async def test_setup_entity_different_platforms( ) -> None: """Test that same name on different platforms doesn't conflict.""" - added_expressions = setup_test_environment - # Create mock entities sensor = MockObj("sensor1") binary_sensor = MockObj("binary_sensor1") @@ -356,15 +359,11 @@ async def test_setup_entity_different_platforms( (text_sensor, "text_sensor"), ] - object_ids: list[str] = [] for var, platform in platforms: - added_expressions.clear() await _setup_entity_impl(var, config, platform) - object_id = extract_object_id_from_expressions(added_expressions) - object_ids.append(object_id) - # All should get base object ID without suffix - assert all(obj_id == "status" for obj_id in object_ids) + # All should get the same object ID (name stored in config, not platform-specific) + assert extract_object_id_from_config(config) == "status" @pytest.fixture @@ -389,7 +388,6 @@ async def test_setup_entity_with_devices( setup_test_environment: list[str], mock_get_variable: dict[ID, MockObj] ) -> None: """Test that same name on different devices doesn't conflict.""" - added_expressions = setup_test_environment # Create mock devices device1_id = ID("device1", type="Device") @@ -418,24 +416,18 @@ async def test_setup_entity_with_devices( } # Get object IDs - object_ids: list[str] = [] for var, config in [(sensor1, config1), (sensor2, config2)]: - added_expressions.clear() await _setup_entity_impl(var, config, "sensor") - object_id = extract_object_id_from_expressions(added_expressions) - object_ids.append(object_id) # Both should get base object ID without suffix (different devices) - assert object_ids[0] == "temperature" - assert object_ids[1] == "temperature" + assert extract_object_id_from_config(config1) == "temperature" + assert extract_object_id_from_config(config2) == "temperature" @pytest.mark.asyncio async def test_setup_entity_empty_name(setup_test_environment: list[str]) -> None: """Test setup_entity with empty entity name.""" - added_expressions = setup_test_environment - var = MockObj("sensor1") config = { @@ -445,7 +437,7 @@ async def test_setup_entity_empty_name(setup_test_environment: list[str]) -> Non await _setup_entity_impl(var, config, "sensor") - object_id = extract_object_id_from_expressions(added_expressions) + object_id = extract_object_id_from_config(config) # Should use friendly name assert object_id == "test_device" @@ -456,8 +448,6 @@ async def test_setup_entity_special_characters( ) -> None: """Test setup_entity with names containing special characters.""" - added_expressions = setup_test_environment - var = MockObj("sensor1") config = { @@ -466,7 +456,7 @@ async def test_setup_entity_special_characters( } await _setup_entity_impl(var, config, "sensor") - object_id = extract_object_id_from_expressions(added_expressions) + object_id = extract_object_id_from_config(config) # Special characters should be sanitized assert object_id == "temperature_sensor_" @@ -476,8 +466,6 @@ async def test_setup_entity_special_characters( async def test_setup_entity_with_icon(setup_test_environment: list[str]) -> None: """Test setup_entity sets icon correctly.""" - setup_test_environment # noqa: F841 - fixture initializes CORE state - var = MockObj("sensor1") config = { @@ -800,10 +788,9 @@ async def test_setup_entity_empty_name_with_device( # Check that set_device was called assert any("sensor1.set_device" in expr for expr in added_expressions) - # For empty-name entities, Python passes 0 - C++ calculates hash at runtime - assert any('set_name("", 0)' in expr for expr in added_expressions), ( - f"Expected set_name with hash 0, got {added_expressions}" - ) + # For empty-name entities, Python stores hash 0 - C++ calculates hash at runtime + assert config.get("_entity_name") == "" + assert config.get("_entity_object_id_hash") == 0 @pytest.mark.asyncio @@ -815,7 +802,6 @@ async def test_setup_entity_empty_name_with_mac_suffix( For empty-name entities, Python passes 0 and C++ calculates the hash at runtime from friendly_name (bug-for-bug compatibility). """ - added_expressions = setup_test_environment # Set up CORE.config with name_add_mac_suffix enabled CORE.config = {"name_add_mac_suffix": True} @@ -831,10 +817,9 @@ async def test_setup_entity_empty_name_with_mac_suffix( await _setup_entity_impl(var, config, "sensor") - # For empty-name entities, Python passes 0 - C++ calculates hash at runtime - assert any('set_name("", 0)' in expr for expr in added_expressions), ( - f"Expected set_name with hash 0, got {added_expressions}" - ) + # For empty-name entities, Python stores hash 0 - C++ calculates hash at runtime + assert config.get("_entity_name") == "" + assert config.get("_entity_object_id_hash") == 0 @pytest.mark.asyncio @@ -847,7 +832,6 @@ async def test_setup_entity_empty_name_with_mac_suffix_no_friendly_name( at runtime. In this case C++ will hash the empty friendly_name (bug-for-bug compatibility). """ - added_expressions = setup_test_environment # Set up CORE.config with name_add_mac_suffix enabled CORE.config = {"name_add_mac_suffix": True} @@ -863,10 +847,9 @@ async def test_setup_entity_empty_name_with_mac_suffix_no_friendly_name( await _setup_entity_impl(var, config, "sensor") - # For empty-name entities, Python passes 0 - C++ calculates hash at runtime - assert any('set_name("", 0)' in expr for expr in added_expressions), ( - f"Expected set_name with hash 0, got {added_expressions}" - ) + # For empty-name entities, Python stores hash 0 - C++ calculates hash at runtime + assert config.get("_entity_name") == "" + assert config.get("_entity_object_id_hash") == 0 @pytest.mark.asyncio @@ -878,7 +861,6 @@ async def test_setup_entity_empty_name_no_mac_suffix_no_friendly_name( For empty-name entities, Python passes 0 and C++ calculates the hash at runtime from the device name. """ - added_expressions = setup_test_environment # No MAC suffix (either not set or False) CORE.config = {} @@ -896,10 +878,9 @@ async def test_setup_entity_empty_name_no_mac_suffix_no_friendly_name( await _setup_entity_impl(var, config, "sensor") - # For empty-name entities, Python passes 0 - C++ calculates hash at runtime - assert any('set_name("", 0)' in expr for expr in added_expressions), ( - f"Expected set_name with hash 0, got {added_expressions}" - ) + # For empty-name entities, Python stores hash 0 - C++ calculates hash at runtime + assert config.get("_entity_name") == "" + assert config.get("_entity_object_id_hash") == 0 def test_register_string_overflow() -> None: @@ -976,7 +957,7 @@ async def test_setup_entity_direct_call(setup_test_environment: list[str]) -> No # Direct call mode: await setup_entity(var, config, "camera") await setup_entity(var, config, "camera") - # Should have called set_name + # Should have emitted configure_entity_ object_id = extract_object_id_from_expressions(added_expressions) assert object_id == "my_camera" From 77f2c371b2b20b00d6e064bd5cbc618b2f1e22c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:26:34 -1000 Subject: [PATCH 1189/2030] [api] Single-pass protobuf encode for BLE proxy advertisements (#14575) --- esphome/components/api/api_pb2.cpp | 28 ++++++------ esphome/components/api/proto.cpp | 71 +++++++++++++++++++++++++++++ esphome/components/api/proto.h | 44 ++++++++---------- script/api_protobuf/api_protobuf.py | 17 +++---- 4 files changed, 111 insertions(+), 49 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index b1176de539..1944aac6e8 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -120,16 +120,16 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { #endif #ifdef USE_DEVICES for (const auto &it : this->devices) { - buffer.encode_message(20, it); + buffer.encode_sub_message(20, it); } #endif #ifdef USE_AREAS for (const auto &it : this->areas) { - buffer.encode_message(21, it); + buffer.encode_sub_message(21, it); } #endif #ifdef USE_AREAS - buffer.encode_message(22, this->area, false); + buffer.encode_optional_sub_message(22, this->area); #endif #ifdef USE_ZWAVE_PROXY buffer.encode_uint32(23, this->zwave_proxy_feature_flags); @@ -920,13 +920,13 @@ uint32_t HomeassistantServiceMap::calculate_size() const { void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->service); for (auto &it : this->data) { - buffer.encode_message(2, it); + buffer.encode_sub_message(2, it); } for (auto &it : this->data_template) { - buffer.encode_message(3, it); + buffer.encode_sub_message(3, it); } for (auto &it : this->variables) { - buffer.encode_message(4, it); + buffer.encode_sub_message(4, it); } buffer.encode_bool(5, this->is_event); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES @@ -1126,7 +1126,7 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); buffer.encode_fixed32(2, this->key); for (auto &it : this->args) { - buffer.encode_message(3, it); + buffer.encode_sub_message(3, it); } buffer.encode_uint32(4, static_cast<uint32_t>(this->supports_response)); } @@ -2133,7 +2133,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); buffer.encode_bool(8, this->supports_pause); for (auto &it : this->supported_formats) { - buffer.encode_message(9, it); + buffer.encode_sub_message(9, it); } #ifdef USE_DEVICES buffer.encode_uint32(10, this->device_id); @@ -2264,7 +2264,7 @@ uint32_t BluetoothLERawAdvertisement::calculate_size() const { } void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { for (uint16_t i = 0; i < this->advertisements_len; i++) { - buffer.encode_message(1, this->advertisements[i]); + buffer.encode_sub_message(1, this->advertisements[i]); } } uint32_t BluetoothLERawAdvertisementsResponse::calculate_size() const { @@ -2343,7 +2343,7 @@ void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(2, this->handle); buffer.encode_uint32(3, this->properties); for (auto &it : this->descriptors) { - buffer.encode_message(4, it); + buffer.encode_sub_message(4, it); } buffer.encode_uint32(5, this->short_uuid); } @@ -2370,7 +2370,7 @@ void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const { } buffer.encode_uint32(2, this->handle); for (auto &it : this->characteristics) { - buffer.encode_message(3, it); + buffer.encode_sub_message(3, it); } buffer.encode_uint32(4, this->short_uuid); } @@ -2392,7 +2392,7 @@ uint32_t BluetoothGATTService::calculate_size() const { void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint64(1, this->address); for (auto &it : this->services) { - buffer.encode_message(2, it); + buffer.encode_sub_message(2, it); } } uint32_t BluetoothGATTGetServicesResponse::calculate_size() const { @@ -2673,7 +2673,7 @@ void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->start); buffer.encode_string(2, this->conversation_id); buffer.encode_uint32(3, this->flags); - buffer.encode_message(4, this->audio_settings, false); + buffer.encode_optional_sub_message(4, this->audio_settings); buffer.encode_string(5, this->wake_word_phrase); } uint32_t VoiceAssistantRequest::calculate_size() const { @@ -2906,7 +2906,7 @@ bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoL } void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer) const { for (auto &it : this->available_wake_words) { - buffer.encode_message(1, it); + buffer.encode_sub_message(1, it); } for (const auto &it : *this->active_wake_words) { buffer.encode_string(2, it, true); diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index a252907fd7..1ca6b702ad 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -1,5 +1,6 @@ #include "proto.h" #include <cinttypes> +#include <cstring> #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -87,6 +88,76 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size return count; } +// Single-pass encode for repeated submessage elements (non-template core). +// Writes field tag, reserves 1 byte for length varint, encodes the submessage body, +// then backpatches the actual length. For the common case (body < 128 bytes), this is +// just a single byte write with no memmove — all current repeated submessage types +// (BLE advertisements at ~47B, GATT descriptors at ~24B, service args, etc.) take +// this fast path. +// +// The memmove fallback for body >= 128 bytes exists only for correctness (e.g., a GATT +// characteristic with many descriptors). It is safe because calculate_size() already +// reserved space for the full multi-byte varint — the shift fills that reserved space: +// +// calculate_size() allocates per element: tag + varint_size(body) + body_size +// +// After encode, before memmove (1 byte reserved, body written): +// [tag][__][body ..... body][??] +// ^ ^-- unused byte (v2 space from calculate_size) +// len_pos +// +// After memmove(body_start+1, body_start, body_size): +// [tag][__][__][body ..... body] +// ^ ^-- body shifted forward, fills v2 space exactly +// len_pos +// +// After writing 2-byte varint at len_pos: +// [tag][v1][v2][body ..... body] +// ^-- pos_ = element end, within buffer +void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const void *value, + void (*encode_fn)(const void *, ProtoWriteBuffer &)) { + this->encode_field_raw(field_id, 2); + // Reserve 1 byte for length varint (optimistic: submessage < 128 bytes) + uint8_t *len_pos = this->pos_; + this->debug_check_bounds_(1); + this->pos_++; + uint8_t *body_start = this->pos_; + encode_fn(value, *this); + uint32_t body_size = static_cast<uint32_t>(this->pos_ - body_start); + if (body_size < 128) [[likely]] { + // Common case: 1-byte varint, just backpatch + *len_pos = static_cast<uint8_t>(body_size); + return; + } + // Compute extra bytes needed for varint beyond the 1 already reserved + uint8_t extra = ProtoSize::varint(body_size) - 1; + // Shift body forward to make room for the extra varint bytes + this->debug_check_bounds_(extra); + std::memmove(body_start + extra, body_start, body_size); + uint8_t *end = this->pos_ + extra; + // Write the full varint at len_pos + this->pos_ = len_pos; + this->encode_varint_raw(body_size); + this->pos_ = end; +} + +// Non-template core for encode_optional_sub_message. +void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value, + void (*encode_fn)(const void *, ProtoWriteBuffer &)) { + if (nested_size == 0) + return; + this->encode_field_raw(field_id, 2); + this->encode_varint_raw(nested_size); +#ifdef ESPHOME_DEBUG_API + uint8_t *start = this->pos_; + encode_fn(value, *this); + if (static_cast<uint32_t>(this->pos_ - start) != nested_size) + this->debug_check_encode_size_(field_id, nested_size, this->pos_ - start); +#else + encode_fn(value, *this); +#endif +} + #ifdef ESPHOME_DEBUG_API void ProtoWriteBuffer::debug_check_bounds_(size_t bytes, const char *caller) { if (this->pos_ + bytes > this->buffer_->data() + this->buffer_->size()) { diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 702208d9de..bbdd11b29d 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -185,7 +185,7 @@ class ProtoVarInt { #endif }; -// Forward declarations for decode_to_message, encode_message and encode_packed_sint32 +// Forward declarations for decode_to_message and related encoding helpers class ProtoDecodableMessage; class ProtoMessage; class ProtoSize; @@ -363,12 +363,18 @@ class ProtoWriteBuffer { } /// Encode a packed repeated sint32 field (zero-copy from vector) void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values); - /// Encode a nested message field (force=true for repeated, false for singular) - /// Templated so concrete message type is preserved for direct encode/calculate_size calls. - template<typename T> void encode_message(uint32_t field_id, const T &value, bool force = true); - // Non-template core for encode_message — all buffer work happens here - void encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value, - void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force); + /// Single-pass encode for repeated submessage elements. + /// Thin template wrapper; all buffer work is in the non-template core. + template<typename T> void encode_sub_message(uint32_t field_id, const T &value); + /// Encode an optional singular submessage field — skips if empty. + /// Thin template wrapper; all buffer work is in the non-template core. + template<typename T> void encode_optional_sub_message(uint32_t field_id, const T &value); + + // Non-template core for encode_sub_message — backpatch approach. + void encode_sub_message(uint32_t field_id, const void *value, void (*encode_fn)(const void *, ProtoWriteBuffer &)); + // Non-template core for encode_optional_sub_message. + void encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value, + void (*encode_fn)(const void *, ProtoWriteBuffer &)); std::vector<uint8_t> *get_buffer() const { return buffer_; } protected: @@ -690,26 +696,14 @@ template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &bu static_cast<const T *>(msg)->encode(buf); } -// Implementation of encode_message - must be after ProtoMessage is defined -template<typename T> inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const T &value, bool force) { - this->encode_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>, force); +// Thin template wrapper; delegates to non-template core in proto.cpp. +template<typename T> inline void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const T &value) { + this->encode_sub_message(field_id, &value, &proto_encode_msg<T>); } -// Non-template core for encode_message -inline void ProtoWriteBuffer::encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value, - void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force) { - if (msg_length_bytes == 0 && !force) - return; - this->encode_field_raw(field_id, 2); - this->encode_varint_raw(msg_length_bytes); -#ifdef ESPHOME_DEBUG_API - uint8_t *start = this->pos_; - encode_fn(value, *this); - if (static_cast<uint32_t>(this->pos_ - start) != msg_length_bytes) - this->debug_check_encode_size_(field_id, msg_length_bytes, this->pos_ - start); -#else - encode_fn(value, *this); -#endif +// Thin template wrapper; delegates to non-template core. +template<typename T> inline void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, const T &value) { + this->encode_optional_sub_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>); } // Implementation of decode_to_message - must be after ProtoDecodableMessage is defined diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 85352689e6..7ae7063a41 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -690,15 +690,12 @@ class MessageType(TypeInfo): @property def encode_func(self) -> str: - return "encode_message" + return "encode_optional_sub_message" @property def encode_content(self) -> str: - # Singular message fields pass force=false (skip empty messages) - # The default for encode_nested_message is force=true (for repeated fields) - return ( - f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, false);" - ) + # Singular message fields skip encoding when empty + return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" @property def decode_length(self) -> str: @@ -1322,9 +1319,9 @@ class FixedArrayRepeatedType(TypeInfo): """Helper to generate encode statement for a single element.""" if isinstance(self._ti, EnumType): return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);" - # MessageType.encode_message doesn't have a force parameter + # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): - return f"buffer.{self._ti.encode_func}({self.number}, {element});" + return f"buffer.encode_sub_message({self.number}, {element});" return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);" @property @@ -1650,9 +1647,9 @@ class RepeatedTypeInfo(TypeInfo): """Helper to generate encode call for a single element.""" if isinstance(self._ti, EnumType): return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);" - # MessageType.encode_message doesn't have a force parameter + # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): - return f"buffer.{self._ti.encode_func}({self.number}, {element});" + return f"buffer.encode_sub_message({self.number}, {element});" return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);" @property From e7b8ec18f17b23709719c63e1d05a6b9ecfb0054 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:26:50 -1000 Subject: [PATCH 1190/2030] [api] Inline APIServer::is_connected() for common no-arg path (#14574) --- esphome/components/api/api_server.cpp | 6 +----- esphome/components/api/api_server.h | 8 ++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 06816fe3e0..17d69405ad 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -582,11 +582,7 @@ void APIServer::request_time() { } #endif -bool APIServer::is_connected(bool state_subscription_only) const { - if (!state_subscription_only) { - return !this->clients_.empty(); - } - +bool APIServer::is_connected_with_state_subscription() const { for (const auto &client : this->clients_) { if (client->flags_.state_subscription) { return true; diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index e6c10d1595..e5f371d8a1 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -185,7 +185,8 @@ class APIServer : public Component, void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings); #endif - bool is_connected(bool state_subscription_only = false) const; + bool is_connected() const { return !this->clients_.empty(); } + bool is_connected_with_state_subscription() const; #ifdef USE_API_HOMEASSISTANT_STATES struct HomeAssistantStateSubscription { @@ -323,7 +324,10 @@ template<typename... Ts> class APIConnectedCondition : public Condition<Ts...> { TEMPLATABLE_VALUE(bool, state_subscription_only) public: bool check(const Ts &...x) override { - return global_api_server->is_connected(this->state_subscription_only_.value(x...)); + if (this->state_subscription_only_.value(x...)) { + return global_api_server->is_connected_with_state_subscription(); + } + return global_api_server->is_connected(); } }; From a0cd35c5fc2b8b1e9ab0db69fd70b90c95e8dbad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 07:27:08 -1000 Subject: [PATCH 1191/2030] [core] Inline status_clear_warning/error fast path (#14571) --- esphome/core/component.cpp | 8 ++------ esphome/core/component.h | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index a9ff3ec1eb..2879d4b5ab 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -422,15 +422,11 @@ void Component::status_set_error(const LogString *message) { store_component_error_message(this, LOG_STR_ARG(message), true); } } -void Component::status_clear_warning() { - if ((this->component_state_ & STATUS_LED_WARNING) == 0) - return; +void Component::status_clear_warning_slow_path_() { this->component_state_ &= ~STATUS_LED_WARNING; ESP_LOGW(TAG, "%s cleared Warning flag", LOG_STR_ARG(this->get_component_log_str())); } -void Component::status_clear_error() { - if ((this->component_state_ & STATUS_LED_ERROR) == 0) - return; +void Component::status_clear_error_slow_path_() { this->component_state_ &= ~STATUS_LED_ERROR; ESP_LOGE(TAG, "%s cleared Error flag", LOG_STR_ARG(this->get_component_log_str())); } diff --git a/esphome/core/component.h b/esphome/core/component.h index 59222dc4f4..7266f57e15 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -251,9 +251,17 @@ class Component { void status_set_error(const char *message); void status_set_error(const LogString *message); - void status_clear_warning(); + void status_clear_warning() { + if ((this->component_state_ & STATUS_LED_WARNING) == 0) + return; + this->status_clear_warning_slow_path_(); + } - void status_clear_error(); + void status_clear_error() { + if ((this->component_state_ & STATUS_LED_ERROR) == 0) + return; + this->status_clear_error_slow_path_(); + } /** Set warning status flag and automatically clear it after a timeout. * @@ -505,6 +513,9 @@ class Component { bool cancel_defer(const char *name); // NOLINT bool cancel_defer(uint32_t id); // NOLINT + void status_clear_warning_slow_path_(); + void status_clear_error_slow_path_(); + // Ordered for optimal packing on 32-bit systems const LogString *component_source_{nullptr}; uint16_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS}; ///< Warn if blocked for this many ms (max 65.5s) From 3f700bac1cebf7eb6ff3b20a87d8c8af5cb9fc41 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Sat, 7 Mar 2026 19:50:44 +0100 Subject: [PATCH 1192/2030] [component] Fix components for compatibility with stricter compilers (#14545) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/esp32_ble/ble.cpp | 2 +- esphome/components/ethernet/esp_eth_phy_jl1101.c | 2 +- esphome/components/ethernet/ethernet_component.cpp | 4 ++-- esphome/components/heatpumpir/climate.py | 1 + .../http_request/update/http_request_update.cpp | 3 ++- esphome/components/mlx90393/sensor_mlx90393.cpp | 2 +- esphome/components/whirlpool/whirlpool.cpp | 7 +++++++ esphome/components/whirlpool/whirlpool.h | 12 ++++++------ 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index bbe972b9f3..7fa5370072 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -451,7 +451,7 @@ void ESP32BLE::loop() { ESP_LOGV(TAG, "gap_event_handler - %d", gap_event); #ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT { - esp_ble_gap_cb_param_t *param; + esp_ble_gap_cb_param_t *param = NULL; // clang-format off switch (gap_event) { // All three scan complete events have the same structure with just status diff --git a/esphome/components/ethernet/esp_eth_phy_jl1101.c b/esphome/components/ethernet/esp_eth_phy_jl1101.c index 5e73e99101..a19f7aa6b0 100644 --- a/esphome/components/ethernet/esp_eth_phy_jl1101.c +++ b/esphome/components/ethernet/esp_eth_phy_jl1101.c @@ -27,7 +27,7 @@ #include "esp_rom_sys.h" #include "esp_idf_version.h" -#if defined(USE_ARDUINO) || ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) static const char *TAG = "jl1101"; #define PHY_CHECK(a, str, goto_tag, ...) \ diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 0bc67c8b03..d6b0d40cd9 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -209,7 +209,7 @@ void EthernetComponent::setup() { break; } #endif -#ifdef USE_ETHERNET_JL1101 +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) case ETHERNET_TYPE_JL1101: { this->phy_ = esp_eth_phy_new_jl1101(&phy_config); break; @@ -374,7 +374,7 @@ void EthernetComponent::dump_config() { eth_type = "IP101"; break; #endif -#ifdef USE_ETHERNET_JL1101 +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) case ETHERNET_TYPE_JL1101: eth_type = "JL1101"; break; diff --git a/esphome/components/heatpumpir/climate.py b/esphome/components/heatpumpir/climate.py index 0d760938d0..7743da77ab 100644 --- a/esphome/components/heatpumpir/climate.py +++ b/esphome/components/heatpumpir/climate.py @@ -125,6 +125,7 @@ async def to_code(config): cg.add(var.set_vertical_default(config[CONF_VERTICAL_DEFAULT])) cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE])) cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) + cg.add_build_flag("-Wno-error=overloaded-virtual") cg.add_library("tonia/HeatpumpIR", "1.0.40") if CORE.is_libretiny or CORE.is_esp32: diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index 1900f69a69..c40590af95 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -128,7 +128,8 @@ void HttpRequestUpdate::update_task(void *params) { this_update->update_info_.title = root[ESPHOME_F("name")].as<std::string>(); this_update->update_info_.latest_version = root[ESPHOME_F("version")].as<std::string>(); - for (auto build : root[ESPHOME_F("builds")].as<JsonArray>()) { + auto builds_array = root[ESPHOME_F("builds")].as<JsonArray>(); + for (auto build : builds_array) { if (!build[ESPHOME_F("chipFamily")].is<const char *>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; diff --git a/esphome/components/mlx90393/sensor_mlx90393.cpp b/esphome/components/mlx90393/sensor_mlx90393.cpp index ee52f9b9ab..01084e50df 100644 --- a/esphome/components/mlx90393/sensor_mlx90393.cpp +++ b/esphome/components/mlx90393/sensor_mlx90393.cpp @@ -160,7 +160,7 @@ bool MLX90393Cls::verify_setting_(MLX90393Setting which) { uint8_t read_value = 0xFF; uint8_t expected_value = 0xFF; uint8_t read_status = -1; - char read_back_str[25] = {0}; + char read_back_str[33] = {0}; switch (which) { case MLX90393_GAIN_SEL: { diff --git a/esphome/components/whirlpool/whirlpool.cpp b/esphome/components/whirlpool/whirlpool.cpp index e9f602e97f..86209cb7a6 100644 --- a/esphome/components/whirlpool/whirlpool.cpp +++ b/esphome/components/whirlpool/whirlpool.cpp @@ -32,6 +32,13 @@ const uint8_t WHIRLPOOL_SWING_MASK = 128; const uint8_t WHIRLPOOL_POWER = 0x04; +WhirlpoolClimate::WhirlpoolClimate() + : climate_ir::ClimateIR( + WHIRLPOOL_DG11J1_3A_TEMP_MIN, WHIRLPOOL_DG11J1_3A_TEMP_MAX, 1.0f, true, true, + {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, climate::CLIMATE_FAN_HIGH}, + {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}), + model_(MODEL_DG11J1_3A) {} + void WhirlpoolClimate::transmit_state() { this->last_transmit_time_ = millis(); // setting the time of the last transmission. uint8_t remote_state[WHIRLPOOL_STATE_LENGTH] = {0}; diff --git a/esphome/components/whirlpool/whirlpool.h b/esphome/components/whirlpool/whirlpool.h index 992b2a7adf..ada5a36de9 100644 --- a/esphome/components/whirlpool/whirlpool.h +++ b/esphome/components/whirlpool/whirlpool.h @@ -19,11 +19,7 @@ const float WHIRLPOOL_DG11J1_91_TEMP_MIN = 16.0; class WhirlpoolClimate : public climate_ir::ClimateIR { public: - WhirlpoolClimate() - : climate_ir::ClimateIR(temperature_min_(), temperature_max_(), 1.0f, true, true, - {climate::CLIMATE_FAN_AUTO, climate::CLIMATE_FAN_LOW, climate::CLIMATE_FAN_MEDIUM, - climate::CLIMATE_FAN_HIGH}, - {climate::CLIMATE_SWING_OFF, climate::CLIMATE_SWING_VERTICAL}) {} + WhirlpoolClimate(); void setup() override { climate_ir::ClimateIR::setup(); @@ -37,7 +33,11 @@ class WhirlpoolClimate : public climate_ir::ClimateIR { climate_ir::ClimateIR::control(call); } - void set_model(Model model) { this->model_ = model; } + void set_model(Model model) { + this->model_ = model; + this->minimum_temperature_ = temperature_min_(); + this->maximum_temperature_ = temperature_max_(); + } // used to track when to send the power toggle command bool powered_on_assumed; From f2dfb5e1dcfd7bd47677f8d0c75b41bbd0e25bb7 Mon Sep 17 00:00:00 2001 From: Oliver Kleinecke <okleinecke@web.de> Date: Sun, 8 Mar 2026 00:16:12 +0100 Subject: [PATCH 1193/2030] [uart][usb_uart] Add debug_prefix option to distinguish multiple defined uarts in log (#14525) --- esphome/components/uart/__init__.py | 13 ++++- esphome/components/uart/uart_debugger.cpp | 18 +++--- esphome/components/uart/uart_debugger.h | 17 ++++-- esphome/components/usb_uart/__init__.py | 5 +- esphome/components/usb_uart/usb_uart.cpp | 4 +- esphome/components/usb_uart/usb_uart.h | 3 + tests/components/uart/test.esp32-c3-idf.yaml | 16 +++++- tests/components/uart/test.esp32-idf.yaml | 60 +++++++++++++++----- tests/components/uart/test.esp8266-ard.yaml | 24 +++++--- tests/components/uart/test.host.yaml | 2 +- tests/components/uart/test.rp2040-ard.yaml | 16 +++++- tests/components/usb_uart/common.yaml | 8 +++ 12 files changed, 138 insertions(+), 48 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 3bc4263b31..1b976b73a9 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -203,8 +203,10 @@ UART_DIRECTIONS = { # round numbers. AFTER_DEFAULTS = {CONF_BYTES: 150, CONF_TIMEOUT: "100ms"} +CONF_DEBUG_PREFIX = "debug_prefix" + # By default, log in hex format when no specific sequence is provided. -DEFAULT_DEBUG_OUTPUT = "UARTDebug::log_hex(direction, bytes, ':');" +DEFAULT_DEBUG_OUTPUT = "UARTDebug::log_hex(direction, bytes, ':', debug_prefix);" DEFAULT_SEQUENCE = [{CONF_LAMBDA: make_data_base(DEFAULT_DEBUG_OUTPUT)}] @@ -242,6 +244,7 @@ DEBUG_SCHEMA = cv.Schema( ): automation.validate_automation(), cv.Optional(CONF_DUMMY_RECEIVER, default=False): cv.boolean, cv.GenerateID(CONF_DUMMY_RECEIVER_ID): cv.declare_id(UARTDummyReceiver), + cv.Optional(CONF_DEBUG_PREFIX, default=""): cv.string, } ) @@ -283,7 +286,11 @@ async def debug_to_code(config, parent): for action in config[CONF_SEQUENCE]: await automation.build_automation( trigger, - [(UARTDirection, "direction"), (cg.std_vector.template(cg.uint8), "bytes")], + [ + (UARTDirection, "direction"), + (cg.std_vector.template(cg.uint8), "bytes"), + (cg.StringRef, "debug_prefix"), + ], action, ) cg.add(trigger.set_direction(config[CONF_DIRECTION])) @@ -299,6 +306,8 @@ async def debug_to_code(config, parent): if config[CONF_DUMMY_RECEIVER]: dummy = cg.new_Pvariable(config[CONF_DUMMY_RECEIVER_ID], parent) await cg.register_component(dummy, {}) + if debug_prefix := config[CONF_DEBUG_PREFIX]: + cg.add(trigger.set_debug_prefix(debug_prefix)) cg.add_define("USE_UART_DEBUGGER") diff --git a/esphome/components/uart/uart_debugger.cpp b/esphome/components/uart/uart_debugger.cpp index 5490154d01..e0be599d8d 100644 --- a/esphome/components/uart/uart_debugger.cpp +++ b/esphome/components/uart/uart_debugger.cpp @@ -74,7 +74,7 @@ bool UARTDebugger::has_buffered_bytes_() { return !this->bytes_.empty(); } void UARTDebugger::fire_trigger_() { this->is_triggering_ = true; - trigger(this->last_direction_, this->bytes_); + trigger(this->last_direction_, this->bytes_, this->debug_prefix_); this->bytes_.clear(); this->is_triggering_ = false; } @@ -94,7 +94,7 @@ void UARTDummyReceiver::loop() { // TCP connection(s). Without these delays, debug log lines could go // missing when UART devices block the main loop for too long. -void UARTDebug::log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) { +void UARTDebug::log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, StringRef prefix) { std::string res; if (direction == UART_DIRECTION_RX) { res += "<<< "; @@ -110,11 +110,11 @@ void UARTDebug::log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uin buf_append_printf(buf, sizeof(buf), 0, "%02X", bytes[i]); res += buf; } - ESP_LOGD(TAG, "%s", res.c_str()); + ESP_LOGD(TAG, "%s%s", prefix.c_str(), res.c_str()); delay(10); } -void UARTDebug::log_string(UARTDirection direction, std::vector<uint8_t> bytes) { +void UARTDebug::log_string(UARTDirection direction, std::vector<uint8_t> bytes, StringRef prefix) { std::string res; if (direction == UART_DIRECTION_RX) { res += "<<< \""; @@ -154,11 +154,11 @@ void UARTDebug::log_string(UARTDirection direction, std::vector<uint8_t> bytes) } } res += '"'; - ESP_LOGD(TAG, "%s", res.c_str()); + ESP_LOGD(TAG, "%s%s", prefix.c_str(), res.c_str()); delay(10); } -void UARTDebug::log_int(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) { +void UARTDebug::log_int(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, StringRef prefix) { std::string res; size_t len = bytes.size(); if (direction == UART_DIRECTION_RX) { @@ -174,11 +174,11 @@ void UARTDebug::log_int(UARTDirection direction, std::vector<uint8_t> bytes, uin buf_append_printf(buf, sizeof(buf), 0, "%u", bytes[i]); res += buf; } - ESP_LOGD(TAG, "%s", res.c_str()); + ESP_LOGD(TAG, "%s%s", prefix.c_str(), res.c_str()); delay(10); } -void UARTDebug::log_binary(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator) { +void UARTDebug::log_binary(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, StringRef prefix) { std::string res; size_t len = bytes.size(); if (direction == UART_DIRECTION_RX) { @@ -194,7 +194,7 @@ void UARTDebug::log_binary(UARTDirection direction, std::vector<uint8_t> bytes, buf_append_printf(buf, sizeof(buf), 0, "0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", BYTE_TO_BINARY(bytes[i]), bytes[i]); res += buf; } - ESP_LOGD(TAG, "%s", res.c_str()); + ESP_LOGD(TAG, "%s%s", prefix.c_str(), res.c_str()); delay(10); } diff --git a/esphome/components/uart/uart_debugger.h b/esphome/components/uart/uart_debugger.h index df87655962..da33bea70c 100644 --- a/esphome/components/uart/uart_debugger.h +++ b/esphome/components/uart/uart_debugger.h @@ -5,6 +5,7 @@ #include <vector> #include "esphome/core/component.h" #include "esphome/core/automation.h" +#include "esphome/core/string_ref.h" #include "uart.h" #include "uart_component.h" @@ -17,7 +18,7 @@ namespace esphome::uart { /// 'appropriate time' means exactly, is determined by a number of /// configurable constraints. E.g. when a given number of bytes is gathered /// and/or when no more data has been seen for a given time interval. -class UARTDebugger : public Component, public Trigger<UARTDirection, std::vector<uint8_t>> { +class UARTDebugger : public Component, public Trigger<UARTDirection, std::vector<uint8_t>, StringRef> { public: explicit UARTDebugger(UARTComponent *parent); void loop() override; @@ -41,6 +42,8 @@ class UARTDebugger : public Component, public Trigger<UARTDirection, std::vector /// logging will be triggered. void add_delimiter_byte(uint8_t byte) { this->after_delimiter_.push_back(byte); } + void set_debug_prefix(const char *prefix) { this->debug_prefix_ = StringRef(prefix); } + protected: UARTDirection for_direction_; UARTDirection last_direction_{}; @@ -51,6 +54,7 @@ class UARTDebugger : public Component, public Trigger<UARTDirection, std::vector std::vector<uint8_t> after_delimiter_{}; size_t after_delimiter_pos_{}; bool is_triggering_{false}; + StringRef debug_prefix_{}; bool is_my_direction_(UARTDirection direction); bool is_recursive_(); @@ -81,18 +85,21 @@ class UARTDebug { public: /// Log the bytes as hex values, separated by the provided separator /// character. - static void log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator); + static void log_hex(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, + StringRef prefix = StringRef()); /// Log the bytes as string values, escaping unprintable characters. - static void log_string(UARTDirection direction, std::vector<uint8_t> bytes); + static void log_string(UARTDirection direction, std::vector<uint8_t> bytes, StringRef prefix = StringRef()); /// Log the bytes as integer values, separated by the provided separator /// character. - static void log_int(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator); + static void log_int(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, + StringRef prefix = StringRef()); /// Log the bytes as '<binary> (<hex>)' values, separated by the provided /// separator. - static void log_binary(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator); + static void log_binary(UARTDirection direction, std::vector<uint8_t> bytes, uint8_t separator, + StringRef prefix = StringRef()); }; } // namespace esphome::uart diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index f0ee53d028..eedf590eca 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg from esphome.components import socket from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS -from esphome.components.uart import UARTComponent +from esphome.components.uart import CONF_DEBUG_PREFIX, UARTComponent from esphome.components.usb_host import register_usb_client, usb_device_schema import esphome.config_validation as cv from esphome.const import ( @@ -90,6 +90,7 @@ def channel_schema(channels, baud_rate_required): ), cv.Optional(CONF_DUMMY_RECEIVER, default=False): cv.boolean, cv.Optional(CONF_DEBUG, default=False): cv.boolean, + cv.Optional(CONF_DEBUG_PREFIX, default=""): cv.string, } ) ), @@ -129,6 +130,8 @@ async def to_code(config): cg.add(chvar.set_baud_rate(channel[CONF_BAUD_RATE])) cg.add(chvar.set_dummy_receiver(channel[CONF_DUMMY_RECEIVER])) cg.add(chvar.set_debug(channel[CONF_DEBUG])) + if channel[CONF_DEBUG_PREFIX]: + cg.add(chvar.set_debug_prefix(channel[CONF_DEBUG_PREFIX])) cg.add(var.add_channel(chvar)) if channel[CONF_DEBUG]: cg.add_define("USE_UART_DEBUGGER") diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index e20bbd02db..a1f8738491 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -142,7 +142,7 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { size_t n = std::min(len - off, BATCH); memcpy(buf, ">>> ", 4); format_hex_pretty_to(buf + 4, sizeof(buf) - 4, data + off, n, ','); - ESP_LOGD(TAG, "%s", buf); + ESP_LOGD(TAG, "%s%s", this->debug_prefix_.c_str(), buf); } } #endif @@ -219,7 +219,7 @@ void USBUartComponent::loop() { char buf[4 + format_hex_pretty_size(UsbDataChunk::MAX_CHUNK_SIZE)]; // "<<< " + hex memcpy(buf, "<<< ", 4); format_hex_pretty_to(buf + 4, sizeof(buf) - 4, chunk->data, chunk->length, ','); - ESP_LOGD(TAG, "%s", buf); + ESP_LOGD(TAG, "%s%s", channel->debug_prefix_.c_str(), buf); } #endif diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 0d471e46f6..7290f8a958 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -3,6 +3,7 @@ #if defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include "esphome/core/string_ref.h" #include "esphome/components/uart/uart_component.h" #include "esphome/components/usb_host/usb_host.h" #include "esphome/core/lock_free_queue.h" @@ -114,6 +115,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon void set_parity(UARTParityOptions parity) { this->parity_ = parity; } void set_debug(bool debug) { this->debug_ = debug; } void set_dummy_receiver(bool dummy_receiver) { this->dummy_receiver_ = dummy_receiver; } + void set_debug_prefix(const char *prefix) { this->debug_prefix_ = StringRef(prefix); } /// Register a callback invoked immediately after data is pushed to the input ring buffer. /// Called from USBUartComponent::loop() in the main loop context. @@ -138,6 +140,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon const uint8_t index_; bool debug_{}; bool dummy_receiver_{}; + StringRef debug_prefix_{}; }; class USBUartComponent : public usb_host::USBClient { diff --git a/tests/components/uart/test.esp32-c3-idf.yaml b/tests/components/uart/test.esp32-c3-idf.yaml index b053290a8b..2eae37e824 100644 --- a/tests/components/uart/test.esp32-c3-idf.yaml +++ b/tests/components/uart/test.esp32-c3-idf.yaml @@ -1,11 +1,15 @@ esphome: on_boot: then: - - uart.write: 'Hello World' - - uart.write: [0x00, 0x20, 0x42] + - uart.write: + id: uart_id + data: 'Hello World' + - uart.write: + id: uart_id + data: [0x00, 0x20, 0x42] uart: - - id: uart_uart + - id: uart_id tx_pin: 4 rx_pin: 5 flow_control_pin: 6 @@ -16,3 +20,9 @@ uart: rx_timeout: 1 parity: EVEN stop_bits: 2 + - id: uart_debug + tx_pin: 18 + rx_pin: 19 + baud_rate: 115200 + debug: + debug_prefix: "[UART1] " diff --git a/tests/components/uart/test.esp32-idf.yaml b/tests/components/uart/test.esp32-idf.yaml index 2a97f9a5de..fa76316b9c 100644 --- a/tests/components/uart/test.esp32-idf.yaml +++ b/tests/components/uart/test.esp32-idf.yaml @@ -1,13 +1,19 @@ esphome: on_boot: then: - - uart.write: 'Hello World' - - uart.write: [0x00, 0x20, 0x42] - - uart.write: !lambda |- - return {0xAA, 0xBB, 0xCC}; + - uart.write: + id: uart_id + data: 'Hello World' + - uart.write: + id: uart_id + data: [0x00, 0x20, 0x42] + - uart.write: + id: uart_id + data: !lambda |- + return {0xAA, 0xBB, 0xCC}; uart: - - id: uart_uart + - id: uart_id tx_pin: 17 rx_pin: 16 flow_control_pin: 4 @@ -18,32 +24,54 @@ uart: rx_timeout: 1 parity: EVEN stop_bits: 2 + - id: uart_debug + tx_pin: 21 + rx_pin: 22 + baud_rate: 115200 + debug: + debug_prefix: "[UART1] " + - id: uart_debug_custom + tx_pin: 25 + rx_pin: 26 + baud_rate: 9600 + debug: + debug_prefix: "[UART2] " + after: + delimiter: "\n" + sequence: + - lambda: UARTDebug::log_string(direction, bytes, debug_prefix); + - id: uart_debug_no_prefix + tx_pin: 32 + rx_pin: 33 + baud_rate: 9600 + debug: packet_transport: - platform: uart + uart_id: uart_id switch: # Test uart switch with single state (array) - platform: uart name: "UART Switch Single Array" - uart_id: uart_uart + uart_id: uart_id data: [0x01, 0x02, 0x03] # Test uart switch with single state (string) - platform: uart name: "UART Switch Single String" - uart_id: uart_uart + uart_id: uart_id data: "ON" # Test uart switch with turn_on/turn_off (arrays) - platform: uart name: "UART Switch Dual Array" - uart_id: uart_uart + uart_id: uart_id data: turn_on: [0xA0, 0xA1, 0xA2] turn_off: [0xB0, 0xB1, 0xB2] # Test uart switch with turn_on/turn_off (strings) - platform: uart name: "UART Switch Dual String" - uart_id: uart_uart + uart_id: uart_id data: turn_on: "TURN_ON" turn_off: "TURN_OFF" @@ -61,24 +89,26 @@ button: # Test uart button with array data - platform: uart name: "UART Button Array" - uart_id: uart_uart + uart_id: uart_id data: [0xFF, 0xEE, 0xDD] # Test uart button with string data - platform: uart name: "UART Button String" - uart_id: uart_uart + uart_id: uart_id data: "BUTTON_PRESS" # Test uart button with lambda (function pointer) - platform: template name: "UART Lambda Test" on_press: - - uart.write: !lambda |- - std::string cmd = "VALUE=" + str_sprintf("%.0f", id(test_number).state) + "\r\n"; - return std::vector<uint8_t>(cmd.begin(), cmd.end()); + - uart.write: + id: uart_id + data: !lambda |- + std::string cmd = "VALUE=" + str_sprintf("%.0f", id(test_number).state) + "\r\n"; + return std::vector<uint8_t>(cmd.begin(), cmd.end()); event: - platform: uart - uart_id: uart_uart + uart_id: uart_id name: "UART Event" event_types: - "string_event_A": "*A#" diff --git a/tests/components/uart/test.esp8266-ard.yaml b/tests/components/uart/test.esp8266-ard.yaml index c2670b289a..4c9d6fd736 100644 --- a/tests/components/uart/test.esp8266-ard.yaml +++ b/tests/components/uart/test.esp8266-ard.yaml @@ -1,11 +1,15 @@ esphome: on_boot: then: - - uart.write: 'Hello World' - - uart.write: [0x00, 0x20, 0x42] + - uart.write: + id: uart_id + data: 'Hello World' + - uart.write: + id: uart_id + data: [0x00, 0x20, 0x42] uart: - - id: uart_uart + - id: uart_id tx_pin: 4 rx_pin: 5 baud_rate: 9600 @@ -13,15 +17,21 @@ uart: rx_buffer_size: 512 parity: EVEN stop_bits: 2 + - id: uart_debug + tx_pin: 14 + rx_pin: 12 + baud_rate: 115200 + debug: + debug_prefix: "[UART1] " switch: - platform: uart name: "UART Switch Array" - uart_id: uart_uart + uart_id: uart_id data: [0x01, 0x02, 0x03] - platform: uart name: "UART Switch Dual" - uart_id: uart_uart + uart_id: uart_id data: turn_on: [0xA0, 0xA1] turn_off: [0xB0, 0xB1] @@ -29,12 +39,12 @@ switch: button: - platform: uart name: "UART Button" - uart_id: uart_uart + uart_id: uart_id data: [0xFF, 0xEE] event: - platform: uart - uart_id: uart_uart + uart_id: uart_id name: "UART Event" event_types: - "string_event_A": "*A#" diff --git a/tests/components/uart/test.host.yaml b/tests/components/uart/test.host.yaml index 63f0ade084..bc64245c7b 100644 --- a/tests/components/uart/test.host.yaml +++ b/tests/components/uart/test.host.yaml @@ -5,7 +5,7 @@ esphome: - uart.write: [0x00, 0x20, 0x42] uart: - - id: uart_uart + - id: uart_id port: "/dev/ttyS0" baud_rate: 9600 data_bits: 8 diff --git a/tests/components/uart/test.rp2040-ard.yaml b/tests/components/uart/test.rp2040-ard.yaml index 09178f1663..5eb2b533ea 100644 --- a/tests/components/uart/test.rp2040-ard.yaml +++ b/tests/components/uart/test.rp2040-ard.yaml @@ -1,11 +1,15 @@ esphome: on_boot: then: - - uart.write: 'Hello World' - - uart.write: [0x00, 0x20, 0x42] + - uart.write: + id: uart_id + data: 'Hello World' + - uart.write: + id: uart_id + data: [0x00, 0x20, 0x42] uart: - - id: uart_uart + - id: uart_id tx_pin: 4 rx_pin: 5 baud_rate: 9600 @@ -13,3 +17,9 @@ uart: rx_buffer_size: 512 parity: EVEN stop_bits: 2 + - id: uart_debug + tx_pin: 8 + rx_pin: 9 + baud_rate: 115200 + debug: + debug_prefix: "[UART1] " diff --git a/tests/components/usb_uart/common.yaml b/tests/components/usb_uart/common.yaml index 474c3f5c8d..5869b9468b 100644 --- a/tests/components/usb_uart/common.yaml +++ b/tests/components/usb_uart/common.yaml @@ -34,3 +34,11 @@ usb_uart: - id: channel_4_1 debug: true dummy_receiver: true + debug_prefix: "[ESP_JTAG] " + - id: uart_5 + type: cp210x + channels: + - id: channel_5_1 + baud_rate: 9600 + debug: true + debug_prefix: "[CP210X] " From 545395a6f0d2180c648998f0ded5302f01df89cf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 13:16:19 -1000 Subject: [PATCH 1194/2030] [ci] Add RP2350 to PR template test environment (#14599) --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 965b186c31..72013e411e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -25,7 +25,7 @@ - [ ] ESP32 - [ ] ESP32 IDF - [ ] ESP8266 -- [ ] RP2040 +- [ ] RP2040/RP2350 - [ ] BK72xx - [ ] RTL87xx - [ ] LN882x From 888f3d804b9550036c20153218e4286d38c88775 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 13:22:50 -1000 Subject: [PATCH 1195/2030] [ld2420] Add integration tests with mock UART (#14471) --- .../uart_mock/uart_mock.cpp | 8 +- .../fixtures/uart_mock_ld2420.yaml | 187 ++++++++++++ .../fixtures/uart_mock_ld2420_simple.yaml | 141 +++++++++ tests/integration/test_uart_mock_ld2420.py | 273 ++++++++++++++++++ 4 files changed, 605 insertions(+), 4 deletions(-) create mode 100644 tests/integration/fixtures/uart_mock_ld2420.yaml create mode 100644 tests/integration/fixtures/uart_mock_ld2420_simple.yaml create mode 100644 tests/integration/test_uart_mock_ld2420.py diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index affcc8d908..e8c07d632d 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -104,12 +104,12 @@ void MockUartComponent::write_array(const uint8_t *data, size_t len) { } #endif - if (this->scenario_active_) { - this->try_match_response_(); - } + // Responses are always active - they are request-response pairs triggered by + // component TX, not timed injections. No race condition with test subscription. + this->try_match_response_(); // This directly calls a tx_hook (lambda) as an alternative to the simpler match_response mechanism. - if (this->tx_hook_ && this->scenario_active_) { + if (this->tx_hook_) { std::vector<uint8_t> buf(data, data + len); this->tx_hook_(buf); } diff --git a/tests/integration/fixtures/uart_mock_ld2420.yaml b/tests/integration/fixtures/uart_mock_ld2420.yaml new file mode 100644 index 0000000000..5380b81071 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2420.yaml @@ -0,0 +1,187 @@ +esphome: + name: uart-mock-ld2420-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2420's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 115200 + auto_start: false + responses: + # Version-specific response: match the complete firmware version command TX. + # CMD_READ_VERSION (0x0000) TX = FD FC FB FA 02 00 00 00 04 03 02 01 + # Returns "v2.0.0" → get_firmware_int = 200 >= 154 → energy mode + # + # Response layout: + # [0-3] FD FC FB FA = header + # [4-5] 0C 00 = length 12 + # [6] 00 = cmd (CMD_READ_VERSION) + # [7] 01 = status (ACK) + # [8-9] 00 00 = error = 0 + # [10] 06 = ver_len = 6 + # [11] 00 = padding + # [12-17] "v2.0.0" = version string + # [18-21] 04 03 02 01 = footer + - expect_tx: + [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0x00, 0x00, 0x04, 0x03, 0x02, 0x01] + inject_rx: + [ + 0xFD, 0xFC, 0xFB, 0xFA, + 0x0C, 0x00, + 0x00, 0x01, + 0x00, 0x00, + 0x06, 0x00, + 0x76, 0x32, 0x2E, 0x30, 0x2E, 0x30, + 0x04, 0x03, 0x02, 0x01, + ] + + # Catch-all response: match any command footer (04 03 02 01). + # Returns a generic ACK with cmd=0xFF (CMD_ENABLE_CONF case in switch). + # All commands get unblocked via cmd_reply_.ack = true. + # Data fields stay zeroed (min_gate=0, max_gate=0, timeout=0, thresholds=0). + # + # Response layout: + # [0-3] FD FC FB FA = header + # [4-5] 04 00 = length 4 + # [6] FF = cmd (handled as CMD_ENABLE_CONF) + # [7] 01 = status (ACK) + # [8-9] 00 00 = error = 0 + # [10-13] 04 03 02 01 = footer + - expect_tx: [0x04, 0x03, 0x02, 0x01] + inject_rx: + [ + 0xFD, 0xFC, 0xFB, 0xFA, + 0x04, 0x00, + 0xFF, 0x01, + 0x00, 0x00, + 0x04, 0x03, 0x02, 0x01, + ] + + injections: + # Phase 1 (t=100ms): Valid LD2420 energy mode data frame - happy path + # Buffer is clean (buffer_pos_=0). This frame should parse correctly. + # Presence: 1 (target detected), Distance: 100cm, Gate energies: all 0 + # + # Energy frame layout (45 bytes): + # [0-3] F4 F3 F2 F1 = energy frame header + # [4-5] 23 00 = length 35 (1+2+32) + # [6] 01 = presence (1 = target) + # [7-8] 64 00 = distance 100 (uint16_t LE) + # [9-40] 00 00 x16 = 16 gate energies (uint16_t LE each) + # [41-44] F8 F7 F6 F5 = energy frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, + 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=300ms): Garbage bytes + # LD2420's readline_ does NOT check frame headers at position 0 (unlike LD2412), + # so these bytes accumulate in the buffer. buffer_pos_ goes from 0 to 7. + - delay: 200ms + inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22] + + # Phase 3 (t=400ms): Truncated energy frame WITH footer (13 bytes) + # This tests PR #14458 bug #3: missing length validation in handle_energy_mode_. + # The 7 garbage bytes from Phase 2 are still in the buffer (buffer_pos_=7). + # These 13 bytes are appended at positions 7-19 (buffer_pos_=20). + # Energy footer at positions 16-19 triggers handle_energy_mode_(buffer, 20). + # + # Pre-fix: handle_energy_mode_ reads 32 bytes of gate energy from buffer[9:40], + # which is past the 20 actual bytes. Reads uninitialized data. + # No "Energy frame too short" warning exists. + # Post-fix: len=20 < 41 → logs "Energy frame too short: 20 bytes", returns early. + # + # Frame: header + length + presence + distance + footer (no gate data) + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, + 0x64, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 4 (t=600ms): Overflow - inject 50 bytes of 0xFF (MAX_LINE_LENGTH=50) + # After Phase 3, buffer_pos_=0 (reset after energy footer detection). + # 49 bytes fill positions 0-48 (buffer_pos_=49), 50th byte triggers overflow. + # Logs "Max command length exceeded; ignoring", buffer_pos_=0. + - delay: 200ms + inject_rx: + [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ] + + # Phase 5 (t=1500ms): Valid frame after overflow - recovery test + # Buffer was reset by overflow. This valid frame should parse correctly. + # Presence: 1 (target), Distance: 50cm + # Delay=900ms ensures >1000ms gap from Phase 1 for REFRESH_RATE_MS throttle. + - delay: 900ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x23, 0x00, + 0x01, + 0x32, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +button: + - platform: template + name: "Start Scenario" + on_press: + - lambda: 'id(mock_uart).start_scenario();' + +ld2420: + id: ld2420_dev + uart_id: mock_uart + +sensor: + - platform: ld2420 + ld2420_id: ld2420_dev + moving_distance: + name: "Moving Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +binary_sensor: + - platform: ld2420 + ld2420_id: ld2420_dev + has_target: + name: "Has Target" + filters: + - settle: 50ms diff --git a/tests/integration/fixtures/uart_mock_ld2420_simple.yaml b/tests/integration/fixtures/uart_mock_ld2420_simple.yaml new file mode 100644 index 0000000000..2ceca5d35d --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2420_simple.yaml @@ -0,0 +1,141 @@ +esphome: + name: uart-mock-ld2420-simple-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2420's DEPENDENCIES = ["uart"] +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 115200 + auto_start: false + responses: + # Catch-all response only (no version-specific response). + # Without a version response, firmware_ver_ stays at default "v0.0.0". + # get_firmware_int("v0.0.0") = 0 < 154 → simple mode (CMD_SYSTEM_MODE_SIMPLE). + - expect_tx: [0x04, 0x03, 0x02, 0x01] + inject_rx: + [ + 0xFD, 0xFC, 0xFB, 0xFA, + 0x04, 0x00, + 0xFF, 0x01, + 0x00, 0x00, + 0x04, 0x03, 0x02, 0x01, + ] + + injections: + # Phase 1 (t=100ms): Valid simple mode text frame - happy path + # "ON Range 0100\r\n" → presence=true, distance=100 + # Simple mode frames end with \r\n (0x0D 0x0A), triggering handle_simple_mode_. + - delay: 100ms + inject_rx: + [ + 0x4F, 0x4E, 0x20, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x20, + 0x30, 0x31, 0x30, 0x30, + 0x0D, 0x0A, + ] + + # Phase 2 (t=300ms): Garbage bytes + # LD2420's readline_ stores all bytes regardless of header. buffer_pos_ = 7. + - delay: 200ms + inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22] + + # Phase 3 (t=500ms): Overflow - inject 50 bytes of 0xFF (MAX_LINE_LENGTH=50) + # buffer_pos_ starts at 7 (from Phase 2 garbage). + # Positions 7-48 fill (42 bytes), byte 43 triggers overflow (buffer_pos_=49). + # After overflow: buffer_pos_=0, remaining 7 bytes fill positions 0-6. + # Final buffer_pos_ = 7. + - delay: 200ms + inject_rx: + [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ] + + # Phase 4 (t=1400ms): Recovery after overflow + # buffer_pos_ = 7 (from overflow remainder). These 15 bytes fill positions 7-21. + # At position 21 (0x0A), \r\n detected → handle_simple_mode_(buffer, 22). + # Parser skips 0xFF bytes at positions 0-6, finds "ON" at positions 7-8, + # parses digits "0050" → distance=50. + # Delay=900ms ensures >1000ms gap from Phase 1 for REFRESH_RATE_MS throttle. + - delay: 900ms + inject_rx: + [ + 0x4F, 0x4E, 0x20, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x20, + 0x30, 0x30, 0x35, 0x30, + 0x0D, 0x0A, + ] + + # Phase 5 (t=2500ms): 16-digit distance - tests PR #14458 bug #1 + # "ON Range 0000000000000000\r\n" has 16 digit characters. + # handle_simple_mode_ outbuf is 16 bytes, can hold 15 digits (index 0-14). + # + # Pre-fix: At the 16th digit, index=15, (index < bufsize-1) is false. + # The digit branch doesn't increment pos. The else branch is skipped. + # pos stays at the 16th digit FOREVER → INFINITE LOOP. + # The binary hangs, no more state updates, test times out. + # Post-fix: pos always increments (moved outside digit branch). + # 16th digit skipped, loop continues to \r\n. distance=0. + - delay: 1100ms + inject_rx: + [ + 0x4F, 0x4E, 0x20, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x20, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x0D, 0x0A, + ] + + # Phase 6 (t=3700ms): Post-bug-trigger recovery + # If Phase 5 didn't hang, this frame should parse correctly. + # "ON Range 0025\r\n" → distance=25 + # Delay=1200ms ensures >1000ms gap from Phase 5 for throttle. + - delay: 1200ms + inject_rx: + [ + 0x4F, 0x4E, 0x20, 0x52, 0x61, 0x6E, 0x67, 0x65, 0x20, + 0x30, 0x30, 0x32, 0x35, + 0x0D, 0x0A, + ] + +button: + - platform: template + name: "Start Scenario" + on_press: + - lambda: 'id(mock_uart).start_scenario();' + +ld2420: + id: ld2420_dev + uart_id: mock_uart + +sensor: + - platform: ld2420 + ld2420_id: ld2420_dev + moving_distance: + name: "Moving Distance" + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +binary_sensor: + - platform: ld2420 + ld2420_id: ld2420_dev + has_target: + name: "Has Target" + filters: + - settle: 50ms diff --git a/tests/integration/test_uart_mock_ld2420.py b/tests/integration/test_uart_mock_ld2420.py new file mode 100644 index 0000000000..ae28da4d3e --- /dev/null +++ b/tests/integration/test_uart_mock_ld2420.py @@ -0,0 +1,273 @@ +"""Integration test for LD2420 component with mock UART. + +Tests: +test_uart_mock_ld2420 (energy mode): + 1. Happy path - valid energy frame publishes correct sensor values + 2. Garbage resilience - random bytes don't crash the component + 3. Truncated energy frame - triggers "Energy frame too short" warning (PR #14458 bug #3) + 4. Buffer overflow recovery - overflow resets the parser + 5. Post-overflow parsing - next valid frame after overflow is parsed correctly + 6. TX logging - verifies LD2420 sends expected setup commands + +test_uart_mock_ld2420_simple (simple mode): + 1. Happy path - valid simple mode text frame publishes correct values + 2. Garbage resilience + 3. Buffer overflow recovery + 4. 16-digit distance triggers infinite loop pre-fix (PR #14458 bug #1) + 5. Post-bug-trigger recovery proves the parser survived +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path + +from aioesphomeapi import ButtonInfo +import pytest + +from .state_utils import InitialStateHelper, SensorStateCollector, find_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_uart_mock_ld2420( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2420 energy mode: happy path, truncated frame, overflow, and recovery.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track overflow warning in logs + overflow_seen = loop.create_future() + + # Track "Energy frame too short" warning (PR #14458 bug #3 fix) + # This message ONLY exists after the fix. Pre-fix, handle_energy_mode_ + # silently reads past the buffer without any warning. + truncated_frame_warning_seen = loop.create_future() + + # Track TX data logged by the mock for assertions + tx_log_lines: list[str] = [] + + def line_callback(line: str) -> None: + if "Max command length exceeded" in line and not overflow_seen.done(): + overflow_seen.set_result(True) + if "Energy frame too short" in line and not truncated_frame_warning_seen.done(): + truncated_frame_warning_seen.set_result(True) + # Capture all TX log lines from uart_mock + if "uart_mock" in line and "TX " in line: + tx_log_lines.append(line) + + collector = SensorStateCollector( + sensor_names=["moving_distance"], + binary_sensor_names=["has_target"], + ) + + # Signal when we see recovery frame values + recovery_received = collector.add_waiter( + lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + ) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + collector.build_key_mapping(entities) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) + + # Phase 1 values: moving=100, has_target=true + assert collector.sensor_states["moving_distance"][0] == pytest.approx(100.0) + assert collector.binary_states["has_target"][0] is True + + # Wait for the recovery frame (Phase 5) to be parsed + # This proves the component survived garbage + truncated + overflow + try: + await asyncio.wait_for(recovery_received, timeout=5.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received:\n" + f" sensor_states: {collector.sensor_states}" + ) + + # Verify overflow warning was logged + assert overflow_seen.done(), ( + "Expected 'Max command length exceeded' warning in logs" + ) + + # Verify truncated frame warning was logged (PR #14458 bug #3) + # This assertion FAILS before PR #14458 because the length check + # and warning message did not exist. + assert truncated_frame_warning_seen.done(), ( + "Expected 'Energy frame too short' warning in logs. " + "This indicates PR #14458 fix for handle_energy_mode_ length " + "validation is missing." + ) + + # Verify LD2420 sent setup commands (TX logging) + assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" + tx_data = " ".join(tx_log_lines) + # Verify command frame header appears (FD:FC:FB:FA) + assert "FD.FC.FB.FA" in tx_data or "FD:FC:FB:FA" in tx_data, ( + "Expected LD2420 command frame header FD:FC:FB:FA in TX log" + ) + # Verify command frame footer appears (04:03:02:01) + assert "04.03.02.01" in tx_data or "04:03:02:01" in tx_data, ( + "Expected LD2420 command frame footer 04:03:02:01 in TX log" + ) + + # Recovery frame values (Phase 5, after overflow) + recovery_values = [ + v + for v in collector.sensor_states["moving_distance"] + if v == pytest.approx(50.0) + ] + assert len(recovery_values) >= 1, ( + f"Expected moving_distance=50 in recovery, got: {collector.sensor_states['moving_distance']}" + ) + + +@pytest.mark.asyncio +async def test_uart_mock_ld2420_simple( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2420 simple mode: happy path, overflow, and 16-digit bug trigger.""" + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track overflow warning in logs + overflow_seen = loop.create_future() + + def line_callback(line: str) -> None: + if "Max command length exceeded" in line and not overflow_seen.done(): + overflow_seen.set_result(True) + + collector = SensorStateCollector( + sensor_names=["moving_distance"], + binary_sensor_names=["has_target"], + ) + + # Signal for recovery frames + recovery_received = collector.add_waiter( + lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + ) + post_bug_received = collector.add_waiter( + lambda: pytest.approx(25.0) in collector.sensor_states["moving_distance"] + ) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + collector.build_key_mapping(entities) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) + + # Phase 1: simple mode "ON Range 0100\r\n" → distance=100, presence=true + assert collector.sensor_states["moving_distance"][0] == pytest.approx(100.0) + assert collector.binary_states["has_target"][0] is True + + # Wait for Phase 4 recovery (distance=50) after overflow + try: + await asyncio.wait_for(recovery_received, timeout=5.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received:\n" + f" moving_distance: {collector.sensor_states['moving_distance']}" + ) + + # Verify overflow warning was logged + assert overflow_seen.done(), ( + "Expected 'Max command length exceeded' warning in logs" + ) + + # Wait for Phase 6: distance=25 (post-16-digit-bug recovery) + # This assertion FAILS before PR #14458 because the 16-digit frame + # in Phase 5 causes an infinite loop in handle_simple_mode_ pre-fix. + # The binary hangs, Phase 6 never fires, and this wait times out. + try: + await asyncio.wait_for(post_bug_received, timeout=8.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for post-bug recovery (distance=25). " + f"This likely means Phase 5 (16-digit frame) caused an infinite " + f"loop in handle_simple_mode_, indicating PR #14458 bug #1 fix " + f"is missing.\n" + f" moving_distance values: {collector.sensor_states['moving_distance']}" + ) + + # Verify post-bug value + post_bug_values = [ + v + for v in collector.sensor_states["moving_distance"] + if v == pytest.approx(25.0) + ] + assert len(post_bug_values) >= 1, ( + f"Expected moving_distance=25 after 16-digit test, " + f"got: {collector.sensor_states['moving_distance']}" + ) From ea7cfffddaf60c5da30bf9dfa976fcf044477c06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:40:13 +0000 Subject: [PATCH 1196/2030] Bump aioesphomeapi from 44.3.1 to 44.4.0 (#14609) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8e875eba62..a1300a67f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.3.1 +aioesphomeapi==44.4.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 66919ef969574f8e6553d2146089c41ee9cecd27 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 18:33:54 -1000 Subject: [PATCH 1197/2030] [i2s_audio] Include legacy driver IDF component when use_legacy is set (#14613) --- esphome/components/i2s_audio/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 1cd2e97a5e..65b09b93f6 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -281,6 +281,8 @@ async def to_code(config): if use_legacy(): cg.add_define("USE_I2S_LEGACY") + # Legacy I2S API lives in the "driver" shim component (driver/i2s.h) + include_builtin_idf_component("driver") # Helps avoid callbacks being skipped due to processor load add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True) From d55fe9a34b50400347a7d57f6679dbbb514ea8ce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 18:34:35 -1000 Subject: [PATCH 1198/2030] [api] Fix value-initialization of DeviceInfoResponse (#14615) Co-authored-by: Keith Burzinski <kbx81x@gmail.com> --- esphome/components/api/api_connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index bd3de02895..b9b33ddcc2 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1571,7 +1571,7 @@ bool APIConnection::send_ping_response_() { } bool APIConnection::send_device_info_response_() { - DeviceInfoResponse resp{}; + DeviceInfoResponse resp; resp.name = StringRef(App.get_name()); resp.friendly_name = StringRef(App.get_friendly_name()); #ifdef USE_AREAS From 9fea8fe01b4c976caced70881cb986729768c305 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:50:36 -0500 Subject: [PATCH 1199/2030] [vbus][rf_bridge][sensirion_common] Add buffer size guards (#14597) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/rf_bridge/rf_bridge.cpp | 3 +++ esphome/components/rf_bridge/rf_bridge.h | 1 + esphome/components/sensirion_common/i2c_sensirion.cpp | 2 +- esphome/components/vbus/vbus.cpp | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/rf_bridge/rf_bridge.cpp b/esphome/components/rf_bridge/rf_bridge.cpp index 700e2ba162..5ca629c12b 100644 --- a/esphome/components/rf_bridge/rf_bridge.cpp +++ b/esphome/components/rf_bridge/rf_bridge.cpp @@ -145,6 +145,9 @@ void RFBridgeComponent::loop() { } avail -= to_read; for (size_t i = 0; i < to_read; i++) { + if (this->rx_buffer_.size() > MAX_RX_BUFFER_SIZE) { + this->rx_buffer_.clear(); + } if (this->parse_bridge_byte_(buf[i])) { ESP_LOGVV(TAG, "Parsed: 0x%02X", buf[i]); this->last_bridge_byte_ = now; diff --git a/esphome/components/rf_bridge/rf_bridge.h b/esphome/components/rf_bridge/rf_bridge.h index d2f75c819d..c93b636c38 100644 --- a/esphome/components/rf_bridge/rf_bridge.h +++ b/esphome/components/rf_bridge/rf_bridge.h @@ -30,6 +30,7 @@ static const uint8_t RF_CODE_RFIN_BUCKET = 0xB1; static const uint8_t RF_CODE_BEEP = 0xC0; static const uint8_t RF_CODE_STOP = 0x55; static const uint8_t RF_DEBOUNCE = 200; +static const size_t MAX_RX_BUFFER_SIZE = 512; struct RFBridgeData { uint16_t sync; diff --git a/esphome/components/sensirion_common/i2c_sensirion.cpp b/esphome/components/sensirion_common/i2c_sensirion.cpp index 26702c148c..0279e08b9f 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.cpp +++ b/esphome/components/sensirion_common/i2c_sensirion.cpp @@ -12,7 +12,7 @@ static const char *const TAG = "sensirion_i2c"; static const size_t BUFFER_STACK_SIZE = 16; bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) { - const uint8_t num_bytes = len * 3; + const size_t num_bytes = len * 3; uint8_t buf[num_bytes]; this->last_error_ = this->read(buf, num_bytes); diff --git a/esphome/components/vbus/vbus.cpp b/esphome/components/vbus/vbus.cpp index 8616da010d..c6786ee31e 100644 --- a/esphome/components/vbus/vbus.cpp +++ b/esphome/components/vbus/vbus.cpp @@ -87,6 +87,9 @@ void VBus::loop() { this->state_ = 0; ESP_LOGD(TAG, "P1 empty message"); } + } else if (this->buffer_.size() > 15) { + ESP_LOGW(TAG, "Unknown protocol 0x%02x, discarding", this->protocol_); + this->state_ = 0; } continue; } From be6c3c52ac89534f00e54dfa26974402d813a4bf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 18:59:13 -1000 Subject: [PATCH 1200/2030] [api] Add force proto field option to skip zero checks on hot path (#14610) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/api.proto | 6 ++-- esphome/components/api/api_options.proto | 6 ++++ esphome/components/api/api_pb2.cpp | 14 ++++----- script/api_protobuf/api_protobuf.py | 38 ++++++++++++++++++++++-- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 618fd1b83c..257a7aaf82 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1604,11 +1604,11 @@ message BluetoothLEAdvertisementResponse { } message BluetoothLERawAdvertisement { - uint64 address = 1; - sint32 rssi = 2; + uint64 address = 1 [(force) = true]; + sint32 rssi = 2 [(force) = true]; uint32 address_type = 3; - bytes data = 4 [(fixed_array_size) = 62]; + bytes data = 4 [(fixed_array_size) = 62, (force) = true]; } message BluetoothLERawAdvertisementsResponse { diff --git a/esphome/components/api/api_options.proto b/esphome/components/api/api_options.proto index a863f2c7a8..02600f0977 100644 --- a/esphome/components/api/api_options.proto +++ b/esphome/components/api/api_options.proto @@ -90,4 +90,10 @@ extend google.protobuf.FieldOptions { // - uint16_t <field>_length_{0}; // - uint16_t <field>_count_{0}; optional bool packed_buffer = 50015 [default=false]; + + // force: Always encode this field, even when its value equals the proto3 default. + // Skips the zero/empty check in calculate_size() and encode(), using the _force + // variant of the calc_ method. Use on fields that are almost always non-default + // to eliminate dead branches on hot paths. + optional bool force = 50016 [default=false]; } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 1944aac6e8..38ebfb9464 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -139,7 +139,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { #endif #ifdef USE_SERIAL_PROXY for (const auto &it : this->serial_proxies) { - buffer.encode_message(25, it); + buffer.encode_sub_message(25, it); } #endif } @@ -2249,17 +2249,17 @@ bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, return true; } void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_sint32(2, this->rssi); + buffer.encode_uint64(1, this->address, true); + buffer.encode_sint32(2, this->rssi, true); buffer.encode_uint32(3, this->address_type); - buffer.encode_bytes(4, this->data, this->data_len); + buffer.encode_bytes(4, this->data, this->data_len, true); } uint32_t BluetoothLERawAdvertisement::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_uint64(1, this->address); - size += ProtoSize::calc_sint32(1, this->rssi); + size += ProtoSize::calc_uint64_force(1, this->address); + size += ProtoSize::calc_sint32_force(1, this->rssi); size += ProtoSize::calc_uint32(1, this->address_type); - size += ProtoSize::calc_length(1, this->data_len); + size += ProtoSize::calc_length_force(1, this->data_len); return size; } void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 7ae7063a41..206f8f558b 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -151,6 +151,11 @@ class TypeInfo(ABC): """Check if the field is repeated.""" return self._field.label == FieldDescriptorProto.LABEL_REPEATED + @property + def force(self) -> bool: + """Check if this field should always be encoded (skip zero/empty check).""" + return get_field_opt(self._field, pb.force, False) + @property def wire_type(self) -> WireType: """Get the wire type for the field.""" @@ -218,6 +223,8 @@ class TypeInfo(ABC): @property def encode_content(self) -> str: + if self.force: + return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);" return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" encode_func = None @@ -413,6 +420,8 @@ class DoubleType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -437,6 +446,8 @@ class FloatType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_float({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -521,6 +532,8 @@ class Fixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -545,6 +558,8 @@ class Fixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_fixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -607,6 +622,8 @@ class StringType(TypeInfo): @property def encode_content(self) -> str: # Use the StringRef + if self.force: + return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_, true);" return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);" def dump(self, name): @@ -694,7 +711,7 @@ class MessageType(TypeInfo): @property def encode_content(self) -> str: - # Singular message fields skip encoding when empty + # encode_sub_message always encodes (uses backpatch), no force needed return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" @property @@ -771,6 +788,8 @@ class BytesType(TypeInfo): @property def encode_content(self) -> str: + if self.force: + return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" def dump(self, name: str) -> str: @@ -876,6 +895,8 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): @property def encode_content(self) -> str: + if self.force: + return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" @property @@ -923,6 +944,10 @@ class PointerToStringBufferType(PointerToBufferTypeBase): @property def encode_content(self) -> str: + if self.force: + return ( + f"buffer.encode_string({self.number}, this->{self.field_name}, true);" + ) return f"buffer.encode_string({self.number}, this->{self.field_name});" @property @@ -1086,6 +1111,8 @@ class FixedArrayBytesType(TypeInfo): @property def encode_content(self) -> str: + if self.force: + return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" def dump(self, name: str) -> str: @@ -1159,6 +1186,8 @@ class EnumType(TypeInfo): @property def encode_content(self) -> str: + if self.force: + return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}), true);" return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}));" def dump(self, name: str) -> str: @@ -1192,6 +1221,8 @@ class SFixed32Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_sfixed32({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -1216,6 +1247,8 @@ class SFixed64Type(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() + if force: + return f"size += {field_id_size + self.get_fixed_size_bytes()};" return f"size += ProtoSize::calc_sfixed64({field_id_size}, {name});" def get_fixed_size_bytes(self) -> int: @@ -2134,7 +2167,8 @@ def build_message_type( encode.extend(wrap_with_ifdef(ti.encode_content, field_ifdef)) size_calc.extend( wrap_with_ifdef( - ti.get_size_calculation(f"this->{ti.field_name}"), field_ifdef + ti.get_size_calculation(f"this->{ti.field_name}", ti.force), + field_ifdef, ) ) From 5e842a8b207230be2fd8db09baf5098f62767a21 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Sat, 7 Mar 2026 23:23:13 -0600 Subject: [PATCH 1201/2030] [uart] Return `flush` result, expose timeout via config (#14608) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/ble_nus/ble_nus.cpp | 5 +++-- esphome/components/ble_nus/ble_nus.h | 2 +- esphome/components/uart/__init__.py | 6 ++++++ esphome/components/uart/uart.h | 2 +- esphome/components/uart/uart_component.h | 16 +++++++++++++++- .../components/uart/uart_component_esp8266.cpp | 3 ++- esphome/components/uart/uart_component_esp8266.h | 2 +- .../components/uart/uart_component_esp_idf.cpp | 13 +++++++++++-- esphome/components/uart/uart_component_esp_idf.h | 5 ++++- esphome/components/uart/uart_component_host.cpp | 5 +++-- esphome/components/uart/uart_component_host.h | 2 +- .../components/uart/uart_component_libretiny.cpp | 3 ++- .../components/uart/uart_component_libretiny.h | 2 +- .../components/uart/uart_component_rp2040.cpp | 3 ++- esphome/components/uart/uart_component_rp2040.h | 2 +- esphome/components/usb_cdc_acm/usb_cdc_acm.h | 2 +- .../components/usb_cdc_acm/usb_cdc_acm_esp32.cpp | 11 ++++++++--- esphome/components/usb_uart/usb_uart.cpp | 5 ++++- esphome/components/usb_uart/usb_uart.h | 2 +- esphome/components/weikai/weikai.cpp | 5 +++-- esphome/components/weikai/weikai.h | 2 +- tests/components/ld2450/common.h | 2 +- tests/components/uart/common.h | 2 +- .../external_components/uart_mock/uart_mock.cpp | 3 ++- .../external_components/uart_mock/uart_mock.h | 2 +- 25 files changed, 77 insertions(+), 30 deletions(-) diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index d1710100a0..e38dc99802 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -100,16 +100,17 @@ size_t BLENUS::available() { #endif } -void BLENUS::flush() { +uart::FlushResult BLENUS::flush() { constexpr uint32_t timeout_5sec = 5000; uint32_t start = millis(); while (atomic_get(&this->tx_status_) != TX_DISABLED && !ring_buf_is_empty(&global_ble_tx_ring_buf)) { if (millis() - start > timeout_5sec) { ESP_LOGW(TAG, "Flush timeout"); - return; + return uart::FlushResult::TIMEOUT; } delay(1); } + return uart::FlushResult::SUCCESS; } void BLENUS::connected(bt_conn *conn, uint8_t err) { diff --git a/esphome/components/ble_nus/ble_nus.h b/esphome/components/ble_nus/ble_nus.h index 67e9ae9f97..b482c240e5 100644 --- a/esphome/components/ble_nus/ble_nus.h +++ b/esphome/components/ble_nus/ble_nus.h @@ -26,7 +26,7 @@ class BLENUS : public uart::UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + uart::FlushResult flush() override; void check_logger_conflict() override {} void set_expose_log(bool expose_log) { this->expose_log_ = expose_log; } #ifdef USE_LOGGER diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 1b976b73a9..2cb6eac050 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -183,6 +183,7 @@ UART_PARITY_OPTIONS = { "ODD": UARTParityOptions.UART_CONFIG_PARITY_ODD, } +CONF_FLUSH_TIMEOUT = "flush_timeout" CONF_RX_FULL_THRESHOLD = "rx_full_threshold" CONF_RX_TIMEOUT = "rx_timeout" @@ -266,6 +267,9 @@ CONFIG_SCHEMA = cv.All( cv.SplitDefault(CONF_RX_TIMEOUT, esp32=2): cv.All( cv.only_on_esp32, cv.validate_bytes, cv.int_range(min=0, max=92) ), + cv.Optional(CONF_FLUSH_TIMEOUT): cv.All( + cv.only_on_esp32, cv.positive_time_period_milliseconds + ), cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), cv.Optional(CONF_PARITY, default="NONE"): cv.enum( @@ -345,6 +349,8 @@ async def to_code(config): ) cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD])) cg.add(var.set_rx_timeout(config[CONF_RX_TIMEOUT])) + if CONF_FLUSH_TIMEOUT in config: + cg.add(var.set_flush_timeout(config[CONF_FLUSH_TIMEOUT])) cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) cg.add(var.set_data_bits(config[CONF_DATA_BITS])) cg.add(var.set_parity(config[CONF_PARITY])) diff --git a/esphome/components/uart/uart.h b/esphome/components/uart/uart.h index bb91e5cd7c..2c4fb34c9a 100644 --- a/esphome/components/uart/uart.h +++ b/esphome/components/uart/uart.h @@ -45,7 +45,7 @@ class UARTDevice { size_t available() { return this->parent_->available(); } - void flush() { this->parent_->flush(); } + FlushResult flush() { return this->parent_->flush(); } // Compat APIs int read() { diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 078ce64b30..3d7e71b89f 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -29,6 +29,14 @@ enum UARTDirection { const LogString *parity_to_str(UARTParityOptions parity); +/// Result of a flush() call. +enum class FlushResult { + SUCCESS, ///< Confirmed: all bytes left the TX FIFO. + TIMEOUT, ///< Confirmed: timed out before TX completed. + FAILED, ///< Confirmed: driver or hardware error. + ASSUMED_SUCCESS, ///< Platform cannot report result; success is assumed. +}; + class UARTComponent { public: // Writes an array of bytes to the UART bus. @@ -72,7 +80,13 @@ class UARTComponent { virtual size_t available() = 0; // Pure virtual method to block until all bytes have been written to the UART bus. - virtual void flush() = 0; + // @return FlushResult indicating whether the flush was confirmed, timed out, failed, or assumed successful. + virtual FlushResult flush() = 0; + + // Sets the maximum time to wait for TX to drain during flush(). + // Only meaningful on ESP32 (IDF). Other platforms ignore this value. + // @param flush_timeout_ms Timeout in milliseconds; 0 means wait indefinitely. + virtual void set_flush_timeout(uint32_t flush_timeout_ms) {} // Sets the TX (transmit) pin for the UART bus. // @param tx_pin Pointer to the internal GPIO pin used for transmission. diff --git a/esphome/components/uart/uart_component_esp8266.cpp b/esphome/components/uart/uart_component_esp8266.cpp index 3ebf381c84..91218c4300 100644 --- a/esphome/components/uart/uart_component_esp8266.cpp +++ b/esphome/components/uart/uart_component_esp8266.cpp @@ -213,13 +213,14 @@ size_t ESP8266UartComponent::available() { return this->sw_serial_->available(); } } -void ESP8266UartComponent::flush() { +FlushResult ESP8266UartComponent::flush() { ESP_LOGVV(TAG, " Flushing"); if (this->hw_serial_ != nullptr) { this->hw_serial_->flush(); } else { this->sw_serial_->flush(); } + return FlushResult::ASSUMED_SUCCESS; } void ESP8266SoftwareSerial::setup(InternalGPIOPin *tx_pin, InternalGPIOPin *rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t data_bits, UARTParityOptions parity, diff --git a/esphome/components/uart/uart_component_esp8266.h b/esphome/components/uart/uart_component_esp8266.h index e84cbe386d..ca90dc5964 100644 --- a/esphome/components/uart/uart_component_esp8266.h +++ b/esphome/components/uart/uart_component_esp8266.h @@ -58,7 +58,7 @@ class ESP8266UartComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + FlushResult flush() override; uint32_t get_config(); diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 544404448b..47ddf1a38d 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -230,6 +230,9 @@ void IDFUARTComponent::dump_config() { " RX Timeout: %u", this->rx_buffer_size_, this->rx_full_threshold_, this->rx_timeout_); } + if (this->flush_timeout_ms_ > 0) { + ESP_LOGCONFIG(TAG, " Flush Timeout: %" PRIu32 " ms", this->flush_timeout_ms_); + } ESP_LOGCONFIG(TAG, " Baud Rate: %" PRIu32 " baud\n" " Data Bits: %u\n" @@ -332,9 +335,15 @@ size_t IDFUARTComponent::available() { return available; } -void IDFUARTComponent::flush() { +FlushResult IDFUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); - uart_wait_tx_done(this->uart_num_, portMAX_DELAY); + TickType_t ticks = this->flush_timeout_ms_ == 0 ? portMAX_DELAY : pdMS_TO_TICKS(this->flush_timeout_ms_); + esp_err_t err = uart_wait_tx_done(this->uart_num_, ticks); + if (err == ESP_OK) + return FlushResult::SUCCESS; + if (err == ESP_ERR_TIMEOUT) + return FlushResult::TIMEOUT; + return FlushResult::FAILED; } void IDFUARTComponent::check_logger_conflict() {} diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index 631bf54cd5..9fa2013cfd 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -31,7 +31,9 @@ class IDFUARTComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + FlushResult flush() override; + + void set_flush_timeout(uint32_t flush_timeout_ms) override { this->flush_timeout_ms_ = flush_timeout_ms; } uint8_t get_hw_serial_number() { return this->uart_num_; } @@ -57,6 +59,7 @@ class IDFUARTComponent : public UARTComponent, public Component { bool has_peek_{false}; uint8_t peek_byte_; + uint32_t flush_timeout_ms_{0}; ///< 0 means wait indefinitely (portMAX_DELAY). #ifdef USE_UART_WAKE_LOOP_ON_RX // ISR callback for UART RX data notification — wakes the main loop directly. diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 9dce25c500..66026f3ccd 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -274,12 +274,13 @@ size_t HostUartComponent::available() { return result; }; -void HostUartComponent::flush() { +FlushResult HostUartComponent::flush() { if (this->file_descriptor_ == -1) { - return; + return FlushResult::ASSUMED_SUCCESS; } tcflush(this->file_descriptor_, TCIOFLUSH); ESP_LOGV(TAG, " Flushing"); + return FlushResult::ASSUMED_SUCCESS; } void HostUartComponent::update_error_(const std::string &error) { diff --git a/esphome/components/uart/uart_component_host.h b/esphome/components/uart/uart_component_host.h index 89b951093b..c22efdcb92 100644 --- a/esphome/components/uart/uart_component_host.h +++ b/esphome/components/uart/uart_component_host.h @@ -18,7 +18,7 @@ class HostUartComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + FlushResult flush() override; void set_name(std::string port_name) { port_name_ = port_name; }; protected: diff --git a/esphome/components/uart/uart_component_libretiny.cpp b/esphome/components/uart/uart_component_libretiny.cpp index 83d2acb332..6a550f296a 100644 --- a/esphome/components/uart/uart_component_libretiny.cpp +++ b/esphome/components/uart/uart_component_libretiny.cpp @@ -170,9 +170,10 @@ bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) { } size_t LibreTinyUARTComponent::available() { return this->serial_->available(); } -void LibreTinyUARTComponent::flush() { +FlushResult LibreTinyUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); + return FlushResult::ASSUMED_SUCCESS; } void LibreTinyUARTComponent::check_logger_conflict() { diff --git a/esphome/components/uart/uart_component_libretiny.h b/esphome/components/uart/uart_component_libretiny.h index 31f082d31e..77df808067 100644 --- a/esphome/components/uart/uart_component_libretiny.h +++ b/esphome/components/uart/uart_component_libretiny.h @@ -22,7 +22,7 @@ class LibreTinyUARTComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + FlushResult flush() override; uint16_t get_config(); diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index faf8f4d90f..858f1a02dd 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -187,9 +187,10 @@ bool RP2040UartComponent::read_array(uint8_t *data, size_t len) { return true; } size_t RP2040UartComponent::available() { return this->serial_->available(); } -void RP2040UartComponent::flush() { +FlushResult RP2040UartComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); + return FlushResult::ASSUMED_SUCCESS; } } // namespace esphome::uart diff --git a/esphome/components/uart/uart_component_rp2040.h b/esphome/components/uart/uart_component_rp2040.h index 4ca58e8dc6..891212ca74 100644 --- a/esphome/components/uart/uart_component_rp2040.h +++ b/esphome/components/uart/uart_component_rp2040.h @@ -25,7 +25,7 @@ class RP2040UartComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + FlushResult flush() override; uint16_t get_config(); diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index ddcc65232d..624f41cf8c 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -82,7 +82,7 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + uart::FlushResult flush() override; protected: void check_logger_conflict() override; diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index 44de986f9a..1a36ef9f31 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -326,10 +326,10 @@ size_t USBCDCACMInstance::available() { return waiting + (this->has_peek_ ? 1 : 0); } -void USBCDCACMInstance::flush() { +uart::FlushResult USBCDCACMInstance::flush() { // Wait for TX ring buffer to be empty if (this->usb_tx_ringbuf_ == nullptr) { - return; + return uart::FlushResult::ASSUMED_SUCCESS; } UBaseType_t waiting = 1; @@ -341,7 +341,12 @@ void USBCDCACMInstance::flush() { } // Also wait for USB to finish transmitting - tinyusb_cdcacm_write_flush(static_cast<tinyusb_cdcacm_itf_t>(this->itf_), pdMS_TO_TICKS(100)); + esp_err_t err = tinyusb_cdcacm_write_flush(static_cast<tinyusb_cdcacm_itf_t>(this->itf_), pdMS_TO_TICKS(100)); + if (err == ESP_OK) + return uart::FlushResult::SUCCESS; + if (err == ESP_ERR_TIMEOUT) + return uart::FlushResult::TIMEOUT; + return uart::FlushResult::FAILED; } void USBCDCACMInstance::check_logger_conflict() {} diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index a1f8738491..a0101a5546 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -166,7 +166,7 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { this->parent_->start_output(this); } -void USBUartChannel::flush() { +uart::FlushResult USBUartChannel::flush() { // Spin until the output queue is drained and the last USB transfer completes. // Safe to call from the main loop only. // The 100 ms timeout guards against a device that stops responding mid-flush; @@ -177,6 +177,9 @@ void USBUartChannel::flush() { this->parent_->start_output(this); yield(); } + if (!this->output_queue_.empty() || this->output_started_.load()) + return uart::FlushResult::TIMEOUT; + return uart::FlushResult::SUCCESS; } bool USBUartChannel::peek_byte(uint8_t *data) { diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 7290f8a958..671f0cab8c 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -110,7 +110,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override { return this->input_buffer_.get_available(); } - void flush() override; + uart::FlushResult flush() override; void check_logger_conflict() override {} void set_parity(UARTParityOptions parity) { this->parity_ = parity; } void set_debug(bool debug) { this->debug_ = debug; } diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index 3f5d6c787c..f01d164e9f 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -433,15 +433,16 @@ void WeikaiChannel::write_array(const uint8_t *buffer, size_t length) { this->reg(0).write_fifo(const_cast<uint8_t *>(buffer), length); } -void WeikaiChannel::flush() { +uart::FlushResult WeikaiChannel::flush() { uint32_t const start_time = millis(); while (this->tx_fifo_is_not_empty_()) { // wait until buffer empty if (millis() - start_time > 200) { ESP_LOGW(TAG, "WARNING flush timeout - still %d bytes not sent after 200 ms", this->tx_in_fifo_()); - return; + return uart::FlushResult::TIMEOUT; } yield(); // reschedule our thread to avoid blocking } + return uart::FlushResult::SUCCESS; } size_t WeikaiChannel::xfer_fifo_to_buffer_() { diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h index 43c3a1e4f4..715b82bfc7 100644 --- a/esphome/components/weikai/weikai.h +++ b/esphome/components/weikai/weikai.h @@ -380,7 +380,7 @@ class WeikaiChannel : public uart::UARTComponent { /// @details If we refer to Serial.flush() in Arduino it says: ** Waits for the transmission of outgoing serial data /// to complete. (Prior to Arduino 1.0, this the method was removing any buffered incoming serial data.). ** Therefore /// we wait until all bytes are gone with a timeout of 100 ms - void flush() override; + uart::FlushResult flush() override; protected: friend class WeikaiComponent; diff --git a/tests/components/ld2450/common.h b/tests/components/ld2450/common.h index d5ffbe1295..9f9e7b3e9f 100644 --- a/tests/components/ld2450/common.h +++ b/tests/components/ld2450/common.h @@ -16,7 +16,7 @@ class MockUARTComponent : public uart::UARTComponent { MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); MOCK_METHOD(size_t, available, (), (override)); - MOCK_METHOD(void, flush, (), (override)); + MOCK_METHOD(uart::FlushResult, flush, (), (override)); MOCK_METHOD(void, check_logger_conflict, (), (override)); }; diff --git a/tests/components/uart/common.h b/tests/components/uart/common.h index 1f9bfa15e7..f7e2d8a3f7 100644 --- a/tests/components/uart/common.h +++ b/tests/components/uart/common.h @@ -30,7 +30,7 @@ class MockUARTComponent : public UARTComponent { MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); MOCK_METHOD(size_t, available, (), (override)); - MOCK_METHOD(void, flush, (), (override)); + MOCK_METHOD(FlushResult, flush, (), (override)); MOCK_METHOD(void, check_logger_conflict, (), (override)); }; diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index e8c07d632d..1edeb97cf1 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -144,8 +144,9 @@ bool MockUartComponent::read_array(uint8_t *data, size_t len) { size_t MockUartComponent::available() { return this->rx_buffer_.size(); } -void MockUartComponent::flush() { +uart::FlushResult MockUartComponent::flush() { // Nothing to flush in mock + return uart::FlushResult::ASSUMED_SUCCESS; } void MockUartComponent::set_rx_full_threshold(size_t rx_full_threshold) { diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index 901e371dec..c9afb96357 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -28,7 +28,7 @@ class MockUartComponent : public uart::UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - void flush() override; + uart::FlushResult flush() override; void set_rx_full_threshold(size_t rx_full_threshold) override; void set_rx_timeout(size_t rx_timeout) override; From 04cff1c916ece7a8abe16a17f0c8bc4e07628d56 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Sun, 8 Mar 2026 00:04:14 -0600 Subject: [PATCH 1202/2030] [usb_uart] Return `flush` result, expose timeout via config (#14616) --- esphome/components/usb_uart/__init__.py | 6 +++++- esphome/components/usb_uart/usb_uart.cpp | 10 ++++++---- esphome/components/usb_uart/usb_uart.h | 11 ++++++----- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index eedf590eca..2d85723d72 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg from esphome.components import socket from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS -from esphome.components.uart import CONF_DEBUG_PREFIX, UARTComponent +from esphome.components.uart import CONF_DEBUG_PREFIX, CONF_FLUSH_TIMEOUT, UARTComponent from esphome.components.usb_host import register_usb_client, usb_device_schema import esphome.config_validation as cv from esphome.const import ( @@ -91,6 +91,9 @@ def channel_schema(channels, baud_rate_required): cv.Optional(CONF_DUMMY_RECEIVER, default=False): cv.boolean, cv.Optional(CONF_DEBUG, default=False): cv.boolean, cv.Optional(CONF_DEBUG_PREFIX, default=""): cv.string, + cv.Optional( + CONF_FLUSH_TIMEOUT, default="100ms" + ): cv.positive_time_period_milliseconds, } ) ), @@ -129,6 +132,7 @@ async def to_code(config): cg.add(chvar.set_parity(channel[CONF_PARITY])) cg.add(chvar.set_baud_rate(channel[CONF_BAUD_RATE])) cg.add(chvar.set_dummy_receiver(channel[CONF_DUMMY_RECEIVER])) + cg.add(chvar.set_flush_timeout(channel[CONF_FLUSH_TIMEOUT])) cg.add(chvar.set_debug(channel[CONF_DEBUG])) if channel[CONF_DEBUG_PREFIX]: cg.add(chvar.set_debug_prefix(channel[CONF_DEBUG_PREFIX])) diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index a0101a5546..83de0b39fc 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -169,10 +169,10 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { uart::FlushResult USBUartChannel::flush() { // Spin until the output queue is drained and the last USB transfer completes. // Safe to call from the main loop only. - // The 100 ms timeout guards against a device that stops responding mid-flush; + // The flush_timeout_ms_ timeout guards against a device that stops responding mid-flush; // in that case the main loop is blocked for the full duration. - uint32_t start = millis(); // 100 ms safety timeout - while ((!this->output_queue_.empty() || this->output_started_.load()) && millis() - start < 100) { + uint32_t start = millis(); + while ((!this->output_queue_.empty() || this->output_started_.load()) && millis() - start < this->flush_timeout_ms_) { // Kick start_output() in case data arrived but no transfer is in flight yet. this->parent_->start_output(this); yield(); @@ -260,10 +260,12 @@ void USBUartComponent::dump_config() { " Data Bits: %u\n" " Parity: %s\n" " Stop bits: %s\n" + " Flush Timeout: %" PRIu32 " ms\n" " Debug: %s\n" " Dummy receiver: %s", channel->index_, channel->baud_rate_, channel->data_bits_, PARITY_NAMES[channel->parity_], - STOP_BITS_NAMES[channel->stop_bits_], YESNO(channel->debug_), YESNO(channel->dummy_receiver_)); + STOP_BITS_NAMES[channel->stop_bits_], channel->flush_timeout_ms_, YESNO(channel->debug_), + YESNO(channel->dummy_receiver_)); } } void USBUartComponent::start_input(USBUartChannel *channel) { diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 671f0cab8c..b1748aebf2 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -116,6 +116,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon void set_debug(bool debug) { this->debug_ = debug; } void set_dummy_receiver(bool dummy_receiver) { this->dummy_receiver_ = dummy_receiver; } void set_debug_prefix(const char *prefix) { this->debug_prefix_ = StringRef(prefix); } + void set_flush_timeout(uint32_t flush_timeout_ms) override { this->flush_timeout_ms_ = flush_timeout_ms; } /// Register a callback invoked immediately after data is pushed to the input ring buffer. /// Called from USBUartComponent::loop() in the main loop context. @@ -124,23 +125,23 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon void set_rx_callback(std::function<void()> cb) { this->rx_callback_ = std::move(cb); } protected: - // Larger structures first for better alignment + // Larger structures first (8+ bytes) RingBuffer input_buffer_; LockFreeQueue<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_queue_; EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_pool_; std::function<void()> rx_callback_{}; CdcEps cdc_dev_{}; - // Enum (likely 4 bytes) + StringRef debug_prefix_{}; + // 4-byte fields UARTParityOptions parity_{UART_CONFIG_PARITY_NONE}; - // Group atomics together (each 1 byte) + uint32_t flush_timeout_ms_{100}; + // 1-byte fields (no padding between groups) std::atomic<bool> input_started_{true}; std::atomic<bool> output_started_{true}; std::atomic<bool> initialised_{false}; - // Group regular bytes together to minimize padding const uint8_t index_; bool debug_{}; bool dummy_receiver_{}; - StringRef debug_prefix_{}; }; class USBUartComponent : public usb_host::USBClient { From e4b89a69d4aba18e05b0a965e98e5f242637daf2 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sun, 8 Mar 2026 07:32:20 +0100 Subject: [PATCH 1203/2030] [nrf52, ota] ble and serial OTA based on mcumgr (#11932) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/nrf52/__init__.py | 46 +++++- esphome/components/ota/__init__.py | 9 +- esphome/components/safe_mode/safe_mode.cpp | 15 +- esphome/components/zephyr_mcumgr/__init__.py | 0 .../components/zephyr_mcumgr/ota/__init__.py | 141 +++++++++++++++++ .../zephyr_mcumgr/ota/ota_zephyr_mcumgr.cpp | 143 ++++++++++++++++++ .../zephyr_mcumgr/ota/ota_zephyr_mcumgr.h | 29 ++++ esphome/core/defines.h | 1 + script/helpers_zephyr.py | 16 ++ tests/components/ota/test.nrf52-mcumgr.yaml | 27 ++++ 11 files changed, 422 insertions(+), 6 deletions(-) create mode 100644 esphome/components/zephyr_mcumgr/__init__.py create mode 100644 esphome/components/zephyr_mcumgr/ota/__init__.py create mode 100644 esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.cpp create mode 100644 esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.h create mode 100644 tests/components/ota/test.nrf52-mcumgr.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8bf896d159..d60dbc729d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -587,6 +587,7 @@ esphome/components/xl9535/* @mreditor97 esphome/components/xpt2046/touchscreen/* @nielsnl68 @numo68 esphome/components/xxtea/* @clydebarrow esphome/components/zephyr/* @tomaszduda23 +esphome/components/zephyr_mcumgr/ota/* @tomaszduda23 esphome/components/zhlt01/* @cfeenstra1024 esphome/components/zigbee/* @tomaszduda23 esphome/components/zio_ultrasonic/* @kahrendt diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 0a9fb5939a..c3a10a9944 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -27,10 +27,15 @@ from esphome.components.zephyr.const import ( ) import esphome.config_validation as cv from esphome.const import ( + CONF_ADVANCED, CONF_BOARD, + CONF_DISABLED, + CONF_ENABLE_OTA_ROLLBACK, CONF_FRAMEWORK, CONF_ID, + CONF_OTA, CONF_RESET_PIN, + CONF_SAFE_MODE, CONF_VERSION, CONF_VOLTAGE, KEY_CORE, @@ -41,6 +46,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority +import esphome.final_validate as fv from esphome.storage_json import StorageJSON from esphome.types import ConfigType @@ -133,6 +139,7 @@ CONF_UICR_ERASE = "uicr_erase" VOLTAGE_LEVELS = [1.8, 2.1, 2.4, 2.7, 3.0, 3.3] + CONFIG_SCHEMA = cv.All( _detect_bootloader, set_core_data, @@ -156,9 +163,19 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_UICR_ERASE, default=False): cv.boolean, } ), - cv.Optional(CONF_FRAMEWORK, default={CONF_VERSION: "2.6.1-a"}): cv.Schema( + cv.Optional( + CONF_FRAMEWORK, + default={}, + ): cv.Schema( { - cv.Required(CONF_VERSION): cv.string_strict, + cv.Optional(CONF_VERSION, default="2.6.1-a"): cv.string_strict, + cv.Optional(CONF_ADVANCED, default={}): cv.Schema( + { + cv.Optional( + CONF_ENABLE_OTA_ROLLBACK, default=True + ): cv.boolean, + } + ), } ), cv.GenerateID(CONF_CDC_ACM): cv.declare_id(CdcAcm), @@ -181,6 +198,24 @@ def _final_validate(config): _LOGGER.warning( "Selected generic Adafruit bootloader. The board might crash. Consider settings `bootloader:`" ) + full_config = fv.full_config.get() + conf = config[CONF_FRAMEWORK] + advanced = conf[CONF_ADVANCED] + + if advanced[CONF_ENABLE_OTA_ROLLBACK]: + # "disabled: false" means safe mode *is* enabled. + safe_mode_config = full_config.get(CONF_SAFE_MODE, {CONF_DISABLED: True}) + safe_mode_enabled = not safe_mode_config[CONF_DISABLED] + ota_enabled = CONF_OTA in full_config + # Both need to be enabled for rollback to work + if not (ota_enabled and safe_mode_enabled): + # But only warn if ota is even possible + if ota_enabled: + _LOGGER.warning( + "OTA rollback requires safe_mode, disabling rollback support" + ) + # disable the rollback feature anyway since it can't be used. + advanced[CONF_ENABLE_OTA_ROLLBACK] = False FINAL_VALIDATE_SCHEMA = _final_validate @@ -247,6 +282,11 @@ async def to_code(config: ConfigType) -> None: if reg0_config[CONF_UICR_ERASE]: cg.add_define("USE_NRF52_UICR_ERASE") + conf = config[CONF_FRAMEWORK] + advanced = conf[CONF_ADVANCED] + # Enable OTA rollback support + if advanced[CONF_ENABLE_OTA_ROLLBACK]: + cg.add_define("USE_OTA_ROLLBACK") # c++ support if framework_ver < cv.Version(2, 9, 2): zephyr_add_prj_conf("CPLUSPLUS", True) @@ -259,7 +299,7 @@ async def to_code(config: ConfigType) -> None: zephyr_add_prj_conf("WDT_DISABLE_AT_BOOT", False) # disable console zephyr_add_prj_conf("UART_CONSOLE", False) - zephyr_add_prj_conf("CONSOLE", False) + zephyr_add_prj_conf("CONSOLE", False, False) # use NFC pins as GPIO if framework_ver < cv.Version(2, 9, 2): zephyr_add_prj_conf("NFCT_PINS_AS_GPIOS", True) diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index ee54d5f8d3..8f31eb5cdd 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -18,7 +18,14 @@ from esphome.coroutine import CoroPriority OTA_STATE_LISTENER_KEY = "ota_state_listener" CODEOWNERS = ["@esphome/core"] -AUTO_LOAD = ["md5", "safe_mode"] + + +def AUTO_LOAD() -> list[str]: + components = ["safe_mode"] + if not CORE.using_zephyr: + components.extend(["md5"]) + return components + IS_PLATFORM_COMPONENT = True diff --git a/esphome/components/safe_mode/safe_mode.cpp b/esphome/components/safe_mode/safe_mode.cpp index fe2acd9612..40fa03392b 100644 --- a/esphome/components/safe_mode/safe_mode.cpp +++ b/esphome/components/safe_mode/safe_mode.cpp @@ -9,10 +9,14 @@ #include <cinttypes> #include <cstdio> -#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) +#ifdef USE_OTA_ROLLBACK +#ifdef USE_ZEPHYR +#include <zephyr/dfu/mcuboot.h> +#elif defined(USE_ESP32) #include <esp_ota_ops.h> #include <esp_system.h> #endif +#endif namespace esphome::safe_mode { @@ -66,9 +70,16 @@ float SafeModeComponent::get_setup_priority() const { return setup_priority::AFT void SafeModeComponent::mark_successful() { this->clean_rtc(); this->boot_successful_ = true; -#if defined(USE_ESP32) && defined(USE_OTA_ROLLBACK) +#if defined(USE_OTA_ROLLBACK) +// Mark OTA partition as valid to prevent rollback +#if defined(USE_ZEPHYR) + if (!boot_is_img_confirmed()) { + boot_write_img_confirmed(); + } +#elif defined(USE_ESP32) // Mark OTA partition as valid to prevent rollback esp_ota_mark_app_valid_cancel_rollback(); +#endif #endif // Disable loop since we no longer need to check this->disable_loop(); diff --git a/esphome/components/zephyr_mcumgr/__init__.py b/esphome/components/zephyr_mcumgr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/zephyr_mcumgr/ota/__init__.py b/esphome/components/zephyr_mcumgr/ota/__init__.py new file mode 100644 index 0000000000..b0d86190b8 --- /dev/null +++ b/esphome/components/zephyr_mcumgr/ota/__init__.py @@ -0,0 +1,141 @@ +import esphome.codegen as cg +from esphome.components.ota import BASE_OTA_SCHEMA, OTAComponent, ota_to_code +from esphome.components.zephyr import ( + zephyr_add_cdc_acm, + zephyr_add_overlay, + zephyr_add_prj_conf, + zephyr_data, +) +from esphome.components.zephyr.const import BOOTLOADER_MCUBOOT, KEY_BOOTLOADER +import esphome.config_validation as cv +from esphome.const import CONF_HARDWARE_UART, CONF_ID, Framework +from esphome.core import CORE, coroutine_with_priority +from esphome.coroutine import CoroPriority +from esphome.types import ConfigType + +CODEOWNERS = ["@tomaszduda23"] +DEPENDENCIES = ["zephyr"] + +ZephyrMcumgrOTAComponent = cg.esphome_ns.namespace("zephyr_mcumgr").class_( + "OTAComponent", OTAComponent +) + +CONF_BLE = "ble" +CONF_TRANSPORT = "transport" + + +def _validate_transport(conf: ConfigType) -> ConfigType: + transport = conf[CONF_TRANSPORT] + if transport[CONF_BLE] or CONF_HARDWARE_UART in transport: + return conf + raise cv.Invalid( + f"At least one transport protocol has to be enabled. Set '{CONF_BLE}: true' or '{CONF_HARDWARE_UART}'" + ) + + +UARTS = { + "CDC": ("cdc_acm_uart0", 0), + "CDC1": ("cdc_acm_uart1", 1), + "UART0": ("uart0", -1), + "UART1": ("uart1", -1), +} + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ZephyrMcumgrOTAComponent), + cv.Optional(CONF_TRANSPORT, default={CONF_BLE: True}): cv.Schema( + { + cv.Optional(CONF_BLE, default=False): cv.boolean, + cv.Optional( + CONF_HARDWARE_UART, + ): cv.one_of(*UARTS, upper=True), + } + ), + } + ) + .extend(BASE_OTA_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), + _validate_transport, + cv.only_with_framework(Framework.ZEPHYR), +) + + +def _validate_mcumgr_bootloader(config: ConfigType) -> None: + bootloader = zephyr_data()[KEY_BOOTLOADER] + if bootloader != BOOTLOADER_MCUBOOT: + raise cv.Invalid(f"'{bootloader}' bootloader does not support OTA") + + +KEY_ZEPHYR_BLE_SERVER = "zephyr_ble_server" + + +def _validate_ble_server(config: ConfigType) -> None: + if ( + config[CONF_TRANSPORT][CONF_BLE] + and KEY_ZEPHYR_BLE_SERVER not in CORE.loaded_integrations + ): + raise cv.Invalid(f"'{KEY_ZEPHYR_BLE_SERVER}' component is required for BLE OTA") + + +def _final_validate(config: ConfigType) -> None: + _validate_mcumgr_bootloader(config) + _validate_ble_server(config) + + +FINAL_VALIDATE_SCHEMA = _final_validate + + +@coroutine_with_priority(CoroPriority.OTA_UPDATES) +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await ota_to_code(var, config) + + await cg.register_component(var, config) + + zephyr_add_prj_conf("NET_BUF", True) + zephyr_add_prj_conf("ZCBOR", True) + zephyr_add_prj_conf("MCUMGR", True) + + zephyr_add_prj_conf("MCUMGR_GRP_IMG", True) + + zephyr_add_prj_conf("IMG_MANAGER", True) + zephyr_add_prj_conf("STREAM_FLASH", True) + zephyr_add_prj_conf("FLASH_MAP", True) + zephyr_add_prj_conf("FLASH", True) + + zephyr_add_prj_conf("IMG_ERASE_PROGRESSIVELY", True) + + zephyr_add_prj_conf("BOOTLOADER_MCUBOOT", True) + + zephyr_add_prj_conf("MCUMGR_MGMT_NOTIFICATION_HOOKS", True) + zephyr_add_prj_conf("MCUMGR_GRP_IMG_STATUS_HOOKS", True) + zephyr_add_prj_conf("MCUMGR_GRP_IMG_UPLOAD_CHECK_HOOK", True) + transport = config[CONF_TRANSPORT] + if transport[CONF_BLE]: + zephyr_add_prj_conf("MCUMGR_TRANSPORT_BT", True) + zephyr_add_prj_conf("MCUMGR_TRANSPORT_BT_REASSEMBLY", True) + + zephyr_add_prj_conf("MCUMGR_GRP_OS", True) + zephyr_add_prj_conf("MCUMGR_GRP_OS_MCUMGR_PARAMS", True) + + zephyr_add_prj_conf("NCS_SAMPLE_MCUMGR_BT_OTA_DFU_SPEEDUP", True) + if CONF_HARDWARE_UART in transport: + uart = UARTS[transport[CONF_HARDWARE_UART]] + uart_name = uart[0] + cdc_id = uart[1] + if cdc_id >= 0: + zephyr_add_cdc_acm(config, cdc_id) + zephyr_add_prj_conf("MCUMGR_TRANSPORT_UART", True) + zephyr_add_prj_conf("BASE64", True) + zephyr_add_prj_conf("CONSOLE", True) + zephyr_add_overlay( + f""" + / {{ + chosen {{ + zephyr,uart-mcumgr = &{uart_name}; + }}; + }}; + """ + ) diff --git a/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.cpp b/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.cpp new file mode 100644 index 0000000000..f1eac462bc --- /dev/null +++ b/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.cpp @@ -0,0 +1,143 @@ +#ifdef USE_ZEPHYR +#include "ota_zephyr_mcumgr.h" +#include "esphome/core/log.h" +#include "esphome/core/hal.h" +#include <zephyr/sys/math_extras.h> +#include <zephyr/usb/usb_device.h> +#include <zephyr/dfu/mcuboot.h> + +// It should be from below header but there is problem with internal includes. +// #include <zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h> +// NOLINTBEGIN(readability-identifier-naming,google-runtime-int) +struct img_mgmt_upload_action { + /** The total size of the image. */ + unsigned long long size; +}; + +struct img_mgmt_upload_req { + uint32_t image; /* 0 by default */ + size_t off; /* SIZE_MAX if unspecified */ +}; +// NOLINTEND(readability-identifier-naming,google-runtime-int) + +namespace esphome::zephyr_mcumgr { + +static_assert(sizeof(struct img_mgmt_upload_action) == 8, "ABI mismatch"); +static_assert(sizeof(struct img_mgmt_upload_req) == 8, "ABI mismatch"); +static_assert(offsetof(struct img_mgmt_upload_req, image) == 0, "ABI mismatch"); +static_assert(offsetof(struct img_mgmt_upload_req, off) == 4, "ABI mismatch"); + +static const char *const TAG = "zephyr_mcumgr"; +static OTAComponent *global_ota_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +static enum mgmt_cb_return mcumgr_img_mgmt_cb(uint32_t event, enum mgmt_cb_return prev_status, int32_t *rc, + uint16_t *group, bool *abort_more, void *data, size_t data_size) { + if (MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK == event) { + const img_mgmt_upload_check &upload = *static_cast<img_mgmt_upload_check *>(data); + global_ota_component->update_chunk(upload); + } else if (MGMT_EVT_OP_IMG_MGMT_DFU_STARTED == event) { + global_ota_component->update_started(); + } else if (MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE == event) { + global_ota_component->update_chunk_wrote(); + } else if (MGMT_EVT_OP_IMG_MGMT_DFU_PENDING == event) { + global_ota_component->update_pending(); + } else if (MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED == event) { + global_ota_component->update_stopped(); + } else { + ESP_LOGD(TAG, "MCUmgr Image Management Event with the %d ID", u32_count_trailing_zeros(MGMT_EVT_GET_ID(event))); + } + return MGMT_CB_OK; +} + +OTAComponent::OTAComponent() { global_ota_component = this; } + +void OTAComponent::setup() { + this->img_mgmt_callback_.callback = mcumgr_img_mgmt_cb; + this->img_mgmt_callback_.event_id = MGMT_EVT_OP_IMG_MGMT_ALL; + mgmt_callback_register(&this->img_mgmt_callback_); +#ifdef CONFIG_USB_DEVICE_STACK + usb_enable(nullptr); +#endif +// Handle OTA rollback: mark partition valid immediately unless USE_OTA_ROLLBACK is enabled, +// in which case safe_mode will mark it valid after confirming successful boot. +#ifndef USE_OTA_ROLLBACK + if (!boot_is_img_confirmed()) { + boot_write_img_confirmed(); + } +#endif +} + +#ifdef ESPHOME_LOG_HAS_CONFIG +static const char *swap_type_str(uint8_t type) { + switch (type) { + case BOOT_SWAP_TYPE_NONE: + return "none"; + case BOOT_SWAP_TYPE_TEST: + return "test"; + case BOOT_SWAP_TYPE_PERM: + return "perm"; + case BOOT_SWAP_TYPE_REVERT: + return "revert"; + case BOOT_SWAP_TYPE_FAIL: + return "fail"; + } + + return "unknown"; +} +#endif + +void OTAComponent::dump_config() { + ESP_LOGCONFIG(TAG, + "Over-The-Air Updates:\n" + " swap type after reboot: %s\n" + " image confirmed: %s", + swap_type_str(mcuboot_swap_type()), YESNO(boot_is_img_confirmed())); +} + +void OTAComponent::update_chunk(const img_mgmt_upload_check &upload) { + float percentage = (upload.req->off * 100.0f) / upload.action->size; + this->defer([this, percentage]() { this->percentage_ = percentage; }); +} + +void OTAComponent::update_started() { + this->defer([this]() { + ESP_LOGD(TAG, "Starting update"); +#ifdef USE_OTA_STATE_LISTENER + this->notify_state_(ota::OTA_STARTED, 0.0f, 0); +#endif + }); +} + +void OTAComponent::update_chunk_wrote() { + uint32_t now = millis(); + if (now - this->last_progress_ > 1000) { + this->last_progress_ = now; + this->defer([this]() { + ESP_LOGD(TAG, "OTA in progress: %0.1f%%", this->percentage_); +#ifdef USE_OTA_STATE_LISTENER + this->notify_state_(ota::OTA_IN_PROGRESS, this->percentage_, 0); +#endif + }); + } +} + +void OTAComponent::update_pending() { + this->defer([this]() { + ESP_LOGD(TAG, "OTA pending"); +#ifdef USE_OTA_STATE_LISTENER + this->notify_state_(ota::OTA_COMPLETED, 100.0f, 0); +#endif + }); +} + +void OTAComponent::update_stopped() { + this->defer([this]() { + ESP_LOGD(TAG, "OTA stopped"); +#ifdef USE_OTA_STATE_LISTENER + this->notify_state_(ota::OTA_ERROR, 0.0f, static_cast<uint8_t>(ota::OTA_RESPONSE_ERROR_UNKNOWN)); +#endif + }); +} + +} // namespace esphome::zephyr_mcumgr +#endif diff --git a/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.h b/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.h new file mode 100644 index 0000000000..ab98f93598 --- /dev/null +++ b/esphome/components/zephyr_mcumgr/ota/ota_zephyr_mcumgr.h @@ -0,0 +1,29 @@ +#pragma once +#include "esphome/core/defines.h" +#ifdef USE_ZEPHYR +#include "esphome/components/ota/ota_backend.h" +#include <zephyr/mgmt/mcumgr/mgmt/callbacks.h> + +struct img_mgmt_upload_check; + +namespace esphome::zephyr_mcumgr { + +class OTAComponent : public ota::OTAComponent { + public: + OTAComponent(); + void setup() override; + void dump_config() override; + void update_chunk(const img_mgmt_upload_check &upload); + void update_started(); + void update_chunk_wrote(); + void update_pending(); + void update_stopped(); + + protected: + uint32_t last_progress_ = 0; + float percentage_ = 0; + mgmt_callback img_mgmt_callback_{}; +}; + +} // namespace esphome::zephyr_mcumgr +#endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c5f38ab9aa..48c467f69f 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -367,6 +367,7 @@ #define USE_NRF52_DFU #define USE_NRF52_REG0_VOUT 5 #define USE_NRF52_UICR_ERASE +#define USE_OTA_ROLLBACK #define USE_SOFTDEVICE_ID 7 #define USE_SOFTDEVICE_VERSION 1 #define USE_ZIGBEE diff --git a/script/helpers_zephyr.py b/script/helpers_zephyr.py index 1242a60cf4..66ef6ffc98 100644 --- a/script/helpers_zephyr.py +++ b/script/helpers_zephyr.py @@ -28,6 +28,22 @@ extern "C" void zboss_signal_handler() {}; CONFIG_NEWLIB_LIBC=y CONFIG_BT=y CONFIG_ADC=y +#mcumgr begin +CONFIG_NET_BUF=y +CONFIG_ZCBOR=y +CONFIG_MCUMGR=y +CONFIG_MCUMGR_GRP_IMG=y +CONFIG_IMG_MANAGER=y +CONFIG_STREAM_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_FLASH=y +CONFIG_IMG_ERASE_PROGRESSIVELY=y +CONFIG_BOOTLOADER_MCUBOOT=y +CONFIG_MCUMGR_MGMT_NOTIFICATION_HOOKS=y +CONFIG_MCUMGR_GRP_IMG_STATUS_HOOKS=y +CONFIG_MCUMGR_GRP_IMG_UPLOAD_CHECK_HOOK=y +CONFIG_MCUMGR_TRANSPORT_UART=y +#mcumgr end #zigbee begin CONFIG_ZIGBEE=y CONFIG_CRYPTO=y diff --git a/tests/components/ota/test.nrf52-mcumgr.yaml b/tests/components/ota/test.nrf52-mcumgr.yaml new file mode 100644 index 0000000000..1e7986f61a --- /dev/null +++ b/tests/components/ota/test.nrf52-mcumgr.yaml @@ -0,0 +1,27 @@ +zephyr_ble_server: + +ota: + - platform: zephyr_mcumgr + transport: + ble: true + hardware_uart: CDC + 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); From d9e76da8064ba955c2406d13e07e1377ca77ea9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Mar 2026 07:59:25 +0000 Subject: [PATCH 1204/2030] Bump aioesphomeapi from 44.4.0 to 44.5.0 (#14617) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a1300a67f7..4124bf8791 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.4.0 +aioesphomeapi==44.5.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From a530aeec22174300264d58f791518d993658e9ba Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 7 Mar 2026 22:09:12 -1000 Subject: [PATCH 1205/2030] [api] Inline varint and encode_varint_raw fast paths for hot loop performance (#14607) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/proto.cpp | 12 ++++++++ esphome/components/api/proto.h | 51 ++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 1ca6b702ad..fb229928e5 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -8,6 +8,18 @@ namespace esphome::api { static const char *const TAG = "api.proto"; +uint32_t ProtoSize::varint_slow(uint32_t value) { return varint_wide(value); } + +void ProtoWriteBuffer::encode_varint_raw_slow_(uint32_t value) { + do { + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value | 0x80); + value >>= 7; + } while (value > 0x7F); + this->debug_check_bounds_(1); + *this->pos_++ = static_cast<uint8_t>(value); +} + #ifdef USE_API_VARINT64 optional<ProtoVarInt> ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, uint32_t result32) { diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index bbdd11b29d..adde0a8a85 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -240,14 +240,13 @@ class ProtoWriteBuffer { ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} ProtoWriteBuffer(std::vector<uint8_t> *buffer, size_t write_pos) : buffer_(buffer), pos_(buffer->data() + write_pos) {} - void encode_varint_raw(uint32_t value) { - while (value > 0x7F) { + inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint32_t value) { + if (value < 128) [[likely]] { this->debug_check_bounds_(1); - *this->pos_++ = static_cast<uint8_t>(value | 0x80); - value >>= 7; + *this->pos_++ = static_cast<uint8_t>(value); + return; } - this->debug_check_bounds_(1); - *this->pos_++ = static_cast<uint8_t>(value); + this->encode_varint_raw_slow_(value); } void encode_varint_raw_64(uint64_t value) { while (value > 0x7F) { @@ -378,6 +377,9 @@ class ProtoWriteBuffer { std::vector<uint8_t> *get_buffer() const { return buffer_; } protected: + // Slow path for encode_varint_raw values >= 128, outlined to keep fast path small + void encode_varint_raw_slow_(uint32_t value) __attribute__((noinline)); + #ifdef ESPHOME_DEBUG_API void debug_check_bounds_(size_t bytes, const char *caller = __builtin_FUNCTION()); void debug_check_encode_size_(uint32_t field_id, uint32_t expected, ptrdiff_t actual); @@ -511,24 +513,29 @@ class ProtoSize { * @param value The uint32_t value to calculate size for * @return The number of bytes needed to encode the value */ - static constexpr uint32_t varint(uint32_t value) { - // Optimized varint size calculation using leading zeros - // Each 7 bits requires one byte in the varint encoding - if (value < 128) - return 1; // 7 bits, common case for small values - - // For larger values, count bytes needed based on the position of the highest bit set - if (value < 16384) { - return 2; // 14 bits - } else if (value < 2097152) { - return 3; // 21 bits - } else if (value < 268435456) { - return 4; // 28 bits - } else { - return 5; // 32 bits (maximum for uint32_t) - } + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint(uint32_t value) { + if (value < 128) [[likely]] + return 1; // Fast path: 7 bits, most common case + if (__builtin_is_constant_evaluated()) + return varint_wide(value); + return varint_slow(value); } + private: + // Slow path for varint >= 128, outlined to keep fast path small + static uint32_t varint_slow(uint32_t value) __attribute__((noinline)); + // Shared cascade for values >= 128 (used by both constexpr and noinline paths) + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint_wide(uint32_t value) { + if (value < 16384) + return 2; + if (value < 2097152) + return 3; + if (value < 268435456) + return 4; + return 5; + } + + public: /** * @brief Calculates the size in bytes needed to encode a uint64_t value as a varint * From 2c705810cdaff126c8fa5270e012c8037c62311b Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sun, 8 Mar 2026 09:40:52 +0100 Subject: [PATCH 1206/2030] [nrf52] allow to update OTA via cmd (#12344) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/nrf52/__init__.py | 38 +++++-- esphome/components/nrf52/ota.py | 164 +++++++++++++++++++++++++++ requirements.txt | 1 + 3 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 esphome/components/nrf52/ota.py diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index c3a10a9944..5054e5e0df 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -392,22 +392,42 @@ def _upload_using_platformio( def upload_program(config: ConfigType, args, host: str) -> bool: from esphome.__main__ import check_permissions, get_port_type - result = 0 - handled = False + mcumgr_device: str | None = None if get_port_type(host) == "SERIAL": check_permissions(host) - result = _upload_using_platformio(config, host, ["-t", "upload"]) - handled = True + if zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT: + mcumgr_device = host + else: + result = _upload_using_platformio(config, host, ["-t", "upload"]) + if result != 0: + raise EsphomeError(f"Upload failed with result: {result}") + return True # Handled: platformio serial upload if host == "PYOCD": result = _upload_using_platformio(config, host, ["-t", "flash_pyocd"]) - handled = True + if result != 0: + raise EsphomeError(f"Upload failed with result: {result}") + return True # Handled: platformio PYOCD upload - if result != 0: - raise EsphomeError(f"Upload failed with result: {result}") + # Deferred imports: bleak/smpclient are heavy, only load for BLE/mcumgr paths + from .ble_logger import is_mac_address + from .ota import smpmgr_scan, smpmgr_upload - return handled + if host == "BLE": + mcumgr_device = asyncio.run(smpmgr_scan(CORE.name)) + + if is_mac_address(host): + mcumgr_device = host + + if mcumgr_device: + firmware = Path( + CORE.relative_pioenvs_path(CORE.name, "zephyr", "app_update.bin") + ).resolve() + asyncio.run(smpmgr_upload(mcumgr_device, firmware)) + return True # Handled: mcumgr OTA upload + + return False # Not handled: let caller try default upload methods def show_logs(config: ConfigType, args, devices: list[str]) -> bool: @@ -415,7 +435,7 @@ def show_logs(config: ConfigType, args, devices: list[str]) -> bool: from .ble_logger import is_mac_address, logger_connect, logger_scan if devices[0] == "BLE": - ble_device = asyncio.run(logger_scan(CORE.config["esphome"]["name"])) + ble_device = asyncio.run(logger_scan(CORE.name)) if ble_device: address = ble_device.address else: diff --git a/esphome/components/nrf52/ota.py b/esphome/components/nrf52/ota.py new file mode 100644 index 0000000000..e4b26b45eb --- /dev/null +++ b/esphome/components/nrf52/ota.py @@ -0,0 +1,164 @@ +import asyncio +from dataclasses import asdict +import json +import logging +from pathlib import Path + +from bleak import BleakScanner +from bleak.exc import BleakDeviceNotFoundError +from smp.exceptions import SMPBadStartDelimiter +from smpclient import SMPClient +from smpclient.generics import error, success +from smpclient.mcuboot import IMAGE_TLV, ImageInfo, MCUBootImageError, TLVNotFound +from smpclient.requests.image_management import ImageStatesRead, ImageStatesWrite +from smpclient.requests.os_management import ResetWrite +from smpclient.transport import SMPTransportDisconnected +from smpclient.transport.ble import ( + SMPBLETransport, + SMPBLETransportDeviceNotFound, + SMPBLETransportException, +) +from smpclient.transport.serial import SMPSerialTransport + +from esphome.core import EsphomeError +from esphome.espota2 import ProgressBar + +from .ble_logger import is_mac_address + +SMP_SERVICE_UUID = "8D53DC1D-1DB7-4CD3-868B-8A527460AA84" +BLE_SCAN_TIMEOUT = 10.0 # seconds +RESET_DELAY = 2.0 # seconds to wait before reset, allows on_end action to execute + +_LOGGER = logging.getLogger(__name__) + + +def _json_state(o: object) -> object: + """JSON serializer for SMP image state objects.""" + if isinstance(o, (bytes, bytearray)): + return o.hex() + if hasattr(o, "hex"): + return o.hex() + if hasattr(o, "__dict__"): + return vars(o) + return str(o) + + +async def smpmgr_scan(name: str) -> str: + _LOGGER.info("Scanning bluetooth for %s...", name) + for device in await BleakScanner.discover( + timeout=BLE_SCAN_TIMEOUT, service_uuids=[SMP_SERVICE_UUID] + ): + if device.name == name: + return device.address + raise EsphomeError(f"BLE device {name} with OTA service not found") + + +async def smpmgr_upload(device: str, firmware: Path) -> None: + try: + await _smpmgr_upload(device, firmware) + except SMPTransportDisconnected as exc: + raise EsphomeError(f"{device} was disconnected.") from exc + except SMPBLETransportDeviceNotFound as exc: + raise EsphomeError(f"{device} was not found.") from exc + + +def _get_image_tlv_sha256(file: Path) -> bytes: + _LOGGER.info("Checking image: %s", str(file)) + try: + image_info = ImageInfo.load_file(str(file)) + _LOGGER.info( + "Image header:\n%s", json.dumps(asdict(image_info.header), indent=2) + ) + _LOGGER.debug(str(image_info)) + except MCUBootImageError as exc: + raise EsphomeError("Inspection of FW image failed") from exc + except FileNotFoundError as exc: + raise EsphomeError( + f"Firmware image file not found: {file}. Build with zephyr_mcumgr enabled" + ) from exc + + try: + image_tlv_sha256 = image_info.get_tlv(IMAGE_TLV.SHA256) + _LOGGER.info("Image tlv sha256: %s", image_tlv_sha256) + except TLVNotFound as exc: + raise EsphomeError("Could not find IMAGE_TLV_SHA256 in image.") from exc + return image_tlv_sha256.value + + +async def _smpmgr_upload(device: str, firmware: Path) -> None: + image_tlv_sha256 = _get_image_tlv_sha256(firmware) + + if is_mac_address(device): + smp_client = SMPClient(SMPBLETransport(), device) + else: + smp_client = SMPClient(SMPSerialTransport(), device) + + _LOGGER.info("Connecting %s...", device) + try: + await smp_client.connect() + except BleakDeviceNotFoundError as exc: + raise EsphomeError(f"Device {device} not found") from exc + except SMPBLETransportException as exc: + raise EsphomeError(f"Connection error with {device}") from exc + + _LOGGER.info("Connected %s...", device) + try: + await _smpmgr_upload_connected(smp_client, device, firmware, image_tlv_sha256) + finally: + await smp_client.disconnect() + + +async def _smpmgr_upload_connected( + smp_client: SMPClient, device: str, firmware: Path, image_tlv_sha256: bytes +) -> None: + try: + image_state = await smp_client.request(ImageStatesRead(), 2.5) + except (SMPBadStartDelimiter, TimeoutError) as exc: + raise EsphomeError(f"mcumgr is not supported by device ({device})") from exc + + already_uploaded = False + + if error(image_state): + raise EsphomeError(f"Failed to read image state from {device}: {image_state}") + if success(image_state): + if len(image_state.images) == 0: + _LOGGER.warning("No images on device!") + for image in image_state.images: + _LOGGER.info( + "Image state:\n%s", + json.dumps(image, indent=2, default=_json_state), + ) + if image.active and not image.confirmed: + raise EsphomeError("No free slot. Testing mode but not confirmed yet.") + if image.hash == image_tlv_sha256: + if already_uploaded: + raise EsphomeError("Both slots have the same image already") + if image.confirmed: + raise EsphomeError("The same image already confirmed") + _LOGGER.warning("The same image already uploaded") + already_uploaded = True + + if not already_uploaded: + with open(firmware, "rb") as file: + image = file.read() + upload_size = len(image) + progress = ProgressBar() + progress.update(0) + try: + async for offset in smp_client.upload(image): + progress.update(offset / upload_size) + finally: + progress.done() + + _LOGGER.info("Mark image for testing") + r = await smp_client.request(ImageStatesWrite(hash=image_tlv_sha256), 1.0) + + if error(r): + raise EsphomeError(f"Failed to mark image for testing on {device}: {r}") + + await asyncio.sleep(RESET_DELAY) + _LOGGER.info("Reset") + r = await smp_client.request(ResetWrite(), 1.0) + + if error(r): + raise EsphomeError(f"Failed to reset {device}: {r}") diff --git a/requirements.txt b/requirements.txt index 4124bf8791..03a7cac5c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -23,6 +23,7 @@ resvg-py==0.2.6 freetype-py==2.5.1 jinja2==3.1.6 bleak==2.1.1 +smpclient==6.0.0 requests==2.32.5 # esp-idf >= 5.0 requires this From 0c4a44566f9ba56d5f01bb6af2b436a1c859128b Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Sun, 8 Mar 2026 03:55:49 -0500 Subject: [PATCH 1207/2030] [serial_proxy] New component (#13944) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- CODEOWNERS | 1 + esphome/components/api/api.proto | 20 ++ esphome/components/api/api_connection.cpp | 93 +++++++++ esphome/components/api/api_connection.h | 10 + esphome/components/api/api_pb2.cpp | 14 ++ esphome/components/api/api_pb2.h | 26 +++ esphome/components/api/api_pb2_dump.cpp | 24 +++ esphome/components/api/api_pb2_service.h | 1 + esphome/components/serial_proxy/__init__.py | 104 ++++++++++ .../components/serial_proxy/serial_proxy.cpp | 188 ++++++++++++++++++ .../components/serial_proxy/serial_proxy.h | 129 ++++++++++++ esphome/core/application.h | 17 ++ esphome/core/defines.h | 2 + tests/components/serial_proxy/common.yaml | 10 + .../serial_proxy/test.esp32-idf.yaml | 8 + .../serial_proxy/test.esp8266-ard.yaml | 8 + .../serial_proxy/test.rp2040-ard.yaml | 8 + 17 files changed, 663 insertions(+) create mode 100644 esphome/components/serial_proxy/__init__.py create mode 100644 esphome/components/serial_proxy/serial_proxy.cpp create mode 100644 esphome/components/serial_proxy/serial_proxy.h create mode 100644 tests/components/serial_proxy/common.yaml create mode 100644 tests/components/serial_proxy/test.esp32-idf.yaml create mode 100644 tests/components/serial_proxy/test.esp8266-ard.yaml create mode 100644 tests/components/serial_proxy/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index d60dbc729d..cb415bb625 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -435,6 +435,7 @@ esphome/components/sen5x/* @martgras esphome/components/sen6x/* @martgras @mebner86 @mikelawrence @tuct esphome/components/sensirion_common/* @martgras esphome/components/sensor/* @esphome/core +esphome/components/serial_proxy/* @kbx81 esphome/components/sfa30/* @ghsensdev esphome/components/sgp40/* @SenexCrenshaw esphome/components/sgp4x/* @martgras @SenexCrenshaw diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 257a7aaf82..28332d67a5 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -2618,6 +2618,14 @@ enum SerialProxyRequestType { SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2; // Flush the serial port (block until all TX data is sent) } +enum SerialProxyStatus { + SERIAL_PROXY_STATUS_OK = 0; // Completed successfully; TX drain confirmed + SERIAL_PROXY_STATUS_ASSUMED_SUCCESS = 1; // Platform cannot confirm TX drain; success assumed + SERIAL_PROXY_STATUS_ERROR = 2; // Driver or hardware error + SERIAL_PROXY_STATUS_TIMEOUT = 3; // Timed out before TX completed + SERIAL_PROXY_STATUS_NOT_SUPPORTED = 4; // Request type not supported by this instance +} + // Generic request message for simple serial proxy operations message SerialProxyRequest { option (id) = 144; @@ -2628,6 +2636,18 @@ message SerialProxyRequest { SerialProxyRequestType type = 2; // Request type } +// Response to a SerialProxyRequest (e.g. flush completion or failure) +message SerialProxyRequestResponse { + option (id) = 147; + option (source) = SOURCE_SERVER; + option (ifdef) = "USE_SERIAL_PROXY"; + + uint32 instance = 1; // Instance index (0-based) + SerialProxyRequestType type = 2; // Which request type this responds to + SerialProxyStatus status = 3; // Result status + string error_message = 4; // Additional detail on failure (optional) +} + // ==================== BLUETOOTH CONNECTION PARAMS ==================== message BluetoothSetConnectionParamsRequest { option (id) = 145; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index b9b33ddcc2..43f5070a40 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1445,6 +1445,89 @@ void APIConnection::on_infrared_rf_transmit_raw_timings_request(const InfraredRF void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg) { this->send_message(msg); } #endif +#ifdef USE_SERIAL_PROXY +void APIConnection::on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) { + auto &proxies = App.get_serial_proxies(); + if (msg.instance >= proxies.size()) { + ESP_LOGW(TAG, "Serial proxy instance %u out of range (max %u)", msg.instance, + static_cast<uint32_t>(proxies.size())); + return; + } + proxies[msg.instance]->configure(msg.baudrate, msg.flow_control, static_cast<uint8_t>(msg.parity), msg.stop_bits, + msg.data_size); +} + +void APIConnection::on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) { + auto &proxies = App.get_serial_proxies(); + if (msg.instance >= proxies.size()) { + ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + return; + } + proxies[msg.instance]->write_from_client(msg.data, msg.data_len); +} + +void APIConnection::on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) { + auto &proxies = App.get_serial_proxies(); + if (msg.instance >= proxies.size()) { + ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + return; + } + proxies[msg.instance]->set_modem_pins(msg.line_states); +} + +void APIConnection::on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) { + auto &proxies = App.get_serial_proxies(); + if (msg.instance >= proxies.size()) { + ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + return; + } + SerialProxyGetModemPinsResponse resp{}; + resp.instance = msg.instance; + resp.line_states = proxies[msg.instance]->get_modem_pins(); + this->send_message(resp); +} + +void APIConnection::on_serial_proxy_request(const SerialProxyRequest &msg) { + auto &proxies = App.get_serial_proxies(); + if (msg.instance >= proxies.size()) { + ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + return; + } + switch (msg.type) { + case enums::SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE: + case enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: + proxies[msg.instance]->serial_proxy_request(this, msg.type); + break; + case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH: { + SerialProxyRequestResponse resp{}; + resp.instance = msg.instance; + resp.type = enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH; + switch (proxies[msg.instance]->flush_port()) { + case uart::FlushResult::SUCCESS: + resp.status = enums::SERIAL_PROXY_STATUS_OK; + break; + case uart::FlushResult::ASSUMED_SUCCESS: + resp.status = enums::SERIAL_PROXY_STATUS_ASSUMED_SUCCESS; + break; + case uart::FlushResult::TIMEOUT: + resp.status = enums::SERIAL_PROXY_STATUS_TIMEOUT; + break; + case uart::FlushResult::FAILED: + resp.status = enums::SERIAL_PROXY_STATUS_ERROR; + break; + } + this->send_message(resp); + break; + } + default: + ESP_LOGW(TAG, "Unknown serial proxy request type: %u", static_cast<uint32_t>(msg.type)); + break; + } +} + +void APIConnection::send_serial_proxy_data(const SerialProxyDataReceived &msg) { this->send_message(msg); } +#endif + #ifdef USE_INFRARED uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size) { auto *infrared = static_cast<infrared::Infrared *>(entity); @@ -1666,6 +1749,16 @@ bool APIConnection::send_device_info_response_() { resp.zwave_proxy_feature_flags = zwave_proxy::global_zwave_proxy->get_feature_flags(); resp.zwave_home_id = zwave_proxy::global_zwave_proxy->get_home_id(); #endif +#ifdef USE_SERIAL_PROXY + size_t serial_proxy_index = 0; + for (auto const &proxy : App.get_serial_proxies()) { + if (serial_proxy_index >= SERIAL_PROXY_COUNT) + break; + auto &info = resp.serial_proxies[serial_proxy_index++]; + info.name = StringRef(proxy->get_name()); + info.port_type = proxy->get_port_type(); + } +#endif #ifdef USE_API_NOISE resp.api_encryption_supported = true; #endif diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index b075bc83ab..5d1469e419 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -189,6 +189,15 @@ class APIConnection final : public APIServerConnectionBase { void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg); #endif +#ifdef USE_SERIAL_PROXY + void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) override; + void on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) override; + void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) override; + void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) override; + void on_serial_proxy_request(const SerialProxyRequest &msg) override; + void send_serial_proxy_data(const SerialProxyDataReceived &msg); +#endif + #ifdef USE_EVENT void send_event(event::Event *event); #endif @@ -254,6 +263,7 @@ class APIConnection final : public APIServerConnectionBase { return static_cast<ConnectionState>(this->flags_.connection_state) == ConnectionState::CONNECTED || this->is_authenticated(); } + bool is_marked_for_removal() const { return this->flags_.remove; } uint8_t get_log_subscription_level() const { return this->flags_.log_subscription; } // Get client API version for feature detection diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 38ebfb9464..6fce10ca0f 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3840,6 +3840,20 @@ bool SerialProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { } return true; } +void SerialProxyRequestResponse::encode(ProtoWriteBuffer &buffer) const { + buffer.encode_uint32(1, this->instance); + buffer.encode_uint32(2, static_cast<uint32_t>(this->type)); + buffer.encode_uint32(3, static_cast<uint32_t>(this->status)); + buffer.encode_string(4, this->error_message); +} +uint32_t SerialProxyRequestResponse::calculate_size() const { + uint32_t size = 0; + size += ProtoSize::calc_uint32(1, this->instance); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); + size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->status)); + size += ProtoSize::calc_length(1, this->error_message.size()); + return size; +} #endif #ifdef USE_BLUETOOTH_PROXY bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a6167dc810..5c712508b9 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -333,6 +333,13 @@ enum SerialProxyRequestType : uint32_t { SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE = 1, SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2, }; +enum SerialProxyStatus : uint32_t { + SERIAL_PROXY_STATUS_OK = 0, + SERIAL_PROXY_STATUS_ASSUMED_SUCCESS = 1, + SERIAL_PROXY_STATUS_ERROR = 2, + SERIAL_PROXY_STATUS_TIMEOUT = 3, + SERIAL_PROXY_STATUS_NOT_SUPPORTED = 4, +}; #endif } // namespace enums @@ -3220,6 +3227,25 @@ class SerialProxyRequest final : public ProtoDecodableMessage { protected: bool decode_varint(uint32_t field_id, ProtoVarInt value) override; }; +class SerialProxyRequestResponse final : public ProtoMessage { + public: + static constexpr uint8_t MESSAGE_TYPE = 147; + static constexpr uint8_t ESTIMATED_SIZE = 17; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *message_name() const override { return "serial_proxy_request_response"; } +#endif + uint32_t instance{0}; + enums::SerialProxyRequestType type{}; + enums::SerialProxyStatus status{}; + StringRef error_message{}; + void encode(ProtoWriteBuffer &buffer) const; + uint32_t calculate_size() const; +#ifdef HAS_PROTO_MESSAGE_DUMP + const char *dump_to(DumpBuffer &out) const override; +#endif + + protected: +}; #endif #ifdef USE_BLUETOOTH_PROXY class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 086b1bdc2f..740bf2e47f 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -789,6 +789,22 @@ template<> const char *proto_enum_to_string<enums::SerialProxyRequestType>(enums return "UNKNOWN"; } } +template<> const char *proto_enum_to_string<enums::SerialProxyStatus>(enums::SerialProxyStatus value) { + switch (value) { + case enums::SERIAL_PROXY_STATUS_OK: + return "SERIAL_PROXY_STATUS_OK"; + case enums::SERIAL_PROXY_STATUS_ASSUMED_SUCCESS: + return "SERIAL_PROXY_STATUS_ASSUMED_SUCCESS"; + case enums::SERIAL_PROXY_STATUS_ERROR: + return "SERIAL_PROXY_STATUS_ERROR"; + case enums::SERIAL_PROXY_STATUS_TIMEOUT: + return "SERIAL_PROXY_STATUS_TIMEOUT"; + case enums::SERIAL_PROXY_STATUS_NOT_SUPPORTED: + return "SERIAL_PROXY_STATUS_NOT_SUPPORTED"; + default: + return "UNKNOWN"; + } +} #endif const char *HelloRequest::dump_to(DumpBuffer &out) const { @@ -2609,6 +2625,14 @@ const char *SerialProxyRequest::dump_to(DumpBuffer &out) const { dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type)); return out.c_str(); } +const char *SerialProxyRequestResponse::dump_to(DumpBuffer &out) const { + MessageDumpHelper helper(out, "SerialProxyRequestResponse"); + dump_field(out, "instance", this->instance); + dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type)); + dump_field(out, "status", static_cast<enums::SerialProxyStatus>(this->status)); + dump_field(out, "error_message", this->error_message); + return out.c_str(); +} #endif #ifdef USE_BLUETOOTH_PROXY const char *BluetoothSetConnectionParamsRequest::dump_to(DumpBuffer &out) const { diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index a031d2d969..10fd88d8e1 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -233,6 +233,7 @@ class APIServerConnectionBase : public ProtoService { #ifdef USE_SERIAL_PROXY virtual void on_serial_proxy_request(const SerialProxyRequest &value){}; #endif + #ifdef USE_BLUETOOTH_PROXY virtual void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){}; #endif diff --git a/esphome/components/serial_proxy/__init__.py b/esphome/components/serial_proxy/__init__.py new file mode 100644 index 0000000000..f9b8c375d2 --- /dev/null +++ b/esphome/components/serial_proxy/__init__.py @@ -0,0 +1,104 @@ +""" +Serial Proxy component for ESPHome. + +WARNING: This component is EXPERIMENTAL. The API (both Python configuration +and C++ interfaces) may change at any time without following the normal +breaking changes policy. Use at your own risk. + +Once the API is considered stable, this warning will be removed. + +Provides a proxy to/from a serial interface on the ESPHome device, allowing +Home Assistant to connect to the serial port and send/receive data to/from +an arbitrary serial device. +""" + +from dataclasses import dataclass + +from esphome import pins +import esphome.codegen as cg +from esphome.components import uart +import esphome.config_validation as cv +from esphome.const import CONF_ID, CONF_NAME +from esphome.core import CORE, coroutine_with_priority +from esphome.coroutine import CoroPriority + +CODEOWNERS = ["@kbx81"] +DEPENDENCIES = ["api", "uart"] + +MULTI_CONF = True + +serial_proxy_ns = cg.esphome_ns.namespace("serial_proxy") +SerialProxy = serial_proxy_ns.class_("SerialProxy", cg.Component, uart.UARTDevice) + +api_enums_ns = cg.esphome_ns.namespace("api").namespace("enums") +SerialProxyPortType = api_enums_ns.enum("SerialProxyPortType") +SERIAL_PROXY_PORT_TYPES = { + "TTL": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_TTL, + "RS232": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_RS232, + "RS485": SerialProxyPortType.SERIAL_PROXY_PORT_TYPE_RS485, +} + +CONF_DTR_PIN = "dtr_pin" +CONF_PORT_TYPE = "port_type" +CONF_RTS_PIN = "rts_pin" + +DOMAIN = "serial_proxy" + + +@dataclass +class SerialProxyData: + count: int = 0 + + +def _get_data() -> SerialProxyData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = SerialProxyData() + return CORE.data[DOMAIN] + + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SerialProxy), + cv.Required(CONF_NAME): cv.string_strict, + cv.Required(CONF_PORT_TYPE): cv.enum(SERIAL_PROXY_PORT_TYPES, upper=True), + cv.Optional(CONF_RTS_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_DTR_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) + + +@coroutine_with_priority(CoroPriority.FINAL) +async def _add_serial_proxy_count_define(): + """Emit the SERIAL_PROXY_COUNT define once with the final instance count.""" + count = _get_data().count + if count > 0: + cg.add_define("SERIAL_PROXY_COUNT", count) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) + cg.add(cg.App.register_serial_proxy(var)) + cg.add(var.set_name(config[CONF_NAME])) + cg.add(var.set_port_type(config[CONF_PORT_TYPE])) + cg.add_define("USE_SERIAL_PROXY") + + # Track instance count for the FINAL priority define + data = _get_data() + if data.count == 0: + # Schedule the count define job only once (on the first instance) + CORE.add_job(_add_serial_proxy_count_define) + data.count += 1 + + if CONF_RTS_PIN in config: + rts_pin = await cg.gpio_pin_expression(config[CONF_RTS_PIN]) + cg.add(var.set_rts_pin(rts_pin)) + + if CONF_DTR_PIN in config: + dtr_pin = await cg.gpio_pin_expression(config[CONF_DTR_PIN]) + cg.add(var.set_dtr_pin(dtr_pin)) diff --git a/esphome/components/serial_proxy/serial_proxy.cpp b/esphome/components/serial_proxy/serial_proxy.cpp new file mode 100644 index 0000000000..340f9b0cb8 --- /dev/null +++ b/esphome/components/serial_proxy/serial_proxy.cpp @@ -0,0 +1,188 @@ +#include "serial_proxy.h" + +#ifdef USE_SERIAL_PROXY + +#include "esphome/core/log.h" +#include "esphome/core/util.h" + +#ifdef USE_API +#include "esphome/components/api/api_connection.h" +#include "esphome/components/api/api_server.h" +#endif + +namespace esphome::serial_proxy { + +static const char *const TAG = "serial_proxy"; + +void SerialProxy::setup() { + // Set up modem control pins if configured + if (this->rts_pin_ != nullptr) { + this->rts_pin_->setup(); + this->rts_pin_->digital_write(this->rts_state_); + } + if (this->dtr_pin_ != nullptr) { + this->dtr_pin_->setup(); + this->dtr_pin_->digital_write(this->dtr_state_); + } +#ifdef USE_API + // instance_index_ is fixed at registration time; pre-set it so loop() only needs to update data + this->outgoing_msg_.instance = this->instance_index_; +#endif +} + +void SerialProxy::loop() { +#ifdef USE_API + // Detect subscriber disconnect + if (this->api_connection_ != nullptr && (this->api_connection_->is_marked_for_removal() || + !this->api_connection_->is_connection_setup() || !api_is_connected())) { + ESP_LOGW(TAG, "Subscriber disconnected"); + this->api_connection_ = nullptr; + } + + if (this->api_connection_ == nullptr) + return; + + // Read available data from UART and forward to subscribed client + size_t available = this->available(); + if (available == 0) + return; + + // Read in chunks up to SERIAL_PROXY_MAX_READ_SIZE + uint8_t buffer[SERIAL_PROXY_MAX_READ_SIZE]; + size_t to_read = std::min(available, sizeof(buffer)); + + if (!this->read_array(buffer, to_read)) + return; + + this->outgoing_msg_.set_data(buffer, to_read); + this->api_connection_->send_serial_proxy_data(this->outgoing_msg_); +#endif +} + +void SerialProxy::dump_config() { + ESP_LOGCONFIG(TAG, + "Serial Proxy [%u]:\n" + " Name: %s\n" + " Port Type: %s\n" + " RTS Pin: %s\n" + " DTR Pin: %s", + this->instance_index_, this->name_ != nullptr ? this->name_ : "", + this->port_type_ == api::enums::SERIAL_PROXY_PORT_TYPE_RS485 ? "RS485" + : this->port_type_ == api::enums::SERIAL_PROXY_PORT_TYPE_RS232 ? "RS232" + : "TTL", + this->rts_pin_ != nullptr ? "configured" : "not configured", + this->dtr_pin_ != nullptr ? "configured" : "not configured"); +} + +void SerialProxy::configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits, + uint8_t data_size) { + ESP_LOGD(TAG, "Configuring serial proxy [%u]: baud=%u, flow_ctrl=%s, parity=%u, stop=%u, data=%u", + this->instance_index_, baudrate, YESNO(flow_control), parity, stop_bits, data_size); + + auto *uart_comp = this->parent_; + if (uart_comp == nullptr) { + ESP_LOGE(TAG, "UART component not available"); + return; + } + + // Validate all parameters before applying any (values come from a remote client) + if (baudrate == 0) { + ESP_LOGW(TAG, "Invalid baud rate: 0"); + return; + } + if (stop_bits < 1 || stop_bits > 2) { + ESP_LOGW(TAG, "Invalid stop bits: %u (must be 1 or 2)", stop_bits); + return; + } + if (data_size < 5 || data_size > 8) { + ESP_LOGW(TAG, "Invalid data bits: %u (must be 5-8)", data_size); + return; + } + if (parity > 2) { + ESP_LOGW(TAG, "Invalid parity: %u (must be 0-2)", parity); + return; + } + + // Apply validated parameters + uart_comp->set_baud_rate(baudrate); + uart_comp->set_stop_bits(stop_bits); + uart_comp->set_data_bits(data_size); + + // Map parity value to UARTParityOptions + static const uart::UARTParityOptions PARITY_MAP[] = { + uart::UART_CONFIG_PARITY_NONE, + uart::UART_CONFIG_PARITY_EVEN, + uart::UART_CONFIG_PARITY_ODD, + }; + uart_comp->set_parity(PARITY_MAP[parity]); + + // load_settings() is available on ESP8266 and ESP32 platforms +#if defined(USE_ESP8266) || defined(USE_ESP32) + uart_comp->load_settings(true); +#endif + + if (flow_control) { + ESP_LOGW(TAG, "Hardware flow control requested but is not yet supported"); + } +} + +void SerialProxy::write_from_client(const uint8_t *data, size_t len) { + if (data == nullptr || len == 0) + return; + this->write_array(data, len); +} + +void SerialProxy::set_modem_pins(uint32_t line_states) { + const bool rts = (line_states & SERIAL_PROXY_LINE_STATE_FLAG_RTS) != 0; + const bool dtr = (line_states & SERIAL_PROXY_LINE_STATE_FLAG_DTR) != 0; + ESP_LOGV(TAG, "Setting modem pins [%u]: RTS=%s, DTR=%s", this->instance_index_, ONOFF(rts), ONOFF(dtr)); + + if (this->rts_pin_ != nullptr) { + this->rts_state_ = rts; + this->rts_pin_->digital_write(rts); + } + if (this->dtr_pin_ != nullptr) { + this->dtr_state_ = dtr; + this->dtr_pin_->digital_write(dtr); + } +} + +uint32_t SerialProxy::get_modem_pins() const { + return (this->rts_state_ ? SERIAL_PROXY_LINE_STATE_FLAG_RTS : 0u) | + (this->dtr_state_ ? SERIAL_PROXY_LINE_STATE_FLAG_DTR : 0u); +} + +uart::FlushResult SerialProxy::flush_port() { + ESP_LOGV(TAG, "Flushing serial proxy [%u]", this->instance_index_); + return this->flush(); +} + +#ifdef USE_API +void SerialProxy::serial_proxy_request(api::APIConnection *api_connection, api::enums::SerialProxyRequestType type) { + switch (type) { + case api::enums::SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE: + if (this->api_connection_ != nullptr) { + ESP_LOGE(TAG, "Only one API subscription is allowed at a time"); + return; + } + this->api_connection_ = api_connection; + ESP_LOGV(TAG, "API connection subscribed to serial proxy [%u]", this->instance_index_); + break; + case api::enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: + if (this->api_connection_ != api_connection) { + ESP_LOGV(TAG, "API connection is not subscribed to serial proxy [%u]", this->instance_index_); + return; + } + this->api_connection_ = nullptr; + ESP_LOGV(TAG, "API connection unsubscribed from serial proxy [%u]", this->instance_index_); + break; + default: + ESP_LOGW(TAG, "Unknown serial proxy request type: %u", static_cast<uint32_t>(type)); + break; + } +} +#endif + +} // namespace esphome::serial_proxy + +#endif // USE_SERIAL_PROXY diff --git a/esphome/components/serial_proxy/serial_proxy.h b/esphome/components/serial_proxy/serial_proxy.h new file mode 100644 index 0000000000..52f0654ff0 --- /dev/null +++ b/esphome/components/serial_proxy/serial_proxy.h @@ -0,0 +1,129 @@ +#pragma once + +// WARNING: This component is EXPERIMENTAL. The API may change at any time +// without following the normal breaking changes policy. Use at your own risk. +// Once the API is considered stable, this warning will be removed. + +#include "esphome/core/defines.h" + +#ifdef USE_SERIAL_PROXY + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/uart/uart.h" + +// Include api_pb2.h only when the API is enabled. The full include is needed +// to hold SerialProxyDataReceived by value as a pre-allocated member. +// Guarding prevents pulling conflicting Zephyr logging macro names into +// translation units that include this header without USE_API defined. +#ifdef USE_API +#include "esphome/components/api/api_pb2.h" +#endif + +// Forward-declare types needed outside the USE_API guard. +namespace esphome::api { +class APIConnection; +namespace enums { +enum SerialProxyPortType : uint32_t; +enum SerialProxyRequestType : uint32_t; +} // namespace enums +} // namespace esphome::api + +namespace esphome::serial_proxy { + +/// Bit flags for the line_states field exchanged with API clients. +/// Bit positions are stable API — new signals must use the next available bit. +enum SerialProxyLineStateFlag : uint32_t { + SERIAL_PROXY_LINE_STATE_FLAG_RTS = 1 << 0, ///< RTS (Request To Send) + SERIAL_PROXY_LINE_STATE_FLAG_DTR = 1 << 1, ///< DTR (Data Terminal Ready) +}; + +/// Maximum bytes to read from UART in a single loop iteration +inline constexpr size_t SERIAL_PROXY_MAX_READ_SIZE = 256; + +class SerialProxy : public uart::UARTDevice, public Component { + public: + void setup() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; } + + /// Get the instance index (position in Application's serial_proxies_ vector) + uint32_t get_instance_index() const { return this->instance_index_; } + + /// Set the instance index (called by Application::register_serial_proxy) + void set_instance_index(uint32_t index) { this->instance_index_ = index; } + + /// Set the human-readable port name (from YAML configuration) + void set_name(const char *name) { this->name_ = name; } + + /// Get the human-readable port name + const char *get_name() const { return this->name_; } + + /// Set the port type (from YAML configuration) + void set_port_type(api::enums::SerialProxyPortType port_type) { this->port_type_ = port_type; } + + /// Get the port type + api::enums::SerialProxyPortType get_port_type() const { return this->port_type_; } + + /// Configure UART parameters and apply them + /// @param baudrate Baud rate in bits per second + /// @param flow_control True to enable hardware flow control + /// @param parity Parity setting (0=none, 1=even, 2=odd) + /// @param stop_bits Number of stop bits (1 or 2) + /// @param data_size Number of data bits (5-8) + void configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits, uint8_t data_size); + + /// Handle a subscribe/unsubscribe request from an API client + void serial_proxy_request(api::APIConnection *api_connection, api::enums::SerialProxyRequestType type); + + /// Write data received from an API client to the serial device + /// @param data Pointer to data buffer + /// @param len Number of bytes to write + void write_from_client(const uint8_t *data, size_t len); + + /// Set modem pin states from a bitmask of SerialProxyLineStateFlag values + void set_modem_pins(uint32_t line_states); + + /// Get current modem pin states as a bitmask of SerialProxyLineStateFlag values + uint32_t get_modem_pins() const; + + /// Flush the serial port (block until all TX data is sent) + uart::FlushResult flush_port(); + + /// Set the RTS GPIO pin (from YAML configuration) + void set_rts_pin(GPIOPin *pin) { this->rts_pin_ = pin; } + + /// Set the DTR GPIO pin (from YAML configuration) + void set_dtr_pin(GPIOPin *pin) { this->dtr_pin_ = pin; } + + protected: + /// Instance index for identifying this proxy in API messages + uint32_t instance_index_{0}; + + /// Subscribed API client (only one allowed at a time) + api::APIConnection *api_connection_{nullptr}; + +#ifdef USE_API + /// Pre-allocated outgoing message; instance field is set once in setup() + api::SerialProxyDataReceived outgoing_msg_; +#endif + + /// Human-readable port name (points to a string literal in flash) + const char *name_{nullptr}; + + /// Port type + api::enums::SerialProxyPortType port_type_{}; + + /// Optional GPIO pins for modem control + GPIOPin *rts_pin_{nullptr}; + GPIOPin *dtr_pin_{nullptr}; + + /// Current modem pin states + bool rts_state_{false}; + bool dtr_state_{false}; +}; + +} // namespace esphome::serial_proxy + +#endif // USE_SERIAL_PROXY diff --git a/esphome/core/application.h b/esphome/core/application.h index 87f9fdf59a..49253b6324 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -102,6 +102,9 @@ void socket_wake(); // NOLINT(readability-redundant-declaration) #ifdef USE_INFRARED #include "esphome/components/infrared/infrared.h" #endif +#ifdef USE_SERIAL_PROXY +#include "esphome/components/serial_proxy/serial_proxy.h" +#endif #ifdef USE_EVENT #include "esphome/components/event/event.h" #endif @@ -267,6 +270,13 @@ class Application { void register_infrared(infrared::Infrared *infrared) { this->infrareds_.push_back(infrared); } #endif +#ifdef USE_SERIAL_PROXY + void register_serial_proxy(serial_proxy::SerialProxy *proxy) { + proxy->set_instance_index(this->serial_proxies_.size()); + this->serial_proxies_.push_back(proxy); + } +#endif + #ifdef USE_EVENT void register_event(event::Event *event) { this->events_.push_back(event); } #endif @@ -498,6 +508,10 @@ class Application { GET_ENTITY_METHOD(infrared::Infrared, infrared, infrareds) #endif +#ifdef USE_SERIAL_PROXY + auto &get_serial_proxies() const { return this->serial_proxies_; } +#endif + #ifdef USE_EVENT auto &get_events() const { return this->events_; } GET_ENTITY_METHOD(event::Event, event, events) @@ -747,6 +761,9 @@ class Application { #ifdef USE_INFRARED StaticVector<infrared::Infrared *, ESPHOME_ENTITY_INFRARED_COUNT> infrareds_{}; #endif +#ifdef USE_SERIAL_PROXY + StaticVector<serial_proxy::SerialProxy *, SERIAL_PROXY_COUNT> serial_proxies_{}; +#endif #ifdef USE_UPDATE StaticVector<update::UpdateEntity *, ESPHOME_ENTITY_UPDATE_COUNT> updates_{}; #endif diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 48c467f69f..51f474d80e 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -107,6 +107,7 @@ #define MDNS_SERVICE_COUNT 3 #define USE_MDNS_DYNAMIC_TXT #define MDNS_DYNAMIC_TXT_COUNT 2 +#define SERIAL_PROXY_COUNT 2 #define SNTP_SERVER_COUNT 3 #define USE_MEDIA_PLAYER #define USE_MEDIA_SOURCE @@ -119,6 +120,7 @@ #define USE_SELECT #define USE_SENSOR #define USE_SENSOR_FILTER +#define USE_SERIAL_PROXY #define USE_SETUP_PRIORITY_OVERRIDE #define USE_STATUS_LED #define USE_STATUS_SENSOR diff --git a/tests/components/serial_proxy/common.yaml b/tests/components/serial_proxy/common.yaml new file mode 100644 index 0000000000..6f03cf95df --- /dev/null +++ b/tests/components/serial_proxy/common.yaml @@ -0,0 +1,10 @@ +wifi: + ssid: MySSID + password: password1 + +api: + +serial_proxy: + - id: serial_proxy_1 + name: Test Serial Port + port_type: RS232 diff --git a/tests/components/serial_proxy/test.esp32-idf.yaml b/tests/components/serial_proxy/test.esp32-idf.yaml new file mode 100644 index 0000000000..b415125e84 --- /dev/null +++ b/tests/components/serial_proxy/test.esp32-idf.yaml @@ -0,0 +1,8 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + uart: !include ../../test_build_components/common/uart/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/serial_proxy/test.esp8266-ard.yaml b/tests/components/serial_proxy/test.esp8266-ard.yaml new file mode 100644 index 0000000000..96ab4ef6ac --- /dev/null +++ b/tests/components/serial_proxy/test.esp8266-ard.yaml @@ -0,0 +1,8 @@ +substitutions: + tx_pin: GPIO0 + rx_pin: GPIO2 + +packages: + uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/serial_proxy/test.rp2040-ard.yaml b/tests/components/serial_proxy/test.rp2040-ard.yaml new file mode 100644 index 0000000000..b28f2b5e05 --- /dev/null +++ b/tests/components/serial_proxy/test.rp2040-ard.yaml @@ -0,0 +1,8 @@ +substitutions: + tx_pin: GPIO4 + rx_pin: GPIO5 + +packages: + uart: !include ../../test_build_components/common/uart/rp2040-ard.yaml + +<<: !include common.yaml From a9b5f95c768c58aeb4e117a94effe0121fdb77c2 Mon Sep 17 00:00:00 2001 From: Oliver Kleinecke <okleinecke@web.de> Date: Sun, 8 Mar 2026 11:24:39 +0100 Subject: [PATCH 1208/2030] [usb_uart] ch34x chip-type & port-count enumeration (#14544) --- esphome/components/usb_uart/ch34x.cpp | 94 ++++++++++++++++++++++++-- esphome/components/usb_uart/usb_uart.h | 37 ++++++++++ 2 files changed, 126 insertions(+), 5 deletions(-) diff --git a/esphome/components/usb_uart/ch34x.cpp b/esphome/components/usb_uart/ch34x.cpp index e6e52a9e2a..d5428cc8d7 100644 --- a/esphome/components/usb_uart/ch34x.cpp +++ b/esphome/components/usb_uart/ch34x.cpp @@ -8,13 +8,97 @@ namespace esphome::usb_uart { using namespace bytebuffer; -/** - * CH34x - */ + +struct CH34xEntry { + uint16_t pid; + uint8_t byte_idx; // which status.data[] byte to inspect + uint8_t mask; // bitmask applied before comparison + uint8_t match; // 0xFF = wildcard (default/fallthrough for this PID) + CH34xChipType chiptype; + const char *name; + uint8_t num_ports; +}; + +static const CH34xEntry CH34X_TABLE[] = { + {0x55D2, 1, 0xFF, 0x41, CHIP_CH342K, "CH342K", 2}, + {0x55D2, 1, 0xFF, 0xFF, CHIP_CH342F, "CH342F", 2}, + {0x55D3, 1, 0xFF, 0x02, CHIP_CH343J, "CH343J", 1}, + {0x55D3, 1, 0xFF, 0x01, CHIP_CH343K, "CH343K", 1}, + {0x55D3, 1, 0xFF, 0x18, CHIP_CH343G_AUTOBAUD, "CH343G_AUTOBAUD", 1}, + {0x55D3, 1, 0xFF, 0xFF, CHIP_CH343GP, "CH343GP", 1}, + {0x55D4, 1, 0xFF, 0x09, CHIP_CH9102X, "CH9102X", 1}, + {0x55D4, 1, 0xFF, 0xFF, CHIP_CH9102F, "CH9102F", 1}, + {0x55D5, 1, 0xFF, 0xC0, CHIP_CH344L, "CH344L", 4}, // CH344L vs CH344L_V2 resolved below + {0x55D5, 1, 0xFF, 0xFF, CHIP_CH344Q, "CH344Q", 4}, + {0x55D7, 1, 0xFF, 0xFF, CHIP_CH9103M, "CH9103M", 2}, + {0x55D8, 1, 0xFF, 0x0A, CHIP_CH9101RY, "CH9101RY", 1}, + {0x55D8, 1, 0xFF, 0xFF, CHIP_CH9101UH, "CH9101UH", 1}, + {0x55DB, 1, 0xFF, 0xFF, CHIP_CH347TF, "CH347TF", 1}, + {0x55DD, 1, 0xFF, 0xFF, CHIP_CH347TF, "CH347TF", 1}, + {0x55DA, 1, 0xFF, 0xFF, CHIP_CH347TF, "CH347TF", 2}, + {0x55DE, 1, 0xFF, 0xFF, CHIP_CH347TF, "CH347TF", 2}, + {0x55E7, 1, 0xFF, 0xFF, CHIP_CH339W, "CH339W", 1}, + {0x55DF, 1, 0xFF, 0xFF, CHIP_CH9104L, "CH9104L", 4}, + {0x55E9, 1, 0xFF, 0xFF, CHIP_CH9111L_M0, "CH9111L_M0", 1}, + {0x55EA, 1, 0xFF, 0xFF, CHIP_CH9111L_M1, "CH9111L_M1", 1}, + {0x55E8, 2, 0xFF, 0x48, CHIP_CH9114L, "CH9114L", 4}, + {0x55E8, 2, 0xFF, 0x49, CHIP_CH9114W, "CH9114W", 4}, + {0x55E8, 2, 0xFF, 0x4A, CHIP_CH9114F, "CH9114F", 4}, + {0x55EB, 4, 0x01, 0x01, CHIP_CH346C_M1, "CH346C_M1", 1}, + {0x55EB, 4, 0x01, 0xFF, CHIP_CH346C_M0, "CH346C_M0", 1}, + {0x55EC, 1, 0xFF, 0xFF, CHIP_CH346C_M2, "CH346C_M2", 2}, +}; void USBUartTypeCH34X::enable_channels() { - // enable the channels - for (auto channel : this->channels_) { + usb_host::transfer_cb_t cb = [this](const usb_host::TransferStatus &status) { + if (!status.success) { + this->defer([this, error_code = status.error_code]() { + ESP_LOGE(TAG, "CH34x chip detection failed: %s", esp_err_to_name(error_code)); + this->apply_line_settings_(); + }); + return; + } + CH34xChipType chiptype = CHIP_UNKNOWN; + uint8_t num_ports = 1; + for (const auto &e : CH34X_TABLE) { + if (e.pid != this->pid_) + continue; + if (e.match != 0xFF && (status.data[e.byte_idx] & e.mask) != e.match) + continue; + chiptype = e.chiptype; + num_ports = e.num_ports; + break; + } + // CH344L vs CH344L_V2 requires chipver (data[0]) in addition to chiptype (data[1]) + if (chiptype == CHIP_CH344L && (status.data[0] & 0xF0) != 0x40) + chiptype = CHIP_CH344L_V2; + const char *name = "unknown"; + for (const auto &e : CH34X_TABLE) { + if (e.chiptype == chiptype) { + name = e.name; + break; + } + } + this->defer([this, chiptype, num_ports, name]() { + this->chiptype_ = chiptype; + this->chip_name_ = name; + this->num_ports_ = num_ports; + ESP_LOGD(TAG, "CH34x chip: %s, ports: %u", name, this->num_ports_); + this->apply_line_settings_(); + }); + }; + // Vendor-specific GET_CHIP_VERSION request (bRequest=0x5F): returns chip ID bytes + // used to distinguish CH34x variants sharing the same PID. + this->control_transfer(USB_VENDOR_DEV | usb_host::USB_DIR_IN, 0x5F, 0, 0, cb, {0, 0, 0, 0, 0, 0, 0, 0}); +} + +void USBUartTypeCH34X::dump_config() { + USBUartTypeCdcAcm::dump_config(); + ESP_LOGCONFIG(TAG, " CH34x chip: %s", this->chip_name_); +} + +void USBUartTypeCH34X::apply_line_settings_() { + for (auto *channel : this->channels_) { if (!channel->initialised_.load()) continue; usb_host::transfer_cb_t callback = [=](const usb_host::TransferStatus &status) { diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index b1748aebf2..16469df7f6 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -35,6 +35,36 @@ struct CdcEps { uint8_t interrupt_interface_number; }; +enum CH34xChipType : uint8_t { + CHIP_CH342F = 0, + CHIP_CH342K, + CHIP_CH343GP, + CHIP_CH343G_AUTOBAUD, + CHIP_CH343K, + CHIP_CH343J, + CHIP_CH344L, + CHIP_CH344L_V2, + CHIP_CH344Q, + CHIP_CH347TF, + CHIP_CH9101UH, + CHIP_CH9101RY, + CHIP_CH9102F, + CHIP_CH9102X, + CHIP_CH9103M, + CHIP_CH9104L, + CHIP_CH340B, + CHIP_CH339W, + CHIP_CH9111L_M0, + CHIP_CH9111L_M1, + CHIP_CH9114L, + CHIP_CH9114W, + CHIP_CH9114F, + CHIP_CH346C_M0, + CHIP_CH346C_M1, + CHIP_CH346C_M2, + CHIP_UNKNOWN = 0xFF, +}; + enum UARTParityOptions { UART_CONFIG_PARITY_NONE = 0, UART_CONFIG_PARITY_ODD, @@ -192,10 +222,17 @@ class USBUartTypeCP210X : public USBUartTypeCdcAcm { class USBUartTypeCH34X : public USBUartTypeCdcAcm { public: USBUartTypeCH34X(uint16_t vid, uint16_t pid) : USBUartTypeCdcAcm(vid, pid) {} + void dump_config() override; protected: void enable_channels() override; std::vector<CdcEps> parse_descriptors(usb_device_handle_t dev_hdl) override; + + private: + void apply_line_settings_(); + CH34xChipType chiptype_{CHIP_UNKNOWN}; + const char *chip_name_{"unknown"}; + uint8_t num_ports_{1}; }; } // namespace esphome::usb_uart From 3f143d9f19ae29a408f1024e202aa869e86a7787 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Sun, 8 Mar 2026 14:50:32 +0100 Subject: [PATCH 1209/2030] [ethernet] Fix commit 3f700bac1cebf7eb6ff3b20a87d8c8af5cb9fc41 (#14618) --- esphome/components/ethernet/esp_eth_phy_jl1101.c | 2 ++ esphome/components/ethernet/ethernet_component.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/ethernet/esp_eth_phy_jl1101.c b/esphome/components/ethernet/esp_eth_phy_jl1101.c index a19f7aa6b0..b81d8227d4 100644 --- a/esphome/components/ethernet/esp_eth_phy_jl1101.c +++ b/esphome/components/ethernet/esp_eth_phy_jl1101.c @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include "esphome/core/defines.h" + #ifdef USE_ESP32 #include <string.h> diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index e54e1543e3..d9f05be9de 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -214,7 +214,7 @@ class EthernetComponent : public Component { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern EthernetComponent *global_eth_component; -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) extern "C" esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config); #endif From 1b3a7f0b6a8d927d50348b59979cae2aaa437f99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:18:14 +0000 Subject: [PATCH 1210/2030] Bump aioesphomeapi from 44.5.0 to 44.5.1 (#14624) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 03a7cac5c7..3da2d52b44 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.5.0 +aioesphomeapi==44.5.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 9be1876fae30e97e763480eb4e73ecaf3a4fa445 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Sun, 8 Mar 2026 21:52:16 +0100 Subject: [PATCH 1211/2030] [ble_nus] make ble_nus timeout shorter than watchdog (#14619) Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/ble_nus/ble_nus.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index e38dc99802..d0d37dbf1c 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -71,7 +71,10 @@ bool BLENUS::read_array(uint8_t *data, size_t len) { this->has_peek_ = false; data++; if (--len == 0) { // Decrement len first, then check it... - return true; // No more to read +#ifdef USE_UART_DEBUGGER + this->debug_callback_.call(uart::UART_DIRECTION_RX, this->peek_buffer_); +#endif + return true; // No more to read } } @@ -101,10 +104,10 @@ size_t BLENUS::available() { } uart::FlushResult BLENUS::flush() { - constexpr uint32_t timeout_5sec = 5000; + constexpr uint32_t timeout_500ms = 500; uint32_t start = millis(); while (atomic_get(&this->tx_status_) != TX_DISABLED && !ring_buf_is_empty(&global_ble_tx_ring_buf)) { - if (millis() - start > timeout_5sec) { + if (millis() - start > timeout_500ms) { ESP_LOGW(TAG, "Flush timeout"); return uart::FlushResult::TIMEOUT; } From ad5811280aaa9bce7ecfa49ea4c280522d5ac2c9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 10:59:43 -1000 Subject: [PATCH 1212/2030] =?UTF-8?q?[ci]=20Add=20medium-pr=20label=20for?= =?UTF-8?q?=20PRs=20with=20=E2=89=A4100=20lines=20changed=20(#14628)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/scripts/auto-label-pr/constants.js | 1 + .github/scripts/auto-label-pr/detectors.js | 7 ++++++- .github/scripts/auto-label-pr/index.js | 3 ++- .github/workflows/auto-label-pr.yml | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/scripts/auto-label-pr/constants.js b/.github/scripts/auto-label-pr/constants.js index 8c3a62cf19..1c33772c4c 100644 --- a/.github/scripts/auto-label-pr/constants.js +++ b/.github/scripts/auto-label-pr/constants.js @@ -14,6 +14,7 @@ module.exports = { 'chained-pr', 'core', 'small-pr', + 'medium-pr', 'dashboard', 'github-actions', 'by-code-owner', diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index 832fcb41db..fc63198019 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -103,7 +103,7 @@ async function detectCoreChanges(changedFiles) { } // Strategy: PR size detection -async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, TOO_BIG_THRESHOLD) { +async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD) { const labels = new Set(); if (totalChanges <= SMALL_PR_THRESHOLD) { @@ -111,6 +111,11 @@ async function detectPRSize(prFiles, totalAdditions, totalDeletions, totalChange return labels; } + if (totalChanges <= MEDIUM_PR_THRESHOLD) { + labels.add('medium-pr'); + return labels; + } + const testAdditions = prFiles .filter(file => file.filename.startsWith('tests/')) .reduce((sum, file) => sum + (file.additions || 0), 0); diff --git a/.github/scripts/auto-label-pr/index.js b/.github/scripts/auto-label-pr/index.js index 483d2cb626..42588c0bc8 100644 --- a/.github/scripts/auto-label-pr/index.js +++ b/.github/scripts/auto-label-pr/index.js @@ -35,6 +35,7 @@ async function fetchApiData() { module.exports = async ({ github, context }) => { // Environment variables const SMALL_PR_THRESHOLD = parseInt(process.env.SMALL_PR_THRESHOLD); + const MEDIUM_PR_THRESHOLD = parseInt(process.env.MEDIUM_PR_THRESHOLD); const MAX_LABELS = parseInt(process.env.MAX_LABELS); const TOO_BIG_THRESHOLD = parseInt(process.env.TOO_BIG_THRESHOLD); const COMPONENT_LABEL_THRESHOLD = parseInt(process.env.COMPONENT_LABEL_THRESHOLD); @@ -120,7 +121,7 @@ module.exports = async ({ github, context }) => { detectNewComponents(prFiles), detectNewPlatforms(prFiles, apiData), detectCoreChanges(changedFiles), - detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, TOO_BIG_THRESHOLD), + detectPRSize(prFiles, totalAdditions, totalDeletions, totalChanges, isMegaPR, SMALL_PR_THRESHOLD, MEDIUM_PR_THRESHOLD, TOO_BIG_THRESHOLD), detectDashboardChanges(changedFiles), detectGitHubActionsChanges(changedFiles), detectCodeOwner(github, context, changedFiles), diff --git a/.github/workflows/auto-label-pr.yml b/.github/workflows/auto-label-pr.yml index 6fcb50b70a..6376cf877e 100644 --- a/.github/workflows/auto-label-pr.yml +++ b/.github/workflows/auto-label-pr.yml @@ -12,6 +12,7 @@ permissions: env: SMALL_PR_THRESHOLD: 30 + MEDIUM_PR_THRESHOLD: 100 MAX_LABELS: 15 TOO_BIG_THRESHOLD: 1000 COMPONENT_LABEL_THRESHOLD: 10 From 50b3f9d25cb91b31fb0adc6bad090f2f5bb3d778 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Sun, 8 Mar 2026 17:09:06 -0500 Subject: [PATCH 1213/2030] [mixer_speaker] Add task debounce (#14581) --- .../mixer/speaker/mixer_speaker.cpp | 25 ++++++++++++++----- .../components/mixer/speaker/mixer_speaker.h | 7 +++--- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 8e1278206f..9d11abb327 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -11,14 +11,14 @@ #include <array> #include <cstring> -namespace esphome { -namespace mixer_speaker { +namespace esphome::mixer_speaker { static const UBaseType_t MIXER_TASK_PRIORITY = 10; static const uint32_t STOPPING_TIMEOUT_MS = 5000; static const uint32_t TRANSFER_BUFFER_DURATION_MS = 50; static const uint32_t TASK_DELAY_MS = 25; +static const uint32_t MIXER_AUTO_STOP_DEBOUNCE_MS = 200; static const size_t TASK_STACK_SIZE = 4096; @@ -471,6 +471,7 @@ void MixerSpeaker::loop() { this->task_.deallocate(); ESP_LOGD(TAG, "Stopped"); xEventGroupClearBits(this->event_group_, MIXER_TASK_ALL_BITS); + this->all_stopped_since_ms_ = 0; } if (this->task_.is_created()) { @@ -483,8 +484,18 @@ void MixerSpeaker::loop() { } if (all_stopped) { - // Send stop command signal to the mixer task since no source speakers are active - xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_STOP); + if (this->all_stopped_since_ms_ == 0) { + this->all_stopped_since_ms_ = millis(); + } else if ((millis() - this->all_stopped_since_ms_) >= MIXER_AUTO_STOP_DEBOUNCE_MS) { + // Send stop command only after a short debounce to avoid stop/start thrash during rapid seeks. + xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_STOP); + } + } else { + this->all_stopped_since_ms_ = 0; + // New activity detected; clear any stale auto-stop request before it can stop the running task. + if (event_group_bits & MIXER_TASK_COMMAND_STOP) { + xEventGroupClearBits(this->event_group_, MIXER_TASK_COMMAND_STOP); + } } } else { // Task is fully stopped and cleaned up, check if we can disable loop @@ -515,6 +526,9 @@ esp_err_t MixerSpeaker::start(audio::AudioStreamInfo &stream_info) { this->enable_loop_soon_any_context(); // ensure loop processes command + // Starting a new stream supersedes any previously queued stop request. + xEventGroupClearBits(this->event_group_, MIXER_TASK_COMMAND_STOP); + uint32_t event_bits = xEventGroupGetBits(this->event_group_); if (!(event_bits & MIXER_TASK_COMMAND_START)) { // Set MIXER_TASK_COMMAND_START bit if not already set, and then immediately wake for low latency @@ -755,7 +769,6 @@ void MixerSpeaker::audio_mixer_task(void *params) { vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } -} // namespace mixer_speaker -} // namespace esphome +} // namespace esphome::mixer_speaker #endif diff --git a/esphome/components/mixer/speaker/mixer_speaker.h b/esphome/components/mixer/speaker/mixer_speaker.h index 0e0b33c39b..29876ea262 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.h +++ b/esphome/components/mixer/speaker/mixer_speaker.h @@ -14,8 +14,7 @@ #include <atomic> -namespace esphome { -namespace mixer_speaker { +namespace esphome::mixer_speaker { /* Classes for mixing several source speaker audio streams and writing it to another speaker component. * - Volume controls are passed through to the output speaker @@ -200,9 +199,9 @@ class MixerSpeaker : public Component { optional<audio::AudioStreamInfo> audio_stream_info_; std::atomic<uint32_t> frames_in_pipeline_{0}; // Frames written to output but not yet played + uint32_t all_stopped_since_ms_{0}; // Debounce transient all-stopped windows before stopping task }; -} // namespace mixer_speaker -} // namespace esphome +} // namespace esphome::mixer_speaker #endif From d5dc4a39cb6f10fef73d4950fd21db3beca0f83a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:10:43 -0400 Subject: [PATCH 1214/2030] [i2s_audio] Fix mono sample swap and block 8-bit mono on ESP32 (#14516) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- .../components/i2s_audio/microphone/__init__.py | 6 ++++++ .../microphone/i2s_audio_microphone.cpp | 17 +++++++++-------- .../components/i2s_audio/speaker/__init__.py | 13 +++++++++---- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 16 ++++++++-------- .../speaker/media_player/audio_pipeline.cpp | 2 +- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index dd23673db5..bf583b9f81 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -46,6 +46,12 @@ def _validate_esp32_variant(config): if config[CONF_ADC_TYPE] == "external": if config[CONF_PDM] and variant not in PDM_VARIANTS: raise cv.Invalid(f"{variant} does not support PDM") + if ( + variant == esp32.VARIANT_ESP32 + and config.get(CONF_BITS_PER_SAMPLE) == 8 + and config.get(CONF_CHANNEL) in (CONF_LEFT, CONF_RIGHT) + ): + raise cv.Invalid("8-bit mono mode is not supported on ESP32") return config if config[CONF_ADC_TYPE] == "internal": if variant not in INTERNAL_ADC_VARIANTS: diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index cdebc214e2..eb4506071e 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -281,7 +281,7 @@ bool I2SAudioMicrophone::start_driver_() { } /* Before reading data, start the RX channel first */ - i2s_channel_enable(this->rx_handle_); + err = i2s_channel_enable(this->rx_handle_); if (err != ESP_OK) { ESP_LOGE(TAG, "Enabling failed: %s", esp_err_to_name(err)); return false; @@ -454,13 +454,14 @@ size_t I2SAudioMicrophone::read_(uint8_t *buf, size_t len, TickType_t ticks_to_w } this->status_clear_warning(); #if defined(USE_ESP32_VARIANT_ESP32) and not defined(USE_I2S_LEGACY) - // For ESP32 8/16 bit standard mono mode samples need to be switched. - if (this->slot_mode_ == I2S_SLOT_MODE_MONO && this->slot_bit_width_ <= 16 && !this->pdm_) { - size_t samples_read = bytes_read / sizeof(int16_t); - for (int i = 0; i < samples_read; i += 2) { - int16_t tmp = buf[i]; - buf[i] = buf[i + 1]; - buf[i + 1] = tmp; + // For ESP32 16-bit standard mono mode, adjacent samples need to be swapped. + if (this->slot_mode_ == I2S_SLOT_MODE_MONO && this->slot_bit_width_ == I2S_SLOT_BIT_WIDTH_16BIT && !this->pdm_) { + int16_t *samples = reinterpret_cast<int16_t *>(buf); + size_t sample_count = bytes_read / sizeof(int16_t); + for (size_t i = 0; i + 1 < sample_count; i += 2) { + int16_t tmp = samples[i]; + samples[i] = samples[i + 1]; + samples[i + 1] = tmp; } } #endif diff --git a/esphome/components/i2s_audio/speaker/__init__.py b/esphome/components/i2s_audio/speaker/__init__.py index 2e009a1de1..b84cf7de3b 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -100,11 +100,16 @@ def _set_stream_limits(config): def _validate_esp32_variant(config): - if config[CONF_DAC_TYPE] != "internal": - return config variant = esp32.get_esp32_variant() - if variant not in INTERNAL_DAC_VARIANTS: - raise cv.Invalid(f"{variant} does not have an internal DAC") + if config[CONF_DAC_TYPE] == "internal": + if variant not in INTERNAL_DAC_VARIANTS: + raise cv.Invalid(f"{variant} does not have an internal DAC") + elif ( + variant == esp32.VARIANT_ESP32 + and config.get(CONF_BITS_PER_SAMPLE) == 8 + and config.get(CONF_CHANNEL) in (CONF_MONO, CONF_LEFT, CONF_RIGHT) + ): + raise cv.Invalid("8-bit mono mode is not supported on ESP32") return config diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index c934d12d65..a996702f8b 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -372,15 +372,15 @@ void I2SAudioSpeaker::speaker_task(void *params) { } #ifdef USE_ESP32_VARIANT_ESP32 - // For ESP32 8/16 bit mono mode samples need to be switched. + // For ESP32 16-bit mono mode, adjacent samples need to be swapped. if (this_speaker->current_stream_info_.get_channels() == 1 && - this_speaker->current_stream_info_.get_bits_per_sample() <= 16) { - size_t len = bytes_read / sizeof(int16_t); - int16_t *tmp_buf = (int16_t *) new_data; - for (size_t i = 0; i < len; i += 2) { - int16_t tmp = tmp_buf[i]; - tmp_buf[i] = tmp_buf[i + 1]; - tmp_buf[i + 1] = tmp; + this_speaker->current_stream_info_.get_bits_per_sample() == 16) { + int16_t *samples = reinterpret_cast<int16_t *>(new_data); + size_t sample_count = bytes_read / sizeof(int16_t); + for (size_t i = 0; i + 1 < sample_count; i += 2) { + int16_t tmp = samples[i]; + samples[i] = samples[i + 1]; + samples[i + 1] = tmp; } } #endif diff --git a/esphome/components/speaker/media_player/audio_pipeline.cpp b/esphome/components/speaker/media_player/audio_pipeline.cpp index 8cea3abcfc..0822d80254 100644 --- a/esphome/components/speaker/media_player/audio_pipeline.cpp +++ b/esphome/components/speaker/media_player/audio_pipeline.cpp @@ -504,7 +504,7 @@ void AudioPipeline::decode_task(void *params) { if (!started_playback && has_stream_info) { // Verify enough data is available before starting playback std::shared_ptr<RingBuffer> temp_ring_buffer = this_pipeline->raw_file_ring_buffer_.lock(); - if (temp_ring_buffer->available() >= initial_bytes_to_buffer) { + if (temp_ring_buffer != nullptr && temp_ring_buffer->available() >= initial_bytes_to_buffer) { started_playback = true; } } From e7730cff0024a9d48680ef6f2a2771f7461b6705 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 13:59:40 -1000 Subject: [PATCH 1215/2030] [esp32_ble] Optimize BLE event hot path performance (#14627) --- esphome/components/esp32_ble/ble_event.h | 18 ++++++------------ esphome/core/lock_free_queue.h | 10 +++++++++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/esphome/components/esp32_ble/ble_event.h b/esphome/components/esp32_ble/ble_event.h index 299fd7705f..ba87fd8805 100644 --- a/esphome/components/esp32_ble/ble_event.h +++ b/esphome/components/esp32_ble/ble_event.h @@ -155,44 +155,38 @@ class BLEEvent { void release() { switch (this->type_) { case GAP: - // GAP events don't have heap allocations + // GAP events never have heap allocations break; case GATTC: - // Param is now stored inline, only delete heap data if it was heap-allocated if (!this->event_.gattc.is_inline && this->event_.gattc.data.heap_data != nullptr) { delete[] this->event_.gattc.data.heap_data; + this->event_.gattc.data.heap_data = nullptr; } - // Clear critical fields to prevent issues if type changes - this->event_.gattc.is_inline = false; - this->event_.gattc.data.heap_data = nullptr; break; case GATTS: - // Param is now stored inline, only delete heap data if it was heap-allocated if (!this->event_.gatts.is_inline && this->event_.gatts.data.heap_data != nullptr) { delete[] this->event_.gatts.data.heap_data; + this->event_.gatts.data.heap_data = nullptr; } - // Clear critical fields to prevent issues if type changes - this->event_.gatts.is_inline = false; - this->event_.gatts.data.heap_data = nullptr; break; } } // Load new event data for reuse (replaces previous event data) + // Note: release() is NOT called here because EventPool::release() already + // calls event->release() before returning to the free list. Every event + // from allocate() is already in a clean state. void load_gap_event(esp_gap_ble_cb_event_t e, esp_ble_gap_cb_param_t *p) { - this->release(); this->type_ = GAP; this->init_gap_data_(e, p); } void load_gattc_event(esp_gattc_cb_event_t e, esp_gatt_if_t i, esp_ble_gattc_cb_param_t *p) { - this->release(); this->type_ = GATTC; this->init_gattc_data_(e, i, p); } void load_gatts_event(esp_gatts_cb_event_t e, esp_gatt_if_t i, esp_ble_gatts_cb_param_t *p) { - this->release(); this->type_ = GATTS; this->init_gatts_data_(e, i, p); } diff --git a/esphome/core/lock_free_queue.h b/esphome/core/lock_free_queue.h index 522fbd36e1..316186ea54 100644 --- a/esphome/core/lock_free_queue.h +++ b/esphome/core/lock_free_queue.h @@ -104,7 +104,15 @@ template<class T, uint8_t SIZE> class LockFreeQueue { } } - uint16_t get_and_reset_dropped_count() { return dropped_count_.exchange(0, std::memory_order_relaxed); } + uint16_t get_and_reset_dropped_count() { + // Fast path: relaxed load is a single instruction on all platforms. + // The atomic exchange (especially for uint16_t on Xtensa) compiles to + // an expensive sub-word CAS retry loop (~25 instructions + memory barriers). + // Since drops are rare, avoid the exchange in the common case. + if (dropped_count_.load(std::memory_order_relaxed) == 0) + return 0; + return dropped_count_.exchange(0, std::memory_order_relaxed); + } void increment_dropped_count() { dropped_count_.fetch_add(1, std::memory_order_relaxed); } From 76c567a71cec76ca820ee0b23107b4258276b72e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:00:04 -1000 Subject: [PATCH 1216/2030] [scheduler] Use std::atomic<uint8_t> instead of std::atomic<bool> for remove flag (#14626) --- esphome/core/scheduler.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index cefbdd1b22..eb6cea4f37 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -178,9 +178,11 @@ class Scheduler { uint16_t next_execution_high_; // Upper 16 bits (millis_major counter) #ifdef ESPHOME_THREAD_MULTI_ATOMICS - // Multi-threaded with atomics: use atomic for lock-free access - // Place atomic<bool> separately since it can't be packed with bit fields - std::atomic<bool> remove{false}; + // Multi-threaded with atomics: use atomic uint8_t for lock-free access. + // std::atomic<bool> is not used because GCC on Xtensa generates an indirect + // function call for std::atomic<bool>::load() instead of inlining it. + // std::atomic<uint8_t> inlines correctly on all platforms. + std::atomic<uint8_t> remove{0}; // Bit-packed fields (4 bits used, 4 bits padding in 1 byte) enum Type : uint8_t { TIMEOUT, INTERVAL } type : 1; @@ -204,7 +206,7 @@ class Scheduler { next_execution_low_(0), next_execution_high_(0), #ifdef ESPHOME_THREAD_MULTI_ATOMICS - // remove is initialized in the member declaration as std::atomic<bool>{false} + // remove is initialized in the member declaration type(TIMEOUT), name_type_(NameType::STATIC_STRING), is_retry(false) { @@ -508,7 +510,7 @@ class Scheduler { // Multi-threaded with atomics: use atomic store with appropriate ordering // Release ordering when setting to true ensures cancellation is visible to other threads // Relaxed ordering when setting to false is sufficient for initialization - item->remove.store(removed, removed ? std::memory_order_release : std::memory_order_relaxed); + item->remove.store(removed ? 1 : 0, removed ? std::memory_order_release : std::memory_order_relaxed); #else // Single-threaded (ESPHOME_THREAD_SINGLE) or // multi-threaded without atomics (ESPHOME_THREAD_MULTI_NO_ATOMICS): direct write From 771404668d04418b377c660398f6ae1812d8bdd5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:01:01 -1000 Subject: [PATCH 1217/2030] [api] Inline fast path of try_to_clear_buffer (#14630) --- esphome/components/api/api_connection.cpp | 6 +----- esphome/components/api/api_connection.h | 10 +++++++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 43f5070a40..28a770a4fb 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1945,11 +1945,7 @@ void APIConnection::on_noise_encryption_set_key_request(const NoiseEncryptionSet #ifdef USE_API_HOMEASSISTANT_STATES void APIConnection::on_subscribe_home_assistant_states_request() { state_subs_at_ = 0; } #endif -bool APIConnection::try_to_clear_buffer(bool log_out_of_space) { - if (this->flags_.remove) - return false; - if (this->helper_->can_write_without_blocking()) - return true; +bool APIConnection::try_to_clear_buffer_slow_(bool log_out_of_space) { delay(0); APIError err = this->helper_->loop(); if (err != APIError::OK) { diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 5d1469e419..ccb51186d6 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -305,7 +305,13 @@ class APIConnection final : public APIServerConnectionBase { this->prepare_first_message_buffer(shared_buf, header_padding, payload_size + header_padding + footer_size); } - bool try_to_clear_buffer(bool log_out_of_space); + bool try_to_clear_buffer(bool log_out_of_space) { + if (this->flags_.remove) + return false; + if (this->helper_->can_write_without_blocking()) + return true; + return this->try_to_clear_buffer_slow_(log_out_of_space); + } bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; const char *get_name() const { return this->helper_->get_client_name(); } @@ -315,6 +321,8 @@ class APIConnection final : public APIServerConnectionBase { } protected: + bool try_to_clear_buffer_slow_(bool log_out_of_space); + // Helper function to handle authentication completion void complete_authentication_(); From 66a5ad0d75cf90ebc22ca85d139a698090be30ed Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:06:55 -1000 Subject: [PATCH 1218/2030] [core] Skip zero-initialization of StaticVector data array (#14592) --- esphome/core/helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 6ce5de4975..11e0afe526 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -215,7 +215,7 @@ template<typename T, size_t N> class StaticVector { using const_reverse_iterator = std::reverse_iterator<const_iterator>; private: - std::array<T, N> data_{}; + std::array<T, N> data_; // intentionally not value-initialized to avoid memset size_t count_{0}; public: From 93d7ec4d72dc77df92b01b3ca84cb29264e46ae5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:07:59 -1000 Subject: [PATCH 1219/2030] [esp32_ble] Inline ble_addr_to_uint64 to eliminate call overhead (#14591) --- esphome/components/esp32_ble/ble.cpp | 11 ----------- esphome/components/esp32_ble/ble.h | 11 ++++++++++- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 7fa5370072..ff9d9bb15a 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -727,17 +727,6 @@ void ESP32BLE::dump_config() { } } -uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) { - uint64_t u = 0; - u |= uint64_t(address[0] & 0xFF) << 40; - u |= uint64_t(address[1] & 0xFF) << 32; - u |= uint64_t(address[2] & 0xFF) << 24; - u |= uint64_t(address[3] & 0xFF) << 16; - u |= uint64_t(address[4] & 0xFF) << 8; - u |= uint64_t(address[5] & 0xFF) << 0; - return u; -} - ESP32BLE *global_ble = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace esphome::esp32_ble diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 2ce17e97be..04bec3f785 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -35,7 +35,16 @@ static constexpr uint8_t MAX_BLE_QUEUE_SIZE = 100; // 64 + 36 (ring buffer size static constexpr uint8_t MAX_BLE_QUEUE_SIZE = 88; // 64 + 24 (ring buffer size without PSRAM) #endif -uint64_t ble_addr_to_uint64(const esp_bd_addr_t address); +inline uint64_t ble_addr_to_uint64(const esp_bd_addr_t address) { + uint64_t u = 0; + u |= uint64_t(address[0] & 0xFF) << 40; + u |= uint64_t(address[1] & 0xFF) << 32; + u |= uint64_t(address[2] & 0xFF) << 24; + u |= uint64_t(address[3] & 0xFF) << 16; + u |= uint64_t(address[4] & 0xFF) << 8; + u |= uint64_t(address[5] & 0xFF) << 0; + return u; +} // NOLINTNEXTLINE(modernize-use-using) typedef struct { From 88536ff72bce462b8290d48ca7bc2f3f40a5e9b8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:31:42 -1000 Subject: [PATCH 1220/2030] [modbus] Fix timeout for non-hardware UARTs (e.g., USB UART) (#14614) Co-authored-by: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/modbus/modbus.cpp | 18 ++++- esphome/components/uart/uart_component.h | 6 +- .../external_components/uart_mock/__init__.py | 8 +- .../uart_mock/automation.h | 16 +++- .../uart_mock/uart_mock.cpp | 20 +++++ .../external_components/uart_mock/uart_mock.h | 10 +++ .../uart_mock_modbus_no_threshold.yaml | 64 +++++++++++++++ tests/integration/test_uart_mock_modbus.py | 79 +++++++++++++++++++ 8 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 28e26e307e..82672217c5 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -11,6 +11,11 @@ static const char *const TAG = "modbus"; // Maximum bytes to log for Modbus frames (truncated if larger) static constexpr size_t MODBUS_MAX_LOG_BYTES = 64; +// Approximate bits per character on the wire (depends on parity/stop bit config) +static constexpr uint32_t MODBUS_BITS_PER_CHAR = 11; +// Milliseconds per second +static constexpr uint32_t MS_PER_SEC = 1000; + void Modbus::setup() { if (this->flow_control_pin_ != nullptr) { this->flow_control_pin_->setup(); @@ -19,10 +24,17 @@ void Modbus::setup() { this->frame_delay_ms_ = std::max(2, // 1750us minimum per spec - rounded up to 2ms. // 3.5 characters * 11 bits per character * 1000ms/sec / (bits/sec) (Standard modbus frame delay) - (uint16_t) (3.5 * 11 * 1000 / this->parent_->get_baud_rate()) + 1); + (uint16_t) (3.5 * MODBUS_BITS_PER_CHAR * MS_PER_SEC / this->parent_->get_baud_rate()) + 1); + // When rx_full_threshold is configured (non-zero), the UART has a hardware FIFO with a + // meaningful threshold (e.g., ESP32 native UART), so we can calculate a precise delay. + // Otherwise (e.g., USB UART), use 50ms to handle data arriving in chunks. + static constexpr uint16_t DEFAULT_LONG_RX_BUFFER_DELAY_MS = 50; + size_t rx_threshold = this->parent_->get_rx_full_threshold(); this->long_rx_buffer_delay_ms_ = - (this->parent_->get_rx_full_threshold() * 11 * 1000 / this->parent_->get_baud_rate()) + 1; + rx_threshold != uart::UARTComponent::RX_FULL_THRESHOLD_UNSET + ? (rx_threshold * MODBUS_BITS_PER_CHAR * MS_PER_SEC / this->parent_->get_baud_rate()) + 1 + : DEFAULT_LONG_RX_BUFFER_DELAY_MS; } void Modbus::loop() { @@ -290,7 +302,7 @@ void Modbus::send_next_frame_() { this->last_send_tx_offset_ = 0; } else { this->write_array(frame.data.get(), frame.size); - this->last_send_tx_offset_ = frame.size * 11 * 1000 / this->parent_->get_baud_rate() + 1; + this->last_send_tx_offset_ = frame.size * MODBUS_BITS_PER_CHAR * MS_PER_SEC / this->parent_->get_baud_rate() + 1; } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 3d7e71b89f..853de719fe 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -39,6 +39,8 @@ enum class FlushResult { class UARTComponent { public: + static constexpr size_t RX_FULL_THRESHOLD_UNSET = 0; + // Writes an array of bytes to the UART bus. // @param data A vector of bytes to be written. void write_array(const std::vector<uint8_t> &data) { this->write_array(&data[0], data.size()); } @@ -201,7 +203,9 @@ class UARTComponent { InternalGPIOPin *rx_pin_{}; InternalGPIOPin *flow_control_pin_{}; size_t rx_buffer_size_{}; - size_t rx_full_threshold_{1}; + // ESP32 (both Arduino and ESP-IDF) always sets this at codegen time via set_rx_full_threshold(). + // Other platforms (USB UART, Arduino, etc.) leave it unset. + size_t rx_full_threshold_{RX_FULL_THRESHOLD_UNSET}; size_t rx_timeout_{0}; uint32_t baud_rate_{0}; uint8_t stop_bits_{0}; diff --git a/tests/integration/fixtures/external_components/uart_mock/__init__.py b/tests/integration/fixtures/external_components/uart_mock/__init__.py index c10d73354e..fdd481b397 100644 --- a/tests/integration/fixtures/external_components/uart_mock/__init__.py +++ b/tests/integration/fixtures/external_components/uart_mock/__init__.py @@ -62,6 +62,7 @@ CONFIG_INJECT_RX_SCHEMA = cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(MockUartComponent), cv.Required("data"): cv.templatable(validate_raw_data), + cv.Optional(CONF_DELAY): cv.positive_time_period_milliseconds, }, key=CONF_DATA, ) @@ -87,7 +88,7 @@ CONFIG_SCHEMA = cv.Schema( cv.GenerateID(): cv.declare_id(MockUartComponent), cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, - cv.Optional(CONF_RX_FULL_THRESHOLD, default=10): cv.int_range(min=1, max=120), + cv.Optional(CONF_RX_FULL_THRESHOLD): cv.int_range(min=1, max=120), cv.Optional(CONF_RX_TIMEOUT, default=2): cv.int_range(min=0, max=92), cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), @@ -126,6 +127,8 @@ async def inject_rx_to_code(config, action_id, template_arg, args): arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) cg.add(var.set_data_static(arr, len(data))) + if CONF_DELAY in config: + cg.add(var.set_delay(config[CONF_DELAY])) return var @@ -135,7 +138,8 @@ async def to_code(config): cg.add(var.set_baud_rate(config[CONF_BAUD_RATE])) cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) - cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD])) + if CONF_RX_FULL_THRESHOLD in config: + cg.add(var.set_rx_full_threshold(config[CONF_RX_FULL_THRESHOLD])) cg.add(var.set_rx_timeout(config[CONF_RX_TIMEOUT])) cg.add(var.set_stop_bits(config[CONF_STOP_BITS])) cg.add(var.set_data_bits(config[CONF_DATA_BITS])) diff --git a/tests/integration/fixtures/external_components/uart_mock/automation.h b/tests/integration/fixtures/external_components/uart_mock/automation.h index 83a057d3a0..b2336ad065 100644 --- a/tests/integration/fixtures/external_components/uart_mock/automation.h +++ b/tests/integration/fixtures/external_components/uart_mock/automation.h @@ -22,18 +22,30 @@ template<typename... Ts> class MockUartInjectRXAction : public Action<Ts...>, pu this->len_ = len; // Length >= 0 indicates static mode } + void set_delay(uint32_t delay_ms) { this->delay_ms_ = delay_ms; } + void play(const Ts &...x) override { if (this->len_ >= 0) { // Static mode: use pointer and length - this->parent_->inject_to_rx_buffer(this->code_.data, static_cast<size_t>(this->len_)); + if (this->delay_ms_ > 0) { + std::vector<uint8_t> data(this->code_.data, this->code_.data + this->len_); + this->parent_->inject_to_rx_buffer_delayed(data, this->delay_ms_); + } else { + this->parent_->inject_to_rx_buffer(this->code_.data, static_cast<size_t>(this->len_)); + } } else { // Template mode: call function auto val = this->code_.func(x...); - this->parent_->inject_to_rx_buffer(val); + if (this->delay_ms_ > 0) { + this->parent_->inject_to_rx_buffer_delayed(val, this->delay_ms_); + } else { + this->parent_->inject_to_rx_buffer(val); + } } } protected: + uint32_t delay_ms_{0}; ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length union Code { std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas) diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index 1edeb97cf1..1a15da76d1 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -53,6 +53,15 @@ void MockUartComponent::loop() { } } + // Process staged RX - deliver bytes whose delay has elapsed + uint32_t now_ms = millis(); + while (!this->staged_rx_.empty() && (static_cast<int32_t>(now_ms - this->staged_rx_.front().available_at_ms) >= 0)) { + auto &staged = this->staged_rx_.front(); + ESP_LOGD(TAG, "Delivering %zu staged RX bytes", staged.data.size()); + this->inject_to_rx_buffer(staged.data); + this->staged_rx_.pop_front(); + } + // Process delayed responses for (auto &response : this->responses_) { if (response.delay_ms > 0 && response.last_match_ms > 0 && now - response.last_match_ms >= response.delay_ms) { @@ -209,4 +218,15 @@ void MockUartComponent::inject_to_rx_buffer(const std::vector<uint8_t> &data) { } } +void MockUartComponent::inject_to_rx_buffer_delayed(const std::vector<uint8_t> &data, uint32_t delay_ms) { + if (!data.empty() && data.size() <= 64) { + char hex_buf[format_hex_pretty_size(64)]; + ESP_LOGD(TAG, "Staging %zu RX bytes with %ums delay: %s", data.size(), delay_ms, + format_hex_pretty_to(hex_buf, sizeof(hex_buf), data.data(), data.size())); + } else if (data.size() > 64) { + ESP_LOGD(TAG, "Staging %zu RX bytes with %ums delay (too large to log inline)", data.size(), delay_ms); + } + this->staged_rx_.push_back({data, millis() + delay_ms}); +} + } // namespace esphome::uart_mock diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index c9afb96357..82e3b3d563 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -43,6 +43,8 @@ class MockUartComponent : public uart::UARTComponent, public Component { void set_tx_hook(std::function<void(const std::vector<uint8_t> &)> &&cb) { this->tx_hook_ = std::move(cb); } void inject_to_rx_buffer(const std::vector<uint8_t> &data); void inject_to_rx_buffer(const uint8_t *data, size_t len); + // Stage bytes for delayed delivery - simulates transport-level latency (e.g., USB packets) + void inject_to_rx_buffer_delayed(const std::vector<uint8_t> &data, uint32_t delay_ms); protected: void check_logger_conflict() override {} @@ -82,6 +84,14 @@ class MockUartComponent : public uart::UARTComponent, public Component { }; std::vector<PeriodicRx> periodic_rx_; + // Staged RX - bytes that are pending delivery after a delay + // Simulates transport-level latency (e.g., USB packet delivery) + struct StagedRx { + std::vector<uint8_t> data; + uint32_t available_at_ms; // millis() time when bytes become available + }; + std::deque<StagedRx> staged_rx_; + // Observability uint32_t tx_count_{0}; uint32_t rx_count_{0}; diff --git a/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml b/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml new file mode 100644 index 0000000000..e3e8c8c8da --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml @@ -0,0 +1,64 @@ +esphome: + name: uart-mock-modbus-no-thresh + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +# Simulate a non-hardware UART (e.g., USB UART) by not setting rx_full_threshold. +# This leaves it at the default sentinel value (0), triggering the 50ms fallback timeout. +uart_mock: + - id: virtual_uart_dev + baud_rate: 9600 + auto_start: false + debug: + on_tx: + - then: + - if: + condition: #Read 80 input registers on device 2, starting at address 0 (SDM meter request) + lambda: "return data == std::vector<uint8_t>({0x02,0x04,0x00,0x00,0x00,0x50,0xF0,0x05});" + then: + - uart_mock.inject_rx: # First USB packet: SDM meter response part 1 + !lambda return {0x02,0x04,0xA0,0x43,0x73,0x19,0x9A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + - uart_mock.inject_rx: # Second USB packet: rest of response (staged with 40ms latency) + delay: 40ms + data: !lambda return{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6F,0xCC,0xCD,0x43,0x7C,0xB8,0x10,0x3D,0x38,0x51,0xEC, + 0x43,0x81,0x1B,0xE7,0x3B,0x03,0x12,0x6F,0x50,0x1B}; + +modbus: + uart_id: virtual_uart_dev + turnaround_time: 10ms + +sensor: + - platform: sdm_meter + address: 2 + update_interval: 1s + phase_a: + voltage: + name: sdm_voltage + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(virtual_uart_dev).start_scenario();' diff --git a/tests/integration/test_uart_mock_modbus.py b/tests/integration/test_uart_mock_modbus.py index 6901dc27fe..e341d86f53 100644 --- a/tests/integration/test_uart_mock_modbus.py +++ b/tests/integration/test_uart_mock_modbus.py @@ -5,6 +5,10 @@ test_uart_mock_modbus : 1. Read a single register and parse successfully (basic_register) 2. Read multiple registers from SDM meter and parse successfully (sdm_voltage), with some intermediate delay to simulate UART buffer time. +test_uart_mock_modbus_no_threshold : + Test modbus with no rx_full_threshold set (simulating USB UART / non-hardware UART). + Verifies the 50ms fallback timeout handles chunked data with USB packet gaps. + """ from __future__ import annotations @@ -218,3 +222,78 @@ async def test_uart_mock_modbus_timing( f"Timeout waiting for SDM voltage change. Received sensor states:\n" f" sdm_voltage: {sensor_states['sdm_voltage']}\n" ) + + +@pytest.mark.asyncio +async def test_uart_mock_modbus_no_threshold( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test modbus with no rx_full_threshold (simulating USB UART). + + Without the 50ms fallback timeout, the chunked response with a 40ms gap + between USB packets would cause a false timeout and CRC failure cascade. + """ + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track sensor state updates (after initial state is swallowed) + sensor_states: dict[str, list[float]] = { + "sdm_voltage": [], + } + + voltage_changed = loop.create_future() + + def on_state(state: EntityState) -> None: + if isinstance(state, SensorState) and not state.missing_state: + sensor_name = key_to_sensor.get(state.key) + if sensor_name and sensor_name in sensor_states: + sensor_states[sensor_name].append(state.state) + # Check if this is a good voltage reading (243V) + if ( + sensor_name == "sdm_voltage" + and state.state > 200.0 + and not voltage_changed.done() + ): + voltage_changed.set_result(True) + + async with ( + run_compiled(yaml_config), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + + # Build key mappings for all sensor types + all_names = list(sensor_states.keys()) + key_to_sensor = build_key_to_entity_mapping(entities, all_names) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for voltage to be updated with successful parse + try: + await asyncio.wait_for(voltage_changed, timeout=2.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for SDM voltage change. Received sensor states:\n" + f" sdm_voltage: {sensor_states['sdm_voltage']}\n" + ) From c11ad7f0e6fdbce4c65eb714e794c0791a8c7352 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:32:35 -1000 Subject: [PATCH 1221/2030] [rp2040] Wrap printf/vprintf/fprintf to eliminate _vfprintf_r (~9.2 KB flash) (#14622) --- esphome/components/rp2040/__init__.py | 17 ++++- esphome/components/rp2040/const.py | 1 + esphome/components/rp2040/printf_stubs.cpp | 74 ++++++++++++++++++++ tests/components/rp2040/test.rp2040-ard.yaml | 3 + 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 esphome/components/rp2040/printf_stubs.cpp diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 1442a0a7f7..54e1db27aa 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -21,7 +21,13 @@ from esphome.const import ( from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority from esphome.helpers import copy_file_if_changed, read_file, write_file_if_changed -from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns +from .const import ( + CONF_ENABLE_FULL_PRINTF, + KEY_BOARD, + KEY_PIO_FILES, + KEY_RP2040, + rp2040_ns, +) # force import gpio to register pin schema from .gpio import rp2040_pin_to_code # noqa @@ -153,6 +159,7 @@ CONFIG_SCHEMA = cv.All( cv.positive_time_period_milliseconds, cv.Range(max=cv.TimePeriod(milliseconds=8388)), ), + cv.Optional(CONF_ENABLE_FULL_PRINTF, default=False): cv.boolean, } ), set_core_data, @@ -190,6 +197,14 @@ async def to_code(config): ], ) + # Wrap FILE*-based printf functions to eliminate newlib's _vfprintf_r + # (~9.2 KB). See printf_stubs.cpp for implementation. + if config.get(CONF_ENABLE_FULL_PRINTF): + cg.add_define("USE_FULL_PRINTF") + else: + for symbol in ("vprintf", "printf", "fprintf"): + cg.add_build_flag(f"-Wl,--wrap={symbol}") + cg.add_platformio_option("board_build.core", "earlephilhower") cg.add_platformio_option("board_build.filesystem_size", "1m") diff --git a/esphome/components/rp2040/const.py b/esphome/components/rp2040/const.py index ab5f42d757..7eeddffc76 100644 --- a/esphome/components/rp2040/const.py +++ b/esphome/components/rp2040/const.py @@ -1,5 +1,6 @@ import esphome.codegen as cg +CONF_ENABLE_FULL_PRINTF = "enable_full_printf" KEY_BOARD = "board" KEY_RP2040 = "rp2040" KEY_PIO_FILES = "pio_files" diff --git a/esphome/components/rp2040/printf_stubs.cpp b/esphome/components/rp2040/printf_stubs.cpp new file mode 100644 index 0000000000..c2174a1dec --- /dev/null +++ b/esphome/components/rp2040/printf_stubs.cpp @@ -0,0 +1,74 @@ +/* + * Linker wrap stubs for FILE*-based printf functions. + * + * The RP2040 Arduino framework and libraries may reference printf(), + * vprintf(), and fprintf() which pull in newlib's _vfprintf_r (~8.9 KB). + * ESPHome never uses these — all logging goes through the logger component + * which uses snprintf/vsnprintf, so the libc FILE*-based printf path is + * dead code. + * + * These stubs redirect through vsnprintf() (which is already in the binary) + * and fwrite(), allowing the linker to dead-code eliminate _vfprintf_r. + * + * Saves ~8.9 KB of flash. + */ + +#if defined(USE_RP2040) && !defined(USE_FULL_PRINTF) +#include <cstdarg> +#include <cstdio> +#include <cstdlib> + +namespace esphome::rp2040 {} + +static constexpr size_t PRINTF_BUFFER_SIZE = 512; + +// These stubs are essentially dead code at runtime — ESPHome uses its own +// logging through snprintf/vsnprintf, not libc printf. +// The buffer overflow check is purely defensive and should never trigger. +static int write_printf_buffer(FILE *stream, char *buf, int len) { + if (len < 0) { + return len; + } + size_t write_len = len; + if (write_len >= PRINTF_BUFFER_SIZE) { + fwrite(buf, 1, PRINTF_BUFFER_SIZE - 1, stream); + // Use fwrite for the message to avoid recursive __wrap_printf call + static const char msg[] = "\nprintf buffer overflow\n"; + fwrite(msg, 1, sizeof(msg) - 1, stream); + abort(); + } + if (fwrite(buf, 1, write_len, stream) < write_len || ferror(stream)) { + return -1; + } + return len; +} + +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +extern "C" { + +int __wrap_vprintf(const char *fmt, va_list ap) { + char buf[PRINTF_BUFFER_SIZE]; + return write_printf_buffer(stdout, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); +} + +int __wrap_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int len = __wrap_vprintf(fmt, ap); + va_end(ap); + return len; +} + +int __wrap_fprintf(FILE *stream, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char buf[PRINTF_BUFFER_SIZE]; + int len = write_printf_buffer(stream, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); + va_end(ap); + return len; +} + +} // extern "C" +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) + +#endif // USE_RP2040 && !USE_FULL_PRINTF diff --git a/tests/components/rp2040/test.rp2040-ard.yaml b/tests/components/rp2040/test.rp2040-ard.yaml index 039a261016..1eb315a3b4 100644 --- a/tests/components/rp2040/test.rp2040-ard.yaml +++ b/tests/components/rp2040/test.rp2040-ard.yaml @@ -1,3 +1,6 @@ +rp2040: + enable_full_printf: false + logger: level: VERBOSE From e1c849d5d22651a6e7d3457f2d5dbe206d21c386 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:32:47 -1000 Subject: [PATCH 1222/2030] [esp8266] Wrap printf/vprintf/fprintf to eliminate _vfiprintf_r (~1.6 KB flash) (#14621) --- esphome/components/esp8266/__init__.py | 10 +++ esphome/components/esp8266/const.py | 1 + esphome/components/esp8266/printf_stubs.cpp | 71 +++++++++++++++++++ .../components/esp8266/test.esp8266-ard.yaml | 3 + 4 files changed, 85 insertions(+) create mode 100644 esphome/components/esp8266/printf_stubs.cpp diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 927a59fd61..1ef4f5e037 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -23,6 +23,7 @@ from esphome.helpers import copy_file_if_changed from .boards import BOARDS, ESP8266_LD_SCRIPTS from .const import ( CONF_EARLY_PIN_INIT, + CONF_ENABLE_FULL_PRINTF, CONF_ENABLE_SERIAL, CONF_ENABLE_SERIAL1, CONF_RESTORE_FROM_FLASH, @@ -179,6 +180,7 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_ENABLE_SERIAL): cv.boolean, cv.Optional(CONF_ENABLE_SERIAL1): cv.boolean, + cv.Optional(CONF_ENABLE_FULL_PRINTF, default=False): cv.boolean, } ), set_core_data, @@ -260,6 +262,14 @@ async def to_code(config): if CORE.testing_mode: cg.add_build_flag("-DESPHOME_TESTING_MODE") + # Wrap FILE*-based printf functions to eliminate newlib's _vfiprintf_r + # (~1.6 KB). See printf_stubs.cpp for implementation. + if config.get(CONF_ENABLE_FULL_PRINTF): + cg.add_define("USE_FULL_PRINTF") + else: + for symbol in ("vprintf", "printf", "fprintf"): + cg.add_build_flag(f"-Wl,--wrap={symbol}") + cg.add_platformio_option("board_build.flash_mode", config[CONF_BOARD_FLASH_MODE]) ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] diff --git a/esphome/components/esp8266/const.py b/esphome/components/esp8266/const.py index 229ac61f24..57eb54f0f8 100644 --- a/esphome/components/esp8266/const.py +++ b/esphome/components/esp8266/const.py @@ -6,6 +6,7 @@ KEY_BOARD = "board" KEY_PIN_INITIAL_STATES = "pin_initial_states" CONF_RESTORE_FROM_FLASH = "restore_from_flash" CONF_EARLY_PIN_INIT = "early_pin_init" +CONF_ENABLE_FULL_PRINTF = "enable_full_printf" CONF_ENABLE_SERIAL = "enable_serial" CONF_ENABLE_SERIAL1 = "enable_serial1" KEY_FLASH_SIZE = "flash_size" diff --git a/esphome/components/esp8266/printf_stubs.cpp b/esphome/components/esp8266/printf_stubs.cpp new file mode 100644 index 0000000000..e6d4a74866 --- /dev/null +++ b/esphome/components/esp8266/printf_stubs.cpp @@ -0,0 +1,71 @@ +/* + * Linker wrap stubs for FILE*-based printf functions. + * + * The ESP8266 Arduino framework and libraries may reference printf(), + * vprintf(), and fprintf() which pull in newlib's _vfprintf_r (~900 bytes). + * ESPHome never uses these — all logging writes directly to the UART via + * Arduino's Serial, so the libc FILE*-based printf path is dead code. + * + * These stubs redirect through vsnprintf() (which is already in the binary + * for ESPHome's logging) and fwrite(), allowing the linker to dead-code + * eliminate _vfprintf_r. + * + * Saves ~1.6 KB of flash. + */ + +#if defined(USE_ESP8266) && !defined(USE_FULL_PRINTF) +#include <cstdarg> +#include <cstdio> +#include <cstdlib> + +namespace esphome::esp8266 {} + +static constexpr size_t PRINTF_BUFFER_SIZE = 512; + +// These stubs are essentially dead code at runtime — ESPHome writes directly +// to the UART via Arduino's Serial, and Serial.printf() has its own implementation. +// The buffer overflow check is purely defensive and should never trigger. +static int write_printf_buffer(FILE *stream, char *buf, int len) { + if (len < 0) { + return len; + } + size_t write_len = len; + if (write_len >= PRINTF_BUFFER_SIZE) { + fwrite(buf, 1, PRINTF_BUFFER_SIZE - 1, stream); + abort(); + } + if (fwrite(buf, 1, write_len, stream) < write_len || ferror(stream)) { + return -1; + } + return len; +} + +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +extern "C" { + +int __wrap_vprintf(const char *fmt, va_list ap) { + char buf[PRINTF_BUFFER_SIZE]; + return write_printf_buffer(stdout, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); +} + +int __wrap_printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int len = __wrap_vprintf(fmt, ap); + va_end(ap); + return len; +} + +int __wrap_fprintf(FILE *stream, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + char buf[PRINTF_BUFFER_SIZE]; + int len = write_printf_buffer(stream, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); + va_end(ap); + return len; +} + +} // extern "C" +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) + +#endif // USE_ESP8266 && !USE_FULL_PRINTF diff --git a/tests/components/esp8266/test.esp8266-ard.yaml b/tests/components/esp8266/test.esp8266-ard.yaml index 039a261016..c77218f7a3 100644 --- a/tests/components/esp8266/test.esp8266-ard.yaml +++ b/tests/components/esp8266/test.esp8266-ard.yaml @@ -1,3 +1,6 @@ +esp8266: + enable_full_printf: false + logger: level: VERBOSE From aef2d74e41123f77900bc5cab37a75cfb9b6e2b1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:32:59 -1000 Subject: [PATCH 1223/2030] [ld2450] Add integration tests with mock UART (#14611) --- .../fixtures/uart_mock_ld2450.yaml | 221 ++++++++++++++++++ tests/integration/state_utils.py | 28 ++- tests/integration/test_uart_mock_ld2450.py | 204 ++++++++++++++++ 3 files changed, 448 insertions(+), 5 deletions(-) create mode 100644 tests/integration/fixtures/uart_mock_ld2450.yaml create mode 100644 tests/integration/test_uart_mock_ld2450.py diff --git a/tests/integration/fixtures/uart_mock_ld2450.yaml b/tests/integration/fixtures/uart_mock_ld2450.yaml new file mode 100644 index 0000000000..269136da68 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2450.yaml @@ -0,0 +1,221 @@ +esphome: + name: uart-mock-ld2450-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2450's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + auto_start: false + responses: + # Catch-all response: match any command footer (04 03 02 01). + # Returns a generic ACK to unblock setup commands. + # + # Response layout: + # [0-3] FD FC FB FA = header + # [4-5] 04 00 = length 4 + # [6] FF = cmd (handled as CMD_ENABLE_CONF) + # [7] 01 = status (ACK) + # [8-9] 00 00 = error = 0 + # [10-13] 04 03 02 01 = footer + - expect_tx: [0x04, 0x03, 0x02, 0x01] + inject_rx: + [ + 0xFD, 0xFC, 0xFB, 0xFA, + 0x04, 0x00, + 0xFF, 0x01, + 0x00, 0x00, + 0x04, 0x03, 0x02, 0x01, + ] + + injections: + # Phase 1 (t=100ms): Valid LD2450 periodic data frame - happy path + # The buffer is clean at this point, so this frame should parse correctly. + # + # Target 1: X=-500mm, Y=1000mm, Speed=-50mm/s (approaching), Res=320mm + # X: magnitude=500 (0x01F4), negative → high=0x01, low=0xF4 + # Y: magnitude=1000 (0x03E8), positive → high=0x83, low=0xE8 + # Speed: raw=5, negative (approaching) → high=0x00, low=0x05, decoded=-50mm/s + # Resolution: 320 → low=0x40, high=0x01 + # Distance: sqrt(500²+1000²) = sqrt(1250000) ≈ 1118mm + # + # Target 2: X=200mm, Y=500mm, Speed=0 (stationary), Res=100mm + # X: magnitude=200 (0x00C8), positive → high=0x80, low=0xC8 + # Y: magnitude=500 (0x01F4), positive → high=0x81, low=0xF4 + # Speed: 0 → 0x00, 0x00 + # Resolution: 100 → low=0x64, high=0x00 + # Distance: sqrt(200²+500²) = sqrt(290000) ≈ 538mm + # + # Target 3: No target (all zeros) + # Distance: 0 → sensors publish unknown/NaN + # + # Counts: target_count=2, moving_target_count=1, still_target_count=1 + # + # Frame layout (30 bytes): + # [0-3] AA FF 03 00 = periodic data header + # [4-11] Target 1 (8 bytes): X_L X_H Y_L Y_H SPD_L SPD_H RES_L RES_H + # [12-19] Target 2 (8 bytes) + # [20-27] Target 3 (8 bytes) + # [28-29] 55 CC = periodic data footer + - delay: 100ms + inject_rx: + [ + 0xAA, 0xFF, 0x03, 0x00, + 0xF4, 0x01, 0xE8, 0x83, 0x05, 0x00, 0x40, 0x01, + 0xC8, 0x80, 0xF4, 0x81, 0x00, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0xCC, + ] + + # Phase 2 (t=300ms): Garbage bytes + # LD2450's readline_ does NOT reject bytes at position 0 (unlike LD2412), + # so these bytes accumulate in the buffer. buffer_pos_ goes from 0 to 7. + - delay: 200ms + inject_rx: [0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x11, 0x22] + + # Phase 3 (t=400ms): Truncated frame (header + partial data, no footer) + # More bytes accumulating in the buffer without a footer match. + # After this, buffer_pos_ = 7 + 8 = 15. + - delay: 100ms + inject_rx: [0xAA, 0xFF, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04] + + # Phase 4 (t=600ms): Overflow - inject 75 bytes of 0xFF (MAX_LINE_LENGTH=45) + # Buffer has 15 bytes from phases 2+3. + # readline_() stores bytes while buffer_pos_ < 44. When buffer_pos_ == 44, + # the next byte triggers overflow: logs warning, resets buffer_pos_ to 0, + # and discards that byte. + # + # First overflow: 29 bytes fill positions 15-43 (buffer_pos_=44), byte 30 + # triggers overflow (discarded). Total consumed: 30 bytes. + # Second overflow: 44 bytes fill positions 0-43 (buffer_pos_=44), byte 45 + # triggers overflow (discarded). Total consumed: 30+45 = 75 bytes. + # After both overflows, buffer_pos_ = 0 (clean state for recovery frame). + - delay: 200ms + inject_rx: + [ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + ] + + # Phase 5 (t=700ms): Valid frame after overflow - recovery test + # Buffer was reset by overflow. This valid frame should parse correctly. + # + # Target 1: X=300mm, Y=400mm, Speed=30mm/s (moving away), Res=100mm + # X: magnitude=300 (0x012C), positive → high=0x81, low=0x2C + # Y: magnitude=400 (0x0190), positive → high=0x81, low=0x90 + # Speed: raw=3, positive (moving away) → high=0x80, low=0x03, decoded=30mm/s + # Resolution: 100 → low=0x64, high=0x00 + # Distance: sqrt(300²+400²) = 500mm + # + # Target 2 & 3: No target (all zeros) + # Counts: target_count=1, moving_target_count=1, still_target_count=0 + - delay: 100ms + inject_rx: + [ + 0xAA, 0xFF, 0x03, 0x00, + 0x2C, 0x81, 0x90, 0x81, 0x03, 0x80, 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0xCC, + ] + +ld2450: + id: ld2450_dev + uart_id: mock_uart + +sensor: + - platform: ld2450 + ld2450_id: ld2450_dev + target_count: + name: "Target Count" + filters: &sensor_filters + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + still_target_count: + name: "Still Target Count" + filters: *sensor_filters + moving_target_count: + name: "Moving Target Count" + filters: *sensor_filters + target_1: + x: + name: "Target 1 X" + filters: *sensor_filters + y: + name: "Target 1 Y" + filters: *sensor_filters + speed: + name: "Target 1 Speed" + filters: *sensor_filters + distance: + name: "Target 1 Distance" + filters: *sensor_filters + resolution: + name: "Target 1 Resolution" + filters: *sensor_filters + angle: + name: "Target 1 Angle" + filters: *sensor_filters + target_2: + x: + name: "Target 2 X" + filters: *sensor_filters + y: + name: "Target 2 Y" + filters: *sensor_filters + speed: + name: "Target 2 Speed" + filters: *sensor_filters + distance: + name: "Target 2 Distance" + filters: *sensor_filters + +binary_sensor: + - platform: ld2450 + ld2450_id: ld2450_dev + has_target: + name: "Has Target" + filters: &binary_sensor_filters + - settle: 50ms + has_moving_target: + name: "Has Moving Target" + filters: *binary_sensor_filters + has_still_target: + name: "Has Still Target" + filters: *binary_sensor_filters + +text_sensor: + - platform: ld2450 + ld2450_id: ld2450_dev + target_1: + direction: + name: "Target 1 Direction" + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/state_utils.py b/tests/integration/state_utils.py index e8c2cc5e66..ab9fdb01bb 100644 --- a/tests/integration/state_utils.py +++ b/tests/integration/state_utils.py @@ -13,6 +13,7 @@ from aioesphomeapi import ( EntityInfo, EntityState, SensorState, + TextSensorState, ) _LOGGER = logging.getLogger(__name__) @@ -244,12 +245,13 @@ class InitialStateHelper: class SensorStateCollector: - """Collects sensor and binary sensor state updates and provides wait helpers. + """Collects sensor, binary sensor, and text sensor state updates with wait helpers. Usage: collector = SensorStateCollector( sensor_names=["moving_distance", "still_distance"], binary_sensor_names=["has_target"], + text_sensor_names=["direction"], ) # Use collector.on_state as the callback (or wrap it) client.subscribe_states(helper.on_state_wrapper(collector.on_state)) @@ -259,18 +261,23 @@ class SensorStateCollector: # Access collected states assert collector.sensor_states["moving_distance"][0] == approx(100.0) + assert collector.text_sensor_states["direction"][0] == "Approaching" """ def __init__( self, sensor_names: list[str], binary_sensor_names: list[str] | None = None, + text_sensor_names: list[str] | None = None, entities: list[EntityInfo] | None = None, ) -> None: self.sensor_states: dict[str, list[float]] = {name: [] for name in sensor_names} self.binary_states: dict[str, list[bool]] = { name: [] for name in (binary_sensor_names or []) } + self.text_sensor_states: dict[str, list[str]] = { + name: [] for name in (text_sensor_names or []) + } self._key_to_sensor: dict[int, str] = {} self._waiters: list[tuple[Callable[[], bool], asyncio.Future[bool]]] = [] @@ -279,7 +286,11 @@ class SensorStateCollector: def build_key_mapping(self, entities: list[EntityInfo]) -> None: """Build key-to-name mapping from entities. Sorted by descending length.""" - all_names = list(self.sensor_states.keys()) + list(self.binary_states.keys()) + all_names = ( + list(self.sensor_states.keys()) + + list(self.binary_states.keys()) + + list(self.text_sensor_states.keys()) + ) all_names.sort(key=len, reverse=True) self._key_to_sensor = build_key_to_entity_mapping(entities, all_names) @@ -295,6 +306,11 @@ class SensorStateCollector: if sensor_name and sensor_name in self.binary_states: self.binary_states[sensor_name].append(state.state) self._check_waiters() + elif isinstance(state, TextSensorState) and not state.missing_state: + sensor_name = self._key_to_sensor.get(state.key) + if sensor_name and sensor_name in self.text_sensor_states: + self.text_sensor_states[sensor_name].append(state.state) + self._check_waiters() def _check_waiters(self) -> None: """Check all pending waiters and resolve any whose condition is met.""" @@ -303,9 +319,11 @@ class SensorStateCollector: future.set_result(True) def _all_have_values(self) -> bool: - """Check if all sensor and binary sensor lists have at least one value.""" - return all(len(v) >= 1 for v in self.sensor_states.values()) and all( - len(v) >= 1 for v in self.binary_states.values() + """Check if all sensor, binary sensor, and text sensor lists have at least one value.""" + return ( + all(len(v) >= 1 for v in self.sensor_states.values()) + and all(len(v) >= 1 for v in self.binary_states.values()) + and all(len(v) >= 1 for v in self.text_sensor_states.values()) ) async def wait_for_all(self, timeout: float = 3.0) -> None: diff --git a/tests/integration/test_uart_mock_ld2450.py b/tests/integration/test_uart_mock_ld2450.py new file mode 100644 index 0000000000..b1aa2f6952 --- /dev/null +++ b/tests/integration/test_uart_mock_ld2450.py @@ -0,0 +1,204 @@ +"""Integration test for LD2450 component with mock UART. + +Tests: +test_uart_mock_ld2450: + 1. Happy path - valid periodic data frame publishes correct target sensor values + 2. Multi-target tracking - verifies target count, moving/still counts + 3. Target coordinate decoding - signed X/Y coordinates with sign-magnitude encoding + 4. Speed decoding - approaching (negative) and stationary (zero) targets + 5. Distance calculation - computed from X/Y via sqrt(x²+y²) + 6. Direction text sensor - "Approaching" for negative speed target + 7. Garbage resilience - random bytes don't crash the component + 8. Truncated frame handling - partial frame doesn't corrupt state + 9. Buffer overflow recovery - overflow resets the parser + 10. Post-overflow parsing - next valid frame after overflow is parsed correctly + 11. TX logging - verifies LD2450 sends expected setup commands +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path + +from aioesphomeapi import ButtonInfo +import pytest + +from .state_utils import InitialStateHelper, SensorStateCollector, find_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_uart_mock_ld2450( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LD2450 data parsing with happy path, garbage, overflow, and recovery.""" + # Replace external component path placeholder + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track overflow warning in logs + overflow_seen = loop.create_future() + + # Track TX data logged by the mock for assertions + tx_log_lines: list[str] = [] + + def line_callback(line: str) -> None: + if "Max command length exceeded" in line and not overflow_seen.done(): + overflow_seen.set_result(True) + # Capture all TX log lines from uart_mock + if "uart_mock" in line and "TX " in line: + tx_log_lines.append(line) + + collector = SensorStateCollector( + sensor_names=[ + "target_1_x", + "target_1_y", + "target_1_speed", + "target_1_distance", + "target_1_resolution", + "target_1_angle", + "target_2_x", + "target_2_y", + "target_2_speed", + "target_2_distance", + "target_count", + "still_target_count", + "moving_target_count", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + ], + text_sensor_names=[ + "target_1_direction", + ], + ) + + # Signal when we see recovery frame values (target 1 distance ≈ 500mm) + recovery_received = collector.add_waiter( + lambda: ( + pytest.approx(500.0, abs=1.0) + in collector.sensor_states["target_1_distance"] + ) + ) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + collector.build_key_mapping(entities) + + # Set up initial state helper + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + # Start the UART mock scenario now that we're subscribed + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 - all sensors and binary sensors have at least one value + try: + await collector.wait_for_all(timeout=5.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}\n" + f" text_states: {collector.text_sensor_states}" + ) + + # Phase 1 values: + # Target 1: X=-500, Y=1000, Speed=-50 (approaching), Res=320 + # Distance = sqrt(500²+1000²) ≈ 1118mm + assert collector.sensor_states["target_1_x"][0] == pytest.approx(-500.0) + assert collector.sensor_states["target_1_y"][0] == pytest.approx(1000.0) + assert collector.sensor_states["target_1_speed"][0] == pytest.approx(-50.0) + assert collector.sensor_states["target_1_resolution"][0] == pytest.approx(320.0) + # Distance computed from X/Y + assert collector.sensor_states["target_1_distance"][0] == pytest.approx( + 1118.0, abs=1.0 + ) + + # Target 2: X=200, Y=500, Speed=0 (stationary), Res=100 + # Distance = sqrt(200²+500²) ≈ 538mm + assert collector.sensor_states["target_2_x"][0] == pytest.approx(200.0) + assert collector.sensor_states["target_2_y"][0] == pytest.approx(500.0) + assert collector.sensor_states["target_2_speed"][0] == pytest.approx(0.0) + assert collector.sensor_states["target_2_distance"][0] == pytest.approx( + 538.0, abs=1.0 + ) + + # Target counts: 2 targets total, 1 moving, 1 still + assert collector.sensor_states["target_count"][0] == pytest.approx(2.0) + assert collector.sensor_states["moving_target_count"][0] == pytest.approx(1.0) + assert collector.sensor_states["still_target_count"][0] == pytest.approx(1.0) + + # Binary sensors: all true (targets detected) + assert collector.binary_states["has_target"][0] is True + assert collector.binary_states["has_moving_target"][0] is True + assert collector.binary_states["has_still_target"][0] is True + + # Direction text sensor: Target 1 is approaching (speed < 0) + assert collector.text_sensor_states["target_1_direction"][0] == "Approaching" + + # Wait for the recovery frame (Phase 5) to be parsed + # This proves the component survived garbage + truncated + overflow + try: + await asyncio.wait_for(recovery_received, timeout=5.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received:\n" + f" sensor_states: {collector.sensor_states}" + ) + + # Verify overflow warning was logged + assert overflow_seen.done(), ( + "Expected 'Max command length exceeded' warning in logs" + ) + + # Verify LD2450 sent setup commands (TX logging) + assert len(tx_log_lines) > 0, "Expected TX log lines from uart_mock" + tx_data = " ".join(tx_log_lines) + # Verify command frame header appears (FD:FC:FB:FA) + assert "FD:FC:FB:FA" in tx_data, ( + "Expected LD2450 command frame header FD:FC:FB:FA in TX log" + ) + # Verify command frame footer appears (04:03:02:01) + assert "04:03:02:01" in tx_data, ( + "Expected LD2450 command frame footer 04:03:02:01 in TX log" + ) + + # Recovery frame values (Phase 5, after overflow): + # Target 1: X=300, Y=400, Distance=500, Speed=30 (moving away) + # target_count=1, moving=1, still=0 + # + # Note: throttle filters cause sensor lists to have different lengths, + # so we check each value appeared somewhere rather than using a shared index. + assert ( + pytest.approx(500.0, abs=1.0) + in collector.sensor_states["target_1_distance"] + ) + assert pytest.approx(300.0) in collector.sensor_states["target_1_x"] + assert pytest.approx(400.0) in collector.sensor_states["target_1_y"] + assert pytest.approx(30.0) in collector.sensor_states["target_1_speed"] + assert pytest.approx(1.0) in collector.sensor_states["target_count"] + assert pytest.approx(1.0) in collector.sensor_states["moving_target_count"] + assert pytest.approx(0.0) in collector.sensor_states["still_target_count"] From b05dbfccd31ec769bfa873783506b469ac6def27 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:52:21 -1000 Subject: [PATCH 1224/2030] [api] Bump noise-c to 0.1.11 (#14632) --- .clang-tidy.hash | 2 +- esphome/components/api/__init__.py | 2 +- platformio.ini | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index adcebadeb4..ff25675918 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -b6f8c16c1ddd222134bf4a71910b4c832e764e23caf49f9bce3280b079955fcf +e4b9c4b54e705d3c9400e1cdda8ba0b32634780cfa5f32271832e911bdcafe7e diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index dd99862cc2..c7dec6e78b 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -453,7 +453,7 @@ async def to_code(config: ConfigType) -> None: # and plaintext disabled. Only a factory reset can remove it. cg.add_define("USE_API_PLAINTEXT") cg.add_define("USE_API_NOISE") - cg.add_library("esphome/noise-c", "0.1.10") + cg.add_library("esphome/noise-c", "0.1.11") else: cg.add_define("USE_API_PLAINTEXT") diff --git a/platformio.ini b/platformio.ini index 87f992759c..deee23d049 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,7 +46,7 @@ lib_deps_base = lib_deps = ${common.lib_deps_base} - esphome/noise-c@0.1.10 ; api + esphome/noise-c@0.1.11 ; api improv/Improv@1.2.4 ; improv_serial / esp32_improv kikuchan98/pngle@1.1.0 ; online_image ; Using the repository directly, otherwise ESP-IDF can't use the library @@ -542,7 +542,7 @@ build_unflags = extends = common platform = platformio/native lib_deps = - esphome/noise-c@0.1.10 ; used by api + esphome/noise-c@0.1.11 ; used by api build_flags = ${common.build_flags} -DUSE_HOST From 9547a54fac5de13f36a98d670e60ef18b1e88fe8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 14:52:40 -1000 Subject: [PATCH 1225/2030] [const] Move CONF_ENABLE_FULL_PRINTF to const.py (#14633) --- esphome/components/esp32/__init__.py | 2 +- esphome/components/esp8266/__init__.py | 2 +- esphome/components/esp8266/const.py | 1 - esphome/components/rp2040/__init__.py | 9 ++------- esphome/components/rp2040/const.py | 1 - esphome/const.py | 1 + 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 8ad84656ed..52e70501dc 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_BOARD, CONF_COMPONENTS, CONF_DISABLED, + CONF_ENABLE_FULL_PRINTF, CONF_ENABLE_OTA_ROLLBACK, CONF_ESPHOME, CONF_FRAMEWORK, @@ -954,7 +955,6 @@ CONF_HEAP_IN_IRAM = "heap_in_iram" CONF_LOOP_TASK_STACK_SIZE = "loop_task_stack_size" CONF_USE_FULL_CERTIFICATE_BUNDLE = "use_full_certificate_bundle" CONF_DISABLE_DEBUG_STUBS = "disable_debug_stubs" -CONF_ENABLE_FULL_PRINTF = "enable_full_printf" CONF_DISABLE_OCD_AWARE = "disable_ocd_aware" CONF_DISABLE_USB_SERIAL_JTAG_SECONDARY = "disable_usb_serial_jtag_secondary" CONF_DISABLE_DEV_NULL_VFS = "disable_dev_null_vfs" diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 1ef4f5e037..16043b6d69 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -6,6 +6,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_BOARD, CONF_BOARD_FLASH_MODE, + CONF_ENABLE_FULL_PRINTF, CONF_FRAMEWORK, CONF_PLATFORM_VERSION, CONF_SOURCE, @@ -23,7 +24,6 @@ from esphome.helpers import copy_file_if_changed from .boards import BOARDS, ESP8266_LD_SCRIPTS from .const import ( CONF_EARLY_PIN_INIT, - CONF_ENABLE_FULL_PRINTF, CONF_ENABLE_SERIAL, CONF_ENABLE_SERIAL1, CONF_RESTORE_FROM_FLASH, diff --git a/esphome/components/esp8266/const.py b/esphome/components/esp8266/const.py index 57eb54f0f8..229ac61f24 100644 --- a/esphome/components/esp8266/const.py +++ b/esphome/components/esp8266/const.py @@ -6,7 +6,6 @@ KEY_BOARD = "board" KEY_PIN_INITIAL_STATES = "pin_initial_states" CONF_RESTORE_FROM_FLASH = "restore_from_flash" CONF_EARLY_PIN_INIT = "early_pin_init" -CONF_ENABLE_FULL_PRINTF = "enable_full_printf" CONF_ENABLE_SERIAL = "enable_serial" CONF_ENABLE_SERIAL1 = "enable_serial1" KEY_FLASH_SIZE = "flash_size" diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 54e1db27aa..359337adfb 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -6,6 +6,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( CONF_BOARD, + CONF_ENABLE_FULL_PRINTF, CONF_FRAMEWORK, CONF_PLATFORM_VERSION, CONF_SOURCE, @@ -21,13 +22,7 @@ from esphome.const import ( from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority from esphome.helpers import copy_file_if_changed, read_file, write_file_if_changed -from .const import ( - CONF_ENABLE_FULL_PRINTF, - KEY_BOARD, - KEY_PIO_FILES, - KEY_RP2040, - rp2040_ns, -) +from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns # force import gpio to register pin schema from .gpio import rp2040_pin_to_code # noqa diff --git a/esphome/components/rp2040/const.py b/esphome/components/rp2040/const.py index 7eeddffc76..ab5f42d757 100644 --- a/esphome/components/rp2040/const.py +++ b/esphome/components/rp2040/const.py @@ -1,6 +1,5 @@ import esphome.codegen as cg -CONF_ENABLE_FULL_PRINTF = "enable_full_printf" KEY_BOARD = "board" KEY_RP2040 = "rp2040" KEY_PIO_FILES = "pio_files" diff --git a/esphome/const.py b/esphome/const.py index 88e3c33fbc..d409514f3c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -356,6 +356,7 @@ CONF_EFFECT = "effect" CONF_EFFECTS = "effects" CONF_ELSE = "else" CONF_ENABLE_BTM = "enable_btm" +CONF_ENABLE_FULL_PRINTF = "enable_full_printf" CONF_ENABLE_IPV6 = "enable_ipv6" CONF_ENABLE_ON_BOOT = "enable_on_boot" CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" From d0285cdc41d479ed0aa7dc0984a71215ee4ff696 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 15:11:15 -1000 Subject: [PATCH 1226/2030] [core] Pack entity flags into configure_entity_() and protect setters (#14564) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/entity_base.cpp | 14 +- esphome/core/entity_base.h | 31 ++- esphome/core/entity_helpers.py | 84 ++++++- .../binary_sensor/test_binary_sensor.py | 8 +- tests/component_tests/button/test_button.py | 8 +- tests/component_tests/helpers.py | 19 ++ tests/component_tests/sensor/test_sensor.py | 12 +- tests/component_tests/text/test_text.py | 10 +- .../text_sensor/test_text_sensor.py | 20 +- tests/unit_tests/core/test_entity_helpers.py | 222 +++++++++++++++++- 10 files changed, 354 insertions(+), 74 deletions(-) create mode 100644 tests/component_tests/helpers.py diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 3274640eb3..818dae06de 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -11,7 +11,7 @@ static const char *const TAG = "entity_base"; // Entity Name const StringRef &EntityBase::get_name() const { return this->name_; } -void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_strings_packed) { +void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_fields) { this->name_ = StringRef(name); if (this->name_.empty()) { #ifdef USE_DEVICES @@ -44,17 +44,19 @@ void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, ui this->calc_object_id_(); } } - // Unpack entity string table indices. - // Packed: [23..16] icon | [15..8] UoM | [7..0] device_class (each 8 bits) + // Unpack entity string table indices and flags from entity_fields. #ifdef USE_ENTITY_DEVICE_CLASS - this->device_class_idx_ = entity_strings_packed & 0xFF; + this->device_class_idx_ = (entity_fields >> ENTITY_FIELD_DC_SHIFT) & 0xFF; #endif #ifdef USE_ENTITY_UNIT_OF_MEASUREMENT - this->uom_idx_ = (entity_strings_packed >> 8) & 0xFF; + this->uom_idx_ = (entity_fields >> ENTITY_FIELD_UOM_SHIFT) & 0xFF; #endif #ifdef USE_ENTITY_ICON - this->icon_idx_ = (entity_strings_packed >> 16) & 0xFF; + this->icon_idx_ = (entity_fields >> ENTITY_FIELD_ICON_SHIFT) & 0xFF; #endif + this->flags_.internal = (entity_fields >> ENTITY_FIELD_INTERNAL_SHIFT) & 1; + this->flags_.disabled_by_default = (entity_fields >> ENTITY_FIELD_DISABLED_BY_DEFAULT_SHIFT) & 1; + this->flags_.entity_category = (entity_fields >> ENTITY_FIELD_ENTITY_CATEGORY_SHIFT) & 0x3; } // Weak default lookup functions — overridden by generated code in main.cpp diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index accd532b0d..cccbafd2c3 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -55,6 +55,15 @@ enum EntityCategory : uint8_t { ENTITY_CATEGORY_DIAGNOSTIC = 2, }; +// Bit layout for entity_fields parameter in configure_entity_(). +// Keep in sync with _*_SHIFT constants in esphome/core/entity_helpers.py +static constexpr uint8_t ENTITY_FIELD_DC_SHIFT = 0; +static constexpr uint8_t ENTITY_FIELD_UOM_SHIFT = 8; +static constexpr uint8_t ENTITY_FIELD_ICON_SHIFT = 16; +static constexpr uint8_t ENTITY_FIELD_INTERNAL_SHIFT = 24; +static constexpr uint8_t ENTITY_FIELD_DISABLED_BY_DEFAULT_SHIFT = 25; +static constexpr uint8_t ENTITY_FIELD_ENTITY_CATEGORY_SHIFT = 26; + // The generic Entity base class that provides an interface common to all Entities. class EntityBase { public: @@ -88,21 +97,16 @@ class EntityBase { /// Useful for building compound strings without intermediate buffer size_t write_object_id_to(char *buf, size_t buf_size) const; - // Get/set whether this Entity should be hidden outside ESPHome + // Get whether this Entity should be hidden outside ESPHome bool is_internal() const { return this->flags_.internal; } - void set_internal(bool internal) { this->flags_.internal = internal; } // Check if this object is declared to be disabled by default. // That means that when the device gets added to Home Assistant (or other clients) it should // not be added to the default view by default, and a user action is necessary to manually add it. bool is_disabled_by_default() const { return this->flags_.disabled_by_default; } - void set_disabled_by_default(bool disabled_by_default) { this->flags_.disabled_by_default = disabled_by_default; } - // Get/set the entity category. + // Get the entity category. EntityCategory get_entity_category() const { return static_cast<EntityCategory>(this->flags_.entity_category); } - void set_entity_category(EntityCategory entity_category) { - this->flags_.entity_category = static_cast<uint8_t>(entity_category); - } // Get this entity's device class into a stack buffer. // On non-ESP8266: returns pointer to PROGMEM string directly (buffer unused). @@ -164,14 +168,13 @@ class EntityBase { #endif #ifdef USE_DEVICES - // Get/set this entity's device id + // Get this entity's device id uint32_t get_device_id() const { if (this->device_ == nullptr) { return 0; // No device set, return 0 } return this->device_->get_device_id(); } - void set_device(Device *device) { this->device_ = device; } // Get the device this entity belongs to (nullptr if main device) Device *get_device() const { return this->device_; } #endif @@ -228,8 +231,14 @@ class EntityBase { friend void ::setup(); friend void ::original_setup(); - /// Combined entity setup from codegen: set name, object_id hash, and entity string indices. - void configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_strings_packed); + /// Combined entity setup from codegen: set name, object_id hash, entity string indices, and flags. + /// Bit layout of entity_fields is defined by the ENTITY_FIELD_*_SHIFT constants above. + void configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_fields); + +#ifdef USE_DEVICES + // Codegen-only setter — only accessible from setup() via friend declaration. + void set_device_(Device *device) { this->device_ = device; } +#endif /// Non-template helper for make_entity_preference() to avoid code bloat. /// When preference hash algorithm changes, migration logic goes here. diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index 4fa109fb0e..0589b92364 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -34,11 +34,19 @@ _KEY_ICON_IDX = "_entity_icon_idx" _KEY_ENTITY_NAME = "_entity_name" _KEY_OBJECT_ID_HASH = "_entity_object_id_hash" -# Bit layout for entity_strings_packed in configure_entity_() — must match C++ in entity_base.h: -# [23..16] icon (8 bits) | [15..8] UoM (8 bits) | [7..0] device_class (8 bits) +# Bit layout for entity_fields in configure_entity_(). +# Keep in sync with ENTITY_FIELD_*_SHIFT constants in esphome/core/entity_base.h _DC_SHIFT = 0 _UOM_SHIFT = 8 _ICON_SHIFT = 16 +_INTERNAL_SHIFT = 24 +_DISABLED_BY_DEFAULT_SHIFT = 25 +_ENTITY_CATEGORY_SHIFT = 26 + +# Private config keys for storing flags +_KEY_INTERNAL = "_entity_internal" +_KEY_DISABLED_BY_DEFAULT = "_entity_disabled_by_default" +_KEY_ENTITY_CATEGORY = "_entity_category" # Maximum unique strings per category (8-bit index, 0 = not set) _MAX_DEVICE_CLASSES = 0xFF # 255 @@ -220,8 +228,39 @@ def setup_unit_of_measurement(config: ConfigType) -> None: config[_KEY_UOM_IDX] = idx +def _sanitize_comment(text: str) -> str: + r"""Sanitize a string for safe inclusion in a C++ // line comment. + + Dangerous characters: + - \n, \r: break out of line comment, next line becomes code + - \: at end of line, splices next line into comment (eats real code) + """ + return text.replace("\\", "/").replace("\n", " ").replace("\r", "") + + +def _describe_packed_flags(config: ConfigType, entity_category: int) -> str: + """Build a human-readable description of packed entity flags for C++ comments.""" + parts: list[str] = [] + if config.get(_KEY_INTERNAL): + parts.append("internal") + if config.get(_KEY_DISABLED_BY_DEFAULT): + parts.append("disabled_by_default") + entity_cat_keys = list(cv.ENTITY_CATEGORIES) + if entity_category < len(entity_cat_keys) and ( + cat_name := entity_cat_keys[entity_category] + ): + parts.append(f"category:{cat_name}") + if config.get(_KEY_DC_IDX) and (dc := config.get(CONF_DEVICE_CLASS)): + parts.append(f"dc:{_sanitize_comment(dc)}") + if config.get(_KEY_UOM_IDX) and (uom := config.get(CONF_UNIT_OF_MEASUREMENT)): + parts.append(f"uom:{_sanitize_comment(uom)}") + if config.get(_KEY_ICON_IDX) and (icon := config.get(CONF_ICON)): + parts.append(f"icon:{_sanitize_comment(icon)}") + return ", ".join(parts) + + def finalize_entity_strings(var: MockObj, config: ConfigType) -> None: - """Emit a single configure_entity_() call with name, hash, and packed string indices. + """Emit a single configure_entity_() call with name, hash, packed string indices, and flags. Call this at the end of each component's setup function, after setup_entity() and any register_device_class/register_unit_of_measurement calls. @@ -231,8 +270,24 @@ def finalize_entity_strings(var: MockObj, config: ConfigType) -> None: dc_idx = config.get(_KEY_DC_IDX, 0) uom_idx = config.get(_KEY_UOM_IDX, 0) icon_idx = config.get(_KEY_ICON_IDX, 0) - packed = (dc_idx << _DC_SHIFT) | (uom_idx << _UOM_SHIFT) | (icon_idx << _ICON_SHIFT) - add(var.configure_entity_(entity_name, object_id_hash, packed)) + internal = config.get(_KEY_INTERNAL, 0) + disabled_by_default = config.get(_KEY_DISABLED_BY_DEFAULT, 0) + entity_category = config.get(_KEY_ENTITY_CATEGORY, 0) + packed = ( + (dc_idx << _DC_SHIFT) + | (uom_idx << _UOM_SHIFT) + | (icon_idx << _ICON_SHIFT) + | (internal << _INTERNAL_SHIFT) + | (disabled_by_default << _DISABLED_BY_DEFAULT_SHIFT) + | (entity_category << _ENTITY_CATEGORY_SHIFT) + ) + # Build inline comment describing the packed flags for readability + comment = _describe_packed_flags(config, entity_category) + expr = var.configure_entity_(entity_name, object_id_hash, packed) + if comment: + add(RawStatement(f"{expr}; // {comment}")) + else: + add(expr) def get_base_entity_object_id( @@ -332,7 +387,7 @@ async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> # Get device info if configured if device_id_obj := config.get(CONF_DEVICE_ID): device: MockObj = await get_variable(device_id_obj) - add(var.set_device(device)) + add(var.set_device_(device)) # Pre-compute entity name and object_id hash for configure_entity_() # which is emitted later by finalize_entity_strings(). @@ -343,18 +398,25 @@ async def _setup_entity_impl(var: MockObj, config: ConfigType, platform: str) -> object_id_hash = fnv1_hash_object_id(entity_name) if entity_name else 0 config[_KEY_ENTITY_NAME] = entity_name config[_KEY_OBJECT_ID_HASH] = object_id_hash - # Only set disabled_by_default if True (default is False) - if config[CONF_DISABLED_BY_DEFAULT]: - add(var.set_disabled_by_default(True)) + # Store flags for packing into configure_entity_() + config[_KEY_DISABLED_BY_DEFAULT] = int(config[CONF_DISABLED_BY_DEFAULT]) if CONF_INTERNAL in config: - add(var.set_internal(config[CONF_INTERNAL])) + config[_KEY_INTERNAL] = int(config[CONF_INTERNAL]) icon_idx = 0 if CONF_ICON in config: # Add USE_ENTITY_ICON define when icons are used cg.add_define("USE_ENTITY_ICON") icon_idx = register_icon(config[CONF_ICON]) if CONF_ENTITY_CATEGORY in config: - add(var.set_entity_category(config[CONF_ENTITY_CATEGORY])) + # Derive integer value from key position in cv.ENTITY_CATEGORIES + # (must match C++ EntityCategory enum in entity_base.h) + entity_cat_str = str(config[CONF_ENTITY_CATEGORY]) + entity_cat_keys = list(cv.ENTITY_CATEGORIES) + config[_KEY_ENTITY_CATEGORY] = ( + entity_cat_keys.index(entity_cat_str) + if entity_cat_str in entity_cat_keys + else 0 + ) # Store icon index for finalize_entity_strings config[_KEY_ICON_IDX] = icon_idx diff --git a/tests/component_tests/binary_sensor/test_binary_sensor.py b/tests/component_tests/binary_sensor/test_binary_sensor.py index fbc2f37d9a..10d7f80834 100644 --- a/tests/component_tests/binary_sensor/test_binary_sensor.py +++ b/tests/component_tests/binary_sensor/test_binary_sensor.py @@ -1,5 +1,7 @@ """Tests for the binary sensor component.""" +from tests.component_tests.helpers import INTERNAL_BIT, extract_packed_value + def test_binary_sensor_is_setup(generate_main): """ @@ -44,9 +46,9 @@ def test_binary_sensor_config_value_internal_set(generate_main): "tests/component_tests/binary_sensor/test_binary_sensor.yaml" ) - # Then - assert "bs_1->set_internal(true);" in main_cpp - assert "bs_2->set_internal(false);" in main_cpp + # Then: bs_1 has internal: true, bs_2 has internal: false + assert extract_packed_value(main_cpp, "bs_1") & INTERNAL_BIT != 0 + assert extract_packed_value(main_cpp, "bs_2") & INTERNAL_BIT == 0 def test_binary_sensor_config_value_use_raw_set(generate_main): diff --git a/tests/component_tests/button/test_button.py b/tests/component_tests/button/test_button.py index 9f94d61c8c..a35994a682 100644 --- a/tests/component_tests/button/test_button.py +++ b/tests/component_tests/button/test_button.py @@ -1,5 +1,7 @@ """Tests for the button component""" +from tests.component_tests.helpers import INTERNAL_BIT, extract_packed_value + def test_button_is_setup(generate_main): """ @@ -39,6 +41,6 @@ def test_button_config_value_internal_set(generate_main): # When main_cpp = generate_main("tests/component_tests/button/test_button.yaml") - # Then - assert "wol_1->set_internal(true);" in main_cpp - assert "wol_2->set_internal(false);" in main_cpp + # Then: wol_1 has internal: true, wol_2 has internal: false + assert extract_packed_value(main_cpp, "wol_1") & INTERNAL_BIT != 0 + assert extract_packed_value(main_cpp, "wol_2") & INTERNAL_BIT == 0 diff --git a/tests/component_tests/helpers.py b/tests/component_tests/helpers.py new file mode 100644 index 0000000000..568d1639d0 --- /dev/null +++ b/tests/component_tests/helpers.py @@ -0,0 +1,19 @@ +"""Shared helpers for component tests.""" + +from __future__ import annotations + +import re + +INTERNAL_BIT = 1 << 24 + + +def extract_packed_value(main_cpp: str, var_name: str) -> int: + """Extract the third (packed) argument from a configure_entity_ call.""" + pattern = ( + rf"{re.escape(var_name)}->configure_entity_\(" + r'"(?:\\.|[^"\\])*"' + r",\s*\w+,\s*(\d+)\)" + ) + match = re.search(pattern, main_cpp) + assert match, f"configure_entity_ call not found for {var_name}" + return int(match.group(1)) diff --git a/tests/component_tests/sensor/test_sensor.py b/tests/component_tests/sensor/test_sensor.py index d9ab3a022c..9d18fa36b8 100644 --- a/tests/component_tests/sensor/test_sensor.py +++ b/tests/component_tests/sensor/test_sensor.py @@ -1,14 +1,6 @@ """Tests for the sensor component.""" -import re - - -def _extract_packed_value(main_cpp, var_name): - """Extract the third (packed) argument from a configure_entity_ call.""" - pattern = rf"{re.escape(var_name)}->configure_entity_\([^,]+,\s*\w+,\s*(\d+)\)" - match = re.search(pattern, main_cpp) - assert match, f"configure_entity_ call not found for {var_name}" - return int(match.group(1)) +from tests.component_tests.helpers import extract_packed_value def test_sensor_device_class_set(generate_main): @@ -21,5 +13,5 @@ def test_sensor_device_class_set(generate_main): main_cpp = generate_main("tests/component_tests/sensor/test_sensor.yaml") # Then: device_class: voltage means packed value must be non-zero - packed = _extract_packed_value(main_cpp, "s_1") + packed = extract_packed_value(main_cpp, "s_1") assert packed != 0 diff --git a/tests/component_tests/text/test_text.py b/tests/component_tests/text/test_text.py index 3ceaa9b8f8..c74dfb8a47 100644 --- a/tests/component_tests/text/test_text.py +++ b/tests/component_tests/text/test_text.py @@ -1,4 +1,6 @@ -"""Tests for the binary sensor component.""" +"""Tests for the text component.""" + +from tests.component_tests.helpers import INTERNAL_BIT, extract_packed_value def test_text_is_setup(generate_main): @@ -37,9 +39,9 @@ def test_text_config_value_internal_set(generate_main): # When main_cpp = generate_main("tests/component_tests/text/test_text.yaml") - # Then - assert "it_2->set_internal(false);" in main_cpp - assert "it_3->set_internal(true);" in main_cpp + # Then: it_2 has internal: false, it_3 has internal: true + assert extract_packed_value(main_cpp, "it_2") & INTERNAL_BIT == 0 + assert extract_packed_value(main_cpp, "it_3") & INTERNAL_BIT != 0 def test_text_config_value_mode_set(generate_main): diff --git a/tests/component_tests/text_sensor/test_text_sensor.py b/tests/component_tests/text_sensor/test_text_sensor.py index f30b820e94..1ff31ab96b 100644 --- a/tests/component_tests/text_sensor/test_text_sensor.py +++ b/tests/component_tests/text_sensor/test_text_sensor.py @@ -1,14 +1,6 @@ """Tests for the text sensor component.""" -import re - - -def _extract_packed_value(main_cpp, var_name): - """Extract the third (packed) argument from a configure_entity_ call.""" - pattern = rf"{re.escape(var_name)}->configure_entity_\([^,]+,\s*\w+,\s*(\d+)\)" - match = re.search(pattern, main_cpp) - assert match, f"configure_entity_ call not found for {var_name}" - return int(match.group(1)) +from tests.component_tests.helpers import INTERNAL_BIT, extract_packed_value def test_text_sensor_is_setup(generate_main): @@ -49,9 +41,9 @@ def test_text_sensor_config_value_internal_set(generate_main): # When main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") - # Then - assert "ts_2->set_internal(true);" in main_cpp - assert "ts_3->set_internal(false);" in main_cpp + # Then: ts_2 has internal: true, ts_3 has internal: false + assert extract_packed_value(main_cpp, "ts_2") & INTERNAL_BIT != 0 + assert extract_packed_value(main_cpp, "ts_3") & INTERNAL_BIT == 0 def test_text_sensor_device_class_set(generate_main): @@ -65,7 +57,7 @@ def test_text_sensor_device_class_set(generate_main): # Then: ts_2 has device_class: timestamp, ts_3 has device_class: date # so their packed values must be non-zero - packed_ts_2 = _extract_packed_value(main_cpp, "ts_2") + packed_ts_2 = extract_packed_value(main_cpp, "ts_2") assert packed_ts_2 != 0 - packed_ts_3 = _extract_packed_value(main_cpp, "ts_3") + packed_ts_3 = extract_packed_value(main_cpp, "ts_3") assert packed_ts_3 != 0 diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index 3f6faaee54..d6cbb8c6be 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -9,6 +9,7 @@ import pytest from esphome.config_validation import Invalid from esphome.const import ( + CONF_DEVICE_CLASS, CONF_DEVICE_ID, CONF_DISABLED_BY_DEFAULT, CONF_ENTITY_CATEGORY, @@ -16,16 +17,20 @@ from esphome.const import ( CONF_ID, CONF_INTERNAL, CONF_NAME, + CONF_UNIT_OF_MEASUREMENT, ) from esphome.core import CORE, ID, entity_helpers from esphome.core.entity_helpers import ( _register_string, _setup_entity_impl, entity_duplicate_validator, + finalize_entity_strings, get_base_entity_object_id, register_device_class, register_icon, + setup_device_class, setup_entity, + setup_unit_of_measurement, ) from esphome.cpp_generator import MockObj from esphome.helpers import sanitize, snake_case @@ -486,8 +491,6 @@ async def test_setup_entity_disabled_by_default( ) -> None: """Test setup_entity sets disabled_by_default correctly.""" - added_expressions = setup_test_environment - var = MockObj("sensor1") config = { @@ -497,10 +500,8 @@ async def test_setup_entity_disabled_by_default( await _setup_entity_impl(var, config, "sensor") - # Check disabled_by_default was set - assert any( - "sensor1.set_disabled_by_default(true)" in expr for expr in added_expressions - ) + # disabled_by_default is now packed into config for configure_entity_() + assert config.get("_entity_disabled_by_default") == 1 def test_entity_duplicate_validator() -> None: @@ -785,8 +786,8 @@ async def test_setup_entity_empty_name_with_device( entity_helpers.get_variable = original_get_variable - # Check that set_device was called - assert any("sensor1.set_device" in expr for expr in added_expressions) + # Check that set_device_ was called (separate protected call, accessible via friend) + assert any("sensor1.set_device_" in expr for expr in added_expressions) # For empty-name entities, Python stores hash 0 - C++ calculates hash at runtime assert config.get("_entity_name") == "" @@ -928,7 +929,7 @@ def test_register_device_class_max_length() -> None: async def test_setup_entity_with_entity_category( setup_test_environment: list[str], ) -> None: - """Test setup_entity sets entity_category correctly.""" + """Test entity_category is packed correctly through the full setup flow.""" added_expressions = setup_test_environment var = MockObj("sensor1") config = { @@ -937,9 +938,10 @@ async def test_setup_entity_with_entity_category( CONF_ENTITY_CATEGORY: "diagnostic", } await _setup_entity_impl(var, config, "sensor") - assert any( - 'set_entity_category("diagnostic")' in expr for expr in added_expressions - ) + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed != 0 + assert "category:diagnostic" in added_expressions[0] @pytest.mark.asyncio @@ -988,3 +990,199 @@ async def test_setup_entity_decorator_mode(setup_test_environment: list[str]) -> assert body_called object_id = extract_object_id_from_expressions(added_expressions) assert object_id == "temperature" + + +# Tests for finalize_entity_strings packing +# +# These tests verify that flags and string indices produce non-zero packed values +# and correct inline comments. The actual bit layout correctness (Python _*_SHIFT +# matching C++ ENTITY_FIELD_*_SHIFT) is verified end-to-end by the integration +# test test_host_mode_entity_fields, which compiles firmware and checks values +# via the native API. + + +def _extract_packed_value(expressions: list[str]) -> int: + """Extract the third argument (packed value) from a configure_entity_() call.""" + for expr in expressions: + if "configure_entity_" in expr: + # Match the last integer argument before the closing ");" + match = re.search(r",\s*(\d+)\s*\)", expr) + if match: + return int(match.group(1)) + raise AssertionError("No configure_entity_ call found") + + +@pytest.mark.asyncio +async def test_finalize_no_flags(setup_test_environment: list[str]) -> None: + """Test entity with no special flags — packed value is 0, no comment.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: False, + } + await _setup_entity_impl(var, config, "sensor") + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed == 0 + assert "//" not in added_expressions[0] + + +@pytest.mark.asyncio +async def test_finalize_internal(setup_test_environment: list[str]) -> None: + """Test entity with internal=True packs the internal flag.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: False, + CONF_INTERNAL: True, + } + await _setup_entity_impl(var, config, "sensor") + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed != 0 + assert "// internal" in added_expressions[0] + + +@pytest.mark.asyncio +async def test_finalize_disabled_by_default( + setup_test_environment: list[str], +) -> None: + """Test entity with disabled_by_default=True packs the flag.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: True, + } + await _setup_entity_impl(var, config, "sensor") + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed != 0 + assert "// disabled_by_default" in added_expressions[0] + + +@pytest.mark.asyncio +async def test_finalize_entity_category( + setup_test_environment: list[str], +) -> None: + """Test entity_category values are packed and described in comment.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + + # Test diagnostic + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: False, + CONF_ENTITY_CATEGORY: "diagnostic", + } + await _setup_entity_impl(var, config, "sensor") + finalize_entity_strings(var, config) + packed_diag = _extract_packed_value(added_expressions) + assert packed_diag != 0 + assert "category:diagnostic" in added_expressions[0] + + # Test config — different packed value + added_expressions.clear() + config2 = { + CONF_NAME: "Test2", + CONF_DISABLED_BY_DEFAULT: False, + CONF_ENTITY_CATEGORY: "config", + } + await _setup_entity_impl(var, config2, "sensor") + finalize_entity_strings(var, config2) + packed_cfg = _extract_packed_value(added_expressions) + assert packed_cfg != 0 + assert packed_cfg != packed_diag + assert "category:config" in added_expressions[0] + + +@pytest.mark.asyncio +async def test_finalize_string_indices( + setup_test_environment: list[str], +) -> None: + """Test device_class, unit_of_measurement, and icon produce non-zero packed value.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: False, + CONF_DEVICE_CLASS: "temperature", + CONF_UNIT_OF_MEASUREMENT: "°C", + CONF_ICON: "mdi:thermometer", + } + await _setup_entity_impl(var, config, "sensor") + setup_device_class(config) + setup_unit_of_measurement(config) + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed != 0 + comment = added_expressions[0] + assert "dc:temperature" in comment + assert "uom:°C" in comment + assert "icon:mdi:thermometer" in comment + + +@pytest.mark.asyncio +async def test_finalize_all_fields( + setup_test_environment: list[str], +) -> None: + """Test all fields set: flags, string indices, and comment.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: True, + CONF_INTERNAL: True, + CONF_ENTITY_CATEGORY: "diagnostic", + CONF_DEVICE_CLASS: "temperature", + CONF_UNIT_OF_MEASUREMENT: "°C", + CONF_ICON: "mdi:thermometer", + } + await _setup_entity_impl(var, config, "sensor") + setup_device_class(config) + setup_unit_of_measurement(config) + finalize_entity_strings(var, config) + packed = _extract_packed_value(added_expressions) + assert packed != 0 + # Verify comment contains all flags with actual string values + comment_line = added_expressions[0] + assert ( + "// internal, disabled_by_default, category:diagnostic," + " dc:temperature, uom:°C, icon:mdi:thermometer" in comment_line + ) + + +@pytest.mark.asyncio +async def test_finalize_comment_sanitization( + setup_test_environment: list[str], +) -> None: + """Test that user strings in comments are sanitized against injection.""" + added_expressions = setup_test_environment + var = MockObj("sensor1") + config = { + CONF_NAME: "Test", + CONF_DISABLED_BY_DEFAULT: False, + # Backslash at end would cause line splice eating next code line + CONF_ICON: "mdi:evil\\", + } + await _setup_entity_impl(var, config, "sensor") + finalize_entity_strings(var, config) + comment_line = added_expressions[0] + # Backslash must be replaced to prevent line splice + assert "\\" not in comment_line + assert "mdi:evil/" in comment_line + + added_expressions.clear() + config2 = { + CONF_NAME: "Test2", + CONF_DISABLED_BY_DEFAULT: False, + CONF_ICON: "mdi:evil\nINJECTED_CODE();", + } + await _setup_entity_impl(var, config2, "sensor") + finalize_entity_strings(var, config2) + comment_line = added_expressions[0] + # Newline must be replaced to prevent breaking out of comment + assert "\n" not in comment_line + assert "INJECTED_CODE" in comment_line # still visible but safe in comment From c681dc8872f88f894bb3b71026ffbec013c1bdc9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 15:11:24 -1000 Subject: [PATCH 1227/2030] [socket] Add socket wake support for RP2040 (#14498) --- .../components/socket/lwip_raw_tcp_impl.cpp | 73 ++++++++++++++++++- esphome/components/socket/socket.h | 12 ++- esphome/core/application.cpp | 8 +- esphome/core/application.h | 8 +- esphome/core/component.cpp | 4 +- 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index d697bd47a5..445a57809d 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -11,6 +11,9 @@ #ifdef USE_ESP8266 #include <coredecls.h> // For esp_schedule() +#elif defined(USE_RP2040) +#include <hardware/sync.h> // For __sev(), __wfe() +#include <pico/time.h> // For add_alarm_in_ms(), cancel_alarm() #endif namespace esphome::socket { @@ -40,6 +43,72 @@ void IRAM_ATTR socket_wake() { s_socket_woke = true; esp_schedule(); } +#elif defined(USE_RP2040) +// RP2040 (non-FreeRTOS) socket wake using hardware WFE/SEV instructions. +// +// Same pattern as ESP8266's esp_delay()/esp_schedule(): set a one-shot timer, +// then sleep with __wfe(). Wake on either: +// - Timer alarm fires → callback calls __sev() → __wfe() returns → timeout +// - Socket data arrives → LWIP callback calls socket_wake() → __sev() → __wfe() returns → early wake +// +// CYW43 WiFi chip communicates via SPI interrupts on core 0. When data arrives, +// the GPIO interrupt fires → async_context pendsv processes CYW43/LWIP → recv/accept +// callbacks call socket_wake() → __sev() wakes the main loop from __wfe() sleep. +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +static volatile bool s_socket_woke = false; +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +static volatile bool s_delay_expired = false; + +static int64_t alarm_callback(alarm_id_t id, void *user_data) { + (void) id; + (void) user_data; + s_delay_expired = true; + // Wake the main loop from __wfe() sleep — timeout expired. + __sev(); + // Return 0 = don't reschedule (one-shot) + return 0; +} + +void socket_delay(uint32_t ms) { + if (ms == 0) { + yield(); + return; + } + // If a wake was already signalled, consume it and return immediately + // instead of going to sleep. This avoids losing a wake that arrived + // between loop iterations. + if (s_socket_woke) { + s_socket_woke = false; + return; + } + s_socket_woke = false; + s_delay_expired = false; + // Set a one-shot timer to wake us after the timeout. + // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. + alarm_id_t alarm = add_alarm_in_ms(ms, alarm_callback, nullptr, true); + if (alarm <= 0) { + delay(ms); + return; + } + // Sleep until woken by either the timer alarm or socket_wake(). + // __wfe() may return spuriously (stale event register, other interrupts), + // so we loop checking both flags. + while (!s_socket_woke && !s_delay_expired) { + __wfe(); + } + // Cancel timer if we woke early (socket data arrived before timeout) + if (!s_delay_expired) + cancel_alarm(alarm); +} + +// No IRAM_ATTR equivalent needed: on RP2040, CYW43 async_context runs LWIP +// callbacks via pendsv (not hard IRQ), so they execute from flash safely. +void socket_wake() { + s_socket_woke = true; + // Wake the main loop from __wfe() sleep. __sev() is a global event that + // wakes any core sleeping in __wfe(). This is ISR-safe. + __sev(); +} #endif static const char *const TAG = "socket.lwip"; @@ -371,7 +440,7 @@ err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { } else { pbuf_cat(this->rx_buf_, pb); } -#ifdef USE_ESP8266 +#if (defined(USE_ESP8266) || defined(USE_RP2040)) // Wake the main loop immediately so it can process the received data. socket_wake(); #endif @@ -650,7 +719,7 @@ err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { sock->init(); this->accepted_sockets_[this->accepted_socket_count_++] = std::move(sock); LWIP_LOG("Accepted connection, queue size: %d", this->accepted_socket_count_); -#ifdef USE_ESP8266 +#if (defined(USE_ESP8266) || defined(USE_RP2040)) // Wake the main loop immediately so it can accept the new connection. socket_wake(); #endif diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 0884e4ba3e..a21bd64730 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -120,13 +120,17 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po /// Format sockaddr into caller-provided buffer, returns length written (excluding null) size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::span<char, SOCKADDR_STR_LEN> buf); -#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) /// Delay that can be woken early by socket activity. -/// On ESP8266, lwip callbacks set a flag and call esp_schedule() to wake the delay. +/// On ESP8266, uses esp_delay() with a callback that checks socket activity. +/// On RP2040, uses __wfe() (Wait For Event) to truly sleep until an interrupt +/// (for example, CYW43 GPIO or a timer alarm) fires and wakes the CPU. void socket_delay(uint32_t ms); -/// Signal socket/IO activity and wake the main loop from esp_delay() early. -/// ISR-safe: uses IRAM_ATTR internally and only sets a volatile flag + esp_schedule(). +/// Signal socket/IO activity and wake the main loop early. +/// On ESP8266: sets flag + esp_schedule(). +/// On RP2040: sets flag + __sev() (Send Event) to wake from __wfe(). +/// ISR-safe on both platforms. void socket_wake(); // NOLINT(readability-redundant-declaration) #endif diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index db1c8a0c0a..8685bff360 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -32,7 +32,7 @@ #include "esphome/components/status_led/status_led.h" #endif -#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) #include "esphome/components/socket/socket.h" #endif @@ -713,8 +713,10 @@ void Application::yield_with_select_(uint32_t delay_ms) { } // No sockets registered or select() failed - use regular delay delay(delay_ms); -#elif defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) - // No select support but can wake on socket activity via esp_schedule() +#elif (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) + // No select support but can wake on socket activity + // ESP8266: via esp_schedule() + // RP2040: via __sev()/__wfe() hardware sleep/wake socket::socket_delay(delay_ms); #else // No select support, use regular delay diff --git a/esphome/core/application.h b/esphome/core/application.h index 49253b6324..f357c6b1a3 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -34,7 +34,7 @@ #endif #endif #endif // USE_SOCKET_SELECT_SUPPORT -#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) +#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) namespace esphome::socket { void socket_wake(); // NOLINT(readability-redundant-declaration) } // namespace esphome::socket @@ -565,8 +565,12 @@ class Application { #if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) /// Wake the main event loop from any context (ISR, thread, or main loop). - /// On ESP8266: sets the socket wake flag and calls esp_schedule() to exit esp_delay() early. + /// Sets the socket wake flag and calls esp_schedule() to exit esp_delay() early. static void IRAM_ATTR wake_loop_any_context() { socket::socket_wake(); } +#elif defined(USE_RP2040) && defined(USE_SOCKET_IMPL_LWIP_TCP) + /// Wake the main event loop from any context. + /// Sets the socket wake flag and calls __sev() to exit __wfe() early. + static void wake_loop_any_context() { socket::socket_wake(); } #endif protected: diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 2879d4b5ab..cce0c7b3e0 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -322,11 +322,13 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // 8. Race condition with main loop is handled by clearing flag before processing this->pending_enable_loop_ = true; App.has_pending_enable_loop_requests_ = true; -#if (defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32)) || (defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP)) +#if (defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32)) || \ + ((defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP)) // Wake the main loop from sleep. Without this, the main loop would not // wake until the select/delay timeout expires (~16ms). // ESP32: uses xPortInIsrContext() to choose the correct FreeRTOS notify API. // ESP8266: sets socket wake flag and calls esp_schedule() to exit esp_delay() early. + // RP2040: sets socket wake flag and calls __sev() to exit __wfe() early. Application::wake_loop_any_context(); #endif } From 6ba5c9a7056a07fe431ebf3689dbda307892ea85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 15:22:39 -1000 Subject: [PATCH 1228/2030] [api] Skip state_action_() call in noise data path (#14629) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/api_frame_helper.h | 11 +++++++++++ .../components/api/api_frame_helper_noise.cpp | 18 ++++-------------- .../api/api_frame_helper_plaintext.cpp | 14 +++++++------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 2b4e9ea3cd..151314658e 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -232,6 +232,17 @@ class APIFrameHelper { EXPLICIT_REJECT = 8, // Noise only }; + // Fast inline state check for read_packet/write_protobuf_messages hot path. + // Returns OK only in DATA state; maps CLOSED/FAILED to BAD_STATE and any + // other intermediate state to WOULD_BLOCK. + inline APIError ESPHOME_ALWAYS_INLINE check_data_state_() const { + if (this->state_ == State::DATA) + return APIError::OK; + if (this->state_ == State::CLOSED || this->state_ == State::FAILED) + return APIError::BAD_STATE; + return APIError::WOULD_BLOCK; + } + // Containers (size varies, but typically 12+ bytes on 32-bit) std::array<std::unique_ptr<SendBuffer>, API_MAX_SEND_QUEUE> tx_buf_; std::vector<uint8_t> rx_buf_; diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index ba4f2f0642..62523fb835 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -397,14 +397,9 @@ void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reaso state_ = orig_state; } APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { - APIError aerr = this->state_action_(); - if (aerr != APIError::OK) { + APIError aerr = this->check_data_state_(); + if (aerr != APIError::OK) return aerr; - } - - if (this->state_ != State::DATA) { - return APIError::WOULD_BLOCK; - } aerr = this->try_read_frame_(); if (aerr != APIError::OK) @@ -461,14 +456,9 @@ APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuff } APIError APINoiseFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) { - APIError aerr = state_action_(); - if (aerr != APIError::OK) { + APIError aerr = this->check_data_state_(); + if (aerr != APIError::OK) return aerr; - } - - if (state_ != State::DATA) { - return APIError::WOULD_BLOCK; - } if (messages.empty()) { return APIError::OK; diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index e2bb56e0ac..3c54ed7c70 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -195,11 +195,11 @@ APIError APIPlaintextFrameHelper::try_read_frame_() { } APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { - if (this->state_ != State::DATA) { - return APIError::WOULD_BLOCK; - } + APIError aerr = this->check_data_state_(); + if (aerr != APIError::OK) + return aerr; - APIError aerr = this->try_read_frame_(); + aerr = this->try_read_frame_(); if (aerr != APIError::OK) { if (aerr == APIError::BAD_INDICATOR) { // Make sure to tell the remote that we don't @@ -244,9 +244,9 @@ APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWrite APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) { - if (state_ != State::DATA) { - return APIError::BAD_STATE; - } + APIError aerr = this->check_data_state_(); + if (aerr != APIError::OK) + return aerr; if (messages.empty()) { return APIError::OK; From cac751e9e8d1a185ede1f001bb19cc397a3b6a7f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 9 Mar 2026 02:29:41 +0100 Subject: [PATCH 1229/2030] [nextion] Add configurable HTTP parameters for TFT upload (#14234) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/nextion/base_component.py | 3 + esphome/components/nextion/display.py | 66 +++++++++++++++++-- esphome/components/nextion/nextion.cpp | 12 ++++ esphome/components/nextion/nextion.h | 31 +++++++++ .../nextion/nextion_upload_arduino.cpp | 10 +-- .../nextion/nextion_upload_esp32.cpp | 8 ++- .../components/nextion/common_tft_upload.yaml | 5 ++ .../nextion/common_tft_upload_watchdog.yaml | 3 + tests/components/nextion/test.esp32-ard.yaml | 6 +- tests/components/nextion/test.esp32-idf.yaml | 6 +- .../components/nextion/test.esp8266-ard.yaml | 5 +- 11 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 tests/components/nextion/common_tft_upload.yaml create mode 100644 tests/components/nextion/common_tft_upload_watchdog.yaml diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 86551cbe23..7705b21b0b 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -27,6 +27,9 @@ CONF_PRECISION = "precision" CONF_SKIP_CONNECTION_HANDSHAKE = "skip_connection_handshake" CONF_START_UP_PAGE = "start_up_page" CONF_STARTUP_OVERRIDE_MS = "startup_override_ms" +CONF_TFT_UPLOAD_HTTP_RETRIES = "tft_upload_http_retries" +CONF_TFT_UPLOAD_HTTP_TIMEOUT = "tft_upload_http_timeout" +CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT = "tft_upload_watchdog_timeout" CONF_TFT_URL = "tft_url" CONF_TOUCH_SLEEP_TIMEOUT = "touch_sleep_timeout" CONF_VARIABLE_NAME = "variable_name" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 3bfcc95995..b8fcd5d8cf 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -33,15 +33,24 @@ from .base_component import ( CONF_SKIP_CONNECTION_HANDSHAKE, CONF_START_UP_PAGE, CONF_STARTUP_OVERRIDE_MS, + CONF_TFT_UPLOAD_HTTP_RETRIES, + CONF_TFT_UPLOAD_HTTP_TIMEOUT, + CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT, CONF_TFT_URL, CONF_TOUCH_SLEEP_TIMEOUT, CONF_WAKE_UP_PAGE, ) CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"] - DEPENDENCIES = ["uart"] -AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"] + + +def AUTO_LOAD() -> list[str]: + base = ["binary_sensor", "switch", "sensor", "text_sensor"] + if CORE.is_esp32: + base.append("watchdog") + return base + NextionSetBrightnessAction = nextion_ns.class_( "NextionSetBrightnessAction", automation.Action @@ -55,7 +64,24 @@ BufferOverflowTrigger = nextion_ns.class_( "BufferOverflowTrigger", automation.Trigger.template() ) -CONFIG_SCHEMA = ( + +def _validate_tft_upload(config): + has_tft_url = CONF_TFT_URL in config + for conf_key in ( + CONF_TFT_UPLOAD_HTTP_TIMEOUT, + CONF_TFT_UPLOAD_HTTP_RETRIES, + CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT, + ): + if conf_key in config and not has_tft_url: + raise cv.Invalid(f"{conf_key} requires {CONF_TFT_URL} to be set") + if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config and not CORE.is_esp32: + raise cv.Invalid( + f"{CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT} is only available on ESP32" + ) + return config + + +CONFIG_SCHEMA = cv.All( display.BASIC_DISPLAY_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(Nextion), @@ -115,6 +141,14 @@ CONFIG_SCHEMA = ( ), ), cv.Optional(CONF_START_UP_PAGE): cv.uint8_t, + cv.Optional(CONF_TFT_UPLOAD_HTTP_RETRIES): cv.int_range(min=1, max=255), + cv.Optional(CONF_TFT_UPLOAD_HTTP_TIMEOUT): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(max=TimePeriod(milliseconds=65535)), + ), + cv.Optional( + CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT + ): cv.positive_time_period_milliseconds, cv.Optional(CONF_TFT_URL): cv.url, cv.Optional(CONF_TOUCH_SLEEP_TIMEOUT): cv.Any( 0, cv.int_range(min=3, max=65535) @@ -123,7 +157,8 @@ CONFIG_SCHEMA = ( } ) .extend(cv.polling_component_schema("5s")) - .extend(uart.UART_DEVICE_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA), + _validate_tft_upload, ) @@ -176,6 +211,29 @@ async def to_code(config): if CONF_TFT_URL in config: cg.add_define("USE_NEXTION_TFT_UPLOAD") cg.add(var.set_tft_url(config[CONF_TFT_URL])) + + # TFT upload HTTP timeout (default: 4.5s) + if CONF_TFT_UPLOAD_HTTP_TIMEOUT in config: + cg.add( + var.set_tft_upload_http_timeout( + config[CONF_TFT_UPLOAD_HTTP_TIMEOUT].total_milliseconds + ) + ) + + # TFT upload HTTP retries (default: 5) + if CONF_TFT_UPLOAD_HTTP_RETRIES in config: + cg.add( + var.set_tft_upload_http_retries(config[CONF_TFT_UPLOAD_HTTP_RETRIES]) + ) + + # TFT upload watchdog timeout (default: 0 = no adjustment) + if CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT in config: + cg.add( + var.set_tft_upload_watchdog_timeout( + config[CONF_TFT_UPLOAD_WATCHDOG_TIMEOUT].total_milliseconds + ) + ) + if CORE.is_esp32: # Re-enable ESP-IDF's HTTP client (excluded by default to save compile time) esp32.include_builtin_idf_component("esp_http_client") diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index c8c1b6fa41..cb20c34005 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -191,6 +191,18 @@ void Nextion::dump_config() { #ifdef USE_NEXTION_MAX_QUEUE_SIZE ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_); #endif +#ifdef USE_NEXTION_TFT_UPLOAD + ESP_LOGCONFIG(TAG, + " TFT URL: %s\n" + " TFT upload HTTP timeout: %" PRIu16 "ms\n" + " TFT upload HTTP retries: %u", + this->tft_url_.c_str(), this->tft_upload_http_timeout_, this->tft_upload_http_retries_); +#ifdef USE_ESP32 + if (this->tft_upload_watchdog_timeout_ > 0) { + ESP_LOGCONFIG(TAG, " TFT upload WDT timeout: %" PRIu32 "ms", this->tft_upload_watchdog_timeout_); + } +#endif // USE_ESP32 +#endif // USE_NEXTION_TFT_UPLOAD } void Nextion::update() { diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index c42ddba9b5..7999e3c4e3 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1071,6 +1071,33 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe bool send_command_printf(const char *format, ...) __attribute__((format(printf, 2, 3))); #ifdef USE_NEXTION_TFT_UPLOAD + /** + * @brief Set the HTTP timeout for TFT upload requests. + * @param timeout_ms Timeout in milliseconds. Defaults to 4500ms (4.5s). + */ + void set_tft_upload_http_timeout(uint16_t timeout_ms) { this->tft_upload_http_timeout_ = timeout_ms; } + +#ifdef USE_ESP32 + /** + * @brief Set the watchdog timeout during TFT upload. + * + * The system watchdog timeout is temporarily adjusted to this value + * during the entire TFT transfer process and restored to the original + * value after the transfer completes (whether successful or not). + * + * A value of 0 means no watchdog adjustment (default). + * + * @param timeout_ms Watchdog timeout in milliseconds. 0 = no adjustment. + */ + void set_tft_upload_watchdog_timeout(uint32_t timeout_ms) { this->tft_upload_watchdog_timeout_ = timeout_ms; } +#endif // USE_ESP32 + + /** + * @brief Set the number of HTTP retries for TFT upload requests. + * @param retries Number of retries. Defaults to 5. Range: 1-255. + */ + void set_tft_upload_http_retries(uint8_t retries) { this->tft_upload_http_retries_ = retries; } + /** * Set the tft file URL. */ @@ -1439,8 +1466,12 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe int tft_size_ = 0; uint32_t original_baud_rate_ = 0; bool upload_first_chunk_sent_ = false; + uint16_t tft_upload_http_timeout_{4500}; ///< HTTP timeout in ms (default: 4.5s) + uint8_t tft_upload_http_retries_{5}; ///< HTTP retry count (default: 5) #ifdef USE_ESP32 + uint32_t tft_upload_watchdog_timeout_{0}; ///< WDT timeout in ms (0 = no adjustment) + /** * will request 4096 bytes chunks from the web server * and send each to Nextion diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index 46a04c1b2e..e03f1f470b 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -166,7 +166,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { // Define the configuration for the HTTP client ESP_LOGV(TAG, "Init HTTP client, heap: %" PRIu32, EspClass::getFreeHeap()); HTTPClient http_client; - http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along + http_client.setTimeout(this->tft_upload_http_timeout_); bool begin_status = false; #ifdef USE_ESP8266 @@ -192,15 +192,15 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { http_client.collectHeaders(header_names, 1); ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str()); http_client.setReuse(true); - // try up to 5 times. DNS sometimes needs a second try or so + int tries = 1; int code = http_client.GET(); delay(100); // NOLINT App.feed_wdt(); - while (code != 200 && code != 206 && tries <= 5) { - ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/5", this->tft_url_.c_str(), - HTTPClient::errorToString(code).c_str(), tries); + while (code != 200 && code != 206 && tries <= this->tft_upload_http_retries_) { + ESP_LOGW(TAG, "HTTP fail: URL: %s; Error: %s, retry %d/%u", this->tft_url_.c_str(), + HTTPClient::errorToString(code).c_str(), tries, this->tft_upload_http_retries_); delay(250); // NOLINT App.feed_wdt(); diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index 43f59a8d4b..1014c728a8 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -7,6 +7,7 @@ #include <esp_http_client.h> #include <cinttypes> #include "esphome/components/network/util.h" +#include "esphome/components/watchdog/watchdog.h" #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" @@ -68,7 +69,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r int partial_read_len = 0; uint8_t retries = 0; // Attempt to read the chunk with retries. - while (retries < 5 && read_len < buffer_size) { + while (retries < this->tft_upload_http_retries_ && read_len < buffer_size) { partial_read_len = esp_http_client_read(http_client, reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len); if (partial_read_len > 0) { @@ -167,6 +168,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { return false; } + // Temporarily adjust watchdog timeout for the duration of the TFT upload + watchdog::WatchdogManager wdm(this->tft_upload_watchdog_timeout_); + this->connection_state_.is_updating_ = true; if (exit_reparse) { @@ -190,7 +194,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { .url = this->tft_url_.c_str(), .cert_pem = nullptr, .method = HTTP_METHOD_HEAD, - .timeout_ms = 15000, + .timeout_ms = static_cast<int>(this->tft_upload_http_timeout_), .disable_auto_redirect = false, .max_redirection_count = 10, }; diff --git a/tests/components/nextion/common_tft_upload.yaml b/tests/components/nextion/common_tft_upload.yaml new file mode 100644 index 0000000000..190abbc7b1 --- /dev/null +++ b/tests/components/nextion/common_tft_upload.yaml @@ -0,0 +1,5 @@ +display: + - id: !extend main_lcd + tft_url: http://esphome.io/default35.tft + tft_upload_http_timeout: 20s + tft_upload_http_retries: 10 diff --git a/tests/components/nextion/common_tft_upload_watchdog.yaml b/tests/components/nextion/common_tft_upload_watchdog.yaml new file mode 100644 index 0000000000..385fee359e --- /dev/null +++ b/tests/components/nextion/common_tft_upload_watchdog.yaml @@ -0,0 +1,3 @@ +display: + - id: !extend main_lcd + tft_upload_watchdog_timeout: 30s diff --git a/tests/components/nextion/test.esp32-ard.yaml b/tests/components/nextion/test.esp32-ard.yaml index 7e94a9b4a5..a4f71628da 100644 --- a/tests/components/nextion/test.esp32-ard.yaml +++ b/tests/components/nextion/test.esp32-ard.yaml @@ -1,7 +1,5 @@ packages: uart: !include ../../test_build_components/common/uart/esp32-ard.yaml base: !include common.yaml - -display: - - id: !extend main_lcd - tft_url: http://esphome.io/default35.tft + tft_upload: !include common_tft_upload.yaml + tft_upload_watchdog: !include common_tft_upload_watchdog.yaml diff --git a/tests/components/nextion/test.esp32-idf.yaml b/tests/components/nextion/test.esp32-idf.yaml index 99820f0f8d..259b71c9d0 100644 --- a/tests/components/nextion/test.esp32-idf.yaml +++ b/tests/components/nextion/test.esp32-idf.yaml @@ -1,7 +1,5 @@ packages: uart: !include ../../test_build_components/common/uart/esp32-idf.yaml base: !include common.yaml - -display: - - id: !extend main_lcd - tft_url: http://esphome.io/default35.tft + tft_upload: !include common_tft_upload.yaml + tft_upload_watchdog: !include common_tft_upload_watchdog.yaml diff --git a/tests/components/nextion/test.esp8266-ard.yaml b/tests/components/nextion/test.esp8266-ard.yaml index 49f79b2f4c..a2b0e727cc 100644 --- a/tests/components/nextion/test.esp8266-ard.yaml +++ b/tests/components/nextion/test.esp8266-ard.yaml @@ -1,7 +1,4 @@ packages: uart: !include ../../test_build_components/common/uart/esp8266-ard.yaml base: !include common.yaml - -display: - - id: !extend main_lcd - tft_url: http://esphome.io/default35.tft + tft_upload: !include common_tft_upload.yaml From 5b9cab02bee18da518c522fbdcf26b0b12fb17f6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 8 Mar 2026 22:37:54 -0400 Subject: [PATCH 1230/2030] [multiple] Add default initializers to uninitialized member variables (#14636) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/duty_time/duty_time_sensor.h | 6 +++--- esphome/components/growatt_solar/growatt_solar.h | 4 ++-- esphome/components/hte501/hte501.h | 4 ++-- esphome/components/select/select_call.h | 2 +- esphome/components/uponor_smatrix/uponor_smatrix.h | 4 ++-- esphome/components/wifi_info/wifi_info_text_sensor.h | 2 +- esphome/components/x9c/x9c.h | 6 +++--- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/esphome/components/duty_time/duty_time_sensor.h b/esphome/components/duty_time/duty_time_sensor.h index d9fb2a6d60..d21802ebb6 100644 --- a/esphome/components/duty_time/duty_time_sensor.h +++ b/esphome/components/duty_time/duty_time_sensor.h @@ -41,9 +41,9 @@ class DutyTimeSensor : public sensor::Sensor, public PollingComponent { sensor::Sensor *last_duty_time_sensor_{nullptr}; ESPPreferenceObject pref_; - uint32_t total_sec_; - uint32_t last_time_; - uint32_t edge_time_; + uint32_t total_sec_{0}; + uint32_t last_time_{0}; + uint32_t edge_time_{0}; bool last_state_{false}; bool restore_; }; diff --git a/esphome/components/growatt_solar/growatt_solar.h b/esphome/components/growatt_solar/growatt_solar.h index b0ddd4b99d..833d6a36dd 100644 --- a/esphome/components/growatt_solar/growatt_solar.h +++ b/esphome/components/growatt_solar/growatt_solar.h @@ -56,8 +56,8 @@ class GrowattSolar : public PollingComponent, public modbus::ModbusDevice { } protected: - bool waiting_to_update_; - uint32_t last_send_; + bool waiting_to_update_{false}; + uint32_t last_send_{0}; struct GrowattPhase { sensor::Sensor *voltage_sensor_{nullptr}; diff --git a/esphome/components/hte501/hte501.h b/esphome/components/hte501/hte501.h index b47daf9157..7f29885f49 100644 --- a/esphome/components/hte501/hte501.h +++ b/esphome/components/hte501/hte501.h @@ -18,8 +18,8 @@ class HTE501Component : public PollingComponent, public i2c::I2CDevice { void update() override; protected: - sensor::Sensor *temperature_sensor_; - sensor::Sensor *humidity_sensor_; + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; enum ErrorCode { NONE = 0, COMMUNICATION_FAILED, CRC_CHECK_FAILED } error_code_{NONE}; }; diff --git a/esphome/components/select/select_call.h b/esphome/components/select/select_call.h index c9abbc69a0..fbe7b82e92 100644 --- a/esphome/components/select/select_call.h +++ b/esphome/components/select/select_call.h @@ -43,7 +43,7 @@ class SelectCall { Select *const parent_; optional<size_t> index_; SelectOperation operation_{SELECT_OP_NONE}; - bool cycle_; + bool cycle_{false}; }; } // namespace esphome::select diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.h b/esphome/components/uponor_smatrix/uponor_smatrix.h index bd760f0d77..bd20e9b6a0 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.h +++ b/esphome/components/uponor_smatrix/uponor_smatrix.h @@ -89,8 +89,8 @@ class UponorSmatrixComponent : public uart::UARTDevice, public Component { std::vector<uint8_t> rx_buffer_; std::queue<std::vector<uint8_t>> tx_queue_; - uint32_t last_rx_; - uint32_t last_tx_; + uint32_t last_rx_{0}; + uint32_t last_tx_{0}; #ifdef USE_TIME time::RealTimeClock *time_id_{nullptr}; diff --git a/esphome/components/wifi_info/wifi_info_text_sensor.h b/esphome/components/wifi_info/wifi_info_text_sensor.h index 8ef35a5f5d..7ade170c02 100644 --- a/esphome/components/wifi_info/wifi_info_text_sensor.h +++ b/esphome/components/wifi_info/wifi_info_text_sensor.h @@ -23,7 +23,7 @@ class IPAddressWiFiInfo final : public Component, public text_sensor::TextSensor const network::IPAddress &dns2) override; protected: - std::array<text_sensor::TextSensor *, 5> ip_sensors_; + std::array<text_sensor::TextSensor *, 5> ip_sensors_{}; }; class DNSAddressWifiInfo final : public Component, public text_sensor::TextSensor, public wifi::WiFiIPStateListener { diff --git a/esphome/components/x9c/x9c.h b/esphome/components/x9c/x9c.h index 66c3df14e1..7dcd79bb7c 100644 --- a/esphome/components/x9c/x9c.h +++ b/esphome/components/x9c/x9c.h @@ -25,9 +25,9 @@ class X9cOutput : public output::FloatOutput, public Component { InternalGPIOPin *cs_pin_; InternalGPIOPin *inc_pin_; InternalGPIOPin *ud_pin_; - float initial_value_; - float pot_value_; - int step_delay_; + float initial_value_{0.0f}; + float pot_value_{0.0f}; + int step_delay_{0}; }; } // namespace x9c From 5d3893368d003a0904554e9170a1645f5c687efe Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 8 Mar 2026 23:16:32 -0400 Subject: [PATCH 1231/2030] [multiple] Add array bounds checks (#14635) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../addressable_light/addressable_light_display.cpp | 5 ++++- esphome/components/bme680_bsec/bme680_bsec.cpp | 2 +- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp | 1 + esphome/components/dac7678/dac7678_output.cpp | 2 ++ esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp | 5 +++-- esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp | 6 ++++++ 6 files changed, 17 insertions(+), 4 deletions(-) diff --git a/esphome/components/addressable_light/addressable_light_display.cpp b/esphome/components/addressable_light/addressable_light_display.cpp index 16fab15b17..329620bcf0 100644 --- a/esphome/components/addressable_light/addressable_light_display.cpp +++ b/esphome/components/addressable_light/addressable_light_display.cpp @@ -58,7 +58,10 @@ void HOT AddressableLightDisplay::draw_absolute_pixel_internal(int x, int y, Col if (this->pixel_mapper_f_.has_value()) { // Params are passed by reference, so they may be modified in call. - this->addressable_light_buffer_[(*this->pixel_mapper_f_)(x, y)] = color; + int index = (*this->pixel_mapper_f_)(x, y); + if (index < 0 || static_cast<size_t>(index) >= this->addressable_light_buffer_.size()) + return; + this->addressable_light_buffer_[index] = color; } else { this->addressable_light_buffer_[y * this->get_width_internal() + x] = color; } diff --git a/esphome/components/bme680_bsec/bme680_bsec.cpp b/esphome/components/bme680_bsec/bme680_bsec.cpp index 392d071b31..454be0c0fe 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.cpp +++ b/esphome/components/bme680_bsec/bme680_bsec.cpp @@ -383,7 +383,7 @@ void BME680BSECComponent::publish_(const bsec_output_t *outputs, uint8_t num_out switch (outputs[i].sensor_id) { case BSEC_OUTPUT_IAQ: case BSEC_OUTPUT_STATIC_IAQ: { - uint8_t accuracy = outputs[i].accuracy; + uint8_t accuracy = std::min<uint8_t>(outputs[i].accuracy, std::size(IAQ_ACCURACY_STATES) - 1); this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); }); this->queue_push_([this, accuracy]() { this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[accuracy]); diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index 1a42c9d54b..0210d1e67d 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -438,6 +438,7 @@ void BME68xBSEC2Component::publish_(const bsec_output_t *outputs, uint8_t num_ou } } if (update_accuracy) { + max_accuracy = std::min<uint8_t>(max_accuracy, std::size(IAQ_ACCURACY_STATES) - 1); #ifdef USE_SENSOR this->queue_push_( [this, max_accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, max_accuracy, true); }); diff --git a/esphome/components/dac7678/dac7678_output.cpp b/esphome/components/dac7678/dac7678_output.cpp index 83f8722e7f..27ab54f0be 100644 --- a/esphome/components/dac7678/dac7678_output.cpp +++ b/esphome/components/dac7678/dac7678_output.cpp @@ -62,6 +62,8 @@ void DAC7678Output::register_channel(DAC7678Channel *channel) { } void DAC7678Output::set_channel_value_(uint8_t channel, uint16_t value) { + if (channel >= std::size(this->dac_input_reg_)) + return; if (this->dac_input_reg_[channel] != value) { ESP_LOGV(TAG, "Channel %01u: input_reg=%04u ", channel, value); diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 99d519b434..263603704a 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -452,7 +452,8 @@ void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *da } break; case 0x83: - if (this->custom_presence_of_detection_sensor_ != nullptr) { + if (this->custom_presence_of_detection_sensor_ != nullptr && + data[FRAME_DATA_INDEX] < std::size(S_PRESENCE_OF_DETECTION_RANGE_STR)) { this->custom_presence_of_detection_sensor_->publish_state( S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]); } @@ -646,7 +647,7 @@ void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) { #ifdef USE_BINARY_SENSOR case 0x01: case 0x81: - if (this->has_target_binary_sensor_ != nullptr) { + if (this->has_target_binary_sensor_ != nullptr && data[FRAME_DATA_INDEX] < std::size(S_SOMEONE_EXISTS_STR)) { this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]); } break; diff --git a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp index c6527a948e..e24e9b338e 100644 --- a/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp +++ b/esphome/components/seeed_mr60fda2/seeed_mr60fda2.cpp @@ -334,6 +334,8 @@ void MR60FDA2Component::process_frame_() { // Send Heartbeat Packet Command void MR60FDA2Component::set_install_height(uint8_t index) { + if (index >= std::size(INSTALL_HEIGHT)) + return; uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x04, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00}; float_to_bytes(INSTALL_HEIGHT[index], &send_data[8]); send_data[12] = calculate_checksum(send_data + 8, 4); @@ -345,6 +347,8 @@ void MR60FDA2Component::set_install_height(uint8_t index) { } void MR60FDA2Component::set_height_threshold(uint8_t index) { + if (index >= std::size(HEIGHT_THRESHOLD)) + return; uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x08, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00}; float_to_bytes(HEIGHT_THRESHOLD[index], &send_data[8]); send_data[12] = calculate_checksum(send_data + 8, 4); @@ -356,6 +360,8 @@ void MR60FDA2Component::set_height_threshold(uint8_t index) { } void MR60FDA2Component::set_sensitivity(uint8_t index) { + if (index >= std::size(SENSITIVITY)) + return; uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x0A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00}; int_to_bytes(SENSITIVITY[index], &send_data[8]); From 088a8a4338940c061fa181b55845a5d25c6268ce Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 8 Mar 2026 17:23:58 -1000 Subject: [PATCH 1232/2030] [ci] Match symbols with changed signatures in memory impact analysis (#14600) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- script/ci_memory_impact_comment.py | 75 ++++++++++++++ tests/unit_tests/analyze_memory/__init__.py | 0 .../test_ci_memory_impact_comment.py | 99 +++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 tests/unit_tests/analyze_memory/__init__.py create mode 100644 tests/unit_tests/analyze_memory/test_ci_memory_impact_comment.py diff --git a/script/ci_memory_impact_comment.py b/script/ci_memory_impact_comment.py index a296130645..01316da27f 100755 --- a/script/ci_memory_impact_comment.py +++ b/script/ci_memory_impact_comment.py @@ -160,6 +160,76 @@ def format_change(before: int, after: int, threshold: float | None = None) -> st return f"{emoji} {delta_str} ({pct_str})" +def _sig_base(sym: str) -> str: + """Strip argument types from a symbol name for fuzzy matching. + + Removes the entire outermost parenthesized argument list (including + the parentheses) from the symbol string. + + This makes, for example, "foo(int)::nested" and "foo(float)::nested" + share the same key "foo::nested", while "foo(int)" maps to "foo" and + therefore does NOT collide with "foo(int)::nested". + """ + start = sym.find("(") + if start == -1: + return sym + end = sym.rfind(")") + if end == -1: + return sym + return sym[:start] + sym[end + 1 :] + + +_AMBIGUOUS = object() + + +def _match_signature_changes( + changed_symbols: list[tuple[str, int, int, int]], + new_symbols: list[tuple[str, int]], + removed_symbols: list[tuple[str, int]], +) -> tuple[ + list[tuple[str, int, int, int]], + list[tuple[str, int]], + list[tuple[str, int]], +]: + """Match new/removed symbol pairs that only differ in argument types. + + When a function's argument types change (e.g. foo(vector<>&) -> foo(Buffer&)), + it appears as a new + removed symbol. This matches them by base name and moves + them to changed_symbols. Only matches unambiguous 1:1 pairs. + """ + if not new_symbols or not removed_symbols: + return changed_symbols, new_symbols, removed_symbols + + # Build base -> entry maps; mark ambiguous bases with sentinel + new_by_base: dict[str, tuple[str, int] | object] = {} + for entry in new_symbols: + base = _sig_base(entry[0]) + new_by_base[base] = _AMBIGUOUS if base in new_by_base else entry + removed_by_base: dict[str, tuple[str, int] | object] = {} + for entry in removed_symbols: + base = _sig_base(entry[0]) + removed_by_base[base] = _AMBIGUOUS if base in removed_by_base else entry + + matched: set[str] = set() # matched base keys + for base, new_entry in new_by_base.items(): + if new_entry is _AMBIGUOUS: + continue + rem_entry = removed_by_base.get(base) + if rem_entry is None or rem_entry is _AMBIGUOUS: + continue + pr_sym, pr_size = new_entry + _rm_sym, target_size = rem_entry + delta = pr_size - target_size + if delta != 0: + changed_symbols.append((pr_sym, target_size, pr_size, delta)) + matched.add(base) + + if matched: + new_symbols = [e for e in new_symbols if _sig_base(e[0]) not in matched] + removed_symbols = [e for e in removed_symbols if _sig_base(e[0]) not in matched] + return changed_symbols, new_symbols, removed_symbols + + def prepare_symbol_changes_data( target_symbols: dict | None, pr_symbols: dict | None ) -> dict | None: @@ -200,6 +270,11 @@ def prepare_symbol_changes_data( delta = pr_size - target_size changed_symbols.append((symbol, target_size, pr_size, delta)) + # Match new/removed symbols that only differ in argument types + changed_symbols, new_symbols, removed_symbols = _match_signature_changes( + changed_symbols, new_symbols, removed_symbols + ) + if not changed_symbols and not new_symbols and not removed_symbols: return None diff --git a/tests/unit_tests/analyze_memory/__init__.py b/tests/unit_tests/analyze_memory/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/unit_tests/analyze_memory/test_ci_memory_impact_comment.py b/tests/unit_tests/analyze_memory/test_ci_memory_impact_comment.py new file mode 100644 index 0000000000..8399ac0303 --- /dev/null +++ b/tests/unit_tests/analyze_memory/test_ci_memory_impact_comment.py @@ -0,0 +1,99 @@ +"""Tests for script/ci_memory_impact_comment.py symbol matching.""" + +from pathlib import Path +import sys + +# Add script directory to path so we can import the module +sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "script")) + +from ci_memory_impact_comment import prepare_symbol_changes_data # noqa: E402 + + +def test_prepare_symbol_changes_signature_match() -> None: + """Symbols with same base name but different args are matched as changed.""" + target = { + "Foo::bar(std::vector<unsigned char>&, int)": 300, + "unchanged()": 50, + } + pr = { + "Foo::bar(ProtoByteBuffer&, int)": 320, + "unchanged()": 50, + } + result = prepare_symbol_changes_data(target, pr) + assert result is not None + assert len(result["changed_symbols"]) == 1 + assert len(result["new_symbols"]) == 0 + assert len(result["removed_symbols"]) == 0 + sym, t_size, p_size, delta = result["changed_symbols"][0] + assert sym == "Foo::bar(ProtoByteBuffer&, int)" + assert t_size == 300 + assert p_size == 320 + assert delta == 20 + + +def test_prepare_symbol_changes_ambiguous_overloads_not_matched() -> None: + """Multiple overloads with same base name stay as new/removed.""" + target = { + "Foo::bar(int)": 100, + "Foo::bar(float)": 200, + } + pr = { + "Foo::bar(double)": 150, + "Foo::bar(long)": 250, + } + result = prepare_symbol_changes_data(target, pr) + assert result is not None + assert len(result["changed_symbols"]) == 0 + assert len(result["new_symbols"]) == 2 + assert len(result["removed_symbols"]) == 2 + + +def test_prepare_symbol_changes_no_parens_not_matched() -> None: + """Symbols without parens (variables) are not fuzzy-matched.""" + target = {"my_global_var": 100} + pr = {"my_global_var_v2": 120} + result = prepare_symbol_changes_data(target, pr) + assert result is not None + assert len(result["changed_symbols"]) == 0 + assert len(result["new_symbols"]) == 1 + assert len(result["removed_symbols"]) == 1 + + +def test_prepare_symbol_changes_nested_symbols_matched_separately() -> None: + """Nested symbols like ::__pstr__ don't collide with parent function.""" + target = { + "Foo::bar(std::vector<unsigned char>&, int)": 300, + "Foo::bar(std::vector<unsigned char>&, int)::__pstr__": 19, + } + pr = { + "Foo::bar(ProtoByteBuffer&, int)": 320, + "Foo::bar(ProtoByteBuffer&, int)::__pstr__": 19, + } + result = prepare_symbol_changes_data(target, pr) + assert result is not None + # Both the function and its nested __pstr__ should be matched (not new/removed) + assert len(result["new_symbols"]) == 0 + assert len(result["removed_symbols"]) == 0 + # __pstr__ has delta=0 so it's silently dropped, only the function shows + assert len(result["changed_symbols"]) == 1 + sym, t_size, p_size, delta = result["changed_symbols"][0] + assert sym == "Foo::bar(ProtoByteBuffer&, int)" + assert delta == 20 + + +def test_prepare_symbol_changes_exact_match_preferred() -> None: + """Exact name matches are found before fuzzy matching runs.""" + target = { + "Foo::bar(int)": 100, + } + pr = { + "Foo::bar(int)": 120, + } + result = prepare_symbol_changes_data(target, pr) + assert result is not None + assert len(result["changed_symbols"]) == 1 + assert len(result["new_symbols"]) == 0 + assert len(result["removed_symbols"]) == 0 + sym, t_size, p_size, delta = result["changed_symbols"][0] + assert sym == "Foo::bar(int)" + assert delta == 20 From f3ca86b67017991a13a1cb27b242b373e64ed29e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 9 Mar 2026 14:48:03 +1100 Subject: [PATCH 1233/2030] [ci-custom] Directions on constant hoisting (#14637) --- script/ci-custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/ci-custom.py b/script/ci-custom.py index 8e1652b505..06fcdadb8c 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -519,7 +519,7 @@ def lint_constants_usage(): continue errs.append( f"Constant {highlight(constant)} is defined in {len(uses)} files. Please move all definitions of the " - f"constant to const.py (Uses: {', '.join(str(u) for u in uses)}) in a separate PR. " + f"constant to esphome/components/const/__init__.py (Uses: {', '.join(str(u) for u in uses)}) in a separate PR. " "See https://developers.esphome.io/contributing/code/#python" ) return errs From 0db9137d9101a04c4b2a8836e13308de60280c35 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 00:10:48 -0400 Subject: [PATCH 1234/2030] [multiple] Add division by zero guards (#14634) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/bl0942/bl0942.cpp | 2 +- esphome/components/combination/combination.cpp | 11 ++++++++++- esphome/components/graph/graph.cpp | 2 +- esphome/components/mics_4514/mics_4514.cpp | 6 ++++++ esphome/components/tsl2561/tsl2561.cpp | 4 ++++ esphome/components/ufire_ec/ufire_ec.cpp | 14 +++++++++++--- esphome/components/ufire_ec/ufire_ec.h | 2 +- esphome/components/xxtea/xxtea.cpp | 4 ++++ 8 files changed, 38 insertions(+), 7 deletions(-) diff --git a/esphome/components/bl0942/bl0942.cpp b/esphome/components/bl0942/bl0942.cpp index 16ad33141d..7d38597423 100644 --- a/esphome/components/bl0942/bl0942.cpp +++ b/esphome/components/bl0942/bl0942.cpp @@ -173,7 +173,7 @@ void BL0942::received_package_(DataPacket *data) { float i_rms = (uint24_t) data->i_rms / current_reference_; float watt = (int24_t) data->watt / power_reference_; float total_energy_consumption = cf_cnt / energy_reference_; - float frequency = 1000000.0f / data->frequency; + float frequency = data->frequency != 0 ? 1000000.0f / data->frequency : NAN; if (voltage_sensor_ != nullptr) { voltage_sensor_->publish_state(v_rms); diff --git a/esphome/components/combination/combination.cpp b/esphome/components/combination/combination.cpp index ece7cca482..2f0bd26a02 100644 --- a/esphome/components/combination/combination.cpp +++ b/esphome/components/combination/combination.cpp @@ -163,7 +163,7 @@ void MeanCombinationComponent::handle_new_value(float value) { return; float sum = 0.0; - size_t count = 0.0; + size_t count = 0; for (const auto &sensor : this->sensors_) { if (std::isfinite(sensor->state)) { @@ -172,6 +172,10 @@ void MeanCombinationComponent::handle_new_value(float value) { } } + if (count == 0) { + this->publish_state(NAN); + return; + } float mean = sum / count; this->publish_state(mean); @@ -238,6 +242,11 @@ void RangeCombinationComponent::handle_new_value(float value) { } } + if (sensor_states.empty()) { + this->publish_state(NAN); + return; + } + sort(sensor_states.begin(), sensor_states.end()); float range = sensor_states.back() - sensor_states.front(); diff --git a/esphome/components/graph/graph.cpp b/esphome/components/graph/graph.cpp index c43cd07fe0..801c97e3f5 100644 --- a/esphome/components/graph/graph.cpp +++ b/esphome/components/graph/graph.cpp @@ -171,7 +171,7 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo bool prev_b = false; int16_t prev_y = 0; for (uint32_t i = 0; i < this->width_; i++) { - float v = (trace->get_tracedata()->get_value(i) - ymin) / yrange; + float v = yrange != 0 ? (trace->get_tracedata()->get_value(i) - ymin) / yrange : NAN; if (!std::isnan(v) && (thick > 0)) { int16_t x = this->width_ - 1 - i + x_offset; uint8_t bit = 1 << ((i % (thick * LineType::PATTERN_LENGTH)) / thick); diff --git a/esphome/components/mics_4514/mics_4514.cpp b/esphome/components/mics_4514/mics_4514.cpp index 60413b32d7..ce63a7d062 100644 --- a/esphome/components/mics_4514/mics_4514.cpp +++ b/esphome/components/mics_4514/mics_4514.cpp @@ -59,6 +59,12 @@ void MICS4514Component::update() { return; } + if (this->red_calibration_ == 0 || this->ox_calibration_ == 0) { + ESP_LOGW(TAG, "Calibration values are zero, retrying"); + this->status_set_warning(); + this->initial_ = true; + return; + } float red_f = (float) (power - red) / this->red_calibration_; float ox_f = (float) (power - ox) / this->ox_calibration_; diff --git a/esphome/components/tsl2561/tsl2561.cpp b/esphome/components/tsl2561/tsl2561.cpp index cb4c38a83c..bccff1fb26 100644 --- a/esphome/components/tsl2561/tsl2561.cpp +++ b/esphome/components/tsl2561/tsl2561.cpp @@ -70,6 +70,10 @@ float TSL2561Sensor::calculate_lx_(uint16_t ch0, uint16_t ch1) { return NAN; } + if (ch0 == 0) { + ESP_LOGVV(TAG, "No light detected"); + return 0.0f; + } float d0 = ch0, d1 = ch1; float ratio = d1 / d0; diff --git a/esphome/components/ufire_ec/ufire_ec.cpp b/esphome/components/ufire_ec/ufire_ec.cpp index a1c3568a1a..40e3be2757 100644 --- a/esphome/components/ufire_ec/ufire_ec.cpp +++ b/esphome/components/ufire_ec/ufire_ec.cpp @@ -1,5 +1,6 @@ #include "esphome/core/log.h" #include "ufire_ec.h" +#include <cmath> namespace esphome { namespace ufire_ec { @@ -60,9 +61,15 @@ float UFireECComponent::measure_temperature_() { return this->read_data_(REGISTE float UFireECComponent::measure_ms_() { return this->read_data_(REGISTER_MS); } -void UFireECComponent::set_solution_(float solution, float temperature) { - solution /= (1 - (this->temperature_coefficient_ * (temperature - 25))); +bool UFireECComponent::set_solution_(float solution, float temperature) { + float denom = 1 - (this->temperature_coefficient_ * (temperature - 25)); + if (std::abs(denom) < 1e-6f) { + ESP_LOGE(TAG, "Temperature compensation denominator is zero"); + return false; + } + solution /= denom; this->write_data_(REGISTER_SOLUTION, solution); + return true; } void UFireECComponent::set_compensation_(float temperature) { this->write_data_(REGISTER_COMPENSATION, temperature); } @@ -72,7 +79,8 @@ void UFireECComponent::set_coefficient_(float coefficient) { this->write_data_(R void UFireECComponent::set_temperature_(float temperature) { this->write_data_(REGISTER_TEMP, temperature); } void UFireECComponent::calibrate_probe(float solution, float temperature) { - this->set_solution_(solution, temperature); + if (!this->set_solution_(solution, temperature)) + return; this->write_byte(REGISTER_TASK, COMMAND_CALIBRATE_PROBE); } diff --git a/esphome/components/ufire_ec/ufire_ec.h b/esphome/components/ufire_ec/ufire_ec.h index bfbed1b43e..8a648b5038 100644 --- a/esphome/components/ufire_ec/ufire_ec.h +++ b/esphome/components/ufire_ec/ufire_ec.h @@ -44,7 +44,7 @@ class UFireECComponent : public PollingComponent, public i2c::I2CDevice { protected: float measure_temperature_(); float measure_ms_(); - void set_solution_(float solution, float temperature); + bool set_solution_(float solution, float temperature); void set_compensation_(float temperature); void set_coefficient_(float coefficient); void set_temperature_(float temperature); diff --git a/esphome/components/xxtea/xxtea.cpp b/esphome/components/xxtea/xxtea.cpp index aae663ee01..ba17530b24 100644 --- a/esphome/components/xxtea/xxtea.cpp +++ b/esphome/components/xxtea/xxtea.cpp @@ -7,6 +7,8 @@ static const uint32_t DELTA = 0x9e3779b9; #define MX ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p ^ e) & 7] ^ z))) void encrypt(uint32_t *v, size_t n, const uint32_t *k) { + if (n == 0) + return; uint32_t z, y, sum, e; size_t p; size_t q = 6 + 52 / n; @@ -25,6 +27,8 @@ void encrypt(uint32_t *v, size_t n, const uint32_t *k) { } void decrypt(uint32_t *v, size_t n, const uint32_t *k) { + if (n == 0) + return; uint32_t z, y, sum, e; size_t p; size_t q = 6 + 52 / n; From 31f4b4d00d5242979ca83a98acc3b60b0bf0c84b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 07:33:08 -0400 Subject: [PATCH 1235/2030] [multiple] Fix undefined behavior across components (#14639) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/e131/e131_packet.cpp | 3 ++- .../components/globals/globals_component.h | 2 +- .../grove_tb6612fng/grove_tb6612fng.cpp | 3 ++- esphome/components/midea/appliance_base.h | 6 +++-- esphome/components/nextion/nextion.cpp | 12 +++------ esphome/components/ruuvi_ble/ruuvi_ble.cpp | 26 +++++++++---------- .../components/tormatic/tormatic_protocol.h | 2 +- 7 files changed, 26 insertions(+), 28 deletions(-) diff --git a/esphome/components/e131/e131_packet.cpp b/esphome/components/e131/e131_packet.cpp index b90e6d5c91..600793f5d3 100644 --- a/esphome/components/e131/e131_packet.cpp +++ b/esphome/components/e131/e131_packet.cpp @@ -1,3 +1,4 @@ +#include <cstddef> #include <cstring> #include "e131.h" #ifdef USE_NETWORK @@ -57,7 +58,7 @@ union E131RawPacket { // We need to have at least one `1` value // Get the offset of `property_values[1]` -const size_t E131_MIN_PACKET_SIZE = reinterpret_cast<size_t>(&((E131RawPacket *) nullptr)->property_values[1]); +const size_t E131_MIN_PACKET_SIZE = offsetof(E131RawPacket, property_values) + sizeof(uint8_t); bool E131Component::join_igmp_groups_() { if (this->listen_method_ != E131_MULTICAST) diff --git a/esphome/components/globals/globals_component.h b/esphome/components/globals/globals_component.h index 3db29bea35..520c068e6f 100644 --- a/esphome/components/globals/globals_component.h +++ b/esphome/components/globals/globals_component.h @@ -84,7 +84,7 @@ template<typename T, uint8_t SZ> class RestoringGlobalStringComponent : public P this->rtc_ = global_preferences->make_preference<uint8_t[SZ]>(1944399030U ^ this->name_hash_); bool hasdata = this->rtc_.load(&temp); if (hasdata) { - this->value_.assign(temp + 1, temp[0]); + this->value_.assign(temp + 1, static_cast<uint8_t>(temp[0])); } this->last_checked_value_.assign(this->value_); } diff --git a/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp b/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp index 428c8ec4a8..c10fa4cf25 100644 --- a/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp +++ b/esphome/components/grove_tb6612fng/grove_tb6612fng.cpp @@ -139,7 +139,8 @@ void GroveMotorDriveTB6612FNG::stepper_run(StepperModeTypeT mode, int16_t steps, } void GroveMotorDriveTB6612FNG::stepper_stop() { - if (this->write_register(GROVE_MOTOR_DRIVER_I2C_CMD_STEPPER_STOP, nullptr, 1) != i2c::ERROR_OK) { + uint8_t status = 0; + if (this->write_register(GROVE_MOTOR_DRIVER_I2C_CMD_STEPPER_STOP, &status, 1) != i2c::ERROR_OK) { ESP_LOGW(TAG, "Send stop stepper failed!"); this->status_set_warning(); return; diff --git a/esphome/components/midea/appliance_base.h b/esphome/components/midea/appliance_base.h index 060cbd996b..660d185b49 100644 --- a/esphome/components/midea/appliance_base.h +++ b/esphome/components/midea/appliance_base.h @@ -28,12 +28,14 @@ class UARTStream : public Stream { int available() override { return this->uart_->available(); } int read() override { uint8_t data; - this->uart_->read_byte(&data); + if (!this->uart_->read_byte(&data)) + return -1; return data; } int peek() override { uint8_t data; - this->uart_->peek_byte(&data); + if (!this->uart_->peek_byte(&data)) + return -1; return data; } size_t write(uint8_t data) override { diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index cb20c34005..7ae4d50fc8 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -651,11 +651,7 @@ void Nextion::process_nextion_commands_() { break; } - int value = 0; - - for (int i = 0; i < 4; ++i) { - value += to_process[i] << (8 * i); - } + int value = static_cast<int>(encode_uint32(to_process[3], to_process[2], to_process[1], to_process[0])); NextionQueue *nb = this->nextion_queue_.front(); if (!nb || !nb->component) { @@ -751,10 +747,8 @@ void Nextion::process_nextion_commands_() { index = to_process.find('\0'); variable_name = to_process.substr(0, index); // // Get variable name - int value = 0; - for (int i = 0; i < 4; ++i) { - value += to_process[i + index + 1] << (8 * i); - } + int value = static_cast<int>( + encode_uint32(to_process[index + 4], to_process[index + 3], to_process[index + 2], to_process[index + 1])); ESP_LOGN(TAG, "Sensor: %s=%d", variable_name.c_str(), value); diff --git a/esphome/components/ruuvi_ble/ruuvi_ble.cpp b/esphome/components/ruuvi_ble/ruuvi_ble.cpp index bf088873ce..07f870b60c 100644 --- a/esphome/components/ruuvi_ble/ruuvi_ble.cpp +++ b/esphome/components/ruuvi_ble/ruuvi_ble.cpp @@ -21,11 +21,11 @@ bool parse_ruuvi_data_byte(const esp32_ble_tracker::adv_data_t &adv_data, RuuviP const float temperature = temp_sign == 0 ? temp_val : -1 * temp_val; const float humidity = data[0] * 0.5f; - const float pressure = (uint16_t(data[3] << 8) + uint16_t(data[4]) + 50000.0f) / 100.0f; - const float acceleration_x = (int16_t(data[5] << 8) + int16_t(data[6])) / 1000.0f; - const float acceleration_y = (int16_t(data[7] << 8) + int16_t(data[8])) / 1000.0f; - const float acceleration_z = (int16_t(data[9] << 8) + int16_t(data[10])) / 1000.0f; - const float battery_voltage = (uint16_t(data[11] << 8) + uint16_t(data[12])) / 1000.0f; + const float pressure = (encode_uint16(data[3], data[4]) + 50000.0f) / 100.0f; + const float acceleration_x = static_cast<int16_t>(encode_uint16(data[5], data[6])) / 1000.0f; + const float acceleration_y = static_cast<int16_t>(encode_uint16(data[7], data[8])) / 1000.0f; + const float acceleration_z = static_cast<int16_t>(encode_uint16(data[9], data[10])) / 1000.0f; + const float battery_voltage = encode_uint16(data[11], data[12]) / 1000.0f; result.humidity = humidity; result.temperature = temperature; @@ -43,19 +43,19 @@ bool parse_ruuvi_data_byte(const esp32_ble_tracker::adv_data_t &adv_data, RuuviP if (adv_data.size() != 24) return false; - const float temperature = (int16_t(data[0] << 8) + int16_t(data[1])) * 0.005f; - const float humidity = (uint16_t(data[2] << 8) | uint16_t(data[3])) / 400.0f; - const float pressure = ((uint16_t(data[4] << 8) | uint16_t(data[5])) + 50000.0f) / 100.0f; - const float acceleration_x = (int16_t(data[6] << 8) + int16_t(data[7])) / 1000.0f; - const float acceleration_y = (int16_t(data[8] << 8) + int16_t(data[9])) / 1000.0f; - const float acceleration_z = (int16_t(data[10] << 8) + int16_t(data[11])) / 1000.0f; + const float temperature = static_cast<int16_t>(encode_uint16(data[0], data[1])) * 0.005f; + const float humidity = encode_uint16(data[2], data[3]) / 400.0f; + const float pressure = (encode_uint16(data[4], data[5]) + 50000.0f) / 100.0f; + const float acceleration_x = static_cast<int16_t>(encode_uint16(data[6], data[7])) / 1000.0f; + const float acceleration_y = static_cast<int16_t>(encode_uint16(data[8], data[9])) / 1000.0f; + const float acceleration_z = static_cast<int16_t>(encode_uint16(data[10], data[11])) / 1000.0f; - const uint16_t power_info = (uint16_t(data[12] << 8) | data[13]); + const uint16_t power_info = encode_uint16(data[12], data[13]); const float battery_voltage = ((power_info >> 5) + 1600.0f) / 1000.0f; const float tx_power = ((power_info & 0x1F) * 2.0f) - 40.0f; const float movement_counter = float(data[14]); - const float measurement_sequence_number = float(uint16_t(data[15] << 8) | uint16_t(data[16])); + const float measurement_sequence_number = float(encode_uint16(data[15], data[16])); result.temperature = data[0] == 0x7F && data[1] == 0xFF ? NAN : temperature; result.humidity = data[2] == 0xFF && data[3] == 0xFF ? NAN : humidity; diff --git a/esphome/components/tormatic/tormatic_protocol.h b/esphome/components/tormatic/tormatic_protocol.h index 057713b884..26a634b630 100644 --- a/esphome/components/tormatic/tormatic_protocol.h +++ b/esphome/components/tormatic/tormatic_protocol.h @@ -99,7 +99,7 @@ struct MessageHeader { // payload_size returns the amount of payload bytes to be read from the uart // buffer after reading the header. - uint32_t payload_size() { return this->len - sizeof(this->type); } + uint32_t payload_size() { return this->len > sizeof(this->type) ? this->len - sizeof(this->type) : 0; } } __attribute__((packed)); // StatusType denotes which 'page' of information needs to be retrieved. From 019db745828289f5d105475a816f6dc1cabd814d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:44:27 +0000 Subject: [PATCH 1236/2030] Bump setuptools from 82.0.0 to 82.0.1 (#14665) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c6a2c22a5d..2e3a247768 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools==82.0.0", "wheel>=0.43,<0.47"] +requires = ["setuptools==82.0.1", "wheel>=0.43,<0.47"] build-backend = "setuptools.build_meta" [project] From a379e5a6357340a696d9cbc67a8ad48a0bad0924 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:16:29 -0400 Subject: [PATCH 1237/2030] [runtime_image][st7701s] Fix BMP decoder and LCD init bugs (#14663) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/runtime_image/bmp_decoder.cpp | 18 +++++++++++++++--- esphome/components/st7701s/st7701s.cpp | 6 ++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/esphome/components/runtime_image/bmp_decoder.cpp b/esphome/components/runtime_image/bmp_decoder.cpp index 1a56484c60..7003f4da2f 100644 --- a/esphome/components/runtime_image/bmp_decoder.cpp +++ b/esphome/components/runtime_image/bmp_decoder.cpp @@ -63,7 +63,8 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { switch (this->bits_per_pixel_) { case 1: - this->width_bytes_ = (this->width_ % 8 == 0) ? (this->width_ / 8) : (this->width_ / 8 + 1); + this->width_bytes_ = (this->width_ + 7) / 8; + this->padding_bytes_ = (4 - (this->width_bytes_ % 4)) % 4; break; case 24: this->width_bytes_ = this->width_ * 3; @@ -92,15 +93,26 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { case 1: { while (index < size) { uint8_t current_byte = buffer[index]; + bool end_of_row = false; for (uint8_t i = 0; i < 8; i++) { - size_t x = (this->paint_index_ % static_cast<size_t>(this->width_)) + i; + size_t x = this->paint_index_ % static_cast<size_t>(this->width_); size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_)); Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF; this->draw(x, y, 1, 1, c); + this->paint_index_++; + // End of pixel row: skip remaining bits in this byte + if (x + 1 >= static_cast<size_t>(this->width_)) { + end_of_row = true; + break; + } } - this->paint_index_ += 8; this->current_index_++; index++; + // End of pixel row: skip row padding bytes (4-byte alignment) + if (end_of_row && this->padding_bytes_ > 0) { + index += this->padding_bytes_; + this->current_index_ += this->padding_bytes_; + } } break; } diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index 221fe39b9d..ecce4eb4b2 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -36,11 +36,13 @@ void ST7701S::setup() { config.de_gpio_num = this->de_pin_->get_pin(); config.pclk_gpio_num = this->pclk_pin_->get_pin(); esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_); - ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_)); if (err != ESP_OK) { esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err)); + this->mark_failed(); + return; } + ESP_ERROR_CHECK(esp_lcd_panel_reset(this->handle_)); + ESP_ERROR_CHECK(esp_lcd_panel_init(this->handle_)); } void ST7701S::loop() { From 75f55adbfa0cd1a75c9e33a16cc6a95d7195c50c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:17:31 -0400 Subject: [PATCH 1238/2030] [api][at581x][vl53l0x] Fix bounds check issues in 3 components (#14660) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/api_frame_helper_noise.cpp | 2 ++ esphome/components/at581x/at581x.cpp | 5 +++++ esphome/components/vl53l0x/vl53l0x_sensor.cpp | 4 ++-- esphome/components/vl53l0x/vl53l0x_sensor.h | 3 +-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 62523fb835..256357ce6a 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -375,6 +375,7 @@ void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reaso #ifdef USE_STORE_LOG_STR_IN_FLASH // On ESP8266 with flash strings, we need to use PROGMEM-aware functions size_t reason_len = strlen_P(reinterpret_cast<PGM_P>(reason)); + reason_len = std::min(reason_len, sizeof(data) - 1); if (reason_len > 0) { memcpy_P(data + 1, reinterpret_cast<PGM_P>(reason), reason_len); } @@ -382,6 +383,7 @@ void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reaso // Normal memory access const char *reason_str = LOG_STR_ARG(reason); size_t reason_len = strlen(reason_str); + reason_len = std::min(reason_len, sizeof(data) - 1); if (reason_len > 0) { // NOLINTNEXTLINE(bugprone-not-null-terminated-result) - binary protocol, not a C string std::memcpy(data + 1, reason_str, reason_len); diff --git a/esphome/components/at581x/at581x.cpp b/esphome/components/at581x/at581x.cpp index 728fbe20c6..6fc85b0790 100644 --- a/esphome/components/at581x/at581x.cpp +++ b/esphome/components/at581x/at581x.cpp @@ -135,6 +135,11 @@ bool AT581XComponent::i2c_write_config() { } // Set gain + if (this->gain_ < 0 || static_cast<size_t>(this->gain_) >= ARRAY_SIZE(GAIN5C_TABLE) || + static_cast<size_t>(this->gain_ >> 1) >= ARRAY_SIZE(GAIN63_TABLE)) { + ESP_LOGE(TAG, "AT581X gain index out of range: %d", this->gain_); + return false; + } if (!this->i2c_write_reg(GAIN_ADDR_TABLE[0], GAIN5C_TABLE[this->gain_]) || !this->i2c_write_reg(GAIN_ADDR_TABLE[1], GAIN63_TABLE[this->gain_ >> 1])) { ESP_LOGE(TAG, "Failed to write AT581X gain registers"); diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.cpp b/esphome/components/vl53l0x/vl53l0x_sensor.cpp index e833657fc4..0b2b40d723 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.cpp +++ b/esphome/components/vl53l0x/vl53l0x_sensor.cpp @@ -87,9 +87,9 @@ void VL53L0XSensor::setup() { reg(0x94) = 0x6B; reg(0x83) = 0x00; - this->timeout_start_us_ = micros(); + uint32_t timeout_start_us = micros(); while (reg(0x83).get() == 0x00) { - if (this->timeout_us_ > 0 && ((uint16_t) (micros() - this->timeout_start_us_) > this->timeout_us_)) { + if (this->timeout_us_ > 0 && (micros() - timeout_start_us > this->timeout_us_)) { ESP_LOGE(TAG, "'%s' - setup timeout", this->name_.c_str()); this->mark_failed(); return; diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.h b/esphome/components/vl53l0x/vl53l0x_sensor.h index 2bf90015fe..f533005b5b 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.h +++ b/esphome/components/vl53l0x/vl53l0x_sensor.h @@ -64,8 +64,7 @@ class VL53L0XSensor : public sensor::Sensor, public PollingComponent, public i2c bool waiting_for_interrupt_{false}; uint8_t stop_variable_; - uint16_t timeout_start_us_; - uint16_t timeout_us_{}; + uint32_t timeout_us_{}; static std::list<VL53L0XSensor *> vl53_sensors; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static bool enable_pin_setup_complete; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) From b721cd48e5d8d41ad12eedf9e4ec941483cd99c3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:18:07 -0400 Subject: [PATCH 1239/2030] [hmc5883l][mmc5603][honeywellabp2][xgzp68xx][max9611] Fix uninitialized members (#14659) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/hmc5883l/hmc5883l.h | 2 +- esphome/components/honeywellabp2_i2c/honeywellabp2.h | 4 ++-- esphome/components/max9611/sensor.py | 4 +++- esphome/components/mmc5603/mmc5603.h | 4 ++-- esphome/components/xgzp68xx/sensor.py | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/esphome/components/hmc5883l/hmc5883l.h b/esphome/components/hmc5883l/hmc5883l.h index 8eae0f7a50..b5cf93e62b 100644 --- a/esphome/components/hmc5883l/hmc5883l.h +++ b/esphome/components/hmc5883l/hmc5883l.h @@ -61,7 +61,7 @@ class HMC5883LComponent : public PollingComponent, public i2c::I2CDevice { NONE = 0, COMMUNICATION_FAILED, ID_REGISTERS, - } error_code_; + } error_code_{NONE}; HighFrequencyLoopRequester high_freq_; }; diff --git a/esphome/components/honeywellabp2_i2c/honeywellabp2.h b/esphome/components/honeywellabp2_i2c/honeywellabp2.h index 274de847ac..d29ebb855d 100644 --- a/esphome/components/honeywellabp2_i2c/honeywellabp2.h +++ b/esphome/components/honeywellabp2_i2c/honeywellabp2.h @@ -45,8 +45,8 @@ class HONEYWELLABP2Sensor : public PollingComponent, public i2c::I2CDevice { const float max_count_b_ = 11744051.2; // (70% of 2^24 counts or 0xB33333) const float min_count_b_ = 5033164.8; // (30% of 2^24 counts or 0x4CCCCC) - float max_count_; - float min_count_; + float max_count_{max_count_a_}; + float min_count_{min_count_a_}; bool measurement_running_ = false; uint8_t raw_data_[7]; // holds output data diff --git a/esphome/components/max9611/sensor.py b/esphome/components/max9611/sensor.py index 8405a3f75a..b3a73d8c10 100644 --- a/esphome/components/max9611/sensor.py +++ b/esphome/components/max9611/sensor.py @@ -35,7 +35,9 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(MAX9611Component), - cv.Required(CONF_SHUNT_RESISTANCE): cv.resistance, + cv.Required(CONF_SHUNT_RESISTANCE): cv.All( + cv.resistance, cv.Range(min=1e-6) + ), cv.Required(CONF_GAIN): cv.enum(MAX9611_GAIN, upper=True), cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, diff --git a/esphome/components/mmc5603/mmc5603.h b/esphome/components/mmc5603/mmc5603.h index f827e27e04..9a77b78bc1 100644 --- a/esphome/components/mmc5603/mmc5603.h +++ b/esphome/components/mmc5603/mmc5603.h @@ -27,7 +27,7 @@ class MMC5603Component : public PollingComponent, public i2c::I2CDevice { void set_auto_set_reset(bool auto_set_reset) { auto_set_reset_ = auto_set_reset; } protected: - MMC5603Datarate datarate_; + MMC5603Datarate datarate_{MMC5603_DATARATE_75_0_HZ}; sensor::Sensor *x_sensor_{nullptr}; sensor::Sensor *y_sensor_{nullptr}; sensor::Sensor *z_sensor_{nullptr}; @@ -37,7 +37,7 @@ class MMC5603Component : public PollingComponent, public i2c::I2CDevice { NONE = 0, COMMUNICATION_FAILED, ID_REGISTERS, - } error_code_; + } error_code_{NONE}; }; } // namespace mmc5603 diff --git a/esphome/components/xgzp68xx/sensor.py b/esphome/components/xgzp68xx/sensor.py index 2b38392a02..6b83012eb4 100644 --- a/esphome/components/xgzp68xx/sensor.py +++ b/esphome/components/xgzp68xx/sensor.py @@ -56,7 +56,7 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), - cv.Optional(CONF_K_VALUE, default=4096): cv.uint16_t, + cv.Optional(CONF_K_VALUE, default=4096): cv.int_range(min=1, max=65535), } ) .extend(cv.polling_component_schema("60s")) From 08a0608a48965edfd7ef11301d2e38faefe2f5ab Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:18:21 -0400 Subject: [PATCH 1240/2030] [wifi][captive_portal][heatpumpir][es8388] Fix wrong behavior in 4 components (#14657) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../captive_portal/dns_server_esp32_idf.cpp | 5 +++-- esphome/components/es8388/es8388.cpp | 4 ++-- esphome/components/heatpumpir/heatpumpir.cpp | 2 +- .../wifi/wifi_component_esp8266.cpp | 20 ++++--------------- 4 files changed, 10 insertions(+), 21 deletions(-) diff --git a/esphome/components/captive_portal/dns_server_esp32_idf.cpp b/esphome/components/captive_portal/dns_server_esp32_idf.cpp index bd9989a40c..7b75f04241 100644 --- a/esphome/components/captive_portal/dns_server_esp32_idf.cpp +++ b/esphome/components/captive_portal/dns_server_esp32_idf.cpp @@ -14,6 +14,7 @@ static const char *const TAG = "captive_portal.dns"; // DNS constants static constexpr uint16_t DNS_PORT = 53; static constexpr uint16_t DNS_QR_FLAG = 1 << 15; +static constexpr uint16_t DNS_AA_FLAG = 1 << 10; static constexpr uint16_t DNS_OPCODE_MASK = 0x7800; static constexpr uint16_t DNS_QTYPE_A = 0x0001; static constexpr uint16_t DNS_QCLASS_IN = 0x0001; @@ -162,8 +163,8 @@ void DNSServer::process_next_request() { } // Build DNS response by modifying the request in-place - header->flags = htons(DNS_QR_FLAG | 0x8000); // Response + Authoritative - header->an_count = htons(1); // One answer + header->flags = htons(DNS_QR_FLAG | DNS_AA_FLAG); // Response + Authoritative + header->an_count = htons(1); // One answer // Add answer section after the question size_t question_len = (ptr + sizeof(DNSQuestion)) - this->buffer_ - sizeof(DNSHeader); diff --git a/esphome/components/es8388/es8388.cpp b/esphome/components/es8388/es8388.cpp index 72026a2a84..c252cdb707 100644 --- a/esphome/components/es8388/es8388.cpp +++ b/esphome/components/es8388/es8388.cpp @@ -152,7 +152,7 @@ void ES8388::dump_config() { bool ES8388::set_volume(float volume) { volume = clamp(volume, 0.0f, 1.0f); - uint8_t value = remap<uint8_t, float>(volume, 0.0f, 1.0f, -96, 0); + uint8_t value = remap<uint8_t, float>(volume, 0.0f, 1.0f, 192, 0); ESP_LOGD(TAG, "Setting ES8388_DACCONTROL4 / ES8388_DACCONTROL5 to 0x%02X (volume: %f)", value, volume); ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL4, value)); ES8388_ERROR_CHECK(this->write_byte(ES8388_DACCONTROL5, value)); @@ -163,7 +163,7 @@ bool ES8388::set_volume(float volume) { float ES8388::volume() { uint8_t value; ES8388_ERROR_CHECK(this->read_byte(ES8388_DACCONTROL4, &value)); - return remap<float, uint8_t>(value, -96, 0, 0.0f, 1.0f); + return remap<float, uint8_t>(value, 192, 0, 0.0f, 1.0f); } bool ES8388::set_mute_state_(bool mute_state) { diff --git a/esphome/components/heatpumpir/heatpumpir.cpp b/esphome/components/heatpumpir/heatpumpir.cpp index 6b73a24dc4..11e7672dc1 100644 --- a/esphome/components/heatpumpir/heatpumpir.cpp +++ b/esphome/components/heatpumpir/heatpumpir.cpp @@ -114,7 +114,7 @@ void HeatpumpIRClimate::setup() { this->current_temperature = state; IRSenderESPHome esp_sender(this->transmitter_); - this->heatpump_ir_->send(esp_sender, uint8_t(lround(this->current_temperature + 0.5))); + this->heatpump_ir_->send(esp_sender, uint8_t(lround(this->current_temperature))); // current temperature changed, publish state this->publish_state(); diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index a9b26c5935..0bf7934878 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -638,8 +638,6 @@ WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { return WiFiSTAConnectStatus::IDLE; } bool WiFiComponent::wifi_scan_start_(bool passive) { - static bool first_scan = false; - // enable STA if (!this->wifi_mode_(true, {})) return false; @@ -656,23 +654,13 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { config.show_hidden = 1; #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 4, 0) config.scan_type = passive ? WIFI_SCAN_TYPE_PASSIVE : WIFI_SCAN_TYPE_ACTIVE; - if (first_scan) { - if (passive) { - config.scan_time.passive = 200; - } else { - config.scan_time.active.min = 100; - config.scan_time.active.max = 200; - } + if (passive) { + config.scan_time.passive = 500; } else { - if (passive) { - config.scan_time.passive = 500; - } else { - config.scan_time.active.min = 400; - config.scan_time.active.max = 500; - } + config.scan_time.active.min = 400; + config.scan_time.active.max = 500; } #endif - first_scan = false; bool ret = wifi_station_scan(&config, &WiFiComponent::s_wifi_scan_done_callback); if (!ret) { ESP_LOGV(TAG, "wifi_station_scan failed"); From 9418f35cc32e0a6216b09b813664aa40bcc3e216 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:18:44 -0400 Subject: [PATCH 1241/2030] [multiple] Remove unnecessary heap allocations in 4 components (#14656) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/daikin_arc/daikin_arc.cpp | 9 +++++---- esphome/components/pn7150_i2c/pn7150_i2c.cpp | 3 ++- esphome/components/pn7160_i2c/pn7160_i2c.cpp | 3 ++- esphome/components/toshiba/toshiba.cpp | 6 +++--- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp index c45fa307a7..adb7b9fec7 100644 --- a/esphome/components/daikin_arc/daikin_arc.cpp +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -350,8 +350,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { if (data.expect_item(DAIKIN_HEADER_MARK, DAIKIN_HEADER_SPACE)) { valid_daikin_frame = true; size_t bytes_count = data.size() / 2 / 8; - size_t buf_size = bytes_count * 3 + 1; - std::unique_ptr<char[]> buf(new char[buf_size]()); // value-initialize (zero-fill) + // Header (20) + state (19) = 39 bytes max; truncates gracefully via buf_append_printf + char buf[40 * 3 + 1] = {}; + constexpr size_t buf_size = sizeof(buf); size_t buf_pos = 0; for (size_t i = 0; i < bytes_count; i++) { uint8_t byte = 0; @@ -363,9 +364,9 @@ bool DaikinArcClimate::on_receive(remote_base::RemoteReceiveData data) { break; } } - buf_pos = buf_append_printf(buf.get(), buf_size, buf_pos, "%02x ", byte); + buf_pos = buf_append_printf(buf, buf_size, buf_pos, "%02x ", byte); } - ESP_LOGD(TAG, "WHOLE FRAME %s size: %d", buf.get(), data.size()); + ESP_LOGD(TAG, "WHOLE FRAME %s size: %d", buf, data.size()); } if (!valid_daikin_frame) { char sbuf[16 * 10 + 1] = {0}; diff --git a/esphome/components/pn7150_i2c/pn7150_i2c.cpp b/esphome/components/pn7150_i2c/pn7150_i2c.cpp index 38b3102b37..4ae884595b 100644 --- a/esphome/components/pn7150_i2c/pn7150_i2c.cpp +++ b/esphome/components/pn7150_i2c/pn7150_i2c.cpp @@ -34,7 +34,8 @@ uint8_t PN7150I2C::read_nfcc(nfc::NciMessage &rx, const uint16_t timeout) { } uint8_t PN7150I2C::write_nfcc(nfc::NciMessage &tx) { - if (this->write(tx.encode().data(), tx.encode().size()) == i2c::ERROR_OK) { + auto encoded = tx.encode(); + if (this->write(encoded.data(), encoded.size()) == i2c::ERROR_OK) { return nfc::STATUS_OK; } return nfc::STATUS_FAILED; diff --git a/esphome/components/pn7160_i2c/pn7160_i2c.cpp b/esphome/components/pn7160_i2c/pn7160_i2c.cpp index 7c6da9dd06..e33c6c793d 100644 --- a/esphome/components/pn7160_i2c/pn7160_i2c.cpp +++ b/esphome/components/pn7160_i2c/pn7160_i2c.cpp @@ -34,7 +34,8 @@ uint8_t PN7160I2C::read_nfcc(nfc::NciMessage &rx, const uint16_t timeout) { } uint8_t PN7160I2C::write_nfcc(nfc::NciMessage &tx) { - if (this->write(tx.encode().data(), tx.encode().size()) == i2c::ERROR_OK) { + auto encoded = tx.encode(); + if (this->write(encoded.data(), encoded.size()) == i2c::ERROR_OK) { return nfc::STATUS_OK; } return nfc::STATUS_FAILED; diff --git a/esphome/components/toshiba/toshiba.cpp b/esphome/components/toshiba/toshiba.cpp index e0c150537a..53114cc50f 100644 --- a/esphome/components/toshiba/toshiba.cpp +++ b/esphome/components/toshiba/toshiba.cpp @@ -951,10 +951,10 @@ void ToshibaClimate::transmit_ras_2819t_() { } uint8_t ToshibaClimate::is_valid_rac_pt1411hwru_header_(const uint8_t *message) { - const std::vector<uint8_t> header{RAC_PT1411HWRU_MESSAGE_HEADER0, RAC_PT1411HWRU_CS_HEADER, - RAC_PT1411HWRU_SWING_HEADER}; + static constexpr uint8_t HEADERS[] = {RAC_PT1411HWRU_MESSAGE_HEADER0, RAC_PT1411HWRU_CS_HEADER, + RAC_PT1411HWRU_SWING_HEADER}; - for (auto i : header) { + for (auto i : HEADERS) { if ((message[0] == i) && (message[1] == static_cast<uint8_t>(~i))) return i; } From fecedeb01833d01cbc26ad331597a554e7904086 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:20:09 -0400 Subject: [PATCH 1242/2030] [multiple] Fix crashes from malformed external input (batch 2) (#14651) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 5 ++++ .../modbus_controller/modbus_controller.cpp | 23 +++++++++++++++++++ .../nextion/nextion_upload_arduino.cpp | 6 +++++ .../nextion/nextion_upload_esp32.cpp | 6 +++++ .../seeed_mr60bha2/seeed_mr60bha2.cpp | 2 +- .../components/usb_host/usb_host_client.cpp | 5 ++++ 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 73a298d279..0e2a515b40 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -514,6 +514,11 @@ void ESPBTDevice::parse_adv_(const uint8_t *payload, uint8_t len) { continue; // Possible zero padded advertisement data } + // Validate field fits in remaining payload + if (offset + field_length > len) { + break; + } + // first byte of adv record is adv record type const uint8_t record_type = payload[offset++]; const uint8_t *record = &payload[offset]; diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 7f0eb230e0..f77f51a20d 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -59,6 +59,10 @@ bool ModbusController::send_next_command_() { // Queue incoming response void ModbusController::on_modbus_data(const std::vector<uint8_t> &data) { + if (this->command_queue_.empty()) { + ESP_LOGW(TAG, "Received modbus data but command queue is empty"); + return; + } auto ¤t_command = this->command_queue_.front(); if (current_command != nullptr) { if (this->module_offline_) { @@ -92,6 +96,9 @@ void ModbusController::process_modbus_data_(const ModbusCommandItem *response) { void ModbusController::on_modbus_error(uint8_t function_code, uint8_t exception_code) { ESP_LOGE(TAG, "Modbus error function code: 0x%X exception: %d ", function_code, exception_code); + if (this->command_queue_.empty()) { + return; + } // Remove pending command waiting for a response auto ¤t_command = this->command_queue_.front(); if (current_command != nullptr) { @@ -175,6 +182,11 @@ void ModbusController::on_modbus_write_registers(uint8_t function_code, const st uint16_t payload_offset; if (function_code == ModbusFunctionCode::WRITE_MULTIPLE_REGISTERS) { + if (data.size() < 5) { + ESP_LOGW(TAG, "Write multiple registers data too short (%zu bytes)", data.size()); + this->send_error(function_code, ModbusExceptionCode::ILLEGAL_DATA_VALUE); + return; + } number_of_registers = uint16_t(data[3]) | (uint16_t(data[2]) << 8); if (number_of_registers == 0 || number_of_registers > modbus::MAX_NUM_OF_REGISTERS_TO_WRITE) { ESP_LOGW(TAG, "Invalid number of registers %d. Sending exception response.", number_of_registers); @@ -188,8 +200,19 @@ void ModbusController::on_modbus_write_registers(uint8_t function_code, const st this->send_error(function_code, ModbusExceptionCode::ILLEGAL_DATA_VALUE); return; } + if (data.size() < 5 + payload_size) { + ESP_LOGW(TAG, "Write multiple registers payload truncated (%zu bytes, expected %u)", data.size(), + 5 + payload_size); + this->send_error(function_code, ModbusExceptionCode::ILLEGAL_DATA_VALUE); + return; + } payload_offset = 5; } else if (function_code == ModbusFunctionCode::WRITE_SINGLE_REGISTER) { + if (data.size() < 4) { + ESP_LOGW(TAG, "Write single register data too short (%zu bytes)", data.size()); + this->send_error(function_code, ModbusExceptionCode::ILLEGAL_DATA_VALUE); + return; + } number_of_registers = 1; payload_offset = 2; } else { diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index e03f1f470b..6c454ab745 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -86,6 +86,12 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { ESP_LOGD(TAG, "Upload: %0.2f%% (%" PRIu32 " left, heap: %" PRIu32 ")", upload_percentage, this->content_length_, EspClass::getFreeHeap()); upload_first_chunk_sent_ = true; + if (recv_string.empty()) { + ESP_LOGW(TAG, "No response from display during upload"); + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request char hex_buf[format_hex_pretty_size(NEXTION_MAX_RESPONSE_LOG_BYTES)]; ESP_LOGD( diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index 1014c728a8..166bbcc86a 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -108,6 +108,12 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r static_cast<uint32_t>(esp_get_free_heap_size())); #endif upload_first_chunk_sent_ = true; + if (recv_string.empty()) { + ESP_LOGW(TAG, "No response from display during upload"); + allocator.deallocate(buffer, 4096); + buffer = nullptr; + return -1; + } if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request char hex_buf[format_hex_pretty_size(NEXTION_MAX_RESPONSE_LOG_BYTES)]; ESP_LOGD( diff --git a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp index 8628faac5a..1b5eaf6367 100644 --- a/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp +++ b/esphome/components/seeed_mr60bha2/seeed_mr60bha2.cpp @@ -199,7 +199,7 @@ void MR60BHA2Component::process_frame_(uint16_t frame_id, uint16_t frame_type, c } break; case DISTANCE_TYPE_BUFFER: - if (data[0] != 0) { + if (length >= 1 && data[0] != 0) { if (this->distance_sensor_ != nullptr && length >= 8) { uint32_t current_distance_int = encode_uint32(data[7], data[6], data[5], data[4]); float distance_float; diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index c77d738ace..2a460d1a07 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -492,6 +492,11 @@ bool USBClient::transfer_in(uint8_t ep_address, const transfer_cb_t &callback, u ESP_LOGE(TAG, "Too many requests queued"); return false; } + if (length > trq->transfer->data_buffer_size) { + ESP_LOGE(TAG, "transfer_in: data length %u exceeds buffer size %u", length, trq->transfer->data_buffer_size); + this->release_trq(trq); + return false; + } trq->callback = callback; trq->transfer->callback = transfer_callback; trq->transfer->bEndpointAddress = ep_address | USB_DIR_IN; From 7c1b9f0cb4b7862764ace94d4ccb2119b1024419 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:22:06 -0400 Subject: [PATCH 1243/2030] [multiple] Fix wrong behavior in 5 components (#14647) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/anova/anova.cpp | 9 ++++++--- esphome/components/binary_sensor/filter.cpp | 1 - esphome/components/bl0906/bl0906.cpp | 8 +++----- .../components/esp32_ble_tracker/esp32_ble_tracker.cpp | 2 +- esphome/components/ledc/ledc_output.cpp | 3 +++ 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/esphome/components/anova/anova.cpp b/esphome/components/anova/anova.cpp index b625f92115..f21230b075 100644 --- a/esphome/components/anova/anova.cpp +++ b/esphome/components/anova/anova.cpp @@ -144,9 +144,12 @@ void Anova::update() { return; if (this->current_request_ < 2) { - auto *pkt = this->codec_->get_read_device_status_request(); - if (this->current_request_ == 0) - this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c'); + AnovaPacket *pkt; + if (this->current_request_ == 0) { + pkt = this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c'); + } else { + pkt = this->codec_->get_read_device_status_request(); + } auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_, pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE); diff --git a/esphome/components/binary_sensor/filter.cpp b/esphome/components/binary_sensor/filter.cpp index 25a69c413a..5d525e967d 100644 --- a/esphome/components/binary_sensor/filter.cpp +++ b/esphome/components/binary_sensor/filter.cpp @@ -136,7 +136,6 @@ optional<bool> SettleFilter::new_value(bool value) { return {}; } else { this->steady_ = false; - this->output(value); this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->steady_ = true; }); return value; } diff --git a/esphome/components/bl0906/bl0906.cpp b/esphome/components/bl0906/bl0906.cpp index 7b643bba98..dcae4a2591 100644 --- a/esphome/components/bl0906/bl0906.cpp +++ b/esphome/components/bl0906/bl0906.cpp @@ -190,11 +190,9 @@ void BL0906::bias_correction_(uint8_t address, float measurements, float correct float i_rms0 = measurements * ki; float i_rms = correction * ki; int32_t value = (i_rms * i_rms - i_rms0 * i_rms0) / 256; - data.l = value << 24 >> 24; - data.m = value << 16 >> 24; - if (value < 0) { - data.h = (value << 8 >> 24) | 0b10000000; - } + data.l = value & 0xFF; + data.m = (value >> 8) & 0xFF; + data.h = (value >> 16) & 0xFF; data.address = bl0906_checksum(address, &data); ESP_LOGV(TAG, "RMSOS:%02X%02X%02X%02X%02X%02X", BL0906_WRITE_COMMAND, address, data.l, data.m, data.h, data.address); this->write_byte(BL0906_WRITE_COMMAND); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 0e2a515b40..5a43cf7e49 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -549,7 +549,7 @@ void ESPBTDevice::parse_adv_(const uint8_t *payload, uint8_t len) { // CSS 1.5 TX POWER LEVEL // "The TX Power Level data type indicates the transmitted power level of the packet containing the data type." // CSS 1: Optional in this context (may appear more than once in a block). - this->tx_powers_.push_back(*payload); + this->tx_powers_.push_back(*record); break; } case ESP_BLE_AD_TYPE_APPEARANCE: { diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 21e0682257..763de851da 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -76,6 +76,9 @@ esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_n init_result = ledc_timer_config(&timer_conf); if (init_result != ESP_OK) { ESP_LOGW(TAG, "Unable to initialize timer with frequency %.1f and bit depth of %u", frequency, bit_depth); + if (bit_depth <= 1) { + break; + } // try again with a lower bit depth timer_conf.duty_resolution = static_cast<ledc_timer_bit_t>(--bit_depth); } From 9902447834e8b997bf8831b569484f0c164c8f33 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:51:50 -0400 Subject: [PATCH 1244/2030] [multiple] Fix minor bugs in 8 components (#14650) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bl0906/bl0906.cpp | 35 ++++++++++--------- esphome/components/bmi160/bmi160.cpp | 3 +- .../components/esp32_camera/esp32_camera.cpp | 7 ++++ esphome/components/ld2450/ld2450.cpp | 2 +- esphome/components/ld2450/ld2450.h | 2 +- .../light/addressable_light_effect.h | 2 ++ .../mopeka_std_check/mopeka_std_check.cpp | 18 +++++----- .../mopeka_std_check/mopeka_std_check.h | 2 +- esphome/components/rtttl/rtttl.cpp | 13 ++++--- 9 files changed, 49 insertions(+), 35 deletions(-) diff --git a/esphome/components/bl0906/bl0906.cpp b/esphome/components/bl0906/bl0906.cpp index dcae4a2591..70db235a37 100644 --- a/esphome/components/bl0906/bl0906.cpp +++ b/esphome/components/bl0906/bl0906.cpp @@ -138,23 +138,24 @@ void BL0906::read_data_(const uint8_t address, const float reference, sensor::Se this->write_byte(BL0906_READ_COMMAND); this->write_byte(address); - if (this->read_array((uint8_t *) &buffer, sizeof(buffer) - 1)) { - if (bl0906_checksum(address, &buffer) == buffer.checksum) { - if (signed_result) { - data_s24.l = buffer.l; - data_s24.m = buffer.m; - data_s24.h = buffer.h; - } else { - data_u24.l = buffer.l; - data_u24.m = buffer.m; - data_u24.h = buffer.h; - } - } else { - ESP_LOGW(TAG, "Junk on wire. Throwing away partial message"); - while (read() >= 0) - ; - return; - } + if (!this->read_array((uint8_t *) &buffer, sizeof(buffer) - 1)) { + ESP_LOGW(TAG, "Read failed"); + return; + } + if (bl0906_checksum(address, &buffer) != buffer.checksum) { + ESP_LOGW(TAG, "Junk on wire. Throwing away partial message"); + while (read() >= 0) + ; + return; + } + if (signed_result) { + data_s24.l = buffer.l; + data_s24.m = buffer.m; + data_s24.h = buffer.h; + } else { + data_u24.l = buffer.l; + data_u24.m = buffer.m; + data_u24.h = buffer.h; } // Power if (reference == BL0906_PREF) { diff --git a/esphome/components/bmi160/bmi160.cpp b/esphome/components/bmi160/bmi160.cpp index 1e8c91d7b7..ed92979d24 100644 --- a/esphome/components/bmi160/bmi160.cpp +++ b/esphome/components/bmi160/bmi160.cpp @@ -6,6 +6,7 @@ namespace esphome { namespace bmi160 { static const char *const TAG = "bmi160"; +static constexpr uint32_t GYRO_WAKEUP_TIMEOUT_MS = 100; const uint8_t BMI160_REGISTER_CHIPID = 0x00; @@ -144,7 +145,7 @@ void BMI160Component::internal_setup_(int stage) { } ESP_LOGV(TAG, " Waiting for gyroscope to wake up"); // wait between 51 & 81ms, doing 100 to be safe - this->set_timeout(10, [this]() { this->internal_setup_(2); }); + this->set_timeout(GYRO_WAKEUP_TIMEOUT_MS, [this]() { this->internal_setup_(2); }); break; case 2: diff --git a/esphome/components/esp32_camera/esp32_camera.cpp b/esphome/components/esp32_camera/esp32_camera.cpp index 655ae54f0a..085feb8c8a 100644 --- a/esphome/components/esp32_camera/esp32_camera.cpp +++ b/esphome/components/esp32_camera/esp32_camera.cpp @@ -146,6 +146,10 @@ void ESP32Camera::dump_config() { } sensor_t *s = esp_camera_sensor_get(); + if (s == nullptr) { + ESP_LOGE(TAG, " Camera sensor not available"); + return; + } auto st = s->status; ESP_LOGCONFIG(TAG, " JPEG Quality: %u\n" @@ -483,6 +487,9 @@ void ESP32Camera::request_image(camera::CameraRequester requester) { this->singl camera::CameraImageReader *ESP32Camera::create_image_reader() { return new ESP32CameraImageReader; } void ESP32Camera::update_camera_parameters() { sensor_t *s = esp_camera_sensor_get(); + if (s == nullptr) { + return; + } /* update image */ s->set_vflip(s, this->vertical_flip_); s->set_hmirror(s, this->horizontal_mirror_); diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index eb17cc7de7..f9701cbdf6 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -133,7 +133,7 @@ static constexpr uint8_t DATA_FRAME_FOOTER[2] = {0x55, 0xCC}; // MAC address the module uses when Bluetooth is disabled static constexpr uint8_t NO_MAC[] = {0x08, 0x05, 0x04, 0x03, 0x02, 0x01}; -static inline uint16_t convert_seconds_to_ms(uint16_t value) { return value * 1000; }; +static inline uint32_t convert_seconds_to_ms(uint16_t value) { return (uint32_t) value * 1000; }; static inline void convert_int_values_to_hex(const int *values, uint8_t *bytes) { for (uint8_t i = 0; i < 4; i++) { diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 39b0ebd9da..9409dfc21d 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -168,7 +168,7 @@ class LD2450Component : public Component, public uart::UARTDevice { uint32_t presence_millis_ = 0; uint32_t still_presence_millis_ = 0; uint32_t moving_presence_millis_ = 0; - uint16_t timeout_ = 5; + uint32_t timeout_ = 5; uint8_t buffer_data_[MAX_LINE_LENGTH]; uint8_t mac_address_[6] = {0, 0, 0, 0, 0, 0}; uint8_t version_[6] = {0, 0, 0, 0, 0, 0}; diff --git a/esphome/components/light/addressable_light_effect.h b/esphome/components/light/addressable_light_effect.h index 461ddbc085..283b037aca 100644 --- a/esphome/components/light/addressable_light_effect.h +++ b/esphome/components/light/addressable_light_effect.h @@ -324,6 +324,8 @@ class AddressableFireworksEffect : public AddressableLightEffect { target *= 170; view = target; } + if (it.size() < 2) + return; int last = it.size() - 1; it[0].set(it[0].get() + (it[1].get() * 128)); for (int i = 1; i < last; i++) { diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.cpp b/esphome/components/mopeka_std_check/mopeka_std_check.cpp index 88bd7b02fd..a4a31b8260 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.cpp +++ b/esphome/components/mopeka_std_check/mopeka_std_check.cpp @@ -126,18 +126,18 @@ bool MopekaStdCheck::parse_device(const esp32_ble_tracker::ESPBTDevice &device) // Copy measurements over into my array. { u_int8_t measurements_index = 0; - for (u_int8_t i = 0; i < 3; i++) { - measurements_time[measurements_index] = mopeka_data->val[i].time_0 + 1; - measurements_value[measurements_index] = mopeka_data->val[i].value_0; + for (const auto &val : mopeka_data->val) { + measurements_time[measurements_index] = val.time_0 + 1; + measurements_value[measurements_index] = val.value_0; measurements_index++; - measurements_time[measurements_index] = mopeka_data->val[i].time_1 + 1; - measurements_value[measurements_index] = mopeka_data->val[i].value_1; + measurements_time[measurements_index] = val.time_1 + 1; + measurements_value[measurements_index] = val.value_1; measurements_index++; - measurements_time[measurements_index] = mopeka_data->val[i].time_2 + 1; - measurements_value[measurements_index] = mopeka_data->val[i].value_2; + measurements_time[measurements_index] = val.time_2 + 1; + measurements_value[measurements_index] = val.value_2; measurements_index++; - measurements_time[measurements_index] = mopeka_data->val[i].time_3 + 1; - measurements_value[measurements_index] = mopeka_data->val[i].value_3; + measurements_time[measurements_index] = val.time_3 + 1; + measurements_value[measurements_index] = val.value_3; measurements_index++; } } diff --git a/esphome/components/mopeka_std_check/mopeka_std_check.h b/esphome/components/mopeka_std_check/mopeka_std_check.h index 45588988c5..c0a02f27f2 100644 --- a/esphome/components/mopeka_std_check/mopeka_std_check.h +++ b/esphome/components/mopeka_std_check/mopeka_std_check.h @@ -40,7 +40,7 @@ struct mopeka_std_package { // NOLINT(readability-identifier-naming,altera-stru bool slow_update_rate : 1; bool sync_pressed : 1; - mopeka_std_values val[4]; + mopeka_std_values val[3]; } __attribute__((packed)); class MopekaStdCheck : public Component, public esp32_ble_tracker::ESPBTDeviceListener { diff --git a/esphome/components/rtttl/rtttl.cpp b/esphome/components/rtttl/rtttl.cpp index 9bf0450993..01f5aad810 100644 --- a/esphome/components/rtttl/rtttl.cpp +++ b/esphome/components/rtttl/rtttl.cpp @@ -146,16 +146,19 @@ void Rtttl::loop() { } #endif // USE_SPEAKER + // Align to note: most rtttl's out there does not add any space after the ',' separator but just in case + while (this->position_ < this->rtttl_.length()) { + char c = this->rtttl_[this->position_]; + if (c != ',' && c != ' ') + break; + this->position_++; + } + if (this->position_ >= this->rtttl_.length()) { this->finish_(); return; } - // Align to note: most rtttl's out there does not add any space after the ',' separator but just in case - while (this->rtttl_[this->position_] == ',' || this->rtttl_[this->position_] == ' ') { - this->position_++; - } - // First, get note duration, if available uint8_t note_denominator = this->get_integer_(); From 470d9160a512b41042710bf4eb48455dbbd17007 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:57:02 -0400 Subject: [PATCH 1245/2030] [demo] Fix alarm control panel auth bypass when code is omitted (#14645) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/demo/demo_alarm_control_panel.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/demo/demo_alarm_control_panel.h b/esphome/components/demo/demo_alarm_control_panel.h index 76cb24c2f4..9976e5c7f0 100644 --- a/esphome/components/demo/demo_alarm_control_panel.h +++ b/esphome/components/demo/demo_alarm_control_panel.h @@ -32,8 +32,8 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component { auto code = call.get_code(); switch (state) { case ACP_STATE_ARMED_AWAY: - if (this->get_requires_code_to_arm() && code.has_value()) { - if (*code != "1234") { + if (this->get_requires_code_to_arm()) { + if (!code.has_value() || *code != "1234") { this->status_momentary_error("invalid_code", 5000); return; } @@ -41,8 +41,8 @@ class DemoAlarmControlPanel : public AlarmControlPanel, public Component { this->publish_state(ACP_STATE_ARMED_AWAY); break; case ACP_STATE_DISARMED: - if (this->get_requires_code() && code.has_value()) { - if (*code != "1234") { + if (this->get_requires_code()) { + if (!code.has_value() || *code != "1234") { this->status_momentary_error("invalid_code", 5000); return; } From 308e8e78cd0fb549b64b1ed16a30dcd1be26c9e3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 17:59:36 -0400 Subject: [PATCH 1246/2030] [ble_scanner] Escape special characters in JSON output (#14664) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/ble_scanner/ble_scanner.h | 23 ++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/components/ble_scanner/ble_scanner.h b/esphome/components/ble_scanner/ble_scanner.h index 7061b6d336..c6d7f24cce 100644 --- a/esphome/components/ble_scanner/ble_scanner.h +++ b/esphome/components/ble_scanner/ble_scanner.h @@ -16,12 +16,27 @@ namespace ble_scanner { class BLEScanner : public text_sensor::TextSensor, public esp32_ble_tracker::ESPBTDeviceListener, public Component { public: bool parse_device(const esp32_ble_tracker::ESPBTDevice &device) override { - // Format JSON using stack buffer to avoid heap allocations from string concatenation - char buf[128]; char addr_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + // Escape special characters in the device name for valid JSON + const char *name = device.get_name().c_str(); + char escaped_name[128]; + size_t pos = 0; + for (; *name != '\0' && pos < sizeof(escaped_name) - 7; name++) { + uint8_t c = static_cast<uint8_t>(*name); + if (c == '"' || c == '\\') { + escaped_name[pos++] = '\\'; + escaped_name[pos++] = c; + } else if (c < 0x20) { + pos += snprintf(escaped_name + pos, sizeof(escaped_name) - pos, "\\u%04x", c); + } else { + escaped_name[pos++] = c; + } + } + escaped_name[pos] = '\0'; + + char buf[256]; snprintf(buf, sizeof(buf), "{\"timestamp\":%" PRId64 ",\"address\":\"%s\",\"rssi\":%d,\"name\":\"%s\"}", - static_cast<int64_t>(::time(nullptr)), device.address_str_to(addr_buf), device.get_rssi(), - device.get_name().c_str()); + static_cast<int64_t>(::time(nullptr)), device.address_str_to(addr_buf), device.get_rssi(), escaped_name); this->publish_state(buf); return true; } From b3fc43c13c5bee4b60c0bae0dbc1b244e4f4c60c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:00:17 -0400 Subject: [PATCH 1247/2030] [multiple] Fix wrong behavior in sensor calculations and drivers (#14644) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/bme280_base/bme280_base.cpp | 7 +++++-- esphome/components/bme680/bme680.h | 4 ++-- esphome/components/cse7766/cse7766.cpp | 9 +++++---- esphome/components/hitachi_ac344/hitachi_ac344.h | 2 +- esphome/components/rx8130/rx8130.cpp | 4 ++-- esphome/components/usb_uart/cp210x.cpp | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/esphome/components/bme280_base/bme280_base.cpp b/esphome/components/bme280_base/bme280_base.cpp index f396888fd1..addbfe618d 100644 --- a/esphome/components/bme280_base/bme280_base.cpp +++ b/esphome/components/bme280_base/bme280_base.cpp @@ -147,8 +147,11 @@ void BME280Component::setup() { this->calibration_.h1 = read_u8_(BME280_REGISTER_DIG_H1); this->calibration_.h2 = read_s16_le_(BME280_REGISTER_DIG_H2); this->calibration_.h3 = read_u8_(BME280_REGISTER_DIG_H3); - this->calibration_.h4 = read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F); - this->calibration_.h5 = read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4); + // h4 and h5 are signed 12-bit values; shift left then arithmetic right shift to sign-extend + int16_t h4_raw = read_u8_(BME280_REGISTER_DIG_H4) << 4 | (read_u8_(BME280_REGISTER_DIG_H4 + 1) & 0x0F); + this->calibration_.h4 = static_cast<int16_t>(h4_raw << 4) >> 4; + int16_t h5_raw = read_u8_(BME280_REGISTER_DIG_H5 + 1) << 4 | (read_u8_(BME280_REGISTER_DIG_H5) >> 4); + this->calibration_.h5 = static_cast<int16_t>(h5_raw << 4) >> 4; this->calibration_.h6 = read_u8_(BME280_REGISTER_DIG_H6); uint8_t humid_control_val = 0; diff --git a/esphome/components/bme680/bme680.h b/esphome/components/bme680/bme680.h index d48a42823b..239823fa8c 100644 --- a/esphome/components/bme680/bme680.h +++ b/esphome/components/bme680/bme680.h @@ -32,8 +32,8 @@ enum BME680Oversampling { /// Struct for storing calibration data for the BME680. struct BME680CalibrationData { uint16_t t1; - uint16_t t2; - uint8_t t3; + int16_t t2; + int8_t t3; uint16_t p1; int16_t p2; diff --git a/esphome/components/cse7766/cse7766.cpp b/esphome/components/cse7766/cse7766.cpp index 806b79e19e..ce77b62b7b 100644 --- a/esphome/components/cse7766/cse7766.cpp +++ b/esphome/components/cse7766/cse7766.cpp @@ -2,6 +2,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cmath> namespace esphome::cse7766 { @@ -192,12 +193,12 @@ void CSE7766Component::parse_data_() { this->apparent_power_sensor_->publish_state(apparent_power); } if (have_power && this->reactive_power_sensor_ != nullptr) { - const float reactive_power = apparent_power - power; - if (reactive_power < 0.0f) { - ESP_LOGD(TAG, "Impossible reactive power: %.4f is negative", reactive_power); + const float q_squared = apparent_power * apparent_power - power * power; + if (q_squared < 0.0f) { + ESP_LOGD(TAG, "Impossible reactive power: S^2-P^2 is negative (%.4f)", q_squared); this->reactive_power_sensor_->publish_state(0.0f); } else { - this->reactive_power_sensor_->publish_state(reactive_power); + this->reactive_power_sensor_->publish_state(std::sqrt(q_squared)); } } if (this->power_factor_sensor_ != nullptr && (have_power || power_cycle_exceeds_range)) { diff --git a/esphome/components/hitachi_ac344/hitachi_ac344.h b/esphome/components/hitachi_ac344/hitachi_ac344.h index c34f033d92..0877b83261 100644 --- a/esphome/components/hitachi_ac344/hitachi_ac344.h +++ b/esphome/components/hitachi_ac344/hitachi_ac344.h @@ -96,7 +96,7 @@ class HitachiClimate : public climate_ir::ClimateIR { void set_power_(bool on); uint8_t get_mode_(); void set_mode_(uint8_t mode); - void set_temp_(uint8_t celsius, bool set_previous = false); + void set_temp_(uint8_t celsius, bool set_previous = true); uint8_t get_fan_(); void set_fan_(uint8_t speed); void set_swing_v_toggle_(bool on); diff --git a/esphome/components/rx8130/rx8130.cpp b/esphome/components/rx8130/rx8130.cpp index ba092a4834..9e6f05ee15 100644 --- a/esphome/components/rx8130/rx8130.cpp +++ b/esphome/components/rx8130/rx8130.cpp @@ -75,7 +75,7 @@ void RX8130Component::read_time() { .second = bcd2dec(date[0] & 0x7f), .minute = bcd2dec(date[1] & 0x7f), .hour = bcd2dec(date[2] & 0x3f), - .day_of_week = bcd2dec(date[3] & 0x7f), + .day_of_week = static_cast<uint8_t>((date[3] & 0x7f) ? __builtin_ctz(date[3] & 0x7f) + 1 : 1), .day_of_month = bcd2dec(date[4] & 0x3f), .day_of_year = 1, // ignored by recalc_timestamp_utc(false) .month = bcd2dec(date[5] & 0x1f), @@ -103,7 +103,7 @@ void RX8130Component::write_time() { buff[0] = dec2bcd(now.second); buff[1] = dec2bcd(now.minute); buff[2] = dec2bcd(now.hour); - buff[3] = dec2bcd(now.day_of_week); + buff[3] = 1 << (now.day_of_week - 1); buff[4] = dec2bcd(now.day_of_month); buff[5] = dec2bcd(now.month); buff[6] = dec2bcd(now.year % 100); diff --git a/esphome/components/usb_uart/cp210x.cpp b/esphome/components/usb_uart/cp210x.cpp index ae9170c5fb..261f40c0db 100644 --- a/esphome/components/usb_uart/cp210x.cpp +++ b/esphome/components/usb_uart/cp210x.cpp @@ -65,7 +65,7 @@ std::vector<CdcEps> USBUartTypeCP210X::parse_descriptors(usb_device_handle_t dev } for (uint8_t i = 0; i != config_desc->bNumInterfaces; i++) { - auto data_desc = usb_parse_interface_descriptor(config_desc, 0, 0, &conf_offset); + auto data_desc = usb_parse_interface_descriptor(config_desc, i, 0, &conf_offset); if (!data_desc) { ESP_LOGE(TAG, "data_desc: usb_parse_interface_descriptor failed"); break; From 468ce74c8e2822a87c5367f22ca2c8732732e940 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 9 Mar 2026 17:04:47 -0500 Subject: [PATCH 1248/2030] [api][serial_proxy] Fix dangling pointer (#14640) --- esphome/components/api/api_connection.cpp | 12 ++++++++++++ esphome/components/serial_proxy/serial_proxy.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 28a770a4fb..7bd5d5120b 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -155,6 +155,18 @@ APIConnection::~APIConnection() { voice_assistant::global_voice_assistant->client_subscription(this, false); } #endif +#ifdef USE_ZWAVE_PROXY + if (zwave_proxy::global_zwave_proxy != nullptr && zwave_proxy::global_zwave_proxy->get_api_connection() == this) { + zwave_proxy::global_zwave_proxy->zwave_proxy_request(this, enums::ZWAVE_PROXY_REQUEST_TYPE_UNSUBSCRIBE); + } +#endif +#ifdef USE_SERIAL_PROXY + for (auto *proxy : App.get_serial_proxies()) { + if (proxy->get_api_connection() == this) { + proxy->serial_proxy_request(this, enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE); + } + } +#endif } void APIConnection::destroy_active_iterator_() { diff --git a/esphome/components/serial_proxy/serial_proxy.h b/esphome/components/serial_proxy/serial_proxy.h index 52f0654ff0..62f942b19d 100644 --- a/esphome/components/serial_proxy/serial_proxy.h +++ b/esphome/components/serial_proxy/serial_proxy.h @@ -74,6 +74,9 @@ class SerialProxy : public uart::UARTDevice, public Component { /// @param data_size Number of data bits (5-8) void configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits, uint8_t data_size); + /// Get the currently subscribed API connection (nullptr if none) + api::APIConnection *get_api_connection() { return this->api_connection_; } + /// Handle a subscribe/unsubscribe request from an API client void serial_proxy_request(api::APIConnection *api_connection, api::enums::SerialProxyRequestType type); From d2686b49bef3fdf1d56f7f222e1532e8c25d4380 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:15:33 -0400 Subject: [PATCH 1249/2030] [canbus] Fix multiple MCP component bugs (#14461) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/canbus/canbus.cpp | 3 ++- esphome/components/mcp23x08_base/mcp23x08_base.cpp | 4 ++-- esphome/components/mcp23x17_base/mcp23x17_base.cpp | 4 ++-- esphome/components/mcp2515/mcp2515.cpp | 1 + esphome/components/mcp4461/mcp4461.cpp | 12 ++++++------ esphome/components/mcp4728/mcp4728.h | 2 +- 6 files changed, 14 insertions(+), 12 deletions(-) diff --git a/esphome/components/canbus/canbus.cpp b/esphome/components/canbus/canbus.cpp index e208b0fd66..ce48bfbba5 100644 --- a/esphome/components/canbus/canbus.cpp +++ b/esphome/components/canbus/canbus.cpp @@ -1,4 +1,5 @@ #include "canbus.h" +#include <algorithm> #include "esphome/core/log.h" namespace esphome { @@ -82,7 +83,7 @@ void Canbus::loop() { std::vector<uint8_t> data; // show data received - for (int i = 0; i < can_message.can_data_length_code; i++) { + for (int i = 0; i < std::min(can_message.can_data_length_code, CAN_MAX_DATA_LENGTH); i++) { ESP_LOGV(TAG, " can_message.data[%d]=%02x", i, can_message.data[i]); data.push_back(can_message.data[i]); } diff --git a/esphome/components/mcp23x08_base/mcp23x08_base.cpp b/esphome/components/mcp23x08_base/mcp23x08_base.cpp index 1593c376cd..92228be62c 100644 --- a/esphome/components/mcp23x08_base/mcp23x08_base.cpp +++ b/esphome/components/mcp23x08_base/mcp23x08_base.cpp @@ -47,12 +47,12 @@ void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterr case mcp23xxx_base::MCP23XXX_RISING: this->update_reg(pin, true, gpinten); this->update_reg(pin, true, intcon); - this->update_reg(pin, true, defval); + this->update_reg(pin, false, defval); break; case mcp23xxx_base::MCP23XXX_FALLING: this->update_reg(pin, true, gpinten); this->update_reg(pin, true, intcon); - this->update_reg(pin, false, defval); + this->update_reg(pin, true, defval); break; case mcp23xxx_base::MCP23XXX_NO_INTERRUPT: this->update_reg(pin, false, gpinten); diff --git a/esphome/components/mcp23x17_base/mcp23x17_base.cpp b/esphome/components/mcp23x17_base/mcp23x17_base.cpp index b1f1f260b4..6f95ee98fd 100644 --- a/esphome/components/mcp23x17_base/mcp23x17_base.cpp +++ b/esphome/components/mcp23x17_base/mcp23x17_base.cpp @@ -59,12 +59,12 @@ void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterr case mcp23xxx_base::MCP23XXX_RISING: this->update_reg(pin, true, gpinten); this->update_reg(pin, true, intcon); - this->update_reg(pin, true, defval); + this->update_reg(pin, false, defval); break; case mcp23xxx_base::MCP23XXX_FALLING: this->update_reg(pin, true, gpinten); this->update_reg(pin, true, intcon); - this->update_reg(pin, false, defval); + this->update_reg(pin, true, defval); break; case mcp23xxx_base::MCP23XXX_NO_INTERRUPT: this->update_reg(pin, false, gpinten); diff --git a/esphome/components/mcp2515/mcp2515.cpp b/esphome/components/mcp2515/mcp2515.cpp index 77bfaf9224..c2db9228c8 100644 --- a/esphome/components/mcp2515/mcp2515.cpp +++ b/esphome/components/mcp2515/mcp2515.cpp @@ -506,6 +506,7 @@ canbus::Error MCP2515::set_bitrate_(canbus::CanSpeed can_speed, CanClock can_clo cfg3 = MCP_12MHZ_40KBPS_CFG3; break; case (canbus::CAN_50KBPS): // 50Kbps + cfg1 = MCP_12MHZ_50KBPS_CFG1; cfg2 = MCP_12MHZ_50KBPS_CFG2; cfg3 = MCP_12MHZ_50KBPS_CFG3; break; diff --git a/esphome/components/mcp4461/mcp4461.cpp b/esphome/components/mcp4461/mcp4461.cpp index dc7e7019aa..48d90377df 100644 --- a/esphome/components/mcp4461/mcp4461.cpp +++ b/esphome/components/mcp4461/mcp4461.cpp @@ -79,8 +79,8 @@ void Mcp4461Component::dump_config() { // reworked to be a one-line intentionally, as output would not be in order if (i < 4) { ESP_LOGCONFIG(TAG, " ├── Volatile wiper [%u] level: %u, Status: %s, HW: %s, A: %s, B: %s, W: %s", i, - this->reg_[i].state, ONOFF(this->reg_[i].terminal_hw), ONOFF(this->reg_[i].terminal_a), - ONOFF(this->reg_[i].terminal_b), ONOFF(this->reg_[i].terminal_w), ONOFF(this->reg_[i].enabled)); + this->reg_[i].state, ONOFF(this->reg_[i].enabled), ONOFF(this->reg_[i].terminal_hw), + ONOFF(this->reg_[i].terminal_a), ONOFF(this->reg_[i].terminal_b), ONOFF(this->reg_[i].terminal_w)); } else { ESP_LOGCONFIG(TAG, " ├── Nonvolatile wiper [%u] level: %u", i, this->reg_[i].state); } @@ -315,9 +315,9 @@ void Mcp4461Component::disable_wiper_(Mcp4461WiperIdx wiper) { return; } ESP_LOGV(TAG, "Disabling wiper %u", wiper_idx); - this->reg_[wiper_idx].enabled = true; + this->reg_[wiper_idx].enabled = false; if (wiper_idx < 4) { - this->reg_[wiper_idx].terminal_hw = true; + this->reg_[wiper_idx].terminal_hw = false; this->reg_[wiper_idx].update_terminal = true; } } @@ -490,7 +490,7 @@ void Mcp4461Component::enable_terminal_(Mcp4461WiperIdx wiper, char terminal) { ESP_LOGW(TAG, "Unknown terminal %c specified", terminal); return; } - this->reg_[wiper_idx].update_terminal = false; + this->reg_[wiper_idx].update_terminal = true; } void Mcp4461Component::disable_terminal_(Mcp4461WiperIdx wiper, char terminal) { @@ -517,7 +517,7 @@ void Mcp4461Component::disable_terminal_(Mcp4461WiperIdx wiper, char terminal) { ESP_LOGW(TAG, "Unknown terminal %c specified", terminal); return; } - this->reg_[wiper_idx].update_terminal = false; + this->reg_[wiper_idx].update_terminal = true; } uint16_t Mcp4461Component::get_eeprom_value(Mcp4461EepromLocation location) { diff --git a/esphome/components/mcp4728/mcp4728.h b/esphome/components/mcp4728/mcp4728.h index f2262f4a35..d657408081 100644 --- a/esphome/components/mcp4728/mcp4728.h +++ b/esphome/components/mcp4728/mcp4728.h @@ -58,7 +58,7 @@ class MCP4728Component : public Component, public i2c::I2CDevice { void select_gain_(MCP4728ChannelIdx channel, MCP4728Gain gain); private: - DACInputData reg_[4]; + DACInputData reg_[4]{}; bool store_in_eeprom_ = false; bool update_ = false; }; From d96be88ff58d3dac9454364f6da24ff4ff0e3561 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 18:32:57 -0400 Subject: [PATCH 1250/2030] [multiple] Fix reliability issues in 5 components (#14655) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/bme680_bsec/bme680_bsec.cpp | 8 +++++++- esphome/components/hlk_fm22x/hlk_fm22x.cpp | 16 ++++++++++++++++ esphome/components/lvgl/lvgl_esphome.cpp | 6 ++++++ esphome/components/mqtt/mqtt_client.cpp | 4 +++- esphome/components/usb_uart/usb_uart.cpp | 5 +++++ 5 files changed, 37 insertions(+), 2 deletions(-) diff --git a/esphome/components/bme680_bsec/bme680_bsec.cpp b/esphome/components/bme680_bsec/bme680_bsec.cpp index 454be0c0fe..75efb6835a 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.cpp +++ b/esphome/components/bme680_bsec/bme680_bsec.cpp @@ -271,10 +271,16 @@ void BME680BSECComponent::read_() { int64_t curr_time_ns = this->get_time_ns_(); if (this->bme680_settings_.trigger_measurement) { + uint32_t start = millis(); while (this->bme680_.power_mode != BME680_SLEEP_MODE) { + if (millis() - start > 50) { + ESP_LOGE(TAG, "Timeout waiting for BME680 to enter sleep mode"); + return; + } this->bme680_status_ = bme680_get_sensor_mode(&this->bme680_); if (this->bme680_status_ != BME680_OK) { - ESP_LOGW(TAG, "Failed to get sensor mode (BME680 Error Code %d)", this->bme680_status_); + ESP_LOGE(TAG, "Failed to get sensor mode (BME680 Error Code %d)", this->bme680_status_); + return; } } } diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.cpp b/esphome/components/hlk_fm22x/hlk_fm22x.cpp index 7c7c8782de..7a0dc0690c 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.cpp +++ b/esphome/components/hlk_fm22x/hlk_fm22x.cpp @@ -6,6 +6,7 @@ namespace esphome::hlk_fm22x { static const char *const TAG = "hlk_fm22x"; +static constexpr uint32_t PAYLOAD_TIMEOUT_MS = 20; void HlkFm22xComponent::setup() { ESP_LOGCONFIG(TAG, "Setting up HLK-FM22X..."); @@ -133,6 +134,21 @@ void HlkFm22xComponent::recv_command_() { checksum ^= byte; length |= byte; + // Wait for remaining data (payload + checksum) to arrive. + // Header bytes are already consumed, so we must finish reading this message. + uint32_t start = millis(); + while (this->available() < length + 1) { + if (millis() - start > PAYLOAD_TIMEOUT_MS) { + ESP_LOGE(TAG, "Timeout waiting for payload (%u bytes)", length); + // Drain any partial payload bytes to resync the parser + while (this->available() > 0) { + this->read(); + } + return; + } + delay(1); + } + // Read up to buffer size; discard excess bytes while still computing checksum // GET_ALL_FACE_IDS can return all enrolled face data (hundreds of bytes) // but handlers only need the first few bytes diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 66cb25b864..5400054bb1 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -163,8 +163,11 @@ void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t ti void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) { if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_)) return; + size_t start = this->current_page_; do { this->current_page_ = (this->current_page_ + 1) % this->pages_.size(); + if (this->current_page_ == start) + return; // all pages have skip=true (guaranteed not to happen by YAML validation) } while (this->pages_[this->current_page_]->skip); // skip empty pages() this->show_page(this->current_page_, anim, time); } @@ -172,8 +175,11 @@ void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) { void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) { if (this->pages_.empty() || (this->current_page_ == 0 && !this->page_wrap_)) return; + size_t start = this->current_page_; do { this->current_page_ = (this->current_page_ + this->pages_.size() - 1) % this->pages_.size(); + if (this->current_page_ == start) + return; // all pages have skip=true (guaranteed not to happen by YAML validation) } while (this->pages_[this->current_page_]->skip); // skip empty pages() this->show_page(this->current_page_, anim, time); } diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 1a03c5329e..38daf8f8f6 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -44,8 +44,10 @@ MQTTClientComponent::MQTTClientComponent() { void MQTTClientComponent::setup() { this->mqtt_backend_.set_on_message( [this](const char *topic, const char *payload, size_t len, size_t index, size_t total) { - if (index == 0) + if (index == 0) { + this->payload_buffer_.clear(); this->payload_buffer_.reserve(total); + } // append new payload, may contain incomplete MQTT message this->payload_buffer_.append(payload, len); diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 83de0b39fc..3d35f368fb 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -106,10 +106,15 @@ std::vector<CdcEps> USBUartTypeCdcAcm::parse_descriptors(usb_device_handle_t dev } void RingBuffer::push(uint8_t item) { + if (this->get_free_space() == 0) + return; this->buffer_[this->insert_pos_] = item; this->insert_pos_ = (this->insert_pos_ + 1) % this->buffer_size_; } void RingBuffer::push(const uint8_t *data, size_t len) { + size_t free = this->get_free_space(); + if (len > free) + len = free; for (size_t i = 0; i != len; i++) { this->buffer_[this->insert_pos_] = *data++; this->insert_pos_ = (this->insert_pos_ + 1) % this->buffer_size_; From dadbdd0f7b2081031d395a2778f92706ab98647a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Mar 2026 12:34:31 -1000 Subject: [PATCH 1251/2030] [ci] Make codeowner label update non-fatal for fork PRs (#14668) --- .../codeowner-approved-label-update.yml | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/codeowner-approved-label-update.yml b/.github/workflows/codeowner-approved-label-update.yml index c2eb886913..0bce33ebe2 100644 --- a/.github/workflows/codeowner-approved-label-update.yml +++ b/.github/workflows/codeowner-approved-label-update.yml @@ -55,18 +55,24 @@ jobs: return; } - if (action === LabelAction.ADD) { - await github.rest.issues.addLabels({ - owner, repo, issue_number: pr_number, labels: [LABEL_NAME] - }); - console.log(`Added '${LABEL_NAME}' label`); - } else if (action === LabelAction.REMOVE) { - try { + try { + if (action === LabelAction.ADD) { + await github.rest.issues.addLabels({ + owner, repo, issue_number: pr_number, labels: [LABEL_NAME] + }); + console.log(`Added '${LABEL_NAME}' label`); + } else if (action === LabelAction.REMOVE) { await github.rest.issues.removeLabel({ owner, repo, issue_number: pr_number, name: LABEL_NAME }); console.log(`Removed '${LABEL_NAME}' label`); - } catch (error) { - if (error.status !== 404) throw error; + } + } catch (error) { + if (error.status === 403) { + console.log(`Warning: insufficient permissions to update label (expected for fork PRs)`); + } else if (error.status === 404) { + console.log(`Label '${LABEL_NAME}' not present, nothing to remove`); + } else { + throw error; } } From d6ce5dda81d6fdf966392e80b68a8c8cac0a3192 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Mar 2026 12:54:56 -1000 Subject: [PATCH 1252/2030] [ci] Skip YAML anchor keys in integration fixture component extraction (#14670) --- script/helpers.py | 6 ++++-- tests/script/test_helpers.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/script/helpers.py b/script/helpers.py index 202ac9b5fc..d372d2a7ec 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -705,8 +705,10 @@ def get_components_from_integration_fixtures() -> set[str]: if not config: continue - # Add all top-level component keys - components.update(config.keys()) + # Add all top-level component keys (skip YAML anchor keys starting with '.') + components.update( + k for k in config if isinstance(k, str) and not k.startswith(".") + ) # Add platform components (e.g., output.template) for value in config.values(): diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index 7e60ba41fc..2953a9fd42 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -1057,6 +1057,30 @@ def test_get_components_from_integration_fixtures() -> None: assert components == expected_components +def test_get_components_from_integration_fixtures_skips_yaml_anchors() -> None: + """Test that YAML anchor keys (starting with '.') are excluded.""" + yaml_content = { + "sensor": [{"platform": "template", "name": "test"}], + "esphome": {"name": "test"}, + ".sensor_filters": {"filters": [{"timeout": "50ms"}]}, + ".binary_filters": {"filters": [{"settle": "50ms"}]}, + } + + mock_yaml_file = Mock() + + with ( + patch("pathlib.Path.glob") as mock_glob, + patch("esphome.yaml_util.load_yaml", return_value=yaml_content), + ): + mock_glob.return_value = [mock_yaml_file] + + components = helpers.get_components_from_integration_fixtures() + + assert ".sensor_filters" not in components + assert ".binary_filters" not in components + assert components == {"sensor", "esphome", "template"} + + @pytest.mark.parametrize( "output,expected", [ From c31ac662bd08cdb99859819dc92a8a9295fb828c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 9 Mar 2026 20:39:58 -0400 Subject: [PATCH 1253/2030] [multiple] Fix crashes from malformed external input (#14643) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/b_parasite/b_parasite.cpp | 10 ++ .../components/kamstrup_kmp/kamstrup_kmp.cpp | 12 +- esphome/components/ld2412/ld2412.cpp | 39 ++-- esphome/components/nextion/nextion.cpp | 4 +- esphome/components/pipsolar/pipsolar.cpp | 9 +- esphome/components/smt100/smt100.cpp | 25 ++- .../uart_mock_ld2412_engineering.yaml | 93 +++------- ...art_mock_ld2412_engineering_truncated.yaml | 167 ++++++++++++++++++ tests/integration/test_uart_mock_ld2412.py | 125 +++++++++++++ 9 files changed, 390 insertions(+), 94 deletions(-) create mode 100644 tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml diff --git a/esphome/components/b_parasite/b_parasite.cpp b/esphome/components/b_parasite/b_parasite.cpp index 356f396476..7be26efa7f 100644 --- a/esphome/components/b_parasite/b_parasite.cpp +++ b/esphome/components/b_parasite/b_parasite.cpp @@ -38,6 +38,11 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { const auto &data = service_data.data; + if (data.size() < 10) { + ESP_LOGW(TAG, "Service data too short: %zu", data.size()); + return false; + } + const uint8_t protocol_version = data[0] >> 4; if (protocol_version != 1 && protocol_version != 2) { ESP_LOGE(TAG, "Unsupported protocol version: %u", protocol_version); @@ -47,6 +52,11 @@ bool BParasite::parse_device(const esp32_ble_tracker::ESPBTDevice &device) { // Some b-parasite versions have an (optional) illuminance sensor. bool has_illuminance = data[0] & 0x1; + if (has_illuminance && data.size() < 18) { + ESP_LOGW(TAG, "Service data too short for illuminance: %zu", data.size()); + return false; + } + // Counter for deduplicating messages. uint8_t counter = data[1] & 0x0f; if (last_processed_counter_ == counter) { diff --git a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp index 29de651255..9f2557243c 100644 --- a/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp +++ b/esphome/components/kamstrup_kmp/kamstrup_kmp.cpp @@ -110,9 +110,17 @@ void KamstrupKMPComponent::send_message_(const uint8_t *msg, int msg_len) { for (int i = 0; i < buffer_len; i++) { if (buffer[i] == 0x06 || buffer[i] == 0x0d || buffer[i] == 0x1b || buffer[i] == 0x40 || buffer[i] == 0x80) { + if (tx_msg_len + 2 >= static_cast<int>(sizeof(tx_msg))) { + ESP_LOGE(TAG, "TX message overflow"); + return; + } tx_msg[tx_msg_len++] = 0x1b; tx_msg[tx_msg_len++] = buffer[i] ^ 0xff; } else { + if (tx_msg_len + 1 >= static_cast<int>(sizeof(tx_msg))) { + ESP_LOGE(TAG, "TX message overflow"); + return; + } tx_msg[tx_msg_len++] = buffer[i]; } } @@ -216,8 +224,8 @@ void KamstrupKMPComponent::parse_command_message_(uint16_t command, const uint8_ uint8_t unit_idx = msg[4]; uint8_t mantissa_range = msg[5]; - if (mantissa_range > 4) { - ESP_LOGE(TAG, "Received invalid message (mantissa size too large %d, expected 4)", mantissa_range); + if (mantissa_range > 4 || msg_len < 7 + mantissa_range) { + ESP_LOGE(TAG, "Received invalid message (mantissa size %d, msg_len %d)", mantissa_range, msg_len); return; } diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index ef0915d0bc..37578dd8da 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -413,24 +413,29 @@ void LD2412Component::handle_periodic_data_() { this->detection_distance_sensor_->publish_state_if_not_dup(new_detect_distance); } if (engineering_mode) { - /* - Moving distance range: 18th byte - Still distance range: 19th byte - Moving energy: 20~28th bytes - */ - for (uint8_t i = 0; i < TOTAL_GATES; i++) { - SAFE_PUBLISH_SENSOR(this->gate_move_sensors_[i], this->buffer_data_[MOVING_SENSOR_START + i]) + // Engineering mode needs at least LIGHT_SENSOR + 1 bytes + if (this->buffer_pos_ < LIGHT_SENSOR + 1) { + ESP_LOGW(TAG, "Engineering mode packet too short: %u", this->buffer_pos_); + } else { + /* + Moving distance range: 18th byte + Still distance range: 19th byte + Moving energy: 20~28th bytes + */ + for (uint8_t i = 0; i < TOTAL_GATES; i++) { + SAFE_PUBLISH_SENSOR(this->gate_move_sensors_[i], this->buffer_data_[MOVING_SENSOR_START + i]) + } + /* + Still energy: 29~37th bytes + */ + for (uint8_t i = 0; i < TOTAL_GATES; i++) { + SAFE_PUBLISH_SENSOR(this->gate_still_sensors_[i], this->buffer_data_[STILL_SENSOR_START + i]) + } + /* + Light sensor value + */ + SAFE_PUBLISH_SENSOR(this->light_sensor_, this->buffer_data_[LIGHT_SENSOR]) } - /* - Still energy: 29~37th bytes - */ - for (uint8_t i = 0; i < TOTAL_GATES; i++) { - SAFE_PUBLISH_SENSOR(this->gate_still_sensors_[i], this->buffer_data_[STILL_SENSOR_START + i]) - } - /* - Light sensor: 38th bytes - */ - SAFE_PUBLISH_SENSOR(this->light_sensor_, this->buffer_data_[LIGHT_SENSOR]) } else { for (auto &gate_move_sensor : this->gate_move_sensors_) { SAFE_PUBLISH_SENSOR_UNKNOWN(gate_move_sensor) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 7ae4d50fc8..01ceb3d765 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -646,8 +646,8 @@ void Nextion::process_nextion_commands_() { break; } - if (to_process_length == 0) { - ESP_LOGE(TAG, "Numeric return but no data"); + if (to_process_length < 4) { + ESP_LOGE(TAG, "Numeric return but insufficient data (need 4, got %zu)", to_process_length); break; } diff --git a/esphome/components/pipsolar/pipsolar.cpp b/esphome/components/pipsolar/pipsolar.cpp index eb6d3931e0..c304d206c0 100644 --- a/esphome/components/pipsolar/pipsolar.cpp +++ b/esphome/components/pipsolar/pipsolar.cpp @@ -192,8 +192,13 @@ bool Pipsolar::send_next_command_() { if (!this->command_queue_[this->command_queue_position_].empty()) { const char *command = this->command_queue_[this->command_queue_position_].c_str(); uint8_t byte_command[16]; - uint8_t length = this->command_queue_[this->command_queue_position_].length(); - for (uint8_t i = 0; i < length; i++) { + size_t length = this->command_queue_[this->command_queue_position_].length(); + if (length > sizeof(byte_command)) { + ESP_LOGE(TAG, "Command too long: %zu", length); + this->command_queue_[this->command_queue_position_].clear(); + return false; + } + for (size_t i = 0; i < length; i++) { byte_command[i] = (uint8_t) this->command_queue_[this->command_queue_position_].at(i); } this->state_ = STATE_COMMAND; diff --git a/esphome/components/smt100/smt100.cpp b/esphome/components/smt100/smt100.cpp index 105cc06edb..6eb6416447 100644 --- a/esphome/components/smt100/smt100.cpp +++ b/esphome/components/smt100/smt100.cpp @@ -14,11 +14,26 @@ void SMT100Component::update() { void SMT100Component::loop() { while (this->available() != 0) { if (this->readline_(this->read(), this->readline_buffer_, MAX_LINE_LENGTH) > 0) { - int counts = (int) strtol((strtok(this->readline_buffer_, ",")), nullptr, 10); - float permittivity = (float) strtod((strtok(nullptr, ",")), nullptr); - float moisture = (float) strtod((strtok(nullptr, ",")), nullptr); - float temperature = (float) strtod((strtok(nullptr, ",")), nullptr); - float voltage = (float) strtod((strtok(nullptr, ",")), nullptr); + char *token = strtok(this->readline_buffer_, ","); + if (!token) + continue; + int counts = (int) strtol(token, nullptr, 10); + token = strtok(nullptr, ","); + if (!token) + continue; + float permittivity = (float) strtod(token, nullptr); + token = strtok(nullptr, ","); + if (!token) + continue; + float moisture = (float) strtod(token, nullptr); + token = strtok(nullptr, ","); + if (!token) + continue; + float temperature = (float) strtod(token, nullptr); + token = strtok(nullptr, ","); + if (!token) + continue; + float voltage = (float) strtod(token, nullptr); if (this->counts_sensor_ != nullptr) { counts_sensor_->publish_state(counts); diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml index 103dbed132..a69e18888e 100644 --- a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml @@ -102,6 +102,18 @@ uart_mock: 0xF8, 0xF7, 0xF6, 0xF5, ] +# Common filter definitions +.sensor_filters: &sensor_filters + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +.binary_filters: &binary_filters + filters: + - settle: 50ms + ld2412: id: ld2412_dev uart_id: mock_uart @@ -111,107 +123,56 @@ sensor: ld2412_id: ld2412_dev moving_distance: name: "Moving Distance" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters still_distance: name: "Still Distance" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters moving_energy: name: "Moving Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters still_energy: name: "Still Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters detection_distance: name: "Detection Distance" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters light: name: "Light" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters gate_0: move_energy: name: "Gate 0 Move Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters still_energy: name: "Gate 0 Still Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters gate_1: move_energy: name: "Gate 1 Move Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters still_energy: name: "Gate 1 Still Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters gate_2: move_energy: name: "Gate 2 Move Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters still_energy: name: "Gate 2 Still Energy" - filters: - - timeout: - timeout: 50ms - value: last - - throttle_with_priority: 50ms + <<: *sensor_filters binary_sensor: - platform: ld2412 ld2412_id: ld2412_dev has_target: name: "Has Target" - filters: - - settle: 50ms + <<: *binary_filters has_moving_target: name: "Has Moving Target" - filters: - - settle: 50ms + <<: *binary_filters has_still_target: name: "Has Still Target" - filters: - - settle: 50ms + <<: *binary_filters button: - platform: template diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml new file mode 100644 index 0000000000..c0bd514762 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml @@ -0,0 +1,167 @@ +esphome: + name: uart-mock-ld2412-eng-trunc + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy ld2412's DEPENDENCIES = ["uart"] +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + id: mock_uart + baud_rate: 256000 + auto_start: false + injections: + # Phase 1 (t=100ms): Valid engineering mode frame (52 bytes, buffer_pos_=52) + # Establishes baseline: gate_0_move=100, light=87 + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x2A, 0x00, + 0x01, 0xAA, + 0x03, + 0x1E, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x00, 0x00, + 0x64, 0x41, 0x06, 0x0E, 0x2B, 0x16, 0x03, 0x03, 0x07, 0x05, 0x09, 0x08, 0x07, 0x06, + 0x00, 0x00, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x50, 0x40, 0x30, 0x20, 0x10, + 0x57, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 2 (t=200ms): Truncated engineering mode frame (24 bytes, buffer_pos_=24) + # This frame has data_type=0x01 (engineering) but only enough data for the + # basic target fields, not the gate energies or light sensor. + # buffer_pos_=24 passes the old check (>= 12) but fails the new check (< 46). + # Without the fix, indices 17-45 would read stale buffer data from Phase 1. + # + # Layout (24 bytes): + # [0-3] F4 F3 F2 F1 = data frame header + # [4-5] 0E 00 = length 14 + # [6] 01 = data type (engineering mode) + # [7] AA = data header marker + # [8] 03 = target states (moving+still) + # [9-10] 1E 00 = moving distance 30 + # [11] 50 = moving energy 80 + # [12-13] 1E 00 = still distance 30 + # [14] 50 = still energy 80 + # [15-16] FF FF = garbage detection distance bytes + # [17] FF = padding (would be gate data in full frame) + # [18] 55 = data footer marker (at buffer_pos_ - 6) + # [19] 00 = check byte + # [20-23] F8 F7 F6 F5 = data frame footer + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x0E, 0x00, + 0x01, 0xAA, + 0x03, + 0x1E, 0x00, + 0x50, + 0x1E, 0x00, + 0x50, + 0xFF, 0xFF, + 0xFF, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + + # Phase 3 (t=300ms): Valid recovery frame with different values + # gate_0_move=50, light=42 — proves component recovered + - delay: 100ms + inject_rx: + [ + 0xF4, 0xF3, 0xF2, 0xF1, + 0x2A, 0x00, + 0x01, 0xAA, + 0x03, + 0x1E, 0x00, + 0x64, + 0x1E, 0x00, + 0x64, + 0x00, 0x00, + 0x32, 0x20, 0x06, 0x0E, 0x2B, 0x16, 0x03, 0x03, 0x07, 0x05, 0x09, 0x08, 0x07, 0x06, + 0x00, 0x00, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x28, 0x20, 0x18, 0x10, 0x08, + 0x2A, + 0x55, 0x00, + 0xF8, 0xF7, 0xF6, 0xF5, + ] + +# Common filter definitions +.sensor_filters: &sensor_filters + filters: + - timeout: + timeout: 50ms + value: last + - throttle_with_priority: 50ms + +.binary_filters: &binary_filters + filters: + - settle: 50ms + +ld2412: + id: ld2412_dev + uart_id: mock_uart + +sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + moving_distance: + name: "Moving Distance" + <<: *sensor_filters + still_distance: + name: "Still Distance" + <<: *sensor_filters + moving_energy: + name: "Moving Energy" + <<: *sensor_filters + still_energy: + name: "Still Energy" + <<: *sensor_filters + detection_distance: + name: "Detection Distance" + <<: *sensor_filters + light: + name: "Light" + <<: *sensor_filters + gate_0: + move_energy: + name: "Gate 0 Move Energy" + <<: *sensor_filters + still_energy: + name: "Gate 0 Still Energy" + <<: *sensor_filters + +binary_sensor: + - platform: ld2412 + ld2412_id: ld2412_dev + has_target: + name: "Has Target" + <<: *binary_filters + has_moving_target: + name: "Has Moving Target" + <<: *binary_filters + has_still_target: + name: "Has Still Target" + <<: *binary_filters + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: 'id(mock_uart).start_scenario();' diff --git a/tests/integration/test_uart_mock_ld2412.py b/tests/integration/test_uart_mock_ld2412.py index a964ba0073..9b928ef14f 100644 --- a/tests/integration/test_uart_mock_ld2412.py +++ b/tests/integration/test_uart_mock_ld2412.py @@ -14,6 +14,12 @@ test_uart_mock_ld2412_engineering (engineering mode): 2. Multi-byte still distance (291cm) using high byte > 0 3. Gate energy sensor values 4. Detection distance computed from target state + +test_uart_mock_ld2412_engineering_truncated (truncated engineering mode): + 1. Valid engineering frame establishes baseline sensor values + 2. Truncated engineering frame (24 bytes) is rejected — gate/light sensors + must not receive garbage from stale buffer data or frame footer bytes + 3. Recovery frame with different values proves the component survived """ from __future__ import annotations @@ -273,3 +279,122 @@ async def test_uart_mock_ld2412_engineering( ) assert pytest.approx(291.0) in collector.sensor_states["detection_distance"] + + +@pytest.mark.asyncio +async def test_uart_mock_ld2412_engineering_truncated( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that truncated engineering mode frames don't corrupt sensor values. + + Without the fix, a 24-byte engineering mode frame passes the old buffer_pos_ >= 12 + check but reads indices 17-45 from stale buffer data, publishing garbage values + (e.g. frame footer bytes 0xF8=248 as gate energy). + """ + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + yaml_config = yaml_config.replace( + "EXTERNAL_COMPONENT_PATH", external_components_path + ) + + loop = asyncio.get_running_loop() + + # Track the truncated frame warning + truncated_warning_seen = loop.create_future() + + def line_callback(line: str) -> None: + if ( + "Engineering mode packet too short" in line + and not truncated_warning_seen.done() + ): + truncated_warning_seen.set_result(True) + + collector = SensorStateCollector( + sensor_names=[ + "moving_distance", + "still_distance", + "moving_energy", + "still_energy", + "detection_distance", + "light", + "gate_0_move_energy", + "gate_0_still_energy", + ], + binary_sensor_names=[ + "has_target", + "has_moving_target", + "has_still_target", + ], + ) + + # Signal when we see Phase 3 recovery values (gate_0_move=50) + recovery_received = collector.add_waiter( + lambda: pytest.approx(50.0) in collector.sensor_states["gate_0_move_energy"] + ) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + collector.build_key_mapping(entities) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states( + initial_state_helper.on_state_wrapper(collector.on_state) + ) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + + # Wait for Phase 1 — valid engineering frame establishes baseline + try: + await collector.wait_for_all(timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for Phase 1 frame. Received:\n" + f" sensor_states: {collector.sensor_states}\n" + f" binary_states: {collector.binary_states}" + ) + + # Phase 1 baseline: gate_0_move=100, light=87 + assert collector.sensor_states["gate_0_move_energy"][0] == pytest.approx(100.0) + assert collector.sensor_states["light"][0] == pytest.approx(87.0) + + # Wait for Phase 3 recovery frame (gate_0_move=50) + try: + await asyncio.wait_for(recovery_received, timeout=3.0) + except TimeoutError: + pytest.fail( + f"Timeout waiting for recovery frame. Received:\n" + f" gate_0_move_energy: {collector.sensor_states['gate_0_move_energy']}\n" + f" light: {collector.sensor_states['light']}" + ) + + # Verify the truncated frame warning was logged + assert truncated_warning_seen.done(), ( + "Expected 'Engineering mode packet too short' warning in logs" + ) + + # Phase 3 recovery: gate_0_move=50, light=42 + assert pytest.approx(50.0) in collector.sensor_states["gate_0_move_energy"] + assert pytest.approx(42.0) in collector.sensor_states["light"] + + # The critical assertion: gate_0_move_energy must never have received + # garbage values from the truncated frame. Without the fix, + # buffer_data_[17] = 0xFF = 255 would be published as gate_0_move. + for value in collector.sensor_states["gate_0_move_energy"]: + assert value == pytest.approx(100.0) or value == pytest.approx(50.0), ( + f"gate_0_move_energy got unexpected value {value} — " + f"truncated frame likely leaked stale buffer data. " + f"All values: {collector.sensor_states['gate_0_move_energy']}" + ) From 00f809f5f001a1428f099f3e0846d2c5d848cdf3 Mon Sep 17 00:00:00 2001 From: Tobias Stanzel <tobi.stanzel@gmail.com> Date: Tue, 10 Mar 2026 02:45:20 +0100 Subject: [PATCH 1254/2030] [sen6x] fix memory leak issue (#14623) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/sen6x/sen6x.cpp | 338 ++++++++++++++++------------- esphome/components/sen6x/sen6x.h | 6 + 2 files changed, 188 insertions(+), 156 deletions(-) diff --git a/esphome/components/sen6x/sen6x.cpp b/esphome/components/sen6x/sen6x.cpp index baaadd6463..2a6ea64735 100644 --- a/esphome/components/sen6x/sen6x.cpp +++ b/esphome/components/sen6x/sen6x.cpp @@ -2,13 +2,16 @@ #include "esphome/core/hal.h" #include "esphome/core/log.h" #include <cmath> -#include <functional> -#include <memory> namespace esphome::sen6x { static const char *const TAG = "sen6x"; +static constexpr uint8_t POLL_RETRIES = 24; // 24 attempts +static constexpr uint32_t I2C_READ_DELAY = 20; // 20 ms to wait for I2C read to complete +static constexpr uint32_t POLL_INTERVAL = 50; // 50 ms between poll attempts +// Single numeric timeout ID — the chain is sequential so only one is active at a time. +static constexpr uint32_t TIMEOUT_POLL = 1; static constexpr uint16_t SEN6X_CMD_GET_DATA_READY_STATUS = 0x0202; static constexpr uint16_t SEN6X_CMD_GET_FIRMWARE_VERSION = 0xD100; static constexpr uint16_t SEN6X_CMD_GET_PRODUCT_NAME = 0xD014; @@ -182,179 +185,202 @@ void SEN6XComponent::update() { return; } - uint16_t read_cmd; - uint8_t read_words; - set_read_command_and_words(this->sen6x_type_, read_cmd, read_words); + // Cancel any in-flight polling from a previous update() cycle. + this->cancel_timeout(TIMEOUT_POLL); - const uint8_t poll_retries = 24; - auto poll_ready = std::make_shared<std::function<void(uint8_t)>>(); - *poll_ready = [this, poll_ready, read_cmd, read_words](uint8_t retries_left) { - const uint8_t attempt = static_cast<uint8_t>(poll_retries - retries_left + 1); - ESP_LOGV(TAG, "Data ready polling attempt %u", attempt); + set_read_command_and_words(this->sen6x_type_, this->read_cmd_, this->read_words_); - if (!this->write_command(SEN6X_CMD_GET_DATA_READY_STATUS)) { + // Polling uses chained timeouts to guarantee each I2C operation completes + // before the next begins. The flow is: + // + // poll_data_ready_() + // -> write_command (data ready status) + // -> timeout I2C_READ_DELAY + // -> read_data (check ready flag) + // -> if not ready: timeout POLL_INTERVAL -> poll_data_ready_() (retry) + // -> if ready: read_measurements_() + // -> write_command (read measurement) + // -> timeout I2C_READ_DELAY + // -> parse_and_publish_measurements_() + // + // All timeouts share a single ID (TIMEOUT_POLL) since only one is active + // at a time. cancel_timeout in update() stops any in-flight chain. + this->poll_retries_remaining_ = POLL_RETRIES; + this->poll_data_ready_(); +} + +void SEN6XComponent::poll_data_ready_() { + if (this->poll_retries_remaining_ == 0) { + this->status_set_warning(); + ESP_LOGD(TAG, "Data not ready"); + return; + } + ESP_LOGV(TAG, "Data ready polling attempt %u", + static_cast<unsigned>(POLL_RETRIES - this->poll_retries_remaining_ + 1)); + this->poll_retries_remaining_--; + + if (!this->write_command(SEN6X_CMD_GET_DATA_READY_STATUS)) { + this->status_set_warning(); + ESP_LOGD(TAG, "write data ready status error (%d)", this->last_error_); + return; + } + + this->set_timeout(TIMEOUT_POLL, I2C_READ_DELAY, [this]() { + uint16_t raw_read_status; + if (!this->read_data(&raw_read_status, 1)) { this->status_set_warning(); - ESP_LOGD(TAG, "write data ready status error (%d)", this->last_error_); + ESP_LOGD(TAG, "read data ready status error (%d)", this->last_error_); return; } - this->set_timeout(20, [this, poll_ready, retries_left, read_cmd, read_words]() { - uint16_t raw_read_status; - if (!this->read_data(&raw_read_status, 1)) { - this->status_set_warning(); - ESP_LOGD(TAG, "read data ready status error (%d)", this->last_error_); - return; - } + if ((raw_read_status & 0x0001) == 0) { + // Not ready yet; schedule next attempt after POLL_INTERVAL. + this->set_timeout(TIMEOUT_POLL, POLL_INTERVAL, [this]() { this->poll_data_ready_(); }); + return; + } - if ((raw_read_status & 0x0001) == 0) { - if (retries_left == 0) { - this->status_set_warning(); - ESP_LOGD(TAG, "Data not ready"); - return; - } - this->set_timeout(50, [poll_ready, retries_left]() { (*poll_ready)(retries_left - 1); }); - return; - } + this->read_measurements_(); + }); +} - if (!this->write_command(read_cmd)) { - this->status_set_warning(); - ESP_LOGD(TAG, "Read measurement failed (%d)", this->last_error_); - return; - } +void SEN6XComponent::read_measurements_() { + if (!this->write_command(this->read_cmd_)) { + this->status_set_warning(); + ESP_LOGD(TAG, "Read measurement failed (%d)", this->last_error_); + return; + } - this->set_timeout(20, [this, read_words]() { - uint16_t measurements[10]; + this->set_timeout(TIMEOUT_POLL, I2C_READ_DELAY, [this]() { this->parse_and_publish_measurements_(); }); +} - if (!this->read_data(measurements, read_words)) { - this->status_set_warning(); - ESP_LOGD(TAG, "Read data failed (%d)", this->last_error_); - return; - } - int8_t voc_index = -1; - int8_t nox_index = -1; - int8_t hcho_index = -1; - int8_t co2_index = -1; - bool co2_uint16 = false; - switch (this->sen6x_type_) { - case SEN62: - break; - case SEN63C: - co2_index = 6; - break; - case SEN65: - voc_index = 6; - nox_index = 7; - break; - case SEN66: - voc_index = 6; - nox_index = 7; - co2_index = 8; - co2_uint16 = true; - break; - case SEN68: - voc_index = 6; - nox_index = 7; - hcho_index = 8; - break; - case SEN69C: - voc_index = 6; - nox_index = 7; - hcho_index = 8; - co2_index = 9; - break; - default: - break; - } +void SEN6XComponent::parse_and_publish_measurements_() { + uint16_t measurements[10]; - float pm_1_0 = measurements[0] / 10.0f; - if (measurements[0] == 0xFFFF) - pm_1_0 = NAN; - float pm_2_5 = measurements[1] / 10.0f; - if (measurements[1] == 0xFFFF) - pm_2_5 = NAN; - float pm_4_0 = measurements[2] / 10.0f; - if (measurements[2] == 0xFFFF) - pm_4_0 = NAN; - float pm_10_0 = measurements[3] / 10.0f; - if (measurements[3] == 0xFFFF) - pm_10_0 = NAN; - float humidity = static_cast<int16_t>(measurements[4]) / 100.0f; - if (measurements[4] == 0x7FFF) - humidity = NAN; - float temperature = static_cast<int16_t>(measurements[5]) / 200.0f; - if (measurements[5] == 0x7FFF) - temperature = NAN; + if (!this->read_data(measurements, this->read_words_)) { + this->status_set_warning(); + ESP_LOGD(TAG, "Read data failed (%d)", this->last_error_); + return; + } + int8_t voc_index = -1; + int8_t nox_index = -1; + int8_t hcho_index = -1; + int8_t co2_index = -1; + bool co2_uint16 = false; + switch (this->sen6x_type_) { + case SEN62: + break; + case SEN63C: + co2_index = 6; + break; + case SEN65: + voc_index = 6; + nox_index = 7; + break; + case SEN66: + voc_index = 6; + nox_index = 7; + co2_index = 8; + co2_uint16 = true; + break; + case SEN68: + voc_index = 6; + nox_index = 7; + hcho_index = 8; + break; + case SEN69C: + voc_index = 6; + nox_index = 7; + hcho_index = 8; + co2_index = 9; + break; + default: + break; + } - float voc = NAN; - float nox = NAN; - float hcho = NAN; - float co2 = NAN; + float pm_1_0 = measurements[0] / 10.0f; + if (measurements[0] == 0xFFFF) + pm_1_0 = NAN; + float pm_2_5 = measurements[1] / 10.0f; + if (measurements[1] == 0xFFFF) + pm_2_5 = NAN; + float pm_4_0 = measurements[2] / 10.0f; + if (measurements[2] == 0xFFFF) + pm_4_0 = NAN; + float pm_10_0 = measurements[3] / 10.0f; + if (measurements[3] == 0xFFFF) + pm_10_0 = NAN; + float humidity = static_cast<int16_t>(measurements[4]) / 100.0f; + if (measurements[4] == 0x7FFF) + humidity = NAN; + float temperature = static_cast<int16_t>(measurements[5]) / 200.0f; + if (measurements[5] == 0x7FFF) + temperature = NAN; - if (voc_index >= 0) { - voc = static_cast<int16_t>(measurements[voc_index]) / 10.0f; - if (measurements[voc_index] == 0x7FFF) - voc = NAN; - } - if (nox_index >= 0) { - nox = static_cast<int16_t>(measurements[nox_index]) / 10.0f; - if (measurements[nox_index] == 0x7FFF) - nox = NAN; - } + float voc = NAN; + float nox = NAN; + float hcho = NAN; + float co2 = NAN; - if (hcho_index >= 0) { - const uint16_t hcho_raw = measurements[hcho_index]; - hcho = hcho_raw / 10.0f; - if (hcho_raw == 0xFFFF) - hcho = NAN; - } + if (voc_index >= 0) { + voc = static_cast<int16_t>(measurements[voc_index]) / 10.0f; + if (measurements[voc_index] == 0x7FFF) + voc = NAN; + } + if (nox_index >= 0) { + nox = static_cast<int16_t>(measurements[nox_index]) / 10.0f; + if (measurements[nox_index] == 0x7FFF) + nox = NAN; + } - if (co2_index >= 0) { - if (co2_uint16) { - const uint16_t co2_raw = measurements[co2_index]; - co2 = static_cast<float>(co2_raw); - if (co2_raw == 0xFFFF) - co2 = NAN; - } else { - const int16_t co2_raw = static_cast<int16_t>(measurements[co2_index]); - co2 = static_cast<float>(co2_raw); - if (co2_raw == 0x7FFF) - co2 = NAN; - } - } + if (hcho_index >= 0) { + const uint16_t hcho_raw = measurements[hcho_index]; + hcho = hcho_raw / 10.0f; + if (hcho_raw == 0xFFFF) + hcho = NAN; + } - if (!this->startup_complete_) { - ESP_LOGD(TAG, "Startup delay, ignoring values"); - this->status_clear_warning(); - return; - } + if (co2_index >= 0) { + if (co2_uint16) { + const uint16_t co2_raw = measurements[co2_index]; + co2 = static_cast<float>(co2_raw); + if (co2_raw == 0xFFFF) + co2 = NAN; + } else { + const int16_t co2_raw = static_cast<int16_t>(measurements[co2_index]); + co2 = static_cast<float>(co2_raw); + if (co2_raw == 0x7FFF) + co2 = NAN; + } + } - if (this->pm_1_0_sensor_ != nullptr) - this->pm_1_0_sensor_->publish_state(pm_1_0); - if (this->pm_2_5_sensor_ != nullptr) - this->pm_2_5_sensor_->publish_state(pm_2_5); - if (this->pm_4_0_sensor_ != nullptr) - this->pm_4_0_sensor_->publish_state(pm_4_0); - if (this->pm_10_0_sensor_ != nullptr) - this->pm_10_0_sensor_->publish_state(pm_10_0); - if (this->temperature_sensor_ != nullptr) - this->temperature_sensor_->publish_state(temperature); - if (this->humidity_sensor_ != nullptr) - this->humidity_sensor_->publish_state(humidity); - if (this->voc_sensor_ != nullptr) - this->voc_sensor_->publish_state(voc); - if (this->nox_sensor_ != nullptr) - this->nox_sensor_->publish_state(nox); - if (this->hcho_sensor_ != nullptr) - this->hcho_sensor_->publish_state(hcho); - if (this->co2_sensor_ != nullptr) - this->co2_sensor_->publish_state(co2); + if (!this->startup_complete_) { + ESP_LOGD(TAG, "Startup delay, ignoring values"); + this->status_clear_warning(); + return; + } - this->status_clear_warning(); - }); - }); - }; + if (this->pm_1_0_sensor_ != nullptr) + this->pm_1_0_sensor_->publish_state(pm_1_0); + if (this->pm_2_5_sensor_ != nullptr) + this->pm_2_5_sensor_->publish_state(pm_2_5); + if (this->pm_4_0_sensor_ != nullptr) + this->pm_4_0_sensor_->publish_state(pm_4_0); + if (this->pm_10_0_sensor_ != nullptr) + this->pm_10_0_sensor_->publish_state(pm_10_0); + if (this->temperature_sensor_ != nullptr) + this->temperature_sensor_->publish_state(temperature); + if (this->humidity_sensor_ != nullptr) + this->humidity_sensor_->publish_state(humidity); + if (this->voc_sensor_ != nullptr) + this->voc_sensor_->publish_state(voc); + if (this->nox_sensor_ != nullptr) + this->nox_sensor_->publish_state(nox); + if (this->hcho_sensor_ != nullptr) + this->hcho_sensor_->publish_state(hcho); + if (this->co2_sensor_ != nullptr) + this->co2_sensor_->publish_state(co2); - (*poll_ready)(poll_retries); + this->status_clear_warning(); } SEN6XComponent::Sen6xType SEN6XComponent::infer_type_from_product_name_(const std::string &product_name) { diff --git a/esphome/components/sen6x/sen6x.h b/esphome/components/sen6x/sen6x.h index 01e89dce1b..bc44611882 100644 --- a/esphome/components/sen6x/sen6x.h +++ b/esphome/components/sen6x/sen6x.h @@ -30,13 +30,19 @@ class SEN6XComponent : public PollingComponent, public sensirion_common::Sensiri protected: Sen6xType infer_type_from_product_name_(const std::string &product_name); + void poll_data_ready_(); + void read_measurements_(); + void parse_and_publish_measurements_(); bool initialized_{false}; std::string product_name_; Sen6xType sen6x_type_{UNKNOWN}; std::string serial_number_; + uint16_t read_cmd_{0}; uint8_t firmware_version_major_{0}; uint8_t firmware_version_minor_{0}; + uint8_t poll_retries_remaining_{0}; + uint8_t read_words_{0}; bool startup_complete_{false}; }; From e82f0f443223a4985bf2014fbf9b5f4130b2f4b8 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Tue, 10 Mar 2026 03:41:02 +0100 Subject: [PATCH 1255/2030] [cpptests] support testing platform components (#13075) Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/core/__init__.py | 15 + esphome/loader.py | 5 + script/cpp_unit_test.py | 153 +++++++---- script/helpers.py | 15 +- tests/components/README.md | 13 + .../binary_sensor/binary_sensor_test.cpp | 77 ++++++ .../components/packet_transport/cpp_test.yaml | 11 - .../packet_transport_test.cpp | 259 ------------------ .../packet_transport/sensor/sensor_test.cpp | 170 ++++++++++++ tests/script/test_helpers.py | 67 +++++ tests/unit_tests/test_core.py | 12 + 11 files changed, 467 insertions(+), 330 deletions(-) create mode 100644 tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp delete mode 100644 tests/components/packet_transport/cpp_test.yaml create mode 100644 tests/components/packet_transport/sensor/sensor_test.cpp diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 484f679369..a86478aca1 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -615,6 +615,10 @@ class EsphomeCore: self.address_cache: AddressCache | None = None # Cached config hash (computed lazily) self._config_hash: int | None = None + # True if compiling for C++ unit tests + self.cpp_testing = False + # Allowlist of components whose to_code should run during C++ testing + self.cpp_testing_codegen: set[str] = set() def reset(self): from esphome.pins import PIN_SCHEMA_REGISTRY @@ -644,6 +648,8 @@ class EsphomeCore: self.current_component = None self.address_cache = None self._config_hash = None + self.cpp_testing = False + self.cpp_testing_codegen = set() PIN_SCHEMA_REGISTRY.reset() @contextmanager @@ -987,6 +993,15 @@ class EsphomeCore: """ self.platform_counts[platform_name] += 1 + def testing_ensure_platform_registered(self, platform_name: str) -> None: + """Ensure a platform has at least one entity registered for testing. + + Used during C++ test builds to guarantee USE_* defines are emitted + without needing a real component variable. + """ + if not self.platform_counts[platform_name]: + self.platform_counts[platform_name] = 1 + def register_controller(self) -> None: """Track registration of a Controller for ControllerRegistry StaticVector sizing.""" controller_count = self.data.setdefault(KEY_CONTROLLER_REGISTRY_COUNT, 0) diff --git a/esphome/loader.py b/esphome/loader.py index 968c8cf3e0..5771e07473 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -71,6 +71,11 @@ class ComponentManifest: @property def to_code(self) -> Callable[[Any], None] | None: + if CORE.cpp_testing: + # During C++ testing, only run to_code for allowlisted components + name = self.module.__package__.rsplit(".", 1)[-1] + if name not in CORE.cpp_testing_codegen: + return None return getattr(self.module, "to_code", None) @property diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index b87261ab33..e11687dc16 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -10,9 +10,10 @@ from helpers import get_all_components, get_all_dependencies, root_path from esphome.__main__ import command_compile, parse_args from esphome.config import validate_config +from esphome.const import CONF_PLATFORM from esphome.core import CORE +from esphome.loader import get_component from esphome.platformio_api import get_idedata -from esphome.yaml_util import load_yaml # This must coincide with the version in /platformio.ini PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" @@ -20,6 +21,13 @@ PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" # Path to /tests/components COMPONENTS_TESTS_DIR: Path = Path(root_path) / "tests" / "components" +# Components whose to_code should run during C++ test builds. +# Most components don't need code generation for tests; only these +# essential ones (platform setup, logging, core config) are needed. +# Note: "core" is the esphome core config module (esphome/core/config.py), +# which registers under package name "core" not "esphome". +CPP_TESTING_CODEGEN_COMPONENTS = {"core", "host", "logger"} + def hash_components(components: list[str]) -> str: key = ",".join(components) @@ -30,12 +38,14 @@ def filter_components_without_tests(components: list[str]) -> list[str]: """Filter out components that do not have a corresponding test file. This is done by checking if the component's directory contains at - least a .cpp file. + least a .cpp or .h file. """ filtered_components: list[str] = [] for component in components: test_dir = COMPONENTS_TESTS_DIR / component - if test_dir.is_dir() and any(test_dir.glob("*.cpp")): + if test_dir.is_dir() and ( + any(test_dir.glob("*.cpp")) or any(test_dir.glob("*.h")) + ): filtered_components.append(component) else: print( @@ -45,38 +55,6 @@ def filter_components_without_tests(components: list[str]) -> list[str]: return filtered_components -# Name of optional per-component YAML config merged into the test build -# before validation so that platform defines (USE_SENSOR, etc.) are generated. -CPP_TEST_CONFIG_FILE = "cpp_test.yaml" - - -def load_component_test_configs(components: list[str]) -> dict: - """Load cpp_test.yaml files from test component directories. - - These configs are merged into the base test config *before* validation - so that entity registration runs during code generation, which causes - the corresponding USE_* defines to be emitted. - """ - merged: dict = {} - for component in components: - config_file = COMPONENTS_TESTS_DIR / component / CPP_TEST_CONFIG_FILE - if not config_file.exists(): - continue - component_config = load_yaml(config_file) - if not component_config: - continue - for key, value in component_config.items(): - if ( - key in merged - and isinstance(merged[key], list) - and isinstance(value, list) - ): - merged[key].extend(value) - else: - merged[key] = value - return merged - - def create_test_config(config_name: str, includes: list[str]) -> dict: """Create ESPHome test configuration for C++ unit tests. @@ -113,11 +91,52 @@ def create_test_config(config_name: str, includes: list[str]) -> dict: } +def get_platform_components(components: list[str]) -> list[str]: + """Discover platform sub-components referenced by test directory structure. + + For each component being tested, any sub-directory named after a platform + domain (e.g. ``sensor``, ``binary_sensor``) is treated as a request to + include that ``<domain>.<component>`` platform in the build. The sub- + directory must name a valid platform domain; anything else raises an error + so that typos are caught early. + + Returns: + List of ``"domain.component"`` strings, one per discovered sub-directory. + """ + platform_components: list[str] = [] + for component in components: + test_dir = COMPONENTS_TESTS_DIR / component + if not test_dir.is_dir(): + continue + # Each sub-directory name is expected to be a platform domain + # (e.g. tests/components/bthome/sensor/ → sensor.bthome). + for domain_dir in test_dir.iterdir(): + if not domain_dir.is_dir(): + continue + domain = domain_dir.name + domain_module = get_component(domain) + if domain_module is None or not domain_module.is_platform_component: + raise ValueError( + f"Component tests for '{component}' reference non-existing or invalid domain '{domain}'" + f" in its directory structure. See ({COMPONENTS_TESTS_DIR / component / domain})." + ) + platform_components.append(f"{domain}.{component}") + return platform_components + + +# Exit codes for run_tests +EXIT_OK = 0 +EXIT_SKIPPED = 1 +EXIT_COMPILE_ERROR = 2 +EXIT_CONFIG_ERROR = 3 +EXIT_NO_EXECUTABLE = 4 + + def run_tests(selected_components: list[str]) -> int: # Skip tests on Windows if os.name == "nt": print("Skipping esphome tests on Windows", file=sys.stderr) - return 1 + return EXIT_SKIPPED # Remove components that do not have tests components = filter_components_without_tests(selected_components) @@ -127,45 +146,63 @@ def run_tests(selected_components: list[str]) -> int: "No components specified or no tests found for the specified components.", file=sys.stderr, ) - return 0 + return EXIT_OK components = sorted(components) - # Obtain possible dependencies for the requested components. - # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, - # which causes core/time.h to include components/time/posix_tz.h. - components_with_dependencies = sorted( - get_all_dependencies(set(components) | {"time"}) - ) - - # Build a list of include folders, one folder per component containing tests. - # A special replacement main.cpp is located in /tests/components/main.cpp + # Build a list of include folders relative to COMPONENTS_TESTS_DIR. These folders will + # be added along with their subfolders. + # "main.cpp" is a special entry that points to /tests/components/main.cpp, + # which provides a custom test runner entry-point replacing the default one. + # Each remaining entry is a component folder whose *.cpp files are compiled. includes: list[str] = ["main.cpp"] + components + # Obtain a list of platform components to be tested: + try: + platform_components = get_platform_components(components) + except ValueError as e: + print(f"Error obtaining platform components: {e}") + return EXIT_CONFIG_ERROR + + components = sorted(components + platform_components) + # Create a unique name for this config based on the actual components being tested # to maximize cache during testing config_name: str = "cpptests-" + hash_components(components) - config = create_test_config(config_name, includes) + # Obtain possible dependencies for the requested components. + # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, + # which causes core/time.h to include components/time/posix_tz.h. + components_with_dependencies: list[str] = sorted( + get_all_dependencies(set(components) | {"time"}, cpp_testing=True) + ) - # Merge component-specific test configs (e.g. sensor instances) before - # validation so that entity registration and USE_* defines work. - extra_config = load_component_test_configs(components) - config.update(extra_config) + config = create_test_config(config_name, includes) CORE.config_path = COMPONENTS_TESTS_DIR / "dummy.yaml" CORE.dashboard = None + CORE.cpp_testing = True + CORE.cpp_testing_codegen = CPP_TESTING_CODEGEN_COMPONENTS # Validate config will expand the above with defaults: config = validate_config(config, {}) # Add all components and dependencies to the base configuration after validation, so their files - # are added to the build. Use setdefault to avoid overwriting entries that were - # already validated (e.g. sensor instances from cpp_test.yaml). - for key in components_with_dependencies: - config.setdefault(key, {}) + # are added to the build. + for component_name in components_with_dependencies: + if "." in component_name: + # Format is always "domain.component" (exactly one dot), + # as produced by get_platform_components(). + domain, component = component_name.split(".", maxsplit=1) + domain_list = config.setdefault(domain, []) + CORE.testing_ensure_platform_registered(domain) + domain_list.append({CONF_PLATFORM: component}) + else: + config.setdefault(component_name, []) - print(f"Testing components: {', '.join(components)}") + dependencies = set(components_with_dependencies) - set(components) + deps_str = ", ".join(dependencies) if dependencies else "None" + print(f"Testing components: {', '.join(components)}. Dependencies: {deps_str}") CORE.config = config args = parse_args(["program", "compile", str(CORE.config_path)]) try: @@ -178,13 +215,13 @@ def run_tests(selected_components: list[str]) -> int: print( f"Error compiling unit tests for {', '.join(components)}. Check path. : {e}" ) - return 2 + return EXIT_COMPILE_ERROR # After a successful compilation, locate the executable and run it: idedata = get_idedata(config) if idedata is None: print("Cannot find executable") - return 1 + return EXIT_NO_EXECUTABLE program_path: str = idedata.raw["prog_path"] run_cmd: list[str] = [program_path] diff --git a/script/helpers.py b/script/helpers.py index d372d2a7ec..6ee286a657 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -15,6 +15,8 @@ from typing import Any import colorama +from esphome.loader import get_platform + root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, "..", ".."))) basepath = os.path.join(root_path, "esphome") temp_folder = os.path.join(root_path, ".temp") @@ -624,11 +626,15 @@ def get_usable_cpu_count() -> int: ) -def get_all_dependencies(component_names: set[str]) -> set[str]: +def get_all_dependencies( + component_names: set[str], cpp_testing: bool = False +) -> set[str]: """Get all dependencies for a set of components. Args: component_names: Set of component names to get dependencies for + cpp_testing: If True, set CORE.cpp_testing so AUTO_LOAD callables that + conditionally include testing-only dependencies work correctly Returns: Set of all components including dependencies and auto-loaded components @@ -646,6 +652,7 @@ def get_all_dependencies(component_names: set[str]) -> set[str]: # Reset CORE to ensure clean state CORE.reset() + CORE.cpp_testing = cpp_testing # Set up fake config path for component loading root = Path(__file__).parent.parent @@ -660,7 +667,11 @@ def get_all_dependencies(component_names: set[str]) -> set[str]: new_components: set[str] = set() for comp_name in all_components: - comp = get_component(comp_name) + if "." in comp_name: + domain, platform = comp_name.split(".", maxsplit=1) + comp = get_platform(domain, platform) + else: + comp = get_component(comp_name) if not comp: continue diff --git a/tests/components/README.md b/tests/components/README.md index 0901f2ef17..6da0dadd25 100644 --- a/tests/components/README.md +++ b/tests/components/README.md @@ -7,10 +7,23 @@ testing binaries that combine many components. By convention, this unique namespace is `esphome::component::testing` (where "component" is the component under test), for example: `esphome::uart::testing`. +### Platform components + +For components that expose to a platform component, create a folder under your component test folder with the platform component name, e.g. `binary_sensor` and +include the relevant `.cpp` and `.h` test files there. + +### Override component code generation for testing + +When generating code for testing, ESPHome won't invoke the component's `to_code` function, since most components do not +need to generate configuration code for testing. + +If you do need to generate code to for example configure compilation flags or add libraries, +add the component name to the `CPP_TESTING_CODEGEN_COMPONENTS` allowlist in `script/cpp_unit_test.py`. ## Running component unit tests (from the repository root) + ```bash ./script/cpp_unit_test.py component1 component2 ... ``` diff --git a/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp b/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp new file mode 100644 index 0000000000..36af087d2c --- /dev/null +++ b/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp @@ -0,0 +1,77 @@ +#include "../common.h" + +namespace esphome::packet_transport::testing { + +TEST(PacketTransportBinarySensorTest, AddBinarySensor) { + TestablePacketTransport transport; + binary_sensor::BinarySensor bs; + transport.add_binary_sensor("motion", &bs); + ASSERT_EQ(transport.binary_sensors_.size(), 1u); + EXPECT_STREQ(transport.binary_sensors_[0].id, "motion"); + EXPECT_EQ(transport.binary_sensors_[0].sensor, &bs); +} + +TEST(PacketTransportBinarySensorTest, AddRemoteBinarySensor) { + TestablePacketTransport transport; + binary_sensor::BinarySensor bs; + transport.add_remote_binary_sensor("host1", "remote_motion", &bs); + EXPECT_TRUE(transport.providers_.contains("host1")); + EXPECT_EQ(transport.remote_binary_sensors_["host1"]["remote_motion"], &bs); +} + +TEST(PacketTransportBinarySensorTest, UnencryptedBinarySensorRoundTrip) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + binary_sensor::BinarySensor local_bs; + local_bs.state = true; + encoder.add_binary_sensor("motion", &local_bs); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + binary_sensor::BinarySensor remote_bs; + decoder.add_remote_binary_sensor("sender", "motion", &remote_bs); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_TRUE(remote_bs.state); +} + +TEST(PacketTransportBinarySensorTest, MultipleSensorsRoundTrip) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + + sensor::Sensor s1, s2; + s1.state = 10.0f; + s2.state = 20.0f; + encoder.add_sensor("s1", &s1); + encoder.add_sensor("s2", &s2); + + binary_sensor::BinarySensor bs1; + bs1.state = true; + encoder.add_binary_sensor("bs1", &bs1); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor rs1, rs2; + binary_sensor::BinarySensor rbs1; + rs1.state = -999.0f; + rs2.state = -999.0f; + decoder.add_remote_sensor("sender", "s1", &rs1); + decoder.add_remote_sensor("sender", "s2", &rs2); + decoder.add_remote_binary_sensor("sender", "bs1", &rbs1); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + + EXPECT_FLOAT_EQ(rs1.state, 10.0f); + EXPECT_FLOAT_EQ(rs2.state, 20.0f); + EXPECT_TRUE(rbs1.state); +} + +} // namespace esphome::packet_transport::testing diff --git a/tests/components/packet_transport/cpp_test.yaml b/tests/components/packet_transport/cpp_test.yaml deleted file mode 100644 index fa39df3c0a..0000000000 --- a/tests/components/packet_transport/cpp_test.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Extra component configuration required by C++ unit tests. -# Loaded by cpp_unit_test.py and merged into the test build config -# before validation, so that platform defines (USE_SENSOR, etc.) are generated. - -sensor: - - platform: template - id: test_cpp_sensor - -binary_sensor: - - platform: template - id: test_cpp_binary_sensor diff --git a/tests/components/packet_transport/packet_transport_test.cpp b/tests/components/packet_transport/packet_transport_test.cpp index d8f11ca607..59c0a88ed7 100644 --- a/tests/components/packet_transport/packet_transport_test.cpp +++ b/tests/components/packet_transport/packet_transport_test.cpp @@ -65,198 +65,6 @@ TEST(PacketTransportTest, SetProviderEncryption) { EXPECT_EQ(transport.providers_["host1"].encryption_key, key); } -// --- Sensor management (requires USE_SENSOR / USE_BINARY_SENSOR) --- - -#ifdef USE_SENSOR -TEST(PacketTransportTest, AddSensor) { - TestablePacketTransport transport; - sensor::Sensor s; - transport.add_sensor("temp", &s); - ASSERT_EQ(transport.sensors_.size(), 1u); - EXPECT_STREQ(transport.sensors_[0].id, "temp"); - EXPECT_EQ(transport.sensors_[0].sensor, &s); - EXPECT_TRUE(transport.sensors_[0].updated); -} - -TEST(PacketTransportTest, AddRemoteSensor) { - TestablePacketTransport transport; - sensor::Sensor s; - transport.add_remote_sensor("host1", "remote_temp", &s); - EXPECT_TRUE(transport.providers_.contains("host1")); - EXPECT_EQ(transport.remote_sensors_["host1"]["remote_temp"], &s); -} -#endif - -#ifdef USE_BINARY_SENSOR -TEST(PacketTransportTest, AddBinarySensor) { - TestablePacketTransport transport; - binary_sensor::BinarySensor bs; - transport.add_binary_sensor("motion", &bs); - ASSERT_EQ(transport.binary_sensors_.size(), 1u); - EXPECT_STREQ(transport.binary_sensors_[0].id, "motion"); - EXPECT_EQ(transport.binary_sensors_[0].sensor, &bs); -} - -TEST(PacketTransportTest, AddRemoteBinarySensor) { - TestablePacketTransport transport; - binary_sensor::BinarySensor bs; - transport.add_remote_binary_sensor("host1", "remote_motion", &bs); - EXPECT_TRUE(transport.providers_.contains("host1")); - EXPECT_EQ(transport.remote_binary_sensors_["host1"]["remote_motion"], &bs); -} -#endif - -// --- Unencrypted round-trip tests (require USE_SENSOR / USE_BINARY_SENSOR) --- - -#ifdef USE_SENSOR -TEST(PacketTransportTest, UnencryptedSensorRoundTrip) { - // Encoder - TestablePacketTransport encoder; - encoder.init_for_test("sender"); - sensor::Sensor local_sensor; - local_sensor.state = 42.5f; - encoder.add_sensor("temp", &local_sensor); - - encoder.send_data_(true); - ASSERT_EQ(encoder.sent_packets.size(), 1u); - - // Decoder - TestablePacketTransport decoder; - decoder.init_for_test("receiver"); - sensor::Sensor remote_sensor; - remote_sensor.state = -999.0f; // sentinel - decoder.add_remote_sensor("sender", "temp", &remote_sensor); - - auto &packet = encoder.sent_packets[0]; - decoder.process_({packet.data(), packet.size()}); - EXPECT_FLOAT_EQ(remote_sensor.state, 42.5f); -} -#endif - -#ifdef USE_BINARY_SENSOR -TEST(PacketTransportTest, UnencryptedBinarySensorRoundTrip) { - TestablePacketTransport encoder; - encoder.init_for_test("sender"); - binary_sensor::BinarySensor local_bs; - local_bs.state = true; - encoder.add_binary_sensor("motion", &local_bs); - - encoder.send_data_(true); - ASSERT_EQ(encoder.sent_packets.size(), 1u); - - TestablePacketTransport decoder; - decoder.init_for_test("receiver"); - binary_sensor::BinarySensor remote_bs; - decoder.add_remote_binary_sensor("sender", "motion", &remote_bs); - - auto &packet = encoder.sent_packets[0]; - decoder.process_({packet.data(), packet.size()}); - EXPECT_TRUE(remote_bs.state); -} -#endif - -#if defined(USE_SENSOR) && defined(USE_BINARY_SENSOR) -TEST(PacketTransportTest, MultipleSensorsRoundTrip) { - TestablePacketTransport encoder; - encoder.init_for_test("sender"); - - sensor::Sensor s1, s2; - s1.state = 10.0f; - s2.state = 20.0f; - encoder.add_sensor("s1", &s1); - encoder.add_sensor("s2", &s2); - - binary_sensor::BinarySensor bs1; - bs1.state = true; - encoder.add_binary_sensor("bs1", &bs1); - - encoder.send_data_(true); - ASSERT_EQ(encoder.sent_packets.size(), 1u); - - TestablePacketTransport decoder; - decoder.init_for_test("receiver"); - sensor::Sensor rs1, rs2; - binary_sensor::BinarySensor rbs1; - rs1.state = -999.0f; - rs2.state = -999.0f; - decoder.add_remote_sensor("sender", "s1", &rs1); - decoder.add_remote_sensor("sender", "s2", &rs2); - decoder.add_remote_binary_sensor("sender", "bs1", &rbs1); - - auto &packet = encoder.sent_packets[0]; - decoder.process_({packet.data(), packet.size()}); - - EXPECT_FLOAT_EQ(rs1.state, 10.0f); - EXPECT_FLOAT_EQ(rs2.state, 20.0f); - EXPECT_TRUE(rbs1.state); -} -#endif - -// --- Encrypted round-trip --- - -#ifdef USE_SENSOR -TEST(PacketTransportTest, EncryptedSensorRoundTrip) { - std::vector<uint8_t> key(32); - for (int i = 0; i < 32; i++) - key[i] = i; - - TestablePacketTransport encoder; - encoder.init_for_test("sender"); - encoder.set_encryption_key(key); - sensor::Sensor local_sensor; - local_sensor.state = 99.9f; - encoder.add_sensor("temp", &local_sensor); - - encoder.send_data_(true); - ASSERT_EQ(encoder.sent_packets.size(), 1u); - - TestablePacketTransport decoder; - decoder.init_for_test("receiver"); - sensor::Sensor remote_sensor; - remote_sensor.state = -999.0f; - decoder.add_remote_sensor("sender", "temp", &remote_sensor); - decoder.set_provider_encryption("sender", key); - - auto &packet = encoder.sent_packets[0]; - decoder.process_({packet.data(), packet.size()}); - EXPECT_FLOAT_EQ(remote_sensor.state, 99.9f); -} - -// --- Selective send --- - -TEST(PacketTransportTest, SendDataOnlyUpdated) { - TestablePacketTransport encoder; - encoder.init_for_test("sender"); - - sensor::Sensor s1, s2; - s1.state = 1.0f; - s2.state = 2.0f; - encoder.add_sensor("s1", &s1); - encoder.add_sensor("s2", &s2); - - // Mark s1 as not updated, only s2 as updated - encoder.sensors_[0].updated = false; - encoder.sensors_[1].updated = true; - - encoder.send_data_(false); - ASSERT_EQ(encoder.sent_packets.size(), 1u); - - TestablePacketTransport decoder; - decoder.init_for_test("receiver"); - sensor::Sensor rs1, rs2; - rs1.state = -999.0f; - rs2.state = -999.0f; - decoder.add_remote_sensor("sender", "s1", &rs1); - decoder.add_remote_sensor("sender", "s2", &rs2); - - auto &packet = encoder.sent_packets[0]; - decoder.process_({packet.data(), packet.size()}); - - EXPECT_FLOAT_EQ(rs1.state, -999.0f); // not updated, not sent - EXPECT_FLOAT_EQ(rs2.state, 2.0f); // updated, sent -} -#endif - // --- Ping key tests --- TEST(PacketTransportTest, PingKeyStoredWhenEncrypted) { @@ -319,73 +127,6 @@ TEST(PacketTransportTest, PingKeyMaxLimit) { EXPECT_FALSE(transport.ping_keys_.contains("host4")); } -#ifdef USE_SENSOR -TEST(PacketTransportTest, PingKeyIncludedInTransmittedPacket) { - std::vector<uint8_t> key(32, 0xBB); - - // Responder: encrypted, owns a sensor - TestablePacketTransport responder; - responder.init_for_test("responder"); - responder.set_encryption_key(key); - sensor::Sensor local_sensor; - local_sensor.state = 77.7f; - responder.add_sensor("temp", &local_sensor); - - // Requester sends a MAGIC_PING that the responder processes - auto ping = build_ping_packet("requester", 0xDEADBEEF); - responder.process_({ping.data(), ping.size()}); - ASSERT_EQ(responder.ping_keys_.size(), 1u); - - // Responder sends sensor data — ping key should be embedded - responder.send_data_(true); - ASSERT_EQ(responder.sent_packets.size(), 1u); - - // Requester: encrypted provider, ping-pong enabled, expects key 0xDEADBEEF - TestablePacketTransport requester; - requester.init_for_test("requester"); - requester.set_ping_pong_enable(true); - requester.ping_key_ = 0xDEADBEEF; - sensor::Sensor remote_sensor; - remote_sensor.state = -999.0f; - requester.add_remote_sensor("responder", "temp", &remote_sensor); - requester.set_provider_encryption("responder", key); - - // The requester decrypts the packet and finds its ping key echoed back, - // which gates the sensor data — if the key is missing, data is blocked. - auto &packet = responder.sent_packets[0]; - requester.process_({packet.data(), packet.size()}); - EXPECT_FLOAT_EQ(remote_sensor.state, 77.7f); -} - -TEST(PacketTransportTest, MissingPingKeyBlocksSensorData) { - std::vector<uint8_t> key(32, 0xBB); - - // Responder sends data WITHOUT receiving any MAGIC_PING first — no ping keys - TestablePacketTransport responder; - responder.init_for_test("responder"); - responder.set_encryption_key(key); - sensor::Sensor local_sensor; - local_sensor.state = 77.7f; - responder.add_sensor("temp", &local_sensor); - responder.send_data_(true); - ASSERT_EQ(responder.sent_packets.size(), 1u); - - // Requester with ping-pong enabled expects a key that isn't in the packet - TestablePacketTransport requester; - requester.init_for_test("requester"); - requester.set_ping_pong_enable(true); - requester.ping_key_ = 0xDEADBEEF; - sensor::Sensor remote_sensor; - remote_sensor.state = -999.0f; - requester.add_remote_sensor("responder", "temp", &remote_sensor); - requester.set_provider_encryption("responder", key); - - auto &packet = responder.sent_packets[0]; - requester.process_({packet.data(), packet.size()}); - EXPECT_FLOAT_EQ(remote_sensor.state, -999.0f); // blocked — ping key not found -} -#endif - // --- Process error handling --- TEST(PacketTransportTest, ProcessShortBuffer) { diff --git a/tests/components/packet_transport/sensor/sensor_test.cpp b/tests/components/packet_transport/sensor/sensor_test.cpp new file mode 100644 index 0000000000..2f681aee58 --- /dev/null +++ b/tests/components/packet_transport/sensor/sensor_test.cpp @@ -0,0 +1,170 @@ +#include "../common.h" + +namespace esphome::packet_transport::testing { + +TEST(PacketTransportSensorTest, AddSensor) { + TestablePacketTransport transport; + sensor::Sensor s; + transport.add_sensor("temp", &s); + ASSERT_EQ(transport.sensors_.size(), 1u); + EXPECT_STREQ(transport.sensors_[0].id, "temp"); + EXPECT_EQ(transport.sensors_[0].sensor, &s); + EXPECT_TRUE(transport.sensors_[0].updated); +} + +TEST(PacketTransportSensorTest, AddRemoteSensor) { + TestablePacketTransport transport; + sensor::Sensor s; + transport.add_remote_sensor("host1", "remote_temp", &s); + EXPECT_TRUE(transport.providers_.contains("host1")); + EXPECT_EQ(transport.remote_sensors_["host1"]["remote_temp"], &s); +} + +TEST(PacketTransportSensorTest, UnencryptedSensorRoundTrip) { + // Encoder + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + sensor::Sensor local_sensor; + local_sensor.state = 42.5f; + encoder.add_sensor("temp", &local_sensor); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + // Decoder + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; // sentinel + decoder.add_remote_sensor("sender", "temp", &remote_sensor); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 42.5f); +} + +TEST(PacketTransportSensorTest, EncryptedSensorRoundTrip) { + std::vector<uint8_t> key(32); + for (int i = 0; i < 32; i++) + key[i] = i; + + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + encoder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 99.9f; + encoder.add_sensor("temp", &local_sensor); + + encoder.send_data_(true); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + decoder.add_remote_sensor("sender", "temp", &remote_sensor); + decoder.set_provider_encryption("sender", key); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 99.9f); +} + +TEST(PacketTransportSensorTest, SendDataOnlyUpdated) { + TestablePacketTransport encoder; + encoder.init_for_test("sender"); + + sensor::Sensor s1, s2; + s1.state = 1.0f; + s2.state = 2.0f; + encoder.add_sensor("s1", &s1); + encoder.add_sensor("s2", &s2); + + // Mark s1 as not updated, only s2 as updated + encoder.sensors_[0].updated = false; + encoder.sensors_[1].updated = true; + + encoder.send_data_(false); + ASSERT_EQ(encoder.sent_packets.size(), 1u); + + TestablePacketTransport decoder; + decoder.init_for_test("receiver"); + sensor::Sensor rs1, rs2; + rs1.state = -999.0f; + rs2.state = -999.0f; + decoder.add_remote_sensor("sender", "s1", &rs1); + decoder.add_remote_sensor("sender", "s2", &rs2); + + auto &packet = encoder.sent_packets[0]; + decoder.process_({packet.data(), packet.size()}); + + EXPECT_FLOAT_EQ(rs1.state, -999.0f); // not updated, not sent + EXPECT_FLOAT_EQ(rs2.state, 2.0f); // updated, sent +} + +TEST(PacketTransportSensorTest, PingKeyIncludedInTransmittedPacket) { + std::vector<uint8_t> key(32, 0xBB); + + // Responder: encrypted, owns a sensor + TestablePacketTransport responder; + responder.init_for_test("responder"); + responder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 77.7f; + responder.add_sensor("temp", &local_sensor); + + // Requester sends a MAGIC_PING that the responder processes + auto ping = build_ping_packet("requester", 0xDEADBEEF); + responder.process_({ping.data(), ping.size()}); + ASSERT_EQ(responder.ping_keys_.size(), 1u); + + // Responder sends sensor data — ping key should be embedded + responder.send_data_(true); + ASSERT_EQ(responder.sent_packets.size(), 1u); + + // Requester: encrypted provider, ping-pong enabled, expects key 0xDEADBEEF + TestablePacketTransport requester; + requester.init_for_test("requester"); + requester.set_ping_pong_enable(true); + requester.ping_key_ = 0xDEADBEEF; + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + requester.add_remote_sensor("responder", "temp", &remote_sensor); + requester.set_provider_encryption("responder", key); + + // The requester decrypts the packet and finds its ping key echoed back, + // which gates the sensor data — if the key is missing, data is blocked. + auto &packet = responder.sent_packets[0]; + requester.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, 77.7f); +} + +TEST(PacketTransportSensorTest, MissingPingKeyBlocksSensorData) { + std::vector<uint8_t> key(32, 0xBB); + + // Responder sends data WITHOUT receiving any MAGIC_PING first — no ping keys + TestablePacketTransport responder; + responder.init_for_test("responder"); + responder.set_encryption_key(key); + sensor::Sensor local_sensor; + local_sensor.state = 77.7f; + responder.add_sensor("temp", &local_sensor); + responder.send_data_(true); + ASSERT_EQ(responder.sent_packets.size(), 1u); + + // Requester with ping-pong enabled expects a key that isn't in the packet + TestablePacketTransport requester; + requester.init_for_test("requester"); + requester.set_ping_pong_enable(true); + requester.ping_key_ = 0xDEADBEEF; + sensor::Sensor remote_sensor; + remote_sensor.state = -999.0f; + requester.add_remote_sensor("responder", "temp", &remote_sensor); + requester.set_provider_encryption("responder", key); + + auto &packet = responder.sent_packets[0]; + requester.process_({packet.data(), packet.size()}); + EXPECT_FLOAT_EQ(remote_sensor.state, -999.0f); // blocked — ping key not found +} + +} // namespace esphome::packet_transport::testing diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index 2953a9fd42..781054eb3b 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -1027,6 +1027,73 @@ def test_get_all_dependencies_empty_set() -> None: assert result == set() +def test_get_all_dependencies_platform_component() -> None: + """Platform components (domain.component) are looked up via get_platform, + not get_component.""" + platform_comp = Mock() + platform_comp.dependencies = [] + platform_comp.auto_load = [] + + with ( + patch("esphome.loader.get_component") as mock_get_component, + patch("helpers.get_platform") as mock_get_platform, + ): + mock_get_platform.return_value = platform_comp + mock_get_component.return_value = None + + result = helpers.get_all_dependencies({"sensor.bthome"}) + + mock_get_platform.assert_called_once_with("sensor", "bthome") + mock_get_component.assert_not_called() + assert result == {"sensor.bthome"} + + +def test_get_all_dependencies_platform_component_with_dependencies() -> None: + """Dependencies of a platform component are resolved transitively.""" + platform_comp = Mock() + platform_comp.dependencies = ["sensor"] + platform_comp.auto_load = [] + + sensor_comp = Mock() + sensor_comp.dependencies = [] + sensor_comp.auto_load = [] + + with ( + patch("esphome.loader.get_component") as mock_get_component, + patch("helpers.get_platform") as mock_get_platform, + ): + mock_get_platform.return_value = platform_comp + mock_get_component.side_effect = lambda name: ( + sensor_comp if name == "sensor" else None + ) + + result = helpers.get_all_dependencies({"sensor.bthome"}) + + assert result == {"sensor.bthome", "sensor"} + + +def test_get_all_dependencies_cpp_testing_flag() -> None: + """cpp_testing=True propagates to CORE.cpp_testing during resolution.""" + from esphome.core import CORE + + with ( + patch("esphome.loader.get_component") as mock_get_component, + patch("esphome.loader.get_platform"), + ): + observed: list[bool] = [] + + def capturing_get_component(name: str): + observed.append(CORE.cpp_testing) + + mock_get_component.side_effect = capturing_get_component + + helpers.get_all_dependencies({"some_comp"}, cpp_testing=True) + + assert observed and all(observed), ( + "CORE.cpp_testing should be True during resolution" + ) + + def test_get_components_from_integration_fixtures() -> None: """Test extraction of components from fixture YAML files.""" yaml_content = { diff --git a/tests/unit_tests/test_core.py b/tests/unit_tests/test_core.py index 174b3fec85..22be59653a 100644 --- a/tests/unit_tests/test_core.py +++ b/tests/unit_tests/test_core.py @@ -841,6 +841,18 @@ class TestEsphomeCore: assert "WiFi" in target.platformio_libraries + def test_testing_ensure_platform_registered__sets_count(self, target): + """Test testing_ensure_platform_registered sets count to 1 for new platform.""" + assert target.platform_counts["sensor"] == 0 + target.testing_ensure_platform_registered("sensor") + assert target.platform_counts["sensor"] == 1 + + def test_testing_ensure_platform_registered__does_not_overwrite(self, target): + """Test testing_ensure_platform_registered preserves existing count.""" + target.platform_counts["sensor"] = 3 + target.testing_ensure_platform_registered("sensor") + assert target.platform_counts["sensor"] == 3 + def test_add_library__extracts_short_name_from_path(self, target): """Test add_library extracts short name from library paths like owner/lib.""" target.data[const.KEY_CORE] = { From 4b50d14496896181d261a3c8a9dc5b4d4a062bda Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 9 Mar 2026 21:10:03 -1000 Subject: [PATCH 1256/2030] [serial_proxy] Reduce loop() overhead by disabling when idle and splitting read path (#14673) --- .../components/serial_proxy/serial_proxy.cpp | 29 ++++++++++++++----- .../components/serial_proxy/serial_proxy.h | 5 ++++ 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/esphome/components/serial_proxy/serial_proxy.cpp b/esphome/components/serial_proxy/serial_proxy.cpp index 340f9b0cb8..00d822b75c 100644 --- a/esphome/components/serial_proxy/serial_proxy.cpp +++ b/esphome/components/serial_proxy/serial_proxy.cpp @@ -28,25 +28,38 @@ void SerialProxy::setup() { // instance_index_ is fixed at registration time; pre-set it so loop() only needs to update data this->outgoing_msg_.instance = this->instance_index_; #endif + // No subscriber at startup; disable loop until a client subscribes + this->disable_loop(); } void SerialProxy::loop() { #ifdef USE_API - // Detect subscriber disconnect - if (this->api_connection_ != nullptr && (this->api_connection_->is_marked_for_removal() || - !this->api_connection_->is_connection_setup() || !api_is_connected())) { - ESP_LOGW(TAG, "Subscriber disconnected"); - this->api_connection_ = nullptr; + // Safety check — loop should only run when subscribed, but guard against races + if (this->api_connection_ == nullptr) [[unlikely]] { + this->disable_loop(); + return; } - if (this->api_connection_ == nullptr) + // Detect subscriber disconnect + if (this->api_connection_->is_marked_for_removal() || !this->api_connection_->is_connection_setup() || + !api_is_connected()) { + ESP_LOGW(TAG, "Subscriber disconnected"); + this->api_connection_ = nullptr; + this->disable_loop(); return; + } // Read available data from UART and forward to subscribed client size_t available = this->available(); if (available == 0) return; + this->read_and_send_(available); +#endif +} + +#ifdef USE_API +void __attribute__((noinline)) SerialProxy::read_and_send_(size_t available) { // Read in chunks up to SERIAL_PROXY_MAX_READ_SIZE uint8_t buffer[SERIAL_PROXY_MAX_READ_SIZE]; size_t to_read = std::min(available, sizeof(buffer)); @@ -56,8 +69,8 @@ void SerialProxy::loop() { this->outgoing_msg_.set_data(buffer, to_read); this->api_connection_->send_serial_proxy_data(this->outgoing_msg_); -#endif } +#endif void SerialProxy::dump_config() { ESP_LOGCONFIG(TAG, @@ -166,6 +179,7 @@ void SerialProxy::serial_proxy_request(api::APIConnection *api_connection, api:: return; } this->api_connection_ = api_connection; + this->enable_loop(); ESP_LOGV(TAG, "API connection subscribed to serial proxy [%u]", this->instance_index_); break; case api::enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: @@ -174,6 +188,7 @@ void SerialProxy::serial_proxy_request(api::APIConnection *api_connection, api:: return; } this->api_connection_ = nullptr; + this->disable_loop(); ESP_LOGV(TAG, "API connection unsubscribed from serial proxy [%u]", this->instance_index_); break; default: diff --git a/esphome/components/serial_proxy/serial_proxy.h b/esphome/components/serial_proxy/serial_proxy.h index 62f942b19d..5adfa4fe53 100644 --- a/esphome/components/serial_proxy/serial_proxy.h +++ b/esphome/components/serial_proxy/serial_proxy.h @@ -101,6 +101,11 @@ class SerialProxy : public uart::UARTDevice, public Component { void set_dtr_pin(GPIOPin *pin) { this->dtr_pin_ = pin; } protected: +#ifdef USE_API + /// Read from UART and send to API client (slow path with 256-byte stack buffer) + void read_and_send_(size_t available); +#endif + /// Instance index for identifying this proxy in API messages uint32_t instance_index_{0}; From fba21e6dd4bd321d4b0ee3b31869e81fee75aab5 Mon Sep 17 00:00:00 2001 From: Anunay Kulshrestha <anunay@kul.sh> Date: Tue, 10 Mar 2026 20:14:19 +0530 Subject: [PATCH 1257/2030] [bl0940] Fix reset_calibration() declaration missing from header (#14676) Co-authored-by: Claude <noreply@anthropic.com> --- esphome/components/bl0940/bl0940.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/bl0940/bl0940.h b/esphome/components/bl0940/bl0940.h index 93d54003f5..e0ca748a22 100644 --- a/esphome/components/bl0940/bl0940.h +++ b/esphome/components/bl0940/bl0940.h @@ -69,10 +69,8 @@ class BL0940 : public PollingComponent, public uart::UARTDevice { void set_energy_calibration_number(number::Number *num) { this->energy_calibration_number_ = num; } #endif -#ifdef USE_BUTTON - // Resets all calibration values to defaults (can be triggered by a button) + // Resets all calibration values to defaults void reset_calibration(); -#endif // Core component methods void loop() override; From 06a127f64b49c7306815100cc667af8c9842c463 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:52:48 +0100 Subject: [PATCH 1258/2030] [core] ESP-IDF compilation fixes (#14541) --- esphome/build_gen/espidf.py | 6 ++-- esphome/espidf_api.py | 61 ++++++++++++++++++++++++++++++++----- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/esphome/build_gen/espidf.py b/esphome/build_gen/espidf.py index f45efb82c1..9df9b1069c 100644 --- a/esphome/build_gen/espidf.py +++ b/esphome/build_gen/espidf.py @@ -72,7 +72,7 @@ def get_component_cmakelists(minimal: bool = False) -> str: # Extract compile definitions from build flags (-DXXX -> XXX) compile_defs = [flag[2:] for flag in CORE.build_flags if flag.startswith("-D")] - compile_defs_str = "\n ".join(compile_defs) if compile_defs else "" + compile_defs_str = "\n ".join(sorted(compile_defs)) if compile_defs else "" # Extract compile options (-W flags, excluding linker flags) compile_opts = [ @@ -80,11 +80,11 @@ def get_component_cmakelists(minimal: bool = False) -> str: for flag in CORE.build_flags if flag.startswith("-W") and not flag.startswith("-Wl,") ] - compile_opts_str = "\n ".join(compile_opts) if compile_opts else "" + compile_opts_str = "\n ".join(sorted(compile_opts)) if compile_opts else "" # Extract linker options (-Wl, flags) link_opts = [flag for flag in CORE.build_flags if flag.startswith("-Wl,")] - link_opts_str = "\n ".join(link_opts) if link_opts else "" + link_opts_str = "\n ".join(sorted(link_opts)) if link_opts else "" return f"""\ # Auto-generated by ESPHome diff --git a/esphome/espidf_api.py b/esphome/espidf_api.py index 9e9c57bfbd..9ebcc48513 100644 --- a/esphome/espidf_api.py +++ b/esphome/espidf_api.py @@ -8,7 +8,6 @@ import shutil import subprocess from esphome.components.esp32.const import KEY_ESP32, KEY_FLASH_SIZE -from esphome.const import CONF_COMPILE_PROCESS_LIMIT, CONF_ESPHOME from esphome.core import CORE, EsphomeError _LOGGER = logging.getLogger(__name__) @@ -102,6 +101,55 @@ def run_reconfigure() -> int: return run_idf_py("reconfigure") +def has_outdated_files(): + """Check if the build configuration is stale. + + Returns True if required build files are missing or if configuration inputs + are newer than the generated CMake/Ninja build artifacts. + """ + cmakecache_txt_path = CORE.relative_build_path("build/CMakeCache.txt") + + cmakelists_txt_build_path = CORE.relative_build_path("CMakeLists.txt") + cmakelists_txt_src_path = CORE.relative_src_path("CMakeLists.txt") + build_config_path = CORE.relative_build_path("build/config") + sdkconfig_internal_path = CORE.relative_build_path( + f"sdkconfig.{CORE.name}.esphomeinternal" + ) + dependency_lock_path = CORE.relative_build_path("dependencies.lock") + build_ninja_path = CORE.relative_build_path("build/build.ninja") + + if not os.path.isdir(build_config_path) or not os.listdir(build_config_path): + return True + if not os.path.isfile(cmakecache_txt_path): + return True + if not os.path.isfile(build_ninja_path): + return True + if os.path.isfile(dependency_lock_path) and os.path.getmtime( + dependency_lock_path + ) > os.path.getmtime(build_ninja_path): + return True + + cmakecache_txt_mtime = os.path.getmtime(cmakecache_txt_path) + return any( + os.path.getmtime(f) > cmakecache_txt_mtime + for f in [ + _get_idf_path(), + cmakelists_txt_build_path, + cmakelists_txt_src_path, + sdkconfig_internal_path, + build_config_path, + ] + if f and os.path.exists(f) + ) + + +def need_reconfigure() -> bool: + from esphome.build_gen.espidf import has_discovered_components + + # We need to reconfigure either if the files are outdated or if there is no component discovered + return has_outdated_files() or not has_discovered_components() + + def run_compile(config, verbose: bool) -> int: """Compile the ESP-IDF project. @@ -110,10 +158,10 @@ def run_compile(config, verbose: bool) -> int: 2. Regenerate CMakeLists.txt with discovered components 3. Run full build """ - from esphome.build_gen.espidf import has_discovered_components, write_project + from esphome.build_gen.espidf import write_project # Check if we need to do discovery phase - if not has_discovered_components(): + if need_reconfigure(): _LOGGER.info("Discovering available ESP-IDF components...") write_project(minimal=True) rc = run_reconfigure() @@ -124,15 +172,12 @@ def run_compile(config, verbose: bool) -> int: write_project(minimal=False) # Build - args = ["build"] + args = [] if verbose: args.append("-v") - # Add parallel job limit if configured - if CONF_COMPILE_PROCESS_LIMIT in config.get(CONF_ESPHOME, {}): - limit = config[CONF_ESPHOME][CONF_COMPILE_PROCESS_LIMIT] - args.extend(["-j", str(limit)]) + args.append("build") # Set the sdkconfig file sdkconfig_path = CORE.relative_build_path(f"sdkconfig.{CORE.name}") From 2c7ef4f758522ac324a5983dfc89f963fa22af70 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:10:33 -1000 Subject: [PATCH 1259/2030] [rp2040] Use picotool for BOOTSEL upload and improve upload UX (#14483) --- esphome/__main__.py | 211 ++++++++++++++++- esphome/espota2.py | 26 +-- esphome/helpers.py | 27 +++ esphome/util.py | 70 ++++++ tests/unit_tests/test_main.py | 420 ++++++++++++++++++++++++++++++++++ tests/unit_tests/test_util.py | 132 +++++++++++ 6 files changed, 859 insertions(+), 27 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 0164e2eeb3..f33e7f4b42 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -9,6 +9,8 @@ import logging import os from pathlib import Path import re +import shutil +import subprocess import sys import time from typing import Protocol @@ -44,7 +46,9 @@ from esphome.const import ( CONF_SUBSTITUTIONS, CONF_TOPIC, ENV_NOGITIGNORE, + KEY_CORE, KEY_NATIVE_IDF, + KEY_TARGET_PLATFORM, PLATFORM_ESP32, PLATFORM_ESP8266, PLATFORM_RP2040, @@ -56,7 +60,11 @@ from esphome.helpers import get_bool_env, indent, is_ip_address from esphome.log import AnsiFore, color, setup_log from esphome.types import ConfigType from esphome.util import ( + PICOTOOL_PACKAGE, + detect_rp2040_bootsel, + get_picotool_path, get_serial_ports, + is_picotool_usb_permission_error, list_yaml_files, run_external_command, run_external_process, @@ -68,6 +76,21 @@ _LOGGER = logging.getLogger(__name__) # Maximum buffer size for serial log reading to prevent unbounded memory growth SERIAL_BUFFER_MAX_SIZE = 65536 +_RP2040_BOOTSEL_INSTRUCTIONS = ( + "To enter BOOTSEL mode:\n" + " 1. Unplug the device\n" + " 2. Hold the BOOT/BOOTSEL button\n" + " 3. Plug in the USB cable while holding the button\n" + " 4. Release the button - the device should appear as a USB drive (RPI-RP2)\n" + "Then run the upload command again." +) + +_RP2040_UDEV_HINT = ( + "You may need to add a udev rule for RP2040 devices. " + "See: https://github.com/raspberrypi/picotool" + "/blob/master/udev/60-picotool.rules" +) + # Special non-component keys that appear in configs _NON_COMPONENT_KEYS = frozenset( { @@ -163,6 +186,7 @@ class PortType(StrEnum): NETWORK = "NETWORK" MQTT = "MQTT" MQTTIP = "MQTTIP" + BOOTSEL = "BOOTSEL" # Magic MQTT port types that require special handling @@ -241,6 +265,19 @@ def choose_upload_log_host( (f"{port.path} ({port.description})", port.path) for port in get_serial_ports() ] + # Add RP2040 BOOTSEL device option when uploading + bootsel_permission_error = False + if ( + purpose == Purpose.UPLOADING + and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040 + and (picotool := _find_picotool()) is not None + ): + bootsel = detect_rp2040_bootsel(picotool) + if bootsel.device_count > 0: + options.append(("RP2040 BOOTSEL (via picotool)", "BOOTSEL")) + elif bootsel.permission_error: + bootsel_permission_error = True + if purpose == Purpose.LOGGING: if has_mqtt_logging(): mqtt_config = CORE.config[CONF_MQTT] @@ -258,6 +295,25 @@ def choose_upload_log_host( if has_mqtt_ip_lookup(): options.append(("Over The Air (MQTT IP lookup)", "MQTTIP")) + # Show helpful BOOTSEL instructions for RP2040 when no BOOTSEL device is found + if ( + purpose == Purpose.UPLOADING + and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040 + and not any(get_port_type(opt[1]) == PortType.BOOTSEL for opt in options) + ): + if bootsel_permission_error: + _LOGGER.warning( + "An RP2040 device in BOOTSEL mode was detected but could " + "not be accessed due to USB permissions." + ) + if sys.platform.startswith("linux"): + _LOGGER.warning(_RP2040_UDEV_HINT) + if not options: + raise EsphomeError( + f"No RP2040 device found. {_RP2040_BOOTSEL_INSTRUCTIONS}" + ) + _LOGGER.info("Tip: %s", _RP2040_BOOTSEL_INSTRUCTIONS) + if check_default is not None and check_default in [opt[1] for opt in options]: return [check_default] return [choose_prompt(options, purpose=purpose)] @@ -404,10 +460,13 @@ def get_port_type(port: str) -> PortType: Returns: PortType.SERIAL for serial ports (/dev/ttyUSB0, COM1, etc.) + PortType.BOOTSEL for RP2040 BOOTSEL upload via picotool PortType.MQTT for MQTT logging PortType.MQTTIP for MQTT IP lookup PortType.NETWORK for IP addresses, hostnames, or mDNS names """ + if port == "BOOTSEL": + return PortType.BOOTSEL if port.startswith("/") or port.startswith("COM"): return PortType.SERIAL if port == "MQTT": @@ -695,15 +754,138 @@ def upload_using_esptool( return run_esptool(115200) -def upload_using_platformio(config: ConfigType, port: str): +def upload_using_platformio(config: ConfigType, port: str) -> int: from esphome import platformio_api + # RP2040 platform-raspberrypi build recipe expects firmware.bin.signed for + # the upload target, but 'nobuild' skips the build phase that creates it. + # Create it here so the upload doesn't fail. + if CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040: + idedata = platformio_api.get_idedata(config) + build_dir = Path(idedata.firmware_elf_path).parent + firmware_bin = build_dir / "firmware.bin" + signed_bin = build_dir / "firmware.bin.signed" + if firmware_bin.is_file() and not signed_bin.is_file(): + shutil.copy2(firmware_bin, signed_bin) + upload_args = ["-t", "upload", "-t", "nobuild"] if port is not None: upload_args += ["--upload-port", port] return platformio_api.run_platformio_cli_run(config, CORE.verbose, *upload_args) +def _find_picotool() -> Path | None: + """Find the picotool binary from PlatformIO packages.""" + from esphome import platformio_api + + try: + idedata = platformio_api.get_idedata(CORE.config) + except Exception: # noqa: BLE001 # pylint: disable=broad-except + return None + return get_picotool_path(idedata.cc_path) + + +def upload_using_picotool(config: ConfigType) -> int: + """Upload firmware to RP2040 in BOOTSEL mode using picotool. + + Uses picotool to load the ELF firmware directly via USB, avoiding + the mass storage copy approach that causes "disk not ejected properly" + warnings on macOS. + """ + from esphome import platformio_api + + idedata = platformio_api.get_idedata(config) + firmware_elf = Path(idedata.firmware_elf_path) + + if not firmware_elf.is_file(): + _LOGGER.error( + "Firmware ELF file not found at %s. " + "Make sure the project has been compiled first.", + firmware_elf, + ) + return 1 + + picotool = get_picotool_path(idedata.cc_path) + if picotool is None: + _LOGGER.error( + "picotool not found. Ensure the RP2040 PlatformIO platform " + "is installed (%s).", + PICOTOOL_PACKAGE, + ) + return 1 + + _LOGGER.info("Uploading firmware to RP2040 via picotool...") + try: + # Don't capture stdout — let picotool write directly to the terminal + # so progress bars display in real-time with \r updates. + # Capture stderr only so we can detect permission errors. + result = subprocess.run( + [str(picotool), "load", "-v", "-x", str(firmware_elf)], + stderr=subprocess.PIPE, + timeout=60, + check=False, + ) + except subprocess.TimeoutExpired: + _LOGGER.error("picotool upload timed out after 60 seconds.") + return 1 + except OSError as err: + _LOGGER.error("Failed to run picotool: %s", err) + return 1 + + if result.returncode != 0: + stderr = result.stderr.decode("utf-8", errors="replace").strip() + if stderr: + for line in stderr.splitlines(): + safe_print(line) + if is_picotool_usb_permission_error(stderr): + msg = "Permission denied accessing USB device." + if sys.platform.startswith("linux"): + msg += f" {_RP2040_UDEV_HINT}" + _LOGGER.error(msg) + else: + _LOGGER.error("picotool upload failed (exit code %d).", result.returncode) + return 1 + + return 0 + + +def _wait_for_serial_port( + port: str | None = None, + timeout: float = 30.0, + known_ports: set[str] | None = None, +) -> None: + """Wait for a serial port to appear, e.g. after a device reboot. + + USB-CDC devices disappear briefly after flashing while the device + reboots and re-enumerates on the USB bus. + + If port is given, wait for that specific path. If known_ports is + given, wait for a new port that wasn't in the set. Otherwise wait + for any serial port to appear. + """ + + def _port_found() -> bool: + ports = get_serial_ports() + if port is not None: + return any(p.path == port for p in ports) + if known_ports is not None: + return any(p.path not in known_ports for p in ports) + return bool(ports) + + if _port_found(): + return + if port is not None: + _LOGGER.info("Waiting for %s to come online...", port) + else: + _LOGGER.info("Waiting for device to reboot...") + start = time.monotonic() + while time.monotonic() - start < timeout: + time.sleep(0.05) + if _port_found(): + time.sleep(0.05) + return + + def check_permissions(port: str): if os.name == "posix" and get_port_type(port) == PortType.SERIAL: # Check if we can open selected serial port @@ -733,7 +915,15 @@ def upload_program( except AttributeError: pass - if get_port_type(host) == PortType.SERIAL: + port_type = get_port_type(host) + + if port_type == PortType.BOOTSEL: + exit_code = upload_using_picotool(config) + # Return None for device - BOOTSEL can't be used for logging, + # so command_run will show the interactive chooser for log source + return exit_code, None + + if port_type == PortType.SERIAL: check_permissions(host) exit_code = 1 @@ -787,6 +977,7 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int port_type = get_port_type(port) if port_type == PortType.SERIAL: + _wait_for_serial_port(port) check_permissions(port) return run_miniterm(config, port, args) @@ -925,6 +1116,9 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None: purpose=Purpose.UPLOADING, ) + # Snapshot current serial ports before upload so we can detect new ones + pre_upload_ports = {p.path for p in get_serial_ports()} + exit_code, successful_device = upload_program(config, args, devices) if exit_code == 0: _LOGGER.info("Successfully uploaded program.") @@ -935,6 +1129,19 @@ def command_run(args: ArgsProtocol, config: ConfigType) -> int | None: if args.no_logs: return 0 + # After BOOTSEL upload, wait for a new serial port to appear + # so it shows up in the log chooser + if ( + successful_device is None + and CORE.data.get(KEY_CORE, {}).get(KEY_TARGET_PLATFORM) == PLATFORM_RP2040 + ): + _wait_for_serial_port(known_ports=pre_upload_ports) + # If exactly one new serial port appeared, use it directly + serial_ports = get_serial_ports() + new_ports = [p for p in serial_ports if p.path not in pre_upload_ports] + if len(new_ports) == 1: + successful_device = new_ports[0].path + # For logs, prefer the device we successfully uploaded to devices = choose_upload_log_host( default=successful_device, diff --git a/esphome/espota2.py b/esphome/espota2.py index c342eb4463..c412bb51ff 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -13,7 +13,7 @@ import time from typing import Any from esphome.core import EsphomeError -from esphome.helpers import resolve_ip_address +from esphome.helpers import ProgressBar, resolve_ip_address RESPONSE_OK = 0x00 RESPONSE_REQUEST_AUTH = 0x01 @@ -63,30 +63,6 @@ _AUTH_METHODS: dict[int, tuple[Callable[..., Any], int, str]] = { } -class ProgressBar: - def __init__(self): - self.last_progress = None - - def update(self, progress): - bar_length = 60 - status = "" - if progress >= 1: - progress = 1 - status = "Done...\r\n" - new_progress = int(progress * 100) - if new_progress == self.last_progress: - return - self.last_progress = new_progress - block = int(round(bar_length * progress)) - text = f"\rUploading: [{'=' * block + ' ' * (bar_length - block)}] {new_progress}% {status}" - sys.stderr.write(text) - sys.stderr.flush() - - def done(self): - sys.stderr.write("\n") - sys.stderr.flush() - - class OTAError(EsphomeError): pass diff --git a/esphome/helpers.py b/esphome/helpers.py index 145ebd4096..f41bec357d 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -9,6 +9,7 @@ import platform import re import shutil import stat +import sys import tempfile from typing import TYPE_CHECKING from urllib.parse import urlparse @@ -585,6 +586,32 @@ def sanitize(value): return _DISALLOWED_CHARS.sub("_", value) +class ProgressBar: + """A simple terminal progress bar for upload operations.""" + + def __init__(self) -> None: + self.last_progress: int | None = None + + def update(self, progress: float) -> None: + bar_length = 60 + status = "" + if progress >= 1: + progress = 1 + status = "Done...\r\n" + new_progress = int(progress * 100) + if new_progress == self.last_progress: + return + self.last_progress = new_progress + block = int(round(bar_length * progress)) + text = f"\rUploading: [{'=' * block + ' ' * (bar_length - block)}] {new_progress}% {status}" + sys.stderr.write(text) + sys.stderr.flush() + + def done(self) -> None: + sys.stderr.write("\n") + sys.stderr.flush() + + def docs_url(path: str) -> str: """Return the URL to the documentation for a given path.""" # Local import to avoid circular import diff --git a/esphome/util.py b/esphome/util.py index 686aa74306..6a21b4f627 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -1,5 +1,6 @@ import collections from collections.abc import Callable +from dataclasses import dataclass import io import logging from pathlib import Path @@ -355,6 +356,75 @@ def get_serial_ports() -> list[SerialPort]: return result +PICOTOOL_PACKAGE = "tool-picotool-rp2040-earlephilhower" + + +def get_picotool_path(cc_path: str) -> Path | None: + """Derive the picotool binary path from the PlatformIO toolchain cc_path. + + The cc_path from IDEData points to the toolchain package, e.g.: + ~/.platformio/packages/toolchain-rp2040-earlephilhower/bin/arm-none-eabi-gcc + Picotool is in a sibling package: + ~/.platformio/packages/tool-picotool-rp2040-earlephilhower/picotool + """ + cc = Path(cc_path) + # Go from .../packages/toolchain-.../bin/gcc up to .../packages/ + packages_dir = cc.parent.parent.parent + binary_name = "picotool.exe" if sys.platform == "win32" else "picotool" + picotool = packages_dir / PICOTOOL_PACKAGE / binary_name + if picotool.is_file(): + return picotool + return None + + +def is_picotool_usb_permission_error(output: str | bytes) -> bool: + """Check if picotool output indicates a USB permission error.""" + if isinstance(output, str): + return ( + "unable to connect" in output + or "LIBUSB_ERROR_ACCESS" in output + or "Permission denied" in output + ) + return ( + b"unable to connect" in output + or b"LIBUSB_ERROR_ACCESS" in output + or b"Permission denied" in output + ) + + +@dataclass +class BootselResult: + """Result of RP2040 BOOTSEL detection.""" + + device_count: int + permission_error: bool = False + + +def detect_rp2040_bootsel(picotool_path: str | Path) -> BootselResult: + """Detect RP2040/RP2350 devices in BOOTSEL mode using picotool. + + Returns a BootselResult with the number of devices found (by counting + 'type:' lines in output), and whether a permission error was detected. + """ + try: + result = subprocess.run( + [str(picotool_path), "info", "-d"], + capture_output=True, + timeout=10, + check=False, + ) + device_count = result.stdout.count(b"type:") + if device_count > 0: + return BootselResult(device_count) + # Check for permission issues — picotool can see the device + # on the USB bus but can't connect without proper permissions + if is_picotool_usb_permission_error(result.stderr + result.stdout): + return BootselResult(0, permission_error=True) + return BootselResult(0) + except (OSError, subprocess.TimeoutExpired): + return BootselResult(0) + + def get_esp32_arduino_flash_error_help() -> str | None: """Returns helpful message when ESP32 with Arduino runs out of flash space.""" from esphome.core import CORE diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index cef561c54b..b6f1a28086 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -8,6 +8,7 @@ import json import logging from pathlib import Path import re +import sys import time from typing import Any from unittest.mock import MagicMock, Mock, patch @@ -40,6 +41,8 @@ from esphome.__main__ import ( show_logs, upload_program, upload_using_esptool, + upload_using_picotool, + upload_using_platformio, ) from esphome.components.esp32 import KEY_ESP32, KEY_VARIANT, VARIANT_ESP32 from esphome.const import ( @@ -70,6 +73,7 @@ from esphome.const import ( PLATFORM_RP2040, ) from esphome.core import CORE, EsphomeError +from esphome.util import BootselResult def strip_ansi_codes(text: str) -> str: @@ -174,6 +178,13 @@ def mock_upload_using_platformio() -> Generator[Mock]: yield mock +@pytest.fixture +def mock_upload_using_picotool() -> Generator[Mock]: + """Mock upload_using_picotool for testing.""" + with patch("esphome.__main__.upload_using_picotool") as mock: + yield mock + + @pytest.fixture def mock_run_ota() -> Generator[Mock]: """Mock espota2.run_ota for testing.""" @@ -851,6 +862,221 @@ def test_choose_upload_log_host_no_address_with_ota_config() -> None: ) +@pytest.mark.usefixtures("mock_no_serial_ports") +def test_choose_upload_log_host_no_defaults_with_rp2040_bootsel( + mock_choose_prompt: Mock, +) -> None: + """Test interactive mode shows RP2040 BOOTSEL option via picotool.""" + setup_core(platform=PLATFORM_RP2040) + + with ( + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch("esphome.__main__.detect_rp2040_bootsel", return_value=BootselResult(1)), + ): + result = choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + assert result == ["/dev/ttyUSB0"] # mock_choose_prompt default + mock_choose_prompt.assert_called_once_with( + [("RP2040 BOOTSEL (via picotool)", "BOOTSEL")], + purpose=Purpose.UPLOADING, + ) + + +@pytest.mark.usefixtures("mock_no_serial_ports") +def test_choose_upload_log_host_rp2040_no_device_shows_bootsel_help() -> None: + """Test BOOTSEL instructions shown when no RP2040 device found.""" + setup_core(platform=PLATFORM_RP2040) + + with ( + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch("esphome.__main__.detect_rp2040_bootsel", return_value=BootselResult(0)), + pytest.raises(EsphomeError, match="BOOTSEL"), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + + +@pytest.mark.usefixtures("mock_no_serial_ports") +def test_choose_upload_log_host_rp2040_bootsel_tip_with_ota( + caplog: pytest.LogCaptureFixture, +) -> None: + """Test BOOTSEL tip shown when only OTA options exist for RP2040.""" + setup_core( + platform=PLATFORM_RP2040, + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, + address="192.168.1.100", + ) + + with ( + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch("esphome.__main__.detect_rp2040_bootsel", return_value=BootselResult(0)), + patch( + "esphome.__main__.choose_prompt", + return_value="192.168.1.100", + ), + caplog.at_level(logging.INFO, logger="esphome.__main__"), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + assert "BOOTSEL" in caplog.text + + +def test_choose_upload_log_host_rp2040_bootsel_tip_with_serial_ports( + caplog: pytest.LogCaptureFixture, + mock_choose_prompt: Mock, +) -> None: + """Test BOOTSEL tip shown when serial ports exist but no BOOTSEL device.""" + setup_core(platform=PLATFORM_RP2040) + + mock_ports = [MockSerialPort("/dev/ttyACM0", "RP2040 Serial")] + with ( + patch("esphome.__main__.get_serial_ports", return_value=mock_ports), + patch( + "esphome.__main__._find_picotool", + return_value=Path("/usr/bin/picotool"), + ), + patch("esphome.__main__.detect_rp2040_bootsel", return_value=BootselResult(0)), + caplog.at_level(logging.INFO, logger="esphome.__main__"), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + assert "BOOTSEL" in caplog.text + + +@pytest.mark.usefixtures("mock_no_serial_ports") +def test_choose_upload_log_host_rp2040_permission_error_no_options( + caplog: pytest.LogCaptureFixture, +) -> None: + """Test permission warning shown when BOOTSEL device found but not accessible.""" + setup_core(platform=PLATFORM_RP2040) + + with ( + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch( + "esphome.__main__.detect_rp2040_bootsel", + return_value=BootselResult(0, permission_error=True), + ), + patch("esphome.__main__.sys.platform", "linux"), + pytest.raises(EsphomeError, match="BOOTSEL"), + caplog.at_level(logging.WARNING, logger="esphome.__main__"), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + + assert "USB permissions" in caplog.text + assert "udev" in caplog.text + + +@pytest.mark.usefixtures("mock_no_serial_ports") +def test_choose_upload_log_host_rp2040_permission_error_with_ota( + caplog: pytest.LogCaptureFixture, +) -> None: + """Test permission warning shown with OTA fallback available.""" + setup_core( + platform=PLATFORM_RP2040, + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, + address="192.168.1.100", + ) + + with ( + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch( + "esphome.__main__.detect_rp2040_bootsel", + return_value=BootselResult(0, permission_error=True), + ), + patch( + "esphome.__main__.choose_prompt", + return_value="192.168.1.100", + ), + caplog.at_level(logging.WARNING, logger="esphome.__main__"), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + + assert "USB permissions" in caplog.text + + +def test_choose_upload_log_host_no_bootsel_for_non_rp2040( + mock_no_serial_ports: Mock, +) -> None: + """Test that BOOTSEL detection is not run for non-RP2040 platforms.""" + setup_core( + platform=PLATFORM_ESP32, + config={CONF_OTA: [{CONF_PLATFORM: CONF_ESPHOME}]}, + address="192.168.1.100", + ) + + with ( + patch("esphome.__main__._find_picotool") as mock_find_picotool, + patch( + "esphome.__main__.choose_prompt", + return_value="192.168.1.100", + ), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + mock_find_picotool.assert_not_called() + + +def test_choose_upload_log_host_rp2040_serial_and_bootsel( + mock_choose_prompt: Mock, +) -> None: + """Test both serial ports and BOOTSEL option shown for RP2040.""" + setup_core(platform=PLATFORM_RP2040) + + mock_ports = [MockSerialPort("/dev/ttyACM0", "RP2040 Serial")] + with ( + patch("esphome.__main__.get_serial_ports", return_value=mock_ports), + patch( + "esphome.__main__._find_picotool", return_value=Path("/usr/bin/picotool") + ), + patch("esphome.__main__.detect_rp2040_bootsel", return_value=BootselResult(1)), + ): + choose_upload_log_host( + default=None, + check_default=None, + purpose=Purpose.UPLOADING, + ) + mock_choose_prompt.assert_called_once_with( + [ + ("/dev/ttyACM0 (RP2040 Serial)", "/dev/ttyACM0"), + ("RP2040 BOOTSEL (via picotool)", "BOOTSEL"), + ], + purpose=Purpose.UPLOADING, + ) + + @dataclass class MockArgs: """Mock args for testing.""" @@ -1060,6 +1286,46 @@ def test_upload_program_serial_platformio_platforms( mock_upload_using_platformio.assert_called_once_with(config, device) +def test_upload_using_platformio_creates_signed_bin_for_rp2040( + tmp_path: Path, +) -> None: + """Test that upload_using_platformio creates firmware.bin.signed for RP2040.""" + setup_core(platform=PLATFORM_RP2040) + + build_dir = tmp_path / "build" + build_dir.mkdir() + firmware_bin = build_dir / "firmware.bin" + firmware_bin.write_bytes(b"test firmware content") + firmware_elf = build_dir / "firmware.elf" + firmware_elf.write_bytes(b"elf") + + mock_idedata = MagicMock() + mock_idedata.firmware_elf_path = str(firmware_elf) + + with ( + patch("esphome.platformio_api.get_idedata", return_value=mock_idedata), + patch("esphome.platformio_api.run_platformio_cli_run", return_value=0), + ): + result = upload_using_platformio({}, "/dev/ttyACM0") + + assert result == 0 + signed_bin = build_dir / "firmware.bin.signed" + assert signed_bin.is_file() + assert signed_bin.read_bytes() == b"test firmware content" + + +def test_upload_using_platformio_skips_signed_bin_for_non_rp2040( + tmp_path: Path, +) -> None: + """Test that upload_using_platformio doesn't create signed bin for non-RP2040.""" + setup_core(platform=PLATFORM_ESP32) + + with patch("esphome.platformio_api.run_platformio_cli_run", return_value=0): + result = upload_using_platformio({}, "/dev/ttyUSB0") + + assert result == 0 + + def test_upload_program_serial_upload_failed( mock_upload_using_esptool: Mock, mock_get_port_type: Mock, @@ -1082,6 +1348,158 @@ def test_upload_program_serial_upload_failed( mock_upload_using_esptool.assert_called_once() +def test_upload_program_bootsel( + mock_upload_using_picotool: Mock, + mock_get_port_type: Mock, +) -> None: + """Test upload_program with BOOTSEL for RP2040.""" + setup_core(platform=PLATFORM_RP2040) + mock_get_port_type.return_value = "BOOTSEL" + mock_upload_using_picotool.return_value = 0 + + config = {} + args = MockArgs() + devices = ["BOOTSEL"] + + exit_code, host = upload_program(config, args, devices) + + assert exit_code == 0 + # BOOTSEL device can't be used for logging, so host should be None + assert host is None + mock_upload_using_picotool.assert_called_once_with(config) + + +def test_upload_program_bootsel_failed( + mock_upload_using_picotool: Mock, + mock_get_port_type: Mock, +) -> None: + """Test upload_program when BOOTSEL upload fails.""" + setup_core(platform=PLATFORM_RP2040) + mock_get_port_type.return_value = "BOOTSEL" + mock_upload_using_picotool.return_value = 1 + + config = {} + args = MockArgs() + devices = ["BOOTSEL"] + + exit_code, host = upload_program(config, args, devices) + + assert exit_code == 1 + assert host is None + mock_upload_using_picotool.assert_called_once_with(config) + + +def test_upload_using_picotool_success(tmp_path: Path) -> None: + """Test upload_using_picotool succeeds.""" + setup_core(platform=PLATFORM_RP2040, tmp_path=tmp_path) + + build_dir = tmp_path / "build" + build_dir.mkdir() + firmware_elf = build_dir / "firmware.elf" + firmware_elf.write_bytes(b"\x00" * 1024) + + # Create picotool binary + packages_dir = tmp_path / "packages" + toolchain_bin = packages_dir / "toolchain-rp2040-earlephilhower" / "bin" + toolchain_bin.mkdir(parents=True) + picotool_dir = packages_dir / "tool-picotool-rp2040-earlephilhower" + picotool_dir.mkdir(parents=True) + binary_name = "picotool.exe" if sys.platform == "win32" else "picotool" + picotool = picotool_dir / binary_name + picotool.touch() + + mock_idedata = MagicMock() + mock_idedata.firmware_elf_path = str(firmware_elf) + mock_idedata.cc_path = str(toolchain_bin / "arm-none-eabi-gcc") + + mock_result = MagicMock() + mock_result.returncode = 0 + mock_result.stderr = b"" + + config = {} + with ( + patch("esphome.platformio_api.get_idedata", return_value=mock_idedata), + patch("subprocess.run", return_value=mock_result), + ): + exit_code = upload_using_picotool(config) + + assert exit_code == 0 + + +def test_upload_using_picotool_no_elf(tmp_path: Path) -> None: + """Test upload_using_picotool when ELF file is missing.""" + setup_core(platform=PLATFORM_RP2040, tmp_path=tmp_path) + + build_dir = tmp_path / "build" + build_dir.mkdir() + + mock_idedata = MagicMock() + mock_idedata.firmware_elf_path = str(build_dir / "firmware.elf") + mock_idedata.cc_path = "/fake/path/gcc" + + config = {} + with patch("esphome.platformio_api.get_idedata", return_value=mock_idedata): + exit_code = upload_using_picotool(config) + + assert exit_code == 1 + + +def test_upload_using_picotool_not_found(tmp_path: Path) -> None: + """Test upload_using_picotool when picotool binary not found.""" + setup_core(platform=PLATFORM_RP2040, tmp_path=tmp_path) + + build_dir = tmp_path / "build" + build_dir.mkdir() + firmware_elf = build_dir / "firmware.elf" + firmware_elf.write_bytes(b"\x00" * 512) + + mock_idedata = MagicMock() + mock_idedata.firmware_elf_path = str(firmware_elf) + mock_idedata.cc_path = "/fake/path/gcc" + + config = {} + with patch("esphome.platformio_api.get_idedata", return_value=mock_idedata): + exit_code = upload_using_picotool(config) + + assert exit_code == 1 + + +def test_upload_using_picotool_permission_error(tmp_path: Path) -> None: + """Test upload_using_picotool shows helpful message on permission error.""" + setup_core(platform=PLATFORM_RP2040, tmp_path=tmp_path) + + build_dir = tmp_path / "build" + build_dir.mkdir() + firmware_elf = build_dir / "firmware.elf" + firmware_elf.write_bytes(b"\x00" * 512) + + packages_dir = tmp_path / "packages" + toolchain_bin = packages_dir / "toolchain-rp2040-earlephilhower" / "bin" + toolchain_bin.mkdir(parents=True) + picotool_dir = packages_dir / "tool-picotool-rp2040-earlephilhower" + picotool_dir.mkdir(parents=True) + binary_name = "picotool.exe" if sys.platform == "win32" else "picotool" + picotool = picotool_dir / binary_name + picotool.touch() + + mock_idedata = MagicMock() + mock_idedata.firmware_elf_path = str(firmware_elf) + mock_idedata.cc_path = str(toolchain_bin / "arm-none-eabi-gcc") + + mock_result = MagicMock() + mock_result.returncode = 1 + mock_result.stderr = b"LIBUSB_ERROR_ACCESS" + + config = {} + with ( + patch("esphome.platformio_api.get_idedata", return_value=mock_idedata), + patch("subprocess.run", return_value=mock_result), + ): + exit_code = upload_using_picotool(config) + + assert exit_code == 1 + + def test_upload_program_ota_success( mock_run_ota: Mock, mock_get_port_type: Mock, @@ -1606,6 +2024,8 @@ def test_get_port_type() -> None: assert get_port_type("esphome-device.local") == "NETWORK" assert get_port_type("10.0.0.1") == "NETWORK" + assert get_port_type("BOOTSEL") == "BOOTSEL" + def test_has_mqtt_ip_lookup() -> None: """Test has_mqtt_ip_lookup function.""" diff --git a/tests/unit_tests/test_util.py b/tests/unit_tests/test_util.py index 85873caea8..ca3fd9b78a 100644 --- a/tests/unit_tests/test_util.py +++ b/tests/unit_tests/test_util.py @@ -3,6 +3,9 @@ from __future__ import annotations from pathlib import Path +import subprocess +import sys +from unittest.mock import MagicMock, patch import pytest @@ -402,3 +405,132 @@ def test_shlex_quote_edge_cases() -> None: assert util.shlex_quote("\t") == "'\t'" assert util.shlex_quote("\n") == "'\n'" assert util.shlex_quote(" ") == "' '" + + +def test_get_picotool_path_found(tmp_path: Path) -> None: + """Test picotool path derivation from cc_path.""" + # Create the expected directory structure + packages_dir = tmp_path / "packages" + toolchain_dir = packages_dir / "toolchain-rp2040-earlephilhower" / "bin" + toolchain_dir.mkdir(parents=True) + gcc = toolchain_dir / "arm-none-eabi-gcc" + gcc.touch() + + binary_name = "picotool.exe" if sys.platform == "win32" else "picotool" + picotool_dir = packages_dir / "tool-picotool-rp2040-earlephilhower" + picotool_dir.mkdir(parents=True) + picotool = picotool_dir / binary_name + picotool.touch() + + result = util.get_picotool_path(str(gcc)) + assert result == picotool + + +def test_get_picotool_path_not_found(tmp_path: Path) -> None: + """Test picotool path returns None when not installed.""" + packages_dir = tmp_path / "packages" + toolchain_dir = packages_dir / "toolchain-rp2040-earlephilhower" / "bin" + toolchain_dir.mkdir(parents=True) + gcc = toolchain_dir / "arm-none-eabi-gcc" + gcc.touch() + + result = util.get_picotool_path(str(gcc)) + assert result is None + + +def test_get_picotool_path_windows(tmp_path: Path) -> None: + """Test picotool path uses .exe on Windows.""" + packages_dir = tmp_path / "packages" + toolchain_dir = packages_dir / "toolchain-rp2040-earlephilhower" / "bin" + toolchain_dir.mkdir(parents=True) + gcc = toolchain_dir / "arm-none-eabi-gcc.exe" + gcc.touch() + + picotool_dir = packages_dir / "tool-picotool-rp2040-earlephilhower" + picotool_dir.mkdir(parents=True) + picotool = picotool_dir / "picotool.exe" + picotool.touch() + + with patch("esphome.util.sys.platform", "win32"): + result = util.get_picotool_path(str(gcc)) + assert result == picotool + + +def test_detect_rp2040_bootsel_found() -> None: + """Test BOOTSEL device detection when device is present.""" + mock_result = MagicMock() + mock_result.stdout = b"Device Information\n type: RP2040\n" + with patch("esphome.util.subprocess.run", return_value=mock_result): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 1 + assert result.permission_error is False + + +def test_detect_rp2040_bootsel_multiple() -> None: + """Test BOOTSEL detection with multiple devices.""" + mock_result = MagicMock() + mock_result.stdout = b"type: RP2040\ntype: RP2350\n" + with patch("esphome.util.subprocess.run", return_value=mock_result): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 2 + assert result.permission_error is False + + +def test_detect_rp2040_bootsel_none() -> None: + """Test BOOTSEL detection when no device found.""" + mock_result = MagicMock() + mock_result.stdout = ( + b"No accessible RP2040/RP2350 devices in BOOTSEL mode were found.\n" + ) + mock_result.stderr = b"" + with patch("esphome.util.subprocess.run", return_value=mock_result): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 0 + assert result.permission_error is False + + +def test_detect_rp2040_bootsel_permission_error() -> None: + """Test BOOTSEL detection with device found but not accessible.""" + mock_result = MagicMock() + mock_result.stdout = ( + b"No accessible RP-series devices in BOOTSEL mode were found.\n" + ) + mock_result.stderr = ( + b"RP2040 device at bus 5, address 24 appears to be in BOOTSEL mode, " + b"but picotool was unable to connect. " + b"Maybe try 'sudo' or check your permissions.\n" + ) + with patch("esphome.util.subprocess.run", return_value=mock_result): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 0 + assert result.permission_error is True + + +def test_detect_rp2040_bootsel_libusb_access_error() -> None: + """Test BOOTSEL detection with LIBUSB_ERROR_ACCESS.""" + mock_result = MagicMock() + mock_result.stdout = b"" + mock_result.stderr = b"LIBUSB_ERROR_ACCESS\n" + with patch("esphome.util.subprocess.run", return_value=mock_result): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 0 + assert result.permission_error is True + + +def test_detect_rp2040_bootsel_oserror() -> None: + """Test BOOTSEL detection handles OSError.""" + with patch("esphome.util.subprocess.run", side_effect=OSError("not found")): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 0 + assert result.permission_error is False + + +def test_detect_rp2040_bootsel_timeout() -> None: + """Test BOOTSEL detection handles timeout.""" + with patch( + "esphome.util.subprocess.run", + side_effect=subprocess.TimeoutExpired("picotool", 10), + ): + result = util.detect_rp2040_bootsel("/usr/bin/picotool") + assert result.device_count == 0 + assert result.permission_error is False From 6e468936ec670461e244aa93b7d3ea74f1fa2bef Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:10:55 -1000 Subject: [PATCH 1260/2030] [api] Inline ProtoVarInt::parse fast path and return consumed in struct (#14638) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../api/api_frame_helper_plaintext.cpp | 24 +- esphome/components/api/api_pb2.cpp | 430 +++++++++--------- esphome/components/api/api_pb2.h | 102 ++--- esphome/components/api/proto.cpp | 75 +-- esphome/components/api/proto.h | 118 ++--- script/api_protobuf/api_protobuf.py | 20 +- 6 files changed, 376 insertions(+), 393 deletions(-) diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index 3c54ed7c70..793cece3b8 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -128,37 +128,37 @@ APIError APIPlaintextFrameHelper::try_read_frame_() { // Skip indicator byte at position 0 uint8_t varint_pos = 1; - uint32_t consumed = 0; - auto msg_size_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos, &consumed); + // rx_header_buf_pos_ >= 3 and varint_pos == 1, so len >= 2 + auto msg_size_varint = ProtoVarInt::parse_non_empty(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos); if (!msg_size_varint.has_value()) { // not enough data there yet continue; } - if (msg_size_varint->as_uint32() > MAX_MESSAGE_SIZE) { + if (msg_size_varint.value > MAX_MESSAGE_SIZE) { state_ = State::FAILED; - HELPER_LOG("Bad packet: message size %" PRIu32 " exceeds maximum %u", msg_size_varint->as_uint32(), - MAX_MESSAGE_SIZE); + HELPER_LOG("Bad packet: message size %" PRIu32 " exceeds maximum %u", + static_cast<uint32_t>(msg_size_varint.value), MAX_MESSAGE_SIZE); return APIError::BAD_DATA_PACKET; } - rx_header_parsed_len_ = msg_size_varint->as_uint16(); + rx_header_parsed_len_ = static_cast<uint16_t>(msg_size_varint.value); // Move to next varint position - varint_pos += consumed; + varint_pos += msg_size_varint.consumed; - auto msg_type_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos, &consumed); + auto msg_type_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos); if (!msg_type_varint.has_value()) { // not enough data there yet continue; } - if (msg_type_varint->as_uint32() > std::numeric_limits<uint16_t>::max()) { + if (msg_type_varint.value > std::numeric_limits<uint16_t>::max()) { state_ = State::FAILED; - HELPER_LOG("Bad packet: message type %" PRIu32 " exceeds maximum %u", msg_type_varint->as_uint32(), - std::numeric_limits<uint16_t>::max()); + HELPER_LOG("Bad packet: message type %" PRIu32 " exceeds maximum %u", + static_cast<uint32_t>(msg_type_varint.value), std::numeric_limits<uint16_t>::max()); return APIError::BAD_DATA_PACKET; } - rx_header_parsed_type_ = msg_type_varint->as_uint16(); + rx_header_parsed_type_ = static_cast<uint16_t>(msg_type_varint.value); rx_header_parsed_ = true; } // header reading done diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 6fce10ca0f..01993cc5e5 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7,13 +7,13 @@ namespace esphome::api { -bool HelloRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool HelloRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->api_version_major = value.as_uint32(); + this->api_version_major = value; break; case 3: - this->api_version_minor = value.as_uint32(); + this->api_version_minor = value; break; default: return false; @@ -316,20 +316,20 @@ uint32_t CoverStateResponse::calculate_size() const { #endif return size; } -bool CoverCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool CoverCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 4: - this->has_position = value.as_bool(); + this->has_position = value != 0; break; case 6: - this->has_tilt = value.as_bool(); + this->has_tilt = value != 0; break; case 8: - this->stop = value.as_bool(); + this->stop = value != 0; break; #ifdef USE_DEVICES case 9: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -423,38 +423,38 @@ uint32_t FanStateResponse::calculate_size() const { #endif return size; } -bool FanCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool FanCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_state = value.as_bool(); + this->has_state = value != 0; break; case 3: - this->state = value.as_bool(); + this->state = value != 0; break; case 6: - this->has_oscillating = value.as_bool(); + this->has_oscillating = value != 0; break; case 7: - this->oscillating = value.as_bool(); + this->oscillating = value != 0; break; case 8: - this->has_direction = value.as_bool(); + this->has_direction = value != 0; break; case 9: - this->direction = static_cast<enums::FanDirection>(value.as_uint32()); + this->direction = static_cast<enums::FanDirection>(value); break; case 10: - this->has_speed_level = value.as_bool(); + this->has_speed_level = value != 0; break; case 11: - this->speed_level = value.as_int32(); + this->speed_level = static_cast<int32_t>(value); break; case 12: - this->has_preset_mode = value.as_bool(); + this->has_preset_mode = value != 0; break; #ifdef USE_DEVICES case 14: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -571,59 +571,59 @@ uint32_t LightStateResponse::calculate_size() const { #endif return size; } -bool LightCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool LightCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_state = value.as_bool(); + this->has_state = value != 0; break; case 3: - this->state = value.as_bool(); + this->state = value != 0; break; case 4: - this->has_brightness = value.as_bool(); + this->has_brightness = value != 0; break; case 22: - this->has_color_mode = value.as_bool(); + this->has_color_mode = value != 0; break; case 23: - this->color_mode = static_cast<enums::ColorMode>(value.as_uint32()); + this->color_mode = static_cast<enums::ColorMode>(value); break; case 20: - this->has_color_brightness = value.as_bool(); + this->has_color_brightness = value != 0; break; case 6: - this->has_rgb = value.as_bool(); + this->has_rgb = value != 0; break; case 10: - this->has_white = value.as_bool(); + this->has_white = value != 0; break; case 12: - this->has_color_temperature = value.as_bool(); + this->has_color_temperature = value != 0; break; case 24: - this->has_cold_white = value.as_bool(); + this->has_cold_white = value != 0; break; case 26: - this->has_warm_white = value.as_bool(); + this->has_warm_white = value != 0; break; case 14: - this->has_transition_length = value.as_bool(); + this->has_transition_length = value != 0; break; case 15: - this->transition_length = value.as_uint32(); + this->transition_length = value; break; case 16: - this->has_flash_length = value.as_bool(); + this->has_flash_length = value != 0; break; case 17: - this->flash_length = value.as_uint32(); + this->flash_length = value; break; case 18: - this->has_effect = value.as_bool(); + this->has_effect = value != 0; break; #ifdef USE_DEVICES case 28: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -787,14 +787,14 @@ uint32_t SwitchStateResponse::calculate_size() const { #endif return size; } -bool SwitchCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SwitchCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->state = value.as_bool(); + this->state = value != 0; break; #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -863,13 +863,13 @@ uint32_t TextSensorStateResponse::calculate_size() const { return size; } #endif -bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SubscribeLogsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->level = static_cast<enums::LogLevel>(value.as_uint32()); + this->level = static_cast<enums::LogLevel>(value); break; case 2: - this->dump_config = value.as_bool(); + this->dump_config = value != 0; break; default: return false; @@ -971,13 +971,13 @@ uint32_t HomeassistantActionRequest::calculate_size() const { } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES -bool HomeassistantActionResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool HomeassistantActionResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->call_id = value.as_uint32(); + this->call_id = value; break; case 2: - this->success = value.as_bool(); + this->success = value != 0; break; default: return false; @@ -1036,38 +1036,38 @@ bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDel return true; } #endif -bool DSTRule::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool DSTRule::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->time_seconds = value.as_sint32(); + this->time_seconds = decode_zigzag32(static_cast<uint32_t>(value)); break; case 2: - this->day = value.as_uint32(); + this->day = value; break; case 3: - this->type = static_cast<enums::DSTRuleType>(value.as_uint32()); + this->type = static_cast<enums::DSTRuleType>(value); break; case 4: - this->month = value.as_uint32(); + this->month = value; break; case 5: - this->week = value.as_uint32(); + this->week = value; break; case 6: - this->day_of_week = value.as_uint32(); + this->day_of_week = value; break; default: return false; } return true; } -bool ParsedTimezone::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ParsedTimezone::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->std_offset_seconds = value.as_sint32(); + this->std_offset_seconds = decode_zigzag32(static_cast<uint32_t>(value)); break; case 2: - this->dst_offset_seconds = value.as_sint32(); + this->dst_offset_seconds = decode_zigzag32(static_cast<uint32_t>(value)); break; default: return false; @@ -1142,22 +1142,22 @@ uint32_t ListEntitiesServicesResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->supports_response)); return size; } -bool ExecuteServiceArgument::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ExecuteServiceArgument::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->bool_ = value.as_bool(); + this->bool_ = value != 0; break; case 2: - this->legacy_int = value.as_int32(); + this->legacy_int = static_cast<int32_t>(value); break; case 5: - this->int_ = value.as_sint32(); + this->int_ = decode_zigzag32(static_cast<uint32_t>(value)); break; case 6: - this->bool_array.push_back(value.as_bool()); + this->bool_array.push_back(value != 0); break; case 7: - this->int_array.push_back(value.as_sint32()); + this->int_array.push_back(decode_zigzag32(static_cast<uint32_t>(value))); break; default: return false; @@ -1202,16 +1202,16 @@ void ExecuteServiceArgument::decode(const uint8_t *buffer, size_t length) { this->string_array.init(count_string_array); ProtoDecodableMessage::decode(buffer, length); } -bool ExecuteServiceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ExecuteServiceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES case 3: - this->call_id = value.as_uint32(); + this->call_id = value; break; #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES case 4: - this->return_response = value.as_bool(); + this->return_response = value != 0; break; #endif default: @@ -1313,13 +1313,13 @@ uint32_t CameraImageResponse::calculate_size() const { #endif return size; } -bool CameraImageRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->single = value.as_bool(); + this->single = value != 0; break; case 2: - this->stream = value.as_bool(); + this->stream = value != 0; break; default: return false; @@ -1468,53 +1468,53 @@ uint32_t ClimateStateResponse::calculate_size() const { #endif return size; } -bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ClimateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_mode = value.as_bool(); + this->has_mode = value != 0; break; case 3: - this->mode = static_cast<enums::ClimateMode>(value.as_uint32()); + this->mode = static_cast<enums::ClimateMode>(value); break; case 4: - this->has_target_temperature = value.as_bool(); + this->has_target_temperature = value != 0; break; case 6: - this->has_target_temperature_low = value.as_bool(); + this->has_target_temperature_low = value != 0; break; case 8: - this->has_target_temperature_high = value.as_bool(); + this->has_target_temperature_high = value != 0; break; case 12: - this->has_fan_mode = value.as_bool(); + this->has_fan_mode = value != 0; break; case 13: - this->fan_mode = static_cast<enums::ClimateFanMode>(value.as_uint32()); + this->fan_mode = static_cast<enums::ClimateFanMode>(value); break; case 14: - this->has_swing_mode = value.as_bool(); + this->has_swing_mode = value != 0; break; case 15: - this->swing_mode = static_cast<enums::ClimateSwingMode>(value.as_uint32()); + this->swing_mode = static_cast<enums::ClimateSwingMode>(value); break; case 16: - this->has_custom_fan_mode = value.as_bool(); + this->has_custom_fan_mode = value != 0; break; case 18: - this->has_preset = value.as_bool(); + this->has_preset = value != 0; break; case 19: - this->preset = static_cast<enums::ClimatePreset>(value.as_uint32()); + this->preset = static_cast<enums::ClimatePreset>(value); break; case 20: - this->has_custom_preset = value.as_bool(); + this->has_custom_preset = value != 0; break; case 22: - this->has_target_humidity = value.as_bool(); + this->has_target_humidity = value != 0; break; #ifdef USE_DEVICES case 24: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -1631,21 +1631,21 @@ uint32_t WaterHeaterStateResponse::calculate_size() const { size += ProtoSize::calc_float(1, this->target_temperature_high); return size; } -bool WaterHeaterCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool WaterHeaterCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_fields = value.as_uint32(); + this->has_fields = value; break; case 3: - this->mode = static_cast<enums::WaterHeaterMode>(value.as_uint32()); + this->mode = static_cast<enums::WaterHeaterMode>(value); break; #ifdef USE_DEVICES case 5: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif case 6: - this->state = value.as_uint32(); + this->state = value; break; default: return false; @@ -1731,11 +1731,11 @@ uint32_t NumberStateResponse::calculate_size() const { #endif return size; } -bool NumberCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool NumberCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -1812,11 +1812,11 @@ uint32_t SelectStateResponse::calculate_size() const { #endif return size; } -bool SelectCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SelectCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -1903,29 +1903,29 @@ uint32_t SirenStateResponse::calculate_size() const { #endif return size; } -bool SirenCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SirenCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_state = value.as_bool(); + this->has_state = value != 0; break; case 3: - this->state = value.as_bool(); + this->state = value != 0; break; case 4: - this->has_tone = value.as_bool(); + this->has_tone = value != 0; break; case 6: - this->has_duration = value.as_bool(); + this->has_duration = value != 0; break; case 7: - this->duration = value.as_uint32(); + this->duration = value; break; case 8: - this->has_volume = value.as_bool(); + this->has_volume = value != 0; break; #ifdef USE_DEVICES case 10: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -2011,17 +2011,17 @@ uint32_t LockStateResponse::calculate_size() const { #endif return size; } -bool LockCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool LockCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->command = static_cast<enums::LockCommand>(value.as_uint32()); + this->command = static_cast<enums::LockCommand>(value); break; case 3: - this->has_code = value.as_bool(); + this->has_code = value != 0; break; #ifdef USE_DEVICES case 5: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -2082,11 +2082,11 @@ uint32_t ListEntitiesButtonResponse::calculate_size() const { #endif return size; } -bool ButtonCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ButtonCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 2: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -2182,29 +2182,29 @@ uint32_t MediaPlayerStateResponse::calculate_size() const { #endif return size; } -bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_command = value.as_bool(); + this->has_command = value != 0; break; case 3: - this->command = static_cast<enums::MediaPlayerCommand>(value.as_uint32()); + this->command = static_cast<enums::MediaPlayerCommand>(value); break; case 4: - this->has_volume = value.as_bool(); + this->has_volume = value != 0; break; case 6: - this->has_media_url = value.as_bool(); + this->has_media_url = value != 0; break; case 8: - this->has_announcement = value.as_bool(); + this->has_announcement = value != 0; break; case 9: - this->announcement = value.as_bool(); + this->announcement = value != 0; break; #ifdef USE_DEVICES case 10: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -2238,10 +2238,10 @@ bool MediaPlayerCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value } #endif #ifdef USE_BLUETOOTH_PROXY -bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->flags = value.as_uint32(); + this->flags = value; break; default: return false; @@ -2274,19 +2274,19 @@ uint32_t BluetoothLERawAdvertisementsResponse::calculate_size() const { } return size; } -bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->request_type = static_cast<enums::BluetoothDeviceRequestType>(value.as_uint32()); + this->request_type = static_cast<enums::BluetoothDeviceRequestType>(value); break; case 3: - this->has_address_type = value.as_bool(); + this->has_address_type = value != 0; break; case 4: - this->address_type = value.as_uint32(); + this->address_type = value; break; default: return false; @@ -2307,10 +2307,10 @@ uint32_t BluetoothDeviceConnectionResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->error); return size; } -bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; default: return false; @@ -2413,13 +2413,13 @@ uint32_t BluetoothGATTGetServicesDoneResponse::calculate_size() const { size += ProtoSize::calc_uint64(1, this->address); return size; } -bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->handle = value.as_uint32(); + this->handle = value; break; default: return false; @@ -2438,16 +2438,16 @@ uint32_t BluetoothGATTReadResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->data_len_); return size; } -bool BluetoothGATTWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTWriteRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->handle = value.as_uint32(); + this->handle = value; break; case 3: - this->response = value.as_bool(); + this->response = value != 0; break; default: return false; @@ -2466,26 +2466,26 @@ bool BluetoothGATTWriteRequest::decode_length(uint32_t field_id, ProtoLengthDeli } return true; } -bool BluetoothGATTReadDescriptorRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTReadDescriptorRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->handle = value.as_uint32(); + this->handle = value; break; default: return false; } return true; } -bool BluetoothGATTWriteDescriptorRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTWriteDescriptorRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->handle = value.as_uint32(); + this->handle = value; break; default: return false; @@ -2504,16 +2504,16 @@ bool BluetoothGATTWriteDescriptorRequest::decode_length(uint32_t field_id, Proto } return true; } -bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->handle = value.as_uint32(); + this->handle = value; break; case 3: - this->enable = value.as_bool(); + this->enable = value != 0; break; default: return false; @@ -2632,10 +2632,10 @@ uint32_t BluetoothScannerStateResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->configured_mode)); return size; } -bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->mode = static_cast<enums::BluetoothScannerMode>(value.as_uint32()); + this->mode = static_cast<enums::BluetoothScannerMode>(value); break; default: return false; @@ -2644,13 +2644,13 @@ bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, ProtoVarIn } #endif #ifdef USE_VOICE_ASSISTANT -bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->subscribe = value.as_bool(); + this->subscribe = value != 0; break; case 2: - this->flags = value.as_uint32(); + this->flags = value; break; default: return false; @@ -2685,13 +2685,13 @@ uint32_t VoiceAssistantRequest::calculate_size() const { size += ProtoSize::calc_length(1, this->wake_word_phrase.size()); return size; } -bool VoiceAssistantResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->port = value.as_uint32(); + this->port = value; break; case 2: - this->error = value.as_bool(); + this->error = value != 0; break; default: return false; @@ -2713,10 +2713,10 @@ bool VoiceAssistantEventData::decode_length(uint32_t field_id, ProtoLengthDelimi } return true; } -bool VoiceAssistantEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantEventResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->event_type = static_cast<enums::VoiceAssistantEvent>(value.as_uint32()); + this->event_type = static_cast<enums::VoiceAssistantEvent>(value); break; default: return false; @@ -2734,10 +2734,10 @@ bool VoiceAssistantEventResponse::decode_length(uint32_t field_id, ProtoLengthDe } return true; } -bool VoiceAssistantAudio::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantAudio::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->end = value.as_bool(); + this->end = value != 0; break; default: return false; @@ -2766,19 +2766,19 @@ uint32_t VoiceAssistantAudio::calculate_size() const { size += ProtoSize::calc_bool(1, this->end); return size; } -bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->event_type = static_cast<enums::VoiceAssistantTimerEvent>(value.as_uint32()); + this->event_type = static_cast<enums::VoiceAssistantTimerEvent>(value); break; case 4: - this->total_seconds = value.as_uint32(); + this->total_seconds = value; break; case 5: - this->seconds_left = value.as_uint32(); + this->seconds_left = value; break; case 6: - this->is_active = value.as_bool(); + this->is_active = value != 0; break; default: return false; @@ -2800,10 +2800,10 @@ bool VoiceAssistantTimerEventResponse::decode_length(uint32_t field_id, ProtoLen } return true; } -bool VoiceAssistantAnnounceRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantAnnounceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 4: - this->start_conversation = value.as_bool(); + this->start_conversation = value != 0; break; default: return false; @@ -2853,10 +2853,10 @@ uint32_t VoiceAssistantWakeWord::calculate_size() const { } return size; } -bool VoiceAssistantExternalWakeWord::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool VoiceAssistantExternalWakeWord::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 5: - this->model_size = value.as_uint32(); + this->model_size = value; break; default: return false; @@ -2990,14 +2990,14 @@ uint32_t AlarmControlPanelStateResponse::calculate_size() const { #endif return size; } -bool AlarmControlPanelCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool AlarmControlPanelCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->command = static_cast<enums::AlarmControlPanelStateCommand>(value.as_uint32()); + this->command = static_cast<enums::AlarmControlPanelStateCommand>(value); break; #ifdef USE_DEVICES case 4: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3082,11 +3082,11 @@ uint32_t TextStateResponse::calculate_size() const { #endif return size; } -bool TextCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool TextCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3167,20 +3167,20 @@ uint32_t DateStateResponse::calculate_size() const { #endif return size; } -bool DateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool DateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->year = value.as_uint32(); + this->year = value; break; case 3: - this->month = value.as_uint32(); + this->month = value; break; case 4: - this->day = value.as_uint32(); + this->day = value; break; #ifdef USE_DEVICES case 5: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3250,20 +3250,20 @@ uint32_t TimeStateResponse::calculate_size() const { #endif return size; } -bool TimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool TimeCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->hour = value.as_uint32(); + this->hour = value; break; case 3: - this->minute = value.as_uint32(); + this->minute = value; break; case 4: - this->second = value.as_uint32(); + this->second = value; break; #ifdef USE_DEVICES case 5: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3393,17 +3393,17 @@ uint32_t ValveStateResponse::calculate_size() const { #endif return size; } -bool ValveCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ValveCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->has_position = value.as_bool(); + this->has_position = value != 0; break; case 4: - this->stop = value.as_bool(); + this->stop = value != 0; break; #ifdef USE_DEVICES case 5: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3472,11 +3472,11 @@ uint32_t DateTimeStateResponse::calculate_size() const { #endif return size; } -bool DateTimeCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool DateTimeCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3561,14 +3561,14 @@ uint32_t UpdateStateResponse::calculate_size() const { #endif return size; } -bool UpdateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool UpdateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 2: - this->command = static_cast<enums::UpdateCommand>(value.as_uint32()); + this->command = static_cast<enums::UpdateCommand>(value); break; #ifdef USE_DEVICES case 3: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif default: @@ -3606,10 +3606,10 @@ uint32_t ZWaveProxyFrame::calculate_size() const { size += ProtoSize::calc_length(1, this->data_len); return size; } -bool ZWaveProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool ZWaveProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->type = static_cast<enums::ZWaveProxyRequestType>(value.as_uint32()); + this->type = static_cast<enums::ZWaveProxyRequestType>(value); break; default: return false; @@ -3672,18 +3672,18 @@ uint32_t ListEntitiesInfraredResponse::calculate_size() const { } #endif #ifdef USE_IR_RF -bool InfraredRFTransmitRawTimingsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool InfraredRFTransmitRawTimingsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { #ifdef USE_DEVICES case 1: - this->device_id = value.as_uint32(); + this->device_id = value; break; #endif case 3: - this->carrier_frequency = value.as_uint32(); + this->carrier_frequency = value; break; case 4: - this->repeat_count = value.as_uint32(); + this->repeat_count = value; break; default: return false; @@ -3737,25 +3737,25 @@ uint32_t InfraredRFReceiveEvent::calculate_size() const { } #endif #ifdef USE_SERIAL_PROXY -bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->instance = value.as_uint32(); + this->instance = value; break; case 2: - this->baudrate = value.as_uint32(); + this->baudrate = value; break; case 3: - this->flow_control = value.as_bool(); + this->flow_control = value != 0; break; case 4: - this->parity = static_cast<enums::SerialProxyParity>(value.as_uint32()); + this->parity = static_cast<enums::SerialProxyParity>(value); break; case 5: - this->stop_bits = value.as_uint32(); + this->stop_bits = value; break; case 6: - this->data_size = value.as_uint32(); + this->data_size = value; break; default: return false; @@ -3772,10 +3772,10 @@ uint32_t SerialProxyDataReceived::calculate_size() const { size += ProtoSize::calc_length(1, this->data_len_); return size; } -bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->instance = value.as_uint32(); + this->instance = value; break; default: return false; @@ -3794,23 +3794,23 @@ bool SerialProxyWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimi } return true; } -bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->instance = value.as_uint32(); + this->instance = value; break; case 2: - this->line_states = value.as_uint32(); + this->line_states = value; break; default: return false; } return true; } -bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->instance = value.as_uint32(); + this->instance = value; break; default: return false; @@ -3827,13 +3827,13 @@ uint32_t SerialProxyGetModemPinsResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->line_states); return size; } -bool SerialProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool SerialProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->instance = value.as_uint32(); + this->instance = value; break; case 2: - this->type = static_cast<enums::SerialProxyRequestType>(value.as_uint32()); + this->type = static_cast<enums::SerialProxyRequestType>(value); break; default: return false; @@ -3856,22 +3856,22 @@ uint32_t SerialProxyRequestResponse::calculate_size() const { } #endif #ifdef USE_BLUETOOTH_PROXY -bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) { +bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { switch (field_id) { case 1: - this->address = value.as_uint64(); + this->address = value; break; case 2: - this->min_interval = value.as_uint32(); + this->min_interval = value; break; case 3: - this->max_interval = value.as_uint32(); + this->max_interval = value; break; case 4: - this->latency = value.as_uint32(); + this->latency = value; break; case 5: - this->timeout = value.as_uint32(); + this->timeout = value; break; default: return false; diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 5c712508b9..a4ee0adb8b 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -399,7 +399,7 @@ class HelloRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class HelloResponse final : public ProtoMessage { public: @@ -688,7 +688,7 @@ class CoverCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_FAN @@ -756,7 +756,7 @@ class FanCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_LIGHT @@ -846,7 +846,7 @@ class LightCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_SENSOR @@ -936,7 +936,7 @@ class SwitchCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_TEXT_SENSOR @@ -988,7 +988,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SubscribeLogsResponse final : public ProtoMessage { public: @@ -1110,7 +1110,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_API_HOMEASSISTANT_STATES @@ -1176,7 +1176,7 @@ class DSTRule final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class ParsedTimezone final : public ProtoDecodableMessage { public: @@ -1190,7 +1190,7 @@ class ParsedTimezone final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class GetTimeResponse final : public ProtoDecodableMessage { public: @@ -1261,7 +1261,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class ExecuteServiceRequest final : public ProtoDecodableMessage { public: @@ -1286,7 +1286,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES @@ -1365,7 +1365,7 @@ class CameraImageRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_CLIMATE @@ -1464,7 +1464,7 @@ class ClimateCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_WATER_HEATER @@ -1528,7 +1528,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_NUMBER @@ -1584,7 +1584,7 @@ class NumberCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_SELECT @@ -1636,7 +1636,7 @@ class SelectCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_SIREN @@ -1696,7 +1696,7 @@ class SirenCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_LOCK @@ -1752,7 +1752,7 @@ class LockCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_BUTTON @@ -1785,7 +1785,7 @@ class ButtonCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_MEDIA_PLAYER @@ -1862,7 +1862,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_BLUETOOTH_PROXY @@ -1879,7 +1879,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothLERawAdvertisement final : public ProtoMessage { public: @@ -1929,7 +1929,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothDeviceConnectionResponse final : public ProtoMessage { public: @@ -1963,7 +1963,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTDescriptor final : public ProtoMessage { public: @@ -2054,7 +2054,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTReadResponse final : public ProtoMessage { public: @@ -2097,7 +2097,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2113,7 +2113,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2132,7 +2132,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { public: @@ -2149,7 +2149,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothGATTNotifyDataResponse final : public ProtoMessage { public: @@ -2329,7 +2329,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_VOICE_ASSISTANT @@ -2347,7 +2347,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantAudioSettings final : public ProtoMessage { public: @@ -2396,7 +2396,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantEventData final : public ProtoDecodableMessage { public: @@ -2424,7 +2424,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantAudio final : public ProtoDecodableMessage { public: @@ -2444,7 +2444,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { public: @@ -2465,7 +2465,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { public: @@ -2484,7 +2484,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantAnnounceFinished final : public ProtoMessage { public: @@ -2530,7 +2530,7 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { public: @@ -2632,7 +2632,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_TEXT @@ -2687,7 +2687,7 @@ class TextCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_DATETIME_DATE @@ -2741,7 +2741,7 @@ class DateCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_DATETIME_TIME @@ -2795,7 +2795,7 @@ class TimeCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_EVENT @@ -2886,7 +2886,7 @@ class ValveCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_DATETIME_DATETIME @@ -2936,7 +2936,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_UPDATE @@ -2994,7 +2994,7 @@ class UpdateCommandRequest final : public CommandProtoMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_ZWAVE_PROXY @@ -3034,7 +3034,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; #endif #ifdef USE_INFRARED @@ -3079,7 +3079,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { protected: bool decode_32bit(uint32_t field_id, Proto32Bit value) override; bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class InfraredRFReceiveEvent final : public ProtoMessage { public: @@ -3121,7 +3121,7 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SerialProxyDataReceived final : public ProtoMessage { public: @@ -3161,7 +3161,7 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage { protected: bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3177,7 +3177,7 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3192,7 +3192,7 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SerialProxyGetModemPinsResponse final : public ProtoMessage { public: @@ -3225,7 +3225,7 @@ class SerialProxyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class SerialProxyRequestResponse final : public ProtoMessage { public: @@ -3265,7 +3265,7 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, ProtoVarInt value) override; + bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; }; class BluetoothSetConnectionParamsResponse final : public ProtoMessage { public: diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index fb229928e5..4f5b3f0918 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -20,20 +20,40 @@ void ProtoWriteBuffer::encode_varint_raw_slow_(uint32_t value) { *this->pos_++ = static_cast<uint8_t>(value); } +ProtoVarIntResult ProtoVarInt::parse_slow(const uint8_t *buffer, uint32_t len) { + // Multi-byte varint: first byte already checked to have high bit set + uint32_t result32 = buffer[0] & 0x7F; #ifdef USE_API_VARINT64 -optional<ProtoVarInt> ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, - uint32_t result32) { + uint32_t limit = std::min(len, uint32_t(4)); +#else + uint32_t limit = std::min(len, uint32_t(5)); +#endif + for (uint32_t i = 1; i < limit; i++) { + uint8_t val = buffer[i]; + result32 |= uint32_t(val & 0x7F) << (i * 7); + if ((val & 0x80) == 0) { + return {result32, i + 1}; + } + } +#ifdef USE_API_VARINT64 + return parse_wide(buffer, len, result32); +#else + return {0, PROTO_VARINT_PARSE_FAILED}; +#endif +} + +#ifdef USE_API_VARINT64 +ProtoVarIntResult ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) { uint64_t result64 = result32; uint32_t limit = std::min(len, uint32_t(10)); for (uint32_t i = 4; i < limit; i++) { uint8_t val = buffer[i]; result64 |= uint64_t(val & 0x7F) << (i * 7); if ((val & 0x80) == 0) { - *consumed = i + 1; - return ProtoVarInt(result64); + return {result64, i + 1}; } } - return {}; + return {0, PROTO_VARINT_PARSE_FAILED}; } #endif @@ -43,18 +63,16 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size const uint8_t *end = buffer + length; while (ptr < end) { - uint32_t consumed; - - // Parse field header (tag) - auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + // Parse field header (tag) - ptr < end guarantees len >= 1 + auto res = ProtoVarInt::parse_non_empty(ptr, end - ptr); if (!res.has_value()) { break; // Invalid data, stop counting } - uint32_t tag = res->as_uint32(); + uint32_t tag = static_cast<uint32_t>(res.value); uint32_t field_type = tag & WIRE_TYPE_MASK; uint32_t field_id = tag >> 3; - ptr += consumed; + ptr += res.consumed; // Count if this is the target field if (field_id == target_field_id) { @@ -64,20 +82,20 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size // Skip field data based on wire type switch (field_type) { case WIRE_TYPE_VARINT: { // VarInt - parse and skip - res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + res = ProtoVarInt::parse(ptr, end - ptr); if (!res.has_value()) { return count; // Invalid data, return what we have } - ptr += consumed; + ptr += res.consumed; break; } case WIRE_TYPE_LENGTH_DELIMITED: { // Length-delimited - parse length and skip data - res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + res = ProtoVarInt::parse(ptr, end - ptr); if (!res.has_value()) { return count; } - uint32_t field_length = res->as_uint32(); - ptr += consumed; + uint32_t field_length = static_cast<uint32_t>(res.value); + ptr += res.consumed; if (field_length > static_cast<size_t>(end - ptr)) { return count; // Out of bounds } @@ -190,41 +208,40 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { const uint8_t *end = buffer + length; while (ptr < end) { - uint32_t consumed; - - // Parse field header - auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + // Parse field header - ptr < end guarantees len >= 1 + auto res = ProtoVarInt::parse_non_empty(ptr, end - ptr); if (!res.has_value()) { ESP_LOGV(TAG, "Invalid field start at offset %ld", (long) (ptr - buffer)); return; } - uint32_t tag = res->as_uint32(); + uint32_t tag = static_cast<uint32_t>(res.value); uint32_t field_type = tag & WIRE_TYPE_MASK; uint32_t field_id = tag >> 3; - ptr += consumed; + ptr += res.consumed; switch (field_type) { case WIRE_TYPE_VARINT: { // VarInt - res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + res = ProtoVarInt::parse(ptr, end - ptr); if (!res.has_value()) { ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer)); return; } - if (!this->decode_varint(field_id, *res)) { - ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32()); + if (!this->decode_varint(field_id, res.value)) { + ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu64 "!", field_id, + static_cast<uint64_t>(res.value)); } - ptr += consumed; + ptr += res.consumed; break; } case WIRE_TYPE_LENGTH_DELIMITED: { // Length-delimited - res = ProtoVarInt::parse(ptr, end - ptr, &consumed); + res = ProtoVarInt::parse(ptr, end - ptr); if (!res.has_value()) { ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer)); return; } - uint32_t field_length = res->as_uint32(); - ptr += consumed; + uint32_t field_length = static_cast<uint32_t>(res.value); + ptr += res.consumed; if (field_length > static_cast<size_t>(end - ptr)) { ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer)); return; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index adde0a8a85..7050efb446 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -98,90 +98,56 @@ inline void encode_varint_to_buffer(uint32_t val, uint8_t *buffer) { * within the same function scope where temporaries are created. */ -/// Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit +/// Type used for decoded varint values - uint64_t when BLE needs 64-bit addresses, uint32_t otherwise +#ifdef USE_API_VARINT64 +using proto_varint_value_t = uint64_t; +#else +using proto_varint_value_t = uint32_t; +#endif + +/// Sentinel value for consumed field indicating parse failure +inline constexpr uint32_t PROTO_VARINT_PARSE_FAILED = 0; + +/// Result of parsing a varint: value + number of bytes consumed. +/// consumed == PROTO_VARINT_PARSE_FAILED indicates parse failure (not enough data or invalid). +struct ProtoVarIntResult { + proto_varint_value_t value; + uint32_t consumed; // PROTO_VARINT_PARSE_FAILED = parse failed + + constexpr bool has_value() const { return this->consumed != PROTO_VARINT_PARSE_FAILED; } +}; + +/// Static varint parsing methods for the protobuf wire format. class ProtoVarInt { public: - ProtoVarInt() : value_(0) {} - explicit ProtoVarInt(uint64_t value) : value_(value) {} - - /// Parse a varint from buffer. consumed must be a valid pointer (not null). - static optional<ProtoVarInt> parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed) { + /// Parse a varint from buffer. Caller must ensure len >= 1. + /// Returns result with consumed=0 on failure (truncated multi-byte varint). + static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse_non_empty(const uint8_t *buffer, uint32_t len) { #ifdef ESPHOME_DEBUG_API - assert(consumed != nullptr); + assert(len > 0); #endif - if (len == 0) - return {}; // Fast path: single-byte varints (0-127) are the most common case - // (booleans, small enums, field tags). Avoid loop overhead entirely. - if ((buffer[0] & 0x80) == 0) { - *consumed = 1; - return ProtoVarInt(buffer[0]); - } - // 32-bit phase: process remaining bytes with native 32-bit shifts. - // Without USE_API_VARINT64: cover bytes 1-4 (shifts 7, 14, 21, 28) — the uint32_t - // shift at byte 4 (shift by 28) may lose bits 32-34, but those are always zero for valid uint32 values. - // With USE_API_VARINT64: cover bytes 1-3 (shifts 7, 14, 21) so parse_wide handles - // byte 4+ with full 64-bit arithmetic (avoids truncating values > UINT32_MAX). - uint32_t result32 = buffer[0] & 0x7F; -#ifdef USE_API_VARINT64 - uint32_t limit = std::min(len, uint32_t(4)); -#else - uint32_t limit = std::min(len, uint32_t(5)); -#endif - for (uint32_t i = 1; i < limit; i++) { - uint8_t val = buffer[i]; - result32 |= uint32_t(val & 0x7F) << (i * 7); - if ((val & 0x80) == 0) { - *consumed = i + 1; - return ProtoVarInt(result32); - } - } - // 64-bit phase for remaining bytes (BLE addresses etc.) -#ifdef USE_API_VARINT64 - return parse_wide(buffer, len, consumed, result32); -#else - return {}; -#endif + // (booleans, small enums, field tags, small message sizes/types). + if ((buffer[0] & 0x80) == 0) [[likely]] + return {buffer[0], 1}; + return parse_slow(buffer, len); + } + + /// Parse a varint from buffer (safe for empty buffers). + /// Returns result with consumed=0 on failure (empty buffer or truncated varint). + static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len) { + if (len == 0) + return {0, PROTO_VARINT_PARSE_FAILED}; + return parse_non_empty(buffer, len); } -#ifdef USE_API_VARINT64 protected: + // Slow path for multi-byte varints (>= 128), outlined to keep fast path small + static ProtoVarIntResult parse_slow(const uint8_t *buffer, uint32_t len) __attribute__((noinline)); + +#ifdef USE_API_VARINT64 /// Continue parsing varint bytes 4-9 with 64-bit arithmetic. - /// Separated to keep 64-bit shift code (__ashldi3 on 32-bit platforms) out of the common path. - static optional<ProtoVarInt> parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, uint32_t result32) - __attribute__((noinline)); - - public: -#endif - - constexpr uint16_t as_uint16() const { return this->value_; } - constexpr uint32_t as_uint32() const { return this->value_; } - constexpr bool as_bool() const { return this->value_; } - constexpr int32_t as_int32() const { - // Not ZigZag encoded - return static_cast<int32_t>(this->value_); - } - constexpr int32_t as_sint32() const { - // with ZigZag encoding - return decode_zigzag32(static_cast<uint32_t>(this->value_)); - } -#ifdef USE_API_VARINT64 - constexpr uint64_t as_uint64() const { return this->value_; } - constexpr int64_t as_int64() const { - // Not ZigZag encoded - return static_cast<int64_t>(this->value_); - } - constexpr int64_t as_sint64() const { - // with ZigZag encoding - return decode_zigzag64(this->value_); - } -#endif - - protected: -#ifdef USE_API_VARINT64 - uint64_t value_; -#else - uint32_t value_; + static ProtoVarIntResult parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) __attribute__((noinline)); #endif }; @@ -499,7 +465,7 @@ class ProtoDecodableMessage : public ProtoMessage { protected: ~ProtoDecodableMessage() = default; - virtual bool decode_varint(uint32_t field_id, ProtoVarInt value) { return false; } + virtual bool decode_varint(uint32_t field_id, proto_varint_value_t value) { return false; } virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; } virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; } // NOTE: decode_64bit removed - wire type 1 not supported diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 206f8f558b..b4044c362c 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -461,7 +461,7 @@ class FloatType(TypeInfo): class Int64Type(TypeInfo): cpp_type = "int64_t" default_value = "0" - decode_varint = "value.as_int64()" + decode_varint = "static_cast<int64_t>(value)" encode_func = "encode_int64" wire_type = WireType.VARINT # Uses wire type 0 @@ -481,7 +481,7 @@ class Int64Type(TypeInfo): class UInt64Type(TypeInfo): cpp_type = "uint64_t" default_value = "0" - decode_varint = "value.as_uint64()" + decode_varint = "value" encode_func = "encode_uint64" wire_type = WireType.VARINT # Uses wire type 0 @@ -501,7 +501,7 @@ class UInt64Type(TypeInfo): class Int32Type(TypeInfo): cpp_type = "int32_t" default_value = "0" - decode_varint = "value.as_int32()" + decode_varint = "static_cast<int32_t>(value)" encode_func = "encode_int32" wire_type = WireType.VARINT # Uses wire type 0 @@ -573,7 +573,7 @@ class Fixed32Type(TypeInfo): class BoolType(TypeInfo): cpp_type = "bool" default_value = "false" - decode_varint = "value.as_bool()" + decode_varint = "value != 0" encode_func = "encode_bool" wire_type = WireType.VARINT # Uses wire type 0 @@ -1151,7 +1151,7 @@ class FixedArrayBytesType(TypeInfo): class UInt32Type(TypeInfo): cpp_type = "uint32_t" default_value = "0" - decode_varint = "value.as_uint32()" + decode_varint = "value" encode_func = "encode_uint32" wire_type = WireType.VARINT # Uses wire type 0 @@ -1175,7 +1175,7 @@ class EnumType(TypeInfo): @property def decode_varint(self) -> str: - return f"static_cast<{self.cpp_type}>(value.as_uint32())" + return f"static_cast<{self.cpp_type}>(value)" default_value = "" wire_type = WireType.VARINT # Uses wire type 0 @@ -1262,7 +1262,7 @@ class SFixed64Type(TypeInfo): class SInt32Type(TypeInfo): cpp_type = "int32_t" default_value = "0" - decode_varint = "value.as_sint32()" + decode_varint = "decode_zigzag32(static_cast<uint32_t>(value))" encode_func = "encode_sint32" wire_type = WireType.VARINT # Uses wire type 0 @@ -1282,7 +1282,7 @@ class SInt32Type(TypeInfo): class SInt64Type(TypeInfo): cpp_type = "int64_t" default_value = "0" - decode_varint = "value.as_sint64()" + decode_varint = "decode_zigzag64(value)" encode_func = "encode_sint64" wire_type = WireType.VARINT # Uses wire type 0 @@ -2205,7 +2205,7 @@ def build_message_type( cpp = "" if decode_varint: - o = f"bool {desc.name}::decode_varint(uint32_t field_id, ProtoVarInt value) {{\n" + o = f"bool {desc.name}::decode_varint(uint32_t field_id, proto_varint_value_t value) {{\n" o += " switch (field_id) {\n" o += indent("\n".join(decode_varint), " ") + "\n" o += " default: return false;\n" @@ -2213,7 +2213,7 @@ def build_message_type( o += " return true;\n" o += "}\n" cpp += o - prot = "bool decode_varint(uint32_t field_id, ProtoVarInt value) override;" + prot = "bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;" protected_content.insert(0, prot) if decode_length: o = f"bool {desc.name}::decode_length(uint32_t field_id, ProtoLengthDelimited value) {{\n" From c709010c4cb04c7276f93af781dee82bf566ca85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:11:12 -1000 Subject: [PATCH 1261/2030] [api] Replace std::vector<uint8_t> with APIBuffer to skip zero-fill (#14593) --- esphome/components/api/api_buffer.cpp | 13 ++++ esphome/components/api/api_buffer.h | 67 +++++++++++++++++++ esphome/components/api/api_connection.cpp | 4 +- esphome/components/api/api_connection.h | 8 +-- esphome/components/api/api_frame_helper.h | 10 +-- .../components/api/api_frame_helper_noise.cpp | 7 +- .../components/api/api_frame_helper_noise.h | 4 +- .../api/api_frame_helper_plaintext.cpp | 4 +- esphome/components/api/api_server.h | 5 +- esphome/components/api/proto.h | 10 +-- tests/components/api/test.ln882x-ard.yaml | 5 ++ 11 files changed, 107 insertions(+), 30 deletions(-) create mode 100644 esphome/components/api/api_buffer.cpp create mode 100644 esphome/components/api/api_buffer.h create mode 100644 tests/components/api/test.ln882x-ard.yaml diff --git a/esphome/components/api/api_buffer.cpp b/esphome/components/api/api_buffer.cpp new file mode 100644 index 0000000000..6db18b0365 --- /dev/null +++ b/esphome/components/api/api_buffer.cpp @@ -0,0 +1,13 @@ +#include "api_buffer.h" + +namespace esphome::api { + +void APIBuffer::grow_(size_t n) { + auto new_data = make_buffer(n); + if (this->size_) + std::memcpy(new_data.get(), this->data_.get(), this->size_); + this->data_ = std::move(new_data); + this->capacity_ = n; +} + +} // namespace esphome::api diff --git a/esphome/components/api/api_buffer.h b/esphome/components/api/api_buffer.h new file mode 100644 index 0000000000..00801e3ee5 --- /dev/null +++ b/esphome/components/api/api_buffer.h @@ -0,0 +1,67 @@ +#pragma once + +#include <cstdint> +#include <cstring> +#include <memory> + +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +namespace esphome::api { + +/// Helper to use make_unique_for_overwrite where available (skips zero-fill), +/// falling back to make_unique on older GCC (ESP8266, LibreTiny). +inline std::unique_ptr<uint8_t[]> make_buffer(size_t n) { +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) + return std::make_unique<uint8_t[]>(n); +#else + return std::make_unique_for_overwrite<uint8_t[]>(n); +#endif +} + +/// Byte buffer that skips zero-initialization on resize(). +/// +/// std::vector<uint8_t>::resize() zero-fills new bytes via memset. For the +/// shared protobuf write buffer, every byte is overwritten by the encoder, +/// making the zero-fill pure waste. For the receive buffer, bytes are +/// overwritten by socket reads. +/// +/// Designed for bulk clear/resize/overwrite patterns. grow_() allocates +/// exactly the requested size (no growth factor) since callers resize to +/// known sizes rather than appending incrementally. +/// +/// Safe because: callers always write exactly the number of bytes they +/// resize for. In the protobuf write path, debug_check_bounds_ validates +/// writes in debug builds. +class APIBuffer { + public: + void clear() { this->size_ = 0; } + inline void reserve(size_t n) ESPHOME_ALWAYS_INLINE { + if (n > this->capacity_) + this->grow_(n); + } + inline void resize(size_t n) ESPHOME_ALWAYS_INLINE { + this->reserve(n); + this->size_ = n; // no zero-fill + } + uint8_t *data() { return this->data_.get(); } + const uint8_t *data() const { return this->data_.get(); } + size_t size() const { return this->size_; } + bool empty() const { return this->size_ == 0; } + uint8_t &operator[](size_t i) { return this->data_[i]; } + const uint8_t &operator[](size_t i) const { return this->data_[i]; } + /// Release all memory (equivalent to std::vector swap trick). + void release() { + this->data_.reset(); + this->size_ = 0; + this->capacity_ = 0; + } + + protected: + void grow_(size_t n); + std::unique_ptr<uint8_t[]> data_; + size_t size_{0}; + size_t capacity_{0}; +}; + +} // namespace esphome::api diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 7bd5d5120b..dea3ba5460 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -2016,7 +2016,7 @@ uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncode if (total_calculated_size > remaining_size) return 0; // Doesn't fit - std::vector<uint8_t> &shared_buf = conn->parent_->get_shared_buffer_ref(); + auto &shared_buf = conn->parent_->get_shared_buffer_ref(); if (conn->flags_.batch_first_message) { // First message - buffer already prepared by caller, just clear flag @@ -2184,7 +2184,7 @@ void APIConnection::process_batch_() { // Separated from process_batch_() so the single-message fast path gets a minimal // stack frame without the MAX_MESSAGES_PER_BATCH * sizeof(MessageInfo) array. -void APIConnection::process_batch_multi_(std::vector<uint8_t> &shared_buf, size_t num_items, uint8_t header_padding, +void APIConnection::process_batch_multi_(APIBuffer &shared_buf, size_t num_items, uint8_t header_padding, uint8_t footer_size) { // Ensure MessageInfo remains trivially destructible for our placement new approach static_assert(std::is_trivially_destructible<MessageInfo>::value, diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index ccb51186d6..3356511684 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -288,7 +288,7 @@ class APIConnection final : public APIServerConnectionBase { } } - void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t header_padding, size_t total_size) { + void prepare_first_message_buffer(APIBuffer &shared_buf, size_t header_padding, size_t total_size) { shared_buf.clear(); // Reserve space for header padding + message + footer // - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext) @@ -299,7 +299,7 @@ class APIConnection final : public APIServerConnectionBase { } // Convenience overload - computes frame overhead internally - void prepare_first_message_buffer(std::vector<uint8_t> &shared_buf, size_t payload_size) { + void prepare_first_message_buffer(APIBuffer &shared_buf, size_t payload_size) { const uint8_t header_padding = this->helper_->frame_header_padding(); const uint8_t footer_size = this->helper_->frame_footer_size(); this->prepare_first_message_buffer(shared_buf, header_padding, payload_size + header_padding + footer_size); @@ -687,8 +687,8 @@ class APIConnection final : public APIServerConnectionBase { bool schedule_batch_(); void process_batch_(); - void process_batch_multi_(std::vector<uint8_t> &shared_buf, size_t num_items, uint8_t header_padding, - uint8_t footer_size) __attribute__((noinline)); + void process_batch_multi_(APIBuffer &shared_buf, size_t num_items, uint8_t header_padding, uint8_t footer_size) + __attribute__((noinline)); void clear_batch_() { this->deferred_batch_.clear(); this->flags_.batch_scheduled = false; diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 151314658e..98de24501e 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -5,10 +5,10 @@ #include <memory> #include <span> #include <utility> -#include <vector> #include "esphome/core/defines.h" #ifdef USE_API +#include "esphome/components/api/api_buffer.h" #include "esphome/components/socket/socket.h" #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -178,8 +178,7 @@ class APIFrameHelper { // rx_buf_len_ tracks bytes read so far; if non-zero, we're mid-frame // and clearing would lose partially received data. if (this->rx_buf_len_ == 0) { - // Use swap trick since shrink_to_fit() is non-binding and may be ignored - std::vector<uint8_t>().swap(this->rx_buf_); + this->rx_buf_.release(); } } @@ -206,9 +205,6 @@ class APIFrameHelper { // Common socket write error handling APIError handle_socket_write_error_(); - template<typename StateEnum> - APIError write_raw_(const struct iovec *iov, int iovcnt, socket::Socket *socket, std::vector<uint8_t> &tx_buf, - const std::string &info, StateEnum &state, StateEnum failed_state); // Socket ownership (4 bytes on 32-bit, 8 bytes on 64-bit) std::unique_ptr<socket::Socket> socket_; @@ -245,7 +241,7 @@ class APIFrameHelper { // Containers (size varies, but typically 12+ bytes on 32-bit) std::array<std::unique_ptr<SendBuffer>, API_MAX_SEND_QUEUE> tx_buf_; - std::vector<uint8_t> rx_buf_; + APIBuffer rx_buf_; // Client name buffer - stores name from Hello message or initial peername char client_name_[CLIENT_INFO_NAME_MAX_LEN]{}; diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 256357ce6a..3e6ecf9dc3 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -207,9 +207,7 @@ APIError APINoiseFrameHelper::try_read_frame_() { // During handshake, rx_buf_.size() is used in prologue construction, so // the buffer must be exactly msg_size to avoid prologue mismatch.) uint16_t alloc_size = msg_size + (is_data ? RX_BUF_NULL_TERMINATOR : 0); - if (this->rx_buf_.size() != alloc_size) { - this->rx_buf_.resize(alloc_size); - } + this->rx_buf_.resize(alloc_size); if (rx_buf_len_ < msg_size) { // more data to read @@ -571,8 +569,7 @@ APIError APINoiseFrameHelper::init_handshake_() { if (aerr != APIError::OK) return aerr; // set_prologue copies it into handshakestate, so we can get rid of it now - // Use swap idiom to actually release memory (= {} only clears size, not capacity) - std::vector<uint8_t>().swap(prologue_); + prologue_.release(); err = noise_handshakestate_start(handshake_); aerr = handle_noise_error_(err, LOG_STR("noise_handshakestate_start"), APIError::HANDSHAKESTATE_SETUP_FAILED); diff --git a/esphome/components/api/api_frame_helper_noise.h b/esphome/components/api/api_frame_helper_noise.h index 183b8c8a51..83410febb2 100644 --- a/esphome/components/api/api_frame_helper_noise.h +++ b/esphome/components/api/api_frame_helper_noise.h @@ -43,8 +43,8 @@ class APINoiseFrameHelper final : public APIFrameHelper { // Reference to noise context (4 bytes on 32-bit) APINoiseContext &ctx_; - // Vector (12 bytes on 32-bit) - std::vector<uint8_t> prologue_; + // Buffer for noise handshake prologue (released after handshake) + APIBuffer prologue_; // NoiseProtocolId (size depends on implementation) NoiseProtocolId nid_; diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index 793cece3b8..007da7ef2b 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -165,9 +165,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_() { // Reserve space for body (+ null terminator so protobuf StringRef fields // can be safely null-terminated in-place after decode) - if (this->rx_buf_.size() != this->rx_header_parsed_len_ + RX_BUF_NULL_TERMINATOR) { - this->rx_buf_.resize(this->rx_header_parsed_len_ + RX_BUF_NULL_TERMINATOR); - } + this->rx_buf_.resize(this->rx_header_parsed_len_ + RX_BUF_NULL_TERMINATOR); if (rx_buf_len_ < rx_header_parsed_len_) { // more data to read diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index e5f371d8a1..69fc26cc00 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #ifdef USE_API +#include "api_buffer.h" #include "api_noise_context.h" #include "api_pb2.h" #include "api_pb2_service.h" @@ -65,7 +66,7 @@ class APIServer : public Component, void set_max_connections(uint8_t max_connections) { this->max_connections_ = max_connections; } // Get reference to shared buffer for API connections - std::vector<uint8_t> &get_shared_buffer_ref() { return shared_write_buffer_; } + APIBuffer &get_shared_buffer_ref() { return shared_write_buffer_; } #ifdef USE_API_NOISE bool save_noise_psk(psk_t psk, bool make_active = true); @@ -276,7 +277,7 @@ class APIServer : public Component, // Not pre-allocated: all send paths call prepare_first_message_buffer() which // reserves the exact needed size. Pre-allocating here would cause heap fragmentation // since the buffer would almost always reallocate on first use. - std::vector<uint8_t> shared_write_buffer_; + APIBuffer shared_write_buffer_; #ifdef USE_API_HOMEASSISTANT_STATES std::vector<HomeAssistantStateSubscription> state_subs_; #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 7050efb446..d1c955b1fb 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -1,6 +1,7 @@ #pragma once #include "api_pb2_defines.h" +#include "api_buffer.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -203,9 +204,8 @@ class Proto32Bit { class ProtoWriteBuffer { public: - ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} - ProtoWriteBuffer(std::vector<uint8_t> *buffer, size_t write_pos) - : buffer_(buffer), pos_(buffer->data() + write_pos) {} + ProtoWriteBuffer(APIBuffer *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} + ProtoWriteBuffer(APIBuffer *buffer, size_t write_pos) : buffer_(buffer), pos_(buffer->data() + write_pos) {} inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint32_t value) { if (value < 128) [[likely]] { this->debug_check_bounds_(1); @@ -340,7 +340,7 @@ class ProtoWriteBuffer { // Non-template core for encode_optional_sub_message. void encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value, void (*encode_fn)(const void *, ProtoWriteBuffer &)); - std::vector<uint8_t> *get_buffer() const { return buffer_; } + APIBuffer *get_buffer() const { return buffer_; } protected: // Slow path for encode_varint_raw values >= 128, outlined to keep fast path small @@ -353,7 +353,7 @@ class ProtoWriteBuffer { void debug_check_bounds_([[maybe_unused]] size_t bytes) {} #endif - std::vector<uint8_t> *buffer_; + APIBuffer *buffer_; uint8_t *pos_; }; diff --git a/tests/components/api/test.ln882x-ard.yaml b/tests/components/api/test.ln882x-ard.yaml new file mode 100644 index 0000000000..46c01d926f --- /dev/null +++ b/tests/components/api/test.ln882x-ard.yaml @@ -0,0 +1,5 @@ +<<: !include common.yaml + +wifi: + ssid: MySSID + password: password1 From 9dd3ec258c2f1ebf636cd7765981df2f1711c4a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:11:28 -1000 Subject: [PATCH 1262/2030] [scheduler] Replace unique_ptr with raw pointers, add leak detection (#14620) --- esphome/core/scheduler.cpp | 179 +++++++++++------- esphome/core/scheduler.h | 94 +++++---- .../fixtures/scheduler_bulk_cleanup.yaml | 1 + .../fixtures/scheduler_defer_cancel.yaml | 1 + .../scheduler_defer_cancels_regular.yaml | 1 + .../fixtures/scheduler_defer_fifo_simple.yaml | 1 + .../fixtures/scheduler_defer_stress.yaml | 1 + .../fixtures/scheduler_heap_stress.yaml | 1 + .../scheduler_internal_id_no_collision.yaml | 1 + .../fixtures/scheduler_null_name.yaml | 1 + .../fixtures/scheduler_numeric_id_test.yaml | 1 + .../scheduler_rapid_cancellation.yaml | 1 + .../fixtures/scheduler_recursive_timeout.yaml | 1 + .../fixtures/scheduler_removed_item_race.yaml | 1 + .../fixtures/scheduler_retry_test.yaml | 1 + .../scheduler_simultaneous_callbacks.yaml | 1 + .../fixtures/scheduler_string_lifetime.yaml | 1 + .../scheduler_string_name_stress.yaml | 1 + 18 files changed, 172 insertions(+), 117 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index ca560e8250..63e1006b03 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -30,11 +30,6 @@ static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5; // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; -// Prevent inlining of SchedulerItem deletion. On BK7231N (Thumb-1), GCC inlines -// ~unique_ptr<SchedulerItem> (~30 bytes each) at every destruction site. Defining -// the deleter in the .cpp file ensures a single copy of the destructor + operator delete. -void Scheduler::SchedulerItemDeleter::operator()(SchedulerItem *ptr) const noexcept { delete ptr; } - #if defined(ESPHOME_LOG_HAS_VERBOSE) || defined(ESPHOME_DEBUG_SCHEDULER) // Helper struct for formatting scheduler item names consistently in logs // Uses a stack buffer to avoid heap allocation @@ -122,8 +117,8 @@ uint32_t Scheduler::calculate_interval_offset_(uint32_t delay) { bool Scheduler::is_retry_cancelled_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id) { for (auto *container : {&this->items_, &this->to_add_}) { - for (auto &item : *container) { - if (item && this->is_item_removed_locked_(item.get()) && + for (auto *item : *container) { + if (item != nullptr && this->is_item_removed_locked_(item) && this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, SchedulerItem::TIMEOUT, /* match_retry= */ true, /* skip_removed= */ false)) { return true; @@ -147,17 +142,31 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type return; } - // Take lock early to protect scheduler_item_pool_ access + // Take lock early to protect scheduler_item_pool_ access and retry-cancelled check LockGuard guard{this->lock_}; + // For retries, check if there's a cancelled timeout first - before allocating an item. + // Skip check for anonymous retries (STATIC_STRING with nullptr) - they can't be cancelled by name + // Skip check for defer (delay=0) - deferred retries bypass the cancellation check + if (is_retry && delay != 0 && (name_type != NameType::STATIC_STRING || static_name != nullptr) && + type == SchedulerItem::TIMEOUT && + this->is_retry_cancelled_locked_(component, name_type, static_name, hash_or_id)) { +#ifdef ESPHOME_DEBUG_SCHEDULER + SchedulerNameLog skip_name_log; + ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", + skip_name_log.format(name_type, static_name, hash_or_id)); +#endif + return; + } + // Create and populate the scheduler item - auto item = this->get_item_from_pool_locked_(); + SchedulerItem *item = this->get_item_from_pool_locked_(); item->component = component; item->set_name(name_type, static_name, hash_or_id); item->type = type; item->callback = std::move(func); // Reset remove flag - recycled items may have been cancelled (remove=true) in previous use - this->set_item_removed_(item.get(), false); + this->set_item_removed_(item, false); item->is_retry = is_retry; // Determine target container: defer_queue_ for deferred items, to_add_ for everything else. @@ -193,29 +202,15 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type } #ifdef ESPHOME_DEBUG_SCHEDULER - this->debug_log_timer_(item.get(), name_type, static_name, hash_or_id, type, delay, now_64); + this->debug_log_timer_(item, name_type, static_name, hash_or_id, type, delay, now_64); #endif /* ESPHOME_DEBUG_SCHEDULER */ - - // For retries, check if there's a cancelled timeout first - // Skip check for anonymous retries (STATIC_STRING with nullptr) - they can't be cancelled by name - if (is_retry && (name_type != NameType::STATIC_STRING || static_name != nullptr) && - type == SchedulerItem::TIMEOUT && - this->is_retry_cancelled_locked_(component, name_type, static_name, hash_or_id)) { - // Skip scheduling - the retry was cancelled -#ifdef ESPHOME_DEBUG_SCHEDULER - SchedulerNameLog skip_name_log; - ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", - skip_name_log.format(name_type, static_name, hash_or_id)); -#endif - return; - } } // Common epilogue: atomic cancel-and-add (unless skip_cancel is true) if (!skip_cancel) { this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } - target->push_back(std::move(item)); + target->push_back(item); } void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, @@ -395,7 +390,7 @@ optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) { if (this->cleanup_() == 0) return {}; - auto &item = this->items_[0]; + SchedulerItem *item = this->items_[0]; const auto now_64 = this->millis_64_from_(now); const uint64_t next_exec = item->get_next_execution(); if (next_exec < now_64) @@ -414,13 +409,13 @@ void Scheduler::full_cleanup_removed_items_() { // Compact in-place: move valid items forward, recycle removed ones size_t write = 0; for (size_t read = 0; read < this->items_.size(); ++read) { - if (!is_item_removed_locked_(this->items_[read].get())) { + if (!is_item_removed_locked_(this->items_[read])) { if (write != read) { - this->items_[write] = std::move(this->items_[read]); + this->items_[write] = this->items_[read]; } ++write; } else { - this->recycle_item_main_loop_(std::move(this->items_[read])); + this->recycle_item_main_loop_(this->items_[read]); } } this->items_.erase(this->items_.begin() + write, this->items_.end()); @@ -444,7 +439,7 @@ void Scheduler::compact_defer_queue_locked_() { // and recycled on the next loop iteration. size_t remaining = this->defer_queue_.size() - this->defer_queue_front_; for (size_t i = 0; i < remaining; i++) { - this->defer_queue_[i] = std::move(this->defer_queue_[this->defer_queue_front_ + i]); + this->defer_queue_[i] = this->defer_queue_[this->defer_queue_front_ + i]; } // Use erase() instead of resize() to avoid instantiating _M_default_append // (saves ~156 bytes flash). Erasing from the end is O(1) - no shifting needed. @@ -469,26 +464,26 @@ void HOT Scheduler::call(uint32_t now) { if (now_64 - last_print > 2000) { last_print = now_64; - std::vector<SchedulerItemPtr> old_items; + std::vector<SchedulerItem *> old_items; ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64, this->items_.size(), this->scheduler_item_pool_.size(), now_64); // Cleanup before debug output this->cleanup_(); while (!this->items_.empty()) { - SchedulerItemPtr item; + SchedulerItem *item; { LockGuard guard{this->lock_}; item = this->pop_raw_locked_(); } SchedulerNameLog name_log; - bool is_cancelled = is_item_removed_(item.get()); + bool is_cancelled = is_item_removed_(item); ESP_LOGD(TAG, " %s '%s/%s' interval=%" PRIu32 " next_execution in %" PRIu64 "ms at %" PRIu64 "%s", item->get_type_str(), LOG_STR_ARG(item->get_source()), name_log.format(item->get_name_type(), item->get_name(), item->get_name_hash_or_id()), item->interval, item->get_next_execution() - now_64, item->get_next_execution(), is_cancelled ? " [CANCELLED]" : ""); - old_items.push_back(std::move(item)); + old_items.push_back(item); } ESP_LOGD(TAG, "\n"); @@ -512,7 +507,7 @@ void HOT Scheduler::call(uint32_t now) { } while (!this->items_.empty()) { // Don't copy-by value yet - auto &item = this->items_[0]; + SchedulerItem *item = this->items_[0]; if (item->get_next_execution() > now_64) { // Not reached timeout yet, done for this call break; @@ -532,7 +527,7 @@ void HOT Scheduler::call(uint32_t now) { // Multi-threaded platforms without atomics: must take lock to safely read remove flag { LockGuard guard{this->lock_}; - if (is_item_removed_locked_(item.get())) { + if (is_item_removed_locked_(item)) { this->recycle_item_main_loop_(this->pop_raw_locked_()); this->to_remove_--; continue; @@ -540,7 +535,7 @@ void HOT Scheduler::call(uint32_t now) { } #else // Single-threaded or multi-threaded with atomics: can check without lock - if (is_item_removed_(item.get())) { + if (is_item_removed_(item)) { LockGuard guard{this->lock_}; this->recycle_item_main_loop_(this->pop_raw_locked_()); this->to_remove_--; @@ -561,18 +556,18 @@ void HOT Scheduler::call(uint32_t now) { // Warning: During callback(), a lot of stuff can happen, including: // - timeouts/intervals get added, potentially invalidating vector pointers // - timeouts/intervals get cancelled - now = this->execute_item_(item.get(), now); + now = this->execute_item_(item, now); LockGuard guard{this->lock_}; // Only pop after function call, this ensures we were reachable // during the function call and know if we were cancelled. - auto executed_item = this->pop_raw_locked_(); + SchedulerItem *executed_item = this->pop_raw_locked_(); - if (this->is_item_removed_locked_(executed_item.get())) { + if (this->is_item_removed_locked_(executed_item)) { // We were removed/cancelled in the function call, recycle and continue this->to_remove_--; - this->recycle_item_main_loop_(std::move(executed_item)); + this->recycle_item_main_loop_(executed_item); continue; } @@ -580,10 +575,10 @@ void HOT Scheduler::call(uint32_t now) { executed_item->set_next_execution(now_64 + executed_item->interval); // Add new item directly to to_add_ // since we have the lock held - this->to_add_.push_back(std::move(executed_item)); + this->to_add_.push_back(executed_item); } else { // Timeout completed - recycle it - this->recycle_item_main_loop_(std::move(executed_item)); + this->recycle_item_main_loop_(executed_item); } has_added_items |= !this->to_add_.empty(); @@ -592,17 +587,33 @@ void HOT Scheduler::call(uint32_t now) { if (has_added_items) { this->process_to_add(); } + +#ifdef ESPHOME_DEBUG_SCHEDULER + // Verify no items were leaked during this call() cycle. + // All items must be in items_, to_add_, defer_queue_, or the pool. + // Safe to check here because: + // - process_defer_queue_ has already run its cleanup_defer_queue_locked_(), + // so defer_queue_ contains no nullptr slots inflating the count. + // - The while loop above has finished, so no items are held in local variables; + // every item has been returned to a container (items_, to_add_, or pool). + // Lock needed to get a consistent snapshot of all containers. + { + LockGuard guard{this->lock_}; + this->debug_verify_no_leak_(); + } +#endif } void HOT Scheduler::process_to_add() { LockGuard guard{this->lock_}; - for (auto &it : this->to_add_) { - if (is_item_removed_locked_(it.get())) { + for (auto *&it : this->to_add_) { + if (is_item_removed_locked_(it)) { // Recycle cancelled items - this->recycle_item_main_loop_(std::move(it)); + this->recycle_item_main_loop_(it); + it = nullptr; continue; } - this->items_.push_back(std::move(it)); + this->items_.push_back(it); std::push_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); } this->to_add_.clear(); @@ -628,20 +639,18 @@ size_t HOT Scheduler::cleanup_() { // leading to race conditions LockGuard guard{this->lock_}; while (!this->items_.empty()) { - auto &item = this->items_[0]; - if (!this->is_item_removed_locked_(item.get())) + SchedulerItem *item = this->items_[0]; + if (!this->is_item_removed_locked_(item)) break; this->to_remove_--; this->recycle_item_main_loop_(this->pop_raw_locked_()); } return this->items_.size(); } -Scheduler::SchedulerItemPtr HOT Scheduler::pop_raw_locked_() { +Scheduler::SchedulerItem *HOT Scheduler::pop_raw_locked_() { std::pop_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); - // Move the item out before popping - this is the item that was at the front of the heap - auto item = std::move(this->items_.back()); - + SchedulerItem *item = this->items_.back(); this->items_.pop_back(); return item; } @@ -699,7 +708,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type return total_cancelled > 0; } -bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) { +bool HOT Scheduler::SchedulerItem::cmp(SchedulerItem *a, SchedulerItem *b) { // High bits are almost always equal (change only on 32-bit rollover ~49 days) // Optimize for common case: check low bits first when high bits are equal return (a->next_execution_high_ == b->next_execution_high_) ? (a->next_execution_low_ > b->next_execution_low_) @@ -710,23 +719,26 @@ bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const Schedule // IMPORTANT: Caller must hold the scheduler lock before calling this function. // This protects scheduler_item_pool_ from concurrent access by other threads // that may be acquiring items from the pool in set_timer_common_(). -void Scheduler::recycle_item_main_loop_(SchedulerItemPtr item) { - if (!item) +void Scheduler::recycle_item_main_loop_(SchedulerItem *item) { + if (item == nullptr) return; if (this->scheduler_item_pool_.size() < MAX_POOL_SIZE) { // Clear callback to release captured resources item->callback = nullptr; - this->scheduler_item_pool_.push_back(std::move(item)); + this->scheduler_item_pool_.push_back(item); #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Recycled item to pool (pool size now: %zu)", this->scheduler_item_pool_.size()); #endif } else { #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Pool full (size: %zu), deleting item", this->scheduler_item_pool_.size()); +#endif + delete item; +#ifdef ESPHOME_DEBUG_SCHEDULER + this->debug_live_items_--; #endif } - // else: unique_ptr will delete the item when it goes out of scope } #ifdef ESPHOME_DEBUG_SCHEDULER @@ -753,21 +765,54 @@ void Scheduler::debug_log_timer_(const SchedulerItem *item, NameType name_type, // Helper to get or create a scheduler item from the pool // IMPORTANT: Caller must hold the scheduler lock before calling this function. -Scheduler::SchedulerItemPtr Scheduler::get_item_from_pool_locked_() { - SchedulerItemPtr item; +Scheduler::SchedulerItem *Scheduler::get_item_from_pool_locked_() { if (!this->scheduler_item_pool_.empty()) { - item = std::move(this->scheduler_item_pool_.back()); + SchedulerItem *item = this->scheduler_item_pool_.back(); this->scheduler_item_pool_.pop_back(); #ifdef ESPHOME_DEBUG_SCHEDULER ESP_LOGD(TAG, "Reused item from pool (pool size now: %zu)", this->scheduler_item_pool_.size()); #endif - } else { - item = SchedulerItemPtr(new SchedulerItem()); -#ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Allocated new item (pool empty)"); -#endif + return item; } +#ifdef ESPHOME_DEBUG_SCHEDULER + ESP_LOGD(TAG, "Allocated new item (pool empty)"); +#endif + auto *item = new SchedulerItem(); +#ifdef ESPHOME_DEBUG_SCHEDULER + this->debug_live_items_++; +#endif return item; } +#ifdef ESPHOME_DEBUG_SCHEDULER +bool Scheduler::debug_verify_no_leak_() const { + // Invariant: every live SchedulerItem must be in exactly one container. + // debug_live_items_ tracks allocations minus deletions. + size_t accounted = this->items_.size() + this->to_add_.size() + this->scheduler_item_pool_.size(); +#ifndef ESPHOME_THREAD_SINGLE + accounted += this->defer_queue_.size(); +#endif + if (accounted != this->debug_live_items_) { + ESP_LOGE(TAG, + "SCHEDULER LEAK DETECTED: live=%" PRIu32 " but accounted=%" PRIu32 " (items=%" PRIu32 " to_add=%" PRIu32 + " pool=%" PRIu32 +#ifndef ESPHOME_THREAD_SINGLE + " defer=%" PRIu32 +#endif + ")", + static_cast<uint32_t>(this->debug_live_items_), static_cast<uint32_t>(accounted), + static_cast<uint32_t>(this->items_.size()), static_cast<uint32_t>(this->to_add_.size()), + static_cast<uint32_t>(this->scheduler_item_pool_.size()) +#ifndef ESPHOME_THREAD_SINGLE + , + static_cast<uint32_t>(this->defer_queue_.size()) +#endif + ); + assert(false); + return false; + } + return true; +} +#endif + } // namespace esphome diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index eb6cea4f37..0476513bb9 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -2,7 +2,6 @@ #include "esphome/core/defines.h" #include <cstring> -#include <memory> #include <string> #include <vector> #ifdef ESPHOME_THREAD_MULTI_ATOMICS @@ -144,19 +143,6 @@ class Scheduler { }; protected: - struct SchedulerItem; - - // Custom deleter for SchedulerItem unique_ptr that prevents the compiler from - // inlining the destructor at every destruction site. On BK7231N (Thumb-1), GCC - // inlines ~unique_ptr<SchedulerItem> (~30 bytes: null check + ~std::function + - // operator delete) at every destruction site, while ESP32/ESP8266/RTL8720CF outline - // it into a single helper. This noinline deleter ensures only one copy exists. - // operator() is defined in scheduler.cpp to prevent inlining. - struct SchedulerItemDeleter { - void operator()(SchedulerItem *ptr) const noexcept; - }; - using SchedulerItemPtr = std::unique_ptr<SchedulerItem, SchedulerItemDeleter>; - struct SchedulerItem { // Ordered by size to minimize padding Component *component; @@ -219,14 +205,14 @@ class Scheduler { name_.static_name = nullptr; } - // Destructor - no dynamic memory to clean up + // Destructor - no dynamic memory to clean up (callback's std::function handles its own) ~SchedulerItem() = default; // Delete copy operations to prevent accidental copies SchedulerItem(const SchedulerItem &) = delete; SchedulerItem &operator=(const SchedulerItem &) = delete; - // Delete move operations: SchedulerItem objects are only managed via unique_ptr, never moved directly + // Delete move operations: SchedulerItem objects are managed via raw pointers, never moved directly SchedulerItem(SchedulerItem &&) = delete; SchedulerItem &operator=(SchedulerItem &&) = delete; @@ -250,7 +236,7 @@ class Scheduler { name_type_ = type; } - static bool cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b); + static bool cmp(SchedulerItem *a, SchedulerItem *b); // Note: We use 48 bits total (32 + 16), stored in a 64-bit value for API compatibility. // The upper 16 bits of the 64-bit value are always zero, which is fine since @@ -301,12 +287,13 @@ class Scheduler { // Returns the number of items remaining after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). size_t cleanup_(); - // Remove and return the front item from the heap + // Remove and return the front item from the heap as a raw pointer. + // Caller takes ownership and must either recycle or delete the item. // IMPORTANT: Caller must hold the scheduler lock before calling this function. - SchedulerItemPtr pop_raw_locked_(); + SchedulerItem *pop_raw_locked_(); // Get or create a scheduler item from the pool // IMPORTANT: Caller must hold the scheduler lock before calling this function. - SchedulerItemPtr get_item_from_pool_locked_(); + SchedulerItem *get_item_from_pool_locked_(); private: // Helper to cancel items - must be called with lock held @@ -330,19 +317,16 @@ class Scheduler { // Helper function to check if item matches criteria for cancellation // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // IMPORTANT: Must be called with scheduler lock held - inline bool HOT matches_item_locked_(const SchedulerItemPtr &item, Component *component, NameType name_type, + inline bool HOT matches_item_locked_(SchedulerItem *item, Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry, bool skip_removed = true) const { // THREAD SAFETY: Check for nullptr first to prevent LoadProhibited crashes. On multi-threaded - // platforms, items can be moved out of defer_queue_ during processing, leaving nullptr entries. - // PR #11305 added nullptr checks in callers (mark_matching_items_removed_locked_()), but this check - // provides defense-in-depth: helper - // functions should be safe regardless of caller behavior. + // platforms, items can be nulled in defer_queue_ during processing. // Fixes: https://github.com/esphome/esphome/issues/11940 - if (!item) + if (item == nullptr) return false; - if (item->component != component || item->type != type || - (skip_removed && this->is_item_removed_locked_(item.get())) || (match_retry && !item->is_retry)) { + if (item->component != component || item->type != type || (skip_removed && this->is_item_removed_locked_(item)) || + (match_retry && !item->is_retry)) { return false; } // Name type must match @@ -364,10 +348,12 @@ class Scheduler { } // Helper to recycle a SchedulerItem back to the pool. + // Takes a raw pointer — caller transfers ownership. The item is either added to the + // pool or deleted if the pool is full. // IMPORTANT: Only call from main loop context! Recycling clears the callback, // so calling from another thread while the callback is executing causes use-after-free. // IMPORTANT: Caller must hold the scheduler lock before calling this function. - void recycle_item_main_loop_(SchedulerItemPtr item); + void recycle_item_main_loop_(SchedulerItem *item); // Helper to perform full cleanup when too many items are cancelled void full_cleanup_removed_items_(); @@ -423,27 +409,28 @@ class Scheduler { // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), // recycle each item after re-acquiring the lock for the next iteration (N+1 total). // The lock is held across: recycle → loop condition → move-out, then released for execution. - SchedulerItemPtr item; + SchedulerItem *item; this->lock_.lock(); while (this->defer_queue_front_ < defer_queue_end) { - // SAFETY: Moving out the unique_ptr leaves a nullptr in the vector at defer_queue_front_. - // This is intentional and safe because: + // Take ownership of the item, leaving nullptr in the vector slot. + // This is safe because: // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_) // 3. The lock protects concurrent access, but the nullptr remains until cleanup - item = std::move(this->defer_queue_[this->defer_queue_front_]); + item = this->defer_queue_[this->defer_queue_front_]; + this->defer_queue_[this->defer_queue_front_] = nullptr; this->defer_queue_front_++; this->lock_.unlock(); // Execute callback without holding lock to prevent deadlocks // if the callback tries to call defer() again - if (!this->should_skip_item_(item.get())) { - now = this->execute_item_(item.get(), now); + if (!this->should_skip_item_(item)) { + now = this->execute_item_(item, now); } this->lock_.lock(); - this->recycle_item_main_loop_(std::move(item)); + this->recycle_item_main_loop_(item); } // Clean up the queue (lock already held from last recycle or initial acquisition) this->cleanup_defer_queue_locked_(); @@ -523,18 +510,14 @@ class Scheduler { // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal // IMPORTANT: Must be called with scheduler lock held - __attribute__((noinline)) size_t mark_matching_items_removed_locked_(std::vector<SchedulerItemPtr> &container, + __attribute__((noinline)) size_t mark_matching_items_removed_locked_(std::vector<SchedulerItem *> &container, Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { size_t count = 0; - for (auto &item : container) { - // Skip nullptr items (can happen in defer_queue_ when items are being processed) - // The defer_queue_ uses index-based processing: items are std::moved out but left in the - // vector as nullptr until cleanup. Even though this function is called with lock held, - // the vector can still contain nullptr items from the processing loop. This check prevents crashes. - if (item && this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { - this->set_item_removed_(item.get(), true); + for (auto *item : container) { + if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { + this->set_item_removed_(item, true); count++; } } @@ -542,15 +525,15 @@ class Scheduler { } Mutex lock_; - std::vector<SchedulerItemPtr> items_; - std::vector<SchedulerItemPtr> to_add_; + std::vector<SchedulerItem *> items_; + std::vector<SchedulerItem *> to_add_; #ifndef ESPHOME_THREAD_SINGLE // Single-core platforms don't need the defer queue and save ~32 bytes of RAM // Using std::vector instead of std::deque avoids 512-byte chunked allocations // Index tracking avoids O(n) erase() calls when draining the queue each loop - std::vector<SchedulerItemPtr> defer_queue_; // FIFO queue for defer() calls - size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) -#endif /* ESPHOME_THREAD_SINGLE */ + std::vector<SchedulerItem *> defer_queue_; // FIFO queue for defer() calls + size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) +#endif /* ESPHOME_THREAD_SINGLE */ uint32_t to_remove_{0}; // Memory pool for recycling SchedulerItem objects to reduce heap churn. @@ -561,7 +544,18 @@ class Scheduler { // - The pool significantly reduces heap fragmentation which is critical because heap allocation/deallocation // can stall the entire system, causing timing issues and dropped events for any components that need // to synchronize between tasks (see https://github.com/esphome/backlog/issues/52) - std::vector<SchedulerItemPtr> scheduler_item_pool_; + std::vector<SchedulerItem *> scheduler_item_pool_; + +#ifdef ESPHOME_DEBUG_SCHEDULER + // Leak detection: tracks total live SchedulerItem allocations. + // Invariant: debug_live_items_ == items_.size() + to_add_.size() + defer_queue_.size() + scheduler_item_pool_.size() + // Verified periodically in call() to catch leaks early. + size_t debug_live_items_{0}; + + // Verify the scheduler memory invariant: all allocated items are accounted for. + // Returns true if no leak detected. Logs an error and asserts on failure. + bool debug_verify_no_leak_() const; +#endif }; } // namespace esphome diff --git a/tests/integration/fixtures/scheduler_bulk_cleanup.yaml b/tests/integration/fixtures/scheduler_bulk_cleanup.yaml index de876da8c4..3d2c47a0de 100644 --- a/tests/integration/fixtures/scheduler_bulk_cleanup.yaml +++ b/tests/integration/fixtures/scheduler_bulk_cleanup.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-bulk-cleanup external_components: diff --git a/tests/integration/fixtures/scheduler_defer_cancel.yaml b/tests/integration/fixtures/scheduler_defer_cancel.yaml index 9e3f927c33..92ae0062ac 100644 --- a/tests/integration/fixtures/scheduler_defer_cancel.yaml +++ b/tests/integration/fixtures/scheduler_defer_cancel.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-defer-cancel host: diff --git a/tests/integration/fixtures/scheduler_defer_cancels_regular.yaml b/tests/integration/fixtures/scheduler_defer_cancels_regular.yaml index fb6b1791dc..cf7f6ec733 100644 --- a/tests/integration/fixtures/scheduler_defer_cancels_regular.yaml +++ b/tests/integration/fixtures/scheduler_defer_cancels_regular.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-defer-cancel-regular host: diff --git a/tests/integration/fixtures/scheduler_defer_fifo_simple.yaml b/tests/integration/fixtures/scheduler_defer_fifo_simple.yaml index 7384082ac2..f69e5c6c67 100644 --- a/tests/integration/fixtures/scheduler_defer_fifo_simple.yaml +++ b/tests/integration/fixtures/scheduler_defer_fifo_simple.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-defer-fifo-simple host: diff --git a/tests/integration/fixtures/scheduler_defer_stress.yaml b/tests/integration/fixtures/scheduler_defer_stress.yaml index 0d9c1d1405..70eac01daf 100644 --- a/tests/integration/fixtures/scheduler_defer_stress.yaml +++ b/tests/integration/fixtures/scheduler_defer_stress.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-defer-stress-test external_components: diff --git a/tests/integration/fixtures/scheduler_heap_stress.yaml b/tests/integration/fixtures/scheduler_heap_stress.yaml index d4d340b68b..486a5d1276 100644 --- a/tests/integration/fixtures/scheduler_heap_stress.yaml +++ b/tests/integration/fixtures/scheduler_heap_stress.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-heap-stress-test external_components: diff --git a/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml b/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml index 46dbb8e728..e696e99efa 100644 --- a/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml +++ b/tests/integration/fixtures/scheduler_internal_id_no_collision.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-internal-id-test on_boot: priority: -100 diff --git a/tests/integration/fixtures/scheduler_null_name.yaml b/tests/integration/fixtures/scheduler_null_name.yaml index 42eaacdd43..d5488761d6 100644 --- a/tests/integration/fixtures/scheduler_null_name.yaml +++ b/tests/integration/fixtures/scheduler_null_name.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-null-name host: diff --git a/tests/integration/fixtures/scheduler_numeric_id_test.yaml b/tests/integration/fixtures/scheduler_numeric_id_test.yaml index 1669f026f5..25decf20f5 100644 --- a/tests/integration/fixtures/scheduler_numeric_id_test.yaml +++ b/tests/integration/fixtures/scheduler_numeric_id_test.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-numeric-id-test on_boot: priority: -100 diff --git a/tests/integration/fixtures/scheduler_rapid_cancellation.yaml b/tests/integration/fixtures/scheduler_rapid_cancellation.yaml index 4824654c5c..530b8241f5 100644 --- a/tests/integration/fixtures/scheduler_rapid_cancellation.yaml +++ b/tests/integration/fixtures/scheduler_rapid_cancellation.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: sched-rapid-cancel-test external_components: diff --git a/tests/integration/fixtures/scheduler_recursive_timeout.yaml b/tests/integration/fixtures/scheduler_recursive_timeout.yaml index f1168802f6..66b6f4b19b 100644 --- a/tests/integration/fixtures/scheduler_recursive_timeout.yaml +++ b/tests/integration/fixtures/scheduler_recursive_timeout.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: sched-recursive-timeout external_components: diff --git a/tests/integration/fixtures/scheduler_removed_item_race.yaml b/tests/integration/fixtures/scheduler_removed_item_race.yaml index 2f8a7fb987..55d2197d7c 100644 --- a/tests/integration/fixtures/scheduler_removed_item_race.yaml +++ b/tests/integration/fixtures/scheduler_removed_item_race.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-removed-item-race host: diff --git a/tests/integration/fixtures/scheduler_retry_test.yaml b/tests/integration/fixtures/scheduler_retry_test.yaml index ffe9082a69..cdf71152bd 100644 --- a/tests/integration/fixtures/scheduler_retry_test.yaml +++ b/tests/integration/fixtures/scheduler_retry_test.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-retry-test on_boot: priority: -100 diff --git a/tests/integration/fixtures/scheduler_simultaneous_callbacks.yaml b/tests/integration/fixtures/scheduler_simultaneous_callbacks.yaml index 446ee7fdc0..c15edc3ffd 100644 --- a/tests/integration/fixtures/scheduler_simultaneous_callbacks.yaml +++ b/tests/integration/fixtures/scheduler_simultaneous_callbacks.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: sched-simul-callbacks-test external_components: diff --git a/tests/integration/fixtures/scheduler_string_lifetime.yaml b/tests/integration/fixtures/scheduler_string_lifetime.yaml index ebd5052b8b..5ae5a1914e 100644 --- a/tests/integration/fixtures/scheduler_string_lifetime.yaml +++ b/tests/integration/fixtures/scheduler_string_lifetime.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: scheduler-string-lifetime-test external_components: diff --git a/tests/integration/fixtures/scheduler_string_name_stress.yaml b/tests/integration/fixtures/scheduler_string_name_stress.yaml index d1ef55c8d5..8f68d1d102 100644 --- a/tests/integration/fixtures/scheduler_string_name_stress.yaml +++ b/tests/integration/fixtures/scheduler_string_name_stress.yaml @@ -1,4 +1,5 @@ esphome: + debug_scheduler: true # Enable scheduler leak detection name: sched-string-name-stress external_components: From 89bb5d9e42fcc911a73af225af78390a96ad8e5f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:11:45 -1000 Subject: [PATCH 1263/2030] [core] Require explicit synchronous= for register_action (#14606) --- esphome/automation.py | 38 ++++++++++--- esphome/components/ags10/sensor.py | 2 + esphome/components/aic3204/audio_dac.py | 5 +- .../alarm_control_panel/__init__.py | 40 +++++++++++--- esphome/components/animation/__init__.py | 12 +++-- esphome/components/api/__init__.py | 1 + esphome/components/at581x/__init__.py | 2 + esphome/components/audio_adc/__init__.py | 5 +- esphome/components/audio_dac/__init__.py | 13 +++-- esphome/components/binary_sensor/__init__.py | 1 + esphome/components/bl0906/sensor.py | 1 + esphome/components/ble_client/__init__.py | 22 ++++++-- esphome/components/bm8563/time.py | 3 ++ esphome/components/canbus/__init__.py | 1 + esphome/components/cc1101/__init__.py | 27 +++++++--- esphome/components/climate/__init__.py | 5 +- esphome/components/cm1106/sensor.py | 1 + esphome/components/cs5460a/sensor.py | 1 + esphome/components/datetime/__init__.py | 3 ++ esphome/components/deep_sleep/__init__.py | 7 ++- esphome/components/dfplayer/__init__.py | 16 ++++++ .../components/dfrobot_sen0395/__init__.py | 2 + esphome/components/display/__init__.py | 3 ++ .../components/display_menu_base/__init__.py | 33 +++++++++--- esphome/components/ds1307/time.py | 2 + esphome/components/duty_time/sensor.py | 12 +++-- esphome/components/esp32_ble/__init__.py | 8 ++- .../components/esp32_ble_server/__init__.py | 3 ++ .../components/esp32_ble_tracker/__init__.py | 2 + esphome/components/esp8266_pwm/output.py | 1 + esphome/components/esp_ldo/__init__.py | 1 + esphome/components/espnow/__init__.py | 5 ++ esphome/components/event/__init__.py | 4 +- esphome/components/ezo_pmp/__init__.py | 28 ++++++++-- esphome/components/fan/__init__.py | 1 + .../components/fingerprint_grow/__init__.py | 6 +++ .../components/grove_tb6612fng/__init__.py | 6 +++ esphome/components/haier/climate.py | 49 +++++++++++++---- esphome/components/hbridge/fan/__init__.py | 1 + esphome/components/hc8/sensor.py | 5 +- esphome/components/hdc302x/sensor.py | 10 +++- esphome/components/hlk_fm22x/__init__.py | 5 ++ esphome/components/http_request/__init__.py | 15 ++++-- .../components/http_request/ota/__init__.py | 1 + esphome/components/htu21d/sensor.py | 2 + esphome/components/hub75/display.py | 1 + esphome/components/integration/sensor.py | 2 + esphome/components/key_collector/__init__.py | 2 + esphome/components/ld2410/__init__.py | 5 +- esphome/components/ledc/output.py | 1 + esphome/components/libretiny_pwm/output.py | 1 + esphome/components/light/automation.py | 5 +- esphome/components/lightwaverf/__init__.py | 1 + esphome/components/lock/__init__.py | 12 +++-- esphome/components/logger/__init__.py | 1 + esphome/components/lvgl/automation.py | 27 ++++++++-- esphome/components/lvgl/styles.py | 1 + esphome/components/lvgl/types.py | 1 + esphome/components/lvgl/widgets/animimg.py | 2 + .../components/lvgl/widgets/buttonmatrix.py | 1 + esphome/components/lvgl/widgets/canvas.py | 8 +++ esphome/components/lvgl/widgets/meter.py | 1 + esphome/components/lvgl/widgets/page.py | 3 ++ esphome/components/lvgl/widgets/spinbox.py | 2 + esphome/components/lvgl/widgets/tabview.py | 1 + esphome/components/lvgl/widgets/tileview.py | 1 + esphome/components/max17043/sensor.py | 4 +- esphome/components/max6956/__init__.py | 2 + esphome/components/max7219digit/display.py | 35 +++++++++--- esphome/components/media_player/__init__.py | 7 ++- esphome/components/mhz19/sensor.py | 20 +++++-- .../components/micro_wake_word/__init__.py | 13 ++++- esphome/components/microphone/__init__.py | 22 +++++--- esphome/components/midea/climate.py | 4 +- esphome/components/mixer/speaker/__init__.py | 1 + esphome/components/mqtt/__init__.py | 2 + esphome/components/nau7802/sensor.py | 3 ++ .../nextion/binary_sensor/__init__.py | 1 + esphome/components/nextion/display.py | 1 + esphome/components/nextion/sensor/__init__.py | 1 + esphome/components/nextion/switch/__init__.py | 1 + .../nextion/text_sensor/__init__.py | 1 + esphome/components/online_image/__init__.py | 9 +++- esphome/components/output/__init__.py | 2 + esphome/components/pcf85063/time.py | 2 + esphome/components/pcf8563/time.py | 2 + esphome/components/pid/climate.py | 3 ++ .../components/pipsolar/output/__init__.py | 1 + esphome/components/pmwcs3/sensor.py | 3 ++ esphome/components/pn7150/__init__.py | 43 +++++++++++---- esphome/components/pn7160/__init__.py | 43 +++++++++++---- esphome/components/pulse_counter/sensor.py | 1 + esphome/components/pulse_meter/sensor.py | 1 + esphome/components/pzemac/sensor.py | 1 + esphome/components/pzemdc/sensor.py | 1 + esphome/components/remote_base/__init__.py | 5 +- .../components/remote_transmitter/__init__.py | 5 +- esphome/components/rf_bridge/__init__.py | 22 ++++++-- esphome/components/rotary_encoder/sensor.py | 1 + esphome/components/rp2040_pwm/output.py | 1 + esphome/components/rtttl/__init__.py | 2 + esphome/components/rx8130/time.py | 2 + esphome/components/safe_mode/__init__.py | 1 + esphome/components/scd30/sensor.py | 1 + esphome/components/scd4x/sensor.py | 6 ++- esphome/components/script/__init__.py | 1 + esphome/components/sen5x/sensor.py | 5 +- esphome/components/senseair/sensor.py | 17 ++++-- esphome/components/servo/__init__.py | 2 + esphome/components/sim800l/__init__.py | 16 ++++-- esphome/components/sound_level/sensor.py | 8 ++- esphome/components/speaker/__init__.py | 23 +++++--- .../speaker/media_player/__init__.py | 1 + esphome/components/sprinkler/__init__.py | 53 +++++++++++++++---- esphome/components/sps30/sensor.py | 15 ++++-- esphome/components/stepper/__init__.py | 5 ++ esphome/components/sx126x/__init__.py | 30 ++++++++--- esphome/components/sx127x/__init__.py | 30 ++++++++--- .../template/binary_sensor/__init__.py | 1 + esphome/components/template/cover/__init__.py | 1 + esphome/components/template/lock/__init__.py | 1 + .../components/template/sensor/__init__.py | 1 + .../components/template/switch/__init__.py | 1 + .../template/text_sensor/__init__.py | 1 + esphome/components/template/valve/__init__.py | 1 + .../template/water_heater/__init__.py | 1 + esphome/components/tm1651/__init__.py | 12 ++++- esphome/components/uart/__init__.py | 1 + esphome/components/udp/__init__.py | 1 + esphome/components/ufire_ec/sensor.py | 2 + esphome/components/ufire_ise/sensor.py | 3 ++ esphome/components/update/__init__.py | 2 + esphome/components/valve/__init__.py | 20 +++++-- .../components/voice_assistant/__init__.py | 6 ++- esphome/components/wifi/__init__.py | 9 +++- esphome/components/wireguard/__init__.py | 2 + esphome/components/zigbee/__init__.py | 1 + 137 files changed, 852 insertions(+), 187 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index d9b8b2ec57..36ab30b654 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -1,3 +1,5 @@ +import logging + import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( @@ -57,22 +59,41 @@ def maybe_conf(conf, *validators): return validate +_LOGGER = logging.getLogger(__name__) + + def register_action( name: str, action_type: MockObjClass, schema: cv.Schema, *, - synchronous: bool = False, + synchronous: bool | None = None, ): """Register an action type. - Actions default to ``synchronous=False`` (safe default), meaning string - arguments use owning std::string to prevent dangling references. + All callers must pass ``synchronous`` explicitly. - Set ``synchronous=True`` only for actions that complete synchronously - and never store trigger arguments for later execution. This allows - the code generator to use non-owning StringRef for zero-copy access. + ``synchronous=True`` — the action never defers ``play_next_()`` to a + later point (callback, timer, or ``loop()``). Trigger arguments are + only used during the initial call, so string args can use non-owning + StringRef for zero-copy access. + + ``synchronous=False`` — the action defers ``play_next_()`` via a + callback, timer, or ``Component::loop()``. Trigger arguments must + outlive the initial call, so string args use owning std::string to + prevent dangling references. """ + if synchronous is None: + _LOGGER.warning( + "register_action('%s', ...) is missing the synchronous= parameter. " + "Defaulting to synchronous=False (safe but prevents StringRef " + "optimization). Check the C++ class: use synchronous=False if " + "play_next_() is deferred to a callback, timer, or loop(); " + "use synchronous=True if play_next_() always runs before the " + "initial play/play_complex call returns", + name, + ) + synchronous = False return ACTION_REGISTRY.register(name, action_type, schema, synchronous=synchronous) @@ -353,6 +374,7 @@ async def component_is_idle_condition_to_code( "delay", DelayAction, cv.templatable(cv.positive_time_period_milliseconds), + synchronous=False, ) async def delay_action_to_code( config: ConfigType, @@ -465,7 +487,7 @@ _validate_wait_until = cv.maybe_simple_value( ) -@register_action("wait_until", WaitUntilAction, _validate_wait_until) +@register_action("wait_until", WaitUntilAction, _validate_wait_until, synchronous=False) async def wait_until_action_to_code( config: ConfigType, action_id: ID, @@ -611,7 +633,7 @@ def has_non_synchronous_actions(actions: ConfigType) -> bool: Non-synchronous actions (delay, wait_until, script.wait, etc.) store trigger args for later execution, making non-owning types like StringRef - unsafe. Actions that haven't been audited default to non-synchronous. + unsafe. """ if isinstance(actions, list): return any(has_non_synchronous_actions(item) for item in actions) diff --git a/esphome/components/ags10/sensor.py b/esphome/components/ags10/sensor.py index 8f0f372951..4cfa9e67ec 100644 --- a/esphome/components/ags10/sensor.py +++ b/esphome/components/ags10/sensor.py @@ -92,6 +92,7 @@ AGS10_NEW_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value( "ags10.new_i2c_address", AGS10NewI2cAddressAction, AGS10_NEW_I2C_ADDRESS_SCHEMA, + synchronous=True, ) async def ags10newi2caddress_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -121,6 +122,7 @@ AGS10_SET_ZERO_POINT_SCHEMA = cv.Schema( "ags10.set_zero_point", AGS10SetZeroPointAction, AGS10_SET_ZERO_POINT_SCHEMA, + synchronous=True, ) async def ags10setzeropoint_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/aic3204/audio_dac.py b/esphome/components/aic3204/audio_dac.py index da7a54df54..a644638f69 100644 --- a/esphome/components/aic3204/audio_dac.py +++ b/esphome/components/aic3204/audio_dac.py @@ -34,7 +34,10 @@ SET_AUTO_MUTE_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "aic3204.set_auto_mute_mode", SetAutoMuteAction, SET_AUTO_MUTE_ACTION_SCHEMA + "aic3204.set_auto_mute_mode", + SetAutoMuteAction, + SET_AUTO_MUTE_ACTION_SCHEMA, + synchronous=True, ) async def aic3204_set_volume_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index b855586152..aefb18d25c 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -243,7 +243,10 @@ async def new_alarm_control_panel(config, *args): @automation.register_action( - "alarm_control_panel.arm_away", ArmAwayAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.arm_away", + ArmAwayAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_arm_away_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -255,7 +258,10 @@ async def alarm_action_arm_away_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.arm_home", ArmHomeAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.arm_home", + ArmHomeAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_arm_home_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -267,7 +273,10 @@ async def alarm_action_arm_home_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.arm_night", ArmNightAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.arm_night", + ArmNightAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_arm_night_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -279,7 +288,10 @@ async def alarm_action_arm_night_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.disarm", DisarmAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.disarm", + DisarmAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_disarm_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -291,7 +303,10 @@ async def alarm_action_disarm_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.pending", PendingAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.pending", + PendingAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_pending_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -299,7 +314,10 @@ async def alarm_action_pending_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.triggered", TriggeredAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.triggered", + TriggeredAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_trigger_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -307,7 +325,10 @@ async def alarm_action_trigger_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.chime", ChimeAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.chime", + ChimeAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) async def alarm_action_chime_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -315,7 +336,10 @@ async def alarm_action_chime_to_code(config, action_id, template_arg, args): @automation.register_action( - "alarm_control_panel.ready", ReadyAction, ALARM_CONTROL_PANEL_ACTION_SCHEMA + "alarm_control_panel.ready", + ReadyAction, + ALARM_CONTROL_PANEL_ACTION_SCHEMA, + synchronous=True, ) @automation.register_condition( "alarm_control_panel.ready", diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index c4ac7adb23..e9630f5266 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -69,9 +69,15 @@ SET_FRAME_SCHEMA = cv.Schema( ) -@automation.register_action("animation.next_frame", NextFrameAction, NEXT_FRAME_SCHEMA) -@automation.register_action("animation.prev_frame", PrevFrameAction, PREV_FRAME_SCHEMA) -@automation.register_action("animation.set_frame", SetFrameAction, SET_FRAME_SCHEMA) +@automation.register_action( + "animation.next_frame", NextFrameAction, NEXT_FRAME_SCHEMA, synchronous=True +) +@automation.register_action( + "animation.prev_frame", PrevFrameAction, PREV_FRAME_SCHEMA, synchronous=True +) +@automation.register_action( + "animation.set_frame", SetFrameAction, SET_FRAME_SCHEMA, synchronous=True +) async def animation_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) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index c7dec6e78b..9772e6afca 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -712,6 +712,7 @@ API_RESPOND_ACTION_SCHEMA = cv.All( "api.respond", APIRespondAction, API_RESPOND_ACTION_SCHEMA, + synchronous=True, ) async def api_respond_to_code( config: ConfigType, diff --git a/esphome/components/at581x/__init__.py b/esphome/components/at581x/__init__.py index 117ada123d..0780814ea6 100644 --- a/esphome/components/at581x/__init__.py +++ b/esphome/components/at581x/__init__.py @@ -89,6 +89,7 @@ AT581XSettingsAction = at581x_ns.class_("AT581XSettingsAction", automation.Actio cv.Required(CONF_ID): cv.use_id(AT581XComponent), } ), + synchronous=True, ) async def at581x_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -160,6 +161,7 @@ RADAR_SETTINGS_SCHEMA = cv.Schema( "at581x.settings", AT581XSettingsAction, RADAR_SETTINGS_SCHEMA, + synchronous=True, ) async def at581x_settings_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/audio_adc/__init__.py b/esphome/components/audio_adc/__init__.py index 2f95a039f5..3c9b32e610 100644 --- a/esphome/components/audio_adc/__init__.py +++ b/esphome/components/audio_adc/__init__.py @@ -23,7 +23,10 @@ SET_MIC_GAIN_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "audio_adc.set_mic_gain", SetMicGainAction, SET_MIC_GAIN_ACTION_SCHEMA + "audio_adc.set_mic_gain", + SetMicGainAction, + SET_MIC_GAIN_ACTION_SCHEMA, + synchronous=True, ) async def audio_adc_set_mic_gain_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/audio_dac/__init__.py b/esphome/components/audio_dac/__init__.py index 92e6cb18fa..a950c1967b 100644 --- a/esphome/components/audio_dac/__init__.py +++ b/esphome/components/audio_dac/__init__.py @@ -31,15 +31,22 @@ SET_VOLUME_ACTION_SCHEMA = cv.maybe_simple_value( ) -@automation.register_action("audio_dac.mute_off", MuteOffAction, MUTE_ACTION_SCHEMA) -@automation.register_action("audio_dac.mute_on", MuteOnAction, MUTE_ACTION_SCHEMA) +@automation.register_action( + "audio_dac.mute_off", MuteOffAction, MUTE_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "audio_dac.mute_on", MuteOnAction, MUTE_ACTION_SCHEMA, synchronous=True +) async def audio_dac_mute_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action( - "audio_dac.set_volume", SetVolumeAction, SET_VOLUME_ACTION_SCHEMA + "audio_dac.set_volume", + SetVolumeAction, + SET_VOLUME_ACTION_SCHEMA, + synchronous=True, ) async def audio_dac_set_volume_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 1f64118560..37cccc01be 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -685,6 +685,7 @@ async def to_code(config): }, key=CONF_ID, ), + synchronous=True, ) async def binary_sensor_invalidate_state_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/bl0906/sensor.py b/esphome/components/bl0906/sensor.py index 42c6f06092..059e10e962 100644 --- a/esphome/components/bl0906/sensor.py +++ b/esphome/components/bl0906/sensor.py @@ -143,6 +143,7 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( cv.Required(CONF_ID): cv.use_id(BL0906), } ), + synchronous=True, ) async def reset_energy_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/ble_client/__init__.py b/esphome/components/ble_client/__init__.py index 37db181584..56ac2ea147 100644 --- a/esphome/components/ble_client/__init__.py +++ b/esphome/components/ble_client/__init__.py @@ -172,7 +172,10 @@ BLE_REMOVE_BOND_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "ble_client.disconnect", BLEDisconnectAction, BLE_CONNECT_ACTION_SCHEMA + "ble_client.disconnect", + BLEDisconnectAction, + BLE_CONNECT_ACTION_SCHEMA, + synchronous=False, ) async def ble_disconnect_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -180,7 +183,10 @@ async def ble_disconnect_to_code(config, action_id, template_arg, args): @automation.register_action( - "ble_client.connect", BLEConnectAction, BLE_CONNECT_ACTION_SCHEMA + "ble_client.connect", + BLEConnectAction, + BLE_CONNECT_ACTION_SCHEMA, + synchronous=False, ) async def ble_connect_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -188,7 +194,10 @@ async def ble_connect_to_code(config, action_id, template_arg, args): @automation.register_action( - "ble_client.ble_write", BLEWriteAction, BLE_WRITE_ACTION_SCHEMA + "ble_client.ble_write", + BLEWriteAction, + BLE_WRITE_ACTION_SCHEMA, + synchronous=False, ) async def ble_write_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -247,6 +256,7 @@ async def ble_write_to_code(config, action_id, template_arg, args): "ble_client.numeric_comparison_reply", BLENumericComparisonReplyAction, BLE_NUMERIC_COMPARISON_REPLY_ACTION_SCHEMA, + synchronous=True, ) async def numeric_comparison_reply_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -263,7 +273,10 @@ async def numeric_comparison_reply_to_code(config, action_id, template_arg, args @automation.register_action( - "ble_client.passkey_reply", BLEPasskeyReplyAction, BLE_PASSKEY_REPLY_ACTION_SCHEMA + "ble_client.passkey_reply", + BLEPasskeyReplyAction, + BLE_PASSKEY_REPLY_ACTION_SCHEMA, + synchronous=True, ) async def passkey_reply_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -283,6 +296,7 @@ async def passkey_reply_to_code(config, action_id, template_arg, args): "ble_client.remove_bond", BLERemoveBondAction, BLE_REMOVE_BOND_ACTION_SCHEMA, + synchronous=True, ) async def remove_bond_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/bm8563/time.py b/esphome/components/bm8563/time.py index 2785315af2..ba264f00bf 100644 --- a/esphome/components/bm8563/time.py +++ b/esphome/components/bm8563/time.py @@ -33,6 +33,7 @@ CONFIG_SCHEMA = ( cv.GenerateID(): cv.use_id(BM8563), } ), + synchronous=True, ) async def bm8563_write_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -49,6 +50,7 @@ async def bm8563_write_time_to_code(config, action_id, template_arg, args): cv.Required(CONF_DURATION): cv.templatable(cv.positive_time_period_seconds), } ), + synchronous=True, ) async def bm8563_start_timer_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -66,6 +68,7 @@ async def bm8563_start_timer_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(BM8563), } ), + synchronous=True, ) async def bm8563_read_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index 7b51c2c45c..c94c8647a9 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -155,6 +155,7 @@ async def register_canbus(var, config): validate_id, key=CONF_DATA, ), + synchronous=True, ) async def canbus_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/cc1101/__init__.py b/esphome/components/cc1101/__init__.py index e2e5986daf..2709290862 100644 --- a/esphome/components/cc1101/__init__.py +++ b/esphome/components/cc1101/__init__.py @@ -287,10 +287,18 @@ CC1101_ACTION_SCHEMA = cv.Schema( ) -@automation.register_action("cc1101.begin_tx", BeginTxAction, CC1101_ACTION_SCHEMA) -@automation.register_action("cc1101.begin_rx", BeginRxAction, CC1101_ACTION_SCHEMA) -@automation.register_action("cc1101.reset", ResetAction, CC1101_ACTION_SCHEMA) -@automation.register_action("cc1101.set_idle", SetIdleAction, CC1101_ACTION_SCHEMA) +@automation.register_action( + "cc1101.begin_tx", BeginTxAction, CC1101_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "cc1101.begin_rx", BeginRxAction, CC1101_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "cc1101.reset", ResetAction, CC1101_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "cc1101.set_idle", SetIdleAction, CC1101_ACTION_SCHEMA, synchronous=True +) async def cc1101_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) @@ -317,7 +325,10 @@ SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "cc1101.send_packet", SendPacketAction, SEND_PACKET_ACTION_SCHEMA + "cc1101.send_packet", + SendPacketAction, + SEND_PACKET_ACTION_SCHEMA, + synchronous=True, ) async def send_packet_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -419,9 +430,9 @@ def _register_setter_actions(): cg.add(getattr(var, _setter)(_map[data] if _map else data)) return var - automation.register_action(f"cc1101.{setter_name}", action_cls, schema)( - _setter_action_to_code - ) + automation.register_action( + f"cc1101.{setter_name}", action_cls, schema, synchronous=True + )(_setter_action_to_code) _register_setter_actions() diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index f5b91c502c..8cf5fa9b0c 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -476,7 +476,10 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "climate.control", ControlAction, CLIMATE_CONTROL_ACTION_SCHEMA + "climate.control", + ControlAction, + CLIMATE_CONTROL_ACTION_SCHEMA, + synchronous=True, ) async def climate_control_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/cm1106/sensor.py b/esphome/components/cm1106/sensor.py index 1d95bcc666..3c82fac977 100644 --- a/esphome/components/cm1106/sensor.py +++ b/esphome/components/cm1106/sensor.py @@ -65,6 +65,7 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id( "cm1106.calibrate_zero", CM1106CalibrateZeroAction, CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) async def cm1106_calibration_to_code(config, action_id, template_arg, args) -> None: """Service code generation entry point.""" diff --git a/esphome/components/cs5460a/sensor.py b/esphome/components/cs5460a/sensor.py index 07b5ea1c63..d2383bd01b 100644 --- a/esphome/components/cs5460a/sensor.py +++ b/esphome/components/cs5460a/sensor.py @@ -132,6 +132,7 @@ async def to_code(config): cv.Required(CONF_ID): cv.use_id(CS5460AComponent), } ), + synchronous=True, ) async def restart_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/datetime/__init__.py b/esphome/components/datetime/__init__.py index 74c9d594f7..90835624bf 100644 --- a/esphome/components/datetime/__init__.py +++ b/esphome/components/datetime/__init__.py @@ -187,6 +187,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def datetime_date_set_to_code(config, action_id, template_arg, args): action_var = cg.new_Pvariable(action_id, template_arg) @@ -218,6 +219,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args): ), } ), + synchronous=True, ) async def datetime_time_set_to_code(config, action_id, template_arg, args): action_var = cg.new_Pvariable(action_id, template_arg) @@ -249,6 +251,7 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args): ), }, ), + synchronous=True, ) async def datetime_datetime_set_to_code(config, action_id, template_arg, args): action_var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index 3cfe7aa641..4098fd3fb8 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -405,7 +405,10 @@ DEEP_SLEEP_ENTER_SCHEMA = cv.All( @automation.register_action( - "deep_sleep.enter", EnterDeepSleepAction, DEEP_SLEEP_ENTER_SCHEMA + "deep_sleep.enter", + EnterDeepSleepAction, + DEEP_SLEEP_ENTER_SCHEMA, + synchronous=True, ) async def deep_sleep_enter_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -428,11 +431,13 @@ async def deep_sleep_enter_to_code(config, action_id, template_arg, args): "deep_sleep.prevent", PreventDeepSleepAction, automation.maybe_simple_id(DEEP_SLEEP_ACTION_SCHEMA), + synchronous=True, ) @automation.register_action( "deep_sleep.allow", AllowDeepSleepAction, automation.maybe_simple_id(DEEP_SLEEP_ACTION_SCHEMA), + synchronous=True, ) async def deep_sleep_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index 53ebda6bcc..9df108c9c0 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -91,6 +91,7 @@ async def to_code(config): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_next_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -106,6 +107,7 @@ async def dfplayer_next_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_previous_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -123,6 +125,7 @@ async def dfplayer_previous_to_code(config, action_id, template_arg, args): }, key=CONF_FILE, ), + synchronous=True, ) async def dfplayer_play_mp3_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -143,6 +146,7 @@ async def dfplayer_play_mp3_to_code(config, action_id, template_arg, args): }, key=CONF_FILE, ), + synchronous=True, ) async def dfplayer_play_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -166,6 +170,7 @@ async def dfplayer_play_to_code(config, action_id, template_arg, args): cv.Optional(CONF_LOOP): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def dfplayer_play_folder_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -191,6 +196,7 @@ async def dfplayer_play_folder_to_code(config, action_id, template_arg, args): }, key=CONF_DEVICE, ), + synchronous=True, ) async def dfplayer_set_device_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -210,6 +216,7 @@ async def dfplayer_set_device_to_code(config, action_id, template_arg, args): }, key=CONF_VOLUME, ), + synchronous=True, ) async def dfplayer_set_volume_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -227,6 +234,7 @@ async def dfplayer_set_volume_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_volume_up_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -242,6 +250,7 @@ async def dfplayer_volume_up_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_volume_down_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -259,6 +268,7 @@ async def dfplayer_volume_down_to_code(config, action_id, template_arg, args): }, key=CONF_EQ_PRESET, ), + synchronous=True, ) async def dfplayer_set_eq_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -276,6 +286,7 @@ async def dfplayer_set_eq_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_sleep_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -291,6 +302,7 @@ async def dfplayer_sleep_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -306,6 +318,7 @@ async def dfplayer_reset_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_start_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -321,6 +334,7 @@ async def dfplayer_start_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_pause_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -336,6 +350,7 @@ async def dfplayer_pause_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_stop_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -351,6 +366,7 @@ async def dfplayer_stop_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DFPlayer), } ), + synchronous=True, ) async def dfplayer_random_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/dfrobot_sen0395/__init__.py b/esphome/components/dfrobot_sen0395/__init__.py index d54b147036..ba77e56abb 100644 --- a/esphome/components/dfrobot_sen0395/__init__.py +++ b/esphome/components/dfrobot_sen0395/__init__.py @@ -52,6 +52,7 @@ async def to_code(config): cv.GenerateID(): cv.use_id(DfrobotSen0395Component), } ), + synchronous=True, ) async def dfrobot_sen0395_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -151,6 +152,7 @@ MMWAVE_SETTINGS_SCHEMA = cv.Schema( "dfrobot_sen0395.settings", DfrobotSen0395SettingsAction, MMWAVE_SETTINGS_SCHEMA, + synchronous=True, ) async def dfrobot_sen0395_settings_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 695e7cde47..6367f88acc 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -159,6 +159,7 @@ async def register_display(var, config): cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayPage)), } ), + synchronous=True, ) async def display_page_show_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -179,6 +180,7 @@ async def display_page_show_to_code(config, action_id, template_arg, args): cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)), } ), + synchronous=True, ) async def display_page_show_next_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -193,6 +195,7 @@ async def display_page_show_next_to_code(config, action_id, template_arg, args): cv.GenerateID(CONF_ID): cv.templatable(cv.use_id(Display)), } ), + synchronous=True, ) async def display_page_show_previous_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/display_menu_base/__init__.py b/esphome/components/display_menu_base/__init__.py index 658292ec7a..c9a0c7ee93 100644 --- a/esphome/components/display_menu_base/__init__.py +++ b/esphome/components/display_menu_base/__init__.py @@ -294,50 +294,67 @@ MENU_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("display_menu.up", UpAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.up", UpAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_up_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.down", DownAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.down", DownAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_down_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.left", LeftAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.left", LeftAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_left_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.right", RightAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.right", RightAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_right_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.enter", EnterAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.enter", EnterAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_enter_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.show", ShowAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.show", ShowAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_show_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("display_menu.hide", HideAction, MENU_ACTION_SCHEMA) +@automation.register_action( + "display_menu.hide", HideAction, MENU_ACTION_SCHEMA, synchronous=True +) async def menu_hide_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action( - "display_menu.show_main", ShowMainAction, MENU_ACTION_SCHEMA + "display_menu.show_main", + ShowMainAction, + MENU_ACTION_SCHEMA, + synchronous=True, ) async def menu_show_main_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/ds1307/time.py b/esphome/components/ds1307/time.py index 42b7184db9..0e7bb976a2 100644 --- a/esphome/components/ds1307/time.py +++ b/esphome/components/ds1307/time.py @@ -27,6 +27,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( cv.GenerateID(): cv.use_id(DS1307Component), } ), + synchronous=True, ) async def ds1307_write_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -42,6 +43,7 @@ async def ds1307_write_time_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(DS1307Component), } ), + synchronous=True, ) async def ds1307_read_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/duty_time/sensor.py b/esphome/components/duty_time/sensor.py index 1907b3fcfe..456859f8e4 100644 --- a/esphome/components/duty_time/sensor.py +++ b/esphome/components/duty_time/sensor.py @@ -90,21 +90,27 @@ DUTY_TIME_ID_SCHEMA = maybe_simple_id( ) -@register_action("sensor.duty_time.start", StartAction, DUTY_TIME_ID_SCHEMA) +@register_action( + "sensor.duty_time.start", StartAction, DUTY_TIME_ID_SCHEMA, synchronous=True +) async def sensor_runtime_start_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) return var -@register_action("sensor.duty_time.stop", StopAction, DUTY_TIME_ID_SCHEMA) +@register_action( + "sensor.duty_time.stop", StopAction, DUTY_TIME_ID_SCHEMA, synchronous=True +) async def sensor_runtime_stop_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) return var -@register_action("sensor.duty_time.reset", ResetAction, DUTY_TIME_ID_SCHEMA) +@register_action( + "sensor.duty_time.reset", ResetAction, DUTY_TIME_ID_SCHEMA, synchronous=True +) async def sensor_runtime_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 8b368afc2e..43208eb87e 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -604,11 +604,15 @@ async def ble_enabled_to_code(config, condition_id, template_arg, args): return cg.new_Pvariable(condition_id, template_arg) -@automation.register_action("ble.enable", BLEEnableAction, cv.Schema({})) +@automation.register_action( + "ble.enable", BLEEnableAction, cv.Schema({}), synchronous=True +) async def ble_enable_to_code(config, action_id, template_arg, args): return cg.new_Pvariable(action_id, template_arg) -@automation.register_action("ble.disable", BLEDisableAction, cv.Schema({})) +@automation.register_action( + "ble.disable", BLEDisableAction, cv.Schema({}), synchronous=True +) async def ble_disable_to_code(config, action_id, template_arg, args): return cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index b08e791e7e..827ddba955 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -622,6 +622,7 @@ async def to_code(config): ), validate_set_value_action, ), + synchronous=True, ) async def ble_server_characteristic_set_value(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -641,6 +642,7 @@ async def ble_server_characteristic_set_value(config, action_id, template_arg, a cv.Required(CONF_VALUE): value_schema(), } ), + synchronous=True, ) async def ble_server_descriptor_set_value(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -662,6 +664,7 @@ async def ble_server_descriptor_set_value(config, action_id, template_arg, args) ), validate_notify_action, ), + synchronous=True, ) async def ble_server_characteristic_notify(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index 37e74672ed..c5e8f3178d 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -373,6 +373,7 @@ ESP32_BLE_START_SCAN_ACTION_SCHEMA = cv.Schema( "esp32_ble_tracker.start_scan", ESP32BLEStartScanAction, ESP32_BLE_START_SCAN_ACTION_SCHEMA, + synchronous=True, ) async def esp32_ble_tracker_start_scan_action_to_code( config, action_id, template_arg, args @@ -396,6 +397,7 @@ ESP32_BLE_STOP_SCAN_ACTION_SCHEMA = automation.maybe_simple_id( "esp32_ble_tracker.stop_scan", ESP32BLEStopScanAction, ESP32_BLE_STOP_SCAN_ACTION_SCHEMA, + synchronous=True, ) async def esp32_ble_tracker_stop_scan_action_to_code( config, action_id, template_arg, args diff --git a/esphome/components/esp8266_pwm/output.py b/esphome/components/esp8266_pwm/output.py index a78831c516..b9b6dcc95a 100644 --- a/esphome/components/esp8266_pwm/output.py +++ b/esphome/components/esp8266_pwm/output.py @@ -57,6 +57,7 @@ async def to_code(config) -> None: cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), } ), + synchronous=True, ) async def esp8266_set_frequency_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/esp_ldo/__init__.py b/esphome/components/esp_ldo/__init__.py index 5235a9411e..a489651b59 100644 --- a/esphome/components/esp_ldo/__init__.py +++ b/esphome/components/esp_ldo/__init__.py @@ -129,6 +129,7 @@ def adjusted_ldo_id(value): ), } ), + synchronous=True, ) async def ldo_voltage_adjust_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index faeccd910e..d1a85ae8fd 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -220,6 +220,7 @@ SEND_SCHEMA.add_extra(_validate_send_action) "espnow.send", SendAction, SEND_SCHEMA, + synchronous=False, ) @automation.register_action( "espnow.broadcast", @@ -232,6 +233,7 @@ SEND_SCHEMA.add_extra(_validate_send_action) ), key=CONF_DATA, ), + synchronous=False, ) async def send_action( config: ConfigType, @@ -271,6 +273,7 @@ async def send_action( PEER_SCHEMA, key=CONF_ADDRESS, ), + synchronous=True, ) @automation.register_action( "espnow.peer.delete", @@ -279,6 +282,7 @@ async def send_action( PEER_SCHEMA, key=CONF_ADDRESS, ), + synchronous=True, ) async def peer_action( config: ConfigType, @@ -303,6 +307,7 @@ async def peer_action( }, key=CONF_CHANNEL, ), + synchronous=True, ) async def channel_action( config: ConfigType, diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 14cc1505ad..300902b8ca 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -129,7 +129,9 @@ TRIGGER_EVENT_SCHEMA = cv.Schema( ) -@automation.register_action("event.trigger", TriggerEventAction, TRIGGER_EVENT_SCHEMA) +@automation.register_action( + "event.trigger", TriggerEventAction, TRIGGER_EVENT_SCHEMA, synchronous=True +) async def event_fire_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/ezo_pmp/__init__.py b/esphome/components/ezo_pmp/__init__.py index c1f72bb05d..1538e303f1 100644 --- a/esphome/components/ezo_pmp/__init__.py +++ b/esphome/components/ezo_pmp/__init__.py @@ -81,7 +81,10 @@ EzoPMPArbitraryCommandAction = ezo_pmp_ns.class_( @automation.register_action( - "ezo_pmp.find", EzoPMPFindAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA + "ezo_pmp.find", + EzoPMPFindAction, + EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_find_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -92,6 +95,7 @@ async def ezo_pmp_find_to_code(config, action_id, template_arg, args): "ezo_pmp.dose_continuously", EzoPMPDoseContinuouslyAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_dose_continuously_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -102,6 +106,7 @@ async def ezo_pmp_dose_continuously_to_code(config, action_id, template_arg, arg "ezo_pmp.clear_total_volume_dosed", EzoPMPClearTotalVolumeDispensedAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_clear_total_volume_dosed_to_code( config, action_id, template_arg, args @@ -114,6 +119,7 @@ async def ezo_pmp_clear_total_volume_dosed_to_code( "ezo_pmp.clear_calibration", EzoPMPClearCalibrationAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_clear_calibration_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -121,7 +127,10 @@ async def ezo_pmp_clear_calibration_to_code(config, action_id, template_arg, arg @automation.register_action( - "ezo_pmp.pause_dosing", EzoPMPPauseDosingAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA + "ezo_pmp.pause_dosing", + EzoPMPPauseDosingAction, + EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_pause_dosing_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -129,7 +138,10 @@ async def ezo_pmp_pause_dosing_to_code(config, action_id, template_arg, args): @automation.register_action( - "ezo_pmp.stop_dosing", EzoPMPStopDosingAction, EZO_PMP_NO_ARGS_ACTION_SCHEMA + "ezo_pmp.stop_dosing", + EzoPMPStopDosingAction, + EZO_PMP_NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_stop_dosing_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -149,7 +161,10 @@ EZO_PMP_DOSE_VOLUME_ACTION_SCHEMA = cv.All( @automation.register_action( - "ezo_pmp.dose_volume", EzoPMPDoseVolumeAction, EZO_PMP_DOSE_VOLUME_ACTION_SCHEMA + "ezo_pmp.dose_volume", + EzoPMPDoseVolumeAction, + EZO_PMP_DOSE_VOLUME_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_dose_volume_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -178,6 +193,7 @@ EZO_PMP_DOSE_VOLUME_OVER_TIME_ACTION_SCHEMA = cv.All( "ezo_pmp.dose_volume_over_time", EzoPMPDoseVolumeOverTimeAction, EZO_PMP_DOSE_VOLUME_OVER_TIME_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_dose_volume_over_time_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -209,6 +225,7 @@ EZO_PMP_DOSE_WITH_CONSTANT_FLOW_RATE_ACTION_SCHEMA = cv.All( "ezo_pmp.dose_with_constant_flow_rate", EzoPMPDoseWithConstantFlowRateAction, EZO_PMP_DOSE_WITH_CONSTANT_FLOW_RATE_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_dose_with_constant_flow_rate_to_code( config, action_id, template_arg, args @@ -239,6 +256,7 @@ EZO_PMP_SET_CALIBRATION_VOLUME_ACTION_SCHEMA = cv.All( "ezo_pmp.set_calibration_volume", EzoPMPSetCalibrationVolumeAction, EZO_PMP_SET_CALIBRATION_VOLUME_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_set_calibration_volume_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -262,6 +280,7 @@ EZO_PMP_CHANGE_I2C_ADDRESS_ACTION_SCHEMA = cv.All( "ezo_pmp.change_i2c_address", EzoPMPChangeI2CAddressAction, EZO_PMP_CHANGE_I2C_ADDRESS_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_change_i2c_address_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -285,6 +304,7 @@ EZO_PMP_ARBITRARY_COMMAND_ACTION_SCHEMA = cv.All( "ezo_pmp.arbitrary_command", EzoPMPArbitraryCommandAction, EZO_PMP_ARBITRARY_COMMAND_ACTION_SCHEMA, + synchronous=True, ) async def ezo_pmp_arbitrary_command_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index da28c577c8..df71c6ab3f 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -365,6 +365,7 @@ async def fan_turn_on_to_code(config, action_id, template_arg, args): cv.Optional(CONF_OFF_SPEED_CYCLE, default=True): cv.boolean, } ), + synchronous=True, ) async def fan_cycle_speed_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/fingerprint_grow/__init__.py b/esphome/components/fingerprint_grow/__init__.py index 115b89433b..2637097be8 100644 --- a/esphome/components/fingerprint_grow/__init__.py +++ b/esphome/components/fingerprint_grow/__init__.py @@ -261,6 +261,7 @@ async def to_code(config): }, key=CONF_FINGER_ID, ), + synchronous=True, ) async def fingerprint_grow_enroll_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -282,6 +283,7 @@ async def fingerprint_grow_enroll_to_code(config, action_id, template_arg, args) cv.GenerateID(): cv.use_id(FingerprintGrowComponent), } ), + synchronous=True, ) async def fingerprint_grow_cancel_enroll_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -299,6 +301,7 @@ async def fingerprint_grow_cancel_enroll_to_code(config, action_id, template_arg }, key=CONF_FINGER_ID, ), + synchronous=True, ) async def fingerprint_grow_delete_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -317,6 +320,7 @@ async def fingerprint_grow_delete_to_code(config, action_id, template_arg, args) cv.GenerateID(): cv.use_id(FingerprintGrowComponent), } ), + synchronous=True, ) async def fingerprint_grow_delete_all_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -337,6 +341,7 @@ FINGERPRINT_GROW_LED_CONTROL_ACTION_SCHEMA = cv.maybe_simple_value( "fingerprint_grow.led_control", LEDControlAction, FINGERPRINT_GROW_LED_CONTROL_ACTION_SCHEMA, + synchronous=True, ) async def fingerprint_grow_led_control_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -359,6 +364,7 @@ async def fingerprint_grow_led_control_to_code(config, action_id, template_arg, cv.Required(CONF_COUNT): cv.templatable(cv.uint8_t), } ), + synchronous=True, ) async def fingerprint_grow_aura_led_control_to_code( config, action_id, template_arg, args diff --git a/esphome/components/grove_tb6612fng/__init__.py b/esphome/components/grove_tb6612fng/__init__.py index 869c05387f..210e2f7bab 100644 --- a/esphome/components/grove_tb6612fng/__init__.py +++ b/esphome/components/grove_tb6612fng/__init__.py @@ -72,6 +72,7 @@ async def to_code(config): cv.Required(CONF_DIRECTION): cv.enum(DIRECTION_TYPE, upper=True), } ), + synchronous=True, ) async def grove_tb6612fng_run_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -96,6 +97,7 @@ async def grove_tb6612fng_run_to_code(config, action_id, template_arg, args): cv.Required(CONF_CHANNEL): cv.templatable(cv.int_range(min=0, max=1)), } ), + synchronous=True, ) async def grove_tb6612fng_break_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -115,6 +117,7 @@ async def grove_tb6612fng_break_to_code(config, action_id, template_arg, args): cv.Required(CONF_CHANNEL): cv.templatable(cv.int_range(min=0, max=1)), } ), + synchronous=True, ) async def grove_tb6612fng_stop_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -133,6 +136,7 @@ async def grove_tb6612fng_stop_to_code(config, action_id, template_arg, args): cv.Required(CONF_ID): cv.use_id(GROVE_TB6612FNG), } ), + synchronous=True, ) async def grove_tb6612fng_standby_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -149,6 +153,7 @@ async def grove_tb6612fng_standby_to_code(config, action_id, template_arg, args) cv.Required(CONF_ID): cv.use_id(GROVE_TB6612FNG), } ), + synchronous=True, ) async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -166,6 +171,7 @@ async def grove_tb6612fng_no_standby_to_code(config, action_id, template_arg, ar cv.Required(CONF_ADDRESS): cv.i2c_address, } ), + synchronous=True, ) async def grove_tb6612fng_change_address_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index 6c208f6caa..caaaa18dd6 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -319,10 +319,16 @@ HAIER_HON_BASE_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "climate.haier.display_on", DisplayOnAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.display_on", + DisplayOnAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "climate.haier.display_off", DisplayOffAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.display_off", + DisplayOffAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) async def display_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -330,10 +336,16 @@ async def display_action_to_code(config, action_id, template_arg, args): @automation.register_action( - "climate.haier.beeper_on", BeeperOnAction, HAIER_HON_BASE_ACTION_SCHEMA + "climate.haier.beeper_on", + BeeperOnAction, + HAIER_HON_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "climate.haier.beeper_off", BeeperOffAction, HAIER_HON_BASE_ACTION_SCHEMA + "climate.haier.beeper_off", + BeeperOffAction, + HAIER_HON_BASE_ACTION_SCHEMA, + synchronous=True, ) async def beeper_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -345,11 +357,13 @@ async def beeper_action_to_code(config, action_id, template_arg, args): "climate.haier.start_self_cleaning", StartSelfCleaningAction, HAIER_HON_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( "climate.haier.start_steri_cleaning", StartSteriCleaningAction, HAIER_HON_BASE_ACTION_SCHEMA, + synchronous=True, ) async def start_cleaning_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -368,6 +382,7 @@ async def start_cleaning_to_code(config, action_id, template_arg, args): ), } ), + synchronous=True, ) async def haier_set_vertical_airflow_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -391,6 +406,7 @@ async def haier_set_vertical_airflow_to_code(config, action_id, template_arg, ar ), } ), + synchronous=True, ) async def haier_set_horizontal_airflow_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -403,10 +419,16 @@ async def haier_set_horizontal_airflow_to_code(config, action_id, template_arg, @automation.register_action( - "climate.haier.health_on", HealthOnAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.health_on", + HealthOnAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "climate.haier.health_off", HealthOffAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.health_off", + HealthOffAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) async def health_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -414,13 +436,22 @@ async def health_action_to_code(config, action_id, template_arg, args): @automation.register_action( - "climate.haier.power_on", PowerOnAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.power_on", + PowerOnAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "climate.haier.power_off", PowerOffAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.power_off", + PowerOffAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "climate.haier.power_toggle", PowerToggleAction, HAIER_BASE_ACTION_SCHEMA + "climate.haier.power_toggle", + PowerToggleAction, + HAIER_BASE_ACTION_SCHEMA, + synchronous=True, ) async def power_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/hbridge/fan/__init__.py b/esphome/components/hbridge/fan/__init__.py index 31a20a8981..8ea8677ba2 100644 --- a/esphome/components/hbridge/fan/__init__.py +++ b/esphome/components/hbridge/fan/__init__.py @@ -52,6 +52,7 @@ CONFIG_SCHEMA = ( "fan.hbridge.brake", BrakeAction, maybe_simple_id({cv.GenerateID(): cv.use_id(HBridgeFan)}), + synchronous=True, ) async def fan_hbridge_brake_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/hc8/sensor.py b/esphome/components/hc8/sensor.py index 2f39b47f3c..29b428e310 100644 --- a/esphome/components/hc8/sensor.py +++ b/esphome/components/hc8/sensor.py @@ -68,7 +68,10 @@ CALIBRATION_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "hc8.calibrate", HC8CalibrateAction, CALIBRATION_ACTION_SCHEMA + "hc8.calibrate", + HC8CalibrateAction, + CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) async def hc8_calibration_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/hdc302x/sensor.py b/esphome/components/hdc302x/sensor.py index 7215a4cfb7..a6265b9b98 100644 --- a/esphome/components/hdc302x/sensor.py +++ b/esphome/components/hdc302x/sensor.py @@ -114,7 +114,10 @@ HDC302X_HEATER_ON_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "hdc302x.heater_on", HeaterOnAction, HDC302X_HEATER_ON_ACTION_SCHEMA + "hdc302x.heater_on", + HeaterOnAction, + HDC302X_HEATER_ON_ACTION_SCHEMA, + synchronous=True, ) async def hdc302x_heater_on_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -127,7 +130,10 @@ async def hdc302x_heater_on_to_code(config, action_id, template_arg, args): @automation.register_action( - "hdc302x.heater_off", HeaterOffAction, HDC302X_ACTION_SCHEMA + "hdc302x.heater_off", + HeaterOffAction, + HDC302X_ACTION_SCHEMA, + synchronous=True, ) async def hdc302x_heater_off_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/hlk_fm22x/__init__.py b/esphome/components/hlk_fm22x/__init__.py index efd64b6513..cb6d5cdfd6 100644 --- a/esphome/components/hlk_fm22x/__init__.py +++ b/esphome/components/hlk_fm22x/__init__.py @@ -170,6 +170,7 @@ async def to_code(config): }, key=CONF_NAME, ), + synchronous=True, ) async def hlk_fm22x_enroll_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -192,6 +193,7 @@ async def hlk_fm22x_enroll_to_code(config, action_id, template_arg, args): }, key=CONF_FACE_ID, ), + synchronous=True, ) async def hlk_fm22x_delete_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -210,6 +212,7 @@ async def hlk_fm22x_delete_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(HlkFm22xComponent), } ), + synchronous=True, ) async def hlk_fm22x_delete_all_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -225,6 +228,7 @@ async def hlk_fm22x_delete_all_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(HlkFm22xComponent), } ), + synchronous=True, ) async def hlk_fm22x_scan_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -240,6 +244,7 @@ async def hlk_fm22x_scan_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(HlkFm22xComponent), } ), + synchronous=True, ) async def hlk_fm22x_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index 81337ebdf6..416432cfc4 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -279,13 +279,22 @@ HTTP_REQUEST_SEND_ACTION_SCHEMA = HTTP_REQUEST_ACTION_SCHEMA.extend( @automation.register_action( - "http_request.get", HttpRequestSendAction, HTTP_REQUEST_GET_ACTION_SCHEMA + "http_request.get", + HttpRequestSendAction, + HTTP_REQUEST_GET_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "http_request.post", HttpRequestSendAction, HTTP_REQUEST_POST_ACTION_SCHEMA + "http_request.post", + HttpRequestSendAction, + HTTP_REQUEST_POST_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "http_request.send", HttpRequestSendAction, HTTP_REQUEST_SEND_ACTION_SCHEMA + "http_request.send", + HttpRequestSendAction, + HTTP_REQUEST_SEND_ACTION_SCHEMA, + synchronous=True, ) async def http_request_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/http_request/ota/__init__.py b/esphome/components/http_request/ota/__init__.py index d2c574d8c6..fb59e51943 100644 --- a/esphome/components/http_request/ota/__init__.py +++ b/esphome/components/http_request/ota/__init__.py @@ -70,6 +70,7 @@ OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA = cv.All( "ota.http_request.flash", OtaHttpRequestComponentFlashAction, OTA_HTTP_REQUEST_FLASH_ACTION_SCHEMA, + synchronous=True, ) async def ota_http_request_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index a578670e37..92c088a22f 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -93,6 +93,7 @@ async def to_code(config): }, key=CONF_LEVEL, ), + synchronous=True, ) async def set_heater_level_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -112,6 +113,7 @@ async def set_heater_level_to_code(config, action_id, template_arg, args): }, key=CONF_STATUS, ), + synchronous=True, ) async def set_heater_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index f1e6ef4243..4f62ce7a94 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -652,6 +652,7 @@ async def to_code(config: ConfigType) -> None: }, key=CONF_BRIGHTNESS, ), + synchronous=True, ) async def hub75_set_brightness_to_code( config: ConfigType, diff --git a/esphome/components/integration/sensor.py b/esphome/components/integration/sensor.py index 2676638556..d0aae4201e 100644 --- a/esphome/components/integration/sensor.py +++ b/esphome/components/integration/sensor.py @@ -111,6 +111,7 @@ async def to_code(config): cv.Required(CONF_ID): cv.use_id(IntegrationSensor), } ), + synchronous=True, ) async def sensor_integration_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -127,6 +128,7 @@ async def sensor_integration_reset_to_code(config, action_id, template_arg, args cv.Required(CONF_VALUE): cv.templatable(cv.float_), } ), + synchronous=True, ) async def sensor_integration_set_value_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/key_collector/__init__.py b/esphome/components/key_collector/__init__.py index badb28c32c..1f4519df2d 100644 --- a/esphome/components/key_collector/__init__.py +++ b/esphome/components/key_collector/__init__.py @@ -142,6 +142,7 @@ async def to_code(config): cv.GenerateID(): cv.use_id(KeyCollector), } ), + synchronous=True, ) async def enable_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -157,6 +158,7 @@ async def enable_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(KeyCollector), } ), + synchronous=True, ) async def disable_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/ld2410/__init__.py b/esphome/components/ld2410/__init__.py index b492bbcd14..360e56330a 100644 --- a/esphome/components/ld2410/__init__.py +++ b/esphome/components/ld2410/__init__.py @@ -97,7 +97,10 @@ BLUETOOTH_PASSWORD_SET_SCHEMA = cv.Schema( @automation.register_action( - "bluetooth_password.set", BluetoothPasswordSetAction, BLUETOOTH_PASSWORD_SET_SCHEMA + "bluetooth_password.set", + BluetoothPasswordSetAction, + BLUETOOTH_PASSWORD_SET_SCHEMA, + synchronous=True, ) async def bluetooth_password_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/ledc/output.py b/esphome/components/ledc/output.py index 7a45b9dc3f..62ff5ad30a 100644 --- a/esphome/components/ledc/output.py +++ b/esphome/components/ledc/output.py @@ -77,6 +77,7 @@ async def to_code(config): cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), } ), + synchronous=True, ) async def ledc_set_frequency_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/libretiny_pwm/output.py b/esphome/components/libretiny_pwm/output.py index 28556514d8..e812b6a8f2 100644 --- a/esphome/components/libretiny_pwm/output.py +++ b/esphome/components/libretiny_pwm/output.py @@ -38,6 +38,7 @@ async def to_code(config): cv.Required(CONF_FREQUENCY): cv.templatable(cv.int_), } ), + synchronous=True, ) async def libretiny_pwm_set_frequency_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 08fd26a937..55273003b9 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -278,7 +278,10 @@ LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA = cv.Schema( @automation.register_action( - "light.addressable_set", AddressableSet, LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA + "light.addressable_set", + AddressableSet, + LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA, + synchronous=True, ) async def light_addressable_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/lightwaverf/__init__.py b/esphome/components/lightwaverf/__init__.py index 802b341601..acbbbb4de9 100644 --- a/esphome/components/lightwaverf/__init__.py +++ b/esphome/components/lightwaverf/__init__.py @@ -55,6 +55,7 @@ LIGHTWAVE_SEND_SCHEMA = cv.Any( "lightwaverf.send_raw", LightwaveRawAction, LIGHTWAVE_SEND_SCHEMA, + synchronous=True, ) async def send_raw_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index e37092756f..fe4db23ae3 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -129,9 +129,15 @@ LOCK_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("lock.unlock", UnlockAction, LOCK_ACTION_SCHEMA) -@automation.register_action("lock.lock", LockAction, LOCK_ACTION_SCHEMA) -@automation.register_action("lock.open", OpenAction, LOCK_ACTION_SCHEMA) +@automation.register_action( + "lock.unlock", UnlockAction, LOCK_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "lock.lock", LockAction, LOCK_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "lock.open", OpenAction, LOCK_ACTION_SCHEMA, synchronous=True +) async def lock_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 026b8aaf24..83a7854165 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -545,6 +545,7 @@ async def logger_log_action_to_code(config, action_id, template_arg, args): }, key=CONF_LEVEL, ), + synchronous=True, ) async def logger_set_level_to_code(config, action_id, template_arg, args): level = LOG_LEVELS[config[CONF_LEVEL]] diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index b589e42f3b..f9adca9c33 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -182,6 +182,7 @@ async def disp_update(disp, config: dict): ), LVGL_SCHEMA, ), + synchronous=True, ) async def obj_invalidate_to_code(config, action_id, template_arg, args): if CONF_LVGL_ID in config: @@ -202,6 +203,7 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args): DISP_BG_SCHEMA.extend(LVGL_SCHEMA).add_extra( cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE) ), + synchronous=True, ) async def lvgl_update_to_code(config, action_id, template_arg, args): widgets = await get_widgets(config, CONF_LVGL_ID) @@ -222,6 +224,7 @@ async def lvgl_update_to_code(config, action_id, template_arg, args): cv.Optional(CONF_SHOW_SNOW, default=False): lv_bool, } ), + synchronous=True, ) async def pause_action_to_code(config, action_id, template_arg, args): lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) @@ -237,6 +240,7 @@ async def pause_action_to_code(config, action_id, template_arg, args): "lvgl.resume", LvglAction, LVGL_SCHEMA, + synchronous=True, ) async def resume_action_to_code(config, action_id, template_arg, args): lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) @@ -247,7 +251,9 @@ async def resume_action_to_code(config, action_id, template_arg, args): return var -@automation.register_action("lvgl.widget.disable", ObjUpdateAction, LIST_ACTION_SCHEMA) +@automation.register_action( + "lvgl.widget.disable", ObjUpdateAction, LIST_ACTION_SCHEMA, synchronous=True +) async def obj_disable_to_code(config, action_id, template_arg, args): async def do_disable(widget: Widget): widget.add_state(LV_STATE.DISABLED) @@ -257,7 +263,9 @@ async def obj_disable_to_code(config, action_id, template_arg, args): ) -@automation.register_action("lvgl.widget.enable", ObjUpdateAction, LIST_ACTION_SCHEMA) +@automation.register_action( + "lvgl.widget.enable", ObjUpdateAction, LIST_ACTION_SCHEMA, synchronous=True +) async def obj_enable_to_code(config, action_id, template_arg, args): async def do_enable(widget: Widget): widget.clear_state(LV_STATE.DISABLED) @@ -267,7 +275,9 @@ async def obj_enable_to_code(config, action_id, template_arg, args): ) -@automation.register_action("lvgl.widget.hide", ObjUpdateAction, LIST_ACTION_SCHEMA) +@automation.register_action( + "lvgl.widget.hide", ObjUpdateAction, LIST_ACTION_SCHEMA, synchronous=True +) async def obj_hide_to_code(config, action_id, template_arg, args): async def do_hide(widget: Widget): widget.add_flag("LV_OBJ_FLAG_HIDDEN") @@ -276,7 +286,9 @@ async def obj_hide_to_code(config, action_id, template_arg, args): return await action_to_code(widgets, do_hide, action_id, template_arg, args) -@automation.register_action("lvgl.widget.show", ObjUpdateAction, LIST_ACTION_SCHEMA) +@automation.register_action( + "lvgl.widget.show", ObjUpdateAction, LIST_ACTION_SCHEMA, synchronous=True +) async def obj_show_to_code(config, action_id, template_arg, args): async def do_show(widget: Widget): widget.clear_flag("LV_OBJ_FLAG_HIDDEN") @@ -318,6 +330,7 @@ def focused_id(value): key=CONF_ID, ), ), + synchronous=True, ) async def widget_focus(config, action_id, template_arg, args): widget = await get_widgets(config) @@ -357,7 +370,10 @@ async def widget_focus(config, action_id, template_arg, args): @automation.register_action( - "lvgl.widget.update", ObjUpdateAction, base_update_schema(lv_obj_base_t, PARTS) + "lvgl.widget.update", + ObjUpdateAction, + base_update_schema(lv_obj_base_t, PARTS), + synchronous=True, ) async def obj_update_to_code(config, action_id, template_arg, args): async def do_update(widget: Widget): @@ -389,6 +405,7 @@ def validate_refresh_config(config): ), validate_refresh_config, ), + synchronous=True, ) async def obj_refresh_to_code(config, action_id, template_arg, args): widget = await get_widgets(config) diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 3969c9f388..b9801b4133 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -59,6 +59,7 @@ async def styles_to_code(config): cv.Required(CONF_ID): cv.use_id(lv_style_t), } ), + synchronous=True, ) async def style_update_to_code(config, action_id, template_arg, args): await wait_for_widgets() diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 9c92ca7e98..09d40bb7ef 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -164,6 +164,7 @@ class WidgetType: f"lvgl.{self.name}.update", ObjUpdateAction, base_update_schema(self, self.parts).extend(self.modify_schema), + synchronous=True, )(update_to_code) @property diff --git a/esphome/components/lvgl/widgets/animimg.py b/esphome/components/lvgl/widgets/animimg.py index b824d28fb8..8e2db5ff35 100644 --- a/esphome/components/lvgl/widgets/animimg.py +++ b/esphome/components/lvgl/widgets/animimg.py @@ -83,6 +83,7 @@ animimg_spec = AnimimgType() }, key=CONF_ID, ), + synchronous=True, ) async def animimg_start(config, action_id, template_arg, args): widget = await get_widgets(config) @@ -102,6 +103,7 @@ async def animimg_start(config, action_id, template_arg, args): }, key=CONF_ID, ), + synchronous=True, ) async def animimg_stop(config, action_id, template_arg, args): widget = await get_widgets(config) diff --git a/esphome/components/lvgl/widgets/buttonmatrix.py b/esphome/components/lvgl/widgets/buttonmatrix.py index fe421aa477..f94f12b69b 100644 --- a/esphome/components/lvgl/widgets/buttonmatrix.py +++ b/esphome/components/lvgl/widgets/buttonmatrix.py @@ -245,6 +245,7 @@ buttonmatrix_spec = ButtonMatrixType() cv.Optional(CONF_SELECTED): lv_bool, } ), + synchronous=True, ) async def button_update_to_code(config, action_id, template_arg, args): widgets = await get_widgets(config[CONF_ID]) diff --git a/esphome/components/lvgl/widgets/canvas.py b/esphome/components/lvgl/widgets/canvas.py index ead352aa77..50cc8b0af6 100644 --- a/esphome/components/lvgl/widgets/canvas.py +++ b/esphome/components/lvgl/widgets/canvas.py @@ -97,6 +97,7 @@ canvas_spec = CanvasType() cv.Optional(CONF_OPA, default="COVER"): opacity, }, ), + synchronous=True, ) async def canvas_fill(config, action_id, template_arg, args): widget = await get_widgets(config) @@ -120,6 +121,7 @@ async def canvas_fill(config, action_id, template_arg, args): cv.Required(CONF_POINTS): cv.ensure_list(point_schema), }, ), + synchronous=True, ) async def canvas_set_pixel(config, action_id, template_arg, args): widget = await get_widgets(config) @@ -229,6 +231,7 @@ RECT_PROPS = { **{cv.Optional(prop): STYLE_PROPS[prop] for prop in RECT_PROPS}, } ), + synchronous=True, ) async def canvas_draw_rect(config, action_id, template_arg, args): width = await pixels.process(config[CONF_WIDTH]) @@ -268,6 +271,7 @@ TEXT_PROPS = { **{cv.Optional(prop): STYLE_PROPS[f"text_{prop}"] for prop in TEXT_PROPS}, }, ), + synchronous=True, ) async def canvas_draw_text(config, action_id, template_arg, args): text = await lv_text.process(config[CONF_TEXT]) @@ -302,6 +306,7 @@ IMG_PROPS = { **{cv.Optional(prop): validator for prop, validator in IMG_PROPS.items()}, } ), + synchronous=True, ) async def canvas_draw_image(config, action_id, template_arg, args): src = await lv_image.process(config[CONF_SRC]) @@ -341,6 +346,7 @@ LINE_PROPS = { **{cv.Optional(prop): validator for prop, validator in LINE_PROPS.items()}, } ), + synchronous=True, ) async def canvas_draw_line(config, action_id, template_arg, args): points = [ @@ -369,6 +375,7 @@ async def canvas_draw_line(config, action_id, template_arg, args): **{cv.Optional(prop): STYLE_PROPS[prop] for prop in RECT_PROPS}, }, ), + synchronous=True, ) async def canvas_draw_polygon(config, action_id, template_arg, args): points = [ @@ -408,6 +415,7 @@ ARC_PROPS = { **{cv.Optional(prop): validator for prop, validator in ARC_PROPS.items()}, } ), + synchronous=True, ) async def canvas_draw_arc(config, action_id, template_arg, args): radius = await size.process(config[CONF_RADIUS]) diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index aefda0e71a..b7e3af9a78 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -297,6 +297,7 @@ meter_spec = MeterType() cv.Optional(CONF_OPA): opacity, } ), + synchronous=True, ) async def indicator_update_to_code(config, action_id, template_arg, args): widget = await get_widgets(config) diff --git a/esphome/components/lvgl/widgets/page.py b/esphome/components/lvgl/widgets/page.py index 23c162e010..7e75ab6a2d 100644 --- a/esphome/components/lvgl/widgets/page.py +++ b/esphome/components/lvgl/widgets/page.py @@ -85,6 +85,7 @@ page_spec = PageType() "lvgl.page.next", LvglAction, SHOW_SCHEMA, + synchronous=True, ) async def page_next_to_code(config, action_id, template_arg, args): animation = await LV_ANIM.process(config[CONF_ANIMATION]) @@ -125,6 +126,7 @@ async def page_is_showing_to_code(config, condition_id, template_arg, args): "lvgl.page.previous", LvglAction, SHOW_SCHEMA, + synchronous=True, ) async def page_previous_to_code(config, action_id, template_arg, args): animation = await LV_ANIM.process(config[CONF_ANIMATION]) @@ -148,6 +150,7 @@ async def page_previous_to_code(config, action_id, template_arg, args): ), key=CONF_ID, ), + synchronous=True, ) async def page_show_to_code(config, action_id, template_arg, args): widget = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/lvgl/widgets/spinbox.py b/esphome/components/lvgl/widgets/spinbox.py index c6f25e9587..58e3435c5c 100644 --- a/esphome/components/lvgl/widgets/spinbox.py +++ b/esphome/components/lvgl/widgets/spinbox.py @@ -147,6 +147,7 @@ spinbox_spec = SpinboxType() }, key=CONF_ID, ), + synchronous=True, ) async def spinbox_increment(config, action_id, template_arg, args): widgets = await get_widgets(config) @@ -166,6 +167,7 @@ async def spinbox_increment(config, action_id, template_arg, args): }, key=CONF_ID, ), + synchronous=True, ) async def spinbox_decrement(config, action_id, template_arg, args): widgets = await get_widgets(config) diff --git a/esphome/components/lvgl/widgets/tabview.py b/esphome/components/lvgl/widgets/tabview.py index e8931bab7c..cd7cf7b471 100644 --- a/esphome/components/lvgl/widgets/tabview.py +++ b/esphome/components/lvgl/widgets/tabview.py @@ -109,6 +109,7 @@ tabview_spec = TabviewType() cv.Required(CONF_INDEX): lv_int, }, ).add_extra(cv.has_at_least_one_key(CONF_INDEX, CONF_TAB_ID)), + synchronous=True, ) async def tabview_select(config, action_id, template_arg, args): widget = await get_widgets(config) diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 5e3a95f017..430a386d2e 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -112,6 +112,7 @@ def tile_select_validate(config): cv.Optional(CONF_TILE_ID): cv.use_id(lv_tile_t), }, ).add_extra(tile_select_validate), + synchronous=True, ) async def tileview_select(config, action_id, template_arg, args): widgets = await get_widgets(config) diff --git a/esphome/components/max17043/sensor.py b/esphome/components/max17043/sensor.py index 3da0f953b0..ebb045dfce 100644 --- a/esphome/components/max17043/sensor.py +++ b/esphome/components/max17043/sensor.py @@ -71,7 +71,9 @@ MAX17043_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("max17043.sleep_mode", SleepAction, MAX17043_ACTION_SCHEMA) +@automation.register_action( + "max17043.sleep_mode", SleepAction, MAX17043_ACTION_SCHEMA, synchronous=True +) async def max17043_sleep_mode_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/max6956/__init__.py b/esphome/components/max6956/__init__.py index 0d2ff527c7..be6390fc17 100644 --- a/esphome/components/max6956/__init__.py +++ b/esphome/components/max6956/__init__.py @@ -112,6 +112,7 @@ async def max6956_pin_to_code(config): }, key=CONF_BRIGHTNESS_GLOBAL, ), + synchronous=True, ) async def max6956_set_brightness_global_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -133,6 +134,7 @@ async def max6956_set_brightness_global_to_code(config, action_id, template_arg, }, key=CONF_BRIGHTNESS_MODE, ), + synchronous=True, ) async def max6956_set_brightness_mode_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py index a251eaccea..eb751b995d 100644 --- a/esphome/components/max7219digit/display.py +++ b/esphome/components/max7219digit/display.py @@ -133,10 +133,16 @@ MAX7219_ON_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "max7219digit.invert_off", DisplayInvertAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.invert_off", + DisplayInvertAction, + MAX7219_OFF_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "max7219digit.invert_on", DisplayInvertAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.invert_on", + DisplayInvertAction, + MAX7219_ON_ACTION_SCHEMA, + synchronous=True, ) async def max7219digit_invert_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -146,10 +152,16 @@ async def max7219digit_invert_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7219digit.turn_off", DisplayVisibilityAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.turn_off", + DisplayVisibilityAction, + MAX7219_OFF_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "max7219digit.turn_on", DisplayVisibilityAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.turn_on", + DisplayVisibilityAction, + MAX7219_ON_ACTION_SCHEMA, + synchronous=True, ) async def max7219digit_visible_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -159,10 +171,16 @@ async def max7219digit_visible_to_code(config, action_id, template_arg, args): @automation.register_action( - "max7219digit.reverse_off", DisplayReverseAction, MAX7219_OFF_ACTION_SCHEMA + "max7219digit.reverse_off", + DisplayReverseAction, + MAX7219_OFF_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "max7219digit.reverse_on", DisplayReverseAction, MAX7219_ON_ACTION_SCHEMA + "max7219digit.reverse_on", + DisplayReverseAction, + MAX7219_ON_ACTION_SCHEMA, + synchronous=True, ) async def max7219digit_reverse_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -183,7 +201,10 @@ MAX7219_INTENSITY_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "max7219digit.intensity", DisplayIntensityAction, MAX7219_INTENSITY_SCHEMA + "max7219digit.intensity", + DisplayIntensityAction, + MAX7219_INTENSITY_SCHEMA, + synchronous=True, ) async def max7219digit_intensity_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 051e386eaf..a5baca2994 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -177,6 +177,7 @@ MEDIA_PLAYER_CONDITION_SCHEMA = automation.maybe_simple_id( }, key=CONF_MEDIA_URL, ), + synchronous=True, ) async def media_player_play_media_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -206,7 +207,10 @@ def _register_command_actions(): class_name, automation.Action, cg.Parented.template(MediaPlayer) ) automation.register_action( - f"media_player.{action_name}", action_class, MEDIA_PLAYER_ACTION_SCHEMA + f"media_player.{action_name}", + action_class, + MEDIA_PLAYER_ACTION_SCHEMA, + synchronous=True, )(handler) @@ -242,6 +246,7 @@ _register_state_conditions() }, key=CONF_VOLUME, ), + synchronous=True, ) async def media_player_volume_set_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/mhz19/sensor.py b/esphome/components/mhz19/sensor.py index 2841afde7a..b7d0ad1998 100644 --- a/esphome/components/mhz19/sensor.py +++ b/esphome/components/mhz19/sensor.py @@ -112,13 +112,22 @@ NO_ARGS_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "mhz19.calibrate_zero", MHZ19CalibrateZeroAction, NO_ARGS_ACTION_SCHEMA + "mhz19.calibrate_zero", + MHZ19CalibrateZeroAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "mhz19.abc_enable", MHZ19ABCEnableAction, NO_ARGS_ACTION_SCHEMA + "mhz19.abc_enable", + MHZ19ABCEnableAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "mhz19.abc_disable", MHZ19ABCDisableAction, NO_ARGS_ACTION_SCHEMA + "mhz19.abc_disable", + MHZ19ABCDisableAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def mhz19_no_args_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -137,7 +146,10 @@ RANGE_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "mhz19.detection_range_set", MHZ19DetectionRangeSetAction, RANGE_ACTION_SCHEMA + "mhz19.detection_range_set", + MHZ19DetectionRangeSetAction, + RANGE_ACTION_SCHEMA, + synchronous=True, ) async def mhz19_detection_range_set_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 74696584da..372eb4c3b0 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -529,8 +529,15 @@ async def to_code(config): MICRO_WAKE_WORD_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(MicroWakeWord)}) -@register_action("micro_wake_word.start", StartAction, MICRO_WAKE_WORD_ACTION_SCHEMA) -@register_action("micro_wake_word.stop", StopAction, MICRO_WAKE_WORD_ACTION_SCHEMA) +@register_action( + "micro_wake_word.start", + StartAction, + MICRO_WAKE_WORD_ACTION_SCHEMA, + synchronous=True, +) +@register_action( + "micro_wake_word.stop", StopAction, MICRO_WAKE_WORD_ACTION_SCHEMA, synchronous=True +) @register_condition( "micro_wake_word.is_running", IsRunningCondition, MICRO_WAKE_WORD_ACTION_SCHEMA ) @@ -551,11 +558,13 @@ MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA = automation.maybe_simple_id( "micro_wake_word.enable_model", EnableModelAction, MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA, + synchronous=True, ) @register_action( "micro_wake_word.disable_model", DisableModelAction, MICRO_WAKE_WORLD_MODEL_ACTION_SCHEMA, + synchronous=True, ) @register_condition( "micro_wake_word.model_is_enabled", diff --git a/esphome/components/microphone/__init__.py b/esphome/components/microphone/__init__.py index ce31484413..6b5ee8c3e1 100644 --- a/esphome/components/microphone/__init__.py +++ b/esphome/components/microphone/__init__.py @@ -190,19 +190,25 @@ async def microphone_action(config, action_id, template_arg, args): automation.register_action( - "microphone.capture", CaptureAction, MICROPHONE_ACTION_SCHEMA + "microphone.capture", + CaptureAction, + MICROPHONE_ACTION_SCHEMA, + synchronous=True, )(microphone_action) automation.register_action( - "microphone.stop_capture", StopCaptureAction, MICROPHONE_ACTION_SCHEMA + "microphone.stop_capture", + StopCaptureAction, + MICROPHONE_ACTION_SCHEMA, + synchronous=True, )(microphone_action) -automation.register_action("microphone.mute", MuteAction, MICROPHONE_ACTION_SCHEMA)( - microphone_action -) -automation.register_action("microphone.unmute", UnmuteAction, MICROPHONE_ACTION_SCHEMA)( - microphone_action -) +automation.register_action( + "microphone.mute", MuteAction, MICROPHONE_ACTION_SCHEMA, synchronous=True +)(microphone_action) +automation.register_action( + "microphone.unmute", UnmuteAction, MICROPHONE_ACTION_SCHEMA, synchronous=True +)(microphone_action) automation.register_condition( "microphone.is_capturing", IsCapturingCondition, MICROPHONE_ACTION_SCHEMA diff --git a/esphome/components/midea/climate.py b/esphome/components/midea/climate.py index 8a3d4f22ba..c954b45033 100644 --- a/esphome/components/midea/climate.py +++ b/esphome/components/midea/climate.py @@ -53,7 +53,9 @@ def templatize(value): def register_action(name, type_, schema): validator = templatize(schema).extend(MIDEA_ACTION_BASE_SCHEMA) - registerer = automation.register_action(f"midea_ac.{name}", type_, validator) + registerer = automation.register_action( + f"midea_ac.{name}", type_, validator, synchronous=True + ) def decorator(func): async def new_func(config, action_id, template_arg, args): diff --git a/esphome/components/mixer/speaker/__init__.py b/esphome/components/mixer/speaker/__init__.py index a3025d7121..63b419cc98 100644 --- a/esphome/components/mixer/speaker/__init__.py +++ b/esphome/components/mixer/speaker/__init__.py @@ -162,6 +162,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def ducking_set_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index c25c472038..d110d7c160 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -607,6 +607,7 @@ async def mqtt_connected_to_code(config, condition_id, template_arg, args): cv.GenerateID(): cv.use_id(MQTTClientComponent), } ), + synchronous=True, ) async def mqtt_enable_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -621,6 +622,7 @@ async def mqtt_enable_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(MQTTClientComponent), } ), + synchronous=True, ) async def mqtt_disable_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/nau7802/sensor.py b/esphome/components/nau7802/sensor.py index 9192f48f53..9798c1c297 100644 --- a/esphome/components/nau7802/sensor.py +++ b/esphome/components/nau7802/sensor.py @@ -117,16 +117,19 @@ NAU7802_CALIBRATE_SCHEMA = maybe_simple_id( "nau7802.calibrate_internal_offset", NAU7802CalbrateInternalOffsetAction, NAU7802_CALIBRATE_SCHEMA, + synchronous=True, ) @automation.register_action( "nau7802.calibrate_external_offset", NAU7802CalbrateExternalOffsetAction, NAU7802_CALIBRATE_SCHEMA, + synchronous=True, ) @automation.register_action( "nau7802.calibrate_gain", NAU7802CalbrateGainAction, NAU7802_CALIBRATE_SCHEMA, + synchronous=True, ) async def nau7802_calibrate_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/nextion/binary_sensor/__init__.py b/esphome/components/nextion/binary_sensor/__init__.py index 7ef72c6491..5b5922887c 100644 --- a/esphome/components/nextion/binary_sensor/__init__.py +++ b/esphome/components/nextion/binary_sensor/__init__.py @@ -70,6 +70,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def sensor_nextion_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index b8fcd5d8cf..5b2dfc488d 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -172,6 +172,7 @@ CONFIG_SCHEMA = cv.All( }, key=CONF_BRIGHTNESS, ), + synchronous=True, ) async def nextion_set_brightness_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/nextion/sensor/__init__.py b/esphome/components/nextion/sensor/__init__.py index 9802762ff3..cab531f1db 100644 --- a/esphome/components/nextion/sensor/__init__.py +++ b/esphome/components/nextion/sensor/__init__.py @@ -110,6 +110,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def sensor_nextion_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/nextion/switch/__init__.py b/esphome/components/nextion/switch/__init__.py index 1974ff3b9e..81e6721d0f 100644 --- a/esphome/components/nextion/switch/__init__.py +++ b/esphome/components/nextion/switch/__init__.py @@ -52,6 +52,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def sensor_nextion_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/nextion/text_sensor/__init__.py b/esphome/components/nextion/text_sensor/__init__.py index 8fc0a8ceaf..168a672497 100644 --- a/esphome/components/nextion/text_sensor/__init__.py +++ b/esphome/components/nextion/text_sensor/__init__.py @@ -48,6 +48,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def sensor_nextion_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 057244e03d..35a9de3537 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -106,9 +106,14 @@ RELEASE_IMAGE_SCHEMA = automation.maybe_simple_id( ) -@automation.register_action("online_image.set_url", SetUrlAction, SET_URL_SCHEMA) @automation.register_action( - "online_image.release", ReleaseImageAction, RELEASE_IMAGE_SCHEMA + "online_image.set_url", SetUrlAction, SET_URL_SCHEMA, synchronous=True +) +@automation.register_action( + "online_image.release", + ReleaseImageAction, + RELEASE_IMAGE_SCHEMA, + synchronous=True, ) async def online_image_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index a4c960927b..a4ce2b2d1a 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -118,6 +118,7 @@ async def output_set_level_to_code(config, action_id, template_arg, args): cv.Required(CONF_MIN_POWER): cv.templatable(cv.percentage), } ), + synchronous=True, ) async def output_set_min_power_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -136,6 +137,7 @@ async def output_set_min_power_to_code(config, action_id, template_arg, args): cv.Required(CONF_MAX_POWER): cv.templatable(cv.percentage), } ), + synchronous=True, ) async def output_set_max_power_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pcf85063/time.py b/esphome/components/pcf85063/time.py index f3c0c3230f..8e19178cc9 100644 --- a/esphome/components/pcf85063/time.py +++ b/esphome/components/pcf85063/time.py @@ -29,6 +29,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( cv.GenerateID(): cv.use_id(PCF85063Component), } ), + synchronous=True, ) async def pcf85063_write_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -44,6 +45,7 @@ async def pcf85063_write_time_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(PCF85063Component), } ), + synchronous=True, ) async def pcf85063_read_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/pcf8563/time.py b/esphome/components/pcf8563/time.py index e3b3b572aa..0d4de3cb73 100644 --- a/esphome/components/pcf8563/time.py +++ b/esphome/components/pcf8563/time.py @@ -32,6 +32,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( cv.GenerateID(): cv.use_id(pcf8563Component), } ), + synchronous=True, ) async def pcf8563_write_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -47,6 +48,7 @@ async def pcf8563_write_time_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(pcf8563Component), } ), + synchronous=True, ) async def pcf8563_read_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py index 5fa3166f9d..0e66b67637 100644 --- a/esphome/components/pid/climate.py +++ b/esphome/components/pid/climate.py @@ -133,6 +133,7 @@ async def to_code(config): cv.Required(CONF_ID): cv.use_id(PIDClimate), } ), + synchronous=True, ) async def pid_reset_integral_term(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -154,6 +155,7 @@ async def pid_reset_integral_term(config, action_id, template_arg, args): ): cv.possibly_negative_percentage, } ), + synchronous=True, ) async def esp8266_set_frequency_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -175,6 +177,7 @@ async def esp8266_set_frequency_to_code(config, action_id, template_arg, args): cv.Optional(CONF_KD, default=0.0): cv.templatable(cv.float_), } ), + synchronous=True, ) async def set_control_parameters(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pipsolar/output/__init__.py b/esphome/components/pipsolar/output/__init__.py index 829f8f7037..81e99e15a2 100644 --- a/esphome/components/pipsolar/output/__init__.py +++ b/esphome/components/pipsolar/output/__init__.py @@ -98,6 +98,7 @@ async def to_code(config): cv.Required(CONF_VALUE): cv.templatable(cv.positive_float), } ), + synchronous=True, ) async def output_pipsolar_set_level_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pmwcs3/sensor.py b/esphome/components/pmwcs3/sensor.py index 075b9b00b5..bb40f3e499 100644 --- a/esphome/components/pmwcs3/sensor.py +++ b/esphome/components/pmwcs3/sensor.py @@ -106,11 +106,13 @@ PMWCS3_CALIBRATION_SCHEMA = cv.Schema( "pmwcs3.air_calibration", PMWCS3AirCalibrationAction, PMWCS3_CALIBRATION_SCHEMA, + synchronous=True, ) @automation.register_action( "pmwcs3.water_calibration", PMWCS3WaterCalibrationAction, PMWCS3_CALIBRATION_SCHEMA, + synchronous=True, ) async def pmwcs3_calibration_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) @@ -130,6 +132,7 @@ PMWCS3_NEW_I2C_ADDRESS_SCHEMA = cv.maybe_simple_value( "pmwcs3.new_i2c_address", PMWCS3NewI2cAddressAction, PMWCS3_NEW_I2C_ADDRESS_SCHEMA, + synchronous=True, ) async def pmwcs3newi2caddress_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pn7150/__init__.py b/esphome/components/pn7150/__init__.py index 131b56e30e..6af1412881 100644 --- a/esphome/components/pn7150/__init__.py +++ b/esphome/components/pn7150/__init__.py @@ -119,11 +119,13 @@ PN7150_SCHEMA = cv.Schema( "tag.set_emulation_message", SetEmulationMessageAction, SET_MESSAGE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( "tag.set_write_message", SetWriteMessageAction, SET_MESSAGE_ACTION_SCHEMA, + synchronous=True, ) async def pn7150_set_message_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -138,22 +140,43 @@ async def pn7150_set_message_to_code(config, action_id, template_arg, args): @automation.register_action( - "tag.emulation_off", EmulationOffAction, SIMPLE_ACTION_SCHEMA -) -@automation.register_action("tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action("tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action("tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action( - "tag.set_clean_mode", SetCleanModeAction, SIMPLE_ACTION_SCHEMA + "tag.emulation_off", + EmulationOffAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "tag.set_format_mode", SetFormatModeAction, SIMPLE_ACTION_SCHEMA + "tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "tag.set_read_mode", SetReadModeAction, SIMPLE_ACTION_SCHEMA + "tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "tag.set_write_mode", SetWriteModeAction, SIMPLE_ACTION_SCHEMA + "tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "tag.set_clean_mode", + SetCleanModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_format_mode", + SetFormatModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_read_mode", + SetReadModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_write_mode", + SetWriteModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, ) async def pn7150_simple_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/pn7160/__init__.py b/esphome/components/pn7160/__init__.py index 899ecd595e..54e4b74796 100644 --- a/esphome/components/pn7160/__init__.py +++ b/esphome/components/pn7160/__init__.py @@ -123,11 +123,13 @@ PN7160_SCHEMA = cv.Schema( "tag.set_emulation_message", SetEmulationMessageAction, SET_MESSAGE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( "tag.set_write_message", SetWriteMessageAction, SET_MESSAGE_ACTION_SCHEMA, + synchronous=True, ) async def pn7160_set_message_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -142,22 +144,43 @@ async def pn7160_set_message_to_code(config, action_id, template_arg, args): @automation.register_action( - "tag.emulation_off", EmulationOffAction, SIMPLE_ACTION_SCHEMA -) -@automation.register_action("tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action("tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action("tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA) -@automation.register_action( - "tag.set_clean_mode", SetCleanModeAction, SIMPLE_ACTION_SCHEMA + "tag.emulation_off", + EmulationOffAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "tag.set_format_mode", SetFormatModeAction, SIMPLE_ACTION_SCHEMA + "tag.emulation_on", EmulationOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "tag.set_read_mode", SetReadModeAction, SIMPLE_ACTION_SCHEMA + "tag.polling_off", PollingOffAction, SIMPLE_ACTION_SCHEMA, synchronous=True ) @automation.register_action( - "tag.set_write_mode", SetWriteModeAction, SIMPLE_ACTION_SCHEMA + "tag.polling_on", PollingOnAction, SIMPLE_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "tag.set_clean_mode", + SetCleanModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_format_mode", + SetFormatModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_read_mode", + SetReadModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "tag.set_write_mode", + SetWriteModeAction, + SIMPLE_ACTION_SCHEMA, + synchronous=True, ) async def pn7160_simple_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/pulse_counter/sensor.py b/esphome/components/pulse_counter/sensor.py index 0124463567..c09d778eda 100644 --- a/esphome/components/pulse_counter/sensor.py +++ b/esphome/components/pulse_counter/sensor.py @@ -155,6 +155,7 @@ async def to_code(config): cv.Required(CONF_VALUE): cv.templatable(cv.uint32_t), } ), + synchronous=True, ) async def set_total_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pulse_meter/sensor.py b/esphome/components/pulse_meter/sensor.py index ca026eefa4..499b7309c8 100644 --- a/esphome/components/pulse_meter/sensor.py +++ b/esphome/components/pulse_meter/sensor.py @@ -105,6 +105,7 @@ async def to_code(config): cv.Required(CONF_VALUE): cv.templatable(cv.uint32_t), } ), + synchronous=True, ) async def set_total_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pzemac/sensor.py b/esphome/components/pzemac/sensor.py index 3af73b8695..fa1c3961d0 100644 --- a/esphome/components/pzemac/sensor.py +++ b/esphome/components/pzemac/sensor.py @@ -88,6 +88,7 @@ CONFIG_SCHEMA = ( cv.Required(CONF_ID): cv.use_id(PZEMAC), } ), + synchronous=True, ) async def reset_energy_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pzemdc/sensor.py b/esphome/components/pzemdc/sensor.py index 383a9dbb2c..3291be4c34 100644 --- a/esphome/components/pzemdc/sensor.py +++ b/esphome/components/pzemdc/sensor.py @@ -72,6 +72,7 @@ CONFIG_SCHEMA = ( cv.GenerateID(CONF_ID): cv.use_id(PZEMDC), } ), + synchronous=True, ) async def reset_energy_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index 9d3e655c57..bf17ac27b8 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -163,7 +163,10 @@ BASE_REMOTE_TRANSMITTER_SCHEMA = cv.Schema( def register_action(name, type_, schema): validator = templatize(schema).extend(BASE_REMOTE_TRANSMITTER_SCHEMA) registerer = automation.register_action( - f"remote_transmitter.transmit_{name}", type_, validator + f"remote_transmitter.transmit_{name}", + type_, + validator, + synchronous=True, ) def decorator(func): diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index 371dbb685f..89019e296e 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -120,7 +120,10 @@ DIGITAL_WRITE_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "remote_transmitter.digital_write", DigitalWriteAction, DIGITAL_WRITE_ACTION_SCHEMA + "remote_transmitter.digital_write", + DigitalWriteAction, + DIGITAL_WRITE_ACTION_SCHEMA, + synchronous=True, ) async def digital_write_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/rf_bridge/__init__.py b/esphome/components/rf_bridge/__init__.py index b4770726b4..934f24b789 100644 --- a/esphome/components/rf_bridge/__init__.py +++ b/esphome/components/rf_bridge/__init__.py @@ -114,7 +114,10 @@ RFBRIDGE_SEND_CODE_SCHEMA = cv.Schema( @automation.register_action( - "rf_bridge.send_code", RFBridgeSendCodeAction, RFBRIDGE_SEND_CODE_SCHEMA + "rf_bridge.send_code", + RFBridgeSendCodeAction, + RFBRIDGE_SEND_CODE_SCHEMA, + synchronous=True, ) async def rf_bridge_send_code_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) @@ -133,7 +136,9 @@ async def rf_bridge_send_code_to_code(config, action_id, template_args, args): RFBRIDGE_ID_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(RFBridgeComponent)}) -@automation.register_action("rf_bridge.learn", RFBridgeLearnAction, RFBRIDGE_ID_SCHEMA) +@automation.register_action( + "rf_bridge.learn", RFBridgeLearnAction, RFBRIDGE_ID_SCHEMA, synchronous=True +) async def rf_bridge_learnx_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_args, paren) @@ -143,6 +148,7 @@ async def rf_bridge_learnx_to_code(config, action_id, template_args, args): "rf_bridge.start_advanced_sniffing", RFBridgeStartAdvancedSniffingAction, RFBRIDGE_ID_SCHEMA, + synchronous=True, ) async def rf_bridge_start_advanced_sniffing_to_code( config, action_id, template_args, args @@ -155,6 +161,7 @@ async def rf_bridge_start_advanced_sniffing_to_code( "rf_bridge.stop_advanced_sniffing", RFBridgeStopAdvancedSniffingAction, RFBRIDGE_ID_SCHEMA, + synchronous=True, ) async def rf_bridge_stop_advanced_sniffing_to_code( config, action_id, template_args, args @@ -167,6 +174,7 @@ async def rf_bridge_stop_advanced_sniffing_to_code( "rf_bridge.start_bucket_sniffing", RFBridgeStartBucketSniffingAction, RFBRIDGE_ID_SCHEMA, + synchronous=True, ) async def rf_bridge_start_bucket_sniffing_to_code( config, action_id, template_args, args @@ -189,6 +197,7 @@ RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA = cv.Schema( "rf_bridge.send_advanced_code", RFBridgeSendAdvancedCodeAction, RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA, + synchronous=True, ) async def rf_bridge_send_advanced_code_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) @@ -211,7 +220,10 @@ RFBRIDGE_SEND_RAW_SCHEMA = cv.Schema( @automation.register_action( - "rf_bridge.send_raw", RFBridgeSendRawAction, RFBRIDGE_SEND_RAW_SCHEMA + "rf_bridge.send_raw", + RFBridgeSendRawAction, + RFBRIDGE_SEND_RAW_SCHEMA, + synchronous=True, ) async def rf_bridge_send_raw_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) @@ -229,7 +241,9 @@ RFBRIDGE_BEEP_SCHEMA = cv.Schema( ) -@automation.register_action("rf_bridge.beep", RFBridgeBeepAction, RFBRIDGE_BEEP_SCHEMA) +@automation.register_action( + "rf_bridge.beep", RFBridgeBeepAction, RFBRIDGE_BEEP_SCHEMA, synchronous=True +) async def rf_bridge_beep_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_args, paren) diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index 645b4a81c5..be315db55d 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -139,6 +139,7 @@ async def to_code(config): cv.Required(CONF_VALUE): cv.templatable(cv.int_), } ), + synchronous=True, ) async def sensor_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/rp2040_pwm/output.py b/esphome/components/rp2040_pwm/output.py index 441a52de7f..4ea488a6cd 100644 --- a/esphome/components/rp2040_pwm/output.py +++ b/esphome/components/rp2040_pwm/output.py @@ -42,6 +42,7 @@ async def to_code(config): cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), } ), + synchronous=True, ) async def rp2040_set_frequency_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/rtttl/__init__.py b/esphome/components/rtttl/__init__.py index 19412bb454..3566734200 100644 --- a/esphome/components/rtttl/__init__.py +++ b/esphome/components/rtttl/__init__.py @@ -117,6 +117,7 @@ async def to_code(config): }, key=CONF_RTTTL, ), + synchronous=True, ) async def rtttl_play_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -134,6 +135,7 @@ async def rtttl_play_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(Rtttl), } ), + synchronous=True, ) async def rtttl_stop_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/rx8130/time.py b/esphome/components/rx8130/time.py index cb0402bd32..4f6310358c 100644 --- a/esphome/components/rx8130/time.py +++ b/esphome/components/rx8130/time.py @@ -27,6 +27,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( cv.GenerateID(): cv.use_id(RX8130Component), } ), + synchronous=True, ) async def rx8130_write_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -42,6 +43,7 @@ async def rx8130_write_time_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(RX8130Component), } ), + synchronous=True, ) async def rx8130_read_time_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index f54151b746..e868985054 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -62,6 +62,7 @@ CONFIG_SCHEMA = cv.All( cv.GenerateID(): cv.use_id(SafeModeComponent), } ), + synchronous=True, ) async def safe_mode_mark_successful_to_code(config, action_id, template_arg, args): parent = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index 194df8ec4f..f60e913a0c 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -128,6 +128,7 @@ async def to_code(config): }, key=CONF_VALUE, ), + synchronous=True, ) async def scd30_force_recalibration_with_reference_to_code( config, action_id, template_arg, args diff --git a/esphome/components/scd4x/sensor.py b/esphome/components/scd4x/sensor.py index ec90234ac3..6f14118660 100644 --- a/esphome/components/scd4x/sensor.py +++ b/esphome/components/scd4x/sensor.py @@ -141,6 +141,7 @@ SCD4X_ACTION_SCHEMA = maybe_simple_id( "scd4x.perform_forced_calibration", PerformForcedCalibrationAction, SCD4X_ACTION_SCHEMA, + synchronous=True, ) async def scd4x_frc_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -158,7 +159,10 @@ SCD4X_RESET_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "scd4x.factory_reset", FactoryResetAction, SCD4X_RESET_ACTION_SCHEMA + "scd4x.factory_reset", + FactoryResetAction, + SCD4X_RESET_ACTION_SCHEMA, + synchronous=True, ) async def scd4x_reset_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/script/__init__.py b/esphome/components/script/__init__.py index 369cefad91..51cae695b7 100644 --- a/esphome/components/script/__init__.py +++ b/esphome/components/script/__init__.py @@ -221,6 +221,7 @@ async def script_stop_action_to_code(config, action_id, template_arg, args): "script.wait", ScriptWaitAction, maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}), + synchronous=False, ) async def script_wait_action_to_code(config, action_id, template_arg, args): full_id, paren = await cg.get_variable_with_full_id(config[CONF_ID]) diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 538a2f5239..9fe51121f1 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -267,7 +267,10 @@ SEN5X_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "sen5x.start_fan_autoclean", StartFanAction, SEN5X_ACTION_SCHEMA + "sen5x.start_fan_autoclean", + StartFanAction, + SEN5X_ACTION_SCHEMA, + synchronous=True, ) async def sen54_fan_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/senseair/sensor.py b/esphome/components/senseair/sensor.py index 2eb2617e30..c5bef76741 100644 --- a/esphome/components/senseair/sensor.py +++ b/esphome/components/senseair/sensor.py @@ -73,20 +73,31 @@ CALIBRATION_ACTION_SCHEMA = maybe_simple_id( "senseair.background_calibration", SenseAirBackgroundCalibrationAction, CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( "senseair.background_calibration_result", SenseAirBackgroundCalibrationResultAction, CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "senseair.abc_enable", SenseAirABCEnableAction, CALIBRATION_ACTION_SCHEMA + "senseair.abc_enable", + SenseAirABCEnableAction, + CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "senseair.abc_disable", SenseAirABCDisableAction, CALIBRATION_ACTION_SCHEMA + "senseair.abc_disable", + SenseAirABCDisableAction, + CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "senseair.abc_get_period", SenseAirABCGetPeriodAction, CALIBRATION_ACTION_SCHEMA + "senseair.abc_get_period", + SenseAirABCGetPeriodAction, + CALIBRATION_ACTION_SCHEMA, + synchronous=True, ) async def senseair_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/servo/__init__.py b/esphome/components/servo/__init__.py index 2fee2840a5..a23bb53536 100644 --- a/esphome/components/servo/__init__.py +++ b/esphome/components/servo/__init__.py @@ -62,6 +62,7 @@ async def to_code(config): cv.Required(CONF_LEVEL): cv.templatable(cv.possibly_negative_percentage), } ), + synchronous=True, ) async def servo_write_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -79,6 +80,7 @@ async def servo_write_to_code(config, action_id, template_arg, args): cv.Required(CONF_ID): cv.use_id(Servo), } ), + synchronous=True, ) async def servo_detach_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/sim800l/__init__.py b/esphome/components/sim800l/__init__.py index c48a3c63c4..ebb74302a9 100644 --- a/esphome/components/sim800l/__init__.py +++ b/esphome/components/sim800l/__init__.py @@ -135,7 +135,10 @@ SIM800L_SEND_SMS_SCHEMA = cv.Schema( @automation.register_action( - "sim800l.send_sms", Sim800LSendSmsAction, SIM800L_SEND_SMS_SCHEMA + "sim800l.send_sms", + Sim800LSendSmsAction, + SIM800L_SEND_SMS_SCHEMA, + synchronous=True, ) async def sim800l_send_sms_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -155,7 +158,9 @@ SIM800L_DIAL_SCHEMA = cv.Schema( ) -@automation.register_action("sim800l.dial", Sim800LDialAction, SIM800L_DIAL_SCHEMA) +@automation.register_action( + "sim800l.dial", Sim800LDialAction, SIM800L_DIAL_SCHEMA, synchronous=True +) async def sim800l_dial_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) @@ -168,6 +173,7 @@ async def sim800l_dial_to_code(config, action_id, template_arg, args): "sim800l.connect", Sim800LConnectAction, cv.Schema({cv.GenerateID(): cv.use_id(Sim800LComponent)}), + synchronous=True, ) async def sim800l_connect_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -183,7 +189,10 @@ SIM800L_SEND_USSD_SCHEMA = cv.Schema( @automation.register_action( - "sim800l.send_ussd", Sim800LSendUssdAction, SIM800L_SEND_USSD_SCHEMA + "sim800l.send_ussd", + Sim800LSendUssdAction, + SIM800L_SEND_USSD_SCHEMA, + synchronous=True, ) async def sim800l_send_ussd_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -197,6 +206,7 @@ async def sim800l_send_ussd_to_code(config, action_id, template_arg, args): "sim800l.disconnect", Sim800LDisconnectAction, cv.Schema({cv.GenerateID(): cv.use_id(Sim800LComponent)}), + synchronous=True, ) async def sim800l_disconnect_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/sound_level/sensor.py b/esphome/components/sound_level/sensor.py index 8ca0feccc0..44f31979b4 100644 --- a/esphome/components/sound_level/sensor.py +++ b/esphome/components/sound_level/sensor.py @@ -89,8 +89,12 @@ SOUND_LEVEL_ACTION_SCHEMA = automation.maybe_simple_id( ) -@automation.register_action("sound_level.start", StartAction, SOUND_LEVEL_ACTION_SCHEMA) -@automation.register_action("sound_level.stop", StopAction, SOUND_LEVEL_ACTION_SCHEMA) +@automation.register_action( + "sound_level.start", StartAction, SOUND_LEVEL_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "sound_level.stop", StopAction, SOUND_LEVEL_ACTION_SCHEMA, synchronous=True +) async def sound_level_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/speaker/__init__.py b/esphome/components/speaker/__init__.py index 10ee6d5212..8480eebcdb 100644 --- a/esphome/components/speaker/__init__.py +++ b/esphome/components/speaker/__init__.py @@ -78,6 +78,7 @@ async def speaker_action(config, action_id, template_arg, args): }, key=CONF_DATA, ), + synchronous=True, ) async def speaker_play_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -95,12 +96,12 @@ async def speaker_play_action(config, action_id, template_arg, args): return var -automation.register_action("speaker.stop", StopAction, SPEAKER_AUTOMATION_SCHEMA)( - speaker_action -) -automation.register_action("speaker.finish", FinishAction, SPEAKER_AUTOMATION_SCHEMA)( - speaker_action -) +automation.register_action( + "speaker.stop", StopAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True +)(speaker_action) +automation.register_action( + "speaker.finish", FinishAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True +)(speaker_action) automation.register_condition( "speaker.is_playing", IsPlayingCondition, SPEAKER_AUTOMATION_SCHEMA @@ -121,6 +122,7 @@ automation.register_condition( }, key=CONF_VOLUME, ), + synchronous=True, ) async def speaker_volume_set_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -131,9 +133,14 @@ async def speaker_volume_set_action(config, action_id, template_arg, args): @automation.register_action( - "speaker.mute_off", MuteOffAction, SPEAKER_AUTOMATION_SCHEMA + "speaker.mute_off", + MuteOffAction, + SPEAKER_AUTOMATION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "speaker.mute_on", MuteOnAction, SPEAKER_AUTOMATION_SCHEMA, synchronous=True ) -@automation.register_action("speaker.mute_on", MuteOnAction, SPEAKER_AUTOMATION_SCHEMA) async def speaker_mute_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) diff --git a/esphome/components/speaker/media_player/__init__.py b/esphome/components/speaker/media_player/__init__.py index 42ca762858..92a178fe95 100644 --- a/esphome/components/speaker/media_player/__init__.py +++ b/esphome/components/speaker/media_player/__init__.py @@ -505,6 +505,7 @@ async def to_code(config): }, key=CONF_MEDIA_FILE, ), + synchronous=True, ) async def play_on_device_media_media_action(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/sprinkler/__init__.py b/esphome/components/sprinkler/__init__.py index 50c69f9496..6e2ff4ee2e 100644 --- a/esphome/components/sprinkler/__init__.py +++ b/esphome/components/sprinkler/__init__.py @@ -422,6 +422,7 @@ CONFIG_SCHEMA = cv.All( "sprinkler.set_divider", SetDividerAction, SPRINKLER_ACTION_SET_DIVIDER_SCHEMA, + synchronous=True, ) async def sprinkler_set_divider_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -435,6 +436,7 @@ async def sprinkler_set_divider_to_code(config, action_id, template_arg, args): "sprinkler.set_multiplier", SetMultiplierAction, SPRINKLER_ACTION_SET_MULTIPLIER_SCHEMA, + synchronous=True, ) async def sprinkler_set_multiplier_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -448,6 +450,7 @@ async def sprinkler_set_multiplier_to_code(config, action_id, template_arg, args "sprinkler.queue_valve", QueueValveAction, SPRINKLER_ACTION_QUEUE_VALVE_SCHEMA, + synchronous=True, ) async def sprinkler_set_queued_valve_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -463,6 +466,7 @@ async def sprinkler_set_queued_valve_to_code(config, action_id, template_arg, ar "sprinkler.set_repeat", SetRepeatAction, SPRINKLER_ACTION_REPEAT_SCHEMA, + synchronous=True, ) async def sprinkler_set_repeat_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -476,6 +480,7 @@ async def sprinkler_set_repeat_to_code(config, action_id, template_arg, args): "sprinkler.set_valve_run_duration", SetRunDurationAction, SPRINKLER_ACTION_SET_RUN_DURATION_SCHEMA, + synchronous=True, ) async def sprinkler_set_valve_run_duration_to_code( config, action_id, template_arg, args @@ -490,7 +495,10 @@ async def sprinkler_set_valve_run_duration_to_code( @automation.register_action( - "sprinkler.start_from_queue", StartFromQueueAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.start_from_queue", + StartFromQueueAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) async def sprinkler_start_from_queue_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -498,7 +506,10 @@ async def sprinkler_start_from_queue_to_code(config, action_id, template_arg, ar @automation.register_action( - "sprinkler.start_full_cycle", StartFullCycleAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.start_full_cycle", + StartFullCycleAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) async def sprinkler_start_full_cycle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -509,6 +520,7 @@ async def sprinkler_start_full_cycle_to_code(config, action_id, template_arg, ar "sprinkler.start_single_valve", StartSingleValveAction, SPRINKLER_ACTION_SINGLE_VALVE_SCHEMA, + synchronous=True, ) async def sprinkler_start_single_valve_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -522,21 +534,40 @@ async def sprinkler_start_single_valve_to_code(config, action_id, template_arg, @automation.register_action( - "sprinkler.clear_queued_valves", ClearQueuedValvesAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.clear_queued_valves", + ClearQueuedValvesAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sprinkler.next_valve", NextValveAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.next_valve", + NextValveAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sprinkler.previous_valve", PreviousValveAction, SPRINKLER_ACTION_SCHEMA -) -@automation.register_action("sprinkler.pause", PauseAction, SPRINKLER_ACTION_SCHEMA) -@automation.register_action("sprinkler.resume", ResumeAction, SPRINKLER_ACTION_SCHEMA) -@automation.register_action( - "sprinkler.resume_or_start_full_cycle", ResumeOrStartAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.previous_valve", + PreviousValveAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sprinkler.shutdown", ShutdownAction, SPRINKLER_ACTION_SCHEMA + "sprinkler.pause", PauseAction, SPRINKLER_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "sprinkler.resume", ResumeAction, SPRINKLER_ACTION_SCHEMA, synchronous=True +) +@automation.register_action( + "sprinkler.resume_or_start_full_cycle", + ResumeOrStartAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, +) +@automation.register_action( + "sprinkler.shutdown", + ShutdownAction, + SPRINKLER_ACTION_SCHEMA, + synchronous=True, ) async def sprinkler_simple_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/sps30/sensor.py b/esphome/components/sps30/sensor.py index 3c967fc01b..40557f2cbd 100644 --- a/esphome/components/sps30/sensor.py +++ b/esphome/components/sps30/sensor.py @@ -180,13 +180,22 @@ SPS30_ACTION_SCHEMA = maybe_simple_id( @automation.register_action( - "sps30.start_fan_autoclean", StartFanAction, SPS30_ACTION_SCHEMA + "sps30.start_fan_autoclean", + StartFanAction, + SPS30_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sps30.start_measurement", StartMeasurementAction, SPS30_ACTION_SCHEMA + "sps30.start_measurement", + StartMeasurementAction, + SPS30_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sps30.stop_measurement", StopMeasurementAction, SPS30_ACTION_SCHEMA + "sps30.stop_measurement", + StopMeasurementAction, + SPS30_ACTION_SCHEMA, + synchronous=True, ) async def sps30_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/stepper/__init__.py b/esphome/components/stepper/__init__.py index 62bc71f2d1..27d4fc276d 100644 --- a/esphome/components/stepper/__init__.py +++ b/esphome/components/stepper/__init__.py @@ -97,6 +97,7 @@ async def register_stepper(var, config): cv.Required(CONF_TARGET): cv.templatable(cv.int_), } ), + synchronous=True, ) async def stepper_set_target_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -115,6 +116,7 @@ async def stepper_set_target_to_code(config, action_id, template_arg, args): cv.Required(CONF_POSITION): cv.templatable(cv.int_), } ), + synchronous=True, ) async def stepper_report_position_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -133,6 +135,7 @@ async def stepper_report_position_to_code(config, action_id, template_arg, args) cv.Required(CONF_SPEED): cv.templatable(validate_speed), } ), + synchronous=True, ) async def stepper_set_speed_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -151,6 +154,7 @@ async def stepper_set_speed_to_code(config, action_id, template_arg, args): cv.Required(CONF_ACCELERATION): cv.templatable(validate_acceleration), } ), + synchronous=True, ) async def stepper_set_acceleration_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -169,6 +173,7 @@ async def stepper_set_acceleration_to_code(config, action_id, template_arg, args cv.Required(CONF_DECELERATION): cv.templatable(validate_acceleration), } ), + synchronous=True, ) async def stepper_set_deceleration_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/sx126x/__init__.py b/esphome/components/sx126x/__init__.py index 413eb139d6..08f4c0fb88 100644 --- a/esphome/components/sx126x/__init__.py +++ b/esphome/components/sx126x/__init__.py @@ -290,19 +290,34 @@ NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "sx126x.run_image_cal", RunImageCalAction, NO_ARGS_ACTION_SCHEMA + "sx126x.run_image_cal", + RunImageCalAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx126x.set_mode_tx", SetModeTxAction, NO_ARGS_ACTION_SCHEMA + "sx126x.set_mode_tx", + SetModeTxAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx126x.set_mode_rx", SetModeRxAction, NO_ARGS_ACTION_SCHEMA + "sx126x.set_mode_rx", + SetModeRxAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx126x.set_mode_sleep", SetModeSleepAction, NO_ARGS_ACTION_SCHEMA + "sx126x.set_mode_sleep", + SetModeSleepAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx126x.set_mode_standby", SetModeStandbyAction, NO_ARGS_ACTION_SCHEMA + "sx126x.set_mode_standby", + SetModeStandbyAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def no_args_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -320,7 +335,10 @@ SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "sx126x.send_packet", SendPacketAction, SEND_PACKET_ACTION_SCHEMA + "sx126x.send_packet", + SendPacketAction, + SEND_PACKET_ACTION_SCHEMA, + synchronous=True, ) async def send_packet_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/sx127x/__init__.py b/esphome/components/sx127x/__init__.py index f3a9cca93f..7f554fbf84 100644 --- a/esphome/components/sx127x/__init__.py +++ b/esphome/components/sx127x/__init__.py @@ -283,19 +283,34 @@ NO_ARGS_ACTION_SCHEMA = automation.maybe_simple_id( @automation.register_action( - "sx127x.run_image_cal", RunImageCalAction, NO_ARGS_ACTION_SCHEMA + "sx127x.run_image_cal", + RunImageCalAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx127x.set_mode_tx", SetModeTxAction, NO_ARGS_ACTION_SCHEMA + "sx127x.set_mode_tx", + SetModeTxAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx127x.set_mode_rx", SetModeRxAction, NO_ARGS_ACTION_SCHEMA + "sx127x.set_mode_rx", + SetModeRxAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx127x.set_mode_sleep", SetModeSleepAction, NO_ARGS_ACTION_SCHEMA + "sx127x.set_mode_sleep", + SetModeSleepAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) @automation.register_action( - "sx127x.set_mode_standby", SetModeStandbyAction, NO_ARGS_ACTION_SCHEMA + "sx127x.set_mode_standby", + SetModeStandbyAction, + NO_ARGS_ACTION_SCHEMA, + synchronous=True, ) async def no_args_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -313,7 +328,10 @@ SEND_PACKET_ACTION_SCHEMA = cv.maybe_simple_value( @automation.register_action( - "sx127x.send_packet", SendPacketAction, SEND_PACKET_ACTION_SCHEMA + "sx127x.send_packet", + SendPacketAction, + SEND_PACKET_ACTION_SCHEMA, + synchronous=True, ) async def send_packet_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/template/binary_sensor/__init__.py b/esphome/components/template/binary_sensor/__init__.py index 9d4208dcca..e537e1f97c 100644 --- a/esphome/components/template/binary_sensor/__init__.py +++ b/esphome/components/template/binary_sensor/__init__.py @@ -59,6 +59,7 @@ async def to_code(config): cv.Required(CONF_STATE): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def binary_sensor_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/template/cover/__init__.py b/esphome/components/template/cover/__init__.py index a4fb0b7021..cfc19c00cd 100644 --- a/esphome/components/template/cover/__init__.py +++ b/esphome/components/template/cover/__init__.py @@ -125,6 +125,7 @@ async def to_code(config): cv.Optional(CONF_TILT): cv.templatable(cv.zero_to_one_float), } ), + synchronous=True, ) async def cover_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/template/lock/__init__.py b/esphome/components/template/lock/__init__.py index 4c74a521fa..d8bd9d16c6 100644 --- a/esphome/components/template/lock/__init__.py +++ b/esphome/components/template/lock/__init__.py @@ -90,6 +90,7 @@ async def to_code(config): }, key=CONF_STATE, ), + synchronous=True, ) async def lock_template_publish_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/template/sensor/__init__.py b/esphome/components/template/sensor/__init__.py index 2c325427e9..b0f48ade46 100644 --- a/esphome/components/template/sensor/__init__.py +++ b/esphome/components/template/sensor/__init__.py @@ -44,6 +44,7 @@ async def to_code(config): cv.Required(CONF_STATE): cv.templatable(cv.float_), } ), + synchronous=True, ) async def sensor_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/template/switch/__init__.py b/esphome/components/template/switch/__init__.py index 8ae5a07dc3..eb6f0f46de 100644 --- a/esphome/components/template/switch/__init__.py +++ b/esphome/components/template/switch/__init__.py @@ -80,6 +80,7 @@ async def to_code(config): cv.Required(CONF_STATE): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def switch_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/template/text_sensor/__init__.py b/esphome/components/template/text_sensor/__init__.py index 550b27356d..ddbdd6dadb 100644 --- a/esphome/components/template/text_sensor/__init__.py +++ b/esphome/components/template/text_sensor/__init__.py @@ -43,6 +43,7 @@ async def to_code(config): cv.Required(CONF_STATE): cv.templatable(cv.string_strict), } ), + synchronous=True, ) async def text_sensor_template_publish_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/template/valve/__init__.py b/esphome/components/template/valve/__init__.py index 526751564d..3e8fd81603 100644 --- a/esphome/components/template/valve/__init__.py +++ b/esphome/components/template/valve/__init__.py @@ -112,6 +112,7 @@ async def to_code(config): ), } ), + synchronous=True, ) async def valve_template_publish_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/template/water_heater/__init__.py b/esphome/components/template/water_heater/__init__.py index cb5f2dbe56..814aa40193 100644 --- a/esphome/components/template/water_heater/__init__.py +++ b/esphome/components/template/water_heater/__init__.py @@ -134,6 +134,7 @@ async def to_code(config: ConfigType) -> None: cv.Optional(CONF_IS_ON): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def water_heater_template_publish_to_code( config: ConfigType, diff --git a/esphome/components/tm1651/__init__.py b/esphome/components/tm1651/__init__.py index 49796d9b42..fb35eb21b5 100644 --- a/esphome/components/tm1651/__init__.py +++ b/esphome/components/tm1651/__init__.py @@ -73,6 +73,7 @@ BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id( }, key=CONF_BRIGHTNESS, ), + synchronous=True, ) async def tm1651_set_brightness_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -92,6 +93,7 @@ async def tm1651_set_brightness_to_code(config, action_id, template_arg, args): }, key=CONF_LEVEL, ), + synchronous=True, ) async def tm1651_set_level_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -111,6 +113,7 @@ async def tm1651_set_level_to_code(config, action_id, template_arg, args): }, key=CONF_LEVEL_PERCENT, ), + synchronous=True, ) async def tm1651_set_level_percent_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -121,7 +124,10 @@ async def tm1651_set_level_percent_to_code(config, action_id, template_arg, args @automation.register_action( - "tm1651.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA + "tm1651.turn_off", + TurnOffAction, + BINARY_OUTPUT_ACTION_SCHEMA, + synchronous=True, ) async def output_turn_off_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -129,7 +135,9 @@ async def output_turn_off_to_code(config, action_id, template_arg, args): return var -@automation.register_action("tm1651.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action( + "tm1651.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA, synchronous=True +) async def output_turn_on_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 2cb6eac050..83649cc209 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -500,6 +500,7 @@ async def register_uart_device(var, config): }, key=CONF_DATA, ), + synchronous=True, ) async def uart_write_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 37dd871a6c..17bbf19c9e 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -171,6 +171,7 @@ def validate_raw_data(value): }, key=CONF_DATA, ), + synchronous=True, ) async def udp_write_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/ufire_ec/sensor.py b/esphome/components/ufire_ec/sensor.py index 9edf0f89ff..10b4ece614 100644 --- a/esphome/components/ufire_ec/sensor.py +++ b/esphome/components/ufire_ec/sensor.py @@ -97,6 +97,7 @@ UFIRE_EC_CALIBRATE_PROBE_SCHEMA = cv.Schema( "ufire_ec.calibrate_probe", UFireECCalibrateProbeAction, UFIRE_EC_CALIBRATE_PROBE_SCHEMA, + synchronous=True, ) async def ufire_ec_calibrate_probe_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -119,6 +120,7 @@ UFIRE_EC_RESET_SCHEMA = cv.Schema( "ufire_ec.reset", UFireECResetAction, UFIRE_EC_RESET_SCHEMA, + synchronous=True, ) async def ufire_ec_reset_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/ufire_ise/sensor.py b/esphome/components/ufire_ise/sensor.py index 8009cdaa6a..a116012d05 100644 --- a/esphome/components/ufire_ise/sensor.py +++ b/esphome/components/ufire_ise/sensor.py @@ -91,6 +91,7 @@ UFIRE_ISE_CALIBRATE_PROBE_SCHEMA = cv.Schema( "ufire_ise.calibrate_probe_low", UFireISECalibrateProbeLowAction, UFIRE_ISE_CALIBRATE_PROBE_SCHEMA, + synchronous=True, ) async def ufire_ise_calibrate_probe_low_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -104,6 +105,7 @@ async def ufire_ise_calibrate_probe_low_to_code(config, action_id, template_arg, "ufire_ise.calibrate_probe_high", UFireISECalibrateProbeHighAction, UFIRE_ISE_CALIBRATE_PROBE_SCHEMA, + synchronous=True, ) async def ufire_ise_calibrate_probe_high_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) @@ -120,6 +122,7 @@ UFIRE_ISE_RESET_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(UFireISEComponent "ufire_ise.reset", UFireISEResetAction, UFIRE_ISE_RESET_SCHEMA, + synchronous=True, ) async def ufire_ise_reset_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/update/__init__.py b/esphome/components/update/__init__.py index c36a4ab769..db6c1445e3 100644 --- a/esphome/components/update/__init__.py +++ b/esphome/components/update/__init__.py @@ -138,6 +138,7 @@ async def to_code(config): cv.Optional(CONF_FORCE_UPDATE, default=False): cv.templatable(cv.boolean), } ), + synchronous=True, ) async def update_perform_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -156,6 +157,7 @@ async def update_perform_action_to_code(config, action_id, template_arg, args): cv.GenerateID(): cv.use_id(UpdateEntity), } ), + synchronous=True, ) async def update_check_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/valve/__init__.py b/esphome/components/valve/__init__.py index 22cd01988d..0319ff50e7 100644 --- a/esphome/components/valve/__init__.py +++ b/esphome/components/valve/__init__.py @@ -180,25 +180,33 @@ VALVE_ACTION_SCHEMA = maybe_simple_id( ) -@automation.register_action("valve.open", OpenAction, VALVE_ACTION_SCHEMA) +@automation.register_action( + "valve.open", OpenAction, VALVE_ACTION_SCHEMA, synchronous=True +) async def valve_open_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("valve.close", CloseAction, VALVE_ACTION_SCHEMA) +@automation.register_action( + "valve.close", CloseAction, VALVE_ACTION_SCHEMA, synchronous=True +) async def valve_close_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("valve.stop", StopAction, VALVE_ACTION_SCHEMA) +@automation.register_action( + "valve.stop", StopAction, VALVE_ACTION_SCHEMA, synchronous=True +) async def valve_stop_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) -@automation.register_action("valve.toggle", ToggleAction, VALVE_ACTION_SCHEMA) +@automation.register_action( + "valve.toggle", ToggleAction, VALVE_ACTION_SCHEMA, synchronous=True +) async def valve_toggle_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @@ -214,7 +222,9 @@ VALVE_CONTROL_ACTION_SCHEMA = cv.Schema( ) -@automation.register_action("valve.control", ControlAction, VALVE_CONTROL_ACTION_SCHEMA) +@automation.register_action( + "valve.control", ControlAction, VALVE_CONTROL_ACTION_SCHEMA, synchronous=True +) async def valve_control_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) diff --git a/esphome/components/voice_assistant/__init__.py b/esphome/components/voice_assistant/__init__.py index 8b7dcb4f21..d970df2a44 100644 --- a/esphome/components/voice_assistant/__init__.py +++ b/esphome/components/voice_assistant/__init__.py @@ -393,6 +393,7 @@ VOICE_ASSISTANT_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(VoiceAssis "voice_assistant.start_continuous", StartContinuousAction, VOICE_ASSISTANT_ACTION_SCHEMA, + synchronous=True, ) @register_action( "voice_assistant.start", @@ -403,6 +404,7 @@ VOICE_ASSISTANT_ACTION_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(VoiceAssis cv.Optional(CONF_WAKE_WORD): cv.templatable(cv.string), } ), + synchronous=True, ) async def voice_assistant_listen_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -415,7 +417,9 @@ async def voice_assistant_listen_to_code(config, action_id, template_arg, args): return var -@register_action("voice_assistant.stop", StopAction, VOICE_ASSISTANT_ACTION_SCHEMA) +@register_action( + "voice_assistant.stop", StopAction, VOICE_ASSISTANT_ACTION_SCHEMA, synchronous=True +) async def voice_assistant_stop_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 0f86ec059e..2808d31311 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -670,12 +670,16 @@ async def wifi_ap_active_to_code(config, condition_id, template_arg, args): return cg.new_Pvariable(condition_id, template_arg) -@automation.register_action("wifi.enable", WiFiEnableAction, cv.Schema({})) +@automation.register_action( + "wifi.enable", WiFiEnableAction, cv.Schema({}), synchronous=True +) async def wifi_enable_to_code(config, action_id, template_arg, args): return cg.new_Pvariable(action_id, template_arg) -@automation.register_action("wifi.disable", WiFiDisableAction, cv.Schema({})) +@automation.register_action( + "wifi.disable", WiFiDisableAction, cv.Schema({}), synchronous=True +) async def wifi_disable_to_code(config, action_id, template_arg, args): return cg.new_Pvariable(action_id, template_arg) @@ -781,6 +785,7 @@ async def final_step(): cv.Optional(CONF_ON_ERROR): automation.validate_automation(single=True), } ), + synchronous=False, ) async def wifi_set_sta_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index 124d9a8c32..e2ea61a542 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -168,6 +168,7 @@ async def wireguard_enabled_to_code(config, condition_id, template_arg, args): "wireguard.enable", WireguardEnableAction, cv.Schema({cv.GenerateID(): cv.use_id(Wireguard)}), + synchronous=True, ) async def wireguard_enable_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) @@ -179,6 +180,7 @@ async def wireguard_enable_to_code(config, action_id, template_arg, args): "wireguard.disable", WireguardDisableAction, cv.Schema({cv.GenerateID(): cv.use_id(Wireguard)}), + synchronous=True, ) async def wireguard_disable_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) diff --git a/esphome/components/zigbee/__init__.py b/esphome/components/zigbee/__init__.py index a327cc2988..280ff6b50c 100644 --- a/esphome/components/zigbee/__init__.py +++ b/esphome/components/zigbee/__init__.py @@ -195,6 +195,7 @@ FactoryResetAction = zigbee_ns.class_( "zigbee.factory_reset", FactoryResetAction, ZIGBEE_ACTION_SCHEMA, + synchronous=True, ) async def reset_zigbee_to_code( config: ConfigType, From 4d2ef09a296c4fd3e1b5e723024770ab8b8c3339 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:12:10 -1000 Subject: [PATCH 1264/2030] [log] Detect early log calls before logger init and optimize hot path (#14538) --- esphome/components/logger/__init__.py | 5 +- esphome/core/application.h | 2 + esphome/core/log.cpp | 60 +++++++++++++------ esphome/core/log.h | 12 +++- script/cpp_unit_test.py | 1 + tests/component_tests/logger/__init__.py | 0 tests/component_tests/logger/test_logger.py | 50 ++++++++++++++++ tests/component_tests/logger/test_logger.yaml | 14 +++++ tests/components/main.cpp | 8 +++ tests/integration/conftest.py | 1 + 10 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 tests/component_tests/logger/__init__.py create mode 100644 tests/component_tests/logger/test_logger.py create mode 100644 tests/component_tests/logger/test_logger.yaml diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 83a7854165..e370f4215d 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -337,6 +337,10 @@ async def to_code(config): ) if CORE.is_esp32: cg.add(log.create_pthread_key()) + # pre_setup() must be called before init_log_buffer() because + # init_log_buffer() calls disable_loop() which may log at VV level, + # and global_logger must be set before any logging occurs. + cg.add(log.pre_setup()) if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] if task_log_buffer_size > 0: @@ -356,7 +360,6 @@ async def to_code(config): HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]] ) ) - cg.add(log.pre_setup()) # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] diff --git a/esphome/core/application.h b/esphome/core/application.h index f357c6b1a3..23bb209eaf 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -142,6 +142,7 @@ static constexpr uint32_t TEARDOWN_TIMEOUT_REBOOT_MS = 1000; // 1 second for qu class Application { public: #ifdef ESPHOME_NAME_ADD_MAC_SUFFIX + // Called before Logger::pre_setup() — must not log (global_logger is not yet set). /// Pre-setup with MAC suffix: overwrites placeholder in mutable static buffers with actual MAC. void pre_setup(char *name, size_t name_len, char *friendly_name, size_t friendly_name_len) { arch_init(); @@ -163,6 +164,7 @@ class Application { this->friendly_name_ = StringRef(friendly_name, friendly_name_len); } #else + // Called before Logger::pre_setup() — must not log (global_logger is not yet set). /// Pre-setup without MAC suffix: StringRef points directly at const string literals in flash. void pre_setup(const char *name, size_t name_len, const char *friendly_name, size_t friendly_name_len) { arch_init(); diff --git a/esphome/core/log.cpp b/esphome/core/log.cpp index 8338efbb33..0da457adec 100644 --- a/esphome/core/log.cpp +++ b/esphome/core/log.cpp @@ -1,6 +1,7 @@ #include "log.h" #include "defines.h" #include "helpers.h" +#include <cstdio> #ifdef USE_LOGGER #include "esphome/components/logger/logger.h" @@ -8,40 +9,63 @@ namespace esphome { +#ifdef ESPHOME_DEBUG +static void early_log_printf_(const char *tag, int line, const char *format, va_list args) { + fprintf(stderr, "LOG BEFORE LOGGER INIT [%s:%d]: ", tag, line); + vfprintf(stderr, format, args); + fputc('\n', stderr); + assert(false && "log called before Logger::pre_setup()"); // NOLINT +} +#endif + void HOT esp_log_printf_(int level, const char *tag, int line, const char *format, ...) { // NOLINT +#ifdef USE_LOGGER +#ifdef ESPHOME_DEBUG + if (logger::global_logger == nullptr) { + va_list arg; + va_start(arg, format); + early_log_printf_(tag, line, format, arg); + va_end(arg); + return; + } +#endif va_list arg; va_start(arg, format); - esp_log_vprintf_(level, tag, line, format, arg); + logger::global_logger->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, arg); va_end(arg); +#endif } + #ifdef USE_STORE_LOG_STR_IN_FLASH void HOT esp_log_printf_(int level, const char *tag, int line, const __FlashStringHelper *format, ...) { +#ifdef USE_LOGGER + ESPHOME_DEBUG_ASSERT(logger::global_logger != nullptr); va_list arg; va_start(arg, format); - esp_log_vprintf_(level, tag, line, format, arg); + logger::global_logger->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, arg); va_end(arg); +#endif } #endif void HOT esp_log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT #ifdef USE_LOGGER - auto *log = logger::global_logger; - if (log == nullptr) +#ifdef ESPHOME_DEBUG + if (logger::global_logger == nullptr) { + early_log_printf_(tag, line, format, args); return; - - log->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, args); + } +#endif + logger::global_logger->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, args); #endif } #ifdef USE_STORE_LOG_STR_IN_FLASH -void HOT esp_log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format, - va_list args) { // NOLINT +// Remove before 2026.9.0 +void HOT esp_log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format, va_list args) { #ifdef USE_LOGGER - auto *log = logger::global_logger; - if (log == nullptr) - return; - - log->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, args); + ESPHOME_DEBUG_ASSERT(logger::global_logger != nullptr); + logger::global_logger->log_vprintf_(static_cast<uint8_t>(level), tag, line, format, args); #endif } #endif @@ -49,11 +73,13 @@ void HOT esp_log_vprintf_(int level, const char *tag, int line, const __FlashStr #ifdef USE_ESP32 int HOT esp_idf_log_vprintf_(const char *format, va_list args) { // NOLINT #ifdef USE_LOGGER - auto *log = logger::global_logger; - if (log == nullptr) +#ifdef ESPHOME_DEBUG + if (logger::global_logger == nullptr) { + early_log_printf_("esp-idf", 0, format, args); return 0; - - log->log_vprintf_(ESPHOME_LOG_LEVEL, "esp-idf", 0, format, args); + } +#endif + logger::global_logger->log_vprintf_(ESPHOME_LOG_LEVEL, "esp-idf", 0, format, args); #endif return 0; } diff --git a/esphome/core/log.h b/esphome/core/log.h index a2c4b35c6e..ff39633142 100644 --- a/esphome/core/log.h +++ b/esphome/core/log.h @@ -4,6 +4,14 @@ #include <cassert> #include <cstdarg> + +// Debug assert that only fires when ESPHOME_DEBUG is defined (e.g. in CI/test builds). +// Zero cost in production firmware. +#ifdef ESPHOME_DEBUG +#define ESPHOME_DEBUG_ASSERT(expr) assert(expr) // NOLINT +#else +#define ESPHOME_DEBUG_ASSERT(expr) ((void) 0) +#endif // for PRIu32 and friends #include <cinttypes> #include <string> @@ -61,7 +69,9 @@ void esp_log_printf_(int level, const char *tag, int line, const __FlashStringHe #endif void esp_log_vprintf_(int level, const char *tag, int line, const char *format, va_list args); // NOLINT #ifdef USE_STORE_LOG_STR_IN_FLASH -void esp_log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format, va_list args); +// Remove before 2026.9.0 +__attribute__((deprecated("Use esp_log_printf_() instead. Removed in 2026.9.0."))) void esp_log_vprintf_( + int level, const char *tag, int line, const __FlashStringHelper *format, va_list args); #endif #if defined(USE_ESP32) int esp_idf_log_vprintf_(const char *format, va_list args); // NOLINT diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index e11687dc16..c917458472 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -78,6 +78,7 @@ def create_test_config(config_name: str, includes: list[str]) -> dict: "build_flags": [ "-Og", # optimize for debug "-DUSE_TIME_TIMEZONE", # enable timezone code paths for testing + "-DESPHOME_DEBUG", # enable debug assertions ], "debug_build_flags": [ # only for debug builds "-g3", # max debug info diff --git a/tests/component_tests/logger/__init__.py b/tests/component_tests/logger/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/logger/test_logger.py b/tests/component_tests/logger/test_logger.py new file mode 100644 index 0000000000..98aa741964 --- /dev/null +++ b/tests/component_tests/logger/test_logger.py @@ -0,0 +1,50 @@ +"""Tests for the logger component.""" + +import re + + +def test_logger_pre_setup_before_other_components(generate_main): + """Logger::pre_setup() must be called before any other component is created. + + Log functions call global_logger->log_vprintf_() without a null check, + so global_logger must be set before anything can log. + """ + main_cpp = generate_main("tests/component_tests/logger/test_logger.yaml") + + # Find the logger's pre_setup() call specifically + logger_pre_setup = re.search(r"logger_logger->pre_setup\(\)", main_cpp) + if logger_pre_setup is None: + # Fall back to finding any logger-related pre_setup + logger_pre_setup = re.search(r"logger\w*->pre_setup\(\)", main_cpp) + assert logger_pre_setup is not None, ( + "Logger pre_setup() not found in generated code" + ) + + # Find all "new " allocations (component creation) + new_allocations = list(re.finditer(r"\bnew [\w:]+", main_cpp)) + assert len(new_allocations) > 0, "No component allocations found" + + # Separate logger and non-logger allocations + logger_allocs = [a for a in new_allocations if "logger" in a.group().lower()] + non_logger_allocs = [ + a + for a in new_allocations + if "logger" not in a.group().lower() + # Skip placement new for App + and "(&App)" not in main_cpp[max(0, a.start() - 5) : a.start()] + ] + + assert len(logger_allocs) > 0, ( + f"Logger allocation not found in: {[a.group() for a in new_allocations]}" + ) + assert len(non_logger_allocs) > 0, ( + "No non-logger component allocations found — " + "add a component to test_logger.yaml so the ordering check is meaningful" + ) + + # All non-logger allocations must appear after logger pre_setup() + for alloc in non_logger_allocs: + assert alloc.start() > logger_pre_setup.start(), ( + f"Component allocation '{alloc.group()}' at position {alloc.start()} " + f"appears before logger pre_setup() at position {logger_pre_setup.start()}" + ) diff --git a/tests/component_tests/logger/test_logger.yaml b/tests/component_tests/logger/test_logger.yaml new file mode 100644 index 0000000000..f43e99d94f --- /dev/null +++ b/tests/component_tests/logger/test_logger.yaml @@ -0,0 +1,14 @@ +--- +esphome: + name: test + +esp8266: + board: d1_mini_lite + +logger: + level: DEBUG + +# Need at least one non-logger component so the ordering test +# can verify that logger pre_setup() comes before other allocations. +preferences: + flash_write_interval: 1min diff --git a/tests/components/main.cpp b/tests/components/main.cpp index 928f0e6059..373fde7151 100644 --- a/tests/components/main.cpp +++ b/tests/components/main.cpp @@ -1,5 +1,7 @@ #include <gtest/gtest.h> +#include "esphome/components/logger/logger.h" + /* This special main.cpp replaces the default one. It will run all the Google Tests found in all compiled cpp files and then exit with the result @@ -18,6 +20,12 @@ void original_setup() { } void setup() { + // Log functions call global_logger->log_vprintf_() without a null check, + // so we must set up a Logger before any test that triggers logging. + static esphome::logger::Logger test_logger(0); + test_logger.set_log_level(ESPHOME_LOG_LEVEL); + test_logger.pre_setup(); + ::testing::InitGoogleTest(); int exit_code = RUN_ALL_TESTS(); exit(exit_code); diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index b7f7fc60b3..b652b4174c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -193,6 +193,7 @@ async def yaml_config(request: pytest.FixtureRequest, unused_tcp_port: int) -> s " platformio_options:\n" " build_flags:\n" ' - "-DDEBUG" # Enable assert() statements\n' + ' - "-DESPHOME_DEBUG" # Enable ESPHOME_DEBUG_ASSERT checks\n' ' - "-DESPHOME_DEBUG_API" # Enable API protocol asserts\n' ' - "-g" # Add debug symbols', ) From 9404eadaf8fe50fab155bae12252adad31530336 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 09:12:28 -1000 Subject: [PATCH 1265/2030] [rp2040_ble] Add BLE component for RP2040/RP2350 (#14603) --- CODEOWNERS | 1 + esphome/components/rp2040_ble/__init__.py | 31 +++++ esphome/components/rp2040_ble/rp2040_ble.cpp | 124 ++++++++++++++++++ esphome/components/rp2040_ble/rp2040_ble.h | 51 +++++++ esphome/core/defines.h | 1 + tests/components/rp2040_ble/common.yaml | 1 + .../test-disable-on-boot.rp2040-ard.yaml | 2 + .../rp2040_ble/test.rp2040-ard.yaml | 1 + 8 files changed, 212 insertions(+) create mode 100644 esphome/components/rp2040_ble/__init__.py create mode 100644 esphome/components/rp2040_ble/rp2040_ble.cpp create mode 100644 esphome/components/rp2040_ble/rp2040_ble.h create mode 100644 tests/components/rp2040_ble/common.yaml create mode 100644 tests/components/rp2040_ble/test-disable-on-boot.rp2040-ard.yaml create mode 100644 tests/components/rp2040_ble/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index cb415bb625..a95e100cbf 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -410,6 +410,7 @@ esphome/components/restart/* @esphome/core esphome/components/rf_bridge/* @jesserockz esphome/components/rgbct/* @jesserockz esphome/components/rp2040/* @jesserockz +esphome/components/rp2040_ble/* @bdraco esphome/components/rp2040_pio_led_strip/* @Papa-DMan esphome/components/rp2040_pwm/* @jesserockz esphome/components/rpi_dpi_rgb/* @clydebarrow diff --git a/esphome/components/rp2040_ble/__init__.py b/esphome/components/rp2040_ble/__init__.py new file mode 100644 index 0000000000..648f22691c --- /dev/null +++ b/esphome/components/rp2040_ble/__init__.py @@ -0,0 +1,31 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID +from esphome.types import ConfigType + +DEPENDENCIES = ["rp2040"] +CODEOWNERS = ["@bdraco"] + +rp2040_ble_ns = cg.esphome_ns.namespace("rp2040_ble") +RP2040BLE = rp2040_ble_ns.class_("RP2040BLE", cg.Component) + +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(RP2040BLE), + cv.Optional(CONF_ENABLE_ON_BOOT, default=True): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) + + +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + + cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT])) + + # Enable Bluetooth in the arduino-pico build + # This switches linking from liblwip.a to liblwip-bt.a and defines + # ENABLE_CLASSIC, ENABLE_BLE, CYW43_ENABLE_BLUETOOTH + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_ENABLE_BLUETOOTH") + + cg.add_define("USE_RP2040_BLE") diff --git a/esphome/components/rp2040_ble/rp2040_ble.cpp b/esphome/components/rp2040_ble/rp2040_ble.cpp new file mode 100644 index 0000000000..4125da7ec0 --- /dev/null +++ b/esphome/components/rp2040_ble/rp2040_ble.cpp @@ -0,0 +1,124 @@ +#include "rp2040_ble.h" + +#ifdef USE_RP2040_BLE + +#include "esphome/core/log.h" + +namespace esphome::rp2040_ble { + +static const char *const TAG = "rp2040_ble"; + +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +RP2040BLE *global_ble = nullptr; + +void RP2040BLE::setup() { + global_ble = this; + + if (this->enable_on_boot_) { + this->enable(); + } else { + this->state_ = BLEComponentState::DISABLED; + } +} + +void RP2040BLE::enable() { + if (this->state_ == BLEComponentState::ACTIVE || this->state_ == BLEComponentState::ENABLING) { + return; + } + + ESP_LOGD(TAG, "Enabling BLE..."); + this->state_ = BLEComponentState::ENABLING; + this->active_logged_ = false; + + if (!this->btstack_initialized_) { + // BTstack init functions are not idempotent — only call once + l2cap_init(); + sm_init(); + + this->hci_event_callback_registration_.callback = &RP2040BLE::packet_handler_; + hci_add_event_handler(&this->hci_event_callback_registration_); + + this->sm_event_callback_registration_.callback = &RP2040BLE::packet_handler_; + sm_add_event_handler(&this->sm_event_callback_registration_); + + this->btstack_initialized_ = true; + } + + hci_power_control(HCI_POWER_ON); +} + +void RP2040BLE::disable() { + if (this->state_ == BLEComponentState::DISABLED || this->state_ == BLEComponentState::OFF) { + return; + } + + ESP_LOGD(TAG, "Disabling BLE..."); + this->state_ = BLEComponentState::DISABLING; + + hci_power_control(HCI_POWER_OFF); + + this->state_ = BLEComponentState::DISABLED; + ESP_LOGD(TAG, "BLE disabled"); +} + +void RP2040BLE::loop() { + if (this->state_ == BLEComponentState::ACTIVE && !this->active_logged_) { + this->active_logged_ = true; + ESP_LOGI(TAG, "BLE active"); + } +} + +static const char *state_to_str(BLEComponentState state) { + switch (state) { + case BLEComponentState::OFF: + return "OFF"; + case BLEComponentState::ENABLING: + return "ENABLING"; + case BLEComponentState::ACTIVE: + return "ACTIVE"; + case BLEComponentState::DISABLING: + return "DISABLING"; + case BLEComponentState::DISABLED: + return "DISABLED"; + default: + return "UNKNOWN"; + } +} + +void RP2040BLE::dump_config() { + ESP_LOGCONFIG(TAG, + "RP2040 BLE:\n" + " Enable on boot: %s\n" + " State: %s", + YESNO(this->enable_on_boot_), state_to_str(this->state_)); +} + +float RP2040BLE::get_setup_priority() const { return setup_priority::BLUETOOTH; } + +void RP2040BLE::packet_handler_(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size) { + if (global_ble == nullptr) { + return; + } + + if (type != HCI_EVENT_PACKET) { + return; + } + + uint8_t event_type = hci_event_packet_get_type(packet); + + switch (event_type) { + case BTSTACK_EVENT_STATE: { + uint8_t state = btstack_event_state_get_state(packet); + if (state == HCI_STATE_WORKING && global_ble->state_ == BLEComponentState::ENABLING) { + global_ble->state_ = BLEComponentState::ACTIVE; + } + break; + } + default: + break; + } +} + +} // namespace esphome::rp2040_ble + +#endif // USE_RP2040_BLE diff --git a/esphome/components/rp2040_ble/rp2040_ble.h b/esphome/components/rp2040_ble/rp2040_ble.h new file mode 100644 index 0000000000..24b3860cc1 --- /dev/null +++ b/esphome/components/rp2040_ble/rp2040_ble.h @@ -0,0 +1,51 @@ +#pragma once + +#include "esphome/core/defines.h" // Must be included before conditional includes + +#ifdef USE_RP2040_BLE + +#include "esphome/core/component.h" + +#include <btstack.h> + +namespace esphome::rp2040_ble { + +enum class BLEComponentState : uint8_t { + OFF = 0, + ENABLING, + ACTIVE, + DISABLING, + DISABLED, +}; + +class RP2040BLE : public Component { + public: + void setup() override; + void loop() override; + void dump_config() override; + float get_setup_priority() const override; + + void enable(); + void disable(); + bool is_active() const { return this->state_ == BLEComponentState::ACTIVE; } + + void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; } + + protected: + static void packet_handler_(uint8_t type, uint16_t channel, uint8_t *packet, uint16_t size); + + btstack_packet_callback_registration_t hci_event_callback_registration_{}; + btstack_packet_callback_registration_t sm_event_callback_registration_{}; + + BLEComponentState state_{BLEComponentState::OFF}; + bool enable_on_boot_{true}; + bool btstack_initialized_{false}; + bool active_logged_{false}; +}; + +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +extern RP2040BLE *global_ble; + +} // namespace esphome::rp2040_ble + +#endif // USE_RP2040_BLE diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 51f474d80e..44918fe00c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -339,6 +339,7 @@ #define USE_I2C #define USE_LOGGER_USB_CDC #define USE_SOCKET_IMPL_LWIP_TCP +#define USE_RP2040_BLE #define USE_SPI #endif diff --git a/tests/components/rp2040_ble/common.yaml b/tests/components/rp2040_ble/common.yaml new file mode 100644 index 0000000000..f6205a4724 --- /dev/null +++ b/tests/components/rp2040_ble/common.yaml @@ -0,0 +1 @@ +rp2040_ble: diff --git a/tests/components/rp2040_ble/test-disable-on-boot.rp2040-ard.yaml b/tests/components/rp2040_ble/test-disable-on-boot.rp2040-ard.yaml new file mode 100644 index 0000000000..2154536111 --- /dev/null +++ b/tests/components/rp2040_ble/test-disable-on-boot.rp2040-ard.yaml @@ -0,0 +1,2 @@ +rp2040_ble: + enable_on_boot: false diff --git a/tests/components/rp2040_ble/test.rp2040-ard.yaml b/tests/components/rp2040_ble/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/rp2040_ble/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 04d80cfb75ffc19eaa14fcadce805c4c57369919 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:17:30 -0400 Subject: [PATCH 1266/2030] [esp32_hosted] Bump esp_wifi_remote and esp_hosted versions (#14680) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_hosted/__init__.py | 4 ++-- esphome/idf_component.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 720d81acc4..6d49053d6d 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -103,9 +103,9 @@ async def to_code(config): framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] os.environ["ESP_IDF_VERSION"] = f"{framework_ver.major}.{framework_ver.minor}" if framework_ver >= cv.Version(5, 5, 0): - esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.3.2") + esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.4.0") esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") - esp32.add_idf_component(name="espressif/esp_hosted", ref="2.11.5") + esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.0") else: esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0") esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 550e7b9af7..acd7f7a479 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -12,7 +12,7 @@ dependencies: espressif/mdns: version: 1.10.0 espressif/esp_wifi_remote: - version: 1.3.2 + version: 1.4.0 rules: - if: "target in [esp32h2, esp32p4]" espressif/eppp_link: @@ -20,7 +20,7 @@ dependencies: rules: - if: "target in [esp32h2, esp32p4]" espressif/esp_hosted: - version: 2.11.5 + version: 2.12.0 rules: - if: "target in [esp32h2, esp32p4]" zorxx/multipart-parser: From 780e009bf46854cabb42fb937659569eadc23d83 Mon Sep 17 00:00:00 2001 From: mahumpula <90641469+mahumpula@users.noreply.github.com> Date: Tue, 10 Mar 2026 21:23:49 +0100 Subject: [PATCH 1267/2030] [runtime_image] Add support for 8bit BMPs and fix existing issues (#10733) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../components/runtime_image/bmp_decoder.cpp | 109 ++++++++++++++---- .../components/runtime_image/bmp_decoder.h | 4 + tests/components/online_image/common.yaml | 4 + 3 files changed, 95 insertions(+), 22 deletions(-) diff --git a/esphome/components/runtime_image/bmp_decoder.cpp b/esphome/components/runtime_image/bmp_decoder.cpp index 7003f4da2f..174f924b28 100644 --- a/esphome/components/runtime_image/bmp_decoder.cpp +++ b/esphome/components/runtime_image/bmp_decoder.cpp @@ -12,7 +12,10 @@ static const char *const TAG = "image_decoder.bmp"; int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { size_t index = 0; - if (this->current_index_ == 0 && index == 0 && size > 14) { + if (this->current_index_ == 0) { + if (size <= 14) { + return 0; // Need more data for file header + } /** * BMP file format: * 0-1: Signature (BM) @@ -39,7 +42,10 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { this->current_index_ = 14; index = 14; } - if (this->current_index_ == 14 && index == 14 && size > this->data_offset_) { + if (this->current_index_ == 14) { + if (size <= this->data_offset_) { + return 0; // Need more data for DIB header and color table + } /** * BMP DIB header: * 14-17: DIB header size @@ -66,6 +72,28 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { this->width_bytes_ = (this->width_ + 7) / 8; this->padding_bytes_ = (4 - (this->width_bytes_ % 4)) % 4; break; + case 8: { + this->width_bytes_ = this->width_; + if (this->color_table_entries_ == 0) { + this->color_table_entries_ = 256; + } else if (this->color_table_entries_ > 256) { + ESP_LOGE(TAG, "Too many color table entries: %" PRIu32, this->color_table_entries_); + return DECODE_ERROR_UNSUPPORTED_FORMAT; + } + size_t header_size = encode_uint32(buffer[17], buffer[16], buffer[15], buffer[14]); + size_t offset = 14 + header_size; + + this->color_table_ = std::make_unique<uint32_t[]>(this->color_table_entries_); + + for (size_t i = 0; i < this->color_table_entries_; i++) { + this->color_table_[i] = encode_uint32(buffer[offset + i * 4 + 3], buffer[offset + i * 4 + 2], + buffer[offset + i * 4 + 1], buffer[offset + i * 4]); + } + + this->padding_bytes_ = (4 - (this->width_bytes_ % 4)) % 4; + + break; + } case 24: this->width_bytes_ = this->width_ * 3; if (this->width_bytes_ % 4 != 0) { @@ -91,21 +119,24 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { } switch (this->bits_per_pixel_) { case 1: { + size_t width = static_cast<size_t>(this->width_); while (index < size) { - uint8_t current_byte = buffer[index]; - bool end_of_row = false; - for (uint8_t i = 0; i < 8; i++) { - size_t x = this->paint_index_ % static_cast<size_t>(this->width_); - size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_)); - Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF; - this->draw(x, y, 1, 1, c); - this->paint_index_++; - // End of pixel row: skip remaining bits in this byte - if (x + 1 >= static_cast<size_t>(this->width_)) { - end_of_row = true; - break; - } + size_t x = this->paint_index_ % width; + size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / width); + size_t remaining_in_row = width - x; + uint8_t pixels_in_byte = std::min<size_t>(remaining_in_row, 8); + bool end_of_row = remaining_in_row <= 8; + size_t needed = 1 + (end_of_row ? this->padding_bytes_ : 0); + if (index + needed > size) { + this->decoded_bytes_ += index; + return index; } + uint8_t current_byte = buffer[index]; + for (uint8_t i = 0; i < pixels_in_byte; i++) { + Color c = (current_byte & (1 << (7 - i))) ? display::COLOR_ON : display::COLOR_OFF; + this->draw(x + i, y, 1, 1, c); + } + this->paint_index_ += pixels_in_byte; this->current_index_++; index++; // End of pixel row: skip row padding bytes (4-byte alignment) @@ -116,23 +147,57 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { } break; } - case 24: { + case 8: { + size_t width = static_cast<size_t>(this->width_); + size_t last_col = width - 1; while (index < size) { - if (index + 2 >= size) { + size_t x = this->paint_index_ % width; + size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / width); + size_t needed = 1 + ((x == last_col) ? this->padding_bytes_ : 0); + if (index + needed > size) { + this->decoded_bytes_ += index; + return index; + } + + uint8_t color_index = buffer[index]; + if (color_index >= this->color_table_entries_) { + ESP_LOGE(TAG, "Invalid color index: %u", color_index); + return DECODE_ERROR_UNSUPPORTED_FORMAT; + } + + uint32_t rgb = this->color_table_[color_index]; + uint8_t b = rgb & 0xff; + uint8_t g = (rgb >> 8) & 0xff; + uint8_t r = (rgb >> 16) & 0xff; + this->draw(x, y, 1, 1, Color(r, g, b)); + this->paint_index_++; + this->current_index_++; + index++; + if (x == last_col && this->padding_bytes_ > 0) { + index += this->padding_bytes_; + this->current_index_ += this->padding_bytes_; + } + } + break; + } + case 24: { + size_t width = static_cast<size_t>(this->width_); + size_t last_col = width - 1; + while (index < size) { + size_t x = this->paint_index_ % width; + size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / width); + size_t needed = 3 + ((x == last_col) ? this->padding_bytes_ : 0); + if (index + needed > size) { this->decoded_bytes_ += index; return index; } uint8_t b = buffer[index]; uint8_t g = buffer[index + 1]; uint8_t r = buffer[index + 2]; - size_t x = this->paint_index_ % static_cast<size_t>(this->width_); - size_t y = static_cast<size_t>(this->height_ - 1) - (this->paint_index_ / static_cast<size_t>(this->width_)); - Color c = Color(r, g, b); - this->draw(x, y, 1, 1, c); + this->draw(x, y, 1, 1, Color(r, g, b)); this->paint_index_++; this->current_index_ += 3; index += 3; - size_t last_col = static_cast<size_t>(this->width_) - 1; if (x == last_col && this->padding_bytes_ > 0) { index += this->padding_bytes_; this->current_index_ += this->padding_bytes_; diff --git a/esphome/components/runtime_image/bmp_decoder.h b/esphome/components/runtime_image/bmp_decoder.h index 37db6b4940..73e54f5430 100644 --- a/esphome/components/runtime_image/bmp_decoder.h +++ b/esphome/components/runtime_image/bmp_decoder.h @@ -3,6 +3,9 @@ #include "esphome/core/defines.h" #ifdef USE_RUNTIME_IMAGE_BMP +#include <algorithm> +#include <memory> + #include "image_decoder.h" #include "runtime_image.h" @@ -36,6 +39,7 @@ class BmpDecoder : public ImageDecoder { uint32_t compression_method_{0}; uint32_t image_data_size_{0}; uint32_t color_table_entries_{0}; + std::unique_ptr<uint32_t[]> color_table_; size_t width_bytes_{0}; size_t data_offset_{0}; uint8_t padding_bytes_{0}; diff --git a/tests/components/online_image/common.yaml b/tests/components/online_image/common.yaml index 422a24b540..fc3cc94217 100644 --- a/tests/components/online_image/common.yaml +++ b/tests/components/online_image/common.yaml @@ -40,6 +40,10 @@ online_image: url: https://samples-files.com/samples/images/bmp/480-360-sample.bmp format: BMP type: BINARY + - id: online_rgb_bmp_8bit + url: https://samples-files.com/samples/images/bmp/480-360-sample.bmp + format: BMP + type: RGB - id: online_jpeg_image url: http://www.faqs.org/images/library.jpg format: JPEG From 8ca6ee4349acb28878d4c15ef32d67999b96f139 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 10 Mar 2026 15:25:26 -0500 Subject: [PATCH 1268/2030] [speaker_source] Add new media player (#14649) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- CODEOWNERS | 1 + esphome/components/speaker_source/__init__.py | 0 .../components/speaker_source/media_player.py | 212 +++++++ .../speaker_source_media_player.cpp | 546 ++++++++++++++++++ .../speaker_source_media_player.h | 217 +++++++ tests/components/speaker_source/common.yaml | 43 ++ .../speaker_source/test.esp32-idf.yaml | 9 + tests/components/speaker_source/test.wav | Bin 0 -> 46 bytes 8 files changed, 1028 insertions(+) create mode 100644 esphome/components/speaker_source/__init__.py create mode 100644 esphome/components/speaker_source/media_player.py create mode 100644 esphome/components/speaker_source/speaker_source_media_player.cpp create mode 100644 esphome/components/speaker_source/speaker_source_media_player.h create mode 100644 tests/components/speaker_source/common.yaml create mode 100644 tests/components/speaker_source/test.esp32-idf.yaml create mode 100644 tests/components/speaker_source/test.wav diff --git a/CODEOWNERS b/CODEOWNERS index a95e100cbf..12aff01e73 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -459,6 +459,7 @@ esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/sound_level/* @kahrendt esphome/components/speaker/* @jesserockz @kahrendt esphome/components/speaker/media_player/* @kahrendt @synesthesiam +esphome/components/speaker_source/* @kahrendt esphome/components/spi/* @clydebarrow @esphome/core esphome/components/spi_device/* @clydebarrow esphome/components/spi_led_strip/* @clydebarrow diff --git a/esphome/components/speaker_source/__init__.py b/esphome/components/speaker_source/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/speaker_source/media_player.py b/esphome/components/speaker_source/media_player.py new file mode 100644 index 0000000000..a44cdcbf01 --- /dev/null +++ b/esphome/components/speaker_source/media_player.py @@ -0,0 +1,212 @@ +from esphome import automation +import esphome.codegen as cg +from esphome.components import audio, media_player, media_source, speaker +import esphome.config_validation as cv +from esphome.const import ( + CONF_FORMAT, + CONF_ID, + CONF_NUM_CHANNELS, + CONF_SAMPLE_RATE, + CONF_SPEAKER, +) +from esphome.core.entity_helpers import inherit_property_from +from esphome.types import ConfigType + +AUTO_LOAD = ["audio"] +DEPENDENCIES = ["media_source", "speaker"] + +CODEOWNERS = ["@kahrendt"] + +CONF_MEDIA_PIPELINE = "media_pipeline" +CONF_ON_MUTE = "on_mute" +CONF_ON_UNMUTE = "on_unmute" +CONF_ON_VOLUME = "on_volume" +CONF_SOURCES = "sources" +CONF_VOLUME_INCREMENT = "volume_increment" +CONF_VOLUME_INITIAL = "volume_initial" +CONF_VOLUME_MAX = "volume_max" +CONF_VOLUME_MIN = "volume_min" + +speaker_source_ns = cg.esphome_ns.namespace("speaker_source") + +SpeakerSourceMediaPlayer = speaker_source_ns.class_( + "SpeakerSourceMediaPlayer", cg.Component, media_player.MediaPlayer +) + +PipelineContext = speaker_source_ns.struct("PipelineContext") + +Pipeline = speaker_source_ns.enum("Pipeline") + + +FORMAT_MAPPING = { + "FLAC": "flac", + "MP3": "mp3", + "OPUS": "opus", + "WAV": "wav", +} + + +# Returns a media_player.MediaPlayerSupportedFormat struct with the configured +# format, sample rate, number of channels, purpose, and bytes per sample +def _get_supported_format_struct(pipeline: ConfigType): + args = [ + media_player.MediaPlayerSupportedFormat, + ] + + args.append(("format", FORMAT_MAPPING[pipeline[CONF_FORMAT]])) + + args.append(("sample_rate", pipeline[CONF_SAMPLE_RATE])) + args.append(("num_channels", pipeline[CONF_NUM_CHANNELS])) + args.append(("purpose", media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["default"])) + + # Omit sample_bytes for MP3: ffmpeg transcoding in Home Assistant fails + # if the number of bytes per sample is specified for MP3. + if pipeline[CONF_FORMAT] != "MP3": + args.append(("sample_bytes", 2)) + + return cg.StructInitializer(*args) + + +def _validate_pipeline(config: ConfigType) -> ConfigType: + # Inherit settings from speaker if not manually set + inherit_property_from(CONF_NUM_CHANNELS, CONF_SPEAKER)(config) + inherit_property_from(CONF_SAMPLE_RATE, CONF_SPEAKER)(config) + + # Opus only supports 48 kHz + if config.get(CONF_FORMAT) == "OPUS" and config.get(CONF_SAMPLE_RATE) != 48000: + raise cv.Invalid("Opus only supports a sample rate of 48000 Hz") + + audio.final_validate_audio_schema( + "speaker_source media_player", + audio_device=CONF_SPEAKER, + bits_per_sample=16, + channels=config.get(CONF_NUM_CHANNELS), + sample_rate=config.get(CONF_SAMPLE_RATE), + )(config) + + return config + + +PIPELINE_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id( + PipelineContext + ), # Needed to inherit audio settings from the speaker + cv.Required(CONF_SPEAKER): cv.use_id(speaker.Speaker), + cv.Required(CONF_SOURCES): cv.All( + cv.ensure_list(cv.use_id(media_source.MediaSource)), + cv.Length(min=1), + ), + cv.Optional(CONF_FORMAT, default="FLAC"): cv.enum(audio.AUDIO_FILE_TYPE_ENUM), + cv.Optional(CONF_SAMPLE_RATE): cv.int_range(min=1), + cv.Optional(CONF_NUM_CHANNELS): cv.int_range(1, 2), + } +) + + +def _validate_volume_settings(config: ConfigType) -> ConfigType: + # CONF_VOLUME_INITIAL is in the scaled volume domain (0.0-1.0) and doesn't need to be validated + if config[CONF_VOLUME_MIN] > config[CONF_VOLUME_MAX]: + raise cv.Invalid( + f"{CONF_VOLUME_MIN} ({config[CONF_VOLUME_MIN]}) must be less than or equal to {CONF_VOLUME_MAX} ({config[CONF_VOLUME_MAX]})" + ) + return config + + +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_VOLUME_INCREMENT, default=0.05): cv.percentage, + cv.Optional(CONF_VOLUME_INITIAL, default=0.5): cv.percentage, + cv.Optional(CONF_VOLUME_MAX, default=1.0): cv.percentage, + cv.Optional(CONF_VOLUME_MIN, default=0.0): cv.percentage, + cv.Required(CONF_MEDIA_PIPELINE): PIPELINE_SCHEMA, + cv.Optional(CONF_ON_MUTE): automation.validate_automation(single=True), + cv.Optional(CONF_ON_UNMUTE): automation.validate_automation(single=True), + cv.Optional(CONF_ON_VOLUME): automation.validate_automation(single=True), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(media_player.media_player_schema(SpeakerSourceMediaPlayer)), + cv.only_on_esp32, + _validate_volume_settings, +) + + +def _final_validate_codecs(config: ConfigType) -> ConfigType: + pipeline = config[CONF_MEDIA_PIPELINE] + fmt = pipeline[CONF_FORMAT] + if fmt == "NONE": + audio.request_flac_support() + audio.request_mp3_support() + audio.request_opus_support() + elif fmt == "FLAC": + audio.request_flac_support() + elif fmt == "MP3": + audio.request_mp3_support() + elif fmt == "OPUS": + audio.request_opus_support() + + return config + + +FINAL_VALIDATE_SCHEMA = cv.All( + cv.Schema( + { + cv.Required(CONF_MEDIA_PIPELINE): _validate_pipeline, + }, + extra=cv.ALLOW_EXTRA, + ), + _final_validate_codecs, +) + + +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await media_player.register_media_player(var, config) + + cg.add(var.set_volume_increment(config[CONF_VOLUME_INCREMENT])) + cg.add(var.set_volume_initial(config[CONF_VOLUME_INITIAL])) + cg.add(var.set_volume_max(config[CONF_VOLUME_MAX])) + cg.add(var.set_volume_min(config[CONF_VOLUME_MIN])) + + pipeline_config = config[CONF_MEDIA_PIPELINE] + pipeline_enum = Pipeline.MEDIA_PIPELINE + + for source in pipeline_config[CONF_SOURCES]: + src = await cg.get_variable(source) + cg.add(var.add_media_source(pipeline_enum, src)) + + cg.add( + var.set_speaker( + pipeline_enum, + await cg.get_variable(pipeline_config[CONF_SPEAKER]), + ) + ) + if pipeline_config[CONF_FORMAT] != "NONE": + cg.add( + var.set_format( + pipeline_enum, + _get_supported_format_struct(pipeline_config), + ) + ) + + if on_mute := config.get(CONF_ON_MUTE): + await automation.build_automation( + var.get_mute_trigger(), + [], + on_mute, + ) + if on_unmute := config.get(CONF_ON_UNMUTE): + await automation.build_automation( + var.get_unmute_trigger(), + [], + on_unmute, + ) + if on_volume := config.get(CONF_ON_VOLUME): + await automation.build_automation( + var.get_volume_trigger(), + [(cg.float_, "x")], + on_volume, + ) diff --git a/esphome/components/speaker_source/speaker_source_media_player.cpp b/esphome/components/speaker_source/speaker_source_media_player.cpp new file mode 100644 index 0000000000..a3679891d2 --- /dev/null +++ b/esphome/components/speaker_source/speaker_source_media_player.cpp @@ -0,0 +1,546 @@ +#include "speaker_source_media_player.h" + +#ifdef USE_ESP32 + +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +namespace esphome::speaker_source { + +static constexpr uint32_t MEDIA_CONTROLS_QUEUE_LENGTH = 20; + +static const char *const TAG = "speaker_source_media_player"; + +// SourceBinding method implementations (defined here because SpeakerSourceMediaPlayer is forward-declared in the +// header) + +// THREAD CONTEXT: Called from media source decode task thread +size_t SourceBinding::write_audio(const uint8_t *data, size_t length, uint32_t timeout_ms, + const audio::AudioStreamInfo &stream_info) { + return this->player->handle_media_output_(this->pipeline, this->source, data, length, timeout_ms, stream_info); +} + +// THREAD CONTEXT: Called from main loop (media source's loop() calls set_state_ which calls report_state) +void SourceBinding::report_state(media_source::MediaSourceState state) { + this->player->handle_media_state_changed_(this->pipeline, this->source, state); +} + +// THREAD CONTEXT: Called from media source task thread; uses defer() to marshal to main loop +void SourceBinding::request_volume(float volume) { + this->player->defer([this, volume]() { this->player->handle_volume_request_(volume); }); +} + +// THREAD CONTEXT: Called from media source task thread; uses defer() to marshal to main loop +void SourceBinding::request_mute(bool is_muted) { + this->player->defer([this, is_muted]() { this->player->handle_mute_request_(is_muted); }); +} + +// THREAD CONTEXT: Called from media source task thread; uses defer() to marshal to main loop +void SourceBinding::request_play_uri(const std::string &uri) { + this->player->defer([this, uri]() { this->player->handle_play_uri_request_(this->pipeline, uri); }); +} + +// THREAD CONTEXT: Called during code generation setup (main loop) +void SpeakerSourceMediaPlayer::add_media_source(uint8_t pipeline, media_source::MediaSource *media_source) { + auto &binding = + this->pipelines_[pipeline].sources.emplace_back(std::make_unique<SourceBinding>(this, media_source, pipeline)); + media_source->set_listener(binding.get()); +} + +void SpeakerSourceMediaPlayer::dump_config() { + ESP_LOGCONFIG(TAG, + "Speaker Source Media Player:\n" + " Volume Increment: %.2f\n" + " Volume Min: %.2f\n" + " Volume Max: %.2f", + this->volume_increment_, this->volume_min_, this->volume_max_); +} + +void SpeakerSourceMediaPlayer::setup() { + this->state = media_player::MEDIA_PLAYER_STATE_IDLE; + + this->media_control_command_queue_ = xQueueCreate(MEDIA_CONTROLS_QUEUE_LENGTH, sizeof(MediaPlayerControlCommand)); + + this->pref_ = this->make_entity_preference<VolumeRestoreState>(); + + VolumeRestoreState volume_restore_state; + if (this->pref_.load(&volume_restore_state)) { + this->set_volume_(volume_restore_state.volume); + this->set_mute_state_(volume_restore_state.is_muted); + } else { + this->set_volume_(this->volume_initial_); + this->set_mute_state_(false); + } + + // Register callbacks to receive playback notifications from speakers + for (size_t i = 0; i < this->pipelines_.size(); i++) { + if (this->pipelines_[i].is_configured()) { + this->pipelines_[i].speaker->add_audio_output_callback([this, i](uint32_t frames, int64_t timestamp) { + this->handle_speaker_playback_callback_(frames, timestamp, i); + }); + } + } +} + +// THREAD CONTEXT: Called from the speaker's playback callback task (not main loop) +void SpeakerSourceMediaPlayer::handle_speaker_playback_callback_(uint32_t frames, int64_t timestamp, uint8_t pipeline) { + PipelineContext &ps = this->pipelines_[pipeline]; + + // Load once so the null check and use below are consistent + media_source::MediaSource *active_source = ps.active_source.load(std::memory_order_relaxed); + if (active_source == nullptr) { + return; + } + + // CAS loop to safely subtract frames without underflow. If pending_frames is reset to 0 (new source + // starting) between the load and the subtract, compare_exchange_weak will fail and reload the current value. + uint32_t current = ps.pending_frames.load(std::memory_order_relaxed); + uint32_t source_frames; + do { + source_frames = std::min(frames, current); + } while (source_frames > 0 && + !ps.pending_frames.compare_exchange_weak(current, current - source_frames, std::memory_order_relaxed)); + + if (source_frames > 0) { + // Notify the source about the played audio + active_source->notify_audio_played(source_frames, timestamp); + } +} + +// THREAD CONTEXT: Called from main loop via defer() +void SpeakerSourceMediaPlayer::handle_volume_request_(float volume) { + // Update the media player's volume + this->set_volume_(volume); + this->publish_state(); +} + +// THREAD CONTEXT: Called from main loop via defer() +void SpeakerSourceMediaPlayer::handle_mute_request_(bool is_muted) { + // Update the media player's mute state + this->set_mute_state_(is_muted); + this->publish_state(); +} + +// THREAD CONTEXT: Called from main loop via defer() +void SpeakerSourceMediaPlayer::handle_play_uri_request_(uint8_t pipeline, const std::string &uri) { + // Smart source is requesting the player to play a different URI + auto call = this->make_call(); + call.set_media_url(uri); + call.perform(); +} + +// THREAD CONTEXT: Called from main loop (media source's loop() calls set_state_ which calls report_state) +void SpeakerSourceMediaPlayer::handle_media_state_changed_(uint8_t pipeline, media_source::MediaSource *source, + media_source::MediaSourceState state) { + PipelineContext &ps = this->pipelines_[pipeline]; + + if (state == media_source::MediaSourceState::IDLE) { + // Source went idle - clear stopping flag if this was the source we asked to stop + if (ps.stopping_source == source) { + ps.stopping_source = nullptr; + } + + // Clear pending flag if this was the source we asked to play + if (ps.pending_source == source) { + ps.pending_source = nullptr; + } + + // Source went idle - clear it if it's the active source + if (ps.active_source == source) { + ps.last_source = ps.active_source; + ps.active_source = nullptr; + + // Finish the speaker to ensure it's ready for the next playback + ps.speaker->finish(); + } + } else if (state == media_source::MediaSourceState::PLAYING) { + // Source started playing - make it the active source if no one else is active + if (ps.active_source == nullptr) { + ps.active_source = source; + ps.last_source = nullptr; + + // Clear pending flag now that the source is active + if (ps.pending_source == source) { + ps.pending_source = nullptr; + } + } + } +} + +// THREAD CONTEXT: Called from media source decode task thread (not main loop). +// Reads ps.active_source (atomic), writes ps.pending_frames (atomic), and calls +// ps.speaker methods (speaker pointer is immutable after setup). +size_t SpeakerSourceMediaPlayer::handle_media_output_(uint8_t pipeline, media_source::MediaSource *source, + const uint8_t *data, size_t length, uint32_t timeout_ms, + const audio::AudioStreamInfo &stream_info) { + PipelineContext &ps = this->pipelines_[pipeline]; + + // Single read; the if-body only uses ps.speaker (immutable after setup) and the source parameter. + if (ps.active_source == source) { + // This source is active - play the audio + if (ps.speaker->get_audio_stream_info() != stream_info) { + // Setup the speaker to play this stream + ps.speaker->set_audio_stream_info(stream_info); + vTaskDelay(pdMS_TO_TICKS(timeout_ms)); + return 0; + } + size_t bytes_written = ps.speaker->play(data, length, pdMS_TO_TICKS(timeout_ms)); + if (bytes_written > 0) { + // Track frames sent to speaker for this source + ps.pending_frames.fetch_add(stream_info.bytes_to_frames(bytes_written), std::memory_order_relaxed); + } + return bytes_written; + } + + // Not the active source - wait for state callback to set us as active when we transition to PLAYING + vTaskDelay(pdMS_TO_TICKS(timeout_ms)); + return 0; +} + +media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_media_pipeline_state_( + media_source::MediaSource *source) const { + if (source != nullptr) { + switch (source->get_state()) { + case media_source::MediaSourceState::PLAYING: + return media_player::MEDIA_PLAYER_STATE_PLAYING; + case media_source::MediaSourceState::PAUSED: + return media_player::MEDIA_PLAYER_STATE_PAUSED; + case media_source::MediaSourceState::ERROR: + ESP_LOGE(TAG, "Source error"); + return media_player::MEDIA_PLAYER_STATE_IDLE; + case media_source::MediaSourceState::IDLE: + default: + return media_player::MEDIA_PLAYER_STATE_IDLE; + } + } + + return media_player::MEDIA_PLAYER_STATE_IDLE; +} + +void SpeakerSourceMediaPlayer::loop() { + // Process queued control commands + MediaPlayerControlCommand control_command; + + // Use peek to check command without removing it + if (xQueuePeek(this->media_control_command_queue_, &control_command, 0) == pdTRUE) { + bool command_executed = false; + uint8_t pipeline = control_command.pipeline; + + switch (control_command.type) { + case MediaPlayerControlCommand::PLAY_URI: { + command_executed = this->try_execute_play_uri_(*control_command.data.uri, pipeline); + break; + } + + case MediaPlayerControlCommand::SEND_COMMAND: { + PipelineContext &ps = this->pipelines_[pipeline]; + + // Determine target source: prefer active, fall back to last + media_source::MediaSource *target_source = nullptr; + if (ps.active_source != nullptr) { + target_source = ps.active_source; + } else if (ps.last_source != nullptr) { + target_source = ps.last_source; + } + + media_player::MediaPlayerCommand player_command = control_command.data.command; + switch (player_command) { + case media_player::MEDIA_PLAYER_COMMAND_TOGGLE: { + media_source::MediaSource *active_source = ps.active_source; + if ((active_source != nullptr) && (active_source->get_state() == media_source::MediaSourceState::PLAYING)) { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PAUSE); + } + } else { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PLAY); + } + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_PLAY: { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PLAY); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_PAUSE: { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PAUSE); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_STOP: { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::STOP); + } + break; + } + + default: + break; + } + + command_executed = true; + break; + } + } + + // Only remove from queue if successfully executed + if (command_executed) { + xQueueReceive(this->media_control_command_queue_, &control_command, 0); + + // Delete the allocated string for PLAY_URI commands + if (control_command.type == MediaPlayerControlCommand::PLAY_URI) { + delete control_command.data.uri; + } + } + } + + // Update state based on active sources + media_player::MediaPlayerState old_state = this->state; + + PipelineContext &media_ps = this->pipelines_[MEDIA_PIPELINE]; + this->state = this->get_media_pipeline_state_(media_ps.active_source); + + if (this->state != old_state) { + this->publish_state(); + ESP_LOGD(TAG, "State changed to %s", media_player::media_player_state_to_string(this->state)); + } +} + +media_source::MediaSource *SpeakerSourceMediaPlayer::find_source_for_uri_(const std::string &uri, uint8_t pipeline) { + PipelineContext &ps = this->pipelines_[pipeline]; + media_source::MediaSource *first_match = nullptr; + for (auto &binding : ps.sources) { + if (binding->source->can_handle(uri)) { + // Prefer an idle source; otherwise remember the first match (will be stopped by try_execute_play_uri_) + if (binding->source->get_state() == media_source::MediaSourceState::IDLE) { + return binding->source; + } + if (first_match == nullptr) { + first_match = binding->source; + } + } + } + return first_match; +} + +bool SpeakerSourceMediaPlayer::try_execute_play_uri_(const std::string &uri, uint8_t pipeline) { + // Find target source + media_source::MediaSource *target_source = this->find_source_for_uri_(uri, pipeline); + if (target_source == nullptr) { + ESP_LOGW(TAG, "No source for URI"); + ESP_LOGV(TAG, "URI: %s", uri.c_str()); + return true; // Remove from queue (unrecoverable) + } + + PipelineContext &ps = this->pipelines_[pipeline]; + + media_source::MediaSource *active_source = ps.active_source; + + // If active source exists and is not IDLE, stop it and wait + if (active_source != nullptr) { + media_source::MediaSourceState active_state = active_source->get_state(); + if (active_state != media_source::MediaSourceState::IDLE) { + // Only send END command once per source - check if we've already asked this source to stop + if (ps.stopping_source != active_source) { + ESP_LOGV(TAG, "Pipeline %u: stopping active source", pipeline); + active_source->handle_command(media_source::MediaSourceCommand::STOP); + ps.speaker->stop(); + ps.stopping_source = active_source; + } + return false; // Leave in queue, retry next loop + } + } + + // Also check target source directly - handles case where source errored before PLAYING state + media_source::MediaSourceState target_state = target_source->get_state(); + if (target_state != media_source::MediaSourceState::IDLE) { + // Only send STOP command once per source + if (ps.stopping_source != target_source) { + ESP_LOGV(TAG, "Pipeline %u: target source busy, stopping", pipeline); + target_source->handle_command(media_source::MediaSourceCommand::STOP); + ps.speaker->stop(); + ps.stopping_source = target_source; + } + return false; // Leave in queue, retry next loop + } + + // Clear stopping flag since we're past the stopping phase + ps.stopping_source = nullptr; + + // Check if speaker is ready + if (!ps.speaker->is_stopped()) { + return false; // Speaker not ready yet, retry later + } + + // Set pending source so handle_media_state_changed_ can recognize it when the source transitions to PLAYING + ps.pending_source = target_source; + + // Speaker is ready, try to play + if (!target_source->play_uri(uri)) { + ESP_LOGE(TAG, "Pipeline %u: Failed to play URI: %s", pipeline, uri.c_str()); + ps.pending_source = nullptr; + } + + // Reset pending frame counter for this pipeline since we're starting a new source + ps.pending_frames.store(0, std::memory_order_relaxed); + + return true; // Remove from queue +} + +// THREAD CONTEXT: Called from main loop only. Entry points: +// - HA/automation commands (direct) +// - handle_play_uri_request_() via make_call().perform() (deferred from source tasks) +void SpeakerSourceMediaPlayer::control(const media_player::MediaPlayerCall &call) { + if (!this->is_ready()) { + return; + } + + MediaPlayerControlCommand control_command; + control_command.pipeline = MEDIA_PIPELINE; + + auto media_url = call.get_media_url(); + if (media_url.has_value()) { + control_command.type = MediaPlayerControlCommand::PLAY_URI; + // Heap allocation is unavoidable: URIs from Home Assistant are arbitrary-length (media URLs with tokens + // can easily exceed 500 bytes). Deleted after the command is consumed. FreeRTOS queues require items to be + // copyable, so we store a pointer to the string in the queue rather than the string itself. + control_command.data.uri = new std::string(media_url.value()); + if (xQueueSend(this->media_control_command_queue_, &control_command, 0) != pdTRUE) { + delete control_command.data.uri; + ESP_LOGE(TAG, "Queue full, URI dropped"); + } + return; + } + + auto volume = call.get_volume(); + if (volume.has_value()) { + this->set_volume_(volume.value()); + this->publish_state(); + return; + } + + auto cmd = call.get_command(); + if (cmd.has_value()) { + switch (cmd.value()) { + case media_player::MEDIA_PLAYER_COMMAND_MUTE: + this->set_mute_state_(true); + break; + case media_player::MEDIA_PLAYER_COMMAND_UNMUTE: + this->set_mute_state_(false); + break; + case media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP: + this->set_volume_(std::min(1.0f, this->volume + this->volume_increment_)); + break; + case media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN: + this->set_volume_(std::max(0.0f, this->volume - this->volume_increment_)); + break; + default: + // Queue command for processing in loop() + control_command.type = MediaPlayerControlCommand::SEND_COMMAND; + control_command.data.command = cmd.value(); + if (xQueueSend(this->media_control_command_queue_, &control_command, 0) != pdTRUE) { + ESP_LOGE(TAG, "Queue full, command dropped"); + } + return; + } + this->publish_state(); + } +} + +media_player::MediaPlayerTraits SpeakerSourceMediaPlayer::get_traits() { + auto traits = media_player::MediaPlayerTraits(); + traits.set_supports_pause(true); + + for (const auto &ps : this->pipelines_) { + if (ps.format.has_value()) { + traits.get_supported_formats().push_back(ps.format.value()); + } + } + + return traits; +} + +void SpeakerSourceMediaPlayer::save_volume_restore_state_() { + VolumeRestoreState volume_restore_state; + volume_restore_state.volume = this->volume; + volume_restore_state.is_muted = this->is_muted_; + this->pref_.save(&volume_restore_state); +} + +void SpeakerSourceMediaPlayer::set_mute_state_(bool mute_state, bool publish) { + if (this->is_muted_ == mute_state) { + return; + } + + for (auto &ps : this->pipelines_) { + if (ps.is_configured()) { + ps.speaker->set_mute_state(mute_state); + } + } + + this->is_muted_ = mute_state; + + if (publish) { + this->save_volume_restore_state_(); + } + + // Notify all media sources about the mute state change + for (auto &ps : this->pipelines_) { + for (auto &binding : ps.sources) { + binding->source->notify_mute_changed(mute_state); + } + } + + if (mute_state) { + this->defer([this]() { this->mute_trigger_.trigger(); }); + } else { + this->defer([this]() { this->unmute_trigger_.trigger(); }); + } +} + +void SpeakerSourceMediaPlayer::set_volume_(float volume, bool publish) { + // Remap the volume to fit within the configured limits + float bounded_volume = remap<float, float>(volume, 0.0f, 1.0f, this->volume_min_, this->volume_max_); + + for (auto &ps : this->pipelines_) { + if (ps.is_configured()) { + ps.speaker->set_volume(bounded_volume); + } + } + + if (publish) { + this->volume = volume; + } + + // Notify all media sources about the volume change + for (auto &ps : this->pipelines_) { + for (auto &binding : ps.sources) { + binding->source->notify_volume_changed(volume); + } + } + + // Turn on the mute state if the volume is effectively zero, off otherwise. + // Pass publish=false to avoid saving twice. + if (volume < 0.001) { + this->set_mute_state_(true, false); + } else { + this->set_mute_state_(false, false); + } + + // Save after mute mutation so the restored state has the correct is_muted_ value + if (publish) { + this->save_volume_restore_state_(); + } + + this->defer([this, volume]() { this->volume_trigger_.trigger(volume); }); +} + +} // namespace esphome::speaker_source + +#endif // USE_ESP32 diff --git a/esphome/components/speaker_source/speaker_source_media_player.h b/esphome/components/speaker_source/speaker_source_media_player.h new file mode 100644 index 0000000000..7896fef295 --- /dev/null +++ b/esphome/components/speaker_source/speaker_source_media_player.h @@ -0,0 +1,217 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_ESP32 + +#include "esphome/components/audio/audio.h" +#include "esphome/components/media_source/media_source.h" +#include "esphome/components/media_player/media_player.h" +#include "esphome/components/speaker/speaker.h" + +#include "esphome/core/automation.h" +#include "esphome/core/component.h" +#include "esphome/core/preferences.h" + +#include <array> +#include <atomic> +#include <memory> +#include <vector> +#include <freertos/FreeRTOS.h> +#include <freertos/queue.h> + +namespace esphome::speaker_source { + +// THREADING MODEL: +// This component coordinates media sources that run their own decode tasks with speakers +// that have their own playback callback tasks. Three thread contexts exist: +// +// - Main loop task: setup(), loop(), dump_config(), handle_media_state_changed_(), +// handle_volume_request_(), handle_mute_request_(), handle_play_uri_request_(), +// set_volume_(), set_mute_state_(), control(), get_media_pipeline_state_(), +// find_source_for_uri_(), try_execute_play_uri_(), save_volume_restore_state_() +// +// - Media source task(s): handle_media_output_() via SourceBinding::write_audio(). +// Called from each source's decode task thread when streaming audio data. +// Reads ps.active_source (atomic), writes ps.pending_frames (atomic), and calls +// ps.speaker methods (speaker pointer is immutable after setup). +// +// - Speaker callback task: handle_speaker_playback_callback_() via speaker's +// add_audio_output_callback(). Called when the speaker finishes writing frames to the DAC. +// Reads ps.active_source (atomic), writes ps.pending_frames (atomic), and calls +// active_source->notify_audio_played(). +// +// control() is only called from the main loop (HA/automation commands). +// Source tasks use defer() for all requests (volume, mute, play_uri). +// +// Thread-safe communication: +// - FreeRTOS queue (media_control_command_queue_): control() -> loop() for play/command dispatch +// - defer(): SourceBinding::request_volume/request_mute/request_play_uri -> main loop +// - Atomic fields (active_source, pending_frames): shared between all three thread contexts +// +// Non-atomic pipeline fields (last_source, stopping_source, pending_source) are only accessed +// from the main loop thread. + +enum Pipeline : uint8_t { + MEDIA_PIPELINE = 0, +}; + +// Forward declaration +class SpeakerSourceMediaPlayer; + +/// @brief Per-source listener binding that captures the source pointer at registration time. +/// Each binding implements MediaSourceListener and forwards callbacks to the player with the source identified. +/// Defined before PipelineContext so pipelines can own their bindings directly. +struct SourceBinding : public media_source::MediaSourceListener { + SourceBinding(SpeakerSourceMediaPlayer *player, media_source::MediaSource *source, uint8_t pipeline) + : player(player), source(source), pipeline(pipeline) {} + SpeakerSourceMediaPlayer *player; + media_source::MediaSource *source; + uint8_t pipeline; + + // Implementations are in the .cpp file because SpeakerSourceMediaPlayer is only forward-declared here + size_t write_audio(const uint8_t *data, size_t length, uint32_t timeout_ms, + const audio::AudioStreamInfo &stream_info) override; + void report_state(media_source::MediaSourceState state) override; + void request_volume(float volume) override; + void request_mute(bool is_muted) override; + void request_play_uri(const std::string &uri) override; +}; + +struct PipelineContext { + speaker::Speaker *speaker{nullptr}; + optional<media_player::MediaPlayerSupportedFormat> format; + + std::atomic<media_source::MediaSource *> active_source{nullptr}; + media_source::MediaSource *last_source{nullptr}; + media_source::MediaSource *stopping_source{nullptr}; // Source we've asked to stop, awaiting IDLE + media_source::MediaSource *pending_source{nullptr}; // Source we've asked to play, awaiting PLAYING + + // Each SourceBinding pairs a MediaSource* with its listener implementation. + // Uses unique_ptr so binding addresses are stable and set_listener() can be called in add_media_source(). + // Uses std::vector because the count varies across instances (multiple speaker_source media players may exist). + std::vector<std::unique_ptr<SourceBinding>> sources; + + // Track frames sent to speaker to correlate with playback callbacks. + // Atomic because it is written from the main loop/source tasks and read/decremented from the speaker playback + // callback. + std::atomic<uint32_t> pending_frames{0}; + + /// @brief Check if this pipeline is configured (has a speaker assigned) + bool is_configured() const { return this->speaker != nullptr; } +}; + +struct MediaPlayerControlCommand { + enum Type : uint8_t { + PLAY_URI, // Find a source that can handle this URI and play it + SEND_COMMAND, // Send command to active source + }; + Type type; + uint8_t pipeline; + + union { + std::string *uri; // Owned pointer, must delete after xQueueReceive (for PLAY_URI) + media_player::MediaPlayerCommand command; + } data; +}; + +struct VolumeRestoreState { + float volume; + bool is_muted; +}; + +class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPlayer { + friend struct SourceBinding; + + public: + float get_setup_priority() const override { return esphome::setup_priority::PROCESSOR; } + void setup() override; + void loop() override; + void dump_config() override; + + // MediaPlayer implementations + media_player::MediaPlayerTraits get_traits() override; + bool is_muted() const override { return this->is_muted_; } + + // Percentage to increase or decrease the volume for volume up or volume down commands + void set_volume_increment(float volume_increment) { this->volume_increment_ = volume_increment; } + + // Volume used initially on first boot when no volume had been previously saved + void set_volume_initial(float volume_initial) { this->volume_initial_ = volume_initial; } + + void set_volume_max(float volume_max) { this->volume_max_ = volume_max; } + void set_volume_min(float volume_min) { this->volume_min_ = volume_min; } + + /// @brief Adds a media source to a pipeline and registers this player as its listener + void add_media_source(uint8_t pipeline, media_source::MediaSource *media_source); + + void set_speaker(uint8_t pipeline, speaker::Speaker *speaker) { this->pipelines_[pipeline].speaker = speaker; } + void set_format(uint8_t pipeline, const media_player::MediaPlayerSupportedFormat &format) { + this->pipelines_[pipeline].format = format; + } + + Trigger<> *get_mute_trigger() { return &this->mute_trigger_; } + Trigger<> *get_unmute_trigger() { return &this->unmute_trigger_; } + Trigger<float> *get_volume_trigger() { return &this->volume_trigger_; } + + protected: + // Callbacks from source bindings (pipeline index is captured at binding creation time) + size_t handle_media_output_(uint8_t pipeline, media_source::MediaSource *source, const uint8_t *data, size_t length, + uint32_t timeout_ms, const audio::AudioStreamInfo &stream_info); + void handle_media_state_changed_(uint8_t pipeline, media_source::MediaSource *source, + media_source::MediaSourceState state); + void handle_volume_request_(float volume); + void handle_mute_request_(bool is_muted); + void handle_play_uri_request_(uint8_t pipeline, const std::string &uri); + + void handle_speaker_playback_callback_(uint32_t frames, int64_t timestamp, uint8_t pipeline); + + // Receives commands from HA or from the voice assistant component + // Sends commands to the media_control_command_queue_ + void control(const media_player::MediaPlayerCall &call) override; + + /// @brief Updates this->volume and saves volume/mute state to flash for restoration if publish is true. + void set_volume_(float volume, bool publish = true); + + /// @brief Sets the mute state. + /// @param mute_state If true, audio will be muted. If false, audio will be unmuted + /// @param publish If true, saves volume/mute state to flash for restoration + void set_mute_state_(bool mute_state, bool publish = true); + + /// @brief Saves the current volume and mute state to the flash for restoration. + void save_volume_restore_state_(); + + /// @brief Determine media player state from the media pipeline's active source + /// @param media_source Active source for the media pipeline (may be nullptr) + /// @return The appropriate MediaPlayerState + media_player::MediaPlayerState get_media_pipeline_state_(media_source::MediaSource *media_source) const; + + bool try_execute_play_uri_(const std::string &uri, uint8_t pipeline); + media_source::MediaSource *find_source_for_uri_(const std::string &uri, uint8_t pipeline); + QueueHandle_t media_control_command_queue_; + + // Pipeline context for media pipeline. See THREADING MODEL at top of namespace for access rules. + std::array<PipelineContext, 1> pipelines_; + + // Used to save volume/mute state for restoration on reboot + ESPPreferenceObject pref_; + + Trigger<> mute_trigger_; + Trigger<> unmute_trigger_; + Trigger<float> volume_trigger_; + + // The amount to change the volume on volume up/down commands + float volume_increment_; + + // The initial volume used by Setup when no previous volume was saved + float volume_initial_; + + float volume_max_; + float volume_min_; + + bool is_muted_{false}; +}; + +} // namespace esphome::speaker_source + +#endif // USE_ESP32 diff --git a/tests/components/speaker_source/common.yaml b/tests/components/speaker_source/common.yaml new file mode 100644 index 0000000000..cfcb065f57 --- /dev/null +++ b/tests/components/speaker_source/common.yaml @@ -0,0 +1,43 @@ +i2s_audio: + i2s_lrclk_pin: ${i2s_bclk_pin} + i2s_bclk_pin: ${i2s_lrclk_pin} + i2s_mclk_pin: ${i2s_mclk_pin} + +speaker: + - platform: i2s_audio + id: speaker_id + dac_type: external + i2s_dout_pin: ${i2s_dout_pin} + sample_rate: 48000 + num_channels: 2 + +audio_file: + - id: test_audio + file: + type: local + path: $component_dir/test.wav + +media_source: + - platform: audio_file + id: audio_file_source + +media_player: + - platform: speaker_source + id: media_player_id + name: Media Player + volume_increment: 0.02 + volume_initial: 0.75 + volume_max: 0.95 + volume_min: 0.0 + media_pipeline: + speaker: speaker_id + format: FLAC + num_channels: 1 + sources: + - audio_file_source + on_mute: + - media_player.pause: + id: media_player_id + on_unmute: + - media_player.play: + id: media_player_id diff --git a/tests/components/speaker_source/test.esp32-idf.yaml b/tests/components/speaker_source/test.esp32-idf.yaml new file mode 100644 index 0000000000..e2439ebdf2 --- /dev/null +++ b/tests/components/speaker_source/test.esp32-idf.yaml @@ -0,0 +1,9 @@ +substitutions: + scl_pin: GPIO16 + sda_pin: GPIO17 + i2s_bclk_pin: GPIO27 + i2s_lrclk_pin: GPIO26 + i2s_mclk_pin: GPIO25 + i2s_dout_pin: GPIO23 + +<<: !include common.yaml diff --git a/tests/components/speaker_source/test.wav b/tests/components/speaker_source/test.wav new file mode 100644 index 0000000000000000000000000000000000000000..f9d07ef2238eb2fcb355055466d3789ee1a1fe0b GIT binary patch literal 46 ycmWIYbaPW<U|<M$40BD(Em06)U|?WmU}R{pV_;yYWnf@p5MW42EJ<Wy0098Ji3Z~U literal 0 HcmV?d00001 From 8d988723cdcd18dbe5a464f3065017a3cf64cbcf Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 10 Mar 2026 16:38:50 -0400 Subject: [PATCH 1269/2030] [config] Allow !extend/!remove on components without id in schema (#14682) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/voluptuous_schema.py | 6 ++ .../external_components/common.yaml | 6 +- .../external_components/test.esp32-idf.yaml | 4 + tests/unit_tests/test_voluptuous_schema.py | 86 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 tests/unit_tests/test_voluptuous_schema.py diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index 7220fb307f..0703c54a7a 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -175,6 +175,12 @@ class _Schema(vol.Schema): else: if self.extra == vol.ALLOW_EXTRA: out[key] = value + elif key == "id": + # Silently drop 'id' on any dict so that + # !extend / !remove work on every list-based + # config without requiring each component to + # declare an id in its schema. + pass elif self.extra != vol.REMOVE_EXTRA: if isinstance(key, str) and key_names: matches = difflib.get_close_matches(key, key_names) diff --git a/tests/components/external_components/common.yaml b/tests/components/external_components/common.yaml index 2b51267ec6..c55129094c 100644 --- a/tests/components/external_components/common.yaml +++ b/tests/components/external_components/common.yaml @@ -1,6 +1,8 @@ external_components: - - source: github://esphome/esphome@dev + - id: my_ext + source: github://esphome/esphome@dev refresh: 1d components: [bh1750] - - source: ../../../esphome/components + - id: my_local + source: ../../../esphome/components components: [sntp] diff --git a/tests/components/external_components/test.esp32-idf.yaml b/tests/components/external_components/test.esp32-idf.yaml index dade44d145..afe2bd5d6a 100644 --- a/tests/components/external_components/test.esp32-idf.yaml +++ b/tests/components/external_components/test.esp32-idf.yaml @@ -1 +1,5 @@ +# WARNING: Using !extend or !remove prevents automatic component grouping in CI, making builds slower. <<: !include common.yaml + +external_components: + - id: !remove my_local diff --git a/tests/unit_tests/test_voluptuous_schema.py b/tests/unit_tests/test_voluptuous_schema.py new file mode 100644 index 0000000000..21c7decede --- /dev/null +++ b/tests/unit_tests/test_voluptuous_schema.py @@ -0,0 +1,86 @@ +"""Tests for voluptuous_schema.py.""" + +import pytest +import voluptuous as vol + +from esphome.voluptuous_schema import _Schema + + +class TestIdKeyDropping: + """Test that 'id' keys are silently dropped in PREVENT_EXTRA schemas.""" + + def test_id_key_silently_dropped(self): + """Schema without 'id' should accept and drop 'id' key from input.""" + schema = _Schema( + { + vol.Required("name"): str, + vol.Optional("value", default=0): int, + } + ) + result = schema({"name": "test", "value": 42, "id": "my_id"}) + assert result == {"name": "test", "value": 42} + assert "id" not in result + + def test_id_key_dropped_with_only_required(self): + """Schema with only required keys should still drop 'id'.""" + schema = _Schema( + { + vol.Required("source"): str, + } + ) + result = schema({"source": "github://test", "id": "my_component"}) + assert result == {"source": "github://test"} + + def test_other_extra_keys_still_rejected(self): + """Non-'id' extra keys should still raise errors.""" + schema = _Schema( + { + vol.Required("name"): str, + } + ) + with pytest.raises(vol.MultipleInvalid, match="extra keys not allowed"): + schema({"name": "test", "unknown_key": "value"}) + + def test_id_key_not_dropped_when_in_schema(self): + """When 'id' is declared in the schema, it should be validated normally.""" + schema = _Schema( + { + vol.Required("id"): str, + vol.Required("name"): str, + } + ) + result = schema({"id": "my_id", "name": "test"}) + assert result == {"id": "my_id", "name": "test"} + + def test_id_key_not_dropped_with_allow_extra(self): + """With ALLOW_EXTRA, 'id' should be kept (not dropped).""" + schema = _Schema( + { + vol.Required("name"): str, + }, + extra=vol.ALLOW_EXTRA, + ) + result = schema({"name": "test", "id": "my_id"}) + assert result == {"name": "test", "id": "my_id"} + + def test_id_key_dropped_with_remove_extra(self): + """With REMOVE_EXTRA, 'id' should be removed along with other extras.""" + schema = _Schema( + { + vol.Required("name"): str, + }, + extra=vol.REMOVE_EXTRA, + ) + result = schema({"name": "test", "id": "my_id", "other": "value"}) + assert result == {"name": "test"} + + def test_without_id_no_extra_keys(self): + """Normal validation without 'id' key should work as before.""" + schema = _Schema( + { + vol.Required("name"): str, + vol.Optional("value", default=0): int, + } + ) + result = schema({"name": "test"}) + assert result == {"name": "test", "value": 0} From 6356e3def9dce68f3e815d5bd58d2c42ef4ccb7f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 10:42:38 -1000 Subject: [PATCH 1270/2030] [core] Warn on crystal frequency mismatch during serial upload (#14582) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/__main__.py | 58 ++++++++++- esphome/util.py | 45 +++++++-- tests/unit_tests/test_main.py | 124 ++++++++++++++++++++++++ tests/unit_tests/test_util.py | 175 ++++++++++++++++++++++++++++++++++ 4 files changed, 391 insertions(+), 11 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index f33e7f4b42..3f0da85a69 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1,6 +1,7 @@ # PYTHON_ARGCOMPLETE_OK import argparse from collections.abc import Callable +from contextlib import suppress from datetime import datetime import functools import getpass @@ -687,6 +688,47 @@ def _check_and_emit_build_info() -> None: ) +def _get_configured_xtal_freq() -> int | None: + """Read the configured crystal frequency from the sdkconfig file.""" + sdkconfig_path = CORE.relative_build_path(f"sdkconfig.{CORE.name}") + if not sdkconfig_path.is_file(): + return None + with suppress(OSError, ValueError): + content = sdkconfig_path.read_text() + for line in content.splitlines(): + if line.startswith("CONFIG_XTAL_FREQ="): + return int(line.split("=", 1)[1]) + return None + + +def _make_crystal_freq_callback( + configured_freq: int, +) -> Callable[[str], str | None]: + """Create a callback that checks esptool crystal frequency output.""" + crystal_re = re.compile(r"Crystal frequency:\s+(\d+)\s*MHz") + + def check_crystal_line(line: str) -> str | None: + if not (match := crystal_re.search(line)): + return None + detected = int(match.group(1)) + if detected == configured_freq: + return None + return ( + f"\n\033[33mWARNING: Crystal frequency mismatch! " + f"Device reports {detected}MHz but firmware is configured " + f"for {configured_freq}MHz.\n" + f"UART logging and other clock-dependent features will not " + f"work correctly.\n" + f"Set the correct crystal frequency with sdkconfig_options:\n" + f" esp32:\n" + f" framework:\n" + f" sdkconfig_options:\n" + f" CONFIG_XTAL_FREQ_{detected}: 'y'\033[0m\n\n" + ) + + return check_crystal_line + + def upload_using_esptool( config: ConfigType, port: str, file: str, speed: int ) -> str | int: @@ -715,6 +757,14 @@ def upload_using_esptool( mcu = get_esp32_variant().lower() + line_callbacks: list[Callable[[str], str | None]] = [] + if ( + CORE.is_esp32 + and file is None + and (configured_freq := _get_configured_xtal_freq()) is not None + ): + line_callbacks.append(_make_crystal_freq_callback(configured_freq)) + def run_esptool(baud_rate): cmd = [ "esptool", @@ -739,9 +789,13 @@ def upload_using_esptool( if os.environ.get("ESPHOME_USE_SUBPROCESS") is None: import esptool - return run_external_command(esptool.main, *cmd) # pylint: disable=no-member + return run_external_command( + esptool.main, # pylint: disable=no-member + *cmd, + line_callbacks=line_callbacks, + ) - return run_external_process(*cmd) + return run_external_process(*cmd, line_callbacks=line_callbacks) rc = run_esptool(first_baudrate) if rc == 0 or first_baudrate == 115200: diff --git a/esphome/util.py b/esphome/util.py index 6a21b4f627..73cc3aa5ab 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -125,7 +125,12 @@ ANSI_ESCAPE = re.compile(r"\033[@-_][0-?]*[ -/]*[@-~]") class RedirectText: - def __init__(self, out, filter_lines=None): + def __init__( + self, + out, + filter_lines: list[str] | None = None, + line_callbacks: list[Callable[[str], str | None]] | None = None, + ) -> None: self._out = out if filter_lines is None: self._filter_pattern = None @@ -133,6 +138,7 @@ class RedirectText: pattern = r"|".join(r"(?:" + pattern + r")" for pattern in filter_lines) self._filter_pattern = re.compile(pattern) self._line_buffer = "" + self._line_callbacks = line_callbacks or [] def __getattr__(self, item): return getattr(self._out, item) @@ -157,7 +163,7 @@ class RedirectText: if not isinstance(s, str): s = s.decode() - if self._filter_pattern is not None: + if self._filter_pattern is not None or self._line_callbacks: self._line_buffer += s lines = self._line_buffer.splitlines(True) for line in lines: @@ -169,7 +175,10 @@ class RedirectText: line_without_ansi = ANSI_ESCAPE.sub("", line) line_without_end = line_without_ansi.rstrip() - if self._filter_pattern.match(line_without_end) is not None: + if ( + self._filter_pattern is not None + and self._filter_pattern.match(line_without_end) is not None + ): # Filter pattern matched, ignore the line continue @@ -181,6 +190,9 @@ class RedirectText: and (help_msg := get_esp32_arduino_flash_error_help()) ): self._write_color_replace(help_msg) + for callback in self._line_callbacks: + if msg := callback(line_without_end): + self._write_color_replace(msg) else: self._write_color_replace(s) @@ -194,7 +206,11 @@ class RedirectText: def run_external_command( - func, *cmd, capture_stdout: bool = False, filter_lines: str = None + func, + *cmd, + capture_stdout: bool = False, + filter_lines: list[str] | None = None, + line_callbacks: list[Callable[[str], str | None]] | None = None, ) -> int | str: """ Run a function from an external package that acts like a main method. @@ -204,7 +220,9 @@ def run_external_command( :param func: Function to execute :param cmd: Command to run as (eg first element of sys.argv) :param capture_stdout: Capture text from stdout and return that. - :param filter_lines: Regular expression used to filter captured output. + Note: line_callbacks are not invoked when capture_stdout is True. + :param filter_lines: Regular expressions used to filter captured output. + :param line_callbacks: Callbacks invoked per line; non-None returns are written to output. :return: str if `capture_stdout` is set else int exit code. """ @@ -218,9 +236,13 @@ def run_external_command( _LOGGER.debug("Running: %s", full_cmd) orig_stdout = sys.stdout - sys.stdout = RedirectText(sys.stdout, filter_lines=filter_lines) + sys.stdout = RedirectText( + sys.stdout, filter_lines=filter_lines, line_callbacks=line_callbacks + ) orig_stderr = sys.stderr - sys.stderr = RedirectText(sys.stderr, filter_lines=filter_lines) + sys.stderr = RedirectText( + sys.stderr, filter_lines=filter_lines, line_callbacks=line_callbacks + ) if capture_stdout: cap_stdout = sys.stdout = io.StringIO() @@ -254,14 +276,19 @@ def run_external_process(*cmd: str, **kwargs: Any) -> int | str: full_cmd = " ".join(shlex_quote(x) for x in cmd) _LOGGER.debug("Running: %s", full_cmd) filter_lines = kwargs.get("filter_lines") + line_callbacks = kwargs.get("line_callbacks") capture_stdout = kwargs.get("capture_stdout", False) if capture_stdout: sub_stdout = subprocess.PIPE else: - sub_stdout = RedirectText(sys.stdout, filter_lines=filter_lines) + sub_stdout = RedirectText( + sys.stdout, filter_lines=filter_lines, line_callbacks=line_callbacks + ) - sub_stderr = RedirectText(sys.stderr, filter_lines=filter_lines) + sub_stderr = RedirectText( + sys.stderr, filter_lines=filter_lines, line_callbacks=line_callbacks + ) try: proc = subprocess.run( diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index b6f1a28086..b853461151 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -6,6 +6,7 @@ from collections.abc import Generator from dataclasses import dataclass import json import logging +import os from pathlib import Path import re import sys @@ -19,6 +20,8 @@ from pytest import CaptureFixture from esphome import platformio_api from esphome.__main__ import ( Purpose, + _get_configured_xtal_freq, + _make_crystal_freq_callback, choose_upload_log_host, command_analyze_memory, command_clean_all, @@ -3717,3 +3720,124 @@ esp32: clean_output.split("SUMMARY")[1] if "SUMMARY" in clean_output else "" ) assert "secrets.yaml" not in summary_section + + +def test_get_configured_xtal_freq_reads_sdkconfig(tmp_path: Path) -> None: + """Test reading XTAL_FREQ from sdkconfig.""" + CORE.name = "test-device" + CORE.build_path = tmp_path + sdkconfig = tmp_path / "sdkconfig.test-device" + sdkconfig.write_text( + "CONFIG_SOC_XTAL_SUPPORT_26M=y\nCONFIG_XTAL_FREQ=26\nCONFIG_XTAL_FREQ_26=y\n" + ) + assert _get_configured_xtal_freq() == 26 + + +def test_get_configured_xtal_freq_default_40(tmp_path: Path) -> None: + """Test reading default 40MHz XTAL_FREQ from sdkconfig.""" + CORE.name = "test-device" + CORE.build_path = tmp_path + sdkconfig = tmp_path / "sdkconfig.test-device" + sdkconfig.write_text("CONFIG_XTAL_FREQ=40\nCONFIG_XTAL_FREQ_40=y\n") + assert _get_configured_xtal_freq() == 40 + + +def test_get_configured_xtal_freq_missing_file(tmp_path: Path) -> None: + """Test that missing sdkconfig returns None.""" + CORE.name = "test-device" + CORE.build_path = tmp_path + assert _get_configured_xtal_freq() is None + + +def test_get_configured_xtal_freq_no_xtal_line(tmp_path: Path) -> None: + """Test that sdkconfig without XTAL_FREQ returns None.""" + CORE.name = "test-device" + CORE.build_path = tmp_path + sdkconfig = tmp_path / "sdkconfig.test-device" + sdkconfig.write_text("CONFIG_OTHER=123\n") + assert _get_configured_xtal_freq() is None + + +def test_crystal_freq_callback_mismatch() -> None: + """Test callback returns warning on crystal frequency mismatch.""" + callback = _make_crystal_freq_callback(40) + result = callback("Crystal frequency: 26MHz") + assert result is not None + assert "26MHz" in result + assert "40MHz" in result + assert "CONFIG_XTAL_FREQ_26" in result + + +def test_crystal_freq_callback_match() -> None: + """Test callback returns None when frequencies match.""" + callback = _make_crystal_freq_callback(40) + result = callback("Crystal frequency: 40MHz") + assert result is None + + +def test_crystal_freq_callback_no_crystal_line() -> None: + """Test callback returns None for unrelated lines.""" + callback = _make_crystal_freq_callback(40) + assert callback("Chip type: ESP8684H") is None + assert callback("MAC: a0:b7:65:8b:16:d4") is None + assert callback("") is None + + +def test_upload_using_esptool_passes_crystal_callback( + tmp_path: Path, + mock_run_external_command_main: Mock, + mock_get_idedata: Mock, +) -> None: + """Test that upload_using_esptool passes crystal freq callback for ESP32.""" + setup_core(platform=PLATFORM_ESP32, tmp_path=tmp_path, name="test") + CORE.data[KEY_ESP32] = {KEY_VARIANT: VARIANT_ESP32} + + # Create sdkconfig with XTAL_FREQ + build_dir = Path(CORE.build_path) + build_dir.mkdir(parents=True, exist_ok=True) + sdkconfig = build_dir / "sdkconfig.test" + sdkconfig.write_text("CONFIG_XTAL_FREQ=40\n") + + mock_idedata = MagicMock(spec=platformio_api.IDEData) + mock_idedata.firmware_bin_path = tmp_path / "firmware.bin" + mock_idedata.extra_flash_images = [] + mock_get_idedata.return_value = mock_idedata + (tmp_path / "firmware.bin").touch() + + config = {CONF_ESPHOME: {"platformio_options": {}}} + upload_using_esptool(config, "/dev/ttyUSB0", None, None) + + # Verify line_callbacks was passed with the crystal callback + call_kwargs = mock_run_external_command_main.call_args[1] + assert "line_callbacks" in call_kwargs + assert len(call_kwargs["line_callbacks"]) == 1 + + +def test_upload_using_esptool_subprocess_passes_crystal_callback( + mock_run_external_process: Mock, + mock_get_idedata: Mock, + tmp_path: Path, +) -> None: + """Test that crystal freq callback is passed via run_external_process.""" + setup_core(platform=PLATFORM_ESP32, tmp_path=tmp_path, name="test") + CORE.data[KEY_ESP32] = {KEY_VARIANT: VARIANT_ESP32} + + # Create sdkconfig with XTAL_FREQ + build_dir = Path(CORE.build_path) + build_dir.mkdir(parents=True, exist_ok=True) + sdkconfig = build_dir / "sdkconfig.test" + sdkconfig.write_text("CONFIG_XTAL_FREQ=40\n") + + mock_idedata = MagicMock(spec=platformio_api.IDEData) + mock_idedata.firmware_bin_path = tmp_path / "firmware.bin" + mock_idedata.extra_flash_images = [] + mock_get_idedata.return_value = mock_idedata + (tmp_path / "firmware.bin").touch() + + config = {CONF_ESPHOME: {"platformio_options": {}}} + with patch.dict(os.environ, {"ESPHOME_USE_SUBPROCESS": "1"}): + upload_using_esptool(config, "/dev/ttyUSB0", None, None) + + call_kwargs = mock_run_external_process.call_args[1] + assert "line_callbacks" in call_kwargs + assert len(call_kwargs["line_callbacks"]) == 1 diff --git a/tests/unit_tests/test_util.py b/tests/unit_tests/test_util.py index ca3fd9b78a..ff58fb1394 100644 --- a/tests/unit_tests/test_util.py +++ b/tests/unit_tests/test_util.py @@ -2,9 +2,12 @@ from __future__ import annotations +from collections.abc import Callable +import io from pathlib import Path import subprocess import sys +from typing import Any from unittest.mock import MagicMock, patch import pytest @@ -407,6 +410,178 @@ def test_shlex_quote_edge_cases() -> None: assert util.shlex_quote(" ") == "' '" +def _make_redirect( + line_callbacks: list[Callable[[str], str | None]] | None = None, + filter_lines: list[str] | None = None, +) -> tuple[util.RedirectText, io.StringIO]: + """Create a RedirectText that writes to a StringIO buffer.""" + buf = io.StringIO() + redirect = util.RedirectText( + buf, filter_lines=filter_lines, line_callbacks=line_callbacks + ) + return redirect, buf + + +def test_redirect_text_callback_called_on_matching_line() -> None: + """Test that a line callback is called and its output is written.""" + results: list[str] = [] + + def callback(line: str) -> str | None: + results.append(line) + if "target" in line: + return "CALLBACK OUTPUT\n" + return None + + redirect, buf = _make_redirect(line_callbacks=[callback]) + redirect.write("some target line\n") + + assert "some target line" in buf.getvalue() + assert "CALLBACK OUTPUT" in buf.getvalue() + assert len(results) == 1 + + +def test_redirect_text_callback_not_triggered_on_non_matching_line() -> None: + """Test that callback returns None for non-matching lines.""" + + def callback(line: str) -> str | None: + if "target" in line: + return "FOUND\n" + return None + + redirect, buf = _make_redirect(line_callbacks=[callback]) + redirect.write("no match here\n") + + assert "no match here" in buf.getvalue() + assert "FOUND" not in buf.getvalue() + + +def test_redirect_text_callback_works_without_filter_pattern() -> None: + """Test that callbacks fire even when no filter_lines is set.""" + + def callback(line: str) -> str | None: + if "Crystal" in line: + return "WARNING: mismatch\n" + return None + + redirect, buf = _make_redirect(line_callbacks=[callback]) + redirect.write("Crystal frequency: 26MHz\n") + + assert "Crystal frequency: 26MHz" in buf.getvalue() + assert "WARNING: mismatch" in buf.getvalue() + + +def test_redirect_text_callback_works_with_filter_pattern() -> None: + """Test that callbacks fire alongside filter patterns.""" + + def callback(line: str) -> str | None: + if "important" in line: + return "NOTED\n" + return None + + redirect, buf = _make_redirect( + line_callbacks=[callback], + filter_lines=[r"^skip this.*"], + ) + redirect.write("skip this line\n") + redirect.write("important line\n") + + assert "skip this" not in buf.getvalue() + assert "important line" in buf.getvalue() + assert "NOTED" in buf.getvalue() + + +def test_redirect_text_multiple_callbacks() -> None: + """Test that multiple callbacks are all invoked.""" + + def callback_a(line: str) -> str | None: + if "test" in line: + return "FROM A\n" + return None + + def callback_b(line: str) -> str | None: + if "test" in line: + return "FROM B\n" + return None + + redirect, buf = _make_redirect(line_callbacks=[callback_a, callback_b]) + redirect.write("test line\n") + + output = buf.getvalue() + assert "FROM A" in output + assert "FROM B" in output + + +def test_redirect_text_incomplete_line_buffered() -> None: + """Test that incomplete lines are buffered until newline.""" + results: list[str] = [] + + def callback(line: str) -> str | None: + results.append(line) + return None + + redirect, buf = _make_redirect(line_callbacks=[callback]) + redirect.write("partial") + assert len(results) == 0 + + redirect.write(" line\n") + assert len(results) == 1 + assert results[0] == "partial line" + + +def test_run_external_command_line_callbacks(capsys: pytest.CaptureFixture) -> None: + """Test that run_external_command passes line_callbacks to RedirectText.""" + results: list[str] = [] + + def callback(line: str) -> str | None: + results.append(line) + if "hello" in line: + return "CALLBACK FIRED\n" + return None + + def fake_main() -> int: + print("hello world") + return 0 + + rc = util.run_external_command(fake_main, "fake", line_callbacks=[callback]) + + assert rc == 0 + assert len(results) == 1 + assert "hello world" in results[0] + captured = capsys.readouterr() + assert "CALLBACK FIRED" in captured.out + + +def test_run_external_process_line_callbacks() -> None: + """Test that run_external_process passes line_callbacks to RedirectText.""" + results: list[str] = [] + + def callback(line: str) -> str | None: + results.append(line) + if "from subprocess" in line: + return "PROCESS CALLBACK\n" + return None + + with patch("esphome.util.subprocess.run") as mock_run: + + def run_side_effect(*args: Any, **kwargs: Any) -> MagicMock: + # Simulate subprocess writing to the stdout RedirectText + stdout = kwargs.get("stdout") + if stdout is not None and isinstance(stdout, util.RedirectText): + stdout.write("from subprocess\n") + return MagicMock(returncode=0) + + mock_run.side_effect = run_side_effect + + rc = util.run_external_process( + "echo", + "test", + line_callbacks=[callback], + ) + + assert rc == 0 + assert any("from subprocess" in r for r in results) + + def test_get_picotool_path_found(tmp_path: Path) -> None: """Test picotool path derivation from cc_path.""" # Create the expected directory structure From 9513edc46875904c9638133c9feb612de9301c62 Mon Sep 17 00:00:00 2001 From: CFlix <38142312+CFlix@users.noreply.github.com> Date: Tue, 10 Mar 2026 22:17:13 +0100 Subject: [PATCH 1271/2030] [dew_point] Add dew_point sensor component (#14441) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/dew_point/__init__.py | 1 + esphome/components/dew_point/dew_point.cpp | 82 +++++++++++++++++++ esphome/components/dew_point/dew_point.h | 26 ++++++ esphome/components/dew_point/sensor.py | 46 +++++++++++ tests/components/dew_point/common.yaml | 19 +++++ .../components/dew_point/test.esp32-idf.yaml | 1 + .../dew_point/test.esp8266-ard.yaml | 1 + .../components/dew_point/test.rp2040-ard.yaml | 1 + 9 files changed, 178 insertions(+) create mode 100644 esphome/components/dew_point/__init__.py create mode 100644 esphome/components/dew_point/dew_point.cpp create mode 100644 esphome/components/dew_point/dew_point.h create mode 100644 esphome/components/dew_point/sensor.py create mode 100644 tests/components/dew_point/common.yaml create mode 100644 tests/components/dew_point/test.esp32-idf.yaml create mode 100644 tests/components/dew_point/test.esp8266-ard.yaml create mode 100644 tests/components/dew_point/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 12aff01e73..e72b164761 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -132,6 +132,7 @@ esphome/components/dashboard_import/* @esphome/core esphome/components/datetime/* @jesserockz @rfdarter esphome/components/debug/* @esphome/core esphome/components/delonghi/* @grob6000 +esphome/components/dew_point/* @CFlix esphome/components/dfplayer/* @glmnet esphome/components/dfrobot_sen0395/* @niklasweber esphome/components/dht/* @OttoWinter diff --git a/esphome/components/dew_point/__init__.py b/esphome/components/dew_point/__init__.py new file mode 100644 index 0000000000..3b852436c3 --- /dev/null +++ b/esphome/components/dew_point/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@CFlix"] diff --git a/esphome/components/dew_point/dew_point.cpp b/esphome/components/dew_point/dew_point.cpp new file mode 100644 index 0000000000..04ac305e3d --- /dev/null +++ b/esphome/components/dew_point/dew_point.cpp @@ -0,0 +1,82 @@ + +#include "dew_point.h" + +namespace esphome::dew_point { + +static const char *const TAG = "dew_point.sensor"; + +void DewPointComponent::setup() { + // Register callbacks for sensor updates + if (this->temperature_sensor_ != nullptr) { + this->temperature_sensor_->add_on_state_callback([this](float state) { + this->temperature_value_ = state; + this->enable_loop(); + }); + // Get initial value + if (this->temperature_sensor_->has_state()) { + this->temperature_value_ = this->temperature_sensor_->get_state(); + } + } + + if (this->humidity_sensor_ != nullptr) { + this->humidity_sensor_->add_on_state_callback([this](float state) { + this->humidity_value_ = state; + this->enable_loop(); + }); + // Get initial value + if (this->humidity_sensor_->has_state()) { + this->humidity_value_ = this->humidity_sensor_->get_state(); + } + } +} + +void DewPointComponent::dump_config() { + LOG_SENSOR("", "Dew Point", this); + ESP_LOGCONFIG(TAG, + "Sources\n" + " Temperature: '%s'\n" + " Humidity: '%s'", + this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str()); +} + +float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; } + +void DewPointComponent::loop() { + // Only run once + this->disable_loop(); + + // Check if we have valid values for both sensors + if (std::isnan(this->temperature_value_) || std::isnan(this->humidity_value_)) { + ESP_LOGW(TAG, "Temperature or humidity value is NaN, skipping calculation"); + this->publish_state(NAN); + return; + } + + // Check for valid humidity range + if (this->humidity_value_ <= 0.0f || this->humidity_value_ > 100.0f) { + ESP_LOGW(TAG, "Humidity value out of range (0-100): %.2f", this->humidity_value_); + this->publish_state(NAN); + return; + } + + // Magnus formula constants + const float a{17.625f}; + const float b{243.04f}; + + // Calculate dew point using Magnus formula + // Td = (b * alpha) / (a - alpha) + // where alpha = ln(RH/100) + (a * T) / (b + T) + + const float alpha{std::log(this->humidity_value_ / 100.0f) + + (a * this->temperature_value_) / (b + this->temperature_value_)}; + + const float dew_point{(b * alpha) / (a - alpha)}; + + // Publish the calculated dew point + this->publish_state(dew_point); + + ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_, + this->humidity_value_); +} + +} // namespace esphome::dew_point diff --git a/esphome/components/dew_point/dew_point.h b/esphome/components/dew_point/dew_point.h new file mode 100644 index 0000000000..833c50fba2 --- /dev/null +++ b/esphome/components/dew_point/dew_point.h @@ -0,0 +1,26 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome::dew_point { + +class DewPointComponent : public Component, public sensor::Sensor { + public: + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } + void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } + + void setup() override; + void dump_config() override; + void loop() override; + + float get_setup_priority() const override; + + protected: + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; + float temperature_value_{NAN}; + float humidity_value_{NAN}; +}; + +} // namespace esphome::dew_point diff --git a/esphome/components/dew_point/sensor.py b/esphome/components/dew_point/sensor.py new file mode 100644 index 0000000000..4fee095602 --- /dev/null +++ b/esphome/components/dew_point/sensor.py @@ -0,0 +1,46 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_HUMIDITY, + CONF_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, +) + +DEPENDENCIES = ["sensor"] + +dew_point_ns = cg.esphome_ns.namespace("dew_point") +DewPointComponent = dew_point_ns.class_( + "DewPointComponent", cg.Component, sensor.Sensor +) + +CONFIG_SCHEMA = ( + sensor.sensor_schema( + DewPointComponent, + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + icon="mdi:weather-rainy", + ) + .extend( + { + cv.Required(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), + cv.Required(CONF_HUMIDITY): cv.use_id(sensor.Sensor), + } + ) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + var = await sensor.new_sensor(config) + await cg.register_component(var, config) + + temperature_sensor = await cg.get_variable(config[CONF_TEMPERATURE]) + cg.add(var.set_temperature_sensor(temperature_sensor)) + + humidity_sensor = await cg.get_variable(config[CONF_HUMIDITY]) + cg.add(var.set_humidity_sensor(humidity_sensor)) diff --git a/tests/components/dew_point/common.yaml b/tests/components/dew_point/common.yaml new file mode 100644 index 0000000000..527eeb2f84 --- /dev/null +++ b/tests/components/dew_point/common.yaml @@ -0,0 +1,19 @@ +sensor: + - platform: dew_point + name: Dew Point + temperature: template_temperature + humidity: template_humidity + - platform: template + id: template_humidity + lambda: |- + if (millis() > 10000) { + return 0.6; + } + return 0.0; + - platform: template + id: template_temperature + lambda: |- + if (millis() > 10000) { + return 42.0; + } + return 0.0; diff --git a/tests/components/dew_point/test.esp32-idf.yaml b/tests/components/dew_point/test.esp32-idf.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/dew_point/test.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/dew_point/test.esp8266-ard.yaml b/tests/components/dew_point/test.esp8266-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/dew_point/test.esp8266-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml diff --git a/tests/components/dew_point/test.rp2040-ard.yaml b/tests/components/dew_point/test.rp2040-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/dew_point/test.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 30c8c6870383f5c5e6d3f47328b3b685fc8a1518 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 11:22:23 -1000 Subject: [PATCH 1272/2030] [socket] Fix RP2040 TCP race condition between lwip callbacks and main loop (#14679) --- esphome/components/rp2040/helpers.cpp | 16 +++++- .../components/socket/lwip_raw_tcp_impl.cpp | 52 +++++++++++++++++++ esphome/components/socket/lwip_raw_tcp_impl.h | 6 +++ 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/esphome/components/rp2040/helpers.cpp b/esphome/components/rp2040/helpers.cpp index 30b40a723a..4191c2164a 100644 --- a/esphome/components/rp2040/helpers.cpp +++ b/esphome/components/rp2040/helpers.cpp @@ -7,6 +7,7 @@ #if defined(USE_WIFI) #include <WiFi.h> +#include <pico/cyw43_arch.h> // For cyw43_arch_lwip_begin/end (LwIPLock) #endif #include <hardware/structs/rosc.h> #include <hardware/sync.h> @@ -44,9 +45,22 @@ void Mutex::unlock() {} IRAM_ATTR InterruptLock::InterruptLock() { state_ = save_and_disable_interrupts(); } IRAM_ATTR InterruptLock::~InterruptLock() { restore_interrupts(state_); } -// RP2040 doesn't support lwIP core locking, so this is a no-op +// On RP2040 (Pico W), arduino-pico sets PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1. +// This means lwip callbacks run from a low-priority user IRQ context, not the +// main loop (see low_priority_irq_handler() in pico-sdk +// async_context_threadsafe_background.c). cyw43_arch_lwip_begin/end acquires the +// async_context recursive mutex to prevent IRQ callbacks from firing during +// critical sections. See esphome#10681. +// +// When CYW43 is not available (non-WiFi RP2040 boards), this is a no-op since +// there's no network stack and no lwip callbacks to race with. +#if defined(USE_WIFI) +LwIPLock::LwIPLock() { cyw43_arch_lwip_begin(); } +LwIPLock::~LwIPLock() { cyw43_arch_lwip_end(); } +#else LwIPLock::LwIPLock() {} LwIPLock::~LwIPLock() {} +#endif void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) #ifdef USE_WIFI diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 445a57809d..d7fa6a2694 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -111,6 +111,24 @@ void socket_wake() { } #endif +// ---- LWIP thread safety ---- +// +// On RP2040 (Pico W), arduino-pico sets PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1. +// This means lwip callbacks (recv_fn, accept_fn, err_fn) run from a low-priority +// user IRQ context, not the main loop (see low_priority_irq_handler() in pico-sdk +// async_context_threadsafe_background.c). They can preempt main-loop code at any point. +// +// Without locking, this causes race conditions between recv_fn and read() on the +// shared rx_buf_ pbuf chain — recv_fn calls pbuf_cat() while read() is freeing +// nodes, leading to use-after-free and infinite-loop crashes. See esphome#10681. +// +// On ESP8266, lwip callbacks run from the SYS context which cooperates with user +// code (CONT context) — they never preempt each other, so no locking is needed. +// +// esphome::LwIPLock is the platform-provided RAII guard (see helpers.h/helpers.cpp). +// On RP2040, it acquires cyw43_arch_lwip_begin/end. On ESP8266, it's a no-op. +#define LWIP_LOCK() esphome::LwIPLock lwip_lock_guard // NOLINT + static const char *const TAG = "socket.lwip"; // set to 1 to enable verbose lwip logging @@ -123,6 +141,7 @@ static const char *const TAG = "socket.lwip"; // ---- LWIPRawCommon methods ---- LWIPRawCommon::~LWIPRawCommon() { + LWIP_LOCK(); if (this->pcb_ != nullptr) { LWIP_LOG("tcp_abort(%p)", this->pcb_); tcp_abort(this->pcb_); @@ -131,6 +150,7 @@ LWIPRawCommon::~LWIPRawCommon() { } int LWIPRawCommon::bind(const struct sockaddr *name, socklen_t addrlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = EBADF; return -1; @@ -196,6 +216,7 @@ int LWIPRawCommon::bind(const struct sockaddr *name, socklen_t addrlen) { } int LWIPRawCommon::close() { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -214,6 +235,7 @@ int LWIPRawCommon::close() { } int LWIPRawCommon::shutdown(int how) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -240,6 +262,7 @@ int LWIPRawCommon::shutdown(int how) { } int LWIPRawCommon::getpeername(struct sockaddr *name, socklen_t *addrlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -252,6 +275,7 @@ int LWIPRawCommon::getpeername(struct sockaddr *name, socklen_t *addrlen) { } int LWIPRawCommon::getsockname(struct sockaddr *name, socklen_t *addrlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -284,6 +308,7 @@ size_t LWIPRawCommon::getsockname_to(std::span<char, SOCKADDR_STR_LEN> buf) { } int LWIPRawCommon::getsockopt(int level, int optname, void *optval, socklen_t *optlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -318,6 +343,7 @@ int LWIPRawCommon::getsockopt(int level, int optname, void *optval, socklen_t *o } int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, socklen_t optlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -388,6 +414,7 @@ int LWIPRawCommon::ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *n // ---- LWIPRawImpl methods ---- LWIPRawImpl::~LWIPRawImpl() { + LWIP_LOCK(); // Free any received pbufs that LWIP transferred ownership of via recv_fn. // tcp_abort() in the base destructor won't free these since LWIP considers // ownership transferred once the recv callback accepts them. @@ -399,6 +426,7 @@ LWIPRawImpl::~LWIPRawImpl() { } void LWIPRawImpl::init() { + LWIP_LOCK(); LWIP_LOG("init(%p)", this->pcb_); tcp_arg(this->pcb_, this); tcp_recv(this->pcb_, LWIPRawImpl::s_recv_fn); @@ -406,6 +434,9 @@ void LWIPRawImpl::init() { } void LWIPRawImpl::s_err_fn(void *arg, err_t err) { + // Called by lwip core which already holds the async_context lock on RP2040. + // No LWIP_LOCK() needed — acquiring it would be redundant (recursive mutex). + // // "If a connection is aborted because of an error, the application is alerted of this event by // the err callback." // pcb is already freed when this callback is called @@ -422,6 +453,7 @@ err_t LWIPRawImpl::s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, er } err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { + // Called by lwip core which already holds the async_context lock on RP2040. LWIP_LOG("recv(pb=%p err=%d)", pb, err); if (err != 0) { // "An error code if there has been an error receiving Only return ERR_ABRT if you have @@ -448,6 +480,7 @@ err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { } ssize_t LWIPRawImpl::read(void *buf, size_t len) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -507,6 +540,7 @@ ssize_t LWIPRawImpl::read(void *buf, size_t len) { } ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { + LWIP_LOCK(); // Hold for entire scatter-gather operation ssize_t ret = 0; for (int i = 0; i < iovcnt; i++) { ssize_t err = this->read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); @@ -525,6 +559,7 @@ ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { } ssize_t LWIPRawImpl::internal_write_(const void *buf, size_t len) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -557,6 +592,11 @@ ssize_t LWIPRawImpl::internal_write_(const void *buf, size_t len) { } int LWIPRawImpl::internal_output_() { + LWIP_LOCK(); + if (this->pcb_ == nullptr) { + errno = ECONNRESET; + return -1; + } LWIP_LOG("tcp_output(%p)", this->pcb_); err_t err = tcp_output(this->pcb_); if (err == ERR_ABRT) { @@ -576,6 +616,7 @@ int LWIPRawImpl::internal_output_() { } ssize_t LWIPRawImpl::write(const void *buf, size_t len) { + LWIP_LOCK(); // Hold for write + optional output ssize_t written = this->internal_write_(buf, len); if (written == -1) return -1; @@ -592,6 +633,7 @@ ssize_t LWIPRawImpl::write(const void *buf, size_t len) { } ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { + LWIP_LOCK(); // Hold for entire scatter-gather operation ssize_t written = 0; for (int i = 0; i < iovcnt; i++) { ssize_t err = this->internal_write_(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); @@ -621,6 +663,7 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { // ---- LWIPRawListenImpl methods ---- LWIPRawListenImpl::~LWIPRawListenImpl() { + LWIP_LOCK(); // Listen PCBs must use tcp_close(), not tcp_abort(). // tcp_abandon() asserts pcb->state != LISTEN and would access // fields that don't exist in the smaller tcp_pcb_listen struct. @@ -632,6 +675,7 @@ LWIPRawListenImpl::~LWIPRawListenImpl() { } void LWIPRawListenImpl::init() { + LWIP_LOCK(); LWIP_LOG("init(%p)", this->pcb_); tcp_arg(this->pcb_, this); tcp_accept(this->pcb_, LWIPRawListenImpl::s_accept_fn); @@ -639,6 +683,7 @@ void LWIPRawListenImpl::init() { } void LWIPRawListenImpl::s_err_fn(void *arg, err_t err) { + // Called by lwip core which already holds the async_context lock on RP2040. auto *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); ESP_LOGVV(TAG, "socket %p: err(err=%d)", arg_this, err); arg_this->pcb_ = nullptr; @@ -650,6 +695,7 @@ err_t LWIPRawListenImpl::s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t er } std::unique_ptr<LWIPRawImpl> LWIPRawListenImpl::accept(struct sockaddr *addr, socklen_t *addrlen) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = EBADF; return nullptr; @@ -674,6 +720,7 @@ std::unique_ptr<LWIPRawImpl> LWIPRawListenImpl::accept(struct sockaddr *addr, so } int LWIPRawListenImpl::listen(int backlog) { + LWIP_LOCK(); if (this->pcb_ == nullptr) { errno = EBADF; return -1; @@ -699,6 +746,7 @@ int LWIPRawListenImpl::listen(int backlog) { } err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { + // Called by lwip core which already holds the async_context lock on RP2040. LWIP_LOG("accept(newpcb=%p err=%d)", newpcb, err); if (err != ERR_OK || newpcb == nullptr) { // "An error code if there has been an error accepting. Only return ERR_ABRT if you have @@ -734,6 +782,7 @@ std::unique_ptr<Socket> socket(int domain, int type, int protocol) { errno = EPROTOTYPE; return nullptr; } + LWIP_LOCK(); auto *pcb = tcp_new(); if (pcb == nullptr) return nullptr; @@ -753,6 +802,7 @@ std::unique_ptr<ListenSocket> socket_listen(int domain, int type, int protocol) errno = EPROTOTYPE; return nullptr; } + LWIP_LOCK(); auto *pcb = tcp_new(); if (pcb == nullptr) return nullptr; @@ -766,6 +816,8 @@ std::unique_ptr<ListenSocket> socket_listen_loop_monitored(int domain, int type, return socket_listen(domain, type, protocol); } +#undef LWIP_LOCK + } // namespace esphome::socket #endif // USE_SOCKET_IMPL_LWIP_TCP diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index c171e0537f..5b2c11cfe2 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -95,8 +95,13 @@ class LWIPRawImpl : public LWIPRawCommon { errno = ENOSYS; return -1; } + // Intentionally unlocked — this is a polling check called every loop iteration. + // A stale read at worst delays processing by one loop tick; the actual I/O in + // read() holds the lwip lock and re-checks properly. See esphome#10681. bool ready() const { return this->rx_buf_ != nullptr || this->rx_closed_ || this->pcb_ == nullptr; } + // No lock needed — only called during setup before callbacks are registered. + // A stale pcb_ read is benign (returns ECONNRESET, which the caller handles). int setblocking(bool blocking) { if (this->pcb_ == nullptr) { errno = ECONNRESET; @@ -134,6 +139,7 @@ class LWIPRawListenImpl : public LWIPRawCommon { void init(); + // Intentionally unlocked — polling check, see LWIPRawImpl::ready() comment. bool ready() const { return this->accepted_socket_count_ > 0; } std::unique_ptr<LWIPRawImpl> accept(struct sockaddr *addr, socklen_t *addrlen); From dcbf3c8728a1a0040e0f2899a6bfc899888f0e9e Mon Sep 17 00:00:00 2001 From: Thomas Rupprecht <rupprecht.thomas@gmail.com> Date: Tue, 10 Mar 2026 23:18:35 +0100 Subject: [PATCH 1273/2030] [esp32] gpio type improvements (#14517) --- esphome/components/esp32/gpio.py | 4 ++-- esphome/components/esp32/gpio_esp32.py | 5 +++-- esphome/components/esp32/gpio_esp32_c2.py | 5 +++-- esphome/components/esp32/gpio_esp32_c3.py | 5 +++-- esphome/components/esp32/gpio_esp32_c5.py | 5 +++-- esphome/components/esp32/gpio_esp32_c6.py | 5 +++-- esphome/components/esp32/gpio_esp32_c61.py | 5 +++-- esphome/components/esp32/gpio_esp32_h2.py | 5 +++-- esphome/components/esp32/gpio_esp32_p4.py | 5 +++-- esphome/components/esp32/gpio_esp32_s2.py | 5 +++-- esphome/components/esp32/gpio_esp32_s3.py | 5 +++-- 11 files changed, 32 insertions(+), 22 deletions(-) diff --git a/esphome/components/esp32/gpio.py b/esphome/components/esp32/gpio.py index c0803f40a8..a7180cbcd7 100644 --- a/esphome/components/esp32/gpio.py +++ b/esphome/components/esp32/gpio.py @@ -88,8 +88,8 @@ def _translate_pin(value): @dataclass class ESP32ValidationFunctions: - pin_validation: Callable[[Any], Any] - usage_validation: Callable[[Any], Any] + pin_validation: Callable[[int], int] + usage_validation: Callable[[dict[str, Any]], dict[str, Any]] _esp32_validations = { diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index 973d2dc0ef..b3166cf822 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import ( @@ -22,7 +23,7 @@ _ESP32_STRAPPING_PINS = {0, 2, 5, 12, 15} _LOGGER = logging.getLogger(__name__) -def esp32_validate_gpio_pin(value): +def esp32_validate_gpio_pin(value: int) -> int: if value < 0 or value > 39: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-39)") if value in _ESP_SDIO_PINS: @@ -41,7 +42,7 @@ def esp32_validate_gpio_pin(value): return value -def esp32_validate_supports(value): +def esp32_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_c2.py b/esphome/components/esp32/gpio_esp32_c2.py index 32a24050ca..2d6e3a4a4e 100644 --- a/esphome/components/esp32/gpio_esp32_c2.py +++ b/esphome/components/esp32/gpio_esp32_c2.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER @@ -9,14 +10,14 @@ _ESP32C2_STRAPPING_PINS = {8, 9} _LOGGER = logging.getLogger(__name__) -def esp32_c2_validate_gpio_pin(value): +def esp32_c2_validate_gpio_pin(value: int) -> int: if value < 0 or value > 20: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-20)") return value -def esp32_c2_validate_supports(value): +def esp32_c2_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_c3.py b/esphome/components/esp32/gpio_esp32_c3.py index c1427cc02a..93e0b97093 100644 --- a/esphome/components/esp32/gpio_esp32_c3.py +++ b/esphome/components/esp32/gpio_esp32_c3.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER @@ -18,7 +19,7 @@ _ESP32C3_STRAPPING_PINS = {2, 8, 9} _LOGGER = logging.getLogger(__name__) -def esp32_c3_validate_gpio_pin(value): +def esp32_c3_validate_gpio_pin(value: int) -> int: if value < 0 or value > 21: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-21)") if value in _ESP32C3_SPI_PSRAM_PINS: @@ -29,7 +30,7 @@ def esp32_c3_validate_gpio_pin(value): return value -def esp32_c3_validate_supports(value): +def esp32_c3_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_c5.py b/esphome/components/esp32/gpio_esp32_c5.py index fa2ce1a689..639ed64c9e 100644 --- a/esphome/components/esp32/gpio_esp32_c5.py +++ b/esphome/components/esp32/gpio_esp32_c5.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER, CONF_SCL, CONF_SDA @@ -22,7 +23,7 @@ _ESP32C5_STRAPPING_PINS = {2, 7, 27, 28} _LOGGER = logging.getLogger(__name__) -def esp32_c5_validate_gpio_pin(value): +def esp32_c5_validate_gpio_pin(value: int) -> int: if value < 0 or value > 28: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-28)") if value in _ESP32C5_SPI_PSRAM_PINS: @@ -33,7 +34,7 @@ def esp32_c5_validate_gpio_pin(value): return value -def esp32_c5_validate_supports(value): +def esp32_c5_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py index 5d679dede2..cfd3bca833 100644 --- a/esphome/components/esp32/gpio_esp32_c6.py +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER, CONF_SCL, CONF_SDA @@ -22,7 +23,7 @@ _ESP32C6_STRAPPING_PINS = {8, 9, 15} _LOGGER = logging.getLogger(__name__) -def esp32_c6_validate_gpio_pin(value): +def esp32_c6_validate_gpio_pin(value: int) -> int: if value < 0 or value > 23: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-23)") if value in _ESP32C6_SPI_PSRAM_PINS: @@ -33,7 +34,7 @@ def esp32_c6_validate_gpio_pin(value): return value -def esp32_c6_validate_supports(value): +def esp32_c6_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_c61.py b/esphome/components/esp32/gpio_esp32_c61.py index 77be42db3e..2f3abe6a0f 100644 --- a/esphome/components/esp32/gpio_esp32_c61.py +++ b/esphome/components/esp32/gpio_esp32_c61.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER @@ -20,7 +21,7 @@ _ESP32C61_STRAPPING_PINS = {8, 9} _LOGGER = logging.getLogger(__name__) -def esp32_c61_validate_gpio_pin(value): +def esp32_c61_validate_gpio_pin(value: int) -> int: if value < 0 or value > 29: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-29)") if value in _ESP32C61_SPI_PSRAM_PINS: @@ -31,7 +32,7 @@ def esp32_c61_validate_gpio_pin(value): return value -def esp32_c61_validate_supports(value): +def esp32_c61_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_h2.py b/esphome/components/esp32/gpio_esp32_h2.py index f37297764b..5e7a6158f9 100644 --- a/esphome/components/esp32/gpio_esp32_h2.py +++ b/esphome/components/esp32/gpio_esp32_h2.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER @@ -13,7 +14,7 @@ _ESP32H2_STRAPPING_PINS = {2, 3, 8, 9, 25} _LOGGER = logging.getLogger(__name__) -def esp32_h2_validate_gpio_pin(value): +def esp32_h2_validate_gpio_pin(value: int) -> int: if value < 0 or value > 27: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-27)") if value in _ESP32H2_SPI_FLASH_PINS: @@ -33,7 +34,7 @@ def esp32_h2_validate_gpio_pin(value): return value -def esp32_h2_validate_supports(value): +def esp32_h2_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_p4.py b/esphome/components/esp32/gpio_esp32_p4.py index 2726c5932f..865db92652 100644 --- a/esphome/components/esp32/gpio_esp32_p4.py +++ b/esphome/components/esp32/gpio_esp32_p4.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER, CONF_SCL, CONF_SDA @@ -14,7 +15,7 @@ _ESP32P4_STRAPPING_PINS = {34, 35, 36, 37, 38} _LOGGER = logging.getLogger(__name__) -def esp32_p4_validate_gpio_pin(value): +def esp32_p4_validate_gpio_pin(value: int) -> int: if value < 0 or value > 54: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-54)") if value in _ESP32P4_USB_JTAG_PINS: @@ -27,7 +28,7 @@ def esp32_p4_validate_gpio_pin(value): return value -def esp32_p4_validate_supports(value): +def esp32_p4_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_s2.py b/esphome/components/esp32/gpio_esp32_s2.py index 331aeb9d94..4978f48a1c 100644 --- a/esphome/components/esp32/gpio_esp32_s2.py +++ b/esphome/components/esp32/gpio_esp32_s2.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import ( @@ -26,7 +27,7 @@ _ESP32S2_STRAPPING_PINS = {0, 45, 46} _LOGGER = logging.getLogger(__name__) -def esp32_s2_validate_gpio_pin(value): +def esp32_s2_validate_gpio_pin(value: int) -> int: if value < 0 or value > 46: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-46)") @@ -43,7 +44,7 @@ def esp32_s2_validate_gpio_pin(value): return value -def esp32_s2_validate_supports(value): +def esp32_s2_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] diff --git a/esphome/components/esp32/gpio_esp32_s3.py b/esphome/components/esp32/gpio_esp32_s3.py index aea378f499..cb0eb8178c 100644 --- a/esphome/components/esp32/gpio_esp32_s3.py +++ b/esphome/components/esp32/gpio_esp32_s3.py @@ -1,4 +1,5 @@ import logging +from typing import Any import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER @@ -27,7 +28,7 @@ _ESP_32S3_STRAPPING_PINS = {0, 3, 45, 46} _LOGGER = logging.getLogger(__name__) -def esp32_s3_validate_gpio_pin(value): +def esp32_s3_validate_gpio_pin(value: int) -> int: if value < 0 or value > 48: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-48)") @@ -49,7 +50,7 @@ def esp32_s3_validate_gpio_pin(value): return value -def esp32_s3_validate_supports(value): +def esp32_s3_validate_supports(value: dict[str, Any]) -> dict[str, Any]: num = value[CONF_NUMBER] mode = value[CONF_MODE] is_input = mode[CONF_INPUT] From b84d773becad306de294beadb0a3efa73c9a854d Mon Sep 17 00:00:00 2001 From: CFlix <38142312+CFlix@users.noreply.github.com> Date: Wed, 11 Mar 2026 01:24:46 +0100 Subject: [PATCH 1274/2030] [bme280] Change communication error message to include "no response" hint. (#14686) --- esphome/components/bme280_base/bme280_base.cpp | 2 +- esphome/components/bmp280_base/bmp280_base.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/bme280_base/bme280_base.cpp b/esphome/components/bme280_base/bme280_base.cpp index addbfe618d..f31940df10 100644 --- a/esphome/components/bme280_base/bme280_base.cpp +++ b/esphome/components/bme280_base/bme280_base.cpp @@ -7,7 +7,7 @@ #include <esphome/components/sensor/sensor.h> #include <esphome/core/component.h> -#define BME280_ERROR_WRONG_CHIP_ID "Wrong chip ID" +#define BME280_ERROR_WRONG_CHIP_ID "Wrong chip ID or no response" namespace esphome { namespace bme280_base { diff --git a/esphome/components/bmp280_base/bmp280_base.cpp b/esphome/components/bmp280_base/bmp280_base.cpp index de685e7c27..603966a2b5 100644 --- a/esphome/components/bmp280_base/bmp280_base.cpp +++ b/esphome/components/bmp280_base/bmp280_base.cpp @@ -2,7 +2,7 @@ #include "esphome/core/hal.h" #include "esphome/core/log.h" -#define BMP280_ERROR_WRONG_CHIP_ID "Wrong chip ID" +#define BMP280_ERROR_WRONG_CHIP_ID "Wrong chip ID or no response" namespace esphome { namespace bmp280_base { From 794098de99f083105440f8a36f2f070d1e6f9a04 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 16:40:45 -1000 Subject: [PATCH 1275/2030] [rp2040] Add HardFault crash handler with backtrace (#14685) --- esphome/components/logger/logger_rp2040.cpp | 2 + esphome/components/rp2040/__init__.py | 47 ++++ esphome/components/rp2040/core.cpp | 2 + esphome/components/rp2040/crash_handler.cpp | 227 ++++++++++++++++++++ esphome/components/rp2040/crash_handler.h | 17 ++ 5 files changed, 295 insertions(+) create mode 100644 esphome/components/rp2040/crash_handler.cpp create mode 100644 esphome/components/rp2040/crash_handler.h diff --git a/esphome/components/logger/logger_rp2040.cpp b/esphome/components/logger/logger_rp2040.cpp index 1f435031f6..f76b823a8f 100644 --- a/esphome/components/logger/logger_rp2040.cpp +++ b/esphome/components/logger/logger_rp2040.cpp @@ -1,5 +1,6 @@ #ifdef USE_RP2040 #include "logger.h" +#include "esphome/components/rp2040/crash_handler.h" #include "esphome/core/log.h" namespace esphome::logger { @@ -25,6 +26,7 @@ void Logger::pre_setup() { } global_logger = this; ESP_LOGI(TAG, "Log initialized"); + rp2040::crash_handler_log(); } void HOT Logger::write_msg_(const char *msg, uint16_t len) { diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 359337adfb..b15811241c 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -1,6 +1,8 @@ import logging from pathlib import Path +import re from string import ascii_letters, digits +import subprocess import esphome.codegen as cg import esphome.config_validation as cv @@ -264,3 +266,48 @@ def copy_files(): path = CORE.relative_src_path("esphome.h") content = read_file(path).rstrip("\n") write_file_if_changed(path, content + '\n#include "pio_includes.h"\n') + + +# RP2040 crash handler stacktrace decoding +# Matches output from esphome/components/rp2040/crash_handler.cpp +_CRASH_RE = re.compile(r"CRASH DETECTED ON PREVIOUS BOOT") +_CRASH_ADDR_RE = re.compile( + r"(?:PC|LR|BT\d):\s+(0x[0-9a-fA-F]{8})\s+\((?:fault location|return address|stack backtrace)\)" +) + + +def _addr2line(tool: str, elf: Path, addr: str) -> str: + try: + result = subprocess.run( + [tool, "-pfiaC", "-e", str(elf), addr], + capture_output=True, + text=True, + check=True, + ) + return result.stdout.strip() + except (OSError, subprocess.CalledProcessError): + return f"{addr} (decode failed)" + + +def process_stacktrace(config, line: str, backtrace_state: bool) -> bool: + """Decode RP2040 crash handler output using addr2line.""" + if _CRASH_RE.search(line): + _LOGGER.error("RP2040 crash detected - decoding addresses") + return True + + if backtrace_state: + if match := _CRASH_ADDR_RE.search(line): + from esphome.platformio_api import get_idedata + + idedata = get_idedata(config) + if idedata.addr2line_path: + elf = idedata.firmware_elf_path + if elf.exists(): + decoded = _addr2line(idedata.addr2line_path, elf, match.group(1)) + _LOGGER.error(" %s => %s", match.group(1), decoded) + + # Stop backtrace state after addr2line hint (last line of crash dump) + if "addr2line" in line: + return False + + return backtrace_state diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 63b154d80d..5e5a96c78b 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -1,6 +1,7 @@ #ifdef USE_RP2040 #include "core.h" +#include "crash_handler.h" #include "esphome/core/defines.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -24,6 +25,7 @@ void arch_restart() { } void arch_init() { + rp2040::crash_handler_read_and_clear(); #if USE_RP2040_WATCHDOG_TIMEOUT > 0 watchdog_enable(USE_RP2040_WATCHDOG_TIMEOUT, false); #endif diff --git a/esphome/components/rp2040/crash_handler.cpp b/esphome/components/rp2040/crash_handler.cpp new file mode 100644 index 0000000000..6ab46da444 --- /dev/null +++ b/esphome/components/rp2040/crash_handler.cpp @@ -0,0 +1,227 @@ +#ifdef USE_RP2040 + +#include "crash_handler.h" +#include "esphome/core/log.h" + +#include <cinttypes> +#include <hardware/regs/addressmap.h> +#include <hardware/structs/watchdog.h> +#include <hardware/watchdog.h> + +// Cortex-M0+ exception frame offsets (words) +// When a fault occurs, the CPU pushes: R0, R1, R2, R3, R12, LR, PC, xPSR +static constexpr uint32_t EF_LR = 5; +static constexpr uint32_t EF_PC = 6; + +static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF; + +// We only have 8 scratch registers (32 bytes) that survive watchdog reboot. +// Use them for the most important data, then scan the stack for code addresses. +// +// Scratch register layout: +// [0] = magic (CRASH_MAGIC) +// [1] = PC (program counter at fault) +// [2] = LR (link register from exception frame) +// [3] = SP (stack pointer at fault) +// [4..7] = up to 4 additional code addresses found by scanning the stack +// (return addresses from callers, giving a deeper backtrace) + +// Flash is mapped at XIP_BASE (0x10000000). We use a conservative upper bound +// to keep false positives low during stack scanning. Wider ranges would match +// more stale data on the stack that happens to look like code addresses. +#if defined(PICO_RP2350) +static constexpr uint32_t FLASH_SCAN_END = XIP_BASE + 0x400000; // 4MB — RP2350 typical max +#else +static constexpr uint32_t FLASH_SCAN_END = XIP_BASE + 0x200000; // 2MB — RP2040 typical max +#endif + +static inline bool is_code_addr(uint32_t val) { + uint32_t cleared = val & ~1u; // Clear Thumb bit + return cleared >= XIP_BASE && cleared < FLASH_SCAN_END; +} + +static constexpr size_t MAX_BACKTRACE = 4; + +namespace esphome::rp2040 { + +static const char *const TAG = "rp2040.crash"; + +// Placed in .noinit so BSS zero-init cannot race with crash_handler_read_and_clear(). +// The valid field is explicitly cleared in crash_handler_read_and_clear() instead. +static struct { + bool valid; + uint32_t pc; + uint32_t lr; + uint32_t sp; + uint32_t backtrace[MAX_BACKTRACE]; + uint8_t backtrace_count; +} __attribute__((section(".noinit"))) s_crash_data; + +void crash_handler_read_and_clear() { + s_crash_data.valid = false; + if (watchdog_hw->scratch[0] == CRASH_MAGIC) { + s_crash_data.valid = true; + s_crash_data.pc = watchdog_hw->scratch[1]; + s_crash_data.lr = watchdog_hw->scratch[2]; + s_crash_data.sp = watchdog_hw->scratch[3]; + s_crash_data.backtrace_count = 0; + for (size_t i = 0; i < MAX_BACKTRACE; i++) { + uint32_t addr = watchdog_hw->scratch[4 + i]; + if (addr == 0) + break; + s_crash_data.backtrace[i] = addr; + s_crash_data.backtrace_count++; + } + } + // Clear scratch registers regardless + for (int i = 0; i < 8; i++) { + watchdog_hw->scratch[i] = 0; + } +} + +// Intentionally uses separate ESP_LOGE calls per line instead of combining into +// one multi-line log message. This ensures each address appears as its own line +// on the serial console (miniterm), making it possible to see partial output if +// the device crashes again during boot, and allowing the CLI's process_stacktrace +// to match and decode each address individually. +void crash_handler_log() { + if (!s_crash_data.valid) + return; + + ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***"); + ESP_LOGE(TAG, " PC: 0x%08" PRIX32 " (fault location)", s_crash_data.pc); + ESP_LOGE(TAG, " LR: 0x%08" PRIX32 " (return address)", s_crash_data.lr); + ESP_LOGE(TAG, " SP: 0x%08" PRIX32, s_crash_data.sp); + for (uint8_t i = 0; i < s_crash_data.backtrace_count; i++) { + ESP_LOGE(TAG, " BT%d: 0x%08" PRIX32 " (stack backtrace)", i, s_crash_data.backtrace[i]); + } + // Build addr2line hint with all captured addresses for easy copy-paste + char hint[160]; + int pos = snprintf(hint, sizeof(hint), "Use: addr2line -pfiaC -e firmware.elf 0x%08" PRIX32 " 0x%08" PRIX32, + s_crash_data.pc, s_crash_data.lr); + for (uint8_t i = 0; i < s_crash_data.backtrace_count && pos < (int) sizeof(hint) - 12; i++) { + pos += snprintf(hint + pos, sizeof(hint) - pos, " 0x%08" PRIX32, s_crash_data.backtrace[i]); + } + ESP_LOGE(TAG, "%s", hint); +} + +} // namespace esphome::rp2040 + +// --- HardFault handler --- +// Overrides the weak isr_hardfault from arduino-pico's crt0.S. +// On Cortex-M0+, the CPU pushes {R0,R1,R2,R3,R12,LR,PC,xPSR} onto the +// active stack (MSP or PSP). We determine which stack was active, +// extract key registers, store them in watchdog scratch registers +// (which survive watchdog reboot), then trigger a reboot. + +// Check if a pointer falls within SRAM (valid for stack access). +// SRAM_BASE and SRAM_END are chip-specific SDK defines: +// RP2040: 0x20000000 - 0x20042000 (264KB) +// RP2350: 0x20000000 - 0x20082000 (520KB) +static inline bool is_valid_sram_ptr(const uint32_t *ptr) { + auto addr = reinterpret_cast<uintptr_t>(ptr); + // Exception frame is 8 words (32 bytes), so frame+7 must also be in SRAM. + // Check alignment (must be word-aligned) and that the full frame fits. + return (addr % 4 == 0) && addr >= SRAM_BASE && (addr + 32) <= SRAM_END; +} + +// C handler called from the asm wrapper with the exception frame pointer. +static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame, uint32_t /*exc_return*/) { + // watchdog_reboot() overwrites scratch[4]-[7], so we must call it first + // then write ALL our data after. The 10ms timeout gives us plenty of time. + watchdog_reboot(0, 0, 10); + + // Validate frame pointer before dereferencing. If the HardFault was caused + // by a stacking error or corrupted SP, frame may be invalid. Write a minimal + // crash marker so we at least know a crash occurred. + if (!is_valid_sram_ptr(frame)) { + watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[1] = 0; // PC unknown + watchdog_hw->scratch[2] = 0; // LR unknown + watchdog_hw->scratch[3] = reinterpret_cast<uintptr_t>(frame); // Record the bad SP for diagnosis + for (uint32_t i = 0; i < MAX_BACKTRACE; i++) { + watchdog_hw->scratch[4 + i] = 0; + } + while (true) { + __asm volatile("nop"); + } + } + + // Pre-fault SP: the exception frame is 8 words pushed onto the stack, + // so the SP before the fault was frame + 8 words. If xPSR bit 9 is set, + // the hardware pushed an extra alignment word to maintain 8-byte stack + // alignment (ARMv6-M/ARMv7-M spec), so add 1 more word. + static constexpr uint32_t EF_XPSR = 7; + uint32_t extra_align = (frame[EF_XPSR] & (1u << 9)) ? 1 : 0; + uint32_t *post_frame = frame + 8 + extra_align; + uint32_t pre_fault_sp = reinterpret_cast<uintptr_t>(post_frame); + + // Write key registers + watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[1] = frame[EF_PC]; + watchdog_hw->scratch[2] = frame[EF_LR]; + watchdog_hw->scratch[3] = pre_fault_sp; + + // Scan stack for code addresses to build a deeper backtrace. + // The exception frame is 8 words (32 bytes) at 'frame', plus an optional + // alignment word. Walk up to 64 words looking for return addresses. + uint32_t *scan_start = post_frame; + // SRAM_END is chip-specific: 0x20042000 (RP2040) or 0x20082000 (RP2350) + uint32_t *stack_top = reinterpret_cast<uint32_t *>(SRAM_END); + // Scan up to 64 words (256 bytes) — covers typical nested call frames + // without scanning too much stale stack data that could produce false positives. + uint32_t bt_count = 0; + + for (uint32_t *p = scan_start; p < stack_top && p < scan_start + 64 && bt_count < MAX_BACKTRACE; p++) { + uint32_t val = *p; + // Check if this looks like a code address in flash + // Skip if it's the same as PC or LR we already saved + if (is_code_addr(val) && val != frame[EF_PC] && val != frame[EF_LR]) { + watchdog_hw->scratch[4 + bt_count] = val; + bt_count++; + } + } + // Zero remaining slots + for (uint32_t i = bt_count; i < MAX_BACKTRACE; i++) { + watchdog_hw->scratch[4 + i] = 0; + } + + while (true) { + __asm volatile("nop"); + } +} + +// Naked asm wrapper - Cortex-M0+ compatible (no ITE/conditional execution). +// Determines active stack pointer and branches to C handler. +// Uses literal pool (.word) for addresses since M0+ has limited immediate encoding. +// +// Based on the standard Cortex-M0+ HardFault handler pattern described in: +// - ARM Application Note AN209: "Using Cortex-M3/M4/M7 Fault Exceptions" +// (adapted for M0+ which lacks conditional execution instructions) +// - Memfault: "How to debug a HardFault on an ARM Cortex-M MCU" +// https://interrupt.memfault.com/blog/cortex-m-hardfault-debug +// - Raspberry Pi Forums: "Cortex-M0+ Hard Fault handler porting" +// https://www.eevblog.com/forum/microcontrollers/cortex-m0-hard-fault-handler-porting/ +// +// The key M0+ adaptation: replaces ITE/MRSEQ/MRSNE (Cortex-M3+) with +// MOVS+TST+BEQ branch sequence, and uses a literal pool for the C handler address. +extern "C" void __attribute__((naked, used)) isr_hardfault() { + __asm volatile("movs r0, #4 \n" // Prepare bit 2 mask + "mov r1, lr \n" // r1 = EXC_RETURN + "tst r1, r0 \n" // Test bit 2 + "beq 1f \n" // If 0, was using MSP + "mrs r0, psp \n" // Bit 2 set = PSP was active + "b 2f \n" + "1: \n" + "mrs r0, msp \n" // Bit 2 clear = MSP was active + "2: \n" + // r0 = exception frame pointer, r1 = EXC_RETURN (still in r1) + "ldr r2, 3f \n" // Load C handler address from literal pool + "bx r2 \n" // Branch to handler (r0=frame, r1=exc_return) + ".align 2 \n" + "3: .word %c0 \n" // Literal pool: address of C handler + : + : "i"(hard_fault_handler_c)); +} + +#endif // USE_RP2040 diff --git a/esphome/components/rp2040/crash_handler.h b/esphome/components/rp2040/crash_handler.h new file mode 100644 index 0000000000..f10db47c23 --- /dev/null +++ b/esphome/components/rp2040/crash_handler.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef USE_RP2040 + +#include <cstdint> + +namespace esphome::rp2040 { + +/// Read crash data from watchdog scratch registers and clear them. +void crash_handler_read_and_clear(); + +/// Log crash data if a crash was detected on previous boot. +void crash_handler_log(); + +} // namespace esphome::rp2040 + +#endif // USE_RP2040 From 6561c9bc95500915584afbe13a8cf3da6f3da051 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Tue, 10 Mar 2026 22:32:29 -0500 Subject: [PATCH 1276/2030] [core] Fix waiting for port indefinitely (#14688) --- esphome/__main__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 3f0da85a69..58b995e8df 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -919,9 +919,11 @@ def _wait_for_serial_port( """ def _port_found() -> bool: - ports = get_serial_ports() if port is not None: - return any(p.path == port for p in ports) + if os.name == "posix": + return os.path.exists(port) + return any(p.path == port for p in get_serial_ports()) + ports = get_serial_ports() if known_ports is not None: return any(p.path not in known_ports for p in ports) return bool(ports) From d0f37ae69460ac90e2f95a39216ec09090373df6 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Tue, 10 Mar 2026 23:31:27 -0500 Subject: [PATCH 1277/2030] [logger] Fix UART selection not applied before `pre_setup()` (#14690) --- esphome/components/logger/__init__.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index e370f4215d..675f9a2ca4 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -337,6 +337,16 @@ async def to_code(config): ) if CORE.is_esp32: cg.add(log.create_pthread_key()) + # set_uart_selection() must be called before pre_setup() because + # pre_setup() switches on uart_ to decide which hardware to initialize + # (e.g. UART0 vs USB_SERIAL_JTAG). Without this, uart_ is still the + # default UART_SELECTION_UART0 and the wrong hardware gets initialized. + if CONF_HARDWARE_UART in config: + cg.add( + log.set_uart_selection( + HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]] + ) + ) # pre_setup() must be called before init_log_buffer() because # init_log_buffer() calls disable_loop() which may log at VV level, # and global_logger must be set before any logging occurs. @@ -354,12 +364,6 @@ async def to_code(config): cg.add(log.init_log_buffer(64)) # Fixed 64 slots for host cg.add(log.set_log_level(initial_level)) - if CONF_HARDWARE_UART in config: - cg.add( - log.set_uart_selection( - HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]] - ) - ) # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] From 4df3d3554e5767edf6469977972409d3b882cd2e Mon Sep 17 00:00:00 2001 From: Adam DeMuri <adam.demuri@gmail.com> Date: Tue, 10 Mar 2026 23:44:05 -0600 Subject: [PATCH 1278/2030] Enable the address and behavior sanitizers for C++ component unit tests (#13490) --- script/cpp_unit_test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index c917458472..c6cfd8270f 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -79,6 +79,10 @@ def create_test_config(config_name: str, includes: list[str]) -> dict: "-Og", # optimize for debug "-DUSE_TIME_TIMEZONE", # enable timezone code paths for testing "-DESPHOME_DEBUG", # enable debug assertions + # Enable the address and undefined behavior sanitizers + "-fsanitize=address", + "-fsanitize=undefined", + "-fno-omit-frame-pointer", ], "debug_build_flags": [ # only for debug builds "-g3", # max debug info From e8e700a683f2ad210892393e6f67260855e493d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 10 Mar 2026 20:51:54 -1000 Subject: [PATCH 1279/2030] [socket] Fix RP2040 heap corruption from malloc in lwip accept callback (#14687) --- .../components/socket/lwip_raw_tcp_impl.cpp | 142 ++++++++++++++---- esphome/components/socket/lwip_raw_tcp_impl.h | 41 ++--- 2 files changed, 138 insertions(+), 45 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index d7fa6a2694..fd1b8a9554 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -425,20 +425,24 @@ LWIPRawImpl::~LWIPRawImpl() { // Base class destructor handles pcb_ cleanup via tcp_abort } -void LWIPRawImpl::init() { +void LWIPRawImpl::init(struct pbuf *initial_rx, bool initial_rx_closed) { LWIP_LOCK(); LWIP_LOG("init(%p)", this->pcb_); tcp_arg(this->pcb_, this); tcp_recv(this->pcb_, LWIPRawImpl::s_recv_fn); tcp_err(this->pcb_, LWIPRawImpl::s_err_fn); + if (initial_rx != nullptr) { + this->rx_buf_ = initial_rx; + this->rx_buf_offset_ = 0; + } + this->rx_closed_ = initial_rx_closed; } void LWIPRawImpl::s_err_fn(void *arg, err_t err) { - // Called by lwip core which already holds the async_context lock on RP2040. - // No LWIP_LOCK() needed — acquiring it would be redundant (recursive mutex). + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). + // No LWIP_LOCK() needed — lwip core already holds the async_context lock. // - // "If a connection is aborted because of an error, the application is alerted of this event by - // the err callback." // pcb is already freed when this callback is called // ERR_RST: connection was reset by remote host // ERR_ABRT: aborted through tcp_abort or TCP timer @@ -453,11 +457,15 @@ err_t LWIPRawImpl::s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, er } err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { - // Called by lwip core which already holds the async_context lock on RP2040. + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). LWIP_LOG("recv(pb=%p err=%d)", pb, err); if (err != 0) { // "An error code if there has been an error receiving Only return ERR_ABRT if you have // called tcp_abort from within the callback function!" + if (pb != nullptr) { + pbuf_free(pb); + } this->rx_closed_ = true; return ERR_OK; } @@ -664,6 +672,22 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { LWIPRawListenImpl::~LWIPRawListenImpl() { LWIP_LOCK(); + // Abort any queued PCBs that were never accepted by the main loop. + // Clear the error callback first — tcp_abort triggers it, and we don't + // want s_queued_err_fn writing to slots during destruction. + for (uint8_t i = 0; i < this->accepted_socket_count_; i++) { + auto &entry = this->accepted_pcbs_[i]; + if (entry.pcb != nullptr) { + tcp_err(entry.pcb, nullptr); + tcp_abort(entry.pcb); + entry.pcb = nullptr; + } + if (entry.rx_buf != nullptr) { + pbuf_free(entry.rx_buf); + entry.rx_buf = nullptr; + } + } + this->accepted_socket_count_ = 0; // Listen PCBs must use tcp_close(), not tcp_abort(). // tcp_abandon() asserts pcb->state != LISTEN and would access // fields that don't exist in the smaller tcp_pcb_listen struct. @@ -683,12 +707,49 @@ void LWIPRawListenImpl::init() { } void LWIPRawListenImpl::s_err_fn(void *arg, err_t err) { - // Called by lwip core which already holds the async_context lock on RP2040. + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). auto *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); ESP_LOGVV(TAG, "socket %p: err(err=%d)", arg_this, err); arg_this->pcb_ = nullptr; } +void LWIPRawListenImpl::s_queued_err_fn(void *arg, err_t err) { + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). + // Called when a queued (not yet accepted) PCB errors — e.g., remote sent RST. + // The PCB is already freed by lwip. Null our pointer so accept() skips it. + (void) err; + auto *entry = reinterpret_cast<QueuedPcb *>(arg); + entry->pcb = nullptr; + // Don't free rx_buf here — accept() will clean it up when it sees pcb==nullptr +} + +err_t LWIPRawListenImpl::s_queued_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err) { + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). + // Temporary recv callback for PCBs queued between accept_fn_ and accept(). + // Without this, lwip's default tcp_recv_null handler would ACK and drop the data, + // causing the API handshake to silently fail (client sends Hello, server never sees it). + (void) pcb; + auto *entry = reinterpret_cast<QueuedPcb *>(arg); + if (pb == nullptr || err != ERR_OK) { + // Remote closed or error + if (pb != nullptr) { + pbuf_free(pb); + } + entry->rx_closed = true; + return ERR_OK; + } + // Buffer the data — tcp_recved() is deferred to read() after accept() creates the socket. + if (entry->rx_buf == nullptr) { + entry->rx_buf = pb; + } else { + pbuf_cat(entry->rx_buf, pb); + } + return ERR_OK; +} + err_t LWIPRawListenImpl::s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t err) { auto *arg_this = reinterpret_cast<LWIPRawListenImpl *>(arg); return arg_this->accept_fn_(newpcb, err); @@ -700,23 +761,40 @@ std::unique_ptr<LWIPRawImpl> LWIPRawListenImpl::accept(struct sockaddr *addr, so errno = EBADF; return nullptr; } - if (this->accepted_socket_count_ == 0) { - errno = EWOULDBLOCK; - return nullptr; + // Dequeue front entry, skipping any null entries (PCBs freed by lwip while queued). + // The error callback nulled their pcb pointers; clean up buffered data and discard. + while (this->accepted_socket_count_ > 0) { + QueuedPcb entry = this->accepted_pcbs_[0]; + // Shift remaining entries forward, updating tcp_arg pointers as we go. + // Safe because we hold LWIP_LOCK, so err/recv callbacks can't fire during the update. + for (uint8_t i = 1; i < this->accepted_socket_count_; i++) { + this->accepted_pcbs_[i - 1] = this->accepted_pcbs_[i]; + if (this->accepted_pcbs_[i - 1].pcb != nullptr) { + tcp_arg(this->accepted_pcbs_[i - 1].pcb, &this->accepted_pcbs_[i - 1]); + } + } + this->accepted_pcbs_[this->accepted_socket_count_ - 1] = {}; + this->accepted_socket_count_--; + if (entry.pcb == nullptr) { + // PCB was freed by lwip (RST/timeout) while queued — discard and try next + if (entry.rx_buf != nullptr) { + pbuf_free(entry.rx_buf); + } + continue; + } + LWIP_LOG("Connection accepted by application, queue size: %d", this->accepted_socket_count_); + // Create socket wrapper on the main loop (not in accept callback) to avoid + // heap allocation in IRQ context on RP2040. Transfer any data received while queued. + auto sock = make_unique<LWIPRawImpl>(this->family_, entry.pcb); + sock->init(entry.rx_buf, entry.rx_closed); + if (addr != nullptr) { + sock->getpeername(addr, addrlen); + } + LWIP_LOG("accept(%p)", sock.get()); + return sock; } - // Take from front for FIFO ordering - std::unique_ptr<LWIPRawImpl> sock = std::move(this->accepted_sockets_[0]); - // Shift remaining sockets forward - for (uint8_t i = 1; i < this->accepted_socket_count_; i++) { - this->accepted_sockets_[i - 1] = std::move(this->accepted_sockets_[i]); - } - this->accepted_socket_count_--; - LWIP_LOG("Connection accepted by application, queue size: %d", this->accepted_socket_count_); - if (addr != nullptr) { - sock->getpeername(addr, addrlen); - } - LWIP_LOG("accept(%p)", sock.get()); - return sock; + errno = EWOULDBLOCK; + return nullptr; } int LWIPRawListenImpl::listen(int backlog) { @@ -746,7 +824,8 @@ int LWIPRawListenImpl::listen(int backlog) { } err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { - // Called by lwip core which already holds the async_context lock on RP2040. + // LWIP CALLBACK — runs from IRQ context on RP2040 (low-priority user IRQ). + // No heap allocation allowed — malloc is not IRQ-safe (see #14687). LWIP_LOG("accept(newpcb=%p err=%d)", newpcb, err); if (err != ERR_OK || newpcb == nullptr) { // "An error code if there has been an error accepting. Only return ERR_ABRT if you have @@ -763,9 +842,18 @@ err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { // Must return ERR_ABRT since we called tcp_abort() return ERR_ABRT; } - auto sock = make_unique<LWIPRawImpl>(this->family_, newpcb); - sock->init(); - this->accepted_sockets_[this->accepted_socket_count_++] = std::move(sock); + // Store the raw PCB — LWIPRawImpl creation is deferred to the main-loop accept(). + // This avoids heap allocation in this callback, which is unsafe from IRQ context on RP2040. + uint8_t idx = this->accepted_socket_count_++; + this->accepted_pcbs_[idx] = {newpcb, nullptr, false}; + // Register temporary callbacks so that while the PCB is queued: + // - err: nulls our pointer if the connection errors (RST, timeout) + // - recv: buffers any data that arrives before accept() creates the LWIPRawImpl + // (without this, lwip's default tcp_recv_null would ACK and drop the data) + // tcp_arg points to our queue entry; accept() updates these pointers after shifting. + tcp_arg(newpcb, &this->accepted_pcbs_[idx]); + tcp_err(newpcb, LWIPRawListenImpl::s_queued_err_fn); + tcp_recv(newpcb, LWIPRawListenImpl::s_queued_recv_fn); LWIP_LOG("Accepted connection, queue size: %d", this->accepted_socket_count_); #if (defined(USE_ESP8266) || defined(USE_RP2040)) // Wake the main loop immediately so it can accept the new connection. diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index 5b2c11cfe2..95931afcf3 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -66,7 +66,7 @@ class LWIPRawImpl : public LWIPRawCommon { using LWIPRawCommon::LWIPRawCommon; ~LWIPRawImpl(); - void init(); + void init(struct pbuf *initial_rx = nullptr, bool initial_rx_closed = false); // Non-listening sockets return error std::unique_ptr<LWIPRawImpl> accept(struct sockaddr *, socklen_t *) { @@ -182,23 +182,28 @@ class LWIPRawListenImpl : public LWIPRawCommon { err_t accept_fn_(struct tcp_pcb *newpcb, err_t err); static err_t s_accept_fn(void *arg, struct tcp_pcb *newpcb, err_t err); - // Accept queue - holds incoming connections briefly until the event loop calls accept() - // This is NOT a connection pool - just a temporary queue between LWIP callbacks and the main loop - // 3 slots is plenty since connections are pulled out quickly by the event loop - // - // Memory analysis: std::array<3> vs original std::queue implementation: - // - std::queue uses std::deque internally which on 32-bit systems needs: - // 24 bytes (deque object) + 32+ bytes (map array) + heap allocations - // Total: ~56+ bytes minimum, plus heap fragmentation - // - std::array<3>: 12 bytes fixed (3 pointers × 4 bytes) - // Saves ~44+ bytes RAM per listening socket + avoids ALL heap allocations - // Used on ESP8266 and RP2040 (platforms using LWIP_TCP implementation) - // - // By using a separate listening socket class, regular connected sockets save - // 16 bytes (12 bytes array + 1 byte count + 3 bytes padding) of memory overhead on 32-bit systems - static constexpr size_t MAX_ACCEPTED_SOCKETS = 3; - std::array<std::unique_ptr<LWIPRawImpl>, MAX_ACCEPTED_SOCKETS> accepted_sockets_; - uint8_t accepted_socket_count_ = 0; // Number of sockets currently in queue + // Temporary callbacks for queued PCBs (between accept_fn_ and accept()) + static void s_queued_err_fn(void *arg, err_t err); + static err_t s_queued_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err); + + // Accept queue entry — stores a raw tcp_pcb and any data received while queued. + // lwip's default tcp_recv_null handler drops data and ACKs it, so we must register + // a temporary recv callback to buffer any data that arrives between accept_fn_ + // (which stores the PCB) and accept() (which creates the LWIPRawImpl). + struct QueuedPcb { + struct tcp_pcb *pcb{nullptr}; + struct pbuf *rx_buf{nullptr}; // Data received while queued (before accept() picks it up) + bool rx_closed{false}; // Remote sent FIN while queued + }; + + // Accept queue — stores raw tcp_pcb entries instead of heap-allocated LWIPRawImpl objects. + // LWIPRawImpl creation is deferred to the main-loop accept() call. This avoids: + // - Heap allocation in the accept callback (unsafe from IRQ context on RP2040) + // - Dangling LWIPRawImpl if the connection errors before accept() picks it up + // 2 slots is plenty since the main loop drains the queue every iteration. + static constexpr size_t MAX_ACCEPTED_SOCKETS = 2; + std::array<QueuedPcb, MAX_ACCEPTED_SOCKETS> accepted_pcbs_{}; + uint8_t accepted_socket_count_ = 0; // Number of entries currently in queue }; } // namespace esphome::socket From 236f6b1935aec81d6350213e3049c6b0f4fb0794 Mon Sep 17 00:00:00 2001 From: Robert Resch <robert@resch.dev> Date: Wed, 11 Mar 2026 07:52:43 +0100 Subject: [PATCH 1280/2030] [micronova] Add command queue (#12268) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: edenhaus <edenhaus@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/micronova/__init__.py | 54 +++- .../components/micronova/button/__init__.py | 2 + .../micronova/button/micronova_button.cpp | 10 +- .../micronova/button/micronova_button.h | 11 +- esphome/components/micronova/micronova.cpp | 256 +++++++++++------- esphome/components/micronova/micronova.h | 93 ++++--- .../components/micronova/number/__init__.py | 7 +- .../micronova/number/micronova_number.cpp | 10 +- .../micronova/number/micronova_number.h | 9 +- .../micronova/sensor/micronova_sensor.cpp | 7 + .../micronova/sensor/micronova_sensor.h | 8 +- .../components/micronova/switch/__init__.py | 2 + .../micronova/switch/micronova_switch.cpp | 21 +- .../micronova/switch/micronova_switch.h | 8 +- .../text_sensor/micronova_text_sensor.cpp | 7 + .../text_sensor/micronova_text_sensor.h | 8 +- esphome/core/defines.h | 2 + esphome/core/helpers.h | 75 +++++ 18 files changed, 399 insertions(+), 191 deletions(-) diff --git a/esphome/components/micronova/__init__.py b/esphome/components/micronova/__init__.py index d6ef93cf30..b462352229 100644 --- a/esphome/components/micronova/__init__.py +++ b/esphome/components/micronova/__init__.py @@ -1,14 +1,34 @@ +from dataclasses import dataclass + from esphome import pins import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv from esphome.const import CONF_ID +from esphome.core import CORE, coroutine_with_priority +from esphome.coroutine import CoroPriority CODEOWNERS = ["@jorre05", "@edenhaus"] DEPENDENCIES = ["uart"] DOMAIN = "micronova" + + +@dataclass +class MicronovaData: + """Track micronova component state during code generation.""" + + listener_count: int = 0 + has_writer: bool = False + + +def _get_data() -> MicronovaData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = MicronovaData() + return CORE.data[DOMAIN] + + CONF_MICRONOVA_ID = f"{DOMAIN}_id" CONF_ENABLE_RX_PIN = "enable_rx_pin" CONF_MEMORY_LOCATION = "memory_location" @@ -66,16 +86,42 @@ def MICRONOVA_ADDRESS_SCHEMA( return schema +def register_micronova_writer() -> None: + """Register a component that can write to the stove (button, switch, number).""" + _get_data().has_writer = True + + async def to_code_micronova_listener(mv, var, config): + _get_data().listener_count += 1 await cg.register_component(var, config) - cg.add(mv.register_micronova_listener(var)) cg.add(var.set_memory_location(config[CONF_MEMORY_LOCATION])) cg.add(var.set_memory_address(config[CONF_MEMORY_ADDRESS])) + # Register listener as last step as we need all properties set before registering + cg.add(mv.register_micronova_listener(var)) async def to_code(config): - var = cg.new_Pvariable(config[CONF_ID]) + enable_rx_pin = await cg.gpio_pin_expression(config[CONF_ENABLE_RX_PIN]) + var = cg.new_Pvariable(config[CONF_ID], enable_rx_pin) await cg.register_component(var, config) await uart.register_uart_device(var, config) - enable_rx_pin = await cg.gpio_pin_expression(config[CONF_ENABLE_RX_PIN]) - cg.add(var.set_enable_rx_pin(enable_rx_pin)) + CORE.add_job(_final_step) + + +@coroutine_with_priority(CoroPriority.FINAL) +async def _final_step() -> None: + """Add defines for listener and writer counts after all are registered.""" + data = _get_data() + if data.listener_count == 0 and not data.has_writer: + raise cv.Invalid( + "No micronova entities configured. Add at least one micronova entity." + ) + if data.listener_count > 255: + raise cv.Invalid( + f"Too many micronova reading entities ({data.listener_count}). Maximum is 255." + ) + if data.listener_count > 0: + cg.add_define("MICRONOVA_LISTENER_COUNT", data.listener_count) + + if data.has_writer: + cg.add_define("USE_MICRONOVA_WRITER") diff --git a/esphome/components/micronova/button/__init__.py b/esphome/components/micronova/button/__init__.py index 6adf8d96fe..1ef359ea6c 100644 --- a/esphome/components/micronova/button/__init__.py +++ b/esphome/components/micronova/button/__init__.py @@ -9,6 +9,7 @@ from .. import ( MICRONOVA_ADDRESS_SCHEMA, MicroNova, micronova_ns, + register_micronova_writer, ) MicroNovaButton = micronova_ns.class_("MicroNovaButton", button.Button, cg.Component) @@ -36,6 +37,7 @@ async def to_code(config): mv = await cg.get_variable(config[CONF_MICRONOVA_ID]) if custom_button_config := config.get(CONF_CUSTOM_BUTTON): + register_micronova_writer() bt = await button.new_button(custom_button_config, mv) cg.add(bt.set_memory_location(custom_button_config[CONF_MEMORY_LOCATION])) cg.add(bt.set_memory_address(custom_button_config[CONF_MEMORY_ADDRESS])) diff --git a/esphome/components/micronova/button/micronova_button.cpp b/esphome/components/micronova/button/micronova_button.cpp index 3f49d4b5b3..13c0e1f117 100644 --- a/esphome/components/micronova/button/micronova_button.cpp +++ b/esphome/components/micronova/button/micronova_button.cpp @@ -2,9 +2,15 @@ namespace esphome::micronova { +static const char *const TAG = "micronova.button"; + +void MicroNovaButton::dump_config() { + LOG_BUTTON("", "Micronova button", this); + this->dump_base_config(); +} + void MicroNovaButton::press_action() { - this->micronova_->write_address(this->memory_location_, this->memory_address_, this->memory_data_); - this->micronova_->request_update_listeners(); + this->micronova_->queue_write_command(this->memory_location_, this->memory_address_, this->memory_data_); } } // namespace esphome::micronova diff --git a/esphome/components/micronova/button/micronova_button.h b/esphome/components/micronova/button/micronova_button.h index 951ae8bba3..0258dbb53c 100644 --- a/esphome/components/micronova/button/micronova_button.h +++ b/esphome/components/micronova/button/micronova_button.h @@ -6,19 +6,18 @@ namespace esphome::micronova { -class MicroNovaButton : public Component, public button::Button, public MicroNovaButtonListener { +class MicroNovaButton : public Component, public button::Button, public MicroNovaBaseListener { public: - MicroNovaButton(MicroNova *m) : MicroNovaButtonListener(m) {} - void dump_config() override { - LOG_BUTTON("", "Micronova button", this); - this->dump_base_config(); - } + MicroNovaButton(MicroNova *m) : MicroNovaBaseListener(m) {} + void dump_config() override; void set_memory_data(uint8_t f) { this->memory_data_ = f; } uint8_t get_memory_data() { return this->memory_data_; } protected: void press_action() override; + + uint8_t memory_data_ = 0; }; } // namespace esphome::micronova diff --git a/esphome/components/micronova/micronova.cpp b/esphome/components/micronova/micronova.cpp index 22daef4fe6..c2e3ef8640 100644 --- a/esphome/components/micronova/micronova.cpp +++ b/esphome/components/micronova/micronova.cpp @@ -3,8 +3,12 @@ namespace esphome::micronova { -static const int STOVE_REPLY_DELAY = 60; -static const uint8_t WRITE_BIT = 1 << 7; // 0x80 +static const char *const TAG = "micronova"; +static constexpr uint8_t STOVE_REPLY_SIZE = 2; +static constexpr uint32_t STOVE_REPLY_TIMEOUT = 200; // ms +static constexpr uint8_t WRITE_BIT = 1 << 7; // 0x80 + +bool MicroNovaCommand::is_write() const { return this->memory_location & WRITE_BIT; } void MicroNovaBaseListener::dump_base_config() { ESP_LOGCONFIG(TAG, @@ -18,139 +22,193 @@ void MicroNovaListener::dump_base_config() { LOG_UPDATE_INTERVAL(this); } +void MicroNovaListener::request_value_from_stove_() { + this->micronova_->queue_read_request(this->memory_location_, this->memory_address_); +} + void MicroNova::setup() { - if (this->enable_rx_pin_ != nullptr) { - this->enable_rx_pin_->setup(); - this->enable_rx_pin_->pin_mode(gpio::FLAG_OUTPUT); - this->enable_rx_pin_->digital_write(false); - } - this->current_transmission_.request_transmission_time = millis(); - this->current_transmission_.memory_location = 0; - this->current_transmission_.memory_address = 0; - this->current_transmission_.reply_pending = false; - this->current_transmission_.initiating_listener = nullptr; + this->enable_rx_pin_->setup(); + this->enable_rx_pin_->pin_mode(gpio::FLAG_OUTPUT); + this->enable_rx_pin_->digital_write(false); } void MicroNova::dump_config() { ESP_LOGCONFIG(TAG, "MicroNova:"); - if (this->enable_rx_pin_ != nullptr) { - LOG_PIN(" Enable RX Pin: ", this->enable_rx_pin_); - } + LOG_PIN(" Enable RX Pin: ", this->enable_rx_pin_); } -void MicroNova::request_update_listeners() { - ESP_LOGD(TAG, "Schedule listener update"); - for (auto &mv_listener : this->micronova_listeners_) { - mv_listener->set_needs_update(true); +#ifdef MICRONOVA_LISTENER_COUNT +void MicroNova::register_micronova_listener(MicroNovaListener *listener) { + this->listeners_.push_back(listener); + // Request initial value + this->queue_read_request(listener->get_memory_location(), listener->get_memory_address()); +} + +void MicroNova::request_update_listeners_() { + ESP_LOGD(TAG, "Requesting update from all listeners"); + for (auto *listener : this->listeners_) { + this->queue_read_request(listener->get_memory_location(), listener->get_memory_address()); } } +#endif void MicroNova::loop() { - // Only read one sensor that needs update per loop - // If STOVE_REPLY_DELAY time has passed since last loop() - // check for a reply from the stove - if ((this->current_transmission_.reply_pending) && - (millis() - this->current_transmission_.request_transmission_time > STOVE_REPLY_DELAY)) { - int stove_reply_value = this->read_stove_reply(); - if (this->current_transmission_.initiating_listener != nullptr) { - this->current_transmission_.initiating_listener->process_value_from_stove(stove_reply_value); - this->current_transmission_.initiating_listener = nullptr; - } - this->current_transmission_.reply_pending = false; - return; - } else if (!this->current_transmission_.reply_pending) { - for (auto &mv_listener : this->micronova_listeners_) { - if (mv_listener->get_needs_update()) { - mv_listener->set_needs_update(false); - this->current_transmission_.initiating_listener = mv_listener; - mv_listener->request_value_from_stove(); - return; + // Check if we're processing a command and waiting for reply + if (this->reply_pending_) { + // Check if all reply bytes have arrived + if (this->available() >= STOVE_REPLY_SIZE) { +#ifdef MICRONOVA_LISTENER_COUNT + int stove_reply_value = this->read_stove_reply_(); + if (this->current_command_.is_write()) { + if (stove_reply_value == -1) { + ESP_LOGW(TAG, "Write to [0x%02X:0x%02X] may have failed (checksum mismatch in reply)", + this->current_command_.memory_location & ~WRITE_BIT, this->current_command_.memory_address); + } + } else { + // For READ commands, notify all listeners registered for this address + uint8_t loc = this->current_command_.memory_location; + uint8_t addr = this->current_command_.memory_address; + for (auto *listener : this->listeners_) { + if (listener->get_memory_location() == loc && listener->get_memory_address() == addr) { + listener->process_value_from_stove(stove_reply_value); + } + } } +#else + this->read_stove_reply_(); +#endif + this->reply_pending_ = false; + } else if (millis() - this->transmission_time_ > STOVE_REPLY_TIMEOUT) { + // Timeout - no reply received (buffer cleared before next command) + ESP_LOGW(TAG, "Timeout waiting for reply from [0x%02X:0x%02X], available: %d", + this->current_command_.memory_location, this->current_command_.memory_address, this->available()); + this->reply_pending_ = false; } + return; } + + // No reply pending - process next command (writes have priority over reads) +#ifdef USE_MICRONOVA_WRITER + if (!this->write_queue_.empty()) { + this->current_command_ = this->write_queue_.front(); + this->write_queue_.pop(); + this->send_current_command_(); + return; + } +#endif +#ifdef MICRONOVA_LISTENER_COUNT + if (!this->read_queue_.empty()) { + this->current_command_ = this->read_queue_.front(); + this->read_queue_.pop(); + this->send_current_command_(); + } +#endif } -void MicroNova::request_address(uint8_t location, uint8_t address, MicroNovaListener *listener) { - uint8_t write_data[2] = {0, 0}; +#ifdef MICRONOVA_LISTENER_COUNT +void MicroNova::queue_read_request(uint8_t location, uint8_t address) { + // Check if this read is already queued + for (const auto &queued : this->read_queue_) { + if (queued.memory_location == location && queued.memory_address == address) { + ESP_LOGV(TAG, "Read [%02X,%02X] already queued, skipping", location, address); + return; + } + } + + MicroNovaCommand cmd; + cmd.memory_location = location; + cmd.memory_address = address; + cmd.data = 0; + + if (!this->read_queue_.push(cmd)) { + ESP_LOGW(TAG, "Read queue full, dropping read [%02X,%02X]", location, address); + return; + } + ESP_LOGV(TAG, "Queued read [%02X,%02X] (queue size: %u)", location, address, this->read_queue_.size()); +} +#endif + +void MicroNova::send_current_command_() { uint8_t trash_rx; - if (this->reply_pending_mutex_.try_lock()) { - // clear rx buffer. - // Stove hickups may cause late replies in the rx - while (this->available()) { - this->read_byte(&trash_rx); - ESP_LOGW(TAG, "Reading excess byte 0x%02X", trash_rx); - } - - write_data[0] = location; - write_data[1] = address; - ESP_LOGV(TAG, "Request from stove [%02X,%02X]", write_data[0], write_data[1]); - - this->enable_rx_pin_->digital_write(true); - this->write_array(write_data, 2); - this->flush(); - this->enable_rx_pin_->digital_write(false); - - this->current_transmission_.request_transmission_time = millis(); - this->current_transmission_.memory_location = location; - this->current_transmission_.memory_address = address; - this->current_transmission_.reply_pending = true; - this->current_transmission_.initiating_listener = listener; - } else { - ESP_LOGE(TAG, "Reply is pending, skipping read request"); + // Clear rx buffer - stove hiccups may cause late replies in the rx + while (this->available()) { + this->read_byte(&trash_rx); + ESP_LOGW(TAG, "Reading excess byte 0x%02X", trash_rx); } + + uint8_t write_data[4] = {this->current_command_.memory_location, this->current_command_.memory_address, 0, 0}; + size_t write_len; + + if (this->current_command_.is_write()) { + write_len = 4; + write_data[2] = this->current_command_.data; + // calculate checksum + write_data[3] = write_data[0] + write_data[1] + write_data[2]; + ESP_LOGV(TAG, "Sending write request [%02X,%02X,%02X,%02X]", write_data[0], write_data[1], write_data[2], + write_data[3]); + } else { + write_len = 2; + ESP_LOGV(TAG, "Sending read request [%02X,%02X]", write_data[0], write_data[1]); + } + + this->enable_rx_pin_->digital_write(true); + this->write_array(write_data, write_len); + this->flush(); + this->enable_rx_pin_->digital_write(false); + + this->transmission_time_ = millis(); + this->reply_pending_ = true; } -int MicroNova::read_stove_reply() { +int MicroNova::read_stove_reply_() { uint8_t reply_data[2] = {0, 0}; - uint8_t checksum = 0; - // assert enable_rx_pin is false this->read_array(reply_data, 2); - this->reply_pending_mutex_.unlock(); ESP_LOGV(TAG, "Reply from stove [%02X,%02X]", reply_data[0], reply_data[1]); - checksum = ((uint16_t) this->current_transmission_.memory_location + - (uint16_t) this->current_transmission_.memory_address + (uint16_t) reply_data[1]) & - 0xFF; + uint8_t checksum = this->current_command_.memory_location + this->current_command_.memory_address + reply_data[1]; if (reply_data[0] != checksum) { - ESP_LOGE(TAG, "Checksum missmatch! From [0x%02X:0x%02X] received [0x%02X,0x%02X]. Expected 0x%02X, got 0x%02X", - this->current_transmission_.memory_location, this->current_transmission_.memory_address, reply_data[0], + ESP_LOGE(TAG, "Checksum mismatch! From [0x%02X:0x%02X] received [0x%02X,0x%02X]. Expected 0x%02X, got 0x%02X", + this->current_command_.memory_location, this->current_command_.memory_address, reply_data[0], reply_data[1], checksum, reply_data[0]); return -1; } return ((int) reply_data[1]); } -void MicroNova::write_address(uint8_t location, uint8_t address, uint8_t data) { - uint8_t write_data[4] = {0, 0, 0, 0}; - uint16_t checksum = 0; +#ifdef USE_MICRONOVA_WRITER +bool MicroNova::queue_write_command(uint8_t location, uint8_t address, uint8_t data) { + MicroNovaCommand cmd; + cmd.memory_location = location | WRITE_BIT; + cmd.memory_address = address; + cmd.data = data; - if (this->reply_pending_mutex_.try_lock()) { - uint8_t write_location = location | WRITE_BIT; - write_data[0] = write_location; - write_data[1] = address; - write_data[2] = data; - - checksum = ((uint16_t) write_data[0] + (uint16_t) write_data[1] + (uint16_t) write_data[2]) & 0xFF; - write_data[3] = checksum; - - ESP_LOGV(TAG, "Write 4 bytes [%02X,%02X,%02X,%02X]", write_data[0], write_data[1], write_data[2], write_data[3]); - - this->enable_rx_pin_->digital_write(true); - this->write_array(write_data, 4); - this->flush(); - this->enable_rx_pin_->digital_write(false); - - this->current_transmission_.request_transmission_time = millis(); - this->current_transmission_.memory_location = write_location; - this->current_transmission_.memory_address = address; - this->current_transmission_.reply_pending = true; - this->current_transmission_.initiating_listener = nullptr; - } else { - ESP_LOGE(TAG, "Reply is pending, skipping write"); + // Check if a write to the same address is already queued - update data in-place + for (auto &queued : this->write_queue_) { + if (queued.memory_location == cmd.memory_location && queued.memory_address == cmd.memory_address) { + if (queued.data != cmd.data) { + ESP_LOGD(TAG, "Updating queued write [%02X,%02X] data 0x%02X -> 0x%02X", location, address, queued.data, data); + queued.data = cmd.data; + } else { + ESP_LOGV(TAG, "Write [%02X,%02X] with data 0x%02X already queued, skipping", location, address, data); + } + return true; + } } + + if (!this->write_queue_.push(cmd)) { + ESP_LOGW(TAG, "Write queue full, dropping command"); + return false; + } + ESP_LOGD(TAG, "Queued write [%02X,%02X] (queue size: %u)", location, address, this->write_queue_.size()); +#ifdef MICRONOVA_LISTENER_COUNT + // Automatically queue sensor updates after write commands + this->request_update_listeners_(); +#endif + return true; } +#endif } // namespace esphome::micronova diff --git a/esphome/components/micronova/micronova.h b/esphome/components/micronova/micronova.h index a70f355ead..58cca30b83 100644 --- a/esphome/components/micronova/micronova.h +++ b/esphome/components/micronova/micronova.h @@ -6,11 +6,19 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include <vector> - namespace esphome::micronova { -static const char *const TAG = "micronova"; +static constexpr uint8_t WRITE_QUEUE_SIZE = 10; + +/// Represents a command to be sent to the stove +/// Write commands have the high bit (0x80) set in memory_location +struct MicroNovaCommand { + uint8_t memory_location; + uint8_t memory_address; + uint8_t data; ///< Only used for write commands + + bool is_write() const; +}; class MicroNova; @@ -18,11 +26,8 @@ class MicroNova; // Interface classes. class MicroNovaBaseListener { public: - MicroNovaBaseListener() {} MicroNovaBaseListener(MicroNova *m) { this->micronova_ = m; } - void set_micronova_object(MicroNova *m) { this->micronova_ = m; } - void set_memory_location(uint8_t l) { this->memory_location_ = l; } uint8_t get_memory_location() { return this->memory_location_; } @@ -32,70 +37,76 @@ class MicroNovaBaseListener { void dump_base_config(); protected: - MicroNova *micronova_{nullptr}; + MicroNova *micronova_; uint8_t memory_location_ = 0; uint8_t memory_address_ = 0; }; class MicroNovaListener : public MicroNovaBaseListener, public PollingComponent { public: - MicroNovaListener() {} MicroNovaListener(MicroNova *m) : MicroNovaBaseListener(m) {} - virtual void request_value_from_stove() = 0; + + void update() override { this->request_value_from_stove_(); } + virtual void process_value_from_stove(int value_from_stove) = 0; - void set_needs_update(bool u) { this->needs_update_ = u; } - bool get_needs_update() { return this->needs_update_; } - - void update() override { this->set_needs_update(true); } - void dump_base_config(); protected: - bool needs_update_ = false; -}; - -class MicroNovaButtonListener : public MicroNovaBaseListener { - public: - MicroNovaButtonListener(MicroNova *m) : MicroNovaBaseListener(m) {} - - protected: - uint8_t memory_data_ = 0; + void request_value_from_stove_(); }; ///////////////////////////////////////////////////////////////////// // Main component class class MicroNova : public Component, public uart::UARTDevice { public: - MicroNova() {} + MicroNova(GPIOPin *enable_rx_pin) : enable_rx_pin_(enable_rx_pin) {} void setup() override; void loop() override; void dump_config() override; - void register_micronova_listener(MicroNovaListener *l) { this->micronova_listeners_.push_back(l); } - void request_update_listeners(); - void request_address(uint8_t location, uint8_t address, MicroNovaListener *listener); - void write_address(uint8_t location, uint8_t address, uint8_t data); - int read_stove_reply(); +#ifdef MICRONOVA_LISTENER_COUNT + void register_micronova_listener(MicroNovaListener *listener); - void set_enable_rx_pin(GPIOPin *enable_rx_pin) { this->enable_rx_pin_ = enable_rx_pin; } + /// Queue a read request to the stove (low priority - added at back) + /// All listeners registered for this address will be notified with the result + /// @param location Memory location on the stove + /// @param address Memory address on the stove + void queue_read_request(uint8_t location, uint8_t address); +#endif + +#ifdef USE_MICRONOVA_WRITER + /// Queue a write command to the stove (processed before reads) + /// @param location Memory location on the stove + /// @param address Memory address on the stove + /// @param data Data to write + /// @return true if command was queued, false if queue was full + bool queue_write_command(uint8_t location, uint8_t address, uint8_t data); +#endif protected: - GPIOPin *enable_rx_pin_{nullptr}; + void send_current_command_(); + int read_stove_reply_(); +#ifdef MICRONOVA_LISTENER_COUNT + void request_update_listeners_(); +#endif - struct MicroNovaSerialTransmission { - uint32_t request_transmission_time; - uint8_t memory_location; - uint8_t memory_address; - bool reply_pending; - MicroNovaListener *initiating_listener; - }; + GPIOPin *enable_rx_pin_; - Mutex reply_pending_mutex_; - MicroNovaSerialTransmission current_transmission_; +#ifdef USE_MICRONOVA_WRITER + StaticRingBuffer<MicroNovaCommand, WRITE_QUEUE_SIZE> write_queue_; +#endif +#ifdef MICRONOVA_LISTENER_COUNT + StaticRingBuffer<MicroNovaCommand, MICRONOVA_LISTENER_COUNT> read_queue_; +#endif + MicroNovaCommand current_command_{}; + uint32_t transmission_time_{0}; ///< Time when current command was sent + bool reply_pending_{false}; ///< True if we are waiting for a reply from the stove - std::vector<MicroNovaListener *> micronova_listeners_{}; +#ifdef MICRONOVA_LISTENER_COUNT + StaticVector<MicroNovaListener *, MICRONOVA_LISTENER_COUNT> listeners_; +#endif }; } // namespace esphome::micronova diff --git a/esphome/components/micronova/number/__init__.py b/esphome/components/micronova/number/__init__.py index ef6cc0f7d7..bcc972c5a9 100644 --- a/esphome/components/micronova/number/__init__.py +++ b/esphome/components/micronova/number/__init__.py @@ -9,6 +9,7 @@ from .. import ( MicroNova, MicroNovaListener, micronova_ns, + register_micronova_writer, to_code_micronova_listener, ) @@ -59,22 +60,24 @@ async def to_code(config): mv = await cg.get_variable(config[CONF_MICRONOVA_ID]) if thermostat_temperature_config := config.get(CONF_THERMOSTAT_TEMPERATURE): + register_micronova_writer() numb = await number.new_number( thermostat_temperature_config, + mv, min_value=0, max_value=40, step=thermostat_temperature_config.get(CONF_STEP), ) await to_code_micronova_listener(mv, numb, thermostat_temperature_config) - cg.add(numb.set_micronova_object(mv)) cg.add(numb.set_use_step_scaling(True)) if power_level_config := config.get(CONF_POWER_LEVEL): + register_micronova_writer() numb = await number.new_number( power_level_config, + mv, min_value=1, max_value=5, step=1, ) await to_code_micronova_listener(mv, numb, power_level_config) - cg.add(numb.set_micronova_object(mv)) diff --git a/esphome/components/micronova/number/micronova_number.cpp b/esphome/components/micronova/number/micronova_number.cpp index 8027947468..02a6de1c84 100644 --- a/esphome/components/micronova/number/micronova_number.cpp +++ b/esphome/components/micronova/number/micronova_number.cpp @@ -2,6 +2,13 @@ namespace esphome::micronova { +static const char *const TAG = "micronova.number"; + +void MicroNovaNumber::dump_config() { + LOG_NUMBER("", "Micronova number", this); + this->dump_base_config(); +} + void MicroNovaNumber::process_value_from_stove(int value_from_stove) { if (value_from_stove == -1) { this->publish_state(NAN); @@ -22,8 +29,7 @@ void MicroNovaNumber::control(float value) { } else { new_number = static_cast<uint8_t>(value); } - this->micronova_->write_address(this->memory_location_, this->memory_address_, new_number); - this->micronova_->request_update_listeners(); + this->micronova_->queue_write_command(this->memory_location_, this->memory_address_, new_number); } } // namespace esphome::micronova diff --git a/esphome/components/micronova/number/micronova_number.h b/esphome/components/micronova/number/micronova_number.h index 3fc5838a4f..73666b632b 100644 --- a/esphome/components/micronova/number/micronova_number.h +++ b/esphome/components/micronova/number/micronova_number.h @@ -7,16 +7,9 @@ namespace esphome::micronova { class MicroNovaNumber : public number::Number, public MicroNovaListener { public: - MicroNovaNumber() {} MicroNovaNumber(MicroNova *m) : MicroNovaListener(m) {} - void dump_config() override { - LOG_NUMBER("", "Micronova number", this); - this->dump_base_config(); - } + void dump_config() override; void control(float value) override; - void request_value_from_stove() override { - this->micronova_->request_address(this->memory_location_, this->memory_address_, this); - } void process_value_from_stove(int value_from_stove) override; void set_use_step_scaling(bool v) { this->use_step_scaling_ = v; } diff --git a/esphome/components/micronova/sensor/micronova_sensor.cpp b/esphome/components/micronova/sensor/micronova_sensor.cpp index d845e0ab3c..8d528145cd 100644 --- a/esphome/components/micronova/sensor/micronova_sensor.cpp +++ b/esphome/components/micronova/sensor/micronova_sensor.cpp @@ -2,6 +2,13 @@ namespace esphome::micronova { +static const char *const TAG = "micronova.sensor"; + +void MicroNovaSensor::dump_config() { + LOG_SENSOR("", "Micronova sensor", this); + this->dump_base_config(); +} + void MicroNovaSensor::process_value_from_stove(int value_from_stove) { if (value_from_stove == -1) { this->publish_state(NAN); diff --git a/esphome/components/micronova/sensor/micronova_sensor.h b/esphome/components/micronova/sensor/micronova_sensor.h index a2f232c7dc..f3b06d140e 100644 --- a/esphome/components/micronova/sensor/micronova_sensor.h +++ b/esphome/components/micronova/sensor/micronova_sensor.h @@ -8,14 +8,8 @@ namespace esphome::micronova { class MicroNovaSensor : public sensor::Sensor, public MicroNovaListener { public: MicroNovaSensor(MicroNova *m) : MicroNovaListener(m) {} - void dump_config() override { - LOG_SENSOR("", "Micronova sensor", this); - this->dump_base_config(); - } + void dump_config() override; - void request_value_from_stove() override { - this->micronova_->request_address(this->memory_location_, this->memory_address_, this); - } void process_value_from_stove(int value_from_stove) override; void set_divisor(uint8_t d) { this->divisor_ = d; } diff --git a/esphome/components/micronova/switch/__init__.py b/esphome/components/micronova/switch/__init__.py index c937a4cac9..d9722b5d48 100644 --- a/esphome/components/micronova/switch/__init__.py +++ b/esphome/components/micronova/switch/__init__.py @@ -9,6 +9,7 @@ from .. import ( MicroNova, MicroNovaListener, micronova_ns, + register_micronova_writer, to_code_micronova_listener, ) @@ -48,6 +49,7 @@ async def to_code(config): mv = await cg.get_variable(config[CONF_MICRONOVA_ID]) if stove_config := config.get(CONF_STOVE): + register_micronova_writer() sw = await switch.new_switch(stove_config, mv) await to_code_micronova_listener(mv, sw, stove_config) cg.add(sw.set_memory_data_on(stove_config[CONF_MEMORY_DATA_ON])) diff --git a/esphome/components/micronova/switch/micronova_switch.cpp b/esphome/components/micronova/switch/micronova_switch.cpp index 9b9ad61018..d01cc57254 100644 --- a/esphome/components/micronova/switch/micronova_switch.cpp +++ b/esphome/components/micronova/switch/micronova_switch.cpp @@ -2,33 +2,42 @@ namespace esphome::micronova { +static const char *const TAG = "micronova.switch"; + +void MicroNovaSwitch::dump_config() { + LOG_SWITCH("", "Micronova switch", this); + this->dump_base_config(); +} + void MicroNovaSwitch::write_state(bool state) { if (state) { // Only send power-on when current state is Off if (this->raw_state_ == 0) { - this->micronova_->write_address(this->memory_location_, this->memory_address_, this->memory_data_on_); - this->publish_state(true); + if (this->micronova_->queue_write_command(this->memory_location_, this->memory_address_, this->memory_data_on_)) { + this->publish_state(true); + } } else { ESP_LOGW(TAG, "Unable to turn stove on, invalid state: %d", this->raw_state_); } } else { // don't send power-off when status is Off or Final cleaning if (this->raw_state_ != 0 && this->raw_state_ != 6) { - this->micronova_->write_address(this->memory_location_, this->memory_address_, this->memory_data_off_); - this->publish_state(false); + if (this->micronova_->queue_write_command(this->memory_location_, this->memory_address_, + this->memory_data_off_)) { + this->publish_state(false); + } } else { ESP_LOGW(TAG, "Unable to turn stove off, invalid state: %d", this->raw_state_); } } - this->set_needs_update(true); } void MicroNovaSwitch::process_value_from_stove(int value_from_stove) { - this->raw_state_ = value_from_stove; if (value_from_stove == -1) { ESP_LOGE(TAG, "Error reading stove state"); return; } + this->raw_state_ = value_from_stove; // set the stove switch to on for any value but 0 bool state = value_from_stove != 0; diff --git a/esphome/components/micronova/switch/micronova_switch.h b/esphome/components/micronova/switch/micronova_switch.h index 96c2c14e9e..fee3c73976 100644 --- a/esphome/components/micronova/switch/micronova_switch.h +++ b/esphome/components/micronova/switch/micronova_switch.h @@ -9,13 +9,7 @@ namespace esphome::micronova { class MicroNovaSwitch : public switch_::Switch, public MicroNovaListener { public: MicroNovaSwitch(MicroNova *m) : MicroNovaListener(m) {} - void dump_config() override { - LOG_SWITCH("", "Micronova switch", this); - this->dump_base_config(); - } - void request_value_from_stove() override { - this->micronova_->request_address(this->memory_location_, this->memory_address_, this); - } + void dump_config() override; void process_value_from_stove(int value_from_stove) override; void set_memory_data_on(uint8_t f) { this->memory_data_on_ = f; } diff --git a/esphome/components/micronova/text_sensor/micronova_text_sensor.cpp b/esphome/components/micronova/text_sensor/micronova_text_sensor.cpp index 2217ed6d6f..50a0d34b3a 100644 --- a/esphome/components/micronova/text_sensor/micronova_text_sensor.cpp +++ b/esphome/components/micronova/text_sensor/micronova_text_sensor.cpp @@ -2,6 +2,13 @@ namespace esphome::micronova { +static const char *const TAG = "micronova.text_sensor"; + +void MicroNovaTextSensor::dump_config() { + LOG_TEXT_SENSOR("", "Micronova text sensor", this); + this->dump_base_config(); +} + void MicroNovaTextSensor::process_value_from_stove(int value_from_stove) { if (value_from_stove == -1) { this->publish_state("unknown"); diff --git a/esphome/components/micronova/text_sensor/micronova_text_sensor.h b/esphome/components/micronova/text_sensor/micronova_text_sensor.h index 290f0ca45a..6918a372e8 100644 --- a/esphome/components/micronova/text_sensor/micronova_text_sensor.h +++ b/esphome/components/micronova/text_sensor/micronova_text_sensor.h @@ -20,13 +20,7 @@ static const char *const STOVE_STATES[11] = {"Off", class MicroNovaTextSensor : public text_sensor::TextSensor, public MicroNovaListener { public: MicroNovaTextSensor(MicroNova *m) : MicroNovaListener(m) {} - void dump_config() override { - LOG_TEXT_SENSOR("", "Micronova text sensor", this); - this->dump_base_config(); - } - void request_value_from_stove() override { - this->micronova_->request_address(this->memory_location_, this->memory_address_, this); - } + void dump_config() override; void process_value_from_stove(int value_from_stove) override; }; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 44918fe00c..cec77fe2e2 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -107,6 +107,8 @@ #define MDNS_SERVICE_COUNT 3 #define USE_MDNS_DYNAMIC_TXT #define MDNS_DYNAMIC_TXT_COUNT 2 +#define MICRONOVA_LISTENER_COUNT 1 +#define USE_MICRONOVA_WRITER #define SERIAL_PROXY_COUNT 2 #define SNTP_SERVER_COUNT 3 #define USE_MEDIA_PLAYER diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 11e0afe526..70ac1574f0 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -293,6 +293,81 @@ template<typename T, size_t N> class StaticVector { operator std::span<const T>() const { return std::span<const T>(data_.data(), count_); } }; +/// Fixed-size circular buffer with FIFO semantics and iteration support. +/// +/// A tiny ring buffer that avoids dynamic allocations from std::deque/std::queue +/// (which can be wasteful on MCUs), while supporting iteration over queued elements. +/// +/// Not thread-safe. All access (push/pop/iteration) must occur from a single +/// context, or the caller must provide external synchronization. +template<typename T, size_t N> class StaticRingBuffer { + using index_type = std::conditional_t<(N <= 255), uint8_t, uint16_t>; + + public: + class Iterator { + public: + Iterator(StaticRingBuffer *buf, index_type pos) : buf_(buf), pos_(pos) {} + T &operator*() { return buf_->data_[(buf_->head_ + pos_) % N]; } + Iterator &operator++() { + ++pos_; + return *this; + } + bool operator!=(const Iterator &other) const { return pos_ != other.pos_; } + + private: + StaticRingBuffer *buf_; + index_type pos_; + }; + + class ConstIterator { + public: + ConstIterator(const StaticRingBuffer *buf, index_type pos) : buf_(buf), pos_(pos) {} + const T &operator*() const { return buf_->data_[(buf_->head_ + pos_) % N]; } + ConstIterator &operator++() { + ++pos_; + return *this; + } + bool operator!=(const ConstIterator &other) const { return pos_ != other.pos_; } + + private: + const StaticRingBuffer *buf_; + index_type pos_; + }; + + bool push(const T &value) { + if (this->count_ >= N) { + return false; + } + this->data_[this->tail_] = value; + this->tail_ = (this->tail_ + 1) % N; + ++this->count_; + return true; + } + + void pop() { + if (this->count_ > 0) { + this->head_ = (this->head_ + 1) % N; + --this->count_; + } + } + + T &front() { return this->data_[this->head_]; } + const T &front() const { return this->data_[this->head_]; } + index_type size() const { return this->count_; } + bool empty() const { return this->count_ == 0; } + + Iterator begin() { return Iterator(this, 0); } + Iterator end() { return Iterator(this, this->count_); } + ConstIterator begin() const { return ConstIterator(this, 0); } + ConstIterator end() const { return ConstIterator(this, this->count_); } + + protected: + T data_[N]; + index_type head_{0}; + index_type tail_{0}; + index_type count_{0}; +}; + /// Fixed-capacity vector - allocates once at runtime, never reallocates /// This avoids std::vector template overhead (_M_realloc_insert, _M_default_append) /// when size is known at initialization but not at compile time From c52a48ed38923eccf0d5c38a70650d34e17a4f22 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Mar 2026 03:11:46 -0400 Subject: [PATCH 1281/2030] [multiple] Convert static function locals to member variables (#14689) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/daikin_arc/daikin_arc.cpp | 5 ++--- esphome/components/daikin_arc/daikin_arc.h | 1 + esphome/components/haier/hon_climate.cpp | 5 ++--- esphome/components/haier/hon_climate.h | 1 + .../components/ina2xx_base/ina2xx_base.cpp | 5 ++--- esphome/components/ltr_als_ps/ltr_als_ps.cpp | 21 +++++++++---------- esphome/components/ltr_als_ps/ltr_als_ps.h | 5 ++++- .../matrix_keypad/matrix_keypad.cpp | 12 +++++------ .../components/matrix_keypad/matrix_keypad.h | 2 ++ .../components/mqtt/mqtt_backend_esp32.cpp | 9 ++++---- esphome/components/mqtt/mqtt_backend_esp32.h | 1 + esphome/components/sgp4x/sgp4x.cpp | 5 +++-- esphome/components/sgp4x/sgp4x.h | 3 ++- 13 files changed, 39 insertions(+), 36 deletions(-) diff --git a/esphome/components/daikin_arc/daikin_arc.cpp b/esphome/components/daikin_arc/daikin_arc.cpp index adb7b9fec7..18f12dbfc6 100644 --- a/esphome/components/daikin_arc/daikin_arc.cpp +++ b/esphome/components/daikin_arc/daikin_arc.cpp @@ -91,11 +91,10 @@ void DaikinArcClimate::transmit_state() { remote_state[5] = this->operation_mode_() | 0x08; remote_state[6] = this->temperature_(); remote_state[7] = this->humidity_(); - static uint8_t last_humidity = 0x66; - if (remote_state[7] != last_humidity && this->mode != climate::CLIMATE_MODE_OFF) { + if (remote_state[7] != this->last_humidity_ && this->mode != climate::CLIMATE_MODE_OFF) { ESP_LOGD(TAG, "Set Humditiy: %d, %d\n", (int) this->target_humidity, (int) remote_state[7]); remote_header[9] |= 0x10; - last_humidity = remote_state[7]; + this->last_humidity_ = remote_state[7]; } uint16_t fan_speed = this->fan_speed_(); remote_state[8] = fan_speed >> 8; diff --git a/esphome/components/daikin_arc/daikin_arc.h b/esphome/components/daikin_arc/daikin_arc.h index 6cfffd4725..2b4d4375aa 100644 --- a/esphome/components/daikin_arc/daikin_arc.h +++ b/esphome/components/daikin_arc/daikin_arc.h @@ -70,6 +70,7 @@ class DaikinArcClimate : public climate_ir::ClimateIR { // Handle received IR Buffer bool on_receive(remote_base::RemoteReceiveData data) override; bool parse_state_frame_(const uint8_t frame[]); + uint8_t last_humidity_{0x66}; }; } // namespace daikin_arc diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index be5035caa1..b8889ef2bd 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -1375,9 +1375,8 @@ void HonClimate::process_protocol_reset() { bool HonClimate::should_get_big_data_() { if (this->big_data_sensors_ > 0) { - static uint8_t counter = 0; - counter = (counter + 1) % 3; - return counter == 1; + this->big_data_counter_ = (this->big_data_counter_ + 1) % 3; + return this->big_data_counter_ == 1; } return false; } diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 4565ed2981..9bddac3f92 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -188,6 +188,7 @@ class HonClimate : public HaierClimateBase { float active_alarm_count_{NAN}; std::chrono::steady_clock::time_point last_alarm_request_; int big_data_sensors_{0}; + uint8_t big_data_counter_{0}; esphome::optional<hon_protocol::VerticalSwingMode> current_vertical_swing_{}; esphome::optional<hon_protocol::HorizontalSwingMode> current_horizontal_swing_{}; HonSettings settings_{}; diff --git a/esphome/components/ina2xx_base/ina2xx_base.cpp b/esphome/components/ina2xx_base/ina2xx_base.cpp index 9f510eef74..2d08562e54 100644 --- a/esphome/components/ina2xx_base/ina2xx_base.cpp +++ b/esphome/components/ina2xx_base/ina2xx_base.cpp @@ -572,9 +572,8 @@ bool INA2XX::write_unsigned_16_(uint8_t reg, uint16_t val) { } bool INA2XX::read_unsigned_(uint8_t reg, uint8_t reg_size, uint64_t &data_out) { - static uint8_t rx_buf[5] = {0}; // max buffer size - - if (reg_size > 5) { + uint8_t rx_buf[5]{}; + if (reg_size > sizeof(rx_buf)) { return false; } diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.cpp b/esphome/components/ltr_als_ps/ltr_als_ps.cpp index f9c1474c85..ff335fe34c 100644 --- a/esphome/components/ltr_als_ps/ltr_als_ps.cpp +++ b/esphome/components/ltr_als_ps/ltr_als_ps.cpp @@ -137,7 +137,6 @@ void LTRAlsPsComponent::update() { void LTRAlsPsComponent::loop() { ErrorCode err = i2c::ERROR_OK; - static uint8_t tries{0}; switch (this->state_) { case State::DELAYED_SETUP: @@ -166,20 +165,20 @@ void LTRAlsPsComponent::loop() { case State::WAITING_FOR_DATA: if (this->is_als_data_ready_(this->als_readings_) == LtrDataAvail::LTR_DATA_OK) { - tries = 0; + this->read_data_tries_ = 0; ESP_LOGV(TAG, "Reading sensor data having gain = %.0fx, time = %d ms", get_gain_coeff(this->als_readings_.gain), get_itime_ms(this->als_readings_.integration_time)); this->read_sensor_data_(this->als_readings_); this->state_ = State::DATA_COLLECTED; this->apply_lux_calculation_(this->als_readings_); - } else if (tries >= MAX_TRIES) { + } else if (this->read_data_tries_ >= MAX_TRIES) { ESP_LOGW(TAG, "Can't get data after several tries."); - tries = 0; + this->read_data_tries_ = 0; this->status_set_warning(); this->state_ = State::IDLE; return; } else { - tries++; + this->read_data_tries_++; } break; @@ -221,21 +220,21 @@ void LTRAlsPsComponent::loop() { } void LTRAlsPsComponent::check_and_trigger_ps_() { - static uint32_t last_high_trigger_time{0}; - static uint32_t last_low_trigger_time{0}; uint16_t ps_data = this->read_ps_data_(); uint32_t now = millis(); if (ps_data != this->ps_readings_) { this->ps_readings_ = ps_data; // Higher values - object is closer to sensor - if (ps_data > this->ps_threshold_high_ && now - last_high_trigger_time >= this->ps_cooldown_time_s_ * 1000) { - last_high_trigger_time = now; + if (ps_data > this->ps_threshold_high_ && + now - this->last_ps_high_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) { + this->last_ps_high_trigger_time_ = now; ESP_LOGV(TAG, "Proximity high threshold triggered. Value = %d, Trigger level = %d", ps_data, this->ps_threshold_high_); this->on_ps_high_trigger_callback_.call(); - } else if (ps_data < this->ps_threshold_low_ && now - last_low_trigger_time >= this->ps_cooldown_time_s_ * 1000) { - last_low_trigger_time = now; + } else if (ps_data < this->ps_threshold_low_ && + now - this->last_ps_low_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) { + this->last_ps_low_trigger_time_ = now; ESP_LOGV(TAG, "Proximity low threshold triggered. Value = %d, Trigger level = %d", ps_data, this->ps_threshold_low_); this->on_ps_low_trigger_callback_.call(); diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.h b/esphome/components/ltr_als_ps/ltr_als_ps.h index c6052300de..3ab2cea074 100644 --- a/esphome/components/ltr_als_ps/ltr_als_ps.h +++ b/esphome/components/ltr_als_ps/ltr_als_ps.h @@ -126,10 +126,13 @@ class LTRAlsPsComponent : public PollingComponent, public i2c::I2CDevice { MeasurementRepeatRate repeat_rate_{MeasurementRepeatRate::REPEAT_RATE_500MS}; float glass_attenuation_factor_{1.0}; + uint32_t last_ps_high_trigger_time_{0}; + uint32_t last_ps_low_trigger_time_{0}; uint16_t ps_cooldown_time_s_{5}; - PsGain ps_gain_{PsGain::PS_GAIN_16}; uint16_t ps_threshold_high_{0xffff}; uint16_t ps_threshold_low_{0x0000}; + uint8_t read_data_tries_{0}; + PsGain ps_gain_{PsGain::PS_GAIN_16}; // // Sensors for publishing data diff --git a/esphome/components/matrix_keypad/matrix_keypad.cpp b/esphome/components/matrix_keypad/matrix_keypad.cpp index febbe794e4..cc46ba98d6 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.cpp +++ b/esphome/components/matrix_keypad/matrix_keypad.cpp @@ -27,8 +27,6 @@ void MatrixKeypad::setup() { } void MatrixKeypad::loop() { - static uint32_t active_start = 0; - static int active_key = -1; uint32_t now = App.get_loop_component_start_time(); int key = -1; bool error = false; @@ -54,8 +52,8 @@ void MatrixKeypad::loop() { if (error) return; - if (key != active_key) { - if ((active_key != -1) && (this->pressed_key_ == active_key)) { + if (key != this->active_key_) { + if ((this->active_key_ != -1) && (this->pressed_key_ == this->active_key_)) { row = this->pressed_key_ / this->columns_.size(); col = this->pressed_key_ % this->columns_.size(); ESP_LOGD(TAG, "key @ row %d, col %d released", row, col); @@ -70,13 +68,13 @@ void MatrixKeypad::loop() { this->pressed_key_ = -1; } - active_key = key; + this->active_key_ = key; if (key == -1) return; - active_start = now; + this->active_start_ = now; } - if ((this->pressed_key_ == key) || (now - active_start < this->debounce_time_)) + if ((this->pressed_key_ == key) || (now - this->active_start_ < this->debounce_time_)) return; row = key / this->columns_.size(); diff --git a/esphome/components/matrix_keypad/matrix_keypad.h b/esphome/components/matrix_keypad/matrix_keypad.h index 258ab4fadc..8963612d0c 100644 --- a/esphome/components/matrix_keypad/matrix_keypad.h +++ b/esphome/components/matrix_keypad/matrix_keypad.h @@ -44,6 +44,8 @@ class MatrixKeypad : public key_provider::KeyProvider, public Component { bool has_diodes_{false}; bool has_pulldowns_{false}; int pressed_key_ = -1; + uint32_t active_start_{0}; + int active_key_{-1}; std::vector<MatrixKeypadListener *> listeners_{}; std::vector<MatrixKeyTrigger *> key_triggers_; diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index 8a7fb965e9..5642fd5f7b 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -150,17 +150,16 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) { this->on_publish_.call((int) event.msg_id); break; case MQTT_EVENT_DATA: { - static std::string topic; if (!event.topic.empty()) { // When a single message arrives as multiple chunks, the topic will be empty // on any but the first message, leading to event.topic being an empty string. // To ensure handlers get the correct topic, cache the last seen topic to // simulate always receiving the topic from underlying library - topic = event.topic; + this->cached_topic_ = event.topic; } - ESP_LOGV(TAG, "MQTT_EVENT_DATA %s", topic.c_str()); - this->on_message_.call(topic.c_str(), event.data.data(), event.data.size(), event.current_data_offset, - event.total_data_len); + ESP_LOGV(TAG, "MQTT_EVENT_DATA %s", this->cached_topic_.c_str()); + this->on_message_.call(this->cached_topic_.c_str(), event.data.data(), event.data.size(), + event.current_data_offset, event.total_data_len); } break; case MQTT_EVENT_ERROR: ESP_LOGE(TAG, "MQTT_EVENT_ERROR"); diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index ccc4c4026c..5c4dc413bd 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -265,6 +265,7 @@ class MQTTBackendESP32 final : public MQTTBackend { CallbackManager<on_unsubscribe_callback_t> on_unsubscribe_; CallbackManager<on_message_callback_t> on_message_; CallbackManager<on_publish_user_callback_t> on_publish_; + std::string cached_topic_; std::queue<Event> mqtt_events_; #if defined(USE_MQTT_IDF_ENQUEUE) diff --git a/esphome/components/sgp4x/sgp4x.cpp b/esphome/components/sgp4x/sgp4x.cpp index cb41e374f8..bbf1ffd4c0 100644 --- a/esphome/components/sgp4x/sgp4x.cpp +++ b/esphome/components/sgp4x/sgp4x.cpp @@ -124,6 +124,7 @@ void SGP4xComponent::self_test_() { } this->self_test_complete_ = true; + this->nox_conditioning_start_ = millis(); ESP_LOGD(TAG, "Self-test complete"); }); } @@ -161,7 +162,6 @@ void SGP4xComponent::update_gas_indices_() { void SGP4xComponent::measure_raw_() { float humidity = NAN; - static uint32_t nox_conditioning_start = millis(); if (!this->self_test_complete_) { ESP_LOGW(TAG, "Self-test incomplete"); @@ -191,10 +191,11 @@ void SGP4xComponent::measure_raw_() { response_words = 1; } else { // SGP41 sensor must use NOx conditioning command for the first 10 seconds - if (millis() - nox_conditioning_start < 10000) { + if (this->nox_conditioning_start_.has_value() && millis() - *this->nox_conditioning_start_ < 10000) { command = SGP41_CMD_NOX_CONDITIONING; response_words = 1; } else { + this->nox_conditioning_start_.reset(); command = SGP41_CMD_MEASURE_RAW; response_words = 2; } diff --git a/esphome/components/sgp4x/sgp4x.h b/esphome/components/sgp4x/sgp4x.h index 89fa627c61..6b8b598aff 100644 --- a/esphome/components/sgp4x/sgp4x.h +++ b/esphome/components/sgp4x/sgp4x.h @@ -127,8 +127,9 @@ class SGP4xComponent : public PollingComponent, public sensor::Sensor, public se uint16_t measure_time_; uint8_t samples_read_ = 0; uint8_t samples_to_stabilize_ = static_cast<int8_t>(GasIndexAlgorithm_INITIAL_BLACKOUT) * 2; - bool store_baseline_; + + optional<uint32_t> nox_conditioning_start_{}; ESPPreferenceObject pref_; uint32_t seconds_since_last_store_; SGP4xBaselines voc_baselines_storage_; From 4e16f270a3928738460139426748c3d96dafdddd Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 11 Mar 2026 12:47:58 -0500 Subject: [PATCH 1282/2030] [speaker_source] Add playlist management (#14652) --- .../components/speaker_source/automation.h | 29 ++ .../components/speaker_source/media_player.py | 43 ++ .../speaker_source_media_player.cpp | 401 ++++++++++++++---- .../speaker_source_media_player.h | 46 +- tests/components/speaker_source/common.yaml | 5 + 5 files changed, 429 insertions(+), 95 deletions(-) create mode 100644 esphome/components/speaker_source/automation.h diff --git a/esphome/components/speaker_source/automation.h b/esphome/components/speaker_source/automation.h new file mode 100644 index 0000000000..b436149a03 --- /dev/null +++ b/esphome/components/speaker_source/automation.h @@ -0,0 +1,29 @@ +#pragma once + +#include "esphome/core/defines.h" + +#ifdef USE_ESP32 + +#include "esphome/core/automation.h" +#include "speaker_source_media_player.h" + +namespace esphome::speaker_source { + +template<typename... Ts> class SetPlaylistDelayAction : public Action<Ts...> { + public: + explicit SetPlaylistDelayAction(SpeakerSourceMediaPlayer *parent) : parent_(parent) {} + + TEMPLATABLE_VALUE(uint8_t, pipeline) + TEMPLATABLE_VALUE(uint32_t, delay) + + void play(const Ts &...x) override { + this->parent_->set_playlist_delay_ms(this->pipeline_.value(x...), this->delay_.value(x...)); + } + + protected: + SpeakerSourceMediaPlayer *parent_; +}; + +} // namespace esphome::speaker_source + +#endif // USE_ESP32 diff --git a/esphome/components/speaker_source/media_player.py b/esphome/components/speaker_source/media_player.py index a44cdcbf01..9080bebcae 100644 --- a/esphome/components/speaker_source/media_player.py +++ b/esphome/components/speaker_source/media_player.py @@ -3,13 +3,16 @@ import esphome.codegen as cg from esphome.components import audio, media_player, media_source, speaker import esphome.config_validation as cv from esphome.const import ( + CONF_DELAY, CONF_FORMAT, CONF_ID, CONF_NUM_CHANNELS, CONF_SAMPLE_RATE, CONF_SPEAKER, ) +from esphome.core import ID from esphome.core.entity_helpers import inherit_property_from +from esphome.cpp_generator import MockObj, TemplateArgsType from esphome.types import ConfigType AUTO_LOAD = ["audio"] @@ -19,6 +22,7 @@ CODEOWNERS = ["@kahrendt"] CONF_MEDIA_PIPELINE = "media_pipeline" CONF_ON_MUTE = "on_mute" +CONF_PIPELINE = "pipeline" CONF_ON_UNMUTE = "on_unmute" CONF_ON_VOLUME = "on_volume" CONF_SOURCES = "sources" @@ -36,6 +40,13 @@ SpeakerSourceMediaPlayer = speaker_source_ns.class_( PipelineContext = speaker_source_ns.struct("PipelineContext") Pipeline = speaker_source_ns.enum("Pipeline") +PIPELINE_ENUM = { + "media": Pipeline.MEDIA_PIPELINE, +} + +SetPlaylistDelayAction = speaker_source_ns.class_( + "SetPlaylistDelayAction", automation.Action +) FORMAT_MAPPING = { @@ -210,3 +221,35 @@ async def to_code(config: ConfigType) -> None: [(cg.float_, "x")], on_volume, ) + + +SET_PLAYLIST_DELAY_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(SpeakerSourceMediaPlayer), + cv.Required(CONF_PIPELINE): cv.enum(PIPELINE_ENUM, lower=True), + cv.Required(CONF_DELAY): cv.templatable(cv.positive_time_period_milliseconds), + } +) + + +@automation.register_action( + "speaker_source.set_playlist_delay", + SetPlaylistDelayAction, + SET_PLAYLIST_DELAY_ACTION_SCHEMA, + synchronous=True, +) +async def set_playlist_delay_action_to_code( + config: ConfigType, + action_id: ID, + template_arg: cg.TemplateArguments, + args: TemplateArgsType, +) -> MockObj: + parent = await cg.get_variable(config[CONF_ID]) + var = cg.new_Pvariable(action_id, template_arg, parent) + + cg.add(var.set_pipeline(config[CONF_PIPELINE])) + + template_ = await cg.templatable(config[CONF_DELAY], args, cg.uint32) + cg.add(var.set_delay(template_)) + + return var diff --git a/esphome/components/speaker_source/speaker_source_media_player.cpp b/esphome/components/speaker_source/speaker_source_media_player.cpp index a3679891d2..3724e20667 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.cpp +++ b/esphome/components/speaker_source/speaker_source_media_player.cpp @@ -135,8 +135,12 @@ void SpeakerSourceMediaPlayer::handle_media_state_changed_(uint8_t pipeline, med PipelineContext &ps = this->pipelines_[pipeline]; if (state == media_source::MediaSourceState::IDLE) { + // Track whether this IDLE was from an orchestrator-initiated stop (e.g., NEXT/PREV/PLAY_URI) + // so we can suppress spurious PLAYLIST_ADVANCE below + bool was_stopping = (ps.stopping_source == source); + // Source went idle - clear stopping flag if this was the source we asked to stop - if (ps.stopping_source == source) { + if (was_stopping) { ps.stopping_source = nullptr; } @@ -152,6 +156,11 @@ void SpeakerSourceMediaPlayer::handle_media_state_changed_(uint8_t pipeline, med // Finish the speaker to ensure it's ready for the next playback ps.speaker->finish(); + + // Only advance the playlist if the track finished naturally (not stopped by the orchestrator) + if (!was_stopping) { + this->queue_command_(MediaPlayerControlCommand::PLAYLIST_ADVANCE, pipeline); + } } } else if (state == media_source::MediaSourceState::PLAYING) { // Source started playing - make it the active source if no one else is active @@ -197,8 +206,9 @@ size_t SpeakerSourceMediaPlayer::handle_media_output_(uint8_t pipeline, media_so return 0; } +// THREAD CONTEXT: Called from main loop (loop) media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_media_pipeline_state_( - media_source::MediaSource *source) const { + media_source::MediaSource *source, bool playlist_active, media_player::MediaPlayerState old_state) const { if (source != nullptr) { switch (source->get_state()) { case media_source::MediaSourceState::PLAYING: @@ -214,97 +224,27 @@ media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_media_pipeline_stat } } + // No active source. Stay PLAYING during playlist transitions + if (playlist_active && old_state == media_player::MEDIA_PLAYER_STATE_PLAYING) { + return media_player::MEDIA_PLAYER_STATE_PLAYING; + } return media_player::MEDIA_PLAYER_STATE_IDLE; } void SpeakerSourceMediaPlayer::loop() { // Process queued control commands - MediaPlayerControlCommand control_command; - - // Use peek to check command without removing it - if (xQueuePeek(this->media_control_command_queue_, &control_command, 0) == pdTRUE) { - bool command_executed = false; - uint8_t pipeline = control_command.pipeline; - - switch (control_command.type) { - case MediaPlayerControlCommand::PLAY_URI: { - command_executed = this->try_execute_play_uri_(*control_command.data.uri, pipeline); - break; - } - - case MediaPlayerControlCommand::SEND_COMMAND: { - PipelineContext &ps = this->pipelines_[pipeline]; - - // Determine target source: prefer active, fall back to last - media_source::MediaSource *target_source = nullptr; - if (ps.active_source != nullptr) { - target_source = ps.active_source; - } else if (ps.last_source != nullptr) { - target_source = ps.last_source; - } - - media_player::MediaPlayerCommand player_command = control_command.data.command; - switch (player_command) { - case media_player::MEDIA_PLAYER_COMMAND_TOGGLE: { - media_source::MediaSource *active_source = ps.active_source; - if ((active_source != nullptr) && (active_source->get_state() == media_source::MediaSourceState::PLAYING)) { - if (target_source != nullptr) { - target_source->handle_command(media_source::MediaSourceCommand::PAUSE); - } - } else { - if (target_source != nullptr) { - target_source->handle_command(media_source::MediaSourceCommand::PLAY); - } - } - break; - } - - case media_player::MEDIA_PLAYER_COMMAND_PLAY: { - if (target_source != nullptr) { - target_source->handle_command(media_source::MediaSourceCommand::PLAY); - } - break; - } - - case media_player::MEDIA_PLAYER_COMMAND_PAUSE: { - if (target_source != nullptr) { - target_source->handle_command(media_source::MediaSourceCommand::PAUSE); - } - break; - } - - case media_player::MEDIA_PLAYER_COMMAND_STOP: { - if (target_source != nullptr) { - target_source->handle_command(media_source::MediaSourceCommand::STOP); - } - break; - } - - default: - break; - } - - command_executed = true; - break; - } - } - - // Only remove from queue if successfully executed - if (command_executed) { - xQueueReceive(this->media_control_command_queue_, &control_command, 0); - - // Delete the allocated string for PLAY_URI commands - if (control_command.type == MediaPlayerControlCommand::PLAY_URI) { - delete control_command.data.uri; - } - } - } + this->process_control_queue_(); // Update state based on active sources media_player::MediaPlayerState old_state = this->state; PipelineContext &media_ps = this->pipelines_[MEDIA_PIPELINE]; - this->state = this->get_media_pipeline_state_(media_ps.active_source); + + // Check playlist state to detect transitions between items + bool media_playlist_active = (media_ps.playlist_index < media_ps.playlist.size()) || + (media_ps.repeat_mode != REPEAT_OFF && !media_ps.playlist.empty()); + + this->state = this->get_media_pipeline_state_(media_ps.active_source, media_playlist_active, old_state); if (this->state != old_state) { this->publish_state(); @@ -349,9 +289,9 @@ bool SpeakerSourceMediaPlayer::try_execute_play_uri_(const std::string &uri, uin // Only send END command once per source - check if we've already asked this source to stop if (ps.stopping_source != active_source) { ESP_LOGV(TAG, "Pipeline %u: stopping active source", pipeline); + ps.stopping_source = active_source; active_source->handle_command(media_source::MediaSourceCommand::STOP); ps.speaker->stop(); - ps.stopping_source = active_source; } return false; // Leave in queue, retry next loop } @@ -363,9 +303,9 @@ bool SpeakerSourceMediaPlayer::try_execute_play_uri_(const std::string &uri, uin // Only send STOP command once per source if (ps.stopping_source != target_source) { ESP_LOGV(TAG, "Pipeline %u: target source busy, stopping", pipeline); + ps.stopping_source = target_source; target_source->handle_command(media_source::MediaSourceCommand::STOP); ps.speaker->stop(); - ps.stopping_source = target_source; } return false; // Leave in queue, retry next loop } @@ -385,6 +325,7 @@ bool SpeakerSourceMediaPlayer::try_execute_play_uri_(const std::string &uri, uin if (!target_source->play_uri(uri)) { ESP_LOGE(TAG, "Pipeline %u: Failed to play URI: %s", pipeline, uri.c_str()); ps.pending_source = nullptr; + this->queue_command_(MediaPlayerControlCommand::PLAYLIST_ADVANCE, pipeline); } // Reset pending frame counter for this pipeline since we're starting a new source @@ -393,6 +334,280 @@ bool SpeakerSourceMediaPlayer::try_execute_play_uri_(const std::string &uri, uin return true; // Remove from queue } +// THREAD CONTEXT: Called from main loop (process_control_queue_, queue_play_current_, handle_media_state_changed_) +void SpeakerSourceMediaPlayer::queue_command_(MediaPlayerControlCommand::Type type, uint8_t pipeline) { + MediaPlayerControlCommand cmd{}; + cmd.type = type; + cmd.pipeline = pipeline; + if (xQueueSend(this->media_control_command_queue_, &cmd, 0) != pdTRUE) { + ESP_LOGE(TAG, "Queue full, command dropped"); + } +} + +// THREAD CONTEXT: Called from main loop via automation commands (direct) +void SpeakerSourceMediaPlayer::set_playlist_delay_ms(uint8_t pipeline, uint32_t delay_ms) { + if (pipeline < this->pipelines_.size()) { + this->pipelines_[pipeline].playlist_delay_ms = delay_ms; + } +} + +// THREAD CONTEXT: Called from main loop (process_control_queue_). +// The timeout callback also runs on the main loop. +void SpeakerSourceMediaPlayer::queue_play_current_(uint8_t pipeline, uint32_t delay_ms) { + if (delay_ms > 0) { + this->set_timeout(PipelineContext::TIMEOUT_IDS[pipeline], delay_ms, + [this, pipeline]() { this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); }); + } else { + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } +} + +// THREAD CONTEXT: Called from main loop (loop) +void SpeakerSourceMediaPlayer::process_control_queue_() { + MediaPlayerControlCommand control_command; + + // Use peek to check command without removing it + if (xQueuePeek(this->media_control_command_queue_, &control_command, 0) != pdTRUE) { + return; + } + + bool command_executed = false; + uint8_t pipeline = control_command.pipeline; + + // Get pipeline state + PipelineContext &ps = this->pipelines_[pipeline]; + media_source::MediaSource *active_source = ps.active_source; + + switch (control_command.type) { + case MediaPlayerControlCommand::PLAY_URI: { + // Always use our local playlist to start playback + this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + ps.playlist.clear(); + ps.playlist_index = 0; // Reset index + ps.playlist.push_back(*control_command.data.uri); + + // Queue PLAY_CURRENT to initiate playback + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + command_executed = true; + break; + } + + case MediaPlayerControlCommand::ENQUEUE_URI: { + // Always add to our local playlist + ps.playlist.push_back(*control_command.data.uri); + + // If nothing is playing and no upcoming items are queued, start the new item. + bool nothing_playing = + (active_source == nullptr) || (active_source->get_state() == media_source::MediaSourceState::IDLE); + if (nothing_playing && ps.playlist_index >= ps.playlist.size() - 1) { + ps.playlist_index = ps.playlist.size() - 1; // Point to newly added item + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } + command_executed = true; + break; + } + + case MediaPlayerControlCommand::PLAYLIST_ADVANCE: { + // Internal message: a track finished, advance to next + if (ps.repeat_mode != REPEAT_ONE) { + ps.playlist_index++; + } + + // Check if we should continue playback + if (ps.playlist_index < ps.playlist.size()) { + this->queue_play_current_(pipeline, ps.playlist_delay_ms); + } else if (ps.repeat_mode == REPEAT_ALL && !ps.playlist.empty()) { + ps.playlist_index = 0; + this->queue_play_current_(pipeline, ps.playlist_delay_ms); + } + command_executed = true; + break; + } + + case MediaPlayerControlCommand::PLAY_CURRENT: { + // Play the item at current playlist index + if (ps.playlist_index < ps.playlist.size()) { + command_executed = this->try_execute_play_uri_(ps.playlist[ps.playlist_index], pipeline); + } else { + command_executed = true; // Index out of bounds or empty playlist + } + break; + } + + case MediaPlayerControlCommand::SEND_COMMAND: { + this->handle_player_command_(control_command.data.command, pipeline); + command_executed = true; + break; + } + } + + // Only remove from queue if successfully executed + if (command_executed) { + xQueueReceive(this->media_control_command_queue_, &control_command, 0); + + // Delete the allocated string for PLAY_URI and ENQUEUE_URI commands + if (control_command.type == MediaPlayerControlCommand::PLAY_URI || + control_command.type == MediaPlayerControlCommand::ENQUEUE_URI) { + delete control_command.data.uri; + } + } +} + +// THREAD CONTEXT: Called from main loop only (via process_control_queue_) +void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerCommand player_command, + uint8_t pipeline) { + PipelineContext &ps = this->pipelines_[pipeline]; + media_source::MediaSource *active_source = ps.active_source; + bool has_internal_playlist = (active_source != nullptr) && active_source->has_internal_playlist(); + + // Determine target source: prefer active, fall back to last + media_source::MediaSource *target_source = nullptr; + if (active_source != nullptr) { + target_source = active_source; + } else if (ps.last_source != nullptr) { + target_source = ps.last_source; + } + + switch (player_command) { + case media_player::MEDIA_PLAYER_COMMAND_TOGGLE: { + // Convert TOGGLE to PLAY or PAUSE based on current state + if ((active_source != nullptr) && (active_source->get_state() == media_source::MediaSourceState::PLAYING)) { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PAUSE); + } + } else if (!has_internal_playlist && active_source == nullptr && !ps.playlist.empty()) { + bool last_has_internal_playlist = (ps.last_source != nullptr) && ps.last_source->has_internal_playlist(); + if (last_has_internal_playlist) { + ps.last_source->handle_command(media_source::MediaSourceCommand::PLAY); + } else { + if (ps.playlist_index >= ps.playlist.size()) { + ps.playlist_index = 0; + } + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } + } else { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PLAY); + } + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_PLAY: { + if (!has_internal_playlist && active_source == nullptr && !ps.playlist.empty()) { + bool last_has_internal_playlist = (ps.last_source != nullptr) && ps.last_source->has_internal_playlist(); + if (last_has_internal_playlist) { + ps.last_source->handle_command(media_source::MediaSourceCommand::PLAY); + } else { + if (ps.playlist_index >= ps.playlist.size()) { + ps.playlist_index = 0; + } + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PLAY); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_PAUSE: { + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PAUSE); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_STOP: { + if (!has_internal_playlist) { + this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + ps.playlist.clear(); + ps.playlist_index = 0; + } + if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::STOP); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_NEXT: { + if (!has_internal_playlist) { + this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + if (ps.playlist_index + 1 < ps.playlist.size()) { + ps.playlist_index++; + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } else if (ps.repeat_mode == REPEAT_ALL && !ps.playlist.empty()) { + ps.playlist_index = 0; + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::NEXT); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_PREVIOUS: { + if (!has_internal_playlist) { + this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + if (ps.playlist_index > 0) { + ps.playlist_index--; + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } else if (ps.repeat_mode == REPEAT_ALL && !ps.playlist.empty()) { + ps.playlist_index = ps.playlist.size() - 1; + this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); + } + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::PREVIOUS); + } + break; + } + + case media_player::MEDIA_PLAYER_COMMAND_REPEAT_ONE: + if (!has_internal_playlist) { + ps.repeat_mode = REPEAT_ONE; + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::REPEAT_ONE); + } + break; + + case media_player::MEDIA_PLAYER_COMMAND_REPEAT_OFF: + if (!has_internal_playlist) { + ps.repeat_mode = REPEAT_OFF; + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::REPEAT_OFF); + } + break; + + case media_player::MEDIA_PLAYER_COMMAND_REPEAT_ALL: + if (!has_internal_playlist) { + ps.repeat_mode = REPEAT_ALL; + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::REPEAT_ALL); + } + break; + + case media_player::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST: { + if (!has_internal_playlist) { + this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + if (ps.playlist_index < ps.playlist.size()) { + ps.playlist[0] = std::move(ps.playlist[ps.playlist_index]); + ps.playlist.resize(1); + ps.playlist_index = 0; + } else { + ps.playlist.clear(); + ps.playlist_index = 0; + } + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::CLEAR_PLAYLIST); + } + break; + } + + default: + // TURN_ON, TURN_OFF, ENQUEUE (handled separately with URL), SHUFFLE/UNSHUFFLE (PR3) are no-ops + break; + } +} + // THREAD CONTEXT: Called from main loop only. Entry points: // - HA/automation commands (direct) // - handle_play_uri_request_() via make_call().perform() (deferred from source tasks) @@ -406,10 +621,17 @@ void SpeakerSourceMediaPlayer::control(const media_player::MediaPlayerCall &call auto media_url = call.get_media_url(); if (media_url.has_value()) { - control_command.type = MediaPlayerControlCommand::PLAY_URI; + auto command = call.get_command(); + bool enqueue = command.has_value() && command.value() == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE; + + if (enqueue) { + control_command.type = MediaPlayerControlCommand::ENQUEUE_URI; + } else { + control_command.type = MediaPlayerControlCommand::PLAY_URI; + } // Heap allocation is unavoidable: URIs from Home Assistant are arbitrary-length (media URLs with tokens - // can easily exceed 500 bytes). Deleted after the command is consumed. FreeRTOS queues require items to be - // copyable, so we store a pointer to the string in the queue rather than the string itself. + // can easily exceed 500 bytes). Deleted in process_control_queue_() after the command is consumed. FreeRTOS queues + // require items to be copyable, so we store a pointer to the string in the queue rather than the string itself. control_command.data.uri = new std::string(media_url.value()); if (xQueueSend(this->media_control_command_queue_, &control_command, 0) != pdTRUE) { delete control_command.data.uri; @@ -454,6 +676,9 @@ void SpeakerSourceMediaPlayer::control(const media_player::MediaPlayerCall &call } media_player::MediaPlayerTraits SpeakerSourceMediaPlayer::get_traits() { + // This media player supports more traits like playlists, repeat, and shuffle, but the ESPHome API currently (March + // 2026) doesn't support those commands, so we only report pause support for now since that's used by the frontend and + // supported by our player. auto traits = media_player::MediaPlayerTraits(); traits.set_supports_pause(true); diff --git a/esphome/components/speaker_source/speaker_source_media_player.h b/esphome/components/speaker_source/speaker_source_media_player.h index 7896fef295..0967084504 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.h +++ b/esphome/components/speaker_source/speaker_source_media_player.h @@ -29,7 +29,8 @@ namespace esphome::speaker_source { // - Main loop task: setup(), loop(), dump_config(), handle_media_state_changed_(), // handle_volume_request_(), handle_mute_request_(), handle_play_uri_request_(), // set_volume_(), set_mute_state_(), control(), get_media_pipeline_state_(), -// find_source_for_uri_(), try_execute_play_uri_(), save_volume_restore_state_() +// find_source_for_uri_(), try_execute_play_uri_(), save_volume_restore_state_(), +// process_control_queue_(), handle_player_command_(), queue_command_(), queue_play_current_() // // - Media source task(s): handle_media_output_() via SourceBinding::write_audio(). // Called from each source's decode task thread when streaming audio data. @@ -49,13 +50,19 @@ namespace esphome::speaker_source { // - defer(): SourceBinding::request_volume/request_mute/request_play_uri -> main loop // - Atomic fields (active_source, pending_frames): shared between all three thread contexts // -// Non-atomic pipeline fields (last_source, stopping_source, pending_source) are only accessed -// from the main loop thread. +// Non-atomic pipeline fields (last_source, stopping_source, pending_source, playlist, +// playlist_index, repeat_mode) are only accessed from the main loop thread. enum Pipeline : uint8_t { MEDIA_PIPELINE = 0, }; +enum RepeatMode : uint8_t { + REPEAT_OFF = 0, + REPEAT_ONE = 1, + REPEAT_ALL = 2, +}; + // Forward declaration class SpeakerSourceMediaPlayer; @@ -79,6 +86,9 @@ struct SourceBinding : public media_source::MediaSourceListener { }; struct PipelineContext { + /// @brief Timeout IDs for playlist delay, indexed by Pipeline enum + static constexpr const char *const TIMEOUT_IDS[] = {"next_media"}; + speaker::Speaker *speaker{nullptr}; optional<media_player::MediaPlayerSupportedFormat> format; @@ -92,6 +102,14 @@ struct PipelineContext { // Uses std::vector because the count varies across instances (multiple speaker_source media players may exist). std::vector<std::unique_ptr<SourceBinding>> sources; + // Dynamic allocation is unavoidable here: URIs from Home Assistant are arbitrary-length strings + // (media URLs with tokens can easily exceed 500 bytes), and playlist size is unbounded. + // Pre-allocating fixed buffers would waste significant RAM when idle without covering worst cases. + std::vector<std::string> playlist; + size_t playlist_index{0}; + RepeatMode repeat_mode{REPEAT_OFF}; + uint32_t playlist_delay_ms{0}; + // Track frames sent to speaker to correlate with playback callbacks. // Atomic because it is written from the main loop/source tasks and read/decremented from the speaker playback // callback. @@ -103,14 +121,17 @@ struct PipelineContext { struct MediaPlayerControlCommand { enum Type : uint8_t { - PLAY_URI, // Find a source that can handle this URI and play it - SEND_COMMAND, // Send command to active source + PLAY_URI, // Clear playlist, reset index, add URI, queue PLAY_CURRENT + ENQUEUE_URI, // Add URI to playlist, queue PLAY_CURRENT if idle + PLAYLIST_ADVANCE, // Advance index (or wrap for repeat_all), queue PLAY_CURRENT if more items + PLAY_CURRENT, // Play item at current playlist index (can retry if speaker not ready) + SEND_COMMAND, // Send command to active source }; Type type; uint8_t pipeline; union { - std::string *uri; // Owned pointer, must delete after xQueueReceive (for PLAY_URI) + std::string *uri; // Owned pointer, must delete after xQueueReceive (for PLAY_URI and ENQUEUE_URI) media_player::MediaPlayerCommand command; } data; }; @@ -154,6 +175,8 @@ class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPla Trigger<> *get_unmute_trigger() { return &this->unmute_trigger_; } Trigger<float> *get_volume_trigger() { return &this->volume_trigger_; } + void set_playlist_delay_ms(uint8_t pipeline, uint32_t delay_ms); + protected: // Callbacks from source bindings (pipeline index is captured at binding creation time) size_t handle_media_output_(uint8_t pipeline, media_source::MediaSource *source, const uint8_t *data, size_t length, @@ -183,11 +206,20 @@ class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPla /// @brief Determine media player state from the media pipeline's active source /// @param media_source Active source for the media pipeline (may be nullptr) + /// @param playlist_active Whether the media pipeline's playlist is in progress + /// @param old_state Previous media player state (used for transition smoothing) /// @return The appropriate MediaPlayerState - media_player::MediaPlayerState get_media_pipeline_state_(media_source::MediaSource *media_source) const; + media_player::MediaPlayerState get_media_pipeline_state_(media_source::MediaSource *media_source, + bool playlist_active, + media_player::MediaPlayerState old_state) const; + void process_control_queue_(); + void handle_player_command_(media_player::MediaPlayerCommand player_command, uint8_t pipeline); bool try_execute_play_uri_(const std::string &uri, uint8_t pipeline); media_source::MediaSource *find_source_for_uri_(const std::string &uri, uint8_t pipeline); + void queue_command_(MediaPlayerControlCommand::Type type, uint8_t pipeline); + void queue_play_current_(uint8_t pipeline, uint32_t delay_ms = 0); + QueueHandle_t media_control_command_queue_; // Pipeline context for media pipeline. See THREADING MODEL at top of namespace for access rules. diff --git a/tests/components/speaker_source/common.yaml b/tests/components/speaker_source/common.yaml index cfcb065f57..9e4c309c06 100644 --- a/tests/components/speaker_source/common.yaml +++ b/tests/components/speaker_source/common.yaml @@ -41,3 +41,8 @@ media_player: on_unmute: - media_player.play: id: media_player_id + on_volume: + - speaker_source.set_playlist_delay: + id: media_player_id + pipeline: media + delay: 500ms From 3d4ebe74ce2dc7948d2163cdf11f7f89be3c6dec Mon Sep 17 00:00:00 2001 From: Big Mike <mikelawrence@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:00:42 -0500 Subject: [PATCH 1283/2030] [sensirion_common] Use SmallBufferWithHeapFallback helper (#14270) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../sensirion_common/i2c_sensirion.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/components/sensirion_common/i2c_sensirion.cpp b/esphome/components/sensirion_common/i2c_sensirion.cpp index 0279e08b9f..6e244faf59 100644 --- a/esphome/components/sensirion_common/i2c_sensirion.cpp +++ b/esphome/components/sensirion_common/i2c_sensirion.cpp @@ -12,24 +12,25 @@ static const char *const TAG = "sensirion_i2c"; static const size_t BUFFER_STACK_SIZE = 16; bool SensirionI2CDevice::read_data(uint16_t *data, const uint8_t len) { - const size_t num_bytes = len * 3; - uint8_t buf[num_bytes]; + const size_t required_buffer_len = len * 3; + SmallBufferWithHeapFallback<BUFFER_STACK_SIZE> buffer(required_buffer_len); + uint8_t *temp = buffer.get(); - this->last_error_ = this->read(buf, num_bytes); + this->last_error_ = this->read(temp, required_buffer_len); if (this->last_error_ != i2c::ERROR_OK) { return false; } - for (uint8_t i = 0; i < len; i++) { - const uint8_t j = 3 * i; + for (size_t i = 0; i < len; i++) { + const size_t j = i * 3; // Use MSB first since Sensirion devices use CRC-8 with MSB first - uint8_t crc = crc8(&buf[j], 2, 0xFF, CRC_POLYNOMIAL, true); - if (crc != buf[j + 2]) { - ESP_LOGE(TAG, "CRC invalid @ %d! 0x%02X != 0x%02X", i, buf[j + 2], crc); + uint8_t crc = crc8(&temp[j], 2, 0xFF, CRC_POLYNOMIAL, true); + if (crc != temp[j + 2]) { + ESP_LOGE(TAG, "CRC invalid @ %zu! 0x%02X != 0x%02X", i, temp[j + 2], crc); this->last_error_ = i2c::ERROR_CRC; return false; } - data[i] = encode_uint16(buf[j], buf[j + 1]); + data[i] = encode_uint16(temp[j], temp[j + 1]); } return true; } From b27165a8427cb45044f7795cb46a3d6d2835cb52 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 11 Mar 2026 13:11:00 -0500 Subject: [PATCH 1284/2030] [speaker_source] Add shuffle support (#14653) --- .../speaker_source_media_player.cpp | 90 +++++++++++++++++-- .../speaker_source_media_player.h | 13 +++ tests/components/speaker_source/common.yaml | 4 +- 3 files changed, 100 insertions(+), 7 deletions(-) diff --git a/esphome/components/speaker_source/speaker_source_media_player.cpp b/esphome/components/speaker_source/speaker_source_media_player.cpp index 3724e20667..cf7169df6a 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.cpp +++ b/esphome/components/speaker_source/speaker_source_media_player.cpp @@ -5,6 +5,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <algorithm> + namespace esphome::speaker_source { static constexpr uint32_t MEDIA_CONTROLS_QUEUE_LENGTH = 20; @@ -383,7 +385,8 @@ void SpeakerSourceMediaPlayer::process_control_queue_() { // Always use our local playlist to start playback this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); ps.playlist.clear(); - ps.playlist_index = 0; // Reset index + ps.shuffle_indices.clear(); // Clear shuffle when starting fresh playlist + ps.playlist_index = 0; // Reset index ps.playlist.push_back(*control_command.data.uri); // Queue PLAY_CURRENT to initiate playback @@ -396,6 +399,11 @@ void SpeakerSourceMediaPlayer::process_control_queue_() { // Always add to our local playlist ps.playlist.push_back(*control_command.data.uri); + // If shuffle is active, add the new item to the end of the shuffle order + if (!ps.shuffle_indices.empty()) { + ps.shuffle_indices.push_back(ps.playlist.size() - 1); + } + // If nothing is playing and no upcoming items are queued, start the new item. bool nothing_playing = (active_source == nullptr) || (active_source->get_state() == media_source::MediaSourceState::IDLE); @@ -425,9 +433,10 @@ void SpeakerSourceMediaPlayer::process_control_queue_() { } case MediaPlayerControlCommand::PLAY_CURRENT: { - // Play the item at current playlist index + // Play the item at current playlist index (mapped through shuffle if active) if (ps.playlist_index < ps.playlist.size()) { - command_executed = this->try_execute_play_uri_(ps.playlist[ps.playlist_index], pipeline); + size_t actual_position = this->get_playlist_position_(pipeline); + command_executed = this->try_execute_play_uri_(ps.playlist[actual_position], pipeline); } else { command_executed = true; // Index out of bounds or empty playlist } @@ -521,6 +530,7 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC if (!has_internal_playlist) { this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); ps.playlist.clear(); + ps.shuffle_indices.clear(); ps.playlist_index = 0; } if (target_source != nullptr) { @@ -589,21 +599,39 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC if (!has_internal_playlist) { this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); if (ps.playlist_index < ps.playlist.size()) { - ps.playlist[0] = std::move(ps.playlist[ps.playlist_index]); + size_t actual_position = this->get_playlist_position_(pipeline); + ps.playlist[0] = std::move(ps.playlist[actual_position]); ps.playlist.resize(1); ps.playlist_index = 0; } else { ps.playlist.clear(); ps.playlist_index = 0; } + ps.shuffle_indices.clear(); } else if (target_source != nullptr) { target_source->handle_command(media_source::MediaSourceCommand::CLEAR_PLAYLIST); } break; } + case media_player::MEDIA_PLAYER_COMMAND_SHUFFLE: + if (!has_internal_playlist) { + this->shuffle_playlist_(pipeline); + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::SHUFFLE); + } + break; + + case media_player::MEDIA_PLAYER_COMMAND_UNSHUFFLE: + if (!has_internal_playlist) { + this->unshuffle_playlist_(pipeline); + } else if (target_source != nullptr) { + target_source->handle_command(media_source::MediaSourceCommand::UNSHUFFLE); + } + break; + default: - // TURN_ON, TURN_OFF, ENQUEUE (handled separately with URL), SHUFFLE/UNSHUFFLE (PR3) are no-ops + // TURN_ON, TURN_OFF, ENQUEUE (handled separately with URL) are no-ops break; } } @@ -766,6 +794,58 @@ void SpeakerSourceMediaPlayer::set_volume_(float volume, bool publish) { this->defer([this, volume]() { this->volume_trigger_.trigger(volume); }); } +size_t SpeakerSourceMediaPlayer::get_playlist_position_(uint8_t pipeline) const { + const PipelineContext &ps = this->pipelines_[pipeline]; + + if (ps.shuffle_indices.empty() || ps.playlist_index >= ps.shuffle_indices.size()) { + return ps.playlist_index; + } + return ps.shuffle_indices[ps.playlist_index]; +} + +void SpeakerSourceMediaPlayer::shuffle_playlist_(uint8_t pipeline) { + PipelineContext &ps = this->pipelines_[pipeline]; + + if (ps.playlist.size() <= 1) { + ps.shuffle_indices.clear(); + return; + } + + // Capture current actual position BEFORE modifying shuffle_indices + size_t current_actual = this->get_playlist_position_(pipeline); + + // Build indices vector + ps.shuffle_indices.resize(ps.playlist.size()); + for (size_t i = 0; i < ps.playlist.size(); i++) { + ps.shuffle_indices[i] = i; + } + + // Fisher-Yates shuffle using ESPHome's random helper + for (size_t i = ps.shuffle_indices.size() - 1; i > 0; i--) { + size_t j = random_uint32() % (i + 1); + std::swap(ps.shuffle_indices[i], ps.shuffle_indices[j]); + } + + // Move current track to current position (so playback continues seamlessly) + if (ps.playlist_index < ps.shuffle_indices.size()) { + for (size_t i = 0; i < ps.shuffle_indices.size(); i++) { + if (ps.shuffle_indices[i] == current_actual) { + std::swap(ps.shuffle_indices[i], ps.shuffle_indices[ps.playlist_index]); + break; + } + } + } +} + +void SpeakerSourceMediaPlayer::unshuffle_playlist_(uint8_t pipeline) { + PipelineContext &ps = this->pipelines_[pipeline]; + + if (!ps.shuffle_indices.empty() && ps.playlist_index < ps.shuffle_indices.size()) { + ps.playlist_index = ps.shuffle_indices[ps.playlist_index]; + } + ps.shuffle_indices.clear(); +} + } // namespace esphome::speaker_source #endif // USE_ESP32 diff --git a/esphome/components/speaker_source/speaker_source_media_player.h b/esphome/components/speaker_source/speaker_source_media_player.h index 0967084504..4fbb534110 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.h +++ b/esphome/components/speaker_source/speaker_source_media_player.h @@ -110,6 +110,10 @@ struct PipelineContext { RepeatMode repeat_mode{REPEAT_OFF}; uint32_t playlist_delay_ms{0}; + // When non-empty, playlist_index indexes into these vectors + // which contain the actual playlist indices in shuffled order + std::vector<size_t> shuffle_indices; + // Track frames sent to speaker to correlate with playback callbacks. // Atomic because it is written from the main loop/source tasks and read/decremented from the speaker playback // callback. @@ -220,6 +224,15 @@ class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPla void queue_command_(MediaPlayerControlCommand::Type type, uint8_t pipeline); void queue_play_current_(uint8_t pipeline, uint32_t delay_ms = 0); + /// @brief Maps playlist_index through shuffle indices if shuffle is active + size_t get_playlist_position_(uint8_t pipeline) const; + + /// @brief Generates shuffled indices for the playlist, keeping current track at current position + void shuffle_playlist_(uint8_t pipeline); + + /// @brief Clears shuffle indices and adjusts playlist_index to maintain current track + void unshuffle_playlist_(uint8_t pipeline); + QueueHandle_t media_control_command_queue_; // Pipeline context for media pipeline. See THREADING MODEL at top of namespace for access rules. diff --git a/tests/components/speaker_source/common.yaml b/tests/components/speaker_source/common.yaml index 9e4c309c06..05b5181dfd 100644 --- a/tests/components/speaker_source/common.yaml +++ b/tests/components/speaker_source/common.yaml @@ -36,10 +36,10 @@ media_player: sources: - audio_file_source on_mute: - - media_player.pause: + - media_player.shuffle: id: media_player_id on_unmute: - - media_player.play: + - media_player.unshuffle: id: media_player_id on_volume: - speaker_source.set_playlist_delay: From 03c0ce704b0c89a87f1fe2b67dbbcb6a74eb9688 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:22:48 -0400 Subject: [PATCH 1285/2030] Bump pyupgrade to v3.21.2 for Python 3.14 compatibility (#14699) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b036da6ef1..2d8f698395 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 + rev: v3.21.2 hooks: - id: pyupgrade args: [--py311-plus] From 04bcd9f56ba24d40199f8f4cadf7761429bc942c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:25:36 -0400 Subject: [PATCH 1286/2030] [dashboard] Use sys.executable for dashboard subprocess commands (#14698) Co-authored-by: Jonathan Swoboda <swoboda1337@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/__main__.py | 13 +++++++------ esphome/dashboard/const.py | 5 ++++- esphome/dashboard/web_server.py | 6 +++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 58b995e8df..4b0fc2cec7 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -74,6 +74,8 @@ from esphome.util import ( _LOGGER = logging.getLogger(__name__) +ESPHOME_COMMAND = [sys.executable, "-m", "esphome"] + # Maximum buffer size for serial log reading to prevent unbounded memory growth SERIAL_BUFFER_MAX_SIZE = 65536 @@ -1307,9 +1309,8 @@ def command_update_all(args: ArgsProtocol) -> int | None: files = list_yaml_files(args.configuration) def build_command(f): - if CORE.dashboard: - return ["esphome", "--dashboard", "run", f, "--no-logs", "--device", "OTA"] - return ["esphome", "run", f, "--no-logs", "--device", "OTA"] + dashboard = ["--dashboard"] if CORE.dashboard else [] + return [*ESPHOME_COMMAND, *dashboard, "run", f, "--no-logs", "--device", "OTA"] return run_multiple_configs(files, build_command) @@ -1458,7 +1459,7 @@ def command_rename(args: ArgsProtocol, config: ConfigType) -> int | None: new_path.write_text(new_raw, encoding="utf-8") - rc = run_external_process("esphome", "config", str(new_path)) + rc = run_external_process(*ESPHOME_COMMAND, "config", str(new_path)) if rc != 0: print(color(AnsiFore.BOLD_RED, "Rename failed. Reverting changes.")) new_path.unlink() @@ -1476,7 +1477,7 @@ def command_rename(args: ArgsProtocol, config: ConfigType) -> int | None: cli_args.insert(0, "--dashboard") try: - rc = run_external_process("esphome", *cli_args) + rc = run_external_process(*ESPHOME_COMMAND, *cli_args) except KeyboardInterrupt: rc = 1 if rc != 0: @@ -1873,7 +1874,7 @@ def run_esphome(argv): # argv[0] is the program path, skip it since we prefix with "esphome" def build_command(f): return ( - ["esphome"] + [*ESPHOME_COMMAND] + [arg for arg in argv[1:] if arg not in args.configuration] + [str(f)] ) diff --git a/esphome/dashboard/const.py b/esphome/dashboard/const.py index ada5575d0e..9cadc442ef 100644 --- a/esphome/dashboard/const.py +++ b/esphome/dashboard/const.py @@ -1,5 +1,7 @@ from __future__ import annotations +import sys + from esphome.enum import StrEnum @@ -26,4 +28,5 @@ MAX_EXECUTOR_WORKERS = 48 SENTINEL = object() -DASHBOARD_COMMAND = ["esphome", "--dashboard"] +ESPHOME_COMMAND = [sys.executable, "-m", "esphome"] +DASHBOARD_COMMAND = [*ESPHOME_COMMAND, "--dashboard"] diff --git a/esphome/dashboard/web_server.py b/esphome/dashboard/web_server.py index 92cab929ef..b8e17244e5 100644 --- a/esphome/dashboard/web_server.py +++ b/esphome/dashboard/web_server.py @@ -52,7 +52,7 @@ from esphome.util import get_serial_ports, shlex_quote from esphome.yaml_util import FastestAvailableSafeLoader from ..helpers import write_file -from .const import DASHBOARD_COMMAND, DashboardEvent +from .const import DASHBOARD_COMMAND, ESPHOME_COMMAND, DashboardEvent from .core import DASHBOARD, ESPHomeDashboard, Event from .entries import UNKNOWN_STATE, DashboardEntry, entry_state_to_bool from .models import build_device_list_response @@ -1079,7 +1079,7 @@ class DownloadBinaryRequestHandler(BaseHandler): return if not path.is_file(): - args = ["esphome", "idedata", settings.rel_path(configuration)] + args = [*ESPHOME_COMMAND, "idedata", settings.rel_path(configuration)] rc, stdout, _ = await async_run_system_command(args) if rc != 0: @@ -1462,7 +1462,7 @@ class JsonConfigRequestHandler(BaseHandler): self.send_error(404) return - args = ["esphome", "config", str(filename), "--show-secrets"] + args = [*ESPHOME_COMMAND, "config", str(filename), "--show-secrets"] rc, stdout, stderr = await async_run_system_command(args) From bef5e4de9c0a89f319c9f7124814cf7390fb922e Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 11 Mar 2026 13:29:17 -0500 Subject: [PATCH 1287/2030] [speaker_source] Add announcement pipeline (#14654) --- .../components/speaker_source/media_player.py | 125 +++++++++++++----- .../speaker_source_media_player.cpp | 74 +++++++++-- .../speaker_source_media_player.h | 27 ++-- tests/components/speaker_source/common.yaml | 21 ++- 4 files changed, 186 insertions(+), 61 deletions(-) diff --git a/esphome/components/speaker_source/media_player.py b/esphome/components/speaker_source/media_player.py index 9080bebcae..fe50536e8f 100644 --- a/esphome/components/speaker_source/media_player.py +++ b/esphome/components/speaker_source/media_player.py @@ -20,6 +20,7 @@ DEPENDENCIES = ["media_source", "speaker"] CODEOWNERS = ["@kahrendt"] +CONF_ANNOUNCEMENT_PIPELINE = "announcement_pipeline" CONF_MEDIA_PIPELINE = "media_pipeline" CONF_ON_MUTE = "on_mute" CONF_PIPELINE = "pipeline" @@ -42,6 +43,19 @@ PipelineContext = speaker_source_ns.struct("PipelineContext") Pipeline = speaker_source_ns.enum("Pipeline") PIPELINE_ENUM = { "media": Pipeline.MEDIA_PIPELINE, + "announcement": Pipeline.ANNOUNCEMENT_PIPELINE, +} + +# Maps config key -> (C++ Pipeline enum value, format purpose) +_PIPELINE_INFO = { + CONF_MEDIA_PIPELINE: ( + Pipeline.MEDIA_PIPELINE, + media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["default"], + ), + CONF_ANNOUNCEMENT_PIPELINE: ( + Pipeline.ANNOUNCEMENT_PIPELINE, + media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["announcement"], + ), } SetPlaylistDelayAction = speaker_source_ns.class_( @@ -59,7 +73,7 @@ FORMAT_MAPPING = { # Returns a media_player.MediaPlayerSupportedFormat struct with the configured # format, sample rate, number of channels, purpose, and bytes per sample -def _get_supported_format_struct(pipeline: ConfigType): +def _get_supported_format_struct(pipeline: ConfigType, purpose: MockObj): args = [ media_player.MediaPlayerSupportedFormat, ] @@ -68,7 +82,7 @@ def _get_supported_format_struct(pipeline: ConfigType): args.append(("sample_rate", pipeline[CONF_SAMPLE_RATE])) args.append(("num_channels", pipeline[CONF_NUM_CHANNELS])) - args.append(("purpose", media_player.MEDIA_PLAYER_FORMAT_PURPOSE_ENUM["default"])) + args.append(("purpose", purpose)) # Omit sample_bytes for MP3: ffmpeg transcoding in Home Assistant fails # if the number of bytes per sample is specified for MP3. @@ -115,6 +129,40 @@ PIPELINE_SCHEMA = cv.Schema( ) +def _validate_no_shared_resources(config: ConfigType) -> ConfigType: + announcement_config = config.get(CONF_ANNOUNCEMENT_PIPELINE) + media_config = config.get(CONF_MEDIA_PIPELINE) + + # Check for duplicates within each pipeline + for pipeline_key in (CONF_ANNOUNCEMENT_PIPELINE, CONF_MEDIA_PIPELINE): + if pipeline_config := config.get(pipeline_key): + source_ids = [s.id for s in pipeline_config[CONF_SOURCES]] + if len(source_ids) != len(set(source_ids)): + raise cv.Invalid( + f"Duplicate media sources in {pipeline_key}. " + "Each media source can only appear once per pipeline." + ) + + # Check for sources shared between pipelines + if announcement_config and media_config: + if announcement_config[CONF_SPEAKER] == media_config[CONF_SPEAKER]: + raise cv.Invalid( + "The announcement and media pipelines cannot use the same speaker. " + "Use the `mixer` speaker component to create two source speakers." + ) + + announcement_source_ids = {s.id for s in announcement_config[CONF_SOURCES]} + media_source_ids = {s.id for s in media_config[CONF_SOURCES]} + shared = announcement_source_ids & media_source_ids + if shared: + raise cv.Invalid( + f"Media sources cannot be shared between pipelines: {', '.join(shared)}. " + "Create separate media source instances for each pipeline." + ) + + return config + + def _validate_volume_settings(config: ConfigType) -> ConfigType: # CONF_VOLUME_INITIAL is in the scaled volume domain (0.0-1.0) and doesn't need to be validated if config[CONF_VOLUME_MIN] > config[CONF_VOLUME_MAX]: @@ -131,7 +179,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_VOLUME_INITIAL, default=0.5): cv.percentage, cv.Optional(CONF_VOLUME_MAX, default=1.0): cv.percentage, cv.Optional(CONF_VOLUME_MIN, default=0.0): cv.percentage, - cv.Required(CONF_MEDIA_PIPELINE): PIPELINE_SCHEMA, + cv.Optional(CONF_ANNOUNCEMENT_PIPELINE): PIPELINE_SCHEMA, + cv.Optional(CONF_MEDIA_PIPELINE): PIPELINE_SCHEMA, cv.Optional(CONF_ON_MUTE): automation.validate_automation(single=True), cv.Optional(CONF_ON_UNMUTE): automation.validate_automation(single=True), cv.Optional(CONF_ON_VOLUME): automation.validate_automation(single=True), @@ -140,23 +189,37 @@ CONFIG_SCHEMA = cv.All( .extend(cv.COMPONENT_SCHEMA) .extend(media_player.media_player_schema(SpeakerSourceMediaPlayer)), cv.only_on_esp32, + cv.has_at_least_one_key(CONF_ANNOUNCEMENT_PIPELINE, CONF_MEDIA_PIPELINE), + _validate_no_shared_resources, _validate_volume_settings, ) def _final_validate_codecs(config: ConfigType) -> ConfigType: - pipeline = config[CONF_MEDIA_PIPELINE] - fmt = pipeline[CONF_FORMAT] - if fmt == "NONE": + # "NONE" means the pipeline accepts any format at runtime, so all optional codecs must be available. + # When a specific format is set, only that codec is requested. + needed_formats: set[str] = set() + need_all = False + + for pipeline_key in (CONF_ANNOUNCEMENT_PIPELINE, CONF_MEDIA_PIPELINE): + if pipeline := config.get(pipeline_key): + fmt = pipeline[CONF_FORMAT] + if fmt == "NONE": + need_all = True + else: + needed_formats.add(fmt) + + if need_all: audio.request_flac_support() audio.request_mp3_support() audio.request_opus_support() - elif fmt == "FLAC": - audio.request_flac_support() - elif fmt == "MP3": - audio.request_mp3_support() - elif fmt == "OPUS": - audio.request_opus_support() + else: + if "FLAC" in needed_formats: + audio.request_flac_support() + if "MP3" in needed_formats: + audio.request_mp3_support() + if "OPUS" in needed_formats: + audio.request_opus_support() return config @@ -164,7 +227,8 @@ def _final_validate_codecs(config: ConfigType) -> ConfigType: FINAL_VALIDATE_SCHEMA = cv.All( cv.Schema( { - cv.Required(CONF_MEDIA_PIPELINE): _validate_pipeline, + cv.Optional(CONF_ANNOUNCEMENT_PIPELINE): _validate_pipeline, + cv.Optional(CONF_MEDIA_PIPELINE): _validate_pipeline, }, extra=cv.ALLOW_EXTRA, ), @@ -182,26 +246,25 @@ async def to_code(config: ConfigType) -> None: cg.add(var.set_volume_max(config[CONF_VOLUME_MAX])) cg.add(var.set_volume_min(config[CONF_VOLUME_MIN])) - pipeline_config = config[CONF_MEDIA_PIPELINE] - pipeline_enum = Pipeline.MEDIA_PIPELINE + for pipeline_key, (pipeline_enum, purpose) in _PIPELINE_INFO.items(): + if pipeline_config := config.get(pipeline_key): + for source in pipeline_config[CONF_SOURCES]: + src = await cg.get_variable(source) + cg.add(var.add_media_source(pipeline_enum, src)) - for source in pipeline_config[CONF_SOURCES]: - src = await cg.get_variable(source) - cg.add(var.add_media_source(pipeline_enum, src)) - - cg.add( - var.set_speaker( - pipeline_enum, - await cg.get_variable(pipeline_config[CONF_SPEAKER]), - ) - ) - if pipeline_config[CONF_FORMAT] != "NONE": - cg.add( - var.set_format( - pipeline_enum, - _get_supported_format_struct(pipeline_config), + cg.add( + var.set_speaker( + pipeline_enum, + await cg.get_variable(pipeline_config[CONF_SPEAKER]), + ) ) - ) + if pipeline_config[CONF_FORMAT] != "NONE": + cg.add( + var.set_format( + pipeline_enum, + _get_supported_format_struct(pipeline_config, purpose), + ) + ) if on_mute := config.get(CONF_ON_MUTE): await automation.build_automation( diff --git a/esphome/components/speaker_source/speaker_source_media_player.cpp b/esphome/components/speaker_source/speaker_source_media_player.cpp index cf7169df6a..9d02ac9c74 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.cpp +++ b/esphome/components/speaker_source/speaker_source_media_player.cpp @@ -128,6 +128,7 @@ void SpeakerSourceMediaPlayer::handle_play_uri_request_(uint8_t pipeline, const // Smart source is requesting the player to play a different URI auto call = this->make_call(); call.set_media_url(uri); + call.set_announcement(pipeline == ANNOUNCEMENT_PIPELINE); call.perform(); } @@ -209,7 +210,7 @@ size_t SpeakerSourceMediaPlayer::handle_media_output_(uint8_t pipeline, media_so } // THREAD CONTEXT: Called from main loop (loop) -media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_media_pipeline_state_( +media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_source_state_( media_source::MediaSource *source, bool playlist_active, media_player::MediaPlayerState old_state) const { if (source != nullptr) { switch (source->get_state()) { @@ -218,7 +219,7 @@ media_player::MediaPlayerState SpeakerSourceMediaPlayer::get_media_pipeline_stat case media_source::MediaSourceState::PAUSED: return media_player::MEDIA_PLAYER_STATE_PAUSED; case media_source::MediaSourceState::ERROR: - ESP_LOGE(TAG, "Source error"); + ESP_LOGE(TAG, "Media source error"); return media_player::MEDIA_PLAYER_STATE_IDLE; case media_source::MediaSourceState::IDLE: default: @@ -237,16 +238,47 @@ void SpeakerSourceMediaPlayer::loop() { // Process queued control commands this->process_control_queue_(); - // Update state based on active sources + // Update state based on active sources - announcement pipeline takes priority media_player::MediaPlayerState old_state = this->state; + PipelineContext &ann_ps = this->pipelines_[ANNOUNCEMENT_PIPELINE]; PipelineContext &media_ps = this->pipelines_[MEDIA_PIPELINE]; // Check playlist state to detect transitions between items + bool announcement_playlist_active = (ann_ps.playlist_index < ann_ps.playlist.size()) || + (ann_ps.repeat_mode != REPEAT_OFF && !ann_ps.playlist.empty()); bool media_playlist_active = (media_ps.playlist_index < media_ps.playlist.size()) || (media_ps.repeat_mode != REPEAT_OFF && !media_ps.playlist.empty()); - this->state = this->get_media_pipeline_state_(media_ps.active_source, media_playlist_active, old_state); + // Check announcement pipeline first + media_source::MediaSource *announcement_source = ann_ps.active_source; + if (announcement_source != nullptr) { + media_source::MediaSourceState announcement_state = announcement_source->get_state(); + if (announcement_state != media_source::MediaSourceState::IDLE) { + // Announcement is active - announcements take priority and never report PAUSED + switch (announcement_state) { + case media_source::MediaSourceState::PLAYING: + case media_source::MediaSourceState::PAUSED: // Treat paused announcements as announcing + this->state = media_player::MEDIA_PLAYER_STATE_ANNOUNCING; + break; + case media_source::MediaSourceState::ERROR: + ESP_LOGE(TAG, "Announcement source error"); + // Fall through to media pipeline state + this->state = this->get_source_state_(media_ps.active_source, media_playlist_active, old_state); + break; + default: + break; + } + } else { + // Announcement source is idle, fall through to media pipeline + this->state = this->get_source_state_(media_ps.active_source, media_playlist_active, old_state); + } + } else if (announcement_playlist_active && old_state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { + this->state = media_player::MEDIA_PLAYER_STATE_ANNOUNCING; + } else { + // No active announcement, check media pipeline + this->state = this->get_source_state_(media_ps.active_source, media_playlist_active, old_state); + } if (this->state != old_state) { this->publish_state(); @@ -357,7 +389,7 @@ void SpeakerSourceMediaPlayer::set_playlist_delay_ms(uint8_t pipeline, uint32_t // The timeout callback also runs on the main loop. void SpeakerSourceMediaPlayer::queue_play_current_(uint8_t pipeline, uint32_t delay_ms) { if (delay_ms > 0) { - this->set_timeout(PipelineContext::TIMEOUT_IDS[pipeline], delay_ms, + this->set_timeout(PIPELINE_TIMEOUT_IDS[pipeline], delay_ms, [this, pipeline]() { this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); }); } else { this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); @@ -366,7 +398,7 @@ void SpeakerSourceMediaPlayer::queue_play_current_(uint8_t pipeline, uint32_t de // THREAD CONTEXT: Called from main loop (loop) void SpeakerSourceMediaPlayer::process_control_queue_() { - MediaPlayerControlCommand control_command; + MediaPlayerControlCommand control_command{}; // Use peek to check command without removing it if (xQueuePeek(this->media_control_command_queue_, &control_command, 0) != pdTRUE) { @@ -383,7 +415,7 @@ void SpeakerSourceMediaPlayer::process_control_queue_() { switch (control_command.type) { case MediaPlayerControlCommand::PLAY_URI: { // Always use our local playlist to start playback - this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + this->cancel_timeout(PIPELINE_TIMEOUT_IDS[pipeline]); ps.playlist.clear(); ps.shuffle_indices.clear(); // Clear shuffle when starting fresh playlist ps.playlist_index = 0; // Reset index @@ -528,7 +560,7 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC case media_player::MEDIA_PLAYER_COMMAND_STOP: { if (!has_internal_playlist) { - this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + this->cancel_timeout(PIPELINE_TIMEOUT_IDS[pipeline]); ps.playlist.clear(); ps.shuffle_indices.clear(); ps.playlist_index = 0; @@ -541,7 +573,7 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC case media_player::MEDIA_PLAYER_COMMAND_NEXT: { if (!has_internal_playlist) { - this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + this->cancel_timeout(PIPELINE_TIMEOUT_IDS[pipeline]); if (ps.playlist_index + 1 < ps.playlist.size()) { ps.playlist_index++; this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); @@ -557,7 +589,7 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC case media_player::MEDIA_PLAYER_COMMAND_PREVIOUS: { if (!has_internal_playlist) { - this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + this->cancel_timeout(PIPELINE_TIMEOUT_IDS[pipeline]); if (ps.playlist_index > 0) { ps.playlist_index--; this->queue_command_(MediaPlayerControlCommand::PLAY_CURRENT, pipeline); @@ -597,7 +629,7 @@ void SpeakerSourceMediaPlayer::handle_player_command_(media_player::MediaPlayerC case media_player::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST: { if (!has_internal_playlist) { - this->cancel_timeout(PipelineContext::TIMEOUT_IDS[pipeline]); + this->cancel_timeout(PIPELINE_TIMEOUT_IDS[pipeline]); if (ps.playlist_index < ps.playlist.size()) { size_t actual_position = this->get_playlist_position_(pipeline); ps.playlist[0] = std::move(ps.playlist[actual_position]); @@ -644,8 +676,24 @@ void SpeakerSourceMediaPlayer::control(const media_player::MediaPlayerCall &call return; } - MediaPlayerControlCommand control_command; - control_command.pipeline = MEDIA_PIPELINE; + MediaPlayerControlCommand control_command{}; + + // Determine which pipeline to use based on announcement flag, falling back if the preferred pipeline + // is not configured + auto announcement = call.get_announcement(); + if (announcement.has_value() && announcement.value()) { + if (this->pipelines_[ANNOUNCEMENT_PIPELINE].is_configured()) { + control_command.pipeline = ANNOUNCEMENT_PIPELINE; + } else { + control_command.pipeline = MEDIA_PIPELINE; + } + } else { + if (this->pipelines_[MEDIA_PIPELINE].is_configured()) { + control_command.pipeline = MEDIA_PIPELINE; + } else { + control_command.pipeline = ANNOUNCEMENT_PIPELINE; + } + } auto media_url = call.get_media_url(); if (media_url.has_value()) { diff --git a/esphome/components/speaker_source/speaker_source_media_player.h b/esphome/components/speaker_source/speaker_source_media_player.h index 4fbb534110..652390edd2 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.h +++ b/esphome/components/speaker_source/speaker_source_media_player.h @@ -28,7 +28,7 @@ namespace esphome::speaker_source { // // - Main loop task: setup(), loop(), dump_config(), handle_media_state_changed_(), // handle_volume_request_(), handle_mute_request_(), handle_play_uri_request_(), -// set_volume_(), set_mute_state_(), control(), get_media_pipeline_state_(), +// set_volume_(), set_mute_state_(), control(), get_source_state_(), // find_source_for_uri_(), try_execute_play_uri_(), save_volume_restore_state_(), // process_control_queue_(), handle_player_command_(), queue_command_(), queue_play_current_() // @@ -55,6 +55,7 @@ namespace esphome::speaker_source { enum Pipeline : uint8_t { MEDIA_PIPELINE = 0, + ANNOUNCEMENT_PIPELINE = 1, }; enum RepeatMode : uint8_t { @@ -85,10 +86,10 @@ struct SourceBinding : public media_source::MediaSourceListener { void request_play_uri(const std::string &uri) override; }; -struct PipelineContext { - /// @brief Timeout IDs for playlist delay, indexed by Pipeline enum - static constexpr const char *const TIMEOUT_IDS[] = {"next_media"}; +/// @brief Timeout IDs for playlist delay, indexed by Pipeline enum +static constexpr uint32_t PIPELINE_TIMEOUT_IDS[] = {1, 2}; +struct PipelineContext { speaker::Speaker *speaker{nullptr}; optional<media_player::MediaPlayerSupportedFormat> format; @@ -132,7 +133,7 @@ struct MediaPlayerControlCommand { SEND_COMMAND, // Send command to active source }; Type type; - uint8_t pipeline; + uint8_t pipeline; // MEDIA_PIPELINE or ANNOUNCEMENT_PIPELINE union { std::string *uri; // Owned pointer, must delete after xQueueReceive (for PLAY_URI and ENQUEUE_URI) @@ -208,14 +209,13 @@ class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPla /// @brief Saves the current volume and mute state to the flash for restoration. void save_volume_restore_state_(); - /// @brief Determine media player state from the media pipeline's active source - /// @param media_source Active source for the media pipeline (may be nullptr) - /// @param playlist_active Whether the media pipeline's playlist is in progress + /// @brief Determine media player state from a pipeline's active source + /// @param media_source Active source (may be nullptr) + /// @param playlist_active Whether the pipeline's playlist is in progress /// @param old_state Previous media player state (used for transition smoothing) /// @return The appropriate MediaPlayerState - media_player::MediaPlayerState get_media_pipeline_state_(media_source::MediaSource *media_source, - bool playlist_active, - media_player::MediaPlayerState old_state) const; + media_player::MediaPlayerState get_source_state_(media_source::MediaSource *media_source, bool playlist_active, + media_player::MediaPlayerState old_state) const; void process_control_queue_(); void handle_player_command_(media_player::MediaPlayerCommand player_command, uint8_t pipeline); @@ -235,8 +235,9 @@ class SpeakerSourceMediaPlayer : public Component, public media_player::MediaPla QueueHandle_t media_control_command_queue_; - // Pipeline context for media pipeline. See THREADING MODEL at top of namespace for access rules. - std::array<PipelineContext, 1> pipelines_; + // Pipeline context for media (index 0) and announcement (index 1) pipelines. + // See THREADING MODEL at top of namespace for access rules. + std::array<PipelineContext, 2> pipelines_; // Used to save volume/mute state for restoration on reboot ESPPreferenceObject pref_; diff --git a/tests/components/speaker_source/common.yaml b/tests/components/speaker_source/common.yaml index 05b5181dfd..7d663b802c 100644 --- a/tests/components/speaker_source/common.yaml +++ b/tests/components/speaker_source/common.yaml @@ -10,6 +10,11 @@ speaker: i2s_dout_pin: ${i2s_dout_pin} sample_rate: 48000 num_channels: 2 + - platform: mixer + output_speaker: speaker_id + source_speakers: + - id: announcement_mixer_speaker_id + - id: media_mixer_speaker_id audio_file: - id: test_audio @@ -19,7 +24,9 @@ audio_file: media_source: - platform: audio_file - id: audio_file_source + id: announcement_audio_file_source + - platform: audio_file + id: media_audio_file_source media_player: - platform: speaker_source @@ -29,12 +36,18 @@ media_player: volume_initial: 0.75 volume_max: 0.95 volume_min: 0.0 - media_pipeline: - speaker: speaker_id + announcement_pipeline: + speaker: announcement_mixer_speaker_id format: FLAC num_channels: 1 sources: - - audio_file_source + - announcement_audio_file_source + media_pipeline: + speaker: media_mixer_speaker_id + format: FLAC + num_channels: 1 + sources: + - media_audio_file_source on_mute: - media_player.shuffle: id: media_player_id From e7c3277eeb095a5b3e2c88ca4c7631d43528099c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:34:53 +1300 Subject: [PATCH 1288/2030] Bump version to 2026.4.0-dev --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 1a9e0b4e10..cfdb74bd19 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0-dev +PROJECT_NUMBER = 2026.4.0-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index d409514f3c..33a2526d38 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0-dev" +__version__ = "2026.4.0-dev" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 02f7aee680bb0a7b7a7a54e1b2cd759f8876d77c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Mar 2026 07:34:53 +1300 Subject: [PATCH 1289/2030] Bump version to 2026.3.0b1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 1a9e0b4e10..9f5cd0a2ce 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0-dev +PROJECT_NUMBER = 2026.3.0b1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index d409514f3c..eb49c9a1d7 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0-dev" +__version__ = "2026.3.0b1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 928f6f18660af1ffde5a1fc91f02c8a31fd43021 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Mar 2026 08:57:43 -1000 Subject: [PATCH 1290/2030] [ci] Add PR title check for unescaped angle brackets (#14701) --- .github/workflows/pr-title-check.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml index 198b9a6b25..2ad023ed1b 100644 --- a/.github/workflows/pr-title-check.yml +++ b/.github/workflows/pr-title-check.yml @@ -65,6 +65,18 @@ jobs: return; } + // Check for angle brackets not wrapped in backticks. + // Astro docs MDX treats bare < as JSX component opening tags. + const stripped = title.replace(/`[^`]*`/g, ''); + if (/[<>]/.test(stripped)) { + core.setFailed( + 'PR title contains `<` or `>` not wrapped in backticks.\n' + + 'Astro docs MDX interprets bare `<` as JSX components.\n' + + 'Please wrap angle brackets with backticks, e.g.: [component] Add `<feature>` support' + ); + return; + } + // Check title starts with [tag] prefix const bracketPattern = /^\[\w+\]/; if (!bracketPattern.test(title)) { From b6ff7185e74da275db2bef375732b26d2e125f20 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 12 Mar 2026 08:04:07 +1300 Subject: [PATCH 1291/2030] [ci] Dont run codeowners workflows on release or beta PRs (#14703) --- .github/workflows/codeowner-approved-label-update.yml | 3 +++ .github/workflows/codeowner-review-request.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/codeowner-approved-label-update.yml b/.github/workflows/codeowner-approved-label-update.yml index 0bce33ebe2..34ff934b77 100644 --- a/.github/workflows/codeowner-approved-label-update.yml +++ b/.github/workflows/codeowner-approved-label-update.yml @@ -10,6 +10,9 @@ name: Codeowner Approved Label on: pull_request_target: types: [opened, synchronize, reopened, ready_for_review] + branches-ignore: + - release + - beta permissions: issues: write diff --git a/.github/workflows/codeowner-review-request.yml b/.github/workflows/codeowner-review-request.yml index 02bf0e4a29..a89c03ba04 100644 --- a/.github/workflows/codeowner-review-request.yml +++ b/.github/workflows/codeowner-review-request.yml @@ -13,6 +13,9 @@ on: # Needs to be pull_request_target to get write permissions pull_request_target: types: [opened, reopened, synchronize, ready_for_review] + branches-ignore: + - release + - beta permissions: pull-requests: write From 73f305ff9c9c94c3ca7e7e6a3f2b8e10749a0147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 09:28:19 -1000 Subject: [PATCH 1292/2030] Bump tornado from 6.5.4 to 6.5.5 (#14704) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3da2d52b44..e634bcb104 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ PyYAML==6.0.3 paho-mqtt==1.6.1 colorama==0.4.6 icmplib==3.0.4 -tornado==6.5.4 +tornado==6.5.5 tzlocal==5.3.1 # from time tzdata>=2021.1 # from time pyserial==3.5 From a060f175ad04bf0f497a178501ca4df414b002a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 09:28:46 -1000 Subject: [PATCH 1293/2030] Bump actions/download-artifact from 8.0.0 to 8.0.1 (#14705) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c9e8c58bc..461e676c4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -945,13 +945,13 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Download target analysis JSON - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: memory-analysis-target path: ./memory-analysis continue-on-error: true - name: Download PR analysis JSON - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: memory-analysis-pr path: ./memory-analysis diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8f68e9c873..0ed41d99c7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -171,7 +171,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Download digests - uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: digests-* path: /tmp/digests From 409640c0ee441d683b2939c2235f2bee184aecaf Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:30:44 -0400 Subject: [PATCH 1294/2030] [esp32_hosted] Bump esp_hosted to 2.12.1 (#14708) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_hosted/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 6d49053d6d..a51ae2cd66 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -105,7 +105,7 @@ async def to_code(config): if framework_ver >= cv.Version(5, 5, 0): esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.4.0") esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") - esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.0") + esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.1") else: esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0") esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index acd7f7a479..f7fd3e67bc 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -20,7 +20,7 @@ dependencies: rules: - if: "target in [esp32h2, esp32p4]" espressif/esp_hosted: - version: 2.12.0 + version: 2.12.1 rules: - if: "target in [esp32h2, esp32p4]" zorxx/multipart-parser: From ddc40f44fa81f41ad8970e1e607d50d646e8f2cc Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Wed, 11 Mar 2026 19:56:25 -0500 Subject: [PATCH 1295/2030] [ethernet] ESP32-P4 Ethernet compilation fix (#14714) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../components/ethernet/ethernet_component.cpp | 18 +----------------- .../components/ethernet/ethernet_component.h | 2 ++ esphome/components/ethernet/ethernet_helpers.c | 8 ++++++++ .../components/ethernet/test.esp32-p4-idf.yaml | 1 + 4 files changed, 12 insertions(+), 17 deletions(-) create mode 100644 esphome/components/ethernet/ethernet_helpers.c create mode 100644 tests/components/ethernet/test.esp32-p4-idf.yaml diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index d6b0d40cd9..e0788e1149 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -21,22 +21,6 @@ namespace esphome::ethernet { -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) -// work around IDF compile issue on P4 https://github.com/espressif/esp-idf/pull/15637 -#ifdef USE_ESP32_VARIANT_ESP32P4 -#undef ETH_ESP32_EMAC_DEFAULT_CONFIG -#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \ - { \ - .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, .interface = EMAC_DATA_INTERFACE_RMII, \ - .clock_config = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) 50}}, \ - .dma_burst_len = ETH_DMA_BURST_LEN_32, .intr_priority = 0, \ - .emac_dataif_gpio = \ - {.rmii = {.tx_en_num = 49, .txd0_num = 34, .txd1_num = 35, .crs_dv_num = 28, .rxd0_num = 29, .rxd1_num = 30}}, \ - .clock_config_out_in = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) -1}}, \ - } -#endif -#endif - static const char *const TAG = "ethernet"; // PHY register size for hex logging @@ -162,7 +146,7 @@ void EthernetComponent::setup() { phy_config.phy_addr = this->phy_addr_; phy_config.reset_gpio_num = this->power_pin_; - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + eth_esp32_emac_config_t esp32_emac_config = eth_esp32_emac_default_config(); #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) esp32_emac_config.smi_gpio.mdc_num = this->mdc_pin_; esp32_emac_config.smi_gpio.mdio_num = this->mdio_pin_; diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index d9f05be9de..c464e20b84 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -15,6 +15,8 @@ #include "esp_mac.h" #include "esp_idf_version.h" +extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); + namespace esphome::ethernet { #ifdef USE_ETHERNET_IP_STATE_LISTENERS diff --git a/esphome/components/ethernet/ethernet_helpers.c b/esphome/components/ethernet/ethernet_helpers.c new file mode 100644 index 0000000000..96faccad24 --- /dev/null +++ b/esphome/components/ethernet/ethernet_helpers.c @@ -0,0 +1,8 @@ +#include "esp_eth_mac_esp.h" + +// ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers +// which are valid in C but not in C++. This wrapper allows C++ code to get +// the default config without replicating the macro's contents. +eth_esp32_emac_config_t eth_esp32_emac_default_config(void) { + return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG(); +} diff --git a/tests/components/ethernet/test.esp32-p4-idf.yaml b/tests/components/ethernet/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..e52329d7ea --- /dev/null +++ b/tests/components/ethernet/test.esp32-p4-idf.yaml @@ -0,0 +1 @@ +<<: !include common-ip101.yaml From 8daa946afa37e92500809cd0ad60e1fd429cb3ca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Mar 2026 15:00:20 -1000 Subject: [PATCH 1296/2030] [esp32] Add crash handler to capture and report backtrace across reboots (#14709) --- esphome/components/api/api_connection.h | 6 + esphome/components/api/client.py | 21 ++ esphome/components/esp32/__init__.py | 5 + esphome/components/esp32/core.cpp | 6 + esphome/components/esp32/crash_handler.cpp | 355 +++++++++++++++++++++ esphome/components/esp32/crash_handler.h | 18 ++ esphome/components/logger/logger_esp32.cpp | 4 + esphome/core/defines.h | 1 + esphome/platformio_api.py | 7 + tests/unit_tests/test_platformio_api.py | 28 ++ 10 files changed, 451 insertions(+) create mode 100644 esphome/components/esp32/crash_handler.cpp create mode 100644 esphome/components/esp32/crash_handler.h diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 3356511684..60cc3e91b1 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -14,6 +14,9 @@ #include "api_server.h" #include "esphome/core/application.h" #include "esphome/core/component.h" +#ifdef USE_ESP32_CRASH_HANDLER +#include "esphome/components/esp32/crash_handler.h" +#endif #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -235,6 +238,9 @@ class APIConnection final : public APIServerConnectionBase { this->flags_.log_subscription = msg.level; if (msg.dump_config) App.schedule_dump_config(); +#ifdef USE_ESP32_CRASH_HANDLER + esp32::crash_handler_log(); +#endif } #ifdef USE_API_HOMEASSISTANT_SERVICES void on_subscribe_homeassistant_services_request() override { this->flags_.service_call_subscription = true; } diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index 200d0938bd..0e71ad8fcb 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio from datetime import datetime +import importlib import logging from typing import TYPE_CHECKING, Any import warnings @@ -18,6 +19,7 @@ import contextlib from esphome.const import CONF_KEY, CONF_PORT, __version__ from esphome.core import CORE +from esphome.platformio_api import process_stacktrace from . import CONF_ENCRYPTION @@ -55,9 +57,19 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: addresses=addresses, # Pass all addresses for automatic retry ) dashboard = CORE.dashboard + backtrace_state = False + + # Try platform-specific stacktrace handler first, fall back to generic + platform_process_stacktrace = None + try: + module = importlib.import_module("esphome.components." + CORE.target_platform) + platform_process_stacktrace = getattr(module, "process_stacktrace") + except (AttributeError, ImportError): + pass def on_log(msg: SubscribeLogsResponse) -> None: """Handle a new log message.""" + nonlocal backtrace_state time_ = datetime.now() message: bytes = msg.message text = message.decode("utf8", "backslashreplace") @@ -67,6 +79,15 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: ) for parsed_msg in parse_log_message(text, timestamp): print(parsed_msg.replace("\033", "\\033") if dashboard else parsed_msg) + for raw_line in text.splitlines(): + if platform_process_stacktrace: + backtrace_state = platform_process_stacktrace( + config, raw_line, backtrace_state + ) + else: + backtrace_state = process_stacktrace( + config, raw_line, backtrace_state=backtrace_state + ) stop = await async_run(cli, on_log, name=name) try: diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 52e70501dc..475de6aa3e 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1442,6 +1442,11 @@ async def to_code(config): cg.add_build_flag("-DUSE_ESP32") cg.add_define("USE_NATIVE_64BIT_TIME") cg.add_build_flag("-Wl,-z,noexecstack") + # Arduino already wraps esp_panic_handler for its own backtrace handler, + # so only add our wrap when using ESP-IDF framework to avoid linker conflicts. + if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: + cg.add_build_flag("-Wl,--wrap=esp_panic_handler") + cg.add_define("USE_ESP32_CRASH_HANDLER") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) variant = config[CONF_VARIANT] cg.add_build_flag(f"-DUSE_ESP32_VARIANT_{variant}") diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 46c000562e..cba25bca2b 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -1,6 +1,7 @@ #ifdef USE_ESP32 #include "esphome/core/defines.h" +#include "crash_handler.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -36,6 +37,11 @@ void arch_restart() { } void arch_init() { +#ifdef USE_ESP32_CRASH_HANDLER + // Read crash data from previous boot before anything else + esp32::crash_handler_read_and_clear(); +#endif + // Enable the task watchdog only on the loop task (from which we're currently running) esp_task_wdt_add(nullptr); diff --git a/esphome/components/esp32/crash_handler.cpp b/esphome/components/esp32/crash_handler.cpp new file mode 100644 index 0000000000..ecf30d7878 --- /dev/null +++ b/esphome/components/esp32/crash_handler.cpp @@ -0,0 +1,355 @@ +#ifdef USE_ESP32 + +#include "esphome/core/defines.h" +#ifdef USE_ESP32_CRASH_HANDLER + +#include "crash_handler.h" +#include "esphome/core/log.h" + +#include <cinttypes> +#include <cstring> +#include <esp_attr.h> +#include <esp_private/panic_internal.h> +#include <soc/soc.h> + +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#include <esp_cpu_utils.h> +#include <esp_debug_helpers.h> +#include <xtensa_context.h> +#elif CONFIG_IDF_TARGET_ARCH_RISCV +#include <riscv/rvruntime-frames.h> +#endif + +static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF; +static constexpr size_t MAX_BACKTRACE = 16; + +// Check if an address looks like code (flash-mapped or IRAM). +// Must be safe to call from panic context (no flash access needed). +static inline bool IRAM_ATTR is_code_addr(uint32_t addr) { + return (addr >= SOC_IROM_LOW && addr < SOC_IROM_HIGH) || (addr >= SOC_IRAM_LOW && addr < SOC_IRAM_HIGH); +} + +#if CONFIG_IDF_TARGET_ARCH_RISCV +// Check if a code address is a real return address by verifying the preceding +// instruction is a JAL or JALR with rd=ra (x1). Called at log time (not during +// panic) so flash cache is available and both IRAM and IROM are safely readable. +static inline bool is_return_addr(uint32_t addr) { + if (!is_code_addr(addr) || addr < 4) + return false; + // A return address on the stack points to the instruction after a call. + // Check for 4-byte JAL/JALR call instruction before this address. + // Use memcpy for alignment safety — RISC-V C extension means code addresses + // are only 2-byte aligned, so addr-4 may not be 4-byte aligned. + uint32_t inst; + memcpy(&inst, (const void *) (addr - 4), sizeof(inst)); + // RISC-V instruction encoding: bits [6:0] = opcode, bits [11:7] = rd + uint32_t opcode = inst & 0x7f; // Extract 7-bit opcode + uint32_t rd = inst & 0xf80; // Extract rd field (bits 11:7) + // Match JAL (0x6f) or JALR (0x67) with rd=ra (x1, encoded as 0x80 = 1<<7) + if ((opcode == 0x6f || opcode == 0x67) && rd == 0x80) + return true; + // Check for 2-byte compressed c.jalr before this address (C extension). + // c.jalr saves to ra implicitly: funct4=1001, rs1!=0, rs2=0, op=10 + if (addr >= 2) { + uint16_t c_inst = *(uint16_t *) (addr - 2); + if ((c_inst & 0xf07f) == 0x9002 && (c_inst & 0x0f80) != 0) + return true; + } + return false; +} +#endif + +// Raw crash data written by the panic handler wrapper. +// Lives in .noinit so it survives software reset but contains garbage after power cycle. +// Validated by magic marker. Static linkage since it's only used within this file. +// Version field is first so future firmware can always identify the struct layout. +// Magic is second to validate the data. Remaining fields can change between versions. +// Version is uint32_t because it would be padded to 4 bytes anyway before the next +// uint32_t field, so we use the full width rather than wasting 3 bytes of padding. +static constexpr uint32_t CRASH_DATA_VERSION = 1; +struct RawCrashData { + uint32_t version; + uint32_t magic; + uint32_t pc; + uint8_t backtrace_count; + uint8_t reg_frame_count; // Number of entries from registers (not stack-scanned) + uint8_t exception; // panic_exception_t enum (FAULT/ABORT/IWDT/TWDT/DEBUG) + uint8_t pseudo_excause; // Whether cause is a pseudo exception (Xtensa SoC-level panic) + uint32_t backtrace[MAX_BACKTRACE]; + uint32_t cause; // Architecture-specific: exccause (Xtensa) or mcause (RISC-V) +}; +static RawCrashData __attribute__((section(".noinit"))) +s_raw_crash_data; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// Whether crash data was found and validated this boot. +static bool s_crash_data_valid = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +namespace esphome::esp32 { + +static const char *const TAG = "esp32.crash"; + +void crash_handler_read_and_clear() { + if (s_raw_crash_data.magic == CRASH_MAGIC && s_raw_crash_data.version == CRASH_DATA_VERSION) { + s_crash_data_valid = true; + // Clamp counts to prevent out-of-bounds reads from corrupt .noinit data + if (s_raw_crash_data.backtrace_count > MAX_BACKTRACE) + s_raw_crash_data.backtrace_count = MAX_BACKTRACE; + if (s_raw_crash_data.reg_frame_count > s_raw_crash_data.backtrace_count) + s_raw_crash_data.reg_frame_count = s_raw_crash_data.backtrace_count; + if (s_raw_crash_data.exception > 4) // panic_exception_t max value + s_raw_crash_data.exception = 4; // Default to PANIC_EXCEPTION_FAULT + if (s_raw_crash_data.pseudo_excause > 1) + s_raw_crash_data.pseudo_excause = 0; + } + // Clear magic regardless so we don't re-report on next normal reboot + s_raw_crash_data.magic = 0; +} + +bool crash_handler_has_data() { return s_crash_data_valid; } + +// Look up the exception cause as a human-readable string. +// Tables mirror ESP-IDF's panic_arch_fill_info() which uses local static arrays +// not exposed via any public API. +static const char *get_exception_reason() { +#if CONFIG_IDF_TARGET_ARCH_XTENSA + if (s_raw_crash_data.pseudo_excause) { + // SoC-level panic: watchdog, cache error, etc. + // Keep in sync with ESP-IDF's PANIC_RSN_* defines + static const char *const PSEUDO_REASON[] = { + "Unknown reason", // 0 + "Unhandled debug exception", // 1 + "Double exception", // 2 + "Unhandled kernel exception", // 3 + "Coprocessor exception", // 4 + "Interrupt wdt timeout on CPU0", // 5 + "Interrupt wdt timeout on CPU1", // 6 + "Cache error", // 7 + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(PSEUDO_REASON) / sizeof(PSEUDO_REASON[0])) + return PSEUDO_REASON[cause]; + return PSEUDO_REASON[0]; + } + // Real Xtensa exception + static const char *const REASON[] = { + "IllegalInstruction", + "Syscall", + "InstructionFetchError", + "LoadStoreError", + "Level1Interrupt", + "Alloca", + "IntegerDivideByZero", + "PCValue", + "Privileged", + "LoadStoreAlignment", + nullptr, + nullptr, + "InstrPDAddrError", + "LoadStorePIFDataError", + "InstrPIFAddrError", + "LoadStorePIFAddrError", + "InstTLBMiss", + "InstTLBMultiHit", + "InstFetchPrivilege", + nullptr, + "InstrFetchProhibited", + nullptr, + nullptr, + nullptr, + "LoadStoreTLBMiss", + "LoadStoreTLBMultihit", + "LoadStorePrivilege", + nullptr, + "LoadProhibited", + "StoreProhibited", + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(REASON) / sizeof(REASON[0]) && REASON[cause] != nullptr) + return REASON[cause]; +#elif CONFIG_IDF_TARGET_ARCH_RISCV + // For SoC-level panics (watchdog, cache error), mcause holds IDF-internal + // interrupt numbers, not standard RISC-V cause codes. The exception type + // field already identifies these, so just return null to use the type name. + if (s_raw_crash_data.pseudo_excause) + return nullptr; + static const char *const REASON[] = { + "Instruction address misaligned", + "Instruction access fault", + "Illegal instruction", + "Breakpoint", + "Load address misaligned", + "Load access fault", + "Store address misaligned", + "Store access fault", + "Environment call from U-mode", + "Environment call from S-mode", + nullptr, + "Environment call from M-mode", + "Instruction page fault", + "Load page fault", + nullptr, + "Store page fault", + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(REASON) / sizeof(REASON[0]) && REASON[cause] != nullptr) + return REASON[cause]; +#endif + return "Unknown"; +} + +// Exception type names matching panic_exception_t enum +static const char *get_exception_type() { + static const char *const TYPES[] = { + "Debug exception", // PANIC_EXCEPTION_DEBUG + "Interrupt wdt", // PANIC_EXCEPTION_IWDT + "Task wdt", // PANIC_EXCEPTION_TWDT + "Abort", // PANIC_EXCEPTION_ABORT + "Fault", // PANIC_EXCEPTION_FAULT + }; + uint8_t exc = s_raw_crash_data.exception; + if (exc < sizeof(TYPES) / sizeof(TYPES[0])) + return TYPES[exc]; + return "Unknown"; +} + +// Intentionally uses separate ESP_LOGE calls per line instead of combining into +// one multi-line log message. This ensures each address appears as its own line +// on the serial console, making it possible to see partial output if the device +// crashes again during boot, and allowing the CLI's process_stacktrace to match +// and decode each address individually. +void crash_handler_log() { + if (!s_crash_data_valid) + return; + + ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***"); + const char *reason = get_exception_reason(); + if (reason != nullptr) { + ESP_LOGE(TAG, " Reason: %s - %s", get_exception_type(), reason); + } else { + ESP_LOGE(TAG, " Reason: %s", get_exception_type()); + } + ESP_LOGE(TAG, " PC: 0x%08" PRIX32 " (fault location)", s_raw_crash_data.pc); + uint8_t bt_num = 0; + for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count; i++) { + uint32_t addr = s_raw_crash_data.backtrace[i]; +#if CONFIG_IDF_TARGET_ARCH_RISCV + // Register-sourced entries (MEPC/RA) are trusted; only filter stack-scanned ones. + if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr)) + continue; +#endif +#if CONFIG_IDF_TARGET_ARCH_RISCV + const char *source = (i < s_raw_crash_data.reg_frame_count) ? "backtrace" : "stack scan"; +#else + const char *source = "backtrace"; +#endif + ESP_LOGE(TAG, " BT%d: 0x%08" PRIX32 " (%s)", bt_num++, addr, source); + } + // Build addr2line hint with all captured addresses for easy copy-paste + char hint[256]; + int pos = snprintf(hint, sizeof(hint), "Use: addr2line -pfiaC -e firmware.elf 0x%08" PRIX32, s_raw_crash_data.pc); + for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count && pos < (int) sizeof(hint) - 12; i++) { + uint32_t addr = s_raw_crash_data.backtrace[i]; +#if CONFIG_IDF_TARGET_ARCH_RISCV + if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr)) + continue; +#endif + pos += snprintf(hint + pos, sizeof(hint) - pos, " 0x%08" PRIX32, addr); + } + ESP_LOGE(TAG, "%s", hint); +} + +} // namespace esphome::esp32 + +// --- Panic handler wrapper --- +// Intercepts esp_panic_handler() via --wrap linker flag to capture crash data +// into NOINIT memory before the normal panic handler runs. +// +extern "C" { +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +// Names are mandated by the --wrap linker mechanism +extern void __real_esp_panic_handler(panic_info_t *info); + +void IRAM_ATTR __wrap_esp_panic_handler(panic_info_t *info) { + // Save the faulting PC and exception info + s_raw_crash_data.pc = (uint32_t) info->addr; + s_raw_crash_data.backtrace_count = 0; + s_raw_crash_data.reg_frame_count = 0; + s_raw_crash_data.exception = (uint8_t) info->exception; + s_raw_crash_data.pseudo_excause = info->pseudo_excause ? 1 : 0; + +#if CONFIG_IDF_TARGET_ARCH_XTENSA + // Xtensa: walk the backtrace using the public API + if (info->frame != nullptr) { + auto *xt_frame = (XtExcFrame *) info->frame; + s_raw_crash_data.cause = xt_frame->exccause; + esp_backtrace_frame_t bt_frame = { + .pc = (uint32_t) xt_frame->pc, + .sp = (uint32_t) xt_frame->a1, + .next_pc = (uint32_t) xt_frame->a0, + .exc_frame = xt_frame, + }; + + uint8_t count = 0; + // First frame PC + uint32_t first_pc = esp_cpu_process_stack_pc(bt_frame.pc); + if (is_code_addr(first_pc)) { + s_raw_crash_data.backtrace[count++] = first_pc; + } + // Walk remaining frames + while (count < MAX_BACKTRACE && bt_frame.next_pc != 0) { + if (!esp_backtrace_get_next_frame(&bt_frame)) { + break; + } + uint32_t pc = esp_cpu_process_stack_pc(bt_frame.pc); + if (is_code_addr(pc)) { + s_raw_crash_data.backtrace[count++] = pc; + } + } + s_raw_crash_data.backtrace_count = count; + } + +#elif CONFIG_IDF_TARGET_ARCH_RISCV + // RISC-V: capture MEPC + RA, then scan stack for code addresses + if (info->frame != nullptr) { + auto *rv_frame = (RvExcFrame *) info->frame; + s_raw_crash_data.cause = rv_frame->mcause; + uint8_t count = 0; + + // Save MEPC (fault PC) and RA (return address) + if (is_code_addr(rv_frame->mepc)) { + s_raw_crash_data.backtrace[count++] = rv_frame->mepc; + } + if (is_code_addr(rv_frame->ra) && rv_frame->ra != rv_frame->mepc) { + s_raw_crash_data.backtrace[count++] = rv_frame->ra; + } + + // Track how many entries came from registers (MEPC/RA) so we can + // skip return-address validation for them at log time. + s_raw_crash_data.reg_frame_count = count; + + // Scan stack for code addresses — captures broadly during panic, + // filtered by is_return_addr() at log time when flash is accessible. + auto *scan_start = (uint32_t *) rv_frame->sp; + for (uint32_t i = 0; i < 64 && count < MAX_BACKTRACE; i++) { + uint32_t val = scan_start[i]; + if (is_code_addr(val) && val != rv_frame->mepc && val != rv_frame->ra) { + s_raw_crash_data.backtrace[count++] = val; + } + } + s_raw_crash_data.backtrace_count = count; + } +#endif + + // Write version and magic last — ensures all data is written before we mark it valid + s_raw_crash_data.version = CRASH_DATA_VERSION; + s_raw_crash_data.magic = CRASH_MAGIC; + + // Call the real panic handler (prints to UART, does core dump, reboots, etc.) + __real_esp_panic_handler(info); +} + +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +} // extern "C" + +#endif // USE_ESP32_CRASH_HANDLER +#endif // USE_ESP32 diff --git a/esphome/components/esp32/crash_handler.h b/esphome/components/esp32/crash_handler.h new file mode 100644 index 0000000000..97a4d4e116 --- /dev/null +++ b/esphome/components/esp32/crash_handler.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef USE_ESP32_CRASH_HANDLER + +namespace esphome::esp32 { + +/// Read crash data from NOINIT memory and clear the magic marker. +void crash_handler_read_and_clear(); + +/// Log crash data if a crash was detected on previous boot. +void crash_handler_log(); + +/// Returns true if crash data was found this boot. +bool crash_handler_has_data(); + +} // namespace esphome::esp32 + +#endif // USE_ESP32_CRASH_HANDLER diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index d6ad77ff4f..f5bf782289 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -1,6 +1,7 @@ #ifdef USE_ESP32 #include "logger.h" +#include "esphome/components/esp32/crash_handler.h" #include <esp_log.h> #include <driver/uart.h> @@ -117,6 +118,9 @@ void Logger::pre_setup() { esp_log_set_vprintf(esp_idf_log_vprintf_); ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_ESP32_CRASH_HANDLER + esp32::crash_handler_log(); +#endif } void HOT Logger::write_msg_(const char *msg, uint16_t len) { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index cec77fe2e2..a33f10cb9c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -195,6 +195,7 @@ // ESP32-specific feature flags #ifdef USE_ESP32 +#define USE_ESP32_CRASH_HANDLER #define USE_MQTT_IDF_ENQUEUE #define USE_ESPHOME_TASK_LOG_BUFFER #define USE_OTA_ROLLBACK diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 5d4065207f..cb080b2a95 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -340,6 +340,8 @@ STACKTRACE_ESP32_BACKTRACE_RE = re.compile( r"Backtrace:(?:\s*0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8})+" ) STACKTRACE_ESP32_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") +# ESP32 crash handler (stored backtrace from previous boot) +STACKTRACE_ESP32_CRASH_BT_RE = re.compile(r"BT\d+:\s*0x([0-9a-fA-F]{8})") STACKTRACE_ESP8266_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") @@ -371,6 +373,11 @@ def process_stacktrace(config, line, backtrace_state): ) _decode_pc(config, match.group(1)) + # ESP32 crash handler backtrace (from previous boot) + match = re.search(STACKTRACE_ESP32_CRASH_BT_RE, line) + if match is not None: + _decode_pc(config, match.group(1)) + # ESP32 single-line backtrace match = re.match(STACKTRACE_ESP32_BACKTRACE_RE, line) if match is not None: diff --git a/tests/unit_tests/test_platformio_api.py b/tests/unit_tests/test_platformio_api.py index 1686144277..e1b3908c24 100644 --- a/tests/unit_tests/test_platformio_api.py +++ b/tests/unit_tests/test_platformio_api.py @@ -673,6 +673,34 @@ def test_process_stacktrace_bad_alloc( assert state is False +def test_process_stacktrace_esp32_crash_handler( + setup_core: Path, mock_decode_pc: Mock +) -> None: + """Test process_stacktrace handles ESP32 crash handler backtrace lines.""" + config = {"name": "test"} + + # Simulate crash handler log lines as they appear from the API/serial + line_pc = "[E][esp32.crash:078]: PC: 0x400D1234 (fault location)" + state = platformio_api.process_stacktrace(config, line_pc, False) + # PC line is matched by existing STACKTRACE_ESP32_PC_RE + mock_decode_pc.assert_called_with(config, "400D1234") + assert state is False + + mock_decode_pc.reset_mock() + + line_bt0 = "[E][esp32.crash:080]: BT0: 0x400D5678 (backtrace)" + state = platformio_api.process_stacktrace(config, line_bt0, False) + mock_decode_pc.assert_called_once_with(config, "400D5678") + assert state is False + + mock_decode_pc.reset_mock() + + line_bt1 = "[E][esp32.crash:080]: BT1: 0x42005ABC (backtrace)" + state = platformio_api.process_stacktrace(config, line_bt1, False) + mock_decode_pc.assert_called_once_with(config, "42005ABC") + assert state is False + + def test_patch_file_downloader_succeeds_first_try() -> None: """Test patch_file_downloader succeeds on first attempt.""" mock_exception_cls = type("PackageException", (Exception,), {}) From bb7d96b954d12e99c75a02c4ebc6f12c62382942 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Thu, 12 Mar 2026 03:31:17 +0100 Subject: [PATCH 1297/2030] [const] Add UNIT_METER_PER_SECOND, UNIT_MILLILITRE, UNIT_POUND to const.py (#14713) --- esphome/const.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/const.py b/esphome/const.py index 33a2526d38..29ce030329 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1235,6 +1235,7 @@ UNIT_LITRE = "L" UNIT_LUX = "lx" UNIT_MEGAJOULE = "MJ" UNIT_METER = "m" +UNIT_METER_PER_SECOND = "m/s" UNIT_METER_PER_SECOND_SQUARED = "m/s²" UNIT_MICROAMP = "µA" UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" @@ -1244,6 +1245,7 @@ UNIT_MICROSILVERTS_PER_HOUR = "µSv/h" UNIT_MICROTESLA = "µT" UNIT_MILLIAMP = "mA" UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" +UNIT_MILLILITRE = "mL" UNIT_MILLIMETER = "mm" UNIT_MILLISECOND = "ms" UNIT_MILLISIEMENS_PER_CENTIMETER = "mS/cm" @@ -1255,6 +1257,7 @@ UNIT_PARTS_PER_MILLION = "ppm" UNIT_PASCAL = "Pa" UNIT_PERCENT = "%" UNIT_PH = "pH" +UNIT_POUND = "lb" UNIT_PULSES = "pulses" UNIT_PULSES_PER_MINUTE = "pulses/min" UNIT_REVOLUTIONS_PER_MINUTE = "RPM" From 7f38d95424d0d5a29acfaba0b891d5f847320ad7 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Wed, 11 Mar 2026 23:48:27 -0500 Subject: [PATCH 1298/2030] [ethernet] ESP32-S3 Ethernet compilation fix (#14717) --- esphome/components/ethernet/ethernet_component.h | 3 +++ esphome/components/ethernet/ethernet_helpers.c | 2 ++ tests/components/ethernet/common-w5500.yaml | 4 ++-- tests/components/ethernet/test.esp32-s3-idf.yaml | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/components/ethernet/test.esp32-s3-idf.yaml diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index c464e20b84..f7a0996fb7 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -11,11 +11,14 @@ #include "esp_eth.h" #include "esp_eth_mac.h" +#include "esp_eth_mac_esp.h" #include "esp_netif.h" #include "esp_mac.h" #include "esp_idf_version.h" +#if CONFIG_ETH_USE_ESP32_EMAC extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); +#endif namespace esphome::ethernet { diff --git a/esphome/components/ethernet/ethernet_helpers.c b/esphome/components/ethernet/ethernet_helpers.c index 96faccad24..963db3ff1c 100644 --- a/esphome/components/ethernet/ethernet_helpers.c +++ b/esphome/components/ethernet/ethernet_helpers.c @@ -3,6 +3,8 @@ // ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers // which are valid in C but not in C++. This wrapper allows C++ code to get // the default config without replicating the macro's contents. +#if CONFIG_ETH_USE_ESP32_EMAC eth_esp32_emac_config_t eth_esp32_emac_default_config(void) { return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG(); } +#endif diff --git a/tests/components/ethernet/common-w5500.yaml b/tests/components/ethernet/common-w5500.yaml index 1f8b8650dd..bf3f6f3f0c 100644 --- a/tests/components/ethernet/common-w5500.yaml +++ b/tests/components/ethernet/common-w5500.yaml @@ -2,10 +2,10 @@ ethernet: type: W5500 clk_pin: 19 mosi_pin: 21 - miso_pin: 23 + miso_pin: 17 cs_pin: 18 interrupt_pin: 36 - reset_pin: 22 + reset_pin: 12 clock_speed: 10Mhz manual_ip: static_ip: 192.168.178.56 diff --git a/tests/components/ethernet/test.esp32-s3-idf.yaml b/tests/components/ethernet/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..36f1b5365f --- /dev/null +++ b/tests/components/ethernet/test.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-w5500.yaml From f8a22b87b8908c33903355a74e3d593e29584f54 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Mar 2026 19:23:01 -1000 Subject: [PATCH 1299/2030] [rp2040] Fix crash handler design flaws (#14716) --- esphome/components/api/api_connection.h | 6 ++++++ esphome/components/logger/logger_rp2040.cpp | 5 +++++ esphome/components/rp2040/__init__.py | 1 + esphome/components/rp2040/core.cpp | 6 +++++- esphome/components/rp2040/crash_handler.cpp | 23 ++++++++++++++++----- esphome/components/rp2040/crash_handler.h | 8 ++++++- esphome/core/defines.h | 1 + 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 60cc3e91b1..68f698d190 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -17,6 +17,9 @@ #ifdef USE_ESP32_CRASH_HANDLER #include "esphome/components/esp32/crash_handler.h" #endif +#ifdef USE_RP2040_CRASH_HANDLER +#include "esphome/components/rp2040/crash_handler.h" +#endif #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -240,6 +243,9 @@ class APIConnection final : public APIServerConnectionBase { App.schedule_dump_config(); #ifdef USE_ESP32_CRASH_HANDLER esp32::crash_handler_log(); +#endif +#ifdef USE_RP2040_CRASH_HANDLER + rp2040::crash_handler_log(); #endif } #ifdef USE_API_HOMEASSISTANT_SERVICES diff --git a/esphome/components/logger/logger_rp2040.cpp b/esphome/components/logger/logger_rp2040.cpp index f76b823a8f..b7225c2a25 100644 --- a/esphome/components/logger/logger_rp2040.cpp +++ b/esphome/components/logger/logger_rp2040.cpp @@ -1,6 +1,9 @@ #ifdef USE_RP2040 #include "logger.h" +#include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER #include "esphome/components/rp2040/crash_handler.h" +#endif #include "esphome/core/log.h" namespace esphome::logger { @@ -26,7 +29,9 @@ void Logger::pre_setup() { } global_logger = this; ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_RP2040_CRASH_HANDLER rp2040::crash_handler_log(); +#endif } void HOT Logger::write_msg_(const char *msg, uint16_t len) { diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b15811241c..276187b273 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -212,6 +212,7 @@ async def to_code(config): ) cg.add_define("USE_RP2040_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT]) + cg.add_define("USE_RP2040_CRASH_HANDLER") def add_pio_file(component: str, key: str, data: str): diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 5e5a96c78b..7079cbca15 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -1,8 +1,10 @@ #ifdef USE_RP2040 #include "core.h" -#include "crash_handler.h" #include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER +#include "crash_handler.h" +#endif #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -25,7 +27,9 @@ void arch_restart() { } void arch_init() { +#ifdef USE_RP2040_CRASH_HANDLER rp2040::crash_handler_read_and_clear(); +#endif #if USE_RP2040_WATCHDOG_TIMEOUT > 0 watchdog_enable(USE_RP2040_WATCHDOG_TIMEOUT, false); #endif diff --git a/esphome/components/rp2040/crash_handler.cpp b/esphome/components/rp2040/crash_handler.cpp index 6ab46da444..1f579c2d18 100644 --- a/esphome/components/rp2040/crash_handler.cpp +++ b/esphome/components/rp2040/crash_handler.cpp @@ -1,5 +1,8 @@ #ifdef USE_RP2040 +#include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER + #include "crash_handler.h" #include "esphome/core/log.h" @@ -13,13 +16,19 @@ static constexpr uint32_t EF_LR = 5; static constexpr uint32_t EF_PC = 6; -static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF; +// Version encoded in the magic value: upper 16 bits are sentinel (0xDEAD), +// lower 16 bits are the version number. This avoids using a separate scratch +// register for versioning (we only have 8 total). Future firmware reads the +// sentinel to confirm it's crash data, then the version to know the layout. +static constexpr uint32_t CRASH_MAGIC_SENTINEL = 0xDEAD0000; +static constexpr uint32_t CRASH_DATA_VERSION = 1; +static constexpr uint32_t CRASH_MAGIC_V1 = CRASH_MAGIC_SENTINEL | CRASH_DATA_VERSION; // We only have 8 scratch registers (32 bytes) that survive watchdog reboot. // Use them for the most important data, then scan the stack for code addresses. // // Scratch register layout: -// [0] = magic (CRASH_MAGIC) +// [0] = versioned magic (upper 16 bits = 0xDEAD sentinel, lower 16 bits = version) // [1] = PC (program counter at fault) // [2] = LR (link register from exception frame) // [3] = SP (stack pointer at fault) @@ -57,9 +66,12 @@ static struct { uint8_t backtrace_count; } __attribute__((section(".noinit"))) s_crash_data; +bool crash_handler_has_data() { return s_crash_data.valid; } + void crash_handler_read_and_clear() { s_crash_data.valid = false; - if (watchdog_hw->scratch[0] == CRASH_MAGIC) { + uint32_t magic = watchdog_hw->scratch[0]; + if ((magic & 0xFFFF0000) == CRASH_MAGIC_SENTINEL && (magic & 0xFFFF) == CRASH_DATA_VERSION) { s_crash_data.valid = true; s_crash_data.pc = watchdog_hw->scratch[1]; s_crash_data.lr = watchdog_hw->scratch[2]; @@ -135,7 +147,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame // by a stacking error or corrupted SP, frame may be invalid. Write a minimal // crash marker so we at least know a crash occurred. if (!is_valid_sram_ptr(frame)) { - watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[0] = CRASH_MAGIC_V1; watchdog_hw->scratch[1] = 0; // PC unknown watchdog_hw->scratch[2] = 0; // LR unknown watchdog_hw->scratch[3] = reinterpret_cast<uintptr_t>(frame); // Record the bad SP for diagnosis @@ -157,7 +169,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame uint32_t pre_fault_sp = reinterpret_cast<uintptr_t>(post_frame); // Write key registers - watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[0] = CRASH_MAGIC_V1; watchdog_hw->scratch[1] = frame[EF_PC]; watchdog_hw->scratch[2] = frame[EF_LR]; watchdog_hw->scratch[3] = pre_fault_sp; @@ -224,4 +236,5 @@ extern "C" void __attribute__((naked, used)) isr_hardfault() { : "i"(hard_fault_handler_c)); } +#endif // USE_RP2040_CRASH_HANDLER #endif // USE_RP2040 diff --git a/esphome/components/rp2040/crash_handler.h b/esphome/components/rp2040/crash_handler.h index f10db47c23..78e8ede08c 100644 --- a/esphome/components/rp2040/crash_handler.h +++ b/esphome/components/rp2040/crash_handler.h @@ -2,7 +2,9 @@ #ifdef USE_RP2040 -#include <cstdint> +#include "esphome/core/defines.h" + +#ifdef USE_RP2040_CRASH_HANDLER namespace esphome::rp2040 { @@ -12,6 +14,10 @@ void crash_handler_read_and_clear(); /// Log crash data if a crash was detected on previous boot. void crash_handler_log(); +/// Returns true if crash data was found this boot. +bool crash_handler_has_data(); + } // namespace esphome::rp2040 +#endif // USE_RP2040_CRASH_HANDLER #endif // USE_RP2040 diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a33f10cb9c..073170aafb 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -338,6 +338,7 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) #define USE_LOOP_PRIORITY +#define USE_RP2040_CRASH_HANDLER #define USE_HTTP_REQUEST_RESPONSE #define USE_I2C #define USE_LOGGER_USB_CDC From 8a5f008aee25d70a9350959cfcbd5de23d2f83e8 Mon Sep 17 00:00:00 2001 From: Adam DeMuri <adam.demuri@gmail.com> Date: Thu, 12 Mar 2026 02:00:26 -0600 Subject: [PATCH 1300/2030] [modbus] Fix buffer overflow in modbus (#14719) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/modbus/modbus.cpp | 12 ++--- tests/components/modbus/modbus_test.cpp | 59 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 tests/components/modbus/modbus_test.cpp diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 82672217c5..7a61868e6e 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -125,13 +125,17 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { // Byte 0: modbus address (match all) if (at == 0) return true; - uint8_t address = raw[0]; - uint8_t function_code = raw[1]; + // Byte 1: function code + if (at == 1) + return true; // Byte 2: Size (with modbus rtu function code 4/3) // See also https://en.wikipedia.org/wiki/Modbus if (at == 2) return true; + uint8_t address = raw[0]; + uint8_t function_code = raw[1]; + uint8_t data_len = raw[2]; uint8_t data_offset = 3; @@ -146,10 +150,6 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { // chance that this is a complete message ... admittedly there is a small chance is // isn't but that is quite small given the purpose of the CRC in the first place - // Fewer than 2 bytes can't calc CRC - if (at < 2) - return true; - data_len = at - 2; data_offset = 1; diff --git a/tests/components/modbus/modbus_test.cpp b/tests/components/modbus/modbus_test.cpp new file mode 100644 index 0000000000..afe5ced082 --- /dev/null +++ b/tests/components/modbus/modbus_test.cpp @@ -0,0 +1,59 @@ +#include <gtest/gtest.h> +#include "esphome/components/modbus/modbus.h" +#include "esphome/core/helpers.h" + +namespace esphome::modbus { + +// Exposes protected methods for testing. +class TestModbus : public Modbus { + public: + bool test_parse_modbus_byte(uint8_t byte) { return this->parse_modbus_byte_(byte); } + void test_clear_rx_buffer() { this->rx_buffer_.clear(); } + void set_waiting(uint8_t addr) { this->waiting_for_response_ = addr; } +}; + +class MockDevice : public ModbusDevice { + public: + void on_modbus_data(const std::vector<uint8_t> &data) override { this->data_received = true; } + bool data_received{false}; +}; + +TEST(ModbusTest, TwoByteRegressionTest) { + TestModbus modbus; + modbus.set_role(ModbusRole::CLIENT); + // First byte (at=0) + EXPECT_TRUE(modbus.test_parse_modbus_byte(0x01)); + // Second byte (at=1) + // This used to reach raw[2] because it skipped the if(at==2) check, causing a + // buffer overflow. + EXPECT_TRUE(modbus.test_parse_modbus_byte(0x03)); +} + +TEST(ModbusTest, TestValidFrame) { + TestModbus modbus; + modbus.set_role(ModbusRole::CLIENT); + + MockDevice device; + device.set_parent(&modbus); + device.set_address(0x01); + modbus.register_device(&device); + modbus.set_waiting(0x01); + + // Address 1, Function 3, Length 2, Data 0x1234 + uint8_t frame_data[] = {0x01, 0x03, 0x02, 0x12, 0x34}; + uint16_t crc = esphome::crc16(frame_data, sizeof(frame_data)); + + std::vector<uint8_t> frame; + for (uint8_t b : frame_data) + frame.push_back(b); + frame.push_back(crc & 0xFF); + frame.push_back((crc >> 8) & 0xFF); + + for (size_t i = 0; i < frame.size(); i++) { + bool result = modbus.test_parse_modbus_byte(frame[i]); + EXPECT_TRUE(result) << "Failed at byte " << i << " (0x" << std::hex << (int) frame[i] << ")"; + } + EXPECT_TRUE(device.data_received); +} + +} // namespace esphome::modbus From 657890695f8215aeaa4166d6c41b950273538b64 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Thu, 12 Mar 2026 03:16:02 -0500 Subject: [PATCH 1301/2030] [ledc] Fix high-pressure crash & recovery (#14720) --- esphome/components/ledc/ledc_output.cpp | 53 +++++++++++++++++++++++-- esphome/components/ledc/ledc_output.h | 8 ++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 763de851da..592fc7bd0c 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -5,6 +5,10 @@ #include <driver/ledc.h> #include <cinttypes> +#include <esp_private/periph_ctrl.h> +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) +#include <hal/ledc_ll.h> +#endif #define CLOCK_FREQUENCY 80e6f @@ -16,10 +20,10 @@ static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5; -namespace esphome { -namespace ledc { +namespace esphome::ledc { static const char *const TAG = "ledc.output"; +static bool ledc_peripheral_reset_done = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1; #if SOC_LEDC_SUPPORT_HS_MODE @@ -32,6 +36,28 @@ inline ledc_mode_t get_speed_mode(uint8_t channel) { return channel < 8 ? LEDC_H inline ledc_mode_t get_speed_mode(uint8_t) { return LEDC_LOW_SPEED_MODE; } #endif +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) +// Classic ESP32 (currently the only target without SOC_LEDC_SUPPORT_FADE_STOP) can block in +// ledc_ll_set_duty_start() while duty_start is set. We check the same conf1.duty_start bit here +// to defer updates and avoid entering IDF's unbounded wait loop. +// +// This intentionally depends on the classic ESP32 LEDC register layout used by IDF's own LL HAL. +// If another target without SOC_LEDC_SUPPORT_FADE_STOP is introduced, revisit this helper. +static_assert( +#if defined(CONFIG_IDF_TARGET_ESP32) + true, +#else + false, +#endif + "LEDC duty_start pending check assumes classic ESP32 register layout; " + "re-evaluate for this target"); + +static bool ledc_duty_update_pending(ledc_mode_t speed_mode, ledc_channel_t chan_num) { + auto *hw = LEDC_LL_GET_HW(); + return hw->channel_group[speed_mode].channel[chan_num].conf1.duty_start != 0; +} +#endif + float ledc_max_frequency_for_bit_depth(uint8_t bit_depth) { return static_cast<float>(CLOCK_FREQUENCY) / static_cast<float>(1 << bit_depth); } @@ -105,21 +131,40 @@ void LEDCOutput::write_state(float state) { const uint32_t max_duty = (uint32_t(1) << this->bit_depth_) - 1; const float duty_rounded = roundf(state * max_duty); auto duty = static_cast<uint32_t>(duty_rounded); + if (duty == this->last_duty_) { + return; + } + ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_); auto speed_mode = get_speed_mode(this->channel_); auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); if (duty == max_duty) { ledc_stop(speed_mode, chan_num, 1); + this->last_duty_ = duty; } else if (duty == 0) { ledc_stop(speed_mode, chan_num, 0); + this->last_duty_ = duty; } else { +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) + if (ledc_duty_update_pending(speed_mode, chan_num)) { + ESP_LOGV(TAG, "Skipping LEDC duty update on channel %u while previous duty_start is still set", this->channel_); + return; + } +#endif ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); ledc_update_duty(speed_mode, chan_num); + this->last_duty_ = duty; } } void LEDCOutput::setup() { + if (!ledc_peripheral_reset_done) { + ESP_LOGV(TAG, "Resetting LEDC peripheral to clear stale state after reboot"); + periph_module_reset(PERIPH_LEDC_MODULE); + ledc_peripheral_reset_done = true; + } + auto speed_mode = get_speed_mode(this->channel_); auto timer_num = static_cast<ledc_timer_t>((this->channel_ % 8) / 2); auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8); @@ -207,12 +252,12 @@ void LEDCOutput::update_frequency(float frequency) { this->status_clear_error(); // re-apply duty + this->last_duty_ = UINT32_MAX; this->write_state(this->duty_); } uint8_t next_ledc_channel = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -} // namespace ledc -} // namespace esphome +} // namespace esphome::ledc #endif diff --git a/esphome/components/ledc/ledc_output.h b/esphome/components/ledc/ledc_output.h index b24e3cfdb2..bf5cdb9305 100644 --- a/esphome/components/ledc/ledc_output.h +++ b/esphome/components/ledc/ledc_output.h @@ -4,11 +4,11 @@ #include "esphome/core/hal.h" #include "esphome/core/automation.h" #include "esphome/components/output/float_output.h" +#include <cstdint> #ifdef USE_ESP32 -namespace esphome { -namespace ledc { +namespace esphome::ledc { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern uint8_t next_ledc_channel; @@ -39,6 +39,7 @@ class LEDCOutput : public output::FloatOutput, public Component { float phase_angle_{0.0f}; float frequency_{}; float duty_{0.0f}; + uint32_t last_duty_{UINT32_MAX}; bool initialized_ = false; }; @@ -56,7 +57,6 @@ template<typename... Ts> class SetFrequencyAction : public Action<Ts...> { LEDCOutput *parent_; }; -} // namespace ledc -} // namespace esphome +} // namespace esphome::ledc #endif From fe2d60ccecf6ceb18def3895a174277037942791 Mon Sep 17 00:00:00 2001 From: Massimo Antonello <31179882+MaxPlap@users.noreply.github.com> Date: Thu, 12 Mar 2026 09:52:58 +0100 Subject: [PATCH 1302/2030] [one_wire] allow changing address at runtime (#12150) --- esphome/components/one_wire/one_wire.cpp | 5 +++++ esphome/components/one_wire/one_wire.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/one_wire/one_wire.cpp b/esphome/components/one_wire/one_wire.cpp index 187f559ca6..d14c1c92bd 100644 --- a/esphome/components/one_wire/one_wire.cpp +++ b/esphome/components/one_wire/one_wire.cpp @@ -13,6 +13,11 @@ const std::string &OneWireDevice::get_address_name() { return this->address_name_; } +void OneWireDevice::set_address(uint64_t address) { + this->address_ = address; + this->address_name_.clear(); +} + bool OneWireDevice::send_command_(uint8_t cmd) { if (!this->bus_->select(this->address_)) return false; diff --git a/esphome/components/one_wire/one_wire.h b/esphome/components/one_wire/one_wire.h index f6a956a92c..324e46cd55 100644 --- a/esphome/components/one_wire/one_wire.h +++ b/esphome/components/one_wire/one_wire.h @@ -15,7 +15,7 @@ class OneWireDevice { public: /// @brief store the address of the device /// @param address of the device - void set_address(uint64_t address) { this->address_ = address; } + void set_address(uint64_t address); void set_index(uint8_t index) { this->index_ = index; } From c4c19c8a6ca7feaf08f4c30e9153c3d4c87fb0b9 Mon Sep 17 00:00:00 2001 From: Brian Kaufman <bkaufx@gmail.com> Date: Thu, 12 Mar 2026 02:07:26 -0700 Subject: [PATCH 1303/2030] [web_server] use DETAIL_ALL in update_all_json_generator (#14711) --- esphome/components/web_server/web_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 5590e67b82..4083019643 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -2181,7 +2181,7 @@ json::SerializationBuffer<> WebServer::update_state_json_generator(WebServer *we } json::SerializationBuffer<> WebServer::update_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE); + return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_ALL); } json::SerializationBuffer<> WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson From 511d18577276dcd4b434e82f4abe469c77a0bf47 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 12 Mar 2026 07:56:01 -0500 Subject: [PATCH 1304/2030] [audio] Bump microOpus to v0.3.5 (#14727) --- esphome/components/audio/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index d95fcf66d7..b28c2ed3d8 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -214,4 +214,4 @@ async def to_code(config): cg.add_define("USE_AUDIO_MP3_SUPPORT") if data.opus_support: cg.add_define("USE_AUDIO_OPUS_SUPPORT") - add_idf_component(name="esphome/micro-opus", ref="0.3.4") + add_idf_component(name="esphome/micro-opus", ref="0.3.5") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index f7fd3e67bc..df651ae15d 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -4,7 +4,7 @@ dependencies: esphome/esp-audio-libs: version: 2.0.3 esphome/micro-opus: - version: 0.3.4 + version: 0.3.5 espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: From a76767a0abdc371ad7f3169427cea5b0b83a7594 Mon Sep 17 00:00:00 2001 From: guillempages <guillempages@users.noreply.github.com> Date: Thu, 12 Mar 2026 15:15:20 +0100 Subject: [PATCH 1305/2030] [runtime_image] Update jpegdec lib version (#14726) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .clang-tidy.hash | 2 +- esphome/components/runtime_image/__init__.py | 2 +- platformio.ini | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index ff25675918..87b4ebb2c6 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -e4b9c4b54e705d3c9400e1cdda8ba0b32634780cfa5f32271832e911bdcafe7e +8e48e836c6fc196d3da000d46eb09db243b87fe33518a74e49c8e009d756074a diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py index 0773a53d91..7c22bfc9d1 100644 --- a/esphome/components/runtime_image/__init__.py +++ b/esphome/components/runtime_image/__init__.py @@ -74,7 +74,7 @@ class JPEGFormat(Format): def actions(self) -> None: cg.add_define("USE_RUNTIME_IMAGE_JPEG") - cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2") + cg.add_library("JPEGDEC", "1.8.4", "https://github.com/bitbank2/JPEGDEC#1.8.4") class PNGFormat(Format): diff --git a/platformio.ini b/platformio.ini index deee23d049..3c3d62ef76 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,11 +46,11 @@ lib_deps_base = lib_deps = ${common.lib_deps_base} - esphome/noise-c@0.1.11 ; api + esphome/noise-c@0.1.11 ; api improv/Improv@1.2.4 ; improv_serial / esp32_improv kikuchan98/pngle@1.1.0 ; online_image ; Using the repository directly, otherwise ESP-IDF can't use the library - https://github.com/bitbank2/JPEGDEC.git#ca1e0f2 ; online_image + https://github.com/bitbank2/JPEGDEC.git#1.8.4 ; online_image ; This dependency is used only in unit tests. ; Must coincide with PLATFORMIO_GOOGLE_TEST_LIB in scripts/cpp_unit_test.py ; See scripts/cpp_unit_test.py and tests/components/README.md From 25c30ac5bb5f32c59663dbeb4946b4f8c5e9d533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6nig?= <Matthias.Konitzny@kabelmail.de> Date: Thu, 12 Mar 2026 17:00:08 +0100 Subject: [PATCH 1306/2030] [mqtt] Fixed permission denied error for client certificates on Windows (#13525) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/mqtt.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/esphome/mqtt.py b/esphome/mqtt.py index cbf78bd3f6..ccacbaea54 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -2,6 +2,7 @@ import contextlib from datetime import datetime import json import logging +import os import ssl import tempfile import time @@ -109,14 +110,18 @@ def prepare( CONF_CLIENT_CERTIFICATE_KEY ): with ( - tempfile.NamedTemporaryFile(mode="w+") as cert_file, - tempfile.NamedTemporaryFile(mode="w+") as key_file, + tempfile.NamedTemporaryFile(mode="w+", delete=False) as cert_file, + tempfile.NamedTemporaryFile(mode="w+", delete=False) as key_file, ): - cert_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE)) - cert_file.flush() - key_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE_KEY)) - key_file.flush() - context.load_cert_chain(cert_file.name, key_file.name) + try: + cert_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE)) + key_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE_KEY)) + cert_file.close() + key_file.close() + context.load_cert_chain(cert_file.name, key_file.name) + finally: + os.unlink(cert_file.name) + os.unlink(key_file.name) client.tls_set_context(context) try: From 07f8ae6c8266ae2f6207463bb3c0bebe4eb5c062 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:14:49 -1000 Subject: [PATCH 1307/2030] [socket] Fix use-after-free in LWIP PCB close/abort path (#14706) --- .../components/socket/lwip_raw_tcp_impl.cpp | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index fd1b8a9554..1e03a4935c 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -138,13 +138,46 @@ static const char *const TAG = "socket.lwip"; #define LWIP_LOG(msg, ...) #endif +// Clear arg, recv, and err callbacks, then abort a connected PCB. +// Only valid for full tcp_pcb (not tcp_pcb_listen). +// Must be called before destroying the object that tcp_arg points to — +// tcp_abort() triggers the err callback synchronously, which would +// otherwise call back into a partially-destroyed object. +// tcp_sent/tcp_poll are not cleared because this implementation +// never registers them. +static void pcb_detach_abort(struct tcp_pcb *pcb) { + tcp_arg(pcb, nullptr); + tcp_recv(pcb, nullptr); + tcp_err(pcb, nullptr); + tcp_abort(pcb); +} + +// Clear arg, recv, and err callbacks, then gracefully close a connected PCB. +// Only valid for full tcp_pcb (not tcp_pcb_listen). +// After tcp_close(), the PCB remains alive during the TCP close handshake +// (FIN_WAIT, TIME_WAIT states). Without clearing callbacks first, LWIP +// would call recv/err on a destroyed socket object, corrupting the heap. +// tcp_sent/tcp_poll are not cleared because this implementation +// never registers them. +// Returns ERR_OK on success; on failure the PCB is aborted instead. +static err_t pcb_detach_close(struct tcp_pcb *pcb) { + tcp_arg(pcb, nullptr); + tcp_recv(pcb, nullptr); + tcp_err(pcb, nullptr); + err_t err = tcp_close(pcb); + if (err != ERR_OK) { + tcp_abort(pcb); + } + return err; +} + // ---- LWIPRawCommon methods ---- LWIPRawCommon::~LWIPRawCommon() { LWIP_LOCK(); if (this->pcb_ != nullptr) { LWIP_LOG("tcp_abort(%p)", this->pcb_); - tcp_abort(this->pcb_); + pcb_detach_abort(this->pcb_); this->pcb_ = nullptr; } } @@ -222,15 +255,13 @@ int LWIPRawCommon::close() { return -1; } LWIP_LOG("tcp_close(%p)", this->pcb_); - err_t err = tcp_close(this->pcb_); + err_t err = pcb_detach_close(this->pcb_); + this->pcb_ = nullptr; if (err != ERR_OK) { LWIP_LOG(" -> err %d", err); - tcp_abort(this->pcb_); - this->pcb_ = nullptr; errno = err == ERR_MEM ? ENOMEM : EIO; return -1; } - this->pcb_ = nullptr; return 0; } @@ -673,13 +704,10 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { LWIPRawListenImpl::~LWIPRawListenImpl() { LWIP_LOCK(); // Abort any queued PCBs that were never accepted by the main loop. - // Clear the error callback first — tcp_abort triggers it, and we don't - // want s_queued_err_fn writing to slots during destruction. for (uint8_t i = 0; i < this->accepted_socket_count_; i++) { auto &entry = this->accepted_pcbs_[i]; if (entry.pcb != nullptr) { - tcp_err(entry.pcb, nullptr); - tcp_abort(entry.pcb); + pcb_detach_abort(entry.pcb); entry.pcb = nullptr; } if (entry.rx_buf != nullptr) { @@ -691,6 +719,10 @@ LWIPRawListenImpl::~LWIPRawListenImpl() { // Listen PCBs must use tcp_close(), not tcp_abort(). // tcp_abandon() asserts pcb->state != LISTEN and would access // fields that don't exist in the smaller tcp_pcb_listen struct. + // Don't use pcb_detach_close() here — tcp_recv()/tcp_err() also access + // fields that only exist in the full tcp_pcb, not tcp_pcb_listen. + // tcp_close() on a listen PCB is synchronous (frees immediately), + // so there are no async callbacks to worry about. // Close here and null pcb_ so the base destructor skips tcp_abort. if (this->pcb_ != nullptr) { tcp_close(this->pcb_); From a3a88acfcf799a6e0a56051dcdface547642b7aa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:04 -1000 Subject: [PATCH 1308/2030] [socket] Fast path for TCP_NODELAY bypasses lwip_setsockopt overhead (#14693) --- esphome/components/socket/bsd_sockets_impl.h | 11 ++++++++++- esphome/components/socket/lwip_sockets_impl.h | 11 ++++++++++- esphome/core/lwip_fast_select.c | 16 ++++++++++++++++ esphome/core/lwip_fast_select.h | 7 +++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h index 9ebbe72002..339a699bc9 100644 --- a/esphome/components/socket/bsd_sockets_impl.h +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -14,7 +14,7 @@ #endif #ifdef USE_LWIP_FAST_SELECT -struct lwip_sock; +#include "esphome/core/lwip_fast_select.h" #endif namespace esphome::socket { @@ -56,6 +56,15 @@ class BSDSocketImpl { return ::getsockopt(this->fd_, level, optname, optval, optlen); } int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { +#if defined(USE_LWIP_FAST_SELECT) && defined(CONFIG_LWIP_TCPIP_CORE_LOCKING) + // Fast path for TCP_NODELAY: directly set the pcb flag under the TCPIP core lock, + // bypassing lwip_setsockopt overhead (socket lookups, hook, switch cascade, refcounting). + if (level == IPPROTO_TCP && optname == TCP_NODELAY && optlen == sizeof(int) && optval != nullptr) { + LwIPLock lock; + if (esphome_lwip_set_nodelay(this->cached_sock_, *reinterpret_cast<const int *>(optval) != 0)) + return 0; + } +#endif return ::setsockopt(this->fd_, level, optname, optval, optlen); } int listen(int backlog) { return ::listen(this->fd_, backlog); } diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h index c579219863..bfc4da9926 100644 --- a/esphome/components/socket/lwip_sockets_impl.h +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -10,7 +10,7 @@ #include "headers.h" #ifdef USE_LWIP_FAST_SELECT -struct lwip_sock; +#include "esphome/core/lwip_fast_select.h" #endif namespace esphome::socket { @@ -52,6 +52,15 @@ class LwIPSocketImpl { return lwip_getsockopt(this->fd_, level, optname, optval, optlen); } int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { +#if defined(USE_LWIP_FAST_SELECT) && defined(CONFIG_LWIP_TCPIP_CORE_LOCKING) + // Fast path for TCP_NODELAY: directly set the pcb flag under the TCPIP core lock, + // bypassing lwip_setsockopt overhead (socket lookups, hook, switch cascade, refcounting). + if (level == IPPROTO_TCP && optname == TCP_NODELAY && optlen == sizeof(int) && optval != nullptr) { + LwIPLock lock; + if (esphome_lwip_set_nodelay(this->cached_sock_, *reinterpret_cast<const int *>(optval) != 0)) + return 0; + } +#endif return lwip_setsockopt(this->fd_, level, optname, optval, optlen); } int listen(int backlog) { return lwip_listen(this->fd_, backlog); } diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index c578a9aae9..a695fa396b 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -112,6 +112,7 @@ // LwIP headers must come first — they define netconn_callback, struct lwip_sock, etc. #include <lwip/api.h> #include <lwip/priv/sockets_priv.h> +#include <lwip/tcp.h> // FreeRTOS include paths differ: ESP-IDF uses freertos/ prefix, LibreTiny does not #ifdef USE_ESP32 #include <freertos/FreeRTOS.h> @@ -216,6 +217,21 @@ void esphome_lwip_hook_socket(struct lwip_sock *sock) { sock->conn->callback = esphome_socket_event_callback; } +bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable) { + if (sock == NULL || sock->conn == NULL) + return false; + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) + return false; + if (sock->conn->pcb.tcp == NULL) + return false; + if (enable) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + return true; +} + // Wake the main loop from another FreeRTOS task. NOT ISR-safe. void esphome_lwip_wake_main_loop(void) { TaskHandle_t task = s_main_loop_task; diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index 46c6b711cd..50706ba9f6 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -66,6 +66,13 @@ void esphome_lwip_wake_main_loop(void); /// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); +/// Set or clear TCP_NODELAY on a socket's tcp_pcb directly. +/// Must be called with the TCPIP core lock held (LwIPLock in C++). +/// This bypasses lwip_setsockopt() overhead (socket lookups, switch cascade, +/// hooks, refcounting) — just a direct pcb->flags bit set/clear. +/// Returns true if successful, false if sock/conn/pcb is NULL or the socket is not TCP. +bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable); + /// Wake the main loop task from any context (ISR, thread, or main loop). /// ESP32-only: uses xPortInIsrContext() to detect ISR context. /// LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths. From 03c091adfcf1981c2259715e563d84b8f5210935 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:21 -1000 Subject: [PATCH 1309/2030] [esp32_ble_client] Fix disconnect race that causes stuck connections (#14211) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../esp32_ble_client/ble_client_base.cpp | 43 ++++++++++++++++--- .../esp32_ble_client/ble_client_base.h | 17 +++++++- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 2f17334c77..9d6e079d92 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -27,6 +27,7 @@ static constexpr uint16_t MEDIUM_CONN_TIMEOUT = 800; // 800 * 10ms = 8s static constexpr uint16_t FAST_MIN_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms (BLE minimum) static constexpr uint16_t FAST_MAX_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms static constexpr uint16_t FAST_CONN_TIMEOUT = 1000; // 1000 * 10ms = 10s +static constexpr uint32_t DISCONNECTING_TIMEOUT = 10000; // 10s static const esp_bt_uuid_t NOTIFY_DESC_UUID = { .len = ESP_UUID_LEN_16, .uuid = @@ -62,6 +63,15 @@ void BLEClientBase::loop() { // will enable it again when a connection is needed. else if (this->state() == espbt::ClientState::IDLE) { this->disable_loop(); + } else if (this->state() == espbt::ClientState::DISCONNECTING && + (millis() - this->disconnecting_started_) > DISCONNECTING_TIMEOUT) { + ESP_LOGE(TAG, "[%d] [%s] Timeout waiting for CLOSE_EVT after disconnect, forcing IDLE", this->connection_index_, + this->address_str_); + // release_services() must be called before set_idle_() — if we entered DISCONNECTING + // via unconditional_disconnect() (which doesn't call release_services()), and ESP-IDF + // never delivered CLOSE_EVT/DISCONNECT_EVT, services would leak without this call. + this->release_services(); + this->set_idle_(); } } @@ -101,12 +111,16 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) { #endif void BLEClientBase::connect() { - // Prevent duplicate connection attempts + // Prevent duplicate connection attempts or connecting while still disconnecting if (this->state() == espbt::ClientState::CONNECTING || this->state() == espbt::ClientState::CONNECTED || this->state() == espbt::ClientState::ESTABLISHED) { ESP_LOGW(TAG, "[%d] [%s] Connection already in progress, state=%s", this->connection_index_, this->address_str_, espbt::client_state_to_string(this->state())); return; + } else if (this->state() == espbt::ClientState::DISCONNECTING) { + ESP_LOGW(TAG, "[%d] [%s] Cannot connect, still waiting for CLOSE_EVT to complete disconnect", + this->connection_index_, this->address_str_); + return; } ESP_LOGI(TAG, "[%d] [%s] 0x%02x Connecting", this->connection_index_, this->address_str_, this->remote_addr_type_); this->paired_ = false; @@ -174,7 +188,7 @@ void BLEClientBase::unconditional_disconnect() { this->set_address(0); this->set_state(espbt::ClientState::IDLE); } else { - this->set_state(espbt::ClientState::DISCONNECTING); + this->set_disconnecting_(); } } @@ -220,6 +234,7 @@ void BLEClientBase::log_connection_params_(const char *param_type) { void BLEClientBase::handle_connection_result_(esp_err_t ret) { if (ret) { this->log_gattc_warning_("esp_ble_gattc_open", ret); + // Don't use set_idle_() here — CONNECT_EVT never fired so conn_id_ is still UNSET_CONN_ID. this->set_state(espbt::ClientState::IDLE); } } @@ -311,15 +326,16 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) { this->log_gattc_warning_("Connection open", param->open.status); - this->set_state(espbt::ClientState::IDLE); + // Connection was never established so CLOSE_EVT may not follow + this->set_idle_(); break; } if (this->want_disconnect_) { // Disconnect was requested after connecting started, // but before the connection was established. Now that we have // this->conn_id_ set, we can disconnect it. + // Don't reset conn_id_ here — CLOSE_EVT needs it to match and call set_idle_(). this->unconditional_disconnect(); - this->conn_id_ = UNSET_CONN_ID; break; } // MTU negotiation already started in ESP_GATTC_CONNECT_EVT @@ -363,8 +379,22 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason 0x%02x", this->connection_index_, this->address_str_, param->disconnect.reason); } + // For active disconnects (esp_ble_gattc_close), CLOSE_EVT arrives before + // DISCONNECT_EVT. If CLOSE_EVT already transitioned us to IDLE, don't go + // backwards to DISCONNECTING — the connection is already fully cleaned up. + if (this->state() == espbt::ClientState::IDLE) { + this->log_event_("DISCONNECT_EVT after CLOSE_EVT, already IDLE"); + break; + } + // For passive disconnects (remote device disconnected or link lost), + // DISCONNECT_EVT arrives first. Don't transition to IDLE yet — wait for + // CLOSE_EVT to ensure the controller has fully freed resources (L2CAP + // channels, ATT resources, HCI connection handle). Transitioning to IDLE + // here would allow reconnection before cleanup is complete, causing the + // controller to reject the new connection (status=133) or crash with + // ASSERT_PARAM in lld_evt.c. this->release_services(); - this->set_state(espbt::ClientState::IDLE); + this->set_disconnecting_(); break; } @@ -387,8 +417,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ return false; this->log_gattc_lifecycle_event_("CLOSE"); this->release_services(); - this->set_state(espbt::ClientState::IDLE); - this->conn_id_ = UNSET_CONN_ID; + this->set_idle_(); break; } case ESP_GATTC_SEARCH_RES_EVT: { diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index af4f1b3029..4e0b22cc29 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -113,11 +113,14 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { char address_str_[MAC_ADDRESS_PRETTY_BUFFER_SIZE]{}; esp_bd_addr_t remote_bda_; // 6 bytes - // Group 5: 2-byte types + // Group 5: 4-byte types + uint32_t disconnecting_started_{0}; + + // Group 6: 2-byte types uint16_t conn_id_{UNSET_CONN_ID}; uint16_t mtu_{23}; - // Group 6: 1-byte types and small enums + // Group 7: 1-byte types and small enums esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC}; espbt::ConnectionType connection_type_{espbt::ConnectionType::V1}; uint8_t connection_index_; @@ -137,6 +140,16 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { void log_gattc_warning_(const char *operation, esp_err_t err); void log_connection_params_(const char *param_type); void handle_connection_result_(esp_err_t ret); + /// Transition to IDLE and reset conn_id — call when the connection is fully dead. + void set_idle_() { + this->set_state(espbt::ClientState::IDLE); + this->conn_id_ = UNSET_CONN_ID; + } + /// Transition to DISCONNECTING and start the safety timeout. + void set_disconnecting_() { + this->disconnecting_started_ = millis(); + this->set_state(espbt::ClientState::DISCONNECTING); + } // Compact error logging helpers to reduce flash usage void log_error_(const char *message); void log_error_(const char *message, int code); From fd1d0167951b7b228f6c13c2ce463059a2636417 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:34 -1000 Subject: [PATCH 1310/2030] [time] Fix settimeofday() failure on ESP8266 (#14707) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/time/real_time_clock.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 566344fa88..4e623942ac 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -88,16 +88,16 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { struct timeval timev { .tv_sec = static_cast<time_t>(epoch), .tv_usec = 0, }; +#ifdef USE_ESP8266 + // ESP8266 settimeofday() requires tz to be nullptr + int ret = settimeofday(&timev, nullptr); +#else struct timezone tz = {0, 0}; int ret = settimeofday(&timev, &tz); - if (ret != 0 && errno == EINVAL) { - // Some ESP8266 frameworks abort when timezone parameter is not NULL - // while ESP32 expects it not to be NULL - ret = settimeofday(&timev, nullptr); - } +#endif if (ret != 0) { - ESP_LOGW(TAG, "setimeofday() failed with code %d", ret); + ESP_LOGW(TAG, "settimeofday() failed with code %d", ret); } #endif auto time = this->now(); From 4a21afe7ce056115b7af94ccb02c7bc5bd3d8f36 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:48 -1000 Subject: [PATCH 1311/2030] [ota][socket] Fix ESP8266/RP2040 OTA timeout by using SO_RCVTIMEO instead of polling (#14675) --- .../components/esphome/ota/ota_esphome.cpp | 46 +++++++++++- esphome/components/socket/headers.h | 2 + .../components/socket/lwip_raw_tcp_impl.cpp | 71 +++++++++++++++++-- esphome/components/socket/lwip_raw_tcp_impl.h | 16 +++-- 4 files changed, 123 insertions(+), 12 deletions(-) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index a1cdf59d2b..d8dbe2dee2 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -18,6 +18,7 @@ #include <cerrno> #include <cstdio> +#include <sys/time.h> namespace esphome { @@ -238,6 +239,31 @@ void ESPHomeOTAComponent::handle_data_() { /// and reboots on success. /// /// Authentication has already been handled in the non-blocking states AUTH_SEND/AUTH_READ. + /// + /// Socket I/O strategy: + /// + /// Before this function, the handshake states use non-blocking I/O: + /// read()/write() return immediately with EWOULDBLOCK if no data + /// loop() retries on next iteration (~16ms), no delay needed + /// + /// This function switches to blocking mode with SO_RCVTIMEO/SO_SNDTIMEO: + /// + /// Path | Wait mechanism | WDT strategy + /// --------------|------------------------|--------------------------- + /// Main read | SO_RCVTIMEO (2s block) | feed_wdt() only, no delay + /// readall_() | SO_RCVTIMEO (2s block) | feed_wdt() + delay(0) + /// writeall_() | SO_SNDTIMEO (2s block) | feed_wdt() + delay(1) + /// + /// readall_() uses delay(0) because SO_RCVTIMEO already waited — just yield. + /// writeall_() uses delay(1) because on raw TCP (ESP8266, RP2040) writes + /// never block (tcp_write returns immediately), so delay(1) prevents spinning. + /// + /// Platform details: + /// BSD sockets (ESP32): setblocking(true) makes read/write block + /// lwip sockets (LT): setblocking(true) makes read/write block + /// Raw TCP (8266, RP2040): setblocking is no-op; SO_RCVTIMEO uses + /// socket_delay()/socket_wake() in read(); + /// write() always returns immediately ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_ERROR_UNKNOWN; bool update_started = false; size_t total = 0; @@ -249,6 +275,14 @@ void ESPHomeOTAComponent::handle_data_() { size_t size_acknowledged = 0; #endif + // Set socket timeouts and blocking mode (see strategy table above) + struct timeval tv; + tv.tv_sec = 2; + tv.tv_usec = 0; + this->client_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + this->client_->setsockopt(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + this->client_->setblocking(true); + // Acknowledge auth OK - 1 byte this->write_byte_(ota::OTA_RESPONSE_AUTH_OK); @@ -299,7 +333,8 @@ void ESPHomeOTAComponent::handle_data_() { ssize_t read = this->client_->read(buf, requested); if (read == -1) { if (this->would_block_(errno)) { - this->yield_and_feed_watchdog_(); + // read() already waited up to SO_RCVTIMEO for data, just feed WDT + App.feed_wdt(); continue; } ESP_LOGW(TAG, "Read err %d", errno); @@ -401,7 +436,9 @@ bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) { } else { at += read; } - this->yield_and_feed_watchdog_(); + // read() already waited via SO_RCVTIMEO, just yield without 1ms stall + App.feed_wdt(); + delay(0); } return true; @@ -422,10 +459,13 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno); return false; } + // EWOULDBLOCK: on raw TCP writes never block, delay(1) prevents spinning + this->yield_and_feed_watchdog_(); } else { at += written; + // write() may block up to SO_SNDTIMEO on BSD/lwip sockets, feed WDT + App.feed_wdt(); } - this->yield_and_feed_watchdog_(); } return true; } diff --git a/esphome/components/socket/headers.h b/esphome/components/socket/headers.h index 16e4d23d3b..0eece6480f 100644 --- a/esphome/components/socket/headers.h +++ b/esphome/components/socket/headers.h @@ -51,6 +51,8 @@ #define SO_REUSEADDR 0x0004 /* Allow local address reuse */ #define SO_KEEPALIVE 0x0008 /* keep connections alive */ #define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ #define SOL_SOCKET 0xfff /* options for socket level */ diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 1e03a4935c..96328e68c7 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -5,6 +5,7 @@ #include <cerrno> #include <cstring> +#include <sys/time.h> #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -81,7 +82,9 @@ void socket_delay(uint32_t ms) { s_socket_woke = false; return; } - s_socket_woke = false; + // Don't clear s_socket_woke here — if an IRQ fires between the check above + // and the while loop below, the while condition sees it immediately. Clearing + // here would lose that wake and sleep until the timer fires. s_delay_expired = false; // Set a one-shot timer to wake us after the timeout. // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. @@ -99,6 +102,7 @@ void socket_delay(uint32_t ms) { // Cancel timer if we woke early (socket data arrived before timeout) if (!s_delay_expired) cancel_alarm(alarm); + s_socket_woke = false; // consume the wake for next call } // No IRAM_ATTR equivalent needed: on RP2040, CYW43 async_context runs LWIP @@ -359,6 +363,18 @@ int LWIPRawCommon::getsockopt(int level, int optname, void *optval, socklen_t *o *optlen = 4; return 0; } + if (level == SOL_SOCKET && optname == SO_RCVTIMEO) { + if (*optlen < sizeof(struct timeval)) { + errno = EINVAL; + return -1; + } + uint32_t ms = this->recv_timeout_cs_ * 10; + auto *tv = reinterpret_cast<struct timeval *>(optval); + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; + *optlen = sizeof(struct timeval); + return 0; + } if (level == IPPROTO_TCP && optname == TCP_NODELAY) { if (*optlen < 4) { errno = EINVAL; @@ -388,6 +404,21 @@ int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, sockle // to prevent warnings return 0; } + if (level == SOL_SOCKET && optname == SO_RCVTIMEO) { + if (optlen < sizeof(struct timeval)) { + errno = EINVAL; + return -1; + } + const auto *tv = reinterpret_cast<const struct timeval *>(optval); + uint32_t ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + uint32_t cs = (ms + 9) / 10; // round up to nearest centisecond + this->recv_timeout_cs_ = cs > 255 ? 255 : static_cast<uint8_t>(cs); + return 0; + } + if (level == SOL_SOCKET && optname == SO_SNDTIMEO) { + // Raw TCP writes are non-blocking (tcp_write), so send timeout is a no-op. + return 0; + } if (level == IPPROTO_TCP && optname == TCP_NODELAY) { if (optlen != 4) { errno = EINVAL; @@ -518,8 +549,25 @@ err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { return ERR_OK; } -ssize_t LWIPRawImpl::read(void *buf, size_t len) { - LWIP_LOCK(); +void LWIPRawImpl::wait_for_data_() { + // Wait for data without holding LWIP_LOCK so recv_fn() can run on RP2040 + // (needs async_context lock). + // + // Loop until data arrives, connection closes, or the full timeout elapses. + // socket_delay() may return early due to other sockets waking the global + // socket_wake() flag, so we re-enter for the remaining time. + uint32_t timeout_ms = this->recv_timeout_cs_ * 10; + uint32_t start = millis(); + while (this->waiting_for_data_()) { + uint32_t elapsed = millis() - start; + if (elapsed >= timeout_ms) + break; + socket_delay(timeout_ms - elapsed); + } +} + +ssize_t LWIPRawImpl::read_locked_(void *buf, size_t len) { + // Caller must hold LWIP_LOCK. Copies available data from rx_buf_ into buf. if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -578,11 +626,26 @@ ssize_t LWIPRawImpl::read(void *buf, size_t len) { return read; } +ssize_t LWIPRawImpl::read(void *buf, size_t len) { + // See waiting_for_data_() for safety of unlocked reads. + if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { + this->wait_for_data_(); + } + + LWIP_LOCK(); + return this->read_locked_(buf, len); +} + ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { + // See waiting_for_data_() for safety of unlocked reads. + if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { + this->wait_for_data_(); + } + LWIP_LOCK(); // Hold for entire scatter-gather operation ssize_t ret = 0; for (int i = 0; i < iovcnt; i++) { - ssize_t err = this->read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); + ssize_t err = this->read_locked_(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); if (err == -1) { if (ret != 0) { // if we already read some don't return an error diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index 95931afcf3..3c27d71062 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -57,6 +57,7 @@ class LWIPRawCommon { // instead use it for determining whether to call lwip_output bool nodelay_ = false; sa_family_t family_ = 0; + uint8_t recv_timeout_cs_ = 0; // SO_RCVTIMEO in centiseconds (0 = no timeout, max 2.55s) }; /// Connected socket implementation for LWIP raw TCP. @@ -107,11 +108,8 @@ class LWIPRawImpl : public LWIPRawCommon { errno = ECONNRESET; return -1; } - if (blocking) { - // blocking operation not supported - errno = EINVAL; - return -1; - } + // Raw TCP doesn't use a blocking flag directly. Blocking behavior + // is provided by SO_RCVTIMEO which makes read() wait via socket_delay(). return 0; } int loop() { return 0; } @@ -122,6 +120,14 @@ class LWIPRawImpl : public LWIPRawCommon { static err_t s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err); protected: + // True when the socket could receive data but none has arrived yet. + // Safe to call without LWIP_LOCK — only null-checks pointers and reads a bool, + // all atomic on ARM/Xtensa. A stale value is harmless: the caller either does + // an unnecessary wait (stale true) or skips it (stale false), and the + // authoritative recheck happens under LWIP_LOCK afterward. + bool waiting_for_data_() const { return this->rx_buf_ == nullptr && !this->rx_closed_ && this->pcb_ != nullptr; } + void wait_for_data_(); + ssize_t read_locked_(void *buf, size_t len); ssize_t internal_write_(const void *buf, size_t len); int internal_output_(); From 70d188202a1ddca4a3a342ca332f2d0c13a47588 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:08 -1000 Subject: [PATCH 1312/2030] [adc] Fix PICO_VSYS_PIN compile error on RP2350 boards (#14724) --- esphome/components/adc/adc_sensor_rp2040.cpp | 7 +++++++ tests/components/adc/test.rp2040-pico2-ard.yaml | 11 +++++++++++ tests/components/spi/test.rp2040-pico2-ard.yaml | 6 ++++++ .../build_components_base.rp2040-pico2-ard.yaml | 15 +++++++++++++++ .../common/spi/rp2040-pico2-ard.yaml | 12 ++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 tests/components/adc/test.rp2040-pico2-ard.yaml create mode 100644 tests/components/spi/test.rp2040-pico2-ard.yaml create mode 100644 tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml create mode 100644 tests/test_build_components/common/spi/rp2040-pico2-ard.yaml diff --git a/esphome/components/adc/adc_sensor_rp2040.cpp b/esphome/components/adc/adc_sensor_rp2040.cpp index 8496e0f41e..a79707e234 100644 --- a/esphome/components/adc/adc_sensor_rp2040.cpp +++ b/esphome/components/adc/adc_sensor_rp2040.cpp @@ -8,6 +8,13 @@ #endif // CYW43_USES_VSYS_PIN #include <hardware/adc.h> +// PICO_VSYS_PIN is defined in pico-sdk board headers (e.g. boards/pico2.h), +// but the Arduino framework's config_autogen.h includes a generic board header +// that doesn't define it. Provide the standard value (pin 29) as a fallback. +#ifndef PICO_VSYS_PIN +#define PICO_VSYS_PIN 29 // NOLINT(cppcoreguidelines-macro-usage) +#endif + namespace esphome { namespace adc { diff --git a/tests/components/adc/test.rp2040-pico2-ard.yaml b/tests/components/adc/test.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..4cc865bb5d --- /dev/null +++ b/tests/components/adc/test.rp2040-pico2-ard.yaml @@ -0,0 +1,11 @@ +sensor: + - id: my_sensor + platform: adc + pin: VCC + name: ADC Test sensor + update_interval: "1:01" + unit_of_measurement: "°C" + icon: "mdi:water-percent" + accuracy_decimals: 5 + setup_priority: -100 + force_update: true diff --git a/tests/components/spi/test.rp2040-pico2-ard.yaml b/tests/components/spi/test.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..81a8acafd8 --- /dev/null +++ b/tests/components/spi/test.rp2040-pico2-ard.yaml @@ -0,0 +1,6 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml b/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..0922a5238e --- /dev/null +++ b/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml @@ -0,0 +1,15 @@ +esphome: + name: componenttestrp2040pico2ard + friendly_name: $component_name + +rp2040: + board: rpipico2 + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_test_file: $component_test_file diff --git a/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml b/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..205beb6e1b --- /dev/null +++ b/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml @@ -0,0 +1,12 @@ +# Common SPI configuration for RP2040 Pico 2 (RP2350) Arduino tests + +substitutions: + clk_pin: GPIO18 + mosi_pin: GPIO19 + miso_pin: GPIO16 + +spi: + - id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} From 618312f0ee0944a9575b58bc9eb62fb929755fa9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:23 -1000 Subject: [PATCH 1313/2030] [api] Fix undefined behavior in noise handshake with empty rx buffer (#14722) --- esphome/components/api/api_frame_helper_noise.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 3e6ecf9dc3..f945253c89 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -258,10 +258,13 @@ APIError APINoiseFrameHelper::state_action_() { // ignore contents, may be used in future for flags // Resize for: existing prologue + 2 size bytes + frame data size_t old_size = this->prologue_.size(); - this->prologue_.resize(old_size + 2 + this->rx_buf_.size()); - this->prologue_[old_size] = (uint8_t) (this->rx_buf_.size() >> 8); - this->prologue_[old_size + 1] = (uint8_t) this->rx_buf_.size(); - std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), this->rx_buf_.size()); + size_t rx_size = this->rx_buf_.size(); + this->prologue_.resize(old_size + 2 + rx_size); + this->prologue_[old_size] = (uint8_t) (rx_size >> 8); + this->prologue_[old_size + 1] = (uint8_t) rx_size; + if (rx_size > 0) { + std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), rx_size); + } state_ = State::SERVER_HELLO; } From 186ca4e458cdc16cf1ee9fa692b9dbe066d57b1f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:38 -1000 Subject: [PATCH 1314/2030] [uart] Allow hardware UART with single pin on RP2040 (#14725) --- .../components/uart/uart_component_rp2040.cpp | 37 +++++++++++++++---- tests/components/uart/test.rp2040-ard.yaml | 3 ++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 858f1a02dd..6f6f1fb96b 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -105,15 +105,34 @@ void RP2040UartComponent::setup() { } } + // Determine which hardware UART to use. A pin that is not specified + // should not prevent hardware UART selection — one-way UART is valid. + // When both pins are configured, both must be HW-capable and agree on UART number. + // When only one pin is configured (nullptr other), use that pin's HW UART. + // If a pin is configured but not HW-capable (inverted/invalid), fall back to SerialPIO. + int8_t hw_uart = -1; + const bool tx_configured = (this->tx_pin_ != nullptr); + const bool rx_configured = (this->rx_pin_ != nullptr); + + if (tx_configured && rx_configured) { + // Both pins configured — both must map to the same hardware UART + if (tx_hw != -1 && rx_hw != -1 && tx_hw == rx_hw) { + hw_uart = tx_hw; + } + } else if (tx_configured) { + hw_uart = tx_hw; + } else if (rx_configured) { + hw_uart = rx_hw; + } + #ifdef USE_LOGGER - if (tx_hw == rx_hw && logger::global_logger->get_uart() == tx_hw) { - ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", tx_hw); - tx_hw = -1; - rx_hw = -1; + if (hw_uart != -1 && logger::global_logger->get_uart() == hw_uart) { + ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", hw_uart); + hw_uart = -1; } #endif - if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) { + if (hw_uart == -1) { ESP_LOGV(TAG, "Using SerialPIO"); pin_size_t tx = this->tx_pin_ == nullptr ? NOPIN : this->tx_pin_->get_pin(); pin_size_t rx = this->rx_pin_ == nullptr ? NOPIN : this->rx_pin_->get_pin(); @@ -127,13 +146,15 @@ void RP2040UartComponent::setup() { } else { ESP_LOGV(TAG, "Using Hardware Serial"); SerialUART *serial; - if (tx_hw == 0) { + if (hw_uart == 0) { serial = &Serial1; } else { serial = &Serial2; } - serial->setTX(this->tx_pin_->get_pin()); - serial->setRX(this->rx_pin_->get_pin()); + if (this->tx_pin_ != nullptr) + serial->setTX(this->tx_pin_->get_pin()); + if (this->rx_pin_ != nullptr) + serial->setRX(this->rx_pin_->get_pin()); serial->setFIFOSize(this->rx_buffer_size_); serial->begin(this->baud_rate_, config); this->serial_ = serial; diff --git a/tests/components/uart/test.rp2040-ard.yaml b/tests/components/uart/test.rp2040-ard.yaml index 5eb2b533ea..1d5f91c6a7 100644 --- a/tests/components/uart/test.rp2040-ard.yaml +++ b/tests/components/uart/test.rp2040-ard.yaml @@ -23,3 +23,6 @@ uart: baud_rate: 115200 debug: debug_prefix: "[UART1] " + - id: uart_rx_only + rx_pin: 17 + baud_rate: 1200 From 05d285ba861572e5af149676dfe763edc39129c1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:53 -1000 Subject: [PATCH 1315/2030] [api] Fix heap-buffer-overflow in protobuf message dump for StringRef (#14721) --- esphome/components/api/api_pb2_dump.cpp | 2 +- script/api_protobuf/api_protobuf.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 740bf2e47f..5a53f0281f 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -13,7 +13,7 @@ namespace esphome::api { static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { - out.append(ref.c_str()); + out.append(ref.c_str(), ref.size()); } out.append("'"); } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index b4044c362c..dff6c7690a 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -642,7 +642,7 @@ class StringType(TypeInfo): # For SOURCE_BOTH, check if StringRef is set (sending) or use string (received) return ( f"if (!this->{self.field_name}_ref_.empty()) {{" - f' out.append("\'").append(this->{self.field_name}_ref_.c_str()).append("\'");' + f' out.append("\'").append(this->{self.field_name}_ref_.c_str(), this->{self.field_name}_ref_.size()).append("\'");' f"}} else {{" f' out.append("\'").append(this->{self.field_name}).append("\'");' f"}}" @@ -2705,7 +2705,7 @@ namespace esphome::api { static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { - out.append(ref.c_str()); + out.append(ref.c_str(), ref.size()); } out.append("'"); } From 25c74c8f99bb1948d9ceece698f4d8d5a80a8a53 Mon Sep 17 00:00:00 2001 From: Brian Kaufman <bkaufx@gmail.com> Date: Thu, 12 Mar 2026 16:23:29 -0700 Subject: [PATCH 1316/2030] [OTA] Stage exact uploaded size for ESP8266 web OTA (gzip fix) (#14741) --- esphome/components/ota/ota_backend_esp8266.cpp | 7 +++++-- esphome/components/ota/ota_backend_esp8266.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota/ota_backend_esp8266.cpp b/esphome/components/ota/ota_backend_esp8266.cpp index 1f9a77e426..93e6249fb3 100644 --- a/esphome/components/ota/ota_backend_esp8266.cpp +++ b/esphome/components/ota/ota_backend_esp8266.cpp @@ -105,6 +105,7 @@ OTAResponseTypes ESP8266OTABackend::begin(size_t image_size) { this->current_address_ = this->start_address_; this->image_size_ = image_size; + this->bytes_received_ = 0; this->buffer_len_ = 0; this->md5_set_ = false; @@ -140,6 +141,7 @@ OTAResponseTypes ESP8266OTABackend::write(uint8_t *data, size_t len) { size_t to_buffer = std::min(len - written, this->buffer_size_ - this->buffer_len_); memcpy(this->buffer_.get() + this->buffer_len_, data + written, to_buffer); this->buffer_len_ += to_buffer; + this->bytes_received_ += to_buffer; written += to_buffer; // If buffer is full, write to flash @@ -252,8 +254,8 @@ OTAResponseTypes ESP8266OTABackend::end() { } } - // Calculate actual bytes written - size_t actual_size = this->current_address_ - this->start_address_; + // Calculate actual bytes written (exact uploaded size, excluding flash write padding) + size_t actual_size = this->bytes_received_; // Check if any data was written if (actual_size == 0) { @@ -304,6 +306,7 @@ void ESP8266OTABackend::abort() { this->buffer_.reset(); this->buffer_len_ = 0; this->image_size_ = 0; + this->bytes_received_ = 0; esp8266::preferences_prevent_write(false); } diff --git a/esphome/components/ota/ota_backend_esp8266.h b/esphome/components/ota/ota_backend_esp8266.h index 6213289acc..b364e216a3 100644 --- a/esphome/components/ota/ota_backend_esp8266.h +++ b/esphome/components/ota/ota_backend_esp8266.h @@ -48,6 +48,7 @@ class ESP8266OTABackend final { uint32_t start_address_{0}; uint32_t current_address_{0}; size_t image_size_{0}; + size_t bytes_received_{0}; md5::MD5Digest md5_{}; uint8_t expected_md5_[16]; // Fixed-size buffer for 128-bit (16-byte) MD5 digest From fd8e510745542d097e2ab0dcc36352b428cd5f4e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 13:28:25 -1000 Subject: [PATCH 1317/2030] [light] Fix ambiguous set_effect overload for const char* (#14732) --- .../addressable_light/addressable_light_display.h | 2 +- esphome/components/light/light_call.cpp | 2 +- esphome/components/light/light_call.h | 2 ++ tests/components/light/common.yaml | 6 ++++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/esphome/components/addressable_light/addressable_light_display.h b/esphome/components/addressable_light/addressable_light_display.h index 53f8604b7d..d9b8680547 100644 --- a/esphome/components/addressable_light/addressable_light_display.h +++ b/esphome/components/addressable_light/addressable_light_display.h @@ -33,7 +33,7 @@ class AddressableLightDisplay : public display::DisplayBuffer { // - Save the current effect index. this->last_effect_index_ = light_state_->get_current_effect_index(); // - Disable any current effect. - light_state_->make_call().set_effect(0).perform(); + light_state_->make_call().set_effect(uint32_t{0}).perform(); } } enabled_ = enabled; diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 14cd0e92f6..cd45994f62 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -506,7 +506,7 @@ color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() { LightCall &LightCall::set_effect(const char *effect, size_t len) { if (len == 4 && strncasecmp(effect, "none", 4) == 0) { - this->set_effect(0); + this->set_effect(uint32_t{0}); return *this; } diff --git a/esphome/components/light/light_call.h b/esphome/components/light/light_call.h index 0926ab6108..0eb1785239 100644 --- a/esphome/components/light/light_call.h +++ b/esphome/components/light/light_call.h @@ -130,6 +130,8 @@ class LightCall { LightCall &set_effect(optional<std::string> effect); /// Set the effect of the light by its name. LightCall &set_effect(const std::string &effect) { return this->set_effect(effect.data(), effect.size()); } + /// Set the effect of the light by its name (const char * overload to resolve ambiguity). + LightCall &set_effect(const char *effect) { return this->set_effect(effect, strlen(effect)); } /// Set the effect of the light by its name and length (zero-copy from API). LightCall &set_effect(const char *effect, size_t len); /// Set the effect of the light by its internal index number (only for internal use). diff --git a/tests/components/light/common.yaml b/tests/components/light/common.yaml index e5fab62a79..e1216e7b60 100644 --- a/tests/components/light/common.yaml +++ b/tests/components/light/common.yaml @@ -60,6 +60,12 @@ esphome: } } + # Test set_effect with const char* doesn't cause ambiguous overload (issue #14728) + - lambda: |- + auto call = id(test_monochromatic_light).turn_on(); + call.set_effect("None"); + call.perform(); + - light.toggle: test_binary_light - light.turn_off: test_rgb_light - light.turn_on: From 7bb4e754591a4b3e56a6398dfeda1a0113e2ee81 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:47:16 -1000 Subject: [PATCH 1318/2030] [rp2040] Use full flash for sketch in testing mode (#14747) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/rp2040/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 276187b273..71e5f1488c 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -203,7 +203,12 @@ async def to_code(config): cg.add_build_flag(f"-Wl,--wrap={symbol}") cg.add_platformio_option("board_build.core", "earlephilhower") - cg.add_platformio_option("board_build.filesystem_size", "1m") + # In testing mode, use all flash for sketch to allow linking grouped component tests. + # Real RP2040 hardware uses 1MB filesystem + 1MB sketch, but CI tests may combine + # many components that exceed the 1MB sketch partition. + cg.add_platformio_option( + "board_build.filesystem_size", "0m" if CORE.testing_mode else "1m" + ) ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] cg.add_define( From 2ca13972b939a551278d6064c98d6660be69440a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:06 -1000 Subject: [PATCH 1319/2030] [debug] Fix missing reset reason for RP2040/RP2350 (#14740) --- esphome/components/debug/debug_rp2040.cpp | 64 +++++++++++++++++++++-- esphome/core/helpers.h | 22 ++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index c9d41942db..8dc84a2673 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -1,23 +1,81 @@ #include "debug_component.h" #ifdef USE_RP2040 +#include "esphome/core/defines.h" #include "esphome/core/log.h" #include <Arduino.h> +#include <hardware/watchdog.h> +#if defined(PICO_RP2350) +#include <hardware/structs/powman.h> +#else +#include <hardware/structs/vreg_and_chip_reset.h> +#endif +#ifdef USE_RP2040_CRASH_HANDLER +#include "esphome/components/rp2040/crash_handler.h" +#endif namespace esphome { namespace debug { static const char *const TAG = "debug"; -const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { + char *buf = buffer.data(); + const size_t size = RESET_REASON_BUFFER_SIZE; + size_t pos = 0; + +#if defined(PICO_RP2350) + uint32_t chip_reset = powman_hw->chip_reset; + if (chip_reset & 0x04000000) // HAD_GLITCH_DETECT + pos = buf_append_str(buf, size, pos, "Power supply glitch|"); + if (chip_reset & 0x00040000) // HAD_RUN_LOW + pos = buf_append_str(buf, size, pos, "RUN pin|"); + if (chip_reset & 0x00020000) // HAD_BOR + pos = buf_append_str(buf, size, pos, "Brown-out|"); + if (chip_reset & 0x00010000) // HAD_POR + pos = buf_append_str(buf, size, pos, "Power-on reset|"); +#else + uint32_t chip_reset = vreg_and_chip_reset_hw->chip_reset; + if (chip_reset & 0x00010000) // HAD_RUN + pos = buf_append_str(buf, size, pos, "RUN pin|"); + if (chip_reset & 0x00000100) // HAD_POR + pos = buf_append_str(buf, size, pos, "Power-on reset|"); +#endif + + if (watchdog_caused_reboot()) { + bool handled = false; +#ifdef USE_RP2040_CRASH_HANDLER + if (rp2040::crash_handler_has_data()) { + pos = buf_append_str(buf, size, pos, "Crash (HardFault)|"); + handled = true; + } +#endif + if (!handled) { + if (watchdog_enable_caused_reboot()) { + pos = buf_append_str(buf, size, pos, "Watchdog timeout|"); + } else { + pos = buf_append_str(buf, size, pos, "Software reset|"); + } + } + } + + // Remove trailing '|' + if (pos > 0 && buf[pos - 1] == '|') { + buf[pos - 1] = '\0'; + } else if (pos == 0) { + return "Unknown"; + } + + return buf; +} const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } -uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); } +uint32_t DebugComponent::get_free_heap_() { return ::rp2040.getFreeHeap(); } size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> buffer, size_t pos) { constexpr size_t size = DEVICE_INFO_BUFFER_SIZE; char *buf = buffer.data(); - uint32_t cpu_freq = rp2040.f_cpu(); + uint32_t cpu_freq = ::rp2040.f_cpu(); ESP_LOGD(TAG, "CPU Frequency: %" PRIu32, cpu_freq); pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32, cpu_freq); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 70ac1574f0..b2517e2d7a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -942,6 +942,28 @@ __attribute__((format(printf, 4, 5))) inline size_t buf_append_printf(char *buf, } #endif +/// Safely append a string to buffer without format parsing, returning new position (capped at size). +/// More efficient than buf_append_printf for plain string literals. +/// @param buf Output buffer +/// @param size Total buffer size +/// @param pos Current position in buffer +/// @param str String to append (must not be null) +/// @return New position after appending (capped at size on overflow) +inline size_t buf_append_str(char *buf, size_t size, size_t pos, const char *str) { + if (pos >= size) { + return size; + } + size_t remaining = size - pos - 1; // reserve space for null terminator + size_t len = strlen(str); + if (len > remaining) { + len = remaining; + } + memcpy(buf + pos, str, len); + pos += len; + buf[pos] = '\0'; + return pos; +} + /// Concatenate a name with a separator and suffix using an efficient stack-based approach. /// This avoids multiple heap allocations during string construction. /// Maximum name length supported is 120 characters for friendly names. From e15b19b2237739c945010d8addb3108b06733219 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:29 -1000 Subject: [PATCH 1320/2030] [captive_portal] Fix captive portal inaccessible when web_server auth is configured (#14734) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/captive_portal/captive_portal.cpp | 4 ++-- esphome/components/web_server_base/web_server_base.cpp | 4 ++++ esphome/components/web_server_base/web_server_base.h | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 5af6ab29a2..183f16c5f8 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -61,7 +61,7 @@ void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) { // Defer save to main loop thread to avoid NVS operations from HTTP thread this->defer([ssid, psk]() { wifi::global_wifi_component->save_wifi_sta(ssid.c_str(), psk.c_str()); }); #endif - request->redirect(ESPHOME_F("/?save")); + request->send(200, ESPHOME_F("text/plain"), ESPHOME_F("Saved. Connecting...")); } void CaptivePortal::setup() { @@ -71,7 +71,7 @@ void CaptivePortal::setup() { void CaptivePortal::start() { this->base_->init(); if (!this->initialized_) { - this->base_->add_handler(this); + this->base_->add_handler_without_auth(this); } network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip(); diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index dbbcd10d8d..3e1baf34ba 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -11,6 +11,10 @@ void WebServerBase::add_handler(AsyncWebHandler *handler) { handler = new internal::AuthMiddlewareHandler(handler, &credentials_); } #endif + this->add_handler_without_auth(handler); +} + +void WebServerBase::add_handler_without_auth(AsyncWebHandler *handler) { this->handlers_.push_back(handler); if (this->server_ != nullptr) { this->server_->addHandler(handler); diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 54421c851e..48e13ad71e 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -122,6 +122,14 @@ class WebServerBase { #endif void add_handler(AsyncWebHandler *handler); + /** + * WARNING: Registers a handler that bypasses the USE_WEBSERVER_AUTH middleware. + * + * This should only be used for endpoints that are intentionally unauthenticated + * (for example, captive portal or very limited-status endpoints). For normal + * endpoints that should respect web server authentication, use add_handler(). + */ + void add_handler_without_auth(AsyncWebHandler *handler); void set_port(uint16_t port) { port_ = port; } uint16_t get_port() const { return port_; } From 89719cf4b2490e068c057db61f1dce782839f7d5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:41 -1000 Subject: [PATCH 1321/2030] [water_heater] Set OPERATION_MODE feature flag when modes are configured (#14748) --- .../template/water_heater/template_water_heater.cpp | 1 + tests/integration/test_water_heater_template.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index 73081d204b..092df6fdca 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -26,6 +26,7 @@ water_heater::WaterHeaterTraits TemplateWaterHeater::traits() { if (!this->supported_modes_.empty()) { traits.set_supported_modes(this->supported_modes_); + traits.add_feature_flags(water_heater::WATER_HEATER_SUPPORTS_OPERATION_MODE); } traits.set_supports_current_temperature(true); diff --git a/tests/integration/test_water_heater_template.py b/tests/integration/test_water_heater_template.py index 096d4c8461..d63d1d6984 100644 --- a/tests/integration/test_water_heater_template.py +++ b/tests/integration/test_water_heater_template.py @@ -102,7 +102,11 @@ async def test_water_heater_template( f"Expected target temp 60.0, got {initial_state.target_temperature}" ) - # Verify supported features: away mode and on/off (fixture has away + is_on lambdas) + # Verify supported features: operation mode, away mode, and on/off + assert ( + test_water_heater.supported_features + & WaterHeaterFeature.SUPPORTS_OPERATION_MODE + ) != 0, "Expected SUPPORTS_OPERATION_MODE in supported_features" assert ( test_water_heater.supported_features & WaterHeaterFeature.SUPPORTS_AWAY_MODE ) != 0, "Expected SUPPORTS_AWAY_MODE in supported_features" From 22b25724ae23dc19982baef702fad6061eb544c6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:55 -1000 Subject: [PATCH 1322/2030] [wifi] Reject EAP/WPA2 Enterprise config on unsupported platforms (#14746) --- esphome/components/wifi/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 2808d31311..480ccd65c5 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -166,6 +166,7 @@ TTLS_PHASE_2 = { } EAP_AUTH_SCHEMA = cv.All( + cv.only_on([Platform.ESP32, Platform.ESP8266]), cv.Schema( { cv.Optional(CONF_IDENTITY): cv.string_strict, From 7e8e085a040a946906085661253c8a8ba693f19f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:49:07 -1000 Subject: [PATCH 1323/2030] [light] Fix binary light spamming 'brightness not supported' warning with strobe effect (#14735) --- esphome/components/light/light_call.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index cd45994f62..0b2d391fd6 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -214,7 +214,14 @@ LightColorValues LightCall::validate_() { if (this->has_brightness() && this->brightness_ == 0.0f) { this->state_ = false; this->set_flag_(FLAG_HAS_STATE); - this->brightness_ = 1.0f; + if (color_mode & ColorCapability::BRIGHTNESS) { + // Reset brightness so the light has nonzero brightness when turned back on. + this->brightness_ = 1.0f; + } else { + // Light doesn't support brightness; clear the flag to avoid a spurious + // "brightness not supported" warning during capability validation. + this->clear_flag_(FLAG_HAS_BRIGHTNESS); + } } // Set color brightness to 100% if currently zero and a color is set. From 59c1368440f13bdc6baa0f40a21edfd7f99d71db Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:53:46 -1000 Subject: [PATCH 1324/2030] [i2c] Fix RP2040 I2C bus selection based on pin assignment (#14745) --- esphome/components/i2c/__init__.py | 37 ++++++++++++++++++++++ esphome/components/i2c/i2c_bus_arduino.cpp | 10 +++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index de3f2be674..1684f479ba 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -93,11 +93,31 @@ def _bus_declare_type(value): raise NotImplementedError +def _rp2040_i2c_controller(pin): + """Return the I2C controller number (0 or 1) for a given RP2040/RP2350 GPIO pin. + + See RP2040 datasheet Table 2 (section 1.4.3, "GPIO Functions"): + https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + See RP2350 datasheet Table 7 (section 9.4, "Function Select"): + https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf + """ + return (pin // 2) % 2 + + def validate_config(config): if CORE.is_esp32: return cv.require_framework_version( esp_idf=cv.Version(5, 4, 2), esp32_arduino=cv.Version(3, 2, 1) )(config) + if CORE.is_rp2040: + sda_controller = _rp2040_i2c_controller(config[CONF_SDA]) + scl_controller = _rp2040_i2c_controller(config[CONF_SCL]) + if sda_controller != scl_controller: + raise cv.Invalid( + f"SDA pin GPIO{config[CONF_SDA]} is on I2C{sda_controller} but " + f"SCL pin GPIO{config[CONF_SCL]} is on I2C{scl_controller}. " + f"Both pins must be on the same I2C controller." + ) return config @@ -146,6 +166,23 @@ def _final_validate(config): full_config = fv.full_config.get()[CONF_I2C] if CORE.using_zephyr and len(full_config) > 1: raise cv.Invalid("Second i2c is not implemented on Zephyr yet") + if CORE.is_rp2040: + if len(full_config) > 2: + raise cv.Invalid( + "The maximum number of I2C interfaces for RP2040/RP2350 is 2" + ) + if len(full_config) > 1: + controllers = [ + _rp2040_i2c_controller(conf[CONF_SDA]) for conf in full_config + ] + if len(set(controllers)) != len(controllers): + raise cv.Invalid( + "Multiple I2C buses are configured to use the same I2C controller. " + "Each bus must use pins on a different controller. " + "The I2C controller is determined by (gpio / 2) % 2: " + "even pin pairs (0-1, 4-5, 8-9, ...) use I2C0, " + "odd pin pairs (2-3, 6-7, 10-11, ...) use I2C1." + ) if CORE.is_esp32 and get_esp32_variant() in ESP32_I2C_CAPABILITIES: variant = get_esp32_variant() max_num = ESP32_I2C_CAPABILITIES[variant]["NUM"] diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index 5120eb4c00..47a06abe9e 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -20,12 +20,14 @@ void ArduinoI2CBus::setup() { #if defined(USE_ESP8266) wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory) #elif defined(USE_RP2040) - static bool first = true; - if (first) { + // Select Wire instance based on pin assignment, not definition order. + // I2C controller = (gpio / 2) % 2: even pairs (0-1,4-5,...) → I2C0, odd pairs (2-3,6-7,...) → I2C1 + // RP2040 datasheet Table 2 (section 1.4.3): https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + // RP2350 datasheet Table 7 (section 9.4): https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf + if ((this->sda_pin_ / 2) % 2 == 0) { wire_ = &Wire; - first = false; } else { - wire_ = &Wire1; // NOLINT(cppcoreguidelines-owning-memory) + wire_ = &Wire1; } #endif From a744261934717a3ab52c1e2ec252c0fd46c4ea8c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 15:12:22 -1000 Subject: [PATCH 1325/2030] [mdns] Fix RP2040 mDNS not restarting after WiFi reconnect (#14737) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/mdns/mdns_component.h | 4 +++ esphome/components/mdns/mdns_rp2040.cpp | 32 ++++++++++++++++++---- esphome/components/wifi/__init__.py | 7 ----- esphome/components/wifi/wifi_component.cpp | 14 ---------- esphome/components/wifi/wifi_component.h | 4 --- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index 13c8ccf288..47cad4bf71 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -129,6 +129,10 @@ class MDNSComponent final : public Component { #endif #ifdef USE_MDNS_STORE_SERVICES StaticVector<MDNSService, MDNS_SERVICE_COUNT> services_{}; +#endif +#ifdef USE_RP2040 + bool was_connected_{false}; + bool initialized_{false}; #endif void compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUNT> &services, char *mac_address_buf); }; diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index 05d991c1fa..c0b22aa84f 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -36,12 +36,32 @@ static void register_rp2040(MDNSComponent *, StaticVector<MDNSService, MDNS_SERV } void MDNSComponent::setup() { - this->setup_buffers_and_register_(register_rp2040); - // Schedule MDNS.update() via set_interval() instead of overriding loop(). - // This removes the component from the per-iteration loop list entirely, - // eliminating virtual dispatch overhead on every main loop cycle. - // See MDNS_UPDATE_INTERVAL_MS comment in mdns_component.h for safety analysis. - this->set_interval(MDNS_UPDATE_INTERVAL_MS, []() { MDNS.update(); }); + // RP2040's LEAmDNS library registers a LwipIntf::stateUpCB() callback to restart + // mDNS when the network interface reconnects. However, stateUpCB() is stubbed out + // in arduino-pico's LwipIntfCB.cpp because the original ESP8266 implementation used + // schedule_function() which doesn't exist in arduino-pico, and the callback can't + // safely run directly since netif status callbacks fire from IRQ context + // (PICO_CYW43_ARCH_THREADSAFE_BACKGROUND) while _restart() allocates UDP sockets. + // + // Workaround: defer MDNS.begin() and service registration until the network is + // connected (has an IP), then call notifyAPChange() on subsequent reconnects to + // restart mDNS probing and announcing — all from main loop context so it's + // thread-safe. + this->set_interval(MDNS_UPDATE_INTERVAL_MS, [this]() { + bool connected = network::is_connected(); + if (connected && !this->was_connected_) { + if (!this->initialized_) { + this->setup_buffers_and_register_(register_rp2040); + this->initialized_ = true; + } else { + MDNS.notifyAPChange(); + } + } + this->was_connected_ = connected; + if (this->initialized_) { + MDNS.update(); + } + }); } void MDNSComponent::on_shutdown() { diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 480ccd65c5..9f73b1cc6f 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -563,13 +563,6 @@ async def to_code(config): cg.add_library("ESP8266WiFi", None) elif CORE.is_rp2040: cg.add_library("WiFi", None) - # RP2040's mDNS library (LEAmDNS) relies on LwipIntf::stateUpCB() to restart - # mDNS when the network interface reconnects. However, this callback is disabled - # in the arduino-pico framework. As a workaround, we block component setup until - # WiFi is connected via can_proceed(), ensuring mDNS.begin() is called with an - # active connection. This define enables the loop priority sorting infrastructure - # used during the setup blocking phase. - cg.add_define("USE_LOOP_PRIORITY") if CORE.is_esp32: if config[CONF_ENABLE_BTM] or config[CONF_ENABLE_RRM]: diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 60764955cc..09f883ed61 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2109,20 +2109,6 @@ void WiFiComponent::retry_connect() { } } -#ifdef USE_RP2040 -// RP2040's mDNS library (LEAmDNS) relies on LwipIntf::stateUpCB() to restart -// mDNS when the network interface reconnects. However, this callback is disabled -// in the arduino-pico framework. As a workaround, we block component setup until -// WiFi is connected, ensuring mDNS.begin() is called with an active connection. - -bool WiFiComponent::can_proceed() { - if (!this->has_sta() || this->state_ == WIFI_COMPONENT_STATE_DISABLED || this->ap_setup_) { - return true; - } - return this->is_connected_(); -} -#endif - void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } bool WiFiComponent::is_connected_() const { return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index f340b708c9..883cc1344b 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -437,10 +437,6 @@ class WiFiComponent : public Component { void retry_connect(); -#ifdef USE_RP2040 - bool can_proceed() override; -#endif - void set_reboot_timeout(uint32_t reboot_timeout); bool is_connected() const { return this->connected_; } From 920af91db693e36ad54033db100ecbb3b2915c19 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 15:37:46 -1000 Subject: [PATCH 1326/2030] [rp2040] Fix compiler warnings in crash_handler and mdns (#14739) --- esphome/components/mdns/mdns_rp2040.cpp | 5 +++++ esphome/components/rp2040/crash_handler.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index c0b22aa84f..88f707afd3 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -7,7 +7,12 @@ #include "esphome/core/log.h" #include "mdns_component.h" +// Arduino-Pico's PolledTimeout.h (pulled in by ESP8266mDNS.h) redefines IRAM_ATTR to empty. +// Save and restore our definition around the include to avoid a redefinition warning. +#pragma push_macro("IRAM_ATTR") +#undef IRAM_ATTR #include <ESP8266mDNS.h> +#pragma pop_macro("IRAM_ATTR") namespace esphome::mdns { diff --git a/esphome/components/rp2040/crash_handler.cpp b/esphome/components/rp2040/crash_handler.cpp index 1f579c2d18..f9eb42a0f8 100644 --- a/esphome/components/rp2040/crash_handler.cpp +++ b/esphome/components/rp2040/crash_handler.cpp @@ -57,14 +57,14 @@ static const char *const TAG = "rp2040.crash"; // Placed in .noinit so BSS zero-init cannot race with crash_handler_read_and_clear(). // The valid field is explicitly cleared in crash_handler_read_and_clear() instead. -static struct { +static struct CrashData { bool valid; uint32_t pc; uint32_t lr; uint32_t sp; uint32_t backtrace[MAX_BACKTRACE]; uint8_t backtrace_count; -} __attribute__((section(".noinit"))) s_crash_data; +} s_crash_data __attribute__((section(".noinit"))); bool crash_handler_has_data() { return s_crash_data.valid; } From 15ec46abfe2f5f93a77cfdac7b8891a726a329f0 Mon Sep 17 00:00:00 2001 From: Michael Kerscher <github@kerscher-michael.de> Date: Fri, 13 Mar 2026 06:31:16 +0100 Subject: [PATCH 1327/2030] [vbus] add DeltaSol CS4 (Citrin Solar 1.3) (#12477) --- esphome/components/vbus/__init__.py | 1 + .../components/vbus/binary_sensor/__init__.py | 41 +++++ .../vbus/binary_sensor/vbus_binary_sensor.cpp | 19 +++ .../vbus/binary_sensor/vbus_binary_sensor.h | 17 +++ esphome/components/vbus/sensor/__init__.py | 141 +++++++++++++++++- .../components/vbus/sensor/vbus_sensor.cpp | 46 ++++++ esphome/components/vbus/sensor/vbus_sensor.h | 35 +++++ tests/components/vbus/common.yaml | 8 + 8 files changed, 307 insertions(+), 1 deletion(-) diff --git a/esphome/components/vbus/__init__.py b/esphome/components/vbus/__init__.py index 5790a9cce0..2663496456 100644 --- a/esphome/components/vbus/__init__.py +++ b/esphome/components/vbus/__init__.py @@ -19,6 +19,7 @@ CONF_DELTASOL_BS_2009 = "deltasol_bs_2009" CONF_DELTASOL_BS2 = "deltasol_bs2" CONF_DELTASOL_C = "deltasol_c" CONF_DELTASOL_CS2 = "deltasol_cs2" +CONF_DELTASOL_CS4 = "deltasol_cs4" CONF_DELTASOL_CS_PLUS = "deltasol_cs_plus" CONFIG_SCHEMA = uart.UART_DEVICE_SCHEMA.extend( diff --git a/esphome/components/vbus/binary_sensor/__init__.py b/esphome/components/vbus/binary_sensor/__init__.py index 70dda94300..85f1172166 100644 --- a/esphome/components/vbus/binary_sensor/__init__.py +++ b/esphome/components/vbus/binary_sensor/__init__.py @@ -20,6 +20,7 @@ from .. import ( CONF_DELTASOL_BS_PLUS, CONF_DELTASOL_C, CONF_DELTASOL_CS2, + CONF_DELTASOL_CS4, CONF_DELTASOL_CS_PLUS, CONF_VBUS_ID, VBus, @@ -31,6 +32,7 @@ DeltaSol_BS_2009 = vbus_ns.class_("DeltaSolBS2009BSensor", cg.Component) DeltaSol_BS2 = vbus_ns.class_("DeltaSolBS2BSensor", cg.Component) DeltaSol_C = vbus_ns.class_("DeltaSolCBSensor", cg.Component) DeltaSol_CS2 = vbus_ns.class_("DeltaSolCS2BSensor", cg.Component) +DeltaSol_CS4 = vbus_ns.class_("DeltaSolCS4BSensor", cg.Component) DeltaSol_CS_Plus = vbus_ns.class_("DeltaSolCSPlusBSensor", cg.Component) VBusCustom = vbus_ns.class_("VBusCustomBSensor", cg.Component) VBusCustomSub = vbus_ns.class_("VBusCustomSubBSensor", cg.Component) @@ -186,6 +188,28 @@ CONFIG_SCHEMA = cv.typed_schema( ), } ), + CONF_DELTASOL_CS4: cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(DeltaSol_CS4), + cv.GenerateID(CONF_VBUS_ID): cv.use_id(VBus), + cv.Optional(CONF_SENSOR1_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR2_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR3_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_SENSOR4_ERROR): binary_sensor.binary_sensor_schema( + device_class=DEVICE_CLASS_PROBLEM, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + } + ), CONF_DELTASOL_CS_PLUS: cv.COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(DeltaSol_CS_Plus), @@ -350,6 +374,23 @@ async def to_code(config): sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR4_ERROR]) cg.add(var.set_s4_error_bsensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_CS4: + cg.add(var.set_command(0x0100)) + cg.add(var.set_source(0x1122)) + cg.add(var.set_dest(0x0010)) + if CONF_SENSOR1_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR1_ERROR]) + cg.add(var.set_s1_error_bsensor(sens)) + if CONF_SENSOR2_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR2_ERROR]) + cg.add(var.set_s2_error_bsensor(sens)) + if CONF_SENSOR3_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR3_ERROR]) + cg.add(var.set_s3_error_bsensor(sens)) + if CONF_SENSOR4_ERROR in config: + sens = await binary_sensor.new_binary_sensor(config[CONF_SENSOR4_ERROR]) + cg.add(var.set_s4_error_bsensor(sens)) + elif config[CONF_MODEL] == CONF_DELTASOL_CS_PLUS: cg.add(var.set_command(0x0100)) cg.add(var.set_source(0x2211)) diff --git a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp index c1d7bc1b18..e598b1de6b 100644 --- a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp +++ b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.cpp @@ -110,6 +110,25 @@ void DeltaSolCS2BSensor::handle_message(std::vector<uint8_t> &message) { this->s4_error_bsensor_->publish_state(message[18] & 8); } +void DeltaSolCS4BSensor::dump_config() { + ESP_LOGCONFIG(TAG, "Deltasol CS4:"); + LOG_BINARY_SENSOR(" ", "Sensor 1 Error", this->s1_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 2 Error", this->s2_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 3 Error", this->s3_error_bsensor_); + LOG_BINARY_SENSOR(" ", "Sensor 4 Error", this->s4_error_bsensor_); +} + +void DeltaSolCS4BSensor::handle_message(std::vector<uint8_t> &message) { + if (this->s1_error_bsensor_ != nullptr) + this->s1_error_bsensor_->publish_state(message[20] & 1); + if (this->s2_error_bsensor_ != nullptr) + this->s2_error_bsensor_->publish_state(message[20] & 2); + if (this->s3_error_bsensor_ != nullptr) + this->s3_error_bsensor_->publish_state(message[20] & 4); + if (this->s4_error_bsensor_ != nullptr) + this->s4_error_bsensor_->publish_state(message[20] & 8); +} + void DeltaSolCSPlusBSensor::dump_config() { ESP_LOGCONFIG(TAG, "Deltasol CS Plus:"); LOG_BINARY_SENSOR(" ", "Sensor 1 Error", this->s1_error_bsensor_); diff --git a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h index 2decdde602..04c9a7b826 100644 --- a/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h +++ b/esphome/components/vbus/binary_sensor/vbus_binary_sensor.h @@ -94,6 +94,23 @@ class DeltaSolCS2BSensor : public VBusListener, public Component { void handle_message(std::vector<uint8_t> &message) override; }; +class DeltaSolCS4BSensor : public VBusListener, public Component { + public: + void dump_config() override; + void set_s1_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s1_error_bsensor_ = bsensor; } + void set_s2_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s2_error_bsensor_ = bsensor; } + void set_s3_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s3_error_bsensor_ = bsensor; } + void set_s4_error_bsensor(binary_sensor::BinarySensor *bsensor) { this->s4_error_bsensor_ = bsensor; } + + protected: + binary_sensor::BinarySensor *s1_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s2_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s3_error_bsensor_{nullptr}; + binary_sensor::BinarySensor *s4_error_bsensor_{nullptr}; + + void handle_message(std::vector<uint8_t> &message) override; +}; + class DeltaSolCSPlusBSensor : public VBusListener, public Component { public: void dump_config() override; diff --git a/esphome/components/vbus/sensor/__init__.py b/esphome/components/vbus/sensor/__init__.py index ff8ef98a1a..9c3665eb1c 100644 --- a/esphome/components/vbus/sensor/__init__.py +++ b/esphome/components/vbus/sensor/__init__.py @@ -36,6 +36,7 @@ from .. import ( CONF_DELTASOL_BS_PLUS, CONF_DELTASOL_C, CONF_DELTASOL_CS2, + CONF_DELTASOL_CS4, CONF_DELTASOL_CS_PLUS, CONF_VBUS_ID, VBus, @@ -47,6 +48,7 @@ DeltaSol_BS_2009 = vbus_ns.class_("DeltaSolBS2009Sensor", cg.Component) DeltaSol_BS2 = vbus_ns.class_("DeltaSolBS2Sensor", cg.Component) DeltaSol_C = vbus_ns.class_("DeltaSolCSensor", cg.Component) DeltaSol_CS2 = vbus_ns.class_("DeltaSolCS2Sensor", cg.Component) +DeltaSol_CS4 = vbus_ns.class_("DeltaSolCS4Sensor", cg.Component) DeltaSol_CS_Plus = vbus_ns.class_("DeltaSolCSPlusSensor", cg.Component) VBusCustom = vbus_ns.class_("VBusCustomSensor", cg.Component) VBusCustomSub = vbus_ns.class_("VBusCustomSubSensor", cg.Component) @@ -438,6 +440,99 @@ CONFIG_SCHEMA = cv.typed_schema( ), } ), + CONF_DELTASOL_CS4: cv.COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(DeltaSol_CS4), + cv.GenerateID(CONF_VBUS_ID): cv.use_id(VBus), + cv.Optional(CONF_TEMPERATURE_1): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_2): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_3): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_4): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_TEMPERATURE_5): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + icon=ICON_THERMOMETER, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PUMP_SPEED_1): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PUMP_SPEED_2): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + icon=ICON_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_OPERATING_HOURS_1): sensor.sensor_schema( + unit_of_measurement=UNIT_HOUR, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DURATION, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_OPERATING_HOURS_2): sensor.sensor_schema( + unit_of_measurement=UNIT_HOUR, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DURATION, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_HEAT_QUANTITY): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + icon=ICON_RADIATOR, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional(CONF_TIME): sensor.sensor_schema( + unit_of_measurement=UNIT_MINUTE, + icon=ICON_TIMER, + accuracy_decimals=0, + device_class=DEVICE_CLASS_DURATION, + state_class=STATE_CLASS_MEASUREMENT, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_VERSION): sensor.sensor_schema( + accuracy_decimals=2, + entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + ), + cv.Optional(CONF_FLOW_RATE): sensor.sensor_schema( + accuracy_decimals=0, + device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ), CONF_DELTASOL_CS_PLUS: cv.COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(DeltaSol_CS_Plus), @@ -734,7 +829,51 @@ async def to_code(config): sens = await sensor.new_sensor(config[CONF_VERSION]) cg.add(var.set_version_sensor(sens)) - if config[CONF_MODEL] == CONF_DELTASOL_CS_PLUS: + elif config[CONF_MODEL] == CONF_DELTASOL_CS4: + cg.add(var.set_command(0x0100)) + cg.add(var.set_source(0x1122)) + cg.add(var.set_dest(0x0010)) + if CONF_TEMPERATURE_1 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_1]) + cg.add(var.set_temperature1_sensor(sens)) + if CONF_TEMPERATURE_2 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_2]) + cg.add(var.set_temperature2_sensor(sens)) + if CONF_TEMPERATURE_3 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_3]) + cg.add(var.set_temperature3_sensor(sens)) + if CONF_TEMPERATURE_4 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_4]) + cg.add(var.set_temperature4_sensor(sens)) + if CONF_TEMPERATURE_5 in config: + sens = await sensor.new_sensor(config[CONF_TEMPERATURE_5]) + cg.add(var.set_temperature5_sensor(sens)) + if CONF_PUMP_SPEED_1 in config: + sens = await sensor.new_sensor(config[CONF_PUMP_SPEED_1]) + cg.add(var.set_pump_speed1_sensor(sens)) + if CONF_PUMP_SPEED_2 in config: + sens = await sensor.new_sensor(config[CONF_PUMP_SPEED_2]) + cg.add(var.set_pump_speed2_sensor(sens)) + if CONF_OPERATING_HOURS_1 in config: + sens = await sensor.new_sensor(config[CONF_OPERATING_HOURS_1]) + cg.add(var.set_operating_hours1_sensor(sens)) + if CONF_OPERATING_HOURS_2 in config: + sens = await sensor.new_sensor(config[CONF_OPERATING_HOURS_2]) + cg.add(var.set_operating_hours2_sensor(sens)) + if CONF_HEAT_QUANTITY in config: + sens = await sensor.new_sensor(config[CONF_HEAT_QUANTITY]) + cg.add(var.set_heat_quantity_sensor(sens)) + if CONF_TIME in config: + sens = await sensor.new_sensor(config[CONF_TIME]) + cg.add(var.set_time_sensor(sens)) + if CONF_VERSION in config: + sens = await sensor.new_sensor(config[CONF_VERSION]) + cg.add(var.set_version_sensor(sens)) + if CONF_FLOW_RATE in config: + sens = await sensor.new_sensor(config[CONF_FLOW_RATE]) + cg.add(var.set_flow_rate_sensor(sens)) + + elif config[CONF_MODEL] == CONF_DELTASOL_CS_PLUS: cg.add(var.set_command(0x0100)) cg.add(var.set_source(0x2211)) cg.add(var.set_dest(0x0010)) diff --git a/esphome/components/vbus/sensor/vbus_sensor.cpp b/esphome/components/vbus/sensor/vbus_sensor.cpp index 75c9ea1aee..1cabb49703 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.cpp +++ b/esphome/components/vbus/sensor/vbus_sensor.cpp @@ -168,6 +168,52 @@ void DeltaSolCS2Sensor::handle_message(std::vector<uint8_t> &message) { this->version_sensor_->publish_state(get_u16(message, 28) * 0.01f); } +void DeltaSolCS4Sensor::dump_config() { + ESP_LOGCONFIG(TAG, "Deltasol CS4:"); + LOG_SENSOR(" ", "Temperature 1", this->temperature1_sensor_); + LOG_SENSOR(" ", "Temperature 2", this->temperature2_sensor_); + LOG_SENSOR(" ", "Temperature 3", this->temperature3_sensor_); + LOG_SENSOR(" ", "Temperature 4", this->temperature4_sensor_); + LOG_SENSOR(" ", "Temperature 5", this->temperature5_sensor_); + LOG_SENSOR(" ", "Pump Speed 1", this->pump_speed1_sensor_); + LOG_SENSOR(" ", "Pump Speed 2", this->pump_speed2_sensor_); + LOG_SENSOR(" ", "Operating Hours 1", this->operating_hours1_sensor_); + LOG_SENSOR(" ", "Operating Hours 2", this->operating_hours2_sensor_); + LOG_SENSOR(" ", "Heat Quantity", this->heat_quantity_sensor_); + LOG_SENSOR(" ", "System Time", this->time_sensor_); + LOG_SENSOR(" ", "FW Version", this->version_sensor_); + LOG_SENSOR(" ", "Flow Rate", this->flow_rate_sensor_); +} + +void DeltaSolCS4Sensor::handle_message(std::vector<uint8_t> &message) { + if (this->temperature1_sensor_ != nullptr) + this->temperature1_sensor_->publish_state(get_i16(message, 0) * 0.1f); + if (this->temperature2_sensor_ != nullptr) + this->temperature2_sensor_->publish_state(get_i16(message, 2) * 0.1f); + if (this->temperature3_sensor_ != nullptr) + this->temperature3_sensor_->publish_state(get_i16(message, 4) * 0.1f); + if (this->temperature4_sensor_ != nullptr) + this->temperature4_sensor_->publish_state(get_i16(message, 6) * 0.1f); + if (this->temperature5_sensor_ != nullptr) + this->temperature5_sensor_->publish_state(get_i16(message, 36) * 0.1f); + if (this->pump_speed1_sensor_ != nullptr) + this->pump_speed1_sensor_->publish_state(message[8]); + if (this->pump_speed2_sensor_ != nullptr) + this->pump_speed2_sensor_->publish_state(message[12]); + if (this->operating_hours1_sensor_ != nullptr) + this->operating_hours1_sensor_->publish_state(get_u16(message, 10)); + if (this->operating_hours2_sensor_ != nullptr) + this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); + if (this->heat_quantity_sensor_ != nullptr) + this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28)); + if (this->time_sensor_ != nullptr) + this->time_sensor_->publish_state(get_u16(message, 22)); + if (this->version_sensor_ != nullptr) + this->version_sensor_->publish_state(get_u16(message, 32) * 0.01f); + if (this->flow_rate_sensor_ != nullptr) + this->flow_rate_sensor_->publish_state(get_u16(message, 38)); +} + void DeltaSolCSPlusSensor::dump_config() { ESP_LOGCONFIG(TAG, "Deltasol CS Plus:"); LOG_SENSOR(" ", "Temperature 1", this->temperature1_sensor_); diff --git a/esphome/components/vbus/sensor/vbus_sensor.h b/esphome/components/vbus/sensor/vbus_sensor.h index cea2ee1c86..ea248b1db2 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.h +++ b/esphome/components/vbus/sensor/vbus_sensor.h @@ -122,6 +122,41 @@ class DeltaSolCS2Sensor : public VBusListener, public Component { void handle_message(std::vector<uint8_t> &message) override; }; +class DeltaSolCS4Sensor : public VBusListener, public Component { + public: + void dump_config() override; + void set_temperature1_sensor(sensor::Sensor *sensor) { this->temperature1_sensor_ = sensor; } + void set_temperature2_sensor(sensor::Sensor *sensor) { this->temperature2_sensor_ = sensor; } + void set_temperature3_sensor(sensor::Sensor *sensor) { this->temperature3_sensor_ = sensor; } + void set_temperature4_sensor(sensor::Sensor *sensor) { this->temperature4_sensor_ = sensor; } + void set_temperature5_sensor(sensor::Sensor *sensor) { this->temperature5_sensor_ = sensor; } + void set_pump_speed1_sensor(sensor::Sensor *sensor) { this->pump_speed1_sensor_ = sensor; } + void set_pump_speed2_sensor(sensor::Sensor *sensor) { this->pump_speed2_sensor_ = sensor; } + void set_operating_hours1_sensor(sensor::Sensor *sensor) { this->operating_hours1_sensor_ = sensor; } + void set_operating_hours2_sensor(sensor::Sensor *sensor) { this->operating_hours2_sensor_ = sensor; } + void set_heat_quantity_sensor(sensor::Sensor *sensor) { this->heat_quantity_sensor_ = sensor; } + void set_time_sensor(sensor::Sensor *sensor) { this->time_sensor_ = sensor; } + void set_version_sensor(sensor::Sensor *sensor) { this->version_sensor_ = sensor; } + void set_flow_rate_sensor(sensor::Sensor *sensor) { this->flow_rate_sensor_ = sensor; } + + protected: + sensor::Sensor *temperature1_sensor_{nullptr}; + sensor::Sensor *temperature2_sensor_{nullptr}; + sensor::Sensor *temperature3_sensor_{nullptr}; + sensor::Sensor *temperature4_sensor_{nullptr}; + sensor::Sensor *temperature5_sensor_{nullptr}; + sensor::Sensor *pump_speed1_sensor_{nullptr}; + sensor::Sensor *pump_speed2_sensor_{nullptr}; + sensor::Sensor *operating_hours1_sensor_{nullptr}; + sensor::Sensor *operating_hours2_sensor_{nullptr}; + sensor::Sensor *heat_quantity_sensor_{nullptr}; + sensor::Sensor *time_sensor_{nullptr}; + sensor::Sensor *version_sensor_{nullptr}; + sensor::Sensor *flow_rate_sensor_{nullptr}; + + void handle_message(std::vector<uint8_t> &message) override; +}; + class DeltaSolCSPlusSensor : public VBusListener, public Component { public: void dump_config() override; diff --git a/tests/components/vbus/common.yaml b/tests/components/vbus/common.yaml index 5c771be922..bdd75a2b97 100644 --- a/tests/components/vbus/common.yaml +++ b/tests/components/vbus/common.yaml @@ -19,6 +19,10 @@ binary_sensor: name: BS2 Sensor 3 Error sensor4_error: name: BS2 Sensor 4 Error + - platform: vbus + model: deltasol_cs4 + sensor1_error: + name: "DeltaSol CS4 Sensor 1 Error" - platform: vbus model: custom command: 0x100 @@ -44,6 +48,10 @@ sensor: name: DeltaSol C Heat Quantity time: name: DeltaSol C System Time + - platform: vbus + model: deltasol_cs4 + temperature_1: + name: "DeltaSol CS4 Temperature 1" - platform: vbus model: deltasol_bs2 temperature_1: From 7524590bcfe3fb3e28cdaf4d33b9f9f1a41201f2 Mon Sep 17 00:00:00 2001 From: Thomas SAMTER <7680607+P4uLT@users.noreply.github.com> Date: Fri, 13 Mar 2026 14:17:11 +0100 Subject: [PATCH 1328/2030] [const] Add CONF_CLIMATE_ID for climate component sub-entities (#14764) --- esphome/components/const/__init__.py | 1 + esphome/components/pid/sensor/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index 059bf3f26a..f6da32569f 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -3,6 +3,7 @@ CODEOWNERS = ["@esphome/core"] CONF_BYTE_ORDER = "byte_order" +CONF_CLIMATE_ID = "climate_id" BYTE_ORDER_LITTLE = "little_endian" BYTE_ORDER_BIG = "big_endian" diff --git a/esphome/components/pid/sensor/__init__.py b/esphome/components/pid/sensor/__init__.py index 4547f4d708..d26e88e38a 100644 --- a/esphome/components/pid/sensor/__init__.py +++ b/esphome/components/pid/sensor/__init__.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.const import CONF_CLIMATE_ID import esphome.config_validation as cv from esphome.const import CONF_TYPE, ICON_GAUGE, STATE_CLASS_MEASUREMENT, UNIT_PERCENT @@ -21,7 +22,6 @@ PID_CLIMATE_SENSOR_TYPES = { "KD": PIDClimateSensorType.PID_SENSOR_TYPE_KD, } -CONF_CLIMATE_ID = "climate_id" CONFIG_SCHEMA = ( sensor.sensor_schema( PIDClimateSensor, From 326769e43c8c85f6bcb8001301028f7be805acf8 Mon Sep 17 00:00:00 2001 From: Kjell Braden <afflux@pentabarf.de> Date: Fri, 13 Mar 2026 14:18:42 +0100 Subject: [PATCH 1329/2030] [runtime_image] fix BMP parsing (#14762) --- .../components/runtime_image/bmp_decoder.h | 4 + .../fixtures/online_image_bmp.yaml | 27 ++++ tests/integration/test_online_image_bmp.py | 119 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 tests/integration/fixtures/online_image_bmp.yaml create mode 100644 tests/integration/test_online_image_bmp.py diff --git a/esphome/components/runtime_image/bmp_decoder.h b/esphome/components/runtime_image/bmp_decoder.h index 73e54f5430..a52a561584 100644 --- a/esphome/components/runtime_image/bmp_decoder.h +++ b/esphome/components/runtime_image/bmp_decoder.h @@ -26,6 +26,10 @@ class BmpDecoder : public ImageDecoder { int HOT decode(uint8_t *buffer, size_t size) override; bool is_finished() const override { + if (this->bits_per_pixel_ == 0) { + // header not yet received, so dimensions not yet determined + return false; + } // BMP is finished when we've decoded all pixel data return this->paint_index_ >= static_cast<size_t>(this->width_ * this->height_); } diff --git a/tests/integration/fixtures/online_image_bmp.yaml b/tests/integration/fixtures/online_image_bmp.yaml new file mode 100644 index 0000000000..e36514e9ae --- /dev/null +++ b/tests/integration/fixtures/online_image_bmp.yaml @@ -0,0 +1,27 @@ +esphome: + name: online-image-bmp + +host: + +http_request: + +display: + +online_image: + - url: http://127.0.0.1:HTTP_PORT/foo.bmp + id: myimg + format: BMP + type: RGB + on_download_finished: + logger.log: + format: "download finished. cache hit: %u" + args: [cached] + +api: + actions: + - action: fetch_image + then: + - component.update: myimg + +logger: + level: DEBUG diff --git a/tests/integration/test_online_image_bmp.py b/tests/integration/test_online_image_bmp.py new file mode 100644 index 0000000000..7c32154fdd --- /dev/null +++ b/tests/integration/test_online_image_bmp.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + +# black 8x8 RGB BMP, generated with +# from PIL import Image +# from io import BytesIO +# b = BytesIO() +# img = Image.new("RGB", (8, 8)) +# img.save(b, format="BMP") +# b.getvalue() +BMP_IMAGE = b"BM\xf6\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x08\x00\x00\x00\x08\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\xc0\x00\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +LEN_BMP_IMAGE = len(BMP_IMAGE) + + +def handle_http(http_request_future): + async def handler(reader, writer): + try: + async with asyncio.timeout(1.0): + data = await reader.readuntil(b"\r\n") + + # ensure our request matches the expectation + expected_request = b"GET /foo.bmp HTTP/1.1\r\n" + assert data[: len(expected_request)] == expected_request + + # consume rest of request + async with asyncio.timeout(1.0): + data = await reader.readuntil(b"\r\n\r\n") + + http_request_future.set_result(True) + + http_response = [ + b"HTTP/1.1 200 OK", + b"Content-Length: %d" % LEN_BMP_IMAGE, + b"Content-Type: text/plain", + b"Connection: close", + b"", + b"", + ] + writer.write(b"\r\n".join(http_response)) + await writer.drain() + + writer.write(BMP_IMAGE) + + await writer.drain() + except Exception as exc: + if not http_request_future.done(): + http_request_future.set_exception(exc) + raise + finally: + writer.close() + + return handler + + +@pytest.mark.asyncio +async def test_online_image_bmp( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Esphome shouldn't block the main loop when a http response is slow""" + loop = asyncio.get_running_loop() + + # Track http request + http_request_future = loop.create_future() + download_finished_future = loop.create_future() + downloaded_bytes_future = loop.create_future() + + def check_output(line: str) -> None: + """Check log output for expected messages.""" + + if match := re.search(r"Image fully downloaded, (\d+) bytes", line): + downloaded_bytes_future.set_result(int(match.group(1))) + + if "download finished" in line: + download_finished_future.set_result(True) + + server = await asyncio.start_server( + handle_http(http_request_future), "127.0.0.1", 0 + ) + http_server_port = server.sockets[0].getsockname()[1] + + config = yaml_config.replace("HTTP_PORT", str(http_server_port)) + + # Run with log monitoring + async with ( + server, + run_compiled(config, line_callback=check_output), + api_client_connected() as client, + ): + # Verify device info + + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "online-image-bmp" + + # List services to find our test service + _, services = await client.list_entities_services() + + # Find test service + request_service = next((s for s in services if s.name == "fetch_image"), None) + + assert request_service is not None, "fetch_image service not found" + + await client.execute_service(request_service, {}) + + async with asyncio.timeout(0.1): + await http_request_future + + async with asyncio.timeout(0.5): + numbytes = await downloaded_bytes_future + assert numbytes == LEN_BMP_IMAGE + await download_finished_future From 5920fa97e4b671e424f7d53cbbcb1bd1ba8d250c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 03:20:50 -1000 Subject: [PATCH 1330/2030] [select] Fix -Wmaybe-uninitialized warnings on ESP8266 (#14759) --- esphome/components/select/select_call.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 45fb42c116..83f5052fc8 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -41,7 +41,7 @@ SelectCall &SelectCall::with_index(size_t index) { this->operation_ = SELECT_OP_SET; if (index >= this->parent_->size()) { ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", this->parent_->get_name().c_str(), index); - this->index_ = {}; // Store nullopt for invalid index + this->index_ = nullopt; // Store nullopt for invalid index } else { this->index_ = index; } @@ -52,7 +52,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { const auto &options = this->parent_->traits.get_options(); if (options.empty()) { ESP_LOGW(TAG, "'%s' - Select has no options", name); - return {}; + return nullopt; } if (this->operation_ == SELECT_OP_FIRST) { @@ -67,7 +67,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { ESP_LOGD(TAG, "'%s' - Setting", name); if (!this->index_.has_value()) { ESP_LOGW(TAG, "'%s' - No option set", name); - return {}; + return nullopt; } return this->index_; } @@ -96,7 +96,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { return active_index + 1; } - return {}; // Can't navigate further without cycling + return nullopt; // Can't navigate further without cycling } void SelectCall::perform() { From 8936be628f4cd4d223aeefa6bed333682073db84 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 07:37:30 -1000 Subject: [PATCH 1331/2030] [api] Increase log Nagle coalescing on all platforms except ESP8266 (#14752) --- esphome/components/api/api_frame_helper.h | 24 ++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 98de24501e..5e07ad43a9 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -134,12 +134,16 @@ class APIFrameHelper { // // For log messages: Use Nagle to coalesce multiple small log packets into // fewer larger packets, reducing WiFi overhead. However, we limit batching - // to 3 messages to avoid excessive LWIP buffer pressure on memory-constrained - // devices like ESP8266. LWIP's TCP_OVERSIZE option coalesces the data into - // shared pbufs, but holding data too long waiting for Nagle's timer causes - // buffer exhaustion and dropped messages. + // to avoid excessive LWIP buffer pressure on memory-constrained devices. + // LWIP's TCP_OVERSIZE option coalesces the data into shared pbufs, but + // holding data too long waiting for Nagle's timer causes buffer exhaustion + // and dropped messages. // - // Flow: Log 1 (Nagle on) -> Log 2 (Nagle on) -> Log 3 (NODELAY, flush all) + // ESP32 (TCP_SND_BUF=4×MSS+) / RP2040 (8×MSS) / LibreTiny (4×MSS): 4 logs per cycle + // ESP8266 (2×MSS): 3 logs per cycle (tightest buffers) + // + // Flow (ESP32/RP2040/LT): Log 1 (Nagle on) -> Log 2 -> Log 3 -> Log 4 (NODELAY, flush) + // Flow (ESP8266): Log 1 (Nagle on) -> Log 2 -> Log 3 (NODELAY, flush all) // void set_nodelay_for_message(bool is_log_message) { if (!is_log_message) { @@ -150,7 +154,7 @@ class APIFrameHelper { return; } - // Log messages 1-3: state transitions -1 -> 1 -> 2 -> -1 (flush on 3rd) + // Log messages: state transitions -1 -> 1 -> ... -> LOG_NAGLE_COUNT -> -1 (flush) if (this->nodelay_state_ == NODELAY_ON) { this->set_nodelay_raw_(false); this->nodelay_state_ = 1; @@ -255,10 +259,16 @@ class APIFrameHelper { uint8_t tx_buf_tail_{0}; uint8_t tx_buf_count_{0}; // Nagle batching state for log messages. NODELAY_ON (-1) means NODELAY is enabled - // (immediate send). Values 1-2 count log messages in the current Nagle batch. + // (immediate send). Values 1..LOG_NAGLE_COUNT count log messages in the current Nagle batch. // After LOG_NAGLE_COUNT logs, we switch to NODELAY to flush and reset. + // ESP8266 has the tightest TCP send buffer (2×MSS) and needs conservative batching. + // ESP32 (4×MSS+), RP2040 (8×MSS), and LibreTiny (4×MSS) can coalesce more. static constexpr int8_t NODELAY_ON = -1; +#ifdef USE_ESP8266 static constexpr int8_t LOG_NAGLE_COUNT = 2; +#else + static constexpr int8_t LOG_NAGLE_COUNT = 3; +#endif int8_t nodelay_state_{NODELAY_ON}; // Internal helper to set TCP_NODELAY socket option From bd844fcd0aa0cf9857f4a548d58543b7fe020331 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 07:37:44 -1000 Subject: [PATCH 1332/2030] [template] Fix misleading 'Text value too long to save' warning (#14753) --- .../components/template/text/template_text.h | 32 ++--- .../fixtures/template_text_save.yaml | 23 +++ tests/integration/test_template_text_save.py | 131 ++++++++++++++++++ 3 files changed, 170 insertions(+), 16 deletions(-) create mode 100644 tests/integration/fixtures/template_text_save.yaml create mode 100644 tests/integration/test_template_text_save.py diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index 7f176db09e..229a61d9b8 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -24,23 +24,23 @@ class TemplateTextSaverBase { template<uint8_t SZ> class TextSaver : public TemplateTextSaverBase { public: bool save(const std::string &value) override { - int diff = value.compare(this->prev_); - if (diff != 0) { - // If string is bigger than the allocation, do not save it. - // We don't need to waste ram setting prev_value either. - int size = value.size(); - if (size <= SZ) { - // Make it into a length prefixed thing - unsigned char temp[SZ + 1]; - memcpy(temp + 1, value.c_str(), size); - // SZ should be pre checked at the schema level, it can't go past the char range. - temp[0] = ((unsigned char) size); - this->pref_.save(&temp); - this->prev_.assign(value); - return true; - } + if (value == this->prev_) { + return true; // No change, nothing to save } - return false; + // If string is bigger than the allocation, do not save it. + // We don't need to waste ram setting prev_value either. + int size = value.size(); + if (size > SZ) { + return false; + } + // Make it into a length prefixed thing + unsigned char temp[SZ + 1]; + memcpy(temp + 1, value.c_str(), size); + // SZ should be pre checked at the schema level, it can't go past the char range. + temp[0] = ((unsigned char) size); + this->pref_.save(&temp); + this->prev_.assign(value); + return true; } // Make the preference object. Fill the provided location with the saved data diff --git a/tests/integration/fixtures/template_text_save.yaml b/tests/integration/fixtures/template_text_save.yaml new file mode 100644 index 0000000000..526561732d --- /dev/null +++ b/tests/integration/fixtures/template_text_save.yaml @@ -0,0 +1,23 @@ +esphome: + name: host-template-text-save-test + +host: + +api: + batch_delay: 0ms + +logger: + +preferences: + flash_write_interval: 0s + +text: + - platform: template + name: "Test Text Restore" + id: test_text_restore + optimistic: true + min_length: 0 + max_length: 10 + mode: text + initial_value: "hello" + restore_value: true diff --git a/tests/integration/test_template_text_save.py b/tests/integration/test_template_text_save.py new file mode 100644 index 0000000000..47c8e3188a --- /dev/null +++ b/tests/integration/test_template_text_save.py @@ -0,0 +1,131 @@ +"""Integration test for template text restore_value persistence. + +Tests that: +1. A template text with restore_value saves its value to preferences +2. The saved value persists across restarts (binary re-run) +3. Setting the same value again does not produce a spurious "too long" warning +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path +import socket +from typing import Any + +from aioesphomeapi import TextInfo, TextState +import pytest + +from .conftest import run_binary_and_wait_for_port, wait_and_connect_api_client +from .state_utils import InitialStateHelper, require_entity +from .types import CompileFunction, ConfigWriter + + +@pytest.mark.asyncio +async def test_template_text_save( + yaml_config: str, + write_yaml_config: ConfigWriter, + compile_esphome: CompileFunction, + reserved_tcp_port: tuple[int, socket.socket], +) -> None: + """Test template text save/restore persistence and duplicate-save behavior.""" + port, port_socket = reserved_tcp_port + + # Clean up any stale preference file from previous runs + prefs_file = ( + Path.home() / ".esphome" / "prefs" / "host-template-text-save-test.prefs" + ) + if prefs_file.exists(): + prefs_file.unlink() + + # Write and compile once + config_path = await write_yaml_config(yaml_config) + binary_path = await compile_esphome(config_path) + + # Release the reserved port so the binary can bind to it + port_socket.close() + + # --- First run: set a value and verify no spurious warnings --- + warning_lines: list[str] = [] + + def capture_warnings(line: str) -> None: + if "too long to save" in line.lower(): + warning_lines.append(line) + + async with ( + run_binary_and_wait_for_port( + binary_path, "127.0.0.1", port, line_callback=capture_warnings + ), + wait_and_connect_api_client(port=port) as client, + ): + device_info = await client.device_info() + assert device_info.name == "host-template-text-save-test" + + entities, _ = await client.list_entities_services() + text_entity = require_entity( + entities, "test_text_restore", TextInfo, "Test Text Restore" + ) + + # Set up state tracking + loop = asyncio.get_running_loop() + state_futures: dict[int, asyncio.Future[Any]] = {} + + def on_state(state: Any) -> None: + if state.key in state_futures and not state_futures[state.key].done(): + state_futures[state.key].set_result(state) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + await initial_state_helper.wait_for_initial_states() + + # Verify initial value from config + initial = initial_state_helper.initial_states[text_entity.key] + assert isinstance(initial, TextState) + assert initial.state == "hello" + + async def wait_for_state(key: int, timeout: float = 2.0) -> Any: + state_futures[key] = loop.create_future() + try: + return await asyncio.wait_for(state_futures[key], timeout) + finally: + state_futures.pop(key, None) + + # Set a new value that fits within max_length + client.text_command(key=text_entity.key, state="world") + state = await wait_for_state(text_entity.key) + assert state.state == "world" + + # Set the same value again - should NOT produce "too long" warning + client.text_command(key=text_entity.key, state="world") + # Give time for the warning to appear (if any) + await asyncio.sleep(0.5) + + # No warnings should have appeared + assert warning_lines == [], ( + f"Unexpected 'too long to save' warning(s): {warning_lines}" + ) + + # --- Second run: verify the value was restored from preferences --- + async with ( + run_binary_and_wait_for_port(binary_path, "127.0.0.1", port), + wait_and_connect_api_client(port=port) as client, + ): + entities, _ = await client.list_entities_services() + text_entity = require_entity( + entities, "test_text_restore", TextInfo, "Test Text Restore" + ) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(lambda s: None)) + await initial_state_helper.wait_for_initial_states() + + # The value should be "world" - restored from preferences + restored = initial_state_helper.initial_states[text_entity.key] + assert isinstance(restored, TextState) + assert restored.state == "world", ( + f"Expected restored value 'world', got '{restored.state}'" + ) + + # Clean up preference file + if prefs_file.exists(): + prefs_file.unlink() From b147830ef954ed5d6c012a041c5b20ea7d88f93b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 13 Mar 2026 14:24:39 -0400 Subject: [PATCH 1333/2030] [core] Fix std::isnan conflict with picolibc on ESP-IDF 6.0 (#14768) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/core/config.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/core/config.py b/esphome/core/config.py index d4a839cb79..e112720f2b 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -589,7 +589,10 @@ async def _add_looping_components() -> None: async def to_code(config: ConfigType) -> None: cg.add_global(cg.global_ns.namespace("esphome").using) # These can be used by user lambdas, put them to default scope + # picolibc (IDF 6.0+) declares isnan in global scope, conflicting with using std::isnan + cg.add_global(cg.RawStatement("#ifndef __PICOLIBC__")) cg.add_global(cg.RawExpression("using std::isnan")) + cg.add_global(cg.RawStatement("#endif")) cg.add_global(cg.RawExpression("using std::min")) cg.add_global(cg.RawExpression("using std::max")) From 6700347a4894ca991a7176bac7a6227afd3289e3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 13 Mar 2026 14:47:12 -0400 Subject: [PATCH 1334/2030] [wifi] Fix ESP-IDF 6.0 compatibility (#14766) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/wifi/wifi_component.cpp | 2 +- esphome/components/wifi/wifi_component.h | 2 +- .../wifi/wifi_component_esp_idf.cpp | 44 +++++++++++++++---- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 09f883ed61..346276692a 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -6,7 +6,7 @@ #include <type_traits> #ifdef USE_ESP32 -#if (ESP_IDF_VERSION_MAJOR >= 5 && ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) #include <esp_eap_client.h> #else #include <esp_wpa2.h> diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 883cc1344b..aeb32352a9 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -18,7 +18,7 @@ #endif #if defined(USE_ESP32) && defined(USE_WIFI_WPA2_EAP) -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) #include <esp_eap_client.h> #else #include <esp_wpa2.h> diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index eca3f19249..2866ec1513 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -17,7 +17,7 @@ #include <memory> #include <utility> #ifdef USE_WIFI_WPA2_EAP -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) #include <esp_eap_client.h> #else #include <esp_wpa2.h> @@ -75,7 +75,11 @@ struct IDFWiFiEvent { #if USE_NETWORK_IPV6 ip_event_got_ip6_t ip_got_ip6; #endif /* USE_NETWORK_IPV6 */ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + ip_event_assigned_ip_to_client_t ip_assigned_ip_to_client; +#else ip_event_ap_staipassigned_t ip_ap_staipassigned; +#endif } data; }; @@ -116,8 +120,13 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi memcpy(&event.data.ap_staconnected, event_data, sizeof(wifi_event_ap_staconnected_t)); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) { memcpy(&event.data.ap_stadisconnected, event_data, sizeof(wifi_event_ap_stadisconnected_t)); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + } else if (event_base == IP_EVENT && event_id == IP_EVENT_ASSIGNED_IP_TO_CLIENT) { + memcpy(&event.data.ip_assigned_ip_to_client, event_data, sizeof(ip_event_assigned_ip_to_client_t)); +#else } else if (event_base == IP_EVENT && event_id == IP_EVENT_AP_STAIPASSIGNED) { memcpy(&event.data.ip_ap_staipassigned, event_data, sizeof(ip_event_ap_staipassigned_t)); +#endif } else { // did not match any event, don't send anything return; @@ -407,7 +416,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { if (eap_opt.has_value()) { // note: all certificates and keys have to be null terminated. Lengths are appended by +1 to include \0. EAPAuth eap = *eap_opt; -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); #else err = esp_wifi_sta_wpa2_ent_set_identity((uint8_t *) eap.identity.c_str(), eap.identity.length()); @@ -419,7 +428,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { int client_cert_len = strlen(eap.client_cert); int client_key_len = strlen(eap.client_key); if (ca_cert_len) { -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1); #else err = esp_wifi_sta_wpa2_ent_set_ca_cert((uint8_t *) eap.ca_cert, ca_cert_len + 1); @@ -432,7 +441,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // validation is not required as the config tool has already validated it if (client_cert_len && client_key_len) { // if we have certs, this must be EAP-TLS -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_certificate_and_key((uint8_t *) eap.client_cert, client_cert_len + 1, (uint8_t *) eap.client_key, client_key_len + 1, (uint8_t *) eap.password.c_str(), eap.password.length()); @@ -446,7 +455,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { } } else { // in the absence of certs, assume this is username/password based -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_username((uint8_t *) eap.username.c_str(), eap.username.length()); #else err = esp_wifi_sta_wpa2_ent_set_username((uint8_t *) eap.username.c_str(), eap.username.length()); @@ -454,7 +463,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { if (err != ESP_OK) { ESP_LOGV(TAG, "set_username failed %d", err); } -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_password((uint8_t *) eap.password.c_str(), eap.password.length()); #else err = esp_wifi_sta_wpa2_ent_set_password((uint8_t *) eap.password.c_str(), eap.password.length()); @@ -463,7 +472,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { ESP_LOGV(TAG, "set_password failed %d", err); } // set TTLS Phase 2, defaults to MSCHAPV2 -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_eap_client_set_ttls_phase2_method(eap.ttls_phase_2); #else err = esp_wifi_sta_wpa2_ent_set_ttls_phase2_method(eap.ttls_phase_2); @@ -472,7 +481,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { ESP_LOGV(TAG, "set_ttls_phase2_method failed %d", err); } } -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 1) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) err = esp_wifi_sta_enterprise_enable(); #else err = esp_wifi_sta_wpa2_ent_enable(); @@ -628,14 +637,26 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "Auth Expired"; case WIFI_REASON_AUTH_LEAVE: return "Auth Leave"; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + case WIFI_REASON_DISASSOC_DUE_TO_INACTIVITY: + return "Disassociated Due to Inactivity"; +#else case WIFI_REASON_ASSOC_EXPIRE: return "Association Expired"; +#endif case WIFI_REASON_ASSOC_TOOMANY: return "Too Many Associations"; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + case WIFI_REASON_CLASS2_FRAME_FROM_NONAUTH_STA: + return "Class 2 Frame from Non-Authenticated STA"; + case WIFI_REASON_CLASS3_FRAME_FROM_NONASSOC_STA: + return "Class 3 Frame from Non-Associated STA"; +#else case WIFI_REASON_NOT_AUTHED: return "Not Authenticated"; case WIFI_REASON_NOT_ASSOCED: return "Not Associated"; +#endif case WIFI_REASON_ASSOC_LEAVE: return "Association Leave"; case WIFI_REASON_ASSOC_NOT_AUTHED: @@ -688,7 +709,7 @@ const char *get_disconnect_reason_str(uint8_t reason) { return "Association comeback time too long"; case WIFI_REASON_SA_QUERY_TIMEOUT: return "SA query timeout"; -#if (ESP_IDF_VERSION_MAJOR >= 5) && (ESP_IDF_VERSION_MINOR >= 2) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) case WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY: return "No AP found with compatible security"; case WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD: @@ -917,8 +938,13 @@ void WiFiComponent::wifi_process_event_(IDFWiFiEvent *data) { ESP_LOGV(TAG, "AP client disconnected MAC=%s", mac_buf); #endif +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_ASSIGNED_IP_TO_CLIENT) { + const auto &it = data->data.ip_assigned_ip_to_client; +#else } else if (data->event_base == IP_EVENT && data->event_id == IP_EVENT_AP_STAIPASSIGNED) { const auto &it = data->data.ip_ap_staipassigned; +#endif ESP_LOGV(TAG, "AP client assigned IP " IPSTR, IP2STR(&it.ip)); } } From f41aa8b18c739f98a50f38f6e8cfbca945e04c1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:35:10 +0000 Subject: [PATCH 1335/2030] Bump ruff from 0.15.5 to 0.15.6 (#14774) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2d8f698395..5e2bfe09ce 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.5 + rev: v0.15.6 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 93a20896aa..acd8383a2f 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.5 # also change in .pre-commit-config.yaml when updating +ruff==0.15.6 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From a6c08576be6e87df3007d0c7cc11e780377604a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 10:17:40 -1000 Subject: [PATCH 1336/2030] [sensor] Use FixedRingBuffer in SlidingWindowFilter, add window_size limit (#14736) --- esphome/components/sensor/__init__.py | 34 +++---- esphome/components/sensor/filter.cpp | 34 ++----- esphome/components/sensor/filter.h | 33 +++---- esphome/core/helpers.h | 131 +++++++++++++++++++++++++- 4 files changed, 171 insertions(+), 61 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 4be6ed1b84..64d4dc4177 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -403,9 +403,9 @@ async def filter_out_filter_to_code(config, filter_id): QUANTILE_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), cv.Optional(CONF_QUANTILE, default=0.9): cv.zero_to_one_float, } ), @@ -427,9 +427,9 @@ async def quantile_filter_to_code(config, filter_id): MEDIAN_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), } ), validate_send_first_at, @@ -449,9 +449,9 @@ async def median_filter_to_code(config, filter_id): MIN_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), } ), validate_send_first_at, @@ -483,9 +483,9 @@ async def min_filter_to_code(config, filter_id): MAX_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), } ), validate_send_first_at, @@ -509,9 +509,9 @@ async def max_filter_to_code(config, filter_id): SLIDING_AVERAGE_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_WINDOW_SIZE, default=15): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=15): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), } ), validate_send_first_at, @@ -540,8 +540,8 @@ EXPONENTIAL_AVERAGE_SCHEMA = cv.All( cv.Schema( { cv.Optional(CONF_ALPHA, default=0.1): cv.positive_float, - cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + cv.Optional(CONF_SEND_EVERY, default=15): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), } ), validate_send_first_at, diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 0fe1effe17..d995ee4111 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -41,26 +41,14 @@ void Filter::initialize(Sensor *parent, Filter *next) { } // SlidingWindowFilter -SlidingWindowFilter::SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at) - : window_size_(window_size), send_every_(send_every), send_at_(send_every - send_first_at) { - // Allocate ring buffer once at initialization +SlidingWindowFilter::SlidingWindowFilter(uint16_t window_size, uint16_t send_every, uint16_t send_first_at) + : send_every_(send_every), send_at_(send_every - send_first_at) { this->window_.init(window_size); } optional<float> SlidingWindowFilter::new_value(float value) { - // Add value to ring buffer - if (this->window_count_ < this->window_size_) { - // Buffer not yet full - just append - this->window_.push_back(value); - this->window_count_++; - } else { - // Buffer full - overwrite oldest value (ring buffer) - this->window_[this->window_head_] = value; - this->window_head_++; - if (this->window_head_ >= this->window_size_) { - this->window_head_ = 0; - } - } + // Add value to ring buffer (overwrites oldest when full) + this->window_.push_overwrite(value); // Check if we should send a result if (++this->send_at_ >= this->send_every_) { @@ -77,9 +65,8 @@ FixedVector<float> SortedWindowFilter::get_window_values_() { // Copy window without NaN values using FixedVector (no heap allocation) // Returns unsorted values - caller will use std::nth_element for partial sorting as needed FixedVector<float> values; - values.init(this->window_count_); - for (size_t i = 0; i < this->window_count_; i++) { - float v = this->window_[i]; + values.init(this->window_.size()); + for (float v : this->window_) { if (!std::isnan(v)) { values.push_back(v); } @@ -150,8 +137,7 @@ float MaxFilter::compute_result() { return this->find_extremum_<std::greater<flo float SlidingWindowMovingAverageFilter::compute_result() { float sum = 0; size_t valid_count = 0; - for (size_t i = 0; i < this->window_count_; i++) { - float v = this->window_[i]; + for (float v : this->window_) { if (!std::isnan(v)) { sum += v; valid_count++; @@ -161,7 +147,7 @@ float SlidingWindowMovingAverageFilter::compute_result() { } // ExponentialMovingAverageFilter -ExponentialMovingAverageFilter::ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at) +ExponentialMovingAverageFilter::ExponentialMovingAverageFilter(float alpha, uint16_t send_every, uint16_t send_first_at) : alpha_(alpha), send_every_(send_every), send_at_(send_every - send_first_at) {} optional<float> ExponentialMovingAverageFilter::new_value(float value) { if (!std::isnan(value)) { @@ -183,7 +169,7 @@ optional<float> ExponentialMovingAverageFilter::new_value(float value) { } return {}; } -void ExponentialMovingAverageFilter::set_send_every(size_t send_every) { this->send_every_ = send_every; } +void ExponentialMovingAverageFilter::set_send_every(uint16_t send_every) { this->send_every_ = send_every; } void ExponentialMovingAverageFilter::set_alpha(float alpha) { this->alpha_ = alpha; } // ThrottleAverageFilter @@ -511,7 +497,7 @@ optional<float> ToNTCTemperatureFilter::new_value(float value) { } // StreamingFilter (base class) -StreamingFilter::StreamingFilter(size_t window_size, size_t send_first_at) +StreamingFilter::StreamingFilter(uint16_t window_size, uint16_t send_first_at) : window_size_(window_size), send_first_at_(send_first_at) {} optional<float> StreamingFilter::new_value(float value) { diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 8bfcdb37cf..6a76bd373e 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -52,7 +52,7 @@ class Filter { */ class SlidingWindowFilter : public Filter { public: - SlidingWindowFilter(size_t window_size, size_t send_every, size_t send_first_at); + SlidingWindowFilter(uint16_t window_size, uint16_t send_every, uint16_t send_first_at); optional<float> new_value(float value) final; @@ -60,14 +60,10 @@ class SlidingWindowFilter : public Filter { /// Called by new_value() to compute the filtered result from the current window virtual float compute_result() = 0; - /// Access the sliding window values (ring buffer implementation) - /// Use: for (size_t i = 0; i < window_count_; i++) { float val = window_[i]; } - FixedVector<float> window_; - size_t window_head_{0}; ///< Index where next value will be written - size_t window_count_{0}; ///< Number of valid values in window (0 to window_size_) - size_t window_size_; ///< Maximum window size - size_t send_every_; ///< Send result every N values - size_t send_at_; ///< Counter for send_every + /// Sliding window ring buffer - automatically overwrites oldest values when full + FixedRingBuffer<float> window_; + uint16_t send_every_; ///< Send result every N values + uint16_t send_at_; ///< Counter for send_every }; /** Base class for Min/Max filters. @@ -84,8 +80,7 @@ class MinMaxFilter : public SlidingWindowFilter { template<typename Compare> float find_extremum_() { float result = NAN; Compare comp; - for (size_t i = 0; i < this->window_count_; i++) { - float v = this->window_[i]; + for (float v : this->window_) { if (!std::isnan(v)) { result = std::isnan(result) ? v : (comp(v, result) ? v : result); } @@ -239,18 +234,18 @@ class SlidingWindowMovingAverageFilter : public SlidingWindowFilter { */ class ExponentialMovingAverageFilter : public Filter { public: - ExponentialMovingAverageFilter(float alpha, size_t send_every, size_t send_first_at); + ExponentialMovingAverageFilter(float alpha, uint16_t send_every, uint16_t send_first_at); optional<float> new_value(float value) override; - void set_send_every(size_t send_every); + void set_send_every(uint16_t send_every); void set_alpha(float alpha); protected: float accumulator_{NAN}; float alpha_; - size_t send_every_; - size_t send_at_; + uint16_t send_every_; + uint16_t send_at_; bool first_value_{true}; }; @@ -570,7 +565,7 @@ class ToNTCTemperatureFilter : public Filter { */ class StreamingFilter : public Filter { public: - StreamingFilter(size_t window_size, size_t send_first_at); + StreamingFilter(uint16_t window_size, uint16_t send_first_at); optional<float> new_value(float value) final; @@ -584,9 +579,9 @@ class StreamingFilter : public Filter { /// Called by new_value() to reset internal state after sending a result virtual void reset_batch() = 0; - size_t window_size_; - size_t count_{0}; - size_t send_first_at_; + uint16_t window_size_; + uint16_t count_{0}; + uint16_t send_first_at_; bool first_send_{true}; }; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index b2517e2d7a..9828df29cb 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -301,7 +301,7 @@ template<typename T, size_t N> class StaticVector { /// Not thread-safe. All access (push/pop/iteration) must occur from a single /// context, or the caller must provide external synchronization. template<typename T, size_t N> class StaticRingBuffer { - using index_type = std::conditional_t<(N <= 255), uint8_t, uint16_t>; + using index_type = std::conditional_t<(N <= std::numeric_limits<uint8_t>::max()), uint8_t, uint16_t>; public: class Iterator { @@ -356,6 +356,13 @@ template<typename T, size_t N> class StaticRingBuffer { index_type size() const { return this->count_; } bool empty() const { return this->count_ == 0; } + /// Clear all elements (reset to empty) + void clear() { + this->head_ = 0; + this->tail_ = 0; + this->count_ = 0; + } + Iterator begin() { return Iterator(this, 0); } Iterator end() { return Iterator(this, this->count_); } ConstIterator begin() const { return ConstIterator(this, 0); } @@ -368,6 +375,128 @@ template<typename T, size_t N> class StaticRingBuffer { index_type count_{0}; }; +/// Fixed-capacity circular buffer - allocates once at runtime, never reallocates. +/// Runtime-sized equivalent of StaticRingBuffer - use when capacity is only known at initialization. +/// Supports FIFO push/pop and iteration over queued elements. +/// Not thread-safe. +template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()> class FixedRingBuffer { + using index_type = std::conditional_t< + (MAX_CAPACITY <= std::numeric_limits<uint8_t>::max()), uint8_t, + std::conditional_t<(MAX_CAPACITY <= std::numeric_limits<uint16_t>::max()), uint16_t, uint32_t>>; + + public: + class Iterator { + public: + Iterator(FixedRingBuffer *buf, index_type pos) : buf_(buf), pos_(pos) {} + T &operator*() { return buf_->data_[(buf_->head_ + pos_) % buf_->capacity_]; } + Iterator &operator++() { + ++pos_; + return *this; + } + bool operator!=(const Iterator &other) const { return pos_ != other.pos_; } + + private: + FixedRingBuffer *buf_; + index_type pos_; + }; + + class ConstIterator { + public: + ConstIterator(const FixedRingBuffer *buf, index_type pos) : buf_(buf), pos_(pos) {} + const T &operator*() const { return buf_->data_[(buf_->head_ + pos_) % buf_->capacity_]; } + ConstIterator &operator++() { + ++pos_; + return *this; + } + bool operator!=(const ConstIterator &other) const { return pos_ != other.pos_; } + + private: + const FixedRingBuffer *buf_; + index_type pos_; + }; + + FixedRingBuffer() = default; + ~FixedRingBuffer() { + if constexpr (std::is_trivial<T>::value) { + ::operator delete(this->data_); + } else { + delete[] this->data_; + } + } + + // Disable copy + FixedRingBuffer(const FixedRingBuffer &) = delete; + FixedRingBuffer &operator=(const FixedRingBuffer &) = delete; + + /// Allocate capacity - can only be called once + void init(index_type capacity) { + if constexpr (std::is_trivial<T>::value) { + // Raw allocation without initialization (elements are written before read) + // NOLINTNEXTLINE(bugprone-sizeof-expression) + this->data_ = static_cast<T *>(::operator new(capacity * sizeof(T))); + } else { + this->data_ = new T[capacity]; + } + this->capacity_ = capacity; + } + + /// Push a value. Returns false if full. + bool push(const T &value) { + if (this->count_ >= this->capacity_) + return false; + this->data_[this->tail_] = value; + this->tail_ = (this->tail_ + 1) % this->capacity_; + ++this->count_; + return true; + } + + /// Push a value, overwriting the oldest if full. + void push_overwrite(const T &value) { + this->data_[this->tail_] = value; + this->tail_ = (this->tail_ + 1) % this->capacity_; + if (this->count_ >= this->capacity_) { + // Buffer full - advance head to drop oldest, count stays at capacity + this->head_ = this->tail_; + } else { + ++this->count_; + } + } + + /// Remove the oldest element. + void pop() { + if (this->count_ > 0) { + this->head_ = (this->head_ + 1) % this->capacity_; + --this->count_; + } + } + + T &front() { return this->data_[this->head_]; } + const T &front() const { return this->data_[this->head_]; } + index_type size() const { return this->count_; } + bool empty() const { return this->count_ == 0; } + index_type capacity() const { return this->capacity_; } + bool full() const { return this->count_ == this->capacity_; } + + /// Clear all elements (reset to empty, keep capacity) + void clear() { + this->head_ = 0; + this->tail_ = 0; + this->count_ = 0; + } + + Iterator begin() { return Iterator(this, 0); } + Iterator end() { return Iterator(this, this->count_); } + ConstIterator begin() const { return ConstIterator(this, 0); } + ConstIterator end() const { return ConstIterator(this, this->count_); } + + protected: + T *data_{nullptr}; + index_type head_{0}; + index_type tail_{0}; + index_type count_{0}; + index_type capacity_{0}; +}; + /// Fixed-capacity vector - allocates once at runtime, never reallocates /// This avoids std::vector template overhead (_M_realloc_insert, _M_default_append) /// when size is known at initialization but not at compile time From 1eed1adfa0314bb53b3716ea59187b49aa40a036 Mon Sep 17 00:00:00 2001 From: Thomas SAMTER <7680607+P4uLT@users.noreply.github.com> Date: Fri, 13 Mar 2026 22:38:45 +0100 Subject: [PATCH 1337/2030] [pid] Replace std::deque with FixedRingBuffer (#14733) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/pid/climate.py | 24 ++++++++++------- esphome/components/pid/pid_climate.h | 10 ++++++- esphome/components/pid/pid_controller.cpp | 32 +++++++++++------------ esphome/components/pid/pid_controller.h | 24 ++++++++++------- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py index 0e66b67637..18e33b8039 100644 --- a/esphome/components/pid/climate.py +++ b/esphome/components/pid/climate.py @@ -57,7 +57,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_KD_MULTIPLIER, default=0.0): cv.float_, cv.Optional( CONF_DEADBAND_OUTPUT_AVERAGING_SAMPLES, default=1 - ): cv.int_, + ): cv.positive_not_null_int, } ), cv.Required(CONF_CONTROL_PARAMETERS): cv.Schema( @@ -68,8 +68,12 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_STARTING_INTEGRAL_TERM, default=0.0): cv.float_, cv.Optional(CONF_MIN_INTEGRAL, default=-1): cv.float_, cv.Optional(CONF_MAX_INTEGRAL, default=1): cv.float_, - cv.Optional(CONF_DERIVATIVE_AVERAGING_SAMPLES, default=1): cv.int_, - cv.Optional(CONF_OUTPUT_AVERAGING_SAMPLES, default=1): cv.int_, + cv.Optional( + CONF_DERIVATIVE_AVERAGING_SAMPLES, default=1 + ): cv.positive_not_null_int, + cv.Optional( + CONF_OUTPUT_AVERAGING_SAMPLES, default=1 + ): cv.positive_not_null_int, } ), } @@ -102,13 +106,15 @@ async def to_code(config): cg.add(var.set_starting_integral_term(params[CONF_STARTING_INTEGRAL_TERM])) cg.add(var.set_derivative_samples(params[CONF_DERIVATIVE_AVERAGING_SAMPLES])) - cg.add(var.set_output_samples(params[CONF_OUTPUT_AVERAGING_SAMPLES])) + output_samples = params[CONF_OUTPUT_AVERAGING_SAMPLES] + cg.add(var.set_output_samples(output_samples)) if CONF_MIN_INTEGRAL in params: cg.add(var.set_min_integral(params[CONF_MIN_INTEGRAL])) if CONF_MAX_INTEGRAL in params: cg.add(var.set_max_integral(params[CONF_MAX_INTEGRAL])) + deadband_output_samples = 1 if CONF_DEADBAND_PARAMETERS in config: params = config[CONF_DEADBAND_PARAMETERS] cg.add(var.set_threshold_low(params[CONF_THRESHOLD_LOW])) @@ -116,11 +122,11 @@ async def to_code(config): cg.add(var.set_kp_multiplier(params[CONF_KP_MULTIPLIER])) cg.add(var.set_ki_multiplier(params[CONF_KI_MULTIPLIER])) cg.add(var.set_kd_multiplier(params[CONF_KD_MULTIPLIER])) - cg.add( - var.set_deadband_output_samples( - params[CONF_DEADBAND_OUTPUT_AVERAGING_SAMPLES] - ) - ) + deadband_output_samples = params[CONF_DEADBAND_OUTPUT_AVERAGING_SAMPLES] + cg.add(var.set_deadband_output_samples(deadband_output_samples)) + + # Single shared output buffer sized to max of both modes + cg.add(var.init_output_buffer(max(output_samples, deadband_output_samples))) cg.add(var.set_default_target_temperature(config[CONF_DEFAULT_TARGET_TEMPERATURE])) diff --git a/esphome/components/pid/pid_climate.h b/esphome/components/pid/pid_climate.h index dc0a92efed..3708c29ff1 100644 --- a/esphome/components/pid/pid_climate.h +++ b/esphome/components/pid/pid_climate.h @@ -28,7 +28,11 @@ class PIDClimate : public climate::Climate, public Component { void set_min_integral(float min_integral) { controller_.min_integral_ = min_integral; } void set_max_integral(float max_integral) { controller_.max_integral_ = max_integral; } void set_output_samples(int in) { controller_.output_samples_ = in; } - void set_derivative_samples(int in) { controller_.derivative_samples_ = in; } + void set_derivative_samples(int in) { + controller_.derivative_samples_ = in; + if (in > 1) // No allocation needed when samples=1 (ring_buffer_average_ short-circuits) + controller_.derivative_window_.init(in); + } void set_threshold_low(float in) { controller_.threshold_low_ = in; } void set_threshold_high(float in) { controller_.threshold_high_ = in; } @@ -38,6 +42,10 @@ class PIDClimate : public climate::Climate, public Component { void set_starting_integral_term(float in) { controller_.set_starting_integral_term(in); } void set_deadband_output_samples(int in) { controller_.deadband_output_samples_ = in; } + void init_output_buffer(int size) { + if (size > 1) // No allocation needed when samples=1 (ring_buffer_average_ short-circuits) + controller_.output_window_.init(size); + } float get_output_value() const { return output_value_; } float get_error_value() const { return controller_.error_; } diff --git a/esphome/components/pid/pid_controller.cpp b/esphome/components/pid/pid_controller.cpp index 5d7aecdb05..cab15331cd 100644 --- a/esphome/components/pid/pid_controller.cpp +++ b/esphome/components/pid/pid_controller.cpp @@ -21,9 +21,9 @@ float PIDController::update(float setpoint, float process_value) { // u(t) := p(t) + i(t) + d(t) float output = proportional_term_ + integral_term_ + derivative_term_; - // smooth/sample the output + // smooth/sample the output using shared buffer with mode-appropriate sample count int samples = in_deadband() ? deadband_output_samples_ : output_samples_; - return weighted_average_(output_list_, output, samples); + return ring_buffer_average_(output_window_, output, samples); } bool PIDController::in_deadband() { @@ -83,7 +83,7 @@ void PIDController::calculate_derivative_term_(float setpoint) { previous_setpoint_ = setpoint; // smooth the derivative samples - derivative = weighted_average_(derivative_list_, derivative, derivative_samples_); + derivative = ring_buffer_average_(derivative_window_, derivative, derivative_samples_); derivative_term_ = kd_ * derivative; @@ -93,25 +93,23 @@ void PIDController::calculate_derivative_term_(float setpoint) { } } -float PIDController::weighted_average_(std::deque<float> &list, float new_value, int samples) { - // if only 1 sample needed, clear the list and return - if (samples == 1) { - list.clear(); +float PIDController::ring_buffer_average_(FixedRingBuffer<float> &buf, float new_value, int max_samples) { + // if only 1 sample needed (or invalid), clear the buffer and return + if (max_samples <= 1) { + buf.clear(); return new_value; } - // add the new item to the list - list.push_front(new_value); + // Trim oldest entries to make room (handles mode-switching where buffer + // may have more entries than the current mode needs) + while (buf.size() >= static_cast<size_t>(max_samples)) + buf.pop(); + buf.push(new_value); - // keep only 'samples' readings, by popping off the back of the list - while (samples > 0 && list.size() > static_cast<size_t>(samples)) - list.pop_back(); - - // calculate and return the average of all values in the list float sum = 0; - for (auto &elem : list) - sum += elem; - return sum / list.size(); + for (auto val : buf) + sum += val; + return sum / buf.size(); } float PIDController::calculate_relative_time_() { diff --git a/esphome/components/pid/pid_controller.h b/esphome/components/pid/pid_controller.h index e2a7030b57..6848a23965 100644 --- a/esphome/components/pid/pid_controller.h +++ b/esphome/components/pid/pid_controller.h @@ -1,6 +1,7 @@ #pragma once + #include "esphome/core/hal.h" -#include <deque> +#include "esphome/core/helpers.h" #include <cmath> namespace esphome { @@ -24,10 +25,10 @@ struct PIDController { /// Differential gain K_d. float kd_ = 0; - // smooth the derivative value using a weighted average over X samples - int derivative_samples_ = 8; + // smooth the derivative value using an average over X samples + int derivative_samples_ = 1; - /// smooth the output value using a weighted average over X values + /// smooth the output value using an average over X values int output_samples_ = 1; float threshold_low_ = 0.0f; @@ -50,7 +51,10 @@ struct PIDController { void calculate_proportional_term_(); void calculate_integral_term_(); void calculate_derivative_term_(float setpoint); - float weighted_average_(std::deque<float> &list, float new_value, int samples); + + /// Ring buffer smoothing using FixedRingBuffer (single allocation at setup) + float ring_buffer_average_(FixedRingBuffer<float> &buf, float new_value, int max_samples); + float calculate_relative_time_(); /// Error from previous update used for derivative term @@ -60,12 +64,12 @@ struct PIDController { float accumulated_integral_ = 0; uint32_t last_time_ = 0; - // this is a list of derivative values for smoothing. - std::deque<float> derivative_list_; + // Ring buffer for derivative smoothing + FixedRingBuffer<float> derivative_window_; - // this is a list of output values for smoothing. - std::deque<float> output_list_; + // Ring buffer for output smoothing (shared between normal and deadband modes) + FixedRingBuffer<float> output_window_; -}; // Struct PID Controller +}; // Struct PIDController } // namespace pid } // namespace esphome From cdb445f69da73e51d72a45bb4488aa760be1427b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:00:28 -0400 Subject: [PATCH 1338/2030] [mipi_dsi] Fix ESP-IDF 6.0 compatibility for LCD color format (#14785) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/mipi_dsi/mipi_dsi.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 815b9d75a1..7103e0868d 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -54,6 +54,17 @@ void MIPI_DSI::setup() { this->smark_failed(LOG_STR("new_panel_io_dbi failed"), err); return; } + // clang-format off +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + auto color_format = LCD_COLOR_FMT_RGB565; + if (this->color_depth_ == display::COLOR_BITNESS_888) { + color_format = LCD_COLOR_FMT_RGB888; + } + esp_lcd_dpi_panel_config_t dpi_config = {.virtual_channel = 0, + .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, + .dpi_clock_freq_mhz = this->pclk_frequency_, + .in_color_format = color_format, +#else auto pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565; if (this->color_depth_ == display::COLOR_BITNESS_888) { pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888; @@ -62,6 +73,7 @@ void MIPI_DSI::setup() { .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, .dpi_clock_freq_mhz = this->pclk_frequency_, .pixel_format = pixel_format, +#endif .num_fbs = 1, // number of frame buffers to allocate .video_timing = { @@ -77,6 +89,7 @@ void MIPI_DSI::setup() { .flags = { .use_dma2d = true, }}; + // clang-format on err = esp_lcd_new_panel_dpi(this->bus_handle_, &dpi_config, &this->handle_); if (err != ESP_OK) { this->smark_failed(LOG_STR("esp_lcd_new_panel_dpi failed"), err); From ab3b677113ff9bf6a00a2159b6f3d6817a17b916 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:11:18 -0400 Subject: [PATCH 1339/2030] [adc] Fix ESP-IDF 6.0 compatibility for ADC_ATTEN_DB_12 (#14784) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/adc/adc_sensor.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/adc/adc_sensor.h b/esphome/components/adc/adc_sensor.h index 91cf4eaafc..cf48ccd9c3 100644 --- a/esphome/components/adc/adc_sensor.h +++ b/esphome/components/adc/adc_sensor.h @@ -22,7 +22,8 @@ namespace adc { #ifdef USE_ESP32 // clang-format off -#if (ESP_IDF_VERSION_MAJOR == 5 && \ +#if ESP_IDF_VERSION_MAJOR >= 6 || \ + (ESP_IDF_VERSION_MAJOR == 5 && \ ((ESP_IDF_VERSION_MINOR == 0 && ESP_IDF_VERSION_PATCH >= 5) || \ (ESP_IDF_VERSION_MINOR == 1 && ESP_IDF_VERSION_PATCH >= 3) || \ (ESP_IDF_VERSION_MINOR >= 2)) \ From 22062d79a2b7d82bf9f62f9dc92f37d8f8e91686 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 13:20:17 -1000 Subject: [PATCH 1340/2030] [analyze-memory] Add function call frequency analysis (#14779) --- esphome/analyze_memory/__init__.py | 56 ++++++++++++++- esphome/analyze_memory/cli.py | 109 +++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 3 deletions(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index bf1bcbfa05..7954c22822 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -1,6 +1,6 @@ """Memory usage analyzer for ESPHome compiled binaries.""" -from collections import defaultdict +from collections import Counter, defaultdict from dataclasses import dataclass, field import logging from pathlib import Path @@ -40,6 +40,15 @@ _READELF_SECTION_PATTERN = re.compile( r"\s*\[\s*\d+\]\s+([\.\w]+)\s+\w+\s+[\da-fA-F]+\s+[\da-fA-F]+\s+([\da-fA-F]+)" ) +# Regex for extracting call targets from objdump disassembly +# Matches direct call instructions across architectures: +# Xtensa: call0/call4/call8/call12/callx0/callx4/callx8/callx12 <addr> <symbol> +# ARM: bl/blx <addr> <symbol> +# Captures the mangled symbol name inside angle brackets. +_CALL_TARGET_PATTERN = re.compile( + r"\t(?:call(?:0|4|8|12)|callx(?:0|4|8|12)|blx?)\s+[\da-fA-F]+ <([^>]+)>" +) + # Component category prefixes _COMPONENT_PREFIX_ESPHOME = "[esphome]" _COMPONENT_PREFIX_EXTERNAL = "[external]" @@ -197,6 +206,8 @@ class MemoryAnalyzer: self._lib_hash_to_name: dict[str, str] = {} # Heuristic category to library redirect: "mdns_lib" -> "[lib]mdns" self._heuristic_to_lib: dict[str, str] = {} + # Function call counts: mangled_name -> call_count + self._function_call_counts: Counter[str] = Counter() def analyze(self) -> dict[str, ComponentMemory]: """Analyze the ELF file and return component memory usage.""" @@ -206,6 +217,7 @@ class MemoryAnalyzer: self._categorize_symbols() self._analyze_cswtch_symbols() self._analyze_sdk_libraries() + self._analyze_function_calls() return dict(self.components) def _parse_sections(self) -> None: @@ -384,8 +396,9 @@ class MemoryAnalyzer: return _LOGGER.info("Demangling %d symbols", len(symbols)) - self._demangle_cache = batch_demangle(symbols, objdump_path=self.objdump_path) - _LOGGER.info("Successfully demangled %d symbols", len(self._demangle_cache)) + demangled = batch_demangle(symbols, objdump_path=self.objdump_path) + self._demangle_cache.update(demangled) + _LOGGER.info("Successfully demangled %d symbols", len(demangled)) def _demangle_symbol(self, symbol: str) -> str: """Get demangled C++ symbol name from cache.""" @@ -1011,6 +1024,43 @@ class MemoryAnalyzer: total_size, ) + def _analyze_function_calls(self) -> None: + """Count function call sites by parsing disassembly output. + + Parses direct call instructions (call0/call8/bl/blx) from objdump -d + to count how many times each function is called. This helps identify + inlining candidates — frequently called small functions benefit most + from inlining. + """ + result = run_tool( + [self.objdump_path, "-d", str(self.elf_path)], + timeout=60, + ) + if result is None or result.returncode != 0: + _LOGGER.debug("Failed to disassemble ELF for function call analysis") + return + + self._function_call_counts = Counter( + match.group(1) + for line in result.stdout.splitlines() + if (match := _CALL_TARGET_PATTERN.search(line)) + ) + + # Demangle any call targets not already in the cache + missing = [ + name + for name in self._function_call_counts + if name not in self._demangle_cache + ] + if missing: + self._batch_demangle_symbols(missing) + + _LOGGER.debug( + "Function call analysis: %d unique targets, %d total calls", + len(self._function_call_counts), + sum(self._function_call_counts.values()), + ) + def get_unattributed_ram(self) -> tuple[int, int, int]: """Get unattributed RAM sizes (SDK/framework overhead). diff --git a/esphome/analyze_memory/cli.py b/esphome/analyze_memory/cli.py index dbc19c6b89..acaf5f4562 100644 --- a/esphome/analyze_memory/cli.py +++ b/esphome/analyze_memory/cli.py @@ -231,6 +231,110 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): lines.append(f" {size:>6,} B {sym_name}") lines.append("") + # Number of top called functions to show + TOP_CALLS_LIMIT: int = 50 + # Number of inlining candidates to show + INLINE_CANDIDATES_LIMIT: int = 25 + # Maximum function size in bytes to consider for inlining + INLINE_SIZE_THRESHOLD: int = 16 + + def _build_symbol_sizes(self) -> dict[str, int]: + """Build a size lookup from all component symbols: mangled_name -> size.""" + return { + symbol: size + for symbols in self._component_symbols.values() + for symbol, _, size, _ in symbols + } + + def _format_call_row( + self, index: int, mangled: str, count: int, symbol_sizes: dict[str, int] + ) -> str: + """Format a single row for call frequency tables.""" + demangled = self._demangle_cache.get(mangled, mangled) + if len(demangled) > 80: + demangled = f"{demangled[:77]}..." + size = symbol_sizes.get(mangled) + size_str = f"{size:>5,} B" if size is not None else " ?" + return f"{index:>3} {count:>5} {size_str} {demangled}" + + def _add_call_table_header(self, lines: list[str]) -> None: + """Add the header row for call frequency tables.""" + lines.append(f"{'#':>3} {'Calls':>5} {'Size':>7} Function") + lines.append(f"{'---':>3} {'-----':>5} {'-------':>7} {'-' * 60}") + + def _add_function_call_analysis(self, lines: list[str]) -> None: + """Add function call frequency analysis section. + + Shows the most frequently called functions by call site count. + """ + self._add_section_header(lines, "Top Called Functions") + + symbol_sizes = self._build_symbol_sizes() + + # Sort by call count descending + sorted_calls = sorted( + self._function_call_counts.items(), key=lambda x: x[1], reverse=True + ) + + self._add_call_table_header(lines) + + for i, (mangled, count) in enumerate(sorted_calls[: self.TOP_CALLS_LIMIT]): + lines.append(self._format_call_row(i + 1, mangled, count, symbol_sizes)) + + total_calls = sum(self._function_call_counts.values()) + lines.append("") + lines.append( + f"Total: {len(self._function_call_counts)} unique targets, " + f"{total_calls:,} call sites" + ) + lines.append("") + + def _add_inline_candidates(self, lines: list[str]) -> None: + """Add inlining candidates section. + + Shows frequently called functions that are small enough to benefit + from inlining (< 16 bytes). These are the best candidates for + reducing call overhead. + """ + self._add_section_header( + lines, + f"Inlining Candidates (<{self.INLINE_SIZE_THRESHOLD} B, by call count)", + ) + + symbol_sizes = self._build_symbol_sizes() + + # Filter to small functions with known size, sort by call count + candidates = sorted( + ( + (mangled, count) + for mangled, count in self._function_call_counts.items() + if mangled in symbol_sizes + and symbol_sizes[mangled] < self.INLINE_SIZE_THRESHOLD + ), + key=lambda x: x[1], + reverse=True, + ) + + if not candidates: + lines.append("No candidates found.") + lines.append("") + return + + self._add_call_table_header(lines) + + for i, (mangled, count) in enumerate( + candidates[: self.INLINE_CANDIDATES_LIMIT] + ): + lines.append(self._format_call_row(i + 1, mangled, count, symbol_sizes)) + + lines.append("") + lines.append( + f"Showing top {min(len(candidates), self.INLINE_CANDIDATES_LIMIT)} " + f"of {len(candidates)} functions under " + f"{self.INLINE_SIZE_THRESHOLD} B" + ) + lines.append("") + def generate_report(self, detailed: bool = False) -> str: """Generate a formatted memory report.""" components = sorted( @@ -533,6 +637,11 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): if self._cswtch_symbols: self._add_cswtch_analysis(lines) + # Function call frequency analysis + if self._function_call_counts: + self._add_function_call_analysis(lines) + self._add_inline_candidates(lines) + lines.append( "Note: This analysis covers symbols in the ELF file. Some runtime allocations may not be included." ) From 56f7b3e61b0bb6defd652092d9f4c13e4dabd593 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 13:20:35 -1000 Subject: [PATCH 1341/2030] [ci] Only run integration tests for changed components (#14776) --- .github/workflows/ci.yml | 17 ++- script/determine-jobs.py | 104 ++++++++----- script/helpers.py | 132 +++++++++++++++-- tests/script/test_determine_jobs.py | 217 ++++++++++++++++++++++------ tests/script/test_helpers.py | 30 +++- 5 files changed, 400 insertions(+), 100 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 461e676c4e..fedfebf393 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -170,6 +170,8 @@ jobs: - common outputs: integration-tests: ${{ steps.determine.outputs.integration-tests }} + integration-tests-run-all: ${{ steps.determine.outputs.integration-tests-run-all }} + integration-test-files: ${{ steps.determine.outputs.integration-test-files }} clang-tidy: ${{ steps.determine.outputs.clang-tidy }} clang-tidy-mode: ${{ steps.determine.outputs.clang-tidy-mode }} python-linters: ${{ steps.determine.outputs.python-linters }} @@ -210,6 +212,8 @@ jobs: # Extract individual fields echo "integration-tests=$(echo "$output" | jq -r '.integration_tests')" >> $GITHUB_OUTPUT + echo "integration-tests-run-all=$(echo "$output" | jq -r '.integration_tests_run_all')" >> $GITHUB_OUTPUT + echo "integration-test-files=$(echo "$output" | jq -c '.integration_test_files')" >> $GITHUB_OUTPUT echo "clang-tidy=$(echo "$output" | jq -r '.clang_tidy')" >> $GITHUB_OUTPUT echo "clang-tidy-mode=$(echo "$output" | jq -r '.clang_tidy_mode')" >> $GITHUB_OUTPUT echo "python-linters=$(echo "$output" | jq -r '.python_linters')" >> $GITHUB_OUTPUT @@ -261,9 +265,20 @@ jobs: - name: Register matcher run: echo "::add-matcher::.github/workflows/matchers/pytest.json" - name: Run integration tests + env: + INTEGRATION_TEST_FILES: ${{ needs.determine-jobs.outputs.integration-test-files }} + INTEGRATION_TESTS_RUN_ALL: ${{ needs.determine-jobs.outputs.integration-tests-run-all }} run: | . venv/bin/activate - pytest -vv --no-cov --tb=native -n auto tests/integration/ + if [[ "$INTEGRATION_TESTS_RUN_ALL" == "true" ]]; then + echo "Running all integration tests" + pytest -vv --no-cov --tb=native -n auto tests/integration/ + else + # Parse JSON array into bash array to avoid shell expansion issues + mapfile -t test_files < <(echo "$INTEGRATION_TEST_FILES" | jq -r '.[]') + echo "Running ${#test_files[@]} specific integration tests" + pytest -vv --no-cov --tb=native -n auto "${test_files[@]}" + fi cpp-unit-tests: name: Run C++ unit tests diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 318ac04a7d..6808a3cf6c 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -6,6 +6,8 @@ what files have changed. It outputs JSON with the following structure: { "integration_tests": true/false, + "integration_tests_run_all": true/false, + "integration_test_files": ["tests/integration/test_foo.py", ...], "clang_tidy": true/false, "clang_format": true/false, "python_linters": true/false, @@ -56,13 +58,13 @@ from helpers import ( core_changed, filter_component_and_test_cpp_files, filter_component_and_test_files, - get_all_dependencies, get_changed_components, get_component_from_path, get_component_test_files, - get_components_from_integration_fixtures, get_components_with_dependencies, get_cpp_changed_components, + get_fixture_to_test_files, + get_integration_test_files_for_components, get_target_branch, git_ls_files, parse_test_filename, @@ -143,65 +145,88 @@ MEMORY_IMPACT_PLATFORM_PREFERENCE = [ ] -def should_run_integration_tests(branch: str | None = None) -> bool: - """Determine if integration tests should run based on changed files. +def determine_integration_tests(branch: str | None = None) -> tuple[bool, list[str]]: + """Determine which integration tests should run based on changed files. - This function is used by the CI workflow to intelligently skip integration tests when they're - not needed, saving significant CI time and resources. + This function is used by the CI workflow to intelligently skip or filter + integration tests, saving significant CI time and resources. - Integration tests will run when ANY of the following conditions are met: + Returns (run_all=True, []) when ANY of the following conditions are met: 1. Core C++ files changed (esphome/core/*) - Any .cpp, .h, .tcc files in the core directory - These files contain fundamental functionality used throughout ESPHome - - Examples: esphome/core/component.cpp, esphome/core/application.h 2. Core Python files changed (esphome/core/*.py) - Only .py files in the esphome/core/ directory - These are core Python files that affect the entire system - - Examples: esphome/core/config.py, esphome/core/__init__.py - - NOT included: esphome/*.py, esphome/dashboard/*.py, esphome/components/*/*.py - 3. Integration test files changed - - Any file in tests/integration/ directory - - This includes test files themselves and fixture YAML files - - Examples: tests/integration/test_api.py, tests/integration/fixtures/api.yaml + 3. Integration test infrastructure files changed + - conftest.py, types.py, const.py, entity_utils.py, state_utils.py, etc. - 4. Components used by integration tests (or their dependencies) changed - - The function parses all YAML files in tests/integration/fixtures/ - - Extracts which components are used in integration tests - - Recursively finds all dependencies of those components - - If any of these components have changes, tests must run - - Example: If api.yaml uses 'sensor' and 'api' components, and 'api' depends on 'socket', - then changes to sensor/, api/, or socket/ components trigger tests + Returns (run_all=False, [test_files...]) when: + + 4. Specific integration test files changed + - Only those specific test files are returned + + 5. Components used by integration tests (or their dependencies) changed + - Only test files whose fixtures use the changed components are returned Args: branch: Branch to compare against. If None, uses default. Returns: - True if integration tests should run, False otherwise. + Tuple of (run_all, test_files) where: + - run_all: True if all integration tests should run + - test_files: List of specific test file paths to run (empty if run_all + is True, or if no tests need to run) """ files = changed_files(branch) if core_changed(files): - # If any core files changed, run integration tests - return True + # If any core files changed, run all integration tests + return (True, []) - # Check if any integration test files changed - if any("tests/integration" in file for file in files): - return True + # If infrastructure Python files changed (conftest, utils, etc.), run all tests + # Excludes test files (test_*.py), fixtures, and non-Python files (README.md) + if any( + f.startswith("tests/integration/") + and f.endswith(".py") + and not f.startswith("tests/integration/test_") + and "/fixtures/" not in f + for f in files + ): + return (True, []) - # Get all components used in integration tests and their dependencies - fixture_components = get_components_from_integration_fixtures() - all_required_components = get_all_dependencies(fixture_components) + # Collect specific test files that need to run + test_files: set[str] = set() + fixture_to_test_files = get_fixture_to_test_files() - # Check if any required components changed - for file in files: - component = get_component_from_path(file) - if component and component in all_required_components: - return True + for f in files: + if f.startswith("tests/integration/test_") and f.endswith(".py"): + test_files.add(f) + elif f.startswith("tests/integration/fixtures/"): + if f.endswith(".yaml"): + # Fixture YAML changed - add corresponding test file(s) + test_files.update(fixture_to_test_files.get(Path(f).stem, ())) + else: + # Non-YAML fixture file changed (e.g., external_components/) + # Run all tests since we can't determine which tests are affected + return (True, []) - return False + # Find test files whose fixtures use any of the changed components + changed_component_set = { + component for file in files if (component := get_component_from_path(file)) + } + if changed_component_set: + test_files.update( + get_integration_test_files_for_components(changed_component_set) + ) + + if test_files: + return (False, sorted(test_files)) + + return (False, []) @cache @@ -682,7 +707,10 @@ def main() -> None: args = parser.parse_args() # Determine what should run - run_integration = should_run_integration_tests(args.branch) + integration_run_all, integration_test_files = determine_integration_tests( + args.branch + ) + run_integration = integration_run_all or bool(integration_test_files) run_clang_tidy = should_run_clang_tidy(args.branch) run_clang_format = should_run_clang_format(args.branch) run_python_linters = should_run_python_linters(args.branch) @@ -810,6 +838,8 @@ def main() -> None: output: dict[str, Any] = { "integration_tests": run_integration, + "integration_tests_run_all": integration_run_all, + "integration_test_files": integration_test_files, "clang_tidy": run_clang_tidy, "clang_tidy_mode": clang_tidy_mode, "clang_format": run_clang_format, diff --git a/script/helpers.py b/script/helpers.py index 6ee286a657..9665af70ec 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -700,37 +700,141 @@ def get_all_dependencies( return all_components +def _extract_components_from_yaml(config: dict) -> set[str]: + """Extract component names from a parsed YAML config. + + Args: + config: Parsed YAML configuration dictionary + + Returns: + Set of component names found in the config + """ + components: set[str] = set() + + # Add all top-level component keys (skip YAML anchor keys starting with '.') + components.update(k for k in config if isinstance(k, str) and not k.startswith(".")) + + # Add platform values from list entries (e.g., sensor -> platform: template adds "template") + for value in config.values(): + if isinstance(value, list): + components.update( + item["platform"] + for item in value + if isinstance(item, dict) and "platform" in item + ) + + return components + + def get_components_from_integration_fixtures() -> set[str]: """Extract all components used in integration test fixtures. Returns: Set of component names used in integration test fixtures """ + return { + comp + for components in get_components_per_integration_fixture().values() + for comp in components + } + + +@cache +def get_components_per_integration_fixture() -> dict[str, set[str]]: + """Extract components used in each integration test fixture. + + Returns: + Dictionary mapping fixture name (stem) to set of component names + """ from esphome import yaml_util - components: set[str] = set() + result: dict[str, set[str]] = {} fixtures_dir = Path(__file__).parent.parent / "tests" / "integration" / "fixtures" for yaml_file in fixtures_dir.glob("*.yaml"): - config: dict[str, any] | None = yaml_util.load_yaml(yaml_file) + config: dict[str, Any] | None = yaml_util.load_yaml(yaml_file) if not config: continue - # Add all top-level component keys (skip YAML anchor keys starting with '.') - components.update( - k for k in config if isinstance(k, str) and not k.startswith(".") - ) + result[yaml_file.stem] = _extract_components_from_yaml(config) - # Add platform components (e.g., output.template) - for value in config.values(): - if not isinstance(value, list): - continue + return result - for item in value: - if isinstance(item, dict) and "platform" in item: - components.add(item["platform"]) - return components +_TEST_FUNC_RE = re.compile(r"async def (test_\w+)") + + +@cache +def get_fixture_to_test_files() -> dict[str, frozenset[str]]: + """Map integration test fixture names to the test files that use them. + + Returns: + Dictionary mapping fixture name to frozenset of test file paths + (relative to repo root) + """ + integration_dir = Path(__file__).parent.parent / "tests" / "integration" + result: dict[str, set[str]] = {} + + for test_file in integration_dir.glob("test_*.py"): + content = test_file.read_text(encoding="utf-8") + rel_path = test_file.relative_to(Path(__file__).parent.parent).as_posix() + for func in _TEST_FUNC_RE.findall(content): + base_name = func.replace("test_", "").partition("[")[0] + result.setdefault(base_name, set()).add(rel_path) + + return {k: frozenset(v) for k, v in result.items()} + + +@cache +def _get_component_to_integration_test_files() -> dict[str, frozenset[str]]: + """Build index mapping each component to the test files that depend on it. + + Resolves full dependency trees once per fixture, then inverts the mapping + so lookups are O(1) per component. + + Returns: + Dictionary mapping component name to frozenset of test file paths + """ + fixture_components = get_components_per_integration_fixture() + fixture_to_test_files = get_fixture_to_test_files() + + result: dict[str, set[str]] = {} + for fixture_name, components in fixture_components.items(): + test_files = fixture_to_test_files.get(fixture_name) + if not test_files: + continue + # Get full dependency tree for this fixture's components + all_deps = get_all_dependencies(components) + for dep in all_deps: + result.setdefault(dep, set()).update(test_files) + + return {k: frozenset(v) for k, v in result.items()} + + +def get_integration_test_files_for_components( + changed_components: set[str], +) -> list[str]: + """Get integration test file paths that use any of the given components. + + Uses a precomputed component → test files index for O(C) lookup + where C is the number of changed components. + + Args: + changed_components: Set of component names that have changed + + Returns: + Sorted list of test file paths relative to repo root + (e.g., ["tests/integration/test_api.py", ...]) + """ + component_to_tests = _get_component_to_integration_test_files() + + return sorted( + { + test_file + for component in changed_components + for test_file in component_to_tests.get(component, ()) + } + ) def filter_component_and_test_files(file_path: str) -> bool: diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 61ef8985df..5c81ad374b 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -29,9 +29,9 @@ spec.loader.exec_module(determine_jobs) @pytest.fixture -def mock_should_run_integration_tests() -> Generator[Mock, None, None]: - """Mock should_run_integration_tests from helpers.""" - with patch.object(determine_jobs, "should_run_integration_tests") as mock: +def mock_determine_integration_tests() -> Generator[Mock, None, None]: + """Mock determine_integration_tests.""" + with patch.object(determine_jobs, "determine_integration_tests") as mock: yield mock @@ -87,7 +87,7 @@ def clear_determine_jobs_caches() -> None: def test_main_all_tests_should_run( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -100,7 +100,7 @@ def test_main_all_tests_should_run( # Ensure we're not in GITHUB_ACTIONS mode for this test monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = True + mock_determine_integration_tests.return_value = (True, []) mock_should_run_clang_tidy.return_value = True mock_should_run_clang_format.return_value = True mock_should_run_python_linters.return_value = True @@ -152,6 +152,8 @@ def test_main_all_tests_should_run( output = json.loads(captured.out) assert output["integration_tests"] is True + assert output["integration_tests_run_all"] is True + assert output["integration_test_files"] == [] assert output["clang_tidy"] is True assert output["clang_tidy_mode"] in ["nosplit", "split"] assert output["clang_format"] is True @@ -183,7 +185,7 @@ def test_main_all_tests_should_run( def test_main_no_tests_should_run( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -196,7 +198,7 @@ def test_main_no_tests_should_run( # Ensure we're not in GITHUB_ACTIONS mode for this test monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = False mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False @@ -233,6 +235,8 @@ def test_main_no_tests_should_run( output = json.loads(captured.out) assert output["integration_tests"] is False + assert output["integration_tests_run_all"] is False + assert output["integration_test_files"] == [] assert output["clang_tidy"] is False assert output["clang_tidy_mode"] == "disabled" assert output["clang_format"] is False @@ -253,7 +257,7 @@ def test_main_no_tests_should_run( def test_main_with_branch_argument( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -266,7 +270,7 @@ def test_main_with_branch_argument( # Ensure we're not in GITHUB_ACTIONS mode for this test monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = True mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = True @@ -302,7 +306,7 @@ def test_main_with_branch_argument( determine_jobs.main() # Check that functions were called with branch - mock_should_run_integration_tests.assert_called_once_with("main") + mock_determine_integration_tests.assert_called_once_with("main") mock_should_run_clang_tidy.assert_called_once_with("main") mock_should_run_clang_format.assert_called_once_with("main") mock_should_run_python_linters.assert_called_once_with("main") @@ -312,6 +316,8 @@ def test_main_with_branch_argument( output = json.loads(captured.out) assert output["integration_tests"] is False + assert output["integration_tests_run_all"] is False + assert output["integration_test_files"] == [] assert output["clang_tidy"] is True assert output["clang_tidy_mode"] in ["nosplit", "split"] assert output["clang_format"] is False @@ -334,30 +340,33 @@ def test_main_with_branch_argument( assert output["cpp_unit_tests_components"] == ["mqtt"] -def test_should_run_integration_tests( +def test_determine_integration_tests( monkeypatch: pytest.MonkeyPatch, ) -> None: - """Test should_run_integration_tests function.""" - # Core C++ files trigger tests + """Test determine_integration_tests function.""" + # Core C++ files trigger run_all with patch.object( determine_jobs, "changed_files", return_value=["esphome/core/component.cpp"] ): - result = determine_jobs.should_run_integration_tests() - assert result is True + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is True + assert test_files == [] - # Core Python files trigger tests + # Core Python files trigger run_all with patch.object( determine_jobs, "changed_files", return_value=["esphome/core/config.py"] ): - result = determine_jobs.should_run_integration_tests() - assert result is True + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is True + assert test_files == [] # Python files directly in esphome/ do NOT trigger tests with patch.object( determine_jobs, "changed_files", return_value=["esphome/config.py"] ): - result = determine_jobs.should_run_integration_tests() - assert result is False + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == [] # Python files in subdirectories (not core) do NOT trigger tests with patch.object( @@ -365,35 +374,151 @@ def test_should_run_integration_tests( "changed_files", return_value=["esphome/dashboard/web_server.py"], ): - result = determine_jobs.should_run_integration_tests() - assert result is False + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == [] -def test_should_run_integration_tests_with_branch() -> None: - """Test should_run_integration_tests with branch argument.""" +def test_determine_integration_tests_with_branch() -> None: + """Test determine_integration_tests with branch argument.""" with patch.object(determine_jobs, "changed_files") as mock_changed: mock_changed.return_value = [] - determine_jobs.should_run_integration_tests("release") + run_all, test_files = determine_jobs.determine_integration_tests("release") mock_changed.assert_called_once_with("release") + assert run_all is False + assert test_files == [] -def test_should_run_integration_tests_component_dependency() -> None: - """Test that integration tests run when components used in fixtures change.""" +def test_determine_integration_tests_component_dependency() -> None: + """Test that integration tests return specific test files when components used in fixtures change.""" with ( patch.object( determine_jobs, "changed_files", return_value=["esphome/components/api/api.cpp"], ), + patch.object(determine_jobs, "get_fixture_to_test_files") as mock_fixture_map, patch.object( - determine_jobs, "get_components_from_integration_fixtures" - ) as mock_fixtures, + determine_jobs, "get_integration_test_files_for_components" + ) as mock_test_files, ): - mock_fixtures.return_value = {"api", "sensor"} - with patch.object(determine_jobs, "get_all_dependencies") as mock_deps: - mock_deps.return_value = {"api", "sensor", "network"} - result = determine_jobs.should_run_integration_tests() - assert result is True + mock_fixture_map.return_value = {} + mock_test_files.return_value = [ + "tests/integration/test_api.py", + "tests/integration/test_sensor.py", + ] + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == [ + "tests/integration/test_api.py", + "tests/integration/test_sensor.py", + ] + + +def test_determine_integration_tests_component_only_affected_tests() -> None: + """Test that only tests using the changed component are returned.""" + with ( + patch.object( + determine_jobs, + "changed_files", + return_value=["esphome/components/modbus/modbus.cpp"], + ), + patch.object(determine_jobs, "get_fixture_to_test_files", return_value={}), + patch.object( + determine_jobs, "get_integration_test_files_for_components" + ) as mock_test_files, + ): + mock_test_files.return_value = [ + "tests/integration/test_uart_mock_modbus.py", + ] + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == ["tests/integration/test_uart_mock_modbus.py"] + # Verify it was called with the right component + mock_test_files.assert_called_once_with({"modbus"}) + + +def test_determine_integration_tests_infra_file_runs_all() -> None: + """Test that changing infrastructure files (conftest.py, etc.) runs all tests.""" + with patch.object( + determine_jobs, + "changed_files", + return_value=["tests/integration/conftest.py"], + ): + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is True + assert test_files == [] + + +def test_determine_integration_tests_readme_does_not_run_all() -> None: + """Test that changing README.md does not trigger integration tests.""" + with patch.object( + determine_jobs, + "changed_files", + return_value=["tests/integration/README.md"], + ): + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == [] + + +def test_determine_integration_tests_changed_test_file() -> None: + """Test that changing a specific test file only runs that test.""" + with ( + patch.object( + determine_jobs, + "changed_files", + return_value=["tests/integration/test_syslog.py"], + ), + patch.object(determine_jobs, "get_fixture_to_test_files", return_value={}), + patch.object( + determine_jobs, + "get_integration_test_files_for_components", + return_value=[], + ), + ): + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == ["tests/integration/test_syslog.py"] + + +def test_determine_integration_tests_changed_fixture_yaml() -> None: + """Test that changing a fixture YAML runs the corresponding test file.""" + with ( + patch.object( + determine_jobs, + "changed_files", + return_value=["tests/integration/fixtures/uart_mock_modbus.yaml"], + ), + patch.object(determine_jobs, "get_fixture_to_test_files") as mock_fixture_map, + patch.object( + determine_jobs, + "get_integration_test_files_for_components", + return_value=[], + ), + ): + mock_fixture_map.return_value = { + "uart_mock_modbus": frozenset( + {"tests/integration/test_uart_mock_modbus.py"} + ), + } + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is False + assert test_files == ["tests/integration/test_uart_mock_modbus.py"] + + +def test_determine_integration_tests_non_yaml_fixture_runs_all() -> None: + """Test that non-YAML changes under fixtures/ (e.g., external_components) run all tests.""" + with patch.object( + determine_jobs, + "changed_files", + return_value=[ + "tests/integration/fixtures/external_components/test_component/__init__.py" + ], + ): + run_all, test_files = determine_jobs.determine_integration_tests() + assert run_all is True + assert test_files == [] @pytest.mark.parametrize( @@ -538,7 +663,7 @@ def test_count_changed_cpp_files_with_branch() -> None: def test_main_filters_components_without_tests( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -551,7 +676,7 @@ def test_main_filters_components_without_tests( # Ensure we're not in GITHUB_ACTIONS mode for this test monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = False mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False @@ -631,7 +756,7 @@ def test_main_filters_components_without_tests( def test_main_detects_components_with_variant_tests( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -649,7 +774,7 @@ def test_main_detects_components_with_variant_tests( # Ensure we're not in GITHUB_ACTIONS mode for this test monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = False mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False @@ -999,7 +1124,7 @@ def test_detect_memory_impact_config_with_variant_tests(tmp_path: Path) -> None: def test_clang_tidy_mode_full_scan( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -1010,7 +1135,7 @@ def test_clang_tidy_mode_full_scan( """Test that full scan (hash changed) always uses split mode.""" monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = True mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False @@ -1065,7 +1190,7 @@ def test_clang_tidy_mode_targeted_scan( component_count: int, files_per_component: int, expected_mode: str, - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -1076,7 +1201,7 @@ def test_clang_tidy_mode_targeted_scan( """Test clang-tidy mode selection based on files_to_check count.""" monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = True mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False @@ -1123,7 +1248,7 @@ def test_clang_tidy_mode_targeted_scan( def test_main_core_files_changed_still_detects_components( - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -1135,7 +1260,7 @@ def test_main_core_files_changed_still_detects_components( """Test that component changes are detected even when core files change.""" monkeypatch.delenv("GITHUB_ACTIONS", raising=False) - mock_should_run_integration_tests.return_value = True + mock_determine_integration_tests.return_value = (True, []) mock_should_run_clang_tidy.return_value = True mock_should_run_clang_format.return_value = True mock_should_run_python_linters.return_value = True @@ -1604,7 +1729,7 @@ def test_detect_platform_hint_from_filename_case_insensitive( def test_component_batching_beta_branch_40_per_batch( tmp_path: Path, - mock_should_run_integration_tests: Mock, + mock_determine_integration_tests: Mock, mock_should_run_clang_tidy: Mock, mock_should_run_clang_format: Mock, mock_should_run_python_linters: Mock, @@ -1628,7 +1753,7 @@ def test_component_batching_beta_branch_40_per_batch( (comp_dir / "test.esp32-idf.yaml").write_text(f"# Test for {comp}") # Setup mocks - mock_should_run_integration_tests.return_value = False + mock_determine_integration_tests.return_value = (False, []) mock_should_run_clang_tidy.return_value = False mock_should_run_clang_format.return_value = False mock_should_run_python_linters.return_value = False diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index 781054eb3b..e3802d2d51 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -36,6 +36,7 @@ def clear_helpers_cache() -> None: """Clear cached functions before each test.""" helpers._get_github_event_data.cache_clear() helpers._get_changed_files_github_actions.cache_clear() + helpers.get_components_per_integration_fixture.cache_clear() @pytest.mark.parametrize( @@ -1111,7 +1112,7 @@ def test_get_components_from_integration_fixtures() -> None: "gpio", } - mock_yaml_file = Mock() + mock_yaml_file = Mock(stem="test_fixture") with ( patch("pathlib.Path.glob") as mock_glob, @@ -1133,7 +1134,7 @@ def test_get_components_from_integration_fixtures_skips_yaml_anchors() -> None: ".binary_filters": {"filters": [{"settle": "50ms"}]}, } - mock_yaml_file = Mock() + mock_yaml_file = Mock(stem="test_fixture") with ( patch("pathlib.Path.glob") as mock_glob, @@ -1148,6 +1149,31 @@ def test_get_components_from_integration_fixtures_skips_yaml_anchors() -> None: assert components == {"sensor", "esphome", "template"} +def test_get_integration_test_files_for_components_real_fixtures() -> None: + """Test that component changes map to the correct real integration test files. + + This test uses real fixtures to verify the mapping stays correct + as new tests are added. + """ + # modbus should include at least the modbus test + modbus_tests = helpers.get_integration_test_files_for_components({"modbus"}) + assert "tests/integration/test_uart_mock_modbus.py" in modbus_tests + + # ld2410 should include at least the ld2410 test + ld2410_tests = helpers.get_integration_test_files_for_components({"ld2410"}) + assert "tests/integration/test_uart_mock_ld2410.py" in ld2410_tests + + # syslog should include at least the syslog test + syslog_tests = helpers.get_integration_test_files_for_components({"syslog"}) + assert "tests/integration/test_syslog.py" in syslog_tests + + # A component not used by any fixture should return nothing + fake_tests = helpers.get_integration_test_files_for_components( + {"nonexistent_component_xyz"} + ) + assert fake_tests == [] + + @pytest.mark.parametrize( "output,expected", [ From 7cceb72cc310e784acd249ff1108793abe36293f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 13:23:41 -1000 Subject: [PATCH 1342/2030] [api] Inline force-variant ProtoSize calc methods (#14781) --- esphome/components/api/proto.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index d1c955b1fb..814a3f4456 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -602,7 +602,7 @@ class ProtoSize { static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value) { return value ? field_id_size + varint(encode_zigzag32(value)) : 0; } - static constexpr uint32_t calc_sint32_force(uint32_t field_id_size, int32_t value) { + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_sint32_force(uint32_t field_id_size, int32_t value) { return field_id_size + varint(encode_zigzag32(value)); } static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value) { @@ -614,13 +614,13 @@ class ProtoSize { static constexpr uint32_t calc_uint64(uint32_t field_id_size, uint64_t value) { return value ? field_id_size + varint(value) : 0; } - static constexpr uint32_t calc_uint64_force(uint32_t field_id_size, uint64_t value) { + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_uint64_force(uint32_t field_id_size, uint64_t value) { return field_id_size + varint(value); } static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len) { return len ? field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len) : 0; } - static constexpr uint32_t calc_length_force(uint32_t field_id_size, size_t len) { + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_length_force(uint32_t field_id_size, size_t len) { return field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len); } static constexpr uint32_t calc_sint64(uint32_t field_id_size, int64_t value) { @@ -638,7 +638,8 @@ class ProtoSize { static constexpr uint32_t calc_message(uint32_t field_id_size, uint32_t nested_size) { return nested_size ? field_id_size + varint(nested_size) + nested_size : 0; } - static constexpr uint32_t calc_message_force(uint32_t field_id_size, uint32_t nested_size) { + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_message_force(uint32_t field_id_size, + uint32_t nested_size) { return field_id_size + varint(nested_size) + nested_size; } }; From 86b79330815c75cb3cd980afecfe80eb87b1026a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 13 Mar 2026 19:24:41 -0400 Subject: [PATCH 1343/2030] [esp32_rmt_led_strip][remote_transmitter][remote_receiver] Fix ESP-IDF 6.0 RMT compatibility (#14783) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../components/esp32_rmt_led_strip/led_strip.cpp | 2 -- .../remote_receiver/remote_receiver_rmt.cpp | 1 - .../remote_transmitter/remote_transmitter_rmt.cpp | 13 +++++++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/esphome/components/esp32_rmt_led_strip/led_strip.cpp b/esphome/components/esp32_rmt_led_strip/led_strip.cpp index 66b41931aa..ca97a181fd 100644 --- a/esphome/components/esp32_rmt_led_strip/led_strip.cpp +++ b/esphome/components/esp32_rmt_led_strip/led_strip.cpp @@ -99,8 +99,6 @@ void ESP32RMTLEDStripLightOutput::setup() { channel.gpio_num = gpio_num_t(this->pin_); channel.mem_block_symbols = this->rmt_symbols_; channel.trans_queue_depth = 1; - channel.flags.io_loop_back = 0; - channel.flags.io_od_mode = 0; channel.flags.invert_out = this->invert_out_; channel.flags.with_dma = this->use_dma_; channel.intr_priority = 0; diff --git a/esphome/components/remote_receiver/remote_receiver_rmt.cpp b/esphome/components/remote_receiver/remote_receiver_rmt.cpp index 96b23bd0f5..596608a4d0 100644 --- a/esphome/components/remote_receiver/remote_receiver_rmt.cpp +++ b/esphome/components/remote_receiver/remote_receiver_rmt.cpp @@ -44,7 +44,6 @@ void RemoteReceiverComponent::setup() { channel.intr_priority = 0; channel.flags.invert_in = 0; channel.flags.with_dma = this->with_dma_; - channel.flags.io_loop_back = 0; esp_err_t error = rmt_new_rx_channel(&channel, &this->channel_); if (error != ESP_OK) { this->error_code_ = error; diff --git a/esphome/components/remote_transmitter/remote_transmitter_rmt.cpp b/esphome/components/remote_transmitter/remote_transmitter_rmt.cpp index 71773e3ddf..3c9a12d472 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_rmt.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_rmt.cpp @@ -120,11 +120,13 @@ void RemoteTransmitterComponent::configure_rmt_() { channel.gpio_num = gpio_num_t(this->pin_->get_pin()); channel.mem_block_symbols = this->rmt_symbols_; channel.trans_queue_depth = 1; - channel.flags.io_loop_back = open_drain; - channel.flags.io_od_mode = open_drain; channel.flags.invert_out = 0; channel.flags.with_dma = this->with_dma_; channel.intr_priority = 0; +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) + channel.flags.io_loop_back = open_drain; + channel.flags.io_od_mode = open_drain; +#endif error = rmt_new_tx_channel(&channel, &this->channel_); if (error != ESP_OK) { this->error_code_ = error; @@ -136,6 +138,13 @@ void RemoteTransmitterComponent::configure_rmt_() { this->mark_failed(); return; } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + if (open_drain) { + gpio_num_t gpio = gpio_num_t(this->pin_->get_pin()); + gpio_od_enable(gpio); + gpio_input_enable(gpio); + } +#endif if (this->pin_->get_flags() & gpio::FLAG_PULLUP) { gpio_pullup_en(gpio_num_t(this->pin_->get_pin())); } else { From d6d3bbbad8f6e14a78c2f6c7505bdbfcbd3dad2d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 13:28:34 -1000 Subject: [PATCH 1344/2030] [scheduler] Use integer math for interval offset calculation (#14755) --- esphome/core/scheduler.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 63e1006b03..72b183384e 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -105,10 +105,11 @@ static void validate_static_string(const char *name) { // avoid the main thread modifying the list while it is being accessed. // Calculate random offset for interval timers -// Extracted from set_timer_common_ to reduce code size - float math + random_float() -// only needed for intervals, not timeouts +// Extracted from set_timer_common_ to reduce code size - only needed for intervals, not timeouts uint32_t Scheduler::calculate_interval_offset_(uint32_t delay) { - return static_cast<uint32_t>(std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); + uint32_t max_offset = std::min(delay / 2, MAX_INTERVAL_DELAY); + // Multiply-and-shift: uniform random in [0, max_offset) without floating point + return static_cast<uint32_t>((static_cast<uint64_t>(random_uint32()) * max_offset) >> 32); } // Check if a retry was already cancelled in items_ or to_add_ From 5e3c44d48fc5e7870725e5572accf0d0b0cd9de0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 13:28:55 -1000 Subject: [PATCH 1345/2030] [rp2040] Add CI check for boards.py freshness (#14754) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/ci.yml | 1 + esphome/components/rp2040/generate_boards.py | 12 +++- script/generate-rp2040-boards.py | 61 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100755 script/generate-rp2040-boards.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fedfebf393..f7710589c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,6 +106,7 @@ jobs: script/build_codeowners.py --check script/build_language_schema.py --check script/generate-esp32-boards.py --check + script/generate-rp2040-boards.py --check pytest: name: Run pytest diff --git a/esphome/components/rp2040/generate_boards.py b/esphome/components/rp2040/generate_boards.py index a0e3699f37..7ea02d185e 100644 --- a/esphome/components/rp2040/generate_boards.py +++ b/esphome/components/rp2040/generate_boards.py @@ -6,6 +6,7 @@ Usage: python esphome/components/rp2040/generate_boards.py <arduino-pico-path> import json from pathlib import Path import re +import subprocess import sys from jinja2 import Environment, FileSystemLoader @@ -157,7 +158,7 @@ def generate(arduino_pico_path: Path) -> str: board_pins, boards = load_boards(arduino_pico_path) template = _jinja_env.get_template("boards.jinja2") - return template.render( + content = template.render( cyw43_gpio_offset=CYW43_GPIO_OFFSET, cyw43_max_gpio=CYW43_GPIO_OFFSET + CYW43_GPIO_COUNT - 1, default_max_pin=DEFAULT_MAX_PIN, @@ -165,6 +166,15 @@ def generate(arduino_pico_path: Path) -> str: boards=sorted(boards.items()), ) + # Format output to match pre-commit ruff formatting + result = subprocess.run( + [sys.executable, "-m", "ruff", "format", "--stdin-filename", "boards.py"], + input=content.encode(), + capture_output=True, + check=True, + ) + return result.stdout.decode() + def main(): if len(sys.argv) < 2: diff --git a/script/generate-rp2040-boards.py b/script/generate-rp2040-boards.py new file mode 100755 index 0000000000..1b4846fd2b --- /dev/null +++ b/script/generate-rp2040-boards.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +from __future__ import annotations + +import argparse +from pathlib import Path +import subprocess +import sys +import tempfile + +from esphome.components.rp2040 import RECOMMENDED_ARDUINO_FRAMEWORK_VERSION +from esphome.components.rp2040.generate_boards import generate +from esphome.helpers import write_file_if_changed + +ver = RECOMMENDED_ARDUINO_FRAMEWORK_VERSION +version_tag: str = f"{ver.major}.{ver.minor}.{ver.patch}" +root: Path = Path(__file__).parent.parent +boards_file_path: Path = root / "esphome" / "components" / "rp2040" / "boards.py" + + +def main(check: bool) -> None: + with tempfile.TemporaryDirectory() as tempdir: + subprocess.run( + [ + "git", + "clone", + "-q", + "-c", + "advice.detachedHead=false", + "--depth", + "1", + "--branch", + version_tag, + "https://github.com/earlephilhower/arduino-pico", + tempdir, + ], + check=True, + ) + + content: str = generate(Path(tempdir)) + + if check: + existing_content: str = boards_file_path.read_text(encoding="utf-8") + if existing_content != content: + print("esphome/components/rp2040/boards.py is not up to date.") + print("Please run `script/generate-rp2040-boards.py`") + sys.exit(1) + print("esphome/components/rp2040/boards.py is up to date") + elif write_file_if_changed(boards_file_path, content): + print("RP2040 boards updated successfully.") + + +if __name__ == "__main__": + parser: argparse.ArgumentParser = argparse.ArgumentParser() + parser.add_argument( + "--check", + help="Check if the boards.py file is up to date.", + action="store_true", + ) + args: argparse.Namespace = parser.parse_args() + main(args.check) From fcf5637aa5f42823d14015ec10c8aced123c1842 Mon Sep 17 00:00:00 2001 From: leccelecce <24962424+leccelecce@users.noreply.github.com> Date: Sat, 14 Mar 2026 13:15:54 +0000 Subject: [PATCH 1346/2030] [online_image] Log download duration in milliseconds instead of seconds (#14803) --- esphome/components/online_image/online_image.cpp | 6 +++--- esphome/components/online_image/online_image.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index da866599c9..22bf6a3056 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -129,7 +129,7 @@ void OnlineImage::update() { } ESP_LOGI(TAG, "Downloading image (Size: %zu)", total_size); - this->start_time_ = ::time(nullptr); + this->start_time_ = millis(); this->enable_loop(); } @@ -155,8 +155,8 @@ void OnlineImage::loop() { // Finalize decoding this->end_decode(); - ESP_LOGD(TAG, "Image fully downloaded, %zu bytes in %" PRIu32 "s", this->downloader_->get_bytes_read(), - (uint32_t) (::time(nullptr) - this->start_time_)); + ESP_LOGD(TAG, "Image fully downloaded, %zu bytes in %" PRIu32 " ms", this->downloader_->get_bytes_read(), + millis() - this->start_time_); // Save caching headers this->etag_ = this->downloader_->get_response_header(ETAG_HEADER_NAME); diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index c7c80c7c66..12c2564526 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -97,7 +97,7 @@ class OnlineImage : public PollingComponent, */ std::string last_modified_ = ""; - time_t start_time_; + uint32_t start_time_{0}; }; template<typename... Ts> class OnlineImageSetUrlAction : public Action<Ts...> { From 0716c9f7227873bc236009ce5438cf0974bffe53 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 08:12:04 -1000 Subject: [PATCH 1347/2030] [core] Inline LwIPLock as no-op on platforms without lwIP core locking (#14787) --- esphome/components/esp8266/helpers.cpp | 4 +--- esphome/components/libretiny/helpers.cpp | 4 +--- esphome/components/zephyr/core.cpp | 4 +--- esphome/core/helpers.h | 22 +++++++++++++++------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/esphome/components/esp8266/helpers.cpp b/esphome/components/esp8266/helpers.cpp index 036594fa17..4a64ae181e 100644 --- a/esphome/components/esp8266/helpers.cpp +++ b/esphome/components/esp8266/helpers.cpp @@ -22,9 +22,7 @@ void Mutex::unlock() {} IRAM_ATTR InterruptLock::InterruptLock() { state_ = xt_rsil(15); } IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(state_); } -// ESP8266 doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// ESP8266 LwIPLock is defined inline as a no-op in helpers.h void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) wifi_get_macaddr(STATION_IF, mac); diff --git a/esphome/components/libretiny/helpers.cpp b/esphome/components/libretiny/helpers.cpp index 37ae0fb455..21913e4a16 100644 --- a/esphome/components/libretiny/helpers.cpp +++ b/esphome/components/libretiny/helpers.cpp @@ -26,9 +26,7 @@ void Mutex::unlock() { xSemaphoreGive(this->handle_); } IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); } IRAM_ATTR InterruptLock::~InterruptLock() { portENABLE_INTERRUPTS(); } -// LibreTiny doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// LibreTiny LwIPLock is defined inline as a no-op in helpers.h void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) WiFi.macAddress(mac); diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index eee7fb3f4f..1d105a1057 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -76,9 +76,7 @@ void Mutex::unlock() { k_mutex_unlock(static_cast<k_mutex *>(this->handle_)); } IRAM_ATTR InterruptLock::InterruptLock() { state_ = irq_lock(); } IRAM_ATTR InterruptLock::~InterruptLock() { irq_unlock(state_); } -// Zephyr doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// Zephyr LwIPLock is defined inline as a no-op in helpers.h uint32_t random_uint32() { return rand(); } // NOLINT(cert-msc30-c, cert-msc50-cpp) bool random_bytes(uint8_t *data, size_t len) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 9828df29cb..2267208752 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1930,19 +1930,27 @@ class InterruptLock { /** Helper class to lock the lwIP TCPIP core when making lwIP API calls from non-TCPIP threads. * - * This is needed on multi-threaded platforms (ESP32) when CONFIG_LWIP_TCPIP_CORE_LOCKING is enabled. - * It ensures thread-safe access to lwIP APIs. + * This is needed on multi-threaded platforms (ESP32) when CONFIG_LWIP_TCPIP_CORE_LOCKING is enabled, + * and on RP2040 when CYW43 WiFi is active (cyw43_arch_lwip_begin/end). * - * @note This follows the same pattern as InterruptLock - platform-specific implementations in helpers.cpp + * On platforms without lwIP core locking (ESP8266, LibreTiny, Zephyr), + * this is a no-op defined inline so the compiler can eliminate all call overhead. */ class LwIPLock { public: - LwIPLock(); - ~LwIPLock(); - - // Delete copy constructor and copy assignment operator to prevent accidental copying LwIPLock(const LwIPLock &) = delete; LwIPLock &operator=(const LwIPLock &) = delete; + +#if defined(USE_ESP32) || defined(USE_RP2040) + // Platforms with potential lwIP core locking — out-of-line implementations in helpers.cpp + LwIPLock(); + ~LwIPLock(); +#else + // No lwIP core locking — inline no-ops (empty bodies instead of = default + // to prevent clang-tidy unused-variable warnings at call sites) + LwIPLock() {} + ~LwIPLock() {} +#endif }; /** Helper class to request `loop()` to be called as fast as possible. From 0043be616529e78cf7b9717f9fadf50749b904d2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 08:13:01 -1000 Subject: [PATCH 1348/2030] [core] Inline trivial EntityBase accessors (#14782) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/core/entity_base.cpp | 5 ----- esphome/core/entity_base.h | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/esphome/core/entity_base.cpp b/esphome/core/entity_base.cpp index 818dae06de..a47af1dd93 100644 --- a/esphome/core/entity_base.cpp +++ b/esphome/core/entity_base.cpp @@ -8,9 +8,6 @@ namespace esphome { static const char *const TAG = "entity_base"; -// Entity Name -const StringRef &EntityBase::get_name() const { return this->name_; } - void EntityBase::configure_entity_(const char *name, uint32_t object_id_hash, uint32_t entity_fields) { this->name_ = StringRef(name); if (this->name_.empty()) { @@ -176,8 +173,6 @@ StringRef EntityBase::get_object_id_to(std::span<char, OBJECT_ID_MAX_LEN> buf) c return StringRef(buf.data(), len); } -uint32_t EntityBase::get_object_id_hash() { return this->object_id_hash_; } - // Migrate preference data from old_key to new_key if they differ. // This helper is exposed so callers with custom key computation (like TextPrefs) // can use it for manual migration. See: https://github.com/esphome/backlog/issues/85 diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index cccbafd2c3..012a62f1c0 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -68,7 +68,7 @@ static constexpr uint8_t ENTITY_FIELD_ENTITY_CATEGORY_SHIFT = 26; class EntityBase { public: // Get the name of this Entity - const StringRef &get_name() const; + const StringRef &get_name() const { return this->name_; } // Get whether this Entity has its own name or it should use the device friendly_name. bool has_own_name() const { return this->flags_.has_own_name; } @@ -86,7 +86,7 @@ class EntityBase { std::string get_object_id() const; // Get the unique Object ID of this Entity - uint32_t get_object_id_hash(); + uint32_t get_object_id_hash() const { return this->object_id_hash_; } /// Get object_id with zero heap allocation /// For static case: returns StringRef to internal storage (buffer unused) From f2968e044903ca35db4da1e1773323c74b19fee2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 08:13:50 -1000 Subject: [PATCH 1349/2030] [api] Reduce API code size with buffer and nodelay optimizations (#14797) --- esphome/components/api/api_buffer.h | 6 +++++ esphome/components/api/api_connection.cpp | 3 +-- esphome/components/api/api_connection.h | 6 ++--- esphome/components/api/api_frame_helper.h | 29 ++++++++++------------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/esphome/components/api/api_buffer.h b/esphome/components/api/api_buffer.h index 00801e3ee5..1d0cccf61c 100644 --- a/esphome/components/api/api_buffer.h +++ b/esphome/components/api/api_buffer.h @@ -44,6 +44,12 @@ class APIBuffer { this->reserve(n); this->size_ = n; // no zero-fill } + /// Reserve capacity for max(reserve_size, new_size) bytes, then set size to new_size. + /// Single grow_ check regardless of argument order. + inline void reserve_and_resize(size_t reserve_size, size_t new_size) ESPHOME_ALWAYS_INLINE { + this->reserve(std::max(reserve_size, new_size)); + this->size_ = new_size; + } uint8_t *data() { return this->data_.get(); } const uint8_t *data() const { return this->data_.get(); } size_t size() const { return this->size_; } diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index dea3ba5460..d55b5dffb6 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -2025,8 +2025,7 @@ uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncode // Batch message second or later // Add padding for previous message footer + this message header size_t current_size = shared_buf.size(); - shared_buf.reserve(current_size + total_calculated_size); - shared_buf.resize(current_size + footer_size + header_padding); + shared_buf.reserve_and_resize(current_size + total_calculated_size, current_size + footer_size + header_padding); } // Pre-resize buffer to include payload, then encode through raw pointer diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 68f698d190..85c8e777a9 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -305,9 +305,9 @@ class APIConnection final : public APIServerConnectionBase { // Reserve space for header padding + message + footer // - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext) // - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext) - shared_buf.reserve(total_size); - // Resize to add header padding so message encoding starts at the correct position - shared_buf.resize(header_padding); + // Reserve full size but only set initial size to header padding + // so message encoding starts at the correct position + shared_buf.reserve_and_resize(total_size, header_padding); } // Convenience overload - computes frame overhead internally diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 5e07ad43a9..b2561f2b32 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -147,22 +147,18 @@ class APIFrameHelper { // void set_nodelay_for_message(bool is_log_message) { if (!is_log_message) { - if (this->nodelay_state_ != NODELAY_ON) { + if (this->nodelay_counter_) { this->set_nodelay_raw_(true); - this->nodelay_state_ = NODELAY_ON; + this->nodelay_counter_ = 0; } return; } - - // Log messages: state transitions -1 -> 1 -> ... -> LOG_NAGLE_COUNT -> -1 (flush) - if (this->nodelay_state_ == NODELAY_ON) { + // Log message: enable Nagle on first, flush after LOG_NAGLE_COUNT + if (!this->nodelay_counter_) this->set_nodelay_raw_(false); - this->nodelay_state_ = 1; - } else if (this->nodelay_state_ >= LOG_NAGLE_COUNT) { + if (++this->nodelay_counter_ > LOG_NAGLE_COUNT) { this->set_nodelay_raw_(true); - this->nodelay_state_ = NODELAY_ON; - } else { - this->nodelay_state_++; + this->nodelay_counter_ = 0; } } virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0; @@ -258,18 +254,17 @@ class APIFrameHelper { uint8_t tx_buf_head_{0}; uint8_t tx_buf_tail_{0}; uint8_t tx_buf_count_{0}; - // Nagle batching state for log messages. NODELAY_ON (-1) means NODELAY is enabled - // (immediate send). Values 1..LOG_NAGLE_COUNT count log messages in the current Nagle batch. - // After LOG_NAGLE_COUNT logs, we switch to NODELAY to flush and reset. + // Nagle batching counter for log messages. 0 means NODELAY is enabled (immediate send). + // Values 1..LOG_NAGLE_COUNT count log messages in the current Nagle batch. + // After LOG_NAGLE_COUNT logs, we flush by re-enabling NODELAY and resetting to 0. // ESP8266 has the tightest TCP send buffer (2×MSS) and needs conservative batching. // ESP32 (4×MSS+), RP2040 (8×MSS), and LibreTiny (4×MSS) can coalesce more. - static constexpr int8_t NODELAY_ON = -1; #ifdef USE_ESP8266 - static constexpr int8_t LOG_NAGLE_COUNT = 2; + static constexpr uint8_t LOG_NAGLE_COUNT = 2; #else - static constexpr int8_t LOG_NAGLE_COUNT = 3; + static constexpr uint8_t LOG_NAGLE_COUNT = 3; #endif - int8_t nodelay_state_{NODELAY_ON}; + uint8_t nodelay_counter_{0}; // Internal helper to set TCP_NODELAY socket option void set_nodelay_raw_(bool enable) { From ca279110c9157da5026451839e4a9b8b9724a69b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 08:31:50 -1000 Subject: [PATCH 1350/2030] [output] Inline trivial FloatOutput accessors (#14786) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/components/output/float_output.cpp | 6 ------ esphome/components/output/float_output.h | 8 ++++---- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/esphome/components/output/float_output.cpp b/esphome/components/output/float_output.cpp index 3b83c85716..46014e0903 100644 --- a/esphome/components/output/float_output.cpp +++ b/esphome/components/output/float_output.cpp @@ -11,16 +11,10 @@ void FloatOutput::set_max_power(float max_power) { this->max_power_ = clamp(max_power, this->min_power_, 1.0f); // Clamp to MIN>=MAX>=1.0 } -float FloatOutput::get_max_power() const { return this->max_power_; } - void FloatOutput::set_min_power(float min_power) { this->min_power_ = clamp(min_power, 0.0f, this->max_power_); // Clamp to 0.0>=MIN>=MAX } -void FloatOutput::set_zero_means_zero(bool zero_means_zero) { this->zero_means_zero_ = zero_means_zero; } - -float FloatOutput::get_min_power() const { return this->min_power_; } - void FloatOutput::set_level(float state) { state = clamp(state, 0.0f, 1.0f); diff --git a/esphome/components/output/float_output.h b/esphome/components/output/float_output.h index 3e2b3ada8d..5225f88c66 100644 --- a/esphome/components/output/float_output.h +++ b/esphome/components/output/float_output.h @@ -48,9 +48,9 @@ class FloatOutput : public BinaryOutput { /** Sets this output to ignore min_power for a 0 state * - * @param zero True if a 0 state should mean 0 and not min_power. + * @param zero_means_zero True if a 0 state should mean 0 and not min_power. */ - void set_zero_means_zero(bool zero_means_zero); + void set_zero_means_zero(bool zero_means_zero) { this->zero_means_zero_ = zero_means_zero; } /** Set the level of this float output, this is called from the front-end. * @@ -70,10 +70,10 @@ class FloatOutput : public BinaryOutput { // (In most use cases you won't need these) /// Get the maximum power output. - float get_max_power() const; + float get_max_power() const { return this->max_power_; } /// Get the minimum power output. - float get_min_power() const; + float get_min_power() const { return this->min_power_; } protected: /// Implement BinarySensor's write_enabled; this should never be called. From f12531e7e0b2a2702d3a68cbf95515839c885377 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:32:17 -0400 Subject: [PATCH 1351/2030] [esp32_camera] Bump esp32-camera to 2.1.5 (#14806) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/camera_encoder/__init__.py | 2 +- esphome/components/esp32_camera/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/camera_encoder/__init__.py b/esphome/components/camera_encoder/__init__.py index 89181d27b4..a0c59a517a 100644 --- a/esphome/components/camera_encoder/__init__.py +++ b/esphome/components/camera_encoder/__init__.py @@ -50,7 +50,7 @@ async def to_code(config: ConfigType) -> None: buffer = cg.new_Pvariable(config[CONF_ENCODER_BUFFER_ID]) cg.add(buffer.set_buffer_size(config[CONF_BUFFER_SIZE])) if config[CONF_TYPE] == ESP32_CAMERA_ENCODER: - add_idf_component(name="espressif/esp32-camera", ref="2.1.1") + add_idf_component(name="espressif/esp32-camera", ref="2.1.5") cg.add_define("USE_ESP32_CAMERA_JPEG_ENCODER") var = cg.new_Pvariable( config[CONF_ID], diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index 3a5d87792b..afab849a7c 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -400,7 +400,7 @@ async def to_code(config): if config[CONF_JPEG_QUALITY] != 0 and config[CONF_PIXEL_FORMAT] != "JPEG": cg.add_define("USE_ESP32_CAMERA_JPEG_CONVERSION") - add_idf_component(name="espressif/esp32-camera", ref="2.1.1") + add_idf_component(name="espressif/esp32-camera", ref="2.1.5") add_idf_sdkconfig_option("CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW", True) add_idf_sdkconfig_option("CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY", False) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index df651ae15d..d83a71624c 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -8,7 +8,7 @@ dependencies: espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: - version: 2.1.1 + version: 2.1.5 espressif/mdns: version: 1.10.0 espressif/esp_wifi_remote: From c52042e023c6178801a1c74e9480cfe4b9747689 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:01:29 -0400 Subject: [PATCH 1352/2030] [tinyusb][usb_cdc_acm] Bump esp_tinyusb to 2.1.1 (#14796) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/tinyusb/__init__.py | 2 +- esphome/components/tinyusb/tinyusb_component.cpp | 12 ++++++++---- esphome/components/usb_cdc_acm/usb_cdc_acm.h | 2 +- esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp | 7 +++---- esphome/idf_component.yml | 2 +- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/esphome/components/tinyusb/__init__.py b/esphome/components/tinyusb/__init__.py index 90043e969c..df94ad7534 100644 --- a/esphome/components/tinyusb/__init__.py +++ b/esphome/components/tinyusb/__init__.py @@ -54,7 +54,7 @@ async def to_code(config): if config[CONF_USB_SERIAL_STR]: cg.add(var.set_usb_desc_serial(config[CONF_USB_SERIAL_STR])) - add_idf_component(name="espressif/esp_tinyusb", ref="1.7.6~1") + add_idf_component(name="espressif/esp_tinyusb", ref="2.1.1") add_idf_sdkconfig_option("CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID", False) add_idf_sdkconfig_option("CONFIG_TINYUSB_DESC_USE_DEFAULT_PID", False) diff --git a/esphome/components/tinyusb/tinyusb_component.cpp b/esphome/components/tinyusb/tinyusb_component.cpp index 19bb545c4b..7f8fea5264 100644 --- a/esphome/components/tinyusb/tinyusb_component.cpp +++ b/esphome/components/tinyusb/tinyusb_component.cpp @@ -16,10 +16,14 @@ void TinyUSB::setup() { } this->tusb_cfg_ = { - .descriptor = &this->usb_descriptor_, - .string_descriptor = this->string_descriptor_, - .string_descriptor_count = SIZE, - .external_phy = false, + .port = TINYUSB_PORT_FULL_SPEED_0, + .phy = {.skip_setup = false}, + .descriptor = + { + .device = &this->usb_descriptor_, + .string = this->string_descriptor_, + .string_count = SIZE, + }, }; esp_err_t result = tinyusb_driver_install(&this->tusb_cfg_); diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index 624f41cf8c..020542e749 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -8,7 +8,7 @@ #include <functional> #include "freertos/ringbuf.h" -#include "tusb_cdc_acm.h" +#include "tinyusb_cdc_acm.h" namespace esphome::usb_cdc_acm { diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index 1a36ef9f31..583aa77d06 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -11,7 +11,7 @@ #include "esp_log.h" #include "tusb.h" -#include "tusb_cdc_acm.h" +#include "tinyusb_cdc_acm.h" namespace esphome::usb_cdc_acm { @@ -140,7 +140,6 @@ void USBCDCACMInstance::setup() { // Configure this CDC interface const tinyusb_config_cdcacm_t acm_cfg = { - .usb_dev = TINYUSB_USBDEV_0, .cdc_port = static_cast<tinyusb_cdcacm_itf_t>(this->itf_), .callback_rx = &tinyusb_cdc_rx_callback, .callback_rx_wanted_char = NULL, @@ -148,9 +147,9 @@ void USBCDCACMInstance::setup() { .callback_line_coding_changed = &tinyusb_cdc_line_coding_changed_callback, }; - esp_err_t result = tusb_cdc_acm_init(&acm_cfg); + esp_err_t result = tinyusb_cdcacm_init(&acm_cfg); if (result != ESP_OK) { - ESP_LOGE(TAG, "tusb_cdc_acm_init failed: %d", result); + ESP_LOGE(TAG, "tinyusb_cdcacm_init failed: %d", result); this->parent_->mark_failed(); return; } diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index d83a71624c..bb94de7e05 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -30,7 +30,7 @@ dependencies: rules: - if: "target in [esp32, esp32p4]" espressif/esp_tinyusb: - version: "1.7.6~1" + version: "2.1.1" rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: From 417858f09816f6d7ec726b11155eaeca63b8d9dc Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:01:49 -0400 Subject: [PATCH 1353/2030] [psram] Add ESP32-C61 PSRAM support (#14795) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/psram/__init__.py | 3 +++ tests/components/psram/test.esp32-c61-idf.yaml | 7 +++++++ 2 files changed, 10 insertions(+) create mode 100644 tests/components/psram/test.esp32-c61-idf.yaml diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index 39afb407f1..ccf35b851c 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -8,6 +8,7 @@ from esphome.components.esp32 import ( CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES, VARIANT_ESP32, VARIANT_ESP32C5, + VARIANT_ESP32C61, VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, @@ -53,6 +54,7 @@ CONF_ENABLE_ECC = "enable_ecc" SPIRAM_MODES = { VARIANT_ESP32: (TYPE_QUAD,), VARIANT_ESP32C5: (TYPE_QUAD,), + VARIANT_ESP32C61: (TYPE_QUAD,), VARIANT_ESP32S2: (TYPE_QUAD,), VARIANT_ESP32S3: (TYPE_QUAD, TYPE_OCTAL), VARIANT_ESP32P4: (TYPE_HEX,), @@ -62,6 +64,7 @@ SPIRAM_MODES = { SPIRAM_SPEEDS = { VARIANT_ESP32: (40, 80, 120), VARIANT_ESP32C5: (40, 80, 120), + VARIANT_ESP32C61: (40, 80), VARIANT_ESP32S2: (40, 80, 120), VARIANT_ESP32S3: (40, 80, 120), VARIANT_ESP32P4: (20, 100, 200), diff --git a/tests/components/psram/test.esp32-c61-idf.yaml b/tests/components/psram/test.esp32-c61-idf.yaml new file mode 100644 index 0000000000..d443aab951 --- /dev/null +++ b/tests/components/psram/test.esp32-c61-idf.yaml @@ -0,0 +1,7 @@ +esp32: + framework: + type: esp-idf + +psram: + speed: 80MHz + ignore_not_found: false From 271b423b227e8d92938f58ed126246c61afa3fae Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:01:58 -0400 Subject: [PATCH 1354/2030] [psram] Fix ESP-IDF 6.0 compatibility for PSRAM sdkconfig options (#14794) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/psram/__init__.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index ccf35b851c..9b364584ff 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -181,9 +181,6 @@ async def to_code(config): if config[CONF_MODE] == TYPE_OCTAL: cg.add_platformio_option("board_build.arduino.memory_type", "qio_opi") - add_idf_sdkconfig_option( - f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True - ) add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True) add_idf_sdkconfig_option("CONFIG_SPIRAM", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True) @@ -198,11 +195,19 @@ async def to_code(config): speed = int(config[CONF_SPEED][:-3]) add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed) - if config[CONF_MODE] == TYPE_OCTAL and speed == 120: - add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) - if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0): + if speed == 120: + variant = get_esp32_variant() + # On chips with MSPI timing tuning, FLASH and PSRAM share the core + # clock so flash frequency must match PSRAM frequency. + # ESP32 and ESP32-S2 don't have this constraint. + if variant not in (VARIANT_ESP32, VARIANT_ESP32S2): + add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) + if config[CONF_MODE] == TYPE_OCTAL and CORE.data[KEY_CORE][ + KEY_FRAMEWORK_VERSION + ] >= cv.Version(5, 4, 0): add_idf_sdkconfig_option( - "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True + "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", + True, ) if config[CONF_ENABLE_ECC]: add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True) From d4e1e32a300733b205c5da85d115e3c7c4df4336 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:02:06 -0400 Subject: [PATCH 1355/2030] [mipi_dsi] Fix ESP-IDF 6.0 compatibility for use_dma2d flag (#14792) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/mipi_dsi/mipi_dsi.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index 7103e0868d..e8e9ca2bfb 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -87,7 +87,9 @@ void MIPI_DSI::setup() { .vsync_front_porch = this->vsync_front_porch_, }, .flags = { +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) .use_dma2d = true, +#endif }}; // clang-format on err = esp_lcd_new_panel_dpi(this->bus_handle_, &dpi_config, &this->handle_); @@ -95,6 +97,13 @@ void MIPI_DSI::setup() { this->smark_failed(LOG_STR("esp_lcd_new_panel_dpi failed"), err); return; } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + err = esp_lcd_dpi_panel_enable_dma2d(this->handle_); + if (err != ESP_OK) { + this->smark_failed(LOG_STR("esp_lcd_dpi_panel_enable_dma2d failed"), err); + return; + } +#endif if (this->reset_pin_ != nullptr) { this->reset_pin_->setup(); this->reset_pin_->digital_write(true); From b126f3af3b3949d7e9d9b2cddad211e0fc7bdd29 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:02:13 -0400 Subject: [PATCH 1356/2030] [ledc] Fix ESP-IDF 6.0 compatibility for peripheral reset (#14790) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/ledc/ledc_output.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 592fc7bd0c..a3d1e4d392 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -5,10 +5,9 @@ #include <driver/ledc.h> #include <cinttypes> +#include <esp_idf_version.h> #include <esp_private/periph_ctrl.h> -#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) #include <hal/ledc_ll.h> -#endif #define CLOCK_FREQUENCY 80e6f @@ -161,7 +160,14 @@ void LEDCOutput::write_state(float state) { void LEDCOutput::setup() { if (!ledc_peripheral_reset_done) { ESP_LOGV(TAG, "Resetting LEDC peripheral to clear stale state after reboot"); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + PERIPH_RCC_ATOMIC() { + ledc_ll_enable_reset_reg(true); + ledc_ll_enable_reset_reg(false); + } +#else periph_module_reset(PERIPH_LEDC_MODULE); +#endif ledc_peripheral_reset_done = true; } From 158a119a5a6a4591e531739aae6e5f9fb1cb3880 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 10:43:04 -1000 Subject: [PATCH 1357/2030] [sha256] Migrate to PSA Crypto API for ESP-IDF 6.0 (#14809) --- esphome/components/sha256/sha256.cpp | 23 ++++++++++++++++++++++- esphome/components/sha256/sha256.h | 19 +++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/esphome/components/sha256/sha256.cpp b/esphome/components/sha256/sha256.cpp index 23995e6534..079665c959 100644 --- a/esphome/components/sha256/sha256.cpp +++ b/esphome/components/sha256/sha256.cpp @@ -8,7 +8,28 @@ namespace esphome::sha256 { -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_SHA256_PSA) + +// ESP-IDF 6.0 ships mbedtls 4.0 which removed the legacy mbedtls_sha256_* API. +// Use the PSA Crypto API instead. PSA crypto is auto-initialized by ESP-IDF +// at startup, so no psa_crypto_init() call is needed. + +SHA256::~SHA256() { psa_hash_abort(&this->op_); } + +void SHA256::init() { + psa_hash_abort(&this->op_); + this->op_ = PSA_HASH_OPERATION_INIT; + psa_hash_setup(&this->op_, PSA_ALG_SHA_256); +} + +void SHA256::add(const uint8_t *data, size_t len) { psa_hash_update(&this->op_, data, len); } + +void SHA256::calculate() { + size_t hash_length; + psa_hash_finish(&this->op_, this->digest_, sizeof(this->digest_), &hash_length); +} + +#elif defined(USE_SHA256_MBEDTLS) // CRITICAL ESP32 HARDWARE SHA ACCELERATION REQUIREMENTS (IDF 5.5.x): // diff --git a/esphome/components/sha256/sha256.h b/esphome/components/sha256/sha256.h index bafb359485..0f995fcd91 100644 --- a/esphome/components/sha256/sha256.h +++ b/esphome/components/sha256/sha256.h @@ -10,7 +10,20 @@ #include <memory> #include "esphome/core/hash_base.h" -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_ESP32) +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +// mbedtls 4.0 (IDF 6.0) removed the legacy mbedtls_sha256_* API. +// Use the PSA Crypto API instead. PSA crypto is auto-initialized by +// ESP-IDF at startup (esp_psa_crypto_init.c, priority 104). +#define USE_SHA256_PSA +#include <psa/crypto.h> +#else +#define USE_SHA256_MBEDTLS +#include "mbedtls/sha256.h" +#endif +#elif defined(USE_LIBRETINY) +#define USE_SHA256_MBEDTLS #include "mbedtls/sha256.h" #elif defined(USE_ESP8266) || defined(USE_RP2040) #include <bearssl/bearssl_hash.h> @@ -51,7 +64,9 @@ class SHA256 : public esphome::HashBase { size_t get_size() const override { return 32; } protected: -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_SHA256_PSA) + psa_hash_operation_t op_ = PSA_HASH_OPERATION_INIT; +#elif defined(USE_SHA256_MBEDTLS) // The mbedtls context for ESP32-S3 hardware SHA requires proper alignment and stack frame constraints. // See class documentation above for critical requirements. mbedtls_sha256_context ctx_{}; From 27942f19733d442998bd457531ffbc58ac3e8f63 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 11:05:39 -1000 Subject: [PATCH 1358/2030] [helpers] Replace deprecated std::is_trivial in FixedRingBuffer (#14808) --- esphome/core/helpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 2267208752..c2f4cace9a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -417,7 +417,7 @@ template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()> FixedRingBuffer() = default; ~FixedRingBuffer() { - if constexpr (std::is_trivial<T>::value) { + if constexpr (std::is_trivially_copyable<T>::value && std::is_trivially_default_constructible<T>::value) { ::operator delete(this->data_); } else { delete[] this->data_; @@ -430,7 +430,7 @@ template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()> /// Allocate capacity - can only be called once void init(index_type capacity) { - if constexpr (std::is_trivial<T>::value) { + if constexpr (std::is_trivially_copyable<T>::value && std::is_trivially_default_constructible<T>::value) { // Raw allocation without initialization (elements are written before read) // NOLINTNEXTLINE(bugprone-sizeof-expression) this->data_ = static_cast<T *>(::operator new(capacity * sizeof(T))); From 447c4669b1d7c3e66becaeeaaaf83071f07928ee Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 11:26:20 -1000 Subject: [PATCH 1359/2030] [esp32] Disable SHA-512 in mbedTLS on IDF 6.0+ and add idf_version() helper (#14810) --- esphome/components/esp32/__init__.py | 53 +++++++++++++++++++-- esphome/components/esp32/const.py | 1 + esphome/components/esp32_hosted/__init__.py | 15 ++---- esphome/components/ethernet/__init__.py | 10 ++-- esphome/components/psram/__init__.py | 7 +-- 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 475de6aa3e..eaa9aa163d 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -59,6 +59,7 @@ from .const import ( # noqa KEY_EXTRA_BUILD_FILES, KEY_FLASH_SIZE, KEY_FULL_CERT_BUNDLE, + KEY_IDF_VERSION, KEY_PATH, KEY_REF, KEY_REPO, @@ -420,9 +421,20 @@ def set_core_data(config): CORE.data[KEY_ESP32][KEY_EXCLUDE_COMPONENTS] = excluded # Initialize Arduino library tracking - cg.add_library() auto-enables libraries CORE.data[KEY_ESP32][KEY_ARDUINO_LIBRARIES] = set() - CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = cv.Version.parse( - config[CONF_FRAMEWORK][CONF_VERSION] - ) + framework_ver = cv.Version.parse(config[CONF_FRAMEWORK][CONF_VERSION]) + CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = framework_ver + + # Store the underlying IDF version for framework-agnostic checks + if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: + CORE.data[KEY_ESP32][KEY_IDF_VERSION] = framework_ver + elif (idf_ver := ARDUINO_IDF_VERSION_LOOKUP.get(framework_ver)) is not None: + CORE.data[KEY_ESP32][KEY_IDF_VERSION] = idf_ver + else: + raise cv.Invalid( + f"Arduino version {framework_ver} has no known ESP-IDF version mapping. " + "Please update ARDUINO_IDF_VERSION_LOOKUP.", + path=[CONF_FRAMEWORK, CONF_VERSION], + ) CORE.data[KEY_ESP32][KEY_BOARD] = config[CONF_BOARD] CORE.data[KEY_ESP32][KEY_FLASH_SIZE] = config[CONF_FLASH_SIZE] @@ -974,6 +986,7 @@ KEY_USB_SERIAL_JTAG_SECONDARY_REQUIRED = "usb_serial_jtag_secondary_required" KEY_MBEDTLS_PEER_CERT_REQUIRED = "mbedtls_peer_cert_required" KEY_MBEDTLS_PKCS7_REQUIRED = "mbedtls_pkcs7_required" KEY_FATFS_REQUIRED = "fatfs_required" +KEY_MBEDTLS_SHA512_REQUIRED = "mbedtls_sha512_required" def require_vfs_select() -> None: @@ -1043,6 +1056,25 @@ def require_mbedtls_pkcs7() -> None: CORE.data[KEY_ESP32][KEY_MBEDTLS_PKCS7_REQUIRED] = True +def require_mbedtls_sha512() -> None: + """Mark that mbedTLS SHA-384/SHA-512 support is required by a component. + + Call this from components that need to verify TLS certificates or signatures + using SHA-384 or SHA-512 algorithms. This prevents CONFIG_MBEDTLS_SHA384_C + and CONFIG_MBEDTLS_SHA512_C from being disabled. + """ + CORE.data[KEY_ESP32][KEY_MBEDTLS_SHA512_REQUIRED] = True + + +def idf_version() -> cv.Version: + """Return the underlying ESP-IDF version regardless of framework choice. + + For ESP-IDF builds this is the framework version directly. + For Arduino builds this is the mapped IDF version from ARDUINO_IDF_VERSION_LOOKUP. + """ + return CORE.data[KEY_ESP32][KEY_IDF_VERSION] + + def require_fatfs() -> None: """Mark that FATFS support is required by a component. @@ -1802,6 +1834,21 @@ async def to_code(config): elif advanced[CONF_DISABLE_MBEDTLS_PKCS7]: add_idf_sdkconfig_option("CONFIG_MBEDTLS_PKCS7_C", False) + # Disable SHA-384 and SHA-512 in mbedTLS + # ESPHome doesn't use either algorithm. SHA-384 shares the same + # compression function as SHA-512 (mbedtls_internal_sha512_process), + # so both must be disabled to eliminate the ~3KB software fallback + # that IDF 6.0's PSA parallel engine always links in. + # On IDF < 6.0 these are a single config and hardware-only (no + # software fallback), so there was no code size cost to leaving + # them enabled. + # Components that need SHA-384/SHA-512 can call require_mbedtls_sha512() + if idf_version() >= cv.Version(6, 0, 0) and not CORE.data[KEY_ESP32].get( + KEY_MBEDTLS_SHA512_REQUIRED, False + ): + add_idf_sdkconfig_option("CONFIG_MBEDTLS_SHA384_C", False) + add_idf_sdkconfig_option("CONFIG_MBEDTLS_SHA512_C", False) + # Disable regi2c control functions in IRAM # Only needed if using analog peripherals (ADC, DAC, etc.) from ISRs while cache is disabled if advanced[CONF_DISABLE_REGI2C_IN_IRAM]: diff --git a/esphome/components/esp32/const.py b/esphome/components/esp32/const.py index 7874c1c759..d0d00723fc 100644 --- a/esphome/components/esp32/const.py +++ b/esphome/components/esp32/const.py @@ -15,6 +15,7 @@ KEY_PATH = "path" KEY_SUBMODULES = "submodules" KEY_EXTRA_BUILD_FILES = "extra_build_files" KEY_FULL_CERT_BUNDLE = "full_cert_bundle" +KEY_IDF_VERSION = "idf_version" VARIANT_ESP32 = "ESP32" VARIANT_ESP32C2 = "ESP32C2" diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index a51ae2cd66..3f9185745d 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -4,14 +4,7 @@ from pathlib import Path from esphome import pins from esphome.components import esp32 import esphome.config_validation as cv -from esphome.const import ( - CONF_CLK_PIN, - CONF_RESET_PIN, - CONF_VARIANT, - KEY_CORE, - KEY_FRAMEWORK_VERSION, -) -from esphome.core import CORE +from esphome.const import CONF_CLK_PIN, CONF_RESET_PIN, CONF_VARIANT from esphome.cpp_generator import add_define CODEOWNERS = ["@swoboda1337"] @@ -100,9 +93,9 @@ async def to_code(config): int(config[CONF_SDIO_FREQUENCY] // 1000), ) - framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] - os.environ["ESP_IDF_VERSION"] = f"{framework_ver.major}.{framework_ver.minor}" - if framework_ver >= cv.Version(5, 5, 0): + idf_ver = esp32.idf_version() + os.environ["ESP_IDF_VERSION"] = f"{idf_ver.major}.{idf_ver.minor}" + if idf_ver >= cv.Version(5, 5, 0): esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.4.0") esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.1") diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 935d2004d4..e520c0e914 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -14,6 +14,7 @@ from esphome.components.esp32 import ( add_idf_component, add_idf_sdkconfig_option, get_esp32_variant, + idf_version, include_builtin_idf_component, ) from esphome.components.network import ip_address_literal @@ -176,13 +177,12 @@ ManualIP = ethernet_ns.struct("ManualIP") def _is_framework_spi_polling_mode_supported(): # SPI Ethernet without IRQ feature is added in # esp-idf >= (5.3+ ,5.2.1+, 5.1.4) - # Note: Arduino now uses ESP-IDF as a component, so we only check IDF version - framework_version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] - if framework_version >= cv.Version(5, 3, 0): + ver = idf_version() + if ver >= cv.Version(5, 3, 0): return True - if cv.Version(5, 3, 0) > framework_version >= cv.Version(5, 2, 1): + if cv.Version(5, 3, 0) > ver >= cv.Version(5, 2, 1): return True - if cv.Version(5, 2, 0) > framework_version >= cv.Version(5, 1, 4): # noqa: SIM103 + if cv.Version(5, 2, 0) > ver >= cv.Version(5, 1, 4): # noqa: SIM103 return True return False diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index 9b364584ff..86c17ce9ca 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -14,6 +14,7 @@ from esphome.components.esp32 import ( VARIANT_ESP32S3, add_idf_sdkconfig_option, get_esp32_variant, + idf_version, ) import esphome.config_validation as cv from esphome.const import ( @@ -23,8 +24,6 @@ from esphome.const import ( CONF_ID, CONF_MODE, CONF_SPEED, - KEY_CORE, - KEY_FRAMEWORK_VERSION, PLATFORM_ESP32, ) from esphome.core import CORE @@ -202,9 +201,7 @@ async def to_code(config): # ESP32 and ESP32-S2 don't have this constraint. if variant not in (VARIANT_ESP32, VARIANT_ESP32S2): add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) - if config[CONF_MODE] == TYPE_OCTAL and CORE.data[KEY_CORE][ - KEY_FRAMEWORK_VERSION - ] >= cv.Version(5, 4, 0): + if config[CONF_MODE] == TYPE_OCTAL and idf_version() >= cv.Version(5, 4, 0): add_idf_sdkconfig_option( "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True, From 234ca7c9514351e059bb3cea5a1c0d15fea88f5c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:17:32 -1000 Subject: [PATCH 1360/2030] [debug] Fix shared buffer between reset reason and wakeup cause (#14813) --- esphome/components/debug/debug_component.h | 3 ++- esphome/components/debug/debug_esp32.cpp | 9 +++++---- esphome/components/debug/debug_esp8266.cpp | 2 +- esphome/components/debug/debug_host.cpp | 2 +- esphome/components/debug/debug_libretiny.cpp | 2 +- esphome/components/debug/debug_rp2040.cpp | 2 +- esphome/components/debug/debug_zephyr.cpp | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index e4f4bb36eb..3da6b800c6 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -18,6 +18,7 @@ namespace debug { static constexpr size_t DEVICE_INFO_BUFFER_SIZE = 256; static constexpr size_t RESET_REASON_BUFFER_SIZE = 128; +static constexpr size_t WAKEUP_CAUSE_BUFFER_SIZE = 128; // buf_append_printf is now provided by esphome/core/helpers.h @@ -94,7 +95,7 @@ class DebugComponent : public PollingComponent { #endif // USE_TEXT_SENSOR const char *get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer); - const char *get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer); + const char *get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer); uint32_t get_free_heap_(); size_t get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> buffer, size_t pos); void update_platform_(); diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 6898621dd0..c9df4fdf21 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -98,7 +98,7 @@ static const char *const WAKEUP_CAUSES[] = { "BT", }; -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { const char *wake_reason; unsigned reason = esp_sleep_get_wakeup_cause(); if (reason < sizeof(WAKEUP_CAUSES) / sizeof(WAKEUP_CAUSES[0])) { @@ -196,9 +196,10 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> uint32_t cpu_freq_mhz = arch_get_cpu_freq_hz() / 1000000; pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); - char reason_buffer[RESET_REASON_BUFFER_SIZE]; - const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); - const char *wakeup_cause = get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); + char reset_buffer[RESET_REASON_BUFFER_SIZE]; + char wakeup_buffer[WAKEUP_CAUSE_BUFFER_SIZE]; + const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reset_buffer)); + const char *wakeup_cause = get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE>(wakeup_buffer)); uint8_t mac[6]; get_mac_address_raw(mac); diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 4df4aaa851..0519ab72fe 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -91,7 +91,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buffer.data(); } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { // ESP8266 doesn't have detailed wakeup cause like ESP32 return ""; } diff --git a/esphome/components/debug/debug_host.cpp b/esphome/components/debug/debug_host.cpp index 2fa88f0909..0dfab86e4c 100644 --- a/esphome/components/debug/debug_host.cpp +++ b/esphome/components/debug/debug_host.cpp @@ -7,7 +7,7 @@ namespace debug { const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return INT_MAX; } diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index 39269d6f2f..1d458c602a 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -12,7 +12,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return lt_get_reboot_reason_name(lt_get_reboot_reason()); } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index 8dc84a2673..73f08492c8 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -67,7 +67,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buf; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return ::rp2040.getFreeHeap(); } diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index bd6432e949..bf87b7ae3d 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -53,7 +53,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buf; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { // Zephyr doesn't have detailed wakeup cause like ESP32 return ""; } From cc4c13930f7ad862c17dbbd630169f09a5e9af1e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:17:43 -1000 Subject: [PATCH 1361/2030] [hmac_sha256] Migrate to PSA Crypto MAC API for ESP-IDF 6.0 (#14814) --- .../components/hmac_sha256/hmac_sha256.cpp | 52 ++++++++++++++++++- esphome/components/hmac_sha256/hmac_sha256.h | 21 +++++++- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/esphome/components/hmac_sha256/hmac_sha256.cpp b/esphome/components/hmac_sha256/hmac_sha256.cpp index 2146e961bc..c113cb48a6 100644 --- a/esphome/components/hmac_sha256/hmac_sha256.cpp +++ b/esphome/components/hmac_sha256/hmac_sha256.cpp @@ -7,7 +7,55 @@ namespace esphome::hmac_sha256 { constexpr size_t SHA256_DIGEST_SIZE = 32; -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_HMAC_SHA256_PSA) + +// ESP-IDF 6.0 ships mbedtls 4.0 which removed the legacy mbedtls_md HMAC API. +// Use the PSA Crypto MAC API instead. + +HmacSHA256::~HmacSHA256() { + psa_mac_abort(&this->op_); + psa_destroy_key(this->key_id_); +} + +void HmacSHA256::init(const uint8_t *key, size_t len) { + psa_mac_abort(&this->op_); + psa_destroy_key(this->key_id_); + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE); + psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_256)); + psa_import_key(&attributes, key, len, &this->key_id_); + + this->op_ = PSA_MAC_OPERATION_INIT; + psa_mac_sign_setup(&this->op_, this->key_id_, PSA_ALG_HMAC(PSA_ALG_SHA_256)); +} + +void HmacSHA256::add(const uint8_t *data, size_t len) { psa_mac_update(&this->op_, data, len); } + +void HmacSHA256::calculate() { + size_t mac_length; + psa_mac_sign_finish(&this->op_, this->digest_, sizeof(this->digest_), &mac_length); +} + +void HmacSHA256::get_bytes(uint8_t *output) { memcpy(output, this->digest_, SHA256_DIGEST_SIZE); } + +void HmacSHA256::get_hex(char *output) { + format_hex_to(output, SHA256_DIGEST_SIZE * 2 + 1, this->digest_, SHA256_DIGEST_SIZE); +} + +bool HmacSHA256::equals_bytes(const uint8_t *expected) { + return memcmp(this->digest_, expected, SHA256_DIGEST_SIZE) == 0; +} + +bool HmacSHA256::equals_hex(const char *expected) { + char hex_output[SHA256_DIGEST_SIZE * 2 + 1]; + this->get_hex(hex_output); + hex_output[SHA256_DIGEST_SIZE * 2] = '\0'; + return strncmp(hex_output, expected, SHA256_DIGEST_SIZE * 2) == 0; +} + +#elif defined(USE_HMAC_SHA256_MBEDTLS) HmacSHA256::~HmacSHA256() { mbedtls_md_free(&this->ctx_); } @@ -93,7 +141,7 @@ bool HmacSHA256::equals_bytes(const uint8_t *expected) { return this->ohash_.equ bool HmacSHA256::equals_hex(const char *expected) { return this->ohash_.equals_hex(expected); } -#endif // USE_ESP32 || USE_LIBRETINY +#endif // USE_HMAC_SHA256_PSA / USE_HMAC_SHA256_MBEDTLS } // namespace esphome::hmac_sha256 #endif diff --git a/esphome/components/hmac_sha256/hmac_sha256.h b/esphome/components/hmac_sha256/hmac_sha256.h index 85622cac46..22129b1182 100644 --- a/esphome/components/hmac_sha256/hmac_sha256.h +++ b/esphome/components/hmac_sha256/hmac_sha256.h @@ -5,7 +5,19 @@ #include <string> -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_ESP32) +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +// mbedtls 4.0 (IDF 6.0) removed the legacy mbedtls_md HMAC API. +// Use the PSA Crypto MAC API instead. +#define USE_HMAC_SHA256_PSA +#include <psa/crypto.h> +#else +#define USE_HMAC_SHA256_MBEDTLS +#include "mbedtls/md.h" +#endif +#elif defined(USE_LIBRETINY) +#define USE_HMAC_SHA256_MBEDTLS #include "mbedtls/md.h" #else #include "esphome/components/sha256/sha256.h" @@ -45,7 +57,12 @@ class HmacSHA256 { bool equals_hex(const char *expected); protected: -#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#if defined(USE_HMAC_SHA256_PSA) + static constexpr size_t SHA256_DIGEST_SIZE = 32; + psa_mac_operation_t op_ = PSA_MAC_OPERATION_INIT; + mbedtls_svc_key_id_t key_id_ = MBEDTLS_SVC_KEY_ID_INIT; + uint8_t digest_[SHA256_DIGEST_SIZE]{}; +#elif defined(USE_HMAC_SHA256_MBEDTLS) static constexpr size_t SHA256_DIGEST_SIZE = 32; mbedtls_md_context_t ctx_{}; uint8_t digest_[SHA256_DIGEST_SIZE]{}; From 0edc0fd9c885da0ecc5184a80bae878c02777041 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:17:56 -1000 Subject: [PATCH 1362/2030] [esp32_ble_tracker] Migrate to PSA Crypto API for ESP-IDF 6.0 (#14811) --- .../esp32_ble_tracker/esp32_ble_tracker.cpp | 44 ++++++++++++++++--- .../esp32_ble_tracker/esp32_ble_tracker.h | 7 +++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 5a43cf7e49..6dce70f839 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -27,8 +27,14 @@ #include <esp_coexist.h> #endif +#ifdef USE_ESP32_BLE_DEVICE +#ifdef USE_BLE_TRACKER_PSA_AES +#include <psa/crypto.h> +#else #define MBEDTLS_AES_ALT #include <aes_alt.h> +#endif +#endif // USE_ESP32_BLE_DEVICE // bt_trace.h #undef TAG @@ -738,23 +744,48 @@ void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) { } bool ESPBTDevice::resolve_irk(const uint8_t *irk) const { - uint8_t ecb_key[16]; - uint8_t ecb_plaintext[16]; - uint8_t ecb_ciphertext[16]; + static constexpr size_t AES_BLOCK_SIZE = 16; + static constexpr size_t AES_KEY_BITS = 128; + + uint8_t ecb_key[AES_BLOCK_SIZE]; + uint8_t ecb_plaintext[AES_BLOCK_SIZE]; + uint8_t ecb_ciphertext[AES_BLOCK_SIZE]; uint64_t addr64 = esp32_ble::ble_addr_to_uint64(this->address_); - memcpy(&ecb_key, irk, 16); - memset(&ecb_plaintext, 0, 16); + memcpy(&ecb_key, irk, AES_BLOCK_SIZE); + memset(&ecb_plaintext, 0, AES_BLOCK_SIZE); ecb_plaintext[13] = (addr64 >> 40) & 0xff; ecb_plaintext[14] = (addr64 >> 32) & 0xff; ecb_plaintext[15] = (addr64 >> 24) & 0xff; +#ifdef USE_BLE_TRACKER_PSA_AES + // Use PSA Crypto API (mbedtls 4.0 / IDF 6.0+) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, AES_KEY_BITS); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING); + + mbedtls_svc_key_id_t key_id; + if (psa_import_key(&attributes, ecb_key, AES_BLOCK_SIZE, &key_id) != PSA_SUCCESS) { + return false; + } + + size_t output_length; + psa_status_t status = psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, ecb_plaintext, AES_BLOCK_SIZE, + ecb_ciphertext, AES_BLOCK_SIZE, &output_length); + psa_destroy_key(key_id); + if (status != PSA_SUCCESS || output_length != AES_BLOCK_SIZE) { + return false; + } +#else + // Use legacy mbedtls AES API (IDF < 6.0) mbedtls_aes_context ctx = {0, 0, {0}}; mbedtls_aes_init(&ctx); - if (mbedtls_aes_setkey_enc(&ctx, ecb_key, 128) != 0) { + if (mbedtls_aes_setkey_enc(&ctx, ecb_key, AES_KEY_BITS) != 0) { mbedtls_aes_free(&ctx); return false; } @@ -765,6 +796,7 @@ bool ESPBTDevice::resolve_irk(const uint8_t *irk) const { } mbedtls_aes_free(&ctx); +#endif return ecb_ciphertext[15] == (addr64 & 0xff) && ecb_ciphertext[14] == ((addr64 >> 8) & 0xff) && ecb_ciphertext[13] == ((addr64 >> 16) & 0xff); diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 7f1c2b0f7c..f50ed107b6 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -12,6 +12,13 @@ #ifdef USE_ESP32 +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +// mbedtls 4.0 (IDF 6.0) removed the legacy mbedtls AES API. +// Use the PSA Crypto API instead. +#define USE_BLE_TRACKER_PSA_AES +#endif + #include <esp_bt_defs.h> #include <esp_gap_ble_api.h> #include <esp_gattc_api.h> From efc508a82bf4edb19196761ee57cc388ec78d3b6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:18:40 -1000 Subject: [PATCH 1363/2030] [dlms_meter] Migrate GCM to PSA AEAD API for ESP-IDF 6.0 (#14817) --- esphome/components/dlms_meter/dlms_meter.cpp | 35 ++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/esphome/components/dlms_meter/dlms_meter.cpp b/esphome/components/dlms_meter/dlms_meter.cpp index bd2150e8dd..052a0f4d01 100644 --- a/esphome/components/dlms_meter/dlms_meter.cpp +++ b/esphome/components/dlms_meter/dlms_meter.cpp @@ -3,9 +3,14 @@ #if defined(USE_ESP8266_FRAMEWORK_ARDUINO) #include <bearssl/bearssl.h> #elif defined(USE_ESP32) +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#include <psa/crypto.h> +#else #include "mbedtls/esp_config.h" #include "mbedtls/gcm.h" #endif +#endif namespace esphome::dlms_meter { @@ -240,6 +245,35 @@ bool DlmsMeterComponent::decrypt_(std::vector<uint8_t> &mbus_payload, uint16_t m br_gcm_flip(&gcm_ctx); br_gcm_run(&gcm_ctx, 0, payload_ptr, message_length); #elif defined(USE_ESP32) +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // PSA Crypto multipart AEAD (no tag verification, matching legacy behavior) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, this->decryption_key_.size() * 8); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_GCM); + + mbedtls_svc_key_id_t key_id; + bool decrypt_failed = true; + if (psa_import_key(&attributes, this->decryption_key_.data(), this->decryption_key_.size(), &key_id) == PSA_SUCCESS) { + psa_aead_operation_t op = PSA_AEAD_OPERATION_INIT; + if (psa_aead_decrypt_setup(&op, key_id, PSA_ALG_GCM) == PSA_SUCCESS && + psa_aead_set_nonce(&op, iv, sizeof(iv)) == PSA_SUCCESS) { + size_t outlen = 0; + if (psa_aead_update(&op, payload_ptr, message_length, payload_ptr, message_length, &outlen) == PSA_SUCCESS && + outlen == message_length) { + decrypt_failed = false; + } + } + psa_aead_abort(&op); + psa_destroy_key(key_id); + } + if (decrypt_failed) { + ESP_LOGE(TAG, "Decryption failed"); + this->receive_buffer_.clear(); + return false; + } +#else size_t outlen = 0; mbedtls_gcm_context gcm_ctx; mbedtls_gcm_init(&gcm_ctx); @@ -252,6 +286,7 @@ bool DlmsMeterComponent::decrypt_(std::vector<uint8_t> &mbus_payload, uint16_t m this->receive_buffer_.clear(); return false; } +#endif #else #error "Invalid Platform" #endif From d7c42bc9ec72f02ca802f75152bb869734e30d05 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:38:51 -1000 Subject: [PATCH 1364/2030] [debug] Fix ESP-IDF 6.0 compatibility for wakeup cause API (#14812) --- esphome/components/debug/debug_esp32.cpp | 85 ++++++++++++++++++------ 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index c9df4fdf21..aa379599c6 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -5,6 +5,7 @@ #include "esphome/core/log.h" #include "esphome/core/hal.h" #include <esp_sleep.h> +#include <esp_idf_version.h> #include <esp_heap_caps.h> #include <esp_system.h> @@ -82,32 +83,74 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buf; } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) static const char *const WAKEUP_CAUSES[] = { - "undefined", - "undefined", - "external signal using RTC_IO", - "external signal using RTC_CNTL", - "timer", - "touchpad", - "ULP program", - "GPIO", - "UART", - "WIFI", - "COCPU int", - "COCPU crash", - "BT", + "undefined", // ESP_SLEEP_WAKEUP_UNDEFINED (0) + "undefined", // ESP_SLEEP_WAKEUP_ALL (1) + "external signal using RTC_IO", // ESP_SLEEP_WAKEUP_EXT0 (2) + "external signal using RTC_CNTL", // ESP_SLEEP_WAKEUP_EXT1 (3) + "timer", // ESP_SLEEP_WAKEUP_TIMER (4) + "touchpad", // ESP_SLEEP_WAKEUP_TOUCHPAD (5) + "ULP program", // ESP_SLEEP_WAKEUP_ULP (6) + "GPIO", // ESP_SLEEP_WAKEUP_GPIO (7) + "UART", // ESP_SLEEP_WAKEUP_UART (8) + "UART1", // ESP_SLEEP_WAKEUP_UART1 (9) + "UART2", // ESP_SLEEP_WAKEUP_UART2 (10) + "WIFI", // ESP_SLEEP_WAKEUP_WIFI (11) + "COCPU int", // ESP_SLEEP_WAKEUP_COCPU (12) + "COCPU crash", // ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG (13) + "BT", // ESP_SLEEP_WAKEUP_BT (14) + "VAD", // ESP_SLEEP_WAKEUP_VAD (15) + "VBAT under voltage", // ESP_SLEEP_WAKEUP_VBAT_UNDER_VOLT (16) }; +#else +static const char *const WAKEUP_CAUSES[] = { + "undefined", // ESP_SLEEP_WAKEUP_UNDEFINED (0) + "undefined", // ESP_SLEEP_WAKEUP_ALL (1) + "external signal using RTC_IO", // ESP_SLEEP_WAKEUP_EXT0 (2) + "external signal using RTC_CNTL", // ESP_SLEEP_WAKEUP_EXT1 (3) + "timer", // ESP_SLEEP_WAKEUP_TIMER (4) + "touchpad", // ESP_SLEEP_WAKEUP_TOUCHPAD (5) + "ULP program", // ESP_SLEEP_WAKEUP_ULP (6) + "GPIO", // ESP_SLEEP_WAKEUP_GPIO (7) + "UART", // ESP_SLEEP_WAKEUP_UART (8) + "WIFI", // ESP_SLEEP_WAKEUP_WIFI (9) + "COCPU int", // ESP_SLEEP_WAKEUP_COCPU (10) + "COCPU crash", // ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG (11) + "BT", // ESP_SLEEP_WAKEUP_BT (12) +}; +#endif const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { - const char *wake_reason; - unsigned reason = esp_sleep_get_wakeup_cause(); - if (reason < sizeof(WAKEUP_CAUSES) / sizeof(WAKEUP_CAUSES[0])) { - wake_reason = WAKEUP_CAUSES[reason]; - } else { - wake_reason = "unknown source"; + static constexpr auto NUM_CAUSES = sizeof(WAKEUP_CAUSES) / sizeof(WAKEUP_CAUSES[0]); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // IDF 6.0+ returns a bitmap of all wakeup sources + uint32_t causes = esp_sleep_get_wakeup_causes(); + if (causes == 0) { + return WAKEUP_CAUSES[0]; // "undefined" } - // Return the static string directly - no need to copy to buffer - return wake_reason; + char *p = buffer.data(); + char *end = p + buffer.size(); + *p = '\0'; + const char *sep = ""; + for (unsigned i = 0; i < NUM_CAUSES && p < end; i++) { + if (causes & (1U << i)) { + size_t needed = strlen(sep) + strlen(WAKEUP_CAUSES[i]); + if (p + needed >= end) { + break; + } + p += snprintf(p, end - p, "%s%s", sep, WAKEUP_CAUSES[i]); + sep = ", "; + } + } + return buffer.data(); +#else + unsigned reason = esp_sleep_get_wakeup_cause(); + if (reason < NUM_CAUSES) { + return WAKEUP_CAUSES[reason]; + } + return "unknown source"; +#endif } void DebugComponent::log_partition_info_() { From d37f8876d73a637045b3e65f4aca525572a5aab1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:39:07 -1000 Subject: [PATCH 1365/2030] [bthome_mithermometer][xiaomi_ble] Migrate CCM to PSA AEAD API for ESP-IDF 6.0 (#14816) --- .../bthome_mithermometer/bthome_ble.cpp | 37 ++++++++++++++++++ esphome/components/xiaomi_ble/xiaomi_ble.cpp | 39 +++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/esphome/components/bthome_mithermometer/bthome_ble.cpp b/esphome/components/bthome_mithermometer/bthome_ble.cpp index 2b73d8735c..32278dbfbd 100644 --- a/esphome/components/bthome_mithermometer/bthome_ble.cpp +++ b/esphome/components/bthome_mithermometer/bthome_ble.cpp @@ -10,7 +10,12 @@ #ifdef USE_ESP32 +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#include <psa/crypto.h> +#else #include "mbedtls/ccm.h" +#endif namespace esphome { namespace bthome_mithermometer { @@ -196,6 +201,37 @@ bool BTHomeMiThermometer::decrypt_bthome_payload_(const std::vector<uint8_t> &da const uint8_t *ciphertext = data.data() + 1; const uint8_t *mic = data.data() + data.size() - BTHOME_MIC_SIZE; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // PSA AEAD expects ciphertext + tag concatenated + // BLE advertisement max payload is 31 bytes, so this is always sufficient + static constexpr size_t MAX_CT_WITH_TAG = 32; + uint8_t ct_with_tag[MAX_CT_WITH_TAG]; + size_t ct_with_tag_size = ciphertext_size + BTHOME_MIC_SIZE; + memcpy(ct_with_tag, ciphertext, ciphertext_size); + memcpy(ct_with_tag + ciphertext_size, mic, BTHOME_MIC_SIZE); + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, BTHOME_BINDKEY_SIZE * 8); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, BTHOME_MIC_SIZE)); + + mbedtls_svc_key_id_t key_id; + if (psa_import_key(&attributes, this->bindkey_, BTHOME_BINDKEY_SIZE, &key_id) != PSA_SUCCESS) { + ESP_LOGVV(TAG, "psa_import_key() failed."); + return false; + } + + size_t plaintext_length; + psa_status_t status = psa_aead_decrypt(key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, BTHOME_MIC_SIZE), + nonce.data(), nonce.size(), nullptr, 0, ct_with_tag, ct_with_tag_size, + payload.data(), ciphertext_size, &plaintext_length); + psa_destroy_key(key_id); + if (status != PSA_SUCCESS || plaintext_length != ciphertext_size) { + ESP_LOGVV(TAG, "BTHome decryption failed."); + return false; + } +#else mbedtls_ccm_context ctx; mbedtls_ccm_init(&ctx); @@ -213,6 +249,7 @@ bool BTHomeMiThermometer::decrypt_bthome_payload_(const std::vector<uint8_t> &da ESP_LOGVV(TAG, "BTHome decryption failed (ret=%d).", ret); return false; } +#endif return true; } diff --git a/esphome/components/xiaomi_ble/xiaomi_ble.cpp b/esphome/components/xiaomi_ble/xiaomi_ble.cpp index 97a660f0e3..2c1611d0c7 100644 --- a/esphome/components/xiaomi_ble/xiaomi_ble.cpp +++ b/esphome/components/xiaomi_ble/xiaomi_ble.cpp @@ -5,7 +5,12 @@ #ifdef USE_ESP32 #include <vector> +#include <esp_idf_version.h> +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#include <psa/crypto.h> +#else #include "mbedtls/ccm.h" +#endif namespace esphome { namespace xiaomi_ble { @@ -314,6 +319,32 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c memcpy(vector.iv + 6, v + 2, 3); // sensor type (2) + packet id (1) memcpy(vector.iv + 9, v + raw.size() - 7, 3); // payload counter +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + // PSA AEAD expects ciphertext + tag concatenated + uint8_t ct_with_tag[sizeof(vector.ciphertext) + sizeof(vector.tag)]; + memcpy(ct_with_tag, vector.ciphertext, vector.datasize); + memcpy(ct_with_tag + vector.datasize, vector.tag, vector.tagsize); + size_t ct_with_tag_size = vector.datasize + vector.tagsize; + + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&attributes, PSA_KEY_TYPE_AES); + psa_set_key_bits(&attributes, vector.keysize * 8); + psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT); + psa_set_key_algorithm(&attributes, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, vector.tagsize)); + + mbedtls_svc_key_id_t key_id; + if (psa_import_key(&attributes, vector.key, vector.keysize, &key_id) != PSA_SUCCESS) { + ESP_LOGVV(TAG, "decrypt_xiaomi_payload(): psa_import_key() failed."); + return false; + } + + size_t plaintext_length; + psa_status_t status = psa_aead_decrypt(key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, vector.tagsize), + vector.iv, vector.ivsize, vector.authdata, vector.authsize, ct_with_tag, + ct_with_tag_size, vector.plaintext, vector.datasize, &plaintext_length); + psa_destroy_key(key_id); + bool decrypt_ok = (status == PSA_SUCCESS && plaintext_length == vector.datasize); +#else mbedtls_ccm_context ctx; mbedtls_ccm_init(&ctx); @@ -326,7 +357,11 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c ret = mbedtls_ccm_auth_decrypt(&ctx, vector.datasize, vector.iv, vector.ivsize, vector.authdata, vector.authsize, vector.ciphertext, vector.plaintext, vector.tag, vector.tagsize); - if (ret) { + mbedtls_ccm_free(&ctx); + bool decrypt_ok = (ret == 0); +#endif + + if (!decrypt_ok) { uint8_t mac_address[6] = {0}; memcpy(mac_address, mac_reverse + 5, 1); memcpy(mac_address + 1, mac_reverse + 4, 1); @@ -346,7 +381,6 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c ESP_LOGVV(TAG, " Iv : %s", format_hex_pretty_to(hex_buf, vector.iv, vector.ivsize)); ESP_LOGVV(TAG, " Cipher : %s", format_hex_pretty_to(hex_buf, vector.ciphertext, vector.datasize)); ESP_LOGVV(TAG, " Tag : %s", format_hex_pretty_to(hex_buf, vector.tag, vector.tagsize)); - mbedtls_ccm_free(&ctx); return false; } @@ -367,7 +401,6 @@ bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, c ESP_LOGVV(TAG, " Plaintext : %s, Packet : %d", format_hex_pretty_to(hex_buf, raw.data() + cipher_pos, vector.datasize), static_cast<int>(raw[4])); - mbedtls_ccm_free(&ctx); return true; } From fe9f19d9ed078db9eb3d82e2fb698c90dc9e6043 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Mar 2026 09:30:12 -0400 Subject: [PATCH 1366/2030] [mqtt] Fix ESP-IDF 6.0 compatibility for external MQTT component (#14822) --- esphome/components/mqtt/__init__.py | 8 +++++++- esphome/idf_component.yml | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index d110d7c160..817f99375e 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -3,7 +3,9 @@ from esphome.automation import Condition import esphome.codegen as cg from esphome.components import logger, socket from esphome.components.esp32 import ( + add_idf_component, add_idf_sdkconfig_option, + idf_version, include_builtin_idf_component, ) from esphome.config_helpers import filter_source_files_from_platform @@ -351,7 +353,11 @@ async def to_code(config): if CORE.is_esp32: socket.require_wake_loop_threadsafe() # Re-enable ESP-IDF's mqtt component (excluded by default to save compile time) - include_builtin_idf_component("mqtt") + # IDF 6.0 moved esp-mqtt to an external component + if idf_version() >= cv.Version(6, 0, 0): + add_idf_component(name="espressif/mqtt", ref="1.0.0") + else: + include_builtin_idf_component("mqtt") cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index bb94de7e05..1e2d452919 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -37,5 +37,9 @@ dependencies: version: 0.3.2 rules: - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" + espressif/mqtt: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0" esp32async/asynctcp: version: 3.4.91 From 7f418d969e9bd3de284123fcbae113e5c36a09d6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:57:52 -0400 Subject: [PATCH 1367/2030] [multiple] Fix implicit int-to-gpio_num_t conversions for GCC 15 (#14830) --- esphome/components/ledc/ledc_output.cpp | 3 ++- esphome/components/mipi_rgb/mipi_rgb.cpp | 17 +++++++++-------- .../pulse_counter/pulse_counter_sensor.cpp | 5 +++-- esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp | 13 +++++++------ esphome/components/st7701s/st7701s.cpp | 13 +++++++------ 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index a3d1e4d392..d2f2d72acb 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -3,6 +3,7 @@ #ifdef USE_ESP32 +#include <driver/gpio.h> #include <driver/ledc.h> #include <cinttypes> #include <esp_idf_version.h> @@ -189,7 +190,7 @@ void LEDCOutput::setup() { this->phase_angle_, hpoint); ledc_channel_config_t chan_conf{}; - chan_conf.gpio_num = this->pin_->get_pin(); + chan_conf.gpio_num = static_cast<gpio_num_t>(this->pin_->get_pin()); chan_conf.speed_mode = speed_mode; chan_conf.channel = chan_num; chan_conf.intr_type = LEDC_INTR_DISABLE; diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index ae7c795846..824ff6afe7 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -4,7 +4,8 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esp_lcd_panel_rgb.h" +#include <driver/gpio.h> +#include <esp_lcd_panel_rgb.h> #include <span> namespace esphome { @@ -153,18 +154,18 @@ void MipiRgb::common_setup_() { config.clk_src = LCD_CLK_SRC_PLL160M; size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); for (size_t i = 0; i != data_pin_count; i++) { - config.data_gpio_nums[i] = this->data_pins_[i]->get_pin(); + config.data_gpio_nums[i] = static_cast<gpio_num_t>(this->data_pins_[i]->get_pin()); } config.data_width = data_pin_count; - config.disp_gpio_num = -1; - config.hsync_gpio_num = this->hsync_pin_->get_pin(); - config.vsync_gpio_num = this->vsync_pin_->get_pin(); + config.disp_gpio_num = GPIO_NUM_NC; + config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin()); + config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin()); if (this->de_pin_) { - config.de_gpio_num = this->de_pin_->get_pin(); + config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin()); } else { - config.de_gpio_num = -1; + config.de_gpio_num = GPIO_NUM_NC; } - config.pclk_gpio_num = this->pclk_pin_->get_pin(); + config.pclk_gpio_num = static_cast<gpio_num_t>(this->pclk_pin_->get_pin()); esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_); if (err == ESP_OK) err = esp_lcd_panel_reset(this->handle_); diff --git a/esphome/components/pulse_counter/pulse_counter_sensor.cpp b/esphome/components/pulse_counter/pulse_counter_sensor.cpp index ec00bd024e..5d73bef7da 100644 --- a/esphome/components/pulse_counter/pulse_counter_sensor.cpp +++ b/esphome/components/pulse_counter/pulse_counter_sensor.cpp @@ -2,6 +2,7 @@ #include "esphome/core/log.h" #ifdef HAS_PCNT +#include <driver/gpio.h> #include <esp_private/esp_clk.h> #include <hal/pcnt_ll.h> #endif @@ -76,8 +77,8 @@ bool HwPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) { } pcnt_chan_config_t chan_config = { - .edge_gpio_num = this->pin->get_pin(), - .level_gpio_num = -1, + .edge_gpio_num = static_cast<gpio_num_t>(this->pin->get_pin()), + .level_gpio_num = GPIO_NUM_NC, }; error = pcnt_new_channel(this->pcnt_unit, &chan_config, &this->pcnt_channel); if (error != ESP_OK) { diff --git a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp index 363f4b63b8..d29f6a0bcb 100644 --- a/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp +++ b/esphome/components/rpi_dpi_rgb/rpi_dpi_rgb.cpp @@ -2,6 +2,7 @@ #include "rpi_dpi_rgb.h" #include "esphome/core/gpio.h" #include "esphome/core/log.h" +#include <driver/gpio.h> namespace esphome { namespace rpi_dpi_rgb { @@ -25,14 +26,14 @@ void RpiDpiRgb::setup() { config.clk_src = LCD_CLK_SRC_PLL160M; size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); for (size_t i = 0; i != data_pin_count; i++) { - config.data_gpio_nums[i] = this->data_pins_[i]->get_pin(); + config.data_gpio_nums[i] = static_cast<gpio_num_t>(this->data_pins_[i]->get_pin()); } config.data_width = data_pin_count; - config.disp_gpio_num = -1; - config.hsync_gpio_num = this->hsync_pin_->get_pin(); - config.vsync_gpio_num = this->vsync_pin_->get_pin(); - config.de_gpio_num = this->de_pin_->get_pin(); - config.pclk_gpio_num = this->pclk_pin_->get_pin(); + config.disp_gpio_num = GPIO_NUM_NC; + config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin()); + config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin()); + config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin()); + config.pclk_gpio_num = static_cast<gpio_num_t>(this->pclk_pin_->get_pin()); esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_); if (err != ESP_OK) { ESP_LOGE(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err)); diff --git a/esphome/components/st7701s/st7701s.cpp b/esphome/components/st7701s/st7701s.cpp index ecce4eb4b2..701b6dd79e 100644 --- a/esphome/components/st7701s/st7701s.cpp +++ b/esphome/components/st7701s/st7701s.cpp @@ -2,6 +2,7 @@ #include "st7701s.h" #include "esphome/core/gpio.h" #include "esphome/core/log.h" +#include <driver/gpio.h> namespace esphome { namespace st7701s { @@ -27,14 +28,14 @@ void ST7701S::setup() { config.clk_src = LCD_CLK_SRC_PLL160M; size_t data_pin_count = sizeof(this->data_pins_) / sizeof(this->data_pins_[0]); for (size_t i = 0; i != data_pin_count; i++) { - config.data_gpio_nums[i] = this->data_pins_[i]->get_pin(); + config.data_gpio_nums[i] = static_cast<gpio_num_t>(this->data_pins_[i]->get_pin()); } config.data_width = data_pin_count; - config.disp_gpio_num = -1; - config.hsync_gpio_num = this->hsync_pin_->get_pin(); - config.vsync_gpio_num = this->vsync_pin_->get_pin(); - config.de_gpio_num = this->de_pin_->get_pin(); - config.pclk_gpio_num = this->pclk_pin_->get_pin(); + config.disp_gpio_num = GPIO_NUM_NC; + config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin()); + config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin()); + config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin()); + config.pclk_gpio_num = static_cast<gpio_num_t>(this->pclk_pin_->get_pin()); esp_err_t err = esp_lcd_new_rgb_panel(&config, &this->handle_); if (err != ESP_OK) { esph_log_e(TAG, "lcd_new_rgb_panel failed: %s", esp_err_to_name(err)); From 18a082de30abe7e3e0a525fac10dcf67fb3ef375 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:58:01 -0400 Subject: [PATCH 1368/2030] [ci] Support URL and version extras in generate-esp32-boards.py (#14828) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- script/generate-esp32-boards.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/script/generate-esp32-boards.py b/script/generate-esp32-boards.py index ab4a38ced5..9fa0f652ef 100755 --- a/script/generate-esp32-boards.py +++ b/script/generate-esp32-boards.py @@ -7,17 +7,26 @@ import subprocess import sys import tempfile +from esphome import config_validation as cv from esphome.components.esp32 import PLATFORM_VERSION_LOOKUP from esphome.helpers import write_file_if_changed ver = PLATFORM_VERSION_LOOKUP["recommended"] -version_str = f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}" root = Path(__file__).parent.parent boards_file_path = root / "esphome" / "components" / "esp32" / "boards.py" def get_boards(): with tempfile.TemporaryDirectory() as tempdir: + if isinstance(ver, cv.Version): + branch = f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}" + if ver.extra: + branch += f"-{ver.extra}" + repo = "https://github.com/pioarduino/platform-espressif32" + else: + # URL format: "https://github.com/user/repo.git#branch" + url = str(ver) + repo, branch = url.rsplit("#", 1) if "#" in url else (url, "main") subprocess.run( [ "git", @@ -28,8 +37,8 @@ def get_boards(): "--depth", "1", "--branch", - f"{ver.major}.{ver.minor:02d}.{ver.patch:02d}", - "https://github.com/pioarduino/platform-espressif32", + branch, + repo, tempdir, ], check=True, From 33f9ad9cee4e712d14721966318f99d8d0f63238 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:58:12 -0400 Subject: [PATCH 1369/2030] [esp32] Support non-numeric version extras in IDF version string (#14826) --- esphome/components/esp32/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index eaa9aa163d..18178c83ff 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -612,10 +612,12 @@ def _format_framework_espidf_version( ext = "tar.xz" else: ext = "zip" - # Build version string with dot-separated extra (e.g., "5.5.3.1" not "5.5.3-1") + # Build version string with extra separator based on type: + # numeric extra uses dot (e.g., "5.5.3.1"), string extra uses dash (e.g., "6.0.0-rc1") ver_str = f"{ver.major}.{ver.minor}.{ver.patch}" if ver.extra: - ver_str += f".{ver.extra}" + sep = "." if str(ver.extra).isdigit() else "-" + ver_str += f"{sep}{ver.extra}" if release: return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{ver_str}.{release}/esp-idf-v{ver_str}.{ext}" return f"pioarduino/framework-espidf@https://github.com/pioarduino/esp-idf/releases/download/v{ver_str}/esp-idf-v{ver_str}.{ext}" From 4219d6d3673d8a1e4d8f36ac6ce45b162c898292 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 09:28:19 -1000 Subject: [PATCH 1370/2030] Bump tornado from 6.5.4 to 6.5.5 (#14704) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 3da2d52b44..e634bcb104 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ PyYAML==6.0.3 paho-mqtt==1.6.1 colorama==0.4.6 icmplib==3.0.4 -tornado==6.5.4 +tornado==6.5.5 tzlocal==5.3.1 # from time tzdata>=2021.1 # from time pyserial==3.5 From 2627490a11952d55ef282c5b6b57522e6467123e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:30:44 -0400 Subject: [PATCH 1371/2030] [esp32_hosted] Bump esp_hosted to 2.12.1 (#14708) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32_hosted/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_hosted/__init__.py b/esphome/components/esp32_hosted/__init__.py index 6d49053d6d..a51ae2cd66 100644 --- a/esphome/components/esp32_hosted/__init__.py +++ b/esphome/components/esp32_hosted/__init__.py @@ -105,7 +105,7 @@ async def to_code(config): if framework_ver >= cv.Version(5, 5, 0): esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="1.4.0") esp32.add_idf_component(name="espressif/eppp_link", ref="1.1.4") - esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.0") + esp32.add_idf_component(name="espressif/esp_hosted", ref="2.12.1") else: esp32.add_idf_component(name="espressif/esp_wifi_remote", ref="0.13.0") esp32.add_idf_component(name="espressif/eppp_link", ref="0.2.0") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index acd7f7a479..f7fd3e67bc 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -20,7 +20,7 @@ dependencies: rules: - if: "target in [esp32h2, esp32p4]" espressif/esp_hosted: - version: 2.12.0 + version: 2.12.1 rules: - if: "target in [esp32h2, esp32p4]" zorxx/multipart-parser: From 064bd13ebb6ba91576c7e6c78c23a2986ad5e5d5 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Wed, 11 Mar 2026 19:56:25 -0500 Subject: [PATCH 1372/2030] [ethernet] ESP32-P4 Ethernet compilation fix (#14714) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .../components/ethernet/ethernet_component.cpp | 18 +----------------- .../components/ethernet/ethernet_component.h | 2 ++ esphome/components/ethernet/ethernet_helpers.c | 8 ++++++++ .../components/ethernet/test.esp32-p4-idf.yaml | 1 + 4 files changed, 12 insertions(+), 17 deletions(-) create mode 100644 esphome/components/ethernet/ethernet_helpers.c create mode 100644 tests/components/ethernet/test.esp32-p4-idf.yaml diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index d6b0d40cd9..e0788e1149 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -21,22 +21,6 @@ namespace esphome::ethernet { -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) -// work around IDF compile issue on P4 https://github.com/espressif/esp-idf/pull/15637 -#ifdef USE_ESP32_VARIANT_ESP32P4 -#undef ETH_ESP32_EMAC_DEFAULT_CONFIG -#define ETH_ESP32_EMAC_DEFAULT_CONFIG() \ - { \ - .smi_gpio = {.mdc_num = 31, .mdio_num = 52}, .interface = EMAC_DATA_INTERFACE_RMII, \ - .clock_config = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) 50}}, \ - .dma_burst_len = ETH_DMA_BURST_LEN_32, .intr_priority = 0, \ - .emac_dataif_gpio = \ - {.rmii = {.tx_en_num = 49, .txd0_num = 34, .txd1_num = 35, .crs_dv_num = 28, .rxd0_num = 29, .rxd1_num = 30}}, \ - .clock_config_out_in = {.rmii = {.clock_mode = EMAC_CLK_EXT_IN, .clock_gpio = (emac_rmii_clock_gpio_t) -1}}, \ - } -#endif -#endif - static const char *const TAG = "ethernet"; // PHY register size for hex logging @@ -162,7 +146,7 @@ void EthernetComponent::setup() { phy_config.phy_addr = this->phy_addr_; phy_config.reset_gpio_num = this->power_pin_; - eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG(); + eth_esp32_emac_config_t esp32_emac_config = eth_esp32_emac_default_config(); #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) esp32_emac_config.smi_gpio.mdc_num = this->mdc_pin_; esp32_emac_config.smi_gpio.mdio_num = this->mdio_pin_; diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index d9f05be9de..c464e20b84 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -15,6 +15,8 @@ #include "esp_mac.h" #include "esp_idf_version.h" +extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); + namespace esphome::ethernet { #ifdef USE_ETHERNET_IP_STATE_LISTENERS diff --git a/esphome/components/ethernet/ethernet_helpers.c b/esphome/components/ethernet/ethernet_helpers.c new file mode 100644 index 0000000000..96faccad24 --- /dev/null +++ b/esphome/components/ethernet/ethernet_helpers.c @@ -0,0 +1,8 @@ +#include "esp_eth_mac_esp.h" + +// ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers +// which are valid in C but not in C++. This wrapper allows C++ code to get +// the default config without replicating the macro's contents. +eth_esp32_emac_config_t eth_esp32_emac_default_config(void) { + return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG(); +} diff --git a/tests/components/ethernet/test.esp32-p4-idf.yaml b/tests/components/ethernet/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..e52329d7ea --- /dev/null +++ b/tests/components/ethernet/test.esp32-p4-idf.yaml @@ -0,0 +1 @@ +<<: !include common-ip101.yaml From 2b0c471ed7b08e422fe48fd7153c22cfd8f1a23a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Mar 2026 15:00:20 -1000 Subject: [PATCH 1373/2030] [esp32] Add crash handler to capture and report backtrace across reboots (#14709) --- esphome/components/api/api_connection.h | 6 + esphome/components/api/client.py | 21 ++ esphome/components/esp32/__init__.py | 5 + esphome/components/esp32/core.cpp | 6 + esphome/components/esp32/crash_handler.cpp | 355 +++++++++++++++++++++ esphome/components/esp32/crash_handler.h | 18 ++ esphome/components/logger/logger_esp32.cpp | 4 + esphome/core/defines.h | 1 + esphome/platformio_api.py | 7 + tests/unit_tests/test_platformio_api.py | 28 ++ 10 files changed, 451 insertions(+) create mode 100644 esphome/components/esp32/crash_handler.cpp create mode 100644 esphome/components/esp32/crash_handler.h diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 3356511684..60cc3e91b1 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -14,6 +14,9 @@ #include "api_server.h" #include "esphome/core/application.h" #include "esphome/core/component.h" +#ifdef USE_ESP32_CRASH_HANDLER +#include "esphome/components/esp32/crash_handler.h" +#endif #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -235,6 +238,9 @@ class APIConnection final : public APIServerConnectionBase { this->flags_.log_subscription = msg.level; if (msg.dump_config) App.schedule_dump_config(); +#ifdef USE_ESP32_CRASH_HANDLER + esp32::crash_handler_log(); +#endif } #ifdef USE_API_HOMEASSISTANT_SERVICES void on_subscribe_homeassistant_services_request() override { this->flags_.service_call_subscription = true; } diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index 200d0938bd..0e71ad8fcb 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -2,6 +2,7 @@ from __future__ import annotations import asyncio from datetime import datetime +import importlib import logging from typing import TYPE_CHECKING, Any import warnings @@ -18,6 +19,7 @@ import contextlib from esphome.const import CONF_KEY, CONF_PORT, __version__ from esphome.core import CORE +from esphome.platformio_api import process_stacktrace from . import CONF_ENCRYPTION @@ -55,9 +57,19 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: addresses=addresses, # Pass all addresses for automatic retry ) dashboard = CORE.dashboard + backtrace_state = False + + # Try platform-specific stacktrace handler first, fall back to generic + platform_process_stacktrace = None + try: + module = importlib.import_module("esphome.components." + CORE.target_platform) + platform_process_stacktrace = getattr(module, "process_stacktrace") + except (AttributeError, ImportError): + pass def on_log(msg: SubscribeLogsResponse) -> None: """Handle a new log message.""" + nonlocal backtrace_state time_ = datetime.now() message: bytes = msg.message text = message.decode("utf8", "backslashreplace") @@ -67,6 +79,15 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: ) for parsed_msg in parse_log_message(text, timestamp): print(parsed_msg.replace("\033", "\\033") if dashboard else parsed_msg) + for raw_line in text.splitlines(): + if platform_process_stacktrace: + backtrace_state = platform_process_stacktrace( + config, raw_line, backtrace_state + ) + else: + backtrace_state = process_stacktrace( + config, raw_line, backtrace_state=backtrace_state + ) stop = await async_run(cli, on_log, name=name) try: diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 52e70501dc..475de6aa3e 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1442,6 +1442,11 @@ async def to_code(config): cg.add_build_flag("-DUSE_ESP32") cg.add_define("USE_NATIVE_64BIT_TIME") cg.add_build_flag("-Wl,-z,noexecstack") + # Arduino already wraps esp_panic_handler for its own backtrace handler, + # so only add our wrap when using ESP-IDF framework to avoid linker conflicts. + if conf[CONF_TYPE] == FRAMEWORK_ESP_IDF: + cg.add_build_flag("-Wl,--wrap=esp_panic_handler") + cg.add_define("USE_ESP32_CRASH_HANDLER") cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) variant = config[CONF_VARIANT] cg.add_build_flag(f"-DUSE_ESP32_VARIANT_{variant}") diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 46c000562e..cba25bca2b 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -1,6 +1,7 @@ #ifdef USE_ESP32 #include "esphome/core/defines.h" +#include "crash_handler.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -36,6 +37,11 @@ void arch_restart() { } void arch_init() { +#ifdef USE_ESP32_CRASH_HANDLER + // Read crash data from previous boot before anything else + esp32::crash_handler_read_and_clear(); +#endif + // Enable the task watchdog only on the loop task (from which we're currently running) esp_task_wdt_add(nullptr); diff --git a/esphome/components/esp32/crash_handler.cpp b/esphome/components/esp32/crash_handler.cpp new file mode 100644 index 0000000000..ecf30d7878 --- /dev/null +++ b/esphome/components/esp32/crash_handler.cpp @@ -0,0 +1,355 @@ +#ifdef USE_ESP32 + +#include "esphome/core/defines.h" +#ifdef USE_ESP32_CRASH_HANDLER + +#include "crash_handler.h" +#include "esphome/core/log.h" + +#include <cinttypes> +#include <cstring> +#include <esp_attr.h> +#include <esp_private/panic_internal.h> +#include <soc/soc.h> + +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#include <esp_cpu_utils.h> +#include <esp_debug_helpers.h> +#include <xtensa_context.h> +#elif CONFIG_IDF_TARGET_ARCH_RISCV +#include <riscv/rvruntime-frames.h> +#endif + +static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF; +static constexpr size_t MAX_BACKTRACE = 16; + +// Check if an address looks like code (flash-mapped or IRAM). +// Must be safe to call from panic context (no flash access needed). +static inline bool IRAM_ATTR is_code_addr(uint32_t addr) { + return (addr >= SOC_IROM_LOW && addr < SOC_IROM_HIGH) || (addr >= SOC_IRAM_LOW && addr < SOC_IRAM_HIGH); +} + +#if CONFIG_IDF_TARGET_ARCH_RISCV +// Check if a code address is a real return address by verifying the preceding +// instruction is a JAL or JALR with rd=ra (x1). Called at log time (not during +// panic) so flash cache is available and both IRAM and IROM are safely readable. +static inline bool is_return_addr(uint32_t addr) { + if (!is_code_addr(addr) || addr < 4) + return false; + // A return address on the stack points to the instruction after a call. + // Check for 4-byte JAL/JALR call instruction before this address. + // Use memcpy for alignment safety — RISC-V C extension means code addresses + // are only 2-byte aligned, so addr-4 may not be 4-byte aligned. + uint32_t inst; + memcpy(&inst, (const void *) (addr - 4), sizeof(inst)); + // RISC-V instruction encoding: bits [6:0] = opcode, bits [11:7] = rd + uint32_t opcode = inst & 0x7f; // Extract 7-bit opcode + uint32_t rd = inst & 0xf80; // Extract rd field (bits 11:7) + // Match JAL (0x6f) or JALR (0x67) with rd=ra (x1, encoded as 0x80 = 1<<7) + if ((opcode == 0x6f || opcode == 0x67) && rd == 0x80) + return true; + // Check for 2-byte compressed c.jalr before this address (C extension). + // c.jalr saves to ra implicitly: funct4=1001, rs1!=0, rs2=0, op=10 + if (addr >= 2) { + uint16_t c_inst = *(uint16_t *) (addr - 2); + if ((c_inst & 0xf07f) == 0x9002 && (c_inst & 0x0f80) != 0) + return true; + } + return false; +} +#endif + +// Raw crash data written by the panic handler wrapper. +// Lives in .noinit so it survives software reset but contains garbage after power cycle. +// Validated by magic marker. Static linkage since it's only used within this file. +// Version field is first so future firmware can always identify the struct layout. +// Magic is second to validate the data. Remaining fields can change between versions. +// Version is uint32_t because it would be padded to 4 bytes anyway before the next +// uint32_t field, so we use the full width rather than wasting 3 bytes of padding. +static constexpr uint32_t CRASH_DATA_VERSION = 1; +struct RawCrashData { + uint32_t version; + uint32_t magic; + uint32_t pc; + uint8_t backtrace_count; + uint8_t reg_frame_count; // Number of entries from registers (not stack-scanned) + uint8_t exception; // panic_exception_t enum (FAULT/ABORT/IWDT/TWDT/DEBUG) + uint8_t pseudo_excause; // Whether cause is a pseudo exception (Xtensa SoC-level panic) + uint32_t backtrace[MAX_BACKTRACE]; + uint32_t cause; // Architecture-specific: exccause (Xtensa) or mcause (RISC-V) +}; +static RawCrashData __attribute__((section(".noinit"))) +s_raw_crash_data; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +// Whether crash data was found and validated this boot. +static bool s_crash_data_valid = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +namespace esphome::esp32 { + +static const char *const TAG = "esp32.crash"; + +void crash_handler_read_and_clear() { + if (s_raw_crash_data.magic == CRASH_MAGIC && s_raw_crash_data.version == CRASH_DATA_VERSION) { + s_crash_data_valid = true; + // Clamp counts to prevent out-of-bounds reads from corrupt .noinit data + if (s_raw_crash_data.backtrace_count > MAX_BACKTRACE) + s_raw_crash_data.backtrace_count = MAX_BACKTRACE; + if (s_raw_crash_data.reg_frame_count > s_raw_crash_data.backtrace_count) + s_raw_crash_data.reg_frame_count = s_raw_crash_data.backtrace_count; + if (s_raw_crash_data.exception > 4) // panic_exception_t max value + s_raw_crash_data.exception = 4; // Default to PANIC_EXCEPTION_FAULT + if (s_raw_crash_data.pseudo_excause > 1) + s_raw_crash_data.pseudo_excause = 0; + } + // Clear magic regardless so we don't re-report on next normal reboot + s_raw_crash_data.magic = 0; +} + +bool crash_handler_has_data() { return s_crash_data_valid; } + +// Look up the exception cause as a human-readable string. +// Tables mirror ESP-IDF's panic_arch_fill_info() which uses local static arrays +// not exposed via any public API. +static const char *get_exception_reason() { +#if CONFIG_IDF_TARGET_ARCH_XTENSA + if (s_raw_crash_data.pseudo_excause) { + // SoC-level panic: watchdog, cache error, etc. + // Keep in sync with ESP-IDF's PANIC_RSN_* defines + static const char *const PSEUDO_REASON[] = { + "Unknown reason", // 0 + "Unhandled debug exception", // 1 + "Double exception", // 2 + "Unhandled kernel exception", // 3 + "Coprocessor exception", // 4 + "Interrupt wdt timeout on CPU0", // 5 + "Interrupt wdt timeout on CPU1", // 6 + "Cache error", // 7 + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(PSEUDO_REASON) / sizeof(PSEUDO_REASON[0])) + return PSEUDO_REASON[cause]; + return PSEUDO_REASON[0]; + } + // Real Xtensa exception + static const char *const REASON[] = { + "IllegalInstruction", + "Syscall", + "InstructionFetchError", + "LoadStoreError", + "Level1Interrupt", + "Alloca", + "IntegerDivideByZero", + "PCValue", + "Privileged", + "LoadStoreAlignment", + nullptr, + nullptr, + "InstrPDAddrError", + "LoadStorePIFDataError", + "InstrPIFAddrError", + "LoadStorePIFAddrError", + "InstTLBMiss", + "InstTLBMultiHit", + "InstFetchPrivilege", + nullptr, + "InstrFetchProhibited", + nullptr, + nullptr, + nullptr, + "LoadStoreTLBMiss", + "LoadStoreTLBMultihit", + "LoadStorePrivilege", + nullptr, + "LoadProhibited", + "StoreProhibited", + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(REASON) / sizeof(REASON[0]) && REASON[cause] != nullptr) + return REASON[cause]; +#elif CONFIG_IDF_TARGET_ARCH_RISCV + // For SoC-level panics (watchdog, cache error), mcause holds IDF-internal + // interrupt numbers, not standard RISC-V cause codes. The exception type + // field already identifies these, so just return null to use the type name. + if (s_raw_crash_data.pseudo_excause) + return nullptr; + static const char *const REASON[] = { + "Instruction address misaligned", + "Instruction access fault", + "Illegal instruction", + "Breakpoint", + "Load address misaligned", + "Load access fault", + "Store address misaligned", + "Store access fault", + "Environment call from U-mode", + "Environment call from S-mode", + nullptr, + "Environment call from M-mode", + "Instruction page fault", + "Load page fault", + nullptr, + "Store page fault", + }; + uint32_t cause = s_raw_crash_data.cause; + if (cause < sizeof(REASON) / sizeof(REASON[0]) && REASON[cause] != nullptr) + return REASON[cause]; +#endif + return "Unknown"; +} + +// Exception type names matching panic_exception_t enum +static const char *get_exception_type() { + static const char *const TYPES[] = { + "Debug exception", // PANIC_EXCEPTION_DEBUG + "Interrupt wdt", // PANIC_EXCEPTION_IWDT + "Task wdt", // PANIC_EXCEPTION_TWDT + "Abort", // PANIC_EXCEPTION_ABORT + "Fault", // PANIC_EXCEPTION_FAULT + }; + uint8_t exc = s_raw_crash_data.exception; + if (exc < sizeof(TYPES) / sizeof(TYPES[0])) + return TYPES[exc]; + return "Unknown"; +} + +// Intentionally uses separate ESP_LOGE calls per line instead of combining into +// one multi-line log message. This ensures each address appears as its own line +// on the serial console, making it possible to see partial output if the device +// crashes again during boot, and allowing the CLI's process_stacktrace to match +// and decode each address individually. +void crash_handler_log() { + if (!s_crash_data_valid) + return; + + ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***"); + const char *reason = get_exception_reason(); + if (reason != nullptr) { + ESP_LOGE(TAG, " Reason: %s - %s", get_exception_type(), reason); + } else { + ESP_LOGE(TAG, " Reason: %s", get_exception_type()); + } + ESP_LOGE(TAG, " PC: 0x%08" PRIX32 " (fault location)", s_raw_crash_data.pc); + uint8_t bt_num = 0; + for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count; i++) { + uint32_t addr = s_raw_crash_data.backtrace[i]; +#if CONFIG_IDF_TARGET_ARCH_RISCV + // Register-sourced entries (MEPC/RA) are trusted; only filter stack-scanned ones. + if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr)) + continue; +#endif +#if CONFIG_IDF_TARGET_ARCH_RISCV + const char *source = (i < s_raw_crash_data.reg_frame_count) ? "backtrace" : "stack scan"; +#else + const char *source = "backtrace"; +#endif + ESP_LOGE(TAG, " BT%d: 0x%08" PRIX32 " (%s)", bt_num++, addr, source); + } + // Build addr2line hint with all captured addresses for easy copy-paste + char hint[256]; + int pos = snprintf(hint, sizeof(hint), "Use: addr2line -pfiaC -e firmware.elf 0x%08" PRIX32, s_raw_crash_data.pc); + for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count && pos < (int) sizeof(hint) - 12; i++) { + uint32_t addr = s_raw_crash_data.backtrace[i]; +#if CONFIG_IDF_TARGET_ARCH_RISCV + if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr)) + continue; +#endif + pos += snprintf(hint + pos, sizeof(hint) - pos, " 0x%08" PRIX32, addr); + } + ESP_LOGE(TAG, "%s", hint); +} + +} // namespace esphome::esp32 + +// --- Panic handler wrapper --- +// Intercepts esp_panic_handler() via --wrap linker flag to capture crash data +// into NOINIT memory before the normal panic handler runs. +// +extern "C" { +// NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +// Names are mandated by the --wrap linker mechanism +extern void __real_esp_panic_handler(panic_info_t *info); + +void IRAM_ATTR __wrap_esp_panic_handler(panic_info_t *info) { + // Save the faulting PC and exception info + s_raw_crash_data.pc = (uint32_t) info->addr; + s_raw_crash_data.backtrace_count = 0; + s_raw_crash_data.reg_frame_count = 0; + s_raw_crash_data.exception = (uint8_t) info->exception; + s_raw_crash_data.pseudo_excause = info->pseudo_excause ? 1 : 0; + +#if CONFIG_IDF_TARGET_ARCH_XTENSA + // Xtensa: walk the backtrace using the public API + if (info->frame != nullptr) { + auto *xt_frame = (XtExcFrame *) info->frame; + s_raw_crash_data.cause = xt_frame->exccause; + esp_backtrace_frame_t bt_frame = { + .pc = (uint32_t) xt_frame->pc, + .sp = (uint32_t) xt_frame->a1, + .next_pc = (uint32_t) xt_frame->a0, + .exc_frame = xt_frame, + }; + + uint8_t count = 0; + // First frame PC + uint32_t first_pc = esp_cpu_process_stack_pc(bt_frame.pc); + if (is_code_addr(first_pc)) { + s_raw_crash_data.backtrace[count++] = first_pc; + } + // Walk remaining frames + while (count < MAX_BACKTRACE && bt_frame.next_pc != 0) { + if (!esp_backtrace_get_next_frame(&bt_frame)) { + break; + } + uint32_t pc = esp_cpu_process_stack_pc(bt_frame.pc); + if (is_code_addr(pc)) { + s_raw_crash_data.backtrace[count++] = pc; + } + } + s_raw_crash_data.backtrace_count = count; + } + +#elif CONFIG_IDF_TARGET_ARCH_RISCV + // RISC-V: capture MEPC + RA, then scan stack for code addresses + if (info->frame != nullptr) { + auto *rv_frame = (RvExcFrame *) info->frame; + s_raw_crash_data.cause = rv_frame->mcause; + uint8_t count = 0; + + // Save MEPC (fault PC) and RA (return address) + if (is_code_addr(rv_frame->mepc)) { + s_raw_crash_data.backtrace[count++] = rv_frame->mepc; + } + if (is_code_addr(rv_frame->ra) && rv_frame->ra != rv_frame->mepc) { + s_raw_crash_data.backtrace[count++] = rv_frame->ra; + } + + // Track how many entries came from registers (MEPC/RA) so we can + // skip return-address validation for them at log time. + s_raw_crash_data.reg_frame_count = count; + + // Scan stack for code addresses — captures broadly during panic, + // filtered by is_return_addr() at log time when flash is accessible. + auto *scan_start = (uint32_t *) rv_frame->sp; + for (uint32_t i = 0; i < 64 && count < MAX_BACKTRACE; i++) { + uint32_t val = scan_start[i]; + if (is_code_addr(val) && val != rv_frame->mepc && val != rv_frame->ra) { + s_raw_crash_data.backtrace[count++] = val; + } + } + s_raw_crash_data.backtrace_count = count; + } +#endif + + // Write version and magic last — ensures all data is written before we mark it valid + s_raw_crash_data.version = CRASH_DATA_VERSION; + s_raw_crash_data.magic = CRASH_MAGIC; + + // Call the real panic handler (prints to UART, does core dump, reboots, etc.) + __real_esp_panic_handler(info); +} + +// NOLINTEND(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp,readability-identifier-naming) +} // extern "C" + +#endif // USE_ESP32_CRASH_HANDLER +#endif // USE_ESP32 diff --git a/esphome/components/esp32/crash_handler.h b/esphome/components/esp32/crash_handler.h new file mode 100644 index 0000000000..97a4d4e116 --- /dev/null +++ b/esphome/components/esp32/crash_handler.h @@ -0,0 +1,18 @@ +#pragma once + +#ifdef USE_ESP32_CRASH_HANDLER + +namespace esphome::esp32 { + +/// Read crash data from NOINIT memory and clear the magic marker. +void crash_handler_read_and_clear(); + +/// Log crash data if a crash was detected on previous boot. +void crash_handler_log(); + +/// Returns true if crash data was found this boot. +bool crash_handler_has_data(); + +} // namespace esphome::esp32 + +#endif // USE_ESP32_CRASH_HANDLER diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index d6ad77ff4f..f5bf782289 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -1,6 +1,7 @@ #ifdef USE_ESP32 #include "logger.h" +#include "esphome/components/esp32/crash_handler.h" #include <esp_log.h> #include <driver/uart.h> @@ -117,6 +118,9 @@ void Logger::pre_setup() { esp_log_set_vprintf(esp_idf_log_vprintf_); ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_ESP32_CRASH_HANDLER + esp32::crash_handler_log(); +#endif } void HOT Logger::write_msg_(const char *msg, uint16_t len) { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index cec77fe2e2..a33f10cb9c 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -195,6 +195,7 @@ // ESP32-specific feature flags #ifdef USE_ESP32 +#define USE_ESP32_CRASH_HANDLER #define USE_MQTT_IDF_ENQUEUE #define USE_ESPHOME_TASK_LOG_BUFFER #define USE_OTA_ROLLBACK diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 5d4065207f..cb080b2a95 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -340,6 +340,8 @@ STACKTRACE_ESP32_BACKTRACE_RE = re.compile( r"Backtrace:(?:\s*0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8})+" ) STACKTRACE_ESP32_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") +# ESP32 crash handler (stored backtrace from previous boot) +STACKTRACE_ESP32_CRASH_BT_RE = re.compile(r"BT\d+:\s*0x([0-9a-fA-F]{8})") STACKTRACE_ESP8266_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") @@ -371,6 +373,11 @@ def process_stacktrace(config, line, backtrace_state): ) _decode_pc(config, match.group(1)) + # ESP32 crash handler backtrace (from previous boot) + match = re.search(STACKTRACE_ESP32_CRASH_BT_RE, line) + if match is not None: + _decode_pc(config, match.group(1)) + # ESP32 single-line backtrace match = re.match(STACKTRACE_ESP32_BACKTRACE_RE, line) if match is not None: diff --git a/tests/unit_tests/test_platformio_api.py b/tests/unit_tests/test_platformio_api.py index 1686144277..e1b3908c24 100644 --- a/tests/unit_tests/test_platformio_api.py +++ b/tests/unit_tests/test_platformio_api.py @@ -673,6 +673,34 @@ def test_process_stacktrace_bad_alloc( assert state is False +def test_process_stacktrace_esp32_crash_handler( + setup_core: Path, mock_decode_pc: Mock +) -> None: + """Test process_stacktrace handles ESP32 crash handler backtrace lines.""" + config = {"name": "test"} + + # Simulate crash handler log lines as they appear from the API/serial + line_pc = "[E][esp32.crash:078]: PC: 0x400D1234 (fault location)" + state = platformio_api.process_stacktrace(config, line_pc, False) + # PC line is matched by existing STACKTRACE_ESP32_PC_RE + mock_decode_pc.assert_called_with(config, "400D1234") + assert state is False + + mock_decode_pc.reset_mock() + + line_bt0 = "[E][esp32.crash:080]: BT0: 0x400D5678 (backtrace)" + state = platformio_api.process_stacktrace(config, line_bt0, False) + mock_decode_pc.assert_called_once_with(config, "400D5678") + assert state is False + + mock_decode_pc.reset_mock() + + line_bt1 = "[E][esp32.crash:080]: BT1: 0x42005ABC (backtrace)" + state = platformio_api.process_stacktrace(config, line_bt1, False) + mock_decode_pc.assert_called_once_with(config, "42005ABC") + assert state is False + + def test_patch_file_downloader_succeeds_first_try() -> None: """Test patch_file_downloader succeeds on first attempt.""" mock_exception_cls = type("PackageException", (Exception,), {}) From 7cec2d3029ae4d2f873633c060b49ade4f77eadd Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Wed, 11 Mar 2026 23:48:27 -0500 Subject: [PATCH 1374/2030] [ethernet] ESP32-S3 Ethernet compilation fix (#14717) --- esphome/components/ethernet/ethernet_component.h | 3 +++ esphome/components/ethernet/ethernet_helpers.c | 2 ++ tests/components/ethernet/common-w5500.yaml | 4 ++-- tests/components/ethernet/test.esp32-s3-idf.yaml | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 tests/components/ethernet/test.esp32-s3-idf.yaml diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index c464e20b84..f7a0996fb7 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -11,11 +11,14 @@ #include "esp_eth.h" #include "esp_eth_mac.h" +#include "esp_eth_mac_esp.h" #include "esp_netif.h" #include "esp_mac.h" #include "esp_idf_version.h" +#if CONFIG_ETH_USE_ESP32_EMAC extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); +#endif namespace esphome::ethernet { diff --git a/esphome/components/ethernet/ethernet_helpers.c b/esphome/components/ethernet/ethernet_helpers.c index 96faccad24..963db3ff1c 100644 --- a/esphome/components/ethernet/ethernet_helpers.c +++ b/esphome/components/ethernet/ethernet_helpers.c @@ -3,6 +3,8 @@ // ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers // which are valid in C but not in C++. This wrapper allows C++ code to get // the default config without replicating the macro's contents. +#if CONFIG_ETH_USE_ESP32_EMAC eth_esp32_emac_config_t eth_esp32_emac_default_config(void) { return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG(); } +#endif diff --git a/tests/components/ethernet/common-w5500.yaml b/tests/components/ethernet/common-w5500.yaml index 1f8b8650dd..bf3f6f3f0c 100644 --- a/tests/components/ethernet/common-w5500.yaml +++ b/tests/components/ethernet/common-w5500.yaml @@ -2,10 +2,10 @@ ethernet: type: W5500 clk_pin: 19 mosi_pin: 21 - miso_pin: 23 + miso_pin: 17 cs_pin: 18 interrupt_pin: 36 - reset_pin: 22 + reset_pin: 12 clock_speed: 10Mhz manual_ip: static_ip: 192.168.178.56 diff --git a/tests/components/ethernet/test.esp32-s3-idf.yaml b/tests/components/ethernet/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..36f1b5365f --- /dev/null +++ b/tests/components/ethernet/test.esp32-s3-idf.yaml @@ -0,0 +1 @@ +<<: !include common-w5500.yaml From e8f51fec889ada351d35311c2b3ce1ed7239d35e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 11 Mar 2026 19:23:01 -1000 Subject: [PATCH 1375/2030] [rp2040] Fix crash handler design flaws (#14716) --- esphome/components/api/api_connection.h | 6 ++++++ esphome/components/logger/logger_rp2040.cpp | 5 +++++ esphome/components/rp2040/__init__.py | 1 + esphome/components/rp2040/core.cpp | 6 +++++- esphome/components/rp2040/crash_handler.cpp | 23 ++++++++++++++++----- esphome/components/rp2040/crash_handler.h | 8 ++++++- esphome/core/defines.h | 1 + 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 60cc3e91b1..68f698d190 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -17,6 +17,9 @@ #ifdef USE_ESP32_CRASH_HANDLER #include "esphome/components/esp32/crash_handler.h" #endif +#ifdef USE_RP2040_CRASH_HANDLER +#include "esphome/components/rp2040/crash_handler.h" +#endif #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -240,6 +243,9 @@ class APIConnection final : public APIServerConnectionBase { App.schedule_dump_config(); #ifdef USE_ESP32_CRASH_HANDLER esp32::crash_handler_log(); +#endif +#ifdef USE_RP2040_CRASH_HANDLER + rp2040::crash_handler_log(); #endif } #ifdef USE_API_HOMEASSISTANT_SERVICES diff --git a/esphome/components/logger/logger_rp2040.cpp b/esphome/components/logger/logger_rp2040.cpp index f76b823a8f..b7225c2a25 100644 --- a/esphome/components/logger/logger_rp2040.cpp +++ b/esphome/components/logger/logger_rp2040.cpp @@ -1,6 +1,9 @@ #ifdef USE_RP2040 #include "logger.h" +#include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER #include "esphome/components/rp2040/crash_handler.h" +#endif #include "esphome/core/log.h" namespace esphome::logger { @@ -26,7 +29,9 @@ void Logger::pre_setup() { } global_logger = this; ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_RP2040_CRASH_HANDLER rp2040::crash_handler_log(); +#endif } void HOT Logger::write_msg_(const char *msg, uint16_t len) { diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index b15811241c..276187b273 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -212,6 +212,7 @@ async def to_code(config): ) cg.add_define("USE_RP2040_WATCHDOG_TIMEOUT", config[CONF_WATCHDOG_TIMEOUT]) + cg.add_define("USE_RP2040_CRASH_HANDLER") def add_pio_file(component: str, key: str, data: str): diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 5e5a96c78b..7079cbca15 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -1,8 +1,10 @@ #ifdef USE_RP2040 #include "core.h" -#include "crash_handler.h" #include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER +#include "crash_handler.h" +#endif #include "esphome/core/hal.h" #include "esphome/core/helpers.h" @@ -25,7 +27,9 @@ void arch_restart() { } void arch_init() { +#ifdef USE_RP2040_CRASH_HANDLER rp2040::crash_handler_read_and_clear(); +#endif #if USE_RP2040_WATCHDOG_TIMEOUT > 0 watchdog_enable(USE_RP2040_WATCHDOG_TIMEOUT, false); #endif diff --git a/esphome/components/rp2040/crash_handler.cpp b/esphome/components/rp2040/crash_handler.cpp index 6ab46da444..1f579c2d18 100644 --- a/esphome/components/rp2040/crash_handler.cpp +++ b/esphome/components/rp2040/crash_handler.cpp @@ -1,5 +1,8 @@ #ifdef USE_RP2040 +#include "esphome/core/defines.h" +#ifdef USE_RP2040_CRASH_HANDLER + #include "crash_handler.h" #include "esphome/core/log.h" @@ -13,13 +16,19 @@ static constexpr uint32_t EF_LR = 5; static constexpr uint32_t EF_PC = 6; -static constexpr uint32_t CRASH_MAGIC = 0xDEADBEEF; +// Version encoded in the magic value: upper 16 bits are sentinel (0xDEAD), +// lower 16 bits are the version number. This avoids using a separate scratch +// register for versioning (we only have 8 total). Future firmware reads the +// sentinel to confirm it's crash data, then the version to know the layout. +static constexpr uint32_t CRASH_MAGIC_SENTINEL = 0xDEAD0000; +static constexpr uint32_t CRASH_DATA_VERSION = 1; +static constexpr uint32_t CRASH_MAGIC_V1 = CRASH_MAGIC_SENTINEL | CRASH_DATA_VERSION; // We only have 8 scratch registers (32 bytes) that survive watchdog reboot. // Use them for the most important data, then scan the stack for code addresses. // // Scratch register layout: -// [0] = magic (CRASH_MAGIC) +// [0] = versioned magic (upper 16 bits = 0xDEAD sentinel, lower 16 bits = version) // [1] = PC (program counter at fault) // [2] = LR (link register from exception frame) // [3] = SP (stack pointer at fault) @@ -57,9 +66,12 @@ static struct { uint8_t backtrace_count; } __attribute__((section(".noinit"))) s_crash_data; +bool crash_handler_has_data() { return s_crash_data.valid; } + void crash_handler_read_and_clear() { s_crash_data.valid = false; - if (watchdog_hw->scratch[0] == CRASH_MAGIC) { + uint32_t magic = watchdog_hw->scratch[0]; + if ((magic & 0xFFFF0000) == CRASH_MAGIC_SENTINEL && (magic & 0xFFFF) == CRASH_DATA_VERSION) { s_crash_data.valid = true; s_crash_data.pc = watchdog_hw->scratch[1]; s_crash_data.lr = watchdog_hw->scratch[2]; @@ -135,7 +147,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame // by a stacking error or corrupted SP, frame may be invalid. Write a minimal // crash marker so we at least know a crash occurred. if (!is_valid_sram_ptr(frame)) { - watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[0] = CRASH_MAGIC_V1; watchdog_hw->scratch[1] = 0; // PC unknown watchdog_hw->scratch[2] = 0; // LR unknown watchdog_hw->scratch[3] = reinterpret_cast<uintptr_t>(frame); // Record the bad SP for diagnosis @@ -157,7 +169,7 @@ static void __attribute__((used, noreturn)) hard_fault_handler_c(uint32_t *frame uint32_t pre_fault_sp = reinterpret_cast<uintptr_t>(post_frame); // Write key registers - watchdog_hw->scratch[0] = CRASH_MAGIC; + watchdog_hw->scratch[0] = CRASH_MAGIC_V1; watchdog_hw->scratch[1] = frame[EF_PC]; watchdog_hw->scratch[2] = frame[EF_LR]; watchdog_hw->scratch[3] = pre_fault_sp; @@ -224,4 +236,5 @@ extern "C" void __attribute__((naked, used)) isr_hardfault() { : "i"(hard_fault_handler_c)); } +#endif // USE_RP2040_CRASH_HANDLER #endif // USE_RP2040 diff --git a/esphome/components/rp2040/crash_handler.h b/esphome/components/rp2040/crash_handler.h index f10db47c23..78e8ede08c 100644 --- a/esphome/components/rp2040/crash_handler.h +++ b/esphome/components/rp2040/crash_handler.h @@ -2,7 +2,9 @@ #ifdef USE_RP2040 -#include <cstdint> +#include "esphome/core/defines.h" + +#ifdef USE_RP2040_CRASH_HANDLER namespace esphome::rp2040 { @@ -12,6 +14,10 @@ void crash_handler_read_and_clear(); /// Log crash data if a crash was detected on previous boot. void crash_handler_log(); +/// Returns true if crash data was found this boot. +bool crash_handler_has_data(); + } // namespace esphome::rp2040 +#endif // USE_RP2040_CRASH_HANDLER #endif // USE_RP2040 diff --git a/esphome/core/defines.h b/esphome/core/defines.h index a33f10cb9c..073170aafb 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -338,6 +338,7 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) #define USE_LOOP_PRIORITY +#define USE_RP2040_CRASH_HANDLER #define USE_HTTP_REQUEST_RESPONSE #define USE_I2C #define USE_LOGGER_USB_CDC From 6002badb3c35b20475a76cef3781f13967c1260e Mon Sep 17 00:00:00 2001 From: Adam DeMuri <adam.demuri@gmail.com> Date: Thu, 12 Mar 2026 02:00:26 -0600 Subject: [PATCH 1376/2030] [modbus] Fix buffer overflow in modbus (#14719) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/modbus/modbus.cpp | 12 ++--- tests/components/modbus/modbus_test.cpp | 59 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 tests/components/modbus/modbus_test.cpp diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 82672217c5..7a61868e6e 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -125,13 +125,17 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { // Byte 0: modbus address (match all) if (at == 0) return true; - uint8_t address = raw[0]; - uint8_t function_code = raw[1]; + // Byte 1: function code + if (at == 1) + return true; // Byte 2: Size (with modbus rtu function code 4/3) // See also https://en.wikipedia.org/wiki/Modbus if (at == 2) return true; + uint8_t address = raw[0]; + uint8_t function_code = raw[1]; + uint8_t data_len = raw[2]; uint8_t data_offset = 3; @@ -146,10 +150,6 @@ bool Modbus::parse_modbus_byte_(uint8_t byte) { // chance that this is a complete message ... admittedly there is a small chance is // isn't but that is quite small given the purpose of the CRC in the first place - // Fewer than 2 bytes can't calc CRC - if (at < 2) - return true; - data_len = at - 2; data_offset = 1; diff --git a/tests/components/modbus/modbus_test.cpp b/tests/components/modbus/modbus_test.cpp new file mode 100644 index 0000000000..afe5ced082 --- /dev/null +++ b/tests/components/modbus/modbus_test.cpp @@ -0,0 +1,59 @@ +#include <gtest/gtest.h> +#include "esphome/components/modbus/modbus.h" +#include "esphome/core/helpers.h" + +namespace esphome::modbus { + +// Exposes protected methods for testing. +class TestModbus : public Modbus { + public: + bool test_parse_modbus_byte(uint8_t byte) { return this->parse_modbus_byte_(byte); } + void test_clear_rx_buffer() { this->rx_buffer_.clear(); } + void set_waiting(uint8_t addr) { this->waiting_for_response_ = addr; } +}; + +class MockDevice : public ModbusDevice { + public: + void on_modbus_data(const std::vector<uint8_t> &data) override { this->data_received = true; } + bool data_received{false}; +}; + +TEST(ModbusTest, TwoByteRegressionTest) { + TestModbus modbus; + modbus.set_role(ModbusRole::CLIENT); + // First byte (at=0) + EXPECT_TRUE(modbus.test_parse_modbus_byte(0x01)); + // Second byte (at=1) + // This used to reach raw[2] because it skipped the if(at==2) check, causing a + // buffer overflow. + EXPECT_TRUE(modbus.test_parse_modbus_byte(0x03)); +} + +TEST(ModbusTest, TestValidFrame) { + TestModbus modbus; + modbus.set_role(ModbusRole::CLIENT); + + MockDevice device; + device.set_parent(&modbus); + device.set_address(0x01); + modbus.register_device(&device); + modbus.set_waiting(0x01); + + // Address 1, Function 3, Length 2, Data 0x1234 + uint8_t frame_data[] = {0x01, 0x03, 0x02, 0x12, 0x34}; + uint16_t crc = esphome::crc16(frame_data, sizeof(frame_data)); + + std::vector<uint8_t> frame; + for (uint8_t b : frame_data) + frame.push_back(b); + frame.push_back(crc & 0xFF); + frame.push_back((crc >> 8) & 0xFF); + + for (size_t i = 0; i < frame.size(); i++) { + bool result = modbus.test_parse_modbus_byte(frame[i]); + EXPECT_TRUE(result) << "Failed at byte " << i << " (0x" << std::hex << (int) frame[i] << ")"; + } + EXPECT_TRUE(device.data_received); +} + +} // namespace esphome::modbus From 4b1c4ba5c0561cba93d979aa8fb76da0bafff301 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Thu, 12 Mar 2026 03:16:02 -0500 Subject: [PATCH 1377/2030] [ledc] Fix high-pressure crash & recovery (#14720) --- esphome/components/ledc/ledc_output.cpp | 53 +++++++++++++++++++++++-- esphome/components/ledc/ledc_output.h | 8 ++-- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index 763de851da..592fc7bd0c 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -5,6 +5,10 @@ #include <driver/ledc.h> #include <cinttypes> +#include <esp_private/periph_ctrl.h> +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) +#include <hal/ledc_ll.h> +#endif #define CLOCK_FREQUENCY 80e6f @@ -16,10 +20,10 @@ static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5; -namespace esphome { -namespace ledc { +namespace esphome::ledc { static const char *const TAG = "ledc.output"; +static bool ledc_peripheral_reset_done = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1; #if SOC_LEDC_SUPPORT_HS_MODE @@ -32,6 +36,28 @@ inline ledc_mode_t get_speed_mode(uint8_t channel) { return channel < 8 ? LEDC_H inline ledc_mode_t get_speed_mode(uint8_t) { return LEDC_LOW_SPEED_MODE; } #endif +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) +// Classic ESP32 (currently the only target without SOC_LEDC_SUPPORT_FADE_STOP) can block in +// ledc_ll_set_duty_start() while duty_start is set. We check the same conf1.duty_start bit here +// to defer updates and avoid entering IDF's unbounded wait loop. +// +// This intentionally depends on the classic ESP32 LEDC register layout used by IDF's own LL HAL. +// If another target without SOC_LEDC_SUPPORT_FADE_STOP is introduced, revisit this helper. +static_assert( +#if defined(CONFIG_IDF_TARGET_ESP32) + true, +#else + false, +#endif + "LEDC duty_start pending check assumes classic ESP32 register layout; " + "re-evaluate for this target"); + +static bool ledc_duty_update_pending(ledc_mode_t speed_mode, ledc_channel_t chan_num) { + auto *hw = LEDC_LL_GET_HW(); + return hw->channel_group[speed_mode].channel[chan_num].conf1.duty_start != 0; +} +#endif + float ledc_max_frequency_for_bit_depth(uint8_t bit_depth) { return static_cast<float>(CLOCK_FREQUENCY) / static_cast<float>(1 << bit_depth); } @@ -105,21 +131,40 @@ void LEDCOutput::write_state(float state) { const uint32_t max_duty = (uint32_t(1) << this->bit_depth_) - 1; const float duty_rounded = roundf(state * max_duty); auto duty = static_cast<uint32_t>(duty_rounded); + if (duty == this->last_duty_) { + return; + } + ESP_LOGV(TAG, "Setting duty: %" PRIu32 " on channel %u", duty, this->channel_); auto speed_mode = get_speed_mode(this->channel_); auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8); int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_); if (duty == max_duty) { ledc_stop(speed_mode, chan_num, 1); + this->last_duty_ = duty; } else if (duty == 0) { ledc_stop(speed_mode, chan_num, 0); + this->last_duty_ = duty; } else { +#if !defined(SOC_LEDC_SUPPORT_FADE_STOP) + if (ledc_duty_update_pending(speed_mode, chan_num)) { + ESP_LOGV(TAG, "Skipping LEDC duty update on channel %u while previous duty_start is still set", this->channel_); + return; + } +#endif ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint); ledc_update_duty(speed_mode, chan_num); + this->last_duty_ = duty; } } void LEDCOutput::setup() { + if (!ledc_peripheral_reset_done) { + ESP_LOGV(TAG, "Resetting LEDC peripheral to clear stale state after reboot"); + periph_module_reset(PERIPH_LEDC_MODULE); + ledc_peripheral_reset_done = true; + } + auto speed_mode = get_speed_mode(this->channel_); auto timer_num = static_cast<ledc_timer_t>((this->channel_ % 8) / 2); auto chan_num = static_cast<ledc_channel_t>(this->channel_ % 8); @@ -207,12 +252,12 @@ void LEDCOutput::update_frequency(float frequency) { this->status_clear_error(); // re-apply duty + this->last_duty_ = UINT32_MAX; this->write_state(this->duty_); } uint8_t next_ledc_channel = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -} // namespace ledc -} // namespace esphome +} // namespace esphome::ledc #endif diff --git a/esphome/components/ledc/ledc_output.h b/esphome/components/ledc/ledc_output.h index b24e3cfdb2..bf5cdb9305 100644 --- a/esphome/components/ledc/ledc_output.h +++ b/esphome/components/ledc/ledc_output.h @@ -4,11 +4,11 @@ #include "esphome/core/hal.h" #include "esphome/core/automation.h" #include "esphome/components/output/float_output.h" +#include <cstdint> #ifdef USE_ESP32 -namespace esphome { -namespace ledc { +namespace esphome::ledc { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern uint8_t next_ledc_channel; @@ -39,6 +39,7 @@ class LEDCOutput : public output::FloatOutput, public Component { float phase_angle_{0.0f}; float frequency_{}; float duty_{0.0f}; + uint32_t last_duty_{UINT32_MAX}; bool initialized_ = false; }; @@ -56,7 +57,6 @@ template<typename... Ts> class SetFrequencyAction : public Action<Ts...> { LEDCOutput *parent_; }; -} // namespace ledc -} // namespace esphome +} // namespace esphome::ledc #endif From df2ddc47ec2baae7da48a6f14831c429c8f292af Mon Sep 17 00:00:00 2001 From: Brian Kaufman <bkaufx@gmail.com> Date: Thu, 12 Mar 2026 02:07:26 -0700 Subject: [PATCH 1378/2030] [web_server] use DETAIL_ALL in update_all_json_generator (#14711) --- esphome/components/web_server/web_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 5590e67b82..4083019643 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -2181,7 +2181,7 @@ json::SerializationBuffer<> WebServer::update_state_json_generator(WebServer *we } json::SerializationBuffer<> WebServer::update_all_json_generator(WebServer *web_server, void *source) { // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson - return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_STATE); + return web_server->update_json_((update::UpdateEntity *) (source), DETAIL_ALL); } json::SerializationBuffer<> WebServer::update_json_(update::UpdateEntity *obj, JsonDetail start_config) { // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson From 440734dadf0e4c60accb4a5d6b79eaf6a9c9c60d Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 12 Mar 2026 07:56:01 -0500 Subject: [PATCH 1379/2030] [audio] Bump microOpus to v0.3.5 (#14727) --- esphome/components/audio/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index d95fcf66d7..b28c2ed3d8 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -214,4 +214,4 @@ async def to_code(config): cg.add_define("USE_AUDIO_MP3_SUPPORT") if data.opus_support: cg.add_define("USE_AUDIO_OPUS_SUPPORT") - add_idf_component(name="esphome/micro-opus", ref="0.3.4") + add_idf_component(name="esphome/micro-opus", ref="0.3.5") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index f7fd3e67bc..df651ae15d 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -4,7 +4,7 @@ dependencies: esphome/esp-audio-libs: version: 2.0.3 esphome/micro-opus: - version: 0.3.4 + version: 0.3.5 espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: From da130c900f82326080c1b790be68c9625912b153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20K=C3=B6nig?= <Matthias.Konitzny@kabelmail.de> Date: Thu, 12 Mar 2026 17:00:08 +0100 Subject: [PATCH 1380/2030] [mqtt] Fixed permission denied error for client certificates on Windows (#13525) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/mqtt.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/esphome/mqtt.py b/esphome/mqtt.py index cbf78bd3f6..ccacbaea54 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -2,6 +2,7 @@ import contextlib from datetime import datetime import json import logging +import os import ssl import tempfile import time @@ -109,14 +110,18 @@ def prepare( CONF_CLIENT_CERTIFICATE_KEY ): with ( - tempfile.NamedTemporaryFile(mode="w+") as cert_file, - tempfile.NamedTemporaryFile(mode="w+") as key_file, + tempfile.NamedTemporaryFile(mode="w+", delete=False) as cert_file, + tempfile.NamedTemporaryFile(mode="w+", delete=False) as key_file, ): - cert_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE)) - cert_file.flush() - key_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE_KEY)) - key_file.flush() - context.load_cert_chain(cert_file.name, key_file.name) + try: + cert_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE)) + key_file.write(config[CONF_MQTT].get(CONF_CLIENT_CERTIFICATE_KEY)) + cert_file.close() + key_file.close() + context.load_cert_chain(cert_file.name, key_file.name) + finally: + os.unlink(cert_file.name) + os.unlink(key_file.name) client.tls_set_context(context) try: From 3a838d897fac21b120b8d913141dee194cf87c6a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:14:49 -1000 Subject: [PATCH 1381/2030] [socket] Fix use-after-free in LWIP PCB close/abort path (#14706) --- .../components/socket/lwip_raw_tcp_impl.cpp | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index fd1b8a9554..1e03a4935c 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -138,13 +138,46 @@ static const char *const TAG = "socket.lwip"; #define LWIP_LOG(msg, ...) #endif +// Clear arg, recv, and err callbacks, then abort a connected PCB. +// Only valid for full tcp_pcb (not tcp_pcb_listen). +// Must be called before destroying the object that tcp_arg points to — +// tcp_abort() triggers the err callback synchronously, which would +// otherwise call back into a partially-destroyed object. +// tcp_sent/tcp_poll are not cleared because this implementation +// never registers them. +static void pcb_detach_abort(struct tcp_pcb *pcb) { + tcp_arg(pcb, nullptr); + tcp_recv(pcb, nullptr); + tcp_err(pcb, nullptr); + tcp_abort(pcb); +} + +// Clear arg, recv, and err callbacks, then gracefully close a connected PCB. +// Only valid for full tcp_pcb (not tcp_pcb_listen). +// After tcp_close(), the PCB remains alive during the TCP close handshake +// (FIN_WAIT, TIME_WAIT states). Without clearing callbacks first, LWIP +// would call recv/err on a destroyed socket object, corrupting the heap. +// tcp_sent/tcp_poll are not cleared because this implementation +// never registers them. +// Returns ERR_OK on success; on failure the PCB is aborted instead. +static err_t pcb_detach_close(struct tcp_pcb *pcb) { + tcp_arg(pcb, nullptr); + tcp_recv(pcb, nullptr); + tcp_err(pcb, nullptr); + err_t err = tcp_close(pcb); + if (err != ERR_OK) { + tcp_abort(pcb); + } + return err; +} + // ---- LWIPRawCommon methods ---- LWIPRawCommon::~LWIPRawCommon() { LWIP_LOCK(); if (this->pcb_ != nullptr) { LWIP_LOG("tcp_abort(%p)", this->pcb_); - tcp_abort(this->pcb_); + pcb_detach_abort(this->pcb_); this->pcb_ = nullptr; } } @@ -222,15 +255,13 @@ int LWIPRawCommon::close() { return -1; } LWIP_LOG("tcp_close(%p)", this->pcb_); - err_t err = tcp_close(this->pcb_); + err_t err = pcb_detach_close(this->pcb_); + this->pcb_ = nullptr; if (err != ERR_OK) { LWIP_LOG(" -> err %d", err); - tcp_abort(this->pcb_); - this->pcb_ = nullptr; errno = err == ERR_MEM ? ENOMEM : EIO; return -1; } - this->pcb_ = nullptr; return 0; } @@ -673,13 +704,10 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) { LWIPRawListenImpl::~LWIPRawListenImpl() { LWIP_LOCK(); // Abort any queued PCBs that were never accepted by the main loop. - // Clear the error callback first — tcp_abort triggers it, and we don't - // want s_queued_err_fn writing to slots during destruction. for (uint8_t i = 0; i < this->accepted_socket_count_; i++) { auto &entry = this->accepted_pcbs_[i]; if (entry.pcb != nullptr) { - tcp_err(entry.pcb, nullptr); - tcp_abort(entry.pcb); + pcb_detach_abort(entry.pcb); entry.pcb = nullptr; } if (entry.rx_buf != nullptr) { @@ -691,6 +719,10 @@ LWIPRawListenImpl::~LWIPRawListenImpl() { // Listen PCBs must use tcp_close(), not tcp_abort(). // tcp_abandon() asserts pcb->state != LISTEN and would access // fields that don't exist in the smaller tcp_pcb_listen struct. + // Don't use pcb_detach_close() here — tcp_recv()/tcp_err() also access + // fields that only exist in the full tcp_pcb, not tcp_pcb_listen. + // tcp_close() on a listen PCB is synchronous (frees immediately), + // so there are no async callbacks to worry about. // Close here and null pcb_ so the base destructor skips tcp_abort. if (this->pcb_ != nullptr) { tcp_close(this->pcb_); From 1d881ef6f4d4a4ba8575fe5ac1c4bb50c121f767 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:04 -1000 Subject: [PATCH 1382/2030] [socket] Fast path for TCP_NODELAY bypasses lwip_setsockopt overhead (#14693) --- esphome/components/socket/bsd_sockets_impl.h | 11 ++++++++++- esphome/components/socket/lwip_sockets_impl.h | 11 ++++++++++- esphome/core/lwip_fast_select.c | 16 ++++++++++++++++ esphome/core/lwip_fast_select.h | 7 +++++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/esphome/components/socket/bsd_sockets_impl.h b/esphome/components/socket/bsd_sockets_impl.h index 9ebbe72002..339a699bc9 100644 --- a/esphome/components/socket/bsd_sockets_impl.h +++ b/esphome/components/socket/bsd_sockets_impl.h @@ -14,7 +14,7 @@ #endif #ifdef USE_LWIP_FAST_SELECT -struct lwip_sock; +#include "esphome/core/lwip_fast_select.h" #endif namespace esphome::socket { @@ -56,6 +56,15 @@ class BSDSocketImpl { return ::getsockopt(this->fd_, level, optname, optval, optlen); } int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { +#if defined(USE_LWIP_FAST_SELECT) && defined(CONFIG_LWIP_TCPIP_CORE_LOCKING) + // Fast path for TCP_NODELAY: directly set the pcb flag under the TCPIP core lock, + // bypassing lwip_setsockopt overhead (socket lookups, hook, switch cascade, refcounting). + if (level == IPPROTO_TCP && optname == TCP_NODELAY && optlen == sizeof(int) && optval != nullptr) { + LwIPLock lock; + if (esphome_lwip_set_nodelay(this->cached_sock_, *reinterpret_cast<const int *>(optval) != 0)) + return 0; + } +#endif return ::setsockopt(this->fd_, level, optname, optval, optlen); } int listen(int backlog) { return ::listen(this->fd_, backlog); } diff --git a/esphome/components/socket/lwip_sockets_impl.h b/esphome/components/socket/lwip_sockets_impl.h index c579219863..bfc4da9926 100644 --- a/esphome/components/socket/lwip_sockets_impl.h +++ b/esphome/components/socket/lwip_sockets_impl.h @@ -10,7 +10,7 @@ #include "headers.h" #ifdef USE_LWIP_FAST_SELECT -struct lwip_sock; +#include "esphome/core/lwip_fast_select.h" #endif namespace esphome::socket { @@ -52,6 +52,15 @@ class LwIPSocketImpl { return lwip_getsockopt(this->fd_, level, optname, optval, optlen); } int setsockopt(int level, int optname, const void *optval, socklen_t optlen) { +#if defined(USE_LWIP_FAST_SELECT) && defined(CONFIG_LWIP_TCPIP_CORE_LOCKING) + // Fast path for TCP_NODELAY: directly set the pcb flag under the TCPIP core lock, + // bypassing lwip_setsockopt overhead (socket lookups, hook, switch cascade, refcounting). + if (level == IPPROTO_TCP && optname == TCP_NODELAY && optlen == sizeof(int) && optval != nullptr) { + LwIPLock lock; + if (esphome_lwip_set_nodelay(this->cached_sock_, *reinterpret_cast<const int *>(optval) != 0)) + return 0; + } +#endif return lwip_setsockopt(this->fd_, level, optname, optval, optlen); } int listen(int backlog) { return lwip_listen(this->fd_, backlog); } diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index c578a9aae9..a695fa396b 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -112,6 +112,7 @@ // LwIP headers must come first — they define netconn_callback, struct lwip_sock, etc. #include <lwip/api.h> #include <lwip/priv/sockets_priv.h> +#include <lwip/tcp.h> // FreeRTOS include paths differ: ESP-IDF uses freertos/ prefix, LibreTiny does not #ifdef USE_ESP32 #include <freertos/FreeRTOS.h> @@ -216,6 +217,21 @@ void esphome_lwip_hook_socket(struct lwip_sock *sock) { sock->conn->callback = esphome_socket_event_callback; } +bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable) { + if (sock == NULL || sock->conn == NULL) + return false; + if (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_TCP) + return false; + if (sock->conn->pcb.tcp == NULL) + return false; + if (enable) { + tcp_nagle_disable(sock->conn->pcb.tcp); + } else { + tcp_nagle_enable(sock->conn->pcb.tcp); + } + return true; +} + // Wake the main loop from another FreeRTOS task. NOT ISR-safe. void esphome_lwip_wake_main_loop(void) { TaskHandle_t task = s_main_loop_task; diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index 46c6b711cd..50706ba9f6 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -66,6 +66,13 @@ void esphome_lwip_wake_main_loop(void); /// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); +/// Set or clear TCP_NODELAY on a socket's tcp_pcb directly. +/// Must be called with the TCPIP core lock held (LwIPLock in C++). +/// This bypasses lwip_setsockopt() overhead (socket lookups, switch cascade, +/// hooks, refcounting) — just a direct pcb->flags bit set/clear. +/// Returns true if successful, false if sock/conn/pcb is NULL or the socket is not TCP. +bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable); + /// Wake the main loop task from any context (ISR, thread, or main loop). /// ESP32-only: uses xPortInIsrContext() to detect ISR context. /// LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths. From 1b7d0f9c0b6745f3610dc84b38dd7236fc5dced7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:21 -1000 Subject: [PATCH 1383/2030] [esp32_ble_client] Fix disconnect race that causes stuck connections (#14211) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- .../esp32_ble_client/ble_client_base.cpp | 43 ++++++++++++++++--- .../esp32_ble_client/ble_client_base.h | 17 +++++++- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 2f17334c77..9d6e079d92 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -27,6 +27,7 @@ static constexpr uint16_t MEDIUM_CONN_TIMEOUT = 800; // 800 * 10ms = 8s static constexpr uint16_t FAST_MIN_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms (BLE minimum) static constexpr uint16_t FAST_MAX_CONN_INTERVAL = 0x06; // 6 * 1.25ms = 7.5ms static constexpr uint16_t FAST_CONN_TIMEOUT = 1000; // 1000 * 10ms = 10s +static constexpr uint32_t DISCONNECTING_TIMEOUT = 10000; // 10s static const esp_bt_uuid_t NOTIFY_DESC_UUID = { .len = ESP_UUID_LEN_16, .uuid = @@ -62,6 +63,15 @@ void BLEClientBase::loop() { // will enable it again when a connection is needed. else if (this->state() == espbt::ClientState::IDLE) { this->disable_loop(); + } else if (this->state() == espbt::ClientState::DISCONNECTING && + (millis() - this->disconnecting_started_) > DISCONNECTING_TIMEOUT) { + ESP_LOGE(TAG, "[%d] [%s] Timeout waiting for CLOSE_EVT after disconnect, forcing IDLE", this->connection_index_, + this->address_str_); + // release_services() must be called before set_idle_() — if we entered DISCONNECTING + // via unconditional_disconnect() (which doesn't call release_services()), and ESP-IDF + // never delivered CLOSE_EVT/DISCONNECT_EVT, services would leak without this call. + this->release_services(); + this->set_idle_(); } } @@ -101,12 +111,16 @@ bool BLEClientBase::parse_device(const espbt::ESPBTDevice &device) { #endif void BLEClientBase::connect() { - // Prevent duplicate connection attempts + // Prevent duplicate connection attempts or connecting while still disconnecting if (this->state() == espbt::ClientState::CONNECTING || this->state() == espbt::ClientState::CONNECTED || this->state() == espbt::ClientState::ESTABLISHED) { ESP_LOGW(TAG, "[%d] [%s] Connection already in progress, state=%s", this->connection_index_, this->address_str_, espbt::client_state_to_string(this->state())); return; + } else if (this->state() == espbt::ClientState::DISCONNECTING) { + ESP_LOGW(TAG, "[%d] [%s] Cannot connect, still waiting for CLOSE_EVT to complete disconnect", + this->connection_index_, this->address_str_); + return; } ESP_LOGI(TAG, "[%d] [%s] 0x%02x Connecting", this->connection_index_, this->address_str_, this->remote_addr_type_); this->paired_ = false; @@ -174,7 +188,7 @@ void BLEClientBase::unconditional_disconnect() { this->set_address(0); this->set_state(espbt::ClientState::IDLE); } else { - this->set_state(espbt::ClientState::DISCONNECTING); + this->set_disconnecting_(); } } @@ -220,6 +234,7 @@ void BLEClientBase::log_connection_params_(const char *param_type) { void BLEClientBase::handle_connection_result_(esp_err_t ret) { if (ret) { this->log_gattc_warning_("esp_ble_gattc_open", ret); + // Don't use set_idle_() here — CONNECT_EVT never fired so conn_id_ is still UNSET_CONN_ID. this->set_state(espbt::ClientState::IDLE); } } @@ -311,15 +326,16 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ } if (param->open.status != ESP_GATT_OK && param->open.status != ESP_GATT_ALREADY_OPEN) { this->log_gattc_warning_("Connection open", param->open.status); - this->set_state(espbt::ClientState::IDLE); + // Connection was never established so CLOSE_EVT may not follow + this->set_idle_(); break; } if (this->want_disconnect_) { // Disconnect was requested after connecting started, // but before the connection was established. Now that we have // this->conn_id_ set, we can disconnect it. + // Don't reset conn_id_ here — CLOSE_EVT needs it to match and call set_idle_(). this->unconditional_disconnect(); - this->conn_id_ = UNSET_CONN_ID; break; } // MTU negotiation already started in ESP_GATTC_CONNECT_EVT @@ -363,8 +379,22 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ ESP_LOGD(TAG, "[%d] [%s] ESP_GATTC_DISCONNECT_EVT, reason 0x%02x", this->connection_index_, this->address_str_, param->disconnect.reason); } + // For active disconnects (esp_ble_gattc_close), CLOSE_EVT arrives before + // DISCONNECT_EVT. If CLOSE_EVT already transitioned us to IDLE, don't go + // backwards to DISCONNECTING — the connection is already fully cleaned up. + if (this->state() == espbt::ClientState::IDLE) { + this->log_event_("DISCONNECT_EVT after CLOSE_EVT, already IDLE"); + break; + } + // For passive disconnects (remote device disconnected or link lost), + // DISCONNECT_EVT arrives first. Don't transition to IDLE yet — wait for + // CLOSE_EVT to ensure the controller has fully freed resources (L2CAP + // channels, ATT resources, HCI connection handle). Transitioning to IDLE + // here would allow reconnection before cleanup is complete, causing the + // controller to reject the new connection (status=133) or crash with + // ASSERT_PARAM in lld_evt.c. this->release_services(); - this->set_state(espbt::ClientState::IDLE); + this->set_disconnecting_(); break; } @@ -387,8 +417,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ return false; this->log_gattc_lifecycle_event_("CLOSE"); this->release_services(); - this->set_state(espbt::ClientState::IDLE); - this->conn_id_ = UNSET_CONN_ID; + this->set_idle_(); break; } case ESP_GATTC_SEARCH_RES_EVT: { diff --git a/esphome/components/esp32_ble_client/ble_client_base.h b/esphome/components/esp32_ble_client/ble_client_base.h index af4f1b3029..4e0b22cc29 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.h +++ b/esphome/components/esp32_ble_client/ble_client_base.h @@ -113,11 +113,14 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { char address_str_[MAC_ADDRESS_PRETTY_BUFFER_SIZE]{}; esp_bd_addr_t remote_bda_; // 6 bytes - // Group 5: 2-byte types + // Group 5: 4-byte types + uint32_t disconnecting_started_{0}; + + // Group 6: 2-byte types uint16_t conn_id_{UNSET_CONN_ID}; uint16_t mtu_{23}; - // Group 6: 1-byte types and small enums + // Group 7: 1-byte types and small enums esp_ble_addr_type_t remote_addr_type_{BLE_ADDR_TYPE_PUBLIC}; espbt::ConnectionType connection_type_{espbt::ConnectionType::V1}; uint8_t connection_index_; @@ -137,6 +140,16 @@ class BLEClientBase : public espbt::ESPBTClient, public Component { void log_gattc_warning_(const char *operation, esp_err_t err); void log_connection_params_(const char *param_type); void handle_connection_result_(esp_err_t ret); + /// Transition to IDLE and reset conn_id — call when the connection is fully dead. + void set_idle_() { + this->set_state(espbt::ClientState::IDLE); + this->conn_id_ = UNSET_CONN_ID; + } + /// Transition to DISCONNECTING and start the safety timeout. + void set_disconnecting_() { + this->disconnecting_started_ = millis(); + this->set_state(espbt::ClientState::DISCONNECTING); + } // Compact error logging helpers to reduce flash usage void log_error_(const char *message); void log_error_(const char *message, int code); From 33475703da772d24e7a6df3e8a15160c5db53f8d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:34 -1000 Subject: [PATCH 1384/2030] [time] Fix settimeofday() failure on ESP8266 (#14707) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/time/real_time_clock.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/time/real_time_clock.cpp b/esphome/components/time/real_time_clock.cpp index 566344fa88..4e623942ac 100644 --- a/esphome/components/time/real_time_clock.cpp +++ b/esphome/components/time/real_time_clock.cpp @@ -88,16 +88,16 @@ void RealTimeClock::synchronize_epoch_(uint32_t epoch) { struct timeval timev { .tv_sec = static_cast<time_t>(epoch), .tv_usec = 0, }; +#ifdef USE_ESP8266 + // ESP8266 settimeofday() requires tz to be nullptr + int ret = settimeofday(&timev, nullptr); +#else struct timezone tz = {0, 0}; int ret = settimeofday(&timev, &tz); - if (ret != 0 && errno == EINVAL) { - // Some ESP8266 frameworks abort when timezone parameter is not NULL - // while ESP32 expects it not to be NULL - ret = settimeofday(&timev, nullptr); - } +#endif if (ret != 0) { - ESP_LOGW(TAG, "setimeofday() failed with code %d", ret); + ESP_LOGW(TAG, "settimeofday() failed with code %d", ret); } #endif auto time = this->now(); From c8cf9b74b104a1965897c16706ee30999d6fe25b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:15:48 -1000 Subject: [PATCH 1385/2030] [ota][socket] Fix ESP8266/RP2040 OTA timeout by using SO_RCVTIMEO instead of polling (#14675) --- .../components/esphome/ota/ota_esphome.cpp | 46 +++++++++++- esphome/components/socket/headers.h | 2 + .../components/socket/lwip_raw_tcp_impl.cpp | 71 +++++++++++++++++-- esphome/components/socket/lwip_raw_tcp_impl.h | 16 +++-- 4 files changed, 123 insertions(+), 12 deletions(-) diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index a1cdf59d2b..d8dbe2dee2 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -18,6 +18,7 @@ #include <cerrno> #include <cstdio> +#include <sys/time.h> namespace esphome { @@ -238,6 +239,31 @@ void ESPHomeOTAComponent::handle_data_() { /// and reboots on success. /// /// Authentication has already been handled in the non-blocking states AUTH_SEND/AUTH_READ. + /// + /// Socket I/O strategy: + /// + /// Before this function, the handshake states use non-blocking I/O: + /// read()/write() return immediately with EWOULDBLOCK if no data + /// loop() retries on next iteration (~16ms), no delay needed + /// + /// This function switches to blocking mode with SO_RCVTIMEO/SO_SNDTIMEO: + /// + /// Path | Wait mechanism | WDT strategy + /// --------------|------------------------|--------------------------- + /// Main read | SO_RCVTIMEO (2s block) | feed_wdt() only, no delay + /// readall_() | SO_RCVTIMEO (2s block) | feed_wdt() + delay(0) + /// writeall_() | SO_SNDTIMEO (2s block) | feed_wdt() + delay(1) + /// + /// readall_() uses delay(0) because SO_RCVTIMEO already waited — just yield. + /// writeall_() uses delay(1) because on raw TCP (ESP8266, RP2040) writes + /// never block (tcp_write returns immediately), so delay(1) prevents spinning. + /// + /// Platform details: + /// BSD sockets (ESP32): setblocking(true) makes read/write block + /// lwip sockets (LT): setblocking(true) makes read/write block + /// Raw TCP (8266, RP2040): setblocking is no-op; SO_RCVTIMEO uses + /// socket_delay()/socket_wake() in read(); + /// write() always returns immediately ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_ERROR_UNKNOWN; bool update_started = false; size_t total = 0; @@ -249,6 +275,14 @@ void ESPHomeOTAComponent::handle_data_() { size_t size_acknowledged = 0; #endif + // Set socket timeouts and blocking mode (see strategy table above) + struct timeval tv; + tv.tv_sec = 2; + tv.tv_usec = 0; + this->client_->setsockopt(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + this->client_->setsockopt(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + this->client_->setblocking(true); + // Acknowledge auth OK - 1 byte this->write_byte_(ota::OTA_RESPONSE_AUTH_OK); @@ -299,7 +333,8 @@ void ESPHomeOTAComponent::handle_data_() { ssize_t read = this->client_->read(buf, requested); if (read == -1) { if (this->would_block_(errno)) { - this->yield_and_feed_watchdog_(); + // read() already waited up to SO_RCVTIMEO for data, just feed WDT + App.feed_wdt(); continue; } ESP_LOGW(TAG, "Read err %d", errno); @@ -401,7 +436,9 @@ bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) { } else { at += read; } - this->yield_and_feed_watchdog_(); + // read() already waited via SO_RCVTIMEO, just yield without 1ms stall + App.feed_wdt(); + delay(0); } return true; @@ -422,10 +459,13 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno); return false; } + // EWOULDBLOCK: on raw TCP writes never block, delay(1) prevents spinning + this->yield_and_feed_watchdog_(); } else { at += written; + // write() may block up to SO_SNDTIMEO on BSD/lwip sockets, feed WDT + App.feed_wdt(); } - this->yield_and_feed_watchdog_(); } return true; } diff --git a/esphome/components/socket/headers.h b/esphome/components/socket/headers.h index 16e4d23d3b..0eece6480f 100644 --- a/esphome/components/socket/headers.h +++ b/esphome/components/socket/headers.h @@ -51,6 +51,8 @@ #define SO_REUSEADDR 0x0004 /* Allow local address reuse */ #define SO_KEEPALIVE 0x0008 /* keep connections alive */ #define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ #define SOL_SOCKET 0xfff /* options for socket level */ diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 1e03a4935c..96328e68c7 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -5,6 +5,7 @@ #include <cerrno> #include <cstring> +#include <sys/time.h> #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -81,7 +82,9 @@ void socket_delay(uint32_t ms) { s_socket_woke = false; return; } - s_socket_woke = false; + // Don't clear s_socket_woke here — if an IRQ fires between the check above + // and the while loop below, the while condition sees it immediately. Clearing + // here would lose that wake and sleep until the timer fires. s_delay_expired = false; // Set a one-shot timer to wake us after the timeout. // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. @@ -99,6 +102,7 @@ void socket_delay(uint32_t ms) { // Cancel timer if we woke early (socket data arrived before timeout) if (!s_delay_expired) cancel_alarm(alarm); + s_socket_woke = false; // consume the wake for next call } // No IRAM_ATTR equivalent needed: on RP2040, CYW43 async_context runs LWIP @@ -359,6 +363,18 @@ int LWIPRawCommon::getsockopt(int level, int optname, void *optval, socklen_t *o *optlen = 4; return 0; } + if (level == SOL_SOCKET && optname == SO_RCVTIMEO) { + if (*optlen < sizeof(struct timeval)) { + errno = EINVAL; + return -1; + } + uint32_t ms = this->recv_timeout_cs_ * 10; + auto *tv = reinterpret_cast<struct timeval *>(optval); + tv->tv_sec = ms / 1000; + tv->tv_usec = (ms % 1000) * 1000; + *optlen = sizeof(struct timeval); + return 0; + } if (level == IPPROTO_TCP && optname == TCP_NODELAY) { if (*optlen < 4) { errno = EINVAL; @@ -388,6 +404,21 @@ int LWIPRawCommon::setsockopt(int level, int optname, const void *optval, sockle // to prevent warnings return 0; } + if (level == SOL_SOCKET && optname == SO_RCVTIMEO) { + if (optlen < sizeof(struct timeval)) { + errno = EINVAL; + return -1; + } + const auto *tv = reinterpret_cast<const struct timeval *>(optval); + uint32_t ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + uint32_t cs = (ms + 9) / 10; // round up to nearest centisecond + this->recv_timeout_cs_ = cs > 255 ? 255 : static_cast<uint8_t>(cs); + return 0; + } + if (level == SOL_SOCKET && optname == SO_SNDTIMEO) { + // Raw TCP writes are non-blocking (tcp_write), so send timeout is a no-op. + return 0; + } if (level == IPPROTO_TCP && optname == TCP_NODELAY) { if (optlen != 4) { errno = EINVAL; @@ -518,8 +549,25 @@ err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { return ERR_OK; } -ssize_t LWIPRawImpl::read(void *buf, size_t len) { - LWIP_LOCK(); +void LWIPRawImpl::wait_for_data_() { + // Wait for data without holding LWIP_LOCK so recv_fn() can run on RP2040 + // (needs async_context lock). + // + // Loop until data arrives, connection closes, or the full timeout elapses. + // socket_delay() may return early due to other sockets waking the global + // socket_wake() flag, so we re-enter for the remaining time. + uint32_t timeout_ms = this->recv_timeout_cs_ * 10; + uint32_t start = millis(); + while (this->waiting_for_data_()) { + uint32_t elapsed = millis() - start; + if (elapsed >= timeout_ms) + break; + socket_delay(timeout_ms - elapsed); + } +} + +ssize_t LWIPRawImpl::read_locked_(void *buf, size_t len) { + // Caller must hold LWIP_LOCK. Copies available data from rx_buf_ into buf. if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -578,11 +626,26 @@ ssize_t LWIPRawImpl::read(void *buf, size_t len) { return read; } +ssize_t LWIPRawImpl::read(void *buf, size_t len) { + // See waiting_for_data_() for safety of unlocked reads. + if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { + this->wait_for_data_(); + } + + LWIP_LOCK(); + return this->read_locked_(buf, len); +} + ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { + // See waiting_for_data_() for safety of unlocked reads. + if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { + this->wait_for_data_(); + } + LWIP_LOCK(); // Hold for entire scatter-gather operation ssize_t ret = 0; for (int i = 0; i < iovcnt; i++) { - ssize_t err = this->read(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); + ssize_t err = this->read_locked_(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); if (err == -1) { if (ret != 0) { // if we already read some don't return an error diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index 95931afcf3..3c27d71062 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -57,6 +57,7 @@ class LWIPRawCommon { // instead use it for determining whether to call lwip_output bool nodelay_ = false; sa_family_t family_ = 0; + uint8_t recv_timeout_cs_ = 0; // SO_RCVTIMEO in centiseconds (0 = no timeout, max 2.55s) }; /// Connected socket implementation for LWIP raw TCP. @@ -107,11 +108,8 @@ class LWIPRawImpl : public LWIPRawCommon { errno = ECONNRESET; return -1; } - if (blocking) { - // blocking operation not supported - errno = EINVAL; - return -1; - } + // Raw TCP doesn't use a blocking flag directly. Blocking behavior + // is provided by SO_RCVTIMEO which makes read() wait via socket_delay(). return 0; } int loop() { return 0; } @@ -122,6 +120,14 @@ class LWIPRawImpl : public LWIPRawCommon { static err_t s_recv_fn(void *arg, struct tcp_pcb *pcb, struct pbuf *pb, err_t err); protected: + // True when the socket could receive data but none has arrived yet. + // Safe to call without LWIP_LOCK — only null-checks pointers and reads a bool, + // all atomic on ARM/Xtensa. A stale value is harmless: the caller either does + // an unnecessary wait (stale true) or skips it (stale false), and the + // authoritative recheck happens under LWIP_LOCK afterward. + bool waiting_for_data_() const { return this->rx_buf_ == nullptr && !this->rx_closed_ && this->pcb_ != nullptr; } + void wait_for_data_(); + ssize_t read_locked_(void *buf, size_t len); ssize_t internal_write_(const void *buf, size_t len); int internal_output_(); From 2ba807efe85c5e1216f793b2b1354576d38a49bc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:08 -1000 Subject: [PATCH 1386/2030] [adc] Fix PICO_VSYS_PIN compile error on RP2350 boards (#14724) --- esphome/components/adc/adc_sensor_rp2040.cpp | 7 +++++++ tests/components/adc/test.rp2040-pico2-ard.yaml | 11 +++++++++++ tests/components/spi/test.rp2040-pico2-ard.yaml | 6 ++++++ .../build_components_base.rp2040-pico2-ard.yaml | 15 +++++++++++++++ .../common/spi/rp2040-pico2-ard.yaml | 12 ++++++++++++ 5 files changed, 51 insertions(+) create mode 100644 tests/components/adc/test.rp2040-pico2-ard.yaml create mode 100644 tests/components/spi/test.rp2040-pico2-ard.yaml create mode 100644 tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml create mode 100644 tests/test_build_components/common/spi/rp2040-pico2-ard.yaml diff --git a/esphome/components/adc/adc_sensor_rp2040.cpp b/esphome/components/adc/adc_sensor_rp2040.cpp index 8496e0f41e..a79707e234 100644 --- a/esphome/components/adc/adc_sensor_rp2040.cpp +++ b/esphome/components/adc/adc_sensor_rp2040.cpp @@ -8,6 +8,13 @@ #endif // CYW43_USES_VSYS_PIN #include <hardware/adc.h> +// PICO_VSYS_PIN is defined in pico-sdk board headers (e.g. boards/pico2.h), +// but the Arduino framework's config_autogen.h includes a generic board header +// that doesn't define it. Provide the standard value (pin 29) as a fallback. +#ifndef PICO_VSYS_PIN +#define PICO_VSYS_PIN 29 // NOLINT(cppcoreguidelines-macro-usage) +#endif + namespace esphome { namespace adc { diff --git a/tests/components/adc/test.rp2040-pico2-ard.yaml b/tests/components/adc/test.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..4cc865bb5d --- /dev/null +++ b/tests/components/adc/test.rp2040-pico2-ard.yaml @@ -0,0 +1,11 @@ +sensor: + - id: my_sensor + platform: adc + pin: VCC + name: ADC Test sensor + update_interval: "1:01" + unit_of_measurement: "°C" + icon: "mdi:water-percent" + accuracy_decimals: 5 + setup_priority: -100 + force_update: true diff --git a/tests/components/spi/test.rp2040-pico2-ard.yaml b/tests/components/spi/test.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..81a8acafd8 --- /dev/null +++ b/tests/components/spi/test.rp2040-pico2-ard.yaml @@ -0,0 +1,6 @@ +substitutions: + clk_pin: GPIO2 + mosi_pin: GPIO3 + miso_pin: GPIO4 + +<<: !include common.yaml diff --git a/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml b/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..0922a5238e --- /dev/null +++ b/tests/test_build_components/build_components_base.rp2040-pico2-ard.yaml @@ -0,0 +1,15 @@ +esphome: + name: componenttestrp2040pico2ard + friendly_name: $component_name + +rp2040: + board: rpipico2 + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_test_file: $component_test_file diff --git a/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml b/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml new file mode 100644 index 0000000000..205beb6e1b --- /dev/null +++ b/tests/test_build_components/common/spi/rp2040-pico2-ard.yaml @@ -0,0 +1,12 @@ +# Common SPI configuration for RP2040 Pico 2 (RP2350) Arduino tests + +substitutions: + clk_pin: GPIO18 + mosi_pin: GPIO19 + miso_pin: GPIO16 + +spi: + - id: spi_bus + clk_pin: ${clk_pin} + mosi_pin: ${mosi_pin} + miso_pin: ${miso_pin} From cb4d1d1b5e2f6a354b4b873e444386a4fd4b2924 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:23 -1000 Subject: [PATCH 1387/2030] [api] Fix undefined behavior in noise handshake with empty rx buffer (#14722) --- esphome/components/api/api_frame_helper_noise.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 3e6ecf9dc3..f945253c89 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -258,10 +258,13 @@ APIError APINoiseFrameHelper::state_action_() { // ignore contents, may be used in future for flags // Resize for: existing prologue + 2 size bytes + frame data size_t old_size = this->prologue_.size(); - this->prologue_.resize(old_size + 2 + this->rx_buf_.size()); - this->prologue_[old_size] = (uint8_t) (this->rx_buf_.size() >> 8); - this->prologue_[old_size + 1] = (uint8_t) this->rx_buf_.size(); - std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), this->rx_buf_.size()); + size_t rx_size = this->rx_buf_.size(); + this->prologue_.resize(old_size + 2 + rx_size); + this->prologue_[old_size] = (uint8_t) (rx_size >> 8); + this->prologue_[old_size + 1] = (uint8_t) rx_size; + if (rx_size > 0) { + std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), rx_size); + } state_ = State::SERVER_HELLO; } From 23c7e0f8030d5caa5b07a9447293114639e89472 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:38 -1000 Subject: [PATCH 1388/2030] [uart] Allow hardware UART with single pin on RP2040 (#14725) --- .../components/uart/uart_component_rp2040.cpp | 37 +++++++++++++++---- tests/components/uart/test.rp2040-ard.yaml | 3 ++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 858f1a02dd..6f6f1fb96b 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -105,15 +105,34 @@ void RP2040UartComponent::setup() { } } + // Determine which hardware UART to use. A pin that is not specified + // should not prevent hardware UART selection — one-way UART is valid. + // When both pins are configured, both must be HW-capable and agree on UART number. + // When only one pin is configured (nullptr other), use that pin's HW UART. + // If a pin is configured but not HW-capable (inverted/invalid), fall back to SerialPIO. + int8_t hw_uart = -1; + const bool tx_configured = (this->tx_pin_ != nullptr); + const bool rx_configured = (this->rx_pin_ != nullptr); + + if (tx_configured && rx_configured) { + // Both pins configured — both must map to the same hardware UART + if (tx_hw != -1 && rx_hw != -1 && tx_hw == rx_hw) { + hw_uart = tx_hw; + } + } else if (tx_configured) { + hw_uart = tx_hw; + } else if (rx_configured) { + hw_uart = rx_hw; + } + #ifdef USE_LOGGER - if (tx_hw == rx_hw && logger::global_logger->get_uart() == tx_hw) { - ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", tx_hw); - tx_hw = -1; - rx_hw = -1; + if (hw_uart != -1 && logger::global_logger->get_uart() == hw_uart) { + ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", hw_uart); + hw_uart = -1; } #endif - if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) { + if (hw_uart == -1) { ESP_LOGV(TAG, "Using SerialPIO"); pin_size_t tx = this->tx_pin_ == nullptr ? NOPIN : this->tx_pin_->get_pin(); pin_size_t rx = this->rx_pin_ == nullptr ? NOPIN : this->rx_pin_->get_pin(); @@ -127,13 +146,15 @@ void RP2040UartComponent::setup() { } else { ESP_LOGV(TAG, "Using Hardware Serial"); SerialUART *serial; - if (tx_hw == 0) { + if (hw_uart == 0) { serial = &Serial1; } else { serial = &Serial2; } - serial->setTX(this->tx_pin_->get_pin()); - serial->setRX(this->rx_pin_->get_pin()); + if (this->tx_pin_ != nullptr) + serial->setTX(this->tx_pin_->get_pin()); + if (this->rx_pin_ != nullptr) + serial->setRX(this->rx_pin_->get_pin()); serial->setFIFOSize(this->rx_buffer_size_); serial->begin(this->baud_rate_, config); this->serial_ = serial; diff --git a/tests/components/uart/test.rp2040-ard.yaml b/tests/components/uart/test.rp2040-ard.yaml index 5eb2b533ea..1d5f91c6a7 100644 --- a/tests/components/uart/test.rp2040-ard.yaml +++ b/tests/components/uart/test.rp2040-ard.yaml @@ -23,3 +23,6 @@ uart: baud_rate: 115200 debug: debug_prefix: "[UART1] " + - id: uart_rx_only + rx_pin: 17 + baud_rate: 1200 From 14c3e2d9d948837a35aff984646bf55a9a225b33 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 07:16:53 -1000 Subject: [PATCH 1389/2030] [api] Fix heap-buffer-overflow in protobuf message dump for StringRef (#14721) --- esphome/components/api/api_pb2_dump.cpp | 2 +- script/api_protobuf/api_protobuf.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 740bf2e47f..5a53f0281f 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -13,7 +13,7 @@ namespace esphome::api { static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { - out.append(ref.c_str()); + out.append(ref.c_str(), ref.size()); } out.append("'"); } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index b4044c362c..dff6c7690a 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -642,7 +642,7 @@ class StringType(TypeInfo): # For SOURCE_BOTH, check if StringRef is set (sending) or use string (received) return ( f"if (!this->{self.field_name}_ref_.empty()) {{" - f' out.append("\'").append(this->{self.field_name}_ref_.c_str()).append("\'");' + f' out.append("\'").append(this->{self.field_name}_ref_.c_str(), this->{self.field_name}_ref_.size()).append("\'");' f"}} else {{" f' out.append("\'").append(this->{self.field_name}).append("\'");' f"}}" @@ -2705,7 +2705,7 @@ namespace esphome::api { static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); if (!ref.empty()) { - out.append(ref.c_str()); + out.append(ref.c_str(), ref.size()); } out.append("'"); } From 390bb0451ffd06cb4e2d88674c9af76bb88c25f0 Mon Sep 17 00:00:00 2001 From: Brian Kaufman <bkaufx@gmail.com> Date: Thu, 12 Mar 2026 16:23:29 -0700 Subject: [PATCH 1390/2030] [OTA] Stage exact uploaded size for ESP8266 web OTA (gzip fix) (#14741) --- esphome/components/ota/ota_backend_esp8266.cpp | 7 +++++-- esphome/components/ota/ota_backend_esp8266.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/ota/ota_backend_esp8266.cpp b/esphome/components/ota/ota_backend_esp8266.cpp index 1f9a77e426..93e6249fb3 100644 --- a/esphome/components/ota/ota_backend_esp8266.cpp +++ b/esphome/components/ota/ota_backend_esp8266.cpp @@ -105,6 +105,7 @@ OTAResponseTypes ESP8266OTABackend::begin(size_t image_size) { this->current_address_ = this->start_address_; this->image_size_ = image_size; + this->bytes_received_ = 0; this->buffer_len_ = 0; this->md5_set_ = false; @@ -140,6 +141,7 @@ OTAResponseTypes ESP8266OTABackend::write(uint8_t *data, size_t len) { size_t to_buffer = std::min(len - written, this->buffer_size_ - this->buffer_len_); memcpy(this->buffer_.get() + this->buffer_len_, data + written, to_buffer); this->buffer_len_ += to_buffer; + this->bytes_received_ += to_buffer; written += to_buffer; // If buffer is full, write to flash @@ -252,8 +254,8 @@ OTAResponseTypes ESP8266OTABackend::end() { } } - // Calculate actual bytes written - size_t actual_size = this->current_address_ - this->start_address_; + // Calculate actual bytes written (exact uploaded size, excluding flash write padding) + size_t actual_size = this->bytes_received_; // Check if any data was written if (actual_size == 0) { @@ -304,6 +306,7 @@ void ESP8266OTABackend::abort() { this->buffer_.reset(); this->buffer_len_ = 0; this->image_size_ = 0; + this->bytes_received_ = 0; esp8266::preferences_prevent_write(false); } diff --git a/esphome/components/ota/ota_backend_esp8266.h b/esphome/components/ota/ota_backend_esp8266.h index 6213289acc..b364e216a3 100644 --- a/esphome/components/ota/ota_backend_esp8266.h +++ b/esphome/components/ota/ota_backend_esp8266.h @@ -48,6 +48,7 @@ class ESP8266OTABackend final { uint32_t start_address_{0}; uint32_t current_address_{0}; size_t image_size_{0}; + size_t bytes_received_{0}; md5::MD5Digest md5_{}; uint8_t expected_md5_[16]; // Fixed-size buffer for 128-bit (16-byte) MD5 digest From 93be53978925e7eb76035a7ca0356282bea7ae21 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 13:28:25 -1000 Subject: [PATCH 1391/2030] [light] Fix ambiguous set_effect overload for const char* (#14732) --- .../addressable_light/addressable_light_display.h | 2 +- esphome/components/light/light_call.cpp | 2 +- esphome/components/light/light_call.h | 2 ++ tests/components/light/common.yaml | 6 ++++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/esphome/components/addressable_light/addressable_light_display.h b/esphome/components/addressable_light/addressable_light_display.h index 53f8604b7d..d9b8680547 100644 --- a/esphome/components/addressable_light/addressable_light_display.h +++ b/esphome/components/addressable_light/addressable_light_display.h @@ -33,7 +33,7 @@ class AddressableLightDisplay : public display::DisplayBuffer { // - Save the current effect index. this->last_effect_index_ = light_state_->get_current_effect_index(); // - Disable any current effect. - light_state_->make_call().set_effect(0).perform(); + light_state_->make_call().set_effect(uint32_t{0}).perform(); } } enabled_ = enabled; diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 14cd0e92f6..cd45994f62 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -506,7 +506,7 @@ color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() { LightCall &LightCall::set_effect(const char *effect, size_t len) { if (len == 4 && strncasecmp(effect, "none", 4) == 0) { - this->set_effect(0); + this->set_effect(uint32_t{0}); return *this; } diff --git a/esphome/components/light/light_call.h b/esphome/components/light/light_call.h index 0926ab6108..0eb1785239 100644 --- a/esphome/components/light/light_call.h +++ b/esphome/components/light/light_call.h @@ -130,6 +130,8 @@ class LightCall { LightCall &set_effect(optional<std::string> effect); /// Set the effect of the light by its name. LightCall &set_effect(const std::string &effect) { return this->set_effect(effect.data(), effect.size()); } + /// Set the effect of the light by its name (const char * overload to resolve ambiguity). + LightCall &set_effect(const char *effect) { return this->set_effect(effect, strlen(effect)); } /// Set the effect of the light by its name and length (zero-copy from API). LightCall &set_effect(const char *effect, size_t len); /// Set the effect of the light by its internal index number (only for internal use). diff --git a/tests/components/light/common.yaml b/tests/components/light/common.yaml index e5fab62a79..e1216e7b60 100644 --- a/tests/components/light/common.yaml +++ b/tests/components/light/common.yaml @@ -60,6 +60,12 @@ esphome: } } + # Test set_effect with const char* doesn't cause ambiguous overload (issue #14728) + - lambda: |- + auto call = id(test_monochromatic_light).turn_on(); + call.set_effect("None"); + call.perform(); + - light.toggle: test_binary_light - light.turn_off: test_rgb_light - light.turn_on: From 0b99e8f08d0cca47ccc49e93f0e063b7315cd80b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:47:16 -1000 Subject: [PATCH 1392/2030] [rp2040] Use full flash for sketch in testing mode (#14747) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/rp2040/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 276187b273..71e5f1488c 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -203,7 +203,12 @@ async def to_code(config): cg.add_build_flag(f"-Wl,--wrap={symbol}") cg.add_platformio_option("board_build.core", "earlephilhower") - cg.add_platformio_option("board_build.filesystem_size", "1m") + # In testing mode, use all flash for sketch to allow linking grouped component tests. + # Real RP2040 hardware uses 1MB filesystem + 1MB sketch, but CI tests may combine + # many components that exceed the 1MB sketch partition. + cg.add_platformio_option( + "board_build.filesystem_size", "0m" if CORE.testing_mode else "1m" + ) ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] cg.add_define( From 910784ca841d1a117285df0eb8ba408fe6798b44 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:06 -1000 Subject: [PATCH 1393/2030] [debug] Fix missing reset reason for RP2040/RP2350 (#14740) --- esphome/components/debug/debug_rp2040.cpp | 64 +++++++++++++++++++++-- esphome/core/helpers.h | 22 ++++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index c9d41942db..8dc84a2673 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -1,23 +1,81 @@ #include "debug_component.h" #ifdef USE_RP2040 +#include "esphome/core/defines.h" #include "esphome/core/log.h" #include <Arduino.h> +#include <hardware/watchdog.h> +#if defined(PICO_RP2350) +#include <hardware/structs/powman.h> +#else +#include <hardware/structs/vreg_and_chip_reset.h> +#endif +#ifdef USE_RP2040_CRASH_HANDLER +#include "esphome/components/rp2040/crash_handler.h" +#endif namespace esphome { namespace debug { static const char *const TAG = "debug"; -const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { + char *buf = buffer.data(); + const size_t size = RESET_REASON_BUFFER_SIZE; + size_t pos = 0; + +#if defined(PICO_RP2350) + uint32_t chip_reset = powman_hw->chip_reset; + if (chip_reset & 0x04000000) // HAD_GLITCH_DETECT + pos = buf_append_str(buf, size, pos, "Power supply glitch|"); + if (chip_reset & 0x00040000) // HAD_RUN_LOW + pos = buf_append_str(buf, size, pos, "RUN pin|"); + if (chip_reset & 0x00020000) // HAD_BOR + pos = buf_append_str(buf, size, pos, "Brown-out|"); + if (chip_reset & 0x00010000) // HAD_POR + pos = buf_append_str(buf, size, pos, "Power-on reset|"); +#else + uint32_t chip_reset = vreg_and_chip_reset_hw->chip_reset; + if (chip_reset & 0x00010000) // HAD_RUN + pos = buf_append_str(buf, size, pos, "RUN pin|"); + if (chip_reset & 0x00000100) // HAD_POR + pos = buf_append_str(buf, size, pos, "Power-on reset|"); +#endif + + if (watchdog_caused_reboot()) { + bool handled = false; +#ifdef USE_RP2040_CRASH_HANDLER + if (rp2040::crash_handler_has_data()) { + pos = buf_append_str(buf, size, pos, "Crash (HardFault)|"); + handled = true; + } +#endif + if (!handled) { + if (watchdog_enable_caused_reboot()) { + pos = buf_append_str(buf, size, pos, "Watchdog timeout|"); + } else { + pos = buf_append_str(buf, size, pos, "Software reset|"); + } + } + } + + // Remove trailing '|' + if (pos > 0 && buf[pos - 1] == '|') { + buf[pos - 1] = '\0'; + } else if (pos == 0) { + return "Unknown"; + } + + return buf; +} const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } -uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); } +uint32_t DebugComponent::get_free_heap_() { return ::rp2040.getFreeHeap(); } size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> buffer, size_t pos) { constexpr size_t size = DEVICE_INFO_BUFFER_SIZE; char *buf = buffer.data(); - uint32_t cpu_freq = rp2040.f_cpu(); + uint32_t cpu_freq = ::rp2040.f_cpu(); ESP_LOGD(TAG, "CPU Frequency: %" PRIu32, cpu_freq); pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32, cpu_freq); diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 70ac1574f0..b2517e2d7a 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -942,6 +942,28 @@ __attribute__((format(printf, 4, 5))) inline size_t buf_append_printf(char *buf, } #endif +/// Safely append a string to buffer without format parsing, returning new position (capped at size). +/// More efficient than buf_append_printf for plain string literals. +/// @param buf Output buffer +/// @param size Total buffer size +/// @param pos Current position in buffer +/// @param str String to append (must not be null) +/// @return New position after appending (capped at size on overflow) +inline size_t buf_append_str(char *buf, size_t size, size_t pos, const char *str) { + if (pos >= size) { + return size; + } + size_t remaining = size - pos - 1; // reserve space for null terminator + size_t len = strlen(str); + if (len > remaining) { + len = remaining; + } + memcpy(buf + pos, str, len); + pos += len; + buf[pos] = '\0'; + return pos; +} + /// Concatenate a name with a separator and suffix using an efficient stack-based approach. /// This avoids multiple heap allocations during string construction. /// Maximum name length supported is 120 characters for friendly names. From c263c2c382292eb33bec5ed560620964b6a25c34 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:29 -1000 Subject: [PATCH 1394/2030] [captive_portal] Fix captive portal inaccessible when web_server auth is configured (#14734) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/captive_portal/captive_portal.cpp | 4 ++-- esphome/components/web_server_base/web_server_base.cpp | 4 ++++ esphome/components/web_server_base/web_server_base.h | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/esphome/components/captive_portal/captive_portal.cpp b/esphome/components/captive_portal/captive_portal.cpp index 5af6ab29a2..183f16c5f8 100644 --- a/esphome/components/captive_portal/captive_portal.cpp +++ b/esphome/components/captive_portal/captive_portal.cpp @@ -61,7 +61,7 @@ void CaptivePortal::handle_wifisave(AsyncWebServerRequest *request) { // Defer save to main loop thread to avoid NVS operations from HTTP thread this->defer([ssid, psk]() { wifi::global_wifi_component->save_wifi_sta(ssid.c_str(), psk.c_str()); }); #endif - request->redirect(ESPHOME_F("/?save")); + request->send(200, ESPHOME_F("text/plain"), ESPHOME_F("Saved. Connecting...")); } void CaptivePortal::setup() { @@ -71,7 +71,7 @@ void CaptivePortal::setup() { void CaptivePortal::start() { this->base_->init(); if (!this->initialized_) { - this->base_->add_handler(this); + this->base_->add_handler_without_auth(this); } network::IPAddress ip = wifi::global_wifi_component->wifi_soft_ap_ip(); diff --git a/esphome/components/web_server_base/web_server_base.cpp b/esphome/components/web_server_base/web_server_base.cpp index dbbcd10d8d..3e1baf34ba 100644 --- a/esphome/components/web_server_base/web_server_base.cpp +++ b/esphome/components/web_server_base/web_server_base.cpp @@ -11,6 +11,10 @@ void WebServerBase::add_handler(AsyncWebHandler *handler) { handler = new internal::AuthMiddlewareHandler(handler, &credentials_); } #endif + this->add_handler_without_auth(handler); +} + +void WebServerBase::add_handler_without_auth(AsyncWebHandler *handler) { this->handlers_.push_back(handler); if (this->server_ != nullptr) { this->server_->addHandler(handler); diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 54421c851e..48e13ad71e 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -122,6 +122,14 @@ class WebServerBase { #endif void add_handler(AsyncWebHandler *handler); + /** + * WARNING: Registers a handler that bypasses the USE_WEBSERVER_AUTH middleware. + * + * This should only be used for endpoints that are intentionally unauthenticated + * (for example, captive portal or very limited-status endpoints). For normal + * endpoints that should respect web server authentication, use add_handler(). + */ + void add_handler_without_auth(AsyncWebHandler *handler); void set_port(uint16_t port) { port_ = port; } uint16_t get_port() const { return port_; } From dc5032f72fa5571eebb2381c208f9b4deb33f93d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:41 -1000 Subject: [PATCH 1395/2030] [water_heater] Set OPERATION_MODE feature flag when modes are configured (#14748) --- .../template/water_heater/template_water_heater.cpp | 1 + tests/integration/test_water_heater_template.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/template/water_heater/template_water_heater.cpp b/esphome/components/template/water_heater/template_water_heater.cpp index 73081d204b..092df6fdca 100644 --- a/esphome/components/template/water_heater/template_water_heater.cpp +++ b/esphome/components/template/water_heater/template_water_heater.cpp @@ -26,6 +26,7 @@ water_heater::WaterHeaterTraits TemplateWaterHeater::traits() { if (!this->supported_modes_.empty()) { traits.set_supported_modes(this->supported_modes_); + traits.add_feature_flags(water_heater::WATER_HEATER_SUPPORTS_OPERATION_MODE); } traits.set_supports_current_temperature(true); diff --git a/tests/integration/test_water_heater_template.py b/tests/integration/test_water_heater_template.py index 096d4c8461..d63d1d6984 100644 --- a/tests/integration/test_water_heater_template.py +++ b/tests/integration/test_water_heater_template.py @@ -102,7 +102,11 @@ async def test_water_heater_template( f"Expected target temp 60.0, got {initial_state.target_temperature}" ) - # Verify supported features: away mode and on/off (fixture has away + is_on lambdas) + # Verify supported features: operation mode, away mode, and on/off + assert ( + test_water_heater.supported_features + & WaterHeaterFeature.SUPPORTS_OPERATION_MODE + ) != 0, "Expected SUPPORTS_OPERATION_MODE in supported_features" assert ( test_water_heater.supported_features & WaterHeaterFeature.SUPPORTS_AWAY_MODE ) != 0, "Expected SUPPORTS_AWAY_MODE in supported_features" From aacbaab5f800e26c7f614ec641f061dfcda4ce77 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:48:55 -1000 Subject: [PATCH 1396/2030] [wifi] Reject EAP/WPA2 Enterprise config on unsupported platforms (#14746) --- esphome/components/wifi/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 2808d31311..480ccd65c5 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -166,6 +166,7 @@ TTLS_PHASE_2 = { } EAP_AUTH_SCHEMA = cv.All( + cv.only_on([Platform.ESP32, Platform.ESP8266]), cv.Schema( { cv.Optional(CONF_IDENTITY): cv.string_strict, From b0447dc52165abf25b18281bb0e5277e50ba896a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:49:07 -1000 Subject: [PATCH 1397/2030] [light] Fix binary light spamming 'brightness not supported' warning with strobe effect (#14735) --- esphome/components/light/light_call.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index cd45994f62..0b2d391fd6 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -214,7 +214,14 @@ LightColorValues LightCall::validate_() { if (this->has_brightness() && this->brightness_ == 0.0f) { this->state_ = false; this->set_flag_(FLAG_HAS_STATE); - this->brightness_ = 1.0f; + if (color_mode & ColorCapability::BRIGHTNESS) { + // Reset brightness so the light has nonzero brightness when turned back on. + this->brightness_ = 1.0f; + } else { + // Light doesn't support brightness; clear the flag to avoid a spurious + // "brightness not supported" warning during capability validation. + this->clear_flag_(FLAG_HAS_BRIGHTNESS); + } } // Set color brightness to 100% if currently zero and a color is set. From 039efdb02a765f554e33f0d2c897cd69fa9fd581 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 14:53:46 -1000 Subject: [PATCH 1398/2030] [i2c] Fix RP2040 I2C bus selection based on pin assignment (#14745) --- esphome/components/i2c/__init__.py | 37 ++++++++++++++++++++++ esphome/components/i2c/i2c_bus_arduino.cpp | 10 +++--- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index de3f2be674..1684f479ba 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -93,11 +93,31 @@ def _bus_declare_type(value): raise NotImplementedError +def _rp2040_i2c_controller(pin): + """Return the I2C controller number (0 or 1) for a given RP2040/RP2350 GPIO pin. + + See RP2040 datasheet Table 2 (section 1.4.3, "GPIO Functions"): + https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + See RP2350 datasheet Table 7 (section 9.4, "Function Select"): + https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf + """ + return (pin // 2) % 2 + + def validate_config(config): if CORE.is_esp32: return cv.require_framework_version( esp_idf=cv.Version(5, 4, 2), esp32_arduino=cv.Version(3, 2, 1) )(config) + if CORE.is_rp2040: + sda_controller = _rp2040_i2c_controller(config[CONF_SDA]) + scl_controller = _rp2040_i2c_controller(config[CONF_SCL]) + if sda_controller != scl_controller: + raise cv.Invalid( + f"SDA pin GPIO{config[CONF_SDA]} is on I2C{sda_controller} but " + f"SCL pin GPIO{config[CONF_SCL]} is on I2C{scl_controller}. " + f"Both pins must be on the same I2C controller." + ) return config @@ -146,6 +166,23 @@ def _final_validate(config): full_config = fv.full_config.get()[CONF_I2C] if CORE.using_zephyr and len(full_config) > 1: raise cv.Invalid("Second i2c is not implemented on Zephyr yet") + if CORE.is_rp2040: + if len(full_config) > 2: + raise cv.Invalid( + "The maximum number of I2C interfaces for RP2040/RP2350 is 2" + ) + if len(full_config) > 1: + controllers = [ + _rp2040_i2c_controller(conf[CONF_SDA]) for conf in full_config + ] + if len(set(controllers)) != len(controllers): + raise cv.Invalid( + "Multiple I2C buses are configured to use the same I2C controller. " + "Each bus must use pins on a different controller. " + "The I2C controller is determined by (gpio / 2) % 2: " + "even pin pairs (0-1, 4-5, 8-9, ...) use I2C0, " + "odd pin pairs (2-3, 6-7, 10-11, ...) use I2C1." + ) if CORE.is_esp32 and get_esp32_variant() in ESP32_I2C_CAPABILITIES: variant = get_esp32_variant() max_num = ESP32_I2C_CAPABILITIES[variant]["NUM"] diff --git a/esphome/components/i2c/i2c_bus_arduino.cpp b/esphome/components/i2c/i2c_bus_arduino.cpp index 5120eb4c00..47a06abe9e 100644 --- a/esphome/components/i2c/i2c_bus_arduino.cpp +++ b/esphome/components/i2c/i2c_bus_arduino.cpp @@ -20,12 +20,14 @@ void ArduinoI2CBus::setup() { #if defined(USE_ESP8266) wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory) #elif defined(USE_RP2040) - static bool first = true; - if (first) { + // Select Wire instance based on pin assignment, not definition order. + // I2C controller = (gpio / 2) % 2: even pairs (0-1,4-5,...) → I2C0, odd pairs (2-3,6-7,...) → I2C1 + // RP2040 datasheet Table 2 (section 1.4.3): https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf + // RP2350 datasheet Table 7 (section 9.4): https://datasheets.raspberrypi.com/rp2350/rp2350-datasheet.pdf + if ((this->sda_pin_ / 2) % 2 == 0) { wire_ = &Wire; - first = false; } else { - wire_ = &Wire1; // NOLINT(cppcoreguidelines-owning-memory) + wire_ = &Wire1; } #endif From 1ab1534028ef2052825e09301f26bb3e02f45d82 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 15:12:22 -1000 Subject: [PATCH 1399/2030] [mdns] Fix RP2040 mDNS not restarting after WiFi reconnect (#14737) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/mdns/mdns_component.h | 4 +++ esphome/components/mdns/mdns_rp2040.cpp | 32 ++++++++++++++++++---- esphome/components/wifi/__init__.py | 7 ----- esphome/components/wifi/wifi_component.cpp | 14 ---------- esphome/components/wifi/wifi_component.h | 4 --- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/esphome/components/mdns/mdns_component.h b/esphome/components/mdns/mdns_component.h index 13c8ccf288..47cad4bf71 100644 --- a/esphome/components/mdns/mdns_component.h +++ b/esphome/components/mdns/mdns_component.h @@ -129,6 +129,10 @@ class MDNSComponent final : public Component { #endif #ifdef USE_MDNS_STORE_SERVICES StaticVector<MDNSService, MDNS_SERVICE_COUNT> services_{}; +#endif +#ifdef USE_RP2040 + bool was_connected_{false}; + bool initialized_{false}; #endif void compile_records_(StaticVector<MDNSService, MDNS_SERVICE_COUNT> &services, char *mac_address_buf); }; diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index 05d991c1fa..c0b22aa84f 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -36,12 +36,32 @@ static void register_rp2040(MDNSComponent *, StaticVector<MDNSService, MDNS_SERV } void MDNSComponent::setup() { - this->setup_buffers_and_register_(register_rp2040); - // Schedule MDNS.update() via set_interval() instead of overriding loop(). - // This removes the component from the per-iteration loop list entirely, - // eliminating virtual dispatch overhead on every main loop cycle. - // See MDNS_UPDATE_INTERVAL_MS comment in mdns_component.h for safety analysis. - this->set_interval(MDNS_UPDATE_INTERVAL_MS, []() { MDNS.update(); }); + // RP2040's LEAmDNS library registers a LwipIntf::stateUpCB() callback to restart + // mDNS when the network interface reconnects. However, stateUpCB() is stubbed out + // in arduino-pico's LwipIntfCB.cpp because the original ESP8266 implementation used + // schedule_function() which doesn't exist in arduino-pico, and the callback can't + // safely run directly since netif status callbacks fire from IRQ context + // (PICO_CYW43_ARCH_THREADSAFE_BACKGROUND) while _restart() allocates UDP sockets. + // + // Workaround: defer MDNS.begin() and service registration until the network is + // connected (has an IP), then call notifyAPChange() on subsequent reconnects to + // restart mDNS probing and announcing — all from main loop context so it's + // thread-safe. + this->set_interval(MDNS_UPDATE_INTERVAL_MS, [this]() { + bool connected = network::is_connected(); + if (connected && !this->was_connected_) { + if (!this->initialized_) { + this->setup_buffers_and_register_(register_rp2040); + this->initialized_ = true; + } else { + MDNS.notifyAPChange(); + } + } + this->was_connected_ = connected; + if (this->initialized_) { + MDNS.update(); + } + }); } void MDNSComponent::on_shutdown() { diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 480ccd65c5..9f73b1cc6f 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -563,13 +563,6 @@ async def to_code(config): cg.add_library("ESP8266WiFi", None) elif CORE.is_rp2040: cg.add_library("WiFi", None) - # RP2040's mDNS library (LEAmDNS) relies on LwipIntf::stateUpCB() to restart - # mDNS when the network interface reconnects. However, this callback is disabled - # in the arduino-pico framework. As a workaround, we block component setup until - # WiFi is connected via can_proceed(), ensuring mDNS.begin() is called with an - # active connection. This define enables the loop priority sorting infrastructure - # used during the setup blocking phase. - cg.add_define("USE_LOOP_PRIORITY") if CORE.is_esp32: if config[CONF_ENABLE_BTM] or config[CONF_ENABLE_RRM]: diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 60764955cc..09f883ed61 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2109,20 +2109,6 @@ void WiFiComponent::retry_connect() { } } -#ifdef USE_RP2040 -// RP2040's mDNS library (LEAmDNS) relies on LwipIntf::stateUpCB() to restart -// mDNS when the network interface reconnects. However, this callback is disabled -// in the arduino-pico framework. As a workaround, we block component setup until -// WiFi is connected, ensuring mDNS.begin() is called with an active connection. - -bool WiFiComponent::can_proceed() { - if (!this->has_sta() || this->state_ == WIFI_COMPONENT_STATE_DISABLED || this->ap_setup_) { - return true; - } - return this->is_connected_(); -} -#endif - void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } bool WiFiComponent::is_connected_() const { return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index f340b708c9..883cc1344b 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -437,10 +437,6 @@ class WiFiComponent : public Component { void retry_connect(); -#ifdef USE_RP2040 - bool can_proceed() override; -#endif - void set_reboot_timeout(uint32_t reboot_timeout); bool is_connected() const { return this->connected_; } From 45e40223ac3a32fdca7a535f35da73b6d866f29b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 12 Mar 2026 15:37:46 -1000 Subject: [PATCH 1400/2030] [rp2040] Fix compiler warnings in crash_handler and mdns (#14739) --- esphome/components/mdns/mdns_rp2040.cpp | 5 +++++ esphome/components/rp2040/crash_handler.cpp | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/esphome/components/mdns/mdns_rp2040.cpp b/esphome/components/mdns/mdns_rp2040.cpp index c0b22aa84f..88f707afd3 100644 --- a/esphome/components/mdns/mdns_rp2040.cpp +++ b/esphome/components/mdns/mdns_rp2040.cpp @@ -7,7 +7,12 @@ #include "esphome/core/log.h" #include "mdns_component.h" +// Arduino-Pico's PolledTimeout.h (pulled in by ESP8266mDNS.h) redefines IRAM_ATTR to empty. +// Save and restore our definition around the include to avoid a redefinition warning. +#pragma push_macro("IRAM_ATTR") +#undef IRAM_ATTR #include <ESP8266mDNS.h> +#pragma pop_macro("IRAM_ATTR") namespace esphome::mdns { diff --git a/esphome/components/rp2040/crash_handler.cpp b/esphome/components/rp2040/crash_handler.cpp index 1f579c2d18..f9eb42a0f8 100644 --- a/esphome/components/rp2040/crash_handler.cpp +++ b/esphome/components/rp2040/crash_handler.cpp @@ -57,14 +57,14 @@ static const char *const TAG = "rp2040.crash"; // Placed in .noinit so BSS zero-init cannot race with crash_handler_read_and_clear(). // The valid field is explicitly cleared in crash_handler_read_and_clear() instead. -static struct { +static struct CrashData { bool valid; uint32_t pc; uint32_t lr; uint32_t sp; uint32_t backtrace[MAX_BACKTRACE]; uint8_t backtrace_count; -} __attribute__((section(".noinit"))) s_crash_data; +} s_crash_data __attribute__((section(".noinit"))); bool crash_handler_has_data() { return s_crash_data.valid; } From 18b54f075ee02f1f36da37681968b147554f89ba Mon Sep 17 00:00:00 2001 From: Kjell Braden <afflux@pentabarf.de> Date: Fri, 13 Mar 2026 14:18:42 +0100 Subject: [PATCH 1401/2030] [runtime_image] fix BMP parsing (#14762) --- .../components/runtime_image/bmp_decoder.h | 4 + .../fixtures/online_image_bmp.yaml | 27 ++++ tests/integration/test_online_image_bmp.py | 119 ++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 tests/integration/fixtures/online_image_bmp.yaml create mode 100644 tests/integration/test_online_image_bmp.py diff --git a/esphome/components/runtime_image/bmp_decoder.h b/esphome/components/runtime_image/bmp_decoder.h index 73e54f5430..a52a561584 100644 --- a/esphome/components/runtime_image/bmp_decoder.h +++ b/esphome/components/runtime_image/bmp_decoder.h @@ -26,6 +26,10 @@ class BmpDecoder : public ImageDecoder { int HOT decode(uint8_t *buffer, size_t size) override; bool is_finished() const override { + if (this->bits_per_pixel_ == 0) { + // header not yet received, so dimensions not yet determined + return false; + } // BMP is finished when we've decoded all pixel data return this->paint_index_ >= static_cast<size_t>(this->width_ * this->height_); } diff --git a/tests/integration/fixtures/online_image_bmp.yaml b/tests/integration/fixtures/online_image_bmp.yaml new file mode 100644 index 0000000000..e36514e9ae --- /dev/null +++ b/tests/integration/fixtures/online_image_bmp.yaml @@ -0,0 +1,27 @@ +esphome: + name: online-image-bmp + +host: + +http_request: + +display: + +online_image: + - url: http://127.0.0.1:HTTP_PORT/foo.bmp + id: myimg + format: BMP + type: RGB + on_download_finished: + logger.log: + format: "download finished. cache hit: %u" + args: [cached] + +api: + actions: + - action: fetch_image + then: + - component.update: myimg + +logger: + level: DEBUG diff --git a/tests/integration/test_online_image_bmp.py b/tests/integration/test_online_image_bmp.py new file mode 100644 index 0000000000..7c32154fdd --- /dev/null +++ b/tests/integration/test_online_image_bmp.py @@ -0,0 +1,119 @@ +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + +# black 8x8 RGB BMP, generated with +# from PIL import Image +# from io import BytesIO +# b = BytesIO() +# img = Image.new("RGB", (8, 8)) +# img.save(b, format="BMP") +# b.getvalue() +BMP_IMAGE = b"BM\xf6\x00\x00\x00\x00\x00\x00\x006\x00\x00\x00(\x00\x00\x00\x08\x00\x00\x00\x08\x00\x00\x00\x01\x00\x18\x00\x00\x00\x00\x00\xc0\x00\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +LEN_BMP_IMAGE = len(BMP_IMAGE) + + +def handle_http(http_request_future): + async def handler(reader, writer): + try: + async with asyncio.timeout(1.0): + data = await reader.readuntil(b"\r\n") + + # ensure our request matches the expectation + expected_request = b"GET /foo.bmp HTTP/1.1\r\n" + assert data[: len(expected_request)] == expected_request + + # consume rest of request + async with asyncio.timeout(1.0): + data = await reader.readuntil(b"\r\n\r\n") + + http_request_future.set_result(True) + + http_response = [ + b"HTTP/1.1 200 OK", + b"Content-Length: %d" % LEN_BMP_IMAGE, + b"Content-Type: text/plain", + b"Connection: close", + b"", + b"", + ] + writer.write(b"\r\n".join(http_response)) + await writer.drain() + + writer.write(BMP_IMAGE) + + await writer.drain() + except Exception as exc: + if not http_request_future.done(): + http_request_future.set_exception(exc) + raise + finally: + writer.close() + + return handler + + +@pytest.mark.asyncio +async def test_online_image_bmp( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Esphome shouldn't block the main loop when a http response is slow""" + loop = asyncio.get_running_loop() + + # Track http request + http_request_future = loop.create_future() + download_finished_future = loop.create_future() + downloaded_bytes_future = loop.create_future() + + def check_output(line: str) -> None: + """Check log output for expected messages.""" + + if match := re.search(r"Image fully downloaded, (\d+) bytes", line): + downloaded_bytes_future.set_result(int(match.group(1))) + + if "download finished" in line: + download_finished_future.set_result(True) + + server = await asyncio.start_server( + handle_http(http_request_future), "127.0.0.1", 0 + ) + http_server_port = server.sockets[0].getsockname()[1] + + config = yaml_config.replace("HTTP_PORT", str(http_server_port)) + + # Run with log monitoring + async with ( + server, + run_compiled(config, line_callback=check_output), + api_client_connected() as client, + ): + # Verify device info + + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "online-image-bmp" + + # List services to find our test service + _, services = await client.list_entities_services() + + # Find test service + request_service = next((s for s in services if s.name == "fetch_image"), None) + + assert request_service is not None, "fetch_image service not found" + + await client.execute_service(request_service, {}) + + async with asyncio.timeout(0.1): + await http_request_future + + async with asyncio.timeout(0.5): + numbytes = await downloaded_bytes_future + assert numbytes == LEN_BMP_IMAGE + await download_finished_future From e9c265914768a3c5fea24b6c2fb28eeb211cfb90 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 03:20:50 -1000 Subject: [PATCH 1402/2030] [select] Fix -Wmaybe-uninitialized warnings on ESP8266 (#14759) --- esphome/components/select/select_call.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 45fb42c116..83f5052fc8 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -41,7 +41,7 @@ SelectCall &SelectCall::with_index(size_t index) { this->operation_ = SELECT_OP_SET; if (index >= this->parent_->size()) { ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", this->parent_->get_name().c_str(), index); - this->index_ = {}; // Store nullopt for invalid index + this->index_ = nullopt; // Store nullopt for invalid index } else { this->index_ = index; } @@ -52,7 +52,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { const auto &options = this->parent_->traits.get_options(); if (options.empty()) { ESP_LOGW(TAG, "'%s' - Select has no options", name); - return {}; + return nullopt; } if (this->operation_ == SELECT_OP_FIRST) { @@ -67,7 +67,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { ESP_LOGD(TAG, "'%s' - Setting", name); if (!this->index_.has_value()) { ESP_LOGW(TAG, "'%s' - No option set", name); - return {}; + return nullopt; } return this->index_; } @@ -96,7 +96,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { return active_index + 1; } - return {}; // Can't navigate further without cycling + return nullopt; // Can't navigate further without cycling } void SelectCall::perform() { From 49107f217463b8ceb9200fd3bb51aa38d1bb9527 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 07:37:30 -1000 Subject: [PATCH 1403/2030] [api] Increase log Nagle coalescing on all platforms except ESP8266 (#14752) --- esphome/components/api/api_frame_helper.h | 24 ++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index 98de24501e..5e07ad43a9 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -134,12 +134,16 @@ class APIFrameHelper { // // For log messages: Use Nagle to coalesce multiple small log packets into // fewer larger packets, reducing WiFi overhead. However, we limit batching - // to 3 messages to avoid excessive LWIP buffer pressure on memory-constrained - // devices like ESP8266. LWIP's TCP_OVERSIZE option coalesces the data into - // shared pbufs, but holding data too long waiting for Nagle's timer causes - // buffer exhaustion and dropped messages. + // to avoid excessive LWIP buffer pressure on memory-constrained devices. + // LWIP's TCP_OVERSIZE option coalesces the data into shared pbufs, but + // holding data too long waiting for Nagle's timer causes buffer exhaustion + // and dropped messages. // - // Flow: Log 1 (Nagle on) -> Log 2 (Nagle on) -> Log 3 (NODELAY, flush all) + // ESP32 (TCP_SND_BUF=4×MSS+) / RP2040 (8×MSS) / LibreTiny (4×MSS): 4 logs per cycle + // ESP8266 (2×MSS): 3 logs per cycle (tightest buffers) + // + // Flow (ESP32/RP2040/LT): Log 1 (Nagle on) -> Log 2 -> Log 3 -> Log 4 (NODELAY, flush) + // Flow (ESP8266): Log 1 (Nagle on) -> Log 2 -> Log 3 (NODELAY, flush all) // void set_nodelay_for_message(bool is_log_message) { if (!is_log_message) { @@ -150,7 +154,7 @@ class APIFrameHelper { return; } - // Log messages 1-3: state transitions -1 -> 1 -> 2 -> -1 (flush on 3rd) + // Log messages: state transitions -1 -> 1 -> ... -> LOG_NAGLE_COUNT -> -1 (flush) if (this->nodelay_state_ == NODELAY_ON) { this->set_nodelay_raw_(false); this->nodelay_state_ = 1; @@ -255,10 +259,16 @@ class APIFrameHelper { uint8_t tx_buf_tail_{0}; uint8_t tx_buf_count_{0}; // Nagle batching state for log messages. NODELAY_ON (-1) means NODELAY is enabled - // (immediate send). Values 1-2 count log messages in the current Nagle batch. + // (immediate send). Values 1..LOG_NAGLE_COUNT count log messages in the current Nagle batch. // After LOG_NAGLE_COUNT logs, we switch to NODELAY to flush and reset. + // ESP8266 has the tightest TCP send buffer (2×MSS) and needs conservative batching. + // ESP32 (4×MSS+), RP2040 (8×MSS), and LibreTiny (4×MSS) can coalesce more. static constexpr int8_t NODELAY_ON = -1; +#ifdef USE_ESP8266 static constexpr int8_t LOG_NAGLE_COUNT = 2; +#else + static constexpr int8_t LOG_NAGLE_COUNT = 3; +#endif int8_t nodelay_state_{NODELAY_ON}; // Internal helper to set TCP_NODELAY socket option From a064eceb9bf750979c74009b508c8148eca70d81 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 13 Mar 2026 07:37:44 -1000 Subject: [PATCH 1404/2030] [template] Fix misleading 'Text value too long to save' warning (#14753) --- .../components/template/text/template_text.h | 32 ++--- .../fixtures/template_text_save.yaml | 23 +++ tests/integration/test_template_text_save.py | 131 ++++++++++++++++++ 3 files changed, 170 insertions(+), 16 deletions(-) create mode 100644 tests/integration/fixtures/template_text_save.yaml create mode 100644 tests/integration/test_template_text_save.py diff --git a/esphome/components/template/text/template_text.h b/esphome/components/template/text/template_text.h index 7f176db09e..229a61d9b8 100644 --- a/esphome/components/template/text/template_text.h +++ b/esphome/components/template/text/template_text.h @@ -24,23 +24,23 @@ class TemplateTextSaverBase { template<uint8_t SZ> class TextSaver : public TemplateTextSaverBase { public: bool save(const std::string &value) override { - int diff = value.compare(this->prev_); - if (diff != 0) { - // If string is bigger than the allocation, do not save it. - // We don't need to waste ram setting prev_value either. - int size = value.size(); - if (size <= SZ) { - // Make it into a length prefixed thing - unsigned char temp[SZ + 1]; - memcpy(temp + 1, value.c_str(), size); - // SZ should be pre checked at the schema level, it can't go past the char range. - temp[0] = ((unsigned char) size); - this->pref_.save(&temp); - this->prev_.assign(value); - return true; - } + if (value == this->prev_) { + return true; // No change, nothing to save } - return false; + // If string is bigger than the allocation, do not save it. + // We don't need to waste ram setting prev_value either. + int size = value.size(); + if (size > SZ) { + return false; + } + // Make it into a length prefixed thing + unsigned char temp[SZ + 1]; + memcpy(temp + 1, value.c_str(), size); + // SZ should be pre checked at the schema level, it can't go past the char range. + temp[0] = ((unsigned char) size); + this->pref_.save(&temp); + this->prev_.assign(value); + return true; } // Make the preference object. Fill the provided location with the saved data diff --git a/tests/integration/fixtures/template_text_save.yaml b/tests/integration/fixtures/template_text_save.yaml new file mode 100644 index 0000000000..526561732d --- /dev/null +++ b/tests/integration/fixtures/template_text_save.yaml @@ -0,0 +1,23 @@ +esphome: + name: host-template-text-save-test + +host: + +api: + batch_delay: 0ms + +logger: + +preferences: + flash_write_interval: 0s + +text: + - platform: template + name: "Test Text Restore" + id: test_text_restore + optimistic: true + min_length: 0 + max_length: 10 + mode: text + initial_value: "hello" + restore_value: true diff --git a/tests/integration/test_template_text_save.py b/tests/integration/test_template_text_save.py new file mode 100644 index 0000000000..47c8e3188a --- /dev/null +++ b/tests/integration/test_template_text_save.py @@ -0,0 +1,131 @@ +"""Integration test for template text restore_value persistence. + +Tests that: +1. A template text with restore_value saves its value to preferences +2. The saved value persists across restarts (binary re-run) +3. Setting the same value again does not produce a spurious "too long" warning +""" + +from __future__ import annotations + +import asyncio +from pathlib import Path +import socket +from typing import Any + +from aioesphomeapi import TextInfo, TextState +import pytest + +from .conftest import run_binary_and_wait_for_port, wait_and_connect_api_client +from .state_utils import InitialStateHelper, require_entity +from .types import CompileFunction, ConfigWriter + + +@pytest.mark.asyncio +async def test_template_text_save( + yaml_config: str, + write_yaml_config: ConfigWriter, + compile_esphome: CompileFunction, + reserved_tcp_port: tuple[int, socket.socket], +) -> None: + """Test template text save/restore persistence and duplicate-save behavior.""" + port, port_socket = reserved_tcp_port + + # Clean up any stale preference file from previous runs + prefs_file = ( + Path.home() / ".esphome" / "prefs" / "host-template-text-save-test.prefs" + ) + if prefs_file.exists(): + prefs_file.unlink() + + # Write and compile once + config_path = await write_yaml_config(yaml_config) + binary_path = await compile_esphome(config_path) + + # Release the reserved port so the binary can bind to it + port_socket.close() + + # --- First run: set a value and verify no spurious warnings --- + warning_lines: list[str] = [] + + def capture_warnings(line: str) -> None: + if "too long to save" in line.lower(): + warning_lines.append(line) + + async with ( + run_binary_and_wait_for_port( + binary_path, "127.0.0.1", port, line_callback=capture_warnings + ), + wait_and_connect_api_client(port=port) as client, + ): + device_info = await client.device_info() + assert device_info.name == "host-template-text-save-test" + + entities, _ = await client.list_entities_services() + text_entity = require_entity( + entities, "test_text_restore", TextInfo, "Test Text Restore" + ) + + # Set up state tracking + loop = asyncio.get_running_loop() + state_futures: dict[int, asyncio.Future[Any]] = {} + + def on_state(state: Any) -> None: + if state.key in state_futures and not state_futures[state.key].done(): + state_futures[state.key].set_result(state) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + await initial_state_helper.wait_for_initial_states() + + # Verify initial value from config + initial = initial_state_helper.initial_states[text_entity.key] + assert isinstance(initial, TextState) + assert initial.state == "hello" + + async def wait_for_state(key: int, timeout: float = 2.0) -> Any: + state_futures[key] = loop.create_future() + try: + return await asyncio.wait_for(state_futures[key], timeout) + finally: + state_futures.pop(key, None) + + # Set a new value that fits within max_length + client.text_command(key=text_entity.key, state="world") + state = await wait_for_state(text_entity.key) + assert state.state == "world" + + # Set the same value again - should NOT produce "too long" warning + client.text_command(key=text_entity.key, state="world") + # Give time for the warning to appear (if any) + await asyncio.sleep(0.5) + + # No warnings should have appeared + assert warning_lines == [], ( + f"Unexpected 'too long to save' warning(s): {warning_lines}" + ) + + # --- Second run: verify the value was restored from preferences --- + async with ( + run_binary_and_wait_for_port(binary_path, "127.0.0.1", port), + wait_and_connect_api_client(port=port) as client, + ): + entities, _ = await client.list_entities_services() + text_entity = require_entity( + entities, "test_text_restore", TextInfo, "Test Text Restore" + ) + + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(lambda s: None)) + await initial_state_helper.wait_for_initial_states() + + # The value should be "world" - restored from preferences + restored = initial_state_helper.initial_states[text_entity.key] + assert isinstance(restored, TextState) + assert restored.state == "world", ( + f"Expected restored value 'world', got '{restored.state}'" + ) + + # Clean up preference file + if prefs_file.exists(): + prefs_file.unlink() From 98d98716203da8d8d7a42f3312bb547ce2c425cb Mon Sep 17 00:00:00 2001 From: leccelecce <24962424+leccelecce@users.noreply.github.com> Date: Sat, 14 Mar 2026 13:15:54 +0000 Subject: [PATCH 1405/2030] [online_image] Log download duration in milliseconds instead of seconds (#14803) --- esphome/components/online_image/online_image.cpp | 6 +++--- esphome/components/online_image/online_image.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index da866599c9..22bf6a3056 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -129,7 +129,7 @@ void OnlineImage::update() { } ESP_LOGI(TAG, "Downloading image (Size: %zu)", total_size); - this->start_time_ = ::time(nullptr); + this->start_time_ = millis(); this->enable_loop(); } @@ -155,8 +155,8 @@ void OnlineImage::loop() { // Finalize decoding this->end_decode(); - ESP_LOGD(TAG, "Image fully downloaded, %zu bytes in %" PRIu32 "s", this->downloader_->get_bytes_read(), - (uint32_t) (::time(nullptr) - this->start_time_)); + ESP_LOGD(TAG, "Image fully downloaded, %zu bytes in %" PRIu32 " ms", this->downloader_->get_bytes_read(), + millis() - this->start_time_); // Save caching headers this->etag_ = this->downloader_->get_response_header(ETAG_HEADER_NAME); diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index c7c80c7c66..12c2564526 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -97,7 +97,7 @@ class OnlineImage : public PollingComponent, */ std::string last_modified_ = ""; - time_t start_time_; + uint32_t start_time_{0}; }; template<typename... Ts> class OnlineImageSetUrlAction : public Action<Ts...> { From 632dbc8fe83a7de72841ad72965a4e484898cc81 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 08:12:04 -1000 Subject: [PATCH 1406/2030] [core] Inline LwIPLock as no-op on platforms without lwIP core locking (#14787) --- esphome/components/esp8266/helpers.cpp | 4 +--- esphome/components/libretiny/helpers.cpp | 4 +--- esphome/components/zephyr/core.cpp | 4 +--- esphome/core/helpers.h | 22 +++++++++++++++------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/esphome/components/esp8266/helpers.cpp b/esphome/components/esp8266/helpers.cpp index 036594fa17..4a64ae181e 100644 --- a/esphome/components/esp8266/helpers.cpp +++ b/esphome/components/esp8266/helpers.cpp @@ -22,9 +22,7 @@ void Mutex::unlock() {} IRAM_ATTR InterruptLock::InterruptLock() { state_ = xt_rsil(15); } IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(state_); } -// ESP8266 doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// ESP8266 LwIPLock is defined inline as a no-op in helpers.h void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) wifi_get_macaddr(STATION_IF, mac); diff --git a/esphome/components/libretiny/helpers.cpp b/esphome/components/libretiny/helpers.cpp index 37ae0fb455..21913e4a16 100644 --- a/esphome/components/libretiny/helpers.cpp +++ b/esphome/components/libretiny/helpers.cpp @@ -26,9 +26,7 @@ void Mutex::unlock() { xSemaphoreGive(this->handle_); } IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); } IRAM_ATTR InterruptLock::~InterruptLock() { portENABLE_INTERRUPTS(); } -// LibreTiny doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// LibreTiny LwIPLock is defined inline as a no-op in helpers.h void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) WiFi.macAddress(mac); diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index eee7fb3f4f..1d105a1057 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -76,9 +76,7 @@ void Mutex::unlock() { k_mutex_unlock(static_cast<k_mutex *>(this->handle_)); } IRAM_ATTR InterruptLock::InterruptLock() { state_ = irq_lock(); } IRAM_ATTR InterruptLock::~InterruptLock() { irq_unlock(state_); } -// Zephyr doesn't support lwIP core locking, so this is a no-op -LwIPLock::LwIPLock() {} -LwIPLock::~LwIPLock() {} +// Zephyr LwIPLock is defined inline as a no-op in helpers.h uint32_t random_uint32() { return rand(); } // NOLINT(cert-msc30-c, cert-msc50-cpp) bool random_bytes(uint8_t *data, size_t len) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index b2517e2d7a..dafd899ae4 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1801,19 +1801,27 @@ class InterruptLock { /** Helper class to lock the lwIP TCPIP core when making lwIP API calls from non-TCPIP threads. * - * This is needed on multi-threaded platforms (ESP32) when CONFIG_LWIP_TCPIP_CORE_LOCKING is enabled. - * It ensures thread-safe access to lwIP APIs. + * This is needed on multi-threaded platforms (ESP32) when CONFIG_LWIP_TCPIP_CORE_LOCKING is enabled, + * and on RP2040 when CYW43 WiFi is active (cyw43_arch_lwip_begin/end). * - * @note This follows the same pattern as InterruptLock - platform-specific implementations in helpers.cpp + * On platforms without lwIP core locking (ESP8266, LibreTiny, Zephyr), + * this is a no-op defined inline so the compiler can eliminate all call overhead. */ class LwIPLock { public: - LwIPLock(); - ~LwIPLock(); - - // Delete copy constructor and copy assignment operator to prevent accidental copying LwIPLock(const LwIPLock &) = delete; LwIPLock &operator=(const LwIPLock &) = delete; + +#if defined(USE_ESP32) || defined(USE_RP2040) + // Platforms with potential lwIP core locking — out-of-line implementations in helpers.cpp + LwIPLock(); + ~LwIPLock(); +#else + // No lwIP core locking — inline no-ops (empty bodies instead of = default + // to prevent clang-tidy unused-variable warnings at call sites) + LwIPLock() {} + ~LwIPLock() {} +#endif }; /** Helper class to request `loop()` to be called as fast as possible. From 22ea2764d4c48edfb365150a11be9c557806f9bc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 14 Mar 2026 13:17:32 -1000 Subject: [PATCH 1407/2030] [debug] Fix shared buffer between reset reason and wakeup cause (#14813) --- esphome/components/debug/debug_component.h | 3 ++- esphome/components/debug/debug_esp32.cpp | 9 +++++---- esphome/components/debug/debug_esp8266.cpp | 2 +- esphome/components/debug/debug_host.cpp | 2 +- esphome/components/debug/debug_libretiny.cpp | 2 +- esphome/components/debug/debug_rp2040.cpp | 2 +- esphome/components/debug/debug_zephyr.cpp | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/esphome/components/debug/debug_component.h b/esphome/components/debug/debug_component.h index e4f4bb36eb..3da6b800c6 100644 --- a/esphome/components/debug/debug_component.h +++ b/esphome/components/debug/debug_component.h @@ -18,6 +18,7 @@ namespace debug { static constexpr size_t DEVICE_INFO_BUFFER_SIZE = 256; static constexpr size_t RESET_REASON_BUFFER_SIZE = 128; +static constexpr size_t WAKEUP_CAUSE_BUFFER_SIZE = 128; // buf_append_printf is now provided by esphome/core/helpers.h @@ -94,7 +95,7 @@ class DebugComponent : public PollingComponent { #endif // USE_TEXT_SENSOR const char *get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer); - const char *get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer); + const char *get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer); uint32_t get_free_heap_(); size_t get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> buffer, size_t pos); void update_platform_(); diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index 6898621dd0..c9df4fdf21 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -98,7 +98,7 @@ static const char *const WAKEUP_CAUSES[] = { "BT", }; -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { const char *wake_reason; unsigned reason = esp_sleep_get_wakeup_cause(); if (reason < sizeof(WAKEUP_CAUSES) / sizeof(WAKEUP_CAUSES[0])) { @@ -196,9 +196,10 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> uint32_t cpu_freq_mhz = arch_get_cpu_freq_hz() / 1000000; pos = buf_append_printf(buf, size, pos, "|CPU Frequency: %" PRIu32 " MHz", cpu_freq_mhz); - char reason_buffer[RESET_REASON_BUFFER_SIZE]; - const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); - const char *wakeup_cause = get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE>(reason_buffer)); + char reset_buffer[RESET_REASON_BUFFER_SIZE]; + char wakeup_buffer[WAKEUP_CAUSE_BUFFER_SIZE]; + const char *reset_reason = get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reset_buffer)); + const char *wakeup_cause = get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE>(wakeup_buffer)); uint8_t mac[6]; get_mac_address_raw(mac); diff --git a/esphome/components/debug/debug_esp8266.cpp b/esphome/components/debug/debug_esp8266.cpp index 4df4aaa851..0519ab72fe 100644 --- a/esphome/components/debug/debug_esp8266.cpp +++ b/esphome/components/debug/debug_esp8266.cpp @@ -91,7 +91,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buffer.data(); } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { // ESP8266 doesn't have detailed wakeup cause like ESP32 return ""; } diff --git a/esphome/components/debug/debug_host.cpp b/esphome/components/debug/debug_host.cpp index 2fa88f0909..0dfab86e4c 100644 --- a/esphome/components/debug/debug_host.cpp +++ b/esphome/components/debug/debug_host.cpp @@ -7,7 +7,7 @@ namespace debug { const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return INT_MAX; } diff --git a/esphome/components/debug/debug_libretiny.cpp b/esphome/components/debug/debug_libretiny.cpp index 39269d6f2f..1d458c602a 100644 --- a/esphome/components/debug/debug_libretiny.cpp +++ b/esphome/components/debug/debug_libretiny.cpp @@ -12,7 +12,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return lt_get_reboot_reason_name(lt_get_reboot_reason()); } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); } diff --git a/esphome/components/debug/debug_rp2040.cpp b/esphome/components/debug/debug_rp2040.cpp index 8dc84a2673..73f08492c8 100644 --- a/esphome/components/debug/debug_rp2040.cpp +++ b/esphome/components/debug/debug_rp2040.cpp @@ -67,7 +67,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buf; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { return ""; } +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { return ""; } uint32_t DebugComponent::get_free_heap_() { return ::rp2040.getFreeHeap(); } diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index bd6432e949..bf87b7ae3d 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -53,7 +53,7 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE return buf; } -const char *DebugComponent::get_wakeup_cause_(std::span<char, RESET_REASON_BUFFER_SIZE> buffer) { +const char *DebugComponent::get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE> buffer) { // Zephyr doesn't have detailed wakeup cause like ESP32 return ""; } From deb6b97eea98feea201c73402df493c30a502e7d Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:25:21 +1300 Subject: [PATCH 1408/2030] Bump version to 2026.3.0b2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 9f5cd0a2ce..4ec3a24c9f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0b1 +PROJECT_NUMBER = 2026.3.0b2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index eb49c9a1d7..2466f2c49c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0b1" +__version__ = "2026.3.0b2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 92d5e7b18c233403ea58835e12fffd4a52431ede Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Sun, 15 Mar 2026 16:02:23 -0700 Subject: [PATCH 1409/2030] [tests] Fix integration helper to match entities exactly (#14837) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../fixtures/sensor_filters_nan_handling.yaml | 18 +++++++++--------- .../fixtures/sensor_filters_ring_buffer.yaml | 18 +++++++++--------- .../sensor_filters_ring_buffer_wraparound.yaml | 8 ++++---- tests/integration/state_utils.py | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/integration/fixtures/sensor_filters_nan_handling.yaml b/tests/integration/fixtures/sensor_filters_nan_handling.yaml index fcb12cfde5..beaf55eacf 100644 --- a/tests/integration/fixtures/sensor_filters_nan_handling.yaml +++ b/tests/integration/fixtures/sensor_filters_nan_handling.yaml @@ -3,7 +3,7 @@ esphome: host: api: - batch_delay: 0ms # Disable batching to receive all state updates + batch_delay: 0ms # Disable batching to receive all state updates logger: level: DEBUG @@ -15,8 +15,8 @@ sensor: - platform: copy source_id: source_nan_sensor - name: "Min NaN Sensor" - id: min_nan_sensor + name: "Min NaN" + id: min_nan filters: - min: window_size: 5 @@ -25,8 +25,8 @@ sensor: - platform: copy source_id: source_nan_sensor - name: "Max NaN Sensor" - id: max_nan_sensor + name: "Max NaN" + id: max_nan filters: - max: window_size: 5 @@ -42,7 +42,7 @@ script: - delay: 20ms - sensor.template.publish: id: source_nan_sensor - state: !lambda 'return NAN;' + state: !lambda "return NAN;" - delay: 20ms - sensor.template.publish: id: source_nan_sensor @@ -50,7 +50,7 @@ script: - delay: 20ms - sensor.template.publish: id: source_nan_sensor - state: !lambda 'return NAN;' + state: !lambda "return NAN;" - delay: 20ms - sensor.template.publish: id: source_nan_sensor @@ -62,7 +62,7 @@ script: - delay: 20ms - sensor.template.publish: id: source_nan_sensor - state: !lambda 'return NAN;' + state: !lambda "return NAN;" - delay: 20ms - sensor.template.publish: id: source_nan_sensor @@ -74,7 +74,7 @@ script: - delay: 20ms - sensor.template.publish: id: source_nan_sensor - state: !lambda 'return NAN;' + state: !lambda "return NAN;" button: - platform: template diff --git a/tests/integration/fixtures/sensor_filters_ring_buffer.yaml b/tests/integration/fixtures/sensor_filters_ring_buffer.yaml index ea7a326b8d..b9b8ed8f74 100644 --- a/tests/integration/fixtures/sensor_filters_ring_buffer.yaml +++ b/tests/integration/fixtures/sensor_filters_ring_buffer.yaml @@ -3,7 +3,7 @@ esphome: host: api: - batch_delay: 0ms # Disable batching to receive all state updates + batch_delay: 0ms # Disable batching to receive all state updates logger: level: DEBUG @@ -18,8 +18,8 @@ sensor: # Window of 5, send every 2 values - platform: copy source_id: source_sensor - name: "Sliding Min Sensor" - id: sliding_min_sensor + name: "Sliding Min" + id: sliding_min filters: - min: window_size: 5 @@ -28,8 +28,8 @@ sensor: - platform: copy source_id: source_sensor - name: "Sliding Max Sensor" - id: sliding_max_sensor + name: "Sliding Max" + id: sliding_max filters: - max: window_size: 5 @@ -38,8 +38,8 @@ sensor: - platform: copy source_id: source_sensor - name: "Sliding Median Sensor" - id: sliding_median_sensor + name: "Sliding Median" + id: sliding_median filters: - median: window_size: 5 @@ -48,8 +48,8 @@ sensor: - platform: copy source_id: source_sensor - name: "Sliding Moving Avg Sensor" - id: sliding_moving_avg_sensor + name: "Sliding Moving Avg" + id: sliding_moving_avg filters: - sliding_window_moving_average: window_size: 5 diff --git a/tests/integration/fixtures/sensor_filters_ring_buffer_wraparound.yaml b/tests/integration/fixtures/sensor_filters_ring_buffer_wraparound.yaml index bd5980160b..d1528e4438 100644 --- a/tests/integration/fixtures/sensor_filters_ring_buffer_wraparound.yaml +++ b/tests/integration/fixtures/sensor_filters_ring_buffer_wraparound.yaml @@ -3,20 +3,20 @@ esphome: host: api: - batch_delay: 0ms # Disable batching to receive all state updates + batch_delay: 0ms # Disable batching to receive all state updates logger: level: DEBUG sensor: - platform: template - name: "Source Wraparound Sensor" + name: "Source Wraparound" id: source_wraparound accuracy_decimals: 2 - platform: copy source_id: source_wraparound - name: "Wraparound Min Sensor" - id: wraparound_min_sensor + name: "Wraparound Min" + id: wraparound_min filters: - min: window_size: 3 diff --git a/tests/integration/state_utils.py b/tests/integration/state_utils.py index ab9fdb01bb..5792a8e804 100644 --- a/tests/integration/state_utils.py +++ b/tests/integration/state_utils.py @@ -88,7 +88,7 @@ def build_key_to_entity_mapping( Args: entities: List of entity info objects from the API - entity_names: List of entity names to search for in object_ids + entity_names: List of entity names to match exactly against object_ids Returns: Dictionary mapping entity keys to entity names @@ -97,7 +97,7 @@ def build_key_to_entity_mapping( for entity in entities: obj_id = entity.object_id.lower() for entity_name in entity_names: - if entity_name in obj_id: + if entity_name == obj_id: key_to_entity[entity.key] = entity_name break return key_to_entity From d97c23b8e3c8cb7e7feec411c58fe0c3a4a7b006 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 15:13:10 -1000 Subject: [PATCH 1410/2030] [core] Add no-arg status_set_warning() to allow linker GC of const char* overload (#14821) --- esphome/components/rx8130/rx8130.cpp | 6 +++--- esphome/components/usb_uart/usb_uart.cpp | 2 +- esphome/components/zwave_proxy/zwave_proxy.cpp | 2 +- esphome/core/component.cpp | 1 + esphome/core/component.h | 3 ++- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/esphome/components/rx8130/rx8130.cpp b/esphome/components/rx8130/rx8130.cpp index 9e6f05ee15..07ed7acc56 100644 --- a/esphome/components/rx8130/rx8130.cpp +++ b/esphome/components/rx8130/rx8130.cpp @@ -68,7 +68,7 @@ void RX8130Component::dump_config() { void RX8130Component::read_time() { uint8_t date[7]; if (this->read_register(RX8130_REG_SEC, date, 7) != i2c::ERROR_OK) { - this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); + this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); return; } ESPTime rtc_time{ @@ -109,7 +109,7 @@ void RX8130Component::write_time() { buff[6] = dec2bcd(now.year % 100); this->stop_(true); if (this->write_register(RX8130_REG_SEC, buff, 7) != i2c::ERROR_OK) { - this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); + this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); } else { ESP_LOGD(TAG, "Wrote UTC time: %04d-%02d-%02d %02d:%02d:%02d", now.year, now.month, now.day_of_month, now.hour, now.minute, now.second); @@ -120,7 +120,7 @@ void RX8130Component::write_time() { void RX8130Component::stop_(bool stop) { const uint8_t data = stop ? RX8130_BIT_CTRL_STOP : RX8130_CLEAR_FLAGS; if (this->write_register(RX8130_REG_CTRL0, &data, 1) != i2c::ERROR_OK) { - this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); + this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL)); } } diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 3d35f368fb..997f836146 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -416,7 +416,7 @@ void USBUartTypeCdcAcm::on_connected() { for (auto *channel : this->channels_) { if (i == cdc_devs.size()) { ESP_LOGE(TAG, "No configuration found for channel %d", channel->index_); - this->status_set_warning("No configuration found for channel"); + this->status_set_warning(LOG_STR("No configuration found for channel")); break; } channel->cdc_dev_ = cdc_devs[i++]; diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index 9e5c57814d..ad4357663f 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -90,7 +90,7 @@ void ZWaveProxy::process_uart_() { while (this->available()) { uint8_t byte; if (!this->read_byte(&byte)) { - this->status_set_warning("UART read failed"); + this->status_set_warning(LOG_STR("UART read failed")); return; } if (this->parse_byte_(byte)) { diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index cce0c7b3e0..761f1bd485 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -392,6 +392,7 @@ bool Component::set_status_flag_(uint8_t flag) { return true; } +void Component::status_set_warning() { this->status_set_warning((const LogString *) nullptr); } void Component::status_set_warning(const char *message) { if (!this->set_status_flag_(STATUS_LED_WARNING)) return; diff --git a/esphome/core/component.h b/esphome/core/component.h index 7266f57e15..1aac1c7219 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -240,7 +240,8 @@ class Component { bool status_has_error() const { return this->component_state_ & STATUS_LED_ERROR; } - void status_set_warning(const char *message = nullptr); + void status_set_warning(); // Set warning flag without message + void status_set_warning(const char *message); void status_set_warning(const LogString *message); void status_set_error(); // Set error flag without message From 29501ef4f87870db3e9bee59c13681a99534ca00 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 15:13:34 -1000 Subject: [PATCH 1411/2030] [core] Mark leaf Component subclasses as final (#14833) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/api/api_server.h | 6 +++--- esphome/components/binary_sensor/filter.h | 2 +- esphome/components/gpio/binary_sensor/gpio_binary_sensor.h | 2 +- esphome/components/gpio/switch/gpio_switch.h | 2 +- esphome/components/homeassistant/time/homeassistant_time.h | 2 +- esphome/components/md5/md5.h | 2 +- esphome/components/preferences/syncer.h | 2 +- esphome/components/restart/button/restart_button.h | 2 +- esphome/components/safe_mode/button/safe_mode_button.h | 2 +- esphome/components/sha256/sha256.h | 2 +- esphome/components/version/version_text_sensor.h | 2 +- esphome/components/wifi/wifi_component.h | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index 69fc26cc00..ccba6deb00 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -36,11 +36,11 @@ struct SavedNoisePsk { } PACKED; // NOLINT #endif -class APIServer : public Component, - public Controller +class APIServer final : public Component, + public Controller #ifdef USE_CAMERA , - public camera::CameraListener + public camera::CameraListener #endif { public: diff --git a/esphome/components/binary_sensor/filter.h b/esphome/components/binary_sensor/filter.h index 2735a32ab0..0813847ca2 100644 --- a/esphome/components/binary_sensor/filter.h +++ b/esphome/components/binary_sensor/filter.h @@ -37,7 +37,7 @@ class TimeoutFilter : public Filter, public Component { TemplatableValue<uint32_t> timeout_delay_{}; }; -class DelayedOnOffFilter : public Filter, public Component { +class DelayedOnOffFilter final : public Filter, public Component { public: optional<bool> new_value(bool value) override; diff --git a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h index 8cf52f540b..8b1cc29613 100644 --- a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +++ b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h @@ -39,7 +39,7 @@ class GPIOBinarySensorStore { Component *component_{nullptr}; // Pointer to the component for enable_loop_soon_any_context() }; -class GPIOBinarySensor : public binary_sensor::BinarySensor, public Component { +class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Component { public: // No destructor needed: ESPHome components are created at boot and live forever. // Interrupts are only detached on reboot when memory is cleared anyway. diff --git a/esphome/components/gpio/switch/gpio_switch.h b/esphome/components/gpio/switch/gpio_switch.h index 080decac08..a73fb9e18c 100644 --- a/esphome/components/gpio/switch/gpio_switch.h +++ b/esphome/components/gpio/switch/gpio_switch.h @@ -8,7 +8,7 @@ namespace esphome { namespace gpio { -class GPIOSwitch : public switch_::Switch, public Component { +class GPIOSwitch final : public switch_::Switch, public Component { public: void set_pin(GPIOPin *pin) { pin_ = pin; } diff --git a/esphome/components/homeassistant/time/homeassistant_time.h b/esphome/components/homeassistant/time/homeassistant_time.h index 7b5842fefd..455ded2022 100644 --- a/esphome/components/homeassistant/time/homeassistant_time.h +++ b/esphome/components/homeassistant/time/homeassistant_time.h @@ -7,7 +7,7 @@ namespace esphome { namespace homeassistant { -class HomeassistantTime : public time::RealTimeClock { +class HomeassistantTime final : public time::RealTimeClock { public: void setup() override; void update() override; diff --git a/esphome/components/md5/md5.h b/esphome/components/md5/md5.h index 6ff651b02e..80e74d188e 100644 --- a/esphome/components/md5/md5.h +++ b/esphome/components/md5/md5.h @@ -32,7 +32,7 @@ namespace esphome { namespace md5 { -class MD5Digest : public HashBase { +class MD5Digest final : public HashBase { public: MD5Digest() = default; ~MD5Digest() override; diff --git a/esphome/components/preferences/syncer.h b/esphome/components/preferences/syncer.h index b6b422d4ba..96716d3f30 100644 --- a/esphome/components/preferences/syncer.h +++ b/esphome/components/preferences/syncer.h @@ -6,7 +6,7 @@ namespace esphome { namespace preferences { -class IntervalSyncer : public Component { +class IntervalSyncer final : public Component { public: void set_write_interval(uint32_t write_interval) { this->write_interval_ = write_interval; } void setup() override { diff --git a/esphome/components/restart/button/restart_button.h b/esphome/components/restart/button/restart_button.h index db18f1dadc..fd51282d36 100644 --- a/esphome/components/restart/button/restart_button.h +++ b/esphome/components/restart/button/restart_button.h @@ -6,7 +6,7 @@ namespace esphome { namespace restart { -class RestartButton : public button::Button, public Component { +class RestartButton final : public button::Button, public Component { public: void dump_config() override; diff --git a/esphome/components/safe_mode/button/safe_mode_button.h b/esphome/components/safe_mode/button/safe_mode_button.h index fea0955abb..0307a81feb 100644 --- a/esphome/components/safe_mode/button/safe_mode_button.h +++ b/esphome/components/safe_mode/button/safe_mode_button.h @@ -7,7 +7,7 @@ namespace esphome { namespace safe_mode { -class SafeModeButton : public button::Button, public Component { +class SafeModeButton final : public button::Button, public Component { public: void dump_config() override; void set_safe_mode(SafeModeComponent *safe_mode_component); diff --git a/esphome/components/sha256/sha256.h b/esphome/components/sha256/sha256.h index 0f995fcd91..d10d418c7a 100644 --- a/esphome/components/sha256/sha256.h +++ b/esphome/components/sha256/sha256.h @@ -48,7 +48,7 @@ namespace esphome::sha256 { /// hasher.init(); /// hasher.add(data, len); /// hasher.calculate(); -class SHA256 : public esphome::HashBase { +class SHA256 final : public esphome::HashBase { public: SHA256() = default; ~SHA256() override; diff --git a/esphome/components/version/version_text_sensor.h b/esphome/components/version/version_text_sensor.h index fec898ae03..d2ca0ba6f6 100644 --- a/esphome/components/version/version_text_sensor.h +++ b/esphome/components/version/version_text_sensor.h @@ -5,7 +5,7 @@ namespace esphome::version { -class VersionTextSensor : public text_sensor::TextSensor, public Component { +class VersionTextSensor final : public text_sensor::TextSensor, public Component { public: void set_hide_hash(bool hide_hash); void set_hide_timestamp(bool hide_timestamp); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index aeb32352a9..057f2c0661 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -399,7 +399,7 @@ class WiFiPowerSaveListener { }; /// This component is responsible for managing the ESP WiFi interface. -class WiFiComponent : public Component { +class WiFiComponent final : public Component { public: /// Construct a WiFiComponent. WiFiComponent(); From 1377776d218bc8061d7bb9da96517e1e34105867 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 15:17:21 -1000 Subject: [PATCH 1412/2030] [ethernet] Restructure for multi-platform support (#14819) --- esphome/components/ethernet/__init__.py | 306 ++++--- .../ethernet/ethernet_component.cpp | 850 +----------------- .../components/ethernet/ethernet_component.h | 89 +- .../ethernet/ethernet_component_esp32.cpp | 841 +++++++++++++++++ .../components/ethernet/ethernet_helpers.c | 3 + .../ethernet_info_text_sensor.cpp | 4 +- .../ethernet_info/ethernet_info_text_sensor.h | 4 +- esphome/core/defines.h | 6 + 8 files changed, 1099 insertions(+), 1004 deletions(-) create mode 100644 esphome/components/ethernet/ethernet_component_esp32.cpp diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index e520c0e914..83bef4d91c 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -2,23 +2,8 @@ import logging from esphome import automation, pins import esphome.codegen as cg -from esphome.components.esp32 import ( - VARIANT_ESP32, - VARIANT_ESP32C3, - VARIANT_ESP32C5, - VARIANT_ESP32C6, - VARIANT_ESP32C61, - VARIANT_ESP32P4, - VARIANT_ESP32S2, - VARIANT_ESP32S3, - add_idf_component, - add_idf_sdkconfig_option, - get_esp32_variant, - idf_version, - include_builtin_idf_component, -) from esphome.components.network import ip_address_literal -from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface +from esphome.config_helpers import filter_source_files_from_platform import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, @@ -50,6 +35,8 @@ from esphome.const import ( CONF_VALUE, KEY_CORE, KEY_FRAMEWORK_VERSION, + Platform, + PlatformFramework, ) from esphome.core import ( CORE, @@ -61,7 +48,6 @@ import esphome.final_validate as fv from esphome.types import ConfigType CONFLICTS_WITH = ["wifi"] -DEPENDENCIES = ["esp32"] AUTO_LOAD = ["network"] LOGGER = logging.getLogger(__name__) @@ -174,9 +160,16 @@ EthernetComponent = ethernet_ns.class_("EthernetComponent", cg.Component) ManualIP = ethernet_ns.struct("ManualIP") -def _is_framework_spi_polling_mode_supported(): - # SPI Ethernet without IRQ feature is added in - # esp-idf >= (5.3+ ,5.2.1+, 5.1.4) +def _is_framework_spi_polling_mode_supported() -> bool: + """Check if ESP-IDF framework supports SPI polling mode (ESP32 only). + + SPI Ethernet without IRQ feature is added in + esp-idf >= (5.3+, 5.2.1+, 5.1.4) + """ + if not CORE.is_esp32: + return False + from esphome.components.esp32 import idf_version + ver = idf_version() if ver >= cv.Version(5, 3, 0): return True @@ -195,52 +188,63 @@ def _validate(config): use_address = CORE.name + config[CONF_DOMAIN] config[CONF_USE_ADDRESS] = use_address - if config[CONF_TYPE] in SPI_ETHERNET_TYPES: - if _is_framework_spi_polling_mode_supported(): - if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config: - raise cv.Invalid( - f"Cannot specify more than one of {CONF_INTERRUPT_PIN}, {CONF_POLLING_INTERVAL}" - ) - if CONF_POLLING_INTERVAL not in config and CONF_INTERRUPT_PIN not in config: - config[CONF_POLLING_INTERVAL] = SPI_ETHERNET_DEFAULT_POLLING_INTERVAL - else: - if CONF_POLLING_INTERVAL in config: - raise cv.Invalid( - "In this version of the framework " - f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " - f"'{CONF_POLLING_INTERVAL}' is not supported." - ) - if CONF_INTERRUPT_PIN not in config: - raise cv.Invalid( - "In this version of the framework " - f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " - f"'{CONF_INTERRUPT_PIN}' is a required option for [ethernet]." - ) - elif config[CONF_TYPE] != "OPENETH": - if CONF_CLK_MODE in config: - mode, pin = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] - LOGGER.warning( - "[ethernet] The 'clk_mode' option is deprecated. " - "Please replace 'clk_mode: %s' with:\n" - " clk:\n" - " mode: %s\n" - " pin: %s\n" - "Removal scheduled for 2026.7.0.", - config[CONF_CLK_MODE], - mode, - pin, - ) - config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode, CONF_PIN: pin}) - del config[CONF_CLK_MODE] - elif CONF_CLK not in config: - raise cv.Invalid("'clk' is a required option for [ethernet].") - variant = get_esp32_variant() - if variant not in (VARIANT_ESP32, VARIANT_ESP32P4): - raise cv.Invalid( - f"{config[CONF_TYPE]} PHY requires RMII interface and is only supported " - f"on ESP32 classic and ESP32-P4, not {variant}" + if CORE.is_esp32: + if config[CONF_TYPE] in SPI_ETHERNET_TYPES: + if _is_framework_spi_polling_mode_supported(): + if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config: + raise cv.Invalid( + f"Cannot specify more than one of {CONF_INTERRUPT_PIN}, {CONF_POLLING_INTERVAL}" + ) + if ( + CONF_POLLING_INTERVAL not in config + and CONF_INTERRUPT_PIN not in config + ): + config[CONF_POLLING_INTERVAL] = ( + SPI_ETHERNET_DEFAULT_POLLING_INTERVAL + ) + else: + if CONF_POLLING_INTERVAL in config: + raise cv.Invalid( + "In this version of the framework " + f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " + f"'{CONF_POLLING_INTERVAL}' is not supported." + ) + if CONF_INTERRUPT_PIN not in config: + raise cv.Invalid( + "In this version of the framework " + f"({CORE.target_framework} {CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}), " + f"'{CONF_INTERRUPT_PIN}' is a required option for [ethernet]." + ) + elif config[CONF_TYPE] != "OPENETH": + from esphome.components.esp32 import ( + VARIANT_ESP32, + VARIANT_ESP32P4, + get_esp32_variant, ) + if CONF_CLK_MODE in config: + mode, pin = CLK_MODES_DEPRECATED[config[CONF_CLK_MODE]] + LOGGER.warning( + "[ethernet] The 'clk_mode' option is deprecated. " + "Please replace 'clk_mode: %s' with:\n" + " clk:\n" + " mode: %s\n" + " pin: %s\n" + "Removal scheduled for 2026.7.0.", + config[CONF_CLK_MODE], + mode, + pin, + ) + config[CONF_CLK] = CLK_SCHEMA({CONF_MODE: mode, CONF_PIN: pin}) + del config[CONF_CLK_MODE] + elif CONF_CLK not in config: + raise cv.Invalid("'clk' is a required option for [ethernet].") + variant = get_esp32_variant() + if variant not in (VARIANT_ESP32, VARIANT_ESP32P4): + raise cv.Invalid( + f"{config[CONF_TYPE]} PHY requires RMII interface and is only supported " + f"on ESP32 classic and ESP32-P4, not {variant}" + ) return config @@ -269,41 +273,47 @@ CLK_SCHEMA = cv.Schema( cv.Required(CONF_PIN): pins.internal_gpio_pin_number, } ) -RMII_SCHEMA = BASE_SCHEMA.extend( - cv.Schema( - { - cv.Required(CONF_MDC_PIN): pins.internal_gpio_output_pin_number, - cv.Required(CONF_MDIO_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_CLK_MODE): cv.enum( - CLK_MODES_DEPRECATED, upper=True, space="_" - ), - cv.Optional(CONF_CLK): CLK_SCHEMA, - 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), - } - ) +RMII_SCHEMA = cv.All( + BASE_SCHEMA.extend( + cv.Schema( + { + cv.Required(CONF_MDC_PIN): pins.internal_gpio_output_pin_number, + cv.Required(CONF_MDIO_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_CLK_MODE): cv.enum( + CLK_MODES_DEPRECATED, upper=True, space="_" + ), + cv.Optional(CONF_CLK): CLK_SCHEMA, + 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), + } + ) + ), + cv.only_on([Platform.ESP32]), ) -SPI_SCHEMA = BASE_SCHEMA.extend( - cv.Schema( - { - cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_number, - cv.Required(CONF_MISO_PIN): pins.internal_gpio_input_pin_number, - cv.Required(CONF_MOSI_PIN): pins.internal_gpio_output_pin_number, - cv.Required(CONF_CS_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_number, - cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_CLOCK_SPEED, default="26.67MHz"): cv.All( - cv.frequency, cv.int_range(int(8e6), int(80e6)) - ), - # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() - cv.Optional(CONF_POLLING_INTERVAL): cv.All( - cv.positive_time_period_milliseconds, - cv.Range(min=TimePeriodMilliseconds(milliseconds=1)), - ), - } +SPI_SCHEMA = cv.All( + BASE_SCHEMA.extend( + cv.Schema( + { + cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_number, + cv.Required(CONF_MISO_PIN): pins.internal_gpio_input_pin_number, + cv.Required(CONF_MOSI_PIN): pins.internal_gpio_output_pin_number, + cv.Required(CONF_CS_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_number, + cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_CLOCK_SPEED, default="26.67MHz"): cv.All( + cv.frequency, cv.int_range(int(8e6), int(80e6)) + ), + # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() + cv.Optional(CONF_POLLING_INTERVAL): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(min=TimePeriodMilliseconds(milliseconds=1)), + ), + } + ), ), + cv.only_on([Platform.ESP32]), ) CONFIG_SCHEMA = cv.All( @@ -317,7 +327,7 @@ CONFIG_SCHEMA = cv.All( "KSZ8081": RMII_SCHEMA, "KSZ8081RNA": RMII_SCHEMA, "W5500": SPI_SCHEMA, - "OPENETH": BASE_SCHEMA, + "OPENETH": cv.All(BASE_SCHEMA, cv.only_on([Platform.ESP32])), "DM9051": SPI_SCHEMA, "LAN8670": RMII_SCHEMA, }, @@ -328,8 +338,21 @@ CONFIG_SCHEMA = cv.All( def _final_validate_spi(config): + if not CORE.is_esp32: + return # SPI interface validation is ESP32-only if config[CONF_TYPE] not in SPI_ETHERNET_TYPES: return + from esphome.components.esp32 import ( + VARIANT_ESP32C3, + VARIANT_ESP32C5, + VARIANT_ESP32C6, + VARIANT_ESP32C61, + VARIANT_ESP32S2, + VARIANT_ESP32S3, + get_esp32_variant, + ) + from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface + if spi_configs := fv.full_config.get().get(CONF_SPI): variant = get_esp32_variant() if variant in ( @@ -378,6 +401,47 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + if CORE.is_esp32: + await _to_code_esp32(var, config) + + cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) + cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) + + if CONF_MANUAL_IP in config: + cg.add_define("USE_ETHERNET_MANUAL_IP") + cg.add(var.set_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) + + # Add compile-time define for PHY types with specific code + if phy_define := _PHY_TYPE_TO_DEFINE.get(config[CONF_TYPE]): + cg.add_define(phy_define) + + if mac_address := config.get(CONF_MAC_ADDRESS): + cg.add(var.set_fixed_mac(mac_address.parts)) + + cg.add_define("USE_ETHERNET") + + if on_connect_config := config.get(CONF_ON_CONNECT): + cg.add_define("USE_ETHERNET_CONNECT_TRIGGER") + await automation.build_automation( + var.get_connect_trigger(), [], on_connect_config + ) + + if on_disconnect_config := config.get(CONF_ON_DISCONNECT): + cg.add_define("USE_ETHERNET_DISCONNECT_TRIGGER") + await automation.build_automation( + var.get_disconnect_trigger(), [], on_disconnect_config + ) + + CORE.add_job(final_step) + + +async def _to_code_esp32(var, config): + from esphome.components.esp32 import ( + add_idf_component, + add_idf_sdkconfig_option, + include_builtin_idf_component, + ) + if config[CONF_TYPE] in SPI_ETHERNET_TYPES: cg.add(var.set_clk_pin(config[CONF_CLK_PIN])) cg.add(var.set_miso_pin(config[CONF_MISO_PIN])) @@ -415,22 +479,6 @@ async def to_code(config): ) 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])) - - if CONF_MANUAL_IP in config: - cg.add_define("USE_ETHERNET_MANUAL_IP") - cg.add(var.set_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) - - # Add compile-time define for PHY types with specific code - if phy_define := _PHY_TYPE_TO_DEFINE.get(config[CONF_TYPE]): - cg.add_define(phy_define) - - if mac_address := config.get(CONF_MAC_ADDRESS): - cg.add(var.set_fixed_mac(mac_address.parts)) - - cg.add_define("USE_ETHERNET") - # Disable WiFi when using Ethernet to save memory add_idf_sdkconfig_option("CONFIG_ESP_WIFI_ENABLED", False) # Also disable WiFi/BT coexistence since WiFi is disabled @@ -443,27 +491,21 @@ async def to_code(config): # Add LAN867x 10BASE-T1S PHY support component add_idf_component(name="espressif/lan867x", ref="2.0.0") - if on_connect_config := config.get(CONF_ON_CONNECT): - cg.add_define("USE_ETHERNET_CONNECT_TRIGGER") - await automation.build_automation( - var.get_connect_trigger(), [], on_connect_config - ) - - if on_disconnect_config := config.get(CONF_ON_DISCONNECT): - cg.add_define("USE_ETHERNET_DISCONNECT_TRIGGER") - await automation.build_automation( - var.get_disconnect_trigger(), [], on_disconnect_config - ) - - CORE.add_job(final_step) - def _final_validate_rmii_pins(config: ConfigType) -> None: """Validate that RMII pins are not used by other components.""" + if not CORE.is_esp32: + return # RMII validation is ESP32-only # Only validate for RMII-based PHYs on ESP32/ESP32P4 if config[CONF_TYPE] in SPI_ETHERNET_TYPES or config[CONF_TYPE] == "OPENETH": return # SPI and OPENETH don't use RMII + from esphome.components.esp32 import ( + VARIANT_ESP32, + VARIANT_ESP32P4, + get_esp32_variant, + ) + variant = get_esp32_variant() if variant == VARIANT_ESP32: rmii_pins = ESP32_RMII_FIXED_PINS @@ -521,3 +563,13 @@ async def final_step(): if ip_state_count := CORE.data.get(ETHERNET_IP_STATE_LISTENERS_KEY, 0): cg.add_define("USE_ETHERNET_IP_STATE_LISTENERS") cg.add_define("ESPHOME_ETHERNET_IP_STATE_LISTENERS", ip_state_count) + + +FILTER_SOURCE_FILES = filter_source_files_from_platform( + { + "ethernet_component_esp32.cpp": { + PlatformFramework.ESP32_IDF, + PlatformFramework.ESP32_ARDUINO, + }, + } +) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index e0788e1149..4421a1c7aa 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -1,547 +1,28 @@ #include "ethernet_component.h" -#include "esphome/core/application.h" -#include "esphome/core/helpers.h" + +#ifdef USE_ETHERNET + #include "esphome/core/log.h" -#include "esphome/core/util.h" - -#ifdef USE_ESP32 - -#include <lwip/dns.h> -#include <cinttypes> -#include "esp_event.h" - -#ifdef USE_ETHERNET_LAN8670 -#include "esp_eth_phy_lan867x.h" -#endif - -#ifdef USE_ETHERNET_SPI -#include <driver/gpio.h> -#include <driver/spi_master.h> -#endif namespace esphome::ethernet { -static const char *const TAG = "ethernet"; - -// PHY register size for hex logging -static constexpr size_t PHY_REG_SIZE = 2; - EthernetComponent *global_eth_component; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -void EthernetComponent::log_error_and_mark_failed_(esp_err_t err, const char *message) { - ESP_LOGE(TAG, "%s: (%d) %s", message, err, esp_err_to_name(err)); - this->mark_failed(); -} - -#define ESPHL_ERROR_CHECK(err, message) \ - if ((err) != ESP_OK) { \ - this->log_error_and_mark_failed_(err, message); \ - return; \ - } - -#define ESPHL_ERROR_CHECK_RET(err, message, ret) \ - if ((err) != ESP_OK) { \ - this->log_error_and_mark_failed_(err, message); \ - return ret; \ - } - EthernetComponent::EthernetComponent() { global_eth_component = this; } -void EthernetComponent::setup() { - if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { - // Delay here to allow power to stabilise before Ethernet is initialized. - delay(300); // NOLINT - } - - esp_err_t err; - -#ifdef USE_ETHERNET_SPI - // Install GPIO ISR handler to be able to service SPI Eth modules interrupts - gpio_install_isr_service(0); - - spi_bus_config_t buscfg = { - .mosi_io_num = this->mosi_pin_, - .miso_io_num = this->miso_pin_, - .sclk_io_num = this->clk_pin_, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .data4_io_num = -1, - .data5_io_num = -1, - .data6_io_num = -1, - .data7_io_num = -1, - .max_transfer_sz = 0, - .flags = 0, - .intr_flags = 0, - }; - -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || defined(USE_ESP32_VARIANT_ESP32C6) || \ - defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - auto host = SPI2_HOST; -#else - auto host = SPI3_HOST; -#endif - - err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO); - ESPHL_ERROR_CHECK(err, "SPI bus initialize error"); -#endif - - err = esp_netif_init(); - ESPHL_ERROR_CHECK(err, "ETH netif init error"); - err = esp_event_loop_create_default(); - ESPHL_ERROR_CHECK(err, "ETH event loop error"); - - esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); - this->eth_netif_ = esp_netif_new(&cfg); - - // Init MAC and PHY configs to default - eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); - eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); - -#ifdef USE_ETHERNET_SPI // Configure SPI interface and Ethernet driver for specific SPI module - spi_device_interface_config_t devcfg = { - .command_bits = 0, - .address_bits = 0, - .dummy_bits = 0, - .mode = 0, - .duty_cycle_pos = 0, - .cs_ena_pretrans = 0, - .cs_ena_posttrans = 0, - .clock_speed_hz = this->clock_speed_, - .input_delay_ns = 0, - .spics_io_num = this->cs_pin_, - .flags = 0, - .queue_size = 20, - .pre_cb = nullptr, - .post_cb = nullptr, - }; - -#if CONFIG_ETH_SPI_ETHERNET_W5500 - eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); -#endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 - eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); -#endif - -#if CONFIG_ETH_SPI_ETHERNET_W5500 - w5500_config.int_gpio_num = this->interrupt_pin_; -#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT - w5500_config.poll_period_ms = this->polling_interval_; -#endif -#endif - -#if CONFIG_ETH_SPI_ETHERNET_DM9051 - dm9051_config.int_gpio_num = this->interrupt_pin_; -#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT - dm9051_config.poll_period_ms = this->polling_interval_; -#endif -#endif - - phy_config.phy_addr = this->phy_addr_spi_; - phy_config.reset_gpio_num = this->reset_pin_; - - esp_eth_mac_t *mac = nullptr; -#elif defined(USE_ETHERNET_OPENETH) - esp_eth_mac_t *mac = esp_eth_mac_new_openeth(&mac_config); -#else - phy_config.phy_addr = this->phy_addr_; - phy_config.reset_gpio_num = this->power_pin_; - - eth_esp32_emac_config_t esp32_emac_config = eth_esp32_emac_default_config(); -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) - esp32_emac_config.smi_gpio.mdc_num = this->mdc_pin_; - esp32_emac_config.smi_gpio.mdio_num = this->mdio_pin_; -#else - esp32_emac_config.smi_mdc_gpio_num = this->mdc_pin_; - esp32_emac_config.smi_mdio_gpio_num = this->mdio_pin_; -#endif - esp32_emac_config.clock_config.rmii.clock_mode = this->clk_mode_; - esp32_emac_config.clock_config.rmii.clock_gpio = (emac_rmii_clock_gpio_t) this->clk_pin_; - - esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); -#endif - - switch (this->type_) { -#ifdef USE_ETHERNET_OPENETH - case ETHERNET_TYPE_OPENETH: { - phy_config.autonego_timeout_ms = 1000; - this->phy_ = esp_eth_phy_new_dp83848(&phy_config); - break; - } -#endif -#if CONFIG_ETH_USE_ESP32_EMAC -#ifdef USE_ETHERNET_LAN8720 - case ETHERNET_TYPE_LAN8720: { - this->phy_ = esp_eth_phy_new_lan87xx(&phy_config); - break; - } -#endif -#ifdef USE_ETHERNET_RTL8201 - case ETHERNET_TYPE_RTL8201: { - this->phy_ = esp_eth_phy_new_rtl8201(&phy_config); - break; - } -#endif -#ifdef USE_ETHERNET_DP83848 - case ETHERNET_TYPE_DP83848: { - this->phy_ = esp_eth_phy_new_dp83848(&phy_config); - break; - } -#endif -#ifdef USE_ETHERNET_IP101 - case ETHERNET_TYPE_IP101: { - this->phy_ = esp_eth_phy_new_ip101(&phy_config); - break; - } -#endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) - case ETHERNET_TYPE_JL1101: { - this->phy_ = esp_eth_phy_new_jl1101(&phy_config); - break; - } -#endif -#ifdef USE_ETHERNET_KSZ8081 - case ETHERNET_TYPE_KSZ8081: - case ETHERNET_TYPE_KSZ8081RNA: { - this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config); - break; - } -#endif -#ifdef USE_ETHERNET_LAN8670 - case ETHERNET_TYPE_LAN8670: { - this->phy_ = esp_eth_phy_new_lan867x(&phy_config); - break; - } -#endif -#endif -#ifdef USE_ETHERNET_SPI -#if CONFIG_ETH_SPI_ETHERNET_W5500 - case ETHERNET_TYPE_W5500: { - mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); - this->phy_ = esp_eth_phy_new_w5500(&phy_config); - break; - } -#endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 - case ETHERNET_TYPE_DM9051: { - mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); - this->phy_ = esp_eth_phy_new_dm9051(&phy_config); - break; - } -#endif -#endif - default: { - this->mark_failed(); - return; - } - } - - esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, this->phy_); - this->eth_handle_ = nullptr; - err = esp_eth_driver_install(ð_config, &this->eth_handle_); - ESPHL_ERROR_CHECK(err, "ETH driver install error"); - -#ifndef USE_ETHERNET_SPI -#ifdef USE_ETHERNET_KSZ8081 - if (this->type_ == ETHERNET_TYPE_KSZ8081RNA && this->clk_mode_ == EMAC_CLK_OUT) { - // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. - this->ksz8081_set_clock_reference_(mac); - } -#endif // USE_ETHERNET_KSZ8081 - - for (const auto &phy_register : this->phy_registers_) { - this->write_phy_register_(mac, phy_register); - } -#endif - - // use ESP internal eth mac - uint8_t mac_addr[6]; - if (this->fixed_mac_.has_value()) { - memcpy(mac_addr, this->fixed_mac_->data(), 6); - } else { - esp_read_mac(mac_addr, ESP_MAC_ETH); - } - err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_S_MAC_ADDR, mac_addr); - ESPHL_ERROR_CHECK(err, "set mac address error"); - - /* attach Ethernet driver to TCP/IP stack */ - err = esp_netif_attach(this->eth_netif_, esp_eth_new_netif_glue(this->eth_handle_)); - ESPHL_ERROR_CHECK(err, "ETH netif attach error"); - - // Register user defined event handers - err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &EthernetComponent::eth_event_handler, nullptr); - ESPHL_ERROR_CHECK(err, "ETH event handler register error"); - err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &EthernetComponent::got_ip_event_handler, nullptr); - ESPHL_ERROR_CHECK(err, "GOT IP event handler register error"); -#if USE_NETWORK_IPV6 - err = esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &EthernetComponent::got_ip6_event_handler, nullptr); - ESPHL_ERROR_CHECK(err, "GOT IPv6 event handler register error"); -#endif /* USE_NETWORK_IPV6 */ - - /* start Ethernet driver state machine */ - err = esp_eth_start(this->eth_handle_); - ESPHL_ERROR_CHECK(err, "ETH start error"); -} - -void EthernetComponent::loop() { - const uint32_t now = App.get_loop_component_start_time(); - - switch (this->state_) { - case EthernetComponentState::STOPPED: - if (this->started_) { - ESP_LOGI(TAG, "Starting connection"); - this->state_ = EthernetComponentState::CONNECTING; - this->start_connect_(); - } - break; - case EthernetComponentState::CONNECTING: - if (!this->started_) { - ESP_LOGI(TAG, "Stopped connection"); - this->state_ = EthernetComponentState::STOPPED; - } else if (this->connected_) { - // connection established - ESP_LOGI(TAG, "Connected"); - this->state_ = EthernetComponentState::CONNECTED; - - this->dump_connect_params_(); - this->status_clear_warning(); -#ifdef USE_ETHERNET_CONNECT_TRIGGER - this->connect_trigger_.trigger(); -#endif - } else if (now - this->connect_begin_ > 15000) { - ESP_LOGW(TAG, "Connecting failed; reconnecting"); - this->start_connect_(); - } - break; - case EthernetComponentState::CONNECTED: - if (!this->started_) { - ESP_LOGI(TAG, "Stopped connection"); - this->state_ = EthernetComponentState::STOPPED; -#ifdef USE_ETHERNET_DISCONNECT_TRIGGER - this->disconnect_trigger_.trigger(); -#endif - } else if (!this->connected_) { - ESP_LOGW(TAG, "Connection lost; reconnecting"); - this->state_ = EthernetComponentState::CONNECTING; - this->start_connect_(); -#ifdef USE_ETHERNET_DISCONNECT_TRIGGER - this->disconnect_trigger_.trigger(); -#endif - } else { - this->finish_connect_(); - // When connected and stable, disable the loop to save CPU cycles - this->disable_loop(); - } - break; - } -} - -void EthernetComponent::dump_config() { - const char *eth_type; - switch (this->type_) { -#ifdef USE_ETHERNET_LAN8720 - case ETHERNET_TYPE_LAN8720: - eth_type = "LAN8720"; - break; -#endif -#ifdef USE_ETHERNET_RTL8201 - case ETHERNET_TYPE_RTL8201: - eth_type = "RTL8201"; - break; -#endif -#ifdef USE_ETHERNET_DP83848 - case ETHERNET_TYPE_DP83848: - eth_type = "DP83848"; - break; -#endif -#ifdef USE_ETHERNET_IP101 - case ETHERNET_TYPE_IP101: - eth_type = "IP101"; - break; -#endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) - case ETHERNET_TYPE_JL1101: - eth_type = "JL1101"; - break; -#endif -#ifdef USE_ETHERNET_KSZ8081 - case ETHERNET_TYPE_KSZ8081: - eth_type = "KSZ8081"; - break; - - case ETHERNET_TYPE_KSZ8081RNA: - eth_type = "KSZ8081RNA"; - break; -#endif -#if CONFIG_ETH_SPI_ETHERNET_W5500 - case ETHERNET_TYPE_W5500: - eth_type = "W5500"; - break; -#endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 - case ETHERNET_TYPE_DM9051: - eth_type = "DM9051"; - break; -#endif -#ifdef USE_ETHERNET_OPENETH - case ETHERNET_TYPE_OPENETH: - eth_type = "OPENETH"; - break; -#endif -#ifdef USE_ETHERNET_LAN8670 - case ETHERNET_TYPE_LAN8670: - eth_type = "LAN8670"; - break; -#endif - - default: - eth_type = "Unknown"; - break; - } - - ESP_LOGCONFIG(TAG, - "Ethernet:\n" - " Connected: %s", - YESNO(this->is_connected())); - this->dump_connect_params_(); -#ifdef USE_ETHERNET_SPI - ESP_LOGCONFIG(TAG, - " CLK Pin: %u\n" - " MISO Pin: %u\n" - " MOSI Pin: %u\n" - " CS Pin: %u", - this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_); -#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT - if (this->polling_interval_ != 0) { - ESP_LOGCONFIG(TAG, " Polling Interval: %lu ms", this->polling_interval_); - } else -#endif - { - ESP_LOGCONFIG(TAG, " IRQ Pin: %d", this->interrupt_pin_); - } - ESP_LOGCONFIG(TAG, - " Reset Pin: %d\n" - " Clock Speed: %d MHz", - this->reset_pin_, this->clock_speed_ / 1000000); -#else - if (this->power_pin_ != -1) { - ESP_LOGCONFIG(TAG, " Power Pin: %u", this->power_pin_); - } - ESP_LOGCONFIG(TAG, - " CLK Pin: %u\n" - " MDC Pin: %u\n" - " MDIO Pin: %u\n" - " PHY addr: %u", - this->clk_pin_, this->mdc_pin_, this->mdio_pin_, this->phy_addr_); -#endif - ESP_LOGCONFIG(TAG, " Type: %s", eth_type); -} - float EthernetComponent::get_setup_priority() const { return setup_priority::WIFI; } -network::IPAddresses EthernetComponent::get_ip_addresses() { - network::IPAddresses addresses; - esp_netif_ip_info_t ip; - esp_err_t err = esp_netif_get_ip_info(this->eth_netif_, &ip); - if (err != ESP_OK) { - ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err)); - // TODO: do something smarter - // return false; - } else { - addresses[0] = network::IPAddress(&ip.ip); - } -#if USE_NETWORK_IPV6 - struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; - uint8_t count = 0; - count = esp_netif_get_all_ip6(this->eth_netif_, if_ip6s); - assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); - assert(count < addresses.size()); - for (int i = 0; i < count; i++) { - addresses[i + 1] = network::IPAddress(&if_ip6s[i]); - } -#endif /* USE_NETWORK_IPV6 */ +void EthernetComponent::set_type(EthernetType type) { this->type_ = type; } - return addresses; -} - -network::IPAddress EthernetComponent::get_dns_address(uint8_t num) { - LwIPLock lock; - const ip_addr_t *dns_ip = dns_getserver(num); - return dns_ip; -} - -void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) { - const char *event_name; - - switch (event) { - case ETHERNET_EVENT_START: - event_name = "ETH started"; - global_eth_component->started_ = true; - global_eth_component->enable_loop_soon_any_context(); - break; - case ETHERNET_EVENT_STOP: - event_name = "ETH stopped"; - global_eth_component->started_ = false; - global_eth_component->connected_ = false; - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes - break; - case ETHERNET_EVENT_CONNECTED: - event_name = "ETH connected"; - // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here -#if defined(USE_ETHERNET_IP_STATE_LISTENERS) && defined(USE_ETHERNET_MANUAL_IP) - if (global_eth_component->manual_ip_.has_value()) { - global_eth_component->notify_ip_state_listeners_(); - } +#ifdef USE_ETHERNET_MANUAL_IP +void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; } #endif - break; - case ETHERNET_EVENT_DISCONNECTED: - event_name = "ETH disconnected"; - global_eth_component->connected_ = false; - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes - break; - default: - return; - } - ESP_LOGV(TAG, "[Ethernet event] %s (num=%" PRId32 ")", event_name, event); -} +// set_use_address() is guaranteed to be called during component setup by Python code generation, +// so use_address_ will always be valid when get_use_address() is called - no fallback needed. +const char *EthernetComponent::get_use_address() const { return this->use_address_; } -void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, - void *event_data) { - ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; - const esp_netif_ip_info_t *ip_info = &event->ip_info; - ESP_LOGV(TAG, "[Ethernet event] ETH Got IP " IPSTR, IP2STR(&ip_info->ip)); - global_eth_component->got_ipv4_address_ = true; -#if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) - global_eth_component->connected_ = global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT; - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes -#else - global_eth_component->connected_ = true; - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes -#endif /* USE_NETWORK_IPV6 */ -#ifdef USE_ETHERNET_IP_STATE_LISTENERS - global_eth_component->notify_ip_state_listeners_(); -#endif -} - -#if USE_NETWORK_IPV6 -void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, - void *event_data) { - ip_event_got_ip6_t *event = (ip_event_got_ip6_t *) event_data; - ESP_LOGV(TAG, "[Ethernet event] ETH Got IPv6: " IPV6STR, IPV62STR(event->ip6_info.ip)); - global_eth_component->ipv6_count_ += 1; -#if (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) - global_eth_component->connected_ = - global_eth_component->got_ipv4_address_ && (global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT); - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes -#else - global_eth_component->connected_ = global_eth_component->got_ipv4_address_; - global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes -#endif -#ifdef USE_ETHERNET_IP_STATE_LISTENERS - global_eth_component->notify_ip_state_listeners_(); -#endif -} -#endif /* USE_NETWORK_IPV6 */ +void EthernetComponent::set_use_address(const char *use_address) { this->use_address_ = use_address; } #ifdef USE_ETHERNET_IP_STATE_LISTENERS void EthernetComponent::notify_ip_state_listeners_() { @@ -554,315 +35,6 @@ void EthernetComponent::notify_ip_state_listeners_() { } #endif // USE_ETHERNET_IP_STATE_LISTENERS -void EthernetComponent::finish_connect_() { -#if USE_NETWORK_IPV6 - // Retry IPv6 link-local setup if it failed during initial connect - // This handles the case where min_ipv6_addr_count is NOT set (or is 0), - // allowing us to reach CONNECTED state with just IPv4. - // If IPv6 setup failed in start_connect_() because the interface wasn't ready: - // - Bootup timing issues (#10281) - // - Cable unplugged/network interruption (#10705) - // We can now retry since we're in CONNECTED state and the interface is definitely up. - if (!this->ipv6_setup_done_) { - esp_err_t err = esp_netif_create_ip6_linklocal(this->eth_netif_); - if (err == ESP_OK) { - ESP_LOGD(TAG, "IPv6 link-local address created (retry succeeded)"); - } - // Always set the flag to prevent continuous retries - // If IPv6 setup fails here with the interface up and stable, it's - // likely a persistent issue (IPv6 disabled at router, hardware - // limitation, etc.) that won't be resolved by further retries. - // The device continues to work with IPv4. - this->ipv6_setup_done_ = true; - } -#endif /* USE_NETWORK_IPV6 */ -} - -void EthernetComponent::start_connect_() { - global_eth_component->got_ipv4_address_ = false; -#if USE_NETWORK_IPV6 - global_eth_component->ipv6_count_ = 0; - this->ipv6_setup_done_ = false; -#endif /* USE_NETWORK_IPV6 */ - this->connect_begin_ = millis(); - this->status_set_warning(LOG_STR("waiting for IP configuration")); - - esp_err_t err; - err = esp_netif_set_hostname(this->eth_netif_, App.get_name().c_str()); - if (err != ERR_OK) { - ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err)); - } - - esp_netif_ip_info_t info; -#ifdef USE_ETHERNET_MANUAL_IP - if (this->manual_ip_.has_value()) { - info.ip = this->manual_ip_->static_ip; - info.gw = this->manual_ip_->gateway; - info.netmask = this->manual_ip_->subnet; - } else -#endif - { - info.ip.addr = 0; - info.gw.addr = 0; - info.netmask.addr = 0; - } - - esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT; - - err = esp_netif_dhcpc_get_status(this->eth_netif_, &status); - ESPHL_ERROR_CHECK(err, "DHCPC Get Status Failed!"); - - ESP_LOGV(TAG, "DHCP Client Status: %d", status); - - err = esp_netif_dhcpc_stop(this->eth_netif_); - if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { - ESPHL_ERROR_CHECK(err, "DHCPC stop error"); - } - - err = esp_netif_set_ip_info(this->eth_netif_, &info); - ESPHL_ERROR_CHECK(err, "DHCPC set IP info error"); - -#ifdef USE_ETHERNET_MANUAL_IP - if (this->manual_ip_.has_value()) { - LwIPLock lock; - if (this->manual_ip_->dns1.is_set()) { - ip_addr_t d; - d = this->manual_ip_->dns1; - dns_setserver(0, &d); - } - if (this->manual_ip_->dns2.is_set()) { - ip_addr_t d; - d = this->manual_ip_->dns2; - dns_setserver(1, &d); - } - } else -#endif - { - err = esp_netif_dhcpc_start(this->eth_netif_); - if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { - ESPHL_ERROR_CHECK(err, "DHCPC start error"); - } - } -#if USE_NETWORK_IPV6 - // Attempt to create IPv6 link-local address - // We MUST attempt this here, not just in finish_connect_(), because with - // min_ipv6_addr_count set, the component won't reach CONNECTED state without IPv6. - // However, this may fail with ESP_FAIL if the interface is not up yet: - // - At bootup when link isn't ready (#10281) - // - After disconnection/cable unplugged (#10705) - // We'll retry in finish_connect_() if it fails here. - err = esp_netif_create_ip6_linklocal(this->eth_netif_); - if (err != ESP_OK) { - if (err == ESP_ERR_ESP_NETIF_INVALID_PARAMS) { - // This is a programming error, not a transient failure - ESPHL_ERROR_CHECK(err, "esp_netif_create_ip6_linklocal invalid parameters"); - } else { - // ESP_FAIL means the interface isn't up yet - // This is expected and non-fatal, happens in multiple scenarios: - // - During reconnection after network interruptions (#10705) - // - At bootup when the link isn't ready yet (#10281) - // We'll retry once we reach CONNECTED state and the interface is up - ESP_LOGW(TAG, "esp_netif_create_ip6_linklocal failed: %s", esp_err_to_name(err)); - // Don't mark component as failed - this is a transient error - } - } -#endif /* USE_NETWORK_IPV6 */ - - this->connect_begin_ = millis(); - this->status_set_warning(); -} - -void EthernetComponent::dump_connect_params_() { - esp_netif_ip_info_t ip; - esp_netif_get_ip_info(this->eth_netif_, &ip); - const ip_addr_t *dns_ip1; - const ip_addr_t *dns_ip2; - { - LwIPLock lock; - dns_ip1 = dns_getserver(0); - dns_ip2 = dns_getserver(1); - } - - // Use stack buffers for IP address formatting to avoid heap allocations - char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; - char subnet_buf[network::IP_ADDRESS_BUFFER_SIZE]; - char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE]; - char dns1_buf[network::IP_ADDRESS_BUFFER_SIZE]; - char dns2_buf[network::IP_ADDRESS_BUFFER_SIZE]; - char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; - ESP_LOGCONFIG(TAG, - " IP Address: %s\n" - " Hostname: '%s'\n" - " Subnet: %s\n" - " Gateway: %s\n" - " DNS1: %s\n" - " DNS2: %s\n" - " MAC Address: %s\n" - " Is Full Duplex: %s\n" - " Link Speed: %u", - network::IPAddress(&ip.ip).str_to(ip_buf), App.get_name().c_str(), - network::IPAddress(&ip.netmask).str_to(subnet_buf), network::IPAddress(&ip.gw).str_to(gateway_buf), - network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf), - this->get_eth_mac_address_pretty_into_buffer(mac_buf), - YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); - -#if USE_NETWORK_IPV6 - struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; - uint8_t count = 0; - count = esp_netif_get_all_ip6(this->eth_netif_, if_ip6s); - assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); - for (int i = 0; i < count; i++) { - ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(if_ip6s[i])); - } -#endif /* USE_NETWORK_IPV6 */ -} - -#ifdef USE_ETHERNET_SPI -void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; } -void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; } -void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; } -void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; } -void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } -void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; } -void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; } -#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT -void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; } -#endif -#else -void EthernetComponent::set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; } -void EthernetComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; } -void EthernetComponent::set_mdc_pin(uint8_t mdc_pin) { this->mdc_pin_ = mdc_pin; } -void EthernetComponent::set_mdio_pin(uint8_t mdio_pin) { this->mdio_pin_ = mdio_pin; } -void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; } -void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode) { this->clk_mode_ = clk_mode; } -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; } -#ifdef USE_ETHERNET_MANUAL_IP -void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; } -#endif - -// set_use_address() is guaranteed to be called during component setup by Python code generation, -// so use_address_ will always be valid when get_use_address() is called - no fallback needed. -const char *EthernetComponent::get_use_address() const { return this->use_address_; } - -void EthernetComponent::set_use_address(const char *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() { - char buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; - return std::string(this->get_eth_mac_address_pretty_into_buffer(buf)); -} - -const char *EthernetComponent::get_eth_mac_address_pretty_into_buffer( - std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf) { - uint8_t mac[6]; - get_eth_mac_address_raw(mac); - format_mac_addr_upper(mac, buf.data()); - return buf.data(); -} - -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) { - ESP_LOGE(TAG, "Ethernet PHY not assigned"); - return false; - } - this->connected_ = false; - this->started_ = false; - // No need to enable_loop() here as this is only called during shutdown/reboot - if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) { - ESP_LOGE(TAG, "Error powering down ethernet PHY"); - return false; - } - return true; -} - -#ifndef USE_ETHERNET_SPI - -#ifdef USE_ETHERNET_KSZ8081 -constexpr uint8_t KSZ80XX_PC2R_REG_ADDR = 0x1F; - -void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { - esp_err_t err; - - uint32_t phy_control_2; - err = mac->read_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, &(phy_control_2)); - ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE - char hex_buf[format_hex_pretty_size(PHY_REG_SIZE)]; -#endif - ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty_to(hex_buf, (uint8_t *) &phy_control_2, PHY_REG_SIZE)); - - /* - * 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. - * 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. - */ - if ((phy_control_2 & (1 << 7)) != (1 << 7)) { - phy_control_2 |= 1 << 7; - err = mac->write_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, phy_control_2); - ESPHL_ERROR_CHECK(err, "Write PHY Control 2 failed"); - err = mac->read_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, &(phy_control_2)); - ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); - ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", - format_hex_pretty_to(hex_buf, (uint8_t *) &phy_control_2, PHY_REG_SIZE)); - } -} -#endif // USE_ETHERNET_KSZ8081 - -void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) { - esp_err_t err; - -#ifdef USE_ETHERNET_RTL8201 - constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; - 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"); - } -#endif - - ESP_LOGD(TAG, "Writing PHY reg 0x%02" PRIX32 " = 0x%04" PRIX32, register_data.address, 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"); - -#ifdef USE_ETHERNET_RTL8201 - if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { - ESP_LOGD(TAG, "Select PHY Register Page 0x00"); - 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 -} - -#endif - } // namespace esphome::ethernet -#endif // USE_ESP32 +#endif // USE_ETHERNET diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index f7a0996fb7..80038d50ec 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -7,8 +7,9 @@ #include "esphome/core/automation.h" #include "esphome/components/network/ip_address.h" -#ifdef USE_ESP32 +#ifdef USE_ETHERNET +#ifdef USE_ESP32 #include "esp_eth.h" #include "esp_eth_mac.h" #include "esp_eth_mac_esp.h" @@ -19,6 +20,7 @@ #if CONFIG_ETH_USE_ESP32_EMAC extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); #endif +#endif // USE_ESP32 namespace esphome::ethernet { @@ -73,6 +75,12 @@ enum class EthernetComponentState : uint8_t { CONNECTED, }; +// Platform-neutral duplex/speed types +#ifndef USE_ESP32 +enum eth_duplex_t { ETH_DUPLEX_HALF, ETH_DUPLEX_FULL }; +enum eth_speed_t { ETH_SPEED_10M, ETH_SPEED_100M }; +#endif + class EthernetComponent : public Component { public: EthernetComponent(); @@ -83,6 +91,28 @@ class EthernetComponent : public Component { void on_powerdown() override { powerdown(); } bool is_connected() { return this->state_ == EthernetComponentState::CONNECTED; } + void set_type(EthernetType type); +#ifdef USE_ETHERNET_MANUAL_IP + void set_manual_ip(const ManualIP &manual_ip); +#endif + void set_fixed_mac(const std::array<uint8_t, 6> &mac) { this->fixed_mac_ = mac; } + + network::IPAddresses get_ip_addresses(); + network::IPAddress get_dns_address(uint8_t num); + const char *get_use_address() const; + void set_use_address(const char *use_address); + void get_eth_mac_address_raw(uint8_t *mac); + // Remove before 2026.9.0 + ESPDEPRECATED("Use get_eth_mac_address_pretty_into_buffer() instead. Removed in 2026.9.0", "2026.3.0") + std::string get_eth_mac_address_pretty(); + const char *get_eth_mac_address_pretty_into_buffer(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf); + eth_duplex_t get_duplex_mode(); + eth_speed_t get_link_speed(); + bool powerdown(); + +#ifdef USE_ESP32 + esp_eth_handle_t get_eth_handle() const { return this->eth_handle_; } + #ifdef USE_ETHERNET_SPI void set_clk_pin(uint8_t clk_pin); void set_miso_pin(uint8_t miso_pin); @@ -102,26 +132,8 @@ class EthernetComponent : public Component { void set_clk_pin(uint8_t clk_pin); void set_clk_mode(emac_rmii_clock_mode_t clk_mode); void add_phy_register(PHYRegister register_value); -#endif - void set_type(EthernetType type); -#ifdef USE_ETHERNET_MANUAL_IP - void set_manual_ip(const ManualIP &manual_ip); -#endif - void set_fixed_mac(const std::array<uint8_t, 6> &mac) { this->fixed_mac_ = mac; } - - network::IPAddresses get_ip_addresses(); - network::IPAddress get_dns_address(uint8_t num); - const char *get_use_address() const; - void set_use_address(const char *use_address); - void get_eth_mac_address_raw(uint8_t *mac); - // Remove before 2026.9.0 - ESPDEPRECATED("Use get_eth_mac_address_pretty_into_buffer() instead. Removed in 2026.9.0", "2026.3.0") - std::string get_eth_mac_address_pretty(); - const char *get_eth_mac_address_pretty_into_buffer(std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf); - eth_duplex_t get_duplex_mode(); - eth_speed_t get_link_speed(); - esp_eth_handle_t get_eth_handle() const { return this->eth_handle_; } - bool powerdown(); +#endif // USE_ETHERNET_SPI +#endif // USE_ESP32 #ifdef USE_ETHERNET_IP_STATE_LISTENERS void add_ip_state_listener(EthernetIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); } @@ -133,19 +145,22 @@ class EthernetComponent : public Component { #ifdef USE_ETHERNET_DISCONNECT_TRIGGER Trigger<> *get_disconnect_trigger() { return &this->disconnect_trigger_; } #endif + protected: + void start_connect_(); + void finish_connect_(); + void dump_connect_params_(); + +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + void notify_ip_state_listeners_(); +#endif + +#ifdef USE_ESP32 static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); static void got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); #if LWIP_IPV6 static void got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); #endif /* LWIP_IPV6 */ -#ifdef USE_ETHERNET_IP_STATE_LISTENERS - void notify_ip_state_listeners_(); -#endif - - void start_connect_(); - void finish_connect_(); - void dump_connect_params_(); void log_error_and_mark_failed_(esp_err_t err, const char *message); #ifdef USE_ETHERNET_KSZ8081 /// @brief Set `RMII Reference Clock Select` bit for KSZ8081. @@ -177,7 +192,15 @@ class EthernetComponent : public Component { uint8_t phy_addr_{0}; uint8_t mdc_pin_{23}; uint8_t mdio_pin_{18}; -#endif +#endif // USE_ETHERNET_SPI + + // ESP32 pointers + esp_netif_t *eth_netif_{nullptr}; + esp_eth_handle_t eth_handle_; + esp_eth_phy_t *phy_{nullptr}; +#endif // USE_ESP32 + + // Common members #ifdef USE_ETHERNET_MANUAL_IP optional<ManualIP> manual_ip_{}; #endif @@ -194,10 +217,6 @@ class EthernetComponent : public Component { bool ipv6_setup_done_{false}; #endif /* LWIP_IPV6 */ - // Pointers at the end (naturally aligned) - esp_netif_t *eth_netif_{nullptr}; - esp_eth_handle_t eth_handle_; - esp_eth_phy_t *phy_{nullptr}; optional<std::array<uint8_t, 6>> fixed_mac_; #ifdef USE_ETHERNET_IP_STATE_LISTENERS @@ -219,10 +238,12 @@ class EthernetComponent : public Component { // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern EthernetComponent *global_eth_component; +#ifdef USE_ESP32 #if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) extern "C" esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config); #endif +#endif // USE_ESP32 } // namespace esphome::ethernet -#endif // USE_ESP32 +#endif // USE_ETHERNET diff --git a/esphome/components/ethernet/ethernet_component_esp32.cpp b/esphome/components/ethernet/ethernet_component_esp32.cpp new file mode 100644 index 0000000000..ac8680f3e1 --- /dev/null +++ b/esphome/components/ethernet/ethernet_component_esp32.cpp @@ -0,0 +1,841 @@ +#include "ethernet_component.h" + +#if defined(USE_ETHERNET) && defined(USE_ESP32) + +#include "esphome/core/application.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#include <lwip/dns.h> +#include <cinttypes> +#include "esp_event.h" + +#ifdef USE_ETHERNET_LAN8670 +#include "esp_eth_phy_lan867x.h" +#endif + +#ifdef USE_ETHERNET_SPI +#include <driver/gpio.h> +#include <driver/spi_master.h> +#endif + +namespace esphome::ethernet { + +static const char *const TAG = "ethernet"; + +// PHY register size for hex logging +static constexpr size_t PHY_REG_SIZE = 2; + +void EthernetComponent::log_error_and_mark_failed_(esp_err_t err, const char *message) { + ESP_LOGE(TAG, "%s: (%d) %s", message, err, esp_err_to_name(err)); + this->mark_failed(); +} + +#define ESPHL_ERROR_CHECK(err, message) \ + if ((err) != ESP_OK) { \ + this->log_error_and_mark_failed_(err, message); \ + return; \ + } + +#define ESPHL_ERROR_CHECK_RET(err, message, ret) \ + if ((err) != ESP_OK) { \ + this->log_error_and_mark_failed_(err, message); \ + return ret; \ + } + +void EthernetComponent::loop() { + const uint32_t now = App.get_loop_component_start_time(); + + switch (this->state_) { + case EthernetComponentState::STOPPED: + if (this->started_) { + ESP_LOGI(TAG, "Starting connection"); + this->state_ = EthernetComponentState::CONNECTING; + this->start_connect_(); + } + break; + case EthernetComponentState::CONNECTING: + if (!this->started_) { + ESP_LOGI(TAG, "Stopped connection"); + this->state_ = EthernetComponentState::STOPPED; + } else if (this->connected_) { + // connection established + ESP_LOGI(TAG, "Connected"); + this->state_ = EthernetComponentState::CONNECTED; + + this->dump_connect_params_(); + this->status_clear_warning(); +#ifdef USE_ETHERNET_CONNECT_TRIGGER + this->connect_trigger_.trigger(); +#endif + } else if (now - this->connect_begin_ > 15000) { + ESP_LOGW(TAG, "Connecting failed; reconnecting"); + this->start_connect_(); + } + break; + case EthernetComponentState::CONNECTED: + if (!this->started_) { + ESP_LOGI(TAG, "Stopped connection"); + this->state_ = EthernetComponentState::STOPPED; +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif + } else if (!this->connected_) { + ESP_LOGW(TAG, "Connection lost; reconnecting"); + this->state_ = EthernetComponentState::CONNECTING; + this->start_connect_(); +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif + } else { + this->finish_connect_(); + // When connected and stable, disable the loop to save CPU cycles + this->disable_loop(); + } + break; + } +} + +void EthernetComponent::setup() { + if (esp_reset_reason() != ESP_RST_DEEPSLEEP) { + // Delay here to allow power to stabilise before Ethernet is initialized. + delay(300); // NOLINT + } + + esp_err_t err; + +#ifdef USE_ETHERNET_SPI + // Install GPIO ISR handler to be able to service SPI Eth modules interrupts + gpio_install_isr_service(0); + + spi_bus_config_t buscfg = { + .mosi_io_num = this->mosi_pin_, + .miso_io_num = this->miso_pin_, + .sclk_io_num = this->clk_pin_, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .data4_io_num = -1, + .data5_io_num = -1, + .data6_io_num = -1, + .data7_io_num = -1, + .max_transfer_sz = 0, + .flags = 0, + .intr_flags = 0, + }; + +#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || defined(USE_ESP32_VARIANT_ESP32C6) || \ + defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) + auto host = SPI2_HOST; +#else + auto host = SPI3_HOST; +#endif + + err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO); + ESPHL_ERROR_CHECK(err, "SPI bus initialize error"); +#endif + + err = esp_netif_init(); + ESPHL_ERROR_CHECK(err, "ETH netif init error"); + err = esp_event_loop_create_default(); + ESPHL_ERROR_CHECK(err, "ETH event loop error"); + + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH(); + this->eth_netif_ = esp_netif_new(&cfg); + + // Init MAC and PHY configs to default + eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG(); + eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG(); + +#ifdef USE_ETHERNET_SPI // Configure SPI interface and Ethernet driver for specific SPI module + spi_device_interface_config_t devcfg = { + .command_bits = 0, + .address_bits = 0, + .dummy_bits = 0, + .mode = 0, + .duty_cycle_pos = 0, + .cs_ena_pretrans = 0, + .cs_ena_posttrans = 0, + .clock_speed_hz = this->clock_speed_, + .input_delay_ns = 0, + .spics_io_num = this->cs_pin_, + .flags = 0, + .queue_size = 20, + .pre_cb = nullptr, + .post_cb = nullptr, + }; + +#if CONFIG_ETH_SPI_ETHERNET_W5500 + eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); +#endif +#if CONFIG_ETH_SPI_ETHERNET_DM9051 + eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); +#endif + +#if CONFIG_ETH_SPI_ETHERNET_W5500 + w5500_config.int_gpio_num = this->interrupt_pin_; +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + w5500_config.poll_period_ms = this->polling_interval_; +#endif +#endif + +#if CONFIG_ETH_SPI_ETHERNET_DM9051 + dm9051_config.int_gpio_num = this->interrupt_pin_; +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + dm9051_config.poll_period_ms = this->polling_interval_; +#endif +#endif + + phy_config.phy_addr = this->phy_addr_spi_; + phy_config.reset_gpio_num = this->reset_pin_; + + esp_eth_mac_t *mac = nullptr; +#elif defined(USE_ETHERNET_OPENETH) + esp_eth_mac_t *mac = esp_eth_mac_new_openeth(&mac_config); +#else + phy_config.phy_addr = this->phy_addr_; + phy_config.reset_gpio_num = this->power_pin_; + + eth_esp32_emac_config_t esp32_emac_config = eth_esp32_emac_default_config(); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) + esp32_emac_config.smi_gpio.mdc_num = this->mdc_pin_; + esp32_emac_config.smi_gpio.mdio_num = this->mdio_pin_; +#else + esp32_emac_config.smi_mdc_gpio_num = this->mdc_pin_; + esp32_emac_config.smi_mdio_gpio_num = this->mdio_pin_; +#endif + esp32_emac_config.clock_config.rmii.clock_mode = this->clk_mode_; + esp32_emac_config.clock_config.rmii.clock_gpio = (emac_rmii_clock_gpio_t) this->clk_pin_; + + esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); +#endif + + switch (this->type_) { +#ifdef USE_ETHERNET_OPENETH + case ETHERNET_TYPE_OPENETH: { + phy_config.autonego_timeout_ms = 1000; + this->phy_ = esp_eth_phy_new_dp83848(&phy_config); + break; + } +#endif +#if CONFIG_ETH_USE_ESP32_EMAC +#ifdef USE_ETHERNET_LAN8720 + case ETHERNET_TYPE_LAN8720: { + this->phy_ = esp_eth_phy_new_lan87xx(&phy_config); + break; + } +#endif +#ifdef USE_ETHERNET_RTL8201 + case ETHERNET_TYPE_RTL8201: { + this->phy_ = esp_eth_phy_new_rtl8201(&phy_config); + break; + } +#endif +#ifdef USE_ETHERNET_DP83848 + case ETHERNET_TYPE_DP83848: { + this->phy_ = esp_eth_phy_new_dp83848(&phy_config); + break; + } +#endif +#ifdef USE_ETHERNET_IP101 + case ETHERNET_TYPE_IP101: { + this->phy_ = esp_eth_phy_new_ip101(&phy_config); + break; + } +#endif +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) + case ETHERNET_TYPE_JL1101: { + this->phy_ = esp_eth_phy_new_jl1101(&phy_config); + break; + } +#endif +#ifdef USE_ETHERNET_KSZ8081 + case ETHERNET_TYPE_KSZ8081: + case ETHERNET_TYPE_KSZ8081RNA: { + this->phy_ = esp_eth_phy_new_ksz80xx(&phy_config); + break; + } +#endif +#ifdef USE_ETHERNET_LAN8670 + case ETHERNET_TYPE_LAN8670: { + this->phy_ = esp_eth_phy_new_lan867x(&phy_config); + break; + } +#endif +#endif +#ifdef USE_ETHERNET_SPI +#if CONFIG_ETH_SPI_ETHERNET_W5500 + case ETHERNET_TYPE_W5500: { + mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); + this->phy_ = esp_eth_phy_new_w5500(&phy_config); + break; + } +#endif +#if CONFIG_ETH_SPI_ETHERNET_DM9051 + case ETHERNET_TYPE_DM9051: { + mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); + this->phy_ = esp_eth_phy_new_dm9051(&phy_config); + break; + } +#endif +#endif + default: { + this->mark_failed(); + return; + } + } + + esp_eth_config_t eth_config = ETH_DEFAULT_CONFIG(mac, this->phy_); + this->eth_handle_ = nullptr; + err = esp_eth_driver_install(ð_config, &this->eth_handle_); + ESPHL_ERROR_CHECK(err, "ETH driver install error"); + +#ifndef USE_ETHERNET_SPI +#ifdef USE_ETHERNET_KSZ8081 + if (this->type_ == ETHERNET_TYPE_KSZ8081RNA && this->clk_mode_ == EMAC_CLK_OUT) { + // KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide. + this->ksz8081_set_clock_reference_(mac); + } +#endif // USE_ETHERNET_KSZ8081 + + for (const auto &phy_register : this->phy_registers_) { + this->write_phy_register_(mac, phy_register); + } +#endif + + // use ESP internal eth mac + uint8_t mac_addr[6]; + if (this->fixed_mac_.has_value()) { + memcpy(mac_addr, this->fixed_mac_->data(), 6); + } else { + esp_read_mac(mac_addr, ESP_MAC_ETH); + } + err = esp_eth_ioctl(this->eth_handle_, ETH_CMD_S_MAC_ADDR, mac_addr); + ESPHL_ERROR_CHECK(err, "set mac address error"); + + /* attach Ethernet driver to TCP/IP stack */ + err = esp_netif_attach(this->eth_netif_, esp_eth_new_netif_glue(this->eth_handle_)); + ESPHL_ERROR_CHECK(err, "ETH netif attach error"); + + // Register user defined event handers + err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &EthernetComponent::eth_event_handler, nullptr); + ESPHL_ERROR_CHECK(err, "ETH event handler register error"); + err = esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &EthernetComponent::got_ip_event_handler, nullptr); + ESPHL_ERROR_CHECK(err, "GOT IP event handler register error"); +#if USE_NETWORK_IPV6 + err = esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6, &EthernetComponent::got_ip6_event_handler, nullptr); + ESPHL_ERROR_CHECK(err, "GOT IPv6 event handler register error"); +#endif /* USE_NETWORK_IPV6 */ + + /* start Ethernet driver state machine */ + err = esp_eth_start(this->eth_handle_); + ESPHL_ERROR_CHECK(err, "ETH start error"); +} + +void EthernetComponent::dump_config() { + const char *eth_type; + switch (this->type_) { +#ifdef USE_ETHERNET_LAN8720 + case ETHERNET_TYPE_LAN8720: + eth_type = "LAN8720"; + break; +#endif +#ifdef USE_ETHERNET_RTL8201 + case ETHERNET_TYPE_RTL8201: + eth_type = "RTL8201"; + break; +#endif +#ifdef USE_ETHERNET_DP83848 + case ETHERNET_TYPE_DP83848: + eth_type = "DP83848"; + break; +#endif +#ifdef USE_ETHERNET_IP101 + case ETHERNET_TYPE_IP101: + eth_type = "IP101"; + break; +#endif +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) + case ETHERNET_TYPE_JL1101: + eth_type = "JL1101"; + break; +#endif +#ifdef USE_ETHERNET_KSZ8081 + case ETHERNET_TYPE_KSZ8081: + eth_type = "KSZ8081"; + break; + + case ETHERNET_TYPE_KSZ8081RNA: + eth_type = "KSZ8081RNA"; + break; +#endif +#if CONFIG_ETH_SPI_ETHERNET_W5500 + case ETHERNET_TYPE_W5500: + eth_type = "W5500"; + break; +#endif +#if CONFIG_ETH_SPI_ETHERNET_DM9051 + case ETHERNET_TYPE_DM9051: + eth_type = "DM9051"; + break; +#endif +#ifdef USE_ETHERNET_OPENETH + case ETHERNET_TYPE_OPENETH: + eth_type = "OPENETH"; + break; +#endif +#ifdef USE_ETHERNET_LAN8670 + case ETHERNET_TYPE_LAN8670: + eth_type = "LAN8670"; + break; +#endif + + default: + eth_type = "Unknown"; + break; + } + + ESP_LOGCONFIG(TAG, + "Ethernet:\n" + " Connected: %s", + YESNO(this->is_connected())); + this->dump_connect_params_(); +#ifdef USE_ETHERNET_SPI + ESP_LOGCONFIG(TAG, + " CLK Pin: %u\n" + " MISO Pin: %u\n" + " MOSI Pin: %u\n" + " CS Pin: %u", + this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_); +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT + if (this->polling_interval_ != 0) { + ESP_LOGCONFIG(TAG, " Polling Interval: %" PRIu32 " ms", this->polling_interval_); + } else +#endif + { + ESP_LOGCONFIG(TAG, " IRQ Pin: %d", this->interrupt_pin_); + } + ESP_LOGCONFIG(TAG, + " Reset Pin: %d\n" + " Clock Speed: %d MHz", + this->reset_pin_, this->clock_speed_ / 1000000); +#else + if (this->power_pin_ != -1) { + ESP_LOGCONFIG(TAG, " Power Pin: %u", this->power_pin_); + } + ESP_LOGCONFIG(TAG, + " CLK Pin: %u\n" + " MDC Pin: %u\n" + " MDIO Pin: %u\n" + " PHY addr: %u", + this->clk_pin_, this->mdc_pin_, this->mdio_pin_, this->phy_addr_); +#endif + ESP_LOGCONFIG(TAG, " Type: %s", eth_type); +} + +network::IPAddresses EthernetComponent::get_ip_addresses() { + network::IPAddresses addresses; + esp_netif_ip_info_t ip; + esp_err_t err = esp_netif_get_ip_info(this->eth_netif_, &ip); + if (err != ESP_OK) { + ESP_LOGV(TAG, "esp_netif_get_ip_info failed: %s", esp_err_to_name(err)); + // TODO: do something smarter + // return false; + } else { + addresses[0] = network::IPAddress(&ip.ip); + } +#if USE_NETWORK_IPV6 + struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; + uint8_t count = 0; + count = esp_netif_get_all_ip6(this->eth_netif_, if_ip6s); + assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + assert(count < addresses.size()); + for (int i = 0; i < count; i++) { + addresses[i + 1] = network::IPAddress(&if_ip6s[i]); + } +#endif /* USE_NETWORK_IPV6 */ + + return addresses; +} + +network::IPAddress EthernetComponent::get_dns_address(uint8_t num) { + LwIPLock lock; + const ip_addr_t *dns_ip = dns_getserver(num); + return dns_ip; +} + +void EthernetComponent::eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event, void *event_data) { + const char *event_name; + + switch (event) { + case ETHERNET_EVENT_START: + event_name = "ETH started"; + global_eth_component->started_ = true; + global_eth_component->enable_loop_soon_any_context(); + break; + case ETHERNET_EVENT_STOP: + event_name = "ETH stopped"; + global_eth_component->started_ = false; + global_eth_component->connected_ = false; + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes + break; + case ETHERNET_EVENT_CONNECTED: + event_name = "ETH connected"; + // For static IP configurations, GOT_IP event may not fire, so notify IP listeners here +#if defined(USE_ETHERNET_IP_STATE_LISTENERS) && defined(USE_ETHERNET_MANUAL_IP) + if (global_eth_component->manual_ip_.has_value()) { + global_eth_component->notify_ip_state_listeners_(); + } +#endif + break; + case ETHERNET_EVENT_DISCONNECTED: + event_name = "ETH disconnected"; + global_eth_component->connected_ = false; + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes + break; + default: + return; + } + + ESP_LOGV(TAG, "[Ethernet event] %s (num=%" PRId32 ")", event_name, event); +} + +void EthernetComponent::got_ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) { + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; + const esp_netif_ip_info_t *ip_info = &event->ip_info; + ESP_LOGV(TAG, "[Ethernet event] ETH Got IP " IPSTR, IP2STR(&ip_info->ip)); + global_eth_component->got_ipv4_address_ = true; +#if USE_NETWORK_IPV6 && (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) + global_eth_component->connected_ = global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT; + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes +#else + global_eth_component->connected_ = true; + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes +#endif /* USE_NETWORK_IPV6 */ +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + global_eth_component->notify_ip_state_listeners_(); +#endif +} + +#if USE_NETWORK_IPV6 +void EthernetComponent::got_ip6_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) { + ip_event_got_ip6_t *event = (ip_event_got_ip6_t *) event_data; + ESP_LOGV(TAG, "[Ethernet event] ETH Got IPv6: " IPV6STR, IPV62STR(event->ip6_info.ip)); + global_eth_component->ipv6_count_ += 1; +#if (USE_NETWORK_MIN_IPV6_ADDR_COUNT > 0) + global_eth_component->connected_ = + global_eth_component->got_ipv4_address_ && (global_eth_component->ipv6_count_ >= USE_NETWORK_MIN_IPV6_ADDR_COUNT); + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes +#else + global_eth_component->connected_ = global_eth_component->got_ipv4_address_; + global_eth_component->enable_loop_soon_any_context(); // Enable loop when connection state changes +#endif +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + global_eth_component->notify_ip_state_listeners_(); +#endif +} +#endif /* USE_NETWORK_IPV6 */ + +void EthernetComponent::finish_connect_() { +#if USE_NETWORK_IPV6 + // Retry IPv6 link-local setup if it failed during initial connect + // This handles the case where min_ipv6_addr_count is NOT set (or is 0), + // allowing us to reach CONNECTED state with just IPv4. + // If IPv6 setup failed in start_connect_() because the interface wasn't ready: + // - Bootup timing issues (#10281) + // - Cable unplugged/network interruption (#10705) + // We can now retry since we're in CONNECTED state and the interface is definitely up. + if (!this->ipv6_setup_done_) { + esp_err_t err = esp_netif_create_ip6_linklocal(this->eth_netif_); + if (err == ESP_OK) { + ESP_LOGD(TAG, "IPv6 link-local address created (retry succeeded)"); + } + // Always set the flag to prevent continuous retries + // If IPv6 setup fails here with the interface up and stable, it's + // likely a persistent issue (IPv6 disabled at router, hardware + // limitation, etc.) that won't be resolved by further retries. + // The device continues to work with IPv4. + this->ipv6_setup_done_ = true; + } +#endif /* USE_NETWORK_IPV6 */ +} + +void EthernetComponent::start_connect_() { + global_eth_component->got_ipv4_address_ = false; +#if USE_NETWORK_IPV6 + global_eth_component->ipv6_count_ = 0; + this->ipv6_setup_done_ = false; +#endif /* USE_NETWORK_IPV6 */ + this->connect_begin_ = millis(); + this->status_set_warning(LOG_STR("waiting for IP configuration")); + + esp_err_t err; + err = esp_netif_set_hostname(this->eth_netif_, App.get_name().c_str()); + if (err != ERR_OK) { + ESP_LOGW(TAG, "esp_netif_set_hostname failed: %s", esp_err_to_name(err)); + } + + esp_netif_ip_info_t info; +#ifdef USE_ETHERNET_MANUAL_IP + if (this->manual_ip_.has_value()) { + info.ip = this->manual_ip_->static_ip; + info.gw = this->manual_ip_->gateway; + info.netmask = this->manual_ip_->subnet; + } else +#endif + { + info.ip.addr = 0; + info.gw.addr = 0; + info.netmask.addr = 0; + } + + esp_netif_dhcp_status_t status = ESP_NETIF_DHCP_INIT; + + err = esp_netif_dhcpc_get_status(this->eth_netif_, &status); + ESPHL_ERROR_CHECK(err, "DHCPC Get Status Failed!"); + + ESP_LOGV(TAG, "DHCP Client Status: %d", status); + + err = esp_netif_dhcpc_stop(this->eth_netif_); + if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED) { + ESPHL_ERROR_CHECK(err, "DHCPC stop error"); + } + + err = esp_netif_set_ip_info(this->eth_netif_, &info); + ESPHL_ERROR_CHECK(err, "DHCPC set IP info error"); + +#ifdef USE_ETHERNET_MANUAL_IP + if (this->manual_ip_.has_value()) { + LwIPLock lock; + if (this->manual_ip_->dns1.is_set()) { + ip_addr_t d; + d = this->manual_ip_->dns1; + dns_setserver(0, &d); + } + if (this->manual_ip_->dns2.is_set()) { + ip_addr_t d; + d = this->manual_ip_->dns2; + dns_setserver(1, &d); + } + } else +#endif + { + err = esp_netif_dhcpc_start(this->eth_netif_); + if (err != ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED) { + ESPHL_ERROR_CHECK(err, "DHCPC start error"); + } + } +#if USE_NETWORK_IPV6 + // Attempt to create IPv6 link-local address + // We MUST attempt this here, not just in finish_connect_(), because with + // min_ipv6_addr_count set, the component won't reach CONNECTED state without IPv6. + // However, this may fail with ESP_FAIL if the interface is not up yet: + // - At bootup when link isn't ready (#10281) + // - After disconnection/cable unplugged (#10705) + // We'll retry in finish_connect_() if it fails here. + err = esp_netif_create_ip6_linklocal(this->eth_netif_); + if (err != ESP_OK) { + if (err == ESP_ERR_ESP_NETIF_INVALID_PARAMS) { + // This is a programming error, not a transient failure + ESPHL_ERROR_CHECK(err, "esp_netif_create_ip6_linklocal invalid parameters"); + } else { + // ESP_FAIL means the interface isn't up yet + // This is expected and non-fatal, happens in multiple scenarios: + // - During reconnection after network interruptions (#10705) + // - At bootup when the link isn't ready yet (#10281) + // We'll retry once we reach CONNECTED state and the interface is up + ESP_LOGW(TAG, "esp_netif_create_ip6_linklocal failed: %s", esp_err_to_name(err)); + // Don't mark component as failed - this is a transient error + } + } +#endif /* USE_NETWORK_IPV6 */ + + this->connect_begin_ = millis(); + this->status_set_warning(); +} + +void EthernetComponent::dump_connect_params_() { + esp_netif_ip_info_t ip; + esp_netif_get_ip_info(this->eth_netif_, &ip); + const ip_addr_t *dns_ip1; + const ip_addr_t *dns_ip2; + { + LwIPLock lock; + dns_ip1 = dns_getserver(0); + dns_ip2 = dns_getserver(1); + } + + // Use stack buffers for IP address formatting to avoid heap allocations + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char subnet_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char dns1_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char dns2_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + ESP_LOGCONFIG(TAG, + " IP Address: %s\n" + " Hostname: '%s'\n" + " Subnet: %s\n" + " Gateway: %s\n" + " DNS1: %s\n" + " DNS2: %s\n" + " MAC Address: %s\n" + " Is Full Duplex: %s\n" + " Link Speed: %u", + network::IPAddress(&ip.ip).str_to(ip_buf), App.get_name().c_str(), + network::IPAddress(&ip.netmask).str_to(subnet_buf), network::IPAddress(&ip.gw).str_to(gateway_buf), + network::IPAddress(dns_ip1).str_to(dns1_buf), network::IPAddress(dns_ip2).str_to(dns2_buf), + this->get_eth_mac_address_pretty_into_buffer(mac_buf), + YESNO(this->get_duplex_mode() == ETH_DUPLEX_FULL), this->get_link_speed() == ETH_SPEED_100M ? 100 : 10); + +#if USE_NETWORK_IPV6 + struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES]; + uint8_t count = 0; + count = esp_netif_get_all_ip6(this->eth_netif_, if_ip6s); + assert(count <= CONFIG_LWIP_IPV6_NUM_ADDRESSES); + for (int i = 0; i < count; i++) { + ESP_LOGCONFIG(TAG, " IPv6: " IPV6STR, IPV62STR(if_ip6s[i])); + } +#endif /* USE_NETWORK_IPV6 */ +} + +#ifdef USE_ETHERNET_SPI +void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; } +void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; } +void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; } +void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; } +void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } +void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; } +void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; } +#ifdef USE_ETHERNET_SPI_POLLING_SUPPORT +void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; } +#endif +#else +void EthernetComponent::set_phy_addr(uint8_t phy_addr) { this->phy_addr_ = phy_addr; } +void EthernetComponent::set_power_pin(int power_pin) { this->power_pin_ = power_pin; } +void EthernetComponent::set_mdc_pin(uint8_t mdc_pin) { this->mdc_pin_ = mdc_pin; } +void EthernetComponent::set_mdio_pin(uint8_t mdio_pin) { this->mdio_pin_ = mdio_pin; } +void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; } +void EthernetComponent::set_clk_mode(emac_rmii_clock_mode_t clk_mode) { this->clk_mode_ = clk_mode; } +void EthernetComponent::add_phy_register(PHYRegister register_value) { this->phy_registers_.push_back(register_value); } +#endif + +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() { + char buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + return std::string(this->get_eth_mac_address_pretty_into_buffer(buf)); +} + +const char *EthernetComponent::get_eth_mac_address_pretty_into_buffer( + std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf) { + uint8_t mac[6]; + get_eth_mac_address_raw(mac); + format_mac_addr_upper(mac, buf.data()); + return buf.data(); +} + +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) { + ESP_LOGE(TAG, "Ethernet PHY not assigned"); + return false; + } + this->connected_ = false; + this->started_ = false; + // No need to enable_loop() here as this is only called during shutdown/reboot + if (this->phy_->pwrctl(this->phy_, false) != ESP_OK) { + ESP_LOGE(TAG, "Error powering down ethernet PHY"); + return false; + } + return true; +} + +#ifndef USE_ETHERNET_SPI + +#ifdef USE_ETHERNET_KSZ8081 +constexpr uint8_t KSZ80XX_PC2R_REG_ADDR = 0x1F; + +void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) { + esp_err_t err; + + uint32_t phy_control_2; + err = mac->read_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, &(phy_control_2)); + ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char hex_buf[format_hex_pretty_size(PHY_REG_SIZE)]; +#endif + ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty_to(hex_buf, (uint8_t *) &phy_control_2, PHY_REG_SIZE)); + + /* + * 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. + * 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. + */ + if ((phy_control_2 & (1 << 7)) != (1 << 7)) { + phy_control_2 |= 1 << 7; + err = mac->write_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, phy_control_2); + ESPHL_ERROR_CHECK(err, "Write PHY Control 2 failed"); + err = mac->read_phy_reg(mac, this->phy_addr_, KSZ80XX_PC2R_REG_ADDR, &(phy_control_2)); + ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed"); + ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", + format_hex_pretty_to(hex_buf, (uint8_t *) &phy_control_2, PHY_REG_SIZE)); + } +} +#endif // USE_ETHERNET_KSZ8081 + +void EthernetComponent::write_phy_register_(esp_eth_mac_t *mac, PHYRegister register_data) { + esp_err_t err; + +#ifdef USE_ETHERNET_RTL8201 + constexpr uint8_t eth_phy_psr_reg_addr = 0x1F; + 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"); + } +#endif + + ESP_LOGD(TAG, "Writing PHY reg 0x%02" PRIX32 " = 0x%04" PRIX32, register_data.address, 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"); + +#ifdef USE_ETHERNET_RTL8201 + if (this->type_ == ETHERNET_TYPE_RTL8201 && register_data.page) { + ESP_LOGD(TAG, "Select PHY Register Page 0x00"); + 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 +} + +#endif + +} // namespace esphome::ethernet + +#endif // USE_ETHERNET && USE_ESP32 diff --git a/esphome/components/ethernet/ethernet_helpers.c b/esphome/components/ethernet/ethernet_helpers.c index 963db3ff1c..49fbe825c8 100644 --- a/esphome/components/ethernet/ethernet_helpers.c +++ b/esphome/components/ethernet/ethernet_helpers.c @@ -1,3 +1,5 @@ +#include "esphome/core/defines.h" +#ifdef USE_ESP32 #include "esp_eth_mac_esp.h" // ETH_ESP32_EMAC_DEFAULT_CONFIG() uses out-of-order designated initializers @@ -8,3 +10,4 @@ eth_esp32_emac_config_t eth_esp32_emac_default_config(void) { return (eth_esp32_emac_config_t) ETH_ESP32_EMAC_DEFAULT_CONFIG(); } #endif +#endif // USE_ESP32 diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp index 72ce9c86e2..15ef6a1f20 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.cpp @@ -1,7 +1,7 @@ #include "ethernet_info_text_sensor.h" #include "esphome/core/log.h" -#ifdef USE_ESP32 +#ifdef USE_ETHERNET namespace esphome::ethernet_info { @@ -49,4 +49,4 @@ void MACAddressEthernetInfo::dump_config() { LOG_TEXT_SENSOR("", "EthernetInfo M } // namespace esphome::ethernet_info -#endif // USE_ESP32 +#endif // USE_ETHERNET diff --git a/esphome/components/ethernet_info/ethernet_info_text_sensor.h b/esphome/components/ethernet_info/ethernet_info_text_sensor.h index 912a39a83f..11002d51ba 100644 --- a/esphome/components/ethernet_info/ethernet_info_text_sensor.h +++ b/esphome/components/ethernet_info/ethernet_info_text_sensor.h @@ -4,7 +4,7 @@ #include "esphome/components/text_sensor/text_sensor.h" #include "esphome/components/ethernet/ethernet_component.h" -#ifdef USE_ESP32 +#ifdef USE_ETHERNET namespace esphome::ethernet_info { @@ -50,4 +50,4 @@ class MACAddressEthernetInfo final : public Component, public text_sensor::TextS } // namespace esphome::ethernet_info -#endif // USE_ESP32 +#endif // USE_ETHERNET diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 073170aafb..75e63b1462 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -278,6 +278,12 @@ #define USE_ETHERNET_JL1101 #define USE_ETHERNET_KSZ8081 #define USE_ETHERNET_LAN8670 +#define USE_ETHERNET_SPI +#define USE_ETHERNET_SPI_POLLING_SUPPORT +#define USE_ETHERNET_OPENETH +#define CONFIG_ETH_SPI_ETHERNET_W5500 1 +#define CONFIG_ETH_SPI_ETHERNET_DM9051 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 #define USE_ETHERNET_MANUAL_IP #define USE_ETHERNET_IP_STATE_LISTENERS #define USE_ETHERNET_CONNECT_TRIGGER From ccb467b219409fc8d5632f81af531c423437fba7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 18:14:41 -1000 Subject: [PATCH 1413/2030] [fastled] Include esp_lcd IDF component for ESP32-S3 compatibility (#14839) --- esphome/components/fastled_base/__init__.py | 5 +++++ tests/components/fastled_clockless/test.esp32-s3-ard.yaml | 1 + 2 files changed, 6 insertions(+) create mode 100644 tests/components/fastled_clockless/test.esp32-s3-ard.yaml diff --git a/esphome/components/fastled_base/__init__.py b/esphome/components/fastled_base/__init__.py index 11e8423258..c944e8a930 100644 --- a/esphome/components/fastled_base/__init__.py +++ b/esphome/components/fastled_base/__init__.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_OUTPUT_ID, CONF_RGB_ORDER, ) +from esphome.core import CORE CODEOWNERS = ["@OttoWinter"] fastled_base_ns = cg.esphome_ns.namespace("fastled_base") @@ -41,5 +42,9 @@ async def new_fastled_light(config): cg.add(var.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE])) cg.add_library("fastled/FastLED", "3.9.16") + if CORE.is_esp32: + from esphome.components.esp32 import include_builtin_idf_component + + include_builtin_idf_component("esp_lcd") await light.register_light(var, config) return var diff --git a/tests/components/fastled_clockless/test.esp32-s3-ard.yaml b/tests/components/fastled_clockless/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/fastled_clockless/test.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 9948adc6a004c2961f7c578f5fd329a030784bb4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 18:15:01 -1000 Subject: [PATCH 1414/2030] [runtime_image] Add esp-dsp dependency for JPEGDEC SIMD on ESP32 (#14840) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/runtime_image/__init__.py | 8 ++++++++ esphome/idf_component.yml | 2 ++ .../online_image/test.esp32-s3-ard.yaml | 19 +++++++++++++++++++ .../online_image/test.esp32-s3-idf.yaml | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/components/online_image/test.esp32-s3-ard.yaml create mode 100644 tests/components/online_image/test.esp32-s3-idf.yaml diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py index 7c22bfc9d1..3ae35cc5f1 100644 --- a/esphome/components/runtime_image/__init__.py +++ b/esphome/components/runtime_image/__init__.py @@ -11,6 +11,7 @@ from esphome.components.image import ( ) import esphome.config_validation as cv from esphome.const import CONF_FORMAT, CONF_ID, CONF_RESIZE, CONF_TYPE +from esphome.core import CORE AUTO_LOAD = ["image"] CODEOWNERS = ["@guillempages", "@clydebarrow", "@kahrendt"] @@ -75,6 +76,13 @@ class JPEGFormat(Format): def actions(self) -> None: cg.add_define("USE_RUNTIME_IMAGE_JPEG") cg.add_library("JPEGDEC", "1.8.4", "https://github.com/bitbank2/JPEGDEC#1.8.4") + if CORE.is_esp32: + from esphome.components.esp32 import add_idf_component + + # JPEGDEC uses ESP32-S3 SIMD optimizations (guarded by board-level + # ARDUINO_ESP32S3_DEV define) that require esp-dsp headers. + # On Arduino this overwrites the stub; on IDF it adds the component. + add_idf_component(name="espressif/esp-dsp", ref="1.7.1") class PNGFormat(Format): diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 1e2d452919..59876e8b3d 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -5,6 +5,8 @@ dependencies: version: 2.0.3 esphome/micro-opus: version: 0.3.5 + espressif/esp-dsp: + version: "1.7.1" espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: diff --git a/tests/components/online_image/test.esp32-s3-ard.yaml b/tests/components/online_image/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..9116fd86e0 --- /dev/null +++ b/tests/components/online_image/test.esp32-s3-ard.yaml @@ -0,0 +1,19 @@ +packages: + spi: !include ../../test_build_components/common/spi/esp32-s3-ard.yaml + +<<: !include common.yaml + +http_request: + +display: + - platform: ili9xxx + spi_id: spi_bus + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 13 + reset_pin: 21 + invert_colors: true + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/online_image/test.esp32-s3-idf.yaml b/tests/components/online_image/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..f219f71ee2 --- /dev/null +++ b/tests/components/online_image/test.esp32-s3-idf.yaml @@ -0,0 +1,19 @@ +packages: + spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml + +<<: !include common.yaml + +http_request: + +display: + - platform: ili9xxx + spi_id: spi_bus + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 13 + reset_pin: 21 + invert_colors: true + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); From c09edb94c1984add3e28fcbe56003800d588ae15 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 16 Mar 2026 00:04:07 -0500 Subject: [PATCH 1415/2030] [tinyusb] Fix regression from bump to 2.x in #14796 (#14848) --- .../components/tinyusb/tinyusb_component.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/components/tinyusb/tinyusb_component.cpp b/esphome/components/tinyusb/tinyusb_component.cpp index 7f8fea5264..2ec696c3e4 100644 --- a/esphome/components/tinyusb/tinyusb_component.cpp +++ b/esphome/components/tinyusb/tinyusb_component.cpp @@ -2,6 +2,7 @@ #include "tinyusb_component.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "tinyusb_default_config.h" namespace esphome::tinyusb { @@ -15,19 +16,19 @@ void TinyUSB::setup() { this->string_descriptor_[SERIAL_NUMBER] = mac_addr_buf; } - this->tusb_cfg_ = { - .port = TINYUSB_PORT_FULL_SPEED_0, - .phy = {.skip_setup = false}, - .descriptor = - { - .device = &this->usb_descriptor_, - .string = this->string_descriptor_, - .string_count = SIZE, - }, + // Start from esp_tinyusb defaults to keep required task settings valid across esp_tinyusb updates. + this->tusb_cfg_ = TINYUSB_DEFAULT_CONFIG(); + this->tusb_cfg_.port = TINYUSB_PORT_FULL_SPEED_0; + this->tusb_cfg_.phy.skip_setup = false; + this->tusb_cfg_.descriptor = { + .device = &this->usb_descriptor_, + .string = this->string_descriptor_, + .string_count = SIZE, }; esp_err_t result = tinyusb_driver_install(&this->tusb_cfg_); if (result != ESP_OK) { + ESP_LOGE(TAG, "tinyusb_driver_install failed: %s", esp_err_to_name(result)); this->mark_failed(); } } From 1183ef825b6d1fbb316b1df150d846bac0c09aeb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 01:09:55 -0400 Subject: [PATCH 1416/2030] [usb_host] Fix ESP-IDF 6.0 compatibility for external USB host component (#14844) --- esphome/components/usb_host/__init__.py | 5 +++++ esphome/idf_component.yml | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/esphome/components/usb_host/__init__.py b/esphome/components/usb_host/__init__.py index e4c11be489..5eb0371e5c 100644 --- a/esphome/components/usb_host/__init__.py +++ b/esphome/components/usb_host/__init__.py @@ -4,7 +4,9 @@ from esphome.components.esp32 import ( VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, + add_idf_component, add_idf_sdkconfig_option, + idf_version, only_on_variant, ) import esphome.config_validation as cv @@ -64,6 +66,9 @@ async def register_usb_client(config): async def to_code(config: ConfigType) -> None: + # IDF 6.0 moved USB host to an external component + if idf_version() >= cv.Version(6, 0, 0): + add_idf_component(name="espressif/usb", ref="1.3.0") add_idf_sdkconfig_option("CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE", 1024) if config.get(CONF_ENABLE_HUBS): add_idf_sdkconfig_option("CONFIG_USB_HOST_HUBS_SUPPORTED", True) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 59876e8b3d..c949c3b026 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -43,5 +43,9 @@ dependencies: version: "1.0.0" rules: - if: "idf_version >=6.0.0" + espressif/usb: + version: "1.3.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32s2, esp32s3, esp32p4]" esp32async/asynctcp: version: 3.4.91 From e1252e32d146d547c54edfd54d69e4b91c65f5ff Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 01:10:30 -0400 Subject: [PATCH 1417/2030] [deep_sleep] Fix ESP-IDF 6.0 GPIO wakeup API rename (#14846) --- esphome/components/deep_sleep/deep_sleep_esp32.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/deep_sleep/deep_sleep_esp32.cpp b/esphome/components/deep_sleep/deep_sleep_esp32.cpp index 79c34f627a..4f4d262d30 100644 --- a/esphome/components/deep_sleep/deep_sleep_esp32.cpp +++ b/esphome/components/deep_sleep/deep_sleep_esp32.cpp @@ -3,6 +3,7 @@ #include "driver/gpio.h" #include "deep_sleep_component.h" #include "esphome/core/log.h" +#include <esp_idf_version.h> namespace esphome { namespace deep_sleep { @@ -26,7 +27,7 @@ namespace deep_sleep { // - ext0: Single pin wakeup using RTC GPIO (esp_sleep_enable_ext0_wakeup) // - ext1: Multiple pin wakeup (esp_sleep_enable_ext1_wakeup) // - Touch: Touch pad wakeup (esp_sleep_enable_touchpad_wakeup) -// - GPIO wakeup: GPIO wakeup for RTC pins (esp_deep_sleep_enable_gpio_wakeup) +// - GPIO wakeup: GPIO wakeup for RTC pins static const char *const TAG = "deep_sleep"; @@ -135,8 +136,13 @@ void DeepSleepComponent::deep_sleep_() { } // Internal pullup/pulldown resistors are enabled automatically, when // ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS is set (by default it is) - esp_deep_sleep_enable_gpio_wakeup(1 << this->wakeup_pin_->get_pin(), +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(1ULL << this->wakeup_pin_->get_pin(), + static_cast<esp_sleep_gpio_wake_up_mode_t>(level)); +#else + esp_deep_sleep_enable_gpio_wakeup(1ULL << this->wakeup_pin_->get_pin(), static_cast<esp_deepsleep_gpio_wake_up_mode_t>(level)); +#endif } #endif From 2ee0df1da3d5dc2e025cbe1ae5b352c523bc61d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 05:43:38 +0000 Subject: [PATCH 1418/2030] Bump aioesphomeapi from 44.5.1 to 44.5.2 (#14849) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e634bcb104..da95dd5a13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.5.1 +aioesphomeapi==44.5.2 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 414182fe6d9ca2173631843338c690c9e304ea5d Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Mon, 16 Mar 2026 08:08:05 +0100 Subject: [PATCH 1419/2030] [ble_nus] fix uart debug (#14850) --- esphome/components/ble_nus/ble_nus.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index d0d37dbf1c..2f60f81471 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -67,14 +67,14 @@ bool BLENUS::read_array(uint8_t *data, size_t len) { // First, use the peek buffer if available if (this->has_peek_) { +#ifdef USE_UART_DEBUGGER + this->debug_callback_.call(uart::UART_DIRECTION_RX, this->peek_buffer_); +#endif data[0] = this->peek_buffer_; this->has_peek_ = false; data++; if (--len == 0) { // Decrement len first, then check it... -#ifdef USE_UART_DEBUGGER - this->debug_callback_.call(uart::UART_DIRECTION_RX, this->peek_buffer_); -#endif - return true; // No more to read + return true; // No more to read } } From f86bb2bdb045e97392caa4ef6ce35048bd3d4d93 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 02:02:59 -1000 Subject: [PATCH 1420/2030] [ethernet] Add IDF 6.0 registry component dependencies (#14847) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/components/ethernet/__init__.py | 69 ++++++++++++++++++- .../components/ethernet/esp_eth_phy_jl1101.c | 3 +- .../components/ethernet/ethernet_component.h | 3 +- .../ethernet/ethernet_component_esp32.cpp | 59 +++++++++++++--- esphome/core/defines.h | 2 + esphome/idf_component.yml | 28 ++++++++ 6 files changed, 149 insertions(+), 15 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 83bef4d91c..e1ceefeacd 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass import logging from esphome import automation, pins @@ -35,6 +36,7 @@ from esphome.const import ( CONF_VALUE, KEY_CORE, KEY_FRAMEWORK_VERSION, + KEY_NATIVE_IDF, Platform, PlatformFramework, ) @@ -53,6 +55,9 @@ LOGGER = logging.getLogger(__name__) # Key for tracking IP state listener count in CORE.data ETHERNET_IP_STATE_LISTENERS_KEY = "ethernet_ip_state_listeners" +# Key for tracking configured ethernet type +ETHERNET_TYPE_KEY = "ethernet_type" +KEY_ETHERNET = "ethernet" def request_ethernet_ip_state_listener() -> None: @@ -126,9 +131,32 @@ _PHY_TYPE_TO_DEFINE = { "JL1101": "USE_ETHERNET_JL1101", "KSZ8081": "USE_ETHERNET_KSZ8081", "KSZ8081RNA": "USE_ETHERNET_KSZ8081", + "W5500": "USE_ETHERNET_W5500", + "DM9051": "USE_ETHERNET_DM9051", "LAN8670": "USE_ETHERNET_LAN8670", } + +@dataclass(frozen=True) +class IDFRegistryComponent: + """An ESP-IDF component from the Espressif Component Registry.""" + + name: str + version: str + + +# IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry. +_IDF6_ETHERNET_COMPONENTS: dict[str, IDFRegistryComponent] = { + "LAN8720": IDFRegistryComponent("espressif/lan87xx", "1.0.0"), + "RTL8201": IDFRegistryComponent("espressif/rtl8201", "1.0.1"), + "DP83848": IDFRegistryComponent("espressif/dp83848", "1.0.0"), + "IP101": IDFRegistryComponent("espressif/ip101", "1.0.0"), + "KSZ8081": IDFRegistryComponent("espressif/ksz80xx", "1.0.0"), + "KSZ8081RNA": IDFRegistryComponent("espressif/ksz80xx", "1.0.0"), + "W5500": IDFRegistryComponent("espressif/w5500", "1.0.1"), + "DM9051": IDFRegistryComponent("espressif/dm9051", "1.0.0"), +} + SPI_ETHERNET_TYPES = ["W5500", "DM9051"] SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) @@ -406,6 +434,7 @@ async def to_code(config): cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) + CORE.data.setdefault(KEY_ETHERNET, {})[ETHERNET_TYPE_KEY] = config[CONF_TYPE] if CONF_MANUAL_IP in config: cg.add_define("USE_ETHERNET_MANUAL_IP") @@ -439,6 +468,7 @@ async def _to_code_esp32(var, config): from esphome.components.esp32 import ( add_idf_component, add_idf_sdkconfig_option, + idf_version, include_builtin_idf_component, ) @@ -459,7 +489,11 @@ async def _to_code_esp32(var, config): cg.add_define("USE_ETHERNET_SPI") add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) - add_idf_sdkconfig_option(f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True) + # CONFIG_ETH_SPI_ETHERNET_{TYPE} Kconfig options were removed in IDF 6.0 + if idf_version() < cv.Version(6, 0, 0): + add_idf_sdkconfig_option( + f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True + ) elif config[CONF_TYPE] == "OPENETH": cg.add_define("USE_ETHERNET_OPENETH") add_idf_sdkconfig_option("CONFIG_ETH_USE_OPENETH", True) @@ -491,6 +525,12 @@ async def _to_code_esp32(var, config): # Add LAN867x 10BASE-T1S PHY support component add_idf_component(name="espressif/lan867x", ref="2.0.0") + # IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry + if idf_version() >= cv.Version(6, 0, 0) and ( + component := _IDF6_ETHERNET_COMPONENTS.get(config[CONF_TYPE]) + ): + add_idf_component(name=component.name, ref=component.version) + def _final_validate_rmii_pins(config: ConfigType) -> None: """Validate that RMII pins are not used by other components.""" @@ -565,11 +605,36 @@ async def final_step(): cg.add_define("ESPHOME_ETHERNET_IP_STATE_LISTENERS", ip_state_count) -FILTER_SOURCE_FILES = filter_source_files_from_platform( +_platform_filter = filter_source_files_from_platform( { "ethernet_component_esp32.cpp": { PlatformFramework.ESP32_IDF, PlatformFramework.ESP32_ARDUINO, }, + "esp_eth_phy_jl1101.c": { + PlatformFramework.ESP32_IDF, + PlatformFramework.ESP32_ARDUINO, + }, } ) + + +def _filter_source_files() -> list[str]: + excluded = _platform_filter() + eth_data = CORE.data.get(KEY_ETHERNET, {}) + eth_type = eth_data.get(ETHERNET_TYPE_KEY) + # Only compile the custom JL1101 driver when JL1101 is configured + # and pioarduino doesn't have it builtin (IDF 5.4.2 to 5.x) + if eth_type != "JL1101": + excluded.append("esp_eth_phy_jl1101.c") + elif CORE.is_esp32 and not CORE.data.get(KEY_NATIVE_IDF, False): + from esphome.components.esp32 import idf_version + + # pioarduino has JL1101 builtin on IDF 5.4.2-5.x; exclude custom driver + # to avoid shadowing. Native IDF builds always need the custom driver. + if cv.Version(5, 4, 2) <= idf_version() < cv.Version(6, 0, 0): + excluded.append("esp_eth_phy_jl1101.c") + return excluded + + +FILTER_SOURCE_FILES = _filter_source_files diff --git a/esphome/components/ethernet/esp_eth_phy_jl1101.c b/esphome/components/ethernet/esp_eth_phy_jl1101.c index b81d8227d4..46671a2dd0 100644 --- a/esphome/components/ethernet/esp_eth_phy_jl1101.c +++ b/esphome/components/ethernet/esp_eth_phy_jl1101.c @@ -29,7 +29,8 @@ #include "esp_rom_sys.h" #include "esp_idf_version.h" -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) || \ + ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) static const char *TAG = "jl1101"; #define PHY_CHECK(a, str, goto_tag, ...) \ diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 80038d50ec..cc73c01df4 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -239,7 +239,8 @@ class EthernetComponent : public Component { extern EthernetComponent *global_eth_component; #ifdef USE_ESP32 -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) || \ + ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) extern "C" esp_eth_phy_t *esp_eth_phy_new_jl1101(const eth_phy_config_t *config); #endif #endif // USE_ESP32 diff --git a/esphome/components/ethernet/ethernet_component_esp32.cpp b/esphome/components/ethernet/ethernet_component_esp32.cpp index ac8680f3e1..fb69a901aa 100644 --- a/esphome/components/ethernet/ethernet_component_esp32.cpp +++ b/esphome/components/ethernet/ethernet_component_esp32.cpp @@ -10,6 +10,36 @@ #include <cinttypes> #include "esp_event.h" +// IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry; +// they are no longer included via esp_eth.h and need explicit includes. +// On IDF 5.x these headers don't exist as standalone files. +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) +#ifdef USE_ETHERNET_LAN8720 +#include "esp_eth_phy_lan87xx.h" +#endif +#ifdef USE_ETHERNET_RTL8201 +#include "esp_eth_phy_rtl8201.h" +#endif +#ifdef USE_ETHERNET_DP83848 +#include "esp_eth_phy_dp83848.h" +#endif +#ifdef USE_ETHERNET_IP101 +#include "esp_eth_phy_ip101.h" +#endif +#ifdef USE_ETHERNET_KSZ8081 +#include "esp_eth_phy_ksz80xx.h" +#endif +#ifdef USE_ETHERNET_W5500 +#include "esp_eth_mac_w5500.h" +#include "esp_eth_phy_w5500.h" +#endif +#ifdef USE_ETHERNET_DM9051 +#include "esp_eth_mac_dm9051.h" +#include "esp_eth_phy_dm9051.h" +#endif +#endif // ESP_IDF_VERSION >= 6.0.0 + +// LAN867x header exists on all IDF versions (external component since IDF 5.3) #ifdef USE_ETHERNET_LAN8670 #include "esp_eth_phy_lan867x.h" #endif @@ -164,21 +194,21 @@ void EthernetComponent::setup() { .post_cb = nullptr, }; -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); #endif -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 w5500_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT w5500_config.poll_period_ms = this->polling_interval_; #endif #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 dm9051_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT dm9051_config.poll_period_ms = this->polling_interval_; @@ -204,7 +234,8 @@ void EthernetComponent::setup() { esp32_emac_config.smi_mdio_gpio_num = this->mdio_pin_; #endif esp32_emac_config.clock_config.rmii.clock_mode = this->clk_mode_; - esp32_emac_config.clock_config.rmii.clock_gpio = (emac_rmii_clock_gpio_t) this->clk_pin_; + esp32_emac_config.clock_config.rmii.clock_gpio = + static_cast<decltype(esp32_emac_config.clock_config.rmii.clock_gpio)>(this->clk_pin_); esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config); #endif @@ -213,7 +244,11 @@ void EthernetComponent::setup() { #ifdef USE_ETHERNET_OPENETH case ETHERNET_TYPE_OPENETH: { phy_config.autonego_timeout_ms = 1000; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + this->phy_ = esp_eth_phy_new_generic(&phy_config); +#else this->phy_ = esp_eth_phy_new_dp83848(&phy_config); +#endif break; } #endif @@ -242,8 +277,10 @@ void EthernetComponent::setup() { break; } #endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: { + // PlatformIO (pioarduino): builtin esp_eth_phy_new_jl1101() on all IDF versions + // Non-PlatformIO: custom ESPHome driver (esp_eth_phy_jl1101.c) this->phy_ = esp_eth_phy_new_jl1101(&phy_config); break; } @@ -263,14 +300,14 @@ void EthernetComponent::setup() { #endif #endif #ifdef USE_ETHERNET_SPI -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 case ETHERNET_TYPE_W5500: { mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); this->phy_ = esp_eth_phy_new_w5500(&phy_config); break; } #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 case ETHERNET_TYPE_DM9051: { mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); this->phy_ = esp_eth_phy_new_dm9051(&phy_config); @@ -354,7 +391,7 @@ void EthernetComponent::dump_config() { eth_type = "IP101"; break; #endif -#if defined(USE_ETHERNET_JL1101) && (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 4, 2) || !defined(PLATFORMIO)) +#ifdef USE_ETHERNET_JL1101 case ETHERNET_TYPE_JL1101: eth_type = "JL1101"; break; @@ -368,12 +405,12 @@ void EthernetComponent::dump_config() { eth_type = "KSZ8081RNA"; break; #endif -#if CONFIG_ETH_SPI_ETHERNET_W5500 +#ifdef USE_ETHERNET_W5500 case ETHERNET_TYPE_W5500: eth_type = "W5500"; break; #endif -#if CONFIG_ETH_SPI_ETHERNET_DM9051 +#ifdef USE_ETHERNET_DM9051 case ETHERNET_TYPE_DM9051: eth_type = "DM9051"; break; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 75e63b1462..513c70e17e 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -281,6 +281,8 @@ #define USE_ETHERNET_SPI #define USE_ETHERNET_SPI_POLLING_SUPPORT #define USE_ETHERNET_OPENETH +#define USE_ETHERNET_W5500 +#define USE_ETHERNET_DM9051 #define CONFIG_ETH_SPI_ETHERNET_W5500 1 #define CONFIG_ETH_SPI_ETHERNET_DM9051 1 #define CONFIG_ETH_USE_ESP32_EMAC 1 diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index c949c3b026..1478d9544e 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -31,6 +31,34 @@ dependencies: version: "2.0.0" rules: - if: "target in [esp32, esp32p4]" + espressif/lan87xx: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/rtl8201: + version: "1.0.1" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/dp83848: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/ip101: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/ksz80xx: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0 && target in [esp32, esp32p4]" + espressif/w5500: + version: "1.0.1" + rules: + - if: "idf_version >=6.0.0" + espressif/dm9051: + version: "1.0.0" + rules: + - if: "idf_version >=6.0.0" espressif/esp_tinyusb: version: "2.1.1" rules: From 2cd93daa5e57eb22c64ba98d67f38818cf4b7957 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 07:32:58 -1000 Subject: [PATCH 1421/2030] [api] Optimize plaintext varint encoding and devirtualize write_protobuf_packet (#14758) --- esphome/components/api/api_frame_helper.h | 12 +++++++++--- .../components/api/api_frame_helper_noise.cpp | 8 -------- esphome/components/api/api_frame_helper_noise.h | 1 - .../api/api_frame_helper_plaintext.cpp | 17 +++++++---------- .../components/api/api_frame_helper_plaintext.h | 1 - esphome/components/api/proto.h | 14 ++++++++++---- 6 files changed, 26 insertions(+), 27 deletions(-) diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index b2561f2b32..e78c71507c 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -12,6 +12,7 @@ #include "esphome/components/socket/socket.h" #include "esphome/core/application.h" #include "esphome/core/log.h" +#include "proto.h" namespace esphome::api { @@ -37,8 +38,6 @@ static constexpr uint16_t RX_BUF_NULL_TERMINATOR = 1; // Must be >= MAX_INITIAL_PER_BATCH in api_connection.h (enforced by static_assert there) static constexpr size_t MAX_MESSAGES_PER_BATCH = 34; -class ProtoWriteBuffer; - // Max client name length (e.g., "Home Assistant 2026.1.0.dev0" = 28 chars) static constexpr size_t CLIENT_INFO_NAME_MAX_LEN = 32; @@ -161,7 +160,14 @@ class APIFrameHelper { this->nodelay_counter_ = 0; } } - virtual APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) = 0; + APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { + // Resize buffer to include footer space if needed (e.g. Noise MAC) + if (frame_footer_size_) + buffer.get_buffer()->resize(buffer.get_buffer()->size() + frame_footer_size_); + MessageInfo msg{type, 0, + static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)}; + return write_protobuf_messages(buffer, std::span<const MessageInfo>(&msg, 1)); + } // Write multiple protobuf messages in a single operation // messages contains (message_type, offset, length) for each message in the buffer // The buffer contains all messages with appropriate padding before each diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index f945253c89..b635d84f16 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -450,14 +450,6 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) { buffer->type = type; return APIError::OK; } -APIError APINoiseFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { - // Resize to include MAC space (required for Noise encryption) - buffer.get_buffer()->resize(buffer.get_buffer()->size() + frame_footer_size_); - MessageInfo msg{type, 0, - static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_ - frame_footer_size_)}; - return write_protobuf_messages(buffer, std::span<const MessageInfo>(&msg, 1)); -} - APIError APINoiseFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) { APIError aerr = this->check_data_state_(); if (aerr != APIError::OK) diff --git a/esphome/components/api/api_frame_helper_noise.h b/esphome/components/api/api_frame_helper_noise.h index 83410febb2..a6b17ff3b9 100644 --- a/esphome/components/api/api_frame_helper_noise.h +++ b/esphome/components/api/api_frame_helper_noise.h @@ -22,7 +22,6 @@ class APINoiseFrameHelper final : public APIFrameHelper { APIError init() override; APIError loop() override; APIError read_packet(ReadPacketBuffer *buffer) override; - APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override; APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) override; protected: diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index 007da7ef2b..e97b558fa3 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -235,11 +235,6 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { buffer->type = this->rx_header_parsed_type_; return APIError::OK; } -APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { - MessageInfo msg{type, 0, static_cast<uint16_t>(buffer.get_buffer()->size() - frame_header_padding_)}; - return write_protobuf_messages(buffer, std::span<const MessageInfo>(&msg, 1)); -} - APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) { APIError aerr = this->check_data_state_(); @@ -257,9 +252,11 @@ APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffe uint16_t total_write_len = 0; for (const auto &msg : messages) { - // Calculate varint sizes for header layout - uint8_t size_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(msg.payload_size)); - uint8_t type_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(msg.message_type)); + // Calculate varint sizes for header layout using inline ternary to avoid varint_slow call overhead + uint8_t size_varint_len = msg.payload_size < ProtoSize::VARINT_THRESHOLD_1_BYTE + ? 1 + : (msg.payload_size < ProtoSize::VARINT_THRESHOLD_2_BYTE ? 2 : 3); + uint8_t type_varint_len = msg.message_type < ProtoSize::VARINT_THRESHOLD_1_BYTE ? 1 : 2; uint8_t total_header_len = 1 + size_varint_len + type_varint_len; // Calculate where to start writing the header @@ -281,8 +278,8 @@ APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffe // // Example 3 (large values): total_header_len = 6, header_offset = 6 - 6 = 0 // [0] - 0x00 indicator byte - // [1-3] - Payload size varint (3 bytes, for sizes 16384-2097151) - // [4-5] - Message type varint (2 bytes, for types 128-32767) + // [1-3] - Payload size varint (3 bytes, for sizes 16384-65535) + // [4-5] - Message type varint (2 bytes, for types 128-16383) // [6...] - Actual payload data // // The message starts at offset + frame_header_padding_ diff --git a/esphome/components/api/api_frame_helper_plaintext.h b/esphome/components/api/api_frame_helper_plaintext.h index 96d47e9c7b..f8161c039d 100644 --- a/esphome/components/api/api_frame_helper_plaintext.h +++ b/esphome/components/api/api_frame_helper_plaintext.h @@ -19,7 +19,6 @@ class APIPlaintextFrameHelper final : public APIFrameHelper { APIError init() override; APIError loop() override; APIError read_packet(ReadPacketBuffer *buffer) override; - APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override; APIError write_protobuf_messages(ProtoWriteBuffer buffer, std::span<const MessageInfo> messages) override; protected: diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 814a3f4456..6752dfb9cd 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -473,6 +473,12 @@ class ProtoDecodableMessage : public ProtoMessage { class ProtoSize { public: + // Varint encoding thresholds: values below each threshold fit in N bytes + static constexpr uint32_t VARINT_THRESHOLD_1_BYTE = 1 << 7; // 128 + static constexpr uint32_t VARINT_THRESHOLD_2_BYTE = 1 << 14; // 16384 + static constexpr uint32_t VARINT_THRESHOLD_3_BYTE = 1 << 21; // 2097152 + static constexpr uint32_t VARINT_THRESHOLD_4_BYTE = 1 << 28; // 268435456 + /** * @brief Calculates the size in bytes needed to encode a uint32_t value as a varint * @@ -480,7 +486,7 @@ class ProtoSize { * @return The number of bytes needed to encode the value */ static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint(uint32_t value) { - if (value < 128) [[likely]] + if (value < VARINT_THRESHOLD_1_BYTE) [[likely]] return 1; // Fast path: 7 bits, most common case if (__builtin_is_constant_evaluated()) return varint_wide(value); @@ -492,11 +498,11 @@ class ProtoSize { static uint32_t varint_slow(uint32_t value) __attribute__((noinline)); // Shared cascade for values >= 128 (used by both constexpr and noinline paths) static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint_wide(uint32_t value) { - if (value < 16384) + if (value < VARINT_THRESHOLD_2_BYTE) return 2; - if (value < 2097152) + if (value < VARINT_THRESHOLD_3_BYTE) return 3; - if (value < 268435456) + if (value < VARINT_THRESHOLD_4_BYTE) return 4; return 5; } From 7b4af76a61a37aeeeac00f747adcab4d4b742c28 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 07:33:10 -1000 Subject: [PATCH 1422/2030] [core] Inline Mutex on all embedded platforms (#14756) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/components/esp32/helpers.cpp | 6 ------ esphome/components/esp8266/helpers.cpp | 8 ++----- esphome/components/libretiny/helpers.cpp | 6 ------ esphome/components/rp2040/helpers.cpp | 7 +----- esphome/core/helpers.h | 27 ++++++++++++++++++------ 5 files changed, 24 insertions(+), 30 deletions(-) diff --git a/esphome/components/esp32/helpers.cpp b/esphome/components/esp32/helpers.cpp index 051b7ce162..76f1c59c73 100644 --- a/esphome/components/esp32/helpers.cpp +++ b/esphome/components/esp32/helpers.cpp @@ -20,12 +20,6 @@ bool random_bytes(uint8_t *data, size_t len) { return true; } -Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); } -Mutex::~Mutex() {} -void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); } -bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; } -void Mutex::unlock() { xSemaphoreGive(this->handle_); } - // only affects the executing core // so should not be used as a mutex lock, only to get accurate timing IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); } diff --git a/esphome/components/esp8266/helpers.cpp b/esphome/components/esp8266/helpers.cpp index 4a64ae181e..aadfc31197 100644 --- a/esphome/components/esp8266/helpers.cpp +++ b/esphome/components/esp8266/helpers.cpp @@ -12,12 +12,8 @@ namespace esphome { uint32_t random_uint32() { return os_random(); } bool random_bytes(uint8_t *data, size_t len) { return os_get_random(data, len) == 0; } -// ESP8266 doesn't have mutexes, but that shouldn't be an issue as it's single-core and non-preemptive OS. -Mutex::Mutex() {} -Mutex::~Mutex() {} -void Mutex::lock() {} -bool Mutex::try_lock() { return true; } -void Mutex::unlock() {} +// ESP8266 Mutex is defined inline as a no-op in helpers.h when USE_ESP8266 (or USE_RP2040) is set, +// independent of the ESPHOME_THREAD_SINGLE thread model define. IRAM_ATTR InterruptLock::InterruptLock() { state_ = xt_rsil(15); } IRAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(state_); } diff --git a/esphome/components/libretiny/helpers.cpp b/esphome/components/libretiny/helpers.cpp index 21913e4a16..ffbd181c54 100644 --- a/esphome/components/libretiny/helpers.cpp +++ b/esphome/components/libretiny/helpers.cpp @@ -15,12 +15,6 @@ bool random_bytes(uint8_t *data, size_t len) { return true; } -Mutex::Mutex() { handle_ = xSemaphoreCreateMutex(); } -Mutex::~Mutex() {} -void Mutex::lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); } -bool Mutex::try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; } -void Mutex::unlock() { xSemaphoreGive(this->handle_); } - // only affects the executing core // so should not be used as a mutex lock, only to get accurate timing IRAM_ATTR InterruptLock::InterruptLock() { portDISABLE_INTERRUPTS(); } diff --git a/esphome/components/rp2040/helpers.cpp b/esphome/components/rp2040/helpers.cpp index 4191c2164a..a69b8da480 100644 --- a/esphome/components/rp2040/helpers.cpp +++ b/esphome/components/rp2040/helpers.cpp @@ -35,12 +35,7 @@ bool random_bytes(uint8_t *data, size_t len) { return true; } -// RP2040 doesn't have mutexes, but that shouldn't be an issue as it's single-core and non-preemptive OS. -Mutex::Mutex() {} -Mutex::~Mutex() {} -void Mutex::lock() {} -bool Mutex::try_lock() { return true; } -void Mutex::unlock() {} +// RP2040 Mutex is defined inline in helpers.h for RP2040/ESP8266 builds. IRAM_ATTR InterruptLock::InterruptLock() { state_ = save_and_disable_interrupts(); } IRAM_ATTR InterruptLock::~InterruptLock() { restore_interrupts(state_); } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index c2f4cace9a..d220626bcf 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1866,19 +1866,34 @@ template<typename T> class Parented { */ class Mutex { public: - Mutex(); Mutex(const Mutex &) = delete; + Mutex &operator=(const Mutex &) = delete; + +#if defined(USE_ESP8266) || defined(USE_RP2040) + // Single-threaded platforms: inline no-ops so the compiler eliminates all call overhead. + Mutex() = default; + ~Mutex() = default; + void lock() {} + bool try_lock() { return true; } + void unlock() {} +#elif defined(USE_ESP32) || defined(USE_LIBRETINY) + // FreeRTOS platforms: inline to avoid out-of-line call overhead. + Mutex() { handle_ = xSemaphoreCreateMutex(); } + ~Mutex() = default; + void lock() { xSemaphoreTake(this->handle_, portMAX_DELAY); } + bool try_lock() { return xSemaphoreTake(this->handle_, 0) == pdTRUE; } + void unlock() { xSemaphoreGive(this->handle_); } + + private: + SemaphoreHandle_t handle_; +#else + Mutex(); ~Mutex(); void lock(); bool try_lock(); void unlock(); - Mutex &operator=(const Mutex &) = delete; - private: -#if defined(USE_ESP32) || defined(USE_LIBRETINY) - SemaphoreHandle_t handle_; -#else // d-pointer to store private data on new platforms void *handle_; // NOLINT(clang-diagnostic-unused-private-field) #endif From 7131eafc09b69eb8da0e1587435a90c4bda84b98 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 07:35:04 -1000 Subject: [PATCH 1423/2030] [logger] Reduce per-message overhead by inlining hot path helpers (#14851) --- esphome/components/logger/log_buffer.h | 31 ++++++++++++------- esphome/components/logger/logger.h | 18 ++++++++++- esphome/components/logger/logger_esp32.cpp | 17 ---------- esphome/components/logger/logger_esp32.h | 28 +++++++++++++++++ esphome/components/logger/logger_esp8266.cpp | 5 --- esphome/components/logger/logger_esp8266.h | 13 ++++++++ .../components/logger/logger_libretiny.cpp | 2 -- esphome/components/logger/logger_libretiny.h | 13 ++++++++ esphome/components/logger/logger_rp2040.cpp | 5 --- esphome/components/logger/logger_rp2040.h | 13 ++++++++ 10 files changed, 103 insertions(+), 42 deletions(-) create mode 100644 esphome/components/logger/logger_esp32.h create mode 100644 esphome/components/logger/logger_esp8266.h create mode 100644 esphome/components/logger/logger_libretiny.h create mode 100644 esphome/components/logger/logger_rp2040.h diff --git a/esphome/components/logger/log_buffer.h b/esphome/components/logger/log_buffer.h index a56276f732..734cb14dc5 100644 --- a/esphome/components/logger/log_buffer.h +++ b/esphome/components/logger/log_buffer.h @@ -111,7 +111,12 @@ struct LogBuffer { } #endif void write_body(const char *text, uint16_t text_length) { - this->write_(text, text_length); + const uint16_t available = this->remaining_(); + const uint16_t copy_len = (text_length < available) ? text_length : available; + if (copy_len > 0) { + memcpy(this->current_(), text, copy_len); + this->pos += copy_len; + } this->finalize_(); } @@ -119,21 +124,23 @@ struct LogBuffer { bool full_() const { return this->pos >= this->size; } uint16_t remaining_() const { return this->size - this->pos; } char *current_() { return this->data + this->pos; } - void write_(const char *value, uint16_t length) { - const uint16_t available = this->remaining_(); - const uint16_t copy_len = (length < available) ? length : available; - if (copy_len > 0) { - memcpy(this->current_(), value, copy_len); - this->pos += copy_len; - } - } void finalize_() { - // Write color reset sequence - static constexpr uint16_t RESET_COLOR_LEN = sizeof(ESPHOME_LOG_RESET_COLOR) - 1; - this->write_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN); + this->write_ansi_reset_(); // Null terminate this->data[this->full_() ? this->size - 1 : this->pos] = '\0'; } + // Write ANSI reset sequence inline ("\033[0m") - avoids write_() call overhead + static constexpr uint16_t ANSI_RESET_LEN = 4; // "\033[0m" + void write_ansi_reset_() { + if (this->remaining_() >= ANSI_RESET_LEN) { + char *p = this->current_(); + *p++ = '\033'; + *p++ = '['; + *p++ = '0'; + *p++ = 'm'; + this->pos += ANSI_RESET_LEN; + } + } void strip_trailing_newlines_() { while (this->pos > 0 && this->data[this->pos - 1] == '\n') this->pos--; diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 263d12b444..8c38cadcbc 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -233,7 +233,11 @@ class Logger final : public Component { void cdc_loop_(); #endif void process_messages_(); +#if defined(USE_HOST) || defined(USE_ZEPHYR) void write_msg_(const char *msg, uint16_t len); +#else + inline void write_msg_(const char *msg, uint16_t len); // Defined in platform-specific logger_*.h +#endif // Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator // thread_name: name of the calling thread/task, or nullptr for main task (callers already know which task they're on) @@ -366,7 +370,7 @@ class Logger final : public Component { bool non_main_task_recursion_guard_{false}; // Shared guard for all non-main tasks on LibreTiny #endif #else - bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms + bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms #endif // Large buffer placed last to keep frequently-accessed member offsets small @@ -498,3 +502,15 @@ class LoggerMessageTrigger final : public Trigger<uint8_t, const char *, const c }; } // namespace esphome::logger + +// Platform-specific inline implementations of write_msg_() +// Must be included after the Logger class definition is complete +#if defined(USE_ESP32) +#include "logger_esp32.h" +#elif defined(USE_ESP8266) +#include "logger_esp8266.h" +#elif defined(USE_RP2040) +#include "logger_rp2040.h" +#elif defined(USE_LIBRETINY) +#include "logger_libretiny.h" +#endif diff --git a/esphome/components/logger/logger_esp32.cpp b/esphome/components/logger/logger_esp32.cpp index f5bf782289..8e0c00267a 100644 --- a/esphome/components/logger/logger_esp32.cpp +++ b/esphome/components/logger/logger_esp32.cpp @@ -123,23 +123,6 @@ void Logger::pre_setup() { #endif } -void HOT Logger::write_msg_(const char *msg, uint16_t len) { -#if defined(USE_LOGGER_UART_SELECTION_USB_CDC) || defined(USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG) - // USB CDC/JTAG - single write including newline (already in buffer) - // Use fwrite to stdout which goes through VFS to USB console - // - // Note: These defines indicate the user's YAML configuration choice (hardware_uart: USB_CDC/USB_SERIAL_JTAG). - // They are ONLY defined when the user explicitly selects USB as the logger output in their config. - // This is compile-time selection, not runtime detection - if USB is configured, it's always used. - // There is no fallback to regular UART if "USB isn't connected" - that's the user's responsibility - // to configure correctly for their hardware. This approach eliminates runtime overhead. - fwrite(msg, 1, len, stdout); -#else - // Regular UART - single write including newline (already in buffer) - uart_write_bytes(this->uart_num_, msg, len); -#endif -} - const LogString *Logger::get_uart_selection_() { switch (this->uart_) { case UART_SELECTION_UART0: diff --git a/esphome/components/logger/logger_esp32.h b/esphome/components/logger/logger_esp32.h new file mode 100644 index 0000000000..905111c718 --- /dev/null +++ b/esphome/components/logger/logger_esp32.h @@ -0,0 +1,28 @@ +#pragma once + +#ifdef USE_ESP32 +#include "esphome/core/helpers.h" +#include <driver/uart.h> + +namespace esphome::logger { + +inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { +#if defined(USE_LOGGER_UART_SELECTION_USB_CDC) || defined(USE_LOGGER_UART_SELECTION_USB_SERIAL_JTAG) + // USB CDC/JTAG - single write including newline (already in buffer) + // Use fwrite to stdout which goes through VFS to USB console + // + // Note: These defines indicate the user's YAML configuration choice (hardware_uart: USB_CDC/USB_SERIAL_JTAG). + // They are ONLY defined when the user explicitly selects USB as the logger output in their config. + // This is compile-time selection, not runtime detection - if USB is configured, it's always used. + // There is no fallback to regular UART if "USB isn't connected" - that's the user's responsibility + // to configure correctly for their hardware. This approach eliminates runtime overhead. + fwrite(msg, 1, len, stdout); +#else + // Regular UART - single write including newline (already in buffer) + uart_write_bytes(this->uart_num_, msg, len); +#endif +} + +} // namespace esphome::logger + +#endif diff --git a/esphome/components/logger/logger_esp8266.cpp b/esphome/components/logger/logger_esp8266.cpp index 0a3433d132..b9507e707a 100644 --- a/esphome/components/logger/logger_esp8266.cpp +++ b/esphome/components/logger/logger_esp8266.cpp @@ -28,11 +28,6 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, uint16_t len) { - // Single write with newline already in buffer (added by caller) - this->hw_serial_->write(msg, len); -} - const LogString *Logger::get_uart_selection_() { #if defined(USE_ESP8266_LOGGER_SERIAL) if (this->uart_ == UART_SELECTION_UART0_SWAP) { diff --git a/esphome/components/logger/logger_esp8266.h b/esphome/components/logger/logger_esp8266.h new file mode 100644 index 0000000000..719c10f7ba --- /dev/null +++ b/esphome/components/logger/logger_esp8266.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef USE_ESP8266 +#include "esphome/core/helpers.h" + +namespace esphome::logger { + +// Single write with newline already in buffer (added by caller) +inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); } + +} // namespace esphome::logger + +#endif diff --git a/esphome/components/logger/logger_libretiny.cpp b/esphome/components/logger/logger_libretiny.cpp index aab8a97abf..bc3922c436 100644 --- a/esphome/components/logger/logger_libretiny.cpp +++ b/esphome/components/logger/logger_libretiny.cpp @@ -49,8 +49,6 @@ void Logger::pre_setup() { ESP_LOGI(TAG, "Log initialized"); } -void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); } - const LogString *Logger::get_uart_selection_() { switch (this->uart_) { case UART_SELECTION_DEFAULT: diff --git a/esphome/components/logger/logger_libretiny.h b/esphome/components/logger/logger_libretiny.h new file mode 100644 index 0000000000..7b1f174ff9 --- /dev/null +++ b/esphome/components/logger/logger_libretiny.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef USE_LIBRETINY +#include "esphome/core/helpers.h" + +namespace esphome::logger { + +// Single write with newline already in buffer (added by caller) +inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); } + +} // namespace esphome::logger + +#endif diff --git a/esphome/components/logger/logger_rp2040.cpp b/esphome/components/logger/logger_rp2040.cpp index b7225c2a25..a0215ec9ec 100644 --- a/esphome/components/logger/logger_rp2040.cpp +++ b/esphome/components/logger/logger_rp2040.cpp @@ -34,11 +34,6 @@ void Logger::pre_setup() { #endif } -void HOT Logger::write_msg_(const char *msg, uint16_t len) { - // Single write with newline already in buffer (added by caller) - this->hw_serial_->write(msg, len); -} - const LogString *Logger::get_uart_selection_() { switch (this->uart_) { case UART_SELECTION_UART0: diff --git a/esphome/components/logger/logger_rp2040.h b/esphome/components/logger/logger_rp2040.h new file mode 100644 index 0000000000..604d8b8ca6 --- /dev/null +++ b/esphome/components/logger/logger_rp2040.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef USE_RP2040 +#include "esphome/core/helpers.h" + +namespace esphome::logger { + +// Single write with newline already in buffer (added by caller) +inline void HOT Logger::write_msg_(const char *msg, uint16_t len) { this->hw_serial_->write(msg, len); } + +} // namespace esphome::logger + +#endif From 808c7b67b3ad3c85b7241bd96134b4844fb2b502 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 07:35:19 -1000 Subject: [PATCH 1424/2030] [core] Inline WarnIfComponentBlockingGuard::finish() into header (#14798) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/core/component.cpp | 13 ++++--------- esphome/core/component.h | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 761f1bd485..bfe9beb272 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -510,7 +510,8 @@ void PollingComponent::stop_poller() { uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } -static void __attribute__((noinline, cold)) warn_blocking(Component *component, uint32_t blocking_time) { +void __attribute__((noinline, cold)) +WarnIfComponentBlockingGuard::warn_blocking(Component *component, uint32_t blocking_time) { bool should_warn; if (component != nullptr) { should_warn = component->should_warn_of_blocking(blocking_time); @@ -524,10 +525,8 @@ static void __attribute__((noinline, cold)) warn_blocking(Component *component, } } -uint32_t WarnIfComponentBlockingGuard::finish() { - uint32_t curr_time = millis(); - uint32_t blocking_time = curr_time - this->started_; #ifdef USE_RUNTIME_STATS +void WarnIfComponentBlockingGuard::record_runtime_stats_() { // Use micros() for accurate sub-millisecond timing. millis() has insufficient // resolution — most components complete in microseconds but millis() only has // 1ms granularity, so results were essentially random noise. @@ -535,12 +534,8 @@ uint32_t WarnIfComponentBlockingGuard::finish() { uint32_t duration_us = micros() - this->started_us_; global_runtime_stats->record_component_time(this->component_, duration_us); } -#endif - if (blocking_time > WARN_IF_BLOCKING_OVER_MS) { - warn_blocking(this->component_, blocking_time); - } - return curr_time; } +#endif #ifdef USE_SETUP_PRIORITY_OVERRIDE void clear_setup_priority_overrides() { diff --git a/esphome/core/component.h b/esphome/core/component.h index 1aac1c7219..5fdf23e128 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -6,6 +6,7 @@ #include <string> #include "esphome/core/defines.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/optional.h" @@ -575,9 +576,7 @@ class PollingComponent : public Component { uint32_t update_interval_; }; -#ifdef USE_RUNTIME_STATS -uint32_t micros(); // Forward declare for inline constructor -#endif +// millis() and micros() are available via hal.h class WarnIfComponentBlockingGuard { public: @@ -592,7 +591,18 @@ class WarnIfComponentBlockingGuard { } // Finish the timing operation and return the current time - uint32_t finish(); + // Inlined: the fast path is just millis() + subtract + compare + inline uint32_t HOT finish() { + uint32_t curr_time = millis(); + uint32_t blocking_time = curr_time - this->started_; +#ifdef USE_RUNTIME_STATS + this->record_runtime_stats_(); +#endif + if (blocking_time > WARN_IF_BLOCKING_OVER_MS) [[unlikely]] { + warn_blocking(this->component_, blocking_time); + } + return curr_time; + } ~WarnIfComponentBlockingGuard() = default; @@ -601,7 +611,12 @@ class WarnIfComponentBlockingGuard { Component *component_; #ifdef USE_RUNTIME_STATS uint32_t started_us_; + void record_runtime_stats_(); #endif + + private: + // Cold path for blocking warning - defined in component.cpp + static void __attribute__((noinline, cold)) warn_blocking(Component *component, uint32_t blocking_time); }; // Function to clear setup priority overrides after all components are set up From db405c483e10daa21adf57c2444ba4ab48775416 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 07:35:34 -1000 Subject: [PATCH 1425/2030] [core] Cache errno to avoid duplicate __errno() calls (#14751) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/api/api_frame_helper.cpp | 10 +++--- .../components/async_tcp/async_tcp_socket.cpp | 32 +++++++++++-------- .../captive_portal/dns_server_esp32_idf.cpp | 5 +-- .../components/esphome/ota/ota_esphome.cpp | 15 +++++---- .../web_server_idf/web_server_idf.cpp | 5 +-- esphome/core/application.cpp | 10 ++++-- 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index e432a976b0..fbee294022 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -113,10 +113,11 @@ APIError APIFrameHelper::loop() { // Common socket write error handling APIError APIFrameHelper::handle_socket_write_error_() { - if (errno == EWOULDBLOCK || errno == EAGAIN) { + const int err = errno; + if (err == EWOULDBLOCK || err == EAGAIN) { return APIError::WOULD_BLOCK; } - HELPER_LOG("Socket write failed with errno %d", errno); + HELPER_LOG("Socket write failed with errno %d", err); this->state_ = State::FAILED; return APIError::SOCKET_WRITE_FAILED; } @@ -278,11 +279,12 @@ APIError APIFrameHelper::init_common_() { APIError APIFrameHelper::handle_socket_read_result_(ssize_t received) { if (received == -1) { - if (errno == EWOULDBLOCK || errno == EAGAIN) { + const int err = errno; + if (err == EWOULDBLOCK || err == EAGAIN) { return APIError::WOULD_BLOCK; } state_ = State::FAILED; - HELPER_LOG("Socket read failed with errno %d", errno); + HELPER_LOG("Socket read failed with errno %d", err); return APIError::SOCKET_READ_FAILED; } else if (received == 0) { state_ = State::FAILED; diff --git a/esphome/components/async_tcp/async_tcp_socket.cpp b/esphome/components/async_tcp/async_tcp_socket.cpp index f64e494f5f..e8c0f163b3 100644 --- a/esphome/components/async_tcp/async_tcp_socket.cpp +++ b/esphome/components/async_tcp/async_tcp_socket.cpp @@ -52,11 +52,12 @@ bool AsyncClient::connect(const char *host, uint16_t port) { connect_cb_(connect_arg_, this); return true; } - if (errno != EINPROGRESS) { - ESP_LOGE(TAG, "Connect failed: %d", errno); + const int saved_errno = errno; + if (saved_errno != EINPROGRESS) { + ESP_LOGE(TAG, "Connect failed: %d", saved_errno); close(); if (error_cb_) - error_cb_(error_arg_, this, errno); + error_cb_(error_arg_, this, saved_errno); return false; } @@ -79,11 +80,12 @@ size_t AsyncClient::write(const char *data, size_t len) { ssize_t sent = socket_->write(data, len); if (sent < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK) { - ESP_LOGE(TAG, "Write error: %d", errno); + const int err = errno; + if (err != EAGAIN && err != EWOULDBLOCK) { + ESP_LOGE(TAG, "Write error: %d", err); close(); if (error_cb_) - error_cb_(error_arg_, this, errno); + error_cb_(error_arg_, this, err); } return 0; } @@ -129,10 +131,11 @@ void AsyncClient::loop() { error_cb_(error_arg_, this, error); } } else if (ret < 0) { - ESP_LOGE(TAG, "Select error: %d", errno); + const int err = errno; + ESP_LOGE(TAG, "Select error: %d", err); close(); if (error_cb_) - error_cb_(error_arg_, this, errno); + error_cb_(error_arg_, this, err); } } else if (connected_) { // For connected sockets, use the Application's select() results @@ -148,11 +151,14 @@ void AsyncClient::loop() { } else if (len > 0) { if (data_cb_) data_cb_(data_arg_, this, buf, len); - } else if (errno != EAGAIN && errno != EWOULDBLOCK) { - ESP_LOGW(TAG, "Read error: %d", errno); - close(); - if (error_cb_) - error_cb_(error_arg_, this, errno); + } else { + const int err = errno; + if (err != EAGAIN && err != EWOULDBLOCK) { + ESP_LOGW(TAG, "Read error: %d", err); + close(); + if (error_cb_) + error_cb_(error_arg_, this, err); + } } } } diff --git a/esphome/components/captive_portal/dns_server_esp32_idf.cpp b/esphome/components/captive_portal/dns_server_esp32_idf.cpp index 7b75f04241..56ad9f7176 100644 --- a/esphome/components/captive_portal/dns_server_esp32_idf.cpp +++ b/esphome/components/captive_portal/dns_server_esp32_idf.cpp @@ -100,8 +100,9 @@ void DNSServer::process_next_request() { &client_addr_len); if (len < 0) { - if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { - ESP_LOGE(TAG, "recvfrom failed: %d", errno); + const int err = errno; + if (err != EAGAIN && err != EWOULDBLOCK && err != EINTR) { + ESP_LOGE(TAG, "recvfrom failed: %d", err); } return; } diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index d8dbe2dee2..972d2b2b8d 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -332,12 +332,13 @@ void ESPHomeOTAComponent::handle_data_() { size_t requested = remaining < OTA_BUFFER_SIZE ? remaining : OTA_BUFFER_SIZE; ssize_t read = this->client_->read(buf, requested); if (read == -1) { - if (this->would_block_(errno)) { + const int err = errno; + if (this->would_block_(err)) { // read() already waited up to SO_RCVTIMEO for data, just feed WDT App.feed_wdt(); continue; } - ESP_LOGW(TAG, "Read err %d", errno); + ESP_LOGW(TAG, "Read err %d", err); goto error; // NOLINT(cppcoreguidelines-avoid-goto) } else if (read == 0) { ESP_LOGW(TAG, "Remote closed"); @@ -426,8 +427,9 @@ bool ESPHomeOTAComponent::readall_(uint8_t *buf, size_t len) { ssize_t read = this->client_->read(buf + at, len - at); if (read == -1) { - if (!this->would_block_(errno)) { - ESP_LOGW(TAG, "Read err %zu bytes, errno %d", len, errno); + const int err = errno; + if (!this->would_block_(err)) { + ESP_LOGW(TAG, "Read err %zu bytes, errno %d", len, err); return false; } } else if (read == 0) { @@ -455,8 +457,9 @@ bool ESPHomeOTAComponent::writeall_(const uint8_t *buf, size_t len) { ssize_t written = this->client_->write(buf + at, len - at); if (written == -1) { - if (!this->would_block_(errno)) { - ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, errno); + const int err = errno; + if (!this->would_block_(err)) { + ESP_LOGW(TAG, "Write err %zu bytes, errno %d", len, err); return false; } // EWOULDBLOCK: on raw TCP writes never block, delay(1) prevents spinning diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index f18570965b..60816fc6dd 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -74,12 +74,13 @@ int nonblocking_send(httpd_handle_t hd, int sockfd, const char *buf, size_t buf_ // Use MSG_DONTWAIT to prevent blocking when TCP send buffer is full int ret = send(sockfd, buf, buf_len, flags | MSG_DONTWAIT); if (ret < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + const int err = errno; + if (err == EAGAIN || err == EWOULDBLOCK) { // Buffer full - retry later return HTTPD_SOCK_ERR_TIMEOUT; } // Real error - ESP_LOGD(TAG, "send error: errno %d", errno); + ESP_LOGD(TAG, "send error: errno %d", err); return HTTPD_SOCK_ERR_FAIL; } return ret; diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 8685bff360..3a9e825e04 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -698,18 +698,22 @@ void Application::yield_with_select_(uint32_t delay_ms) { #endif // Process select() result: - // ret < 0: error (except EINTR which is normal) // ret > 0: socket(s) have data ready - normal and expected // ret == 0: timeout occurred - normal and expected - if (ret >= 0 || errno == EINTR) [[likely]] { + if (ret >= 0) [[likely]] { // Yield if zero timeout since select(0) only polls without yielding if (delay_ms == 0) [[unlikely]] { yield(); } return; } + // ret < 0: error (EINTR is normal, anything else is unexpected) + const int err = errno; + if (err == EINTR) { + return; + } // select() error - log and fall through to delay() - ESP_LOGW(TAG, "select() failed with errno %d", errno); + ESP_LOGW(TAG, "select() failed with errno %d", err); } // No sockets registered or select() failed - use regular delay delay(delay_ms); From b14255797941f285fcb6df301b96275a4c601257 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 16 Mar 2026 08:26:06 -1000 Subject: [PATCH 1426/2030] [ethernet] Add RP2040 W5500 Ethernet support (#14820) --- esphome/components/ethernet/__init__.py | 35 +- .../components/ethernet/ethernet_component.h | 25 ++ .../ethernet/ethernet_component_rp2040.cpp | 315 ++++++++++++++++++ esphome/components/rp2040/helpers.cpp | 23 +- .../components/socket/lwip_raw_tcp_impl.cpp | 3 +- esphome/core/defines.h | 6 + .../ethernet/common-w5500-rp2040.yaml | 18 + .../ethernet/test-w5500.rp2040-ard.yaml | 1 + 8 files changed, 415 insertions(+), 11 deletions(-) create mode 100644 esphome/components/ethernet/ethernet_component_rp2040.cpp create mode 100644 tests/components/ethernet/common-w5500-rp2040.yaml create mode 100644 tests/components/ethernet/test-w5500.rp2040-ard.yaml diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index e1ceefeacd..f519d79aa1 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -158,6 +158,8 @@ _IDF6_ETHERNET_COMPONENTS: dict[str, IDFRegistryComponent] = { } SPI_ETHERNET_TYPES = ["W5500", "DM9051"] +# RP2040-supported SPI ethernet types +RP2040_SPI_ETHERNET_TYPES = ["W5500"] SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t") @@ -273,6 +275,11 @@ def _validate(config): f"{config[CONF_TYPE]} PHY requires RMII interface and is only supported " f"on ESP32 classic and ESP32-P4, not {variant}" ) + elif CORE.is_rp2040 and config[CONF_TYPE] not in RP2040_SPI_ETHERNET_TYPES: + raise cv.Invalid( + f"Only {', '.join(RP2040_SPI_ETHERNET_TYPES)} are supported on RP2040, " + f"not {config[CONF_TYPE]}" + ) return config @@ -330,18 +337,21 @@ SPI_SCHEMA = cv.All( cv.Required(CONF_CS_PIN): pins.internal_gpio_output_pin_number, cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_number, cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_CLOCK_SPEED, default="26.67MHz"): cv.All( - cv.frequency, cv.int_range(int(8e6), int(80e6)) + cv.SplitDefault(CONF_CLOCK_SPEED, esp32="26.67MHz"): cv.All( + cv.only_on_esp32, + cv.frequency, + cv.int_range(int(8e6), int(80e6)), ), # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() cv.Optional(CONF_POLLING_INTERVAL): cv.All( + cv.only_on_esp32, cv.positive_time_period_milliseconds, cv.Range(min=TimePeriodMilliseconds(milliseconds=1)), ), } ), ), - cv.only_on([Platform.ESP32]), + cv.only_on([Platform.ESP32, Platform.RP2040]), ) CONFIG_SCHEMA = cv.All( @@ -431,6 +441,8 @@ async def to_code(config): if CORE.is_esp32: await _to_code_esp32(var, config) + elif CORE.is_rp2040: + await _to_code_rp2040(var, config) cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) @@ -464,7 +476,7 @@ async def to_code(config): CORE.add_job(final_step) -async def _to_code_esp32(var, config): +async def _to_code_esp32(var: cg.Pvariable, config: ConfigType) -> None: from esphome.components.esp32 import ( add_idf_component, add_idf_sdkconfig_option, @@ -532,6 +544,20 @@ async def _to_code_esp32(var, config): add_idf_component(name=component.name, ref=component.version) +async def _to_code_rp2040(var: cg.Pvariable, config: ConfigType) -> None: + cg.add(var.set_clk_pin(config[CONF_CLK_PIN])) + cg.add(var.set_miso_pin(config[CONF_MISO_PIN])) + cg.add(var.set_mosi_pin(config[CONF_MOSI_PIN])) + cg.add(var.set_cs_pin(config[CONF_CS_PIN])) + if CONF_INTERRUPT_PIN in config: + cg.add(var.set_interrupt_pin(config[CONF_INTERRUPT_PIN])) + if CONF_RESET_PIN in config: + cg.add(var.set_reset_pin(config[CONF_RESET_PIN])) + + cg.add_define("USE_ETHERNET_SPI") + cg.add_library("lwIP_w5500", None) + + def _final_validate_rmii_pins(config: ConfigType) -> None: """Validate that RMII pins are not used by other components.""" if not CORE.is_esp32: @@ -611,6 +637,7 @@ _platform_filter = filter_source_files_from_platform( PlatformFramework.ESP32_IDF, PlatformFramework.ESP32_ARDUINO, }, + "ethernet_component_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO}, "esp_eth_phy_jl1101.c": { PlatformFramework.ESP32_IDF, PlatformFramework.ESP32_ARDUINO, diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index cc73c01df4..901d9bc0bb 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -22,6 +22,10 @@ extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); #endif #endif // USE_ESP32 +#ifdef USE_RP2040 +#include <W5500lwIP.h> +#endif + namespace esphome::ethernet { #ifdef USE_ETHERNET_IP_STATE_LISTENERS @@ -135,6 +139,15 @@ class EthernetComponent : public Component { #endif // USE_ETHERNET_SPI #endif // USE_ESP32 +#ifdef USE_RP2040 + void set_clk_pin(uint8_t clk_pin); + void set_miso_pin(uint8_t miso_pin); + void set_mosi_pin(uint8_t mosi_pin); + void set_cs_pin(uint8_t cs_pin); + void set_interrupt_pin(int8_t interrupt_pin); + void set_reset_pin(int8_t reset_pin); +#endif // USE_RP2040 + #ifdef USE_ETHERNET_IP_STATE_LISTENERS void add_ip_state_listener(EthernetIPStateListener *listener) { this->ip_state_listeners_.push_back(listener); } #endif @@ -200,6 +213,18 @@ class EthernetComponent : public Component { esp_eth_phy_t *phy_{nullptr}; #endif // USE_ESP32 +#ifdef USE_RP2040 + static constexpr uint32_t LINK_CHECK_INTERVAL = 500; // ms between link/IP polls + Wiznet5500lwIP *eth_{nullptr}; + uint32_t last_link_check_{0}; + uint8_t clk_pin_; + uint8_t miso_pin_; + uint8_t mosi_pin_; + uint8_t cs_pin_; + int8_t interrupt_pin_{-1}; + int8_t reset_pin_{-1}; +#endif // USE_RP2040 + // Common members #ifdef USE_ETHERNET_MANUAL_IP optional<ManualIP> manual_ip_{}; diff --git a/esphome/components/ethernet/ethernet_component_rp2040.cpp b/esphome/components/ethernet/ethernet_component_rp2040.cpp new file mode 100644 index 0000000000..77b1a22d66 --- /dev/null +++ b/esphome/components/ethernet/ethernet_component_rp2040.cpp @@ -0,0 +1,315 @@ +#include "ethernet_component.h" + +#if defined(USE_ETHERNET) && defined(USE_RP2040) + +#include "esphome/core/application.h" +#include "esphome/core/helpers.h" +#include "esphome/core/log.h" + +#include "esphome/components/rp2040/gpio.h" + +#include <SPI.h> +#include <lwip/dns.h> +#include <lwip/netif.h> + +namespace esphome::ethernet { + +static const char *const TAG = "ethernet"; + +void EthernetComponent::setup() { + // Configure SPI pins + SPI.setRX(this->miso_pin_); + SPI.setTX(this->mosi_pin_); + SPI.setSCK(this->clk_pin_); + + // Toggle reset pin if configured + if (this->reset_pin_ >= 0) { + rp2040::RP2040GPIOPin reset_pin; + reset_pin.set_pin(this->reset_pin_); + reset_pin.set_flags(gpio::FLAG_OUTPUT); + reset_pin.setup(); + reset_pin.digital_write(false); + delay(1); // NOLINT + reset_pin.digital_write(true); + delay(10); // NOLINT - wait for W5500 to initialize after reset + } + + // Create the W5500 device instance + this->eth_ = new Wiznet5500lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT + + // Set hostname before begin() so the LWIP netif gets it + this->eth_->hostname(App.get_name().c_str()); + + // Configure static IP if set (must be done before begin()) +#ifdef USE_ETHERNET_MANUAL_IP + if (this->manual_ip_.has_value()) { + IPAddress ip(this->manual_ip_->static_ip); + IPAddress gateway(this->manual_ip_->gateway); + IPAddress subnet(this->manual_ip_->subnet); + IPAddress dns1(this->manual_ip_->dns1); + IPAddress dns2(this->manual_ip_->dns2); + this->eth_->config(ip, gateway, subnet, dns1, dns2); + } +#endif + + // Begin with fixed MAC or auto-generated + bool success; + if (this->fixed_mac_.has_value()) { + success = this->eth_->begin(this->fixed_mac_->data()); + } else { + success = this->eth_->begin(); + } + + if (!success) { + ESP_LOGE(TAG, "Failed to initialize W5500 Ethernet"); + delete this->eth_; // NOLINT(cppcoreguidelines-owning-memory) + this->eth_ = nullptr; + this->mark_failed(); + return; + } + + // Make this the default interface for routing + this->eth_->setDefault(true); + + // The arduino-pico LwipIntfDev automatically handles packet processing + // via __addEthernetPacketHandler when no interrupt pin is used, + // or via GPIO interrupt when one is provided. + + // Don't set started_ here — let the link polling in loop() set it + // when the W5500 link is actually up. Setting it prematurely causes + // a "Starting → Stopped → Starting" log sequence because the W5500 + // needs time after begin() before the PHY link is ready. +} + +void EthernetComponent::loop() { + // On RP2040, we need to poll connection state since there are no events. + const uint32_t now = App.get_loop_component_start_time(); + + // Throttle link/IP polling to avoid excessive SPI transactions from linkStatus() + // which reads the W5500 PHY register via SPI on every call. + // connected() reads netif->ip_addr without LwIPLock, but this is a single + // 32-bit aligned read (atomic on ARM) — worst case is a one-iteration-stale + // value, which is benign for polling. + if (this->eth_ != nullptr && now - this->last_link_check_ >= LINK_CHECK_INTERVAL) { + this->last_link_check_ = now; + bool link_up = this->eth_->linkStatus() == LinkON; + bool has_ip = this->eth_->connected(); + + if (!link_up) { + if (this->started_) { + this->started_ = false; + this->connected_ = false; + } + } else { + if (!this->started_) { + this->started_ = true; + } + bool was_connected = this->connected_; + this->connected_ = has_ip; + if (this->connected_ && !was_connected) { +#ifdef USE_ETHERNET_IP_STATE_LISTENERS + this->notify_ip_state_listeners_(); +#endif + } + } + } + + // State machine + switch (this->state_) { + case EthernetComponentState::STOPPED: + if (this->started_) { + ESP_LOGI(TAG, "Starting connection"); + this->state_ = EthernetComponentState::CONNECTING; + this->start_connect_(); + } + break; + case EthernetComponentState::CONNECTING: + if (!this->started_) { + ESP_LOGI(TAG, "Stopped connection"); + this->state_ = EthernetComponentState::STOPPED; + } else if (this->connected_) { + // connection established + ESP_LOGI(TAG, "Connected"); + this->state_ = EthernetComponentState::CONNECTED; + + this->dump_connect_params_(); + this->status_clear_warning(); +#ifdef USE_ETHERNET_CONNECT_TRIGGER + this->connect_trigger_.trigger(); +#endif + } else if (now - this->connect_begin_ > 15000) { + ESP_LOGW(TAG, "Connecting failed; reconnecting"); + this->start_connect_(); + } + break; + case EthernetComponentState::CONNECTED: + if (!this->started_) { + ESP_LOGI(TAG, "Stopped connection"); + this->state_ = EthernetComponentState::STOPPED; +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif + } else if (!this->connected_) { + ESP_LOGW(TAG, "Connection lost; reconnecting"); + this->state_ = EthernetComponentState::CONNECTING; + this->start_connect_(); +#ifdef USE_ETHERNET_DISCONNECT_TRIGGER + this->disconnect_trigger_.trigger(); +#endif + } else { + this->finish_connect_(); + } + break; + } +} + +void EthernetComponent::dump_config() { + ESP_LOGCONFIG(TAG, + "Ethernet:\n" + " Type: W5500\n" + " Connected: %s\n" + " CLK Pin: %u\n" + " MISO Pin: %u\n" + " MOSI Pin: %u\n" + " CS Pin: %u\n" + " IRQ Pin: %d\n" + " Reset Pin: %d", + YESNO(this->is_connected()), this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_, + this->interrupt_pin_, this->reset_pin_); + this->dump_connect_params_(); +} + +network::IPAddresses EthernetComponent::get_ip_addresses() { + network::IPAddresses addresses; + if (this->eth_ != nullptr) { + LwIPLock lock; + addresses[0] = network::IPAddress(this->eth_->localIP()); + } + return addresses; +} + +network::IPAddress EthernetComponent::get_dns_address(uint8_t num) { + LwIPLock lock; + const ip_addr_t *dns_ip = dns_getserver(num); + return dns_ip; +} + +void EthernetComponent::get_eth_mac_address_raw(uint8_t *mac) { + if (this->eth_ != nullptr) { + this->eth_->macAddress(mac); + } else { + memset(mac, 0, 6); + } +} + +std::string EthernetComponent::get_eth_mac_address_pretty() { + char buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + return std::string(this->get_eth_mac_address_pretty_into_buffer(buf)); +} + +const char *EthernetComponent::get_eth_mac_address_pretty_into_buffer( + std::span<char, MAC_ADDRESS_PRETTY_BUFFER_SIZE> buf) { + uint8_t mac[6]; + get_eth_mac_address_raw(mac); + format_mac_addr_upper(mac, buf.data()); + return buf.data(); +} + +eth_duplex_t EthernetComponent::get_duplex_mode() { + // W5500 is always full duplex + return ETH_DUPLEX_FULL; +} + +eth_speed_t EthernetComponent::get_link_speed() { + // W5500 is always 100Mbps + return ETH_SPEED_100M; +} + +bool EthernetComponent::powerdown() { + ESP_LOGI(TAG, "Powering down ethernet"); + if (this->eth_ != nullptr) { + this->eth_->end(); + } + this->connected_ = false; + this->started_ = false; + return true; +} + +void EthernetComponent::start_connect_() { + this->got_ipv4_address_ = false; + this->connect_begin_ = millis(); + this->status_set_warning(LOG_STR("waiting for IP configuration")); + + // Hostname is already set in setup() via LwipIntf::setHostname() + +#ifdef USE_ETHERNET_MANUAL_IP + if (this->manual_ip_.has_value()) { + // Static IP was already configured before begin() in setup() + // Set DNS servers + LwIPLock lock; + if (this->manual_ip_->dns1.is_set()) { + ip_addr_t d; + d = this->manual_ip_->dns1; + dns_setserver(0, &d); + } + if (this->manual_ip_->dns2.is_set()) { + ip_addr_t d; + d = this->manual_ip_->dns2; + dns_setserver(1, &d); + } + } +#endif +} + +void EthernetComponent::finish_connect_() { + // No additional work needed on RP2040 for now + // IPv6 link-local could be added here in the future +} + +void EthernetComponent::dump_connect_params_() { + if (this->eth_ == nullptr) { + return; + } + + char ip_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char subnet_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char gateway_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char dns1_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char dns2_buf[network::IP_ADDRESS_BUFFER_SIZE]; + char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + + // Copy all lwIP state under the lock to avoid races with IRQ callbacks + ip_addr_t ip_addr, netmask, gw, dns1_addr, dns2_addr; + { + LwIPLock lock; + auto *netif = this->eth_->getNetIf(); + ip_addr = netif->ip_addr; + netmask = netif->netmask; + gw = netif->gw; + dns1_addr = *dns_getserver(0); + dns2_addr = *dns_getserver(1); + } + ESP_LOGCONFIG(TAG, + " IP Address: %s\n" + " Hostname: '%s'\n" + " Subnet: %s\n" + " Gateway: %s\n" + " DNS1: %s\n" + " DNS2: %s\n" + " MAC Address: %s", + network::IPAddress(&ip_addr).str_to(ip_buf), App.get_name().c_str(), + network::IPAddress(&netmask).str_to(subnet_buf), network::IPAddress(&gw).str_to(gateway_buf), + network::IPAddress(&dns1_addr).str_to(dns1_buf), network::IPAddress(&dns2_addr).str_to(dns2_buf), + this->get_eth_mac_address_pretty_into_buffer(mac_buf)); +} + +void EthernetComponent::set_clk_pin(uint8_t clk_pin) { this->clk_pin_ = clk_pin; } +void EthernetComponent::set_miso_pin(uint8_t miso_pin) { this->miso_pin_ = miso_pin; } +void EthernetComponent::set_mosi_pin(uint8_t mosi_pin) { this->mosi_pin_ = mosi_pin; } +void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; } +void EthernetComponent::set_interrupt_pin(int8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } +void EthernetComponent::set_reset_pin(int8_t reset_pin) { this->reset_pin_ = reset_pin; } + +} // namespace esphome::ethernet + +#endif // USE_ETHERNET && USE_RP2040 diff --git a/esphome/components/rp2040/helpers.cpp b/esphome/components/rp2040/helpers.cpp index a69b8da480..ad69192af9 100644 --- a/esphome/components/rp2040/helpers.cpp +++ b/esphome/components/rp2040/helpers.cpp @@ -8,6 +8,8 @@ #if defined(USE_WIFI) #include <WiFi.h> #include <pico/cyw43_arch.h> // For cyw43_arch_lwip_begin/end (LwIPLock) +#elif defined(USE_ETHERNET) +#include <LwipEthernet.h> // For ethernet_arch_lwip_begin/end (LwIPLock) #endif #include <hardware/structs/rosc.h> #include <hardware/sync.h> @@ -40,18 +42,27 @@ bool random_bytes(uint8_t *data, size_t len) { IRAM_ATTR InterruptLock::InterruptLock() { state_ = save_and_disable_interrupts(); } IRAM_ATTR InterruptLock::~InterruptLock() { restore_interrupts(state_); } -// On RP2040 (Pico W), arduino-pico sets PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1. -// This means lwip callbacks run from a low-priority user IRQ context, not the +// On RP2040, lwip callbacks run from a low-priority user IRQ context, not the // main loop (see low_priority_irq_handler() in pico-sdk -// async_context_threadsafe_background.c). cyw43_arch_lwip_begin/end acquires the -// async_context recursive mutex to prevent IRQ callbacks from firing during -// critical sections. See esphome#10681. +// async_context_threadsafe_background.c). This applies to both WiFi (CYW43) and +// Ethernet (W5500) — both use async_context_threadsafe_background. // -// When CYW43 is not available (non-WiFi RP2040 boards), this is a no-op since +// Without locking, recv_fn() from IRQ context races with read_locked_() on the +// main loop, corrupting the shared rx_buf_ pbuf chain (use-after-free, pbuf_cat +// assertion failures). See esphome#10681. +// +// WiFi uses cyw43_arch_lwip_begin/end; Ethernet uses ethernet_arch_lwip_begin/end. +// Both acquire the async_context recursive mutex to prevent IRQ callbacks from +// firing during critical sections. +// +// When neither WiFi nor Ethernet is configured, this is a no-op since // there's no network stack and no lwip callbacks to race with. #if defined(USE_WIFI) LwIPLock::LwIPLock() { cyw43_arch_lwip_begin(); } LwIPLock::~LwIPLock() { cyw43_arch_lwip_end(); } +#elif defined(USE_ETHERNET) +LwIPLock::LwIPLock() { ethernet_arch_lwip_begin(); } +LwIPLock::~LwIPLock() { ethernet_arch_lwip_end(); } #else LwIPLock::LwIPLock() {} LwIPLock::~LwIPLock() {} diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 96328e68c7..3bcbd88085 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -130,7 +130,8 @@ void socket_wake() { // code (CONT context) — they never preempt each other, so no locking is needed. // // esphome::LwIPLock is the platform-provided RAII guard (see helpers.h/helpers.cpp). -// On RP2040, it acquires cyw43_arch_lwip_begin/end. On ESP8266, it's a no-op. +// On RP2040, it acquires cyw43_arch_lwip_begin/end (WiFi) or ethernet_arch_lwip_begin/end +// (Ethernet). On ESP8266, it's a no-op. #define LWIP_LOCK() esphome::LwIPLock lwip_lock_guard // NOLINT static const char *const TAG = "socket.lwip"; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 513c70e17e..390ac8ddd7 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -353,6 +353,12 @@ #define USE_SOCKET_IMPL_LWIP_TCP #define USE_RP2040_BLE #define USE_SPI +#ifndef USE_ETHERNET +#define USE_ETHERNET +#endif +#ifndef USE_ETHERNET_SPI +#define USE_ETHERNET_SPI +#endif #endif #ifdef USE_LIBRETINY diff --git a/tests/components/ethernet/common-w5500-rp2040.yaml b/tests/components/ethernet/common-w5500-rp2040.yaml new file mode 100644 index 0000000000..78b2b952fc --- /dev/null +++ b/tests/components/ethernet/common-w5500-rp2040.yaml @@ -0,0 +1,18 @@ +ethernet: + type: W5500 + clk_pin: 18 + mosi_pin: 19 + miso_pin: 16 + cs_pin: 17 + interrupt_pin: 21 + reset_pin: 20 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/test-w5500.rp2040-ard.yaml b/tests/components/ethernet/test-w5500.rp2040-ard.yaml new file mode 100644 index 0000000000..7953198b7e --- /dev/null +++ b/tests/components/ethernet/test-w5500.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-w5500-rp2040.yaml From cdf2867bafd8464d1147c66c5b5ef109b519aafb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:05:56 -0400 Subject: [PATCH 1427/2030] [hub75] Bump esp-hub75 to 0.3.4 (#14862) --- esphome/components/hub75/display.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 4f62ce7a94..4cca0cea5d 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -587,7 +587,7 @@ def _build_config_struct( async def to_code(config: ConfigType) -> None: add_idf_component( name="esphome/esp-hub75", - ref="0.3.2", + ref="0.3.4", ) # Set compile-time configuration via build flags (so external library sees them) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 1478d9544e..a847e34b02 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -64,7 +64,7 @@ dependencies: rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: - version: 0.3.2 + version: 0.3.4 rules: - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" espressif/mqtt: From 05590a3a216dcfa56669926ed6e0d04c134bb10d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:39:26 -0400 Subject: [PATCH 1428/2030] [gpio][dallas_temp] Fix one_wire read64() and DS18S20 division by zero (#14866) --- esphome/components/dallas_temp/dallas_temp.cpp | 3 +++ esphome/components/gpio/one_wire/gpio_one_wire.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index 13f2fa59bd..f119e28e78 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -136,6 +136,9 @@ bool DallasTemperatureSensor::check_scratch_pad_() { float DallasTemperatureSensor::get_temp_c_() { int16_t temp = (this->scratch_pad_[1] << 8) | this->scratch_pad_[0]; if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) { + if (this->scratch_pad_[7] == 0) { + return NAN; + } return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25; } switch (this->resolution_) { diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index 4191c45de1..4e2a306fc9 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -131,7 +131,7 @@ uint8_t IRAM_ATTR GPIOOneWireBus::read8() { uint64_t IRAM_ATTR GPIOOneWireBus::read64() { InterruptLock lock; uint64_t ret = 0; - for (uint8_t i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 64; i++) { ret |= (uint64_t(this->read_bit_()) << i); } return ret; From c8f708c13ce39f012a049872fd32aadaff6215df Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:40:24 -0400 Subject: [PATCH 1429/2030] [lilygo_t5_47] Fix Y coordinate mapping and clamp touch point count (#14865) --- .../lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp b/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp index b29e4c2154..ee6c2ee471 100644 --- a/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +++ b/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp @@ -42,7 +42,7 @@ void LilygoT547Touchscreen::setup() { this->x_raw_max_ = this->display_->get_native_width(); } if (this->y_raw_max_ == this->y_raw_min_) { - this->x_raw_max_ = this->display_->get_native_height(); + this->y_raw_max_ = this->display_->get_native_height(); } } } @@ -64,6 +64,10 @@ void LilygoT547Touchscreen::update_touches() { } point = buffer[5] & 0xF; + if (point > 2) { + ESP_LOGW(TAG, "Invalid touch point count: %d", point); + point = 2; + } if (point == 1) { err = this->write_register(TOUCH_REGISTER, READ_TOUCH, 1); From 9362d9745ef22b96b8da73fb246ee05665c81739 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:41:21 -0400 Subject: [PATCH 1430/2030] [ci] Fix clang-tidy hash check 403 error on fork PRs (#14860) --- .github/workflows/ci-clang-tidy-hash.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-clang-tidy-hash.yml b/.github/workflows/ci-clang-tidy-hash.yml index 5054a62207..7905739b15 100644 --- a/.github/workflows/ci-clang-tidy-hash.yml +++ b/.github/workflows/ci-clang-tidy-hash.yml @@ -40,7 +40,7 @@ jobs: echo "You have modified clang-tidy configuration but have not updated the hash." | tee -a $GITHUB_STEP_SUMMARY echo "Please run 'script/clang_tidy_hash.py --update' and commit the changes." | tee -a $GITHUB_STEP_SUMMARY - - if: failure() + - if: failure() && github.event.pull_request.head.repo.full_name == github.repository name: Request changes uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: @@ -53,7 +53,7 @@ jobs: body: 'You have modified clang-tidy configuration but have not updated the hash.\nPlease run `script/clang_tidy_hash.py --update` and commit the changes.' }) - - if: success() + - if: success() && github.event.pull_request.head.repo.full_name == github.repository name: Dismiss review uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: From 0bbba7575714e2b2b2509e821d555fcd7b3fb768 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:42:13 -0400 Subject: [PATCH 1431/2030] [am43] Fix battery update throttle using wrong type (#14864) --- esphome/components/am43/sensor/am43_sensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/am43/sensor/am43_sensor.h b/esphome/components/am43/sensor/am43_sensor.h index 91973d8e33..195b96a19e 100644 --- a/esphome/components/am43/sensor/am43_sensor.h +++ b/esphome/components/am43/sensor/am43_sensor.h @@ -35,7 +35,7 @@ class Am43 : public esphome::ble_client::BLEClientNode, public PollingComponent uint8_t current_sensor_; // The AM43 often gets into a state where it spams loads of battery update // notifications. Here we will limit to no more than every 10s. - uint8_t last_battery_update_; + uint32_t last_battery_update_; }; } // namespace am43 From 2f86e48a836f02eec8858d139cb2c1dee7fb4b4b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:44:55 -0400 Subject: [PATCH 1432/2030] [as3935] Fix ENERGY_MASK dropping bit 4 of lightning energy MMSB (#14861) --- esphome/components/as3935/as3935.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/as3935/as3935.h b/esphome/components/as3935/as3935.h index 5dff1cb0ae..5f46dadfa8 100644 --- a/esphome/components/as3935/as3935.h +++ b/esphome/components/as3935/as3935.h @@ -41,7 +41,7 @@ enum AS3935RegisterMasks { INT_MASK = 0xF0, THRESH_MASK = 0x0F, R_SPIKE_MASK = 0xF0, - ENERGY_MASK = 0xF0, + ENERGY_MASK = 0xE0, CAP_MASK = 0xF0, LIGHT_MASK = 0xCF, DISTURB_MASK = 0xDF, From c47f4fbc1c41948fc08c87c0f0412a83e0027f3c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:45:16 -0400 Subject: [PATCH 1433/2030] [core] Support both dot and dash separators in Version.parse (#14858) --- esphome/config_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1eac53e9b2..32689dab27 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -314,7 +314,7 @@ class Version: @classmethod def parse(cls, value: str) -> Version: - match = re.match(r"^(\d+).(\d+).(\d+)-?(\w*)$", value) + match = re.match(r"^(\d+).(\d+).(\d+)[-.]?(\w*)$", value) if match is None: raise ValueError(f"Not a valid version number {value}") major = int(match[1]) From 037f75e0ff453f66758df15ce7b1679ed3490679 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:57:17 -1000 Subject: [PATCH 1434/2030] Bump github/codeql-action from 4.32.6 to 4.33.0 (#14869) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1a0c54da6d..2ef1a5af31 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6 + uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 with: category: "/language:${{matrix.language}}" From 5ee3e94ca1dfcb2cca8b75c565b585a3d5a27da8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:57:33 -1000 Subject: [PATCH 1435/2030] Bump actions/create-github-app-token from 2.2.1 to 3.0.0 (#14868) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto-label-pr.yml | 2 +- .github/workflows/release.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/auto-label-pr.yml b/.github/workflows/auto-label-pr.yml index 6376cf877e..3b5e9f0d15 100644 --- a/.github/workflows/auto-label-pr.yml +++ b/.github/workflows/auto-label-pr.yml @@ -27,7 +27,7 @@ jobs: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2 + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v2 with: app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }} private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ed41d99c7..4aa63f6a16 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -221,7 +221,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0 with: app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }} private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} @@ -256,7 +256,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0 with: app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }} private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} @@ -287,7 +287,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 + uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0 with: app-id: ${{ secrets.ESPHOME_GITHUB_APP_ID }} private-key: ${{ secrets.ESPHOME_GITHUB_APP_PRIVATE_KEY }} From 80730fd012ee039acd821551c748ada8b9c01f37 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:57:53 -0400 Subject: [PATCH 1436/2030] [seeed_mr24hpc1] Fix frame parser length handling bugs (#14863) --- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 263603704a..c9fe3a2e6e 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -297,19 +297,17 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { this->sg_recv_data_state_ = FRAME_DATA_LEN_H; break; case FRAME_DATA_LEN_H: - if (value <= 4) { - this->sg_data_len_ = value * 256; + if (value == 0) { this->sg_frame_buf_[4] = value; this->sg_recv_data_state_ = FRAME_DATA_LEN_L; } else { - this->sg_data_len_ = 0; this->sg_recv_data_state_ = FRAME_IDLE; ESP_LOGD(TAG, "FRAME_DATA_LEN_H ERROR value:%x", value); } break; case FRAME_DATA_LEN_L: - this->sg_data_len_ += value; - if (this->sg_data_len_ > 32) { + this->sg_data_len_ = value; + if (this->sg_data_len_ == 0 || this->sg_data_len_ > 32) { ESP_LOGD(TAG, "len=%d, FRAME_DATA_LEN_L ERROR value:%x", this->sg_data_len_, value); this->sg_data_len_ = 0; this->sg_recv_data_state_ = FRAME_IDLE; @@ -320,9 +318,8 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { } break; case FRAME_DATA_BYTES: - this->sg_data_len_ -= 1; this->sg_frame_buf_[this->sg_frame_len_++] = value; - if (this->sg_data_len_ <= 0) { + if (--this->sg_data_len_ == 0) { this->sg_recv_data_state_ = FRAME_DATA_CRC; } break; From 8577c263583cacbb77c531608c8b045a7c269f69 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:03:09 -0400 Subject: [PATCH 1437/2030] [i2c] Handle ESP_ERR_INVALID_RESPONSE as NACK for IDF 6.0 (#14867) --- esphome/components/i2c/i2c_bus_esp_idf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/i2c/i2c_bus_esp_idf.cpp b/esphome/components/i2c/i2c_bus_esp_idf.cpp index eaefabf75b..4aca4f0fae 100644 --- a/esphome/components/i2c/i2c_bus_esp_idf.cpp +++ b/esphome/components/i2c/i2c_bus_esp_idf.cpp @@ -185,7 +185,7 @@ ErrorCode IDFI2CBus::write_readv(uint8_t address, const uint8_t *write_buffer, s jobs[num_jobs++].command = I2C_MASTER_CMD_STOP; ESP_LOGV(TAG, "Sending %zu jobs", num_jobs); esp_err_t err = i2c_master_execute_defined_operations(this->dev_, jobs, num_jobs, 100); - if (err == ESP_ERR_INVALID_STATE) { + if (err == ESP_ERR_INVALID_STATE || err == ESP_ERR_INVALID_RESPONSE) { ESP_LOGV(TAG, "TX to %02X failed: not acked", address); return ERROR_NOT_ACKNOWLEDGED; } else if (err == ESP_ERR_TIMEOUT) { From c3327d0b435f5e2a736a23ca03ce5149e157e319 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 16:04:20 -0400 Subject: [PATCH 1438/2030] [i2s_audio] Fix ESP-IDF 6.0 compatibility for I2S port types (#14818) Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/components/i2s_audio/__init__.py | 70 +++++++++++++++++++ esphome/components/i2s_audio/i2s_audio.cpp | 27 ------- esphome/components/i2s_audio/i2s_audio.h | 13 ++-- .../i2s_audio/microphone/__init__.py | 4 +- .../microphone/i2s_audio_microphone.cpp | 21 ------ 5 files changed, 80 insertions(+), 55 deletions(-) delete mode 100644 esphome/components/i2s_audio/i2s_audio.cpp diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 65b09b93f6..977a239497 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -1,3 +1,5 @@ +from dataclasses import dataclass, field + from esphome import pins import esphome.codegen as cg from esphome.components.esp32 import ( @@ -26,6 +28,9 @@ CODEOWNERS = ["@jesserockz"] DEPENDENCIES = ["esp32"] MULTI_CONF = True +CONF_PDM = "pdm" +CONF_ADC_TYPE = "adc_type" + CONF_I2S_DOUT_PIN = "i2s_dout_pin" CONF_I2S_DIN_PIN = "i2s_din_pin" CONF_I2S_MCLK_PIN = "i2s_mclk_pin" @@ -254,7 +259,65 @@ CONFIG_SCHEMA = cv.All( ) +@dataclass +class I2SAudioData: + """I2S audio component state stored in CORE.data.""" + + port_map: dict[str, int] = field(default_factory=dict) + + +def _get_data() -> I2SAudioData: + if CONF_I2S_AUDIO not in CORE.data: + CORE.data[CONF_I2S_AUDIO] = I2SAudioData() + return CORE.data[CONF_I2S_AUDIO] + + +def _assign_ports() -> None: + """Assign I2S port numbers, prioritizing instances with microphone children. + + Microphones (especially PDM) require port 0 on most ESP32 variants. + This runs once and stores the mapping in CORE.data. + """ + data = _get_data() + if data.port_map: + return + + full_config = fv.full_config.get() + i2s_configs = full_config[CONF_I2S_AUDIO] + + # Find i2s_audio instances with microphones that require port 0 + # (PDM and internal ADC only work on I2S port 0) + port0_parent_id = None + for mic_config in full_config.get("microphone", []): + if CONF_I2S_AUDIO_ID not in mic_config: + continue + if mic_config.get(CONF_PDM) or mic_config.get(CONF_ADC_TYPE) == "internal": + if port0_parent_id is not None: + raise cv.Invalid( + "Only one PDM/ADC microphone is supported (requires I2S port 0)" + ) + port0_parent_id = str(mic_config[CONF_I2S_AUDIO_ID]) + + # Assign ports: port 0 parent first (if any), rest get sequential + next_port = 0 + if port0_parent_id is not None: + data.port_map[port0_parent_id] = next_port + next_port += 1 + for config in i2s_configs: + config_id = str(config[CONF_ID]) + if config_id != port0_parent_id: + data.port_map[config_id] = next_port + next_port += 1 + + def _final_validate(_): + from esphome.components.esp32 import idf_version + + if use_legacy() and idf_version() >= cv.Version(6, 0, 0): + raise cv.Invalid( + "The legacy I2S driver is not available in ESP-IDF 6.0+. " + "Set 'use_legacy: false' in i2s_audio configuration." + ) i2s_audio_configs = fv.full_config.get()[CONF_I2S_AUDIO] variant = get_esp32_variant() if variant not in I2S_PORTS: @@ -263,6 +326,7 @@ def _final_validate(_): raise cv.Invalid( f"Only {I2S_PORTS[variant]} I2S audio ports are supported on {variant}" ) + _assign_ports() def use_legacy(): @@ -276,6 +340,12 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) + # Assign I2S port from _final_validate computed mapping + data = _get_data() + if (port := data.port_map.get(str(config[CONF_ID]))) is None: + raise ValueError(f"No I2S port assigned for {config[CONF_ID]}") + cg.add(var.set_port(port)) + # Re-enable ESP-IDF's I2S driver (excluded by default to save compile time) include_builtin_idf_component("esp_driver_i2s") diff --git a/esphome/components/i2s_audio/i2s_audio.cpp b/esphome/components/i2s_audio/i2s_audio.cpp deleted file mode 100644 index 43064498cc..0000000000 --- a/esphome/components/i2s_audio/i2s_audio.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "i2s_audio.h" - -#ifdef USE_ESP32 - -#include "esphome/core/log.h" - -namespace esphome { -namespace i2s_audio { - -static const char *const TAG = "i2s_audio"; - -void I2SAudioComponent::setup() { - static i2s_port_t next_port_num = I2S_NUM_0; - if (next_port_num >= SOC_I2S_NUM) { - ESP_LOGE(TAG, "Too many components"); - this->mark_failed(); - return; - } - - this->port_ = next_port_num; - next_port_num = (i2s_port_t) (next_port_num + 1); -} - -} // namespace i2s_audio -} // namespace esphome - -#endif // USE_ESP32 diff --git a/esphome/components/i2s_audio/i2s_audio.h b/esphome/components/i2s_audio/i2s_audio.h index cfccf7e01f..f26ffddd46 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -5,6 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" +#include <esp_idf_version.h> #ifdef USE_I2S_LEGACY #include <driver/i2s.h> #else @@ -56,8 +57,6 @@ class I2SAudioOut : public I2SAudioBase {}; class I2SAudioComponent : public Component { public: - void setup() override; - #ifdef USE_I2S_LEGACY i2s_pin_config_t get_pin_config() const { return { @@ -86,13 +85,17 @@ class I2SAudioComponent : public Component { void set_mclk_pin(int pin) { this->mclk_pin_ = pin; } void set_bclk_pin(int pin) { this->bclk_pin_ = pin; } void set_lrclk_pin(int pin) { this->lrclk_pin_ = pin; } + void set_port(int port) { this->port_ = port; } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0) + int get_port() const { return this->port_; } +#else + i2s_port_t get_port() const { return static_cast<i2s_port_t>(this->port_); } +#endif void lock() { this->lock_.lock(); } bool try_lock() { return this->lock_.try_lock(); } void unlock() { this->lock_.unlock(); } - i2s_port_t get_port() const { return this->port_; } - protected: Mutex lock_; @@ -106,7 +109,7 @@ class I2SAudioComponent : public Component { int bclk_pin_{I2S_GPIO_UNUSED}; #endif int lrclk_pin_; - i2s_port_t port_{}; + int port_{}; }; } // namespace i2s_audio diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index bf583b9f81..aa15625cd7 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -13,9 +13,11 @@ from esphome.const import ( ) from .. import ( + CONF_ADC_TYPE, CONF_I2S_DIN_PIN, CONF_LEFT, CONF_MONO, + CONF_PDM, CONF_RIGHT, I2SAudioIn, i2s_audio_component_schema, @@ -29,9 +31,7 @@ CODEOWNERS = ["@jesserockz"] DEPENDENCIES = ["i2s_audio"] CONF_ADC_PIN = "adc_pin" -CONF_ADC_TYPE = "adc_type" CONF_CORRECT_DC_OFFSET = "correct_dc_offset" -CONF_PDM = "pdm" I2SAudioMicrophone = i2s_audio_ns.class_( "I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index eb4506071e..a17cb0d84a 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -37,27 +37,6 @@ enum MicrophoneEventGroupBits : uint32_t { }; void I2SAudioMicrophone::setup() { -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_ADC - if (this->adc_) { - if (this->parent_->get_port() != I2S_NUM_0) { - ESP_LOGE(TAG, "Internal ADC only works on I2S0"); - this->mark_failed(); - return; - } - } else -#endif -#endif - { - if (this->pdm_) { - if (this->parent_->get_port() != I2S_NUM_0) { - ESP_LOGE(TAG, "PDM only works on I2S0"); - this->mark_failed(); - return; - } - } - } - this->active_listeners_semaphore_ = xSemaphoreCreateCounting(MAX_LISTENERS, MAX_LISTENERS); if (this->active_listeners_semaphore_ == nullptr) { ESP_LOGE(TAG, "Creating semaphore failed"); From f81e04b0366732793e718d3745d700969b02dd50 Mon Sep 17 00:00:00 2001 From: KamilCuk <kamilcukrowski@gmail.com> Date: Mon, 16 Mar 2026 22:30:31 +0100 Subject: [PATCH 1439/2030] [web_server] Fix wrong printf format specifier (#14836) --- esphome/components/web_server/web_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 4083019643..1dda6204fe 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -415,7 +415,7 @@ void WebServer::setup() { this->set_interval(10000, [this]() { char buf[32]; auto uptime = static_cast<uint32_t>(millis_64() / 1000); - buf_append_printf(buf, sizeof(buf), 0, "{\"uptime\":%u}", uptime); + buf_append_printf(buf, sizeof(buf), 0, "{\"uptime\":%" PRIu32 "}", uptime); this->events_.try_send_nodefer(buf, "ping", millis(), 30000); }); } From 2142bc1b767c0f0e178d8b34b0bf7d186e0529ca Mon Sep 17 00:00:00 2001 From: Fabrice <fabrice@weinberg.me> Date: Mon, 16 Mar 2026 23:25:11 +0100 Subject: [PATCH 1440/2030] [mipi_rgb] Make h- and v-sync pins optional (#14870) --- esphome/components/mipi_rgb/display.py | 18 ++++++++++++------ esphome/components/mipi_rgb/mipi_rgb.cpp | 12 ++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/esphome/components/mipi_rgb/display.py b/esphome/components/mipi_rgb/display.py index 24988cfcf8..0aa8c56719 100644 --- a/esphome/components/mipi_rgb/display.py +++ b/esphome/components/mipi_rgb/display.py @@ -194,8 +194,12 @@ def model_schema(config): CONF_DE_PIN, cv.UNDEFINED ): pins.internal_gpio_output_pin_schema, model.option(CONF_PCLK_PIN): pins.internal_gpio_output_pin_schema, - model.option(CONF_HSYNC_PIN): pins.internal_gpio_output_pin_schema, - model.option(CONF_VSYNC_PIN): pins.internal_gpio_output_pin_schema, + model.option( + CONF_HSYNC_PIN, cv.UNDEFINED + ): pins.internal_gpio_output_pin_schema, + model.option( + CONF_VSYNC_PIN, cv.UNDEFINED + ): pins.internal_gpio_output_pin_schema, model.option(CONF_RESET_PIN, cv.UNDEFINED): pins.gpio_output_pin_schema, } ) @@ -307,10 +311,12 @@ async def to_code(config): cg.add(var.set_de_pin(pin)) pin = await cg.gpio_pin_expression(config[CONF_PCLK_PIN]) cg.add(var.set_pclk_pin(pin)) - pin = await cg.gpio_pin_expression(config[CONF_HSYNC_PIN]) - cg.add(var.set_hsync_pin(pin)) - pin = await cg.gpio_pin_expression(config[CONF_VSYNC_PIN]) - cg.add(var.set_vsync_pin(pin)) + if hsync_pin := config.get(CONF_HSYNC_PIN): + pin = await cg.gpio_pin_expression(hsync_pin) + cg.add(var.set_hsync_pin(pin)) + if vsync_pin := config.get(CONF_VSYNC_PIN): + pin = await cg.gpio_pin_expression(vsync_pin) + cg.add(var.set_vsync_pin(pin)) await display.register_display(var, config) if lamb := config.get(CONF_LAMBDA): diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index 824ff6afe7..0b0a5344e4 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -158,8 +158,16 @@ void MipiRgb::common_setup_() { } config.data_width = data_pin_count; config.disp_gpio_num = GPIO_NUM_NC; - config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin()); - config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin()); + if (this->hsync_pin_) { + config.hsync_gpio_num = static_cast<gpio_num_t>(this->hsync_pin_->get_pin()); + } else { + config.hsync_gpio_num = GPIO_NUM_NC; + } + if (this->vsync_pin_) { + config.vsync_gpio_num = static_cast<gpio_num_t>(this->vsync_pin_->get_pin()); + } else { + config.vsync_gpio_num = GPIO_NUM_NC; + } if (this->de_pin_) { config.de_gpio_num = static_cast<gpio_num_t>(this->de_pin_->get_pin()); } else { From 06d1498c47e78a9635333a109a089c58309f50c2 Mon Sep 17 00:00:00 2001 From: guillempages <guillempages@users.noreply.github.com> Date: Thu, 12 Mar 2026 15:15:20 +0100 Subject: [PATCH 1441/2030] [runtime_image] Update jpegdec lib version (#14726) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .clang-tidy.hash | 2 +- esphome/components/runtime_image/__init__.py | 2 +- platformio.ini | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index ff25675918..87b4ebb2c6 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -e4b9c4b54e705d3c9400e1cdda8ba0b32634780cfa5f32271832e911bdcafe7e +8e48e836c6fc196d3da000d46eb09db243b87fe33518a74e49c8e009d756074a diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py index 0773a53d91..7c22bfc9d1 100644 --- a/esphome/components/runtime_image/__init__.py +++ b/esphome/components/runtime_image/__init__.py @@ -74,7 +74,7 @@ class JPEGFormat(Format): def actions(self) -> None: cg.add_define("USE_RUNTIME_IMAGE_JPEG") - cg.add_library("JPEGDEC", None, "https://github.com/bitbank2/JPEGDEC#ca1e0f2") + cg.add_library("JPEGDEC", "1.8.4", "https://github.com/bitbank2/JPEGDEC#1.8.4") class PNGFormat(Format): diff --git a/platformio.ini b/platformio.ini index deee23d049..3c3d62ef76 100644 --- a/platformio.ini +++ b/platformio.ini @@ -46,11 +46,11 @@ lib_deps_base = lib_deps = ${common.lib_deps_base} - esphome/noise-c@0.1.11 ; api + esphome/noise-c@0.1.11 ; api improv/Improv@1.2.4 ; improv_serial / esp32_improv kikuchan98/pngle@1.1.0 ; online_image ; Using the repository directly, otherwise ESP-IDF can't use the library - https://github.com/bitbank2/JPEGDEC.git#ca1e0f2 ; online_image + https://github.com/bitbank2/JPEGDEC.git#1.8.4 ; online_image ; This dependency is used only in unit tests. ; Must coincide with PLATFORMIO_GOOGLE_TEST_LIB in scripts/cpp_unit_test.py ; See scripts/cpp_unit_test.py and tests/components/README.md From 5d5c2723b2570d06dddab60a1152903df592d5a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 18:14:41 -1000 Subject: [PATCH 1442/2030] [fastled] Include esp_lcd IDF component for ESP32-S3 compatibility (#14839) --- esphome/components/fastled_base/__init__.py | 5 +++++ tests/components/fastled_clockless/test.esp32-s3-ard.yaml | 1 + 2 files changed, 6 insertions(+) create mode 100644 tests/components/fastled_clockless/test.esp32-s3-ard.yaml diff --git a/esphome/components/fastled_base/__init__.py b/esphome/components/fastled_base/__init__.py index 11e8423258..c944e8a930 100644 --- a/esphome/components/fastled_base/__init__.py +++ b/esphome/components/fastled_base/__init__.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_OUTPUT_ID, CONF_RGB_ORDER, ) +from esphome.core import CORE CODEOWNERS = ["@OttoWinter"] fastled_base_ns = cg.esphome_ns.namespace("fastled_base") @@ -41,5 +42,9 @@ async def new_fastled_light(config): cg.add(var.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE])) cg.add_library("fastled/FastLED", "3.9.16") + if CORE.is_esp32: + from esphome.components.esp32 import include_builtin_idf_component + + include_builtin_idf_component("esp_lcd") await light.register_light(var, config) return var diff --git a/tests/components/fastled_clockless/test.esp32-s3-ard.yaml b/tests/components/fastled_clockless/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/fastled_clockless/test.esp32-s3-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From d6fba390378b6e8469254c518b3e0e5d1312026b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 15 Mar 2026 18:15:01 -1000 Subject: [PATCH 1443/2030] [runtime_image] Add esp-dsp dependency for JPEGDEC SIMD on ESP32 (#14840) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/runtime_image/__init__.py | 8 ++++++++ esphome/idf_component.yml | 2 ++ .../online_image/test.esp32-s3-ard.yaml | 19 +++++++++++++++++++ .../online_image/test.esp32-s3-idf.yaml | 19 +++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 tests/components/online_image/test.esp32-s3-ard.yaml create mode 100644 tests/components/online_image/test.esp32-s3-idf.yaml diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py index 7c22bfc9d1..3ae35cc5f1 100644 --- a/esphome/components/runtime_image/__init__.py +++ b/esphome/components/runtime_image/__init__.py @@ -11,6 +11,7 @@ from esphome.components.image import ( ) import esphome.config_validation as cv from esphome.const import CONF_FORMAT, CONF_ID, CONF_RESIZE, CONF_TYPE +from esphome.core import CORE AUTO_LOAD = ["image"] CODEOWNERS = ["@guillempages", "@clydebarrow", "@kahrendt"] @@ -75,6 +76,13 @@ class JPEGFormat(Format): def actions(self) -> None: cg.add_define("USE_RUNTIME_IMAGE_JPEG") cg.add_library("JPEGDEC", "1.8.4", "https://github.com/bitbank2/JPEGDEC#1.8.4") + if CORE.is_esp32: + from esphome.components.esp32 import add_idf_component + + # JPEGDEC uses ESP32-S3 SIMD optimizations (guarded by board-level + # ARDUINO_ESP32S3_DEV define) that require esp-dsp headers. + # On Arduino this overwrites the stub; on IDF it adds the component. + add_idf_component(name="espressif/esp-dsp", ref="1.7.1") class PNGFormat(Format): diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index df651ae15d..381ecdcbf6 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -5,6 +5,8 @@ dependencies: version: 2.0.3 esphome/micro-opus: version: 0.3.5 + espressif/esp-dsp: + version: "1.7.1" espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: diff --git a/tests/components/online_image/test.esp32-s3-ard.yaml b/tests/components/online_image/test.esp32-s3-ard.yaml new file mode 100644 index 0000000000..9116fd86e0 --- /dev/null +++ b/tests/components/online_image/test.esp32-s3-ard.yaml @@ -0,0 +1,19 @@ +packages: + spi: !include ../../test_build_components/common/spi/esp32-s3-ard.yaml + +<<: !include common.yaml + +http_request: + +display: + - platform: ili9xxx + spi_id: spi_bus + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 13 + reset_pin: 21 + invert_colors: true + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); diff --git a/tests/components/online_image/test.esp32-s3-idf.yaml b/tests/components/online_image/test.esp32-s3-idf.yaml new file mode 100644 index 0000000000..f219f71ee2 --- /dev/null +++ b/tests/components/online_image/test.esp32-s3-idf.yaml @@ -0,0 +1,19 @@ +packages: + spi: !include ../../test_build_components/common/spi/esp32-s3-idf.yaml + +<<: !include common.yaml + +http_request: + +display: + - platform: ili9xxx + spi_id: spi_bus + id: main_lcd + model: ili9342 + cs_pin: 20 + dc_pin: 13 + reset_pin: 21 + invert_colors: true + lambda: |- + it.fill(Color(0, 0, 0)); + it.image(0, 0, id(online_rgba_image)); From ffce637ea547698c034ab6fde3d04c3ee8fc6e41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 05:43:38 +0000 Subject: [PATCH 1444/2030] Bump aioesphomeapi from 44.5.1 to 44.5.2 (#14849) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e634bcb104..da95dd5a13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.5.1 +aioesphomeapi==44.5.2 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From b8ce907976689a5f78ca4f80d483087d001fc5d8 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Mon, 16 Mar 2026 08:08:05 +0100 Subject: [PATCH 1445/2030] [ble_nus] fix uart debug (#14850) --- esphome/components/ble_nus/ble_nus.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index d0d37dbf1c..2f60f81471 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -67,14 +67,14 @@ bool BLENUS::read_array(uint8_t *data, size_t len) { // First, use the peek buffer if available if (this->has_peek_) { +#ifdef USE_UART_DEBUGGER + this->debug_callback_.call(uart::UART_DIRECTION_RX, this->peek_buffer_); +#endif data[0] = this->peek_buffer_; this->has_peek_ = false; data++; if (--len == 0) { // Decrement len first, then check it... -#ifdef USE_UART_DEBUGGER - this->debug_callback_.call(uart::UART_DIRECTION_RX, this->peek_buffer_); -#endif - return true; // No more to read + return true; // No more to read } } From 0c260e483e2700401724706ffd02bc038c65fc93 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:39:26 -0400 Subject: [PATCH 1446/2030] [gpio][dallas_temp] Fix one_wire read64() and DS18S20 division by zero (#14866) --- esphome/components/dallas_temp/dallas_temp.cpp | 3 +++ esphome/components/gpio/one_wire/gpio_one_wire.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/dallas_temp/dallas_temp.cpp b/esphome/components/dallas_temp/dallas_temp.cpp index 13f2fa59bd..f119e28e78 100644 --- a/esphome/components/dallas_temp/dallas_temp.cpp +++ b/esphome/components/dallas_temp/dallas_temp.cpp @@ -136,6 +136,9 @@ bool DallasTemperatureSensor::check_scratch_pad_() { float DallasTemperatureSensor::get_temp_c_() { int16_t temp = (this->scratch_pad_[1] << 8) | this->scratch_pad_[0]; if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) { + if (this->scratch_pad_[7] == 0) { + return NAN; + } return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25; } switch (this->resolution_) { diff --git a/esphome/components/gpio/one_wire/gpio_one_wire.cpp b/esphome/components/gpio/one_wire/gpio_one_wire.cpp index 4191c45de1..4e2a306fc9 100644 --- a/esphome/components/gpio/one_wire/gpio_one_wire.cpp +++ b/esphome/components/gpio/one_wire/gpio_one_wire.cpp @@ -131,7 +131,7 @@ uint8_t IRAM_ATTR GPIOOneWireBus::read8() { uint64_t IRAM_ATTR GPIOOneWireBus::read64() { InterruptLock lock; uint64_t ret = 0; - for (uint8_t i = 0; i < 8; i++) { + for (uint8_t i = 0; i < 64; i++) { ret |= (uint64_t(this->read_bit_()) << i); } return ret; From bb0a5dc8a8c2df1217dd9cab0402b2e9c29e2b7d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:40:24 -0400 Subject: [PATCH 1447/2030] [lilygo_t5_47] Fix Y coordinate mapping and clamp touch point count (#14865) --- .../lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp b/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp index b29e4c2154..ee6c2ee471 100644 --- a/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp +++ b/esphome/components/lilygo_t5_47/touchscreen/lilygo_t5_47_touchscreen.cpp @@ -42,7 +42,7 @@ void LilygoT547Touchscreen::setup() { this->x_raw_max_ = this->display_->get_native_width(); } if (this->y_raw_max_ == this->y_raw_min_) { - this->x_raw_max_ = this->display_->get_native_height(); + this->y_raw_max_ = this->display_->get_native_height(); } } } @@ -64,6 +64,10 @@ void LilygoT547Touchscreen::update_touches() { } point = buffer[5] & 0xF; + if (point > 2) { + ESP_LOGW(TAG, "Invalid touch point count: %d", point); + point = 2; + } if (point == 1) { err = this->write_register(TOUCH_REGISTER, READ_TOUCH, 1); From f36b0fcb61f78ab2a01cfb03c57f5b1ad75b8fdc Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:42:13 -0400 Subject: [PATCH 1448/2030] [am43] Fix battery update throttle using wrong type (#14864) --- esphome/components/am43/sensor/am43_sensor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/am43/sensor/am43_sensor.h b/esphome/components/am43/sensor/am43_sensor.h index 91973d8e33..195b96a19e 100644 --- a/esphome/components/am43/sensor/am43_sensor.h +++ b/esphome/components/am43/sensor/am43_sensor.h @@ -35,7 +35,7 @@ class Am43 : public esphome::ble_client::BLEClientNode, public PollingComponent uint8_t current_sensor_; // The AM43 often gets into a state where it spams loads of battery update // notifications. Here we will limit to no more than every 10s. - uint8_t last_battery_update_; + uint32_t last_battery_update_; }; } // namespace am43 From 9133582aa0c636bd3e81bc424b46c5248427ccb3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:44:55 -0400 Subject: [PATCH 1449/2030] [as3935] Fix ENERGY_MASK dropping bit 4 of lightning energy MMSB (#14861) --- esphome/components/as3935/as3935.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/as3935/as3935.h b/esphome/components/as3935/as3935.h index 5dff1cb0ae..5f46dadfa8 100644 --- a/esphome/components/as3935/as3935.h +++ b/esphome/components/as3935/as3935.h @@ -41,7 +41,7 @@ enum AS3935RegisterMasks { INT_MASK = 0xF0, THRESH_MASK = 0x0F, R_SPIKE_MASK = 0xF0, - ENERGY_MASK = 0xF0, + ENERGY_MASK = 0xE0, CAP_MASK = 0xF0, LIGHT_MASK = 0xCF, DISTURB_MASK = 0xDF, From 0816b27398b0abb63c11d6f7a10e65ef95f6dcec Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:45:16 -0400 Subject: [PATCH 1450/2030] [core] Support both dot and dash separators in Version.parse (#14858) --- esphome/config_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 1eac53e9b2..32689dab27 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -314,7 +314,7 @@ class Version: @classmethod def parse(cls, value: str) -> Version: - match = re.match(r"^(\d+).(\d+).(\d+)-?(\w*)$", value) + match = re.match(r"^(\d+).(\d+).(\d+)[-.]?(\w*)$", value) if match is None: raise ValueError(f"Not a valid version number {value}") major = int(match[1]) From d6c67d5c357669e547f94a461614976e0d3d54cb Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 17 Mar 2026 11:45:03 +1300 Subject: [PATCH 1451/2030] Bump version to 2026.3.0b3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 4ec3a24c9f..96295b3fc8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0b2 +PROJECT_NUMBER = 2026.3.0b3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 2466f2c49c..561a27d228 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0b2" +__version__ = "2026.3.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 73ca0ff1069ad2582830316890faaa9e43fad3b2 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:22:31 +0100 Subject: [PATCH 1452/2030] [core] Small improvements (#14884) --- esphome/components/bme68x_bsec2/__init__.py | 4 ++-- script/merge_component_configs.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py index 4200b2f0b8..5f0afa9c9f 100644 --- a/esphome/components/bme68x_bsec2/__init__.py +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -186,8 +186,8 @@ async def to_code_base(config): cg.add_library("SPI", None) cg.add_library( "BME68x Sensor library", - "1.3.40408", - "https://github.com/boschsensortec/Bosch-BME68x-Library", + None, + "https://github.com/boschsensortec/Bosch-BME68x-Library#v1.3.40408", ) cg.add_library( "BSEC2 Software Library", diff --git a/script/merge_component_configs.py b/script/merge_component_configs.py index 5e98f1fef5..41bbafcd02 100755 --- a/script/merge_component_configs.py +++ b/script/merge_component_configs.py @@ -384,7 +384,7 @@ def merge_component_configs( # Write merged config output_file.parent.mkdir(parents=True, exist_ok=True) yaml_content = yaml_util.dump(merged_config_data) - output_file.write_text(yaml_content) + output_file.write_text(yaml_content, encoding="utf-8") print(f"Successfully merged {len(component_names)} components into {output_file}") From b083491e7493f4f2f1c6acadee673c0c05e29bd0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:46:32 -0400 Subject: [PATCH 1453/2030] [microphone] Switch IDF test to new I2S driver (#14886) --- tests/components/microphone/common.yaml | 10 +++++++++- .../components/microphone/test.esp32-idf.yaml | 20 +++---------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/tests/components/microphone/common.yaml b/tests/components/microphone/common.yaml index 00d33bcc3d..39ab06da61 100644 --- a/tests/components/microphone/common.yaml +++ b/tests/components/microphone/common.yaml @@ -6,7 +6,7 @@ i2s_audio: microphone: - platform: i2s_audio id: mic_id_external - i2s_din_pin: ${i2s_din_pin} + i2s_din_pin: ${i2s_din_pin1} adc_type: external pdm: false mclk_multiple: 384 @@ -15,7 +15,15 @@ microphone: - if: condition: - microphone.is_muted: + id: mic_id_external then: - microphone.unmute: + id: mic_id_external else: - microphone.mute: + id: mic_id_external + - platform: i2s_audio + id: mic_id_pdm + i2s_din_pin: ${i2s_din_pin2} + adc_type: external + pdm: true diff --git a/tests/components/microphone/test.esp32-idf.yaml b/tests/components/microphone/test.esp32-idf.yaml index 830f0156d7..2f39263a43 100644 --- a/tests/components/microphone/test.esp32-idf.yaml +++ b/tests/components/microphone/test.esp32-idf.yaml @@ -2,21 +2,7 @@ substitutions: i2s_bclk_pin: GPIO15 i2s_lrclk_pin: GPIO4 i2s_mclk_pin: GPIO5 - i2s_din_pin: GPIO33 + i2s_din_pin1: GPIO33 + i2s_din_pin2: GPIO34 -i2s_audio: - i2s_bclk_pin: ${i2s_bclk_pin} - i2s_lrclk_pin: ${i2s_lrclk_pin} - i2s_mclk_pin: ${i2s_mclk_pin} - use_legacy: true - -microphone: - - platform: i2s_audio - id: mic_id_external - i2s_din_pin: ${i2s_din_pin} - adc_type: external - pdm: false - - platform: i2s_audio - id: mic_id_adc - adc_pin: 32 - adc_type: internal +<<: !include common.yaml From 3826e9550616bf154fcdcb2541289b9bf2f3a1db Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 08:14:36 -1000 Subject: [PATCH 1454/2030] [api] Fix ProtoMessage protected destructor compile error on host platform (#14882) --- esphome/components/api/proto.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 6752dfb9cd..d6e993d3a5 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -442,8 +442,12 @@ class ProtoMessage { virtual const char *message_name() const { return "unknown"; } #endif +#ifndef USE_HOST protected: +#endif // Non-virtual destructor is protected to prevent polymorphic deletion. + // On host platform, made public to allow value-initialization of std::array + // members (e.g. DeviceInfoResponse::devices) without clang errors. ~ProtoMessage() = default; }; From 82ccc37ba11a81894a38c729ab6f176db86b87ae Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 08:14:52 -1000 Subject: [PATCH 1455/2030] [ethernet] Mark EthernetComponent as final (#14842) --- esphome/components/ethernet/ethernet_component.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 901d9bc0bb..88a86bc043 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -85,7 +85,7 @@ enum eth_duplex_t { ETH_DUPLEX_HALF, ETH_DUPLEX_FULL }; enum eth_speed_t { ETH_SPEED_10M, ETH_SPEED_100M }; #endif -class EthernetComponent : public Component { +class EthernetComponent final : public Component { public: EthernetComponent(); void setup() override; From b3210de374aec9f63126af7617cf31d235875abf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 08:53:36 -1000 Subject: [PATCH 1456/2030] [core] Extract shared C++ build helpers from cpp_unit_test.py (#14883) --- script/cpp_unit_test.py | 257 ++++---------------------- script/test_helpers.py | 400 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 436 insertions(+), 221 deletions(-) create mode 100644 script/test_helpers.py diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index c6cfd8270f..81c56b82da 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -1,238 +1,53 @@ #!/usr/bin/env python3 import argparse -import hashlib -import os from pathlib import Path -import subprocess import sys -from helpers import get_all_components, get_all_dependencies, root_path - -from esphome.__main__ import command_compile, parse_args -from esphome.config import validate_config -from esphome.const import CONF_PLATFORM -from esphome.core import CORE -from esphome.loader import get_component -from esphome.platformio_api import get_idedata - -# This must coincide with the version in /platformio.ini -PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" +from helpers import get_all_components, root_path +from test_helpers import ( + BASE_CODEGEN_COMPONENTS, + PLATFORMIO_GOOGLE_TEST_LIB, + USE_TIME_TIMEZONE_FLAG, + build_and_run, +) # Path to /tests/components COMPONENTS_TESTS_DIR: Path = Path(root_path) / "tests" / "components" -# Components whose to_code should run during C++ test builds. -# Most components don't need code generation for tests; only these -# essential ones (platform setup, logging, core config) are needed. -# Note: "core" is the esphome core config module (esphome/core/config.py), -# which registers under package name "core" not "esphome". -CPP_TESTING_CODEGEN_COMPONENTS = {"core", "host", "logger"} - - -def hash_components(components: list[str]) -> str: - key = ",".join(components) - return hashlib.sha256(key.encode()).hexdigest()[:16] - - -def filter_components_without_tests(components: list[str]) -> list[str]: - """Filter out components that do not have a corresponding test file. - - This is done by checking if the component's directory contains at - least a .cpp or .h file. - """ - filtered_components: list[str] = [] - for component in components: - test_dir = COMPONENTS_TESTS_DIR / component - if test_dir.is_dir() and ( - any(test_dir.glob("*.cpp")) or any(test_dir.glob("*.h")) - ): - filtered_components.append(component) - else: - print( - f"WARNING: No tests found for component '{component}', skipping.", - file=sys.stderr, - ) - return filtered_components - - -def create_test_config(config_name: str, includes: list[str]) -> dict: - """Create ESPHome test configuration for C++ unit tests. - - Args: - config_name: Unique name for this test configuration - includes: List of include folders for the test build - - Returns: - Configuration dict for ESPHome - """ - return { - "esphome": { - "name": config_name, - "friendly_name": "CPP Unit Tests", - "libraries": PLATFORMIO_GOOGLE_TEST_LIB, - "platformio_options": { - "build_type": "debug", - "build_unflags": [ - "-Os", # remove size-opt flag - ], - "build_flags": [ - "-Og", # optimize for debug - "-DUSE_TIME_TIMEZONE", # enable timezone code paths for testing - "-DESPHOME_DEBUG", # enable debug assertions - # Enable the address and undefined behavior sanitizers - "-fsanitize=address", - "-fsanitize=undefined", - "-fno-omit-frame-pointer", - ], - "debug_build_flags": [ # only for debug builds - "-g3", # max debug info - "-ggdb3", - ], - }, - "includes": includes, - }, - "host": {}, - "logger": {"level": "DEBUG"}, - } - - -def get_platform_components(components: list[str]) -> list[str]: - """Discover platform sub-components referenced by test directory structure. - - For each component being tested, any sub-directory named after a platform - domain (e.g. ``sensor``, ``binary_sensor``) is treated as a request to - include that ``<domain>.<component>`` platform in the build. The sub- - directory must name a valid platform domain; anything else raises an error - so that typos are caught early. - - Returns: - List of ``"domain.component"`` strings, one per discovered sub-directory. - """ - platform_components: list[str] = [] - for component in components: - test_dir = COMPONENTS_TESTS_DIR / component - if not test_dir.is_dir(): - continue - # Each sub-directory name is expected to be a platform domain - # (e.g. tests/components/bthome/sensor/ → sensor.bthome). - for domain_dir in test_dir.iterdir(): - if not domain_dir.is_dir(): - continue - domain = domain_dir.name - domain_module = get_component(domain) - if domain_module is None or not domain_module.is_platform_component: - raise ValueError( - f"Component tests for '{component}' reference non-existing or invalid domain '{domain}'" - f" in its directory structure. See ({COMPONENTS_TESTS_DIR / component / domain})." - ) - platform_components.append(f"{domain}.{component}") - return platform_components - - -# Exit codes for run_tests -EXIT_OK = 0 -EXIT_SKIPPED = 1 -EXIT_COMPILE_ERROR = 2 -EXIT_CONFIG_ERROR = 3 -EXIT_NO_EXECUTABLE = 4 +PLATFORMIO_OPTIONS = { + "build_type": "debug", + "build_unflags": [ + "-Os", # remove size-opt flag + ], + "build_flags": [ + "-Og", # optimize for debug + USE_TIME_TIMEZONE_FLAG, + "-DESPHOME_DEBUG", # enable debug assertions + # Enable the address and undefined behavior sanitizers + "-fsanitize=address", + "-fsanitize=undefined", + "-fno-omit-frame-pointer", + ], + "debug_build_flags": [ # only for debug builds + "-g3", # max debug info + "-ggdb3", + ], +} def run_tests(selected_components: list[str]) -> int: - # Skip tests on Windows - if os.name == "nt": - print("Skipping esphome tests on Windows", file=sys.stderr) - return EXIT_SKIPPED - - # Remove components that do not have tests - components = filter_components_without_tests(selected_components) - - if len(components) == 0: - print( - "No components specified or no tests found for the specified components.", - file=sys.stderr, - ) - return EXIT_OK - - components = sorted(components) - - # Build a list of include folders relative to COMPONENTS_TESTS_DIR. These folders will - # be added along with their subfolders. - # "main.cpp" is a special entry that points to /tests/components/main.cpp, - # which provides a custom test runner entry-point replacing the default one. - # Each remaining entry is a component folder whose *.cpp files are compiled. - includes: list[str] = ["main.cpp"] + components - - # Obtain a list of platform components to be tested: - try: - platform_components = get_platform_components(components) - except ValueError as e: - print(f"Error obtaining platform components: {e}") - return EXIT_CONFIG_ERROR - - components = sorted(components + platform_components) - - # Create a unique name for this config based on the actual components being tested - # to maximize cache during testing - config_name: str = "cpptests-" + hash_components(components) - - # Obtain possible dependencies for the requested components. - # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, - # which causes core/time.h to include components/time/posix_tz.h. - components_with_dependencies: list[str] = sorted( - get_all_dependencies(set(components) | {"time"}, cpp_testing=True) + return build_and_run( + selected_components=selected_components, + tests_dir=COMPONENTS_TESTS_DIR, + codegen_components=BASE_CODEGEN_COMPONENTS, + config_prefix="cpptests", + friendly_name="CPP Unit Tests", + libraries=PLATFORMIO_GOOGLE_TEST_LIB, + platformio_options=PLATFORMIO_OPTIONS, + main_entry="main.cpp", + label="unit tests", ) - config = create_test_config(config_name, includes) - - CORE.config_path = COMPONENTS_TESTS_DIR / "dummy.yaml" - CORE.dashboard = None - CORE.cpp_testing = True - CORE.cpp_testing_codegen = CPP_TESTING_CODEGEN_COMPONENTS - - # Validate config will expand the above with defaults: - config = validate_config(config, {}) - - # Add all components and dependencies to the base configuration after validation, so their files - # are added to the build. - for component_name in components_with_dependencies: - if "." in component_name: - # Format is always "domain.component" (exactly one dot), - # as produced by get_platform_components(). - domain, component = component_name.split(".", maxsplit=1) - domain_list = config.setdefault(domain, []) - CORE.testing_ensure_platform_registered(domain) - domain_list.append({CONF_PLATFORM: component}) - else: - config.setdefault(component_name, []) - - dependencies = set(components_with_dependencies) - set(components) - deps_str = ", ".join(dependencies) if dependencies else "None" - print(f"Testing components: {', '.join(components)}. Dependencies: {deps_str}") - CORE.config = config - args = parse_args(["program", "compile", str(CORE.config_path)]) - try: - exit_code: int = command_compile(args, config) - - if exit_code != 0: - print(f"Error compiling unit tests for {', '.join(components)}") - return exit_code - except Exception as e: - print( - f"Error compiling unit tests for {', '.join(components)}. Check path. : {e}" - ) - return EXIT_COMPILE_ERROR - - # After a successful compilation, locate the executable and run it: - idedata = get_idedata(config) - if idedata is None: - print("Cannot find executable") - return EXIT_NO_EXECUTABLE - - program_path: str = idedata.raw["prog_path"] - run_cmd: list[str] = [program_path] - run_proc = subprocess.run(run_cmd, check=False) - return run_proc.returncode - def main() -> None: parser = argparse.ArgumentParser( diff --git a/script/test_helpers.py b/script/test_helpers.py new file mode 100644 index 0000000000..e872bbc516 --- /dev/null +++ b/script/test_helpers.py @@ -0,0 +1,400 @@ +"""Shared helpers for C++ unit test and benchmark build scripts.""" + +from __future__ import annotations + +import hashlib +import os +from pathlib import Path +import subprocess +import sys + +from helpers import get_all_dependencies +import yaml + +from esphome.__main__ import command_compile, parse_args +from esphome.config import validate_config +from esphome.const import CONF_PLATFORM +from esphome.core import CORE +from esphome.loader import get_component +from esphome.platformio_api import get_idedata + +# This must coincide with the version in /platformio.ini +PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" + +# Google Benchmark library for PlatformIO +# Format: name=repository_url (see esphome/core/config.py library parsing) +PLATFORMIO_GOOGLE_BENCHMARK_LIB = ( + "benchmark=https://github.com/google/benchmark.git#v1.9.1" +) + +# Key names for the base config sections +ESPHOME_KEY = "esphome" +HOST_KEY = "host" +LOGGER_KEY = "logger" + +# Base config keys that are always present and must not be fully overridden +# by component benchmark.yaml files. esphome: allows sub-key merging. +BASE_CONFIG_KEYS = frozenset({ESPHOME_KEY, HOST_KEY, LOGGER_KEY}) + +# Shared build flag — enables timezone code paths for testing/benchmarking. +USE_TIME_TIMEZONE_FLAG = "-DUSE_TIME_TIMEZONE" + +# Components whose to_code should always run during C++ test/benchmark builds. +# These are the minimal infrastructure components needed for host compilation. +# Note: "core" is the esphome core config module (esphome/core/config.py), +# which registers under package name "core" not "esphome". +BASE_CODEGEN_COMPONENTS = {"core", "host", "logger"} + +# Exit codes +EXIT_OK = 0 +EXIT_SKIPPED = 1 +EXIT_COMPILE_ERROR = 2 +EXIT_CONFIG_ERROR = 3 +EXIT_NO_EXECUTABLE = 4 + +# Name of the per-component YAML config file in benchmark directories +BENCHMARK_YAML_FILENAME = "benchmark.yaml" + + +def hash_components(components: list[str]) -> str: + """Create a short hash of component names for unique config naming.""" + key = ",".join(components) + return hashlib.sha256(key.encode()).hexdigest()[:16] + + +def filter_components_with_files(components: list[str], tests_dir: Path) -> list[str]: + """Filter out components that do not have .cpp or .h files in the tests dir. + + Args: + components: List of component names to check + tests_dir: Base directory containing component test/benchmark folders + + Returns: + Filtered list of components that have test files + """ + filtered_components: list[str] = [] + for component in components: + test_dir = tests_dir / component + if test_dir.is_dir() and ( + any(test_dir.glob("*.cpp")) or any(test_dir.glob("*.h")) + ): + filtered_components.append(component) + else: + print( + f"WARNING: No files found for component '{component}' in {test_dir}, skipping.", + file=sys.stderr, + ) + return filtered_components + + +def get_platform_components(components: list[str], tests_dir: Path) -> list[str]: + """Discover platform sub-components referenced by test directory structure. + + For each component, any sub-directory named after a platform domain + (e.g. ``sensor``, ``binary_sensor``) is treated as a request to include + that ``<domain>.<component>`` platform in the build. + + Args: + components: List of component names to scan + tests_dir: Base directory containing component test/benchmark folders + + Returns: + List of ``"domain.component"`` strings + """ + platform_components: list[str] = [] + for component in components: + test_dir = tests_dir / component + if not test_dir.is_dir(): + continue + for domain_dir in test_dir.iterdir(): + if not domain_dir.is_dir(): + continue + domain = domain_dir.name + domain_module = get_component(domain) + if domain_module is None or not domain_module.is_platform_component: + raise ValueError( + f"Component '{component}' references non-existing or invalid domain '{domain}'" + f" in its directory structure. See ({tests_dir / component / domain})." + ) + platform_components.append(f"{domain}.{component}") + return platform_components + + +def load_component_yaml_configs(components: list[str], tests_dir: Path) -> dict: + """Load and merge benchmark.yaml files from component directories. + + Each component directory may contain a ``benchmark.yaml`` file that + declares additional ESPHome components needed for the build (e.g. + ``api:``, ``sensor:``). These get merged into the base config before + validation so that dependencies are properly resolved with defaults. + + The ``esphome:`` key is special: its sub-keys are merged into the + existing esphome config (e.g. to add ``areas:`` or ``devices:``). + Other base config keys (``host:``, ``logger:``) are not overridable. + + Args: + components: List of component directory names + tests_dir: Base directory containing component folders + + Returns: + Merged dict of component configs to add to the base config + """ + # Note: components are processed in sorted order. For conflicting keys + # (e.g. two benchmark.yaml files both declaring sensor:), the first + # component alphabetically wins via setdefault(). This is fine for now + # with a single benchmark component (api) but would need a real merge + # strategy if multiple components declare overlapping configs. + merged: dict = {} + for component in components: + yaml_path = tests_dir / component / BENCHMARK_YAML_FILENAME + if not yaml_path.is_file(): + continue + with open(yaml_path) as f: + component_config = yaml.safe_load(f) + if component_config and isinstance(component_config, dict): + for key, value in component_config.items(): + if key in BASE_CONFIG_KEYS - {ESPHOME_KEY}: + # host: and logger: are not overridable + continue + if key == ESPHOME_KEY and isinstance(value, dict): + # Merge esphome sub-keys rather than replacing + esphome_extra = merged.setdefault(ESPHOME_KEY, {}) + for sub_key, sub_value in value.items(): + esphome_extra.setdefault(sub_key, sub_value) + continue + merged.setdefault(key, value) + return merged + + +def create_host_config( + config_name: str, + friendly_name: str, + libraries: str | list[str], + includes: list[str], + platformio_options: dict, +) -> dict: + """Create an ESPHome host configuration for C++ builds. + + Args: + config_name: Unique name for this configuration + friendly_name: Human-readable name + libraries: PlatformIO library specification(s) + includes: List of include folders for the build + platformio_options: Dict of platformio_options to set + + Returns: + Configuration dict for ESPHome + """ + return { + ESPHOME_KEY: { + "name": config_name, + "friendly_name": friendly_name, + "libraries": libraries, + "platformio_options": platformio_options, + "includes": includes, + }, + HOST_KEY: {}, + LOGGER_KEY: {"level": "DEBUG"}, + } + + +def compile_and_get_binary( + config: dict, + components: list[str], + codegen_components: set[str], + tests_dir: Path, + label: str = "build", +) -> tuple[int, str | None]: + """Compile an ESPHome configuration and return the binary path. + + Args: + config: ESPHome configuration dict (already created via create_host_config) + components: List of components to include in the build + codegen_components: Set of component names whose to_code should run + tests_dir: Base directory for test files (used as config_path base) + label: Label for log messages (e.g. "unit tests", "benchmarks") + + Returns: + Tuple of (exit_code, program_path_or_none) + """ + # Load any benchmark.yaml files from component directories and merge + # them into the config BEFORE dependency resolution and validation. + # This allows each benchmark/test dir to declare which ESPHome components + # it needs (e.g. api:) so they get proper config defaults. + extra_config = load_component_yaml_configs(components, tests_dir) + for key, value in extra_config.items(): + if key == ESPHOME_KEY and isinstance(value, dict): + # Merge esphome sub-keys into existing esphome config. + # For list values (e.g. libraries), extend rather than replace. + for sub_key, sub_value in value.items(): + existing = config[ESPHOME_KEY].get(sub_key) + if existing is not None and isinstance(sub_value, list): + # Ensure existing is a list, then extend + if not isinstance(existing, list): + config[ESPHOME_KEY][sub_key] = [existing] + config[ESPHOME_KEY][sub_key].extend(sub_value) + else: + config[ESPHOME_KEY].setdefault(sub_key, sub_value) + else: + config.setdefault(key, value) + + # Obtain possible dependencies BEFORE validate_config, because + # get_all_dependencies calls CORE.reset() which clears build_path. + # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, + # which causes core/time.h to include components/time/posix_tz.h. + components_with_dependencies: list[str] = sorted( + get_all_dependencies(set(components) | {"time"}, cpp_testing=True) + ) + + CORE.config_path = tests_dir / "dummy.yaml" + CORE.dashboard = None + CORE.cpp_testing = True + CORE.cpp_testing_codegen = codegen_components + + # Validate config will expand the above with defaults: + config = validate_config(config, {}) + + # Add remaining components and dependencies to the configuration after + # validation, so their source files are included in the build. + for component_name in components_with_dependencies: + if "." in component_name: + domain, component = component_name.split(".", maxsplit=1) + domain_list = config.setdefault(domain, []) + CORE.testing_ensure_platform_registered(domain) + domain_list.append({CONF_PLATFORM: component}) + # Skip "core" — it's a pseudo-component handled by the build + # system, not a real loadable component (get_component returns None) + elif get_component(component_name) is not None: + config.setdefault(component_name, []) + + # Register platforms from the extra config (benchmark.yaml) so + # USE_SENSOR, USE_LIGHT, etc. defines are emitted without needing + # real entity instances. + for key in extra_config: + if key == ESPHOME_KEY: + continue + comp = get_component(key) + if comp is not None and comp.is_platform_component: + CORE.testing_ensure_platform_registered(key) + + dependencies = set(components_with_dependencies) - set(components) + deps_str = ", ".join(dependencies) if dependencies else "None" + print(f"Building {label}: {', '.join(components)}. Dependencies: {deps_str}") + CORE.config = config + args = parse_args(["program", "compile", str(CORE.config_path)]) + try: + exit_code: int = command_compile(args, config) + + if exit_code != 0: + print(f"Error compiling {label} for {', '.join(components)}") + return exit_code, None + except Exception as e: + print(f"Error compiling {label} for {', '.join(components)}: {e}") + return EXIT_COMPILE_ERROR, None + + # After a successful compilation, locate the executable: + idedata = get_idedata(config) + if idedata is None: + print("Cannot find executable") + return EXIT_NO_EXECUTABLE, None + + program_path: str = idedata.raw["prog_path"] + return EXIT_OK, program_path + + +def build_and_run( + selected_components: list[str], + tests_dir: Path, + codegen_components: set[str], + config_prefix: str, + friendly_name: str, + libraries: str | list[str], + platformio_options: dict, + main_entry: str, + label: str = "build", + build_only: bool = False, + extra_run_args: list[str] | None = None, + extra_include_dirs: list[Path] | None = None, +) -> int: + """Build and optionally run a C++ test/benchmark binary. + + This is the main orchestration function shared between unit tests + and benchmarks. + + Args: + selected_components: Components to include (directory names in tests_dir) + tests_dir: Directory containing test/benchmark files + codegen_components: Components whose to_code should run + config_prefix: Prefix for the config name (e.g. "cpptests", "cppbench") + friendly_name: Human-readable name for the config + libraries: PlatformIO library specification(s) + platformio_options: PlatformIO options dict + main_entry: Name of the main entry file (e.g. "main.cpp") + label: Label for log messages + build_only: If True, print binary path and return without running + extra_run_args: Extra arguments to pass to the binary + extra_include_dirs: Additional directories whose .cpp files + should be compiled (resolved relative to tests_dir if possible) + + Returns: + Exit code + """ + # Skip on Windows + if os.name == "nt": + print(f"Skipping {label} on Windows", file=sys.stderr) + return EXIT_SKIPPED + + # Remove components that do not have files + components = filter_components_with_files(selected_components, tests_dir) + + if len(components) == 0: + print( + f"No components specified or no files found for {label}.", + file=sys.stderr, + ) + return EXIT_OK + + components = sorted(components) + + # Build include list: main entry point + component folders + extra dirs + includes: list[str] = [main_entry] + components + if extra_include_dirs: + for d in extra_include_dirs: + if d.is_dir() and (any(d.glob("*.cpp")) or any(d.glob("*.h"))): + # ESPHome includes are relative to the config directory (tests_dir) + rel = os.path.relpath(d, tests_dir) + includes.append(rel) + + # Discover platform sub-components + try: + platform_components = get_platform_components(components, tests_dir) + except ValueError as e: + print(f"Error obtaining platform components: {e}") + return EXIT_CONFIG_ERROR + + components = sorted(components + platform_components) + + # Create unique config name + config_name: str = f"{config_prefix}-" + hash_components(components) + + config = create_host_config( + config_name, friendly_name, libraries, includes, platformio_options + ) + + exit_code, program_path = compile_and_get_binary( + config, components, codegen_components, tests_dir, label + ) + + if exit_code != EXIT_OK or program_path is None: + return exit_code + + if build_only: + print(f"BUILD_BINARY={program_path}") + return EXIT_OK + + # Run the binary + run_cmd: list[str] = [program_path] + if extra_run_args: + run_cmd.extend(extra_run_args) + run_proc = subprocess.run(run_cmd, check=False) + return run_proc.returncode From 53fa346ddc6ce6e99ff712ddc8964841368c6851 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:18:49 -0400 Subject: [PATCH 1457/2030] [speaker] Fix media playlist using announcement delay (#14889) --- .../components/speaker/media_player/speaker_media_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 9f168f854d..930373c6fc 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -417,7 +417,7 @@ void SpeakerMediaPlayer::loop() { this->media_playlist_.pop_front(); } // Only delay starting playback if moving on the next playlist item or repeating the current item - timeout_ms = this->announcement_playlist_delay_ms_; + timeout_ms = this->media_playlist_delay_ms_; } if (!this->media_playlist_.empty()) { PlaylistItem playlist_item = this->media_playlist_.front(); From 9a729608d57f993deac55144e39414185421aa3d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 09:58:05 -1000 Subject: [PATCH 1458/2030] [core] Add back deprecated set_internal() for external projects (#14887) --- esphome/core/entity_base.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 012a62f1c0..4c6e5f6596 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -100,6 +100,14 @@ class EntityBase { // Get whether this Entity should be hidden outside ESPHome bool is_internal() const { return this->flags_.internal; } + // Deprecated: Calling set_internal() at runtime is undefined behavior. Components and clients + // are NOT notified of the change, the flag may have already been read during setup, and there + // is NO guarantee any consumer will observe the new value. Use the 'internal:' YAML key instead. + ESPDEPRECATED("set_internal() is undefined behavior at runtime — components and Home Assistant are NOT " + "notified. Use the 'internal:' YAML key instead. Will be removed in 2027.3.0.", + "2026.3.0") + void set_internal(bool internal) { this->flags_.internal = internal; } + // Check if this object is declared to be disabled by default. // That means that when the device gets added to Home Assistant (or other clients) it should // not be added to the default view by default, and a user action is necessary to manually add it. From 851e8b6c0def9938b9603887166a3d1f2693c03b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:28:13 -0400 Subject: [PATCH 1459/2030] [gree] Fix IR checksum for YAA/YAC/YAC1FB9/GENERIC models (#14888) --- esphome/components/gree/gree.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index 8a9f264932..732ebd9632 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -87,19 +87,12 @@ void GreeClimate::transmit_state() { // Calculate the checksum if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) { remote_state[7] = ((remote_state[0] << 4) + (remote_state[1] << 4) + 0xC0); - } else if (this->model_ == GREE_YAG) { + } else { remote_state[7] = ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) + ((remote_state[4] & 0xF0) >> 4) + ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + 0x0A) & 0x0F) << 4); - } else { - remote_state[7] = - ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) + - ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + ((remote_state[7] & 0xF0) >> 4) + 0x0A) & - 0x0F) - << 4) | - (remote_state[7] & 0x0F); } auto transmit = this->transmitter_->transmit(); From 5f06679d78316582e09b8d0f6f56ef0dd8816b1a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:16:44 -1000 Subject: [PATCH 1460/2030] [espnow] Fix EventPool/LockFreeQueue sizing off-by-one (#14893) --- esphome/components/espnow/espnow_component.cpp | 6 ++++-- esphome/components/espnow/espnow_component.h | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index 991803d870..78916891f4 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -87,7 +87,8 @@ void on_send_report(const uint8_t *mac_addr, esp_now_send_status_t status) // Push the packet to the queue global_esp_now->receive_packet_queue_.push(packet); - // Push always because we're the only producer and the pool ensures we never exceed queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. // Wake main loop immediately to process ESP-NOW send event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) @@ -109,7 +110,8 @@ void on_data_received(const esp_now_recv_info_t *info, const uint8_t *data, int // Push the packet to the queue global_esp_now->receive_packet_queue_.push(packet); - // Push always because we're the only producer and the pool ensures we never exceed queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. // Wake main loop immediately to process ESP-NOW receive event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) diff --git a/esphome/components/espnow/espnow_component.h b/esphome/components/espnow/espnow_component.h index 9941e97227..ee4adc1b4d 100644 --- a/esphome/components/espnow/espnow_component.h +++ b/esphome/components/espnow/espnow_component.h @@ -163,10 +163,14 @@ class ESPNowComponent : public Component { uint8_t own_address_[ESP_NOW_ETH_ALEN]{0}; LockFreeQueue<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE> receive_packet_queue_{}; - EventPool<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE> receive_packet_pool_{}; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE - 1> receive_packet_pool_{}; LockFreeQueue<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE> send_packet_queue_{}; - EventPool<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE> send_packet_pool_{}; + // Pool sized to queue capacity (SIZE-1) — see receive_packet_pool_ comment. + EventPool<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE - 1> send_packet_pool_{}; ESPNowSendPacket *current_send_packet_{nullptr}; // Currently sending packet, nullptr if none uint8_t wifi_channel_{0}; From 97382ed8148fbe42c18bfd1ed7c10cd76b3b922e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:17:43 -1000 Subject: [PATCH 1461/2030] [usb_cdc_acm] Fix EventPool/LockFreeQueue sizing off-by-one (#14894) --- .../components/usb_cdc_acm/usb_cdc_acm.cpp | 26 +++++++------------ esphome/components/usb_cdc_acm/usb_cdc_acm.h | 6 ++++- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp index a4c2e6c4a4..253626f0a3 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp @@ -26,16 +26,13 @@ void USBCDCACMInstance::queue_line_state_event(bool dtr, bool rts) { event->data.line_state.dtr = dtr; event->data.line_state.rts = rts; - if (!this->event_queue_.push(event)) { - ESP_LOGW(TAG, "Event queue full, line state event dropped (itf=%d)", this->itf_); - // Return event to pool since we couldn't queue it - this->event_pool_.release(event); - } else { - // Wake main loop immediately to process event + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->event_queue_.push(event); + #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); + App.wake_loop_threadsafe(); #endif - } } void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, @@ -53,16 +50,13 @@ void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_ event->data.line_coding.parity = parity; event->data.line_coding.data_bits = data_bits; - if (!this->event_queue_.push(event)) { - ESP_LOGW(TAG, "Event queue full, line coding event dropped (itf=%d)", this->itf_); - // Return event to pool since we couldn't queue it - this->event_pool_.release(event); - } else { - // Wake main loop immediately to process event + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->event_queue_.push(event); + #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); + App.wake_loop_threadsafe(); #endif - } } void USBCDCACMInstance::process_events_() { diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index 020542e749..a56abc9ee8 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -102,7 +102,11 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC LineStateCallback line_state_callback_{nullptr}; // Lock-free queue and event pool for cross-task event passing - EventPool<CDCEvent, EVENT_QUEUE_SIZE> event_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing both a pool slot leak and an SPSC + // violation on the pool's internal free list. + EventPool<CDCEvent, EVENT_QUEUE_SIZE - 1> event_pool_; LockFreeQueue<CDCEvent, EVENT_QUEUE_SIZE> event_queue_; }; From c19c75220bbf2f20e37dec81ac18dc0735e5e058 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:17:59 -1000 Subject: [PATCH 1462/2030] [usb_host] Fix EventPool/LockFreeQueue sizing off-by-one (#14896) --- esphome/components/usb_host/usb_host.h | 5 ++++- esphome/components/usb_host/usb_host_client.cpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index 2eec0c9699..dcb76a3a3b 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -144,7 +144,10 @@ class USBClient : public Component { // Lock-free event queue and pool for USB task to main loop communication // Must be public for access from static callbacks LockFreeQueue<UsbEvent, USB_EVENT_QUEUE_SIZE> event_queue; - EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE> event_pool; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE - 1> event_pool; protected: // Process USB events from the queue. Returns true if any work was done. diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 2a460d1a07..18d938344c 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -193,7 +193,8 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * return; } - // Push to lock-free queue (always succeeds since pool size == queue size) + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. client->event_queue.push(event); // Re-enable component loop to process the queued event From a94bb74d043da0b1128c7a899a1765a3e13f6af0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:18:31 -1000 Subject: [PATCH 1463/2030] [usb_uart] Fix EventPool/LockFreeQueue sizing off-by-one (#14895) --- esphome/components/usb_uart/usb_uart.cpp | 11 +++++------ esphome/components/usb_uart/usb_uart.h | 8 ++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 997f836146..a5d312f191 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -160,11 +160,9 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { size_t chunk_len = std::min(len, UsbOutputChunk::MAX_CHUNK_SIZE); memcpy(chunk->data, data, chunk_len); chunk->length = static_cast<uint8_t>(chunk_len); - if (!this->output_queue_.push(chunk)) { - this->output_pool_.release(chunk); - ESP_LOGE(TAG, "Output queue full - lost %zu bytes", len); - break; - } + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->output_queue_.push(chunk); data += chunk_len; len -= chunk_len; } @@ -320,7 +318,8 @@ void USBUartComponent::start_input(USBUartChannel *channel) { chunk->channel = channel; // Push to lock-free queue for main loop processing - // Push always succeeds because pool size == queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. this->usb_data_queue_.push(chunk); // Re-enable component loop to process the queued data diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 16469df7f6..7a06b04f11 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -158,7 +158,10 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon // Larger structures first (8+ bytes) RingBuffer input_buffer_; LockFreeQueue<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_queue_; - EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT - 1> output_pool_; std::function<void()> rx_callback_{}; CdcEps cdc_dev_{}; StringRef debug_prefix_{}; @@ -190,7 +193,8 @@ class USBUartComponent : public usb_host::USBClient { // Lock-free data transfer from USB task to main loop static constexpr int USB_DATA_QUEUE_SIZE = 32; LockFreeQueue<UsbDataChunk, USB_DATA_QUEUE_SIZE> usb_data_queue_; - EventPool<UsbDataChunk, USB_DATA_QUEUE_SIZE> chunk_pool_; + // Pool sized to queue capacity (SIZE-1) — see USBUartChannel::output_pool_ comment. + EventPool<UsbDataChunk, USB_DATA_QUEUE_SIZE - 1> chunk_pool_; protected: std::vector<USBUartChannel *> channels_{}; From 1adf05e2d59b60e7b22d0a0efedd5f9181f1fa12 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:24:02 -1000 Subject: [PATCH 1464/2030] [esp32_ble] Fix EventPool/LockFreeQueue sizing off-by-one (#14892) --- esphome/components/esp32_ble/ble.cpp | 3 ++- esphome/components/esp32_ble/ble.h | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index ff9d9bb15a..fee1c546be 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -575,8 +575,9 @@ template<typename... Args> void enqueue_ble_event(Args... args) { load_ble_event(event, args...); // Push the event to the queue + // Push always succeeds: pool is sized to queue capacity (N-1), so if + // allocate() returned non-null, the queue is guaranteed to have room. global_ble->ble_events_.push(event); - // Push always succeeds because we're the only producer and the pool ensures we never exceed queue size } // Explicit template instantiations for the friend function diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 04bec3f785..752ddc9d1f 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -221,7 +221,13 @@ class ESP32BLE : public Component { // Large objects (size depends on template parameters, but typically aligned to 4 bytes) esphome::LockFreeQueue<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_events_; - esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_event_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements (one slot distinguishes full from empty). + // This guarantees allocate() returns nullptr before push() can fail, which: + // 1. Prevents leaking a pool slot (the Nth allocate succeeds but push fails) + // 2. Avoids needing release() on the producer path after a failed push(), + // preserving the SPSC contract on the pool's internal free list + esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE - 1> ble_event_pool_; // 4-byte aligned members #ifdef USE_ESP32_BLE_ADVERTISING From 1670f04a8715380be9452e37d0b0c133c092c5f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:29:38 -1000 Subject: [PATCH 1465/2030] [core] Add CodSpeed C++ benchmarks for protobuf, main loop, and helpers (#14878) --- .github/workflows/ci.yml | 34 ++ esphome/core/component.h | 2 + script/clang-tidy | 3 + script/cpp_benchmark.py | 130 ++++++++ script/determine-jobs.py | 61 ++++ script/setup_codspeed_lib.py | 231 ++++++++++++++ tests/benchmarks/components/.gitignore | 2 + .../components/api/bench_proto_decode.cpp | 93 ++++++ .../components/api/bench_proto_encode.cpp | 298 ++++++++++++++++++ .../components/api/bench_proto_varint.cpp | 133 ++++++++ .../benchmarks/components/api/benchmark.yaml | 114 +++++++ tests/benchmarks/components/main.cpp | 42 +++ .../core/bench_application_loop.cpp | 22 ++ tests/benchmarks/core/bench_helpers.cpp | 41 +++ tests/benchmarks/core/bench_logger.cpp | 54 ++++ tests/benchmarks/core/bench_scheduler.cpp | 133 ++++++++ tests/script/test_determine_jobs.py | 148 +++++++++ 17 files changed, 1541 insertions(+) create mode 100755 script/cpp_benchmark.py create mode 100755 script/setup_codspeed_lib.py create mode 100644 tests/benchmarks/components/.gitignore create mode 100644 tests/benchmarks/components/api/bench_proto_decode.cpp create mode 100644 tests/benchmarks/components/api/bench_proto_encode.cpp create mode 100644 tests/benchmarks/components/api/bench_proto_varint.cpp create mode 100644 tests/benchmarks/components/api/benchmark.yaml create mode 100644 tests/benchmarks/components/main.cpp create mode 100644 tests/benchmarks/core/bench_application_loop.cpp create mode 100644 tests/benchmarks/core/bench_helpers.cpp create mode 100644 tests/benchmarks/core/bench_logger.cpp create mode 100644 tests/benchmarks/core/bench_scheduler.cpp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7710589c5..1926ad5bf4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -185,6 +185,7 @@ jobs: cpp-unit-tests-run-all: ${{ steps.determine.outputs.cpp-unit-tests-run-all }} cpp-unit-tests-components: ${{ steps.determine.outputs.cpp-unit-tests-components }} component-test-batches: ${{ steps.determine.outputs.component-test-batches }} + benchmarks: ${{ steps.determine.outputs.benchmarks }} steps: - name: Check out code from GitHub uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -227,6 +228,7 @@ jobs: echo "cpp-unit-tests-run-all=$(echo "$output" | jq -r '.cpp_unit_tests_run_all')" >> $GITHUB_OUTPUT echo "cpp-unit-tests-components=$(echo "$output" | jq -c '.cpp_unit_tests_components')" >> $GITHUB_OUTPUT echo "component-test-batches=$(echo "$output" | jq -c '.component_test_batches')" >> $GITHUB_OUTPUT + echo "benchmarks=$(echo "$output" | jq -r '.benchmarks')" >> $GITHUB_OUTPUT - name: Save components graph cache if: github.ref == 'refs/heads/dev' uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 @@ -308,6 +310,38 @@ jobs: script/cpp_unit_test.py $ARGS fi + benchmarks: + name: Run CodSpeed benchmarks + runs-on: ubuntu-24.04 + needs: + - common + - determine-jobs + if: github.event_name == 'pull_request' && needs.determine-jobs.outputs.benchmarks == 'true' + steps: + - name: Check out code from GitHub + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Restore Python + uses: ./.github/actions/restore-python + with: + python-version: ${{ env.DEFAULT_PYTHON }} + cache-key: ${{ needs.common.outputs.cache-key }} + + - name: Build benchmarks + id: build + run: | + . venv/bin/activate + export BENCHMARK_LIB_CONFIG=$(python script/setup_codspeed_lib.py) + # --build-only prints BUILD_BINARY=<path> to stdout + BINARY=$(script/cpp_benchmark.py --all --build-only | grep '^BUILD_BINARY=' | tail -1 | cut -d= -f2-) + echo "binary=$BINARY" >> $GITHUB_OUTPUT + + - name: Run CodSpeed benchmarks + uses: CodSpeedHQ/action@281164b0f014a4e7badd2c02cecad9b595b70537 # v4 + with: + run: ${{ steps.build.outputs.binary }} + mode: simulation + clang-tidy-single: name: ${{ matrix.name }} runs-on: ubuntu-24.04 diff --git a/esphome/core/component.h b/esphome/core/component.h index 5fdf23e128..557ba09bbc 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -598,9 +598,11 @@ class WarnIfComponentBlockingGuard { #ifdef USE_RUNTIME_STATS this->record_runtime_stats_(); #endif +#ifndef USE_BENCHMARK if (blocking_time > WARN_IF_BLOCKING_OVER_MS) [[unlikely]] { warn_blocking(this->component_, blocking_time); } +#endif return curr_time; } diff --git a/script/clang-tidy b/script/clang-tidy index 9c2899026d..f2834b44ac 100755 --- a/script/clang-tidy +++ b/script/clang-tidy @@ -231,6 +231,9 @@ def main(): cwd = os.getcwd() files = [os.path.relpath(path, cwd) for path in git_ls_files(["*.cpp"])] + # Exclude benchmark files — they require google benchmark headers not + # available in the ESP32 toolchain and use different naming conventions. + files = [f for f in files if not f.startswith("tests/benchmarks/")] # Print initial file count if it's large if len(files) > 50: diff --git a/script/cpp_benchmark.py b/script/cpp_benchmark.py new file mode 100755 index 0000000000..bd92266ea6 --- /dev/null +++ b/script/cpp_benchmark.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +"""Build and run C++ benchmarks for ESPHome components using Google Benchmark.""" + +import argparse +import json +import os +from pathlib import Path +import sys + +from helpers import root_path +from test_helpers import ( + BASE_CODEGEN_COMPONENTS, + PLATFORMIO_GOOGLE_BENCHMARK_LIB, + USE_TIME_TIMEZONE_FLAG, + build_and_run, +) + +# Path to /tests/benchmarks/components +BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "components" + +# Path to /tests/benchmarks/core (always included, not a component) +CORE_BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "core" + +# Additional codegen components beyond the base set. +# json is needed because its to_code adds the ArduinoJson library +# (auto-loaded by api, but cpp_testing suppresses to_code unless listed). +BENCHMARK_CODEGEN_COMPONENTS = BASE_CODEGEN_COMPONENTS | {"json"} + +PLATFORMIO_OPTIONS = { + "build_unflags": [ + "-Os", # remove default size-opt + ], + "build_flags": [ + "-O2", # optimize for speed (CodSpeed recommends RelWithDebInfo) + "-g", # debug symbols for profiling + USE_TIME_TIMEZONE_FLAG, + "-DUSE_BENCHMARK", # disable WarnIfComponentBlockingGuard in finish() + ], + # Use deep+ LDF mode to ensure PlatformIO detects the benchmark + # library dependency from nested includes. + "lib_ldf_mode": "deep+", +} + + +def run_benchmarks(selected_components: list[str], build_only: bool = False) -> int: + # Allow CI to override the benchmark library (e.g. with CodSpeed's fork). + # BENCHMARK_LIB_CONFIG is a JSON string from setup_codspeed_lib.py + # containing {"lib_path": "/path/to/google_benchmark"}. + lib_config_json = os.environ.get("BENCHMARK_LIB_CONFIG") + + pio_options = PLATFORMIO_OPTIONS + if lib_config_json: + lib_config = json.loads(lib_config_json) + benchmark_lib = f"benchmark=symlink://{lib_config['lib_path']}" + # These defines must be global (not just in library.json) because + # benchmark.h uses #ifdef CODSPEED_ENABLED to switch benchmark + # registration to CodSpeed-instrumented variants, and + # CODSPEED_ROOT_DIR is used to display relative file paths in reports. + project_root = Path(__file__).resolve().parent.parent + codspeed_flags = [ + "-DNDEBUG", + "-DCODSPEED_ENABLED", + "-DCODSPEED_ANALYSIS", + f'-DCODSPEED_ROOT_DIR=\\"{project_root}\\"', + ] + pio_options = { + **PLATFORMIO_OPTIONS, + "build_flags": PLATFORMIO_OPTIONS["build_flags"] + codspeed_flags, + } + else: + benchmark_lib = PLATFORMIO_GOOGLE_BENCHMARK_LIB + + return build_and_run( + selected_components=selected_components, + tests_dir=BENCHMARKS_DIR, + codegen_components=BENCHMARK_CODEGEN_COMPONENTS, + config_prefix="cppbench", + friendly_name="CPP Benchmarks", + libraries=benchmark_lib, + platformio_options=pio_options, + main_entry="main.cpp", + label="benchmarks", + build_only=build_only, + extra_include_dirs=[CORE_BENCHMARKS_DIR], + ) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Build and run C++ benchmarks for ESPHome components." + ) + parser.add_argument( + "components", + nargs="*", + help="List of components to benchmark (must have files in tests/benchmarks/components/).", + ) + parser.add_argument( + "--all", + action="store_true", + help="Benchmark all components with benchmark files.", + ) + parser.add_argument( + "--build-only", + action="store_true", + help="Only build, print binary path without running.", + ) + + args = parser.parse_args() + + if args.all: + # Find all component directories that have .cpp files + components: list[str] = ( + sorted( + d.name + for d in BENCHMARKS_DIR.iterdir() + if d.is_dir() + and d.name != "__pycache__" + and (any(d.glob("*.cpp")) or any(d.glob("*.h"))) + ) + if BENCHMARKS_DIR.is_dir() + else [] + ) + else: + components: list[str] = args.components + + sys.exit(run_benchmarks(components, build_only=args.build_only)) + + +if __name__ == "__main__": + main() diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 6808a3cf6c..ad08f8dce5 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -381,6 +381,63 @@ def determine_cpp_unit_tests( return (False, get_cpp_changed_components(cpp_files)) +# Paths within tests/benchmarks/ that contain component benchmark files +BENCHMARKS_COMPONENTS_PATH = "tests/benchmarks/components" + +# Files that, when changed, should trigger benchmark runs +BENCHMARK_INFRASTRUCTURE_FILES = frozenset( + { + "script/cpp_benchmark.py", + "script/test_helpers.py", + "script/setup_codspeed_lib.py", + } +) + + +def should_run_benchmarks(branch: str | None = None) -> bool: + """Determine if C++ benchmarks should run based on changed files. + + Benchmarks run when any of the following conditions are met: + + 1. Core C++ files changed (esphome/core/*) + 2. A directly changed component has benchmark files (no dependency expansion) + 3. Benchmark infrastructure changed (tests/benchmarks/*, script/cpp_benchmark.py, + script/test_helpers.py, script/setup_codspeed_lib.py) + + Unlike unit tests, benchmarks do NOT expand to dependent components. + Changing ``sensor`` does not trigger ``api`` benchmarks just because + api depends on sensor. + + Args: + branch: Branch to compare against. If None, uses default. + + Returns: + True if benchmarks should run, False otherwise. + """ + files = changed_files(branch) + if core_changed(files): + return True + + # Check if benchmark infrastructure changed + if any( + f.startswith("tests/benchmarks/") or f in BENCHMARK_INFRASTRUCTURE_FILES + for f in files + ): + return True + + # Check if any directly changed component has benchmarks + benchmarks_dir = Path(root_path) / BENCHMARKS_COMPONENTS_PATH + if not benchmarks_dir.is_dir(): + return False + benchmarked_components = { + d.name + for d in benchmarks_dir.iterdir() + if d.is_dir() and (any(d.glob("*.cpp")) or any(d.glob("*.h"))) + } + # Only direct changes — no dependency expansion + return any(get_component_from_path(f) in benchmarked_components for f in files) + + def _any_changed_file_endswith(branch: str | None, extensions: tuple[str, ...]) -> bool: """Check if a changed file ends with any of the specified extensions.""" return any(file.endswith(extensions) for file in changed_files(branch)) @@ -804,6 +861,9 @@ def main() -> None: # Determine which C++ unit tests to run cpp_run_all, cpp_components = determine_cpp_unit_tests(args.branch) + # Determine if benchmarks should run + run_benchmarks = should_run_benchmarks(args.branch) + # Split components into batches for CI testing # This intelligently groups components with similar bus configurations component_test_batches: list[str] @@ -856,6 +916,7 @@ def main() -> None: "cpp_unit_tests_run_all": cpp_run_all, "cpp_unit_tests_components": cpp_components, "component_test_batches": component_test_batches, + "benchmarks": run_benchmarks, } # Output as JSON diff --git a/script/setup_codspeed_lib.py b/script/setup_codspeed_lib.py new file mode 100755 index 0000000000..959c89d05b --- /dev/null +++ b/script/setup_codspeed_lib.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +"""Set up CodSpeed's google_benchmark fork as a PlatformIO library. + +CodSpeed requires their codspeed-cpp fork for CPU simulation instrumentation. +This script clones the repo and assembles a flat PlatformIO-compatible library +by combining google_benchmark sources, codspeed core, and instrument-hooks. + +PlatformIO quirks addressed: + - .cc files renamed to .cpp (PlatformIO ignores .cc) + - All sources merged into one src/ dir (PlatformIO can't compile from + multiple source directories in a single library) + - library.json created with required CodSpeed preprocessor defines + +Usage: + python script/setup_codspeed_lib.py [--output-dir DIR] + +Prints JSON to stdout with lib_path for cpp_benchmark.py. +Git output goes to stderr. + +See https://codspeed.io/docs/benchmarks/cpp#custom-build-systems +""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path +import shutil +import subprocess +import sys + +# Pin to a specific release for reproducibility +CODSPEED_CPP_REPO = "https://github.com/CodSpeedHQ/codspeed-cpp.git" +CODSPEED_CPP_SHA = "e633aca00da3d0ad14e7bf424d9cb47165a29028" # v2.1.0 + +DEFAULT_OUTPUT_DIR = "/tmp/codspeed-cpp" + +# Well-known paths within the codspeed-cpp repository +GOOGLE_BENCHMARK_SUBDIR = "google_benchmark" +CORE_SUBDIR = "core" +INSTRUMENT_HOOKS_SUBDIR = Path(CORE_SUBDIR) / "instrument-hooks" +INSTRUMENT_HOOKS_INCLUDES = INSTRUMENT_HOOKS_SUBDIR / "includes" +INSTRUMENT_HOOKS_DIST = INSTRUMENT_HOOKS_SUBDIR / "dist" / "core.c" +CORE_CMAKE = Path(CORE_SUBDIR) / "CMakeLists.txt" + + +def _git(args: list[str], **kwargs: object) -> None: + """Run a git command, sending output to stderr.""" + subprocess.run( + ["git", *args], + check=True, + stdout=kwargs.pop("stdout", sys.stderr), + stderr=kwargs.pop("stderr", sys.stderr), + **kwargs, + ) + + +def _clone_repo(output_dir: Path) -> None: + """Shallow-clone codspeed-cpp at the pinned SHA with submodules.""" + output_dir.mkdir(parents=True, exist_ok=True) + _git(["init", str(output_dir)]) + _git(["-C", str(output_dir), "remote", "add", "origin", CODSPEED_CPP_REPO]) + _git(["-C", str(output_dir), "fetch", "--depth", "1", "origin", CODSPEED_CPP_SHA]) + _git( + ["-C", str(output_dir), "checkout", "FETCH_HEAD"], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + _git( + [ + "-C", + str(output_dir), + "submodule", + "update", + "--init", + "--recursive", + "--depth", + "1", + ] + ) + + +def _read_codspeed_version(cmake_path: Path) -> str: + """Extract CODSPEED_VERSION from core/CMakeLists.txt.""" + if not cmake_path.exists(): + return "0.0.0" + for line in cmake_path.read_text().splitlines(): + if line.startswith("set(CODSPEED_VERSION"): + return line.split()[1].rstrip(")") + return "0.0.0" + + +def _rename_cc_to_cpp(src_dir: Path) -> None: + """Rename .cc files to .cpp so PlatformIO compiles them.""" + for cc_file in src_dir.glob("*.cc"): + cpp_file = cc_file.with_suffix(".cpp") + if not cpp_file.exists(): + cc_file.rename(cpp_file) + + +def _copy_if_missing(src: Path, dest: Path) -> None: + """Copy a file only if the destination doesn't already exist.""" + if not dest.exists(): + shutil.copy2(src, dest) + + +def _merge_codspeed_core_into_lib(core_src: Path, lib_src: Path) -> None: + """Copy codspeed core sources into the benchmark library src/. + + .cpp files get a ``codspeed_`` prefix to avoid name collisions with + google_benchmark's own sources. .h files keep their original names + since they're referenced by ``#include "walltime.h"`` etc. + """ + for src_file in core_src.iterdir(): + if src_file.suffix == ".cpp": + _copy_if_missing(src_file, lib_src / f"codspeed_{src_file.name}") + elif src_file.suffix == ".h": + _copy_if_missing(src_file, lib_src / src_file.name) + + +def _write_library_json( + benchmark_dir: Path, + core_include: Path, + hooks_include: Path, + version: str, + project_root: Path, +) -> None: + """Write a PlatformIO library.json with CodSpeed build flags.""" + library_json = { + "name": "benchmark", + "version": "0.0.0", + "build": { + "flags": [ + f"-I{core_include}", + f"-I{hooks_include}", + # google benchmark build flags + # -O2 is critical: without it, instrument_hooks_start_benchmark_inline + # doesn't get inlined and shows up as overhead in profiles + "-O2", + "-DNDEBUG", + "-DHAVE_STD_REGEX", + "-DHAVE_STEADY_CLOCK", + "-DBENCHMARK_STATIC_DEFINE", + # CodSpeed instrumentation flags + # https://codspeed.io/docs/benchmarks/cpp#custom-build-systems + "-DCODSPEED_ENABLED", + "-DCODSPEED_ANALYSIS", + f'-DCODSPEED_VERSION=\\"{version}\\"', + f'-DCODSPEED_ROOT_DIR=\\"{project_root}\\"', + '-DCODSPEED_MODE_DISPLAY=\\"simulation\\"', + ], + "includeDir": "include", + }, + } + (benchmark_dir / "library.json").write_text( + json.dumps(library_json, indent=2) + "\n" + ) + + +def setup_codspeed_lib(output_dir: Path) -> None: + """Clone codspeed-cpp and assemble a flat PlatformIO library. + + The resulting library at ``output_dir/google_benchmark/`` contains: + - google_benchmark sources (.cc renamed to .cpp) + - codspeed core sources (prefixed ``codspeed_``) + - instrument-hooks C source (as ``instrument_hooks.c``) + - library.json with all required CodSpeed defines + + Args: + output_dir: Directory to clone the repository into + """ + if not (output_dir / ".git").exists(): + _clone_repo(output_dir) + else: + # Verify the existing checkout matches the pinned SHA + result = subprocess.run( + ["git", "-C", str(output_dir), "rev-parse", "HEAD"], + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0 or result.stdout.strip() != CODSPEED_CPP_SHA: + print( + f"Stale codspeed-cpp checkout, re-cloning at {CODSPEED_CPP_SHA}", + file=sys.stderr, + ) + shutil.rmtree(output_dir) + _clone_repo(output_dir) + + benchmark_dir = output_dir / GOOGLE_BENCHMARK_SUBDIR + lib_src = benchmark_dir / "src" + core_dir = output_dir / CORE_SUBDIR + core_include = core_dir / "include" + hooks_include = output_dir / INSTRUMENT_HOOKS_INCLUDES + hooks_dist_c = output_dir / INSTRUMENT_HOOKS_DIST + project_root = Path(__file__).resolve().parent.parent + + # 1. Rename .cc → .cpp (PlatformIO doesn't compile .cc) + _rename_cc_to_cpp(lib_src) + + # 2. Merge codspeed core sources into the library + _merge_codspeed_core_into_lib(core_dir / "src", lib_src) + + # 3. Copy instrument-hooks C source (provides instrument_hooks_* symbols) + if hooks_dist_c.exists(): + _copy_if_missing(hooks_dist_c, lib_src / "instrument_hooks.c") + + # 4. Write library.json + version = _read_codspeed_version(output_dir / CORE_CMAKE) + _write_library_json( + benchmark_dir, core_include, hooks_include, version, project_root + ) + + # Output JSON config for cpp_benchmark.py + print(json.dumps({"lib_path": str(benchmark_dir)})) + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--output-dir", + type=Path, + default=Path(DEFAULT_OUTPUT_DIR), + help=f"Directory to clone codspeed-cpp into (default: {DEFAULT_OUTPUT_DIR})", + ) + args = parser.parse_args() + setup_codspeed_lib(args.output_dir) + + +if __name__ == "__main__": + main() diff --git a/tests/benchmarks/components/.gitignore b/tests/benchmarks/components/.gitignore new file mode 100644 index 0000000000..163bec7b80 --- /dev/null +++ b/tests/benchmarks/components/.gitignore @@ -0,0 +1,2 @@ +/.esphome/ +/secrets.yaml diff --git a/tests/benchmarks/components/api/bench_proto_decode.cpp b/tests/benchmarks/components/api/bench_proto_decode.cpp new file mode 100644 index 0000000000..113201dd8a --- /dev/null +++ b/tests/benchmarks/components/api/bench_proto_decode.cpp @@ -0,0 +1,93 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/api/api_pb2.h" +#include "esphome/components/api/api_buffer.h" + +namespace esphome::api::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// Helper: encode a message into a buffer and return it. +// Benchmarks encode once in setup, then decode the resulting bytes in a loop. +// This keeps decode benchmarks in sync with the actual protobuf schema — +// hand-encoded byte arrays would silently break when fields change. +template<typename T> static APIBuffer encode_message(const T &msg) { + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + return buffer; +} + +// --- HelloRequest decode (string + varint fields) --- + +static void Decode_HelloRequest(benchmark::State &state) { + HelloRequest source; + source.client_info = StringRef::from_lit("aioesphomeapi"); + source.api_version_major = 1; + source.api_version_minor = 10; + auto encoded = encode_message(source); + + for (auto _ : state) { + HelloRequest msg; + for (int i = 0; i < kInnerIterations; i++) { + msg.decode(encoded.data(), encoded.size()); + } + benchmark::DoNotOptimize(msg.api_version_major); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Decode_HelloRequest); + +// --- SwitchCommandRequest decode (simple command) --- + +static void Decode_SwitchCommandRequest(benchmark::State &state) { + SwitchCommandRequest source; + source.key = 0x12345678; + source.state = true; + auto encoded = encode_message(source); + + for (auto _ : state) { + SwitchCommandRequest msg; + for (int i = 0; i < kInnerIterations; i++) { + msg.decode(encoded.data(), encoded.size()); + } + benchmark::DoNotOptimize(msg.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Decode_SwitchCommandRequest); + +// --- LightCommandRequest decode (complex command with many fields) --- + +static void Decode_LightCommandRequest(benchmark::State &state) { + LightCommandRequest source; + source.key = 0x11223344; + source.has_state = true; + source.state = true; + source.has_brightness = true; + source.brightness = 0.8f; + source.has_rgb = true; + source.red = 1.0f; + source.green = 0.5f; + source.blue = 0.2f; + source.has_effect = true; + source.effect = StringRef::from_lit("rainbow"); + auto encoded = encode_message(source); + + for (auto _ : state) { + LightCommandRequest msg; + for (int i = 0; i < kInnerIterations; i++) { + msg.decode(encoded.data(), encoded.size()); + } + benchmark::DoNotOptimize(msg.brightness); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Decode_LightCommandRequest); + +} // namespace esphome::api::benchmarks diff --git a/tests/benchmarks/components/api/bench_proto_encode.cpp b/tests/benchmarks/components/api/bench_proto_encode.cpp new file mode 100644 index 0000000000..656c1e17db --- /dev/null +++ b/tests/benchmarks/components/api/bench_proto_encode.cpp @@ -0,0 +1,298 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/api/api_pb2.h" +#include "esphome/components/api/api_buffer.h" + +namespace esphome::api::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// --- SensorStateResponse (highest frequency message) --- + +static void Encode_SensorStateResponse(benchmark::State &state) { + APIBuffer buffer; + SensorStateResponse msg; + msg.key = 0x12345678; + msg.state = 23.5f; + msg.missing_state = false; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_SensorStateResponse); + +static void CalculateSize_SensorStateResponse(benchmark::State &state) { + SensorStateResponse msg; + msg.key = 0x12345678; + msg.state = 23.5f; + msg.missing_state = false; + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_SensorStateResponse); + +// Steady state: buffer already allocated from previous iteration +static void CalcAndEncode_SensorStateResponse(benchmark::State &state) { + APIBuffer buffer; + SensorStateResponse msg; + msg.key = 0x12345678; + msg.state = 23.5f; + msg.missing_state = false; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_SensorStateResponse); + +// Cold path: fresh buffer each iteration (measures heap allocation cost). +// Inner loop still needed to amortize CodSpeed instrumentation overhead. +// Each inner iteration creates a fresh buffer, so this measures +// alloc+calc+encode per item. +static void CalcAndEncode_SensorStateResponse_Fresh(benchmark::State &state) { + SensorStateResponse msg; + msg.key = 0x12345678; + msg.state = 23.5f; + msg.missing_state = false; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + benchmark::DoNotOptimize(buffer.data()); + } + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_SensorStateResponse_Fresh); + +// --- BinarySensorStateResponse --- + +static void Encode_BinarySensorStateResponse(benchmark::State &state) { + APIBuffer buffer; + BinarySensorStateResponse msg; + msg.key = 0xAABBCCDD; + msg.state = true; + msg.missing_state = false; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_BinarySensorStateResponse); + +// --- HelloResponse (string fields) --- + +static void Encode_HelloResponse(benchmark::State &state) { + APIBuffer buffer; + HelloResponse msg; + msg.api_version_major = 1; + msg.api_version_minor = 10; + msg.server_info = StringRef::from_lit("esphome v2026.3.0"); + msg.name = StringRef::from_lit("living-room-sensor"); + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_HelloResponse); + +// --- LightStateResponse (complex multi-field message) --- + +static void Encode_LightStateResponse(benchmark::State &state) { + APIBuffer buffer; + LightStateResponse msg; + msg.key = 0x11223344; + msg.state = true; + msg.brightness = 0.8f; + msg.color_mode = enums::COLOR_MODE_RGB_WHITE; + msg.color_brightness = 1.0f; + msg.red = 1.0f; + msg.green = 0.5f; + msg.blue = 0.2f; + msg.white = 0.0f; + msg.color_temperature = 4000.0f; + msg.cold_white = 0.0f; + msg.warm_white = 0.0f; + msg.effect = StringRef::from_lit("rainbow"); + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_LightStateResponse); + +static void CalculateSize_LightStateResponse(benchmark::State &state) { + LightStateResponse msg; + msg.key = 0x11223344; + msg.state = true; + msg.brightness = 0.8f; + msg.color_mode = enums::COLOR_MODE_RGB_WHITE; + msg.color_brightness = 1.0f; + msg.red = 1.0f; + msg.green = 0.5f; + msg.blue = 0.2f; + msg.white = 0.0f; + msg.color_temperature = 4000.0f; + msg.cold_white = 0.0f; + msg.warm_white = 0.0f; + msg.effect = StringRef::from_lit("rainbow"); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_LightStateResponse); + +// --- DeviceInfoResponse (nested submessages: 20 devices + 20 areas) --- + +static DeviceInfoResponse make_device_info_response() { + DeviceInfoResponse msg; + msg.name = StringRef::from_lit("living-room-sensor"); + msg.mac_address = StringRef::from_lit("AA:BB:CC:DD:EE:FF"); + msg.esphome_version = StringRef::from_lit("2026.3.0"); + msg.compilation_time = StringRef::from_lit("Mar 16 2026, 12:00:00"); + msg.model = StringRef::from_lit("esp32-poe-iso"); + msg.manufacturer = StringRef::from_lit("Olimex"); + msg.friendly_name = StringRef::from_lit("Living Room Sensor"); +#ifdef USE_DEVICES + for (uint32_t i = 0; i < ESPHOME_DEVICE_COUNT && i < 20; i++) { + msg.devices[i].device_id = i + 1; + msg.devices[i].name = StringRef::from_lit("device"); + msg.devices[i].area_id = (i % 20) + 1; + } +#endif +#ifdef USE_AREAS + for (uint32_t i = 0; i < ESPHOME_AREA_COUNT && i < 20; i++) { + msg.areas[i].area_id = i + 1; + msg.areas[i].name = StringRef::from_lit("area"); + } +#endif + return msg; +} + +static void CalculateSize_DeviceInfoResponse(benchmark::State &state) { + auto msg = make_device_info_response(); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_DeviceInfoResponse); + +static void Encode_DeviceInfoResponse(benchmark::State &state) { + auto msg = make_device_info_response(); + APIBuffer buffer; + uint32_t total_size = msg.calculate_size(); + buffer.resize(total_size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_DeviceInfoResponse); + +// Steady state: buffer already allocated from previous iteration +static void CalcAndEncode_DeviceInfoResponse(benchmark::State &state) { + auto msg = make_device_info_response(); + APIBuffer buffer; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_DeviceInfoResponse); + +// Cold path: fresh buffer each iteration (measures heap allocation cost). +// Inner loop still needed to amortize CodSpeed instrumentation overhead. +// Each inner iteration creates a fresh buffer, so this measures +// alloc+calc+encode per item. +static void CalcAndEncode_DeviceInfoResponse_Fresh(benchmark::State &state) { + auto msg = make_device_info_response(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + benchmark::DoNotOptimize(buffer.data()); + } + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_DeviceInfoResponse_Fresh); + +} // namespace esphome::api::benchmarks diff --git a/tests/benchmarks/components/api/bench_proto_varint.cpp b/tests/benchmarks/components/api/bench_proto_varint.cpp new file mode 100644 index 0000000000..0b5ccc2b7d --- /dev/null +++ b/tests/benchmarks/components/api/bench_proto_varint.cpp @@ -0,0 +1,133 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/api/proto.h" +#include "esphome/components/api/api_buffer.h" + +namespace esphome::api::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// --- ProtoVarInt::parse() benchmarks --- + +static void ProtoVarInt_Parse_SingleByte(benchmark::State &state) { + uint8_t buf[] = {0x42}; // value = 66 + + for (auto _ : state) { + ProtoVarIntResult result{}; + for (int i = 0; i < kInnerIterations; i++) { + result = ProtoVarInt::parse(buf, sizeof(buf)); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ProtoVarInt_Parse_SingleByte); + +static void ProtoVarInt_Parse_TwoByte(benchmark::State &state) { + uint8_t buf[] = {0x80, 0x01}; // value = 128 + + for (auto _ : state) { + ProtoVarIntResult result{}; + for (int i = 0; i < kInnerIterations; i++) { + result = ProtoVarInt::parse(buf, sizeof(buf)); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ProtoVarInt_Parse_TwoByte); + +static void ProtoVarInt_Parse_FiveByte(benchmark::State &state) { + uint8_t buf[] = {0xFF, 0xFF, 0xFF, 0xFF, 0x0F}; + + for (auto _ : state) { + ProtoVarIntResult result{}; + for (int i = 0; i < kInnerIterations; i++) { + result = ProtoVarInt::parse(buf, sizeof(buf)); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ProtoVarInt_Parse_FiveByte); + +// --- Varint encoding benchmarks --- + +static void Encode_Varint_Small(benchmark::State &state) { + APIBuffer buffer; + buffer.resize(16); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + writer.encode_varint_raw(42); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_Varint_Small); + +static void Encode_Varint_Large(benchmark::State &state) { + APIBuffer buffer; + buffer.resize(16); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + writer.encode_varint_raw(300); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_Varint_Large); + +static void Encode_Varint_MaxUint32(benchmark::State &state) { + APIBuffer buffer; + buffer.resize(16); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + writer.encode_varint_raw(0xFFFFFFFF); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_Varint_MaxUint32); + +// --- ProtoSize::varint() benchmarks --- + +static void ProtoSize_Varint_Small(benchmark::State &state) { + // Use varying input to prevent constant folding. + // Values 0-127 all take 1 byte but the compiler can't prove that. + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += ProtoSize::varint(static_cast<uint32_t>(i) & 0x7F); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ProtoSize_Varint_Small); + +static void ProtoSize_Varint_Large(benchmark::State &state) { + // Use varying input to prevent constant folding. + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += ProtoSize::varint(0xFFFF0000 | static_cast<uint32_t>(i)); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ProtoSize_Varint_Large); + +} // namespace esphome::api::benchmarks diff --git a/tests/benchmarks/components/api/benchmark.yaml b/tests/benchmarks/components/api/benchmark.yaml new file mode 100644 index 0000000000..bfc24d7440 --- /dev/null +++ b/tests/benchmarks/components/api/benchmark.yaml @@ -0,0 +1,114 @@ +# Components needed for API protobuf benchmarks. +# Merged into the base config before validation so all +# dependencies get proper defaults. +# +# esphome: sub-keys are merged into the base config. +esphome: + areas: + - id: area_1 + name: "Area 1" + - id: area_2 + name: "Area 2" + - id: area_3 + name: "Area 3" + - id: area_4 + name: "Area 4" + - id: area_5 + name: "Area 5" + - id: area_6 + name: "Area 6" + - id: area_7 + name: "Area 7" + - id: area_8 + name: "Area 8" + - id: area_9 + name: "Area 9" + - id: area_10 + name: "Area 10" + - id: area_11 + name: "Area 11" + - id: area_12 + name: "Area 12" + - id: area_13 + name: "Area 13" + - id: area_14 + name: "Area 14" + - id: area_15 + name: "Area 15" + - id: area_16 + name: "Area 16" + - id: area_17 + name: "Area 17" + - id: area_18 + name: "Area 18" + - id: area_19 + name: "Area 19" + - id: area_20 + name: "Area 20" + devices: + - id: device_1 + name: "Device 1" + area_id: area_1 + - id: device_2 + name: "Device 2" + area_id: area_2 + - id: device_3 + name: "Device 3" + area_id: area_3 + - id: device_4 + name: "Device 4" + area_id: area_4 + - id: device_5 + name: "Device 5" + area_id: area_5 + - id: device_6 + name: "Device 6" + area_id: area_6 + - id: device_7 + name: "Device 7" + area_id: area_7 + - id: device_8 + name: "Device 8" + area_id: area_8 + - id: device_9 + name: "Device 9" + area_id: area_9 + - id: device_10 + name: "Device 10" + area_id: area_10 + - id: device_11 + name: "Device 11" + area_id: area_11 + - id: device_12 + name: "Device 12" + area_id: area_12 + - id: device_13 + name: "Device 13" + area_id: area_13 + - id: device_14 + name: "Device 14" + area_id: area_14 + - id: device_15 + name: "Device 15" + area_id: area_15 + - id: device_16 + name: "Device 16" + area_id: area_16 + - id: device_17 + name: "Device 17" + area_id: area_17 + - id: device_18 + name: "Device 18" + area_id: area_18 + - id: device_19 + name: "Device 19" + area_id: area_19 + - id: device_20 + name: "Device 20" + area_id: area_20 + +api: +sensor: +binary_sensor: +light: +switch: diff --git a/tests/benchmarks/components/main.cpp b/tests/benchmarks/components/main.cpp new file mode 100644 index 0000000000..9bc0c31a15 --- /dev/null +++ b/tests/benchmarks/components/main.cpp @@ -0,0 +1,42 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/logger/logger.h" + +/* +This special main.cpp provides the entry point for Google Benchmark. +It replaces the default ESPHome main with a benchmark runner. + +*/ + +// Auto generated code by esphome +// ========== AUTO GENERATED INCLUDE BLOCK BEGIN =========== +// ========== AUTO GENERATED INCLUDE BLOCK END =========== + +void original_setup() { + // Code-generated App initialization (pre_setup, area/device registration, etc.) + + // ========== AUTO GENERATED CODE BEGIN =========== + // =========== AUTO GENERATED CODE END ============ +} + +void setup() { + // Run auto-generated initialization (App.pre_setup, area/device registration, + // looping_components_.init, etc.) so benchmarks that use App work correctly. + original_setup(); + + // Log functions call global_logger->log_vprintf_() without a null check, + // so we must set up a Logger before any test that triggers logging. + static esphome::logger::Logger test_logger(0); + test_logger.set_log_level(ESPHOME_LOG_LEVEL); + test_logger.pre_setup(); + + int argc = 1; + char arg0[] = "benchmark"; + char *argv[] = {arg0, nullptr}; + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + ::benchmark::Shutdown(); + exit(0); +} + +void loop() {} diff --git a/tests/benchmarks/core/bench_application_loop.cpp b/tests/benchmarks/core/bench_application_loop.cpp new file mode 100644 index 0000000000..dde78ae739 --- /dev/null +++ b/tests/benchmarks/core/bench_application_loop.cpp @@ -0,0 +1,22 @@ +#include <benchmark/benchmark.h> + +#include "esphome/core/application.h" + +namespace esphome::benchmarks { + +// Benchmark Application::loop() with no registered components. +// App is initialized by original_setup() in main.cpp (code-generated +// pre_setup, area/device registration, looping_components_.init). +// This measures the baseline overhead of the main loop: scheduler, +// timing, before/after loop tasks, and yield_with_select_. +static void ApplicationLoop_Empty(benchmark::State &state) { + // Set loop interval to 0 so yield_with_select_ returns immediately + // instead of sleeping. This benchmarks the loop overhead, not the sleep. + App.set_loop_interval(0); + for (auto _ : state) { + App.loop(); + } +} +BENCHMARK(ApplicationLoop_Empty); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/core/bench_helpers.cpp b/tests/benchmarks/core/bench_helpers.cpp new file mode 100644 index 0000000000..c6e1e6930e --- /dev/null +++ b/tests/benchmarks/core/bench_helpers.cpp @@ -0,0 +1,41 @@ +#include <benchmark/benchmark.h> + +#include "esphome/core/helpers.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// --- random_float() --- +// Ported from ol.yaml:148 "Random Float Benchmark" + +static void RandomFloat(benchmark::State &state) { + for (auto _ : state) { + float result = 0.0f; + for (int i = 0; i < kInnerIterations; i++) { + result += random_float(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(RandomFloat); + +// --- random_uint32() --- + +static void RandomUint32(benchmark::State &state) { + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += random_uint32(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(RandomUint32); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/core/bench_logger.cpp b/tests/benchmarks/core/bench_logger.cpp new file mode 100644 index 0000000000..b7e9a1c4ea --- /dev/null +++ b/tests/benchmarks/core/bench_logger.cpp @@ -0,0 +1,54 @@ +#include <benchmark/benchmark.h> + +#include "esphome/core/log.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +static const char *const TAG = "bench"; + +// --- Log a message with no format specifiers (fastest path) --- + +static void Logger_NoFormat(benchmark::State &state) { + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ESP_LOGW(TAG, "Something happened"); + } + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Logger_NoFormat); + +// --- Log a message with 3 uint32_t format specifiers --- + +static void Logger_3Uint32(benchmark::State &state) { + uint32_t a = 12345, b = 67890, c = 99999; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ESP_LOGW(TAG, "Values: %" PRIu32 " %" PRIu32 " %" PRIu32, a, b, c); + } + benchmark::DoNotOptimize(a); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Logger_3Uint32); + +// --- Log a message with 3 floats (common for sensor values) --- + +static void Logger_3Float(benchmark::State &state) { + float temp = 23.456f, humidity = 67.89f, pressure = 1013.25f; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ESP_LOGW(TAG, "Sensor: %.2f %.1f %.2f", temp, humidity, pressure); + } + benchmark::DoNotOptimize(temp); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Logger_3Float); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/core/bench_scheduler.cpp b/tests/benchmarks/core/bench_scheduler.cpp new file mode 100644 index 0000000000..764f17ed73 --- /dev/null +++ b/tests/benchmarks/core/bench_scheduler.cpp @@ -0,0 +1,133 @@ +#include <benchmark/benchmark.h> + +#include "esphome/core/scheduler.h" +#include "esphome/core/hal.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// --- Scheduler fast path: no work to do --- + +static void Scheduler_Call_NoWork(benchmark::State &state) { + Scheduler scheduler; + uint32_t now = millis(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + scheduler.call(now); + } + benchmark::DoNotOptimize(now); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_Call_NoWork); + +// --- Scheduler with timers: call() when timers exist but aren't due --- + +static void Scheduler_Call_TimersNotDue(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + // Add some timeouts far in the future + for (int i = 0; i < 10; i++) { + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i), 1000000, []() {}); + } + scheduler.process_to_add(); + + uint32_t now = millis(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + scheduler.call(now); + } + benchmark::DoNotOptimize(now); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_Call_TimersNotDue); + +// --- Scheduler with 5 intervals firing every call --- + +static void Scheduler_Call_5IntervalsFiring(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + int fire_count = 0; + + // Benchmarks the heap-based scheduler dispatch with 5 callbacks firing. + // Uses monotonically increasing fake time so intervals reliably fire every call. + // USE_BENCHMARK ifdef in component.h disables WarnIfComponentBlockingGuard + // (fake now > real millis() would cause underflow in finish()). + // interval=0 would cause an infinite loop (reschedules at same now). + for (int i = 0; i < 5; i++) { + scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i), 1, [&fire_count]() { fire_count++; }); + } + scheduler.process_to_add(); + + uint32_t now = millis() + 100; + + for (auto _ : state) { + scheduler.call(now); + now++; + benchmark::DoNotOptimize(fire_count); + } +} +BENCHMARK(Scheduler_Call_5IntervalsFiring); + +// --- Scheduler: set_timeout registration --- + +static void Scheduler_SetTimeout(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % 5), 1000, []() {}); + } + scheduler.process_to_add(); + benchmark::DoNotOptimize(scheduler); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_SetTimeout); + +// --- Scheduler: set_interval registration --- + +static void Scheduler_SetInterval(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i % 5), 1000, []() {}); + } + scheduler.process_to_add(); + benchmark::DoNotOptimize(scheduler); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_SetInterval); + +// --- Scheduler: defer registration (set_timeout with delay=0) --- + +static void Scheduler_Defer(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + // defer() is Component::defer which calls set_timeout(delay=0). + // Call set_timeout directly since defer() is protected. + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % 5), 0, []() {}); + } + scheduler.process_to_add(); + benchmark::DoNotOptimize(scheduler); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_Defer); + +} // namespace esphome::benchmarks diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 5c81ad374b..29535d1fd3 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -1821,3 +1821,151 @@ def test_component_batching_beta_branch_40_per_batch( all_components.extend(batch_str.split()) assert len(all_components) == 120 assert set(all_components) == set(component_names) + + +# --- should_run_benchmarks tests --- + + +def test_should_run_benchmarks_core_change() -> None: + """Test benchmarks trigger on core C++ file changes.""" + with patch.object( + determine_jobs, "changed_files", return_value=["esphome/core/scheduler.cpp"] + ): + assert determine_jobs.should_run_benchmarks() is True + + +def test_should_run_benchmarks_core_header_change() -> None: + """Test benchmarks trigger on core header changes.""" + with patch.object( + determine_jobs, "changed_files", return_value=["esphome/core/helpers.h"] + ): + assert determine_jobs.should_run_benchmarks() is True + + +def test_should_run_benchmarks_benchmark_infra_change() -> None: + """Test benchmarks trigger on benchmark infrastructure changes.""" + for infra_file in [ + "script/cpp_benchmark.py", + "script/test_helpers.py", + "script/setup_codspeed_lib.py", + ]: + with patch.object(determine_jobs, "changed_files", return_value=[infra_file]): + assert determine_jobs.should_run_benchmarks() is True, ( + f"Expected benchmarks to run for {infra_file}" + ) + + +def test_should_run_benchmarks_benchmark_file_change() -> None: + """Test benchmarks trigger on benchmark file changes.""" + with patch.object( + determine_jobs, + "changed_files", + return_value=["tests/benchmarks/components/api/bench_proto_encode.cpp"], + ): + assert determine_jobs.should_run_benchmarks() is True + + +def test_should_run_benchmarks_core_benchmark_file_change() -> None: + """Test benchmarks trigger on core benchmark file changes.""" + with patch.object( + determine_jobs, + "changed_files", + return_value=["tests/benchmarks/core/bench_scheduler.cpp"], + ): + assert determine_jobs.should_run_benchmarks() is True + + +def test_should_run_benchmarks_benchmarked_component_change(tmp_path: Path) -> None: + """Test benchmarks trigger when a benchmarked component changes.""" + # Create a fake benchmarks directory with an 'api' component + benchmarks_dir = tmp_path / "tests" / "benchmarks" / "components" / "api" + benchmarks_dir.mkdir(parents=True) + (benchmarks_dir / "bench_proto_encode.cpp").write_text("// benchmark") + + with ( + patch.object( + determine_jobs, + "changed_files", + return_value=["esphome/components/api/proto.h"], + ), + patch.object(determine_jobs, "root_path", str(tmp_path)), + patch.object( + determine_jobs, + "BENCHMARKS_COMPONENTS_PATH", + "tests/benchmarks/components", + ), + ): + assert determine_jobs.should_run_benchmarks() is True + + +def test_should_run_benchmarks_non_benchmarked_component_change( + tmp_path: Path, +) -> None: + """Test benchmarks do NOT trigger for non-benchmarked component changes.""" + # Create a fake benchmarks directory with only 'api' + benchmarks_dir = tmp_path / "tests" / "benchmarks" / "components" / "api" + benchmarks_dir.mkdir(parents=True) + (benchmarks_dir / "bench_proto_encode.cpp").write_text("// benchmark") + + with ( + patch.object( + determine_jobs, + "changed_files", + return_value=["esphome/components/sensor/__init__.py"], + ), + patch.object(determine_jobs, "root_path", str(tmp_path)), + patch.object( + determine_jobs, + "BENCHMARKS_COMPONENTS_PATH", + "tests/benchmarks/components", + ), + ): + assert determine_jobs.should_run_benchmarks() is False + + +def test_should_run_benchmarks_no_dependency_expansion(tmp_path: Path) -> None: + """Test benchmarks do NOT expand to dependent components. + + Changing 'sensor' should not trigger 'api' benchmarks even if api + depends on sensor. This is intentional — benchmark runs should be + targeted to directly changed components only. + """ + benchmarks_dir = tmp_path / "tests" / "benchmarks" / "components" / "api" + benchmarks_dir.mkdir(parents=True) + (benchmarks_dir / "bench_proto_encode.cpp").write_text("// benchmark") + + with ( + patch.object( + determine_jobs, + "changed_files", + # sensor is a dependency of api, but benchmarks don't expand + return_value=["esphome/components/sensor/sensor.cpp"], + ), + patch.object(determine_jobs, "root_path", str(tmp_path)), + patch.object( + determine_jobs, + "BENCHMARKS_COMPONENTS_PATH", + "tests/benchmarks/components", + ), + ): + assert determine_jobs.should_run_benchmarks() is False + + +def test_should_run_benchmarks_unrelated_change() -> None: + """Test benchmarks do NOT trigger for unrelated changes.""" + with patch.object(determine_jobs, "changed_files", return_value=["README.md"]): + assert determine_jobs.should_run_benchmarks() is False + + +def test_should_run_benchmarks_no_changes() -> None: + """Test benchmarks do NOT trigger with no changes.""" + with patch.object(determine_jobs, "changed_files", return_value=[]): + assert determine_jobs.should_run_benchmarks() is False + + +def test_should_run_benchmarks_with_branch() -> None: + """Test should_run_benchmarks passes branch to changed_files.""" + with patch.object(determine_jobs, "changed_files") as mock_changed: + mock_changed.return_value = [] + determine_jobs.should_run_benchmarks("release") + mock_changed.assert_called_with("release") From 6b91df8d756686cbcd9e575733402be78f02d929 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:05:16 -1000 Subject: [PATCH 1466/2030] [esp32_ble][esp32_ble_server] Inline is_active/is_running and remove STL bloat (#14875) --- esphome/components/esp32_ble/ble.cpp | 2 -- esphome/components/esp32_ble/ble.h | 2 +- .../components/esp32_ble_server/ble_server.cpp | 16 +++++++--------- esphome/components/esp32_ble_server/ble_server.h | 2 +- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index fee1c546be..317f8fd11b 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -81,8 +81,6 @@ void ESP32BLE::disable() { this->state_ = BLE_COMPONENT_STATE_DISABLE; } -bool ESP32BLE::is_active() { return this->state_ == BLE_COMPONENT_STATE_ACTIVE; } - #ifdef USE_ESP32_BLE_ADVERTISING void ESP32BLE::advertising_start() { this->advertising_init_(); diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 752ddc9d1f..82b2789461 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -135,7 +135,7 @@ class ESP32BLE : public Component { void enable(); void disable(); - bool is_active(); + ESPHOME_ALWAYS_INLINE bool is_active() { return this->state_ == BLE_COMPONENT_STATE_ACTIVE; } void setup() override; void loop() override; void dump_config() override; diff --git a/esphome/components/esp32_ble_server/ble_server.cpp b/esphome/components/esp32_ble_server/ble_server.cpp index ecc53e197f..be0691dc06 100644 --- a/esphome/components/esp32_ble_server/ble_server.cpp +++ b/esphome/components/esp32_ble_server/ble_server.cpp @@ -7,7 +7,6 @@ #ifdef USE_ESP32 -#include <algorithm> #include <nvs_flash.h> #include <freertos/FreeRTOSConfig.h> #include <esp_bt_main.h> @@ -39,16 +38,17 @@ void BLEServer::loop() { case RUNNING: { // Start all services that are pending to start if (!this->services_to_start_.empty()) { - for (auto &service : this->services_to_start_) { + size_t write_idx = 0; + for (auto *service : this->services_to_start_) { if (service->is_created()) { service->start(); // Needs to be called once per characteristic in the service } + // Remove services that have started or are starting + if (!service->is_starting() && !service->is_running()) { + this->services_to_start_[write_idx++] = service; + } } - // Remove services that have been started - this->services_to_start_.erase( - std::remove_if(this->services_to_start_.begin(), this->services_to_start_.end(), - [](BLEService *service) { return service->is_starting() || service->is_running(); }), - this->services_to_start_.end()); + this->services_to_start_.erase(this->services_to_start_.begin() + write_idx, this->services_to_start_.end()); } break; } @@ -91,8 +91,6 @@ void BLEServer::loop() { } } -bool BLEServer::is_running() { return this->parent_->is_active() && this->state_ == RUNNING; } - bool BLEServer::can_proceed() { return this->is_running() || !this->parent_->is_active(); } void BLEServer::restart_advertising_() { diff --git a/esphome/components/esp32_ble_server/ble_server.h b/esphome/components/esp32_ble_server/ble_server.h index ff7e0044e4..1b419d2ee4 100644 --- a/esphome/components/esp32_ble_server/ble_server.h +++ b/esphome/components/esp32_ble_server/ble_server.h @@ -32,7 +32,7 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv float get_setup_priority() const override; bool can_proceed() override; - bool is_running(); + ESPHOME_ALWAYS_INLINE bool is_running() { return this->parent_->is_active() && this->state_ == RUNNING; } void set_manufacturer_data(const std::vector<uint8_t> &data) { this->manufacturer_data_ = data; From 77b7201eb88434531cba130c2772c9d40623b833 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:08:45 -1000 Subject: [PATCH 1467/2030] [ci] Run CodSpeed benchmarks on push to dev for baseline (#14899) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1926ad5bf4..0a03579abc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -316,7 +316,9 @@ jobs: needs: - common - determine-jobs - if: github.event_name == 'pull_request' && needs.determine-jobs.outputs.benchmarks == 'true' + if: >- + (github.event_name == 'push' && github.ref_name == 'dev') || + (github.event_name == 'pull_request' && needs.determine-jobs.outputs.benchmarks == 'true') steps: - name: Check out code from GitHub uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From f3409acfa85a8bd7f7cda4d1a76a6deb07f4a0c0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:08:58 -1000 Subject: [PATCH 1468/2030] [core] Document EventPool sizing requirement with LockFreeQueue (#14897) --- esphome/core/event_pool.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/core/event_pool.h b/esphome/core/event_pool.h index 99541d4a17..ee8e81225a 100644 --- a/esphome/core/event_pool.h +++ b/esphome/core/event_pool.h @@ -13,6 +13,14 @@ namespace esphome { // Events are allocated on first use and reused thereafter, growing to peak usage // @tparam T The type of objects managed by the pool (must have a release() method) // @tparam SIZE The maximum number of objects in the pool (1-255, limited by uint8_t) +// +// SIZING: When paired with a LockFreeQueue<T, Q_SIZE>, the pool SIZE should be +// Q_SIZE - 1 (the queue's actual capacity, since the ring buffer reserves one slot). +// This ensures allocate() returns nullptr before push() can fail, which: +// - Prevents the allocate-succeeds-but-push-fails mismatch that permanently +// leaks a pool slot (the element is never returned to the pool) +// - Avoids needing release() on the producer path after a failed push(), +// preserving the SPSC contract on the internal free list template<class T, uint8_t SIZE> class EventPool { public: EventPool() : total_created_(0) {} From ece235218fe77108170d640b7320337d13c2260a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:27:46 -1000 Subject: [PATCH 1469/2030] [debug][bme680_bsec] Use fnv1_hash_extend to avoid temporary string allocations (#14876) --- esphome/components/bme680_bsec/bme680_bsec.cpp | 2 +- esphome/components/debug/debug_esp32.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/esphome/components/bme680_bsec/bme680_bsec.cpp b/esphome/components/bme680_bsec/bme680_bsec.cpp index 75efb6835a..bb0417b823 100644 --- a/esphome/components/bme680_bsec/bme680_bsec.cpp +++ b/esphome/components/bme680_bsec/bme680_bsec.cpp @@ -521,7 +521,7 @@ int BME680BSECComponent::reinit_bsec_lib_() { } void BME680BSECComponent::load_state_() { - uint32_t hash = fnv1_hash("bme680_bsec_state_" + this->device_id_); + uint32_t hash = fnv1_hash_extend(fnv1_hash("bme680_bsec_state_"), this->device_id_); this->bsec_state_ = global_preferences->make_preference<uint8_t[BSEC_MAX_STATE_BLOB_SIZE]>(hash, true); if (!this->bsec_state_.load(&this->bsec_state_data_)) { diff --git a/esphome/components/debug/debug_esp32.cpp b/esphome/components/debug/debug_esp32.cpp index aa379599c6..2e04090749 100644 --- a/esphome/components/debug/debug_esp32.cpp +++ b/esphome/components/debug/debug_esp32.cpp @@ -49,7 +49,8 @@ static const size_t REBOOT_MAX_LEN = 24; void DebugComponent::on_shutdown() { auto *component = App.get_current_component(); char buffer[REBOOT_MAX_LEN]{}; - auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name())); + auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, + fnv1_hash_extend(fnv1_hash(REBOOT_KEY), App.get_name().c_str())); if (component != nullptr) { strncpy(buffer, LOG_STR_ARG(component->get_component_log_str()), REBOOT_MAX_LEN - 1); buffer[REBOOT_MAX_LEN - 1] = '\0'; @@ -66,7 +67,8 @@ const char *DebugComponent::get_reset_reason_(std::span<char, RESET_REASON_BUFFE unsigned reason = esp_reset_reason(); if (reason < sizeof(RESET_REASONS) / sizeof(RESET_REASONS[0])) { if (reason == ESP_RST_SW) { - auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, fnv1_hash(REBOOT_KEY + App.get_name())); + auto pref = global_preferences->make_preference(REBOOT_MAX_LEN, + fnv1_hash_extend(fnv1_hash(REBOOT_KEY), App.get_name().c_str())); char reboot_source[REBOOT_MAX_LEN]{}; if (pref.load(&reboot_source)) { reboot_source[REBOOT_MAX_LEN - 1] = '\0'; From 83484a8828f2bb4936e41d069700c3b12cf2fa49 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:38:41 -1000 Subject: [PATCH 1470/2030] [esp32_ble_server] Remove vestigial semaphore from BLECharacteristic (#14900) --- .../components/esp32_ble_server/ble_characteristic.cpp | 10 +--------- .../components/esp32_ble_server/ble_characteristic.h | 4 ---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index 1806354712..aa82b773ba 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -16,13 +16,9 @@ BLECharacteristic::~BLECharacteristic() { for (auto *descriptor : this->descriptors_) { delete descriptor; // NOLINT(cppcoreguidelines-owning-memory) } - vSemaphoreDelete(this->set_value_lock_); } BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) : uuid_(uuid) { - this->set_value_lock_ = xSemaphoreCreateBinary(); - xSemaphoreGive(this->set_value_lock_); - this->properties_ = (esp_gatt_char_prop_t) 0; this->set_broadcast_property((properties & PROPERTY_BROADCAST) != 0); @@ -35,11 +31,7 @@ BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) void BLECharacteristic::set_value(ByteBuffer buffer) { this->set_value(buffer.get_data()); } -void BLECharacteristic::set_value(std::vector<uint8_t> &&buffer) { - xSemaphoreTake(this->set_value_lock_, 0L); - this->value_ = std::move(buffer); - xSemaphoreGive(this->set_value_lock_); -} +void BLECharacteristic::set_value(std::vector<uint8_t> &&buffer) { this->value_ = std::move(buffer); } void BLECharacteristic::set_value(std::initializer_list<uint8_t> data) { this->set_value(std::vector<uint8_t>(data)); // Delegate to move overload diff --git a/esphome/components/esp32_ble_server/ble_characteristic.h b/esphome/components/esp32_ble_server/ble_characteristic.h index 72897d1dfb..062052cdf8 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.h +++ b/esphome/components/esp32_ble_server/ble_characteristic.h @@ -16,8 +16,6 @@ #include <esp_gattc_api.h> #include <esp_gatts_api.h> #include <esp_bt_defs.h> -#include <freertos/FreeRTOS.h> -#include <freertos/semphr.h> namespace esphome { namespace esp32_ble_server { @@ -84,8 +82,6 @@ class BLECharacteristic { uint16_t value_read_offset_{0}; std::vector<uint8_t> value_; - SemaphoreHandle_t set_value_lock_; - std::vector<BLEDescriptor *> descriptors_; struct ClientNotificationEntry { From 53bfb02a21487d70b4070a75a2709fcad2e3ff58 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:46:26 -0400 Subject: [PATCH 1471/2030] [sensor][ee895][hdc2010] Fix misc bugs found during component scan (#14890) --- esphome/components/ee895/ee895.cpp | 15 ++--- esphome/components/hdc2010/hdc2010.cpp | 76 +++++++++++--------------- esphome/components/sensor/__init__.py | 4 +- 3 files changed, 40 insertions(+), 55 deletions(-) diff --git a/esphome/components/ee895/ee895.cpp b/esphome/components/ee895/ee895.cpp index 22f28be9bc..93e5d4203b 100644 --- a/esphome/components/ee895/ee895.cpp +++ b/esphome/components/ee895/ee895.cpp @@ -24,7 +24,7 @@ void EE895Component::setup() { this->read(serial_number, 20); crc16_check = (serial_number[19] << 8) + serial_number[18]; - if (crc16_check != calc_crc16_(serial_number, 19)) { + if (crc16_check != calc_crc16_(serial_number, 18)) { this->error_code_ = CRC_CHECK_FAILED; this->mark_failed(); return; @@ -84,7 +84,7 @@ void EE895Component::write_command_(uint16_t addr, uint16_t reg_cnt) { address[2] = addr & 0xFF; address[3] = (reg_cnt >> 8) & 0xFF; address[4] = reg_cnt & 0xFF; - crc16 = calc_crc16_(address, 6); + crc16 = calc_crc16_(address, 5); address[5] = crc16 & 0xFF; address[6] = (crc16 >> 8) & 0xFF; this->write(address, 7); @@ -95,7 +95,7 @@ float EE895Component::read_float_() { uint8_t i2c_response[8]; this->read(i2c_response, 8); crc16_check = (i2c_response[7] << 8) + i2c_response[6]; - if (crc16_check != calc_crc16_(i2c_response, 7)) { + if (crc16_check != calc_crc16_(i2c_response, 6)) { this->error_code_ = CRC_CHECK_FAILED; this->status_set_warning(); return 0; @@ -107,12 +107,9 @@ float EE895Component::read_float_() { } uint16_t EE895Component::calc_crc16_(const uint8_t buf[], uint8_t len) { - uint8_t crc_check_buf[22]; - for (int i = 0; i < len; i++) { - crc_check_buf[i + 1] = buf[i]; - } - crc_check_buf[0] = this->address_; - return crc16(crc_check_buf, len); + uint8_t addr = this->address_; + uint16_t crc = crc16(&addr, 1); + return crc16(buf, len, crc); } } // namespace ee895 } // namespace esphome diff --git a/esphome/components/hdc2010/hdc2010.cpp b/esphome/components/hdc2010/hdc2010.cpp index c53fdb3f5b..0334b30eec 100644 --- a/esphome/components/hdc2010/hdc2010.cpp +++ b/esphome/components/hdc2010/hdc2010.cpp @@ -7,50 +7,36 @@ namespace hdc2010 { static const char *const TAG = "hdc2010"; -static const uint8_t HDC2010_ADDRESS = 0x40; // 0b1000000 or 0b1000001 from datasheet -static const uint8_t HDC2010_CMD_CONFIGURATION_MEASUREMENT = 0x8F; -static const uint8_t HDC2010_CMD_START_MEASUREMENT = 0xF9; -static const uint8_t HDC2010_CMD_TEMPERATURE_LOW = 0x00; -static const uint8_t HDC2010_CMD_TEMPERATURE_HIGH = 0x01; -static const uint8_t HDC2010_CMD_HUMIDITY_LOW = 0x02; -static const uint8_t HDC2010_CMD_HUMIDITY_HIGH = 0x03; -static const uint8_t CONFIG = 0x0E; -static const uint8_t MEASUREMENT_CONFIG = 0x0F; +// Register addresses +static constexpr uint8_t REG_TEMPERATURE_LOW = 0x00; +static constexpr uint8_t REG_TEMPERATURE_HIGH = 0x01; +static constexpr uint8_t REG_HUMIDITY_LOW = 0x02; +static constexpr uint8_t REG_HUMIDITY_HIGH = 0x03; +static constexpr uint8_t REG_RESET_DRDY_INT_CONF = 0x0E; +static constexpr uint8_t REG_MEASUREMENT_CONF = 0x0F; + +// REG_MEASUREMENT_CONF (0x0F) bit masks +static constexpr uint8_t MEAS_TRIG = 0x01; // Bit 0: measurement trigger +static constexpr uint8_t MEAS_CONF_MASK = 0x06; // Bits 2:1: measurement mode +static constexpr uint8_t HRES_MASK = 0x30; // Bits 5:4: humidity resolution +static constexpr uint8_t TRES_MASK = 0xC0; // Bits 7:6: temperature resolution + +// REG_RESET_DRDY_INT_CONF (0x0E) bit masks +static constexpr uint8_t AMM_MASK = 0x70; // Bits 6:4: auto measurement mode void HDC2010Component::setup() { ESP_LOGCONFIG(TAG, "Running setup"); - const uint8_t data[2] = { - 0b00000000, // resolution 14bit for both humidity and temperature - 0b00000000 // reserved - }; - - if (!this->write_bytes(HDC2010_CMD_CONFIGURATION_MEASUREMENT, data, 2)) { - ESP_LOGW(TAG, "Initial config instruction error"); - this->status_set_warning(); - return; - } - - // Set measurement mode to temperature and humidity + // Set 14-bit resolution for both sensors and measurement mode to temp + humidity uint8_t config_contents; - this->read_register(MEASUREMENT_CONFIG, &config_contents, 1); - config_contents = (config_contents & 0xF9); // Always set to TEMP_AND_HUMID mode - this->write_bytes(MEASUREMENT_CONFIG, &config_contents, 1); + this->read_register(REG_MEASUREMENT_CONF, &config_contents, 1); + config_contents &= ~(TRES_MASK | HRES_MASK | MEAS_CONF_MASK); // 14-bit temp, 14-bit humidity, temp+humidity mode + this->write_bytes(REG_MEASUREMENT_CONF, &config_contents, 1); - // Set rate to manual - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0x8F; - this->write_bytes(CONFIG, &config_contents, 1); - - // Set temperature resolution to 14bit - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0x3F; - this->write_bytes(CONFIG, &config_contents, 1); - - // Set humidity resolution to 14bit - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0xCF; - this->write_bytes(CONFIG, &config_contents, 1); + // Set auto measurement rate to manual (on-demand via MEAS_TRIG) + this->read_register(REG_RESET_DRDY_INT_CONF, &config_contents, 1); + config_contents &= ~AMM_MASK; + this->write_bytes(REG_RESET_DRDY_INT_CONF, &config_contents, 1); } void HDC2010Component::dump_config() { @@ -67,9 +53,9 @@ void HDC2010Component::dump_config() { void HDC2010Component::update() { // Trigger measurement uint8_t config_contents; - this->read_register(CONFIG, &config_contents, 1); - config_contents |= 0x01; - this->write_bytes(MEASUREMENT_CONFIG, &config_contents, 1); + this->read_register(REG_MEASUREMENT_CONF, &config_contents, 1); + config_contents |= MEAS_TRIG; + this->write_bytes(REG_MEASUREMENT_CONF, &config_contents, 1); // 1ms delay after triggering the sample set_timeout(1, [this]() { @@ -90,8 +76,8 @@ void HDC2010Component::update() { float HDC2010Component::read_temp() { uint8_t byte[2]; - this->read_register(HDC2010_CMD_TEMPERATURE_LOW, &byte[0], 1); - this->read_register(HDC2010_CMD_TEMPERATURE_HIGH, &byte[1], 1); + this->read_register(REG_TEMPERATURE_LOW, &byte[0], 1); + this->read_register(REG_TEMPERATURE_HIGH, &byte[1], 1); uint16_t temp = encode_uint16(byte[1], byte[0]); return (float) temp * 0.0025177f - 40.0f; @@ -100,8 +86,8 @@ float HDC2010Component::read_temp() { float HDC2010Component::read_humidity() { uint8_t byte[2]; - this->read_register(HDC2010_CMD_HUMIDITY_LOW, &byte[0], 1); - this->read_register(HDC2010_CMD_HUMIDITY_HIGH, &byte[1], 1); + this->read_register(REG_HUMIDITY_LOW, &byte[0], 1); + this->read_register(REG_HUMIDITY_HIGH, &byte[1], 1); uint16_t humidity = encode_uint16(byte[1], byte[0]); return (float) humidity * 0.001525879f; diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 64d4dc4177..9f3c1484b0 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -406,7 +406,9 @@ QUANTILE_SCHEMA = cv.All( cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), - cv.Optional(CONF_QUANTILE, default=0.9): cv.zero_to_one_float, + cv.Optional(CONF_QUANTILE, default=0.9): cv.float_range( + min=0, min_included=False, max=1 + ), } ), validate_send_first_at, From 62f9bc79c4e4ee929e158cab64087c7bcd289072 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:48:21 -1000 Subject: [PATCH 1472/2030] [ci] Add CodSpeed badge to README (#14901) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b8ce8d091d..16497ee0be 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ESPHome [![Discord Chat](https://img.shields.io/discord/429907082951524364.svg)](https://discord.gg/KhAMKrd) [![GitHub release](https://img.shields.io/github/release/esphome/esphome.svg)](https://GitHub.com/esphome/esphome/releases/) +# ESPHome [![Discord Chat](https://img.shields.io/discord/429907082951524364.svg)](https://discord.gg/KhAMKrd) [![GitHub release](https://img.shields.io/github/release/esphome/esphome.svg)](https://GitHub.com/esphome/esphome/releases/) [![CodSpeed](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/esphome/esphome) <a href="https://esphome.io/"> <picture> From 342020e1d3c53378febedc38819674b10049ea82 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:49:24 -1000 Subject: [PATCH 1473/2030] [mqtt] Fix data race on inbound event queue (#14891) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/mqtt/mqtt_backend_esp32.cpp | 34 ++++++--- esphome/components/mqtt/mqtt_backend_esp32.h | 69 +++++++++++-------- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index 5642fd5f7b..ab067c4418 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -82,10 +82,16 @@ bool MQTTBackendESP32::initialize_() { void MQTTBackendESP32::loop() { // process new events // handle only 1 message per loop iteration - if (!mqtt_events_.empty()) { - auto &event = mqtt_events_.front(); - mqtt_event_handler_(event); - mqtt_events_.pop(); + Event *event = this->mqtt_event_queue_.pop(); + if (event != nullptr) { + this->mqtt_event_handler_(*event); + this->mqtt_event_pool_.release(event); + } + + // Log dropped inbound events (check is cheap - single atomic load in common case) + uint16_t inbound_dropped = this->mqtt_event_queue_.get_and_reset_dropped_count(); + if (inbound_dropped > 0) { + ESP_LOGW(TAG, "Dropped %u inbound MQTT events", inbound_dropped); } #if defined(USE_MQTT_IDF_ENQUEUE) @@ -183,10 +189,18 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) { void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { MQTTBackendESP32 *instance = static_cast<MQTTBackendESP32 *>(handler_args); - // queue event to decouple processing + // queue event to decouple processing from ESP-IDF MQTT task to main loop if (instance) { - auto event = *static_cast<esp_mqtt_event_t *>(event_data); - instance->mqtt_events_.emplace(event); + auto *event = instance->mqtt_event_pool_.allocate(); + if (event == nullptr) { + // Pool exhausted, drop event (counted via queue's dropped counter) + instance->mqtt_event_queue_.increment_dropped_count(); + return; + } + event->populate(*static_cast<esp_mqtt_event_t *>(event_data)); + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + instance->mqtt_event_queue_.push(event); // Wake main loop immediately to process MQTT event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) @@ -226,14 +240,14 @@ void MQTTBackendESP32::esphome_mqtt_task(void *params) { break; } } - this_mqtt->mqtt_event_pool_.release(elem); + this_mqtt->mqtt_outbound_pool_.release(elem); } } } bool MQTTBackendESP32::enqueue_(MqttQueueTypeT type, const char *topic, int qos, bool retain, const char *payload, size_t len) { - auto *elem = this->mqtt_event_pool_.allocate(); + auto *elem = this->mqtt_outbound_pool_.allocate(); if (!elem) { // Queue is full - increment counter but don't log immediately. @@ -253,7 +267,7 @@ bool MQTTBackendESP32::enqueue_(MqttQueueTypeT type, const char *topic, int qos, // Use the helper to allocate and copy data if (!elem->set_data(topic, payload, len)) { // Allocation failed, return elem to pool - this->mqtt_event_pool_.release(elem); + this->mqtt_outbound_pool_.release(elem); // Increment counter without logging to avoid cascade effect during memory pressure this->mqtt_queue_.increment_dropped_count(); return false; diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index 5c4dc413bd..58d1b29b32 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -5,7 +5,6 @@ #ifdef USE_ESP32 #include <string> -#include <queue> #include <cstring> #include <mqtt_client.h> #include <freertos/FreeRTOS.h> @@ -18,32 +17,39 @@ namespace esphome::mqtt { struct Event { - esp_mqtt_event_id_t event_id; + esp_mqtt_event_id_t event_id{}; std::vector<char> data; - int total_data_len; - int current_data_offset; + int total_data_len{0}; + int current_data_offset{0}; std::string topic; - int msg_id; - bool retain; - int qos; - bool dup; - bool session_present; - esp_mqtt_error_codes_t error_handle; + int msg_id{0}; + bool retain{false}; + int qos{0}; + bool dup{false}; + bool session_present{false}; + esp_mqtt_error_codes_t error_handle{}; - // Construct from esp_mqtt_event_t - // Any pointer values that are unsafe to keep are converted to safe copies - Event(const esp_mqtt_event_t &event) - : event_id(event.event_id), - data(event.data, event.data + event.data_len), - total_data_len(event.total_data_len), - current_data_offset(event.current_data_offset), - topic(event.topic, event.topic_len), - msg_id(event.msg_id), - retain(event.retain), - qos(event.qos), - dup(event.dup), - session_present(event.session_present), - error_handle(*event.error_handle) {} + // Populate from esp_mqtt_event_t + // Copies pointer-based data to owned storage for safe cross-thread transfer + void populate(const esp_mqtt_event_t &event) { + this->event_id = event.event_id; + this->data.assign(event.data, event.data + event.data_len); + this->total_data_len = event.total_data_len; + this->current_data_offset = event.current_data_offset; + this->topic.assign(event.topic, event.topic_len); + this->msg_id = event.msg_id; + this->retain = event.retain; + this->qos = event.qos; + this->dup = event.dup; + this->session_present = event.session_present; + this->error_handle = *event.error_handle; + } + + // Release owned resources for pool reuse (keeps allocated capacity for efficiency) + void release() { + this->data.clear(); + this->topic.clear(); + } }; enum MqttQueueTypeT : uint8_t { @@ -118,7 +124,8 @@ class MQTTBackendESP32 final : public MQTTBackend { static constexpr size_t TASK_STACK_SIZE = 3072; static constexpr size_t TASK_STACK_SIZE_TLS = 4096; // Larger stack for TLS operations static constexpr ssize_t TASK_PRIORITY = 5; - static constexpr uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 + static constexpr uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 + static constexpr uint8_t MQTT_EVENT_QUEUE_LENGTH = 32; // Inbound events from broker void set_keep_alive(uint16_t keep_alive) final { this->keep_alive_ = keep_alive; } void set_client_id(const char *client_id) final { this->client_id_ = client_id; } @@ -251,7 +258,8 @@ class MQTTBackendESP32 final : public MQTTBackend { bool skip_cert_cn_check_{false}; #if defined(USE_MQTT_IDF_ENQUEUE) static void esphome_mqtt_task(void *params); - EventPool<struct QueueElement, MQTT_QUEUE_LENGTH> mqtt_event_pool_; + // Pool sized to queue capacity (SIZE-1) — see mqtt_event_pool_ comment. + EventPool<struct QueueElement, MQTT_QUEUE_LENGTH - 1> mqtt_outbound_pool_; NotifyingLockFreeQueue<struct QueueElement, MQTT_QUEUE_LENGTH> mqtt_queue_; TaskHandle_t task_handle_{nullptr}; bool enqueue_(MqttQueueTypeT type, const char *topic, int qos = 0, bool retain = false, const char *payload = NULL, @@ -266,7 +274,14 @@ class MQTTBackendESP32 final : public MQTTBackend { CallbackManager<on_message_callback_t> on_message_; CallbackManager<on_publish_user_callback_t> on_publish_; std::string cached_topic_; - std::queue<Event> mqtt_events_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements (one slot distinguishes full from empty). + // This guarantees allocate() returns nullptr before push() can fail, which: + // 1. Prevents leaking a pool slot (the Nth allocate succeeds but push fails) + // 2. Avoids needing release() on the producer path after a failed push(), + // preserving the SPSC contract on the pool's internal free list + EventPool<Event, MQTT_EVENT_QUEUE_LENGTH - 1> mqtt_event_pool_; + LockFreeQueue<Event, MQTT_EVENT_QUEUE_LENGTH> mqtt_event_queue_; #if defined(USE_MQTT_IDF_ENQUEUE) uint32_t last_dropped_log_time_{0}; From 0c5f055d45a333733460d5fe10877cefeb1a71ed Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Wed, 18 Mar 2026 01:16:01 +0100 Subject: [PATCH 1474/2030] [core] cpp tests: Allow customizing code generation during tests (#14681) Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/core/__init__.py | 6 - esphome/loader.py | 15 +- script/{test_helpers.py => build_helpers.py} | 128 ++++++--- script/cpp_benchmark.py | 18 +- script/cpp_unit_test.py | 13 +- script/determine-jobs.py | 4 +- script/helpers.py | 5 +- tests/benchmarks/components/core/__init__.py | 7 + tests/benchmarks/components/host/__init__.py | 7 + tests/benchmarks/components/json/__init__.py | 7 + .../benchmarks/components/logger/__init__.py | 7 + tests/benchmarks/components/time/__init__.py | 9 + tests/components/README.md | 60 +++- tests/components/core/__init__.py | 8 + tests/components/host/__init__.py | 7 + tests/components/logger/__init__.py | 7 + tests/components/time/__init__.py | 9 + tests/script/test_determine_jobs.py | 2 +- tests/script/test_helpers.py | 22 -- tests/script/test_test_helpers.py | 260 ++++++++++++++++++ tests/testing_helpers.py | 63 +++++ tests/unit_tests/test_loader.py | 99 ++++++- 22 files changed, 667 insertions(+), 96 deletions(-) rename script/{test_helpers.py => build_helpers.py} (78%) create mode 100644 tests/benchmarks/components/core/__init__.py create mode 100644 tests/benchmarks/components/host/__init__.py create mode 100644 tests/benchmarks/components/json/__init__.py create mode 100644 tests/benchmarks/components/logger/__init__.py create mode 100644 tests/benchmarks/components/time/__init__.py create mode 100644 tests/components/core/__init__.py create mode 100644 tests/components/host/__init__.py create mode 100644 tests/components/logger/__init__.py create mode 100644 tests/components/time/__init__.py create mode 100644 tests/script/test_test_helpers.py create mode 100644 tests/testing_helpers.py diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index a86478aca1..009fef2f86 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -615,10 +615,6 @@ class EsphomeCore: self.address_cache: AddressCache | None = None # Cached config hash (computed lazily) self._config_hash: int | None = None - # True if compiling for C++ unit tests - self.cpp_testing = False - # Allowlist of components whose to_code should run during C++ testing - self.cpp_testing_codegen: set[str] = set() def reset(self): from esphome.pins import PIN_SCHEMA_REGISTRY @@ -648,8 +644,6 @@ class EsphomeCore: self.current_component = None self.address_cache = None self._config_hash = None - self.cpp_testing = False - self.cpp_testing_codegen = set() PIN_SCHEMA_REGISTRY.reset() @contextmanager diff --git a/esphome/loader.py b/esphome/loader.py index 5771e07473..68664aaa26 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -71,11 +71,6 @@ class ComponentManifest: @property def to_code(self) -> Callable[[Any], None] | None: - if CORE.cpp_testing: - # During C++ testing, only run to_code for allowlisted components - name = self.module.__package__.rsplit(".", 1)[-1] - if name not in CORE.cpp_testing_codegen: - return None return getattr(self.module, "to_code", None) @property @@ -243,3 +238,13 @@ def get_platform(domain: str, platform: str) -> ComponentManifest | None: _COMPONENT_CACHE: dict[str, ComponentManifest] = {} CORE_COMPONENTS_PATH = (Path(__file__).parent / "components").resolve() _COMPONENT_CACHE["esphome"] = ComponentManifest(esphome.core.config) + + +def _replace_component_manifest(domain: str, manifest: ComponentManifest) -> None: + """Replace the cached manifest for a component. + + This is an intentionally-supported hook for the C++ test infrastructure + to install ``ComponentManifestOverride`` wrappers. Normal application + code should never call this. + """ + _COMPONENT_CACHE[domain] = manifest diff --git a/script/test_helpers.py b/script/build_helpers.py similarity index 78% rename from script/test_helpers.py rename to script/build_helpers.py index e872bbc516..1cfae51fca 100644 --- a/script/test_helpers.py +++ b/script/build_helpers.py @@ -2,21 +2,29 @@ from __future__ import annotations +from collections.abc import Callable import hashlib +import importlib.util import os from pathlib import Path import subprocess import sys -from helpers import get_all_dependencies +from helpers import get_all_dependencies, root_path as _root_path import yaml +# Ensure the repo root is on sys.path so that ``tests.testing_helpers`` and +# override ``__init__.py`` modules can ``from tests.testing_helpers import ...``. +if _root_path not in sys.path: + sys.path.insert(0, _root_path) + from esphome.__main__ import command_compile, parse_args from esphome.config import validate_config from esphome.const import CONF_PLATFORM from esphome.core import CORE -from esphome.loader import get_component +from esphome.loader import get_component, get_platform from esphome.platformio_api import get_idedata +from tests.testing_helpers import ComponentManifestOverride, set_testing_manifest # This must coincide with the version in /platformio.ini PLATFORMIO_GOOGLE_TEST_LIB = "google/googletest@^1.15.2" @@ -32,19 +40,6 @@ ESPHOME_KEY = "esphome" HOST_KEY = "host" LOGGER_KEY = "logger" -# Base config keys that are always present and must not be fully overridden -# by component benchmark.yaml files. esphome: allows sub-key merging. -BASE_CONFIG_KEYS = frozenset({ESPHOME_KEY, HOST_KEY, LOGGER_KEY}) - -# Shared build flag — enables timezone code paths for testing/benchmarking. -USE_TIME_TIMEZONE_FLAG = "-DUSE_TIME_TIMEZONE" - -# Components whose to_code should always run during C++ test/benchmark builds. -# These are the minimal infrastructure components needed for host compilation. -# Note: "core" is the esphome core config module (esphome/core/config.py), -# which registers under package name "core" not "esphome". -BASE_CODEGEN_COMPONENTS = {"core", "host", "logger"} - # Exit codes EXIT_OK = 0 EXIT_SKIPPED = 1 @@ -110,6 +105,8 @@ def get_platform_components(components: list[str], tests_dir: Path) -> list[str] if not domain_dir.is_dir(): continue domain = domain_dir.name + if domain.startswith("__"): + continue domain_module = get_component(domain) if domain_module is None or not domain_module.is_platform_component: raise ValueError( @@ -130,7 +127,8 @@ def load_component_yaml_configs(components: list[str], tests_dir: Path) -> dict: The ``esphome:`` key is special: its sub-keys are merged into the existing esphome config (e.g. to add ``areas:`` or ``devices:``). - Other base config keys (``host:``, ``logger:``) are not overridable. + Keys already present in the base config (e.g. ``host:``, ``logger:``) + are protected by ``setdefault`` in the caller. Args: components: List of component directory names @@ -139,11 +137,6 @@ def load_component_yaml_configs(components: list[str], tests_dir: Path) -> dict: Returns: Merged dict of component configs to add to the base config """ - # Note: components are processed in sorted order. For conflicting keys - # (e.g. two benchmark.yaml files both declaring sensor:), the first - # component alphabetically wins via setdefault(). This is fine for now - # with a single benchmark component (api) but would need a real merge - # strategy if multiple components declare overlapping configs. merged: dict = {} for component in components: yaml_path = tests_dir / component / BENCHMARK_YAML_FILENAME @@ -153,9 +146,6 @@ def load_component_yaml_configs(components: list[str], tests_dir: Path) -> dict: component_config = yaml.safe_load(f) if component_config and isinstance(component_config, dict): for key, value in component_config.items(): - if key in BASE_CONFIG_KEYS - {ESPHOME_KEY}: - # host: and logger: are not overridable - continue if key == ESPHOME_KEY and isinstance(value, dict): # Merge esphome sub-keys rather than replacing esphome_extra = merged.setdefault(ESPHOME_KEY, {}) @@ -198,11 +188,78 @@ def create_host_config( } +def _wrap_manifest( + comp_name: str, +) -> ComponentManifestOverride | None: + """Wrap a component manifest in a ComponentManifestOverride with to_code suppressed. + + If the manifest is already wrapped or not found, returns None. + Otherwise returns the newly created override after installing it. + """ + if "." in comp_name: + domain, component = comp_name.split(".", maxsplit=1) + manifest = get_platform(domain, component) + cache_key = f"{component}.{domain}" + else: + manifest = get_component(comp_name) + cache_key = comp_name + + if manifest is None or isinstance(manifest, ComponentManifestOverride): + return None + + override = ComponentManifestOverride(manifest) + override.to_code = None # suppress by default + set_testing_manifest(cache_key, override) + return override + + +def load_test_manifest_overrides( + components: list[str], + tests_dir: Path, +) -> None: + """Apply per-component manifest overrides from test ``__init__.py`` files. + + For every component, wraps its manifest and suppresses ``to_code``. + If the component's test directory contains an ``__init__.py`` that + defines ``override_manifest(manifest)``, it is called to customise + the override (e.g. ``manifest.enable_codegen()``). + """ + for comp_name in components: + override = _wrap_manifest(comp_name) + if override is None: + continue + + if "." in comp_name: + domain, component = comp_name.split(".", maxsplit=1) + cache_key = f"{component}.{domain}" + test_init = tests_dir / component / domain / "__init__.py" + else: + cache_key = comp_name + test_init = tests_dir / comp_name / "__init__.py" + + if not test_init.is_file(): + continue + spec = importlib.util.spec_from_file_location( + f"_test_manifest_override.{cache_key}", test_init + ) + if spec is None or spec.loader is None: + continue + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + override_fn = getattr(mod, "override_manifest", None) + if override_fn is not None: + override_fn(override) + + +# Type alias for manifest override loaders +ManifestOverrideLoader = Callable[[list[str]], None] + + def compile_and_get_binary( config: dict, components: list[str], - codegen_components: set[str], tests_dir: Path, + manifest_override_loader: ManifestOverrideLoader, label: str = "build", ) -> tuple[int, str | None]: """Compile an ESPHome configuration and return the binary path. @@ -210,8 +267,8 @@ def compile_and_get_binary( Args: config: ESPHome configuration dict (already created via create_host_config) components: List of components to include in the build - codegen_components: Set of component names whose to_code should run tests_dir: Base directory for test files (used as config_path base) + manifest_override_loader: Callback to apply manifest overrides for components label: Label for log messages (e.g. "unit tests", "benchmarks") Returns: @@ -238,18 +295,21 @@ def compile_and_get_binary( else: config.setdefault(key, value) + # Apply manifest overrides before dependency resolution so that any + # dependency additions made by override_manifest() are picked up. + manifest_override_loader(components) + # Obtain possible dependencies BEFORE validate_config, because # get_all_dependencies calls CORE.reset() which clears build_path. - # Always include 'time' because USE_TIME_TIMEZONE is defined as a build flag, - # which causes core/time.h to include components/time/posix_tz.h. components_with_dependencies: list[str] = sorted( - get_all_dependencies(set(components) | {"time"}, cpp_testing=True) + get_all_dependencies(set(components)) ) + # Apply overrides for any transitively discovered dependencies. + manifest_override_loader(components_with_dependencies) + CORE.config_path = tests_dir / "dummy.yaml" CORE.dashboard = None - CORE.cpp_testing = True - CORE.cpp_testing_codegen = codegen_components # Validate config will expand the above with defaults: config = validate_config(config, {}) @@ -305,7 +365,7 @@ def compile_and_get_binary( def build_and_run( selected_components: list[str], tests_dir: Path, - codegen_components: set[str], + manifest_override_loader: ManifestOverrideLoader, config_prefix: str, friendly_name: str, libraries: str | list[str], @@ -324,7 +384,7 @@ def build_and_run( Args: selected_components: Components to include (directory names in tests_dir) tests_dir: Directory containing test/benchmark files - codegen_components: Components whose to_code should run + manifest_override_loader: Callback to apply manifest overrides for components config_prefix: Prefix for the config name (e.g. "cpptests", "cppbench") friendly_name: Human-readable name for the config libraries: PlatformIO library specification(s) @@ -382,7 +442,7 @@ def build_and_run( ) exit_code, program_path = compile_and_get_binary( - config, components, codegen_components, tests_dir, label + config, components, tests_dir, manifest_override_loader, label ) if exit_code != EXIT_OK or program_path is None: diff --git a/script/cpp_benchmark.py b/script/cpp_benchmark.py index bd92266ea6..a54d3752df 100755 --- a/script/cpp_benchmark.py +++ b/script/cpp_benchmark.py @@ -2,18 +2,18 @@ """Build and run C++ benchmarks for ESPHome components using Google Benchmark.""" import argparse +from functools import partial import json import os from pathlib import Path import sys -from helpers import root_path -from test_helpers import ( - BASE_CODEGEN_COMPONENTS, +from build_helpers import ( PLATFORMIO_GOOGLE_BENCHMARK_LIB, - USE_TIME_TIMEZONE_FLAG, build_and_run, + load_test_manifest_overrides, ) +from helpers import root_path # Path to /tests/benchmarks/components BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "components" @@ -21,11 +21,6 @@ BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "components" # Path to /tests/benchmarks/core (always included, not a component) CORE_BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "core" -# Additional codegen components beyond the base set. -# json is needed because its to_code adds the ArduinoJson library -# (auto-loaded by api, but cpp_testing suppresses to_code unless listed). -BENCHMARK_CODEGEN_COMPONENTS = BASE_CODEGEN_COMPONENTS | {"json"} - PLATFORMIO_OPTIONS = { "build_unflags": [ "-Os", # remove default size-opt @@ -33,7 +28,6 @@ PLATFORMIO_OPTIONS = { "build_flags": [ "-O2", # optimize for speed (CodSpeed recommends RelWithDebInfo) "-g", # debug symbols for profiling - USE_TIME_TIMEZONE_FLAG, "-DUSE_BENCHMARK", # disable WarnIfComponentBlockingGuard in finish() ], # Use deep+ LDF mode to ensure PlatformIO detects the benchmark @@ -73,7 +67,9 @@ def run_benchmarks(selected_components: list[str], build_only: bool = False) -> return build_and_run( selected_components=selected_components, tests_dir=BENCHMARKS_DIR, - codegen_components=BENCHMARK_CODEGEN_COMPONENTS, + manifest_override_loader=partial( + load_test_manifest_overrides, tests_dir=BENCHMARKS_DIR + ), config_prefix="cppbench", friendly_name="CPP Benchmarks", libraries=benchmark_lib, diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index 81c56b82da..5594d64240 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -1,15 +1,15 @@ #!/usr/bin/env python3 import argparse +from functools import partial from pathlib import Path import sys -from helpers import get_all_components, root_path -from test_helpers import ( - BASE_CODEGEN_COMPONENTS, +from build_helpers import ( PLATFORMIO_GOOGLE_TEST_LIB, - USE_TIME_TIMEZONE_FLAG, build_and_run, + load_test_manifest_overrides, ) +from helpers import get_all_components, root_path # Path to /tests/components COMPONENTS_TESTS_DIR: Path = Path(root_path) / "tests" / "components" @@ -21,7 +21,6 @@ PLATFORMIO_OPTIONS = { ], "build_flags": [ "-Og", # optimize for debug - USE_TIME_TIMEZONE_FLAG, "-DESPHOME_DEBUG", # enable debug assertions # Enable the address and undefined behavior sanitizers "-fsanitize=address", @@ -39,7 +38,9 @@ def run_tests(selected_components: list[str]) -> int: return build_and_run( selected_components=selected_components, tests_dir=COMPONENTS_TESTS_DIR, - codegen_components=BASE_CODEGEN_COMPONENTS, + manifest_override_loader=partial( + load_test_manifest_overrides, tests_dir=COMPONENTS_TESTS_DIR + ), config_prefix="cpptests", friendly_name="CPP Unit Tests", libraries=PLATFORMIO_GOOGLE_TEST_LIB, diff --git a/script/determine-jobs.py b/script/determine-jobs.py index ad08f8dce5..9f32238780 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -388,7 +388,7 @@ BENCHMARKS_COMPONENTS_PATH = "tests/benchmarks/components" BENCHMARK_INFRASTRUCTURE_FILES = frozenset( { "script/cpp_benchmark.py", - "script/test_helpers.py", + "script/build_helpers.py", "script/setup_codspeed_lib.py", } ) @@ -402,7 +402,7 @@ def should_run_benchmarks(branch: str | None = None) -> bool: 1. Core C++ files changed (esphome/core/*) 2. A directly changed component has benchmark files (no dependency expansion) 3. Benchmark infrastructure changed (tests/benchmarks/*, script/cpp_benchmark.py, - script/test_helpers.py, script/setup_codspeed_lib.py) + script/build_helpers.py, script/setup_codspeed_lib.py) Unlike unit tests, benchmarks do NOT expand to dependent components. Changing ``sensor`` does not trigger ``api`` benchmarks just because diff --git a/script/helpers.py b/script/helpers.py index 9665af70ec..290dcadf0b 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -627,14 +627,12 @@ def get_usable_cpu_count() -> int: def get_all_dependencies( - component_names: set[str], cpp_testing: bool = False + component_names: set[str], ) -> set[str]: """Get all dependencies for a set of components. Args: component_names: Set of component names to get dependencies for - cpp_testing: If True, set CORE.cpp_testing so AUTO_LOAD callables that - conditionally include testing-only dependencies work correctly Returns: Set of all components including dependencies and auto-loaded components @@ -652,7 +650,6 @@ def get_all_dependencies( # Reset CORE to ensure clean state CORE.reset() - CORE.cpp_testing = cpp_testing # Set up fake config path for component loading root = Path(__file__).parent.parent diff --git a/tests/benchmarks/components/core/__init__.py b/tests/benchmarks/components/core/__init__.py new file mode 100644 index 0000000000..d676ab669b --- /dev/null +++ b/tests/benchmarks/components/core/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # core (esphome/core/config.py) must run its to_code during builds + # because it bootstraps the fundamental application infrastructure. + manifest.enable_codegen() diff --git a/tests/benchmarks/components/host/__init__.py b/tests/benchmarks/components/host/__init__.py new file mode 100644 index 0000000000..f418c25f88 --- /dev/null +++ b/tests/benchmarks/components/host/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # host must run its to_code during builds because it sets up + # the host platform target execution environment. + manifest.enable_codegen() diff --git a/tests/benchmarks/components/json/__init__.py b/tests/benchmarks/components/json/__init__.py new file mode 100644 index 0000000000..56826b64bd --- /dev/null +++ b/tests/benchmarks/components/json/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # json must run its to_code during benchmark builds because it + # adds the ArduinoJson library dependency needed by the API component. + manifest.enable_codegen() diff --git a/tests/benchmarks/components/logger/__init__.py b/tests/benchmarks/components/logger/__init__.py new file mode 100644 index 0000000000..cfab73e1e5 --- /dev/null +++ b/tests/benchmarks/components/logger/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # logger must run its to_code during builds because it configures + # the logging subsystem used by ESP_LOG* macros. + manifest.enable_codegen() diff --git a/tests/benchmarks/components/time/__init__.py b/tests/benchmarks/components/time/__init__.py new file mode 100644 index 0000000000..7f68003e29 --- /dev/null +++ b/tests/benchmarks/components/time/__init__.py @@ -0,0 +1,9 @@ +import esphome.codegen as cg +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + async def to_code(config): + cg.add_build_flag("-DUSE_TIME_TIMEZONE") + + manifest.to_code = to_code diff --git a/tests/components/README.md b/tests/components/README.md index 6da0dadd25..145a3440d2 100644 --- a/tests/components/README.md +++ b/tests/components/README.md @@ -14,11 +14,63 @@ include the relevant `.cpp` and `.h` test files there. ### Override component code generation for testing -When generating code for testing, ESPHome won't invoke the component's `to_code` function, since most components do not -need to generate configuration code for testing. +During C++ test builds, `to_code` is suppressed for every component by default — most components do not +need to generate configuration code for a unit test binary. -If you do need to generate code to for example configure compilation flags or add libraries, -add the component name to the `CPP_TESTING_CODEGEN_COMPONENTS` allowlist in `script/cpp_unit_test.py`. +#### Manifest overrides + +If your component needs to customise code generation behavior for testing — for example to re-enable +`to_code`, supply a lightweight stub, add a test-only dependency, or change any other manifest attribute — +create an `__init__.py` in your component's test directory and define `override_manifest`: + +**Top-level component** (`tests/components/<component>/__init__.py`): + +```python +from tests.testing_helpers import ComponentManifestOverride + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # Re-enable the component's own to_code (needed when the component must + # emit C++ setup code that the test binary depends on at link time). + manifest.enable_codegen() +``` + +Or supply a lightweight stub instead of the real `to_code`: + +```python +from tests.testing_helpers import ComponentManifestOverride + +def override_manifest(manifest: ComponentManifestOverride) -> None: + async def to_code_testing(config): + # Only emit what the C++ tests actually need + pass + + manifest.to_code = to_code_testing + manifest.dependencies = manifest.dependencies + ["some_test_only_dep"] +``` + +**Platform component** (`tests/components/<component>/<domain>/__init__.py`, +e.g. `tests/components/my_sensor/sensor/__init__.py`): + +```python +from tests.testing_helpers import ComponentManifestOverride + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() +``` + +`override_manifest` receives a `ComponentManifestOverride` that wraps the real manifest. +Attribute assignments store an override; reads fall back to the real manifest when no +override is present. + +Key methods: + +| Method | Effect | +|---|---| +| `manifest.enable_codegen()` | Remove the `to_code` suppression, re-enabling code generation | +| `manifest.restore()` | Clear **all** overrides, reverting every attribute to the original | + +The function is called after `to_code` has already been set to `None`, so calling +`enable_codegen()` is a deliberate opt-in. ## Running component unit tests diff --git a/tests/components/core/__init__.py b/tests/components/core/__init__.py new file mode 100644 index 0000000000..34ca4fbe4f --- /dev/null +++ b/tests/components/core/__init__.py @@ -0,0 +1,8 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # core (esphome/core/config.py) must run its to_code during C++ test builds + # because it bootstraps the fundamental application infrastructure that all + # components depend on (component registration, event loop, etc.). + manifest.enable_codegen() diff --git a/tests/components/host/__init__.py b/tests/components/host/__init__.py new file mode 100644 index 0000000000..bcb363cdc3 --- /dev/null +++ b/tests/components/host/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # host must run its to_code during C++ test builds because it sets up the + # host platform target, which is the execution environment for all unit tests. + manifest.enable_codegen() diff --git a/tests/components/logger/__init__.py b/tests/components/logger/__init__.py new file mode 100644 index 0000000000..3acfe02748 --- /dev/null +++ b/tests/components/logger/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # logger must run its to_code during C++ test builds because it configures + # the logging subsystem used by ESP_LOG* macros throughout component code. + manifest.enable_codegen() diff --git a/tests/components/time/__init__.py b/tests/components/time/__init__.py new file mode 100644 index 0000000000..7f68003e29 --- /dev/null +++ b/tests/components/time/__init__.py @@ -0,0 +1,9 @@ +import esphome.codegen as cg +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + async def to_code(config): + cg.add_build_flag("-DUSE_TIME_TIMEZONE") + + manifest.to_code = to_code diff --git a/tests/script/test_determine_jobs.py b/tests/script/test_determine_jobs.py index 29535d1fd3..de239ee0b5 100644 --- a/tests/script/test_determine_jobs.py +++ b/tests/script/test_determine_jobs.py @@ -1846,7 +1846,7 @@ def test_should_run_benchmarks_benchmark_infra_change() -> None: """Test benchmarks trigger on benchmark infrastructure changes.""" for infra_file in [ "script/cpp_benchmark.py", - "script/test_helpers.py", + "script/build_helpers.py", "script/setup_codspeed_lib.py", ]: with patch.object(determine_jobs, "changed_files", return_value=[infra_file]): diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index e3802d2d51..28f111d758 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -1073,28 +1073,6 @@ def test_get_all_dependencies_platform_component_with_dependencies() -> None: assert result == {"sensor.bthome", "sensor"} -def test_get_all_dependencies_cpp_testing_flag() -> None: - """cpp_testing=True propagates to CORE.cpp_testing during resolution.""" - from esphome.core import CORE - - with ( - patch("esphome.loader.get_component") as mock_get_component, - patch("esphome.loader.get_platform"), - ): - observed: list[bool] = [] - - def capturing_get_component(name: str): - observed.append(CORE.cpp_testing) - - mock_get_component.side_effect = capturing_get_component - - helpers.get_all_dependencies({"some_comp"}, cpp_testing=True) - - assert observed and all(observed), ( - "CORE.cpp_testing should be True during resolution" - ) - - def test_get_components_from_integration_fixtures() -> None: """Test extraction of components from fixture YAML files.""" yaml_content = { diff --git a/tests/script/test_test_helpers.py b/tests/script/test_test_helpers.py new file mode 100644 index 0000000000..467940fc33 --- /dev/null +++ b/tests/script/test_test_helpers.py @@ -0,0 +1,260 @@ +"""Unit tests for script/build_helpers.py manifest override and build helpers.""" + +import os +from pathlib import Path +import sys +import textwrap +from unittest.mock import MagicMock, patch + +import pytest + +# Add the script directory to Python path so we can import build_helpers +sys.path.insert( + 0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "script")) +) + +import build_helpers # noqa: E402 + +from esphome.loader import ComponentManifest # noqa: E402 +from tests.testing_helpers import ComponentManifestOverride # noqa: E402 + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_component_manifest(*, to_code=None, dependencies=None) -> ComponentManifest: + mod = MagicMock() + mod.to_code = to_code + mod.DEPENDENCIES = dependencies or [] + return ComponentManifest(mod) + + +# --------------------------------------------------------------------------- +# filter_components_with_files +# --------------------------------------------------------------------------- + + +def test_filter_keeps_components_with_cpp_files(tmp_path: Path) -> None: + comp_dir = tmp_path / "mycomp" + comp_dir.mkdir() + (comp_dir / "mycomp_test.cpp").write_text("") + + result = build_helpers.filter_components_with_files(["mycomp"], tmp_path) + + assert result == ["mycomp"] + + +def test_filter_keeps_components_with_h_files(tmp_path: Path) -> None: + comp_dir = tmp_path / "mycomp" + comp_dir.mkdir() + (comp_dir / "helpers.h").write_text("") + + result = build_helpers.filter_components_with_files(["mycomp"], tmp_path) + + assert result == ["mycomp"] + + +def test_filter_drops_components_without_test_dir(tmp_path: Path) -> None: + result = build_helpers.filter_components_with_files(["nodir"], tmp_path) + + assert result == [] + + +def test_filter_drops_components_with_no_cpp_or_h(tmp_path: Path) -> None: + comp_dir = tmp_path / "mycomp" + comp_dir.mkdir() + (comp_dir / "README.md").write_text("") + + result = build_helpers.filter_components_with_files(["mycomp"], tmp_path) + + assert result == [] + + +# --------------------------------------------------------------------------- +# get_platform_components +# --------------------------------------------------------------------------- + + +def test_get_platform_components_discovers_subdirectory(tmp_path: Path) -> None: + (tmp_path / "bthome" / "sensor").mkdir(parents=True) + + sensor_mod = MagicMock() + sensor_mod.IS_PLATFORM_COMPONENT = True + + with patch( + "build_helpers.get_component", return_value=ComponentManifest(sensor_mod) + ): + result = build_helpers.get_platform_components(["bthome"], tmp_path) + + assert result == ["sensor.bthome"] + + +def test_get_platform_components_skips_pycache(tmp_path: Path) -> None: + (tmp_path / "bthome" / "__pycache__").mkdir(parents=True) + + result = build_helpers.get_platform_components(["bthome"], tmp_path) + + assert result == [] + + +def test_get_platform_components_raises_for_invalid_domain(tmp_path: Path) -> None: + (tmp_path / "bthome" / "notadomain").mkdir(parents=True) + + with ( + patch("build_helpers.get_component", return_value=None), + pytest.raises(ValueError, match="notadomain"), + ): + build_helpers.get_platform_components(["bthome"], tmp_path) + + +# --------------------------------------------------------------------------- +# load_test_manifest_overrides +# --------------------------------------------------------------------------- + + +def test_load_suppresses_to_code(tmp_path: Path) -> None: + """to_code is always set to None before the override is called.""" + + async def real_to_code(config): + pass + + inner = _make_component_manifest(to_code=real_to_code) + + with ( + patch("build_helpers.get_component", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + installed: ComponentManifestOverride = mock_set.call_args[0][1] + + assert installed.to_code is None + + +def test_load_calls_override_fn(tmp_path: Path) -> None: + """override_manifest() in test_init is called with the ComponentManifestOverride.""" + comp_dir = tmp_path / "mycomp" + comp_dir.mkdir() + init_py = comp_dir / "__init__.py" + init_py.write_text( + textwrap.dedent("""\ + def override_manifest(manifest): + manifest.dependencies = ["injected"] + """) + ) + + inner = _make_component_manifest() + override = ComponentManifestOverride(inner) + override.to_code = None + + with ( + patch("build_helpers.get_component", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + installed: ComponentManifestOverride = mock_set.call_args[0][1] + + assert installed.dependencies == ["injected"] + + +def test_load_enable_codegen_in_override(tmp_path: Path) -> None: + """An override_manifest that calls enable_codegen() restores to_code.""" + + async def real_to_code(config): + pass + + comp_dir = tmp_path / "mycomp" + comp_dir.mkdir() + init_py = comp_dir / "__init__.py" + init_py.write_text( + textwrap.dedent("""\ + def override_manifest(manifest): + manifest.enable_codegen() + """) + ) + + inner = _make_component_manifest(to_code=real_to_code) + + with ( + patch("build_helpers.get_component", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + installed: ComponentManifestOverride = mock_set.call_args[0][1] + + assert installed.to_code is real_to_code + + +def test_load_no_override_file(tmp_path: Path) -> None: + """No override file: manifest is wrapped and to_code suppressed, nothing else.""" + inner = _make_component_manifest() + + with ( + patch("build_helpers.get_component", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + + mock_set.assert_called_once() + key, installed = mock_set.call_args[0] + assert key == "mycomp" + assert isinstance(installed, ComponentManifestOverride) + + +def test_load_skips_already_wrapped(tmp_path: Path) -> None: + """Components already wrapped as ComponentManifestOverride are not double-wrapped.""" + inner = _make_component_manifest() + already_wrapped = ComponentManifestOverride(inner) + + with ( + patch("build_helpers.get_component", return_value=already_wrapped), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + + mock_set.assert_not_called() + + +def test_load_skips_platform_component_already_wrapped(tmp_path: Path) -> None: + inner = _make_component_manifest() + already_wrapped = ComponentManifestOverride(inner) + + with ( + patch("build_helpers.get_platform", return_value=already_wrapped), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["sensor.bthome"], tmp_path) + + mock_set.assert_not_called() + + +def test_load_wraps_top_level_component(tmp_path: Path) -> None: + inner = _make_component_manifest() + + with ( + patch("build_helpers.get_component", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["mycomp"], tmp_path) + + mock_set.assert_called_once() + key, installed = mock_set.call_args[0] + assert key == "mycomp" + assert isinstance(installed, ComponentManifestOverride) + assert installed.to_code is None + + +def test_load_wraps_platform_component(tmp_path: Path) -> None: + inner = _make_component_manifest() + + with ( + patch("build_helpers.get_platform", return_value=inner), + patch("build_helpers.set_testing_manifest") as mock_set, + ): + build_helpers.load_test_manifest_overrides(["sensor.bthome"], tmp_path) + + mock_set.assert_called_once() + key, installed = mock_set.call_args[0] + assert key == "bthome.sensor" + assert isinstance(installed, ComponentManifestOverride) + assert installed.to_code is None diff --git a/tests/testing_helpers.py b/tests/testing_helpers.py new file mode 100644 index 0000000000..20b76697a1 --- /dev/null +++ b/tests/testing_helpers.py @@ -0,0 +1,63 @@ +from typing import Any + +from esphome.loader import ComponentManifest, _replace_component_manifest + + +class ComponentManifestOverride: + """Mutable wrapper around ComponentManifest for test-specific attribute overrides. + + When ``tests/components/<name>/__init__.py`` defines:: + + def override_manifest(manifest: ComponentManifestOverride) -> None: + ... + + the function receives an instance of this class wrapping the real component + manifest. Any attribute assignment stores an override; reads fall back to + the underlying ``ComponentManifest`` when no override has been set. + + Example:: + + def override_manifest(manifest: ComponentManifestOverride) -> None: + async def to_code_testing(config): + pass # lightweight no-op stub for C++ unit tests + + manifest.to_code = to_code_testing + manifest.dependencies = manifest.dependencies + ["extra_dep_for_tests"] + """ + + def __init__(self, wrapped: "ComponentManifest") -> None: + object.__setattr__(self, "_wrapped", wrapped) + object.__setattr__(self, "_overrides", {}) + + def __getattr__(self, name: str) -> Any: + overrides: dict[str, Any] = object.__getattribute__(self, "_overrides") + if name in overrides: + return overrides[name] + wrapped: ComponentManifest = object.__getattribute__(self, "_wrapped") + return getattr(wrapped, name) + + def __setattr__(self, name: str, value: Any) -> None: + overrides: dict[str, Any] = object.__getattribute__(self, "_overrides") + overrides[name] = value + + def enable_codegen(self) -> None: + """Remove the to_code suppression, re-enabling code generation for this component. + + Call this from ``override_manifest`` when the component needs its real (or a + custom stub) ``to_code`` to run during C++ unit test builds. + """ + overrides: dict[str, Any] = object.__getattribute__(self, "_overrides") + overrides.pop("to_code", None) + + def restore(self) -> None: + """Clear all overrides, reverting to the wrapped manifest's values.""" + object.__getattribute__(self, "_overrides").clear() + + +def set_testing_manifest(domain: str, manifest: ComponentManifestOverride) -> None: + """Install a testing manifest override into the component cache. + + Called from the C++ unit test infrastructure when a component's test + directory provides an ``override_manifest`` function. + """ + _replace_component_manifest(domain, manifest) diff --git a/tests/unit_tests/test_loader.py b/tests/unit_tests/test_loader.py index c6d4c4aef0..a42cc5cca7 100644 --- a/tests/unit_tests/test_loader.py +++ b/tests/unit_tests/test_loader.py @@ -2,7 +2,104 @@ from unittest.mock import MagicMock, patch -from esphome.loader import ComponentManifest +from esphome.loader import ComponentManifest, _replace_component_manifest, get_component +from tests.testing_helpers import ComponentManifestOverride + +# --------------------------------------------------------------------------- +# ComponentManifestOverride +# --------------------------------------------------------------------------- + + +def _make_manifest(*, to_code=None, dependencies=None) -> ComponentManifest: + """Return a ComponentManifest backed by a minimal mock module.""" + mod = MagicMock() + mod.to_code = to_code + mod.DEPENDENCIES = dependencies or [] + return ComponentManifest(mod) + + +def test_testing_manifest_delegates_to_wrapped() -> None: + """Unoverridden attributes fall through to the wrapped manifest.""" + inner = _make_manifest(dependencies=["wifi"]) + tm = ComponentManifestOverride(inner) + assert tm.dependencies == ["wifi"] + + +def test_testing_manifest_override_shadows_wrapped() -> None: + """An assigned attribute shadows the wrapped value.""" + inner = _make_manifest(dependencies=["wifi"]) + tm = ComponentManifestOverride(inner) + tm.dependencies = ["ble"] + assert tm.dependencies == ["ble"] + # Wrapped value unchanged + assert inner.dependencies == ["wifi"] + + +def test_testing_manifest_to_code_suppression() -> None: + """Setting to_code=None suppresses code generation.""" + + async def real_to_code(config): + pass + + inner = _make_manifest(to_code=real_to_code) + tm = ComponentManifestOverride(inner) + tm.to_code = None + assert tm.to_code is None + + +def test_testing_manifest_enable_codegen_removes_suppression() -> None: + """enable_codegen() removes the to_code override, restoring the original.""" + + async def real_to_code(config): + pass + + inner = _make_manifest(to_code=real_to_code) + tm = ComponentManifestOverride(inner) + tm.to_code = None + assert tm.to_code is None + + tm.enable_codegen() + assert tm.to_code is real_to_code + + +def test_testing_manifest_enable_codegen_preserves_other_overrides() -> None: + """enable_codegen() only removes to_code; other overrides survive.""" + inner = _make_manifest(dependencies=["wifi"]) + tm = ComponentManifestOverride(inner) + tm.to_code = None + tm.dependencies = ["ble"] + + tm.enable_codegen() + + assert tm.to_code is inner.to_code + assert tm.dependencies == ["ble"] + + +def test_testing_manifest_restore_clears_all_overrides() -> None: + """restore() removes every override, reverting all attributes to wrapped values.""" + + async def real_to_code(config): + pass + + inner = _make_manifest(to_code=real_to_code, dependencies=["wifi"]) + tm = ComponentManifestOverride(inner) + tm.to_code = None + tm.dependencies = ["ble"] + + tm.restore() + + assert tm.to_code is real_to_code + assert tm.dependencies == ["wifi"] + + +def test_replace_component_manifest_installs_override() -> None: + """_replace_component_manifest replaces the cached manifest for a domain.""" + inner = _make_manifest() + override = ComponentManifestOverride(inner) + + _replace_component_manifest("_test_dummy_domain", override) + + assert get_component("_test_dummy_domain") is override def test_component_manifest_resources_with_filter_source_files() -> None: From b9e8da92c734a4b761b9835b6e584d87c1d47eaa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 14:19:31 -1000 Subject: [PATCH 1475/2030] [scheduler] Fix UB in cross-thread counter/vector reads, add atomic fast-path (#14880) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/core/scheduler.cpp | 48 ++++++----- esphome/core/scheduler.h | 159 ++++++++++++++++++++++++++++++++++--- 2 files changed, 177 insertions(+), 30 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 72b183384e..db40ede78c 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -212,6 +212,14 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } target->push_back(item); + if (target == &this->to_add_) { + this->to_add_count_increment_(); + } +#ifndef ESPHOME_THREAD_SINGLE + else { + this->defer_count_increment_(); + } +#endif } void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, @@ -388,7 +396,7 @@ optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) { // safe when called from the main thread. Other threads must not call this method. // If no items, return empty optional - if (this->cleanup_() == 0) + if (!this->cleanup_()) return {}; SchedulerItem *item = this->items_[0]; @@ -422,7 +430,7 @@ void Scheduler::full_cleanup_removed_items_() { this->items_.erase(this->items_.begin() + write, this->items_.end()); // Rebuild the heap structure since items are no longer in heap order std::make_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); - this->to_remove_ = 0; + this->to_remove_clear_(); } #ifndef ESPHOME_THREAD_SINGLE @@ -503,7 +511,7 @@ void HOT Scheduler::call(uint32_t now) { // If we still have too many cancelled items, do a full cleanup // This only happens if cancelled items are stuck in the middle/bottom of the heap - if (this->to_remove_ >= MAX_LOGICALLY_DELETED_ITEMS) { + if (this->to_remove_count_() >= MAX_LOGICALLY_DELETED_ITEMS) { this->full_cleanup_removed_items_(); } while (!this->items_.empty()) { @@ -530,7 +538,7 @@ void HOT Scheduler::call(uint32_t now) { LockGuard guard{this->lock_}; if (is_item_removed_locked_(item)) { this->recycle_item_main_loop_(this->pop_raw_locked_()); - this->to_remove_--; + this->to_remove_decrement_(); continue; } } @@ -539,7 +547,7 @@ void HOT Scheduler::call(uint32_t now) { if (is_item_removed_(item)) { LockGuard guard{this->lock_}; this->recycle_item_main_loop_(this->pop_raw_locked_()); - this->to_remove_--; + this->to_remove_decrement_(); continue; } #endif @@ -567,7 +575,7 @@ void HOT Scheduler::call(uint32_t now) { if (this->is_item_removed_locked_(executed_item)) { // We were removed/cancelled in the function call, recycle and continue - this->to_remove_--; + this->to_remove_decrement_(); this->recycle_item_main_loop_(executed_item); continue; } @@ -577,6 +585,7 @@ void HOT Scheduler::call(uint32_t now) { // Add new item directly to to_add_ // since we have the lock held this->to_add_.push_back(executed_item); + this->to_add_count_increment_(); } else { // Timeout completed - recycle it this->recycle_item_main_loop_(executed_item); @@ -605,6 +614,10 @@ void HOT Scheduler::call(uint32_t now) { #endif } void HOT Scheduler::process_to_add() { + // Fast path: skip lock acquisition when nothing to add. + // Worst case is a one-loop-iteration delay before newly added items are processed. + if (this->to_add_empty_()) + return; LockGuard guard{this->lock_}; for (auto *&it : this->to_add_) { if (is_item_removed_locked_(it)) { @@ -618,17 +631,14 @@ void HOT Scheduler::process_to_add() { std::push_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); } this->to_add_.clear(); + this->to_add_count_clear_(); } -size_t HOT Scheduler::cleanup_() { - // Fast path: if nothing to remove, just return the current size - // Reading to_remove_ without lock is safe because: - // 1. We only call this from the main thread during call() - // 2. If it's 0, there's definitely nothing to cleanup - // 3. If it becomes non-zero after we check, cleanup will happen on the next loop iteration - // 4. Not all platforms support atomics, so we accept this race in favor of performance - // 5. The worst case is a one-loop-iteration delay in cleanup, which is harmless - if (this->to_remove_ == 0) - return this->items_.size(); +bool HOT Scheduler::cleanup_() { + // Fast path: if nothing to remove, just check if items exist. + // Uses atomic load on platforms with atomics, falls back to always taking the lock otherwise. + // Worst case is a one-loop-iteration delay in cleanup. + if (this->to_remove_empty_()) + return !this->items_.empty(); // We must hold the lock for the entire cleanup operation because: // 1. We're modifying items_ (via pop_raw_locked_) which requires exclusive access @@ -643,10 +653,10 @@ size_t HOT Scheduler::cleanup_() { SchedulerItem *item = this->items_[0]; if (!this->is_item_removed_locked_(item)) break; - this->to_remove_--; + this->to_remove_decrement_(); this->recycle_item_main_loop_(this->pop_raw_locked_()); } - return this->items_.size(); + return !this->items_.empty(); } Scheduler::SchedulerItem *HOT Scheduler::pop_raw_locked_() { std::pop_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); @@ -699,7 +709,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_, component, name_type, static_name, hash_or_id, type, match_retry); total_cancelled += heap_cancelled; - this->to_remove_ += heap_cancelled; + this->to_remove_add_(heap_cancelled); } // Cancel items in to_add_ diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 0476513bb9..e545055fca 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -284,9 +284,9 @@ class Scheduler { #endif } // Cleanup logically deleted items from the scheduler - // Returns the number of items remaining after cleanup + // Returns true if items remain after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). - size_t cleanup_(); + bool cleanup_(); // Remove and return the front item from the heap as a raw pointer. // Caller takes ownership and must either recycle or delete the item. // IMPORTANT: Caller must hold the scheduler lock before calling this function. @@ -395,15 +395,9 @@ class Scheduler { // erase() on every pop, which would be O(n). The queue is processed once per loop - // any items added during processing are left for the next loop iteration. - // Snapshot the queue end point - only process items that existed at loop start - // Items added during processing (by callbacks or other threads) run next loop - // No lock needed: single consumer (main loop), stale read just means we process less this iteration - size_t defer_queue_end = this->defer_queue_.size(); - // Fast path: nothing to process, avoid lock entirely. - // Safe without lock: single consumer (main loop) reads front_, and a stale size() read - // from a concurrent push can only make us see fewer items — they'll be processed next loop. - if (this->defer_queue_front_ >= defer_queue_end) + // Worst case is a one-loop-iteration delay before newly deferred items are processed. + if (this->defer_empty_()) return; // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), @@ -412,6 +406,13 @@ class Scheduler { SchedulerItem *item; this->lock_.lock(); + // Reset counter and snapshot queue end under lock + this->defer_count_clear_(); + size_t defer_queue_end = this->defer_queue_.size(); + if (this->defer_queue_front_ >= defer_queue_end) { + this->lock_.unlock(); + return; + } while (this->defer_queue_front_ < defer_queue_end) { // Take ownership of the item, leaving nullptr in the vector slot. // This is safe because: @@ -527,14 +528,150 @@ class Scheduler { Mutex lock_; std::vector<SchedulerItem *> items_; std::vector<SchedulerItem *> to_add_; + +#ifndef ESPHOME_THREAD_SINGLE + // Fast-path counter for process_to_add() to skip taking the lock when there is + // nothing to add. Uses std::atomic on platforms that support it, plain uint32_t + // otherwise. On non-atomic platforms, callers must hold the scheduler lock when + // mutating this counter. Not needed on single-threaded platforms where we can + // check to_add_.empty() directly. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> to_add_count_{0}; +#else + uint32_t to_add_count_{0}; +#endif +#endif /* ESPHOME_THREAD_SINGLE */ + + // Fast-path helper for process_to_add() to decide if it can try the lock-free path. + // - On ESPHOME_THREAD_SINGLE: direct container check is safe (no concurrent writers). + // - On ESPHOME_THREAD_MULTI_ATOMICS: performs a lock-free check via to_add_count_. + // - On ESPHOME_THREAD_MULTI_NO_ATOMICS: always returns false to force the caller + // down the locked path; this is NOT a lock-free emptiness check on that platform. + bool to_add_empty_() const { +#ifdef ESPHOME_THREAD_SINGLE + return this->to_add_.empty(); +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + return this->to_add_count_.load(std::memory_order_relaxed) == 0; +#else + return false; +#endif + } + + // Increment to_add_count_ (no-op on single-threaded platforms) + void to_add_count_increment_() { +#ifdef ESPHOME_THREAD_SINGLE + // No counter needed — to_add_empty_() checks the vector directly +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + this->to_add_count_.fetch_add(1, std::memory_order_relaxed); +#else + this->to_add_count_++; +#endif + } + + // Reset to_add_count_ (no-op on single-threaded platforms) + void to_add_count_clear_() { +#ifdef ESPHOME_THREAD_SINGLE + // No counter needed — to_add_empty_() checks the vector directly +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + this->to_add_count_.store(0, std::memory_order_relaxed); +#else + this->to_add_count_ = 0; +#endif + } + #ifndef ESPHOME_THREAD_SINGLE // Single-core platforms don't need the defer queue and save ~32 bytes of RAM // Using std::vector instead of std::deque avoids 512-byte chunked allocations // Index tracking avoids O(n) erase() calls when draining the queue each loop std::vector<SchedulerItem *> defer_queue_; // FIFO queue for defer() calls size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) -#endif /* ESPHOME_THREAD_SINGLE */ + + // Fast-path counter for process_defer_queue_() to skip lock when nothing to process. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> defer_count_{0}; +#else + uint32_t defer_count_{0}; +#endif + + bool defer_empty_() const { + // defer_queue_ only exists on multi-threaded platforms, so no ESPHOME_THREAD_SINGLE path + // ESPHOME_THREAD_MULTI_NO_ATOMICS: always take the lock +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->defer_count_.load(std::memory_order_relaxed) == 0; +#else + return false; +#endif + } + + void defer_count_increment_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->defer_count_.fetch_add(1, std::memory_order_relaxed); +#else + this->defer_count_++; +#endif + } + + void defer_count_clear_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->defer_count_.store(0, std::memory_order_relaxed); +#else + this->defer_count_ = 0; +#endif + } + +#endif /* ESPHOME_THREAD_SINGLE */ + + // Counter for items marked for removal. Incremented cross-thread in cancel_item_locked_(). + // On ESPHOME_THREAD_MULTI_ATOMICS this is read without a lock in the cleanup_() fast path; + // on ESPHOME_THREAD_MULTI_NO_ATOMICS the fast path is disabled so cleanup_() always takes the lock. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> to_remove_{0}; +#else uint32_t to_remove_{0}; +#endif + + // Lock-free check if there are items to remove (for fast-path in cleanup_) + bool to_remove_empty_() const { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->to_remove_.load(std::memory_order_relaxed) == 0; +#elif defined(ESPHOME_THREAD_SINGLE) + return this->to_remove_ == 0; +#else + return false; // Always take the lock path +#endif + } + + void to_remove_add_(uint32_t count) { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.fetch_add(count, std::memory_order_relaxed); +#else + this->to_remove_ += count; +#endif + } + + void to_remove_decrement_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.fetch_sub(1, std::memory_order_relaxed); +#else + this->to_remove_--; +#endif + } + + void to_remove_clear_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.store(0, std::memory_order_relaxed); +#else + this->to_remove_ = 0; +#endif + } + + uint32_t to_remove_count_() const { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->to_remove_.load(std::memory_order_relaxed); +#else + return this->to_remove_; +#endif + } // Memory pool for recycling SchedulerItem objects to reduce heap churn. // Design decisions: From 8bbfadb59aa39b02156653dee670f6c2990cd506 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 17 Mar 2026 14:22:31 +0100 Subject: [PATCH 1476/2030] [core] Small improvements (#14884) --- esphome/components/bme68x_bsec2/__init__.py | 4 ++-- script/merge_component_configs.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/bme68x_bsec2/__init__.py b/esphome/components/bme68x_bsec2/__init__.py index 4200b2f0b8..5f0afa9c9f 100644 --- a/esphome/components/bme68x_bsec2/__init__.py +++ b/esphome/components/bme68x_bsec2/__init__.py @@ -186,8 +186,8 @@ async def to_code_base(config): cg.add_library("SPI", None) cg.add_library( "BME68x Sensor library", - "1.3.40408", - "https://github.com/boschsensortec/Bosch-BME68x-Library", + None, + "https://github.com/boschsensortec/Bosch-BME68x-Library#v1.3.40408", ) cg.add_library( "BSEC2 Software Library", diff --git a/script/merge_component_configs.py b/script/merge_component_configs.py index 5e98f1fef5..41bbafcd02 100755 --- a/script/merge_component_configs.py +++ b/script/merge_component_configs.py @@ -384,7 +384,7 @@ def merge_component_configs( # Write merged config output_file.parent.mkdir(parents=True, exist_ok=True) yaml_content = yaml_util.dump(merged_config_data) - output_file.write_text(yaml_content) + output_file.write_text(yaml_content, encoding="utf-8") print(f"Successfully merged {len(component_names)} components into {output_file}") From 37f9541f322d3ccee1c232df8b2a9a503165d41a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 08:14:36 -1000 Subject: [PATCH 1477/2030] [api] Fix ProtoMessage protected destructor compile error on host platform (#14882) --- esphome/components/api/proto.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index d1c955b1fb..44d8f04585 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -442,8 +442,12 @@ class ProtoMessage { virtual const char *message_name() const { return "unknown"; } #endif +#ifndef USE_HOST protected: +#endif // Non-virtual destructor is protected to prevent polymorphic deletion. + // On host platform, made public to allow value-initialization of std::array + // members (e.g. DeviceInfoResponse::devices) without clang errors. ~ProtoMessage() = default; }; From c5d42b05696f0238929447fcbb3db6ba1018ae82 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:18:49 -0400 Subject: [PATCH 1478/2030] [speaker] Fix media playlist using announcement delay (#14889) --- .../components/speaker/media_player/speaker_media_player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 9f168f854d..930373c6fc 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -417,7 +417,7 @@ void SpeakerMediaPlayer::loop() { this->media_playlist_.pop_front(); } // Only delay starting playback if moving on the next playlist item or repeating the current item - timeout_ms = this->announcement_playlist_delay_ms_; + timeout_ms = this->media_playlist_delay_ms_; } if (!this->media_playlist_.empty()) { PlaylistItem playlist_item = this->media_playlist_.front(); From 4122fa5dddaea6b354592dd41e20ad6179223b76 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 09:58:05 -1000 Subject: [PATCH 1479/2030] [core] Add back deprecated set_internal() for external projects (#14887) --- esphome/core/entity_base.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index cccbafd2c3..723bf54584 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -100,6 +100,14 @@ class EntityBase { // Get whether this Entity should be hidden outside ESPHome bool is_internal() const { return this->flags_.internal; } + // Deprecated: Calling set_internal() at runtime is undefined behavior. Components and clients + // are NOT notified of the change, the flag may have already been read during setup, and there + // is NO guarantee any consumer will observe the new value. Use the 'internal:' YAML key instead. + ESPDEPRECATED("set_internal() is undefined behavior at runtime — components and Home Assistant are NOT " + "notified. Use the 'internal:' YAML key instead. Will be removed in 2027.3.0.", + "2026.3.0") + void set_internal(bool internal) { this->flags_.internal = internal; } + // Check if this object is declared to be disabled by default. // That means that when the device gets added to Home Assistant (or other clients) it should // not be added to the default view by default, and a user action is necessary to manually add it. From 1b70df2c1f8a9a7edbc3b389fe6095ddd7e9f2b3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:16:44 -1000 Subject: [PATCH 1480/2030] [espnow] Fix EventPool/LockFreeQueue sizing off-by-one (#14893) --- esphome/components/espnow/espnow_component.cpp | 6 ++++-- esphome/components/espnow/espnow_component.h | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index 991803d870..78916891f4 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -87,7 +87,8 @@ void on_send_report(const uint8_t *mac_addr, esp_now_send_status_t status) // Push the packet to the queue global_esp_now->receive_packet_queue_.push(packet); - // Push always because we're the only producer and the pool ensures we never exceed queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. // Wake main loop immediately to process ESP-NOW send event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) @@ -109,7 +110,8 @@ void on_data_received(const esp_now_recv_info_t *info, const uint8_t *data, int // Push the packet to the queue global_esp_now->receive_packet_queue_.push(packet); - // Push always because we're the only producer and the pool ensures we never exceed queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. // Wake main loop immediately to process ESP-NOW receive event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) diff --git a/esphome/components/espnow/espnow_component.h b/esphome/components/espnow/espnow_component.h index 9941e97227..ee4adc1b4d 100644 --- a/esphome/components/espnow/espnow_component.h +++ b/esphome/components/espnow/espnow_component.h @@ -163,10 +163,14 @@ class ESPNowComponent : public Component { uint8_t own_address_[ESP_NOW_ETH_ALEN]{0}; LockFreeQueue<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE> receive_packet_queue_{}; - EventPool<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE> receive_packet_pool_{}; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<ESPNowPacket, MAX_ESP_NOW_RECEIVE_QUEUE_SIZE - 1> receive_packet_pool_{}; LockFreeQueue<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE> send_packet_queue_{}; - EventPool<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE> send_packet_pool_{}; + // Pool sized to queue capacity (SIZE-1) — see receive_packet_pool_ comment. + EventPool<ESPNowSendPacket, MAX_ESP_NOW_SEND_QUEUE_SIZE - 1> send_packet_pool_{}; ESPNowSendPacket *current_send_packet_{nullptr}; // Currently sending packet, nullptr if none uint8_t wifi_channel_{0}; From 8caa11dcf45aed498be5ec8ef83611be86b9a547 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:17:43 -1000 Subject: [PATCH 1481/2030] [usb_cdc_acm] Fix EventPool/LockFreeQueue sizing off-by-one (#14894) --- .../components/usb_cdc_acm/usb_cdc_acm.cpp | 26 +++++++------------ esphome/components/usb_cdc_acm/usb_cdc_acm.h | 6 ++++- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp index a4c2e6c4a4..253626f0a3 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp @@ -26,16 +26,13 @@ void USBCDCACMInstance::queue_line_state_event(bool dtr, bool rts) { event->data.line_state.dtr = dtr; event->data.line_state.rts = rts; - if (!this->event_queue_.push(event)) { - ESP_LOGW(TAG, "Event queue full, line state event dropped (itf=%d)", this->itf_); - // Return event to pool since we couldn't queue it - this->event_pool_.release(event); - } else { - // Wake main loop immediately to process event + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->event_queue_.push(event); + #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); + App.wake_loop_threadsafe(); #endif - } } void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, @@ -53,16 +50,13 @@ void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_ event->data.line_coding.parity = parity; event->data.line_coding.data_bits = data_bits; - if (!this->event_queue_.push(event)) { - ESP_LOGW(TAG, "Event queue full, line coding event dropped (itf=%d)", this->itf_); - // Return event to pool since we couldn't queue it - this->event_pool_.release(event); - } else { - // Wake main loop immediately to process event + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->event_queue_.push(event); + #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - App.wake_loop_threadsafe(); + App.wake_loop_threadsafe(); #endif - } } void USBCDCACMInstance::process_events_() { diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index 624f41cf8c..90c673a89e 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -102,7 +102,11 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC LineStateCallback line_state_callback_{nullptr}; // Lock-free queue and event pool for cross-task event passing - EventPool<CDCEvent, EVENT_QUEUE_SIZE> event_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing both a pool slot leak and an SPSC + // violation on the pool's internal free list. + EventPool<CDCEvent, EVENT_QUEUE_SIZE - 1> event_pool_; LockFreeQueue<CDCEvent, EVENT_QUEUE_SIZE> event_queue_; }; From 3bde7ec978f2d691586700ab107cff59a0f014c9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:17:59 -1000 Subject: [PATCH 1482/2030] [usb_host] Fix EventPool/LockFreeQueue sizing off-by-one (#14896) --- esphome/components/usb_host/usb_host.h | 5 ++++- esphome/components/usb_host/usb_host_client.cpp | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/usb_host/usb_host.h b/esphome/components/usb_host/usb_host.h index 2eec0c9699..dcb76a3a3b 100644 --- a/esphome/components/usb_host/usb_host.h +++ b/esphome/components/usb_host/usb_host.h @@ -144,7 +144,10 @@ class USBClient : public Component { // Lock-free event queue and pool for USB task to main loop communication // Must be public for access from static callbacks LockFreeQueue<UsbEvent, USB_EVENT_QUEUE_SIZE> event_queue; - EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE> event_pool; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<UsbEvent, USB_EVENT_QUEUE_SIZE - 1> event_pool; protected: // Process USB events from the queue. Returns true if any work was done. diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 2a460d1a07..18d938344c 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -193,7 +193,8 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * return; } - // Push to lock-free queue (always succeeds since pool size == queue size) + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. client->event_queue.push(event); // Re-enable component loop to process the queued event From 6154b673c2b6d25d05ec899731d3f4abd171f033 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:18:31 -1000 Subject: [PATCH 1483/2030] [usb_uart] Fix EventPool/LockFreeQueue sizing off-by-one (#14895) --- esphome/components/usb_uart/usb_uart.cpp | 11 +++++------ esphome/components/usb_uart/usb_uart.h | 8 ++++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 3d35f368fb..7c4358fdbd 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -160,11 +160,9 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { size_t chunk_len = std::min(len, UsbOutputChunk::MAX_CHUNK_SIZE); memcpy(chunk->data, data, chunk_len); chunk->length = static_cast<uint8_t>(chunk_len); - if (!this->output_queue_.push(chunk)) { - this->output_pool_.release(chunk); - ESP_LOGE(TAG, "Output queue full - lost %zu bytes", len); - break; - } + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + this->output_queue_.push(chunk); data += chunk_len; len -= chunk_len; } @@ -320,7 +318,8 @@ void USBUartComponent::start_input(USBUartChannel *channel) { chunk->channel = channel; // Push to lock-free queue for main loop processing - // Push always succeeds because pool size == queue size + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. this->usb_data_queue_.push(chunk); // Re-enable component loop to process the queued data diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 16469df7f6..7a06b04f11 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -158,7 +158,10 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon // Larger structures first (8+ bytes) RingBuffer input_buffer_; LockFreeQueue<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_queue_; - EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT> output_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements. This guarantees allocate() returns nullptr + // before push() can fail, preventing a pool slot leak. + EventPool<UsbOutputChunk, USB_OUTPUT_CHUNK_COUNT - 1> output_pool_; std::function<void()> rx_callback_{}; CdcEps cdc_dev_{}; StringRef debug_prefix_{}; @@ -190,7 +193,8 @@ class USBUartComponent : public usb_host::USBClient { // Lock-free data transfer from USB task to main loop static constexpr int USB_DATA_QUEUE_SIZE = 32; LockFreeQueue<UsbDataChunk, USB_DATA_QUEUE_SIZE> usb_data_queue_; - EventPool<UsbDataChunk, USB_DATA_QUEUE_SIZE> chunk_pool_; + // Pool sized to queue capacity (SIZE-1) — see USBUartChannel::output_pool_ comment. + EventPool<UsbDataChunk, USB_DATA_QUEUE_SIZE - 1> chunk_pool_; protected: std::vector<USBUartChannel *> channels_{}; From ccf672d7ee37389dcd85f46f49ca0a5b5471f3d0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 12:24:02 -1000 Subject: [PATCH 1484/2030] [esp32_ble] Fix EventPool/LockFreeQueue sizing off-by-one (#14892) --- esphome/components/esp32_ble/ble.cpp | 3 ++- esphome/components/esp32_ble/ble.h | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index ff9d9bb15a..fee1c546be 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -575,8 +575,9 @@ template<typename... Args> void enqueue_ble_event(Args... args) { load_ble_event(event, args...); // Push the event to the queue + // Push always succeeds: pool is sized to queue capacity (N-1), so if + // allocate() returned non-null, the queue is guaranteed to have room. global_ble->ble_events_.push(event); - // Push always succeeds because we're the only producer and the pool ensures we never exceed queue size } // Explicit template instantiations for the friend function diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 04bec3f785..752ddc9d1f 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -221,7 +221,13 @@ class ESP32BLE : public Component { // Large objects (size depends on template parameters, but typically aligned to 4 bytes) esphome::LockFreeQueue<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_events_; - esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE> ble_event_pool_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements (one slot distinguishes full from empty). + // This guarantees allocate() returns nullptr before push() can fail, which: + // 1. Prevents leaking a pool slot (the Nth allocate succeeds but push fails) + // 2. Avoids needing release() on the producer path after a failed push(), + // preserving the SPSC contract on the pool's internal free list + esphome::EventPool<BLEEvent, MAX_BLE_QUEUE_SIZE - 1> ble_event_pool_; // 4-byte aligned members #ifdef USE_ESP32_BLE_ADVERTISING From 80bd6489cf12c6eadafe02604facb7f841cc5600 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:38:41 -1000 Subject: [PATCH 1485/2030] [esp32_ble_server] Remove vestigial semaphore from BLECharacteristic (#14900) --- .../components/esp32_ble_server/ble_characteristic.cpp | 10 +--------- .../components/esp32_ble_server/ble_characteristic.h | 4 ---- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/esphome/components/esp32_ble_server/ble_characteristic.cpp b/esphome/components/esp32_ble_server/ble_characteristic.cpp index 1806354712..aa82b773ba 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.cpp +++ b/esphome/components/esp32_ble_server/ble_characteristic.cpp @@ -16,13 +16,9 @@ BLECharacteristic::~BLECharacteristic() { for (auto *descriptor : this->descriptors_) { delete descriptor; // NOLINT(cppcoreguidelines-owning-memory) } - vSemaphoreDelete(this->set_value_lock_); } BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) : uuid_(uuid) { - this->set_value_lock_ = xSemaphoreCreateBinary(); - xSemaphoreGive(this->set_value_lock_); - this->properties_ = (esp_gatt_char_prop_t) 0; this->set_broadcast_property((properties & PROPERTY_BROADCAST) != 0); @@ -35,11 +31,7 @@ BLECharacteristic::BLECharacteristic(const ESPBTUUID uuid, uint32_t properties) void BLECharacteristic::set_value(ByteBuffer buffer) { this->set_value(buffer.get_data()); } -void BLECharacteristic::set_value(std::vector<uint8_t> &&buffer) { - xSemaphoreTake(this->set_value_lock_, 0L); - this->value_ = std::move(buffer); - xSemaphoreGive(this->set_value_lock_); -} +void BLECharacteristic::set_value(std::vector<uint8_t> &&buffer) { this->value_ = std::move(buffer); } void BLECharacteristic::set_value(std::initializer_list<uint8_t> data) { this->set_value(std::vector<uint8_t>(data)); // Delegate to move overload diff --git a/esphome/components/esp32_ble_server/ble_characteristic.h b/esphome/components/esp32_ble_server/ble_characteristic.h index 72897d1dfb..062052cdf8 100644 --- a/esphome/components/esp32_ble_server/ble_characteristic.h +++ b/esphome/components/esp32_ble_server/ble_characteristic.h @@ -16,8 +16,6 @@ #include <esp_gattc_api.h> #include <esp_gatts_api.h> #include <esp_bt_defs.h> -#include <freertos/FreeRTOS.h> -#include <freertos/semphr.h> namespace esphome { namespace esp32_ble_server { @@ -84,8 +82,6 @@ class BLECharacteristic { uint16_t value_read_offset_{0}; std::vector<uint8_t> value_; - SemaphoreHandle_t set_value_lock_; - std::vector<BLEDescriptor *> descriptors_; struct ClientNotificationEntry { From be2e4a5278a83155fa3128e68c4b9824c311f1cf Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 13:49:24 -1000 Subject: [PATCH 1486/2030] [mqtt] Fix data race on inbound event queue (#14891) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- .../components/mqtt/mqtt_backend_esp32.cpp | 34 ++++++--- esphome/components/mqtt/mqtt_backend_esp32.h | 69 +++++++++++-------- 2 files changed, 66 insertions(+), 37 deletions(-) diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index 5642fd5f7b..ab067c4418 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -82,10 +82,16 @@ bool MQTTBackendESP32::initialize_() { void MQTTBackendESP32::loop() { // process new events // handle only 1 message per loop iteration - if (!mqtt_events_.empty()) { - auto &event = mqtt_events_.front(); - mqtt_event_handler_(event); - mqtt_events_.pop(); + Event *event = this->mqtt_event_queue_.pop(); + if (event != nullptr) { + this->mqtt_event_handler_(*event); + this->mqtt_event_pool_.release(event); + } + + // Log dropped inbound events (check is cheap - single atomic load in common case) + uint16_t inbound_dropped = this->mqtt_event_queue_.get_and_reset_dropped_count(); + if (inbound_dropped > 0) { + ESP_LOGW(TAG, "Dropped %u inbound MQTT events", inbound_dropped); } #if defined(USE_MQTT_IDF_ENQUEUE) @@ -183,10 +189,18 @@ void MQTTBackendESP32::mqtt_event_handler_(const Event &event) { void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { MQTTBackendESP32 *instance = static_cast<MQTTBackendESP32 *>(handler_args); - // queue event to decouple processing + // queue event to decouple processing from ESP-IDF MQTT task to main loop if (instance) { - auto event = *static_cast<esp_mqtt_event_t *>(event_data); - instance->mqtt_events_.emplace(event); + auto *event = instance->mqtt_event_pool_.allocate(); + if (event == nullptr) { + // Pool exhausted, drop event (counted via queue's dropped counter) + instance->mqtt_event_queue_.increment_dropped_count(); + return; + } + event->populate(*static_cast<esp_mqtt_event_t *>(event_data)); + // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if + // allocate() returned non-null, the queue cannot be full. + instance->mqtt_event_queue_.push(event); // Wake main loop immediately to process MQTT event instead of waiting for select() timeout #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) @@ -226,14 +240,14 @@ void MQTTBackendESP32::esphome_mqtt_task(void *params) { break; } } - this_mqtt->mqtt_event_pool_.release(elem); + this_mqtt->mqtt_outbound_pool_.release(elem); } } } bool MQTTBackendESP32::enqueue_(MqttQueueTypeT type, const char *topic, int qos, bool retain, const char *payload, size_t len) { - auto *elem = this->mqtt_event_pool_.allocate(); + auto *elem = this->mqtt_outbound_pool_.allocate(); if (!elem) { // Queue is full - increment counter but don't log immediately. @@ -253,7 +267,7 @@ bool MQTTBackendESP32::enqueue_(MqttQueueTypeT type, const char *topic, int qos, // Use the helper to allocate and copy data if (!elem->set_data(topic, payload, len)) { // Allocation failed, return elem to pool - this->mqtt_event_pool_.release(elem); + this->mqtt_outbound_pool_.release(elem); // Increment counter without logging to avoid cascade effect during memory pressure this->mqtt_queue_.increment_dropped_count(); return false; diff --git a/esphome/components/mqtt/mqtt_backend_esp32.h b/esphome/components/mqtt/mqtt_backend_esp32.h index 5c4dc413bd..58d1b29b32 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.h +++ b/esphome/components/mqtt/mqtt_backend_esp32.h @@ -5,7 +5,6 @@ #ifdef USE_ESP32 #include <string> -#include <queue> #include <cstring> #include <mqtt_client.h> #include <freertos/FreeRTOS.h> @@ -18,32 +17,39 @@ namespace esphome::mqtt { struct Event { - esp_mqtt_event_id_t event_id; + esp_mqtt_event_id_t event_id{}; std::vector<char> data; - int total_data_len; - int current_data_offset; + int total_data_len{0}; + int current_data_offset{0}; std::string topic; - int msg_id; - bool retain; - int qos; - bool dup; - bool session_present; - esp_mqtt_error_codes_t error_handle; + int msg_id{0}; + bool retain{false}; + int qos{0}; + bool dup{false}; + bool session_present{false}; + esp_mqtt_error_codes_t error_handle{}; - // Construct from esp_mqtt_event_t - // Any pointer values that are unsafe to keep are converted to safe copies - Event(const esp_mqtt_event_t &event) - : event_id(event.event_id), - data(event.data, event.data + event.data_len), - total_data_len(event.total_data_len), - current_data_offset(event.current_data_offset), - topic(event.topic, event.topic_len), - msg_id(event.msg_id), - retain(event.retain), - qos(event.qos), - dup(event.dup), - session_present(event.session_present), - error_handle(*event.error_handle) {} + // Populate from esp_mqtt_event_t + // Copies pointer-based data to owned storage for safe cross-thread transfer + void populate(const esp_mqtt_event_t &event) { + this->event_id = event.event_id; + this->data.assign(event.data, event.data + event.data_len); + this->total_data_len = event.total_data_len; + this->current_data_offset = event.current_data_offset; + this->topic.assign(event.topic, event.topic_len); + this->msg_id = event.msg_id; + this->retain = event.retain; + this->qos = event.qos; + this->dup = event.dup; + this->session_present = event.session_present; + this->error_handle = *event.error_handle; + } + + // Release owned resources for pool reuse (keeps allocated capacity for efficiency) + void release() { + this->data.clear(); + this->topic.clear(); + } }; enum MqttQueueTypeT : uint8_t { @@ -118,7 +124,8 @@ class MQTTBackendESP32 final : public MQTTBackend { static constexpr size_t TASK_STACK_SIZE = 3072; static constexpr size_t TASK_STACK_SIZE_TLS = 4096; // Larger stack for TLS operations static constexpr ssize_t TASK_PRIORITY = 5; - static constexpr uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 + static constexpr uint8_t MQTT_QUEUE_LENGTH = 30; // 30*12 bytes = 360 + static constexpr uint8_t MQTT_EVENT_QUEUE_LENGTH = 32; // Inbound events from broker void set_keep_alive(uint16_t keep_alive) final { this->keep_alive_ = keep_alive; } void set_client_id(const char *client_id) final { this->client_id_ = client_id; } @@ -251,7 +258,8 @@ class MQTTBackendESP32 final : public MQTTBackend { bool skip_cert_cn_check_{false}; #if defined(USE_MQTT_IDF_ENQUEUE) static void esphome_mqtt_task(void *params); - EventPool<struct QueueElement, MQTT_QUEUE_LENGTH> mqtt_event_pool_; + // Pool sized to queue capacity (SIZE-1) — see mqtt_event_pool_ comment. + EventPool<struct QueueElement, MQTT_QUEUE_LENGTH - 1> mqtt_outbound_pool_; NotifyingLockFreeQueue<struct QueueElement, MQTT_QUEUE_LENGTH> mqtt_queue_; TaskHandle_t task_handle_{nullptr}; bool enqueue_(MqttQueueTypeT type, const char *topic, int qos = 0, bool retain = false, const char *payload = NULL, @@ -266,7 +274,14 @@ class MQTTBackendESP32 final : public MQTTBackend { CallbackManager<on_message_callback_t> on_message_; CallbackManager<on_publish_user_callback_t> on_publish_; std::string cached_topic_; - std::queue<Event> mqtt_events_; + // Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring + // buffer that holds N-1 elements (one slot distinguishes full from empty). + // This guarantees allocate() returns nullptr before push() can fail, which: + // 1. Prevents leaking a pool slot (the Nth allocate succeeds but push fails) + // 2. Avoids needing release() on the producer path after a failed push(), + // preserving the SPSC contract on the pool's internal free list + EventPool<Event, MQTT_EVENT_QUEUE_LENGTH - 1> mqtt_event_pool_; + LockFreeQueue<Event, MQTT_EVENT_QUEUE_LENGTH> mqtt_event_queue_; #if defined(USE_MQTT_IDF_ENQUEUE) uint32_t last_dropped_log_time_{0}; From 0fa96b6e1ea76b46a19d8cc4f847dcea3606452a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 14:19:31 -1000 Subject: [PATCH 1487/2030] [scheduler] Fix UB in cross-thread counter/vector reads, add atomic fast-path (#14880) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/core/scheduler.cpp | 48 ++++++----- esphome/core/scheduler.h | 159 ++++++++++++++++++++++++++++++++++--- 2 files changed, 177 insertions(+), 30 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 63e1006b03..8c4ff0ddb5 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -211,6 +211,14 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); } target->push_back(item); + if (target == &this->to_add_) { + this->to_add_count_increment_(); + } +#ifndef ESPHOME_THREAD_SINGLE + else { + this->defer_count_increment_(); + } +#endif } void HOT Scheduler::set_timeout(Component *component, const char *name, uint32_t timeout, @@ -387,7 +395,7 @@ optional<uint32_t> HOT Scheduler::next_schedule_in(uint32_t now) { // safe when called from the main thread. Other threads must not call this method. // If no items, return empty optional - if (this->cleanup_() == 0) + if (!this->cleanup_()) return {}; SchedulerItem *item = this->items_[0]; @@ -421,7 +429,7 @@ void Scheduler::full_cleanup_removed_items_() { this->items_.erase(this->items_.begin() + write, this->items_.end()); // Rebuild the heap structure since items are no longer in heap order std::make_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); - this->to_remove_ = 0; + this->to_remove_clear_(); } #ifndef ESPHOME_THREAD_SINGLE @@ -502,7 +510,7 @@ void HOT Scheduler::call(uint32_t now) { // If we still have too many cancelled items, do a full cleanup // This only happens if cancelled items are stuck in the middle/bottom of the heap - if (this->to_remove_ >= MAX_LOGICALLY_DELETED_ITEMS) { + if (this->to_remove_count_() >= MAX_LOGICALLY_DELETED_ITEMS) { this->full_cleanup_removed_items_(); } while (!this->items_.empty()) { @@ -529,7 +537,7 @@ void HOT Scheduler::call(uint32_t now) { LockGuard guard{this->lock_}; if (is_item_removed_locked_(item)) { this->recycle_item_main_loop_(this->pop_raw_locked_()); - this->to_remove_--; + this->to_remove_decrement_(); continue; } } @@ -538,7 +546,7 @@ void HOT Scheduler::call(uint32_t now) { if (is_item_removed_(item)) { LockGuard guard{this->lock_}; this->recycle_item_main_loop_(this->pop_raw_locked_()); - this->to_remove_--; + this->to_remove_decrement_(); continue; } #endif @@ -566,7 +574,7 @@ void HOT Scheduler::call(uint32_t now) { if (this->is_item_removed_locked_(executed_item)) { // We were removed/cancelled in the function call, recycle and continue - this->to_remove_--; + this->to_remove_decrement_(); this->recycle_item_main_loop_(executed_item); continue; } @@ -576,6 +584,7 @@ void HOT Scheduler::call(uint32_t now) { // Add new item directly to to_add_ // since we have the lock held this->to_add_.push_back(executed_item); + this->to_add_count_increment_(); } else { // Timeout completed - recycle it this->recycle_item_main_loop_(executed_item); @@ -604,6 +613,10 @@ void HOT Scheduler::call(uint32_t now) { #endif } void HOT Scheduler::process_to_add() { + // Fast path: skip lock acquisition when nothing to add. + // Worst case is a one-loop-iteration delay before newly added items are processed. + if (this->to_add_empty_()) + return; LockGuard guard{this->lock_}; for (auto *&it : this->to_add_) { if (is_item_removed_locked_(it)) { @@ -617,17 +630,14 @@ void HOT Scheduler::process_to_add() { std::push_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); } this->to_add_.clear(); + this->to_add_count_clear_(); } -size_t HOT Scheduler::cleanup_() { - // Fast path: if nothing to remove, just return the current size - // Reading to_remove_ without lock is safe because: - // 1. We only call this from the main thread during call() - // 2. If it's 0, there's definitely nothing to cleanup - // 3. If it becomes non-zero after we check, cleanup will happen on the next loop iteration - // 4. Not all platforms support atomics, so we accept this race in favor of performance - // 5. The worst case is a one-loop-iteration delay in cleanup, which is harmless - if (this->to_remove_ == 0) - return this->items_.size(); +bool HOT Scheduler::cleanup_() { + // Fast path: if nothing to remove, just check if items exist. + // Uses atomic load on platforms with atomics, falls back to always taking the lock otherwise. + // Worst case is a one-loop-iteration delay in cleanup. + if (this->to_remove_empty_()) + return !this->items_.empty(); // We must hold the lock for the entire cleanup operation because: // 1. We're modifying items_ (via pop_raw_locked_) which requires exclusive access @@ -642,10 +652,10 @@ size_t HOT Scheduler::cleanup_() { SchedulerItem *item = this->items_[0]; if (!this->is_item_removed_locked_(item)) break; - this->to_remove_--; + this->to_remove_decrement_(); this->recycle_item_main_loop_(this->pop_raw_locked_()); } - return this->items_.size(); + return !this->items_.empty(); } Scheduler::SchedulerItem *HOT Scheduler::pop_raw_locked_() { std::pop_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); @@ -698,7 +708,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_, component, name_type, static_name, hash_or_id, type, match_retry); total_cancelled += heap_cancelled; - this->to_remove_ += heap_cancelled; + this->to_remove_add_(heap_cancelled); } // Cancel items in to_add_ diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 0476513bb9..e545055fca 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -284,9 +284,9 @@ class Scheduler { #endif } // Cleanup logically deleted items from the scheduler - // Returns the number of items remaining after cleanup + // Returns true if items remain after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). - size_t cleanup_(); + bool cleanup_(); // Remove and return the front item from the heap as a raw pointer. // Caller takes ownership and must either recycle or delete the item. // IMPORTANT: Caller must hold the scheduler lock before calling this function. @@ -395,15 +395,9 @@ class Scheduler { // erase() on every pop, which would be O(n). The queue is processed once per loop - // any items added during processing are left for the next loop iteration. - // Snapshot the queue end point - only process items that existed at loop start - // Items added during processing (by callbacks or other threads) run next loop - // No lock needed: single consumer (main loop), stale read just means we process less this iteration - size_t defer_queue_end = this->defer_queue_.size(); - // Fast path: nothing to process, avoid lock entirely. - // Safe without lock: single consumer (main loop) reads front_, and a stale size() read - // from a concurrent push can only make us see fewer items — they'll be processed next loop. - if (this->defer_queue_front_ >= defer_queue_end) + // Worst case is a one-loop-iteration delay before newly deferred items are processed. + if (this->defer_empty_()) return; // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), @@ -412,6 +406,13 @@ class Scheduler { SchedulerItem *item; this->lock_.lock(); + // Reset counter and snapshot queue end under lock + this->defer_count_clear_(); + size_t defer_queue_end = this->defer_queue_.size(); + if (this->defer_queue_front_ >= defer_queue_end) { + this->lock_.unlock(); + return; + } while (this->defer_queue_front_ < defer_queue_end) { // Take ownership of the item, leaving nullptr in the vector slot. // This is safe because: @@ -527,14 +528,150 @@ class Scheduler { Mutex lock_; std::vector<SchedulerItem *> items_; std::vector<SchedulerItem *> to_add_; + +#ifndef ESPHOME_THREAD_SINGLE + // Fast-path counter for process_to_add() to skip taking the lock when there is + // nothing to add. Uses std::atomic on platforms that support it, plain uint32_t + // otherwise. On non-atomic platforms, callers must hold the scheduler lock when + // mutating this counter. Not needed on single-threaded platforms where we can + // check to_add_.empty() directly. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> to_add_count_{0}; +#else + uint32_t to_add_count_{0}; +#endif +#endif /* ESPHOME_THREAD_SINGLE */ + + // Fast-path helper for process_to_add() to decide if it can try the lock-free path. + // - On ESPHOME_THREAD_SINGLE: direct container check is safe (no concurrent writers). + // - On ESPHOME_THREAD_MULTI_ATOMICS: performs a lock-free check via to_add_count_. + // - On ESPHOME_THREAD_MULTI_NO_ATOMICS: always returns false to force the caller + // down the locked path; this is NOT a lock-free emptiness check on that platform. + bool to_add_empty_() const { +#ifdef ESPHOME_THREAD_SINGLE + return this->to_add_.empty(); +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + return this->to_add_count_.load(std::memory_order_relaxed) == 0; +#else + return false; +#endif + } + + // Increment to_add_count_ (no-op on single-threaded platforms) + void to_add_count_increment_() { +#ifdef ESPHOME_THREAD_SINGLE + // No counter needed — to_add_empty_() checks the vector directly +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + this->to_add_count_.fetch_add(1, std::memory_order_relaxed); +#else + this->to_add_count_++; +#endif + } + + // Reset to_add_count_ (no-op on single-threaded platforms) + void to_add_count_clear_() { +#ifdef ESPHOME_THREAD_SINGLE + // No counter needed — to_add_empty_() checks the vector directly +#elif defined(ESPHOME_THREAD_MULTI_ATOMICS) + this->to_add_count_.store(0, std::memory_order_relaxed); +#else + this->to_add_count_ = 0; +#endif + } + #ifndef ESPHOME_THREAD_SINGLE // Single-core platforms don't need the defer queue and save ~32 bytes of RAM // Using std::vector instead of std::deque avoids 512-byte chunked allocations // Index tracking avoids O(n) erase() calls when draining the queue each loop std::vector<SchedulerItem *> defer_queue_; // FIFO queue for defer() calls size_t defer_queue_front_{0}; // Index of first valid item in defer_queue_ (tracks consumed items) -#endif /* ESPHOME_THREAD_SINGLE */ + + // Fast-path counter for process_defer_queue_() to skip lock when nothing to process. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> defer_count_{0}; +#else + uint32_t defer_count_{0}; +#endif + + bool defer_empty_() const { + // defer_queue_ only exists on multi-threaded platforms, so no ESPHOME_THREAD_SINGLE path + // ESPHOME_THREAD_MULTI_NO_ATOMICS: always take the lock +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->defer_count_.load(std::memory_order_relaxed) == 0; +#else + return false; +#endif + } + + void defer_count_increment_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->defer_count_.fetch_add(1, std::memory_order_relaxed); +#else + this->defer_count_++; +#endif + } + + void defer_count_clear_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->defer_count_.store(0, std::memory_order_relaxed); +#else + this->defer_count_ = 0; +#endif + } + +#endif /* ESPHOME_THREAD_SINGLE */ + + // Counter for items marked for removal. Incremented cross-thread in cancel_item_locked_(). + // On ESPHOME_THREAD_MULTI_ATOMICS this is read without a lock in the cleanup_() fast path; + // on ESPHOME_THREAD_MULTI_NO_ATOMICS the fast path is disabled so cleanup_() always takes the lock. +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + std::atomic<uint32_t> to_remove_{0}; +#else uint32_t to_remove_{0}; +#endif + + // Lock-free check if there are items to remove (for fast-path in cleanup_) + bool to_remove_empty_() const { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->to_remove_.load(std::memory_order_relaxed) == 0; +#elif defined(ESPHOME_THREAD_SINGLE) + return this->to_remove_ == 0; +#else + return false; // Always take the lock path +#endif + } + + void to_remove_add_(uint32_t count) { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.fetch_add(count, std::memory_order_relaxed); +#else + this->to_remove_ += count; +#endif + } + + void to_remove_decrement_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.fetch_sub(1, std::memory_order_relaxed); +#else + this->to_remove_--; +#endif + } + + void to_remove_clear_() { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + this->to_remove_.store(0, std::memory_order_relaxed); +#else + this->to_remove_ = 0; +#endif + } + + uint32_t to_remove_count_() const { +#ifdef ESPHOME_THREAD_MULTI_ATOMICS + return this->to_remove_.load(std::memory_order_relaxed); +#else + return this->to_remove_; +#endif + } // Memory pool for recycling SchedulerItem objects to reduce heap churn. // Design decisions: From 5cc03d9befb7326fe708e7368778416eddd47253 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 18 Mar 2026 13:35:21 +1300 Subject: [PATCH 1488/2030] Bump version to 2026.3.0b4 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 96295b3fc8..ea34106f36 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0b3 +PROJECT_NUMBER = 2026.3.0b4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 561a27d228..4ba8b1a23f 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0b3" +__version__ = "2026.3.0b4" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 3e845d387a482db37a7c4dfea4692b974ffa9566 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 17 Mar 2026 14:44:17 -1000 Subject: [PATCH 1489/2030] [tests] Fix test_show_logs_serial taking 30s due to unmocked serial port wait (#14903) --- tests/unit_tests/test_main.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index b853461151..5e36c06bb3 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -167,6 +167,13 @@ def mock_run_miniterm() -> Generator[Mock]: yield mock +@pytest.fixture +def mock_wait_for_serial_port() -> Generator[Mock]: + """Mock _wait_for_serial_port for testing.""" + with patch("esphome.__main__._wait_for_serial_port") as mock: + yield mock + + @pytest.fixture def mock_upload_using_esptool() -> Generator[Mock]: """Mock upload_using_esptool for testing.""" @@ -1706,6 +1713,7 @@ def test_show_logs_serial( mock_get_port_type: Mock, mock_check_permissions: Mock, mock_run_miniterm: Mock, + mock_wait_for_serial_port: Mock, ) -> None: """Test show_logs with serial port.""" setup_core(config={"logger": {}}, platform=PLATFORM_ESP32) From 2531fb1a021cf30e238754de5194e77a05be1800 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:12:13 -0400 Subject: [PATCH 1490/2030] [voice_assistant][micro_wake_word] Fix null deref and missing error return (#14906) --- esphome/components/micro_wake_word/streaming_model.cpp | 1 + esphome/components/voice_assistant/voice_assistant.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/esphome/components/micro_wake_word/streaming_model.cpp b/esphome/components/micro_wake_word/streaming_model.cpp index 47d2c70e13..0ab6cd3772 100644 --- a/esphome/components/micro_wake_word/streaming_model.cpp +++ b/esphome/components/micro_wake_word/streaming_model.cpp @@ -80,6 +80,7 @@ bool StreamingModel::load_model_() { TfLiteTensor *output = this->interpreter_->output(0); if ((output->dims->size != 2) || (output->dims->data[0] != 1) || (output->dims->data[1] != 1)) { ESP_LOGE(TAG, "Streaming model tensor output dimension is not 1x1."); + return false; } if (output->type != kTfLiteUInt8) { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 51d52a8af8..15124e422f 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -619,6 +619,8 @@ void VoiceAssistant::start_playback_timeout_() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::RESPONSE_FINISHED, State::RESPONSE_FINISHED); + if (this->api_client_ == nullptr) + return; api::VoiceAssistantAnnounceFinished msg; msg.success = true; this->api_client_->send_message(msg); From 16c52243416332d18f2ff066c378b2968dbd5083 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 07:48:43 -0400 Subject: [PATCH 1491/2030] [tc74][apds9960] Fix signed temperature and FIFO register address (#14907) --- esphome/components/apds9960/apds9960.cpp | 8 ++++---- esphome/components/tc74/tc74.cpp | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/esphome/components/apds9960/apds9960.cpp b/esphome/components/apds9960/apds9960.cpp index 260de82d14..a07175f2c9 100644 --- a/esphome/components/apds9960/apds9960.cpp +++ b/esphome/components/apds9960/apds9960.cpp @@ -251,11 +251,11 @@ void APDS9960::read_gesture_data_() { uint8_t buf[128]; for (uint8_t pos = 0; pos < fifo_level * 4; pos += 32) { - // The ESP's i2c driver has a limited buffer size. - // This way of retrieving the data should be wrong according to the datasheet - // but it seems to work. + // Read in 32-byte chunks due to ESP8266 I2C buffer limit. + // Always read from 0xFC — the FIFO auto-increments through 0xFC-0xFF + // and advances its internal pointer after every 4th byte. uint8_t read = std::min(32, fifo_level * 4 - pos); - APDS9960_WARNING_CHECK(this->read_bytes(0xFC + pos, buf + pos, read), "Reading FIFO buffer failed."); + APDS9960_WARNING_CHECK(this->read_bytes(0xFC, buf + pos, read), "Reading FIFO buffer failed."); } if (millis() - this->gesture_start_ > 500) { diff --git a/esphome/components/tc74/tc74.cpp b/esphome/components/tc74/tc74.cpp index 969ef3671e..cb58e583dc 100644 --- a/esphome/components/tc74/tc74.cpp +++ b/esphome/components/tc74/tc74.cpp @@ -50,8 +50,9 @@ void TC74Component::read_temperature_() { } } - uint8_t temperature_reg; - if (this->read_register(TC74_REGISTER_TEMPERATURE, &temperature_reg, 1) != i2c::ERROR_OK) { + int8_t temperature_reg; + if (this->read_register(TC74_REGISTER_TEMPERATURE, reinterpret_cast<uint8_t *>(&temperature_reg), 1) != + i2c::ERROR_OK) { this->status_set_warning(); return; } From 1d07f37d6215f35980946d5f543d97347d15e797 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:22:28 -0400 Subject: [PATCH 1492/2030] [opentherm] Migrate from legacy timer API to GPTimer API (#14859) --- esphome/components/opentherm/__init__.py | 5 +- esphome/components/opentherm/opentherm.cpp | 89 +++++++--------------- esphome/components/opentherm/opentherm.h | 18 +++-- 3 files changed, 40 insertions(+), 72 deletions(-) diff --git a/esphome/components/opentherm/__init__.py b/esphome/components/opentherm/__init__.py index 36f85a9766..85632d0bf8 100644 --- a/esphome/components/opentherm/__init__.py +++ b/esphome/components/opentherm/__init__.py @@ -81,10 +81,7 @@ CONFIG_SCHEMA = cv.All( async def to_code(config: dict[str, Any]) -> None: if CORE.is_esp32: - # Re-enable ESP-IDF's legacy driver component (excluded by default to save compile time) - # Provides driver/timer.h header for hardware timer API - # TODO: Remove this once opentherm migrates to GPTimer API (driver/gptimer.h) - include_builtin_idf_component("driver") + include_builtin_idf_component("esp_driver_gptimer") var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/opentherm/opentherm.cpp b/esphome/components/opentherm/opentherm.cpp index cdf89207bc..97cf83a5aa 100644 --- a/esphome/components/opentherm/opentherm.cpp +++ b/esphome/components/opentherm/opentherm.cpp @@ -8,10 +8,7 @@ #include "opentherm.h" #include "esphome/core/helpers.h" #include <cinttypes> -// TODO: Migrate from legacy timer API (driver/timer.h) to GPTimer API (driver/gptimer.h) -// The legacy timer API is deprecated in ESP-IDF 5.x. See opentherm.h for details. #ifdef USE_ESP32 -#include "driver/timer.h" #include "esp_err.h" #endif #ifdef ESP8266 @@ -33,10 +30,6 @@ OpenTherm *OpenTherm::instance = nullptr; OpenTherm::OpenTherm(InternalGPIOPin *in_pin, InternalGPIOPin *out_pin, int32_t device_timeout) : in_pin_(in_pin), out_pin_(out_pin), -#ifdef USE_ESP32 - timer_group_(TIMER_GROUP_0), - timer_idx_(TIMER_0), -#endif mode_(OperationMode::IDLE), error_type_(ProtocolErrorType::NO_ERROR), capture_(0), @@ -134,7 +127,12 @@ void IRAM_ATTR OpenTherm::read_() { // period in OpenTherm. } +#ifdef USE_ESP32 +bool IRAM_ATTR OpenTherm::timer_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx) { + auto *arg = static_cast<OpenTherm *>(user_ctx); +#else bool IRAM_ATTR OpenTherm::timer_isr(OpenTherm *arg) { +#endif if (arg->mode_ == OperationMode::LISTEN) { if (arg->timeout_counter_ == 0) { arg->mode_ = OperationMode::ERROR_TIMEOUT; @@ -243,67 +241,35 @@ void IRAM_ATTR OpenTherm::write_bit_(uint8_t high, uint8_t clock) { #ifdef USE_ESP32 bool OpenTherm::init_esp32_timer_() { - // Search for a free timer. Maybe unstable, we'll see. - int cur_timer = 0; - timer_group_t timer_group = TIMER_GROUP_0; - timer_idx_t timer_idx = TIMER_0; - bool timer_found = false; - - for (; cur_timer < SOC_TIMER_GROUP_TOTAL_TIMERS; cur_timer++) { - timer_config_t temp_config; - timer_group = cur_timer < 2 ? TIMER_GROUP_0 : TIMER_GROUP_1; - timer_idx = cur_timer < 2 ? (timer_idx_t) cur_timer : (timer_idx_t) (cur_timer - 2); - - auto err = timer_get_config(timer_group, timer_idx, &temp_config); - if (err == ESP_ERR_INVALID_ARG) { - // Error means timer was not initialized (or other things, but we are careful with our args) - timer_found = true; - break; - } - - ESP_LOGD(TAG, "Timer %d:%d seems to be occupied, will try another", timer_group, timer_idx); - } - - if (!timer_found) { - ESP_LOGE(TAG, "No free timer was found! OpenTherm cannot function without a timer."); - return false; - } - - ESP_LOGD(TAG, "Found free timer %d:%d", timer_group, timer_idx); - this->timer_group_ = timer_group; - this->timer_idx_ = timer_idx; - - timer_config_t const config = { - .alarm_en = TIMER_ALARM_EN, - .counter_en = TIMER_PAUSE, - .intr_type = TIMER_INTR_LEVEL, - .counter_dir = TIMER_COUNT_UP, - .auto_reload = TIMER_AUTORELOAD_EN, - .clk_src = TIMER_SRC_CLK_DEFAULT, - .divider = 80, + // 80MHz / 80 = 1MHz resolution (1µs per tick) + gptimer_config_t config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1000000, }; - esp_err_t result; - - result = timer_init(this->timer_group_, this->timer_idx_, &config); + esp_err_t result = gptimer_new_timer(&config, &this->timer_handle_); if (result != ESP_OK) { - const auto *error = esp_err_to_name(result); - ESP_LOGE(TAG, "Failed to init timer. Error: %s", error); + ESP_LOGE(TAG, "Failed to create timer: %s", esp_err_to_name(result)); return false; } - result = timer_set_counter_value(this->timer_group_, this->timer_idx_, 0); + gptimer_event_callbacks_t cbs = { + .on_alarm = OpenTherm::timer_isr, + }; + result = gptimer_register_event_callbacks(this->timer_handle_, &cbs, this); if (result != ESP_OK) { - const auto *error = esp_err_to_name(result); - ESP_LOGE(TAG, "Failed to set counter value. Error: %s", error); + ESP_LOGE(TAG, "Failed to register timer callback: %s", esp_err_to_name(result)); + gptimer_del_timer(this->timer_handle_); + this->timer_handle_ = nullptr; return false; } - result = timer_isr_callback_add(this->timer_group_, this->timer_idx_, reinterpret_cast<bool (*)(void *)>(timer_isr), - this, 0); + result = gptimer_enable(this->timer_handle_); if (result != ESP_OK) { - const auto *error = esp_err_to_name(result); - ESP_LOGE(TAG, "Failed to register timer interrupt. Error: %s", error); + ESP_LOGE(TAG, "Failed to enable timer: %s", esp_err_to_name(result)); + gptimer_del_timer(this->timer_handle_); + this->timer_handle_ = nullptr; return false; } @@ -315,12 +281,13 @@ void IRAM_ATTR OpenTherm::start_esp32_timer_(uint64_t alarm_value) { this->timer_error_ = ESP_OK; this->timer_error_type_ = TimerErrorType::NO_TIMER_ERROR; - this->timer_error_ = timer_set_alarm_value(this->timer_group_, this->timer_idx_, alarm_value); + this->alarm_config_.alarm_count = alarm_value; + this->timer_error_ = gptimer_set_alarm_action(this->timer_handle_, &this->alarm_config_); if (this->timer_error_ != ESP_OK) { this->timer_error_type_ = TimerErrorType::SET_ALARM_VALUE_ERROR; return; } - this->timer_error_ = timer_start(this->timer_group_, this->timer_idx_); + this->timer_error_ = gptimer_start(this->timer_handle_); if (this->timer_error_ != ESP_OK) { this->timer_error_type_ = TimerErrorType::TIMER_START_ERROR; } @@ -356,12 +323,12 @@ void IRAM_ATTR OpenTherm::stop_timer_() { this->timer_error_ = ESP_OK; this->timer_error_type_ = TimerErrorType::NO_TIMER_ERROR; - this->timer_error_ = timer_pause(this->timer_group_, this->timer_idx_); + this->timer_error_ = gptimer_stop(this->timer_handle_); if (this->timer_error_ != ESP_OK) { this->timer_error_type_ = TimerErrorType::TIMER_PAUSE_ERROR; return; } - this->timer_error_ = timer_set_counter_value(this->timer_group_, this->timer_idx_, 0); + this->timer_error_ = gptimer_set_raw_count(this->timer_handle_, 0); if (this->timer_error_ != ESP_OK) { this->timer_error_type_ = TimerErrorType::SET_COUNTER_VALUE_ERROR; } diff --git a/esphome/components/opentherm/opentherm.h b/esphome/components/opentherm/opentherm.h index a2c347d0d8..eb8c5b3ad6 100644 --- a/esphome/components/opentherm/opentherm.h +++ b/esphome/components/opentherm/opentherm.h @@ -12,12 +12,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -// TODO: Migrate from legacy timer API (driver/timer.h) to GPTimer API (driver/gptimer.h) -// The legacy timer API is deprecated in ESP-IDF 5.x. Migration would allow removing the -// "driver" IDF component dependency. See: -// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/release-5.x/5.0/peripherals.html#id4 #ifdef USE_ESP32 -#include "driver/timer.h" +#include "driver/gptimer.h" #endif namespace esphome { @@ -348,7 +344,11 @@ class OpenTherm { const char *operation_mode_to_str(OperationMode mode); const char *message_id_to_str(MessageId id); +#ifdef USE_ESP32 + static bool timer_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx); +#else static bool timer_isr(OpenTherm *arg); +#endif #ifdef ESP8266 static void esp8266_timer_isr(); @@ -361,8 +361,12 @@ class OpenTherm { ISRInternalGPIOPin isr_out_pin_; #ifdef USE_ESP32 - timer_group_t timer_group_; - timer_idx_t timer_idx_; + gptimer_handle_t timer_handle_{nullptr}; + gptimer_alarm_config_t alarm_config_{ + .alarm_count = 0, + .reload_count = 0, + .flags = {.auto_reload_on_alarm = true}, + }; #endif OperationMode mode_; From 3f28ab88cafb51f04cbef929a2b525be03f64c83 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:46:18 -1000 Subject: [PATCH 1493/2030] [http_request] Fix data race on update_info_ strings in update task (#14909) --- .../update/http_request_update.cpp | 222 ++++++++++-------- 1 file changed, 121 insertions(+), 101 deletions(-) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index c40590af95..a15dc61675 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -23,6 +23,12 @@ namespace http_request { static const char *const TAG = "http_request.update"; +// Wraps UpdateInfo + error for the task→main-loop handoff. +struct TaskResult { + update::UpdateInfo info; + const LogString *error_str{nullptr}; +}; + static const size_t MAX_READ_SIZE = 256; static constexpr uint32_t INITIAL_CHECK_INTERVAL_ID = 0; static constexpr uint32_t INITIAL_CHECK_INTERVAL_MS = 10000; @@ -77,134 +83,148 @@ void HttpRequestUpdate::update() { void HttpRequestUpdate::update_task(void *params) { HttpRequestUpdate *this_update = (HttpRequestUpdate *) params; + // Allocate once — every path below returns via the single defer at the end. + // On failure, error_str is set; on success it is nullptr. + auto *result = new TaskResult(); + auto *info = &result->info; + auto container = this_update->request_parent_->get(this_update->source_url_); if (container == nullptr || container->status_code != HTTP_STATUS_OK) { ESP_LOGE(TAG, "Failed to fetch manifest from %s", this_update->source_url_.c_str()); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to fetch manifest")); }); - UPDATE_RETURN; + if (container != nullptr) + container->end(); + result->error_str = LOG_STR("Failed to fetch manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) } - RAMAllocator<uint8_t> allocator; - uint8_t *data = allocator.allocate(container->content_length); - if (data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate %zu bytes for manifest", container->content_length); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer( - [this_update]() { this_update->status_set_error(LOG_STR("Failed to allocate memory for manifest")); }); - container->end(); - UPDATE_RETURN; - } - - auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, - this_update->request_parent_->get_timeout()); - if (read_result.status != HttpReadStatus::OK) { - if (read_result.status == HttpReadStatus::TIMEOUT) { - ESP_LOGE(TAG, "Timeout reading manifest"); - } else { - ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); + { + RAMAllocator<uint8_t> allocator; + uint8_t *data = allocator.allocate(container->content_length); + if (data == nullptr) { + ESP_LOGE(TAG, "Failed to allocate %zu bytes for manifest", container->content_length); + container->end(); + result->error_str = LOG_STR("Failed to allocate memory for manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) } - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to read manifest")); }); - allocator.deallocate(data, container->content_length); - container->end(); - UPDATE_RETURN; - } - size_t read_index = container->get_bytes_read(); - size_t content_length = container->content_length; - container->end(); - container.reset(); // Release ownership of the container's shared_ptr - - bool valid = false; - { // Scope to ensure JsonDocument is destroyed before deallocating buffer - valid = json::parse_json(data, read_index, [this_update](JsonObject root) -> bool { - if (!root[ESPHOME_F("name")].is<const char *>() || !root[ESPHOME_F("version")].is<const char *>() || - !root[ESPHOME_F("builds")].is<JsonArray>()) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; + auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, + this_update->request_parent_->get_timeout()); + if (read_result.status != HttpReadStatus::OK) { + if (read_result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading manifest"); + } else { + ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); } - this_update->update_info_.title = root[ESPHOME_F("name")].as<std::string>(); - this_update->update_info_.latest_version = root[ESPHOME_F("version")].as<std::string>(); + allocator.deallocate(data, container->content_length); + container->end(); + result->error_str = LOG_STR("Failed to read manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) + } + size_t read_index = container->get_bytes_read(); + size_t content_length = container->content_length; - auto builds_array = root[ESPHOME_F("builds")].as<JsonArray>(); - for (auto build : builds_array) { - if (!build[ESPHOME_F("chipFamily")].is<const char *>()) { + container->end(); + container.reset(); // Release ownership of the container's shared_ptr + + bool valid = false; + { // Scope to ensure JsonDocument is destroyed before deallocating buffer + valid = json::parse_json(data, read_index, [info](JsonObject root) -> bool { + if (!root[ESPHOME_F("name")].is<const char *>() || !root[ESPHOME_F("version")].is<const char *>() || + !root[ESPHOME_F("builds")].is<JsonArray>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - if (build[ESPHOME_F("chipFamily")] == ESPHOME_VARIANT) { - if (!build[ESPHOME_F("ota")].is<JsonObject>()) { + info->title = root[ESPHOME_F("name")].as<std::string>(); + info->latest_version = root[ESPHOME_F("version")].as<std::string>(); + + auto builds_array = root[ESPHOME_F("builds")].as<JsonArray>(); + for (auto build : builds_array) { + if (!build[ESPHOME_F("chipFamily")].is<const char *>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - JsonObject ota = build[ESPHOME_F("ota")].as<JsonObject>(); - if (!ota[ESPHOME_F("path")].is<const char *>() || !ota[ESPHOME_F("md5")].is<const char *>()) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; + if (build[ESPHOME_F("chipFamily")] == ESPHOME_VARIANT) { + if (!build[ESPHOME_F("ota")].is<JsonObject>()) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + JsonObject ota = build[ESPHOME_F("ota")].as<JsonObject>(); + if (!ota[ESPHOME_F("path")].is<const char *>() || !ota[ESPHOME_F("md5")].is<const char *>()) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + info->firmware_url = ota[ESPHOME_F("path")].as<std::string>(); + info->md5 = ota[ESPHOME_F("md5")].as<std::string>(); + + if (ota[ESPHOME_F("summary")].is<const char *>()) + info->summary = ota[ESPHOME_F("summary")].as<std::string>(); + if (ota[ESPHOME_F("release_url")].is<const char *>()) + info->release_url = ota[ESPHOME_F("release_url")].as<std::string>(); + + return true; } - this_update->update_info_.firmware_url = ota[ESPHOME_F("path")].as<std::string>(); - this_update->update_info_.md5 = ota[ESPHOME_F("md5")].as<std::string>(); - - if (ota[ESPHOME_F("summary")].is<const char *>()) - this_update->update_info_.summary = ota[ESPHOME_F("summary")].as<std::string>(); - if (ota[ESPHOME_F("release_url")].is<const char *>()) - this_update->update_info_.release_url = ota[ESPHOME_F("release_url")].as<std::string>(); - - return true; } - } - return false; - }); - } - allocator.deallocate(data, content_length); + return false; + }); + } + allocator.deallocate(data, content_length); - if (!valid) { - ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to parse manifest JSON")); }); - UPDATE_RETURN; - } + if (!valid) { + ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); + result->error_str = LOG_STR("Failed to parse manifest JSON"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) + } - // Merge source_url_ and this_update->update_info_.firmware_url - if (this_update->update_info_.firmware_url.find("http") == std::string::npos) { - std::string path = this_update->update_info_.firmware_url; - if (path[0] == '/') { - std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8)); - this_update->update_info_.firmware_url = domain + path; - } else { - std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1); - this_update->update_info_.firmware_url = domain + path; + // Merge source_url_ and firmware_url + if (!info->firmware_url.empty() && info->firmware_url.find("http") == std::string::npos) { + std::string path = info->firmware_url; + if (path[0] == '/') { + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8)); + info->firmware_url = domain + path; + } else { + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1); + info->firmware_url = domain + path; + } } - } #ifdef ESPHOME_PROJECT_VERSION - this_update->update_info_.current_version = ESPHOME_PROJECT_VERSION; + info->current_version = ESPHOME_PROJECT_VERSION; #else - this_update->update_info_.current_version = ESPHOME_VERSION; + info->current_version = ESPHOME_VERSION; #endif - - bool trigger_update_available = false; - - if (this_update->update_info_.latest_version.empty() || - this_update->update_info_.latest_version == this_update->update_info_.current_version) { - this_update->state_ = update::UPDATE_STATE_NO_UPDATE; - } else { - if (this_update->state_ != update::UPDATE_STATE_AVAILABLE) { - trigger_update_available = true; - } - this_update->state_ = update::UPDATE_STATE_AVAILABLE; } - // Defer to main loop to ensure thread-safe execution of: - // - status_clear_error() performs non-atomic read-modify-write on component_state_ - // - publish_state() triggers API callbacks that write to the shared protobuf buffer - // which can be corrupted if accessed concurrently from task and main loop threads - // - update_available trigger to ensure consistent state when the trigger fires - this_update->defer([this_update, trigger_update_available]() { - this_update->update_info_.has_progress = false; - this_update->update_info_.progress = 0.0f; +defer: + // Release container before vTaskDelete (which doesn't call destructors) + container.reset(); + + // Defer to the main loop so all update_info_ and state_ writes happen on the + // same thread as readers (API, MQTT, web server). This is a single defer for + // both success and error paths to avoid multiple std::function instantiations. + // Lambda captures only 2 pointers (8 bytes) — fits in std::function SBO on supported toolchains. + this_update->defer([this_update, result]() { + if (result->error_str != nullptr) { + this_update->status_set_error(result->error_str); + delete result; + return; + } + + // Determine new state on main loop (avoids extra lambda captures from task) + bool trigger_update_available = false; + update::UpdateState new_state; + if (result->info.latest_version.empty() || result->info.latest_version == result->info.current_version) { + new_state = update::UPDATE_STATE_NO_UPDATE; + } else { + new_state = update::UPDATE_STATE_AVAILABLE; + if (this_update->state_ != update::UPDATE_STATE_AVAILABLE) { + trigger_update_available = true; + } + } + + this_update->update_info_ = std::move(result->info); + this_update->state_ = new_state; + delete result; // Safe: moved-from state is valid for destruction this_update->status_clear_error(); this_update->publish_state(); From 45be290392f902905c4b17b7bf3c998c0ce400fb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:47:17 -1000 Subject: [PATCH 1494/2030] [ci] Bump Python to 3.14 in sync-device-classes workflow (#14912) --- .github/workflows/sync-device-classes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/sync-device-classes.yml b/.github/workflows/sync-device-classes.yml index b0d966555b..a71e5ef4ca 100644 --- a/.github/workflows/sync-device-classes.yml +++ b/.github/workflows/sync-device-classes.yml @@ -24,7 +24,7 @@ jobs: - name: Setup Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - python-version: 3.13 + python-version: "3.14" - name: Install Home Assistant run: | From e88c9ba0661131f39d5ee3c9de77a6e48204b4c5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:47:42 -1000 Subject: [PATCH 1495/2030] [core] Inline progmem_read functions on non-ESP8266 platforms (#14913) --- esphome/components/esp32/core.cpp | 3 --- esphome/components/host/core.cpp | 3 --- esphome/components/libretiny/core.cpp | 3 --- esphome/components/rp2040/core.cpp | 7 ------- esphome/components/zephyr/core.cpp | 3 --- esphome/core/hal.h | 9 +++++++++ 6 files changed, 9 insertions(+), 19 deletions(-) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index cba25bca2b..83bd09b643 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -53,9 +53,6 @@ void arch_init() { } void HOT arch_feed_wdt() { esp_task_wdt_reset(); } -uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } -const char *progmem_read_ptr(const char *const *addr) { return *addr; } -uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { uint32_t freq = 0; diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index d5c61ec986..a662e842ee 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -58,9 +58,6 @@ void HOT arch_feed_wdt() { // pass } -uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } -const char *progmem_read_ptr(const char *const *addr) { return *addr; } -uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t arch_get_cpu_cycle_count() { struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); diff --git a/esphome/components/libretiny/core.cpp b/esphome/components/libretiny/core.cpp index 6bb2d9dcc1..1cfe68e924 100644 --- a/esphome/components/libretiny/core.cpp +++ b/esphome/components/libretiny/core.cpp @@ -54,9 +54,6 @@ void arch_restart() { void HOT arch_feed_wdt() { lt_wdt_feed(); } uint32_t arch_get_cpu_cycle_count() { return lt_cpu_get_cycle_count(); } uint32_t arch_get_cpu_freq_hz() { return lt_cpu_get_freq(); } -uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } -const char *progmem_read_ptr(const char *const *addr) { return *addr; } -uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } } // namespace esphome diff --git a/esphome/components/rp2040/core.cpp b/esphome/components/rp2040/core.cpp index 7079cbca15..b7a9000612 100644 --- a/esphome/components/rp2040/core.cpp +++ b/esphome/components/rp2040/core.cpp @@ -37,13 +37,6 @@ void arch_init() { void HOT arch_feed_wdt() { watchdog_update(); } -uint8_t progmem_read_byte(const uint8_t *addr) { - return pgm_read_byte(addr); // NOLINT -} -const char *progmem_read_ptr(const char *const *addr) { - return reinterpret_cast<const char *>(pgm_read_ptr(addr)); // NOLINT -} -uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); } uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); } diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index 1d105a1057..d7c77fdd2c 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -59,9 +59,6 @@ void arch_feed_wdt() { void arch_restart() { sys_reboot(SYS_REBOOT_COLD); } uint32_t arch_get_cpu_cycle_count() { return k_cycle_get_32(); } uint32_t arch_get_cpu_freq_hz() { return sys_clock_hw_cycles_per_sec(); } -uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } -const char *progmem_read_ptr(const char *const *addr) { return *addr; } -uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } Mutex::Mutex() { auto *mutex = new k_mutex(); diff --git a/esphome/core/hal.h b/esphome/core/hal.h index c2c9b1a325..03a30b7459 100644 --- a/esphome/core/hal.h +++ b/esphome/core/hal.h @@ -41,8 +41,17 @@ void arch_init(); void arch_feed_wdt(); uint32_t arch_get_cpu_cycle_count(); uint32_t arch_get_cpu_freq_hz(); + +#ifdef USE_ESP8266 +// ESP8266: pgm_read_* does real flash reads on Harvard architecture uint8_t progmem_read_byte(const uint8_t *addr); const char *progmem_read_ptr(const char *const *addr); uint16_t progmem_read_uint16(const uint16_t *addr); +#else +// All other platforms: PROGMEM is a no-op, so these are direct dereferences +inline uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } +inline const char *progmem_read_ptr(const char *const *addr) { return *addr; } +inline uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } +#endif } // namespace esphome From c9e6c85e6a66cee3dcc867e68b2ecd2589dbdc1a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:48:11 -1000 Subject: [PATCH 1496/2030] [scheduler] Inline fast-path checks into header (#14905) --- esphome/core/scheduler.cpp | 69 +++++++++++++++++++++++----- esphome/core/scheduler.h | 92 ++++++++++++++------------------------ 2 files changed, 91 insertions(+), 70 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index db40ede78c..44fc277ec8 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -454,6 +454,61 @@ void Scheduler::compact_defer_queue_locked_() { // (saves ~156 bytes flash). Erasing from the end is O(1) - no shifting needed. this->defer_queue_.erase(this->defer_queue_.begin() + remaining, this->defer_queue_.end()); } +void HOT Scheduler::process_defer_queue_slow_path_(uint32_t &now) { + // Process defer queue to guarantee FIFO execution order for deferred items. + // Previously, defer() used the heap which gave undefined order for equal timestamps, + // causing race conditions on multi-core systems (ESP32, BK7200). + // With the defer queue: + // - Deferred items (delay=0) go directly to defer_queue_ in set_timer_common_ + // - Items execute in exact order they were deferred (FIFO guarantee) + // - No deferred items exist in to_add_, so processing order doesn't affect correctness + // Single-core platforms don't use this queue and fall back to the heap-based approach. + // + // Note: Items cancelled via cancel_item_locked_() are marked with remove=true but still + // processed here. They are skipped during execution by should_skip_item_(). + // This is intentional - no memory leak occurs. + // + // We use an index (defer_queue_front_) to track the read position instead of calling + // erase() on every pop, which would be O(n). The queue is processed once per loop - + // any items added during processing are left for the next loop iteration. + + // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), + // recycle each item after re-acquiring the lock for the next iteration (N+1 total). + // The lock is held across: recycle → loop condition → move-out, then released for execution. + SchedulerItem *item; + + this->lock_.lock(); + // Reset counter and snapshot queue end under lock + this->defer_count_clear_(); + size_t defer_queue_end = this->defer_queue_.size(); + if (this->defer_queue_front_ >= defer_queue_end) { + this->lock_.unlock(); + return; + } + while (this->defer_queue_front_ < defer_queue_end) { + // Take ownership of the item, leaving nullptr in the vector slot. + // This is safe because: + // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function + // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_) + // 3. The lock protects concurrent access, but the nullptr remains until cleanup + item = this->defer_queue_[this->defer_queue_front_]; + this->defer_queue_[this->defer_queue_front_] = nullptr; + this->defer_queue_front_++; + this->lock_.unlock(); + + // Execute callback without holding lock to prevent deadlocks + // if the callback tries to call defer() again + if (!this->should_skip_item_(item)) { + now = this->execute_item_(item, now); + } + + this->lock_.lock(); + this->recycle_item_main_loop_(item); + } + // Clean up the queue (lock already held from last recycle or initial acquisition) + this->cleanup_defer_queue_locked_(); + this->lock_.unlock(); +} #endif /* not ESPHOME_THREAD_SINGLE */ void HOT Scheduler::call(uint32_t now) { @@ -613,11 +668,7 @@ void HOT Scheduler::call(uint32_t now) { } #endif } -void HOT Scheduler::process_to_add() { - // Fast path: skip lock acquisition when nothing to add. - // Worst case is a one-loop-iteration delay before newly added items are processed. - if (this->to_add_empty_()) - return; +void HOT Scheduler::process_to_add_slow_path_() { LockGuard guard{this->lock_}; for (auto *&it : this->to_add_) { if (is_item_removed_locked_(it)) { @@ -633,13 +684,7 @@ void HOT Scheduler::process_to_add() { this->to_add_.clear(); this->to_add_count_clear_(); } -bool HOT Scheduler::cleanup_() { - // Fast path: if nothing to remove, just check if items exist. - // Uses atomic load on platforms with atomics, falls back to always taking the lock otherwise. - // Worst case is a one-loop-iteration delay in cleanup. - if (this->to_remove_empty_()) - return !this->items_.empty(); - +bool HOT Scheduler::cleanup_slow_path_() { // We must hold the lock for the entire cleanup operation because: // 1. We're modifying items_ (via pop_raw_locked_) which requires exclusive access // 2. We're decrementing to_remove_ which is also modified by other threads diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index e545055fca..36c853ad17 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -131,7 +131,18 @@ class Scheduler { // @param now Fresh timestamp from millis() - must not be stale/cached void call(uint32_t now); - void process_to_add(); + // Move items from to_add_ into the main heap. + // IMPORTANT: This method should only be called from the main thread (loop task). + // Inlined: the fast path (nothing to add) is just an atomic load / empty check. + // The lock-free fast path uses to_add_count_ (atomic) or to_add_.empty() + // (single-threaded). This is safe because the main loop is the only thread + // that reads to_add_ without holding lock_; other threads may read it only + // while holding the mutex (e.g. cancel_item_locked_). + inline void HOT process_to_add() { + if (this->to_add_empty_()) + return; + this->process_to_add_slow_path_(); + } // Name storage type discriminator for SchedulerItem // Used to distinguish between static strings, hashed strings, numeric IDs, and internal numeric IDs @@ -286,7 +297,20 @@ class Scheduler { // Cleanup logically deleted items from the scheduler // Returns true if items remain after cleanup // IMPORTANT: This method should only be called from the main thread (loop task). - bool cleanup_(); + // Inlined: the fast path (nothing to remove) is just an atomic load + empty check. + // Reading items_.empty() without the lock is safe here because only the main + // loop thread structurally modifies items_ (push/pop/erase). Other threads may + // iterate items_ and mark items removed under lock_, but never change the + // vector's size or data pointer. + inline bool HOT cleanup_() { + if (this->to_remove_empty_()) + return !this->items_.empty(); + return this->cleanup_slow_path_(); + } + // Slow path for cleanup_() when there are items to remove - defined in scheduler.cpp + bool cleanup_slow_path_(); + // Slow path for process_to_add() when there are items to merge - defined in scheduler.cpp + void process_to_add_slow_path_(); // Remove and return the front item from the heap as a raw pointer. // Caller takes ownership and must either recycle or delete the item. // IMPORTANT: Caller must hold the scheduler lock before calling this function. @@ -376,68 +400,20 @@ class Scheduler { #endif /* ESPHOME_DEBUG_SCHEDULER */ #ifndef ESPHOME_THREAD_SINGLE - // Helper to process defer queue - inline for performance in hot path - inline void process_defer_queue_(uint32_t &now) { - // Process defer queue first to guarantee FIFO execution order for deferred items. - // Previously, defer() used the heap which gave undefined order for equal timestamps, - // causing race conditions on multi-core systems (ESP32, BK7200). - // With the defer queue: - // - Deferred items (delay=0) go directly to defer_queue_ in set_timer_common_ - // - Items execute in exact order they were deferred (FIFO guarantee) - // - No deferred items exist in to_add_, so processing order doesn't affect correctness - // Single-core platforms don't use this queue and fall back to the heap-based approach. - // - // Note: Items cancelled via cancel_item_locked_() are marked with remove=true but still - // processed here. They are skipped during execution by should_skip_item_(). - // This is intentional - no memory leak occurs. - // - // We use an index (defer_queue_front_) to track the read position instead of calling - // erase() on every pop, which would be O(n). The queue is processed once per loop - - // any items added during processing are left for the next loop iteration. - + // Process defer queue for FIFO execution of deferred items. + // IMPORTANT: This method should only be called from the main thread (loop task). + // Inlined: the fast path (nothing deferred) is just an atomic load check. + inline void HOT process_defer_queue_(uint32_t &now) { // Fast path: nothing to process, avoid lock entirely. // Worst case is a one-loop-iteration delay before newly deferred items are processed. if (this->defer_empty_()) return; - - // Merge lock acquisitions: instead of separate locks for move-out and recycle (2N+1 total), - // recycle each item after re-acquiring the lock for the next iteration (N+1 total). - // The lock is held across: recycle → loop condition → move-out, then released for execution. - SchedulerItem *item; - - this->lock_.lock(); - // Reset counter and snapshot queue end under lock - this->defer_count_clear_(); - size_t defer_queue_end = this->defer_queue_.size(); - if (this->defer_queue_front_ >= defer_queue_end) { - this->lock_.unlock(); - return; - } - while (this->defer_queue_front_ < defer_queue_end) { - // Take ownership of the item, leaving nullptr in the vector slot. - // This is safe because: - // 1. The vector is only cleaned up by cleanup_defer_queue_locked_() at the end of this function - // 2. Any code iterating defer_queue_ MUST check for nullptr items (see mark_matching_items_removed_locked_) - // 3. The lock protects concurrent access, but the nullptr remains until cleanup - item = this->defer_queue_[this->defer_queue_front_]; - this->defer_queue_[this->defer_queue_front_] = nullptr; - this->defer_queue_front_++; - this->lock_.unlock(); - - // Execute callback without holding lock to prevent deadlocks - // if the callback tries to call defer() again - if (!this->should_skip_item_(item)) { - now = this->execute_item_(item, now); - } - - this->lock_.lock(); - this->recycle_item_main_loop_(item); - } - // Clean up the queue (lock already held from last recycle or initial acquisition) - this->cleanup_defer_queue_locked_(); - this->lock_.unlock(); + this->process_defer_queue_slow_path_(now); } + // Slow path for process_defer_queue_() - defined in scheduler.cpp + void process_defer_queue_slow_path_(uint32_t &now); + // Helper to cleanup defer_queue_ after processing. // Keeps the common clear() path inline, outlines the rare compaction to keep // cold code out of the hot instruction cache lines. From 9a80c980cb91b783387cfd1552284e5f36d82ba9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:48:26 -1000 Subject: [PATCH 1497/2030] [scheduler] Early exit cancel path after first match (#14902) --- esphome/core/scheduler.cpp | 27 +++++++++++++++++------ esphome/core/scheduler.h | 21 +++++++++++++----- tests/benchmarks/core/bench_scheduler.cpp | 12 +++++++++- 3 files changed, 47 insertions(+), 13 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 44fc277ec8..51cbfb208e 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -138,7 +138,8 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Still need to cancel existing timer if we have a name/id if (!skip_cancel) { LockGuard guard{this->lock_}; - this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); + this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type, /* match_retry= */ false, + /* find_first= */ true); } return; } @@ -209,7 +210,8 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Common epilogue: atomic cancel-and-add (unless skip_cancel is true) if (!skip_cancel) { - this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type); + this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type, /* match_retry= */ false, + /* find_first= */ true); } target->push_back(item); if (target == &this->to_add_) { @@ -723,13 +725,20 @@ uint32_t HOT Scheduler::execute_item_(SchedulerItem *item, uint32_t now) { bool HOT Scheduler::cancel_item_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { LockGuard guard{this->lock_}; + // Public cancel path uses default find_first=false to cancel ALL matches because + // DelayAction parallel mode (skip_cancel=true) can create multiple items with the same key. return this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type, match_retry); } -// Helper to cancel items - must be called with lock held +// Helper to cancel matching items - must be called with lock held. +// When find_first=true, stops after the first match and exits across containers +// (used by set_timer_common_ where cancel-before-add guarantees at most one match). +// When find_first=false, cancels ALL matches across all containers (needed for +// public cancel path where DelayAction parallel mode can create duplicates). // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type, const char *static_name, - uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry) { + uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry, + bool find_first) { // Early return if static string name is invalid if (name_type == NameType::STATIC_STRING && static_name == nullptr) { return false; @@ -741,7 +750,9 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type // Mark items in defer queue as cancelled (they'll be skipped when processed) if (type == SchedulerItem::TIMEOUT) { total_cancelled += this->mark_matching_items_removed_locked_(this->defer_queue_, component, name_type, static_name, - hash_or_id, type, match_retry); + hash_or_id, type, match_retry, find_first); + if (find_first && total_cancelled > 0) + return true; } #endif /* not ESPHOME_THREAD_SINGLE */ @@ -752,14 +763,16 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type // Only the main loop in call() should recycle items after execution completes. if (!this->items_.empty()) { size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_, component, name_type, static_name, - hash_or_id, type, match_retry); + hash_or_id, type, match_retry, find_first); total_cancelled += heap_cancelled; this->to_remove_add_(heap_cancelled); + if (find_first && total_cancelled > 0) + return true; } // Cancel items in to_add_ total_cancelled += this->mark_matching_items_removed_locked_(this->to_add_, component, name_type, static_name, - hash_or_id, type, match_retry); + hash_or_id, type, match_retry, find_first); return total_cancelled > 0; } diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 36c853ad17..1e44f41da8 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -320,10 +320,14 @@ class Scheduler { SchedulerItem *get_item_from_pool_locked_(); private: - // Helper to cancel items - must be called with lock held + // Helper to cancel matching items - must be called with lock held. + // When find_first=true, stops after the first match (used by set_timer_common_ where + // the cancel-before-add invariant guarantees at most one match). + // When find_first=false (default), cancels ALL matches (needed for DelayAction parallel + // mode where skip_cancel=true allows multiple items with the same key). // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id bool cancel_item_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, - SchedulerItem::Type type, bool match_retry = false); + SchedulerItem::Type type, bool match_retry = false, bool find_first = false); // Common implementation for cancel operations - handles locking bool cancel_item_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, @@ -483,18 +487,25 @@ class Scheduler { #endif } - // Helper to mark matching items in a container as removed + // Helper to mark matching items in a container as removed. + // When find_first=true, stops after the first match (used by set_timer_common_ where + // the cancel-before-add invariant guarantees at most one match). + // When find_first=false, marks ALL matches (needed for public cancel path where + // DelayAction parallel mode with skip_cancel=true can create multiple items with the same key). // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id - // Returns the number of items marked for removal + // Returns the number of items marked for removal. // IMPORTANT: Must be called with scheduler lock held __attribute__((noinline)) size_t mark_matching_items_removed_locked_(std::vector<SchedulerItem *> &container, Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, - SchedulerItem::Type type, bool match_retry) { + SchedulerItem::Type type, bool match_retry, + bool find_first = false) { size_t count = 0; for (auto *item : container) { if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { this->set_item_removed_(item, true); + if (find_first) + return 1; count++; } } diff --git a/tests/benchmarks/core/bench_scheduler.cpp b/tests/benchmarks/core/bench_scheduler.cpp index 764f17ed73..9357734cc8 100644 --- a/tests/benchmarks/core/bench_scheduler.cpp +++ b/tests/benchmarks/core/bench_scheduler.cpp @@ -99,11 +99,21 @@ BENCHMARK(Scheduler_SetTimeout); static void Scheduler_SetInterval(benchmark::State &state) { Scheduler scheduler; Component dummy_component; + // Number of distinct interval keys; controls how many unique timers exist + // simultaneously and the drain cadence for process_to_add(). + static constexpr int kKeyCount = 5; for (auto _ : state) { for (int i = 0; i < kInnerIterations; i++) { - scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i % 5), 1000, []() {}); + scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i % kKeyCount), 1000, []() {}); + // Drain to_add_ periodically to reflect production behavior where + // process_to_add() runs each main loop iteration. Without this, + // cancelled items accumulate in to_add_ causing O(n²) scan cost. + if ((i + 1) % kKeyCount == 0) { + scheduler.process_to_add(); + } } + // Final drain in case kInnerIterations is not a multiple of 5 scheduler.process_to_add(); benchmark::DoNotOptimize(scheduler); } From 6cf32af33f4ec92d0b06939129be8c7cb254cb59 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:57:53 -0400 Subject: [PATCH 1498/2030] [seeed_mr24hpc1] Fix frame parser length handling bugs (#14863) --- esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index 263603704a..c9fe3a2e6e 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -297,19 +297,17 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { this->sg_recv_data_state_ = FRAME_DATA_LEN_H; break; case FRAME_DATA_LEN_H: - if (value <= 4) { - this->sg_data_len_ = value * 256; + if (value == 0) { this->sg_frame_buf_[4] = value; this->sg_recv_data_state_ = FRAME_DATA_LEN_L; } else { - this->sg_data_len_ = 0; this->sg_recv_data_state_ = FRAME_IDLE; ESP_LOGD(TAG, "FRAME_DATA_LEN_H ERROR value:%x", value); } break; case FRAME_DATA_LEN_L: - this->sg_data_len_ += value; - if (this->sg_data_len_ > 32) { + this->sg_data_len_ = value; + if (this->sg_data_len_ == 0 || this->sg_data_len_ > 32) { ESP_LOGD(TAG, "len=%d, FRAME_DATA_LEN_L ERROR value:%x", this->sg_data_len_, value); this->sg_data_len_ = 0; this->sg_recv_data_state_ = FRAME_IDLE; @@ -320,9 +318,8 @@ void MR24HPC1Component::r24_split_data_frame_(uint8_t value) { } break; case FRAME_DATA_BYTES: - this->sg_data_len_ -= 1; this->sg_frame_buf_[this->sg_frame_len_++] = value; - if (this->sg_data_len_ <= 0) { + if (--this->sg_data_len_ == 0) { this->sg_recv_data_state_ = FRAME_DATA_CRC; } break; From 91e66cfd9d7e3a31ca4a0923463dcc107de321d1 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 16:28:13 -0400 Subject: [PATCH 1499/2030] [gree] Fix IR checksum for YAA/YAC/YAC1FB9/GENERIC models (#14888) --- esphome/components/gree/gree.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/esphome/components/gree/gree.cpp b/esphome/components/gree/gree.cpp index 8a9f264932..732ebd9632 100644 --- a/esphome/components/gree/gree.cpp +++ b/esphome/components/gree/gree.cpp @@ -87,19 +87,12 @@ void GreeClimate::transmit_state() { // Calculate the checksum if (this->model_ == GREE_YAN || this->model_ == GREE_YX1FF) { remote_state[7] = ((remote_state[0] << 4) + (remote_state[1] << 4) + 0xC0); - } else if (this->model_ == GREE_YAG) { + } else { remote_state[7] = ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) + ((remote_state[4] & 0xF0) >> 4) + ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + 0x0A) & 0x0F) << 4); - } else { - remote_state[7] = - ((((remote_state[0] & 0x0F) + (remote_state[1] & 0x0F) + (remote_state[2] & 0x0F) + (remote_state[3] & 0x0F) + - ((remote_state[5] & 0xF0) >> 4) + ((remote_state[6] & 0xF0) >> 4) + ((remote_state[7] & 0xF0) >> 4) + 0x0A) & - 0x0F) - << 4) | - (remote_state[7] & 0x0F); } auto transmit = this->transmitter_->transmit(); From 4cb93d4df8c3661158ffb7e96966eccdb08bedad Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 19:46:26 -0400 Subject: [PATCH 1500/2030] [sensor][ee895][hdc2010] Fix misc bugs found during component scan (#14890) --- esphome/components/ee895/ee895.cpp | 15 ++--- esphome/components/hdc2010/hdc2010.cpp | 76 +++++++++++--------------- esphome/components/sensor/__init__.py | 10 ++-- 3 files changed, 43 insertions(+), 58 deletions(-) diff --git a/esphome/components/ee895/ee895.cpp b/esphome/components/ee895/ee895.cpp index 22f28be9bc..93e5d4203b 100644 --- a/esphome/components/ee895/ee895.cpp +++ b/esphome/components/ee895/ee895.cpp @@ -24,7 +24,7 @@ void EE895Component::setup() { this->read(serial_number, 20); crc16_check = (serial_number[19] << 8) + serial_number[18]; - if (crc16_check != calc_crc16_(serial_number, 19)) { + if (crc16_check != calc_crc16_(serial_number, 18)) { this->error_code_ = CRC_CHECK_FAILED; this->mark_failed(); return; @@ -84,7 +84,7 @@ void EE895Component::write_command_(uint16_t addr, uint16_t reg_cnt) { address[2] = addr & 0xFF; address[3] = (reg_cnt >> 8) & 0xFF; address[4] = reg_cnt & 0xFF; - crc16 = calc_crc16_(address, 6); + crc16 = calc_crc16_(address, 5); address[5] = crc16 & 0xFF; address[6] = (crc16 >> 8) & 0xFF; this->write(address, 7); @@ -95,7 +95,7 @@ float EE895Component::read_float_() { uint8_t i2c_response[8]; this->read(i2c_response, 8); crc16_check = (i2c_response[7] << 8) + i2c_response[6]; - if (crc16_check != calc_crc16_(i2c_response, 7)) { + if (crc16_check != calc_crc16_(i2c_response, 6)) { this->error_code_ = CRC_CHECK_FAILED; this->status_set_warning(); return 0; @@ -107,12 +107,9 @@ float EE895Component::read_float_() { } uint16_t EE895Component::calc_crc16_(const uint8_t buf[], uint8_t len) { - uint8_t crc_check_buf[22]; - for (int i = 0; i < len; i++) { - crc_check_buf[i + 1] = buf[i]; - } - crc_check_buf[0] = this->address_; - return crc16(crc_check_buf, len); + uint8_t addr = this->address_; + uint16_t crc = crc16(&addr, 1); + return crc16(buf, len, crc); } } // namespace ee895 } // namespace esphome diff --git a/esphome/components/hdc2010/hdc2010.cpp b/esphome/components/hdc2010/hdc2010.cpp index c53fdb3f5b..0334b30eec 100644 --- a/esphome/components/hdc2010/hdc2010.cpp +++ b/esphome/components/hdc2010/hdc2010.cpp @@ -7,50 +7,36 @@ namespace hdc2010 { static const char *const TAG = "hdc2010"; -static const uint8_t HDC2010_ADDRESS = 0x40; // 0b1000000 or 0b1000001 from datasheet -static const uint8_t HDC2010_CMD_CONFIGURATION_MEASUREMENT = 0x8F; -static const uint8_t HDC2010_CMD_START_MEASUREMENT = 0xF9; -static const uint8_t HDC2010_CMD_TEMPERATURE_LOW = 0x00; -static const uint8_t HDC2010_CMD_TEMPERATURE_HIGH = 0x01; -static const uint8_t HDC2010_CMD_HUMIDITY_LOW = 0x02; -static const uint8_t HDC2010_CMD_HUMIDITY_HIGH = 0x03; -static const uint8_t CONFIG = 0x0E; -static const uint8_t MEASUREMENT_CONFIG = 0x0F; +// Register addresses +static constexpr uint8_t REG_TEMPERATURE_LOW = 0x00; +static constexpr uint8_t REG_TEMPERATURE_HIGH = 0x01; +static constexpr uint8_t REG_HUMIDITY_LOW = 0x02; +static constexpr uint8_t REG_HUMIDITY_HIGH = 0x03; +static constexpr uint8_t REG_RESET_DRDY_INT_CONF = 0x0E; +static constexpr uint8_t REG_MEASUREMENT_CONF = 0x0F; + +// REG_MEASUREMENT_CONF (0x0F) bit masks +static constexpr uint8_t MEAS_TRIG = 0x01; // Bit 0: measurement trigger +static constexpr uint8_t MEAS_CONF_MASK = 0x06; // Bits 2:1: measurement mode +static constexpr uint8_t HRES_MASK = 0x30; // Bits 5:4: humidity resolution +static constexpr uint8_t TRES_MASK = 0xC0; // Bits 7:6: temperature resolution + +// REG_RESET_DRDY_INT_CONF (0x0E) bit masks +static constexpr uint8_t AMM_MASK = 0x70; // Bits 6:4: auto measurement mode void HDC2010Component::setup() { ESP_LOGCONFIG(TAG, "Running setup"); - const uint8_t data[2] = { - 0b00000000, // resolution 14bit for both humidity and temperature - 0b00000000 // reserved - }; - - if (!this->write_bytes(HDC2010_CMD_CONFIGURATION_MEASUREMENT, data, 2)) { - ESP_LOGW(TAG, "Initial config instruction error"); - this->status_set_warning(); - return; - } - - // Set measurement mode to temperature and humidity + // Set 14-bit resolution for both sensors and measurement mode to temp + humidity uint8_t config_contents; - this->read_register(MEASUREMENT_CONFIG, &config_contents, 1); - config_contents = (config_contents & 0xF9); // Always set to TEMP_AND_HUMID mode - this->write_bytes(MEASUREMENT_CONFIG, &config_contents, 1); + this->read_register(REG_MEASUREMENT_CONF, &config_contents, 1); + config_contents &= ~(TRES_MASK | HRES_MASK | MEAS_CONF_MASK); // 14-bit temp, 14-bit humidity, temp+humidity mode + this->write_bytes(REG_MEASUREMENT_CONF, &config_contents, 1); - // Set rate to manual - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0x8F; - this->write_bytes(CONFIG, &config_contents, 1); - - // Set temperature resolution to 14bit - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0x3F; - this->write_bytes(CONFIG, &config_contents, 1); - - // Set humidity resolution to 14bit - this->read_register(CONFIG, &config_contents, 1); - config_contents &= 0xCF; - this->write_bytes(CONFIG, &config_contents, 1); + // Set auto measurement rate to manual (on-demand via MEAS_TRIG) + this->read_register(REG_RESET_DRDY_INT_CONF, &config_contents, 1); + config_contents &= ~AMM_MASK; + this->write_bytes(REG_RESET_DRDY_INT_CONF, &config_contents, 1); } void HDC2010Component::dump_config() { @@ -67,9 +53,9 @@ void HDC2010Component::dump_config() { void HDC2010Component::update() { // Trigger measurement uint8_t config_contents; - this->read_register(CONFIG, &config_contents, 1); - config_contents |= 0x01; - this->write_bytes(MEASUREMENT_CONFIG, &config_contents, 1); + this->read_register(REG_MEASUREMENT_CONF, &config_contents, 1); + config_contents |= MEAS_TRIG; + this->write_bytes(REG_MEASUREMENT_CONF, &config_contents, 1); // 1ms delay after triggering the sample set_timeout(1, [this]() { @@ -90,8 +76,8 @@ void HDC2010Component::update() { float HDC2010Component::read_temp() { uint8_t byte[2]; - this->read_register(HDC2010_CMD_TEMPERATURE_LOW, &byte[0], 1); - this->read_register(HDC2010_CMD_TEMPERATURE_HIGH, &byte[1], 1); + this->read_register(REG_TEMPERATURE_LOW, &byte[0], 1); + this->read_register(REG_TEMPERATURE_HIGH, &byte[1], 1); uint16_t temp = encode_uint16(byte[1], byte[0]); return (float) temp * 0.0025177f - 40.0f; @@ -100,8 +86,8 @@ float HDC2010Component::read_temp() { float HDC2010Component::read_humidity() { uint8_t byte[2]; - this->read_register(HDC2010_CMD_HUMIDITY_LOW, &byte[0], 1); - this->read_register(HDC2010_CMD_HUMIDITY_HIGH, &byte[1], 1); + this->read_register(REG_HUMIDITY_LOW, &byte[0], 1); + this->read_register(REG_HUMIDITY_HIGH, &byte[1], 1); uint16_t humidity = encode_uint16(byte[1], byte[0]); return (float) humidity * 0.001525879f; diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 4be6ed1b84..02db381ff4 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -403,10 +403,12 @@ async def filter_out_filter_to_code(config, filter_id): QUANTILE_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, - cv.Optional(CONF_QUANTILE, default=0.9): cv.zero_to_one_float, + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_EVERY, default=5): cv.int_range(min=1, max=65535), + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.int_range(min=1, max=65535), + cv.Optional(CONF_QUANTILE, default=0.9): cv.float_range( + min=0, min_included=False, max=1 + ), } ), validate_send_first_at, From 98d3dce6727f39dd0a0efd4fdabf0daa9b369140 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 17 Mar 2026 23:12:13 -0400 Subject: [PATCH 1501/2030] [voice_assistant][micro_wake_word] Fix null deref and missing error return (#14906) --- esphome/components/micro_wake_word/streaming_model.cpp | 1 + esphome/components/voice_assistant/voice_assistant.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/esphome/components/micro_wake_word/streaming_model.cpp b/esphome/components/micro_wake_word/streaming_model.cpp index 47d2c70e13..0ab6cd3772 100644 --- a/esphome/components/micro_wake_word/streaming_model.cpp +++ b/esphome/components/micro_wake_word/streaming_model.cpp @@ -80,6 +80,7 @@ bool StreamingModel::load_model_() { TfLiteTensor *output = this->interpreter_->output(0); if ((output->dims->size != 2) || (output->dims->data[0] != 1) || (output->dims->data[1] != 1)) { ESP_LOGE(TAG, "Streaming model tensor output dimension is not 1x1."); + return false; } if (output->type != kTfLiteUInt8) { diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 51d52a8af8..15124e422f 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -619,6 +619,8 @@ void VoiceAssistant::start_playback_timeout_() { this->cancel_timeout("speaker-timeout"); this->set_state_(State::RESPONSE_FINISHED, State::RESPONSE_FINISHED); + if (this->api_client_ == nullptr) + return; api::VoiceAssistantAnnounceFinished msg; msg.success = true; this->api_client_->send_message(msg); From fc67551edc0bfc4e5966e11b325c2d5277114df5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 07:48:43 -0400 Subject: [PATCH 1502/2030] [tc74][apds9960] Fix signed temperature and FIFO register address (#14907) --- esphome/components/apds9960/apds9960.cpp | 8 ++++---- esphome/components/tc74/tc74.cpp | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/esphome/components/apds9960/apds9960.cpp b/esphome/components/apds9960/apds9960.cpp index 260de82d14..a07175f2c9 100644 --- a/esphome/components/apds9960/apds9960.cpp +++ b/esphome/components/apds9960/apds9960.cpp @@ -251,11 +251,11 @@ void APDS9960::read_gesture_data_() { uint8_t buf[128]; for (uint8_t pos = 0; pos < fifo_level * 4; pos += 32) { - // The ESP's i2c driver has a limited buffer size. - // This way of retrieving the data should be wrong according to the datasheet - // but it seems to work. + // Read in 32-byte chunks due to ESP8266 I2C buffer limit. + // Always read from 0xFC — the FIFO auto-increments through 0xFC-0xFF + // and advances its internal pointer after every 4th byte. uint8_t read = std::min(32, fifo_level * 4 - pos); - APDS9960_WARNING_CHECK(this->read_bytes(0xFC + pos, buf + pos, read), "Reading FIFO buffer failed."); + APDS9960_WARNING_CHECK(this->read_bytes(0xFC, buf + pos, read), "Reading FIFO buffer failed."); } if (millis() - this->gesture_start_ > 500) { diff --git a/esphome/components/tc74/tc74.cpp b/esphome/components/tc74/tc74.cpp index 969ef3671e..cb58e583dc 100644 --- a/esphome/components/tc74/tc74.cpp +++ b/esphome/components/tc74/tc74.cpp @@ -50,8 +50,9 @@ void TC74Component::read_temperature_() { } } - uint8_t temperature_reg; - if (this->read_register(TC74_REGISTER_TEMPERATURE, &temperature_reg, 1) != i2c::ERROR_OK) { + int8_t temperature_reg; + if (this->read_register(TC74_REGISTER_TEMPERATURE, reinterpret_cast<uint8_t *>(&temperature_reg), 1) != + i2c::ERROR_OK) { this->status_set_warning(); return; } From 448402ca2cb49160c66472e3464dafe2209ab47b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 07:46:18 -1000 Subject: [PATCH 1503/2030] [http_request] Fix data race on update_info_ strings in update task (#14909) --- .../update/http_request_update.cpp | 222 ++++++++++-------- 1 file changed, 121 insertions(+), 101 deletions(-) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index c40590af95..a15dc61675 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -23,6 +23,12 @@ namespace http_request { static const char *const TAG = "http_request.update"; +// Wraps UpdateInfo + error for the task→main-loop handoff. +struct TaskResult { + update::UpdateInfo info; + const LogString *error_str{nullptr}; +}; + static const size_t MAX_READ_SIZE = 256; static constexpr uint32_t INITIAL_CHECK_INTERVAL_ID = 0; static constexpr uint32_t INITIAL_CHECK_INTERVAL_MS = 10000; @@ -77,134 +83,148 @@ void HttpRequestUpdate::update() { void HttpRequestUpdate::update_task(void *params) { HttpRequestUpdate *this_update = (HttpRequestUpdate *) params; + // Allocate once — every path below returns via the single defer at the end. + // On failure, error_str is set; on success it is nullptr. + auto *result = new TaskResult(); + auto *info = &result->info; + auto container = this_update->request_parent_->get(this_update->source_url_); if (container == nullptr || container->status_code != HTTP_STATUS_OK) { ESP_LOGE(TAG, "Failed to fetch manifest from %s", this_update->source_url_.c_str()); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to fetch manifest")); }); - UPDATE_RETURN; + if (container != nullptr) + container->end(); + result->error_str = LOG_STR("Failed to fetch manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) } - RAMAllocator<uint8_t> allocator; - uint8_t *data = allocator.allocate(container->content_length); - if (data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate %zu bytes for manifest", container->content_length); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer( - [this_update]() { this_update->status_set_error(LOG_STR("Failed to allocate memory for manifest")); }); - container->end(); - UPDATE_RETURN; - } - - auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, - this_update->request_parent_->get_timeout()); - if (read_result.status != HttpReadStatus::OK) { - if (read_result.status == HttpReadStatus::TIMEOUT) { - ESP_LOGE(TAG, "Timeout reading manifest"); - } else { - ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); + { + RAMAllocator<uint8_t> allocator; + uint8_t *data = allocator.allocate(container->content_length); + if (data == nullptr) { + ESP_LOGE(TAG, "Failed to allocate %zu bytes for manifest", container->content_length); + container->end(); + result->error_str = LOG_STR("Failed to allocate memory for manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) } - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to read manifest")); }); - allocator.deallocate(data, container->content_length); - container->end(); - UPDATE_RETURN; - } - size_t read_index = container->get_bytes_read(); - size_t content_length = container->content_length; - container->end(); - container.reset(); // Release ownership of the container's shared_ptr - - bool valid = false; - { // Scope to ensure JsonDocument is destroyed before deallocating buffer - valid = json::parse_json(data, read_index, [this_update](JsonObject root) -> bool { - if (!root[ESPHOME_F("name")].is<const char *>() || !root[ESPHOME_F("version")].is<const char *>() || - !root[ESPHOME_F("builds")].is<JsonArray>()) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; + auto read_result = http_read_fully(container.get(), data, container->content_length, MAX_READ_SIZE, + this_update->request_parent_->get_timeout()); + if (read_result.status != HttpReadStatus::OK) { + if (read_result.status == HttpReadStatus::TIMEOUT) { + ESP_LOGE(TAG, "Timeout reading manifest"); + } else { + ESP_LOGE(TAG, "Error reading manifest: %d", read_result.error_code); } - this_update->update_info_.title = root[ESPHOME_F("name")].as<std::string>(); - this_update->update_info_.latest_version = root[ESPHOME_F("version")].as<std::string>(); + allocator.deallocate(data, container->content_length); + container->end(); + result->error_str = LOG_STR("Failed to read manifest"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) + } + size_t read_index = container->get_bytes_read(); + size_t content_length = container->content_length; - auto builds_array = root[ESPHOME_F("builds")].as<JsonArray>(); - for (auto build : builds_array) { - if (!build[ESPHOME_F("chipFamily")].is<const char *>()) { + container->end(); + container.reset(); // Release ownership of the container's shared_ptr + + bool valid = false; + { // Scope to ensure JsonDocument is destroyed before deallocating buffer + valid = json::parse_json(data, read_index, [info](JsonObject root) -> bool { + if (!root[ESPHOME_F("name")].is<const char *>() || !root[ESPHOME_F("version")].is<const char *>() || + !root[ESPHOME_F("builds")].is<JsonArray>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - if (build[ESPHOME_F("chipFamily")] == ESPHOME_VARIANT) { - if (!build[ESPHOME_F("ota")].is<JsonObject>()) { + info->title = root[ESPHOME_F("name")].as<std::string>(); + info->latest_version = root[ESPHOME_F("version")].as<std::string>(); + + auto builds_array = root[ESPHOME_F("builds")].as<JsonArray>(); + for (auto build : builds_array) { + if (!build[ESPHOME_F("chipFamily")].is<const char *>()) { ESP_LOGE(TAG, "Manifest does not contain required fields"); return false; } - JsonObject ota = build[ESPHOME_F("ota")].as<JsonObject>(); - if (!ota[ESPHOME_F("path")].is<const char *>() || !ota[ESPHOME_F("md5")].is<const char *>()) { - ESP_LOGE(TAG, "Manifest does not contain required fields"); - return false; + if (build[ESPHOME_F("chipFamily")] == ESPHOME_VARIANT) { + if (!build[ESPHOME_F("ota")].is<JsonObject>()) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + JsonObject ota = build[ESPHOME_F("ota")].as<JsonObject>(); + if (!ota[ESPHOME_F("path")].is<const char *>() || !ota[ESPHOME_F("md5")].is<const char *>()) { + ESP_LOGE(TAG, "Manifest does not contain required fields"); + return false; + } + info->firmware_url = ota[ESPHOME_F("path")].as<std::string>(); + info->md5 = ota[ESPHOME_F("md5")].as<std::string>(); + + if (ota[ESPHOME_F("summary")].is<const char *>()) + info->summary = ota[ESPHOME_F("summary")].as<std::string>(); + if (ota[ESPHOME_F("release_url")].is<const char *>()) + info->release_url = ota[ESPHOME_F("release_url")].as<std::string>(); + + return true; } - this_update->update_info_.firmware_url = ota[ESPHOME_F("path")].as<std::string>(); - this_update->update_info_.md5 = ota[ESPHOME_F("md5")].as<std::string>(); - - if (ota[ESPHOME_F("summary")].is<const char *>()) - this_update->update_info_.summary = ota[ESPHOME_F("summary")].as<std::string>(); - if (ota[ESPHOME_F("release_url")].is<const char *>()) - this_update->update_info_.release_url = ota[ESPHOME_F("release_url")].as<std::string>(); - - return true; } - } - return false; - }); - } - allocator.deallocate(data, content_length); + return false; + }); + } + allocator.deallocate(data, content_length); - if (!valid) { - ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); - // Defer to main loop to avoid race condition on component_state_ read-modify-write - this_update->defer([this_update]() { this_update->status_set_error(LOG_STR("Failed to parse manifest JSON")); }); - UPDATE_RETURN; - } + if (!valid) { + ESP_LOGE(TAG, "Failed to parse JSON from %s", this_update->source_url_.c_str()); + result->error_str = LOG_STR("Failed to parse manifest JSON"); + goto defer; // NOLINT(cppcoreguidelines-avoid-goto) + } - // Merge source_url_ and this_update->update_info_.firmware_url - if (this_update->update_info_.firmware_url.find("http") == std::string::npos) { - std::string path = this_update->update_info_.firmware_url; - if (path[0] == '/') { - std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8)); - this_update->update_info_.firmware_url = domain + path; - } else { - std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1); - this_update->update_info_.firmware_url = domain + path; + // Merge source_url_ and firmware_url + if (!info->firmware_url.empty() && info->firmware_url.find("http") == std::string::npos) { + std::string path = info->firmware_url; + if (path[0] == '/') { + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.find('/', 8)); + info->firmware_url = domain + path; + } else { + std::string domain = this_update->source_url_.substr(0, this_update->source_url_.rfind('/') + 1); + info->firmware_url = domain + path; + } } - } #ifdef ESPHOME_PROJECT_VERSION - this_update->update_info_.current_version = ESPHOME_PROJECT_VERSION; + info->current_version = ESPHOME_PROJECT_VERSION; #else - this_update->update_info_.current_version = ESPHOME_VERSION; + info->current_version = ESPHOME_VERSION; #endif - - bool trigger_update_available = false; - - if (this_update->update_info_.latest_version.empty() || - this_update->update_info_.latest_version == this_update->update_info_.current_version) { - this_update->state_ = update::UPDATE_STATE_NO_UPDATE; - } else { - if (this_update->state_ != update::UPDATE_STATE_AVAILABLE) { - trigger_update_available = true; - } - this_update->state_ = update::UPDATE_STATE_AVAILABLE; } - // Defer to main loop to ensure thread-safe execution of: - // - status_clear_error() performs non-atomic read-modify-write on component_state_ - // - publish_state() triggers API callbacks that write to the shared protobuf buffer - // which can be corrupted if accessed concurrently from task and main loop threads - // - update_available trigger to ensure consistent state when the trigger fires - this_update->defer([this_update, trigger_update_available]() { - this_update->update_info_.has_progress = false; - this_update->update_info_.progress = 0.0f; +defer: + // Release container before vTaskDelete (which doesn't call destructors) + container.reset(); + + // Defer to the main loop so all update_info_ and state_ writes happen on the + // same thread as readers (API, MQTT, web server). This is a single defer for + // both success and error paths to avoid multiple std::function instantiations. + // Lambda captures only 2 pointers (8 bytes) — fits in std::function SBO on supported toolchains. + this_update->defer([this_update, result]() { + if (result->error_str != nullptr) { + this_update->status_set_error(result->error_str); + delete result; + return; + } + + // Determine new state on main loop (avoids extra lambda captures from task) + bool trigger_update_available = false; + update::UpdateState new_state; + if (result->info.latest_version.empty() || result->info.latest_version == result->info.current_version) { + new_state = update::UPDATE_STATE_NO_UPDATE; + } else { + new_state = update::UPDATE_STATE_AVAILABLE; + if (this_update->state_ != update::UPDATE_STATE_AVAILABLE) { + trigger_update_available = true; + } + } + + this_update->update_info_ = std::move(result->info); + this_update->state_ = new_state; + delete result; // Safe: moved-from state is valid for destruction this_update->status_clear_error(); this_update->publish_state(); From af9366fdd4822cb5e8a1a7c571c08d6901993cc3 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:19:26 +1300 Subject: [PATCH 1504/2030] Bump version to 2026.3.0b5 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index ea34106f36..53eae48966 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0b4 +PROJECT_NUMBER = 2026.3.0b5 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 4ba8b1a23f..579235ff69 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0b4" +__version__ = "2026.3.0b5" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 89066e3e20c84c1d2eac1a7ebd54059381c9a253 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:33:00 -1000 Subject: [PATCH 1505/2030] Bump actions/cache from 5.0.3 to 5.0.4 (#14929) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a03579abc..cf5c7029c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: venv # yamllint disable-line rule:line-length @@ -159,7 +159,7 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} - name: Save Python virtual environment cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: venv key: ${{ runner.os }}-${{ steps.restore-python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -198,7 +198,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Restore components graph cache - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -231,7 +231,7 @@ jobs: echo "benchmarks=$(echo "$output" | jq -r '.benchmarks')" >> $GITHUB_OUTPUT - name: Save components graph cache if: github.ref == 'refs/heads/dev' - uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: .temp/components_graph.json key: components-graph-${{ hashFiles('esphome/components/**/*.py') }} @@ -253,7 +253,7 @@ jobs: python-version: "3.13" - name: Restore Python virtual environment id: cache-venv - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: venv key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-venv-${{ needs.common.outputs.cache-key }} @@ -387,14 +387,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }} @@ -466,14 +466,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -555,14 +555,14 @@ jobs: - name: Cache platformio if: github.ref == 'refs/heads/dev' - uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} - name: Cache platformio if: github.ref != 'refs/heads/dev' - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-tidyesp32-${{ hashFiles('platformio.ini') }} @@ -817,7 +817,7 @@ jobs: - name: Restore cached memory analysis id: cache-memory-analysis if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -841,7 +841,7 @@ jobs: - name: Cache platformio if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} @@ -882,7 +882,7 @@ jobs: - name: Save memory analysis to cache if: steps.check-script.outputs.skip != 'true' && steps.check-tests.outputs.skip != 'true' && steps.cache-memory-analysis.outputs.cache-hit != 'true' && steps.build.outcome == 'success' - uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/save@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: memory-analysis-target.json key: ${{ steps.cache-key.outputs.cache-key }} @@ -929,7 +929,7 @@ jobs: python-version: ${{ env.DEFAULT_PYTHON }} cache-key: ${{ needs.common.outputs.cache-key }} - name: Cache platformio - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: ~/.platformio key: platformio-memory-${{ fromJSON(needs.determine-jobs.outputs.memory_impact).platform }}-${{ hashFiles('platformio.ini') }} From 3a47317fc890e04d2148edcb567beac8de6d8268 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:33:15 -1000 Subject: [PATCH 1506/2030] Bump actions/cache from 5.0.3 to 5.0.4 in /.github/actions/restore-python (#14930) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/restore-python/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/restore-python/action.yml b/.github/actions/restore-python/action.yml index 6d7d4f8c12..af54175c01 100644 --- a/.github/actions/restore-python/action.yml +++ b/.github/actions/restore-python/action.yml @@ -22,7 +22,7 @@ runs: python-version: ${{ inputs.python-version }} - name: Restore Python virtual environment id: cache-venv - uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3 + uses: actions/cache/restore@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: venv # yamllint disable-line rule:line-length From ef3afe3e2183d01d34d1910ef8aae22a7f36fd8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:33:29 -1000 Subject: [PATCH 1507/2030] Bump codecov/codecov-action from 5.5.2 to 5.5.3 (#14928) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf5c7029c5..ead87ad087 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: . venv/bin/activate pytest -vv --cov-report=xml --tb=native -n auto tests --ignore=tests/integration/ - name: Upload coverage to Codecov - uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 + uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3 with: token: ${{ secrets.CODECOV_TOKEN }} - name: Save Python virtual environment cache From 16667bf5be6c17df7125d01bff3acac87a3fd8c4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:39:26 -1000 Subject: [PATCH 1508/2030] Bump aioesphomeapi from 44.5.2 to 44.6.0 (#14927) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index da95dd5a13..f8f60f1932 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.5.2 +aioesphomeapi==44.6.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 47909d529982a7e8ac400750b3237ac689822c47 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 15:47:14 -0400 Subject: [PATCH 1509/2030] [hub75] Bump esp-hub75 to 0.3.5 (#14915) --- esphome/components/hub75/display.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index 4cca0cea5d..ede5078c33 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -587,7 +587,7 @@ def _build_config_struct( async def to_code(config: ConfigType) -> None: add_idf_component( name="esphome/esp-hub75", - ref="0.3.4", + ref="0.3.5", ) # Set compile-time configuration via build flags (so external library sees them) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index a847e34b02..620dc6131d 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -64,7 +64,7 @@ dependencies: rules: - if: "target in [esp32s2, esp32s3, esp32p4]" esphome/esp-hub75: - version: 0.3.4 + version: 0.3.5 rules: - if: "target in [esp32, esp32s2, esp32s3, esp32c6, esp32p4]" espressif/mqtt: From cc0655a9048202ccd62fcca881b2fb6fc3a1b12d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 16:42:13 -0400 Subject: [PATCH 1510/2030] [bedjet][light][i2s_audio][ld2412] Fix uninitialized pointers, div-by-zero, and buffer validation (#14925) --- esphome/components/bedjet/bedjet_codec.h | 2 +- .../i2s_audio/speaker/i2s_audio_speaker.h | 2 +- esphome/components/ld2412/ld2412.cpp | 41 +++++++------------ esphome/components/light/effects.py | 2 +- 4 files changed, 18 insertions(+), 29 deletions(-) diff --git a/esphome/components/bedjet/bedjet_codec.h b/esphome/components/bedjet/bedjet_codec.h index 07aee32d54..3936ba2315 100644 --- a/esphome/components/bedjet/bedjet_codec.h +++ b/esphome/components/bedjet/bedjet_codec.h @@ -183,7 +183,7 @@ class BedjetCodec { BedjetPacket packet_; - BedjetStatusPacket *status_packet_; + BedjetStatusPacket *status_packet_{nullptr}; BedjetStatusPacket buf_; }; diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 1d03a4c495..93ec754178 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -110,7 +110,7 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp TaskHandle_t speaker_task_handle_{nullptr}; EventGroupHandle_t event_group_{nullptr}; - QueueHandle_t i2s_event_queue_; + QueueHandle_t i2s_event_queue_{nullptr}; std::weak_ptr<RingBuffer> audio_ring_buffer_; diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 37578dd8da..6ff6963e9f 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -455,12 +455,10 @@ void LD2412Component::handle_periodic_data_() { } #ifdef USE_NUMBER -std::function<void(void)> set_number_value(number::Number *n, float value) { +void set_number_value(number::Number *n, float value) { if (n != nullptr && (!n->has_state() || n->state != value)) { - n->state = value; - return [n, value]() { n->publish_state(value); }; + n->publish_state(value); } - return []() {}; } #endif @@ -504,6 +502,9 @@ bool LD2412Component::handle_ack_data_() { break; case CMD_QUERY_VERSION: { + if (this->buffer_pos_ < 12 + sizeof(this->version_)) { + return false; + } std::memcpy(this->version_, &this->buffer_data_[12], sizeof(this->version_)); char version_s[20]; ld24xx::format_version_str(this->version_, version_s); @@ -596,13 +597,8 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_MOTION_GATE_SENS: { #ifdef USE_NUMBER - std::vector<std::function<void(void)>> updates; - updates.reserve(this->gate_still_threshold_numbers_.size()); - for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) { - updates.push_back(set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i])); - } - for (auto &update : updates) { - update(); + for (size_t i = 0; i < this->gate_move_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) { + set_number_value(this->gate_move_threshold_numbers_[i], this->buffer_data_[10 + i]); } #endif break; @@ -610,13 +606,8 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_STATIC_GATE_SENS: { #ifdef USE_NUMBER - std::vector<std::function<void(void)>> updates; - updates.reserve(this->gate_still_threshold_numbers_.size()); - for (size_t i = 0; i < this->gate_still_threshold_numbers_.size(); i++) { - updates.push_back(set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i])); - } - for (auto &update : updates) { - update(); + for (size_t i = 0; i < this->gate_still_threshold_numbers_.size() && (10 + i) < this->buffer_pos_; i++) { + set_number_value(this->gate_still_threshold_numbers_[i], this->buffer_data_[10 + i]); } #endif break; @@ -625,20 +616,21 @@ bool LD2412Component::handle_ack_data_() { case CMD_QUERY_BASIC_CONF: // Query parameters response { #ifdef USE_NUMBER + if (this->buffer_pos_ < 15) { + return false; + } /* Moving distance range: 9th byte Still distance range: 10th byte */ - std::vector<std::function<void(void)>> updates; - updates.push_back(set_number_value(this->min_distance_gate_number_, this->buffer_data_[10])); - updates.push_back(set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1)); + set_number_value(this->min_distance_gate_number_, this->buffer_data_[10]); + set_number_value(this->max_distance_gate_number_, this->buffer_data_[11] - 1); ESP_LOGV(TAG, "min_distance_gate_number_: %u, max_distance_gate_number_ %u", this->buffer_data_[10], this->buffer_data_[11]); /* None Duration: 11~12th bytes */ - updates.push_back( - set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12]))); + set_number_value(this->timeout_number_, encode_uint16(this->buffer_data_[13], this->buffer_data_[12])); ESP_LOGV(TAG, "timeout_number_: %u", encode_uint16(this->buffer_data_[13], this->buffer_data_[12])); /* Output pin configuration: 13th bytes @@ -650,9 +642,6 @@ bool LD2412Component::handle_ack_data_() { this->out_pin_level_select_->publish_state(out_pin_level_str); } #endif - for (auto &update : updates) { - update(); - } #endif } break; default: diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index 15d9272d1a..4088a78e0d 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -392,7 +392,7 @@ async def addressable_lambda_effect_to_code(config, effect_id): "Rainbow", { cv.Optional(CONF_SPEED, default=10): cv.uint32_t, - cv.Optional(CONF_WIDTH, default=50): cv.uint32_t, + cv.Optional(CONF_WIDTH, default=50): cv.int_range(min=1, max=65535), }, ) async def addressable_rainbow_effect_to_code(config, effect_id): From 4a93d5b54465647a8abfa226e2091650d9057b4c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 16:42:53 -0400 Subject: [PATCH 1511/2030] [vl53l0x][ld2420][ble_client][inkplate] Fix state corruption, crash, OOB read, and shift UB (#14919) --- .../ble_client/sensor/ble_sensor.cpp | 8 +++++++- .../text_sensor/ble_text_sensor.cpp | 4 ++++ esphome/components/inkplate/inkplate.cpp | 2 +- esphome/components/inkplate/inkplate.h | 20 +++++++++---------- esphome/components/ld2420/ld2420.cpp | 20 +++++++++++-------- esphome/components/vl53l0x/vl53l0x_sensor.cpp | 1 + 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/esphome/components/ble_client/sensor/ble_sensor.cpp b/esphome/components/ble_client/sensor/ble_sensor.cpp index fe5f11bbc2..4bd871dc81 100644 --- a/esphome/components/ble_client/sensor/ble_sensor.cpp +++ b/esphome/components/ble_client/sensor/ble_sensor.cpp @@ -102,6 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga break; } case ESP_GATTC_NOTIFY_EVT: { + if (param->notify.value_len == 0) { + ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str()); + break; + } ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(), param->notify.handle, param->notify.value[0]); if (param->notify.handle != this->handle) @@ -131,8 +135,10 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) { if (this->has_data_to_value_) { std::vector<uint8_t> data(value, value + value_len); return this->data_to_value_func_(data); - } else { + } else if (value_len > 0) { return value[0]; + } else { + return NAN; } } diff --git a/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp b/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp index cacf1b4835..7eaa6af076 100644 --- a/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp +++ b/esphome/components/ble_client/text_sensor/ble_text_sensor.cpp @@ -104,6 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ case ESP_GATTC_NOTIFY_EVT: { if (param->notify.handle != this->handle) break; + if (param->notify.value_len == 0) { + ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str()); + break; + } ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(), param->notify.handle, param->notify.value[0]); this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len); diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index 7551c6fc77..326bdff774 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -229,7 +229,7 @@ void Inkplate::eink_off_() { this->oe_pin_->digital_write(false); this->gmod_pin_->digital_write(false); - GPIO.out &= ~(this->get_data_pin_mask_() | (1 << this->cl_pin_->get_pin()) | (1 << this->le_pin_->get_pin())); + GPIO.out &= ~(this->get_data_pin_mask_() | (1UL << this->cl_pin_->get_pin()) | (1UL << this->le_pin_->get_pin())); this->ckv_pin_->digital_write(false); this->sph_pin_->digital_write(false); this->spv_pin_->digital_write(false); diff --git a/esphome/components/inkplate/inkplate.h b/esphome/components/inkplate/inkplate.h index fb4674b522..bcd56b829a 100644 --- a/esphome/components/inkplate/inkplate.h +++ b/esphome/components/inkplate/inkplate.h @@ -152,16 +152,16 @@ class Inkplate : public display::DisplayBuffer, public i2c::I2CDevice { size_t get_buffer_length_(); - int get_data_pin_mask_() { - int data = 0; - data |= (1 << this->display_data_0_pin_->get_pin()); - data |= (1 << this->display_data_1_pin_->get_pin()); - data |= (1 << this->display_data_2_pin_->get_pin()); - data |= (1 << this->display_data_3_pin_->get_pin()); - data |= (1 << this->display_data_4_pin_->get_pin()); - data |= (1 << this->display_data_5_pin_->get_pin()); - data |= (1 << this->display_data_6_pin_->get_pin()); - data |= (1 << this->display_data_7_pin_->get_pin()); + uint32_t get_data_pin_mask_() { + uint32_t data = 0; + data |= (1UL << this->display_data_0_pin_->get_pin()); + data |= (1UL << this->display_data_1_pin_->get_pin()); + data |= (1UL << this->display_data_2_pin_->get_pin()); + data |= (1UL << this->display_data_3_pin_->get_pin()); + data |= (1UL << this->display_data_4_pin_->get_pin()); + data |= (1UL << this->display_data_5_pin_->get_pin()); + data |= (1UL << this->display_data_6_pin_->get_pin()); + data |= (1UL << this->display_data_7_pin_->get_pin()); return data; } diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 1e671363c9..ae622cda28 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -170,14 +170,18 @@ static uint8_t calc_checksum(void *data, size_t size) { return checksum; } -static int get_firmware_int(const char *version_string) { - std::string version_str = version_string; - if (version_str[0] == 'v') { - version_str.erase(0, 1); +static int32_t get_firmware_int(const char *version_string) { + // Convert "v1.5.4" -> 154 by skipping 'v' and '.', accumulating digits + const char *p = (*version_string == 'v') ? version_string + 1 : version_string; + int32_t result = 0; + for (; *p != '\0'; p++) { + if (*p == '.') + continue; + if (*p < '0' || *p > '9') + return 0; + result = result * 10 + (*p - '0'); } - version_str.erase(remove(version_str.begin(), version_str.end(), '.'), version_str.end()); - int version_integer = stoi(version_str); - return version_integer; + return result; } float LD2420Component::get_setup_priority() const { return setup_priority::BUS; } @@ -683,7 +687,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { retry = 0; } if (this->cmd_reply_.error > 0) { - this->handle_cmd_error(error); + this->handle_cmd_error(this->cmd_reply_.error); } } return error; diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.cpp b/esphome/components/vl53l0x/vl53l0x_sensor.cpp index 0b2b40d723..8a76ed7760 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.cpp +++ b/esphome/components/vl53l0x/vl53l0x_sensor.cpp @@ -266,6 +266,7 @@ void VL53L0XSensor::update() { this->status_momentary_warning("update", 5000); ESP_LOGW(TAG, "%s - update called before prior reading complete - initiated:%d waiting_for_interrupt:%d", this->name_.c_str(), this->initiated_read_, this->waiting_for_interrupt_); + return; } // initiate single shot measurement From 73a49493a261a2a7fb748875e66d85bf0ff2b050 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 16:43:42 -0400 Subject: [PATCH 1512/2030] [vbus][shelly_dimmer][st7789v][modbus_controller] Fix integer overflows, off-by-one, and coordinate swap (#14916) --- .../modbus_controller/modbus_controller.h | 2 +- .../shelly_dimmer/shelly_dimmer.cpp | 2 +- esphome/components/st7789v/st7789v.cpp | 4 +-- .../components/vbus/sensor/vbus_sensor.cpp | 26 ++++++++++++------- esphome/components/vbus/vbus.cpp | 3 +-- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index fca2926568..bd3d4d705e 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -178,7 +178,7 @@ template<typename N> N mask_and_shift_by_rightbit(N data, uint32_t mask) { return result; } for (size_t pos = 0; pos < sizeof(N) << 3; pos++) { - if ((mask & (1 << pos)) != 0) + if ((mask & (1UL << pos)) != 0) return result >> pos; } return 0; diff --git a/esphome/components/shelly_dimmer/shelly_dimmer.cpp b/esphome/components/shelly_dimmer/shelly_dimmer.cpp index 88fcbcbfe1..230fb963b1 100644 --- a/esphome/components/shelly_dimmer/shelly_dimmer.cpp +++ b/esphome/components/shelly_dimmer/shelly_dimmer.cpp @@ -402,7 +402,7 @@ bool ShellyDimmer::handle_frame_() { // Handle response. switch (cmd) { case SHELLY_DIMMER_PROTO_CMD_POLL: { - if (payload_len < 16) { + if (payload_len < 17) { return false; } diff --git a/esphome/components/st7789v/st7789v.cpp b/esphome/components/st7789v/st7789v.cpp index 6e4360ae74..dc03fb04ca 100644 --- a/esphome/components/st7789v/st7789v.cpp +++ b/esphome/components/st7789v/st7789v.cpp @@ -156,9 +156,9 @@ void ST7789V::update() { void ST7789V::set_model_str(const char *model_str) { this->model_str_ = model_str; } void ST7789V::write_display_data() { - uint16_t x1 = this->offset_height_; + uint16_t x1 = this->offset_width_; uint16_t x2 = x1 + get_width_internal() - 1; - uint16_t y1 = this->offset_width_; + uint16_t y1 = this->offset_height_; uint16_t y2 = y1 + get_height_internal() - 1; this->enable(); diff --git a/esphome/components/vbus/sensor/vbus_sensor.cpp b/esphome/components/vbus/sensor/vbus_sensor.cpp index 1cabb49703..407a81c83b 100644 --- a/esphome/components/vbus/sensor/vbus_sensor.cpp +++ b/esphome/components/vbus/sensor/vbus_sensor.cpp @@ -48,8 +48,8 @@ void DeltaSolBSPlusSensor::handle_message(std::vector<uint8_t> &message) { if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 18)); if (this->heat_quantity_sensor_ != nullptr) { - this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000 + - get_u16(message, 24) * 1000000); + this->heat_quantity_sensor_->publish_state(get_u16(message, 20) + get_u16(message, 22) * 1000.0f + + get_u16(message, 24) * 1000000.0f); } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 12)); @@ -130,8 +130,8 @@ void DeltaSolCSensor::handle_message(std::vector<uint8_t> &message) { if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); if (this->heat_quantity_sensor_ != nullptr) { - this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000 + - get_u16(message, 20) * 1000000); + this->heat_quantity_sensor_->publish_state(get_u16(message, 16) + get_u16(message, 18) * 1000.0f + + get_u16(message, 20) * 1000000.0f); } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); @@ -162,8 +162,10 @@ void DeltaSolCS2Sensor::handle_message(std::vector<uint8_t> &message) { this->pump_speed_sensor_->publish_state(message[12]); if (this->operating_hours_sensor_ != nullptr) this->operating_hours_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 26) << 16) + get_u16(message, 24)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 26)) << 16) | + get_u16(message, 24)); + } if (this->version_sensor_ != nullptr) this->version_sensor_->publish_state(get_u16(message, 28) * 0.01f); } @@ -204,8 +206,10 @@ void DeltaSolCS4Sensor::handle_message(std::vector<uint8_t> &message) { this->operating_hours1_sensor_->publish_state(get_u16(message, 10)); if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 30)) << 16) | + get_u16(message, 28)); + } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); if (this->version_sensor_ != nullptr) @@ -250,8 +254,10 @@ void DeltaSolCSPlusSensor::handle_message(std::vector<uint8_t> &message) { this->operating_hours1_sensor_->publish_state(get_u16(message, 10)); if (this->operating_hours2_sensor_ != nullptr) this->operating_hours2_sensor_->publish_state(get_u16(message, 14)); - if (this->heat_quantity_sensor_ != nullptr) - this->heat_quantity_sensor_->publish_state((get_u16(message, 30) << 16) + get_u16(message, 28)); + if (this->heat_quantity_sensor_ != nullptr) { + this->heat_quantity_sensor_->publish_state((static_cast<uint32_t>(get_u16(message, 30)) << 16) | + get_u16(message, 28)); + } if (this->time_sensor_ != nullptr) this->time_sensor_->publish_state(get_u16(message, 22)); if (this->version_sensor_ != nullptr) diff --git a/esphome/components/vbus/vbus.cpp b/esphome/components/vbus/vbus.cpp index c6786ee31e..195d6ed568 100644 --- a/esphome/components/vbus/vbus.cpp +++ b/esphome/components/vbus/vbus.cpp @@ -67,8 +67,7 @@ void VBus::loop() { } septet_spread(this->buffer_.data(), 7, 6, this->buffer_[13]); uint16_t id = (this->buffer_[8] << 8) + this->buffer_[7]; - uint32_t value = - (this->buffer_[12] << 24) + (this->buffer_[11] << 16) + (this->buffer_[10] << 8) + this->buffer_[9]; + uint32_t value = encode_uint32(this->buffer_[12], this->buffer_[11], this->buffer_[10], this->buffer_[9]); ESP_LOGV(TAG, "P1 C%04x %04x->%04x: %04x %04" PRIx32 " (%" PRIu32 ")", this->command_, this->source_, this->dest_, id, value, value); } else if ((this->protocol_ == 0x10) && (this->buffer_.size() == 9)) { From 097e6eb41fba8fede3495e63ae0357880b26bd9d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 17:42:56 -0400 Subject: [PATCH 1513/2030] [i2s_audio] Remove legacy I2S driver support (#14932) --- CODEOWNERS | 1 - esphome/components/i2s_audio/__init__.py | 101 ++----- esphome/components/i2s_audio/i2s_audio.h | 35 --- .../i2s_audio/media_player/__init__.py | 122 +------- .../media_player/i2s_audio_media_player.cpp | 260 ------------------ .../media_player/i2s_audio_media_player.h | 87 ------ .../i2s_audio/microphone/__init__.py | 20 +- .../microphone/i2s_audio_microphone.cpp | 97 +------ .../microphone/i2s_audio_microphone.h | 21 -- .../components/i2s_audio/speaker/__init__.py | 36 +-- .../i2s_audio/speaker/i2s_audio_speaker.cpp | 126 --------- .../i2s_audio/speaker/i2s_audio_speaker.h | 18 -- esphome/core/defines.h | 1 - .../components/i2s_audio/test.esp32-ard.yaml | 16 -- tests/components/media_player/common.yaml | 16 +- 15 files changed, 50 insertions(+), 907 deletions(-) delete mode 100644 esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp delete mode 100644 esphome/components/i2s_audio/media_player/i2s_audio_media_player.h delete mode 100644 tests/components/i2s_audio/test.esp32-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index e72b164761..88f62c3194 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -244,7 +244,6 @@ esphome/components/hyt271/* @Philippe12 esphome/components/i2c/* @esphome/core esphome/components/i2c_device/* @gabest11 esphome/components/i2s_audio/* @jesserockz -esphome/components/i2s_audio/media_player/* @jesserockz esphome/components/i2s_audio/microphone/* @jesserockz esphome/components/i2s_audio/speaker/* @jesserockz @kahrendt esphome/components/iaqcore/* @yozik04 diff --git a/esphome/components/i2s_audio/__init__.py b/esphome/components/i2s_audio/__init__.py index 977a239497..ffa63f5ee8 100644 --- a/esphome/components/i2s_audio/__init__.py +++ b/esphome/components/i2s_audio/__init__.py @@ -53,8 +53,6 @@ CONF_RIGHT = "right" CONF_STEREO = "stereo" CONF_BOTH = "both" -CONF_USE_LEGACY = "use_legacy" - i2s_audio_ns = cg.esphome_ns.namespace("i2s_audio") I2SAudioComponent = i2s_audio_ns.class_("I2SAudioComponent", cg.Component) I2SAudioBase = i2s_audio_ns.class_( @@ -154,20 +152,6 @@ def validate_mclk_divisible_by_3(config): return config -# Key for storing legacy driver setting in CORE.data -I2S_USE_LEGACY_DRIVER_KEY = "i2s_use_legacy_driver" - - -def _get_use_legacy_driver(): - """Get the legacy driver setting from CORE.data.""" - return CORE.data.get(I2S_USE_LEGACY_DRIVER_KEY) - - -def _set_use_legacy_driver(value: bool) -> None: - """Set the legacy driver setting in CORE.data.""" - CORE.data[I2S_USE_LEGACY_DRIVER_KEY] = value - - def i2s_audio_component_schema( class_: MockObjClass, *, @@ -192,10 +176,6 @@ def i2s_audio_component_schema( *I2S_MODE_OPTIONS, lower=True ), cv.Optional(CONF_USE_APLL, default=False): cv.boolean, - cv.Optional(CONF_BITS_PER_CHANNEL, default="default"): cv.All( - cv.Any(cv.float_with_unit("bits", "bit"), "default"), - cv.one_of(*I2S_BITS_PER_CHANNEL), - ), cv.Optional(CONF_MCLK_MULTIPLE, default=256): cv.one_of(*I2S_MCLK_MULTIPLE), } ) @@ -203,59 +183,28 @@ def i2s_audio_component_schema( async def register_i2s_audio_component(var, config): await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) - if use_legacy(): - cg.add(var.set_i2s_mode(I2S_MODE_OPTIONS[config[CONF_I2S_MODE]])) - cg.add(var.set_channel(I2S_CHANNELS[config[CONF_CHANNEL]])) - cg.add( - var.set_bits_per_sample(I2S_BITS_PER_SAMPLE[config[CONF_BITS_PER_SAMPLE]]) - ) - cg.add( - var.set_bits_per_channel( - I2S_BITS_PER_CHANNEL[config[CONF_BITS_PER_CHANNEL]] - ) - ) - else: - cg.add(var.set_i2s_role(I2S_ROLE_OPTIONS[config[CONF_I2S_MODE]])) - slot_mode = config[CONF_CHANNEL] - if slot_mode != CONF_STEREO: - slot_mode = CONF_MONO - slot_mask = config[CONF_CHANNEL] - if slot_mask not in [CONF_LEFT, CONF_RIGHT]: - slot_mask = CONF_BOTH - cg.add(var.set_slot_mode(I2S_SLOT_MODE[slot_mode])) - cg.add(var.set_std_slot_mask(I2S_STD_SLOT_MASK[slot_mask])) - cg.add(var.set_slot_bit_width(I2S_SLOT_BIT_WIDTH[config[CONF_BITS_PER_SAMPLE]])) + cg.add(var.set_i2s_role(I2S_ROLE_OPTIONS[config[CONF_I2S_MODE]])) + slot_mode = config[CONF_CHANNEL] + if slot_mode != CONF_STEREO: + slot_mode = CONF_MONO + slot_mask = config[CONF_CHANNEL] + if slot_mask not in [CONF_LEFT, CONF_RIGHT]: + slot_mask = CONF_BOTH + cg.add(var.set_slot_mode(I2S_SLOT_MODE[slot_mode])) + cg.add(var.set_std_slot_mask(I2S_STD_SLOT_MASK[slot_mask])) + cg.add(var.set_slot_bit_width(I2S_SLOT_BIT_WIDTH[config[CONF_BITS_PER_SAMPLE]])) cg.add(var.set_sample_rate(config[CONF_SAMPLE_RATE])) cg.add(var.set_use_apll(config[CONF_USE_APLL])) cg.add(var.set_mclk_multiple(I2S_MCLK_MULTIPLE[config[CONF_MCLK_MULTIPLE]])) -def validate_use_legacy(value): - if CONF_USE_LEGACY in value: - existing_value = _get_use_legacy_driver() - if (existing_value is not None) and (existing_value != value[CONF_USE_LEGACY]): - raise cv.Invalid( - f"All i2s_audio components must set {CONF_USE_LEGACY} to the same value." - ) - if (not value[CONF_USE_LEGACY]) and (CORE.using_arduino): - raise cv.Invalid("Arduino supports only the legacy i2s driver") - _set_use_legacy_driver(value[CONF_USE_LEGACY]) - elif CORE.using_arduino: - _set_use_legacy_driver(True) - return value - - -CONFIG_SCHEMA = cv.All( - cv.Schema( - { - cv.GenerateID(): cv.declare_id(I2SAudioComponent), - cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_I2S_MCLK_PIN): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_USE_LEGACY): cv.boolean, - }, - ), - validate_use_legacy, +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(I2SAudioComponent), + cv.Required(CONF_I2S_LRCLK_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_I2S_BCLK_PIN): pins.internal_gpio_output_pin_number, + cv.Optional(CONF_I2S_MCLK_PIN): pins.internal_gpio_output_pin_number, + }, ) @@ -311,13 +260,6 @@ def _assign_ports() -> None: def _final_validate(_): - from esphome.components.esp32 import idf_version - - if use_legacy() and idf_version() >= cv.Version(6, 0, 0): - raise cv.Invalid( - "The legacy I2S driver is not available in ESP-IDF 6.0+. " - "Set 'use_legacy: false' in i2s_audio configuration." - ) i2s_audio_configs = fv.full_config.get()[CONF_I2S_AUDIO] variant = get_esp32_variant() if variant not in I2S_PORTS: @@ -329,10 +271,6 @@ def _final_validate(_): _assign_ports() -def use_legacy(): - return _get_use_legacy_driver() - - FINAL_VALIDATE_SCHEMA = _final_validate @@ -349,11 +287,6 @@ async def to_code(config): # Re-enable ESP-IDF's I2S driver (excluded by default to save compile time) include_builtin_idf_component("esp_driver_i2s") - if use_legacy(): - cg.add_define("USE_I2S_LEGACY") - # Legacy I2S API lives in the "driver" shim component (driver/i2s.h) - include_builtin_idf_component("driver") - # Helps avoid callbacks being skipped due to processor load add_idf_sdkconfig_option("CONFIG_I2S_ISR_IRAM_SAFE", True) diff --git a/esphome/components/i2s_audio/i2s_audio.h b/esphome/components/i2s_audio/i2s_audio.h index f26ffddd46..5b260fa7ed 100644 --- a/esphome/components/i2s_audio/i2s_audio.h +++ b/esphome/components/i2s_audio/i2s_audio.h @@ -6,11 +6,7 @@ #include "esphome/core/defines.h" #include "esphome/core/helpers.h" #include <esp_idf_version.h> -#ifdef USE_I2S_LEGACY -#include <driver/i2s.h> -#else #include <driver/i2s_std.h> -#endif namespace esphome { namespace i2s_audio { @@ -19,33 +15,19 @@ class I2SAudioComponent; class I2SAudioBase : public Parented<I2SAudioComponent> { public: -#ifdef USE_I2S_LEGACY - void set_i2s_mode(i2s_mode_t mode) { this->i2s_mode_ = mode; } - void set_channel(i2s_channel_fmt_t channel) { this->channel_ = channel; } - void set_bits_per_sample(i2s_bits_per_sample_t bits_per_sample) { this->bits_per_sample_ = bits_per_sample; } - void set_bits_per_channel(i2s_bits_per_chan_t bits_per_channel) { this->bits_per_channel_ = bits_per_channel; } -#else void set_i2s_role(i2s_role_t role) { this->i2s_role_ = role; } void set_slot_mode(i2s_slot_mode_t slot_mode) { this->slot_mode_ = slot_mode; } void set_std_slot_mask(i2s_std_slot_mask_t std_slot_mask) { this->std_slot_mask_ = std_slot_mask; } void set_slot_bit_width(i2s_slot_bit_width_t slot_bit_width) { this->slot_bit_width_ = slot_bit_width; } -#endif void set_sample_rate(uint32_t sample_rate) { this->sample_rate_ = sample_rate; } void set_use_apll(uint32_t use_apll) { this->use_apll_ = use_apll; } void set_mclk_multiple(i2s_mclk_multiple_t mclk_multiple) { this->mclk_multiple_ = mclk_multiple; } protected: -#ifdef USE_I2S_LEGACY - i2s_mode_t i2s_mode_{}; - i2s_channel_fmt_t channel_; - i2s_bits_per_sample_t bits_per_sample_; - i2s_bits_per_chan_t bits_per_channel_; -#else i2s_role_t i2s_role_{}; i2s_slot_mode_t slot_mode_; i2s_std_slot_mask_t std_slot_mask_; i2s_slot_bit_width_t slot_bit_width_; -#endif uint32_t sample_rate_; bool use_apll_; i2s_mclk_multiple_t mclk_multiple_; @@ -57,17 +39,6 @@ class I2SAudioOut : public I2SAudioBase {}; class I2SAudioComponent : public Component { public: -#ifdef USE_I2S_LEGACY - i2s_pin_config_t get_pin_config() const { - return { - .mck_io_num = this->mclk_pin_, - .bck_io_num = this->bclk_pin_, - .ws_io_num = this->lrclk_pin_, - .data_out_num = I2S_PIN_NO_CHANGE, - .data_in_num = I2S_PIN_NO_CHANGE, - }; - } -#else i2s_std_gpio_config_t get_pin_config() const { return {.mclk = (gpio_num_t) this->mclk_pin_, .bclk = (gpio_num_t) this->bclk_pin_, @@ -80,7 +51,6 @@ class I2SAudioComponent : public Component { .ws_inv = false, }}; } -#endif void set_mclk_pin(int pin) { this->mclk_pin_ = pin; } void set_bclk_pin(int pin) { this->bclk_pin_ = pin; } @@ -101,13 +71,8 @@ class I2SAudioComponent : public Component { I2SAudioIn *audio_in_{nullptr}; I2SAudioOut *audio_out_{nullptr}; -#ifdef USE_I2S_LEGACY - int mclk_pin_{I2S_PIN_NO_CHANGE}; - int bclk_pin_{I2S_PIN_NO_CHANGE}; -#else int mclk_pin_{I2S_GPIO_UNUSED}; int bclk_pin_{I2S_GPIO_UNUSED}; -#endif int lrclk_pin_; int port_{}; }; diff --git a/esphome/components/i2s_audio/media_player/__init__.py b/esphome/components/i2s_audio/media_player/__init__.py index 426b211f47..b366d4fb05 100644 --- a/esphome/components/i2s_audio/media_player/__init__.py +++ b/esphome/components/i2s_audio/media_player/__init__.py @@ -1,121 +1,7 @@ -from esphome import pins -import esphome.codegen as cg -from esphome.components import esp32, media_player import esphome.config_validation as cv -from esphome.const import CONF_MODE -from .. import ( - CONF_I2S_AUDIO_ID, - CONF_I2S_DOUT_PIN, - CONF_LEFT, - CONF_MONO, - CONF_RIGHT, - CONF_STEREO, - I2SAudioComponent, - I2SAudioOut, - i2s_audio_ns, - use_legacy, +CONFIG_SCHEMA = cv.invalid( + "The I2S audio media player has been removed. " + "Use the speaker media player component instead. " + "See https://esphome.io/components/media_player/speaker.html for details." ) - -CODEOWNERS = ["@jesserockz"] -DEPENDENCIES = ["i2s_audio"] - -I2SAudioMediaPlayer = i2s_audio_ns.class_( - "I2SAudioMediaPlayer", cg.Component, media_player.MediaPlayer, I2SAudioOut -) - -i2s_dac_mode_t = cg.global_ns.enum("i2s_dac_mode_t") - - -CONF_MUTE_PIN = "mute_pin" -CONF_AUDIO_ID = "audio_id" -CONF_DAC_TYPE = "dac_type" -CONF_I2S_COMM_FMT = "i2s_comm_fmt" - -INTERNAL_DAC_OPTIONS = { - CONF_LEFT: i2s_dac_mode_t.I2S_DAC_CHANNEL_LEFT_EN, - CONF_RIGHT: i2s_dac_mode_t.I2S_DAC_CHANNEL_RIGHT_EN, - CONF_STEREO: i2s_dac_mode_t.I2S_DAC_CHANNEL_BOTH_EN, -} - -EXTERNAL_DAC_OPTIONS = [CONF_MONO, CONF_STEREO] - -NO_INTERNAL_DAC_VARIANTS = [esp32.VARIANT_ESP32S2] - -I2C_COMM_FMT_OPTIONS = ["lsb", "msb"] - - -def validate_esp32_variant(config): - if config[CONF_DAC_TYPE] != "internal": - return config - variant = esp32.get_esp32_variant() - if variant in NO_INTERNAL_DAC_VARIANTS: - raise cv.Invalid(f"{variant} does not have an internal DAC") - return config - - -CONFIG_SCHEMA = cv.All( - cv.typed_schema( - { - "internal": media_player.media_player_schema(I2SAudioMediaPlayer) - .extend( - { - cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), - cv.Required(CONF_MODE): cv.enum(INTERNAL_DAC_OPTIONS, lower=True), - } - ) - .extend(cv.COMPONENT_SCHEMA), - "external": media_player.media_player_schema(I2SAudioMediaPlayer) - .extend( - { - cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), - cv.Required( - CONF_I2S_DOUT_PIN - ): pins.internal_gpio_output_pin_number, - cv.Optional(CONF_MUTE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_MODE, default="mono"): cv.one_of( - *EXTERNAL_DAC_OPTIONS, lower=True - ), - cv.Optional(CONF_I2S_COMM_FMT, default="msb"): cv.one_of( - *I2C_COMM_FMT_OPTIONS, lower=True - ), - } - ) - .extend(cv.COMPONENT_SCHEMA), - }, - key=CONF_DAC_TYPE, - ), - cv.only_with_arduino, - validate_esp32_variant, -) - - -def _final_validate(_): - if not use_legacy(): - raise cv.Invalid("I2S media player is only compatible with legacy i2s driver") - - -FINAL_VALIDATE_SCHEMA = _final_validate - - -async def to_code(config): - var = await media_player.new_media_player(config) - await cg.register_component(var, config) - - await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) - - if config[CONF_DAC_TYPE] == "internal": - cg.add(var.set_internal_dac_mode(config[CONF_MODE])) - else: - cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) - if CONF_MUTE_PIN in config: - pin = await cg.gpio_pin_expression(config[CONF_MUTE_PIN]) - cg.add(var.set_mute_pin(pin)) - cg.add(var.set_external_dac_channels(2 if config[CONF_MODE] == "stereo" else 1)) - cg.add(var.set_i2s_comm_fmt_lsb(config[CONF_I2S_COMM_FMT] == "lsb")) - - cg.add_library("WiFi", None) - cg.add_library("NetworkClientSecure", None) - cg.add_library("HTTPClient", None) - cg.add_library("esphome/ESP32-audioI2S", "2.3.0") - cg.add_build_flag("-DAUDIO_NO_SD_FS") 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 deleted file mode 100644 index 369c964a85..0000000000 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include "i2s_audio_media_player.h" - -#ifdef USE_ESP32_FRAMEWORK_ARDUINO - -#include "esphome/core/log.h" - -namespace esphome { -namespace i2s_audio { - -static const char *const TAG = "audio"; - -void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) { - media_player::MediaPlayerState play_state = media_player::MEDIA_PLAYER_STATE_PLAYING; - auto announcement = call.get_announcement(); - if (announcement.has_value()) { - play_state = *announcement ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING : media_player::MEDIA_PLAYER_STATE_PLAYING; - } - auto media_url = call.get_media_url(); - if (media_url.has_value()) { - this->current_url_ = media_url; - if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) { - if (this->audio_->isRunning()) { - this->audio_->stopSong(); - } - this->audio_->connecttohost(media_url->c_str()); - this->state = play_state; - } else { - this->start(); - } - } - - if (play_state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) { - this->is_announcement_ = true; - } - - auto vol = call.get_volume(); - if (vol.has_value()) { - this->volume = *vol; - this->set_volume_(volume); - this->unmute_(); - } - auto cmd = call.get_command(); - if (cmd.has_value()) { - switch (*cmd) { - case media_player::MEDIA_PLAYER_COMMAND_MUTE: - this->mute_(); - break; - case media_player::MEDIA_PLAYER_COMMAND_UNMUTE: - this->unmute_(); - break; - case media_player::MEDIA_PLAYER_COMMAND_VOLUME_UP: { - float new_volume = this->volume + 0.1f; - if (new_volume > 1.0f) - new_volume = 1.0f; - this->set_volume_(new_volume); - this->unmute_(); - break; - } - case media_player::MEDIA_PLAYER_COMMAND_VOLUME_DOWN: { - float new_volume = this->volume - 0.1f; - if (new_volume < 0.0f) - new_volume = 0.0f; - this->set_volume_(new_volume); - this->unmute_(); - break; - } - default: - break; - } - if (this->i2s_state_ != I2S_STATE_RUNNING) { - return; - } - switch (*cmd) { - case media_player::MEDIA_PLAYER_COMMAND_PLAY: - if (!this->audio_->isRunning()) - this->audio_->pauseResume(); - this->state = play_state; - break; - case media_player::MEDIA_PLAYER_COMMAND_PAUSE: - if (this->audio_->isRunning()) - this->audio_->pauseResume(); - this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; - break; - case media_player::MEDIA_PLAYER_COMMAND_STOP: - this->stop(); - break; - case media_player::MEDIA_PLAYER_COMMAND_TOGGLE: - this->audio_->pauseResume(); - if (this->audio_->isRunning()) { - this->state = media_player::MEDIA_PLAYER_STATE_PLAYING; - } else { - this->state = media_player::MEDIA_PLAYER_STATE_PAUSED; - } - break; - default: - break; - } - } - this->publish_state(); -} - -void I2SAudioMediaPlayer::mute_() { - if (this->mute_pin_ != nullptr) { - this->mute_pin_->digital_write(true); - } else { - this->set_volume_(0.0f, false); - } - this->muted_ = true; -} -void I2SAudioMediaPlayer::unmute_() { - if (this->mute_pin_ != nullptr) { - this->mute_pin_->digital_write(false); - } else { - this->set_volume_(this->volume, false); - } - this->muted_ = false; -} -void I2SAudioMediaPlayer::set_volume_(float volume, bool publish) { - if (this->audio_ != nullptr) - this->audio_->setVolume(remap<uint8_t, float>(volume, 0.0f, 1.0f, 0, 21)); - if (publish) - this->volume = volume; -} - -void I2SAudioMediaPlayer::setup() { this->state = media_player::MEDIA_PLAYER_STATE_IDLE; } - -void I2SAudioMediaPlayer::loop() { - switch (this->i2s_state_) { - case I2S_STATE_STARTING: - this->start_(); - break; - case I2S_STATE_RUNNING: - this->play_(); - break; - case I2S_STATE_STOPPING: - this->stop_(); - break; - case I2S_STATE_STOPPED: - break; - } -} - -void I2SAudioMediaPlayer::play_() { - this->audio_->loop(); - if ((this->state == media_player::MEDIA_PLAYER_STATE_PLAYING || - this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) && - !this->audio_->isRunning()) { - this->stop(); - } -} - -void I2SAudioMediaPlayer::start() { this->i2s_state_ = I2S_STATE_STARTING; } -void I2SAudioMediaPlayer::start_() { - if (!this->parent_->try_lock()) { - return; // Waiting for another i2s to return lock - } - -#if SOC_I2S_SUPPORTS_DAC - if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { - this->audio_ = make_unique<Audio>(true, this->internal_dac_mode_, this->parent_->get_port()); - } else { -#endif - this->audio_ = make_unique<Audio>(false, 3, this->parent_->get_port()); - - i2s_pin_config_t pin_config = this->parent_->get_pin_config(); - pin_config.data_out_num = this->dout_pin_; - i2s_set_pin(this->parent_->get_port(), &pin_config); - - this->audio_->setI2SCommFMT_LSB(this->i2s_comm_fmt_lsb_); - this->audio_->forceMono(this->external_dac_channels_ == 1); - if (this->mute_pin_ != nullptr) { - this->mute_pin_->setup(); - this->mute_pin_->digital_write(false); - } -#if SOC_I2S_SUPPORTS_DAC - } -#endif - - this->i2s_state_ = I2S_STATE_RUNNING; - this->high_freq_.start(); - this->audio_->setVolume(remap<uint8_t, float>(this->volume, 0.0f, 1.0f, 0, 21)); - 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_) { - this->state = media_player::MEDIA_PLAYER_STATE_ANNOUNCING; - } - this->publish_state(); - } -} -void I2SAudioMediaPlayer::stop() { - if (this->i2s_state_ == I2S_STATE_STOPPED) { - return; - } - if (this->i2s_state_ == I2S_STATE_STARTING) { - this->i2s_state_ = I2S_STATE_STOPPED; - return; - } - this->i2s_state_ = I2S_STATE_STOPPING; -} -void I2SAudioMediaPlayer::stop_() { - if (this->audio_->isRunning()) { - this->audio_->stopSong(); - return; - } - - this->audio_ = nullptr; - this->current_url_ = {}; - this->parent_->unlock(); - this->i2s_state_ = I2S_STATE_STOPPED; - - 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() { - auto traits = media_player::MediaPlayerTraits(); - traits.set_supports_pause(true); - return traits; -}; - -void I2SAudioMediaPlayer::dump_config() { - ESP_LOGCONFIG(TAG, "Audio:"); - if (this->is_failed()) { - ESP_LOGCONFIG(TAG, "Audio failed to initialize!"); - return; - } -#if SOC_I2S_SUPPORTS_DAC - if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { - switch (this->internal_dac_mode_) { - case I2S_DAC_CHANNEL_LEFT_EN: - ESP_LOGCONFIG(TAG, " Internal DAC mode: Left"); - break; - case I2S_DAC_CHANNEL_RIGHT_EN: - ESP_LOGCONFIG(TAG, " Internal DAC mode: Right"); - break; - case I2S_DAC_CHANNEL_BOTH_EN: - ESP_LOGCONFIG(TAG, " Internal DAC mode: Left & Right"); - break; - default: - break; - } - } else { -#endif - ESP_LOGCONFIG(TAG, - " External DAC channels: %d\n" - " I2S DOUT Pin: %d", - this->external_dac_channels_, this->dout_pin_); - LOG_PIN(" Mute Pin: ", this->mute_pin_); -#if SOC_I2S_SUPPORTS_DAC - } -#endif -} - -} // namespace i2s_audio -} // namespace esphome - -#endif // USE_ESP32_FRAMEWORK_ARDUINO 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 deleted file mode 100644 index 4672f94d7e..0000000000 --- a/esphome/components/i2s_audio/media_player/i2s_audio_media_player.h +++ /dev/null @@ -1,87 +0,0 @@ -#pragma once - -#ifdef USE_ESP32_FRAMEWORK_ARDUINO - -#include "../i2s_audio.h" - -#include <driver/i2s.h> - -#include "esphome/components/media_player/media_player.h" -#include "esphome/core/component.h" -#include "esphome/core/gpio.h" -#include "esphome/core/helpers.h" - -#include <Audio.h> - -namespace esphome { -namespace i2s_audio { - -enum I2SState : uint8_t { - I2S_STATE_STOPPED = 0, - I2S_STATE_STARTING, - I2S_STATE_RUNNING, - I2S_STATE_STOPPING, -}; - -class I2SAudioMediaPlayer : public Component, public Parented<I2SAudioComponent>, public media_player::MediaPlayer { - public: - void setup() override; - float get_setup_priority() const override { return esphome::setup_priority::LATE; } - - void loop() override; - - void dump_config() override; - - void set_dout_pin(uint8_t pin) { this->dout_pin_ = pin; } - void set_mute_pin(GPIOPin *mute_pin) { this->mute_pin_ = mute_pin; } -#if SOC_I2S_SUPPORTS_DAC - void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; } -#endif - void set_external_dac_channels(uint8_t channels) { this->external_dac_channels_ = channels; } - - void set_i2s_comm_fmt_lsb(bool lsb) { this->i2s_comm_fmt_lsb_ = lsb; } - - media_player::MediaPlayerTraits get_traits() override; - - bool is_muted() const override { return this->muted_; } - - void start(); - void stop(); - - protected: - void control(const media_player::MediaPlayerCall &call) override; - - void mute_(); - void unmute_(); - void set_volume_(float volume, bool publish = true); - - void start_(); - void stop_(); - void play_(); - - I2SState i2s_state_{I2S_STATE_STOPPED}; - std::unique_ptr<Audio> audio_; - - uint8_t dout_pin_{0}; - - GPIOPin *mute_pin_{nullptr}; - bool muted_{false}; - float unmuted_volume_{0}; - -#if SOC_I2S_SUPPORTS_DAC - i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; -#endif - uint8_t external_dac_channels_; - - bool i2s_comm_fmt_lsb_; - - HighFrequencyLoopRequester high_freq_; - - optional<std::string> current_url_{}; - bool is_announcement_{false}; -}; - -} // namespace i2s_audio -} // namespace esphome - -#endif // USE_ESP32_FRAMEWORK_ARDUINO diff --git a/esphome/components/i2s_audio/microphone/__init__.py b/esphome/components/i2s_audio/microphone/__init__.py index aa15625cd7..761cbb7f48 100644 --- a/esphome/components/i2s_audio/microphone/__init__.py +++ b/esphome/components/i2s_audio/microphone/__init__.py @@ -1,14 +1,13 @@ from esphome import pins import esphome.codegen as cg from esphome.components import audio, esp32, microphone -from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin +from esphome.components.adc import validate_adc_pin import esphome.config_validation as cv from esphome.const import ( CONF_BITS_PER_SAMPLE, CONF_CHANNEL, CONF_ID, CONF_NUM_CHANNELS, - CONF_NUMBER, CONF_SAMPLE_RATE, ) @@ -23,7 +22,6 @@ from .. import ( i2s_audio_component_schema, i2s_audio_ns, register_i2s_audio_component, - use_legacy, validate_mclk_divisible_by_3, ) @@ -127,8 +125,10 @@ CONFIG_SCHEMA = cv.All( def _final_validate(config): - if not use_legacy() and config[CONF_ADC_TYPE] == "internal": - raise cv.Invalid("Internal ADC is only compatible with legacy i2s driver") + if config[CONF_ADC_TYPE] == "internal": + raise cv.Invalid( + "Internal ADC is no longer supported. Use an external I2S microphone instead." + ) FINAL_VALIDATE_SCHEMA = _final_validate @@ -140,13 +140,7 @@ async def to_code(config): await register_i2s_audio_component(var, config) await microphone.register_microphone(var, config) - if config[CONF_ADC_TYPE] == "internal": - variant = esp32.get_esp32_variant() - pin_num = config[CONF_ADC_PIN][CONF_NUMBER] - channel = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num] - cg.add(var.set_adc_channel(channel)) - else: - cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) - cg.add(var.set_pdm(config[CONF_PDM])) + cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) + cg.add(var.set_pdm(config[CONF_PDM])) cg.add(var.set_correct_dc_offset(config[CONF_CORRECT_DC_OFFSET])) diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp index a17cb0d84a..d697808c99 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.cpp @@ -2,12 +2,8 @@ #ifdef USE_ESP32 -#ifdef USE_I2S_LEGACY -#include <driver/i2s.h> -#else #include <driver/i2s_std.h> #include <driver/i2s_pdm.h> -#endif #include "esphome/core/hal.h" #include "esphome/core/log.h" @@ -65,13 +61,6 @@ void I2SAudioMicrophone::dump_config() { void I2SAudioMicrophone::configure_stream_settings_() { uint8_t channel_count = 1; -#ifdef USE_I2S_LEGACY - uint8_t bits_per_sample = this->bits_per_sample_; - - if (this->channel_ == I2S_CHANNEL_FMT_RIGHT_LEFT) { - channel_count = 2; - } -#else uint8_t bits_per_sample = 16; if (this->slot_bit_width_ != I2S_SLOT_BIT_WIDTH_AUTO) { bits_per_sample = this->slot_bit_width_; @@ -80,7 +69,6 @@ void I2SAudioMicrophone::configure_stream_settings_() { if (this->slot_mode_ == I2S_SLOT_MODE_STEREO) { channel_count = 2; } -#endif #ifdef USE_ESP32_VARIANT_ESP32 // ESP32 reads audio aligned to a multiple of 2 bytes. For example, if configured for 24 bits per sample, then it will @@ -114,65 +102,6 @@ bool I2SAudioMicrophone::start_driver_() { this->locked_driver_ = true; esp_err_t err; -#ifdef USE_I2S_LEGACY - i2s_driver_config_t config = { - .mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_RX), - .sample_rate = this->sample_rate_, - .bits_per_sample = this->bits_per_sample_, - .channel_format = this->channel_, - .communication_format = I2S_COMM_FORMAT_STAND_I2S, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, - .dma_buf_count = 4, - .dma_buf_len = 240, // Must be divisible by 3 to support 24 bits per sample on old driver and newer variants - .use_apll = this->use_apll_, - .tx_desc_auto_clear = false, - .fixed_mclk = 0, - .mclk_multiple = this->mclk_multiple_, - .bits_per_chan = this->bits_per_channel_, - }; - -#if SOC_I2S_SUPPORTS_ADC - if (this->adc_) { - config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); - err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err)); - return false; - } - - err = i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error setting ADC mode: %s", esp_err_to_name(err)); - return false; - } - - err = i2s_adc_enable(this->parent_->get_port()); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error enabling ADC: %s", esp_err_to_name(err)); - return false; - } - } else -#endif - { - if (this->pdm_) - config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); - - err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error installing driver: %s", esp_err_to_name(err)); - return false; - } - - i2s_pin_config_t pin_config = this->parent_->get_pin_config(); - pin_config.data_in_num = this->din_pin_; - - err = i2s_set_pin(this->parent_->get_port(), &pin_config); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error setting pin: %s", esp_err_to_name(err)); - return false; - } - } -#else i2s_chan_config_t chan_cfg = { .id = this->parent_->get_port(), .role = this->i2s_role_, @@ -265,7 +194,6 @@ bool I2SAudioMicrophone::start_driver_() { ESP_LOGE(TAG, "Enabling failed: %s", esp_err_to_name(err)); return false; } -#endif this->configure_stream_settings_(); // redetermine the settings in case some settings were changed after compilation @@ -284,24 +212,6 @@ void I2SAudioMicrophone::stop_driver_() { // ensures that we stop/unload the driver when it only partially starts. esp_err_t err; -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_ADC - if (this->adc_) { - err = i2s_adc_disable(this->parent_->get_port()); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Error disabling ADC: %s", esp_err_to_name(err)); - } - } -#endif - err = i2s_stop(this->parent_->get_port()); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Error stopping: %s", esp_err_to_name(err)); - } - err = i2s_driver_uninstall(this->parent_->get_port()); - if (err != ESP_OK) { - ESP_LOGW(TAG, "Error uninstalling driver: %s", esp_err_to_name(err)); - } -#else if (this->rx_handle_ != nullptr) { /* Have to stop the channel before deleting it */ err = i2s_channel_disable(this->rx_handle_); @@ -315,7 +225,6 @@ void I2SAudioMicrophone::stop_driver_() { } this->rx_handle_ = nullptr; } -#endif if (this->locked_driver_) { this->parent_->unlock(); this->locked_driver_ = false; @@ -412,12 +321,8 @@ void I2SAudioMicrophone::fix_dc_offset_(std::vector<uint8_t> &data) { size_t I2SAudioMicrophone::read_(uint8_t *buf, size_t len, TickType_t ticks_to_wait) { size_t bytes_read = 0; -#ifdef USE_I2S_LEGACY - esp_err_t err = i2s_read(this->parent_->get_port(), buf, len, &bytes_read, ticks_to_wait); -#else // i2s_channel_read expects the timeout value in ms, not ticks esp_err_t err = i2s_channel_read(this->rx_handle_, buf, len, &bytes_read, pdTICKS_TO_MS(ticks_to_wait)); -#endif if ((err != ESP_OK) && ((err != ESP_ERR_TIMEOUT) || (ticks_to_wait != 0))) { // Ignore ESP_ERR_TIMEOUT if ticks_to_wait = 0, as it will read the data on the next call if (!this->status_has_warning()) { @@ -432,7 +337,7 @@ size_t I2SAudioMicrophone::read_(uint8_t *buf, size_t len, TickType_t ticks_to_w return 0; } this->status_clear_warning(); -#if defined(USE_ESP32_VARIANT_ESP32) and not defined(USE_I2S_LEGACY) +#ifdef USE_ESP32_VARIANT_ESP32 // For ESP32 16-bit standard mono mode, adjacent samples need to be swapped. if (this->slot_mode_ == I2S_SLOT_MODE_MONO && this->slot_bit_width_ == I2S_SLOT_BIT_WIDTH_16BIT && !this->pdm_) { int16_t *samples = reinterpret_cast<int16_t *>(buf); diff --git a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h index de272ba23d..e277409262 100644 --- a/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h +++ b/esphome/components/i2s_audio/microphone/i2s_audio_microphone.h @@ -26,23 +26,10 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub void set_correct_dc_offset(bool correct_dc_offset) { this->correct_dc_offset_ = correct_dc_offset; } -#ifdef USE_I2S_LEGACY - void set_din_pin(int8_t pin) { this->din_pin_ = pin; } -#else void set_din_pin(int8_t pin) { this->din_pin_ = (gpio_num_t) pin; } -#endif void set_pdm(bool pdm) { this->pdm_ = pdm; } -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_ADC - void set_adc_channel(adc_channel_t channel) { - this->adc_channel_ = (adc1_channel_t) channel; - this->adc_ = true; - } -#endif -#endif - protected: /// @brief Starts the I2S driver. Updates the ``audio_stream_info_`` member variable with the current setttings. /// @return True if succesful, false otherwise @@ -68,16 +55,8 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub TaskHandle_t task_handle_{nullptr}; -#ifdef USE_I2S_LEGACY - int8_t din_pin_{I2S_PIN_NO_CHANGE}; -#if SOC_I2S_SUPPORTS_ADC - adc1_channel_t adc_channel_{ADC1_CHANNEL_MAX}; - bool adc_{false}; -#endif -#else gpio_num_t din_pin_{I2S_GPIO_UNUSED}; i2s_chan_handle_t rx_handle_; -#endif bool pdm_{false}; bool correct_dc_offset_; diff --git a/esphome/components/i2s_audio/speaker/__init__.py b/esphome/components/i2s_audio/speaker/__init__.py index b84cf7de3b..d1d1bc3ee3 100644 --- a/esphome/components/i2s_audio/speaker/__init__.py +++ b/esphome/components/i2s_audio/speaker/__init__.py @@ -26,7 +26,6 @@ from .. import ( i2s_audio_component_schema, i2s_audio_ns, register_i2s_audio_component, - use_legacy, validate_mclk_divisible_by_3, ) @@ -166,13 +165,12 @@ CONFIG_SCHEMA = cv.All( def _final_validate(config): - if not use_legacy(): - if config[CONF_DAC_TYPE] == "internal": - raise cv.Invalid("Internal DAC is only compatible with legacy i2s driver") - if config[CONF_I2S_COMM_FMT] == "stand_max": - raise cv.Invalid( - "I2S standard max format only implemented with legacy i2s driver." - ) + if config[CONF_DAC_TYPE] == "internal": + raise cv.Invalid( + "Internal DAC is no longer supported. Use an external I2S DAC instead." + ) + if config[CONF_I2S_COMM_FMT] == "stand_max": + raise cv.Invalid("I2S standard max format is no longer supported.") FINAL_VALIDATE_SCHEMA = _final_validate @@ -184,21 +182,13 @@ async def to_code(config): await register_i2s_audio_component(var, config) await speaker.register_speaker(var, config) - if config[CONF_DAC_TYPE] == "internal": - cg.add(var.set_internal_dac_mode(config[CONF_MODE])) - else: - cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) - if use_legacy(): - cg.add( - var.set_i2s_comm_fmt(I2C_COMM_FMT_OPTIONS[config[CONF_I2S_COMM_FMT]]) - ) - else: - fmt = "std" # equals stand_i2s, stand_pcm_long, i2s_msb, pcm_long - if config[CONF_I2S_COMM_FMT] in ["stand_msb", "i2s_lsb"]: - fmt = "msb" - elif config[CONF_I2S_COMM_FMT] in ["stand_pcm_short", "pcm_short", "pcm"]: - fmt = "pcm" - cg.add(var.set_i2s_comm_fmt(fmt)) + cg.add(var.set_dout_pin(config[CONF_I2S_DOUT_PIN])) + fmt = "std" # equals stand_i2s, stand_pcm_long, i2s_msb, pcm_long + if config[CONF_I2S_COMM_FMT] in ["stand_msb", "i2s_lsb"]: + fmt = "msb" + elif config[CONF_I2S_COMM_FMT] in ["stand_pcm_short", "pcm_short", "pcm"]: + fmt = "pcm" + cg.add(var.set_i2s_comm_fmt(fmt)) if config[CONF_TIMEOUT] != CONF_NEVER: cg.add(var.set_timeout(config[CONF_TIMEOUT])) cg.add(var.set_buffer_duration(config[CONF_BUFFER_DURATION])) diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp index a996702f8b..dde1f70bc5 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.cpp @@ -2,11 +2,7 @@ #ifdef USE_ESP32 -#ifdef USE_I2S_LEGACY -#include <driver/i2s.h> -#else #include <driver/i2s_std.h> -#endif #include "esphome/components/audio/audio.h" #include "esphome/components/audio/audio_transfer_buffer.h" @@ -79,14 +75,7 @@ void I2SAudioSpeaker::dump_config() { if (this->timeout_.has_value()) { ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 " ms", this->timeout_.value()); } -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_DAC - ESP_LOGCONFIG(TAG, " Internal DAC mode: %d", static_cast<int8_t>(this->internal_dac_mode_)); -#endif - ESP_LOGCONFIG(TAG, " Communication format: %d", static_cast<int8_t>(this->i2s_comm_fmt_)); -#else ESP_LOGCONFIG(TAG, " Communication format: %s", this->i2s_comm_fmt_.c_str()); -#endif } void I2SAudioSpeaker::loop() { @@ -300,14 +289,6 @@ void I2SAudioSpeaker::speaker_task(void *params) { // Audio stream info changed, stop the speaker task so it will restart with the proper settings. break; } -#ifdef USE_I2S_LEGACY - i2s_event_t i2s_event; - while (xQueueReceive(this_speaker->i2s_event_queue_, &i2s_event, 0)) { - if (i2s_event.type == I2S_EVENT_TX_Q_OVF) { - tx_dma_underflow = true; - } - } -#else int64_t write_timestamp; while (xQueueReceive(this_speaker->i2s_event_queue_, &write_timestamp, 0)) { // Receives timing events from the I2S on_sent callback. If actual audio data was sent in this event, it passes @@ -326,7 +307,6 @@ void I2SAudioSpeaker::speaker_task(void *params) { this_speaker->audio_output_callback_(frames_sent, write_timestamp); } } -#endif if (this_speaker->pause_state_) { // Pause state is accessed atomically, so thread safe @@ -393,17 +373,6 @@ void I2SAudioSpeaker::speaker_task(void *params) { vTaskDelay(pdMS_TO_TICKS(DMA_BUFFER_DURATION_MS / 2)); } else { size_t bytes_written = 0; -#ifdef USE_I2S_LEGACY - if (this_speaker->current_stream_info_.get_bits_per_sample() == (uint8_t) this_speaker->bits_per_sample_) { - i2s_write(this_speaker->parent_->get_port(), transfer_buffer->get_buffer_start(), - transfer_buffer->available(), &bytes_written, pdMS_TO_TICKS(DMA_BUFFER_DURATION_MS)); - } else if (this_speaker->current_stream_info_.get_bits_per_sample() < - (uint8_t) this_speaker->bits_per_sample_) { - i2s_write_expand(this_speaker->parent_->get_port(), transfer_buffer->get_buffer_start(), - transfer_buffer->available(), this_speaker->current_stream_info_.get_bits_per_sample(), - this_speaker->bits_per_sample_, &bytes_written, pdMS_TO_TICKS(DMA_BUFFER_DURATION_MS)); - } -#else if (tx_dma_underflow) { // Temporarily disable channel and callback to reset the I2S driver's internal DMA buffer queue so timing // callbacks are accurate. Preload the data. @@ -420,14 +389,12 @@ void I2SAudioSpeaker::speaker_task(void *params) { i2s_channel_write(this_speaker->tx_handle_, transfer_buffer->get_buffer_start(), transfer_buffer->available(), &bytes_written, DMA_BUFFER_DURATION_MS); } -#endif if (bytes_written > 0) { last_data_received_time = millis(); frames_written += this_speaker->current_stream_info_.bytes_to_frames(bytes_written); transfer_buffer->decrease_buffer_length(bytes_written); if (tx_dma_underflow) { tx_dma_underflow = false; -#ifndef USE_I2S_LEGACY // Reset the event queue timestamps // Enable the on_sent callback to accurately track the timestamps of played audio // Enable the I2S channel to start sending the preloaded audio @@ -440,14 +407,7 @@ void I2SAudioSpeaker::speaker_task(void *params) { i2s_channel_register_event_callback(this_speaker->tx_handle_, &callbacks, this_speaker); i2s_channel_enable(this_speaker->tx_handle_); -#endif } -#ifdef USE_I2S_LEGACY - // The legacy driver doesn't easily support the callback approach for timestamps, so fall back to a direct but - // less accurate approach. - this_speaker->audio_output_callback_(this_speaker->current_stream_info_.bytes_to_frames(bytes_written), - esp_timer_get_time() + dma_buffers_duration_ms * 1000); -#endif } } } @@ -496,22 +456,14 @@ void I2SAudioSpeaker::stop_(bool wait_on_empty) { esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_stream_info) { this->current_stream_info_ = audio_stream_info; // store the stream info settings the driver will use -#ifdef USE_I2S_LEGACY - if ((this->i2s_mode_ & I2S_MODE_SLAVE) && (this->sample_rate_ != audio_stream_info.get_sample_rate())) { // NOLINT -#else if ((this->i2s_role_ & I2S_ROLE_SLAVE) && (this->sample_rate_ != audio_stream_info.get_sample_rate())) { // NOLINT -#endif // Can't reconfigure I2S bus, so the sample rate must match the configured value ESP_LOGE(TAG, "Audio stream settings are not compatible with this I2S configuration"); return ESP_ERR_NOT_SUPPORTED; } -#ifdef USE_I2S_LEGACY - if ((i2s_bits_per_sample_t) audio_stream_info.get_bits_per_sample() > this->bits_per_sample_) { -#else if (this->slot_bit_width_ != I2S_SLOT_BIT_WIDTH_AUTO && (i2s_slot_bit_width_t) audio_stream_info.get_bits_per_sample() > this->slot_bit_width_) { -#endif // Currently can't handle the case when the incoming audio has more bits per sample than the configured value ESP_LOGE(TAG, "Audio streams with more bits per sample than the I2S speaker's configuration is not supported"); return ESP_ERR_NOT_SUPPORTED; @@ -524,77 +476,6 @@ esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_strea uint32_t dma_buffer_length = audio_stream_info.ms_to_frames(DMA_BUFFER_DURATION_MS); -#ifdef USE_I2S_LEGACY - i2s_channel_fmt_t channel = this->channel_; - - if (audio_stream_info.get_channels() == 1) { - if (this->channel_ == I2S_CHANNEL_FMT_ONLY_LEFT) { - channel = I2S_CHANNEL_FMT_ONLY_LEFT; - } else { - channel = I2S_CHANNEL_FMT_ONLY_RIGHT; - } - } else if (audio_stream_info.get_channels() == 2) { - channel = I2S_CHANNEL_FMT_RIGHT_LEFT; - } - - i2s_driver_config_t config = { - .mode = (i2s_mode_t) (this->i2s_mode_ | I2S_MODE_TX), - .sample_rate = audio_stream_info.get_sample_rate(), - .bits_per_sample = this->bits_per_sample_, - .channel_format = channel, - .communication_format = this->i2s_comm_fmt_, - .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, - .dma_buf_count = DMA_BUFFERS_COUNT, - .dma_buf_len = (int) dma_buffer_length, - .use_apll = this->use_apll_, - .tx_desc_auto_clear = true, - .fixed_mclk = I2S_PIN_NO_CHANGE, - .mclk_multiple = this->mclk_multiple_, - .bits_per_chan = this->bits_per_channel_, -#if SOC_I2S_SUPPORTS_TDM - .chan_mask = (i2s_channel_t) (I2S_TDM_ACTIVE_CH0 | I2S_TDM_ACTIVE_CH1), - .total_chan = 2, - .left_align = false, - .big_edin = false, - .bit_order_msb = false, - .skip_msk = false, -#endif - }; -#if SOC_I2S_SUPPORTS_DAC - if (this->internal_dac_mode_ != I2S_DAC_CHANNEL_DISABLE) { - config.mode = (i2s_mode_t) (config.mode | I2S_MODE_DAC_BUILT_IN); - } -#endif - - esp_err_t err = - i2s_driver_install(this->parent_->get_port(), &config, I2S_EVENT_QUEUE_COUNT, &this->i2s_event_queue_); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to install I2S legacy driver"); - // Failed to install the driver, so unlock the I2S port - this->parent_->unlock(); - return err; - } - -#if SOC_I2S_SUPPORTS_DAC - if (this->internal_dac_mode_ == I2S_DAC_CHANNEL_DISABLE) { -#endif - i2s_pin_config_t pin_config = this->parent_->get_pin_config(); - pin_config.data_out_num = this->dout_pin_; - - err = i2s_set_pin(this->parent_->get_port(), &pin_config); -#if SOC_I2S_SUPPORTS_DAC - } else { - i2s_set_dac_mode(this->internal_dac_mode_); - } -#endif - - if (err != ESP_OK) { - // Failed to set the data out pin, so uninstall the driver and unlock the I2S port - ESP_LOGE(TAG, "Failed to set the data out pin"); - i2s_driver_uninstall(this->parent_->get_port()); - this->parent_->unlock(); - } -#else i2s_chan_config_t chan_cfg = { .id = this->parent_->get_port(), .role = this->i2s_role_, @@ -683,12 +564,10 @@ esp_err_t I2SAudioSpeaker::start_i2s_driver_(audio::AudioStreamInfo &audio_strea } i2s_channel_enable(this->tx_handle_); -#endif return err; } -#ifndef USE_I2S_LEGACY bool IRAM_ATTR I2SAudioSpeaker::i2s_on_sent_cb(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx) { int64_t now = esp_timer_get_time(); @@ -709,16 +588,11 @@ bool IRAM_ATTR I2SAudioSpeaker::i2s_on_sent_cb(i2s_chan_handle_t handle, i2s_eve return need_yield1 | need_yield2 | need_yield3; } -#endif void I2SAudioSpeaker::stop_i2s_driver_() { -#ifdef USE_I2S_LEGACY - i2s_driver_uninstall(this->parent_->get_port()); -#else i2s_channel_disable(this->tx_handle_); i2s_del_channel(this->tx_handle_); this->tx_handle_ = nullptr; -#endif this->parent_->unlock(); } diff --git a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h index 93ec754178..76b6692209 100644 --- a/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h +++ b/esphome/components/i2s_audio/speaker/i2s_audio_speaker.h @@ -29,16 +29,8 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; } void set_timeout(uint32_t ms) { this->timeout_ = ms; } -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_DAC - void set_internal_dac_mode(i2s_dac_mode_t mode) { this->internal_dac_mode_ = mode; } -#endif - void set_dout_pin(uint8_t pin) { this->dout_pin_ = pin; } - void set_i2s_comm_fmt(i2s_comm_format_t mode) { this->i2s_comm_fmt_ = mode; } -#else void set_dout_pin(uint8_t pin) { this->dout_pin_ = (gpio_num_t) pin; } void set_i2s_comm_fmt(std::string mode) { this->i2s_comm_fmt_ = std::move(mode); } -#endif void start() override; void stop() override; @@ -83,14 +75,12 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp /// @param wait_on_empty If false, sends the COMMAND_STOP signal. If true, sends the COMMAND_STOP_GRACEFULLY signal. void stop_(bool wait_on_empty); -#ifndef USE_I2S_LEGACY /// @brief Callback function used to send playback timestamps the to the speaker task. /// @param handle (i2s_chan_handle_t) /// @param event (i2s_event_data_t) /// @param user_ctx (void*) User context pointer that the callback accesses /// @return True if a higher priority task was interrupted static bool i2s_on_sent_cb(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx); -#endif /// @brief Starts the ESP32 I2S driver. /// Attempts to lock the I2S port, starts the I2S driver using the passed in stream information, and sets the data out @@ -124,17 +114,9 @@ class I2SAudioSpeaker : public I2SAudioOut, public speaker::Speaker, public Comp audio::AudioStreamInfo current_stream_info_; // The currently loaded driver's stream info -#ifdef USE_I2S_LEGACY -#if SOC_I2S_SUPPORTS_DAC - i2s_dac_mode_t internal_dac_mode_{I2S_DAC_CHANNEL_DISABLE}; -#endif - uint8_t dout_pin_; - i2s_comm_format_t i2s_comm_fmt_; -#else gpio_num_t dout_pin_; std::string i2s_comm_fmt_; i2s_chan_handle_t tx_handle_; -#endif }; } // namespace i2s_audio diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 390ac8ddd7..09269ea1b4 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -185,7 +185,6 @@ #ifdef USE_ARDUINO #define USE_PROMETHEUS #define USE_WIFI_WPA2_EAP -#define USE_I2S_LEGACY #endif // Platforms with native 64-bit time sources (no rollover tracking needed) diff --git a/tests/components/i2s_audio/test.esp32-ard.yaml b/tests/components/i2s_audio/test.esp32-ard.yaml deleted file mode 100644 index 4276b4f922..0000000000 --- a/tests/components/i2s_audio/test.esp32-ard.yaml +++ /dev/null @@ -1,16 +0,0 @@ -substitutions: - i2s_bclk_pin: GPIO15 - i2s_lrclk_pin: GPIO4 - i2s_mclk_pin: GPIO5 - -<<: !include common.yaml - -wifi: - ssid: test - password: test1234 - -media_player: - - platform: i2s_audio - name: Test Media Player - dac_type: internal - mode: stereo diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml index c83ee89ad4..89600f70f6 100644 --- a/tests/components/media_player/common.yaml +++ b/tests/components/media_player/common.yaml @@ -1,18 +1,18 @@ -wifi: - ssid: MySSID - password: password1 - i2s_audio: i2s_lrclk_pin: 13 i2s_bclk_pin: 14 i2s_mclk_pin: 15 -media_player: +speaker: - platform: i2s_audio - name: None - dac_type: external + id: test_speaker i2s_dout_pin: 18 - mute_pin: 19 + dac_type: external + +media_player: + - platform: speaker + name: None + speaker: test_speaker on_state: - media_player.play: - media_player.play_media: http://localhost/media.mp3 From ef0eef8117af41b994b0f86c265ff1c5dc077dbf Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Mar 2026 16:57:33 -0500 Subject: [PATCH 1514/2030] [const] Move shared volume constants to components/const (#14935) --- esphome/components/const/__init__.py | 4 ++++ esphome/components/speaker/media_player/__init__.py | 10 ++++++---- esphome/components/speaker_source/media_player.py | 10 ++++++---- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index f6da32569f..2a972a2939 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -21,6 +21,10 @@ CONF_REQUEST_HEADERS = "request_headers" CONF_ROWS = "rows" CONF_STOP_BITS = "stop_bits" CONF_USE_PSRAM = "use_psram" +CONF_VOLUME_INCREMENT = "volume_increment" +CONF_VOLUME_INITIAL = "volume_initial" +CONF_VOLUME_MAX = "volume_max" +CONF_VOLUME_MIN = "volume_min" ICON_CURRENT_DC = "mdi:current-dc" ICON_SOLAR_PANEL = "mdi:solar-panel" diff --git a/esphome/components/speaker/media_player/__init__.py b/esphome/components/speaker/media_player/__init__.py index 92a178fe95..b16f882cba 100644 --- a/esphome/components/speaker/media_player/__init__.py +++ b/esphome/components/speaker/media_player/__init__.py @@ -7,6 +7,12 @@ from pathlib import Path from esphome import automation, external_files import esphome.codegen as cg from esphome.components import audio, esp32, media_player, network, ota, psram, speaker +from esphome.components.const import ( + CONF_VOLUME_INCREMENT, + CONF_VOLUME_INITIAL, + CONF_VOLUME_MAX, + CONF_VOLUME_MIN, +) import esphome.config_validation as cv from esphome.const import ( CONF_BUFFER_SIZE, @@ -55,10 +61,6 @@ CONF_ON_MUTE = "on_mute" CONF_ON_UNMUTE = "on_unmute" CONF_ON_VOLUME = "on_volume" CONF_STREAM = "stream" -CONF_VOLUME_INCREMENT = "volume_increment" -CONF_VOLUME_INITIAL = "volume_initial" -CONF_VOLUME_MIN = "volume_min" -CONF_VOLUME_MAX = "volume_max" speaker_ns = cg.esphome_ns.namespace("speaker") diff --git a/esphome/components/speaker_source/media_player.py b/esphome/components/speaker_source/media_player.py index fe50536e8f..7f0f776ee5 100644 --- a/esphome/components/speaker_source/media_player.py +++ b/esphome/components/speaker_source/media_player.py @@ -1,6 +1,12 @@ from esphome import automation import esphome.codegen as cg from esphome.components import audio, media_player, media_source, speaker +from esphome.components.const import ( + CONF_VOLUME_INCREMENT, + CONF_VOLUME_INITIAL, + CONF_VOLUME_MAX, + CONF_VOLUME_MIN, +) import esphome.config_validation as cv from esphome.const import ( CONF_DELAY, @@ -27,10 +33,6 @@ CONF_PIPELINE = "pipeline" CONF_ON_UNMUTE = "on_unmute" CONF_ON_VOLUME = "on_volume" CONF_SOURCES = "sources" -CONF_VOLUME_INCREMENT = "volume_increment" -CONF_VOLUME_INITIAL = "volume_initial" -CONF_VOLUME_MAX = "volume_max" -CONF_VOLUME_MIN = "volume_min" speaker_source_ns = cg.esphome_ns.namespace("speaker_source") From 9f4c7739636bbb4d9d66c92d1b5b5c6511ea1d72 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Wed, 18 Mar 2026 17:34:16 -0500 Subject: [PATCH 1515/2030] [media_source] Add request helpers for smart sources (#14936) --- .../components/media_source/media_source.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/esphome/components/media_source/media_source.h b/esphome/components/media_source/media_source.h index f21ba486b8..ec2fcbc44f 100644 --- a/esphome/components/media_source/media_source.h +++ b/esphome/components/media_source/media_source.h @@ -153,6 +153,31 @@ class MediaSource { } } + // === Listener request helpers for smart sources === + // Smart sources (those with internal playlists or external control) use these to request + // the orchestrator to take actions. Simple sources never call these. + + /// @brief Request the orchestrator to play a new URI + void request_play_uri_(const std::string &uri) { + if (this->listener_ != nullptr) { + this->listener_->request_play_uri(uri); + } + } + + /// @brief Request the orchestrator to change volume + void request_volume_(float volume) { + if (this->listener_ != nullptr) { + this->listener_->request_volume(volume); + } + } + + /// @brief Request the orchestrator to change mute state + void request_mute_(bool is_muted) { + if (this->listener_ != nullptr) { + this->listener_->request_mute(is_muted); + } + } + private: // Private to enforce the invariant that listener notifications always fire on state changes. // All state transitions must go through set_state_() which couples the update with notification. From a2a048e3bf28947b65bf62e7633f3eb8dbdb3340 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 13:02:07 -1000 Subject: [PATCH 1516/2030] [ld2412] Inline trivial gate threshold number setters (#14937) --- esphome/components/ld2412/ld2412.cpp | 7 ------- esphome/components/ld2412/ld2412.h | 6 ++++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/esphome/components/ld2412/ld2412.cpp b/esphome/components/ld2412/ld2412.cpp index 6ff6963e9f..38e1a59aba 100644 --- a/esphome/components/ld2412/ld2412.cpp +++ b/esphome/components/ld2412/ld2412.cpp @@ -825,13 +825,6 @@ void LD2412Component::get_gate_threshold() { this->send_command_(CMD_QUERY_STATIC_GATE_SENS, nullptr, 0); } -void LD2412Component::set_gate_still_threshold_number(uint8_t gate, number::Number *n) { - this->gate_still_threshold_numbers_[gate] = n; -} - -void LD2412Component::set_gate_move_threshold_number(uint8_t gate, number::Number *n) { - this->gate_move_threshold_numbers_[gate] = n; -} #endif void LD2412Component::set_light_out_control() { diff --git a/esphome/components/ld2412/ld2412.h b/esphome/components/ld2412/ld2412.h index 5dd5e7bcde..7fd2245978 100644 --- a/esphome/components/ld2412/ld2412.h +++ b/esphome/components/ld2412/ld2412.h @@ -85,8 +85,10 @@ class LD2412Component : public Component, public uart::UARTDevice { void set_light_out_control(); void set_basic_config(); #ifdef USE_NUMBER - void set_gate_move_threshold_number(uint8_t gate, number::Number *n); - void set_gate_still_threshold_number(uint8_t gate, number::Number *n); + void set_gate_move_threshold_number(uint8_t gate, number::Number *n) { this->gate_move_threshold_numbers_[gate] = n; } + void set_gate_still_threshold_number(uint8_t gate, number::Number *n) { + this->gate_still_threshold_numbers_[gate] = n; + } void set_gate_threshold(); void get_gate_threshold(); #endif From 5856d05701bd10b052a8bdade43e5e106694c788 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 14:05:57 -1000 Subject: [PATCH 1517/2030] [core] Devirtualize PollingComponent::set_update_interval (#14938) --- esphome/components/sds011/sds011.h | 2 -- esphome/components/sds011/sensor.py | 7 +++++-- esphome/core/component.cpp | 1 - esphome/core/component.h | 4 +--- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/esphome/components/sds011/sds011.h b/esphome/components/sds011/sds011.h index 3be74e66d1..d65299c635 100644 --- a/esphome/components/sds011/sds011.h +++ b/esphome/components/sds011/sds011.h @@ -21,8 +21,6 @@ class SDS011Component : public Component, public uart::UARTDevice { void dump_config() override; void loop() override; - void set_update_interval(uint32_t val) { /* ignore */ - } void set_update_interval_min(uint8_t update_interval_min); void set_working_state(bool working_state); diff --git a/esphome/components/sds011/sensor.py b/esphome/components/sds011/sensor.py index ae1cc58a95..76abc70bb7 100644 --- a/esphome/components/sds011/sensor.py +++ b/esphome/components/sds011/sensor.py @@ -64,12 +64,15 @@ CONFIG_SCHEMA = cv.All( async def to_code(config): + # Pop update_interval before register_component so it doesn't generate + # a set_update_interval call — sds011 handles this via set_update_interval_min + update_interval = config.pop(CONF_UPDATE_INTERVAL, None) var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - if CONF_UPDATE_INTERVAL in config: - cg.add(var.set_update_interval_min(config[CONF_UPDATE_INTERVAL])) + if update_interval is not None: + cg.add(var.set_update_interval_min(update_interval)) cg.add(var.set_rx_mode_only(config[CONF_RX_ONLY])) if CONF_PM_2_5 in config: diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index bfe9beb272..a9e93f9131 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -508,7 +508,6 @@ void PollingComponent::stop_poller() { } uint32_t PollingComponent::get_update_interval() const { return this->update_interval_; } -void PollingComponent::set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } void __attribute__((noinline, cold)) WarnIfComponentBlockingGuard::warn_blocking(Component *component, uint32_t blocking_time) { diff --git a/esphome/core/component.h b/esphome/core/component.h index 557ba09bbc..02598b53ff 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -548,12 +548,10 @@ class PollingComponent : public Component { explicit PollingComponent(uint32_t update_interval); /** Manually set the update interval in ms for this polling object. - * - * Override this if you want to do some validation for the update interval. * * @param update_interval The update interval in ms. */ - virtual void set_update_interval(uint32_t update_interval); + void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } // ========== OVERRIDE METHODS ========== // (You'll only need this when creating your own custom sensor) From 44037c4f9ba5d81b68fc0f5e367bc08821f52337 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 14:06:41 -1000 Subject: [PATCH 1518/2030] [http_request] Prevent double update task launch (#14910) --- .../components/http_request/update/http_request_update.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index a15dc61675..1c52a28105 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -74,6 +74,10 @@ void HttpRequestUpdate::update() { } this->cancel_interval(INITIAL_CHECK_INTERVAL_ID); #ifdef USE_ESP32 + if (this->update_task_handle_ != nullptr) { + ESP_LOGW(TAG, "Update check already in progress"); + return; + } xTaskCreate(HttpRequestUpdate::update_task, "update_task", 8192, (void *) this, 1, &this->update_task_handle_); #else this->update_task(this); @@ -204,6 +208,9 @@ defer: // both success and error paths to avoid multiple std::function instantiations. // Lambda captures only 2 pointers (8 bytes) — fits in std::function SBO on supported toolchains. this_update->defer([this_update, result]() { +#ifdef USE_ESP32 + this_update->update_task_handle_ = nullptr; +#endif if (result->error_str != nullptr) { this_update->status_set_error(result->error_str); delete result; From 4d86049c217b5e170ffba1cfe75847526c25df70 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 14:06:55 -1000 Subject: [PATCH 1519/2030] [ota] Pack deferred state args into uint32 to avoid heap allocation (#14922) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/components/ota/ota_backend.cpp | 13 +++++++++++++ esphome/components/ota/ota_backend.h | 4 +--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/ota/ota_backend.cpp b/esphome/components/ota/ota_backend.cpp index 8fb9f67214..01a18a58ef 100644 --- a/esphome/components/ota/ota_backend.cpp +++ b/esphome/components/ota/ota_backend.cpp @@ -13,6 +13,19 @@ OTAGlobalCallback *get_global_ota_callback() { return global_ota_callback; } +void OTAComponent::notify_state_deferred_(OTAState state, float progress, uint8_t error) { + // Pack state, error, and progress into a single uint32_t so the lambda + // captures only [this, packed] (8 bytes) — fits in std::function SBO. + // Layout: [state:8][error:8][progress_fixed:16] where progress is 0–10000 (0.01% resolution) + static_assert(OTA_ERROR <= 0xFF, "OTAState must fit in 8 bits for packing"); + uint32_t packed = (static_cast<uint32_t>(state) << 24) | (static_cast<uint32_t>(error) << 16) | + static_cast<uint16_t>(progress * 100.0f); + this->defer([this, packed]() { + this->notify_state_(static_cast<OTAState>(packed >> 24), static_cast<float>(packed & 0xFFFF) / 100.0f, + static_cast<uint8_t>(packed >> 16)); + }); +} + void OTAComponent::notify_state_(OTAState state, float progress, uint8_t error) { for (auto *listener : this->state_listeners_) { listener->on_ota_state(state, progress, error); diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index bc603a6e9e..ab0ec58e8a 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -73,9 +73,7 @@ class OTAComponent : public Component { * This should be used by OTA implementations that run in separate tasks * (like web_server OTA) to ensure listeners execute in the main loop. */ - void notify_state_deferred_(OTAState state, float progress, uint8_t error) { - this->defer([this, state, progress, error]() { this->notify_state_(state, progress, error); }); - } + void notify_state_deferred_(OTAState state, float progress, uint8_t error); std::vector<OTAStateListener *> state_listeners_; #endif From a50d70c8d3ea39b27681bfe6e8f5a62519dfe760 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 14:08:03 -1000 Subject: [PATCH 1520/2030] [core] Remove call_loop_ wrapper and call loop() directly (#14931) --- esphome/core/component.cpp | 5 ++--- esphome/core/component.h | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index a9e93f9131..00dda0cc26 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -209,7 +209,6 @@ bool Component::cancel_retry(uint32_t id) { #pragma GCC diagnostic pop } -void Component::call_loop_() { this->loop(); } void Component::call_setup() { this->setup(); } void Component::call_dump_config_() { this->dump_config(); @@ -259,11 +258,11 @@ void Component::call() { case COMPONENT_STATE_SETUP: // State setup: Call first loop and set state to loop this->set_component_state_(COMPONENT_STATE_LOOP); - this->call_loop_(); + this->loop(); break; case COMPONENT_STATE_LOOP: // State loop: Call loop - this->call_loop_(); + this->loop(); break; case COMPONENT_STATE_FAILED: // State failed: Do nothing diff --git a/esphome/core/component.h b/esphome/core/component.h index 02598b53ff..119681f64c 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -301,7 +301,6 @@ class Component { protected: friend class Application; - void call_loop_(); virtual void call_setup(); void call_dump_config_(); From 2c10adba858b409fc5a7f445863fbda6589afc04 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Thu, 19 Mar 2026 13:09:03 +1300 Subject: [PATCH 1521/2030] Bump version to 2026.3.0 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 53eae48966..d8a030536e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0b5 +PROJECT_NUMBER = 2026.3.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 579235ff69..756ad69464 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0b5" +__version__ = "2026.3.0" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From f8be27ce6d07d42e13dbbce08d5f6252ea4a2acf Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 20:10:42 -0400 Subject: [PATCH 1522/2030] [ble_client] Fix RSSI sensor reporting same value for all clients (#14939) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/ble_client/sensor/ble_rssi_sensor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp b/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp index dc032a7a98..715298e592 100644 --- a/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +++ b/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp @@ -47,6 +47,8 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl switch (event) { // server response on RSSI request: case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: + if (!this->parent()->check_addr(param->read_rssi_cmpl.remote_addr)) + return; if (param->read_rssi_cmpl.status == ESP_BT_STATUS_SUCCESS) { int8_t rssi = param->read_rssi_cmpl.rssi; ESP_LOGI(TAG, "ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT RSSI: %d", rssi); From 403ba262c683dab7266d54ed56807ad6074d8718 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:23:47 -0400 Subject: [PATCH 1523/2030] [openthread] Guard InstanceLock against uninitialized semaphore (#14940) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/openthread/openthread.h | 4 ++++ .../components/openthread/openthread_esp.cpp | 22 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 75d8fe11fd..bd10774fcf 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -11,6 +11,7 @@ #include <openthread/instance.h> #include <openthread/thread.h> +#include <atomic> #include <optional> #include <vector> @@ -28,6 +29,8 @@ class OpenThreadComponent : public Component { float get_setup_priority() const override { return setup_priority::WIFI; } bool is_connected() const { return this->connected_; } + /// Returns true once esp_openthread_init() has completed and the OT lock is usable. + bool is_lock_initialized() const { return this->lock_initialized_; } network::IPAddresses get_ip_addresses(); std::optional<otIp6Address> get_omr_address(); void ot_main(); @@ -51,6 +54,7 @@ class OpenThreadComponent : public Component { uint32_t poll_period_{0}; #endif std::optional<int8_t> output_power_{}; + std::atomic<bool> lock_initialized_{false}; bool teardown_started_{false}; bool teardown_complete_{false}; bool connected_{false}; diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 9cc9223b52..27712bd86a 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -8,6 +8,7 @@ #include "esp_openthread_lock.h" #include "esp_task_wdt.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -81,6 +82,9 @@ void OpenThreadComponent::ot_main() { // Initialize the OpenThread stack // otLoggingSetLevel(OT_LOG_LEVEL_DEBG); ESP_ERROR_CHECK(esp_openthread_init(&config)); + // Mark lock as initialized so InstanceLock callers know it's safe to acquire. + // Must be set after esp_openthread_init() which creates the internal semaphore. + this->lock_initialized_ = true; // Fetch OT instance once to avoid repeated call into OT stack otInstance *instance = esp_openthread_get_instance(); @@ -180,7 +184,8 @@ void OpenThreadComponent::ot_main() { esp_openthread_launch_mainloop(); - // Clean up + // Clean up - reset lock flag before deinit destroys the semaphore + this->lock_initialized_ = false; esp_openthread_deinit(); esp_openthread_netif_glue_deinit(); esp_netif_destroy(openthread_netif); @@ -210,6 +215,9 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() { otInstance *OpenThreadComponent::get_openthread_instance_() { return esp_openthread_get_instance(); } std::optional<InstanceLock> InstanceLock::try_acquire(int delay) { + if (!global_openthread_component->is_lock_initialized()) { + return {}; + } if (esp_openthread_lock_acquire(delay)) { return InstanceLock(); } @@ -217,6 +225,18 @@ std::optional<InstanceLock> InstanceLock::try_acquire(int delay) { } InstanceLock InstanceLock::acquire() { + // Wait for the lock to be created by ot_main() before attempting to acquire it. + // esp_openthread_lock_acquire() will assert-crash if called before esp_openthread_init(). + constexpr uint32_t lock_init_timeout_ms = 10000; + uint32_t start = millis(); + while (!global_openthread_component->is_lock_initialized()) { + if (millis() - start > lock_init_timeout_ms) { + ESP_LOGE(TAG, "OpenThread lock not initialized after %" PRIu32 "ms, aborting", lock_init_timeout_ms); + abort(); + } + delay(10); + esp_task_wdt_reset(); + } while (!esp_openthread_lock_acquire(100)) { esp_task_wdt_reset(); } From 8fe36cde23f7974683eab4090a1639890ef1b41d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 18:41:05 -1000 Subject: [PATCH 1524/2030] [core] Replace std::function with lightweight Callback in CallbackManager (#14853) --- .../alarm_control_panel.cpp | 16 ---- .../alarm_control_panel/alarm_control_panel.h | 31 ++++---- esphome/components/button/button.cpp | 1 - esphome/components/button/button.h | 4 +- esphome/components/canbus/canbus.h | 5 +- esphome/components/climate/climate.cpp | 8 -- esphome/components/climate/climate.h | 8 +- esphome/components/cover/cover.cpp | 1 - esphome/components/cover/cover.h | 2 +- esphome/components/datetime/datetime_base.h | 4 +- esphome/components/dfplayer/dfplayer.h | 4 +- .../components/display_menu_base/menu_item.h | 10 +-- .../esp32_improv/esp32_improv_component.h | 4 +- esphome/components/event/event.cpp | 4 - esphome/components/event/event.h | 4 +- esphome/components/ezo/ezo.h | 20 ++--- .../components/factory_reset/factory_reset.h | 4 +- esphome/components/fan/fan.cpp | 1 - esphome/components/fan/fan.h | 4 +- .../fingerprint_grow/fingerprint_grow.h | 32 ++++---- .../graphical_display_menu.h | 2 +- esphome/components/haier/haier_base.cpp | 4 - esphome/components/haier/haier_base.h | 4 +- esphome/components/haier/hon_climate.cpp | 8 -- esphome/components/haier/hon_climate.h | 8 +- esphome/components/hlk_fm22x/hlk_fm22x.h | 25 +++---- .../components/key_collector/key_collector.h | 12 +-- .../components/key_provider/key_provider.cpp | 4 - .../components/key_provider/key_provider.h | 2 +- esphome/components/ld2450/ld2450.cpp | 4 - esphome/components/ld2450/ld2450.h | 2 +- esphome/components/lock/lock.cpp | 2 - esphome/components/lock/lock.h | 4 +- esphome/components/ltr501/ltr501.h | 8 +- esphome/components/ltr_als_ps/ltr_als_ps.h | 8 +- esphome/components/lvgl/lvgl_esphome.h | 4 +- .../components/media_player/media_player.cpp | 4 - .../components/media_player/media_player.h | 4 +- esphome/components/microphone/microphone.cpp | 19 ----- esphome/components/microphone/microphone.h | 11 ++- .../microphone/microphone_source.cpp | 18 ----- .../components/microphone/microphone_source.h | 17 ++++- .../modbus_controller/modbus_controller.cpp | 12 --- .../modbus_controller/modbus_controller.h | 12 ++- esphome/components/nextion/nextion.cpp | 24 ------ esphome/components/nextion/nextion.h | 22 ++++-- esphome/components/number/number.cpp | 4 - esphome/components/number/number.h | 4 +- .../components/online_image/online_image.cpp | 8 -- .../components/online_image/online_image.h | 8 +- esphome/components/opentherm/hub.h | 8 +- esphome/components/pid/pid_climate.h | 4 +- esphome/components/pn532/pn532.h | 4 +- esphome/components/pn7150/pn7150.h | 8 +- esphome/components/pn7160/pn7160.h | 8 +- esphome/components/rf_bridge/rf_bridge.h | 8 +- .../rotary_encoder/rotary_encoder.h | 10 +-- esphome/components/rtttl/rtttl.h | 4 +- esphome/components/safe_mode/safe_mode.h | 4 +- esphome/components/sdl/sdl_esphome.h | 4 +- esphome/components/select/select.cpp | 4 - esphome/components/select/select.h | 4 +- esphome/components/sensor/sensor.cpp | 5 -- esphome/components/sensor/sensor.h | 6 +- esphome/components/sim800l/sim800l.h | 20 ++--- esphome/components/sml/sml.cpp | 4 - esphome/components/sml/sml.h | 2 +- esphome/components/speaker/speaker.h | 4 +- esphome/components/switch/switch.cpp | 3 - esphome/components/switch/switch.h | 4 +- esphome/components/text/text.cpp | 4 - esphome/components/text/text.h | 4 +- .../components/text_sensor/text_sensor.cpp | 7 -- esphome/components/text_sensor/text_sensor.h | 6 +- esphome/components/time/real_time_clock.h | 6 +- esphome/components/tuya/tuya.h | 4 +- esphome/components/uart/uart_component.h | 4 +- esphome/components/udp/udp_component.h | 4 +- esphome/components/update/update_entity.h | 4 +- esphome/components/valve/valve.cpp | 1 - esphome/components/valve/valve.h | 2 +- esphome/components/zephyr/cdc_acm.h | 4 +- esphome/components/zigbee/zigbee_zephyr.h | 2 +- esphome/core/entity_base.h | 24 +++--- esphome/core/helpers.h | 75 ++++++++++++++++--- 85 files changed, 319 insertions(+), 385 deletions(-) delete mode 100644 esphome/components/microphone/microphone.cpp diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index ab0a780cef..fb61776532 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -51,22 +51,6 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { } } -void AlarmControlPanel::add_on_state_callback(std::function<void()> &&callback) { - this->state_callback_.add(std::move(callback)); -} - -void AlarmControlPanel::add_on_cleared_callback(std::function<void()> &&callback) { - this->cleared_callback_.add(std::move(callback)); -} - -void AlarmControlPanel::add_on_chime_callback(std::function<void()> &&callback) { - this->chime_callback_.add(std::move(callback)); -} - -void AlarmControlPanel::add_on_ready_callback(std::function<void()> &&callback) { - this->ready_callback_.add(std::move(callback)); -} - void AlarmControlPanel::arm_with_code_(AlarmControlPanelCall &(AlarmControlPanelCall::*arm_method)(), const char *code) { auto call = this->make_call(); diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.h b/esphome/components/alarm_control_panel/alarm_control_panel.h index e8dc197e26..cf99d359e7 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel.h @@ -37,25 +37,24 @@ class AlarmControlPanel : public EntityBase { * * @param callback The callback function */ - void add_on_state_callback(std::function<void()> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } - /** Add a callback for when the state of the alarm_control_panel clears from triggered - * - * @param callback The callback function - */ - void add_on_cleared_callback(std::function<void()> &&callback); + /** Add a callback for when the state of the alarm_control_panel clears from triggered. */ + template<typename F> void add_on_cleared_callback(F &&callback) { + this->cleared_callback_.add(std::forward<F>(callback)); + } - /** Add a callback for when a chime zone goes from closed to open - * - * @param callback The callback function - */ - void add_on_chime_callback(std::function<void()> &&callback); + /** Add a callback for when a chime zone goes from closed to open. */ + template<typename F> void add_on_chime_callback(F &&callback) { + this->chime_callback_.add(std::forward<F>(callback)); + } - /** Add a callback for when a ready state changes - * - * @param callback The callback function - */ - void add_on_ready_callback(std::function<void()> &&callback); + /** Add a callback for when a ready state changes. */ + template<typename F> void add_on_ready_callback(F &&callback) { + this->ready_callback_.add(std::forward<F>(callback)); + } /** A numeric representation of the supported features as per HomeAssistant * diff --git a/esphome/components/button/button.cpp b/esphome/components/button/button.cpp index 8c06cfe59b..b1c491805e 100644 --- a/esphome/components/button/button.cpp +++ b/esphome/components/button/button.cpp @@ -20,6 +20,5 @@ void Button::press() { this->press_action(); this->press_callback_.call(); } -void Button::add_on_press_callback(std::function<void()> &&callback) { this->press_callback_.add(std::move(callback)); } } // namespace esphome::button diff --git a/esphome/components/button/button.h b/esphome/components/button/button.h index 0f7576a419..96e9107532 100644 --- a/esphome/components/button/button.h +++ b/esphome/components/button/button.h @@ -34,7 +34,9 @@ class Button : public EntityBase { * * @param callback The void() callback. */ - void add_on_press_callback(std::function<void()> &&callback); + template<typename F> void add_on_press_callback(F &&callback) { + this->press_callback_.add(std::forward<F>(callback)); + } protected: /** You should implement this virtual method if you want to create your own button. diff --git a/esphome/components/canbus/canbus.h b/esphome/components/canbus/canbus.h index f7b84111bd..420125e1d3 100644 --- a/esphome/components/canbus/canbus.h +++ b/esphome/components/canbus/canbus.h @@ -91,10 +91,7 @@ class Canbus : public Component { * - rtr If this is a remote transmission request * - data The message data */ - void add_callback( - std::function<void(uint32_t can_id, bool extended_id, bool rtr, const std::vector<uint8_t> &data)> callback) { - this->callback_manager_.add(std::move(callback)); - } + template<typename F> void add_callback(F &&callback) { this->callback_manager_.add(std::forward<F>(callback)); } protected: template<typename... Ts> friend class CanbusSendAction; diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 43d25effa3..3f44b986dc 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -356,14 +356,6 @@ ClimateCall &ClimateCall::set_swing_mode(optional<ClimateSwingMode> swing_mode) return *this; } -void Climate::add_on_state_callback(std::function<void(Climate &)> &&callback) { - this->state_callback_.add(std::move(callback)); -} - -void Climate::add_on_control_callback(std::function<void(ClimateCall &)> &&callback) { - this->control_callback_.add(std::move(callback)); -} - // Random 32bit value; If this changes existing restore preferences are invalidated static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL; diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index aa9ca91bc2..e2cb743c0a 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -192,7 +192,9 @@ class Climate : public EntityBase { * * @param callback The callback to call. */ - void add_on_state_callback(std::function<void(Climate &)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } /** * Add a callback for the climate device configuration; each time the configuration parameters of a climate device @@ -200,7 +202,9 @@ class Climate : public EntityBase { * * @param callback The callback to call. */ - void add_on_control_callback(std::function<void(ClimateCall &)> &&callback); + template<typename F> void add_on_control_callback(F &&callback) { + this->control_callback_.add(std::forward<F>(callback)); + } /** Make a climate device control call, this is used to control the climate device, see the ClimateCall description * for more info. diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index 0589aa2379..bb5965d861 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -139,7 +139,6 @@ bool CoverCall::get_stop() const { return this->stop_; } CoverCall Cover::make_call() { return {this}; } -void Cover::add_on_state_callback(std::function<void()> &&f) { this->state_callback_.add(std::move(f)); } void Cover::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); this->tilt = clamp(this->tilt, 0.0f, 1.0f); diff --git a/esphome/components/cover/cover.h b/esphome/components/cover/cover.h index 8cf9aa092a..9a75e68487 100644 --- a/esphome/components/cover/cover.h +++ b/esphome/components/cover/cover.h @@ -125,7 +125,7 @@ class Cover : public EntityBase { /// Construct a new cover call used to control the cover. CoverCall make_call(); - void add_on_state_callback(std::function<void()> &&f); + template<typename F> void add_on_state_callback(F &&f) { this->state_callback_.add(std::forward<F>(f)); } /** Publish the current state of the cover. * diff --git a/esphome/components/datetime/datetime_base.h b/esphome/components/datetime/datetime_base.h index 1b0b3d5463..98f23aa713 100644 --- a/esphome/components/datetime/datetime_base.h +++ b/esphome/components/datetime/datetime_base.h @@ -14,7 +14,9 @@ class DateTimeBase : public EntityBase { public: virtual ESPTime state_as_esptime() const = 0; - void add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); } + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } #ifdef USE_TIME void set_rtc(time::RealTimeClock *rtc) { this->rtc_ = rtc; } diff --git a/esphome/components/dfplayer/dfplayer.h b/esphome/components/dfplayer/dfplayer.h index 03d2230ca6..2c4ee03470 100644 --- a/esphome/components/dfplayer/dfplayer.h +++ b/esphome/components/dfplayer/dfplayer.h @@ -51,8 +51,8 @@ class DFPlayer : public uart::UARTDevice, public Component { bool is_playing() { return is_playing_; } void dump_config() override; - void add_on_finished_playback_callback(std::function<void()> callback) { - this->on_finished_playback_callback_.add(std::move(callback)); + template<typename F> void add_on_finished_playback_callback(F &&callback) { + this->on_finished_playback_callback_.add(std::forward<F>(callback)); } protected: diff --git a/esphome/components/display_menu_base/menu_item.h b/esphome/components/display_menu_base/menu_item.h index 36de146031..57d7350b9e 100644 --- a/esphome/components/display_menu_base/menu_item.h +++ b/esphome/components/display_menu_base/menu_item.h @@ -44,9 +44,9 @@ class MenuItem { MenuItemMenu *get_parent() { return this->parent_; } MenuItemType get_type() const { return this->item_type_; } template<typename V> void set_text(V val) { this->text_ = val; } - void add_on_enter_callback(std::function<void()> &&cb) { this->on_enter_callbacks_.add(std::move(cb)); } - void add_on_leave_callback(std::function<void()> &&cb) { this->on_leave_callbacks_.add(std::move(cb)); } - void add_on_value_callback(std::function<void()> &&cb) { this->on_value_callbacks_.add(std::move(cb)); } + template<typename F> void add_on_enter_callback(F &&cb) { this->on_enter_callbacks_.add(std::forward<F>(cb)); } + template<typename F> void add_on_leave_callback(F &&cb) { this->on_leave_callbacks_.add(std::forward<F>(cb)); } + template<typename F> void add_on_value_callback(F &&cb) { this->on_value_callbacks_.add(std::forward<F>(cb)); } std::string get_text() const { return const_cast<MenuItem *>(this)->text_.value(this); } virtual bool get_immediate_edit() const { return false; } @@ -170,8 +170,8 @@ class MenuItemCommand : public MenuItem { class MenuItemCustom : public MenuItemEditable { public: explicit MenuItemCustom() : MenuItemEditable(MENU_ITEM_CUSTOM) {} - void add_on_next_callback(std::function<void()> &&cb) { this->on_next_callbacks_.add(std::move(cb)); } - void add_on_prev_callback(std::function<void()> &&cb) { this->on_prev_callbacks_.add(std::move(cb)); } + template<typename F> void add_on_next_callback(F &&cb) { this->on_next_callbacks_.add(std::forward<F>(cb)); } + template<typename F> void add_on_prev_callback(F &&cb) { this->on_prev_callbacks_.add(std::forward<F>(cb)); } bool has_value() const override { return this->value_getter_.has_value(); } std::string get_value_text() const override; diff --git a/esphome/components/esp32_improv/esp32_improv_component.h b/esphome/components/esp32_improv/esp32_improv_component.h index 8f4cfd7958..41799f2325 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.h +++ b/esphome/components/esp32_improv/esp32_improv_component.h @@ -48,8 +48,8 @@ class ESP32ImprovComponent : public Component, public improv_base::ImprovBase { bool should_start() const { return this->should_start_; } #ifdef USE_ESP32_IMPROV_STATE_CALLBACK - void add_on_state_callback(std::function<void(improv::State, improv::Error)> &&callback) { - this->state_callback_.add(std::move(callback)); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); } #endif #ifdef USE_BINARY_SENSOR diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp index 667d4218f3..ec63fd9c3e 100644 --- a/esphome/components/event/event.cpp +++ b/esphome/components/event/event.cpp @@ -45,9 +45,5 @@ void Event::set_event_types(const std::vector<const char *> &event_types) { this->last_event_type_ = nullptr; // Reset when types change } -void Event::add_on_event_callback(std::function<void(StringRef event_type)> &&callback) { - this->event_callback_.add(std::move(callback)); -} - } // namespace event } // namespace esphome diff --git a/esphome/components/event/event.h b/esphome/components/event/event.h index 5b6a94b47c..ebbee0bfe2 100644 --- a/esphome/components/event/event.h +++ b/esphome/components/event/event.h @@ -66,7 +66,9 @@ class Event : public EntityBase { /// Check if an event has been triggered. bool has_event() const { return this->last_event_type_ != nullptr; } - void add_on_event_callback(std::function<void(StringRef event_type)> &&callback); + template<typename F> void add_on_event_callback(F &&callback) { + this->event_callback_.add(std::forward<F>(callback)); + } protected: LazyCallbackManager<void(StringRef event_type)> event_callback_; diff --git a/esphome/components/ezo/ezo.h b/esphome/components/ezo/ezo.h index f1a2802cbd..d80869fbd9 100644 --- a/esphome/components/ezo/ezo.h +++ b/esphome/components/ezo/ezo.h @@ -44,8 +44,8 @@ class EZOSensor : public sensor::Sensor, public PollingComponent, public i2c::I2 // Device Information void get_device_information(); - void add_device_infomation_callback(std::function<void(std::string)> &&callback) { - this->device_infomation_callback_.add(std::move(callback)); + template<typename F> void add_device_infomation_callback(F &&callback) { + this->device_infomation_callback_.add(std::forward<F>(callback)); } // Sleep @@ -56,15 +56,13 @@ class EZOSensor : public sensor::Sensor, public PollingComponent, public i2c::I2 // Slope void get_slope(); - void add_slope_callback(std::function<void(std::string)> &&callback) { - this->slope_callback_.add(std::move(callback)); - } + template<typename F> void add_slope_callback(F &&callback) { this->slope_callback_.add(std::forward<F>(callback)); } // T void get_t(); void set_t(float value); void set_tempcomp_value(float temp); // For backwards compatibility - void add_t_callback(std::function<void(std::string)> &&callback) { this->t_callback_.add(std::move(callback)); } + template<typename F> void add_t_callback(F &&callback) { this->t_callback_.add(std::forward<F>(callback)); } // Calibration void get_calibration(); @@ -73,20 +71,18 @@ class EZOSensor : public sensor::Sensor, public PollingComponent, public i2c::I2 void set_calibration_point_high(float value); void set_calibration_generic(float value); void clear_calibration(); - void add_calibration_callback(std::function<void(std::string)> &&callback) { - this->calibration_callback_.add(std::move(callback)); + template<typename F> void add_calibration_callback(F &&callback) { + this->calibration_callback_.add(std::forward<F>(callback)); } // LED void get_led_state(); void set_led_state(bool on); - void add_led_state_callback(std::function<void(bool)> &&callback) { this->led_callback_.add(std::move(callback)); } + template<typename F> void add_led_state_callback(F &&callback) { this->led_callback_.add(std::forward<F>(callback)); } // Custom void send_custom(const std::string &to_send); - void add_custom_callback(std::function<void(std::string)> &&callback) { - this->custom_callback_.add(std::move(callback)); - } + template<typename F> void add_custom_callback(F &&callback) { this->custom_callback_.add(std::forward<F>(callback)); } protected: std::deque<std::unique_ptr<EzoCommand>> commands_; diff --git a/esphome/components/factory_reset/factory_reset.h b/esphome/components/factory_reset/factory_reset.h index 990bb2edb6..34f89d73b6 100644 --- a/esphome/components/factory_reset/factory_reset.h +++ b/esphome/components/factory_reset/factory_reset.h @@ -17,8 +17,8 @@ class FactoryResetComponent : public Component { void dump_config() override; void setup() override; - void add_increment_callback(std::function<void(uint8_t, uint8_t)> &&callback) { - this->increment_callback_.add(std::move(callback)); + template<typename F> void add_increment_callback(F &&callback) { + this->increment_callback_.add(std::forward<F>(callback)); } protected: diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index c1e0a3dc2e..97336e17b5 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -193,7 +193,6 @@ void Fan::apply_preset_mode_(const FanCall &call) { } } -void Fan::add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); } void Fan::publish_state() { auto traits = this->get_traits(); diff --git a/esphome/components/fan/fan.h b/esphome/components/fan/fan.h index 2caf3a712a..e7b3681e32 100644 --- a/esphome/components/fan/fan.h +++ b/esphome/components/fan/fan.h @@ -122,7 +122,9 @@ class Fan : public EntityBase { FanCall make_call(); /// Register a callback that will be called each time the state changes. - void add_on_state_callback(std::function<void()> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } void publish_state(); diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index db9d5ce564..63839534f6 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -127,30 +127,30 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic void set_enrolling_binary_sensor(binary_sensor::BinarySensor *enrolling_binary_sensor) { this->enrolling_binary_sensor_ = enrolling_binary_sensor; } - void add_on_finger_scan_start_callback(std::function<void()> callback) { - this->finger_scan_start_callback_.add(std::move(callback)); + template<typename F> void add_on_finger_scan_start_callback(F &&callback) { + this->finger_scan_start_callback_.add(std::forward<F>(callback)); } - void add_on_finger_scan_matched_callback(std::function<void(uint16_t, uint16_t)> callback) { - this->finger_scan_matched_callback_.add(std::move(callback)); + template<typename F> void add_on_finger_scan_matched_callback(F &&callback) { + this->finger_scan_matched_callback_.add(std::forward<F>(callback)); } - void add_on_finger_scan_unmatched_callback(std::function<void()> callback) { - this->finger_scan_unmatched_callback_.add(std::move(callback)); + template<typename F> void add_on_finger_scan_unmatched_callback(F &&callback) { + this->finger_scan_unmatched_callback_.add(std::forward<F>(callback)); } - void add_on_finger_scan_misplaced_callback(std::function<void()> callback) { - this->finger_scan_misplaced_callback_.add(std::move(callback)); + template<typename F> void add_on_finger_scan_misplaced_callback(F &&callback) { + this->finger_scan_misplaced_callback_.add(std::forward<F>(callback)); } - void add_on_finger_scan_invalid_callback(std::function<void()> callback) { - this->finger_scan_invalid_callback_.add(std::move(callback)); + template<typename F> void add_on_finger_scan_invalid_callback(F &&callback) { + this->finger_scan_invalid_callback_.add(std::forward<F>(callback)); } - void add_on_enrollment_scan_callback(std::function<void(uint8_t, uint16_t)> callback) { - this->enrollment_scan_callback_.add(std::move(callback)); + template<typename F> void add_on_enrollment_scan_callback(F &&callback) { + this->enrollment_scan_callback_.add(std::forward<F>(callback)); } - void add_on_enrollment_done_callback(std::function<void(uint16_t)> callback) { - this->enrollment_done_callback_.add(std::move(callback)); + template<typename F> void add_on_enrollment_done_callback(F &&callback) { + this->enrollment_done_callback_.add(std::forward<F>(callback)); } - void add_on_enrollment_failed_callback(std::function<void(uint16_t)> callback) { - this->enrollment_failed_callback_.add(std::move(callback)); + template<typename F> void add_on_enrollment_failed_callback(F &&callback) { + this->enrollment_failed_callback_.add(std::forward<F>(callback)); } void enroll_fingerprint(uint16_t finger_id, uint8_t num_buffers); diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.h b/esphome/components/graphical_display_menu/graphical_display_menu.h index 96f2bd79fd..007889557d 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.h +++ b/esphome/components/graphical_display_menu/graphical_display_menu.h @@ -44,7 +44,7 @@ class GraphicalDisplayMenu : public display_menu_base::DisplayMenuComponent { void set_foreground_color(Color foreground_color); void set_background_color(Color background_color); - void add_on_redraw_callback(std::function<void()> &&cb) { this->on_redraw_callbacks_.add(std::move(cb)); } + template<typename F> void add_on_redraw_callback(F &&cb) { this->on_redraw_callbacks_.add(std::forward<F>(cb)); } void draw(display::Display *display, const display::Rect *bounds); diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 1882aa439e..35eaf36d32 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -197,10 +197,6 @@ void HaierClimateBase::send_custom_command(const haier_protocol::HaierMessage &m this->action_request_ = PendingAction({ActionRequest::SEND_CUSTOM_COMMAND, message}); } -void HaierClimateBase::add_status_message_callback(std::function<void(const char *, size_t)> &&callback) { - this->status_message_callback_.add(std::move(callback)); -} - haier_protocol::HandlerError HaierClimateBase::answer_preprocess_( haier_protocol::FrameType request_message_type, haier_protocol::FrameType expected_request_message_type, haier_protocol::FrameType answer_message_type, haier_protocol::FrameType expected_answer_message_type, diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index e24217bfd9..87aa1d65ef 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -74,7 +74,9 @@ class HaierClimateBase : public esphome::Component, void set_answer_timeout(uint32_t timeout); void set_send_wifi(bool send_wifi); void send_custom_command(const haier_protocol::HaierMessage &message); - void add_status_message_callback(std::function<void(const char *, size_t)> &&callback); + template<typename F> void add_status_message_callback(F &&callback) { + this->status_message_callback_.add(std::forward<F>(callback)); + } protected: enum class ProtocolPhases { diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index b8889ef2bd..b7888f7976 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -114,14 +114,6 @@ void HonClimate::start_steri_cleaning() { } } -void HonClimate::add_alarm_start_callback(std::function<void(uint8_t, const char *)> &&callback) { - this->alarm_start_callback_.add(std::move(callback)); -} - -void HonClimate::add_alarm_end_callback(std::function<void(uint8_t, const char *)> &&callback) { - this->alarm_end_callback_.add(std::move(callback)); -} - haier_protocol::HandlerError HonClimate::get_device_version_answer_handler_(haier_protocol::FrameType request_type, haier_protocol::FrameType message_type, const uint8_t *data, size_t data_size) { diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 9bddac3f92..7c48a3748b 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -124,8 +124,12 @@ class HonClimate : public HaierClimateBase { void set_extra_sensors_packet_bytes_size(size_t size) { this->extra_sensors_packet_bytes_ = size; }; void set_status_message_header_size(size_t size) { this->status_message_header_size_ = size; }; void set_control_method(HonControlMethod method) { this->control_method_ = method; }; - void add_alarm_start_callback(std::function<void(uint8_t, const char *)> &&callback); - void add_alarm_end_callback(std::function<void(uint8_t, const char *)> &&callback); + template<typename F> void add_alarm_start_callback(F &&callback) { + this->alarm_start_callback_.add(std::forward<F>(callback)); + } + template<typename F> void add_alarm_end_callback(F &&callback) { + this->alarm_end_callback_.add(std::forward<F>(callback)); + } float get_active_alarm_count() const { return this->active_alarm_count_; } protected: diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.h b/esphome/components/hlk_fm22x/hlk_fm22x.h index 0ea4636281..d897d51881 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.h +++ b/esphome/components/hlk_fm22x/hlk_fm22x.h @@ -91,24 +91,23 @@ class HlkFm22xComponent : public PollingComponent, public uart::UARTDevice { void set_version_text_sensor(text_sensor::TextSensor *version_text_sensor) { this->version_text_sensor_ = version_text_sensor; } - void add_on_face_scan_matched_callback(std::function<void(int16_t, std::string)> callback) { - this->face_scan_matched_callback_.add(std::move(callback)); + template<typename F> void add_on_face_scan_matched_callback(F &&callback) { + this->face_scan_matched_callback_.add(std::forward<F>(callback)); } - void add_on_face_scan_unmatched_callback(std::function<void()> callback) { - this->face_scan_unmatched_callback_.add(std::move(callback)); + template<typename F> void add_on_face_scan_unmatched_callback(F &&callback) { + this->face_scan_unmatched_callback_.add(std::forward<F>(callback)); } - void add_on_face_scan_invalid_callback(std::function<void(uint8_t)> callback) { - this->face_scan_invalid_callback_.add(std::move(callback)); + template<typename F> void add_on_face_scan_invalid_callback(F &&callback) { + this->face_scan_invalid_callback_.add(std::forward<F>(callback)); } - void add_on_face_info_callback( - std::function<void(int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t)> callback) { - this->face_info_callback_.add(std::move(callback)); + template<typename F> void add_on_face_info_callback(F &&callback) { + this->face_info_callback_.add(std::forward<F>(callback)); } - void add_on_enrollment_done_callback(std::function<void(int16_t, uint8_t)> callback) { - this->enrollment_done_callback_.add(std::move(callback)); + template<typename F> void add_on_enrollment_done_callback(F &&callback) { + this->enrollment_done_callback_.add(std::forward<F>(callback)); } - void add_on_enrollment_failed_callback(std::function<void(uint8_t)> callback) { - this->enrollment_failed_callback_.add(std::move(callback)); + template<typename F> void add_on_enrollment_failed_callback(F &&callback) { + this->enrollment_failed_callback_.add(std::forward<F>(callback)); } void enroll_face(const std::string &name, HlkFm22xFaceDirection direction); diff --git a/esphome/components/key_collector/key_collector.h b/esphome/components/key_collector/key_collector.h index 8e30c333df..014e2034bd 100644 --- a/esphome/components/key_collector/key_collector.h +++ b/esphome/components/key_collector/key_collector.h @@ -21,14 +21,14 @@ class KeyCollector : public Component { void set_back_keys(std::string back_keys) { this->back_keys_ = std::move(back_keys); }; void set_clear_keys(std::string clear_keys) { this->clear_keys_ = std::move(clear_keys); }; void set_allowed_keys(std::string allowed_keys) { this->allowed_keys_ = std::move(allowed_keys); }; - void add_on_progress_callback(std::function<void(const std::string &, uint8_t)> &&callback) { - this->progress_callbacks_.add(std::move(callback)); + template<typename F> void add_on_progress_callback(F &&callback) { + this->progress_callbacks_.add(std::forward<F>(callback)); } - void add_on_result_callback(std::function<void(const std::string &, uint8_t, uint8_t)> &&callback) { - this->result_callbacks_.add(std::move(callback)); + template<typename F> void add_on_result_callback(F &&callback) { + this->result_callbacks_.add(std::forward<F>(callback)); } - void add_on_timeout_callback(std::function<void(const std::string &, uint8_t)> &&callback) { - this->timeout_callbacks_.add(std::move(callback)); + template<typename F> void add_on_timeout_callback(F &&callback) { + this->timeout_callbacks_.add(std::forward<F>(callback)); } void set_timeout(int timeout) { this->timeout_ = timeout; }; void set_enabled(bool enabled); diff --git a/esphome/components/key_provider/key_provider.cpp b/esphome/components/key_provider/key_provider.cpp index 5a0e24b13f..64b0729d4d 100644 --- a/esphome/components/key_provider/key_provider.cpp +++ b/esphome/components/key_provider/key_provider.cpp @@ -3,10 +3,6 @@ namespace esphome { namespace key_provider { -void KeyProvider::add_on_key_callback(std::function<void(uint8_t)> &&callback) { - this->key_callback_.add(std::move(callback)); -} - void KeyProvider::send_key_(uint8_t key) { this->key_callback_.call(key); } } // namespace key_provider diff --git a/esphome/components/key_provider/key_provider.h b/esphome/components/key_provider/key_provider.h index 272d3eecad..9740342751 100644 --- a/esphome/components/key_provider/key_provider.h +++ b/esphome/components/key_provider/key_provider.h @@ -9,7 +9,7 @@ namespace key_provider { /// interface for components that provide keypresses class KeyProvider { public: - void add_on_key_callback(std::function<void(uint8_t)> &&callback); + template<typename F> void add_on_key_callback(F &&callback) { this->key_callback_.add(std::forward<F>(callback)); } protected: void send_key_(uint8_t key); diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index f9701cbdf6..0a1147c924 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -407,10 +407,6 @@ void LD2450Component::restart_and_read_all_info() { this->set_timeout(1500, [this]() { this->read_all_info(); }); } -void LD2450Component::add_on_data_callback(std::function<void()> &&callback) { - this->data_callback_.add(std::move(callback)); -} - // Send command with values to LD2450 void LD2450Component::send_command_(uint8_t command, const uint8_t *command_value, uint8_t command_value_len) { ESP_LOGV(TAG, "Sending COMMAND %02X", command); diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index 9409dfc21d..e774dd9c75 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -145,7 +145,7 @@ class LD2450Component : public Component, public uart::UARTDevice { int32_t zone3_y1, int32_t zone3_x2, int32_t zone3_y2); /// Add a callback that will be called after each successfully processed periodic data frame. - void add_on_data_callback(std::function<void()> &&callback); + template<typename F> void add_on_data_callback(F &&callback) { this->data_callback_.add(std::forward<F>(callback)); } protected: void send_command_(uint8_t command_str, const uint8_t *command_value, uint8_t command_value_len); diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 939c84720b..4aa636e998 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -48,8 +48,6 @@ void Lock::publish_state(LockState state) { #endif } -void Lock::add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); } - void LockCall::perform() { ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); this->validate_(); diff --git a/esphome/components/lock/lock.h b/esphome/components/lock/lock.h index bebd296eac..707431d543 100644 --- a/esphome/components/lock/lock.h +++ b/esphome/components/lock/lock.h @@ -150,7 +150,9 @@ class Lock : public EntityBase { * * @param callback The void(bool) callback. */ - void add_on_state_callback(std::function<void()> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } protected: friend LockCall; diff --git a/esphome/components/ltr501/ltr501.h b/esphome/components/ltr501/ltr501.h index d9a53c9bd4..2bd838a0fe 100644 --- a/esphome/components/ltr501/ltr501.h +++ b/esphome/components/ltr501/ltr501.h @@ -160,12 +160,12 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { CallbackManager<void()> on_ps_high_trigger_callback_; CallbackManager<void()> on_ps_low_trigger_callback_; - void add_on_ps_high_trigger_callback_(std::function<void()> callback) { - this->on_ps_high_trigger_callback_.add(std::move(callback)); + template<typename F> void add_on_ps_high_trigger_callback_(F &&callback) { + this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); } - void add_on_ps_low_trigger_callback_(std::function<void()> callback) { - this->on_ps_low_trigger_callback_.add(std::move(callback)); + template<typename F> void add_on_ps_low_trigger_callback_(F &&callback) { + this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); } }; diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.h b/esphome/components/ltr_als_ps/ltr_als_ps.h index 3ab2cea074..2e24a14283 100644 --- a/esphome/components/ltr_als_ps/ltr_als_ps.h +++ b/esphome/components/ltr_als_ps/ltr_als_ps.h @@ -160,12 +160,12 @@ class LTRAlsPsComponent : public PollingComponent, public i2c::I2CDevice { CallbackManager<void()> on_ps_high_trigger_callback_; CallbackManager<void()> on_ps_low_trigger_callback_; - void add_on_ps_high_trigger_callback_(std::function<void()> callback) { - this->on_ps_high_trigger_callback_.add(std::move(callback)); + template<typename F> void add_on_ps_high_trigger_callback_(F &&callback) { + this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); } - void add_on_ps_low_trigger_callback_(std::function<void()> callback) { - this->on_ps_low_trigger_callback_.add(std::move(callback)); + template<typename F> void add_on_ps_low_trigger_callback_(F &&callback) { + this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); } }; diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 9c82f3646b..aa8dd2fba5 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -158,9 +158,7 @@ class LvglComponent : public PollingComponent { void setup() override; void update() override; void loop() override; - void add_on_idle_callback(std::function<void(uint32_t)> &&callback) { - this->idle_callbacks_.add(std::move(callback)); - } + template<typename F> void add_on_idle_callback(F &&callback) { this->idle_callbacks_.add(std::forward<F>(callback)); } static void monitor_cb(lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px); static void render_start_cb(lv_disp_drv_t *disp_drv); diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index a53d598b0f..70086089ff 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -198,10 +198,6 @@ MediaPlayerCall &MediaPlayerCall::set_announcement(bool announce) { return *this; } -void MediaPlayer::add_on_state_callback(std::function<void()> &&callback) { - this->state_callback_.add(std::move(callback)); -} - void MediaPlayer::publish_state() { this->state_callback_.call(); #if defined(USE_MEDIA_PLAYER) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 3509747718..26eca469e7 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -155,7 +155,9 @@ class MediaPlayer : public EntityBase { void publish_state(); - void add_on_state_callback(std::function<void()> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } virtual bool is_muted() const { return false; } diff --git a/esphome/components/microphone/microphone.cpp b/esphome/components/microphone/microphone.cpp deleted file mode 100644 index 0fbb393fd2..0000000000 --- a/esphome/components/microphone/microphone.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "microphone.h" - -namespace esphome { -namespace microphone { - -void Microphone::add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback) { - std::function<void(const std::vector<uint8_t> &)> mute_handled_callback = - [this, data_callback](const std::vector<uint8_t> &data) { - if (this->mute_state_) { - data_callback(std::vector<uint8_t>(data.size(), 0)); - } else { - data_callback(data); - }; - }; - this->data_callbacks_.add(std::move(mute_handled_callback)); -} - -} // namespace microphone -} // namespace esphome diff --git a/esphome/components/microphone/microphone.h b/esphome/components/microphone/microphone.h index fcf9822458..50ce1a7281 100644 --- a/esphome/components/microphone/microphone.h +++ b/esphome/components/microphone/microphone.h @@ -4,7 +4,6 @@ #include <cstddef> #include <cstdint> -#include <functional> #include <vector> #include "esphome/core/helpers.h" @@ -22,7 +21,15 @@ class Microphone { public: virtual void start() = 0; virtual void stop() = 0; - void add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback); + template<typename F> void add_data_callback(F &&data_callback) { + this->data_callbacks_.add([this, data_callback](const std::vector<uint8_t> &data) { + if (this->mute_state_) { + data_callback(std::vector<uint8_t>(data.size(), 0)); + } else { + data_callback(data); + } + }); + } bool is_running() const { return this->state_ == STATE_RUNNING; } bool is_stopped() const { return this->state_ == STATE_STOPPED; } diff --git a/esphome/components/microphone/microphone_source.cpp b/esphome/components/microphone/microphone_source.cpp index 00efcf22a1..fb4ebc4a04 100644 --- a/esphome/components/microphone/microphone_source.cpp +++ b/esphome/components/microphone/microphone_source.cpp @@ -6,24 +6,6 @@ namespace microphone { static const int32_t Q25_MAX_VALUE = (1 << 25) - 1; static const int32_t Q25_MIN_VALUE = ~Q25_MAX_VALUE; -void MicrophoneSource::add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback) { - std::function<void(const std::vector<uint8_t> &)> filtered_callback = - [this, data_callback](const std::vector<uint8_t> &data) { - if (this->enabled_ || this->passive_) { - if (this->processed_samples_.use_count() == 0) { - // Create vector if its unused - this->processed_samples_ = std::make_shared<std::vector<uint8_t>>(); - } - - // Take temporary ownership of samples vector to avoid deallaction before the callback finishes - std::shared_ptr<std::vector<uint8_t>> output_samples = this->processed_samples_; - this->process_audio_(data, *output_samples); - data_callback(*output_samples); - } - }; - this->mic_->add_data_callback(std::move(filtered_callback)); -} - audio::AudioStreamInfo MicrophoneSource::get_audio_stream_info() { return audio::AudioStreamInfo(this->bits_per_sample_, this->channels_.count(), this->mic_->get_audio_stream_info().get_sample_rate()); diff --git a/esphome/components/microphone/microphone_source.h b/esphome/components/microphone/microphone_source.h index 1e81a284b6..5c8053e502 100644 --- a/esphome/components/microphone/microphone_source.h +++ b/esphome/components/microphone/microphone_source.h @@ -7,7 +7,6 @@ #include <bitset> #include <cstddef> #include <cstdint> -#include <functional> #include <vector> namespace esphome { @@ -47,7 +46,21 @@ class MicrophoneSource { /// @param channel 0-indexed channel number to enable void add_channel(uint8_t channel) { this->channels_.set(channel); } - void add_data_callback(std::function<void(const std::vector<uint8_t> &)> &&data_callback); + template<typename F> void add_data_callback(F &&data_callback) { + this->mic_->add_data_callback([this, data_callback](const std::vector<uint8_t> &data) { + if (this->enabled_ || this->passive_) { + if (this->processed_samples_.use_count() == 0) { + // Create vector if its unused + this->processed_samples_ = std::make_shared<std::vector<uint8_t>>(); + } + + // Take temporary ownership of samples vector to avoid deallocation before the callback finishes + std::shared_ptr<std::vector<uint8_t>> output_samples = this->processed_samples_; + this->process_audio_(data, *output_samples); + data_callback(*output_samples); + } + }); + } void set_gain_factor(int32_t gain_factor) { this->gain_factor_ = clamp<int32_t>(gain_factor, 1, MAX_GAIN_FACTOR); } int32_t get_gain_factor() { return this->gain_factor_; } diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index f77f51a20d..ea6ba9d085 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -837,17 +837,5 @@ int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sens return value; } -void ModbusController::add_on_command_sent_callback(std::function<void(int, int)> &&callback) { - this->command_sent_callback_.add(std::move(callback)); -} - -void ModbusController::add_on_online_callback(std::function<void(int, int)> &&callback) { - this->online_callback_.add(std::move(callback)); -} - -void ModbusController::add_on_offline_callback(std::function<void(int, int)> &&callback) { - this->offline_callback_.add(std::move(callback)); -} - } // namespace modbus_controller } // namespace esphome diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index bd3d4d705e..78c3b95965 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -508,11 +508,17 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { /// get if the module is offline, didn't respond the last command bool get_module_offline() { return module_offline_; } /// Set callback for commands - void add_on_command_sent_callback(std::function<void(int, int)> &&callback); + template<typename F> void add_on_command_sent_callback(F &&callback) { + this->command_sent_callback_.add(std::forward<F>(callback)); + } /// Set callback for online changes - void add_on_online_callback(std::function<void(int, int)> &&callback); + template<typename F> void add_on_online_callback(F &&callback) { + this->online_callback_.add(std::forward<F>(callback)); + } /// Set callback for offline changes - void add_on_offline_callback(std::function<void(int, int)> &&callback); + template<typename F> void add_on_offline_callback(F &&callback) { + this->offline_callback_.add(std::forward<F>(callback)); + } /// called by esphome generated code to set the max_cmd_retries. void set_max_cmd_retries(uint8_t max_cmd_retries) { this->max_cmd_retries_ = max_cmd_retries; } /// get how many times a command will be (re)sent if no response is received diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 01ceb3d765..85da6af48a 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -214,30 +214,6 @@ void Nextion::update() { } } -void Nextion::add_sleep_state_callback(std::function<void()> &&callback) { - this->sleep_callback_.add(std::move(callback)); -} - -void Nextion::add_wake_state_callback(std::function<void()> &&callback) { - this->wake_callback_.add(std::move(callback)); -} - -void Nextion::add_setup_state_callback(std::function<void()> &&callback) { - this->setup_callback_.add(std::move(callback)); -} - -void Nextion::add_new_page_callback(std::function<void(uint8_t)> &&callback) { - this->page_callback_.add(std::move(callback)); -} - -void Nextion::add_touch_event_callback(std::function<void(uint8_t, uint8_t, bool)> &&callback) { - this->touch_callback_.add(std::move(callback)); -} - -void Nextion::add_buffer_overflow_event_callback(std::function<void()> &&callback) { - this->buffer_overflow_callback_.add(std::move(callback)); -} - void Nextion::update_all_components() { if ((!this->is_setup() && !this->connection_state_.ignore_is_setup_) || this->is_sleeping()) return; diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 7999e3c4e3..2842e57ce8 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1138,37 +1138,47 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe * * @param callback The void() callback. */ - void add_sleep_state_callback(std::function<void()> &&callback); + template<typename F> void add_sleep_state_callback(F &&callback) { + this->sleep_callback_.add(std::forward<F>(callback)); + } /** Add a callback to be notified of wake state changes. * * @param callback The void() callback. */ - void add_wake_state_callback(std::function<void()> &&callback); + template<typename F> void add_wake_state_callback(F &&callback) { + this->wake_callback_.add(std::forward<F>(callback)); + } /** Add a callback to be notified when the nextion completes its initialize setup. * * @param callback The void() callback. */ - void add_setup_state_callback(std::function<void()> &&callback); + template<typename F> void add_setup_state_callback(F &&callback) { + this->setup_callback_.add(std::forward<F>(callback)); + } /** Add a callback to be notified when the nextion changes pages. * * @param callback The void(std::string) callback. */ - void add_new_page_callback(std::function<void(uint8_t)> &&callback); + template<typename F> void add_new_page_callback(F &&callback) { this->page_callback_.add(std::forward<F>(callback)); } /** Add a callback to be notified when Nextion has a touch event. * * @param callback The void() callback. */ - void add_touch_event_callback(std::function<void(uint8_t, uint8_t, bool)> &&callback); + template<typename F> void add_touch_event_callback(F &&callback) { + this->touch_callback_.add(std::forward<F>(callback)); + } /** Add a callback to be notified when the nextion reports a buffer overflow. * * @param callback The void() callback. */ - void add_buffer_overflow_event_callback(std::function<void()> &&callback); + template<typename F> void add_buffer_overflow_event_callback(F &&callback) { + this->buffer_overflow_callback_.add(std::forward<F>(callback)); + } void update_all_components(); diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index c0653c3b30..fb5d6e9f28 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -29,8 +29,4 @@ void Number::publish_state(float state) { #endif } -void Number::add_on_state_callback(std::function<void(float)> &&callback) { - this->state_callback_.add(std::move(callback)); -} - } // namespace esphome::number diff --git a/esphome/components/number/number.h b/esphome/components/number/number.h index 0425714702..579d488cf0 100644 --- a/esphome/components/number/number.h +++ b/esphome/components/number/number.h @@ -34,7 +34,9 @@ class Number : public EntityBase { NumberCall make_call() { return NumberCall(this); } - void add_on_state_callback(std::function<void(float)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } NumberTraits traits; diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index 22bf6a3056..24926aa4dc 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -228,14 +228,6 @@ void OnlineImage::end_connection_() { this->disable_loop(); } -void OnlineImage::add_on_finished_callback(std::function<void(bool)> &&callback) { - this->download_finished_callback_.add(std::move(callback)); -} - -void OnlineImage::add_on_error_callback(std::function<void()> &&callback) { - this->download_error_callback_.add(std::move(callback)); -} - void OnlineImage::release() { // Clear cache headers this->etag_ = ""; diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 12c2564526..3a348cbb07 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -65,8 +65,12 @@ class OnlineImage : public PollingComponent, */ void release(); - void add_on_finished_callback(std::function<void(bool)> &&callback); - void add_on_error_callback(std::function<void()> &&callback); + template<typename F> void add_on_finished_callback(F &&callback) { + this->download_finished_callback_.add(std::forward<F>(callback)); + } + template<typename F> void add_on_error_callback(F &&callback) { + this->download_error_callback_.add(std::forward<F>(callback)); + } protected: bool validate_url_(const std::string &url); diff --git a/esphome/components/opentherm/hub.h b/esphome/components/opentherm/hub.h index ee0cfd104d..960e23d6dd 100644 --- a/esphome/components/opentherm/hub.h +++ b/esphome/components/opentherm/hub.h @@ -160,11 +160,11 @@ class OpenthermHub : public Component { void set_dhw_block(bool value) { this->dhw_block = value; } void set_sync_mode(bool sync_mode) { this->sync_mode_ = sync_mode; } - void add_on_before_send_callback(std::function<void(OpenthermData &)> &&callback) { - this->before_send_callback_.add(std::move(callback)); + template<typename F> void add_on_before_send_callback(F &&callback) { + this->before_send_callback_.add(std::forward<F>(callback)); } - void add_on_before_process_response_callback(std::function<void(OpenthermData &)> &&callback) { - this->before_process_response_callback_.add(std::move(callback)); + template<typename F> void add_on_before_process_response_callback(F &&callback) { + this->before_process_response_callback_.add(std::forward<F>(callback)); } float get_setup_priority() const override { return setup_priority::HARDWARE; } diff --git a/esphome/components/pid/pid_climate.h b/esphome/components/pid/pid_climate.h index 3708c29ff1..479a0e48ee 100644 --- a/esphome/components/pid/pid_climate.h +++ b/esphome/components/pid/pid_climate.h @@ -72,8 +72,8 @@ class PIDClimate : public climate::Climate, public Component { // float get_deadband() const { return controller_.deadband; } // float get_proportional_deadband_multiplier() const { return controller_.proportional_deadband_multiplier; } - void add_on_pid_computed_callback(std::function<void()> &&callback) { - pid_computed_callback_.add(std::move(callback)); + template<typename F> void add_on_pid_computed_callback(F &&callback) { + this->pid_computed_callback_.add(std::forward<F>(callback)); } void set_default_target_temperature(float default_target_temperature) { default_target_temperature_ = default_target_temperature; diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index e57ecd8104..1f6a6b3bc3 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -43,8 +43,8 @@ class PN532 : public PollingComponent { void register_ontag_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontag_.push_back(trig); } void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontagremoved_.push_back(trig); } - void add_on_finished_write_callback(std::function<void()> callback) { - this->on_finished_write_callback_.add(std::move(callback)); + template<typename F> void add_on_finished_write_callback(F &&callback) { + this->on_finished_write_callback_.add(std::forward<F>(callback)); } bool is_writing() { return this->next_task_ != READ; }; diff --git a/esphome/components/pn7150/pn7150.h b/esphome/components/pn7150/pn7150.h index c5dd283832..a468d80943 100644 --- a/esphome/components/pn7150/pn7150.h +++ b/esphome/components/pn7150/pn7150.h @@ -167,12 +167,12 @@ class PN7150 : public nfc::Nfcc, public Component { void register_ontag_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontag_.push_back(trig); } void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontagremoved_.push_back(trig); } - void add_on_emulated_tag_scan_callback(std::function<void()> callback) { - this->on_emulated_tag_scan_callback_.add(std::move(callback)); + template<typename F> void add_on_emulated_tag_scan_callback(F &&callback) { + this->on_emulated_tag_scan_callback_.add(std::forward<F>(callback)); } - void add_on_finished_write_callback(std::function<void()> callback) { - this->on_finished_write_callback_.add(std::move(callback)); + template<typename F> void add_on_finished_write_callback(F &&callback) { + this->on_finished_write_callback_.add(std::forward<F>(callback)); } bool is_writing() { return this->next_task_ != EP_READ; }; diff --git a/esphome/components/pn7160/pn7160.h b/esphome/components/pn7160/pn7160.h index 77ab49399c..44f7eb0796 100644 --- a/esphome/components/pn7160/pn7160.h +++ b/esphome/components/pn7160/pn7160.h @@ -184,12 +184,12 @@ class PN7160 : public nfc::Nfcc, public Component { void register_ontag_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontag_.push_back(trig); } void register_ontagremoved_trigger(nfc::NfcOnTagTrigger *trig) { this->triggers_ontagremoved_.push_back(trig); } - void add_on_emulated_tag_scan_callback(std::function<void()> callback) { - this->on_emulated_tag_scan_callback_.add(std::move(callback)); + template<typename F> void add_on_emulated_tag_scan_callback(F &&callback) { + this->on_emulated_tag_scan_callback_.add(std::forward<F>(callback)); } - void add_on_finished_write_callback(std::function<void()> callback) { - this->on_finished_write_callback_.add(std::move(callback)); + template<typename F> void add_on_finished_write_callback(F &&callback) { + this->on_finished_write_callback_.add(std::forward<F>(callback)); } bool is_writing() { return this->next_task_ != EP_READ; }; diff --git a/esphome/components/rf_bridge/rf_bridge.h b/esphome/components/rf_bridge/rf_bridge.h index c93b636c38..e5780c9ebe 100644 --- a/esphome/components/rf_bridge/rf_bridge.h +++ b/esphome/components/rf_bridge/rf_bridge.h @@ -49,11 +49,11 @@ class RFBridgeComponent : public uart::UARTDevice, public Component { public: void loop() override; void dump_config() override; - void add_on_code_received_callback(std::function<void(RFBridgeData)> callback) { - this->data_callback_.add(std::move(callback)); + template<typename F> void add_on_code_received_callback(F &&callback) { + this->data_callback_.add(std::forward<F>(callback)); } - void add_on_advanced_code_received_callback(std::function<void(RFBridgeAdvancedData)> callback) { - this->advanced_data_callback_.add(std::move(callback)); + template<typename F> void add_on_advanced_code_received_callback(F &&callback) { + this->advanced_data_callback_.add(std::forward<F>(callback)); } void send_code(RFBridgeData data); void send_advanced_code(const RFBridgeAdvancedData &data); diff --git a/esphome/components/rotary_encoder/rotary_encoder.h b/esphome/components/rotary_encoder/rotary_encoder.h index 865554cd4d..4b776fe55e 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.h +++ b/esphome/components/rotary_encoder/rotary_encoder.h @@ -82,15 +82,15 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { void dump_config() override; void loop() override; - void add_on_clockwise_callback(std::function<void()> callback) { - this->on_clockwise_callback_.add(std::move(callback)); + template<typename F> void add_on_clockwise_callback(F &&callback) { + this->on_clockwise_callback_.add(std::forward<F>(callback)); } - void add_on_anticlockwise_callback(std::function<void()> callback) { - this->on_anticlockwise_callback_.add(std::move(callback)); + template<typename F> void add_on_anticlockwise_callback(F &&callback) { + this->on_anticlockwise_callback_.add(std::forward<F>(callback)); } - void register_listener(std::function<void(uint32_t)> listener) { this->listeners_.add(std::move(listener)); } + template<typename F> void register_listener(F &&listener) { this->listeners_.add(std::forward<F>(listener)); } protected: InternalGPIOPin *pin_a_; diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index e37cccae9e..bff43d2edd 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -45,8 +45,8 @@ class Rtttl : public Component { bool is_playing() { return this->state_ != State::STOPPED; } - void add_on_finished_playback_callback(std::function<void()> callback) { - this->on_finished_playback_callback_.add(std::move(callback)); + template<typename F> void add_on_finished_playback_callback(F &&callback) { + this->on_finished_playback_callback_.add(std::forward<F>(callback)); } protected: diff --git a/esphome/components/safe_mode/safe_mode.h b/esphome/components/safe_mode/safe_mode.h index 1b28ea28f2..2733054962 100644 --- a/esphome/components/safe_mode/safe_mode.h +++ b/esphome/components/safe_mode/safe_mode.h @@ -34,8 +34,8 @@ class SafeModeComponent final : public Component { void mark_successful(); #ifdef USE_SAFE_MODE_CALLBACK - void add_on_safe_mode_callback(std::function<void()> &&callback) { - this->safe_mode_callback_.add(std::move(callback)); + template<typename F> void add_on_safe_mode_callback(F &&callback) { + this->safe_mode_callback_.add(std::forward<F>(callback)); } #endif diff --git a/esphome/components/sdl/sdl_esphome.h b/esphome/components/sdl/sdl_esphome.h index bf5fde1428..c025e8ff6e 100644 --- a/esphome/components/sdl/sdl_esphome.h +++ b/esphome/components/sdl/sdl_esphome.h @@ -37,11 +37,11 @@ class Sdl : public display::Display { int get_height() override { return this->height_; } float get_setup_priority() const override { return setup_priority::HARDWARE; } void dump_config() override { LOG_DISPLAY("", "SDL", this); } - void add_key_listener(int32_t keycode, std::function<void(bool)> &&callback) { + template<typename F> void add_key_listener(int32_t keycode, F &&callback) { if (!this->key_callbacks_.count(keycode)) { this->key_callbacks_[keycode] = CallbackManager<void(bool)>(); } - this->key_callbacks_[keycode].add(std::move(callback)); + this->key_callbacks_[keycode].add(std::forward<F>(callback)); } int mouse_x{}; diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index 91e27b30de..df90c657e2 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -42,10 +42,6 @@ StringRef Select::current_option() const { return this->has_state() ? StringRef(this->option_at(this->active_index_)) : StringRef(); } -void Select::add_on_state_callback(std::function<void(size_t)> &&callback) { - this->state_callback_.add(std::move(callback)); -} - bool Select::has_option(const std::string &option) const { return this->index_of(option.c_str()).has_value(); } bool Select::has_option(const char *option) const { return this->index_of(option).has_value(); } diff --git a/esphome/components/select/select.h b/esphome/components/select/select.h index c91acd1e19..465283d92a 100644 --- a/esphome/components/select/select.h +++ b/esphome/components/select/select.h @@ -76,7 +76,9 @@ class Select : public EntityBase { /// Return the option value at the provided index offset (as const char* from flash). const char *option_at(size_t index) const; - void add_on_state_callback(std::function<void(size_t)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } protected: friend class SelectCall; diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index a7af6403ef..b4e59dfeb5 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -79,11 +79,6 @@ void Sensor::publish_state(float state) { #endif } -void Sensor::add_on_state_callback(std::function<void(float)> &&callback) { this->callback_.add(std::move(callback)); } -void Sensor::add_on_raw_state_callback(std::function<void(float)> &&callback) { - this->raw_callback_.add(std::move(callback)); -} - #ifdef USE_SENSOR_FILTER void Sensor::add_filter(Filter *filter) { // inefficient, but only happens once on every sensor setup and nobody's going to have massive amounts of diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index 197896f6f6..b3bd962036 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -111,9 +111,11 @@ class Sensor : public EntityBase { // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) /// Add a callback that will be called every time a filtered value arrives. - void add_on_state_callback(std::function<void(float)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { this->callback_.add(std::forward<F>(callback)); } /// Add a callback that will be called every time the sensor sends a raw value. - void add_on_raw_state_callback(std::function<void(float)> &&callback); + template<typename F> void add_on_raw_state_callback(F &&callback) { + this->raw_callback_.add(std::forward<F>(callback)); + } /** This member variable stores the last state that has passed through all filters. * diff --git a/esphome/components/sim800l/sim800l.h b/esphome/components/sim800l/sim800l.h index e9e2f66d78..d79279ea72 100644 --- a/esphome/components/sim800l/sim800l.h +++ b/esphome/components/sim800l/sim800l.h @@ -61,20 +61,20 @@ class Sim800LComponent : public uart::UARTDevice, public PollingComponent { #ifdef USE_SENSOR void set_rssi_sensor(sensor::Sensor *rssi_sensor) { rssi_sensor_ = rssi_sensor; } #endif - void add_on_sms_received_callback(std::function<void(std::string, std::string)> callback) { - this->sms_received_callback_.add(std::move(callback)); + template<typename F> void add_on_sms_received_callback(F &&callback) { + this->sms_received_callback_.add(std::forward<F>(callback)); } - void add_on_incoming_call_callback(std::function<void(std::string)> callback) { - this->incoming_call_callback_.add(std::move(callback)); + template<typename F> void add_on_incoming_call_callback(F &&callback) { + this->incoming_call_callback_.add(std::forward<F>(callback)); } - void add_on_call_connected_callback(std::function<void()> callback) { - this->call_connected_callback_.add(std::move(callback)); + template<typename F> void add_on_call_connected_callback(F &&callback) { + this->call_connected_callback_.add(std::forward<F>(callback)); } - void add_on_call_disconnected_callback(std::function<void()> callback) { - this->call_disconnected_callback_.add(std::move(callback)); + template<typename F> void add_on_call_disconnected_callback(F &&callback) { + this->call_disconnected_callback_.add(std::forward<F>(callback)); } - void add_on_ussd_received_callback(std::function<void(std::string)> callback) { - this->ussd_received_callback_.add(std::move(callback)); + template<typename F> void add_on_ussd_received_callback(F &&callback) { + this->ussd_received_callback_.add(std::forward<F>(callback)); } void send_sms(const std::string &recipient, const std::string &message); void send_ussd(const std::string &ussd_code); diff --git a/esphome/components/sml/sml.cpp b/esphome/components/sml/sml.cpp index c1ffdc0e68..c8d5fcc269 100644 --- a/esphome/components/sml/sml.cpp +++ b/esphome/components/sml/sml.cpp @@ -61,10 +61,6 @@ void Sml::loop() { } } -void Sml::add_on_data_callback(std::function<void(std::vector<uint8_t>, bool)> &&callback) { - this->data_callbacks_.add(std::move(callback)); -} - void Sml::process_sml_file_(const BytesView &sml_data) { SmlFile sml_file(sml_data); std::vector<ObisInfo> obis_info = sml_file.get_obis_info(); diff --git a/esphome/components/sml/sml.h b/esphome/components/sml/sml.h index 15ca43944c..29a2f48bbe 100644 --- a/esphome/components/sml/sml.h +++ b/esphome/components/sml/sml.h @@ -24,7 +24,7 @@ class Sml : public Component, public uart::UARTDevice { void loop() override; void dump_config() override; std::vector<SmlListener *> sml_listeners_{}; - void add_on_data_callback(std::function<void(std::vector<uint8_t>, bool)> &&callback); + template<typename F> void add_on_data_callback(F &&callback) { this->data_callbacks_.add(std::forward<F>(callback)); } protected: void process_sml_file_(const BytesView &sml_data); diff --git a/esphome/components/speaker/speaker.h b/esphome/components/speaker/speaker.h index 373d2e3a74..5b89d00c69 100644 --- a/esphome/components/speaker/speaker.h +++ b/esphome/components/speaker/speaker.h @@ -106,8 +106,8 @@ class Speaker { /// Parameters: /// - Frames played /// - System time in microseconds when the frames were written to the DAC - void add_audio_output_callback(std::function<void(uint32_t, int64_t)> &&callback) { - this->audio_output_callback_.add(std::move(callback)); + template<typename F> void add_audio_output_callback(F &&callback) { + this->audio_output_callback_.add(std::forward<F>(callback)); } protected: diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 9e9af21368..df762addbb 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -69,9 +69,6 @@ void Switch::publish_state(bool state) { } bool Switch::assumed_state() { return false; } -void Switch::add_on_state_callback(std::function<void(bool)> &&callback) { - this->state_callback_.add(std::move(callback)); -} void Switch::set_inverted(bool inverted) { this->inverted_ = inverted; } bool Switch::is_inverted() const { return this->inverted_; } diff --git a/esphome/components/switch/switch.h b/esphome/components/switch/switch.h index c4f8525793..b7761cba0a 100644 --- a/esphome/components/switch/switch.h +++ b/esphome/components/switch/switch.h @@ -93,7 +93,9 @@ class Switch : public EntityBase { * * @param callback The void(bool) callback. */ - void add_on_state_callback(std::function<void(bool)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } /** Returns the initial state of the switch, as persisted previously, or empty if never persisted. diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index d8ab6b1b92..12abc5d939 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -29,8 +29,4 @@ void Text::publish_state(const char *state, size_t len) { #endif } -void Text::add_on_state_callback(std::function<void(const std::string &)> &&callback) { - this->state_callback_.add(std::move(callback)); -} - } // namespace esphome::text diff --git a/esphome/components/text/text.h b/esphome/components/text/text.h index 7d255e5688..eb6a68f998 100644 --- a/esphome/components/text/text.h +++ b/esphome/components/text/text.h @@ -30,7 +30,9 @@ class Text : public EntityBase { /// Instantiate a TextCall object to modify this text component's state. TextCall make_call() { return TextCall(this); } - void add_on_state_callback(std::function<void(const std::string &)> &&callback); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } protected: friend class TextCall; diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 91561c5f42..aa49a85d26 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -83,13 +83,6 @@ void TextSensor::clear_filters() { } #endif // USE_TEXT_SENSOR_FILTER -void TextSensor::add_on_state_callback(std::function<void(const std::string &)> callback) { - this->callback_.add(std::move(callback)); -} -void TextSensor::add_on_raw_state_callback(std::function<void(const std::string &)> callback) { - this->raw_callback_.add(std::move(callback)); -} - const std::string &TextSensor::get_state() const { return this->state; } const std::string &TextSensor::get_raw_state() const { #ifdef USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/text_sensor.h b/esphome/components/text_sensor/text_sensor.h index d26cfade96..8941790e7c 100644 --- a/esphome/components/text_sensor/text_sensor.h +++ b/esphome/components/text_sensor/text_sensor.h @@ -62,9 +62,11 @@ class TextSensor : public EntityBase { void clear_filters(); #endif - void add_on_state_callback(std::function<void(const std::string &)> callback); + template<typename F> void add_on_state_callback(F &&callback) { this->callback_.add(std::forward<F>(callback)); } /// Add a callback that will be called every time the sensor sends a raw value. - void add_on_raw_state_callback(std::function<void(const std::string &)> callback); + template<typename F> void add_on_raw_state_callback(F &&callback) { + this->raw_callback_.add(std::forward<F>(callback)); + } // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) diff --git a/esphome/components/time/real_time_clock.h b/esphome/components/time/real_time_clock.h index f9de5f5614..06ee2ea5af 100644 --- a/esphome/components/time/real_time_clock.h +++ b/esphome/components/time/real_time_clock.h @@ -55,9 +55,9 @@ class RealTimeClock : public PollingComponent { /// Get the current time as the UTC epoch since January 1st 1970. time_t timestamp_now() { return ::time(nullptr); } - void add_on_time_sync_callback(std::function<void()> &&callback) { - this->time_sync_callback_.add(std::move(callback)); - }; + template<typename F> void add_on_time_sync_callback(F &&callback) { + this->time_sync_callback_.add(std::forward<F>(callback)); + } void dump_config() override; diff --git a/esphome/components/tuya/tuya.h b/esphome/components/tuya/tuya.h index 76431ddfe4..7e6b50f084 100644 --- a/esphome/components/tuya/tuya.h +++ b/esphome/components/tuya/tuya.h @@ -112,8 +112,8 @@ class Tuya : public Component, public uart::UARTDevice { void add_ignore_mcu_update_on_datapoints(uint8_t ignore_mcu_update_on_datapoints) { this->ignore_mcu_update_on_datapoints_.push_back(ignore_mcu_update_on_datapoints); } - void add_on_initialized_callback(std::function<void()> callback) { - this->initialized_callback_.add(std::move(callback)); + template<typename F> void add_on_initialized_callback(F &&callback) { + this->initialized_callback_.add(std::forward<F>(callback)); } protected: diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 853de719fe..ee2b006039 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -190,9 +190,7 @@ class UARTComponent { #endif // USE_ESP8266 || USE_ESP32 #ifdef USE_UART_DEBUGGER - void add_debug_callback(std::function<void(UARTDirection, uint8_t)> &&callback) { - this->debug_callback_.add(std::move(callback)); - } + template<typename F> void add_debug_callback(F &&callback) { this->debug_callback_.add(std::forward<F>(callback)); } #endif protected: diff --git a/esphome/components/udp/udp_component.h b/esphome/components/udp/udp_component.h index 7fd6308065..fb0edf2ebd 100644 --- a/esphome/components/udp/udp_component.h +++ b/esphome/components/udp/udp_component.h @@ -28,9 +28,7 @@ class UDPComponent : public Component { void set_broadcast_port(uint16_t port) { this->broadcast_port_ = port; } void set_should_broadcast() { this->should_broadcast_ = true; } void set_should_listen() { this->should_listen_ = true; } - void add_listener(std::function<void(std::span<const uint8_t>)> &&listener) { - this->packet_listeners_.add(std::move(listener)); - } + template<typename F> void add_listener(F &&listener) { this->packet_listeners_.add(std::forward<F>(listener)); } void setup() override; void loop() override; void dump_config() override; diff --git a/esphome/components/update/update_entity.h b/esphome/components/update/update_entity.h index 82eaacaf76..f7d0032f21 100644 --- a/esphome/components/update/update_entity.h +++ b/esphome/components/update/update_entity.h @@ -40,7 +40,9 @@ class UpdateEntity : public EntityBase { const UpdateInfo &update_info = update_info_; const UpdateState &state = state_; - void add_on_state_callback(std::function<void()> &&callback) { this->state_callback_.add(std::move(callback)); } + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } Trigger<const UpdateInfo &> *get_update_available_trigger() { if (!update_available_trigger_) { update_available_trigger_ = std::make_unique<Trigger<const UpdateInfo &>>(); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index 493ffd8da2..636da1f3c3 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -125,7 +125,6 @@ bool ValveCall::get_stop() const { return this->stop_; } ValveCall Valve::make_call() { return {this}; } -void Valve::add_on_state_callback(std::function<void()> &&f) { this->state_callback_.add(std::move(f)); } void Valve::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); diff --git a/esphome/components/valve/valve.h b/esphome/components/valve/valve.h index aab819a778..b4141f5ff5 100644 --- a/esphome/components/valve/valve.h +++ b/esphome/components/valve/valve.h @@ -117,7 +117,7 @@ class Valve : public EntityBase { /// Construct a new valve call used to control the valve. ValveCall make_call(); - void add_on_state_callback(std::function<void()> &&f); + template<typename F> void add_on_state_callback(F &&f) { this->state_callback_.add(std::forward<F>(f)); } /** Publish the current state of the valve. * diff --git a/esphome/components/zephyr/cdc_acm.h b/esphome/components/zephyr/cdc_acm.h index 2e9da85a11..4dc14397d8 100644 --- a/esphome/components/zephyr/cdc_acm.h +++ b/esphome/components/zephyr/cdc_acm.h @@ -11,9 +11,7 @@ class CdcAcm : public Component { public: CdcAcm(); void setup() override; - void add_on_rate_callback(std::function<void(const device *, uint32_t)> &&callback) { - this->rate_callbacks_.add(std::move(callback)); - } + template<typename F> void add_on_rate_callback(F &&callback) { this->rate_callbacks_.add(std::forward<F>(callback)); } protected: static void cdc_dte_rate_callback_(const device *device, uint32_t rate); diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index dcc2b40a16..3fa5818ec5 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -74,7 +74,7 @@ class ZigbeeComponent : public Component { // endpoints are enumerated from 1 this->callbacks_[endpoint - 1] = std::move(cb); } - void add_join_callback(std::function<void()> &&cb) { this->join_cb_.add(std::move(cb)); } + template<typename F> void add_join_callback(F &&cb) { this->join_cb_.add(std::forward<F>(cb)); } void zboss_signal_handler_esphome(zb_bufid_t bufid); void factory_reset(); Trigger<> *get_join_trigger() { return &this->join_trigger_; }; diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 4c6e5f6596..8c1f1a213e 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -307,15 +307,11 @@ template<typename T> class StatefulEntityBase : public EntityBase { virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); } void invalidate_state() { this->set_new_state({}); } - void add_full_state_callback(std::function<void(optional<T> previous, optional<T> current)> &&callback) { - if (this->full_state_callbacks_ == nullptr) - this->full_state_callbacks_ = new CallbackManager<void(optional<T> previous, optional<T> current)>(); // NOLINT - this->full_state_callbacks_->add(std::move(callback)); + template<typename F> void add_full_state_callback(F &&callback) { + this->full_state_callbacks_.add(std::forward<F>(callback)); } - void add_on_state_callback(std::function<void(T)> &&callback) { - if (this->state_callbacks_ == nullptr) - this->state_callbacks_ = new CallbackManager<void(T)>(); // NOLINT - this->state_callbacks_->add(std::move(callback)); + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callbacks_.add(std::forward<F>(callback)); } void set_trigger_on_initial_state(bool trigger_on_initial_state) { @@ -333,21 +329,19 @@ template<typename T> class StatefulEntityBase : public EntityBase { virtual bool set_new_state(const optional<T> &new_state) { if (this->state_ != new_state) { // call the full state callbacks with the previous and new state - if (this->full_state_callbacks_ != nullptr) - this->full_state_callbacks_->call(this->state_, new_state); + this->full_state_callbacks_.call(this->state_, new_state); // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or // the previous state was valid auto had_state = this->has_state(); this->state_ = new_state; - if (this->state_callbacks_ != nullptr && new_state.has_value() && (this->trigger_on_initial_state_ || had_state)) - this->state_callbacks_->call(new_state.value()); + if (new_state.has_value() && (this->trigger_on_initial_state_ || had_state)) + this->state_callbacks_.call(new_state.value()); return true; } return false; } bool trigger_on_initial_state_{true}; - // callbacks with full state and previous state - CallbackManager<void(optional<T> previous, optional<T> current)> *full_state_callbacks_{}; - CallbackManager<void(T)> *state_callbacks_{}; + LazyCallbackManager<void(optional<T> previous, optional<T> current)> full_state_callbacks_; + LazyCallbackManager<void(T)> state_callbacks_; }; } // namespace esphome diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index d220626bcf..a703b5a5f3 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1729,6 +1729,51 @@ constexpr float fahrenheit_to_celsius(float value) { return (value - 32.0f) / 1. /// @name Utilities /// @{ +/// Lightweight type-erased callback (8 bytes on 32-bit) that avoids std::function overhead. +/// No null check, no exceptions, no heap allocation for small trivially-copyable callables. +/// +/// With C++20 if constexpr, automatically detects [this] lambdas (sizeof <= sizeof(void*), +/// trivially copyable) and stores them inline. Larger callables are heap-allocated. +template<typename... X> struct Callback; + +template<typename... Ts> struct Callback<void(Ts...)> { + // The inline storage path stores callable bytes in ctx_ via memcpy. + // sizeof equality with uintptr_t ensures void* can round-trip arbitrary bit patterns, + // which combined with flat address spaces on all ESPHome targets means no trap representations. + static_assert(sizeof(void *) == sizeof(std::uintptr_t), "void* must be the same size as uintptr_t"); + + void (*fn_)(void *, Ts...){nullptr}; + void *ctx_{nullptr}; + + /// Invoke the callback. Only valid on Callbacks created via create(), never on default-constructed instances. + void call(Ts... args) const { this->fn_(this->ctx_, args...); } + + /// Create from any callable. Small trivially-copyable callables (like [this] lambdas) + /// are stored inline in the ctx pointer without heap allocation. + template<typename F> static Callback create(F &&callable) { + using DecayF = std::decay_t<F>; + if constexpr (sizeof(DecayF) <= sizeof(void *) && std::is_trivially_copyable_v<DecayF>) { + // Small trivial callable (e.g. [this]() { this->method(); }) - store inline in ctx. + // Safe under C++20 (P0593R6): byte copy into aligned storage implicitly + // creates objects of implicit-lifetime types (trivially copyable qualifies). + Callback cb; // fn and ctx are zero-initialized by default + __builtin_memcpy(&cb.ctx_, &callable, sizeof(DecayF)); + cb.fn_ = [](void *c, Ts... args) { + alignas(DecayF) char buf[sizeof(DecayF)]; + __builtin_memcpy(buf, &c, sizeof(DecayF)); + (*std::launder(reinterpret_cast<DecayF *>(buf)))(args...); + }; + return cb; + } else { + // Large or non-trivial callable - heap allocate. + // Intentionally never freed: callbacks in ESPHome are registered during setup() + // and live for device lifetime. Same lifetime as the previous std::function approach. + auto *stored = new DecayF(std::forward<F>(callable)); + return {[](void *c, Ts... args) { (*static_cast<DecayF *>(c))(args...); }, static_cast<void *>(stored)}; + } + } +}; + template<typename... X> class CallbackManager; /** Helper class to allow having multiple subscribers to a callback. @@ -1737,13 +1782,14 @@ template<typename... X> class CallbackManager; */ template<typename... Ts> class CallbackManager<void(Ts...)> { public: - /// Add a callback to the list. - void add(std::function<void(Ts...)> &&callback) { this->callbacks_.push_back(std::move(callback)); } + /// Add any callable. Small trivially-copyable callables (like [this] lambdas) + /// are stored inline without heap allocation or std::function. + template<typename F> void add(F &&callback) { this->add_(Callback<void(Ts...)>::create(std::forward<F>(callback))); } - /// Call all callbacks in this manager. + /// Call all callbacks in this manager. No null check on invoke. void call(Ts... args) { for (auto &cb : this->callbacks_) - cb(args...); + cb.call(args...); } size_t size() const { return this->callbacks_.size(); } @@ -1751,7 +1797,10 @@ template<typename... Ts> class CallbackManager<void(Ts...)> { void operator()(Ts... args) { call(args...); } protected: - std::vector<std::function<void(Ts...)>> callbacks_; + template<typename...> friend class LazyCallbackManager; + /// Non-template core to avoid code duplication per lambda type. + void add_(Callback<void(Ts...)> cb) { this->callbacks_.push_back(cb); } + std::vector<Callback<void(Ts...)>> callbacks_; }; template<typename... X> class LazyCallbackManager; @@ -1784,13 +1833,8 @@ template<typename... Ts> class LazyCallbackManager<void(Ts...)> { LazyCallbackManager(LazyCallbackManager &&) = delete; LazyCallbackManager &operator=(LazyCallbackManager &&) = delete; - /// Add a callback to the list. Allocates the underlying CallbackManager on first use. - void add(std::function<void(Ts...)> &&callback) { - if (!this->callbacks_) { - this->callbacks_ = new CallbackManager<void(Ts...)>(); - } - this->callbacks_->add(std::move(callback)); - } + /// Add any callable. Allocates the underlying CallbackManager on first use. + template<typename F> void add(F &&callback) { this->add_(Callback<void(Ts...)>::create(std::forward<F>(callback))); } /// Call all callbacks in this manager. No-op if no callbacks registered. void call(Ts... args) { @@ -1809,6 +1853,13 @@ template<typename... Ts> class LazyCallbackManager<void(Ts...)> { void operator()(Ts... args) { this->call(args...); } protected: + /// Non-template core to avoid code duplication per lambda type. + void add_(Callback<void(Ts...)> cb) { + if (!this->callbacks_) { + this->callbacks_ = new CallbackManager<void(Ts...)>(); + } + this->callbacks_->add_(cb); + } CallbackManager<void(Ts...)> *callbacks_{nullptr}; }; From 2271ac64701b5524997d2c1c7335b585a97cc939 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 18:41:45 -1000 Subject: [PATCH 1525/2030] [api] Extract overflow buffer from frame helper into APIOverflowBuffer (#14871) --- esphome/components/api/__init__.py | 5 +- esphome/components/api/api_frame_helper.cpp | 161 ++++-------------- esphome/components/api/api_frame_helper.h | 43 ++--- .../components/api/api_frame_helper_noise.cpp | 6 +- .../api/api_frame_helper_plaintext.cpp | 6 +- .../components/api/api_overflow_buffer.cpp | 73 ++++++++ esphome/components/api/api_overflow_buffer.h | 76 +++++++++ 7 files changed, 214 insertions(+), 156 deletions(-) create mode 100644 esphome/components/api/api_overflow_buffer.cpp create mode 100644 esphome/components/api/api_overflow_buffer.h diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 9772e6afca..4c3cf81927 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -301,11 +301,12 @@ CONFIG_SCHEMA = cv.All( # Maximum queued send buffers per connection before dropping connection # Each buffer uses ~8-12 bytes overhead plus actual message size # Platform defaults based on available RAM and typical message rates: + # CONF_MAX_SEND_QUEUE defaults are power of 2 for efficient modulo cv.SplitDefault( CONF_MAX_SEND_QUEUE, - esp8266=5, # Limited RAM, need to fail fast + esp8266=4, # Limited RAM, need to fail fast esp32=8, # More RAM, can buffer more - rp2040=5, # Limited RAM + rp2040=8, # Moderate RAM bk72xx=8, # Moderate RAM nrf52=8, # Moderate RAM rtl87xx=8, # Moderate RAM diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index fbee294022..6d3bd51b58 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -100,150 +100,61 @@ const LogString *api_error_to_logstr(APIError err) { return LOG_STR("UNKNOWN"); } -// Default implementation for loop - handles sending buffered data -APIError APIFrameHelper::loop() { - if (this->tx_buf_count_ > 0) { - APIError err = try_send_tx_buf_(); - if (err != APIError::OK && err != APIError::WOULD_BLOCK) { - return err; +APIError APIFrameHelper::drain_overflow_and_handle_errors_() { + if (this->overflow_buf_.try_drain(this->socket_.get()) == -1) { + int err = errno; + if (this->check_socket_write_err_(err) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", err); + return APIError::SOCKET_WRITE_FAILED; } } - return APIError::OK; // Convert WOULD_BLOCK to OK to avoid connection termination + return APIError::OK; } -// Common socket write error handling -APIError APIFrameHelper::handle_socket_write_error_() { - const int err = errno; - if (err == EWOULDBLOCK || err == EAGAIN) { - return APIError::WOULD_BLOCK; - } - HELPER_LOG("Socket write failed with errno %d", err); - this->state_ = State::FAILED; - return APIError::SOCKET_WRITE_FAILED; -} - -// Helper method to buffer data from IOVs -void APIFrameHelper::buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, - uint16_t offset) { - // Check if queue is full - if (this->tx_buf_count_ >= API_MAX_SEND_QUEUE) { - HELPER_LOG("Send queue full (%u buffers), dropping connection", this->tx_buf_count_); - this->state_ = State::FAILED; - return; - } - - uint16_t buffer_size = total_write_len - offset; - auto &buffer = this->tx_buf_[this->tx_buf_tail_]; - buffer = std::make_unique<SendBuffer>(SendBuffer{ - .data = std::make_unique<uint8_t[]>(buffer_size), - .size = buffer_size, - .offset = 0, - }); - - uint16_t to_skip = offset; - uint16_t write_pos = 0; - - for (int i = 0; i < iovcnt; i++) { - if (to_skip >= iov[i].iov_len) { - // Skip this entire segment - to_skip -= static_cast<uint16_t>(iov[i].iov_len); - } else { - // Include this segment (partially or fully) - const uint8_t *src = reinterpret_cast<uint8_t *>(iov[i].iov_base) + to_skip; - uint16_t len = static_cast<uint16_t>(iov[i].iov_len) - to_skip; - std::memcpy(buffer->data.get() + write_pos, src, len); - write_pos += len; - to_skip = 0; - } - } - - // Update circular buffer tracking - this->tx_buf_tail_ = (this->tx_buf_tail_ + 1) % API_MAX_SEND_QUEUE; - this->tx_buf_count_++; -} - -// This method writes data to socket or buffers it +// Write data to socket, overflow to backlog buffer if LWIP TCP send buffer is full. +// Returns OK if all data was sent or successfully queued. +// Returns SOCKET_WRITE_FAILED on hard error (sets state to FAILED). APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len) { - // Returns APIError::OK if successful (or would block, but data has been buffered) - // Returns APIError::SOCKET_WRITE_FAILED if socket write failed, and sets state to FAILED - - if (iovcnt == 0) - return APIError::OK; // Nothing to do, success - #ifdef HELPER_LOG_PACKETS for (int i = 0; i < iovcnt; i++) { LOG_PACKET_SENDING(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len); } #endif - // Try to send any existing buffered data first if there is any - if (this->tx_buf_count_ > 0) { - APIError send_result = try_send_tx_buf_(); - // If real error occurred (not just WOULD_BLOCK), return it - if (send_result != APIError::OK && send_result != APIError::WOULD_BLOCK) { - return send_result; - } + uint16_t skip = 0; - // If there is still data in the buffer, we can't send, buffer - // the new data and return - if (this->tx_buf_count_ > 0) { - this->buffer_data_from_iov_(iov, iovcnt, total_write_len, 0); - return APIError::OK; // Success, data buffered - } + // Drain any existing backlog first + if (!this->overflow_buf_.empty()) [[unlikely]] { + APIError err = this->drain_overflow_and_handle_errors_(); + if (err != APIError::OK) + return err; } - // Try to send directly if no buffered data - // Optimize for single iovec case (common for plaintext API) - ssize_t sent = - (iovcnt == 1) ? this->socket_->write(iov[0].iov_base, iov[0].iov_len) : this->socket_->writev(iov, iovcnt); + // If backlog is clear, try direct send + if (this->overflow_buf_.empty()) [[likely]] { + ssize_t sent = + (iovcnt == 1) ? this->socket_->write(iov[0].iov_base, iov[0].iov_len) : this->socket_->writev(iov, iovcnt); - if (sent == -1) { - APIError err = this->handle_socket_write_error_(); - if (err == APIError::WOULD_BLOCK) { - // Socket would block, buffer the data - this->buffer_data_from_iov_(iov, iovcnt, total_write_len, 0); - return APIError::OK; // Success, data buffered - } - return err; // Socket write failed - } else if (static_cast<uint16_t>(sent) < total_write_len) { - // Partially sent, buffer the remaining data - this->buffer_data_from_iov_(iov, iovcnt, total_write_len, static_cast<uint16_t>(sent)); - } - - return APIError::OK; // Success, all data sent or buffered -} - -// Common implementation for trying to send buffered data -// IMPORTANT: Caller MUST ensure tx_buf_count_ > 0 before calling this method -APIError APIFrameHelper::try_send_tx_buf_() { - // Try to send from tx_buf - we assume it's not empty as it's the caller's responsibility to check - while (this->tx_buf_count_ > 0) { - // Get the first buffer in the queue - SendBuffer *front_buffer = this->tx_buf_[this->tx_buf_head_].get(); - - // Try to send the remaining data in this buffer - ssize_t sent = this->socket_->write(front_buffer->current_data(), front_buffer->remaining()); - - if (sent == -1) { - return this->handle_socket_write_error_(); - } else if (sent == 0) { - // Nothing sent but not an error - return APIError::WOULD_BLOCK; - } else if (static_cast<uint16_t>(sent) < front_buffer->remaining()) { - // Partially sent, update offset - // Cast to ensure no overflow issues with uint16_t - front_buffer->offset += static_cast<uint16_t>(sent); - return APIError::WOULD_BLOCK; // Stop processing more buffers if we couldn't send a complete buffer + if (sent == -1) [[unlikely]] { + int err = errno; + if (this->check_socket_write_err_(err) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", err); + return APIError::SOCKET_WRITE_FAILED; + } + } else if (static_cast<uint16_t>(sent) >= total_write_len) [[likely]] { + return APIError::OK; } else { - // Buffer completely sent, remove it from the queue - this->tx_buf_[this->tx_buf_head_].reset(); - this->tx_buf_head_ = (this->tx_buf_head_ + 1) % API_MAX_SEND_QUEUE; - this->tx_buf_count_--; - // Continue loop to try sending the next buffer + skip = static_cast<uint16_t>(sent); } } - return APIError::OK; // All buffers sent successfully + // Queue unsent data into overflow buffer + if (!this->overflow_buf_.enqueue_iov(iov, iovcnt, total_write_len, skip)) { + HELPER_LOG("Overflow buffer full, dropping connection"); + this->state_ = State::FAILED; + return APIError::SOCKET_WRITE_FAILED; + } + return APIError::OK; } const char *APIFrameHelper::get_peername_to(std::span<char, socket::SOCKADDR_STR_LEN> buf) const { diff --git a/esphome/components/api/api_frame_helper.h b/esphome/components/api/api_frame_helper.h index e78c71507c..72ccf8aa56 100644 --- a/esphome/components/api/api_frame_helper.h +++ b/esphome/components/api/api_frame_helper.h @@ -9,6 +9,7 @@ #include "esphome/core/defines.h" #ifdef USE_API #include "esphome/components/api/api_buffer.h" +#include "esphome/components/api/api_overflow_buffer.h" #include "esphome/components/socket/socket.h" #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -104,9 +105,9 @@ class APIFrameHelper { } virtual ~APIFrameHelper() = default; virtual APIError init() = 0; - virtual APIError loop(); + virtual APIError loop() = 0; virtual APIError read_packet(ReadPacketBuffer *buffer) = 0; - bool can_write_without_blocking() { return this->state_ == State::DATA && this->tx_buf_count_ == 0; } + bool can_write_without_blocking() { return this->state_ == State::DATA && this->overflow_buf_.empty(); } int getpeername(struct sockaddr *addr, socklen_t *addrlen) { return socket_->getpeername(addr, addrlen); } APIError close() { if (state_ == State::CLOSED) @@ -189,28 +190,23 @@ class APIFrameHelper { } protected: - // Buffer containing data to be sent - struct SendBuffer { - std::unique_ptr<uint8_t[]> data; - uint16_t size{0}; // Total size of the buffer - uint16_t offset{0}; // Current offset within the buffer - - // Using uint16_t reduces memory usage since ESPHome API messages are limited to UINT16_MAX (65535) bytes - uint16_t remaining() const { return size - offset; } - const uint8_t *current_data() const { return data.get() + offset; } - }; + // Drain backlogged overflow data to the socket and handle errors. + // Called when overflow_buf_.empty() is false. Out-of-line to keep the + // fast path (empty check) inline at call sites. + // Returns OK for transient errors (WOULD_BLOCK), SOCKET_WRITE_FAILED for hard errors. + APIError drain_overflow_and_handle_errors_(); // Common implementation for writing raw data to socket APIError write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len); - // Try to send data from the tx buffer - APIError try_send_tx_buf_(); - - // Helper method to buffer data from IOVs - void buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len, uint16_t offset); - - // Common socket write error handling - APIError handle_socket_write_error_(); + // Check if a socket write errno is a hard error (not WOULD_BLOCK/EAGAIN). + // Returns WOULD_BLOCK for transient errors, SOCKET_WRITE_FAILED for hard errors. + APIError check_socket_write_err_(int err) { + if (err == EWOULDBLOCK || err == EAGAIN) + return APIError::WOULD_BLOCK; + this->state_ = State::FAILED; + return APIError::SOCKET_WRITE_FAILED; + } // Socket ownership (4 bytes on 32-bit, 8 bytes on 64-bit) std::unique_ptr<socket::Socket> socket_; @@ -245,8 +241,8 @@ class APIFrameHelper { return APIError::WOULD_BLOCK; } - // Containers (size varies, but typically 12+ bytes on 32-bit) - std::array<std::unique_ptr<SendBuffer>, API_MAX_SEND_QUEUE> tx_buf_; + // Backlog for unsent data when TCP send buffer is full (rarely used in production) + APIOverflowBuffer overflow_buf_; APIBuffer rx_buf_; // Client name buffer - stores name from Hello message or initial peername @@ -257,9 +253,6 @@ class APIFrameHelper { State state_{State::INITIALIZE}; uint8_t frame_header_padding_{0}; uint8_t frame_footer_size_{0}; - uint8_t tx_buf_head_{0}; - uint8_t tx_buf_tail_{0}; - uint8_t tx_buf_count_{0}; // Nagle batching counter for log messages. 0 means NODELAY is enabled (immediate send). // Values 1..LOG_NAGLE_COUNT count log messages in the current Nagle batch. // After LOG_NAGLE_COUNT logs, we flush by re-enabling NODELAY and resetting to 0. diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index b635d84f16..78e87793fc 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -153,8 +153,10 @@ APIError APINoiseFrameHelper::loop() { } } - // Use base class implementation for buffer sending - return APIFrameHelper::loop(); + if (!this->overflow_buf_.empty()) [[unlikely]] { + return this->drain_overflow_and_handle_errors_(); + } + return APIError::OK; } /** Read a packet into the rx_buf_. diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index e97b558fa3..9e669b31ee 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -64,8 +64,10 @@ APIError APIPlaintextFrameHelper::loop() { if (state_ != State::DATA) { return APIError::BAD_STATE; } - // Use base class implementation for buffer sending - return APIFrameHelper::loop(); + if (!this->overflow_buf_.empty()) [[unlikely]] { + return this->drain_overflow_and_handle_errors_(); + } + return APIError::OK; } /** Read a packet into the rx_buf_. diff --git a/esphome/components/api/api_overflow_buffer.cpp b/esphome/components/api/api_overflow_buffer.cpp new file mode 100644 index 0000000000..e242d4553e --- /dev/null +++ b/esphome/components/api/api_overflow_buffer.cpp @@ -0,0 +1,73 @@ +#include "api_overflow_buffer.h" +#ifdef USE_API +#include <cstring> + +namespace esphome::api { + +APIOverflowBuffer::~APIOverflowBuffer() { + for (auto *entry : this->queue_) { + if (entry != nullptr) + Entry::destroy(entry); + } +} + +ssize_t APIOverflowBuffer::try_drain(socket::Socket *socket) { + while (this->count_ > 0) { + Entry *front = this->queue_[this->head_]; + + ssize_t sent = socket->write(front->current_data(), front->remaining()); + + if (sent <= 0) { + // -1 = error (caller checks errno for EWOULDBLOCK vs hard error) + // 0 = nothing sent (treat as no progress) + return sent; + } + + if (static_cast<uint16_t>(sent) < front->remaining()) { + // Partially sent, update offset and stop + front->offset += static_cast<uint16_t>(sent); + return sent; + } + + // Entry fully sent — free it and advance + Entry::destroy(front); + this->queue_[this->head_] = nullptr; + this->head_ = (this->head_ + 1) % API_MAX_SEND_QUEUE; + this->count_--; + } + + return 0; // All drained +} + +bool APIOverflowBuffer::enqueue_iov(const struct iovec *iov, int iovcnt, uint16_t total_len, uint16_t skip) { + if (this->count_ >= API_MAX_SEND_QUEUE) + return false; + + uint16_t buffer_size = total_len - skip; + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) + auto *entry = new Entry{new uint8_t[buffer_size], buffer_size, 0}; + this->queue_[this->tail_] = entry; + + uint16_t to_skip = skip; + uint16_t write_pos = 0; + + for (int i = 0; i < iovcnt; i++) { + if (to_skip >= iov[i].iov_len) { + to_skip -= static_cast<uint16_t>(iov[i].iov_len); + } else { + const uint8_t *src = reinterpret_cast<uint8_t *>(iov[i].iov_base) + to_skip; + uint16_t len = static_cast<uint16_t>(iov[i].iov_len) - to_skip; + std::memcpy(entry->data + write_pos, src, len); + write_pos += len; + to_skip = 0; + } + } + + this->tail_ = (this->tail_ + 1) % API_MAX_SEND_QUEUE; + this->count_++; + return true; +} + +} // namespace esphome::api + +#endif // USE_API diff --git a/esphome/components/api/api_overflow_buffer.h b/esphome/components/api/api_overflow_buffer.h new file mode 100644 index 0000000000..19aae680f0 --- /dev/null +++ b/esphome/components/api/api_overflow_buffer.h @@ -0,0 +1,76 @@ +#pragma once +#include <array> +#include <cstdint> +#include <sys/types.h> + +#include "esphome/core/defines.h" +#ifdef USE_API + +#include "esphome/components/socket/headers.h" +#include "esphome/components/socket/socket.h" +#include "esphome/core/helpers.h" + +namespace esphome::api { + +/// Circular queue of heap-allocated byte buffers used as a TCP send backlog. +/// +/// Under normal operation this buffer is **never used** — data goes straight +/// from the frame helper to the socket. It only fills when the LWIP TCP +/// send buffer is full (slow client, congested network, heavy logging). +/// The queue drains automatically on subsequent write/loop calls once the +/// socket becomes writable again. +/// +/// Capacity is compile-time-fixed via API_MAX_SEND_QUEUE (set from Python +/// config). If the queue fills completely the connection is marked failed. +class APIOverflowBuffer { + public: + /// A single heap-allocated send-backlog entry. + /// Lifetime is manually managed — see destroy(). + struct Entry { + uint8_t *data; + uint16_t size; // Total size of the buffer + uint16_t offset; // Current send offset within the buffer + + uint16_t remaining() const { return this->size - this->offset; } + const uint8_t *current_data() const { return this->data + this->offset; } + + /// Free this entry and its data buffer. + static ESPHOME_ALWAYS_INLINE void destroy(Entry *entry) { + delete[] entry->data; + delete entry; // NOLINT(cppcoreguidelines-owning-memory) + } + }; + + ~APIOverflowBuffer(); + + /// True when no backlogged data is waiting. + bool empty() const { return this->count_ == 0; } + + /// True when the queue has no room for another entry. + bool full() const { return this->count_ >= API_MAX_SEND_QUEUE; } + + /// Number of entries currently queued. + uint8_t count() const { return this->count_; } + + /// Try to drain queued data to the socket. + /// Returns bytes-written > 0 on success/partial, 0 if all drained or no progress, + /// -1 on error (caller must check errno to distinguish EWOULDBLOCK from hard errors). + /// Callers only need to act on -1; 0 and positive values both mean "no error". + /// Frees entries as they are fully sent. + ssize_t try_drain(socket::Socket *socket); + + /// Enqueue unsent IOV data into the backlog. + /// Copies iov data starting at byte offset `skip` into a new entry. + /// Returns false if the queue is full (caller should fail the connection). + bool enqueue_iov(const struct iovec *iov, int iovcnt, uint16_t total_len, uint16_t skip); + + protected: + std::array<Entry *, API_MAX_SEND_QUEUE> queue_{}; + uint8_t head_{0}; + uint8_t tail_{0}; + uint8_t count_{0}; +}; + +} // namespace esphome::api + +#endif // USE_API From a1aff7cadf88b14e39fcda559d3f2895b0a43e8d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 18:42:05 -1000 Subject: [PATCH 1526/2030] [preferences] Devirtualize preference backend and manager classes (#14825) --- esphome/components/esp32/preference_backend.h | 27 ++ esphome/components/esp32/preferences.cpp | 306 +++++++++--------- esphome/components/esp32/preferences.h | 29 +- .../components/esp8266/preference_backend.h | 29 ++ esphome/components/esp8266/preferences.cpp | 248 +++++++------- esphome/components/esp8266/preferences.h | 24 +- esphome/components/host/preference_backend.h | 29 ++ esphome/components/host/preferences.cpp | 11 +- esphome/components/host/preferences.h | 39 +-- .../components/libretiny/preference_backend.h | 32 ++ esphome/components/libretiny/preferences.cpp | 269 +++++++-------- esphome/components/libretiny/preferences.h | 26 +- .../components/rp2040/preference_backend.h | 27 ++ esphome/components/rp2040/preferences.cpp | 189 +++++------ esphome/components/rp2040/preferences.h | 29 +- .../components/zephyr/preference_backend.h | 48 +++ esphome/components/zephyr/preferences.cpp | 233 ++++++------- esphome/components/zephyr/preferences.h | 31 +- esphome/core/preference_backend.h | 83 +++++ esphome/core/preferences.h | 75 ++--- 20 files changed, 1021 insertions(+), 763 deletions(-) create mode 100644 esphome/components/esp32/preference_backend.h create mode 100644 esphome/components/esp8266/preference_backend.h create mode 100644 esphome/components/host/preference_backend.h create mode 100644 esphome/components/libretiny/preference_backend.h create mode 100644 esphome/components/rp2040/preference_backend.h create mode 100644 esphome/components/zephyr/preference_backend.h create mode 100644 esphome/core/preference_backend.h diff --git a/esphome/components/esp32/preference_backend.h b/esphome/components/esp32/preference_backend.h new file mode 100644 index 0000000000..893bc35f0c --- /dev/null +++ b/esphome/components/esp32/preference_backend.h @@ -0,0 +1,27 @@ +#pragma once +#ifdef USE_ESP32 + +#include <cstddef> +#include <cstdint> + +namespace esphome::esp32 { + +class ESP32PreferenceBackend final { + public: + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + uint32_t key; + uint32_t nvs_handle; +}; + +class ESP32Preferences; +ESP32Preferences *get_preferences(); + +} // namespace esphome::esp32 + +namespace esphome { +using PreferenceBackend = esp32::ESP32PreferenceBackend; +} // namespace esphome + +#endif // USE_ESP32 diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index a3ef10b21f..7260bf54e0 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -1,16 +1,14 @@ #ifdef USE_ESP32 +#include "preferences.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/preferences.h" #include <nvs_flash.h> #include <cinttypes> #include <cstring> -#include <memory> #include <vector> -namespace esphome { -namespace esp32 { +namespace esphome::esp32 { static const char *const TAG = "esp32.preferences"; @@ -24,185 +22,175 @@ struct NVSData { static std::vector<NVSData> s_pending_save; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -class ESP32PreferenceBackend : public ESPPreferenceBackend { - public: - uint32_t key; - uint32_t nvs_handle; - bool save(const uint8_t *data, size_t len) override { - // try find in pending saves and update that - for (auto &obj : s_pending_save) { - if (obj.key == this->key) { - obj.data.set(data, len); - return true; - } +bool ESP32PreferenceBackend::save(const uint8_t *data, size_t len) { + // try find in pending saves and update that + for (auto &obj : s_pending_save) { + if (obj.key == this->key) { + obj.data.set(data, len); + return true; } - NVSData save{}; - save.key = this->key; - save.data.set(data, len); - s_pending_save.push_back(std::move(save)); - ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); - return true; } - bool load(uint8_t *data, size_t len) override { - // try find in pending saves and load from that - for (auto &obj : s_pending_save) { - if (obj.key == this->key) { - if (obj.data.size() != len) { - // size mismatch - return false; - } - memcpy(data, obj.data.data(), len); - return true; - } - } + NVSData save{}; + save.key = this->key; + save.data.set(data, len); + s_pending_save.push_back(std::move(save)); + ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); + return true; +} +bool ESP32PreferenceBackend::load(uint8_t *data, size_t len) { + // try find in pending saves and load from that + for (auto &obj : s_pending_save) { + if (obj.key == this->key) { + if (obj.data.size() != len) { + // size mismatch + return false; + } + memcpy(data, obj.data.data(), len); + return true; + } + } + + char key_str[KEY_BUFFER_SIZE]; + snprintf(key_str, sizeof(key_str), "%" PRIu32, this->key); + size_t actual_len; + esp_err_t err = nvs_get_blob(this->nvs_handle, key_str, nullptr, &actual_len); + if (err != 0) { + ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", key_str, esp_err_to_name(err)); + return false; + } + if (actual_len != len) { + ESP_LOGVV(TAG, "NVS length does not match (%zu!=%zu)", actual_len, len); + return false; + } + err = nvs_get_blob(this->nvs_handle, key_str, data, &len); + if (err != 0) { + ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); + return false; + } else { + ESP_LOGVV(TAG, "nvs_get_blob: key: %s, len: %zu", key_str, len); + } + return true; +} + +void ESP32Preferences::open() { + nvs_flash_init(); + esp_err_t err = nvs_open("esphome", NVS_READWRITE, &this->nvs_handle); + if (err == 0) + return; + + ESP_LOGW(TAG, "nvs_open failed: %s - erasing NVS", esp_err_to_name(err)); + nvs_flash_deinit(); + nvs_flash_erase(); + nvs_flash_init(); + + err = nvs_open("esphome", NVS_READWRITE, &this->nvs_handle); + if (err != 0) { + this->nvs_handle = 0; + } +} + +ESPPreferenceObject ESP32Preferences::make_preference(size_t length, uint32_t type) { + auto *pref = new ESP32PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) + pref->nvs_handle = this->nvs_handle; + pref->key = type; + + return ESPPreferenceObject(pref); +} + +bool ESP32Preferences::sync() { + if (s_pending_save.empty()) + return true; + + ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); + int cached = 0, written = 0, failed = 0; + esp_err_t last_err = ESP_OK; + uint32_t last_key = 0; + + for (const auto &save : s_pending_save) { char key_str[KEY_BUFFER_SIZE]; - snprintf(key_str, sizeof(key_str), "%" PRIu32, this->key); - size_t actual_len; - esp_err_t err = nvs_get_blob(this->nvs_handle, key_str, nullptr, &actual_len); - if (err != 0) { - ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", key_str, esp_err_to_name(err)); - return false; - } - if (actual_len != len) { - ESP_LOGVV(TAG, "NVS length does not match (%zu!=%zu)", actual_len, len); - return false; - } - err = nvs_get_blob(this->nvs_handle, key_str, data, &len); - if (err != 0) { - ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); - return false; - } else { - ESP_LOGVV(TAG, "nvs_get_blob: key: %s, len: %zu", key_str, len); - } - return true; - } -}; - -class ESP32Preferences : public ESPPreferences { - public: - uint32_t nvs_handle; - - void open() { - nvs_flash_init(); - esp_err_t err = nvs_open("esphome", NVS_READWRITE, &nvs_handle); - if (err == 0) - return; - - ESP_LOGW(TAG, "nvs_open failed: %s - erasing NVS", esp_err_to_name(err)); - nvs_flash_deinit(); - nvs_flash_erase(); - nvs_flash_init(); - - err = nvs_open("esphome", NVS_READWRITE, &nvs_handle); - if (err != 0) { - nvs_handle = 0; - } - } - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { - return this->make_preference(length, type); - } - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { - auto *pref = new ESP32PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) - pref->nvs_handle = this->nvs_handle; - pref->key = type; - - return ESPPreferenceObject(pref); - } - - bool sync() override { - if (s_pending_save.empty()) - return true; - - ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); - int cached = 0, written = 0, failed = 0; - esp_err_t last_err = ESP_OK; - uint32_t last_key = 0; - - for (const auto &save : s_pending_save) { - char key_str[KEY_BUFFER_SIZE]; - snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); - ESP_LOGVV(TAG, "Checking if NVS data %s has changed", key_str); - if (this->is_changed_(this->nvs_handle, save, key_str)) { - esp_err_t err = nvs_set_blob(this->nvs_handle, key_str, save.data.data(), save.data.size()); - ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); - if (err != 0) { - ESP_LOGV(TAG, "nvs_set_blob('%s', len=%zu) failed: %s", key_str, save.data.size(), esp_err_to_name(err)); - failed++; - last_err = err; - last_key = save.key; - continue; - } - written++; - } else { - ESP_LOGV(TAG, "NVS data not changed skipping %" PRIu32 " len=%zu", save.key, save.data.size()); - cached++; + snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); + ESP_LOGVV(TAG, "Checking if NVS data %s has changed", key_str); + if (this->is_changed_(this->nvs_handle, save, key_str)) { + esp_err_t err = nvs_set_blob(this->nvs_handle, key_str, save.data.data(), save.data.size()); + ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); + if (err != 0) { + ESP_LOGV(TAG, "nvs_set_blob('%s', len=%zu) failed: %s", key_str, save.data.size(), esp_err_to_name(err)); + failed++; + last_err = err; + last_key = save.key; + continue; } + written++; + } else { + ESP_LOGV(TAG, "NVS data not changed skipping %" PRIu32 " len=%zu", save.key, save.data.size()); + cached++; } - s_pending_save.clear(); + } + s_pending_save.clear(); - ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, - failed); - if (failed > 0) { - ESP_LOGE(TAG, "Writing %d items failed. Last error=%s for key=%" PRIu32, failed, esp_err_to_name(last_err), - last_key); - } - - // note: commit on esp-idf currently is a no-op, nvs_set_blob always writes - esp_err_t err = nvs_commit(this->nvs_handle); - if (err != 0) { - ESP_LOGV(TAG, "nvs_commit() failed: %s", esp_err_to_name(err)); - return false; - } - - return failed == 0; + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); + if (failed > 0) { + ESP_LOGE(TAG, "Writing %d items failed. Last error=%s for key=%" PRIu32, failed, esp_err_to_name(last_err), + last_key); } - protected: - bool is_changed_(uint32_t nvs_handle, const NVSData &to_save, const char *key_str) { - size_t actual_len; - esp_err_t err = nvs_get_blob(nvs_handle, key_str, nullptr, &actual_len); - if (err != 0) { - ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", key_str, esp_err_to_name(err)); - return true; - } - // Check size first before allocating memory - if (actual_len != to_save.data.size()) { - return true; - } - // Most preferences are small, use stack buffer with heap fallback for large ones - SmallBufferWithHeapFallback<256> stored_data(actual_len); - err = nvs_get_blob(nvs_handle, key_str, stored_data.get(), &actual_len); - if (err != 0) { - ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); - return true; - } - return memcmp(to_save.data.data(), stored_data.get(), to_save.data.size()) != 0; + // note: commit on esp-idf currently is a no-op, nvs_set_blob always writes + esp_err_t err = nvs_commit(this->nvs_handle); + if (err != 0) { + ESP_LOGV(TAG, "nvs_commit() failed: %s", esp_err_to_name(err)); + return false; } - bool reset() override { - ESP_LOGD(TAG, "Erasing storage"); - s_pending_save.clear(); + return failed == 0; +} - nvs_flash_deinit(); - nvs_flash_erase(); - // Make the handle invalid to prevent any saves until restart - nvs_handle = 0; +bool ESP32Preferences::is_changed_(uint32_t nvs_handle, const NVSData &to_save, const char *key_str) { + size_t actual_len; + esp_err_t err = nvs_get_blob(nvs_handle, key_str, nullptr, &actual_len); + if (err != 0) { + ESP_LOGV(TAG, "nvs_get_blob('%s'): %s - the key might not be set yet", key_str, esp_err_to_name(err)); return true; } -}; + // Check size first before allocating memory + if (actual_len != to_save.data.size()) { + return true; + } + // Most preferences are small, use stack buffer with heap fallback for large ones + SmallBufferWithHeapFallback<256> stored_data(actual_len); + err = nvs_get_blob(nvs_handle, key_str, stored_data.get(), &actual_len); + if (err != 0) { + ESP_LOGV(TAG, "nvs_get_blob('%s') failed: %s", key_str, esp_err_to_name(err)); + return true; + } + return memcmp(to_save.data.data(), stored_data.get(), to_save.data.size()) != 0; +} + +bool ESP32Preferences::reset() { + ESP_LOGD(TAG, "Erasing storage"); + s_pending_save.clear(); + + nvs_flash_deinit(); + nvs_flash_erase(); + // Make the handle invalid to prevent any saves until restart + this->nvs_handle = 0; + return true; +} static ESP32Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +ESP32Preferences *get_preferences() { return &s_preferences; } + void setup_preferences() { s_preferences.open(); global_preferences = &s_preferences; } -} // namespace esp32 +} // namespace esphome::esp32 +namespace esphome { ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome #endif // USE_ESP32 diff --git a/esphome/components/esp32/preferences.h b/esphome/components/esp32/preferences.h index e44213e4cf..0e187d87a9 100644 --- a/esphome/components/esp32/preferences.h +++ b/esphome/components/esp32/preferences.h @@ -1,12 +1,33 @@ #pragma once #ifdef USE_ESP32 -namespace esphome { -namespace esp32 { +#include "esphome/core/preference_backend.h" + +namespace esphome::esp32 { + +struct NVSData; + +class ESP32Preferences final : public PreferencesMixin<ESP32Preferences> { + public: + using PreferencesMixin<ESP32Preferences>::make_preference; + void open(); + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) { + return this->make_preference(length, type); + } + ESPPreferenceObject make_preference(size_t length, uint32_t type); + bool sync(); + bool reset(); + + uint32_t nvs_handle; + + protected: + bool is_changed_(uint32_t nvs_handle, const NVSData &to_save, const char *key_str); +}; void setup_preferences(); -} // namespace esp32 -} // namespace esphome +} // namespace esphome::esp32 + +DECLARE_PREFERENCE_ALIASES(esphome::esp32::ESP32Preferences) #endif // USE_ESP32 diff --git a/esphome/components/esp8266/preference_backend.h b/esphome/components/esp8266/preference_backend.h new file mode 100644 index 0000000000..f9da8ff165 --- /dev/null +++ b/esphome/components/esp8266/preference_backend.h @@ -0,0 +1,29 @@ +#pragma once +#ifdef USE_ESP8266 + +#include <cstddef> +#include <cstdint> + +namespace esphome::esp8266 { + +class ESP8266PreferenceBackend final { + public: + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + uint32_t type = 0; + uint16_t offset = 0; + uint8_t length_words = 0; // Max 255 words (1020 bytes of data) + bool in_flash = false; +}; + +class ESP8266Preferences; +ESP8266Preferences *get_preferences(); + +} // namespace esphome::esp8266 + +namespace esphome { +using PreferenceBackend = esp8266::ESP8266PreferenceBackend; +} // namespace esphome + +#endif // USE_ESP8266 diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index e749b1f633..0b31c53ff8 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -5,11 +5,9 @@ extern "C" { #include "spi_flash.h" } -#include "esphome/core/defines.h" +#include "preferences.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/preferences.h" -#include "preferences.h" #include <cstring> @@ -137,155 +135,135 @@ static bool load_from_rtc(size_t offset, uint32_t *data, size_t len) { static constexpr size_t PREF_MAX_BUFFER_WORDS = ESP8266_FLASH_STORAGE_SIZE > RTC_NORMAL_REGION_WORDS ? ESP8266_FLASH_STORAGE_SIZE : RTC_NORMAL_REGION_WORDS; -class ESP8266PreferenceBackend : public ESPPreferenceBackend { - public: - uint32_t type = 0; - uint16_t offset = 0; - uint8_t length_words = 0; // Max 255 words (1020 bytes of data) - bool in_flash = false; +bool ESP8266PreferenceBackend::save(const uint8_t *data, size_t len) { + if (bytes_to_words(len) != this->length_words) + return false; + const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; + if (buffer_size > PREF_MAX_BUFFER_WORDS) + return false; + uint32_t buffer[PREF_MAX_BUFFER_WORDS]; + memset(buffer, 0, buffer_size * sizeof(uint32_t)); + memcpy(buffer, data, len); + buffer[this->length_words] = calculate_crc(buffer, buffer + this->length_words, this->type); + return this->in_flash ? save_to_flash(this->offset, buffer, buffer_size) + : save_to_rtc(this->offset, buffer, buffer_size); +} - bool save(const uint8_t *data, size_t len) override { - if (bytes_to_words(len) != this->length_words) - return false; - const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; - if (buffer_size > PREF_MAX_BUFFER_WORDS) - return false; - uint32_t buffer[PREF_MAX_BUFFER_WORDS]; - memset(buffer, 0, buffer_size * sizeof(uint32_t)); - memcpy(buffer, data, len); - buffer[this->length_words] = calculate_crc(buffer, buffer + this->length_words, this->type); - return this->in_flash ? save_to_flash(this->offset, buffer, buffer_size) - : save_to_rtc(this->offset, buffer, buffer_size); +bool ESP8266PreferenceBackend::load(uint8_t *data, size_t len) { + if (bytes_to_words(len) != this->length_words) + return false; + const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; + if (buffer_size > PREF_MAX_BUFFER_WORDS) + return false; + uint32_t buffer[PREF_MAX_BUFFER_WORDS]; + bool ret = this->in_flash ? load_from_flash(this->offset, buffer, buffer_size) + : load_from_rtc(this->offset, buffer, buffer_size); + if (!ret) + return false; + if (buffer[this->length_words] != calculate_crc(buffer, buffer + this->length_words, this->type)) + return false; + memcpy(data, buffer, len); + return true; +} + +void ESP8266Preferences::setup() { + ESP_LOGVV(TAG, "Loading preferences from flash"); + + { + InterruptLock lock; + spi_flash_read(get_esp8266_flash_address(), s_flash_storage, ESP8266_FLASH_STORAGE_SIZE * 4); + } +} + +ESPPreferenceObject ESP8266Preferences::make_preference(size_t length, uint32_t type, bool in_flash) { + const uint32_t length_words = bytes_to_words(length); + if (length_words > MAX_PREFERENCE_WORDS) { + ESP_LOGE(TAG, "Preference too large: %u words", static_cast<unsigned int>(length_words)); + return {}; } - bool load(uint8_t *data, size_t len) override { - if (bytes_to_words(len) != this->length_words) - return false; - const size_t buffer_size = static_cast<size_t>(this->length_words) + 1; - if (buffer_size > PREF_MAX_BUFFER_WORDS) - return false; - uint32_t buffer[PREF_MAX_BUFFER_WORDS]; - bool ret = this->in_flash ? load_from_flash(this->offset, buffer, buffer_size) - : load_from_rtc(this->offset, buffer, buffer_size); - if (!ret) - return false; - if (buffer[this->length_words] != calculate_crc(buffer, buffer + this->length_words, this->type)) - return false; - memcpy(data, buffer, len); - return true; - } -}; + const uint32_t total_words = length_words + 1; // +1 for CRC + uint16_t offset; -class ESP8266Preferences : public ESPPreferences { - public: - uint32_t current_offset = 0; - uint32_t current_flash_offset = 0; // in words - - void setup() { - ESP_LOGVV(TAG, "Loading preferences from flash"); - - { - InterruptLock lock; - spi_flash_read(get_esp8266_flash_address(), s_flash_storage, ESP8266_FLASH_STORAGE_SIZE * 4); - } - } - - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { - const uint32_t length_words = bytes_to_words(length); - if (length_words > MAX_PREFERENCE_WORDS) { - ESP_LOGE(TAG, "Preference too large: %u words", static_cast<unsigned int>(length_words)); + if (in_flash) { + if (this->current_flash_offset + total_words > ESP8266_FLASH_STORAGE_SIZE) return {}; + offset = static_cast<uint16_t>(this->current_flash_offset); + this->current_flash_offset += total_words; + } else { + uint32_t start = this->current_offset; + bool in_normal = start < RTC_NORMAL_REGION_WORDS; + // Normal: offset 0-95 maps to RTC offset 32-127 + // Eboot: offset 96-127 maps to RTC offset 0-31 + if (in_normal && start + total_words > RTC_NORMAL_REGION_WORDS) { + // start is in normal but end is not -> switch to Eboot + this->current_offset = start = RTC_NORMAL_REGION_WORDS; + in_normal = false; } - - const uint32_t total_words = length_words + 1; // +1 for CRC - uint16_t offset; - - if (in_flash) { - if (this->current_flash_offset + total_words > ESP8266_FLASH_STORAGE_SIZE) - return {}; - offset = static_cast<uint16_t>(this->current_flash_offset); - this->current_flash_offset += total_words; - } else { - uint32_t start = this->current_offset; - bool in_normal = start < RTC_NORMAL_REGION_WORDS; - // Normal: offset 0-95 maps to RTC offset 32-127 - // Eboot: offset 96-127 maps to RTC offset 0-31 - if (in_normal && start + total_words > RTC_NORMAL_REGION_WORDS) { - // start is in normal but end is not -> switch to Eboot - this->current_offset = start = RTC_NORMAL_REGION_WORDS; - in_normal = false; - } - if (start + total_words > PREF_TOTAL_WORDS) - return {}; // Doesn't fit in RTC memory - // Convert preference offset to RTC memory offset - offset = static_cast<uint16_t>(in_normal ? start + RTC_EBOOT_REGION_WORDS : start - RTC_NORMAL_REGION_WORDS); - this->current_offset = start + total_words; - } - - auto *pref = new ESP8266PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) - pref->offset = offset; - pref->type = type; - pref->length_words = static_cast<uint8_t>(length_words); - pref->in_flash = in_flash; - return pref; + if (start + total_words > PREF_TOTAL_WORDS) + return {}; // Doesn't fit in RTC memory + // Convert preference offset to RTC memory offset + offset = static_cast<uint16_t>(in_normal ? start + RTC_EBOOT_REGION_WORDS : start - RTC_NORMAL_REGION_WORDS); + this->current_offset = start + total_words; } - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { -#ifdef USE_ESP8266_PREFERENCES_FLASH - return make_preference(length, type, true); -#else - return make_preference(length, type, false); -#endif - } + auto *pref = new ESP8266PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) + pref->offset = offset; + pref->type = type; + pref->length_words = static_cast<uint8_t>(length_words); + pref->in_flash = in_flash; + return ESPPreferenceObject(pref); +} - bool sync() override { - if (!s_flash_dirty) - return true; - if (s_prevent_write) - return false; - - ESP_LOGD(TAG, "Saving"); - SpiFlashOpResult erase_res, write_res = SPI_FLASH_RESULT_OK; - { - InterruptLock lock; - erase_res = spi_flash_erase_sector(get_esp8266_flash_sector()); - if (erase_res == SPI_FLASH_RESULT_OK) { - write_res = spi_flash_write(get_esp8266_flash_address(), s_flash_storage, ESP8266_FLASH_STORAGE_SIZE * 4); - } - } - if (erase_res != SPI_FLASH_RESULT_OK) { - ESP_LOGE(TAG, "Erasing failed"); - return false; - } - if (write_res != SPI_FLASH_RESULT_OK) { - ESP_LOGE(TAG, "Writing failed"); - return false; - } - - s_flash_dirty = false; +bool ESP8266Preferences::sync() { + if (!s_flash_dirty) return true; + if (s_prevent_write) + return false; + + ESP_LOGD(TAG, "Saving"); + SpiFlashOpResult erase_res, write_res = SPI_FLASH_RESULT_OK; + { + InterruptLock lock; + erase_res = spi_flash_erase_sector(get_esp8266_flash_sector()); + if (erase_res == SPI_FLASH_RESULT_OK) { + write_res = spi_flash_write(get_esp8266_flash_address(), s_flash_storage, ESP8266_FLASH_STORAGE_SIZE * 4); + } + } + if (erase_res != SPI_FLASH_RESULT_OK) { + ESP_LOGE(TAG, "Erasing failed"); + return false; + } + if (write_res != SPI_FLASH_RESULT_OK) { + ESP_LOGE(TAG, "Writing failed"); + return false; } - bool reset() override { - ESP_LOGD(TAG, "Erasing storage"); - SpiFlashOpResult erase_res; - { - InterruptLock lock; - erase_res = spi_flash_erase_sector(get_esp8266_flash_sector()); - } - if (erase_res != SPI_FLASH_RESULT_OK) { - ESP_LOGE(TAG, "Erasing failed"); - return false; - } + s_flash_dirty = false; + return true; +} - // Protect flash from writing till restart - s_prevent_write = true; - return true; +bool ESP8266Preferences::reset() { + ESP_LOGD(TAG, "Erasing storage"); + SpiFlashOpResult erase_res; + { + InterruptLock lock; + erase_res = spi_flash_erase_sector(get_esp8266_flash_sector()); } -}; + if (erase_res != SPI_FLASH_RESULT_OK) { + ESP_LOGE(TAG, "Erasing failed"); + return false; + } + + // Protect flash from writing till restart + s_prevent_write = true; + return true; +} static ESP8266Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +ESP8266Preferences *get_preferences() { return &s_preferences; } + void setup_preferences() { s_preferences.setup(); global_preferences = &s_preferences; diff --git a/esphome/components/esp8266/preferences.h b/esphome/components/esp8266/preferences.h index 16cf80a129..43557d5ec5 100644 --- a/esphome/components/esp8266/preferences.h +++ b/esphome/components/esp8266/preferences.h @@ -1,12 +1,34 @@ #pragma once - #ifdef USE_ESP8266 +#include "esphome/core/preference_backend.h" + namespace esphome::esp8266 { +class ESP8266Preferences final : public PreferencesMixin<ESP8266Preferences> { + public: + using PreferencesMixin<ESP8266Preferences>::make_preference; + void setup(); + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash); + ESPPreferenceObject make_preference(size_t length, uint32_t type) { +#ifdef USE_ESP8266_PREFERENCES_FLASH + return this->make_preference(length, type, true); +#else + return this->make_preference(length, type, false); +#endif + } + bool sync(); + bool reset(); + + uint32_t current_offset = 0; + uint32_t current_flash_offset = 0; // in words +}; + void setup_preferences(); void preferences_prevent_write(bool prevent); } // namespace esphome::esp8266 +DECLARE_PREFERENCE_ALIASES(esphome::esp8266::ESP8266Preferences) + #endif // USE_ESP8266 diff --git a/esphome/components/host/preference_backend.h b/esphome/components/host/preference_backend.h new file mode 100644 index 0000000000..68537cad28 --- /dev/null +++ b/esphome/components/host/preference_backend.h @@ -0,0 +1,29 @@ +#pragma once +#ifdef USE_HOST + +#include <cstddef> +#include <cstdint> + +namespace esphome::host { + +class HostPreferenceBackend final { + public: + explicit HostPreferenceBackend(uint32_t key) : key_(key) {} + + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + protected: + uint32_t key_{}; +}; + +class HostPreferences; +HostPreferences *get_preferences(); + +} // namespace esphome::host + +namespace esphome { +using PreferenceBackend = host::HostPreferenceBackend; +} // namespace esphome + +#endif // USE_HOST diff --git a/esphome/components/host/preferences.cpp b/esphome/components/host/preferences.cpp index 275c202e3e..fce3d62dda 100644 --- a/esphome/components/host/preferences.cpp +++ b/esphome/components/host/preferences.cpp @@ -6,8 +6,7 @@ #include "esphome/core/application.h" #include "esphome/core/log.h" -namespace esphome { -namespace host { +namespace esphome::host { namespace fs = std::filesystem; static const char *const TAG = "host.preferences"; @@ -77,6 +76,8 @@ ESPPreferenceObject HostPreferences::make_preference(size_t length, uint32_t typ static HostPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +HostPreferences *get_preferences() { return &s_preferences; } + void setup_preferences() { host_preferences = &s_preferences; global_preferences = &s_preferences; @@ -88,9 +89,11 @@ bool HostPreferenceBackend::save(const uint8_t *data, size_t len) { bool HostPreferenceBackend::load(uint8_t *data, size_t len) { return host_preferences->load(this->key_, data, len); } -HostPreferences *host_preferences; -} // namespace host +HostPreferences *host_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +} // namespace esphome::host + +namespace esphome { ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) } // namespace esphome diff --git a/esphome/components/host/preferences.h b/esphome/components/host/preferences.h index 6b2e7eb8f9..25858799ff 100644 --- a/esphome/components/host/preferences.h +++ b/esphome/components/host/preferences.h @@ -1,33 +1,22 @@ #pragma once - #ifdef USE_HOST -#include "esphome/core/preferences.h" +#include "esphome/core/preference_backend.h" +#include <cstring> #include <map> +#include <string> +#include <vector> -namespace esphome { -namespace host { +namespace esphome::host { -class HostPreferenceBackend : public ESPPreferenceBackend { +class HostPreferences final : public PreferencesMixin<HostPreferences> { public: - explicit HostPreferenceBackend(uint32_t key) { this->key_ = key; } + using PreferencesMixin<HostPreferences>::make_preference; + bool sync(); + bool reset(); - bool save(const uint8_t *data, size_t len) override; - bool load(uint8_t *data, size_t len) override; - - protected: - uint32_t key_{}; -}; - -class HostPreferences : public ESPPreferences { - public: - bool sync() override; - bool reset() override; - - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override; - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { - return make_preference(length, type, false); - } + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash); + ESPPreferenceObject make_preference(size_t length, uint32_t type) { return make_preference(length, type, false); } bool save(uint32_t key, const uint8_t *data, size_t len) { if (len > 255) @@ -58,10 +47,12 @@ class HostPreferences : public ESPPreferences { std::string filename_{}; std::map<uint32_t, std::vector<uint8_t>> data{}; }; + void setup_preferences(); extern HostPreferences *host_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -} // namespace host -} // namespace esphome +} // namespace esphome::host + +DECLARE_PREFERENCE_ALIASES(esphome::host::HostPreferences) #endif // USE_HOST diff --git a/esphome/components/libretiny/preference_backend.h b/esphome/components/libretiny/preference_backend.h new file mode 100644 index 0000000000..66b6847bee --- /dev/null +++ b/esphome/components/libretiny/preference_backend.h @@ -0,0 +1,32 @@ +#pragma once +#ifdef USE_LIBRETINY + +#include <cstddef> +#include <cstdint> + +// Forward declare FlashDB types to avoid pulling in flashdb.h +struct fdb_kvdb; +struct fdb_blob; + +namespace esphome::libretiny { + +class LibreTinyPreferenceBackend final { + public: + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + uint32_t key; + struct fdb_kvdb *db; + struct fdb_blob *blob; +}; + +class LibreTinyPreferences; +LibreTinyPreferences *get_preferences(); + +} // namespace esphome::libretiny + +namespace esphome { +using PreferenceBackend = libretiny::LibreTinyPreferenceBackend; +} // namespace esphome + +#endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 1c101136e1..f22c12f1fb 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -1,12 +1,11 @@ #ifdef USE_LIBRETINY +#include "preferences.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/preferences.h" -#include <flashdb.h> #include <cinttypes> #include <cstring> -#include <memory> +#include <vector> namespace esphome::libretiny { @@ -22,163 +21,147 @@ struct NVSData { static std::vector<NVSData> s_pending_save; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -class LibreTinyPreferenceBackend : public ESPPreferenceBackend { - public: - uint32_t key; - fdb_kvdb_t db; - fdb_blob_t blob; +bool LibreTinyPreferenceBackend::save(const uint8_t *data, size_t len) { + // try find in pending saves and update that + for (auto &obj : s_pending_save) { + if (obj.key == this->key) { + obj.data.set(data, len); + return true; + } + } + NVSData save{}; + save.key = this->key; + save.data.set(data, len); + s_pending_save.push_back(std::move(save)); + ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); + return true; +} - bool save(const uint8_t *data, size_t len) override { - // try find in pending saves and update that - for (auto &obj : s_pending_save) { - if (obj.key == this->key) { - obj.data.set(data, len); - return true; +bool LibreTinyPreferenceBackend::load(uint8_t *data, size_t len) { + // try find in pending saves and load from that + for (auto &obj : s_pending_save) { + if (obj.key == this->key) { + if (obj.data.size() != len) { + // size mismatch + return false; } + memcpy(data, obj.data.data(), len); + return true; } - NVSData save{}; - save.key = this->key; - save.data.set(data, len); - s_pending_save.push_back(std::move(save)); - ESP_LOGVV(TAG, "s_pending_save: key: %" PRIu32 ", len: %zu", this->key, len); - return true; } - bool load(uint8_t *data, size_t len) override { - // try find in pending saves and load from that - for (auto &obj : s_pending_save) { - if (obj.key == this->key) { - if (obj.data.size() != len) { - // size mismatch - return false; - } - memcpy(data, obj.data.data(), len); - return true; - } - } + char key_str[KEY_BUFFER_SIZE]; + snprintf(key_str, sizeof(key_str), "%" PRIu32, this->key); + fdb_blob_make(this->blob, data, len); + size_t actual_len = fdb_kv_get_blob(this->db, key_str, this->blob); + if (actual_len != len) { + ESP_LOGVV(TAG, "NVS length does not match (%zu!=%zu)", actual_len, len); + return false; + } else { + ESP_LOGVV(TAG, "fdb_kv_get_blob: key: %s, len: %zu", key_str, len); + } + return true; +} +void LibreTinyPreferences::open() { + // + fdb_err_t err = fdb_kvdb_init(&this->db, "esphome", "kvs", NULL, NULL); + if (err != FDB_NO_ERR) { + LT_E("fdb_kvdb_init(...) failed: %d", err); + } else { + LT_I("Preferences initialized"); + } +} + +ESPPreferenceObject LibreTinyPreferences::make_preference(size_t length, uint32_t type) { + auto *pref = new LibreTinyPreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) + pref->db = &this->db; + pref->blob = &this->blob; + pref->key = type; + + return ESPPreferenceObject(pref); +} + +bool LibreTinyPreferences::sync() { + if (s_pending_save.empty()) + return true; + + ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); + int cached = 0, written = 0, failed = 0; + fdb_err_t last_err = FDB_NO_ERR; + uint32_t last_key = 0; + + for (const auto &save : s_pending_save) { char key_str[KEY_BUFFER_SIZE]; - snprintf(key_str, sizeof(key_str), "%" PRIu32, this->key); - fdb_blob_make(this->blob, data, len); - size_t actual_len = fdb_kv_get_blob(this->db, key_str, this->blob); - if (actual_len != len) { - ESP_LOGVV(TAG, "NVS length does not match (%zu!=%zu)", actual_len, len); - return false; - } else { - ESP_LOGVV(TAG, "fdb_kv_get_blob: key: %s, len: %zu", key_str, len); - } - return true; - } -}; - -class LibreTinyPreferences : public ESPPreferences { - public: - struct fdb_kvdb db; - struct fdb_blob blob; - - void open() { - // - fdb_err_t err = fdb_kvdb_init(&db, "esphome", "kvs", NULL, NULL); - if (err != FDB_NO_ERR) { - LT_E("fdb_kvdb_init(...) failed: %d", err); - } else { - LT_I("Preferences initialized"); - } - } - - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { - return this->make_preference(length, type); - } - - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { - auto *pref = new LibreTinyPreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) - pref->db = &this->db; - pref->blob = &this->blob; - pref->key = type; - - return ESPPreferenceObject(pref); - } - - bool sync() override { - if (s_pending_save.empty()) - return true; - - ESP_LOGV(TAG, "Saving %zu items...", s_pending_save.size()); - int cached = 0, written = 0, failed = 0; - fdb_err_t last_err = FDB_NO_ERR; - uint32_t last_key = 0; - - for (const auto &save : s_pending_save) { - char key_str[KEY_BUFFER_SIZE]; - snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); - ESP_LOGVV(TAG, "Checking if FDB data %s has changed", key_str); - if (this->is_changed_(&this->db, save, key_str)) { - ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); - fdb_blob_make(&this->blob, save.data.data(), save.data.size()); - fdb_err_t err = fdb_kv_set_blob(&this->db, key_str, &this->blob); - if (err != FDB_NO_ERR) { - ESP_LOGV(TAG, "fdb_kv_set_blob('%s', len=%zu) failed: %d", key_str, save.data.size(), err); - failed++; - last_err = err; - last_key = save.key; - continue; - } - written++; - } else { - ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.data.size()); - cached++; + snprintf(key_str, sizeof(key_str), "%" PRIu32, save.key); + ESP_LOGVV(TAG, "Checking if FDB data %s has changed", key_str); + if (this->is_changed_(&this->db, save, key_str)) { + ESP_LOGV(TAG, "sync: key: %s, len: %zu", key_str, save.data.size()); + fdb_blob_make(&this->blob, save.data.data(), save.data.size()); + fdb_err_t err = fdb_kv_set_blob(&this->db, key_str, &this->blob); + if (err != FDB_NO_ERR) { + ESP_LOGV(TAG, "fdb_kv_set_blob('%s', len=%zu) failed: %d", key_str, save.data.size(), err); + failed++; + last_err = err; + last_key = save.key; + continue; } + written++; + } else { + ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.data.size()); + cached++; } - s_pending_save.clear(); + } + s_pending_save.clear(); - ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, - failed); - if (failed > 0) { - ESP_LOGE(TAG, "Writing %d items failed. Last error=%d for key=%" PRIu32, failed, last_err, last_key); - } - - return failed == 0; + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); + if (failed > 0) { + ESP_LOGE(TAG, "Writing %d items failed. Last error=%d for key=%" PRIu32, failed, last_err, last_key); } - protected: - bool is_changed_(fdb_kvdb_t db, const NVSData &to_save, const char *key_str) { - struct fdb_kv kv; - fdb_kv_t kvp = fdb_kv_get_obj(db, key_str, &kv); - if (kvp == nullptr) { - ESP_LOGV(TAG, "fdb_kv_get_obj('%s'): nullptr - the key might not be set yet", key_str); - return true; - } + return failed == 0; +} - // Check size first - if different, data has changed - if (kv.value_len != to_save.data.size()) { - return true; - } - - // Most preferences are small, use stack buffer with heap fallback for large ones - SmallBufferWithHeapFallback<256> stored_data(kv.value_len); - fdb_blob_make(&this->blob, stored_data.get(), kv.value_len); - size_t actual_len = fdb_kv_get_blob(db, key_str, &this->blob); - if (actual_len != kv.value_len) { - ESP_LOGV(TAG, "fdb_kv_get_blob('%s') len mismatch: %u != %u", key_str, actual_len, kv.value_len); - return true; - } - - // Compare the actual data - return memcmp(to_save.data.data(), stored_data.get(), kv.value_len) != 0; - } - - bool reset() override { - ESP_LOGD(TAG, "Erasing storage"); - s_pending_save.clear(); - - fdb_kv_set_default(&db); - fdb_kvdb_deinit(&db); +bool LibreTinyPreferences::is_changed_(fdb_kvdb_t db, const NVSData &to_save, const char *key_str) { + struct fdb_kv kv; + fdb_kv_t kvp = fdb_kv_get_obj(db, key_str, &kv); + if (kvp == nullptr) { + ESP_LOGV(TAG, "fdb_kv_get_obj('%s'): nullptr - the key might not be set yet", key_str); return true; } -}; + + // Check size first - if different, data has changed + if (kv.value_len != to_save.data.size()) { + return true; + } + + // Most preferences are small, use stack buffer with heap fallback for large ones + SmallBufferWithHeapFallback<256> stored_data(kv.value_len); + fdb_blob_make(&this->blob, stored_data.get(), kv.value_len); + size_t actual_len = fdb_kv_get_blob(db, key_str, &this->blob); + if (actual_len != kv.value_len) { + ESP_LOGV(TAG, "fdb_kv_get_blob('%s') len mismatch: %zu != %zu", key_str, actual_len, (size_t) kv.value_len); + return true; + } + + // Compare the actual data + return memcmp(to_save.data.data(), stored_data.get(), kv.value_len) != 0; +} + +bool LibreTinyPreferences::reset() { + ESP_LOGD(TAG, "Erasing storage"); + s_pending_save.clear(); + + fdb_kv_set_default(&this->db); + fdb_kvdb_deinit(&this->db); + return true; +} static LibreTinyPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +LibreTinyPreferences *get_preferences() { return &s_preferences; } + void setup_preferences() { s_preferences.open(); global_preferences = &s_preferences; @@ -187,9 +170,7 @@ void setup_preferences() { } // namespace esphome::libretiny namespace esphome { - ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome #endif // USE_LIBRETINY diff --git a/esphome/components/libretiny/preferences.h b/esphome/components/libretiny/preferences.h index 68f377bd3e..8365d590c2 100644 --- a/esphome/components/libretiny/preferences.h +++ b/esphome/components/libretiny/preferences.h @@ -1,11 +1,35 @@ #pragma once - #ifdef USE_LIBRETINY +#include "esphome/core/preference_backend.h" +#include <flashdb.h> + namespace esphome::libretiny { +struct NVSData; + +class LibreTinyPreferences final : public PreferencesMixin<LibreTinyPreferences> { + public: + using PreferencesMixin<LibreTinyPreferences>::make_preference; + void open(); + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) { + return this->make_preference(length, type); + } + ESPPreferenceObject make_preference(size_t length, uint32_t type); + bool sync(); + bool reset(); + + struct fdb_kvdb db; + struct fdb_blob blob; + + protected: + bool is_changed_(fdb_kvdb_t db, const NVSData &to_save, const char *key_str); +}; + void setup_preferences(); } // namespace esphome::libretiny +DECLARE_PREFERENCE_ALIASES(esphome::libretiny::LibreTinyPreferences) + #endif // USE_LIBRETINY diff --git a/esphome/components/rp2040/preference_backend.h b/esphome/components/rp2040/preference_backend.h new file mode 100644 index 0000000000..790ee8831d --- /dev/null +++ b/esphome/components/rp2040/preference_backend.h @@ -0,0 +1,27 @@ +#pragma once +#ifdef USE_RP2040 + +#include <cstddef> +#include <cstdint> + +namespace esphome::rp2040 { + +class RP2040PreferenceBackend final { + public: + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + size_t offset = 0; + uint32_t type = 0; +}; + +class RP2040Preferences; +RP2040Preferences *get_preferences(); + +} // namespace esphome::rp2040 + +namespace esphome { +using PreferenceBackend = rp2040::RP2040PreferenceBackend; +} // namespace esphome + +#endif // USE_RP2040 diff --git a/esphome/components/rp2040/preferences.cpp b/esphome/components/rp2040/preferences.cpp index fa72fd9a24..0a91136a9f 100644 --- a/esphome/components/rp2040/preferences.cpp +++ b/esphome/components/rp2040/preferences.cpp @@ -11,10 +11,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "esphome/core/preferences.h" -namespace esphome { -namespace rp2040 { +namespace esphome::rp2040 { static const char *const TAG = "rp2040.preferences"; @@ -39,129 +37,116 @@ template<class It> uint8_t calculate_crc(It first, It last, uint32_t type) { return crc; } -class RP2040PreferenceBackend : public ESPPreferenceBackend { - public: - size_t offset = 0; - uint32_t type = 0; +bool RP2040PreferenceBackend::save(const uint8_t *data, size_t len) { + const size_t buffer_size = len + 1; + if (buffer_size > PREF_MAX_BUFFER_SIZE) + return false; + uint8_t buffer[PREF_MAX_BUFFER_SIZE]; + memcpy(buffer, data, len); + buffer[len] = calculate_crc(buffer, buffer + len, this->type); - bool save(const uint8_t *data, size_t len) override { - const size_t buffer_size = len + 1; - if (buffer_size > PREF_MAX_BUFFER_SIZE) + for (size_t i = 0; i < buffer_size; i++) { + uint32_t j = this->offset + i; + if (j >= RP2040_FLASH_STORAGE_SIZE) return false; - uint8_t buffer[PREF_MAX_BUFFER_SIZE]; - memcpy(buffer, data, len); - buffer[len] = calculate_crc(buffer, buffer + len, this->type); - - for (size_t i = 0; i < buffer_size; i++) { - uint32_t j = this->offset + i; - if (j >= RP2040_FLASH_STORAGE_SIZE) - return false; - uint8_t v = buffer[i]; - uint8_t *ptr = &s_flash_storage[j]; - if (*ptr != v) - s_flash_dirty = true; - *ptr = v; - } - return true; + uint8_t v = buffer[i]; + uint8_t *ptr = &s_flash_storage[j]; + if (*ptr != v) + s_flash_dirty = true; + *ptr = v; } - bool load(uint8_t *data, size_t len) override { - const size_t buffer_size = len + 1; - if (buffer_size > PREF_MAX_BUFFER_SIZE) + return true; +} + +bool RP2040PreferenceBackend::load(uint8_t *data, size_t len) { + const size_t buffer_size = len + 1; + if (buffer_size > PREF_MAX_BUFFER_SIZE) + return false; + uint8_t buffer[PREF_MAX_BUFFER_SIZE]; + + for (size_t i = 0; i < buffer_size; i++) { + uint32_t j = this->offset + i; + if (j >= RP2040_FLASH_STORAGE_SIZE) return false; - uint8_t buffer[PREF_MAX_BUFFER_SIZE]; + buffer[i] = s_flash_storage[j]; + } - for (size_t i = 0; i < buffer_size; i++) { - uint32_t j = this->offset + i; - if (j >= RP2040_FLASH_STORAGE_SIZE) - return false; - buffer[i] = s_flash_storage[j]; - } + uint8_t crc = calculate_crc(buffer, buffer + len, this->type); + if (buffer[len] != crc) { + return false; + } - uint8_t crc = calculate_crc(buffer, buffer + len, this->type); - if (buffer[len] != crc) { - return false; - } + memcpy(data, buffer, len); + return true; +} - memcpy(data, buffer, len); +RP2040Preferences::RP2040Preferences() : eeprom_sector_(&_EEPROM_start) {} + +void RP2040Preferences::setup() { + ESP_LOGVV(TAG, "Loading preferences from flash"); + memcpy(s_flash_storage, this->eeprom_sector_, RP2040_FLASH_STORAGE_SIZE); +} + +ESPPreferenceObject RP2040Preferences::make_preference(size_t length, uint32_t type) { + uint32_t start = this->current_flash_offset; + uint32_t end = start + length + 1; + if (end > RP2040_FLASH_STORAGE_SIZE) { + return {}; + } + auto *pref = new RP2040PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) + pref->offset = start; + pref->type = type; + this->current_flash_offset = end; + return ESPPreferenceObject(pref); +} + +bool RP2040Preferences::sync() { + if (!s_flash_dirty) return true; - } -}; + if (s_prevent_write) + return false; -class RP2040Preferences : public ESPPreferences { - public: - uint32_t current_flash_offset = 0; + ESP_LOGD(TAG, "Saving"); - RP2040Preferences() : eeprom_sector_(&_EEPROM_start) {} - void setup() { - ESP_LOGVV(TAG, "Loading preferences from flash"); - memcpy(s_flash_storage, this->eeprom_sector_, RP2040_FLASH_STORAGE_SIZE); + { + InterruptLock lock; + ::rp2040.idleOtherCore(); + flash_range_erase((intptr_t) this->eeprom_sector_ - (intptr_t) XIP_BASE, 4096); + flash_range_program((intptr_t) this->eeprom_sector_ - (intptr_t) XIP_BASE, s_flash_storage, + RP2040_FLASH_STORAGE_SIZE); + ::rp2040.resumeOtherCore(); } - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { - return make_preference(length, type); + s_flash_dirty = false; + return true; +} + +bool RP2040Preferences::reset() { + ESP_LOGD(TAG, "Erasing storage"); + { + InterruptLock lock; + ::rp2040.idleOtherCore(); + flash_range_erase((intptr_t) this->eeprom_sector_ - (intptr_t) XIP_BASE, 4096); + ::rp2040.resumeOtherCore(); } - - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { - uint32_t start = this->current_flash_offset; - uint32_t end = start + length + 1; - if (end > RP2040_FLASH_STORAGE_SIZE) { - return {}; - } - auto *pref = new RP2040PreferenceBackend(); // NOLINT(cppcoreguidelines-owning-memory) - pref->offset = start; - pref->type = type; - current_flash_offset = end; - return {pref}; - } - - bool sync() override { - if (!s_flash_dirty) - return true; - if (s_prevent_write) - return false; - - ESP_LOGD(TAG, "Saving"); - - { - InterruptLock lock; - ::rp2040.idleOtherCore(); - flash_range_erase((intptr_t) eeprom_sector_ - (intptr_t) XIP_BASE, 4096); - flash_range_program((intptr_t) eeprom_sector_ - (intptr_t) XIP_BASE, s_flash_storage, RP2040_FLASH_STORAGE_SIZE); - ::rp2040.resumeOtherCore(); - } - - s_flash_dirty = false; - return true; - } - - bool reset() override { - ESP_LOGD(TAG, "Erasing storage"); - { - InterruptLock lock; - ::rp2040.idleOtherCore(); - flash_range_erase((intptr_t) eeprom_sector_ - (intptr_t) XIP_BASE, 4096); - ::rp2040.resumeOtherCore(); - } - s_prevent_write = true; - return true; - } - - protected: - uint8_t *eeprom_sector_; -}; + s_prevent_write = true; + return true; +} static RP2040Preferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +RP2040Preferences *get_preferences() { return &s_preferences; } + void setup_preferences() { s_preferences.setup(); global_preferences = &s_preferences; } void preferences_prevent_write(bool prevent) { s_prevent_write = prevent; } -} // namespace rp2040 +} // namespace esphome::rp2040 +namespace esphome { ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome #endif // USE_RP2040 diff --git a/esphome/components/rp2040/preferences.h b/esphome/components/rp2040/preferences.h index b815c6d58a..eb8c3e5f64 100644 --- a/esphome/components/rp2040/preferences.h +++ b/esphome/components/rp2040/preferences.h @@ -1,14 +1,33 @@ #pragma once - #ifdef USE_RP2040 -namespace esphome { -namespace rp2040 { +#include "esphome/core/preference_backend.h" + +namespace esphome::rp2040 { + +class RP2040Preferences final : public PreferencesMixin<RP2040Preferences> { + public: + using PreferencesMixin<RP2040Preferences>::make_preference; + RP2040Preferences(); + void setup(); + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) { + return this->make_preference(length, type); + } + ESPPreferenceObject make_preference(size_t length, uint32_t type); + bool sync(); + bool reset(); + + uint32_t current_flash_offset = 0; + + protected: + uint8_t *eeprom_sector_; +}; void setup_preferences(); void preferences_prevent_write(bool prevent); -} // namespace rp2040 -} // namespace esphome +} // namespace esphome::rp2040 + +DECLARE_PREFERENCE_ALIASES(esphome::rp2040::RP2040Preferences) #endif // USE_RP2040 diff --git a/esphome/components/zephyr/preference_backend.h b/esphome/components/zephyr/preference_backend.h new file mode 100644 index 0000000000..07e5d8053c --- /dev/null +++ b/esphome/components/zephyr/preference_backend.h @@ -0,0 +1,48 @@ +#pragma once +#ifdef USE_ZEPHYR +#ifdef CONFIG_SETTINGS + +#include <cstddef> +#include <cstdint> +#include <cinttypes> +#include <cstdio> +#include <cstring> +#include <vector> + +namespace esphome::zephyr { + +static constexpr const char *ESPHOME_SETTINGS_KEY = "esphome"; + +// Buffer size for key: "esphome/" (8) + max hex uint32 (8) + null terminator (1) = 17; use 20 for safety margin +static constexpr size_t KEY_BUFFER_SIZE = 20; + +class ZephyrPreferenceBackend final { + public: + explicit ZephyrPreferenceBackend(uint32_t type) : type_(type) {} + ZephyrPreferenceBackend(uint32_t type, std::vector<uint8_t> &&data) : data(std::move(data)), type_(type) {} + + bool save(const uint8_t *data, size_t len); + bool load(uint8_t *data, size_t len); + + uint32_t get_type() const { return this->type_; } + void format_key(char *buf, size_t size) const { + snprintf(buf, size, "%s/%" PRIx32, ESPHOME_SETTINGS_KEY, this->type_); + } + + std::vector<uint8_t> data; + + protected: + uint32_t type_ = 0; +}; + +class ZephyrPreferences; +ZephyrPreferences *get_preferences(); + +} // namespace esphome::zephyr + +namespace esphome { +using PreferenceBackend = zephyr::ZephyrPreferenceBackend; +} // namespace esphome + +#endif // CONFIG_SETTINGS +#endif // USE_ZEPHYR diff --git a/esphome/components/zephyr/preferences.cpp b/esphome/components/zephyr/preferences.cpp index f02fa16326..df69c0e652 100644 --- a/esphome/components/zephyr/preferences.cpp +++ b/esphome/components/zephyr/preferences.cpp @@ -2,167 +2,138 @@ #ifdef CONFIG_SETTINGS #include <zephyr/kernel.h> -#include "esphome/core/preferences.h" +#include "preferences.h" #include "esphome/core/log.h" #include <zephyr/settings/settings.h> #include <cinttypes> #include <cstring> -namespace esphome { -namespace zephyr { +namespace esphome::zephyr { static const char *const TAG = "zephyr.preferences"; -#define ESPHOME_SETTINGS_KEY "esphome" +bool ZephyrPreferenceBackend::save(const uint8_t *data, size_t len) { + this->data.resize(len); + std::memcpy(this->data.data(), data, len); + ESP_LOGVV(TAG, "save key: %" PRIu32 ", len: %zu", this->type_, len); + return true; +} -// Buffer size for key: "esphome/" (8) + max hex uint32 (8) + null terminator (1) = 17; use 20 for safety margin -static constexpr size_t KEY_BUFFER_SIZE = 20; - -class ZephyrPreferenceBackend : public ESPPreferenceBackend { - public: - ZephyrPreferenceBackend(uint32_t type) { this->type_ = type; } - ZephyrPreferenceBackend(uint32_t type, std::vector<uint8_t> &&data) : data(std::move(data)) { this->type_ = type; } - - bool save(const uint8_t *data, size_t len) override { - this->data.resize(len); - std::memcpy(this->data.data(), data, len); - ESP_LOGVV(TAG, "save key: %u, len: %d", this->type_, len); - return true; - } - - bool load(uint8_t *data, size_t len) override { - if (len != this->data.size()) { - char key_buf[KEY_BUFFER_SIZE]; - this->format_key(key_buf, sizeof(key_buf)); - ESP_LOGE(TAG, "size of setting key %s changed, from: %u, to: %u", key_buf, this->data.size(), len); - return false; - } - std::memcpy(data, this->data.data(), len); - ESP_LOGVV(TAG, "load key: %u, len: %d", this->type_, len); - return true; - } - - uint32_t get_type() const { return this->type_; } - void format_key(char *buf, size_t size) const { snprintf(buf, size, ESPHOME_SETTINGS_KEY "/%" PRIx32, this->type_); } - - std::vector<uint8_t> data; - - protected: - uint32_t type_ = 0; -}; - -class ZephyrPreferences : public ESPPreferences { - public: - void open() { - int err = settings_subsys_init(); - if (err) { - ESP_LOGE(TAG, "Failed to initialize settings subsystem, err: %d", err); - return; - } - - static struct settings_handler settings_cb = { - .name = ESPHOME_SETTINGS_KEY, - .h_set = load_setting, - .h_export = export_settings, - }; - - err = settings_register(&settings_cb); - if (err) { - ESP_LOGE(TAG, "setting_register failed, err, %d", err); - return; - } - - err = settings_load_subtree(ESPHOME_SETTINGS_KEY); - if (err) { - ESP_LOGE(TAG, "Cannot load settings, err: %d", err); - return; - } - ESP_LOGD(TAG, "Loaded %u settings.", this->backends_.size()); - } - - ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override { - return make_preference(length, type); - } - - ESPPreferenceObject make_preference(size_t length, uint32_t type) override { - for (auto *backend : this->backends_) { - if (backend->get_type() == type) { - return ESPPreferenceObject(backend); - } - } - printf("type %u size %u\n", type, this->backends_.size()); - auto *pref = new ZephyrPreferenceBackend(type); // NOLINT(cppcoreguidelines-owning-memory) +bool ZephyrPreferenceBackend::load(uint8_t *data, size_t len) { + if (len != this->data.size()) { char key_buf[KEY_BUFFER_SIZE]; - pref->format_key(key_buf, sizeof(key_buf)); - ESP_LOGD(TAG, "Add new setting %s.", key_buf); - this->backends_.push_back(pref); - return ESPPreferenceObject(pref); + this->format_key(key_buf, sizeof(key_buf)); + ESP_LOGE(TAG, "size of setting key %s changed, from: %zu, to: %zu", key_buf, this->data.size(), len); + return false; + } + std::memcpy(data, this->data.data(), len); + ESP_LOGVV(TAG, "load key: %" PRIu32 ", len: %zu", this->type_, len); + return true; +} + +void ZephyrPreferences::open() { + int err = settings_subsys_init(); + if (err) { + ESP_LOGE(TAG, "Failed to initialize settings subsystem, err: %d", err); + return; } - bool sync() override { - ESP_LOGD(TAG, "Save settings"); - int err = settings_save(); - if (err) { - ESP_LOGE(TAG, "Cannot save settings, err: %d", err); - return false; + static struct settings_handler settings_cb = { + .name = ESPHOME_SETTINGS_KEY, + .h_set = load_setting, + .h_export = export_settings, + }; + + err = settings_register(&settings_cb); + if (err) { + ESP_LOGE(TAG, "setting_register failed, err, %d", err); + return; + } + + err = settings_load_subtree(ESPHOME_SETTINGS_KEY); + if (err) { + ESP_LOGE(TAG, "Cannot load settings, err: %d", err); + return; + } + ESP_LOGD(TAG, "Loaded %zu settings.", this->backends_.size()); +} + +ESPPreferenceObject ZephyrPreferences::make_preference(size_t length, uint32_t type) { + for (auto *backend : this->backends_) { + if (backend->get_type() == type) { + return ESPPreferenceObject(backend); } - return true; } + auto *pref = new ZephyrPreferenceBackend(type); // NOLINT(cppcoreguidelines-owning-memory) + char key_buf[KEY_BUFFER_SIZE]; + pref->format_key(key_buf, sizeof(key_buf)); + ESP_LOGD(TAG, "Add new setting %s.", key_buf); + this->backends_.push_back(pref); + return ESPPreferenceObject(pref); +} - bool reset() override { - ESP_LOGD(TAG, "Reset settings"); - for (auto *backend : this->backends_) { - // save empty delete data - backend->data.clear(); - } - sync(); - return true; +bool ZephyrPreferences::sync() { + ESP_LOGD(TAG, "Save settings"); + int err = settings_save(); + if (err) { + ESP_LOGE(TAG, "Cannot save settings, err: %d", err); + return false; } + return true; +} - protected: - std::vector<ZephyrPreferenceBackend *> backends_; - - static int load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) { - auto type = parse_hex<uint32_t>(name); - if (!type.has_value()) { - std::string full_name(ESPHOME_SETTINGS_KEY); - full_name += "/"; - full_name += name; - // Delete unusable keys. Otherwise it will stay in flash forever. - settings_delete(full_name.c_str()); - return 1; - } - std::vector<uint8_t> data(len); - int err = read_cb(cb_arg, data.data(), len); - - ESP_LOGD(TAG, "load setting, name: %s(%u), len %u, err %u", name, *type, len, err); - auto *pref = new ZephyrPreferenceBackend(*type, std::move(data)); // NOLINT(cppcoreguidelines-owning-memory) - static_cast<ZephyrPreferences *>(global_preferences)->backends_.push_back(pref); - return 0; +bool ZephyrPreferences::reset() { + ESP_LOGD(TAG, "Reset settings"); + for (auto *backend : this->backends_) { + // save empty delete data + backend->data.clear(); } + this->sync(); + return true; +} - static int export_settings(int (*cb)(const char *name, const void *value, size_t val_len)) { - for (auto *backend : static_cast<ZephyrPreferences *>(global_preferences)->backends_) { - char name[KEY_BUFFER_SIZE]; - backend->format_key(name, sizeof(name)); - int err = cb(name, backend->data.data(), backend->data.size()); - ESP_LOGD(TAG, "save in flash, name %s, len %u, err %d", name, backend->data.size(), err); - } - return 0; +int ZephyrPreferences::load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) { + auto type = parse_hex<uint32_t>(name); + if (!type.has_value()) { + std::string full_name(ESPHOME_SETTINGS_KEY); + full_name += "/"; + full_name += name; + // Delete unusable keys. Otherwise it will stay in flash forever. + settings_delete(full_name.c_str()); + return 1; } -}; + std::vector<uint8_t> data(len); + int err = read_cb(cb_arg, data.data(), len); + + ESP_LOGD(TAG, "load setting, name: %s(%" PRIu32 "), len %zu, err %d", name, *type, len, err); + auto *pref = new ZephyrPreferenceBackend(*type, std::move(data)); // NOLINT(cppcoreguidelines-owning-memory) + get_preferences()->backends_.push_back(pref); + return 0; +} + +int ZephyrPreferences::export_settings(int (*cb)(const char *name, const void *value, size_t val_len)) { + for (auto *backend : get_preferences()->backends_) { + char name[KEY_BUFFER_SIZE]; + backend->format_key(name, sizeof(name)); + int err = cb(name, backend->data.data(), backend->data.size()); + ESP_LOGD(TAG, "save in flash, name %s, len %zu, err %d", name, backend->data.size(), err); + } + return 0; +} static ZephyrPreferences s_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +ZephyrPreferences *get_preferences() { return &s_preferences; } + void setup_preferences() { global_preferences = &s_preferences; s_preferences.open(); } -} // namespace zephyr +} // namespace esphome::zephyr +namespace esphome { ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome #endif diff --git a/esphome/components/zephyr/preferences.h b/esphome/components/zephyr/preferences.h index 4bee96d79e..9e2555f910 100644 --- a/esphome/components/zephyr/preferences.h +++ b/esphome/components/zephyr/preferences.h @@ -1,11 +1,36 @@ #pragma once - #ifdef USE_ZEPHYR +#ifdef CONFIG_SETTINGS + +#include "esphome/core/preference_backend.h" +#include <zephyr/settings/settings.h> +#include <vector> namespace esphome::zephyr { +class ZephyrPreferences final : public PreferencesMixin<ZephyrPreferences> { + public: + using PreferencesMixin<ZephyrPreferences>::make_preference; + void open(); + ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) { + return this->make_preference(length, type); + } + ESPPreferenceObject make_preference(size_t length, uint32_t type); + bool sync(); + bool reset(); + + protected: + std::vector<ZephyrPreferenceBackend *> backends_; + + static int load_setting(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg); + static int export_settings(int (*cb)(const char *name, const void *value, size_t val_len)); +}; + void setup_preferences(); -} +} // namespace esphome::zephyr -#endif +DECLARE_PREFERENCE_ALIASES(esphome::zephyr::ZephyrPreferences) + +#endif // CONFIG_SETTINGS +#endif // USE_ZEPHYR diff --git a/esphome/core/preference_backend.h b/esphome/core/preference_backend.h new file mode 100644 index 0000000000..3766934da4 --- /dev/null +++ b/esphome/core/preference_backend.h @@ -0,0 +1,83 @@ +#pragma once + +#include <cstdint> + +#include "esphome/core/defines.h" +#include "esphome/core/helpers.h" + +// Include the concrete preference backend for the active platform. +// Each header defines its backend class, forward-declares its manager class, +// declares get_preferences(), and provides the PreferenceBackend alias. +#ifdef USE_ESP32 +#include "esphome/components/esp32/preference_backend.h" +#elif defined(USE_ESP8266) +#include "esphome/components/esp8266/preference_backend.h" +#elif defined(USE_RP2040) +#include "esphome/components/rp2040/preference_backend.h" +#elif defined(USE_LIBRETINY) +#include "esphome/components/libretiny/preference_backend.h" +#elif defined(USE_HOST) +#include "esphome/components/host/preference_backend.h" +#elif defined(USE_ZEPHYR) && defined(CONFIG_SETTINGS) +#include "esphome/components/zephyr/preference_backend.h" +#endif + +namespace esphome { + +#if !defined(USE_ESP32) && !defined(USE_ESP8266) && !defined(USE_RP2040) && !defined(USE_LIBRETINY) && \ + !defined(USE_HOST) && !(defined(USE_ZEPHYR) && defined(CONFIG_SETTINGS)) +// Stub for static analysis when no platform is defined. +struct PreferenceBackend { + bool save(const uint8_t *, size_t) { return false; } + bool load(uint8_t *, size_t) { return false; } +}; +#endif + +using ESPPreferenceBackend = PreferenceBackend; + +class ESPPreferenceObject { + public: + ESPPreferenceObject() = default; + explicit ESPPreferenceObject(PreferenceBackend *backend) : backend_(backend) {} + + template<typename T> bool save(const T *src) { + if (this->backend_ == nullptr) + return false; + return this->backend_->save(reinterpret_cast<const uint8_t *>(src), sizeof(T)); + } + + template<typename T> bool load(T *dest) { + if (this->backend_ == nullptr) + return false; + return this->backend_->load(reinterpret_cast<uint8_t *>(dest), sizeof(T)); + } + + protected: + PreferenceBackend *backend_{nullptr}; +}; + +/// CRTP mixin providing type-safe template make_preference<T>() helpers. +/// Platform preferences classes inherit this to avoid duplicating these templates. +template<typename Derived> class PreferencesMixin { + public: + template<typename T, enable_if_t<is_trivially_copyable<T>::value, bool> = true> + ESPPreferenceObject make_preference(uint32_t type, bool in_flash) { + return static_cast<Derived *>(this)->make_preference(sizeof(T), type, in_flash); + } + + template<typename T, enable_if_t<is_trivially_copyable<T>::value, bool> = true> + ESPPreferenceObject make_preference(uint32_t type) { + return static_cast<Derived *>(this)->make_preference(sizeof(T), type); + } +}; + +// Macro for platform preferences.h headers to declare the standard aliases. +// Must be used at file scope (outside any namespace). +#define DECLARE_PREFERENCE_ALIASES(platform_class) \ + namespace esphome { \ + using Preferences = platform_class; \ + using ESPPreferences = Preferences; \ + extern ESPPreferences *global_preferences; /* NOLINT(cppcoreguidelines-avoid-non-const-global-variables) */ \ + } + +} // namespace esphome diff --git a/esphome/core/preferences.h b/esphome/core/preferences.h index 6d2dd967e9..64a0a927e6 100644 --- a/esphome/core/preferences.h +++ b/esphome/core/preferences.h @@ -1,50 +1,35 @@ #pragma once -#include <cstring> -#include <cstdint> - -#include "esphome/core/helpers.h" +#include "esphome/core/preference_backend.h" +// Include the concrete preferences manager for the active platform. +// Each header defines its manager class and provides the Preferences, +// ESPPreferences, and global_preferences declarations. +#ifdef USE_ESP32 +#include "esphome/components/esp32/preferences.h" +#elif defined(USE_ESP8266) +#include "esphome/components/esp8266/preferences.h" +#elif defined(USE_RP2040) +#include "esphome/components/rp2040/preferences.h" +#elif defined(USE_LIBRETINY) +#include "esphome/components/libretiny/preferences.h" +#elif defined(USE_HOST) +#include "esphome/components/host/preferences.h" +#elif defined(USE_ZEPHYR) && defined(CONFIG_SETTINGS) +#include "esphome/components/zephyr/preferences.h" +#else namespace esphome { - -class ESPPreferenceBackend { - public: - virtual bool save(const uint8_t *data, size_t len) = 0; - virtual bool load(uint8_t *data, size_t len) = 0; -}; - -class ESPPreferenceObject { - public: - ESPPreferenceObject() = default; - ESPPreferenceObject(ESPPreferenceBackend *backend) : backend_(backend) {} - - template<typename T> bool save(const T *src) { - if (backend_ == nullptr) - return false; - return backend_->save(reinterpret_cast<const uint8_t *>(src), sizeof(T)); - } - - template<typename T> bool load(T *dest) { - if (backend_ == nullptr) - return false; - return backend_->load(reinterpret_cast<uint8_t *>(dest), sizeof(T)); - } - - protected: - ESPPreferenceBackend *backend_{nullptr}; -}; - -class ESPPreferences { - public: - virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) = 0; - virtual ESPPreferenceObject make_preference(size_t length, uint32_t type) = 0; +struct Preferences : public PreferencesMixin<Preferences> { + using PreferencesMixin<Preferences>::make_preference; + ESPPreferenceObject make_preference(size_t, uint32_t, bool) { return {}; } + ESPPreferenceObject make_preference(size_t, uint32_t) { return {}; } /** * Commit pending writes to flash. * * @return true if write is successful. */ - virtual bool sync() = 0; + bool sync() { return false; } /** * Forget all unsaved changes and re-initialize the permanent preferences storage. @@ -52,19 +37,9 @@ class ESPPreferences { * * @return true if operation is successful. */ - virtual bool reset() = 0; - - template<typename T, enable_if_t<is_trivially_copyable<T>::value, bool> = true> - ESPPreferenceObject make_preference(uint32_t type, bool in_flash) { - return this->make_preference(sizeof(T), type, in_flash); - } - - template<typename T, enable_if_t<is_trivially_copyable<T>::value, bool> = true> - ESPPreferenceObject make_preference(uint32_t type) { - return this->make_preference(sizeof(T), type); - } + bool reset() { return false; } }; - +using ESPPreferences = Preferences; extern ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - } // namespace esphome +#endif From e1334cf57f8b41bff21cab25cafb65bb5c0f3171 Mon Sep 17 00:00:00 2001 From: Nate Clark <nate@nateclark.com> Date: Thu, 19 Mar 2026 01:40:48 -0400 Subject: [PATCH 1527/2030] [mqtt] Support JSON payload with code for alarm control panel commands (#14731) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- .../mqtt/mqtt_alarm_control_panel.cpp | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index a461a140ae..74a60b3624 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -23,27 +23,52 @@ static ProgmemStr alarm_state_to_mqtt_str(AlarmControlPanelState state) { MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel) : alarm_control_panel_(alarm_control_panel) {} + +static bool apply_command(AlarmControlPanelCall &call, const char *state) { + if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("ARM_AWAY")) == 0) { + call.arm_away(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("ARM_HOME")) == 0) { + call.arm_home(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("ARM_NIGHT")) == 0) { + call.arm_night(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("ARM_VACATION")) == 0) { + call.arm_vacation(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("ARM_CUSTOM_BYPASS")) == 0) { + call.arm_custom_bypass(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("DISARM")) == 0) { + call.disarm(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("PENDING")) == 0) { + call.pending(); + } else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("TRIGGERED")) == 0) { + call.triggered(); + } else { + return false; + } + return true; +} + void MQTTAlarmControlPanelComponent::setup() { this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); }); this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) { auto call = this->alarm_control_panel_->make_call(); - if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_AWAY")) == 0) { - call.arm_away(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_HOME")) == 0) { - call.arm_home(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_NIGHT")) == 0) { - call.arm_night(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_VACATION")) == 0) { - call.arm_vacation(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("ARM_CUSTOM_BYPASS")) == 0) { - call.arm_custom_bypass(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("DISARM")) == 0) { - call.disarm(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("PENDING")) == 0) { - call.pending(); - } else if (ESPHOME_strcasecmp_P(payload.c_str(), ESPHOME_PSTR("TRIGGERED")) == 0) { - call.triggered(); - } else { + if (!payload.empty() && payload[0] == '{') { + // JSON payload: {"state": "DISARM", "code": "1234"} + JsonDocument doc = json::parse_json(payload); + JsonObject root = doc.as<JsonObject>(); + if (!root.isNull()) { + const char *state = root[ESPHOME_F("state")]; + if (state == nullptr) { + ESP_LOGW(TAG, "'%s': JSON payload missing 'state' key", this->friendly_name_().c_str()); + } else if (!apply_command(call, state)) { + ESP_LOGW(TAG, "'%s': Received unknown state in JSON payload: %s", this->friendly_name_().c_str(), state); + } else { + const char *code = root[ESPHOME_F("code")]; + if (code != nullptr) { + call.set_code(code); + } + } + } + } else if (!apply_command(call, payload.c_str())) { ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name_().c_str(), payload.c_str()); } call.perform(); From 9d6f2f71e89673d33ce5360d2ed7aab4da331bd0 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 19 Mar 2026 00:51:17 -0500 Subject: [PATCH 1528/2030] [speaker_source] Reshuffle playlist on repeat all restart (#14773) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .../components/speaker_source/speaker_source_media_player.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/speaker_source/speaker_source_media_player.cpp b/esphome/components/speaker_source/speaker_source_media_player.cpp index 9d02ac9c74..2caab828fb 100644 --- a/esphome/components/speaker_source/speaker_source_media_player.cpp +++ b/esphome/components/speaker_source/speaker_source_media_player.cpp @@ -457,6 +457,9 @@ void SpeakerSourceMediaPlayer::process_control_queue_() { if (ps.playlist_index < ps.playlist.size()) { this->queue_play_current_(pipeline, ps.playlist_delay_ms); } else if (ps.repeat_mode == REPEAT_ALL && !ps.playlist.empty()) { + if (!ps.shuffle_indices.empty()) { + this->shuffle_playlist_(pipeline); + } ps.playlist_index = 0; this->queue_play_current_(pipeline, ps.playlist_delay_ms); } From 2341d510d39cc2bd9bfb8a93b64dc421d1d3e545 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 19 Mar 2026 17:31:33 +1000 Subject: [PATCH 1529/2030] [lvgl] Migrate to library v9.5.0 (#12312) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- .clang-tidy.hash | 2 +- esphome/components/font/__init__.py | 1 + esphome/components/font/font.cpp | 85 ++- esphome/components/font/font.h | 2 +- esphome/components/image/__init__.py | 94 ++- esphome/components/image/image.cpp | 28 +- esphome/components/image/image.h | 2 +- esphome/components/lvgl/__init__.py | 168 +++-- esphome/components/lvgl/automation.py | 97 ++- esphome/components/lvgl/defines.py | 188 +++++- esphome/components/lvgl/encoders.py | 2 +- esphome/components/lvgl/gradient.py | 50 +- esphome/components/lvgl/keypads.py | 2 +- esphome/components/lvgl/layout.py | 24 +- esphome/components/lvgl/light/lvgl_light.h | 2 +- esphome/components/lvgl/lv_validation.py | 117 ++-- esphome/components/lvgl/lvcode.py | 8 + esphome/components/lvgl/lvgl_esphome.cpp | 393 ++++++++---- esphome/components/lvgl/lvgl_esphome.h | 133 ++-- esphome/components/lvgl/lvgl_hal.h | 21 - esphome/components/lvgl/number/__init__.py | 6 +- esphome/components/lvgl/schemas.py | 62 +- esphome/components/lvgl/select/lvgl_select.h | 6 +- esphome/components/lvgl/styles.py | 43 +- esphome/components/lvgl/text/lvgl_text.h | 9 +- esphome/components/lvgl/touchscreens.py | 2 - esphome/components/lvgl/trigger.py | 4 +- esphome/components/lvgl/types.py | 154 +---- esphome/components/lvgl/widgets/__init__.py | 348 ++++++++--- esphome/components/lvgl/widgets/arc.py | 47 +- esphome/components/lvgl/widgets/button.py | 8 +- .../components/lvgl/widgets/buttonmatrix.py | 36 +- esphome/components/lvgl/widgets/canvas.py | 278 ++++++--- esphome/components/lvgl/widgets/container.py | 12 +- esphome/components/lvgl/widgets/img.py | 49 +- esphome/components/lvgl/widgets/label.py | 4 +- esphome/components/lvgl/widgets/led.py | 6 +- esphome/components/lvgl/widgets/line.py | 6 +- esphome/components/lvgl/widgets/lv_bar.py | 4 +- esphome/components/lvgl/widgets/meter.py | 585 +++++++++++++----- esphome/components/lvgl/widgets/msgbox.py | 173 +++--- esphome/components/lvgl/widgets/obj.py | 3 +- esphome/components/lvgl/widgets/qrcode.py | 47 +- esphome/components/lvgl/widgets/slider.py | 14 +- esphome/components/lvgl/widgets/spinner.py | 21 +- esphome/components/lvgl/widgets/tabview.py | 45 +- esphome/components/lvgl/widgets/tileview.py | 14 +- esphome/components/online_image/__init__.py | 9 + esphome/components/runtime_image/__init__.py | 3 +- .../runtime_image/runtime_image.cpp | 9 +- esphome/core/defines.h | 1 + esphome/idf_component.yml | 2 + platformio.ini | 5 +- tests/components/lvgl/lvgl-package.yaml | 75 ++- 54 files changed, 2312 insertions(+), 1197 deletions(-) delete mode 100644 esphome/components/lvgl/lvgl_hal.h diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 87b4ebb2c6..72023e511d 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -8e48e836c6fc196d3da000d46eb09db243b87fe33518a74e49c8e009d756074a +44c877ff43765562ac8298902bf2208799643b77facf09c1c0c3c8c4e17187eb diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 2667dbdbdf..c8813bf1bc 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -552,6 +552,7 @@ async def to_code(config): """ # get the codepoints from glyphsets and flatten to a set of chrs. + cg.add_define("USE_FONT") point_set: set[str] = { chr(x) for x in flatten( diff --git a/esphome/components/font/font.cpp b/esphome/components/font/font.cpp index 5e3bf1dd20..ecf0ca6bdd 100644 --- a/esphome/components/font/font.cpp +++ b/esphome/components/font/font.cpp @@ -9,13 +9,87 @@ namespace font { static const char *const TAG = "font"; #ifdef USE_LVGL_FONT -const uint8_t *Font::get_glyph_bitmap(const lv_font_t *font, uint32_t unicode_letter) { - auto *fe = (Font *) font->dsc; - const auto *gd = fe->get_glyph_data_(unicode_letter); +static const uint8_t OPA4_TABLE[16] = {0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}; + +static const uint8_t OPA2_TABLE[4] = {0, 85, 170, 255}; + +const void *Font::get_glyph_bitmap(lv_font_glyph_dsc_t *dsc, lv_draw_buf_t *draw_buf) { + const auto *font = dsc->resolved_font; + auto *const fe = (Font *) font->dsc; + + const auto *gd = fe->get_glyph_data_(dsc->gid.index); if (gd == nullptr) { return nullptr; } - return gd->data; + + const uint8_t *bitmap_in = gd->data; + uint8_t *bitmap_out_tmp = draw_buf->data; + int32_t i = 0; + int32_t x, y; + uint32_t stride = lv_draw_buf_width_to_stride(gd->width, LV_COLOR_FORMAT_A8); + + switch (fe->get_bpp()) { + case 1: { + uint8_t mask = 0; + uint8_t byte = 0; + for (y = 0; y != gd->height; y++) { + for (x = 0; x != gd->width; x++) { + if (mask == 0) { + mask = 0x80; + byte = *bitmap_in++; + } + bitmap_out_tmp[x] = byte & mask ? 255 : 0; + mask >>= 1; + } + bitmap_out_tmp += stride; + } + } break; + + case 2: + for (y = 0; y != gd->height; y++) { + for (x = 0; x != gd->width; x++, i++) { + switch (i & 0x3) { + default: + bitmap_out_tmp[x] = OPA2_TABLE[(*bitmap_in) >> 6]; + break; + case 1: + bitmap_out_tmp[x] = OPA2_TABLE[((*bitmap_in) >> 4) & 0x3]; + break; + case 2: + bitmap_out_tmp[x] = OPA2_TABLE[((*bitmap_in) >> 2) & 0x3]; + break; + case 3: + bitmap_out_tmp[x] = OPA2_TABLE[((*bitmap_in) >> 0) & 0x3]; + bitmap_in++; + } + } + bitmap_out_tmp += stride; + } + break; + + case 4: + for (y = 0; y != gd->height; y++) { + for (x = 0; x != gd->width; x++, i++) { + i = i & 0x1; + if (i == 0) { + bitmap_out_tmp[x] = OPA4_TABLE[(*bitmap_in) >> 4]; + } else if (i == 1) { + bitmap_out_tmp[x] = OPA4_TABLE[(*bitmap_in) & 0xF]; + bitmap_in++; + } + } + bitmap_out_tmp += stride; + } + break; + + case 8: + memcpy(bitmap_out_tmp, bitmap_in, gd->width * gd->height); + break; + default: + ESP_LOGD(TAG, "Unknown bpp: %d", fe->get_bpp()); + break; + } + return draw_buf; } bool Font::get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, uint32_t unicode_letter, uint32_t next) { @@ -30,7 +104,8 @@ bool Font::get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, uin dsc->box_w = gd->width; dsc->box_h = gd->height; dsc->is_placeholder = 0; - dsc->bpp = fe->get_bpp(); + dsc->format = (lv_font_glyph_format_t) fe->get_bpp(); + dsc->gid.index = unicode_letter; return true; } diff --git a/esphome/components/font/font.h b/esphome/components/font/font.h index 262ded3be4..4a09d7314d 100644 --- a/esphome/components/font/font.h +++ b/esphome/components/font/font.h @@ -90,7 +90,7 @@ class Font uint8_t bpp_; // bits per pixel #ifdef USE_LVGL_FONT lv_font_t lv_font_{}; - static const uint8_t *get_glyph_bitmap(const lv_font_t *font, uint32_t unicode_letter); + static const void *get_glyph_bitmap(lv_font_glyph_dsc_t *dsc, lv_draw_buf_t *draw_buf); static bool get_glyph_dsc_cb(const lv_font_t *font, lv_font_glyph_dsc_t *dsc, uint32_t unicode_letter, uint32_t next); const Glyph *get_glyph_data_(uint32_t unicode_letter); uint32_t last_letter_{}; diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 6ff75d7709..6fb0e46d93 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -28,6 +28,7 @@ from esphome.const import ( CONF_URL, ) from esphome.core import CORE, HexInt +from esphome.final_validate import full_config _LOGGER = logging.getLogger(__name__) @@ -84,7 +85,7 @@ class ImageEncoder: def __init__(self, width, height, transparency, dither, invert_alpha): """ - :param width: The image width in pixels + :param width: The image width in pixels (or bytes) :param height: The image height in pixels :param transparency: Transparency type :param dither: Dither method @@ -93,11 +94,12 @@ class ImageEncoder: self.transparency = transparency self.width = width self.height = height - self.data = [0 for _ in range(width * height)] + self.data = [0] * width * height self.dither = dither self.index = 0 self.invert_alpha = invert_alpha self.path = "" + self.big_endian = False def convert(self, image, path): """ @@ -119,12 +121,21 @@ class ImageEncoder: :return: """ + def end_image(self): + """ + Called at the end of the image. + :return: + """ + + def set_big_endian(self, big_endian: bool) -> None: + self.big_endian = big_endian + @classmethod def is_endian(cls) -> bool: """ Check if the image encoder supports endianness configuration """ - return getattr(cls, "set_big_endian", None) is not None + return False @classmethod def get_options(cls) -> list[str]: @@ -212,18 +223,21 @@ class ImageGrayscale(ImageEncoder): class ImageRGB565(ImageEncoder): def __init__(self, width, height, transparency, dither, invert_alpha): - stride = 3 if transparency == CONF_ALPHA_CHANNEL else 2 super().__init__( - width * stride, + width * 2, height, transparency, dither, invert_alpha, ) - self.big_endian = True + self.alpha = [0] * width * height - def set_big_endian(self, big_endian: bool) -> None: - self.big_endian = big_endian + @classmethod + def is_endian(cls) -> bool: + """ + Check if the image encoder supports endianness configuration + """ + return True def convert(self, image, path): return image.convert("RGBA") @@ -233,6 +247,9 @@ class ImageRGB565(ImageEncoder): r = r >> 3 g = g >> 2 b = b >> 3 + if self.invert_alpha: + a ^= 0xFF + self.alpha[self.index // 2] = a if self.transparency == CONF_CHROMA_KEY: if r == 0 and g == 1 and b == 0: g = 0 @@ -251,11 +268,10 @@ class ImageRGB565(ImageEncoder): self.index += 1 self.data[self.index] = rgb >> 8 self.index += 1 + + def end_image(self): if self.transparency == CONF_ALPHA_CHANNEL: - if self.invert_alpha: - a ^= 0xFF - self.data[self.index] = a - self.index += 1 + self.data.extend(self.alpha) class ImageRGB(ImageEncoder): @@ -281,11 +297,11 @@ class ImageRGB(ImageEncoder): r = 0 g = 1 b = 0 - self.data[self.index] = r + self.data[self.index] = b self.index += 1 self.data[self.index] = g self.index += 1 - self.data[self.index] = b + self.data[self.index] = r self.index += 1 if self.transparency == CONF_ALPHA_CHANNEL: if self.invert_alpha: @@ -655,6 +671,24 @@ def _config_schema(value): CONFIG_SCHEMA = _config_schema +def _final_validate(config): + """ + For LVGL 9 the default byte order for RGB565 images is little-endian + :param config: + :return: + """ + fv = full_config.get() + if "lvgl" in fv and not all(CONF_BYTE_ORDER in x for x in config): + config = config.copy() + for c in config: + if not c.get(CONF_BYTE_ORDER): + c[CONF_BYTE_ORDER] = "LITTLE_ENDIAN" + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate + + async def write_image(config, all_frames=False): path = Path(config[CONF_FILE]) if not path.is_file(): @@ -720,6 +754,7 @@ async def write_image(config, all_frames=False): for col in range(width): encoder.encode(pixels[row * width + col]) encoder.end_row() + encoder.end_image() rhs = [HexInt(x) for x in encoder.data] prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) @@ -729,31 +764,24 @@ async def write_image(config, all_frames=False): return prog_arr, width, height, image_type, trans_value, frame_count -async def _image_to_code(entry): - """ - Convert a single image entry to code and return its metadata. - :param entry: The config entry for the image. - :return: An ImageMetaData object - """ - prog_arr, width, height, image_type, trans_value, _ = await write_image(entry) - cg.new_Pvariable(entry[CONF_ID], prog_arr, width, height, image_type, trans_value) - return ImageMetaData( - width, - height, - entry[CONF_TYPE], - entry[CONF_TRANSPARENCY], +def add_metadata(id: str, width: int, height: int, image_type: str, transparency): + all_metadata = CORE.data.setdefault(DOMAIN, {}).setdefault(KEY_METADATA, {}) + all_metadata[str(id)] = ImageMetaData( + width=width, height=height, image_type=image_type, transparency=transparency ) async def to_code(config): cg.add_define("USE_IMAGE") # By now the config will be a simple list. - # Use a subkey to allow for other data in the future - CORE.data[DOMAIN] = { - KEY_METADATA: { - entry[CONF_ID].id: await _image_to_code(entry) for entry in config - } - } + for entry in config: + prog_arr, width, height, image_type, trans_value, _ = await write_image(entry) + cg.new_Pvariable( + entry[CONF_ID], prog_arr, width, height, image_type, trans_value + ) + add_metadata( + entry[CONF_ID], width, height, entry[CONF_TYPE], entry[CONF_TRANSPARENCY] + ) def get_all_image_metadata() -> dict[str, ImageMetaData]: diff --git a/esphome/components/image/image.cpp b/esphome/components/image/image.cpp index 90e021467f..a6f9e35e2e 100644 --- a/esphome/components/image/image.cpp +++ b/esphome/components/image/image.cpp @@ -105,22 +105,22 @@ Color Image::get_pixel(int x, int y, const Color color_on, const Color color_off } } #ifdef USE_LVGL -lv_img_dsc_t *Image::get_lv_img_dsc() { +lv_image_dsc_t *Image::get_lv_image_dsc() { // lazily construct lvgl image_dsc. if (this->dsc_.data != this->data_start_) { this->dsc_.data = this->data_start_; - this->dsc_.header.always_zero = 0; - this->dsc_.header.reserved = 0; + this->dsc_.header.reserved_2 = 0; + this->dsc_.header.stride = this->get_width_stride(); this->dsc_.header.w = this->width_; this->dsc_.header.h = this->height_; this->dsc_.data_size = this->get_width_stride() * this->get_height(); switch (this->get_type()) { case IMAGE_TYPE_BINARY: - this->dsc_.header.cf = LV_IMG_CF_ALPHA_1BIT; + this->dsc_.header.cf = LV_COLOR_FORMAT_A1; break; case IMAGE_TYPE_GRAYSCALE: - this->dsc_.header.cf = LV_IMG_CF_ALPHA_8BIT; + this->dsc_.header.cf = LV_COLOR_FORMAT_A8; break; case IMAGE_TYPE_RGB: @@ -138,7 +138,7 @@ lv_img_dsc_t *Image::get_lv_img_dsc() { } #else this->dsc_.header.cf = - this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? LV_IMG_CF_RGBA8888 : LV_IMG_CF_RGB888; + this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? LV_COLOR_FORMAT_ARGB8888 : LV_COLOR_FORMAT_RGB888; #endif break; @@ -146,14 +146,10 @@ lv_img_dsc_t *Image::get_lv_img_dsc() { #if LV_COLOR_DEPTH == 16 switch (this->transparency_) { case TRANSPARENCY_ALPHA_CHANNEL: - this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; - break; - case TRANSPARENCY_CHROMA_KEY: - this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; + this->dsc_.header.cf = LV_COLOR_FORMAT_RGB565A8; break; default: - this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR; - break; + this->dsc_.header.cf = LV_COLOR_FORMAT_RGB565; } #else this->dsc_.header.cf = @@ -173,8 +169,8 @@ bool Image::get_binary_pixel_(int x, int y) const { } Color Image::get_rgb_pixel_(int x, int y) const { const uint32_t pos = (x + y * this->width_) * this->bpp_ / 8; - Color color = Color(progmem_read_byte(this->data_start_ + pos + 0), progmem_read_byte(this->data_start_ + pos + 1), - progmem_read_byte(this->data_start_ + pos + 2), 0xFF); + Color color = Color(progmem_read_byte(this->data_start_ + pos + 2), progmem_read_byte(this->data_start_ + pos + 1), + progmem_read_byte(this->data_start_ + pos + 0), 0xFF); switch (this->transparency_) { case TRANSPARENCY_CHROMA_KEY: @@ -200,7 +196,7 @@ Color Image::get_rgb565_pixel_(int x, int y) const { auto a = 0xFF; switch (this->transparency_) { case TRANSPARENCY_ALPHA_CHANNEL: - a = progmem_read_byte(pos + 2); + a = progmem_read_byte(this->data_start_ + this->width_ * this->height_ * 2 + (x + y * this->width_)); break; case TRANSPARENCY_CHROMA_KEY: if (rgb565 == 0x0020) @@ -239,7 +235,7 @@ Image::Image(const uint8_t *data_start, int width, int height, ImageType type, T this->bpp_ = 8; break; case IMAGE_TYPE_RGB565: - this->bpp_ = transparency == TRANSPARENCY_ALPHA_CHANNEL ? 24 : 16; + this->bpp_ = 16; break; case IMAGE_TYPE_RGB: this->bpp_ = this->transparency_ == TRANSPARENCY_ALPHA_CHANNEL ? 32 : 24; diff --git a/esphome/components/image/image.h b/esphome/components/image/image.h index 4024ab1357..d4865570e4 100644 --- a/esphome/components/image/image.h +++ b/esphome/components/image/image.h @@ -41,7 +41,7 @@ class Image : public display::BaseImage { bool has_transparency() const { return this->transparency_ != TRANSPARENCY_OPAQUE; } #ifdef USE_LVGL - lv_img_dsc_t *get_lv_img_dsc(); + lv_image_dsc_t *get_lv_image_dsc(); #endif protected: bool get_binary_pixel_(int x, int y) const; diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index c9cad1ac90..c37a32ecca 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -1,12 +1,30 @@ import importlib -import logging from pathlib import Path import pkgutil from esphome.automation import build_automation, validate_automation import esphome.codegen as cg -from esphome.components.const import CONF_COLOR_DEPTH, CONF_DRAW_ROUNDING +from esphome.components.const import ( + CONF_BYTE_ORDER, + CONF_COLOR_DEPTH, + CONF_DRAW_ROUNDING, +) from esphome.components.display import Display +from esphome.components.esp32 import ( + VARIANT_ESP32P4, + add_idf_component, + add_idf_sdkconfig_option, + get_esp32_variant, +) +from esphome.components.image import ( + CONF_OPAQUE, + IMAGE_TYPE, + ImageBinary, + ImageGrayscale, + ImageRGB, + ImageRGB565, + get_image_metadata, +) from esphome.components.psram import DOMAIN as PSRAM_DOMAIN import esphome.config_validation as cv from esphome.const import ( @@ -21,7 +39,6 @@ from esphome.const import ( CONF_PAGES, CONF_TIMEOUT, CONF_TRIGGER_ID, - CONF_TYPE, ) from esphome.core import CORE, ID, Lambda from esphome.cpp_generator import MockObj @@ -30,8 +47,7 @@ from esphome.helpers import write_file_if_changed from esphome.yaml_util import load_yaml from . import defines as df, helpers, lv_validation as lvalid, widgets -from .automation import disp_update, focused_widgets, refreshed_widgets -from .defines import add_define +from .automation import focused_widgets, layers_to_code, lvgl_update, refreshed_widgets from .encoders import ( ENCODERS_CONFIG, encoders_to_code, @@ -45,12 +61,13 @@ from .lvcode import LvContext, LvglComponent, lvgl_static from .schemas import ( DISP_BG_SCHEMA, FULL_STYLE_SCHEMA, + STYLE_REMAP, WIDGET_TYPES, any_widget_schema, container_schema, obj_schema, ) -from .styles import add_top_layer, styles_to_code, theme_to_code +from .styles import styles_to_code, theme_to_code from .touchscreens import touchscreen_schema, touchscreens_to_code from .trigger import add_on_boot_triggers, generate_triggers from .types import IdleTrigger, PlainTrigger, lv_font_t, lv_group_t, lv_style_t, lvgl_ns @@ -58,7 +75,7 @@ from .widgets import ( LvScrActType, Widget, add_widgets, - get_scr_act, + get_screen_active, set_obj_properties, styles_used, ) @@ -84,7 +101,6 @@ DOMAIN = "lvgl" DEPENDENCIES = ["display"] AUTO_LOAD = ["key_provider"] CODEOWNERS = ["@clydebarrow"] -LOGGER = logging.getLogger(__name__) HELLO_WORLD_FILE = "hello_world.yaml" @@ -102,6 +118,7 @@ def as_macro(macro, value): return f"#define {macro} {value}" +LVGL_VERSION = "9.5.0" LV_CONF_FILENAME = "lv_conf.h" LV_CONF_H_FORMAT = """\ #pragma once @@ -110,7 +127,17 @@ LV_CONF_H_FORMAT = """\ def generate_lv_conf_h(): - definitions = [as_macro(m, v) for m, v in df.get_data(df.KEY_LV_DEFINES).items()] + # Get all possible LV_ config defines based on the widgets used in the config, and the standard LVGL options + all_defines = set( + df.LV_DEFINES + tuple(f"LV_USE_{w.upper()}" for w in WIDGET_TYPES) + ) + # Get the defines that are actually used based on the config + lv_defines = df.get_data(df.KEY_LV_DEFINES) + unused_defines = all_defines - set(lv_defines) + # Create the content of lv_conf.h with the used defines set to their value, and the unused defines disabled + definitions = [as_macro(m, v) for m, v in lv_defines.items()] + [ + as_macro(m, "0") for m in unused_defines + ] definitions.sort() return LV_CONF_H_FORMAT.format("\n".join(definitions)) @@ -133,7 +160,7 @@ def multi_conf_validate(configs: list[dict]): for item in ( CONF_LOG_LEVEL, CONF_COLOR_DEPTH, - df.CONF_BYTE_ORDER, + CONF_BYTE_ORDER, df.CONF_TRANSPARENCY_KEY, ): if base_config[item] != config[item]: @@ -166,14 +193,7 @@ def final_validation(config_list): ) buffer_frac = config[CONF_BUFFER_SIZE] if CORE.is_esp32 and buffer_frac > 0.5 and PSRAM_DOMAIN not in global_config: - LOGGER.warning("buffer_size: may need to be reduced without PSRAM") - for image_id in lv_images_used: - path = global_config.get_path_for_id(image_id)[:-1] - image_conf = global_config.get_config_for_path(path) - if image_conf[CONF_TYPE] in ("RGBA", "RGB24"): - raise cv.Invalid( - "Using RGBA or RGB24 in image config not compatible with LVGL", path - ) + df.LOGGER.warning("buffer_size: may need to be reduced without PSRAM") for w in focused_widgets: path = global_config.get_path_for_id(w) widget_conf = global_config.get_config_for_path(path[:-1]) @@ -205,39 +225,48 @@ def final_validation(config_list): async def to_code(configs): config_0 = configs[0] # Global configuration - cg.add_library("lvgl/lvgl", "8.4.0") + if CORE.is_esp32: + if get_esp32_variant() == VARIANT_ESP32P4: + add_idf_sdkconfig_option("CONFIG_LV_DRAW_BUF_ALIGN", 64) + # disable use of PPA for fills until upstream bugs fixed + df.add_define("LV_USE_PPA", "0") + df.add_define("LV_DRAW_BUF_ALIGN", "64") + else: + df.add_define("LV_DRAW_BUF_ALIGN", "32") + add_idf_component(name="lvgl/lvgl", ref=LVGL_VERSION) + else: + df.add_define("LV_DRAW_BUF_ALIGN", "1") + cg.add_library("lvgl/lvgl", LVGL_VERSION) + df.add_define("LV_DRAW_BUF_STRIDE_ALIGN", "1") + df.add_define("LV_USE_DRAW_SW", "1") + df.add_define("LV_USE_STDLIB_SPRINTF", "LV_STDLIB_CLIB") + df.add_define("LV_USE_STDLIB_STRING", "LV_STDLIB_CLIB") + df.add_define("LV_USE_STDLIB_MALLOC", "LV_STDLIB_CUSTOM") cg.add_define("USE_LVGL") # suppress default enabling of extra widgets - add_define("_LV_KCONFIG_PRESENT") + # cg.add_define("LV_KCONFIG_PRESENT") # Always enable - lots of things use it. - add_define("LV_DRAW_COMPLEX", "1") - add_define("LV_TICK_CUSTOM", "1") - add_define("LV_TICK_CUSTOM_INCLUDE", '"esphome/components/lvgl/lvgl_hal.h"') - add_define("LV_TICK_CUSTOM_SYS_TIME_EXPR", "(lv_millis())") - add_define("LV_MEM_CUSTOM", "1") - add_define("LV_MEM_CUSTOM_ALLOC", "lv_custom_mem_alloc") - add_define("LV_MEM_CUSTOM_FREE", "lv_custom_mem_free") - add_define("LV_MEM_CUSTOM_REALLOC", "lv_custom_mem_realloc") - add_define("LV_MEM_CUSTOM_INCLUDE", '"esphome/components/lvgl/lvgl_hal.h"') + df.add_define("LV_DRAW_SW_COMPLEX", "1") - add_define( + df.add_define( "LV_LOG_LEVEL", f"LV_LOG_LEVEL_{df.LV_LOG_LEVELS[config_0[CONF_LOG_LEVEL]]}", ) + df.add_define("LV_USE_LOG", "1") cg.add_define( "LVGL_LOG_LEVEL", cg.RawExpression(f"ESPHOME_LOG_LEVEL_{config_0[CONF_LOG_LEVEL]}"), ) - add_define("LV_COLOR_DEPTH", config_0[CONF_COLOR_DEPTH]) + df.add_define("LV_COLOR_DEPTH", config_0[CONF_COLOR_DEPTH]) for font in helpers.lv_fonts_used: - add_define(f"LV_FONT_{font.upper()}") + df.add_define(f"LV_FONT_{font.upper()}") if config_0[CONF_COLOR_DEPTH] == 16: - add_define( + df.add_define( "LV_COLOR_16_SWAP", - "1" if config_0[df.CONF_BYTE_ORDER] == "big_endian" else "0", + "1" if config_0[CONF_BYTE_ORDER] == "big_endian" else "0", ) - add_define( + df.add_define( "LV_COLOR_CHROMA_KEY", await lvalid.lv_color.process(config_0[df.CONF_TRANSPARENCY_KEY]), ) @@ -248,7 +277,7 @@ async def to_code(configs): await cg.get_variable(font) default_font = config_0[df.CONF_DEFAULT_FONT] if not lvalid.is_lv_font(default_font): - add_define( + df.add_define( "LV_FONT_CUSTOM_DECLARE", f"LV_FONT_DECLARE(*{df.DEFAULT_ESPHOME_FONT})" ) globfont_id = ID( @@ -262,9 +291,9 @@ async def to_code(configs): MockObj(await lvalid.lv_font.process(default_font), "->").get_lv_font(), static=False, ) - add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) + df.add_define("LV_FONT_DEFAULT", df.DEFAULT_ESPHOME_FONT) else: - add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) + df.add_define("LV_FONT_DEFAULT", await lvalid.lv_font.process(default_font)) cg.add(lvgl_static.esphome_lvgl_init()) default_group = get_default_group(config_0) @@ -293,8 +322,9 @@ async def to_code(configs): await cg.register_component(lv_component, config) Widget.create(config[CONF_ID], lv_component, LvScrActType(), config) - lv_scr_act = get_scr_act(lv_component) + lv_scr_act = get_screen_active(lv_component) async with LvContext(): + cg.add(lv_component.set_big_endian(config[CONF_BYTE_ORDER] == "big_endian")) await touchscreens_to_code(lv_component, config) await encoders_to_code(lv_component, config, default_group) await keypads_to_code(lv_component, config, default_group) @@ -304,9 +334,10 @@ async def to_code(configs): await set_obj_properties(lv_scr_act, config) await add_widgets(lv_scr_act, config) await add_pages(lv_component, config) - await add_top_layer(lv_component, config) + await layers_to_code(lv_component, config) + await lvgl_update(lv_component, config) await msgboxes_to_code(lv_component, config) - await disp_update(lv_component.get_disp(), config) + # await disp_update(lv_component.get_disp(), config) # Set this directly since we are limited in how many methods can be added to the Widget class. Widget.widgets_completed = True async with LvContext(): @@ -336,15 +367,53 @@ async def to_code(configs): # This must be done after all widgets are created for comp in helpers.lvgl_components_required: cg.add_define(f"USE_LVGL_{comp.upper()}") - if {"transform_angle", "transform_zoom"} & styles_used: - add_define("LV_COLOR_SCREEN_TRANSP", "1") + lv_image_formats = df.get_color_formats().copy() + if { + "transform_rotation", + "transform_scale", + "transform_scale_x", + "transform_scale_y", + } & styles_used: + df.add_define("LV_COLOR_SCREEN_TRANSP", "1") + lv_image_formats.add("ARGB8888") + lv_image_formats.add( + "RGB565" + ) # Currently always need RGB565 for the display buffer for use in helpers.lv_uses: - add_define(f"LV_USE_{use.upper()}") + df.add_define(f"LV_USE_{use.upper()}") cg.add_define(f"USE_LVGL_{use.upper()}") + + for image_id in lv_images_used: + await cg.get_variable(image_id) + metadata = get_image_metadata(image_id.id) + image_type = IMAGE_TYPE[metadata.image_type] + transparent = metadata.transparency != CONF_OPAQUE + if transparent: + # Internal draw layer will use ARGB8888 + lv_image_formats.add("ARGB8888") + if image_type == ImageBinary: + lv_image_formats.add("I1") + if image_type == ImageGrayscale: + lv_image_formats.add("A8") + if image_type == ImageRGB565: + lv_image_formats.add("RGB565A8" if transparent else "RGB565") + if image_type == ImageRGB: + lv_image_formats.add("ARGB8888" if transparent else "RGB8888") + if df.is_defined("LV_GRADIENT_MAX_STOPS"): + lv_image_formats.add("RGB888") + for fmt in lv_image_formats: + df.add_define(f"LV_DRAW_SW_SUPPORT_{fmt}", "1") lv_conf_h_file = CORE.relative_src_path(LV_CONF_FILENAME) write_file_if_changed(lv_conf_h_file, generate_lv_conf_h()) cg.add_build_flag("-DLV_CONF_H=1") - cg.add_build_flag(f'-DLV_CONF_PATH="{LV_CONF_FILENAME}"') + cg.add_build_flag(f'-DLV_CONF_PATH=\\"{LV_CONF_FILENAME}\\"') + + for prop in df.get_remapped_uses(): + df.LOGGER.warning( + "Property '%s' is deprecated, use '%s' instead", prop, STYLE_REMAP[prop] + ) + for warning in df.get_warnings(): + df.LOGGER.warning(warning) def display_schema(config): @@ -357,7 +426,9 @@ def display_schema(config): def add_hello_world(config): if df.CONF_WIDGETS not in config and CONF_PAGES not in config: - LOGGER.info("No pages or widgets configured, creating default hello_world page") + df.LOGGER.info( + "No pages or widgets configured, creating default hello_world page" + ) hello_world_path = Path(__file__).parent / HELLO_WORLD_FILE config[df.CONF_WIDGETS] = any_widget_schema()(load_yaml(hello_world_path)) return config @@ -395,8 +466,8 @@ LVGL_SCHEMA = cv.All( cv.Optional(CONF_LOG_LEVEL, default="WARN"): cv.one_of( *df.LV_LOG_LEVELS, upper=True ), - cv.Optional(df.CONF_BYTE_ORDER, default="big_endian"): cv.one_of( - "big_endian", "little_endian" + cv.Optional(CONF_BYTE_ORDER, default="big_endian"): cv.one_of( + "big_endian", "little_endian", lower=True ), cv.Optional(df.CONF_STYLE_DEFINITIONS): cv.ensure_list( cv.Schema({cv.Required(CONF_ID): cv.declare_id(lv_style_t)}).extend( @@ -424,6 +495,7 @@ LVGL_SCHEMA = cv.All( cv.Optional(df.CONF_MSGBOXES): cv.ensure_list(MSGBOX_SCHEMA), cv.Optional(df.CONF_PAGE_WRAP, default=True): lv_bool, cv.Optional(df.CONF_TOP_LAYER): container_schema(obj_spec), + cv.Optional(df.CONF_BOTTOM_LAYER): container_schema(obj_spec), cv.Optional( df.CONF_TRANSPARENCY_KEY, default=0x000400 ): lvalid.lv_color, diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index f9adca9c33..24579e5be8 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -10,18 +10,21 @@ from esphome.cpp_generator import TemplateArguments, get_variable from esphome.cpp_types import nullptr from .defines import ( - CONF_DISP_BG_COLOR, - CONF_DISP_BG_IMAGE, - CONF_DISP_BG_OPA, + CONF_BG_OPA, + CONF_BOTTOM_LAYER, CONF_EDITING, CONF_FREEZE, CONF_LVGL_ID, + CONF_MAIN, + CONF_OBJ, + CONF_SCROLLBAR, CONF_SHOW_SNOW, + CONF_TOP_LAYER, PARTS, - literal, - static_cast, + StaticCastExpression, + add_warning, ) -from .lv_validation import lv_bool, lv_color, lv_image, lv_milliseconds, opacity +from .lv_validation import lv_bool, lv_milliseconds from .lvcode import ( LVGL_COMP_ARG, UPDATE_EVENT, @@ -42,13 +45,13 @@ from .schemas import ( LIST_ACTION_SCHEMA, LVGL_SCHEMA, base_update_schema, + part_schema, ) from .types import ( LV_STATE, LvglAction, LvglCondition, ObjUpdateAction, - lv_disp_t, lv_group_t, lv_obj_base_t, lv_obj_t, @@ -56,7 +59,9 @@ from .types import ( ) from .widgets import ( Widget, - get_scr_act, + WidgetType, + add_widgets, + get_screen_active, get_widgets, set_obj_properties, wait_for_widgets, @@ -67,6 +72,41 @@ focused_widgets = set() refreshed_widgets = set() +async def layers_to_code(lv_component, config): + if top_conf := config.get(CONF_TOP_LAYER): + top_layer = lv_expr.display_get_layer_top(lv_component.get_disp()) + with LocalVariable("top_layer", lv_obj_t, top_layer) as top_layer_obj: + top_w = Widget(top_layer_obj, layer_spec, top_conf) + await set_obj_properties(top_w, top_conf) + await add_widgets(top_w, top_conf) + if bottom_conf := config.get(CONF_BOTTOM_LAYER): + bottom_layer = lv_expr.display_get_layer_bottom(lv_component.get_disp()) + with LocalVariable("bottom_layer", lv_obj_t, bottom_layer) as bottom_layer_obj: + bottom_w = Widget(bottom_layer_obj, layer_spec, bottom_conf) + await set_obj_properties(bottom_w, bottom_conf) + await add_widgets(bottom_w, bottom_conf) + + +async def lvgl_update(lv_component, config): + bottom = {k.removeprefix("disp_"): v for k, v in config.items() if k in DISP_PROPS} + if not bottom: + return + plural = len(bottom) != 1 + add_warning( + "The propert" + + ("ies " if plural else "y ") + + "'" + + "','".join(k for k in config if k in DISP_PROPS) + + "'" + + (" are " if plural else " is ") + + "deprecated, use 'bottom_layer' instead." + ) + # Preserve default opacity from 8.x + if CONF_BG_OPA not in bottom: + bottom[CONF_BG_OPA] = 1.0 + await layers_to_code(lv_component, {CONF_BOTTOM_LAYER: bottom}) + + async def action_to_code( widgets: list[Widget], action: Callable[[Widget], Any], @@ -151,25 +191,6 @@ async def lvgl_is_idle(config, condition_id, template_arg, args): return var -async def disp_update(disp, config: dict): - if ( - CONF_DISP_BG_COLOR not in config - and CONF_DISP_BG_IMAGE not in config - and CONF_DISP_BG_OPA not in config - ): - return - with LocalVariable("lv_disp_tmp", lv_disp_t, disp) as disp_temp: - if (bg_color := config.get(CONF_DISP_BG_COLOR)) is not None: - lv.disp_set_bg_color(disp_temp, await lv_color.process(bg_color)) - if bg_image := config.get(CONF_DISP_BG_IMAGE): - if bg_image == "none": - lv.disp_set_bg_image(disp_temp, static_cast("void *", "nullptr")) - else: - lv.disp_set_bg_image(disp_temp, await lv_image.process(bg_image)) - if (bg_opa := config.get(CONF_DISP_BG_OPA)) is not None: - lv.disp_set_bg_opa(disp_temp, await opacity.process(bg_opa)) - - @automation.register_action( "lvgl.widget.redraw", ObjUpdateAction, @@ -187,7 +208,7 @@ async def disp_update(disp, config: dict): async def obj_invalidate_to_code(config, action_id, template_arg, args): if CONF_LVGL_ID in config: lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) - widgets = [get_scr_act(lv_comp)] + widgets = [get_screen_active(lv_comp)] else: widgets = await get_widgets(config) @@ -197,20 +218,30 @@ async def obj_invalidate_to_code(config, action_id, template_arg, args): return await action_to_code(widgets, do_invalidate, action_id, template_arg, args) +layer_spec = WidgetType(CONF_OBJ, lv_obj_t, (CONF_MAIN, CONF_SCROLLBAR), is_mock=True) + +DISP_PROPS = {str(x) for x in DISP_BG_SCHEMA.schema} + + @automation.register_action( "lvgl.update", LvglAction, - DISP_BG_SCHEMA.extend(LVGL_SCHEMA).add_extra( - cv.has_at_least_one_key(CONF_DISP_BG_COLOR, CONF_DISP_BG_IMAGE) + part_schema(layer_spec.parts) + .extend(LVGL_SCHEMA) + .extend(DISP_BG_SCHEMA) + .extend( + { + cv.Optional(CONF_TOP_LAYER): part_schema(layer_spec.parts), + cv.Optional(CONF_BOTTOM_LAYER): part_schema(layer_spec.parts), + } ), synchronous=True, ) async def lvgl_update_to_code(config, action_id, template_arg, args): widgets = await get_widgets(config, CONF_LVGL_ID) w = widgets[0] - disp = literal(f"{w.obj}->get_disp()") async with LambdaContext(LVGL_COMP_ARG, where=action_id) as context: - await disp_update(disp, config) + await lvgl_update(w.var, config) var = cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) await cg.register_parented(var, w.var) return var @@ -336,7 +367,7 @@ async def widget_focus(config, action_id, template_arg, args): widget = await get_widgets(config) if widget: widget = widget[0] - group = static_cast( + group = StaticCastExpression( lv_group_t.operator("ptr"), lv_expr.obj_get_group(widget.obj) ) elif group := config.get(CONF_GROUP): diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 91077a1ff4..d6d7a5e161 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -10,8 +10,12 @@ from typing import Any from esphome import codegen as cg, config_validation as cv from esphome.const import CONF_ITEMS from esphome.core import CORE, ID, Lambda -from esphome.cpp_generator import LambdaExpression, MockObj -from esphome.cpp_types import uint32 +from esphome.cpp_generator import ( + CallExpression, + LambdaExpression, + MockObj, + MockObjClass, +) from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.types import Expression, SafeExpType @@ -21,8 +25,11 @@ LOGGER = logging.getLogger(__name__) lvgl_ns = cg.esphome_ns.namespace("lvgl") DOMAIN = "lvgl" +KEY_COLOR_FORMATS = "color_formats" KEY_LV_DEFINES = "lv_defines" +KEY_REMAPPED_USES = "remapped_uses" KEY_UPDATED_WIDGETS = "updated_widgets" +KEY_WARNINGS = "warnings" def get_data(key, default=None): @@ -33,10 +40,37 @@ def get_data(key, default=None): :return: """ return CORE.data.setdefault(DOMAIN, {}).setdefault( - key, default if default is not None else {} + key, {} if default is None else default ) +def get_warnings(): + return get_data(KEY_WARNINGS, set()) + + +def get_remapped_uses(): + return get_data(KEY_REMAPPED_USES, set()) + + +def get_color_formats(): + return get_data(KEY_COLOR_FORMATS, set()) + + +def add_warning(msg: str): + get_warnings().add(msg) + + +class StaticCastExpression(Expression): + __slots__ = ("type", "exp") + + def __init__(self, type: Any, exp: SafeExpType): + self.type = str(type) + self.exp = cg.safe_exp(exp) + + def __str__(self): + return f"static_cast<{self.type}>({self.exp})" + + def add_define(macro, value="1"): lv_defines = get_data(KEY_LV_DEFINES) value = str(value) @@ -47,27 +81,43 @@ def add_define(macro, value="1"): lv_defines[macro] = value +def is_defined(macro): + return macro in get_data(KEY_LV_DEFINES) + + def literal(arg) -> MockObj: if isinstance(arg, str): return MockObj(arg) return arg -def static_cast(type, value): - return literal(f"static_cast<{type}>({value})") +def addr(arg) -> MockObj: + return MockObj(f"&{arg}") def call_lambda(lamb: LambdaExpression): + """ + Given a lambda, either reduce to a simple expression or call it, possibly with parameters + from the surrounding context + :param lamb: + :return: + """ expr = lamb.content.strip() if expr.startswith("return") and expr.endswith(";"): - return expr[6:-1].strip() - # If lambda has parameters, call it with those parameter names + # Convert a lambda returning a simple expression to just that expression + expr = cg.RawExpression(expr[6:-1].strip()) + # Don't cast if the return type is a class + if isinstance(lamb.return_type, MockObjClass): + return expr + return StaticCastExpression(lamb.return_type, expr) + # If lambda has parameters, call it with their names # Parameter names come from hardcoded component code (like "x", "it", "event") # not from user input, so they're safe to use directly if lamb.parameters and lamb.parameters.parameters: - param_names = ", ".join(str(param.id) for param in lamb.parameters.parameters) - return f"{lamb}({param_names})" - return f"{lamb}()" + return CallExpression( + lamb, *[MockObj(x.id) for x in lamb.parameters.parameters] + ) + return CallExpression(lamb) class LValidator: @@ -76,7 +126,7 @@ class LValidator: has `process()` to convert a value during code generation """ - def __init__(self, validator, rtype, retmapper=None, requires=None): + def __init__(self, validator, rtype: MockObj, retmapper=None, requires=None): self.validator = validator self.rtype = rtype self.retmapper = retmapper @@ -99,10 +149,9 @@ class LValidator: from .lvcode import get_lambda_context_args args = args or get_lambda_context_args() - return cg.RawExpression( - call_lambda( - await cg.process_lambda(value, args, return_type=self.rtype) - ) + + return call_lambda( + await cg.process_lambda(value, args, return_type=self.rtype) ) if self.retmapper is not None: return self.retmapper(value) @@ -112,6 +161,8 @@ class LValidator: value = [ await cg.get_variable(x) if isinstance(x, ID) else x for x in value ] + if self.rtype is cg.int_: + value = int(value) return cg.safe_exp(value) @@ -122,10 +173,11 @@ class LvConstant(LValidator): The property `one_of` has the single case validator, and `several_of` allows a list of constants. """ - def __init__(self, prefix: str, *choices): + def __init__(self, prefix: str, *choices, typename=None): self.prefix = prefix - self.choices = choices - prefixed_choices = [prefix + v for v in choices] + self.choices = tuple(x.upper() for x in choices) + self.typename = typename or prefix.lower() + "t" + prefixed_choices = [prefix + v.upper() for v in choices] prefixed_validator = cv.one_of(*prefixed_choices, upper=True) @schema_extractor("one_of") @@ -136,24 +188,30 @@ class LvConstant(LValidator): return prefixed_validator(value) return self.prefix + cv.one_of(*choices, upper=True)(value) - super().__init__(validator, rtype=uint32) + super().__init__(validator, rtype=cg.uint32) self.retmapper = self.mapper - self.one_of = LValidator(validator, uint32, retmapper=self.mapper) + self.one_of = LValidator(validator, cg.uint32, retmapper=self.mapper) self.several_of = LValidator( - cv.ensure_list(self.one_of), uint32, retmapper=self.mapper + cv.ensure_list(self.one_of), cg.uint32, retmapper=self.mapper ) def mapper(self, value): if not isinstance(value, list): value = [value] - return literal( - "|".join( - [ - str(v) if str(v).startswith(self.prefix) else self.prefix + str(v) - for v in value - ] - ).upper() - ) + value = [ + ( + str(v).upper() + if str(v).startswith(self.prefix) + else self.prefix + str(v).upper() + ) + for v in value + ] + if len(value) == 1: + return literal(value[0]) + value = literal("|".join(value)) + if self.typename is None: + return value + return StaticCastExpression(self.typename, value) def extend(self, *choices): """ @@ -161,7 +219,14 @@ class LvConstant(LValidator): :param choices: The extra choices :return: A new LVConstant instance """ - return LvConstant(self.prefix, *(self.choices + choices)) + return LvConstant( + self.prefix, *(self.choices + choices), typename=self.typename + ) + + def __getattr__(self, item): + if item.upper() not in self.choices: + raise AttributeError(f"{item} not one of {self.choices}") + return self.mapper(item) # Parts @@ -277,11 +342,13 @@ PARTS = ( CONF_KNOB, CONF_SELECTED, CONF_ITEMS, - CONF_TICKS, + # CONF_TICKS, CONF_CURSOR, CONF_TEXTAREA_PLACEHOLDER, ) +LV_PART = LvConstant("LV_PART_", *(p.upper() for p in PARTS)) + KEYBOARD_MODES = LvConstant( "LV_KEYBOARD_MODE_", "TEXT_LOWER", @@ -359,6 +426,7 @@ OBJ_FLAGS = ( "overflow_visible", "layout_1", "layout_2", + "send_draw_task_events", "widget_1", "widget_2", "user_1", @@ -366,12 +434,14 @@ OBJ_FLAGS = ( "user_3", "user_4", ) +LV_OBJ_FLAG = LvConstant("LV_OBJ_FLAG_", *OBJ_FLAGS) ARC_MODES = LvConstant("LV_ARC_MODE_", "NORMAL", "REVERSE", "SYMMETRICAL") BAR_MODES = LvConstant("LV_BAR_MODE_", "NORMAL", "SYMMETRICAL", "RANGE") +SLIDER_MODES = LvConstant("LV_SLIDER_MODE_", "NORMAL", "SYMMETRICAL", "RANGE") BUTTONMATRIX_CTRLS = LvConstant( - "LV_BTNMATRIX_CTRL_", + "LV_BUTTONMATRIX_CTRL_", "HIDDEN", "NO_REPEAT", "DISABLED", @@ -434,12 +504,16 @@ CONF_ACCEPTED_CHARS = "accepted_chars" CONF_ADJUSTABLE = "adjustable" CONF_ALIGN = "align" CONF_ALIGN_TO = "align_to" +CONF_ANGLE_RANGE = "angle_range" CONF_ANIMATED = "animated" CONF_ANIMATION = "animation" +CONF_ANIMATIONS = "animations" CONF_ANTIALIAS = "antialias" CONF_ARC_LENGTH = "arc_length" CONF_AUTO_START = "auto_start" CONF_BACKGROUND_STYLE = "background_style" +CONF_BG_OPA = "bg_opa" +CONF_BOTTOM_LAYER = "bottom_layer" CONF_BUTTON_STYLE = "button_style" CONF_DECIMAL_PLACES = "decimal_places" CONF_COLUMN = "column" @@ -449,9 +523,11 @@ CONF_DISP_BG_IMAGE = "disp_bg_image" CONF_DISP_BG_OPA = "disp_bg_opa" CONF_BODY = "body" CONF_BUTTONS = "buttons" -CONF_BYTE_ORDER = "byte_order" CONF_CHANGE_RATE = "change_rate" CONF_CLOSE_BUTTON = "close_button" +CONF_COLOR_DEPTH = "color_depth" +CONF_COLOR_END = "color_end" +CONF_COLOR_START = "color_start" CONF_CONTAINER = "container" CONF_CONTROL = "control" CONF_DEFAULT_FONT = "default_font" @@ -483,8 +559,10 @@ CONF_GRID_COLUMN_ALIGN = "grid_column_align" CONF_GRID_COLUMNS = "grid_columns" CONF_GRID_ROW_ALIGN = "grid_row_align" CONF_GRID_ROWS = "grid_rows" +CONF_HEADER_BUTTONS = "header_buttons" CONF_HEADER_MODE = "header_mode" CONF_HOME = "home" +CONF_INDICATORS = "indicators" CONF_INITIAL_FOCUS = "initial_focus" CONF_SELECTED_DIGIT = "selected_digit" CONF_KEY_CODE = "key_code" @@ -496,6 +574,7 @@ CONF_LONG_PRESS_TIME = "long_press_time" CONF_LONG_PRESS_REPEAT_TIME = "long_press_repeat_time" CONF_LVGL_ID = "lvgl_id" CONF_LONG_MODE = "long_mode" +CONF_MAJOR_TICKS_STYLE = "major_ticks_style" CONF_MSGBOXES = "msgboxes" CONF_OBJ = "obj" CONF_ONE_CHECKED = "one_checked" @@ -517,12 +596,15 @@ CONF_PIVOT_Y = "pivot_y" CONF_PLACEHOLDER_TEXT = "placeholder_text" CONF_POINTS = "points" CONF_PREVIOUS = "previous" +CONF_RADIUS = "radius" CONF_REPEAT_COUNT = "repeat_count" CONF_RECOLOR = "recolor" CONF_RESUME_ON_INPUT = "resume_on_input" CONF_RIGHT_BUTTON = "right_button" CONF_ROLLOVER = "rollover" CONF_ROOT_BACK_BTN = "root_back_btn" +CONF_ROWS = "rows" +CONF_SCALE = "scale" CONF_SCALE_LINES = "scale_lines" CONF_SCROLLBAR_MODE = "scrollbar_mode" CONF_SCROLL_DIR = "scroll_dir" @@ -536,6 +618,7 @@ CONF_SRC = "src" CONF_START_ANGLE = "start_angle" CONF_START_VALUE = "start_value" CONF_STATES = "states" +CONF_STRIDE = "stride" CONF_STYLE = "style" CONF_STYLES = "styles" CONF_STYLE_DEFINITIONS = "style_definitions" @@ -544,6 +627,7 @@ CONF_SKIP = "skip" CONF_SYMBOL = "symbol" CONF_TAB_ID = "tab_id" CONF_TABS = "tabs" +CONF_TICK_STYLE = "tick_style" CONF_TIME_FORMAT = "time_format" CONF_TILE = "tile" CONF_TILE_ID = "tile_id" @@ -551,6 +635,8 @@ CONF_TILES = "tiles" CONF_TITLE = "title" CONF_TOP_LAYER = "top_layer" CONF_TOUCHSCREENS = "touchscreens" +CONF_TRANSFORM_ROTATION = "transform_rotation" +CONF_TRANSFORM_SCALE = "transform_scale" CONF_TRANSPARENCY_KEY = "transparency_key" CONF_THEME = "theme" CONF_UPDATE_ON_RELEASE = "update_on_release" @@ -578,6 +664,16 @@ LV_KEYS = LvConstant( "END", ) +LV_SCALE_MODE = LvConstant( + "LV_SCALE_MODE_", + "HORIZONTAL_TOP", + "HORIZONTAL_BOTTOM", + "VERTICAL_LEFT", + "VERTICAL_RIGHT", + "ROUND_INNER", + "ROUND_OUTER", +) + DEFAULT_ESPHOME_FONT = "esphome_lv_default_font" @@ -590,3 +686,29 @@ def join_enums(enums, prefix=""): if prefix: return literal("|".join(f"{prefix}{e.upper()}" for e in enums)) return literal("|".join(f"(int){e.upper()}" for e in enums)) + + +# fmt: off +LV_COLOR_FORMATS = ( + "RGB565", "SWAPPED", "RGB565A8", "RGB888", "XRGB8888", "ARGB8888", "PREMULTIPLIED", "L8", "AL88", "A8", "I1", +) + +LV_DEFINES = ( + "LV_USE_FREERTOS_TASK_NOTIFY", "LV_DRAW_BUF_STRIDE_ALIGN", "LV_USE_DRAW_SW", "LV_DRAW_SW_DRAW_UNIT_CNT", + "LV_DRAW_SW_COMPLEX", "LV_USE_DRAW_PXP", "LV_USE_PXP_DRAW_THREAD", "LV_USE_DRAW_G2D", + "LV_USE_G2D_DRAW_THREAD", "LV_VG_LITE_USE_BOX_SHADOW", "LV_VG_LITE_THORVG_16PIXELS_ALIGN", "LV_LOG_USE_TIMESTAMP", + "LV_LOG_USE_FILE_LINE", "LV_USE_OBJ_ID_BUILTIN", "LV_USE_OBJ_PROPERTY_NAME", "LV_ATTRIBUTE_MEM_ALIGN_SIZE", + "LV_FONT_MONTSERRAT_14", "LV_USE_FONT_PLACEHOLDER", "LV_WIDGETS_HAS_DEFAULT_VALUE", "LV_USE_ARCLABEL", + "LV_USE_CALENDAR", "LV_USE_CALENDAR_HEADER_ARROW", "LV_USE_CALENDAR_HEADER_DROPDOWN", "LV_USE_CHART", + "LV_USE_LIST", "LV_USE_MENU", "LV_USE_MSGBOX", "LV_USE_SCALE", + "LV_USE_TABLE", "LV_USE_SPAN", "LV_USE_WIN", "LV_USE_THEME_DEFAULT", + "LV_THEME_DEFAULT_GROW", "LV_USE_THEME_SIMPLE", "LV_USE_THEME_MONO", "LV_USE_FLEX", + "LV_USE_GRID", "LV_USE_PROFILER_BUILTIN", "LV_PROFILER_BUILTIN_DEFAULT_ENABLE", "LV_PROFILER_LAYOUT", + "LV_PROFILER_REFR", "LV_PROFILER_DRAW", "LV_PROFILER_INDEV", "LV_PROFILER_DECODER", + "LV_PROFILER_FONT", "LV_PROFILER_FS", "LV_PROFILER_TIMER", "LV_PROFILER_CACHE", + "LV_PROFILER_EVENT", "LV_USE_OBSERVER", "LV_IME_PINYIN_USE_DEFAULT_DICT", "LV_IME_PINYIN_USE_K9_MODE", + "LV_FILE_EXPLORER_QUICK_ACCESS", "LV_TEST_SCREENSHOT_CREATE_REFERENCE_IMAGE", "LV_LINUX_FBDEV_MMAP", + "LV_USE_NUTTX_MOUSE_MOVE_STEP", "LV_USE_GENERIC_MIPI", "LV_BUILD_EXAMPLES", "LV_BUILD_DEMOS", + "LV_WAYLAND_USE_EGL", "LV_WAYLAND_USE_G2D", "LV_WAYLAND_USE_SHM", "LV_LINUX_DRM_USE_EGL", + "LV_USE_LZ4", "LV_USE_THORVG", "LV_SDL_USE_EGL", "LV_USE_EGL", "LV_LABEL_LONG_TXT_HINT", "LV_LABEL_TEXT_SELECTION", +) + tuple(f"LV_DRAW_SW_SUPPORT_{f}" for f in LV_COLOR_FORMATS) diff --git a/esphome/components/lvgl/encoders.py b/esphome/components/lvgl/encoders.py index 259c344030..bafda8382e 100644 --- a/esphome/components/lvgl/encoders.py +++ b/esphome/components/lvgl/encoders.py @@ -71,7 +71,7 @@ async def encoders_to_code(var, config, default_group): lv_assign(group, lv_expr.group_create()) else: group = default_group - lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) + lv.indev_set_group(listener.get_drv(), group) async def initial_focus_to_code(config): diff --git a/esphome/components/lvgl/gradient.py b/esphome/components/lvgl/gradient.py index bc89470d47..f3ded6a518 100644 --- a/esphome/components/lvgl/gradient.py +++ b/esphome/components/lvgl/gradient.py @@ -7,12 +7,13 @@ from esphome.const import ( CONF_ID, CONF_POSITION, ) +from esphome.core import ID from esphome.cpp_generator import MockObj -from .defines import CONF_GRADIENTS, LV_DITHER, LV_GRAD_DIR, add_define -from .lv_validation import lv_color, lv_fraction -from .lvcode import lv_assign -from .types import lv_gradient_t +from .defines import CONF_GRADIENTS, CONF_OPA, LV_DITHER, add_define, add_warning +from .lv_validation import lv_color, lv_percentage, opacity +from .lvcode import lv +from .types import lv_color_t, lv_gradient_t, lv_opa_t CONF_STOPS = "stops" @@ -27,14 +28,17 @@ GRADIENT_SCHEMA = cv.ensure_list( cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(lv_gradient_t), - cv.Optional(CONF_DIRECTION, default="NONE"): LV_GRAD_DIR.one_of, + cv.Required(CONF_DIRECTION): cv.one_of( + "HOR", "HORIZONTAL", "VER", "VERTICAL", upper=True + ), cv.Optional(CONF_DITHER, default="NONE"): LV_DITHER.one_of, cv.Required(CONF_STOPS): cv.All( [ cv.Schema( { cv.Required(CONF_COLOR): lv_color, - cv.Required(CONF_POSITION): lv_fraction, + cv.Optional(CONF_OPA, default=1.0): opacity, + cv.Required(CONF_POSITION): lv_percentage, } ) ], @@ -47,15 +51,31 @@ GRADIENT_SCHEMA = cv.ensure_list( async def gradients_to_code(config): max_stops = 2 + if any(CONF_DITHER in x for x in config.get(CONF_GRADIENTS, ())): + add_warning( + "The 'dither' option for gradients is not supported by LVGL 9.x and will be ignored" + ) for gradient in config.get(CONF_GRADIENTS, ()): var = MockObj(cg.new_Pvariable(gradient[CONF_ID]), "->") - max_stops = max(max_stops, len(gradient[CONF_STOPS])) - lv_assign(var.dir, await LV_GRAD_DIR.process(gradient[CONF_DIRECTION])) - lv_assign(var.dither, await LV_DITHER.process(gradient[CONF_DITHER])) - lv_assign(var.stops_count, len(gradient[CONF_STOPS])) - for index, stop in enumerate(gradient[CONF_STOPS]): - lv_assign(var.stops[index].color, await lv_color.process(stop[CONF_COLOR])) - lv_assign( - var.stops[index].frac, await lv_fraction.process(stop[CONF_POSITION]) - ) + idbase = gradient[CONF_ID].id + stops = gradient[CONF_STOPS] + max_stops = max(max_stops, len(stops)) + if gradient[CONF_DIRECTION].startswith("VER"): + lv.grad_vertical_init(var) + else: + lv.grad_horizontal_init(var) + stop_colors = cg.static_const_array( + ID(idbase + "_colors_", type=lv_color_t), + [await lv_color.process(x[CONF_COLOR]) for x in stops], + ) + stop_opacities = cg.static_const_array( + ID(idbase + "_opacities_", type=lv_opa_t), + [await opacity.process(x[CONF_OPA]) for x in stops], + ) + stop_positions = cg.static_const_array( + ID(idbase + "_positions_", type=cg.uint8), + [await lv_percentage.process(x[CONF_POSITION]) for x in stops], + ) + lv.grad_init_stops(var, stop_colors, stop_opacities, stop_positions, len(stops)) + add_define("LV_GRADIENT_MAX_STOPS", max_stops) diff --git a/esphome/components/lvgl/keypads.py b/esphome/components/lvgl/keypads.py index 5e2953d57f..7d8b3dd128 100644 --- a/esphome/components/lvgl/keypads.py +++ b/esphome/components/lvgl/keypads.py @@ -67,7 +67,7 @@ async def keypads_to_code(var, config, default_group): lv_assign(group, lv_expr.group_create()) else: group = default_group - lv.indev_set_group(lv_expr.indev_drv_register(listener.get_drv()), group) + lv.indev_set_group(listener.get_drv(), group) async def initial_focus_to_code(config): diff --git a/esphome/components/lvgl/layout.py b/esphome/components/lvgl/layout.py index b27a0b54a2..46026852af 100644 --- a/esphome/components/lvgl/layout.py +++ b/esphome/components/lvgl/layout.py @@ -88,8 +88,8 @@ grid_spec = cv.Any(size, LvConstant("LV_GRID_", "CONTENT").one_of, grid_free_spa GRID_CELL_SCHEMA = { cv.Optional(CONF_GRID_CELL_ROW_POS): cv.positive_int, cv.Optional(CONF_GRID_CELL_COLUMN_POS): cv.positive_int, - cv.Optional(CONF_GRID_CELL_ROW_SPAN, default=1): cv.positive_int, - cv.Optional(CONF_GRID_CELL_COLUMN_SPAN, default=1): cv.positive_int, + cv.Optional(CONF_GRID_CELL_ROW_SPAN): cv.int_range(min=1), + cv.Optional(CONF_GRID_CELL_COLUMN_SPAN): cv.int_range(min=1), cv.Optional(CONF_GRID_CELL_X_ALIGN): grid_alignments, cv.Optional(CONF_GRID_CELL_Y_ALIGN): grid_alignments, } @@ -198,12 +198,8 @@ class GridLayout(Layout): { cv.Optional(CONF_GRID_CELL_ROW_POS): cv.positive_int, cv.Optional(CONF_GRID_CELL_COLUMN_POS): cv.positive_int, - cv.Optional( - CONF_GRID_CELL_ROW_SPAN, default=1 - ): cv.positive_int, - cv.Optional( - CONF_GRID_CELL_COLUMN_SPAN, default=1 - ): cv.positive_int, + cv.Optional(CONF_GRID_CELL_ROW_SPAN): cv.int_range(min=1), + cv.Optional(CONF_GRID_CELL_COLUMN_SPAN): cv.int_range(min=1), cv.Optional( CONF_GRID_CELL_X_ALIGN, default="center" ): grid_alignments, @@ -231,8 +227,8 @@ class GridLayout(Layout): { cv.Optional(CONF_GRID_CELL_ROW_POS): cv.positive_int, cv.Optional(CONF_GRID_CELL_COLUMN_POS): cv.positive_int, - cv.Optional(CONF_GRID_CELL_ROW_SPAN, default=1): cv.positive_int, - cv.Optional(CONF_GRID_CELL_COLUMN_SPAN, default=1): cv.positive_int, + cv.Optional(CONF_GRID_CELL_ROW_SPAN): cv.int_range(min=1), + cv.Optional(CONF_GRID_CELL_COLUMN_SPAN): cv.int_range(min=1), cv.Optional(CONF_GRID_CELL_X_ALIGN): grid_alignments, cv.Optional(CONF_GRID_CELL_Y_ALIGN): grid_alignments, }, @@ -299,11 +295,13 @@ class GridLayout(Layout): w[CONF_GRID_CELL_ROW_POS] = row w[CONF_GRID_CELL_COLUMN_POS] = column - for i in range(w[CONF_GRID_CELL_ROW_SPAN]): - for j in range(w[CONF_GRID_CELL_COLUMN_SPAN]): + row_span = w.get(CONF_GRID_CELL_ROW_SPAN, 1) + column_span = w.get(CONF_GRID_CELL_COLUMN_SPAN, 1) + for i in range(row_span): + for j in range(column_span): if row + i >= rows or column + j >= columns: raise cv.Invalid( - f"Cell at {row}/{column} span {w[CONF_GRID_CELL_ROW_SPAN]}x{w[CONF_GRID_CELL_COLUMN_SPAN]} " + f"Cell at {row}/{column} span {row_span}x{column_span} " f"exceeds grid size {rows}x{columns}", [CONF_WIDGETS, index], ) diff --git a/esphome/components/lvgl/light/lvgl_light.h b/esphome/components/lvgl/light/lvgl_light.h index 569f9a03c0..7309df9763 100644 --- a/esphome/components/lvgl/light/lvgl_light.h +++ b/esphome/components/lvgl/light/lvgl_light.h @@ -38,7 +38,7 @@ class LVLight : public light::LightOutput { void set_value_(lv_color_t value) { lv_led_set_color(this->obj_, value); lv_led_on(this->obj_); - lv_event_send(this->obj_, lv_api_event, nullptr); + lv_obj_send_event(this->obj_, lv_api_event, nullptr); } lv_obj_t *obj_{}; optional<lv_color_t> initial_value_{}; diff --git a/esphome/components/lvgl/lv_validation.py b/esphome/components/lvgl/lv_validation.py index 3c1838219c..503730098e 100644 --- a/esphome/components/lvgl/lv_validation.py +++ b/esphome/components/lvgl/lv_validation.py @@ -30,6 +30,7 @@ from .defines import ( LV_FONTS, LValidator, LvConstant, + StaticCastExpression, call_lambda, literal, ) @@ -40,22 +41,28 @@ from .helpers import ( lv_fonts_used, requires_component, ) -from .types import lv_gradient_t +from .types import lv_gradient_t, lv_opa_t -opacity_consts = LvConstant("LV_OPA_", "TRANSP", "COVER") +LV_OPA = LvConstant("LV_OPA_", "TRANSP", "COVER") @schema_extractor("one_of") def opacity_validator(value): if value == SCHEMA_EXTRACT: - return opacity_consts.choices - value = cv.Any(cv.percentage, opacity_consts.one_of)(value) - if isinstance(value, float): - return int(value * 255) - return value + return LV_OPA.choices + value = cv.Any(cv.percentage, LV_OPA.one_of)(value) + if value == str(LV_OPA.COVER): + value = 1.0 + if value == str(LV_OPA.TRANSP): + value = 0.0 + return cv.float_range(0.0, 1.0)(value) -opacity = LValidator(opacity_validator, uint32, retmapper=literal) +opacity = LValidator( + opacity_validator, + lv_opa_t, + retmapper=lambda opa: StaticCastExpression(cg.uint8, opa * 255.0), +) COLOR_NAMES = { "aliceblue": 0xF0F8FF, @@ -244,7 +251,17 @@ def option_string(value): return value -lv_color = LValidator(color, ty.lv_color_t, retmapper=color_retmapper) +class LvColor(LValidator): + def __init__(self): + super().__init__(color, ty.lv_color_t, retmapper=color_retmapper) + + def __getattr__(self, item): + if item in COLOR_NAMES: + return color_retmapper(COLOR_NAMES[item]) + raise AttributeError(item) + + +lv_color = LvColor() def pixels_or_percent_validator(value): @@ -252,16 +269,17 @@ def pixels_or_percent_validator(value): if value == SCHEMA_EXTRACT: return ["pixels", "..%"] if isinstance(value, str) and value.lower().endswith("px"): - value = cv.int_(value[:-2]) + return cv.int_(value[:-2]) if isinstance(value, str) and re.match(r"^lv_pct\((\d+)\)$", value): - return value - value = cv.Any(cv.int_, cv.percentage)(value) - if isinstance(value, int): - return value - return f"lv_pct({int(value * 100)})" + return int(value[6:-1]) / 100.0 + return cv.Any(cv.int_, cv.possibly_negative_percentage)(value) -pixels_or_percent = LValidator(pixels_or_percent_validator, uint32, retmapper=literal) +pixels_or_percent = LValidator( + pixels_or_percent_validator, + uint32, + retmapper=lambda x: x if isinstance(x, int) else literal(f"lv_pct({int(x * 100)})"), +) def pixels_validator(value): @@ -282,15 +300,11 @@ def padding_validator(value): padding = LValidator(padding_validator, int32, retmapper=literal) -def zoom_validator(value): +def scale_validator(value): return cv.float_range(0.1, 10.0)(value) -def zoom_retmapper(value): - return int(value * 256) - - -zoom = LValidator(zoom_validator, uint32, retmapper=zoom_retmapper) +scale = LValidator(scale_validator, uint32, retmapper=lambda x: int(x * 256)) def angle(value): @@ -321,17 +335,23 @@ def size_validator(value): return pixels_or_percent_validator(value) -size = LValidator(size_validator, uint32, retmapper=literal) +size = LValidator( + size_validator, + uint32, + retmapper=lambda x: ( + literal(x) if isinstance(x, str) else pixels_or_percent.retmapper(x) + ), +) -radius_consts = LvConstant("LV_RADIUS_", "CIRCLE") +LV_RADIUS = LvConstant("LV_RADIUS_", "CIRCLE") @schema_extractor("one_of") def fraction_validator(value): if value == SCHEMA_EXTRACT: - return radius_consts.choices - value = cv.Any(size, cv.percentage, radius_consts.one_of)(value) + return LV_RADIUS.choices + value = cv.Any(size, cv.percentage, LV_RADIUS.one_of)(value) if isinstance(value, float): return int(value * 255) return value @@ -374,12 +394,6 @@ lv_image_list = LValidator( lv_bool = LValidator(cv.boolean, cg.bool_, retmapper=literal) -def lv_pct(value: int | float): - if isinstance(value, float): - value = int(value * 100) - return literal(f"lv_pct({value})") - - def lvms_validator_(value): if value == "never": value = "2147483647ms" @@ -424,30 +438,28 @@ class TextValidator(LValidator): if time_format := value.get(CONF_TIME_FORMAT): source = value[CONF_TIME] if isinstance(source, Lambda): - time_format = cpp_string_escape(time_format) - return cg.RawExpression( + source = MockObj( call_lambda( await cg.process_lambda(source, args, return_type=ESPTime) ) - + f".strftime({time_format}).c_str()" ) # must be an ID - source = await cg.get_variable(source) - return source.now().strftime(time_format).c_str() + else: + source = (await cg.get_variable(source)).now() + return source.strftime(time_format).c_str() if isinstance(value, Lambda): value = call_lambda( await cg.process_lambda(value, args, return_type=self.rtype) ) + textvalue = str(value) # Was the lambda call reduced to a string? - if value.endswith("c_str()") or ( - value.endswith('"') and value.startswith('"') + if textvalue.endswith("c_str()") or ( + textvalue.endswith('"') and textvalue.startswith('"') ): - pass - else: - # Either a std::string or a lambda call returning that. We need const char* - value = f"({value}).c_str()" - return cg.RawExpression(value) + return value + # Either a std::string or a lambda call returning that. We need const char* + return MockObj(f"({value}).c_str()") return await super().process(value, args) @@ -455,21 +467,24 @@ lv_text = TextValidator() lv_float = LValidator(cv.float_, cg.float_) lv_int = LValidator(cv.int_, cg.int_) lv_positive_int = LValidator(cv.positive_int, cg.int_) -lv_brightness = LValidator(cv.percentage, cg.float_, retmapper=lambda x: int(x * 255)) -def gradient_mapper(value): - return MockObj(value) +def _percentage_validator(value): + value = cv.Any(cv.percentage, cv.float_range(0.0, 1.0), cv.int_range(0, 255))(value) + if isinstance(value, int): + return value / 255.0 + return value -def gradient_validator(value): - return cv.use_id(lv_gradient_t)(value) +lv_percentage = LValidator( + _percentage_validator, cg.float_, retmapper=lambda x: int(x * 255) +) lv_gradient = LValidator( - validator=gradient_validator, + validator=cv.use_id(lv_gradient_t), rtype=lv_gradient_t, - retmapper=gradient_mapper, + retmapper=MockObj, ) diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index b79d1e88dd..146b261f26 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -168,6 +168,9 @@ class LambdaContext(CodeContext): def get_automation_parameters(self) -> list[tuple[SafeExpType, str]]: return self.parameters + def get_parameter(self, index: int): + return literal(self.parameters[index][1]) + async def __aenter__(self): await super().__aenter__() add_line_marks(self.where) @@ -250,10 +253,14 @@ class MockLv: A mock object that can be used to generate LVGL calls. """ + # Mapping for LVGL 9 + ATTR_MAP = {"event_send": "obj_send_event", "dither": "bg_dither_mode"} + def __init__(self, base): self.base = base def __getattr__(self, attr: str) -> "MockLv": + attr = MockLv.ATTR_MAP.get(attr, attr) return MockLv(f"{self.base}{attr}") def append(self, expression): @@ -307,6 +314,7 @@ class ReturnStatement(ExpressionStatement): class LvExpr(MockLv): def __getattr__(self, attr: str) -> "MockLv": + attr = MockLv.ATTR_MAP.get(attr, attr) return LvExpr(f"{self.base}{attr}") def append(self, expression): diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index 5400054bb1..b1618f77c4 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -2,16 +2,21 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#include "lvgl_hal.h" #include "lvgl_esphome.h" +#include "core/lv_global.h" +#include "core/lv_obj_class_private.h" + #include <numeric> -namespace esphome { -namespace lvgl { +static void *lv_alloc_draw_buf(size_t size, bool internal); +static void *draw_buf_alloc_cb(size_t size, lv_color_format_t color_format) { return lv_alloc_draw_buf(size, false); }; + +namespace esphome::lvgl { static const char *const TAG = "lvgl"; -static const size_t MIN_BUFFER_FRAC = 8; +static const size_t MIN_BUFFER_FRAC = 8; // buffer must be at least 1/8 of the display size +static const size_t MIN_BUFFER_SIZE = 2048; // Sensible minimum buffer size static const char *const EVENT_NAMES[] = { "NONE", @@ -61,7 +66,14 @@ static const char *const EVENT_NAMES[] = { "GET_SELF_SIZE", }; -std::string lv_event_code_name_for(uint8_t event_code) { +static const unsigned LOG_LEVEL_MAP[] = { + ESPHOME_LOG_LEVEL_DEBUG, ESPHOME_LOG_LEVEL_INFO, ESPHOME_LOG_LEVEL_WARN, + ESPHOME_LOG_LEVEL_ERROR, ESPHOME_LOG_LEVEL_ERROR, ESPHOME_LOG_LEVEL_NONE, + +}; + +std::string lv_event_code_name_for(lv_event_t *event) { + auto event_code = lv_event_get_code(event); if (event_code < sizeof(EVENT_NAMES) / sizeof(EVENT_NAMES[0])) { return EVENT_NAMES[event_code]; } @@ -71,11 +83,12 @@ std::string lv_event_code_name_for(uint8_t event_code) { return buf; } -static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { +static void rounder_cb(lv_event_t *event) { + auto *comp = static_cast<LvglComponent *>(lv_event_get_user_data(event)); + auto *area = static_cast<lv_area_t *>(lv_event_get_param(event)); // cater for display driver chips with special requirements for bounds of partial // draw areas. Extend the draw area to satisfy: // * Coordinates must be a multiple of draw_rounding - auto *comp = static_cast<LvglComponent *>(disp_drv->user_data); auto draw_rounding = comp->draw_rounding; // round down the start coordinates area->x1 = area->x1 / draw_rounding * draw_rounding; @@ -85,15 +98,14 @@ static void rounder_cb(lv_disp_drv_t *disp_drv, lv_area_t *area) { area->y2 = (area->y2 + draw_rounding) / draw_rounding * draw_rounding - 1; } -void LvglComponent::monitor_cb(lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px) { - ESP_LOGVV(TAG, "Draw end: %" PRIu32 " pixels in %" PRIu32 " ms", px, time); - auto *comp = static_cast<LvglComponent *>(disp_drv->user_data); +void LvglComponent::render_end_cb(lv_event_t *event) { + auto *comp = static_cast<LvglComponent *>(lv_event_get_user_data(event)); comp->draw_end_(); } -void LvglComponent::render_start_cb(lv_disp_drv_t *disp_drv) { +void LvglComponent::render_start_cb(lv_event_t *event) { ESP_LOGVV(TAG, "Draw start"); - auto *comp = static_cast<LvglComponent *>(disp_drv->user_data); + auto *comp = static_cast<LvglComponent *>(lv_event_get_user_data(event)); comp->draw_start_(); } @@ -106,16 +118,15 @@ void LvglComponent::dump_config() { " Buffer size: %zu%%\n" " Rotation: %d\n" " Draw rounding: %d", - this->disp_drv_.hor_res, this->disp_drv_.ver_res, 100 / this->buffer_frac_, this->rotation, - (int) this->draw_rounding); + this->width_, this->height_, 100 / this->buffer_frac_, this->rotation, (int) this->draw_rounding); } void LvglComponent::set_paused(bool paused, bool show_snow) { this->paused_ = paused; this->show_snow_ = show_snow; - if (!paused && lv_scr_act() != nullptr) { - lv_disp_trig_activity(this->disp_); // resets the inactivity time - lv_obj_invalidate(lv_scr_act()); + if (!paused && lv_screen_active() != nullptr) { + lv_display_trigger_activity(this->disp_); // resets the inactivity time + lv_obj_invalidate(lv_screen_active()); } if (paused && this->pause_callback_ != nullptr) this->pause_callback_->trigger(); @@ -125,6 +136,14 @@ void LvglComponent::set_paused(bool paused, bool show_snow) { void LvglComponent::esphome_lvgl_init() { lv_init(); + // override draw buf alloc to ensure proper alignment for PPA + LV_GLOBAL_DEFAULT()->draw_buf_handlers.buf_malloc_cb = draw_buf_alloc_cb; + LV_GLOBAL_DEFAULT()->draw_buf_handlers.buf_free_cb = lv_free_core; + LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers.buf_malloc_cb = draw_buf_alloc_cb; + LV_GLOBAL_DEFAULT()->image_cache_draw_buf_handlers.buf_free_cb = lv_free_core; + LV_GLOBAL_DEFAULT()->font_draw_buf_handlers.buf_malloc_cb = draw_buf_alloc_cb; + LV_GLOBAL_DEFAULT()->font_draw_buf_handlers.buf_free_cb = lv_free_core; + lv_tick_set_cb([] { return millis(); }); lv_update_event = static_cast<lv_event_code_t>(lv_event_register_id()); lv_api_event = static_cast<lv_event_code_t>(lv_event_register_id()); } @@ -149,7 +168,7 @@ void LvglComponent::add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_ev void LvglComponent::add_page(LvPageType *page) { this->pages_.push_back(page); page->set_parent(this); - lv_disp_set_default(this->disp_); + lv_display_set_default(this->disp_); page->setup(this->pages_.size() - 1); } @@ -187,13 +206,13 @@ void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) { size_t LvglComponent::get_current_page() const { return this->current_page_; } bool LvPageType::is_showing() const { return this->parent_->get_current_page() == this->index; } -void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { +void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_data *ptr) { auto width = lv_area_get_width(area); auto height = lv_area_get_height(area); auto height_rounded = (height + this->draw_rounding - 1) / this->draw_rounding * this->draw_rounding; auto x1 = area->x1; auto y1 = area->y1; - lv_color_t *dst = this->rotate_buf_; + lv_color_data *dst = reinterpret_cast<lv_color_data *>(this->rotate_buf_); switch (this->rotation) { case display::DISPLAY_ROTATION_90_DEGREES: for (lv_coord_t x = height; x-- != 0;) { @@ -202,7 +221,7 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { } } y1 = x1; - x1 = this->disp_drv_.ver_res - area->y1 - height; + x1 = this->height_ - area->y1 - height; height = width; width = height_rounded; break; @@ -213,8 +232,8 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { dst[y * width + x] = *ptr++; } } - x1 = this->disp_drv_.hor_res - x1 - width; - y1 = this->disp_drv_.ver_res - y1 - height; + x1 = this->width_ - x1 - width; + y1 = this->height_ - y1 - height; break; case display::DISPLAY_ROTATION_270_DEGREES: @@ -224,7 +243,7 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { } } x1 = y1; - y1 = this->disp_drv_.hor_res - area->x1 - width; + y1 = this->width_ - area->x1 - width; height = width; width = height_rounded; break; @@ -234,20 +253,19 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_t *ptr) { break; } for (auto *display : this->displays_) { - ESP_LOGV(TAG, "draw buffer x1=%d, y1=%d, width=%d, height=%d", x1, y1, width, height); display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) dst, display::COLOR_ORDER_RGB, LV_BITNESS, - LV_COLOR_16_SWAP); + this->big_endian_); } } -void LvglComponent::flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { +void LvglComponent::flush_cb_(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *color_p) { if (!this->is_paused()) { auto now = millis(); - this->draw_buffer_(area, color_p); - ESP_LOGVV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area), - lv_area_get_height(area), (int) (millis() - now)); + this->draw_buffer_(area, reinterpret_cast<lv_color_data *>(color_p)); + ESP_LOGV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area), + lv_area_get_height(area), (int) (millis() - now)); } - lv_disp_flush_ready(disp_drv); + lv_display_flush_ready(disp_drv); } IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeout) : timeout_(std::move(timeout)) { @@ -264,14 +282,14 @@ IdleTrigger::IdleTrigger(LvglComponent *parent, TemplatableValue<uint32_t> timeo #ifdef USE_LVGL_TOUCHSCREEN LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_repeat_time, LvglComponent *parent) { this->set_parent(parent); - lv_indev_drv_init(&this->drv_); - this->drv_.disp = parent->get_disp(); - this->drv_.long_press_repeat_time = long_press_repeat_time; - this->drv_.long_press_time = long_press_time; - this->drv_.type = LV_INDEV_TYPE_POINTER; - this->drv_.user_data = this; - this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) { - auto *l = static_cast<LVTouchListener *>(d->user_data); + this->drv_ = lv_indev_create(); + lv_indev_set_type(this->drv_, LV_INDEV_TYPE_POINTER); + lv_indev_set_disp(this->drv_, parent->get_disp()); + lv_indev_set_long_press_time(this->drv_, long_press_time); + // long press repeat time TBD + lv_indev_set_user_data(this->drv_, this); + lv_indev_set_read_cb(this->drv_, [](lv_indev_t *d, lv_indev_data_t *data) { + auto *l = static_cast<LVTouchListener *>(lv_indev_get_user_data(d)); if (l->touch_pressed_) { data->point.x = l->touch_point_.x; data->point.y = l->touch_point_.y; @@ -279,7 +297,7 @@ LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_r } else { data->state = LV_INDEV_STATE_RELEASED; } - }; + }); } void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) { @@ -289,21 +307,78 @@ void LVTouchListener::update(const touchscreen::TouchPoints_t &tpoints) { } #endif // USE_LVGL_TOUCHSCREEN +#ifdef USE_LVGL_METER + +int16_t lv_get_needle_angle_for_value(lv_obj_t *obj, int value) { + auto *scale = lv_obj_get_parent(obj); + auto min_value = lv_scale_get_range_min_value(scale); + return ((value - min_value) * lv_scale_get_angle_range(scale) / (lv_scale_get_range_max_value(scale) - min_value) + + lv_scale_get_rotation((scale))) % + 360; +} + +void IndicatorLine::set_obj(lv_obj_t *lv_obj) { + LvCompound::set_obj(lv_obj); + lv_line_set_points(lv_obj, this->points_, 2); + lv_obj_add_event_cb( + lv_obj_get_parent(obj), + [](lv_event_t *e) { + auto *indicator = static_cast<IndicatorLine *>(lv_event_get_user_data(e)); + indicator->update_length_(); + ESP_LOGV(TAG, "Updated length, value = %d", indicator->angle_); + }, + LV_EVENT_SIZE_CHANGED, this); +} + +void IndicatorLine::set_value(int value) { + auto angle = lv_get_needle_angle_for_value(this->obj, value); + if (angle != this->angle_) { + this->angle_ = angle; + this->update_length_(); + } +} + +void IndicatorLine::update_length_() { + uint32_t actual_needle_length; + auto radius = lv_obj_get_width(lv_obj_get_parent(this->obj)) / 2; + auto length = lv_obj_get_style_length(this->obj, LV_PART_MAIN); + auto radial_offset = lv_obj_get_style_radial_offset(this->obj, LV_PART_MAIN); + if (LV_COORD_IS_PCT(radial_offset)) { + radial_offset = radius * LV_COORD_GET_PCT(radial_offset) / 100; + } + if (LV_COORD_IS_PCT(length)) { + actual_needle_length = radius * LV_COORD_GET_PCT(length) / 100; + } else if (length < 0) { + actual_needle_length = radius + length; + } else { + actual_needle_length = length; + } + auto x = lv_trigo_cos(this->angle_) / 32768.0f; + auto y = lv_trigo_sin(this->angle_) / 32768.0f; + this->points_[0].x = radius + radial_offset * x; + this->points_[0].y = radius + radial_offset * y; + this->points_[1].x = x * actual_needle_length + radius; + this->points_[1].y = y * actual_needle_length + radius; + lv_obj_refresh_self_size(this->obj); + lv_obj_invalidate(this->obj); +} +#endif + #ifdef USE_LVGL_KEY_LISTENER -LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt) { - lv_indev_drv_init(&this->drv_); - this->drv_.type = type; - this->drv_.user_data = this; - this->drv_.long_press_time = lpt; - this->drv_.long_press_repeat_time = lprt; - this->drv_.read_cb = [](lv_indev_drv_t *d, lv_indev_data_t *data) { - auto *l = static_cast<LVEncoderListener *>(d->user_data); +LVEncoderListener::LVEncoderListener(lv_indev_type_t type, uint16_t long_press_time, uint16_t long_press_repeat_time) { + this->drv_ = lv_indev_create(); + lv_indev_set_type(this->drv_, type); + lv_indev_set_long_press_time(this->drv_, long_press_time); + lv_indev_set_long_press_repeat_time(this->drv_, long_press_repeat_time); + lv_indev_set_user_data(this->drv_, this); + lv_indev_set_read_cb(this->drv_, [](lv_indev_t *d, lv_indev_data_t *data) { + auto *l = static_cast<LVEncoderListener *>(lv_indev_get_user_data(d)); data->state = l->pressed_ ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; data->key = l->key_; data->enc_diff = (int16_t) (l->count_ - l->last_count_); l->last_count_ = l->count_; data->continue_reading = false; - }; + }); } #endif // USE_LVGL_KEY_LISTENER @@ -325,7 +400,7 @@ void LvSelectable::set_selected_text(const std::string &text, lv_anim_enable_t a auto index = std::find(this->options_.begin(), this->options_.end(), text); if (index != this->options_.end()) { this->set_selected_index(index - this->options_.begin(), anim); - lv_event_send(this->obj, lv_api_event, nullptr); + lv_obj_send_event(this->obj, lv_api_event, nullptr); } } @@ -335,7 +410,7 @@ void LvSelectable::set_options(std::vector<std::string> options) { index = options.size() - 1; this->options_ = std::move(options); this->set_option_string(join_string(this->options_).c_str()); - lv_event_send(this->obj, LV_EVENT_REFRESH, nullptr); + lv_obj_send_event(this->obj, LV_EVENT_REFRESH, nullptr); this->set_selected_index(index, LV_ANIM_OFF); } #endif // USE_LVGL_DROPDOWN || LV_USE_ROLLER @@ -346,17 +421,17 @@ void LvButtonMatrixType::set_obj(lv_obj_t *lv_obj) { lv_obj_add_event_cb( lv_obj, [](lv_event_t *event) { - auto *self = static_cast<LvButtonMatrixType *>(event->user_data); + auto *self = static_cast<LvButtonMatrixType *>(lv_event_get_user_data(event)); if (self->key_callback_.size() == 0) return; - auto key_idx = lv_btnmatrix_get_selected_btn(self->obj); - if (key_idx == LV_BTNMATRIX_BTN_NONE) + auto key_idx = lv_buttonmatrix_get_selected_button(self->obj); + if (key_idx == LV_BUTTONMATRIX_BUTTON_NONE) return; if (self->key_map_.count(key_idx) != 0) { self->send_key_(self->key_map_[key_idx]); return; } - const auto *str = lv_btnmatrix_get_btn_text(self->obj, key_idx); + const auto *str = lv_buttonmatrix_get_button_text(self->obj, key_idx); auto len = strlen(str); while (len--) self->send_key_(*str++); @@ -376,14 +451,14 @@ void LvKeyboardType::set_obj(lv_obj_t *lv_obj) { lv_obj_add_event_cb( lv_obj, [](lv_event_t *event) { - auto *self = static_cast<LvKeyboardType *>(event->user_data); + auto *self = static_cast<LvKeyboardType *>(lv_event_get_user_data(event)); if (self->key_callback_.size() == 0) return; - auto key_idx = lv_btnmatrix_get_selected_btn(self->obj); - if (key_idx == LV_BTNMATRIX_BTN_NONE) + auto key_idx = lv_buttonmatrix_get_selected_button(self->obj); + if (key_idx == LV_BUTTONMATRIX_BUTTON_NONE) return; - const char *txt = lv_btnmatrix_get_btn_text(self->obj, key_idx); + const char *txt = lv_buttonmatrix_get_button_text(self->obj, key_idx); if (txt == nullptr) return; for (const auto *kb_special_key : KB_SPECIAL_KEYS) { @@ -419,33 +494,29 @@ bool LvglComponent::is_paused() const { } void LvglComponent::write_random_() { - int iterations = 6 - lv_disp_get_inactive_time(this->disp_) / 60000; + int iterations = 6 - lv_display_get_inactive_time(this->disp_) / 60000; if (iterations <= 0) iterations = 1; while (iterations-- != 0) { - auto col = random_uint32() % this->disp_drv_.hor_res; + int32_t col = random_uint32() % this->width_; col = col / this->draw_rounding * this->draw_rounding; - auto row = random_uint32() % this->disp_drv_.ver_res; + int32_t row = random_uint32() % this->height_; row = row / this->draw_rounding * this->draw_rounding; - auto size = ((random_uint32() % 32) / this->draw_rounding + 2) * this->draw_rounding - 1; - // clamp size so the square fits within the draw buffer - if ((size + 1) * (size + 1) > this->draw_buf_.size) - size = static_cast<decltype(size)>(sqrtf(this->draw_buf_.size)) - 1; - lv_area_t area; - area.x1 = col; - area.y1 = row; - area.x2 = col + size; - area.y2 = row + size; - if (area.x2 >= this->disp_drv_.hor_res) - area.x2 = this->disp_drv_.hor_res - 1; - if (area.y2 >= this->disp_drv_.ver_res) - area.y2 = this->disp_drv_.ver_res - 1; + // size will be between 8 and 32, and a multiple of draw_rounding + int32_t size = (random_uint32() % 25 + 8) / this->draw_rounding * this->draw_rounding; + lv_area_t area{col, row, col + size - 1, row + size - 1}; + // clip to display bounds just in case + if (area.x2 >= this->width_) + area.x2 = this->width_ - 1; + if (area.y2 >= this->height_) + area.y2 = this->height_ - 1; + // line_len can't exceed 1024, and minimum buffer size is 2048, so this won't overflow the buffer size_t line_len = lv_area_get_width(&area) * lv_area_get_height(&area) / 2; for (size_t i = 0; i != line_len; i++) { - ((uint32_t *) (this->draw_buf_.buf1))[i] = random_uint32(); + ((uint32_t *) (this->draw_buf_))[i] = random_uint32(); } - this->draw_buffer_(&area, (lv_color_t *) this->draw_buf_.buf1); + this->draw_buffer_(&area, (lv_color_data *) this->draw_buf_); } } @@ -477,38 +548,32 @@ LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buf full_refresh_(full_refresh), resume_on_input_(resume_on_input), update_when_display_idle_(update_when_display_idle) { - lv_disp_draw_buf_init(&this->draw_buf_, nullptr, nullptr, 0); - lv_disp_drv_init(&this->disp_drv_); - this->disp_drv_.draw_buf = &this->draw_buf_; - this->disp_drv_.user_data = this; - this->disp_drv_.full_refresh = this->full_refresh_; - this->disp_drv_.flush_cb = static_flush_cb; - this->disp_drv_.rounder_cb = rounder_cb; - this->disp_ = lv_disp_drv_register(&this->disp_drv_); + this->disp_ = lv_display_create(240, 240); } void LvglComponent::setup() { auto *display = this->displays_[0]; auto rounding = this->draw_rounding; // cater for displays with dimensions that don't divide by the required rounding + this->width_ = display->get_width(); + this->height_ = display->get_height(); auto width = (display->get_width() + rounding - 1) / rounding * rounding; auto height = (display->get_height() + rounding - 1) / rounding * rounding; auto frac = this->buffer_frac_; if (frac == 0) frac = 1; - size_t buffer_pixels = width * height / frac; - auto buf_bytes = buffer_pixels * LV_COLOR_DEPTH / 8; + auto buf_bytes = clamp_at_least(width * height / frac * LV_COLOR_DEPTH / 8, MIN_BUFFER_SIZE); void *buffer = nullptr; + // for small buffers, try to allocate in internal memory first to improve performance if (this->buffer_frac_ >= MIN_BUFFER_FRAC / 2) - buffer = malloc(buf_bytes); // NOLINT + buffer = lv_alloc_draw_buf(buf_bytes, true); // NOLINT if (buffer == nullptr) - buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT + buffer = lv_alloc_draw_buf(buf_bytes, false); // NOLINT // if specific buffer size not set and can't get 100%, try for a smaller one if (buffer == nullptr && this->buffer_frac_ == 0) { frac = MIN_BUFFER_FRAC; - buffer_pixels /= MIN_BUFFER_FRAC; buf_bytes /= MIN_BUFFER_FRAC; - buffer = lv_custom_mem_alloc(buf_bytes); // NOLINT + buffer = lv_alloc_draw_buf(buf_bytes, false); // NOLINT } this->buffer_frac_ = frac; if (buffer == nullptr) { @@ -516,13 +581,17 @@ void LvglComponent::setup() { this->mark_failed(); return; } - lv_disp_draw_buf_init(&this->draw_buf_, buffer, nullptr, buffer_pixels); - this->disp_drv_.hor_res = display->get_width(); - this->disp_drv_.ver_res = display->get_height(); - lv_disp_drv_update(this->disp_, &this->disp_drv_); + this->draw_buf_ = static_cast<uint8_t *>(buffer); + lv_display_set_resolution(this->disp_, this->width_, this->height_); + lv_display_set_color_format(this->disp_, LV_COLOR_FORMAT_RGB565); + lv_display_set_flush_cb(this->disp_, static_flush_cb); + lv_display_set_user_data(this->disp_, this); + lv_display_add_event_cb(this->disp_, rounder_cb, LV_EVENT_INVALIDATE_AREA, this); + lv_display_set_buffers(this->disp_, this->draw_buf_, nullptr, buf_bytes, + this->full_refresh_ ? LV_DISPLAY_RENDER_MODE_FULL : LV_DISPLAY_RENDER_MODE_PARTIAL); this->rotation = display->get_rotation(); if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) { - this->rotate_buf_ = static_cast<lv_color_t *>(lv_custom_mem_alloc(buf_bytes)); // NOLINT + this->rotate_buf_ = static_cast<lv_color_t *>(lv_alloc_draw_buf(buf_bytes, false)); // NOLINT if (this->rotate_buf_ == nullptr) { this->status_set_error(LOG_STR("Memory allocation failure")); this->mark_failed(); @@ -530,26 +599,28 @@ void LvglComponent::setup() { } } if (this->draw_start_callback_ != nullptr) { - this->disp_drv_.render_start_cb = render_start_cb; + lv_display_add_event_cb(this->disp_, render_start_cb, LV_EVENT_RENDER_START, this); } if (this->draw_end_callback_ != nullptr || this->update_when_display_idle_) { - this->disp_drv_.monitor_cb = monitor_cb; + lv_display_add_event_cb(this->disp_, render_end_cb, LV_EVENT_REFR_READY, this); } #if LV_USE_LOG - lv_log_register_print_cb([](const char *buf) { + lv_log_register_print_cb([](lv_log_level_t level, const char *buf) { auto next = strchr(buf, ')'); if (next != nullptr) buf = next + 1; while (isspace(*buf)) buf++; - esp_log_printf_(LVGL_LOG_LEVEL, TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); + if (level >= sizeof(LOG_LEVEL_MAP) / sizeof(LOG_LEVEL_MAP[0])) + level = sizeof(LOG_LEVEL_MAP) / sizeof(LOG_LEVEL_MAP[0]) - 1; + esp_log_printf_(LOG_LEVEL_MAP[level], TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); }); #endif // Rotation will be handled by our drawing function, so reset the display rotation. for (auto *disp : this->displays_) disp->set_rotation(display::DISPLAY_ROTATION_0_DEGREES); this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0); - lv_disp_trig_activity(this->disp_); + lv_display_trigger_activity(this->disp_); } void LvglComponent::update() { @@ -557,7 +628,7 @@ void LvglComponent::update() { if (this->is_paused()) { return; } - this->idle_callbacks_.call(lv_disp_get_inactive_time(this->disp_)); + this->idle_callbacks_.call(lv_display_get_inactive_time(this->disp_)); } void LvglComponent::loop() { @@ -565,41 +636,129 @@ void LvglComponent::loop() { if (this->paused_ && this->show_snow_) this->write_random_(); } else { - lv_timer_handler_run_in_period(5); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + auto now = millis(); + lv_timer_handler(); + auto elapsed = millis() - now; + if (elapsed > 15) { + ESP_LOGV(TAG, "lv_timer_handler took %dms", (int) (millis() - now)); + } +#else + lv_timer_handler(); +#endif } } #ifdef USE_LVGL_ANIMIMG void lv_animimg_stop(lv_obj_t *obj) { - auto *animg = (lv_animimg_t *) obj; - int32_t duration = animg->anim.time; + int32_t duration = lv_animimg_get_duration(obj); lv_animimg_set_duration(obj, 0); lv_animimg_start(obj); lv_animimg_set_duration(obj, duration); } #endif -void LvglComponent::static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - reinterpret_cast<LvglComponent *>(disp_drv->user_data)->flush_cb_(disp_drv, area, color_p); +void LvglComponent::static_flush_cb(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *color_p) { + reinterpret_cast<LvglComponent *>(lv_display_get_user_data(disp_drv))->flush_cb_(disp_drv, area, color_p); } -} // namespace lvgl -} // namespace esphome -size_t lv_millis(void) { return esphome::millis(); } +#ifdef USE_LVGL_SCALE +/** + * Function to apply colors to ticks based on position + * @param e The event data + * @param color_start The color to apply to the first tick + * @param color_end The color to apply to the last tick + */ +void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, + lv_color_t color_end, bool local) { + auto *scale = static_cast<lv_obj_t *>(lv_event_get_target(e)); + lv_draw_task_t *task = lv_event_get_draw_task(e); + + if (lv_draw_task_get_type(task) == LV_DRAW_TASK_TYPE_LINE) { + auto *line_dsc = static_cast<lv_draw_line_dsc_t *>(lv_draw_task_get_draw_dsc(task)); + auto tick = line_dsc->base.id1; + if (tick >= range_start && tick <= range_end) { + unsigned range = range_end - range_start; + if (local) { + tick -= range_start; + } else { + range = lv_scale_get_total_tick_count(scale) - 1; + } + if (range == 0) + range = 1; + auto ratio = (tick * 255) / range; + line_dsc->color = lv_color_mix(color_end, color_start, ratio); + } + } +} +#endif // USE_LVGL_SCALE + +static void lv_container_constructor(const lv_obj_class_t *class_p, lv_obj_t *obj) { + LV_TRACE_OBJ_CREATE("begin"); + LV_UNUSED(class_p); +} + +// Container class. Name is based on LVGL naming convention but upper case to keep ESPHome clang-tidy happy +const lv_obj_class_t LV_CONTAINER_CLASS = { + .base_class = &lv_obj_class, + .constructor_cb = lv_container_constructor, + .name = "lv_container", +}; + +lv_obj_t *lv_container_create(lv_obj_t *parent) { + lv_obj_t *obj = lv_obj_class_create_obj(&LV_CONTAINER_CLASS, parent); + lv_obj_class_init_obj(obj); + return obj; +} +} // namespace esphome::lvgl + +lv_result_t lv_mem_test_core() { return LV_RESULT_OK; } + +void lv_mem_init() {} + +void lv_mem_deinit() {} #if defined(USE_HOST) || defined(USE_RP2040) || defined(USE_ESP8266) -void *lv_custom_mem_alloc(size_t size) { +void *lv_malloc_core(size_t size) { auto *ptr = malloc(size); // NOLINT if (ptr == nullptr) { ESP_LOGE(esphome::lvgl::TAG, "Failed to allocate %zu bytes", size); } return ptr; } -void lv_custom_mem_free(void *ptr) { return free(ptr); } // NOLINT -void *lv_custom_mem_realloc(void *ptr, size_t size) { return realloc(ptr, size); } // NOLINT -#else +void lv_free_core(void *ptr) { return free(ptr); } // NOLINT +void *lv_realloc_core(void *ptr, size_t size) { return realloc(ptr, size); } // NOLINT + +void lv_mem_monitor_core(lv_mem_monitor_t *mon_p) { memset(mon_p, 0, sizeof(lv_mem_monitor_t)); } +static void *lv_alloc_draw_buf(size_t size, bool internal) { + return malloc(size); // NOLINT +} + +#elif defined(USE_ESP32) static unsigned cap_bits = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT; // NOLINT -void *lv_custom_mem_alloc(size_t size) { +static void *lv_alloc_draw_buf(size_t size, bool internal) { + void *buffer; + size = ((size + LV_DRAW_BUF_ALIGN - 1) / LV_DRAW_BUF_ALIGN) * LV_DRAW_BUF_ALIGN; + buffer = heap_caps_aligned_alloc(LV_DRAW_BUF_ALIGN, size, internal ? MALLOC_CAP_8BIT : cap_bits); // NOLINT + if (buffer == nullptr) + ESP_LOGW(esphome::lvgl::TAG, "Failed to allocate %zu bytes for %sdraw buffer", size, internal ? "internal " : ""); + return buffer; +} + +void lv_mem_monitor_core(lv_mem_monitor_t *mon_p) { + multi_heap_info_t heap_info; + heap_caps_get_info(&heap_info, cap_bits); + mon_p->total_size = heap_info.total_allocated_bytes + heap_info.total_free_bytes; + mon_p->free_size = heap_info.total_free_bytes; + mon_p->max_used = heap_info.total_allocated_bytes; + mon_p->free_biggest_size = heap_info.largest_free_block; + mon_p->used_cnt = heap_info.allocated_blocks; + mon_p->free_cnt = heap_info.free_blocks; + mon_p->used_pct = heap_info.allocated_blocks * 100 / (heap_info.allocated_blocks + heap_info.free_blocks); + mon_p->frag_pct = 0; +} + +void *lv_malloc_core(size_t size) { void *ptr; ptr = heap_caps_malloc(size, cap_bits); if (ptr == nullptr) { @@ -614,14 +773,14 @@ void *lv_custom_mem_alloc(size_t size) { return ptr; } -void lv_custom_mem_free(void *ptr) { +void lv_free_core(void *ptr) { ESP_LOGV(esphome::lvgl::TAG, "free %p", ptr); if (ptr == nullptr) return; heap_caps_free(ptr); } -void *lv_custom_mem_realloc(void *ptr, size_t size) { +void *lv_realloc_core(void *ptr, size_t size) { ESP_LOGV(esphome::lvgl::TAG, "realloc %p: %zu", ptr, size); return heap_caps_realloc(ptr, size, cap_bits); } diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index aa8dd2fba5..4ce7296159 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -4,7 +4,7 @@ #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif // USE_BINARY_SENSOR -#ifdef USE_LVGL_IMAGE +#ifdef USE_IMAGE #include "esphome/components/image/image.h" #endif // USE_LVGL_IMAGE #ifdef USE_LVGL_ROTARY_ENCODER @@ -19,16 +19,17 @@ #include "esphome/components/display/display.h" #include "esphome/components/display/display_color_utils.h" #include "esphome/core/component.h" -#include "esphome/core/log.h" + +#include <list> #include <lvgl.h> #include <map> #include <utility> #include <vector> -#ifdef USE_LVGL_FONT +#ifdef USE_FONT #include "esphome/components/font/font.h" #endif // USE_LVGL_FONT -#ifdef USE_LVGL_TOUCHSCREEN +#ifdef USE_TOUCHSCREEN #include "esphome/components/touchscreen/touchscreen.h" #endif // USE_LVGL_TOUCHSCREEN @@ -36,12 +37,24 @@ #include "esphome/components/key_provider/key_provider.h" #endif // USE_LVGL_BUTTONMATRIX -namespace esphome { -namespace lvgl { +namespace esphome::lvgl { + +#if LV_COLOR_DEPTH == 16 +using lv_color_data = uint16_t; +#endif +#if LV_COLOR_DEPTH == 32 +using lv_color_data = uint32_t; +#endif extern lv_event_code_t lv_api_event; // NOLINT extern lv_event_code_t lv_update_event; // NOLINT -extern std::string lv_event_code_name_for(uint8_t event_code); +extern std::string lv_event_code_name_for(lv_event_t *event); + +lv_obj_t *lv_container_create(lv_obj_t *parent); +#ifdef USE_LVGL_SCALE +void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, + lv_color_t color_end, bool local); +#endif #if LV_COLOR_DEPTH == 16 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; #elif LV_COLOR_DEPTH == 32 @@ -50,7 +63,7 @@ static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BIT static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_332; #endif // LV_COLOR_DEPTH -#ifdef USE_LVGL_FONT +#if defined(USE_FONT) && defined(USE_LVGL_FONT) inline void lv_obj_set_style_text_font(lv_obj_t *obj, const font::Font *font, lv_style_selector_t part) { lv_obj_set_style_text_font(obj, font->get_lv_font(), part); } @@ -58,50 +71,37 @@ inline void lv_style_set_text_font(lv_style_t *style, const font::Font *font) { lv_style_set_text_font(style, font->get_lv_font()); } #endif -#ifdef USE_LVGL_IMAGE +#ifdef USE_IMAGE // Shortcut / overload, so that the source of an image can easily be updated // from within a lambda. -inline void lv_img_set_src(lv_obj_t *obj, esphome::image::Image *image) { - lv_img_set_src(obj, image->get_lv_img_dsc()); -} -inline void lv_disp_set_bg_image(lv_disp_t *disp, esphome::image::Image *image) { - lv_disp_set_bg_image(disp, image->get_lv_img_dsc()); +inline void lv_image_set_src(lv_obj_t *obj, esphome::image::Image *image) { + lv_image_set_src(obj, image->get_lv_image_dsc()); } -inline void lv_obj_set_style_bg_img_src(lv_obj_t *obj, esphome::image::Image *image, lv_style_selector_t selector) { - lv_obj_set_style_bg_img_src(obj, image->get_lv_img_dsc(), selector); +inline void lv_obj_set_style_bg_image_src(lv_obj_t *obj, esphome::image::Image *image, lv_style_selector_t selector) { + lv_obj_set_style_bg_image_src(obj, image->get_lv_image_dsc(), selector); } -#ifdef USE_LVGL_CANVAS -inline void lv_canvas_draw_img(lv_obj_t *canvas, lv_coord_t x, lv_coord_t y, image::Image *image, - lv_draw_img_dsc_t *dsc) { - lv_canvas_draw_img(canvas, x, y, image->get_lv_img_dsc(), dsc); -} -#endif - -#ifdef USE_LVGL_METER -inline lv_meter_indicator_t *lv_meter_add_needle_img(lv_obj_t *obj, lv_meter_scale_t *scale, esphome::image::Image *src, - lv_coord_t pivot_x, lv_coord_t pivot_y) { - return lv_meter_add_needle_img(obj, scale, src->get_lv_img_dsc(), pivot_x, pivot_y); -} -#endif // USE_LVGL_METER #endif // USE_LVGL_IMAGE #ifdef USE_LVGL_ANIMIMG inline void lv_animimg_set_src(lv_obj_t *img, std::vector<image::Image *> images) { - auto *dsc = static_cast<std::vector<lv_img_dsc_t *> *>(lv_obj_get_user_data(img)); + auto *dsc = static_cast<std::vector<lv_image_dsc_t *> *>(lv_obj_get_user_data(img)); if (dsc == nullptr) { // object will be lazily allocated but never freed. - dsc = new std::vector<lv_img_dsc_t *>(images.size()); // NOLINT + dsc = new std::vector<lv_image_dsc_t *>(images.size()); // NOLINT lv_obj_set_user_data(img, dsc); } dsc->clear(); for (auto &image : images) { - dsc->push_back(image->get_lv_img_dsc()); + dsc->push_back(image->get_lv_image_dsc()); } lv_animimg_set_src(img, (const void **) dsc->data(), dsc->size()); } - #endif // USE_LVGL_ANIMIMG +#ifdef USE_LVGL_METER +int16_t lv_get_needle_angle_for_value(lv_obj_t *obj, int value); +#endif + // Parent class for things that wrap an LVGL object class LvCompound { public: @@ -130,7 +130,7 @@ class LvPageType : public Parented<LvglComponent> { using LvLambdaType = std::function<void(lv_obj_t *)>; using set_value_lambda_t = std::function<void(float)>; -using event_callback_t = void(_lv_event_t *); +using event_callback_t = void(lv_event_t *); using text_lambda_t = std::function<const char *()>; template<typename... Ts> class ObjUpdateAction : public Action<Ts...> { @@ -152,7 +152,7 @@ class LvglComponent : public PollingComponent { public: LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh, int draw_rounding, bool resume_on_input, bool update_when_display_idle); - static void static_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); + static void static_flush_cb(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *color_p); float get_setup_priority() const override { return setup_priority::PROCESSOR; } void setup() override; @@ -160,11 +160,11 @@ class LvglComponent : public PollingComponent { void loop() override; template<typename F> void add_on_idle_callback(F &&callback) { this->idle_callbacks_.add(std::forward<F>(callback)); } - static void monitor_cb(lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px); - static void render_start_cb(lv_disp_drv_t *disp_drv); + static void render_end_cb(lv_event_t *event); + static void render_start_cb(lv_event_t *event); void dump_config() override; lv_disp_t *get_disp() { return this->disp_; } - lv_obj_t *get_scr_act() { return lv_disp_get_scr_act(this->disp_); } + lv_obj_t *get_screen_active() { return lv_display_get_screen_active(this->disp_); } // Pause or resume the display. // @param paused If true, pause the display. If false, resume the display. // @param show_snow If true, show the snow effect when paused. @@ -187,11 +187,13 @@ class LvglComponent : public PollingComponent { static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2); static void add_event_cb(lv_obj_t *obj, event_callback_t callback, lv_event_code_t event1, lv_event_code_t event2, lv_event_code_t event3); + void add_page(LvPageType *page); void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time); void show_next_page(lv_scr_load_anim_t anim, uint32_t time); void show_prev_page(lv_scr_load_anim_t anim, uint32_t time); void set_page_wrap(bool wrap) { this->page_wrap_ = wrap; } + void set_big_endian(bool big_endian) { this->big_endian_ = big_endian; } size_t get_current_page() const; void set_focus_mark(lv_group_t *group) { this->focus_marks_[group] = lv_group_get_focused(group); } void restore_focus_mark(lv_group_t *group) { @@ -216,22 +218,25 @@ class LvglComponent : public PollingComponent { void draw_start_() const { this->draw_start_callback_->trigger(); } void write_random_(); - void draw_buffer_(const lv_area_t *area, lv_color_t *ptr); - void flush_cb_(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p); + void draw_buffer_(const lv_area_t *area, lv_color_data *ptr); + void flush_cb_(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *color_p); + std::vector<display::Display *> displays_{}; size_t buffer_frac_{1}; bool full_refresh_{}; bool resume_on_input_{}; bool update_when_display_idle_{}; - lv_disp_draw_buf_t draw_buf_{}; - lv_disp_drv_t disp_drv_{}; - lv_disp_t *disp_{}; + uint8_t *draw_buf_{}; + lv_display_t *disp_{}; + uint16_t width_{}; + uint16_t height_{}; bool paused_{}; std::vector<LvPageType *> pages_{}; size_t current_page_{0}; bool show_snow_{}; bool page_wrap_{true}; + bool big_endian_{}; std::map<lv_group_t *, lv_obj_t *> focus_marks_{}; CallbackManager<void(uint32_t)> idle_callbacks_{}; @@ -239,7 +244,7 @@ class LvglComponent : public PollingComponent { Trigger<> *resume_callback_{}; Trigger<> *draw_start_callback_{}; Trigger<> *draw_end_callback_{}; - lv_color_t *rotate_buf_{}; + void *rotate_buf_{}; }; class IdleTrigger : public Trigger<> { @@ -278,19 +283,37 @@ class LVTouchListener : public touchscreen::TouchListener, public Parented<LvglC touch_pressed_ = false; this->parent_->maybe_wakeup(); } - lv_indev_drv_t *get_drv() { return &this->drv_; } + lv_indev_t *get_drv() { return this->drv_; } protected: - lv_indev_drv_t drv_{}; + lv_indev_t *drv_{}; touchscreen::TouchPoint touch_point_{}; bool touch_pressed_{}; }; #endif // USE_LVGL_TOUCHSCREEN +#ifdef USE_LVGL_METER + +class IndicatorLine : public LvCompound { + public: + IndicatorLine() = default; + + void set_obj(lv_obj_t *lv_obj) override; + + void set_value(int value); + + private: + void update_length_(); + + int16_t angle_{}; + lv_point_precise_t points_[2]{}; +}; +#endif + #ifdef USE_LVGL_KEY_LISTENER class LVEncoderListener : public Parented<LvglComponent> { public: - LVEncoderListener(lv_indev_type_t type, uint16_t lpt, uint16_t lprt); + LVEncoderListener(lv_indev_type_t type, uint16_t long_press_time, uint16_t long_press_repeat_time); #ifdef USE_BINARY_SENSOR void add_button(binary_sensor::BinarySensor *button, lv_key_t key) { @@ -322,10 +345,10 @@ class LVEncoderListener : public Parented<LvglComponent> { } } - lv_indev_drv_t *get_drv() { return &this->drv_; } + lv_indev_t *get_drv() { return this->drv_; } protected: - lv_indev_drv_t drv_{}; + lv_indev_t *drv_{}; bool pressed_{}; int32_t count_{}; int32_t last_count_{}; @@ -336,14 +359,13 @@ class LVEncoderListener : public Parented<LvglComponent> { #ifdef USE_LVGL_LINE class LvLineType : public LvCompound { public: - std::vector<lv_point_t> get_points() { return this->points_; } - void set_points(std::vector<lv_point_t> points) { + void set_points(FixedVector<lv_point_precise_t> points) { this->points_ = std::move(points); - lv_line_set_points(this->obj, this->points_.data(), this->points_.size()); + lv_line_set_points(this->obj, this->points_.begin(), this->points_.size()); } protected: - std::vector<lv_point_t> points_{}; + FixedVector<lv_point_precise_t> points_{}; }; #endif #if defined(USE_LVGL_DROPDOWN) || defined(LV_USE_ROLLER) @@ -392,7 +414,7 @@ class LvRollerType : public LvSelectable { class LvButtonMatrixType : public key_provider::KeyProvider, public LvCompound { public: void set_obj(lv_obj_t *lv_obj) override; - uint16_t get_selected() { return lv_btnmatrix_get_selected_btn(this->obj); } + uint16_t get_selected() { return lv_buttonmatrix_get_selected_button(this->obj); } void set_key(size_t idx, uint8_t key) { this->key_map_[idx] = key; } protected: @@ -406,5 +428,4 @@ class LvKeyboardType : public key_provider::KeyProvider, public LvCompound { void set_obj(lv_obj_t *lv_obj) override; }; #endif // USE_LVGL_KEYBOARD -} // namespace lvgl -} // namespace esphome +} // namespace esphome::lvgl diff --git a/esphome/components/lvgl/lvgl_hal.h b/esphome/components/lvgl/lvgl_hal.h deleted file mode 100644 index 754cc70391..0000000000 --- a/esphome/components/lvgl/lvgl_hal.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by Clyde Stubbs on 20/9/2023. -// - -#pragma once - -#ifdef __cplusplus -#define EXTERNC extern "C" -#include <cstddef> -namespace esphome { -namespace lvgl {} -} // namespace esphome -#else -#define EXTERNC extern -#include <stddef.h> -#endif - -EXTERNC size_t lv_millis(void); -EXTERNC void *lv_custom_mem_alloc(size_t size); -EXTERNC void lv_custom_mem_free(void *ptr); -EXTERNC void *lv_custom_mem_realloc(void *ptr, size_t size); diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index 98f8423b7c..c48e051eac 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -52,9 +52,9 @@ async def to_code(config): await value.get_lambda(), event_code, config[CONF_RESTORE_VALUE], - max_value=widget.get_max(), - min_value=widget.get_min(), - step=widget.get_step(), + max_value=widget.type.get_max(widget.config), + min_value=widget.type.get_min(widget.config), + step=widget.type.get_step(widget.config), ) async with LambdaContext(EVENT_ARG) as event: event.add(var.on_value()) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 2aeeedbd10..4e2bfeae85 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -29,6 +29,7 @@ from .defines import ( CONF_SCROLLBAR_MODE, CONF_TIME_FORMAT, LV_GRAD_DIR, + get_remapped_uses, ) from .helpers import CONF_IF_NAN, requires_component, validate_printf from .layout import ( @@ -42,16 +43,17 @@ from .lvcode import LvglComponent, lv_event_t_ptr from .types import ( LVEncoderListener, LvType, - WidgetType, lv_group_t, lv_obj_t, lv_pseudo_button_t, lv_style_t, ) +from .widgets import WidgetType # this will be populated later, in __init__.py to avoid circular imports. WIDGET_TYPES: dict = {} + TIME_TEXT_SCHEMA = cv.Schema( { cv.Required(CONF_TIME_FORMAT): cv.string, @@ -176,23 +178,28 @@ STYLE_PROPS = { "height": lvalid.size, "image_recolor": lvalid.lv_color, "image_recolor_opa": lvalid.opacity, - "line_width": lvalid.lv_positive_int, - "line_dash_width": lvalid.lv_positive_int, - "line_dash_gap": lvalid.lv_positive_int, - "line_rounded": lvalid.lv_bool, "line_color": lvalid.lv_color, + "line_dash_gap": lvalid.lv_positive_int, + "line_dash_width": lvalid.lv_positive_int, + "line_opa": lvalid.opacity, + "line_rounded": lvalid.lv_bool, + "line_width": lvalid.lv_positive_int, "opa": lvalid.opacity, "opa_layered": lvalid.opacity, "outline_color": lvalid.lv_color, "outline_opa": lvalid.opacity, "outline_pad": lvalid.padding, "outline_width": lvalid.pixels, + "length": lvalid.pixels_or_percent, "pad_all": lvalid.padding, "pad_bottom": lvalid.padding, "pad_left": lvalid.padding, "pad_right": lvalid.padding, "pad_top": lvalid.padding, + "radial_offset": lvalid.size, "shadow_color": lvalid.lv_color, + "shadow_offset_x": lvalid.lv_int, + "shadow_offset_y": lvalid.lv_int, "shadow_ofs_x": lvalid.lv_int, "shadow_ofs_y": lvalid.lv_int, "shadow_opa": lvalid.opacity, @@ -213,7 +220,13 @@ STYLE_PROPS = { "transform_height": lvalid.pixels_or_percent, "transform_pivot_x": lvalid.pixels_or_percent, "transform_pivot_y": lvalid.pixels_or_percent, - "transform_zoom": lvalid.zoom, + "transform_rotation": lvalid.lv_angle, + "transform_scale": lvalid.scale, + "transform_scale_x": lvalid.scale, + "transform_scale_y": lvalid.scale, + "transform_skew_x": lvalid.lv_angle, + "transform_skew_y": lvalid.lv_angle, + "transform_zoom": lvalid.scale, "translate_x": lvalid.pixels_or_percent, "translate_y": lvalid.pixels_or_percent, "max_height": lvalid.pixels_or_percent, @@ -227,15 +240,23 @@ STYLE_PROPS = { } STYLE_REMAP = { - "bg_image_opa": "bg_img_opa", - "bg_image_recolor": "bg_img_recolor", - "bg_image_recolor_opa": "bg_img_recolor_opa", - "bg_image_src": "bg_img_src", - "bg_image_tiled": "bg_img_tiled", - "image_recolor": "img_recolor", - "image_recolor_opa": "img_recolor_opa", + "transform_angle": "transform_rotation", + "transform_zoom": "transform_scale", + "zoom": "scale", + "angle": "rotation", + "shadow_ofs_x": "shadow_offset_x", + "shadow_ofs_y": "shadow_offset_y", + "r_mod": "length", } + +def remap_property(prop): + if prop in STYLE_REMAP: + get_remapped_uses().add(prop) + return STYLE_REMAP[prop] + return prop + + # Complete object style schema STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).extend( { @@ -276,7 +297,7 @@ SET_STATE_SCHEMA = cv.Schema( ) # Setting object flags FLAG_SCHEMA = cv.Schema({cv.Optional(flag): lvalid.lv_bool for flag in df.OBJ_FLAGS}) -FLAG_LIST = cv.ensure_list(df.LvConstant("LV_OBJ_FLAG_", *df.OBJ_FLAGS).one_of) +FLAG_LIST = cv.ensure_list(df.LV_OBJ_FLAG.one_of) def part_schema(parts): @@ -418,6 +439,17 @@ ALL_STYLES = { } +def strip_defaults(schema: cv.Schema): + """ + Take a schema and remove any default values, also convert Required to Optional. + Useful for converting an object schema to a modify schema + :param schema: The original Schema + :return: A new schema with no defaults and all items optional + """ + + return cv.Schema({cv.Optional(k): v for k, v in schema.schema.items()}) + + def container_schema(widget_type: WidgetType, extras=None): """ Create a schema for a container widget of a given type. All obj properties are available, plus @@ -481,9 +513,9 @@ def any_widget_schema(extras=None): container_validator, requires_component(required) ) # Apply custom validation - value = widget_type.validate(value or {}) path = [key] if is_dict else [index, key] with prepend_path(path): + value = widget_type.validate(value or {}) result.append({key: container_validator(value)}) return result diff --git a/esphome/components/lvgl/select/lvgl_select.h b/esphome/components/lvgl/select/lvgl_select.h index ba03920a88..3b00310b67 100644 --- a/esphome/components/lvgl/select/lvgl_select.h +++ b/esphome/components/lvgl/select/lvgl_select.h @@ -6,7 +6,7 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/preferences.h" -#include "../lvgl.h" +#include "esphome/components/lvgl/lvgl_esphome.h" namespace esphome { namespace lvgl { @@ -28,12 +28,12 @@ class LVGLSelect : public select::Select, public Component { lv_obj_add_event_cb( this->widget_->obj, [](lv_event_t *e) { - auto *it = static_cast<LVGLSelect *>(e->user_data); + auto *it = static_cast<LVGLSelect *>(lv_event_get_user_data(e)); it->set_options_(); }, LV_EVENT_REFRESH, this); auto lamb = [](lv_event_t *e) { - auto *self = static_cast<LVGLSelect *>(e->user_data); + auto *self = static_cast<LVGLSelect *>(lv_event_get_user_data(e)); self->publish(); }; lv_obj_add_event_cb(this->widget_->obj, lamb, LV_EVENT_VALUE_CHANGED, this); diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index b9801b4133..6f43e78f90 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -13,7 +13,7 @@ from .defines import ( ) from .helpers import add_lv_use from .lvcode import LambdaContext, LocalVariable, lv -from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, STYLE_REMAP +from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, remap_property from .types import ObjUpdateAction, lv_obj_t, lv_style_t from .widgets import ( Widget, @@ -26,6 +26,10 @@ from .widgets import ( from .widgets.obj import obj_spec +def has_style_props(config) -> bool: + return any(prop in config for prop in ALL_STYLES) + + async def style_set(svar, style): for prop, validator in ALL_STYLES.items(): if (value := style.get(prop)) is not None: @@ -33,22 +37,44 @@ async def style_set(svar, style): value = await validator.process(value) if isinstance(value, list): value = "|".join(value) - remapped_prop = STYLE_REMAP.get(prop, prop) - lv.call(f"style_set_{remapped_prop}", svar, literal(value)) + lv.call(f"style_set_{remap_property(prop)}", svar, literal(value)) -async def create_style(style, id_name): +async def create_style(id_name, style=None): style_id = ID(id_name, True, lv_style_t) svar = cg.new_Pvariable(style_id) lv.style_init(svar) - await style_set(svar, style) + if style: + await style_set(svar, style) return svar +class LVStyle: + """ + A class to lazily create a named style + """ + + named_styles = {} + + def __init__(self, id_name, style=None): + self.id_name = id_name + self.style = style + self._style_var = None + + async def get_var(self): + if self._style_var is None: + self._style_var = await create_style(self.id_name + "_style", self.style) + return self._style_var + + @classmethod + def get_style(cls, id_name): + return cls.named_styles.setdefault(id_name, LVStyle(id_name)) + + async def styles_to_code(config): """Convert styles to C__ code.""" for style in config.get(CONF_STYLE_DEFINITIONS, ()): - await create_style(style, style[CONF_ID].id) + await create_style(style[CONF_ID].id, style) @automation.register_action( @@ -81,8 +107,7 @@ async def theme_to_code(config): for part, states in collect_parts(style).items(): styles[part] = { state: await create_style( - props, - "_lv_theme_style_" + w_name + "_" + part + "_" + state, + "_lv_theme_style_" + w_name + "_" + part + "_" + state, props ) for state, props in states.items() } @@ -90,7 +115,7 @@ async def theme_to_code(config): async def add_top_layer(lv_component, config): - top_layer = lv.disp_get_layer_top(lv_component.get_disp()) + top_layer = lv.disp_get_layer_top(lv_component.var.get_disp()) if top_conf := config.get(CONF_TOP_LAYER): with LocalVariable("top_layer", lv_obj_t, top_layer) as top_layer_obj: top_w = Widget(top_layer_obj, obj_spec, top_conf) diff --git a/esphome/components/lvgl/text/lvgl_text.h b/esphome/components/lvgl/text/lvgl_text.h index 4c380d69a2..eacf69b6ec 100644 --- a/esphome/components/lvgl/text/lvgl_text.h +++ b/esphome/components/lvgl/text/lvgl_text.h @@ -1,19 +1,16 @@ #pragma once -#include <utility> - #include "esphome/components/text/text.h" #include "esphome/core/automation.h" #include "esphome/core/component.h" -#include "esphome/core/preferences.h" namespace esphome { namespace lvgl { class LVGLText : public text::Text { public: - void set_control_lambda(std::function<void(const std::string)> control_lambda) { - this->control_lambda_ = std::move(control_lambda); + void set_control_lambda(const std::function<void(std::string)> &control_lambda) { + this->control_lambda_ = control_lambda; if (this->initial_state_.has_value()) { this->control_lambda_(this->initial_state_.value()); this->initial_state_.reset(); @@ -28,7 +25,7 @@ class LVGLText : public text::Text { this->initial_state_ = value; } } - std::function<void(const std::string)> control_lambda_{}; + std::function<void(std::string)> control_lambda_{}; optional<std::string> initial_state_{}; }; diff --git a/esphome/components/lvgl/touchscreens.py b/esphome/components/lvgl/touchscreens.py index f2dd013f6d..0eb9f22f12 100644 --- a/esphome/components/lvgl/touchscreens.py +++ b/esphome/components/lvgl/touchscreens.py @@ -10,7 +10,6 @@ from .defines import ( CONF_TOUCHSCREENS, ) from .helpers import lvgl_components_required -from .lvcode import lv from .schemas import PRESS_TIME from .types import LVTouchListener @@ -40,5 +39,4 @@ async def touchscreens_to_code(lv_component, config): lpt = tconf[CONF_LONG_PRESS_TIME].total_milliseconds lprt = tconf[CONF_LONG_PRESS_REPEAT_TIME].total_milliseconds listener = cg.new_Pvariable(tconf[CONF_ID], lpt, lprt, lv_component) - lv.indev_drv_register(listener.get_drv()) cg.add(touchscreen.register_listener(listener)) diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 2f8b454ec4..c5ad4d402e 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -30,7 +30,7 @@ from .lvcode import ( lvgl_static, ) from .types import LV_EVENT -from .widgets import LvScrActType, get_scr_act, widget_map +from .widgets import LvScrActType, get_screen_active, widget_map async def add_on_boot_triggers(triggers): @@ -48,7 +48,7 @@ async def generate_triggers(): for w in widget_map.values(): if isinstance(w.type, LvScrActType): - w = get_scr_act(w.var) + w = get_screen_active(w.var) if w.config: for event, conf in { diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 09d40bb7ef..03739f3ff1 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,15 +1,9 @@ -import sys - from esphome import automation, codegen as cg -from esphome.automation import register_action -from esphome.config_validation import Schema -from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_TEXT, CONF_VALUE -from esphome.core import EsphomeError -from esphome.cpp_generator import MockObj, MockObjClass +from esphome.const import CONF_TEXT, CONF_VALUE +from esphome.cpp_generator import MockObj from esphome.cpp_types import esphome_ns from .defines import lvgl_ns -from .lvcode import lv_expr class LvType(cg.MockObjClass): @@ -26,6 +20,10 @@ class LvType(cg.MockObjClass): return None return [arg[0] for arg in self.args] + @property + def name(self): + return self.base.removeprefix("lv_").removesuffix("_t") + class LvNumber(LvType): def __init__(self, *args): @@ -63,6 +61,7 @@ lv_obj_base_t = cg.global_ns.class_("lv_obj_t", lv_pseudo_button_t) lv_obj_t_ptr = lv_obj_base_t.operator("ptr") lv_disp_t = cg.global_ns.struct("lv_disp_t") lv_color_t = cg.global_ns.struct("lv_color_t") +lv_opa_t = cg.global_ns.struct("lv_opa_t") lv_group_t = cg.global_ns.struct("lv_group_t") LVTouchListener = lvgl_ns.class_("LVTouchListener") LVEncoderListener = lvgl_ns.class_("LVEncoderListener") @@ -70,10 +69,11 @@ lv_obj_t = LvType("lv_obj_t") lv_page_t = LvType("LvPageType", parents=(LvCompound,)) lv_img_t = LvType("lv_img_t") lv_gradient_t = LvType("lv_grad_dsc_t") +lv_event_t = LvType("lv_event_t") LV_EVENT = MockObj(base="LV_EVENT_", op="") LV_STATE = MockObj(base="LV_STATE_", op="") -LV_BTNMATRIX_CTRL = MockObj(base="LV_BTNMATRIX_CTRL_", op="") +LV_BTNMATRIX_CTRL = MockObj(base="LV_BUTTONMATRIX_CTRL_", op="") class LvText(LvType): @@ -93,7 +93,7 @@ class LvBoolean(LvType): super().__init__( *args, largs=[(cg.bool_, "x")], - lvalue=lambda w: w.is_checked(), + lvalue=lambda w: w.has_state(LV_STATE.CHECKED), has_on_value=True, **kwargs, ) @@ -110,137 +110,3 @@ class LvSelect(LvType): parents=parens, **kwargs, ) - - -class WidgetType: - """ - Describes a type of Widget, e.g. "bar" or "line" - """ - - def __init__( - self, - name: str, - w_type: LvType, - parts: tuple, - schema=None, - modify_schema=None, - lv_name=None, - is_mock: bool = False, - ): - """ - :param name: The widget name, e.g. "bar" - :param w_type: The C type of the widget - :param parts: What parts this widget supports - :param schema: The config schema for defining a widget - :param modify_schema: A schema to update the widget, defaults to the same as the schema - :param lv_name: The name of the LVGL widget in the LVGL library, if different from the name - :param is_mock: Whether this widget is a mock widget, i.e. not a real LVGL widget - """ - self.name = name - self.lv_name = lv_name or name - self.w_type = w_type - self.parts = parts - if not isinstance(schema, Schema): - schema = Schema(schema or {}) - self.schema = schema - if modify_schema is None: - modify_schema = schema - if not isinstance(modify_schema, Schema): - modify_schema = Schema(modify_schema) - self.modify_schema = modify_schema - self.mock_obj = MockObj(f"lv_{self.lv_name}", "_") - - # Local import to avoid circular import - from .automation import update_to_code - from .schemas import WIDGET_TYPES, base_update_schema - - if not is_mock: - if self.name in WIDGET_TYPES: - raise EsphomeError(f"Duplicate definition of widget type '{self.name}'") - WIDGET_TYPES[self.name] = self - - # Register the update action automatically, adding widget-specific properties - register_action( - f"lvgl.{self.name}.update", - ObjUpdateAction, - base_update_schema(self, self.parts).extend(self.modify_schema), - synchronous=True, - )(update_to_code) - - @property - def animated(self): - return False - - @property - def required_component(self): - return None - - def is_compound(self): - return self.w_type.inherits_from(LvCompound) - - async def to_code(self, w, config: dict): - """ - Generate code for a given widget - :param w: The widget - :param config: Its configuration - """ - - async def obj_creator(self, parent: MockObjClass, config: dict): - """ - Create an instance of the widget type - :param parent: The parent to which it should be attached - :param config: Its configuration - :return: Generated code as a single text line - """ - return lv_expr.call(f"{self.lv_name}_create", parent) - - def on_create(self, var: MockObj, config: dict): - """ - Called from to_code when the widget is created, to set up any initial properties - :param var: The variable representing the widget - :param config: Its configuration - """ - - def get_uses(self): - """ - Get a list of other widgets used by this one - :return: - """ - return () - - def get_max(self, config: dict): - return sys.maxsize - - def get_min(self, config: dict): - return -sys.maxsize - - def get_step(self, config: dict): - return 1 - - def get_scale(self, config: dict): - return 1.0 - - def validate(self, value): - """ - Provides an opportunity for custom validation for a given widget type - :param value: - :return: - """ - return value - - def final_validate(self, widget, update_config, widget_config, path): - """ - Allow final validation for a given widget type update action - :param widget: A widget - :param update_config: The configuration for the update action - :param widget_config: The configuration for the widget itself - :param path: The path to the widget, for error reporting - """ - - -class NumberType(WidgetType): - def get_max(self, config: dict): - return int(config.get(CONF_MAX_VALUE, 100)) - - def get_min(self, config: dict): - return int(config.get(CONF_MIN_VALUE, 0)) diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index b1d157325b..a2a8cf2129 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -2,9 +2,18 @@ import sys from typing import Any from esphome import codegen as cg, config_validation as cv -from esphome.config_validation import Invalid -from esphome.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE -from esphome.core import ID, TimePeriod +from esphome.automation import register_action +from esphome.config_validation import Invalid, Schema +from esphome.const import ( + CONF_DEFAULT, + CONF_GROUP, + CONF_ID, + CONF_MAX_VALUE, + CONF_MIN_VALUE, + CONF_STATE, + CONF_TYPE, +) +from esphome.core import ID, EsphomeError, TimePeriod from esphome.coroutine import FakeAwaitable from esphome.cpp_generator import MockObj @@ -21,6 +30,7 @@ from ..defines import ( CONF_MAIN, CONF_PAD_COLUMN, CONF_PAD_ROW, + CONF_SCALE, CONF_STYLES, CONF_WIDGETS, OBJ_FLAGS, @@ -44,8 +54,15 @@ from ..lvcode import ( lv_obj, lv_Pvariable, ) -from ..schemas import ALL_STYLES, OBJ_PROPERTIES, STYLE_REMAP, WIDGET_TYPES -from ..types import LV_STATE, LvType, WidgetType, lv_coord_t, lv_obj_t, lv_obj_t_ptr +from ..types import ( + LV_STATE, + LvCompound, + LvType, + ObjUpdateAction, + lv_coord_t, + lv_obj_t, + lv_obj_t_ptr, +) EVENT_LAMB = "event_lamb__" @@ -53,6 +70,171 @@ theme_widget_map = {} styles_used = set() +class WidgetType: + """ + Describes a type of Widget, e.g. "bar" or "line" + """ + + def __init__( + self, + name: str, + w_type: LvType, + parts: tuple, + schema=None, + modify_schema=None, + lv_name=None, + is_mock: bool = False, + ): + """ + :param name: The widget name, e.g. "bar" + :param w_type: The C type of the widget + :param parts: What parts this widget supports + :param schema: The config schema for defining a widget + :param modify_schema: A schema to update the widget, defaults to the same as the schema + :param lv_name: The name of the LVGL widget in the LVGL library, if different from the name + :param is_mock: Whether this widget is a mock widget, i.e. not a real LVGL widget + """ + self.name = name + self.lv_name = lv_name or name + self.w_type = w_type + self.parts = parts + if not isinstance(schema, Schema): + schema = Schema(schema or {}) + self.schema = schema + if modify_schema is None: + modify_schema = schema + if not isinstance(modify_schema, Schema): + modify_schema = Schema(modify_schema) + self.modify_schema = modify_schema + self.mock_obj = MockObj(f"lv_{self.lv_name}", "_") + + # Local import to avoid circular import + from ..automation import update_to_code + from ..schemas import WIDGET_TYPES, base_update_schema + + if not is_mock: + if self.name in WIDGET_TYPES: + raise EsphomeError(f"Duplicate definition of widget type '{self.name}'") + WIDGET_TYPES[self.name] = self + + # Register the update action automatically, adding widget-specific properties + register_action( + f"lvgl.{self.name}.update", + ObjUpdateAction, + base_update_schema(self, self.parts).extend(self.modify_schema), + synchronous=True, + )(update_to_code) + + @property + def animated(self): + return False + + @property + def required_component(self): + return None + + def is_compound(self): + return self.w_type.inherits_from(LvCompound) + + async def create_to_code(self, config: dict, parent: MockObj) -> "Widget": + """ + Generate code for a widget creation. + :param config: The configuration for the widget + :param parent: The parent to which it should be attached + """ + + creator = await self.obj_creator(parent, config) + add_lv_use(self.name) + add_lv_use(*self.get_uses()) + wid = config[CONF_ID] + add_line_marks(wid) + if self.is_compound(): + var = cg.new_Pvariable(wid) + lv_add(var.set_obj(creator)) + await self.on_create(var.obj, config) + else: + var = lv_Pvariable(lv_obj_t, wid) + lv_assign(var, creator) + await self.on_create(var, config) + + w = Widget.create(wid, var, self, config) + if theme := theme_widget_map.get(self.w_type.name): + for part, states in theme.items(): + part = "LV_PART_" + part.upper() + for state, style in states.items(): + state = "LV_STATE_" + state.upper() + if state == "LV_STATE_DEFAULT": + lv_state = literal(part) + elif part == "LV_PART_MAIN": + lv_state = literal(state) + else: + lv_state = join_enums((state, part)) + w.add_style(style, lv_state) + await set_obj_properties(w, config) + await add_widgets(w, config) + await self.to_code(w, config) + return w + + async def to_code(self, w: "Widget", config: dict): + """ + Update a widget, also called when creating + :param config: + :return: + """ + + async def obj_creator(self, parent: MockObj, config: dict): + """ + Create an instance of the widget type + :param parent: The parent to which it should be attached + :param config: Its configuration + :return: Generated code as a single text line + """ + return lv_expr.call(f"{self.lv_name}_create", parent) + + async def on_create(self, var: MockObj, config: dict): + """ + Called from to_code when the widget is created, to set up any initial properties + :param var: The variable representing the widget + :param config: Its configuration + """ + + def get_uses(self): + """ + Get a list of other widgets used by this one + :return: + """ + return () + + def get_max(self, config: dict): + return sys.maxsize + + def get_min(self, config: dict): + return -sys.maxsize + + def get_step(self, config: dict): + return 1 + + def get_scale(self, config: dict): + return 1.0 + + def validate(self, value): + """ + Provides an opportunity for custom validation for a given widget type + :param value: + :return: + """ + return value + + def final_validate(self, widget, update_config, widget_config, path): + """ + Allow final validation for a given widget type update action + :param widget: A widget + :param update_config: The configuration for the update action + :param widget_config: The configuration for the widget itself + :param path: The path to the widget, for error reporting + """ + + class Widget: """ Represents a Widget. @@ -74,19 +256,25 @@ class Widget: self.obj = var self.outer = None self.move_to_foreground = False + # Properties for linear equations + self.slope = None + self.y_int = None @staticmethod def create(name, var, wtype: WidgetType, config: dict = None): w = Widget(var, wtype, config) - if name is not None: - widget_map[name] = w + widget_map[name] = w return w def add_state(self, state): + if "|" in state: + state = f"(lv_state_t)({state})" return lv_obj.add_state(self.obj, literal(state)) def clear_state(self, state): - return lv_obj.clear_state(self.obj, literal(state)) + if "|" in state: + state = f"(lv_state_t)({state})" + return lv_obj.remove_state(self.obj, literal(state)) def has_state(self, state): return (lv_expr.obj_get_state(self.obj) & literal(state)) != 0 @@ -98,12 +286,23 @@ class Widget: return self.has_state(LV_STATE.CHECKED) def add_flag(self, flag): + if "|" in flag: + flag = f"(lv_obj_flag_t)({flag})" return lv_obj.add_flag(self.obj, literal(flag)) def clear_flag(self, flag): - return lv_obj.clear_flag(self.obj, literal(flag)) + if "|" in flag: + flag = f"(lv_obj_flag_t)({flag})" + return lv_obj.remove_flag(self.obj, literal(flag)) - async def set_property(self, prop, value, animated: bool = None, lv_name=None): + def add_style(self, style_id, state=LV_STATE.DEFAULT): + if "|" in state: + state = f"(lv_state_t)({state})" + lv_obj.add_style(self.obj, MockObj(style_id), literal(state)) + + async def set_property( + self, prop, value, animated: bool = None, lv_name=None, processor=None + ): """ Set a property of the widget. :param prop: The property name @@ -111,18 +310,28 @@ class Widget: :param animated: If the change should be animated :param lv_name: The base type of the widget e.g. "obj" """ + + from ..schemas import ALL_STYLES, remap_property + if isinstance(value, dict): value = value.get(prop) - if isinstance(ALL_STYLES.get(prop), LValidator): - value = await ALL_STYLES[prop].process(value) - else: - value = literal(value) - if value is None: + if value is None: + return + if not processor and isinstance(ALL_STYLES.get(prop), LValidator): + processor = ALL_STYLES[prop] + if isinstance(processor, LValidator): + processor = processor.process + if processor: + value = await processor(value) + elif value is None: return + prop = remap_property(prop) if isinstance(value, TimePeriod): value = value.total_milliseconds - if isinstance(value, str): + elif isinstance(value, str): value = literal(value) + elif isinstance(value, ID): + value = MockObj(value) lv_name = lv_name or self.type.lv_name if animated is None or self.type.animated is not True: lv.call(f"{lv_name}_set_{prop}", self.obj, value) @@ -138,10 +347,12 @@ class Widget: ltype = ltype or self.__type_base() return cg.RawExpression(f"lv_{ltype}_get_{prop}({self.obj})") - def set_style(self, prop, value, state): + def set_style(self, prop, value, state=LV_STATE.DEFAULT): if value is None: return styles_used.add(prop) + if isinstance(value, str): + value = literal(value) lv.call(f"obj_set_style_{prop}", self.obj, value, state) def __type_base(self): @@ -189,15 +400,6 @@ class Widget: """ return - def get_max(self): - return self.type.get_max(self.config) - - def get_min(self): - return self.type.get_min(self.config) - - def get_step(self): - return self.type.get_step(self.config) - def get_scale(self): return self.type.get_scale(self.config) @@ -212,14 +414,14 @@ class LvScrActType(WidgetType): """ def __init__(self): - super().__init__("lv_scr_act()", lv_obj_t, (), is_mock=True) + super().__init__("lv_screen_active()", lv_obj_t, (), is_mock=True) async def to_code(self, w, config: dict): - return [] + pass -def get_scr_act(lv_comp: MockObj) -> Widget: - return Widget.create(None, lv_comp.get_scr_act(), LvScrActType(), {}) +def get_screen_active(lv_comp: MockObj) -> Widget: + return Widget(lv_comp.get_screen_active(), LvScrActType(), {}) def get_widget_generator(wid): @@ -271,10 +473,17 @@ def collect_props(config): :param config: :return: """ + + from ..schemas import ALL_STYLES + props = {} for prop in [*ALL_STYLES, *OBJ_FLAGS, CONF_STYLES, CONF_GROUP]: if prop in config: - props[prop] = config[prop] + if prop == CONF_SCALE: + props[CONF_SCALE + "_x"] = config[prop] + props[CONF_SCALE + "_y"] = config[prop] + else: + props[prop] = config[prop] return props @@ -304,34 +513,41 @@ def collect_parts(config): return parts +def _size_to_str(value): + if isinstance(value, float): + return f"lv_pct({int(value * 100)})" + return str(value) + + async def set_obj_properties(w: Widget, config): """Generate a list of C++ statements to apply properties to an lv_obj_t""" + + from ..schemas import ALL_STYLES, OBJ_PROPERTIES, remap_property + if layout := config.get(CONF_LAYOUT): layout_type: str = layout[CONF_TYPE] add_lv_use(layout_type) lv_obj.set_layout(w.obj, literal(f"LV_LAYOUT_{layout_type.upper()}")) if (pad_row := layout.get(CONF_PAD_ROW)) is not None: - w.set_style(CONF_PAD_ROW, pad_row, 0) + w.set_style(CONF_PAD_ROW, pad_row) if (pad_column := layout.get(CONF_PAD_COLUMN)) is not None: - w.set_style(CONF_PAD_COLUMN, pad_column, 0) + w.set_style(CONF_PAD_COLUMN, pad_column) if layout_type == TYPE_GRID: wid = config[CONF_ID] - rows = [str(x) for x in layout[CONF_GRID_ROWS]] + rows = [_size_to_str(x) for x in layout[CONF_GRID_ROWS]] rows = "{" + ",".join(rows) + ", LV_GRID_TEMPLATE_LAST}" row_id = ID(f"{wid}_row_dsc", is_declaration=True, type=lv_coord_t) row_array = cg.static_const_array(row_id, cg.RawExpression(rows)) - w.set_style("grid_row_dsc_array", row_array, 0) - columns = [str(x) for x in layout[CONF_GRID_COLUMNS]] + w.set_style("grid_row_dsc_array", row_array) + columns = [_size_to_str(x) for x in layout[CONF_GRID_COLUMNS]] columns = "{" + ",".join(columns) + ", LV_GRID_TEMPLATE_LAST}" column_id = ID(f"{wid}_column_dsc", is_declaration=True, type=lv_coord_t) column_array = cg.static_const_array(column_id, cg.RawExpression(columns)) - w.set_style("grid_column_dsc_array", column_array, 0) + w.set_style("grid_column_dsc_array", column_array) w.set_style( - CONF_GRID_COLUMN_ALIGN, literal(layout.get(CONF_GRID_COLUMN_ALIGN)), 0 - ) - w.set_style( - CONF_GRID_ROW_ALIGN, literal(layout.get(CONF_GRID_ROW_ALIGN)), 0 + CONF_GRID_COLUMN_ALIGN, literal(layout.get(CONF_GRID_COLUMN_ALIGN)) ) + w.set_style(CONF_GRID_ROW_ALIGN, literal(layout.get(CONF_GRID_ROW_ALIGN))) if layout_type == TYPE_FLEX: lv_obj.set_flex_flow(w.obj, literal(layout[CONF_FLEX_FLOW])) main = literal(layout[CONF_FLEX_ALIGN_MAIN]) @@ -353,13 +569,13 @@ async def set_obj_properties(w: Widget, config): else: lv_state = join_enums((state, part)) for style_id in props.get(CONF_STYLES, ()): - lv_obj.add_style(w.obj, MockObj(style_id), lv_state) + w.add_style(style_id, lv_state) for prop, value in { k: v for k, v in props.items() if k in ALL_STYLES }.items(): if isinstance(ALL_STYLES[prop], LValidator): value = await ALL_STYLES[prop].process(value) - prop_r = STYLE_REMAP.get(prop, prop) + prop_r = remap_property(prop) w.set_style(prop_r, value, lv_state) if group := config.get(CONF_GROUP): group = await cg.get_variable(group) @@ -429,7 +645,7 @@ async def add_widgets(parent: Widget, config: dict): await widget_to_code(w_cnfig, w_type, parent.obj) -async def widget_to_code(w_cnfig, w_type: WidgetType, parent): +async def widget_to_code(w_cnfig, w_type: WidgetType | str, parent) -> Widget: """ Converts a Widget definition to C code. :param w_cnfig: The widget configuration @@ -437,34 +653,18 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent): :param parent: The parent to which the widget should be added :return: """ - spec: WidgetType = WIDGET_TYPES[w_type] - creator = await spec.obj_creator(parent, w_cnfig) - add_lv_use(spec.name) - add_lv_use(*spec.get_uses()) - wid = w_cnfig[CONF_ID] - add_line_marks(wid) - if spec.is_compound(): - var = cg.new_Pvariable(wid) - lv_add(var.set_obj(creator)) - spec.on_create(var.obj, w_cnfig) - else: - var = lv_Pvariable(lv_obj_t, wid) - lv_assign(var, creator) - spec.on_create(var, w_cnfig) - w = Widget.create(wid, var, spec, w_cnfig) - if theme := theme_widget_map.get(w_type): - for part, states in theme.items(): - part = "LV_PART_" + part.upper() - for state, style in states.items(): - state = "LV_STATE_" + state.upper() - if state == "LV_STATE_DEFAULT": - lv_state = literal(part) - elif part == "LV_PART_MAIN": - lv_state = literal(state) - else: - lv_state = join_enums((state, part)) - lv.obj_add_style(w.obj, style, lv_state) - await set_obj_properties(w, w_cnfig) - await add_widgets(w, w_cnfig) - await spec.to_code(w, w_cnfig) + from ..schemas import WIDGET_TYPES + + spec: WidgetType = ( + w_type if isinstance(w_type, WidgetType) else WIDGET_TYPES[w_type] + ) + return await spec.create_to_code(w_cnfig, parent) + + +class NumberType(WidgetType): + def get_max(self, config: dict): + return int(config.get(CONF_MAX_VALUE, 100)) + + def get_min(self, config: dict): + return int(config.get(CONF_MIN_VALUE, 0)) diff --git a/esphome/components/lvgl/widgets/arc.py b/esphome/components/lvgl/widgets/arc.py index 34ac9c51f7..9eaf3dadce 100644 --- a/esphome/components/lvgl/widgets/arc.py +++ b/esphome/components/lvgl/widgets/arc.py @@ -18,7 +18,8 @@ from ..defines import ( CONF_KNOB, CONF_MAIN, CONF_START_ANGLE, - literal, + LV_OBJ_FLAG, + LV_PART, ) from ..lv_validation import ( get_start_value, @@ -28,8 +29,8 @@ from ..lv_validation import ( lv_positive_int, ) from ..lvcode import lv, lv_expr, lv_obj -from ..types import LvNumber, NumberType -from . import Widget +from ..types import LvNumber +from . import NumberType, Widget CONF_ARC = "arc" ARC_SCHEMA = cv.Schema( @@ -71,39 +72,17 @@ class ArcType(NumberType): ) async def to_code(self, w: Widget, config): - if CONF_MIN_VALUE in config and CONF_MAX_VALUE in config: - max_value = await lv_int.process(config[CONF_MAX_VALUE]) - min_value = await lv_int.process(config[CONF_MIN_VALUE]) - lv.arc_set_range(w.obj, min_value, max_value) - elif CONF_MIN_VALUE in config: - max_value = w.get_property(CONF_MAX_VALUE) - min_value = await lv_int.process(config[CONF_MIN_VALUE]) - lv.arc_set_range(w.obj, min_value, max_value) - elif CONF_MAX_VALUE in config: - max_value = await lv_int.process(config[CONF_MAX_VALUE]) - min_value = w.get_property(CONF_MIN_VALUE) - lv.arc_set_range(w.obj, min_value, max_value) - - await w.set_property( - "bg_start_angle", - await lv_angle_degrees.process(config.get(CONF_START_ANGLE)), - ) - await w.set_property( - "bg_end_angle", await lv_angle_degrees.process(config.get(CONF_END_ANGLE)) - ) - await w.set_property( - CONF_ROTATION, await lv_angle_degrees.process(config.get(CONF_ROTATION)) - ) - await w.set_property(CONF_MODE, config) - await w.set_property( - CONF_CHANGE_RATE, - await lv_positive_int.process(config.get(CONF_CHANGE_RATE)), - ) - + for prop, validator in ARC_MODIFY_SCHEMA.schema.items(): + if prop != CONF_VALUE: + # start_angle and end_angle are mapped to bg_start_angle and bg_end_angle + prop = str(prop) + if prop.endswith("_angle"): + prop = "bg_" + prop + await w.set_property(prop, config, processor=validator) if CONF_ADJUSTABLE in config: if not config[CONF_ADJUSTABLE]: - lv_obj.remove_style(w.obj, nullptr, literal("LV_PART_KNOB")) - w.clear_flag("LV_OBJ_FLAG_CLICKABLE") + lv_obj.remove_style(w.obj, nullptr, LV_PART.KNOB) + w.clear_flag(LV_OBJ_FLAG.CLICKABLE) elif CONF_GROUP not in config: # For some reason arc does not get automatically added to the default group lv.group_add_obj(lv_expr.group_get_default(), w.obj) diff --git a/esphome/components/lvgl/widgets/button.py b/esphome/components/lvgl/widgets/button.py index 5f2910174f..b943a4d9aa 100644 --- a/esphome/components/lvgl/widgets/button.py +++ b/esphome/components/lvgl/widgets/button.py @@ -7,11 +7,11 @@ from ..helpers import add_lv_use from ..lv_validation import lv_text from ..lvcode import lv, lv_expr from ..schemas import TEXT_SCHEMA -from ..types import LvBoolean, WidgetType -from . import Widget +from ..types import LvBoolean +from . import Widget, WidgetType from .label import label_spec -lv_button_t = LvBoolean("lv_btn_t") +lv_button_t = LvBoolean("lv_button_t") class ButtonType(WidgetType): @@ -30,7 +30,7 @@ class ButtonType(WidgetType): def get_uses(self): return ("btn",) - def on_create(self, var: MockObj, config: dict): + async def on_create(self, var: MockObj, config: dict): if CONF_TEXT in config: lv.label_create(var) return var diff --git a/esphome/components/lvgl/widgets/buttonmatrix.py b/esphome/components/lvgl/widgets/buttonmatrix.py index f94f12b69b..f5ae0deba9 100644 --- a/esphome/components/lvgl/widgets/buttonmatrix.py +++ b/esphome/components/lvgl/widgets/buttonmatrix.py @@ -118,15 +118,15 @@ class MatrixButton(Widget): def has_state(self, state): state = self.map_ctrls(state) - return lv_expr.btnmatrix_has_btn_ctrl(self.obj, self.index, state) + return lv_expr.buttonmatrix_has_button_ctrl(self.obj, self.index, state) def add_state(self, state): state = self.map_ctrls(state) - return lv.btnmatrix_set_btn_ctrl(self.obj, self.index, state) + return lv.buttonmatrix_set_button_ctrl(self.obj, self.index, state) def clear_state(self, state): state = self.map_ctrls(state) - return lv.btnmatrix_clear_btn_ctrl(self.obj, self.index, state) + return lv.buttonmatrix_clear_button_ctrl(self.obj, self.index, state) def is_pressed(self): return self.is_selected() & self.parent.has_state(LV_STATE.PRESSED) @@ -161,7 +161,7 @@ async def get_button_data(config, buttonmatrix: Widget): text_list.append(button_conf.get(CONF_TEXT) or "") key_list.append(button_conf.get(CONF_KEY_CODE) or 0) width_list.append(button_conf[CONF_WIDTH]) - ctrl = ["LV_BTNMATRIX_CTRL_CLICK_TRIG"] + ctrl = ["CLICK_TRIG"] for item in button_conf.get(CONF_CONTROL, ()): ctrl.extend([k for k, v in item.items() if v]) ctrl_list.append(await BUTTONMATRIX_CTRLS.process(ctrl)) @@ -187,7 +187,7 @@ class ButtonMatrixType(WidgetType): (CONF_MAIN, CONF_ITEMS), BUTTONMATRIX_SCHEMA, {}, - lv_name="btnmatrix", + lv_name="buttonmatrix", ) async def to_code(self, w: Widget, config): @@ -199,22 +199,22 @@ class ButtonMatrixType(WidgetType): ) text_id = config[CONF_BUTTON_TEXT_LIST_ID] text_id = cg.static_const_array(text_id, text_list) - lv.btnmatrix_set_map(w.obj, text_id) + lv.buttonmatrix_set_map(w.obj, text_id) set_btn_data(w.obj, ctrl_list, width_list) - lv.btnmatrix_set_one_checked(w.obj, config[CONF_ONE_CHECKED]) + lv.buttonmatrix_set_one_checked(w.obj, config[CONF_ONE_CHECKED]) for index, key in enumerate(key_list): if key != 0: lv_add(w.var.set_key(index, key)) def get_uses(self): - return ("btnmatrix",) + return ("buttonmatrix",) def set_btn_data(obj, ctrl_list, width_list): for index, ctrl in enumerate(ctrl_list): - lv.btnmatrix_set_btn_ctrl(obj, index, ctrl) + lv.buttonmatrix_set_button_ctrl(obj, index, ctrl) for index, width in enumerate(width_list): - lv.btnmatrix_set_btn_width(obj, index, width) + lv.buttonmatrix_set_button_width(obj, index, width) buttonmatrix_spec = ButtonMatrixType() @@ -253,25 +253,21 @@ async def button_update_to_code(config, action_id, template_arg, args): async def do_button_update(w): if (width := config.get(CONF_WIDTH)) is not None: - lv.btnmatrix_set_btn_width(w.obj, w.index, width) + lv.buttonmatrix_set_button_width(w.obj, w.index, width) if config.get(CONF_SELECTED): - lv.btnmatrix_set_selected_btn(w.obj, w.index) + lv.buttonmatrix_set_selected_button(w.obj, w.index) if controls := config.get(CONF_CONTROL): adds = [] clrs = [] for item in controls: - adds.extend( - [f"LV_BTNMATRIX_CTRL_{k.upper()}" for k, v in item.items() if v] - ) - clrs.extend( - [f"LV_BTNMATRIX_CTRL_{k.upper()}" for k, v in item.items() if not v] - ) + adds.extend([f"{k.upper()}" for k, v in item.items() if v]) + clrs.extend([f"{k.upper()}" for k, v in item.items() if not v]) if adds: - lv.btnmatrix_set_btn_ctrl( + lv.buttonmatrix_set_button_ctrl( w.obj, w.index, await BUTTONMATRIX_CTRLS.process(adds) ) if clrs: - lv.btnmatrix_clear_btn_ctrl( + lv.buttonmatrix_clear_button_ctrl( w.obj, w.index, await BUTTONMATRIX_CTRLS.process(clrs) ) diff --git a/esphome/components/lvgl/widgets/canvas.py b/esphome/components/lvgl/widgets/canvas.py index 50cc8b0af6..c670e3732c 100644 --- a/esphome/components/lvgl/widgets/canvas.py +++ b/esphome/components/lvgl/widgets/canvas.py @@ -1,3 +1,22 @@ +""" +LVGL 9.4 Canvas Widget Implementation + +This module implements the canvas widget for LVGL 9.4. Key changes from LVGL 8.4: + +1. Buffer allocation: + - LV_IMG_CF_TRUE_COLOR → LV_COLOR_FORMAT_RGB565 + - LV_IMG_CF_TRUE_COLOR_ALPHA → LV_COLOR_FORMAT_ARGB8888 + - LV_CANVAS_BUF_SIZE_TRUE_COLOR → LV_CANVAS_BUF_SIZE(w, h, bpp, stride) + +2. Drawing API: + - All lv_canvas_draw_* functions removed + - Use layer-based drawing: lv_canvas_init_layer() / lv_canvas_finish_layer() + - Draw using low-level lv_draw_* functions (rect, line, arc, image, label) + +3. Pixel operations: + - lv_canvas_set_px_color + lv_canvas_set_px_opa → lv_canvas_set_px(color, opa) +""" + from esphome import automation, codegen as cg, config_validation as cv from esphome.components.display_menu_base import CONF_LABEL from esphome.const import ( @@ -9,7 +28,7 @@ from esphome.const import ( CONF_X, CONF_Y, ) -from esphome.cpp_generator import Literal, MockObj +from esphome.cpp_types import FixedVector from ..automation import action_to_code from ..defines import ( @@ -19,8 +38,11 @@ from ..defines import ( CONF_PIVOT_X, CONF_PIVOT_Y, CONF_POINTS, + CONF_RADIUS, CONF_SRC, CONF_START_ANGLE, + addr, + get_color_formats, literal, ) from ..lv_validation import ( @@ -34,18 +56,20 @@ from ..lv_validation import ( size, ) from ..lvcode import LocalVariable, lv, lv_assign, lv_expr -from ..schemas import STYLE_PROPS, STYLE_REMAP, TEXT_SCHEMA, point_schema -from ..types import LvType, ObjUpdateAction, WidgetType -from . import Widget, get_widgets -from .line import lv_point_t, process_coord +from ..schemas import STYLE_PROPS, TEXT_SCHEMA, point_schema, remap_property +from ..types import LvType, ObjUpdateAction +from . import Widget, WidgetType, get_widgets +from .img import CONF_IMAGE +from .line import lv_point_precise_t, process_coord CONF_CANVAS = "canvas" CONF_BUFFER_ID = "buffer_id" CONF_MAX_WIDTH = "max_width" CONF_TRANSPARENT = "transparent" -CONF_RADIUS = "radius" +CONF_DRAW_BUF_ID = "draw_buf_id" lv_canvas_t = LvType("lv_canvas_t") +lv_draw_buf_t = LvType("lv_draw_buf_t") class CanvasType(WidgetType): @@ -59,32 +83,44 @@ class CanvasType(WidgetType): cv.Required(CONF_WIDTH): size, cv.Required(CONF_HEIGHT): size, cv.Optional(CONF_TRANSPARENT, default=False): cv.boolean, + cv.GenerateID(CONF_DRAW_BUF_ID): cv.declare_id(lv_draw_buf_t), } ), + modify_schema={}, ) def get_uses(self): - return "img", CONF_LABEL + return CONF_IMAGE, CONF_LABEL async def to_code(self, w: Widget, config): width = config[CONF_WIDTH] height = config[CONF_HEIGHT] - use_alpha = "_ALPHA" if config[CONF_TRANSPARENT] else "" - buf_size = literal( - f"LV_CANVAS_BUF_SIZE_TRUE_COLOR{use_alpha}({width}, {height})" + # LVGL 9.4: Use LV_COLOR_FORMAT instead of LV_IMG_CF + # RGB565 is 16-bit (2 bytes per pixel), ARGB8888 is 32-bit (4 bytes per pixel) + if config[CONF_TRANSPARENT]: + color_format = "LV_COLOR_FORMAT_ARGB8888" + get_color_formats().add("ARGB8888") + else: + color_format = "LV_COLOR_FORMAT_NATIVE" + + # LVGL 9.4: LV_CANVAS_BUF_SIZE(width, height, bits_per_pixel, stride) + # stride is 0 for default (width * bytes_per_pixel) + draw_buf = cg.new_Pvariable(config[CONF_DRAW_BUF_ID]) + buf_size = literal(f"LV_DRAW_BUF_SIZE({width}, {height}, {color_format})") + lv.draw_buf_init( + draw_buf, + width, + height, + literal(color_format), + 0, + lv_expr.malloc_core(buf_size), + literal(buf_size), ) - with LocalVariable("buf", cg.void, lv_expr.custom_mem_alloc(buf_size)) as buf: - cg.add(cg.RawExpression(f"memset({buf}, 0, {buf_size});")) - lv.canvas_set_buffer( - w.obj, - buf, - width, - height, - literal(f"LV_IMG_CF_TRUE_COLOR{use_alpha}"), - ) + lv.draw_buf_set_flag(draw_buf, literal("LV_IMAGE_FLAGS_MODIFIABLE")) + lv.canvas_set_draw_buf(w.obj, draw_buf) -canvas_spec = CanvasType() +CanvasType() @automation.register_action( @@ -117,7 +153,7 @@ async def canvas_fill(config, action_id, template_arg, args): { cv.GenerateID(CONF_ID): cv.use_id(lv_canvas_t), cv.Required(CONF_COLOR): lv_color, - cv.Optional(CONF_OPA): opacity, + cv.Optional(CONF_OPA, default="COVER"): opacity, cv.Required(CONF_POINTS): cv.ensure_list(point_schema), }, ), @@ -126,7 +162,7 @@ async def canvas_fill(config, action_id, template_arg, args): async def canvas_set_pixel(config, action_id, template_arg, args): widget = await get_widgets(config) color = await lv_color.process(config[CONF_COLOR]) - opa = await opacity.process(config.get(CONF_OPA)) + opa = await opacity.process(config.get(CONF_OPA), "COVER") points = [ ( await pixels.process(p[CONF_X]), @@ -136,25 +172,11 @@ async def canvas_set_pixel(config, action_id, template_arg, args): ] async def do_set_pixels(w: Widget): - if isinstance(color, MockObj): - for point in points: - x, y = point - lv.canvas_set_px_color(w.obj, x, y, color) - else: - with LocalVariable("color", "lv_color_t", color, modifier="") as color_var: - for point in points: - x, y = point - lv.canvas_set_px_color(w.obj, x, y, color_var) - if opa: - if isinstance(opa, Literal): - for point in points: - x, y = point - lv.canvas_set_px_opa(w.obj, x, y, opa) - else: - with LocalVariable("opa", "lv_opa_t", opa, modifier="") as opa_var: - for point in points: - x, y = point - lv.canvas_set_px_opa(w.obj, x, y, opa_var) + # LVGL 9.4: lv_canvas_set_px combines color and opacity + # Could optimize this for lambda values + for point in points: + x, y = point + lv.canvas_set_px(w.obj, x, y, color, opa) return await action_to_code( widget, do_set_pixels, action_id, template_arg, args, config @@ -178,18 +200,21 @@ async def draw_to_code(config, dsc_type, props, do_draw, action_id, template_arg y = await pixels.process(config.get(CONF_Y)) async def action_func(w: Widget): - with LocalVariable("dsc", f"lv_draw_{dsc_type}_dsc_t", modifier="") as dsc: - dsc_addr = literal(f"&{dsc}") - lv.call(f"draw_{dsc_type}_dsc_init", dsc_addr) - if CONF_OPA in config: - opa = await opacity.process(config[CONF_OPA]) - lv_assign(dsc.opa, opa) - for prop, validator in props.items(): - if prop in config: - value = await validator.process(config[prop]) - mapped_prop = STYLE_REMAP.get(prop, prop) - lv_assign(getattr(dsc, mapped_prop), value) - await do_draw(w, x, y, dsc_addr) + # LVGL 9.4: Create a layer for drawing on canvas + with LocalVariable("layer", "lv_layer_t", modifier="") as layer: + lv.canvas_init_layer(w.obj, addr(layer)) + with LocalVariable("dsc", f"lv_draw_{dsc_type}_dsc_t", modifier="") as dsc: + lv.call(f"draw_{dsc_type}_dsc_init", addr(dsc)) + if CONF_OPA in config: + opa = await opacity.process(config[CONF_OPA]) + lv_assign(dsc.opa, opa) + for prop, validator in props.items(): + if prop in config: + value = await validator.process(config[prop]) + mapped_prop = remap_property(prop) + lv_assign(getattr(dsc, mapped_prop), value) + await do_draw(addr(layer), x, y, dsc) + lv.canvas_finish_layer(w.obj, addr(layer)) return await action_to_code( widget, action_func, action_id, template_arg, args, config @@ -212,6 +237,8 @@ RECT_PROPS = { "outline_opa", "shadow_color", "shadow_width", + "shadow_offset_x", + "shadow_offset_y", "shadow_ofs_x", "shadow_ofs_y", "shadow_spread", @@ -220,6 +247,24 @@ RECT_PROPS = { } +def _draw_line(layer, dsc, points): + # LVGL 9.4: Use lv_draw_line for each line segment + with ( + LocalVariable( + "points", FixedVector.template(lv_point_precise_t), points, modifier="" + ) as points_var, + LocalVariable("i", "uint32_t", literal("0"), modifier="") as i, + ): + # Draw lines between consecutive points + lv.append( + cg.RawStatement(f"for ({i} = 0; {i} != {points_var}.size() - 1; {i}++) {{") + ) + lv_assign(dsc.p1, points_var[i]) + lv_assign(dsc.p2, points_var[i + 1]) + lv.draw_line(layer, addr(dsc)) + lv.append(cg.RawStatement("}")) + + @automation.register_action( "lvgl.canvas.draw_rectangle", ObjUpdateAction, @@ -237,8 +282,14 @@ async def canvas_draw_rect(config, action_id, template_arg, args): width = await pixels.process(config[CONF_WIDTH]) height = await pixels.process(config[CONF_HEIGHT]) - async def do_draw_rect(w: Widget, x, y, dsc_addr): - lv.canvas_draw_rect(w.obj, x, y, width, height, dsc_addr) + async def do_draw_rect(layer, x, y, dsc): + # LVGL 9.4: Use lv_draw_rect with area + with LocalVariable("area", "lv_area_t", modifier="") as area: + lv_assign(area.x1, x) + lv_assign(area.y1, y) + lv_assign(area.x2, literal(f"{x} + {width} - 1")) + lv_assign(area.y2, literal(f"{y} + {height} - 1")) + lv.draw_rect(layer, addr(dsc), addr(area)) return await draw_to_code( config, "rect", RECT_PROPS, do_draw_rect, action_id, template_arg, args @@ -277,21 +328,55 @@ async def canvas_draw_text(config, action_id, template_arg, args): text = await lv_text.process(config[CONF_TEXT]) max_width = await pixels.process(config[CONF_MAX_WIDTH]) - async def do_draw_text(w: Widget, x, y, dsc_addr): - lv.canvas_draw_text(w.obj, x, y, max_width, dsc_addr, text) + async def do_draw_text(layer, x, y, dsc): + # LVGL 9.4: Use lv_draw_label with area and hint + with LocalVariable("area", "lv_area_t", modifier="") as area: + lv_assign(area.x1, x) + lv_assign(area.y1, y) + lv_assign(area.x2, literal(f"{x} + {max_width} - 1")) + lv_assign(area.y2, literal(f"{y} + LV_COORD_MAX")) + lv_assign(dsc.text, text) + lv.draw_label(layer, addr(dsc), addr(area)) return await draw_to_code( config, "label", TEXT_PROPS, do_draw_text, action_id, template_arg, args ) -IMG_PROPS = { - "angle": STYLE_PROPS["transform_angle"], - "zoom": STYLE_PROPS["transform_zoom"], - "recolor": STYLE_PROPS["image_recolor"], - "recolor_opa": STYLE_PROPS["image_recolor_opa"], - "opa": STYLE_PROPS["opa"], -} +IMG_PROPS = ( + "angle", + "rotation", + "scale_x", + "scale_y", + "skew_x", + "skew_y", + "scale", + "zoom", + "recolor", + "recolor_opa", + "opa", +) + + +def _scale_map(config): + config = {remap_property(p): v for p, v in config.items()} + if "scale" in config and {"scale_x", "scale_y"} & config.keys(): + raise cv.Invalid("Cannot specify both scale and scale_x/scale_y") + if "scale" in config: + config.update({"scale_x": config["scale"], "scale_y": config["scale"]}) + del config["scale"] + return config + + +def _get_prop_validator(prop): + return STYLE_PROPS.get(f"transform_{remap_property(prop)}") or STYLE_PROPS.get(prop) + + +def _prop_validator(prop): + def validator(value): + return _get_prop_validator(prop)(value) + + return validator @automation.register_action( @@ -303,9 +388,9 @@ IMG_PROPS = { cv.Required(CONF_SRC): lv_image, cv.Optional(CONF_PIVOT_X, default=0): pixels, cv.Optional(CONF_PIVOT_Y, default=0): pixels, - **{cv.Optional(prop): validator for prop, validator in IMG_PROPS.items()}, + **{cv.Optional(prop): _prop_validator(prop) for prop in IMG_PROPS}, } - ), + ).add_extra(_scale_map), synchronous=True, ) async def canvas_draw_image(config, action_id, template_arg, args): @@ -313,15 +398,29 @@ async def canvas_draw_image(config, action_id, template_arg, args): pivot_x = await pixels.process(config[CONF_PIVOT_X]) pivot_y = await pixels.process(config[CONF_PIVOT_Y]) - async def do_draw_image(w: Widget, x, y, dsc_addr): - dsc = MockObj(f"(*{dsc_addr})") + async def do_draw_image(layer, x, y, dsc): + # LVGL 9.4: Use lv_draw_image with area + lv_assign(dsc.src, src.get_lv_image_dsc()) if pivot_x or pivot_y: # pylint :disable=no-member - lv_assign(dsc.pivot, literal(f"{{{pivot_x}, {pivot_y}}}")) - lv.canvas_draw_img(w.obj, x, y, src, dsc_addr) + lv_assign(dsc.pivot.x, pivot_x) + lv_assign(dsc.pivot.y, pivot_y) + with LocalVariable("area", "lv_area_t", modifier="") as area: + lv_assign(area.x1, x) + lv_assign(area.y1, y) + # Image size will be determined from the image descriptor + lv_assign(area.x2, x) + lv_assign(area.y2, y) + lv.draw_image(layer, addr(dsc), addr(area)) return await draw_to_code( - config, "img", IMG_PROPS, do_draw_image, action_id, template_arg, args + config, + "image", + {prop: _get_prop_validator(prop) for prop in IMG_PROPS}, + do_draw_image, + action_id, + template_arg, + args, ) @@ -354,11 +453,8 @@ async def canvas_draw_line(config, action_id, template_arg, args): for p in config[CONF_POINTS] ] - async def do_draw_line(w: Widget, x, y, dsc_addr): - with LocalVariable( - "points", cg.std_vector.template(lv_point_t), points, modifier="" - ) as points_var: - lv.canvas_draw_line(w.obj, points_var.data(), points_var.size(), dsc_addr) + async def do_draw_line(layer, _x, _y, dsc): + _draw_line(layer, dsc, points) return await draw_to_code( config, "line", LINE_PROPS, do_draw_line, action_id, template_arg, args @@ -382,14 +478,20 @@ async def canvas_draw_polygon(config, action_id, template_arg, args): [await process_coord(p[CONF_X]), await process_coord(p[CONF_Y])] for p in config[CONF_POINTS] ] + # Close the polygon + points.append(points[0]) - async def do_draw_polygon(w: Widget, x, y, dsc_addr): - with LocalVariable( - "points", cg.std_vector.template(lv_point_t), points, modifier="" - ) as points_var: - lv.canvas_draw_polygon( - w.obj, points_var.data(), points_var.size(), dsc_addr - ) + async def do_draw_polygon(layer, x, y, dsc): + # LVGL 9.4: Draw polygon using line drawing in a closed path + # Note: This draws outline only. For filled polygons, would need different approach + # Convert rect descriptor to line descriptor for polygon outline + with LocalVariable("line_dsc", "lv_draw_line_dsc_t", modifier="") as line_dsc: + lv.draw_line_dsc_init(addr(line_dsc)) + # Copy border properties from rect descriptor to line descriptor + lv_assign(line_dsc.color, dsc.border_color) + lv_assign(line_dsc.width, dsc.border_width) + lv_assign(line_dsc.opa, dsc.border_opa) + _draw_line(layer, line_dsc, points) return await draw_to_code( config, "rect", RECT_PROPS, do_draw_polygon, action_id, template_arg, args @@ -422,8 +524,14 @@ async def canvas_draw_arc(config, action_id, template_arg, args): start_angle = await lv_angle_degrees.process(config[CONF_START_ANGLE]) end_angle = await lv_angle_degrees.process(config[CONF_END_ANGLE]) - async def do_draw_arc(w: Widget, x, y, dsc_addr): - lv.canvas_draw_arc(w.obj, x, y, radius, start_angle, end_angle, dsc_addr) + async def do_draw_arc(layer, x, y, dsc): + # LVGL 9.4: Use lv_draw_arc with center point + lv_assign(dsc.center.x, x) + lv_assign(dsc.center.y, y) + lv_assign(dsc.start_angle, start_angle) + lv_assign(dsc.end_angle, end_angle) + lv_assign(dsc.radius, radius) + lv.draw_arc(layer, addr(dsc)) return await draw_to_code( config, "arc", ARC_PROPS, do_draw_arc, action_id, template_arg, args diff --git a/esphome/components/lvgl/widgets/container.py b/esphome/components/lvgl/widgets/container.py index 2ac1a3b244..427b46affa 100644 --- a/esphome/components/lvgl/widgets/container.py +++ b/esphome/components/lvgl/widgets/container.py @@ -1,11 +1,10 @@ import esphome.config_validation as cv from esphome.const import CONF_HEIGHT, CONF_WIDTH -from esphome.cpp_generator import MockObj -from ..defines import CONF_CONTAINER, CONF_MAIN, CONF_OBJ, CONF_SCROLLBAR +from ..defines import CONF_CONTAINER, CONF_MAIN, CONF_SCROLLBAR from ..lv_validation import size -from ..lvcode import lv -from ..types import WidgetType, lv_obj_t +from ..types import lv_obj_t +from . import WidgetType CONTAINER_SCHEMA = cv.Schema( { @@ -28,12 +27,9 @@ class ContainerType(WidgetType): (CONF_MAIN, CONF_SCROLLBAR), schema=CONTAINER_SCHEMA, modify_schema={}, - lv_name=CONF_OBJ, + lv_name=CONF_CONTAINER, ) self.styles = {} - def on_create(self, var: MockObj, config: dict): - lv.obj_remove_style_all(var) - container_spec = ContainerType() diff --git a/esphome/components/lvgl/widgets/img.py b/esphome/components/lvgl/widgets/img.py index 8ec18e3033..ed6fd30c09 100644 --- a/esphome/components/lvgl/widgets/img.py +++ b/esphome/components/lvgl/widgets/img.py @@ -1,17 +1,22 @@ import esphome.config_validation as cv -from esphome.const import CONF_ANGLE, CONF_MODE, CONF_OFFSET_X, CONF_OFFSET_Y +from esphome.const import ( + CONF_ANGLE, + CONF_MODE, + CONF_OFFSET_X, + CONF_OFFSET_Y, + CONF_ROTATION, +) from ..defines import ( CONF_ANTIALIAS, CONF_MAIN, CONF_PIVOT_X, CONF_PIVOT_Y, + CONF_SCALE, CONF_SRC, CONF_ZOOM, - LvConstant, ) -from ..lv_validation import lv_angle, lv_bool, lv_image, size, zoom -from ..lvcode import lv +from ..lv_validation import lv_angle, lv_bool, lv_image, scale, size from ..types import lv_img_t from . import Widget, WidgetType from .label import CONF_LABEL @@ -22,14 +27,14 @@ BASE_IMG_SCHEMA = cv.Schema( { cv.Optional(CONF_PIVOT_X): size, cv.Optional(CONF_PIVOT_Y): size, - cv.Optional(CONF_ANGLE): lv_angle, - cv.Optional(CONF_ZOOM): zoom, + cv.Exclusive(CONF_ANGLE, CONF_ROTATION): lv_angle, + cv.Exclusive(CONF_ROTATION, CONF_ROTATION): lv_angle, + cv.Exclusive(CONF_ZOOM, CONF_SCALE): scale, + cv.Exclusive(CONF_SCALE, CONF_SCALE): scale, cv.Optional(CONF_OFFSET_X): size, cv.Optional(CONF_OFFSET_Y): size, cv.Optional(CONF_ANTIALIAS): lv_bool, - cv.Optional(CONF_MODE): LvConstant( - "LV_IMG_SIZE_MODE_", "VIRTUAL", "REAL" - ).one_of, + cv.Optional(CONF_MODE): cv.invalid(f"{CONF_MODE} is not supported in LVGL 9.x"), } ) @@ -54,33 +59,15 @@ class ImgType(WidgetType): (CONF_MAIN,), IMG_SCHEMA, IMG_MODIFY_SCHEMA, - lv_name="img", ) def get_uses(self): - return "img", CONF_LABEL + return CONF_IMAGE, CONF_LABEL async def to_code(self, w: Widget, config): - if src := config.get(CONF_SRC): - lv.img_set_src(w.obj, await lv_image.process(src)) - if (pivot_x := config.get(CONF_PIVOT_X)) and ( - pivot_y := config.get(CONF_PIVOT_Y) - ): - lv.img_set_pivot( - w.obj, await size.process(pivot_x), await size.process(pivot_y) - ) - if (cf_angle := config.get(CONF_ANGLE)) is not None: - lv.img_set_angle(w.obj, await lv_angle.process(cf_angle)) - if (img_zoom := config.get(CONF_ZOOM)) is not None: - lv.img_set_zoom(w.obj, await zoom.process(img_zoom)) - if (offset := config.get(CONF_OFFSET_X)) is not None: - lv.img_set_offset_x(w.obj, await size.process(offset)) - if (offset := config.get(CONF_OFFSET_Y)) is not None: - lv.img_set_offset_y(w.obj, await size.process(offset)) - if CONF_ANTIALIAS in config: - lv.img_set_antialias(w.obj, await lv_bool.process(config[CONF_ANTIALIAS])) - if mode := config.get(CONF_MODE): - await w.set_property("size_mode", mode) + await w.set_property(CONF_SRC, await lv_image.process(config.get(CONF_SRC))) + for prop, validator in BASE_IMG_SCHEMA.schema.items(): + await w.set_property(prop, config, processor=validator) img_spec = ImgType() diff --git a/esphome/components/lvgl/widgets/label.py b/esphome/components/lvgl/widgets/label.py index 8afd8d610f..bb5900b8c9 100644 --- a/esphome/components/lvgl/widgets/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -11,8 +11,8 @@ from ..defines import ( ) from ..lv_validation import lv_bool, lv_text from ..schemas import TEXT_SCHEMA -from ..types import LvText, WidgetType -from . import Widget +from ..types import LvText +from . import Widget, WidgetType CONF_LABEL = "label" diff --git a/esphome/components/lvgl/widgets/led.py b/esphome/components/lvgl/widgets/led.py index 647973c9b7..f0092debaa 100644 --- a/esphome/components/lvgl/widgets/led.py +++ b/esphome/components/lvgl/widgets/led.py @@ -2,7 +2,7 @@ import esphome.config_validation as cv from esphome.const import CONF_BRIGHTNESS, CONF_COLOR, CONF_LED from ..defines import CONF_MAIN -from ..lv_validation import lv_brightness, lv_color +from ..lv_validation import lv_color, lv_percentage from ..lvcode import lv from ..types import LvType from . import Widget, WidgetType @@ -10,7 +10,7 @@ from . import Widget, WidgetType LED_SCHEMA = cv.Schema( { cv.Optional(CONF_COLOR): lv_color, - cv.Optional(CONF_BRIGHTNESS): lv_brightness, + cv.Optional(CONF_BRIGHTNESS): lv_percentage, } ) @@ -23,7 +23,7 @@ class LedType(WidgetType): if (color := config.get(CONF_COLOR)) is not None: lv.led_set_color(w.obj, await lv_color.process(color)) if (brightness := config.get(CONF_BRIGHTNESS)) is not None: - lv.led_set_brightness(w.obj, await lv_brightness.process(brightness)) + lv.led_set_brightness(w.obj, await lv_percentage.process(brightness)) led_spec = LedType() diff --git a/esphome/components/lvgl/widgets/line.py b/esphome/components/lvgl/widgets/line.py index 57cb965737..a9b202163f 100644 --- a/esphome/components/lvgl/widgets/line.py +++ b/esphome/components/lvgl/widgets/line.py @@ -14,6 +14,7 @@ CONF_POINTS = "points" CONF_POINT_LIST_ID = "point_list_id" lv_point_t = cg.global_ns.struct("lv_point_t") +lv_point_precise_t = cg.global_ns.struct("lv_point_precise_t") LINE_SCHEMA = { @@ -23,10 +24,7 @@ LINE_SCHEMA = { async def process_coord(coord): if isinstance(coord, Lambda): - coord = call_lambda(await cg.process_lambda(coord, [], return_type=lv_coord_t)) - if not coord.endswith("()"): - coord = f"static_cast<lv_coord_t>({coord})" - return cg.RawExpression(coord) + return call_lambda(await cg.process_lambda(coord, [], return_type=lv_coord_t)) return cg.safe_exp(coord) diff --git a/esphome/components/lvgl/widgets/lv_bar.py b/esphome/components/lvgl/widgets/lv_bar.py index f0fdd6d278..d339807746 100644 --- a/esphome/components/lvgl/widgets/lv_bar.py +++ b/esphome/components/lvgl/widgets/lv_bar.py @@ -11,8 +11,8 @@ from ..defines import ( ) from ..lv_validation import animated, lv_int from ..lvcode import lv -from ..types import LvNumber, NumberType -from . import Widget +from ..types import LvNumber +from . import NumberType, Widget # Note this file cannot be called "bar.py" because that name is disallowed. diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index b7e3af9a78..d45371b3a7 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -1,9 +1,11 @@ from esphome import automation import esphome.codegen as cg +from esphome.components.image import get_image_metadata import esphome.config_validation as cv from esphome.const import ( CONF_COLOR, CONF_COUNT, + CONF_HEIGHT, CONF_ID, CONF_ITEMS, CONF_LENGTH, @@ -13,22 +15,39 @@ from esphome.const import ( CONF_ROTATION, CONF_VALUE, CONF_WIDTH, + CONF_X, ) +from esphome.cpp_generator import MockObj +from esphome.cpp_types import nullptr +from .. import obj_spec, set_obj_properties from ..automation import action_to_code from ..defines import ( + CHILD_ALIGNMENTS, + CONF_ALIGN, + CONF_CONTAINER, CONF_END_VALUE, CONF_INDICATOR, + CONF_LINE_WIDTH, CONF_MAIN, CONF_OPA, CONF_PIVOT_X, CONF_PIVOT_Y, + CONF_RADIUS, + CONF_SCALE, CONF_SRC, CONF_START_VALUE, CONF_TICKS, + LV_OBJ_FLAG, + LV_PART, + LV_SCALE_MODE, + get_remapped_uses, + get_warnings, ) -from ..helpers import add_lv_use, lvgl_components_required +from ..helpers import add_lv_use from ..lv_validation import ( + LV_OPA, + LV_RADIUS, get_end_value, get_start_value, lv_angle_degrees, @@ -36,105 +55,168 @@ from ..lv_validation import ( lv_color, lv_float, lv_image, + lv_int, opacity, + padding, + pixels, + pixels_or_percent, + pixels_or_percent_validator, requires_component, size, ) -from ..lvcode import LocalVariable, lv, lv_assign, lv_expr, lv_obj -from ..types import LvType, ObjUpdateAction -from . import Widget, WidgetType, get_widgets +from ..lvcode import LambdaContext, LocalVariable, lv, lv_add, lv_expr, lv_obj +from ..schemas import STATE_SCHEMA +from ..styles import LVStyle +from ..types import ( + LV_EVENT, + LvCompound, + LvType, + ObjUpdateAction, + lv_event_t, + lv_img_t, + lv_obj_t, +) +from . import Widget, WidgetType, get_widgets, widget_to_code from .arc import CONF_ARC from .img import CONF_IMAGE from .line import CONF_LINE -from .obj import obj_spec CONF_ANGLE_RANGE = "angle_range" CONF_COLOR_END = "color_end" CONF_COLOR_START = "color_start" +CONF_DRAW_TICKS_ON_TOP = "draw_ticks_on_top" +CONF_IMAGE_ID = "image_id" CONF_INDICATORS = "indicators" +CONF_LINE_ID = "line_id" CONF_LABEL_GAP = "label_gap" CONF_MAJOR = "major" CONF_METER = "meter" +CONF_PIVOT = "pivot" CONF_R_MOD = "r_mod" +CONF_RADIAL_OFFSET = "radial_offset" CONF_SCALES = "scales" CONF_STRIDE = "stride" CONF_TICK_STYLE = "tick_style" +# LVGL 9.4 Migration: Use scale widget instead of removed meter widget +# +# The lv_meter widget was removed in LVGL 9.4 and replaced with the more +# flexible lv_scale widget. This implementation emulates meter functionality +# using the scale widget with the following mappings: +# +# - lv_meter -> lv_scale (set to LV_SCALE_MODE_ROUND_OUTER for circular meters) +# - lv_meter_scale -> scale configuration (range, ticks, etc.) +# - lv_meter_indicator -> lv_scale_section (colored ranges on the scale) +# + + +# For compatibility, keep meter types but map to scale +lv_scale_t = LvType("lv_obj_t") lv_meter_t = LvType("lv_meter_t") -lv_meter_indicator_t = cg.global_ns.struct("lv_meter_indicator_t") -lv_meter_indicator_t_ptr = lv_meter_indicator_t.operator("ptr") - - -def pixels(value): - """A size in one axis in pixels""" - if isinstance(value, str) and value.lower().endswith("px"): - return cv.int_(value[:-2]) - return cv.int_(value) +lv_scale_section_t = LvType("lv_scale_section_t") +lv_meter_indicator_t = LvType("lv_meter_indicator_t") +lv_meter_indicator_ticks_t = LvType( + "lv_scale_section_t", parents=(lv_meter_indicator_t,) +) +lv_meter_indicator_arc_t = LvType("lv_scale_section_t", parents=(lv_meter_indicator_t,)) +lv_meter_indicator_line_t = LvType( + "IndicatorLine", + parents=( + LvCompound, + lv_meter_indicator_t, + ), +) +lv_meter_indicator_image_t = LvType("lv_image_t", parents=(lv_meter_indicator_t,)) +DEFAULT_LABEL_GAP = 10 # Default label gap for major ticks added by LVGL INDICATOR_LINE_SCHEMA = cv.Schema( { - cv.Optional(CONF_WIDTH, default=4): size, + cv.Optional(CONF_WIDTH, default=4): cv.int_, cv.Optional(CONF_COLOR, default=0): lv_color, - cv.Optional(CONF_R_MOD, default=0): size, - cv.Optional(CONF_VALUE): lv_float, - cv.Optional(CONF_OPA): opacity, + cv.Optional(CONF_R_MOD): padding, + cv.Optional(CONF_LENGTH): pixels_or_percent_validator, + cv.Optional(CONF_RADIAL_OFFSET, 0): pixels_or_percent_validator, + cv.Optional(CONF_VALUE, default=0.0): lv_float, + cv.Optional(CONF_OPA, default=1.0): opacity, } -) +).add_extra(cv.has_at_most_one_key(CONF_R_MOD, CONF_LENGTH)) + + +class ScaleType(WidgetType): + """ + Will migrate to scale.py in due course + """ + + def __init__(self): + super().__init__( + CONF_SCALE, + lv_scale_t, + (CONF_MAIN, CONF_ITEMS, CONF_INDICATOR), + {}, + is_mock=True, + ) + + +scale_spec = ScaleType() + INDICATOR_IMG_SCHEMA = cv.Schema( { cv.Required(CONF_SRC): lv_image, - cv.Required(CONF_PIVOT_X): pixels, - cv.Required(CONF_PIVOT_Y): pixels, + cv.Optional(CONF_PIVOT_X, default=0): pixels, + cv.Optional(CONF_PIVOT_Y): pixels, cv.Optional(CONF_VALUE): lv_float, - cv.Optional(CONF_OPA): opacity, + cv.Optional(CONF_OPA, default=1.0): opacity, } ) INDICATOR_ARC_SCHEMA = cv.Schema( { - cv.Optional(CONF_WIDTH, default=4): size, + cv.Optional(CONF_WIDTH, default=4): cv.int_, cv.Optional(CONF_COLOR, default=0): lv_color, - cv.Optional(CONF_R_MOD, default=0): size, - cv.Exclusive(CONF_VALUE, CONF_VALUE): lv_float, - cv.Exclusive(CONF_START_VALUE, CONF_VALUE): lv_float, + cv.Optional(CONF_R_MOD): padding, + cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_START_VALUE): lv_float, cv.Optional(CONF_END_VALUE): lv_float, cv.Optional(CONF_OPA): opacity, } -) +).add_extra(cv.has_at_most_one_key(CONF_VALUE, CONF_START_VALUE)) + INDICATOR_TICKS_SCHEMA = cv.Schema( { - cv.Optional(CONF_WIDTH, default=4): size, + cv.Optional(CONF_WIDTH, default=4): cv.int_, cv.Optional(CONF_COLOR_START, default=0): lv_color, cv.Optional(CONF_COLOR_END): lv_color, - cv.Exclusive(CONF_VALUE, CONF_VALUE): lv_float, - cv.Exclusive(CONF_START_VALUE, CONF_VALUE): lv_float, + cv.Optional(CONF_VALUE): lv_float, + cv.Optional(CONF_START_VALUE): lv_float, cv.Optional(CONF_END_VALUE): lv_float, cv.Optional(CONF_LOCAL, default=False): lv_bool, } -) +).add_extra(cv.has_at_most_one_key(CONF_VALUE, CONF_START_VALUE)) + INDICATOR_SCHEMA = cv.Schema( { cv.Exclusive(CONF_LINE, CONF_INDICATORS): INDICATOR_LINE_SCHEMA.extend( { - cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + cv.GenerateID(): cv.declare_id(lv_meter_indicator_line_t), } ), cv.Exclusive(CONF_IMAGE, CONF_INDICATORS): cv.All( INDICATOR_IMG_SCHEMA.extend( { - cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + cv.GenerateID(): cv.declare_id(lv_meter_indicator_image_t), + cv.GenerateID(CONF_IMAGE_ID): cv.declare_id(lv_img_t), } ), requires_component("image"), ), cv.Exclusive(CONF_ARC, CONF_INDICATORS): INDICATOR_ARC_SCHEMA.extend( { - cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + cv.GenerateID(): cv.declare_id(lv_meter_indicator_arc_t), } ), cv.Exclusive(CONF_TICK_STYLE, CONF_INDICATORS): INDICATOR_TICKS_SCHEMA.extend( { - cv.GenerateID(): cv.declare_id(lv_meter_indicator_t), + cv.GenerateID(): cv.declare_id(lv_meter_indicator_ticks_t), } ), } @@ -142,32 +224,96 @@ INDICATOR_SCHEMA = cv.Schema( SCALE_SCHEMA = cv.Schema( { + cv.GenerateID(): cv.declare_id(lv_scale_t), cv.Optional(CONF_TICKS): cv.Schema( { cv.Optional(CONF_COUNT, default=12): cv.positive_int, - cv.Optional(CONF_WIDTH, default=2): size, + cv.Optional(CONF_WIDTH, default=2): cv.positive_int, cv.Optional(CONF_LENGTH, default=10): size, + cv.Optional(CONF_RADIAL_OFFSET, default=0): size, cv.Optional(CONF_COLOR, default=0x808080): lv_color, cv.Optional(CONF_MAJOR): cv.Schema( { cv.Optional(CONF_STRIDE, default=3): cv.positive_int, cv.Optional(CONF_WIDTH, default=5): size, cv.Optional(CONF_LENGTH, default="15%"): size, + cv.Optional(CONF_RADIAL_OFFSET, default=0): size, cv.Optional(CONF_COLOR, default=0): lv_color, cv.Optional(CONF_LABEL_GAP, default=4): size, } ), } ), - cv.Optional(CONF_RANGE_FROM, default=0.0): cv.float_, - cv.Optional(CONF_RANGE_TO, default=100.0): cv.float_, - cv.Optional(CONF_ANGLE_RANGE, default=270): cv.int_range(0, 360), - cv.Optional(CONF_ROTATION): lv_angle_degrees, + cv.Optional(CONF_RANGE_FROM, default=0.0): lv_int, + cv.Optional(CONF_RANGE_TO, default=100.0): lv_int, + cv.Optional(CONF_ANGLE_RANGE, default=270): lv_angle_degrees, + cv.Optional(CONF_ROTATION, default=0): lv_angle_degrees, cv.Optional(CONF_INDICATORS): cv.ensure_list(INDICATOR_SCHEMA), + cv.Optional(CONF_DRAW_TICKS_ON_TOP, default=True): bool, } ) -METER_SCHEMA = {cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA)} +METER_SCHEMA = { + cv.Optional(CONF_PIVOT): STATE_SCHEMA, + cv.Optional(CONF_INDICATOR): STATE_SCHEMA, + cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA), +} + +LIGHT_STYLE = LVStyle( + "lv_meter_light", + { + "bg_opa": 1.0, + "bg_color": 0xEEEEEE, + "line_width": 1, + "line_color": 0xEEEEEE, + "arc_width": 2, + "arc_color": 0xEEEEEE, + "pad_all": 10, + "border_width": 2, + "border_color": 0xEEEEEE, + "radius": "LV_RADIUS_CIRCLE", + }, +) + +PIVOT_STYLE = { + CONF_RADIUS: LV_RADIUS.CIRCLE, + CONF_ALIGN: CHILD_ALIGNMENTS.CENTER, + "bg_color": 0x000000, + "bg_opa": 1.0, + CONF_WIDTH: 15, + CONF_HEIGHT: 15, +} + + +line_indicator_type = WidgetType( + CONF_INDICATOR, + lv_meter_indicator_line_t, + (CONF_MAIN,), + lv_name=CONF_LINE, + is_mock=True, +) + + +class SectionType(WidgetType): + def __init__(self): + super().__init__( + "scale_section", + lv_meter_indicator_arc_t, + (CONF_MAIN,), + is_mock=True, + lv_name="scale_section", + ) + + +arc_indicator_type = SectionType() + +image_indicator_type = WidgetType( + CONF_INDICATOR, + lv_meter_indicator_image_t, + (CONF_MAIN,), + lv_name=CONF_IMAGE, + is_mock=True, +) class MeterType(WidgetType): @@ -175,111 +321,240 @@ class MeterType(WidgetType): super().__init__( CONF_METER, lv_meter_t, + # Note that mapping from 8.x to 9.x, indicator styling is applied to needles, and tick styling + # is migrated to indicator (CONF_MAIN, CONF_INDICATOR, CONF_TICKS, CONF_ITEMS), METER_SCHEMA, + lv_name=CONF_CONTAINER, ) - async def to_code(self, w: Widget, config): - """For a meter object, create and set parameters""" + def get_uses(self): + return CONF_SCALE, CONF_LINE - lvgl_components_required.add(CONF_METER) + def validate(self, value): + return cv.has_at_most_one_key(CONF_INDICATOR, CONF_PIVOT)(value) + + async def on_create(self, var: MockObj, config: dict): + # Remove theme styling from outer container + lv.obj_add_style(var, await LIGHT_STYLE.get_var(), LV_PART.MAIN) + + async def create_to_code(self, config: dict, parent: MockObj): + """For a meter object using scale widget, create and set parameters""" + + add_lv_use(*self.get_uses()) + outer_config = config.copy() + indicator_config = {CONF_INDICATOR: outer_config.pop(CONF_TICKS, {})} + w = await super().create_to_code(outer_config, parent) var = w.obj + + # LVGL 9.4 scale widget setup + # Background style will be applied. for scale_conf in config.get(CONF_SCALES, ()): - rotation = 90 + (360 - scale_conf[CONF_ANGLE_RANGE]) / 2 - if CONF_ROTATION in scale_conf: - rotation = await lv_angle_degrees.process(scale_conf[CONF_ROTATION]) - with LocalVariable( - "meter_var", "lv_meter_scale_t", lv_expr.meter_add_scale(var) - ) as meter_var: - lv.meter_set_scale_range( - var, - meter_var, - scale_conf[CONF_RANGE_FROM], - scale_conf[CONF_RANGE_TO], - scale_conf[CONF_ANGLE_RANGE], - rotation, - ) - if ticks := scale_conf.get(CONF_TICKS): - color = await lv_color.process(ticks[CONF_COLOR]) - lv.meter_set_scale_ticks( - var, - meter_var, - ticks[CONF_COUNT], - await size.process(ticks[CONF_WIDTH]), - await size.process(ticks[CONF_LENGTH]), - color, + scale_var = cg.Pvariable(scale_conf[CONF_ID], lv_expr.scale_create(var)) + percent100 = await pixels_or_percent.process(1.0) + lv_obj.set_style_height(scale_var, percent100, LV_PART.MAIN) + lv_obj.set_style_width(scale_var, percent100, LV_PART.MAIN) + lv_obj.set_style_align(scale_var, CHILD_ALIGNMENTS.CENTER, LV_PART.MAIN) + lv_obj.set_style_bg_opa(scale_var, LV_OPA.TRANSP, LV_PART.MAIN) + lv_obj.set_style_radius(scale_var, LV_RADIUS.CIRCLE, 0) + await set_obj_properties(Widget(scale_var, scale_spec), indicator_config) + + lv.scale_set_mode(scale_var, LV_SCALE_MODE.ROUND_INNER) + # Set the scale range + range_from = await lv_int.process(scale_conf[CONF_RANGE_FROM]) + range_to = await lv_int.process(scale_conf[CONF_RANGE_TO]) + lv.scale_set_range(scale_var, range_from, range_to) + + angle_range = await lv_angle_degrees.process(scale_conf[CONF_ANGLE_RANGE]) + rotation = await lv_angle_degrees.process(scale_conf[CONF_ROTATION]) + # Set angle range + lv.scale_set_angle_range( + scale_var, + angle_range, + ) + + # Set rotation if specified + if rotation: + lv.scale_set_rotation(scale_var, rotation) + + # Handle indicators as sections + for indicator in scale_conf.get(CONF_INDICATORS, ()): + (t, v) = next(iter(indicator.items())) + iid = v[CONF_ID] + + # Enable getting the meter to which this belongs. + + # Set section range based on indicator values + start_value = await get_start_value(v) or scale_conf[CONF_RANGE_FROM] + end_value = await get_end_value(v) or scale_conf[CONF_RANGE_TO] + + # Create and apply styles based on indicator type + if t == CONF_ARC: + props = { + "arc_width": v[CONF_WIDTH], + "arc_color": v[CONF_COLOR], + "arc_rounded": v.get("arc_rounded", False), + } + if (opa := v.get(CONF_OPA)) is not None: + props["arc_opa"] = opa + if CONF_R_MOD in v: + get_warnings().add( + "The 'r_mod' indicator property is not supported in LVGL 9.x and will be ignored." + ) + arc_style = LVStyle(f"meter_arc_{iid.id}", props) + tvar = cg.Pvariable(iid, lv_expr.scale_add_section(scale_var)) + lv.scale_section_set_style( + tvar, LV_PART.MAIN, await arc_style.get_var() ) - if CONF_MAJOR in ticks: - major = ticks[CONF_MAJOR] - lv.meter_set_scale_major_ticks( - var, - meter_var, - major[CONF_STRIDE], - await size.process(major[CONF_WIDTH]), - await size.process(major[CONF_LENGTH]), - await lv_color.process(major[CONF_COLOR]), - await size.process(major[CONF_LABEL_GAP]), - ) - for indicator in scale_conf.get(CONF_INDICATORS, ()): - (t, v) = next(iter(indicator.items())) - iid = v[CONF_ID] - ivar = cg.Pvariable(iid, cg.nullptr, type_=lv_meter_indicator_t) - # Enable getting the meter to which this belongs. - wid = Widget.create(iid, var, obj_spec, v) - wid.obj = ivar - if t == CONF_LINE: - color = await lv_color.process(v[CONF_COLOR]) - lv_assign( - ivar, - lv_expr.meter_add_needle_line( - var, - meter_var, - await size.process(v[CONF_WIDTH]), - color, - await size.process(v[CONF_R_MOD]), - ), - ) - if t == CONF_ARC: - color = await lv_color.process(v[CONF_COLOR]) - lv_assign( - ivar, - lv_expr.meter_add_arc( - var, - meter_var, - await size.process(v[CONF_WIDTH]), - color, - await size.process(v[CONF_R_MOD]), - ), - ) - if t == CONF_TICK_STYLE: - color_start = await lv_color.process(v[CONF_COLOR_START]) - color_end = await lv_color.process( - v.get(CONF_COLOR_END) or color_start - ) - lv_assign( - ivar, - lv_expr.meter_add_scale_lines( - var, - meter_var, + lw = Widget(tvar, arc_indicator_type) + await set_indicator_values(lw, v) + + if t == CONF_TICK_STYLE: + # No object created for this + color_start = await lv_color.process(v[CONF_COLOR_START]) + color_end = await lv_color.process(v[CONF_COLOR_END]) + local = v[CONF_LOCAL] + if color_start and color_end: + async with LambdaContext( + [(lv_event_t.operator("ptr"), "e")] + ) as lambda_: + lv.scale_draw_event_cb( + lambda_.get_parameter(0), + start_value, + end_value, color_start, color_end, - v[CONF_LOCAL], - await size.process(v[CONF_WIDTH]), - ), + local, + ) + lv_obj.add_event_cb( + scale_var, + await lambda_.get_lambda(), + LV_EVENT.DRAW_TASK_ADDED, + nullptr, ) - if t == CONF_IMAGE: - add_lv_use("img") - lv_assign( - ivar, - lv_expr.meter_add_needle_img( - var, - meter_var, - await lv_image.process(v[CONF_SRC]), - v[CONF_PIVOT_X], - v[CONF_PIVOT_Y], - ), - ) - await set_indicator_values(var, ivar, v) + lv.obj_add_flag(scale_var, LV_OBJ_FLAG.SEND_DRAW_TASK_EVENTS) + + if t == CONF_LINE: + # Needle represented by a line + if CONF_LENGTH in v: + length = v[CONF_LENGTH] + elif r_mod := v.get(CONF_R_MOD): + get_remapped_uses().add(CONF_R_MOD) + length = -abs(r_mod) + else: + length = 1.0 + props = { + CONF_ID: v[CONF_ID], + CONF_OPA: v[CONF_OPA], + CONF_LINE_WIDTH: v[CONF_WIDTH], + "line_color": v[CONF_COLOR], + "line_rounded": True, + CONF_ALIGN: CHILD_ALIGNMENTS.TOP_LEFT, + CONF_LENGTH: length, + CONF_RADIAL_OFFSET: v[CONF_RADIAL_OFFSET], + } + lw = await widget_to_code(props, line_indicator_type, scale_var) + await set_indicator_values(lw, v) + + if t == CONF_IMAGE: + add_lv_use(CONF_IMAGE) + src = v[CONF_SRC] + src_data = get_image_metadata(src.id) + pivot_x = await pixels.process(v[CONF_PIVOT_X]) + pivot_y = await pixels.process( + v.get(CONF_PIVOT_Y, src_data.height // 2) + ) + props = { + CONF_X: src_data.width // 2 - pivot_x, + "transform_pivot_x": pivot_x, + "transform_pivot_y": pivot_y, + CONF_SRC: src, + CONF_OPA: v[CONF_OPA], + CONF_ID: v[CONF_ID], + CONF_ALIGN: CHILD_ALIGNMENTS.CENTER, + } + iw = await widget_to_code(props, image_indicator_type, scale_var) + await iw.set_property(CONF_SRC, await lv_image.process(src)) + await set_indicator_values(iw, v) + + if ticks := scale_conf.get(CONF_TICKS): + # Set total tick count + lv.scale_set_total_tick_count(scale_var, ticks[CONF_COUNT]) + lv.scale_set_draw_ticks_on_top( + scale_var, scale_conf[CONF_DRAW_TICKS_ON_TOP] + ) + + # Set tick styling + lv_obj.set_style_length( + scale_var, await size.process(ticks[CONF_LENGTH]), LV_PART.ITEMS + ) + lv_obj.set_style_line_width( + scale_var, await size.process(ticks[CONF_WIDTH]), LV_PART.ITEMS + ) + lv_obj.set_style_radial_offset( + scale_var, + await size.process(ticks[CONF_RADIAL_OFFSET]), + LV_PART.ITEMS, + ) + lv_obj.set_style_line_color( + scale_var, + await lv_color.process(ticks[CONF_COLOR]), + LV_PART.ITEMS, + ) + + # Hide the scale line + lv.obj_set_style_arc_opa(scale_var, LV_OPA.TRANSP, LV_PART.MAIN) + if CONF_MAJOR in ticks: + major = ticks[CONF_MAJOR] + # Set major tick frequency + lv.scale_set_major_tick_every(scale_var, major[CONF_STRIDE]) + + # Enable labels for major ticks + lv.scale_set_label_show(scale_var, True) + + # Set major tick styling + lv_obj.set_style_length( + scale_var, + await size.process(major[CONF_LENGTH]), + LV_PART.INDICATOR, + ) + lv_obj.set_style_radial_offset( + scale_var, + await size.process(ticks[CONF_RADIAL_OFFSET]), + LV_PART.INDICATOR, + ) + lv_obj.set_style_line_width( + scale_var, + await size.process(major[CONF_WIDTH]), + LV_PART.INDICATOR, + ) + lv_obj.set_style_line_color( + scale_var, + await lv_color.process(major[CONF_COLOR]), + LV_PART.INDICATOR, + ) + + # Set label gap (padding) + label_gap = await size.process(major[CONF_LABEL_GAP]) + if isinstance(label_gap, int): + label_gap -= DEFAULT_LABEL_GAP + lv_obj.set_style_pad_radial( + scale_var, + label_gap, + LV_PART.INDICATOR, + ) + else: + lv.scale_set_major_tick_every(scale_var, 0) + else: + lv.scale_set_total_tick_count(scale_var, 0) + + # Add a pivot + # Get the default style + pivot_style = PIVOT_STYLE.copy() + pivot_style.update(config.get(CONF_INDICATOR, config.get(CONF_PIVOT, {}))) + with LocalVariable("pivot", lv_obj_t, lv_expr.container_create(var)) as pivot: + pw = Widget(pivot, obj_spec, pivot_style) + await set_obj_properties(pw, pivot_style) meter_spec = MeterType() @@ -303,23 +578,39 @@ async def indicator_update_to_code(config, action_id, template_arg, args): widget = await get_widgets(config) async def set_value(w: Widget): - await set_indicator_values(w.var, w.obj, config) + await set_indicator_values(w, config) return await action_to_code( widget, set_value, action_id, template_arg, args, config ) -async def set_indicator_values(meter, indicator, config): +async def set_indicator_values(indicator: Widget, config): + """Update scale section values (replaces meter indicator values)""" start_value = await get_start_value(config) end_value = await get_end_value(config) - if start_value is not None: - if end_value is None: - lv.meter_set_indicator_value(meter, indicator, start_value) - else: - lv.meter_set_indicator_start_value(meter, indicator, start_value) - if end_value is not None: - lv.meter_set_indicator_end_value(meter, indicator, end_value) - if (opa := config.get(CONF_OPA)) is not None: - lv_assign(indicator.opa, await opacity.process(opa)) - lv_obj.invalidate(meter) + if indicator.type is arc_indicator_type: + # For scale sections, we update the range + if start_value is not None and end_value is not None: + lv.scale_section_set_range(indicator.obj, start_value, end_value) + elif start_value is not None: + # If only start value, use it as both start and end (single point) + lv.scale_section_set_range(indicator.obj, start_value, start_value) + elif end_value is not None: + # If only end value, assume range from 0 to end_value + lv.scale_section_set_range(indicator.obj, 0, end_value) + return + + if start_value is None: + return + if indicator.type is line_indicator_type: + # Line needle + lv_add(indicator.var.set_value(start_value)) + return + if indicator.type is image_indicator_type: + # Needle represented by an image + lv_obj.set_style_transform_rotation( + indicator.obj, + lv.get_needle_angle_for_value(indicator.obj, start_value) * 10, + LV_PART.MAIN, + ) diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index 82b2442378..af27ee7553 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -1,7 +1,7 @@ -from esphome import config_validation as cv -from esphome.const import CONF_BUTTON, CONF_ID, CONF_ITEMS, CONF_TEXT +from esphome import codegen as cg, config_validation as cv +from esphome.const import CONF_BUTTON, CONF_ID, CONF_TEXT from esphome.core import ID -from esphome.cpp_generator import new_Pvariable, static_const_array +from esphome.cpp_generator import MockObjClass from esphome.cpp_types import nullptr from ..defines import ( @@ -9,40 +9,82 @@ from ..defines import ( CONF_BUTTON_STYLE, CONF_BUTTONS, CONF_CLOSE_BUTTON, + CONF_HEADER_BUTTONS, + CONF_MAIN, CONF_MSGBOXES, + CONF_SRC, CONF_TITLE, + LV_OBJ_FLAG, TYPE_FLEX, + add_warning, literal, ) -from ..helpers import add_lv_use, lvgl_components_required -from ..lv_validation import lv_bool, lv_pct, lv_text -from ..lvcode import ( - EVENT_ARG, - LambdaContext, - LocalVariable, - lv, - lv_add, - lv_assign, - lv_expr, - lv_obj, - lv_Pvariable, -) -from ..schemas import STYLE_SCHEMA, STYLED_TEXT_SCHEMA, container_schema, part_schema -from ..types import LV_EVENT, char_ptr, lv_obj_t -from . import Widget, add_widgets, set_obj_properties -from .button import button_spec -from .buttonmatrix import ( - BUTTONMATRIX_BUTTON_SCHEMA, - CONF_BUTTON_TEXT_LIST_ID, - buttonmatrix_spec, - get_button_data, - lv_buttonmatrix_t, - set_btn_data, +from ..helpers import add_lv_use +from ..lv_validation import lv_bool, lv_image, lv_text, pixels_or_percent +from ..lvcode import EVENT_ARG, LambdaContext, LocalVariable, lv, lv_expr, lv_obj +from ..schemas import ( + STYLE_SCHEMA, + STYLED_TEXT_SCHEMA, + TEXT_SCHEMA, + container_schema, + part_schema, ) +from ..styles import LVStyle +from ..types import LV_EVENT, lv_obj_t +from . import Widget, WidgetType, add_widgets, set_obj_properties, widget_to_code +from .button import button_spec, lv_button_t from .label import CONF_LABEL from .obj import obj_spec CONF_MSGBOX = "msgbox" + +OUTER_STYLE = LVStyle( + "msgbox_outer", + { + "bg_opa": 128, + "bg_color": "black", + "border_width": 0, + "pad_all": 0, + "radius": 0, + }, +) + + +class FooterButtonType(WidgetType): + def __init__(self): + super().__init__( + CONF_BUTTON, lv_button_t, (CONF_MAIN,), TEXT_SCHEMA, is_mock=True + ) + + async def obj_creator(self, parent: MockObjClass, config: dict): + return lv_expr.msgbox_add_footer_button(parent, config[CONF_TEXT]) + + +footer_button_spec = FooterButtonType() + + +class HeaderButtonType(WidgetType): + def __init__(self): + super().__init__( + CONF_BUTTON, + lv_button_t, + (CONF_MAIN,), + cv.Schema( + { + cv.Required(CONF_SRC): lv_image, + } + ), + is_mock=True, + ) + + async def obj_creator(self, parent: MockObjClass, config: dict): + return lv_expr.msgbox_add_header_button( + parent, await lv_image.process(config[CONF_SRC]) + ) + + +header_button_spec = HeaderButtonType() + MSGBOX_SCHEMA = container_schema( obj_spec, STYLE_SCHEMA.extend( @@ -50,10 +92,14 @@ MSGBOX_SCHEMA = container_schema( cv.GenerateID(CONF_ID): cv.declare_id(lv_obj_t), cv.Required(CONF_TITLE): STYLED_TEXT_SCHEMA, cv.Optional(CONF_BODY, default=""): STYLED_TEXT_SCHEMA, - cv.Optional(CONF_BUTTONS): cv.ensure_list(BUTTONMATRIX_BUTTON_SCHEMA), - cv.Optional(CONF_BUTTON_STYLE): part_schema(buttonmatrix_spec.parts), + cv.Optional(CONF_BUTTONS): cv.ensure_list( + container_schema(footer_button_spec) + ), + cv.Optional(CONF_HEADER_BUTTONS): cv.ensure_list( + container_schema(header_button_spec) + ), cv.Optional(CONF_CLOSE_BUTTON, default=True): lv_bool, - cv.GenerateID(CONF_BUTTON_TEXT_LIST_ID): cv.declare_id(char_ptr), + cv.Optional(CONF_BUTTON_STYLE): part_schema(button_spec.parts), } ), ) @@ -62,7 +108,9 @@ MSGBOX_SCHEMA = container_schema( async def msgbox_to_code(top_layer, conf): """ Construct a message box. This consists of a full-screen translucent background enclosing a centered container - with an optional title, body, close button and a button matrix. And any other widgets the user cares to add + with an optional title, body, close button and a set of footer buttons. + Header buttons can be added - they can be image buttons only. + The body of the message box may have any widgets the user wants to add. :param conf: The config data :return: code to add to the init lambda """ @@ -71,60 +119,42 @@ async def msgbox_to_code(top_layer, conf): CONF_BUTTON, CONF_LABEL, CONF_MSGBOX, - *buttonmatrix_spec.get_uses(), *button_spec.get_uses(), ) - lvgl_components_required.add("BUTTONMATRIX") - messagebox_id = conf[CONF_ID] - outer_id = f"{messagebox_id.id}_outer" - outer = lv_Pvariable(lv_obj_t, messagebox_id.id + "_outer") - buttonmatrix = new_Pvariable( - ID( - f"{messagebox_id.id}_buttonmatrix_", - is_declaration=True, - type=lv_buttonmatrix_t, + if CONF_BUTTON_STYLE in conf: + add_warning( + "'button_style' for msgbox is deprecated - style the buttons directly." ) - ) - msgbox = lv_Pvariable(lv_obj_t, messagebox_id.id) - outer_widget = Widget.create(outer_id, outer, obj_spec, conf) + messagebox_id = conf[CONF_ID] + outer_id = ID(f"{messagebox_id.id}_outer", type=lv_obj_t) + outer = cg.Pvariable(outer_id, lv_expr.obj_create(top_layer)) + outer_widget = Widget.create(outer_id.id, outer, obj_spec, conf) + msgbox = cg.Pvariable(messagebox_id, lv_expr.msgbox_create(outer)) outer_widget.move_to_foreground = True msgbox_widget = Widget.create(messagebox_id, msgbox, obj_spec, conf) msgbox_widget.outer = outer_widget - buttonmatrix_widget = Widget.create( - str(buttonmatrix), buttonmatrix, buttonmatrix_spec, conf - ) - text_list, ctrl_list, width_list, _ = await get_button_data( - (conf,), buttonmatrix_widget - ) - text_id = conf[CONF_BUTTON_TEXT_LIST_ID] - text_list = static_const_array(text_id, text_list) text = await lv_text.process(conf[CONF_BODY].get(CONF_TEXT, "")) title = await lv_text.process(conf[CONF_TITLE].get(CONF_TEXT, "")) close_button = conf[CONF_CLOSE_BUTTON] - lv_assign(outer, lv_expr.obj_create(top_layer)) - lv_obj.set_width(outer, lv_pct(100)) - lv_obj.set_height(outer, lv_pct(100)) - lv_obj.set_style_bg_opa(outer, 128, 0) - lv_obj.set_style_bg_color(outer, literal("lv_color_black()"), 0) - lv_obj.set_style_border_width(outer, 0, 0) - lv_obj.set_style_pad_all(outer, 0, 0) - lv_obj.set_style_radius(outer, 0, 0) - outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") - lv_assign( - msgbox, lv_expr.msgbox_create(outer, title, text, text_list, close_button) - ) + percent100 = await pixels_or_percent.process(1.0) + lv_obj.set_size(outer, percent100, percent100) + outer_widget.add_style(await OUTER_STYLE.get_var()) + outer_widget.add_flag(LV_OBJ_FLAG.HIDDEN) + lv.msgbox_add_title(msgbox, title) + lv.msgbox_add_text(msgbox, text) lv_obj.set_style_align(msgbox, literal("LV_ALIGN_CENTER"), 0) - lv_add(buttonmatrix.set_obj(lv_expr.msgbox_get_btns(msgbox))) - if button_style := conf.get(CONF_BUTTON_STYLE): - button_style = {CONF_ITEMS: button_style} - await set_obj_properties(buttonmatrix_widget, button_style) await set_obj_properties(msgbox_widget, conf) await add_widgets(msgbox_widget, conf) + for button in conf.get(CONF_BUTTONS, ()): + await widget_to_code(button, footer_button_spec, msgbox) + for button in conf.get(CONF_HEADER_BUTTONS, ()): + await widget_to_code(button, header_button_spec, msgbox) + async with LambdaContext(EVENT_ARG, where=messagebox_id) as close_action: - outer_widget.add_flag("LV_OBJ_FLAG_HIDDEN") + outer_widget.add_flag(LV_OBJ_FLAG.HIDDEN) if close_button: with LocalVariable( - "close_btn_", lv_obj_t, lv_expr.msgbox_get_close_btn(msgbox) + "close_btn_", lv_obj_t, lv_expr.msgbox_add_close_button(msgbox) ) as close_btn: lv_obj.remove_event_cb(close_btn, nullptr) lv_obj.add_event_cb( @@ -138,9 +168,6 @@ async def msgbox_to_code(top_layer, conf): outer, await close_action.get_lambda(), LV_EVENT.CLICKED, nullptr ) - if len(ctrl_list) != 0 or len(width_list) != 0: - set_btn_data(buttonmatrix.obj, ctrl_list, width_list) - async def msgboxes_to_code(lv_component, config): top_layer = lv.disp_get_layer_top(lv_component.get_disp()) diff --git a/esphome/components/lvgl/widgets/obj.py b/esphome/components/lvgl/widgets/obj.py index ab22a5ce86..079a0734ef 100644 --- a/esphome/components/lvgl/widgets/obj.py +++ b/esphome/components/lvgl/widgets/obj.py @@ -1,5 +1,6 @@ from ..defines import CONF_MAIN, CONF_OBJ, CONF_SCROLLBAR -from ..types import WidgetType, lv_obj_t +from ..types import lv_obj_t +from . import WidgetType class ObjType(WidgetType): diff --git a/esphome/components/lvgl/widgets/qrcode.py b/esphome/components/lvgl/widgets/qrcode.py index ad46f67c6b..82c4370543 100644 --- a/esphome/components/lvgl/widgets/qrcode.py +++ b/esphome/components/lvgl/widgets/qrcode.py @@ -1,14 +1,15 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_SIZE, CONF_TEXT -from esphome.cpp_generator import MockObjClass -from ..defines import CONF_MAIN -from ..lv_validation import lv_color, lv_text -from ..lvcode import LocalVariable, lv, lv_expr +from ..defines import CONF_MAIN, get_color_formats +from ..lv_validation import color, lv_color, lv_int, lv_text +from ..lvcode import LocalVariable, lv from ..schemas import TEXT_SCHEMA -from ..types import WidgetType, lv_obj_t -from . import Widget +from ..types import lv_obj_t +from . import Widget, WidgetType +from .canvas import CONF_CANVAS +from .img import CONF_IMAGE CONF_QRCODE = "qrcode" CONF_DARK_COLOR = "dark_color" @@ -16,9 +17,16 @@ CONF_LIGHT_COLOR = "light_color" QRCODE_SCHEMA = { **TEXT_SCHEMA, - cv.Optional(CONF_DARK_COLOR, default="black"): lv_color, - cv.Optional(CONF_LIGHT_COLOR, default="white"): lv_color, - cv.Required(CONF_SIZE): cv.int_, + cv.Optional(CONF_DARK_COLOR, default="black"): color, + cv.Optional(CONF_LIGHT_COLOR, default="white"): color, + cv.Required(CONF_SIZE): lv_int, +} + +QRCODE_MODIFY_SCHEMA = { + **TEXT_SCHEMA, + cv.Optional(CONF_DARK_COLOR): lv_color, + cv.Optional(CONF_LIGHT_COLOR): lv_color, + cv.Optional(CONF_SIZE): lv_int, } @@ -29,20 +37,25 @@ class QrCodeType(WidgetType): lv_obj_t, (CONF_MAIN,), QRCODE_SCHEMA, - modify_schema=TEXT_SCHEMA, + modify_schema=QRCODE_MODIFY_SCHEMA, ) def get_uses(self): - return "canvas", "img", "label" - - async def obj_creator(self, parent: MockObjClass, config: dict): - dark_color = await lv_color.process(config[CONF_DARK_COLOR]) - light_color = await lv_color.process(config[CONF_LIGHT_COLOR]) - size = config[CONF_SIZE] - return lv_expr.call("qrcode_create", parent, size, dark_color, light_color) + return CONF_CANVAS, CONF_IMAGE async def to_code(self, w: Widget, config): + get_color_formats().add("ARGB8888") + await w.set_property( + CONF_LIGHT_COLOR, await lv_color.process(config.get(CONF_LIGHT_COLOR)) + ) + await w.set_property( + CONF_DARK_COLOR, await lv_color.process(config.get(CONF_DARK_COLOR)) + ) + await w.set_property(CONF_SIZE, await lv_int.process(config.get(CONF_SIZE))) if (value := config.get(CONF_TEXT)) is not None: + if isinstance(value, str): + lv.qrcode_update(w.obj, value, len(value)) + return value = await lv_text.process(value) with LocalVariable("qr_text", cg.std_string, value, modifier="") as str_obj: lv.qrcode_update(w.obj, str_obj.c_str(), str_obj.size()) diff --git a/esphome/components/lvgl/widgets/slider.py b/esphome/components/lvgl/widgets/slider.py index d5017668e4..85096c302a 100644 --- a/esphome/components/lvgl/widgets/slider.py +++ b/esphome/components/lvgl/widgets/slider.py @@ -2,18 +2,18 @@ import esphome.config_validation as cv from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE from ..defines import ( - BAR_MODES, CONF_ANIMATED, CONF_INDICATOR, CONF_KNOB, CONF_MAIN, + SLIDER_MODES, literal, ) -from ..helpers import add_lv_use from ..lv_validation import animated, get_start_value, lv_float from ..lvcode import lv -from ..types import LvNumber, NumberType -from . import Widget +from ..types import LvNumber +from . import NumberType, Widget +from .label import CONF_LABEL from .lv_bar import CONF_BAR CONF_SLIDER = "slider" @@ -29,7 +29,7 @@ SLIDER_SCHEMA = cv.Schema( cv.Optional(CONF_VALUE): lv_float, cv.Optional(CONF_MIN_VALUE, default=0): cv.int_, cv.Optional(CONF_MAX_VALUE, default=100): cv.int_, - cv.Optional(CONF_MODE, default="NORMAL"): BAR_MODES.one_of, + cv.Optional(CONF_MODE, default="NORMAL"): SLIDER_MODES.one_of, cv.Optional(CONF_ANIMATED, default=True): animated, } ) @@ -49,8 +49,10 @@ class SliderType(NumberType): def animated(self): return True + def get_uses(self): + return (CONF_BAR, CONF_LABEL) + async def to_code(self, w: Widget, config): - add_lv_use(CONF_BAR) if CONF_MIN_VALUE in config: # not modify case lv.slider_set_range(w.obj, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE]) diff --git a/esphome/components/lvgl/widgets/spinner.py b/esphome/components/lvgl/widgets/spinner.py index 83aac25a59..0e409ba3b7 100644 --- a/esphome/components/lvgl/widgets/spinner.py +++ b/esphome/components/lvgl/widgets/spinner.py @@ -1,9 +1,8 @@ import esphome.config_validation as cv -from esphome.cpp_generator import MockObjClass from ..defines import CONF_ARC_LENGTH, CONF_INDICATOR, CONF_MAIN, CONF_SPIN_TIME from ..lv_validation import lv_angle_degrees, lv_milliseconds -from ..lvcode import lv_expr +from ..lvcode import lv from ..types import LvType from . import Widget, WidgetType from .arc import CONF_ARC @@ -12,8 +11,10 @@ CONF_SPINNER = "spinner" SPINNER_SCHEMA = cv.Schema( { - cv.Required(CONF_ARC_LENGTH): lv_angle_degrees, - cv.Required(CONF_SPIN_TIME): lv_milliseconds, + cv.Optional(CONF_ARC_LENGTH, default=200): cv.All( + lv_angle_degrees, cv.int_range(min=0, max=360) + ), + cv.Optional(CONF_SPIN_TIME, default="2s"): lv_milliseconds, } ) @@ -25,19 +26,17 @@ class SpinnerType(WidgetType): LvType("lv_spinner_t"), (CONF_MAIN, CONF_INDICATOR), SPINNER_SCHEMA, - {}, ) async def to_code(self, w: Widget, config): - return [] + spin_time = await lv_milliseconds.process(config.get(CONF_SPIN_TIME)) + arc_length = int(config[CONF_ARC_LENGTH]) + if arc_length < 180: + arc_length += 180 + lv.spinner_set_anim_params(w.obj, spin_time, arc_length) def get_uses(self): return (CONF_ARC,) - async def obj_creator(self, parent: MockObjClass, config: dict): - spin_time = await lv_milliseconds.process(config[CONF_SPIN_TIME]) - arc_length = await lv_angle_degrees.process(config[CONF_ARC_LENGTH]) - return lv_expr.call("spinner_create", parent, spin_time, arc_length) - spinner_spec = SpinnerType() diff --git a/esphome/components/lvgl/widgets/tabview.py b/esphome/components/lvgl/widgets/tabview.py index cd7cf7b471..60ba664f04 100644 --- a/esphome/components/lvgl/widgets/tabview.py +++ b/esphome/components/lvgl/widgets/tabview.py @@ -1,8 +1,14 @@ from esphome import automation import esphome.codegen as cg import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_INDEX, CONF_NAME, CONF_POSITION, CONF_SIZE -from esphome.cpp_generator import MockObjClass +from esphome.const import ( + CONF_ID, + CONF_INDEX, + CONF_ITEMS, + CONF_NAME, + CONF_POSITION, + CONF_SIZE, +) from ..automation import action_to_code from ..defines import ( @@ -15,10 +21,11 @@ from ..defines import ( literal, ) from ..lv_validation import animated, lv_int, size -from ..lvcode import LocalVariable, lv, lv_assign, lv_expr +from ..lvcode import LocalVariable, lv, lv_assign, lv_expr, lv_obj from ..schemas import container_schema, part_schema from ..types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties +from .button import button_spec from .buttonmatrix import buttonmatrix_spec from .obj import obj_spec @@ -69,6 +76,10 @@ class TabviewType(WidgetType): return "btnmatrix", TYPE_FLEX async def to_code(self, w: Widget, config: dict): + await w.set_property( + "tab_bar_position", await DIRECTIONS.process(config[CONF_POSITION]) + ) + await w.set_property("tab_bar_size", await size.process(config[CONF_SIZE])) for tab_conf in config[CONF_TABS]: w_id = tab_conf[CONF_ID] tab_obj = cg.Pvariable(w_id, cg.nullptr, type_=lv_tab_t) @@ -76,25 +87,27 @@ class TabviewType(WidgetType): lv_assign(tab_obj, lv_expr.tabview_add_tab(w.obj, tab_conf[CONF_NAME])) await set_obj_properties(tab_widget, tab_conf) await add_widgets(tab_widget, tab_conf) - if button_style := config.get(CONF_TAB_STYLE): + tab_style = config.get(CONF_TAB_STYLE, {}) + tab_items_style = tab_style.get(CONF_ITEMS, {}) + if tab_style: with LocalVariable( - "tabview_btnmatrix", lv_obj_t, rhs=lv_expr.tabview_get_tab_btns(w.obj) - ) as btnmatrix_obj: - await set_obj_properties(Widget(btnmatrix_obj, obj_spec), button_style) + "tabview_bar", lv_obj_t, rhs=lv_expr.tabview_get_tab_bar(w.obj) + ) as bar_obj: + tab_bar = Widget(bar_obj, obj_spec) + await set_obj_properties(tab_bar, tab_style) + if tab_items_style: + for index, tab_conf in enumerate(config[CONF_TABS]): + await set_obj_properties( + Widget(lv_obj.get_child(bar_obj, index), button_spec), + tab_items_style, + ) + if content_style := config.get(CONF_CONTENT_STYLE): with LocalVariable( "tabview_content", lv_obj_t, rhs=lv_expr.tabview_get_content(w.obj) ) as content_obj: await set_obj_properties(Widget(content_obj, obj_spec), content_style) - async def obj_creator(self, parent: MockObjClass, config: dict): - return lv_expr.call( - "tabview_create", - parent, - await DIRECTIONS.process(config[CONF_POSITION]), - await size.process(config[CONF_SIZE]), - ) - tabview_spec = TabviewType() @@ -117,6 +130,6 @@ async def tabview_select(config, action_id, template_arg, args): async def do_select(w: Widget): lv.tabview_set_act(w.obj, index, literal(config[CONF_ANIMATED])) - lv.event_send(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) + lv.obj_send_event(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) return await action_to_code(widget, do_select, action_id, template_arg, args) diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 430a386d2e..dadaef7d07 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -15,7 +15,7 @@ from ..defines import ( TILE_DIRECTIONS, literal, ) -from ..lv_validation import animated, lv_int, lv_pct +from ..lv_validation import animated, lv_int, pixels_or_percent from ..lvcode import lv, lv_assign, lv_expr, lv_obj, lv_Pvariable from ..schemas import container_schema from ..types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr @@ -68,17 +68,19 @@ class TileviewType(WidgetType): w_id = tile_conf[CONF_ID] tile_obj = lv_Pvariable(lv_obj_t, w_id) tile = Widget.create(w_id, tile_obj, tile_spec, tile_conf) - dirs = tile_conf[CONF_DIR] - if isinstance(dirs, list): - dirs = "|".join(dirs) + dirs = await TILE_DIRECTIONS.process(tile_conf[CONF_DIR]) row_pos = tile_conf[CONF_ROW] col_pos = tile_conf[CONF_COLUMN] lv_assign( tile_obj, - lv_expr.tileview_add_tile(w.obj, col_pos, row_pos, literal(dirs)), + lv_expr.tileview_add_tile(w.obj, col_pos, row_pos, dirs), ) # Bugfix for LVGL 8.x - lv_obj.set_pos(tile_obj, lv_pct(col_pos * 100), lv_pct(row_pos * 100)) + lv_obj.set_pos( + tile_obj, + await pixels_or_percent.process(float(col_pos)), + await pixels_or_percent.process(float(row_pos)), + ) await set_obj_properties(tile, tile_conf) await add_widgets(tile, tile_conf) if tiles: diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 35a9de3537..292e2bb3bb 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -5,12 +5,14 @@ import esphome.codegen as cg from esphome.components import runtime_image from esphome.components.const import CONF_REQUEST_HEADERS from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent +from esphome.components.image import CONF_TRANSPARENCY, add_metadata import esphome.config_validation as cv from esphome.const import ( CONF_BUFFER_SIZE, CONF_ID, CONF_ON_ERROR, CONF_TRIGGER_ID, + CONF_TYPE, CONF_URL, ) from esphome.core import Lambda @@ -131,6 +133,13 @@ async def online_image_action_to_code(config, action_id, template_arg, args): async def to_code(config): # Use the enhanced helper function to get all runtime image parameters settings = await runtime_image.process_runtime_image_config(config) + add_metadata( + config[CONF_ID], + settings.width, + settings.height, + config[CONF_TYPE], + config[CONF_TRANSPARENCY], + ) url = config[CONF_URL] var = cg.new_Pvariable( diff --git a/esphome/components/runtime_image/__init__.py b/esphome/components/runtime_image/__init__.py index 3ae35cc5f1..8db69aa53e 100644 --- a/esphome/components/runtime_image/__init__.py +++ b/esphome/components/runtime_image/__init__.py @@ -181,7 +181,8 @@ async def process_runtime_image_config(config: dict) -> RuntimeImageSettings: transparent = get_transparency_enum(config.get(CONF_TRANSPARENCY, "OPAQUE")) # Get byte order (True for big endian, False for little endian) - byte_order_big_endian = config.get(CONF_BYTE_ORDER) != "LITTLE_ENDIAN" + # If unspecified, use little endian + byte_order_big_endian = config.get(CONF_BYTE_ORDER) == "BIG_ENDIAN" # Get placeholder if specified placeholder = None diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 5a4a2ea7d6..2ebe67c3a5 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -106,7 +106,7 @@ void RuntimeImage::draw_pixel(int x, int y, const Color &color) { break; } case image::IMAGE_TYPE_RGB565: { - uint32_t pos = this->get_position_(x, y); + const size_t pos = (x + y * this->buffer_width_) * 2; Color mapped_color = color; this->map_chroma_key(mapped_color); uint16_t rgb565 = display::ColorUtil::color_to_565(mapped_color); @@ -118,7 +118,8 @@ void RuntimeImage::draw_pixel(int x, int y, const Color &color) { this->buffer_[pos + 1] = static_cast<uint8_t>((rgb565 >> 8) & 0xFF); } if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { - this->buffer_[pos + 2] = color.w; + const size_t alpha_pos = pos / 2 + this->buffer_width_ * this->buffer_height_ * 2; + this->buffer_[alpha_pos] = color.w; } break; } @@ -283,6 +284,10 @@ size_t RuntimeImage::resize_buffer_(int width, int height) { } size_t RuntimeImage::get_buffer_size_(int width, int height) const { + if (this->get_type() == image::IMAGE_TYPE_RGB565 && this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { + // Add extra alpha channel for RGB565 with alpha + return width * height * 3; + } return (this->get_bpp() * width + 7u) / 8u * height; } diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 09269ea1b4..c817f8ef27 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -92,6 +92,7 @@ #define USE_LVGL_MSGBOX #define USE_LVGL_ROLLER #define USE_LVGL_ROTARY_ENCODER +#define USE_LVGL_SCALE #define USE_LVGL_SLIDER #define USE_LVGL_SPAN #define USE_LVGL_SPINBOX diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 620dc6131d..5cfa8532ff 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -77,3 +77,5 @@ dependencies: - if: "idf_version >=6.0.0 && target in [esp32s2, esp32s3, esp32p4]" esp32async/asynctcp: version: 3.4.91 + lvgl/lvgl: + version: 9.5.0 diff --git a/platformio.ini b/platformio.ini index 3c3d62ef76..c5a4c630df 100644 --- a/platformio.ini +++ b/platformio.ini @@ -42,7 +42,6 @@ lib_deps_base = https://github.com/esphome/TinyGPSPlus.git#v1.1.0 ; gps ; This is using the repository until a new release is published to PlatformIO https://github.com/Sensirion/arduino-gas-index-algorithm.git#3.2.1 ; Sensirion Gas Index Algorithm Arduino Library - lvgl/lvgl@8.4.0 ; lvgl lib_deps = ${common.lib_deps_base} @@ -120,6 +119,7 @@ lib_deps = ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) droscy/esp_wireguard@0.4.2 ; wireguard + lvgl/lvgl@9.5.0 ; lvgl build_flags = ${common:arduino.build_flags} @@ -204,6 +204,7 @@ lib_deps = ayushsharma82/RPAsyncTCP@1.3.2 ; async_tcp bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base + lvgl/lvgl@9.5.0 ; lvgl build_flags = ${common:arduino.build_flags} -DUSE_RP2040 @@ -221,6 +222,7 @@ lib_deps = bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base droscy/esp_wireguard@0.4.2 ; wireguard + lvgl/lvgl@9.5.0 ; lvgl build_flags = ${common:arduino.build_flags} -DUSE_LIBRETINY @@ -242,6 +244,7 @@ build_flags = lib_deps = ${common.lib_deps_base} bblanchon/ArduinoJson@7.4.2 ; json + lvgl/lvgl@9.5.0 ; lvgl ; All the actual environments are defined below. diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 3635fc710f..7d96b12a01 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -42,6 +42,11 @@ lvgl: disp_bg_color: color_id disp_bg_image: cat_image disp_bg_opa: cover + bottom_layer: + widgets: + - obj: + bg_color: 0x000000 + bg_opa: cover theme: obj: border_width: 1 @@ -49,12 +54,14 @@ lvgl: gradients: - id: color_bar direction: hor - dither: err_diff + # dither: err_diff stops: - color: 0xFF0000 position: 0 + opa: 100% - color: 0xFFFF00 position: 42 + opa: 80% - color: 0x00FF00 position: 84 - color: 0x00FFFF @@ -156,6 +163,16 @@ lvgl: offset_x: !lambda return 20; offset_y: !lambda return 20; antialias: !lambda return true; + - id: msgbox_with_header_buttons + title: Header Buttons Test + body: + text: Testing header buttons + header_buttons: + - src: cat_image + on_click: + logger.log: Header button clicked + buttons: + - text: OK - id: simple_msgbox title: Simple @@ -199,11 +216,11 @@ lvgl: text: Unloaded - lvgl.label.update: id: msgbox_label - text: "" # Empty text + text: "" # Empty text on_all_events: logger.log: format: "Event %s" - args: ['lv_event_code_name_for(event->code).c_str()'] + args: ['lv_event_code_name_for(event).c_str()'] skip: true layout: type: Flex @@ -241,7 +258,7 @@ lvgl: on_all_events: - logger.log: format: "Event %s" - args: ['lv_event_code_name_for(event->code).c_str()'] + args: ['lv_event_code_name_for(event).c_str()'] - lvgl.animimg.update: id: anim_img src: !lambda "return {dog_image, cat_image};" @@ -306,7 +323,6 @@ lvgl: anim_time: 1s bg_color: light_blue bg_grad_color: light_blue - bg_dither_mode: ordered bg_grad_dir: hor bg_grad_stop: 128 bg_image_opa: transp @@ -354,10 +370,18 @@ lvgl: text_line_space: 4 text_opa: cover transform_angle: 180 + transform_rotation: 90 transform_height: 100 transform_pivot_x: 50% transform_pivot_y: 50% transform_zoom: 0.5 + transform_scale: 2.0 + transform_scale_x: 1.5 + transform_scale_y: 0.8 + transform_skew_x: 10 + transform_skew_y: 20 + shadow_offset_x: 3 + shadow_offset_y: 3 translate_x: 10 translate_y: 10 max_height: 100 @@ -549,14 +573,16 @@ lvgl: arc_length: 120 spin_time: 2s align: left_mid + - spinner: + align: right_mid + send_draw_task_events: true - image: id: lv_image src: cat_image align: top_left y: "50" - mode: real - zoom: 2.0 - angle: 45 + scale: 2.0 + rotation: 45 - tileview: id: tileview_id scrollbar_mode: active @@ -661,8 +687,11 @@ lvgl: src: cat_image x: 100 y: 100 - angle: 90 - zoom: 2.0 + rotation: 90 + scale_x: 2.0 + scale_y: 1.5 + skew_x: 10 + skew_y: 5 pivot_x: 25 pivot_y: 25 - lvgl.canvas.draw_line: @@ -710,6 +739,9 @@ lvgl: text: format: "A string with a number %d" args: ['(int)(random_uint32() % 1000)'] + size: 120 + dark_color: navy + light_color: white - slider: min_value: 0 @@ -928,7 +960,6 @@ lvgl: grid_cell_row_pos: 0 grid_cell_column_pos: 0 src: !lambda return dog_image; - mode: virtual on_click: then: - lvgl.tabview.select: @@ -1023,10 +1054,18 @@ lvgl: text_color: 0xFFFFFF scales: - ticks: - width: !lambda return 1; + width: 1 count: 61 length: 20% + radial_offset: 5 color: 0xFFFFFF + major: + stride: 5 + width: 2 + length: 8 + color: 0xC0C0C0 + radial_offset: 3 + label_gap: 6 range_from: 0 range_to: 60 angle_range: 360 @@ -1037,15 +1076,15 @@ lvgl: end_value: 60 color_start: 0x0000bd color_end: 0xbd0000 - width: !lambda return 1; + width: 1 - line: opa: 50% id: minute_hand color: 0xFF0000 - r_mod: !lambda return -1; - width: !lambda return 3; - - - angle_range: 330 + length: 99% + radial_offset: 2 + width: 1 + - angle_range: 330 rotation: 300 range_from: 1 range_to: 12 @@ -1069,7 +1108,7 @@ lvgl: value: 180 width: 4 color: 0xA0A0A0 - r_mod: -20 + length: 80% opa: 0% - id: page3 layout: Horizontal From c2c50ceea7124d189785493f27ae3b99cb185243 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:10:01 +0100 Subject: [PATCH 1530/2030] [substitutions] substitutions pass and !include redesign (package refactor part 2a) (#14917) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/yaml_util.py | 52 +++++++++++- tests/unit_tests/test_yaml_util.py | 126 +++++++++++++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index bba4bbf487..d0eab4e44e 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -24,6 +24,7 @@ except ImportError: from esphome import core from esphome.config_helpers import Extend, Remove +from esphome.const import CONF_DEFAULTS from esphome.core import ( CORE, DocumentRange, @@ -88,6 +89,47 @@ def make_data_base( return value +class ConfigContext: + """This is a mixin class that holds substitution vars that should be applied + to the tagged node and its children. During configuration loading, context vars can + be added to nodes using `add_context` function, which applies the mixin storing + the captured values and unevaluated expressions. + The substitution pass then recreates the effective context by merging the context vars + from this node and parent nodes. + """ + + @property + def vars(self) -> dict[str, Any]: + return self._context_vars + + def set_context(self, vars: dict[str, Any]) -> None: + # pylint: disable=attribute-defined-outside-init + self._context_vars = vars + + +def add_context(value: Any, context_vars: dict[str, Any] | None) -> Any: + """Tags a list/string/dict value with context vars that must be applied to it and its children + during the substitution pass. If no vars are given, no tagging is done. + If the value is already tagged, the new context vars are merged with existing ones, + with new vars taking precedence. Returns the value tagged with ConfigContext. Returns + the original value if value is not a list/string/dict. + """ + if isinstance(value, dict) and CONF_DEFAULTS in value: + context_vars = { + **value.pop(CONF_DEFAULTS), + **(context_vars or {}), + } + + if isinstance(value, ConfigContext): + value.set_context({**value.vars, **(context_vars or {})}) + return value + + if context_vars and isinstance(value, (dict, list, str)): + value = add_class_to_obj(value, ConfigContext) + value.set_context(context_vars) + return value + + def _add_data_ref(fn): @functools.wraps(fn) def wrapped(loader, node): @@ -455,7 +497,7 @@ def parse_yaml( def substitute_vars(config, vars): from esphome.components import substitutions - from esphome.const import CONF_DEFAULTS, CONF_SUBSTITUTIONS + from esphome.const import CONF_SUBSTITUTIONS org_subs = None result = config @@ -612,6 +654,12 @@ class ESPHomeDumper(yaml.SafeDumper): return self.represent_secret(value.value) return self.represent_scalar(tag="!lambda", value=value.value, style="|") + def represent_extend(self, value): + return self.represent_scalar(tag="!extend", value=value.value) + + def represent_remove(self, value): + return self.represent_scalar(tag="!remove", value=value.value) + def represent_id(self, value): if is_secret(value.id): return self.represent_secret(value.id) @@ -638,6 +686,8 @@ ESPHomeDumper.add_multi_representer(_BaseNetwork, ESPHomeDumper.represent_string ESPHomeDumper.add_multi_representer(MACAddress, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(TimePeriod, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(Lambda, ESPHomeDumper.represent_lambda) +ESPHomeDumper.add_multi_representer(Extend, ESPHomeDumper.represent_extend) +ESPHomeDumper.add_multi_representer(Remove, ESPHomeDumper.represent_remove) ESPHomeDumper.add_multi_representer(core.ID, ESPHomeDumper.represent_id) ESPHomeDumper.add_multi_representer(uuid.UUID, ESPHomeDumper.represent_stringify) ESPHomeDumper.add_multi_representer(Path, ESPHomeDumper.represent_stringify) diff --git a/tests/unit_tests/test_yaml_util.py b/tests/unit_tests/test_yaml_util.py index c8cb3e144f..adb7658bfd 100644 --- a/tests/unit_tests/test_yaml_util.py +++ b/tests/unit_tests/test_yaml_util.py @@ -6,6 +6,7 @@ import pytest from esphome import core, yaml_util from esphome.components import substitutions +from esphome.config_helpers import Extend, Remove from esphome.core import EsphomeError from esphome.util import OrderedDict @@ -306,3 +307,128 @@ def test_dump_sort_keys() -> None: # nested keys should also be sorted assert "a_key:" in sorted_dump assert sorted_dump.index("a_key:") < sorted_dump.index("z_key:") + + +@pytest.mark.parametrize( + "data", + [ + { + "key1": "value1", + "key2": 42, + }, + [1, 2, 3], + "simple string", + ], +) +def test_config_context_mixin(data) -> None: + """Test that ConfigContext mixin correctly stores and retrieves context vars in a dict.""" + + context_vars = { + "var1": "context_value1", + "var2": 100, + } + + # Add context to the data + tagged_data = yaml_util.add_context(data, context_vars) + + # Check that tagged_data has ConfigContext and correct vars + assert isinstance(tagged_data, type(data)) + assert isinstance(tagged_data, yaml_util.ConfigContext) + assert tagged_data.vars == context_vars + + # Check that original data is preserved + assert tagged_data == data + + +def test_config_context_mixin_no_context() -> None: + """Test that add_context does not tag data when no context vars are provided.""" + data = {"key": "value"} + + # Add context with None + tagged_data = yaml_util.add_context(data, None) + + # Should return original data without tagging + assert tagged_data is data + assert not isinstance(tagged_data, yaml_util.ConfigContext) + + +def test_config_context_mixin_merge_contexts() -> None: + """Test that add_context merges new context vars with existing ones.""" + data = {"key": "value"} + + initial_context = { + "var1": "initial_value", + } + + # First, add initial context + tagged_data = yaml_util.add_context(data, initial_context) + + assert isinstance(tagged_data, yaml_util.ConfigContext) + assert tagged_data.vars == initial_context + + # Now, add more context vars + new_context = { + "var2": "new_value", + "var1": "overridden_value", # This should override the initial var1 + } + + merged_tagged_data = yaml_util.add_context(tagged_data, new_context) + + # Check that merged_tagged_data has merged context vars + expected_context = { + "var1": "overridden_value", + "var2": "new_value", + } + assert isinstance(merged_tagged_data, yaml_util.ConfigContext) + assert merged_tagged_data.vars == expected_context + + # Check that original data is preserved + assert merged_tagged_data == data + + +@pytest.mark.parametrize("data", [42, 3.14, True, None]) +def test_config_context_non_taggable(data) -> None: + """Test that add_context ignores non-string scalar values.""" + + context_vars = { + "var1": "context_value", + } + + # Add context to the scalar data + tagged_data = yaml_util.add_context(data, context_vars) + + # Check that tagged_data has ConfigContext and correct vars + assert not isinstance(tagged_data, yaml_util.ConfigContext) + + # Check that original data is preserved + assert tagged_data == data + + +def test_config_context_defaults_only() -> None: + """Test that defaults: key is popped and used as context vars when no explicit vars given.""" + data = {"defaults": {"x": "1", "y": "2"}, "key": "value"} + tagged = yaml_util.add_context(data, None) + + assert isinstance(tagged, yaml_util.ConfigContext) + assert tagged.vars == {"x": "1", "y": "2"} + assert "defaults" not in tagged + + +def test_config_context_defaults_explicit_vars_override() -> None: + """Test that explicit vars take precedence over defaults: values.""" + data = {"defaults": {"x": "default_x", "z": "default_z"}, "key": "value"} + tagged = yaml_util.add_context(data, {"x": "explicit_x", "w": "explicit_w"}) + + assert isinstance(tagged, yaml_util.ConfigContext) + assert tagged.vars == {"x": "explicit_x", "z": "default_z", "w": "explicit_w"} + assert "defaults" not in tagged + + +def test_represent_extend() -> None: + """Test that Extend objects are dumped as plain !extend scalars.""" + assert yaml_util.dump({"key": Extend("my_id")}) == "key: !extend 'my_id'\n" + + +def test_represent_remove() -> None: + """Test that Remove objects are dumped as plain !remove scalars.""" + assert yaml_util.dump({"key": Remove("my_id")}) == "key: !remove 'my_id'\n" From 0a3393bed3fbc8623e9d955461783a65ae6c273c Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:13:36 +0100 Subject: [PATCH 1531/2030] [core] Disable LeakSanitizer in C++ unit tests (#14712) --- script/cpp_unit_test.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/cpp_unit_test.py b/script/cpp_unit_test.py index 5594d64240..f8bab39414 100755 --- a/script/cpp_unit_test.py +++ b/script/cpp_unit_test.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse from functools import partial +import os from pathlib import Path import sys @@ -35,6 +36,7 @@ PLATFORMIO_OPTIONS = { def run_tests(selected_components: list[str]) -> int: + os.environ["ASAN_OPTIONS"] = "detect_leaks=0" return build_and_run( selected_components=selected_components, tests_dir=COMPONENTS_TESTS_DIR, From 2c31bdc6a251eeaa2ba56e9ae59ab27163950a07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:43:50 -1000 Subject: [PATCH 1532/2030] Bump aioesphomeapi from 44.6.0 to 44.6.1 (#14954) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f8f60f1932..9e2f4efe3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.6.0 +aioesphomeapi==44.6.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 96da6dd075435d18dd50dc2b700f5fada19620f0 Mon Sep 17 00:00:00 2001 From: luar123 <49960470+luar123@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:41:11 +0100 Subject: [PATCH 1533/2030] [esp32] Add custom partitions and refactor partition table generation (#7682) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 287 +++++++++++++++--- esphome/config_validation.py | 7 + tests/components/esp32/test.esp32-s3-idf.yaml | 5 + 3 files changed, 252 insertions(+), 47 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 18178c83ff..64e5f44081 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -28,6 +28,7 @@ from esphome.const import ( CONF_PLATFORMIO_OPTIONS, CONF_REF, CONF_SAFE_MODE, + CONF_SIZE, CONF_SOURCE, CONF_TYPE, CONF_VARIANT, @@ -96,6 +97,7 @@ CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision" CONF_RELEASE = "release" +CONF_SUBTYPE = "subtype" ARDUINO_FRAMEWORK_NAME = "framework-arduinoespressif32" ARDUINO_FRAMEWORK_PKG = f"pioarduino/{ARDUINO_FRAMEWORK_NAME}" @@ -1258,6 +1260,43 @@ def _set_default_framework(config): return config +RESERVED_PARTITION_NAMES = { + "nvs", + "app0", + "app1", + "otadata", + "eeprom", + "spiffs", + "phy_init", +} + +VALID_APP_SUBTYPES = {"factory", "test"} +VALID_DATA_SUBTYPES = { + "nvs", + "nvs_keys", + "spiffs", + "coredump", + "efuse", + "fat", + "undefined", + "littlefs", +} + + +def _validate_custom_partition(config: ConfigType) -> ConfigType: + """Voluptuous validator for custom partition schema.""" + try: + _validate_partition( + config[CONF_NAME], + config[CONF_TYPE], + config[CONF_SUBTYPE], + config[CONF_SIZE], + ) + except ValueError as e: + raise cv.Invalid(str(e)) from e + return config + + FLASH_SIZES = [ "2MB", "4MB", @@ -1280,7 +1319,28 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of( *FLASH_SIZES, upper=True ), - cv.Optional(CONF_PARTITIONS): cv.file_, + cv.Optional(CONF_PARTITIONS): cv.Any( + cv.file_, + cv.ensure_list( + cv.All( + cv.Schema( + { + cv.Required(CONF_NAME): cv.string_strict, + cv.Required(CONF_TYPE): cv.All( + cv.Any(cv.string_strict, cv.int_range(0x40, 0xFE)), + cv.int_to_hex_string, + ), + cv.Required(CONF_SUBTYPE): cv.All( + cv.Any(cv.string_strict, cv.int_range(0, 0xFE)), + cv.int_to_hex_string, + ), + cv.Required(CONF_SIZE): cv.int_range(min=0x1000), + } + ), + _validate_custom_partition, + ), + ), + ), cv.Optional(CONF_VARIANT): cv.one_of(*VARIANTS, upper=True), cv.Optional(CONF_FRAMEWORK): FRAMEWORK_SCHEMA, } @@ -1749,9 +1809,18 @@ async def to_code(config): if use_platformio: cg.add_platformio_option("board_build.partitions", "partitions.csv") if CONF_PARTITIONS in config: - add_extra_build_file( - "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS]) - ) + if isinstance(config[CONF_PARTITIONS], list): + for partition in config[CONF_PARTITIONS]: + add_partition( + partition[CONF_NAME], + partition[CONF_TYPE], + partition[CONF_SUBTYPE], + partition[CONF_SIZE], + ) + else: + add_extra_build_file( + "partitions.csv", CORE.relative_config_path(config[CONF_PARTITIONS]) + ) if assertion_level := advanced.get(CONF_ASSERTION_LEVEL): for key, flag in ASSERTION_LEVELS.items(): @@ -1885,45 +1954,175 @@ async def to_code(config): CORE.add_job(_write_arduino_libraries_sdkconfig) -APP_PARTITION_SIZES = { - "2MB": 0x0C0000, # 768 KB - "4MB": 0x1C0000, # 1792 KB - "8MB": 0x3C0000, # 3840 KB - "16MB": 0x7C0000, # 7936 KB - "32MB": 0xFC0000, # 16128 KB +KEY_CUSTOM_PARTITIONS = "custom_partitions" + + +@dataclass +class PartitionEntry: + name: str + type: str + subtype: str + size: int + + +# Partition sizes (offsets auto-placed by gen_esp32part.py). +# These constants are the single source of truth — used in both +# the CSV generation and the overhead calculation. +BOOTLOADER_SIZE = 0x8000 +PARTITION_TABLE_SIZE = 0x1000 +FIRST_PARTITION_OFFSET = BOOTLOADER_SIZE + PARTITION_TABLE_SIZE +OTADATA_SIZE = 0x2000 +PHY_INIT_SIZE = 0x1000 +EEPROM_SIZE = 0x1000 # Arduino only +SPIFFS_SIZE = 0xF000 # Arduino only +ARDUINO_NVS_SIZE = 0x60000 +IDF_NVS_SIZE = 0x70000 + + +def _get_partition_overhead() -> int: + """Total non-app partition budget (system partitions + nvs + padding). + + Custom partitions are appended at the end and steal from app. + """ + # otadata + phy_init are followed by app0 which requires 64KB alignment, + # so pad up to the next 64KB boundary. + overhead = ( + FIRST_PARTITION_OFFSET + OTADATA_SIZE + PHY_INIT_SIZE + 0xFFFF + ) & ~0xFFFF + if CORE.using_arduino: + overhead += EEPROM_SIZE + SPIFFS_SIZE + ARDUINO_NVS_SIZE + else: + overhead += IDF_NVS_SIZE + return overhead + + +VALID_SUBTYPES: dict[str, set[str]] = { + "app": VALID_APP_SUBTYPES, + "data": VALID_DATA_SUBTYPES, } -def get_arduino_partition_csv(flash_size: str): - app_partition_size = APP_PARTITION_SIZES[flash_size] - eeprom_partition_size = 0x1000 # 4 KB - spiffs_partition_size = 0xF000 # 60 KB - - app0_partition_start = 0x010000 # 64 KB - app1_partition_start = app0_partition_start + app_partition_size - eeprom_partition_start = app1_partition_start + app_partition_size - spiffs_partition_start = eeprom_partition_start + eeprom_partition_size - - return f"""\ -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xE000, 0x2000, -app0, app, ota_0, 0x{app0_partition_start:X}, 0x{app_partition_size:X}, -app1, app, ota_1, 0x{app1_partition_start:X}, 0x{app_partition_size:X}, -eeprom, data, 0x99, 0x{eeprom_partition_start:X}, 0x{eeprom_partition_size:X}, -spiffs, data, spiffs, 0x{spiffs_partition_start:X}, 0x{spiffs_partition_size:X} -""" +def _validate_partition( + name: str, p_type: str | int, subtype: str | int, size: int +) -> None: + """Validate partition parameters. Raises ValueError on invalid input.""" + if name in RESERVED_PARTITION_NAMES: + raise ValueError(f"Partition name '{name}' is reserved.") + if size % 0x1000 != 0: + raise ValueError("Partition size must be 4KB (0x1000) aligned.") + # Numeric or already-normalized hex types/subtypes skip string validation + if not isinstance(p_type, str) or p_type.startswith("0x"): + return + if p_type not in VALID_SUBTYPES: + raise ValueError( + f"Type '{p_type}' is invalid. Only 'app' and 'data' are allowed." + " Use numbers for custom types." + ) + if not isinstance(subtype, str) or subtype.startswith("0x"): + return + valid = VALID_SUBTYPES[p_type] + if subtype not in valid: + raise ValueError( + f"Subtype '{subtype}' is invalid for {p_type} type." + f" Only {', '.join(sorted(valid))} are allowed." + " Use numbers for custom subtypes." + ) -def get_idf_partition_csv(flash_size: str): - app_partition_size = APP_PARTITION_SIZES[flash_size] +def add_partition(name: str, p_type: str | int, subtype: str | int, size: int) -> None: + """Register a custom partition to be appended to the partition table. - return f"""\ -otadata, data, ota, , 0x2000, -phy_init, data, phy, , 0x1000, -app0, app, ota_0, , 0x{app_partition_size:X}, -app1, app, ota_1, , 0x{app_partition_size:X}, -nvs, data, nvs, , 0x6D000, -""" + Called from component to_code() to request additional flash partitions. + Size must be 4KB aligned. Integer types/subtypes are converted to hex strings. + """ + if name in CORE.data[KEY_ESP32].get(KEY_CUSTOM_PARTITIONS, {}): + raise ValueError(f"Partition name '{name}' is already defined.") + _validate_partition(name, p_type, subtype, size) + p_type_str = f"0x{p_type:X}" if isinstance(p_type, int) else p_type + subtype_str = f"0x{subtype:X}" if isinstance(subtype, int) else subtype + custom_partitions = CORE.data[KEY_ESP32].setdefault(KEY_CUSTOM_PARTITIONS, {}) + custom_partitions[name] = PartitionEntry( + name=name, type=p_type_str, subtype=subtype_str, size=size + ) + + +def _flash_size_to_bytes(flash_size_mb: str) -> int: + """Convert flash size string (e.g. '4MB') to bytes.""" + return int(flash_size_mb.removesuffix("MB")) * 1024 * 1024 + + +def _get_custom_partitions_total_size() -> int: + """Total size of custom partitions including alignment padding.""" + size = 0 + for partition in CORE.data[KEY_ESP32].get(KEY_CUSTOM_PARTITIONS, {}).values(): + if partition.type == "app": + size = (size + 0xFFFF) & ~0xFFFF # align to 64KB + size += partition.size + return size + + +def _get_app_partition_size(flash_size_mb: str) -> int: + flash_bytes = _flash_size_to_bytes(flash_size_mb) + custom_total = _get_custom_partitions_total_size() + # Align down to 64KB — app partitions require 64KB-aligned offsets, + # so the size must also be aligned to avoid unbudgeted padding. + raw_size = (flash_bytes - _get_partition_overhead() - custom_total) // 2 + app_size = raw_size & ~0xFFFF + wasted = (raw_size - app_size) * 2 + if wasted: + _LOGGER.info( + "Custom partitions cause %dKB of wasted flash due to 64KB app partition alignment.", + wasted // 1024, + ) + if app_size <= 0x10000: # 64 KB + raise ValueError( + "Custom partitions are too large to fit in the available flash size. " + "Reduce custom partition sizes." + ) + if app_size <= 0x80000: # 512 KB + _LOGGER.warning( + "App partition size is only %dKB. This may be too small for firmware with " + "many components. Consider reducing custom partition sizes or using a " + "larger flash chip.", + app_size // 1024, + ) + return app_size + + +def get_partition_csv(flash_size_mb: str) -> str: + app_size = _get_app_partition_size(flash_size_mb) + + partitions: list[PartitionEntry] = [ + PartitionEntry(name="otadata", type="data", subtype="ota", size=OTADATA_SIZE), + PartitionEntry(name="phy_init", type="data", subtype="phy", size=PHY_INIT_SIZE), + PartitionEntry(name="app0", type="app", subtype="ota_0", size=app_size), + PartitionEntry(name="app1", type="app", subtype="ota_1", size=app_size), + ] + if CORE.using_arduino: + partitions.append( + PartitionEntry(name="eeprom", type="data", subtype="0x99", size=EEPROM_SIZE) + ) + partitions.append( + PartitionEntry( + name="spiffs", type="data", subtype="spiffs", size=SPIFFS_SIZE + ) + ) + partitions.append( + PartitionEntry( + name="nvs", type="data", subtype="nvs", size=ARDUINO_NVS_SIZE + ) + ) + else: + partitions.append( + PartitionEntry(name="nvs", type="data", subtype="nvs", size=IDF_NVS_SIZE) + ) + partitions.extend(CORE.data[KEY_ESP32].get(KEY_CUSTOM_PARTITIONS, {}).values()) + + csv = "".join( + f"{p.name}, {p.type}, {p.subtype}, , 0x{p.size:X},\n" for p in partitions + ) + _LOGGER.debug("Partition table:\n%s", csv) + return csv def _format_sdkconfig_val(value: SdkconfigValueType) -> str: @@ -2030,16 +2229,10 @@ def copy_files(): if "partitions.csv" not in CORE.data[KEY_ESP32][KEY_EXTRA_BUILD_FILES]: flash_size = CORE.data[KEY_ESP32][KEY_FLASH_SIZE] - if CORE.using_arduino: - write_file_if_changed( - CORE.relative_build_path("partitions.csv"), - get_arduino_partition_csv(flash_size), - ) - else: - write_file_if_changed( - CORE.relative_build_path("partitions.csv"), - get_idf_partition_csv(flash_size), - ) + write_file_if_changed( + CORE.relative_build_path("partitions.csv"), + get_partition_csv(flash_size), + ) # IDF build scripts look for version string to put in the build. # However, if the build path does not have an initialized git repo, # and no version.txt file exists, the CMake script fails for some setups. diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 32689dab27..56f255a076 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -494,6 +494,13 @@ def hex_int(value): return HexInt(int_(value)) +def int_to_hex_string(value: int | str) -> str: + """Convert an integer to a hex string (e.g. 64 -> '0x40'). Pass-through strings.""" + if isinstance(value, int): + return f"0x{value:X}" + return value + + def int_(value): """Validate that the config option is an integer. diff --git a/tests/components/esp32/test.esp32-s3-idf.yaml b/tests/components/esp32/test.esp32-s3-idf.yaml index 7a3bbe55b3..b9a3b804a8 100644 --- a/tests/components/esp32/test.esp32-s3-idf.yaml +++ b/tests/components/esp32/test.esp32-s3-idf.yaml @@ -1,5 +1,10 @@ esp32: variant: esp32s3 + partitions: + - name: my_data + type: data + subtype: spiffs + size: 0x1000 framework: type: esp-idf advanced: From 0858ecbb8e425c54638fe2151cce3a2bad5048e8 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Thu, 19 Mar 2026 08:05:12 -0400 Subject: [PATCH 1534/2030] [spa06_base] Add SPA06-003 Temperature and Pressure Sensor (Part 1 of 3) (#14521) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/spa06_base/__init__.py | 201 ++++++++++++ esphome/components/spa06_base/spa06_base.cpp | 320 +++++++++++++++++++ esphome/components/spa06_base/spa06_base.h | 257 +++++++++++++++ 4 files changed, 779 insertions(+) create mode 100644 esphome/components/spa06_base/__init__.py create mode 100644 esphome/components/spa06_base/spa06_base.cpp create mode 100644 esphome/components/spa06_base/spa06_base.h diff --git a/CODEOWNERS b/CODEOWNERS index 88f62c3194..5869925d7c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -457,6 +457,7 @@ esphome/components/sn74hc165/* @jesserockz esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/sound_level/* @kahrendt +esphome/components/spa06_base/* @danielkent-net esphome/components/speaker/* @jesserockz @kahrendt esphome/components/speaker/media_player/* @kahrendt @synesthesiam esphome/components/speaker_source/* @kahrendt diff --git a/esphome/components/spa06_base/__init__.py b/esphome/components/spa06_base/__init__.py new file mode 100644 index 0000000000..97d09aad81 --- /dev/null +++ b/esphome/components/spa06_base/__init__.py @@ -0,0 +1,201 @@ +import math + +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ID, + CONF_OVERSAMPLING, + CONF_PRESSURE, + CONF_SAMPLE_RATE, + CONF_TEMPERATURE, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PASCAL, +) + +CODEOWNERS = ["@danielkent-net"] + +spa06_ns = cg.esphome_ns.namespace("spa06_base") + +SampleRate = spa06_ns.enum("SampleRate") +SAMPLE_RATE_OPTIONS = { + "1": SampleRate.SAMPLE_RATE_1, + "2": SampleRate.SAMPLE_RATE_2, + "4": SampleRate.SAMPLE_RATE_4, + "8": SampleRate.SAMPLE_RATE_8, + "16": SampleRate.SAMPLE_RATE_16, + "32": SampleRate.SAMPLE_RATE_32, + "64": SampleRate.SAMPLE_RATE_64, + "128": SampleRate.SAMPLE_RATE_128, + "25p16": SampleRate.SAMPLE_RATE_25P16, + "25p8": SampleRate.SAMPLE_RATE_25P8, + "25p4": SampleRate.SAMPLE_RATE_25P4, + "25p2": SampleRate.SAMPLE_RATE_25P2, + "25": SampleRate.SAMPLE_RATE_25, + "50": SampleRate.SAMPLE_RATE_50, + "100": SampleRate.SAMPLE_RATE_100, + "200": SampleRate.SAMPLE_RATE_200, +} + +Oversampling = spa06_ns.enum("Oversampling") +OVERSAMPLING_OPTIONS = { + "NONE": Oversampling.OVERSAMPLING_NONE, + "2X": Oversampling.OVERSAMPLING_X2, + "4X": Oversampling.OVERSAMPLING_X4, + "8X": Oversampling.OVERSAMPLING_X8, + "16X": Oversampling.OVERSAMPLING_X16, + "32X": Oversampling.OVERSAMPLING_X32, + "64X": Oversampling.OVERSAMPLING_X64, + "128X": Oversampling.OVERSAMPLING_X128, +} + +SPA06Component = spa06_ns.class_("SPA06Component", cg.PollingComponent) + + +def spa_oversample_time(oversample): + # Pressure oversampling conversion times are listed on datasheet Pg. 26 + # Datasheet does not have a table for temperature oversampling; + # assumption is that it is the same as pressure + OVERSAMPLING_CONVERSION_TIMES = { + "NONE": 3.6, + "2X": 5.2, + "4X": 8.4, + "8X": 14.8, + "16X": 27.6, + "32X": 53.2, + "64X": 104.4, + "128X": 206.8, + } + return OVERSAMPLING_CONVERSION_TIMES[oversample] + + +def spa_sample_rate(rate): + SAMPLE_RATE_OPTIONS_HZ = { + "1": 1.0, + "2": 2.0, + "4": 4.0, + "8": 8.0, + "16": 16.0, + "32": 32.0, + "64": 64.0, + "128": 128.0, + "25p16": 25.0 / 16.0, + "25p8": 25.0 / 8.0, + "25p4": 25.0 / 4.0, + "25p2": 25.0 / 2.0, + "25": 25.0, + "50": 50.0, + "100": 100.0, + "200": 200.0, + } + return SAMPLE_RATE_OPTIONS_HZ[rate] + + +def compute_measurement_conversion_time(config): + # - adds up sensor conversion time based on temperature and pressure oversampling rates given in datasheet + # - returns a rounded up time in ms + + # No conversion time necessary without a pressure sensor + pressure_conversion_time = 0.0 + if pressure_config := config.get(CONF_PRESSURE): + pressure_conversion_time = spa_oversample_time( + pressure_config.get(CONF_OVERSAMPLING) + ) + # Temperature required in all cases, default to minimum sample time + temperature_conversion_time = 3.6 + if temperature_config := config.get(CONF_TEMPERATURE): + temperature_conversion_time = spa_oversample_time( + temperature_config.get(CONF_OVERSAMPLING) + ) + + # TODO: Read datasheet to find conversion time error + return math.ceil(1.05 * (pressure_conversion_time + temperature_conversion_time)) + + +def measurement_timing_check(config): + + temp_time = 0.0 + if temperature_config := config.get(CONF_TEMPERATURE): + temp_oss = ( + spa_oversample_time(temperature_config.get(CONF_OVERSAMPLING)) / 1000.0 + ) + temp_hz = spa_sample_rate(temperature_config.get(CONF_SAMPLE_RATE)) + temp_time = temp_oss * temp_hz + + pres_time = 0.0 + if pressure_config := config.get(CONF_PRESSURE): + pres_oss = spa_oversample_time(pressure_config.get(CONF_OVERSAMPLING)) / 1000.0 + pres_hz = spa_sample_rate(pressure_config.get(CONF_SAMPLE_RATE)) + pres_time = pres_oss * pres_hz + + if temp_time + pres_time >= 1: + raise cv.Invalid( + "Combined sample_rate and oversampling for temperature and pressure is too high" + ) + return config + + +CONFIG_SCHEMA_BASE = cv.Schema( + { + cv.GenerateID(): cv.declare_id(SPA06Component), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="NONE"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + cv.Optional(CONF_SAMPLE_RATE, default="1"): cv.enum( + SAMPLE_RATE_OPTIONS, lower=True + ), + } + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + unit_of_measurement=UNIT_PASCAL, + accuracy_decimals=0, + device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE, + state_class=STATE_CLASS_MEASUREMENT, + ).extend( + { + cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( + OVERSAMPLING_OPTIONS, upper=True + ), + cv.Optional(CONF_SAMPLE_RATE, default="1"): cv.enum( + SAMPLE_RATE_OPTIONS, lower=True + ), + } + ), + }, +).extend(cv.polling_component_schema("60s")) +CONFIG_SCHEMA_BASE.add_extra(measurement_timing_check) + + +async def to_code_base(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature_sensor(sens)) + cg.add( + var.set_temperature_oversampling_config( + temperature_config[CONF_OVERSAMPLING] + ) + ) + cg.add( + var.set_temperature_sample_rate_config(temperature_config[CONF_SAMPLE_RATE]) + ) + + if pressure_config := config.get(CONF_PRESSURE): + sens = await sensor.new_sensor(pressure_config) + cg.add(var.set_pressure_sensor(sens)) + cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING])) + cg.add(var.set_pressure_sample_rate_config(pressure_config[CONF_SAMPLE_RATE])) + + cg.add(var.set_conversion_time(compute_measurement_conversion_time(config))) + return var diff --git a/esphome/components/spa06_base/spa06_base.cpp b/esphome/components/spa06_base/spa06_base.cpp new file mode 100644 index 0000000000..36268aa9a2 --- /dev/null +++ b/esphome/components/spa06_base/spa06_base.cpp @@ -0,0 +1,320 @@ +#include "spa06_base.h" + +#include "esphome/core/helpers.h" + +namespace esphome::spa06_base { + +static const char *const TAG = "spa06"; + +// Sign extension function for <=16 bit types +inline int16_t decode16(uint8_t msb, uint8_t lsb, size_t bits, size_t head = 0) { + return static_cast<int16_t>(encode_uint16(msb, lsb) << head) >> (16 - bits); +} + +// Sign extension function for <=32 bit types +inline int32_t decode32(uint8_t xmsb, uint8_t msb, uint8_t lsb, uint8_t xlsb, size_t bits, size_t head = 0) { + return static_cast<int32_t>(encode_uint32(xmsb, msb, lsb, xlsb) << head) >> (32 - bits); +} + +void SPA06Component::dump_config() { + ESP_LOGCONFIG(TAG, "SPA06:"); + LOG_UPDATE_INTERVAL(this); + ESP_LOGCONFIG(TAG, " Measurement conversion time: %ums", this->conversion_time_); + if (this->temperature_sensor_) { + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); + ESP_LOGCONFIG(TAG, + " Oversampling: %s\n" + " Rate: %s", + LOG_STR_ARG(oversampling_to_str(this->temperature_oversampling_)), + LOG_STR_ARG(meas_rate_to_str(this->temperature_rate_))); + } + if (this->pressure_sensor_) { + LOG_SENSOR(" ", "Pressure", this->pressure_sensor_); + ESP_LOGCONFIG(TAG, + " Oversampling: %s\n" + " Rate: %s", + LOG_STR_ARG(oversampling_to_str(this->pressure_oversampling_)), + LOG_STR_ARG(meas_rate_to_str(this->pressure_rate_))); + } +} + +void SPA06Component::setup() { + // Startup sequence for SPA06 (Pg. 16, Figure 4.6.4): + // 1. Perform a soft reset + // 2. Verify sensor chip ID matches + // 3. Verify coefficients are ready + // 4. Read coefficients + // 5. Configure temperature and pressure sensors + // 6. Write communication settings + // 7. Write measurement settings (background measurement mode) + + // 1. Soft reset + if (!this->soft_reset_()) { + this->mark_failed(LOG_STR("Reset failed")); + return; + } + + // soft_reset_() internally delays by 3ms to make sure that + // the sensor is in a ready state and coefficients are ready. + + // 2. Read chip ID + // TODO: check ID for consistency? + if (!spa_read_byte(SPA06_ID, &this->prod_id_.reg)) { + this->mark_failed(LOG_STR("Chip ID read failure")); + return; + } + ESP_LOGV(TAG, + "Product Info:\n" + " Prod ID: %u\n" + " Rev ID: %u", + this->prod_id_.bit.prod_id, this->prod_id_.bit.rev_id); + + // 3. Read chip readiness from MEAS_CFG + // First check if the sensor reports ready + if (!spa_read_byte(SPA06_MEAS_CFG, &this->meas_.reg)) { + this->mark_failed(LOG_STR("Sensor status read failure")); + return; + } + // Check if the sensor reports coefficients are ready + if (!meas_.bit.coef_ready) { + this->mark_failed(LOG_STR("Coefficients not ready")); + return; + } + + // 4. Read coefficients + if (!this->read_coefficients_()) { + this->mark_failed(LOG_STR("Coefficients read error")); + return; + } + + // 5. Configure temperature and pressure sensors + // Default to measuring both temperature and pressure + + // Temperature must be read regardless of configuration to compute pressure + // If temperature is not configured in config: + // - No oversampling is used + // - Lowest possible rate is configured + if (!this->temperature_sensor_) { + this->temperature_rate_ = SAMPLE_RATE_1; + this->temperature_oversampling_ = OVERSAMPLING_NONE; + this->kt_ = oversampling_to_scale_factor(OVERSAMPLING_NONE); + } + + // If pressure is not configured in config + // - No oversampling is used + // - Lowest possible rate is configured + if (!this->pressure_sensor_) { + this->pressure_rate_ = SAMPLE_RATE_1; + this->pressure_oversampling_ = OVERSAMPLING_NONE; + this->kp_ = oversampling_to_scale_factor(OVERSAMPLING_NONE); + } + + // Write temperature settings + if (!write_temperature_settings_(this->temperature_oversampling_, this->temperature_rate_)) { + this->mark_failed(LOG_STR("Temperature settings write fail")); + return; + } + + // Write pressure settings + if (!write_pressure_settings_(this->pressure_oversampling_, this->pressure_rate_)) { + this->mark_failed(LOG_STR("Pressure settings write fail")); + return; + } + // 6. Write communication settings + // This call sets the bit shifts for pressure and temperature if + // their respective oversampling config is > X8 + // This call also disables interrupts, FIFO, and specifies SPI 4-wire + if (!write_communication_settings_(this->pressure_oversampling_ > OVERSAMPLING_X8, + this->temperature_oversampling_ > OVERSAMPLING_X8)) { + this->mark_failed(LOG_STR("Comm settings write fail")); + return; + } + + // 7. Write measurement settings + // This function sets background measurement mode without FIFO + if (!write_measurement_settings_(this->pressure_sensor_ ? MeasCrtl::MEASCRTL_BG_BOTH : MeasCrtl::MEASCRTL_BG_TEMP)) { + this->mark_failed(LOG_STR("Measurement settings write fail")); + return; + } +} + +bool SPA06Component::write_temperature_settings_(Oversampling oversampling, SampleRate rate) { + return this->write_sensor_settings_(oversampling, rate, SPA06_TMP_CFG); +} + +bool SPA06Component::write_pressure_settings_(Oversampling oversampling, SampleRate rate) { + return this->write_sensor_settings_(oversampling, rate, SPA06_PSR_CFG); +} + +bool SPA06Component::write_sensor_settings_(Oversampling oversampling, SampleRate rate, uint8_t reg) { + if (reg != SPA06_PSR_CFG && reg != SPA06_TMP_CFG) { + return false; + } + this->pt_meas_cfg_.bit.rate = rate; + this->pt_meas_cfg_.bit.prc = oversampling; + ESP_LOGD(TAG, "Config write: %02x", this->pt_meas_cfg_.reg); + return spa_write_byte(reg, this->pt_meas_cfg_.reg); +} + +bool SPA06Component::write_measurement_settings_(MeasCrtl crtl) { + this->meas_.bit.meas_crtl = crtl; + return spa_write_byte(SPA06_MEAS_CFG, this->meas_.reg); +} + +bool SPA06Component::write_communication_settings_(bool pressure_shift, bool temperature_shift, bool interrupt_hl, + bool interrupt_fifo, bool interrupt_tmp, bool interrupt_prs, + bool enable_fifo, bool spi_3wire) { + this->cfg_.bit.p_shift = pressure_shift; + this->cfg_.bit.t_shift = temperature_shift; + this->cfg_.bit.int_hl = interrupt_hl; + this->cfg_.bit.int_fifo = interrupt_fifo; + this->cfg_.bit.int_tmp = interrupt_tmp; + this->cfg_.bit.int_prs = interrupt_prs; + this->cfg_.bit.fifo_en = enable_fifo; + this->cfg_.bit.spi_3wire = spi_3wire; + return spa_write_byte(SPA06_CFG_REG, this->cfg_.reg); +} + +bool SPA06Component::read_coefficients_() { + uint8_t coef[SPA06_COEF_LEN]; + if (!spa_read_bytes(SPA06_COEF, coef, SPA06_COEF_LEN)) { + return false; + } + this->c0_ = decode16(coef[0], coef[1], 12); + this->c1_ = decode16(coef[1], coef[2], 12, 4); + this->c00_ = decode32(coef[3], coef[4], coef[5], 0, 20); + this->c10_ = decode32(coef[5], coef[6], coef[7], 0, 20, 4); + this->c01_ = decode16(coef[8], coef[9], 16); + this->c11_ = decode16(coef[10], coef[11], 16); + this->c20_ = decode16(coef[12], coef[13], 16); + this->c21_ = decode16(coef[14], coef[15], 16); + this->c30_ = decode16(coef[16], coef[17], 16); + this->c31_ = decode16(coef[18], coef[19], 12); + this->c40_ = decode16(coef[19], coef[20], 12, 4); + + ESP_LOGV(TAG, + "Coefficients:\n" + " c0: %i, c1: %i,\n" + " c00: %i, c10: %i, c20: %i, c30: %i, c40: %i,\n" + " c01: %i, c11: %i, c21: %i, c31: %i", + this->c0_, this->c1_, this->c00_, this->c10_, this->c20_, this->c30_, this->c40_, this->c01_, this->c11_, + this->c21_, this->c31_); + return true; +} + +bool SPA06Component::soft_reset_() { + // Setup steps for SPA06: + // 1. Perform a protocol reset (required to write command for SPI code, noop for I2C) + this->protocol_reset(); + + // 2. Perform the actual reset + this->reset_.bit.fifo_flush = true; + this->reset_.bit.soft_rst = SPA06_SOFT_RESET; + if (!this->spa_write_byte(SPA06_RESET, this->reset_.reg)) { + return false; + } + + // 3. Wait for chip to become ready. Datasheet specifies 2 ms; wait 3 + delay(3); + // 4. Perform another protocol reset (required for SPI code, noop for I2C) + this->protocol_reset(); + return true; +} + +// Temperature conversion formula. See datasheet pg. 14 +float SPA06Component::convert_temperature_(const float &t_raw_sc) { return this->c0_ * 0.5 + this->c1_ * t_raw_sc; } +// Pressure conversion formula. See datasheet pg. 14 +float SPA06Component::convert_pressure_(const float &p_raw_sc, const float &t_raw_sc) { + float p2_raw_sc = p_raw_sc * p_raw_sc; + float p3_raw_sc = p2_raw_sc * p_raw_sc; + float p4_raw_sc = p3_raw_sc * p_raw_sc; + return this->c00_ + (float) this->c10_ * p_raw_sc + (float) this->c20_ * p2_raw_sc + (float) this->c30_ * p3_raw_sc + + (float) this->c40_ * p4_raw_sc + + t_raw_sc * ((float) this->c01_ + (float) this->c11_ * p_raw_sc + (float) this->c21_ * p2_raw_sc + + (float) this->c31_ * p3_raw_sc); +} + +void SPA06Component::update() { + // Verify either a temperature or pressure sensor is defined before proceeding + if ((!this->temperature_sensor_) && (!this->pressure_sensor_)) { + return; + } + + // Queue a background task for retrieving the measurement + this->set_timeout("measurement", this->conversion_time_, [this]() { + float raw_temperature; + float temperature = 0.0; + float pressure = 0.0; + + // Check measurement register for readiness + if (!this->spa_read_byte(SPA06_MEAS_CFG, &this->meas_.reg)) { + ESP_LOGW(TAG, "Cannot read meas config"); + this->status_set_warning(); + return; + } + if (this->pressure_sensor_) { + if (!this->meas_.bit.prs_ready || !this->meas_.bit.tmp_ready) { + ESP_LOGW(TAG, "Temperature and pressure not ready"); + this->status_set_warning(); + return; + } + if (!this->read_temperature_and_pressure_(temperature, pressure, raw_temperature)) { + ESP_LOGW(TAG, "Temperature and pressure read failure"); + this->status_set_warning(); + return; + } + } else { + if (!this->meas_.bit.tmp_ready) { + ESP_LOGW(TAG, "Temperature not ready"); + this->status_set_warning(); + return; + } + if (!this->read_temperature_(temperature, raw_temperature)) { + ESP_LOGW(TAG, "Temperature read fail"); + this->status_set_warning(); + return; + } + } + if (this->temperature_sensor_) { + this->temperature_sensor_->publish_state(temperature); + } else { + ESP_LOGV(TAG, "No temperature sensor configured"); + } + if (this->pressure_sensor_) { + this->pressure_sensor_->publish_state(pressure); + } else { + ESP_LOGV(TAG, "No pressure sensor configured"); + } + this->status_clear_warning(); + }); +} + +bool SPA06Component::read_temperature_and_pressure_(float &temperature, float &pressure, float &t_raw_sc) { + // Temperature read and decode + if (!this->read_temperature_(temperature, t_raw_sc)) { + return false; + } + // Read raw pressure from device + uint8_t buf[3]; + if (!this->spa_read_bytes(SPA06_PSR, buf, 3)) { + return false; + } + // Calculate raw scaled pressure value + float p_raw_sc = (float) decode32(buf[0], buf[1], buf[2], 0, 24) / (float) this->kp_; + + // Calculate full pressure values + pressure = this->convert_pressure_(p_raw_sc, t_raw_sc); + return true; +} + +bool SPA06Component::read_temperature_(float &temperature, float &t_raw_sc) { + uint8_t buf[3]; + if (!this->spa_read_bytes(SPA06_TMP, buf, 3)) { + return false; + } + + t_raw_sc = (float) decode32(buf[0], buf[1], buf[2], 0, 24) / (float) this->kt_; + temperature = this->convert_temperature_(t_raw_sc); + return true; +} +} // namespace esphome::spa06_base diff --git a/esphome/components/spa06_base/spa06_base.h b/esphome/components/spa06_base/spa06_base.h new file mode 100644 index 0000000000..5239e80ec5 --- /dev/null +++ b/esphome/components/spa06_base/spa06_base.h @@ -0,0 +1,257 @@ +// SPA06 interface code for ESPHome +// All datasheet page references refer to Goermicro SPA06-003 datasheet version 2.0 + +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/hal.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/progmem.h" + +namespace esphome::spa06_base { + +// Read sizes. All other registers are size 1 +constexpr size_t SPA06_MEAS_LEN = 3; +constexpr size_t SPA06_COEF_LEN = 21; + +// Soft reset command (0b1001, 0x9) +constexpr uint8_t SPA06_SOFT_RESET = 0x9; + +// SPA06 Register Addresses +enum Register : uint8_t { + SPA06_PSR = 0x00, // Pressure Reading MSB (or all 3) + SPA06_PSR_B1 = 0x01, // Pressure Reading LSB + SPA06_PSR_B0 = 0x02, // Pressure Reading XLSB (LSB: Pressure flag in FIFO) + SPA06_TMP = 0x03, // Temperature Reading MSB (or all 3) + SPA06_TMP_B1 = 0x04, // Temperature Reading LSB + SPA06_TMP_B0 = 0x05, // Temperature Reading XLSB + SPA06_PSR_CFG = 0x06, // Pressure Configuration + SPA06_TMP_CFG = 0x07, // Temperature Configuration + SPA06_MEAS_CFG = 0x08, // Measurement Configuration (includes readiness) + SPA06_CFG_REG = 0x09, // Configuration Register + SPA06_INT_STS = 0x0A, // Interrupt Status + SPA06_FIFO_STS = 0x0B, // FIFO Status + SPA06_RESET = 0x0C, // Reset + FIFO Flush + SPA06_ID = 0x0D, // Product ID and revision + SPA06_COEF = 0x10, // Coefficients (0x10-0x24) + SPA06_INVALID_CMD = 0x25, // End of enum command +}; + +// Oversampling config. +enum Oversampling : uint8_t { + OVERSAMPLING_NONE = 0x0, + OVERSAMPLING_X2 = 0x1, + OVERSAMPLING_X4 = 0x2, + OVERSAMPLING_X8 = 0x3, + OVERSAMPLING_X16 = 0x4, + OVERSAMPLING_X32 = 0x5, + OVERSAMPLING_X64 = 0x6, + OVERSAMPLING_X128 = 0x7, + OVERSAMPLING_COUNT = 0x8, +}; + +// Measuring rate config +enum SampleRate : uint8_t { + SAMPLE_RATE_1 = 0x0, + SAMPLE_RATE_2 = 0x1, + SAMPLE_RATE_4 = 0x2, + SAMPLE_RATE_8 = 0x3, + SAMPLE_RATE_16 = 0x4, + SAMPLE_RATE_32 = 0x5, + SAMPLE_RATE_64 = 0x6, + SAMPLE_RATE_128 = 0x7, + SAMPLE_RATE_25P16 = 0x8, + SAMPLE_RATE_25P8 = 0x9, + SAMPLE_RATE_25P4 = 0xA, + SAMPLE_RATE_25P2 = 0xB, + SAMPLE_RATE_25 = 0xC, + SAMPLE_RATE_50 = 0xD, + SAMPLE_RATE_100 = 0xE, + SAMPLE_RATE_200 = 0xF, +}; + +// Measuring control config, set in MEAS_CFG register. +// See datasheet pages 28-29 +enum MeasCrtl : uint8_t { + MEASCRTL_IDLE = 0x0, + MEASCRTL_PRES = 0x1, + MEASCRTL_TEMP = 0x2, + MEASCRTL_BG_PRES = 0x5, + MEASCRTL_BG_TEMP = 0x6, + MEASCRTL_BG_BOTH = 0x7, +}; + +// Oversampling scale factors. See datasheet page 15. +constexpr uint32_t OVERSAMPLING_K_LUT[8] = {524288, 1572864, 3670016, 7864320, 253952, 516096, 1040384, 2088960}; +PROGMEM_STRING_TABLE(MeasRateStrings, "1Hz", "2Hz", "4Hz", "8Hz", "16Hz", "32Hz", "64Hz", "128Hz", "1.5625Hz", + "3.125Hz", "6.25Hz", "12.5Hz", "25Hz", "50Hz", "100Hz", "200Hz"); +PROGMEM_STRING_TABLE(OversamplingStrings, "X1", "X2", "X4", "X8", "X16", "X32", "X64", "X128"); + +inline static const LogString *oversampling_to_str(const Oversampling oversampling) { + return OversamplingStrings::get_log_str(static_cast<uint8_t>(oversampling), OversamplingStrings::LAST_INDEX); +} +inline static const LogString *meas_rate_to_str(SampleRate rate) { + return MeasRateStrings::get_log_str(static_cast<uint8_t>(rate), MeasRateStrings::LAST_INDEX); +} +inline uint32_t oversampling_to_scale_factor(const Oversampling oversampling) { + return OVERSAMPLING_K_LUT[static_cast<uint8_t>(oversampling)]; +}; + +class SPA06Component : public PollingComponent { + public: + //// Standard ESPHome component class functions + void setup() override; + void update() override; + void dump_config() override; + + //// ESPHome-side settings + void set_conversion_time(uint16_t conversion_time) { this->conversion_time_ = conversion_time; } + void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } + void set_pressure_sensor(sensor::Sensor *pressure_sensor) { this->pressure_sensor_ = pressure_sensor; } + void set_temperature_oversampling_config(Oversampling temperature_oversampling) { + this->temperature_oversampling_ = temperature_oversampling; + this->kt_ = oversampling_to_scale_factor(temperature_oversampling); + } + void set_pressure_oversampling_config(Oversampling pressure_oversampling) { + this->pressure_oversampling_ = pressure_oversampling; + this->kp_ = oversampling_to_scale_factor(pressure_oversampling); + } + void set_pressure_sample_rate_config(SampleRate rate) { this->pressure_rate_ = rate; } + void set_temperature_sample_rate_config(SampleRate rate) { this->temperature_rate_ = rate; } + + protected: + // Virtual read functions. Implemented in SPI/I2C components + virtual bool spa_read_byte(uint8_t reg, uint8_t *data) = 0; + virtual bool spa_write_byte(uint8_t reg, uint8_t data) = 0; + virtual bool spa_read_bytes(uint8_t reg, uint8_t *data, size_t len) = 0; + virtual bool spa_write_bytes(uint8_t reg, uint8_t *data, size_t len) = 0; + + //// Protocol-specific read functions + // Soft reset + bool soft_reset_(); + // Protocol-specific reset (used for SPI only, implemented as noop for I2C) + virtual void protocol_reset() {} + // Read temperature and calculate Celsius and scaled raw temperatures + bool read_temperature_(float &temperature, float &t_raw_sc); + // No pressure only read! Pressure calculation depends on scaled temperature value + // Read temperature and calculate Celsius temperature, Pascal pressure, and scaled raw temperature + bool read_temperature_and_pressure_(float &temperature, float &pressure, float &t_raw_sc); + // Read coefficients. Stores in class variables. + bool read_coefficients_(); + + //// Protocol-specific write functions + // Write temperature settings to TMP_CFG register + bool write_temperature_settings_(Oversampling oversampling, SampleRate rate); + // Write pressure settings to PRS_CFG register + bool write_pressure_settings_(Oversampling oversampling, SampleRate rate); + // Write measurement settings to MEAS_CRTL register + bool write_measurement_settings_(MeasCrtl crtl); + + // Write communication settings to CFG_REG register + // Set pressure_shift to true if pressure oversampling >X8 + // Set temperature_shift to true if temperature oversampling >X8 + bool write_communication_settings_(bool pressure_shift, bool temperature_shift, bool interrupt_hl = false, + bool interrupt_fifo = false, bool interrupt_tmp = false, + bool interrupt_prs = false, bool enable_fifo = false, bool spi_3wire = false); + + //// Protocol helper functions + // Write function for both temperature and pressure (deduplicates code) + bool write_sensor_settings_(Oversampling oversampling, SampleRate rate, uint8_t reg); + // Convert raw temperature reading into Celsius + float convert_temperature_(const float &t_raw_sc); + // Convert raw pressure and scaled raw temperature into Pascals + float convert_pressure_(const float &p_raw_sc, const float &t_raw_sc); + + //// Protocol-related variables + // Oversampling scale factors. Defaults are for X16 (pressure) and X1 (temp) + uint32_t kp_{253952}, kt_{524288}; + // Coefficients for calculating pressure and temperature from raw values + // Obtained from IC during setup + int32_t c00_{0}, c10_{0}; + int16_t c0_{0}, c1_{0}, c01_{0}, c11_{0}, c20_{0}, c21_{0}, c30_{0}, c31_{0}, c40_{0}; + + //// ESPHome class objects and configuration + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *pressure_sensor_{nullptr}; + Oversampling temperature_oversampling_{Oversampling::OVERSAMPLING_NONE}; + Oversampling pressure_oversampling_{Oversampling::OVERSAMPLING_X16}; + SampleRate temperature_rate_{SampleRate::SAMPLE_RATE_1}; + SampleRate pressure_rate_{SampleRate::SAMPLE_RATE_1}; + // Default conversion time: 27.6ms (16x pres) + 3.6ms (1x temp) ~ 32ms + uint16_t conversion_time_{32}; + + union { + struct { + Oversampling prc : 4; + SampleRate rate : 4; + } bit; + uint8_t reg; + } pt_meas_cfg_ = {.reg = 0}; // PRS_CFG and TMP_CFG + + union { + struct { + uint8_t meas_crtl : 3; + bool tmp_ext : 1; + bool prs_ready : 1; + bool tmp_ready : 1; + bool sensor_ready : 1; + bool coef_ready : 1; + } bit; + uint8_t reg; + } meas_ = {.reg = 0}; // MEAS_REG + + union { + struct { + uint8_t _reserved : 5; + bool int_prs : 1; + bool int_tmp : 1; + bool int_fifo_full : 1; + } bit; + uint8_t reg; + } int_status_ = {.reg = 0}; // INT_STS + + union { + struct { + bool spi_3wire : 1; + bool fifo_en : 1; + bool p_shift : 1; + bool t_shift : 1; + bool int_prs : 1; + bool int_tmp : 1; + bool int_fifo : 1; + bool int_hl : 1; + } bit; + uint8_t reg; + } cfg_ = {.reg = 0}; // CFG_REG + + union { + struct { + bool fifo_empty : 1; + bool fifo_full : 1; + uint8_t _reserved : 6; + } bit; + uint8_t reg; + } fifo_sts_ = {.reg = 0}; // FIFO_STS + + union { + struct { + // Set to true to flush FIFO + bool fifo_flush : 1; + // Reserved bits + uint8_t _reserved : 3; + // Soft reset. Set to 1001 (0x9) to perform reset. + uint8_t soft_rst : 4; + } bit; + uint8_t reg = 0; + } reset_ = {.reg = 0}; // RESET + + union { + struct { + uint8_t prod_id : 4; + uint8_t rev_id : 4; + } bit; + uint8_t reg = 0; + } prod_id_ = {.reg = 0}; // ID + +}; // class SPA06Component +} // namespace esphome::spa06_base From cb23f9453f29c8f83ac6bf9e4b0ddd3f2b33d91c Mon Sep 17 00:00:00 2001 From: CFlix <38142312+CFlix@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:09:00 +0100 Subject: [PATCH 1535/2030] [absolute_humidity] loop() improvement (#14684) Co-authored-by: DAVe3283 <DAVe3283+GitHub@gmail.com> --- .../absolute_humidity/absolute_humidity.cpp | 102 +++++++++--------- .../absolute_humidity/absolute_humidity.h | 20 +--- 2 files changed, 55 insertions(+), 67 deletions(-) diff --git a/esphome/components/absolute_humidity/absolute_humidity.cpp b/esphome/components/absolute_humidity/absolute_humidity.cpp index 40676f8655..3137a59fad 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.cpp +++ b/esphome/components/absolute_humidity/absolute_humidity.cpp @@ -1,22 +1,29 @@ #include "esphome/core/log.h" #include "absolute_humidity.h" -namespace esphome { -namespace absolute_humidity { +namespace esphome::absolute_humidity { -static const char *const TAG = "absolute_humidity.sensor"; +static const char *const TAG{"absolute_humidity.sensor"}; void AbsoluteHumidityComponent::setup() { + this->temperature_sensor_->add_on_state_callback([this](float state) { + this->temperature_ = state; + this->enable_loop(); + }); ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str()); - this->temperature_sensor_->add_on_state_callback([this](float state) { this->temperature_callback_(state); }); + // Get initial value if (this->temperature_sensor_->has_state()) { - this->temperature_callback_(this->temperature_sensor_->get_state()); + this->temperature_ = this->temperature_sensor_->get_state(); } + this->humidity_sensor_->add_on_state_callback([this](float state) { + this->humidity_ = state; + this->enable_loop(); + }); ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str()); - this->humidity_sensor_->add_on_state_callback([this](float state) { this->humidity_callback_(state); }); + // Get initial value if (this->humidity_sensor_->has_state()) { - this->humidity_callback_(this->humidity_sensor_->get_state()); + this->humidity_ = this->humidity_sensor_->get_state(); } } @@ -46,14 +53,12 @@ void AbsoluteHumidityComponent::dump_config() { } void AbsoluteHumidityComponent::loop() { - if (!this->next_update_) { - return; - } - this->next_update_ = false; + // Only run once + this->disable_loop(); // Ensure we have source data - const bool no_temperature = std::isnan(this->temperature_); - const bool no_humidity = std::isnan(this->humidity_); + const bool no_temperature{std::isnan(this->temperature_)}; + const bool no_humidity{std::isnan(this->humidity_)}; if (no_temperature || no_humidity) { if (no_temperature) { ESP_LOGW(TAG, "No valid state from temperature sensor!"); @@ -67,9 +72,9 @@ void AbsoluteHumidityComponent::loop() { } // Convert to desired units - const float temperature_c = this->temperature_; - const float temperature_k = temperature_c + 273.15; - const float hr = this->humidity_ / 100; + const float temperature_c{this->temperature_}; + const float temperature_k{temperature_c + 273.15f}; + const float hr{this->humidity_ / 100.0f}; // Calculate saturation vapor pressure float es; @@ -90,7 +95,7 @@ void AbsoluteHumidityComponent::loop() { } // Calculate absolute humidity - const float absolute_humidity = vapor_density(es, hr, temperature_k); + const float absolute_humidity{vapor_density(es, hr, temperature_k)}; ESP_LOGD(TAG, "Saturation vapor pressure %f kPa, absolute humidity %f g/m³", es, absolute_humidity); @@ -103,16 +108,16 @@ void AbsoluteHumidityComponent::loop() { // More accurate than Tetens in normal meteorologic conditions float AbsoluteHumidityComponent::es_buck(float temperature_c) { float a, b, c, d; - if (temperature_c >= 0) { - a = 0.61121; - b = 18.678; - c = 234.5; - d = 257.14; + if (temperature_c >= 0.0f) { + a = 0.61121f; + b = 18.678f; + c = 234.5f; + d = 257.14f; } else { - a = 0.61115; - b = 18.678; - c = 233.7; - d = 279.82; + a = 0.61115f; + b = 18.678f; + c = 233.7f; + d = 279.82f; } return a * expf((b - (temperature_c / c)) * (temperature_c / (d + temperature_c))); } @@ -120,14 +125,14 @@ float AbsoluteHumidityComponent::es_buck(float temperature_c) { // Tetens equation (https://en.wikipedia.org/wiki/Tetens_equation) float AbsoluteHumidityComponent::es_tetens(float temperature_c) { float a, b; - if (temperature_c >= 0) { - a = 17.27; - b = 237.3; + if (temperature_c >= 0.0f) { + a = 17.27f; + b = 237.3f; } else { - a = 21.875; - b = 265.5; + a = 21.875f; + b = 265.5f; } - return 0.61078 * expf((a * temperature_c) / (temperature_c + b)); + return 0.61078f * expf((a * temperature_c) / (temperature_c + b)); } // Wobus equation @@ -146,18 +151,18 @@ float AbsoluteHumidityComponent::es_wobus(float t) { // // Baker, Schlatter 17-MAY-1982 Original version. - const float c0 = +0.99999683e00; - const float c1 = -0.90826951e-02; - const float c2 = +0.78736169e-04; - const float c3 = -0.61117958e-06; - const float c4 = +0.43884187e-08; - const float c5 = -0.29883885e-10; - const float c6 = +0.21874425e-12; - const float c7 = -0.17892321e-14; - const float c8 = +0.11112018e-16; - const float c9 = -0.30994571e-19; - const float p = c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * (c6 + t * (c7 + t * (c8 + t * (c9))))))))); - return 0.61078 / pow(p, 8); + constexpr float c0{+0.99999683e+00f}; + constexpr float c1{-0.90826951e-02f}; + constexpr float c2{+0.78736169e-04f}; + constexpr float c3{-0.61117958e-06f}; + constexpr float c4{+0.43884187e-08f}; + constexpr float c5{-0.29883885e-10f}; + constexpr float c6{+0.21874425e-12f}; + constexpr float c7{-0.17892321e-14f}; + constexpr float c8{+0.11112018e-16f}; + constexpr float c9{-0.30994571e-19f}; + const float p{c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * (c6 + t * (c7 + t * (c8 + t * (c9)))))))))}; + return 0.61078f / powf(p, 8.0f); } // From https://www.environmentalbiophysics.org/chalk-talk-how-to-calculate-absolute-humidity/ @@ -168,11 +173,10 @@ float AbsoluteHumidityComponent::vapor_density(float es, float hr, float ta) { // hr = relative humidity [0-1] // ta = absolute temperature (K) - const float ea = hr * es * 1000; // vapor pressure of the air (Pa) - const float mw = 18.01528; // molar mass of water (g⋅mol⁻¹) - const float r = 8.31446261815324; // molar gas constant (J⋅K⁻¹) + const float ea{hr * es * 1000.0f}; // vapor pressure of the air (Pa) + const float mw{18.01528f}; // molar mass of water (g⋅mol⁻¹) + const float r{8.31446261815324f}; // molar gas constant (J⋅K⁻¹) return (ea * mw) / (r * ta); } -} // namespace absolute_humidity -} // namespace esphome +} // namespace esphome::absolute_humidity diff --git a/esphome/components/absolute_humidity/absolute_humidity.h b/esphome/components/absolute_humidity/absolute_humidity.h index 71feee2c42..be28d3dc50 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.h +++ b/esphome/components/absolute_humidity/absolute_humidity.h @@ -3,8 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -namespace esphome { -namespace absolute_humidity { +namespace esphome::absolute_humidity { /// Enum listing all implemented saturation vapor pressure equations. enum SaturationVaporPressureEquation { @@ -16,8 +15,6 @@ enum SaturationVaporPressureEquation { /// This class implements calculation of absolute humidity from temperature and relative humidity. class AbsoluteHumidityComponent : public sensor::Sensor, public Component { public: - AbsoluteHumidityComponent() = default; - void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } void set_equation(SaturationVaporPressureEquation equation) { this->equation_ = equation; } @@ -27,15 +24,6 @@ class AbsoluteHumidityComponent : public sensor::Sensor, public Component { void loop() override; protected: - void temperature_callback_(float state) { - this->next_update_ = true; - this->temperature_ = state; - } - void humidity_callback_(float state) { - this->next_update_ = true; - this->humidity_ = state; - } - /** Buck equation for saturation vapor pressure in kPa. * * @param temperature_c Air temperature in °C. @@ -57,19 +45,15 @@ class AbsoluteHumidityComponent : public sensor::Sensor, public Component { * @param es Saturation vapor pressure in kPa. * @param hr Relative humidity 0 to 1. * @param ta Absolute temperature in K. - * @param heater_duration The duration in ms that the heater should turn on for when measuring. */ static float vapor_density(float es, float hr, float ta); sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; - bool next_update_{false}; - float temperature_{NAN}; float humidity_{NAN}; SaturationVaporPressureEquation equation_; }; -} // namespace absolute_humidity -} // namespace esphome +} // namespace esphome::absolute_humidity From b9439036d4d2605a40378ae6f624e1b4eecb14b8 Mon Sep 17 00:00:00 2001 From: aanban <stiller-gast@gmx.de> Date: Thu, 19 Mar 2026 14:19:24 +0100 Subject: [PATCH 1536/2030] [remote_base] add support for brennenstuhl comfort-line switches (#9407) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/remote_base/__init__.py | 44 ++++++ .../remote_base/brennenstuhl_protocol.cpp | 144 ++++++++++++++++++ .../remote_base/brennenstuhl_protocol.h | 34 +++++ .../remote_receiver/common-actions.yaml | 5 + .../remote_transmitter/common-buttons.yaml | 6 + 5 files changed, 233 insertions(+) create mode 100644 esphome/components/remote_base/brennenstuhl_protocol.cpp create mode 100644 esphome/components/remote_base/brennenstuhl_protocol.h diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index bf17ac27b8..a0594d7f67 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -310,6 +310,50 @@ async def beo4_action(var, config, args): cg.add(var.set_repeats(template_)) +# Brennenstuhl +( + BrennenstuhlData, + BrennenstuhlBinarySensor, + BrennenstuhlTrigger, + BrennenstuhlAction, + BrennenstuhlDumper, +) = declare_protocol("Brennenstuhl") + +BRENNENSTUHL_SCHEMA = cv.Schema( + { + cv.Required(CONF_CODE): cv.hex_uint32_t, + } +) + + +@register_binary_sensor("brennenstuhl", BrennenstuhlBinarySensor, BRENNENSTUHL_SCHEMA) +def brennenstuhl_binary_sensor(var, config): + cg.add( + var.set_data( + cg.StructInitializer( + BrennenstuhlData, + ("code", config[CONF_CODE]), + ) + ) + ) + + +@register_trigger("brennenstuhl", BrennenstuhlTrigger, BrennenstuhlData) +def brennenstuhl_trigger(var, config): + pass + + +@register_dumper("brennenstuhl", BrennenstuhlDumper) +def brennenstuhl_dumper(var, config): + pass + + +@register_action("brennenstuhl", BrennenstuhlAction, BRENNENSTUHL_SCHEMA) +async def brennenstuhl_action(var, config, args): + template_ = await cg.templatable(config[CONF_CODE], args, cg.uint32) + cg.add(var.set_code(template_)) + + # ByronSX ( ByronSXData, diff --git a/esphome/components/remote_base/brennenstuhl_protocol.cpp b/esphome/components/remote_base/brennenstuhl_protocol.cpp new file mode 100644 index 0000000000..35261dc00a --- /dev/null +++ b/esphome/components/remote_base/brennenstuhl_protocol.cpp @@ -0,0 +1,144 @@ +#include "brennenstuhl_protocol.h" +#include "esphome/core/log.h" + +#include <cinttypes> + +namespace esphome::remote_base { + +static const char *const TAG = "remote.brennenstuhl"; + +// receiver timing ranges [µs] +constexpr uint32_t START_PULSE_MIN = 200; +constexpr uint32_t START_PULSE_MAX = 500; +constexpr uint32_t START_SYMBOL_MIN = 2600; +constexpr uint32_t START_SYMBOL_MAX = 2700; +constexpr uint32_t DATA_SYMBOL_MIN = 1500; +constexpr uint32_t DATA_SYMBOL_MAX = 1600; + +// transmitter timings [µs] +constexpr uint32_t PW_SHORT_US = 390; +constexpr uint32_t PW_LONG_US = 1160; +constexpr uint32_t PW_START_US = 2300; + +// number of data bits +constexpr uint32_t N_BITS = 24; + +// number of required symbols = 2 x (start + N_BITS) = 50 +constexpr uint32_t N_SYMBOLS_REQ = 2u * (N_BITS + 1); + +// number of bs codes within received frame +constexpr int32_t N_FRAME_CODES = 4; + +// decoder finite-state-machine +enum class RxSt { START_PULSE, START_SYMBOL, PULSE, DATA_SYMBOL }; + +// The encode() member function reserves and fills a complete frame, to be send. The Brennenstuhl +// RC receivers demand a frame with a start-symbol followed by 4 repeated codes. +void BrennenstuhlProtocol::encode(RemoteTransmitData *dst, const BrennenstuhlData &data) { + uint32_t code = data.code; + dst->reserve((N_SYMBOLS_REQ * N_FRAME_CODES) + 1); + for (int32_t kc = 0; kc != N_FRAME_CODES; kc++) { + dst->item(PW_SHORT_US, PW_START_US); + for (int32_t ic = (N_BITS - 1); ic != -1; ic--) { + if ((code >> ic) & 1) { + dst->item(PW_LONG_US, PW_SHORT_US); + } else { + dst->item(PW_SHORT_US, PW_LONG_US); + } + } + } +} + +// The decode() member function extracts Brennenstuhl codes from the received frame. Instead +// of validating the pulse width of the carriers and pauses individually, it is more accurate +// to validate the symbols (symbol=carrier+pause) The symbol pulsewidth is around 1550µs, but +// the pulse with of the carrier and the pauses vary greatly. Once the symbol pulsewidth is +// valid, a code bit becomes "1" if the carrier is longer then the pause and "0" else. A total +// frame consists of a start symbol and up to four codes. The decoder decodes all codes and +// returns the best code (the one with the most identical codes) +optional<BrennenstuhlData> BrennenstuhlProtocol::decode(RemoteReceiveData src) { + uint32_t n_received = static_cast<uint32_t>(src.size()); + BrennenstuhlData data{ + .code = 0, + }; + // suppress noisy frames, at least a complete bs_code should be available + if (n_received > N_SYMBOLS_REQ) { + uint32_t bs_codes[4] = {0, 0, 0, 0}; // internal codes + int32_t bs_cnt = 0; // number of bs codes found within frame + int32_t bs_idx = -1; // index to best bs code + uint32_t bit_cnt = 0; // bit counter [0..23] + uint32_t pw_pre = 0; // pulsewidth of previous carrier (abs value) + RxSt fsm = RxSt::START_PULSE; + for (uint32_t ic = 0; (ic != n_received) && (bs_cnt != N_FRAME_CODES); ic++) { + uint32_t pw_cur = (uint32_t) (src[ic] < 0 ? -src[ic] : src[ic]); // current pulsewidth + uint32_t pw_sym = pw_cur + pw_pre; // symbol=pulse+pause + switch (fsm) { + case RxSt::START_PULSE: { // check if start pulse is valid + if ((src[ic] > 0) && (pw_cur >= START_PULSE_MIN) && (pw_cur <= START_PULSE_MAX)) { + bs_codes[bs_cnt] = 0; + bit_cnt = 0; + pw_pre = pw_cur; + fsm = RxSt::START_SYMBOL; + } + break; + } + case RxSt::START_SYMBOL: { // check if start symbol is valid + if ((src[ic] < 0) && (pw_sym >= START_SYMBOL_MIN) && (pw_sym <= START_SYMBOL_MAX)) { + fsm = RxSt::PULSE; + } else { + fsm = RxSt::START_PULSE; + } + break; + } + case RxSt::PULSE: { // just grab pulse, validation is done in DATA_SYMBOL state + if (src[ic] > 0) { + pw_pre = pw_cur; + fsm = RxSt::DATA_SYMBOL; + } else { + fsm = RxSt::START_PULSE; + } + break; + } + case RxSt::DATA_SYMBOL: { // check if data symbol is valid and append bit to data + if ((src[ic] < 0) && (pw_sym >= DATA_SYMBOL_MIN) && (pw_sym <= DATA_SYMBOL_MAX)) { + bs_codes[bs_cnt] <<= 1; + bs_codes[bs_cnt] += (pw_cur < pw_pre) ? 1 : 0; + if (++bit_cnt < N_BITS) { + fsm = RxSt::PULSE; + } else { + bs_cnt++; // complete code found + fsm = RxSt::START_PULSE; // start over for further codes in frame + } + } else { + fsm = RxSt::START_PULSE; // decoding failed, start over for further codes + } + break; + } + } + } + if (bs_cnt > 0) { // complete codes found, find best code in list now + int32_t identical_max = 0; + for (int32_t ic = 0; ic != bs_cnt; ic++) { + int32_t identical_cnt = 0; + for (int32_t jc = 0; jc != bs_cnt; jc++) { + identical_cnt += (bs_codes[ic] == bs_codes[jc]) ? 1 : 0; + } + if (identical_cnt > identical_max) { + identical_max = identical_cnt; + bs_idx = ic; // save index to best code + } + } + if (bs_idx > -1) { + data.code = bs_codes[bs_idx]; + return data; // return best bs code of list + } + } + } + return {}; +} + +void BrennenstuhlProtocol::dump(const BrennenstuhlData &data) { + ESP_LOGI(TAG, "Brennenstuhl: code=0x%06" PRIx32, data.code); +} + +} // namespace esphome::remote_base diff --git a/esphome/components/remote_base/brennenstuhl_protocol.h b/esphome/components/remote_base/brennenstuhl_protocol.h new file mode 100644 index 0000000000..1d5b621714 --- /dev/null +++ b/esphome/components/remote_base/brennenstuhl_protocol.h @@ -0,0 +1,34 @@ +#pragma once + +#include "remote_base.h" + +#include <cinttypes> + +namespace esphome::remote_base { + +struct BrennenstuhlData { + uint32_t code; + bool operator==(const BrennenstuhlData &rhs) const { return code == rhs.code; } +}; + +class BrennenstuhlProtocol : public RemoteProtocol<BrennenstuhlData> { + public: + void encode(RemoteTransmitData *dst, const BrennenstuhlData &data) override; + optional<BrennenstuhlData> decode(RemoteReceiveData src) override; + void dump(const BrennenstuhlData &data) override; +}; + +DECLARE_REMOTE_PROTOCOL(Brennenstuhl) + +template<typename... Ts> class BrennenstuhlAction : public RemoteTransmitterActionBase<Ts...> { + public: + TEMPLATABLE_VALUE(uint32_t, code) + + void encode(RemoteTransmitData *dst, Ts... x) override { + BrennenstuhlData data{}; + data.code = this->code_.value(x...); + BrennenstuhlProtocol().encode(dst, data); + } +}; + +} // namespace esphome::remote_base diff --git a/tests/components/remote_receiver/common-actions.yaml b/tests/components/remote_receiver/common-actions.yaml index de01fa3602..30b99eeb70 100644 --- a/tests/components/remote_receiver/common-actions.yaml +++ b/tests/components/remote_receiver/common-actions.yaml @@ -8,6 +8,11 @@ on_beo4: - logger.log: format: "on_beo4: %u %u" args: ["x.source", "x.command"] +on_brennenstuhl: + then: + - logger.log: + format: "on_brennenstuhl: %u" + args: ["x.code"] on_aeha: then: - logger.log: diff --git a/tests/components/remote_transmitter/common-buttons.yaml b/tests/components/remote_transmitter/common-buttons.yaml index d48d36bd54..c6c7049605 100644 --- a/tests/components/remote_transmitter/common-buttons.yaml +++ b/tests/components/remote_transmitter/common-buttons.yaml @@ -14,6 +14,12 @@ button: remote_transmitter.transmit_beo4: source: 0x01 command: 0x0C + - platform: template + name: brennenstuhl + id: button_a_on + on_press: + remote_transmitter.transmit_brennenstuhl: + code: 0xBD2E2C - platform: template name: Dyson fan up id: dyson_fan_up From 0afcdbfe731702fdd9cac7ab7a6f971c1267d1b9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:40:18 -1000 Subject: [PATCH 1537/2030] [binary_sensor] Replace std::bind with inline lambda in MultiClickTrigger (#14956) --- esphome/components/binary_sensor/automation.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/binary_sensor/automation.h b/esphome/components/binary_sensor/automation.h index f8b130e08a..f30f9d3279 100644 --- a/esphome/components/binary_sensor/automation.h +++ b/esphome/components/binary_sensor/automation.h @@ -96,8 +96,7 @@ class MultiClickTrigger : public Trigger<>, public Component { void setup() override { this->last_state_ = this->parent_->get_state_default(false); - auto f = std::bind(&MultiClickTrigger::on_state_, this, std::placeholders::_1); - this->parent_->add_on_state_callback(f); + this->parent_->add_on_state_callback([this](bool state) { this->on_state_(state); }); } float get_setup_priority() const override { return setup_priority::HARDWARE; } From 16ec237ac6a0a214bd99cc11d8b56496638065c7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:40:32 -1000 Subject: [PATCH 1538/2030] [wireguard] Replace std::bind with inline lambdas (#14957) --- esphome/components/wireguard/wireguard.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/wireguard/wireguard.cpp b/esphome/components/wireguard/wireguard.cpp index 2022e25b6c..b4641894db 100644 --- a/esphome/components/wireguard/wireguard.cpp +++ b/esphome/components/wireguard/wireguard.cpp @@ -2,7 +2,6 @@ #ifdef USE_WIREGUARD #include <cinttypes> #include <ctime> -#include <functional> #include "esphome/core/application.h" #include "esphome/core/log.h" @@ -48,8 +47,8 @@ void Wireguard::setup() { if (this->wg_initialized_ == ESP_OK) { ESP_LOGI(TAG, "Initialized"); this->wg_peer_offline_time_ = millis(); - this->srctime_->add_on_time_sync_callback(std::bind(&Wireguard::start_connection_, this)); - this->defer(std::bind(&Wireguard::start_connection_, this)); // defer to avoid blocking setup + this->srctime_->add_on_time_sync_callback([this]() { this->start_connection_(); }); + this->defer([this]() { this->start_connection_(); }); // defer to avoid blocking setup #ifdef USE_TEXT_SENSOR if (this->address_sensor_ != nullptr) { @@ -206,7 +205,7 @@ void Wireguard::enable() { void Wireguard::disable() { this->enabled_ = false; - this->defer(std::bind(&Wireguard::stop_connection_, this)); // defer to avoid blocking running loop + this->defer([this]() { this->stop_connection_(); }); // defer to avoid blocking running loop ESP_LOGI(TAG, "Disabled"); this->publish_enabled_state(); } From 40a65d36b468ceccfe97d9c2e181199d2404bcff Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:41:01 -1000 Subject: [PATCH 1539/2030] [nau7802] Replace std::bind with lambda to fit std::function SBO (#14958) --- esphome/components/nau7802/nau7802.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/nau7802/nau7802.cpp b/esphome/components/nau7802/nau7802.cpp index 937239b98d..66d36dd741 100644 --- a/esphome/components/nau7802/nau7802.cpp +++ b/esphome/components/nau7802/nau7802.cpp @@ -83,8 +83,7 @@ void NAU7802Sensor::setup() { // turn on AFE pu_ctrl |= PU_CTRL_POWERUP_ANALOG; - auto f = std::bind(&NAU7802Sensor::complete_setup_, this); - this->set_timeout(600, f); + this->set_timeout(600, [this]() { this->complete_setup_(); }); } void NAU7802Sensor::complete_setup_() { From 2ca6681896ad876d79f9b39b9e6a4b52b12de993 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:41:15 -1000 Subject: [PATCH 1540/2030] [xiaomi_rtcgq02lm] Drop unused capture from timeout lambdas (#14959) --- esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.cpp b/esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.cpp index ee3ad316e1..0f27f09c87 100644 --- a/esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.cpp +++ b/esphome/components/xiaomi_rtcgq02lm/xiaomi_rtcgq02lm.cpp @@ -58,15 +58,13 @@ bool XiaomiRTCGQ02LM::parse_device(const esp32_ble_tracker::ESPBTDevice &device) #ifdef USE_BINARY_SENSOR if (res->has_motion.has_value() && this->motion_ != nullptr) { this->motion_->publish_state(*res->has_motion); - this->set_timeout("motion_timeout", this->motion_timeout_, - [this, res]() { this->motion_->publish_state(false); }); + this->set_timeout("motion_timeout", this->motion_timeout_, [this]() { this->motion_->publish_state(false); }); } if (res->is_light.has_value() && this->light_ != nullptr) this->light_->publish_state(*res->is_light); if (res->button_press.has_value() && this->button_ != nullptr) { this->button_->publish_state(*res->button_press); - this->set_timeout("button_timeout", this->button_timeout_, - [this, res]() { this->button_->publish_state(false); }); + this->set_timeout("button_timeout", this->button_timeout_, [this]() { this->button_->publish_state(false); }); } #endif #ifdef USE_SENSOR From 14107ec452576327780f65f4ec07375c460b4ced Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:42:08 -1000 Subject: [PATCH 1541/2030] [bme68x_bsec2] Store trigger time as member to avoid std::function SBO overflow (#14960) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp | 3 ++- esphome/components/bme68x_bsec2/bme68x_bsec2.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index 0210d1e67d..ed2ec80896 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -279,7 +279,8 @@ void BME68xBSEC2Component::run_() { uint32_t meas_dur = 0; meas_dur = bme68x_get_meas_dur(this->op_mode_, &bme68x_conf, &this->bme68x_); ESP_LOGV(TAG, "Queueing read in %uus", meas_dur); - this->set_timeout("read", meas_dur / 1000, [this, curr_time_ns]() { this->read_(curr_time_ns); }); + this->trigger_time_ns_ = curr_time_ns; + this->set_timeout("read", meas_dur / 1000, [this]() { this->read_(this->trigger_time_ns_); }); } else { ESP_LOGV(TAG, "Measurement not required"); this->read_(curr_time_ns); diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.h b/esphome/components/bme68x_bsec2/bme68x_bsec2.h index 8f4d8f61c2..1ed72eee03 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.h +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.h @@ -116,6 +116,8 @@ class BME68xBSEC2Component : public Component { int8_t bme68x_status_{BME68X_OK}; int64_t last_time_ms_{0}; + int64_t trigger_time_ns_{0}; // Stored for set_timeout lambda to help avoid heap allocation on supported 32-bit + // toolchains with small std::function SBO uint32_t millis_overflow_counter_{0}; std::queue<std::function<void()>> queue_; From d1aa1881bba7744ababf24cc7b773f1e08209ef7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:42:26 -1000 Subject: [PATCH 1542/2030] [core] Replace std::bind with lambdas across 13 components (#14961) --- esphome/components/dps310/dps310.cpp | 3 +-- .../components/esp32_improv/esp32_improv_component.cpp | 3 +-- .../components/improv_serial/improv_serial_component.cpp | 3 +-- esphome/components/max31855/max31855.cpp | 3 +-- esphome/components/max31856/max31856.cpp | 4 ++-- esphome/components/max31865/max31865.cpp | 3 +-- esphome/components/max6675/max6675.cpp | 3 +-- esphome/components/midea/appliance_base.h | 2 +- esphome/components/ms5611/ms5611.cpp | 6 ++---- esphome/components/ms8607/ms8607.cpp | 9 +++------ esphome/components/sht4x/sht4x.cpp | 2 +- esphome/components/sprinkler/sprinkler.cpp | 4 ++-- 12 files changed, 17 insertions(+), 28 deletions(-) diff --git a/esphome/components/dps310/dps310.cpp b/esphome/components/dps310/dps310.cpp index aa0a77cdd8..b1366cd069 100644 --- a/esphome/components/dps310/dps310.cpp +++ b/esphome/components/dps310/dps310.cpp @@ -127,8 +127,7 @@ void DPS310Component::read_() { this->update_in_progress_ = false; this->status_clear_warning(); } else { - auto f = std::bind(&DPS310Component::read_, this); - this->set_timeout("dps310", 10, f); + this->set_timeout("dps310", 10, [this]() { this->read_(); }); } } diff --git a/esphome/components/esp32_improv/esp32_improv_component.cpp b/esphome/components/esp32_improv/esp32_improv_component.cpp index e4ae49f235..c24b08b06f 100644 --- a/esphome/components/esp32_improv/esp32_improv_component.cpp +++ b/esphome/components/esp32_improv/esp32_improv_component.cpp @@ -350,8 +350,7 @@ void ESP32ImprovComponent::process_incoming_data_() { ESP_LOGD(TAG, "Received Improv Wi-Fi settings ssid=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(), command.password.c_str()); - auto f = std::bind(&ESP32ImprovComponent::on_wifi_connect_timeout_, this); - this->set_timeout("wifi-connect-timeout", 30000, f); + this->set_timeout("wifi-connect-timeout", 30000, [this]() { this->on_wifi_connect_timeout_(); }); this->incoming_data_.clear(); break; } diff --git a/esphome/components/improv_serial/improv_serial_component.cpp b/esphome/components/improv_serial/improv_serial_component.cpp index edceb9a3b1..003328d535 100644 --- a/esphome/components/improv_serial/improv_serial_component.cpp +++ b/esphome/components/improv_serial/improv_serial_component.cpp @@ -245,8 +245,7 @@ bool ImprovSerialComponent::parse_improv_payload_(improv::ImprovCommand &command ESP_LOGD(TAG, "Received settings: SSID=%s, password=" LOG_SECRET("%s"), command.ssid.c_str(), command.password.c_str()); - auto f = std::bind(&ImprovSerialComponent::on_wifi_connect_timeout_, this); - this->set_timeout("wifi-connect-timeout", 30000, f); + this->set_timeout("wifi-connect-timeout", 30000, [this]() { this->on_wifi_connect_timeout_(); }); return true; } case improv::GET_CURRENT_STATE: diff --git a/esphome/components/max31855/max31855.cpp b/esphome/components/max31855/max31855.cpp index 99129880f4..8370977ce2 100644 --- a/esphome/components/max31855/max31855.cpp +++ b/esphome/components/max31855/max31855.cpp @@ -15,8 +15,7 @@ void MAX31855Sensor::update() { this->disable(); // Conversion time typ: 170ms, max: 220ms - auto f = std::bind(&MAX31855Sensor::read_data_, this); - this->set_timeout("value", 220, f); + this->set_timeout("value", 220, [this]() { this->read_data_(); }); } void MAX31855Sensor::setup() { this->spi_setup(); } diff --git a/esphome/components/max31856/max31856.cpp b/esphome/components/max31856/max31856.cpp index ff65c8c5c9..35e12309ba 100644 --- a/esphome/components/max31856/max31856.cpp +++ b/esphome/components/max31856/max31856.cpp @@ -41,8 +41,8 @@ void MAX31856Sensor::update() { this->one_shot_temperature_(); // Datasheet max conversion time for 1 shot is 155ms for 60Hz / 185ms for 50Hz - auto f = std::bind(&MAX31856Sensor::read_thermocouple_temperature_, this); - this->set_timeout("MAX31856Sensor::read_thermocouple_temperature_", filter_ == FILTER_60HZ ? 155 : 185, f); + this->set_timeout("MAX31856Sensor::read_thermocouple_temperature_", filter_ == FILTER_60HZ ? 155 : 185, + [this]() { this->read_thermocouple_temperature_(); }); } void MAX31856Sensor::read_thermocouple_temperature_() { diff --git a/esphome/components/max31865/max31865.cpp b/esphome/components/max31865/max31865.cpp index 09b8368d07..8b06a01166 100644 --- a/esphome/components/max31865/max31865.cpp +++ b/esphome/components/max31865/max31865.cpp @@ -60,8 +60,7 @@ void MAX31865Sensor::update() { this->write_config_(0b11100000, 0b10100000); // Datasheet max conversion time is 55ms for 60Hz / 66ms for 50Hz - auto f = std::bind(&MAX31865Sensor::read_data_, this); - this->set_timeout("value", filter_ == FILTER_60HZ ? 55 : 66, f); + this->set_timeout("value", filter_ == FILTER_60HZ ? 55 : 66, [this]() { this->read_data_(); }); } void MAX31865Sensor::setup() { diff --git a/esphome/components/max6675/max6675.cpp b/esphome/components/max6675/max6675.cpp index c329cdfd42..b8527c6b1d 100644 --- a/esphome/components/max6675/max6675.cpp +++ b/esphome/components/max6675/max6675.cpp @@ -13,8 +13,7 @@ void MAX6675Sensor::update() { this->disable(); // Conversion time typ: 170ms, max: 220ms - auto f = std::bind(&MAX6675Sensor::read_data_, this); - this->set_timeout("value", 250, f); + this->set_timeout("value", 250, [this]() { this->read_data_(); }); } void MAX6675Sensor::setup() { this->spi_setup(); } diff --git a/esphome/components/midea/appliance_base.h b/esphome/components/midea/appliance_base.h index 660d185b49..c7737ba7d6 100644 --- a/esphome/components/midea/appliance_base.h +++ b/esphome/components/midea/appliance_base.h @@ -59,7 +59,7 @@ template<typename T> class ApplianceBase : public Component { public: ApplianceBase() { this->base_.setStream(&this->stream_); - this->base_.addOnStateCallback(std::bind(&ApplianceBase::on_status_change, this)); + this->base_.addOnStateCallback([this]() { this->on_status_change(); }); dudanov::midea::ApplianceBase::setLogger( [](int level, const char *tag, int line, const String &format, va_list args) { esp_log_vprintf_(level, tag, line, format.c_str(), args); diff --git a/esphome/components/ms5611/ms5611.cpp b/esphome/components/ms5611/ms5611.cpp index 7ed73400c8..d47ca245b8 100644 --- a/esphome/components/ms5611/ms5611.cpp +++ b/esphome/components/ms5611/ms5611.cpp @@ -45,8 +45,7 @@ void MS5611Component::update() { return; } - auto f = std::bind(&MS5611Component::read_temperature_, this); - this->set_timeout("temperature", 10, f); + this->set_timeout("temperature", 10, [this]() { this->read_temperature_(); }); } void MS5611Component::read_temperature_() { uint8_t bytes[3]; @@ -62,8 +61,7 @@ void MS5611Component::read_temperature_() { return; } - auto f = std::bind(&MS5611Component::read_pressure_, this, raw_temperature); - this->set_timeout("pressure", 10, f); + this->set_timeout("pressure", 10, [this, raw_temperature]() { this->read_pressure_(raw_temperature); }); } void MS5611Component::read_pressure_(uint32_t raw_temperature) { uint8_t bytes[3]; diff --git a/esphome/components/ms8607/ms8607.cpp b/esphome/components/ms8607/ms8607.cpp index 88a3e6d7dc..d141dcb191 100644 --- a/esphome/components/ms8607/ms8607.cpp +++ b/esphome/components/ms8607/ms8607.cpp @@ -281,9 +281,8 @@ void MS8607Component::request_read_temperature_() { return; } - auto f = std::bind(&MS8607Component::read_temperature_, this); // datasheet says 17.2ms max conversion time at OSR 8192 - this->set_timeout("temperature", 20, f); + this->set_timeout("temperature", 20, [this]() { this->read_temperature_(); }); } void MS8607Component::read_temperature_() { @@ -303,9 +302,8 @@ void MS8607Component::request_read_pressure_(uint32_t d2_raw_temperature) { return; } - auto f = std::bind(&MS8607Component::read_pressure_, this, d2_raw_temperature); // datasheet says 17.2ms max conversion time at OSR 8192 - this->set_timeout("pressure", 20, f); + this->set_timeout("pressure", 20, [this, d2_raw_temperature]() { this->read_pressure_(d2_raw_temperature); }); } void MS8607Component::read_pressure_(uint32_t d2_raw_temperature) { @@ -325,9 +323,8 @@ void MS8607Component::request_read_humidity_(float temperature_float) { return; } - auto f = std::bind(&MS8607Component::read_humidity_, this, temperature_float); // datasheet says 15.89ms max conversion time at OSR 8192 - this->set_timeout("humidity", 20, f); + this->set_timeout("humidity", 20, [this, temperature_float]() { this->read_humidity_(temperature_float); }); } void MS8607Component::read_humidity_(float temperature_float) { diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 42be326202..bf23e42e66 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -63,7 +63,7 @@ void SHT4XComponent::setup() { } ESP_LOGD(TAG, "Heater command: %x", this->heater_command_); - this->set_interval(heater_interval, std::bind(&SHT4XComponent::start_heater_, this)); + this->set_interval(heater_interval, [this]() { this->start_heater_(); }); } } diff --git a/esphome/components/sprinkler/sprinkler.cpp b/esphome/components/sprinkler/sprinkler.cpp index d1f7452054..0802cdec8e 100644 --- a/esphome/components/sprinkler/sprinkler.cpp +++ b/esphome/components/sprinkler/sprinkler.cpp @@ -335,8 +335,8 @@ Sprinkler::Sprinkler(const char *name) : name_(name) { // The `name` is stored for dump_config logging this->timer_.init(2); // Timer names only need to be unique within this component instance - this->timer_.push_back({"sm", false, 0, 0, std::bind(&Sprinkler::sm_timer_callback_, this)}); - this->timer_.push_back({"vs", false, 0, 0, std::bind(&Sprinkler::valve_selection_callback_, this)}); + this->timer_.push_back({"sm", false, 0, 0, [this]() { this->sm_timer_callback_(); }}); + this->timer_.push_back({"vs", false, 0, 0, [this]() { this->valve_selection_callback_(); }}); } void Sprinkler::setup() { From cdc4ba6295f8da19a369691e072f35943760083d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:43:06 -1000 Subject: [PATCH 1543/2030] [api] Replace std::bind with lambdas in CustomAPIDevice (#14963) --- esphome/components/api/custom_api_device.h | 27 ++++++++++++++-------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/esphome/components/api/custom_api_device.h b/esphome/components/api/custom_api_device.h index 2fd9cb0dd2..c2b0f14bcc 100644 --- a/esphome/components/api/custom_api_device.h +++ b/esphome/components/api/custom_api_device.h @@ -136,8 +136,9 @@ class CustomAPIDevice { template<typename T> void subscribe_homeassistant_state(void (T::*callback)(StringRef), const std::string &entity_id, const std::string &attribute = "") { - auto f = std::bind(callback, (T *) this, std::placeholders::_1); - global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f)); + auto *obj = static_cast<T *>(this); + global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), + [obj, callback](StringRef state) { (obj->*callback)(state); }); } /** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version). @@ -148,10 +149,12 @@ class CustomAPIDevice { ESPDEPRECATED("Use void callback(StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0") void subscribe_homeassistant_state(void (T::*callback)(std::string), const std::string &entity_id, const std::string &attribute = "") { - auto f = std::bind(callback, (T *) this, std::placeholders::_1); + auto *obj = static_cast<T *>(this); // Explicit type to disambiguate overload resolution - global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), - std::function<void(const std::string &)>(f)); + global_api_server->subscribe_home_assistant_state( + entity_id, optional<std::string>(attribute), + std::function<void(const std::string &)>( + [obj, callback](const std::string &state) { (obj->*callback)(state); })); } /** Subscribe to the state (or attribute state) of an entity from Home Assistant. @@ -176,8 +179,10 @@ class CustomAPIDevice { template<typename T> void subscribe_homeassistant_state(void (T::*callback)(const std::string &, StringRef), const std::string &entity_id, const std::string &attribute = "") { - auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); - global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), std::move(f)); + auto *obj = static_cast<T *>(this); + global_api_server->subscribe_home_assistant_state( + entity_id, optional<std::string>(attribute), + [obj, callback, entity_id](StringRef state) { (obj->*callback)(entity_id, state); }); } /** Subscribe to the state (or attribute state) of an entity from Home Assistant (legacy std::string version). @@ -188,10 +193,12 @@ class CustomAPIDevice { ESPDEPRECATED("Use void callback(const std::string &, StringRef) instead. Will be removed in 2027.1.0.", "2026.1.0") void subscribe_homeassistant_state(void (T::*callback)(std::string, std::string), const std::string &entity_id, const std::string &attribute = "") { - auto f = std::bind(callback, (T *) this, entity_id, std::placeholders::_1); + auto *obj = static_cast<T *>(this); // Explicit type to disambiguate overload resolution - global_api_server->subscribe_home_assistant_state(entity_id, optional<std::string>(attribute), - std::function<void(const std::string &)>(f)); + global_api_server->subscribe_home_assistant_state( + entity_id, optional<std::string>(attribute), + std::function<void(const std::string &)>( + [obj, callback, entity_id](const std::string &state) { (obj->*callback)(entity_id, state); })); } #else template<typename T> From 5637116378d5a01c7783f0f90bf1beade4341547 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:43:22 -1000 Subject: [PATCH 1544/2030] [mqtt] Replace std::bind with lambdas in CustomMQTTDevice (#14964) --- esphome/components/mqtt/custom_mqtt_device.h | 25 ++++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/esphome/components/mqtt/custom_mqtt_device.h b/esphome/components/mqtt/custom_mqtt_device.h index 09ed7bd6d1..a003379fe0 100644 --- a/esphome/components/mqtt/custom_mqtt_device.h +++ b/esphome/components/mqtt/custom_mqtt_device.h @@ -189,28 +189,33 @@ class CustomMQTTDevice { template<typename T> void CustomMQTTDevice::subscribe(const std::string &topic, void (T::*callback)(const std::string &, const std::string &), uint8_t qos) { - auto f = std::bind(callback, (T *) this, std::placeholders::_1, std::placeholders::_2); - global_mqtt_client->subscribe(topic, f, qos); + auto *obj = static_cast<T *>(this); + global_mqtt_client->subscribe( + topic, [obj, callback](const std::string &t, const std::string &payload) { (obj->*callback)(t, payload); }, qos); } template<typename T> void CustomMQTTDevice::subscribe(const std::string &topic, void (T::*callback)(const std::string &), uint8_t qos) { - auto f = std::bind(callback, (T *) this, std::placeholders::_2); - global_mqtt_client->subscribe(topic, f, qos); + auto *obj = static_cast<T *>(this); + global_mqtt_client->subscribe( + topic, [obj, callback](const std::string &, const std::string &payload) { (obj->*callback)(payload); }, qos); } template<typename T> void CustomMQTTDevice::subscribe(const std::string &topic, void (T::*callback)(), uint8_t qos) { - auto f = std::bind(callback, (T *) this); - global_mqtt_client->subscribe(topic, f, qos); + auto *obj = static_cast<T *>(this); + global_mqtt_client->subscribe( + topic, [obj, callback](const std::string &, const std::string &) { (obj->*callback)(); }, qos); } template<typename T> void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(const std::string &, JsonObject), uint8_t qos) { - auto f = std::bind(callback, (T *) this, std::placeholders::_1, std::placeholders::_2); - global_mqtt_client->subscribe_json(topic, f, qos); + auto *obj = static_cast<T *>(this); + global_mqtt_client->subscribe_json( + topic, [obj, callback](const std::string &t, JsonObject root) { (obj->*callback)(t, root); }, qos); } template<typename T> void CustomMQTTDevice::subscribe_json(const std::string &topic, void (T::*callback)(JsonObject), uint8_t qos) { - auto f = std::bind(callback, (T *) this, std::placeholders::_2); - global_mqtt_client->subscribe_json(topic, f, qos); + auto *obj = static_cast<T *>(this); + global_mqtt_client->subscribe_json( + topic, [obj, callback](const std::string &, JsonObject root) { (obj->*callback)(root); }, qos); } } // namespace esphome::mqtt From 1ba55049445d1e32567d0c5c9eb03d73c73c17f4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:43:47 -1000 Subject: [PATCH 1545/2030] [mqtt] Replace std::bind with lambda in MQTTPublishJsonAction (#14965) --- esphome/components/mqtt/mqtt_client.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 127e4073b0..0d52d98d2f 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -405,15 +405,14 @@ template<typename... Ts> class MQTTPublishJsonAction : public Action<Ts...> { void set_payload(std::function<void(Ts..., JsonObject)> payload) { this->payload_ = payload; } void play(const Ts &...x) override { - auto f = std::bind(&MQTTPublishJsonAction<Ts...>::encode_, this, x..., std::placeholders::_1); auto topic = this->topic_.value(x...); auto qos = this->qos_.value(x...); auto retain = this->retain_.value(x...); - this->parent_->publish_json(topic, f, qos, retain); + this->parent_->publish_json( + topic, [this, x...](JsonObject root) { this->payload_(x..., root); }, qos, retain); } protected: - void encode_(Ts... x, JsonObject root) { this->payload_(x..., root); } std::function<void(Ts..., JsonObject)> payload_; MQTTClientComponent *parent_; }; From e7dcf54a770125800372efd5195be7480ddad93e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:44:02 -1000 Subject: [PATCH 1546/2030] [http_request] Replace std::bind with lambdas in HttpRequestSendAction (#14966) --- esphome/components/http_request/http_request.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index 8bdea470b5..73dbda8694 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -487,12 +487,10 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { body = this->body_.value(x...); } if (!this->json_.empty()) { - auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_, this, x..., std::placeholders::_1); - body = json::build_json(f); + body = json::build_json([this, x...](JsonObject root) { this->encode_json_(x..., root); }); } if (this->json_func_ != nullptr) { - auto f = std::bind(&HttpRequestSendAction<Ts...>::encode_json_func_, this, x..., std::placeholders::_1); - body = json::build_json(f); + body = json::build_json([this, x...](JsonObject root) { this->json_func_(x..., root); }); } std::vector<Header> request_headers; request_headers.reserve(this->request_headers_.size()); @@ -561,7 +559,6 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> { root[item.first] = val.value(x...); } } - void encode_json_func_(Ts... x, JsonObject root) { this->json_func_(x..., root); } HttpRequestComponent *parent_; FixedVector<std::pair<const char *, TemplatableValue<const char *, Ts...>>> request_headers_{}; std::vector<std::string> lower_case_collect_headers_{"content-type", "content-length"}; From 63f0d054b7b3182f03a94c520c6f239980dce4dd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:44:16 -1000 Subject: [PATCH 1547/2030] [core] Replace std::bind with lambda in DelayAction (#14968) --- esphome/core/base_automation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 67e1755cc9..985f26e711 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -188,7 +188,7 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon // Issue #10264: This is a workaround for parallel script delays interfering with each other. // Optimization: For no-argument delays (most common case), use direct lambda - // instead of std::bind to avoid bind overhead (~16 bytes heap + faster execution) + // to avoid overhead from capturing arguments by value if constexpr (sizeof...(Ts) == 0) { App.scheduler.set_timer_common_( this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL, nullptr, @@ -196,9 +196,9 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon [this]() { this->play_next_(); }, /* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1); } else { - // For delays with arguments, use std::bind to preserve argument values + // For delays with arguments, capture by value to preserve argument values // Arguments must be copied because original references may be invalid after delay - auto f = std::bind(&DelayAction<Ts...>::play_next_, this, x...); + auto f = [this, x...]() { this->play_next_(x...); }; App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL, nullptr, static_cast<uint32_t>(InternalSchedulerID::DELAY_ACTION), this->delay_.value(x...), std::move(f), From a8ed781f3ece3326765e99a4f85876a9be754648 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:44:35 -1000 Subject: [PATCH 1548/2030] [time] Fix lookup of top-level IANA timezone keys like UTC and GMT (#14952) --- esphome/components/time/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 7ffa408db9..9821046a73 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -59,15 +59,20 @@ _DST_RULE_TYPE_MAP = { def _load_tzdata(iana_key: str) -> bytes | None: # From https://tzdata.readthedocs.io/en/latest/#examples + if not iana_key: + return None try: package_loc, resource = iana_key.rsplit("/", 1) except ValueError: - return None - package = "tzdata.zoneinfo." + package_loc.replace("/", ".") + # Handle top-level timezone entries like "UTC", "GMT" + package = "tzdata.zoneinfo" + resource = iana_key + else: + package = "tzdata.zoneinfo." + package_loc.replace("/", ".") try: return (resources.files(package) / resource).read_bytes() - except (FileNotFoundError, ModuleNotFoundError): + except (FileNotFoundError, ModuleNotFoundError, IsADirectoryError): return None From 37a3c3ab3abef07f016efa7e6723ee24457baed6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:50:38 -1000 Subject: [PATCH 1549/2030] [core] Replace std::bind with placeholders to lambdas (#14962) --- esphome/components/haier/haier_base.cpp | 2 +- esphome/components/haier/hon_climate.cpp | 38 +++++++++++-------- .../components/haier/smartair2_climate.cpp | 17 +++++---- .../number/homeassistant_number.cpp | 16 ++++---- .../wifi/wifi_component_libretiny.cpp | 4 +- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/esphome/components/haier/haier_base.cpp b/esphome/components/haier/haier_base.cpp index 35eaf36d32..4a06066d3c 100644 --- a/esphome/components/haier/haier_base.cpp +++ b/esphome/components/haier/haier_base.cpp @@ -242,7 +242,7 @@ void HaierClimateBase::setup() { this->last_request_timestamp_ = std::chrono::steady_clock::now(); this->set_phase(ProtocolPhases::SENDING_INIT_1); this->haier_protocol_.set_default_timeout_handler( - std::bind(&esphome::haier::HaierClimateBase::timeout_default_handler_, this, std::placeholders::_1)); + [this](haier_protocol::FrameType type) { return this->timeout_default_handler_(type); }); this->set_handlers(); this->initialization(); } diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index b7888f7976..92defe560e 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -301,32 +301,38 @@ void HonClimate::set_handlers() { // Set handlers this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::GET_DEVICE_VERSION, - std::bind(&HonClimate::get_device_version_answer_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->get_device_version_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::GET_DEVICE_ID, - std::bind(&HonClimate::get_device_id_answer_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->get_device_id_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::CONTROL, - std::bind(&HonClimate::status_handler_, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, - std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->status_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::GET_MANAGEMENT_INFORMATION, - std::bind(&HonClimate::get_management_information_answer_handler_, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->get_management_information_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::GET_ALARM_STATUS, - std::bind(&HonClimate::get_alarm_status_answer_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->get_alarm_status_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::REPORT_NETWORK_STATUS, - std::bind(&HonClimate::report_network_status_answer_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); - this->haier_protocol_.set_message_handler( - haier_protocol::FrameType::ALARM_STATUS, - std::bind(&HonClimate::alarm_status_message_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->report_network_status_answer_handler_(req, msg, data, size); + }); + this->haier_protocol_.set_message_handler(haier_protocol::FrameType::ALARM_STATUS, + [this](haier_protocol::FrameType type, const uint8_t *data, size_t size) { + return this->alarm_status_message_handler_(type, data, size); + }); } void HonClimate::dump_config() { diff --git a/esphome/components/haier/smartair2_climate.cpp b/esphome/components/haier/smartair2_climate.cpp index e91224e2d8..2be5d13050 100644 --- a/esphome/components/haier/smartair2_climate.cpp +++ b/esphome/components/haier/smartair2_climate.cpp @@ -106,18 +106,21 @@ void Smartair2Climate::set_handlers() { // Set handlers this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::GET_DEVICE_VERSION, - std::bind(&Smartair2Climate::get_device_version_answer_handler_, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->get_device_version_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::CONTROL, - std::bind(&Smartair2Climate::status_handler_, this, std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->status_handler_(req, msg, data, size); + }); this->haier_protocol_.set_answer_handler( haier_protocol::FrameType::REPORT_NETWORK_STATUS, - std::bind(&Smartair2Climate::report_network_status_answer_handler_, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); + [this](haier_protocol::FrameType req, haier_protocol::FrameType msg, const uint8_t *data, size_t size) { + return this->report_network_status_answer_handler_(req, msg, data, size); + }); this->haier_protocol_.set_default_timeout_handler( - std::bind(&Smartair2Climate::messages_timeout_handler_with_cycle_for_init_, this, std::placeholders::_1)); + [this](haier_protocol::FrameType type) { return this->messages_timeout_handler_with_cycle_for_init_(type); }); } void Smartair2Climate::dump_config() { diff --git a/esphome/components/homeassistant/number/homeassistant_number.cpp b/esphome/components/homeassistant/number/homeassistant_number.cpp index 00ea88ff16..da802b7fe9 100644 --- a/esphome/components/homeassistant/number/homeassistant_number.cpp +++ b/esphome/components/homeassistant/number/homeassistant_number.cpp @@ -55,15 +55,15 @@ void HomeassistantNumber::step_retrieved_(StringRef step) { } void HomeassistantNumber::setup() { - api::global_api_server->subscribe_home_assistant_state( - this->entity_id_, nullptr, std::bind(&HomeassistantNumber::state_changed_, this, std::placeholders::_1)); + api::global_api_server->subscribe_home_assistant_state(this->entity_id_, nullptr, + [this](StringRef state) { this->state_changed_(state); }); - api::global_api_server->get_home_assistant_state( - this->entity_id_, "min", std::bind(&HomeassistantNumber::min_retrieved_, this, std::placeholders::_1)); - api::global_api_server->get_home_assistant_state( - this->entity_id_, "max", std::bind(&HomeassistantNumber::max_retrieved_, this, std::placeholders::_1)); - api::global_api_server->get_home_assistant_state( - this->entity_id_, "step", std::bind(&HomeassistantNumber::step_retrieved_, this, std::placeholders::_1)); + api::global_api_server->get_home_assistant_state(this->entity_id_, "min", + [this](StringRef min) { this->min_retrieved_(min); }); + api::global_api_server->get_home_assistant_state(this->entity_id_, "max", + [this](StringRef max) { this->max_retrieved_(max); }); + api::global_api_server->get_home_assistant_state(this->entity_id_, "step", + [this](StringRef step) { this->step_retrieved_(step); }); } void HomeassistantNumber::dump_config() { diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index 4c4150e44d..b049a0413c 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -629,8 +629,8 @@ void WiFiComponent::wifi_pre_setup_() { return; } - auto f = std::bind(&WiFiComponent::wifi_event_callback_, this, std::placeholders::_1, std::placeholders::_2); - WiFi.onEvent(f); + WiFi.onEvent( + [this](arduino_event_id_t event, arduino_event_info_t info) { this->wifi_event_callback_(event, info); }); // Make sure WiFi is in clean state before anything starts this->wifi_mode_(false, false); } From c2a96ea293694126c9e43d8c56cf58130289221b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Mar 2026 10:54:53 -1000 Subject: [PATCH 1550/2030] Bump ruff from 0.15.6 to 0.15.7 (#14977) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index acd8383a2f..0d3f0671f5 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.6 # also change in .pre-commit-config.yaml when updating +ruff==0.15.7 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From 902258b56e3401b1e2c3f439c22e6e6bf9ee84e6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:11:06 -1000 Subject: [PATCH 1551/2030] [preferences] Compile out loop() when flash_write_interval is non-zero (#14943) --- esphome/components/preferences/__init__.py | 6 +++++- esphome/components/preferences/syncer.h | 17 +++++++---------- esphome/core/defines.h | 1 + 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esphome/components/preferences/__init__.py b/esphome/components/preferences/__init__.py index c6bede891a..c426872728 100644 --- a/esphome/components/preferences/__init__.py +++ b/esphome/components/preferences/__init__.py @@ -21,5 +21,9 @@ CONFIG_SCHEMA = cv.Schema( @coroutine_with_priority(CoroPriority.PREFERENCES) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - cg.add(var.set_write_interval(config[CONF_FLASH_WRITE_INTERVAL])) + write_interval = config[CONF_FLASH_WRITE_INTERVAL] + if write_interval.total_milliseconds == 0: + cg.add_define("USE_PREFERENCES_SYNC_EVERY_LOOP") + else: + cg.add(var.set_write_interval(write_interval)) await cg.register_component(var, config) diff --git a/esphome/components/preferences/syncer.h b/esphome/components/preferences/syncer.h index 96716d3f30..e28cc8c8d5 100644 --- a/esphome/components/preferences/syncer.h +++ b/esphome/components/preferences/syncer.h @@ -8,24 +8,21 @@ namespace preferences { class IntervalSyncer final : public Component { public: +#ifdef USE_PREFERENCES_SYNC_EVERY_LOOP + void loop() override { global_preferences->sync(); } +#else void set_write_interval(uint32_t write_interval) { this->write_interval_ = write_interval; } void setup() override { - if (this->write_interval_ != 0) { - set_interval(this->write_interval_, []() { global_preferences->sync(); }); - // When using interval-based syncing, we don't need the loop - this->disable_loop(); - } - } - void loop() override { - if (this->write_interval_ == 0) { - global_preferences->sync(); - } + this->set_interval(this->write_interval_, []() { global_preferences->sync(); }); } +#endif void on_shutdown() override { global_preferences->sync(); } float get_setup_priority() const override { return setup_priority::BUS; } +#ifndef USE_PREFERENCES_SYNC_EVERY_LOOP protected: uint32_t write_interval_{60000}; +#endif }; } // namespace preferences diff --git a/esphome/core/defines.h b/esphome/core/defines.h index c817f8ef27..d94b7e9f5d 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -118,6 +118,7 @@ #define USE_NUMBER #define USE_OUTPUT #define USE_POWER_SUPPLY +#define USE_PREFERENCES_SYNC_EVERY_LOOP #define USE_QR_CODE #define USE_SAFE_MODE_CALLBACK #define USE_SELECT From a9cb7143dc262f09e4c73c04a0bac4c846ed109f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:11:17 -1000 Subject: [PATCH 1552/2030] [core] Inline calculate_looping_components_ into header (#14944) --- esphome/core/application.cpp | 16 ---------------- esphome/core/application.h | 14 +++++++++++++- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 3a9e825e04..08df385475 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -394,22 +394,6 @@ void Application::teardown_components(uint32_t timeout_ms) { } } -void Application::calculate_looping_components_() { - // FixedVector capacity was pre-initialized by codegen with the exact count - // of components that override loop(), computed at C++ compile time. - - // Add all components with loop override that aren't already LOOP_DONE - // Some components (like logger) may call disable_loop() during initialization - // before setup runs, so we need to respect their LOOP_DONE state - this->add_looping_components_by_state_(false); - - this->looping_components_active_end_ = this->looping_components_.size(); - - // Then add any components that are already LOOP_DONE to the inactive section - // This handles components that called disable_loop() during initialization - this->add_looping_components_by_state_(true); -} - void Application::add_looping_components_by_state_(bool match_loop_done) { for (auto *obj : this->components_) { if (obj->has_overridden_loop() && diff --git a/esphome/core/application.h b/esphome/core/application.h index 23bb209eaf..26abc15433 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -595,7 +595,19 @@ class Application { void register_component_impl_(Component *comp, bool has_loop); - void calculate_looping_components_(); + void calculate_looping_components_() { + // FixedVector capacity was pre-initialized by codegen with the exact count + // of components that override loop(), computed at C++ compile time. + + // Add all components with loop override that aren't already LOOP_DONE + // Some components (like logger) may call disable_loop() during initialization + // before setup runs, so we need to respect their LOOP_DONE state + this->add_looping_components_by_state_(false); + this->looping_components_active_end_ = this->looping_components_.size(); + // Then add any components that are already LOOP_DONE to the inactive section + // This handles components that called disable_loop() during initialization + this->add_looping_components_by_state_(true); + } void add_looping_components_by_state_(bool match_loop_done); // These methods are called by Component::disable_loop() and Component::enable_loop() From de177d24451f92b2233836e964d2b442981c50cd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:11:49 -1000 Subject: [PATCH 1553/2030] [logger] Fix ESP8266 crash with VERY_VERBOSE log level (#14980) --- esphome/components/logger/__init__.py | 29 ++++++++++++++++++--------- esphome/core/config.py | 4 +++- esphome/coroutine.py | 10 +++++++-- esphome/writer.py | 3 +++ 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 675f9a2ca4..a5601e6a8f 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -56,6 +56,7 @@ from esphome.const import ( PlatformFramework, ) from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core"] logger_ns = cg.esphome_ns.namespace("logger") @@ -323,12 +324,11 @@ CONFIG_SCHEMA = cv.All( ) -@coroutine_with_priority(CoroPriority.DIAGNOSTICS) -async def to_code(config): - baud_rate = config[CONF_BAUD_RATE] +@coroutine_with_priority(CoroPriority.EARLY_INIT) +async def to_code(config: ConfigType) -> None: + baud_rate: int = config[CONF_BAUD_RATE] level = config[CONF_LEVEL] CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level - initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)] tx_buffer_size = config[CONF_TX_BUFFER_SIZE] cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) log = cg.new_Pvariable( @@ -347,10 +347,23 @@ async def to_code(config): HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]] ) ) - # pre_setup() must be called before init_log_buffer() because - # init_log_buffer() calls disable_loop() which may log at VV level, - # and global_logger must be set before any logging occurs. + # pre_setup() sets global_logger and must run before any other code + # that may call ESP_LOG* (e.g. setup_preferences contains ESP_LOGVV). cg.add(log.pre_setup()) + initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)] + cg.add(log.set_log_level(initial_level)) + + # Schedule the rest of logger setup at DIAGNOSTICS priority, after + # Application is constructed (CORE priority) but before most components. + CORE.add_job(_late_logger_init, config) + + +@coroutine_with_priority(CoroPriority.DIAGNOSTICS) +async def _late_logger_init(config: ConfigType) -> None: + """Finish logger setup after Application is constructed.""" + log = await cg.get_variable(config[CONF_ID]) + level = config[CONF_LEVEL] + baud_rate: int = config[CONF_BAUD_RATE] if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] if task_log_buffer_size > 0: @@ -363,8 +376,6 @@ async def to_code(config): cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") cg.add(log.init_log_buffer(64)) # Fixed 64 slots for host - cg.add(log.set_log_level(initial_level)) - # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] if logs_config or config[CONF_RUNTIME_TAG_LEVELS]: diff --git a/esphome/core/config.py b/esphome/core/config.py index e112720f2b..e02c6ec75f 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -587,7 +587,9 @@ async def _add_looping_components() -> None: @coroutine_with_priority(CoroPriority.CORE) async def to_code(config: ConfigType) -> None: - cg.add_global(cg.global_ns.namespace("esphome").using) + # using namespace esphome is hardcoded in writer.py to guarantee it + # precedes all variable declarations regardless of coroutine priority. + # These can be used by user lambdas, put them to default scope # picolibc (IDF 6.0+) declares isnan in global scope, conflicting with using std::isnan cg.add_global(cg.RawStatement("#ifndef __PICOLIBC__")) diff --git a/esphome/coroutine.py b/esphome/coroutine.py index f5d512e510..3ce94cc979 100644 --- a/esphome/coroutine.py +++ b/esphome/coroutine.py @@ -63,7 +63,13 @@ class CoroPriority(enum.IntEnum): resolution during code generation. """ - # Platform initialization - must run first + # Early init - runs before platform init and before Application exists. + # Currently used only to connect logging so ESP_LOG* calls work + # immediately in all subsequent phases. + # Examples: logger (1100) + EARLY_INIT = 1100 + + # Platform initialization # Examples: esp32, esp8266, rp2040 PLATFORM = 1000 @@ -83,7 +89,7 @@ class CoroPriority(enum.IntEnum): CORE = 100 # Diagnostic and debugging systems - # Examples: logger (90) + # Examples: debug component (90) DIAGNOSTICS = 90 # Status and monitoring systems diff --git a/esphome/writer.py b/esphome/writer.py index fd4c811fb3..69a35d00e3 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -381,7 +381,10 @@ def write_cpp(code_s): code_format = CPP_BASE_FORMAT copy_src_tree() + # using namespace esphome must precede all variable declarations since + # codegen types assume this namespace is in scope (esphome_ns = global_ns). global_s = '#include "esphome.h"\n' + global_s += "using namespace esphome;\n" global_s += CORE.cpp_global_section full_file = f"{code_format[0] + CPP_INCLUDE_BEGIN}\n{global_s}{CPP_INCLUDE_END}" From 7ac001e994428e28f6c838c7b216527af6e2affd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:12:03 -1000 Subject: [PATCH 1554/2030] [mhz19] Fix unused function warning for detection_range_to_log_string (#14981) --- esphome/components/mhz19/mhz19.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/mhz19/mhz19.cpp b/esphome/components/mhz19/mhz19.cpp index bccea7d423..ff518808d9 100644 --- a/esphome/components/mhz19/mhz19.cpp +++ b/esphome/components/mhz19/mhz19.cpp @@ -16,6 +16,7 @@ static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_2000PPM[] = {0xFF, 0x01, 0x static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_5000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x13, 0x88}; static const uint8_t MHZ19_COMMAND_DETECTION_RANGE_0_10000PPM[] = {0xFF, 0x01, 0x99, 0x00, 0x00, 0x00, 0x27, 0x10}; +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG static const LogString *detection_range_to_log_string(MHZ19DetectionRange range) { switch (range) { case MHZ19_DETECTION_RANGE_0_2000PPM: @@ -28,6 +29,7 @@ static const LogString *detection_range_to_log_string(MHZ19DetectionRange range) return LOG_STR("default"); } } +#endif uint8_t mhz19_checksum(const uint8_t *command) { uint8_t sum = 0; From 151f71e033988cef02905d6600f89f98fb0aff77 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:12:15 -1000 Subject: [PATCH 1555/2030] [ci] Add libretiny and zephyr to memory impact platform filter (#14985) --- script/determine-jobs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/determine-jobs.py b/script/determine-jobs.py index 9f32238780..d94d472c9e 100755 --- a/script/determine-jobs.py +++ b/script/determine-jobs.py @@ -111,11 +111,13 @@ PLATFORM_SPECIFIC_COMPONENTS = frozenset( "esp32", # ESP32 platform implementation "esp8266", # ESP8266 platform implementation "rp2040", # Raspberry Pi Pico / RP2040 platform implementation + "libretiny", # LibreTiny base platform implementation "bk72xx", # Beken BK72xx platform implementation (uses LibreTiny) "rtl87xx", # Realtek RTL87xx platform implementation (uses LibreTiny) "ln882x", # Winner Micro LN882x platform implementation (uses LibreTiny) "host", # Host platform (for testing on development machine) "nrf52", # Nordic nRF52 platform implementation (uses Zephyr) + "zephyr", # Zephyr RTOS platform implementation } ) From b02f0e3c5feb2112e82302ac543a77caee451b80 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:39:10 +1000 Subject: [PATCH 1556/2030] [sdl] Fix get_width()/height() when rotation used (#14950) --- esphome/components/sdl/sdl_esphome.cpp | 37 ++++++++++++++++++++++++++ esphome/components/sdl/sdl_esphome.h | 4 +-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/esphome/components/sdl/sdl_esphome.cpp b/esphome/components/sdl/sdl_esphome.cpp index f235e4e68c..74ca2ce39a 100644 --- a/esphome/components/sdl/sdl_esphome.cpp +++ b/esphome/components/sdl/sdl_esphome.cpp @@ -5,6 +5,30 @@ namespace esphome { namespace sdl { +int Sdl::get_width() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + return this->get_height_internal(); + case display::DISPLAY_ROTATION_0_DEGREES: + case display::DISPLAY_ROTATION_180_DEGREES: + default: + return this->get_width_internal(); + } +} + +int Sdl::get_height() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + case display::DISPLAY_ROTATION_180_DEGREES: + return this->get_height_internal(); + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + default: + return this->get_width_internal(); + } +} + void Sdl::setup() { SDL_Init(SDL_INIT_VIDEO); this->window_ = SDL_CreateWindow(App.get_name().c_str(), this->pos_x_, this->pos_y_, this->width_, this->height_, @@ -49,6 +73,19 @@ void Sdl::draw_pixel_at(int x, int y, Color color) { if (!this->get_clipping().inside(x, y)) return; + if (this->rotation_ == display::DISPLAY_ROTATION_180_DEGREES) { + x = this->width_ - x - 1; + y = this->height_ - y - 1; + } else if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES) { + auto tmp = x; + x = this->width_ - y - 1; + y = tmp; + } else if (this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) { + auto tmp = y; + y = this->height_ - x - 1; + x = tmp; + } + SDL_Rect rect{x, y, 1, 1}; auto data = (display::ColorUtil::color_to_565(color, display::COLOR_ORDER_RGB)); SDL_UpdateTexture(this->texture_, &rect, &data, 2); diff --git a/esphome/components/sdl/sdl_esphome.h b/esphome/components/sdl/sdl_esphome.h index c025e8ff6e..ce34cb817e 100644 --- a/esphome/components/sdl/sdl_esphome.h +++ b/esphome/components/sdl/sdl_esphome.h @@ -33,8 +33,8 @@ class Sdl : public display::Display { this->pos_x_ = pos_x; this->pos_y_ = pos_y; } - int get_width() override { return this->width_; } - int get_height() override { return this->height_; } + int get_width() override; + int get_height() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } void dump_config() override { LOG_DISPLAY("", "SDL", this); } template<typename F> void add_key_listener(int32_t keycode, F &&callback) { From 7df550f2a9a9049e742496298f94c9a6bb46cf9e Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:52:52 +1000 Subject: [PATCH 1557/2030] Ensure lvgl libs available when editing for host (#14987) --- .clang-tidy.hash | 2 +- platformio.ini | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index 72023e511d..c32978d411 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -44c877ff43765562ac8298902bf2208799643b77facf09c1c0c3c8c4e17187eb +9f5d763f95ff720024f3fdddba2fad3801e2bfe00b7cc2124e6d68c17d3504c6 diff --git a/platformio.ini b/platformio.ini index c5a4c630df..d3a482b652 100644 --- a/platformio.ini +++ b/platformio.ini @@ -546,6 +546,7 @@ extends = common platform = platformio/native lib_deps = esphome/noise-c@0.1.11 ; used by api + lvgl/lvgl@9.5.0 ; lvgl build_flags = ${common.build_flags} -DUSE_HOST From 6e87f8eb4e350f4a7bbcb0d6dd6fc3c8d9d2b11e Mon Sep 17 00:00:00 2001 From: Kent Gibson <warthog618@gmail.com> Date: Fri, 20 Mar 2026 10:06:58 +0800 Subject: [PATCH 1558/2030] [template] alarm_control_panel collapse SensorDataStore and bypassed_sensor_indicies into SensorInfo (#14852) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- .../template_alarm_control_panel.cpp | 51 ++++++++++--------- .../template_alarm_control_panel.h | 24 ++++----- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp index 651aa3c489..a224ab8459 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.cpp @@ -16,17 +16,15 @@ static const char *const TAG = "template.alarm_control_panel"; TemplateAlarmControlPanel::TemplateAlarmControlPanel(){}; #ifdef USE_BINARY_SENSOR -void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor, uint16_t flags, AlarmSensorType type) { - // Save the flags and type. Assign a store index for the per sensor data type. - SensorDataStore sd; - sd.last_chime_state = false; +void TemplateAlarmControlPanel::add_sensor(binary_sensor::BinarySensor *sensor, uint8_t flags, AlarmSensorType type) { + // Save the sensor pointer, flags, and type in the per-sensor info structure. AlarmSensor alarm_sensor; alarm_sensor.sensor = sensor; alarm_sensor.info.flags = flags; alarm_sensor.info.type = type; - alarm_sensor.info.store_index = this->next_store_index_++; + alarm_sensor.info.chime_active = false; + alarm_sensor.info.auto_bypassed = false; this->sensors_.push_back(alarm_sensor); - this->sensor_data_.push_back(sd); }; // Alarm sensor type strings indexed by AlarmSensorType enum (0-3): DELAYED, INSTANT, DELAYED_FOLLOWER, INSTANT_ALWAYS @@ -55,7 +53,7 @@ void TemplateAlarmControlPanel::dump_config() { (this->trigger_time_ / 1000), this->get_supported_features()); #ifdef USE_BINARY_SENSOR for (const auto &alarm_sensor : this->sensors_) { - const uint16_t flags = alarm_sensor.info.flags; + const uint8_t flags = alarm_sensor.info.flags; ESP_LOGCONFIG(TAG, " Binary Sensor:\n" " Name: %s\n" @@ -95,7 +93,7 @@ void TemplateAlarmControlPanel::loop() { delay = this->arming_night_time_; } if ((millis() - this->last_update_) > delay) { - this->bypass_before_arming(); + this->auto_bypass_sensors_(); this->publish_state(this->desired_state_); } return; @@ -117,26 +115,25 @@ void TemplateAlarmControlPanel::loop() { #ifdef USE_BINARY_SENSOR // Test all of the sensors regardless of the alarm panel state - for (const auto &alarm_sensor : this->sensors_) { - const auto &info = alarm_sensor.info; + for (auto &alarm_sensor : this->sensors_) { + auto &info = alarm_sensor.info; auto *sensor = alarm_sensor.sensor; // Check for chime zones if (info.flags & BINARY_SENSOR_MODE_CHIME) { // Look for the transition from closed to open - if ((!this->sensor_data_[info.store_index].last_chime_state) && (sensor->state)) { + if ((!info.chime_active) && (sensor->state)) { // Must be disarmed to chime if (this->current_state_ == ACP_STATE_DISARMED) { this->chime_callback_.call(); } } // Record the sensor state change - this->sensor_data_[info.store_index].last_chime_state = sensor->state; + info.chime_active = sensor->state; } // Check for faulted sensors if (sensor->state) { // Skip if auto bypassed - if (std::count(this->bypassed_sensor_indicies_.begin(), this->bypassed_sensor_indicies_.end(), - info.store_index) == 1) { + if (info.auto_bypassed) { continue; } // Skip if bypass armed home @@ -239,23 +236,33 @@ void TemplateAlarmControlPanel::arm_(optional<std::string> code, alarm_control_p if (delay > 0) { this->publish_state(ACP_STATE_ARMING); } else { - this->bypass_before_arming(); + this->auto_bypass_sensors_(); this->publish_state(state); } } -void TemplateAlarmControlPanel::bypass_before_arming() { +void TemplateAlarmControlPanel::auto_bypass_sensors_() { #ifdef USE_BINARY_SENSOR - for (const auto &alarm_sensor : this->sensors_) { + for (auto &alarm_sensor : this->sensors_) { + auto &info = alarm_sensor.info; + auto *sensor = alarm_sensor.sensor; // Check for faulted bypass_auto sensors and remove them from monitoring - if ((alarm_sensor.info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (alarm_sensor.sensor->state)) { - ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", alarm_sensor.sensor->get_name().c_str()); - this->bypassed_sensor_indicies_.push_back(alarm_sensor.info.store_index); + if ((info.flags & BINARY_SENSOR_MODE_BYPASS_AUTO) && (sensor->state)) { + ESP_LOGW(TAG, "'%s' is faulted and will be automatically bypassed", sensor->get_name().c_str()); + info.auto_bypassed = true; } } #endif } +void TemplateAlarmControlPanel::clear_auto_bypassed_sensors_() { +#ifdef USE_BINARY_SENSOR + for (auto &alarm_sensor : this->sensors_) { + alarm_sensor.info.auto_bypassed = false; + } +#endif +} + void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) { auto opt_state = call.get_state(); if (opt_state) { @@ -273,9 +280,7 @@ void TemplateAlarmControlPanel::control(const AlarmControlPanelCall &call) { } this->desired_state_ = ACP_STATE_DISARMED; this->publish_state(ACP_STATE_DISARMED); -#ifdef USE_BINARY_SENSOR - this->bypassed_sensor_indicies_.clear(); -#endif + this->clear_auto_bypassed_sensors_(); } else if (state == ACP_STATE_TRIGGERED) { this->publish_state(ACP_STATE_TRIGGERED); } else if (state == ACP_STATE_PENDING) { diff --git a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h index 4f32e99fd7..57a99f2830 100644 --- a/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h +++ b/esphome/components/template/alarm_control_panel/template_alarm_control_panel.h @@ -18,7 +18,7 @@ namespace esphome::template_ { #ifdef USE_BINARY_SENSOR -enum BinarySensorFlags : uint16_t { +enum BinarySensorFlags : uint8_t { BINARY_SENSOR_MODE_NORMAL = 1 << 0, BINARY_SENSOR_MODE_BYPASS_ARMED_HOME = 1 << 1, BINARY_SENSOR_MODE_BYPASS_ARMED_NIGHT = 1 << 2, @@ -41,14 +41,11 @@ enum TemplateAlarmControlPanelRestoreMode { }; #ifdef USE_BINARY_SENSOR -struct SensorDataStore { - bool last_chime_state; -}; - struct SensorInfo { - uint16_t flags; + uint8_t flags; AlarmSensorType type; - uint8_t store_index; + bool chime_active; + bool auto_bypassed; }; struct AlarmSensor { @@ -68,7 +65,9 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl bool get_requires_code_to_arm() const override { return this->requires_code_to_arm_; } bool get_all_sensors_ready() { return this->sensors_ready_; }; void set_restore_mode(TemplateAlarmControlPanelRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } - void bypass_before_arming(); + // Remove before 2026.10.0 + ESPDEPRECATED("bypass_before_arming() is deprecated and will be removed in 2026.10.0", "2026.4.0") + void bypass_before_arming() { this->auto_bypass_sensors_(); } #ifdef USE_BINARY_SENSOR /** Initialize the sensors vector with the specified capacity. @@ -83,7 +82,7 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl * @param flags The OR of BinarySensorFlags for the sensor. * @param type The sensor type which determines its triggering behaviour. */ - void add_sensor(binary_sensor::BinarySensor *sensor, uint16_t flags = 0, + void add_sensor(binary_sensor::BinarySensor *sensor, uint8_t flags = 0, AlarmSensorType type = ALARM_SENSOR_TYPE_DELAYED); #endif @@ -141,11 +140,6 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl #ifdef USE_BINARY_SENSOR // List of binary sensors with their alarm-specific info FixedVector<AlarmSensor> sensors_; - // a list of automatically bypassed sensors - std::vector<uint8_t> bypassed_sensor_indicies_; - // Per sensor data store - std::vector<SensorDataStore> sensor_data_; - uint8_t next_store_index_ = 0; #endif TemplateAlarmControlPanelRestoreMode restore_mode_{}; @@ -170,6 +164,8 @@ class TemplateAlarmControlPanel final : public alarm_control_panel::AlarmControl bool is_code_valid_(optional<std::string> code); void arm_(optional<std::string> code, alarm_control_panel::AlarmControlPanelState state, uint32_t delay); + void auto_bypass_sensors_(); + void clear_auto_bypassed_sensors_(); }; } // namespace esphome::template_ From 02ada93ea5aeb5cee2eb79dff8853269331981ec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 18:40:33 -1000 Subject: [PATCH 1559/2030] [wifi] Reject WiFi config on RP2040/RP2350 boards without CYW43 chip (#14990) --- esphome/components/rp2040/__init__.py | 18 ++++++++ esphome/components/rp2040/boards.py | 10 +++++ esphome/components/rp2040/generate_boards.py | 8 +++- esphome/components/wifi/__init__.py | 8 ++++ .../components/test_rp2040_generate_boards.py | 45 +++++++++++++++++-- 5 files changed, 84 insertions(+), 5 deletions(-) diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 71e5f1488c..0bb1811069 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -24,6 +24,7 @@ from esphome.const import ( from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority from esphome.helpers import copy_file_if_changed, read_file, write_file_if_changed +from . import boards from .const import KEY_BOARD, KEY_PIO_FILES, KEY_RP2040, rp2040_ns # force import gpio to register pin schema @@ -35,6 +36,23 @@ AUTO_LOAD = ["preferences"] IS_TARGET_PLATFORM = True +def get_board() -> str: + """Return the configured board name.""" + return CORE.data[KEY_RP2040][KEY_BOARD] + + +def board_has_wifi() -> bool: + """Return True if the configured board has WiFi (CYW43 wireless chip). + + Returns True for unknown/custom boards to avoid rejecting valid + configurations for boards not in the generated list. + """ + board_info = boards.BOARDS.get(get_board()) + if board_info is None: + return True + return board_info.get("wifi", False) + + def set_core_data(config): CORE.data[KEY_RP2040] = {} CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_RP2040 diff --git a/esphome/components/rp2040/boards.py b/esphome/components/rp2040/boards.py index c99934567a..aac12eae5a 100644 --- a/esphome/components/rp2040/boards.py +++ b/esphome/components/rp2040/boards.py @@ -1910,6 +1910,7 @@ BOARDS = { "name": "Pimoroni PicoPlus2W", "mcu": "rp2350", "max_pin": 47, + "wifi": True, "max_virtual_pin": 64, }, "pimoroni_plasma2040": { @@ -1926,6 +1927,7 @@ BOARDS = { "name": "Pimoroni Plasma2350W", "mcu": "rp2350", "max_pin": 47, + "wifi": True, }, "pimoroni_servo2040": { "name": "Pimoroni Servo2040", @@ -1976,12 +1978,14 @@ BOARDS = { "name": "Raspberry Pi Pico 2W", "mcu": "rp2350", "max_pin": 47, + "wifi": True, "max_virtual_pin": 64, }, "rpipicow": { "name": "Raspberry Pi Pico W", "mcu": "rp2040", "max_pin": 29, + "wifi": True, "max_virtual_pin": 64, }, "sea_picro": { @@ -2013,6 +2017,7 @@ BOARDS = { "name": "Soldered Electronics NULA RP2350", "mcu": "rp2350", "max_pin": 47, + "wifi": True, }, "solderparty_rp2040_stamp": { "name": "Solder Party RP2040 Stamp", @@ -2038,6 +2043,7 @@ BOARDS = { "name": "SparkFun IoT RedBoard RP2350", "mcu": "rp2350", "max_pin": 47, + "wifi": True, }, "sparkfun_micromodrp2040": { "name": "SparkFun MicroMod RP2040", @@ -2063,18 +2069,21 @@ BOARDS = { "name": "SparkFun Thing Plus RP2350", "mcu": "rp2350", "max_pin": 47, + "wifi": True, "max_virtual_pin": 64, }, "sparkfun_xrp_controller": { "name": "SparkFun XRP Controller", "mcu": "rp2350", "max_pin": 47, + "wifi": True, "max_virtual_pin": 64, }, "sparkfun_xrp_controller_beta": { "name": "SparkFun XRP Controller (Beta)", "mcu": "rp2040", "max_pin": 29, + "wifi": True, "max_virtual_pin": 64, }, "upesy_rp2040_devkit": { @@ -2161,6 +2170,7 @@ BOARDS = { "name": "Waveshare RP2350B Plus W", "mcu": "rp2350", "max_pin": 47, + "wifi": True, }, "wiznet_5100s_evb_pico": { "name": "WIZnet W5100S-EVB-Pico", diff --git a/esphome/components/rp2040/generate_boards.py b/esphome/components/rp2040/generate_boards.py index 7ea02d185e..8af261396c 100644 --- a/esphome/components/rp2040/generate_boards.py +++ b/esphome/components/rp2040/generate_boards.py @@ -78,11 +78,17 @@ def load_boards(arduino_pico_path: Path) -> tuple[dict, dict]: display_name = f"{vendor} {name}".strip() if vendor else name - boards[board_name] = { + extra_flags = build.get("extra_flags", "") + has_wifi = "PICO_CYW43_SUPPORTED=1" in extra_flags + + board_entry: dict = { "name": display_name, "mcu": mcu, "max_pin": MCU_MAX_PIN.get(mcu, DEFAULT_MAX_PIN), } + if has_wifi: + board_entry["wifi"] = True + boards[board_name] = board_entry # Get pins for this variant if variant not in variant_pins_cache: diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 9f73b1cc6f..33557f03c7 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -235,6 +235,14 @@ def validate_variant(_): variant = get_esp32_variant() if variant in NO_WIFI_VARIANTS and "esp32_hosted" not in fv.full_config.get(): raise cv.Invalid(f"WiFi requires component esp32_hosted on {variant}") + if CORE.is_rp2040: + from esphome.components.rp2040 import board_has_wifi, get_board + + if not board_has_wifi(): + raise cv.Invalid( + f"Board '{get_board()}' does not have WiFi support (no CYW43 wireless chip). " + f"Use a WiFi-capable board like 'rpipicow' or 'rpipico2w'." + ) def _apply_min_auth_mode_default(config): diff --git a/tests/unit_tests/components/test_rp2040_generate_boards.py b/tests/unit_tests/components/test_rp2040_generate_boards.py index 2e40ed08ba..551e88f6f6 100644 --- a/tests/unit_tests/components/test_rp2040_generate_boards.py +++ b/tests/unit_tests/components/test_rp2040_generate_boards.py @@ -59,6 +59,7 @@ def _add_board( vendor: str = "", name: str | None = None, pins_header: str | None = None, + extra_flags: str = "", ) -> None: """Add a board JSON and variant to the fake arduino-pico tree.""" if variant is None: @@ -69,11 +70,15 @@ def _add_board( json_dir = arduino_pico / "tools" / "json" variants_dir = arduino_pico / "variants" + build: dict = { + "mcu": mcu, + "variant": variant, + } + if extra_flags: + build["extra_flags"] = extra_flags + board_json = { - "build": { - "mcu": mcu, - "variant": variant, - }, + "build": build, "name": name, "vendor": vendor, } @@ -271,3 +276,35 @@ def test_placeholder_pins_not_treated_as_virtual(arduino_pico: Path) -> None: assert "MISO" not in board_pins["badpin"] assert boards["badpin"]["max_virtual_pin"] == 64 + + +def test_cyw43_supported_flag_sets_wifi(arduino_pico: Path) -> None: + """Boards with PICO_CYW43_SUPPORTED=1 in extra_flags should have wifi=True.""" + _add_board( + arduino_pico, + "rpipicow", + vendor="Raspberry Pi", + name="Pico W", + pins_header=PICOW_PINS_HEADER, + extra_flags="-DARDUINO_RASPBERRY_PI_PICO_W -DPICO_CYW43_SUPPORTED=1 -DCYW43_PIN_WL_DYNAMIC=1", + ) + + _, boards = load_boards(arduino_pico) + + assert boards["rpipicow"]["wifi"] is True + + +def test_board_without_cyw43_has_no_wifi(arduino_pico: Path) -> None: + """Boards without PICO_CYW43_SUPPORTED should not have wifi field.""" + _add_board( + arduino_pico, + "rpipico", + vendor="Raspberry Pi", + name="Pico", + pins_header=PICO_PINS_HEADER, + extra_flags="-DARDUINO_RASPBERRY_PI_PICO", + ) + + _, boards = load_boards(arduino_pico) + + assert "wifi" not in boards["rpipico"] From d59c006ff9067c8f7b6a439548f5ee0ef0c85e43 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 20:56:51 -1000 Subject: [PATCH 1560/2030] [uart] Fix UART0 default pin IOMUX loopback on ESP32 (#14978) --- .../uart/uart_component_esp_idf.cpp | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 47ddf1a38d..8168e49805 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -7,7 +7,9 @@ #include "esphome/core/log.h" #include "esphome/core/gpio.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" #include "soc/gpio_num.h" +#include "soc/uart_pins.h" #ifdef USE_UART_WAKE_LOOP_ON_RX #include "esphome/core/application.h" @@ -21,6 +23,20 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; +/// Check if a pin number matches one of the default UART0 GPIO pins. +/// These pins may have residual IOMUX state from the ROM bootloader that +/// must be cleared before UART reconfiguration. +/// +/// ESP-IDF's uart_set_pin() has an asymmetry: when routing TX via GPIO matrix, +/// it calls gpio_func_sel(PIN_FUNC_GPIO) to clear IOMUX, but for RX it only +/// calls gpio_input_enable() which does NOT clear the IOMUX function select. +/// If a default UART0 TX pin (configured as TX via IOMUX during boot) is later +/// reassigned as RX via GPIO matrix, the old IOMUX TX function remains active, +/// causing TX data to loop back into RX on the same pin. +static constexpr bool is_default_uart0_pin(int8_t pin_num) { + return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; +} + uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -131,6 +147,19 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; + int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; + int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; + + // Clear residual IOMUX function on UART0 default pins left by the ROM bootloader. + // See is_default_uart0_pin() comment for details on the ESP-IDF uart_set_pin() bug. + if (is_default_uart0_pin(tx)) { + gpio_func_sel(static_cast<gpio_num_t>(tx), PIN_FUNC_GPIO); + } + if (is_default_uart0_pin(rx)) { + gpio_func_sel(static_cast<gpio_num_t>(rx), PIN_FUNC_GPIO); + } + auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; @@ -146,10 +175,6 @@ void IDFUARTComponent::load_settings(bool dump_config) { setup_pin_if_needed(this->tx_pin_); } - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; - uint32_t invert = 0; if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) { invert |= UART_SIGNAL_TXD_INV; From 12b3aec5672312332c77eaf184f64b2ec32e74a5 Mon Sep 17 00:00:00 2001 From: Keith Roehrenbeck <kroehre@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:11:57 -0500 Subject: [PATCH 1561/2030] [ld2450] Fix zone target counts including untracked ghost targets (#15026) --- esphome/components/ld2450/ld2450.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 0a1147c924..6230a8c30b 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -530,10 +530,11 @@ void LD2450Component::handle_periodic_data_() { } #endif - // Store target info for zone target count - this->target_info_[index].x = tx; - this->target_info_[index].y = ty; - this->target_info_[index].is_moving = is_moving; + // Store target info for zone target count. Zero out untracked targets (td==0) + // so stale coordinates don't produce ghost counts in count_targets_in_zone_(). + this->target_info_[index].x = (td > 0) ? tx : 0; + this->target_info_[index].y = (td > 0) ? ty : 0; + this->target_info_[index].is_moving = (td > 0) && is_moving; } // End loop thru targets From 5a9977cf5c1ff918f6c20e2281301f82ed253ecd Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Fri, 20 Mar 2026 21:35:41 +0100 Subject: [PATCH 1562/2030] [lvgl] Fix arc indicator widget not registered in widget_map (#14986) --- esphome/components/lvgl/widgets/meter.py | 2 +- tests/components/lvgl/lvgl-package.yaml | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index d45371b3a7..63cc645f22 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -406,7 +406,7 @@ class MeterType(WidgetType): lv.scale_section_set_style( tvar, LV_PART.MAIN, await arc_style.get_var() ) - lw = Widget(tvar, arc_indicator_type) + lw = Widget.create(iid, tvar, arc_indicator_type) await set_indicator_values(lw, v) if t == CONF_TICK_STYLE: diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 7d96b12a01..606f57d6a1 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -37,7 +37,11 @@ lvgl: on_resume: logger.log: LVGL has resumed on_boot: - logger.log: LVGL has started + - logger.log: LVGL has started + - lvgl.indicator.update: + id: meter_arc_indicator + start_value: 0 + end_value: 180 bg_color: light_blue disp_bg_color: color_id disp_bg_image: cat_image @@ -1110,6 +1114,12 @@ lvgl: color: 0xA0A0A0 length: 80% opa: 0% + - arc: + id: meter_arc_indicator + color: 0xFF0000 + width: 6 + start_value: 0 + end_value: 360 - id: page3 layout: Horizontal pad_all: 6px From 7257bed1e95ddc4bde5a9c61d83a93b57c88566a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:41:20 -1000 Subject: [PATCH 1563/2030] Bump CodSpeedHQ/action from 4.11.1 to 4.12.1 (#15024) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ead87ad087..965e23870d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -339,7 +339,7 @@ jobs: echo "binary=$BINARY" >> $GITHUB_OUTPUT - name: Run CodSpeed benchmarks - uses: CodSpeedHQ/action@281164b0f014a4e7badd2c02cecad9b595b70537 # v4 + uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4 with: run: ${{ steps.build.outputs.binary }} mode: simulation From a3fd1d5d00714968e630ec692893752b3d16e2e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:41:45 -1000 Subject: [PATCH 1564/2030] Bump github/codeql-action from 4.33.0 to 4.34.1 (#15023) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2ef1a5af31..6baab70b42 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@b1bff81932f5cdfc8695c7752dcee935dcd061c8 # v4.33.0 + uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 with: category: "/language:${{matrix.language}}" From 9e7cdaf4758ff997cf5f385946aab97c992213f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:10:40 -1000 Subject: [PATCH 1565/2030] Bump aioesphomeapi from 44.6.1 to 44.6.2 (#15027) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9e2f4efe3e..10e56c3b49 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.6.1 +aioesphomeapi==44.6.2 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 896b6ec8c9acd581a2d95d66ea00b9d617ad36ed Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 12:06:23 -1000 Subject: [PATCH 1566/2030] [api] Increase noise handshake timeout to 60s for slow WiFi environments (#15022) --- esphome/components/api/api_connection.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index d55b5dffb6..40c27b224b 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -64,7 +64,11 @@ static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * // A stalled handshake from a buggy client or network glitch holds a connection // slot, which can prevent legitimate clients from reconnecting. Also hardens // against the less likely case of intentional connection slot exhaustion. -static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 15000; +// +// 60s is intentionally high: on ESP8266 with power_save_mode: LIGHT and weak +// WiFi (-70 dBm+), TCP retransmissions push real-world handshake times to +// 28-30s. See https://github.com/esphome/esphome/issues/14999 +static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 60000; static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION); From 5e516e78e43e7b9b61fb334f5832ac671ec20b74 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 12:13:49 -1000 Subject: [PATCH 1567/2030] [wifi] Fix ESP8266 power_save_mode mapping (LIGHT/HIGH were swapped) (#15029) --- esphome/components/wifi/wifi_component_esp8266.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 0bf7934878..5514f1c6be 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -92,13 +92,23 @@ bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) { return ret; } bool WiFiComponent::wifi_apply_power_save_() { + // ESP8266 sleep types have confusing names — LIGHT_SLEEP_T is the MORE aggressive mode. + // SDK enum: NONE_SLEEP_T=0, LIGHT_SLEEP_T=1, MODEM_SLEEP_T=2 + // https://github.com/esp8266/Arduino/blob/3.1.2/tools/sdk/include/user_interface.h#L447-L451 + // Arduino ESP32 compat confirms: WIFI_PS_MIN_MODEM=MODEM_SLEEP, WIFI_PS_MAX_MODEM=LIGHT_SLEEP + // https://github.com/esp8266/Arduino/blob/3.1.2/libraries/ESP8266WiFi/src/ESP8266WiFiType.h#L53-L55 sleep_type_t power_save; switch (this->power_save_) { case WIFI_POWER_SAVE_LIGHT: - power_save = LIGHT_SLEEP_T; + // MODEM_SLEEP_T: only the WiFi modem sleeps between DTIM beacons, CPU stays active. + // Matches ESP32's WIFI_PS_MIN_MODEM. + power_save = MODEM_SLEEP_T; break; case WIFI_POWER_SAVE_HIGH: - power_save = MODEM_SLEEP_T; + // LIGHT_SLEEP_T: both WiFi modem AND CPU suspend between DTIM beacons. + // Most aggressive — prevents TCP processing during sleep. Matches ESP32's WIFI_PS_MAX_MODEM. + // See https://github.com/esphome/esphome/issues/14999 + power_save = LIGHT_SLEEP_T; break; case WIFI_POWER_SAVE_NONE: default: From ed8c062d9fc688e97758e702fb743d966334db5b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:53:02 -0400 Subject: [PATCH 1568/2030] [esp32_touch] Fix initial state never published when sensor untouched (#15032) --- esphome/components/esp32_touch/esp32_touch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index e7124ce92f..0d331b29d6 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -360,11 +360,16 @@ void ESP32TouchComponent::loop() { } // Publish initial OFF state for sensors that haven't received events yet + bool all_initial_published = true; for (auto *child : this->children_) { this->publish_initial_state_if_needed_(child, now); + if (!child->initial_state_published_) { + all_initial_published = false; + } } - if (!this->setup_mode_) { + // Only disable loop once all initial states are published + if (!this->setup_mode_ && all_initial_published) { this->disable_loop(); } } From 0b01f9fc42aa7e848dfbab78500d8ba97778dc29 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:57:51 -1000 Subject: [PATCH 1569/2030] [web_server] Increase httpd task stack size to prevent stack overflow (#14997) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/web_server_idf/web_server_idf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 60816fc6dd..fb0c17c854 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -121,7 +121,10 @@ void AsyncWebServer::begin() { if (this->server_) { this->end(); } + // Default httpd stack is defined by ESP-IDF. Increase to accommodate SerializationBuffer's + // 640-byte stack buffer used by web_server JSON request handlers. httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.stack_size = config.stack_size + 256; config.server_port = this->port_; config.uri_match_fn = [](const char * /*unused*/, const char * /*unused*/, size_t /*unused*/) { return true; }; // Always enable LRU purging to handle socket exhaustion gracefully. From 8fa2e75afaacb55d6b8aaa3ca49f746789ab8b83 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:58:02 -1000 Subject: [PATCH 1570/2030] [core] Add copy() method to StringRef for std::string compatibility (#15028) --- esphome/core/string_ref.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index 6047202753..34ba2474b2 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -76,6 +76,15 @@ class StringRef { constexpr bool empty() const { return len_ == 0; } constexpr const_reference operator[](size_type pos) const { return *(base_ + pos); } + /// Copy characters to destination buffer (std::string::copy-like, but returns 0 instead of throwing on out-of-range) + size_type copy(char *dest, size_type count, size_type pos = 0) const { + if (pos >= len_) + return 0; + size_type actual = (count > len_ - pos) ? len_ - pos : count; + std::memcpy(dest, base_ + pos, actual); + return actual; + } + std::string str() const { return std::string(base_, len_); } const uint8_t *byte() const { return reinterpret_cast<const uint8_t *>(base_); } From a9a8f4cb3bf9f304abcd872995dc91aa988859ac Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:58:14 -1000 Subject: [PATCH 1571/2030] [time] Fix timezone_offset() and recalc_timestamp_local() always returning UTC (#14996) --- esphome/core/time.cpp | 16 ++++++---------- esphome/core/time.h | 2 ++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 73ba0a9be7..6add82e7d1 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -283,19 +283,15 @@ void ESPTime::recalc_timestamp_local() { bool dst_valid = time::is_in_dst(utc_if_dst, tz); bool std_valid = !time::is_in_dst(utc_if_std, tz); - if (dst_valid && std_valid) { - // Ambiguous time (repeated hour during fall-back) - prefer standard time - this->timestamp = utc_if_std; - } else if (dst_valid) { + if (dst_valid && !std_valid) { // Only DST interpretation is valid this->timestamp = utc_if_dst; - } else if (std_valid) { - // Only standard interpretation is valid - this->timestamp = utc_if_std; } else { - // Invalid time (skipped hour during spring-forward) - // libc normalizes forward: 02:30 CST -> 08:30 UTC -> 03:30 CDT - // Using std offset achieves this since the UTC result falls during DST + // All other cases use standard offset: + // - Both valid (ambiguous fall-back repeated hour): prefer standard time + // - Only standard valid: straightforward + // - Neither valid (spring-forward skipped hour): std offset normalizes + // forward to match libc mktime(), e.g. 02:30 CST -> 03:30 CDT this->timestamp = utc_if_std; } #else diff --git a/esphome/core/time.h b/esphome/core/time.h index 874f0db4b4..1716c51ffd 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -1,5 +1,7 @@ #pragma once +#include "esphome/core/defines.h" + #include <cstdint> #include <cstdlib> #include <cstring> From 2d39cc2540e877f7bec755b74c2cdf60e625c6b0 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:38:04 -0400 Subject: [PATCH 1572/2030] [spa06_i2c] Add SPA06-003 Temperature and Pressure Sensor - I2C support (Part 2 of 3) (#14522) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/spa06_i2c/__init__.py | 0 esphome/components/spa06_i2c/sensor.py | 23 +++++++++++++++++++ esphome/components/spa06_i2c/spa06_i2c.cpp | 14 +++++++++++ esphome/components/spa06_i2c/spa06_i2c.h | 20 ++++++++++++++++ tests/components/spa06_i2c/common.yaml | 15 ++++++++++++ .../components/spa06_i2c/test.esp32-idf.yaml | 4 ++++ .../spa06_i2c/test.esp8266-ard.yaml | 4 ++++ .../components/spa06_i2c/test.rp2040-ard.yaml | 4 ++++ 9 files changed, 85 insertions(+) create mode 100644 esphome/components/spa06_i2c/__init__.py create mode 100644 esphome/components/spa06_i2c/sensor.py create mode 100644 esphome/components/spa06_i2c/spa06_i2c.cpp create mode 100644 esphome/components/spa06_i2c/spa06_i2c.h create mode 100644 tests/components/spa06_i2c/common.yaml create mode 100644 tests/components/spa06_i2c/test.esp32-idf.yaml create mode 100644 tests/components/spa06_i2c/test.esp8266-ard.yaml create mode 100644 tests/components/spa06_i2c/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 5869925d7c..e3e09cbc11 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -458,6 +458,7 @@ esphome/components/socket/* @esphome/core esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/sound_level/* @kahrendt esphome/components/spa06_base/* @danielkent-net +esphome/components/spa06_i2c/* @danielkent-net esphome/components/speaker/* @jesserockz @kahrendt esphome/components/speaker/media_player/* @kahrendt @synesthesiam esphome/components/speaker_source/* @kahrendt diff --git a/esphome/components/spa06_i2c/__init__.py b/esphome/components/spa06_i2c/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/spa06_i2c/sensor.py b/esphome/components/spa06_i2c/sensor.py new file mode 100644 index 0000000000..b48a5bca50 --- /dev/null +++ b/esphome/components/spa06_i2c/sensor.py @@ -0,0 +1,23 @@ +import esphome.codegen as cg +from esphome.components import i2c +import esphome.config_validation as cv + +from ..spa06_base import CONFIG_SCHEMA_BASE, to_code_base + +AUTO_LOAD = ["spa06_base"] +CODEOWNERS = ["@danielkent-net"] +DEPENDENCIES = ["i2c"] + +spa06_ns = cg.esphome_ns.namespace("spa06_i2c") +SPA06I2CComponent = spa06_ns.class_( + "SPA06I2CComponent", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend( + i2c.i2c_device_schema(default_address=0x77) +).extend({cv.GenerateID(): cv.declare_id(SPA06I2CComponent)}) + + +async def to_code(config): + var = await to_code_base(config) + await i2c.register_i2c_device(var, config) diff --git a/esphome/components/spa06_i2c/spa06_i2c.cpp b/esphome/components/spa06_i2c/spa06_i2c.cpp new file mode 100644 index 0000000000..4970b0822d --- /dev/null +++ b/esphome/components/spa06_i2c/spa06_i2c.cpp @@ -0,0 +1,14 @@ +#include "spa06_i2c.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome::spa06_i2c { + +static const char *const TAG = "spa06_i2c"; + +void SPA06I2CComponent::dump_config() { + LOG_I2C_DEVICE(this); + SPA06Component::dump_config(); +} + +} // namespace esphome::spa06_i2c diff --git a/esphome/components/spa06_i2c/spa06_i2c.h b/esphome/components/spa06_i2c/spa06_i2c.h new file mode 100644 index 0000000000..6b4bce3a4e --- /dev/null +++ b/esphome/components/spa06_i2c/spa06_i2c.h @@ -0,0 +1,20 @@ +#pragma once +#include "esphome/components/spa06_base/spa06_base.h" +#include "esphome/components/i2c/i2c.h" + +namespace esphome::spa06_i2c { + +class SPA06I2CComponent : public spa06_base::SPA06Component, public i2c::I2CDevice { + public: + bool spa_read_byte(uint8_t a_register, uint8_t *data) override { return read_byte(a_register, data); } + bool spa_write_byte(uint8_t a_register, uint8_t data) override { return write_byte(a_register, data); } + bool spa_read_bytes(uint8_t a_register, uint8_t *data, size_t len) override { + return read_bytes(a_register, data, len); + } + bool spa_write_bytes(uint8_t a_register, uint8_t *data, size_t len) override { + return write_bytes(a_register, data, len); + } + void dump_config() override; +}; + +} // namespace esphome::spa06_i2c diff --git a/tests/components/spa06_i2c/common.yaml b/tests/components/spa06_i2c/common.yaml new file mode 100644 index 0000000000..d2be0e3ac9 --- /dev/null +++ b/tests/components/spa06_i2c/common.yaml @@ -0,0 +1,15 @@ +sensor: + - platform: spa06_i2c + i2c_id: i2c_bus + address: 0x77 + temperature: + id: spa06_i2c_temperature + name: Outside Temperature + sample_rate: 1 + oversampling: NONE + pressure: + name: Outside Pressure + id: spa06_i2c_pressure + sample_rate: 25p4 + oversampling: 16X + update_interval: 15s diff --git a/tests/components/spa06_i2c/test.esp32-idf.yaml b/tests/components/spa06_i2c/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/spa06_i2c/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/spa06_i2c/test.esp8266-ard.yaml b/tests/components/spa06_i2c/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/spa06_i2c/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/spa06_i2c/test.rp2040-ard.yaml b/tests/components/spa06_i2c/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/spa06_i2c/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml From 12ead0408ab97d21f2d01fc691db2baed7a99d9f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:00:56 -1000 Subject: [PATCH 1573/2030] [gpio] Use constexpr uint32_t timer ID for interlock timeout (#15010) --- esphome/components/gpio/switch/gpio_switch.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/gpio/switch/gpio_switch.cpp b/esphome/components/gpio/switch/gpio_switch.cpp index 9043a6a493..d461fab051 100644 --- a/esphome/components/gpio/switch/gpio_switch.cpp +++ b/esphome/components/gpio/switch/gpio_switch.cpp @@ -5,6 +5,7 @@ namespace esphome { namespace gpio { static const char *const TAG = "switch.gpio"; +static constexpr uint32_t INTERLOCK_TIMEOUT_ID = 0; float GPIOSwitch::get_setup_priority() const { return setup_priority::HARDWARE; } void GPIOSwitch::setup() { @@ -51,7 +52,7 @@ void GPIOSwitch::write_state(bool state) { } } if (found && this->interlock_wait_time_ != 0) { - this->set_timeout("interlock", this->interlock_wait_time_, [this, state] { + this->set_timeout(INTERLOCK_TIMEOUT_ID, this->interlock_wait_time_, [this, state] { // Don't write directly, call the function again // (some other switch may have changed state while we were waiting) this->write_state(state); @@ -61,7 +62,7 @@ void GPIOSwitch::write_state(bool state) { } else if (this->interlock_wait_time_ != 0) { // If we are switched off during the interlock wait time, cancel any pending // re-activations - this->cancel_timeout("interlock"); + this->cancel_timeout(INTERLOCK_TIMEOUT_ID); } this->pin_->digital_write(state); From 391ffe34f87158a0b308634018be3a03ac33814a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:01:11 -1000 Subject: [PATCH 1574/2030] [rp2040] Fix get_mac_address_raw to use ethernet MAC when WiFi unavailable (#15033) --- esphome/components/rp2040/helpers.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/rp2040/helpers.cpp b/esphome/components/rp2040/helpers.cpp index ad69192af9..e360b45ebb 100644 --- a/esphome/components/rp2040/helpers.cpp +++ b/esphome/components/rp2040/helpers.cpp @@ -10,6 +10,7 @@ #include <pico/cyw43_arch.h> // For cyw43_arch_lwip_begin/end (LwIPLock) #elif defined(USE_ETHERNET) #include <LwipEthernet.h> // For ethernet_arch_lwip_begin/end (LwIPLock) +#include "esphome/components/ethernet/ethernet_component.h" #endif #include <hardware/structs/rosc.h> #include <hardware/sync.h> @@ -71,6 +72,8 @@ LwIPLock::~LwIPLock() {} void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) #ifdef USE_WIFI WiFi.macAddress(mac); +#elif defined(USE_ETHERNET) + ethernet::global_eth_component->get_eth_mac_address_raw(mac); #endif } From 51335e88301d8ae4f6872cb8546c799ef300f964 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:01:30 -1000 Subject: [PATCH 1575/2030] [ledc] Fix deprecated intr_type warning on ESP-IDF 6.0+ (#15009) --- esphome/components/ledc/ledc_output.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ledc/ledc_output.cpp b/esphome/components/ledc/ledc_output.cpp index d2f2d72acb..5b7b6c7ee6 100644 --- a/esphome/components/ledc/ledc_output.cpp +++ b/esphome/components/ledc/ledc_output.cpp @@ -193,7 +193,9 @@ void LEDCOutput::setup() { chan_conf.gpio_num = static_cast<gpio_num_t>(this->pin_->get_pin()); chan_conf.speed_mode = speed_mode; chan_conf.channel = chan_num; +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(6, 0, 0) chan_conf.intr_type = LEDC_INTR_DISABLE; +#endif chan_conf.timer_sel = timer_num; chan_conf.duty = this->inverted_ == this->pin_->is_inverted() ? 0 : (1U << this->bit_depth_); chan_conf.hpoint = hpoint; From edf5542559a4868c57df319ad89e4a7ebe829658 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:05:17 -1000 Subject: [PATCH 1576/2030] [analyze-memory] Attribute extern C symbols to components via source file mapping (#15006) --- esphome/analyze_memory/__init__.py | 125 +++++++++++++++++++++++++++++ esphome/analyze_memory/const.py | 1 - 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index 7954c22822..48ecf2c1dc 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -201,6 +201,9 @@ class MemoryAnalyzer: self._cswtch_symbols: list[tuple[str, int, str, str]] = [] # Library symbol mapping: symbol_name -> library_name self._lib_symbol_map: dict[str, str] = {} + # Source file symbol mapping: symbol_name -> component_name + # Used for extern "C" and other symbols without C++ namespace + self._source_symbol_map: dict[str, str] = {} # Library dir to name mapping: "lib641" -> "espsoftwareserial", # "espressif__mdns" -> "mdns" self._lib_hash_to_name: dict[str, str] = {} @@ -214,6 +217,7 @@ class MemoryAnalyzer: self._parse_sections() self._parse_symbols() self._scan_libraries() + self._scan_source_symbols() self._categorize_symbols() self._analyze_cswtch_symbols() self._analyze_sdk_libraries() @@ -363,6 +367,11 @@ class MemoryAnalyzer: if lib_name := self._lib_symbol_map.get(symbol_name): return f"{_COMPONENT_PREFIX_LIB}{lib_name}" + # Check source file mapping (catches extern "C" functions in ESPHome sources) + # Must be before heuristic patterns since source attribution is authoritative + if component := self._source_symbol_map.get(symbol_name): + return component + # Check against symbol patterns for component, patterns in SYMBOL_PATTERNS.items(): if any(pattern in symbol_name for pattern in patterns): @@ -653,6 +662,7 @@ class MemoryAnalyzer: return None symbol_map: dict[str, str] = {} + source_symbol_map: dict[str, str] = {} current_symbol: str | None = None section_prefixes = (".text.", ".rodata.", ".data.", ".bss.", ".literal.") @@ -688,9 +698,18 @@ class MemoryAnalyzer: if dir_key in source_path: symbol_map[current_symbol] = lib_name break + else: + # Map ESPHome source files to components for extern "C" + # and other symbols without C++ namespace + component = self._source_file_to_component(source_path) + if component.startswith( + (_COMPONENT_PREFIX_ESPHOME, _COMPONENT_PREFIX_EXTERNAL) + ): + source_symbol_map[current_symbol] = component current_symbol = None + self._source_symbol_map = source_symbol_map return symbol_map or None def _scan_libraries(self) -> None: @@ -741,6 +760,112 @@ class MemoryAnalyzer: len(libraries), ) + def _scan_source_symbols(self) -> None: + """Scan ESPHome source object files to map extern "C" symbols to components. + + When no linker map file is available, this uses ``nm`` to scan ``.o`` files + under ``src/esphome/`` and build a symbol-to-component mapping. This catches + ``extern "C"`` functions and other symbols that lack C++ namespace prefixes. + + Skips scanning if ``_source_symbol_map`` was already populated by + ``_parse_map_file()``. + """ + if self._source_symbol_map or not self.nm_path: + return + + obj_dir = self._find_object_files_dir() + if obj_dir is None: + return + + # Find ESPHome source object files + esphome_src_dir = obj_dir / "src" / "esphome" + if not esphome_src_dir.is_dir(): + return + + obj_files = sorted(esphome_src_dir.rglob("*.o")) + if not obj_files: + return + + # Run nm with --print-file-name to get file:symbol mapping + result = run_tool( + [self.nm_path, "--print-file-name", "-g", "--defined-only"] + + [str(f) for f in obj_files], + ) + if result is None or result.returncode != 0: + _LOGGER.debug("nm scan of source objects failed") + return + + self._source_symbol_map = self._parse_nm_source_output(result.stdout, obj_dir) + if self._source_symbol_map: + _LOGGER.info( + "Built source symbol map from nm: %d symbols", + len(self._source_symbol_map), + ) + + def _parse_nm_source_output(self, output: str, base_dir: Path) -> dict[str, str]: + """Parse nm output to map non-namespaced symbols to ESPHome components. + + Extracts global defined symbols from ESPHome source object files that + don't use C++ namespacing (e.g. ``extern "C"`` functions). + + Args: + output: Raw stdout from ``nm --print-file-name -g --defined-only`` + or ``nm --print-file-name -S``. + base_dir: Build directory for computing relative paths. + + Returns: + Dict mapping symbol names to component names. + """ + source_map: dict[str, str] = {} + for line in output.splitlines(): + # Format: /path/to/file.o: addr type name + # or: /path/to/file.o: addr size type name (with -S) + colon_idx = line.rfind(".o:") + if colon_idx == -1: + continue + + file_path = line[: colon_idx + 2] + fields = line[colon_idx + 3 :].split() + if len(fields) < 3: + continue + + # With -S flag, format is: addr size type name + # Without -S flag: addr type name + # type is a single char; size is hex digits + # Detect by checking if fields[1] is a single uppercase letter (type) + if len(fields[1]) == 1 and fields[1].isalpha(): + # addr type name + sym_type = fields[1] + symbol_name = fields[2] + elif len(fields) >= 4: + # addr size type name + sym_type = fields[2] + symbol_name = fields[3] + else: + continue + + # Only global defined symbols (uppercase type) + if not sym_type.isupper() or sym_type == "U": + continue + + # Skip symbols already in esphome:: namespace + if symbol_name.startswith("_ZN7esphome"): + continue + + # Make path relative to base_dir for _source_file_to_component + try: + rel_path = str(Path(file_path).relative_to(base_dir)) + except ValueError: + continue + + component = self._source_file_to_component(rel_path) + if component.startswith( + (_COMPONENT_PREFIX_ESPHOME, _COMPONENT_PREFIX_EXTERNAL) + ): + source_map[symbol_name] = component + + return source_map + def _find_object_files_dir(self) -> Path | None: """Find the directory containing object files for this build. diff --git a/esphome/analyze_memory/const.py b/esphome/analyze_memory/const.py index 3bdf555ae3..0c871d0727 100644 --- a/esphome/analyze_memory/const.py +++ b/esphome/analyze_memory/const.py @@ -408,7 +408,6 @@ SYMBOL_PATTERNS = { ], "arduino_core": [ "pinMode", - "resetPins", "millis", "micros", "delay(", # More specific - Arduino delay function with parenthesis From 564d155cb6980e1b24cbd640cb014128dcb1cc92 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:08:33 -1000 Subject: [PATCH 1577/2030] [wifi] Use LOG_STR_LITERAL for scan complete log on ESP8266 (#15001) --- esphome/components/wifi/wifi_component_esp8266.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 5514f1c6be..f2fabb9080 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -735,7 +735,7 @@ void WiFiComponent::wifi_scan_done_callback_(void *arg, STATUS status) { } } ESP_LOGV(TAG, "Scan complete: %zu found, %zu stored%s", total, this->scan_result_.size(), - needs_full ? "" : " (filtered)"); + needs_full ? LOG_STR_LITERAL("") : LOG_STR_LITERAL(" (filtered)")); this->scan_done_ = true; #ifdef USE_WIFI_SCAN_RESULTS_LISTENERS this->pending_.scan_complete = true; // Defer listener callbacks to main loop From 7f500c4b6ef14967771cec2cb2f8785cc552b891 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:08:46 -1000 Subject: [PATCH 1578/2030] [modbus] Fix size_t format warning in clear_rx_buffer_ (#15002) --- esphome/components/modbus/modbus.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 7a61868e6e..4146a54c87 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -415,10 +415,10 @@ void Modbus::clear_rx_buffer_(const LogString *reason, bool warn) { size_t at = this->rx_buffer_.size(); if (at > 0) { if (warn) { - ESP_LOGW(TAG, "Clearing buffer of %" PRIu32 " bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), + ESP_LOGW(TAG, "Clearing buffer of %zu bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), millis() - this->last_send_); } else { - ESP_LOGV(TAG, "Clearing buffer of %" PRIu32 " bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), + ESP_LOGV(TAG, "Clearing buffer of %zu bytes - %s %" PRIu32 "ms after last send", at, LOG_STR_ARG(reason), millis() - this->last_send_); } this->rx_buffer_.clear(); From 51ccad8461069ac04cd568971b9bf4b1b148e26e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:09:01 -1000 Subject: [PATCH 1579/2030] [preferences] Shorten TAG strings across all platforms (#15004) --- esphome/components/esp32/preferences.cpp | 2 +- esphome/components/esp8266/preferences.cpp | 2 +- esphome/components/host/preferences.cpp | 2 +- esphome/components/libretiny/preferences.cpp | 2 +- esphome/components/rp2040/preferences.cpp | 2 +- esphome/components/zephyr/preferences.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index 7260bf54e0..e88ace3e6b 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -10,7 +10,7 @@ namespace esphome::esp32 { -static const char *const TAG = "esp32.preferences"; +static const char *const TAG = "preferences"; // Buffer size for converting uint32_t to string: max "4294967295" (10 chars) + null terminator + 1 padding static constexpr size_t KEY_BUFFER_SIZE = 12; diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index 0b31c53ff8..906fed2b29 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -13,7 +13,7 @@ extern "C" { namespace esphome::esp8266 { -static const char *const TAG = "esp8266.preferences"; +static const char *const TAG = "preferences"; static constexpr uint32_t ESP_RTC_USER_MEM_START = 0x60001200; static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_WORDS = 128; diff --git a/esphome/components/host/preferences.cpp b/esphome/components/host/preferences.cpp index fce3d62dda..c0be270062 100644 --- a/esphome/components/host/preferences.cpp +++ b/esphome/components/host/preferences.cpp @@ -9,7 +9,7 @@ namespace esphome::host { namespace fs = std::filesystem; -static const char *const TAG = "host.preferences"; +static const char *const TAG = "preferences"; void HostPreferences::setup_() { if (this->setup_complete_) diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index f22c12f1fb..344ca4a8b3 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -9,7 +9,7 @@ namespace esphome::libretiny { -static const char *const TAG = "lt.preferences"; +static const char *const TAG = "preferences"; // Buffer size for converting uint32_t to string: max "4294967295" (10 chars) + null terminator + 1 padding static constexpr size_t KEY_BUFFER_SIZE = 12; diff --git a/esphome/components/rp2040/preferences.cpp b/esphome/components/rp2040/preferences.cpp index 0a91136a9f..cfc802b28f 100644 --- a/esphome/components/rp2040/preferences.cpp +++ b/esphome/components/rp2040/preferences.cpp @@ -14,7 +14,7 @@ namespace esphome::rp2040 { -static const char *const TAG = "rp2040.preferences"; +static const char *const TAG = "preferences"; static constexpr uint32_t RP2040_FLASH_STORAGE_SIZE = 512; diff --git a/esphome/components/zephyr/preferences.cpp b/esphome/components/zephyr/preferences.cpp index df69c0e652..c26a1d6d53 100644 --- a/esphome/components/zephyr/preferences.cpp +++ b/esphome/components/zephyr/preferences.cpp @@ -10,7 +10,7 @@ namespace esphome::zephyr { -static const char *const TAG = "zephyr.preferences"; +static const char *const TAG = "preferences"; bool ZephyrPreferenceBackend::save(const uint8_t *data, size_t len) { this->data.resize(len); From 2c872600464c2b0b168e09277bb5bbe16da4fac0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:09:13 -1000 Subject: [PATCH 1580/2030] [core] Optimize Component::is_ready() with bitmask check (#15005) --- esphome/core/component.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 00dda0cc26..89ac0c7a2a 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -378,9 +378,10 @@ void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std: #pragma GCC diagnostic pop } bool Component::is_ready() const { - return (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP || - (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE || - (this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_SETUP; + // Bitmask check: valid states are SETUP(1), LOOP(2), LOOP_DONE(4) + // (1 << state) & 0b10110 checks membership in one instruction + return ((1u << (this->component_state_ & COMPONENT_STATE_MASK)) & + ((1u << COMPONENT_STATE_SETUP) | (1u << COMPONENT_STATE_LOOP) | (1u << COMPONENT_STATE_LOOP_DONE))) != 0; } bool Component::can_proceed() { return true; } bool Component::set_status_flag_(uint8_t flag) { From 32db055b98cbb964663396b6aa63239cc4f97591 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:09:28 -1000 Subject: [PATCH 1581/2030] [number] Clean up NumberCall::perform() increment/decrement logic (#15000) --- esphome/components/number/number_call.cpp | 22 ++++++---------------- esphome/components/number/number_call.h | 3 +++ 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/esphome/components/number/number_call.cpp b/esphome/components/number/number_call.cpp index 27a857c112..aac9b2a23d 100644 --- a/esphome/components/number/number_call.cpp +++ b/esphome/components/number/number_call.cpp @@ -80,35 +80,25 @@ void NumberCall::perform() { target_value = max_value; } } else if (this->operation_ == NUMBER_OP_INCREMENT) { - ESP_LOGD(TAG, "'%s': Increment with%s cycling", name, this->cycle_ ? "" : "out"); + ESP_LOGD(TAG, "'%s': Increment with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); if (!parent->has_state()) { this->log_perform_warning_(LOG_STR("Can't increment, no state")); return; } auto step = traits.get_step(); target_value = parent->state + (std::isnan(step) ? 1 : step); - if (target_value > max_value) { - if (this->cycle_ && !std::isnan(min_value)) { - target_value = min_value; - } else { - target_value = max_value; - } - } + if (target_value > max_value) + target_value = this->cycle_or_clamp_(max_value, min_value); } else if (this->operation_ == NUMBER_OP_DECREMENT) { - ESP_LOGD(TAG, "'%s': Decrement with%s cycling", name, this->cycle_ ? "" : "out"); + ESP_LOGD(TAG, "'%s': Decrement with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); if (!parent->has_state()) { this->log_perform_warning_(LOG_STR("Can't decrement, no state")); return; } auto step = traits.get_step(); target_value = parent->state - (std::isnan(step) ? 1 : step); - if (target_value < min_value) { - if (this->cycle_ && !std::isnan(max_value)) { - target_value = max_value; - } else { - target_value = min_value; - } - } + if (target_value < min_value) + target_value = this->cycle_or_clamp_(min_value, max_value); } if (target_value < min_value) { diff --git a/esphome/components/number/number_call.h b/esphome/components/number/number_call.h index 584c13f413..29eaeb72d9 100644 --- a/esphome/components/number/number_call.h +++ b/esphome/components/number/number_call.h @@ -33,6 +33,9 @@ class NumberCall { NumberCall &with_cycle(bool cycle); protected: + float cycle_or_clamp_(float clamp, float opposite) const { + return (this->cycle_ && !std::isnan(opposite)) ? opposite : clamp; + } void log_perform_warning_(const LogString *message); void log_perform_warning_value_range_(const LogString *comparison, const LogString *limit_type, float val, float limit); From 21e384cafd89f1a441a7de2c67816338ca90c569 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:10:18 -1000 Subject: [PATCH 1582/2030] [esp32] Disable PicolibC Newlib compatibility shim on IDF 6.0+ (#15008) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/esp32/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 64e5f44081..f85f13fe73 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1920,6 +1920,18 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_MBEDTLS_SHA384_C", False) add_idf_sdkconfig_option("CONFIG_MBEDTLS_SHA512_C", False) + # Disable PicolibC Newlib compatibility shim on IDF 6.0+ + # IDF 6.0 switched from Newlib to PicolibC. The shim provides thread-local + # stdin/stdout/stderr and getreent() for code compiled against Newlib. + # ESPHome doesn't link against Newlib-built libraries that use stdio. + # If a component needs it (e.g. precompiled Newlib binaries), re-enable via: + # esp32: + # framework: + # sdkconfig_options: + # CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY: "y" + if idf_version() >= cv.Version(6, 0, 0): + add_idf_sdkconfig_option("CONFIG_LIBC_PICOLIBC_NEWLIB_COMPATIBILITY", False) + # Disable regi2c control functions in IRAM # Only needed if using analog peripherals (ADC, DAC, etc.) from ISRs while cache is disabled if advanced[CONF_DISABLE_REGI2C_IN_IRAM]: From f3cddcee214fc8c510ecfc88dd3ef277c0d882df Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:25:40 -1000 Subject: [PATCH 1583/2030] [core] Store parent pointers as members to enable inline Callback storage (#14923) --- esphome/components/cover/automation.h | 18 +++--- esphome/components/datetime/datetime_base.h | 7 ++- .../components/display_menu_base/automation.h | 35 ++++++++---- esphome/components/esp32_improv/automation.h | 55 ++++++++++++------- esphome/components/fan/automation.h | 49 ++++++++++------- .../graphical_display_menu.h | 7 ++- esphome/components/lock/automation.h | 9 ++- esphome/components/media_player/automation.h | 9 ++- esphome/components/mqtt/mqtt_fan.cpp | 3 +- esphome/components/valve/automation.h | 18 ++++-- 10 files changed, 134 insertions(+), 76 deletions(-) diff --git a/esphome/components/cover/automation.h b/esphome/components/cover/automation.h index 12ec46725d..f121e5c2d6 100644 --- a/esphome/components/cover/automation.h +++ b/esphome/components/cover/automation.h @@ -105,17 +105,18 @@ template<typename... Ts> using CoverIsClosedCondition = CoverPositionCondition<f template<bool OPEN> class CoverPositionTrigger : public Trigger<> { public: - CoverPositionTrigger(Cover *a_cover) { - a_cover->add_on_state_callback([this, a_cover]() { - if (a_cover->position != this->last_position_) { - this->last_position_ = a_cover->position; - if (a_cover->position == (OPEN ? COVER_OPEN : COVER_CLOSED)) + CoverPositionTrigger(Cover *a_cover) : cover_(a_cover) { + a_cover->add_on_state_callback([this]() { + if (this->cover_->position != this->last_position_) { + this->last_position_ = this->cover_->position; + if (this->cover_->position == (OPEN ? COVER_OPEN : COVER_CLOSED)) this->trigger(); } }); } protected: + Cover *cover_; float last_position_{NAN}; }; @@ -124,9 +125,9 @@ using CoverClosedTrigger = CoverPositionTrigger<false>; template<CoverOperation OP> class CoverTrigger : public Trigger<> { public: - CoverTrigger(Cover *a_cover) { - a_cover->add_on_state_callback([this, a_cover]() { - auto current_op = a_cover->current_operation; + CoverTrigger(Cover *a_cover) : cover_(a_cover) { + a_cover->add_on_state_callback([this]() { + auto current_op = this->cover_->current_operation; if (current_op == OP) { if (!this->last_operation_.has_value() || this->last_operation_.value() != OP) { this->trigger(); @@ -137,6 +138,7 @@ template<CoverOperation OP> class CoverTrigger : public Trigger<> { } protected: + Cover *cover_; optional<CoverOperation> last_operation_{}; }; } // namespace esphome::cover diff --git a/esphome/components/datetime/datetime_base.h b/esphome/components/datetime/datetime_base.h index 98f23aa713..6c0a33c842 100644 --- a/esphome/components/datetime/datetime_base.h +++ b/esphome/components/datetime/datetime_base.h @@ -33,9 +33,12 @@ class DateTimeBase : public EntityBase { class DateTimeStateTrigger : public Trigger<ESPTime> { public: - explicit DateTimeStateTrigger(DateTimeBase *parent) { - parent->add_on_state_callback([this, parent]() { this->trigger(parent->state_as_esptime()); }); + explicit DateTimeStateTrigger(DateTimeBase *parent) : parent_(parent) { + parent->add_on_state_callback([this]() { this->trigger(this->parent_->state_as_esptime()); }); } + + protected: + DateTimeBase *parent_; }; } // namespace esphome::datetime diff --git a/esphome/components/display_menu_base/automation.h b/esphome/components/display_menu_base/automation.h index 9c64794cef..50c26c344c 100644 --- a/esphome/components/display_menu_base/automation.h +++ b/esphome/components/display_menu_base/automation.h @@ -96,37 +96,52 @@ template<typename... Ts> class IsActiveCondition : public Condition<Ts...> { class DisplayMenuOnEnterTrigger : public Trigger<const MenuItem *> { public: - explicit DisplayMenuOnEnterTrigger(MenuItem *parent) { - parent->add_on_enter_callback([this, parent]() { this->trigger(parent); }); + explicit DisplayMenuOnEnterTrigger(MenuItem *parent) : parent_(parent) { + parent->add_on_enter_callback([this]() { this->trigger(this->parent_); }); } + + protected: + MenuItem *parent_; }; class DisplayMenuOnLeaveTrigger : public Trigger<const MenuItem *> { public: - explicit DisplayMenuOnLeaveTrigger(MenuItem *parent) { - parent->add_on_leave_callback([this, parent]() { this->trigger(parent); }); + explicit DisplayMenuOnLeaveTrigger(MenuItem *parent) : parent_(parent) { + parent->add_on_leave_callback([this]() { this->trigger(this->parent_); }); } + + protected: + MenuItem *parent_; }; class DisplayMenuOnValueTrigger : public Trigger<const MenuItem *> { public: - explicit DisplayMenuOnValueTrigger(MenuItem *parent) { - parent->add_on_value_callback([this, parent]() { this->trigger(parent); }); + explicit DisplayMenuOnValueTrigger(MenuItem *parent) : parent_(parent) { + parent->add_on_value_callback([this]() { this->trigger(this->parent_); }); } + + protected: + MenuItem *parent_; }; class DisplayMenuOnNextTrigger : public Trigger<const MenuItem *> { public: - explicit DisplayMenuOnNextTrigger(MenuItemCustom *parent) { - parent->add_on_next_callback([this, parent]() { this->trigger(parent); }); + explicit DisplayMenuOnNextTrigger(MenuItemCustom *parent) : parent_(parent) { + parent->add_on_next_callback([this]() { this->trigger(this->parent_); }); } + + protected: + MenuItemCustom *parent_; }; class DisplayMenuOnPrevTrigger : public Trigger<const MenuItem *> { public: - explicit DisplayMenuOnPrevTrigger(MenuItemCustom *parent) { - parent->add_on_prev_callback([this, parent]() { this->trigger(parent); }); + explicit DisplayMenuOnPrevTrigger(MenuItemCustom *parent) : parent_(parent) { + parent->add_on_prev_callback([this]() { this->trigger(this->parent_); }); } + + protected: + MenuItemCustom *parent_; }; } // namespace display_menu_base diff --git a/esphome/components/esp32_improv/automation.h b/esphome/components/esp32_improv/automation.h index 52c5da125b..cd2bd84c30 100644 --- a/esphome/components/esp32_improv/automation.h +++ b/esphome/components/esp32_improv/automation.h @@ -12,58 +12,73 @@ namespace esp32_improv { class ESP32ImprovProvisionedTrigger : public Trigger<> { public: - explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) { - parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { - if (state == improv::STATE_PROVISIONED && !parent->is_failed()) { - trigger(); + explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) : parent_(parent) { + parent->add_on_state_callback([this](improv::State state, improv::Error error) { + if (state == improv::STATE_PROVISIONED && !this->parent_->is_failed()) { + this->trigger(); } }); } + + protected: + ESP32ImprovComponent *parent_; }; class ESP32ImprovProvisioningTrigger : public Trigger<> { public: - explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) { - parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { - if (state == improv::STATE_PROVISIONING && !parent->is_failed()) { - trigger(); + explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) : parent_(parent) { + parent->add_on_state_callback([this](improv::State state, improv::Error error) { + if (state == improv::STATE_PROVISIONING && !this->parent_->is_failed()) { + this->trigger(); } }); } + + protected: + ESP32ImprovComponent *parent_; }; class ESP32ImprovStartTrigger : public Trigger<> { public: - explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) { - parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { + explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) : parent_(parent) { + parent->add_on_state_callback([this](improv::State state, improv::Error error) { if ((state == improv::STATE_AUTHORIZED || state == improv::STATE_AWAITING_AUTHORIZATION) && - !parent->is_failed()) { - trigger(); + !this->parent_->is_failed()) { + this->trigger(); } }); } + + protected: + ESP32ImprovComponent *parent_; }; class ESP32ImprovStateTrigger : public Trigger<improv::State, improv::Error> { public: - explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) { - parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { - if (!parent->is_failed()) { - trigger(state, error); + explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) : parent_(parent) { + parent->add_on_state_callback([this](improv::State state, improv::Error error) { + if (!this->parent_->is_failed()) { + this->trigger(state, error); } }); } + + protected: + ESP32ImprovComponent *parent_; }; class ESP32ImprovStoppedTrigger : public Trigger<> { public: - explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) { - parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) { - if (state == improv::STATE_STOPPED && !parent->is_failed()) { - trigger(); + explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) : parent_(parent) { + parent->add_on_state_callback([this](improv::State state, improv::Error error) { + if (state == improv::STATE_STOPPED && !this->parent_->is_failed()) { + this->trigger(); } }); } + + protected: + ESP32ImprovComponent *parent_; }; } // namespace esp32_improv diff --git a/esphome/components/fan/automation.h b/esphome/components/fan/automation.h index 3c3b0ce519..3ee6f89e55 100644 --- a/esphome/components/fan/automation.h +++ b/esphome/components/fan/automation.h @@ -113,16 +113,19 @@ template<typename... Ts> class FanIsOffCondition : public Condition<Ts...> { class FanStateTrigger : public Trigger<Fan *> { public: - FanStateTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { this->trigger(state); }); + FanStateTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { this->trigger(this->fan_); }); } + + protected: + Fan *fan_; }; class FanTurnOnTrigger : public Trigger<> { public: - FanTurnOnTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto is_on = state->state; + FanTurnOnTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto is_on = this->fan_->state; auto should_trigger = is_on && !this->last_on_; this->last_on_ = is_on; if (should_trigger) { @@ -133,14 +136,15 @@ class FanTurnOnTrigger : public Trigger<> { } protected: + Fan *fan_; bool last_on_; }; class FanTurnOffTrigger : public Trigger<> { public: - FanTurnOffTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto is_on = state->state; + FanTurnOffTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto is_on = this->fan_->state; auto should_trigger = !is_on && this->last_on_; this->last_on_ = is_on; if (should_trigger) { @@ -151,14 +155,15 @@ class FanTurnOffTrigger : public Trigger<> { } protected: + Fan *fan_; bool last_on_; }; class FanDirectionSetTrigger : public Trigger<FanDirection> { public: - FanDirectionSetTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto direction = state->direction; + FanDirectionSetTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto direction = this->fan_->direction; auto should_trigger = direction != this->last_direction_; this->last_direction_ = direction; if (should_trigger) { @@ -169,14 +174,15 @@ class FanDirectionSetTrigger : public Trigger<FanDirection> { } protected: + Fan *fan_; FanDirection last_direction_; }; class FanOscillatingSetTrigger : public Trigger<bool> { public: - FanOscillatingSetTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto oscillating = state->oscillating; + FanOscillatingSetTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto oscillating = this->fan_->oscillating; auto should_trigger = oscillating != this->last_oscillating_; this->last_oscillating_ = oscillating; if (should_trigger) { @@ -187,14 +193,15 @@ class FanOscillatingSetTrigger : public Trigger<bool> { } protected: + Fan *fan_; bool last_oscillating_; }; class FanSpeedSetTrigger : public Trigger<int> { public: - FanSpeedSetTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto speed = state->speed; + FanSpeedSetTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto speed = this->fan_->speed; auto should_trigger = speed != this->last_speed_; this->last_speed_ = speed; if (should_trigger) { @@ -205,14 +212,15 @@ class FanSpeedSetTrigger : public Trigger<int> { } protected: + Fan *fan_; int last_speed_; }; class FanPresetSetTrigger : public Trigger<StringRef> { public: - FanPresetSetTrigger(Fan *state) { - state->add_on_state_callback([this, state]() { - auto preset_mode = state->get_preset_mode(); + FanPresetSetTrigger(Fan *state) : fan_(state) { + state->add_on_state_callback([this]() { + auto preset_mode = this->fan_->get_preset_mode(); auto should_trigger = preset_mode != this->last_preset_mode_; this->last_preset_mode_ = preset_mode; if (should_trigger) { @@ -223,6 +231,7 @@ class FanPresetSetTrigger : public Trigger<StringRef> { } protected: + Fan *fan_; StringRef last_preset_mode_{}; }; diff --git a/esphome/components/graphical_display_menu/graphical_display_menu.h b/esphome/components/graphical_display_menu/graphical_display_menu.h index 007889557d..ce1db18525 100644 --- a/esphome/components/graphical_display_menu/graphical_display_menu.h +++ b/esphome/components/graphical_display_menu/graphical_display_menu.h @@ -75,9 +75,12 @@ class GraphicalDisplayMenu : public display_menu_base::DisplayMenuComponent { class GraphicalDisplayMenuOnRedrawTrigger : public Trigger<const GraphicalDisplayMenu *> { public: - explicit GraphicalDisplayMenuOnRedrawTrigger(GraphicalDisplayMenu *parent) { - parent->add_on_redraw_callback([this, parent]() { this->trigger(parent); }); + explicit GraphicalDisplayMenuOnRedrawTrigger(GraphicalDisplayMenu *parent) : parent_(parent) { + parent->add_on_redraw_callback([this]() { this->trigger(this->parent_); }); } + + protected: + GraphicalDisplayMenu *parent_; }; } // namespace graphical_display_menu diff --git a/esphome/components/lock/automation.h b/esphome/components/lock/automation.h index 011c6cc6af..6f3c422693 100644 --- a/esphome/components/lock/automation.h +++ b/esphome/components/lock/automation.h @@ -51,13 +51,16 @@ template<typename... Ts> class LockCondition : public Condition<Ts...> { template<LockState State> class LockStateTrigger : public Trigger<> { public: - explicit LockStateTrigger(Lock *a_lock) { - a_lock->add_on_state_callback([this, a_lock]() { - if (a_lock->state == State) { + explicit LockStateTrigger(Lock *a_lock) : lock_(a_lock) { + a_lock->add_on_state_callback([this]() { + if (this->lock_->state == State) { this->trigger(); } }); } + + protected: + Lock *lock_; }; using LockLockTrigger = LockStateTrigger<LockState::LOCK_STATE_LOCKED>; diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 90e7bf75b5..031f6657f4 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -80,12 +80,15 @@ class StateTrigger : public Trigger<> { template<MediaPlayerState State> class MediaPlayerStateTrigger : public Trigger<> { public: - explicit MediaPlayerStateTrigger(MediaPlayer *player) { - player->add_on_state_callback([this, player]() { - if (player->state == State) + explicit MediaPlayerStateTrigger(MediaPlayer *player) : player_(player) { + player->add_on_state_callback([this]() { + if (this->player_->state == State) this->trigger(); }); } + + protected: + MediaPlayer *player_; }; using IdleTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_IDLE>; diff --git a/esphome/components/mqtt/mqtt_fan.cpp b/esphome/components/mqtt/mqtt_fan.cpp index ae2b8c4600..3a8658a55f 100644 --- a/esphome/components/mqtt/mqtt_fan.cpp +++ b/esphome/components/mqtt/mqtt_fan.cpp @@ -121,8 +121,7 @@ void MQTTFanComponent::setup() { }); } - auto f = std::bind(&MQTTFanComponent::publish_state, this); - this->state_->add_on_state_callback([this, f]() { this->defer("send", f); }); + this->state_->add_on_state_callback([this]() { this->defer("send", [this]() { this->publish_state(); }); }); } void MQTTFanComponent::dump_config() { diff --git a/esphome/components/valve/automation.h b/esphome/components/valve/automation.h index 87e9cde088..a064f375f7 100644 --- a/esphome/components/valve/automation.h +++ b/esphome/components/valve/automation.h @@ -87,24 +87,30 @@ template<typename... Ts> class ValveIsClosedCondition : public Condition<Ts...> class ValveOpenTrigger : public Trigger<> { public: - ValveOpenTrigger(Valve *a_valve) { - a_valve->add_on_state_callback([this, a_valve]() { - if (a_valve->is_fully_open()) { + ValveOpenTrigger(Valve *a_valve) : valve_(a_valve) { + a_valve->add_on_state_callback([this]() { + if (this->valve_->is_fully_open()) { this->trigger(); } }); } + + protected: + Valve *valve_; }; class ValveClosedTrigger : public Trigger<> { public: - ValveClosedTrigger(Valve *a_valve) { - a_valve->add_on_state_callback([this, a_valve]() { - if (a_valve->is_fully_closed()) { + ValveClosedTrigger(Valve *a_valve) : valve_(a_valve) { + a_valve->add_on_state_callback([this]() { + if (this->valve_->is_fully_closed()) { this->trigger(); } }); } + + protected: + Valve *valve_; }; } // namespace valve From 95dea59382d422f8d1a44020a64d79935bd6ac19 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 15:25:54 -1000 Subject: [PATCH 1584/2030] [core] Use SplitMix32 PRNG for random_uint32() (#14984) --- esphome/components/esp32/helpers.cpp | 1 - esphome/components/host/helpers.cpp | 9 -------- esphome/components/libretiny/helpers.cpp | 2 -- esphome/components/rp2040/helpers.cpp | 9 -------- esphome/components/zephyr/__init__.py | 2 ++ esphome/components/zephyr/core.cpp | 1 - esphome/core/helpers.cpp | 26 ++++++++++++++++++++++++ esphome/core/helpers.h | 7 ++++++- 8 files changed, 34 insertions(+), 23 deletions(-) diff --git a/esphome/components/esp32/helpers.cpp b/esphome/components/esp32/helpers.cpp index 76f1c59c73..654a35b473 100644 --- a/esphome/components/esp32/helpers.cpp +++ b/esphome/components/esp32/helpers.cpp @@ -14,7 +14,6 @@ namespace esphome { -uint32_t random_uint32() { return esp_random(); } bool random_bytes(uint8_t *data, size_t len) { esp_fill_random(data, len); return true; diff --git a/esphome/components/host/helpers.cpp b/esphome/components/host/helpers.cpp index fdad4f5cb6..7e8849b3e1 100644 --- a/esphome/components/host/helpers.cpp +++ b/esphome/components/host/helpers.cpp @@ -8,8 +8,6 @@ #include <sys/ioctl.h> #endif #include <unistd.h> -#include <limits> -#include <random> #include "esphome/core/defines.h" #include "esphome/core/log.h" @@ -18,13 +16,6 @@ namespace esphome { static const char *const TAG = "helpers.host"; -uint32_t random_uint32() { - std::random_device dev; - std::mt19937 rng(dev()); - std::uniform_int_distribution<uint32_t> dist(0, std::numeric_limits<uint32_t>::max()); - return dist(rng); -} - bool random_bytes(uint8_t *data, size_t len) { FILE *fp = fopen("/dev/urandom", "r"); if (fp == nullptr) { diff --git a/esphome/components/libretiny/helpers.cpp b/esphome/components/libretiny/helpers.cpp index ffbd181c54..52332ef53d 100644 --- a/esphome/components/libretiny/helpers.cpp +++ b/esphome/components/libretiny/helpers.cpp @@ -8,8 +8,6 @@ namespace esphome { -uint32_t random_uint32() { return rand(); } - bool random_bytes(uint8_t *data, size_t len) { lt_rand_bytes(data, len); return true; diff --git a/esphome/components/rp2040/helpers.cpp b/esphome/components/rp2040/helpers.cpp index e360b45ebb..8cb5f7c18d 100644 --- a/esphome/components/rp2040/helpers.cpp +++ b/esphome/components/rp2040/helpers.cpp @@ -17,15 +17,6 @@ namespace esphome { -uint32_t random_uint32() { - uint32_t result = 0; - for (uint8_t i = 0; i < 32; i++) { - result <<= 1; - result |= rosc_hw->randombit; - } - return result; -} - bool random_bytes(uint8_t *data, size_t len) { while (len-- != 0) { uint8_t result = 0; diff --git a/esphome/components/zephyr/__init__.py b/esphome/components/zephyr/__init__.py index b8a091feb9..348e7a3cf2 100644 --- a/esphome/components/zephyr/__init__.py +++ b/esphome/components/zephyr/__init__.py @@ -122,6 +122,8 @@ def zephyr_to_code(config: ConfigType) -> None: zephyr_add_prj_conf("FPU", True) zephyr_add_prj_conf("NEWLIB_LIBC_FLOAT_PRINTF", True) zephyr_add_prj_conf("STD_CPP20", True) + # random_bytes() uses sys_rand_get() which requires the entropy subsystem + zephyr_add_prj_conf("ENTROPY_GENERATOR", True) # <err> os: ***** USAGE FAULT ***** # <err> os: Illegal load of EXC_RETURN into PC diff --git a/esphome/components/zephyr/core.cpp b/esphome/components/zephyr/core.cpp index d7c77fdd2c..a3b0471ebc 100644 --- a/esphome/components/zephyr/core.cpp +++ b/esphome/components/zephyr/core.cpp @@ -75,7 +75,6 @@ IRAM_ATTR InterruptLock::~InterruptLock() { irq_unlock(state_); } // Zephyr LwIPLock is defined inline as a no-op in helpers.h -uint32_t random_uint32() { return rand(); } // NOLINT(cert-msc30-c, cert-msc50-cpp) bool random_bytes(uint8_t *data, size_t len) { sys_rand_get(data, len); return true; diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 00b447ebf2..ee99c54196 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -156,6 +156,32 @@ uint32_t fnv1_hash(const char *str) { return hash; } +// SplitMix32 — a fast, non-cryptographic PRNG from the SplitMix family +// (Steele et al., 2014). Uses a Weyl sequence with golden-ratio increment +// and the MurmurHash3 32-bit finalizer as output mixing function. +// Reference: https://doi.org/10.1145/2714064.2660195 +// Test results: https://lemire.me/blog/2017/08/22/testing-non-cryptographic-random-number-generators-my-results/ +// Seeded lazily from the platform's secure RNG via random_bytes(). +// ESP8266 uses os_random() instead (defined in esp8266/helpers.cpp). +#ifndef USE_ESP8266 +static uint32_t splitmix32_state; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + +uint32_t random_uint32() { + // State of 0 means unseeded. The state will wrap back to 0 after 2^32 calls, + // triggering one extra random_bytes() call — an acceptable trade-off vs. adding + // a separate bool flag (4 bytes BSS + branch on every call). + if (splitmix32_state == 0) { + random_bytes(reinterpret_cast<uint8_t *>(&splitmix32_state), sizeof(splitmix32_state)); + splitmix32_state |= 1; // ensure non-zero seed + } + splitmix32_state += 0x9e3779b9u; + uint32_t z = splitmix32_state; + z = (z ^ (z >> 16)) * 0x85ebca6bu; + z = (z ^ (z >> 13)) * 0xc2b2ae35u; + return z ^ (z >> 16); +} +#endif + float random_float() { return static_cast<float>(random_uint32()) / static_cast<float>(UINT32_MAX); } // Strings diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index a703b5a5f3..43431299de 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -842,10 +842,15 @@ template<typename ReturnT = uint32_t> inline constexpr ESPHOME_ALWAYS_INLINE Ret } /// Return a random 32-bit unsigned integer. +/// Not thread-safe. Must only be called from the main loop. +/// Not suitable for cryptographic use; use random_bytes() instead. uint32_t random_uint32(); /// Return a random float between 0 and 1. +/// Not thread-safe. Must only be called from the main loop. +/// Not suitable for cryptographic use; use random_bytes() instead. float random_float(); -/// Generate \p len number of random bytes. +/// Generate \p len random bytes using the platform's secure RNG (hardware RNG or OS CSPRNG). +/// Thread-safe. Suitable for cryptographic use. bool random_bytes(uint8_t *data, size_t len); ///@} From 1920d8a887407a9d9f2f23f8c1d9f83480a497a5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 17:35:17 -1000 Subject: [PATCH 1585/2030] [benchmark] Add noise encryption benchmarks (#15037) --- script/setup_codspeed_lib.py | 8 +- tests/benchmarks/components/api/__init__.py | 7 + .../components/api/bench_noise_encrypt.cpp | 177 ++++++++++++++++++ .../benchmarks/components/api/benchmark.yaml | 1 + tests/benchmarks/components/mdns/__init__.py | 5 + .../benchmarks/components/network/__init__.py | 5 + .../benchmarks/components/socket/__init__.py | 7 + 7 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 tests/benchmarks/components/api/__init__.py create mode 100644 tests/benchmarks/components/api/bench_noise_encrypt.cpp create mode 100644 tests/benchmarks/components/mdns/__init__.py create mode 100644 tests/benchmarks/components/network/__init__.py create mode 100644 tests/benchmarks/components/socket/__init__.py diff --git a/script/setup_codspeed_lib.py b/script/setup_codspeed_lib.py index 959c89d05b..4f5d1bff24 100755 --- a/script/setup_codspeed_lib.py +++ b/script/setup_codspeed_lib.py @@ -205,7 +205,13 @@ def setup_codspeed_lib(output_dir: Path) -> None: if hooks_dist_c.exists(): _copy_if_missing(hooks_dist_c, lib_src / "instrument_hooks.c") - # 4. Write library.json + # 4. Copy instrument-hooks headers (core.h, callgrind.h, valgrind.h) next to + # measurement.hpp so they are found before any same-named headers from + # other libraries (e.g. libsodium's core.h). + for header in hooks_include.glob("*.h"): + _copy_if_missing(header, core_include / header.name) + + # 5. Write library.json version = _read_codspeed_version(output_dir / CORE_CMAKE) _write_library_json( benchmark_dir, core_include, hooks_include, version, project_root diff --git a/tests/benchmarks/components/api/__init__.py b/tests/benchmarks/components/api/__init__.py new file mode 100644 index 0000000000..0687c3f87f --- /dev/null +++ b/tests/benchmarks/components/api/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # api must run its to_code to define USE_API, USE_API_PLAINTEXT, + # and add the noise-c library dependency. + manifest.enable_codegen() diff --git a/tests/benchmarks/components/api/bench_noise_encrypt.cpp b/tests/benchmarks/components/api/bench_noise_encrypt.cpp new file mode 100644 index 0000000000..223e6ada0d --- /dev/null +++ b/tests/benchmarks/components/api/bench_noise_encrypt.cpp @@ -0,0 +1,177 @@ +#include "esphome/core/defines.h" +#ifdef USE_API_NOISE + +#include <benchmark/benchmark.h> +#include <cstring> +#include <memory> + +#include "noise/protocol.h" + +namespace esphome::api::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Helper to create and initialize a NoiseCipherState with ChaChaPoly. +// Returns nullptr on failure. +static NoiseCipherState *create_cipher() { + NoiseCipherState *cipher = nullptr; + int err = noise_cipherstate_new_by_id(&cipher, NOISE_CIPHER_CHACHAPOLY); + if (err != NOISE_ERROR_NONE || cipher == nullptr) + return nullptr; + + // Initialize with a dummy 32-byte key (same pattern as handshake split produces) + uint8_t key[32]; + memset(key, 0xAB, sizeof(key)); + err = noise_cipherstate_init_key(cipher, key, sizeof(key)); + if (err != NOISE_ERROR_NONE) { + noise_cipherstate_free(cipher); + return nullptr; + } + return cipher; +} + +// Benchmark helper matching the exact pattern from +// APINoiseFrameHelper::write_protobuf_messages: +// - noise_buffer_init + noise_buffer_set_inout (same as production) +// - No explicit set_nonce (production relies on internal nonce increment) +// - Error checking on encrypt return +static void noise_encrypt_bench(benchmark::State &state, size_t plaintext_size) { + NoiseCipherState *cipher = create_cipher(); + if (cipher == nullptr) { + state.SkipWithError("Failed to create cipher state"); + return; + } + + size_t mac_len = noise_cipherstate_get_mac_length(cipher); + size_t buf_capacity = plaintext_size + mac_len; + auto buffer = std::make_unique<uint8_t[]>(buf_capacity); + memset(buffer.get(), 0x42, plaintext_size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + // Match production: init buffer, set inout, encrypt + NoiseBuffer mbuf; + noise_buffer_init(mbuf); + noise_buffer_set_inout(mbuf, buffer.get(), plaintext_size, buf_capacity); + + int err = noise_cipherstate_encrypt(cipher, &mbuf); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("noise_cipherstate_encrypt failed"); + noise_cipherstate_free(cipher); + return; + } + } + benchmark::DoNotOptimize(buffer[0]); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + noise_cipherstate_free(cipher); +} + +// --- Encrypt a typical sensor state message (small payload ~14 bytes) --- +// This is the most common message encrypted on every sensor update. +// 4 bytes type+len header + ~10 bytes payload. + +static void NoiseEncrypt_SmallMessage(benchmark::State &state) { noise_encrypt_bench(state, 14); } +BENCHMARK(NoiseEncrypt_SmallMessage); + +// --- Encrypt a medium message (~128 bytes, typical for LightStateResponse) --- + +static void NoiseEncrypt_MediumMessage(benchmark::State &state) { noise_encrypt_bench(state, 128); } +BENCHMARK(NoiseEncrypt_MediumMessage); + +// --- Encrypt a large message (~1024 bytes, typical for DeviceInfoResponse) --- + +static void NoiseEncrypt_LargeMessage(benchmark::State &state) { noise_encrypt_bench(state, 1024); } +BENCHMARK(NoiseEncrypt_LargeMessage); + +// Benchmark helper matching the exact pattern from +// APINoiseFrameHelper::read_packet: +// - noise_buffer_init + noise_buffer_set_inout with capacity == size (decrypt shrinks) +// - Error checking on decrypt return +// +// Pre-encrypts kInnerIterations messages with sequential nonces before the +// timed loop. Each outer iteration re-inits the decrypt key to reset the +// nonce back to 0, then decrypts all pre-encrypted messages in sequence. +// The init_key cost is amortized over kInnerIterations decrypts. +static void noise_decrypt_bench(benchmark::State &state, size_t plaintext_size) { + NoiseCipherState *encrypt_cipher = create_cipher(); + NoiseCipherState *decrypt_cipher = create_cipher(); + if (encrypt_cipher == nullptr || decrypt_cipher == nullptr) { + state.SkipWithError("Failed to create cipher state"); + if (encrypt_cipher) + noise_cipherstate_free(encrypt_cipher); + if (decrypt_cipher) + noise_cipherstate_free(decrypt_cipher); + return; + } + + size_t mac_len = noise_cipherstate_get_mac_length(encrypt_cipher); + size_t encrypted_size = plaintext_size + mac_len; + + // Pre-encrypt kInnerIterations messages with sequential nonces (0..N-1). + auto ciphertexts = std::make_unique<uint8_t[]>(encrypted_size * kInnerIterations); + for (int i = 0; i < kInnerIterations; i++) { + uint8_t *ct = ciphertexts.get() + i * encrypted_size; + memset(ct, 0x42, plaintext_size); + NoiseBuffer enc_buf; + noise_buffer_init(enc_buf); + noise_buffer_set_inout(enc_buf, ct, plaintext_size, encrypted_size); + int err = noise_cipherstate_encrypt(encrypt_cipher, &enc_buf); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Pre-encrypt failed"); + noise_cipherstate_free(encrypt_cipher); + noise_cipherstate_free(decrypt_cipher); + return; + } + } + + // Working buffer — decrypt modifies in place + auto buffer = std::make_unique<uint8_t[]>(encrypted_size); + static constexpr uint8_t KEY[32] = {0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB}; + + for (auto _ : state) { + // Reset nonce to 0 by re-initing the key (amortized over kInnerIterations) + noise_cipherstate_init_key(decrypt_cipher, KEY, sizeof(KEY)); + + for (int i = 0; i < kInnerIterations; i++) { + // Copy ciphertext into working buffer (decrypt modifies in place) + memcpy(buffer.get(), ciphertexts.get() + i * encrypted_size, encrypted_size); + + // Decrypt matching production pattern + NoiseBuffer mbuf; + noise_buffer_init(mbuf); + noise_buffer_set_inout(mbuf, buffer.get(), encrypted_size, encrypted_size); + + int err = noise_cipherstate_decrypt(decrypt_cipher, &mbuf); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("noise_cipherstate_decrypt failed"); + noise_cipherstate_free(encrypt_cipher); + noise_cipherstate_free(decrypt_cipher); + return; + } + } + benchmark::DoNotOptimize(buffer[0]); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + noise_cipherstate_free(encrypt_cipher); + noise_cipherstate_free(decrypt_cipher); +} + +// --- Decrypt benchmarks (matching read_packet path) --- + +static void NoiseDecrypt_SmallMessage(benchmark::State &state) { noise_decrypt_bench(state, 14); } +BENCHMARK(NoiseDecrypt_SmallMessage); + +static void NoiseDecrypt_MediumMessage(benchmark::State &state) { noise_decrypt_bench(state, 128); } +BENCHMARK(NoiseDecrypt_MediumMessage); + +static void NoiseDecrypt_LargeMessage(benchmark::State &state) { noise_decrypt_bench(state, 1024); } +BENCHMARK(NoiseDecrypt_LargeMessage); + +} // namespace esphome::api::benchmarks + +#endif // USE_API_NOISE diff --git a/tests/benchmarks/components/api/benchmark.yaml b/tests/benchmarks/components/api/benchmark.yaml index bfc24d7440..e57276ea66 100644 --- a/tests/benchmarks/components/api/benchmark.yaml +++ b/tests/benchmarks/components/api/benchmark.yaml @@ -108,6 +108,7 @@ esphome: area_id: area_20 api: + encryption: sensor: binary_sensor: light: diff --git a/tests/benchmarks/components/mdns/__init__.py b/tests/benchmarks/components/mdns/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/mdns/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/network/__init__.py b/tests/benchmarks/components/network/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/network/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/socket/__init__.py b/tests/benchmarks/components/socket/__init__.py new file mode 100644 index 0000000000..7a20f9f230 --- /dev/null +++ b/tests/benchmarks/components/socket/__init__.py @@ -0,0 +1,7 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # socket must run its to_code to define USE_SOCKET_IMPL_BSD_SOCKETS + # which is needed by the api frame helper benchmarks. + manifest.enable_codegen() From d203a46ef808f76c22018eec570bab9f29b999a8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 18:17:37 -1000 Subject: [PATCH 1586/2030] [api] Enable HAVE_WEAK_SYMBOLS and HAVE_INLINE_ASM for libsodium (#15038) --- esphome/components/api/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 4c3cf81927..84589d540d 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -455,6 +455,9 @@ async def to_code(config: ConfigType) -> None: cg.add_define("USE_API_PLAINTEXT") cg.add_define("USE_API_NOISE") cg.add_library("esphome/noise-c", "0.1.11") + # Enable optimized memzero/memcmp in libsodium instead of volatile byte loops + cg.add_build_flag("-DHAVE_WEAK_SYMBOLS=1") + cg.add_build_flag("-DHAVE_INLINE_ASM=1") else: cg.add_define("USE_API_PLAINTEXT") From 8dd69207ea09f8ca8c2d90d9437c7396ae0dc2aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Mar 2026 10:24:56 +0000 Subject: [PATCH 1587/2030] Bump aioesphomeapi from 44.6.2 to 44.7.0 (#15052) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 10e56c3b49..2e09e2ed99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.6.2 +aioesphomeapi==44.7.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 2a6ec597b4ca81bd63f062307799c97c024f2726 Mon Sep 17 00:00:00 2001 From: Samuel Sieb <samuel-github@sieb.net> Date: Sat, 21 Mar 2026 11:13:08 -0700 Subject: [PATCH 1588/2030] [analog_threshhold] add missing header (#15058) --- .../components/analog_threshold/analog_threshold_binary_sensor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/analog_threshold/analog_threshold_binary_sensor.h b/esphome/components/analog_threshold/analog_threshold_binary_sensor.h index 9ea95d8570..dd70768105 100644 --- a/esphome/components/analog_threshold/analog_threshold_binary_sensor.h +++ b/esphome/components/analog_threshold/analog_threshold_binary_sensor.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/sensor/sensor.h" From 86ec218f75685454a3cc012cd632c350ba60ad5c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Mar 2026 13:15:35 -1000 Subject: [PATCH 1589/2030] [benchmark] Add plaintext API frame write benchmarks (#15036) --- .../components/api/bench_plaintext_frame.cpp | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 tests/benchmarks/components/api/bench_plaintext_frame.cpp diff --git a/tests/benchmarks/components/api/bench_plaintext_frame.cpp b/tests/benchmarks/components/api/bench_plaintext_frame.cpp new file mode 100644 index 0000000000..79bffaf953 --- /dev/null +++ b/tests/benchmarks/components/api/bench_plaintext_frame.cpp @@ -0,0 +1,162 @@ +#include "esphome/core/defines.h" +#ifdef USE_API_PLAINTEXT + +#include <benchmark/benchmark.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/socket.h> +#include <unistd.h> + +#include "esphome/components/api/api_frame_helper_plaintext.h" +#include "esphome/components/api/api_pb2.h" +#include "esphome/components/api/api_buffer.h" + +namespace esphome::api::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Helper to drain accumulated data from the read side of a socket +// to prevent the write side from blocking. +static void drain_socket(int fd) { + char buf[65536]; + while (::read(fd, buf, sizeof(buf)) > 0) { + } +} + +// Helper to create a TCP loopback connection with an APIPlaintextFrameHelper +// on the write end. Returns the helper and the read-side fd. +// Uses real TCP sockets so TCP_NODELAY succeeds during init(). +static std::pair<std::unique_ptr<APIPlaintextFrameHelper>, int> create_plaintext_helper() { + // Create a TCP listener on loopback + int listen_fd = ::socket(AF_INET, SOCK_STREAM, 0); + int opt = 1; + ::setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + struct sockaddr_in addr {}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = 0; // OS-assigned port + ::bind(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); + ::listen(listen_fd, 1); + + // Get the assigned port + socklen_t addr_len = sizeof(addr); + ::getsockname(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), &addr_len); + + // Connect from client side + int write_fd = ::socket(AF_INET, SOCK_STREAM, 0); + ::connect(write_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); + + // Accept on server side (this is our read fd) + int read_fd = ::accept(listen_fd, nullptr, nullptr); + ::close(listen_fd); + + // Make both ends non-blocking + int flags = ::fcntl(write_fd, F_GETFL, 0); + ::fcntl(write_fd, F_SETFL, flags | O_NONBLOCK); + flags = ::fcntl(read_fd, F_GETFL, 0); + ::fcntl(read_fd, F_SETFL, flags | O_NONBLOCK); + + // Increase socket buffer sizes to reduce drain frequency + int bufsize = 1024 * 1024; + ::setsockopt(write_fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); + ::setsockopt(read_fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); + + auto sock = std::make_unique<socket::Socket>(write_fd); + auto helper = std::make_unique<APIPlaintextFrameHelper>(std::move(sock)); + helper->init(); + + return {std::move(helper), read_fd}; +} + +// --- Write a single SensorStateResponse through plaintext framing --- +// Measures the full write path: header construction, varint encoding, +// iovec assembly, and socket write. + +static void PlaintextFrame_WriteSensorState(benchmark::State &state) { + auto [helper, read_fd] = create_plaintext_helper(); + uint8_t padding = helper->frame_header_padding(); + + // Pre-init buffer to typical TCP MSS size to avoid benchmarking + // heap allocation — in real use the buffer is reused across writes. + APIBuffer buffer; + buffer.reserve(1460); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + buffer.clear(); + SensorStateResponse msg; + msg.key = 0x12345678; + msg.state = 23.5f; + msg.missing_state = false; + + uint32_t size = msg.calculate_size(); + buffer.resize(padding + size); + ProtoWriteBuffer writer(&buffer, padding); + msg.encode(writer); + + helper->write_protobuf_packet(SensorStateResponse::MESSAGE_TYPE, writer); + + if ((i & 0xFF) == 0) + drain_socket(read_fd); + } + drain_socket(read_fd); + benchmark::DoNotOptimize(helper.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(PlaintextFrame_WriteSensorState); + +// --- Write a batch of 5 SensorStateResponses in one call --- +// Measures batched write: multiple messages assembled into one writev. + +static void PlaintextFrame_WriteBatch5(benchmark::State &state) { + auto [helper, read_fd] = create_plaintext_helper(); + uint8_t padding = helper->frame_header_padding(); + uint8_t footer = helper->frame_footer_size(); + + // Pre-init buffer to typical TCP MSS size to avoid benchmarking + // heap allocation — in real use the buffer is reused across writes. + APIBuffer buffer; + buffer.reserve(1460); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + buffer.clear(); + MessageInfo messages[5] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; + + for (int j = 0; j < 5; j++) { + uint16_t offset = buffer.size(); + SensorStateResponse msg; + msg.key = static_cast<uint32_t>(j); + msg.state = 23.5f + static_cast<float>(j); + msg.missing_state = false; + + uint32_t size = msg.calculate_size(); + buffer.resize(offset + padding + size + footer); + ProtoWriteBuffer writer(&buffer, offset + padding); + msg.encode(writer); + + messages[j] = MessageInfo(SensorStateResponse::MESSAGE_TYPE, offset, size); + } + + helper->write_protobuf_messages(ProtoWriteBuffer(&buffer, 0), std::span<const MessageInfo>(messages, 5)); + + if ((i & 0xFF) == 0) + drain_socket(read_fd); + } + drain_socket(read_fd); + benchmark::DoNotOptimize(helper.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(PlaintextFrame_WriteBatch5); + +} // namespace esphome::api::benchmarks + +#endif // USE_API_PLAINTEXT From dd82a91d8fa8b3922e7e4b8177df5875c1d56d04 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sun, 22 Mar 2026 10:13:17 +1000 Subject: [PATCH 1590/2030] [lvgl] Don't animate page change when not requested (#15069) --- esphome/components/lvgl/defines.py | 2 +- esphome/components/lvgl/lvgl_esphome.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index d6d7a5e161..0a53d88669 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -280,7 +280,7 @@ SWIPE_TRIGGERS = tuple( LV_ANIM = LvConstant( - "LV_SCR_LOAD_ANIM_", + "LV_SCREEN_LOAD_ANIM_", "NONE", "OVER_LEFT", "OVER_RIGHT", diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index b1618f77c4..fb5e595713 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -176,7 +176,11 @@ void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t ti if (index >= this->pages_.size()) return; this->current_page_ = index; - lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false); + if (anim == LV_SCREEN_LOAD_ANIM_NONE) { + lv_scr_load(this->pages_[this->current_page_]->obj); + } else { + lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false); + } } void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) { @@ -262,8 +266,8 @@ void LvglComponent::flush_cb_(lv_display_t *disp_drv, const lv_area_t *area, uin if (!this->is_paused()) { auto now = millis(); this->draw_buffer_(area, reinterpret_cast<lv_color_data *>(color_p)); - ESP_LOGV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", area->x1, area->y1, lv_area_get_width(area), - lv_area_get_height(area), (int) (millis() - now)); + ESP_LOGV(TAG, "flush_cb, area=%d/%d, %d/%d took %dms", (int) area->x1, (int) area->y1, + (int) lv_area_get_width(area), (int) lv_area_get_height(area), (int) (millis() - now)); } lv_display_flush_ready(disp_drv); } @@ -619,7 +623,7 @@ void LvglComponent::setup() { // Rotation will be handled by our drawing function, so reset the display rotation. for (auto *disp : this->displays_) disp->set_rotation(display::DISPLAY_ROTATION_0_DEGREES); - this->show_page(0, LV_SCR_LOAD_ANIM_NONE, 0); + this->show_page(0, LV_SCREEN_LOAD_ANIM_NONE, 0); lv_display_trigger_activity(this->disp_); } From 8224da3460819a7a41fb302018f9ee3265fd46a0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Mar 2026 15:32:24 -1000 Subject: [PATCH 1591/2030] [core] Inline Component::get_component_log_str() (#15068) --- esphome/core/component.cpp | 3 --- esphome/core/component.h | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 89ac0c7a2a..caaea89143 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -272,9 +272,6 @@ void Component::call() { break; } } -const LogString *Component::get_component_log_str() const { - return this->component_source_ == nullptr ? LOG_STR("<unknown>") : this->component_source_; -} bool Component::should_warn_of_blocking(uint32_t blocking_time) { if (blocking_time > this->warn_if_blocking_over_) { // Prevent overflow when adding increment - if we're about to overflow, just max out diff --git a/esphome/core/component.h b/esphome/core/component.h index 119681f64c..46cd77b034 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -294,7 +294,9 @@ class Component { * * Returns LOG_STR("<unknown>") if source not set */ - const LogString *get_component_log_str() const; + const LogString *get_component_log_str() const { + return this->component_source_ == nullptr ? LOG_STR("<unknown>") : this->component_source_; + } bool should_warn_of_blocking(uint32_t blocking_time); From c48fd0738ba6ec1e88860758687c2fae06fae430 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Mar 2026 15:33:42 -1000 Subject: [PATCH 1592/2030] [mqtt] Rate-limit component resends to prevent task WDT on reconnect (#15061) --- esphome/components/mqtt/mqtt_client.cpp | 17 ++++++++++++++--- esphome/components/mqtt/mqtt_component.h | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 38daf8f8f6..ab665e2579 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -28,6 +28,10 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt"; +// Maximum number of MQTT component resends per loop iteration. +// Limits work to avoid triggering the task watchdog on reconnect. +static constexpr uint8_t MAX_RESENDS_PER_LOOP = 8; + // Disconnect reason strings indexed by MQTTClientDisconnectReason enum (0-8) PROGMEM_STRING_TABLE(MQTTDisconnectReasonStrings, "TCP disconnected", "Unacceptable Protocol Version", "Identifier Rejected", "Server Unavailable", "Malformed Credentials", "Not Authorized", @@ -396,9 +400,16 @@ void MQTTClientComponent::loop() { this->resubscribe_subscriptions_(); // Process pending resends for all MQTT components centrally - // This is more efficient than each component polling in its own loop - for (MQTTComponent *component : this->children_) { - component->process_resend(); + // Limit work per loop iteration to avoid triggering task WDT on reconnect + { + uint8_t resend_count = 0; + for (MQTTComponent *component : this->children_) { + if (component->is_resend_pending()) { + component->process_resend(); + if (++resend_count >= MAX_RESENDS_PER_LOOP) + break; + } + } } } break; diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 2403ef64ea..7983e04870 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -147,6 +147,9 @@ class MQTTComponent : public Component { /// Internal method for the MQTT client base to schedule a resend of the state on reconnect. void schedule_resend_state(); + /// Check if a resend is pending (called by MQTTClientComponent to rate-limit work) + bool is_resend_pending() const { return this->resend_state_; } + /// Process pending resend if needed (called by MQTTClientComponent) void process_resend(); From a0d552531238ce2f4d9ae95b6d717f4ab838ed11 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sun, 22 Mar 2026 18:01:49 +1000 Subject: [PATCH 1593/2030] [lvgl] Meter fixes (#15073) --- esphome/components/lvgl/lvgl_esphome.cpp | 4 +++- esphome/components/lvgl/lvgl_esphome.h | 2 +- esphome/components/lvgl/widgets/meter.py | 21 +++++++++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index fb5e595713..b3cb4d56ad 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -671,9 +671,10 @@ void LvglComponent::static_flush_cb(lv_display_t *disp_drv, const lv_area_t *are * @param e The event data * @param color_start The color to apply to the first tick * @param color_end The color to apply to the last tick + * @param width */ void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, - lv_color_t color_end, bool local) { + lv_color_t color_end, int width, bool local) { auto *scale = static_cast<lv_obj_t *>(lv_event_get_target(e)); lv_draw_task_t *task = lv_event_get_draw_task(e); @@ -691,6 +692,7 @@ void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_ range = 1; auto ratio = (tick * 255) / range; line_dsc->color = lv_color_mix(color_end, color_start, ratio); + line_dsc->width += width; } } } diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 4ce7296159..8e34f16c98 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -53,7 +53,7 @@ extern std::string lv_event_code_name_for(lv_event_t *event); lv_obj_t *lv_container_create(lv_obj_t *parent); #ifdef USE_LVGL_SCALE void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, - lv_color_t color_end, bool local); + lv_color_t color_end, int width, bool local); #endif #if LV_COLOR_DEPTH == 16 static const display::ColorBitness LV_BITNESS = display::ColorBitness::COLOR_BITNESS_565; diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 63cc645f22..6a7559c42c 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -177,7 +177,7 @@ INDICATOR_ARC_SCHEMA = cv.Schema( cv.Optional(CONF_VALUE): lv_float, cv.Optional(CONF_START_VALUE): lv_float, cv.Optional(CONF_END_VALUE): lv_float, - cv.Optional(CONF_OPA): opacity, + cv.Optional(CONF_OPA, default=1.0): opacity, } ).add_extra(cv.has_at_most_one_key(CONF_VALUE, CONF_START_VALUE)) @@ -247,7 +247,7 @@ SCALE_SCHEMA = cv.Schema( cv.Optional(CONF_RANGE_FROM, default=0.0): lv_int, cv.Optional(CONF_RANGE_TO, default=100.0): lv_int, cv.Optional(CONF_ANGLE_RANGE, default=270): lv_angle_degrees, - cv.Optional(CONF_ROTATION, default=0): lv_angle_degrees, + cv.Optional(CONF_ROTATION): lv_angle_degrees, cv.Optional(CONF_INDICATORS): cv.ensure_list(INDICATOR_SCHEMA), cv.Optional(CONF_DRAW_TICKS_ON_TOP, default=True): bool, } @@ -329,7 +329,7 @@ class MeterType(WidgetType): ) def get_uses(self): - return CONF_SCALE, CONF_LINE + return CONF_SCALE, CONF_LINE, CONF_IMAGE def validate(self, value): return cv.has_at_most_one_key(CONF_INDICATOR, CONF_PIVOT)(value) @@ -366,16 +366,17 @@ class MeterType(WidgetType): lv.scale_set_range(scale_var, range_from, range_to) angle_range = await lv_angle_degrees.process(scale_conf[CONF_ANGLE_RANGE]) - rotation = await lv_angle_degrees.process(scale_conf[CONF_ROTATION]) + if (rotation := scale_conf.get(CONF_ROTATION)) is not None: + rotation = await lv_angle_degrees.process(rotation) + else: + rotation = 90 + (360 - angle_range) // 2 + # Set angle range lv.scale_set_angle_range( scale_var, angle_range, ) - - # Set rotation if specified - if rotation: - lv.scale_set_rotation(scale_var, rotation) + lv.scale_set_rotation(scale_var, rotation) # Handle indicators as sections for indicator in scale_conf.get(CONF_INDICATORS, ()): @@ -393,10 +394,9 @@ class MeterType(WidgetType): props = { "arc_width": v[CONF_WIDTH], "arc_color": v[CONF_COLOR], + "arc_opa": v[CONF_OPA], "arc_rounded": v.get("arc_rounded", False), } - if (opa := v.get(CONF_OPA)) is not None: - props["arc_opa"] = opa if CONF_R_MOD in v: get_warnings().add( "The 'r_mod' indicator property is not supported in LVGL 9.x and will be ignored." @@ -424,6 +424,7 @@ class MeterType(WidgetType): end_value, color_start, color_end, + v[CONF_WIDTH], local, ) lv_obj.add_event_cb( From 5e68282519caf8601bf2192923b1975d85580044 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:14:52 -1000 Subject: [PATCH 1594/2030] [light] Fix constant_brightness broken by gamma LUT refactor (#15048) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/light/light_color_values.h | 10 + esphome/components/light/light_state.cpp | 47 ++++- .../fixtures/light_constant_brightness.yaml | 57 ++++++ .../test_light_constant_brightness.py | 188 ++++++++++++++++++ 4 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 tests/integration/fixtures/light_constant_brightness.yaml create mode 100644 tests/integration/test_light_constant_brightness.py diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index 3a9ca8c8c2..a2c2dbca46 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -154,6 +154,16 @@ class LightColorValues { } /// Convert these light color values to an CWWW representation with the given parameters. + /// + /// Note on gamma and constant_brightness: This method operates on the raw/internal channel + /// values stored in this object. For cold_white_ and warm_white_ specifically, these + /// may already be gamma-uncorrected when derived from a color_temperature value. + /// For constant_brightness=false, additional gamma for the output can be applied after + /// this method since gamma commutes with simple multiplication. For constant_brightness=true, + /// the caller (LightState::current_values_as_cwww) must apply gamma to the individual + /// channel values BEFORE the balancing formula, because the nonlinear max/sum ratio does + /// not commute with gamma. See LightState::current_values_as_cwww() for the correct + /// implementation. void as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false) const { if (this->color_mode_ & ColorCapability::COLD_WARM_WHITE) { const float cw_level = this->cold_white_; diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index 161092532a..1b736d84f6 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -223,12 +223,11 @@ void LightState::current_values_as_rgbw(float *red, float *green, float *blue, f } void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, constant_brightness); + this->current_values.as_rgb(red, green, blue); *red = this->gamma_correct_lut(*red); *green = this->gamma_correct_lut(*green); *blue = this->gamma_correct_lut(*blue); - *cold_white = this->gamma_correct_lut(*cold_white); - *warm_white = this->gamma_correct_lut(*warm_white); + this->current_values_as_cwww(cold_white, warm_white, constant_brightness); } void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature, float *white_brightness) { @@ -241,9 +240,45 @@ void LightState::current_values_as_rgbct(float *red, float *green, float *blue, *white_brightness = this->gamma_correct_lut(*white_brightness); } void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_cwww(cold_white, warm_white, constant_brightness); - *cold_white = this->gamma_correct_lut(*cold_white); - *warm_white = this->gamma_correct_lut(*warm_white); + if (!constant_brightness) { + // Without constant_brightness, gamma commutes with simple multiplication: + // gamma(white_level * cw) = gamma(white_level) * gamma(cw) + // (since gamma(a*b) = (a*b)^g = a^g * b^g = gamma(a) * gamma(b)) + // so applying gamma after is mathematically equivalent and simpler. + this->current_values.as_cwww(cold_white, warm_white, false); + *cold_white = this->gamma_correct_lut(*cold_white); + *warm_white = this->gamma_correct_lut(*warm_white); + return; + } + + // For constant_brightness mode, gamma MUST be applied to the individual + // channel values BEFORE the balancing formula (max/sum ratio), not after. + // + // Why: The cold_white_ and warm_white_ values stored in LightColorValues + // are gamma-uncorrected (see transform_parameters_() which applies + // gamma_uncorrect to the linear CW/WW fractions derived from color + // temperature). Applying gamma_correct here recovers the original linear + // fractions, which the constant_brightness formula then uses to distribute + // power evenly. The max/sum formula ensures cold+warm PWM output sums to + // a constant, keeping total power (and perceived brightness) the same + // across all color temperatures. + // + // Applying gamma AFTER the formula would be incorrect because gamma is + // nonlinear: gamma(a/b) != gamma(a)/gamma(b), so the carefully balanced + // ratio would be distorted, causing a severe brightness dip at mid-range + // color temperatures. + const auto &v = this->current_values; + if (!(v.get_color_mode() & ColorCapability::COLD_WARM_WHITE)) { + *cold_white = *warm_white = 0; + return; + } + + const float cw_level = this->gamma_correct_lut(v.get_cold_white()); + const float ww_level = this->gamma_correct_lut(v.get_warm_white()); + const float white_level = this->gamma_correct_lut(v.get_state() * v.get_brightness()); + const float sum = cw_level > 0 || ww_level > 0 ? cw_level + ww_level : 1; // Don't divide by zero. + *cold_white = white_level * std::max(cw_level, ww_level) * cw_level / sum; + *warm_white = white_level * std::max(cw_level, ww_level) * ww_level / sum; } void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) { auto traits = this->get_traits(); diff --git a/tests/integration/fixtures/light_constant_brightness.yaml b/tests/integration/fixtures/light_constant_brightness.yaml new file mode 100644 index 0000000000..4357a16d58 --- /dev/null +++ b/tests/integration/fixtures/light_constant_brightness.yaml @@ -0,0 +1,57 @@ +esphome: + name: light-cb-test +host: +api: # Port will be automatically injected +logger: + level: DEBUG + +output: + - platform: template + id: cb_cold_white_output + type: float + write_action: + - logger.log: + format: "CB_CW_OUTPUT:%.6f" + args: [state] + - platform: template + id: cb_warm_white_output + type: float + write_action: + - logger.log: + format: "CB_WW_OUTPUT:%.6f" + args: [state] + - platform: template + id: ncb_cold_white_output + type: float + write_action: + - logger.log: + format: "NCB_CW_OUTPUT:%.6f" + args: [state] + - platform: template + id: ncb_warm_white_output + type: float + write_action: + - logger.log: + format: "NCB_WW_OUTPUT:%.6f" + args: [state] + +light: + - platform: cwww + name: "Test CB Light" + id: test_cb_light + cold_white: cb_cold_white_output + warm_white: cb_warm_white_output + cold_white_color_temperature: 6536 K + warm_white_color_temperature: 2000 K + constant_brightness: true + gamma_correct: 2.8 + + - platform: cwww + name: "Test NCB Light" + id: test_ncb_light + cold_white: ncb_cold_white_output + warm_white: ncb_warm_white_output + cold_white_color_temperature: 6536 K + warm_white_color_temperature: 2000 K + constant_brightness: false + gamma_correct: 2.8 diff --git a/tests/integration/test_light_constant_brightness.py b/tests/integration/test_light_constant_brightness.py new file mode 100644 index 0000000000..622dc0e065 --- /dev/null +++ b/tests/integration/test_light_constant_brightness.py @@ -0,0 +1,188 @@ +"""Integration test for constant_brightness with gamma correction. + +Tests both constant_brightness: true and false cwww lights with gamma +correction in a single compilation to verify: +- constant_brightness: true maintains constant total CW+WW power output +- constant_brightness: false correctly varies total power across color temps + +This is a regression test for https://github.com/esphome/esphome/issues/15040 +where the gamma LUT refactor (#14123) broke constant_brightness by applying +gamma after the balancing formula instead of before it. +""" + +from __future__ import annotations + +import asyncio +import re +from typing import Any + +from aioesphomeapi import EntityState, LightInfo, LightState +import pytest + +from .state_utils import InitialStateHelper +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_light_constant_brightness( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test constant_brightness true and false behavior with gamma correction.""" + # Track output values for both lights from log lines + cb_cw_pattern = re.compile(r"(?<!N)CB_CW_OUTPUT:([\d.]+)") + cb_ww_pattern = re.compile(r"(?<!N)CB_WW_OUTPUT:([\d.]+)") + ncb_cw_pattern = re.compile(r"NCB_CW_OUTPUT:([\d.]+)") + ncb_ww_pattern = re.compile(r"NCB_WW_OUTPUT:([\d.]+)") + + latest: dict[str, float] = { + "cb_cw": 0.0, + "cb_ww": 0.0, + "ncb_cw": 0.0, + "ncb_ww": 0.0, + } + + def on_log_line(line: str) -> None: + for pattern, key in [ + (cb_cw_pattern, "cb_cw"), + (cb_ww_pattern, "cb_ww"), + (ncb_cw_pattern, "ncb_cw"), + (ncb_ww_pattern, "ncb_ww"), + ]: + match = pattern.search(line) + if match: + latest[key] = float(match.group(1)) + + loop = asyncio.get_running_loop() + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + lights = [e for e in entities if isinstance(e, LightInfo)] + cb_light = next(e for e in lights if e.object_id.endswith("cb_light")) + ncb_light = next(e for e in lights if e.object_id.endswith("ncb_light")) + + # Use InitialStateHelper to wait for initial state broadcast + initial_state_helper = InitialStateHelper(entities) + + # Track state changes per light key + state_futures: dict[int, asyncio.Future[EntityState]] = {} + + def on_state(state: EntityState) -> None: + if isinstance(state, LightState) and state.key in state_futures: + future = state_futures[state.key] + if not future.done(): + future.set_result(state) + + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + async def send_and_wait( + light_key: int, timeout: float = 5.0, **kwargs: Any + ) -> LightState: + """Send a light command and wait for the state response.""" + state_futures[light_key] = loop.create_future() + client.light_command(key=light_key, **kwargs) + try: + return await asyncio.wait_for(state_futures[light_key], timeout=timeout) + except TimeoutError: + pytest.fail(f"Timeout waiting for light state after command: {kwargs}") + + # --- Test constant_brightness: true --- + + # Turn on CB light at full brightness + await send_and_wait( + cb_light.key, + state=True, + brightness=1.0, + color_temperature=153.0, + transition_length=0, + ) + + test_mireds = [ + 153.0, # Pure cold white + 200.0, # Mostly cold + 280.0, # Mixed + 326.5, # Midpoint + 400.0, # Mostly warm + 500.0, # Pure warm white + ] + + cb_totals: list[tuple[float, float, float]] = [] + for mireds in test_mireds: + await send_and_wait( + cb_light.key, color_temperature=mireds, transition_length=0 + ) + cb_totals.append((mireds, latest["cb_cw"], latest["cb_ww"])) + + # All totals should be approximately equal (constant brightness) + reference_total = next((cw + ww for _, cw, ww in cb_totals if cw + ww > 0), 0) + assert reference_total > 0, ( + f"Reference total power is zero, CB light outputs not working. " + f"Values: {cb_totals}" + ) + + for mireds, cw, ww in cb_totals: + total = cw + ww + assert total == pytest.approx(reference_total, rel=0.05), ( + f"constant_brightness: Total power at {mireds} mireds " + f"({total:.4f}) differs from reference ({reference_total:.4f}) " + f"by more than 5%. CW={cw:.4f}, WW={ww:.4f}. " + f"All values: {cb_totals}" + ) + + # --- Test constant_brightness: false --- + + # Turn on NCB light at full brightness + await send_and_wait( + ncb_light.key, + state=True, + brightness=1.0, + color_temperature=153.0, + transition_length=0, + ) + + ncb_totals: list[tuple[float, float, float]] = [] + for mireds in test_mireds: + await send_and_wait( + ncb_light.key, color_temperature=mireds, transition_length=0 + ) + ncb_totals.append((mireds, latest["ncb_cw"], latest["ncb_ww"])) + + extreme_cw = ncb_totals[0] # 153 mireds - pure cold + extreme_ww = ncb_totals[-1] # 500 mireds - pure warm + midpoint = ncb_totals[3] # 326.5 mireds - midpoint + + # At pure cold white, WW should be ~0 + assert extreme_cw[2] == pytest.approx(0.0, abs=0.01), ( + f"Pure cold white should have WW~0, got WW={extreme_cw[2]:.4f}" + ) + # At pure warm white, CW should be ~0 + assert extreme_ww[1] == pytest.approx(0.0, abs=0.01), ( + f"Pure warm white should have CW~0, got CW={extreme_ww[1]:.4f}" + ) + + # At midpoint, both channels should be non-zero + assert midpoint[1] > 0.05, f"Midpoint CW should be >0.05, got {midpoint[1]:.4f}" + assert midpoint[2] > 0.05, f"Midpoint WW should be >0.05, got {midpoint[2]:.4f}" + + # Total power at midpoint should be higher than at the extremes + midpoint_total = midpoint[1] + midpoint[2] + extreme_cw_total = extreme_cw[1] + extreme_cw[2] + extreme_ww_total = extreme_ww[1] + extreme_ww[2] + + assert midpoint_total > extreme_cw_total, ( + f"Midpoint total ({midpoint_total:.4f}) should be > pure CW total " + f"({extreme_cw_total:.4f}). All values: {ncb_totals}" + ) + assert midpoint_total > extreme_ww_total, ( + f"Midpoint total ({midpoint_total:.4f}) should be > pure WW total " + f"({extreme_ww_total:.4f}). All values: {ncb_totals}" + ) From ca0523b86ca11cf7eac5bb86c1ff762279371aff Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:16:46 -1000 Subject: [PATCH 1595/2030] [sht4x] Fix heater causing measurement jitter (#15030) --- esphome/components/sht4x/sht4x.cpp | 40 ++++++++++++++++-------------- esphome/components/sht4x/sht4x.h | 3 ++- tests/components/sht4x/common.yaml | 4 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index bf23e42e66..43c2436a56 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -9,14 +9,12 @@ static const char *const TAG = "sht4x"; static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0}; static const uint8_t SERIAL_NUMBER_COMMAND = 0x89; -void SHT4XComponent::start_heater_() { - uint8_t cmd[] = {this->heater_command_}; - - ESP_LOGD(TAG, "Heater turning on"); - if (this->write(cmd, 1) != i2c::ERROR_OK) { - this->status_set_error(LOG_STR("Failed to turn on heater")); - } -} +// Conversion constants from SHT4x datasheet +static constexpr float TEMPERATURE_OFFSET = -45.0f; +static constexpr float TEMPERATURE_SPAN = 175.0f; +static constexpr float HUMIDITY_OFFSET = -6.0f; +static constexpr float HUMIDITY_SPAN = 125.0f; +static constexpr float RAW_MAX = 65535.0f; void SHT4XComponent::read_serial_number_() { uint16_t buffer[2]; @@ -39,8 +37,8 @@ void SHT4XComponent::setup() { this->read_serial_number_(); if (std::isfinite(this->duty_cycle_) && this->duty_cycle_ > 0.0f) { - uint32_t heater_interval = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_); - ESP_LOGD(TAG, "Heater interval: %" PRIu32, heater_interval); + this->heater_interval_ = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_); + ESP_LOGD(TAG, "Heater interval: %" PRIu32, this->heater_interval_); if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) { if (this->heater_time_ == SHT4X_HEATERTIME_LONG) { @@ -62,8 +60,6 @@ void SHT4XComponent::setup() { } } ESP_LOGD(TAG, "Heater command: %x", this->heater_command_); - - this->set_interval(heater_interval, [this]() { this->start_heater_(); }); } } @@ -106,19 +102,27 @@ void SHT4XComponent::update() { // Evaluate and publish measurements if (this->temp_sensor_ != nullptr) { // Temp is contained in the first result word - float sensor_value_temp = buffer[0]; - float temp = -45 + 175 * sensor_value_temp / 65535; - + float temp = TEMPERATURE_OFFSET + TEMPERATURE_SPAN * static_cast<float>(buffer[0]) / RAW_MAX; this->temp_sensor_->publish_state(temp); } if (this->humidity_sensor_ != nullptr) { // Relative humidity is in the second result word - float sensor_value_rh = buffer[1]; - float rh = -6 + 125 * sensor_value_rh / 65535; - + float rh = HUMIDITY_OFFSET + HUMIDITY_SPAN * static_cast<float>(buffer[1]) / RAW_MAX; this->humidity_sensor_->publish_state(rh); } + + // Fire heater after measurement to maximize cooldown time before the next reading. + // The heater command produces a measurement that we don't need (datasheet 4.9). + if (this->heater_interval_ > 0) { + uint32_t now = millis(); + if (now - this->last_heater_millis_ >= this->heater_interval_) { + ESP_LOGD(TAG, "Heater turning on"); + if (this->write_command(this->heater_command_)) { + this->last_heater_millis_ = now; + } + } + } }); } diff --git a/esphome/components/sht4x/sht4x.h b/esphome/components/sht4x/sht4x.h index aec0f3d7f8..51f473fe3f 100644 --- a/esphome/components/sht4x/sht4x.h +++ b/esphome/components/sht4x/sht4x.h @@ -35,9 +35,10 @@ class SHT4XComponent : public PollingComponent, public sensirion_common::Sensiri SHT4XHEATERTIME heater_time_; float duty_cycle_; - void start_heater_(); void read_serial_number_(); uint8_t heater_command_; + uint32_t heater_interval_{0}; + uint32_t last_heater_millis_{0}; uint32_t serial_number_; sensor::Sensor *temp_sensor_{nullptr}; diff --git a/tests/components/sht4x/common.yaml b/tests/components/sht4x/common.yaml index 50d5ad8ca4..bec192d6db 100644 --- a/tests/components/sht4x/common.yaml +++ b/tests/components/sht4x/common.yaml @@ -6,4 +6,8 @@ sensor: humidity: name: SHT4X Humidity address: 0x44 + precision: High + heater_max_duty: 0.02 + heater_power: High + heater_time: Long update_interval: 15s From ba4be2a904b18d0509b9768aa5076bb9e218b8fa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:17:59 -1000 Subject: [PATCH 1596/2030] [uart] Fix RTL87xx compilation failure due to SUCCESS macro collision (#15054) --- esphome/components/uart/uart_component.h | 5 +++++ tests/components/uart/test.rtl87xx-ard.yaml | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/components/uart/test.rtl87xx-ard.yaml diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index ee2b006039..00a4c78878 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -30,12 +30,17 @@ enum UARTDirection { const LogString *parity_to_str(UARTParityOptions parity); /// Result of a flush() call. +// Some vendor SDKs (e.g., Realtek) define SUCCESS as a macro. +// Save and restore around the enum to avoid collisions with our scoped enum value. +#pragma push_macro("SUCCESS") +#undef SUCCESS enum class FlushResult { SUCCESS, ///< Confirmed: all bytes left the TX FIFO. TIMEOUT, ///< Confirmed: timed out before TX completed. FAILED, ///< Confirmed: driver or hardware error. ASSUMED_SUCCESS, ///< Platform cannot report result; success is assumed. }; +#pragma pop_macro("SUCCESS") class UARTComponent { public: diff --git a/tests/components/uart/test.rtl87xx-ard.yaml b/tests/components/uart/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..414bf1f14d --- /dev/null +++ b/tests/components/uart/test.rtl87xx-ard.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_id + tx_pin: PA23 + rx_pin: PA18 + baud_rate: 9600 + data_bits: 8 + parity: NONE + stop_bits: 1 + +switch: + - platform: uart + name: "UART Switch" + uart_id: uart_id + data: [0x01, 0x02, 0x03] From 6a77b8b1f457fb5d2be9e8863b82e0328c8b4b29 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:19:28 -1000 Subject: [PATCH 1597/2030] [light] Fix gamma LUT quantizing small brightness to zero (#15060) --- esphome/components/light/__init__.py | 28 +++-- tests/unit_tests/components/light/__init__.py | 0 .../components/light/test_gamma_table.py | 117 ++++++++++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 tests/unit_tests/components/light/__init__.py create mode 100644 tests/unit_tests/components/light/test_gamma_table.py diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 4403281116..64452e4282 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -81,18 +81,32 @@ def _get_data() -> LightData: return CORE.data[DOMAIN] +def generate_gamma_table(gamma_correct: float) -> list[HexInt]: + """Generate a 256-entry uint16 gamma lookup table. + + For gamma > 0, non-zero indices are clamped to a minimum of 1 to preserve + the invariant that non-zero input always produces non-zero output. Without + this, small brightness values (e.g. 1%) get quantized to exactly 0.0, + which breaks zero_means_zero logic in FloatOutput. + """ + if gamma_correct > 0: + return [ + HexInt( + max(1, min(65535, int(round((i / 255.0) ** gamma_correct * 65535)))) + if i > 0 + else HexInt(0) + ) + for i in range(256) + ] + return [HexInt(int(round(i / 255.0 * 65535))) for i in range(256)] + + def _get_or_create_gamma_table(gamma_correct): data = _get_data() if gamma_correct in data.gamma_tables: return data.gamma_tables[gamma_correct] - if gamma_correct > 0: - forward = [ - HexInt(min(65535, int(round((i / 255.0) ** gamma_correct * 65535)))) - for i in range(256) - ] - else: - forward = [HexInt(int(round(i / 255.0 * 65535))) for i in range(256)] + forward = generate_gamma_table(gamma_correct) gamma_str = f"{gamma_correct}".replace(".", "_") fwd_id = ID(f"gamma_{gamma_str}_fwd", is_declaration=True, type=cg.uint16) diff --git a/tests/unit_tests/components/light/__init__.py b/tests/unit_tests/components/light/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/unit_tests/components/light/test_gamma_table.py b/tests/unit_tests/components/light/test_gamma_table.py new file mode 100644 index 0000000000..a302a355dc --- /dev/null +++ b/tests/unit_tests/components/light/test_gamma_table.py @@ -0,0 +1,117 @@ +"""Tests for the gamma LUT table generation.""" + +import pytest + +from esphome.components.light import generate_gamma_table + + +def _simulate_gamma_correct_lut(table: list[int], value: float) -> float: + """Simulate the C++ gamma_correct_lut interpolation from light_state.cpp.""" + if value <= 0.0: + return 0.0 + if value >= 1.0: + return 1.0 + scaled = value * 255.0 + idx = int(scaled) + if idx >= 255: + return table[255] / 65535.0 + frac = scaled - idx + a = float(table[idx]) + b = float(table[idx + 1]) + return (a + frac * (b - a)) / 65535.0 + + +def test_table_length() -> None: + """Table must always have exactly 256 entries.""" + table = generate_gamma_table(2.8) + assert len(table) == 256 + + +def test_index_zero_is_zero() -> None: + """Index 0 must be 0 so true off remains off.""" + for gamma in (1.0, 2.0, 2.2, 2.8, 3.0): + table = generate_gamma_table(gamma) + assert table[0] == 0, f"gamma={gamma}" + + +def test_index_255_is_max() -> None: + """Index 255 must be 65535 (full on).""" + for gamma in (1.0, 2.0, 2.2, 2.8, 3.0): + table = generate_gamma_table(gamma) + assert table[255] == 65535, f"gamma={gamma}" + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_nonzero_indices_are_nonzero(gamma: float) -> None: + """All indices > 0 must produce non-zero values. + + This prevents zero_means_zero breakage: non-zero input must always + produce non-zero output so FloatOutput applies min_power scaling. + """ + table = generate_gamma_table(gamma) + for i in range(1, 256): + assert table[i] >= 1, f"gamma={gamma}, index {i}: got {table[i]}" + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_table_monotonically_nondecreasing(gamma: float) -> None: + """The gamma table must be monotonically non-decreasing.""" + table = generate_gamma_table(gamma) + for i in range(1, 256): + assert table[i] >= table[i - 1], ( + f"gamma={gamma}: table[{i}]={table[i]} < table[{i - 1}]={table[i - 1]}" + ) + + +def test_linear_gamma() -> None: + """With gamma=0 (linear), table should be evenly spaced.""" + table = generate_gamma_table(0) + assert table[0] == 0 + assert table[128] == round(128 / 255.0 * 65535) + assert table[255] == 65535 + + +@pytest.mark.parametrize("brightness", [0.01, 0.005, 0.001, 1 / 255]) +def test_small_brightness_nonzero_after_lut(brightness: float) -> None: + """Small but non-zero brightness must produce non-zero output through the LUT. + + Regression test for #15055: with zero_means_zero=true, a gamma-corrected + value of exactly 0.0 causes FloatOutput to skip min_power scaling, turning + the LED off instead of to minimum brightness. + """ + table = generate_gamma_table(2.8) + result = _simulate_gamma_correct_lut(table, brightness) + assert result > 0.0, ( + f"brightness={brightness}: gamma LUT returned 0.0, would break zero_means_zero" + ) + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_small_brightness_nonzero_all_gammas(gamma: float) -> None: + """1% brightness must be non-zero for all common gamma values.""" + table = generate_gamma_table(gamma) + result = _simulate_gamma_correct_lut(table, 0.01) + assert result > 0.0, f"gamma={gamma}: 1% brightness returned 0.0" + + +def test_lut_zero_returns_zero() -> None: + """LUT with input 0.0 must return 0.0.""" + table = generate_gamma_table(2.8) + assert _simulate_gamma_correct_lut(table, 0.0) == 0.0 + + +def test_lut_one_returns_one() -> None: + """LUT with input 1.0 must return 1.0.""" + table = generate_gamma_table(2.8) + assert _simulate_gamma_correct_lut(table, 1.0) == 1.0 + + +def test_lut_output_monotonically_nondecreasing() -> None: + """LUT output must be monotonically non-decreasing across the full range.""" + table = generate_gamma_table(2.8) + prev = 0.0 + for i in range(1001): + value = i / 1000.0 + result = _simulate_gamma_correct_lut(table, value) + assert result >= prev, f"value={value}: result {result} < previous {prev}" + prev = result From 12b10d8b89721d4e58ccef224eec4c7c9f37ea6c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:19:46 -0400 Subject: [PATCH 1598/2030] [ultrasonic] Fix ISR edge detection with debounce and trigger filtering (#15014) --- .../ultrasonic/ultrasonic_sensor.cpp | 29 +++++++++---------- .../components/ultrasonic/ultrasonic_sensor.h | 3 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index d3f7e69444..a354b198b4 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -6,11 +6,17 @@ namespace esphome::ultrasonic { static const char *const TAG = "ultrasonic.sensor"; +static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us of each other (noise filtering) +static constexpr uint32_t START_DELAY_US = 100; // Ignore edges within 100us of trigger (filters bleed-through) static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { uint32_t now = micros(); - if (arg->echo_pin_isr.digital_read()) { + // Ignore edges after measurement complete or too soon after trigger pulse + if (arg->echo_end || (now - arg->measurement_start_us) <= START_DELAY_US) { + return; + } + if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) { arg->echo_start_us = now; arg->echo_start = true; } else { @@ -21,15 +27,14 @@ void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { void IRAM_ATTR UltrasonicSensorComponent::send_trigger_pulse_() { InterruptLock lock; - this->store_.echo_start_us = 0; - this->store_.echo_end_us = 0; this->store_.echo_start = false; this->store_.echo_end = false; + this->store_.measurement_start_us = micros(); this->trigger_pin_isr_.digital_write(true); delayMicroseconds(this->pulse_time_us_); this->trigger_pin_isr_.digital_write(false); this->measurement_pending_ = true; - this->measurement_start_us_ = micros(); + this->measurement_start_us_ = this->store_.measurement_start_us; } void UltrasonicSensorComponent::setup() { @@ -37,7 +42,6 @@ void UltrasonicSensorComponent::setup() { this->trigger_pin_->digital_write(false); this->trigger_pin_isr_ = this->trigger_pin_->to_isr(); this->echo_pin_->setup(); - this->store_.echo_pin_isr = this->echo_pin_->to_isr(); this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE); } @@ -77,17 +81,10 @@ void UltrasonicSensorComponent::loop() { } if (this->store_.echo_end) { - float result; - if (this->store_.echo_start) { - uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; - ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us", - this->store_.echo_start_us - this->measurement_start_us_, pulse_duration); - result = UltrasonicSensorComponent::us_to_m(pulse_duration); - ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); - } else { - ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str()); - result = NAN; - } + uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; + ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration); + float result = UltrasonicSensorComponent::us_to_m(pulse_duration); + ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); this->publish_state(result); this->measurement_pending_ = false; return; diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index 541f7d2b70..7d333a1b24 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -11,8 +11,7 @@ namespace esphome::ultrasonic { struct UltrasonicSensorStore { static void gpio_intr(UltrasonicSensorStore *arg); - ISRInternalGPIOPin echo_pin_isr; - volatile uint32_t wait_start_us{0}; + volatile uint32_t measurement_start_us{0}; volatile uint32_t echo_start_us{0}; volatile uint32_t echo_end_us{0}; volatile bool echo_start{false}; From c917b8ce06b80f1db580d84c2512cc981dc7e687 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:20:28 -1000 Subject: [PATCH 1599/2030] [logger] Fix race condition in task log buffer initialization (#15071) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/logger/__init__.py | 39 ++++++++++++++++----------- esphome/components/logger/logger.cpp | 20 ++++++-------- esphome/components/logger/logger.h | 5 ++-- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index a5601e6a8f..3da81e12a0 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -331,11 +331,27 @@ async def to_code(config: ConfigType) -> None: CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level tx_buffer_size = config[CONF_TX_BUFFER_SIZE] cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) - log = cg.new_Pvariable( - config[CONF_ID], - baud_rate, - ) - if CORE.is_esp32: + # Determine task log buffer size and define USE_ESPHOME_TASK_LOG_BUFFER early + # so the constructor can allocate the buffer immediately, preventing a race + # where another task logs before the buffer is initialized. + task_log_buffer_size = 0 + if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: + task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] + elif CORE.is_host: + task_log_buffer_size = 64 # Fixed 64 slots for host + if task_log_buffer_size > 0: + cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") + log = cg.new_Pvariable( + config[CONF_ID], + baud_rate, + task_log_buffer_size, + ) + else: + log = cg.new_Pvariable( + config[CONF_ID], + baud_rate, + ) + if CORE.is_esp32 or CORE.is_host: cg.add(log.create_pthread_key()) # set_uart_selection() must be called before pre_setup() because # pre_setup() switches on uart_ to decide which hardware to initialize @@ -364,17 +380,10 @@ async def _late_logger_init(config: ConfigType) -> None: log = await cg.get_variable(config[CONF_ID]) level = config[CONF_LEVEL] baud_rate: int = config[CONF_BAUD_RATE] - if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: - task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] + if CORE.using_zephyr: + task_log_buffer_size = config.get(CONF_TASK_LOG_BUFFER_SIZE, 0) if task_log_buffer_size > 0: - cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") - cg.add(log.init_log_buffer(task_log_buffer_size)) - if CORE.using_zephyr: - zephyr_add_prj_conf("MPSC_PBUF", True) - elif CORE.is_host: - cg.add(log.create_pthread_key()) - cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") - cg.add(log.init_log_buffer(64)) # Fixed 64 slots for host + zephyr_add_prj_conf("MPSC_PBUF", True) # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 497809cd2e..ceacded775 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -152,29 +152,25 @@ inline uint8_t Logger::level_for(const char *tag) { return this->current_level_; } +#ifdef USE_ESPHOME_TASK_LOG_BUFFER +Logger::Logger(uint32_t baud_rate, size_t task_log_buffer_size) : baud_rate_(baud_rate) { +#else Logger::Logger(uint32_t baud_rate) : baud_rate_(baud_rate) { +#endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) this->main_task_ = xTaskGetCurrentTaskHandle(); #elif defined(USE_ZEPHYR) this->main_task_ = k_current_get(); #elif defined(USE_HOST) - this->main_thread_ = pthread_self(); +this->main_thread_ = pthread_self(); #endif -} #ifdef USE_ESPHOME_TASK_LOG_BUFFER -void Logger::init_log_buffer(size_t total_buffer_size) { - // Host uses slot count instead of byte size // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size); - -#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) - // Start with loop disabled when using task buffer - // The loop will be enabled automatically when messages arrive - // Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_() - this->disable_loop_when_buffer_empty_(); + this->log_buffer_ = new logger::TaskLogBuffer(task_log_buffer_size); + // Note: we don't disable loop here because the component isn't registered with App yet. + // The loop self-disables on its first iteration when it finds no messages to process. #endif } -#endif #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void Logger::loop() { diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 8c38cadcbc..c81b8e4e94 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -143,9 +143,10 @@ enum UARTSelection : uint8_t { */ class Logger final : public Component { public: - explicit Logger(uint32_t baud_rate); #ifdef USE_ESPHOME_TASK_LOG_BUFFER - void init_log_buffer(size_t total_buffer_size); + explicit Logger(uint32_t baud_rate, size_t task_log_buffer_size); +#else + explicit Logger(uint32_t baud_rate); #endif #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void loop() override; From 2b6d63fd09a7c4d40385114bd9222037397804da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20K=C3=B6lker?= <jason@koelker.net> Date: Sun, 22 Mar 2026 20:21:08 +0000 Subject: [PATCH 1600/2030] [pmsx003] Keep active-mode reads aligned (#14832) --- esphome/components/pmsx003/pmsx003.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/esphome/components/pmsx003/pmsx003.cpp b/esphome/components/pmsx003/pmsx003.cpp index 114ecf435e..6275ff60c2 100644 --- a/esphome/components/pmsx003/pmsx003.cpp +++ b/esphome/components/pmsx003/pmsx003.cpp @@ -95,10 +95,6 @@ void PMSX003Component::loop() { // Just go ahead and read stuff break; } - } else if (now - this->last_update_ < this->update_interval_) { - // Otherwise just leave the sensor powered up and come back when we hit the update - // time - return; } if (now - this->last_transmission_ >= 500) { @@ -114,10 +110,11 @@ void PMSX003Component::loop() { this->read_byte(&this->data_[this->data_index_]); auto check = this->check_byte_(); if (!check.has_value()) { - // finished - this->parse_data_(); + if (this->update_interval_ > STABILISING_MS || now - this->last_update_ >= this->update_interval_) { + this->parse_data_(); + this->last_update_ = now; + } this->data_index_ = 0; - this->last_update_ = now; } else if (!*check) { // wrong data this->data_index_ = 0; @@ -138,7 +135,7 @@ optional<bool> PMSX003Component::check_byte_() { return true; } - ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, START_CHARACTER_1); + ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, start_char); return false; } From 705d548435d648eda29e044c43d538034df7f98d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 09:39:26 -1000 Subject: [PATCH 1601/2030] Bump aioesphomeapi from 44.5.2 to 44.6.0 (#14927) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index da95dd5a13..f8f60f1932 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.5.2 +aioesphomeapi==44.6.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 99d968f80a5057ec653e9fba8a55f2aa9ec5ee14 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 18 Mar 2026 14:06:41 -1000 Subject: [PATCH 1602/2030] [http_request] Prevent double update task launch (#14910) --- .../components/http_request/update/http_request_update.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/http_request/update/http_request_update.cpp b/esphome/components/http_request/update/http_request_update.cpp index a15dc61675..1c52a28105 100644 --- a/esphome/components/http_request/update/http_request_update.cpp +++ b/esphome/components/http_request/update/http_request_update.cpp @@ -74,6 +74,10 @@ void HttpRequestUpdate::update() { } this->cancel_interval(INITIAL_CHECK_INTERVAL_ID); #ifdef USE_ESP32 + if (this->update_task_handle_ != nullptr) { + ESP_LOGW(TAG, "Update check already in progress"); + return; + } xTaskCreate(HttpRequestUpdate::update_task, "update_task", 8192, (void *) this, 1, &this->update_task_handle_); #else this->update_task(this); @@ -204,6 +208,9 @@ defer: // both success and error paths to avoid multiple std::function instantiations. // Lambda captures only 2 pointers (8 bytes) — fits in std::function SBO on supported toolchains. this_update->defer([this_update, result]() { +#ifdef USE_ESP32 + this_update->update_task_handle_ = nullptr; +#endif if (result->error_str != nullptr) { this_update->status_set_error(result->error_str); delete result; From 8af0991590f27f870d3544e0b2bd6798380d9564 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 20:10:42 -0400 Subject: [PATCH 1603/2030] [ble_client] Fix RSSI sensor reporting same value for all clients (#14939) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/ble_client/sensor/ble_rssi_sensor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp b/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp index dc032a7a98..715298e592 100644 --- a/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp +++ b/esphome/components/ble_client/sensor/ble_rssi_sensor.cpp @@ -47,6 +47,8 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl switch (event) { // server response on RSSI request: case ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT: + if (!this->parent()->check_addr(param->read_rssi_cmpl.remote_addr)) + return; if (param->read_rssi_cmpl.status == ESP_BT_STATUS_SUCCESS) { int8_t rssi = param->read_rssi_cmpl.rssi; ESP_LOGI(TAG, "ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT RSSI: %d", rssi); From 729d3d4bc22718d0116f3dd1d47eea7d12362ef9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 18 Mar 2026 21:23:47 -0400 Subject: [PATCH 1604/2030] [openthread] Guard InstanceLock against uninitialized semaphore (#14940) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/openthread/openthread.h | 4 ++++ .../components/openthread/openthread_esp.cpp | 22 ++++++++++++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index 75d8fe11fd..bd10774fcf 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -11,6 +11,7 @@ #include <openthread/instance.h> #include <openthread/thread.h> +#include <atomic> #include <optional> #include <vector> @@ -28,6 +29,8 @@ class OpenThreadComponent : public Component { float get_setup_priority() const override { return setup_priority::WIFI; } bool is_connected() const { return this->connected_; } + /// Returns true once esp_openthread_init() has completed and the OT lock is usable. + bool is_lock_initialized() const { return this->lock_initialized_; } network::IPAddresses get_ip_addresses(); std::optional<otIp6Address> get_omr_address(); void ot_main(); @@ -51,6 +54,7 @@ class OpenThreadComponent : public Component { uint32_t poll_period_{0}; #endif std::optional<int8_t> output_power_{}; + std::atomic<bool> lock_initialized_{false}; bool teardown_started_{false}; bool teardown_complete_{false}; bool connected_{false}; diff --git a/esphome/components/openthread/openthread_esp.cpp b/esphome/components/openthread/openthread_esp.cpp index 9cc9223b52..27712bd86a 100644 --- a/esphome/components/openthread/openthread_esp.cpp +++ b/esphome/components/openthread/openthread_esp.cpp @@ -8,6 +8,7 @@ #include "esp_openthread_lock.h" #include "esp_task_wdt.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -81,6 +82,9 @@ void OpenThreadComponent::ot_main() { // Initialize the OpenThread stack // otLoggingSetLevel(OT_LOG_LEVEL_DEBG); ESP_ERROR_CHECK(esp_openthread_init(&config)); + // Mark lock as initialized so InstanceLock callers know it's safe to acquire. + // Must be set after esp_openthread_init() which creates the internal semaphore. + this->lock_initialized_ = true; // Fetch OT instance once to avoid repeated call into OT stack otInstance *instance = esp_openthread_get_instance(); @@ -180,7 +184,8 @@ void OpenThreadComponent::ot_main() { esp_openthread_launch_mainloop(); - // Clean up + // Clean up - reset lock flag before deinit destroys the semaphore + this->lock_initialized_ = false; esp_openthread_deinit(); esp_openthread_netif_glue_deinit(); esp_netif_destroy(openthread_netif); @@ -210,6 +215,9 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() { otInstance *OpenThreadComponent::get_openthread_instance_() { return esp_openthread_get_instance(); } std::optional<InstanceLock> InstanceLock::try_acquire(int delay) { + if (!global_openthread_component->is_lock_initialized()) { + return {}; + } if (esp_openthread_lock_acquire(delay)) { return InstanceLock(); } @@ -217,6 +225,18 @@ std::optional<InstanceLock> InstanceLock::try_acquire(int delay) { } InstanceLock InstanceLock::acquire() { + // Wait for the lock to be created by ot_main() before attempting to acquire it. + // esp_openthread_lock_acquire() will assert-crash if called before esp_openthread_init(). + constexpr uint32_t lock_init_timeout_ms = 10000; + uint32_t start = millis(); + while (!global_openthread_component->is_lock_initialized()) { + if (millis() - start > lock_init_timeout_ms) { + ESP_LOGE(TAG, "OpenThread lock not initialized after %" PRIu32 "ms, aborting", lock_init_timeout_ms); + abort(); + } + delay(10); + esp_task_wdt_reset(); + } while (!esp_openthread_lock_acquire(100)) { esp_task_wdt_reset(); } From 5cbe9362569e17447c661e2cf5ad9a528b2a7ef7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Mar 2026 23:43:50 -1000 Subject: [PATCH 1605/2030] Bump aioesphomeapi from 44.6.0 to 44.6.1 (#14954) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f8f60f1932..9e2f4efe3e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.6.0 +aioesphomeapi==44.6.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 08cab43548fb7546690cdabd07cda2f7a0c0e74a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 08:44:35 -1000 Subject: [PATCH 1606/2030] [time] Fix lookup of top-level IANA timezone keys like UTC and GMT (#14952) --- esphome/components/time/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 7ffa408db9..9821046a73 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -59,15 +59,20 @@ _DST_RULE_TYPE_MAP = { def _load_tzdata(iana_key: str) -> bytes | None: # From https://tzdata.readthedocs.io/en/latest/#examples + if not iana_key: + return None try: package_loc, resource = iana_key.rsplit("/", 1) except ValueError: - return None - package = "tzdata.zoneinfo." + package_loc.replace("/", ".") + # Handle top-level timezone entries like "UTC", "GMT" + package = "tzdata.zoneinfo" + resource = iana_key + else: + package = "tzdata.zoneinfo." + package_loc.replace("/", ".") try: return (resources.files(package) / resource).read_bytes() - except (FileNotFoundError, ModuleNotFoundError): + except (FileNotFoundError, ModuleNotFoundError, IsADirectoryError): return None From daf3502e1527dde0a919f39898ca9cc61849dc8b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 14:11:49 -1000 Subject: [PATCH 1607/2030] [logger] Fix ESP8266 crash with VERY_VERBOSE log level (#14980) --- esphome/components/logger/__init__.py | 29 ++++++++++++++++++--------- esphome/core/config.py | 4 +++- esphome/coroutine.py | 10 +++++++-- esphome/writer.py | 3 +++ 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 675f9a2ca4..a5601e6a8f 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -56,6 +56,7 @@ from esphome.const import ( PlatformFramework, ) from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority +from esphome.types import ConfigType CODEOWNERS = ["@esphome/core"] logger_ns = cg.esphome_ns.namespace("logger") @@ -323,12 +324,11 @@ CONFIG_SCHEMA = cv.All( ) -@coroutine_with_priority(CoroPriority.DIAGNOSTICS) -async def to_code(config): - baud_rate = config[CONF_BAUD_RATE] +@coroutine_with_priority(CoroPriority.EARLY_INIT) +async def to_code(config: ConfigType) -> None: + baud_rate: int = config[CONF_BAUD_RATE] level = config[CONF_LEVEL] CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level - initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)] tx_buffer_size = config[CONF_TX_BUFFER_SIZE] cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) log = cg.new_Pvariable( @@ -347,10 +347,23 @@ async def to_code(config): HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]] ) ) - # pre_setup() must be called before init_log_buffer() because - # init_log_buffer() calls disable_loop() which may log at VV level, - # and global_logger must be set before any logging occurs. + # pre_setup() sets global_logger and must run before any other code + # that may call ESP_LOG* (e.g. setup_preferences contains ESP_LOGVV). cg.add(log.pre_setup()) + initial_level = LOG_LEVELS[config.get(CONF_INITIAL_LEVEL, level)] + cg.add(log.set_log_level(initial_level)) + + # Schedule the rest of logger setup at DIAGNOSTICS priority, after + # Application is constructed (CORE priority) but before most components. + CORE.add_job(_late_logger_init, config) + + +@coroutine_with_priority(CoroPriority.DIAGNOSTICS) +async def _late_logger_init(config: ConfigType) -> None: + """Finish logger setup after Application is constructed.""" + log = await cg.get_variable(config[CONF_ID]) + level = config[CONF_LEVEL] + baud_rate: int = config[CONF_BAUD_RATE] if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] if task_log_buffer_size > 0: @@ -363,8 +376,6 @@ async def to_code(config): cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") cg.add(log.init_log_buffer(64)) # Fixed 64 slots for host - cg.add(log.set_log_level(initial_level)) - # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] if logs_config or config[CONF_RUNTIME_TAG_LEVELS]: diff --git a/esphome/core/config.py b/esphome/core/config.py index d4a839cb79..bdfb1cc417 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -587,7 +587,9 @@ async def _add_looping_components() -> None: @coroutine_with_priority(CoroPriority.CORE) async def to_code(config: ConfigType) -> None: - cg.add_global(cg.global_ns.namespace("esphome").using) + # using namespace esphome is hardcoded in writer.py to guarantee it + # precedes all variable declarations regardless of coroutine priority. + # These can be used by user lambdas, put them to default scope cg.add_global(cg.RawExpression("using std::isnan")) cg.add_global(cg.RawExpression("using std::min")) diff --git a/esphome/coroutine.py b/esphome/coroutine.py index f5d512e510..3ce94cc979 100644 --- a/esphome/coroutine.py +++ b/esphome/coroutine.py @@ -63,7 +63,13 @@ class CoroPriority(enum.IntEnum): resolution during code generation. """ - # Platform initialization - must run first + # Early init - runs before platform init and before Application exists. + # Currently used only to connect logging so ESP_LOG* calls work + # immediately in all subsequent phases. + # Examples: logger (1100) + EARLY_INIT = 1100 + + # Platform initialization # Examples: esp32, esp8266, rp2040 PLATFORM = 1000 @@ -83,7 +89,7 @@ class CoroPriority(enum.IntEnum): CORE = 100 # Diagnostic and debugging systems - # Examples: logger (90) + # Examples: debug component (90) DIAGNOSTICS = 90 # Status and monitoring systems diff --git a/esphome/writer.py b/esphome/writer.py index fd4c811fb3..69a35d00e3 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -381,7 +381,10 @@ def write_cpp(code_s): code_format = CPP_BASE_FORMAT copy_src_tree() + # using namespace esphome must precede all variable declarations since + # codegen types assume this namespace is in scope (esphome_ns = global_ns). global_s = '#include "esphome.h"\n' + global_s += "using namespace esphome;\n" global_s += CORE.cpp_global_section full_file = f"{code_format[0] + CPP_INCLUDE_BEGIN}\n{global_s}{CPP_INCLUDE_END}" From 08187a01b1de0897a9e42f7bf9b4eb5e577c5275 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:39:10 +1000 Subject: [PATCH 1608/2030] [sdl] Fix get_width()/height() when rotation used (#14950) --- esphome/components/sdl/sdl_esphome.cpp | 37 ++++++++++++++++++++++++++ esphome/components/sdl/sdl_esphome.h | 4 +-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/esphome/components/sdl/sdl_esphome.cpp b/esphome/components/sdl/sdl_esphome.cpp index f235e4e68c..74ca2ce39a 100644 --- a/esphome/components/sdl/sdl_esphome.cpp +++ b/esphome/components/sdl/sdl_esphome.cpp @@ -5,6 +5,30 @@ namespace esphome { namespace sdl { +int Sdl::get_width() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + return this->get_height_internal(); + case display::DISPLAY_ROTATION_0_DEGREES: + case display::DISPLAY_ROTATION_180_DEGREES: + default: + return this->get_width_internal(); + } +} + +int Sdl::get_height() { + switch (this->rotation_) { + case display::DISPLAY_ROTATION_0_DEGREES: + case display::DISPLAY_ROTATION_180_DEGREES: + return this->get_height_internal(); + case display::DISPLAY_ROTATION_90_DEGREES: + case display::DISPLAY_ROTATION_270_DEGREES: + default: + return this->get_width_internal(); + } +} + void Sdl::setup() { SDL_Init(SDL_INIT_VIDEO); this->window_ = SDL_CreateWindow(App.get_name().c_str(), this->pos_x_, this->pos_y_, this->width_, this->height_, @@ -49,6 +73,19 @@ void Sdl::draw_pixel_at(int x, int y, Color color) { if (!this->get_clipping().inside(x, y)) return; + if (this->rotation_ == display::DISPLAY_ROTATION_180_DEGREES) { + x = this->width_ - x - 1; + y = this->height_ - y - 1; + } else if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES) { + auto tmp = x; + x = this->width_ - y - 1; + y = tmp; + } else if (this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) { + auto tmp = y; + y = this->height_ - x - 1; + x = tmp; + } + SDL_Rect rect{x, y, 1, 1}; auto data = (display::ColorUtil::color_to_565(color, display::COLOR_ORDER_RGB)); SDL_UpdateTexture(this->texture_, &rect, &data, 2); diff --git a/esphome/components/sdl/sdl_esphome.h b/esphome/components/sdl/sdl_esphome.h index bf5fde1428..968434a04f 100644 --- a/esphome/components/sdl/sdl_esphome.h +++ b/esphome/components/sdl/sdl_esphome.h @@ -33,8 +33,8 @@ class Sdl : public display::Display { this->pos_x_ = pos_x; this->pos_y_ = pos_y; } - int get_width() override { return this->width_; } - int get_height() override { return this->height_; } + int get_width() override; + int get_height() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } void dump_config() override { LOG_DISPLAY("", "SDL", this); } void add_key_listener(int32_t keycode, std::function<void(bool)> &&callback) { From d4f7cb984cdc2510a676f65bc5ca7f70f5eba903 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 19 Mar 2026 20:56:51 -1000 Subject: [PATCH 1609/2030] [uart] Fix UART0 default pin IOMUX loopback on ESP32 (#14978) --- .../uart/uart_component_esp_idf.cpp | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 47ddf1a38d..8168e49805 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -7,7 +7,9 @@ #include "esphome/core/log.h" #include "esphome/core/gpio.h" #include "driver/gpio.h" +#include "esp_private/gpio.h" #include "soc/gpio_num.h" +#include "soc/uart_pins.h" #ifdef USE_UART_WAKE_LOOP_ON_RX #include "esphome/core/application.h" @@ -21,6 +23,20 @@ namespace esphome::uart { static const char *const TAG = "uart.idf"; +/// Check if a pin number matches one of the default UART0 GPIO pins. +/// These pins may have residual IOMUX state from the ROM bootloader that +/// must be cleared before UART reconfiguration. +/// +/// ESP-IDF's uart_set_pin() has an asymmetry: when routing TX via GPIO matrix, +/// it calls gpio_func_sel(PIN_FUNC_GPIO) to clear IOMUX, but for RX it only +/// calls gpio_input_enable() which does NOT clear the IOMUX function select. +/// If a default UART0 TX pin (configured as TX via IOMUX during boot) is later +/// reassigned as RX via GPIO matrix, the old IOMUX TX function remains active, +/// causing TX data to loop back into RX on the same pin. +static constexpr bool is_default_uart0_pin(int8_t pin_num) { + return pin_num == U0TXD_GPIO_NUM || pin_num == U0RXD_GPIO_NUM; +} + uart_config_t IDFUARTComponent::get_config_() { uart_parity_t parity = UART_PARITY_DISABLE; if (this->parity_ == UART_CONFIG_PARITY_EVEN) { @@ -131,6 +147,19 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; + int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; + int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; + + // Clear residual IOMUX function on UART0 default pins left by the ROM bootloader. + // See is_default_uart0_pin() comment for details on the ESP-IDF uart_set_pin() bug. + if (is_default_uart0_pin(tx)) { + gpio_func_sel(static_cast<gpio_num_t>(tx), PIN_FUNC_GPIO); + } + if (is_default_uart0_pin(rx)) { + gpio_func_sel(static_cast<gpio_num_t>(rx), PIN_FUNC_GPIO); + } + auto setup_pin_if_needed = [](InternalGPIOPin *pin) { if (!pin) { return; @@ -146,10 +175,6 @@ void IDFUARTComponent::load_settings(bool dump_config) { setup_pin_if_needed(this->tx_pin_); } - int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; - int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; - int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; - uint32_t invert = 0; if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) { invert |= UART_SIGNAL_TXD_INV; From 0297260a5773d38a2a65ade6cf35333f9aff09f4 Mon Sep 17 00:00:00 2001 From: Keith Roehrenbeck <kroehre@users.noreply.github.com> Date: Fri, 20 Mar 2026 15:11:57 -0500 Subject: [PATCH 1610/2030] [ld2450] Fix zone target counts including untracked ghost targets (#15026) --- esphome/components/ld2450/ld2450.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index f9701cbdf6..1946831ca8 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -534,10 +534,11 @@ void LD2450Component::handle_periodic_data_() { } #endif - // Store target info for zone target count - this->target_info_[index].x = tx; - this->target_info_[index].y = ty; - this->target_info_[index].is_moving = is_moving; + // Store target info for zone target count. Zero out untracked targets (td==0) + // so stale coordinates don't produce ghost counts in count_targets_in_zone_(). + this->target_info_[index].x = (td > 0) ? tx : 0; + this->target_info_[index].y = (td > 0) ? ty : 0; + this->target_info_[index].is_moving = (td > 0) && is_moving; } // End loop thru targets From 28e8250b69e7ae9662e166a6bcf69085f5e3d48f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Mar 2026 11:10:40 -1000 Subject: [PATCH 1611/2030] Bump aioesphomeapi from 44.6.1 to 44.6.2 (#15027) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9e2f4efe3e..10e56c3b49 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.6.1 +aioesphomeapi==44.6.2 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 12eed0d38407c77c70179b2dcbb9c969c06a79c3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 12:06:23 -1000 Subject: [PATCH 1612/2030] [api] Increase noise handshake timeout to 60s for slow WiFi environments (#15022) --- esphome/components/api/api_connection.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index dea3ba5460..d97ef97762 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -64,7 +64,11 @@ static constexpr uint32_t KEEPALIVE_DISCONNECT_TIMEOUT = (KEEPALIVE_TIMEOUT_MS * // A stalled handshake from a buggy client or network glitch holds a connection // slot, which can prevent legitimate clients from reconnecting. Also hardens // against the less likely case of intentional connection slot exhaustion. -static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 15000; +// +// 60s is intentionally high: on ESP8266 with power_save_mode: LIGHT and weak +// WiFi (-70 dBm+), TCP retransmissions push real-world handshake times to +// 28-30s. See https://github.com/esphome/esphome/issues/14999 +static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 60000; static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION); From 3fe84eadef1e5448f6bae7c5f88ac74154e9f6d1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 12:13:49 -1000 Subject: [PATCH 1613/2030] [wifi] Fix ESP8266 power_save_mode mapping (LIGHT/HIGH were swapped) (#15029) --- esphome/components/wifi/wifi_component_esp8266.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 0bf7934878..5514f1c6be 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -92,13 +92,23 @@ bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) { return ret; } bool WiFiComponent::wifi_apply_power_save_() { + // ESP8266 sleep types have confusing names — LIGHT_SLEEP_T is the MORE aggressive mode. + // SDK enum: NONE_SLEEP_T=0, LIGHT_SLEEP_T=1, MODEM_SLEEP_T=2 + // https://github.com/esp8266/Arduino/blob/3.1.2/tools/sdk/include/user_interface.h#L447-L451 + // Arduino ESP32 compat confirms: WIFI_PS_MIN_MODEM=MODEM_SLEEP, WIFI_PS_MAX_MODEM=LIGHT_SLEEP + // https://github.com/esp8266/Arduino/blob/3.1.2/libraries/ESP8266WiFi/src/ESP8266WiFiType.h#L53-L55 sleep_type_t power_save; switch (this->power_save_) { case WIFI_POWER_SAVE_LIGHT: - power_save = LIGHT_SLEEP_T; + // MODEM_SLEEP_T: only the WiFi modem sleeps between DTIM beacons, CPU stays active. + // Matches ESP32's WIFI_PS_MIN_MODEM. + power_save = MODEM_SLEEP_T; break; case WIFI_POWER_SAVE_HIGH: - power_save = MODEM_SLEEP_T; + // LIGHT_SLEEP_T: both WiFi modem AND CPU suspend between DTIM beacons. + // Most aggressive — prevents TCP processing during sleep. Matches ESP32's WIFI_PS_MAX_MODEM. + // See https://github.com/esphome/esphome/issues/14999 + power_save = LIGHT_SLEEP_T; break; case WIFI_POWER_SAVE_NONE: default: From 0bf6e1e8398a3793d5b28b50de20459ec183c132 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 20 Mar 2026 19:53:02 -0400 Subject: [PATCH 1614/2030] [esp32_touch] Fix initial state never published when sensor untouched (#15032) --- esphome/components/esp32_touch/esp32_touch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index e7124ce92f..0d331b29d6 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -360,11 +360,16 @@ void ESP32TouchComponent::loop() { } // Publish initial OFF state for sensors that haven't received events yet + bool all_initial_published = true; for (auto *child : this->children_) { this->publish_initial_state_if_needed_(child, now); + if (!child->initial_state_published_) { + all_initial_published = false; + } } - if (!this->setup_mode_) { + // Only disable loop once all initial states are published + if (!this->setup_mode_ && all_initial_published) { this->disable_loop(); } } From 98b4e1ea15c8badd9e701e225dc59a5de12a3824 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:57:51 -1000 Subject: [PATCH 1615/2030] [web_server] Increase httpd task stack size to prevent stack overflow (#14997) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/web_server_idf/web_server_idf.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index f18570965b..45ee711b1e 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -120,7 +120,10 @@ void AsyncWebServer::begin() { if (this->server_) { this->end(); } + // Default httpd stack is defined by ESP-IDF. Increase to accommodate SerializationBuffer's + // 640-byte stack buffer used by web_server JSON request handlers. httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.stack_size = config.stack_size + 256; config.server_port = this->port_; config.uri_match_fn = [](const char * /*unused*/, const char * /*unused*/, size_t /*unused*/) { return true; }; // Always enable LRU purging to handle socket exhaustion gracefully. From 06cc5a29a733c1078ead4bdf7f6dfc46c5bbe57d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:58:02 -1000 Subject: [PATCH 1616/2030] [core] Add copy() method to StringRef for std::string compatibility (#15028) --- esphome/core/string_ref.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esphome/core/string_ref.h b/esphome/core/string_ref.h index 6047202753..34ba2474b2 100644 --- a/esphome/core/string_ref.h +++ b/esphome/core/string_ref.h @@ -76,6 +76,15 @@ class StringRef { constexpr bool empty() const { return len_ == 0; } constexpr const_reference operator[](size_type pos) const { return *(base_ + pos); } + /// Copy characters to destination buffer (std::string::copy-like, but returns 0 instead of throwing on out-of-range) + size_type copy(char *dest, size_type count, size_type pos = 0) const { + if (pos >= len_) + return 0; + size_type actual = (count > len_ - pos) ? len_ - pos : count; + std::memcpy(dest, base_ + pos, actual); + return actual; + } + std::string str() const { return std::string(base_, len_); } const uint8_t *byte() const { return reinterpret_cast<const uint8_t *>(base_); } From 42da28185456200efbf886da2e4cdad2e670bc97 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 20 Mar 2026 13:58:14 -1000 Subject: [PATCH 1617/2030] [time] Fix timezone_offset() and recalc_timestamp_local() always returning UTC (#14996) --- esphome/core/time.cpp | 16 ++++++---------- esphome/core/time.h | 2 ++ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 73ba0a9be7..6add82e7d1 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -283,19 +283,15 @@ void ESPTime::recalc_timestamp_local() { bool dst_valid = time::is_in_dst(utc_if_dst, tz); bool std_valid = !time::is_in_dst(utc_if_std, tz); - if (dst_valid && std_valid) { - // Ambiguous time (repeated hour during fall-back) - prefer standard time - this->timestamp = utc_if_std; - } else if (dst_valid) { + if (dst_valid && !std_valid) { // Only DST interpretation is valid this->timestamp = utc_if_dst; - } else if (std_valid) { - // Only standard interpretation is valid - this->timestamp = utc_if_std; } else { - // Invalid time (skipped hour during spring-forward) - // libc normalizes forward: 02:30 CST -> 08:30 UTC -> 03:30 CDT - // Using std offset achieves this since the UTC result falls during DST + // All other cases use standard offset: + // - Both valid (ambiguous fall-back repeated hour): prefer standard time + // - Only standard valid: straightforward + // - Neither valid (spring-forward skipped hour): std offset normalizes + // forward to match libc mktime(), e.g. 02:30 CST -> 03:30 CDT this->timestamp = utc_if_std; } #else diff --git a/esphome/core/time.h b/esphome/core/time.h index 874f0db4b4..1716c51ffd 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -1,5 +1,7 @@ #pragma once +#include "esphome/core/defines.h" + #include <cstdint> #include <cstdlib> #include <cstring> From 77264de3f6a17c2f5f0f1bb62bee0f75febab28f Mon Sep 17 00:00:00 2001 From: Samuel Sieb <samuel-github@sieb.net> Date: Sat, 21 Mar 2026 11:13:08 -0700 Subject: [PATCH 1618/2030] [analog_threshhold] add missing header (#15058) --- .../components/analog_threshold/analog_threshold_binary_sensor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/analog_threshold/analog_threshold_binary_sensor.h b/esphome/components/analog_threshold/analog_threshold_binary_sensor.h index 9ea95d8570..dd70768105 100644 --- a/esphome/components/analog_threshold/analog_threshold_binary_sensor.h +++ b/esphome/components/analog_threshold/analog_threshold_binary_sensor.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/components/binary_sensor/binary_sensor.h" #include "esphome/components/sensor/sensor.h" From 2352c732de79b76bb277dc6e1927f73105de12ba Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 21 Mar 2026 15:33:42 -1000 Subject: [PATCH 1619/2030] [mqtt] Rate-limit component resends to prevent task WDT on reconnect (#15061) --- esphome/components/mqtt/mqtt_client.cpp | 17 ++++++++++++++--- esphome/components/mqtt/mqtt_component.h | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.cpp b/esphome/components/mqtt/mqtt_client.cpp index 38daf8f8f6..ab665e2579 100644 --- a/esphome/components/mqtt/mqtt_client.cpp +++ b/esphome/components/mqtt/mqtt_client.cpp @@ -28,6 +28,10 @@ namespace esphome::mqtt { static const char *const TAG = "mqtt"; +// Maximum number of MQTT component resends per loop iteration. +// Limits work to avoid triggering the task watchdog on reconnect. +static constexpr uint8_t MAX_RESENDS_PER_LOOP = 8; + // Disconnect reason strings indexed by MQTTClientDisconnectReason enum (0-8) PROGMEM_STRING_TABLE(MQTTDisconnectReasonStrings, "TCP disconnected", "Unacceptable Protocol Version", "Identifier Rejected", "Server Unavailable", "Malformed Credentials", "Not Authorized", @@ -396,9 +400,16 @@ void MQTTClientComponent::loop() { this->resubscribe_subscriptions_(); // Process pending resends for all MQTT components centrally - // This is more efficient than each component polling in its own loop - for (MQTTComponent *component : this->children_) { - component->process_resend(); + // Limit work per loop iteration to avoid triggering task WDT on reconnect + { + uint8_t resend_count = 0; + for (MQTTComponent *component : this->children_) { + if (component->is_resend_pending()) { + component->process_resend(); + if (++resend_count >= MAX_RESENDS_PER_LOOP) + break; + } + } } } break; diff --git a/esphome/components/mqtt/mqtt_component.h b/esphome/components/mqtt/mqtt_component.h index 2403ef64ea..7983e04870 100644 --- a/esphome/components/mqtt/mqtt_component.h +++ b/esphome/components/mqtt/mqtt_component.h @@ -147,6 +147,9 @@ class MQTTComponent : public Component { /// Internal method for the MQTT client base to schedule a resend of the state on reconnect. void schedule_resend_state(); + /// Check if a resend is pending (called by MQTTClientComponent to rate-limit work) + bool is_resend_pending() const { return this->resend_state_; } + /// Process pending resend if needed (called by MQTTClientComponent) void process_resend(); From b5880df93c6830003b46d106181a26516a4fac07 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:14:52 -1000 Subject: [PATCH 1620/2030] [light] Fix constant_brightness broken by gamma LUT refactor (#15048) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/light/light_color_values.h | 10 + esphome/components/light/light_state.cpp | 47 ++++- .../fixtures/light_constant_brightness.yaml | 57 ++++++ .../test_light_constant_brightness.py | 188 ++++++++++++++++++ 4 files changed, 296 insertions(+), 6 deletions(-) create mode 100644 tests/integration/fixtures/light_constant_brightness.yaml create mode 100644 tests/integration/test_light_constant_brightness.py diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index 3a9ca8c8c2..a2c2dbca46 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -154,6 +154,16 @@ class LightColorValues { } /// Convert these light color values to an CWWW representation with the given parameters. + /// + /// Note on gamma and constant_brightness: This method operates on the raw/internal channel + /// values stored in this object. For cold_white_ and warm_white_ specifically, these + /// may already be gamma-uncorrected when derived from a color_temperature value. + /// For constant_brightness=false, additional gamma for the output can be applied after + /// this method since gamma commutes with simple multiplication. For constant_brightness=true, + /// the caller (LightState::current_values_as_cwww) must apply gamma to the individual + /// channel values BEFORE the balancing formula, because the nonlinear max/sum ratio does + /// not commute with gamma. See LightState::current_values_as_cwww() for the correct + /// implementation. void as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false) const { if (this->color_mode_ & ColorCapability::COLD_WARM_WHITE) { const float cw_level = this->cold_white_; diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index 161092532a..1b736d84f6 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -223,12 +223,11 @@ void LightState::current_values_as_rgbw(float *red, float *green, float *blue, f } void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_rgbww(red, green, blue, cold_white, warm_white, constant_brightness); + this->current_values.as_rgb(red, green, blue); *red = this->gamma_correct_lut(*red); *green = this->gamma_correct_lut(*green); *blue = this->gamma_correct_lut(*blue); - *cold_white = this->gamma_correct_lut(*cold_white); - *warm_white = this->gamma_correct_lut(*warm_white); + this->current_values_as_cwww(cold_white, warm_white, constant_brightness); } void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature, float *white_brightness) { @@ -241,9 +240,45 @@ void LightState::current_values_as_rgbct(float *red, float *green, float *blue, *white_brightness = this->gamma_correct_lut(*white_brightness); } void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) { - this->current_values.as_cwww(cold_white, warm_white, constant_brightness); - *cold_white = this->gamma_correct_lut(*cold_white); - *warm_white = this->gamma_correct_lut(*warm_white); + if (!constant_brightness) { + // Without constant_brightness, gamma commutes with simple multiplication: + // gamma(white_level * cw) = gamma(white_level) * gamma(cw) + // (since gamma(a*b) = (a*b)^g = a^g * b^g = gamma(a) * gamma(b)) + // so applying gamma after is mathematically equivalent and simpler. + this->current_values.as_cwww(cold_white, warm_white, false); + *cold_white = this->gamma_correct_lut(*cold_white); + *warm_white = this->gamma_correct_lut(*warm_white); + return; + } + + // For constant_brightness mode, gamma MUST be applied to the individual + // channel values BEFORE the balancing formula (max/sum ratio), not after. + // + // Why: The cold_white_ and warm_white_ values stored in LightColorValues + // are gamma-uncorrected (see transform_parameters_() which applies + // gamma_uncorrect to the linear CW/WW fractions derived from color + // temperature). Applying gamma_correct here recovers the original linear + // fractions, which the constant_brightness formula then uses to distribute + // power evenly. The max/sum formula ensures cold+warm PWM output sums to + // a constant, keeping total power (and perceived brightness) the same + // across all color temperatures. + // + // Applying gamma AFTER the formula would be incorrect because gamma is + // nonlinear: gamma(a/b) != gamma(a)/gamma(b), so the carefully balanced + // ratio would be distorted, causing a severe brightness dip at mid-range + // color temperatures. + const auto &v = this->current_values; + if (!(v.get_color_mode() & ColorCapability::COLD_WARM_WHITE)) { + *cold_white = *warm_white = 0; + return; + } + + const float cw_level = this->gamma_correct_lut(v.get_cold_white()); + const float ww_level = this->gamma_correct_lut(v.get_warm_white()); + const float white_level = this->gamma_correct_lut(v.get_state() * v.get_brightness()); + const float sum = cw_level > 0 || ww_level > 0 ? cw_level + ww_level : 1; // Don't divide by zero. + *cold_white = white_level * std::max(cw_level, ww_level) * cw_level / sum; + *warm_white = white_level * std::max(cw_level, ww_level) * ww_level / sum; } void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) { auto traits = this->get_traits(); diff --git a/tests/integration/fixtures/light_constant_brightness.yaml b/tests/integration/fixtures/light_constant_brightness.yaml new file mode 100644 index 0000000000..4357a16d58 --- /dev/null +++ b/tests/integration/fixtures/light_constant_brightness.yaml @@ -0,0 +1,57 @@ +esphome: + name: light-cb-test +host: +api: # Port will be automatically injected +logger: + level: DEBUG + +output: + - platform: template + id: cb_cold_white_output + type: float + write_action: + - logger.log: + format: "CB_CW_OUTPUT:%.6f" + args: [state] + - platform: template + id: cb_warm_white_output + type: float + write_action: + - logger.log: + format: "CB_WW_OUTPUT:%.6f" + args: [state] + - platform: template + id: ncb_cold_white_output + type: float + write_action: + - logger.log: + format: "NCB_CW_OUTPUT:%.6f" + args: [state] + - platform: template + id: ncb_warm_white_output + type: float + write_action: + - logger.log: + format: "NCB_WW_OUTPUT:%.6f" + args: [state] + +light: + - platform: cwww + name: "Test CB Light" + id: test_cb_light + cold_white: cb_cold_white_output + warm_white: cb_warm_white_output + cold_white_color_temperature: 6536 K + warm_white_color_temperature: 2000 K + constant_brightness: true + gamma_correct: 2.8 + + - platform: cwww + name: "Test NCB Light" + id: test_ncb_light + cold_white: ncb_cold_white_output + warm_white: ncb_warm_white_output + cold_white_color_temperature: 6536 K + warm_white_color_temperature: 2000 K + constant_brightness: false + gamma_correct: 2.8 diff --git a/tests/integration/test_light_constant_brightness.py b/tests/integration/test_light_constant_brightness.py new file mode 100644 index 0000000000..622dc0e065 --- /dev/null +++ b/tests/integration/test_light_constant_brightness.py @@ -0,0 +1,188 @@ +"""Integration test for constant_brightness with gamma correction. + +Tests both constant_brightness: true and false cwww lights with gamma +correction in a single compilation to verify: +- constant_brightness: true maintains constant total CW+WW power output +- constant_brightness: false correctly varies total power across color temps + +This is a regression test for https://github.com/esphome/esphome/issues/15040 +where the gamma LUT refactor (#14123) broke constant_brightness by applying +gamma after the balancing formula instead of before it. +""" + +from __future__ import annotations + +import asyncio +import re +from typing import Any + +from aioesphomeapi import EntityState, LightInfo, LightState +import pytest + +from .state_utils import InitialStateHelper +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_light_constant_brightness( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test constant_brightness true and false behavior with gamma correction.""" + # Track output values for both lights from log lines + cb_cw_pattern = re.compile(r"(?<!N)CB_CW_OUTPUT:([\d.]+)") + cb_ww_pattern = re.compile(r"(?<!N)CB_WW_OUTPUT:([\d.]+)") + ncb_cw_pattern = re.compile(r"NCB_CW_OUTPUT:([\d.]+)") + ncb_ww_pattern = re.compile(r"NCB_WW_OUTPUT:([\d.]+)") + + latest: dict[str, float] = { + "cb_cw": 0.0, + "cb_ww": 0.0, + "ncb_cw": 0.0, + "ncb_ww": 0.0, + } + + def on_log_line(line: str) -> None: + for pattern, key in [ + (cb_cw_pattern, "cb_cw"), + (cb_ww_pattern, "cb_ww"), + (ncb_cw_pattern, "ncb_cw"), + (ncb_ww_pattern, "ncb_ww"), + ]: + match = pattern.search(line) + if match: + latest[key] = float(match.group(1)) + + loop = asyncio.get_running_loop() + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + entities, _ = await client.list_entities_services() + lights = [e for e in entities if isinstance(e, LightInfo)] + cb_light = next(e for e in lights if e.object_id.endswith("cb_light")) + ncb_light = next(e for e in lights if e.object_id.endswith("ncb_light")) + + # Use InitialStateHelper to wait for initial state broadcast + initial_state_helper = InitialStateHelper(entities) + + # Track state changes per light key + state_futures: dict[int, asyncio.Future[EntityState]] = {} + + def on_state(state: EntityState) -> None: + if isinstance(state, LightState) and state.key in state_futures: + future = state_futures[state.key] + if not future.done(): + future.set_result(state) + + client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) + + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + pytest.fail("Timeout waiting for initial states") + + async def send_and_wait( + light_key: int, timeout: float = 5.0, **kwargs: Any + ) -> LightState: + """Send a light command and wait for the state response.""" + state_futures[light_key] = loop.create_future() + client.light_command(key=light_key, **kwargs) + try: + return await asyncio.wait_for(state_futures[light_key], timeout=timeout) + except TimeoutError: + pytest.fail(f"Timeout waiting for light state after command: {kwargs}") + + # --- Test constant_brightness: true --- + + # Turn on CB light at full brightness + await send_and_wait( + cb_light.key, + state=True, + brightness=1.0, + color_temperature=153.0, + transition_length=0, + ) + + test_mireds = [ + 153.0, # Pure cold white + 200.0, # Mostly cold + 280.0, # Mixed + 326.5, # Midpoint + 400.0, # Mostly warm + 500.0, # Pure warm white + ] + + cb_totals: list[tuple[float, float, float]] = [] + for mireds in test_mireds: + await send_and_wait( + cb_light.key, color_temperature=mireds, transition_length=0 + ) + cb_totals.append((mireds, latest["cb_cw"], latest["cb_ww"])) + + # All totals should be approximately equal (constant brightness) + reference_total = next((cw + ww for _, cw, ww in cb_totals if cw + ww > 0), 0) + assert reference_total > 0, ( + f"Reference total power is zero, CB light outputs not working. " + f"Values: {cb_totals}" + ) + + for mireds, cw, ww in cb_totals: + total = cw + ww + assert total == pytest.approx(reference_total, rel=0.05), ( + f"constant_brightness: Total power at {mireds} mireds " + f"({total:.4f}) differs from reference ({reference_total:.4f}) " + f"by more than 5%. CW={cw:.4f}, WW={ww:.4f}. " + f"All values: {cb_totals}" + ) + + # --- Test constant_brightness: false --- + + # Turn on NCB light at full brightness + await send_and_wait( + ncb_light.key, + state=True, + brightness=1.0, + color_temperature=153.0, + transition_length=0, + ) + + ncb_totals: list[tuple[float, float, float]] = [] + for mireds in test_mireds: + await send_and_wait( + ncb_light.key, color_temperature=mireds, transition_length=0 + ) + ncb_totals.append((mireds, latest["ncb_cw"], latest["ncb_ww"])) + + extreme_cw = ncb_totals[0] # 153 mireds - pure cold + extreme_ww = ncb_totals[-1] # 500 mireds - pure warm + midpoint = ncb_totals[3] # 326.5 mireds - midpoint + + # At pure cold white, WW should be ~0 + assert extreme_cw[2] == pytest.approx(0.0, abs=0.01), ( + f"Pure cold white should have WW~0, got WW={extreme_cw[2]:.4f}" + ) + # At pure warm white, CW should be ~0 + assert extreme_ww[1] == pytest.approx(0.0, abs=0.01), ( + f"Pure warm white should have CW~0, got CW={extreme_ww[1]:.4f}" + ) + + # At midpoint, both channels should be non-zero + assert midpoint[1] > 0.05, f"Midpoint CW should be >0.05, got {midpoint[1]:.4f}" + assert midpoint[2] > 0.05, f"Midpoint WW should be >0.05, got {midpoint[2]:.4f}" + + # Total power at midpoint should be higher than at the extremes + midpoint_total = midpoint[1] + midpoint[2] + extreme_cw_total = extreme_cw[1] + extreme_cw[2] + extreme_ww_total = extreme_ww[1] + extreme_ww[2] + + assert midpoint_total > extreme_cw_total, ( + f"Midpoint total ({midpoint_total:.4f}) should be > pure CW total " + f"({extreme_cw_total:.4f}). All values: {ncb_totals}" + ) + assert midpoint_total > extreme_ww_total, ( + f"Midpoint total ({midpoint_total:.4f}) should be > pure WW total " + f"({extreme_ww_total:.4f}). All values: {ncb_totals}" + ) From 9abc112f7606870ae868954f07547769e0040b83 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:16:46 -1000 Subject: [PATCH 1621/2030] [sht4x] Fix heater causing measurement jitter (#15030) --- esphome/components/sht4x/sht4x.cpp | 40 ++++++++++++++++-------------- esphome/components/sht4x/sht4x.h | 3 ++- tests/components/sht4x/common.yaml | 4 +++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 42be326202..43c2436a56 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -9,14 +9,12 @@ static const char *const TAG = "sht4x"; static const uint8_t MEASURECOMMANDS[] = {0xFD, 0xF6, 0xE0}; static const uint8_t SERIAL_NUMBER_COMMAND = 0x89; -void SHT4XComponent::start_heater_() { - uint8_t cmd[] = {this->heater_command_}; - - ESP_LOGD(TAG, "Heater turning on"); - if (this->write(cmd, 1) != i2c::ERROR_OK) { - this->status_set_error(LOG_STR("Failed to turn on heater")); - } -} +// Conversion constants from SHT4x datasheet +static constexpr float TEMPERATURE_OFFSET = -45.0f; +static constexpr float TEMPERATURE_SPAN = 175.0f; +static constexpr float HUMIDITY_OFFSET = -6.0f; +static constexpr float HUMIDITY_SPAN = 125.0f; +static constexpr float RAW_MAX = 65535.0f; void SHT4XComponent::read_serial_number_() { uint16_t buffer[2]; @@ -39,8 +37,8 @@ void SHT4XComponent::setup() { this->read_serial_number_(); if (std::isfinite(this->duty_cycle_) && this->duty_cycle_ > 0.0f) { - uint32_t heater_interval = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_); - ESP_LOGD(TAG, "Heater interval: %" PRIu32, heater_interval); + this->heater_interval_ = static_cast<uint32_t>(static_cast<uint16_t>(this->heater_time_) / this->duty_cycle_); + ESP_LOGD(TAG, "Heater interval: %" PRIu32, this->heater_interval_); if (this->heater_power_ == SHT4X_HEATERPOWER_HIGH) { if (this->heater_time_ == SHT4X_HEATERTIME_LONG) { @@ -62,8 +60,6 @@ void SHT4XComponent::setup() { } } ESP_LOGD(TAG, "Heater command: %x", this->heater_command_); - - this->set_interval(heater_interval, std::bind(&SHT4XComponent::start_heater_, this)); } } @@ -106,19 +102,27 @@ void SHT4XComponent::update() { // Evaluate and publish measurements if (this->temp_sensor_ != nullptr) { // Temp is contained in the first result word - float sensor_value_temp = buffer[0]; - float temp = -45 + 175 * sensor_value_temp / 65535; - + float temp = TEMPERATURE_OFFSET + TEMPERATURE_SPAN * static_cast<float>(buffer[0]) / RAW_MAX; this->temp_sensor_->publish_state(temp); } if (this->humidity_sensor_ != nullptr) { // Relative humidity is in the second result word - float sensor_value_rh = buffer[1]; - float rh = -6 + 125 * sensor_value_rh / 65535; - + float rh = HUMIDITY_OFFSET + HUMIDITY_SPAN * static_cast<float>(buffer[1]) / RAW_MAX; this->humidity_sensor_->publish_state(rh); } + + // Fire heater after measurement to maximize cooldown time before the next reading. + // The heater command produces a measurement that we don't need (datasheet 4.9). + if (this->heater_interval_ > 0) { + uint32_t now = millis(); + if (now - this->last_heater_millis_ >= this->heater_interval_) { + ESP_LOGD(TAG, "Heater turning on"); + if (this->write_command(this->heater_command_)) { + this->last_heater_millis_ = now; + } + } + } }); } diff --git a/esphome/components/sht4x/sht4x.h b/esphome/components/sht4x/sht4x.h index aec0f3d7f8..51f473fe3f 100644 --- a/esphome/components/sht4x/sht4x.h +++ b/esphome/components/sht4x/sht4x.h @@ -35,9 +35,10 @@ class SHT4XComponent : public PollingComponent, public sensirion_common::Sensiri SHT4XHEATERTIME heater_time_; float duty_cycle_; - void start_heater_(); void read_serial_number_(); uint8_t heater_command_; + uint32_t heater_interval_{0}; + uint32_t last_heater_millis_{0}; uint32_t serial_number_; sensor::Sensor *temp_sensor_{nullptr}; diff --git a/tests/components/sht4x/common.yaml b/tests/components/sht4x/common.yaml index 50d5ad8ca4..bec192d6db 100644 --- a/tests/components/sht4x/common.yaml +++ b/tests/components/sht4x/common.yaml @@ -6,4 +6,8 @@ sensor: humidity: name: SHT4X Humidity address: 0x44 + precision: High + heater_max_duty: 0.02 + heater_power: High + heater_time: Long update_interval: 15s From 67ab2e143c8c549bcdbc1fe0f05c2e488075b661 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:17:59 -1000 Subject: [PATCH 1622/2030] [uart] Fix RTL87xx compilation failure due to SUCCESS macro collision (#15054) --- esphome/components/uart/uart_component.h | 5 +++++ tests/components/uart/test.rtl87xx-ard.yaml | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/components/uart/test.rtl87xx-ard.yaml diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 853de719fe..7b61501d44 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -30,12 +30,17 @@ enum UARTDirection { const LogString *parity_to_str(UARTParityOptions parity); /// Result of a flush() call. +// Some vendor SDKs (e.g., Realtek) define SUCCESS as a macro. +// Save and restore around the enum to avoid collisions with our scoped enum value. +#pragma push_macro("SUCCESS") +#undef SUCCESS enum class FlushResult { SUCCESS, ///< Confirmed: all bytes left the TX FIFO. TIMEOUT, ///< Confirmed: timed out before TX completed. FAILED, ///< Confirmed: driver or hardware error. ASSUMED_SUCCESS, ///< Platform cannot report result; success is assumed. }; +#pragma pop_macro("SUCCESS") class UARTComponent { public: diff --git a/tests/components/uart/test.rtl87xx-ard.yaml b/tests/components/uart/test.rtl87xx-ard.yaml new file mode 100644 index 0000000000..414bf1f14d --- /dev/null +++ b/tests/components/uart/test.rtl87xx-ard.yaml @@ -0,0 +1,14 @@ +uart: + - id: uart_id + tx_pin: PA23 + rx_pin: PA18 + baud_rate: 9600 + data_bits: 8 + parity: NONE + stop_bits: 1 + +switch: + - platform: uart + name: "UART Switch" + uart_id: uart_id + data: [0x01, 0x02, 0x03] From de3292c828c2116713dafddf86e725e6f2b69fc4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:19:28 -1000 Subject: [PATCH 1623/2030] [light] Fix gamma LUT quantizing small brightness to zero (#15060) --- esphome/components/light/__init__.py | 28 +++-- tests/unit_tests/components/light/__init__.py | 0 .../components/light/test_gamma_table.py | 117 ++++++++++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 tests/unit_tests/components/light/__init__.py create mode 100644 tests/unit_tests/components/light/test_gamma_table.py diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 4403281116..64452e4282 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -81,18 +81,32 @@ def _get_data() -> LightData: return CORE.data[DOMAIN] +def generate_gamma_table(gamma_correct: float) -> list[HexInt]: + """Generate a 256-entry uint16 gamma lookup table. + + For gamma > 0, non-zero indices are clamped to a minimum of 1 to preserve + the invariant that non-zero input always produces non-zero output. Without + this, small brightness values (e.g. 1%) get quantized to exactly 0.0, + which breaks zero_means_zero logic in FloatOutput. + """ + if gamma_correct > 0: + return [ + HexInt( + max(1, min(65535, int(round((i / 255.0) ** gamma_correct * 65535)))) + if i > 0 + else HexInt(0) + ) + for i in range(256) + ] + return [HexInt(int(round(i / 255.0 * 65535))) for i in range(256)] + + def _get_or_create_gamma_table(gamma_correct): data = _get_data() if gamma_correct in data.gamma_tables: return data.gamma_tables[gamma_correct] - if gamma_correct > 0: - forward = [ - HexInt(min(65535, int(round((i / 255.0) ** gamma_correct * 65535)))) - for i in range(256) - ] - else: - forward = [HexInt(int(round(i / 255.0 * 65535))) for i in range(256)] + forward = generate_gamma_table(gamma_correct) gamma_str = f"{gamma_correct}".replace(".", "_") fwd_id = ID(f"gamma_{gamma_str}_fwd", is_declaration=True, type=cg.uint16) diff --git a/tests/unit_tests/components/light/__init__.py b/tests/unit_tests/components/light/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/unit_tests/components/light/test_gamma_table.py b/tests/unit_tests/components/light/test_gamma_table.py new file mode 100644 index 0000000000..a302a355dc --- /dev/null +++ b/tests/unit_tests/components/light/test_gamma_table.py @@ -0,0 +1,117 @@ +"""Tests for the gamma LUT table generation.""" + +import pytest + +from esphome.components.light import generate_gamma_table + + +def _simulate_gamma_correct_lut(table: list[int], value: float) -> float: + """Simulate the C++ gamma_correct_lut interpolation from light_state.cpp.""" + if value <= 0.0: + return 0.0 + if value >= 1.0: + return 1.0 + scaled = value * 255.0 + idx = int(scaled) + if idx >= 255: + return table[255] / 65535.0 + frac = scaled - idx + a = float(table[idx]) + b = float(table[idx + 1]) + return (a + frac * (b - a)) / 65535.0 + + +def test_table_length() -> None: + """Table must always have exactly 256 entries.""" + table = generate_gamma_table(2.8) + assert len(table) == 256 + + +def test_index_zero_is_zero() -> None: + """Index 0 must be 0 so true off remains off.""" + for gamma in (1.0, 2.0, 2.2, 2.8, 3.0): + table = generate_gamma_table(gamma) + assert table[0] == 0, f"gamma={gamma}" + + +def test_index_255_is_max() -> None: + """Index 255 must be 65535 (full on).""" + for gamma in (1.0, 2.0, 2.2, 2.8, 3.0): + table = generate_gamma_table(gamma) + assert table[255] == 65535, f"gamma={gamma}" + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_nonzero_indices_are_nonzero(gamma: float) -> None: + """All indices > 0 must produce non-zero values. + + This prevents zero_means_zero breakage: non-zero input must always + produce non-zero output so FloatOutput applies min_power scaling. + """ + table = generate_gamma_table(gamma) + for i in range(1, 256): + assert table[i] >= 1, f"gamma={gamma}, index {i}: got {table[i]}" + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_table_monotonically_nondecreasing(gamma: float) -> None: + """The gamma table must be monotonically non-decreasing.""" + table = generate_gamma_table(gamma) + for i in range(1, 256): + assert table[i] >= table[i - 1], ( + f"gamma={gamma}: table[{i}]={table[i]} < table[{i - 1}]={table[i - 1]}" + ) + + +def test_linear_gamma() -> None: + """With gamma=0 (linear), table should be evenly spaced.""" + table = generate_gamma_table(0) + assert table[0] == 0 + assert table[128] == round(128 / 255.0 * 65535) + assert table[255] == 65535 + + +@pytest.mark.parametrize("brightness", [0.01, 0.005, 0.001, 1 / 255]) +def test_small_brightness_nonzero_after_lut(brightness: float) -> None: + """Small but non-zero brightness must produce non-zero output through the LUT. + + Regression test for #15055: with zero_means_zero=true, a gamma-corrected + value of exactly 0.0 causes FloatOutput to skip min_power scaling, turning + the LED off instead of to minimum brightness. + """ + table = generate_gamma_table(2.8) + result = _simulate_gamma_correct_lut(table, brightness) + assert result > 0.0, ( + f"brightness={brightness}: gamma LUT returned 0.0, would break zero_means_zero" + ) + + +@pytest.mark.parametrize("gamma", [1.0, 2.0, 2.2, 2.8, 3.0]) +def test_small_brightness_nonzero_all_gammas(gamma: float) -> None: + """1% brightness must be non-zero for all common gamma values.""" + table = generate_gamma_table(gamma) + result = _simulate_gamma_correct_lut(table, 0.01) + assert result > 0.0, f"gamma={gamma}: 1% brightness returned 0.0" + + +def test_lut_zero_returns_zero() -> None: + """LUT with input 0.0 must return 0.0.""" + table = generate_gamma_table(2.8) + assert _simulate_gamma_correct_lut(table, 0.0) == 0.0 + + +def test_lut_one_returns_one() -> None: + """LUT with input 1.0 must return 1.0.""" + table = generate_gamma_table(2.8) + assert _simulate_gamma_correct_lut(table, 1.0) == 1.0 + + +def test_lut_output_monotonically_nondecreasing() -> None: + """LUT output must be monotonically non-decreasing across the full range.""" + table = generate_gamma_table(2.8) + prev = 0.0 + for i in range(1001): + value = i / 1000.0 + result = _simulate_gamma_correct_lut(table, value) + assert result >= prev, f"value={value}: result {result} < previous {prev}" + prev = result From bbfe324dd6da2ffddcc98fe67d9655bccb854f6d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 22 Mar 2026 16:19:46 -0400 Subject: [PATCH 1624/2030] [ultrasonic] Fix ISR edge detection with debounce and trigger filtering (#15014) --- .../ultrasonic/ultrasonic_sensor.cpp | 29 +++++++++---------- .../components/ultrasonic/ultrasonic_sensor.h | 3 +- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.cpp b/esphome/components/ultrasonic/ultrasonic_sensor.cpp index d3f7e69444..a354b198b4 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.cpp +++ b/esphome/components/ultrasonic/ultrasonic_sensor.cpp @@ -6,11 +6,17 @@ namespace esphome::ultrasonic { static const char *const TAG = "ultrasonic.sensor"; +static constexpr uint32_t DEBOUNCE_US = 50; // Ignore edges within 50us of each other (noise filtering) +static constexpr uint32_t START_DELAY_US = 100; // Ignore edges within 100us of trigger (filters bleed-through) static constexpr uint32_t START_TIMEOUT_US = 40000; // Maximum time to wait for echo pulse to start void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { uint32_t now = micros(); - if (arg->echo_pin_isr.digital_read()) { + // Ignore edges after measurement complete or too soon after trigger pulse + if (arg->echo_end || (now - arg->measurement_start_us) <= START_DELAY_US) { + return; + } + if (!arg->echo_start || (now - arg->echo_start_us) <= DEBOUNCE_US) { arg->echo_start_us = now; arg->echo_start = true; } else { @@ -21,15 +27,14 @@ void IRAM_ATTR UltrasonicSensorStore::gpio_intr(UltrasonicSensorStore *arg) { void IRAM_ATTR UltrasonicSensorComponent::send_trigger_pulse_() { InterruptLock lock; - this->store_.echo_start_us = 0; - this->store_.echo_end_us = 0; this->store_.echo_start = false; this->store_.echo_end = false; + this->store_.measurement_start_us = micros(); this->trigger_pin_isr_.digital_write(true); delayMicroseconds(this->pulse_time_us_); this->trigger_pin_isr_.digital_write(false); this->measurement_pending_ = true; - this->measurement_start_us_ = micros(); + this->measurement_start_us_ = this->store_.measurement_start_us; } void UltrasonicSensorComponent::setup() { @@ -37,7 +42,6 @@ void UltrasonicSensorComponent::setup() { this->trigger_pin_->digital_write(false); this->trigger_pin_isr_ = this->trigger_pin_->to_isr(); this->echo_pin_->setup(); - this->store_.echo_pin_isr = this->echo_pin_->to_isr(); this->echo_pin_->attach_interrupt(UltrasonicSensorStore::gpio_intr, &this->store_, gpio::INTERRUPT_ANY_EDGE); } @@ -77,17 +81,10 @@ void UltrasonicSensorComponent::loop() { } if (this->store_.echo_end) { - float result; - if (this->store_.echo_start) { - uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; - ESP_LOGV(TAG, "pulse start took %" PRIu32 "us, echo took %" PRIu32 "us", - this->store_.echo_start_us - this->measurement_start_us_, pulse_duration); - result = UltrasonicSensorComponent::us_to_m(pulse_duration); - ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); - } else { - ESP_LOGW(TAG, "'%s' - pulse end before pulse start, does the echo pin need to be inverted?", this->name_.c_str()); - result = NAN; - } + uint32_t pulse_duration = this->store_.echo_end_us - this->store_.echo_start_us; + ESP_LOGV(TAG, "Echo took %" PRIu32 "us", pulse_duration); + float result = UltrasonicSensorComponent::us_to_m(pulse_duration); + ESP_LOGD(TAG, "'%s' - Got distance: %.3f m", this->name_.c_str(), result); this->publish_state(result); this->measurement_pending_ = false; return; diff --git a/esphome/components/ultrasonic/ultrasonic_sensor.h b/esphome/components/ultrasonic/ultrasonic_sensor.h index 541f7d2b70..7d333a1b24 100644 --- a/esphome/components/ultrasonic/ultrasonic_sensor.h +++ b/esphome/components/ultrasonic/ultrasonic_sensor.h @@ -11,8 +11,7 @@ namespace esphome::ultrasonic { struct UltrasonicSensorStore { static void gpio_intr(UltrasonicSensorStore *arg); - ISRInternalGPIOPin echo_pin_isr; - volatile uint32_t wait_start_us{0}; + volatile uint32_t measurement_start_us{0}; volatile uint32_t echo_start_us{0}; volatile uint32_t echo_end_us{0}; volatile bool echo_start{false}; From 036be63f7b022023a7ab36f138dbd6e7df1dde84 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:20:28 -1000 Subject: [PATCH 1625/2030] [logger] Fix race condition in task log buffer initialization (#15071) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/logger/__init__.py | 39 ++++++++++++++++----------- esphome/components/logger/logger.cpp | 20 ++++++-------- esphome/components/logger/logger.h | 5 ++-- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index a5601e6a8f..3da81e12a0 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -331,11 +331,27 @@ async def to_code(config: ConfigType) -> None: CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level tx_buffer_size = config[CONF_TX_BUFFER_SIZE] cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) - log = cg.new_Pvariable( - config[CONF_ID], - baud_rate, - ) - if CORE.is_esp32: + # Determine task log buffer size and define USE_ESPHOME_TASK_LOG_BUFFER early + # so the constructor can allocate the buffer immediately, preventing a race + # where another task logs before the buffer is initialized. + task_log_buffer_size = 0 + if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: + task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] + elif CORE.is_host: + task_log_buffer_size = 64 # Fixed 64 slots for host + if task_log_buffer_size > 0: + cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") + log = cg.new_Pvariable( + config[CONF_ID], + baud_rate, + task_log_buffer_size, + ) + else: + log = cg.new_Pvariable( + config[CONF_ID], + baud_rate, + ) + if CORE.is_esp32 or CORE.is_host: cg.add(log.create_pthread_key()) # set_uart_selection() must be called before pre_setup() because # pre_setup() switches on uart_ to decide which hardware to initialize @@ -364,17 +380,10 @@ async def _late_logger_init(config: ConfigType) -> None: log = await cg.get_variable(config[CONF_ID]) level = config[CONF_LEVEL] baud_rate: int = config[CONF_BAUD_RATE] - if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: - task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] + if CORE.using_zephyr: + task_log_buffer_size = config.get(CONF_TASK_LOG_BUFFER_SIZE, 0) if task_log_buffer_size > 0: - cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") - cg.add(log.init_log_buffer(task_log_buffer_size)) - if CORE.using_zephyr: - zephyr_add_prj_conf("MPSC_PBUF", True) - elif CORE.is_host: - cg.add(log.create_pthread_key()) - cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") - cg.add(log.init_log_buffer(64)) # Fixed 64 slots for host + zephyr_add_prj_conf("MPSC_PBUF", True) # Enable runtime tag levels if logs are configured or explicitly enabled logs_config = config[CONF_LOGS] diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index 497809cd2e..ceacded775 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -152,29 +152,25 @@ inline uint8_t Logger::level_for(const char *tag) { return this->current_level_; } +#ifdef USE_ESPHOME_TASK_LOG_BUFFER +Logger::Logger(uint32_t baud_rate, size_t task_log_buffer_size) : baud_rate_(baud_rate) { +#else Logger::Logger(uint32_t baud_rate) : baud_rate_(baud_rate) { +#endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) this->main_task_ = xTaskGetCurrentTaskHandle(); #elif defined(USE_ZEPHYR) this->main_task_ = k_current_get(); #elif defined(USE_HOST) - this->main_thread_ = pthread_self(); +this->main_thread_ = pthread_self(); #endif -} #ifdef USE_ESPHOME_TASK_LOG_BUFFER -void Logger::init_log_buffer(size_t total_buffer_size) { - // Host uses slot count instead of byte size // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->log_buffer_ = new logger::TaskLogBuffer(total_buffer_size); - -#if !(defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) - // Start with loop disabled when using task buffer - // The loop will be enabled automatically when messages arrive - // Zephyr with USB CDC needs loop active to poll port readiness via cdc_loop_() - this->disable_loop_when_buffer_empty_(); + this->log_buffer_ = new logger::TaskLogBuffer(task_log_buffer_size); + // Note: we don't disable loop here because the component isn't registered with App yet. + // The loop self-disables on its first iteration when it finds no messages to process. #endif } -#endif #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void Logger::loop() { diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index 263d12b444..fdb330c133 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -143,9 +143,10 @@ enum UARTSelection : uint8_t { */ class Logger final : public Component { public: - explicit Logger(uint32_t baud_rate); #ifdef USE_ESPHOME_TASK_LOG_BUFFER - void init_log_buffer(size_t total_buffer_size); + explicit Logger(uint32_t baud_rate, size_t task_log_buffer_size); +#else + explicit Logger(uint32_t baud_rate); #endif #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void loop() override; From a3c483edf3838ba12fb83a927e9d4b1a744d9364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20K=C3=B6lker?= <jason@koelker.net> Date: Sun, 22 Mar 2026 20:21:08 +0000 Subject: [PATCH 1626/2030] [pmsx003] Keep active-mode reads aligned (#14832) --- esphome/components/pmsx003/pmsx003.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/esphome/components/pmsx003/pmsx003.cpp b/esphome/components/pmsx003/pmsx003.cpp index 114ecf435e..6275ff60c2 100644 --- a/esphome/components/pmsx003/pmsx003.cpp +++ b/esphome/components/pmsx003/pmsx003.cpp @@ -95,10 +95,6 @@ void PMSX003Component::loop() { // Just go ahead and read stuff break; } - } else if (now - this->last_update_ < this->update_interval_) { - // Otherwise just leave the sensor powered up and come back when we hit the update - // time - return; } if (now - this->last_transmission_ >= 500) { @@ -114,10 +110,11 @@ void PMSX003Component::loop() { this->read_byte(&this->data_[this->data_index_]); auto check = this->check_byte_(); if (!check.has_value()) { - // finished - this->parse_data_(); + if (this->update_interval_ > STABILISING_MS || now - this->last_update_ >= this->update_interval_) { + this->parse_data_(); + this->last_update_ = now; + } this->data_index_ = 0; - this->last_update_ = now; } else if (!*check) { // wrong data this->data_index_ = 0; @@ -138,7 +135,7 @@ optional<bool> PMSX003Component::check_byte_() { return true; } - ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, START_CHARACTER_1); + ESP_LOGW(TAG, "Start character %u mismatch: 0x%02X != 0x%02X", index + 1, byte, start_char); return false; } From 320474b62d26fd4d8e6d55eba84b6c76e5bad48c Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Mon, 23 Mar 2026 09:28:58 +1300 Subject: [PATCH 1627/2030] Bump version to 2026.3.1 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index d8a030536e..d86894435f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.0 +PROJECT_NUMBER = 2026.3.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 756ad69464..52ac7acd22 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.0" +__version__ = "2026.3.1" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From daafa8faa38fd8ba9cb450da18407961dbfde19a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:36:18 -1000 Subject: [PATCH 1628/2030] [wifi] Inline trivial WiFiAP and WiFiComponent accessors (#15075) --- esphome/components/wifi/wifi_component.cpp | 5 ----- esphome/components/wifi/wifi_component.h | 10 +++++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 346276692a..08065a7544 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -871,9 +871,6 @@ void WiFiComponent::loop() { WiFiComponent::WiFiComponent() { global_wifi_component = this; } -bool WiFiComponent::has_ap() const { return this->has_ap_; } -bool WiFiComponent::is_ap_active() const { return this->ap_started_; } -bool WiFiComponent::has_sta() const { return !this->sta_.empty(); } #ifdef USE_WIFI_11KV_SUPPORT void WiFiComponent::set_btm(bool btm) { this->btm_ = btm; } void WiFiComponent::set_rrm(bool rrm) { this->rrm_ = rrm; } @@ -2250,8 +2247,6 @@ bool WiFiAP::has_bssid() const { return this->bssid_ != bssid_t{}; } #ifdef USE_WIFI_WPA2_EAP const optional<EAPAuth> &WiFiAP::get_eap() const { return this->eap_; } #endif -uint8_t WiFiAP::get_channel() const { return this->channel_; } -bool WiFiAP::has_channel() const { return this->channel_ != 0; } #ifdef USE_WIFI_MANUAL_IP const optional<ManualIP> &WiFiAP::get_manual_ip() const { return this->manual_ip_; } #endif diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 057f2c0661..bd202604d6 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -263,8 +263,8 @@ class WiFiAP { #ifdef USE_WIFI_WPA2_EAP const optional<EAPAuth> &get_eap() const; #endif // USE_WIFI_WPA2_EAP - uint8_t get_channel() const; - bool has_channel() const; + uint8_t get_channel() const { return this->channel_; } + bool has_channel() const { return this->channel_ != 0; } int8_t get_priority() const { return priority_; } #ifdef USE_WIFI_MANUAL_IP const optional<ManualIP> &get_manual_ip() const; @@ -470,9 +470,9 @@ class WiFiComponent final : public Component { /// Reconnect WiFi if required. void loop() override; - bool has_sta() const; - bool has_ap() const; - bool is_ap_active() const; + bool has_sta() const { return !this->sta_.empty(); } + bool has_ap() const { return this->has_ap_; } + bool is_ap_active() const { return this->ap_started_; } #ifdef USE_WIFI_11KV_SUPPORT void set_btm(bool btm); From 593dbc9e67f4347dcb5642ffe60cec63edf97408 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:50:58 -1000 Subject: [PATCH 1629/2030] [logger] Fix unit test and benchmark Logger constructor calls (#15085) --- tests/benchmarks/components/main.cpp | 2 +- tests/components/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/benchmarks/components/main.cpp b/tests/benchmarks/components/main.cpp index 9bc0c31a15..901dc44c07 100644 --- a/tests/benchmarks/components/main.cpp +++ b/tests/benchmarks/components/main.cpp @@ -26,7 +26,7 @@ void setup() { // Log functions call global_logger->log_vprintf_() without a null check, // so we must set up a Logger before any test that triggers logging. - static esphome::logger::Logger test_logger(0); + static esphome::logger::Logger test_logger(0, 64); test_logger.set_log_level(ESPHOME_LOG_LEVEL); test_logger.pre_setup(); diff --git a/tests/components/main.cpp b/tests/components/main.cpp index 373fde7151..622b1f107b 100644 --- a/tests/components/main.cpp +++ b/tests/components/main.cpp @@ -22,7 +22,7 @@ void original_setup() { void setup() { // Log functions call global_logger->log_vprintf_() without a null check, // so we must set up a Logger before any test that triggers logging. - static esphome::logger::Logger test_logger(0); + static esphome::logger::Logger test_logger(0, 64); test_logger.set_log_level(ESPHOME_LOG_LEVEL); test_logger.pre_setup(); From 45c0e6ef7f3cf29ff1934cc8d94f8dcb9217df09 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 10:52:46 -1000 Subject: [PATCH 1630/2030] [logger] Fix unit test Logger constructor call (#15086) --- tests/components/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/components/main.cpp b/tests/components/main.cpp index 373fde7151..622b1f107b 100644 --- a/tests/components/main.cpp +++ b/tests/components/main.cpp @@ -22,7 +22,7 @@ void original_setup() { void setup() { // Log functions call global_logger->log_vprintf_() without a null check, // so we must set up a Logger before any test that triggers logging. - static esphome::logger::Logger test_logger(0); + static esphome::logger::Logger test_logger(0, 64); test_logger.set_log_level(ESPHOME_LOG_LEVEL); test_logger.pre_setup(); From 27f3a5f5f472ee3c80b5b8699e25a2f4d588b73c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 11:54:54 -1000 Subject: [PATCH 1631/2030] [sht4x] Add missing hal.h include for millis() on ESP-IDF (#15087) --- esphome/components/sht4x/sht4x.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 43c2436a56..b1dbde22a4 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -1,4 +1,5 @@ #include "sht4x.h" +#include "esphome/core/hal.h" #include "esphome/core/log.h" namespace esphome { From 6d16c57747773431da0484b0e10e10e5129fed39 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 11:54:54 -1000 Subject: [PATCH 1632/2030] [sht4x] Add missing hal.h include for millis() on ESP-IDF (#15087) --- esphome/components/sht4x/sht4x.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/sht4x/sht4x.cpp b/esphome/components/sht4x/sht4x.cpp index 43c2436a56..b1dbde22a4 100644 --- a/esphome/components/sht4x/sht4x.cpp +++ b/esphome/components/sht4x/sht4x.cpp @@ -1,4 +1,5 @@ #include "sht4x.h" +#include "esphome/core/hal.h" #include "esphome/core/log.h" namespace esphome { From 5cc4f6e85ab77fe914000fb41013f6fc5aadded2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:29:12 -1000 Subject: [PATCH 1633/2030] [logger] Add task_log_buffer_zephyr.cpp to platform source filter (#15081) --- esphome/components/logger/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 3da81e12a0..4345e291a3 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -614,6 +614,7 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.RTL87XX_ARDUINO, PlatformFramework.LN882X_ARDUINO, }, + "task_log_buffer_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR}, } ) From 4d09eb2cec628cd5ad082678f3fa5266ef46fe1d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:29:28 -1000 Subject: [PATCH 1634/2030] [tests] Fix flaky ld24xx integration tests by disabling API batching (#15050) --- tests/integration/fixtures/uart_mock_ld2410.yaml | 1 + tests/integration/fixtures/uart_mock_ld2410_engineering.yaml | 1 + tests/integration/fixtures/uart_mock_ld2412.yaml | 1 + tests/integration/fixtures/uart_mock_ld2412_engineering.yaml | 1 + .../fixtures/uart_mock_ld2412_engineering_truncated.yaml | 1 + tests/integration/fixtures/uart_mock_ld2420.yaml | 1 + tests/integration/fixtures/uart_mock_ld2420_simple.yaml | 1 + tests/integration/fixtures/uart_mock_ld2450.yaml | 1 + 8 files changed, 8 insertions(+) diff --git a/tests/integration/fixtures/uart_mock_ld2410.yaml b/tests/integration/fixtures/uart_mock_ld2410.yaml index 59838b0599..e7568c0e3f 100644 --- a/tests/integration/fixtures/uart_mock_ld2410.yaml +++ b/tests/integration/fixtures/uart_mock_ld2410.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml index 4625ae8511..5e62a4b8a8 100644 --- a/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml +++ b/tests/integration/fixtures/uart_mock_ld2410_engineering.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2412.yaml b/tests/integration/fixtures/uart_mock_ld2412.yaml index 9cf9d6bb87..525ab0d5c4 100644 --- a/tests/integration/fixtures/uart_mock_ld2412.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml index a69e18888e..9f83e3226f 100644 --- a/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml b/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml index c0bd514762..fd1cd9fd33 100644 --- a/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml +++ b/tests/integration/fixtures/uart_mock_ld2412_engineering_truncated.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2420.yaml b/tests/integration/fixtures/uart_mock_ld2420.yaml index 5380b81071..ee22f807d4 100644 --- a/tests/integration/fixtures/uart_mock_ld2420.yaml +++ b/tests/integration/fixtures/uart_mock_ld2420.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2420_simple.yaml b/tests/integration/fixtures/uart_mock_ld2420_simple.yaml index 2ceca5d35d..d3b6ad5d92 100644 --- a/tests/integration/fixtures/uart_mock_ld2420_simple.yaml +++ b/tests/integration/fixtures/uart_mock_ld2420_simple.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE diff --git a/tests/integration/fixtures/uart_mock_ld2450.yaml b/tests/integration/fixtures/uart_mock_ld2450.yaml index 269136da68..4140ff659c 100644 --- a/tests/integration/fixtures/uart_mock_ld2450.yaml +++ b/tests/integration/fixtures/uart_mock_ld2450.yaml @@ -3,6 +3,7 @@ esphome: host: api: + batch_delay: 0ms # Disable batching to receive all state updates logger: level: VERBOSE From 9152f77cdd3833d51026ee95c917ed868c234ba8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:31:48 -1000 Subject: [PATCH 1635/2030] [core] Reduce automation call chain stack depth (#15042) --- esphome/core/automation.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index 7934fdbec9..ca4a2c8b6b 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -322,7 +322,9 @@ template<typename... Ts> class Automation; template<typename... Ts> class Trigger { public: /// Inform the parent automation that the event has triggered. - void trigger(const Ts &...x) { + // Force-inline: collapses the Trigger→Automation→ActionList forwarding + // chain into a single frame, reducing automation call stack depth. + inline void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE { if (this->automation_parent_ == nullptr) return; this->automation_parent_->trigger(x...); @@ -429,7 +431,9 @@ template<typename... Ts> class ActionList { this->add_action(action); } } - void play(const Ts &...x) { + // Force-inline: part of the Trigger→Automation→ActionList forwarding + // chain collapsed to reduce automation call stack depth. + inline void play(const Ts &...x) ESPHOME_ALWAYS_INLINE { if (this->actions_begin_ != nullptr) this->actions_begin_->play_complex(x...); } @@ -473,7 +477,9 @@ template<typename... Ts> class Automation { void stop() { this->actions_.stop(); } - void trigger(const Ts &...x) { this->actions_.play(x...); } + // Force-inline: part of the Trigger→Automation→ActionList forwarding + // chain collapsed to reduce automation call stack depth. + inline void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE { this->actions_.play(x...); } bool is_running() { return this->actions_.is_running(); } From 6caa9ee22770acee9ccbe2369001900dc772a7d2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:32:08 -1000 Subject: [PATCH 1636/2030] [logger] Move log level lookup tables to PROGMEM (#15003) --- esphome/components/logger/log_buffer.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/esphome/components/logger/log_buffer.h b/esphome/components/logger/log_buffer.h index 734cb14dc5..067ce04114 100644 --- a/esphome/components/logger/log_buffer.h +++ b/esphome/components/logger/log_buffer.h @@ -1,5 +1,6 @@ #pragma once +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -8,8 +9,8 @@ namespace esphome::logger { // Maximum header size: 35 bytes fixed + 32 bytes tag + 16 bytes thread name = 83 bytes (45 byte safety margin) static constexpr uint16_t MAX_HEADER_SIZE = 128; -// ANSI color code last digit (30-38 range, store only last digit to save RAM) -static constexpr char LOG_LEVEL_COLOR_DIGIT[] = { +// ANSI color code last digit (30-38 range, store only last digit to save RAM on ESP8266) +static const char LOG_LEVEL_COLOR_DIGIT[] PROGMEM = { '\0', // NONE '1', // ERROR (31 = red) '3', // WARNING (33 = yellow) @@ -20,7 +21,7 @@ static constexpr char LOG_LEVEL_COLOR_DIGIT[] = { '8', // VERY_VERBOSE (38 = white) }; -static constexpr char LOG_LEVEL_LETTER_CHARS[] = { +static const char LOG_LEVEL_LETTER_CHARS[] PROGMEM = { '\0', // NONE 'E', // ERROR 'W', // WARNING @@ -64,7 +65,7 @@ struct LogBuffer { *p++ = 'V'; // VERY_VERBOSE = "VV" *p++ = 'V'; } else { - *p++ = LOG_LEVEL_LETTER_CHARS[level]; + *p++ = static_cast<char>(progmem_read_byte(reinterpret_cast<const uint8_t *>(&LOG_LEVEL_LETTER_CHARS[level]))); } } *p++ = ']'; @@ -184,7 +185,7 @@ struct LogBuffer { *p++ = (level == 1) ? '1' : '0'; // Only ERROR is bold *p++ = ';'; *p++ = '3'; - *p++ = LOG_LEVEL_COLOR_DIGIT[level]; + *p++ = static_cast<char>(progmem_read_byte(reinterpret_cast<const uint8_t *>(&LOG_LEVEL_COLOR_DIGIT[level]))); *p++ = 'm'; } // Copy string without null terminator, updates pointer in place From 30f66be1dab8dc645fdd77293c0730521d03f4dd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:32:42 -1000 Subject: [PATCH 1637/2030] [esp32] Mention ignore_pin_validation_error in flash pin error message (#14998) --- esphome/components/esp32/gpio_esp32.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/gpio_esp32.py b/esphome/components/esp32/gpio_esp32.py index b3166cf822..fec257f90b 100644 --- a/esphome/components/esp32/gpio_esp32.py +++ b/esphome/components/esp32/gpio_esp32.py @@ -28,7 +28,11 @@ def esp32_validate_gpio_pin(value: int) -> int: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-39)") if value in _ESP_SDIO_PINS: raise cv.Invalid( - f"This pin cannot be used on ESP32s and is already used by the flash interface (function: {_ESP_SDIO_PINS[value]})" + f"This pin cannot be used on ESP32s and is already used by the flash interface" + f" (function: {_ESP_SDIO_PINS[value]})." + f" If you are using an ESP32 module that uses a different flash pin" + f" configuration (e.g. ESP32-PICO-V3-02), you can set" + f" 'ignore_pin_validation_error: true' to bypass this check." ) if 9 <= value <= 10: _LOGGER.warning( From b2b61bea6a12993bf6bcb0c2160a4fd735fcfe0f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:33:06 -1000 Subject: [PATCH 1638/2030] [web_server_idf] Inline send() to reduce httpd task stack depth (#15045) --- .../components/web_server_idf/web_server_idf.cpp | 13 ------------- esphome/components/web_server_idf/web_server_idf.h | 13 +++++++++++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index fb0c17c854..38ccfccb76 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -262,19 +262,6 @@ StringRef AsyncWebServerRequest::url_to(std::span<char, URL_BUF_SIZE> buffer) co return StringRef(buffer.data(), decoded_len); } -void AsyncWebServerRequest::send(AsyncWebServerResponse *response) { - httpd_resp_send(*this, response->get_content_data(), response->get_content_size()); -} - -void AsyncWebServerRequest::send(int code, const char *content_type, const char *content) { - this->init_response_(nullptr, code, content_type); - if (content) { - httpd_resp_send(*this, content, HTTPD_RESP_USE_STRLEN); - } else { - httpd_resp_send(*this, nullptr, 0); - } -} - void AsyncWebServerRequest::redirect(const std::string &url) { httpd_resp_set_status(*this, "302 Found"); httpd_resp_set_hdr(*this, "Location", url.c_str()); diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 9d81d89ec7..81683e8d85 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -134,8 +134,17 @@ class AsyncWebServerRequest { void redirect(const std::string &url); - void send(AsyncWebServerResponse *response); - void send(int code, const char *content_type = nullptr, const char *content = nullptr); + inline void ESPHOME_ALWAYS_INLINE send(AsyncWebServerResponse *response) { + httpd_resp_send(*this, response->get_content_data(), response->get_content_size()); + } + inline void ESPHOME_ALWAYS_INLINE send(int code, const char *content_type = nullptr, const char *content = nullptr) { + this->init_response_(nullptr, code, content_type); + if (content) { + httpd_resp_send(*this, content, HTTPD_RESP_USE_STRLEN); + } else { + httpd_resp_send(*this, nullptr, 0); + } + } // NOLINTNEXTLINE(readability-identifier-naming) AsyncWebServerResponse *beginResponse(int code, const char *content_type) { auto *res = new AsyncWebServerResponseEmpty(this); // NOLINT(cppcoreguidelines-owning-memory) From aef987dccf26fbe06a9a54f870e59eb1daa7a176 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:37:46 -1000 Subject: [PATCH 1639/2030] [core] Fix Callback::create memcpy from function reference (#14995) --- esphome/core/helpers.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 43431299de..82c6b3833c 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1762,7 +1762,10 @@ template<typename... Ts> struct Callback<void(Ts...)> { // Safe under C++20 (P0593R6): byte copy into aligned storage implicitly // creates objects of implicit-lifetime types (trivially copyable qualifies). Callback cb; // fn and ctx are zero-initialized by default - __builtin_memcpy(&cb.ctx_, &callable, sizeof(DecayF)); + // Decay callable to a local variable first. When F is a function reference + // (e.g. void(&)(int)), &callable would point at machine code, not a pointer variable. + DecayF decayed = std::forward<F>(callable); + __builtin_memcpy(&cb.ctx_, &decayed, sizeof(DecayF)); cb.fn_ = [](void *c, Ts... args) { alignas(DecayF) char buf[sizeof(DecayF)]; __builtin_memcpy(buf, &c, sizeof(DecayF)); From 84727b1f71e2b3a08f297941592ef6df64fd2ebd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:41:01 -1000 Subject: [PATCH 1640/2030] [esp32] Validate eFuse MAC reads and reject garbage MACs (#15049) --- esphome/components/esp32/helpers.cpp | 46 ++++++++++++++++++++++------ esphome/core/helpers.cpp | 11 ++++++- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/esphome/components/esp32/helpers.cpp b/esphome/components/esp32/helpers.cpp index 654a35b473..afcec8bfc7 100644 --- a/esphome/components/esp32/helpers.cpp +++ b/esphome/components/esp32/helpers.cpp @@ -9,11 +9,14 @@ #include <freertos/FreeRTOS.h> #include <freertos/portmacro.h> +#include "esphome/core/log.h" #include "esp_random.h" #include "esp_system.h" namespace esphome { +static const char *const TAG = "esp32"; + bool random_bytes(uint8_t *data, size_t len) { esp_fill_random(data, len); return true; @@ -63,22 +66,43 @@ LwIPLock::~LwIPLock() { #endif } +/// Read MAC and validate both the return code and content. +static bool read_valid_mac(uint8_t *mac, esp_err_t err) { return err == ESP_OK && mac_address_is_valid(mac); } + +static constexpr size_t MAC_ADDRESS_SIZE_BITS = MAC_ADDRESS_SIZE * 8; // 48 bits + void get_mac_address_raw(uint8_t *mac) { // NOLINT(readability-non-const-parameter) #if defined(CONFIG_SOC_IEEE802154_SUPPORTED) // When CONFIG_SOC_IEEE802154_SUPPORTED is defined, esp_efuse_mac_get_default // returns the 802.15.4 EUI-64 address, so we read directly from eFuse instead. - if (has_custom_mac_address()) { - esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48); - } else { - esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, 48); + // Both paths already read raw eFuse bytes, so there is no CRC-bypass fallback + // (unlike the non-IEEE802154 path where esp_efuse_mac_get_default does CRC checks). + if (has_custom_mac_address() && + read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, MAC_ADDRESS_SIZE_BITS))) { + return; + } + if (read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, MAC_ADDRESS_SIZE_BITS))) { + return; } #else - if (has_custom_mac_address()) { - esp_efuse_mac_get_custom(mac); - } else { - esp_efuse_mac_get_default(mac); + if (has_custom_mac_address() && read_valid_mac(mac, esp_efuse_mac_get_custom(mac))) { + return; + } + if (read_valid_mac(mac, esp_efuse_mac_get_default(mac))) { + return; + } + // Default MAC read failed (e.g., eFuse CRC error) - try reading raw eFuse bytes + // directly, bypassing CRC validation. A MAC that passes mac_address_is_valid() + // (non-zero, non-broadcast, unicast) is almost certainly the real factory MAC + // with a corrupted CRC byte, which is far better than returning garbage or zeros. + if (read_valid_mac(mac, esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY, mac, MAC_ADDRESS_SIZE_BITS))) { + ESP_LOGW(TAG, "eFuse MAC CRC failed but raw bytes appear valid - using raw eFuse MAC"); + return; } #endif + // All methods failed - zero the MAC rather than returning garbage + ESP_LOGE(TAG, "Failed to read a valid MAC address from eFuse"); + memset(mac, 0, MAC_ADDRESS_SIZE); } void set_mac_address(uint8_t *mac) { esp_base_mac_addr_set(mac); } @@ -88,9 +112,11 @@ bool has_custom_mac_address() { uint8_t mac[6]; // do not use 'esp_efuse_mac_get_custom(mac)' because it drops an error in the logs whenever it fails #ifndef USE_ESP32_VARIANT_ESP32 - return (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac); + return (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA_MAC_CUSTOM, mac, MAC_ADDRESS_SIZE_BITS) == ESP_OK) && + mac_address_is_valid(mac); #else - return (esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, 48) == ESP_OK) && mac_address_is_valid(mac); + return (esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM, mac, MAC_ADDRESS_SIZE_BITS) == ESP_OK) && + mac_address_is_valid(mac); #endif #else return false; diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index ee99c54196..1732fc72e8 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -863,7 +863,16 @@ bool mac_address_is_valid(const uint8_t *mac) { is_all_ones = false; } } - return !(is_all_zeros || is_all_ones); + if (is_all_zeros || is_all_ones) { + return false; + } + // Reject multicast MACs (bit 0 of first byte set) - device MACs must be unicast. + // This catches garbage data from corrupted eFuse custom MAC areas, which often + // has random values that would otherwise pass the all-zeros/all-ones check. + if (mac[0] & 0x01) { + return false; + } + return true; } void IRAM_ATTR HOT delay_microseconds_safe(uint32_t us) { From 2c06464f7baa843bf8a45d9bbe93c8314af708a2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:41:54 -1000 Subject: [PATCH 1641/2030] [packet_transport] Use FixedVector and parent pointer to enable inline Callback storage (#14946) --- esphome/components/packet_transport/__init__.py | 10 ++++++++-- .../packet_transport/packet_transport.cpp | 16 ++++++++++------ .../packet_transport/packet_transport.h | 15 +++++++++++---- .../binary_sensor/binary_sensor_test.cpp | 4 ++++ .../packet_transport/sensor/sensor_test.cpp | 6 ++++++ 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/esphome/components/packet_transport/__init__.py b/esphome/components/packet_transport/__init__.py index 1930e45e85..0b166bb65c 100644 --- a/esphome/components/packet_transport/__init__.py +++ b/esphome/components/packet_transport/__init__.py @@ -177,13 +177,19 @@ async def register_packet_transport(var, config): cg.add(var.set_provider_encryption(name, hash_encryption_key(encryption))) is_provider = False - for sens_conf in config.get(CONF_SENSORS, ()): + sensors = config.get(CONF_SENSORS, ()) + binary_sensors = config.get(CONF_BINARY_SENSORS, ()) + if sensors: + cg.add(var.set_sensor_count(len(sensors))) + if binary_sensors: + cg.add(var.set_binary_sensor_count(len(binary_sensors))) + for sens_conf in sensors: is_provider = True sens_id = sens_conf[CONF_ID] sensor = await cg.get_variable(sens_id) bcst_id = sens_conf.get(CONF_BROADCAST_ID, sens_id.id) cg.add(var.add_sensor(bcst_id, sensor)) - for sens_conf in config.get(CONF_BINARY_SENSORS, ()): + for sens_conf in binary_sensors: is_provider = True sens_id = sens_conf[CONF_ID] sensor = await cg.get_variable(sens_id) diff --git a/esphome/components/packet_transport/packet_transport.cpp b/esphome/components/packet_transport/packet_transport.cpp index 964037a02c..a2199977aa 100644 --- a/esphome/components/packet_transport/packet_transport.cpp +++ b/esphome/components/packet_transport/packet_transport.cpp @@ -221,16 +221,20 @@ void PacketTransport::setup() { } #ifdef USE_SENSOR for (auto &sensor : this->sensors_) { - sensor.sensor->add_on_state_callback([this, &sensor](float x) { - this->updated_ = true; + // [&sensor] is safe: sensor refers to a FixedVector element that never reallocates, + // so the reference remains valid for the component's lifetime. + sensor.sensor->add_on_state_callback([&sensor](float x) { + sensor.parent->updated_ = true; sensor.updated = true; }); } #endif #ifdef USE_BINARY_SENSOR for (auto &sensor : this->binary_sensors_) { - sensor.sensor->add_on_state_callback([this, &sensor](bool value) { - this->updated_ = true; + // [&sensor] is safe: sensor refers to a FixedVector element that never reallocates, + // so the reference remains valid for the component's lifetime. + sensor.sensor->add_on_state_callback([&sensor](bool value) { + sensor.parent->updated_ = true; sensor.updated = true; }); } @@ -548,11 +552,11 @@ void PacketTransport::dump_config() { " Ping-pong: %s", this->platform_name_, YESNO(this->is_encrypted_()), YESNO(this->ping_pong_enable_)); #ifdef USE_SENSOR - for (auto sensor : this->sensors_) + for (const auto &sensor : this->sensors_) ESP_LOGCONFIG(TAG, " Sensor: %s", sensor.id); #endif #ifdef USE_BINARY_SENSOR - for (auto sensor : this->binary_sensors_) + for (const auto &sensor : this->binary_sensors_) ESP_LOGCONFIG(TAG, " Binary Sensor: %s", sensor.id); #endif for (const auto &host : this->providers_) { diff --git a/esphome/components/packet_transport/packet_transport.h b/esphome/components/packet_transport/packet_transport.h index b3798738e2..836775bc85 100644 --- a/esphome/components/packet_transport/packet_transport.h +++ b/esphome/components/packet_transport/packet_transport.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/helpers.h" #include "esphome/core/preferences.h" #ifdef USE_SENSOR #include "esphome/components/sensor/sensor.h" @@ -37,11 +38,14 @@ struct Provider { #endif }; +class PacketTransport; + #ifdef USE_SENSOR struct Sensor { sensor::Sensor *sensor; const char *id; bool updated; + PacketTransport *parent; }; #endif #ifdef USE_BINARY_SENSOR @@ -49,6 +53,7 @@ struct BinarySensor { binary_sensor::BinarySensor *sensor; const char *id; bool updated; + PacketTransport *parent; }; #endif @@ -60,8 +65,9 @@ class PacketTransport : public PollingComponent { void dump_config() override; #ifdef USE_SENSOR + void set_sensor_count(size_t count) { this->sensors_.init(count); } void add_sensor(const char *id, sensor::Sensor *sensor) { - Sensor st{sensor, id, true}; + Sensor st{sensor, id, true, this}; this->sensors_.push_back(st); } void add_remote_sensor(const char *hostname, const char *remote_id, sensor::Sensor *sensor) { @@ -70,8 +76,9 @@ class PacketTransport : public PollingComponent { } #endif #ifdef USE_BINARY_SENSOR + void set_binary_sensor_count(size_t count) { this->binary_sensors_.init(count); } void add_binary_sensor(const char *id, binary_sensor::BinarySensor *sensor) { - BinarySensor st{sensor, id, true}; + BinarySensor st{sensor, id, true, this}; this->binary_sensors_.push_back(st); } @@ -141,11 +148,11 @@ class PacketTransport : public PollingComponent { std::vector<uint8_t> encryption_key_{}; #ifdef USE_SENSOR - std::vector<Sensor> sensors_{}; + FixedVector<Sensor> sensors_{}; string_map_t<string_map_t<sensor::Sensor *>> remote_sensors_{}; #endif #ifdef USE_BINARY_SENSOR - std::vector<BinarySensor> binary_sensors_{}; + FixedVector<BinarySensor> binary_sensors_{}; string_map_t<string_map_t<binary_sensor::BinarySensor *>> remote_binary_sensors_{}; #endif diff --git a/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp b/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp index 36af087d2c..5ad25c2d7d 100644 --- a/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp +++ b/tests/components/packet_transport/binary_sensor/binary_sensor_test.cpp @@ -5,6 +5,7 @@ namespace esphome::packet_transport::testing { TEST(PacketTransportBinarySensorTest, AddBinarySensor) { TestablePacketTransport transport; binary_sensor::BinarySensor bs; + transport.set_binary_sensor_count(1); transport.add_binary_sensor("motion", &bs); ASSERT_EQ(transport.binary_sensors_.size(), 1u); EXPECT_STREQ(transport.binary_sensors_[0].id, "motion"); @@ -24,6 +25,7 @@ TEST(PacketTransportBinarySensorTest, UnencryptedBinarySensorRoundTrip) { encoder.init_for_test("sender"); binary_sensor::BinarySensor local_bs; local_bs.state = true; + encoder.set_binary_sensor_count(1); encoder.add_binary_sensor("motion", &local_bs); encoder.send_data_(true); @@ -46,11 +48,13 @@ TEST(PacketTransportBinarySensorTest, MultipleSensorsRoundTrip) { sensor::Sensor s1, s2; s1.state = 10.0f; s2.state = 20.0f; + encoder.set_sensor_count(2); encoder.add_sensor("s1", &s1); encoder.add_sensor("s2", &s2); binary_sensor::BinarySensor bs1; bs1.state = true; + encoder.set_binary_sensor_count(1); encoder.add_binary_sensor("bs1", &bs1); encoder.send_data_(true); diff --git a/tests/components/packet_transport/sensor/sensor_test.cpp b/tests/components/packet_transport/sensor/sensor_test.cpp index 2f681aee58..5d1cfb4bc2 100644 --- a/tests/components/packet_transport/sensor/sensor_test.cpp +++ b/tests/components/packet_transport/sensor/sensor_test.cpp @@ -5,6 +5,7 @@ namespace esphome::packet_transport::testing { TEST(PacketTransportSensorTest, AddSensor) { TestablePacketTransport transport; sensor::Sensor s; + transport.set_sensor_count(1); transport.add_sensor("temp", &s); ASSERT_EQ(transport.sensors_.size(), 1u); EXPECT_STREQ(transport.sensors_[0].id, "temp"); @@ -26,6 +27,7 @@ TEST(PacketTransportSensorTest, UnencryptedSensorRoundTrip) { encoder.init_for_test("sender"); sensor::Sensor local_sensor; local_sensor.state = 42.5f; + encoder.set_sensor_count(1); encoder.add_sensor("temp", &local_sensor); encoder.send_data_(true); @@ -53,6 +55,7 @@ TEST(PacketTransportSensorTest, EncryptedSensorRoundTrip) { encoder.set_encryption_key(key); sensor::Sensor local_sensor; local_sensor.state = 99.9f; + encoder.set_sensor_count(1); encoder.add_sensor("temp", &local_sensor); encoder.send_data_(true); @@ -77,6 +80,7 @@ TEST(PacketTransportSensorTest, SendDataOnlyUpdated) { sensor::Sensor s1, s2; s1.state = 1.0f; s2.state = 2.0f; + encoder.set_sensor_count(2); encoder.add_sensor("s1", &s1); encoder.add_sensor("s2", &s2); @@ -111,6 +115,7 @@ TEST(PacketTransportSensorTest, PingKeyIncludedInTransmittedPacket) { responder.set_encryption_key(key); sensor::Sensor local_sensor; local_sensor.state = 77.7f; + responder.set_sensor_count(1); responder.add_sensor("temp", &local_sensor); // Requester sends a MAGIC_PING that the responder processes @@ -148,6 +153,7 @@ TEST(PacketTransportSensorTest, MissingPingKeyBlocksSensorData) { responder.set_encryption_key(key); sensor::Sensor local_sensor; local_sensor.state = 77.7f; + responder.set_sensor_count(1); responder.add_sensor("temp", &local_sensor); responder.send_data_(true); ASSERT_EQ(responder.sent_packets.size(), 1u); From d0e705d948c20aa68eab915ffbd5c3699916bd03 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 12:46:28 -1000 Subject: [PATCH 1642/2030] [core] Inline Application::loop() to eliminate stack frame (#15041) --- esphome/components/esp32/core.cpp | 4 +- esphome/components/socket/socket.h | 2 +- esphome/core/application.cpp | 145 +-------------------------- esphome/core/application.h | 154 ++++++++++++++++++++++++++++- 4 files changed, 156 insertions(+), 149 deletions(-) diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 83bd09b643..313818e601 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -2,6 +2,7 @@ #include "esphome/core/defines.h" #include "crash_handler.h" +#include "esphome/core/application.h" #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "preferences.h" @@ -15,7 +16,6 @@ #include <freertos/task.h> void setup(); // NOLINT(readability-redundant-declaration) -void loop(); // NOLINT(readability-redundant-declaration) // Weak stub for initArduino - overridden when the Arduino component is present extern "C" __attribute__((weak)) void initArduino() {} @@ -65,7 +65,7 @@ TaskHandle_t loop_task_handle = nullptr; // NOLINT(cppcoreguidelines-avoid-non- void loop_task(void *pv_params) { setup(); while (true) { - loop(); + App.loop(); } } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index a21bd64730..226a669e31 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -125,7 +125,7 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s /// On ESP8266, uses esp_delay() with a callback that checks socket activity. /// On RP2040, uses __wfe() (Wait For Event) to truly sleep until an interrupt /// (for example, CYW43 GPIO or a timer alarm) fires and wakes the CPU. -void socket_delay(uint32_t ms); +void socket_delay(uint32_t ms); // NOLINT(readability-redundant-declaration) /// Signal socket/IO activity and wake the main loop early. /// On ESP8266: sets flag + esp_schedule(). diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 08df385475..c020a8ed58 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -12,21 +12,11 @@ #endif #ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" -#ifdef USE_ESP32 -#include <freertos/FreeRTOS.h> -#include <freertos/task.h> -#else -#include <FreeRTOS.h> -#include <task.h> -#endif #endif // USE_LWIP_FAST_SELECT #include "esphome/core/version.h" #include "esphome/core/hal.h" #include <algorithm> #include <ranges> -#ifdef USE_RUNTIME_STATS -#include "esphome/components/runtime_stats/runtime_stats.h" -#endif #ifdef USE_STATUS_LED #include "esphome/components/status_led/status_led.h" @@ -163,66 +153,6 @@ void Application::setup() { this->schedule_dump_config(); } -void Application::loop() { - uint8_t new_app_state = 0; - - // Get the initial loop time at the start - uint32_t last_op_end_time = millis(); - - this->before_loop_tasks_(last_op_end_time); - - for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_; - this->current_loop_index_++) { - Component *component = this->looping_components_[this->current_loop_index_]; - - // Update the cached time before each component runs - this->loop_component_start_time_ = last_op_end_time; - - { - this->set_current_component(component); - WarnIfComponentBlockingGuard guard{component, last_op_end_time}; - component->loop(); - // Use the finish method to get the current time as the end time - last_op_end_time = guard.finish(); - } - new_app_state |= component->get_component_state(); - this->app_state_ |= new_app_state; - this->feed_wdt(last_op_end_time); - } - - this->after_loop_tasks_(); - this->app_state_ = new_app_state; - -#ifdef USE_RUNTIME_STATS - // Process any pending runtime stats printing after all components have run - // This ensures stats printing doesn't affect component timing measurements - if (global_runtime_stats != nullptr) { - global_runtime_stats->process_pending_stats(last_op_end_time); - } -#endif - - // Use the last component's end time instead of calling millis() again - auto elapsed = last_op_end_time - this->last_loop_; - if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) { - // Even if we overran the loop interval, we still need to select() - // to know if any sockets have data ready - this->yield_with_select_(0); - } else { - uint32_t delay_time = this->loop_interval_ - elapsed; - uint32_t next_schedule = this->scheduler.next_schedule_in(last_op_end_time).value_or(delay_time); - // next_schedule is max 0.5*delay_time - // otherwise interval=0 schedules result in constant looping with almost no sleep - next_schedule = std::max(next_schedule, delay_time / 2); - delay_time = std::min(next_schedule, delay_time); - - this->yield_with_select_(delay_time); - } - this->last_loop_ = last_op_end_time; - - if (this->dump_config_at_ < this->components_.size()) { - this->process_dump_config_(); - } -} void Application::process_dump_config_() { if (this->dump_config_at_ == 0) { @@ -509,41 +439,6 @@ void Application::enable_pending_loops_() { } } -void Application::before_loop_tasks_(uint32_t loop_start_time) { -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) - // Drain wake notifications first to clear socket for next wake - this->drain_wake_notifications_(); -#endif - - // Process scheduled tasks - this->scheduler.call(loop_start_time); - - // Feed the watchdog timer - this->feed_wdt(loop_start_time); - - // Process any pending enable_loop requests from ISRs - // This must be done before marking in_loop_ = true to avoid race conditions - if (this->has_pending_enable_loop_requests_) { - // Clear flag BEFORE processing to avoid race condition - // If ISR sets it during processing, we'll catch it next loop iteration - // This is safe because: - // 1. Each component has its own pending_enable_loop_ flag that we check - // 2. If we can't process a component (wrong state), enable_pending_loops_() - // will set this flag back to true - // 3. Any new ISR requests during processing will set the flag again - this->has_pending_enable_loop_requests_ = false; - this->enable_pending_loops_(); - } - - // Mark that we're in the loop for safe reentrant modifications - this->in_loop_ = true; -} - -void Application::after_loop_tasks_() { - // Clear the in_loop_ flag to indicate we're done processing components - this->in_loop_ = false; -} - #ifdef USE_LWIP_FAST_SELECT bool Application::register_socket(struct lwip_sock *sock) { // It modifies monitored_sockets_ without locking — must only be called from the main loop. @@ -625,36 +520,10 @@ void Application::unregister_socket_fd(int fd) { #endif +// Only the select() fallback path remains in the .cpp — all other paths are inlined in application.h +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) void Application::yield_with_select_(uint32_t delay_ms) { - // Delay while monitoring sockets. When delay_ms is 0, always yield() to ensure other tasks run. -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) - // Fast path (ESP32/LibreTiny): reads rcvevent directly from cached lwip_sock pointers. - // Safe because this runs on the main loop which owns socket lifetime (create, read, close). - if (delay_ms == 0) [[unlikely]] { - yield(); - return; - } - - // Check if any socket already has pending data before sleeping. - // If a socket still has unread data (rcvevent > 0) but the task notification was already - // consumed, ulTaskNotifyTake would block until timeout — adding up to delay_ms latency. - // This scan preserves select() semantics: return immediately when any fd is ready. - for (struct lwip_sock *sock : this->monitored_sockets_) { - if (esphome_lwip_socket_has_data(sock)) { - yield(); - return; - } - } - - // Sleep with instant wake via FreeRTOS task notification. - // Woken by: callback wrapper (socket data arrives), wake_loop_threadsafe() (other tasks), or timeout. - // Without USE_WAKE_LOOP_THREADSAFE, only hooked socket callbacks wake the task — - // background tasks won't call wake, so this degrades to a pure timeout (same as old select path). - ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(delay_ms)); - -#elif defined(USE_SOCKET_SELECT_SUPPORT) // Fallback select() path (host platform and any future platforms without fast select). - // ESP32 and LibreTiny are excluded by the #if above — they use the fast path. if (!this->socket_fds_.empty()) [[likely]] { // Update fd_set if socket list has changed if (this->socket_fds_changed_) [[unlikely]] { @@ -701,16 +570,8 @@ void Application::yield_with_select_(uint32_t delay_ms) { } // No sockets registered or select() failed - use regular delay delay(delay_ms); -#elif (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) - // No select support but can wake on socket activity - // ESP8266: via esp_schedule() - // RP2040: via __sev()/__wfe() hardware sleep/wake - socket::socket_delay(delay_ms); -#else - // No select support, use regular delay - delay(delay_ms); -#endif } +#endif // defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) // App storage — asm label shares the linker symbol with "extern Application App". // char[] is trivially destructible, so no __cxa_atexit or destructor chain is emitted. diff --git a/esphome/core/application.h b/esphome/core/application.h index 26abc15433..06ff30e81f 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -27,6 +27,13 @@ #ifdef USE_SOCKET_SELECT_SUPPORT #ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" +#ifdef USE_ESP32 +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> +#else +#include <FreeRTOS.h> +#include <task.h> +#endif #else #include <sys/select.h> #ifdef USE_WAKE_LOOP_THREADSAFE @@ -34,9 +41,13 @@ #endif #endif #endif // USE_SOCKET_SELECT_SUPPORT +#ifdef USE_RUNTIME_STATS +#include "esphome/components/runtime_stats/runtime_stats.h" +#endif #if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) namespace esphome::socket { -void socket_wake(); // NOLINT(readability-redundant-declaration) +void socket_wake(); // NOLINT(readability-redundant-declaration) +void socket_delay(uint32_t ms); // NOLINT(readability-redundant-declaration) } // namespace esphome::socket #endif #ifdef USE_BINARY_SENSOR @@ -293,7 +304,7 @@ class Application { void setup(); /// Make a loop iteration. Call this in your loop() function. - void loop(); + inline void ESPHOME_ALWAYS_INLINE loop(); /// Get the name of this Application set by pre_setup(). const StringRef &get_name() const { return this->name_; } @@ -617,8 +628,8 @@ class Application { void enable_component_loop_(Component *component); void enable_pending_loops_(); void activate_looping_component_(uint16_t index); - void before_loop_tasks_(uint32_t loop_start_time); - void after_loop_tasks_(); + inline void ESPHOME_ALWAYS_INLINE before_loop_tasks_(uint32_t loop_start_time); + inline void ESPHOME_ALWAYS_INLINE after_loop_tasks_() { this->in_loop_ = false; } /// Process dump_config output one component per loop iteration. /// Extracted from loop() to keep cold startup/reconnect logging out of the hot path. @@ -628,7 +639,12 @@ class Application { void feed_wdt_arch_(); /// Perform a delay while also monitoring socket file descriptors for readiness +#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) + // select() fallback path is too complex to inline (host platform) void yield_with_select_(uint32_t delay_ms); +#else + inline void ESPHOME_ALWAYS_INLINE yield_with_select_(uint32_t delay_ms); +#endif #if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) void setup_wake_loop_threadsafe_(); // Create wake notification socket @@ -814,4 +830,134 @@ inline void Application::drain_wake_notifications_() { } #endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +inline void ESPHOME_ALWAYS_INLINE Application::before_loop_tasks_(uint32_t loop_start_time) { +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) + // Drain wake notifications first to clear socket for next wake + this->drain_wake_notifications_(); +#endif + + // Process scheduled tasks + this->scheduler.call(loop_start_time); + + // Feed the watchdog timer + this->feed_wdt(loop_start_time); + + // Process any pending enable_loop requests from ISRs + // This must be done before marking in_loop_ = true to avoid race conditions + if (this->has_pending_enable_loop_requests_) { + // Clear flag BEFORE processing to avoid race condition + // If ISR sets it during processing, we'll catch it next loop iteration + // This is safe because: + // 1. Each component has its own pending_enable_loop_ flag that we check + // 2. If we can't process a component (wrong state), enable_pending_loops_() + // will set this flag back to true + // 3. Any new ISR requests during processing will set the flag again + this->has_pending_enable_loop_requests_ = false; + this->enable_pending_loops_(); + } + + // Mark that we're in the loop for safe reentrant modifications + this->in_loop_ = true; +} + +inline void ESPHOME_ALWAYS_INLINE Application::loop() { + uint8_t new_app_state = 0; + + // Get the initial loop time at the start + uint32_t last_op_end_time = millis(); + + this->before_loop_tasks_(last_op_end_time); + + for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_; + this->current_loop_index_++) { + Component *component = this->looping_components_[this->current_loop_index_]; + + // Update the cached time before each component runs + this->loop_component_start_time_ = last_op_end_time; + + { + this->set_current_component(component); + WarnIfComponentBlockingGuard guard{component, last_op_end_time}; + component->loop(); + // Use the finish method to get the current time as the end time + last_op_end_time = guard.finish(); + } + new_app_state |= component->get_component_state(); + this->app_state_ |= new_app_state; + this->feed_wdt(last_op_end_time); + } + + this->after_loop_tasks_(); + this->app_state_ = new_app_state; + +#ifdef USE_RUNTIME_STATS + // Process any pending runtime stats printing after all components have run + // This ensures stats printing doesn't affect component timing measurements + if (global_runtime_stats != nullptr) { + global_runtime_stats->process_pending_stats(last_op_end_time); + } +#endif + + // Use the last component's end time instead of calling millis() again + auto elapsed = last_op_end_time - this->last_loop_; + if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) { + // Even if we overran the loop interval, we still need to select() + // to know if any sockets have data ready + this->yield_with_select_(0); + } else { + uint32_t delay_time = this->loop_interval_ - elapsed; + uint32_t next_schedule = this->scheduler.next_schedule_in(last_op_end_time).value_or(delay_time); + // next_schedule is max 0.5*delay_time + // otherwise interval=0 schedules result in constant looping with almost no sleep + next_schedule = std::max(next_schedule, delay_time / 2); + delay_time = std::min(next_schedule, delay_time); + + this->yield_with_select_(delay_time); + } + this->last_loop_ = last_op_end_time; + + if (this->dump_config_at_ < this->components_.size()) { + this->process_dump_config_(); + } +} + +// Inline yield_with_select_ for all paths except the select() fallback +#if !defined(USE_SOCKET_SELECT_SUPPORT) || defined(USE_LWIP_FAST_SELECT) +inline void ESPHOME_ALWAYS_INLINE Application::yield_with_select_(uint32_t delay_ms) { +#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) + // Fast path (ESP32/LibreTiny): reads rcvevent directly from cached lwip_sock pointers. + // Safe because this runs on the main loop which owns socket lifetime (create, read, close). + if (delay_ms == 0) [[unlikely]] { + yield(); + return; + } + + // Check if any socket already has pending data before sleeping. + // If a socket still has unread data (rcvevent > 0) but the task notification was already + // consumed, ulTaskNotifyTake would block until timeout — adding up to delay_ms latency. + // This scan preserves select() semantics: return immediately when any fd is ready. + for (struct lwip_sock *sock : this->monitored_sockets_) { + if (esphome_lwip_socket_has_data(sock)) { + yield(); + return; + } + } + + // Sleep with instant wake via FreeRTOS task notification. + // Woken by: callback wrapper (socket data arrives), wake_loop_threadsafe() (other tasks), or timeout. + // Without USE_WAKE_LOOP_THREADSAFE, only hooked socket callbacks wake the task — + // background tasks won't call wake, so this degrades to a pure timeout (same as old select path). + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(delay_ms)); +#elif (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) + // No select support but can wake on socket activity + // ESP8266: via esp_schedule() + // RP2040: via __sev()/__wfe() hardware sleep/wake + socket::socket_delay(delay_ms); +#else + // No select support, use regular delay + delay(delay_ms); +#endif +} +#endif // !defined(USE_SOCKET_SELECT_SUPPORT) || defined(USE_LWIP_FAST_SELECT) + } // namespace esphome From e85065b1c4211280a49b3b473905c33c83eae337 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 14:06:00 -1000 Subject: [PATCH 1643/2030] [logger] Fix dummy_main.cpp Logger constructor for clang-tidy (#15088) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- tests/dummy_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index 6fa0c08aa3..329286e2fa 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -15,7 +15,7 @@ void setup() { static char name[] = "livingroom"; static char friendly_name[] = "LivingRoom"; App.pre_setup(name, sizeof(name) - 1, friendly_name, sizeof(friendly_name) - 1); - auto *log = new logger::Logger(115200); // NOLINT + auto *log = new logger::Logger(115200, 512); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); App.register_component_(log); From 83d02c602a911181ad0e0ef89ef50fde17ef0bd7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 14:06:00 -1000 Subject: [PATCH 1644/2030] [logger] Fix dummy_main.cpp Logger constructor for clang-tidy (#15088) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- tests/dummy_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index 6fa0c08aa3..329286e2fa 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -15,7 +15,7 @@ void setup() { static char name[] = "livingroom"; static char friendly_name[] = "LivingRoom"; App.pre_setup(name, sizeof(name) - 1, friendly_name, sizeof(friendly_name) - 1); - auto *log = new logger::Logger(115200); // NOLINT + auto *log = new logger::Logger(115200, 512); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); App.register_component_(log); From cd05462e9fc4a295b523412c04fa17acb6c86171 Mon Sep 17 00:00:00 2001 From: Kamil Cukrowski <kamilcukrowski@gmail.com> Date: Mon, 23 Mar 2026 01:42:04 +0100 Subject: [PATCH 1645/2030] [core] Use placement new allocation for Pvariables (#15079) Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/cpp_generator.py | 48 +++++++++++++++---- .../binary_sensor/test_binary_sensor.py | 2 +- tests/component_tests/button/test_button.py | 3 +- tests/component_tests/conftest.py | 2 +- .../deep_sleep/test_deep_sleep.py | 6 ++- tests/component_tests/globals/__init__.py | 0 .../globals/config/globals_test.yaml | 16 +++++++ tests/component_tests/globals/test_globals.py | 27 +++++++++++ .../gpio/test_gpio_binary_sensor.py | 3 +- tests/component_tests/image/test_init.py | 10 +++- tests/component_tests/logger/test_logger.py | 4 ++ .../mipi_dsi/test_mipi_dsi_config.py | 10 +++- tests/component_tests/status_led/__init__.py | 0 .../status_led/config/status_led_test.yaml | 8 ++++ .../status_led/test_status_led.py | 23 +++++++++ tests/component_tests/text/test_text.py | 3 +- .../text_sensor/test_text_sensor.py | 3 +- 17 files changed, 151 insertions(+), 17 deletions(-) create mode 100644 tests/component_tests/globals/__init__.py create mode 100644 tests/component_tests/globals/config/globals_test.yaml create mode 100644 tests/component_tests/globals/test_globals.py create mode 100644 tests/component_tests/status_led/__init__.py create mode 100644 tests/component_tests/status_led/config/status_led_test.yaml create mode 100644 tests/component_tests/status_led/test_status_led.py diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 5457485d25..3ed5d0ba37 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -579,10 +579,41 @@ def Pvariable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": obj = MockObj(id_, "->") if type_ is not None: id_.type = type_ - decl = VariableDeclarationExpression(id_.type, "*", id_, static=True) - CORE.add_global(decl) - assignment = AssignmentExpression(None, None, id_, rhs) - CORE.add(assignment) + + if isinstance(rhs, MockObj) and rhs.is_new_expr: + # For 'new' allocations, use placement new into static storage + # to avoid heap fragmentation on embedded devices. + the_type = id_.type + storage_name = f"{id_.id}__pstorage" + + # Declare aligned byte array for the object storage + CORE.add_global( + RawStatement( + f"alignas({the_type}) static unsigned char {storage_name}[sizeof({the_type})];" + ) + ) + CORE.add_global( + AssignmentExpression( + f"static {the_type}", + "*const ", + id_, + MockObj(f"reinterpret_cast<{the_type} *>({storage_name})"), + ) + ) + # Extract args from the CallExpression and rebuild as placement new. + # Template args are already encoded in the_type (e.g. GlobalsComponent<int>), + # so we only pass the constructor args, not template_args. + call_expr = rhs.base + assert isinstance(call_expr, CallExpression), ( + f"Expected CallExpression for placement new, got {type(call_expr)}" + ) + placement_new = CallExpression(f"new({id_.id}) {the_type}", *call_expr.args) + CORE.add(ExpressionStatement(placement_new)) + else: + decl = VariableDeclarationExpression(id_.type, "*", id_, static=True) + CORE.add_global(decl) + CORE.add(AssignmentExpression(None, None, id_, rhs)) + CORE.register_variable(id_, obj) return obj @@ -799,11 +830,12 @@ class MockObj(Expression): Mostly consists of magic methods that allow ESPHome's codegen syntax. """ - __slots__ = ("base", "op") + __slots__ = ("base", "op", "is_new_expr") - def __init__(self, base, op="."): + def __init__(self, base, op=".", is_new_expr=False) -> None: self.base = base self.op = op + self.is_new_expr = is_new_expr def __getattr__(self, attr: str) -> "MockObj": # prevent python dunder methods being replaced by mock objects @@ -818,7 +850,7 @@ class MockObj(Expression): def __call__(self, *args: SafeExpType) -> "MockObj": call = CallExpression(self.base, *args) - return MockObj(call, self.op) + return MockObj(call, self.op, is_new_expr=self.is_new_expr) def __str__(self): return str(self.base) @@ -832,7 +864,7 @@ class MockObj(Expression): @property def new(self) -> "MockObj": - return MockObj(f"new {self.base}", "->") + return MockObj(f"new {self.base}", "->", is_new_expr=True) def template(self, *args: SafeExpType) -> "MockObj": """Apply template parameters to this object.""" diff --git a/tests/component_tests/binary_sensor/test_binary_sensor.py b/tests/component_tests/binary_sensor/test_binary_sensor.py index 10d7f80834..4f41f2cc70 100644 --- a/tests/component_tests/binary_sensor/test_binary_sensor.py +++ b/tests/component_tests/binary_sensor/test_binary_sensor.py @@ -15,7 +15,7 @@ def test_binary_sensor_is_setup(generate_main): ) # Then - assert "new gpio::GPIOBinarySensor();" in main_cpp + assert "static gpio::GPIOBinarySensor *const" in main_cpp assert "App.register_binary_sensor" in main_cpp diff --git a/tests/component_tests/button/test_button.py b/tests/component_tests/button/test_button.py index a35994a682..544e748f91 100644 --- a/tests/component_tests/button/test_button.py +++ b/tests/component_tests/button/test_button.py @@ -13,7 +13,8 @@ def test_button_is_setup(generate_main): main_cpp = generate_main("tests/component_tests/button/test_button.yaml") # Then - assert "new wake_on_lan::WakeOnLanButton();" in main_cpp + assert "static wake_on_lan::WakeOnLanButton *const" in main_cpp + assert ") wake_on_lan::WakeOnLanButton();" in main_cpp assert "App.register_button" in main_cpp assert "App.register_component" in main_cpp diff --git a/tests/component_tests/conftest.py b/tests/component_tests/conftest.py index 0641e698e9..763628f57c 100644 --- a/tests/component_tests/conftest.py +++ b/tests/component_tests/conftest.py @@ -134,7 +134,7 @@ def generate_main() -> Generator[Callable[[str | Path], str]]: CORE.config_path = Path(path) CORE.config = read_config({}) generate_cpp_contents(CORE.config) - return CORE.cpp_main_section + return CORE.cpp_global_section + CORE.cpp_main_section yield generator diff --git a/tests/component_tests/deep_sleep/test_deep_sleep.py b/tests/component_tests/deep_sleep/test_deep_sleep.py index 41ddd72feb..212f61e44b 100644 --- a/tests/component_tests/deep_sleep/test_deep_sleep.py +++ b/tests/component_tests/deep_sleep/test_deep_sleep.py @@ -7,7 +7,11 @@ def test_deep_sleep_setup(generate_main): """ main_cpp = generate_main("tests/component_tests/deep_sleep/test_deep_sleep1.yaml") - assert "deepsleep = new deep_sleep::DeepSleepComponent();" in main_cpp + assert ( + "static deep_sleep::DeepSleepComponent *const deepsleep = reinterpret_cast<deep_sleep::DeepSleepComponent *>(deepsleep__pstorage);" + in main_cpp + ) + assert "new(deepsleep) deep_sleep::DeepSleepComponent();" in main_cpp assert "App.register_component_(deepsleep);" in main_cpp diff --git a/tests/component_tests/globals/__init__.py b/tests/component_tests/globals/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/globals/config/globals_test.yaml b/tests/component_tests/globals/config/globals_test.yaml new file mode 100644 index 0000000000..1d1a9edaa6 --- /dev/null +++ b/tests/component_tests/globals/config/globals_test.yaml @@ -0,0 +1,16 @@ +esphome: + name: test + +esp32: + board: esp32dev + +globals: + - id: my_global_int + type: int + initial_value: "42" + - id: my_global_float + type: float + initial_value: "1.5" + - id: my_global_bool + type: bool + initial_value: "true" diff --git a/tests/component_tests/globals/test_globals.py b/tests/component_tests/globals/test_globals.py new file mode 100644 index 0000000000..04fd6d5f7d --- /dev/null +++ b/tests/component_tests/globals/test_globals.py @@ -0,0 +1,27 @@ +"""Tests for the globals component.""" + +from __future__ import annotations + +from collections.abc import Callable +from pathlib import Path + + +def test_globals_placement_new_with_template_args( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test that globals uses placement new with template arguments preserved.""" + main_cpp = generate_main(component_config_path("globals_test.yaml")) + + # Globals uses Pvariable with Type.new(template_args, initial_value) + # which exercises the template_args preservation in placement new. + assert "static globals::GlobalsComponent<int> *const my_global_int" in main_cpp + assert "sizeof(globals::GlobalsComponent<int>)" in main_cpp + assert "new(my_global_int) globals::GlobalsComponent<int>" in main_cpp + + # Verify initial value is passed as constructor arg + assert "42" in main_cpp + + # Check other globals are also generated + assert "sizeof(globals::GlobalsComponent<float>)" in main_cpp + assert "sizeof(globals::GlobalsComponent<bool>)" in main_cpp diff --git a/tests/component_tests/gpio/test_gpio_binary_sensor.py b/tests/component_tests/gpio/test_gpio_binary_sensor.py index 73665dc45d..f336a9105e 100644 --- a/tests/component_tests/gpio/test_gpio_binary_sensor.py +++ b/tests/component_tests/gpio/test_gpio_binary_sensor.py @@ -16,7 +16,8 @@ def test_gpio_binary_sensor_basic_setup( """ main_cpp = generate_main("tests/component_tests/gpio/test_gpio_binary_sensor.yaml") - assert "new gpio::GPIOBinarySensor();" in main_cpp + assert "static gpio::GPIOBinarySensor *const" in main_cpp + assert ") gpio::GPIOBinarySensor();" in main_cpp assert "App.register_binary_sensor" in main_cpp # set_use_interrupt(true) should NOT be generated (uses C++ default) assert "bs_gpio->set_use_interrupt(true);" not in main_cpp diff --git a/tests/component_tests/image/test_init.py b/tests/component_tests/image/test_init.py index c9481a0e1d..9003a4ee5d 100644 --- a/tests/component_tests/image/test_init.py +++ b/tests/component_tests/image/test_init.py @@ -242,7 +242,15 @@ def test_image_generation( main_cpp = generate_main(component_config_path("image_test.yaml")) assert "uint8_t_id[] PROGMEM = {0x24, 0x21, 0x24, 0x21" in main_cpp assert ( - "cat_img = new image::Image(uint8_t_id, 32, 24, image::IMAGE_TYPE_RGB565, image::TRANSPARENCY_OPAQUE);" + "alignas(image::Image) static unsigned char cat_img__pstorage[sizeof(image::Image)];" + in main_cpp + ) + assert ( + "static image::Image *const cat_img = reinterpret_cast<image::Image *>(cat_img__pstorage);" + in main_cpp + ) + assert ( + "new(cat_img) image::Image(uint8_t_id, 32, 24, image::IMAGE_TYPE_RGB565, image::TRANSPARENCY_OPAQUE);" in main_cpp ) diff --git a/tests/component_tests/logger/test_logger.py b/tests/component_tests/logger/test_logger.py index 98aa741964..94a6f7ac7b 100644 --- a/tests/component_tests/logger/test_logger.py +++ b/tests/component_tests/logger/test_logger.py @@ -22,6 +22,10 @@ def test_logger_pre_setup_before_other_components(generate_main): # Find all "new " allocations (component creation) new_allocations = list(re.finditer(r"\bnew [\w:]+", main_cpp)) + # Find all "new(" allocations (component creation) and combine them + new_allocations.extend(re.finditer(r"\bnew\([^)]+\) [\w:]+", main_cpp)) + # Sort allocations by position in the file + new_allocations.sort(key=lambda m: m.start()) assert len(new_allocations) > 0, "No component allocations found" # Separate logger and non-logger allocations diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index 92f56b5451..e6f344b086 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -119,7 +119,15 @@ def test_code_generation( main_cpp = generate_main(component_fixture_path("mipi_dsi.yaml")) assert ( - "p4_nano = new mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" + "alignas(mipi_dsi::MIPI_DSI) static unsigned char p4_nano__pstorage[sizeof(mipi_dsi::MIPI_DSI)];" + in main_cpp + ) + assert ( + "static mipi_dsi::MIPI_DSI *const p4_nano = reinterpret_cast<mipi_dsi::MIPI_DSI *>(p4_nano__pstorage);" + in main_cpp + ) + assert ( + "new(p4_nano) mipi_dsi::MIPI_DSI(800, 1280, display::COLOR_BITNESS_565, 16);" in main_cpp ) assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp diff --git a/tests/component_tests/status_led/__init__.py b/tests/component_tests/status_led/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/status_led/config/status_led_test.yaml b/tests/component_tests/status_led/config/status_led_test.yaml new file mode 100644 index 0000000000..c86197d225 --- /dev/null +++ b/tests/component_tests/status_led/config/status_led_test.yaml @@ -0,0 +1,8 @@ +esphome: + name: test + +esp32: + board: esp32dev + +status_led: + pin: GPIO2 diff --git a/tests/component_tests/status_led/test_status_led.py b/tests/component_tests/status_led/test_status_led.py new file mode 100644 index 0000000000..0e96e631f5 --- /dev/null +++ b/tests/component_tests/status_led/test_status_led.py @@ -0,0 +1,23 @@ +"""Tests for status_led.""" + +from __future__ import annotations + +from collections.abc import Callable +from pathlib import Path + + +def test_status_led_generation( + generate_main: Callable[[str | Path], str], + component_config_path: Callable[[str], Path], +) -> None: + """Test status_led generation.""" + main_cpp = generate_main(component_config_path("status_led_test.yaml")) + assert ( + "alignas(status_led::StatusLED) static unsigned char status_led_statusled_id__pstorage[sizeof(status_led::StatusLED)];" + in main_cpp + ) + assert ( + "static status_led::StatusLED *const status_led_statusled_id = reinterpret_cast<status_led::StatusLED *>(status_led_statusled_id__pstorage);" + in main_cpp + ) + assert "new(status_led_statusled_id) status_led::StatusLED(" in main_cpp diff --git a/tests/component_tests/text/test_text.py b/tests/component_tests/text/test_text.py index c74dfb8a47..63eb4f1951 100644 --- a/tests/component_tests/text/test_text.py +++ b/tests/component_tests/text/test_text.py @@ -13,7 +13,8 @@ def test_text_is_setup(generate_main): main_cpp = generate_main("tests/component_tests/text/test_text.yaml") # Then - assert "new template_::TemplateText();" in main_cpp + assert "static template_::TemplateText *const" in main_cpp + assert ") template_::TemplateText();" in main_cpp assert "App.register_text" in main_cpp diff --git a/tests/component_tests/text_sensor/test_text_sensor.py b/tests/component_tests/text_sensor/test_text_sensor.py index 1ff31ab96b..ae094fadf8 100644 --- a/tests/component_tests/text_sensor/test_text_sensor.py +++ b/tests/component_tests/text_sensor/test_text_sensor.py @@ -13,7 +13,8 @@ def test_text_sensor_is_setup(generate_main): main_cpp = generate_main("tests/component_tests/text_sensor/test_text_sensor.yaml") # Then - assert "new template_::TemplateTextSensor();" in main_cpp + assert "static template_::TemplateTextSensor *const" in main_cpp + assert ") template_::TemplateTextSensor();" in main_cpp assert "App.register_text_sensor" in main_cpp From 9cdc17566a9d9b96ff37943cb815e4d66703e47e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 15:06:45 -1000 Subject: [PATCH 1646/2030] [combination] Use FixedVector and parent pointer to enable inline Callback storage (#14947) --- .../components/combination/combination.cpp | 34 +++++++++---------- esphome/components/combination/combination.h | 18 +++++++--- esphome/components/combination/sensor.py | 3 ++ 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/esphome/components/combination/combination.cpp b/esphome/components/combination/combination.cpp index 2f0bd26a02..b858eee4ee 100644 --- a/esphome/components/combination/combination.cpp +++ b/esphome/components/combination/combination.cpp @@ -4,8 +4,6 @@ #include "esphome/core/hal.h" #include <cmath> -#include <functional> -#include <vector> namespace esphome { namespace combination { @@ -20,12 +18,12 @@ void CombinationComponent::log_config_(const LogString *combo_type) { void CombinationNoParameterComponent::add_source(Sensor *sensor) { this->sensors_.emplace_back(sensor); } -void CombinationOneParameterComponent::add_source(Sensor *sensor, std::function<float(float)> const &stddev) { - this->sensor_pairs_.emplace_back(sensor, stddev); +void CombinationOneParameterComponent::add_source(Sensor *sensor, std::function<float(float)> const &compute) { + this->sensor_sources_.push_back({sensor, compute, this}); } -void CombinationOneParameterComponent::add_source(Sensor *sensor, float stddev) { - this->add_source(sensor, std::function<float(float)>{[stddev](float x) -> float { return stddev; }}); +void CombinationOneParameterComponent::add_source(Sensor *sensor, float value) { + this->add_source(sensor, std::function<float(float)>{[value](float x) -> float { return value; }}); } void CombinationNoParameterComponent::log_source_sensors() { @@ -37,9 +35,8 @@ void CombinationNoParameterComponent::log_source_sensors() { void CombinationOneParameterComponent::log_source_sensors() { ESP_LOGCONFIG(TAG, " Source Sensors:"); - for (const auto &sensor : this->sensor_pairs_) { - auto &entity = *sensor.first; - ESP_LOGCONFIG(TAG, " - %s", entity.get_name().c_str()); + for (const auto &source : this->sensor_sources_) { + ESP_LOGCONFIG(TAG, " - %s", source.sensor->get_name().c_str()); } } @@ -62,9 +59,12 @@ void KalmanCombinationComponent::dump_config() { } void KalmanCombinationComponent::setup() { - for (const auto &sensor : this->sensor_pairs_) { - const auto stddev = sensor.second; - sensor.first->add_on_state_callback([this, stddev](float x) -> void { this->correct_(x, stddev(x)); }); + for (auto &source : this->sensor_sources_) { + // [&source] is safe: source refers to a FixedVector element that never reallocates, + // so the reference remains valid for the component's lifetime. + source.sensor->add_on_state_callback([&source](float x) -> void { + static_cast<KalmanCombinationComponent *>(source.parent)->correct_(x, source.compute(x)); + }); } } @@ -117,10 +117,10 @@ void KalmanCombinationComponent::correct_(float value, float stddev) { } void LinearCombinationComponent::setup() { - for (const auto &sensor : this->sensor_pairs_) { + for (auto &source : this->sensor_sources_) { // All sensor updates are deferred until the next loop. This avoids publishing the combined sensor's result // repeatedly in the same loop if multiple source senors update. - sensor.first->add_on_state_callback( + source.sensor->add_on_state_callback( [this](float value) -> void { this->defer("update", [this, value]() { this->handle_new_value(value); }); }); } } @@ -133,10 +133,10 @@ void LinearCombinationComponent::handle_new_value(float value) { float sum = 0.0; - for (const auto &sensor : this->sensor_pairs_) { - const float sensor_state = sensor.first->state; + for (const auto &source : this->sensor_sources_) { + const float sensor_state = source.sensor->state; if (std::isfinite(sensor_state)) { - sum += sensor_state * sensor.second(sensor_state); + sum += sensor_state * source.compute(sensor_state); } } diff --git a/esphome/components/combination/combination.h b/esphome/components/combination/combination.h index fb5e156da9..463eedc564 100644 --- a/esphome/components/combination/combination.h +++ b/esphome/components/combination/combination.h @@ -1,9 +1,10 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/helpers.h" #include "esphome/components/sensor/sensor.h" -#include <vector> +#include <functional> namespace esphome { namespace combination { @@ -41,14 +42,21 @@ class CombinationNoParameterComponent : public CombinationComponent { // Base class for opertions that require one parameter to compute the combination class CombinationOneParameterComponent : public CombinationComponent { public: - void add_source(Sensor *sensor, std::function<float(float)> const &stddev); - void add_source(Sensor *sensor, float stddev); + void set_source_count(size_t count) { this->sensor_sources_.init(count); } + void add_source(Sensor *sensor, std::function<float(float)> const &compute); + void add_source(Sensor *sensor, float value); - /// @brief Logs all source sensor's names in sensor_pairs_ + /// @brief Logs all source sensors' names in sensor_sources_ void log_source_sensors() override; protected: - std::vector<std::pair<Sensor *, std::function<float(float)>>> sensor_pairs_; + struct SensorSource { + sensor::Sensor *sensor; + std::function<float(float)> compute; + CombinationOneParameterComponent *parent; + }; + + FixedVector<SensorSource> sensor_sources_; }; class KalmanCombinationComponent : public CombinationOneParameterComponent { diff --git a/esphome/components/combination/sensor.py b/esphome/components/combination/sensor.py index 0204162e8d..327cedee1e 100644 --- a/esphome/components/combination/sensor.py +++ b/esphome/components/combination/sensor.py @@ -180,6 +180,9 @@ async def to_code(config): if proces_std_dev := config.get(CONF_PROCESS_STD_DEV): cg.add(var.set_process_std_dev(proces_std_dev)) + if config[CONF_TYPE] in (CONF_KALMAN, CONF_LINEAR): + cg.add(var.set_source_count(len(config[CONF_SOURCES]))) + for source_conf in config[CONF_SOURCES]: source = await cg.get_variable(source_conf[CONF_SOURCE]) if config[CONF_TYPE] == CONF_KALMAN: From fbe3e7d99c59da1bdbef279cd99501707b2945eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 15:28:46 -1000 Subject: [PATCH 1647/2030] [api] Emit raw tag+value writes for forced fixed32 key fields (#15051) --- esphome/components/api/api.proto | 142 ++++++++++---------- esphome/components/api/api_pb2.cpp | 200 ++++++++++++++-------------- esphome/components/api/proto.h | 18 ++- script/api_protobuf/api_protobuf.py | 17 ++- 4 files changed, 202 insertions(+), 175 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 28332d67a5..86daa9a2bf 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -316,7 +316,7 @@ message ListEntitiesBinarySensorResponse { option (ifdef) = "USE_BINARY_SENSOR"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -334,7 +334,7 @@ message BinarySensorStateResponse { option (ifdef) = "USE_BINARY_SENSOR"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; // If the binary sensor does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -350,7 +350,7 @@ message ListEntitiesCoverResponse { option (ifdef) = "USE_COVER"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -383,7 +383,7 @@ message CoverStateResponse { option (ifdef) = "USE_COVER"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // legacy: state has been removed in 1.13 // clients/servers must still send/accept it until the next protocol change // Deprecated in API version 1.1 @@ -409,7 +409,7 @@ message CoverCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // legacy: command has been removed in 1.13 // clients/servers must still send/accept it until the next protocol change @@ -434,7 +434,7 @@ message ListEntitiesFanResponse { option (ifdef) = "USE_FAN"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -466,7 +466,7 @@ message FanStateResponse { option (ifdef) = "USE_FAN"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; bool oscillating = 3; // Deprecated in API version 1.6 @@ -483,7 +483,7 @@ message FanCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_state = 2; bool state = 3; // Deprecated in API version 1.6 @@ -522,7 +522,7 @@ message ListEntitiesLightResponse { option (ifdef) = "USE_LIGHT"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -551,7 +551,7 @@ message LightStateResponse { option (ifdef) = "USE_LIGHT"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; float brightness = 3; ColorMode color_mode = 11; @@ -573,7 +573,7 @@ message LightCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_state = 2; bool state = 3; bool has_brightness = 4; @@ -627,7 +627,7 @@ message ListEntitiesSensorResponse { option (ifdef) = "USE_SENSOR"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -651,7 +651,7 @@ message SensorStateResponse { option (ifdef) = "USE_SENSOR"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; float state = 2; // If the sensor does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -667,7 +667,7 @@ message ListEntitiesSwitchResponse { option (ifdef) = "USE_SWITCH"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -685,7 +685,7 @@ message SwitchStateResponse { option (ifdef) = "USE_SWITCH"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -696,7 +696,7 @@ message SwitchCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -709,7 +709,7 @@ message ListEntitiesTextSensorResponse { option (ifdef) = "USE_TEXT_SENSOR"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -726,7 +726,7 @@ message TextSensorStateResponse { option (ifdef) = "USE_TEXT_SENSOR"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string state = 2; // If the text sensor does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -922,7 +922,7 @@ message ListEntitiesServicesResponse { option (ifdef) = "USE_API_USER_DEFINED_ACTIONS"; string name = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; repeated ListEntitiesServicesArgument args = 3 [(fixed_vector) = true]; SupportsResponseType supports_response = 4; } @@ -945,7 +945,7 @@ message ExecuteServiceRequest { option (no_delay) = true; option (ifdef) = "USE_API_USER_DEFINED_ACTIONS"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; repeated ExecuteServiceArgument args = 2 [(fixed_vector) = true]; uint32 call_id = 3 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_RESPONSES"]; bool return_response = 4 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_RESPONSES"]; @@ -972,7 +972,7 @@ message ListEntitiesCameraResponse { option (ifdef) = "USE_CAMERA"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id bool disabled_by_default = 5; @@ -987,7 +987,7 @@ message CameraImageResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_CAMERA"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bytes data = 2; bool done = 3; uint32 device_id = 4 [(field_ifdef) = "USE_DEVICES"]; @@ -1057,7 +1057,7 @@ message ListEntitiesClimateResponse { option (ifdef) = "USE_CLIMATE"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1095,7 +1095,7 @@ message ClimateStateResponse { option (ifdef) = "USE_CLIMATE"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; ClimateMode mode = 2; float current_temperature = 3; float target_temperature = 4; @@ -1121,7 +1121,7 @@ message ClimateCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_mode = 2; ClimateMode mode = 3; bool has_target_temperature = 4; @@ -1168,7 +1168,7 @@ message ListEntitiesWaterHeaterResponse { option (ifdef) = "USE_WATER_HEATER"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"]; bool disabled_by_default = 5; @@ -1189,7 +1189,7 @@ message WaterHeaterStateResponse { option (ifdef) = "USE_WATER_HEATER"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; float current_temperature = 2; float target_temperature = 3; WaterHeaterMode mode = 4; @@ -1219,7 +1219,7 @@ message WaterHeaterCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // Bitmask of which fields are set (see WaterHeaterCommandHasField) uint32 has_fields = 2; WaterHeaterMode mode = 3; @@ -1244,7 +1244,7 @@ message ListEntitiesNumberResponse { option (ifdef) = "USE_NUMBER"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1266,7 +1266,7 @@ message NumberStateResponse { option (ifdef) = "USE_NUMBER"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; float state = 2; // If the number does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -1280,7 +1280,7 @@ message NumberCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; float state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -1293,7 +1293,7 @@ message ListEntitiesSelectResponse { option (ifdef) = "USE_SELECT"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1310,7 +1310,7 @@ message SelectStateResponse { option (ifdef) = "USE_SELECT"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string state = 2; // If the select does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -1324,7 +1324,7 @@ message SelectCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -1337,7 +1337,7 @@ message ListEntitiesSirenResponse { option (ifdef) = "USE_SIREN"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1356,7 +1356,7 @@ message SirenStateResponse { option (ifdef) = "USE_SIREN"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -1367,7 +1367,7 @@ message SirenCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_state = 2; bool state = 3; bool has_tone = 4; @@ -1400,7 +1400,7 @@ message ListEntitiesLockResponse { option (ifdef) = "USE_LOCK"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1422,7 +1422,7 @@ message LockStateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_LOCK"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; LockState state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -1432,7 +1432,7 @@ message LockCommandRequest { option (ifdef) = "USE_LOCK"; option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; LockCommand command = 2; // Not yet implemented: @@ -1449,7 +1449,7 @@ message ListEntitiesButtonResponse { option (ifdef) = "USE_BUTTON"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1466,7 +1466,7 @@ message ButtonCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; uint32 device_id = 2 [(field_ifdef) = "USE_DEVICES"]; } @@ -1516,7 +1516,7 @@ message ListEntitiesMediaPlayerResponse { option (ifdef) = "USE_MEDIA_PLAYER"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -1538,7 +1538,7 @@ message MediaPlayerStateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_MEDIA_PLAYER"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; MediaPlayerState state = 2; float volume = 3; bool muted = 4; @@ -1551,7 +1551,7 @@ message MediaPlayerCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_command = 2; MediaPlayerCommand command = 3; @@ -2104,7 +2104,7 @@ message ListEntitiesAlarmControlPanelResponse { option (ifdef) = "USE_ALARM_CONTROL_PANEL"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; @@ -2122,7 +2122,7 @@ message AlarmControlPanelStateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_ALARM_CONTROL_PANEL"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; AlarmControlPanelState state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -2133,7 +2133,7 @@ message AlarmControlPanelCommandRequest { option (ifdef) = "USE_ALARM_CONTROL_PANEL"; option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; AlarmControlPanelStateCommand command = 2; string code = 3; uint32 device_id = 4 [(field_ifdef) = "USE_DEVICES"]; @@ -2151,7 +2151,7 @@ message ListEntitiesTextResponse { option (ifdef) = "USE_TEXT"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; @@ -2171,7 +2171,7 @@ message TextStateResponse { option (ifdef) = "USE_TEXT"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string state = 2; // If the Text does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller @@ -2185,7 +2185,7 @@ message TextCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string state = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -2199,7 +2199,7 @@ message ListEntitiesDateResponse { option (ifdef) = "USE_DATETIME_DATE"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2215,7 +2215,7 @@ message DateStateResponse { option (ifdef) = "USE_DATETIME_DATE"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // If the date does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller bool missing_state = 2; @@ -2231,7 +2231,7 @@ message DateCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; uint32 year = 2; uint32 month = 3; uint32 day = 4; @@ -2246,7 +2246,7 @@ message ListEntitiesTimeResponse { option (ifdef) = "USE_DATETIME_TIME"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2262,7 +2262,7 @@ message TimeStateResponse { option (ifdef) = "USE_DATETIME_TIME"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // If the time does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller bool missing_state = 2; @@ -2278,7 +2278,7 @@ message TimeCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; uint32 hour = 2; uint32 minute = 3; uint32 second = 4; @@ -2293,7 +2293,7 @@ message ListEntitiesEventResponse { option (ifdef) = "USE_EVENT"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2311,7 +2311,7 @@ message EventResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_EVENT"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; string event_type = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -2324,7 +2324,7 @@ message ListEntitiesValveResponse { option (ifdef) = "USE_VALVE"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2351,7 +2351,7 @@ message ValveStateResponse { option (ifdef) = "USE_VALVE"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; float position = 2; ValveOperation current_operation = 3; uint32 device_id = 4 [(field_ifdef) = "USE_DEVICES"]; @@ -2364,7 +2364,7 @@ message ValveCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool has_position = 2; float position = 3; bool stop = 4; @@ -2379,7 +2379,7 @@ message ListEntitiesDateTimeResponse { option (ifdef) = "USE_DATETIME_DATETIME"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2395,7 +2395,7 @@ message DateTimeStateResponse { option (ifdef) = "USE_DATETIME_DATETIME"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; // If the datetime does not have a valid state yet. // Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller bool missing_state = 2; @@ -2409,7 +2409,7 @@ message DateTimeCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; fixed32 epoch_seconds = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -2422,7 +2422,7 @@ message ListEntitiesUpdateResponse { option (ifdef) = "USE_UPDATE"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; reserved 4; // Deprecated: was string unique_id @@ -2439,7 +2439,7 @@ message UpdateStateResponse { option (ifdef) = "USE_UPDATE"; option (no_delay) = true; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; bool missing_state = 2; bool in_progress = 3; bool has_progress = 4; @@ -2463,7 +2463,7 @@ message UpdateCommandRequest { option (no_delay) = true; option (base_class) = "CommandProtoMessage"; - fixed32 key = 1; + fixed32 key = 1 [(force) = true]; UpdateCommand command = 2; uint32 device_id = 3 [(field_ifdef) = "USE_DEVICES"]; } @@ -2505,7 +2505,7 @@ message ListEntitiesInfraredResponse { option (ifdef) = "USE_INFRARED"; string object_id = 1; - fixed32 key = 2; + fixed32 key = 2 [(force) = true]; string name = 3; string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"]; bool disabled_by_default = 5; @@ -2521,7 +2521,7 @@ message InfraredRFTransmitRawTimingsRequest { option (ifdef) = "USE_IR_RF"; uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"]; - fixed32 key = 2; // Key identifying the transmitter instance + fixed32 key = 2 [(force) = true]; // Key identifying the transmitter instance uint32 carrier_frequency = 3; // Carrier frequency in Hz uint32 repeat_count = 4; // Number of times to transmit (1 = once, 2 = twice, etc.) repeated sint32 timings = 5 [packed = true, (packed_buffer) = true]; // Raw timings in microseconds (zigzag-encoded): positive = mark (LED/TX on), negative = space (LED/TX off) @@ -2535,7 +2535,7 @@ message InfraredRFReceiveEvent { option (no_delay) = true; uint32 device_id = 1 [(field_ifdef) = "USE_DEVICES"]; - fixed32 key = 2; // Key identifying the receiver instance + fixed32 key = 2 [(force) = true]; // Key identifying the receiver instance repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector<int32_t>"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 01993cc5e5..61b034c7ea 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -208,7 +208,7 @@ uint32_t DeviceInfoResponse::calculate_size() const { #ifdef USE_BINARY_SENSOR void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); buffer.encode_string(5, this->device_class); buffer.encode_bool(6, this->is_status_binary_sensor); @@ -224,7 +224,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); size += ProtoSize::calc_length(1, this->device_class.size()); size += ProtoSize::calc_bool(1, this->is_status_binary_sensor); @@ -239,7 +239,7 @@ uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { return size; } void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -248,7 +248,7 @@ void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t BinarySensorStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->state); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -260,7 +260,7 @@ uint32_t BinarySensorStateResponse::calculate_size() const { #ifdef USE_COVER void ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); buffer.encode_bool(5, this->assumed_state); buffer.encode_bool(6, this->supports_position); @@ -279,7 +279,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesCoverResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->supports_position); @@ -297,7 +297,7 @@ uint32_t ListEntitiesCoverResponse::calculate_size() const { return size; } void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_float(3, this->position); buffer.encode_float(4, this->tilt); buffer.encode_uint32(5, static_cast<uint32_t>(this->current_operation)); @@ -307,7 +307,7 @@ void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t CoverStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_float(1, this->position); size += ProtoSize::calc_float(1, this->tilt); size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); @@ -357,7 +357,7 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_FAN void ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); buffer.encode_bool(5, this->supports_oscillation); buffer.encode_bool(6, this->supports_speed); @@ -378,7 +378,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesFanResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); size += ProtoSize::calc_bool(1, this->supports_oscillation); size += ProtoSize::calc_bool(1, this->supports_speed); @@ -400,7 +400,7 @@ uint32_t ListEntitiesFanResponse::calculate_size() const { return size; } void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->state); buffer.encode_bool(3, this->oscillating); buffer.encode_uint32(5, static_cast<uint32_t>(this->direction)); @@ -412,7 +412,7 @@ void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t FanStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->state); size += ProtoSize::calc_bool(1, this->oscillating); size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->direction)); @@ -487,7 +487,7 @@ bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LIGHT void ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); for (const auto &it : *this->supported_color_modes) { buffer.encode_uint32(12, static_cast<uint32_t>(it), true); @@ -509,7 +509,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesLightResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); if (!this->supported_color_modes->empty()) { for (const auto &it : *this->supported_color_modes) { @@ -534,7 +534,7 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { return size; } void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->state); buffer.encode_float(3, this->brightness); buffer.encode_uint32(11, static_cast<uint32_t>(this->color_mode)); @@ -553,7 +553,7 @@ void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t LightStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->state); size += ProtoSize::calc_float(1, this->brightness); size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->color_mode)); @@ -683,7 +683,7 @@ bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SENSOR void ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -702,7 +702,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesSensorResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -720,7 +720,7 @@ uint32_t ListEntitiesSensorResponse::calculate_size() const { return size; } void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_float(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -729,7 +729,7 @@ void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t SensorStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_float(1, this->state); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -741,7 +741,7 @@ uint32_t SensorStateResponse::calculate_size() const { #ifdef USE_SWITCH void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -757,7 +757,7 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesSwitchResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -772,7 +772,7 @@ uint32_t ListEntitiesSwitchResponse::calculate_size() const { return size; } void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->state); #ifdef USE_DEVICES buffer.encode_uint32(3, this->device_id); @@ -780,7 +780,7 @@ void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t SwitchStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->state); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -816,7 +816,7 @@ bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_TEXT_SENSOR void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -831,7 +831,7 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesTextSensorResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -845,7 +845,7 @@ uint32_t ListEntitiesTextSensorResponse::calculate_size() const { return size; } void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -854,7 +854,7 @@ void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t TextSensorStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->state.size()); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -1124,7 +1124,7 @@ uint32_t ListEntitiesServicesArgument::calculate_size() const { } void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->name); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); for (auto &it : this->args) { buffer.encode_sub_message(3, it); } @@ -1133,7 +1133,7 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesServicesResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->name.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; if (!this->args.empty()) { for (const auto &it : this->args) { size += ProtoSize::calc_message_force(1, it.calculate_size()); @@ -1269,7 +1269,7 @@ uint32_t ExecuteServiceResponse::calculate_size() const { #ifdef USE_CAMERA void ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); buffer.encode_bool(5, this->disabled_by_default); #ifdef USE_ENTITY_ICON @@ -1283,7 +1283,7 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesCameraResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON @@ -1296,7 +1296,7 @@ uint32_t ListEntitiesCameraResponse::calculate_size() const { return size; } void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bytes(2, this->data_ptr_, this->data_len_); buffer.encode_bool(3, this->done); #ifdef USE_DEVICES @@ -1305,7 +1305,7 @@ void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t CameraImageResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->data_len_); size += ProtoSize::calc_bool(1, this->done); #ifdef USE_DEVICES @@ -1330,7 +1330,7 @@ bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t v #ifdef USE_CLIMATE void ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); buffer.encode_bool(5, this->supports_current_temperature); buffer.encode_bool(6, this->supports_two_point_target_temperature); @@ -1374,7 +1374,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesClimateResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); size += ProtoSize::calc_bool(1, this->supports_current_temperature); size += ProtoSize::calc_bool(1, this->supports_two_point_target_temperature); @@ -1429,7 +1429,7 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { return size; } void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); buffer.encode_float(3, this->current_temperature); buffer.encode_float(4, this->target_temperature); @@ -1449,7 +1449,7 @@ void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t ClimateStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); size += ProtoSize::calc_float(1, this->current_temperature); size += ProtoSize::calc_float(1, this->target_temperature); @@ -1563,7 +1563,7 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_WATER_HEATER void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(4, this->icon); @@ -1584,7 +1584,7 @@ void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -1606,7 +1606,7 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { return size; } void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_float(2, this->current_temperature); buffer.encode_float(3, this->target_temperature); buffer.encode_uint32(4, static_cast<uint32_t>(this->mode)); @@ -1619,7 +1619,7 @@ void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t WaterHeaterStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_float(1, this->current_temperature); size += ProtoSize::calc_float(1, this->target_temperature); size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); @@ -1675,7 +1675,7 @@ bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value #ifdef USE_NUMBER void ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -1695,7 +1695,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesNumberResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -1714,7 +1714,7 @@ uint32_t ListEntitiesNumberResponse::calculate_size() const { return size; } void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_float(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -1723,7 +1723,7 @@ void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t NumberStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_float(1, this->state); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -1760,7 +1760,7 @@ bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SELECT void ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -1777,7 +1777,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesSelectResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -1795,7 +1795,7 @@ uint32_t ListEntitiesSelectResponse::calculate_size() const { return size; } void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -1804,7 +1804,7 @@ void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t SelectStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->state.size()); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -1849,7 +1849,7 @@ bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SIREN void ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -1868,7 +1868,7 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesSirenResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -1888,7 +1888,7 @@ uint32_t ListEntitiesSirenResponse::calculate_size() const { return size; } void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->state); #ifdef USE_DEVICES buffer.encode_uint32(3, this->device_id); @@ -1896,7 +1896,7 @@ void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t SirenStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->state); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -1961,7 +1961,7 @@ bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LOCK void ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -1979,7 +1979,7 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesLockResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -1996,7 +1996,7 @@ uint32_t ListEntitiesLockResponse::calculate_size() const { return size; } void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES buffer.encode_uint32(3, this->device_id); @@ -2004,7 +2004,7 @@ void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t LockStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -2054,7 +2054,7 @@ bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_BUTTON void ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -2069,7 +2069,7 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesButtonResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -2124,7 +2124,7 @@ uint32_t MediaPlayerSupportedFormat::calculate_size() const { } void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -2143,7 +2143,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -2163,7 +2163,7 @@ uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { return size; } void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); buffer.encode_float(3, this->volume); buffer.encode_bool(4, this->muted); @@ -2173,7 +2173,7 @@ void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t MediaPlayerStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); size += ProtoSize::calc_float(1, this->volume); size += ProtoSize::calc_bool(1, this->muted); @@ -2942,7 +2942,7 @@ bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengt #ifdef USE_ALARM_CONTROL_PANEL void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -2959,7 +2959,7 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer) con uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -2975,7 +2975,7 @@ uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { return size; } void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES buffer.encode_uint32(3, this->device_id); @@ -2983,7 +2983,7 @@ void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t AlarmControlPanelStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -3030,7 +3030,7 @@ bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit #ifdef USE_TEXT void ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3048,7 +3048,7 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesTextResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3065,7 +3065,7 @@ uint32_t ListEntitiesTextResponse::calculate_size() const { return size; } void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_string(2, this->state); buffer.encode_bool(3, this->missing_state); #ifdef USE_DEVICES @@ -3074,7 +3074,7 @@ void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t TextStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->state.size()); size += ProtoSize::calc_bool(1, this->missing_state); #ifdef USE_DEVICES @@ -3119,7 +3119,7 @@ bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATE void ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3133,7 +3133,7 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesDateResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3146,7 +3146,7 @@ uint32_t ListEntitiesDateResponse::calculate_size() const { return size; } void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_uint32(3, this->year); buffer.encode_uint32(4, this->month); @@ -3157,7 +3157,7 @@ void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t DateStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->missing_state); size += ProtoSize::calc_uint32(1, this->year); size += ProtoSize::calc_uint32(1, this->month); @@ -3202,7 +3202,7 @@ bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_TIME void ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3216,7 +3216,7 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesTimeResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3229,7 +3229,7 @@ uint32_t ListEntitiesTimeResponse::calculate_size() const { return size; } void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_uint32(3, this->hour); buffer.encode_uint32(4, this->minute); @@ -3240,7 +3240,7 @@ void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t TimeStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->missing_state); size += ProtoSize::calc_uint32(1, this->hour); size += ProtoSize::calc_uint32(1, this->minute); @@ -3285,7 +3285,7 @@ bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_EVENT void ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3303,7 +3303,7 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesEventResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3322,7 +3322,7 @@ uint32_t ListEntitiesEventResponse::calculate_size() const { return size; } void EventResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_string(2, this->event_type); #ifdef USE_DEVICES buffer.encode_uint32(3, this->device_id); @@ -3330,7 +3330,7 @@ void EventResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t EventResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->event_type.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -3341,7 +3341,7 @@ uint32_t EventResponse::calculate_size() const { #ifdef USE_VALVE void ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3359,7 +3359,7 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesValveResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3376,7 +3376,7 @@ uint32_t ListEntitiesValveResponse::calculate_size() const { return size; } void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_float(2, this->position); buffer.encode_uint32(3, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES @@ -3385,7 +3385,7 @@ void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t ValveStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_float(1, this->position); size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES @@ -3428,7 +3428,7 @@ bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATETIME void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3442,7 +3442,7 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesDateTimeResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3455,7 +3455,7 @@ uint32_t ListEntitiesDateTimeResponse::calculate_size() const { return size; } void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_fixed32(3, this->epoch_seconds); #ifdef USE_DEVICES @@ -3464,7 +3464,7 @@ void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t DateTimeStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->missing_state); size += ProtoSize::calc_fixed32(1, this->epoch_seconds); #ifdef USE_DEVICES @@ -3501,7 +3501,7 @@ bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_UPDATE void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(5, this->icon); @@ -3516,7 +3516,7 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesUpdateResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3530,7 +3530,7 @@ uint32_t ListEntitiesUpdateResponse::calculate_size() const { return size; } void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_fixed32(1, this->key); + buffer.write_tag_and_fixed32(13, this->key); buffer.encode_bool(2, this->missing_state); buffer.encode_bool(3, this->in_progress); buffer.encode_bool(4, this->has_progress); @@ -3546,7 +3546,7 @@ void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { } uint32_t UpdateStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_bool(1, this->missing_state); size += ProtoSize::calc_bool(1, this->in_progress); size += ProtoSize::calc_bool(1, this->has_progress); @@ -3642,7 +3642,7 @@ uint32_t ZWaveProxyRequest::calculate_size() const { #ifdef USE_INFRARED void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_string(1, this->object_id); - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); buffer.encode_string(3, this->name); #ifdef USE_ENTITY_ICON buffer.encode_string(4, this->icon); @@ -3657,7 +3657,7 @@ void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { uint32_t ListEntitiesInfraredResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->object_id.size()); - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; size += ProtoSize::calc_length(1, this->name.size()); #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); @@ -3717,7 +3717,7 @@ void InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer) const { #ifdef USE_DEVICES buffer.encode_uint32(1, this->device_id); #endif - buffer.encode_fixed32(2, this->key); + buffer.write_tag_and_fixed32(21, this->key); for (const auto &it : *this->timings) { buffer.encode_sint32(3, it, true); } @@ -3727,7 +3727,7 @@ uint32_t InfraredRFReceiveEvent::calculate_size() const { #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif - size += ProtoSize::calc_fixed32(1, this->key); + size += 5; if (!this->timings->empty()) { for (const auto &it : *this->timings) { size += ProtoSize::calc_sint32_force(1, it); diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index d6e993d3a5..cd22915703 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -236,6 +236,21 @@ class ProtoWriteBuffer { * Following https://protobuf.dev/programming-guides/encoding/#structure */ void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); } + /// Write a precomputed tag byte + 32-bit value in one operation. + /// Tag must be a single-byte varint (< 128). No zero check. + inline void write_tag_and_fixed32(uint8_t tag, uint32_t value) ESPHOME_ALWAYS_INLINE { + this->debug_check_bounds_(5); + this->pos_[0] = tag; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::memcpy(this->pos_ + 1, &value, 4); +#else + this->pos_[1] = static_cast<uint8_t>(value & 0xFF); + this->pos_[2] = static_cast<uint8_t>((value >> 8) & 0xFF); + this->pos_[3] = static_cast<uint8_t>((value >> 16) & 0xFF); + this->pos_[4] = static_cast<uint8_t>((value >> 24) & 0xFF); +#endif + this->pos_ += 5; + } void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { if (len == 0 && !force) return; @@ -276,8 +291,7 @@ class ProtoWriteBuffer { this->debug_check_bounds_(1); *this->pos_++ = value ? 0x01 : 0x00; } - // noinline: 51 call sites; inlining causes net code growth vs a single out-of-line copy - __attribute__((noinline)) void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { + void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { if (value == 0 && !force) return; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index dff6c7690a..aca31e49c8 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -254,14 +254,17 @@ class TypeInfo(ABC): def dump(self, name: str) -> str: """Dump the value to the output.""" + def calculate_tag(self) -> int: + """Calculate the protobuf tag (field_id << 3 | wire_type).""" + return (self.number << 3) | (self.wire_type & 0b111) + def calculate_field_id_size(self) -> int: """Calculates the size of a field ID in bytes. Returns: The number of bytes needed to encode the field ID """ - # Calculate the tag by combining field_id and wire_type - tag = (self.number << 3) | (self.wire_type & 0b111) + tag = self.calculate_tag() # Calculate the varint size if tag < 128: @@ -556,6 +559,16 @@ class Fixed32Type(TypeInfo): o += "out.append(buffer);" return o + @property + def encode_content(self) -> str: + tag = self.calculate_tag() + if self.force and tag < 128: + # Emit combined tag+value write: precomputed tag + direct memcpy + return f"buffer.write_tag_and_fixed32({tag}, this->{self.field_name});" + if self.force: + return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);" + return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" + def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() if force: From 6992219e341b4eca9f2bfdf28474cbf45883bd08 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 16:27:07 -1000 Subject: [PATCH 1648/2030] [core] Attribute placement new storage symbols to components (#15092) --- esphome/analyze_memory/__init__.py | 29 ++++++ esphome/analyze_memory/cli.py | 48 +++++++--- esphome/cpp_generator.py | 11 ++- .../deep_sleep/test_deep_sleep.py | 2 +- tests/component_tests/image/test_init.py | 4 +- .../mipi_dsi/test_mipi_dsi_config.py | 4 +- .../status_led/test_status_led.py | 4 +- .../test_pstorage_attribution.py | 90 +++++++++++++++++++ 8 files changed, 171 insertions(+), 21 deletions(-) create mode 100644 tests/unit_tests/analyze_memory/test_pstorage_attribution.py diff --git a/esphome/analyze_memory/__init__.py b/esphome/analyze_memory/__init__.py index 48ecf2c1dc..f56d720ec2 100644 --- a/esphome/analyze_memory/__init__.py +++ b/esphome/analyze_memory/__init__.py @@ -56,6 +56,10 @@ _COMPONENT_PREFIX_LIB = "[lib]" _COMPONENT_CORE = f"{_COMPONENT_PREFIX_ESPHOME}core" _COMPONENT_API = f"{_COMPONENT_PREFIX_ESPHOME}api" +# Placement new storage suffix (generated by codegen Pvariable) +_PSTORAGE_SUFFIX = "__pstorage" + + # C++ namespace prefixes _NAMESPACE_ESPHOME = "esphome::" _NAMESPACE_STD = "std::" @@ -332,6 +336,13 @@ class MemoryAnalyzer: # Demangle C++ names if needed demangled = self._demangle_symbol(symbol_name) + # Check for placement new storage symbols (generated by codegen) + # Format: {component}__{id}__pstorage + if demangled.endswith(_PSTORAGE_SUFFIX) and ( + component := self._match_pstorage_component(demangled) + ): + return component + # Check for special component classes first (before namespace pattern) # This handles cases like esphome::ESPHomeOTAComponent which should map to ota if _NAMESPACE_ESPHOME in demangled: @@ -399,6 +410,24 @@ class MemoryAnalyzer: # Track uncategorized symbols for analysis return "other" + def _match_pstorage_component(self, symbol_name: str) -> str | None: + """Match a __pstorage symbol to its ESPHome component. + + Symbol format: {component}__{id}__pstorage + The component namespace is embedded by codegen before the double underscore. + """ + prefix = symbol_name[: -len(_PSTORAGE_SUFFIX)] + # Extract component namespace before the first double underscore + dunder_pos = prefix.find("__") + if dunder_pos == -1: + return None + component_name = prefix[:dunder_pos] + if component_name in get_esphome_components(): + return f"{_COMPONENT_PREFIX_ESPHOME}{component_name}" + if component_name in self.external_components: + return f"{_COMPONENT_PREFIX_EXTERNAL}{component_name}" + return None + def _batch_demangle_symbols(self, symbols: list[str]) -> None: """Batch demangle C++ symbol names for efficiency.""" if not symbols: diff --git a/esphome/analyze_memory/cli.py b/esphome/analyze_memory/cli.py index acaf5f4562..b7561e8ffc 100644 --- a/esphome/analyze_memory/cli.py +++ b/esphome/analyze_memory/cli.py @@ -15,6 +15,7 @@ from . import ( _COMPONENT_PREFIX_ESPHOME, _COMPONENT_PREFIX_EXTERNAL, _COMPONENT_PREFIX_LIB, + _PSTORAGE_SUFFIX, RAM_SECTIONS, MemoryAnalyzer, ) @@ -23,6 +24,17 @@ if TYPE_CHECKING: from . import ComponentMemory +def _format_pstorage_name(name: str) -> str: + """Format a __pstorage symbol as 'storage for {id}'.""" + if not name.endswith(_PSTORAGE_SUFFIX): + return name + prefix = name[: -len(_PSTORAGE_SUFFIX)] + # Strip component namespace prefix: {component}__{id} -> {id} + dunder_pos = prefix.find("__") + var_id = prefix[dunder_pos + 2 :] if dunder_pos != -1 else prefix + return f"storage for {var_id}" + + class MemoryAnalyzerCLI(MemoryAnalyzer): """Memory analyzer with CLI-specific report generation.""" @@ -148,11 +160,14 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): If section is one of the RAM sections (.data or .bss), a label like " [data]" or " [bss]" is appended. For non-RAM sections or when section is None, no section label is added. + + Placement new storage symbols are formatted as "storage for {id}". """ + display_name = _format_pstorage_name(demangled) section_label = "" if section in RAM_SECTIONS: section_label = f" [{section[1:]}]" # .data -> [data], .bss -> [bss] - return f"{demangled} ({size:,} B){section_label}" + return f"{display_name} ({size:,} B){section_label}" def _add_top_symbols(self, lines: list[str]) -> None: """Add a section showing the top largest symbols in the binary.""" @@ -175,11 +190,13 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): for i, (_, demangled, size, section, component) in enumerate(top_symbols): # Format section label section_label = f"[{section[1:]}]" if section else "" - # Truncate demangled name if too long + # Format storage symbols readably + display_name = _format_pstorage_name(demangled) + # Truncate if too long demangled_display = ( - f"{demangled[:truncate_limit]}..." - if len(demangled) > self.COL_TOP_SYMBOL_NAME - else demangled + f"{display_name[:truncate_limit]}..." + if len(display_name) > self.COL_TOP_SYMBOL_NAME + else display_name ) lines.append( f"{i + 1:>2}. {size:>7,} B {section_label:<8} {demangled_display:<{self.COL_TOP_SYMBOL_NAME}} {component}" @@ -573,15 +590,16 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): lines.append(f"Total size: {comp_mem.flash_total:,} B") lines.append("") - # Show all symbols above threshold for better visibility + # Show symbols above threshold, always include storage symbols large_symbols = [ (sym, dem, size, sec) for sym, dem, size, sec in sorted_symbols if size > self.SYMBOL_SIZE_THRESHOLD + or dem.endswith(_PSTORAGE_SUFFIX) ] lines.append( - f"{comp_name} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B ({len(large_symbols)} symbols):" + f"{comp_name} Symbols > {self.SYMBOL_SIZE_THRESHOLD} B & storage ({len(large_symbols)} symbols):" ) for i, (symbol, demangled, size, section) in enumerate(large_symbols): lines.append( @@ -604,7 +622,10 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): # Sort by size descending sorted_ram_syms = sorted(ram_syms, key=lambda x: x[2], reverse=True) large_ram_syms = [ - s for s in sorted_ram_syms if s[2] > self.RAM_SYMBOL_SIZE_THRESHOLD + s + for s in sorted_ram_syms + if s[2] > self.RAM_SYMBOL_SIZE_THRESHOLD + or s[1].endswith(_PSTORAGE_SUFFIX) ] lines.append(f"{name} ({mem.ram_total:,} B total RAM):") @@ -622,13 +643,14 @@ class MemoryAnalyzerCLI(MemoryAnalyzer): for symbol, demangled, size, section in large_ram_syms[:10]: # Format section label consistently by stripping leading dot section_label = section.lstrip(".") if section else "" + display_name = _format_pstorage_name(demangled) # Add ellipsis if name is truncated - demangled_display = ( - f"{demangled[:70]}..." if len(demangled) > 70 else demangled - ) - lines.append( - f" {size:>6,} B [{section_label}] {demangled_display}" + display_name = ( + f"{display_name[:70]}..." + if len(display_name) > 70 + else display_name ) + lines.append(f" {size:>6,} B [{section_label}] {display_name}") if len(large_ram_syms) > 10: lines.append(f" ... and {len(large_ram_syms) - 10} more") lines.append("") diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index 3ed5d0ba37..e97bd71a48 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -584,7 +584,16 @@ def Pvariable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": # For 'new' allocations, use placement new into static storage # to avoid heap fragmentation on embedded devices. the_type = id_.type - storage_name = f"{id_.id}__pstorage" + # Extract component namespace from type for memory analysis attribution + type_str = str(the_type) + # Strip leading esphome:: to get the component namespace + # e.g. esphome::dsmr::Dsmr -> dsmr, logger::Logger -> logger + bare = type_str.removeprefix("esphome::") + if "::" in bare: + component_ns = bare.split("::", maxsplit=1)[0].rstrip("_") + else: + component_ns = "esphome" + storage_name = f"{component_ns}__{id_.id}__pstorage" # Declare aligned byte array for the object storage CORE.add_global( diff --git a/tests/component_tests/deep_sleep/test_deep_sleep.py b/tests/component_tests/deep_sleep/test_deep_sleep.py index 212f61e44b..8c1278a332 100644 --- a/tests/component_tests/deep_sleep/test_deep_sleep.py +++ b/tests/component_tests/deep_sleep/test_deep_sleep.py @@ -8,7 +8,7 @@ def test_deep_sleep_setup(generate_main): main_cpp = generate_main("tests/component_tests/deep_sleep/test_deep_sleep1.yaml") assert ( - "static deep_sleep::DeepSleepComponent *const deepsleep = reinterpret_cast<deep_sleep::DeepSleepComponent *>(deepsleep__pstorage);" + "static deep_sleep::DeepSleepComponent *const deepsleep = reinterpret_cast<deep_sleep::DeepSleepComponent *>(deep_sleep__deepsleep__pstorage);" in main_cpp ) assert "new(deepsleep) deep_sleep::DeepSleepComponent();" in main_cpp diff --git a/tests/component_tests/image/test_init.py b/tests/component_tests/image/test_init.py index 9003a4ee5d..6f73888c7d 100644 --- a/tests/component_tests/image/test_init.py +++ b/tests/component_tests/image/test_init.py @@ -242,11 +242,11 @@ def test_image_generation( main_cpp = generate_main(component_config_path("image_test.yaml")) assert "uint8_t_id[] PROGMEM = {0x24, 0x21, 0x24, 0x21" in main_cpp assert ( - "alignas(image::Image) static unsigned char cat_img__pstorage[sizeof(image::Image)];" + "alignas(image::Image) static unsigned char image__cat_img__pstorage[sizeof(image::Image)];" in main_cpp ) assert ( - "static image::Image *const cat_img = reinterpret_cast<image::Image *>(cat_img__pstorage);" + "static image::Image *const cat_img = reinterpret_cast<image::Image *>(image__cat_img__pstorage);" in main_cpp ) assert ( diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index e6f344b086..1ae8cc644e 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -119,11 +119,11 @@ def test_code_generation( main_cpp = generate_main(component_fixture_path("mipi_dsi.yaml")) assert ( - "alignas(mipi_dsi::MIPI_DSI) static unsigned char p4_nano__pstorage[sizeof(mipi_dsi::MIPI_DSI)];" + "alignas(mipi_dsi::MIPI_DSI) static unsigned char mipi_dsi__p4_nano__pstorage[sizeof(mipi_dsi::MIPI_DSI)];" in main_cpp ) assert ( - "static mipi_dsi::MIPI_DSI *const p4_nano = reinterpret_cast<mipi_dsi::MIPI_DSI *>(p4_nano__pstorage);" + "static mipi_dsi::MIPI_DSI *const p4_nano = reinterpret_cast<mipi_dsi::MIPI_DSI *>(mipi_dsi__p4_nano__pstorage);" in main_cpp ) assert ( diff --git a/tests/component_tests/status_led/test_status_led.py b/tests/component_tests/status_led/test_status_led.py index 0e96e631f5..f7e0a9de86 100644 --- a/tests/component_tests/status_led/test_status_led.py +++ b/tests/component_tests/status_led/test_status_led.py @@ -13,11 +13,11 @@ def test_status_led_generation( """Test status_led generation.""" main_cpp = generate_main(component_config_path("status_led_test.yaml")) assert ( - "alignas(status_led::StatusLED) static unsigned char status_led_statusled_id__pstorage[sizeof(status_led::StatusLED)];" + "alignas(status_led::StatusLED) static unsigned char status_led__status_led_statusled_id__pstorage[sizeof(status_led::StatusLED)];" in main_cpp ) assert ( - "static status_led::StatusLED *const status_led_statusled_id = reinterpret_cast<status_led::StatusLED *>(status_led_statusled_id__pstorage);" + "static status_led::StatusLED *const status_led_statusled_id = reinterpret_cast<status_led::StatusLED *>(status_led__status_led_statusled_id__pstorage);" in main_cpp ) assert "new(status_led_statusled_id) status_led::StatusLED(" in main_cpp diff --git a/tests/unit_tests/analyze_memory/test_pstorage_attribution.py b/tests/unit_tests/analyze_memory/test_pstorage_attribution.py new file mode 100644 index 0000000000..a57b283f44 --- /dev/null +++ b/tests/unit_tests/analyze_memory/test_pstorage_attribution.py @@ -0,0 +1,90 @@ +"""Tests for __pstorage symbol attribution in memory analyzer.""" + +from unittest.mock import patch + +from esphome.analyze_memory import _PSTORAGE_SUFFIX, MemoryAnalyzer + + +def _make_analyzer(external_components: set[str] | None = None) -> MemoryAnalyzer: + """Create a MemoryAnalyzer with mocked dependencies.""" + with patch.object(MemoryAnalyzer, "__init__", lambda self, *a, **kw: None): + analyzer = MemoryAnalyzer.__new__(MemoryAnalyzer) + analyzer.external_components = external_components or set() + return analyzer + + +def test_pstorage_suffix_constant() -> None: + """Verify the suffix constant matches what codegen produces.""" + assert _PSTORAGE_SUFFIX == "__pstorage" + + +def test_match_pstorage_simple_component() -> None: + """Simple component name like 'logger'.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("logger__logger_id__pstorage") + assert result == "[esphome]logger" + + +def test_match_pstorage_underscore_component() -> None: + """Component with underscore like 'web_server'.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("web_server__webserver_id__pstorage") + assert result == "[esphome]web_server" + + +def test_match_pstorage_api() -> None: + """API component.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("api__apiserver_id__pstorage") + assert result == "[esphome]api" + + +def test_match_pstorage_deep_sleep() -> None: + """Component with underscore: deep_sleep.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("deep_sleep__deepsleep__pstorage") + assert result == "[esphome]deep_sleep" + + +def test_match_pstorage_status_led() -> None: + """Component with underscore: status_led.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("status_led__statusled_id__pstorage") + assert result == "[esphome]status_led" + + +def test_match_pstorage_external_component() -> None: + """External component should be attributed correctly.""" + analyzer = _make_analyzer(external_components={"my_custom"}) + result = analyzer._match_pstorage_component("my_custom__thing_id__pstorage") + assert result == "[external]my_custom" + + +def test_match_pstorage_no_dunder_returns_none() -> None: + """Symbol without double underscore separator returns None.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("something__pstorage") + assert result is None + + +def test_match_pstorage_unknown_component_returns_none() -> None: + """Unknown component namespace returns None.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("nonexistent__thing_id__pstorage") + assert result is None + + +def test_match_pstorage_esphome_component() -> None: + """esphome:: namespace types map to the esphome component.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component( + "esphome__esphomeotacomponent_id__pstorage" + ) + assert result == "[esphome]esphome" + + +def test_match_pstorage_user_id_with_component_prefix() -> None: + """User-chosen ID that happens to contain a component name.""" + analyzer = _make_analyzer() + result = analyzer._match_pstorage_component("logger__relay1__pstorage") + assert result == "[esphome]logger" From 98d9fd76b35f995e14fca86e07515317f2220d22 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 16:27:20 -1000 Subject: [PATCH 1649/2030] [mqtt] Fix const-correctness for trigger constructors (#15093) --- esphome/components/mqtt/mqtt_client.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/mqtt/mqtt_client.h b/esphome/components/mqtt/mqtt_client.h index 0d52d98d2f..14473f737a 100644 --- a/esphome/components/mqtt/mqtt_client.h +++ b/esphome/components/mqtt/mqtt_client.h @@ -366,14 +366,14 @@ class MQTTJsonMessageTrigger : public Trigger<JsonObjectConst> { class MQTTConnectTrigger : public Trigger<bool> { public: - explicit MQTTConnectTrigger(MQTTClientComponent *&client) { + explicit MQTTConnectTrigger(MQTTClientComponent *client) { client->set_on_connect([this](bool session_present) { this->trigger(session_present); }); } }; class MQTTDisconnectTrigger : public Trigger<MQTTClientDisconnectReason> { public: - explicit MQTTDisconnectTrigger(MQTTClientComponent *&client) { + explicit MQTTDisconnectTrigger(MQTTClientComponent *client) { client->set_on_disconnect([this](MQTTClientDisconnectReason reason) { this->trigger(reason); }); } }; From 8a3b5a8defe9d2f58ce9b1ca4447e2d0bfe8f77e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 17:09:23 -1000 Subject: [PATCH 1650/2030] [core] Fix placement new storage name for templated types (#15096) --- esphome/cpp_generator.py | 32 ++++++++++++++++++++++++-------- tests/unit_tests/test_codegen.py | 27 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 8 deletions(-) diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index e97bd71a48..a8efe96cce 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -565,6 +565,29 @@ def new_variable( return obj +def _extract_component_ns(type_str: str) -> str: + """Extract the component namespace from a fully-qualified C++ type string. + + Strips leading ``esphome::`` and template arguments, then returns + the first namespace segment. Falls back to ``"esphome"`` when the + type has no namespace qualifier (after stripping templates). + + Examples:: + + esphome::dsmr::Dsmr -> dsmr + esphome::logger::Logger -> logger + esphome::Automation<std::optional<bool>, std::optional<bool>> -> esphome + Logger -> esphome + """ + bare = type_str.removeprefix("esphome::") + # Strip template arguments before namespace extraction to avoid + # matching :: inside template params (e.g. Automation<std::optional<bool>>) + bare_no_template = bare.split("<", maxsplit=1)[0] + if "::" in bare_no_template: + return bare_no_template.split("::", maxsplit=1)[0].rstrip("_") + return "esphome" + + def Pvariable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": """Declare a new pointer variable in the code generation. @@ -585,14 +608,7 @@ def Pvariable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": # to avoid heap fragmentation on embedded devices. the_type = id_.type # Extract component namespace from type for memory analysis attribution - type_str = str(the_type) - # Strip leading esphome:: to get the component namespace - # e.g. esphome::dsmr::Dsmr -> dsmr, logger::Logger -> logger - bare = type_str.removeprefix("esphome::") - if "::" in bare: - component_ns = bare.split("::", maxsplit=1)[0].rstrip("_") - else: - component_ns = "esphome" + component_ns = _extract_component_ns(str(the_type)) storage_name = f"{component_ns}__{id_.id}__pstorage" # Declare aligned byte array for the object storage diff --git a/tests/unit_tests/test_codegen.py b/tests/unit_tests/test_codegen.py index 3f32a117ff..8d01fef7c2 100644 --- a/tests/unit_tests/test_codegen.py +++ b/tests/unit_tests/test_codegen.py @@ -1,6 +1,7 @@ import pytest from esphome import codegen as cg +from esphome.cpp_generator import _extract_component_ns # Test interface remains the same. @@ -75,3 +76,29 @@ from esphome import codegen as cg ) def test_exists(attr): assert hasattr(cg, attr) + + +@pytest.mark.parametrize( + ("type_str", "expected"), + ( + ("esphome::dsmr::Dsmr", "dsmr"), + ("esphome::logger::Logger", "logger"), + ("esphome::web_server::WebServer", "web_server"), + ("esphome::deep_sleep::DeepSleep", "deep_sleep"), + ("esphome::Component", "esphome"), + ("Logger", "esphome"), + # Template types with :: in template args must not confuse extraction + ( + "esphome::Automation<std::optional<bool>, std::optional<bool>>", + "esphome", + ), + ( + "esphome::StatelessLambdaAction<std::optional<bool>, std::optional<bool>>", + "esphome", + ), + # Namespaced template type + ("esphome::sensor::Sensor<std::string>", "sensor"), + ), +) +def test_extract_component_ns(type_str, expected): + assert _extract_component_ns(type_str) == expected From 597bb185432ac4b5c069bf7936ff9a425af94641 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 17:30:57 -1000 Subject: [PATCH 1651/2030] [benchmark] Add binary sensor publish and sensor filter benchmarks (#15035) --- .../components/binary_sensor/__init__.py | 5 ++ .../bench_binary_sensor_publish.cpp | 61 +++++++++++++++ .../components/binary_sensor/benchmark.yaml | 1 + .../benchmarks/components/sensor/__init__.py | 12 +++ .../components/sensor/bench_sensor_filter.cpp | 78 +++++++++++++++++++ .../components/sensor/benchmark.yaml | 1 + 6 files changed, 158 insertions(+) create mode 100644 tests/benchmarks/components/binary_sensor/__init__.py create mode 100644 tests/benchmarks/components/binary_sensor/bench_binary_sensor_publish.cpp create mode 100644 tests/benchmarks/components/binary_sensor/benchmark.yaml create mode 100644 tests/benchmarks/components/sensor/__init__.py create mode 100644 tests/benchmarks/components/sensor/bench_sensor_filter.cpp create mode 100644 tests/benchmarks/components/sensor/benchmark.yaml diff --git a/tests/benchmarks/components/binary_sensor/__init__.py b/tests/benchmarks/components/binary_sensor/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/binary_sensor/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/binary_sensor/bench_binary_sensor_publish.cpp b/tests/benchmarks/components/binary_sensor/bench_binary_sensor_publish.cpp new file mode 100644 index 0000000000..8bae943e2e --- /dev/null +++ b/tests/benchmarks/components/binary_sensor/bench_binary_sensor_publish.cpp @@ -0,0 +1,61 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/binary_sensor/binary_sensor.h" + +namespace esphome::binary_sensor::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Benchmark: publish_state with alternating values (forces state change every time) +static void BinarySensorPublish_Alternating(benchmark::State &state) { + BinarySensor sensor; + + // First publish to establish initial state + sensor.publish_initial_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(i % 2 == 0); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(BinarySensorPublish_Alternating); + +// Benchmark: publish_state with same value (tests dedup fast path) +static void BinarySensorPublish_NoChange(benchmark::State &state) { + BinarySensor sensor; + + sensor.publish_initial_state(true); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(true); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(BinarySensorPublish_NoChange); + +// Benchmark: publish_state with a callback registered +static void BinarySensorPublish_WithCallback(benchmark::State &state) { + BinarySensor sensor; + + int callback_count = 0; + sensor.add_on_state_callback([&callback_count](bool) { callback_count++; }); + + sensor.publish_initial_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(i % 2 == 0); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(BinarySensorPublish_WithCallback); + +} // namespace esphome::binary_sensor::benchmarks diff --git a/tests/benchmarks/components/binary_sensor/benchmark.yaml b/tests/benchmarks/components/binary_sensor/benchmark.yaml new file mode 100644 index 0000000000..fc0db6c52c --- /dev/null +++ b/tests/benchmarks/components/binary_sensor/benchmark.yaml @@ -0,0 +1 @@ +binary_sensor: diff --git a/tests/benchmarks/components/sensor/__init__.py b/tests/benchmarks/components/sensor/__init__.py new file mode 100644 index 0000000000..5a593aa8c2 --- /dev/null +++ b/tests/benchmarks/components/sensor/__init__.py @@ -0,0 +1,12 @@ +import esphome.codegen as cg +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # Sensor filter benchmarks need USE_SENSOR_FILTER defined. + # We use a custom to_code instead of enable_codegen() to avoid + # pulling in the full sensor component setup. + async def to_code(config): + cg.add_define("USE_SENSOR_FILTER") + + manifest.to_code = to_code diff --git a/tests/benchmarks/components/sensor/bench_sensor_filter.cpp b/tests/benchmarks/components/sensor/bench_sensor_filter.cpp new file mode 100644 index 0000000000..e4aa397690 --- /dev/null +++ b/tests/benchmarks/components/sensor/bench_sensor_filter.cpp @@ -0,0 +1,78 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/sensor/sensor.h" +#include "esphome/components/sensor/filter.h" + +namespace esphome::sensor::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Benchmark: sensor publish through a SlidingWindowMovingAverageFilter (window=5, send_every=1) +static void SensorFilter_SlidingWindowAvg(benchmark::State &state) { + Sensor sensor; + + // Create filter: window_size=5, send_every=1, send_first_at=1 + auto *filter = new SlidingWindowMovingAverageFilter(5, 1, 1); + sensor.add_filter(filter); + + float value = 0.0f; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(value); + value += 0.1f; + if (value > 1000.0f) + value = 0.0f; + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorFilter_SlidingWindowAvg); + +// Benchmark: sensor publish through ExponentialMovingAverageFilter +static void SensorFilter_ExponentialMovingAvg(benchmark::State &state) { + Sensor sensor; + + // alpha=0.1, send_every=1, send_first_at=1 + auto *filter = new ExponentialMovingAverageFilter(0.1f, 1, 1); + sensor.add_filter(filter); + + float value = 0.0f; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(value); + value += 0.1f; + if (value > 1000.0f) + value = 0.0f; + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorFilter_ExponentialMovingAvg); + +// Benchmark: sensor publish through a chain of 3 filters (offset + multiply + sliding window) +static void SensorFilter_Chain3(benchmark::State &state) { + Sensor sensor; + + sensor.add_filters({ + new OffsetFilter(1.0f), + new MultiplyFilter(2.0f), + new SlidingWindowMovingAverageFilter(5, 1, 1), + }); + + float value = 0.0f; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(value); + value += 0.1f; + if (value > 1000.0f) + value = 0.0f; + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorFilter_Chain3); + +} // namespace esphome::sensor::benchmarks diff --git a/tests/benchmarks/components/sensor/benchmark.yaml b/tests/benchmarks/components/sensor/benchmark.yaml new file mode 100644 index 0000000000..e1fb52cdd6 --- /dev/null +++ b/tests/benchmarks/components/sensor/benchmark.yaml @@ -0,0 +1 @@ +sensor: From 0de2c758aa1c42d6b9734fb410244c18bf7156f7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 17:31:27 -1000 Subject: [PATCH 1652/2030] [scheduler] Use placement-new for std::function move in set_timer_common_ (#14757) --- esphome/core/scheduler.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 51cbfb208e..9ee3b2fdd2 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -166,7 +166,13 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type item->component = component; item->set_name(name_type, static_name, hash_or_id); item->type = type; - item->callback = std::move(func); + // Use destroy + placement-new instead of move-assignment. + // GCC's std::function::operator=(function&&) does a full swap dance even when the + // target is empty. Since recycled/new items always have an empty callback, we can + // destroy the empty one (no-op) and move-construct directly, saving ~40 bytes of + // swap/destructor code on Xtensa. + item->callback.~function(); + new (&item->callback) std::function<void()>(std::move(func)); // Reset remove flag - recycled items may have been cancelled (remove=true) in previous use this->set_item_removed_(item, false); item->is_retry = is_retry; From baf365404cb2b2d9a359718661a31f1c8d2604f5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 18:18:43 -1000 Subject: [PATCH 1653/2030] [network] Inline get_use_address() to eliminate function call overhead (#14942) --- .../ethernet/ethernet_component.cpp | 6 ----- .../components/ethernet/ethernet_component.h | 4 ++-- esphome/components/network/util.cpp | 24 ------------------- esphome/components/network/util.h | 24 ++++++++++++++++++- esphome/components/openthread/openthread.cpp | 6 ----- esphome/components/openthread/openthread.h | 4 ++-- esphome/components/wifi/wifi_component.cpp | 4 ---- esphome/components/wifi/wifi_component.h | 4 ++-- 8 files changed, 29 insertions(+), 47 deletions(-) diff --git a/esphome/components/ethernet/ethernet_component.cpp b/esphome/components/ethernet/ethernet_component.cpp index 4421a1c7aa..42cb0b3cfc 100644 --- a/esphome/components/ethernet/ethernet_component.cpp +++ b/esphome/components/ethernet/ethernet_component.cpp @@ -18,12 +18,6 @@ void EthernetComponent::set_type(EthernetType type) { this->type_ = type; } void EthernetComponent::set_manual_ip(const ManualIP &manual_ip) { this->manual_ip_ = manual_ip; } #endif -// set_use_address() is guaranteed to be called during component setup by Python code generation, -// so use_address_ will always be valid when get_use_address() is called - no fallback needed. -const char *EthernetComponent::get_use_address() const { return this->use_address_; } - -void EthernetComponent::set_use_address(const char *use_address) { this->use_address_ = use_address; } - #ifdef USE_ETHERNET_IP_STATE_LISTENERS void EthernetComponent::notify_ip_state_listeners_() { auto ips = this->get_ip_addresses(); diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 88a86bc043..b6699e8020 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -103,8 +103,8 @@ class EthernetComponent final : public Component { network::IPAddresses get_ip_addresses(); network::IPAddress get_dns_address(uint8_t num); - const char *get_use_address() const; - void set_use_address(const char *use_address); + const char *get_use_address() const { return this->use_address_; } + void set_use_address(const char *use_address) { this->use_address_ = use_address; } void get_eth_mac_address_raw(uint8_t *mac); // Remove before 2026.9.0 ESPDEPRECATED("Use get_eth_mac_address_pretty_into_buffer() instead. Removed in 2026.9.0", "2026.3.0") diff --git a/esphome/components/network/util.cpp b/esphome/components/network/util.cpp index 226b11b8cd..79ddd3844c 100644 --- a/esphome/components/network/util.cpp +++ b/esphome/components/network/util.cpp @@ -42,29 +42,5 @@ network::IPAddresses get_ip_addresses() { return {}; } -const char *get_use_address() { - // Global component pointers are guaranteed to be set by component constructors when USE_* is defined -#ifdef USE_ETHERNET - return ethernet::global_eth_component->get_use_address(); -#endif - -#ifdef USE_MODEM - return modem::global_modem_component->get_use_address(); -#endif - -#ifdef USE_WIFI - return wifi::global_wifi_component->get_use_address(); -#endif - -#ifdef USE_OPENTHREAD - return openthread::global_openthread_component->get_use_address(); -#endif - -#if !defined(USE_ETHERNET) && !defined(USE_MODEM) && !defined(USE_WIFI) && !defined(USE_OPENTHREAD) - // Fallback when no network component is defined (e.g., host platform) - return ""; -#endif -} - } // namespace esphome::network #endif diff --git a/esphome/components/network/util.h b/esphome/components/network/util.h index 4b700fe74c..e4e8a01f8c 100644 --- a/esphome/components/network/util.h +++ b/esphome/components/network/util.h @@ -54,7 +54,29 @@ ESPHOME_ALWAYS_INLINE inline bool is_connected() { /// Return whether the network is disabled (only wifi for now) bool is_disabled(); /// Get the active network hostname -const char *get_use_address(); +ESPHOME_ALWAYS_INLINE inline const char *get_use_address() { + // Global component pointers are guaranteed to be set by component constructors when USE_* is defined +#ifdef USE_ETHERNET + return ethernet::global_eth_component->get_use_address(); +#endif + +#ifdef USE_MODEM + return modem::global_modem_component->get_use_address(); +#endif + +#ifdef USE_WIFI + return wifi::global_wifi_component->get_use_address(); +#endif + +#ifdef USE_OPENTHREAD + return openthread::global_openthread_component->get_use_address(); +#endif + +#if !defined(USE_ETHERNET) && !defined(USE_MODEM) && !defined(USE_WIFI) && !defined(USE_OPENTHREAD) + // Fallback when no network component is defined (e.g., host platform) + return ""; +#endif +} IPAddresses get_ip_addresses(); } // namespace esphome::network diff --git a/esphome/components/openthread/openthread.cpp b/esphome/components/openthread/openthread.cpp index 1596b6e990..7c9a308303 100644 --- a/esphome/components/openthread/openthread.cpp +++ b/esphome/components/openthread/openthread.cpp @@ -257,11 +257,5 @@ void OpenThreadComponent::on_factory_reset(std::function<void()> callback) { ESP_LOGD(TAG, "Waiting on Confirmation Removal SRP Host and Services"); } -// set_use_address() is guaranteed to be called during component setup by Python code generation, -// so use_address_ will always be valid when get_use_address() is called - no fallback needed. -const char *OpenThreadComponent::get_use_address() const { return this->use_address_; } - -void OpenThreadComponent::set_use_address(const char *use_address) { this->use_address_ = use_address; } - } // namespace esphome::openthread #endif diff --git a/esphome/components/openthread/openthread.h b/esphome/components/openthread/openthread.h index bd10774fcf..b42fdd2d30 100644 --- a/esphome/components/openthread/openthread.h +++ b/esphome/components/openthread/openthread.h @@ -37,8 +37,8 @@ class OpenThreadComponent : public Component { void on_factory_reset(std::function<void()> callback); void defer_factory_reset_external_callback(); - const char *get_use_address() const; - void set_use_address(const char *use_address); + const char *get_use_address() const { return this->use_address_; } + void set_use_address(const char *use_address) { this->use_address_ = use_address; } #if CONFIG_OPENTHREAD_MTD void set_poll_period(uint32_t poll_period) { this->poll_period_ = poll_period; } #endif diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 08065a7544..0fd1385258 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -891,10 +891,6 @@ network::IPAddress WiFiComponent::get_dns_address(int num) { return this->wifi_dns_ip_(num); return {}; } -// set_use_address() is guaranteed to be called during component setup by Python code generation, -// so use_address_ will always be valid when get_use_address() is called - no fallback needed. -const char *WiFiComponent::get_use_address() const { return this->use_address_; } -void WiFiComponent::set_use_address(const char *use_address) { this->use_address_ = use_address; } #ifdef USE_WIFI_AP void WiFiComponent::setup_ap_config_() { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index bd202604d6..718f4a6e12 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -481,8 +481,8 @@ class WiFiComponent final : public Component { network::IPAddress get_dns_address(int num); network::IPAddresses get_ip_addresses(); - const char *get_use_address() const; - void set_use_address(const char *use_address); + const char *get_use_address() const { return this->use_address_; } + void set_use_address(const char *use_address) { this->use_address_ = use_address; } const wifi_scan_vector_t<WiFiScanResult> &get_scan_result() const { return scan_result_; } From e67b5a78d0b4fd4d06ddc347141eb4e19c7d4f10 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 20:51:40 -1000 Subject: [PATCH 1654/2030] [esp32] Patch DRAM segment for testing mode to fix grouped component test overflow (#15102) --- esphome/components/esp32/iram_fix.py.script | 70 ++++++++++++--------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/esphome/components/esp32/iram_fix.py.script b/esphome/components/esp32/iram_fix.py.script index 0d23f9a81b..b656d7d1a6 100644 --- a/esphome/components/esp32/iram_fix.py.script +++ b/esphome/components/esp32/iram_fix.py.script @@ -4,12 +4,40 @@ import re # pylint: disable=E0602 Import("env") # noqa -# IRAM size for testing mode (2MB - large enough to accommodate grouped tests) -TESTING_IRAM_SIZE = 0x200000 +# Memory sizes for testing mode (large enough to accommodate grouped tests) +TESTING_IRAM_SIZE = 0x200000 # 2MB +TESTING_DRAM_SIZE = 0x200000 # 2MB + + +def patch_segment(content, segment_name, new_size): + """Patch a memory segment's length in linker script content. + + Handles both single-line and multi-line segment definitions, e.g.: + iram0_0_seg (RX) : org = 0x40080000, len = 0x20000 + 0x0 + or split across lines: + dram0_0_seg (RW) : org = 0x3FFB0000 + 0xdb5c, + len = 0x2c200 - 0xdb5c + + Args: + content: Full linker script content as string + segment_name: Name of the segment (e.g., 'iram0_0_seg') + new_size: New size as integer + + Returns: + Tuple of (new_content, was_patched) + """ + # Match segment name through to "len = <value>" allowing newlines between org and len + pattern = rf'({re.escape(segment_name)}\s*\([^)]*\)\s*:\s*org\s*=\s*.+?,\s*len\s*=\s*)(\S+[^\n]*)' + if match := re.search(pattern, content, re.DOTALL): + replacement = f"{match.group(1)}{new_size:#x}" + new_content = content[:match.start()] + replacement + content[match.end():] + if new_content != content: + return new_content, True + return content, False def patch_idf_linker_script(source, target, env): - """Patch ESP-IDF linker script to increase IRAM size for testing mode.""" + """Patch ESP-IDF linker script to increase IRAM and DRAM size for testing mode.""" # Check if we're in testing mode by looking for the define build_flags = env.get("BUILD_FLAGS", []) testing_mode = any("-DESPHOME_TESTING_MODE" in flag for flag in build_flags) @@ -34,36 +62,22 @@ def patch_idf_linker_script(source, target, env): print(f"ESPHome: Error reading linker script: {e}") return - # Check if this file contains iram0_0_seg - if 'iram0_0_seg' not in content: - print(f"ESPHome: Warning - iram0_0_seg not found in {memory_ld}") - return + patches = [] - # Look for iram0_0_seg definition and increase its length - # ESP-IDF format can be: - # iram0_0_seg (RX) : org = 0x40080000, len = 0x20000 + 0x0 - # or more complex with nested parentheses: - # iram0_0_seg (RX) : org = (0x40370000 + 0x4000), len = (((0x403CB700 - (0x40378000 - 0x3FC88000)) - 0x3FC88000) + 0x8000 - 0x4000) - # We want to change len to TESTING_IRAM_SIZE for testing + content, patched = patch_segment(content, 'iram0_0_seg', TESTING_IRAM_SIZE) + if patched: + patches.append(f"IRAM={TESTING_IRAM_SIZE:#x}") - # Use a more robust approach: find the line and manually parse it - lines = content.split('\n') - for i, line in enumerate(lines): - if 'iram0_0_seg' in line and 'len' in line: - # Find the position of "len = " and replace everything after it until the end of the statement - match = re.search(r'(iram0_0_seg\s*\([^)]*\)\s*:\s*org\s*=\s*(?:\([^)]+\)|0x[0-9a-fA-F]+)\s*,\s*len\s*=\s*)(.+?)(\s*)$', line) - if match: - lines[i] = f"{match.group(1)}{TESTING_IRAM_SIZE:#x}{match.group(3)}" - break + content, patched = patch_segment(content, 'dram0_0_seg', TESTING_DRAM_SIZE) + if patched: + patches.append(f"DRAM={TESTING_DRAM_SIZE:#x}") - updated = '\n'.join(lines) - - if updated != content: + if patches: with open(memory_ld, "w") as f: - f.write(updated) - print(f"ESPHome: Patched IRAM size to {TESTING_IRAM_SIZE:#x} in {memory_ld} for testing mode") + f.write(content) + print(f"ESPHome: Patched {', '.join(patches)} in {memory_ld} for testing mode") else: - print(f"ESPHome: Warning - could not patch iram0_0_seg in {memory_ld}") + print(f"ESPHome: Warning - could not patch memory segments in {memory_ld}") # Hook into the build process before linking From 225330413a137acbff12e81127b983ad05d92e00 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 23 Mar 2026 01:55:14 -0500 Subject: [PATCH 1655/2030] [uart] Rename `FlushResult` to `UARTFlushResult` with `UART_FLUSH_RESULT_` prefix (#15101) Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> --- esphome/components/api/api_connection.cpp | 8 ++++---- esphome/components/ble_nus/ble_nus.cpp | 6 +++--- esphome/components/ble_nus/ble_nus.h | 2 +- .../components/serial_proxy/serial_proxy.cpp | 2 +- .../components/serial_proxy/serial_proxy.h | 2 +- esphome/components/uart/uart.h | 2 +- esphome/components/uart/uart_component.h | 19 +++++++------------ .../uart/uart_component_esp8266.cpp | 4 ++-- .../components/uart/uart_component_esp8266.h | 2 +- .../uart/uart_component_esp_idf.cpp | 8 ++++---- .../components/uart/uart_component_esp_idf.h | 2 +- .../components/uart/uart_component_host.cpp | 6 +++--- esphome/components/uart/uart_component_host.h | 2 +- .../uart/uart_component_libretiny.cpp | 4 ++-- .../uart/uart_component_libretiny.h | 2 +- .../components/uart/uart_component_rp2040.cpp | 4 ++-- .../components/uart/uart_component_rp2040.h | 2 +- esphome/components/usb_cdc_acm/usb_cdc_acm.h | 2 +- .../usb_cdc_acm/usb_cdc_acm_esp32.cpp | 10 +++++----- esphome/components/usb_uart/usb_uart.cpp | 6 +++--- esphome/components/usb_uart/usb_uart.h | 2 +- esphome/components/weikai/weikai.cpp | 6 +++--- esphome/components/weikai/weikai.h | 2 +- tests/components/ld2450/common.h | 2 +- tests/components/uart/common.h | 2 +- .../uart_mock/uart_mock.cpp | 4 ++-- .../external_components/uart_mock/uart_mock.h | 2 +- 27 files changed, 55 insertions(+), 60 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 40c27b224b..82d7e3f674 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1519,16 +1519,16 @@ void APIConnection::on_serial_proxy_request(const SerialProxyRequest &msg) { resp.instance = msg.instance; resp.type = enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH; switch (proxies[msg.instance]->flush_port()) { - case uart::FlushResult::SUCCESS: + case uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS: resp.status = enums::SERIAL_PROXY_STATUS_OK; break; - case uart::FlushResult::ASSUMED_SUCCESS: + case uart::UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS: resp.status = enums::SERIAL_PROXY_STATUS_ASSUMED_SUCCESS; break; - case uart::FlushResult::TIMEOUT: + case uart::UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT: resp.status = enums::SERIAL_PROXY_STATUS_TIMEOUT; break; - case uart::FlushResult::FAILED: + case uart::UARTFlushResult::UART_FLUSH_RESULT_FAILED: resp.status = enums::SERIAL_PROXY_STATUS_ERROR; break; } diff --git a/esphome/components/ble_nus/ble_nus.cpp b/esphome/components/ble_nus/ble_nus.cpp index 2f60f81471..71d98332e0 100644 --- a/esphome/components/ble_nus/ble_nus.cpp +++ b/esphome/components/ble_nus/ble_nus.cpp @@ -103,17 +103,17 @@ size_t BLENUS::available() { #endif } -uart::FlushResult BLENUS::flush() { +uart::UARTFlushResult BLENUS::flush() { constexpr uint32_t timeout_500ms = 500; uint32_t start = millis(); while (atomic_get(&this->tx_status_) != TX_DISABLED && !ring_buf_is_empty(&global_ble_tx_ring_buf)) { if (millis() - start > timeout_500ms) { ESP_LOGW(TAG, "Flush timeout"); - return uart::FlushResult::TIMEOUT; + return uart::UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT; } delay(1); } - return uart::FlushResult::SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; } void BLENUS::connected(bt_conn *conn, uint8_t err) { diff --git a/esphome/components/ble_nus/ble_nus.h b/esphome/components/ble_nus/ble_nus.h index b482c240e5..f1afd54af9 100644 --- a/esphome/components/ble_nus/ble_nus.h +++ b/esphome/components/ble_nus/ble_nus.h @@ -26,7 +26,7 @@ class BLENUS : public uart::UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - uart::FlushResult flush() override; + uart::UARTFlushResult flush() override; void check_logger_conflict() override {} void set_expose_log(bool expose_log) { this->expose_log_ = expose_log; } #ifdef USE_LOGGER diff --git a/esphome/components/serial_proxy/serial_proxy.cpp b/esphome/components/serial_proxy/serial_proxy.cpp index 00d822b75c..f3c256c62a 100644 --- a/esphome/components/serial_proxy/serial_proxy.cpp +++ b/esphome/components/serial_proxy/serial_proxy.cpp @@ -165,7 +165,7 @@ uint32_t SerialProxy::get_modem_pins() const { (this->dtr_state_ ? SERIAL_PROXY_LINE_STATE_FLAG_DTR : 0u); } -uart::FlushResult SerialProxy::flush_port() { +uart::UARTFlushResult SerialProxy::flush_port() { ESP_LOGV(TAG, "Flushing serial proxy [%u]", this->instance_index_); return this->flush(); } diff --git a/esphome/components/serial_proxy/serial_proxy.h b/esphome/components/serial_proxy/serial_proxy.h index 5adfa4fe53..c435787a61 100644 --- a/esphome/components/serial_proxy/serial_proxy.h +++ b/esphome/components/serial_proxy/serial_proxy.h @@ -92,7 +92,7 @@ class SerialProxy : public uart::UARTDevice, public Component { uint32_t get_modem_pins() const; /// Flush the serial port (block until all TX data is sent) - uart::FlushResult flush_port(); + uart::UARTFlushResult flush_port(); /// Set the RTS GPIO pin (from YAML configuration) void set_rts_pin(GPIOPin *pin) { this->rts_pin_ = pin; } diff --git a/esphome/components/uart/uart.h b/esphome/components/uart/uart.h index 2c4fb34c9a..899d349e21 100644 --- a/esphome/components/uart/uart.h +++ b/esphome/components/uart/uart.h @@ -45,7 +45,7 @@ class UARTDevice { size_t available() { return this->parent_->available(); } - FlushResult flush() { return this->parent_->flush(); } + UARTFlushResult flush() { return this->parent_->flush(); } // Compat APIs int read() { diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 00a4c78878..abc77fbae8 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -30,17 +30,12 @@ enum UARTDirection { const LogString *parity_to_str(UARTParityOptions parity); /// Result of a flush() call. -// Some vendor SDKs (e.g., Realtek) define SUCCESS as a macro. -// Save and restore around the enum to avoid collisions with our scoped enum value. -#pragma push_macro("SUCCESS") -#undef SUCCESS -enum class FlushResult { - SUCCESS, ///< Confirmed: all bytes left the TX FIFO. - TIMEOUT, ///< Confirmed: timed out before TX completed. - FAILED, ///< Confirmed: driver or hardware error. - ASSUMED_SUCCESS, ///< Platform cannot report result; success is assumed. +enum class UARTFlushResult { + UART_FLUSH_RESULT_SUCCESS, ///< Confirmed: all bytes left the TX FIFO. + UART_FLUSH_RESULT_TIMEOUT, ///< Confirmed: timed out before TX completed. + UART_FLUSH_RESULT_FAILED, ///< Confirmed: driver or hardware error. + UART_FLUSH_RESULT_ASSUMED_SUCCESS, ///< Platform cannot report result; success is assumed. }; -#pragma pop_macro("SUCCESS") class UARTComponent { public: @@ -87,8 +82,8 @@ class UARTComponent { virtual size_t available() = 0; // Pure virtual method to block until all bytes have been written to the UART bus. - // @return FlushResult indicating whether the flush was confirmed, timed out, failed, or assumed successful. - virtual FlushResult flush() = 0; + // @return UARTFlushResult indicating whether the flush was confirmed, timed out, failed, or assumed successful. + virtual UARTFlushResult flush() = 0; // Sets the maximum time to wait for TX to drain during flush(). // Only meaningful on ESP32 (IDF). Other platforms ignore this value. diff --git a/esphome/components/uart/uart_component_esp8266.cpp b/esphome/components/uart/uart_component_esp8266.cpp index 91218c4300..0ea7930760 100644 --- a/esphome/components/uart/uart_component_esp8266.cpp +++ b/esphome/components/uart/uart_component_esp8266.cpp @@ -213,14 +213,14 @@ size_t ESP8266UartComponent::available() { return this->sw_serial_->available(); } } -FlushResult ESP8266UartComponent::flush() { +UARTFlushResult ESP8266UartComponent::flush() { ESP_LOGVV(TAG, " Flushing"); if (this->hw_serial_ != nullptr) { this->hw_serial_->flush(); } else { this->sw_serial_->flush(); } - return FlushResult::ASSUMED_SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } void ESP8266SoftwareSerial::setup(InternalGPIOPin *tx_pin, InternalGPIOPin *rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t data_bits, UARTParityOptions parity, diff --git a/esphome/components/uart/uart_component_esp8266.h b/esphome/components/uart/uart_component_esp8266.h index ca90dc5964..7f844d9b65 100644 --- a/esphome/components/uart/uart_component_esp8266.h +++ b/esphome/components/uart/uart_component_esp8266.h @@ -58,7 +58,7 @@ class ESP8266UartComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - FlushResult flush() override; + UARTFlushResult flush() override; uint32_t get_config(); diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 8168e49805..bd2f915d3a 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -360,15 +360,15 @@ size_t IDFUARTComponent::available() { return available; } -FlushResult IDFUARTComponent::flush() { +UARTFlushResult IDFUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); TickType_t ticks = this->flush_timeout_ms_ == 0 ? portMAX_DELAY : pdMS_TO_TICKS(this->flush_timeout_ms_); esp_err_t err = uart_wait_tx_done(this->uart_num_, ticks); if (err == ESP_OK) - return FlushResult::SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; if (err == ESP_ERR_TIMEOUT) - return FlushResult::TIMEOUT; - return FlushResult::FAILED; + return UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT; + return UARTFlushResult::UART_FLUSH_RESULT_FAILED; } void IDFUARTComponent::check_logger_conflict() {} diff --git a/esphome/components/uart/uart_component_esp_idf.h b/esphome/components/uart/uart_component_esp_idf.h index 9fa2013cfd..ec4f2884b2 100644 --- a/esphome/components/uart/uart_component_esp_idf.h +++ b/esphome/components/uart/uart_component_esp_idf.h @@ -31,7 +31,7 @@ class IDFUARTComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - FlushResult flush() override; + UARTFlushResult flush() override; void set_flush_timeout(uint32_t flush_timeout_ms) override { this->flush_timeout_ms_ = flush_timeout_ms; } diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 66026f3ccd..0042ffae23 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -274,13 +274,13 @@ size_t HostUartComponent::available() { return result; }; -FlushResult HostUartComponent::flush() { +UARTFlushResult HostUartComponent::flush() { if (this->file_descriptor_ == -1) { - return FlushResult::ASSUMED_SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } tcflush(this->file_descriptor_, TCIOFLUSH); ESP_LOGV(TAG, " Flushing"); - return FlushResult::ASSUMED_SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } void HostUartComponent::update_error_(const std::string &error) { diff --git a/esphome/components/uart/uart_component_host.h b/esphome/components/uart/uart_component_host.h index c22efdcb92..56ff525bc3 100644 --- a/esphome/components/uart/uart_component_host.h +++ b/esphome/components/uart/uart_component_host.h @@ -18,7 +18,7 @@ class HostUartComponent : public UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - FlushResult flush() override; + UARTFlushResult flush() override; void set_name(std::string port_name) { port_name_ = port_name; }; protected: diff --git a/esphome/components/uart/uart_component_libretiny.cpp b/esphome/components/uart/uart_component_libretiny.cpp index 6a550f296a..4172e7c164 100644 --- a/esphome/components/uart/uart_component_libretiny.cpp +++ b/esphome/components/uart/uart_component_libretiny.cpp @@ -170,10 +170,10 @@ bool LibreTinyUARTComponent::read_array(uint8_t *data, size_t len) { } size_t LibreTinyUARTComponent::available() { return this->serial_->available(); } -FlushResult LibreTinyUARTComponent::flush() { +UARTFlushResult LibreTinyUARTComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); - return FlushResult::ASSUMED_SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } void LibreTinyUARTComponent::check_logger_conflict() { diff --git a/esphome/components/uart/uart_component_libretiny.h b/esphome/components/uart/uart_component_libretiny.h index 77df808067..872ea86601 100644 --- a/esphome/components/uart/uart_component_libretiny.h +++ b/esphome/components/uart/uart_component_libretiny.h @@ -22,7 +22,7 @@ class LibreTinyUARTComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - FlushResult flush() override; + UARTFlushResult flush() override; uint16_t get_config(); diff --git a/esphome/components/uart/uart_component_rp2040.cpp b/esphome/components/uart/uart_component_rp2040.cpp index 6f6f1fb96b..1aaf98dc84 100644 --- a/esphome/components/uart/uart_component_rp2040.cpp +++ b/esphome/components/uart/uart_component_rp2040.cpp @@ -208,10 +208,10 @@ bool RP2040UartComponent::read_array(uint8_t *data, size_t len) { return true; } size_t RP2040UartComponent::available() { return this->serial_->available(); } -FlushResult RP2040UartComponent::flush() { +UARTFlushResult RP2040UartComponent::flush() { ESP_LOGVV(TAG, " Flushing"); this->serial_->flush(); - return FlushResult::ASSUMED_SUCCESS; + return UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } } // namespace esphome::uart diff --git a/esphome/components/uart/uart_component_rp2040.h b/esphome/components/uart/uart_component_rp2040.h index 891212ca74..198c698af9 100644 --- a/esphome/components/uart/uart_component_rp2040.h +++ b/esphome/components/uart/uart_component_rp2040.h @@ -25,7 +25,7 @@ class RP2040UartComponent : public UARTComponent, public Component { bool read_array(uint8_t *data, size_t len) override; size_t available() override; - FlushResult flush() override; + UARTFlushResult flush() override; uint16_t get_config(); diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.h b/esphome/components/usb_cdc_acm/usb_cdc_acm.h index a56abc9ee8..89405ab893 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.h +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.h @@ -82,7 +82,7 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - uart::FlushResult flush() override; + uart::UARTFlushResult flush() override; protected: void check_logger_conflict() override; diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp index 583aa77d06..5498c38515 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm_esp32.cpp @@ -325,10 +325,10 @@ size_t USBCDCACMInstance::available() { return waiting + (this->has_peek_ ? 1 : 0); } -uart::FlushResult USBCDCACMInstance::flush() { +uart::UARTFlushResult USBCDCACMInstance::flush() { // Wait for TX ring buffer to be empty if (this->usb_tx_ringbuf_ == nullptr) { - return uart::FlushResult::ASSUMED_SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } UBaseType_t waiting = 1; @@ -342,10 +342,10 @@ uart::FlushResult USBCDCACMInstance::flush() { // Also wait for USB to finish transmitting esp_err_t err = tinyusb_cdcacm_write_flush(static_cast<tinyusb_cdcacm_itf_t>(this->itf_), pdMS_TO_TICKS(100)); if (err == ESP_OK) - return uart::FlushResult::SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; if (err == ESP_ERR_TIMEOUT) - return uart::FlushResult::TIMEOUT; - return uart::FlushResult::FAILED; + return uart::UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT; + return uart::UARTFlushResult::UART_FLUSH_RESULT_FAILED; } void USBCDCACMInstance::check_logger_conflict() {} diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index a5d312f191..0b8589f671 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -169,7 +169,7 @@ void USBUartChannel::write_array(const uint8_t *data, size_t len) { this->parent_->start_output(this); } -uart::FlushResult USBUartChannel::flush() { +uart::UARTFlushResult USBUartChannel::flush() { // Spin until the output queue is drained and the last USB transfer completes. // Safe to call from the main loop only. // The flush_timeout_ms_ timeout guards against a device that stops responding mid-flush; @@ -181,8 +181,8 @@ uart::FlushResult USBUartChannel::flush() { yield(); } if (!this->output_queue_.empty() || this->output_started_.load()) - return uart::FlushResult::TIMEOUT; - return uart::FlushResult::SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT; + return uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; } bool USBUartChannel::peek_byte(uint8_t *data) { diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 7a06b04f11..8a47f0cf4b 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -140,7 +140,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override { return this->input_buffer_.get_available(); } - uart::FlushResult flush() override; + uart::UARTFlushResult flush() override; void check_logger_conflict() override {} void set_parity(UARTParityOptions parity) { this->parity_ = parity; } void set_debug(bool debug) { this->debug_ = debug; } diff --git a/esphome/components/weikai/weikai.cpp b/esphome/components/weikai/weikai.cpp index f01d164e9f..2ec5632691 100644 --- a/esphome/components/weikai/weikai.cpp +++ b/esphome/components/weikai/weikai.cpp @@ -433,16 +433,16 @@ void WeikaiChannel::write_array(const uint8_t *buffer, size_t length) { this->reg(0).write_fifo(const_cast<uint8_t *>(buffer), length); } -uart::FlushResult WeikaiChannel::flush() { +uart::UARTFlushResult WeikaiChannel::flush() { uint32_t const start_time = millis(); while (this->tx_fifo_is_not_empty_()) { // wait until buffer empty if (millis() - start_time > 200) { ESP_LOGW(TAG, "WARNING flush timeout - still %d bytes not sent after 200 ms", this->tx_in_fifo_()); - return uart::FlushResult::TIMEOUT; + return uart::UARTFlushResult::UART_FLUSH_RESULT_TIMEOUT; } yield(); // reschedule our thread to avoid blocking } - return uart::FlushResult::SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; } size_t WeikaiChannel::xfer_fifo_to_buffer_() { diff --git a/esphome/components/weikai/weikai.h b/esphome/components/weikai/weikai.h index 715b82bfc7..36d8f66265 100644 --- a/esphome/components/weikai/weikai.h +++ b/esphome/components/weikai/weikai.h @@ -380,7 +380,7 @@ class WeikaiChannel : public uart::UARTComponent { /// @details If we refer to Serial.flush() in Arduino it says: ** Waits for the transmission of outgoing serial data /// to complete. (Prior to Arduino 1.0, this the method was removing any buffered incoming serial data.). ** Therefore /// we wait until all bytes are gone with a timeout of 100 ms - uart::FlushResult flush() override; + uart::UARTFlushResult flush() override; protected: friend class WeikaiComponent; diff --git a/tests/components/ld2450/common.h b/tests/components/ld2450/common.h index 9f9e7b3e9f..304634edca 100644 --- a/tests/components/ld2450/common.h +++ b/tests/components/ld2450/common.h @@ -16,7 +16,7 @@ class MockUARTComponent : public uart::UARTComponent { MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); MOCK_METHOD(size_t, available, (), (override)); - MOCK_METHOD(uart::FlushResult, flush, (), (override)); + MOCK_METHOD(uart::UARTFlushResult, flush, (), (override)); MOCK_METHOD(void, check_logger_conflict, (), (override)); }; diff --git a/tests/components/uart/common.h b/tests/components/uart/common.h index f7e2d8a3f7..de3ea3029e 100644 --- a/tests/components/uart/common.h +++ b/tests/components/uart/common.h @@ -30,7 +30,7 @@ class MockUARTComponent : public UARTComponent { MOCK_METHOD(bool, read_array, (uint8_t * data, size_t len), (override)); MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); MOCK_METHOD(size_t, available, (), (override)); - MOCK_METHOD(FlushResult, flush, (), (override)); + MOCK_METHOD(UARTFlushResult, flush, (), (override)); MOCK_METHOD(void, check_logger_conflict, (), (override)); }; diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp index 1a15da76d1..d0690e7515 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.cpp @@ -153,9 +153,9 @@ bool MockUartComponent::read_array(uint8_t *data, size_t len) { size_t MockUartComponent::available() { return this->rx_buffer_.size(); } -uart::FlushResult MockUartComponent::flush() { +uart::UARTFlushResult MockUartComponent::flush() { // Nothing to flush in mock - return uart::FlushResult::ASSUMED_SUCCESS; + return uart::UARTFlushResult::UART_FLUSH_RESULT_ASSUMED_SUCCESS; } void MockUartComponent::set_rx_full_threshold(size_t rx_full_threshold) { diff --git a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h index 82e3b3d563..0b3b49893d 100644 --- a/tests/integration/fixtures/external_components/uart_mock/uart_mock.h +++ b/tests/integration/fixtures/external_components/uart_mock/uart_mock.h @@ -28,7 +28,7 @@ class MockUartComponent : public uart::UARTComponent, public Component { bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override; - uart::FlushResult flush() override; + uart::UARTFlushResult flush() override; void set_rx_full_threshold(size_t rx_full_threshold) override; void set_rx_timeout(size_t rx_timeout) override; From f4097d5a95a37faa963ec2d8ad1588b70b259e3c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 20:57:40 -1000 Subject: [PATCH 1656/2030] [api] Devirtualize API command dispatch (#15044) --- esphome/components/api/api_connection.cpp | 2 +- esphome/components/api/api_connection.h | 156 ++++++++++++--------- esphome/components/api/api_pb2_service.cpp | 3 +- esphome/components/api/api_pb2_service.h | 134 +++++++++--------- esphome/components/api/proto.h | 23 +-- script/api_protobuf/api_protobuf.py | 13 +- 6 files changed, 164 insertions(+), 167 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 82d7e3f674..d023cd21a8 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -234,7 +234,7 @@ void APIConnection::loop() { this->last_traffic_ = now; } // read a packet - this->read_message(buffer.data_len, buffer.type, buffer.data); + this->read_message_(buffer.data_len, buffer.type, buffer.data); if (this->flags_.remove) return; } diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 85c8e777a9..3d8563b1ae 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -49,11 +49,29 @@ class APIConnection final : public APIServerConnectionBase { friend class APIServer; friend class ListEntitiesIterator; APIConnection(std::unique_ptr<socket::Socket> socket, APIServer *parent); - virtual ~APIConnection(); + ~APIConnection(); void start(); void loop(); + protected: + // read_message_ is defined here (instead of in APIServerConnectionBase) so the + // compiler can devirtualize and inline on_* handler calls within this final class. + void read_message_(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data); + + // Auth helpers defined here (not in ProtoService) so the compiler can + // devirtualize is_connection_setup()/on_no_setup_connection() calls + // within this final class. + inline bool check_connection_setup_() { + if (!this->is_connection_setup()) { + this->on_no_setup_connection(); + return false; + } + return true; + } + inline bool check_authenticated_() { return this->check_connection_setup_(); } + + public: bool send_list_info_done() { return this->schedule_message_(nullptr, ListEntitiesDoneResponse::MESSAGE_TYPE, ListEntitiesDoneResponse::ESTIMATED_SIZE); @@ -63,72 +81,72 @@ class APIConnection final : public APIServerConnectionBase { #endif #ifdef USE_COVER bool send_cover_state(cover::Cover *cover); - void on_cover_command_request(const CoverCommandRequest &msg) override; + void on_cover_command_request(const CoverCommandRequest &msg); #endif #ifdef USE_FAN bool send_fan_state(fan::Fan *fan); - void on_fan_command_request(const FanCommandRequest &msg) override; + void on_fan_command_request(const FanCommandRequest &msg); #endif #ifdef USE_LIGHT bool send_light_state(light::LightState *light); - void on_light_command_request(const LightCommandRequest &msg) override; + void on_light_command_request(const LightCommandRequest &msg); #endif #ifdef USE_SENSOR bool send_sensor_state(sensor::Sensor *sensor); #endif #ifdef USE_SWITCH bool send_switch_state(switch_::Switch *a_switch); - void on_switch_command_request(const SwitchCommandRequest &msg) override; + void on_switch_command_request(const SwitchCommandRequest &msg); #endif #ifdef USE_TEXT_SENSOR bool send_text_sensor_state(text_sensor::TextSensor *text_sensor); #endif #ifdef USE_CAMERA void set_camera_state(std::shared_ptr<camera::CameraImage> image); - void on_camera_image_request(const CameraImageRequest &msg) override; + void on_camera_image_request(const CameraImageRequest &msg); #endif #ifdef USE_CLIMATE bool send_climate_state(climate::Climate *climate); - void on_climate_command_request(const ClimateCommandRequest &msg) override; + void on_climate_command_request(const ClimateCommandRequest &msg); #endif #ifdef USE_NUMBER bool send_number_state(number::Number *number); - void on_number_command_request(const NumberCommandRequest &msg) override; + void on_number_command_request(const NumberCommandRequest &msg); #endif #ifdef USE_DATETIME_DATE bool send_date_state(datetime::DateEntity *date); - void on_date_command_request(const DateCommandRequest &msg) override; + void on_date_command_request(const DateCommandRequest &msg); #endif #ifdef USE_DATETIME_TIME bool send_time_state(datetime::TimeEntity *time); - void on_time_command_request(const TimeCommandRequest &msg) override; + void on_time_command_request(const TimeCommandRequest &msg); #endif #ifdef USE_DATETIME_DATETIME bool send_datetime_state(datetime::DateTimeEntity *datetime); - void on_date_time_command_request(const DateTimeCommandRequest &msg) override; + void on_date_time_command_request(const DateTimeCommandRequest &msg); #endif #ifdef USE_TEXT bool send_text_state(text::Text *text); - void on_text_command_request(const TextCommandRequest &msg) override; + void on_text_command_request(const TextCommandRequest &msg); #endif #ifdef USE_SELECT bool send_select_state(select::Select *select); - void on_select_command_request(const SelectCommandRequest &msg) override; + void on_select_command_request(const SelectCommandRequest &msg); #endif #ifdef USE_BUTTON - void on_button_command_request(const ButtonCommandRequest &msg) override; + void on_button_command_request(const ButtonCommandRequest &msg); #endif #ifdef USE_LOCK bool send_lock_state(lock::Lock *a_lock); - void on_lock_command_request(const LockCommandRequest &msg) override; + void on_lock_command_request(const LockCommandRequest &msg); #endif #ifdef USE_VALVE bool send_valve_state(valve::Valve *valve); - void on_valve_command_request(const ValveCommandRequest &msg) override; + void on_valve_command_request(const ValveCommandRequest &msg); #endif #ifdef USE_MEDIA_PLAYER bool send_media_player_state(media_player::MediaPlayer *media_player); - void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override; + void on_media_player_command_request(const MediaPlayerCommandRequest &msg); #endif bool try_send_log_message(int level, const char *tag, const char *line, size_t message_len); #ifdef USE_API_HOMEASSISTANT_SERVICES @@ -138,23 +156,23 @@ class APIConnection final : public APIServerConnectionBase { this->send_message(call); } #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - void on_homeassistant_action_response(const HomeassistantActionResponse &msg) override; + void on_homeassistant_action_response(const HomeassistantActionResponse &msg); #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES #endif // USE_API_HOMEASSISTANT_SERVICES #ifdef USE_BLUETOOTH_PROXY - void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override; - void on_unsubscribe_bluetooth_le_advertisements_request() override; + void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg); + void on_unsubscribe_bluetooth_le_advertisements_request(); - void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override; - void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) override; - void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) override; - void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) override; - void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) override; - void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) override; - void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override; - void on_subscribe_bluetooth_connections_free_request() override; - void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override; - void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg) override; + void on_bluetooth_device_request(const BluetoothDeviceRequest &msg); + void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg); + void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg); + void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg); + void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg); + void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg); + void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg); + void on_subscribe_bluetooth_connections_free_request(); + void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg); + void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg); #endif #ifdef USE_HOMEASSISTANT_TIME @@ -165,42 +183,42 @@ class APIConnection final : public APIServerConnectionBase { #endif #ifdef USE_VOICE_ASSISTANT - void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg) override; - void on_voice_assistant_response(const VoiceAssistantResponse &msg) override; - void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg) override; - void on_voice_assistant_audio(const VoiceAssistantAudio &msg) override; - void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg) override; - void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg) override; - void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg) override; - void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg) override; + void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &msg); + void on_voice_assistant_response(const VoiceAssistantResponse &msg); + void on_voice_assistant_event_response(const VoiceAssistantEventResponse &msg); + void on_voice_assistant_audio(const VoiceAssistantAudio &msg); + void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &msg); + void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &msg); + void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &msg); + void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &msg); #endif #ifdef USE_ZWAVE_PROXY - void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg) override; - void on_z_wave_proxy_request(const ZWaveProxyRequest &msg) override; + void on_z_wave_proxy_frame(const ZWaveProxyFrame &msg); + void on_z_wave_proxy_request(const ZWaveProxyRequest &msg); #endif #ifdef USE_ALARM_CONTROL_PANEL bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel); - void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg) override; + void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &msg); #endif #ifdef USE_WATER_HEATER bool send_water_heater_state(water_heater::WaterHeater *water_heater); - void on_water_heater_command_request(const WaterHeaterCommandRequest &msg) override; + void on_water_heater_command_request(const WaterHeaterCommandRequest &msg); #endif #ifdef USE_IR_RF - void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg) override; + void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &msg); void send_infrared_rf_receive_event(const InfraredRFReceiveEvent &msg); #endif #ifdef USE_SERIAL_PROXY - void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) override; - void on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) override; - void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) override; - void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) override; - void on_serial_proxy_request(const SerialProxyRequest &msg) override; + void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg); + void on_serial_proxy_write_request(const SerialProxyWriteRequest &msg); + void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg); + void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg); + void on_serial_proxy_request(const SerialProxyRequest &msg); void send_serial_proxy_data(const SerialProxyDataReceived &msg); #endif @@ -210,26 +228,26 @@ class APIConnection final : public APIServerConnectionBase { #ifdef USE_UPDATE bool send_update_state(update::UpdateEntity *update); - void on_update_command_request(const UpdateCommandRequest &msg) override; + void on_update_command_request(const UpdateCommandRequest &msg); #endif - void on_disconnect_response() override; - void on_ping_response() override { + void on_disconnect_response(); + void on_ping_response() { // we initiated ping this->flags_.sent_ping = false; } #ifdef USE_API_HOMEASSISTANT_STATES - void on_home_assistant_state_response(const HomeAssistantStateResponse &msg) override; + void on_home_assistant_state_response(const HomeAssistantStateResponse &msg); #endif #ifdef USE_HOMEASSISTANT_TIME - void on_get_time_response(const GetTimeResponse &value) override; + void on_get_time_response(const GetTimeResponse &value); #endif - void on_hello_request(const HelloRequest &msg) override; - void on_disconnect_request() override; - void on_ping_request() override; - void on_device_info_request() override; - void on_list_entities_request() override { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } - void on_subscribe_states_request() override { + void on_hello_request(const HelloRequest &msg); + void on_disconnect_request(); + void on_ping_request(); + void on_device_info_request(); + void on_list_entities_request() { this->begin_iterator_(ActiveIterator::LIST_ENTITIES); } + void on_subscribe_states_request() { this->flags_.state_subscription = true; // Start initial state iterator only if no iterator is active // If list_entities is running, we'll start initial_state when it completes @@ -237,7 +255,7 @@ class APIConnection final : public APIServerConnectionBase { this->begin_iterator_(ActiveIterator::INITIAL_STATE); } } - void on_subscribe_logs_request(const SubscribeLogsRequest &msg) override { + void on_subscribe_logs_request(const SubscribeLogsRequest &msg) { this->flags_.log_subscription = msg.level; if (msg.dump_config) App.schedule_dump_config(); @@ -249,13 +267,13 @@ class APIConnection final : public APIServerConnectionBase { #endif } #ifdef USE_API_HOMEASSISTANT_SERVICES - void on_subscribe_homeassistant_services_request() override { this->flags_.service_call_subscription = true; } + void on_subscribe_homeassistant_services_request() { this->flags_.service_call_subscription = true; } #endif #ifdef USE_API_HOMEASSISTANT_STATES - void on_subscribe_home_assistant_states_request() override; + void on_subscribe_home_assistant_states_request(); #endif #ifdef USE_API_USER_DEFINED_ACTIONS - void on_execute_service_request(const ExecuteServiceRequest &msg) override; + void on_execute_service_request(const ExecuteServiceRequest &msg); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES void send_execute_service_response(uint32_t call_id, bool success, StringRef error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON @@ -265,13 +283,13 @@ class APIConnection final : public APIServerConnectionBase { #endif // USE_API_USER_DEFINED_ACTION_RESPONSES #endif #ifdef USE_API_NOISE - void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg) override; + void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &msg); #endif - bool is_authenticated() override { + bool is_authenticated() { return static_cast<ConnectionState>(this->flags_.connection_state) == ConnectionState::AUTHENTICATED; } - bool is_connection_setup() override { + bool is_connection_setup() { return static_cast<ConnectionState>(this->flags_.connection_state) == ConnectionState::CONNECTED || this->is_authenticated(); } @@ -284,8 +302,8 @@ class APIConnection final : public APIServerConnectionBase { (this->client_api_version_major_ == major && this->client_api_version_minor_ >= minor); } - void on_fatal_error() override; - void on_no_setup_connection() override; + void on_fatal_error(); + void on_no_setup_connection(); // Function pointer type for type-erased message encoding using MessageEncodeFn = void (*)(const void *, ProtoWriteBuffer &); @@ -324,7 +342,7 @@ class APIConnection final : public APIServerConnectionBase { return true; return this->try_to_clear_buffer_slow_(log_out_of_space); } - bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) override; + bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type); const char *get_name() const { return this->helper_->get_client_name(); } /// Get peer name (IP address) into caller-provided buffer, returns buf for convenience diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index f2f7fa5238..d86cf912db 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -1,6 +1,7 @@ // This file was automatically generated with a tool. // See script/api_protobuf/api_protobuf.py #include "api_pb2_service.h" +#include "api_connection.h" #include "esphome/core/log.h" namespace esphome::api { @@ -20,7 +21,7 @@ void APIServerConnectionBase::log_receive_message_(const LogString *name) { } #endif -void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { +void APIConnection::read_message_(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) { // Check authentication/connection requirements switch (msg_type) { case HelloRequest::MESSAGE_TYPE: // No setup required diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 10fd88d8e1..4925a6497a 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -8,7 +8,7 @@ namespace esphome::api { -class APIServerConnectionBase : public ProtoService { +class APIServerConnectionBase { public: #ifdef HAS_PROTO_MESSAGE_DUMP protected: @@ -19,227 +19,223 @@ class APIServerConnectionBase : public ProtoService { public: #endif - virtual void on_hello_request(const HelloRequest &value){}; + void on_hello_request(const HelloRequest &value){}; - virtual void on_disconnect_request(){}; - virtual void on_disconnect_response(){}; - virtual void on_ping_request(){}; - virtual void on_ping_response(){}; - virtual void on_device_info_request(){}; + void on_disconnect_request(){}; + void on_disconnect_response(){}; + void on_ping_request(){}; + void on_ping_response(){}; + void on_device_info_request(){}; - virtual void on_list_entities_request(){}; + void on_list_entities_request(){}; - virtual void on_subscribe_states_request(){}; + void on_subscribe_states_request(){}; #ifdef USE_COVER - virtual void on_cover_command_request(const CoverCommandRequest &value){}; + void on_cover_command_request(const CoverCommandRequest &value){}; #endif #ifdef USE_FAN - virtual void on_fan_command_request(const FanCommandRequest &value){}; + void on_fan_command_request(const FanCommandRequest &value){}; #endif #ifdef USE_LIGHT - virtual void on_light_command_request(const LightCommandRequest &value){}; + void on_light_command_request(const LightCommandRequest &value){}; #endif #ifdef USE_SWITCH - virtual void on_switch_command_request(const SwitchCommandRequest &value){}; + void on_switch_command_request(const SwitchCommandRequest &value){}; #endif - virtual void on_subscribe_logs_request(const SubscribeLogsRequest &value){}; + void on_subscribe_logs_request(const SubscribeLogsRequest &value){}; #ifdef USE_API_NOISE - virtual void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &value){}; + void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &value){}; #endif #ifdef USE_API_HOMEASSISTANT_SERVICES - virtual void on_subscribe_homeassistant_services_request(){}; + void on_subscribe_homeassistant_services_request(){}; #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - virtual void on_homeassistant_action_response(const HomeassistantActionResponse &value){}; + void on_homeassistant_action_response(const HomeassistantActionResponse &value){}; #endif #ifdef USE_API_HOMEASSISTANT_STATES - virtual void on_subscribe_home_assistant_states_request(){}; + void on_subscribe_home_assistant_states_request(){}; #endif #ifdef USE_API_HOMEASSISTANT_STATES - virtual void on_home_assistant_state_response(const HomeAssistantStateResponse &value){}; + void on_home_assistant_state_response(const HomeAssistantStateResponse &value){}; #endif - virtual void on_get_time_response(const GetTimeResponse &value){}; + void on_get_time_response(const GetTimeResponse &value){}; #ifdef USE_API_USER_DEFINED_ACTIONS - virtual void on_execute_service_request(const ExecuteServiceRequest &value){}; + void on_execute_service_request(const ExecuteServiceRequest &value){}; #endif #ifdef USE_CAMERA - virtual void on_camera_image_request(const CameraImageRequest &value){}; + void on_camera_image_request(const CameraImageRequest &value){}; #endif #ifdef USE_CLIMATE - virtual void on_climate_command_request(const ClimateCommandRequest &value){}; + void on_climate_command_request(const ClimateCommandRequest &value){}; #endif #ifdef USE_WATER_HEATER - virtual void on_water_heater_command_request(const WaterHeaterCommandRequest &value){}; + void on_water_heater_command_request(const WaterHeaterCommandRequest &value){}; #endif #ifdef USE_NUMBER - virtual void on_number_command_request(const NumberCommandRequest &value){}; + void on_number_command_request(const NumberCommandRequest &value){}; #endif #ifdef USE_SELECT - virtual void on_select_command_request(const SelectCommandRequest &value){}; + void on_select_command_request(const SelectCommandRequest &value){}; #endif #ifdef USE_SIREN - virtual void on_siren_command_request(const SirenCommandRequest &value){}; + void on_siren_command_request(const SirenCommandRequest &value){}; #endif #ifdef USE_LOCK - virtual void on_lock_command_request(const LockCommandRequest &value){}; + void on_lock_command_request(const LockCommandRequest &value){}; #endif #ifdef USE_BUTTON - virtual void on_button_command_request(const ButtonCommandRequest &value){}; + void on_button_command_request(const ButtonCommandRequest &value){}; #endif #ifdef USE_MEDIA_PLAYER - virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){}; + void on_media_player_command_request(const MediaPlayerCommandRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_subscribe_bluetooth_le_advertisements_request( - const SubscribeBluetoothLEAdvertisementsRequest &value){}; + void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_device_request(const BluetoothDeviceRequest &value){}; + void on_bluetooth_device_request(const BluetoothDeviceRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &value){}; + void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &value){}; + void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &value){}; + void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &value){}; + void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &value){}; + void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &value){}; + void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_subscribe_bluetooth_connections_free_request(){}; + void on_subscribe_bluetooth_connections_free_request(){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_unsubscribe_bluetooth_le_advertisements_request(){}; + void on_unsubscribe_bluetooth_le_advertisements_request(){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &value){}; + void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &value){}; + void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_response(const VoiceAssistantResponse &value){}; + void on_voice_assistant_response(const VoiceAssistantResponse &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_event_response(const VoiceAssistantEventResponse &value){}; + void on_voice_assistant_event_response(const VoiceAssistantEventResponse &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_audio(const VoiceAssistantAudio &value){}; + void on_voice_assistant_audio(const VoiceAssistantAudio &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &value){}; + void on_voice_assistant_timer_event_response(const VoiceAssistantTimerEventResponse &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &value){}; + void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &value){}; + void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &value){}; #endif #ifdef USE_VOICE_ASSISTANT - virtual void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &value){}; + void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &value){}; #endif #ifdef USE_ALARM_CONTROL_PANEL - virtual void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &value){}; + void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &value){}; #endif #ifdef USE_TEXT - virtual void on_text_command_request(const TextCommandRequest &value){}; + void on_text_command_request(const TextCommandRequest &value){}; #endif #ifdef USE_DATETIME_DATE - virtual void on_date_command_request(const DateCommandRequest &value){}; + void on_date_command_request(const DateCommandRequest &value){}; #endif #ifdef USE_DATETIME_TIME - virtual void on_time_command_request(const TimeCommandRequest &value){}; + void on_time_command_request(const TimeCommandRequest &value){}; #endif #ifdef USE_VALVE - virtual void on_valve_command_request(const ValveCommandRequest &value){}; + void on_valve_command_request(const ValveCommandRequest &value){}; #endif #ifdef USE_DATETIME_DATETIME - virtual void on_date_time_command_request(const DateTimeCommandRequest &value){}; + void on_date_time_command_request(const DateTimeCommandRequest &value){}; #endif #ifdef USE_UPDATE - virtual void on_update_command_request(const UpdateCommandRequest &value){}; + void on_update_command_request(const UpdateCommandRequest &value){}; #endif #ifdef USE_ZWAVE_PROXY - virtual void on_z_wave_proxy_frame(const ZWaveProxyFrame &value){}; + void on_z_wave_proxy_frame(const ZWaveProxyFrame &value){}; #endif #ifdef USE_ZWAVE_PROXY - virtual void on_z_wave_proxy_request(const ZWaveProxyRequest &value){}; + void on_z_wave_proxy_request(const ZWaveProxyRequest &value){}; #endif #ifdef USE_IR_RF - virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){}; + void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){}; #endif #ifdef USE_SERIAL_PROXY - virtual void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &value){}; + void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &value){}; #endif #ifdef USE_SERIAL_PROXY - virtual void on_serial_proxy_write_request(const SerialProxyWriteRequest &value){}; + void on_serial_proxy_write_request(const SerialProxyWriteRequest &value){}; #endif #ifdef USE_SERIAL_PROXY - virtual void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &value){}; + void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &value){}; #endif #ifdef USE_SERIAL_PROXY - virtual void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &value){}; + void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &value){}; #endif #ifdef USE_SERIAL_PROXY - virtual void on_serial_proxy_request(const SerialProxyRequest &value){}; + void on_serial_proxy_request(const SerialProxyRequest &value){}; #endif #ifdef USE_BLUETOOTH_PROXY - virtual void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){}; + void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){}; #endif - - protected: - void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override; }; } // namespace esphome::api diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index cd22915703..a1d825ead9 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -711,26 +711,7 @@ inline void ProtoLengthDelimited::decode_to_message(ProtoDecodableMessage &msg) template<typename T> const char *proto_enum_to_string(T value); -class ProtoService { - public: - protected: - virtual bool is_authenticated() = 0; - virtual bool is_connection_setup() = 0; - virtual void on_fatal_error() = 0; - virtual void on_no_setup_connection() = 0; - virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0; - virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0; - - // Authentication helper methods - inline bool check_connection_setup_() { - if (!this->is_connection_setup()) { - this->on_no_setup_connection(); - return false; - } - return true; - } - - inline bool check_authenticated_() { return this->check_connection_setup_(); } -}; +// ProtoService removed — its methods were inlined into APIConnection. +// APIConnection is the concrete server-side implementation; the extra virtual layer was unnecessary. } // namespace esphome::api diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index aca31e49c8..221ccc8d69 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2608,7 +2608,7 @@ def build_service_message_type( is_empty = not has_fields if is_empty: EMPTY_MESSAGES.add(mt.name) - hout += f"virtual void {func}({'' if is_empty else f'const {mt.name} &value'}){{}};\n" + hout += f"void {func}({'' if is_empty else f'const {mt.name} &value'}){{}};\n" case = "" if not is_empty: case += f"{mt.name} msg;\n" @@ -2960,6 +2960,7 @@ namespace esphome::api { cpp = FILE_HEADER cpp += """\ #include "api_pb2_service.h" +#include "api_connection.h" #include "esphome/core/log.h" namespace esphome::api { @@ -2970,7 +2971,7 @@ static const char *const TAG = "api.service"; class_name = "APIServerConnectionBase" - hpp += f"class {class_name} : public ProtoService {{\n" + hpp += f"class {class_name} {{\n" hpp += " public:\n" # Add logging helper method declarations @@ -3063,11 +3064,11 @@ static const char *const TAG = "api.service"; result += "#endif\n" return result - # Generate read_message with auth check before dispatch - hpp += " protected:\n" - hpp += " void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;\n" + # Generate read_message_ as APIConnection method (not base class) so the compiler + # can devirtualize and inline the on_* handler calls within the same class. + # APIConnection declares this method in api_connection.h. - out = f"void {class_name}::read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {{\n" + out = "void APIConnection::read_message_(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) {\n" # Auth check block before dispatch switch out += " // Check authentication/connection requirements\n" From 5560c9eef78e2a7be9fc5d728e767c34a23630c1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 22 Mar 2026 21:10:51 -1000 Subject: [PATCH 1657/2030] [test] Fix flakey ld2412 integration test race condition (#15100) --- tests/integration/test_uart_mock_ld2412.py | 33 +++++++++------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/tests/integration/test_uart_mock_ld2412.py b/tests/integration/test_uart_mock_ld2412.py index 9b928ef14f..12aa3f8397 100644 --- a/tests/integration/test_uart_mock_ld2412.py +++ b/tests/integration/test_uart_mock_ld2412.py @@ -79,9 +79,15 @@ async def test_uart_mock_ld2412( ], ) - # Signal when we see recovery frame values + # Signal when we see all recovery frame values recovery_received = collector.add_waiter( - lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + lambda: ( + pytest.approx(50.0) in collector.sensor_states["moving_distance"] + and pytest.approx(75.0) in collector.sensor_states["still_distance"] + and pytest.approx(100.0) in collector.sensor_states["moving_energy"] + and pytest.approx(80.0) in collector.sensor_states["still_energy"] + and pytest.approx(50.0) in collector.sensor_states["detection_distance"] + ) ) async with ( @@ -150,23 +156,12 @@ async def test_uart_mock_ld2412( ) # Recovery frame: moving=50, still=75, energy=100/80, detect=50 - recovery_idx = next( - i - for i, v in enumerate(collector.sensor_states["moving_distance"]) - if v == pytest.approx(50.0) - ) - assert collector.sensor_states["still_distance"][recovery_idx] == pytest.approx( - 75.0 - ) - assert collector.sensor_states["moving_energy"][recovery_idx] == pytest.approx( - 100.0 - ) - assert collector.sensor_states["still_energy"][recovery_idx] == pytest.approx( - 80.0 - ) - assert collector.sensor_states["detection_distance"][ - recovery_idx - ] == pytest.approx(50.0) + # Check values exist (waiter already ensured all are present) + assert pytest.approx(50.0) in collector.sensor_states["moving_distance"] + assert pytest.approx(75.0) in collector.sensor_states["still_distance"] + assert pytest.approx(100.0) in collector.sensor_states["moving_energy"] + assert pytest.approx(80.0) in collector.sensor_states["still_energy"] + assert pytest.approx(50.0) in collector.sensor_states["detection_distance"] # Verify binary sensors detected targets (from Phase 1 frame) assert collector.binary_states["has_target"][0] is True From 43879964bd3ceff183ff4e113b6b5f4d05b34d77 Mon Sep 17 00:00:00 2001 From: Simone Rossetto <simros85@gmail.com> Date: Mon, 23 Mar 2026 10:03:19 +0100 Subject: [PATCH 1658/2030] [wireguard] bump esp_wireguard to 0.4.4 for mbedtls 4.0+ compatibility (#15104) Co-authored-by: J. Nick Koston <nick@koston.org> --- .clang-tidy.hash | 2 +- esphome/components/wireguard/__init__.py | 2 +- platformio.ini | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.clang-tidy.hash b/.clang-tidy.hash index c32978d411..5c7eab517b 100644 --- a/.clang-tidy.hash +++ b/.clang-tidy.hash @@ -1 +1 @@ -9f5d763f95ff720024f3fdddba2fad3801e2bfe00b7cc2124e6d68c17d3504c6 +f31f13994768b5b07e29624406c9b053bf4bb26e1623ac2bc1e9d4a9477502d6 diff --git a/esphome/components/wireguard/__init__.py b/esphome/components/wireguard/__init__.py index e2ea61a542..1b54391376 100644 --- a/esphome/components/wireguard/__init__.py +++ b/esphome/components/wireguard/__init__.py @@ -137,7 +137,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.2") + cg.add_library("droscy/esp_wireguard", "0.4.4") await cg.register_component(var, config) diff --git a/platformio.ini b/platformio.ini index d3a482b652..e0f7c7d443 100644 --- a/platformio.ini +++ b/platformio.ini @@ -118,7 +118,7 @@ lib_deps = ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in) DNSServer ; captive_portal (Arduino built-in) - droscy/esp_wireguard@0.4.2 ; wireguard + droscy/esp_wireguard@0.4.4 ; wireguard lvgl/lvgl@9.5.0 ; lvgl build_flags = @@ -154,7 +154,7 @@ lib_deps = DNSServer ; captive_portal (Arduino built-in) makuna/NeoPixelBus@2.8.0 ; neopixelbus esphome/ESP32-audioI2S@2.3.0 ; i2s_audio - droscy/esp_wireguard@0.4.2 ; wireguard + droscy/esp_wireguard@0.4.4 ; wireguard kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word build_flags = @@ -176,7 +176,7 @@ platform_packages = framework = espidf lib_deps = ${common:idf.lib_deps} - droscy/esp_wireguard@0.4.2 ; wireguard + droscy/esp_wireguard@0.4.4 ; wireguard kahrendt/ESPMicroSpeechFeatures@1.1.0 ; micro_wake_word tonia/HeatpumpIR@1.0.40 ; heatpumpir build_flags = @@ -221,7 +221,7 @@ lib_compat_mode = soft lib_deps = bblanchon/ArduinoJson@7.4.2 ; json ESP32Async/ESPAsyncWebServer@3.9.6 ; web_server_base - droscy/esp_wireguard@0.4.2 ; wireguard + droscy/esp_wireguard@0.4.4 ; wireguard lvgl/lvgl@9.5.0 ; lvgl build_flags = ${common:arduino.build_flags} From 5a984b54cfce79fbd6ad93365cf8ccc148942d6f Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Mon, 23 Mar 2026 07:31:05 -0500 Subject: [PATCH 1659/2030] [audio] Bump microOpus to avoid creating an extra opus-staged directory (#14974) --- esphome/components/audio/__init__.py | 2 +- esphome/idf_component.yml | 2 +- script/analyze_component_buses.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index b28c2ed3d8..9cc80b9b33 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -214,4 +214,4 @@ async def to_code(config): cg.add_define("USE_AUDIO_MP3_SUPPORT") if data.opus_support: cg.add_define("USE_AUDIO_OPUS_SUPPORT") - add_idf_component(name="esphome/micro-opus", ref="0.3.5") + add_idf_component(name="esphome/micro-opus", ref="0.3.6") diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 5cfa8532ff..4148147a3b 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -4,7 +4,7 @@ dependencies: esphome/esp-audio-libs: version: 2.0.3 esphome/micro-opus: - version: 0.3.5 + version: 0.3.6 espressif/esp-dsp: version: "1.7.1" espressif/esp-tflite-micro: diff --git a/script/analyze_component_buses.py b/script/analyze_component_buses.py index 427602dff2..17af7af577 100755 --- a/script/analyze_component_buses.py +++ b/script/analyze_component_buses.py @@ -83,6 +83,7 @@ ISOLATED_COMPONENTS = { "openthread": "Conflicts with wifi: used by most components", "openthread_info": "Conflicts with wifi: used by most components", "matrix_keypad": "Needs isolation due to keypad", + "microphone": "Defines PDM microphone requiring I2S port 0 - conflicts with micro_wake_word PDM mic when merged", "modbus_controller": "Defines multiple modbus buses for testing client/server functionality - conflicts with package modbus bus", "neopixelbus": "RMT type conflict with ESP32 Arduino/ESP-IDF headers (enum vs struct rmt_channel_t)", "packages": "cannot merge packages", From e8c5dfca3ecc959f17722bdafb13471ad4e3f1a0 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 24 Mar 2026 02:09:30 +1000 Subject: [PATCH 1660/2030] [lvgl] Various fixes (#15098) --- esphome/components/lvgl/__init__.py | 8 +++++++- esphome/components/lvgl/lvgl_esphome.h | 2 +- esphome/components/lvgl/widgets/textarea.py | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index c37a32ecca..a6afa12afa 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -226,6 +226,9 @@ async def to_code(configs): config_0 = configs[0] # Global configuration if CORE.is_esp32: + # Skip compiling lvgl examples + add_idf_sdkconfig_option("CONFIG_LV_BUILD_EXAMPLES", False) + add_idf_sdkconfig_option("CONFIG_LV_BUILD_DEMOS", False) if get_esp32_variant() == VARIANT_ESP32P4: add_idf_sdkconfig_option("CONFIG_LV_DRAW_BUF_ALIGN", 64) # disable use of PPA for fills until upstream bugs fixed @@ -406,7 +409,10 @@ async def to_code(configs): lv_conf_h_file = CORE.relative_src_path(LV_CONF_FILENAME) write_file_if_changed(lv_conf_h_file, generate_lv_conf_h()) cg.add_build_flag("-DLV_CONF_H=1") - cg.add_build_flag(f'-DLV_CONF_PATH=\\"{LV_CONF_FILENAME}\\"') + # handle windows paths in a way that doesn't break the generated C++ + lv_conf_h_path = Path(lv_conf_h_file).as_posix() + cg.add_build_flag(f'-DLV_CONF_PATH=\\"{lv_conf_h_path}\\"') + cg.add_build_flag("-DLV_KCONFIG_IGNORE") for prop in df.get_remapped_uses(): df.LOGGER.warning( diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 8e34f16c98..66f823d549 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -71,7 +71,7 @@ inline void lv_style_set_text_font(lv_style_t *style, const font::Font *font) { lv_style_set_text_font(style, font->get_lv_font()); } #endif -#ifdef USE_IMAGE +#if defined(USE_LVGL_IMAGE) && defined(USE_IMAGE) // Shortcut / overload, so that the source of an image can easily be updated // from within a lambda. inline void lv_image_set_src(lv_obj_t *obj, esphome::image::Image *image) { diff --git a/esphome/components/lvgl/widgets/textarea.py b/esphome/components/lvgl/widgets/textarea.py index e5ab884685..baa40ee2c6 100644 --- a/esphome/components/lvgl/widgets/textarea.py +++ b/esphome/components/lvgl/widgets/textarea.py @@ -16,6 +16,7 @@ from ..lv_validation import lv_bool, lv_int, lv_text from ..schemas import TEXT_SCHEMA from ..types import LvText from . import Widget, WidgetType +from .label import CONF_LABEL CONF_TEXTAREA = "textarea" @@ -46,6 +47,9 @@ class TextareaType(WidgetType): TEXTAREA_SCHEMA, ) + def get_uses(self): + return (CONF_LABEL,) + async def to_code(self, w: Widget, config: dict): for prop in (CONF_TEXT, CONF_PLACEHOLDER_TEXT, CONF_ACCEPTED_CHARS): if (value := config.get(prop)) is not None: From 3b5b51b4f0f918fef64e4996dcf0a551389afc4d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:22:25 -1000 Subject: [PATCH 1661/2030] [time] Point to valid IANA timezone list on validation failure (#15110) --- esphome/components/time/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 9821046a73..c31ccbc7ea 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -284,13 +284,23 @@ def validate_tz(value: str) -> str: tzfile = _load_tzdata(value) if tzfile is not None: value = _extract_tz_string(tzfile) + is_iana = True + else: + is_iana = False # Validate that the POSIX TZ string is parseable (skip empty strings) if value: try: parse_posix_tz_python(value) except ValueError as e: - raise cv.Invalid(f"Invalid POSIX timezone string '{value}': {e}") from e + if is_iana: + raise cv.Invalid(f"Invalid POSIX timezone string '{value}': {e}") from e + raise cv.Invalid( + f"Invalid POSIX timezone string '{value}': {e}. " + f"If you meant to use an IANA timezone, check the list of valid " + f"timezones at " + f"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" + ) from e return value From 03d6b36fe03176ea2bca019f701f8a706dc3f3c0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:22:38 -1000 Subject: [PATCH 1662/2030] [gpio] Compile out interlock fields when unused (#15111) --- esphome/components/gpio/switch/__init__.py | 1 + esphome/components/gpio/switch/gpio_switch.cpp | 9 +++++++++ esphome/components/gpio/switch/gpio_switch.h | 4 ++++ esphome/core/defines.h | 1 + 4 files changed, 15 insertions(+) diff --git a/esphome/components/gpio/switch/__init__.py b/esphome/components/gpio/switch/__init__.py index 604de6d809..9462cd0161 100644 --- a/esphome/components/gpio/switch/__init__.py +++ b/esphome/components/gpio/switch/__init__.py @@ -32,6 +32,7 @@ async def to_code(config): cg.add(var.set_pin(pin)) if CONF_INTERLOCK in config: + cg.add_define("USE_GPIO_SWITCH_INTERLOCK") interlock = [] for it in config[CONF_INTERLOCK]: lock = await cg.get_variable(it) diff --git a/esphome/components/gpio/switch/gpio_switch.cpp b/esphome/components/gpio/switch/gpio_switch.cpp index d461fab051..9c6464815a 100644 --- a/esphome/components/gpio/switch/gpio_switch.cpp +++ b/esphome/components/gpio/switch/gpio_switch.cpp @@ -5,7 +5,9 @@ namespace esphome { namespace gpio { static const char *const TAG = "switch.gpio"; +#ifdef USE_GPIO_SWITCH_INTERLOCK static constexpr uint32_t INTERLOCK_TIMEOUT_ID = 0; +#endif float GPIOSwitch::get_setup_priority() const { return setup_priority::HARDWARE; } void GPIOSwitch::setup() { @@ -28,6 +30,7 @@ void GPIOSwitch::setup() { void GPIOSwitch::dump_config() { LOG_SWITCH("", "GPIO Switch", this); LOG_PIN(" Pin: ", this->pin_); +#ifdef USE_GPIO_SWITCH_INTERLOCK if (!this->interlock_.empty()) { ESP_LOGCONFIG(TAG, " Interlocks:"); for (auto *lock : this->interlock_) { @@ -36,8 +39,10 @@ void GPIOSwitch::dump_config() { ESP_LOGCONFIG(TAG, " %s", lock->get_name().c_str()); } } +#endif } void GPIOSwitch::write_state(bool state) { +#ifdef USE_GPIO_SWITCH_INTERLOCK if (state != this->inverted_) { // Turning ON, check interlocking @@ -64,11 +69,15 @@ void GPIOSwitch::write_state(bool state) { // re-activations this->cancel_timeout(INTERLOCK_TIMEOUT_ID); } +#endif this->pin_->digital_write(state); this->publish_state(state); } + +#ifdef USE_GPIO_SWITCH_INTERLOCK void GPIOSwitch::set_interlock(const std::initializer_list<Switch *> &interlock) { this->interlock_ = interlock; } +#endif } // namespace gpio } // namespace esphome diff --git a/esphome/components/gpio/switch/gpio_switch.h b/esphome/components/gpio/switch/gpio_switch.h index a73fb9e18c..f7415d1dba 100644 --- a/esphome/components/gpio/switch/gpio_switch.h +++ b/esphome/components/gpio/switch/gpio_switch.h @@ -18,15 +18,19 @@ class GPIOSwitch final : public switch_::Switch, public Component { void setup() override; void dump_config() override; +#ifdef USE_GPIO_SWITCH_INTERLOCK void set_interlock(const std::initializer_list<Switch *> &interlock); void set_interlock_wait_time(uint32_t interlock_wait_time) { interlock_wait_time_ = interlock_wait_time; } +#endif protected: void write_state(bool state) override; GPIOPin *pin_; +#ifdef USE_GPIO_SWITCH_INTERLOCK FixedVector<Switch *> interlock_; uint32_t interlock_wait_time_{0}; +#endif }; } // namespace gpio diff --git a/esphome/core/defines.h b/esphome/core/defines.h index d94b7e9f5d..f437e30a95 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -53,6 +53,7 @@ #define USE_ESP32_IMPROV_STATE_CALLBACK #define USE_EVENT #define USE_FAN +#define USE_GPIO_SWITCH_INTERLOCK #define USE_GRAPH #define USE_GRAPHICAL_DISPLAY_MENU #define USE_HOMEASSISTANT_TIME From 36d2e58b11836420fff50447c9c2a9ee70cdf432 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:23:08 -1000 Subject: [PATCH 1663/2030] [api] Make ProtoDecodableMessage::decode() non-virtual (#15076) --- esphome/components/api/api_pb2.h | 4 ++-- esphome/components/api/proto.h | 22 +++++++--------------- script/api_protobuf/api_protobuf.py | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a4ee0adb8b..86289a28d6 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1253,7 +1253,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { FixedVector<int32_t> int_array{}; FixedVector<float> float_array{}; FixedVector<std::string> string_array{}; - void decode(const uint8_t *buffer, size_t length) override; + void decode(const uint8_t *buffer, size_t length); #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1278,7 +1278,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES bool return_response{false}; #endif - void decode(const uint8_t *buffer, size_t length) override; + void decode(const uint8_t *buffer, size_t length); #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index a1d825ead9..d6f9c947d7 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -152,8 +152,7 @@ class ProtoVarInt { #endif }; -// Forward declarations for decode_to_message and related encoding helpers -class ProtoDecodableMessage; +// Forward declarations for encoding helpers class ProtoMessage; class ProtoSize; @@ -166,16 +165,9 @@ class ProtoLengthDelimited { const uint8_t *data() const { return this->value_; } size_t size() const { return this->length_; } - /** - * Decode the length-delimited data into an existing ProtoDecodableMessage instance. - * - * This method allows decoding without templates, enabling use in contexts - * where the message type is not known at compile time. The ProtoDecodableMessage's - * decode() method will be called with the raw data and length. - * - * @param msg The ProtoDecodableMessage instance to decode into - */ - void decode_to_message(ProtoDecodableMessage &msg) const; + /// Decode the length-delimited data into a message instance. + /// Template preserves concrete type so decode() resolves statically. + template<typename T> void decode_to_message(T &msg) const; protected: const uint8_t *const value_; @@ -468,7 +460,7 @@ class ProtoMessage { // Base class for messages that support decoding class ProtoDecodableMessage : public ProtoMessage { public: - virtual void decode(const uint8_t *buffer, size_t length); + void decode(const uint8_t *buffer, size_t length); /** * Count occurrences of a repeated field in a protobuf buffer. @@ -704,8 +696,8 @@ template<typename T> inline void ProtoWriteBuffer::encode_optional_sub_message(u this->encode_optional_sub_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>); } -// Implementation of decode_to_message - must be after ProtoDecodableMessage is defined -inline void ProtoLengthDelimited::decode_to_message(ProtoDecodableMessage &msg) const { +// Template decode_to_message - preserves concrete type so decode() resolves statically +template<typename T> void ProtoLengthDelimited::decode_to_message(T &msg) const { msg.decode(this->value_, this->length_); } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 221ccc8d69..0bb569fdb5 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2275,7 +2275,7 @@ def build_message_type( o += "}\n" cpp += o # Generate the decode() declaration in header (public method) - prot = "void decode(const uint8_t *buffer, size_t length) override;" + prot = "void decode(const uint8_t *buffer, size_t length);" public_content.append(prot) # Only generate encode method if this message needs encoding and has fields From 9385f1612820541019f3685810d07f352b9b5ee1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:23:22 -1000 Subject: [PATCH 1664/2030] [text_sensor] Guard raw_callback_ behind USE_TEXT_SENSOR_FILTER, save 4 bytes per instance (#15097) --- esphome/components/text_sensor/text_sensor.cpp | 2 ++ esphome/components/text_sensor/text_sensor.h | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index aa49a85d26..0dc29f9a94 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -31,7 +31,9 @@ void TextSensor::publish_state(const char *state, size_t len) { if (len != this->state.size() || memcmp(state, this->state.data(), len) != 0) { this->state.assign(state, len); } +#ifdef USE_TEXT_SENSOR_FILTER this->raw_callback_.call(this->state); +#endif ESP_LOGV(TAG, "'%s': Received new state %s", this->name_.c_str(), this->state.c_str()); this->notify_frontend_(); #ifdef USE_TEXT_SENSOR_FILTER diff --git a/esphome/components/text_sensor/text_sensor.h b/esphome/components/text_sensor/text_sensor.h index 8941790e7c..3f69e91c8d 100644 --- a/esphome/components/text_sensor/text_sensor.h +++ b/esphome/components/text_sensor/text_sensor.h @@ -64,8 +64,14 @@ class TextSensor : public EntityBase { template<typename F> void add_on_state_callback(F &&callback) { this->callback_.add(std::forward<F>(callback)); } /// Add a callback that will be called every time the sensor sends a raw value. + /// When USE_TEXT_SENSOR_FILTER is not enabled, delegates to the regular callback + /// since raw state equals filtered state without filter support compiled in. template<typename F> void add_on_raw_state_callback(F &&callback) { +#ifdef USE_TEXT_SENSOR_FILTER this->raw_callback_.add(std::forward<F>(callback)); +#else + this->callback_.add(std::forward<F>(callback)); +#endif } // ========== INTERNAL METHODS ========== @@ -77,8 +83,10 @@ class TextSensor : public EntityBase { protected: /// Notify frontend that state has changed (assumes this->state is already set) void notify_frontend_(); +#ifdef USE_TEXT_SENSOR_FILTER LazyCallbackManager<void(const std::string &)> raw_callback_; ///< Storage for raw state callbacks. - LazyCallbackManager<void(const std::string &)> callback_; ///< Storage for filtered state callbacks. +#endif + LazyCallbackManager<void(const std::string &)> callback_; ///< Storage for filtered state callbacks. #ifdef USE_TEXT_SENSOR_FILTER Filter *filter_list_{nullptr}; ///< Store all active filters. From 4b0c711f7743495db05f97168d09bf991f60e204 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:23:35 -1000 Subject: [PATCH 1665/2030] [ci] Ban std::bind in new C++ code (#14969) --- script/ci-custom.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/script/ci-custom.py b/script/ci-custom.py index 06fcdadb8c..1da923b095 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -890,6 +890,22 @@ def lint_no_powf_in_core(fname, match): ) +@lint_re_check( + r"[^\w]std\s*::\s*bind\s*\(" + CPP_RE_EOL, + include=cpp_include, +) +def lint_no_std_bind(fname, match): + return ( + f"{highlight('std::bind()')} is not allowed in new ESPHome code. " + f"Lambdas are clearer, produce smaller binaries, and are more likely to fit within " + f"the {highlight('std::function')} small-buffer optimization (avoiding heap allocation).\n" + f"Please use a lambda instead.\n" + f" Before: {highlight('std::bind(&Class::method, this, std::placeholders::_1)')}\n" + f" After: {highlight('[this](auto arg) { this->method(arg); }')}\n" + f"(If strictly necessary, add `// NOLINT` to the end of the line)" + ) + + LOG_MULTILINE_RE = re.compile(r"ESP_LOG\w+\s*\(.*?;", re.DOTALL) LOG_BAD_CONTINUATION_RE = re.compile(r'\\n(?:[^ \\"\r\n\t]|"\s*\n\s*"[^ \\])') LOG_PERCENT_S_CONTINUATION_RE = re.compile(r'\\n(?:%s|"\s*\n\s*"%s)') From 9da0c5bc857b13a1a6387670a19629bcd5ab20fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:47:15 -1000 Subject: [PATCH 1666/2030] [wifi] Fix roaming attempt counter reset on disconnect during scan (#15099) --- esphome/components/wifi/wifi_component.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 0fd1385258..e1d4b07471 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -269,11 +269,11 @@ bool CompactString::operator==(const StringRef &other) const { /// │ │ │ /// │ ┌──────────────┼──────────────┐ │ /// │ ↓ ↓ ↓ │ -/// │ scan error no better AP +10 dB better AP │ +/// │ disconnect no better AP +10 dB better AP │ /// │ │ │ │ │ /// │ ↓ ↓ ↓ │ /// │ ┌──────────────────────────────┐ ┌──────────────────────────┐ │ -/// │ │ → IDLE │ │ CONNECTING │ │ +/// │ │ → RECONNECTING │ │ CONNECTING │ │ /// │ │ (counter preserved) │ │ (process_roaming_scan_) │ │ /// │ └──────────────────────────────┘ └────────────┬─────────────┘ │ /// │ │ │ @@ -296,7 +296,7 @@ bool CompactString::operator==(const StringRef &other) const { /// │ Key behaviors: │ /// │ - After 3 checks: attempts >= 3, stop checking │ /// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │ -/// │ - Scan error (SCANNING→IDLE): counter preserved │ +/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ /// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │ /// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ /// └──────────────────────────────────────────────────────────────────────┘ @@ -2068,9 +2068,10 @@ void WiFiComponent::retry_connect() { ESP_LOGD(TAG, "Roam failed, reconnecting (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::SCANNING) { - // Roam scan failed (e.g., scan error on ESP8266) - go back to idle, keep counter - ESP_LOGD(TAG, "Roam scan failed (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); - this->roaming_state_ = RoamingState::IDLE; + // Disconnected during roam scan - transition to RECONNECTING so the attempts + // counter is preserved when reconnection succeeds (IDLE would reset it) + ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::IDLE) { // Not a roaming-triggered reconnect, reset state this->clear_roaming_state_(); From 4c1363b104f198aa837a11bd1ba1ecad28371ec4 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Mon, 23 Mar 2026 15:07:40 -0400 Subject: [PATCH 1667/2030] [spi] Add LOG_SPI_DEVICE macro (#15118) --- esphome/components/spi/spi.h | 2 ++ script/ci-custom.py | 1 + 2 files changed, 3 insertions(+) diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index e237cf44f4..84c8bca267 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -34,6 +34,8 @@ using SPIInterface = void *; // Stub for platforms without SPI (e.g., Zephyr) */ namespace esphome::spi { +#define LOG_SPI_DEVICE(this) ESP_LOGCONFIG(TAG, " CS Pin: %d", esphome::spi::Utility::get_pin_no(this->cs_)); + /// The bit-order for SPI devices. This defines how the data read from and written to the device is interpreted. enum SPIBitOrder { /// The least significant bit is transmitted/received first. diff --git a/script/ci-custom.py b/script/ci-custom.py index 1da923b095..25a0cf2127 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -963,6 +963,7 @@ def lint_log_multiline_continuation(fname, content): "esphome/components/nextion/nextion_base.h", "esphome/components/select/select.h", "esphome/components/sensor/sensor.h", + "esphome/components/spi/spi.h", "esphome/components/stepper/stepper.h", "esphome/components/switch/switch.h", "esphome/components/text/text.h", From 1e16b30380a4703142318a5a1a93f6ad3626f6f2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 09:18:58 -1000 Subject: [PATCH 1668/2030] [ethernet] Add ENC28J60 SPI Ethernet support (#14945) --- esphome/components/ethernet/__init__.py | 44 ++++++++++++++----- .../components/ethernet/ethernet_component.h | 13 ++++++ .../ethernet/ethernet_component_esp32.cpp | 41 +++++++++++------ .../ethernet/ethernet_component_rp2040.cpp | 27 +++++++++--- .../ethernet/common-enc28j60-rp2040.yaml | 18 ++++++++ .../components/ethernet/common-enc28j60.yaml | 19 ++++++++ .../ethernet/test-enc28j60.esp32-idf.yaml | 1 + .../ethernet/test-enc28j60.rp2040-ard.yaml | 1 + 8 files changed, 134 insertions(+), 30 deletions(-) create mode 100644 tests/components/ethernet/common-enc28j60-rp2040.yaml create mode 100644 tests/components/ethernet/common-enc28j60.yaml create mode 100644 tests/components/ethernet/test-enc28j60.esp32-idf.yaml create mode 100644 tests/components/ethernet/test-enc28j60.rp2040-ard.yaml diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index f519d79aa1..e17abfcc93 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -119,6 +119,7 @@ ETHERNET_TYPES = { "OPENETH": EthernetType.ETHERNET_TYPE_OPENETH, "DM9051": EthernetType.ETHERNET_TYPE_DM9051, "LAN8670": EthernetType.ETHERNET_TYPE_LAN8670, + "ENC28J60": EthernetType.ETHERNET_TYPE_ENC28J60, } # PHY types that need compile-time defines for conditional compilation @@ -134,6 +135,7 @@ _PHY_TYPE_TO_DEFINE = { "W5500": "USE_ETHERNET_W5500", "DM9051": "USE_ETHERNET_DM9051", "LAN8670": "USE_ETHERNET_LAN8670", + "ENC28J60": "USE_ETHERNET_ENC28J60", } @@ -155,11 +157,16 @@ _IDF6_ETHERNET_COMPONENTS: dict[str, IDFRegistryComponent] = { "KSZ8081RNA": IDFRegistryComponent("espressif/ksz80xx", "1.0.0"), "W5500": IDFRegistryComponent("espressif/w5500", "1.0.1"), "DM9051": IDFRegistryComponent("espressif/dm9051", "1.0.0"), + "ENC28J60": IDFRegistryComponent("espressif/enc28j60", "1.0.1"), + "LAN8670": IDFRegistryComponent("espressif/lan867x", "2.0.0"), } -SPI_ETHERNET_TYPES = ["W5500", "DM9051"] +# These types are always external IDF components (never built-in to ESP-IDF) +_ALWAYS_EXTERNAL_IDF_COMPONENTS = {"LAN8670", "ENC28J60"} + +SPI_ETHERNET_TYPES = ["W5500", "DM9051", "ENC28J60"] # RP2040-supported SPI ethernet types -RP2040_SPI_ETHERNET_TYPES = ["W5500"] +RP2040_SPI_ETHERNET_TYPES = ["W5500", "ENC28J60"] SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t") @@ -220,7 +227,18 @@ def _validate(config): if CORE.is_esp32: if config[CONF_TYPE] in SPI_ETHERNET_TYPES: - if _is_framework_spi_polling_mode_supported(): + # ENC28J60 driver does not support polling mode - interrupt is required + if config[CONF_TYPE] == "ENC28J60": + if CONF_POLLING_INTERVAL in config: + raise cv.Invalid( + f"'{CONF_POLLING_INTERVAL}' is not supported for ENC28J60. " + f"'{CONF_INTERRUPT_PIN}' is required." + ) + if CONF_INTERRUPT_PIN not in config: + raise cv.Invalid( + f"'{CONF_INTERRUPT_PIN}' is a required option for ENC28J60." + ) + elif _is_framework_spi_polling_mode_supported(): if CONF_POLLING_INTERVAL in config and CONF_INTERRUPT_PIN in config: raise cv.Invalid( f"Cannot specify more than one of {CONF_INTERRUPT_PIN}, {CONF_POLLING_INTERVAL}" @@ -367,6 +385,7 @@ CONFIG_SCHEMA = cv.All( "W5500": SPI_SCHEMA, "OPENETH": cv.All(BASE_SCHEMA, cv.only_on([Platform.ESP32])), "DM9051": SPI_SCHEMA, + "ENC28J60": SPI_SCHEMA, "LAN8670": RMII_SCHEMA, }, upper=True, @@ -502,7 +521,8 @@ async def _to_code_esp32(var: cg.Pvariable, config: ConfigType) -> None: cg.add_define("USE_ETHERNET_SPI") add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) # CONFIG_ETH_SPI_ETHERNET_{TYPE} Kconfig options were removed in IDF 6.0 - if idf_version() < cv.Version(6, 0, 0): + # ENC28J60 was never built-in to IDF, so it has no Kconfig option + if idf_version() < cv.Version(6, 0, 0) and config[CONF_TYPE] != "ENC28J60": add_idf_sdkconfig_option( f"CONFIG_ETH_SPI_ETHERNET_{config[CONF_TYPE]}", True ) @@ -533,12 +553,11 @@ async def _to_code_esp32(var: cg.Pvariable, config: ConfigType) -> None: # Re-enable ESP-IDF's Ethernet driver (excluded by default to save compile time) include_builtin_idf_component("esp_eth") - if config[CONF_TYPE] == "LAN8670": - # Add LAN867x 10BASE-T1S PHY support component - add_idf_component(name="espressif/lan867x", ref="2.0.0") - - # IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry - if idf_version() >= cv.Version(6, 0, 0) and ( + if config[CONF_TYPE] in _ALWAYS_EXTERNAL_IDF_COMPONENTS: + component = _IDF6_ETHERNET_COMPONENTS[config[CONF_TYPE]] + add_idf_component(name=component.name, ref=component.version) + elif idf_version() >= cv.Version(6, 0, 0) and ( + # IDF 6.0 moved per-chip PHY/MAC drivers to the Espressif Component Registry component := _IDF6_ETHERNET_COMPONENTS.get(config[CONF_TYPE]) ): add_idf_component(name=component.name, ref=component.version) @@ -555,7 +574,10 @@ async def _to_code_rp2040(var: cg.Pvariable, config: ConfigType) -> None: cg.add(var.set_reset_pin(config[CONF_RESET_PIN])) cg.add_define("USE_ETHERNET_SPI") - cg.add_library("lwIP_w5500", None) + if config[CONF_TYPE] == "ENC28J60": + cg.add_library("lwIP_enc28j60", None) + else: + cg.add_library("lwIP_w5500", None) def _final_validate_rmii_pins(config: ConfigType) -> None: diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index b6699e8020..4c85c39eb8 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -23,7 +23,13 @@ extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); #endif // USE_ESP32 #ifdef USE_RP2040 +#if defined(USE_ETHERNET_W5500) #include <W5500lwIP.h> +#elif defined(USE_ETHERNET_ENC28J60) +#include <ENC28J60lwIP.h> +#else +#error "Unsupported RP2040 SPI Ethernet type" +#endif #endif namespace esphome::ethernet { @@ -57,6 +63,7 @@ enum EthernetType : uint8_t { ETHERNET_TYPE_OPENETH, ETHERNET_TYPE_DM9051, ETHERNET_TYPE_LAN8670, + ETHERNET_TYPE_ENC28J60, }; struct ManualIP { @@ -215,7 +222,13 @@ class EthernetComponent final : public Component { #ifdef USE_RP2040 static constexpr uint32_t LINK_CHECK_INTERVAL = 500; // ms between link/IP polls +#if defined(USE_ETHERNET_W5500) Wiznet5500lwIP *eth_{nullptr}; +#elif defined(USE_ETHERNET_ENC28J60) + ENC28J60lwIP *eth_{nullptr}; +#else +#error "Unsupported RP2040 SPI Ethernet type" +#endif uint32_t last_link_check_{0}; uint8_t clk_pin_; uint8_t miso_pin_; diff --git a/esphome/components/ethernet/ethernet_component_esp32.cpp b/esphome/components/ethernet/ethernet_component_esp32.cpp index fb69a901aa..a170239e03 100644 --- a/esphome/components/ethernet/ethernet_component_esp32.cpp +++ b/esphome/components/ethernet/ethernet_component_esp32.cpp @@ -44,6 +44,11 @@ #include "esp_eth_phy_lan867x.h" #endif +// ENC28J60 header exists on all IDF versions (always an external component) +#ifdef USE_ETHERNET_ENC28J60 +#include "esp_eth_enc28j60.h" +#endif + #ifdef USE_ETHERNET_SPI #include <driver/gpio.h> #include <driver/spi_master.h> @@ -194,25 +199,27 @@ void EthernetComponent::setup() { .post_cb = nullptr, }; -#ifdef USE_ETHERNET_W5500 +#if defined(USE_ETHERNET_W5500) eth_w5500_config_t w5500_config = ETH_W5500_DEFAULT_CONFIG(host, &devcfg); -#endif -#ifdef USE_ETHERNET_DM9051 +#elif defined(USE_ETHERNET_DM9051) eth_dm9051_config_t dm9051_config = ETH_DM9051_DEFAULT_CONFIG(host, &devcfg); +#elif defined(USE_ETHERNET_ENC28J60) + eth_enc28j60_config_t enc28j60_config = ETH_ENC28J60_DEFAULT_CONFIG(host, &devcfg); #endif -#ifdef USE_ETHERNET_W5500 +#if defined(USE_ETHERNET_W5500) w5500_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT w5500_config.poll_period_ms = this->polling_interval_; #endif -#endif - -#ifdef USE_ETHERNET_DM9051 +#elif defined(USE_ETHERNET_DM9051) dm9051_config.int_gpio_num = this->interrupt_pin_; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT dm9051_config.poll_period_ms = this->polling_interval_; #endif +#elif defined(USE_ETHERNET_ENC28J60) + enc28j60_config.int_gpio_num = this->interrupt_pin_; + // ENC28J60 does not support poll_period_ms #endif phy_config.phy_addr = this->phy_addr_spi_; @@ -300,19 +307,24 @@ void EthernetComponent::setup() { #endif #endif #ifdef USE_ETHERNET_SPI -#ifdef USE_ETHERNET_W5500 +#if defined(USE_ETHERNET_W5500) case ETHERNET_TYPE_W5500: { mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config); this->phy_ = esp_eth_phy_new_w5500(&phy_config); break; } -#endif -#ifdef USE_ETHERNET_DM9051 +#elif defined(USE_ETHERNET_DM9051) case ETHERNET_TYPE_DM9051: { mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config); this->phy_ = esp_eth_phy_new_dm9051(&phy_config); break; } +#elif defined(USE_ETHERNET_ENC28J60) + case ETHERNET_TYPE_ENC28J60: { + mac = esp_eth_mac_new_enc28j60(&enc28j60_config, &mac_config); + this->phy_ = esp_eth_phy_new_enc28j60(&phy_config); + break; + } #endif #endif default: { @@ -405,15 +417,18 @@ void EthernetComponent::dump_config() { eth_type = "KSZ8081RNA"; break; #endif -#ifdef USE_ETHERNET_W5500 +#if defined(USE_ETHERNET_W5500) case ETHERNET_TYPE_W5500: eth_type = "W5500"; break; -#endif -#ifdef USE_ETHERNET_DM9051 +#elif defined(USE_ETHERNET_DM9051) case ETHERNET_TYPE_DM9051: eth_type = "DM9051"; break; +#elif defined(USE_ETHERNET_ENC28J60) + case ETHERNET_TYPE_ENC28J60: + eth_type = "ENC28J60"; + break; #endif #ifdef USE_ETHERNET_OPENETH case ETHERNET_TYPE_OPENETH: diff --git a/esphome/components/ethernet/ethernet_component_rp2040.cpp b/esphome/components/ethernet/ethernet_component_rp2040.cpp index 77b1a22d66..bd8c458985 100644 --- a/esphome/components/ethernet/ethernet_component_rp2040.cpp +++ b/esphome/components/ethernet/ethernet_component_rp2040.cpp @@ -31,11 +31,15 @@ void EthernetComponent::setup() { reset_pin.digital_write(false); delay(1); // NOLINT reset_pin.digital_write(true); - delay(10); // NOLINT - wait for W5500 to initialize after reset + delay(10); // NOLINT - wait for chip to initialize after reset } - // Create the W5500 device instance + // Create the SPI Ethernet device instance +#if defined(USE_ETHERNET_W5500) this->eth_ = new Wiznet5500lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT +#elif defined(USE_ETHERNET_ENC28J60) + this->eth_ = new ENC28J60lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT +#endif // Set hostname before begin() so the LWIP netif gets it this->eth_->hostname(App.get_name().c_str()); @@ -61,7 +65,7 @@ void EthernetComponent::setup() { } if (!success) { - ESP_LOGE(TAG, "Failed to initialize W5500 Ethernet"); + ESP_LOGE(TAG, "Failed to initialize Ethernet"); delete this->eth_; // NOLINT(cppcoreguidelines-owning-memory) this->eth_ = nullptr; this->mark_failed(); @@ -164,9 +168,15 @@ void EthernetComponent::loop() { } void EthernetComponent::dump_config() { + const char *type_str = "Unknown"; +#if defined(USE_ETHERNET_W5500) + type_str = "W5500"; +#elif defined(USE_ETHERNET_ENC28J60) + type_str = "ENC28J60"; +#endif ESP_LOGCONFIG(TAG, "Ethernet:\n" - " Type: W5500\n" + " Type: %s\n" " Connected: %s\n" " CLK Pin: %u\n" " MISO Pin: %u\n" @@ -174,7 +184,7 @@ void EthernetComponent::dump_config() { " CS Pin: %u\n" " IRQ Pin: %d\n" " Reset Pin: %d", - YESNO(this->is_connected()), this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_, + type_str, YESNO(this->is_connected()), this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_, this->interrupt_pin_, this->reset_pin_); this->dump_connect_params_(); } @@ -216,13 +226,18 @@ const char *EthernetComponent::get_eth_mac_address_pretty_into_buffer( } eth_duplex_t EthernetComponent::get_duplex_mode() { - // W5500 is always full duplex + // Both W5500 and ENC28J60 are full-duplex on RP2040 return ETH_DUPLEX_FULL; } eth_speed_t EthernetComponent::get_link_speed() { +#ifdef USE_ETHERNET_ENC28J60 + // ENC28J60 is 10Mbps only + return ETH_SPEED_10M; +#else // W5500 is always 100Mbps return ETH_SPEED_100M; +#endif } bool EthernetComponent::powerdown() { diff --git a/tests/components/ethernet/common-enc28j60-rp2040.yaml b/tests/components/ethernet/common-enc28j60-rp2040.yaml new file mode 100644 index 0000000000..0718723d8a --- /dev/null +++ b/tests/components/ethernet/common-enc28j60-rp2040.yaml @@ -0,0 +1,18 @@ +ethernet: + type: ENC28J60 + clk_pin: 18 + mosi_pin: 19 + miso_pin: 16 + cs_pin: 17 + interrupt_pin: 21 + reset_pin: 20 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/common-enc28j60.yaml b/tests/components/ethernet/common-enc28j60.yaml new file mode 100644 index 0000000000..6b288bed19 --- /dev/null +++ b/tests/components/ethernet/common-enc28j60.yaml @@ -0,0 +1,19 @@ +ethernet: + type: ENC28J60 + clk_pin: 19 + mosi_pin: 21 + miso_pin: 23 + cs_pin: 18 + interrupt_pin: 36 + reset_pin: 22 + clock_speed: 10Mhz + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/test-enc28j60.esp32-idf.yaml b/tests/components/ethernet/test-enc28j60.esp32-idf.yaml new file mode 100644 index 0000000000..b7c1b7f5aa --- /dev/null +++ b/tests/components/ethernet/test-enc28j60.esp32-idf.yaml @@ -0,0 +1 @@ +<<: !include common-enc28j60.yaml diff --git a/tests/components/ethernet/test-enc28j60.rp2040-ard.yaml b/tests/components/ethernet/test-enc28j60.rp2040-ard.yaml new file mode 100644 index 0000000000..61d1cd86f5 --- /dev/null +++ b/tests/components/ethernet/test-enc28j60.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-enc28j60-rp2040.yaml From 11b829dda17b8cca2174272069caf36d0dca2628 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Mon, 23 Mar 2026 15:59:17 -0400 Subject: [PATCH 1669/2030] [spa06_spi] Add SPA06-003 Temperature and Pressure Sensor - SPI support (Part 3 of 3) (#14523) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/spa06_spi/__init__.py | 0 esphome/components/spa06_spi/sensor.py | 41 +++++++++++ esphome/components/spa06_spi/spa06_spi.cpp | 72 +++++++++++++++++++ esphome/components/spa06_spi/spa06_spi.h | 22 ++++++ tests/components/spa06_spi/common.yaml | 15 ++++ .../components/spa06_spi/test.esp32-idf.yaml | 7 ++ .../spa06_spi/test.esp8266-ard.yaml | 7 ++ .../components/spa06_spi/test.rp2040-ard.yaml | 7 ++ 9 files changed, 172 insertions(+) create mode 100644 esphome/components/spa06_spi/__init__.py create mode 100644 esphome/components/spa06_spi/sensor.py create mode 100644 esphome/components/spa06_spi/spa06_spi.cpp create mode 100644 esphome/components/spa06_spi/spa06_spi.h create mode 100644 tests/components/spa06_spi/common.yaml create mode 100644 tests/components/spa06_spi/test.esp32-idf.yaml create mode 100644 tests/components/spa06_spi/test.esp8266-ard.yaml create mode 100644 tests/components/spa06_spi/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index e3e09cbc11..afe4cdb871 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -459,6 +459,7 @@ esphome/components/sonoff_d1/* @anatoly-savchenkov esphome/components/sound_level/* @kahrendt esphome/components/spa06_base/* @danielkent-net esphome/components/spa06_i2c/* @danielkent-net +esphome/components/spa06_spi/* @danielkent-net esphome/components/speaker/* @jesserockz @kahrendt esphome/components/speaker/media_player/* @kahrendt @synesthesiam esphome/components/speaker_source/* @kahrendt diff --git a/esphome/components/spa06_spi/__init__.py b/esphome/components/spa06_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/spa06_spi/sensor.py b/esphome/components/spa06_spi/sensor.py new file mode 100644 index 0000000000..b82186ec21 --- /dev/null +++ b/esphome/components/spa06_spi/sensor.py @@ -0,0 +1,41 @@ +import logging + +import esphome.codegen as cg +from esphome.components import spi +from esphome.components.spi import CONF_SPI_MODE +import esphome.config_validation as cv + +from ..spa06_base import CONFIG_SCHEMA_BASE, to_code_base + +AUTO_LOAD = ["spa06_base"] +CODEOWNERS = ["@danielkent-net"] +DEPENDENCIES = ["spi"] + +spa06_ns = cg.esphome_ns.namespace("spa06_spi") +SPA06SPIComponent = spa06_ns.class_( + "SPA06SPIComponent", cg.PollingComponent, spi.SPIDevice +) + +_LOGGER = logging.getLogger(__name__) + +VALID_SPI_MODES = {3: "MODE3", "3": "MODE3", "MODE3": "MODE3"} + + +def check_spi_mode(config): + spi_mode = config.get(CONF_SPI_MODE) + if spi_mode not in VALID_SPI_MODES: + raise cv.Invalid("SPA06 only supports SPI mode 3") + return config + + +CONFIG_SCHEMA = cv.All( + CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema(default_mode="mode3")).extend( + {cv.GenerateID(): cv.declare_id(SPA06SPIComponent)} + ), + check_spi_mode, +) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/esphome/components/spa06_spi/spa06_spi.cpp b/esphome/components/spa06_spi/spa06_spi.cpp new file mode 100644 index 0000000000..9f3683d219 --- /dev/null +++ b/esphome/components/spa06_spi/spa06_spi.cpp @@ -0,0 +1,72 @@ +#include <cstdint> +#include <cstddef> + +#include "spa06_spi.h" +#include "esphome/components/spa06_base/spa06_base.h" +#include "esphome/components/spi/spi.h" + +// OR (|) register with SPA06_SPI_READ for read. +inline constexpr uint8_t SPA06_SPI_READ = 0x80; + +// AND (&) register with SPA06_SPI_WRITE for write. +inline constexpr uint8_t SPA06_SPI_WRITE = 0x7F; + +namespace esphome::spa06_spi { + +static const char *const TAG = "spa06_spi"; + +void SPA06SPIComponent::dump_config() { + SPA06Component::dump_config(); + LOG_SPI_DEVICE(this) +} + +void SPA06SPIComponent::setup() { + this->spi_setup(); + SPA06Component::setup(); +} + +void SPA06SPIComponent::protocol_reset() { + // Forces the device into SPI mode using a dummy read + uint8_t dummy_read = 0; + this->spa_read_byte(spa06_base::SPA06_ID, &dummy_read); +} + +// In SPI mode, only 7 bits of the register addresses are used; the MSB of register address +// is not used and replaced by a read/write bit (RW = ‘0’ for write and RW = ‘1’ for read). +// Example: address 0xF7 is accessed by using SPI register address 0x77. For write access, +// the byte 0x77 is transferred, for read access, the byte 0xF7 is transferred. +// The expressions SPA06_SPI_READ (| with register) and SPA06_SPI_WRITE (& with register) +// are defined for readability. + +bool SPA06SPIComponent::spa_read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(a_register | SPA06_SPI_READ); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool SPA06SPIComponent::spa_write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(a_register & SPA06_SPI_WRITE); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool SPA06SPIComponent::spa_read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(a_register | SPA06_SPI_READ); + this->read_array(data, len); + this->disable(); + return true; +} + +bool SPA06SPIComponent::spa_write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(a_register & SPA06_SPI_WRITE); + this->write_array(data, len); + this->disable(); + return true; +} +} // namespace esphome::spa06_spi diff --git a/esphome/components/spa06_spi/spa06_spi.h b/esphome/components/spa06_spi/spa06_spi.h new file mode 100644 index 0000000000..ffbc162d6f --- /dev/null +++ b/esphome/components/spa06_spi/spa06_spi.h @@ -0,0 +1,22 @@ +#pragma once + +#include "esphome/components/spa06_base/spa06_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome::spa06_spi { + +class SPA06SPIComponent : public spa06_base::SPA06Component, + public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, + spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_200KHZ> { + void setup() override; + bool spa_read_byte(uint8_t a_register, uint8_t *data) override; + bool spa_write_byte(uint8_t a_register, uint8_t data) override; + bool spa_read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool spa_write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + void dump_config() override; + + protected: + void protocol_reset() override; +}; + +} // namespace esphome::spa06_spi diff --git a/tests/components/spa06_spi/common.yaml b/tests/components/spa06_spi/common.yaml new file mode 100644 index 0000000000..9263202ab4 --- /dev/null +++ b/tests/components/spa06_spi/common.yaml @@ -0,0 +1,15 @@ +sensor: + - platform: spa06_spi + spi_id: spi_bus + cs_pin: ${cs_pin} + temperature: + id: spa06_spi_temperature + name: Outside Temperature + sample_rate: 1 + oversampling: NONE + pressure: + name: Outside Pressure + id: spa06_spi_pressure + sample_rate: 25p4 + oversampling: 16X + update_interval: 15s diff --git a/tests/components/spa06_spi/test.esp32-idf.yaml b/tests/components/spa06_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..a3352cf880 --- /dev/null +++ b/tests/components/spa06_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO5 + +packages: + spi: !include ../../test_build_components/common/spi/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/spa06_spi/test.esp8266-ard.yaml b/tests/components/spa06_spi/test.esp8266-ard.yaml new file mode 100644 index 0000000000..595f31046a --- /dev/null +++ b/tests/components/spa06_spi/test.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO15 + +packages: + spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/spa06_spi/test.rp2040-ard.yaml b/tests/components/spa06_spi/test.rp2040-ard.yaml new file mode 100644 index 0000000000..93e19cfea4 --- /dev/null +++ b/tests/components/spa06_spi/test.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO17 + +packages: + spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml + +<<: !include common.yaml From 6956bf7e539589ee06282d8560b97f91989397c3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 24 Mar 2026 07:24:25 +1000 Subject: [PATCH 1670/2030] [text] Add text_sensor for read-only view of text component (#15090) --- .../components/text/text_sensor/__init__.py | 25 +++++++++++++++++++ .../text/text_sensor/text_text_sensor.cpp | 16 ++++++++++++ .../text/text_sensor/text_text_sensor.h | 19 ++++++++++++++ tests/components/text/common.yaml | 5 ++++ 4 files changed, 65 insertions(+) create mode 100644 esphome/components/text/text_sensor/__init__.py create mode 100644 esphome/components/text/text_sensor/text_text_sensor.cpp create mode 100644 esphome/components/text/text_sensor/text_text_sensor.h diff --git a/esphome/components/text/text_sensor/__init__.py b/esphome/components/text/text_sensor/__init__.py new file mode 100644 index 0000000000..5e45f10193 --- /dev/null +++ b/esphome/components/text/text_sensor/__init__.py @@ -0,0 +1,25 @@ +import esphome.codegen as cg +from esphome.components import text_sensor +import esphome.config_validation as cv +from esphome.const import CONF_SOURCE_ID + +from .. import Text, text_ns + +TextTextSensor = text_ns.class_("TextTextSensor", text_sensor.TextSensor, cg.Component) + + +CONFIG_SCHEMA = ( + text_sensor.text_sensor_schema(TextTextSensor) + .extend( + { + cv.Required(CONF_SOURCE_ID): cv.use_id(Text), + } + ) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + source = await cg.get_variable(config[CONF_SOURCE_ID]) + var = await text_sensor.new_text_sensor(config, source) + await cg.register_component(var, config) diff --git a/esphome/components/text/text_sensor/text_text_sensor.cpp b/esphome/components/text/text_sensor/text_text_sensor.cpp new file mode 100644 index 0000000000..50504c605e --- /dev/null +++ b/esphome/components/text/text_sensor/text_text_sensor.cpp @@ -0,0 +1,16 @@ +#include "text_text_sensor.h" +#include "esphome/core/log.h" + +namespace esphome::text { + +static const char *const TAG = "text.text_sensor"; + +void TextTextSensor::setup() { + this->source_->add_on_state_callback([this](const std::string &value) { this->publish_state(value); }); + if (this->source_->has_state()) + this->publish_state(this->source_->state); +} + +void TextTextSensor::dump_config() { LOG_TEXT_SENSOR("", "Text Text Sensor", this); } + +} // namespace esphome::text diff --git a/esphome/components/text/text_sensor/text_text_sensor.h b/esphome/components/text/text_sensor/text_text_sensor.h new file mode 100644 index 0000000000..fd70ea3451 --- /dev/null +++ b/esphome/components/text/text_sensor/text_text_sensor.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../text.h" +#include "esphome/core/component.h" +#include "esphome/components/text_sensor/text_sensor.h" + +namespace esphome::text { + +class TextTextSensor : public text_sensor::TextSensor, public Component { + public: + explicit TextTextSensor(Text *source) : source_(source) {} + void setup() override; + void dump_config() override; + + protected: + Text *source_; +}; + +} // namespace esphome::text diff --git a/tests/components/text/common.yaml b/tests/components/text/common.yaml index 26618be03a..561d17143f 100644 --- a/tests/components/text/common.yaml +++ b/tests/components/text/common.yaml @@ -23,3 +23,8 @@ text: min_length: 8 max_length: 32 mode: password + +text_sensor: + - platform: text + name: "Test Text State" + source_id: test_text From 332118db5644b161c09c90f64e07f2289d6f86a9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:44:26 -1000 Subject: [PATCH 1671/2030] Bump pytest-cov from 7.0.0 to 7.1.0 (#15123) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index 0d3f0671f5..1440b20333 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -6,7 +6,7 @@ pre-commit # Unit tests pytest==9.0.2 -pytest-cov==7.0.0 +pytest-cov==7.1.0 pytest-mock==3.15.1 pytest-asyncio==1.3.0 pytest-xdist==3.8.0 From bf6000ef3d38bf663d4fc2d69a220d5a64889e78 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Mon, 23 Mar 2026 23:50:28 +0100 Subject: [PATCH 1672/2030] [substitutions] substitutions pass and !include redesign (package refactor part 2b) (#14918) Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/packages/__init__.py | 9 +- esphome/components/substitutions/__init__.py | 444 +++++++++++++----- esphome/components/substitutions/jinja.py | 94 +--- esphome/config.py | 30 +- esphome/yaml_util.py | 41 +- .../component_tests/packages/test_packages.py | 2 + .../substitutions/00-simple_var.approved.yaml | 17 + .../substitutions/00-simple_var.input.yaml | 10 + .../02-expressions.approved.yaml | 6 + .../substitutions/02-expressions.input.yaml | 6 + .../07-package_merging.approved.yaml | 46 ++ .../07-package_merging.input.yaml | 63 +++ ...-include_vars_without_substs.approved.yaml | 5 + .../09-include_vars_without_substs.input.yaml | 7 + tests/unit_tests/test_substitutions.py | 244 +++++++++- tests/unit_tests/test_yaml_util.py | 2 +- 16 files changed, 753 insertions(+), 273 deletions(-) create mode 100644 tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/07-package_merging.input.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.approved.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.input.yaml diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index 6d353ccf11..793cb946dd 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -226,7 +226,7 @@ def _process_remote_package(config: dict, skip_update: bool = False) -> dict: raise cv.Invalid( f"Current ESPHome Version is too old to use this package: {ESPHOME_VERSION} < {min_version}" ) - new_yaml = yaml_util.substitute_vars(new_yaml, vars) + new_yaml = yaml_util.add_context(new_yaml, vars or None) packages[f"{filename}{idx}"] = new_yaml except EsphomeError as e: raise cv.Invalid( @@ -296,6 +296,13 @@ def do_packages_pass(config: dict, skip_update: bool = False) -> dict: def process_package_callback(package_config: dict) -> dict: """This will be called for each package found in the config.""" + if isinstance(package_config, yaml_util.ConfigContext): + context_vars = package_config.vars + if CONF_PACKAGES in package_config or CONF_URL in package_config: + # Remote package definition: eagerly resolve before PACKAGE_SCHEMA validation. + from esphome.components.substitutions import substitute_context_vars + + substitute_context_vars(package_config, context_vars) package_config = PACKAGE_SCHEMA(package_config) if isinstance(package_config, str): return package_config # Jinja string, skip processing diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index 7e15f714f7..ecee816ce9 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -1,31 +1,50 @@ +from collections import ChainMap import logging -from re import Match from typing import Any from esphome import core from esphome.config_helpers import Extend, Remove, merge_config, merge_dicts_ordered import esphome.config_validation as cv from esphome.const import CONF_SUBSTITUTIONS, VALID_SUBSTITUTIONS_CHARACTERS -from esphome.yaml_util import ESPHomeDataBase, ESPLiteralValue, make_data_base +from esphome.types import ConfigType +from esphome.util import OrderedDict +from esphome.yaml_util import ( + ConfigContext, + ESPHomeDataBase, + ESPLiteralValue, + make_data_base, +) -from .jinja import Jinja, JinjaError, JinjaStr, has_jinja +from .jinja import Jinja, JinjaError, Missing, Resolver, UndefinedError, has_jinja CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) +ContextVars = ChainMap[str, Any] +SubstitutionPath = list[int | str] +ErrList = list[tuple[UndefinedError, SubstitutionPath, Any]] +# Module-level instance is safe: context_vars is passed per-call, and context_trace +# is stack-saved/restored within expand(). Not thread-safe — only use from one thread. +jinja = Jinja() -def validate_substitution_key(value): + +def validate_substitution_key(value: Any) -> str: + """Validate and normalize a substitution key, stripping a leading ``$`` if present.""" value = cv.string(value) if not value: raise cv.Invalid("Substitution key must not be empty") if value[0] == "$": value = value[1:] + if not value: + raise cv.Invalid("Substitution key must not be empty") if value[0].isdigit(): raise cv.Invalid("First character in substitutions cannot be a digit.") for char in value: if char not in VALID_SUBSTITUTIONS_CHARACTERS: raise cv.Invalid( - f"Substitution must only consist of upper/lowercase characters, the underscore and numbers. The character '{char}' cannot be used" + f"Substitution must only consist of upper/lowercase characters," + f" the underscore and numbers." + f" The character '{char}' cannot be used" ) return value @@ -37,8 +56,8 @@ CONFIG_SCHEMA = cv.Schema( ) -async def to_code(config): - pass +async def to_code(config: ConfigType) -> None: + """No runtime code generation needed — substitutions are resolved at config time.""" def _restore_data_base(value: Any, orig_value: ESPHomeDataBase) -> ESPHomeDataBase: @@ -62,91 +81,122 @@ def _restore_data_base(value: Any, orig_value: ESPHomeDataBase) -> ESPHomeDataBa return value -def _expand_jinja( - value: str | JinjaStr, - orig_value: str | JinjaStr, - path, - jinja: Jinja, - ignore_missing: bool, -) -> Any: - if has_jinja(value): - # If the original value passed in to this function is a JinjaStr, it means it contains an unresolved - # Jinja expression from a previous pass. - if isinstance(orig_value, JinjaStr): - # Rebuild the JinjaStr in case it was lost while replacing substitutions. - value = JinjaStr(value, orig_value.upvalues) - try: - # Invoke the jinja engine to evaluate the expression. - value, err = jinja.expand(value) - if err is not None and not ignore_missing and "password" not in path: - _LOGGER.warning( - "Found '%s' (see %s) which looks like an expression," - " but could not resolve all the variables: %s", - value, - "->".join(str(x) for x in path), - err.message, - ) - except JinjaError as err: - raise cv.Invalid( - f"{err.error_name()} Error evaluating jinja expression '{value}': {str(err.parent())}." - f"\nEvaluation stack: (most recent evaluation last)\n{err.stack_trace_str()}" - f"\nRelevant context:\n{err.context_trace_str()}" - f"\nSee {'->'.join(str(x) for x in path)}", - path, - ) - # If the original, unexpanded string, contained document metadata (ESPHomeDatabase), - # assign this same document metadata to the resulting value. - if isinstance(orig_value, ESPHomeDataBase): - value = _restore_data_base(value, orig_value) +def _try_substitute(value: Any, context: ContextVars) -> Any: + """Substitute variables in value, returning the result or the original if unchanged.""" + result = _substitute_item(value, [], context, strict_undefined=True) + return result if result is not None else value - return value + +def _resolve_var(name: str, context_vars: ContextVars) -> Any: + """Look up a substitution variable, falling back to the resolver callback.""" + sub = context_vars.get(name, Missing) + if sub is Missing: + resolver = context_vars.get(Resolver) + if resolver: + sub = resolver(name) + return sub + + +def _handle_undefined( + err: UndefinedError, + path: SubstitutionPath, + value: Any, + strict_undefined: bool, + errors: ErrList | None, +) -> None: + """Handle an undefined variable. + + In strict mode, raises immediately. Otherwise, appends to the errors + list for deferred warning at the end of the substitution pass. + """ + if strict_undefined: + raise err + if errors is not None: + errors.append((err, path, value)) def _expand_substitutions( - substitutions: dict, value: str, path, jinja: Jinja, ignore_missing: bool + value: str, + path: SubstitutionPath, + context_vars: ContextVars, + strict_undefined: bool, + errors: ErrList | None, ) -> Any: + """Expand ``$var``, ``${var}``, and Jinja expressions in a string. + + Works in two phases: + + 1. **Simple substitution** — scan for ``$name`` / ``${name}`` tokens + and replace them with the value from *context_vars*. If the token + spans the entire string, return the raw value (preserving type). + 2. **Jinja evaluation** — if the result still contains Jinja syntax + (e.g. ``${a * b}``), render it through the Jinja engine with the + full *context_vars* as template variables. + + Returns the expanded value (may be a non-string type) or the + original *value* unchanged if there is nothing to substitute. + """ if "$" not in value: return value orig_value = value - i = 0 - while True: - m: Match[str] = cv.VARIABLE_PROG.search(value, i) - if not m: - # No more variable substitutions found. See if the remainder looks like a jinja template - value = _expand_jinja(value, orig_value, path, jinja, ignore_missing) - break - - i, j = m.span(0) + # Phase 1: Replace $var and ${var} references + search_pos = 0 + while (m := cv.VARIABLE_PROG.search(value, search_pos)) is not None: + match_start, match_end = m.span(0) name: str = m.group(1) if name.startswith("{") and name.endswith("}"): name = name[1:-1] - if name not in substitutions: - if not ignore_missing and "password" not in path: - _LOGGER.warning( - "Found '%s' (see %s) which looks like a substitution, but '%s' was " - "not declared", - orig_value, - "->".join(str(x) for x in path), - name, - ) - i = j + sub = _resolve_var(name, context_vars) + if sub is Missing: + _handle_undefined( + err=UndefinedError(f"'{name}' is undefined"), + path=path, + value=value, + strict_undefined=strict_undefined, + errors=errors, + ) + search_pos = match_end continue - sub: Any = substitutions[name] - - if i == 0 and j == len(value): - # The variable spans the whole expression, e.g., "${varName}". Return its resolved value directly - # to conserve its type. + if match_start == 0 and match_end == len(value): + # The variable spans the whole expression, e.g., "${varName}". + # Return its resolved value directly to conserve its type. value = sub break - tail = value[j:] - value = value[:i] + str(sub) - i = len(value) + tail = value[match_end:] + value = value[:match_start] + str(sub) + search_pos = len(value) value += tail + # Phase 2: Evaluate any remaining jinja expressions (e.g., "${a * b}") + if isinstance(value, str) and has_jinja(value): + try: + value = jinja.expand(value, context_vars) + except UndefinedError as err: + _handle_undefined( + err=err, + path=path, + value=value, + strict_undefined=strict_undefined, + errors=errors, + ) + except JinjaError as err: + raise cv.Invalid( + f"{err.error_name()} Error evaluating jinja expression" + f" '{value}': {str(err.parent())}." + f"\nEvaluation stack: (most recent evaluation last)" + f"\n{err.stack_trace_str()}" + f"\nRelevant context:\n{err.context_trace_str()}" + f"\nSee {'->'.join(str(x) for x in path)}", + path, + ) + else: + if isinstance(orig_value, ESPHomeDataBase): + value = _restore_data_base(value, orig_value) + # orig_value can also already be a lambda with esp_range info, and only # a plain string is sent in orig_value if isinstance(orig_value, ESPHomeDataBase): @@ -157,83 +207,221 @@ def _expand_substitutions( return value +def _push_context( + local_vars: dict[str, Any], + parent_context: ContextVars, + errors: ErrList | None = None, +) -> tuple[ContextVars, dict[str, Any]]: + """Resolve local_vars and layer them on top of parent_context. + + Returns ``(child_context, resolved_vars)`` where *child_context* is a + new :class:`ChainMap` whose front map is *resolved_vars* (an + :class:`OrderedDict` of successfully-resolved variables). + + Variables may reference each other (e.g. ``b: ${a + 1}``). + Dependencies are resolved recursively via a *resolver* callback + that Jinja invokes on cache-miss. If vars are already in + dependency order, the loop iterates exactly once per variable. + + The ChainMap stack used during resolution is:: + + resolver_context → resolved_vars → parent maps … + ↑ ↑ + holds Resolver filled as vars + callback are resolved + """ + # Vars still waiting to be resolved — popped one-by-one by resolve(). + unresolved_vars = local_vars.copy() + # Accumulates resolved values in dependency order; becomes the front + # map of the returned child context so later lookups find them first. + resolved_vars = OrderedDict() + # The context callees will search: resolved_vars (initially empty) + # shadowing whatever the parent already provides. + context_vars = parent_context.new_child(resolved_vars) + + # Vars that failed resolution (missing or circular references). + # Maps name → (original_value, cause_error) for deferred warnings. + unresolvables: dict[str, tuple[Any, UndefinedError]] = {} + + # One extra child layer so the Resolver callback lives in its own + # map and doesn't pollute resolved_vars. + resolver_context = context_vars.new_child() + + def resolve(key: str) -> Any: + """Resolve a variable, recursively resolving any dependencies it references.""" + value = unresolved_vars.pop(key, Missing) + if value is Missing: + return Missing + try: + value = _try_substitute(value, resolver_context) + except UndefinedError as err: + unresolvables[key] = (value, err) + return Missing + resolved_vars[key] = value + return value + + # Set up the resolver for use during substitution + resolver_context[Resolver] = resolve + + # Resolve all variables, recursively resolving dependencies as needed. + # Each call to resolve() resolves that variable and any variables it depends on. + while unresolved_vars: + resolve(next(iter(unresolved_vars))) + + for name, (value, cause) in unresolvables.items(): + resolved_vars[name] = value + if errors is not None: + _handle_undefined( + err=UndefinedError( + f"Could not resolve substitution variable '{name}': {cause}" + ), + path=["substitutions", name], + value=value, + strict_undefined=False, + errors=errors, + ) + + return context_vars, resolved_vars + + +def push_context( + config_node: Any, + parent_context: ContextVars, + errors: ErrList | None = None, +) -> ContextVars: + """Returns the context vars this config node must be evaluated with.""" + if isinstance(config_node, ConfigContext): + return _push_context(config_node.vars, parent_context, errors)[0] + + # This node does not define any vars itself, so just return parent context + return parent_context + + def _substitute_item( - substitutions: dict, item: Any, - path: list[int | str], - jinja: Jinja, - ignore_missing: bool, + path: SubstitutionPath, + parent_context: ContextVars, + strict_undefined: bool, + errors: ErrList | None = None, ) -> Any | None: - if isinstance(item, ESPLiteralValue): - return None # do not substitute inside literal blocks - if isinstance(item, list): - for i, it in enumerate(item): - sub = _substitute_item(substitutions, it, path + [i], jinja, ignore_missing) - if sub is not None: - item[i] = sub - elif isinstance(item, dict): - replace_keys = [] - for k, v in item.items(): - if path or k != CONF_SUBSTITUTIONS: - sub = _substitute_item( - substitutions, k, path + [k], jinja, ignore_missing - ) + """Recursively substitute variables in a config item. + + Walks dicts, lists, strings, Lambdas, Extend, and Remove nodes, + replacing variable references with values from context_vars. + Mutates containers in-place; returns a replacement value for + strings/scalars, or None if the item was unchanged. + """ + + def _walk(item: Any, path: SubstitutionPath, parent_ctx: ContextVars) -> Any | None: + if isinstance(item, ESPLiteralValue): + return None # do not substitute inside literal blocks + + ctx = push_context(item, parent_ctx, errors) + + if isinstance(item, list): + for idx, it in enumerate(item): + sub = _walk(it, path + [idx], ctx) if sub is not None: - replace_keys.append((k, sub)) - sub = _substitute_item(substitutions, v, path + [k], jinja, ignore_missing) - if sub is not None: - item[k] = sub - for old, new in replace_keys: - if str(new) == str(old): - item[new] = item[old] - else: - item[new] = merge_config(item.get(old), item.get(new)) - del item[old] - elif isinstance(item, str): - sub = _expand_substitutions(substitutions, item, path, jinja, ignore_missing) - if isinstance(sub, JinjaStr) or sub != item: - return sub - elif isinstance(item, (core.Lambda, Extend, Remove)): - sub = _expand_substitutions( - substitutions, item.value, path, jinja, ignore_missing + item[idx] = sub + elif isinstance(item, dict): + replace_keys: list[tuple[str, Any]] = [] + for k, v in item.items(): + if path or k != CONF_SUBSTITUTIONS: + sub = _walk(k, path + [k], ctx) + if sub is not None: + replace_keys.append((k, sub)) + sub = _walk(v, path + [k], ctx) + if sub is not None: + item[k] = sub + for old, new in replace_keys: + if str(new) == str(old): + item[new] = item[old] + else: + item[new] = merge_config(item.get(new), item.get(old)) + del item[old] + elif isinstance(item, str): + sub = _expand_substitutions(item, path, ctx, strict_undefined, errors) + if not isinstance(sub, str) or sub != item: + return sub + elif isinstance(item, (core.Lambda, Extend, Remove)) and item.value: + sub = _expand_substitutions(item.value, path, ctx, strict_undefined, errors) + if sub != item.value: + item.value = sub + return None + + return _walk(item, path, parent_context) + + +def substitute_context_vars(node: Any, context_vars: dict[str, Any]) -> None: + """Eagerly substitute context vars into a config node in-place. + + Undefined variables are silently ignored — this is used before + the main substitution pass when not all variables are visible yet. + """ + _substitute_item(node, [], ContextVars(context_vars), strict_undefined=False) + + +def _warn_unresolved_variables(errors: ErrList) -> None: + """Log warnings for unresolved substitution variables, skipping password fields.""" + for err, path, expression in errors: + if "password" in path: + continue + location: str = "->".join(str(x) for x in path) + if isinstance(expression, ESPHomeDataBase) and expression.esp_range is not None: + location += f" in {str(expression.esp_range.start_mark)}" + + _LOGGER.warning( + "The string '%s' looks like an expression," + " but could not resolve all the variables: %s (see %s)", + expression, + err.message, + location, ) - if sub != item: - item.value = sub - return None def do_substitution_pass( - config: dict, command_line_substitutions: dict, ignore_missing: bool = False -) -> None: - if CONF_SUBSTITUTIONS not in config and not command_line_substitutions: - return + config: OrderedDict, command_line_substitutions: dict[str, Any] | None = None +) -> OrderedDict: + """Run the substitution pass over the entire config. - # Merge substitutions in config, overriding with substitutions coming from command line: + Extracts the ``substitutions:`` block, merges in any command-line + overrides, resolves inter-variable dependencies, then walks the + config tree replacing all ``$var`` / ``${expr}`` references. + Returns the (mutated) config dict with resolved substitutions + restored at the front. + """ + # Extract substitutions from config, overriding with substitutions coming from command line: # Use merge_dicts_ordered to preserve OrderedDict type for move_to_end() - substitutions = merge_dicts_ordered( - config.get(CONF_SUBSTITUTIONS, {}), command_line_substitutions or {} - ) - with cv.prepend_path("substitutions"): + substitutions = config.pop(CONF_SUBSTITUTIONS, {}) + with cv.prepend_path(CONF_SUBSTITUTIONS): if not isinstance(substitutions, dict): raise cv.Invalid( f"Substitutions must be a key to value mapping, got {type(substitutions)}" ) + substitutions = merge_dicts_ordered( + substitutions, command_line_substitutions or {} + ) - replace_keys = [] - for key, value in substitutions.items(): + replace_keys: list[tuple[str, str]] = [] + for key in substitutions: with cv.prepend_path(key): sub = validate_substitution_key(key) if sub != key: replace_keys.append((key, sub)) - substitutions[key] = value for old, new in replace_keys: substitutions[new] = substitutions[old] del substitutions[old] - config[CONF_SUBSTITUTIONS] = substitutions - # Move substitutions to the first place to replace substitutions in them correctly - config.move_to_end(CONF_SUBSTITUTIONS, False) + errors: ErrList = [] # Collect undefined errors during substitution + parent_context, substitutions = _push_context(substitutions, ContextVars(), errors) - # Create a Jinja environment that will consider substitutions in scope: - jinja = Jinja(substitutions) - _substitute_item(substitutions, config, [], jinja, ignore_missing) + _substitute_item(config, [], parent_context, False, errors) + + if errors: + _warn_unresolved_variables(errors) + + # Restore substitutions to front of dict for readability + if substitutions: + config[CONF_SUBSTITUTIONS] = substitutions + config.move_to_end(CONF_SUBSTITUTIONS, last=False) + return config diff --git a/esphome/components/substitutions/jinja.py b/esphome/components/substitutions/jinja.py index fb9f843da2..37e9fa4d2d 100644 --- a/esphome/components/substitutions/jinja.py +++ b/esphome/components/substitutions/jinja.py @@ -1,7 +1,6 @@ from ast import literal_eval -from collections.abc import Iterator +from collections.abc import Iterator, Mapping from itertools import chain, islice -import logging import math import re from types import GeneratorType @@ -9,16 +8,17 @@ from typing import Any import jinja2 as jinja from jinja2.nativetypes import NativeCodeGenerator, NativeTemplate - -from esphome.yaml_util import ESPLiteralValue +from jinja2.runtime import missing as Missing TemplateError = jinja.TemplateError TemplateSyntaxError = jinja.TemplateSyntaxError TemplateRuntimeError = jinja.TemplateRuntimeError UndefinedError = jinja.UndefinedError Undefined = jinja.Undefined +# Sentinel key for resolver callback in ContextVars. +# Dots are invalid in substitution names so this can never collide with user keys. +Resolver = ".resolver" -_LOGGER = logging.getLogger(__name__) DETECT_JINJA = r"(\$\{)" detect_jinja_re = re.compile( @@ -52,33 +52,6 @@ SAFE_GLOBALS = { } -class JinjaStr(str): - """ - Wraps a string containing an unresolved Jinja expression, - storing the variables visible to it when it failed to resolve. - For example, an expression inside a package, `${ A * B }` may fail - to resolve at package parsing time if `A` is a local package var - but `B` is a substitution defined in the root yaml. - Therefore, we store the value of `A` as an upvalue bound - to the original string so we may be able to resolve `${ A * B }` - later in the main substitutions pass. - """ - - Undefined = object() - - def __new__(cls, value: str, upvalues=None): - if isinstance(value, JinjaStr): - base = str(value) - merged = {**value.upvalues, **(upvalues or {})} - else: - base = value - merged = dict(upvalues or {}) - obj = super().__new__(cls, base) - obj.upvalues = merged - obj.result = JinjaStr.Undefined - return obj - - class JinjaError(Exception): def __init__(self, context_trace: dict, expr: str): self.context_trace = context_trace @@ -106,9 +79,13 @@ class JinjaError(Exception): class TrackerContext(jinja.runtime.Context): def resolve_or_missing(self, key): val = super().resolve_or_missing(key) - if isinstance(val, JinjaStr): - self.environment.context_trace[key] = val - val, _ = self.environment.expand(val) + if val is Missing: + # Variable not in the template context — check if a resolver callback + # was registered (by _push_context) to lazily resolve dependencies + # between substitution variables in the same block. + resolver = super().resolve_or_missing(Resolver) + if resolver is not Missing: + val = resolver(key) self.environment.context_trace[key] = val return val @@ -160,15 +137,13 @@ def _concat_nodes_override(values: Iterator[Any]) -> Any: class Jinja(jinja.Environment): - """ - Wraps a Jinja environment - """ + """Jinja environment configured for ESPHome substitution expressions.""" # jinja environment customization overrides code_generator_class = NativeCodeGenerator concat = staticmethod(_concat_nodes_override) - def __init__(self, context_vars: dict): + def __init__(self) -> None: super().__init__( trim_blocks=True, lstrip_blocks=True, @@ -183,49 +158,25 @@ class Jinja(jinja.Environment): self.context_class = TrackerContext self.add_extension("jinja2.ext.do") self.context_trace = {} - self.context_vars = {**context_vars} - for k, v in self.context_vars.items(): - if isinstance(v, ESPLiteralValue): - continue - if isinstance(v, str) and not isinstance(v, JinjaStr) and has_jinja(v): - self.context_vars[k] = JinjaStr(v, self.context_vars) - self.globals = { - **self.globals, - **self.context_vars, - **SAFE_GLOBALS, - } + self.globals = {**self.globals, **SAFE_GLOBALS} - def expand(self, content_str: str | JinjaStr) -> Any: + def expand(self, content_str: str, context_vars: Mapping[str, Any]) -> Any: """ Renders a string that may contain Jinja expressions or statements Returns the resulting value if all variables and expressions could be resolved. - Otherwise, it returns a tagged (JinjaStr) string that captures variables - in scope (upvalues), like a closure for later evaluation. """ result = None - override_vars = {} - if isinstance(content_str, JinjaStr): - if content_str.result is not JinjaStr.Undefined: - return content_str.result, None - # If `value` is already a JinjaStr, it means we are trying to evaluate it again - # in a parent pass. - # Hopefully, all required variables are visible now. - override_vars = content_str.upvalues old_trace = self.context_trace self.context_trace = {} try: template = self.from_string(content_str) - result = template.render(override_vars) + result = template.render(context_vars) if isinstance(result, Undefined): - print("" + result) # force a UndefinedError exception - except (TemplateSyntaxError, UndefinedError) as err: - # `content_str` contains a Jinja expression that refers to a variable that is undefined - # in this scope. Perhaps it refers to a root substitution that is not visible yet. - # Therefore, return `content_str` as a JinjaStr, which contains the variables - # that are actually visible to it at this point to postpone evaluation. - return JinjaStr(content_str, {**self.context_vars, **override_vars}), err + str(result) # force a UndefinedError exception + except UndefinedError as err: + raise err except JinjaError as err: err.context_trace = {**self.context_trace, **err.context_trace} err.eval_stack.append(content_str) @@ -242,10 +193,7 @@ class Jinja(jinja.Environment): finally: self.context_trace = old_trace - if isinstance(content_str, JinjaStr): - content_str.result = result - - return result, None + return result class JinjaTemplate(NativeTemplate): diff --git a/esphome/config.py b/esphome/config.py index 6f6ad4886b..b80aaf3700 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -12,7 +12,8 @@ from typing import Any import voluptuous as vol from esphome import core, loader, pins, yaml_util -from esphome.config_helpers import Extend, Remove, merge_config, merge_dicts_ordered +from esphome.components.substitutions import do_substitution_pass +from esphome.config_helpers import Extend, Remove, merge_config import esphome.config_validation as cv from esphome.const import ( CONF_ESPHOME, @@ -974,7 +975,7 @@ class PinUseValidationCheck(ConfigValidationStep): def validate_config( config: dict[str, Any], - command_line_substitutions: dict[str, Any], + command_line_substitutions: dict[str, Any] | None, skip_external_update: bool = False, ) -> Config: result = Config() @@ -994,21 +995,15 @@ def validate_config( result.add_error(err) return result - CORE.raw_config = config - # 1. Load substitutions if CONF_SUBSTITUTIONS in config or command_line_substitutions: - from esphome.components import substitutions - - result[CONF_SUBSTITUTIONS] = merge_dicts_ordered( - config.get(CONF_SUBSTITUTIONS) or {}, command_line_substitutions - ) result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS) - try: - substitutions.do_substitution_pass(config, command_line_substitutions) - except vol.Invalid as err: - result.add_error(err) - return result + try: + config = do_substitution_pass(config, command_line_substitutions) + except vol.Invalid as err: + CORE.raw_config = config + result.add_error(err) + return result # 1.1. Merge packages if CONF_PACKAGES in config: @@ -1016,6 +1011,9 @@ def validate_config( config = merge_packages(config) + # Remove substitutions from config during validation to prevent + # re-substitution. Re-added to result at the end of this function. + substitutions = config.pop(CONF_SUBSTITUTIONS, None) CORE.raw_config = config # 1.2. Resolve !extend and !remove and check for REPLACEME @@ -1089,6 +1087,10 @@ def validate_config( result.run_validation_steps() + if substitutions is not None: + result[CONF_SUBSTITUTIONS] = substitutions + result.move_to_end(CONF_SUBSTITUTIONS, last=False) + return result diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index d0eab4e44e..e001316a22 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -325,9 +325,7 @@ class ESPHomeLoaderMixin: return val @_add_data_ref - def construct_include( - self, node: yaml.Node - ) -> dict[str, Any] | OrderedDict[str, Any]: + def construct_include(self, node: yaml.Node) -> Any: from esphome.const import CONF_VARS def extract_file_vars(node): @@ -344,9 +342,7 @@ class ESPHomeLoaderMixin: file, vars = node.value, None result = self.yaml_loader(self._rel_path(file)) - if not vars: - vars = {} - return substitute_vars(result, vars) + return add_context(result, vars) @_add_data_ref def construct_include_dir_list(self, node: yaml.Node) -> list[dict[str, Any]]: @@ -495,39 +491,6 @@ def parse_yaml( ) -def substitute_vars(config, vars): - from esphome.components import substitutions - from esphome.const import CONF_SUBSTITUTIONS - - org_subs = None - result = config - if not isinstance(config, dict): - # when the included yaml contains a list or a scalar - # wrap it into an OrderedDict because do_substitution_pass expects it - result = OrderedDict([("yaml", config)]) - elif CONF_SUBSTITUTIONS in result: - org_subs = result.pop(CONF_SUBSTITUTIONS) - - defaults = {} - if CONF_DEFAULTS in result: - defaults = result.pop(CONF_DEFAULTS) - - result[CONF_SUBSTITUTIONS] = vars - for k, v in defaults.items(): - if k not in result[CONF_SUBSTITUTIONS]: - result[CONF_SUBSTITUTIONS][k] = v - - # Ignore missing vars that refer to the top level substitutions - substitutions.do_substitution_pass(result, None, ignore_missing=True) - result.pop(CONF_SUBSTITUTIONS) - - if not isinstance(config, dict): - result = result["yaml"] # unwrap the result - elif org_subs: - result[CONF_SUBSTITUTIONS] = org_subs - return result - - def _load_yaml_internal_with_type( loader_type: type[ESPHomeLoader] | type[ESPHomePurePythonLoader], fname: Path, diff --git a/tests/component_tests/packages/test_packages.py b/tests/component_tests/packages/test_packages.py index 22fb2c4e32..60dc0dccda 100644 --- a/tests/component_tests/packages/test_packages.py +++ b/tests/component_tests/packages/test_packages.py @@ -6,6 +6,7 @@ from unittest.mock import MagicMock, patch import pytest from esphome.components.packages import CONFIG_SCHEMA, do_packages_pass, merge_packages +from esphome.components.substitutions import do_substitution_pass import esphome.config as config_module from esphome.config import resolve_extend_remove from esphome.config_helpers import Extend, Remove @@ -71,6 +72,7 @@ def fixture_basic_esphome(): def packages_pass(config): """Wrapper around packages_pass that also resolves Extend and Remove.""" config = do_packages_pass(config) + config = do_substitution_pass(config) config = merge_packages(config) resolve_extend_remove(config) return config diff --git a/tests/unit_tests/fixtures/substitutions/00-simple_var.approved.yaml b/tests/unit_tests/fixtures/substitutions/00-simple_var.approved.yaml index 9ed9b99c49..87f0e3fa21 100644 --- a/tests/unit_tests/fixtures/substitutions/00-simple_var.approved.yaml +++ b/tests/unit_tests/fixtures/substitutions/00-simple_var.approved.yaml @@ -38,3 +38,20 @@ test_list: - '{ 79, 82 }' - a: 15 should be 15, overridden from command line b: 20 should stay as 20, not overridden + - aa: + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + bb: + - 7 + - 8 + - 9 + - aa: + x: 1 + y: 3 + z: 4 + bb: + w: 5 diff --git a/tests/unit_tests/fixtures/substitutions/00-simple_var.input.yaml b/tests/unit_tests/fixtures/substitutions/00-simple_var.input.yaml index 64701c03dd..d70372f280 100644 --- a/tests/unit_tests/fixtures/substitutions/00-simple_var.input.yaml +++ b/tests/unit_tests/fixtures/substitutions/00-simple_var.input.yaml @@ -44,3 +44,13 @@ test_list: - '{ ${position.x}, ${position.y} }' - a: ${a} should be 15, overridden from command line b: ${b} should stay as 20, not overridden + + # Test merging lists when substituted keys resolve to an existing key + - ${ "aa" }: [1, 2, 3] + ${ "a" + "a" }: [4, 5, 6] + ${ "bb" }: [7, 8, 9] + + # Test merging dicts when substituted keys resolve to an existing key + - ${ "aa" }: {"x": 1, "y": 2} + ${ "a" + "a" }: {"y": 3, "z": 4} + ${ "bb" }: {"w": 5} diff --git a/tests/unit_tests/fixtures/substitutions/02-expressions.approved.yaml b/tests/unit_tests/fixtures/substitutions/02-expressions.approved.yaml index 1a51fc44cf..b8c76fbf52 100644 --- a/tests/unit_tests/fixtures/substitutions/02-expressions.approved.yaml +++ b/tests/unit_tests/fixtures/substitutions/02-expressions.approved.yaml @@ -9,6 +9,11 @@ substitutions: numberOne: 1 var1: 79 double_width: 14 + double_height: 16 + y: ${x} + x: ${y} + b: 79 + c: 80 test_list: - The area is 56 - 56 @@ -27,3 +32,4 @@ test_list: - chr(97) = a - len([1,2,3]) = 3 - width = 7, double_width = 14 + - a = ${a} diff --git a/tests/unit_tests/fixtures/substitutions/02-expressions.input.yaml b/tests/unit_tests/fixtures/substitutions/02-expressions.input.yaml index 4612f581b5..9593867f49 100644 --- a/tests/unit_tests/fixtures/substitutions/02-expressions.input.yaml +++ b/tests/unit_tests/fixtures/substitutions/02-expressions.input.yaml @@ -1,4 +1,7 @@ substitutions: + y: ${x} # Circular reference, expect to pass unresolved. + x: ${y} # Circular reference, expect to pass unresolved. + double_height: ${height * 2} width: 7 height: 8 enabled: true @@ -9,6 +12,8 @@ substitutions: numberOne: 1 var1: 79 double_width: ${width * 2} + c: ${b+1} + b: ${undefined_variable | default(79) } test_list: - "The area is ${width * height}" @@ -25,3 +30,4 @@ test_list: - chr(97) = ${ chr(97) } - len([1,2,3]) = ${ len([1,2,3]) } - width = ${width}, double_width = ${double_width} + - a = ${a} diff --git a/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml b/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml new file mode 100644 index 0000000000..867889b7bc --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml @@ -0,0 +1,46 @@ +fancy_component: &id001 + - id: component9 + value: 9 +some_component: + - id: component1 + value: 1 + - id: component2 + value: 2 + - id: component3 + value: 3 + - id: component4 + value: 4 + - id: component5 + value: 79 + power: 200 + - id: component6 + value: 6 + - id: component7 + value: 7 +switch: &id002 + - platform: gpio + id: switch1 + pin: 12 + - platform: gpio + id: switch2 + pin: 13 +display: + - platform: ili9xxx + dimensions: + width: 100 + height: 480 +substitutions: + extended_component: component5 + package_options: + alternative_package: + alternative_component: + - id: component8 + value: 8 + fancy_package: + substitutions: + fancy_subst: 42 + fancy_component: *id001 + pin: 12 + some_switches: *id002 + package_selection: fancy_package + fancy_subst: 42 diff --git a/tests/unit_tests/fixtures/substitutions/07-package_merging.input.yaml b/tests/unit_tests/fixtures/substitutions/07-package_merging.input.yaml new file mode 100644 index 0000000000..cc7b841aba --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/07-package_merging.input.yaml @@ -0,0 +1,63 @@ +substitutions: + package_options: + alternative_package: + alternative_component: + - id: component8 + value: 8 + fancy_package: + substitutions: + fancy_subst: 42 + fancy_component: + - id: component9 + value: 9 + + pin: 12 + some_switches: + - platform: gpio + id: switch1 + pin: ${pin} + - platform: gpio + id: switch2 + pin: ${pin+1} + + package_selection: fancy_package + +packages: + - ${ package_options[package_selection] } + - some_component: + - id: component1 + value: 1 + - some_component: + - id: component2 + value: 2 + - switch: ${ some_switches } + - packages: + package_with_defaults: !include + file: display.yaml + vars: + native_width: 100 + high_dpi: false + my_package: + packages: + - packages: + special_package: + substitutions: + extended_component: component5 + some_component: + - id: component3 + value: 3 + some_component: + - id: component4 + value: 4 + - id: !extend ${ extended_component } + power: 200 + value: 79 + some_component: + - id: component5 + value: 5 + +some_component: + - id: component6 + value: 6 + - id: component7 + value: 7 diff --git a/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.approved.yaml b/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.approved.yaml new file mode 100644 index 0000000000..4abaf4471d --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.approved.yaml @@ -0,0 +1,5 @@ +values: + - var1: $var1 + - a: 10 + - b: B-default + - c: The value of C is 79 diff --git a/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.input.yaml b/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.input.yaml new file mode 100644 index 0000000000..91eb0e9a3f --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/09-include_vars_without_substs.input.yaml @@ -0,0 +1,7 @@ +# Test that include_vars with vars works even when there are no substitutions key defined. +packages: + - !include + file: inc1.yaml + vars: + a: 10 + c: 79 diff --git a/tests/unit_tests/test_substitutions.py b/tests/unit_tests/test_substitutions.py index 1d8cb7631d..db46a27dfb 100644 --- a/tests/unit_tests/test_substitutions.py +++ b/tests/unit_tests/test_substitutions.py @@ -10,9 +10,10 @@ from esphome import config as config_module, yaml_util from esphome.components import substitutions from esphome.components.packages import do_packages_pass, merge_packages from esphome.config import resolve_extend_remove -from esphome.config_helpers import merge_config +from esphome.config_helpers import Extend, merge_config +import esphome.config_validation as cv from esphome.const import CONF_SUBSTITUTIONS -from esphome.core import CORE +from esphome.core import CORE, Lambda from esphome.util import OrderedDict _LOGGER = logging.getLogger(__name__) @@ -144,7 +145,7 @@ def test_substitutions_fixtures( config = do_packages_pass(config) - substitutions.do_substitution_pass(config, command_line_substitutions) + config = substitutions.do_substitution_pass(config, command_line_substitutions) config = merge_packages(config) @@ -206,7 +207,7 @@ def test_substitutions_with_command_line_maintains_ordered_dict() -> None: command_line_subs = {"var2": "override", "var3": "new_value"} # Call do_substitution_pass with command line substitutions - substitutions.do_substitution_pass(config, command_line_subs) + config = substitutions.do_substitution_pass(config, command_line_subs) # Verify that config is still an OrderedDict assert isinstance(config, OrderedDict), "Config should remain an OrderedDict" @@ -234,7 +235,7 @@ def test_substitutions_without_command_line_maintains_ordered_dict() -> None: config["other_key"] = "other_value" # Call without command line substitutions - substitutions.do_substitution_pass(config, None) + config = substitutions.do_substitution_pass(config, None) # Verify that config is still an OrderedDict assert isinstance(config, OrderedDict), "Config should remain an OrderedDict" @@ -268,7 +269,7 @@ def test_substitutions_after_merge_config_maintains_ordered_dict() -> None: ) # Now try to run substitution pass on the merged config - substitutions.do_substitution_pass(merged_config, None) + merged_config = substitutions.do_substitution_pass(merged_config, None) # Should not raise AttributeError assert isinstance(merged_config, OrderedDict), ( @@ -279,7 +280,7 @@ def test_substitutions_after_merge_config_maintains_ordered_dict() -> None: def test_validate_config_with_command_line_substitutions_maintains_ordered_dict( - tmp_path, + tmp_path: Path, ) -> None: """Test that validate_config preserves OrderedDict when merging command-line substitutions. @@ -288,7 +289,7 @@ def test_validate_config_with_command_line_substitutions_maintains_ordered_dict( """ # Create a minimal valid config test_config = OrderedDict() - test_config["esphome"] = {"name": "test_device", "platform": "ESP32"} + test_config["esphome"] = {"name": "test_device"} test_config[CONF_SUBSTITUTIONS] = OrderedDict({"var1": "value1", "var2": "value2"}) test_config["esp32"] = {"board": "esp32dev"} @@ -314,17 +315,11 @@ def test_validate_config_with_command_line_substitutions_maintains_ordered_dict( assert result[CONF_SUBSTITUTIONS]["var3"] == "new_value" -def test_validate_config_without_command_line_substitutions_maintains_ordered_dict( - tmp_path, -) -> None: - """Test that validate_config preserves OrderedDict without command-line substitutions. - - This tests the code path in config.py where result[CONF_SUBSTITUTIONS] is set - using merge_dicts_ordered() when command_line_substitutions is None. - """ +def _get_test_minimal_valid_config(tmp_path: Path) -> OrderedDict: + """Helper to create a minimal valid config for testing.""" # Create a minimal valid config test_config = OrderedDict() - test_config["esphome"] = {"name": "test_device", "platform": "ESP32"} + test_config["esphome"] = {"name": "test_device"} test_config[CONF_SUBSTITUTIONS] = OrderedDict({"var1": "value1", "var2": "value2"}) test_config["esp32"] = {"board": "esp32dev"} @@ -332,6 +327,19 @@ def test_validate_config_without_command_line_substitutions_maintains_ordered_di test_yaml = tmp_path / "test.yaml" test_yaml.write_text("# test config") CORE.config_path = test_yaml + return test_config + + +def test_validate_config_without_command_line_substitutions_maintains_ordered_dict( + tmp_path: Path, +) -> None: + """Test that validate_config preserves OrderedDict without command-line substitutions. + + This tests the code path in config.py where result[CONF_SUBSTITUTIONS] is set + using merge_dicts_ordered() when command_line_substitutions is None. + """ + + test_config = _get_test_minimal_valid_config(tmp_path) # Call validate_config without command line substitutions result = config_module.validate_config(test_config, None) @@ -384,3 +392,205 @@ def test_merge_config_preserves_ordered_dict() -> None: assert not isinstance(result, OrderedDict), ( "dict + dict should not return OrderedDict" ) + + +def test_substitution_pass_error_gets_captured( + monkeypatch: pytest.MonkeyPatch, tmp_path: Path +) -> None: + """vol.Invalid from do_substitution_pass is captured by validate_config.""" + + # Patch the target: in config_module.do_substitution_pass (NOT where it's defined) + def fake_do_substitution_pass(*args, **kwargs): + raise cv.Invalid("Error in do_substitutions_pass!!") + + monkeypatch.setattr( + config_module, "do_substitution_pass", fake_do_substitution_pass + ) + + # Prepare minimal config + no CLI substitutions + config = _get_test_minimal_valid_config(tmp_path) + + # Call the function under test + result = config_module.validate_config(config, None) + + # Now assert that add_error was called with the vol.Invalid + + assert "Error in do_substitutions_pass!!" in str(result.get_error_for_path([])) + + +@pytest.mark.parametrize( + "value", ["", " ", "1foo", "9VAR", "0abc", "$1foo", "$9VAR", "$0abc"] +) +def test_validate_substitution_key_empty_raises(value: str) -> None: + """Empty (or all-whitespace) substitution keys are rejected.""" + with pytest.raises(cv.Invalid): + substitutions.validate_substitution_key(value) + + +@pytest.mark.parametrize( + "input_value, expected_output", + [ + ("$FOO_bar9", "FOO_bar9"), # Valid key with leading '$' + ("Foo_bar9", "Foo_bar9"), # Normal valid key + ], +) +def test_validate_substitution_key_valid( + input_value: str, expected_output: str +) -> None: + """Valid substitution keys are accepted with optional leading '$'.""" + result = substitutions.validate_substitution_key(input_value) + assert result == expected_output + + +def test_circular_dependency_warnings( + caplog: pytest.LogCaptureFixture, +) -> None: + """Circular substitution references produce warnings naming the cause.""" + config = OrderedDict( + { + CONF_SUBSTITUTIONS: OrderedDict({"x": "${y}", "y": "${x}"}), + "key": "value", + } + ) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert "Could not resolve substitution variable 'x'" in caplog.text + assert "'y' is undefined" in caplog.text + assert "Could not resolve substitution variable 'y'" in caplog.text + assert "'x' is undefined" in caplog.text + # Verify path includes location + assert "substitutions->x" in caplog.text + assert "substitutions->y" in caplog.text + + +def test_missing_dependency_warning( + caplog: pytest.LogCaptureFixture, +) -> None: + """A substitution referencing an undefined variable warns with the cause.""" + config = OrderedDict( + { + CONF_SUBSTITUTIONS: OrderedDict({"a": "${missing}"}), + "key": "value", + } + ) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert "Could not resolve substitution variable 'a'" in caplog.text + assert "'missing' is undefined" in caplog.text + assert "substitutions->a" in caplog.text + + +def test_undefined_variable_warning( + caplog: pytest.LogCaptureFixture, +) -> None: + """A reference to an undefined variable in config values produces a warning.""" + config = OrderedDict( + { + "key": "${undefined_var}", + } + ) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert "'undefined_var' is undefined" in caplog.text + + +def test_password_field_warnings_suppressed( + caplog: pytest.LogCaptureFixture, +) -> None: + """Undefined variables in password fields should not produce warnings.""" + config = OrderedDict( + { + "password": "${undefined_var}", + } + ) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert caplog.text == "" + + +def test_config_context_unresolvable_warns( + caplog: pytest.LogCaptureFixture, +) -> None: + """Unresolvable vars in a ConfigContext produce warnings via push_context.""" + inner = OrderedDict({"key": "${a}"}) + yaml_util.add_context(inner, {"a": "${undefined}"}) + config = OrderedDict({"items": [inner]}) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert "Could not resolve substitution variable 'a'" in caplog.text + assert "'undefined' is undefined" in caplog.text + + +def test_non_string_substitution_value_warning( + caplog: pytest.LogCaptureFixture, +) -> None: + """Undefined vars in non-string contexts (e.g. dict keys) produce warnings.""" + config = OrderedDict( + { + "items": {"${undefined_key}": "value"}, + } + ) + with caplog.at_level(logging.WARNING): + substitutions.do_substitution_pass(config) + + assert "'undefined_key' is undefined" in caplog.text + + +def test_lambda_substitution() -> None: + """Substitution inside a Lambda value should be expanded.""" + lam = Lambda("return ${var};") + config = OrderedDict( + { + CONF_SUBSTITUTIONS: OrderedDict({"var": "42"}), + "lambda": lam, + } + ) + substitutions.do_substitution_pass(config) + assert lam.value == "return 42;" + + +def test_lambda_no_substitution_unchanged() -> None: + """A Lambda with no variable references should not be mutated.""" + lam = Lambda("return 1;") + original_value = lam.value + config = OrderedDict( + { + CONF_SUBSTITUTIONS: OrderedDict({"var": "42"}), + "lambda": lam, + } + ) + substitutions.do_substitution_pass(config) + assert lam.value is original_value + + +def test_extend_substitution() -> None: + """Substitution inside an Extend value should be expanded.""" + ext = Extend("${component_id}") + config = OrderedDict( + { + CONF_SUBSTITUTIONS: OrderedDict({"component_id": "my_sensor"}), + "sensor": ext, + } + ) + substitutions.do_substitution_pass(config) + assert ext.value == "my_sensor" + + +def test_do_substitution_pass_substitutions_must_be_mapping_from_config() -> None: + """Non-mapping substitutions raises cv.Invalid.""" + config = OrderedDict( + { + CONF_SUBSTITUTIONS: ["not", "a", "mapping"], + "other": "value", + } + ) + + with pytest.raises( + cv.Invalid, match="Substitutions must be a key to value mapping" + ): + substitutions.do_substitution_pass(config) diff --git a/tests/unit_tests/test_yaml_util.py b/tests/unit_tests/test_yaml_util.py index adb7658bfd..35a4bc3707 100644 --- a/tests/unit_tests/test_yaml_util.py +++ b/tests/unit_tests/test_yaml_util.py @@ -25,7 +25,7 @@ def test_include_with_vars(fixture_path: Path) -> None: yaml_file = fixture_path / "yaml_util" / "includetest.yaml" actual = yaml_util.load_yaml(yaml_file) - substitutions.do_substitution_pass(actual, None) + actual = substitutions.do_substitution_pass(actual, None) assert actual["esphome"]["name"] == "original" assert actual["esphome"]["libraries"][0] == "Wire" assert actual["esp8266"]["board"] == "nodemcu" From e6a73cab8f1e090244d63d4d63766a570a45ec62 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 24 Mar 2026 09:04:53 +1000 Subject: [PATCH 1673/2030] [number] Add sensor platform (#15125) --- esphome/components/number/sensor/__init__.py | 25 +++++++++++++++++++ .../number/sensor/number_sensor.cpp | 16 ++++++++++++ .../components/number/sensor/number_sensor.h | 19 ++++++++++++++ tests/components/number/common.yaml | 13 ++++++++++ tests/components/number/test.esp32-idf.yaml | 2 ++ tests/components/number/test.esp8266-ard.yaml | 2 ++ 6 files changed, 77 insertions(+) create mode 100644 esphome/components/number/sensor/__init__.py create mode 100644 esphome/components/number/sensor/number_sensor.cpp create mode 100644 esphome/components/number/sensor/number_sensor.h create mode 100644 tests/components/number/common.yaml create mode 100644 tests/components/number/test.esp32-idf.yaml create mode 100644 tests/components/number/test.esp8266-ard.yaml diff --git a/esphome/components/number/sensor/__init__.py b/esphome/components/number/sensor/__init__.py new file mode 100644 index 0000000000..0d4b580d7e --- /dev/null +++ b/esphome/components/number/sensor/__init__.py @@ -0,0 +1,25 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import CONF_SOURCE_ID + +from .. import Number, number_ns + +NumberSensor = number_ns.class_("NumberSensor", sensor.Sensor, cg.Component) + + +CONFIG_SCHEMA = ( + sensor.sensor_schema(NumberSensor) + .extend( + { + cv.Required(CONF_SOURCE_ID): cv.use_id(Number), + } + ) + .extend(cv.COMPONENT_SCHEMA) +) + + +async def to_code(config): + source = await cg.get_variable(config[CONF_SOURCE_ID]) + var = await sensor.new_sensor(config, source) + await cg.register_component(var, config) diff --git a/esphome/components/number/sensor/number_sensor.cpp b/esphome/components/number/sensor/number_sensor.cpp new file mode 100644 index 0000000000..227202622a --- /dev/null +++ b/esphome/components/number/sensor/number_sensor.cpp @@ -0,0 +1,16 @@ +#include "number_sensor.h" +#include "esphome/core/log.h" + +namespace esphome::number { + +static const char *const TAG = "number.sensor"; + +void NumberSensor::setup() { + this->source_->add_on_state_callback([this](float value) { this->publish_state(value); }); + if (this->source_->has_state()) + this->publish_state(this->source_->state); +} + +void NumberSensor::dump_config() { LOG_SENSOR("", "Number Sensor", this); } + +} // namespace esphome::number diff --git a/esphome/components/number/sensor/number_sensor.h b/esphome/components/number/sensor/number_sensor.h new file mode 100644 index 0000000000..2d6825a298 --- /dev/null +++ b/esphome/components/number/sensor/number_sensor.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../number.h" +#include "esphome/core/component.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome::number { + +class NumberSensor : public sensor::Sensor, public Component { + public: + explicit NumberSensor(Number *source) : source_(source) {} + void setup() override; + void dump_config() override; + + protected: + Number *source_; +}; + +} // namespace esphome::number diff --git a/tests/components/number/common.yaml b/tests/components/number/common.yaml new file mode 100644 index 0000000000..c17c2dd5f8 --- /dev/null +++ b/tests/components/number/common.yaml @@ -0,0 +1,13 @@ +number: + - platform: template + name: "Test Number" + id: test_number + optimistic: true + min_value: 0 + max_value: 100 + step: 1 + +sensor: + - platform: number + name: "Test Number Value" + source_id: test_number diff --git a/tests/components/number/test.esp32-idf.yaml b/tests/components/number/test.esp32-idf.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/number/test.esp32-idf.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml diff --git a/tests/components/number/test.esp8266-ard.yaml b/tests/components/number/test.esp8266-ard.yaml new file mode 100644 index 0000000000..25cb37a0b4 --- /dev/null +++ b/tests/components/number/test.esp8266-ard.yaml @@ -0,0 +1,2 @@ +packages: + common: !include common.yaml From 0fb31726f69b304581caec41614a080774feda8a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:39:29 -1000 Subject: [PATCH 1674/2030] [esp32] Add sram1_as_iram option and bootloader version detection (#14874) --- esphome/components/esp32/__init__.py | 19 ++++++++ esphome/core/application.cpp | 50 ++++++++++++++++++---- esphome/core/defines.h | 1 + tests/components/esp32/test.esp32-idf.yaml | 1 + 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index f85f13fe73..1ecc270fd1 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -97,6 +97,7 @@ CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision" CONF_RELEASE = "release" +CONF_SRAM1_AS_IRAM = "sram1_as_iram" CONF_SUBTYPE = "subtype" ARDUINO_FRAMEWORK_NAME = "framework-arduinoespressif32" @@ -884,6 +885,13 @@ def final_validate(config): path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_MINIMUM_CHIP_REVISION], ) ) + if config[CONF_VARIANT] != VARIANT_ESP32 and advanced[CONF_SRAM1_AS_IRAM]: + errs.append( + cv.Invalid( + f"'{CONF_SRAM1_AS_IRAM}' is only supported on {VARIANT_ESP32}", + path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_SRAM1_AS_IRAM], + ) + ) if ( config[CONF_VARIANT] != VARIANT_ESP32P4 and config.get(CONF_ENGINEERING_SAMPLE) is not None @@ -1131,6 +1139,7 @@ FRAMEWORK_SCHEMA = cv.Schema( cv.Optional(CONF_MINIMUM_CHIP_REVISION): cv.one_of( *ESP32_CHIP_REVISIONS ), + cv.Optional(CONF_SRAM1_AS_IRAM, default=False): cv.boolean, # DHCP server is needed for WiFi AP mode. When WiFi component is used, # it will handle disabling DHCP server when AP is not configured. # Default to false (disabled) when WiFi is not used. @@ -1655,6 +1664,16 @@ async def to_code(config): for rev, flag in ESP32_CHIP_REVISIONS.items(): add_idf_sdkconfig_option(flag, rev == min_rev) cg.add_define("USE_ESP32_MIN_CHIP_REVISION_SET") + + # Use SRAM1 region as IRAM on ESP32 (original) variant + # This provides an additional 40KB of IRAM by using SRAM1 memory that was previously + # reserved for bootloader DRAM. Requires a bootloader from ESP-IDF v5.1 or later. + # WARNING: If the device has an old bootloader (pre-v5.1), the app will fail to boot. + # A USB flash will update the bootloader automatically. OTA updates do not. + # See: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/performance/ram-usage.html + if variant == VARIANT_ESP32 and conf[CONF_ADVANCED][CONF_SRAM1_AS_IRAM]: + add_idf_sdkconfig_option("CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM", True) + cg.add_define("USE_ESP32_SRAM1_AS_IRAM") add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False) add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True) add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv") diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index c020a8ed58..ce15aed1e2 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -9,6 +9,8 @@ #endif #ifdef USE_ESP32 #include <esp_chip_info.h> +#include <esp_ota_ops.h> +#include <esp_bootloader_desc.h> #endif #ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" @@ -167,19 +169,49 @@ void Application::process_dump_config_() { esp_chip_info(&chip_info); ESP_LOGI(TAG, "ESP32 Chip: %s rev%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100, chip_info.revision % 100, chip_info.cores); -#if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET) - // Suggest optimization for chips that don't need the PSRAM cache workaround - if (chip_info.revision >= 300) { -#ifdef USE_PSRAM - ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to save ~10KB IRAM", chip_info.revision / 100, - chip_info.revision % 100); -#else - ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to reduce binary size", chip_info.revision / 100, - chip_info.revision % 100); +#if defined(USE_ESP32_VARIANT_ESP32) && (!defined(USE_ESP32_MIN_CHIP_REVISION_SET) || !defined(USE_ESP32_SRAM1_AS_IRAM)) + static const char *const ESP32_ADVANCED_PATH = "under esp32 > framework > advanced"; #endif +#if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET) + { + // Suggest optimization for chips that don't need the PSRAM cache workaround + if (chip_info.revision >= 300) { +#ifdef USE_PSRAM + ESP_LOGW(TAG, "Chip rev >= 3.0 detected. Set minimum_chip_revision: \"%d.%d\" %s to save ~10KB IRAM", + chip_info.revision / 100, chip_info.revision % 100, ESP32_ADVANCED_PATH); +#else + ESP_LOGW(TAG, "Chip rev >= 3.0 detected. Set minimum_chip_revision: \"%d.%d\" %s to reduce binary size", + chip_info.revision / 100, chip_info.revision % 100, ESP32_ADVANCED_PATH); +#endif + } } #endif + { + // esp_bootloader_desc_t is available in ESP-IDF >= 5.2; if readable the bootloader is modern. + // + // Design decision: We intentionally do NOT mention sram1_as_iram when the bootloader is too old. + // Enabling sram1_as_iram with an old bootloader causes a hard brick (device fails to boot, + // requires USB reflash to recover). Users don't always read warnings carefully, so we only + // suggest the option once we've confirmed the bootloader can handle it. In practice this + // means a user with an old bootloader may need to flash twice: once via USB to update the + // bootloader (they'll see the suggestion on next boot), then OTA with sram1_as_iram: true. + // Two flashes is a better outcome than a bricked device. + esp_bootloader_desc_t boot_desc; + if (esp_ota_get_bootloader_description(nullptr, &boot_desc) != ESP_OK) { +#ifdef USE_ESP32_VARIANT_ESP32 + ESP_LOGW(TAG, "Bootloader too old for OTA rollback and SRAM1 as IRAM (+40KB). " + "Flash via USB once to update the bootloader"); +#else + ESP_LOGW(TAG, "Bootloader too old for OTA rollback. Flash via USB once to update the bootloader"); #endif + } +#if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_SRAM1_AS_IRAM) + else { + ESP_LOGW(TAG, "Bootloader supports SRAM1 as IRAM (+40KB). Set sram1_as_iram: true %s", ESP32_ADVANCED_PATH); + } +#endif + } +#endif // USE_ESP32 } this->components_[this->dump_config_at_]->call_dump_config_(); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index f437e30a95..996818c2e6 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -202,6 +202,7 @@ #define USE_ESPHOME_TASK_LOG_BUFFER #define USE_OTA_ROLLBACK #define USE_ESP32_MIN_CHIP_REVISION_SET +#define USE_ESP32_SRAM1_AS_IRAM #define USE_BLUETOOTH_PROXY #define BLUETOOTH_PROXY_MAX_CONNECTIONS 3 diff --git a/tests/components/esp32/test.esp32-idf.yaml b/tests/components/esp32/test.esp32-idf.yaml index da85aa3b0f..b999f23e1c 100644 --- a/tests/components/esp32/test.esp32-idf.yaml +++ b/tests/components/esp32/test.esp32-idf.yaml @@ -19,6 +19,7 @@ esp32: disable_mbedtls_pkcs7: true disable_regi2c_in_iram: true disable_fatfs: true + sram1_as_iram: true wifi: ssid: MySSID From a0d0516b22e7ea8cd29c718ef510e9d33d3de5a7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:40:41 -1000 Subject: [PATCH 1675/2030] [benchmark] Add noise handshake benchmark (#15039) --- .../components/api/bench_noise_encrypt.cpp | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/tests/benchmarks/components/api/bench_noise_encrypt.cpp b/tests/benchmarks/components/api/bench_noise_encrypt.cpp index 223e6ada0d..9ef928192c 100644 --- a/tests/benchmarks/components/api/bench_noise_encrypt.cpp +++ b/tests/benchmarks/components/api/bench_noise_encrypt.cpp @@ -172,6 +172,135 @@ BENCHMARK(NoiseDecrypt_MediumMessage); static void NoiseDecrypt_LargeMessage(benchmark::State &state) { noise_decrypt_bench(state, 1024); } BENCHMARK(NoiseDecrypt_LargeMessage); +// --- Full Noise_NNpsk0 handshake benchmark --- +// Measures the complete handshake between initiator and responder: +// - Create handshake states for both sides +// - Set PSK and prologue +// - Exchange messages (initiator write -> responder read -> responder write -> initiator read) +// - Split to get cipher states +// This is dominated by Curve25519 DH operations (expensive on ESP8266). +// No inner iterations — each handshake is already expensive enough. + +static void NoiseHandshake_Full(benchmark::State &state) { + // Matching ESPHome's protocol: Noise_NNpsk0_25519_ChaChaPoly_SHA256 + NoiseProtocolId nid; + memset(&nid, 0, sizeof(nid)); + nid.pattern_id = NOISE_PATTERN_NN; + nid.cipher_id = NOISE_CIPHER_CHACHAPOLY; + nid.dh_id = NOISE_DH_CURVE25519; + nid.prefix_id = NOISE_PREFIX_STANDARD; + nid.hybrid_id = NOISE_DH_NONE; + nid.hash_id = NOISE_HASH_SHA256; + nid.modifier_ids[0] = NOISE_MODIFIER_PSK0; + + // Dummy PSK (32 bytes) and prologue matching production setup + static constexpr uint8_t PSK[32] = {0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, + 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB}; + static constexpr uint8_t PROLOGUE[] = "NoESPHome"; + + // Message buffer for handshake exchange (max handshake message ~96 bytes) + uint8_t msg_buf[128]; + + for (auto _ : state) { + NoiseHandshakeState *initiator = nullptr; + NoiseHandshakeState *responder = nullptr; + NoiseCipherState *init_send = nullptr, *init_recv = nullptr; + NoiseCipherState *resp_send = nullptr, *resp_recv = nullptr; + int err; + + // Create both handshake states + err = noise_handshakestate_new_by_id(&initiator, &nid, NOISE_ROLE_INITIATOR); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Failed to create initiator"); + return; + } + err = noise_handshakestate_new_by_id(&responder, &nid, NOISE_ROLE_RESPONDER); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Failed to create responder"); + noise_handshakestate_free(initiator); + return; + } + + // Set PSK and prologue on both sides + noise_handshakestate_set_pre_shared_key(initiator, PSK, sizeof(PSK)); + noise_handshakestate_set_pre_shared_key(responder, PSK, sizeof(PSK)); + noise_handshakestate_set_prologue(initiator, PROLOGUE, sizeof(PROLOGUE) - 1); + noise_handshakestate_set_prologue(responder, PROLOGUE, sizeof(PROLOGUE) - 1); + + noise_handshakestate_start(initiator); + noise_handshakestate_start(responder); + + // Message 1: Initiator -> Responder + NoiseBuffer write_buf, read_buf; + noise_buffer_set_output(write_buf, msg_buf, sizeof(msg_buf)); + err = noise_handshakestate_write_message(initiator, &write_buf, nullptr); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Initiator write_message failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + return; + } + + noise_buffer_set_input(read_buf, msg_buf, write_buf.size); + err = noise_handshakestate_read_message(responder, &read_buf, nullptr); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Responder read_message failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + return; + } + + // Message 2: Responder -> Initiator + noise_buffer_set_output(write_buf, msg_buf, sizeof(msg_buf)); + err = noise_handshakestate_write_message(responder, &write_buf, nullptr); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Responder write_message failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + return; + } + + noise_buffer_set_input(read_buf, msg_buf, write_buf.size); + err = noise_handshakestate_read_message(initiator, &read_buf, nullptr); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Initiator read_message failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + return; + } + + // Split to get cipher states + err = noise_handshakestate_split(initiator, &init_send, &init_recv); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Initiator split failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + return; + } + err = noise_handshakestate_split(responder, &resp_send, &resp_recv); + if (err != NOISE_ERROR_NONE) { + state.SkipWithError("Responder split failed"); + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + noise_cipherstate_free(init_send); + noise_cipherstate_free(init_recv); + return; + } + + benchmark::DoNotOptimize(init_send); + + // Cleanup + noise_handshakestate_free(initiator); + noise_handshakestate_free(responder); + noise_cipherstate_free(init_send); + noise_cipherstate_free(init_recv); + noise_cipherstate_free(resp_send); + noise_cipherstate_free(resp_recv); + } +} +BENCHMARK(NoiseHandshake_Full); + } // namespace esphome::api::benchmarks #endif // USE_API_NOISE From 382de7ca906b2b584b1c6188105a50523182f2f1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:40:53 -1000 Subject: [PATCH 1676/2030] [api] Store dump strings in PROGMEM to save RAM on ESP8266 (#14982) --- esphome/components/api/api_pb2.h | 274 +-- esphome/components/api/api_pb2_dump.cpp | 2425 ++++++++++---------- esphome/components/api/api_pb2_service.cpp | 4 +- esphome/components/api/api_pb2_service.h | 2 +- esphome/components/api/proto.h | 20 +- script/api_protobuf/api_protobuf.py | 96 +- 6 files changed, 1443 insertions(+), 1378 deletions(-) diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 86289a28d6..16586e6e9a 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -388,7 +388,7 @@ class HelloRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 1; static constexpr uint8_t ESTIMATED_SIZE = 17; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "hello_request"; } + const LogString *message_name() const override { return LOG_STR("hello_request"); } #endif StringRef client_info{}; uint32_t api_version_major{0}; @@ -406,7 +406,7 @@ class HelloResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 2; static constexpr uint8_t ESTIMATED_SIZE = 26; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "hello_response"; } + const LogString *message_name() const override { return LOG_STR("hello_response"); } #endif uint32_t api_version_major{0}; uint32_t api_version_minor{0}; @@ -425,7 +425,7 @@ class DisconnectRequest final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 5; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "disconnect_request"; } + const LogString *message_name() const override { return LOG_STR("disconnect_request"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -438,7 +438,7 @@ class DisconnectResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 6; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "disconnect_response"; } + const LogString *message_name() const override { return LOG_STR("disconnect_response"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -451,7 +451,7 @@ class PingRequest final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 7; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "ping_request"; } + const LogString *message_name() const override { return LOG_STR("ping_request"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -464,7 +464,7 @@ class PingResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 8; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "ping_response"; } + const LogString *message_name() const override { return LOG_STR("ping_response"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -520,7 +520,7 @@ class DeviceInfoResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 10; static constexpr uint16_t ESTIMATED_SIZE = 309; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "device_info_response"; } + const LogString *message_name() const override { return LOG_STR("device_info_response"); } #endif StringRef name{}; StringRef mac_address{}; @@ -587,7 +587,7 @@ class ListEntitiesDoneResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 19; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_done_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_done_response"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -601,7 +601,7 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 12; static constexpr uint8_t ESTIMATED_SIZE = 51; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_binary_sensor_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_binary_sensor_response"); } #endif StringRef device_class{}; bool is_status_binary_sensor{false}; @@ -618,7 +618,7 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 21; static constexpr uint8_t ESTIMATED_SIZE = 13; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "binary_sensor_state_response"; } + const LogString *message_name() const override { return LOG_STR("binary_sensor_state_response"); } #endif bool state{false}; bool missing_state{false}; @@ -637,7 +637,7 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 13; static constexpr uint8_t ESTIMATED_SIZE = 57; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_cover_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_cover_response"); } #endif bool assumed_state{false}; bool supports_position{false}; @@ -657,7 +657,7 @@ class CoverStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 22; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "cover_state_response"; } + const LogString *message_name() const override { return LOG_STR("cover_state_response"); } #endif float position{0.0f}; float tilt{0.0f}; @@ -675,7 +675,7 @@ class CoverCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 30; static constexpr uint8_t ESTIMATED_SIZE = 25; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "cover_command_request"; } + const LogString *message_name() const override { return LOG_STR("cover_command_request"); } #endif bool has_position{false}; float position{0.0f}; @@ -697,7 +697,7 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 14; static constexpr uint8_t ESTIMATED_SIZE = 68; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_fan_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_fan_response"); } #endif bool supports_oscillation{false}; bool supports_speed{false}; @@ -717,7 +717,7 @@ class FanStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 23; static constexpr uint8_t ESTIMATED_SIZE = 28; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "fan_state_response"; } + const LogString *message_name() const override { return LOG_STR("fan_state_response"); } #endif bool state{false}; bool oscillating{false}; @@ -737,7 +737,7 @@ class FanCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 31; static constexpr uint8_t ESTIMATED_SIZE = 38; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "fan_command_request"; } + const LogString *message_name() const override { return LOG_STR("fan_command_request"); } #endif bool has_state{false}; bool state{false}; @@ -765,7 +765,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 15; static constexpr uint8_t ESTIMATED_SIZE = 73; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_light_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_light_response"); } #endif const light::ColorModeMask *supported_color_modes{}; float min_mireds{0.0f}; @@ -784,7 +784,7 @@ class LightStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 24; static constexpr uint8_t ESTIMATED_SIZE = 67; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "light_state_response"; } + const LogString *message_name() const override { return LOG_STR("light_state_response"); } #endif bool state{false}; float brightness{0.0f}; @@ -811,7 +811,7 @@ class LightCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 32; static constexpr uint8_t ESTIMATED_SIZE = 112; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "light_command_request"; } + const LogString *message_name() const override { return LOG_STR("light_command_request"); } #endif bool has_state{false}; bool state{false}; @@ -855,7 +855,7 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 16; static constexpr uint8_t ESTIMATED_SIZE = 66; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_sensor_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_sensor_response"); } #endif StringRef unit_of_measurement{}; int32_t accuracy_decimals{0}; @@ -875,7 +875,7 @@ class SensorStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 25; static constexpr uint8_t ESTIMATED_SIZE = 16; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "sensor_state_response"; } + const LogString *message_name() const override { return LOG_STR("sensor_state_response"); } #endif float state{0.0f}; bool missing_state{false}; @@ -894,7 +894,7 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 17; static constexpr uint8_t ESTIMATED_SIZE = 51; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_switch_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_switch_response"); } #endif bool assumed_state{false}; StringRef device_class{}; @@ -911,7 +911,7 @@ class SwitchStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 26; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "switch_state_response"; } + const LogString *message_name() const override { return LOG_STR("switch_state_response"); } #endif bool state{false}; void encode(ProtoWriteBuffer &buffer) const; @@ -927,7 +927,7 @@ class SwitchCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 33; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "switch_command_request"; } + const LogString *message_name() const override { return LOG_STR("switch_command_request"); } #endif bool state{false}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -945,7 +945,7 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 18; static constexpr uint8_t ESTIMATED_SIZE = 49; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_text_sensor_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_text_sensor_response"); } #endif StringRef device_class{}; void encode(ProtoWriteBuffer &buffer) const; @@ -961,7 +961,7 @@ class TextSensorStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 27; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "text_sensor_state_response"; } + const LogString *message_name() const override { return LOG_STR("text_sensor_state_response"); } #endif StringRef state{}; bool missing_state{false}; @@ -979,7 +979,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 28; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_logs_request"; } + const LogString *message_name() const override { return LOG_STR("subscribe_logs_request"); } #endif enums::LogLevel level{}; bool dump_config{false}; @@ -995,7 +995,7 @@ class SubscribeLogsResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 29; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_logs_response"; } + const LogString *message_name() const override { return LOG_STR("subscribe_logs_response"); } #endif enums::LogLevel level{}; const uint8_t *message_ptr_{nullptr}; @@ -1018,7 +1018,7 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 124; static constexpr uint8_t ESTIMATED_SIZE = 19; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "noise_encryption_set_key_request"; } + const LogString *message_name() const override { return LOG_STR("noise_encryption_set_key_request"); } #endif const uint8_t *key{nullptr}; uint16_t key_len{0}; @@ -1034,7 +1034,7 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 125; static constexpr uint8_t ESTIMATED_SIZE = 2; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "noise_encryption_set_key_response"; } + const LogString *message_name() const override { return LOG_STR("noise_encryption_set_key_response"); } #endif bool success{false}; void encode(ProtoWriteBuffer &buffer) const; @@ -1064,7 +1064,7 @@ class HomeassistantActionRequest final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 35; static constexpr uint8_t ESTIMATED_SIZE = 128; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "homeassistant_action_request"; } + const LogString *message_name() const override { return LOG_STR("homeassistant_action_request"); } #endif StringRef service{}; FixedVector<HomeassistantServiceMap> data{}; @@ -1095,7 +1095,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 130; static constexpr uint8_t ESTIMATED_SIZE = 34; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "homeassistant_action_response"; } + const LogString *message_name() const override { return LOG_STR("homeassistant_action_response"); } #endif uint32_t call_id{0}; bool success{false}; @@ -1119,7 +1119,7 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 39; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_home_assistant_state_response"; } + const LogString *message_name() const override { return LOG_STR("subscribe_home_assistant_state_response"); } #endif StringRef entity_id{}; StringRef attribute{}; @@ -1137,7 +1137,7 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 40; static constexpr uint8_t ESTIMATED_SIZE = 27; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "home_assistant_state_response"; } + const LogString *message_name() const override { return LOG_STR("home_assistant_state_response"); } #endif StringRef entity_id{}; StringRef state{}; @@ -1155,7 +1155,7 @@ class GetTimeRequest final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 36; static constexpr uint8_t ESTIMATED_SIZE = 0; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "get_time_request"; } + const LogString *message_name() const override { return LOG_STR("get_time_request"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1197,7 +1197,7 @@ class GetTimeResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 37; static constexpr uint8_t ESTIMATED_SIZE = 31; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "get_time_response"; } + const LogString *message_name() const override { return LOG_STR("get_time_response"); } #endif uint32_t epoch_seconds{0}; StringRef timezone{}; @@ -1228,7 +1228,7 @@ class ListEntitiesServicesResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 41; static constexpr uint8_t ESTIMATED_SIZE = 50; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_services_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_services_response"); } #endif StringRef name{}; uint32_t key{0}; @@ -1268,7 +1268,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 42; static constexpr uint8_t ESTIMATED_SIZE = 45; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "execute_service_request"; } + const LogString *message_name() const override { return LOG_STR("execute_service_request"); } #endif uint32_t key{0}; FixedVector<ExecuteServiceArgument> args{}; @@ -1295,7 +1295,7 @@ class ExecuteServiceResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 131; static constexpr uint8_t ESTIMATED_SIZE = 34; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "execute_service_response"; } + const LogString *message_name() const override { return LOG_STR("execute_service_response"); } #endif uint32_t call_id{0}; bool success{false}; @@ -1319,7 +1319,7 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 43; static constexpr uint8_t ESTIMATED_SIZE = 40; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_camera_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_camera_response"); } #endif void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; @@ -1334,7 +1334,7 @@ class CameraImageResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 44; static constexpr uint8_t ESTIMATED_SIZE = 30; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "camera_image_response"; } + const LogString *message_name() const override { return LOG_STR("camera_image_response"); } #endif const uint8_t *data_ptr_{nullptr}; size_t data_len_{0}; @@ -1356,7 +1356,7 @@ class CameraImageRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 45; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "camera_image_request"; } + const LogString *message_name() const override { return LOG_STR("camera_image_request"); } #endif bool single{false}; bool stream{false}; @@ -1374,7 +1374,7 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 46; static constexpr uint8_t ESTIMATED_SIZE = 150; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_climate_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_climate_response"); } #endif bool supports_current_temperature{false}; bool supports_two_point_target_temperature{false}; @@ -1407,7 +1407,7 @@ class ClimateStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 47; static constexpr uint8_t ESTIMATED_SIZE = 68; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "climate_state_response"; } + const LogString *message_name() const override { return LOG_STR("climate_state_response"); } #endif enums::ClimateMode mode{}; float current_temperature{0.0f}; @@ -1435,7 +1435,7 @@ class ClimateCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 48; static constexpr uint8_t ESTIMATED_SIZE = 84; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "climate_command_request"; } + const LogString *message_name() const override { return LOG_STR("climate_command_request"); } #endif bool has_mode{false}; enums::ClimateMode mode{}; @@ -1473,7 +1473,7 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 132; static constexpr uint8_t ESTIMATED_SIZE = 63; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_water_heater_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_water_heater_response"); } #endif float min_temperature{0.0f}; float max_temperature{0.0f}; @@ -1493,7 +1493,7 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 133; static constexpr uint8_t ESTIMATED_SIZE = 35; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "water_heater_state_response"; } + const LogString *message_name() const override { return LOG_STR("water_heater_state_response"); } #endif float current_temperature{0.0f}; float target_temperature{0.0f}; @@ -1514,7 +1514,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 134; static constexpr uint8_t ESTIMATED_SIZE = 34; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "water_heater_command_request"; } + const LogString *message_name() const override { return LOG_STR("water_heater_command_request"); } #endif uint32_t has_fields{0}; enums::WaterHeaterMode mode{}; @@ -1537,7 +1537,7 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 49; static constexpr uint8_t ESTIMATED_SIZE = 75; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_number_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_number_response"); } #endif float min_value{0.0f}; float max_value{0.0f}; @@ -1558,7 +1558,7 @@ class NumberStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 50; static constexpr uint8_t ESTIMATED_SIZE = 16; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "number_state_response"; } + const LogString *message_name() const override { return LOG_STR("number_state_response"); } #endif float state{0.0f}; bool missing_state{false}; @@ -1575,7 +1575,7 @@ class NumberCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 51; static constexpr uint8_t ESTIMATED_SIZE = 14; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "number_command_request"; } + const LogString *message_name() const override { return LOG_STR("number_command_request"); } #endif float state{0.0f}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -1593,7 +1593,7 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 52; static constexpr uint8_t ESTIMATED_SIZE = 58; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_select_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_select_response"); } #endif const FixedVector<const char *> *options{}; void encode(ProtoWriteBuffer &buffer) const; @@ -1609,7 +1609,7 @@ class SelectStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 53; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "select_state_response"; } + const LogString *message_name() const override { return LOG_STR("select_state_response"); } #endif StringRef state{}; bool missing_state{false}; @@ -1626,7 +1626,7 @@ class SelectCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 54; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "select_command_request"; } + const LogString *message_name() const override { return LOG_STR("select_command_request"); } #endif StringRef state{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -1645,7 +1645,7 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 55; static constexpr uint8_t ESTIMATED_SIZE = 62; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_siren_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_siren_response"); } #endif const FixedVector<const char *> *tones{}; bool supports_duration{false}; @@ -1663,7 +1663,7 @@ class SirenStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 56; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "siren_state_response"; } + const LogString *message_name() const override { return LOG_STR("siren_state_response"); } #endif bool state{false}; void encode(ProtoWriteBuffer &buffer) const; @@ -1679,7 +1679,7 @@ class SirenCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 57; static constexpr uint8_t ESTIMATED_SIZE = 37; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "siren_command_request"; } + const LogString *message_name() const override { return LOG_STR("siren_command_request"); } #endif bool has_state{false}; bool state{false}; @@ -1705,7 +1705,7 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 58; static constexpr uint8_t ESTIMATED_SIZE = 55; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_lock_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_lock_response"); } #endif bool assumed_state{false}; bool supports_open{false}; @@ -1724,7 +1724,7 @@ class LockStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 59; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "lock_state_response"; } + const LogString *message_name() const override { return LOG_STR("lock_state_response"); } #endif enums::LockState state{}; void encode(ProtoWriteBuffer &buffer) const; @@ -1740,7 +1740,7 @@ class LockCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 60; static constexpr uint8_t ESTIMATED_SIZE = 22; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "lock_command_request"; } + const LogString *message_name() const override { return LOG_STR("lock_command_request"); } #endif enums::LockCommand command{}; bool has_code{false}; @@ -1761,7 +1761,7 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 61; static constexpr uint8_t ESTIMATED_SIZE = 49; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_button_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_button_response"); } #endif StringRef device_class{}; void encode(ProtoWriteBuffer &buffer) const; @@ -1777,7 +1777,7 @@ class ButtonCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 62; static constexpr uint8_t ESTIMATED_SIZE = 9; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "button_command_request"; } + const LogString *message_name() const override { return LOG_STR("button_command_request"); } #endif #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1809,7 +1809,7 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 63; static constexpr uint8_t ESTIMATED_SIZE = 80; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_media_player_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_media_player_response"); } #endif bool supports_pause{false}; std::vector<MediaPlayerSupportedFormat> supported_formats{}; @@ -1827,7 +1827,7 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 64; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "media_player_state_response"; } + const LogString *message_name() const override { return LOG_STR("media_player_state_response"); } #endif enums::MediaPlayerState state{}; float volume{0.0f}; @@ -1845,7 +1845,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 65; static constexpr uint8_t ESTIMATED_SIZE = 35; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "media_player_command_request"; } + const LogString *message_name() const override { return LOG_STR("media_player_command_request"); } #endif bool has_command{false}; enums::MediaPlayerCommand command{}; @@ -1871,7 +1871,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes static constexpr uint8_t MESSAGE_TYPE = 66; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_bluetooth_le_advertisements_request"; } + const LogString *message_name() const override { return LOG_STR("subscribe_bluetooth_le_advertisements_request"); } #endif uint32_t flags{0}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -1901,7 +1901,7 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 93; static constexpr uint8_t ESTIMATED_SIZE = 136; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_le_raw_advertisements_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_le_raw_advertisements_response"); } #endif std::array<BluetoothLERawAdvertisement, BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE> advertisements{}; uint16_t advertisements_len{0}; @@ -1918,7 +1918,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 68; static constexpr uint8_t ESTIMATED_SIZE = 12; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_device_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_device_request"); } #endif uint64_t address{0}; enums::BluetoothDeviceRequestType request_type{}; @@ -1936,7 +1936,7 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 69; static constexpr uint8_t ESTIMATED_SIZE = 14; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_device_connection_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_device_connection_response"); } #endif uint64_t address{0}; bool connected{false}; @@ -1955,7 +1955,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 70; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_get_services_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_request"); } #endif uint64_t address{0}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2012,7 +2012,7 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 71; static constexpr uint8_t ESTIMATED_SIZE = 38; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_get_services_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_response"); } #endif uint64_t address{0}; std::vector<BluetoothGATTService> services{}; @@ -2029,7 +2029,7 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 72; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_get_services_done_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_done_response"); } #endif uint64_t address{0}; void encode(ProtoWriteBuffer &buffer) const; @@ -2045,7 +2045,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 73; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_read_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_read_request"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2061,7 +2061,7 @@ class BluetoothGATTReadResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 74; static constexpr uint8_t ESTIMATED_SIZE = 27; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_read_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_read_response"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2084,7 +2084,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 75; static constexpr uint8_t ESTIMATED_SIZE = 29; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_write_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_write_request"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2104,7 +2104,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 76; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_read_descriptor_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_read_descriptor_request"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2120,7 +2120,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 77; static constexpr uint8_t ESTIMATED_SIZE = 27; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_write_descriptor_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_write_descriptor_request"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2139,7 +2139,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 78; static constexpr uint8_t ESTIMATED_SIZE = 10; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_notify_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_notify_request"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2156,7 +2156,7 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 79; static constexpr uint8_t ESTIMATED_SIZE = 27; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_notify_data_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_notify_data_response"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2179,7 +2179,7 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 81; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_connections_free_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_connections_free_response"); } #endif uint32_t free{0}; uint32_t limit{0}; @@ -2197,7 +2197,7 @@ class BluetoothGATTErrorResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 82; static constexpr uint8_t ESTIMATED_SIZE = 12; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_error_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_error_response"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2215,7 +2215,7 @@ class BluetoothGATTWriteResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 83; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_write_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_write_response"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2232,7 +2232,7 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 84; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_gatt_notify_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_notify_response"); } #endif uint64_t address{0}; uint32_t handle{0}; @@ -2249,7 +2249,7 @@ class BluetoothDevicePairingResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 85; static constexpr uint8_t ESTIMATED_SIZE = 10; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_device_pairing_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_device_pairing_response"); } #endif uint64_t address{0}; bool paired{false}; @@ -2267,7 +2267,7 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 86; static constexpr uint8_t ESTIMATED_SIZE = 10; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_device_unpairing_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_device_unpairing_response"); } #endif uint64_t address{0}; bool success{false}; @@ -2285,7 +2285,7 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 88; static constexpr uint8_t ESTIMATED_SIZE = 10; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_device_clear_cache_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_device_clear_cache_response"); } #endif uint64_t address{0}; bool success{false}; @@ -2303,7 +2303,7 @@ class BluetoothScannerStateResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 126; static constexpr uint8_t ESTIMATED_SIZE = 6; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_scanner_state_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_scanner_state_response"); } #endif enums::BluetoothScannerState state{}; enums::BluetoothScannerMode mode{}; @@ -2321,7 +2321,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 127; static constexpr uint8_t ESTIMATED_SIZE = 2; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_scanner_set_mode_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_scanner_set_mode_request"); } #endif enums::BluetoothScannerMode mode{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2338,7 +2338,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 89; static constexpr uint8_t ESTIMATED_SIZE = 6; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "subscribe_voice_assistant_request"; } + const LogString *message_name() const override { return LOG_STR("subscribe_voice_assistant_request"); } #endif bool subscribe{false}; uint32_t flags{0}; @@ -2367,7 +2367,7 @@ class VoiceAssistantRequest final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 90; static constexpr uint8_t ESTIMATED_SIZE = 41; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_request"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_request"); } #endif bool start{false}; StringRef conversation_id{}; @@ -2387,7 +2387,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 91; static constexpr uint8_t ESTIMATED_SIZE = 6; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_response"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_response"); } #endif uint32_t port{0}; bool error{false}; @@ -2414,7 +2414,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 92; static constexpr uint8_t ESTIMATED_SIZE = 36; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_event_response"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_event_response"); } #endif enums::VoiceAssistantEvent event_type{}; std::vector<VoiceAssistantEventData> data{}; @@ -2431,7 +2431,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 106; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_audio"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_audio"); } #endif const uint8_t *data{nullptr}; uint16_t data_len{0}; @@ -2451,7 +2451,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 115; static constexpr uint8_t ESTIMATED_SIZE = 30; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_timer_event_response"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_timer_event_response"); } #endif enums::VoiceAssistantTimerEvent event_type{}; StringRef timer_id{}; @@ -2472,7 +2472,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 119; static constexpr uint8_t ESTIMATED_SIZE = 29; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_announce_request"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_announce_request"); } #endif StringRef media_id{}; StringRef text{}; @@ -2491,7 +2491,7 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 120; static constexpr uint8_t ESTIMATED_SIZE = 2; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_announce_finished"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_announce_finished"); } #endif bool success{false}; void encode(ProtoWriteBuffer &buffer) const; @@ -2537,7 +2537,7 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 121; static constexpr uint8_t ESTIMATED_SIZE = 34; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_configuration_request"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_configuration_request"); } #endif std::vector<VoiceAssistantExternalWakeWord> external_wake_words{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2552,7 +2552,7 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 122; static constexpr uint8_t ESTIMATED_SIZE = 56; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_configuration_response"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_configuration_response"); } #endif std::vector<VoiceAssistantWakeWord> available_wake_words{}; const std::vector<std::string> *active_wake_words{}; @@ -2570,7 +2570,7 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 123; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "voice_assistant_set_configuration"; } + const LogString *message_name() const override { return LOG_STR("voice_assistant_set_configuration"); } #endif std::vector<std::string> active_wake_words{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2587,7 +2587,7 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess static constexpr uint8_t MESSAGE_TYPE = 94; static constexpr uint8_t ESTIMATED_SIZE = 48; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_alarm_control_panel_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_alarm_control_panel_response"); } #endif uint32_t supported_features{0}; bool requires_code{false}; @@ -2605,7 +2605,7 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 95; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "alarm_control_panel_state_response"; } + const LogString *message_name() const override { return LOG_STR("alarm_control_panel_state_response"); } #endif enums::AlarmControlPanelState state{}; void encode(ProtoWriteBuffer &buffer) const; @@ -2621,7 +2621,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 96; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "alarm_control_panel_command_request"; } + const LogString *message_name() const override { return LOG_STR("alarm_control_panel_command_request"); } #endif enums::AlarmControlPanelStateCommand command{}; StringRef code{}; @@ -2641,7 +2641,7 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 97; static constexpr uint8_t ESTIMATED_SIZE = 59; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_text_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_text_response"); } #endif uint32_t min_length{0}; uint32_t max_length{0}; @@ -2660,7 +2660,7 @@ class TextStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 98; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "text_state_response"; } + const LogString *message_name() const override { return LOG_STR("text_state_response"); } #endif StringRef state{}; bool missing_state{false}; @@ -2677,7 +2677,7 @@ class TextCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 99; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "text_command_request"; } + const LogString *message_name() const override { return LOG_STR("text_command_request"); } #endif StringRef state{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2696,7 +2696,7 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 100; static constexpr uint8_t ESTIMATED_SIZE = 40; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_date_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_date_response"); } #endif void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; @@ -2711,7 +2711,7 @@ class DateStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 101; static constexpr uint8_t ESTIMATED_SIZE = 23; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "date_state_response"; } + const LogString *message_name() const override { return LOG_STR("date_state_response"); } #endif bool missing_state{false}; uint32_t year{0}; @@ -2730,7 +2730,7 @@ class DateCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 102; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "date_command_request"; } + const LogString *message_name() const override { return LOG_STR("date_command_request"); } #endif uint32_t year{0}; uint32_t month{0}; @@ -2750,7 +2750,7 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 103; static constexpr uint8_t ESTIMATED_SIZE = 40; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_time_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_time_response"); } #endif void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; @@ -2765,7 +2765,7 @@ class TimeStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 104; static constexpr uint8_t ESTIMATED_SIZE = 23; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "time_state_response"; } + const LogString *message_name() const override { return LOG_STR("time_state_response"); } #endif bool missing_state{false}; uint32_t hour{0}; @@ -2784,7 +2784,7 @@ class TimeCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 105; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "time_command_request"; } + const LogString *message_name() const override { return LOG_STR("time_command_request"); } #endif uint32_t hour{0}; uint32_t minute{0}; @@ -2804,7 +2804,7 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 107; static constexpr uint8_t ESTIMATED_SIZE = 67; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_event_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_event_response"); } #endif StringRef device_class{}; const FixedVector<const char *> *event_types{}; @@ -2821,7 +2821,7 @@ class EventResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 108; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "event_response"; } + const LogString *message_name() const override { return LOG_STR("event_response"); } #endif StringRef event_type{}; void encode(ProtoWriteBuffer &buffer) const; @@ -2839,7 +2839,7 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 109; static constexpr uint8_t ESTIMATED_SIZE = 55; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_valve_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_valve_response"); } #endif StringRef device_class{}; bool assumed_state{false}; @@ -2858,7 +2858,7 @@ class ValveStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 110; static constexpr uint8_t ESTIMATED_SIZE = 16; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "valve_state_response"; } + const LogString *message_name() const override { return LOG_STR("valve_state_response"); } #endif float position{0.0f}; enums::ValveOperation current_operation{}; @@ -2875,7 +2875,7 @@ class ValveCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 111; static constexpr uint8_t ESTIMATED_SIZE = 18; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "valve_command_request"; } + const LogString *message_name() const override { return LOG_STR("valve_command_request"); } #endif bool has_position{false}; float position{0.0f}; @@ -2895,7 +2895,7 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 112; static constexpr uint8_t ESTIMATED_SIZE = 40; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_date_time_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_date_time_response"); } #endif void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; @@ -2910,7 +2910,7 @@ class DateTimeStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 113; static constexpr uint8_t ESTIMATED_SIZE = 16; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "date_time_state_response"; } + const LogString *message_name() const override { return LOG_STR("date_time_state_response"); } #endif bool missing_state{false}; uint32_t epoch_seconds{0}; @@ -2927,7 +2927,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 114; static constexpr uint8_t ESTIMATED_SIZE = 14; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "date_time_command_request"; } + const LogString *message_name() const override { return LOG_STR("date_time_command_request"); } #endif uint32_t epoch_seconds{0}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -2945,7 +2945,7 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 116; static constexpr uint8_t ESTIMATED_SIZE = 49; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_update_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_update_response"); } #endif StringRef device_class{}; void encode(ProtoWriteBuffer &buffer) const; @@ -2961,7 +2961,7 @@ class UpdateStateResponse final : public StateResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 117; static constexpr uint8_t ESTIMATED_SIZE = 65; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "update_state_response"; } + const LogString *message_name() const override { return LOG_STR("update_state_response"); } #endif bool missing_state{false}; bool in_progress{false}; @@ -2985,7 +2985,7 @@ class UpdateCommandRequest final : public CommandProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 118; static constexpr uint8_t ESTIMATED_SIZE = 11; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "update_command_request"; } + const LogString *message_name() const override { return LOG_STR("update_command_request"); } #endif enums::UpdateCommand command{}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -3003,7 +3003,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 128; static constexpr uint8_t ESTIMATED_SIZE = 19; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "z_wave_proxy_frame"; } + const LogString *message_name() const override { return LOG_STR("z_wave_proxy_frame"); } #endif const uint8_t *data{nullptr}; uint16_t data_len{0}; @@ -3021,7 +3021,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 129; static constexpr uint8_t ESTIMATED_SIZE = 21; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "z_wave_proxy_request"; } + const LogString *message_name() const override { return LOG_STR("z_wave_proxy_request"); } #endif enums::ZWaveProxyRequestType type{}; const uint8_t *data{nullptr}; @@ -3043,7 +3043,7 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 135; static constexpr uint8_t ESTIMATED_SIZE = 44; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "list_entities_infrared_response"; } + const LogString *message_name() const override { return LOG_STR("list_entities_infrared_response"); } #endif uint32_t capabilities{0}; void encode(ProtoWriteBuffer &buffer) const; @@ -3061,7 +3061,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 136; static constexpr uint8_t ESTIMATED_SIZE = 220; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "infrared_rf_transmit_raw_timings_request"; } + const LogString *message_name() const override { return LOG_STR("infrared_rf_transmit_raw_timings_request"); } #endif #ifdef USE_DEVICES uint32_t device_id{0}; @@ -3086,7 +3086,7 @@ class InfraredRFReceiveEvent final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 137; static constexpr uint8_t ESTIMATED_SIZE = 17; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "infrared_rf_receive_event"; } + const LogString *message_name() const override { return LOG_STR("infrared_rf_receive_event"); } #endif #ifdef USE_DEVICES uint32_t device_id{0}; @@ -3108,7 +3108,7 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 138; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_configure_request"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_configure_request"); } #endif uint32_t instance{0}; uint32_t baudrate{0}; @@ -3128,7 +3128,7 @@ class SerialProxyDataReceived final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 139; static constexpr uint8_t ESTIMATED_SIZE = 23; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_data_received"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_data_received"); } #endif uint32_t instance{0}; const uint8_t *data_ptr_{nullptr}; @@ -3150,7 +3150,7 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 140; static constexpr uint8_t ESTIMATED_SIZE = 23; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_write_request"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_write_request"); } #endif uint32_t instance{0}; const uint8_t *data{nullptr}; @@ -3168,7 +3168,7 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 141; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_set_modem_pins_request"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_set_modem_pins_request"); } #endif uint32_t instance{0}; uint32_t line_states{0}; @@ -3184,7 +3184,7 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 142; static constexpr uint8_t ESTIMATED_SIZE = 4; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_get_modem_pins_request"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_get_modem_pins_request"); } #endif uint32_t instance{0}; #ifdef HAS_PROTO_MESSAGE_DUMP @@ -3199,7 +3199,7 @@ class SerialProxyGetModemPinsResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 143; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_get_modem_pins_response"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_get_modem_pins_response"); } #endif uint32_t instance{0}; uint32_t line_states{0}; @@ -3216,7 +3216,7 @@ class SerialProxyRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 144; static constexpr uint8_t ESTIMATED_SIZE = 6; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_request"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_request"); } #endif uint32_t instance{0}; enums::SerialProxyRequestType type{}; @@ -3232,7 +3232,7 @@ class SerialProxyRequestResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 147; static constexpr uint8_t ESTIMATED_SIZE = 17; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "serial_proxy_request_response"; } + const LogString *message_name() const override { return LOG_STR("serial_proxy_request_response"); } #endif uint32_t instance{0}; enums::SerialProxyRequestType type{}; @@ -3253,7 +3253,7 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { static constexpr uint8_t MESSAGE_TYPE = 145; static constexpr uint8_t ESTIMATED_SIZE = 20; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_set_connection_params_request"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_set_connection_params_request"); } #endif uint64_t address{0}; uint32_t min_interval{0}; @@ -3272,7 +3272,7 @@ class BluetoothSetConnectionParamsResponse final : public ProtoMessage { static constexpr uint8_t MESSAGE_TYPE = 146; static constexpr uint8_t ESTIMATED_SIZE = 8; #ifdef HAS_PROTO_MESSAGE_DUMP - const char *message_name() const override { return "bluetooth_set_connection_params_response"; } + const LogString *message_name() const override { return LOG_STR("bluetooth_set_connection_params_response"); } #endif uint64_t address{0}; int32_t error{0}; diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index 5a53f0281f..a11f3b231e 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -2,6 +2,7 @@ // See script/api_protobuf/api_protobuf.py #include "api_pb2.h" #include "esphome/core/helpers.h" +#include "esphome/core/progmem.h" #include <cinttypes> @@ -9,6 +10,21 @@ namespace esphome::api { +#ifdef USE_ESP8266 +// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site +void DumpBuffer::append_p_esp8266(const char *str) { + size_t len = strlen_P(str); + size_t space = CAPACITY - 1 - pos_; + if (len > space) + len = space; + if (len > 0) { + memcpy_P(buf_ + pos_, str, len); + pos_ += len; + buf_[pos_] = '\0'; + } +} +#endif + // Helper function to append a quoted string, handling empty StringRef static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); @@ -19,8 +35,9 @@ static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { } // Common helpers for dump_field functions +// field_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) static inline void append_field_prefix(DumpBuffer &out, const char *field_name, int indent) { - out.append(indent, ' ').append(field_name).append(": "); + out.append(indent, ' ').append_p(field_name).append(": "); } static inline void append_uint(DumpBuffer &out, uint32_t value) { @@ -28,10 +45,11 @@ static inline void append_uint(DumpBuffer &out, uint32_t value) { } // RAII helper for message dump formatting +// message_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) class MessageDumpHelper { public: MessageDumpHelper(DumpBuffer &out, const char *message_name) : out_(out) { - out_.append(message_name); + out_.append_p(message_name); out_.append(" {\n"); } ~MessageDumpHelper() { out_.append(" }"); } @@ -41,6 +59,10 @@ class MessageDumpHelper { }; // Helper functions to reduce code duplication in dump methods +// field_name parameters are PROGMEM pointers (flash on ESP8266, regular pointers on other platforms) +// Not all overloads are used in every build (depends on enabled components) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { append_field_prefix(out, field_name, indent); out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\n", value)); @@ -85,56 +107,59 @@ static void dump_field(DumpBuffer &out, const char *field_name, const char *valu out.append("\n"); } +// proto_enum_to_string returns PROGMEM pointers, so use append_p template<typename T> static void dump_field(DumpBuffer &out, const char *field_name, T value, int indent = 2) { append_field_prefix(out, field_name, indent); - out.append(proto_enum_to_string<T>(value)); + out.append_p(proto_enum_to_string<T>(value)); out.append("\n"); } // Helper for bytes fields - uses stack buffer to avoid heap allocation // Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer +// field_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); out.append(hex_buf).append("\n"); } +#pragma GCC diagnostic pop template<> const char *proto_enum_to_string<enums::SerialProxyPortType>(enums::SerialProxyPortType value) { switch (value) { case enums::SERIAL_PROXY_PORT_TYPE_TTL: - return "SERIAL_PROXY_PORT_TYPE_TTL"; + return ESPHOME_PSTR("SERIAL_PROXY_PORT_TYPE_TTL"); case enums::SERIAL_PROXY_PORT_TYPE_RS232: - return "SERIAL_PROXY_PORT_TYPE_RS232"; + return ESPHOME_PSTR("SERIAL_PROXY_PORT_TYPE_RS232"); case enums::SERIAL_PROXY_PORT_TYPE_RS485: - return "SERIAL_PROXY_PORT_TYPE_RS485"; + return ESPHOME_PSTR("SERIAL_PROXY_PORT_TYPE_RS485"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) { switch (value) { case enums::ENTITY_CATEGORY_NONE: - return "ENTITY_CATEGORY_NONE"; + return ESPHOME_PSTR("ENTITY_CATEGORY_NONE"); case enums::ENTITY_CATEGORY_CONFIG: - return "ENTITY_CATEGORY_CONFIG"; + return ESPHOME_PSTR("ENTITY_CATEGORY_CONFIG"); case enums::ENTITY_CATEGORY_DIAGNOSTIC: - return "ENTITY_CATEGORY_DIAGNOSTIC"; + return ESPHOME_PSTR("ENTITY_CATEGORY_DIAGNOSTIC"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #ifdef USE_COVER template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverOperation value) { switch (value) { case enums::COVER_OPERATION_IDLE: - return "COVER_OPERATION_IDLE"; + return ESPHOME_PSTR("COVER_OPERATION_IDLE"); case enums::COVER_OPERATION_IS_OPENING: - return "COVER_OPERATION_IS_OPENING"; + return ESPHOME_PSTR("COVER_OPERATION_IS_OPENING"); case enums::COVER_OPERATION_IS_CLOSING: - return "COVER_OPERATION_IS_CLOSING"; + return ESPHOME_PSTR("COVER_OPERATION_IS_CLOSING"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -142,11 +167,11 @@ template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverO template<> const char *proto_enum_to_string<enums::FanDirection>(enums::FanDirection value) { switch (value) { case enums::FAN_DIRECTION_FORWARD: - return "FAN_DIRECTION_FORWARD"; + return ESPHOME_PSTR("FAN_DIRECTION_FORWARD"); case enums::FAN_DIRECTION_REVERSE: - return "FAN_DIRECTION_REVERSE"; + return ESPHOME_PSTR("FAN_DIRECTION_REVERSE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -154,29 +179,29 @@ template<> const char *proto_enum_to_string<enums::FanDirection>(enums::FanDirec template<> const char *proto_enum_to_string<enums::ColorMode>(enums::ColorMode value) { switch (value) { case enums::COLOR_MODE_UNKNOWN: - return "COLOR_MODE_UNKNOWN"; + return ESPHOME_PSTR("COLOR_MODE_UNKNOWN"); case enums::COLOR_MODE_ON_OFF: - return "COLOR_MODE_ON_OFF"; + return ESPHOME_PSTR("COLOR_MODE_ON_OFF"); case enums::COLOR_MODE_LEGACY_BRIGHTNESS: - return "COLOR_MODE_LEGACY_BRIGHTNESS"; + return ESPHOME_PSTR("COLOR_MODE_LEGACY_BRIGHTNESS"); case enums::COLOR_MODE_BRIGHTNESS: - return "COLOR_MODE_BRIGHTNESS"; + return ESPHOME_PSTR("COLOR_MODE_BRIGHTNESS"); case enums::COLOR_MODE_WHITE: - return "COLOR_MODE_WHITE"; + return ESPHOME_PSTR("COLOR_MODE_WHITE"); case enums::COLOR_MODE_COLOR_TEMPERATURE: - return "COLOR_MODE_COLOR_TEMPERATURE"; + return ESPHOME_PSTR("COLOR_MODE_COLOR_TEMPERATURE"); case enums::COLOR_MODE_COLD_WARM_WHITE: - return "COLOR_MODE_COLD_WARM_WHITE"; + return ESPHOME_PSTR("COLOR_MODE_COLD_WARM_WHITE"); case enums::COLOR_MODE_RGB: - return "COLOR_MODE_RGB"; + return ESPHOME_PSTR("COLOR_MODE_RGB"); case enums::COLOR_MODE_RGB_WHITE: - return "COLOR_MODE_RGB_WHITE"; + return ESPHOME_PSTR("COLOR_MODE_RGB_WHITE"); case enums::COLOR_MODE_RGB_COLOR_TEMPERATURE: - return "COLOR_MODE_RGB_COLOR_TEMPERATURE"; + return ESPHOME_PSTR("COLOR_MODE_RGB_COLOR_TEMPERATURE"); case enums::COLOR_MODE_RGB_COLD_WARM_WHITE: - return "COLOR_MODE_RGB_COLD_WARM_WHITE"; + return ESPHOME_PSTR("COLOR_MODE_RGB_COLD_WARM_WHITE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -184,91 +209,91 @@ template<> const char *proto_enum_to_string<enums::ColorMode>(enums::ColorMode v template<> const char *proto_enum_to_string<enums::SensorStateClass>(enums::SensorStateClass value) { switch (value) { case enums::STATE_CLASS_NONE: - return "STATE_CLASS_NONE"; + return ESPHOME_PSTR("STATE_CLASS_NONE"); case enums::STATE_CLASS_MEASUREMENT: - return "STATE_CLASS_MEASUREMENT"; + return ESPHOME_PSTR("STATE_CLASS_MEASUREMENT"); case enums::STATE_CLASS_TOTAL_INCREASING: - return "STATE_CLASS_TOTAL_INCREASING"; + return ESPHOME_PSTR("STATE_CLASS_TOTAL_INCREASING"); case enums::STATE_CLASS_TOTAL: - return "STATE_CLASS_TOTAL"; + return ESPHOME_PSTR("STATE_CLASS_TOTAL"); case enums::STATE_CLASS_MEASUREMENT_ANGLE: - return "STATE_CLASS_MEASUREMENT_ANGLE"; + return ESPHOME_PSTR("STATE_CLASS_MEASUREMENT_ANGLE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel value) { switch (value) { case enums::LOG_LEVEL_NONE: - return "LOG_LEVEL_NONE"; + return ESPHOME_PSTR("LOG_LEVEL_NONE"); case enums::LOG_LEVEL_ERROR: - return "LOG_LEVEL_ERROR"; + return ESPHOME_PSTR("LOG_LEVEL_ERROR"); case enums::LOG_LEVEL_WARN: - return "LOG_LEVEL_WARN"; + return ESPHOME_PSTR("LOG_LEVEL_WARN"); case enums::LOG_LEVEL_INFO: - return "LOG_LEVEL_INFO"; + return ESPHOME_PSTR("LOG_LEVEL_INFO"); case enums::LOG_LEVEL_CONFIG: - return "LOG_LEVEL_CONFIG"; + return ESPHOME_PSTR("LOG_LEVEL_CONFIG"); case enums::LOG_LEVEL_DEBUG: - return "LOG_LEVEL_DEBUG"; + return ESPHOME_PSTR("LOG_LEVEL_DEBUG"); case enums::LOG_LEVEL_VERBOSE: - return "LOG_LEVEL_VERBOSE"; + return ESPHOME_PSTR("LOG_LEVEL_VERBOSE"); case enums::LOG_LEVEL_VERY_VERBOSE: - return "LOG_LEVEL_VERY_VERBOSE"; + return ESPHOME_PSTR("LOG_LEVEL_VERY_VERBOSE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::DSTRuleType>(enums::DSTRuleType value) { switch (value) { case enums::DST_RULE_TYPE_NONE: - return "DST_RULE_TYPE_NONE"; + return ESPHOME_PSTR("DST_RULE_TYPE_NONE"); case enums::DST_RULE_TYPE_MONTH_WEEK_DAY: - return "DST_RULE_TYPE_MONTH_WEEK_DAY"; + return ESPHOME_PSTR("DST_RULE_TYPE_MONTH_WEEK_DAY"); case enums::DST_RULE_TYPE_JULIAN_NO_LEAP: - return "DST_RULE_TYPE_JULIAN_NO_LEAP"; + return ESPHOME_PSTR("DST_RULE_TYPE_JULIAN_NO_LEAP"); case enums::DST_RULE_TYPE_DAY_OF_YEAR: - return "DST_RULE_TYPE_DAY_OF_YEAR"; + return ESPHOME_PSTR("DST_RULE_TYPE_DAY_OF_YEAR"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #ifdef USE_API_USER_DEFINED_ACTIONS template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) { switch (value) { case enums::SERVICE_ARG_TYPE_BOOL: - return "SERVICE_ARG_TYPE_BOOL"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_BOOL"); case enums::SERVICE_ARG_TYPE_INT: - return "SERVICE_ARG_TYPE_INT"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_INT"); case enums::SERVICE_ARG_TYPE_FLOAT: - return "SERVICE_ARG_TYPE_FLOAT"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_FLOAT"); case enums::SERVICE_ARG_TYPE_STRING: - return "SERVICE_ARG_TYPE_STRING"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_STRING"); case enums::SERVICE_ARG_TYPE_BOOL_ARRAY: - return "SERVICE_ARG_TYPE_BOOL_ARRAY"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_BOOL_ARRAY"); case enums::SERVICE_ARG_TYPE_INT_ARRAY: - return "SERVICE_ARG_TYPE_INT_ARRAY"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_INT_ARRAY"); case enums::SERVICE_ARG_TYPE_FLOAT_ARRAY: - return "SERVICE_ARG_TYPE_FLOAT_ARRAY"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_FLOAT_ARRAY"); case enums::SERVICE_ARG_TYPE_STRING_ARRAY: - return "SERVICE_ARG_TYPE_STRING_ARRAY"; + return ESPHOME_PSTR("SERVICE_ARG_TYPE_STRING_ARRAY"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::SupportsResponseType>(enums::SupportsResponseType value) { switch (value) { case enums::SUPPORTS_RESPONSE_NONE: - return "SUPPORTS_RESPONSE_NONE"; + return ESPHOME_PSTR("SUPPORTS_RESPONSE_NONE"); case enums::SUPPORTS_RESPONSE_OPTIONAL: - return "SUPPORTS_RESPONSE_OPTIONAL"; + return ESPHOME_PSTR("SUPPORTS_RESPONSE_OPTIONAL"); case enums::SUPPORTS_RESPONSE_ONLY: - return "SUPPORTS_RESPONSE_ONLY"; + return ESPHOME_PSTR("SUPPORTS_RESPONSE_ONLY"); case enums::SUPPORTS_RESPONSE_STATUS: - return "SUPPORTS_RESPONSE_STATUS"; + return ESPHOME_PSTR("SUPPORTS_RESPONSE_STATUS"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -276,103 +301,103 @@ template<> const char *proto_enum_to_string<enums::SupportsResponseType>(enums:: template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMode value) { switch (value) { case enums::CLIMATE_MODE_OFF: - return "CLIMATE_MODE_OFF"; + return ESPHOME_PSTR("CLIMATE_MODE_OFF"); case enums::CLIMATE_MODE_HEAT_COOL: - return "CLIMATE_MODE_HEAT_COOL"; + return ESPHOME_PSTR("CLIMATE_MODE_HEAT_COOL"); case enums::CLIMATE_MODE_COOL: - return "CLIMATE_MODE_COOL"; + return ESPHOME_PSTR("CLIMATE_MODE_COOL"); case enums::CLIMATE_MODE_HEAT: - return "CLIMATE_MODE_HEAT"; + return ESPHOME_PSTR("CLIMATE_MODE_HEAT"); case enums::CLIMATE_MODE_FAN_ONLY: - return "CLIMATE_MODE_FAN_ONLY"; + return ESPHOME_PSTR("CLIMATE_MODE_FAN_ONLY"); case enums::CLIMATE_MODE_DRY: - return "CLIMATE_MODE_DRY"; + return ESPHOME_PSTR("CLIMATE_MODE_DRY"); case enums::CLIMATE_MODE_AUTO: - return "CLIMATE_MODE_AUTO"; + return ESPHOME_PSTR("CLIMATE_MODE_AUTO"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::ClimateFanMode>(enums::ClimateFanMode value) { switch (value) { case enums::CLIMATE_FAN_ON: - return "CLIMATE_FAN_ON"; + return ESPHOME_PSTR("CLIMATE_FAN_ON"); case enums::CLIMATE_FAN_OFF: - return "CLIMATE_FAN_OFF"; + return ESPHOME_PSTR("CLIMATE_FAN_OFF"); case enums::CLIMATE_FAN_AUTO: - return "CLIMATE_FAN_AUTO"; + return ESPHOME_PSTR("CLIMATE_FAN_AUTO"); case enums::CLIMATE_FAN_LOW: - return "CLIMATE_FAN_LOW"; + return ESPHOME_PSTR("CLIMATE_FAN_LOW"); case enums::CLIMATE_FAN_MEDIUM: - return "CLIMATE_FAN_MEDIUM"; + return ESPHOME_PSTR("CLIMATE_FAN_MEDIUM"); case enums::CLIMATE_FAN_HIGH: - return "CLIMATE_FAN_HIGH"; + return ESPHOME_PSTR("CLIMATE_FAN_HIGH"); case enums::CLIMATE_FAN_MIDDLE: - return "CLIMATE_FAN_MIDDLE"; + return ESPHOME_PSTR("CLIMATE_FAN_MIDDLE"); case enums::CLIMATE_FAN_FOCUS: - return "CLIMATE_FAN_FOCUS"; + return ESPHOME_PSTR("CLIMATE_FAN_FOCUS"); case enums::CLIMATE_FAN_DIFFUSE: - return "CLIMATE_FAN_DIFFUSE"; + return ESPHOME_PSTR("CLIMATE_FAN_DIFFUSE"); case enums::CLIMATE_FAN_QUIET: - return "CLIMATE_FAN_QUIET"; + return ESPHOME_PSTR("CLIMATE_FAN_QUIET"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::ClimateSwingMode>(enums::ClimateSwingMode value) { switch (value) { case enums::CLIMATE_SWING_OFF: - return "CLIMATE_SWING_OFF"; + return ESPHOME_PSTR("CLIMATE_SWING_OFF"); case enums::CLIMATE_SWING_BOTH: - return "CLIMATE_SWING_BOTH"; + return ESPHOME_PSTR("CLIMATE_SWING_BOTH"); case enums::CLIMATE_SWING_VERTICAL: - return "CLIMATE_SWING_VERTICAL"; + return ESPHOME_PSTR("CLIMATE_SWING_VERTICAL"); case enums::CLIMATE_SWING_HORIZONTAL: - return "CLIMATE_SWING_HORIZONTAL"; + return ESPHOME_PSTR("CLIMATE_SWING_HORIZONTAL"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::ClimateAction value) { switch (value) { case enums::CLIMATE_ACTION_OFF: - return "CLIMATE_ACTION_OFF"; + return ESPHOME_PSTR("CLIMATE_ACTION_OFF"); case enums::CLIMATE_ACTION_COOLING: - return "CLIMATE_ACTION_COOLING"; + return ESPHOME_PSTR("CLIMATE_ACTION_COOLING"); case enums::CLIMATE_ACTION_HEATING: - return "CLIMATE_ACTION_HEATING"; + return ESPHOME_PSTR("CLIMATE_ACTION_HEATING"); case enums::CLIMATE_ACTION_IDLE: - return "CLIMATE_ACTION_IDLE"; + return ESPHOME_PSTR("CLIMATE_ACTION_IDLE"); case enums::CLIMATE_ACTION_DRYING: - return "CLIMATE_ACTION_DRYING"; + return ESPHOME_PSTR("CLIMATE_ACTION_DRYING"); case enums::CLIMATE_ACTION_FAN: - return "CLIMATE_ACTION_FAN"; + return ESPHOME_PSTR("CLIMATE_ACTION_FAN"); case enums::CLIMATE_ACTION_DEFROSTING: - return "CLIMATE_ACTION_DEFROSTING"; + return ESPHOME_PSTR("CLIMATE_ACTION_DEFROSTING"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::ClimatePreset value) { switch (value) { case enums::CLIMATE_PRESET_NONE: - return "CLIMATE_PRESET_NONE"; + return ESPHOME_PSTR("CLIMATE_PRESET_NONE"); case enums::CLIMATE_PRESET_HOME: - return "CLIMATE_PRESET_HOME"; + return ESPHOME_PSTR("CLIMATE_PRESET_HOME"); case enums::CLIMATE_PRESET_AWAY: - return "CLIMATE_PRESET_AWAY"; + return ESPHOME_PSTR("CLIMATE_PRESET_AWAY"); case enums::CLIMATE_PRESET_BOOST: - return "CLIMATE_PRESET_BOOST"; + return ESPHOME_PSTR("CLIMATE_PRESET_BOOST"); case enums::CLIMATE_PRESET_COMFORT: - return "CLIMATE_PRESET_COMFORT"; + return ESPHOME_PSTR("CLIMATE_PRESET_COMFORT"); case enums::CLIMATE_PRESET_ECO: - return "CLIMATE_PRESET_ECO"; + return ESPHOME_PSTR("CLIMATE_PRESET_ECO"); case enums::CLIMATE_PRESET_SLEEP: - return "CLIMATE_PRESET_SLEEP"; + return ESPHOME_PSTR("CLIMATE_PRESET_SLEEP"); case enums::CLIMATE_PRESET_ACTIVITY: - return "CLIMATE_PRESET_ACTIVITY"; + return ESPHOME_PSTR("CLIMATE_PRESET_ACTIVITY"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -380,21 +405,21 @@ template<> const char *proto_enum_to_string<enums::ClimatePreset>(enums::Climate template<> const char *proto_enum_to_string<enums::WaterHeaterMode>(enums::WaterHeaterMode value) { switch (value) { case enums::WATER_HEATER_MODE_OFF: - return "WATER_HEATER_MODE_OFF"; + return ESPHOME_PSTR("WATER_HEATER_MODE_OFF"); case enums::WATER_HEATER_MODE_ECO: - return "WATER_HEATER_MODE_ECO"; + return ESPHOME_PSTR("WATER_HEATER_MODE_ECO"); case enums::WATER_HEATER_MODE_ELECTRIC: - return "WATER_HEATER_MODE_ELECTRIC"; + return ESPHOME_PSTR("WATER_HEATER_MODE_ELECTRIC"); case enums::WATER_HEATER_MODE_PERFORMANCE: - return "WATER_HEATER_MODE_PERFORMANCE"; + return ESPHOME_PSTR("WATER_HEATER_MODE_PERFORMANCE"); case enums::WATER_HEATER_MODE_HIGH_DEMAND: - return "WATER_HEATER_MODE_HIGH_DEMAND"; + return ESPHOME_PSTR("WATER_HEATER_MODE_HIGH_DEMAND"); case enums::WATER_HEATER_MODE_HEAT_PUMP: - return "WATER_HEATER_MODE_HEAT_PUMP"; + return ESPHOME_PSTR("WATER_HEATER_MODE_HEAT_PUMP"); case enums::WATER_HEATER_MODE_GAS: - return "WATER_HEATER_MODE_GAS"; + return ESPHOME_PSTR("WATER_HEATER_MODE_GAS"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -402,36 +427,36 @@ template<> const char *proto_enum_to_string<enums::WaterHeaterCommandHasField>(enums::WaterHeaterCommandHasField value) { switch (value) { case enums::WATER_HEATER_COMMAND_HAS_NONE: - return "WATER_HEATER_COMMAND_HAS_NONE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_NONE"); case enums::WATER_HEATER_COMMAND_HAS_MODE: - return "WATER_HEATER_COMMAND_HAS_MODE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_MODE"); case enums::WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE: - return "WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE"); case enums::WATER_HEATER_COMMAND_HAS_STATE: - return "WATER_HEATER_COMMAND_HAS_STATE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_STATE"); case enums::WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW: - return "WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_LOW"); case enums::WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH: - return "WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_TARGET_TEMPERATURE_HIGH"); case enums::WATER_HEATER_COMMAND_HAS_ON_STATE: - return "WATER_HEATER_COMMAND_HAS_ON_STATE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_ON_STATE"); case enums::WATER_HEATER_COMMAND_HAS_AWAY_STATE: - return "WATER_HEATER_COMMAND_HAS_AWAY_STATE"; + return ESPHOME_PSTR("WATER_HEATER_COMMAND_HAS_AWAY_STATE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #ifdef USE_NUMBER template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode value) { switch (value) { case enums::NUMBER_MODE_AUTO: - return "NUMBER_MODE_AUTO"; + return ESPHOME_PSTR("NUMBER_MODE_AUTO"); case enums::NUMBER_MODE_BOX: - return "NUMBER_MODE_BOX"; + return ESPHOME_PSTR("NUMBER_MODE_BOX"); case enums::NUMBER_MODE_SLIDER: - return "NUMBER_MODE_SLIDER"; + return ESPHOME_PSTR("NUMBER_MODE_SLIDER"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -439,31 +464,31 @@ template<> const char *proto_enum_to_string<enums::NumberMode>(enums::NumberMode template<> const char *proto_enum_to_string<enums::LockState>(enums::LockState value) { switch (value) { case enums::LOCK_STATE_NONE: - return "LOCK_STATE_NONE"; + return ESPHOME_PSTR("LOCK_STATE_NONE"); case enums::LOCK_STATE_LOCKED: - return "LOCK_STATE_LOCKED"; + return ESPHOME_PSTR("LOCK_STATE_LOCKED"); case enums::LOCK_STATE_UNLOCKED: - return "LOCK_STATE_UNLOCKED"; + return ESPHOME_PSTR("LOCK_STATE_UNLOCKED"); case enums::LOCK_STATE_JAMMED: - return "LOCK_STATE_JAMMED"; + return ESPHOME_PSTR("LOCK_STATE_JAMMED"); case enums::LOCK_STATE_LOCKING: - return "LOCK_STATE_LOCKING"; + return ESPHOME_PSTR("LOCK_STATE_LOCKING"); case enums::LOCK_STATE_UNLOCKING: - return "LOCK_STATE_UNLOCKING"; + return ESPHOME_PSTR("LOCK_STATE_UNLOCKING"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::LockCommand>(enums::LockCommand value) { switch (value) { case enums::LOCK_UNLOCK: - return "LOCK_UNLOCK"; + return ESPHOME_PSTR("LOCK_UNLOCK"); case enums::LOCK_LOCK: - return "LOCK_LOCK"; + return ESPHOME_PSTR("LOCK_LOCK"); case enums::LOCK_OPEN: - return "LOCK_OPEN"; + return ESPHOME_PSTR("LOCK_OPEN"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -471,65 +496,65 @@ template<> const char *proto_enum_to_string<enums::LockCommand>(enums::LockComma template<> const char *proto_enum_to_string<enums::MediaPlayerState>(enums::MediaPlayerState value) { switch (value) { case enums::MEDIA_PLAYER_STATE_NONE: - return "MEDIA_PLAYER_STATE_NONE"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_NONE"); case enums::MEDIA_PLAYER_STATE_IDLE: - return "MEDIA_PLAYER_STATE_IDLE"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_IDLE"); case enums::MEDIA_PLAYER_STATE_PLAYING: - return "MEDIA_PLAYER_STATE_PLAYING"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_PLAYING"); case enums::MEDIA_PLAYER_STATE_PAUSED: - return "MEDIA_PLAYER_STATE_PAUSED"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_PAUSED"); case enums::MEDIA_PLAYER_STATE_ANNOUNCING: - return "MEDIA_PLAYER_STATE_ANNOUNCING"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_ANNOUNCING"); case enums::MEDIA_PLAYER_STATE_OFF: - return "MEDIA_PLAYER_STATE_OFF"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_OFF"); case enums::MEDIA_PLAYER_STATE_ON: - return "MEDIA_PLAYER_STATE_ON"; + return ESPHOME_PSTR("MEDIA_PLAYER_STATE_ON"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::MediaPlayerCommand>(enums::MediaPlayerCommand value) { switch (value) { case enums::MEDIA_PLAYER_COMMAND_PLAY: - return "MEDIA_PLAYER_COMMAND_PLAY"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_PLAY"); case enums::MEDIA_PLAYER_COMMAND_PAUSE: - return "MEDIA_PLAYER_COMMAND_PAUSE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_PAUSE"); case enums::MEDIA_PLAYER_COMMAND_STOP: - return "MEDIA_PLAYER_COMMAND_STOP"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_STOP"); case enums::MEDIA_PLAYER_COMMAND_MUTE: - return "MEDIA_PLAYER_COMMAND_MUTE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_MUTE"); case enums::MEDIA_PLAYER_COMMAND_UNMUTE: - return "MEDIA_PLAYER_COMMAND_UNMUTE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_UNMUTE"); case enums::MEDIA_PLAYER_COMMAND_TOGGLE: - return "MEDIA_PLAYER_COMMAND_TOGGLE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_TOGGLE"); case enums::MEDIA_PLAYER_COMMAND_VOLUME_UP: - return "MEDIA_PLAYER_COMMAND_VOLUME_UP"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_VOLUME_UP"); case enums::MEDIA_PLAYER_COMMAND_VOLUME_DOWN: - return "MEDIA_PLAYER_COMMAND_VOLUME_DOWN"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_VOLUME_DOWN"); case enums::MEDIA_PLAYER_COMMAND_ENQUEUE: - return "MEDIA_PLAYER_COMMAND_ENQUEUE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_ENQUEUE"); case enums::MEDIA_PLAYER_COMMAND_REPEAT_ONE: - return "MEDIA_PLAYER_COMMAND_REPEAT_ONE"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_REPEAT_ONE"); case enums::MEDIA_PLAYER_COMMAND_REPEAT_OFF: - return "MEDIA_PLAYER_COMMAND_REPEAT_OFF"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_REPEAT_OFF"); case enums::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST: - return "MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST"); case enums::MEDIA_PLAYER_COMMAND_TURN_ON: - return "MEDIA_PLAYER_COMMAND_TURN_ON"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_TURN_ON"); case enums::MEDIA_PLAYER_COMMAND_TURN_OFF: - return "MEDIA_PLAYER_COMMAND_TURN_OFF"; + return ESPHOME_PSTR("MEDIA_PLAYER_COMMAND_TURN_OFF"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::MediaPlayerFormatPurpose>(enums::MediaPlayerFormatPurpose value) { switch (value) { case enums::MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT: - return "MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT"; + return ESPHOME_PSTR("MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT"); case enums::MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT: - return "MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT"; + return ESPHOME_PSTR("MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -538,49 +563,49 @@ template<> const char *proto_enum_to_string<enums::BluetoothDeviceRequestType>(enums::BluetoothDeviceRequestType value) { switch (value) { case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE"); case enums::BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE: - return "BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE"; + return ESPHOME_PSTR("BLUETOOTH_DEVICE_REQUEST_TYPE_CLEAR_CACHE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::BluetoothScannerState>(enums::BluetoothScannerState value) { switch (value) { case enums::BLUETOOTH_SCANNER_STATE_IDLE: - return "BLUETOOTH_SCANNER_STATE_IDLE"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_IDLE"); case enums::BLUETOOTH_SCANNER_STATE_STARTING: - return "BLUETOOTH_SCANNER_STATE_STARTING"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_STARTING"); case enums::BLUETOOTH_SCANNER_STATE_RUNNING: - return "BLUETOOTH_SCANNER_STATE_RUNNING"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_RUNNING"); case enums::BLUETOOTH_SCANNER_STATE_FAILED: - return "BLUETOOTH_SCANNER_STATE_FAILED"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_FAILED"); case enums::BLUETOOTH_SCANNER_STATE_STOPPING: - return "BLUETOOTH_SCANNER_STATE_STOPPING"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_STOPPING"); case enums::BLUETOOTH_SCANNER_STATE_STOPPED: - return "BLUETOOTH_SCANNER_STATE_STOPPED"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_STATE_STOPPED"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::BluetoothScannerMode>(enums::BluetoothScannerMode value) { switch (value) { case enums::BLUETOOTH_SCANNER_MODE_PASSIVE: - return "BLUETOOTH_SCANNER_MODE_PASSIVE"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_MODE_PASSIVE"); case enums::BLUETOOTH_SCANNER_MODE_ACTIVE: - return "BLUETOOTH_SCANNER_MODE_ACTIVE"; + return ESPHOME_PSTR("BLUETOOTH_SCANNER_MODE_ACTIVE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -588,76 +613,76 @@ template<> const char *proto_enum_to_string<enums::VoiceAssistantSubscribeFlag>(enums::VoiceAssistantSubscribeFlag value) { switch (value) { case enums::VOICE_ASSISTANT_SUBSCRIBE_NONE: - return "VOICE_ASSISTANT_SUBSCRIBE_NONE"; + return ESPHOME_PSTR("VOICE_ASSISTANT_SUBSCRIBE_NONE"); case enums::VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO: - return "VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO"; + return ESPHOME_PSTR("VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::VoiceAssistantRequestFlag>(enums::VoiceAssistantRequestFlag value) { switch (value) { case enums::VOICE_ASSISTANT_REQUEST_NONE: - return "VOICE_ASSISTANT_REQUEST_NONE"; + return ESPHOME_PSTR("VOICE_ASSISTANT_REQUEST_NONE"); case enums::VOICE_ASSISTANT_REQUEST_USE_VAD: - return "VOICE_ASSISTANT_REQUEST_USE_VAD"; + return ESPHOME_PSTR("VOICE_ASSISTANT_REQUEST_USE_VAD"); case enums::VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD: - return "VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD"; + return ESPHOME_PSTR("VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #ifdef USE_VOICE_ASSISTANT template<> const char *proto_enum_to_string<enums::VoiceAssistantEvent>(enums::VoiceAssistantEvent value) { switch (value) { case enums::VOICE_ASSISTANT_ERROR: - return "VOICE_ASSISTANT_ERROR"; + return ESPHOME_PSTR("VOICE_ASSISTANT_ERROR"); case enums::VOICE_ASSISTANT_RUN_START: - return "VOICE_ASSISTANT_RUN_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_RUN_START"); case enums::VOICE_ASSISTANT_RUN_END: - return "VOICE_ASSISTANT_RUN_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_RUN_END"); case enums::VOICE_ASSISTANT_STT_START: - return "VOICE_ASSISTANT_STT_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_STT_START"); case enums::VOICE_ASSISTANT_STT_END: - return "VOICE_ASSISTANT_STT_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_STT_END"); case enums::VOICE_ASSISTANT_INTENT_START: - return "VOICE_ASSISTANT_INTENT_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_INTENT_START"); case enums::VOICE_ASSISTANT_INTENT_END: - return "VOICE_ASSISTANT_INTENT_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_INTENT_END"); case enums::VOICE_ASSISTANT_TTS_START: - return "VOICE_ASSISTANT_TTS_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TTS_START"); case enums::VOICE_ASSISTANT_TTS_END: - return "VOICE_ASSISTANT_TTS_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TTS_END"); case enums::VOICE_ASSISTANT_WAKE_WORD_START: - return "VOICE_ASSISTANT_WAKE_WORD_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_WAKE_WORD_START"); case enums::VOICE_ASSISTANT_WAKE_WORD_END: - return "VOICE_ASSISTANT_WAKE_WORD_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_WAKE_WORD_END"); case enums::VOICE_ASSISTANT_STT_VAD_START: - return "VOICE_ASSISTANT_STT_VAD_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_STT_VAD_START"); case enums::VOICE_ASSISTANT_STT_VAD_END: - return "VOICE_ASSISTANT_STT_VAD_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_STT_VAD_END"); case enums::VOICE_ASSISTANT_TTS_STREAM_START: - return "VOICE_ASSISTANT_TTS_STREAM_START"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TTS_STREAM_START"); case enums::VOICE_ASSISTANT_TTS_STREAM_END: - return "VOICE_ASSISTANT_TTS_STREAM_END"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TTS_STREAM_END"); case enums::VOICE_ASSISTANT_INTENT_PROGRESS: - return "VOICE_ASSISTANT_INTENT_PROGRESS"; + return ESPHOME_PSTR("VOICE_ASSISTANT_INTENT_PROGRESS"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::VoiceAssistantTimerEvent>(enums::VoiceAssistantTimerEvent value) { switch (value) { case enums::VOICE_ASSISTANT_TIMER_STARTED: - return "VOICE_ASSISTANT_TIMER_STARTED"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TIMER_STARTED"); case enums::VOICE_ASSISTANT_TIMER_UPDATED: - return "VOICE_ASSISTANT_TIMER_UPDATED"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TIMER_UPDATED"); case enums::VOICE_ASSISTANT_TIMER_CANCELLED: - return "VOICE_ASSISTANT_TIMER_CANCELLED"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TIMER_CANCELLED"); case enums::VOICE_ASSISTANT_TIMER_FINISHED: - return "VOICE_ASSISTANT_TIMER_FINISHED"; + return ESPHOME_PSTR("VOICE_ASSISTANT_TIMER_FINISHED"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -665,48 +690,48 @@ template<> const char *proto_enum_to_string<enums::VoiceAssistantTimerEvent>(enu template<> const char *proto_enum_to_string<enums::AlarmControlPanelState>(enums::AlarmControlPanelState value) { switch (value) { case enums::ALARM_STATE_DISARMED: - return "ALARM_STATE_DISARMED"; + return ESPHOME_PSTR("ALARM_STATE_DISARMED"); case enums::ALARM_STATE_ARMED_HOME: - return "ALARM_STATE_ARMED_HOME"; + return ESPHOME_PSTR("ALARM_STATE_ARMED_HOME"); case enums::ALARM_STATE_ARMED_AWAY: - return "ALARM_STATE_ARMED_AWAY"; + return ESPHOME_PSTR("ALARM_STATE_ARMED_AWAY"); case enums::ALARM_STATE_ARMED_NIGHT: - return "ALARM_STATE_ARMED_NIGHT"; + return ESPHOME_PSTR("ALARM_STATE_ARMED_NIGHT"); case enums::ALARM_STATE_ARMED_VACATION: - return "ALARM_STATE_ARMED_VACATION"; + return ESPHOME_PSTR("ALARM_STATE_ARMED_VACATION"); case enums::ALARM_STATE_ARMED_CUSTOM_BYPASS: - return "ALARM_STATE_ARMED_CUSTOM_BYPASS"; + return ESPHOME_PSTR("ALARM_STATE_ARMED_CUSTOM_BYPASS"); case enums::ALARM_STATE_PENDING: - return "ALARM_STATE_PENDING"; + return ESPHOME_PSTR("ALARM_STATE_PENDING"); case enums::ALARM_STATE_ARMING: - return "ALARM_STATE_ARMING"; + return ESPHOME_PSTR("ALARM_STATE_ARMING"); case enums::ALARM_STATE_DISARMING: - return "ALARM_STATE_DISARMING"; + return ESPHOME_PSTR("ALARM_STATE_DISARMING"); case enums::ALARM_STATE_TRIGGERED: - return "ALARM_STATE_TRIGGERED"; + return ESPHOME_PSTR("ALARM_STATE_TRIGGERED"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::AlarmControlPanelStateCommand>(enums::AlarmControlPanelStateCommand value) { switch (value) { case enums::ALARM_CONTROL_PANEL_DISARM: - return "ALARM_CONTROL_PANEL_DISARM"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_DISARM"); case enums::ALARM_CONTROL_PANEL_ARM_AWAY: - return "ALARM_CONTROL_PANEL_ARM_AWAY"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_ARM_AWAY"); case enums::ALARM_CONTROL_PANEL_ARM_HOME: - return "ALARM_CONTROL_PANEL_ARM_HOME"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_ARM_HOME"); case enums::ALARM_CONTROL_PANEL_ARM_NIGHT: - return "ALARM_CONTROL_PANEL_ARM_NIGHT"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_ARM_NIGHT"); case enums::ALARM_CONTROL_PANEL_ARM_VACATION: - return "ALARM_CONTROL_PANEL_ARM_VACATION"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_ARM_VACATION"); case enums::ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS: - return "ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS"); case enums::ALARM_CONTROL_PANEL_TRIGGER: - return "ALARM_CONTROL_PANEL_TRIGGER"; + return ESPHOME_PSTR("ALARM_CONTROL_PANEL_TRIGGER"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -714,11 +739,11 @@ const char *proto_enum_to_string<enums::AlarmControlPanelStateCommand>(enums::Al template<> const char *proto_enum_to_string<enums::TextMode>(enums::TextMode value) { switch (value) { case enums::TEXT_MODE_TEXT: - return "TEXT_MODE_TEXT"; + return ESPHOME_PSTR("TEXT_MODE_TEXT"); case enums::TEXT_MODE_PASSWORD: - return "TEXT_MODE_PASSWORD"; + return ESPHOME_PSTR("TEXT_MODE_PASSWORD"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -726,13 +751,13 @@ template<> const char *proto_enum_to_string<enums::TextMode>(enums::TextMode val template<> const char *proto_enum_to_string<enums::ValveOperation>(enums::ValveOperation value) { switch (value) { case enums::VALVE_OPERATION_IDLE: - return "VALVE_OPERATION_IDLE"; + return ESPHOME_PSTR("VALVE_OPERATION_IDLE"); case enums::VALVE_OPERATION_IS_OPENING: - return "VALVE_OPERATION_IS_OPENING"; + return ESPHOME_PSTR("VALVE_OPERATION_IS_OPENING"); case enums::VALVE_OPERATION_IS_CLOSING: - return "VALVE_OPERATION_IS_CLOSING"; + return ESPHOME_PSTR("VALVE_OPERATION_IS_CLOSING"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -740,13 +765,13 @@ template<> const char *proto_enum_to_string<enums::ValveOperation>(enums::ValveO template<> const char *proto_enum_to_string<enums::UpdateCommand>(enums::UpdateCommand value) { switch (value) { case enums::UPDATE_COMMAND_NONE: - return "UPDATE_COMMAND_NONE"; + return ESPHOME_PSTR("UPDATE_COMMAND_NONE"); case enums::UPDATE_COMMAND_UPDATE: - return "UPDATE_COMMAND_UPDATE"; + return ESPHOME_PSTR("UPDATE_COMMAND_UPDATE"); case enums::UPDATE_COMMAND_CHECK: - return "UPDATE_COMMAND_CHECK"; + return ESPHOME_PSTR("UPDATE_COMMAND_CHECK"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -754,13 +779,13 @@ template<> const char *proto_enum_to_string<enums::UpdateCommand>(enums::UpdateC template<> const char *proto_enum_to_string<enums::ZWaveProxyRequestType>(enums::ZWaveProxyRequestType value) { switch (value) { case enums::ZWAVE_PROXY_REQUEST_TYPE_SUBSCRIBE: - return "ZWAVE_PROXY_REQUEST_TYPE_SUBSCRIBE"; + return ESPHOME_PSTR("ZWAVE_PROXY_REQUEST_TYPE_SUBSCRIBE"); case enums::ZWAVE_PROXY_REQUEST_TYPE_UNSUBSCRIBE: - return "ZWAVE_PROXY_REQUEST_TYPE_UNSUBSCRIBE"; + return ESPHOME_PSTR("ZWAVE_PROXY_REQUEST_TYPE_UNSUBSCRIBE"); case enums::ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE: - return "ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE"; + return ESPHOME_PSTR("ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif @@ -768,165 +793,165 @@ template<> const char *proto_enum_to_string<enums::ZWaveProxyRequestType>(enums: template<> const char *proto_enum_to_string<enums::SerialProxyParity>(enums::SerialProxyParity value) { switch (value) { case enums::SERIAL_PROXY_PARITY_NONE: - return "SERIAL_PROXY_PARITY_NONE"; + return ESPHOME_PSTR("SERIAL_PROXY_PARITY_NONE"); case enums::SERIAL_PROXY_PARITY_EVEN: - return "SERIAL_PROXY_PARITY_EVEN"; + return ESPHOME_PSTR("SERIAL_PROXY_PARITY_EVEN"); case enums::SERIAL_PROXY_PARITY_ODD: - return "SERIAL_PROXY_PARITY_ODD"; + return ESPHOME_PSTR("SERIAL_PROXY_PARITY_ODD"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::SerialProxyRequestType>(enums::SerialProxyRequestType value) { switch (value) { case enums::SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE: - return "SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE"; + return ESPHOME_PSTR("SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE"); case enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: - return "SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE"; + return ESPHOME_PSTR("SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE"); case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH: - return "SERIAL_PROXY_REQUEST_TYPE_FLUSH"; + return ESPHOME_PSTR("SERIAL_PROXY_REQUEST_TYPE_FLUSH"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } template<> const char *proto_enum_to_string<enums::SerialProxyStatus>(enums::SerialProxyStatus value) { switch (value) { case enums::SERIAL_PROXY_STATUS_OK: - return "SERIAL_PROXY_STATUS_OK"; + return ESPHOME_PSTR("SERIAL_PROXY_STATUS_OK"); case enums::SERIAL_PROXY_STATUS_ASSUMED_SUCCESS: - return "SERIAL_PROXY_STATUS_ASSUMED_SUCCESS"; + return ESPHOME_PSTR("SERIAL_PROXY_STATUS_ASSUMED_SUCCESS"); case enums::SERIAL_PROXY_STATUS_ERROR: - return "SERIAL_PROXY_STATUS_ERROR"; + return ESPHOME_PSTR("SERIAL_PROXY_STATUS_ERROR"); case enums::SERIAL_PROXY_STATUS_TIMEOUT: - return "SERIAL_PROXY_STATUS_TIMEOUT"; + return ESPHOME_PSTR("SERIAL_PROXY_STATUS_TIMEOUT"); case enums::SERIAL_PROXY_STATUS_NOT_SUPPORTED: - return "SERIAL_PROXY_STATUS_NOT_SUPPORTED"; + return ESPHOME_PSTR("SERIAL_PROXY_STATUS_NOT_SUPPORTED"); default: - return "UNKNOWN"; + return ESPHOME_PSTR("UNKNOWN"); } } #endif const char *HelloRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HelloRequest"); - dump_field(out, "client_info", this->client_info); - dump_field(out, "api_version_major", this->api_version_major); - dump_field(out, "api_version_minor", this->api_version_minor); + MessageDumpHelper helper(out, ESPHOME_PSTR("HelloRequest")); + dump_field(out, ESPHOME_PSTR("client_info"), this->client_info); + dump_field(out, ESPHOME_PSTR("api_version_major"), this->api_version_major); + dump_field(out, ESPHOME_PSTR("api_version_minor"), this->api_version_minor); return out.c_str(); } const char *HelloResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HelloResponse"); - dump_field(out, "api_version_major", this->api_version_major); - dump_field(out, "api_version_minor", this->api_version_minor); - dump_field(out, "server_info", this->server_info); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("HelloResponse")); + dump_field(out, ESPHOME_PSTR("api_version_major"), this->api_version_major); + dump_field(out, ESPHOME_PSTR("api_version_minor"), this->api_version_minor); + dump_field(out, ESPHOME_PSTR("server_info"), this->server_info); + dump_field(out, ESPHOME_PSTR("name"), this->name); return out.c_str(); } const char *DisconnectRequest::dump_to(DumpBuffer &out) const { - out.append("DisconnectRequest {}"); + out.append_p(ESPHOME_PSTR("DisconnectRequest {}")); return out.c_str(); } const char *DisconnectResponse::dump_to(DumpBuffer &out) const { - out.append("DisconnectResponse {}"); + out.append_p(ESPHOME_PSTR("DisconnectResponse {}")); return out.c_str(); } const char *PingRequest::dump_to(DumpBuffer &out) const { - out.append("PingRequest {}"); + out.append_p(ESPHOME_PSTR("PingRequest {}")); return out.c_str(); } const char *PingResponse::dump_to(DumpBuffer &out) const { - out.append("PingResponse {}"); + out.append_p(ESPHOME_PSTR("PingResponse {}")); return out.c_str(); } #ifdef USE_AREAS const char *AreaInfo::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "AreaInfo"); - dump_field(out, "area_id", this->area_id); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("AreaInfo")); + dump_field(out, ESPHOME_PSTR("area_id"), this->area_id); + dump_field(out, ESPHOME_PSTR("name"), this->name); return out.c_str(); } #endif #ifdef USE_DEVICES const char *DeviceInfo::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DeviceInfo"); - dump_field(out, "device_id", this->device_id); - dump_field(out, "name", this->name); - dump_field(out, "area_id", this->area_id); + MessageDumpHelper helper(out, ESPHOME_PSTR("DeviceInfo")); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("area_id"), this->area_id); return out.c_str(); } #endif #ifdef USE_SERIAL_PROXY const char *SerialProxyInfo::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyInfo"); - dump_field(out, "name", this->name); - dump_field(out, "port_type", static_cast<enums::SerialProxyPortType>(this->port_type)); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyInfo")); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("port_type"), static_cast<enums::SerialProxyPortType>(this->port_type)); return out.c_str(); } #endif const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DeviceInfoResponse"); - dump_field(out, "name", this->name); - dump_field(out, "mac_address", this->mac_address); - dump_field(out, "esphome_version", this->esphome_version); - dump_field(out, "compilation_time", this->compilation_time); - dump_field(out, "model", this->model); + MessageDumpHelper helper(out, ESPHOME_PSTR("DeviceInfoResponse")); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("mac_address"), this->mac_address); + dump_field(out, ESPHOME_PSTR("esphome_version"), this->esphome_version); + dump_field(out, ESPHOME_PSTR("compilation_time"), this->compilation_time); + dump_field(out, ESPHOME_PSTR("model"), this->model); #ifdef USE_DEEP_SLEEP - dump_field(out, "has_deep_sleep", this->has_deep_sleep); + dump_field(out, ESPHOME_PSTR("has_deep_sleep"), this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - dump_field(out, "project_name", this->project_name); + dump_field(out, ESPHOME_PSTR("project_name"), this->project_name); #endif #ifdef ESPHOME_PROJECT_NAME - dump_field(out, "project_version", this->project_version); + dump_field(out, ESPHOME_PSTR("project_version"), this->project_version); #endif #ifdef USE_WEBSERVER - dump_field(out, "webserver_port", this->webserver_port); + dump_field(out, ESPHOME_PSTR("webserver_port"), this->webserver_port); #endif #ifdef USE_BLUETOOTH_PROXY - dump_field(out, "bluetooth_proxy_feature_flags", this->bluetooth_proxy_feature_flags); + dump_field(out, ESPHOME_PSTR("bluetooth_proxy_feature_flags"), this->bluetooth_proxy_feature_flags); #endif - dump_field(out, "manufacturer", this->manufacturer); - dump_field(out, "friendly_name", this->friendly_name); + dump_field(out, ESPHOME_PSTR("manufacturer"), this->manufacturer); + dump_field(out, ESPHOME_PSTR("friendly_name"), this->friendly_name); #ifdef USE_VOICE_ASSISTANT - dump_field(out, "voice_assistant_feature_flags", this->voice_assistant_feature_flags); + dump_field(out, ESPHOME_PSTR("voice_assistant_feature_flags"), this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - dump_field(out, "suggested_area", this->suggested_area); + dump_field(out, ESPHOME_PSTR("suggested_area"), this->suggested_area); #endif #ifdef USE_BLUETOOTH_PROXY - dump_field(out, "bluetooth_mac_address", this->bluetooth_mac_address); + dump_field(out, ESPHOME_PSTR("bluetooth_mac_address"), this->bluetooth_mac_address); #endif #ifdef USE_API_NOISE - dump_field(out, "api_encryption_supported", this->api_encryption_supported); + dump_field(out, ESPHOME_PSTR("api_encryption_supported"), this->api_encryption_supported); #endif #ifdef USE_DEVICES for (const auto &it : this->devices) { - out.append(" devices: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("devices")).append(": "); it.dump_to(out); out.append("\n"); } #endif #ifdef USE_AREAS for (const auto &it : this->areas) { - out.append(" areas: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("areas")).append(": "); it.dump_to(out); out.append("\n"); } #endif #ifdef USE_AREAS - out.append(" area: "); + out.append(2, ' ').append_p(ESPHOME_PSTR("area")).append(": "); this->area.dump_to(out); out.append("\n"); #endif #ifdef USE_ZWAVE_PROXY - dump_field(out, "zwave_proxy_feature_flags", this->zwave_proxy_feature_flags); + dump_field(out, ESPHOME_PSTR("zwave_proxy_feature_flags"), this->zwave_proxy_feature_flags); #endif #ifdef USE_ZWAVE_PROXY - dump_field(out, "zwave_home_id", this->zwave_home_id); + dump_field(out, ESPHOME_PSTR("zwave_home_id"), this->zwave_home_id); #endif #ifdef USE_SERIAL_PROXY for (const auto &it : this->serial_proxies) { - out.append(" serial_proxies: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("serial_proxies")).append(": "); it.dump_to(out); out.append("\n"); } @@ -934,1720 +959,1720 @@ const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const { return out.c_str(); } const char *ListEntitiesDoneResponse::dump_to(DumpBuffer &out) const { - out.append("ListEntitiesDoneResponse {}"); + out.append_p(ESPHOME_PSTR("ListEntitiesDoneResponse {}")); return out.c_str(); } #ifdef USE_BINARY_SENSOR const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesBinarySensorResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); - dump_field(out, "device_class", this->device_class); - dump_field(out, "is_status_binary_sensor", this->is_status_binary_sensor); - dump_field(out, "disabled_by_default", this->disabled_by_default); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); + dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *BinarySensorStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BinarySensorStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("BinarySensorStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_COVER const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesCoverResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); - dump_field(out, "assumed_state", this->assumed_state); - dump_field(out, "supports_position", this->supports_position); - dump_field(out, "supports_tilt", this->supports_tilt); - dump_field(out, "device_class", this->device_class); - dump_field(out, "disabled_by_default", this->disabled_by_default); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state); + dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position); + dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "supports_stop", this->supports_stop); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("supports_stop"), this->supports_stop); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *CoverStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "CoverStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "position", this->position); - dump_field(out, "tilt", this->tilt); - dump_field(out, "current_operation", static_cast<enums::CoverOperation>(this->current_operation)); + MessageDumpHelper helper(out, ESPHOME_PSTR("CoverStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("position"), this->position); + dump_field(out, ESPHOME_PSTR("tilt"), this->tilt); + dump_field(out, ESPHOME_PSTR("current_operation"), static_cast<enums::CoverOperation>(this->current_operation)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *CoverCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "CoverCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_position", this->has_position); - dump_field(out, "position", this->position); - dump_field(out, "has_tilt", this->has_tilt); - dump_field(out, "tilt", this->tilt); - dump_field(out, "stop", this->stop); + MessageDumpHelper helper(out, ESPHOME_PSTR("CoverCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_position"), this->has_position); + dump_field(out, ESPHOME_PSTR("position"), this->position); + dump_field(out, ESPHOME_PSTR("has_tilt"), this->has_tilt); + dump_field(out, ESPHOME_PSTR("tilt"), this->tilt); + dump_field(out, ESPHOME_PSTR("stop"), this->stop); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_FAN const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesFanResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); - dump_field(out, "supports_oscillation", this->supports_oscillation); - dump_field(out, "supports_speed", this->supports_speed); - dump_field(out, "supports_direction", this->supports_direction); - dump_field(out, "supported_speed_count", this->supported_speed_count); - dump_field(out, "disabled_by_default", this->disabled_by_default); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation); + dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed); + dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction); + dump_field(out, ESPHOME_PSTR("supported_speed_count"), this->supported_speed_count); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); for (const auto &it : *this->supported_preset_modes) { - dump_field(out, "supported_preset_modes", it, 4); + dump_field(out, ESPHOME_PSTR("supported_preset_modes"), it, 4); } #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *FanStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "FanStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "oscillating", this->oscillating); - dump_field(out, "direction", static_cast<enums::FanDirection>(this->direction)); - dump_field(out, "speed_level", this->speed_level); - dump_field(out, "preset_mode", this->preset_mode); + MessageDumpHelper helper(out, ESPHOME_PSTR("FanStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("oscillating"), this->oscillating); + dump_field(out, ESPHOME_PSTR("direction"), static_cast<enums::FanDirection>(this->direction)); + dump_field(out, ESPHOME_PSTR("speed_level"), this->speed_level); + dump_field(out, ESPHOME_PSTR("preset_mode"), this->preset_mode); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *FanCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "FanCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_state", this->has_state); - dump_field(out, "state", this->state); - dump_field(out, "has_oscillating", this->has_oscillating); - dump_field(out, "oscillating", this->oscillating); - dump_field(out, "has_direction", this->has_direction); - dump_field(out, "direction", static_cast<enums::FanDirection>(this->direction)); - dump_field(out, "has_speed_level", this->has_speed_level); - dump_field(out, "speed_level", this->speed_level); - dump_field(out, "has_preset_mode", this->has_preset_mode); - dump_field(out, "preset_mode", this->preset_mode); + MessageDumpHelper helper(out, ESPHOME_PSTR("FanCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_state"), this->has_state); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("has_oscillating"), this->has_oscillating); + dump_field(out, ESPHOME_PSTR("oscillating"), this->oscillating); + dump_field(out, ESPHOME_PSTR("has_direction"), this->has_direction); + dump_field(out, ESPHOME_PSTR("direction"), static_cast<enums::FanDirection>(this->direction)); + dump_field(out, ESPHOME_PSTR("has_speed_level"), this->has_speed_level); + dump_field(out, ESPHOME_PSTR("speed_level"), this->speed_level); + dump_field(out, ESPHOME_PSTR("has_preset_mode"), this->has_preset_mode); + dump_field(out, ESPHOME_PSTR("preset_mode"), this->preset_mode); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_LIGHT const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesLightResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); for (const auto &it : *this->supported_color_modes) { - dump_field(out, "supported_color_modes", static_cast<enums::ColorMode>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4); } - dump_field(out, "min_mireds", this->min_mireds); - dump_field(out, "max_mireds", this->max_mireds); + dump_field(out, ESPHOME_PSTR("min_mireds"), this->min_mireds); + dump_field(out, ESPHOME_PSTR("max_mireds"), this->max_mireds); for (const auto &it : *this->effects) { - dump_field(out, "effects", it, 4); + dump_field(out, ESPHOME_PSTR("effects"), it, 4); } - dump_field(out, "disabled_by_default", this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *LightStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "LightStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "brightness", this->brightness); - dump_field(out, "color_mode", static_cast<enums::ColorMode>(this->color_mode)); - dump_field(out, "color_brightness", this->color_brightness); - dump_field(out, "red", this->red); - dump_field(out, "green", this->green); - dump_field(out, "blue", this->blue); - dump_field(out, "white", this->white); - dump_field(out, "color_temperature", this->color_temperature); - dump_field(out, "cold_white", this->cold_white); - dump_field(out, "warm_white", this->warm_white); - dump_field(out, "effect", this->effect); + MessageDumpHelper helper(out, ESPHOME_PSTR("LightStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("brightness"), this->brightness); + dump_field(out, ESPHOME_PSTR("color_mode"), static_cast<enums::ColorMode>(this->color_mode)); + dump_field(out, ESPHOME_PSTR("color_brightness"), this->color_brightness); + dump_field(out, ESPHOME_PSTR("red"), this->red); + dump_field(out, ESPHOME_PSTR("green"), this->green); + dump_field(out, ESPHOME_PSTR("blue"), this->blue); + dump_field(out, ESPHOME_PSTR("white"), this->white); + dump_field(out, ESPHOME_PSTR("color_temperature"), this->color_temperature); + dump_field(out, ESPHOME_PSTR("cold_white"), this->cold_white); + dump_field(out, ESPHOME_PSTR("warm_white"), this->warm_white); + dump_field(out, ESPHOME_PSTR("effect"), this->effect); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *LightCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "LightCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_state", this->has_state); - dump_field(out, "state", this->state); - dump_field(out, "has_brightness", this->has_brightness); - dump_field(out, "brightness", this->brightness); - dump_field(out, "has_color_mode", this->has_color_mode); - dump_field(out, "color_mode", static_cast<enums::ColorMode>(this->color_mode)); - dump_field(out, "has_color_brightness", this->has_color_brightness); - dump_field(out, "color_brightness", this->color_brightness); - dump_field(out, "has_rgb", this->has_rgb); - dump_field(out, "red", this->red); - dump_field(out, "green", this->green); - dump_field(out, "blue", this->blue); - dump_field(out, "has_white", this->has_white); - dump_field(out, "white", this->white); - dump_field(out, "has_color_temperature", this->has_color_temperature); - dump_field(out, "color_temperature", this->color_temperature); - dump_field(out, "has_cold_white", this->has_cold_white); - dump_field(out, "cold_white", this->cold_white); - dump_field(out, "has_warm_white", this->has_warm_white); - dump_field(out, "warm_white", this->warm_white); - dump_field(out, "has_transition_length", this->has_transition_length); - dump_field(out, "transition_length", this->transition_length); - dump_field(out, "has_flash_length", this->has_flash_length); - dump_field(out, "flash_length", this->flash_length); - dump_field(out, "has_effect", this->has_effect); - dump_field(out, "effect", this->effect); + MessageDumpHelper helper(out, ESPHOME_PSTR("LightCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_state"), this->has_state); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("has_brightness"), this->has_brightness); + dump_field(out, ESPHOME_PSTR("brightness"), this->brightness); + dump_field(out, ESPHOME_PSTR("has_color_mode"), this->has_color_mode); + dump_field(out, ESPHOME_PSTR("color_mode"), static_cast<enums::ColorMode>(this->color_mode)); + dump_field(out, ESPHOME_PSTR("has_color_brightness"), this->has_color_brightness); + dump_field(out, ESPHOME_PSTR("color_brightness"), this->color_brightness); + dump_field(out, ESPHOME_PSTR("has_rgb"), this->has_rgb); + dump_field(out, ESPHOME_PSTR("red"), this->red); + dump_field(out, ESPHOME_PSTR("green"), this->green); + dump_field(out, ESPHOME_PSTR("blue"), this->blue); + dump_field(out, ESPHOME_PSTR("has_white"), this->has_white); + dump_field(out, ESPHOME_PSTR("white"), this->white); + dump_field(out, ESPHOME_PSTR("has_color_temperature"), this->has_color_temperature); + dump_field(out, ESPHOME_PSTR("color_temperature"), this->color_temperature); + dump_field(out, ESPHOME_PSTR("has_cold_white"), this->has_cold_white); + dump_field(out, ESPHOME_PSTR("cold_white"), this->cold_white); + dump_field(out, ESPHOME_PSTR("has_warm_white"), this->has_warm_white); + dump_field(out, ESPHOME_PSTR("warm_white"), this->warm_white); + dump_field(out, ESPHOME_PSTR("has_transition_length"), this->has_transition_length); + dump_field(out, ESPHOME_PSTR("transition_length"), this->transition_length); + dump_field(out, ESPHOME_PSTR("has_flash_length"), this->has_flash_length); + dump_field(out, ESPHOME_PSTR("flash_length"), this->flash_length); + dump_field(out, ESPHOME_PSTR("has_effect"), this->has_effect); + dump_field(out, ESPHOME_PSTR("effect"), this->effect); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_SENSOR const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesSensorResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "unit_of_measurement", this->unit_of_measurement); - dump_field(out, "accuracy_decimals", this->accuracy_decimals); - dump_field(out, "force_update", this->force_update); - dump_field(out, "device_class", this->device_class); - dump_field(out, "state_class", static_cast<enums::SensorStateClass>(this->state_class)); - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("unit_of_measurement"), this->unit_of_measurement); + dump_field(out, ESPHOME_PSTR("accuracy_decimals"), this->accuracy_decimals); + dump_field(out, ESPHOME_PSTR("force_update"), this->force_update); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); + dump_field(out, ESPHOME_PSTR("state_class"), static_cast<enums::SensorStateClass>(this->state_class)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SensorStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SensorStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SensorStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_SWITCH const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesSwitchResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "assumed_state", this->assumed_state); - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SwitchStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SwitchStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SwitchStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SwitchCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SwitchCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SwitchCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_TEXT_SENSOR const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesTextSensorResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *TextSensorStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "TextSensorStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("TextSensorStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif const char *SubscribeLogsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SubscribeLogsRequest"); - dump_field(out, "level", static_cast<enums::LogLevel>(this->level)); - dump_field(out, "dump_config", this->dump_config); + MessageDumpHelper helper(out, ESPHOME_PSTR("SubscribeLogsRequest")); + dump_field(out, ESPHOME_PSTR("level"), static_cast<enums::LogLevel>(this->level)); + dump_field(out, ESPHOME_PSTR("dump_config"), this->dump_config); return out.c_str(); } const char *SubscribeLogsResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SubscribeLogsResponse"); - dump_field(out, "level", static_cast<enums::LogLevel>(this->level)); - dump_bytes_field(out, "message", this->message_ptr_, this->message_len_); + MessageDumpHelper helper(out, ESPHOME_PSTR("SubscribeLogsResponse")); + dump_field(out, ESPHOME_PSTR("level"), static_cast<enums::LogLevel>(this->level)); + dump_bytes_field(out, ESPHOME_PSTR("message"), this->message_ptr_, this->message_len_); return out.c_str(); } #ifdef USE_API_NOISE const char *NoiseEncryptionSetKeyRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "NoiseEncryptionSetKeyRequest"); - dump_bytes_field(out, "key", this->key, this->key_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("NoiseEncryptionSetKeyRequest")); + dump_bytes_field(out, ESPHOME_PSTR("key"), this->key, this->key_len); return out.c_str(); } const char *NoiseEncryptionSetKeyResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "NoiseEncryptionSetKeyResponse"); - dump_field(out, "success", this->success); + MessageDumpHelper helper(out, ESPHOME_PSTR("NoiseEncryptionSetKeyResponse")); + dump_field(out, ESPHOME_PSTR("success"), this->success); return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES const char *HomeassistantServiceMap::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HomeassistantServiceMap"); - dump_field(out, "key", this->key); - dump_field(out, "value", this->value); + MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantServiceMap")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("value"), this->value); return out.c_str(); } const char *HomeassistantActionRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HomeassistantActionRequest"); - dump_field(out, "service", this->service); + MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantActionRequest")); + dump_field(out, ESPHOME_PSTR("service"), this->service); for (const auto &it : this->data) { - out.append(" data: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("data")).append(": "); it.dump_to(out); out.append("\n"); } for (const auto &it : this->data_template) { - out.append(" data_template: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("data_template")).append(": "); it.dump_to(out); out.append("\n"); } for (const auto &it : this->variables) { - out.append(" variables: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("variables")).append(": "); it.dump_to(out); out.append("\n"); } - dump_field(out, "is_event", this->is_event); + dump_field(out, ESPHOME_PSTR("is_event"), this->is_event); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - dump_field(out, "call_id", this->call_id); + dump_field(out, ESPHOME_PSTR("call_id"), this->call_id); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - dump_field(out, "wants_response", this->wants_response); + dump_field(out, ESPHOME_PSTR("wants_response"), this->wants_response); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - dump_field(out, "response_template", this->response_template); + dump_field(out, ESPHOME_PSTR("response_template"), this->response_template); #endif return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES const char *HomeassistantActionResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HomeassistantActionResponse"); - dump_field(out, "call_id", this->call_id); - dump_field(out, "success", this->success); - dump_field(out, "error_message", this->error_message); + MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantActionResponse")); + dump_field(out, ESPHOME_PSTR("call_id"), this->call_id); + dump_field(out, ESPHOME_PSTR("success"), this->success); + dump_field(out, ESPHOME_PSTR("error_message"), this->error_message); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); + dump_bytes_field(out, ESPHOME_PSTR("response_data"), this->response_data, this->response_data_len); #endif return out.c_str(); } #endif #ifdef USE_API_HOMEASSISTANT_STATES const char *SubscribeHomeAssistantStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SubscribeHomeAssistantStateResponse"); - dump_field(out, "entity_id", this->entity_id); - dump_field(out, "attribute", this->attribute); - dump_field(out, "once", this->once); + MessageDumpHelper helper(out, ESPHOME_PSTR("SubscribeHomeAssistantStateResponse")); + dump_field(out, ESPHOME_PSTR("entity_id"), this->entity_id); + dump_field(out, ESPHOME_PSTR("attribute"), this->attribute); + dump_field(out, ESPHOME_PSTR("once"), this->once); return out.c_str(); } const char *HomeAssistantStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "HomeAssistantStateResponse"); - dump_field(out, "entity_id", this->entity_id); - dump_field(out, "state", this->state); - dump_field(out, "attribute", this->attribute); + MessageDumpHelper helper(out, ESPHOME_PSTR("HomeAssistantStateResponse")); + dump_field(out, ESPHOME_PSTR("entity_id"), this->entity_id); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("attribute"), this->attribute); return out.c_str(); } #endif const char *GetTimeRequest::dump_to(DumpBuffer &out) const { - out.append("GetTimeRequest {}"); + out.append_p(ESPHOME_PSTR("GetTimeRequest {}")); return out.c_str(); } const char *DSTRule::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DSTRule"); - dump_field(out, "time_seconds", this->time_seconds); - dump_field(out, "day", this->day); - dump_field(out, "type", static_cast<enums::DSTRuleType>(this->type)); - dump_field(out, "month", this->month); - dump_field(out, "week", this->week); - dump_field(out, "day_of_week", this->day_of_week); + MessageDumpHelper helper(out, ESPHOME_PSTR("DSTRule")); + dump_field(out, ESPHOME_PSTR("time_seconds"), this->time_seconds); + dump_field(out, ESPHOME_PSTR("day"), this->day); + dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::DSTRuleType>(this->type)); + dump_field(out, ESPHOME_PSTR("month"), this->month); + dump_field(out, ESPHOME_PSTR("week"), this->week); + dump_field(out, ESPHOME_PSTR("day_of_week"), this->day_of_week); return out.c_str(); } const char *ParsedTimezone::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ParsedTimezone"); - dump_field(out, "std_offset_seconds", this->std_offset_seconds); - dump_field(out, "dst_offset_seconds", this->dst_offset_seconds); - out.append(" dst_start: "); + MessageDumpHelper helper(out, ESPHOME_PSTR("ParsedTimezone")); + dump_field(out, ESPHOME_PSTR("std_offset_seconds"), this->std_offset_seconds); + dump_field(out, ESPHOME_PSTR("dst_offset_seconds"), this->dst_offset_seconds); + out.append(2, ' ').append_p(ESPHOME_PSTR("dst_start")).append(": "); this->dst_start.dump_to(out); out.append("\n"); - out.append(" dst_end: "); + out.append(2, ' ').append_p(ESPHOME_PSTR("dst_end")).append(": "); this->dst_end.dump_to(out); out.append("\n"); return out.c_str(); } const char *GetTimeResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "GetTimeResponse"); - dump_field(out, "epoch_seconds", this->epoch_seconds); - dump_field(out, "timezone", this->timezone); - out.append(" parsed_timezone: "); + MessageDumpHelper helper(out, ESPHOME_PSTR("GetTimeResponse")); + dump_field(out, ESPHOME_PSTR("epoch_seconds"), this->epoch_seconds); + dump_field(out, ESPHOME_PSTR("timezone"), this->timezone); + out.append(2, ' ').append_p(ESPHOME_PSTR("parsed_timezone")).append(": "); this->parsed_timezone.dump_to(out); out.append("\n"); return out.c_str(); } #ifdef USE_API_USER_DEFINED_ACTIONS const char *ListEntitiesServicesArgument::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesServicesArgument"); - dump_field(out, "name", this->name); - dump_field(out, "type", static_cast<enums::ServiceArgType>(this->type)); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesArgument")); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::ServiceArgType>(this->type)); return out.c_str(); } const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesServicesResponse"); - dump_field(out, "name", this->name); - dump_field(out, "key", this->key); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesResponse")); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("key"), this->key); for (const auto &it : this->args) { - out.append(" args: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("args")).append(": "); it.dump_to(out); out.append("\n"); } - dump_field(out, "supports_response", static_cast<enums::SupportsResponseType>(this->supports_response)); + dump_field(out, ESPHOME_PSTR("supports_response"), static_cast<enums::SupportsResponseType>(this->supports_response)); return out.c_str(); } const char *ExecuteServiceArgument::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ExecuteServiceArgument"); - dump_field(out, "bool_", this->bool_); - dump_field(out, "legacy_int", this->legacy_int); - dump_field(out, "float_", this->float_); - dump_field(out, "string_", this->string_); - dump_field(out, "int_", this->int_); + MessageDumpHelper helper(out, ESPHOME_PSTR("ExecuteServiceArgument")); + dump_field(out, ESPHOME_PSTR("bool_"), this->bool_); + dump_field(out, ESPHOME_PSTR("legacy_int"), this->legacy_int); + dump_field(out, ESPHOME_PSTR("float_"), this->float_); + dump_field(out, ESPHOME_PSTR("string_"), this->string_); + dump_field(out, ESPHOME_PSTR("int_"), this->int_); for (const auto it : this->bool_array) { - dump_field(out, "bool_array", static_cast<bool>(it), 4); + dump_field(out, ESPHOME_PSTR("bool_array"), static_cast<bool>(it), 4); } for (const auto &it : this->int_array) { - dump_field(out, "int_array", it, 4); + dump_field(out, ESPHOME_PSTR("int_array"), it, 4); } for (const auto &it : this->float_array) { - dump_field(out, "float_array", it, 4); + dump_field(out, ESPHOME_PSTR("float_array"), it, 4); } for (const auto &it : this->string_array) { - dump_field(out, "string_array", it, 4); + dump_field(out, ESPHOME_PSTR("string_array"), it, 4); } return out.c_str(); } const char *ExecuteServiceRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ExecuteServiceRequest"); - dump_field(out, "key", this->key); + MessageDumpHelper helper(out, ESPHOME_PSTR("ExecuteServiceRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); for (const auto &it : this->args) { - out.append(" args: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("args")).append(": "); it.dump_to(out); out.append("\n"); } #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - dump_field(out, "call_id", this->call_id); + dump_field(out, ESPHOME_PSTR("call_id"), this->call_id); #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - dump_field(out, "return_response", this->return_response); + dump_field(out, ESPHOME_PSTR("return_response"), this->return_response); #endif return out.c_str(); } #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES const char *ExecuteServiceResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ExecuteServiceResponse"); - dump_field(out, "call_id", this->call_id); - dump_field(out, "success", this->success); - dump_field(out, "error_message", this->error_message); + MessageDumpHelper helper(out, ESPHOME_PSTR("ExecuteServiceResponse")); + dump_field(out, ESPHOME_PSTR("call_id"), this->call_id); + dump_field(out, ESPHOME_PSTR("success"), this->success); + dump_field(out, ESPHOME_PSTR("error_message"), this->error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - dump_bytes_field(out, "response_data", this->response_data, this->response_data_len); + dump_bytes_field(out, ESPHOME_PSTR("response_data"), this->response_data, this->response_data_len); #endif return out.c_str(); } #endif #ifdef USE_CAMERA const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesCameraResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); - dump_field(out, "disabled_by_default", this->disabled_by_default); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *CameraImageResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "CameraImageResponse"); - dump_field(out, "key", this->key); - dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); - dump_field(out, "done", this->done); + MessageDumpHelper helper(out, ESPHOME_PSTR("CameraImageResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data_ptr_, this->data_len_); + dump_field(out, ESPHOME_PSTR("done"), this->done); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *CameraImageRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "CameraImageRequest"); - dump_field(out, "single", this->single); - dump_field(out, "stream", this->stream); + MessageDumpHelper helper(out, ESPHOME_PSTR("CameraImageRequest")); + dump_field(out, ESPHOME_PSTR("single"), this->single); + dump_field(out, ESPHOME_PSTR("stream"), this->stream); return out.c_str(); } #endif #ifdef USE_CLIMATE const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesClimateResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); - dump_field(out, "supports_current_temperature", this->supports_current_temperature); - dump_field(out, "supports_two_point_target_temperature", this->supports_two_point_target_temperature); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature); + dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature); for (const auto &it : *this->supported_modes) { - dump_field(out, "supported_modes", static_cast<enums::ClimateMode>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_modes"), static_cast<enums::ClimateMode>(it), 4); } - dump_field(out, "visual_min_temperature", this->visual_min_temperature); - dump_field(out, "visual_max_temperature", this->visual_max_temperature); - dump_field(out, "visual_target_temperature_step", this->visual_target_temperature_step); - dump_field(out, "supports_action", this->supports_action); + dump_field(out, ESPHOME_PSTR("visual_min_temperature"), this->visual_min_temperature); + dump_field(out, ESPHOME_PSTR("visual_max_temperature"), this->visual_max_temperature); + dump_field(out, ESPHOME_PSTR("visual_target_temperature_step"), this->visual_target_temperature_step); + dump_field(out, ESPHOME_PSTR("supports_action"), this->supports_action); for (const auto &it : *this->supported_fan_modes) { - dump_field(out, "supported_fan_modes", static_cast<enums::ClimateFanMode>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_fan_modes"), static_cast<enums::ClimateFanMode>(it), 4); } for (const auto &it : *this->supported_swing_modes) { - dump_field(out, "supported_swing_modes", static_cast<enums::ClimateSwingMode>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_swing_modes"), static_cast<enums::ClimateSwingMode>(it), 4); } for (const auto &it : *this->supported_custom_fan_modes) { - dump_field(out, "supported_custom_fan_modes", it, 4); + dump_field(out, ESPHOME_PSTR("supported_custom_fan_modes"), it, 4); } for (const auto &it : *this->supported_presets) { - dump_field(out, "supported_presets", static_cast<enums::ClimatePreset>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_presets"), static_cast<enums::ClimatePreset>(it), 4); } for (const auto &it : *this->supported_custom_presets) { - dump_field(out, "supported_custom_presets", it, 4); + dump_field(out, ESPHOME_PSTR("supported_custom_presets"), it, 4); } - dump_field(out, "disabled_by_default", this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "visual_current_temperature_step", this->visual_current_temperature_step); - dump_field(out, "supports_current_humidity", this->supports_current_humidity); - dump_field(out, "supports_target_humidity", this->supports_target_humidity); - dump_field(out, "visual_min_humidity", this->visual_min_humidity); - dump_field(out, "visual_max_humidity", this->visual_max_humidity); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("visual_current_temperature_step"), this->visual_current_temperature_step); + dump_field(out, ESPHOME_PSTR("supports_current_humidity"), this->supports_current_humidity); + dump_field(out, ESPHOME_PSTR("supports_target_humidity"), this->supports_target_humidity); + dump_field(out, ESPHOME_PSTR("visual_min_humidity"), this->visual_min_humidity); + dump_field(out, ESPHOME_PSTR("visual_max_humidity"), this->visual_max_humidity); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "feature_flags", this->feature_flags); + dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags); return out.c_str(); } const char *ClimateStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ClimateStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "mode", static_cast<enums::ClimateMode>(this->mode)); - dump_field(out, "current_temperature", this->current_temperature); - dump_field(out, "target_temperature", this->target_temperature); - dump_field(out, "target_temperature_low", this->target_temperature_low); - dump_field(out, "target_temperature_high", this->target_temperature_high); - dump_field(out, "action", static_cast<enums::ClimateAction>(this->action)); - dump_field(out, "fan_mode", static_cast<enums::ClimateFanMode>(this->fan_mode)); - dump_field(out, "swing_mode", static_cast<enums::ClimateSwingMode>(this->swing_mode)); - dump_field(out, "custom_fan_mode", this->custom_fan_mode); - dump_field(out, "preset", static_cast<enums::ClimatePreset>(this->preset)); - dump_field(out, "custom_preset", this->custom_preset); - dump_field(out, "current_humidity", this->current_humidity); - dump_field(out, "target_humidity", this->target_humidity); + MessageDumpHelper helper(out, ESPHOME_PSTR("ClimateStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::ClimateMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("current_temperature"), this->current_temperature); + dump_field(out, ESPHOME_PSTR("target_temperature"), this->target_temperature); + dump_field(out, ESPHOME_PSTR("target_temperature_low"), this->target_temperature_low); + dump_field(out, ESPHOME_PSTR("target_temperature_high"), this->target_temperature_high); + dump_field(out, ESPHOME_PSTR("action"), static_cast<enums::ClimateAction>(this->action)); + dump_field(out, ESPHOME_PSTR("fan_mode"), static_cast<enums::ClimateFanMode>(this->fan_mode)); + dump_field(out, ESPHOME_PSTR("swing_mode"), static_cast<enums::ClimateSwingMode>(this->swing_mode)); + dump_field(out, ESPHOME_PSTR("custom_fan_mode"), this->custom_fan_mode); + dump_field(out, ESPHOME_PSTR("preset"), static_cast<enums::ClimatePreset>(this->preset)); + dump_field(out, ESPHOME_PSTR("custom_preset"), this->custom_preset); + dump_field(out, ESPHOME_PSTR("current_humidity"), this->current_humidity); + dump_field(out, ESPHOME_PSTR("target_humidity"), this->target_humidity); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *ClimateCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ClimateCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_mode", this->has_mode); - dump_field(out, "mode", static_cast<enums::ClimateMode>(this->mode)); - dump_field(out, "has_target_temperature", this->has_target_temperature); - dump_field(out, "target_temperature", this->target_temperature); - dump_field(out, "has_target_temperature_low", this->has_target_temperature_low); - dump_field(out, "target_temperature_low", this->target_temperature_low); - dump_field(out, "has_target_temperature_high", this->has_target_temperature_high); - dump_field(out, "target_temperature_high", this->target_temperature_high); - dump_field(out, "has_fan_mode", this->has_fan_mode); - dump_field(out, "fan_mode", static_cast<enums::ClimateFanMode>(this->fan_mode)); - dump_field(out, "has_swing_mode", this->has_swing_mode); - dump_field(out, "swing_mode", static_cast<enums::ClimateSwingMode>(this->swing_mode)); - dump_field(out, "has_custom_fan_mode", this->has_custom_fan_mode); - dump_field(out, "custom_fan_mode", this->custom_fan_mode); - dump_field(out, "has_preset", this->has_preset); - dump_field(out, "preset", static_cast<enums::ClimatePreset>(this->preset)); - dump_field(out, "has_custom_preset", this->has_custom_preset); - dump_field(out, "custom_preset", this->custom_preset); - dump_field(out, "has_target_humidity", this->has_target_humidity); - dump_field(out, "target_humidity", this->target_humidity); + MessageDumpHelper helper(out, ESPHOME_PSTR("ClimateCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_mode"), this->has_mode); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::ClimateMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("has_target_temperature"), this->has_target_temperature); + dump_field(out, ESPHOME_PSTR("target_temperature"), this->target_temperature); + dump_field(out, ESPHOME_PSTR("has_target_temperature_low"), this->has_target_temperature_low); + dump_field(out, ESPHOME_PSTR("target_temperature_low"), this->target_temperature_low); + dump_field(out, ESPHOME_PSTR("has_target_temperature_high"), this->has_target_temperature_high); + dump_field(out, ESPHOME_PSTR("target_temperature_high"), this->target_temperature_high); + dump_field(out, ESPHOME_PSTR("has_fan_mode"), this->has_fan_mode); + dump_field(out, ESPHOME_PSTR("fan_mode"), static_cast<enums::ClimateFanMode>(this->fan_mode)); + dump_field(out, ESPHOME_PSTR("has_swing_mode"), this->has_swing_mode); + dump_field(out, ESPHOME_PSTR("swing_mode"), static_cast<enums::ClimateSwingMode>(this->swing_mode)); + dump_field(out, ESPHOME_PSTR("has_custom_fan_mode"), this->has_custom_fan_mode); + dump_field(out, ESPHOME_PSTR("custom_fan_mode"), this->custom_fan_mode); + dump_field(out, ESPHOME_PSTR("has_preset"), this->has_preset); + dump_field(out, ESPHOME_PSTR("preset"), static_cast<enums::ClimatePreset>(this->preset)); + dump_field(out, ESPHOME_PSTR("has_custom_preset"), this->has_custom_preset); + dump_field(out, ESPHOME_PSTR("custom_preset"), this->custom_preset); + dump_field(out, ESPHOME_PSTR("has_target_humidity"), this->has_target_humidity); + dump_field(out, ESPHOME_PSTR("target_humidity"), this->target_humidity); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_WATER_HEATER const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesWaterHeaterResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "min_temperature", this->min_temperature); - dump_field(out, "max_temperature", this->max_temperature); - dump_field(out, "target_temperature_step", this->target_temperature_step); + dump_field(out, ESPHOME_PSTR("min_temperature"), this->min_temperature); + dump_field(out, ESPHOME_PSTR("max_temperature"), this->max_temperature); + dump_field(out, ESPHOME_PSTR("target_temperature_step"), this->target_temperature_step); for (const auto &it : *this->supported_modes) { - dump_field(out, "supported_modes", static_cast<enums::WaterHeaterMode>(it), 4); + dump_field(out, ESPHOME_PSTR("supported_modes"), static_cast<enums::WaterHeaterMode>(it), 4); } - dump_field(out, "supported_features", this->supported_features); + dump_field(out, ESPHOME_PSTR("supported_features"), this->supported_features); return out.c_str(); } const char *WaterHeaterStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "WaterHeaterStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "current_temperature", this->current_temperature); - dump_field(out, "target_temperature", this->target_temperature); - dump_field(out, "mode", static_cast<enums::WaterHeaterMode>(this->mode)); + MessageDumpHelper helper(out, ESPHOME_PSTR("WaterHeaterStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("current_temperature"), this->current_temperature); + dump_field(out, ESPHOME_PSTR("target_temperature"), this->target_temperature); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::WaterHeaterMode>(this->mode)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "state", this->state); - dump_field(out, "target_temperature_low", this->target_temperature_low); - dump_field(out, "target_temperature_high", this->target_temperature_high); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("target_temperature_low"), this->target_temperature_low); + dump_field(out, ESPHOME_PSTR("target_temperature_high"), this->target_temperature_high); return out.c_str(); } const char *WaterHeaterCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "WaterHeaterCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_fields", this->has_fields); - dump_field(out, "mode", static_cast<enums::WaterHeaterMode>(this->mode)); - dump_field(out, "target_temperature", this->target_temperature); + MessageDumpHelper helper(out, ESPHOME_PSTR("WaterHeaterCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_fields"), this->has_fields); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::WaterHeaterMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("target_temperature"), this->target_temperature); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "state", this->state); - dump_field(out, "target_temperature_low", this->target_temperature_low); - dump_field(out, "target_temperature_high", this->target_temperature_high); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("target_temperature_low"), this->target_temperature_low); + dump_field(out, ESPHOME_PSTR("target_temperature_high"), this->target_temperature_high); return out.c_str(); } #endif #ifdef USE_NUMBER const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesNumberResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "min_value", this->min_value); - dump_field(out, "max_value", this->max_value); - dump_field(out, "step", this->step); - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "unit_of_measurement", this->unit_of_measurement); - dump_field(out, "mode", static_cast<enums::NumberMode>(this->mode)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("min_value"), this->min_value); + dump_field(out, ESPHOME_PSTR("max_value"), this->max_value); + dump_field(out, ESPHOME_PSTR("step"), this->step); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("unit_of_measurement"), this->unit_of_measurement); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::NumberMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *NumberStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "NumberStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("NumberStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *NumberCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "NumberCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("NumberCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_SELECT const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesSelectResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif for (const auto &it : *this->options) { - dump_field(out, "options", it, 4); + dump_field(out, ESPHOME_PSTR("options"), it, 4); } - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SelectStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SelectStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SelectStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SelectCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SelectCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SelectCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_SIREN const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesSirenResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); for (const auto &it : *this->tones) { - dump_field(out, "tones", it, 4); + dump_field(out, ESPHOME_PSTR("tones"), it, 4); } - dump_field(out, "supports_duration", this->supports_duration); - dump_field(out, "supports_volume", this->supports_volume); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("supports_duration"), this->supports_duration); + dump_field(out, ESPHOME_PSTR("supports_volume"), this->supports_volume); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SirenStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SirenStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("SirenStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *SirenCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SirenCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_state", this->has_state); - dump_field(out, "state", this->state); - dump_field(out, "has_tone", this->has_tone); - dump_field(out, "tone", this->tone); - dump_field(out, "has_duration", this->has_duration); - dump_field(out, "duration", this->duration); - dump_field(out, "has_volume", this->has_volume); - dump_field(out, "volume", this->volume); + MessageDumpHelper helper(out, ESPHOME_PSTR("SirenCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_state"), this->has_state); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("has_tone"), this->has_tone); + dump_field(out, ESPHOME_PSTR("tone"), this->tone); + dump_field(out, ESPHOME_PSTR("has_duration"), this->has_duration); + dump_field(out, ESPHOME_PSTR("duration"), this->duration); + dump_field(out, ESPHOME_PSTR("has_volume"), this->has_volume); + dump_field(out, ESPHOME_PSTR("volume"), this->volume); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_LOCK const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesLockResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "assumed_state", this->assumed_state); - dump_field(out, "supports_open", this->supports_open); - dump_field(out, "requires_code", this->requires_code); - dump_field(out, "code_format", this->code_format); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state); + dump_field(out, ESPHOME_PSTR("supports_open"), this->supports_open); + dump_field(out, ESPHOME_PSTR("requires_code"), this->requires_code); + dump_field(out, ESPHOME_PSTR("code_format"), this->code_format); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *LockStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "LockStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", static_cast<enums::LockState>(this->state)); + MessageDumpHelper helper(out, ESPHOME_PSTR("LockStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), static_cast<enums::LockState>(this->state)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *LockCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "LockCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "command", static_cast<enums::LockCommand>(this->command)); - dump_field(out, "has_code", this->has_code); - dump_field(out, "code", this->code); + MessageDumpHelper helper(out, ESPHOME_PSTR("LockCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("command"), static_cast<enums::LockCommand>(this->command)); + dump_field(out, ESPHOME_PSTR("has_code"), this->has_code); + dump_field(out, ESPHOME_PSTR("code"), this->code); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_BUTTON const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesButtonResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *ButtonCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ButtonCommandRequest"); - dump_field(out, "key", this->key); + MessageDumpHelper helper(out, ESPHOME_PSTR("ButtonCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_MEDIA_PLAYER const char *MediaPlayerSupportedFormat::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "MediaPlayerSupportedFormat"); - dump_field(out, "format", this->format); - dump_field(out, "sample_rate", this->sample_rate); - dump_field(out, "num_channels", this->num_channels); - dump_field(out, "purpose", static_cast<enums::MediaPlayerFormatPurpose>(this->purpose)); - dump_field(out, "sample_bytes", this->sample_bytes); + MessageDumpHelper helper(out, ESPHOME_PSTR("MediaPlayerSupportedFormat")); + dump_field(out, ESPHOME_PSTR("format"), this->format); + dump_field(out, ESPHOME_PSTR("sample_rate"), this->sample_rate); + dump_field(out, ESPHOME_PSTR("num_channels"), this->num_channels); + dump_field(out, ESPHOME_PSTR("purpose"), static_cast<enums::MediaPlayerFormatPurpose>(this->purpose)); + dump_field(out, ESPHOME_PSTR("sample_bytes"), this->sample_bytes); return out.c_str(); } const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesMediaPlayerResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "supports_pause", this->supports_pause); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("supports_pause"), this->supports_pause); for (const auto &it : this->supported_formats) { - out.append(" supported_formats: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("supported_formats")).append(": "); it.dump_to(out); out.append("\n"); } #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "feature_flags", this->feature_flags); + dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags); return out.c_str(); } const char *MediaPlayerStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "MediaPlayerStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", static_cast<enums::MediaPlayerState>(this->state)); - dump_field(out, "volume", this->volume); - dump_field(out, "muted", this->muted); + MessageDumpHelper helper(out, ESPHOME_PSTR("MediaPlayerStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), static_cast<enums::MediaPlayerState>(this->state)); + dump_field(out, ESPHOME_PSTR("volume"), this->volume); + dump_field(out, ESPHOME_PSTR("muted"), this->muted); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *MediaPlayerCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "MediaPlayerCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_command", this->has_command); - dump_field(out, "command", static_cast<enums::MediaPlayerCommand>(this->command)); - dump_field(out, "has_volume", this->has_volume); - dump_field(out, "volume", this->volume); - dump_field(out, "has_media_url", this->has_media_url); - dump_field(out, "media_url", this->media_url); - dump_field(out, "has_announcement", this->has_announcement); - dump_field(out, "announcement", this->announcement); + MessageDumpHelper helper(out, ESPHOME_PSTR("MediaPlayerCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_command"), this->has_command); + dump_field(out, ESPHOME_PSTR("command"), static_cast<enums::MediaPlayerCommand>(this->command)); + dump_field(out, ESPHOME_PSTR("has_volume"), this->has_volume); + dump_field(out, ESPHOME_PSTR("volume"), this->volume); + dump_field(out, ESPHOME_PSTR("has_media_url"), this->has_media_url); + dump_field(out, ESPHOME_PSTR("media_url"), this->media_url); + dump_field(out, ESPHOME_PSTR("has_announcement"), this->has_announcement); + dump_field(out, ESPHOME_PSTR("announcement"), this->announcement); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_BLUETOOTH_PROXY const char *SubscribeBluetoothLEAdvertisementsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SubscribeBluetoothLEAdvertisementsRequest"); - dump_field(out, "flags", this->flags); + MessageDumpHelper helper(out, ESPHOME_PSTR("SubscribeBluetoothLEAdvertisementsRequest")); + dump_field(out, ESPHOME_PSTR("flags"), this->flags); return out.c_str(); } const char *BluetoothLERawAdvertisement::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothLERawAdvertisement"); - dump_field(out, "address", this->address); - dump_field(out, "rssi", this->rssi); - dump_field(out, "address_type", this->address_type); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothLERawAdvertisement")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("rssi"), this->rssi); + dump_field(out, ESPHOME_PSTR("address_type"), this->address_type); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } const char *BluetoothLERawAdvertisementsResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothLERawAdvertisementsResponse"); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothLERawAdvertisementsResponse")); for (uint16_t i = 0; i < this->advertisements_len; i++) { - out.append(" advertisements: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("advertisements")).append(": "); this->advertisements[i].dump_to(out); out.append("\n"); } return out.c_str(); } const char *BluetoothDeviceRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothDeviceRequest"); - dump_field(out, "address", this->address); - dump_field(out, "request_type", static_cast<enums::BluetoothDeviceRequestType>(this->request_type)); - dump_field(out, "has_address_type", this->has_address_type); - dump_field(out, "address_type", this->address_type); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothDeviceRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("request_type"), static_cast<enums::BluetoothDeviceRequestType>(this->request_type)); + dump_field(out, ESPHOME_PSTR("has_address_type"), this->has_address_type); + dump_field(out, ESPHOME_PSTR("address_type"), this->address_type); return out.c_str(); } const char *BluetoothDeviceConnectionResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothDeviceConnectionResponse"); - dump_field(out, "address", this->address); - dump_field(out, "connected", this->connected); - dump_field(out, "mtu", this->mtu); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothDeviceConnectionResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("connected"), this->connected); + dump_field(out, ESPHOME_PSTR("mtu"), this->mtu); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *BluetoothGATTGetServicesRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTGetServicesRequest"); - dump_field(out, "address", this->address); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTGetServicesRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); return out.c_str(); } const char *BluetoothGATTDescriptor::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTDescriptor"); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTDescriptor")); for (const auto &it : this->uuid) { - dump_field(out, "uuid", it, 4); + dump_field(out, ESPHOME_PSTR("uuid"), it, 4); } - dump_field(out, "handle", this->handle); - dump_field(out, "short_uuid", this->short_uuid); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_field(out, ESPHOME_PSTR("short_uuid"), this->short_uuid); return out.c_str(); } const char *BluetoothGATTCharacteristic::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTCharacteristic"); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTCharacteristic")); for (const auto &it : this->uuid) { - dump_field(out, "uuid", it, 4); + dump_field(out, ESPHOME_PSTR("uuid"), it, 4); } - dump_field(out, "handle", this->handle); - dump_field(out, "properties", this->properties); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_field(out, ESPHOME_PSTR("properties"), this->properties); for (const auto &it : this->descriptors) { - out.append(" descriptors: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("descriptors")).append(": "); it.dump_to(out); out.append("\n"); } - dump_field(out, "short_uuid", this->short_uuid); + dump_field(out, ESPHOME_PSTR("short_uuid"), this->short_uuid); return out.c_str(); } const char *BluetoothGATTService::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTService"); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTService")); for (const auto &it : this->uuid) { - dump_field(out, "uuid", it, 4); + dump_field(out, ESPHOME_PSTR("uuid"), it, 4); } - dump_field(out, "handle", this->handle); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); for (const auto &it : this->characteristics) { - out.append(" characteristics: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("characteristics")).append(": "); it.dump_to(out); out.append("\n"); } - dump_field(out, "short_uuid", this->short_uuid); + dump_field(out, ESPHOME_PSTR("short_uuid"), this->short_uuid); return out.c_str(); } const char *BluetoothGATTGetServicesResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTGetServicesResponse"); - dump_field(out, "address", this->address); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTGetServicesResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); for (const auto &it : this->services) { - out.append(" services: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("services")).append(": "); it.dump_to(out); out.append("\n"); } return out.c_str(); } const char *BluetoothGATTGetServicesDoneResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTGetServicesDoneResponse"); - dump_field(out, "address", this->address); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTGetServicesDoneResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); return out.c_str(); } const char *BluetoothGATTReadRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTReadRequest"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTReadRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); return out.c_str(); } const char *BluetoothGATTReadResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTReadResponse"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTReadResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data_ptr_, this->data_len_); return out.c_str(); } const char *BluetoothGATTWriteRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTWriteRequest"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_field(out, "response", this->response); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTWriteRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_field(out, ESPHOME_PSTR("response"), this->response); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } const char *BluetoothGATTReadDescriptorRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTReadDescriptorRequest"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTReadDescriptorRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); return out.c_str(); } const char *BluetoothGATTWriteDescriptorRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTWriteDescriptorRequest"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTWriteDescriptorRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } const char *BluetoothGATTNotifyRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTNotifyRequest"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_field(out, "enable", this->enable); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTNotifyRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_field(out, ESPHOME_PSTR("enable"), this->enable); return out.c_str(); } const char *BluetoothGATTNotifyDataResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTNotifyDataResponse"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTNotifyDataResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data_ptr_, this->data_len_); return out.c_str(); } const char *BluetoothConnectionsFreeResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothConnectionsFreeResponse"); - dump_field(out, "free", this->free); - dump_field(out, "limit", this->limit); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothConnectionsFreeResponse")); + dump_field(out, ESPHOME_PSTR("free"), this->free); + dump_field(out, ESPHOME_PSTR("limit"), this->limit); for (const auto &it : this->allocated) { - dump_field(out, "allocated", it, 4); + dump_field(out, ESPHOME_PSTR("allocated"), it, 4); } return out.c_str(); } const char *BluetoothGATTErrorResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTErrorResponse"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTErrorResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *BluetoothGATTWriteResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTWriteResponse"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTWriteResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); return out.c_str(); } const char *BluetoothGATTNotifyResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothGATTNotifyResponse"); - dump_field(out, "address", this->address); - dump_field(out, "handle", this->handle); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothGATTNotifyResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("handle"), this->handle); return out.c_str(); } const char *BluetoothDevicePairingResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothDevicePairingResponse"); - dump_field(out, "address", this->address); - dump_field(out, "paired", this->paired); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothDevicePairingResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("paired"), this->paired); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *BluetoothDeviceUnpairingResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothDeviceUnpairingResponse"); - dump_field(out, "address", this->address); - dump_field(out, "success", this->success); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothDeviceUnpairingResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("success"), this->success); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *BluetoothDeviceClearCacheResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothDeviceClearCacheResponse"); - dump_field(out, "address", this->address); - dump_field(out, "success", this->success); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothDeviceClearCacheResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("success"), this->success); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *BluetoothScannerStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothScannerStateResponse"); - dump_field(out, "state", static_cast<enums::BluetoothScannerState>(this->state)); - dump_field(out, "mode", static_cast<enums::BluetoothScannerMode>(this->mode)); - dump_field(out, "configured_mode", static_cast<enums::BluetoothScannerMode>(this->configured_mode)); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothScannerStateResponse")); + dump_field(out, ESPHOME_PSTR("state"), static_cast<enums::BluetoothScannerState>(this->state)); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::BluetoothScannerMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("configured_mode"), static_cast<enums::BluetoothScannerMode>(this->configured_mode)); return out.c_str(); } const char *BluetoothScannerSetModeRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothScannerSetModeRequest"); - dump_field(out, "mode", static_cast<enums::BluetoothScannerMode>(this->mode)); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothScannerSetModeRequest")); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::BluetoothScannerMode>(this->mode)); return out.c_str(); } #endif #ifdef USE_VOICE_ASSISTANT const char *SubscribeVoiceAssistantRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SubscribeVoiceAssistantRequest"); - dump_field(out, "subscribe", this->subscribe); - dump_field(out, "flags", this->flags); + MessageDumpHelper helper(out, ESPHOME_PSTR("SubscribeVoiceAssistantRequest")); + dump_field(out, ESPHOME_PSTR("subscribe"), this->subscribe); + dump_field(out, ESPHOME_PSTR("flags"), this->flags); return out.c_str(); } const char *VoiceAssistantAudioSettings::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantAudioSettings"); - dump_field(out, "noise_suppression_level", this->noise_suppression_level); - dump_field(out, "auto_gain", this->auto_gain); - dump_field(out, "volume_multiplier", this->volume_multiplier); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantAudioSettings")); + dump_field(out, ESPHOME_PSTR("noise_suppression_level"), this->noise_suppression_level); + dump_field(out, ESPHOME_PSTR("auto_gain"), this->auto_gain); + dump_field(out, ESPHOME_PSTR("volume_multiplier"), this->volume_multiplier); return out.c_str(); } const char *VoiceAssistantRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantRequest"); - dump_field(out, "start", this->start); - dump_field(out, "conversation_id", this->conversation_id); - dump_field(out, "flags", this->flags); - out.append(" audio_settings: "); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantRequest")); + dump_field(out, ESPHOME_PSTR("start"), this->start); + dump_field(out, ESPHOME_PSTR("conversation_id"), this->conversation_id); + dump_field(out, ESPHOME_PSTR("flags"), this->flags); + out.append(2, ' ').append_p(ESPHOME_PSTR("audio_settings")).append(": "); this->audio_settings.dump_to(out); out.append("\n"); - dump_field(out, "wake_word_phrase", this->wake_word_phrase); + dump_field(out, ESPHOME_PSTR("wake_word_phrase"), this->wake_word_phrase); return out.c_str(); } const char *VoiceAssistantResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantResponse"); - dump_field(out, "port", this->port); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantResponse")); + dump_field(out, ESPHOME_PSTR("port"), this->port); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } const char *VoiceAssistantEventData::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantEventData"); - dump_field(out, "name", this->name); - dump_field(out, "value", this->value); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantEventData")); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("value"), this->value); return out.c_str(); } const char *VoiceAssistantEventResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantEventResponse"); - dump_field(out, "event_type", static_cast<enums::VoiceAssistantEvent>(this->event_type)); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantEventResponse")); + dump_field(out, ESPHOME_PSTR("event_type"), static_cast<enums::VoiceAssistantEvent>(this->event_type)); for (const auto &it : this->data) { - out.append(" data: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("data")).append(": "); it.dump_to(out); out.append("\n"); } return out.c_str(); } const char *VoiceAssistantAudio::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantAudio"); - dump_bytes_field(out, "data", this->data, this->data_len); - dump_field(out, "end", this->end); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantAudio")); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); + dump_field(out, ESPHOME_PSTR("end"), this->end); return out.c_str(); } const char *VoiceAssistantTimerEventResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantTimerEventResponse"); - dump_field(out, "event_type", static_cast<enums::VoiceAssistantTimerEvent>(this->event_type)); - dump_field(out, "timer_id", this->timer_id); - dump_field(out, "name", this->name); - dump_field(out, "total_seconds", this->total_seconds); - dump_field(out, "seconds_left", this->seconds_left); - dump_field(out, "is_active", this->is_active); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantTimerEventResponse")); + dump_field(out, ESPHOME_PSTR("event_type"), static_cast<enums::VoiceAssistantTimerEvent>(this->event_type)); + dump_field(out, ESPHOME_PSTR("timer_id"), this->timer_id); + dump_field(out, ESPHOME_PSTR("name"), this->name); + dump_field(out, ESPHOME_PSTR("total_seconds"), this->total_seconds); + dump_field(out, ESPHOME_PSTR("seconds_left"), this->seconds_left); + dump_field(out, ESPHOME_PSTR("is_active"), this->is_active); return out.c_str(); } const char *VoiceAssistantAnnounceRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantAnnounceRequest"); - dump_field(out, "media_id", this->media_id); - dump_field(out, "text", this->text); - dump_field(out, "preannounce_media_id", this->preannounce_media_id); - dump_field(out, "start_conversation", this->start_conversation); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantAnnounceRequest")); + dump_field(out, ESPHOME_PSTR("media_id"), this->media_id); + dump_field(out, ESPHOME_PSTR("text"), this->text); + dump_field(out, ESPHOME_PSTR("preannounce_media_id"), this->preannounce_media_id); + dump_field(out, ESPHOME_PSTR("start_conversation"), this->start_conversation); return out.c_str(); } const char *VoiceAssistantAnnounceFinished::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantAnnounceFinished"); - dump_field(out, "success", this->success); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantAnnounceFinished")); + dump_field(out, ESPHOME_PSTR("success"), this->success); return out.c_str(); } const char *VoiceAssistantWakeWord::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantWakeWord"); - dump_field(out, "id", this->id); - dump_field(out, "wake_word", this->wake_word); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantWakeWord")); + dump_field(out, ESPHOME_PSTR("id"), this->id); + dump_field(out, ESPHOME_PSTR("wake_word"), this->wake_word); for (const auto &it : this->trained_languages) { - dump_field(out, "trained_languages", it, 4); + dump_field(out, ESPHOME_PSTR("trained_languages"), it, 4); } return out.c_str(); } const char *VoiceAssistantExternalWakeWord::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantExternalWakeWord"); - dump_field(out, "id", this->id); - dump_field(out, "wake_word", this->wake_word); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantExternalWakeWord")); + dump_field(out, ESPHOME_PSTR("id"), this->id); + dump_field(out, ESPHOME_PSTR("wake_word"), this->wake_word); for (const auto &it : this->trained_languages) { - dump_field(out, "trained_languages", it, 4); + dump_field(out, ESPHOME_PSTR("trained_languages"), it, 4); } - dump_field(out, "model_type", this->model_type); - dump_field(out, "model_size", this->model_size); - dump_field(out, "model_hash", this->model_hash); - dump_field(out, "url", this->url); + dump_field(out, ESPHOME_PSTR("model_type"), this->model_type); + dump_field(out, ESPHOME_PSTR("model_size"), this->model_size); + dump_field(out, ESPHOME_PSTR("model_hash"), this->model_hash); + dump_field(out, ESPHOME_PSTR("url"), this->url); return out.c_str(); } const char *VoiceAssistantConfigurationRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantConfigurationRequest"); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantConfigurationRequest")); for (const auto &it : this->external_wake_words) { - out.append(" external_wake_words: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("external_wake_words")).append(": "); it.dump_to(out); out.append("\n"); } return out.c_str(); } const char *VoiceAssistantConfigurationResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantConfigurationResponse"); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantConfigurationResponse")); for (const auto &it : this->available_wake_words) { - out.append(" available_wake_words: "); + out.append(4, ' ').append_p(ESPHOME_PSTR("available_wake_words")).append(": "); it.dump_to(out); out.append("\n"); } for (const auto &it : *this->active_wake_words) { - dump_field(out, "active_wake_words", it, 4); + dump_field(out, ESPHOME_PSTR("active_wake_words"), it, 4); } - dump_field(out, "max_active_wake_words", this->max_active_wake_words); + dump_field(out, ESPHOME_PSTR("max_active_wake_words"), this->max_active_wake_words); return out.c_str(); } const char *VoiceAssistantSetConfiguration::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "VoiceAssistantSetConfiguration"); + MessageDumpHelper helper(out, ESPHOME_PSTR("VoiceAssistantSetConfiguration")); for (const auto &it : this->active_wake_words) { - dump_field(out, "active_wake_words", it, 4); + dump_field(out, ESPHOME_PSTR("active_wake_words"), it, 4); } return out.c_str(); } #endif #ifdef USE_ALARM_CONTROL_PANEL const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesAlarmControlPanelResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "supported_features", this->supported_features); - dump_field(out, "requires_code", this->requires_code); - dump_field(out, "requires_code_to_arm", this->requires_code_to_arm); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("supported_features"), this->supported_features); + dump_field(out, ESPHOME_PSTR("requires_code"), this->requires_code); + dump_field(out, ESPHOME_PSTR("requires_code_to_arm"), this->requires_code_to_arm); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *AlarmControlPanelStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "AlarmControlPanelStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", static_cast<enums::AlarmControlPanelState>(this->state)); + MessageDumpHelper helper(out, ESPHOME_PSTR("AlarmControlPanelStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), static_cast<enums::AlarmControlPanelState>(this->state)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *AlarmControlPanelCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "AlarmControlPanelCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "command", static_cast<enums::AlarmControlPanelStateCommand>(this->command)); - dump_field(out, "code", this->code); + MessageDumpHelper helper(out, ESPHOME_PSTR("AlarmControlPanelCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("command"), static_cast<enums::AlarmControlPanelStateCommand>(this->command)); + dump_field(out, ESPHOME_PSTR("code"), this->code); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_TEXT const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesTextResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "min_length", this->min_length); - dump_field(out, "max_length", this->max_length); - dump_field(out, "pattern", this->pattern); - dump_field(out, "mode", static_cast<enums::TextMode>(this->mode)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("min_length"), this->min_length); + dump_field(out, ESPHOME_PSTR("max_length"), this->max_length); + dump_field(out, ESPHOME_PSTR("pattern"), this->pattern); + dump_field(out, ESPHOME_PSTR("mode"), static_cast<enums::TextMode>(this->mode)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *TextStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "TextStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); - dump_field(out, "missing_state", this->missing_state); + MessageDumpHelper helper(out, ESPHOME_PSTR("TextStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *TextCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "TextCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "state", this->state); + MessageDumpHelper helper(out, ESPHOME_PSTR("TextCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("state"), this->state); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_DATETIME_DATE const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesDateResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *DateStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DateStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "missing_state", this->missing_state); - dump_field(out, "year", this->year); - dump_field(out, "month", this->month); - dump_field(out, "day", this->day); + MessageDumpHelper helper(out, ESPHOME_PSTR("DateStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); + dump_field(out, ESPHOME_PSTR("year"), this->year); + dump_field(out, ESPHOME_PSTR("month"), this->month); + dump_field(out, ESPHOME_PSTR("day"), this->day); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *DateCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DateCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "year", this->year); - dump_field(out, "month", this->month); - dump_field(out, "day", this->day); + MessageDumpHelper helper(out, ESPHOME_PSTR("DateCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("year"), this->year); + dump_field(out, ESPHOME_PSTR("month"), this->month); + dump_field(out, ESPHOME_PSTR("day"), this->day); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_DATETIME_TIME const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesTimeResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *TimeStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "TimeStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "missing_state", this->missing_state); - dump_field(out, "hour", this->hour); - dump_field(out, "minute", this->minute); - dump_field(out, "second", this->second); + MessageDumpHelper helper(out, ESPHOME_PSTR("TimeStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); + dump_field(out, ESPHOME_PSTR("hour"), this->hour); + dump_field(out, ESPHOME_PSTR("minute"), this->minute); + dump_field(out, ESPHOME_PSTR("second"), this->second); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *TimeCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "TimeCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "hour", this->hour); - dump_field(out, "minute", this->minute); - dump_field(out, "second", this->second); + MessageDumpHelper helper(out, ESPHOME_PSTR("TimeCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("hour"), this->hour); + dump_field(out, ESPHOME_PSTR("minute"), this->minute); + dump_field(out, ESPHOME_PSTR("second"), this->second); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_EVENT const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesEventResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); for (const auto &it : *this->event_types) { - dump_field(out, "event_types", it, 4); + dump_field(out, ESPHOME_PSTR("event_types"), it, 4); } #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *EventResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "EventResponse"); - dump_field(out, "key", this->key); - dump_field(out, "event_type", this->event_type); + MessageDumpHelper helper(out, ESPHOME_PSTR("EventResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("event_type"), this->event_type); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_VALVE const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesValveResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); - dump_field(out, "assumed_state", this->assumed_state); - dump_field(out, "supports_position", this->supports_position); - dump_field(out, "supports_stop", this->supports_stop); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); + dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state); + dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position); + dump_field(out, ESPHOME_PSTR("supports_stop"), this->supports_stop); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *ValveStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ValveStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "position", this->position); - dump_field(out, "current_operation", static_cast<enums::ValveOperation>(this->current_operation)); + MessageDumpHelper helper(out, ESPHOME_PSTR("ValveStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("position"), this->position); + dump_field(out, ESPHOME_PSTR("current_operation"), static_cast<enums::ValveOperation>(this->current_operation)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *ValveCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ValveCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "has_position", this->has_position); - dump_field(out, "position", this->position); - dump_field(out, "stop", this->stop); + MessageDumpHelper helper(out, ESPHOME_PSTR("ValveCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("has_position"), this->has_position); + dump_field(out, ESPHOME_PSTR("position"), this->position); + dump_field(out, ESPHOME_PSTR("stop"), this->stop); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_DATETIME_DATETIME const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesDateTimeResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *DateTimeStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DateTimeStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "missing_state", this->missing_state); - dump_field(out, "epoch_seconds", this->epoch_seconds); + MessageDumpHelper helper(out, ESPHOME_PSTR("DateTimeStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); + dump_field(out, ESPHOME_PSTR("epoch_seconds"), this->epoch_seconds); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *DateTimeCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "DateTimeCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "epoch_seconds", this->epoch_seconds); + MessageDumpHelper helper(out, ESPHOME_PSTR("DateTimeCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("epoch_seconds"), this->epoch_seconds); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_UPDATE const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesUpdateResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); - dump_field(out, "device_class", this->device_class); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("device_class"), this->device_class); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *UpdateStateResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "UpdateStateResponse"); - dump_field(out, "key", this->key); - dump_field(out, "missing_state", this->missing_state); - dump_field(out, "in_progress", this->in_progress); - dump_field(out, "has_progress", this->has_progress); - dump_field(out, "progress", this->progress); - dump_field(out, "current_version", this->current_version); - dump_field(out, "latest_version", this->latest_version); - dump_field(out, "title", this->title); - dump_field(out, "release_summary", this->release_summary); - dump_field(out, "release_url", this->release_url); + MessageDumpHelper helper(out, ESPHOME_PSTR("UpdateStateResponse")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("missing_state"), this->missing_state); + dump_field(out, ESPHOME_PSTR("in_progress"), this->in_progress); + dump_field(out, ESPHOME_PSTR("has_progress"), this->has_progress); + dump_field(out, ESPHOME_PSTR("progress"), this->progress); + dump_field(out, ESPHOME_PSTR("current_version"), this->current_version); + dump_field(out, ESPHOME_PSTR("latest_version"), this->latest_version); + dump_field(out, ESPHOME_PSTR("title"), this->title); + dump_field(out, ESPHOME_PSTR("release_summary"), this->release_summary); + dump_field(out, ESPHOME_PSTR("release_url"), this->release_url); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } const char *UpdateCommandRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "UpdateCommandRequest"); - dump_field(out, "key", this->key); - dump_field(out, "command", static_cast<enums::UpdateCommand>(this->command)); + MessageDumpHelper helper(out, ESPHOME_PSTR("UpdateCommandRequest")); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("command"), static_cast<enums::UpdateCommand>(this->command)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif return out.c_str(); } #endif #ifdef USE_ZWAVE_PROXY const char *ZWaveProxyFrame::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ZWaveProxyFrame"); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("ZWaveProxyFrame")); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } const char *ZWaveProxyRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ZWaveProxyRequest"); - dump_field(out, "type", static_cast<enums::ZWaveProxyRequestType>(this->type)); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("ZWaveProxyRequest")); + dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::ZWaveProxyRequestType>(this->type)); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } #endif #ifdef USE_INFRARED const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "ListEntitiesInfraredResponse"); - dump_field(out, "object_id", this->object_id); - dump_field(out, "key", this->key); - dump_field(out, "name", this->name); + MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse")); + dump_field(out, ESPHOME_PSTR("object_id"), this->object_id); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("name"), this->name); #ifdef USE_ENTITY_ICON - dump_field(out, "icon", this->icon); + dump_field(out, ESPHOME_PSTR("icon"), this->icon); #endif - dump_field(out, "disabled_by_default", this->disabled_by_default); - dump_field(out, "entity_category", static_cast<enums::EntityCategory>(this->entity_category)); + dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default); + dump_field(out, ESPHOME_PSTR("entity_category"), static_cast<enums::EntityCategory>(this->entity_category)); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "capabilities", this->capabilities); + dump_field(out, ESPHOME_PSTR("capabilities"), this->capabilities); return out.c_str(); } #endif #ifdef USE_IR_RF const char *InfraredRFTransmitRawTimingsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "InfraredRFTransmitRawTimingsRequest"); + MessageDumpHelper helper(out, ESPHOME_PSTR("InfraredRFTransmitRawTimingsRequest")); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "key", this->key); - dump_field(out, "carrier_frequency", this->carrier_frequency); - dump_field(out, "repeat_count", this->repeat_count); - out.append(" timings: "); - out.append("packed buffer ["); + dump_field(out, ESPHOME_PSTR("key"), this->key); + dump_field(out, ESPHOME_PSTR("carrier_frequency"), this->carrier_frequency); + dump_field(out, ESPHOME_PSTR("repeat_count"), this->repeat_count); + out.append(2, ' ').append_p(ESPHOME_PSTR("timings")).append(": "); + out.append_p(ESPHOME_PSTR("packed buffer [")); append_uint(out, this->timings_count_); - out.append(" values, "); + out.append_p(ESPHOME_PSTR(" values, ")); append_uint(out, this->timings_length_); - out.append(" bytes]\n"); + out.append_p(ESPHOME_PSTR(" bytes]\n")); return out.c_str(); } const char *InfraredRFReceiveEvent::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "InfraredRFReceiveEvent"); + MessageDumpHelper helper(out, ESPHOME_PSTR("InfraredRFReceiveEvent")); #ifdef USE_DEVICES - dump_field(out, "device_id", this->device_id); + dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif - dump_field(out, "key", this->key); + dump_field(out, ESPHOME_PSTR("key"), this->key); for (const auto &it : *this->timings) { - dump_field(out, "timings", it, 4); + dump_field(out, ESPHOME_PSTR("timings"), it, 4); } return out.c_str(); } #endif #ifdef USE_SERIAL_PROXY const char *SerialProxyConfigureRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyConfigureRequest"); - dump_field(out, "instance", this->instance); - dump_field(out, "baudrate", this->baudrate); - dump_field(out, "flow_control", this->flow_control); - dump_field(out, "parity", static_cast<enums::SerialProxyParity>(this->parity)); - dump_field(out, "stop_bits", this->stop_bits); - dump_field(out, "data_size", this->data_size); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyConfigureRequest")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_field(out, ESPHOME_PSTR("baudrate"), this->baudrate); + dump_field(out, ESPHOME_PSTR("flow_control"), this->flow_control); + dump_field(out, ESPHOME_PSTR("parity"), static_cast<enums::SerialProxyParity>(this->parity)); + dump_field(out, ESPHOME_PSTR("stop_bits"), this->stop_bits); + dump_field(out, ESPHOME_PSTR("data_size"), this->data_size); return out.c_str(); } const char *SerialProxyDataReceived::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyDataReceived"); - dump_field(out, "instance", this->instance); - dump_bytes_field(out, "data", this->data_ptr_, this->data_len_); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyDataReceived")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data_ptr_, this->data_len_); return out.c_str(); } const char *SerialProxyWriteRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyWriteRequest"); - dump_field(out, "instance", this->instance); - dump_bytes_field(out, "data", this->data, this->data_len); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyWriteRequest")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_bytes_field(out, ESPHOME_PSTR("data"), this->data, this->data_len); return out.c_str(); } const char *SerialProxySetModemPinsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxySetModemPinsRequest"); - dump_field(out, "instance", this->instance); - dump_field(out, "line_states", this->line_states); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxySetModemPinsRequest")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_field(out, ESPHOME_PSTR("line_states"), this->line_states); return out.c_str(); } const char *SerialProxyGetModemPinsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyGetModemPinsRequest"); - dump_field(out, "instance", this->instance); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyGetModemPinsRequest")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); return out.c_str(); } const char *SerialProxyGetModemPinsResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyGetModemPinsResponse"); - dump_field(out, "instance", this->instance); - dump_field(out, "line_states", this->line_states); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyGetModemPinsResponse")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_field(out, ESPHOME_PSTR("line_states"), this->line_states); return out.c_str(); } const char *SerialProxyRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyRequest"); - dump_field(out, "instance", this->instance); - dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type)); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyRequest")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::SerialProxyRequestType>(this->type)); return out.c_str(); } const char *SerialProxyRequestResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "SerialProxyRequestResponse"); - dump_field(out, "instance", this->instance); - dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type)); - dump_field(out, "status", static_cast<enums::SerialProxyStatus>(this->status)); - dump_field(out, "error_message", this->error_message); + MessageDumpHelper helper(out, ESPHOME_PSTR("SerialProxyRequestResponse")); + dump_field(out, ESPHOME_PSTR("instance"), this->instance); + dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::SerialProxyRequestType>(this->type)); + dump_field(out, ESPHOME_PSTR("status"), static_cast<enums::SerialProxyStatus>(this->status)); + dump_field(out, ESPHOME_PSTR("error_message"), this->error_message); return out.c_str(); } #endif #ifdef USE_BLUETOOTH_PROXY const char *BluetoothSetConnectionParamsRequest::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothSetConnectionParamsRequest"); - dump_field(out, "address", this->address); - dump_field(out, "min_interval", this->min_interval); - dump_field(out, "max_interval", this->max_interval); - dump_field(out, "latency", this->latency); - dump_field(out, "timeout", this->timeout); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothSetConnectionParamsRequest")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("min_interval"), this->min_interval); + dump_field(out, ESPHOME_PSTR("max_interval"), this->max_interval); + dump_field(out, ESPHOME_PSTR("latency"), this->latency); + dump_field(out, ESPHOME_PSTR("timeout"), this->timeout); return out.c_str(); } const char *BluetoothSetConnectionParamsResponse::dump_to(DumpBuffer &out) const { - MessageDumpHelper helper(out, "BluetoothSetConnectionParamsResponse"); - dump_field(out, "address", this->address); - dump_field(out, "error", this->error); + MessageDumpHelper helper(out, ESPHOME_PSTR("BluetoothSetConnectionParamsResponse")); + dump_field(out, ESPHOME_PSTR("address"), this->address); + dump_field(out, ESPHOME_PSTR("error"), this->error); return out.c_str(); } #endif diff --git a/esphome/components/api/api_pb2_service.cpp b/esphome/components/api/api_pb2_service.cpp index d86cf912db..b41233eddd 100644 --- a/esphome/components/api/api_pb2_service.cpp +++ b/esphome/components/api/api_pb2_service.cpp @@ -9,8 +9,8 @@ namespace esphome::api { static const char *const TAG = "api.service"; #ifdef HAS_PROTO_MESSAGE_DUMP -void APIServerConnectionBase::log_send_message_(const char *name, const char *dump) { - ESP_LOGVV(TAG, "send_message %s: %s", name, dump); +void APIServerConnectionBase::log_send_message_(const LogString *name, const char *dump) { + ESP_LOGVV(TAG, "send_message %s: %s", LOG_STR_ARG(name), dump); } void APIServerConnectionBase::log_receive_message_(const LogString *name, const ProtoMessage &msg) { DumpBuffer dump_buf; diff --git a/esphome/components/api/api_pb2_service.h b/esphome/components/api/api_pb2_service.h index 4925a6497a..6ff988902f 100644 --- a/esphome/components/api/api_pb2_service.h +++ b/esphome/components/api/api_pb2_service.h @@ -12,7 +12,7 @@ class APIServerConnectionBase { public: #ifdef HAS_PROTO_MESSAGE_DUMP protected: - void log_send_message_(const char *name, const char *dump); + void log_send_message_(const LogString *name, const char *dump); void log_receive_message_(const LogString *name, const ProtoMessage &msg); void log_receive_message_(const LogString *name); diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index d6f9c947d7..95a79105a3 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -5,6 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/progmem.h" #include "esphome/core/string_ref.h" #include <cassert> @@ -400,6 +401,23 @@ class DumpBuffer { return *this; } + /// Append a PROGMEM string (flash-safe on ESP8266, regular append on other platforms) + DumpBuffer &append_p(const char *str) { + if (str) { +#ifdef USE_ESP8266 + append_p_esp8266(str); +#else + append_impl_(str, strlen(str)); +#endif + } + return *this; + } + +#ifdef USE_ESP8266 + /// Out-of-line ESP8266 PROGMEM append to avoid inlining strlen_P/memcpy_P at every call site + void append_p_esp8266(const char *str); +#endif + const char *c_str() const { return buf_; } size_t size() const { return pos_; } @@ -445,7 +463,7 @@ class ProtoMessage { uint32_t calculate_size() const { return 0; } #ifdef HAS_PROTO_MESSAGE_DUMP virtual const char *dump_to(DumpBuffer &out) const = 0; - virtual const char *message_name() const { return "unknown"; } + virtual const LogString *message_name() const { return LOG_STR("unknown"); } #endif #ifndef USE_HOST diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 0bb569fdb5..81ea93caf4 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -248,7 +248,7 @@ class TypeInfo(ABC): @property def dump_content(self) -> str: # Default implementation - subclasses can override if they need special handling - return f'dump_field(out, "{self.name}", {self.dump_field_value(f"this->{self.field_name}")});' + return f'dump_field(out, ESPHOME_PSTR("{self.name}"), {self.dump_field_value(f"this->{self.field_name}")});' @abstractmethod def dump(self, name: str) -> str: @@ -665,14 +665,14 @@ class StringType(TypeInfo): def dump_content(self) -> str: # For SOURCE_CLIENT only, use std::string if not self._needs_encode: - return f'dump_field(out, "{self.name}", this->{self.field_name});' + return f'dump_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name});' # For SOURCE_SERVER, use StringRef with _ref_ suffix if not self._needs_decode: - return f'dump_field(out, "{self.name}", this->{self.field_name}_ref_);' + return f'dump_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name}_ref_);' # For SOURCE_BOTH, we need custom logic - o = f'out.append(" {self.name}: ");\n' + o = f'out.append(2, \' \').append_p(ESPHOME_PSTR("{self.name}")).append(": ");\n' o += self.dump(f"this->{self.field_name}") + "\n" o += 'out.append("\\n");' return o @@ -745,7 +745,7 @@ class MessageType(TypeInfo): @property def dump_content(self) -> str: - o = f'out.append(" {self.name}: ");\n' + o = f'out.append(2, \' \').append_p(ESPHOME_PSTR("{self.name}")).append(": ");\n' o += f"this->{self.field_name}.dump_to(out);\n" o += 'out.append("\\n");' return o @@ -831,7 +831,7 @@ class BytesType(TypeInfo): # For SOURCE_CLIENT only, always use std::string if not self._needs_encode: return ( - f'dump_bytes_field(out, "{self.name}", ' + f'dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"reinterpret_cast<const uint8_t*>(this->{self.field_name}.data()), " f"this->{self.field_name}.size());" ) @@ -839,17 +839,17 @@ class BytesType(TypeInfo): # For SOURCE_SERVER, always use pointer/length if not self._needs_decode: return ( - f'dump_bytes_field(out, "{self.name}", ' + f'dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"this->{self.field_name}_ptr_, this->{self.field_name}_len_);" ) # For SOURCE_BOTH, check if pointer is set (sending) or use string (received) return ( f"if (this->{self.field_name}_ptr_ != nullptr) {{\n" - f' dump_bytes_field(out, "{self.name}", ' + f' dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"this->{self.field_name}_ptr_, this->{self.field_name}_len_);\n" f"}} else {{\n" - f' dump_bytes_field(out, "{self.name}", ' + f' dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"reinterpret_cast<const uint8_t*>(this->{self.field_name}.data()), " f"this->{self.field_name}.size());\n" f"}}" @@ -928,7 +928,7 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): @property def dump_content(self) -> str: return ( - f'dump_bytes_field(out, "{self.name}", ' + f'dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"this->{self.field_name}, this->{self.field_name}_len);" ) @@ -976,7 +976,7 @@ class PointerToStringBufferType(PointerToBufferTypeBase): @property def dump_content(self) -> str: - return f'dump_field(out, "{self.name}", this->{self.field_name});' + return f'dump_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name});' def get_size_calculation(self, name: str, force: bool = False) -> str: return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}.size());" @@ -1036,12 +1036,12 @@ class PackedBufferTypeInfo(TypeInfo): def dump_content(self) -> str: """Dump shows buffer info but not decoded values.""" return ( - f'out.append(" {self.name}: ");\n' - + 'out.append("packed buffer [");\n' + f'out.append(2, \' \').append_p(ESPHOME_PSTR("{self.name}")).append(": ");\n' + + 'out.append_p(ESPHOME_PSTR("packed buffer ["));\n' + f"append_uint(out, this->{self.field_name}_count_);\n" - + 'out.append(" values, ");\n' + + 'out.append_p(ESPHOME_PSTR(" values, "));\n' + f"append_uint(out, this->{self.field_name}_length_);\n" - + 'out.append(" bytes]\\n");' + + 'out.append_p(ESPHOME_PSTR(" bytes]\\n"));' ) def dump(self, name: str) -> str: @@ -1134,7 +1134,7 @@ class FixedArrayBytesType(TypeInfo): @property def dump_content(self) -> str: return ( - f'dump_bytes_field(out, "{self.name}", ' + f'dump_bytes_field(out, ESPHOME_PSTR("{self.name}"), ' f"this->{self.field_name}, this->{self.field_name}_len);" ) @@ -1204,7 +1204,7 @@ class EnumType(TypeInfo): return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}));" def dump(self, name: str) -> str: - return f"out.append(proto_enum_to_string<{self.cpp_type}>({name}));" + return f"out.append_p(proto_enum_to_string<{self.cpp_type}>({name}));" def dump_field_value(self, value: str) -> str: # Enums need explicit cast for the template @@ -1326,15 +1326,15 @@ def _generate_array_dump_content( # Check if underlying type can use dump_field if is_const_char_ptr: # Special case for const char* - use it directly - o += f' dump_field(out, "{name}", it, 4);\n' + o += f' dump_field(out, ESPHOME_PSTR("{name}"), it, 4);\n' elif ti.can_use_dump_field(): # For types that have dump_field overloads, use them with extra indent # std::vector<bool> iterators return proxy objects, need explicit cast value_expr = "static_cast<bool>(it)" if is_bool else ti.dump_field_value("it") - o += f' dump_field(out, "{name}", {value_expr}, 4);\n' + o += f' dump_field(out, ESPHOME_PSTR("{name}"), {value_expr}, 4);\n' else: # For complex types (messages, bytes), use the old pattern - o += f' out.append(" {name}: ");\n' + o += f' out.append(4, \' \').append_p(ESPHOME_PSTR("{name}")).append(": ");\n' o += indent(ti.dump("it")) + "\n" o += ' out.append("\\n");\n' o += "}" @@ -1543,9 +1543,9 @@ class FixedArrayWithLengthRepeatedType(FixedArrayRepeatedType): o = f"for (uint16_t i = 0; i < this->{self.field_name}_len; i++) {{\n" # Check if underlying type can use dump_field if self._ti.can_use_dump_field(): - o += f' dump_field(out, "{self.name}", {self._ti.dump_field_value(f"this->{self.field_name}[i]")}, 4);\n' + o += f' dump_field(out, ESPHOME_PSTR("{self.name}"), {self._ti.dump_field_value(f"this->{self.field_name}[i]")}, 4);\n' else: - o += f' out.append(" {self.name}: ");\n' + o += f' out.append(4, \' \').append_p(ESPHOME_PSTR("{self.name}")).append(": ");\n' o += indent(self._ti.dump(f"this->{self.field_name}[i]")) + "\n" o += ' out.append("\\n");\n' o += "}" @@ -2023,9 +2023,9 @@ def build_enum_type(desc, enum_ifdef_map) -> tuple[str, str, str]: dump_cpp += " switch (value) {\n" for v in desc.value: dump_cpp += f" case enums::{v.name}:\n" - dump_cpp += f' return "{v.name}";\n' + dump_cpp += f' return ESPHOME_PSTR("{v.name}");\n' dump_cpp += " default:\n" - dump_cpp += ' return "UNKNOWN";\n' + dump_cpp += ' return ESPHOME_PSTR("UNKNOWN");\n' dump_cpp += " }\n" dump_cpp += "}\n" @@ -2107,7 +2107,7 @@ def build_message_type( public_content.append("#ifdef HAS_PROTO_MESSAGE_DUMP") snake_name = camel_to_snake(desc.name) public_content.append( - f'const char *message_name() const override {{ return "{snake_name}"; }}' + f'const LogString *message_name() const override {{ return LOG_STR("{snake_name}"); }}' ) public_content.append("#endif") @@ -2315,12 +2315,12 @@ def build_message_type( if dump: # Always use MessageDumpHelper for consistent output formatting dump_impl += "\n" - dump_impl += f' MessageDumpHelper helper(out, "{desc.name}");\n' + dump_impl += f' MessageDumpHelper helper(out, ESPHOME_PSTR("{desc.name}"));\n' dump_impl += indent("\n".join(dump)) + "\n" dump_impl += " return out.c_str();\n" else: dump_impl += "\n" - dump_impl += f' out.append("{desc.name} {{}}");\n' + dump_impl += f' out.append_p(ESPHOME_PSTR("{desc.name} {{}}"));\n' dump_impl += " return out.c_str();\n" dump_impl += "}\n" @@ -2707,6 +2707,7 @@ namespace esphome::api { dump_cpp += """\ #include "api_pb2.h" #include "esphome/core/helpers.h" +#include "esphome/core/progmem.h" #include <cinttypes> @@ -2714,6 +2715,21 @@ namespace esphome::api { namespace esphome::api { +#ifdef USE_ESP8266 +// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site +void DumpBuffer::append_p_esp8266(const char *str) { + size_t len = strlen_P(str); + size_t space = CAPACITY - 1 - pos_; + if (len > space) + len = space; + if (len > 0) { + memcpy_P(buf_ + pos_, str, len); + pos_ += len; + buf_[pos_] = '\\0'; + } +} +#endif + // Helper function to append a quoted string, handling empty StringRef static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { out.append("'"); @@ -2724,8 +2740,9 @@ static inline void append_quoted_string(DumpBuffer &out, const StringRef &ref) { } // Common helpers for dump_field functions +// field_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) static inline void append_field_prefix(DumpBuffer &out, const char *field_name, int indent) { - out.append(indent, ' ').append(field_name).append(": "); + out.append(indent, ' ').append_p(field_name).append(": "); } static inline void append_uint(DumpBuffer &out, uint32_t value) { @@ -2733,10 +2750,11 @@ static inline void append_uint(DumpBuffer &out, uint32_t value) { } // RAII helper for message dump formatting +// message_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) class MessageDumpHelper { public: MessageDumpHelper(DumpBuffer &out, const char *message_name) : out_(out) { - out_.append(message_name); + out_.append_p(message_name); out_.append(" {\\n"); } ~MessageDumpHelper() { out_.append(" }"); } @@ -2746,6 +2764,10 @@ class MessageDumpHelper { }; // Helper functions to reduce code duplication in dump methods +// field_name parameters are PROGMEM pointers (flash on ESP8266, regular pointers on other platforms) +// Not all overloads are used in every build (depends on enabled components) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" static void dump_field(DumpBuffer &out, const char *field_name, int32_t value, int indent = 2) { append_field_prefix(out, field_name, indent); out.set_pos(buf_append_printf(out.data(), DumpBuffer::CAPACITY, out.pos(), "%" PRId32 "\\n", value)); @@ -2790,21 +2812,23 @@ static void dump_field(DumpBuffer &out, const char *field_name, const char *valu out.append("\\n"); } -template<typename T> -static void dump_field(DumpBuffer &out, const char *field_name, T value, int indent = 2) { +// proto_enum_to_string returns PROGMEM pointers, so use append_p +template<typename T> static void dump_field(DumpBuffer &out, const char *field_name, T value, int indent = 2) { append_field_prefix(out, field_name, indent); - out.append(proto_enum_to_string<T>(value)); + out.append_p(proto_enum_to_string<T>(value)); out.append("\\n"); } // Helper for bytes fields - uses stack buffer to avoid heap allocation // Buffer sized for 160 bytes of data (480 chars with separators) to fit typical log buffer +// field_name is a PROGMEM pointer (flash on ESP8266, regular pointer on other platforms) static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint8_t *data, size_t len, int indent = 2) { char hex_buf[format_hex_pretty_size(160)]; append_field_prefix(out, field_name, indent); format_hex_pretty_to(hex_buf, data, len); out.append(hex_buf).append("\\n"); } +#pragma GCC diagnostic pop """ @@ -2977,7 +3001,7 @@ static const char *const TAG = "api.service"; # Add logging helper method declarations hpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" hpp += " protected:\n" - hpp += " void log_send_message_(const char *name, const char *dump);\n" + hpp += " void log_send_message_(const LogString *name, const char *dump);\n" hpp += ( " void log_receive_message_(const LogString *name, const ProtoMessage &msg);\n" ) @@ -2990,10 +3014,8 @@ static const char *const TAG = "api.service"; # Add logging helper method implementations to cpp cpp += "#ifdef HAS_PROTO_MESSAGE_DUMP\n" - cpp += ( - f"void {class_name}::log_send_message_(const char *name, const char *dump) {{\n" - ) - cpp += ' ESP_LOGVV(TAG, "send_message %s: %s", name, dump);\n' + cpp += f"void {class_name}::log_send_message_(const LogString *name, const char *dump) {{\n" + cpp += ' ESP_LOGVV(TAG, "send_message %s: %s", LOG_STR_ARG(name), dump);\n' cpp += "}\n" cpp += f"void {class_name}::log_receive_message_(const LogString *name, const ProtoMessage &msg) {{\n" cpp += " DumpBuffer dump_buf;\n" From 13d3968d9b9220fd777b953aac8efbbba1819013 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:41:09 -1000 Subject: [PATCH 1677/2030] [api] Avoid heap allocation in PSK update timeout lambda (#14921) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- esphome/components/api/api_server.cpp | 28 ++++++++++++++++++--------- esphome/components/api/api_server.h | 4 +++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 17d69405ad..1151bc5983 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -46,10 +46,8 @@ void APIServer::setup() { #ifndef USE_API_NOISE_PSK_FROM_YAML // Only load saved PSK if not set from YAML - SavedNoisePsk noise_pref_saved{}; - if (this->noise_pref_.load(&noise_pref_saved)) { + if (this->load_and_apply_noise_psk_()) { ESP_LOGD(TAG, "Loaded saved Noise PSK"); - this->set_noise_psk(noise_pref_saved.psk); } #endif #endif @@ -514,7 +512,7 @@ void APIServer::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeo #ifdef USE_API_NOISE bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, - const LogString *fail_log_msg, const psk_t &active_psk, bool make_active) { + const LogString *fail_log_msg, bool make_active) { if (!this->noise_pref_.save(&new_psk)) { ESP_LOGW(TAG, "%s", LOG_STR_ARG(fail_log_msg)); return false; @@ -526,9 +524,14 @@ bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString } ESP_LOGD(TAG, "%s", LOG_STR_ARG(save_log_msg)); if (make_active) { - this->set_timeout(100, [this, active_psk]() { + this->set_timeout(100, [this]() { + // Re-read the PSK from preferences rather than capturing the 32-byte array + // in the lambda (which would exceed std::function SBO and heap-allocate). + if (!this->load_and_apply_noise_psk_()) { + ESP_LOGW(TAG, "Failed to load saved PSK for activation"); + return; + } ESP_LOGW(TAG, "Disconnecting all clients to reset PSK"); - this->set_noise_psk(active_psk); for (auto &c : this->clients_) { DisconnectRequest req; c->send_message(req); @@ -538,6 +541,14 @@ bool APIServer::update_noise_psk_(const SavedNoisePsk &new_psk, const LogString return true; } +bool APIServer::load_and_apply_noise_psk_() { + SavedNoisePsk saved{}; + if (!this->noise_pref_.load(&saved)) + return false; + this->set_noise_psk(saved.psk); + return true; +} + bool APIServer::save_noise_psk(psk_t psk, bool make_active) { #ifdef USE_API_NOISE_PSK_FROM_YAML // When PSK is set from YAML, this function should never be called @@ -552,7 +563,7 @@ bool APIServer::save_noise_psk(psk_t psk, bool make_active) { } SavedNoisePsk new_saved_psk{psk}; - return this->update_noise_psk_(new_saved_psk, LOG_STR("Noise PSK saved"), LOG_STR("Failed to save Noise PSK"), psk, + return this->update_noise_psk_(new_saved_psk, LOG_STR("Noise PSK saved"), LOG_STR("Failed to save Noise PSK"), make_active); #endif } @@ -564,8 +575,7 @@ bool APIServer::clear_noise_psk(bool make_active) { return false; #else SavedNoisePsk empty_psk{}; - psk_t empty{}; - return this->update_noise_psk_(empty_psk, LOG_STR("Noise PSK cleared"), LOG_STR("Failed to clear Noise PSK"), empty, + return this->update_noise_psk_(empty_psk, LOG_STR("Noise PSK cleared"), LOG_STR("Failed to clear Noise PSK"), make_active); #endif } diff --git a/esphome/components/api/api_server.h b/esphome/components/api/api_server.h index ccba6deb00..65076879a2 100644 --- a/esphome/components/api/api_server.h +++ b/esphome/components/api/api_server.h @@ -239,7 +239,9 @@ class APIServer final : public Component, #ifdef USE_API_NOISE bool update_noise_psk_(const SavedNoisePsk &new_psk, const LogString *save_log_msg, const LogString *fail_log_msg, - const psk_t &active_psk, bool make_active); + bool make_active); + // Load saved PSK from preferences and apply it. Returns true on success. + bool load_and_apply_noise_psk_(); #endif // USE_API_NOISE #ifdef USE_API_HOMEASSISTANT_STATES // Helper methods to reduce code duplication From a3d9854704a7c448908847f95ea5179e54094547 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:56:36 -1000 Subject: [PATCH 1678/2030] [gpio] Remove redundant last_state_ and pack GPIOBinarySensor fields (#15113) --- .../gpio/binary_sensor/gpio_binary_sensor.cpp | 26 +++++++++---------- .../gpio/binary_sensor/gpio_binary_sensor.h | 20 +++++++------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp index 38ebbc90e4..39b1a2f713 100644 --- a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp +++ b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.cpp @@ -23,9 +23,8 @@ static const LogString *gpio_mode_to_string(bool use_interrupt) { void IRAM_ATTR GPIOBinarySensorStore::gpio_intr(GPIOBinarySensorStore *arg) { bool new_state = arg->isr_pin_.digital_read(); - if (new_state != arg->last_state_) { + if (new_state != arg->state_) { arg->state_ = new_state; - arg->last_state_ = new_state; arg->changed_ = true; // Wake up the component from its disabled loop state if (arg->component_ != nullptr) { @@ -34,28 +33,27 @@ void IRAM_ATTR GPIOBinarySensorStore::gpio_intr(GPIOBinarySensorStore *arg) { } } -void GPIOBinarySensorStore::setup(InternalGPIOPin *pin, gpio::InterruptType type, Component *component) { +void GPIOBinarySensorStore::setup(InternalGPIOPin *pin, Component *component) { pin->setup(); this->isr_pin_ = pin->to_isr(); this->component_ = component; // Read initial state - this->last_state_ = pin->digital_read(); - this->state_ = this->last_state_; + this->state_ = pin->digital_read(); // Attach interrupt - from this point on, any changes will be caught by the interrupt - pin->attach_interrupt(&GPIOBinarySensorStore::gpio_intr, this, type); + pin->attach_interrupt(&GPIOBinarySensorStore::gpio_intr, this, this->interrupt_type_); } void GPIOBinarySensor::setup() { - if (this->use_interrupt_ && !this->pin_->is_internal()) { + if (this->store_.use_interrupt_ && !this->pin_->is_internal()) { ESP_LOGD(TAG, "GPIO is not internal, falling back to polling mode"); - this->use_interrupt_ = false; + this->store_.use_interrupt_ = false; } - if (this->use_interrupt_) { + if (this->store_.use_interrupt_) { auto *internal_pin = static_cast<InternalGPIOPin *>(this->pin_); - this->store_.setup(internal_pin, this->interrupt_type_, this); + this->store_.setup(internal_pin, this); this->publish_initial_state(this->store_.get_state()); } else { this->pin_->setup(); @@ -66,14 +64,14 @@ void GPIOBinarySensor::setup() { void GPIOBinarySensor::dump_config() { LOG_BINARY_SENSOR("", "GPIO Binary Sensor", this); LOG_PIN(" Pin: ", this->pin_); - ESP_LOGCONFIG(TAG, " Mode: %s", LOG_STR_ARG(gpio_mode_to_string(this->use_interrupt_))); - if (this->use_interrupt_) { - ESP_LOGCONFIG(TAG, " Interrupt Type: %s", LOG_STR_ARG(interrupt_type_to_string(this->interrupt_type_))); + ESP_LOGCONFIG(TAG, " Mode: %s", LOG_STR_ARG(gpio_mode_to_string(this->store_.use_interrupt_))); + if (this->store_.use_interrupt_) { + ESP_LOGCONFIG(TAG, " Interrupt Type: %s", LOG_STR_ARG(interrupt_type_to_string(this->store_.interrupt_type_))); } } void GPIOBinarySensor::loop() { - if (this->use_interrupt_) { + if (this->store_.use_interrupt_) { if (this->store_.is_changed()) { // Clear the flag immediately to minimize the window where we might miss changes this->store_.clear_changed(); diff --git a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h index 8b1cc29613..24efc2a0e6 100644 --- a/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h +++ b/esphome/components/gpio/binary_sensor/gpio_binary_sensor.h @@ -8,10 +8,10 @@ namespace esphome { namespace gpio { -// Store class for ISR data (no vtables, ISR-safe) +// Store class for ISR data and configuration (no vtables, ISR-safe) class GPIOBinarySensorStore { public: - void setup(InternalGPIOPin *pin, gpio::InterruptType type, Component *component); + void setup(InternalGPIOPin *pin, Component *component); static void gpio_intr(GPIOBinarySensorStore *arg); @@ -32,11 +32,13 @@ class GPIOBinarySensorStore { } protected: + friend class GPIOBinarySensor; ISRInternalGPIOPin isr_pin_; - volatile bool state_{false}; - volatile bool last_state_{false}; - volatile bool changed_{false}; Component *component_{nullptr}; // Pointer to the component for enable_loop_soon_any_context() + volatile bool state_{false}; + volatile bool changed_{false}; + bool use_interrupt_{true}; + gpio::InterruptType interrupt_type_{gpio::INTERRUPT_ANY_EDGE}; }; class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Component { @@ -44,9 +46,9 @@ class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Compon // No destructor needed: ESPHome components are created at boot and live forever. // Interrupts are only detached on reboot when memory is cleared anyway. - void set_pin(GPIOPin *pin) { pin_ = pin; } - void set_use_interrupt(bool use_interrupt) { use_interrupt_ = use_interrupt; } - void set_interrupt_type(gpio::InterruptType type) { interrupt_type_ = type; } + void set_pin(GPIOPin *pin) { this->pin_ = pin; } + void set_use_interrupt(bool use_interrupt) { this->store_.use_interrupt_ = use_interrupt; } + void set_interrupt_type(gpio::InterruptType type) { this->store_.interrupt_type_ = type; } // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) /// Setup pin @@ -59,8 +61,6 @@ class GPIOBinarySensor final : public binary_sensor::BinarySensor, public Compon protected: GPIOPin *pin_; - bool use_interrupt_{true}; - gpio::InterruptType interrupt_type_{gpio::INTERRUPT_ANY_EDGE}; GPIOBinarySensorStore store_; }; From 8ad8f89e504bb93273ff6e703c6113458ae43536 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:56:53 -1000 Subject: [PATCH 1679/2030] [light] Reorder LightState fields to eliminate padding (#15112) --- esphome/components/light/light_state.h | 32 +++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index b8d72cc832..ab7f2e4df8 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -322,22 +322,6 @@ class LightState : public EntityBase, public Component { FixedVector<LightEffect *> effects_; /// Object used to store the persisted values of the light. ESPPreferenceObject rtc_; - /// Value for storing the index of the currently active effect. 0 if no effect is active - uint32_t active_effect_index_{}; - /// Default transition length for all transitions in ms. - uint32_t default_transition_length_{}; - /// Transition length to use for flash transitions. - uint32_t flash_transition_length_{}; - /// Gamma correction factor for the light. - float gamma_correct_{}; -#ifdef USE_LIGHT_GAMMA_LUT - const uint16_t *gamma_table_{nullptr}; -#endif // USE_LIGHT_GAMMA_LUT - - /// Whether the light value should be written in the next cycle. - bool next_write_{true}; - // for effects, true if a transformer (transition) is active. - bool is_transformer_active_ = false; /** Listeners for remote values changes. * @@ -361,6 +345,22 @@ class LightState : public EntityBase, public Component { /// Initial state of the light. optional<LightStateRTCState> initial_state_{}; + /// Value for storing the index of the currently active effect. 0 if no effect is active + uint32_t active_effect_index_{}; + /// Default transition length for all transitions in ms. + uint32_t default_transition_length_{}; + /// Transition length to use for flash transitions. + uint32_t flash_transition_length_{}; + /// Gamma correction factor for the light. + float gamma_correct_{}; +#ifdef USE_LIGHT_GAMMA_LUT + const uint16_t *gamma_table_{nullptr}; +#endif // USE_LIGHT_GAMMA_LUT + + /// Whether the light value should be written in the next cycle. + bool next_write_{true}; + // for effects, true if a transformer (transition) is active. + bool is_transformer_active_{false}; /// Restore mode of the light. LightRestoreMode restore_mode_; }; From 69911c3db1828e3d7e9447cf92f10d728eaaa543 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:58:36 -1000 Subject: [PATCH 1680/2030] [wifi] Reduce ESP8266 roaming scan dwell time to match ESP32 (#15127) --- .../components/wifi/wifi_component_esp8266.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index f2fabb9080..03800cc3a9 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -664,11 +664,22 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { config.show_hidden = 1; #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 4, 0) config.scan_type = passive ? WIFI_SCAN_TYPE_PASSIVE : WIFI_SCAN_TYPE_ACTIVE; + // Use shorter dwell times for roaming scans - we only need to detect strong + // nearby APs, not do a thorough survey. This also reduces off-channel time + // which can cause Beacon Timeout disconnects on some APs. + // Roaming times match the ESP32 IDF scan defaults. + static constexpr uint32_t SCAN_PASSIVE_DEFAULT_MS = 500; + static constexpr uint32_t SCAN_PASSIVE_ROAMING_MS = 300; + static constexpr uint32_t SCAN_ACTIVE_MIN_DEFAULT_MS = 400; + static constexpr uint32_t SCAN_ACTIVE_MAX_DEFAULT_MS = 500; + static constexpr uint32_t SCAN_ACTIVE_MIN_ROAMING_MS = 100; + static constexpr uint32_t SCAN_ACTIVE_MAX_ROAMING_MS = 300; + bool roaming = this->roaming_state_ == RoamingState::SCANNING; if (passive) { - config.scan_time.passive = 500; + config.scan_time.passive = roaming ? SCAN_PASSIVE_ROAMING_MS : SCAN_PASSIVE_DEFAULT_MS; } else { - config.scan_time.active.min = 400; - config.scan_time.active.max = 500; + config.scan_time.active.min = roaming ? SCAN_ACTIVE_MIN_ROAMING_MS : SCAN_ACTIVE_MIN_DEFAULT_MS; + config.scan_time.active.max = roaming ? SCAN_ACTIVE_MAX_ROAMING_MS : SCAN_ACTIVE_MAX_DEFAULT_MS; } #endif bool ret = wifi_station_scan(&config, &WiFiComponent::s_wifi_scan_done_callback); From df4318505f79ce12c15bd848c3a89ae59aa1c9e9 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Tue, 24 Mar 2026 01:28:04 +0100 Subject: [PATCH 1681/2030] [substitutions] refactor substitute() as a pure function (package refactor part 3) (#15031) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/packages/__init__.py | 9 +- esphome/components/substitutions/__init__.py | 93 ++++++++------------ tests/unit_tests/test_substitutions.py | 46 ++++++++-- 3 files changed, 82 insertions(+), 66 deletions(-) diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index 793cb946dd..f9bdb677a7 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -300,9 +300,14 @@ def do_packages_pass(config: dict, skip_update: bool = False) -> dict: context_vars = package_config.vars if CONF_PACKAGES in package_config or CONF_URL in package_config: # Remote package definition: eagerly resolve before PACKAGE_SCHEMA validation. - from esphome.components.substitutions import substitute_context_vars + from esphome.components.substitutions import ContextVars, substitute - substitute_context_vars(package_config, context_vars) + package_config = substitute( + package_config, + [], + ContextVars(context_vars), + strict_undefined=False, + ) package_config = PACKAGE_SCHEMA(package_config) if isinstance(package_config, str): return package_config # Jinja string, skip processing diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index ecee816ce9..aab1712b65 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -81,12 +81,6 @@ def _restore_data_base(value: Any, orig_value: ESPHomeDataBase) -> ESPHomeDataBa return value -def _try_substitute(value: Any, context: ContextVars) -> Any: - """Substitute variables in value, returning the result or the original if unchanged.""" - result = _substitute_item(value, [], context, strict_undefined=True) - return result if result is not None else value - - def _resolve_var(name: str, context_vars: ContextVars) -> Any: """Look up a substitution variable, falling back to the resolver callback.""" sub = context_vars.get(name, Missing) @@ -253,7 +247,7 @@ def _push_context( if value is Missing: return Missing try: - value = _try_substitute(value, resolver_context) + value = substitute(value, [], resolver_context, True) except UndefinedError as err: unresolvables[key] = (value, err) return Missing @@ -297,68 +291,51 @@ def push_context( return parent_context -def _substitute_item( +def substitute( item: Any, path: SubstitutionPath, parent_context: ContextVars, strict_undefined: bool, errors: ErrList | None = None, -) -> Any | None: - """Recursively substitute variables in a config item. +) -> Any: + """Returns a recursively substituted version of `item`.""" - Walks dicts, lists, strings, Lambdas, Extend, and Remove nodes, - replacing variable references with values from context_vars. - Mutates containers in-place; returns a replacement value for - strings/scalars, or None if the item was unchanged. - """ + if isinstance(item, ESPLiteralValue): + return item # do not substitute inside literal blocks - def _walk(item: Any, path: SubstitutionPath, parent_ctx: ContextVars) -> Any | None: - if isinstance(item, ESPLiteralValue): - return None # do not substitute inside literal blocks + # Push the current item's context onto the context stack + context_vars = push_context(item, parent_context, errors) - ctx = push_context(item, parent_ctx, errors) + result = item - if isinstance(item, list): - for idx, it in enumerate(item): - sub = _walk(it, path + [idx], ctx) - if sub is not None: - item[idx] = sub - elif isinstance(item, dict): - replace_keys: list[tuple[str, Any]] = [] - for k, v in item.items(): - if path or k != CONF_SUBSTITUTIONS: - sub = _walk(k, path + [k], ctx) - if sub is not None: - replace_keys.append((k, sub)) - sub = _walk(v, path + [k], ctx) - if sub is not None: - item[k] = sub - for old, new in replace_keys: - if str(new) == str(old): - item[new] = item[old] - else: - item[new] = merge_config(item.get(new), item.get(old)) - del item[old] - elif isinstance(item, str): - sub = _expand_substitutions(item, path, ctx, strict_undefined, errors) - if not isinstance(sub, str) or sub != item: - return sub - elif isinstance(item, (core.Lambda, Extend, Remove)) and item.value: - sub = _expand_substitutions(item.value, path, ctx, strict_undefined, errors) - if sub != item.value: - item.value = sub - return None + if isinstance(item, list): + result = [ + substitute(it, path + [i], context_vars, strict_undefined, errors) + for i, it in enumerate(item) + ] - return _walk(item, path, parent_context) + elif isinstance(item, dict): + result = OrderedDict() + for k, v in item.items(): + v = substitute(v, path + [k], context_vars, strict_undefined, errors) + k = substitute(k, path + [k], context_vars, strict_undefined, errors) + result[k] = merge_config(result.get(k), v) + elif isinstance(item, str): + result = _expand_substitutions( + item, path, context_vars, strict_undefined, errors + ) -def substitute_context_vars(node: Any, context_vars: dict[str, Any]) -> None: - """Eagerly substitute context vars into a config node in-place. + elif isinstance(item, (core.Lambda, Extend, Remove)) and item.value: + value = _expand_substitutions( + item.value, path, context_vars, strict_undefined, errors + ) + if item.value != value: + result = type(item)(value) - Undefined variables are silently ignored — this is used before - the main substitution pass when not all variables are visible yet. - """ - _substitute_item(node, [], ContextVars(context_vars), strict_undefined=False) + if isinstance(item, ESPHomeDataBase): + result = make_data_base(result, item) + return result def _warn_unresolved_variables(errors: ErrList) -> None: @@ -387,7 +364,7 @@ def do_substitution_pass( Extracts the ``substitutions:`` block, merges in any command-line overrides, resolves inter-variable dependencies, then walks the config tree replacing all ``$var`` / ``${expr}`` references. - Returns the (mutated) config dict with resolved substitutions + Returns a new config dict with resolved substitutions restored at the front. """ # Extract substitutions from config, overriding with substitutions coming from command line: @@ -415,7 +392,7 @@ def do_substitution_pass( errors: ErrList = [] # Collect undefined errors during substitution parent_context, substitutions = _push_context(substitutions, ContextVars(), errors) - _substitute_item(config, [], parent_context, False, errors) + config = substitute(config, [], parent_context, False, errors) if errors: _warn_unresolved_variables(errors) diff --git a/tests/unit_tests/test_substitutions.py b/tests/unit_tests/test_substitutions.py index db46a27dfb..30478f9521 100644 --- a/tests/unit_tests/test_substitutions.py +++ b/tests/unit_tests/test_substitutions.py @@ -550,8 +550,8 @@ def test_lambda_substitution() -> None: "lambda": lam, } ) - substitutions.do_substitution_pass(config) - assert lam.value == "return 42;" + config = substitutions.do_substitution_pass(config) + assert config["lambda"].value == "return 42;" def test_lambda_no_substitution_unchanged() -> None: @@ -564,8 +564,8 @@ def test_lambda_no_substitution_unchanged() -> None: "lambda": lam, } ) - substitutions.do_substitution_pass(config) - assert lam.value is original_value + config = substitutions.do_substitution_pass(config) + assert config["lambda"].value is original_value def test_extend_substitution() -> None: @@ -577,8 +577,42 @@ def test_extend_substitution() -> None: "sensor": ext, } ) - substitutions.do_substitution_pass(config) - assert ext.value == "my_sensor" + config = substitutions.do_substitution_pass(config) + assert config["sensor"].value == "my_sensor" + + +def test_substitute_does_not_mutate_input() -> None: + """substitute() must return a new tree without modifying the original.""" + inner_list = ["${var}", "static"] + inner_dict = OrderedDict({"key": "${var}"}) + lam = Lambda("return ${var};") + config = OrderedDict( + { + "a_list": inner_list, + "a_dict": inner_dict, + "a_lambda": lam, + "plain": "${var}", + } + ) + context = substitutions.ContextVars({"var": "replaced"}) + result = substitutions.substitute(config, [], context, strict_undefined=True) + + # Result has substitutions applied + assert result["plain"] == "replaced" + assert result["a_list"] == ["replaced", "static"] + assert result["a_dict"]["key"] == "replaced" + assert result["a_lambda"].value == "return replaced;" + + # Original input is untouched + assert config["plain"] == "${var}" + assert inner_list == ["${var}", "static"] + assert inner_dict["key"] == "${var}" + assert lam.value == "return ${var};" + + # Containers are new objects, not the originals + assert result["a_list"] is not inner_list + assert result["a_dict"] is not inner_dict + assert result["a_lambda"] is not lam def test_do_substitution_pass_substitutions_must_be_mapping_from_config() -> None: From fe2c4e47bfc3c622179b6d006703151a3ee7f39f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 14:40:02 -1000 Subject: [PATCH 1682/2030] [sensor] Deprecate .raw_state, guard raw_callback_ behind USE_SENSOR_FILTER (#15094) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/haier/hon_climate.cpp | 2 +- .../nextion/sensor/nextion_sensor.cpp | 4 --- esphome/components/sensor/sensor.cpp | 10 +++++-- esphome/components/sensor/sensor.h | 28 ++++++++++++++----- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 92defe560e..1cee95bf16 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -748,7 +748,7 @@ void HonClimate::update_sub_sensor_(SubSensorType type, float value) { if (type < SubSensorType::SUB_SENSOR_TYPE_COUNT) { size_t index = (size_t) type; if ((this->sub_sensors_[index] != nullptr) && - ((!this->sub_sensors_[index]->has_state()) || (this->sub_sensors_[index]->raw_state != value))) + ((!this->sub_sensors_[index]->has_state()) || (this->sub_sensors_[index]->get_raw_state() != value))) this->sub_sensors_[index]->publish_state(value); } } diff --git a/esphome/components/nextion/sensor/nextion_sensor.cpp b/esphome/components/nextion/sensor/nextion_sensor.cpp index 03b7261239..9ea12cf808 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.cpp +++ b/esphome/components/nextion/sensor/nextion_sensor.cpp @@ -85,10 +85,6 @@ void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { } this->publish_state(published_state); - } else { - this->raw_state = state; - this->state = state; - this->set_has_state(true); } } this->update_component_settings(); diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index b4e59dfeb5..aad7f86dcf 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -40,7 +40,10 @@ const LogString *state_class_to_string(StateClass state_class) { return StateClassStrings::get_log_str(static_cast<uint8_t>(state_class), 0); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" Sensor::Sensor() : state(NAN), raw_state(NAN) {} +#pragma GCC diagnostic pop int8_t Sensor::get_accuracy_decimals() { if (this->sensor_flags_.has_accuracy_override) @@ -63,8 +66,13 @@ StateClass Sensor::get_state_class() { } void Sensor::publish_state(float state) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" this->raw_state = state; +#pragma GCC diagnostic pop +#ifdef USE_SENSOR_FILTER this->raw_callback_.call(state); +#endif ESP_LOGV(TAG, "'%s': Received new state %f", this->name_.c_str(), state); @@ -110,8 +118,6 @@ void Sensor::clear_filters() { this->filter_list_ = nullptr; } #endif // USE_SENSOR_FILTER -float Sensor::get_state() const { return this->state; } -float Sensor::get_raw_state() const { return this->raw_state; } void Sensor::internal_send_state_to_frontend(float state) { this->set_has_state(true); diff --git a/esphome/components/sensor/sensor.h b/esphome/components/sensor/sensor.h index b3bd962036..f4ea4af985 100644 --- a/esphome/components/sensor/sensor.h +++ b/esphome/components/sensor/sensor.h @@ -95,9 +95,14 @@ class Sensor : public EntityBase { #endif /// Getter-syntax for .state. - float get_state() const; + float get_state() const { return this->state; } /// Getter-syntax for .raw_state - float get_raw_state() const; + float get_raw_state() const { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + return this->raw_state; +#pragma GCC diagnostic pop + } /** Publish a new state to the front-end. * @@ -113,8 +118,14 @@ class Sensor : public EntityBase { /// Add a callback that will be called every time a filtered value arrives. template<typename F> void add_on_state_callback(F &&callback) { this->callback_.add(std::forward<F>(callback)); } /// Add a callback that will be called every time the sensor sends a raw value. + /// When USE_SENSOR_FILTER is not enabled, delegates to the regular callback + /// since raw state equals filtered state without filter support compiled in. template<typename F> void add_on_raw_state_callback(F &&callback) { +#ifdef USE_SENSOR_FILTER this->raw_callback_.add(std::forward<F>(callback)); +#else + this->callback_.add(std::forward<F>(callback)); +#endif } /** This member variable stores the last state that has passed through all filters. @@ -126,17 +137,20 @@ class Sensor : public EntityBase { */ float state; - /** This member variable stores the current raw state of the sensor, without any filters applied. - * - * Unlike .state,this will be updated immediately when publish_state is called. - */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// @deprecated Use get_raw_state() instead. This member will be removed in ESPHome 2026.10.0. + ESPDEPRECATED("Use get_raw_state() instead of .raw_state. Will be removed in 2026.10.0", "2026.4.0") float raw_state; +#pragma GCC diagnostic pop void internal_send_state_to_frontend(float state); protected: +#ifdef USE_SENSOR_FILTER LazyCallbackManager<void(float)> raw_callback_; ///< Storage for raw state callbacks. - LazyCallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks. +#endif + LazyCallbackManager<void(float)> callback_; ///< Storage for filtered state callbacks. #ifdef USE_SENSOR_FILTER Filter *filter_list_{nullptr}; ///< Store all active filters. From 793813790a36d782a726b9b9258b3403ce08c34a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 15:52:39 -1000 Subject: [PATCH 1683/2030] [api] Precompute tag bytes for forced varint and length-delimited fields (#15067) --- esphome/components/api/api_pb2.cpp | 10 ++-- esphome/components/api/proto.h | 11 +++++ script/api_protobuf/api_protobuf.py | 75 +++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 61b034c7ea..f77f4df545 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -2249,10 +2249,14 @@ bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, return true; } void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address, true); - buffer.encode_sint32(2, this->rssi, true); + buffer.write_raw_byte(8); + buffer.encode_varint_raw_64(this->address); + buffer.write_raw_byte(16); + buffer.encode_varint_raw(encode_zigzag32(this->rssi)); buffer.encode_uint32(3, this->address_type); - buffer.encode_bytes(4, this->data, this->data_len, true); + buffer.write_raw_byte(34); + buffer.encode_varint_raw(this->data_len); + buffer.encode_raw(this->data, this->data_len); } uint32_t BluetoothLERawAdvertisement::calculate_size() const { uint32_t size = 0; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 95a79105a3..b629018a91 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -229,6 +229,17 @@ class ProtoWriteBuffer { * Following https://protobuf.dev/programming-guides/encoding/#structure */ void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); } + /// Write a single precomputed tag byte. Tag must be < 128. + inline void write_raw_byte(uint8_t b) ESPHOME_ALWAYS_INLINE { + this->debug_check_bounds_(1); + *this->pos_++ = b; + } + /// Write raw bytes to the buffer (no tag, no length prefix). + inline void encode_raw(const void *data, size_t len) ESPHOME_ALWAYS_INLINE { + this->debug_check_bounds_(len); + std::memcpy(this->pos_, data, len); + this->pos_ += len; + } /// Write a precomputed tag byte + 32-bit value in one operation. /// Tag must be a single-byte varint (< 128). No zero check. inline void write_tag_and_fixed32(uint8_t tag, uint32_t value) ESPHOME_ALWAYS_INLINE { diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 81ea93caf4..f2a11141af 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -221,8 +221,58 @@ class TypeInfo(ABC): decode_64bit = None + # Mapping from encode_func to raw encode expression template. + # When a forced field has a single-byte tag, the code generator emits + # write_raw_byte(tag) + raw encode instead of the full encode_* method, + # eliminating the zero-check branch and encode_field_raw indirection. + # {value} is replaced with the actual field expression. + RAW_ENCODE_MAP: dict[str, str] = { + "encode_uint32": "buffer.encode_varint_raw({value});", + "encode_uint64": "buffer.encode_varint_raw_64({value});", + "encode_sint32": "buffer.encode_varint_raw(encode_zigzag32({value}));", + "encode_sint64": "buffer.encode_varint_raw_64(encode_zigzag64({value}));", + "encode_int64": "buffer.encode_varint_raw_64(static_cast<uint64_t>({value}));", + "encode_bool": "buffer.write_raw_byte({value} ? 0x01 : 0x00);", + } + + def _encode_with_precomputed_tag(self, value_expr: str) -> str | None: + """Try to emit a precomputed-tag encode for a forced field. + + Returns the raw encode string if the tag is a single byte and the + encode_func has a known raw equivalent, or None otherwise. + """ + if not self.force: + return None + tag = self.calculate_tag() + if tag >= 128: + return None + raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) + if raw_expr is None: + return None + return f"buffer.write_raw_byte({tag});\n{raw_expr.format(value=value_expr)}" + + def _encode_bytes_with_precomputed_tag( + self, data_expr: str, len_expr: str + ) -> str | None: + """Try to emit a precomputed-tag encode for a forced bytes/string field. + + Returns the raw encode string if the tag is a single byte, or None. + """ + if not self.force: + return None + tag = self.calculate_tag() + if tag >= 128: + return None + return ( + f"buffer.write_raw_byte({tag});\n" + f"buffer.encode_varint_raw({len_expr});\n" + f"buffer.encode_raw({data_expr}, {len_expr});" + ) + @property def encode_content(self) -> str: + if result := self._encode_with_precomputed_tag(f"this->{self.field_name}"): + return result if self.force: return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);" return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" @@ -635,6 +685,11 @@ class StringType(TypeInfo): @property def encode_content(self) -> str: # Use the StringRef + if result := self._encode_bytes_with_precomputed_tag( + f"this->{self.field_name}_ref_.c_str()", + f"this->{self.field_name}_ref_.size()", + ): + return result if self.force: return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_, true);" return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);" @@ -801,6 +856,10 @@ class BytesType(TypeInfo): @property def encode_content(self) -> str: + if result := self._encode_bytes_with_precomputed_tag( + f"this->{self.field_name}_ptr_", f"this->{self.field_name}_len_" + ): + return result if self.force: return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" @@ -908,6 +967,10 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): @property def encode_content(self) -> str: + if result := self._encode_bytes_with_precomputed_tag( + f"this->{self.field_name}", f"this->{self.field_name}_len" + ): + return result if self.force: return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" @@ -957,6 +1020,10 @@ class PointerToStringBufferType(PointerToBufferTypeBase): @property def encode_content(self) -> str: + if result := self._encode_bytes_with_precomputed_tag( + f"this->{self.field_name}.c_str()", f"this->{self.field_name}.size()" + ): + return result if self.force: return ( f"buffer.encode_string({self.number}, this->{self.field_name}, true);" @@ -1124,6 +1191,10 @@ class FixedArrayBytesType(TypeInfo): @property def encode_content(self) -> str: + if result := self._encode_bytes_with_precomputed_tag( + f"this->{self.field_name}", f"this->{self.field_name}_len" + ): + return result if self.force: return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" @@ -1199,6 +1270,10 @@ class EnumType(TypeInfo): @property def encode_content(self) -> str: + if result := self._encode_with_precomputed_tag( + f"static_cast<uint32_t>(this->{self.field_name})" + ): + return result if self.force: return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}), true);" return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}));" From 7eddf429ea3810f4e1b019b13c20f768de936411 Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Tue, 24 Mar 2026 10:57:22 +0100 Subject: [PATCH 1684/2030] [substitutions] speed up config loading: substitutions pass and `!include` redesign (package refactor part 4) (#12126) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/packages/__init__.py | 406 ++++++++++++------ esphome/config.py | 6 +- tests/component_tests/packages/test_init.py | 4 +- .../component_tests/packages/test_packages.py | 178 +++++++- .../06-remote_packages.approved.yaml | 21 +- .../06-remote_packages.input.yaml | 22 +- .../07-package_merging.approved.yaml | 2 - .../08-include_hierarchy.approved.yaml | 49 +++ .../08-include_hierarchy.input.yaml | 16 + .../10-dynamic_packages.approved.yaml | 69 +++ .../10-dynamic_packages.input.yaml | 62 +++ .../substitutions/level1_package.yaml | 21 + .../substitutions/level2_package.yaml | 21 + .../substitutions/level3_package.yaml | 16 + .../fixtures/substitutions/package2.yaml | 10 + tests/unit_tests/test_substitutions.py | 4 +- tests/unit_tests/test_yaml_util.py | 42 +- 17 files changed, 781 insertions(+), 168 deletions(-) create mode 100644 tests/unit_tests/fixtures/substitutions/08-include_hierarchy.approved.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/08-include_hierarchy.input.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/10-dynamic_packages.approved.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/10-dynamic_packages.input.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/level1_package.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/level2_package.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/level3_package.yaml create mode 100644 tests/unit_tests/fixtures/substitutions/package2.yaml diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index f9bdb677a7..1a6df84fe0 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -6,6 +6,7 @@ from pathlib import Path from typing import Any from esphome import git, yaml_util +from esphome.components.substitutions import ContextVars, push_context, substitute from esphome.components.substitutions.jinja import has_jinja from esphome.config_helpers import Remove, merge_config import esphome.config_validation as cv @@ -32,43 +33,44 @@ _LOGGER = logging.getLogger(__name__) DOMAIN = CONF_PACKAGES -def validate_has_jinja(value: Any): - if not isinstance(value, str) or not has_jinja(value): - raise cv.Invalid("string does not contain Jinja syntax") - return value +def is_remote_package(package_config: dict) -> bool: + """Returns True if the package_config is a remote package definition.""" + return CONF_URL in package_config -def valid_package_contents(allow_jinja: bool = True) -> Callable[[Any], dict]: - """Returns a validator that checks if a package_config that will be merged looks as - much as possible to a valid config to fail early on obvious mistakes.""" +def valid_package_contents(package_config: dict) -> dict: + """Validate that a package looks like a plausible ESPHome config fragment. - def validator(package_config: dict) -> dict: - if isinstance(package_config, dict): - if CONF_URL in package_config: - # If a URL key is found, then make sure the config conforms to a remote package schema: - return REMOTE_PACKAGE_SCHEMA(package_config) - - # Validate manually since Voluptuous would regenerate dicts and lose metadata - # such as ESPHomeDataBase - for k, v in package_config.items(): - if not isinstance(k, str): - raise cv.Invalid("Package content keys must be strings") - if isinstance(v, (dict, list, Remove)): - continue # e.g. script: [], psram: !remove, logger: {level: debug} - if v is None: - continue # e.g. web_server: - if allow_jinja and isinstance(v, str) and has_jinja(v): - # e.g: remote package shorthand: - # package_name: github://esphome/repo/file.yaml@${ branch }, or: - # switch: ${ expression that evals to a switch } - continue - - raise cv.Invalid("Invalid component content in package definition") - return package_config + Rejects non-dict values, remote package schemas (which should have been + handled earlier), non-string keys, and scalar values that aren't Jinja + expressions. This is a lightweight check to catch obvious mistakes before + full component validation runs later. + """ + if not isinstance(package_config, dict): raise cv.Invalid("Package contents must be a dict") - return validator + if is_remote_package(package_config): + # Package contents must not contain a root `url:` key + raise cv.Invalid("Remote package schema not expected here") + + # Validate manually since Voluptuous would regenerate dicts and lose metadata + # such as ESPHomeDataBase + for k, v in package_config.items(): + if not isinstance(k, str): + raise cv.Invalid("Package content keys must be strings") + if isinstance(v, (dict, list, Remove)): + continue # e.g. script: [], psram: !remove, logger: {level: debug} + if v is None: + continue # e.g. web_server: + if isinstance(v, str) and has_jinja(v): + # e.g: remote package shorthand: + # package_name: github://esphome/repo/file.yaml@${ branch }, or: + # switch: ${ expression that evals to a switch } + continue + + raise cv.Invalid("Invalid component content in package definition") + return package_config def expand_file_to_files(config: dict): @@ -105,7 +107,7 @@ def validate_source_shorthand(value): return REMOTE_PACKAGE_SCHEMA(conf) -def deprecate_single_package(config): +def deprecate_single_package(config: dict) -> dict: _LOGGER.warning( """ Including a single package under `packages:`, i.e., `packages: !include mypackage.yaml` is deprecated. @@ -158,10 +160,7 @@ REMOTE_PACKAGE_SCHEMA = cv.All( PACKAGE_SCHEMA = cv.Any( # A package definition is either: validate_source_shorthand, # A git URL shorthand string that expands to a remote package schema, or REMOTE_PACKAGE_SCHEMA, # a valid remote package schema, or - validate_has_jinja, # a Jinja string that may resolve to a package, or - valid_package_contents( - allow_jinja=True - ), # Something that at least looks like an actual package, e.g. {wifi:{ssid: xxx}} + valid_package_contents, # Something that at least looks like an actual package, e.g. {wifi:{ssid: xxx}} # which will have to be fully validated later as per each component's schema. ) @@ -179,7 +178,15 @@ CONFIG_SCHEMA = cv.Any( # under `packages:` we can have either: def _process_remote_package(config: dict, skip_update: bool = False) -> dict: - # When skip_update is True, use NEVER_REFRESH to prevent updates + """Clone/update a git repo and load the YAML files listed in the package definition. + + Returns ``{"packages": {<filename>: <loaded_yaml>, ...}}`` so the caller + can recurse into the loaded packages. Each loaded YAML node is tagged + with any ``vars:`` from the file entry via :func:`yaml_util.add_context`. + + If loading fails after cloning, attempts a revert and retry in case + a prior cached checkout is stale. + """ actual_refresh = git.NEVER_REFRESH if skip_update else config[CONF_REFRESH] repo_dir, revert = git.clone_or_update( url=config[CONF_URL], @@ -189,7 +196,7 @@ def _process_remote_package(config: dict, skip_update: bool = False) -> dict: username=config.get(CONF_USERNAME), password=config.get(CONF_PASSWORD), ) - files = [] + files: list[dict[str, Any]] = [] if base_path := config.get(CONF_PATH): repo_dir = repo_dir / base_path @@ -200,126 +207,255 @@ def _process_remote_package(config: dict, skip_update: bool = False) -> dict: else: files.append(file) - def get_packages(files) -> dict: - packages = {} + def _load_package_yaml(yaml_file: Path, filename: str) -> dict: + """Load a YAML file from a remote package, validating min_version.""" + try: + new_yaml = yaml_util.load_yaml(yaml_file) + except EsphomeError as e: + raise cv.Invalid( + f"{filename} is not a valid YAML file." + f" Please check the file contents.\n{e}" + ) from e + esphome_config = new_yaml.get(CONF_ESPHOME) or {} + min_version = esphome_config.get(CONF_MIN_VERSION) + if min_version is not None and cv.Version.parse(min_version) > cv.Version.parse( + ESPHOME_VERSION + ): + raise cv.Invalid( + f"Current ESPHome Version is too old to use" + f" this package: {ESPHOME_VERSION} < {min_version}" + ) + return new_yaml + + def get_packages(files: list[dict[str, Any]]) -> dict: + packages: dict[str, Any] = {} for idx, file in enumerate(files): filename = file[CONF_PATH] yaml_file: Path = repo_dir / filename - vars = file.get(CONF_VARS, {}) - if not yaml_file.is_file(): raise cv.Invalid( f"{filename} does not exist in repository", path=[CONF_FILES, idx, CONF_PATH], ) - - try: - new_yaml = yaml_util.load_yaml(yaml_file) - if ( - CONF_ESPHOME in new_yaml - and CONF_MIN_VERSION in new_yaml[CONF_ESPHOME] - ): - min_version = new_yaml[CONF_ESPHOME][CONF_MIN_VERSION] - if cv.Version.parse(min_version) > cv.Version.parse( - ESPHOME_VERSION - ): - raise cv.Invalid( - f"Current ESPHome Version is too old to use this package: {ESPHOME_VERSION} < {min_version}" - ) - new_yaml = yaml_util.add_context(new_yaml, vars or None) - packages[f"{filename}{idx}"] = new_yaml - except EsphomeError as e: - raise cv.Invalid( - f"{filename} is not a valid YAML file. Please check the file contents.\n{e}" - ) from e + new_yaml = _load_package_yaml(yaml_file, filename) + new_yaml = yaml_util.add_context(new_yaml, file.get(CONF_VARS)) + packages[f"{filename}{idx}"] = new_yaml return packages - packages = None - error = "" - - try: - packages = get_packages(files) - except cv.Invalid as e: - error = e + if revert is not None: + # If loading fails, the cached checkout may be stale — revert and retry once. try: - if revert is not None: - revert() - packages = get_packages(files) - except cv.Invalid as er: - error = er + return {CONF_PACKAGES: get_packages(files)} + except cv.Invalid: + revert() + try: + return {CONF_PACKAGES: get_packages(files)} + except cv.Invalid as err: + raise cv.Invalid(f"Failed to load packages. {err}", path=err.path) from err - if packages is None: - raise cv.Invalid(f"Failed to load packages. {error}", path=error.path) + return {CONF_PACKAGES: get_packages(files)} - return {"packages": packages} + +def _walk_package_dict( + packages: dict, + callback: Callable[[dict, ContextVars | None], dict], + context: ContextVars | None, +) -> cv.Invalid | None: + """Iterate a packages dict in reverse priority order, invoking callback on each entry. + + Returns ``None`` on success, or the first :class:`cv.Invalid` error if a callback fails. + """ + for package_name, package_config in reversed(packages.items()): + with cv.prepend_path(package_name): + try: + packages[package_name] = callback(package_config, context) + except cv.Invalid as err: + return err + return None + + +def _walk_package_list( + packages: list, + callback: Callable[[dict, ContextVars | None], dict], + context: ContextVars | None, +) -> None: + """Iterate a packages list in reverse priority order, invoking callback on each entry.""" + for idx in reversed(range(len(packages))): + with cv.prepend_path(idx): + packages[idx] = callback(packages[idx], context) def _walk_packages( - config: dict, callback: Callable[[dict], dict], validate_deprecated: bool = True + config: dict, + callback: Callable[[dict, ContextVars | None], dict], + context: ContextVars | None = None, + validate_deprecated: bool = True, ) -> dict: + """Walks the packages structure in priority order, invoking ``callback`` on each package definition found. + + This function only iterates over the immediate ``packages:`` entries in *config*. + If packages may contain nested ``packages:`` keys, the *callback* is responsible + for recursing by calling ``_walk_packages`` on the returned package config. + """ if CONF_PACKAGES not in config: return config packages = config[CONF_PACKAGES] - # The following block and `validate_deprecated` parameter can be safely removed - # once single-package deprecation is effective - if validate_deprecated: - packages = CONFIG_SCHEMA(packages) + if not isinstance(packages, (dict, list)): + raise cv.Invalid( + f"Packages must be a key to value mapping or list, got {type(packages)} instead" + ) with cv.prepend_path(CONF_PACKAGES): - if isinstance(packages, dict): - for package_name, package_config in reversed(packages.items()): - with cv.prepend_path(package_name): - package_config = callback(package_config) - packages[package_name] = _walk_packages(package_config, callback) - elif isinstance(packages, list): - for idx in reversed(range(len(packages))): - with cv.prepend_path(idx): - package_config = callback(packages[idx]) - packages[idx] = _walk_packages(package_config, callback) - else: - raise cv.Invalid( - f"Packages must be a key to value mapping or list, got {type(packages)} instead" - ) + if not isinstance(packages, dict): + _walk_package_list(packages, callback, context) + elif (result := _walk_package_dict(packages, callback, context)) is not None: + if not validate_deprecated: + raise result + # Fallback: treat the dict as a single deprecated package. + # Note: this catches *any* cv.Invalid from the callback, which may + # mask real validation errors in named package dicts. + # This block can be removed once the single-package + # deprecation period (2026.7.0) is over. + config[CONF_PACKAGES] = [packages] + return _walk_packages(deprecate_single_package(config), callback, context) + config[CONF_PACKAGES] = packages return config -def do_packages_pass(config: dict, skip_update: bool = False) -> dict: - """Processes, downloads and validates all packages in the config. - Also extracts and merges all substitutions found in packages into the main config substitutions. +def _substitute_package_definition( + package_config: dict | str, context_vars: ContextVars | None +) -> dict | str: + """Substitute variables in a package definition string or remote package dict. + + Only substitutes strings and remote package dicts (URLs, refs, paths). + Local package contents are left untouched — they will be substituted + later during the main substitution pass. + """ + if isinstance(package_config, str) or ( + isinstance(package_config, dict) and is_remote_package(package_config) + ): + package_config = substitute( + item=package_config, + path=[], + parent_context=context_vars or ContextVars(), + strict_undefined=False, + ) + return package_config + + +def _update_substitutions_context( + parent_context: UserDict, + package_substitutions: dict[str, Any], +) -> None: + """Resolve and add new substitutions to the parent context. + + Skips keys already present (higher-priority sources win). + String values are substituted against the current context so that + cross-references between substitutions are expanded when possible. + """ + for key, value in package_substitutions.items(): + if key in parent_context: + continue + if not isinstance(value, str): + parent_context[key] = value + continue + parent_context[key] = substitute( + item=value, + path=[CONF_SUBSTITUTIONS, key], + parent_context=ContextVars(parent_context), + strict_undefined=False, + ) + + +class _PackageProcessor: + """Stateful processor that resolves packages and collects substitutions. + + Packages are processed highest-priority first (later-declared before + earlier-declared) so that their substitutions are available when + resolving lower-priority package definitions. For each entry: + + 1. Substitute variables in remote package definitions (URLs, refs, paths). + 2. Validate against ``PACKAGE_SCHEMA`` and download remote packages. + 3. Extract ``substitutions:`` and merge into the shared context + (higher-priority packages win on conflicts). + 4. Recurse into any nested ``packages:`` keys. + + Command-line substitutions take the highest priority and are never overridden. + """ + + def __init__( + self, + substitutions: UserDict, + command_line_substitutions: dict[str, Any] | None, + skip_update: bool, + ) -> None: + self.substitutions = substitutions + self.parent_context = UserDict(command_line_substitutions or {}) + self.skip_update = skip_update + + def resolve_package( + self, package_config: dict | str, context_vars: ContextVars | None + ) -> dict: + """Substitute variables in the definition and fetch remote packages. + + The input may be a ``str`` (git shorthand or Jinja expression) or a + ``dict`` (remote or local package). After ``PACKAGE_SCHEMA`` validation + the result is always a ``dict``. + """ + package_config = _substitute_package_definition(package_config, context_vars) + package_config = PACKAGE_SCHEMA(package_config) + if is_remote_package(package_config): + package_config = _process_remote_package(package_config, self.skip_update) + return package_config + + def collect_substitutions(self, package_config: dict) -> None: + """Extract substitutions from a package and merge into the shared context.""" + if subs := package_config.pop(CONF_SUBSTITUTIONS, {}): + self.substitutions.data = merge_config(subs, self.substitutions.data) + _update_substitutions_context(self.parent_context, subs) + + def process_package( + self, package_config: dict | str, context_vars: ContextVars | None + ) -> dict: + """Resolve a single package and recurse into any nested packages.""" + package_config = self.resolve_package(package_config, context_vars) + self.collect_substitutions(package_config) + + if CONF_PACKAGES not in package_config: + return package_config + + # Push context from !include vars on the package root and on the packages key + context_vars = push_context(package_config, context_vars) + context_vars = push_context(package_config[CONF_PACKAGES], context_vars) + return _walk_packages(package_config, self.process_package, context_vars) + + +def do_packages_pass( + config: dict, + *, + command_line_substitutions: dict[str, Any] | None = None, + skip_update: bool = False, +) -> dict: + """Load, validate, and flatten all packages in the config. + + Returns the config with all packages loaded in-place (but not yet merged) + and a consolidated ``substitutions:`` block restored at the front. """ if CONF_PACKAGES not in config: return config substitutions = UserDict(config.pop(CONF_SUBSTITUTIONS, {})) + processor = _PackageProcessor( + substitutions, command_line_substitutions, skip_update + ) + _update_substitutions_context(processor.parent_context, substitutions) - def process_package_callback(package_config: dict) -> dict: - """This will be called for each package found in the config.""" - if isinstance(package_config, yaml_util.ConfigContext): - context_vars = package_config.vars - if CONF_PACKAGES in package_config or CONF_URL in package_config: - # Remote package definition: eagerly resolve before PACKAGE_SCHEMA validation. - from esphome.components.substitutions import ContextVars, substitute - - package_config = substitute( - package_config, - [], - ContextVars(context_vars), - strict_undefined=False, - ) - package_config = PACKAGE_SCHEMA(package_config) - if isinstance(package_config, str): - return package_config # Jinja string, skip processing - if CONF_URL in package_config: - package_config = _process_remote_package(package_config, skip_update) - # Extract substitutions from the package and merge them into the main substitutions: - substitutions.data = merge_config( - package_config.pop(CONF_SUBSTITUTIONS, {}), substitutions.data - ) - return package_config - - _walk_packages(config, process_package_callback) + context_vars = push_context( + config[CONF_PACKAGES], ContextVars(processor.parent_context) + ) + _walk_packages(config, processor.process_package, context_vars) if substitutions: config[CONF_SUBSTITUTIONS] = substitutions.data @@ -328,19 +464,27 @@ def do_packages_pass(config: dict, skip_update: bool = False) -> dict: def merge_packages(config: dict) -> dict: - """Merges all packages into the main config and removes the `packages:` key.""" + """Flatten the ``packages:`` tree into the main config. + + Collects every package (including nested ones) into a flat list in + priority order, then merges them into *config* using :func:`merge_config`. + Higher-priority packages (declared later) override lower-priority ones. + + The ``packages:`` key is removed from the returned config. + Must be called after :func:`do_packages_pass` has resolved all packages. + """ if CONF_PACKAGES not in config: return config # Build flat list of all package configs to merge in priority order: merge_list: list[dict] = [] - validate_package = valid_package_contents(allow_jinja=False) - - def process_package_callback(package_config: dict) -> dict: + def process_package_callback( + package_config: dict, context: ContextVars | None + ) -> dict: """This will be called for each package found in the config.""" - merge_list.append(validate_package(package_config)) - return package_config + merge_list.append(package_config) + return _walk_packages(package_config, process_package_callback) _walk_packages(config, process_package_callback, validate_deprecated=False) # Merge all packages into the main config: diff --git a/esphome/config.py b/esphome/config.py index b80aaf3700..7a6feea3d3 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -989,7 +989,11 @@ def validate_config( result.add_output_path([CONF_PACKAGES], CONF_PACKAGES) try: - config = do_packages_pass(config, skip_update=skip_external_update) + config = do_packages_pass( + config, + command_line_substitutions=command_line_substitutions, + skip_update=skip_external_update, + ) except vol.Invalid as err: result.update(config) result.add_error(err) diff --git a/tests/component_tests/packages/test_init.py b/tests/component_tests/packages/test_init.py index 779244e2ed..fd30c2433f 100644 --- a/tests/component_tests/packages/test_init.py +++ b/tests/component_tests/packages/test_init.py @@ -69,7 +69,7 @@ def test_packages_skip_update_false( } # Call with skip_update=False (default) - do_packages_pass(config, skip_update=False) + do_packages_pass(config, command_line_substitutions={}, skip_update=False) # Verify clone_or_update was called with actual refresh value mock_clone_or_update.assert_called_once() @@ -104,7 +104,7 @@ def test_packages_default_no_skip( } # Call without skip_update parameter - do_packages_pass(config) + do_packages_pass(config, command_line_substitutions={}) # Verify clone_or_update was called with actual refresh value mock_clone_or_update.assert_called_once() diff --git a/tests/component_tests/packages/test_packages.py b/tests/component_tests/packages/test_packages.py index 60dc0dccda..0893c7dcbb 100644 --- a/tests/component_tests/packages/test_packages.py +++ b/tests/component_tests/packages/test_packages.py @@ -37,6 +37,7 @@ from esphome.const import ( ) from esphome.core import CORE from esphome.util import OrderedDict +from esphome.yaml_util import add_context # Test strings TEST_DEVICE_NAME = "test_device_name" @@ -70,7 +71,7 @@ def fixture_basic_esphome(): def packages_pass(config): - """Wrapper around packages_pass that also resolves Extend and Remove.""" + """Passes the config through the packages processing steps.""" config = do_packages_pass(config) config = do_substitution_pass(config) config = merge_packages(config) @@ -705,6 +706,85 @@ def test_remote_packages_with_files_list( assert actual == expected +@patch("esphome.yaml_util.load_yaml") +@patch("pathlib.Path.is_file") +@patch("esphome.git.clone_or_update") +def test_remote_packages_with_files_list_and_substitutions( + mock_clone_or_update, mock_is_file, mock_load_yaml +) -> None: + """ + Ensures that packages are loaded as mixed list of dictionary and strings + """ + # Mock the response from git.clone_or_update + mock_revert = MagicMock() + mock_clone_or_update.return_value = (Path("/tmp/noexists"), mock_revert) + + # Mock the response from pathlib.Path.is_file + mock_is_file.return_value = True + + # Mock the response from esphome.yaml_util.load_yaml + mock_load_yaml.side_effect = [ + OrderedDict( + { + CONF_SENSOR: [ + { + CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, + CONF_NAME: TEST_SENSOR_NAME_1, + } + ] + } + ), + OrderedDict( + { + CONF_SENSOR: [ + { + CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, + CONF_NAME: TEST_SENSOR_NAME_2, + } + ] + } + ), + ] + + # Define the input config + config = { + CONF_PACKAGES: { + "package1": add_context( + { + CONF_URL: r"${url}", + CONF_REF: r"${branch}", + CONF_FILES: [ + {CONF_PATH: r"$file"}, + "sensor2.yaml", + ], + CONF_REFRESH: "1d", + }, + { + "branch": "main", + "file": TEST_YAML_FILENAME, + "url": "https://github.com/esphome/non-existant-repo", + }, + ) + } + } + + expected = { + CONF_SENSOR: [ + { + CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, + CONF_NAME: TEST_SENSOR_NAME_1, + }, + { + CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, + CONF_NAME: TEST_SENSOR_NAME_2, + }, + ] + } + + actual = packages_pass(config) + assert actual == expected + + @patch("esphome.yaml_util.load_yaml") @patch("pathlib.Path.is_file") @patch("esphome.git.clone_or_update") @@ -906,7 +986,7 @@ def test_packages_merge_substitutions() -> None: }, } - actual = do_packages_pass(config) + actual = do_packages_pass(config, command_line_substitutions={}) assert actual == expected @@ -970,33 +1050,107 @@ def test_package_merge() -> None: assert actual == expected +def test_packages_invalid_type_raises() -> None: + """Packages that are not a dict or list raise cv.Invalid.""" + config = { + CONF_PACKAGES: "not_a_dict_or_list", + } + with pytest.raises( + cv.Invalid, match="Packages must be a key to value mapping or list" + ): + do_packages_pass(config) + + @pytest.mark.parametrize( "invalid_package", [ 6, "some string", - ["some string"], - None, True, - {"some_component": 8}, - {3: 2}, - {"some_component": r"${unevaluated expression}"}, ], ) -def test_package_merge_invalid(invalid_package) -> None: - """ - Tests that trying to merge an invalid package raises an error. - """ +def test_invalid_package_contents_rejected(invalid_package: object) -> None: + """Invalid package contents are rejected by PACKAGE_SCHEMA during do_packages_pass.""" config = { CONF_PACKAGES: { "some_package": invalid_package, }, } - with pytest.raises(cv.Invalid): + do_packages_pass(config) + + +@pytest.mark.xfail( + reason="Deprecated single-package fallback swallows these errors. " + "Remove xfail when single-package deprecation is removed (2026.7.0).", + strict=True, +) +@pytest.mark.parametrize( + "invalid_package", + [ + None, + ["some string"], + {"some_component": 8}, + {3: 2}, + ], +) +def test_invalid_package_contents_masked_by_deprecation( + invalid_package: object, +) -> None: + """These invalid packages are swallowed by the deprecated single-package fallback.""" + config = { + CONF_PACKAGES: { + "some_package": invalid_package, + }, + } + with pytest.raises(cv.Invalid): + do_packages_pass(config) + + +def test_merge_packages_invalid_nested_type_raises() -> None: + """Invalid nested packages type during merge raises cv.Invalid.""" + config = { + CONF_PACKAGES: { + "pkg": { + CONF_PACKAGES: "invalid", + }, + }, + } + with pytest.raises( + cv.Invalid, match="Packages must be a key to value mapping or list" + ): merge_packages(config) +@patch("esphome.yaml_util.load_yaml") +@patch("pathlib.Path.is_file") +@patch("esphome.git.clone_or_update") +def test_remote_packages_no_revert( + mock_clone_or_update, mock_is_file, mock_load_yaml +) -> None: + """Remote packages with revert=None load without retry logic.""" + mock_clone_or_update.return_value = (Path("/tmp/noexists"), None) + mock_is_file.return_value = True + mock_load_yaml.return_value = OrderedDict( + {CONF_SENSOR: [{CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, CONF_NAME: "test"}]} + ) + + config = { + CONF_PACKAGES: { + "pkg": { + CONF_URL: "https://github.com/esphome/repo", + CONF_REF: "main", + CONF_FILES: [{CONF_PATH: "file.yaml"}], + CONF_REFRESH: "1d", + } + } + } + actual = packages_pass(config) + assert actual[CONF_SENSOR] == [ + {CONF_PLATFORM: TEST_SENSOR_PLATFORM_1, CONF_NAME: "test"} + ] + + def test_raw_config_contains_merged_esphome_from_package(tmp_path) -> None: """Test that CORE.raw_config contains esphome section from merged package. diff --git a/tests/unit_tests/fixtures/substitutions/06-remote_packages.approved.yaml b/tests/unit_tests/fixtures/substitutions/06-remote_packages.approved.yaml index 0fffbfb7cb..300cd85950 100644 --- a/tests/unit_tests/fixtures/substitutions/06-remote_packages.approved.yaml +++ b/tests/unit_tests/fixtures/substitutions/06-remote_packages.approved.yaml @@ -1,7 +1,3 @@ -substitutions: - x: 10 - y: 20 - z: 30 values_from_repo1_main: - package_name: package1 x: 3 @@ -28,3 +24,20 @@ values_from_repo1_main: y: 20 z: 5 volume: 1000 + - package_name: package6 + x: 12 + y: 13 + z: 5 + volume: 780 + - package_name: default + x: 10 + y: 20 + z: 5 + volume: 1000 +substitutions: + x: 10 + y: 20 + z: 30 + my_repo: repo1 + my_file: file1 + my_ref: main diff --git a/tests/unit_tests/fixtures/substitutions/06-remote_packages.input.yaml b/tests/unit_tests/fixtures/substitutions/06-remote_packages.input.yaml index 772860bf19..c61eeab28d 100644 --- a/tests/unit_tests/fixtures/substitutions/06-remote_packages.input.yaml +++ b/tests/unit_tests/fixtures/substitutions/06-remote_packages.input.yaml @@ -2,16 +2,26 @@ substitutions: x: 10 y: 20 z: 30 + my_repo: default_repo + my_file: default_file + my_ref: main + +# The following key is only used by the test framework +# to simulate command line substitutions +command_line_substitutions: + my_repo: repo1 + my_file: file1 + packages: package1: url: https://github.com/esphome/repo1 + ref: main files: - path: file1.yaml vars: package_name: package1 x: 3 y: 4 - ref: main package2: !include # a package that just includes the given remote package file: remote_package_proxy.yaml vars: @@ -41,3 +51,13 @@ packages: repo: repo1 file: file1.yaml ref: main + package6: + url: https://github.com/esphome/${my_repo} + ref: ${my_ref} + files: + - path: ${my_file + ".yaml"} + vars: + package_name: package6 + x: 12 + y: 13 + package7: github://esphome/${my_repo}/${my_file + ".yaml"}@${my_ref} diff --git a/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml b/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml index 867889b7bc..9e62fcae86 100644 --- a/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml +++ b/tests/unit_tests/fixtures/substitutions/07-package_merging.approved.yaml @@ -37,8 +37,6 @@ substitutions: - id: component8 value: 8 fancy_package: - substitutions: - fancy_subst: 42 fancy_component: *id001 pin: 12 some_switches: *id002 diff --git a/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.approved.yaml b/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.approved.yaml new file mode 100644 index 0000000000..fce47b01bf --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.approved.yaml @@ -0,0 +1,49 @@ +substitutions: + a: 10 + b: 20 + x: 79 +test_list: + - level1: + a: 10 + b: 20 + c: 10 + d: 20 + e: ${e} + f: ${f} + g: ${g} + h: ${h} + i: ${i} + j: ${j} + x: 80 + y: 40 + level2: + - level2: + a: 10 + b: 20 + c: 10 + d: 20 + e: 20 + f: 40 + g: ${g} + h: ${h} + i: ${i} + j: ${j} + x: 81 + y: 40 + level3: + - level3: + a: 10 + b: 20 + c: 10 + d: 20 + e: 20 + f: 40 + g: 100 + h: 200 + i: 30 + j: ${undefined_variable} + x: 82 + y: 40 + - a: 10 + b: 20 + x: 79 diff --git a/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.input.yaml b/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.input.yaml new file mode 100644 index 0000000000..6997ef56c1 --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/08-include_hierarchy.input.yaml @@ -0,0 +1,16 @@ +substitutions: + a: 10 + b: 20 + x: 79 + +test_list: + - !include + file: level1_package.yaml + vars: + x: ${x+1} + y: ${d*2} + c: ${a} + d: ${b} + - a: ${a} + b: ${b} + x: ${x} diff --git a/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.approved.yaml b/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.approved.yaml new file mode 100644 index 0000000000..ec2ae711bb --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.approved.yaml @@ -0,0 +1,69 @@ +substitutions: + a: from base config + b: from package3 + c: from nested package4 + nested_package: + nested_package_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + package1: + package1_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + package2: + package2_test_list: + - a: from package2 vars + - b: from package3 + - c: from nested package4 + package3: + package3_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + package4: + packages: + - nested_package_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + package_map: + package1: + package1_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + package2: + package2_test_list: + - a: from package2 vars + - b: from package3 + - c: from nested package4 + package3: &id001 + package3_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 + selected_package_number: 3 + selected_package_name: package3 + selected_package: *id001 +base_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 +package1_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 +package2_test_list: + - a: from package2 vars + - b: from package3 + - c: from nested package4 +package3_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 +nested_package_test_list: + - a: from base config + - b: from package3 + - c: from nested package4 diff --git a/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.input.yaml b/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.input.yaml new file mode 100644 index 0000000000..800e3cc7a8 --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/10-dynamic_packages.input.yaml @@ -0,0 +1,62 @@ +command_line_substitutions: + selected_package_number: 3 + +substitutions: + a: from base config + + package1: &p1 + substitutions: + a: from package1 + b: from package1 + c: from package1 + package1_test_list: + - a: ${ a } + - b: ${ b } + - c: ${ c } + + package2: &p2 !include + file: package2.yaml + vars: + a: from package2 vars + + package3: &p3 + substitutions: + a: from package3 + b: from package3 + c: from package3 + package3_test_list: + - a: ${ a } + - b: ${ b } + - c: ${ c } + + package4: + substitutions: + nested_package: + substitutions: + c: from nested package4 + nested_package_test_list: + - a: ${ a } + - b: ${ b } + - c: ${ c } + packages: + - ${ nested_package } + + package_map: + package1: *p1 + package2: *p2 + package3: *p3 + + selected_package_number: 2 # will be overridden by command line substitutions + selected_package_name: package${ selected_package_number } + selected_package: ${ package_map[selected_package_name] } + +packages: + - ${ package1 } + - ${ package2 } + - ${ selected_package } + - ${ package4 } + +base_test_list: + - a: ${ a } + - b: ${ b } + - c: ${ c } diff --git a/tests/unit_tests/fixtures/substitutions/level1_package.yaml b/tests/unit_tests/fixtures/substitutions/level1_package.yaml new file mode 100644 index 0000000000..d8a994b7b4 --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/level1_package.yaml @@ -0,0 +1,21 @@ +# this file is included by 07-include_hierarchy.input.yaml +level1: + a: ${a} # top-level substitution + b: ${b} # top-level substitution + c: ${c} # from vars when including + d: ${d} # from vars when including + e: ${e} # undefined at this level + f: ${f} # undefined at this level + g: ${g} # undefined at this level + h: ${h} # undefined at this level + i: ${i} # undefined at this level + j: ${j} # undefined at this level + x: ${x} # from vars when including, calculated + y: ${y} # from vars when including, calculated + level2: + - !include + file: level2_package.yaml + vars: + e: ${c*2} + f: ${d*2} + x: ${x+1} diff --git a/tests/unit_tests/fixtures/substitutions/level2_package.yaml b/tests/unit_tests/fixtures/substitutions/level2_package.yaml new file mode 100644 index 0000000000..460135553a --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/level2_package.yaml @@ -0,0 +1,21 @@ +# this file is included by level1_package.yaml +level2: + a: ${a} # top-level substitution + b: ${b} # top-level substitution + c: ${c} # visible from level1 vars + d: ${d} # visible from level1 vars + e: ${e} # from vars when including + f: ${f} # from vars when including + g: ${g} # undefined at this level + h: ${h} # undefined at this level + i: ${i} # undefined at this level + j: ${j} # undefined at this level + x: ${x} # from vars when including, calculated + y: ${y} # from vars when including, calculated + level3: + - !include + file: level3_package.yaml + vars: + g: ${e*5} + h: ${f*5} + x: ${x+1} diff --git a/tests/unit_tests/fixtures/substitutions/level3_package.yaml b/tests/unit_tests/fixtures/substitutions/level3_package.yaml new file mode 100644 index 0000000000..b16ed5fcf6 --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/level3_package.yaml @@ -0,0 +1,16 @@ +# this file is included by level2_package.yaml +defaults: + i: 30 +level3: + a: ${a} # top-level substitution + b: ${b} # top-level substitution + c: ${c} # visible from level1 vars + d: ${d} # visible from level1 vars + e: ${e} # visible from level2 vars + f: ${f} # visible from level2 vars + g: ${g} # from vars when including + h: ${h} # from vars when including + i: ${i} # Should take the default value of 30 + j: ${undefined_variable} # Does not exist, should be output as-is + x: ${x} # from vars when including, calculated + y: ${y} # from vars when including, calculated diff --git a/tests/unit_tests/fixtures/substitutions/package2.yaml b/tests/unit_tests/fixtures/substitutions/package2.yaml new file mode 100644 index 0000000000..998cd74c52 --- /dev/null +++ b/tests/unit_tests/fixtures/substitutions/package2.yaml @@ -0,0 +1,10 @@ +# included from 10-dynamic_packages.input.yaml +substitutions: + a: from package2 # must not override base config's a + # b not defined here, won't override package1's b + c: from package2 # will override package1's c + +package2_test_list: + - a: ${ a } + - b: ${ b } + - c: ${ c } diff --git a/tests/unit_tests/test_substitutions.py b/tests/unit_tests/test_substitutions.py index 30478f9521..c7b0bbcf7c 100644 --- a/tests/unit_tests/test_substitutions.py +++ b/tests/unit_tests/test_substitutions.py @@ -143,7 +143,9 @@ def test_substitutions_fixtures( command_line_substitutions = config.pop("command_line_substitutions", None) - config = do_packages_pass(config) + config = do_packages_pass( + config, command_line_substitutions=command_line_substitutions + ) config = substitutions.do_substitution_pass(config, command_line_substitutions) diff --git a/tests/unit_tests/test_yaml_util.py b/tests/unit_tests/test_yaml_util.py index 35a4bc3707..667b593819 100644 --- a/tests/unit_tests/test_yaml_util.py +++ b/tests/unit_tests/test_yaml_util.py @@ -98,13 +98,15 @@ def test_construct_secret_missing(fixture_path: Path, tmp_path: Path) -> None: """Test that missing secrets raise proper errors.""" # Create a YAML file with a secret that doesn't exist test_yaml = tmp_path / "test.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ esphome: name: test wifi: password: !secret nonexistent_secret -""") +""" + ) # Create an empty secrets file secrets_yaml = tmp_path / "secrets.yaml" @@ -118,10 +120,12 @@ def test_construct_secret_no_secrets_file(tmp_path: Path) -> None: """Test that missing secrets.yaml file raises proper error.""" # Create a YAML file with a secret but no secrets.yaml test_yaml = tmp_path / "test.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ wifi: password: !secret some_secret -""") +""" + ) # Mock CORE.config_path to avoid NoneType error with ( @@ -140,10 +144,12 @@ def test_construct_secret_fallback_to_main_config_dir( subdir.mkdir() test_yaml = subdir / "test.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ wifi: password: !secret test_secret -""") +""" + ) # Create secrets.yaml in the main directory main_secrets = tmp_path / "secrets.yaml" @@ -164,9 +170,11 @@ def test_construct_include_dir_named(fixture_path: Path, tmp_path: Path) -> None # Create test YAML that uses include_dir_named test_yaml = dst_dir / "test_include_named.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ sensor: !include_dir_named named_dir -""") +""" + ) actual = yaml_util.load_yaml(test_yaml) actual_sensor = actual["sensor"] @@ -199,9 +207,11 @@ def test_construct_include_dir_named_empty_dir(tmp_path: Path) -> None: empty_dir.mkdir() test_yaml = tmp_path / "test.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ sensor: !include_dir_named empty_dir -""") +""" + ) actual = yaml_util.load_yaml(test_yaml) @@ -231,9 +241,11 @@ def test_construct_include_dir_named_with_dots(tmp_path: Path) -> None: hidden_subfile.write_text("key: hidden_subfile_value") test_yaml = tmp_path / "test.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ test: !include_dir_named test_dir -""") +""" + ) actual = yaml_util.load_yaml(test_yaml) @@ -255,9 +267,11 @@ def test_find_files_recursive(fixture_path: Path, tmp_path: Path) -> None: # This indirectly tests _find_files by using include_dir_named test_yaml = dst_dir / "test_include_recursive.yaml" - test_yaml.write_text(""" + test_yaml.write_text( + """ all_sensors: !include_dir_named named_dir -""") +""" + ) actual = yaml_util.load_yaml(test_yaml) From b3390d40fb959808fcc520bff17c4a1350f98420 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 24 Mar 2026 19:31:42 +0100 Subject: [PATCH 1685/2030] [core] Fix cg.add_define propagation to dependencies in native ESP-IDF builds (#15137) --- esphome/build_gen/espidf.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/esphome/build_gen/espidf.py b/esphome/build_gen/espidf.py index 9df9b1069c..01923baaac 100644 --- a/esphome/build_gen/espidf.py +++ b/esphome/build_gen/espidf.py @@ -53,6 +53,13 @@ def get_project_cmakelists() -> str: variant = get_esp32_variant() idf_target = variant.lower().replace("-", "") + # Extract compile definitions from build flags (-DXXX -> XXX) + compile_defs = [flag for flag in CORE.build_flags if flag.startswith("-D")] + extra_compile_options = "\n".join( + f'idf_build_set_property(COMPILE_OPTIONS "{compile_def}" APPEND)' + for compile_def in compile_defs + ) + return f"""\ # Auto-generated by ESPHome cmake_minimum_required(VERSION 3.16) @@ -61,6 +68,9 @@ set(IDF_TARGET {idf_target}) set(EXTRA_COMPONENT_DIRS ${{CMAKE_SOURCE_DIR}}/src) include($ENV{{IDF_PATH}}/tools/cmake/project.cmake) + +{extra_compile_options} + project({CORE.name}) """ @@ -70,10 +80,6 @@ def get_component_cmakelists(minimal: bool = False) -> str: idf_requires = [] if minimal else (get_available_components() or []) requires_str = " ".join(idf_requires) - # Extract compile definitions from build flags (-DXXX -> XXX) - compile_defs = [flag[2:] for flag in CORE.build_flags if flag.startswith("-D")] - compile_defs_str = "\n ".join(sorted(compile_defs)) if compile_defs else "" - # Extract compile options (-W flags, excluding linker flags) compile_opts = [ flag @@ -104,11 +110,6 @@ idf_component_register( # Apply C++ standard target_compile_features(${{COMPONENT_LIB}} PUBLIC cxx_std_20) -# ESPHome compile definitions -target_compile_definitions(${{COMPONENT_LIB}} PUBLIC - {compile_defs_str} -) - # ESPHome compile options target_compile_options(${{COMPONENT_LIB}} PUBLIC {compile_opts_str} From 3cd50f0495564c14f35b55448332079874682f12 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:31:08 -0400 Subject: [PATCH 1686/2030] [ci] Block new CONF_ constants from being added to esphome/const.py (#15145) --- script/ci-custom.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/script/ci-custom.py b/script/ci-custom.py index 25a0cf2127..7d0680a491 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -525,6 +525,29 @@ def lint_constants_usage(): return errs +# Maximum allowed CONF_ constants in esphome/const.py. +# This file is frozen — new constants go in esphome/components/const/__init__.py. +# Decrease this number when constants are moved out of const.py. +CONST_PY_MAX_CONF = 1011 + + +@lint_content_check(include=["esphome/const.py"]) +def lint_const_py_frozen(fname, content): + """Block new CONF_ constants from being added to esphome/const.py. + + New constants should go in esphome/components/const/__init__.py instead. + """ + count = sum(1 for line in content.splitlines() if line.startswith("CONF_")) + if count > CONST_PY_MAX_CONF: + return ( + "esphome/const.py is frozen. " + "Add new constants to esphome/components/const/__init__.py instead." + ) + if count < CONST_PY_MAX_CONF: + return f"CONST_PY_MAX_CONF in ci-custom.py should be updated to {count}." + return None + + def relative_cpp_search_text(fname: Path, content) -> str: parts = fname.parts integration = parts[2] From 55df21db516263a1f7b381035477a66cd84c5e8b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 15:44:28 -0400 Subject: [PATCH 1687/2030] [esp32] Default CPU frequency to maximum supported (#15143) --- esphome/components/esp32/__init__.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 1ecc270fd1..0e216485ac 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -379,12 +379,11 @@ FULL_CPU_FREQUENCIES = set(itertools.chain.from_iterable(CPU_FREQUENCIES.values( def set_core_data(config): cpu_frequency = config.get(CONF_CPU_FREQUENCY, None) variant = config[CONF_VARIANT] - # if not specified in config, set to 160MHz if supported, the fastest otherwise + # if not specified in config, default to the maximum supported frequency + # (ESP32-P4 engineering samples are limited to 360MHz, non-engineering can do 400MHz) if cpu_frequency is None: choices = CPU_FREQUENCIES[variant] - if "160MHZ" in choices: - cpu_frequency = "160MHZ" - elif "360MHZ" in choices: + if variant == VARIANT_ESP32P4 and config.get(CONF_ENGINEERING_SAMPLE): cpu_frequency = "360MHZ" else: cpu_frequency = choices[-1] From 22bc47da23a97187c74477fb282748d0935251aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Bl=C3=A4se?= <fabian@blaese.de> Date: Tue, 24 Mar 2026 20:57:58 +0100 Subject: [PATCH 1688/2030] [light] Fix incorrect mode change handling on transition to off (#15147) --- esphome/components/light/transformers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/light/transformers.h b/esphome/components/light/transformers.h index b6e5e08f2b..61fe098ad7 100644 --- a/esphome/components/light/transformers.h +++ b/esphome/components/light/transformers.h @@ -27,7 +27,7 @@ class LightTransitionTransformer : public LightTransformer { } // When changing color mode, go through off state, as color modes are orthogonal and there can't be two active. - if (this->start_values_.get_color_mode() != this->target_values_.get_color_mode()) { + if (this->start_values_.get_color_mode() != this->end_values_.get_color_mode()) { this->changing_color_mode_ = true; this->intermediate_values_ = this->start_values_; this->intermediate_values_.set_state(false); @@ -39,8 +39,8 @@ class LightTransitionTransformer : public LightTransformer { // Halfway through, when intermediate state (off) is reached, flip it to the target, but remain off. if (this->changing_color_mode_ && p > 0.5f && - this->intermediate_values_.get_color_mode() != this->target_values_.get_color_mode()) { - this->intermediate_values_ = this->target_values_; + this->intermediate_values_.get_color_mode() != this->end_values_.get_color_mode()) { + this->intermediate_values_ = this->end_values_; this->intermediate_values_.set_state(false); } From 8751f348c8ab50db26b4cfbc5abcc1c4703ba739 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:04:27 -0400 Subject: [PATCH 1689/2030] [sx127x] Fix FIFO read corruption (#15114) --- esphome/components/sx127x/sx127x.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index 66957a7342..0fddfdccdb 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -38,14 +38,18 @@ void SX127x::write_register_(uint8_t reg, uint8_t value) { void SX127x::read_fifo_(std::vector<uint8_t> &packet) { this->enable(); this->write_byte(REG_FIFO & 0x7F); - this->read_array(packet.data(), packet.size()); + for (auto &byte : packet) { + byte = this->transfer_byte(0x00); + } this->disable(); } void SX127x::write_fifo_(const std::vector<uint8_t> &packet) { this->enable(); this->write_byte(REG_FIFO | 0x80); - this->write_array(packet.data(), packet.size()); + for (const auto &byte : packet) { + this->transfer_byte(byte); + } this->disable(); } From 13baf260505116b2f6e3ae8e1ed8fbcd18820b58 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 24 Mar 2026 21:26:21 +0100 Subject: [PATCH 1690/2030] [core] get_log_str: fix false-positive error on null-terminated strings with stricter compilers (#15136) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/core/progmem.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/esphome/core/progmem.h b/esphome/core/progmem.h index 6c6a5252cf..031860e3a6 100644 --- a/esphome/core/progmem.h +++ b/esphome/core/progmem.h @@ -3,6 +3,7 @@ #include <array> #include <cstddef> #include <cstdint> +#include <new> #include "esphome/core/hal.h" // For PROGMEM definition @@ -104,7 +105,9 @@ struct LogString; static const char *get_(uint8_t idx, uint8_t fallback) { \ if (idx >= COUNT) \ idx = fallback; \ - return &BLOB[::esphome::progmem_read_byte(&OFFSETS[idx])]; \ + /* std::launder is used here to prevent the inter-procedural analysis that */ \ + /* causes the false positive that the string is not null terminated */ \ + return std::launder(&BLOB[::esphome::progmem_read_byte(&OFFSETS[idx])]); \ } \ static ::ProgmemStr get_progmem_str(uint8_t idx, uint8_t fallback) { \ return reinterpret_cast<::ProgmemStr>(get_(idx, fallback)); \ From 4ff85e2a1e0122f28a3b9d366e79b9fd112215f2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 19:48:17 -0400 Subject: [PATCH 1691/2030] [core] Fix clean-all to handle custom build paths (#15146) Co-authored-by: J. Nick Koston <nick+github@koston.org> --- esphome/writer.py | 31 ++++++-- tests/unit_tests/test_writer.py | 124 ++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 4 deletions(-) diff --git a/esphome/writer.py b/esphome/writer.py index 69a35d00e3..4aac16ffd4 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -18,7 +18,6 @@ from esphome.core import CORE, EsphomeError from esphome.helpers import ( copy_file_if_changed, cpp_string_escape, - get_str_env, is_ha_addon, read_file, rmtree, @@ -441,18 +440,42 @@ def clean_build(clear_pio_cache: bool = True): rmtree(cache_dir) +def _get_custom_build_dir(item: Path, data_dir: Path) -> Path | None: + """Parse a YAML config to find a custom build directory.""" + from esphome import yaml_util + + try: + raw = yaml_util.load_yaml(item) + except (EsphomeError, OSError) as e: + _LOGGER.debug("Could not parse %s to find build_path: %s", item, e) + return None + if not isinstance(raw, dict): + return None + esphome_conf = raw.get("esphome", {}) + if not isinstance(esphome_conf, dict): + return None + if build_path := esphome_conf.get("build_path"): + return data_dir / build_path + return None + + def clean_all(configuration: list[str]): data_dirs = [] for config in configuration: item = Path(config) if item.is_file() and item.suffix in (".yaml", ".yml"): - data_dirs.append(item.parent / ".esphome") + data_dir = item.parent / ".esphome" + data_dirs.append(data_dir) + if custom := _get_custom_build_dir(item, data_dir): + data_dirs.append(custom) else: data_dirs.append(item / ".esphome") if is_ha_addon(): data_dirs.append(Path("/data")) - if "ESPHOME_DATA_DIR" in os.environ: - data_dirs.append(Path(get_str_env("ESPHOME_DATA_DIR", None))) + if env_data_dir := os.environ.get("ESPHOME_DATA_DIR"): + data_dirs.append(Path(env_data_dir)) + if env_build_path := os.environ.get("ESPHOME_BUILD_PATH"): + data_dirs.append(Path(env_build_path)) # Clean build dir for dir in data_dirs: diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index 134b63df4a..6ace38a7d7 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -866,6 +866,130 @@ def test_clean_all_with_yaml_file( assert str(build_dir) in caplog.text +@patch("esphome.writer.CORE") +def test_clean_all_with_yaml_build_path( + mock_core: MagicMock, + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test clean_all cleans absolute build_path specified in YAML config.""" + config_dir = tmp_path / "config" + config_dir.mkdir() + + # Create an absolute custom build path directory with contents + custom_build = tmp_path / "custom_build" + custom_build.mkdir() + (custom_build / "firmware.bin").write_text("x") + sub = custom_build / "subdir" + sub.mkdir() + (sub / "file.txt").write_text("x") + + yaml_file = config_dir / "test.yaml" + # Absolute build_path: data_dir / absolute = absolute (Python Path behavior) + yaml_file.write_text(f"esphome:\n name: test\n build_path: {custom_build}\n") + + # Also create the normal .esphome dir + build_dir = config_dir / ".esphome" + build_dir.mkdir() + (build_dir / "dummy.txt").write_text("x") + + from esphome.writer import clean_all + + with caplog.at_level("INFO"): + clean_all([str(yaml_file)]) + + # Both .esphome and custom build_path should be cleaned + assert build_dir.exists() + assert not (build_dir / "dummy.txt").exists() + assert custom_build.exists() + assert not (custom_build / "firmware.bin").exists() + assert not sub.exists() + + +@patch("esphome.writer.CORE") +def test_clean_all_with_yaml_parse_error( + mock_core: MagicMock, + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test clean_all still cleans .esphome when YAML parse fails.""" + config_dir = tmp_path / "config" + config_dir.mkdir() + yaml_file = config_dir / "test.yaml" + yaml_file.write_text("invalid: yaml: content: [") + + build_dir = config_dir / ".esphome" + build_dir.mkdir() + (build_dir / "dummy.txt").write_text("x") + + from esphome.writer import clean_all + + with caplog.at_level("INFO"): + clean_all([str(yaml_file)]) + + # .esphome should still be cleaned despite YAML parse failure + assert build_dir.exists() + assert not (build_dir / "dummy.txt").exists() + + +@patch("esphome.writer.CORE") +def test_clean_all_with_env_build_path( + mock_core: MagicMock, + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test clean_all cleans ESPHOME_BUILD_PATH directory.""" + config_dir = tmp_path / "config" + config_dir.mkdir() + + build_dir = config_dir / ".esphome" + build_dir.mkdir() + (build_dir / "dummy.txt").write_text("x") + + # Create env build path directory + env_build = tmp_path / "env_build" + env_build.mkdir() + (env_build / "firmware.bin").write_text("x") + + from esphome.writer import clean_all + + with ( + caplog.at_level("INFO"), + patch.dict(os.environ, {"ESPHOME_BUILD_PATH": str(env_build)}), + ): + clean_all([str(config_dir)]) + + # Both should be cleaned + assert not (build_dir / "dummy.txt").exists() + assert env_build.exists() + assert not (env_build / "firmware.bin").exists() + + +@patch("esphome.writer.CORE") +def test_clean_all_ignores_empty_env_vars( + mock_core: MagicMock, + tmp_path: Path, +) -> None: + """Test clean_all ignores empty ESPHOME_BUILD_PATH/ESPHOME_DATA_DIR.""" + config_dir = tmp_path / "config" + config_dir.mkdir() + + # Create a file in cwd that must NOT be cleaned + marker = tmp_path / "important.txt" + marker.write_text("do not delete") + + from esphome.writer import clean_all + + with patch.dict( + os.environ, + {"ESPHOME_BUILD_PATH": "", "ESPHOME_DATA_DIR": ""}, + ): + clean_all([str(config_dir)]) + + # Empty env vars must not cause cwd to be cleaned + assert marker.exists() + + @patch("esphome.writer.CORE") def test_clean_all( mock_core: MagicMock, From 752fe30332749f1608823753dcd65c20f91448e7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:01:59 -1000 Subject: [PATCH 1692/2030] [api] Add descriptive message to status warning when waiting for client (#15148) --- esphome/components/api/api_server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api_server.cpp b/esphome/components/api/api_server.cpp index 1151bc5983..d9c3cc6846 100644 --- a/esphome/components/api/api_server.cpp +++ b/esphome/components/api/api_server.cpp @@ -108,7 +108,7 @@ void APIServer::setup() { this->last_connected_ = App.get_loop_component_start_time(); // Set warning status if reboot timeout is enabled if (this->reboot_timeout_ != 0) { - this->status_set_warning(); + this->status_set_warning(LOG_STR("waiting for client connection")); } } @@ -187,7 +187,7 @@ void APIServer::remove_client_(size_t client_index) { // Last client disconnected - set warning and start tracking for reboot timeout if (this->clients_.empty() && this->reboot_timeout_ != 0) { - this->status_set_warning(); + this->status_set_warning(LOG_STR("waiting for client connection")); this->last_connected_ = App.get_loop_component_start_time(); } From 9fb5b6aa158582ea35e968f9b8209f4f1849fe06 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:03:18 -1000 Subject: [PATCH 1693/2030] [light] Replace initial_state storage with flash-resident callback (#15133) --- esphome/components/light/__init__.py | 12 +++++- esphome/components/light/light_state.cpp | 7 ++-- esphome/components/light/light_state.h | 10 +++-- .../fixtures/light_initial_state.yaml | 39 +++++++++++++++++++ tests/integration/test_light_initial_state.py | 38 ++++++++++++++++++ 5 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 tests/integration/fixtures/light_initial_state.yaml create mode 100644 tests/integration/test_light_initial_state.py diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 64452e4282..4090ca57c2 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -38,7 +38,7 @@ from esphome.const import ( CONF_WEB_SERVER, CONF_WHITE, ) -from esphome.core import CORE, ID, CoroPriority, HexInt, coroutine_with_priority +from esphome.core import CORE, ID, CoroPriority, HexInt, Lambda, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.cpp_generator import MockObjClass @@ -262,6 +262,8 @@ async def setup_light_core_(light_var, config, output_var): cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE])) if (initial_state_config := config.get(CONF_INITIAL_STATE)) is not None: + # Emit a stateless lambda that constructs the initial state — values live + # in flash as code, not stored in the LightState object (~40 bytes saved). initial_state = LightStateRTCState( initial_state_config.get(CONF_COLOR_MODE, ColorMode.UNKNOWN), initial_state_config.get(CONF_STATE, False), @@ -275,7 +277,13 @@ async def setup_light_core_(light_var, config, output_var): initial_state_config.get(CONF_COLD_WHITE, 1.0), initial_state_config.get(CONF_WARM_WHITE, 1.0), ) - cg.add(light_var.set_initial_state(initial_state)) + args = [(LightStateRTCState.operator("ref"), "s")] + lamb = await cg.process_lambda( + Lambda(f"s = {initial_state};"), + args, + return_type=cg.void, + ) + cg.add(light_var.set_initial_state(lamb)) if ( default_transition_length := config.get(CONF_DEFAULT_TRANSITION_LENGTH) diff --git a/esphome/components/light/light_state.cpp b/esphome/components/light/light_state.cpp index 1b736d84f6..bd778926d5 100644 --- a/esphome/components/light/light_state.cpp +++ b/esphome/components/light/light_state.cpp @@ -37,8 +37,9 @@ void LightState::setup() { auto call = this->make_call(); LightStateRTCState recovered{}; - if (this->initial_state_.has_value()) { - recovered = *this->initial_state_; + if (this->initial_state_callback_) { + this->initial_state_callback_(recovered); + this->initial_state_callback_ = nullptr; // One-shot — no longer needed } switch (this->restore_mode_) { case LIGHT_RESTORE_DEFAULT_OFF: @@ -195,7 +196,7 @@ void LightState::set_flash_transition_length(uint32_t flash_transition_length) { uint32_t LightState::get_flash_transition_length() const { return this->flash_transition_length_; } void LightState::set_gamma_correct(float gamma_correct) { this->gamma_correct_ = gamma_correct; } void LightState::set_restore_mode(LightRestoreMode restore_mode) { this->restore_mode_ = restore_mode; } -void LightState::set_initial_state(const LightStateRTCState &initial_state) { this->initial_state_ = initial_state; } +void LightState::set_initial_state(void (*callback)(LightStateRTCState &)) { this->initial_state_callback_ = callback; } bool LightState::supports_effects() { return !this->effects_.empty(); } const FixedVector<LightEffect *> &LightState::get_effects() const { return this->effects_; } void LightState::add_effects(const std::initializer_list<LightEffect *> &effects) { diff --git a/esphome/components/light/light_state.h b/esphome/components/light/light_state.h index ab7f2e4df8..5efc05358b 100644 --- a/esphome/components/light/light_state.h +++ b/esphome/components/light/light_state.h @@ -188,8 +188,9 @@ class LightState : public EntityBase, public Component { /// Set the restore mode of this light void set_restore_mode(LightRestoreMode restore_mode); - /// Set the initial state of this light - void set_initial_state(const LightStateRTCState &initial_state); + /// Set a callback to populate the initial state defaults during setup. + /// The callback is called once, then cleared. Values live in flash as code. + void set_initial_state(void (*callback)(LightStateRTCState &)); /// Return whether the light has any effects that meet the trait requirements. bool supports_effects(); @@ -342,8 +343,9 @@ class LightState : public EntityBase, public Component { */ std::unique_ptr<std::vector<LightTargetStateReachedListener *>> target_state_reached_listeners_; - /// Initial state of the light. - optional<LightStateRTCState> initial_state_{}; + /// Callback to populate initial state defaults — called once during setup, then cleared. + /// Values live in flash as function body; no per-instance data storage beyond this pointer. + void (*initial_state_callback_)(LightStateRTCState &){nullptr}; /// Value for storing the index of the currently active effect. 0 if no effect is active uint32_t active_effect_index_{}; diff --git a/tests/integration/fixtures/light_initial_state.yaml b/tests/integration/fixtures/light_initial_state.yaml new file mode 100644 index 0000000000..2654c76aa0 --- /dev/null +++ b/tests/integration/fixtures/light_initial_state.yaml @@ -0,0 +1,39 @@ +esphome: + name: light-initial-state-test +host: +api: # Port will be automatically injected +logger: + level: DEBUG + +output: + - platform: template + id: test_red + type: float + write_action: + - lambda: "" + - platform: template + id: test_green + type: float + write_action: + - lambda: "" + - platform: template + id: test_blue + type: float + write_action: + - lambda: "" + +light: + - platform: rgb + name: "Test Light" + id: test_light + red: test_red + green: test_green + blue: test_blue + restore_mode: ALWAYS_OFF + initial_state: + color_mode: RGB + state: true + brightness: 0.75 + red: 1.0 + green: 0.5 + blue: 0.0 diff --git a/tests/integration/test_light_initial_state.py b/tests/integration/test_light_initial_state.py new file mode 100644 index 0000000000..f1cd96dbf0 --- /dev/null +++ b/tests/integration/test_light_initial_state.py @@ -0,0 +1,38 @@ +"""Integration test for light initial_state configuration. + +Tests that the initial_state values are correctly applied at boot when +no saved preferences exist. The initial_state callback populates defaults +that the restore logic uses as a fallback. +""" + +import pytest + +from .state_utils import InitialStateHelper, require_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_light_initial_state( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that initial_state values are applied at boot.""" + async with run_compiled(yaml_config), api_client_connected() as client: + entities, _ = await client.list_entities_services() + light = require_entity(entities, "test_light") + + helper = InitialStateHelper(entities) + client.subscribe_states(helper.on_state_wrapper(lambda s: None)) + await helper.wait_for_initial_states() + + state = helper.initial_states[light.key] + + # restore_mode: ALWAYS_OFF overrides state to false + assert state.state is False + + # But the color values from initial_state should be applied + assert state.brightness == pytest.approx(0.75, abs=0.05) + assert state.red == pytest.approx(1.0, abs=0.01) + assert state.green == pytest.approx(0.5, abs=0.01) + assert state.blue == pytest.approx(0.0, abs=0.01) From b6aec4fa25bb9f7fdb09e9738385f5b8fed45267 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:03:30 -1000 Subject: [PATCH 1694/2030] [ethernet] Add W5100 support for RP2040 (#15131) --- esphome/components/ethernet/__init__.py | 20 +++++++++----- .../components/ethernet/ethernet_component.h | 10 +++++++ .../ethernet/ethernet_component_rp2040.cpp | 26 ++++++++++++++----- esphome/core/defines.h | 1 + .../ethernet/common-w5100-rp2040.yaml | 18 +++++++++++++ .../ethernet/test-w5100.rp2040-ard.yaml | 1 + 6 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 tests/components/ethernet/common-w5100-rp2040.yaml create mode 100644 tests/components/ethernet/test-w5100.rp2040-ard.yaml diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index e17abfcc93..17459cabb6 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -115,6 +115,7 @@ ETHERNET_TYPES = { "JL1101": EthernetType.ETHERNET_TYPE_JL1101, "KSZ8081": EthernetType.ETHERNET_TYPE_KSZ8081, "KSZ8081RNA": EthernetType.ETHERNET_TYPE_KSZ8081RNA, + "W5100": EthernetType.ETHERNET_TYPE_W5100, "W5500": EthernetType.ETHERNET_TYPE_W5500, "OPENETH": EthernetType.ETHERNET_TYPE_OPENETH, "DM9051": EthernetType.ETHERNET_TYPE_DM9051, @@ -132,6 +133,7 @@ _PHY_TYPE_TO_DEFINE = { "JL1101": "USE_ETHERNET_JL1101", "KSZ8081": "USE_ETHERNET_KSZ8081", "KSZ8081RNA": "USE_ETHERNET_KSZ8081", + "W5100": "USE_ETHERNET_W5100", "W5500": "USE_ETHERNET_W5500", "DM9051": "USE_ETHERNET_DM9051", "LAN8670": "USE_ETHERNET_LAN8670", @@ -164,9 +166,15 @@ _IDF6_ETHERNET_COMPONENTS: dict[str, IDFRegistryComponent] = { # These types are always external IDF components (never built-in to ESP-IDF) _ALWAYS_EXTERNAL_IDF_COMPONENTS = {"LAN8670", "ENC28J60"} -SPI_ETHERNET_TYPES = ["W5500", "DM9051", "ENC28J60"] +# ESP32-only SPI ethernet types (W5100 is RP2040-only, no ESP-IDF driver) +SPI_ETHERNET_TYPES = {"W5500", "DM9051", "ENC28J60"} # RP2040-supported SPI ethernet types -RP2040_SPI_ETHERNET_TYPES = ["W5500", "ENC28J60"] +RP2040_SPI_ETHERNET_TYPES = {"W5100", "W5500", "ENC28J60"} +_RP2040_SPI_LIBRARIES = { + "W5100": "lwIP_w5100", + "W5500": "lwIP_w5500", + "ENC28J60": "lwIP_enc28j60", +} SPI_ETHERNET_DEFAULT_POLLING_INTERVAL = TimePeriodMilliseconds(milliseconds=10) emac_rmii_clock_mode_t = cg.global_ns.enum("emac_rmii_clock_mode_t") @@ -295,7 +303,7 @@ def _validate(config): ) elif CORE.is_rp2040 and config[CONF_TYPE] not in RP2040_SPI_ETHERNET_TYPES: raise cv.Invalid( - f"Only {', '.join(RP2040_SPI_ETHERNET_TYPES)} are supported on RP2040, " + f"Only {', '.join(sorted(RP2040_SPI_ETHERNET_TYPES))} are supported on RP2040, " f"not {config[CONF_TYPE]}" ) return config @@ -382,6 +390,7 @@ CONFIG_SCHEMA = cv.All( "JL1101": RMII_SCHEMA, "KSZ8081": RMII_SCHEMA, "KSZ8081RNA": RMII_SCHEMA, + "W5100": cv.All(SPI_SCHEMA, cv.only_on([Platform.RP2040])), "W5500": SPI_SCHEMA, "OPENETH": cv.All(BASE_SCHEMA, cv.only_on([Platform.ESP32])), "DM9051": SPI_SCHEMA, @@ -574,10 +583,7 @@ async def _to_code_rp2040(var: cg.Pvariable, config: ConfigType) -> None: cg.add(var.set_reset_pin(config[CONF_RESET_PIN])) cg.add_define("USE_ETHERNET_SPI") - if config[CONF_TYPE] == "ENC28J60": - cg.add_library("lwIP_enc28j60", None) - else: - cg.add_library("lwIP_w5500", None) + cg.add_library(_RP2040_SPI_LIBRARIES[config[CONF_TYPE]], None) def _final_validate_rmii_pins(config: ConfigType) -> None: diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index 4c85c39eb8..c6e37d01ea 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -25,6 +25,8 @@ extern "C" eth_esp32_emac_config_t eth_esp32_emac_default_config(void); #ifdef USE_RP2040 #if defined(USE_ETHERNET_W5500) #include <W5500lwIP.h> +#elif defined(USE_ETHERNET_W5100) +#include <W5100lwIP.h> #elif defined(USE_ETHERNET_ENC28J60) #include <ENC28J60lwIP.h> #else @@ -59,6 +61,7 @@ enum EthernetType : uint8_t { ETHERNET_TYPE_JL1101, ETHERNET_TYPE_KSZ8081, ETHERNET_TYPE_KSZ8081RNA, + ETHERNET_TYPE_W5100, ETHERNET_TYPE_W5500, ETHERNET_TYPE_OPENETH, ETHERNET_TYPE_DM9051, @@ -222,8 +225,15 @@ class EthernetComponent final : public Component { #ifdef USE_RP2040 static constexpr uint32_t LINK_CHECK_INTERVAL = 500; // ms between link/IP polls +#if defined(USE_ETHERNET_W5100) + static constexpr uint32_t RESET_DELAY_MS = 150; // W5100S PLL lock time +#else + static constexpr uint32_t RESET_DELAY_MS = 10; +#endif #if defined(USE_ETHERNET_W5500) Wiznet5500lwIP *eth_{nullptr}; +#elif defined(USE_ETHERNET_W5100) + Wiznet5100lwIP *eth_{nullptr}; #elif defined(USE_ETHERNET_ENC28J60) ENC28J60lwIP *eth_{nullptr}; #else diff --git a/esphome/components/ethernet/ethernet_component_rp2040.cpp b/esphome/components/ethernet/ethernet_component_rp2040.cpp index bd8c458985..9771bc59d5 100644 --- a/esphome/components/ethernet/ethernet_component_rp2040.cpp +++ b/esphome/components/ethernet/ethernet_component_rp2040.cpp @@ -31,12 +31,15 @@ void EthernetComponent::setup() { reset_pin.digital_write(false); delay(1); // NOLINT reset_pin.digital_write(true); - delay(10); // NOLINT - wait for chip to initialize after reset + // W5100S needs 150ms for PLL lock; W5500/ENC28J60 need ~10ms + delay(RESET_DELAY_MS); // NOLINT } // Create the SPI Ethernet device instance #if defined(USE_ETHERNET_W5500) this->eth_ = new Wiznet5500lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT +#elif defined(USE_ETHERNET_W5100) + this->eth_ = new Wiznet5100lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT #elif defined(USE_ETHERNET_ENC28J60) this->eth_ = new ENC28J60lwIP(this->cs_pin_, SPI, this->interrupt_pin_); // NOLINT #endif @@ -80,8 +83,8 @@ void EthernetComponent::setup() { // or via GPIO interrupt when one is provided. // Don't set started_ here — let the link polling in loop() set it - // when the W5500 link is actually up. Setting it prematurely causes - // a "Starting → Stopped → Starting" log sequence because the W5500 + // when the link is actually up. Setting it prematurely causes + // a "Starting → Stopped → Starting" log sequence because the chip // needs time after begin() before the PHY link is ready. } @@ -89,14 +92,21 @@ void EthernetComponent::loop() { // On RP2040, we need to poll connection state since there are no events. const uint32_t now = App.get_loop_component_start_time(); - // Throttle link/IP polling to avoid excessive SPI transactions from linkStatus() - // which reads the W5500 PHY register via SPI on every call. + // Throttle link/IP polling to avoid excessive SPI transactions. + // W5500/ENC28J60 read PHY register via SPI on every linkStatus() call. + // W5100 can't detect link state, so we skip the SPI read and assume link-up. // connected() reads netif->ip_addr without LwIPLock, but this is a single // 32-bit aligned read (atomic on ARM) — worst case is a one-iteration-stale // value, which is benign for polling. if (this->eth_ != nullptr && now - this->last_link_check_ >= LINK_CHECK_INTERVAL) { this->last_link_check_ = now; +#if defined(USE_ETHERNET_W5100) + // W5100 can't detect link (isLinkDetectable() returns false), so linkStatus() + // returns Unknown — assume link is up after successful begin() + bool link_up = true; +#else bool link_up = this->eth_->linkStatus() == LinkON; +#endif bool has_ip = this->eth_->connected(); if (!link_up) { @@ -171,6 +181,8 @@ void EthernetComponent::dump_config() { const char *type_str = "Unknown"; #if defined(USE_ETHERNET_W5500) type_str = "W5500"; +#elif defined(USE_ETHERNET_W5100) + type_str = "W5100"; #elif defined(USE_ETHERNET_ENC28J60) type_str = "ENC28J60"; #endif @@ -226,7 +238,7 @@ const char *EthernetComponent::get_eth_mac_address_pretty_into_buffer( } eth_duplex_t EthernetComponent::get_duplex_mode() { - // Both W5500 and ENC28J60 are full-duplex on RP2040 + // W5100, W5500, and ENC28J60 are full-duplex on RP2040 return ETH_DUPLEX_FULL; } @@ -235,7 +247,7 @@ eth_speed_t EthernetComponent::get_link_speed() { // ENC28J60 is 10Mbps only return ETH_SPEED_10M; #else - // W5500 is always 100Mbps + // W5100 and W5500 are 100Mbps return ETH_SPEED_100M; #endif } diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 996818c2e6..676ad3024f 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -284,6 +284,7 @@ #define USE_ETHERNET_SPI #define USE_ETHERNET_SPI_POLLING_SUPPORT #define USE_ETHERNET_OPENETH +#define USE_ETHERNET_W5100 #define USE_ETHERNET_W5500 #define USE_ETHERNET_DM9051 #define CONFIG_ETH_SPI_ETHERNET_W5500 1 diff --git a/tests/components/ethernet/common-w5100-rp2040.yaml b/tests/components/ethernet/common-w5100-rp2040.yaml new file mode 100644 index 0000000000..4c6d0313df --- /dev/null +++ b/tests/components/ethernet/common-w5100-rp2040.yaml @@ -0,0 +1,18 @@ +ethernet: + type: W5100 + clk_pin: 18 + mosi_pin: 19 + miso_pin: 16 + cs_pin: 17 + interrupt_pin: 21 + reset_pin: 20 + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + mac_address: "02:AA:BB:CC:DD:01" + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" diff --git a/tests/components/ethernet/test-w5100.rp2040-ard.yaml b/tests/components/ethernet/test-w5100.rp2040-ard.yaml new file mode 100644 index 0000000000..e101f3112a --- /dev/null +++ b/tests/components/ethernet/test-w5100.rp2040-ard.yaml @@ -0,0 +1 @@ +<<: !include common-w5100-rp2040.yaml From f457b995f726d54581421f0a885fdab4b922cdb0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:03:56 -1000 Subject: [PATCH 1695/2030] [datetime] Fix state_as_esptime() returning invalid timestamp (#15128) --- .../components/datetime/datetime_entity.cpp | 3 + esphome/core/time.cpp | 2 +- esphome/core/time.h | 18 ++++-- tests/components/time/posix_tz_parser.cpp | 56 ++++++++++++++++++- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index 730abb3ca8..fa50271f04 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -60,6 +60,9 @@ ESPTime DateTimeEntity::state_as_esptime() const { obj.year = this->year_; obj.month = this->month_; obj.day_of_month = this->day_; + obj.day_of_week = 0; + obj.day_of_year = 0; + obj.is_dst = false; obj.hour = this->hour_; obj.minute = this->minute_; obj.second = this->second_; diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 6add82e7d1..650c61d37b 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -231,7 +231,7 @@ void ESPTime::increment_day() { void ESPTime::recalc_timestamp_utc(bool use_day_of_year) { time_t res = 0; - if (!this->fields_in_range()) { + if (!this->fields_in_range(false, use_day_of_year)) { this->timestamp = -1; return; } diff --git a/esphome/core/time.h b/esphome/core/time.h index 1716c51ffd..ed47432038 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -79,11 +79,19 @@ struct ESPTime { /// Check if this ESPTime is valid (all fields in range and year is greater than or equal to 2019) bool is_valid() const { return this->year >= 2019 && this->fields_in_range(); } - /// Check if all time fields of this ESPTime are in range. - bool fields_in_range() const { - return this->second < 61 && this->minute < 60 && this->hour < 24 && this->day_of_week > 0 && - this->day_of_week < 8 && this->day_of_year > 0 && this->day_of_year < 367 && this->month > 0 && - this->month < 13 && this->day_of_month > 0 && this->day_of_month <= days_in_month(this->month, this->year); + /// Check if time fields are in range. + /// @param check_day_of_week validate day_of_week (not always available when constructing from date/time fields) + /// @param check_day_of_year validate day_of_year (not always available when constructing from date/time fields) + bool fields_in_range(bool check_day_of_week = true, bool check_day_of_year = true) const { + bool valid = this->second < 61 && this->minute < 60 && this->hour < 24 && this->month > 0 && this->month < 13 && + this->day_of_month > 0 && this->day_of_month <= days_in_month(this->month, this->year); + if (check_day_of_week) { + valid = valid && this->day_of_week > 0 && this->day_of_week < 8; + } + if (check_day_of_year) { + valid = valid && this->day_of_year > 0 && this->day_of_year < 367; + } + return valid; } /** Convert a string to ESPTime struct as specified by the format argument. diff --git a/tests/components/time/posix_tz_parser.cpp b/tests/components/time/posix_tz_parser.cpp index d1747ef5b1..b7cf2a4afa 100644 --- a/tests/components/time/posix_tz_parser.cpp +++ b/tests/components/time/posix_tz_parser.cpp @@ -1036,8 +1036,6 @@ static time_t esptime_recalc_local(int year, int month, int day, int hour, int m t.hour = hour; t.minute = min; t.second = sec; - t.day_of_week = 1; // Placeholder for fields_in_range() - t.day_of_year = 1; t.recalc_timestamp_local(); return t.timestamp; } @@ -1187,6 +1185,60 @@ TEST(RecalcTimestampLocal, NonDefaultTransitionTime) { EXPECT_EQ(esp_result, libc_result); } +TEST(RecalcTimestampLocal, MinimalFieldsWithoutDayOfWeekOrYear) { + // Regression test for issue #15115: DateTimeEntity::state_as_esptime() constructs + // an ESPTime with only year/month/day/hour/minute/second set (no day_of_week or + // day_of_year). recalc_timestamp_local() must work without those fields. + const char *tz_str = "CET-1CEST,M3.5.0,M10.5.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Construct ESPTime with only date/time fields (like state_as_esptime does) + ESPTime t{}; + t.year = 2026; + t.month = 3; + t.day_of_month = 20; + t.hour = 23; + t.minute = 14; + t.second = 55; + // day_of_week and day_of_year are deliberately left as 0 + t.recalc_timestamp_local(); + + // Must NOT return -1 (the bug: fields_in_range() rejected valid times) + EXPECT_NE(t.timestamp, -1); + + // Verify against libc + time_t libc_result = libc_mktime(2026, 3, 20, 23, 14, 55); + EXPECT_EQ(t.timestamp, libc_result); +} + +TEST(RecalcTimestampLocal, MinimalFieldsNoDST) { + // Same test but with a timezone that has no DST + const char *tz_str = "IST-5:30"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + ESPTime t{}; + t.year = 2026; + t.month = 3; + t.day_of_month = 23; + t.hour = 10; + t.minute = 0; + t.second = 0; + t.recalc_timestamp_local(); + + EXPECT_NE(t.timestamp, -1); + + time_t libc_result = libc_mktime(2026, 3, 23, 10, 0, 0); + EXPECT_EQ(t.timestamp, libc_result); +} + TEST(RecalcTimestampLocal, YearBoundaryDST) { // Test southern hemisphere DST across year boundary // Australia/Sydney: DST active from October to April (spans Jan 1) From 238adbe008b5adbe60fca970cf96343e96a3dba9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:04:17 -1000 Subject: [PATCH 1696/2030] [wifi] Fix roaming counter reset from delayed disconnect and successful retry (#15126) --- esphome/components/wifi/wifi_component.cpp | 66 +++++++++++++++++----- esphome/components/wifi/wifi_component.h | 6 ++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index e1d4b07471..2ed4b32a7a 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -287,18 +287,25 @@ bool CompactString::operator==(const StringRef &other) const { /// │ │ (counter reset to 0) │ │ (retry_connect called) │ /// │ └──────────────────────────────────┘ └───────────┬─────────────┘ /// │ │ │ -/// │ ↓ │ -/// │ ┌───────────────────────┐ │ -/// │ │ → IDLE │ │ -/// │ │ (counter preserved!) │ │ -/// │ └───────────────────────┘ │ +/// │ ┌─────────┴─────────┐ │ +/// │ ↓ ↓ │ +/// │ on target BSSID on other AP │ +/// │ │ │ │ +/// │ ↓ ↓ │ +/// │ ┌──────────────────┐ ┌────────────┐│ +/// │ │ → IDLE │ │ → IDLE ││ +/// │ │ (counter reset) │ │ (counter ││ +/// │ │ (roam worked!) │ │ preserved)││ +/// │ └──────────────────┘ └────────────┘│ /// │ │ /// │ Key behaviors: │ /// │ - After 3 checks: attempts >= 3, stop checking │ /// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │ -/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ +/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ +/// │ - Disconnect after scan (within grace period): counter preserved │ /// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │ -/// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ +/// │ - Roaming success via retry (on target BSSID): counter reset │ +/// │ - Roaming fail (RECONNECTING on other AP): counter preserved │ /// └──────────────────────────────────────────────────────────────────────┘ // Use if-chain instead of switch to avoid jump table in RODATA (wastes RAM on ESP8266) @@ -1576,17 +1583,33 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { // Only preserve attempts if reconnecting after a failed roam attempt // This prevents ping-pong between APs when a roam target is unreachable if (this->roaming_state_ == RoamingState::CONNECTING) { - // Successful roam to better AP - reset attempts so we can roam again later + // Successful roam to better AP on first try - reset attempts so we can roam again later ESP_LOGD(TAG, "Roam successful"); this->roaming_attempts_ = 0; } else if (this->roaming_state_ == RoamingState::RECONNECTING) { - // Failed roam, reconnected via normal recovery - keep attempts to prevent ping-pong - ESP_LOGD(TAG, "Reconnected after failed roam (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + // Check if we ended up on the roam target despite needing a retry + // (e.g., first connect failed but scan-based retry found and connected to the same better AP) + bssid_t current_bssid = this->wifi_bssid(); + if (this->roaming_target_bssid_ != bssid_t{} && current_bssid == this->roaming_target_bssid_) { + char bssid_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(current_bssid.data(), bssid_buf); + ESP_LOGD(TAG, "Roam successful (via retry, attempt %u/%u) to %s", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS, + bssid_buf); + this->roaming_attempts_ = 0; + } else if (this->roaming_target_bssid_ != bssid_t{}) { + // Failed roam to specific target, reconnected to different AP - keep attempts to prevent ping-pong + ESP_LOGD(TAG, "Reconnected after failed roam (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + } else { + // Reconnected after scan-induced disconnect (no roam target) - keep attempts + ESP_LOGD(TAG, "Reconnected after roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + } } else { // Normal connection (boot, credentials changed, etc.) this->roaming_attempts_ = 0; } this->roaming_state_ = RoamingState::IDLE; + this->roaming_target_bssid_ = {}; + this->roaming_scan_end_ = 0; // Clear all priority penalties - the next reconnect will happen when an AP disconnects, // which means the landscape has likely changed and previous tracked failures are stale @@ -2073,8 +2096,16 @@ void WiFiComponent::retry_connect() { ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::IDLE) { - // Not a roaming-triggered reconnect, reset state - this->clear_roaming_state_(); + // Check if a roaming scan recently completed - on ESP8266, going off-channel + // during scan can cause a delayed Beacon Timeout 8-20 seconds after scan finishes. + // Transition to RECONNECTING so the attempts counter is preserved on reconnect. + if (this->roaming_scan_end_ != 0 && millis() - this->roaming_scan_end_ < ROAMING_SCAN_GRACE_PERIOD) { + ESP_LOGD(TAG, "Disconnect after roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::RECONNECTING; + } else { + // Not a roaming-triggered reconnect, reset state + this->clear_roaming_state_(); + } } // RECONNECTING: keep state and counter, still trying to reconnect @@ -2307,6 +2338,8 @@ bool WiFiScanResult::operator==(const WiFiScanResult &rhs) const { return this-> void WiFiComponent::clear_roaming_state_() { this->roaming_attempts_ = 0; this->roaming_last_check_ = 0; + this->roaming_scan_end_ = 0; + this->roaming_target_bssid_ = {}; this->roaming_state_ = RoamingState::IDLE; } @@ -2374,7 +2407,7 @@ void WiFiComponent::check_roaming_(uint32_t now) { // Guard: skip scan if signal is already good (no meaningful improvement possible) int8_t rssi = this->wifi_rssi(); if (rssi > ROAMING_GOOD_RSSI) { - ESP_LOGV(TAG, "Roam check skipped, signal good (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, + ESP_LOGD(TAG, "Roam check skipped, signal good (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); return; } @@ -2388,6 +2421,9 @@ void WiFiComponent::process_roaming_scan_() { this->scan_done_ = false; // Default to IDLE - will be set to CONNECTING if we find a better AP this->roaming_state_ = RoamingState::IDLE; + // Record when scan completed so delayed disconnects (e.g., ESP8266 Beacon Timeout) + // can be attributed to the scan and avoid resetting the attempts counter + this->roaming_scan_end_ = millis(); // Get current connection info int8_t current_rssi = this->wifi_rssi(); @@ -2436,10 +2472,12 @@ void WiFiComponent::process_roaming_scan_() { WiFiAP roam_params = *selected; apply_scan_result_to_params(roam_params, *best); - this->release_scan_results_(); // Mark as roaming attempt - affects retry behavior if connection fails this->roaming_state_ = RoamingState::CONNECTING; + this->roaming_target_bssid_ = best->get_bssid(); // Must read before releasing scan results + + this->release_scan_results_(); // Connect directly - wifi_sta_connect_ handles disconnect internally this->start_connecting(roam_params); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 718f4a6e12..99b23436f7 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -779,6 +779,10 @@ class WiFiComponent final : public Component { static constexpr int8_t ROAMING_MIN_IMPROVEMENT = 10; // dB static constexpr int8_t ROAMING_GOOD_RSSI = -49; // Skip scan if signal is excellent static constexpr uint8_t ROAMING_MAX_ATTEMPTS = 3; + // Grace period after roaming scan completes. If WiFi disconnects within this + // window (e.g., ESP8266 Beacon Timeout caused by going off-channel during scan), + // the disconnect is treated as roaming-related and the attempts counter is preserved. + static constexpr uint32_t ROAMING_SCAN_GRACE_PERIOD = 30 * 1000; // 30 seconds // 4-byte members float output_power_{NAN}; @@ -786,6 +790,7 @@ class WiFiComponent final : public Component { uint32_t last_connected_{0}; uint32_t reboot_timeout_{}; uint32_t roaming_last_check_{0}; + uint32_t roaming_scan_end_{0}; // Timestamp when last roaming scan completed #ifdef USE_WIFI_AP uint32_t ap_timeout_{}; #endif @@ -810,6 +815,7 @@ class WiFiComponent final : public Component { bool error_from_callback_{false}; RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; RoamingState roaming_state_{RoamingState::IDLE}; + bssid_t roaming_target_bssid_{}; // BSSID of the AP we're trying to roam to #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) WiFiPowerSaveMode configured_power_save_{WIFI_POWER_SAVE_NONE}; #endif From 9c9ae190ee040b7eb97f7e82d74e73b7ea6cd7d6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:13:59 -1000 Subject: [PATCH 1697/2030] [core] Use compile-time HasElse parameter in IfAction (#15134) --- esphome/automation.py | 7 +++++-- esphome/core/base_automation.h | 27 ++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index 36ab30b654..17966dc782 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -413,13 +413,16 @@ async def if_action_to_code( template_arg: cg.TemplateArguments, args: TemplateArgsType, ) -> MockObj: + has_else = CONF_ELSE in config + # Prepend HasElse bool to template arguments: IfAction<HasElse, Ts...> + if_template_arg = cg.TemplateArguments(has_else, *template_arg) cond_conf = next(el for el in config if el in (CONF_ANY, CONF_ALL, CONF_CONDITION)) condition = await build_condition(config[cond_conf], template_arg, args) - var = cg.new_Pvariable(action_id, template_arg, condition) + var = cg.new_Pvariable(action_id, if_template_arg, condition) if CONF_THEN in config: actions = await build_action_list(config[CONF_THEN], template_arg, args) cg.add(var.add_then(actions)) - if CONF_ELSE in config: + if has_else: actions = await build_action_list(config[CONF_ELSE], template_arg, args) cg.add(var.add_else(actions)) return var diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index 985f26e711..efcffa8824 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -264,7 +264,7 @@ template<typename... Ts> class WhileLoopContinuation : public Action<Ts...> { WhileAction<Ts...> *parent_; }; -template<typename... Ts> class IfAction : public Action<Ts...> { +template<bool HasElse, typename... Ts> class IfAction : public Action<Ts...> { public: explicit IfAction(Condition<Ts...> *condition) : condition_(condition) {} @@ -273,27 +273,25 @@ template<typename... Ts> class IfAction : public Action<Ts...> { this->then_.add_action(new ContinuationAction<Ts...>(this)); } - void add_else(const std::initializer_list<Action<Ts...> *> &actions) { + void add_else(const std::initializer_list<Action<Ts...> *> &actions) requires(HasElse) { this->else_.add_actions(actions); this->else_.add_action(new ContinuationAction<Ts...>(this)); } void play_complex(const Ts &...x) override { this->num_running_++; - bool res = this->condition_->check(x...); - if (res) { - if (this->then_.empty()) { - this->play_next_(x...); - } else if (this->num_running_ > 0) { + if (this->condition_->check(x...)) { + if (!this->then_.empty() && this->num_running_ > 0) { this->then_.play(x...); + return; } - } else { - if (this->else_.empty()) { - this->play_next_(x...); - } else if (this->num_running_ > 0) { + } else if constexpr (HasElse) { + if (!this->else_.empty() && this->num_running_ > 0) { this->else_.play(x...); + return; } } + this->play_next_(x...); } void play(const Ts &...x) override { /* ignore - see play_complex */ @@ -301,13 +299,16 @@ template<typename... Ts> class IfAction : public Action<Ts...> { void stop() override { this->then_.stop(); - this->else_.stop(); + if constexpr (HasElse) { + this->else_.stop(); + } } protected: Condition<Ts...> *condition_; ActionList<Ts...> then_; - ActionList<Ts...> else_; + struct NoElse {}; + [[no_unique_address]] std::conditional_t<HasElse, ActionList<Ts...>, NoElse> else_; }; template<typename... Ts> class WhileAction : public Action<Ts...> { From 26e78c840ce4e35589245279e7d39f27039af851 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:21:04 -0400 Subject: [PATCH 1698/2030] [wifi] Filter fast_connect by band_mode and use background scan for roaming (#15152) --- esphome/components/wifi/wifi_component.cpp | 8 ++++++++ esphome/components/wifi/wifi_component.h | 2 ++ esphome/components/wifi/wifi_component_esp_idf.cpp | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2ed4b32a7a..620d1a083d 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2222,6 +2222,14 @@ bool WiFiComponent::load_fast_connect_settings_(WiFiAP ¶ms) { params.set_hidden(false); ESP_LOGD(TAG, "Loaded fast_connect settings"); +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + if ((this->band_mode_ == WIFI_BAND_MODE_5G_ONLY && fast_connect_save.channel < FIRST_5GHZ_CHANNEL) || + (this->band_mode_ == WIFI_BAND_MODE_2G_ONLY && fast_connect_save.channel >= FIRST_5GHZ_CHANNEL)) { + ESP_LOGW(TAG, "Saved channel %u not allowed by band mode, ignoring fast_connect", fast_connect_save.channel); + this->selected_sta_index_ = -1; + return false; + } +#endif return true; } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 99b23436f7..55e532c37d 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -774,6 +774,8 @@ class WiFiComponent final : public Component { SemaphoreHandle_t high_performance_semaphore_{nullptr}; #endif + static constexpr uint8_t FIRST_5GHZ_CHANNEL = 36; + // Post-connect roaming constants static constexpr uint32_t ROAMING_CHECK_INTERVAL = 5 * 60 * 1000; // 5 minutes static constexpr int8_t ROAMING_MIN_IMPROVEMENT = 10; // dB diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 2866ec1513..1b80adc82e 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -987,6 +987,11 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { config.scan_time.active.min = 100; config.scan_time.active.max = 300; } + // When scanning while connected (roaming), return to home channel between + // each scanned channel to maintain the connection (helps with BLE/WiFi coexistence) + if (this->roaming_state_ == RoamingState::SCANNING) { + config.coex_background_scan = true; + } esp_err_t err = esp_wifi_scan_start(&config, false); if (err != ESP_OK) { From 690dc324c97d753788491b1fa8c423776af2a1a9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:52:37 -1000 Subject: [PATCH 1699/2030] [logger] Move task log buffer storage to BSS (#15153) --- esphome/components/logger/__init__.py | 20 +++++-------- esphome/components/logger/logger.cpp | 26 +++++------------ esphome/components/logger/logger.h | 13 +++------ .../logger/task_log_buffer_esp32.cpp | 18 +++--------- .../components/logger/task_log_buffer_esp32.h | 13 ++++----- .../logger/task_log_buffer_host.cpp | 17 +++-------- .../components/logger/task_log_buffer_host.h | 13 ++------- .../logger/task_log_buffer_libretiny.cpp | 29 +++++++------------ .../logger/task_log_buffer_libretiny.h | 12 ++++---- .../logger/task_log_buffer_zephyr.cpp | 13 ++++----- .../logger/task_log_buffer_zephyr.h | 10 ++++--- esphome/core/defines.h | 6 ++++ tests/benchmarks/components/main.cpp | 2 +- tests/components/main.cpp | 2 +- tests/dummy_main.cpp | 2 +- 15 files changed, 69 insertions(+), 127 deletions(-) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index 4345e291a3..4144543b89 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -331,9 +331,8 @@ async def to_code(config: ConfigType) -> None: CORE.data.setdefault(CONF_LOGGER, {})[CONF_LEVEL] = level tx_buffer_size = config[CONF_TX_BUFFER_SIZE] cg.add_define("ESPHOME_LOGGER_TX_BUFFER_SIZE", tx_buffer_size) - # Determine task log buffer size and define USE_ESPHOME_TASK_LOG_BUFFER early - # so the constructor can allocate the buffer immediately, preventing a race - # where another task logs before the buffer is initialized. + # Determine task log buffer size. The buffer is a direct member of Logger + # (no separate heap allocation). task_log_buffer_size = 0 if CORE.is_esp32 or CORE.is_libretiny or CORE.is_nrf52: task_log_buffer_size = config[CONF_TASK_LOG_BUFFER_SIZE] @@ -341,16 +340,11 @@ async def to_code(config: ConfigType) -> None: task_log_buffer_size = 64 # Fixed 64 slots for host if task_log_buffer_size > 0: cg.add_define("USE_ESPHOME_TASK_LOG_BUFFER") - log = cg.new_Pvariable( - config[CONF_ID], - baud_rate, - task_log_buffer_size, - ) - else: - log = cg.new_Pvariable( - config[CONF_ID], - baud_rate, - ) + cg.add_define("ESPHOME_TASK_LOG_BUFFER_SIZE", task_log_buffer_size) + log = cg.new_Pvariable( + config[CONF_ID], + baud_rate, + ) if CORE.is_esp32 or CORE.is_host: cg.add(log.create_pthread_key()) # set_uart_selection() must be called before pre_setup() because diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index ceacded775..cd6543bfb8 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -83,7 +83,7 @@ void Logger::log_vprintf_non_main_thread_(uint8_t level, const char *tag, int li #ifdef USE_ESPHOME_TASK_LOG_BUFFER // For non-main threads/tasks, queue the message for callbacks message_sent = - this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), thread_name, format, args); + this->log_buffer_.send_message_thread_safe(level, tag, static_cast<uint16_t>(line), thread_name, format, args); if (message_sent) { // Enable logger loop to process the buffered message // This is safe to call from any context including ISRs @@ -152,23 +152,13 @@ inline uint8_t Logger::level_for(const char *tag) { return this->current_level_; } -#ifdef USE_ESPHOME_TASK_LOG_BUFFER -Logger::Logger(uint32_t baud_rate, size_t task_log_buffer_size) : baud_rate_(baud_rate) { -#else Logger::Logger(uint32_t baud_rate) : baud_rate_(baud_rate) { -#endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) this->main_task_ = xTaskGetCurrentTaskHandle(); #elif defined(USE_ZEPHYR) this->main_task_ = k_current_get(); #elif defined(USE_HOST) -this->main_thread_ = pthread_self(); -#endif -#ifdef USE_ESPHOME_TASK_LOG_BUFFER - // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) - allocated once, never freed - this->log_buffer_ = new logger::TaskLogBuffer(task_log_buffer_size); - // Note: we don't disable loop here because the component isn't registered with App yet. - // The loop self-disables on its first iteration when it finds no messages to process. + this->main_thread_ = pthread_self(); #endif } @@ -184,16 +174,16 @@ void Logger::loop() { void Logger::process_messages_() { #ifdef USE_ESPHOME_TASK_LOG_BUFFER // Process any buffered messages when available - if (this->log_buffer_->has_messages()) { + if (this->log_buffer_.has_messages()) { logger::TaskLogBuffer::LogMessage *message; uint16_t text_length; - while (this->log_buffer_->borrow_message_main_loop(message, text_length)) { + while (this->log_buffer_.borrow_message_main_loop(message, text_length)) { const char *thread_name = message->thread_name[0] != '\0' ? message->thread_name : nullptr; LogBuffer buf{this->tx_buffer_, ESPHOME_LOGGER_TX_BUFFER_SIZE}; this->format_buffered_message_and_notify_(message->level, message->tag, message->line, thread_name, message->text_data(), text_length, buf); // Release the message to allow other tasks to use it as soon as possible - this->log_buffer_->release_message_main_loop(); + this->log_buffer_.release_message_main_loop(); this->write_log_buffer_to_console_(buf); } } @@ -239,13 +229,11 @@ void Logger::dump_config() { this->baud_rate_, LOG_STR_ARG(get_uart_selection_())); #endif #ifdef USE_ESPHOME_TASK_LOG_BUFFER - if (this->log_buffer_) { #ifdef USE_HOST - ESP_LOGCONFIG(TAG, " Task Log Buffer Slots: %u", static_cast<unsigned int>(this->log_buffer_->size())); + ESP_LOGCONFIG(TAG, " Task Log Buffer Slots: %u", static_cast<unsigned int>(this->log_buffer_.size())); #else - ESP_LOGCONFIG(TAG, " Task Log Buffer Size: %u bytes", static_cast<unsigned int>(this->log_buffer_->size())); + ESP_LOGCONFIG(TAG, " Task Log Buffer Size: %u bytes", static_cast<unsigned int>(this->log_buffer_.size())); #endif - } #endif #ifdef USE_LOGGER_RUNTIME_TAG_LEVELS diff --git a/esphome/components/logger/logger.h b/esphome/components/logger/logger.h index c81b8e4e94..784cbea67e 100644 --- a/esphome/components/logger/logger.h +++ b/esphome/components/logger/logger.h @@ -143,11 +143,7 @@ enum UARTSelection : uint8_t { */ class Logger final : public Component { public: -#ifdef USE_ESPHOME_TASK_LOG_BUFFER - explicit Logger(uint32_t baud_rate, size_t task_log_buffer_size); -#else explicit Logger(uint32_t baud_rate); -#endif #if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_UART_SELECTION_USB_CDC)) void loop() override; #endif @@ -353,10 +349,6 @@ class Logger final : public Component { #ifdef USE_LOGGER_LEVEL_LISTENERS std::vector<LoggerLevelListener *> level_listeners_; // Log level change listeners #endif -#ifdef USE_ESPHOME_TASK_LOG_BUFFER - logger::TaskLogBuffer *log_buffer_{nullptr}; // Allocated once, never freed -#endif - // Group smaller types together at the end uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE}; #if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR) @@ -374,8 +366,11 @@ class Logger final : public Component { bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms #endif - // Large buffer placed last to keep frequently-accessed member offsets small + // Large buffers placed last to keep frequently-accessed member offsets small char tx_buffer_[ESPHOME_LOGGER_TX_BUFFER_SIZE + 1]; // +1 for null terminator +#ifdef USE_ESPHOME_TASK_LOG_BUFFER + logger::TaskLogBuffer log_buffer_; // Embedded in Logger (no separate heap allocation) +#endif // --- get_thread_name_ overloads (per-platform) --- diff --git a/esphome/components/logger/task_log_buffer_esp32.cpp b/esphome/components/logger/task_log_buffer_esp32.cpp index e747ddc4d8..cb97f5504f 100644 --- a/esphome/components/logger/task_log_buffer_esp32.cpp +++ b/esphome/components/logger/task_log_buffer_esp32.cpp @@ -1,33 +1,23 @@ #ifdef USE_ESP32 #include "task_log_buffer_esp32.h" -#include "esphome/core/helpers.h" #include "esphome/core/log.h" #ifdef USE_ESPHOME_TASK_LOG_BUFFER namespace esphome::logger { -TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) { - // Store the buffer size - this->size_ = total_buffer_size; - // Allocate memory for the ring buffer using ESPHome's RAM allocator - RAMAllocator<uint8_t> allocator; - this->storage_ = allocator.allocate(this->size_); +TaskLogBuffer::TaskLogBuffer() { // Create a static ring buffer with RINGBUF_TYPE_NOSPLIT for message integrity - this->ring_buffer_ = xRingbufferCreateStatic(this->size_, RINGBUF_TYPE_NOSPLIT, this->storage_, &this->structure_); + // Storage is a member array (embedded in Logger), no heap allocation needed + this->ring_buffer_ = + xRingbufferCreateStatic(sizeof(this->storage_), RINGBUF_TYPE_NOSPLIT, this->storage_, &this->structure_); } TaskLogBuffer::~TaskLogBuffer() { if (this->ring_buffer_ != nullptr) { - // Delete the ring buffer vRingbufferDelete(this->ring_buffer_); this->ring_buffer_ = nullptr; - - // Free the allocated memory - RAMAllocator<uint8_t> allocator; - allocator.deallocate(this->storage_, this->size_); - this->storage_ = nullptr; } } diff --git a/esphome/components/logger/task_log_buffer_esp32.h b/esphome/components/logger/task_log_buffer_esp32.h index 88d72eacfc..e819766795 100644 --- a/esphome/components/logger/task_log_buffer_esp32.h +++ b/esphome/components/logger/task_log_buffer_esp32.h @@ -8,7 +8,6 @@ #ifdef USE_ESPHOME_TASK_LOG_BUFFER #include <cstddef> #include <cstring> -#include <memory> #include <atomic> #include <freertos/FreeRTOS.h> #include <freertos/ringbuf.h> @@ -47,8 +46,7 @@ class TaskLogBuffer { inline const char *text_data() const { return reinterpret_cast<const char *>(this) + sizeof(LogMessage); } }; - // Constructor that takes a total buffer size - explicit TaskLogBuffer(size_t total_buffer_size); + TaskLogBuffer(); ~TaskLogBuffer(); // NOT thread-safe - borrow a message from the ring buffer, only call from main loop @@ -67,13 +65,12 @@ class TaskLogBuffer { } // Get the total buffer size in bytes - inline size_t size() const { return size_; } + static constexpr size_t size() { return ESPHOME_TASK_LOG_BUFFER_SIZE; } private: - RingbufHandle_t ring_buffer_{nullptr}; // FreeRTOS ring buffer handle - StaticRingbuffer_t structure_; // Static structure for the ring buffer - uint8_t *storage_{nullptr}; // Pointer to allocated memory - size_t size_{0}; // Size of allocated memory + RingbufHandle_t ring_buffer_{nullptr}; // FreeRTOS ring buffer handle + StaticRingbuffer_t structure_; // Static structure for the ring buffer + uint8_t storage_[ESPHOME_TASK_LOG_BUFFER_SIZE]; // Embedded in Logger (no separate heap allocation) // Atomic counter for message tracking (only differences matter) std::atomic<uint16_t> message_counter_{0}; // Incremented when messages are committed diff --git a/esphome/components/logger/task_log_buffer_host.cpp b/esphome/components/logger/task_log_buffer_host.cpp index c2ab009db4..8ebc946383 100644 --- a/esphome/components/logger/task_log_buffer_host.cpp +++ b/esphome/components/logger/task_log_buffer_host.cpp @@ -10,22 +10,13 @@ namespace esphome::logger { -TaskLogBuffer::TaskLogBuffer(size_t slot_count) : slot_count_(slot_count) { - // Allocate message slots - this->slots_ = std::make_unique<LogMessage[]>(slot_count); -} - -TaskLogBuffer::~TaskLogBuffer() { - // unique_ptr handles cleanup automatically -} - int TaskLogBuffer::acquire_write_slot_() { // Try to reserve a slot using compare-and-swap size_t current_reserve = this->reserve_index_.load(std::memory_order_relaxed); while (true) { // Calculate next index (with wrap-around) - size_t next_reserve = (current_reserve + 1) % this->slot_count_; + size_t next_reserve = (current_reserve + 1) % ESPHOME_TASK_LOG_BUFFER_SIZE; // Check if buffer would be full // Buffer is full when next write position equals read position @@ -50,7 +41,7 @@ void TaskLogBuffer::commit_write_slot_(int slot_index) { // Try to advance the write_index if we're the next expected commit // This ensures messages are read in order size_t expected = slot_index; - size_t next = (slot_index + 1) % this->slot_count_; + size_t next = (slot_index + 1) % ESPHOME_TASK_LOG_BUFFER_SIZE; // We only advance write_index if this slot is the next one expected // This handles out-of-order commits correctly @@ -63,7 +54,7 @@ void TaskLogBuffer::commit_write_slot_(int slot_index) { // Successfully advanced, check if next slot is also ready expected = next; - next = (next + 1) % this->slot_count_; + next = (next + 1) % ESPHOME_TASK_LOG_BUFFER_SIZE; if (!this->slots_[expected].ready.load(std::memory_order_acquire)) { break; } @@ -142,7 +133,7 @@ void TaskLogBuffer::release_message_main_loop() { this->slots_[current_read].ready.store(false, std::memory_order_release); // Advance read index - size_t next_read = (current_read + 1) % this->slot_count_; + size_t next_read = (current_read + 1) % ESPHOME_TASK_LOG_BUFFER_SIZE; this->read_index_.store(next_read, std::memory_order_release); } diff --git a/esphome/components/logger/task_log_buffer_host.h b/esphome/components/logger/task_log_buffer_host.h index 1d4d2b0ec1..25e9c4da58 100644 --- a/esphome/components/logger/task_log_buffer_host.h +++ b/esphome/components/logger/task_log_buffer_host.h @@ -11,7 +11,6 @@ #include <cstdarg> #include <cstddef> #include <cstring> -#include <memory> #include <pthread.h> namespace esphome::logger { @@ -50,9 +49,6 @@ namespace esphome::logger { */ class TaskLogBuffer { public: - // Default number of message slots - host has plenty of memory - static constexpr size_t DEFAULT_SLOT_COUNT = 64; - // Structure for a log message (fixed size for lock-free operation) struct LogMessage { // Size constants @@ -74,9 +70,7 @@ class TaskLogBuffer { inline char *text_data() { return this->text; } }; - /// Constructor that takes the number of message slots - explicit TaskLogBuffer(size_t slot_count); - ~TaskLogBuffer(); + TaskLogBuffer() = default; // NOT thread-safe - get next message from buffer, only call from main loop // Returns true if a message was retrieved, false if buffer is empty @@ -96,7 +90,7 @@ class TaskLogBuffer { } // Get the buffer size (number of slots) - inline size_t size() const { return slot_count_; } + static constexpr size_t size() { return ESPHOME_TASK_LOG_BUFFER_SIZE; } private: // Acquire a slot for writing (thread-safe) @@ -106,8 +100,7 @@ class TaskLogBuffer { // Commit a slot after writing (thread-safe) void commit_write_slot_(int slot_index); - std::unique_ptr<LogMessage[]> slots_; // Pre-allocated message slots - size_t slot_count_; // Number of slots + LogMessage slots_[ESPHOME_TASK_LOG_BUFFER_SIZE]; // Embedded in Logger (no separate heap allocation) // Lock-free indices using atomics // - reserve_index_: Next slot to reserve (producers CAS this to claim slots) diff --git a/esphome/components/logger/task_log_buffer_libretiny.cpp b/esphome/components/logger/task_log_buffer_libretiny.cpp index 5969f6fb40..b6d6b22ab5 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.cpp +++ b/esphome/components/logger/task_log_buffer_libretiny.cpp @@ -1,19 +1,15 @@ #ifdef USE_LIBRETINY #include "task_log_buffer_libretiny.h" -#include "esphome/core/helpers.h" #include "esphome/core/log.h" #ifdef USE_ESPHOME_TASK_LOG_BUFFER namespace esphome::logger { -TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) { - this->size_ = total_buffer_size; - // Allocate memory for the circular buffer using ESPHome's RAM allocator - RAMAllocator<uint8_t> allocator; - this->storage_ = allocator.allocate(this->size_); +TaskLogBuffer::TaskLogBuffer() { // Create mutex for thread-safe access + // Storage is a member array (embedded in Logger), no heap allocation needed this->mutex_ = xSemaphoreCreateMutex(); } @@ -22,11 +18,6 @@ TaskLogBuffer::~TaskLogBuffer() { vSemaphoreDelete(this->mutex_); this->mutex_ = nullptr; } - if (this->storage_ != nullptr) { - RAMAllocator<uint8_t> allocator; - allocator.deallocate(this->storage_, this->size_); - this->storage_ = nullptr; - } } size_t TaskLogBuffer::available_contiguous_space() const { @@ -34,7 +25,7 @@ size_t TaskLogBuffer::available_contiguous_space() const { // head is ahead of or equal to tail // Available space is from head to end, plus from start to tail // But for contiguous, just from head to end (minus 1 to avoid head==tail ambiguity) - size_t space_to_end = this->size_ - this->head_; + size_t space_to_end = ESPHOME_TASK_LOG_BUFFER_SIZE - this->head_; if (this->tail_ == 0) { // Can't use the last byte or head would equal tail return space_to_end > 0 ? space_to_end - 1 : 0; @@ -48,8 +39,8 @@ size_t TaskLogBuffer::available_contiguous_space() const { } bool TaskLogBuffer::borrow_message_main_loop(LogMessage *&message, uint16_t &text_length) { - // Check if buffer was initialized successfully - if (this->mutex_ == nullptr || this->storage_ == nullptr) { + // Check if mutex was initialized successfully + if (this->mutex_ == nullptr) { return false; } @@ -86,7 +77,7 @@ void TaskLogBuffer::release_message_main_loop() { this->tail_ += this->current_message_size_; // Handle wrap-around if we've reached the end - if (this->tail_ >= this->size_) { + if (this->tail_ >= ESPHOME_TASK_LOG_BUFFER_SIZE) { this->tail_ = 0; } @@ -115,9 +106,9 @@ bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uin // Calculate total size needed (header + text length + null terminator) size_t total_size = message_total_size(text_length); - // Check if buffer was initialized successfully - if (this->mutex_ == nullptr || this->storage_ == nullptr) { - return false; // Buffer not initialized, fall back to direct output + // Check if mutex was initialized successfully + if (this->mutex_ == nullptr) { + return false; // Mutex not initialized, fall back to direct output } // Try to acquire mutex without blocking - don't block logging tasks @@ -185,7 +176,7 @@ bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uin this->head_ += total_size; // Handle wrap-around (shouldn't happen due to contiguous space check, but be safe) - if (this->head_ >= this->size_) { + if (this->head_ >= ESPHOME_TASK_LOG_BUFFER_SIZE) { this->head_ = 0; } diff --git a/esphome/components/logger/task_log_buffer_libretiny.h b/esphome/components/logger/task_log_buffer_libretiny.h index c065065fe7..b42894502a 100644 --- a/esphome/components/logger/task_log_buffer_libretiny.h +++ b/esphome/components/logger/task_log_buffer_libretiny.h @@ -59,8 +59,7 @@ class TaskLogBuffer { // Valid log levels are 0-7, so 0xFF cannot be a real message static constexpr uint8_t PADDING_MARKER_LEVEL = 0xFF; - // Constructor that takes a total buffer size - explicit TaskLogBuffer(size_t total_buffer_size); + TaskLogBuffer(); ~TaskLogBuffer(); // NOT thread-safe - borrow a message from the buffer, only call from main loop @@ -78,7 +77,7 @@ class TaskLogBuffer { inline bool HOT has_messages() const { return this->message_count_ != 0; } // Get the total buffer size in bytes - inline size_t size() const { return this->size_; } + static constexpr size_t size() { return ESPHOME_TASK_LOG_BUFFER_SIZE; } private: // Calculate total size needed for a message (header + text + null terminator) @@ -87,10 +86,9 @@ class TaskLogBuffer { // Calculate available contiguous space at write position size_t available_contiguous_space() const; - uint8_t *storage_{nullptr}; // Pointer to allocated memory - size_t size_{0}; // Size of allocated memory - size_t head_{0}; // Write position - size_t tail_{0}; // Read position + uint8_t storage_[ESPHOME_TASK_LOG_BUFFER_SIZE]; // Embedded in Logger (no separate heap allocation) + size_t head_{0}; // Write position + size_t tail_{0}; // Read position SemaphoreHandle_t mutex_{nullptr}; // FreeRTOS mutex for thread safety volatile uint16_t message_count_{0}; // Fast check counter (dirty read OK) diff --git a/esphome/components/logger/task_log_buffer_zephyr.cpp b/esphome/components/logger/task_log_buffer_zephyr.cpp index 44d12d08a3..a994925a54 100644 --- a/esphome/components/logger/task_log_buffer_zephyr.cpp +++ b/esphome/components/logger/task_log_buffer_zephyr.cpp @@ -17,19 +17,16 @@ static inline uint32_t get_wlen(const mpsc_pbuf_generic *item) { return total_size_in_32bit_words(reinterpret_cast<const TaskLogBuffer::LogMessage *>(item)->text_length); } -TaskLogBuffer::TaskLogBuffer(size_t total_buffer_size) { - // alignment to 4 bytes - total_buffer_size = (total_buffer_size + 3) / sizeof(uint32_t); - this->mpsc_config_.buf = new uint32_t[total_buffer_size]; - this->mpsc_config_.size = total_buffer_size; +TaskLogBuffer::TaskLogBuffer() { + // Storage is a member array (embedded in Logger), no heap allocation needed + this->mpsc_config_.buf = this->buf_storage_; + this->mpsc_config_.size = BUF_WORD_COUNT; this->mpsc_config_.flags = MPSC_PBUF_MODE_OVERWRITE; - this->mpsc_config_.get_wlen = get_wlen, + this->mpsc_config_.get_wlen = get_wlen; mpsc_pbuf_init(&this->log_buffer_, &this->mpsc_config_); } -TaskLogBuffer::~TaskLogBuffer() { delete[] this->mpsc_config_.buf; } - bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args) { // First, calculate the exact length needed using a null buffer (no actual writing) diff --git a/esphome/components/logger/task_log_buffer_zephyr.h b/esphome/components/logger/task_log_buffer_zephyr.h index cc2ed1f687..4f192366ad 100644 --- a/esphome/components/logger/task_log_buffer_zephyr.h +++ b/esphome/components/logger/task_log_buffer_zephyr.h @@ -33,15 +33,14 @@ class TaskLogBuffer { // Methods for accessing message contents inline char *text_data() { return reinterpret_cast<char *>(this) + sizeof(LogMessage); } }; - // Constructor that takes a total buffer size - explicit TaskLogBuffer(size_t total_buffer_size); - ~TaskLogBuffer(); + TaskLogBuffer(); + ~TaskLogBuffer() = default; // Check if there are messages ready to be processed using an atomic counter for performance inline bool HOT has_messages() { return mpsc_pbuf_is_pending(&this->log_buffer_); } // Get the total buffer size in bytes - inline size_t size() const { return this->mpsc_config_.size * sizeof(uint32_t); } + static constexpr size_t size() { return BUF_WORD_COUNT * sizeof(uint32_t); } // NOT thread-safe - borrow a message from the ring buffer, only call from main loop bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length); @@ -54,6 +53,9 @@ class TaskLogBuffer { const char *format, va_list args); protected: + // Round up byte size to 32-bit word count for mpsc_pbuf alignment requirement + static constexpr size_t BUF_WORD_COUNT = (ESPHOME_TASK_LOG_BUFFER_SIZE + 3) / sizeof(uint32_t); + uint32_t buf_storage_[BUF_WORD_COUNT]; // Embedded in Logger (no separate heap allocation) mpsc_pbuf_buffer_config mpsc_config_{}; mpsc_pbuf_buffer log_buffer_{}; const mpsc_pbuf_generic *current_token_{}; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 676ad3024f..b5612a1d3f 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -200,6 +200,7 @@ #define USE_ESP32_CRASH_HANDLER #define USE_MQTT_IDF_ENQUEUE #define USE_ESPHOME_TASK_LOG_BUFFER +#define ESPHOME_TASK_LOG_BUFFER_SIZE 768 #define USE_OTA_ROLLBACK #define USE_ESP32_MIN_CHIP_REVISION_SET #define USE_ESP32_SRAM1_AS_IRAM @@ -373,18 +374,23 @@ #define USE_WEBSERVER #define USE_WEBSERVER_AUTH #define USE_WEBSERVER_PORT 80 // NOLINT +#define USE_ESPHOME_TASK_LOG_BUFFER +#define ESPHOME_TASK_LOG_BUFFER_SIZE 768 #endif #ifdef USE_HOST #define USE_HTTP_REQUEST_RESPONSE #define USE_SOCKET_IMPL_BSD_SOCKETS #define USE_SOCKET_SELECT_SUPPORT +#define USE_ESPHOME_TASK_LOG_BUFFER +#define ESPHOME_TASK_LOG_BUFFER_SIZE 64 #endif #ifdef USE_NRF52 #define ESPHOME_BLE_NUS_TX_RING_BUFFER_SIZE 512 #define ESPHOME_BLE_NUS_RX_RING_BUFFER_SIZE 512 #define USE_ESPHOME_TASK_LOG_BUFFER +#define ESPHOME_TASK_LOG_BUFFER_SIZE 768 #define USE_LOGGER_EARLY_MESSAGE #define USE_LOGGER_UART_SELECTION_USB_CDC #define USE_LOGGER_USB_CDC diff --git a/tests/benchmarks/components/main.cpp b/tests/benchmarks/components/main.cpp index 901dc44c07..9bc0c31a15 100644 --- a/tests/benchmarks/components/main.cpp +++ b/tests/benchmarks/components/main.cpp @@ -26,7 +26,7 @@ void setup() { // Log functions call global_logger->log_vprintf_() without a null check, // so we must set up a Logger before any test that triggers logging. - static esphome::logger::Logger test_logger(0, 64); + static esphome::logger::Logger test_logger(0); test_logger.set_log_level(ESPHOME_LOG_LEVEL); test_logger.pre_setup(); diff --git a/tests/components/main.cpp b/tests/components/main.cpp index 622b1f107b..373fde7151 100644 --- a/tests/components/main.cpp +++ b/tests/components/main.cpp @@ -22,7 +22,7 @@ void original_setup() { void setup() { // Log functions call global_logger->log_vprintf_() without a null check, // so we must set up a Logger before any test that triggers logging. - static esphome::logger::Logger test_logger(0, 64); + static esphome::logger::Logger test_logger(0); test_logger.set_log_level(ESPHOME_LOG_LEVEL); test_logger.pre_setup(); diff --git a/tests/dummy_main.cpp b/tests/dummy_main.cpp index 329286e2fa..6fa0c08aa3 100644 --- a/tests/dummy_main.cpp +++ b/tests/dummy_main.cpp @@ -15,7 +15,7 @@ void setup() { static char name[] = "livingroom"; static char friendly_name[] = "LivingRoom"; App.pre_setup(name, sizeof(name) - 1, friendly_name, sizeof(friendly_name) - 1); - auto *log = new logger::Logger(115200, 512); // NOLINT + auto *log = new logger::Logger(115200); // NOLINT log->pre_setup(); log->set_uart_selection(logger::UART_SELECTION_UART0); App.register_component_(log); From af5b98c635f3209cfcc940a8341545eaaf74749a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 15:07:28 -1000 Subject: [PATCH 1700/2030] [time] Remove dummy placeholder values for recalc_timestamp_utc() (#15129) --- esphome/components/bm8563/bm8563.cpp | 1 - esphome/components/ds1307/ds1307.cpp | 3 --- esphome/components/gps/time/gps_time.cpp | 4 ---- esphome/components/pcf85063/pcf85063.cpp | 3 --- esphome/components/pcf8563/pcf8563.cpp | 3 --- esphome/components/rx8130/rx8130.cpp | 3 --- 6 files changed, 17 deletions(-) diff --git a/esphome/components/bm8563/bm8563.cpp b/esphome/components/bm8563/bm8563.cpp index 07831485c1..269acfea44 100644 --- a/esphome/components/bm8563/bm8563.cpp +++ b/esphome/components/bm8563/bm8563.cpp @@ -56,7 +56,6 @@ void BM8563::read_time() { ESPTime rtc_time; this->get_time_(rtc_time); this->get_date_(rtc_time); - rtc_time.day_of_year = 1; // unused by recalc_timestamp_utc, but needs to be valid ESP_LOGD(TAG, "Read time: %i-%i-%i %i, %i:%i:%i", rtc_time.year, rtc_time.month, rtc_time.day_of_month, rtc_time.day_of_week, rtc_time.hour, rtc_time.minute, rtc_time.second); diff --git a/esphome/components/ds1307/ds1307.cpp b/esphome/components/ds1307/ds1307.cpp index 5c0e98290b..8fff4213b4 100644 --- a/esphome/components/ds1307/ds1307.cpp +++ b/esphome/components/ds1307/ds1307.cpp @@ -40,11 +40,8 @@ void DS1307Component::read_time() { .hour = uint8_t(ds1307_.reg.hour + 10u * ds1307_.reg.hour_10), .day_of_week = uint8_t(ds1307_.reg.weekday), .day_of_month = uint8_t(ds1307_.reg.day + 10u * ds1307_.reg.day_10), - .day_of_year = 1, // ignored by recalc_timestamp_utc(false) .month = uint8_t(ds1307_.reg.month + 10u * ds1307_.reg.month_10), .year = uint16_t(ds1307_.reg.year + 10u * ds1307_.reg.year_10 + 2000), - .is_dst = false, // not used - .timestamp = 0 // overwritten by recalc_timestamp_utc(false) }; rtc_time.recalc_timestamp_utc(false); if (!rtc_time.is_valid()) { diff --git a/esphome/components/gps/time/gps_time.cpp b/esphome/components/gps/time/gps_time.cpp index cff8c1fb07..fb662a3d60 100644 --- a/esphome/components/gps/time/gps_time.cpp +++ b/esphome/components/gps/time/gps_time.cpp @@ -16,10 +16,6 @@ void GPSTime::from_tiny_gps_(TinyGPSPlus &tiny_gps) { val.year = tiny_gps.date.year(); val.month = tiny_gps.date.month(); val.day_of_month = tiny_gps.date.day(); - // Set these to valid value for recalc_timestamp_utc - it's not used for calculation - val.day_of_week = 1; - val.day_of_year = 1; - val.hour = tiny_gps.time.hour(); val.minute = tiny_gps.time.minute(); val.second = tiny_gps.time.second(); diff --git a/esphome/components/pcf85063/pcf85063.cpp b/esphome/components/pcf85063/pcf85063.cpp index 03ed78654f..1cf28a4955 100644 --- a/esphome/components/pcf85063/pcf85063.cpp +++ b/esphome/components/pcf85063/pcf85063.cpp @@ -40,11 +40,8 @@ void PCF85063Component::read_time() { .hour = uint8_t(pcf85063_.reg.hour + 10u * pcf85063_.reg.hour_10), .day_of_week = uint8_t(pcf85063_.reg.weekday), .day_of_month = uint8_t(pcf85063_.reg.day + 10u * pcf85063_.reg.day_10), - .day_of_year = 1, // ignored by recalc_timestamp_utc(false) .month = uint8_t(pcf85063_.reg.month + 10u * pcf85063_.reg.month_10), .year = uint16_t(pcf85063_.reg.year + 10u * pcf85063_.reg.year_10 + 2000), - .is_dst = false, // not used - .timestamp = 0, // overwritten by recalc_timestamp_utc(false) }; rtc_time.recalc_timestamp_utc(false); if (!rtc_time.is_valid()) { diff --git a/esphome/components/pcf8563/pcf8563.cpp b/esphome/components/pcf8563/pcf8563.cpp index dc68807aef..b748f0156a 100644 --- a/esphome/components/pcf8563/pcf8563.cpp +++ b/esphome/components/pcf8563/pcf8563.cpp @@ -40,11 +40,8 @@ void PCF8563Component::read_time() { .hour = uint8_t(pcf8563_.reg.hour + 10u * pcf8563_.reg.hour_10), .day_of_week = uint8_t(pcf8563_.reg.weekday), .day_of_month = uint8_t(pcf8563_.reg.day + 10u * pcf8563_.reg.day_10), - .day_of_year = 1, // ignored by recalc_timestamp_utc(false) .month = uint8_t(pcf8563_.reg.month + 10u * pcf8563_.reg.month_10), .year = uint16_t(pcf8563_.reg.year + 10u * pcf8563_.reg.year_10 + 2000), - .is_dst = false, // not used - .timestamp = 0, // overwritten by recalc_timestamp_utc(false) }; rtc_time.recalc_timestamp_utc(false); if (!rtc_time.is_valid()) { diff --git a/esphome/components/rx8130/rx8130.cpp b/esphome/components/rx8130/rx8130.cpp index 07ed7acc56..3b704d2551 100644 --- a/esphome/components/rx8130/rx8130.cpp +++ b/esphome/components/rx8130/rx8130.cpp @@ -77,11 +77,8 @@ void RX8130Component::read_time() { .hour = bcd2dec(date[2] & 0x3f), .day_of_week = static_cast<uint8_t>((date[3] & 0x7f) ? __builtin_ctz(date[3] & 0x7f) + 1 : 1), .day_of_month = bcd2dec(date[4] & 0x3f), - .day_of_year = 1, // ignored by recalc_timestamp_utc(false) .month = bcd2dec(date[5] & 0x1f), .year = static_cast<uint16_t>(bcd2dec(date[6]) + 2000), - .is_dst = false, // not used - .timestamp = 0 // overwritten by recalc_timestamp_utc(false) }; rtc_time.recalc_timestamp_utc(false); if (!rtc_time.is_valid()) { From 7a407595678d7b855fb79f8b2912fc13d1f1aaad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 08:55:12 +0000 Subject: [PATCH 1701/2030] Bump aioesphomeapi from 44.7.0 to 44.8.0 (#15159) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2e09e2ed99..9e75e6d039 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.7.0 +aioesphomeapi==44.8.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From c45c9da771c47dfbdfa966902a60540e778792c8 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:51:23 +1000 Subject: [PATCH 1702/2030] [lvgl] Various 9.5 fixes (#15157) --- esphome/components/lvgl/lvgl_esphome.cpp | 4 +- esphome/components/lvgl/lvgl_esphome.h | 2 +- esphome/components/lvgl/widgets/__init__.py | 2 +- esphome/components/lvgl/widgets/meter.py | 45 +++++++++++++++------ 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index b3cb4d56ad..d26bcdc714 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -673,14 +673,14 @@ void LvglComponent::static_flush_cb(lv_display_t *disp_drv, const lv_area_t *are * @param color_end The color to apply to the last tick * @param width */ -void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, +void lv_scale_draw_event_cb(lv_event_t *e, int16_t range_start, int16_t range_end, lv_color_t color_start, lv_color_t color_end, int width, bool local) { auto *scale = static_cast<lv_obj_t *>(lv_event_get_target(e)); lv_draw_task_t *task = lv_event_get_draw_task(e); if (lv_draw_task_get_type(task) == LV_DRAW_TASK_TYPE_LINE) { auto *line_dsc = static_cast<lv_draw_line_dsc_t *>(lv_draw_task_get_draw_dsc(task)); - auto tick = line_dsc->base.id1; + int tick = line_dsc->base.id2; if (tick >= range_start && tick <= range_end) { unsigned range = range_end - range_start; if (local) { diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 66f823d549..7baeeb233b 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -52,7 +52,7 @@ extern std::string lv_event_code_name_for(lv_event_t *event); lv_obj_t *lv_container_create(lv_obj_t *parent); #ifdef USE_LVGL_SCALE -void lv_scale_draw_event_cb(lv_event_t *e, uint16_t range_start, uint16_t range_end, lv_color_t color_start, +void lv_scale_draw_event_cb(lv_event_t *e, int16_t range_start, int16_t range_end, lv_color_t color_start, lv_color_t color_end, int width, bool local); #endif #if LV_COLOR_DEPTH == 16 diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index a2a8cf2129..b383196963 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -158,7 +158,7 @@ class WidgetType: await self.on_create(var, config) w = Widget.create(wid, var, self, config) - if theme := theme_widget_map.get(self.w_type.name): + if theme := theme_widget_map.get(self.name): for part, states in theme.items(): part = "LV_PART_" + part.upper() for state, style in states.items(): diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 6a7559c42c..d32efd145b 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -79,6 +79,7 @@ from ..types import ( from . import Widget, WidgetType, get_widgets, widget_to_code from .arc import CONF_ARC from .img import CONF_IMAGE +from .label import CONF_LABEL from .line import CONF_LINE CONF_ANGLE_RANGE = "angle_range" @@ -222,12 +223,31 @@ INDICATOR_SCHEMA = cv.Schema( } ) + +def _scale_validate(config): + if indicators := config.get(CONF_INDICATORS): + style_index = next( + ( + i + for i, indicator in enumerate(indicators) + if CONF_TICK_STYLE in indicator + ), + -1, + ) + if style_index >= 0 and CONF_TICKS not in config: + raise cv.Invalid( + "'tick_style' can't be applied if the enclosing scale has no 'ticks' configured", + path=[CONF_INDICATORS, style_index], + ) + return config + + SCALE_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(lv_scale_t), cv.Optional(CONF_TICKS): cv.Schema( { - cv.Optional(CONF_COUNT, default=12): cv.positive_int, + cv.Optional(CONF_COUNT, default=12): cv.int_range(min=2), cv.Optional(CONF_WIDTH, default=2): cv.positive_int, cv.Optional(CONF_LENGTH, default=10): size, cv.Optional(CONF_RADIAL_OFFSET, default=0): size, @@ -251,7 +271,7 @@ SCALE_SCHEMA = cv.Schema( cv.Optional(CONF_INDICATORS): cv.ensure_list(INDICATOR_SCHEMA), cv.Optional(CONF_DRAW_TICKS_ON_TOP, default=True): bool, } -) +).add_extra(_scale_validate) METER_SCHEMA = { cv.Optional(CONF_PIVOT): STATE_SCHEMA, @@ -259,17 +279,14 @@ METER_SCHEMA = { cv.Optional(CONF_SCALES): cv.ensure_list(SCALE_SCHEMA), } +# Only handling light style at the moment LIGHT_STYLE = LVStyle( "lv_meter_light", { "bg_opa": 1.0, - "bg_color": 0xEEEEEE, - "line_width": 1, - "line_color": 0xEEEEEE, - "arc_width": 2, - "arc_color": 0xEEEEEE, + "bg_color": 0xFFFFFF, "pad_all": 10, - "border_width": 2, + "border_width": 3, "border_color": 0xEEEEEE, "radius": "LV_RADIUS_CIRCLE", }, @@ -329,7 +346,7 @@ class MeterType(WidgetType): ) def get_uses(self): - return CONF_SCALE, CONF_LINE, CONF_IMAGE + return CONF_SCALE, CONF_LINE, CONF_IMAGE, CONF_LABEL def validate(self, value): return cv.has_at_most_one_key(CONF_INDICATOR, CONF_PIVOT)(value) @@ -478,6 +495,8 @@ class MeterType(WidgetType): await iw.set_property(CONF_SRC, await lv_image.process(src)) await set_indicator_values(iw, v) + # Hide the scale line + lv.obj_set_style_arc_opa(scale_var, LV_OPA.TRANSP, LV_PART.MAIN) if ticks := scale_conf.get(CONF_TICKS): # Set total tick count lv.scale_set_total_tick_count(scale_var, ticks[CONF_COUNT]) @@ -503,8 +522,6 @@ class MeterType(WidgetType): LV_PART.ITEMS, ) - # Hide the scale line - lv.obj_set_style_arc_opa(scale_var, LV_OPA.TRANSP, LV_PART.MAIN) if CONF_MAJOR in ticks: major = ticks[CONF_MAJOR] # Set major tick frequency @@ -547,7 +564,11 @@ class MeterType(WidgetType): else: lv.scale_set_major_tick_every(scale_var, 0) else: - lv.scale_set_total_tick_count(scale_var, 0) + # Must have at least 2 ticks otherwise the scale isn't even drawn + lv.scale_set_total_tick_count(scale_var, 2) + # Hide the ticks by making them 0 width + lv_obj.set_style_line_width(scale_var, 0, LV_PART.ITEMS) + lv.scale_set_major_tick_every(scale_var, 0) # Add a pivot # Get the default style From f5bbff0b05a677e7aa0d28218291a8b868c0fb39 Mon Sep 17 00:00:00 2001 From: Piotr Szulc <piotr.szulc@gmail.com> Date: Wed, 25 Mar 2026 12:40:39 +0100 Subject: [PATCH 1703/2030] [core] Add CONF_LIBRETINY constant to const.py (#15141) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/const/__init__.py | 1 + esphome/components/libretiny/const.py | 1 - esphome/components/libretiny/text_sensor.py | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index 2a972a2939..1fbf88c276 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -13,6 +13,7 @@ CONF_DATA_BITS = "data_bits" CONF_DRAW_ROUNDING = "draw_rounding" CONF_ENABLED = "enabled" CONF_IGNORE_NOT_FOUND = "ignore_not_found" +CONF_LIBRETINY = "libretiny" CONF_ON_PACKET = "on_packet" CONF_ON_RECEIVE = "on_receive" CONF_ON_STATE_CHANGE = "on_state_change" diff --git a/esphome/components/libretiny/const.py b/esphome/components/libretiny/const.py index bc4ca99ab4..332be0de1d 100644 --- a/esphome/components/libretiny/const.py +++ b/esphome/components/libretiny/const.py @@ -14,7 +14,6 @@ class LibreTinyComponent: supports_atomics: bool = False # True for Cortex-M4(F) with LDREX/STREX -CONF_LIBRETINY = "libretiny" CONF_LOGLEVEL = "loglevel" CONF_SDK_SILENT = "sdk_silent" CONF_GPIO_RECOVER = "gpio_recover" diff --git a/esphome/components/libretiny/text_sensor.py b/esphome/components/libretiny/text_sensor.py index fa33fb6c02..c1012774c8 100644 --- a/esphome/components/libretiny/text_sensor.py +++ b/esphome/components/libretiny/text_sensor.py @@ -1,5 +1,6 @@ import esphome.codegen as cg from esphome.components import text_sensor +from esphome.components.const import CONF_LIBRETINY import esphome.config_validation as cv from esphome.const import ( CONF_VERSION, @@ -7,7 +8,7 @@ from esphome.const import ( ICON_CELLPHONE_ARROW_DOWN, ) -from .const import CONF_LIBRETINY, LTComponent +from .const import LTComponent DEPENDENCIES = ["libretiny"] From 2355fcb44e0804b68d2892fbe49f574baf9a7a6a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 25 Mar 2026 23:51:51 +1000 Subject: [PATCH 1704/2030] [lvgl] Update function and type names (#15109) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/lvgl/gradient.py | 2 +- esphome/components/lvgl/hello_world.yaml | 6 ++-- esphome/components/lvgl/lvgl_esphome.cpp | 10 +++---- esphome/components/lvgl/lvgl_esphome.h | 8 +++--- esphome/components/lvgl/schemas.py | 12 ++++++-- esphome/components/lvgl/trigger.py | 2 +- esphome/components/lvgl/types.py | 3 +- esphome/components/lvgl/widgets/canvas.py | 4 ++- esphome/components/lvgl/widgets/img.py | 4 +-- esphome/components/lvgl/widgets/meter.py | 4 +-- esphome/components/lvgl/widgets/tileview.py | 8 +++--- tests/components/lvgl/lvgl-package.yaml | 31 ++++++++------------- 12 files changed, 47 insertions(+), 47 deletions(-) diff --git a/esphome/components/lvgl/gradient.py b/esphome/components/lvgl/gradient.py index f3ded6a518..c4a3c8f2cb 100644 --- a/esphome/components/lvgl/gradient.py +++ b/esphome/components/lvgl/gradient.py @@ -31,7 +31,7 @@ GRADIENT_SCHEMA = cv.ensure_list( cv.Required(CONF_DIRECTION): cv.one_of( "HOR", "HORIZONTAL", "VER", "VERTICAL", upper=True ), - cv.Optional(CONF_DITHER, default="NONE"): LV_DITHER.one_of, + cv.Optional(CONF_DITHER): LV_DITHER.one_of, cv.Required(CONF_STOPS): cv.All( [ cv.Schema( diff --git a/esphome/components/lvgl/hello_world.yaml b/esphome/components/lvgl/hello_world.yaml index 359e73cd52..4af179a589 100644 --- a/esphome/components/lvgl/hello_world.yaml +++ b/esphome/components/lvgl/hello_world.yaml @@ -43,14 +43,14 @@ on_boot: lvgl.widget.refresh: hello_world_title_ hidden: !lambda |- - return lv_obj_get_width(lv_scr_act()) < 400; + return lv_obj_get_width(lv_screen_active()) < 400; - checkbox: text: Checkbox id: hello_world_checkbox_ on_boot: lvgl.widget.refresh: hello_world_checkbox_ hidden: !lambda |- - return lv_obj_get_width(lv_scr_act()) < 240; + return lv_obj_get_width(lv_screen_active()) < 240; on_click: lvgl.label.update: id: hello_world_label_ @@ -94,7 +94,7 @@ outline_width: 0 border_width: 0 hidden: !lambda |- - return lv_obj_get_width(lv_scr_act()) < 300 && lv_obj_get_height(lv_scr_act()) < 400; + return lv_obj_get_width(lv_screen_active()) < 300 && lv_obj_get_height(lv_screen_active()) < 400; widgets: - label: text_font: montserrat_14 diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index d26bcdc714..bf86a4e9ee 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -172,18 +172,18 @@ void LvglComponent::add_page(LvPageType *page) { page->setup(this->pages_.size() - 1); } -void LvglComponent::show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time) { +void LvglComponent::show_page(size_t index, lv_screen_load_anim_t anim, uint32_t time) { if (index >= this->pages_.size()) return; this->current_page_ = index; if (anim == LV_SCREEN_LOAD_ANIM_NONE) { - lv_scr_load(this->pages_[this->current_page_]->obj); + lv_screen_load(this->pages_[this->current_page_]->obj); } else { - lv_scr_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false); + lv_screen_load_anim(this->pages_[this->current_page_]->obj, anim, time, 0, false); } } -void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) { +void LvglComponent::show_next_page(lv_screen_load_anim_t anim, uint32_t time) { if (this->pages_.empty() || (this->current_page_ == this->pages_.size() - 1 && !this->page_wrap_)) return; size_t start = this->current_page_; @@ -195,7 +195,7 @@ void LvglComponent::show_next_page(lv_scr_load_anim_t anim, uint32_t time) { this->show_page(this->current_page_, anim, time); } -void LvglComponent::show_prev_page(lv_scr_load_anim_t anim, uint32_t time) { +void LvglComponent::show_prev_page(lv_screen_load_anim_t anim, uint32_t time) { if (this->pages_.empty() || (this->current_page_ == 0 && !this->page_wrap_)) return; size_t start = this->current_page_; diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 7baeeb233b..8de82d50c0 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -163,7 +163,7 @@ class LvglComponent : public PollingComponent { static void render_end_cb(lv_event_t *event); static void render_start_cb(lv_event_t *event); void dump_config() override; - lv_disp_t *get_disp() { return this->disp_; } + lv_display_t *get_disp() { return this->disp_; } lv_obj_t *get_screen_active() { return lv_display_get_screen_active(this->disp_); } // Pause or resume the display. // @param paused If true, pause the display. If false, resume the display. @@ -189,9 +189,9 @@ class LvglComponent : public PollingComponent { lv_event_code_t event3); void add_page(LvPageType *page); - void show_page(size_t index, lv_scr_load_anim_t anim, uint32_t time); - void show_next_page(lv_scr_load_anim_t anim, uint32_t time); - void show_prev_page(lv_scr_load_anim_t anim, uint32_t time); + void show_page(size_t index, lv_screen_load_anim_t anim, uint32_t time); + void show_next_page(lv_screen_load_anim_t anim, uint32_t time); + void show_prev_page(lv_screen_load_anim_t anim, uint32_t time); void set_page_wrap(bool wrap) { this->page_wrap_ = wrap; } void set_big_endian(bool big_endian) { this->big_endian_ = big_endian; } size_t get_current_page() const; diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 4e2bfeae85..bcbb193ce3 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -250,9 +250,17 @@ STYLE_REMAP = { } -def remap_property(prop): +def remap_property(prop, record=True): + """ + Remap an old style property to new style property. + Optionally record the use of the deprecated property. + :param prop: Name of the style property to remap. + :param record: Whether to record the use of the deprecated property. + :return: The remapped property name, or ``prop`` if no remapping exists. + """ if prop in STYLE_REMAP: - get_remapped_uses().add(prop) + if record: + get_remapped_uses().add(prop) return STYLE_REMAP[prop] return prop diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index c5ad4d402e..077ff06bb7 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -72,7 +72,7 @@ async def generate_triggers(): dir = DIRECTIONS.mapper(dir) w.clear_flag("LV_OBJ_FLAG_SCROLLABLE") selected = literal( - f"lv_indev_get_gesture_dir(lv_indev_get_act()) == {dir}" + f"lv_indev_get_gesture_dir(lv_indev_active()) == {dir}" ) await add_trigger( conf, w, literal("LV_EVENT_GESTURE"), is_selected=selected diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 03739f3ff1..8343a542a9 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -59,7 +59,6 @@ lv_style_t = cg.global_ns.struct("lv_style_t") lv_pseudo_button_t = lvgl_ns.class_("LvPseudoButton") lv_obj_base_t = cg.global_ns.class_("lv_obj_t", lv_pseudo_button_t) lv_obj_t_ptr = lv_obj_base_t.operator("ptr") -lv_disp_t = cg.global_ns.struct("lv_disp_t") lv_color_t = cg.global_ns.struct("lv_color_t") lv_opa_t = cg.global_ns.struct("lv_opa_t") lv_group_t = cg.global_ns.struct("lv_group_t") @@ -67,7 +66,7 @@ LVTouchListener = lvgl_ns.class_("LVTouchListener") LVEncoderListener = lvgl_ns.class_("LVEncoderListener") lv_obj_t = LvType("lv_obj_t") lv_page_t = LvType("LvPageType", parents=(LvCompound,)) -lv_img_t = LvType("lv_img_t") +lv_image_t = LvType("lv_image_t") lv_gradient_t = LvType("lv_grad_dsc_t") lv_event_t = LvType("lv_event_t") diff --git a/esphome/components/lvgl/widgets/canvas.py b/esphome/components/lvgl/widgets/canvas.py index c670e3732c..0e40d0dfbe 100644 --- a/esphome/components/lvgl/widgets/canvas.py +++ b/esphome/components/lvgl/widgets/canvas.py @@ -369,7 +369,9 @@ def _scale_map(config): def _get_prop_validator(prop): - return STYLE_PROPS.get(f"transform_{remap_property(prop)}") or STYLE_PROPS.get(prop) + return STYLE_PROPS.get( + f"transform_{remap_property(prop, False)}" + ) or STYLE_PROPS.get(prop) def _prop_validator(prop): diff --git a/esphome/components/lvgl/widgets/img.py b/esphome/components/lvgl/widgets/img.py index ed6fd30c09..8a046fea33 100644 --- a/esphome/components/lvgl/widgets/img.py +++ b/esphome/components/lvgl/widgets/img.py @@ -17,7 +17,7 @@ from ..defines import ( CONF_ZOOM, ) from ..lv_validation import lv_angle, lv_bool, lv_image, scale, size -from ..types import lv_img_t +from ..types import lv_image_t from . import Widget, WidgetType from .label import CONF_LABEL @@ -55,7 +55,7 @@ class ImgType(WidgetType): def __init__(self): super().__init__( CONF_IMAGE, - lv_img_t, + lv_image_t, (CONF_MAIN,), IMG_SCHEMA, IMG_MODIFY_SCHEMA, diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index d32efd145b..494f811a8e 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -73,7 +73,7 @@ from ..types import ( LvType, ObjUpdateAction, lv_event_t, - lv_img_t, + lv_image_t, lv_obj_t, ) from . import Widget, WidgetType, get_widgets, widget_to_code @@ -205,7 +205,7 @@ INDICATOR_SCHEMA = cv.Schema( INDICATOR_IMG_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(lv_meter_indicator_image_t), - cv.GenerateID(CONF_IMAGE_ID): cv.declare_id(lv_img_t), + cv.GenerateID(CONF_IMAGE_ID): cv.declare_id(lv_image_t), } ), requires_component("image"), diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index dadaef7d07..8e9d95f349 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -29,7 +29,7 @@ lv_tile_t = LvType("lv_tileview_tile_t") lv_tileview_t = LvType( "lv_tileview_t", largs=[(lv_obj_t_ptr, "tile")], - lvalue=lambda w: w.get_property("tile_act"), + lvalue=lambda w: w.get_property("tile_active"), has_on_value=True, ) @@ -85,7 +85,7 @@ class TileviewType(WidgetType): await add_widgets(tile, tile_conf) if tiles: # Set the first tile as active - lv_obj.set_tile_id( + lv.tileview_set_tile_by_index( w.obj, tiles[0][CONF_COLUMN], tiles[0][CONF_ROW], literal("LV_ANIM_OFF") ) @@ -122,11 +122,11 @@ async def tileview_select(config, action_id, template_arg, args): async def do_select(w: Widget): if tile := config.get(CONF_TILE_ID): tile = await cg.get_variable(tile) - lv_obj.set_tile(w.obj, tile, literal(config[CONF_ANIMATED])) + lv.tileview_set_tile(w.obj, tile, literal(config[CONF_ANIMATED])) else: row = await lv_int.process(config[CONF_ROW]) column = await lv_int.process(config[CONF_COLUMN]) - lv_obj.set_tile_id( + lv.tileview_set_tile_by_index( widgets[0].obj, column, row, literal(config[CONF_ANIMATED]) ) lv.event_send(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 606f57d6a1..b168578a98 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -43,9 +43,6 @@ lvgl: start_value: 0 end_value: 180 bg_color: light_blue - disp_bg_color: color_id - disp_bg_image: cat_image - disp_bg_opa: cover bottom_layer: widgets: - obj: @@ -58,7 +55,6 @@ lvgl: gradients: - id: color_bar direction: hor - # dither: err_diff stops: - color: 0xFF0000 position: 0 @@ -143,12 +139,11 @@ lvgl: body: text: This is a sample messagebox bg_color: 0x808080 - button_style: - bg_color: 0xff00 - border_width: 4 buttons: - id: msgbox_button text: Button + bg_color: 0x00ff00 + border_width: 4 - id: msgbox_apply text: "Close" on_click: @@ -160,8 +155,8 @@ lvgl: bg_opa: !lambda return 0.5; - lvgl.image.update: id: lv_image - zoom: !lambda return 512; - angle: !lambda return 100; + scale: !lambda return 512; + rotation: !lambda return 100; pivot_x: !lambda return 20; pivot_y: !lambda return 20; offset_x: !lambda return 20; @@ -287,8 +282,8 @@ lvgl: then: - lvgl.animimg.stop: anim_img - lvgl.update: - disp_bg_color: 0xffff00 - disp_bg_image: none + bottom_layer: + bg_color: 0xffff00 - lvgl.widget.show: message_box - label: text: "Hello shiny day" @@ -361,8 +356,6 @@ lvgl: pad_right: 10px pad_top: 10px shadow_color: light_blue - shadow_ofs_x: 5 - shadow_ofs_y: 5 shadow_opa: cover shadow_spread: 5 shadow_width: 10 @@ -373,12 +366,10 @@ lvgl: text_letter_space: 4 text_line_space: 4 text_opa: cover - transform_angle: 180 transform_rotation: 90 transform_height: 100 transform_pivot_x: 50% transform_pivot_y: 50% - transform_zoom: 0.5 transform_scale: 2.0 transform_scale_x: 1.5 transform_scale_y: 0.8 @@ -470,11 +461,11 @@ lvgl: id: button_button width: 20% height: 10% - transform_angle: !lambda return(180*100); + transform_rotation: !lambda return(180*100); arc_width: !lambda return 4; border_width: !lambda return 6; - shadow_ofs_x: !lambda return 6; - shadow_ofs_y: !lambda return 6; + shadow_offset_x: !lambda return 6; + shadow_offset_y: !lambda return 6; shadow_spread: !lambda return 6; shadow_width: !lambda return 6; pressed: @@ -646,8 +637,8 @@ lvgl: border_opa: 80% shadow_color: black shadow_width: 10 - shadow_ofs_x: 5 - shadow_ofs_y: 5 + shadow_offset_x: 5 + shadow_offset_y: 5 shadow_spread: 4 shadow_opa: cover outline_color: red From 6c981e83db9186381742618e5c5bf17f9da689e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brandon=20der=20Bl=C3=A4tter?= <intcreator@users.noreply.github.com> Date: Wed, 25 Mar 2026 06:52:50 -0700 Subject: [PATCH 1705/2030] [hub75] Add SCAN_1_8_32PX_FULL wiring option (#15130) --- esphome/components/hub75/display.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/hub75/display.py b/esphome/components/hub75/display.py index ede5078c33..0d1b87941d 100644 --- a/esphome/components/hub75/display.py +++ b/esphome/components/hub75/display.py @@ -128,6 +128,7 @@ SCAN_WIRINGS = { "STANDARD_TWO_SCAN": Hub75ScanWiring.STANDARD_TWO_SCAN, "SCAN_1_4_16PX_HIGH": Hub75ScanWiring.SCAN_1_4_16PX_HIGH, "SCAN_1_8_32PX_HIGH": Hub75ScanWiring.SCAN_1_8_32PX_HIGH, + "SCAN_1_8_32PX_FULL": Hub75ScanWiring.SCAN_1_8_32PX_FULL, "SCAN_1_8_40PX_HIGH": Hub75ScanWiring.SCAN_1_8_40PX_HIGH, "SCAN_1_8_64PX_HIGH": Hub75ScanWiring.SCAN_1_8_64PX_HIGH, } From b66ff374a2be7a6ebf4761f8124546c9b14684f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Metrich?= <45318189+FredM67@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:26:33 +0100 Subject: [PATCH 1706/2030] [esp32] Fix GPIO strapping pins and add USB-JTAG warnings (#15105) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/esp32/gpio_esp32_c3.py | 8 ++++++++ esphome/components/esp32/gpio_esp32_c6.py | 10 +++++++++- esphome/components/esp32/gpio_esp32_h2.py | 6 +++--- esphome/components/esp32/gpio_esp32_p4.py | 4 ++-- esphome/components/esp32/gpio_esp32_s3.py | 22 +++++++++++++++------- 5 files changed, 37 insertions(+), 13 deletions(-) diff --git a/esphome/components/esp32/gpio_esp32_c3.py b/esphome/components/esp32/gpio_esp32_c3.py index 93e0b97093..6eb002f3f0 100644 --- a/esphome/components/esp32/gpio_esp32_c3.py +++ b/esphome/components/esp32/gpio_esp32_c3.py @@ -14,6 +14,8 @@ _ESP32C3_SPI_PSRAM_PINS = { 17: "SPIQ", } +_ESP32C3_USB_JTAG_PINS = {18, 19} + _ESP32C3_STRAPPING_PINS = {2, 8, 9} _LOGGER = logging.getLogger(__name__) @@ -26,6 +28,12 @@ def esp32_c3_validate_gpio_pin(value: int) -> int: raise cv.Invalid( f"This pin cannot be used on ESP32-C3s and is already used by the SPI/PSRAM interface (function: {_ESP32C3_SPI_PSRAM_PINS[value]})" ) + if value in _ESP32C3_USB_JTAG_PINS: + _LOGGER.warning( + "GPIO%d is used by the USB-Serial-JTAG interface." + " Using this pin as GPIO will conflict with USB-Serial-JTAG.", + value, + ) return value diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py index cfd3bca833..993606d9de 100644 --- a/esphome/components/esp32/gpio_esp32_c6.py +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -18,7 +18,9 @@ _ESP32C6_SPI_PSRAM_PINS = { 30: "SPID", } -_ESP32C6_STRAPPING_PINS = {8, 9, 15} +_ESP32C6_USB_JTAG_PINS = {12, 13} + +_ESP32C6_STRAPPING_PINS = {4, 5, 8, 9, 15} _LOGGER = logging.getLogger(__name__) @@ -30,6 +32,12 @@ def esp32_c6_validate_gpio_pin(value: int) -> int: raise cv.Invalid( f"This pin cannot be used on ESP32-C6s and is already used by the SPI/PSRAM interface (function: {_ESP32C6_SPI_PSRAM_PINS[value]})" ) + if value in _ESP32C6_USB_JTAG_PINS: + _LOGGER.warning( + "GPIO%d is used by the USB-Serial-JTAG interface." + " Using this pin as GPIO will conflict with USB-Serial-JTAG.", + value, + ) return value diff --git a/esphome/components/esp32/gpio_esp32_h2.py b/esphome/components/esp32/gpio_esp32_h2.py index 5e7a6158f9..9dd6537694 100644 --- a/esphome/components/esp32/gpio_esp32_h2.py +++ b/esphome/components/esp32/gpio_esp32_h2.py @@ -9,7 +9,7 @@ _ESP32H2_SPI_FLASH_PINS = {6, 7, 15, 16, 17, 18, 19, 20, 21} _ESP32H2_USB_JTAG_PINS = {26, 27} -_ESP32H2_STRAPPING_PINS = {2, 3, 8, 9, 25} +_ESP32H2_STRAPPING_PINS = {8, 9, 25} _LOGGER = logging.getLogger(__name__) @@ -26,8 +26,8 @@ def esp32_h2_validate_gpio_pin(value: int) -> int: ) if value in _ESP32H2_USB_JTAG_PINS: _LOGGER.warning( - "GPIO%d is reserved for the USB-Serial-JTAG interface.\n" - "To use this pin as GPIO, USB-Serial-JTAG will be disabled.", + "GPIO%d is used by the USB-Serial-JTAG interface." + " Using this pin as GPIO will conflict with USB-Serial-JTAG.", value, ) diff --git a/esphome/components/esp32/gpio_esp32_p4.py b/esphome/components/esp32/gpio_esp32_p4.py index 865db92652..6e9227c501 100644 --- a/esphome/components/esp32/gpio_esp32_p4.py +++ b/esphome/components/esp32/gpio_esp32_p4.py @@ -20,8 +20,8 @@ def esp32_p4_validate_gpio_pin(value: int) -> int: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-54)") if value in _ESP32P4_USB_JTAG_PINS: _LOGGER.warning( - "GPIO%d is reserved for the USB-Serial-JTAG interface.\n" - "To use this pin as GPIO, USB-Serial-JTAG will be disabled.", + "GPIO%d is used by the USB-Serial-JTAG interface." + " Using this pin as GPIO will conflict with USB-Serial-JTAG.", value, ) diff --git a/esphome/components/esp32/gpio_esp32_s3.py b/esphome/components/esp32/gpio_esp32_s3.py index cb0eb8178c..f528de4ccd 100644 --- a/esphome/components/esp32/gpio_esp32_s3.py +++ b/esphome/components/esp32/gpio_esp32_s3.py @@ -5,7 +5,7 @@ import esphome.config_validation as cv from esphome.const import CONF_INPUT, CONF_MODE, CONF_NUMBER from esphome.pins import check_strapping_pin -_ESP_32S3_SPI_PSRAM_PINS = { +_ESP32S3_SPI_PSRAM_PINS = { 26: "SPICS1", 27: "SPIHD", 28: "SPIWP", @@ -15,7 +15,7 @@ _ESP_32S3_SPI_PSRAM_PINS = { 32: "SPID", } -_ESP_32_ESP32_S3R8_PSRAM_PINS = { +_ESP32S3R8_PSRAM_PINS = { 33: "SPIIO4", 34: "SPIIO5", 35: "SPIIO6", @@ -23,7 +23,9 @@ _ESP_32_ESP32_S3R8_PSRAM_PINS = { 37: "SPIDQS", } -_ESP_32S3_STRAPPING_PINS = {0, 3, 45, 46} +_ESP32S3_USB_JTAG_PINS = {19, 20} + +_ESP32S3_STRAPPING_PINS = {0, 3, 45, 46} _LOGGER = logging.getLogger(__name__) @@ -32,11 +34,11 @@ def esp32_s3_validate_gpio_pin(value: int) -> int: if value < 0 or value > 48: raise cv.Invalid(f"Invalid pin number: {value} (must be 0-48)") - if value in _ESP_32S3_SPI_PSRAM_PINS: + if value in _ESP32S3_SPI_PSRAM_PINS: raise cv.Invalid( - f"This pin cannot be used on ESP32-S3s and is already used by the SPI/PSRAM interface(function: {_ESP_32S3_SPI_PSRAM_PINS[value]})" + f"This pin cannot be used on ESP32-S3s and is already used by the SPI/PSRAM interface(function: {_ESP32S3_SPI_PSRAM_PINS[value]})" ) - if value in _ESP_32_ESP32_S3R8_PSRAM_PINS: + if value in _ESP32S3R8_PSRAM_PINS: _LOGGER.warning( "GPIO%d is used by the PSRAM interface on ESP32-S3R8 / ESP32-S3R8V and should be avoided on these models", value, @@ -46,6 +48,12 @@ def esp32_s3_validate_gpio_pin(value: int) -> int: # These pins are not exposed in GPIO mux (reason unknown) # but they're missing from IO_MUX list in datasheet raise cv.Invalid(f"The pin GPIO{value} is not usable on ESP32-S3s.") + if value in _ESP32S3_USB_JTAG_PINS: + _LOGGER.warning( + "GPIO%d is used by the USB-Serial-JTAG interface." + " Using this pin as GPIO will conflict with USB-Serial-JTAG.", + value, + ) return value @@ -61,5 +69,5 @@ def esp32_s3_validate_supports(value: dict[str, Any]) -> dict[str, Any]: # All ESP32 pins support input mode pass - check_strapping_pin(value, _ESP_32S3_STRAPPING_PINS, _LOGGER) + check_strapping_pin(value, _ESP32S3_STRAPPING_PINS, _LOGGER) return value From e0d8000007beb22f66fb093399379de8f592075c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 26 Mar 2026 00:34:34 +1000 Subject: [PATCH 1707/2030] [ai] Add instructions regarding constructor parameters (#15091) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .ai/instructions.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.ai/instructions.md b/.ai/instructions.md index 240a47a52f..a7e08f9c4d 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -124,6 +124,28 @@ This document provides essential context for AI models interacting with this pro * **Indentation:** Use spaces (two per indentation level), not tabs * **Type aliases:** Prefer `using type_t = int;` over `typedef int type_t;` * **Line length:** Wrap lines at no more than 120 characters + * **Constructor parameters vs setters:** Component properties that are both **required** and **invariant** + (never change after construction) should be constructor parameters rather than set via setter methods. + This makes the dependency explicit and prevents use of the object in an incompletely-initialized state. + In code generation, when calling `cg.new_Pvariable()` or the relevant helper function to create the component, pass these as arguments. + ```cpp + // Good - required invariant dependency as constructor parameter + class SourceTextSensor : public text_sensor::TextSensor, public Component { + public: + explicit SourceTextSensor(text::Text *source) : source_(source) {} + protected: + text::Text *source_; + }; + ``` + ```cpp + // Bad - required invariant dependency as setter + class SourceTextSensor : public text_sensor::TextSensor, public Component { + public: + void set_source(text::Text *source) { this->source_ = source; } + protected: + text::Text *source_{nullptr}; + }; + ``` * **Component Structure:** * **Standard Files:** From 5d67868ac6d72159b40f080f556bc8534a1831e9 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:39:46 +0100 Subject: [PATCH 1708/2030] [nextion] Fix inline doc parameter types for page and touch callbacks (#14972) --- esphome/components/nextion/nextion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 2842e57ce8..bb5998cf5d 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1160,13 +1160,13 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe /** Add a callback to be notified when the nextion changes pages. * - * @param callback The void(std::string) callback. + * @param callback The void(uint8_t) callback. */ template<typename F> void add_new_page_callback(F &&callback) { this->page_callback_.add(std::forward<F>(callback)); } /** Add a callback to be notified when Nextion has a touch event. * - * @param callback The void() callback. + * @param callback The void(uint8_t, uint8_t, bool) callback. */ template<typename F> void add_touch_event_callback(F &&callback) { this->touch_callback_.add(std::forward<F>(callback)); From a15389318f41373a4c4466c69056cff9f6466e4b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:57:33 -0400 Subject: [PATCH 1709/2030] [audio] Bump esp-audio-libs to 2.0.4 (#15164) --- esphome/components/audio/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index 9cc80b9b33..acc3b5d351 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -204,7 +204,7 @@ async def to_code(config): add_idf_component( name="esphome/esp-audio-libs", - ref="2.0.3", + ref="2.0.4", ) data = _get_data() diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 4148147a3b..c44853969e 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -2,7 +2,7 @@ dependencies: bblanchon/arduinojson: version: "7.4.2" esphome/esp-audio-libs: - version: 2.0.3 + version: 2.0.4 esphome/micro-opus: version: 0.3.6 espressif/esp-dsp: From 010516aef2f1a155f569fe51a8437e6a48a2f876 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Mar 2026 07:33:17 -1000 Subject: [PATCH 1710/2030] [benchmark] Add sensor publish_state benchmarks (#15034) --- .../sensor/bench_sensor_publish.cpp | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/benchmarks/components/sensor/bench_sensor_publish.cpp diff --git a/tests/benchmarks/components/sensor/bench_sensor_publish.cpp b/tests/benchmarks/components/sensor/bench_sensor_publish.cpp new file mode 100644 index 0000000000..9639191a4d --- /dev/null +++ b/tests/benchmarks/components/sensor/bench_sensor_publish.cpp @@ -0,0 +1,79 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/sensor/sensor.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +// Without this, the ~60ns per-iteration valgrind start/stop cost dominates +// sub-microsecond benchmarks. +static constexpr int kInnerIterations = 2000; + +// Test subclass to access protected configure_entity_() for benchmark setup. +class TestSensor : public sensor::Sensor { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } +}; + +// --- Sensor::publish_state() with no callbacks registered --- +// Measures baseline publish overhead: state assignment, logging, +// internal_send_state_to_frontend, ControllerRegistry notification. + +static void SensorPublish_NoCallbacks(benchmark::State &state) { + TestSensor sensor; + sensor.configure("test_sensor"); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(static_cast<float>(i)); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorPublish_NoCallbacks); + +// --- Sensor::publish_state() with one state callback --- +// Measures callback dispatch overhead through LazyCallbackManager. + +static void SensorPublish_WithCallback(benchmark::State &state) { + TestSensor sensor; + sensor.configure("test_sensor"); + + float callback_value = 0.0f; + sensor.add_on_state_callback([&callback_value](float value) { callback_value = value; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(static_cast<float>(i)); + } + benchmark::DoNotOptimize(callback_value); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorPublish_WithCallback); + +// --- Sensor::publish_state() with the same value every time --- +// Steady-state pattern: sensor reports an unchanged reading. +// Sensor doesn't dedup today, so this exercises the same code path +// as changing values, but tracks the common real-world pattern +// separately for regression detection. + +static void SensorPublish_SameValue(benchmark::State &state) { + TestSensor sensor; + sensor.configure("test_sensor"); + + // Warm up so has_state is already set + sensor.publish_state(23.5f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(23.5f); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SensorPublish_SameValue); + +} // namespace esphome::benchmarks From a22d47c71924c2e6355d12cc014a134619e0e536 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Mar 2026 07:36:53 -1000 Subject: [PATCH 1711/2030] [api] Add --no-states flag to esphome logs command (#15160) --- esphome/__main__.py | 11 +++++++- esphome/components/api/client.py | 18 +++++++++--- tests/unit_tests/test_main.py | 47 ++++++++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 4b0fc2cec7..87abd7f796 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1046,7 +1046,11 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int ): from esphome.components.api.client import run_logs - return run_logs(config, network_devices) + return run_logs( + config, + network_devices, + subscribe_states=not getattr(args, "no_states", False), + ) if port_type in (PortType.NETWORK, PortType.MQTT) and has_mqtt_logging(): from esphome import mqtt @@ -1664,6 +1668,11 @@ def parse_args(argv): help="Reset the device before starting serial logs.", default=os.getenv("ESPHOME_SERIAL_LOGGING_RESET"), ) + parser_logs.add_argument( + "--no-states", + action="store_true", + help="Do not show entity state changes in log output.", + ) parser_discover = subparsers.add_parser( "discover", diff --git a/esphome/components/api/client.py b/esphome/components/api/client.py index 0e71ad8fcb..0c6c569c7d 100644 --- a/esphome/components/api/client.py +++ b/esphome/components/api/client.py @@ -32,7 +32,11 @@ if TYPE_CHECKING: _LOGGER = logging.getLogger(__name__) -async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: +async def async_run_logs( + config: dict[str, Any], + addresses: list[str], + subscribe_states: bool = True, +) -> None: """Run the logs command in the event loop.""" conf = config["api"] name = config["esphome"]["name"] @@ -89,14 +93,20 @@ async def async_run_logs(config: dict[str, Any], addresses: list[str]) -> None: config, raw_line, backtrace_state=backtrace_state ) - stop = await async_run(cli, on_log, name=name) + stop = await async_run(cli, on_log, name=name, subscribe_states=subscribe_states) try: await asyncio.Event().wait() finally: await stop() -def run_logs(config: dict[str, Any], addresses: list[str]) -> None: +def run_logs( + config: dict[str, Any], + addresses: list[str], + subscribe_states: bool = True, +) -> None: """Run the logs command.""" with contextlib.suppress(KeyboardInterrupt): - asyncio.run(async_run_logs(config, addresses)) + asyncio.run( + async_run_logs(config, addresses, subscribe_states=subscribe_states) + ) diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 5e36c06bb3..115ce38c93 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -1762,7 +1762,34 @@ def test_show_logs_api( assert result == 0 mock_run_logs.assert_called_once_with( - CORE.config, ["192.168.1.100", "192.168.1.101"] + CORE.config, ["192.168.1.100", "192.168.1.101"], subscribe_states=True + ) + + +@patch("esphome.components.api.client.run_logs") +def test_show_logs_api_no_states( + mock_run_logs: Mock, +) -> None: + """Test show_logs with --no-states flag.""" + setup_core( + config={ + "logger": {}, + CONF_API: {}, + CONF_MDNS: {CONF_DISABLED: False}, + }, + platform=PLATFORM_ESP32, + ) + mock_run_logs.return_value = 0 + + args = MockArgs() + args.no_states = True + devices = ["192.168.1.100"] + + result = show_logs(CORE.config, args, devices) + + assert result == 0 + mock_run_logs.assert_called_once_with( + CORE.config, ["192.168.1.100"], subscribe_states=False ) @@ -1788,7 +1815,9 @@ def test_show_logs_api_with_fqdn_mdns_disabled( assert result == 0 # Should use the FQDN directly, not try MQTT lookup - mock_run_logs.assert_called_once_with(CORE.config, ["device.example.com"]) + mock_run_logs.assert_called_once_with( + CORE.config, ["device.example.com"], subscribe_states=True + ) @patch("esphome.components.api.client.run_logs") @@ -1816,7 +1845,9 @@ def test_show_logs_api_with_mqtt_fallback( assert result == 0 mock_mqtt_get_ip.assert_called_once_with(CORE.config, "user", "pass", "client") - mock_run_logs.assert_called_once_with(CORE.config, ["192.168.1.200"]) + mock_run_logs.assert_called_once_with( + CORE.config, ["192.168.1.200"], subscribe_states=True + ) @patch("esphome.mqtt.show_logs") @@ -2746,7 +2777,7 @@ def test_show_logs_api_static_ip_with_mqttip( # Verify run_logs was called with both IPs mock_run_logs.assert_called_once_with( - CORE.config, ["192.168.1.100", "192.168.2.50"] + CORE.config, ["192.168.1.100", "192.168.2.50"], subscribe_states=True ) @@ -2782,7 +2813,9 @@ def test_show_logs_api_multiple_mqttip_resolves_once( # Note: "MQTT" is a different magic string from "MQTTIP", but both trigger MQTT resolution # The _resolve_network_devices helper filters out both after first resolution mock_run_logs.assert_called_once_with( - CORE.config, ["192.168.2.50", "192.168.2.51", "192.168.1.100"] + CORE.config, + ["192.168.2.50", "192.168.2.51", "192.168.1.100"], + subscribe_states=True, ) @@ -2862,7 +2895,9 @@ def test_show_logs_api_mqtt_timeout_fallback( mock_mqtt_get_ip.assert_called_once_with(CORE.config, "user", "pass", "client") # Verify run_logs was called with only the static IP (MQTT failed) - mock_run_logs.assert_called_once_with(CORE.config, ["192.168.1.100"]) + mock_run_logs.assert_called_once_with( + CORE.config, ["192.168.1.100"], subscribe_states=True + ) def test_detect_external_components_no_external( From 65d0a91fcc0ad85de3d7a1792ad95a0e8c8977ec Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 25 Mar 2026 19:01:52 +0100 Subject: [PATCH 1712/2030] [nextion] Add defined keys to `defines.h` (#14971) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 8 ++--- esphome/core/defines.h | 7 ++++ tests/components/nextion/common.yaml | 47 ++++++++++++++++---------- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 85da6af48a..ac17e14312 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -50,10 +50,10 @@ bool Nextion::check_connect_() { return true; #ifdef USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE - ESP_LOGW(TAG, "Connected (no handshake)"); // Log the connection status without handshake - this->is_connected_ = true; // Set the connection status to true - return true; // Return true indicating the connection is set -#else // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE + ESP_LOGW(TAG, "Connected (no handshake)"); // Log the connection status without handshake + this->connection_state_.is_connected_ = true; // Set the connection status to true + return true; // Return true indicating the connection is set +#else // USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE if (this->comok_sent_ == 0) { this->reset_(false); diff --git a/esphome/core/defines.h b/esphome/core/defines.h index b5612a1d3f..8cf331c4d6 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -115,6 +115,13 @@ #define SNTP_SERVER_COUNT 3 #define USE_MEDIA_PLAYER #define USE_MEDIA_SOURCE +#define USE_NEXTION_COMMAND_SPACING +#define USE_NEXTION_CONF_START_UP_PAGE +#define USE_NEXTION_CONFIG_DUMP_DEVICE_INFO +#define USE_NEXTION_CONFIG_EXIT_REPARSE_ON_START +#define USE_NEXTION_CONFIG_SKIP_CONNECTION_HANDSHAKE +#define USE_NEXTION_MAX_COMMANDS_PER_LOOP +#define USE_NEXTION_MAX_QUEUE_SIZE #define USE_NEXTION_TFT_UPLOAD #define USE_NUMBER #define USE_OUTPUT diff --git a/tests/components/nextion/common.yaml b/tests/components/nextion/common.yaml index 4373fe5462..d9493db50c 100644 --- a/tests/components/nextion/common.yaml +++ b/tests/components/nextion/common.yaml @@ -273,26 +273,39 @@ text_sensor: display: - platform: nextion id: main_lcd + auto_wake_on_touch: true + brightness: 80% + command_spacing: 5ms + dump_device_info: true + exit_reparse_on_start: true + lambda: |- + ESP_LOGD("display","Display is being tested!"); max_commands_per_loop: 20 + max_queue_age: 5000ms # Remove queue items after 5s max_queue_size: 50 - update_interval: 5s - on_sleep: - then: - lambda: 'ESP_LOGD("display","Display went to sleep");' - on_wake: - then: - lambda: 'ESP_LOGD("display","Display woke up");' - on_setup: - then: - lambda: 'ESP_LOGD("display","Display setup completed");' - on_page: - then: - lambda: 'ESP_LOGD("display","Display shows new page %u", x);' on_buffer_overflow: then: logger.log: "Nextion reported a buffer overflow!" - - command_spacing: 5ms - dump_device_info: true - max_queue_age: 5000ms # Remove queue items after 5s + on_page: + then: + lambda: 'ESP_LOGD("display","Display shows new page %u", x);' + on_setup: + then: + lambda: 'ESP_LOGD("display","Display setup completed");' + on_sleep: + then: + lambda: 'ESP_LOGD("display","Display went to sleep");' + on_touch: + then: + lambda: |- + ESP_LOGD("display", + "Display was touched at page %u, component %u, touch event: %s", + page_id, component_id, touch_event ? "press" : "release"); + on_wake: + then: + lambda: 'ESP_LOGD("display","Display woke up");' + update_interval: 5s + start_up_page: 1 startup_override_ms: 10000ms # Wait 10s for display ready + touch_sleep_timeout: 3 + wake_up_page: 2 From c42c6745b960b989e3373a7bedc663b6360d57f5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:06:48 -0400 Subject: [PATCH 1713/2030] [mcp9600] Fix setup success check using OR instead of AND (#15165) --- esphome/components/mcp9600/mcp9600.cpp | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/esphome/components/mcp9600/mcp9600.cpp b/esphome/components/mcp9600/mcp9600.cpp index ff411bef7a..0c5362b4ba 100644 --- a/esphome/components/mcp9600/mcp9600.cpp +++ b/esphome/components/mcp9600/mcp9600.cpp @@ -40,20 +40,20 @@ void MCP9600Component::setup() { } bool success = this->write_byte(MCP9600_REGISTER_STATUS, 0x00); - success |= this->write_byte(MCP9600_REGISTER_SENSOR_CONFIG, uint8_t(0x00 | thermocouple_type_ << 4)); - success |= this->write_byte(MCP9600_REGISTER_CONFIG, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT1_CONFIG, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT2_CONFIG, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT3_CONFIG, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT4_CONFIG, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT1_HYSTERESIS, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT2_HYSTERESIS, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT3_HYSTERESIS, 0x00); - success |= this->write_byte(MCP9600_REGISTER_ALERT4_HYSTERESIS, 0x00); - success |= this->write_byte_16(MCP9600_REGISTER_ALERT1_LIMIT, 0x0000); - success |= this->write_byte_16(MCP9600_REGISTER_ALERT2_LIMIT, 0x0000); - success |= this->write_byte_16(MCP9600_REGISTER_ALERT3_LIMIT, 0x0000); - success |= this->write_byte_16(MCP9600_REGISTER_ALERT4_LIMIT, 0x0000); + success &= this->write_byte(MCP9600_REGISTER_SENSOR_CONFIG, uint8_t(0x00 | thermocouple_type_ << 4)); + success &= this->write_byte(MCP9600_REGISTER_CONFIG, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT1_CONFIG, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT2_CONFIG, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT3_CONFIG, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT4_CONFIG, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT1_HYSTERESIS, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT2_HYSTERESIS, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT3_HYSTERESIS, 0x00); + success &= this->write_byte(MCP9600_REGISTER_ALERT4_HYSTERESIS, 0x00); + success &= this->write_byte_16(MCP9600_REGISTER_ALERT1_LIMIT, 0x0000); + success &= this->write_byte_16(MCP9600_REGISTER_ALERT2_LIMIT, 0x0000); + success &= this->write_byte_16(MCP9600_REGISTER_ALERT3_LIMIT, 0x0000); + success &= this->write_byte_16(MCP9600_REGISTER_ALERT4_LIMIT, 0x0000); if (!success) { this->error_code_ = FAILED_TO_UPDATE_CONFIGURATION; From 19615f2eaeeb37c5245a7de66abe0965b0e740f8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:10:04 -0400 Subject: [PATCH 1714/2030] [bme68x_bsec2] Fix uninitialized bme68x_conf in measurement duration calculation (#15168) --- esphome/components/bme68x_bsec2/bme68x_bsec2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index ed2ec80896..cf516f6ca6 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -276,8 +276,8 @@ void BME68xBSEC2Component::run_() { } if (this->bsec_settings_.trigger_measurement && this->bsec_settings_.op_mode != BME68X_SLEEP_MODE) { - uint32_t meas_dur = 0; - meas_dur = bme68x_get_meas_dur(this->op_mode_, &bme68x_conf, &this->bme68x_); + bme68x_get_conf(&bme68x_conf, &this->bme68x_); + uint32_t meas_dur = bme68x_get_meas_dur(this->op_mode_, &bme68x_conf, &this->bme68x_); ESP_LOGV(TAG, "Queueing read in %uus", meas_dur); this->trigger_time_ns_ = curr_time_ns; this->set_timeout("read", meas_dur / 1000, [this]() { this->read_(this->trigger_time_ns_); }); From f6c5767a8347ecccb446e4ff60627f18bd354d18 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:10:28 -0400 Subject: [PATCH 1715/2030] [inkplate] Use atomic GPIO write to prevent ISR race (#15166) --- esphome/components/inkplate/inkplate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index 326bdff774..3b4b1a63d5 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -229,7 +229,7 @@ void Inkplate::eink_off_() { this->oe_pin_->digital_write(false); this->gmod_pin_->digital_write(false); - GPIO.out &= ~(this->get_data_pin_mask_() | (1UL << this->cl_pin_->get_pin()) | (1UL << this->le_pin_->get_pin())); + GPIO.out_w1tc = this->get_data_pin_mask_() | (1UL << this->cl_pin_->get_pin()) | (1UL << this->le_pin_->get_pin()); this->ckv_pin_->digital_write(false); this->sph_pin_->digital_write(false); this->spv_pin_->digital_write(false); From d8fbce365aff406360a8ea64e980f25ff510f503 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Mar 2026 09:38:20 -1000 Subject: [PATCH 1716/2030] Bump requests from 2.32.5 to 2.33.0 (#15170) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9e75e6d039..ce735f398a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ freetype-py==2.5.1 jinja2==3.1.6 bleak==2.1.1 smpclient==6.0.0 -requests==2.32.5 +requests==2.33.0 # esp-idf >= 5.0 requires this pyparsing >= 3.0 From ec60da893f6613edceccf6003bc23a3001ed50fe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Mar 2026 09:45:06 -1000 Subject: [PATCH 1717/2030] [core] Move state logging to client-side formatting, console to VERBOSE (#15155) --- .../alarm_control_panel.cpp | 2 +- .../binary_sensor/binary_sensor.cpp | 2 +- esphome/components/climate/climate.cpp | 48 +++++++++---------- esphome/components/cover/cover.cpp | 26 +++++----- esphome/components/datetime/date_entity.cpp | 10 ++-- .../components/datetime/datetime_entity.cpp | 16 +++---- esphome/components/datetime/time_entity.cpp | 10 ++-- esphome/components/event/event.cpp | 2 +- esphome/components/fan/fan.cpp | 22 ++++----- esphome/components/light/light_call.cpp | 24 +++++----- esphome/components/lock/lock.cpp | 6 +-- .../components/media_player/media_player.cpp | 10 ++-- esphome/components/number/number.cpp | 2 +- esphome/components/number/number_call.cpp | 8 ++-- esphome/components/select/select.cpp | 2 +- esphome/components/select/select_call.cpp | 4 +- esphome/components/sensor/sensor.cpp | 2 +- esphome/components/switch/switch.cpp | 2 +- esphome/components/text/text.cpp | 4 +- esphome/components/text/text_call.cpp | 4 +- .../components/text_sensor/text_sensor.cpp | 2 +- esphome/components/update/update_entity.cpp | 14 +++--- esphome/components/valve/valve.cpp | 22 ++++----- .../components/water_heater/water_heater.cpp | 26 +++++----- 24 files changed, 135 insertions(+), 135 deletions(-) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index fb61776532..623241851a 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -31,7 +31,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { this->last_update_ = millis(); if (state != this->current_state_) { auto prev_state = this->current_state_; - ESP_LOGD(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(), + ESP_LOGV(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(), LOG_STR_ARG(alarm_control_panel_state_to_string(state)), LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state))); this->current_state_ = state; diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index c4d3a29a1e..8ace7eafd1 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -45,7 +45,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) { #if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_binary_sensor_update(this); #endif - ESP_LOGD(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); + ESP_LOGV(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state)); return true; } return false; diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 3f44b986dc..5cbe9a5daf 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -46,45 +46,45 @@ constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = { void ClimateCall::perform() { this->parent_->control_callback_.call(*this); - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); this->validate_(); if (this->mode_.has_value()) { const LogString *mode_s = climate_mode_to_string(*this->mode_); - ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(mode_s)); + ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(mode_s)); } if (this->custom_fan_mode_ != nullptr) { this->fan_mode_.reset(); - ESP_LOGD(TAG, " Custom Fan: %s", this->custom_fan_mode_); + ESP_LOGV(TAG, " Custom Fan: %s", this->custom_fan_mode_); } if (this->fan_mode_.has_value()) { this->custom_fan_mode_ = nullptr; const LogString *fan_mode_s = climate_fan_mode_to_string(*this->fan_mode_); - ESP_LOGD(TAG, " Fan: %s", LOG_STR_ARG(fan_mode_s)); + ESP_LOGV(TAG, " Fan: %s", LOG_STR_ARG(fan_mode_s)); } if (this->custom_preset_ != nullptr) { this->preset_.reset(); - ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset_); + ESP_LOGV(TAG, " Custom Preset: %s", this->custom_preset_); } if (this->preset_.has_value()) { this->custom_preset_ = nullptr; const LogString *preset_s = climate_preset_to_string(*this->preset_); - ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(preset_s)); + ESP_LOGV(TAG, " Preset: %s", LOG_STR_ARG(preset_s)); } if (this->swing_mode_.has_value()) { const LogString *swing_mode_s = climate_swing_mode_to_string(*this->swing_mode_); - ESP_LOGD(TAG, " Swing: %s", LOG_STR_ARG(swing_mode_s)); + ESP_LOGV(TAG, " Swing: %s", LOG_STR_ARG(swing_mode_s)); } if (this->target_temperature_.has_value()) { - ESP_LOGD(TAG, " Target Temperature: %.2f", *this->target_temperature_); + ESP_LOGV(TAG, " Target Temperature: %.2f", *this->target_temperature_); } if (this->target_temperature_low_.has_value()) { - ESP_LOGD(TAG, " Target Temperature Low: %.2f", *this->target_temperature_low_); + ESP_LOGV(TAG, " Target Temperature Low: %.2f", *this->target_temperature_low_); } if (this->target_temperature_high_.has_value()) { - ESP_LOGD(TAG, " Target Temperature High: %.2f", *this->target_temperature_high_); + ESP_LOGV(TAG, " Target Temperature High: %.2f", *this->target_temperature_high_); } if (this->target_humidity_.has_value()) { - ESP_LOGD(TAG, " Target Humidity: %.0f", *this->target_humidity_); + ESP_LOGV(TAG, " Target Humidity: %.0f", *this->target_humidity_); } this->parent_->control(*this); } @@ -435,43 +435,43 @@ void Climate::save_state_() { } void Climate::publish_state() { - ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); + ESP_LOGV(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); - ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode))); + ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode))); if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { - ESP_LOGD(TAG, " Action: %s", LOG_STR_ARG(climate_action_to_string(this->action))); + ESP_LOGV(TAG, " Action: %s", LOG_STR_ARG(climate_action_to_string(this->action))); } if (traits.get_supports_fan_modes() && this->fan_mode.has_value()) { - ESP_LOGD(TAG, " Fan Mode: %s", LOG_STR_ARG(climate_fan_mode_to_string(this->fan_mode.value()))); + ESP_LOGV(TAG, " Fan Mode: %s", LOG_STR_ARG(climate_fan_mode_to_string(this->fan_mode.value()))); } if (!traits.get_supported_custom_fan_modes().empty() && this->has_custom_fan_mode()) { - ESP_LOGD(TAG, " Custom Fan Mode: %s", this->custom_fan_mode_); + ESP_LOGV(TAG, " Custom Fan Mode: %s", this->custom_fan_mode_); } if (traits.get_supports_presets() && this->preset.has_value()) { - ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(climate_preset_to_string(this->preset.value()))); + ESP_LOGV(TAG, " Preset: %s", LOG_STR_ARG(climate_preset_to_string(this->preset.value()))); } if (!traits.get_supported_custom_presets().empty() && this->has_custom_preset()) { - ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset_); + ESP_LOGV(TAG, " Custom Preset: %s", this->custom_preset_); } if (traits.get_supports_swing_modes()) { - ESP_LOGD(TAG, " Swing Mode: %s", LOG_STR_ARG(climate_swing_mode_to_string(this->swing_mode))); + ESP_LOGV(TAG, " Swing Mode: %s", LOG_STR_ARG(climate_swing_mode_to_string(this->swing_mode))); } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) { - ESP_LOGD(TAG, " Current Temperature: %.2f°C", this->current_temperature); + ESP_LOGV(TAG, " Current Temperature: %.2f°C", this->current_temperature); } if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { - ESP_LOGD(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low, + ESP_LOGV(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low, this->target_temperature_high); } else { - ESP_LOGD(TAG, " Target Temperature: %.2f°C", this->target_temperature); + ESP_LOGV(TAG, " Target Temperature: %.2f°C", this->target_temperature); } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY)) { - ESP_LOGD(TAG, " Current Humidity: %.0f%%", this->current_humidity); + ESP_LOGV(TAG, " Current Humidity: %.0f%%", this->current_humidity); } if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) { - ESP_LOGD(TAG, " Target Humidity: %.0f%%", this->target_humidity); + ESP_LOGV(TAG, " Target Humidity: %.0f%%", this->target_humidity); } // Send state to frontend diff --git a/esphome/components/cover/cover.cpp b/esphome/components/cover/cover.cpp index bb5965d861..e98a555fe5 100644 --- a/esphome/components/cover/cover.cpp +++ b/esphome/components/cover/cover.cpp @@ -68,24 +68,24 @@ CoverCall &CoverCall::set_tilt(float tilt) { return *this; } void CoverCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); auto traits = this->parent_->get_traits(); this->validate_(); if (this->stop_) { - ESP_LOGD(TAG, " Command: STOP"); + ESP_LOGV(TAG, " Command: STOP"); } if (this->position_.has_value()) { if (traits.get_supports_position()) { - ESP_LOGD(TAG, " Position: %.0f%%", *this->position_ * 100.0f); + ESP_LOGV(TAG, " Position: %.0f%%", *this->position_ * 100.0f); } else { - ESP_LOGD(TAG, " Command: %s", LOG_STR_ARG(cover_command_to_str(*this->position_))); + ESP_LOGV(TAG, " Command: %s", LOG_STR_ARG(cover_command_to_str(*this->position_))); } } if (this->tilt_.has_value()) { - ESP_LOGD(TAG, " Tilt: %.0f%%", *this->tilt_ * 100.0f); + ESP_LOGV(TAG, " Tilt: %.0f%%", *this->tilt_ * 100.0f); } if (this->toggle_.has_value()) { - ESP_LOGD(TAG, " Command: TOGGLE"); + ESP_LOGV(TAG, " Command: TOGGLE"); } this->parent_->control(*this); } @@ -143,23 +143,23 @@ void Cover::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); this->tilt = clamp(this->tilt, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); + ESP_LOGV(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { - ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); + ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f); } else { if (this->position == COVER_OPEN) { - ESP_LOGD(TAG, " State: OPEN"); + ESP_LOGV(TAG, " State: OPEN"); } else if (this->position == COVER_CLOSED) { - ESP_LOGD(TAG, " State: CLOSED"); + ESP_LOGV(TAG, " State: CLOSED"); } else { - ESP_LOGD(TAG, " State: UNKNOWN"); + ESP_LOGV(TAG, " State: UNKNOWN"); } } if (traits.get_supports_tilt()) { - ESP_LOGD(TAG, " Tilt: %.0f%%", this->tilt * 100.0f); + ESP_LOGV(TAG, " Tilt: %.0f%%", this->tilt * 100.0f); } - ESP_LOGD(TAG, " Current Operation: %s", LOG_STR_ARG(cover_operation_to_str(this->current_operation))); + ESP_LOGV(TAG, " Current Operation: %s", LOG_STR_ARG(cover_operation_to_str(this->current_operation))); this->state_callback_.call(); #if defined(USE_COVER) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/datetime/date_entity.cpp b/esphome/components/datetime/date_entity.cpp index 3ba488c0aa..997aec3f69 100644 --- a/esphome/components/datetime/date_entity.cpp +++ b/esphome/components/datetime/date_entity.cpp @@ -30,7 +30,7 @@ void DateEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); + ESP_LOGV(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_); this->state_callback_.call(); #if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_date_update(this); @@ -83,16 +83,16 @@ void DateCall::validate_() { void DateCall::perform() { this->validate_(); - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); if (this->year_.has_value()) { - ESP_LOGD(TAG, " Year: %d", *this->year_); + ESP_LOGV(TAG, " Year: %d", *this->year_); } if (this->month_.has_value()) { - ESP_LOGD(TAG, " Month: %d", *this->month_); + ESP_LOGV(TAG, " Month: %d", *this->month_); } if (this->day_.has_value()) { - ESP_LOGD(TAG, " Day: %d", *this->day_); + ESP_LOGV(TAG, " Day: %d", *this->day_); } this->parent_->control(*this); } diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index fa50271f04..a8e00d6eb3 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -45,7 +45,7 @@ void DateTimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_, + ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_, this->day_, this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY) @@ -127,25 +127,25 @@ void DateTimeCall::validate_() { void DateTimeCall::perform() { this->validate_(); - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); if (this->year_.has_value()) { - ESP_LOGD(TAG, " Year: %d", *this->year_); + ESP_LOGV(TAG, " Year: %d", *this->year_); } if (this->month_.has_value()) { - ESP_LOGD(TAG, " Month: %d", *this->month_); + ESP_LOGV(TAG, " Month: %d", *this->month_); } if (this->day_.has_value()) { - ESP_LOGD(TAG, " Day: %d", *this->day_); + ESP_LOGV(TAG, " Day: %d", *this->day_); } if (this->hour_.has_value()) { - ESP_LOGD(TAG, " Hour: %d", *this->hour_); + ESP_LOGV(TAG, " Hour: %d", *this->hour_); } if (this->minute_.has_value()) { - ESP_LOGD(TAG, " Minute: %d", *this->minute_); + ESP_LOGV(TAG, " Minute: %d", *this->minute_); } if (this->second_.has_value()) { - ESP_LOGD(TAG, " Second: %d", *this->second_); + ESP_LOGV(TAG, " Second: %d", *this->second_); } this->parent_->control(*this); } diff --git a/esphome/components/datetime/time_entity.cpp b/esphome/components/datetime/time_entity.cpp index 74e43fbbe7..1cc9eaf2fb 100644 --- a/esphome/components/datetime/time_entity.cpp +++ b/esphome/components/datetime/time_entity.cpp @@ -26,7 +26,7 @@ void TimeEntity::publish_state() { return; } this->set_has_state(true); - ESP_LOGD(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_); + ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_); this->state_callback_.call(); #if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_time_update(this); @@ -52,15 +52,15 @@ void TimeCall::validate_() { void TimeCall::perform() { this->validate_(); - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); if (this->hour_.has_value()) { - ESP_LOGD(TAG, " Hour: %d", *this->hour_); + ESP_LOGV(TAG, " Hour: %d", *this->hour_); } if (this->minute_.has_value()) { - ESP_LOGD(TAG, " Minute: %d", *this->minute_); + ESP_LOGV(TAG, " Minute: %d", *this->minute_); } if (this->second_.has_value()) { - ESP_LOGD(TAG, " Second: %d", *this->second_); + ESP_LOGV(TAG, " Second: %d", *this->second_); } this->parent_->control(*this); } diff --git a/esphome/components/event/event.cpp b/esphome/components/event/event.cpp index ec63fd9c3e..a5d64a2748 100644 --- a/esphome/components/event/event.cpp +++ b/esphome/components/event/event.cpp @@ -22,7 +22,7 @@ void Event::trigger(const std::string &event_type) { return; } this->last_event_type_ = found; - ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_); + ESP_LOGV(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_); this->event_callback_.call(StringRef(found)); #if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_event(this); diff --git a/esphome/components/fan/fan.cpp b/esphome/components/fan/fan.cpp index 97336e17b5..dc7a75018c 100644 --- a/esphome/components/fan/fan.cpp +++ b/esphome/components/fan/fan.cpp @@ -44,22 +44,22 @@ FanCall &FanCall::set_preset_mode(const char *preset_mode, size_t len) { } void FanCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting:", this->parent_.get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting:", this->parent_.get_name().c_str()); this->validate_(); if (this->binary_state_.has_value()) { - ESP_LOGD(TAG, " State: %s", ONOFF(*this->binary_state_)); + ESP_LOGV(TAG, " State: %s", ONOFF(*this->binary_state_)); } if (this->oscillating_.has_value()) { - ESP_LOGD(TAG, " Oscillating: %s", YESNO(*this->oscillating_)); + ESP_LOGV(TAG, " Oscillating: %s", YESNO(*this->oscillating_)); } if (this->speed_.has_value()) { - ESP_LOGD(TAG, " Speed: %d", *this->speed_); + ESP_LOGV(TAG, " Speed: %d", *this->speed_); } if (this->direction_.has_value()) { - ESP_LOGD(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(*this->direction_))); + ESP_LOGV(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(*this->direction_))); } if (this->preset_mode_ != nullptr) { - ESP_LOGD(TAG, " Preset Mode: %s", this->preset_mode_); + ESP_LOGV(TAG, " Preset Mode: %s", this->preset_mode_); } this->parent_.control(*this); } @@ -196,21 +196,21 @@ void Fan::apply_preset_mode_(const FanCall &call) { void Fan::publish_state() { auto traits = this->get_traits(); - ESP_LOGD(TAG, + ESP_LOGV(TAG, "'%s' >>\n" " State: %s", this->name_.c_str(), ONOFF(this->state)); if (traits.supports_speed()) { - ESP_LOGD(TAG, " Speed: %d", this->speed); + ESP_LOGV(TAG, " Speed: %d", this->speed); } if (traits.supports_oscillation()) { - ESP_LOGD(TAG, " Oscillating: %s", YESNO(this->oscillating)); + ESP_LOGV(TAG, " Oscillating: %s", YESNO(this->oscillating)); } if (traits.supports_direction()) { - ESP_LOGD(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(this->direction))); + ESP_LOGV(TAG, " Direction: %s", LOG_STR_ARG(fan_direction_to_string(this->direction))); } if (this->preset_mode_ != nullptr) { - ESP_LOGD(TAG, " Preset Mode: %s", this->preset_mode_); + ESP_LOGV(TAG, " Preset Mode: %s", this->preset_mode_); } this->state_callback_.call(); #if defined(USE_FAN) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 0b2d391fd6..41bd98de7b 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -62,9 +62,9 @@ static const LogString *color_mode_to_human(ColorMode color_mode) { } // Helper to log percentage values -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_DEBUG +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE static void log_percent(const LogString *param, float value) { - ESP_LOGD(TAG, " %s: %.0f%%", LOG_STR_ARG(param), value * 100.0f); + ESP_LOGV(TAG, " %s: %.0f%%", LOG_STR_ARG(param), value * 100.0f); } #else #define log_percent(param, value) @@ -76,20 +76,20 @@ void LightCall::perform() { const bool publish = this->get_publish_(); if (publish) { - ESP_LOGD(TAG, "'%s' Setting:", name); + ESP_LOGV(TAG, "'%s' Setting:", name); // Only print color mode when it's being changed ColorMode current_color_mode = this->parent_->remote_values.get_color_mode(); ColorMode target_color_mode = this->has_color_mode() ? this->color_mode_ : current_color_mode; if (target_color_mode != current_color_mode) { - ESP_LOGD(TAG, " Color mode: %s", LOG_STR_ARG(color_mode_to_human(v.get_color_mode()))); + ESP_LOGV(TAG, " Color mode: %s", LOG_STR_ARG(color_mode_to_human(v.get_color_mode()))); } // Only print state when it's being changed bool current_state = this->parent_->remote_values.is_on(); bool target_state = this->has_state() ? this->state_ : current_state; if (target_state != current_state) { - ESP_LOGD(TAG, " State: %s", ONOFF(v.is_on())); + ESP_LOGV(TAG, " State: %s", ONOFF(v.is_on())); } if (this->has_brightness()) { @@ -100,7 +100,7 @@ void LightCall::perform() { log_percent(LOG_STR("Color brightness"), v.get_color_brightness()); } if (this->has_red() || this->has_green() || this->has_blue()) { - ESP_LOGD(TAG, " Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.get_red() * 100.0f, v.get_green() * 100.0f, + ESP_LOGV(TAG, " Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.get_red() * 100.0f, v.get_green() * 100.0f, v.get_blue() * 100.0f); } @@ -108,11 +108,11 @@ void LightCall::perform() { log_percent(LOG_STR("White"), v.get_white()); } if (this->has_color_temperature()) { - ESP_LOGD(TAG, " Color temperature: %.1f mireds", v.get_color_temperature()); + ESP_LOGV(TAG, " Color temperature: %.1f mireds", v.get_color_temperature()); } if (this->has_cold_white() || this->has_warm_white()) { - ESP_LOGD(TAG, " Cold white: %.0f%%, warm white: %.0f%%", v.get_cold_white() * 100.0f, + ESP_LOGV(TAG, " Cold white: %.0f%%, warm white: %.0f%%", v.get_cold_white() * 100.0f, v.get_warm_white() * 100.0f); } } @@ -120,20 +120,20 @@ void LightCall::perform() { if (this->has_flash_()) { // FLASH if (publish) { - ESP_LOGD(TAG, " Flash length: %.1fs", this->flash_length_ / 1e3f); + ESP_LOGV(TAG, " Flash length: %.1fs", this->flash_length_ / 1e3f); } this->parent_->start_flash_(v, this->flash_length_, publish); } else if (this->has_transition_()) { // TRANSITION if (publish) { - ESP_LOGD(TAG, " Transition length: %.1fs", this->transition_length_ / 1e3f); + ESP_LOGV(TAG, " Transition length: %.1fs", this->transition_length_ / 1e3f); } // Special case: Transition and effect can be set when turning off if (this->has_effect_()) { if (publish) { - ESP_LOGD(TAG, " Effect: 'None'"); + ESP_LOGV(TAG, " Effect: 'None'"); } this->parent_->stop_effect_(); } @@ -150,7 +150,7 @@ void LightCall::perform() { } if (publish) { - ESP_LOGD(TAG, " Effect: '%.*s'", (int) effect_s.size(), effect_s.c_str()); + ESP_LOGV(TAG, " Effect: '%.*s'", (int) effect_s.size(), effect_s.c_str()); } this->parent_->start_effect_(this->effect_); diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 4aa636e998..90937485b9 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -41,7 +41,7 @@ void Lock::publish_state(LockState state) { this->state = state; this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); + ESP_LOGV(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); this->state_callback_.call(); #if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_lock_update(this); @@ -49,10 +49,10 @@ void Lock::publish_state(LockState state) { } void LockCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); this->validate_(); if (this->state_.has_value()) { - ESP_LOGD(TAG, " State: %s", LOG_STR_ARG(lock_state_to_string(*this->state_))); + ESP_LOGV(TAG, " State: %s", LOG_STR_ARG(lock_state_to_string(*this->state_))); } this->parent_->control(*this); } diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 70086089ff..a0eb7b5500 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -110,20 +110,20 @@ void MediaPlayerCall::validate_() { } void MediaPlayerCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); this->validate_(); if (this->command_.has_value()) { const char *command_s = media_player_command_to_string(this->command_.value()); - ESP_LOGD(TAG, " Command: %s", command_s); + ESP_LOGV(TAG, " Command: %s", command_s); } if (this->media_url_.has_value()) { - ESP_LOGD(TAG, " Media URL: %s", this->media_url_.value().c_str()); + ESP_LOGV(TAG, " Media URL: %s", this->media_url_.value().c_str()); } if (this->volume_.has_value()) { - ESP_LOGD(TAG, " Volume: %.2f", this->volume_.value()); + ESP_LOGV(TAG, " Volume: %.2f", this->volume_.value()); } if (this->announcement_.has_value()) { - ESP_LOGD(TAG, " Announcement: %s", this->announcement_.value() ? "yes" : "no"); + ESP_LOGV(TAG, " Announcement: %s", this->announcement_.value() ? "yes" : "no"); } this->parent_->control(*this); } diff --git a/esphome/components/number/number.cpp b/esphome/components/number/number.cpp index fb5d6e9f28..ca5aab6469 100644 --- a/esphome/components/number/number.cpp +++ b/esphome/components/number/number.cpp @@ -22,7 +22,7 @@ void log_number(const char *tag, const char *prefix, const char *type, Number *o void Number::publish_state(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s' >> %.2f", this->get_name().c_str(), state); + ESP_LOGV(TAG, "'%s' >> %.2f", this->get_name().c_str(), state); this->state_callback_.call(state); #if defined(USE_NUMBER) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_number_update(this); diff --git a/esphome/components/number/number_call.cpp b/esphome/components/number/number_call.cpp index aac9b2a23d..e300ca72de 100644 --- a/esphome/components/number/number_call.cpp +++ b/esphome/components/number/number_call.cpp @@ -61,7 +61,7 @@ void NumberCall::perform() { float max_value = traits.get_max_value(); if (this->operation_ == NUMBER_OP_SET) { - ESP_LOGD(TAG, "'%s': Setting value", name); + ESP_LOGV(TAG, "'%s': Setting value", name); if (!this->value_.has_value() || std::isnan(*this->value_)) { this->log_perform_warning_(LOG_STR("No value")); return; @@ -80,7 +80,7 @@ void NumberCall::perform() { target_value = max_value; } } else if (this->operation_ == NUMBER_OP_INCREMENT) { - ESP_LOGD(TAG, "'%s': Increment with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); + ESP_LOGV(TAG, "'%s': Increment with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); if (!parent->has_state()) { this->log_perform_warning_(LOG_STR("Can't increment, no state")); return; @@ -90,7 +90,7 @@ void NumberCall::perform() { if (target_value > max_value) target_value = this->cycle_or_clamp_(max_value, min_value); } else if (this->operation_ == NUMBER_OP_DECREMENT) { - ESP_LOGD(TAG, "'%s': Decrement with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); + ESP_LOGV(TAG, "'%s': Decrement with%s cycling", name, this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); if (!parent->has_state()) { this->log_perform_warning_(LOG_STR("Can't decrement, no state")); return; @@ -110,7 +110,7 @@ void NumberCall::perform() { return; } - ESP_LOGD(TAG, " New value: %f", target_value); + ESP_LOGV(TAG, " New value: %f", target_value); this->parent_->control(target_value); } diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index df90c657e2..7c3dab15ad 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -31,7 +31,7 @@ void Select::publish_state(size_t index) { #pragma GCC diagnostic ignored "-Wdeprecated-declarations" this->state = option; // Update deprecated member for backward compatibility #pragma GCC diagnostic pop - ESP_LOGD(TAG, "'%s' >> %s (%zu)", this->get_name().c_str(), option, index); + ESP_LOGV(TAG, "'%s' >> %s (%zu)", this->get_name().c_str(), option, index); this->state_callback_.call(index); #if defined(USE_SELECT) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_select_update(this); diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 83f5052fc8..0e14371d00 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -64,7 +64,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { } if (this->operation_ == SELECT_OP_SET) { - ESP_LOGD(TAG, "'%s' - Setting", name); + ESP_LOGV(TAG, "'%s' - Setting", name); if (!this->index_.has_value()) { ESP_LOGW(TAG, "'%s' - No option set", name); return nullopt; @@ -73,7 +73,7 @@ optional<size_t> SelectCall::calculate_target_index_(const char *name) { } // SELECT_OP_NEXT or SELECT_OP_PREVIOUS - ESP_LOGD(TAG, "'%s' - Selecting %s, with%s cycling", name, + ESP_LOGV(TAG, "'%s' - Selecting %s, with%s cycling", name, this->operation_ == SELECT_OP_NEXT ? LOG_STR_LITERAL("next") : LOG_STR_LITERAL("previous"), this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out")); diff --git a/esphome/components/sensor/sensor.cpp b/esphome/components/sensor/sensor.cpp index aad7f86dcf..59e011932b 100644 --- a/esphome/components/sensor/sensor.cpp +++ b/esphome/components/sensor/sensor.cpp @@ -122,7 +122,7 @@ void Sensor::clear_filters() { void Sensor::internal_send_state_to_frontend(float state) { this->set_has_state(true); this->state = state; - ESP_LOGD(TAG, "'%s' >> %.*f %s", this->get_name().c_str(), std::max(0, (int) this->get_accuracy_decimals()), state, + ESP_LOGV(TAG, "'%s' >> %.*f %s", this->get_name().c_str(), std::max(0, (int) this->get_accuracy_decimals()), state, this->get_unit_of_measurement_ref().c_str()); this->callback_.call(state); #if defined(USE_SENSOR) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index df762addbb..11840db3a3 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -61,7 +61,7 @@ void Switch::publish_state(bool state) { if (restore_mode & RESTORE_MODE_PERSISTENT_MASK) this->rtc_.save(&this->state); - ESP_LOGD(TAG, "'%s' >> %s", this->name_.c_str(), ONOFF(this->state)); + ESP_LOGV(TAG, "'%s' >> %s", this->name_.c_str(), ONOFF(this->state)); this->state_callback_.call(this->state); #if defined(USE_SWITCH) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_switch_update(this); diff --git a/esphome/components/text/text.cpp b/esphome/components/text/text.cpp index 12abc5d939..032ea468e6 100644 --- a/esphome/components/text/text.cpp +++ b/esphome/components/text/text.cpp @@ -19,9 +19,9 @@ void Text::publish_state(const char *state, size_t len) { this->state.assign(state, len); } if (this->traits.get_mode() == TEXT_MODE_PASSWORD) { - ESP_LOGD(TAG, "'%s' >> " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); + ESP_LOGV(TAG, "'%s' >> " LOG_SECRET("'%s'"), this->get_name().c_str(), this->state.c_str()); } else { - ESP_LOGD(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->state.c_str()); + ESP_LOGV(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->state.c_str()); } this->state_callback_.call(this->state); #if defined(USE_TEXT) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/text/text_call.cpp b/esphome/components/text/text_call.cpp index b7aed098c7..b7692658af 100644 --- a/esphome/components/text/text_call.cpp +++ b/esphome/components/text/text_call.cpp @@ -48,10 +48,10 @@ void TextCall::perform() { std::string target_value = this->value_.value(); if (this->parent_->traits.get_mode() == TEXT_MODE_PASSWORD) { - ESP_LOGD(TAG, "'%s' - Setting password value: " LOG_SECRET("'%s'"), this->parent_->get_name().c_str(), + ESP_LOGV(TAG, "'%s' - Setting password value: " LOG_SECRET("'%s'"), this->parent_->get_name().c_str(), target_value.c_str()); } else { - ESP_LOGD(TAG, "'%s' - Setting text value: %s", this->parent_->get_name().c_str(), target_value.c_str()); + ESP_LOGV(TAG, "'%s' - Setting text value: %s", this->parent_->get_name().c_str(), target_value.c_str()); } this->parent_->control(target_value); } diff --git a/esphome/components/text_sensor/text_sensor.cpp b/esphome/components/text_sensor/text_sensor.cpp index 0dc29f9a94..31543117b8 100644 --- a/esphome/components/text_sensor/text_sensor.cpp +++ b/esphome/components/text_sensor/text_sensor.cpp @@ -112,7 +112,7 @@ void TextSensor::internal_send_state_to_frontend(const char *state, size_t len) void TextSensor::notify_frontend_() { this->set_has_state(true); - ESP_LOGD(TAG, "'%s' >> '%s'", this->name_.c_str(), this->state.c_str()); + ESP_LOGV(TAG, "'%s' >> '%s'", this->name_.c_str(), this->state.c_str()); this->callback_.call(this->state); #if defined(USE_TEXT_SENSOR) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_text_sensor_update(this); diff --git a/esphome/components/update/update_entity.cpp b/esphome/components/update/update_entity.cpp index 7edea2fe22..1a5a55577f 100644 --- a/esphome/components/update/update_entity.cpp +++ b/esphome/components/update/update_entity.cpp @@ -18,28 +18,28 @@ const LogString *update_state_to_string(UpdateState state) { } void UpdateEntity::publish_state() { - ESP_LOGD(TAG, + ESP_LOGV(TAG, "'%s' >>\n" " Current Version: %s", this->name_.c_str(), this->update_info_.current_version.c_str()); if (!this->update_info_.md5.empty()) { - ESP_LOGD(TAG, " Latest Version: %s", this->update_info_.latest_version.c_str()); + ESP_LOGV(TAG, " Latest Version: %s", this->update_info_.latest_version.c_str()); } if (!this->update_info_.firmware_url.empty()) { - ESP_LOGD(TAG, " Firmware URL: %s", this->update_info_.firmware_url.c_str()); + ESP_LOGV(TAG, " Firmware URL: %s", this->update_info_.firmware_url.c_str()); } - ESP_LOGD(TAG, " Title: %s", this->update_info_.title.c_str()); + ESP_LOGV(TAG, " Title: %s", this->update_info_.title.c_str()); if (!this->update_info_.summary.empty()) { - ESP_LOGD(TAG, " Summary: %s", this->update_info_.summary.c_str()); + ESP_LOGV(TAG, " Summary: %s", this->update_info_.summary.c_str()); } if (!this->update_info_.release_url.empty()) { - ESP_LOGD(TAG, " Release URL: %s", this->update_info_.release_url.c_str()); + ESP_LOGV(TAG, " Release URL: %s", this->update_info_.release_url.c_str()); } if (this->update_info_.has_progress) { - ESP_LOGD(TAG, " Progress: %.0f%%", this->update_info_.progress); + ESP_LOGV(TAG, " Progress: %.0f%%", this->update_info_.progress); } this->set_has_state(true); diff --git a/esphome/components/valve/valve.cpp b/esphome/components/valve/valve.cpp index 636da1f3c3..9e1ef9da50 100644 --- a/esphome/components/valve/valve.cpp +++ b/esphome/components/valve/valve.cpp @@ -68,21 +68,21 @@ ValveCall &ValveCall::set_position(float position) { return *this; } void ValveCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); auto traits = this->parent_->get_traits(); this->validate_(); if (this->stop_) { - ESP_LOGD(TAG, " Command: STOP"); + ESP_LOGV(TAG, " Command: STOP"); } if (this->position_.has_value()) { if (traits.get_supports_position()) { - ESP_LOGD(TAG, " Position: %.0f%%", *this->position_ * 100.0f); + ESP_LOGV(TAG, " Position: %.0f%%", *this->position_ * 100.0f); } else { - ESP_LOGD(TAG, " Command: %s", LOG_STR_ARG(valve_command_to_str(*this->position_))); + ESP_LOGV(TAG, " Command: %s", LOG_STR_ARG(valve_command_to_str(*this->position_))); } } if (this->toggle_.has_value()) { - ESP_LOGD(TAG, " Command: TOGGLE"); + ESP_LOGV(TAG, " Command: TOGGLE"); } this->parent_->control(*this); } @@ -128,20 +128,20 @@ ValveCall Valve::make_call() { return {this}; } void Valve::publish_state(bool save) { this->position = clamp(this->position, 0.0f, 1.0f); - ESP_LOGD(TAG, "'%s' >>", this->name_.c_str()); + ESP_LOGV(TAG, "'%s' >>", this->name_.c_str()); auto traits = this->get_traits(); if (traits.get_supports_position()) { - ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f); + ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f); } else { if (this->position == VALVE_OPEN) { - ESP_LOGD(TAG, " State: OPEN"); + ESP_LOGV(TAG, " State: OPEN"); } else if (this->position == VALVE_CLOSED) { - ESP_LOGD(TAG, " State: CLOSED"); + ESP_LOGV(TAG, " State: CLOSED"); } else { - ESP_LOGD(TAG, " State: UNKNOWN"); + ESP_LOGV(TAG, " State: UNKNOWN"); } } - ESP_LOGD(TAG, " Current Operation: %s", LOG_STR_ARG(valve_operation_to_str(this->current_operation))); + ESP_LOGV(TAG, " Current Operation: %s", LOG_STR_ARG(valve_operation_to_str(this->current_operation))); this->state_callback_.call(); #if defined(USE_VALVE) && defined(USE_CONTROLLER_REGISTRY) diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 3989230d2d..9a74877f0a 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -83,25 +83,25 @@ WaterHeaterCall &WaterHeaterCall::set_on(bool on) { } void WaterHeaterCall::perform() { - ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); + ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str()); this->validate_(); if (this->mode_.has_value()) { - ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(water_heater_mode_to_string(*this->mode_))); + ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(water_heater_mode_to_string(*this->mode_))); } if (!std::isnan(this->target_temperature_)) { - ESP_LOGD(TAG, " Target Temperature: %.2f", this->target_temperature_); + ESP_LOGV(TAG, " Target Temperature: %.2f", this->target_temperature_); } if (!std::isnan(this->target_temperature_low_)) { - ESP_LOGD(TAG, " Target Temperature Low: %.2f", this->target_temperature_low_); + ESP_LOGV(TAG, " Target Temperature Low: %.2f", this->target_temperature_low_); } if (!std::isnan(this->target_temperature_high_)) { - ESP_LOGD(TAG, " Target Temperature High: %.2f", this->target_temperature_high_); + ESP_LOGV(TAG, " Target Temperature High: %.2f", this->target_temperature_high_); } if (this->state_mask_ & WATER_HEATER_STATE_AWAY) { - ESP_LOGD(TAG, " Away: %s", (this->state_ & WATER_HEATER_STATE_AWAY) ? "YES" : "NO"); + ESP_LOGV(TAG, " Away: %s", (this->state_ & WATER_HEATER_STATE_AWAY) ? "YES" : "NO"); } if (this->state_mask_ & WATER_HEATER_STATE_ON) { - ESP_LOGD(TAG, " On: %s", (this->state_ & WATER_HEATER_STATE_ON) ? "YES" : "NO"); + ESP_LOGV(TAG, " On: %s", (this->state_ & WATER_HEATER_STATE_ON) ? "YES" : "NO"); } this->parent_->control(*this); } @@ -158,24 +158,24 @@ void WaterHeaterCall::validate_() { void WaterHeater::publish_state() { auto traits = this->get_traits(); - ESP_LOGD(TAG, + ESP_LOGV(TAG, "'%s' >>\n" " Mode: %s", this->name_.c_str(), LOG_STR_ARG(water_heater_mode_to_string(this->mode_))); if (!std::isnan(this->current_temperature_)) { - ESP_LOGD(TAG, " Current Temperature: %.2f°C", this->current_temperature_); + ESP_LOGV(TAG, " Current Temperature: %.2f°C", this->current_temperature_); } if (traits.get_supports_two_point_target_temperature()) { - ESP_LOGD(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low_, + ESP_LOGV(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low_, this->target_temperature_high_); } else if (!std::isnan(this->target_temperature_)) { - ESP_LOGD(TAG, " Target Temperature: %.2f°C", this->target_temperature_); + ESP_LOGV(TAG, " Target Temperature: %.2f°C", this->target_temperature_); } if (this->state_ & WATER_HEATER_STATE_AWAY) { - ESP_LOGD(TAG, " Away: YES"); + ESP_LOGV(TAG, " Away: YES"); } if (traits.has_feature_flags(WATER_HEATER_SUPPORTS_ON_OFF)) { - ESP_LOGD(TAG, " On: %s", (this->state_ & WATER_HEATER_STATE_ON) ? "YES" : "NO"); + ESP_LOGV(TAG, " On: %s", (this->state_ & WATER_HEATER_STATE_ON) ? "YES" : "NO"); } #if defined(USE_WATER_HEATER) && defined(USE_CONTROLLER_REGISTRY) From a075f63b59c68dd6e627c505397c1cdf5a052b45 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:50:37 -0400 Subject: [PATCH 1718/2030] [uart] Fix debug callback missing peeked byte and reading past end (#15169) --- esphome/components/uart/uart_component_esp_idf.cpp | 6 ++++-- esphome/components/uart/uart_component_host.cpp | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index bd2f915d3a..cd77cd1189 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -324,6 +324,9 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) { } bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { + if (len == 0) { + return false; + } size_t length_to_read = len; int32_t read_len = 0; if (!this->check_read_timeout_(len)) @@ -331,11 +334,10 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { if (this->has_peek_) { length_to_read--; *data = this->peek_byte_; - data++; this->has_peek_ = false; } if (length_to_read > 0) - read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS); + read_len = uart_read_bytes(this->uart_num_, data + (len - length_to_read), length_to_read, 20 / portTICK_PERIOD_MS); #ifdef USE_UART_DEBUGGER for (size_t i = 0; i < len; i++) { this->debug_callback_.call(UART_DIRECTION_RX, data[i]); diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 0042ffae23..085610a983 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -235,16 +235,14 @@ bool HostUartComponent::read_array(uint8_t *data, size_t len) { } if (!this->check_read_timeout_(len)) return false; - uint8_t *data_ptr = data; size_t length_to_read = len; if (this->has_peek_) { length_to_read--; - *data_ptr = this->peek_byte_; - data_ptr++; + *data = this->peek_byte_; this->has_peek_ = false; } if (length_to_read > 0) { - int sz = ::read(this->file_descriptor_, data_ptr, length_to_read); + int sz = ::read(this->file_descriptor_, data + (len - length_to_read), length_to_read); if (sz == -1) { this->update_error_(strerror(errno)); return false; From 29e263ad7d42fc90d54e809e41709f03d2e7f006 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Mar 2026 13:43:01 -1000 Subject: [PATCH 1719/2030] [esp32] Wrap vfprintf to fix printf stub on picolibc (IDF 6) (#15172) --- esphome/components/esp32/__init__.py | 2 +- esphome/components/esp32/printf_stubs.cpp | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0e216485ac..91eb913e3d 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -1587,7 +1587,7 @@ async def to_code(config): if conf[CONF_ADVANCED][CONF_ENABLE_FULL_PRINTF]: cg.add_define("USE_FULL_PRINTF") else: - for symbol in ("vprintf", "printf", "fprintf"): + for symbol in ("vprintf", "printf", "fprintf", "vfprintf"): cg.add_build_flag(f"-Wl,--wrap={symbol}") else: cg.add_build_flag("-DUSE_ARDUINO") diff --git a/esphome/components/esp32/printf_stubs.cpp b/esphome/components/esp32/printf_stubs.cpp index c6f03bc363..386fbbd79d 100644 --- a/esphome/components/esp32/printf_stubs.cpp +++ b/esphome/components/esp32/printf_stubs.cpp @@ -2,10 +2,11 @@ * Linker wrap stubs for FILE*-based printf functions. * * ESP-IDF SDK components (gpio driver, ringbuf, log_write) reference - * fprintf(), printf(), and vprintf() which pull in newlib's _vfprintf_r - * (~11 KB). This is a separate implementation from _svfprintf_r (used by - * snprintf/vsnprintf) that handles FILE* stream I/O with buffering and - * locking. + * fprintf(), printf(), vprintf(), and vfprintf() which pull in the full + * printf implementation (~11 KB on newlib's _vfprintf_r, ~2.8 KB on + * picolibc's vfprintf). This is a separate implementation from the one + * used by snprintf/vsnprintf that handles FILE* stream I/O with buffering + * and locking. * * ESPHome replaces the ESP-IDF log handler via esp_log_set_vprintf_(), * so the SDK's vprintf() path is dead code at runtime. The fprintf() @@ -70,11 +71,15 @@ int __wrap_printf(const char *fmt, ...) { return len; } +int __wrap_vfprintf(FILE *stream, const char *fmt, va_list ap) { + char buf[PRINTF_BUFFER_SIZE]; + return write_printf_buffer(stream, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); +} + int __wrap_fprintf(FILE *stream, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - char buf[PRINTF_BUFFER_SIZE]; - int len = write_printf_buffer(stream, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); + int len = __wrap_vfprintf(stream, fmt, ap); va_end(ap); return len; } From 676ac9d8b876044b0278f48fbd70100cf8594141 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Wed, 25 Mar 2026 21:30:46 -0500 Subject: [PATCH 1720/2030] [infrared][ir_rf_proxy] Add `receiver_frequency` config for IR receiver demodulation frequency (#15156) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/api/api.proto | 1 + esphome/components/api/api_connection.cpp | 1 + esphome/components/api/api_pb2.cpp | 2 ++ esphome/components/api/api_pb2.h | 3 ++- esphome/components/api/api_pb2_dump.cpp | 1 + esphome/components/const/__init__.py | 1 + esphome/components/infrared/infrared.h | 4 ++++ esphome/components/ir_rf_proxy/infrared.py | 15 ++++++++++++++- esphome/components/ir_rf_proxy/ir_rf_proxy.h | 3 +++ tests/components/ir_rf_proxy/common-rx.yaml | 1 + 10 files changed, 30 insertions(+), 2 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 86daa9a2bf..96ee2fb920 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -2512,6 +2512,7 @@ message ListEntitiesInfraredResponse { EntityCategory entity_category = 6; uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"]; uint32 capabilities = 8; // Bitfield of InfraredCapabilityFlags + uint32 receiver_frequency = 9; // Demodulation frequency of the IR receiver in Hz (0 = unspecified) } // Command to transmit infrared/RF data using raw timings diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index d023cd21a8..0a99adcacf 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1549,6 +1549,7 @@ uint16_t APIConnection::try_send_infrared_info(EntityBase *entity, APIConnection auto *infrared = static_cast<infrared::Infrared *>(entity); ListEntitiesInfraredResponse msg; msg.capabilities = infrared->get_capability_flags(); + msg.receiver_frequency = infrared->get_traits().get_receiver_frequency_hz(); return fill_and_encode_entity_info(infrared, msg, conn, remaining_size); } #endif diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f77f4df545..ae2cd2bae8 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -3657,6 +3657,7 @@ void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_uint32(7, this->device_id); #endif buffer.encode_uint32(8, this->capabilities); + buffer.encode_uint32(9, this->receiver_frequency); } uint32_t ListEntitiesInfraredResponse::calculate_size() const { uint32_t size = 0; @@ -3672,6 +3673,7 @@ uint32_t ListEntitiesInfraredResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->device_id); #endif size += ProtoSize::calc_uint32(1, this->capabilities); + size += ProtoSize::calc_uint32(1, this->receiver_frequency); return size; } #endif diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 16586e6e9a..14f6c704ae 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -3041,11 +3041,12 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { public: static constexpr uint8_t MESSAGE_TYPE = 135; - static constexpr uint8_t ESTIMATED_SIZE = 44; + static constexpr uint8_t ESTIMATED_SIZE = 48; #ifdef HAS_PROTO_MESSAGE_DUMP const LogString *message_name() const override { return LOG_STR("list_entities_infrared_response"); } #endif uint32_t capabilities{0}; + uint32_t receiver_frequency{0}; void encode(ProtoWriteBuffer &buffer) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP diff --git a/esphome/components/api/api_pb2_dump.cpp b/esphome/components/api/api_pb2_dump.cpp index a11f3b231e..640c347371 100644 --- a/esphome/components/api/api_pb2_dump.cpp +++ b/esphome/components/api/api_pb2_dump.cpp @@ -2572,6 +2572,7 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const { dump_field(out, ESPHOME_PSTR("device_id"), this->device_id); #endif dump_field(out, ESPHOME_PSTR("capabilities"), this->capabilities); + dump_field(out, ESPHOME_PSTR("receiver_frequency"), this->receiver_frequency); return out.c_str(); } #endif diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index 1fbf88c276..0eb37e3029 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -18,6 +18,7 @@ CONF_ON_PACKET = "on_packet" CONF_ON_RECEIVE = "on_receive" CONF_ON_STATE_CHANGE = "on_state_change" CONF_PARITY = "parity" +CONF_RECEIVER_FREQUENCY = "receiver_frequency" CONF_REQUEST_HEADERS = "request_headers" CONF_ROWS = "rows" CONF_STOP_BITS = "stop_bits" diff --git a/esphome/components/infrared/infrared.h b/esphome/components/infrared/infrared.h index 59535f499a..6d91c97cce 100644 --- a/esphome/components/infrared/infrared.h +++ b/esphome/components/infrared/infrared.h @@ -101,9 +101,13 @@ class InfraredTraits { bool get_supports_receiver() const { return this->supports_receiver_; } void set_supports_receiver(bool supports) { this->supports_receiver_ = supports; } + uint32_t get_receiver_frequency_hz() const { return this->receiver_frequency_hz_; } + void set_receiver_frequency_hz(uint32_t freq) { this->receiver_frequency_hz_ = freq; } + protected: bool supports_transmitter_{false}; bool supports_receiver_{false}; + uint32_t receiver_frequency_hz_{0}; // Demodulation frequency of the IR receiver in Hz (0 = unspecified) }; /// Infrared - Base class for infrared remote control implementations diff --git a/esphome/components/ir_rf_proxy/infrared.py b/esphome/components/ir_rf_proxy/infrared.py index 4a4d9fa860..3218889721 100644 --- a/esphome/components/ir_rf_proxy/infrared.py +++ b/esphome/components/ir_rf_proxy/infrared.py @@ -4,6 +4,7 @@ from typing import Any import esphome.codegen as cg from esphome.components import infrared, remote_receiver, remote_transmitter +from esphome.components.const import CONF_RECEIVER_FREQUENCY import esphome.config_validation as cv from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_FREQUENCY import esphome.final_validate as fv @@ -19,6 +20,7 @@ CONFIG_SCHEMA = cv.All( infrared.infrared_schema(IrRfProxy).extend( { cv.Optional(CONF_FREQUENCY, default=0): cv.frequency, + cv.Optional(CONF_RECEIVER_FREQUENCY): cv.frequency, cv.Optional(CONF_REMOTE_RECEIVER_ID): cv.use_id( remote_receiver.RemoteReceiverComponent ), @@ -33,7 +35,14 @@ CONFIG_SCHEMA = cv.All( def _final_validate(config: dict[str, Any]) -> None: """Validate that transmitters have a proper carrier duty cycle.""" - # Only validate if this is an infrared (not RF) configuration with a transmitter + # receiver_frequency is only meaningful for receiver configurations + if CONF_RECEIVER_FREQUENCY in config and CONF_REMOTE_RECEIVER_ID not in config: + raise cv.Invalid( + f"'{CONF_RECEIVER_FREQUENCY}' can only be used with '{CONF_REMOTE_RECEIVER_ID}', " + "not with a transmitter" + ) + + # Only validate duty cycle if this is an infrared (not RF) configuration with a transmitter if config.get(CONF_FREQUENCY, 0) != 0 or CONF_REMOTE_TRANSMITTER_ID not in config: return @@ -75,3 +84,7 @@ async def to_code(config: dict[str, Any]) -> None: if CONF_REMOTE_RECEIVER_ID in config: receiver = await cg.get_variable(config[CONF_REMOTE_RECEIVER_ID]) cg.add(var.set_receiver(receiver)) + + # Set receiver demodulation frequency if specified (metadata only, no hardware effect) + if CONF_RECEIVER_FREQUENCY in config: + cg.add(var.set_receiver_frequency(config[CONF_RECEIVER_FREQUENCY])) diff --git a/esphome/components/ir_rf_proxy/ir_rf_proxy.h b/esphome/components/ir_rf_proxy/ir_rf_proxy.h index f067a6e17a..05b988f287 100644 --- a/esphome/components/ir_rf_proxy/ir_rf_proxy.h +++ b/esphome/components/ir_rf_proxy/ir_rf_proxy.h @@ -22,6 +22,9 @@ class IrRfProxy : public infrared::Infrared { /// Check if this is RF mode (non-zero frequency) bool is_rf() const { return this->frequency_khz_ > 0; } + /// Set the receiver's hardware demodulation frequency in Hz (metadata only, does not affect hardware) + void set_receiver_frequency(uint32_t frequency_hz) { this->get_traits().set_receiver_frequency_hz(frequency_hz); } + protected: // RF frequency in kHz (Hz / 1000); 0 = infrared, non-zero = RF uint32_t frequency_khz_{0}; diff --git a/tests/components/ir_rf_proxy/common-rx.yaml b/tests/components/ir_rf_proxy/common-rx.yaml index 0f758f832d..37033a128e 100644 --- a/tests/components/ir_rf_proxy/common-rx.yaml +++ b/tests/components/ir_rf_proxy/common-rx.yaml @@ -8,6 +8,7 @@ infrared: - platform: ir_rf_proxy id: ir_rx name: "IR Receiver" + receiver_frequency: 38kHz remote_receiver_id: ir_receiver # RF 900MHz receiver From 8a6b009173a8373df76b3a4d07040c8852162b8e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 25 Mar 2026 16:53:33 -1000 Subject: [PATCH 1721/2030] [light] Move normal state logging to VERBOSE (#15177) --- esphome/components/light/light_call.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 41bd98de7b..7c936b51b7 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -385,7 +385,7 @@ void LightCall::transform_parameters_() { !(this->color_mode_ & ColorCapability::WHITE) && // !(this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) && // min_mireds > 0.0f && max_mireds > 0.0f) { - ESP_LOGD(TAG, "'%s': setting cold/warm white channels using white/color temperature values", + ESP_LOGV(TAG, "'%s': setting cold/warm white channels using white/color temperature values", this->parent_->get_name().c_str()); // Only compute cold_white/warm_white from color_temperature if they're not already explicitly set. // This is important for state restoration, where both color_temperature and cold_white/warm_white @@ -432,7 +432,7 @@ ColorMode LightCall::compute_color_mode_() { // Don't change if the current mode is in the intersection (suitable AND supported) if (ColorModeMask::mask_contains(intersection, current_mode)) { - ESP_LOGI(TAG, "'%s': color mode not specified; retaining %s", this->parent_->get_name().c_str(), + ESP_LOGV(TAG, "'%s': color mode not specified; retaining %s", this->parent_->get_name().c_str(), LOG_STR_ARG(color_mode_to_human(current_mode))); return current_mode; } @@ -440,7 +440,7 @@ ColorMode LightCall::compute_color_mode_() { // Use the preferred suitable mode. if (intersection != 0) { ColorMode mode = ColorModeMask::first_value_from_mask(intersection); - ESP_LOGI(TAG, "'%s': color mode not specified; using %s", this->parent_->get_name().c_str(), + ESP_LOGV(TAG, "'%s': color mode not specified; using %s", this->parent_->get_name().c_str(), LOG_STR_ARG(color_mode_to_human(mode))); return mode; } From 92604017471dd0dbcfbb90f6991f62160545b2e8 Mon Sep 17 00:00:00 2001 From: Daniel Kent <129895318+danielkent-net@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:11:46 -0400 Subject: [PATCH 1722/2030] [bmp581] Add SPI support for BMP581 (#13124) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + .../components/bmp581_base/bmp581_base.cpp | 11 ++- esphome/components/bmp581_base/bmp581_base.h | 3 + esphome/components/bmp581_spi/__init__.py | 0 esphome/components/bmp581_spi/bmp581_spi.cpp | 73 +++++++++++++++++++ esphome/components/bmp581_spi/bmp581_spi.h | 24 ++++++ esphome/components/bmp581_spi/sensor.py | 48 ++++++++++++ tests/components/bmp581_spi/common.yaml | 9 +++ .../components/bmp581_spi/test.esp32-idf.yaml | 7 ++ .../bmp581_spi/test.esp8266-ard.yaml | 7 ++ .../bmp581_spi/test.rp2040-ard.yaml | 7 ++ 11 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 esphome/components/bmp581_spi/__init__.py create mode 100644 esphome/components/bmp581_spi/bmp581_spi.cpp create mode 100644 esphome/components/bmp581_spi/bmp581_spi.h create mode 100644 esphome/components/bmp581_spi/sensor.py create mode 100644 tests/components/bmp581_spi/common.yaml create mode 100644 tests/components/bmp581_spi/test.esp32-idf.yaml create mode 100644 tests/components/bmp581_spi/test.esp8266-ard.yaml create mode 100644 tests/components/bmp581_spi/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index afe4cdb871..8d297d7b07 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -92,6 +92,7 @@ esphome/components/bmp3xx_i2c/* @latonita esphome/components/bmp3xx_spi/* @latonita esphome/components/bmp581_base/* @danielkent-net @kahrendt esphome/components/bmp581_i2c/* @danielkent-net @kahrendt +esphome/components/bmp581_spi/* @danielkent-net @kahrendt esphome/components/bp1658cj/* @Cossid esphome/components/bp5758d/* @Cossid esphome/components/bthome_mithermometer/* @nagyrobi diff --git a/esphome/components/bmp581_base/bmp581_base.cpp b/esphome/components/bmp581_base/bmp581_base.cpp index 89a92de31d..c9d250545b 100644 --- a/esphome/components/bmp581_base/bmp581_base.cpp +++ b/esphome/components/bmp581_base/bmp581_base.cpp @@ -469,14 +469,18 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float & } bool BMP581Component::reset_() { + // - activates interface (only relevant for SPI mode) // - writes reset command to the command register // - waits for sensor to complete reset + // - activates interface (only relevant for SPI mode) // - returns the Power-On-Reboot interrupt status, which is asserted if successful + // activates communication interface (SPI only) + this->activate_interface(); + // writes reset command to BMP's command register if (!this->bmp_write_byte(BMP581_COMMAND, RESET_COMMAND)) { ESP_LOGE(TAG, "Failed to write reset command"); - return false; } @@ -484,6 +488,9 @@ bool BMP581Component::reset_() { // - round up to 3 ms delay(3); + // reactivates communication interface after reset (SPI only) + this->activate_interface(); + // read interrupt status register if (!this->bmp_read_byte(BMP581_INT_STATUS, &this->int_status_.reg)) { ESP_LOGE(TAG, "Failed to read interrupt status register"); @@ -491,7 +498,7 @@ bool BMP581Component::reset_() { return false; } - // Power-On-Reboot bit is asserted if sensor successfully reset + // power-On-Reboot bit is asserted if sensor successfully reset return this->int_status_.bit.por; } diff --git a/esphome/components/bmp581_base/bmp581_base.h b/esphome/components/bmp581_base/bmp581_base.h index d99c420272..c3920512e0 100644 --- a/esphome/components/bmp581_base/bmp581_base.h +++ b/esphome/components/bmp581_base/bmp581_base.h @@ -87,6 +87,9 @@ class BMP581Component : public PollingComponent { virtual bool bmp_read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; virtual bool bmp_write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0; + // Interface activation function. Only used for SPI interface; no-op for I2C. + virtual void activate_interface() {} + sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *pressure_sensor_{nullptr}; diff --git a/esphome/components/bmp581_spi/__init__.py b/esphome/components/bmp581_spi/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/bmp581_spi/bmp581_spi.cpp b/esphome/components/bmp581_spi/bmp581_spi.cpp new file mode 100644 index 0000000000..01435880f0 --- /dev/null +++ b/esphome/components/bmp581_spi/bmp581_spi.cpp @@ -0,0 +1,73 @@ +#include <cstdint> +#include <cstddef> + +#include "bmp581_spi.h" +#include "esphome/components/bmp581_base/bmp581_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome::bmp581_spi { + +static const char *const TAG = "bmp581_spi"; + +// OR (|) register with BMP_SPI_READ for read +inline constexpr uint8_t BMP_SPI_READ = 0x80; + +// AND (&) register with BMP_SPI_WRITE for write +inline constexpr uint8_t BMP_SPI_WRITE = 0x7F; + +void BMP581SPIComponent::dump_config() { + BMP581Component::dump_config(); + LOG_SPI_DEVICE(this); +} + +void BMP581SPIComponent::setup() { + this->spi_setup(); + BMP581Component::setup(); +} + +void BMP581SPIComponent::activate_interface() { + // - forces the device into SPI mode using a dummy read + uint8_t dummy_read = 0; + this->bmp_read_byte(bmp581_base::BMP581_CHIP_ID, &dummy_read); +} + +// In SPI mode, only 7 bits of the register addresses are used; the MSB of register address is not used +// and replaced by a read/write bit (RW = ‘0’ for write and RW = ‘1’ for read). +// Example: address 0xF7 is accessed by using SPI register address 0x77. For write access, the byte +// 0x77 is transferred, for read access, the byte 0xF7 is transferred. +// The expressions BMP_SPI_READ (| with register) and BMP_SPI_WRITE (& with register) +// are defined for readability. +// https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf + +bool BMP581SPIComponent::bmp_read_byte(uint8_t a_register, uint8_t *data) { + this->enable(); + this->transfer_byte(a_register | BMP_SPI_READ); + *data = this->transfer_byte(0); + this->disable(); + return true; +} + +bool BMP581SPIComponent::bmp_write_byte(uint8_t a_register, uint8_t data) { + this->enable(); + this->transfer_byte(a_register & BMP_SPI_WRITE); + this->transfer_byte(data); + this->disable(); + return true; +} + +bool BMP581SPIComponent::bmp_read_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(a_register | BMP_SPI_READ); + this->read_array(data, len); + this->disable(); + return true; +} + +bool BMP581SPIComponent::bmp_write_bytes(uint8_t a_register, uint8_t *data, size_t len) { + this->enable(); + this->transfer_byte(a_register & BMP_SPI_WRITE); + this->write_array(data, len); + this->disable(); + return true; +} +} // namespace esphome::bmp581_spi diff --git a/esphome/components/bmp581_spi/bmp581_spi.h b/esphome/components/bmp581_spi/bmp581_spi.h new file mode 100644 index 0000000000..57f75588d5 --- /dev/null +++ b/esphome/components/bmp581_spi/bmp581_spi.h @@ -0,0 +1,24 @@ +#pragma once + +#include "esphome/components/bmp581_base/bmp581_base.h" +#include "esphome/components/spi/spi.h" + +namespace esphome::bmp581_spi { + +// BMP581 is technically compatible with SPI Mode0 and Mode3. Default to Mode3. +class BMP581SPIComponent : public esphome::bmp581_base::BMP581Component, + public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_HIGH, + spi::CLOCK_PHASE_TRAILING, spi::DATA_RATE_200KHZ> { + public: + void setup() override; + bool bmp_read_byte(uint8_t a_register, uint8_t *data) override; + bool bmp_write_byte(uint8_t a_register, uint8_t data) override; + bool bmp_read_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + bool bmp_write_bytes(uint8_t a_register, uint8_t *data, size_t len) override; + void dump_config() override; + + protected: + void activate_interface() override; +}; + +} // namespace esphome::bmp581_spi diff --git a/esphome/components/bmp581_spi/sensor.py b/esphome/components/bmp581_spi/sensor.py new file mode 100644 index 0000000000..75f60b2460 --- /dev/null +++ b/esphome/components/bmp581_spi/sensor.py @@ -0,0 +1,48 @@ +import logging + +import esphome.codegen as cg +from esphome.components import spi +from esphome.components.spi import CONF_SPI_MODE +import esphome.config_validation as cv + +from ..bmp581_base import CONFIG_SCHEMA_BASE, to_code_base + +AUTO_LOAD = ["bmp581_base"] +CODEOWNERS = ["@kahrendt", "@danielkent-net"] +DEPENDENCIES = ["spi"] + +_LOGGER = logging.getLogger(__name__) + +VALID_SPI_MODES = { + 0: "MODE0", + "0": "MODE0", + "MODE0": "MODE0", + 3: "MODE3", + "3": "MODE3", + "MODE3": "MODE3", +} + +bmp581_ns = cg.esphome_ns.namespace("bmp581_spi") +BMP581SPIComponent = bmp581_ns.class_( + "BMP581SPIComponent", cg.PollingComponent, spi.SPIDevice +) + + +def check_spi_mode(config): + spi_mode = config.get(CONF_SPI_MODE) + if spi_mode not in VALID_SPI_MODES: + raise cv.Invalid("BMP581 only supports SPI mode 3") + return config + + +CONFIG_SCHEMA = cv.All( + CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema(default_mode="mode3")).extend( + {cv.GenerateID(): cv.declare_id(BMP581SPIComponent)} + ), + check_spi_mode, +) + + +async def to_code(config): + var = await to_code_base(config) + await spi.register_spi_device(var, config) diff --git a/tests/components/bmp581_spi/common.yaml b/tests/components/bmp581_spi/common.yaml new file mode 100644 index 0000000000..f22074f867 --- /dev/null +++ b/tests/components/bmp581_spi/common.yaml @@ -0,0 +1,9 @@ +sensor: + - platform: bmp581_spi + cs_pin: ${cs_pin} + temperature: + name: BMP581 Temperature + iir_filter: 2x + pressure: + name: BMP581 Pressure + oversampling: 128x diff --git a/tests/components/bmp581_spi/test.esp32-idf.yaml b/tests/components/bmp581_spi/test.esp32-idf.yaml new file mode 100644 index 0000000000..a3352cf880 --- /dev/null +++ b/tests/components/bmp581_spi/test.esp32-idf.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO5 + +packages: + spi: !include ../../test_build_components/common/spi/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/bmp581_spi/test.esp8266-ard.yaml b/tests/components/bmp581_spi/test.esp8266-ard.yaml new file mode 100644 index 0000000000..595f31046a --- /dev/null +++ b/tests/components/bmp581_spi/test.esp8266-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO15 + +packages: + spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/bmp581_spi/test.rp2040-ard.yaml b/tests/components/bmp581_spi/test.rp2040-ard.yaml new file mode 100644 index 0000000000..79ea6ce90b --- /dev/null +++ b/tests/components/bmp581_spi/test.rp2040-ard.yaml @@ -0,0 +1,7 @@ +substitutions: + cs_pin: GPIO5 + +packages: + spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml + +<<: !include common.yaml From f3a31be6d0f4d896db0356b1cabea72741a73921 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 07:32:39 -1000 Subject: [PATCH 1723/2030] [benchmark] Add climate publish_state and call benchmarks (#15180) --- .../benchmarks/components/climate/__init__.py | 5 + .../components/climate/bench_climate.cpp | 142 ++++++++++++++++++ .../components/climate/benchmark.yaml | 1 + 3 files changed, 148 insertions(+) create mode 100644 tests/benchmarks/components/climate/__init__.py create mode 100644 tests/benchmarks/components/climate/bench_climate.cpp create mode 100644 tests/benchmarks/components/climate/benchmark.yaml diff --git a/tests/benchmarks/components/climate/__init__.py b/tests/benchmarks/components/climate/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/climate/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/climate/bench_climate.cpp b/tests/benchmarks/components/climate/bench_climate.cpp new file mode 100644 index 0000000000..316a72b2b6 --- /dev/null +++ b/tests/benchmarks/components/climate/bench_climate.cpp @@ -0,0 +1,142 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/climate/climate.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Climate for benchmarking — control() is a no-op. +class BenchClimate : public climate::Climate { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + climate::ClimateTraits traits() override { return this->traits_; } + + climate::ClimateTraits traits_; + + protected: + void control(const climate::ClimateCall & /*call*/) override {} +}; + +// Helper to create a typical HVAC climate device for benchmarks. +// Note: setup() is not called (no preferences backend), so save_state_() +// is effectively a no-op. This benchmarks the call/validation path, not persistence. +static void setup_hvac_climate(BenchClimate &climate) { + climate.configure("test_climate"); + climate.traits_.set_supported_modes({ + climate::CLIMATE_MODE_OFF, + climate::CLIMATE_MODE_HEAT_COOL, + climate::CLIMATE_MODE_COOL, + climate::CLIMATE_MODE_HEAT, + climate::CLIMATE_MODE_FAN_ONLY, + }); + climate.traits_.set_supported_fan_modes({ + climate::CLIMATE_FAN_AUTO, + climate::CLIMATE_FAN_LOW, + climate::CLIMATE_FAN_MEDIUM, + climate::CLIMATE_FAN_HIGH, + }); + climate.traits_.set_supported_swing_modes({ + climate::CLIMATE_SWING_OFF, + climate::CLIMATE_SWING_BOTH, + climate::CLIMATE_SWING_VERTICAL, + climate::CLIMATE_SWING_HORIZONTAL, + }); + climate.traits_.set_supported_presets({ + climate::CLIMATE_PRESET_NONE, + climate::CLIMATE_PRESET_HOME, + climate::CLIMATE_PRESET_AWAY, + }); + climate.traits_.set_visual_min_temperature(16.0f); + climate.traits_.set_visual_max_temperature(30.0f); + climate.traits_.set_visual_target_temperature_step(0.5f); + climate.traits_.set_visual_current_temperature_step(0.1f); + climate.traits_.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE | climate::CLIMATE_SUPPORTS_ACTION); +} + +// --- Climate::publish_state() with temperature update --- +// Measures the publish path for a thermostat reporting state — +// the hot path during HVAC operation. + +static void ClimatePublish_State(benchmark::State &state) { + BenchClimate climate; + setup_hvac_climate(climate); + climate.mode = climate::CLIMATE_MODE_HEAT; + climate.action = climate::CLIMATE_ACTION_HEATING; + climate.target_temperature = 22.0f; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + climate.current_temperature = 20.0f + static_cast<float>(i % 100) / 10.0f; + climate.publish_state(); + } + benchmark::DoNotOptimize(climate.current_temperature); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ClimatePublish_State); + +// --- Climate::publish_state() with callback --- +// Measures callback dispatch overhead. + +static void ClimatePublish_WithCallback(benchmark::State &state) { + BenchClimate climate; + setup_hvac_climate(climate); + climate.mode = climate::CLIMATE_MODE_HEAT; + climate.target_temperature = 22.0f; + + uint64_t callback_count = 0; + climate.add_on_state_callback([&callback_count](climate::Climate & /*c*/) { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + climate.current_temperature = 20.0f + static_cast<float>(i % 100) / 10.0f; + climate.publish_state(); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ClimatePublish_WithCallback); + +// --- ClimateCall::perform() set target temperature --- +// The most common climate call — adjusting the thermostat setpoint. + +static void ClimateCall_SetTemperature(benchmark::State &state) { + BenchClimate climate; + setup_hvac_climate(climate); + climate.mode = climate::CLIMATE_MODE_HEAT; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float temp = 18.0f + static_cast<float>(i % 25) * 0.5f; + climate.make_call().set_target_temperature(temp).perform(); + } + benchmark::DoNotOptimize(climate.target_temperature); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ClimateCall_SetTemperature); + +// --- ClimateCall::perform() mode change with fan --- +// Exercises the validation path with multiple fields set. + +static void ClimateCall_ModeChange(benchmark::State &state) { + BenchClimate climate; + setup_hvac_climate(climate); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + auto mode = (i % 2 == 0) ? climate::CLIMATE_MODE_HEAT : climate::CLIMATE_MODE_COOL; + auto fan = (i % 2 == 0) ? climate::CLIMATE_FAN_HIGH : climate::CLIMATE_FAN_LOW; + climate.make_call().set_mode(mode).set_fan_mode(fan).set_target_temperature(22.0f).perform(); + } + benchmark::DoNotOptimize(climate.mode); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ClimateCall_ModeChange); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/climate/benchmark.yaml b/tests/benchmarks/components/climate/benchmark.yaml new file mode 100644 index 0000000000..8e79ed0ae7 --- /dev/null +++ b/tests/benchmarks/components/climate/benchmark.yaml @@ -0,0 +1 @@ +climate: From 689828436107c797a0525dbf5f3b86f96189ec47 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 07:32:54 -1000 Subject: [PATCH 1724/2030] [benchmark] Add cover publish_state and call benchmarks (#15179) --- tests/benchmarks/components/cover/__init__.py | 5 + .../components/cover/bench_cover_publish.cpp | 107 ++++++++++++++++++ .../components/cover/benchmark.yaml | 1 + 3 files changed, 113 insertions(+) create mode 100644 tests/benchmarks/components/cover/__init__.py create mode 100644 tests/benchmarks/components/cover/bench_cover_publish.cpp create mode 100644 tests/benchmarks/components/cover/benchmark.yaml diff --git a/tests/benchmarks/components/cover/__init__.py b/tests/benchmarks/components/cover/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/cover/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/cover/bench_cover_publish.cpp b/tests/benchmarks/components/cover/bench_cover_publish.cpp new file mode 100644 index 0000000000..794d967edb --- /dev/null +++ b/tests/benchmarks/components/cover/bench_cover_publish.cpp @@ -0,0 +1,107 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/cover/cover.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Cover for benchmarking — control() is a no-op. +class BenchCover : public cover::Cover { + public: + cover::CoverTraits get_traits() override { return this->traits_; } + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + cover::CoverTraits traits_; + + protected: + void control(const cover::CoverCall & /*call*/) override {} +}; + +// --- Cover::publish_state() with position updates --- +// Measures the publish path for a garage door reporting position +// during open/close — the hot path during movement. + +static void CoverPublish_Position(benchmark::State &state) { + BenchCover cover; + cover.configure("test_cover"); + cover.traits_.set_supports_position(true); + cover.traits_.set_supports_tilt(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + cover.position = static_cast<float>(i % 101) / 100.0f; + cover.current_operation = (i % 2 == 0) ? cover::COVER_OPERATION_OPENING : cover::COVER_OPERATION_CLOSING; + cover.publish_state(false); + } + benchmark::DoNotOptimize(cover.position); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CoverPublish_Position); + +// --- Cover::publish_state() with callback --- +// Measures callback dispatch overhead. + +static void CoverPublish_WithCallback(benchmark::State &state) { + BenchCover cover; + cover.configure("test_cover"); + cover.traits_.set_supports_position(true); + + uint64_t callback_count = 0; + cover.add_on_state_callback([&callback_count]() { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + cover.position = static_cast<float>(i % 101) / 100.0f; + cover.publish_state(false); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CoverPublish_WithCallback); + +// --- CoverCall::perform() open/close cycle --- +// Measures the full call path: validation + control delegation. + +static void CoverCall_OpenClose(benchmark::State &state) { + BenchCover cover; + cover.configure("test_cover"); + cover.traits_.set_supports_position(true); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + if (i % 2 == 0) { + cover.make_call().set_command_open().perform(); + } else { + cover.make_call().set_command_close().perform(); + } + } + benchmark::DoNotOptimize(cover.position); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CoverCall_OpenClose); + +// --- CoverCall::perform() set position --- +// Measures the position-setting call path. + +static void CoverCall_SetPosition(benchmark::State &state) { + BenchCover cover; + cover.configure("test_cover"); + cover.traits_.set_supports_position(true); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float pos = static_cast<float>(i % 101) / 100.0f; + cover.make_call().set_position(pos).perform(); + } + benchmark::DoNotOptimize(cover.position); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CoverCall_SetPosition); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/cover/benchmark.yaml b/tests/benchmarks/components/cover/benchmark.yaml new file mode 100644 index 0000000000..477724be5a --- /dev/null +++ b/tests/benchmarks/components/cover/benchmark.yaml @@ -0,0 +1 @@ +cover: From 02e23eb386bd3fde73c34a41cebdf2b2a08b41af Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 07:33:10 -1000 Subject: [PATCH 1725/2030] [benchmark] Add light call and publish benchmarks (#15176) --- tests/benchmarks/components/light/__init__.py | 28 ++ .../components/light/bench_light_call.cpp | 253 ++++++++++++++++++ .../components/light/benchmark.yaml | 1 + 3 files changed, 282 insertions(+) create mode 100644 tests/benchmarks/components/light/__init__.py create mode 100644 tests/benchmarks/components/light/bench_light_call.cpp create mode 100644 tests/benchmarks/components/light/benchmark.yaml diff --git a/tests/benchmarks/components/light/__init__.py b/tests/benchmarks/components/light/__init__.py new file mode 100644 index 0000000000..233a3c246e --- /dev/null +++ b/tests/benchmarks/components/light/__init__.py @@ -0,0 +1,28 @@ +import esphome.codegen as cg +from esphome.components.light import generate_gamma_table +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + # Light benchmarks need USE_LIGHT_GAMMA_LUT defined and a gamma table + # with external linkage that the benchmark .cpp can reference. + manifest.enable_codegen() + original_to_code = manifest.to_code + + async def to_code(config): + await original_to_code(config) + cg.add_define("USE_LIGHT_GAMMA_LUT") + # Use the light component's own generate_gamma_table() so the + # benchmark stays in sync with any formula changes. + forward = generate_gamma_table(2.8) + values = ", ".join(f"0x{int(v):04X}" for v in forward) + # Use extern-visible (non-static) array so the benchmark .cpp + # can reference it via extern declaration. + cg.add_global( + cg.RawStatement( + f"extern const uint16_t bench_gamma_2_8_fwd[256] PROGMEM = {{{values}}};" + ) + ) + + to_code.priority = original_to_code.priority + manifest.to_code = to_code diff --git a/tests/benchmarks/components/light/bench_light_call.cpp b/tests/benchmarks/components/light/bench_light_call.cpp new file mode 100644 index 0000000000..c1ef0c425e --- /dev/null +++ b/tests/benchmarks/components/light/bench_light_call.cpp @@ -0,0 +1,253 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/light/light_output.h" +#include "esphome/components/light/light_state.h" + +// Gamma 2.8 forward LUT generated by the light component's Python codegen +// (see tests/benchmarks/components/light/__init__.py which calls generate_gamma_table()) +extern const uint16_t bench_gamma_2_8_fwd[256]; + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal LightOutput for benchmarking — no real hardware interaction. +class BenchLightOutput : public light::LightOutput { + public: + light::LightTraits get_traits() override { return this->traits_; } + void write_state(light::LightState * /*state*/) override {} + + light::LightTraits traits_; +}; + +// Test subclass to access protected configure_entity_() for benchmark setup. +class TestLightState : public light::LightState { + public: + using LightState::LightState; + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } +}; + +// Helper to create a configured RGBWW light state for benchmarks. +// Note: setup() is not called (no preferences backend), so save_remote_values_() +// is effectively a no-op. This benchmarks the call/validation path, not persistence. +static void setup_rgbww_light(BenchLightOutput &output, TestLightState &light) { + output.traits_.set_supported_color_modes({light::ColorMode::RGB_COLD_WARM_WHITE}); + output.traits_.set_min_mireds(153.0f); + output.traits_.set_max_mireds(500.0f); + light.configure("test_light"); + light.set_default_transition_length(0); + light.set_gamma_correct(2.8f); + light.set_gamma_table(bench_gamma_2_8_fwd); + light.set_restore_mode(light::LIGHT_ALWAYS_OFF); +} + +// --- LightCall::perform() with instant RGB color change (Home Assistant API path) --- +// Measures the full call path: validation, set_immediately_, publish, and save. +// HA sends color_mode explicitly since API 1.6. + +static void LightCall_RGBInstant(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + // Turn on first so subsequent calls are color changes + light.make_call().set_state(true).set_brightness(1.0f).set_color_brightness(1.0f).set_transition_length(0).perform(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float v = static_cast<float>(i % 256) / 255.0f; + light.make_call() + .set_color_mode(light::ColorMode::RGB_COLD_WARM_WHITE) + .set_red(v) + .set_green(1.0f - v) + .set_blue(v * 0.5f) + .set_transition_length(0) + .perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_RGBInstant); + +// --- LightCall::perform() turn on/off cycle (Home Assistant API path) --- +// HA sends color_mode explicitly since API 1.6, skipping compute_color_mode_(). + +static void LightCall_ToggleOnOff(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + light.make_call() + .set_state(i % 2 == 0) + .set_color_mode(light::ColorMode::RGB_COLD_WARM_WHITE) + .set_transition_length(0) + .perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_ToggleOnOff); + +// --- LightCall::perform() turn on/off via MQTT --- +// MQTT never sends color_mode, so compute_color_mode_() runs every call. + +static void LightCall_ToggleOnOff_MQTT(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + light.make_call().set_state(i % 2 == 0).set_transition_length(0).perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_ToggleOnOff_MQTT); + +// --- LightCall::perform() with color temperature via MQTT --- +// Exercises the transform_parameters_() path that converts color_temperature +// to cold/warm white fractions. MQTT never sends color_mode, so this also +// hits compute_color_mode_() every call. Modern HA avoids this path entirely +// by converting color temp to CW/WW client-side. + +static void LightCall_ColorTemperature_MQTT(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + light.make_call().set_state(true).set_brightness(1.0f).set_transition_length(0).perform(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + // Sweep through color temperature range + float ct = 153.0f + static_cast<float>(i % 348); + light.make_call().set_color_temperature(ct).set_transition_length(0).perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_ColorTemperature_MQTT); + +// --- LightCall::perform() with 1s transition (Home Assistant API path) --- +// Exercises start_transition_() which allocates a LightTransformer. +// This is the default HA path when transition_length > 0. + +static void LightCall_Transition(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + light.make_call().set_state(true).set_brightness(1.0f).set_transition_length(0).perform(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float v = static_cast<float>(i % 256) / 255.0f; + light.make_call() + .set_color_mode(light::ColorMode::RGB_COLD_WARM_WHITE) + .set_red(v) + .set_green(1.0f - v) + .set_blue(v * 0.5f) + .set_transition_length(1000) + .perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_Transition); + +// --- LightCall::perform() with cold/warm white (Home Assistant API path) --- +// Mirrors what modern HA sends: explicit color_mode with direct cold_white +// and warm_white values. HA converts color temp to CW/WW client-side for +// CWWW lights (API >= 1.6), so this is the primary HA path. + +static void LightCall_ColdWarmWhite(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + light.make_call().set_state(true).set_brightness(1.0f).set_transition_length(0).perform(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float frac = static_cast<float>(i % 256) / 255.0f; + light.make_call() + .set_color_mode(light::ColorMode::RGB_COLD_WARM_WHITE) + .set_cold_white(1.0f - frac) + .set_warm_white(frac) + .set_transition_length(0) + .perform(); + } + benchmark::DoNotOptimize(light.remote_values); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightCall_ColdWarmWhite); + +// --- LightState::publish_state() with a remote values listener --- +// Measures listener notification overhead. + +static void LightPublish_WithListener(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + struct TestListener : public light::LightRemoteValuesListener { + void on_light_remote_values_update() override { count_++; } + uint64_t count_{0}; + } listener; + light.add_remote_values_listener(&listener); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + light.publish_state(); + } + benchmark::DoNotOptimize(listener.count_); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightPublish_WithListener); + +// --- current_values_as_rgbww output conversion with gamma LUT --- +// Measures the output conversion path that real light drivers call +// from write_state() to get hardware PWM values, including gamma +// table lookups via the LUT generated by Python codegen. + +static void LightOutput_RGBWW(benchmark::State &state) { + BenchLightOutput output; + TestLightState light(&output); + setup_rgbww_light(output, light); + + light.make_call() + .set_state(true) + .set_brightness(0.8f) + .set_color_brightness(0.6f) + .set_red(1.0f) + .set_green(0.5f) + .set_blue(0.2f) + .set_cold_white(0.7f) + .set_warm_white(0.3f) + .set_transition_length(0) + .perform(); + + float r, g, b, cw, ww; + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + light.current_values_as_rgbww(&r, &g, &b, &cw, &ww); + } + benchmark::DoNotOptimize(r); + benchmark::DoNotOptimize(cw); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(LightOutput_RGBWW); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/light/benchmark.yaml b/tests/benchmarks/components/light/benchmark.yaml new file mode 100644 index 0000000000..2b7c938581 --- /dev/null +++ b/tests/benchmarks/components/light/benchmark.yaml @@ -0,0 +1 @@ +light: From c2456409bd4bde9b793a5c6c98bebbc18f62511d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Mar 2026 13:39:19 -0400 Subject: [PATCH 1726/2030] [core] Improve clean-all with no arguments (#15184) --- esphome/writer.py | 10 ++++++++ tests/unit_tests/test_writer.py | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/esphome/writer.py b/esphome/writer.py index 4aac16ffd4..06a2230118 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -476,6 +476,16 @@ def clean_all(configuration: list[str]): data_dirs.append(Path(env_data_dir)) if env_build_path := os.environ.get("ESPHOME_BUILD_PATH"): data_dirs.append(Path(env_build_path)) + if not data_dirs: + # No config files or known data dirs, check current directory + cwd_esphome = Path.cwd() / ".esphome" + if cwd_esphome.is_dir(): + data_dirs.append(cwd_esphome) + else: + _LOGGER.warning( + "No configuration files specified and no .esphome directory found in current directory. " + "Pass YAML files or a configuration directory to clean build artifacts." + ) # Clean build dir for dir in data_dirs: diff --git a/tests/unit_tests/test_writer.py b/tests/unit_tests/test_writer.py index 6ace38a7d7..940a394c08 100644 --- a/tests/unit_tests/test_writer.py +++ b/tests/unit_tests/test_writer.py @@ -990,6 +990,47 @@ def test_clean_all_ignores_empty_env_vars( assert marker.exists() +@patch("esphome.writer.CORE") +def test_clean_all_no_args_with_esphome_dir( + mock_core: MagicMock, + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test clean_all with no args cleans .esphome in cwd.""" + esphome_dir = tmp_path / ".esphome" + esphome_dir.mkdir() + (esphome_dir / "dummy.txt").write_text("x") + + from esphome.writer import clean_all + + with ( + caplog.at_level("INFO"), + patch("esphome.writer.Path.cwd", return_value=tmp_path), + ): + clean_all([]) + + assert esphome_dir.exists() + assert not (esphome_dir / "dummy.txt").exists() + + +@patch("esphome.writer.CORE") +def test_clean_all_no_args_no_esphome_dir( + mock_core: MagicMock, + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test clean_all with no args and no .esphome dir warns.""" + from esphome.writer import clean_all + + with ( + caplog.at_level("WARNING"), + patch("esphome.writer.Path.cwd", return_value=tmp_path), + ): + clean_all([]) + + assert "No configuration files specified" in caplog.text + + @patch("esphome.writer.CORE") def test_clean_all( mock_core: MagicMock, From bf89a191f06a4fea3c3b9014f1d46200c89fa2df Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 26 Mar 2026 13:39:35 -0400 Subject: [PATCH 1727/2030] [wifi] Guard coex_background_scan with CONFIG_SOC_WIFI_SUPPORTED (#15187) --- esphome/components/wifi/wifi_component_esp_idf.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index 1b80adc82e..d8b3db9667 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -989,9 +989,11 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { } // When scanning while connected (roaming), return to home channel between // each scanned channel to maintain the connection (helps with BLE/WiFi coexistence) +#ifdef CONFIG_SOC_WIFI_SUPPORTED if (this->roaming_state_ == RoamingState::SCANNING) { config.coex_background_scan = true; } +#endif esp_err_t err = esp_wifi_scan_start(&config, false); if (err != ESP_OK) { From d9ada4536cbcaacdba36ea43806753841e06d515 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Mar 2026 19:58:12 +0100 Subject: [PATCH 1728/2030] [nextion] Fix leading space in pressed color string commands (#15190) --- esphome/components/nextion/nextion_commands.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 2adf314a2e..4ddbfbee6a 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -106,7 +106,7 @@ void Nextion::set_component_pressed_foreground_color(const char *component, uint } void Nextion::set_component_pressed_foreground_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_foreground_color", " %s.pco2=%s", component, color); + this->add_no_result_to_queue_with_printf_("set_component_pressed_foreground_color", "%s.pco2=%s", component, color); } void Nextion::set_component_pressed_foreground_color(const char *component, Color color) { @@ -134,7 +134,7 @@ void Nextion::set_component_pressed_font_color(const char *component, uint16_t c } void Nextion::set_component_pressed_font_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", " %s.pco2=%s", component, color); + this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%s", component, color); } void Nextion::set_component_pressed_font_color(const char *component, Color color) { From 1edf952ddacb7a0ad4d7ea1d106bd340642e6c99 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 27 Mar 2026 04:59:06 +1000 Subject: [PATCH 1729/2030] [font] Add unit tests verifying correct processing of glyphs (#15178) --- tests/component_tests/font/.gitattributes | 2 + .../component_tests/font/NotoSans-Regular.ttf | Bin 0 -> 455188 bytes tests/component_tests/font/__init__.py | 0 tests/component_tests/font/test_font.py | 337 ++++++++++++++++++ tests/components/font/.gitattributes | 3 +- 5 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 tests/component_tests/font/.gitattributes create mode 100644 tests/component_tests/font/NotoSans-Regular.ttf create mode 100644 tests/component_tests/font/__init__.py create mode 100644 tests/component_tests/font/test_font.py diff --git a/tests/component_tests/font/.gitattributes b/tests/component_tests/font/.gitattributes new file mode 100644 index 0000000000..4df6726184 --- /dev/null +++ b/tests/component_tests/font/.gitattributes @@ -0,0 +1,2 @@ +*.pcf -text +*.ttf -text diff --git a/tests/component_tests/font/NotoSans-Regular.ttf b/tests/component_tests/font/NotoSans-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a1b8994edeacd70067de843a4691b15a0ce5921b GIT binary patch literal 455188 zcmZQzWME(rVq{=oVNh^)adrD}{qA!H21XqQ2G#@a0sg`BX718pU|@U0!0<}KJvh|K z#r#zk1H(ra1_rSP|6qNi9D%k_21fQ41_p+NkPtV=9f1;u8Q4CEFfcIwPtHv&I5hv? z69z{1CkzZ+ddX!a3U#vtO&Qo87%(s}mZTM==UQp>)iAI<T*AP>o130kT)@D<Ai%)( zK!bsSfg?SqGOg(74+929ArS_an?4z-i75h88ILirzD{6ZU@*(bNKNF~ETX}{`g#Tf z1A|INZb=1$u5lOx>+3xX3`TQu@{<$gjK5D|V3UhrU@+Q~n^;l6KS6+*fh|ykfq_9G zFEKZD+Vg!Y8Q20%7#P@M3i69fHhyJa#lRLmfq|i8YC%zIf!VCi1O~SEAoYJ47#Wxt z_!t<NqZk;N*Dx?K^f0I}*fKCOxG=;rFfueT%wS+-n8mPzfstVsqbCC+V<=-N10!QN z69WSylQ@$&10$0HlL7-HlLnIp10$0ylPv=ylLM0j10$0YlPd!wlRJ|a10$0UQzio= zQyx<x10z!@b0`BNa{@~%10%~KmSqf#EC*Q*GBC3oWjW5k$a0e93<D#}IaWaiMpjW) zQ3gg<3Dz(MM%EbC7zRexWY!c0M%FaeOa?~QY}Nt>M%EJ65(Y-rcGjs3jI7hyUNbPV zy<>aFz{vKIU7UfDU5Z_efsx&T-GzaX-GkkOfss9iy^w*Cy_LO#ftkINeKi9k`w{lb z42<m8*l#m1vfpRF&%nt3m>m?qFWKKPFtWd6|Hi<`{*(PD10x432P*?32Nwr710x47 z2Ok3?hX98V10#nhhZqARhct%`10#nUhdTo!hYyE810zQuM-T%eM+iqK10zQSM<fFy zM+`>{10zQqM?3=~M+!$e10zQ!M<xR!M+rwY10zQ*M=Jv(M;k{E0~1FtCm#bNrvRrg z10$yxrz8U-rwpeI10$yvry&C)r!l8710$y`r#Ay5ryr+310!b`XBYz`XAEaN10!cL zXEFmLXDVkZ10!cXXFdZXXAx%+10!b%X9WWzXBB5110!b-XD<UI=XA~)42+y}IOi}h za<1WA%fQIFo^w3|Bj-lWjSP&On>jZ#Fmi6^+|Izrxr=ib10&}i&OHo_oQFA&GB9#p z<GjYe$a#<R83QBd3(l7ejGV7I-!L$8o!~mbz{qut>ly<i*A1@w42)clxE?bwa=qeu z&A`a@p6fjWBX<LL0|O&>BX>6gGj|Vn4+A52FZTilX6}XDix?QW7jtiBVCLSzeV2im z`yTgw21f1&+z%O;xgT*qVqoNc#{G(ck^43G8wO_Xx7=?T7`fkZzhhwLe$T_gz{tbK z!_UCTBgCW0z{sP+qszd^qt9c=z{q37W5mGBW5r{`z{q3AW6!|I<G|y{z|7;s<Ho?q z<IdyGz|7;p<H5kl<INMyz|0fM6UxBI6UGz9z|0fQ6T`sBlfaX}z{r!#lgz-#lg3lb zz|2#^Q^LT=Q_9oMz|7OZ)4{;V)5X)pz{oR!XCeb5gAfBdg9?KVg9(EPgA;=jgBJrM z13SZKhA$lL9332;99<my85kK@7#JCYp)?Z%69XFq7Xu@sH3K74IaE{^N-KkD1_n^R zy}`i1@QZ<gaR&nvg9143F>p`gp2@(-J%@V}11t9q?%fPB+=sZ2Feq@J;6BNq%zcjg zB7-XT74EAHn%vj9uQO<K-{QW-pu>Ha`!0hn_e1W740_zJxnDErbARCez+k}ro%;`i zA@_eC76x-3HXdFETOI)(H3nB64IWK~7;wnOfkQTd$C$^GA(_X9$A%$`$CJmCA)CjK z$B!Y0CzL0KAr~BKr95doxeR4I`8>r8bv&g!<qXX{l{^g$Z9Gjp?F@Ykj12tTo4L1e zZ{^;`y`6`RhlfXo$Cf9Tr;w+Nr;4YJr<s9?L7p*~F@%8uTvjl#y<vO9z|8iJ?E?b~ z+i$kN4D9S2>|6|7>=Nu!47}{B>}m`G>|yL-3_{?XF3fe0>mGwRcO&-{1_|yx+y@zS zxQ}ulXE5SE&3%@^l=~9*B?b%bYuwiuEV*xR-(;}jzRi7y!G`-D_X7qy?nm6O7#z9Z zaKC5p;{M3}jlqxmFZVx&5FQ2|eugj}As$19G#)D+Ylb!+J01^)4jykFUxvv%{ya$x z(|FQ&+8I_cFf!<HPvxG)J)8S74<io~4+{?)4?7Ph4;K$N4-XG7j|`6-k35eek2)xH zc_MhSd2)I3c?x(6d5U;SdCGXoc`A9TcxrfRdFpuTc^Y_{c$#@ycv^Ydc-p~r9T$TM zLmmT*i<?gfgH&>5Q4WJtdQoaNgH%ppNgjg~0}BHK1H=FS49pA+;PRe1JGCf}K_oY^ zD4RhlH#;|*K@ThgQpN#M!N9`6%D~3J&cML{sz*5)xEQz@co=vYWb)rlG@5p1U(AI= zmvSzfTzPZ7?XJ_^M=xX;m>4)1m>9UEmoYFhhk@*5T*m*4Z5jVBjy3@v{x1SNV$(Ql z#M8t!i7jFK!oE&CjWa`R6Q_yTCiXiVZem~fU-7>ZPZPVtS;W!CQ6lyZ1UcF`CJ1N= z7;roin}!6Jh^L7yfx=B<$nXxQ2}mDEEvJ)s8U%`M;*0~?3e~ZMGXi8cX9i~mXB>!x zny^Id3kdSR5_>0h2ZTYTCTEe@G_fUOo5V%L-Nco|6U0S0Yq&DRMK~vkyK&tR7vX#& z?j~-+rNosXuEf>Eb%X1kc!Ic+IG;El?*r}#UOrwG-Xh)yyw5~ViA>|$BFZ7MM`Rk` zK9N&mJ)#_<90Hd_riq*q*~8Bw$|2Sx)*~`UWRAcY2oyO5atREBT*Utc41e+e65!zn zlc2B>PY`euR}z~hwnyxkz!{NgBGUw7Kv*D2WDm$Tu^xdl0+&Rd2;2}X68R=FN8}sG zW{`a%PXv2}%!KBE+#qyK=$gnkkQ;<P2+tDb5Pl(62I7hJfJ_wS5Sb&g2yEUSky9d1 zz-9=E3W@cI3W*AdN{Cj8o&c*yjwNI^EVf`Ya-3}v+XIKk#9$B{1E5$CdnfiqTnQ4U zpm2p_5ph)LCXRq0^&p%ejtcqUx^b~!W`cBsunE{ykSWmA1W8kHvOv5I0VOs-pm>k? zH4udG&`I$J5_%FFB(_P$N%Ba>fnkp1J~%ufr3Z&LQf^WyQmdr4NJlX+GA?6aWq{;F zeg**sK?W5DRR%Q%bp{OvO$IFnJqCRSBL-sz69!WTGX`@8O9m?jYX%zzTLwD@H-<=t zD25n@IEG|~T!vbPMusMaW`-7qR)#i)c7_gyPKGXqZiXI)UWQ2wQy8W)Ok<eNFoR(h z!+eGX4Eq@lG8|$!!f=e?1j8wYGYsb#E-+kVxWsUU;TppYhFc7G7(Ot3XZXeNhv6T? ze?|sICPrRHenvq?VMb*}RYrA2Q${mJb4CkBOGYb38%8@uCq@@WH^xxLD8^{U7{)lp zc*X?AM8;&sRK|41490B69L7Axe8vLCLdGJ-V#X52QpR$|3dUN-dd4Qk7RENlcE(P| z$&7Ou=P}M_T*kPZaV6s_#x;y<8P_vzX57iRi*YyO9>%?l`xy5#9%4Mrc!BXT<5R|u zjGq|4GyY`!#rT`?5943Pe~kZ`7?>EDn3$NESee+E*qJz)xR|(^gqcK`6qxLp9GF~~ z+?hO?f|){?!kEIDBA6nX5|~n$(wGXEN|`E{Dw(R8YMJVo>Y19DnweUe+L=0;x|w>J z`k5v$O=OzPG?i&O(@dt>Omms$Gc9IX!nBHM4bxhtbxfO>wlVEw+Rb#7=>*eBrt3^M znQk-PXL`)^l<7IsYo@nM@0mU_eP;T~^o{8|(@&<~On;gFGcz(XGqW<YGjlR?GxIX@ zGYc{cGmA2dGfOf{Gs`l|Gb=JHGix$yGwU+zGaE7+Gn+D-Gg~rSGutxTGrKaoGkY?7 zGy5|8GY2pSG6yjSGlwuIu$*E!&1T1D&*s49$mYc6%;v)8%I3!A&gQ}9$>zo8&E~`A z%htfw$kxQx%+|uz%GSr$&o+T=BHJvs*=%#z=CaLWo6oj@Z6Vttw#954*fz3lV%yBN zg>5U_Hn#0-57-{EJz{&z_Jr*z+cUQ3Y%kbevb|y#W*1=>Wfx-?XIEfXWLIKW=IG_< z<LKv@z%h|y631kYDI8Ndrg2Q?n8h)hV-Ck$j(HsOITmm%<XFV9m}3dYdXD29Cpb=V zT;aINagF0T#|@5~9Je@bbKK#$%W;q60mnm*M;vcC-f_I=_`vaz;}gd}j{lqtoQ#}I zoXngooUEK|oa~$&oSa-MxK?wm<yz0Rk-MHjn8E!25eCcuZy2opzhSWX|A=A!|3{3< z|Bo=L{y)N~{{IN0>Hjy3=KmitTK<2;`1Ai8#^3+nF#i4jhVlRZN6h~JA2A31f5aU8 z{}FS-|04`~3_J`X4E+C(FbMuX!l1+;!l3g14TA%N2txvc2t(8VHw?}H-!QcNf5XuF z{|!Ui|2GWn|KBhi`u~RE$p1GC$Ns-zbo&2>iT(c(Chq@7nE3x6VRHHZhUxGBH%$Nk zzhP$l|Av|Q{~Ko3|8JPt|G#18{QriT`~Mqe-v4iy`TxIR7X1H)S@{1Oj^6)|IQsrS z;^_bXh-1S4M;sIXKjN75{}IRJ|BpDP{C~tT_5UM|Y5yN_O#lCgW5)k;95er)W8mg^ z_x}yY`~TlKKKy^f@$vr~j!*yJaQyrKjg$5NH%_+y-#FR-f8*r%|BaLL|2GCHhTQ+( zn1ug-<Cy*b8^@gg-#F&}|Hd)z|2K~L|G#l8`2US#!~bs_8~=af*!2G!$L9avIJW%% z#&PBUH;$|Szj0jq|Bd7N|8E>O{(s}R`TrZot^eORZvX$rap(Uxj=TTAaoqd=jpP3R zZyb;Qf5YppH=Jz$-*B@3f5XY~{|zVS|2N?FiU<Q2g9sBFg9sBBg9rl?gDyi9gD-;y zg9w8zgAs%I|2GVl|GzO<{r`p(+iw_E|G!~W|Nn;3^#3=c*#5@&`~Nq_zyH5siS0LF z6H^$>|KDJ+{Qro->i;7KoBuZ$=KsIJsQmv1qw4<~jOzbyFq-~<#AyEi2BYQw8;n2y zKVtm-{}JQg|Bo2||G&ZP|NjPa;Qt%U!T)bCC;Y#`z{~&&UF-jEINtt$!@$a*%aF%$ zm?41U2txqJ`~QzP{{4T$zzFsS6N3^%0K-cLHwGq-_y3P@{QG|d%=!k3GX_=${{P<? z1pj|yV*me*iTnRICJ<kQA@~0q##jas#?=4c7<2xAV=Vgrh;bT&2$S&tH*7f!B5b(~ zB5ZjKB5e5#B5VZ=B5Z{WB5W%dMA-f@h_L-<5MgIv5MgIz5MgIx5MgHqrF6zv1}?^F z3|wqE3|wrv3|wq^3|wsa3|wpl3|wr53|wq07`WK}F>tZ{XW(LIVBlhBWZ+_FV&GzD zX5eBF1f?RzSO$K^X$<_J)Wnv<z|WS;z|WS)z|WS?z|U5|z|U65z|XdVfuHRk13%k; z27Y!127Y!%27Y!X27Y#C27U%M#-jh{7)$>@Vr=;Th;j1&H%touA2Hegf5RZk!2kao zgW&&jjB)?pFed(g!<hX45o5;xH;noJzcCj4zrk4e{}E&H|8I=t{~s~7gG1{a6Zijf zO#J`PF**Ey#B%!oBev)N->|*-|At-o|08yh|Bo0LL7~PV2g~K)@QnL^gE8^{4RE+- z{J#MX+ur}*z+sD&oAHM6^Zz&4Ui`m-E3Dc1|9@i_`2UR|mqFnFImTE9ImU|rZy0O- ze`Bou|Aw*Q{~N}Z|KAw9|G#1E`TvHo@BbUd{{L?nC;WfIIPw2C#!3I*Fi!dZjd3d2 zRdS5e|9@kg@&66u%>UmQXZ`=i#Q6Ul6Vv~5Ow9k!vDy89!)E{g4V%ONH*Ajo->^CT zf5Ybd{|%eV|2J%|;FKcAmdhZ=md7B+md_x^R=^;~R>&a7R`vf4TlN1pY&HMiu+{#5 z!&dkI4O{*HH*9VHzp=Id|Hjtw{~KH9|8Hzv|G%+y|Nq9;^Zy%L@BeRXlm35WoBaP9 z+m!#`*rxvf#y0K$H@4~jzp>5u|BY?t|8H!I{=Z>c{QnKx3I;j0RsY|xt^WUpZO#90 zY-|62V_WzC8{7K--`F<%f5W!%{~NYV|KG4}{{Mz;%l|iQTmQdd+xGtr+xGu&*e?A4 z#&+@lH?~Xvzp-8Z|Bda+|8Hzp|9@k<_Wv8(_5a`49{hj9_VE83wnzWpus#0&hV9A! zH*8P;zhQg!{|(ze206C>407xY407y@407yD407zu407z;|G%;G{Qt(z`~Mp|-~Vsy zg8#p<3;qAbF8%)-yUhP@?6UvAvCIAc#xDQ=8#qV4VGsnD?r)g5|G#14|Nn+T7#xS7 z_yffoEY3i2HRJyqcs#(u6&4P#Fo5|P>RtwE2G;*a7`Xl)VXOeBif@ed|KBin{(r;R z{r?*@ReWRY|Njk~Dkgzbz&9qg|3{d({vTnp`~Qv2{{J_&s{h~Es==ZDjcxJ&Z)~gn ze`8w>4&iTX8~=Y}d;I?!+mrv_7#Kl0hQXMD|NkQff&U=CJ%alNlp4`}G?_sJl;W5e z|G!~k`u~QB85|amn7IExV&eb*2<}^4sSXwj=&1`=sNhNocw(A?iRs<{H%uQuzF}bf z|Av9<{~N}Y|GzOF`2U89?f)AluK#bC!v23_O8EbVY5xB=Obh?NVOskC4b$@fZ<x0H zf5Wu%|2L-H|GzQq{r`>WE~utq;QxPvLGb?##yS7rFfRW8hH>ftH;l{wKVn?@{|)2X z|8E%A|9``{;r|=PE&tyz?*9LXanJupjQjq-VLbf*4I`*MaQ6Qj#w-8dFn$Dw)(s}^ z|2LTU|KDH=`~QY1{Qn!Kxc_gMQvQEqO8ftfss8^PrpEtom^%NzVVe5?5!3YlkC<lu zf5bHV{~M;c|KBjJ`u~P$-TyaC>%lI4!?gSV8>YSg-!L8h|Ay)K|2Irm|G#0n{{Iov z&Hs;>ZvTJ8^z{E5rsx0PFunc%hUxwPH%uTmeER=}>HGgTOuzrXVfyp`4XgP7Hw>V< zNQC1pxNI!=e}jPqToO0^f5Z6p|0AZv|KAwc84LdJ0+-Vz|Bo=X{C~r^_x}x!_uv-B z4F*QWg8z>gSQ)J0CG!!+;{R_LPeAj{BL>0$kC@p1!_x`_BiK|a2LAuM7zF?CVq6Rk z(Ho3w|36~f^8XPdYN+jE;{LyjiU0pDrm+7vz@fJ8|08H9++f=M{|3|E|2LRk{=dQW z`u`24kN+PrfqeP<|0B2$8JSLjYF?(O|KAwY7+C*5V&MA!h;h#UM~sUYj2M^xe*})Z z1OIO@9{&G`@%H~Wj1T_5VSEfuHIJCM{y$<$_<w^b<^Ln5wEvHoI{!an>Vn46wEu6I zrvHD#G!q<0kC^6xQ`QZp1>n?mgJ}^sW!+%f`u`2n-Tyb3?t$au5!1W>kC@*7f5i0R z|0AaF{~s~^`2U814dyZ?w*L@YVX0Y*f%X3e2Cn}b80Y*y2X*r~#@+vyF&_ATgz@nI zbBwqD-+;RL1{2%=4NP4BH!vmqKf;vqe-~5Q|6NR-|IaaX{lCF9_5U)aY5#99P5*z6 zY3BcPOmqLAW19E>2GjiiN1$##0(SG#|BslKfpf+qrWIg69D(}b2-FYDnBM)r!Sw$B zGNupzZ!mrTe~#(L{~HXF46OfmF>w9g#d!PwIjD=yF|qyM#l-c07gON>H%zJj-!P^B zf5Vjj{|!^u|8q>!{-0x-@&66etp9JA=KVhhb_FQZK(>Qy28A3b)ZYEy#q{C-E~X#< z&oS_U^CKuPg7Vy9q&$SkJKvaQ{{IHfH?Z{o9Tdild;dRTd;w0|H<+UTzhO%J|Ay)3 z|8ESSFovZINIu{F{|F-_O}qi8i97$lF+TYJ4U{ezzy1f6ypUKzO&cIzf%5MWCP><V zg)_)^pi&2vHoh?}{0~YS-<Y=i2c?Z~OgH|2W4iVK8`B+d$pcC!-<aP1zX2}K-v7S= zD$~IE7L-ne8Cd_HW8ebE`WwbOkd(^!6`WenF>!%o`VH82M7X|Ty7B)F)2;t+nC|?4 z1CBXRtbt6^hNU`iy4nrS+i$@BzWx6ZGzK5RQ)D2x^aSMvP)vf#El_NJW6J;kjj8MZ zBc`eUK{kWRt~X3G{)6HG6tmx$=KX)fH2*)y@1Rl_<abcXdk&h$&Oy@{C@hfk3CREF zm>~WKr7uwHZ7(P%GrnMu1Lv1-3|!!t_{IdHVflp_9Lp#Ee`9?6{~H4vsI+2y@&6Iy z+y6(HqW_;`O8kG0>D2#63@l)Epi&N!5<nu081g`(Oz{kI;8Kc-5md&4QV1hc)c-dO z67V_!RI`A}e^8k1!zkasp_J>OaG4Gck8j}e98{Jg*EXOs99mv8fZ`WYcb)(LjS-aU z?*0D;O>vMqtl|GRraAw=F|Gdpjp^8b)YS9r|2L)=|G$A#4yYys#qSLUE^r<82wc{I z>Mn@8A$8ROaD4?S_aJ574JIyV9R;c>Q~tkUO8fr?TtDF|`yh1`to#GTF{HkN)T*d; z)!qMZFzO~)8ORDsaquz#n)ex)7#A_*F`Z%%VPFRJp5T2c5YGl$4}D``0@pzE|ASaM z3?dBH3`PvB3{Vy`3j-Ik90M1#0RtBU3j^o>M+`~~pjz)7sMpNE2;woYF@SoZ5OG-j z_J)%MTr;+VY=_o^Zx~C!^(3hORr>!MsJ>)U`2UT8g)#a6H*nnt>dSz}2H3zNkp2p& zuL9Ef4czhq)tYa>eLhe>{S5;v)}A^e*P8#|7=*yBG_+cjqxb(ej=uljIQsv8<CyUO z8^^@|-#8}y|Hd)-|2K{)|G#le{r`<)+W&7H)Bk_tnDPG&$4pRN4-LB;48jcj|2HrQ z{@=jF{(l1#_x}w{{QozQIQDRvW9I+M-1YyzF(@#A+QVq=V-j8XjbrBjZyfKyV;J8! zKK}p4@#+6Jj{pC^aWee>#>x2q8z<BMZ=B3H#xxi?S^j@x5QVk-VC_BVxX4HJaS<Hm zVvI>}ZTJrwDZuW#HynNc-*EK*f5S21{~L~p|KD&-`u~Pw^8Ys+Q~tl<nEL+>$F%=% zIHv!90}FppY=Xm!nd9yMZ(M8sKjN<c{}I#^hqN=9*#E=Zh#bBD$ua*8*nB3gHUB}Z zHw==r9^(P|i2>O^pj3UB!G_}qgAD^a2b9Ih`X3`~83Z}r{eJ|?e;gnFKjQfK{}IP0 z$S4WN|Nn0|8UDZFWc>ezlj;8(PUiohd<YuNdc?{0{}Ctq|3{o0{~vLJ@-Y*~VFo#l zBMfp3nk4!4Fhdl_5r!yo#<e)!{lCHS;r|VekN<CQeENTb<KO>B9RL46;$-;$h?DXE zBTlCOk2snCKjLKle}j|l{|!#||2H@}{@>u_{C|T%faBf&%iw(Y;s0fhkN+=oeENSG zY67OOS^s14v84!TZqDX|`vZnZh9J<CA3ps54L(^?<o<tysYbA1B7=|q51L`e=`5HJ zU^GsJG?gIVc4A}o{}FT#fWqZJXml1`0?Plt3(5e^INxAkK;|Q4kXWEqQAk`&CN8(a zd=H}$Ix$5U7(niZsrdg0#zLmC=|YwVv2nQtBu6^_|ArVl85pQ*E2cY<%_r=l|KD(_ zK^8}5W7<dq5zwj_h_MJ3gij|DzmL&n(fKe(;u43+qtc|QM%9bX!_4dGDv<dE^EHxU z<n)CkjLein<_tGBa@m97H-hCKh7NoJG)enJ#2=`%hu81;9Ed6R{~NOTpfVAJG1Vc; z@c(a+bzoJA)M`O3uaL`rWH!W<|K}JOK$yXZf#LrnOnHbZbP^K3Al3hGpynb74{Rcm zCWt7K0G#>%(f<t)4t5{n%I~<uA!ebI*v&>)MTk!wQy{jG=6;Bt!A%Y|A5k+lNsXDI z7FOu~8&LNnN_+$h-GNl#lk3O-H;7AF|DQukUMjeiG$Sy51}V>BrV!_TnCihmWBLf2 ztBCU#F{*H@!7YRAB9JN&Mo$3{F=UmfY(ny=s&Vm1GX=kDNKFrFpZtIH|J?s0*lK!k zJK-G6H6R|0jg1DGh;9nVe307z-%wL3NDLFh+7zU;*kPvN_bp5nh$hA*Aa#Qk6PIW3 zyB@b0gkl+CE-1bcJaiWE@qw-r#)p}J=~mQKhR+@UK`R!)2I5FlMqo)W0aEe*5zJPQ z(Em61%m%4I!7#H>Yd4rEic&BKw+vXCJOU9m{~!Io@&DWZUH^~3Q@jnxOo$IbJ_Grf zfeR!C8oBv@gaP7m2ni7e^_Eb>WEX=7SRYg#kzQadWLc;pC<W><fH0Jci-Ls<sylG^ zK5@(7vVmlA%rr={5d*3L66X*nfMOoP!bSeS0gFq73Wy1a)P<-4K{A-?5jqhnA!4xf z0n!H%fsp^-AWZ*%<NpSH?)-n`|2ar|4Q3k1448@V^bYPJgH-(A1yT=E1H%6wfo(!f zUmyvRFvK>HOOUleL?I%O+7DR-B90gz0P#WfFNg+VP>F+ZJ#xswOaYA%fJPmVRe^NE zFhZPAngz+@4r7ok%uHPL|8J0Z2Ztu8q=1fPfb@c7Kp2-^usFCp0<&O*8;k*=VZMg& z7#JAP<l*9EGcasGH;JGd(KRq&>cCJ!oB*oZK%t6VA7(g%bpAhrDGt*Ql83X8Ffb5N zD#Mhc(GZg$B$^ZvTu2TftdLmq@u|ZTet2il&|QbfVdyfX@JTfVpU*JuB~3M^euxO} z^aGK{B$4eUtQ&XiBbQ6aY)l(*i{OrL+<Gu&h%*J*-<W0$pa_L^9J0$P^CNM(L8?F) z)E=dt-N+{4W)q(yAufcN1geiAENYMtlmDMXP4f^@i22BDhzN`XwR7O?M<5<3?Sf1~ z>H&aiY52T1NDU~Y!L5!B|BpcUa5KQQIVcw+#Ic3Z|2H5t5M3aZu+{)rL<DR;xO|1Q z@35HwRtY7bZ8L`d%b)@%6v#&?0z-@gial6pL1=7kZJ4J(s<F@RfMOM)3Stt3k7^z$ zJ|N<_Nr)}j<?+cubRfF~B7%*CnFC5`*yKqUgPBNJC!rKa*aX}vaHmJmC^2q*=rY8G zBDyYgJ}ey|hYd0tT|M!9kUvrKHM&+h^ua+^LVQD9j1s2`WGX7g)CY+jP#Azzg4_TR z0rQaNk|7}kk^8?3)TRcFt3vvzAhj?IQ3v87=TC?}kSGNIKL?WqsRx+^5eJbV8B}+| zTnCaR9TQuN5o-%5j8I(xOPdf;nA_3Sp_dQ;Z$QVSAlgt!NG%C60TezcQlMH6w4N0# z2vz}_Ek_y00!u+osDUz(DPsMJtcTuga^3j<94JHxyB3rlLFtUJ%0aGz>SG3^`<L9f z0=1q%wvnqJG*Sf8PY4s2B4Dn8nMSNGnEH`OBgY(SDNA1HA)ALkJYi)lepRH%qLty$ znL$i{fJzRSx&LqAa|fblf~^c^fS1o8JHWFU;GP7`Y{E21A9hu!e!;E=B1*hUi2A`z z5}$sM{ee3i5vq`59U+R$!nRHgVlr|)14{`Y84yM`fl@Zay#H_TrAb_Npz1;PEvmmz z)geqHFXR#W2LtQ>8&Inj<`PKD7B*`S6Gf&$;SGyVWN~8H<mv<Um=WefLLD|!fe=S! zk(<ZK)rV?3ZXT|*gj)ywWk7L^(^kY>2z7gi)Ley)aM>VeDPj*vNGgWN;SFzy5)w(& z9s$05_rDHiG;;X|6GNr3rCk!-4qcakY9=u}gd0JsvAYwWJMhUN&&YyIM__!RhEN4# zp}G+!icBNNII=i|4RIr=ET(k{1hJ1a65@7<8xeg5%$NYx`XJ082MSkAdF-}A)PYhL zXx$pJ8c=wEOoEAl)Zp9K1sZFHxRREk2nh|Cn<%827?v=wGO#i*FmQoR-(}!u5M*Ft zP+?GEU}aEa&|qK#pRLHrV8md;z|COJV9UVA;KJa_Aj;su;K?A);LYI8AjuHG5X>OO z5XunBAjc5S5Y8aa5Xlh3pumvJkjtRLP|Hxupvut1(9594Fo|IjgAv0Nh8YaT46_&( zFjz1wVpzdo&#;PNErT1wCWcK6UJP3pb})D|>|)r(5WujX;RHh<!zqSS4ABf{7|t-n zFq~sJ#}LbKf#DKE9K#icy9|j8&l#RGWHWqc_|A~S@RQ*eLoUM~hCdAX4F4Dz7z!Af z7?~J~8Ce-w8A=%08QB?18Mzp_7|IxV7)2P$8O0dI7#bKQ7$q1Q8KoGd7@8QB88sQ2 z8MPU;8M+vC8Fd-D8TA?U8G0BE84VeF8I2i@8TuGa8Lb%l8EqJC7^X7XG1@UqV{~G4 zW0(#;A$$&FBx4-IT+qpm42v0488aA`GUhPmFsx+EW6Wb%1v=f4VKrkhV==>8#!|)# zhINcpjMWUA7;7188MZLiGuAU~Wo%|_X4uBq%Gk=Vow1X#lVJyAH)A)$PR3rwUWQ$a z{fzw#yBQ}jPGZ=@IE`@{!(PT2j58SaG0tI}$FQGqG2?QELyRjKS27%DT+O(a;RNG) z#tjUo88<U-W;n~ZopC$EImVrgdl=4x&WU8W%y@|LFvC^Gqm0KHt}~uwJjrm2@eJd6 zhTDvn880*3XS~jMo#6rFO~#uH4;gPW-e-8k_=xc_!*j-`jL#WfGQMPd&G3ftBjZ<w z_l)0}m>Iq>u`;nUGBR;8aWk@jPLyP12c415$O$?Zoso;lnaP!r8+0x@BOj9=lOLlH zQvg#4qcBq#Qxu~FQw&oKqbyS#QyillQzBCVqdZe7Qw^g&Q$157qd8MEQy-%h(<G+J zjBZR*nHDg5FfC<T!5G4{ifJ`t1k*aE^^8$Wo0v8;#xQMT+Rhlqw3BHMV*=AYrhSYl zOb3{bGo~_~XS&0f%XFXV0b@1OW2P63wM?&>zA!d3{b2gR*vs^rS%tBWS(Dk3aR;+A zvoqsGW>@AA#!Jiz%!!PTK&M7BK4G(C^JRR-7R46L_>C=#t(x%%TLW7w6Bk<_+e9V- zwpnb8nMBx@v8`s3W81)XkV%E@1lxHgGqxLSubJ%FKC*pg3S#@k_KPW$?H@ZkQy4ox zy8u%HyD+;rQxdxZy9!e}M;k{QQw~Qj$8@G#j@cYbm?}7qa-3mm;<&<bkEx5}5yvB@ zsT}V(-Z4$%_`va(X*$P$PG+X1oUEL@Oslw-axG=r%(a|rInx%dbzJM1wlXj=UIOQB zMR49$WZ-AuXRu)qU=U!iW)Nf$WUv9}b7lrL1~mq426YB?1{MYl1`P&Q20aEn24@C+ z27LxC1|tR|1{MZm24jX$@Oj=W4CV~x3?>W~3>FOh;FDI>8LSzs8Jrnx7;G4%8EnDO zg~5e^iNTY>lOX_HMldl1Fa$C%fy)Rha2a6$K9`l7A(|nY!G$4)A%=k)TweHr%L`wI zCWdwfW`+)i4hB|+PKHhfZH6v}UItch3Bm#{L0A}OG0b9MVVKP@kAa_IKEr$lX@&(1 z3m8Hf7BMVmU}D(Mu%CgO;UL3725yE!42Kw)84fcXW?*7C!f=Fvnc*nIQ3fW4V+_X_ zm>G^U9A{u+IKgm&K^t7wXoJfdZE#tm&2WL?0s{-fMTUzEfee=zE-|n$Tw%Dvz{+rq z;Ti)g!wrTT46F>d7;Z7JGTdRf!@vqIkC?#aku$?jhMx>B48ItDF=&BHB`t=34F4Fk z82&T-X9#2j9bv5nE}^u*B@`35gkl1hP)v+Gj64jW6J>cBSQz;k`59Ok1sMeySQv#F zg&A1EC6^Vr<gx;nTvm+AjLHlqj4F&O3<iv<jH(PKjB1Q(3<iwqjOq*~j2es@3<ivv zjG7Gm;L?pBT)OdtOE-RS>BbK(-S`<z8BH0~8O<2Y7`PeD8O<4_87&ws7`PcN87 z8Lb$t7;M31pDnoTvt@K*bYfs;bY^sBU}AJ(bYWm+bYpa5U;&qgoQ#o-kqlgnQH)Ux z;*8OZ(F}ZyF^n+`0*tYYu?#$nag1>coQw&K2@K(kiHwO1oQ$cAsSM(bX^d$MT#V_A z=?r0v8H^bWoZvE499)KmFcvTtFoZJ}G8QuMflJab#!|*o1_8!0#xe#j#&X7T20q3L z#tH^e#wx}t1`)<;#%cyea0x34E@Az_C9DXzgk=Pmu>Rl@RsvkYN`On)2yh820WM*A zz$L5%;~d603~G#X8Rs&nGR|Y1$6&~~m~knC8sjp?Wek#x%Ndt5$b(B>W5(5ts~L<K z*D$VOP-R@pxRybPaXsUD21&*Zj2jq?z-6%{xGd&n+{w6;A((L&<1Pk6#@&p&8B`hf zFz#WHXWYlQk3o`gKjVG|A;v?DhZuwy4>KNSP-8sGc$7hn@fhQA23~M^?ZkM7@eG3; z<5|YD41$d37|$`tGM;BV&maXZ!KJ_@I2*VGXJfq0c$-0v@ebo11{ub?jCUE>81FIO zV~}FJ&v>6fkns`YBL+dn$Bd5|R2ZK!K4nm0e8%{kfsOGc<4Xov##fB57=jpIGrne! z1Dz?%pu+f>@iRjZ;}^y+3{s3=8NV{fFn(wJ&Y;TpgYgH09OF;MpA71ZzZicpa5Mg9 z{LP@w_=oWi12^Me#=i{ejQ<$_F>o{fXZ+6~4LbUtft!huiJ8F~bRsc>A`?3kJA)1A zTw(@ACT=Ef1{)?}CSe9YCJ`nP247H(!XN;uQ5g7`oSB>%n3!CcTo{;{T$x-Mn3&v| z+!-{PJeWKfl$bo3JQ*~YyqLTg6hQS2gDg`3Qvd@mQy^0yg9TF%QxJnUQ!rC7g9=j! zQwW10Qy5bigE3P$Q#gYcQv_24gE3PiQzU~IQxsDagD0qdV(<jjPYgy(iA;$MY)nZ^ zNesM9$xO)%Y)mOkDGc&VsZ6O17EEbOX$<mA=}hSi7EBpTnG7;aSxi|ByiD0l*$iw< zIZQbWyiB=FxeRPfc}#f>yiEB_`3x3J1xy7DhD@bQr3^w$WlUuZf=uO1<qY0T6-*Tj zDomA3l?=g5RZLY3Y)sWm)eLq_HB2=O9!&L2^$g}r4NMIT`b>>XjSNOi%}mV<=1eV2 zEe!fhtxT;9l1yz(Z46RO?M&?ql1v>;9Sl-TolKn!l1yDpT?|r8-AvsKLQFkOJq&_O zy-d9fc1(RteGGC;lb9wkurW<$n#^FxG?i&8gDTTBrfCdvOw*aBGq^L&V4A_;#x#>@ zCWAZEET&luZcMY8W;2*G&0(6upwBdyX)c2h(>$hm41!GandUPHF)d(Pz#z!9lxZo0 zE7LNjWel=R%bAulxH7F^TEQU8w2EmJgCx^xrqv8mOzW7|F$giOXIjr7$h3)R6N3=b zW~R*yf=t_(wlN4XZD-ofAjq_nX(xj*(=Mi63{FhDnRYW6Gwos8!{7v}?-^v74lo^H zkYzf^bdZ6U=@8Q)1~#U{OothGnT{|WVPIoA%5;=LlIa-JF$O87<4ngHjF`?dooC=> zy1;aSfsN@R(?teerb|qh7}%IDGhJrjWxB$2g@KLfD$`X4UZ!hI*BIECt}|U{kY~EV zbb~>L=_b=n26?7iOt%<hm~J!OW{_vP!*qv1hUq@jeFjyg2TTtb<d_~aJ!Y_DdcyRC z!Gq~3(^Cd>re{pg81$K*Gd*XJWO~8$f<d3@HPdSbGp098Zy5BL-ZH&qFk^bh^o~J~ z={?hX1|g;oOdl8onLaXoWH4j;#Po?lkLfehX9hE-FHBz;^gt~b20f<VOurd~nEo*R zVGv~c%k-Clndu+XKL#eI|4jcGn3+LWATTjAGBYwTGcz$WF)%SRg9Mpbm{}N@m|2-w z8JL;bnAsSZnAw@x8JL+lm^m1jm^qm_8JL;5n7J63n7Ns`8JL-Qn0XkOn0c9b8JL;* znE4o(nE9Fc8JL*`m<1S^m<5>y8JL-cn1vXan1z{z8JL+xm_-<vm_?aI8CaRcnZ+4c znI)Me8CaR6nWY(6nPr(}8CaR+ndKQ+nH8B88CaQ>nUxt>nKhX;8CaOLnY9^Mn01+T z8CaP0ne`c1m<^c?8CaN&nT;7(m`#~Y8CaOjnavqAnJt(t7?hYTnJpPKnXQ<u7?hZ; znXMT#nQfSD7?hZ8nQa*~neCYE7?hapne7=gnH`uN7?hYDnH?GUL9IOoer8u@R|XAc zH)b~m1!i|<cLoh+4`vSr1!hlXPX-NUFJ><W1!iw%Zw3u!A7&p01!iAnUj_|kKW0A$ z1!jL{e+Fsh0OkM&ZstJdKn7{%Am$(jZsuU-U<PUC5atjDZsr8$1O^l4MCL>W15j&{ zfe&;FIfE#h1Dh)YJDVGuF9Rp2Wyv7Imc^FMz{r-vR>;7^R>W4xz{OU@R?Q#*YHKox zgW8%5d~CDW7BUEc&LC$HWn0F!oI!+b1=~snMz&RKs~IFf=aMssvTb79&cM#LgKa+p zBijMCgA5{|_9z1*+YPq+42+<&${E<%9<e=P5M_JH_Kbm@?K#^k22Qru;G2X#vVCR{ z0ku{c7}@@@Gc)k8v#_%>aDm#a3=-_Z>|zXj?BeX=3?ZO1%^Ac&r<yYeu&c1EfN$|> zV+a7XVj09ZW^*iHQ07?3v4nwx<0!{51|QIA<_r!TCpk_s*mIoXIK|+=ahl@{gFUE? z%fJC@<1%o7+PDms93MD7F<5eZ=J?AX3~K2z=yI}hax&;}a&hu9n1b574341oE`uYe zz02Upz{JD@Ztq%w+q+f_JPbSx_TW~p4pOUE2i)rA1h;xw8MHtr7=qiltl-uyE4X!Q z1a95(fLpgp;C8JfxK(S*;K1O(V9x+*-Lf;dGPp8`Ft{;zFff8!y3!0@3|<Uc;P$Qv zgCB!Gg9y0Q%f=AI5X8X95X=zFz{U{55W>I+ZU?h5gfWCMSb|%_8VnH(5e#hLezO2W zEJG}VDMJE70)sucP3!}16MKW(#GK$ZaUi%&%nEJ?voe6%!K~nRFb}vLEXlBlVG#o( z!(xUN4D1Xm8P+l|f_v4B;9fN&!)}Is3~b=`u>ivXh64;D;8wB#xRuNaZY8sWTgjZ@ zRx&%dmCOllC9{KD$*c?~8BQ`Vg4@ch45t}RGcbZ%%&ZJ&8O|~=g4@lk4CfinGcbbN z&5R6}87?z0GF)Z2%D~8Qo#8qIBg0LGn+%K$w;66TFf!a_xXZxEaF5|011rOQhWiX! z3=bF{Ft9Q_WO&G+#qfv$bWZAHhQ|zA3{M!IFt9Q_Wq8V<1#V}HF#KTn!5{)|XR|T< zX86q@!tj^jFM|lUg)PF!$jHbb0&ZKgf!o$>;8ryoBQGN_11lpRBOe1JxNXhKD8MMd zzzA+(voZ=X3NbK3+u0(FA`Fb+);1fswavyT!zjaG$*91nz+ee(a~px%+#29Ew-LC_ ztpRRx8-d&08sIiJ52F^N76Ti&<;}yW!>Gf+25x`zFzPYtF|dJK;XI56j0OyB;I=pq zqY<MK0~@$S&ckTJXu`k-ZkH>8+vNh_cDW?DT`mA_mrFw1<<^YW45rZ5xh<nDgDJF) zZqI1XU<z)jbAnsy?BJGqAfqdzD+4>Yz0S($&gjm-$mq%F$zTa?o%4fR=f>c6xiPq1 z9sq8O8-v^80pRwxGPt#^3~p_6GgdNIGH8R_+(L|?Hn%2Y4Py-h6S(Eg4Q_e+GBz?c zGH8R_-$LN_w<cp7V;h4IV+UgggAlka?h9^<b2IiZ_Aq#YTjX|(eT@AK+>8?#Cop(2 zPGp?Ozyxlcb2Cn1oXWriZlm)vPG_9Xzyxlob2H9loW;NdZm-LOTk3p_iy0R)$T2Qu zT*@F1ZmAo9Tk3}3*0~(GbuIyJohveKVcfzX2X3A7f!pPL;C8tmxLs}lZkJ0i9$-Ac zpa5=>%QGHhJjS31Zi~w@o@PA5zzlASi-X(ZT;R627~=)T3k>><7a1=zFf(3Zyuu*P zc$M)Q12edF&c%3x@g@T^<1NNp3|!zgx(v9Dt_N<TbAj9FV&FD9Gvfos2MoH54;ddZ zFoRp_GK^0cpE58rK4W~wpwIZ6@i_xCxV_E=Zm-*b+w07XZy4V&a4~*l{Kz2A_=)io z12eeoZUb(+GlSdidW_!~zcDa_+wRQZw!0Fz?JfXryDKq*+U^42w!0Fz?JfXryGue_ z?QBeJ3|8P)yABf<6BmOOxYe%1#LvXfpaX8Z`+(c--r!cdGPu>w25z-;f?MtE;8r^; zxYf=GZng7(TkUM%Ry!AyKa)QLGq~-}2X4EYgWK-vOrcDn49wtGyCJyME)H(5Gc(09 z#WFC1Tk48T2}}tL3gDJHAGoE?1#YQ(fLrS3OrVy!2e_qf&XmEF!NA9q$&|^!1#YkN zf!pg`;PyHnxV_E=Zm;u!+w11w_BtO^AyXj(7r4F73~sNhgWKyi;FdZwxTUVnRL4}u zzzlAwOMqMIV&Im#B2yDn6N5gurOpg)qcels=<47$x(&FEE)Q;_%Ya+w%;0u8Gt&g7 z2@K3k6PYG5@PXUtT;Mi3AJY`3DGXfTmbxFfr7nZFr7i((sf&SI>hj>0x(v9bt^jVS z>oP55TF9Wlw1{aDgD%q&rX>u_NNsl)q_(>Yxa}?hZo7*ytz}xvzzlA|%Yj?);!GQv zHZm}STky<GTbQ;mC@^hh+RC5{ZpSl&+wq3rcDyXO9d8J3$ICM9W!lSNh}4?r0=MR! z!L4~&aBJQf+?tmKx8^0lt$8tUYhID*1k(uyeWo)^XBe27&M}>1U<SAE`M~XaE^zyv z58S@z0=Mt^!0mf3aQj{n+`iWbx9<(W?R!0N``!TDzSje{?+w81dp)MROm`U+nC>y% zW6%Y+@|l?)F+E~n2DkOq!L57=a4TO7+{%{#xAMi9UNXI8aAJDJ^ooHC+~RivxA?ih zEq+IEi{Am<;&%kM_#MD4emQW9UmV=lXJ-1!^p$~+=^N8G1}>)WOy3#g!L5H8re93I z7`VWF06B0UKpfl$-~{&p*ui}OPH-Q99oz@t1or{h!F>Qua36pj+y~$U_W{_!eE?2y zAAlX)2jB$v0ocKP08VfpfSnoC2jB$v0ocKP08VfpfF0Zi-~{&p*ui}OPH-Q9omq@o zjDe9^f?0xrky(maih+??hFOMzky(yej)9R`fmwlpky(jZiGh(>g;|Ax5!?r0W!7TW zVqjzj^#oX%b(nP+7{UDkR%ShBJqAW_uYi@=fZ2e75!^RmWj10qVqgUK5LlT_m`xZM z!TkhQW;13p21amiffd|aU<CITSi!voMsRO|72I231oswL!Mz1WaBqPX+*@D-_ZE1V zotT{%*uZ@T9%dJ27X~(P&w&Trb6^Aa9C*Mz2R3lefd|}kU<3CYc)&deHgL~@2i$XD z1NR&x!9527aL+*!+;b2B_Z%d_JqH1B&%p@XbI@Qp&2pMSnN^%soIxDif8Yl9A9&gP z*!&r^*#g*t8PveN2qCr@wnPR&a9=_b+?U`7_aeC2YS`)-%-Gu4dKsA5Cb7+AU;_6d zxY?GlEn!e&TgtYSK^xqo5Mo;azJX*V+e!vaaKD0^Z4KLc1}1Rtf*ahs;05<9gxC(T z9cK_^yTEpxfr;$_+am^E&>ct&+~9r%FX$d524gl*k3xv;3)@!)L2!?PpPieXkAVr? zqp)KaWEWy!0^O9vpv*4KF3-Tk(Z<omAPw$Ch;q!}n91PJF^gjs0}HrE!NIYRV?6^4 z#|Dlq3>+L=Ikq#fa2)11!r;Yml;bi33&$0X`wSc$4>%q&ut0khk2#((uy8!*c*7tC z?p;`bdlwc+y$e-v??MIKyD$Nr6UxBIz`?+nzKnr~fidG5Qyv2oLn;I4hFAs$&<(Lt z;2UC1z&FHtgKvn<0*`q90^bn(n@OBWoN+0W0+RycGSJ<yjLSi{!ZNM^&wi`{-3rUN z0dy-Y<2lf+u%LMcmR6?Cpj%;?Z-VZFWxmI9lI0}xLzXivXP6&>ZiQuj47wGTMICf2 zEQ<!{R#=vF(5<j68La87nJihLTVYvpLAS!P6oYPsWhnvO3d_>W_L1!u>kZJH1M4Gp zZgz3jH|)~vDy%<2cf+zVgYJf9<6w_rFJ$8c-3rSl54shW%?WfXEL#x!6ZR);5$rG7 z->^lpzhnQv7R&yL{To{X=vG*^RM4%kY-yldVcF6_x5Bbzf^LOn%jOW}5M#>&-3rTA z0J;^HZ4!qMhd<jC(5<j+GdMyyLfK}4ZiQu=4Z0PUZ7%3mShjf_DIDo+3qZHRvMu2# z;izU?3c3}RZ7oMPCm-83(0#D%R-pS}+3i60!LmDXYH{kbJ98Rx8nSzG+Hrcbdx7qQ zWsd;e2g@D>x(}8;8gw5ldpzj&SM~(Z?XT>qpxa;Bvp~1Mvgd$qe`U`D-Tum+&$*s+ zJ$oVO_E+{I(Cx46#h}|?*-JpTzp|HtZhvJj<2=lHl)aqu8s|0kD$wn(?A4&#U)ftg zx4*Ktfo^|g?*QHY%HGL!gX=bX7uS8R`|N#OkGLMQ_k-?$WuM6Pp6fmPWY8V3>{CGZ zrm|1v>Eh{PpT;wRX9D|l_8D=9#5PI261yYEByJ$(C(|LhkKar7l^m0-ht!97FX;fO zCvr=qzQt{j=9AkXaZbX*dx?aX>^IpPvfrdv#plIckv<{&M{b^UlJq(04bt0W^y2fR zCrQtcz9P#OH!t2odY){ERF_16q+Z-11Qhxtc0rB_0%14t30Z*bi}!*+*$`<y2=rbe z9U!wn_8S6<>=L^cp9g``7El-fvKb;4pC=s<ZvlZ40n$q(0^$zIegk2CBk4C%uVlX= zW3fBZtAs3M^yHZ0^I(|YLi!VkE#)VD0*3kRq)*6n$o`RBBcms|Puc>8r8#6+B=_;V z2;JiMl1}0e;182NC&whcfj@>n2}HxN)CU<o{tW&+FkK>*CZiGW6`u#g{8jOMa!aJI z@Hg<cfoQ33vTPvC-y^&OOi$vU5w{_39tcbG#ap0b{&_N766a(?yq8D>fMQ5ePr?g= zrM>u<NS%@WCiF>Umu!f10RJlf4RMF~w|QwvAL8G`zen<#?6kN;B8#MrWK86kB)nug z;=LsI$-WYf1Eqkt4e?$g2GRjS8{#&2FOl+-u#obT4UydEy+n>fQcp%hcA8X_9EbER z>1QB5{}mYxnHRFtq|XT@@gL$p!GA73Pxh7M1^z2Cda`U%Q6gL9bOa(~LqNLX^Q59= zL*$qw*GL=5-jMnRN(ZvXgs1S|0)?>5EdB>^hvbaJHc1=F`pGc~Cd6BK&-0!qqbKVm z>j82j$W>CW;x@?40=bI+nP3k88v#B3Pl9!V2jo`q{{Z<}j!8y9phI?De4b!he2nZ3 z*&9+_vMb!@2)~HWlbIzwN%kB6KZyX5EmB<qEK*UjU9w#QT#}C@yhPT?&XL{|pC_Xs z&>^xymQ8M+w1sq%h?Ycyj2<X83kb+$34Z~FHw=TqU37zNh;)*yhx9f9F##FbkoY_y z7YPeFChvLid9pVo-w9+1C^<Y5&=AlQyCbwjz(l}G$U^FjfP;XWfR8|slpiQ$qyrot zNxOisK%77dSWkgKnLv#|lT?(1msFJW5~(hM4uL*_DFU+u7RYc3EE8BGunFWU89nK9 z0y|`8Nofh}6LJxLA#g<Cln|fb0f7tBZv?Ih-0@x_@CbwjUI@Gs_#*I2kU@}5Fh@E- zFh}-}AdmMOK_Nj2$$f$ef@y+sf+~Vqf(C+Sf;LiGf=+@Sf_{P_f>DzDKzRs+L1_t; zKZIPQbwC)TE8ZeLMtYU-9q)OvH$WJavO(z$gymL=tdp4~5dg!2IZ{!AMS>NAb&`(+ zTLilVCkRfHu#oDKGm>5<I7i};mzGqH;3B~lg6kyy32qVGCG|n@fZ#E?CDMl^^#sod zUJ|?^cn{<bbc{_LBqpIC_yOczY#1a5%FBXJ1YZe$6Z`;jH#&xh%NfOcA+X>#!9PMw zLL8u+D8wfuf`X-l6ok~kIT4f_17!3>rU~iD83|d)8Oa$rJQ6aJSpzDAge;_TKq5kR zGD<=&@fJc}5-~ynLSaHNlKW);fJ#)MB%utUJQ)qy5TO#GDxn7HB|>dNJ+f><8^pMT zkH`oJO%j<V8zMBrdx_9Ip(R4Aq*sCBK=_W(2I*DtG13Y`+l2PWbO;?1Iw8y=%q1)! zbWZ4s&@G_{LeGTWfI<)CbC7RAzCgzyc@PH0w$KmhC7_Z}_LcNGp?}h!Kp1Qj*i?{= zu$Zt6sB8o20AW~IgKPj{kS!n#D&0UBW}C2*um-4H71k3r5w?<fA?zUR2GTFCBCZ8e zkBmXNOxVYLj&P80g!GKKLsGA#<m8y*HVE$!z982i{6%DuG@o#s9FuU0aF+BW;R5L; zAe%tCWWRyJS<XmGNG3~qiJXzNj<k-Xo*a|(B<Us6CnQ!0m&v>nu94A`(U6-bJ1tH_ zxJkG}dXjLT@D$-$!n0&FWHe+JNC$vQP?0Ud3xpR4F9X9h!keV`NbeEeAw3BKh4%>` ziMNmrkcyIdCwxj~hb)8e1>tMLcZBZ<{{q8D@m?|la!eAdgkMNc5`HKAMS2NHT!cY{ zO@v28NJK(JPDDjSOT<8Chx8$75or+-GtmvwB_cK=P9h#6ej*_vQ6dQ<X(BlyMIsfl zY_i{E*+l9@wurPyUXY3s>5@JtGC^d8$TSHr&>g~(7i7OlC&`A0tPoiz9U#3#>XlTT z$QH>9G7F?$$t;k1B0U3Ce#u^vIwrD9jzi><%nO+pBKKq&L=K1?6FKAcN19JYPi~dS zCFuYVjOP=%VZTIfl_-<!CD}_N_heqk=!rZLc_lqh<b$MMe2mC9kw2nLq8y@pVku%N zq9USpqEey?qH3Z#qDG<?qIRM#qF$n2q5+~|VjZF}qDi6|qIqIUVoG9tq9vkLq79<w z#FWHliMEMZiS~$25}hFyCwfkFo<pDL60tJTRbow|8$`E>?h)N1dPwwy=sB@0(JP|2 zL?4Jg6MZB4N%V*4KQR_DE*U*B0Wq;S4cTeZlcWP=Z%D5KwNS)lq$i2>i7AO`h;@kR ziJ6F%iCKv`$nuD}iTQ~6h?R+zi3N#8h((CSiN%Sfh;@i%i4};IiPeZTiFL^B5$hA1 zA~s8Gf!H#!HFA5zHp$))+ab13?1<PYu?u3?K<x*yM`ABPHz$kz0(Fwad0=T@e1f=; zxP-VIC@qT{#9aa96Hr<gHxsu3(@x?Z;(p>G;!)xWpgaP~UE*otIpRg)6%q>Kbs#L> zBHkrFL3|phUJ;)oz6g}Z#8-%~6W=1fOZ<TNG35LKVoL{rd@el+l=8*Th+hKZ8{+ps ztqAca;;%q72!q(5)`a*6@o(aPB$y;PB=}%?QbI&R3dWXWlAb4_AfX0IDH1voMxb&U zgh9DV0@TK^lW+mivVY>{$%aS-$bOUdlH)*ypq8IRn8XQ*7^xhIB#9(RJp`1<kjRk8 zlPHm>lBfdbGf-ZGVu=QcHi;gINfI+8=1DA(6p)>U3ME#_egoa@EU`yok8GF3Az1ql zL`$5II45yM;+Dh%iDyz#s8HgK#3zX#(rvOKs8HgcB#R`Mq=2NDq>QAJqz1?rAeVyN z1+p1rF32R1F3AOG&_vQi(nr!t(m~Qq(nrz<qz4&G21!Op#!03~&XSxZnI%~u`2r1= zN!Ca<Nj6D#NcKrik(>p#8*GOhhvWiK2!gQWGK86uYh*ekH%Zk=?f|(BhC%Hp$s>}d zK<)%#$qS&8K`P37iT4u8Ym#>)A3^Mu4Uv2yy-o6q<U7ePlE0*Qq!^?aq}Zf*q_;^4 zNgGLTkT#MIkdly+lTwk=k}{Aold_R=lJfALC+!mVN6Js;o%A_r1*s5_E0HnG6)+m) z0%VLKo*<Pbbu6AwDo3hFszRzxss+@Rk(wYiO=^zRBB>Qp>!h|w?ed-{bwKKv)ETKu zavV}OWY);O0zo+@P+vhhz<Zw5J*g*BPvkb(-jVts^-A`Y)CZ|=Qh(wtq?r=E;tt6% zNpnc^NsCBJNh^TbadI5ehvH+T)ueT#jifE4?WB{WU8KFFy`%%A!=z)RlcbZROQe&e zGo<rmd8A9EtE3yG+oXGB*`&{b;Rcxn;2zEl>3Pyiq?bsqg7kZ&_sHl;ACf*HeNILX z)ccXX<#j;%f%G%!H`1S^e@Oq6VUgjI5s+mAm7NGIBL-p1fPj*W9vEtXNfQ|eTqA=H ztz;Zze8A96#s|`il8HlsK{9bN5i)TyDKaTCSuzDOHDFjKQzO$P(;+hp4EtoJ$jp*i zfE6wS+qp?*2N>>?IR%DCWKPL|`fUwz4RQ@K*JSR1>I)S72+VsY^92rn$uhtpn=AzK z$O_3y$Z=R2$;!#9$ZE+N$ePL8$ohd=_MjM*^^*;ejgn1}O_R-Wdm&pSTOnH~+alW~ zx60v>9Fyz>*=e$KWEaV<1GVI3*U4^?-6ea#;gR<|*<-S2WG~6yki94SB<@hWh3qTY z53=86|HNI9W0K>L<C7DSlaf=AQ<GDZ(~&chvyiisbCL6s3y=$wi;+u`%aF^HE0L@6 zo+Q^G*JgXi_KRGP+$6afa`WVt$gPswAh%6!kK7@-6AX-uF8@^+7#VfI<fQ+~42+CM z|D6~Z|Nr?P#=ywv1s353lR6-hp%Fwf)__S<Fj>vOz`)3O0Ze*;L>THoBqQU0(2SrM zh|O>fL^9@pZIJ_uGlE1IK7dHZMzG#(VA29CD+FRQy#H^@z{v0kL^9q7i7@8<cVS>; zEC!KG>|l{75Xr;`A{pL+NJfkQZVZf!F<`dkf6$zq%fI&wjEs_C5_E43BhyrnEE6Y~ z^aPQNpwm?tnTkMcCQ%T{sP<orfsx_se>>3HH;}8ClE9=2h-B;rt8oIc8NPu?#zv5< z7`;F?GTa2qy8UNkU}WU}&&|Ndcmyol2bTQ`4hMg*h&b4_(O~uVAXz3!u&zyDT_s?Z zVjz_a??AE)|G;+HfJ7KYz<Sq%*;yc2#so0i94!7GZ038gNIh6K25hnf*yIebxEfeI z4=ipD7WW2=#DZmw!RDL>v#Y@3tHEZLgUMJh$qABWxCxeB3l*^f%}@WgVqj#n0h7XD z@-SG|7Nnk$7p(p*SmY0wJPjrt!DJekOabds1(PoS13)ndA{kbJ$z~AAs0$`Lz@!P7 z%mI^XV6qKtP9T_U1B(QLNof$ta19)ipwlfG8FRsE^!_V=ZfXXzS-`TgVDd6Zgy9T` zWaI~tOw1sXu?8f|Bn4(K2eBE$!EE#Yb3pUoAU4BR5XqPUCi%f?<UnkO*C3Kn7EG#v z#2HqA*-ZccGcYo=gV;<Qpq$901d?Tx0Fg{zKqAb1V0HtDWZVf-$v6*8c7Rd~^G^_) z8SGl-ND!OxDwy;JtC#xU&cMj<;eRkVAAxe{hX2zU7#Rb=YBWKi&F~sb?gxo590HMy z&%mSsnAH7mz`)4R333S|*bNN-{tGcMGMa)yk6|xJ4a0g6$><5T@d}uI1;l1J4`MT% z2eZMcg<&n2{Q*pF{ol&K$gmZ}X6yv3d<|yv|6j?#$nX=yW_bNykb#lW9wf`i4Yu(X zh|K`@Bhwxbn`tvhCDR^|E+){4Ta1jZV38Kk4a7`lAU5MtkV?ip5Xo?gQJ#U3AqY&i zLr8{x21bT$VD>*SX$uxv$}oX}ks$;uG6zhq0h3)Il2ILGJ|k#P7O2!RW?*D^2DVEK zOtOMWSFnvgz~pxj$(Rim2i@Ml$k6rQ9JG?-e<=eaBWP<1BO_>U2_qxe7Yr}K>bt<C z>Hl5^M#dBnn*kg<41dAw-(d1G*gf(flHnehTn!=_SwSSjdoY;?BLDwo*vY`ia1F#} zI1C~gl|dxKcQE-MOx^;MSHa{~F!>flGHQWINf60!5lrp_le55N6vHwGMuv4DHlq=U zWT*j?=fGq)m^=w084W-r!xAw01x&60hxQRLdo!3F`hNi^j=<!8Fu4RwegTs!Kw-#m z6imJWli)PKXv@sOz{qeOWDX-YI8|>4u^HBa$@yS18B87m+j5d&CIcfw2UsKnO!k3D zMgyoUC{>&Vi7>nYi_8I&Az-o$OzsEE9tD#pz~oXeITuXM1gqJ=@S1^<VG)SUXbp-l zMr%-s#OMSjt^emTFfuy*&tYI>ECKn2Q4&msfmMcq)u@2UFtAD$Fc}6`1F4(B{#!6G zGOB<{T`;Nh-<g4tQ5Rh5>VQ@1f=L#znFV0e%)n#;SR9f^3c%{kKqSMe|DbhR%^;G| z3#^hGOnQNB=l-9{z{t=D7SZ`%3}zRA+Z7gIwhaR#;{mYjbud{2CQZR)4M;De>HkCq zM#dVjYfZtV2S}Eo4n#6~{7+|KWT^X}&%nsY2ohoV03sR1KqSL85XmU^zYvs?!R`?Q znZR)EzcB+NV-ASTsP^9!?4AGyMutCN^{2pOJD5}jhl3`F&F~3CGHQZE7~;U8u@b~) zoB}3ig2`GC$s_<KxxpkTyD~EF2C*4Icb_pbd4bqW&R{YaO!|OHNXtYX#Abw)lMBFX zaCyrJDQ`D|MNWZ8rUWnvZXqy%_Qo<Yf!)Tq7%XlACOtqT<2o?84@5FS+C|_r!vrq3 znGC_=x?s{DL^6B=k<6f7wv5c+dWv~ISY#oX1lRQ}ydX9UxUIzku4P!}f<-{*!7;MT z0kb8*q#Bsq1SY}lE0!5xb_bZ83?dozz%>-4t|<nKfJ<y<aNCbz6<CB1OhVdV`rz<i z0~Xl=CR@Q|JIEYHa2>}8t~Z&%?L&qm;L>0XnA{E~!J)xu4mL*;TytFmk&IQ~c8D3c zh2sTgbA#D(AU4BmFnbc%u52)A3??(dwO$RF1pAQ@;;)%t^N)em>;RMCwk6|FaLZ~Y zsAa{Z1ZHmou^CH2wlG?Nau#DQnC%E=ANcRUz{r>kHo*Z*=7UIPa6V-MhcIJ1xMf}f z5@)OdlaRFc0L)foI>o@qunHVLIbabhu-n=}B*P1k2*X1V$p~q;uz}bN;80~~1?yr0 zi-1!Xqdu4oZf`JvTlfs%x{M(V9JY<%5|s~Bjxn@?N(P2jP~KrG1nFX`2ayboAbT0X z^&kVJrDp;bQGv*UNXF}65}b+{)xm5nuo`gAVgT2tj1^#UaQbIt2Fpr<U8@Ts89Kls z_8^j>86?7}1|}82x;Vh>I4~QWk{L}wDj7||BFZ3=;TuQ|!zB=#(H-0?aR;;6|0gjp zGE4%?g3|*-8AyZ?v>%$0kqe}f;WLB;sb{zYA{h(7qy<Qv(E_aA0xSaBf6vHR24XXS zPAUVnkSiD%8UBMs{)5yrJO;Uq;W1d`F<9gQSmXhS&8P)(38NNR_8*93YzC1G;8q_4 zxJAwI0W1;<u5pYQ%NQ6LA??+?|0WEKOgq5oEf$>8GQgw~NIhc_SUd^LJ^&`8z#`zb zD5E9F4NQ*Ue4zy<b-<)DNSxsbSbY_UWPr5u4}#g?J_y4_5Swukm~;T^QUtS=L2QOc zV0Rt_llMU4|NnsU7X!EyW#j;fFgk%r8*uxI8I-~q!KEu>6IfglOqzj79Wbc}BAFm* z8`63|3KC(w$)v=<$oPUuih+?)1mto?aQVq_3Y?zTfyodM$!G*38BT)95RgiSIbe1- znEVKGEu%4rWatEw)nF2m2OXJCGcYo*V9a1(WCFL%n9@PEGk{}?5mHv$f<zd#K_o*L zlQ07#!y%9fjP)SjF@f?OIM0LDQ25A!)=>DkFo}U<Qk_AYL7%~h!JNUJ!JEOKA&4QI zVG6@khG`7b8D=nSVc5#BjbS^(4u%U17a5*0JZJdD@SEWe!(WDf4F4HH)h90_A0t1b z0HYwI5Ti1q3Zp8c8lwhd1Y;Cq3S%l`4r2jhH{%S(ZH(I)cQamR%4Ax?be`z~(<^38 zW-VrIW*uf-W<6$oW&>tJW+P@}W)o&pW;4((Pv(Wpi<lQPFJWHFyo`Ar^LplE%*UBe zFrQ>T!+e(c9P>lwN6e3zpD@2?{=od3`4977=6}rpSr}LtS(sROS@>9tSVCA*S!!7p zv;1Y1VO3yNVbx&OVKrg3V|8ZDW$kC(!n&1p8|!w~9jrT9cd_nf-NU+<^$hD-)^n`q zSue0&WWB_Cne__mRn`Zr4_P0vK4yKw`jqt<>vPsGtY2Bbv3_U$!TOW+7wc~}AvR$) z5jIgaF*b2F2{uVK3pPu(B(`L>6t+~hG`4iM47N<rN*}fwwpzA2wtBV(wnnxlwq~{# zwpP$89<~!~C)rN1on|}3c9!iN+j+JhY(Lq4fmZReJFzFTr?TH?f5QHb{XP2!4pt69 z4lxdS4tLPH4UQC!RE{Q&4vsF4ZjK&~g&d1P>ux}+`8iH<oZ>jmafRb5$2E@Y95*;_ za@^v$&2f+89mfZbj~t&k^*GmZ?&93Td7twk=QGaNT-Ug6a-U*kW{P3D!dzhA!}Noh zi`mUS&wieLjC~Ir&a;O?rWj@}rYp>D%mwy&$k@KeejW@n{jiS#Vfz>+4kkXPD<D&t zet=8>u^}vGH;`&(E)a<egUkT!^J3;=E&$nutPUa$69Ksh#)i?%1x!Df-Izq|dziwQ zq?i<#)R=UbjF>E#?3i4byqE%*xtPMhz5)3N8DC*`1DS`6LAE1fm>n=0>{6(&L2PC> z`xvGqrVOS$rV^$qrUs@Srb8hA!!T1D(>bOdrVUJ!m}Y>)nC3ApVOqts0ko@%X%EvO zrV~u(n65D0VtT;z%sz(Mjp+x|8&K@n_b?YQePa5-T)_0tK98A&nae)UK95;|S&UhR zS&3PLSp&2Z546$_imgB^>QJx)X#E_sgMAOP8?z5{5OV}`9CHeD7AS<7L1p_1##9DI z#;qWdVGAP<xPN+pfss)I%zn%Gm4T4~w8xy0VHKGD4@_<alP4GtFfcM41(Ri9@+634 z%mtaoxDQMo2a!y^VA2gthJi_c5Xra!L^8#LNp&!(0U{YsfypBvk|`QYMuEuyFqsS{ zBS9qNelU3wOcsO5YhZFYh-5g*;K;zp%nV{PJ_eIwAd;yO<U2+?FlhoJnGHcC<4rL6 z5kxXg0g;T#jB=osKZs<w10or1KqSKh5Xoo?Qp0c=OdbW3CqXtcgn-F1Fxd$X6E={& z3=E8^h}CWGDxi|t;|LX2w>dC5Fs=Zvaa##q<F*#O#%&{bjoW$f8n?^L2`sHlTfl4F zZh_ah-Df!oU)}Z$yt+*byt+-BHHI~YB@4W|Et?gzx-A#Hx~%}bx~&Ynx~-gbI@@cO zHt_1U+u+r0Pr<9(-h)@S{Q<9TV*{^l;|8y8;{mU3Qv$DUa|N$%3k9!kiw3W5ivh20 zOJE1BZc7HQZp#3#Zp#F(Zp-4}<=|t>;Sk^uV#@=sZYu<@ZYu__Zkq~T-8LOmO0vxc zuWp+QUfnhiyt-`xcy-%C@ane3;MHx*!K>R=fLFI|0IzP_30~c13trvk2wvUh3SQmj z243Cf176+c3trt84PM<A3trt82VUKl1YX^i3|`%q0bbpf3trup4_@6?2wvS*1YX@% z0$$x#3SQk-243A(4qn|>0bbo!30~b+1zz1&%XyFU8G9Y)3(lA9?VPVU->`Rbo!~mb z-VI*e*28s!>n?jQcy-%kF3{?>Dd5#@)3`vZ+h%}Qx6K5vZkxpeTHQ9A2ei6v4*OiI zI;mv}O7eLM0{k{2*Q6yB#8enm3>0LPYZR2M-pIePdZY3|{-0Hja*)a&86!~}aWR<; zg;P>%RBRL$c+Rn!p|DBCN#&KwD}@UR7ZjE$T(cHX=u;_Dc%<;iDoWv+!W7dlf-K@P z@*-kVAjt0|l%t{|?4_V2rUQZktHdloP+)`nHhvE=FA(JS6FMW3B31%|(oY0aRQ{+) zh$(;|e~3^Kf0XGj6&o=l5EK*>vjagvCH@5IZ(;!;$e$*3!&*SB3IwHJ2{S3o68a{` z#-Ag{Ag0D&q;N`Vlhh6nmiFVX0MYz)3Jc`7iR|NV;qQ{VBlU=X0{=7x0na&NI$}m* zOky1TbNCnWui#%Na!rgwY?9avX$ci4{w@5w<P!J~$VG{{D2S=N;y=cJhW`@(4KX_v z1BDCXYxwU;8z{&qTtLQBo5ZRVloYOkX#OW4mgo)9dtzZ?F=Ad~0sOBdc8MiP?^5}o z@CZapZ;{>w!t(zV9)W199IGh)5AsYPTKa?ZH~w$@f5aNZ+60&cIK)cCs+5Bit_k`G z1_`DJGYN#r#K<HG@Ck^3Xz_glQUVGBY63a}Mj)F&CR){r%o4B=|0Q52;3Bt3z{{#m zoJB!EAV5JtCPP}n>WzY!ih(#6I0fWby-^O5e*;PZ;$njPL~R83S-lb1AP^=HBakGJ zA&@6fqT;8pL*a;mp16iUm7I`3gYpIOHKJ_t8^o0a+N=cxepm}g_$gddc%)J!Z{fK@ z@QB<BfgXWL0y6~W2`mv<B`qPQBehKapMsdc1{DT@Z326wB?Jx$oKOz3suQ^*wM;=k zxk*7lZjse3fpY>^#Fi+RDc6A92y&Hzl2wl27m%x@B?Oyn1q5y>Hwiotc&74A;Ent_ zg;N5bJlBc$DZlWXqx{I~pTG}+e?mN-i<BRUFS8bq-=NT^Vk4v?E+b(h$RfYN^O*7` z<xPTIf&vPgBr24zDXb9`6WJ#yBT=OANadBFlFBPV4M9DTeS#)}R>~cM4uWpr@CJo> zgkT&f+@-Rt-iX;rm<eVH7Fg9OoU(djEdYuaF&)7&F(bhmxnqKN1e*jqM2iIb1g8kj zGHnuEAiqudj^HxEHG-Q2cL?qiJOa`qcuL`jn3UiJlPiMPKzgK>2|f~hA^1+h!%soN zL#0SqL1Kd77x6WMzl0c6v=pp_*o1iGd*mm{_b6Nt5|ZB_&mq1{xj=lGkc5z&$SmO) z1tk?5s~jN}aWQ!v5SFO(Tp{yDNK42-#ZNiTT0l8Y#YxCa$OeQJ#DtuLJcPOw)+ncl zdMF2}_{nn!`6<VVmkEUkMJb30B?zSn<p>oCRY-IR)d{r-bt$+BO%R$UG)HKW&<de- zqBi1vLR*A(2^|nRCUi#V2FO1`mxOKz-4l8u^h)f3&<CM!LVtvrggJ!yK>iRG5tahc z5_Q6A!aDMkMD8do5H=FF5Vn)Al7A!YBJ5=%B^)3erl2GoBb+3hA^uBTLpV>k1Qfo) zRl*IzZNfcZJV|(l@I2uqVp3uX!mETgfbllrJ;H~CPk?ehC`SvQ6TTvROZb8CGvPO2 z{7LwS@IMh2P)--&5)lC9WRQDB#6)C7lteVZSWm=6#7e{glygMfM0~(FNF+iePOeKN zMWqN7zam*81tMi4HDKH%(jn3(GDT#T$O3UOaT$?iB5Oo8iR=*B2g<n$v*fpl+)<ci zRVQ*p{+Y-rkqh$MM6Q8EJhzBEQZ7)@lF1NxA^%V0oyZpjF_B-Q3<?)S*+h91l;ni0 z-iQi`N{Gsd?@;+5s-o~n{-3Cpc!9E;sDTwIkEV!=iFe5J$%}~EfZ{;BPt;7*M!`zd zNz_BsPc%d!NHj_`K{QP?N3=+^LbOh_MYKzF0w}b^EX3?Uz5|saqSHj@h%ORcA^k^& z2}Fyo6Wt=ZOZ0%~G0`)kmsE;C<)O5ev;ioTK&6-H6VX?qA4I>2{sGB|@rj9mN;i<H zpfCr8E2u;T*#Igj!M1?PyCmsdVi{t2AR9qtm{^a*B}mCCHcxDc*eaO}c@eP<V%tD* zCbmcH5E!2jJ12HU?3Uadu?J$$lpl$`5&I<e!>Ud}$?Thgj8%@pBY6?Af8v|OS(Jms zxfBG%1ymSRUa4$RDFT(KpqNlNrBb9)B)&uLo97vYS>ihs+{Bf{HB>wl%EWglZ1UVC zuOqLca7|oKTu<ed@&zdYaT9SXg$v>i;%*?Qa82QwxR14fM3;DwgpEXnc!Wd+2#Uvv z$0@8)SflVrJViW3p-enQJWIR)R11oi$?KSY5w8(%k{1#05bqQ36W=GkPkf5Ji1;ke zbt)d>3&fYHyb@m{zDaxsSmu=Y5%E*v7sRiL-w}T#{zCkn_!seC5)2XyQdSad$|h0~ z5<C(-5<*6O5)x8PQdUwC5^@qM3XfE56dp-vNf=0&N!Um@Sqn&bNchPcNxYH>k%*E= zkVuoru@+FVQF&$cMxscfLgkObECnUy8hHzA0f{;VC5bw#H!4LkMy6jR&PcRKba}3m z*rGf|d5Xj(i3t+ZB<4sgl2{?JPT`uw0f{Zv0w5@{%X5Xq0f}Q0-z3gRoRPSsJVoJ} z#0`mi3R5JW$crdgNxYKyAo0!Ui^LyECP^kq4oN;q5lJbPIg$#JYLYsVMv@kic9M3I zE|Ol70g_>oF_KA=8IpODc~Ui!C6ZN=4N_u~ZIV5bla#+m&XBT_oF|nfRUo-Ua+Tx; z$!(H*q_U*4q}(JANgk3sA$d;nisUWH2MTd26I5CxpGm%v{3Q28@`vO<g=<nQQe093 z$`=&+tOcajC@cWAQxq;J^hwo7iAl*wDM@Ka=_wQ_f04>kHc=>$GLbS-Hj%QDa*%S9 zas%7pBUK<3Bo!eQCzS$nfmE4PjZ~9Vhg64DpVSnoSyBt6)<`XbVo-}>pTYw9JX9=o zMCz2(1*vPGbPU3vydd>L>YdaVsbA6z(rloXgfx$|5SW%waRQY;(sI%&pd1EjM}RP> z1tD!FZ3Ch~SlUV2L%Bv_nY5pD2&fGK!_raG3DRlOInqVa71DLmEz(`m6Qrj}&yijv zeF>BUq*q9<1Jh@uFM(PBpf-i{0qJAXXQVGl-;llsDxF|h`ib-_P#XhOwt-3l84ejf z84(#N83lzYGHNn9pwuE`A!8@wBI6|!AOmh~fbuK|t2oKz$&|=c$u!8c$wnZ-IN3O> zI;%QUJ((W)PcoBaX2{HtnTG_I$SjdrC9^?ho6I)ZCM4J)+aaqYvq$ET%n6eonR7B% zWNyhkKtQ<=xe%*cGS6h*$b6F1lGBp;A@fhJ1p#GQ<P1y&%rj)UOhjY_5KwM{+yqlS z`5&@kvNE!pkl+s49VS(>O6D0RJ+d0Ida@?6R<d7YzsNesI><@LNyxg%y2<*;`p5>! z2Fb0HTZiPs2-!H<IN2206xkZtEZG9tGT9p08YG`I$%6dSCp$%Umh1xAN3xG(m&vX{ zvU!v24%r>D`(%&Eo{~K!dqMV^>>b%hvM*%c$$nAsll>z5OZJx>gB%+u6y<p2B;<tT zB;-IqMShi>mYji{nVgNBlbnZ~hn$~Wh+LFhf?S$hj$Dykg<PFn9XLd~<R-{Xlba*A z$fQKRL2jMg3b}Q1TjaLL?UFkncTDb#+$Fgia`)t($i0&Lps-Btn{t-I1?4Q2KPn&O z{>U@QbEr6hQY5I3QQ0CdC9fc_Ca)uJq@W>hA#VqTF7goQB@clC@(>s%4}mfA5SSzn zff@1;n5Up5e?q=QzDmA9ex7oTd>gnuGedr!sg?W^`Bm~8<hRN1QQ0DYNdAQUIr%H{ zx8xtlKT|OPK?NDBH=urs{3rPzAePD>l>-V&3Q8&l3QF?-6j-coDR7xzvZ_-MP!LlN zQjk$lQqWK+Qz%o=Q!r7mQgBdkQ}6-v%M^kXA`~L51r*{GQotew3S|me3S|lf3LsXQ zLXAR`!Xt1$2h`W;0QGZJiWH_O%u<-8umIBgQCOpJO?isKCWQ;27O%o1g&hj}6z(V- zQ8?u}2PCHQO5vKq9fd~<FBIM>d{OwN$e_rk$fGEvD4{5)sG_K)XrOpZiBE}1i9?A` zi9^v$(Mi!s(MHipu}INF(N8f%F+?#+F+nj+F-NgTu|ly<u|=^<af0GBr8cED#W{+X z6c;J3P+X_DMRAwn0mWmAXB00f-cbCYcu(<(;uFOWimwzufZ;dAKX6<4lth$bl%$jt zl#G<rlysDglq{6&lw6d&lme8(l){u^l=764lrog^lp2&ul&X{(z_?ARM`?!AB&8Wj zGnD4}@hL4)+NQKhX@k->r9DcAlujs}Q@WybOX-2qGo?35pOk(m{ZnR9=28|=7E_i{ zR#Mhb)>Af7wo-Obc2o9I4pNR#j#Exi&QdN=ZUVLMLGh^EWc5b5L%C0Rii(HwEaex< z3zU~BuTkElyhC}P@)6}z$`_QcDc@0k0cy`HzfgXs{6+bfRh`Nf6$TYH6&@8K6$uqN z6%`dN6$2GB6&n>Ns~IXDDt;;<Dp4v4DrqV?Dmk7jREkt8z_3oGMWst+g32_NIVy`( zR;a8~IiRvdWtYkUm18PrR4%F9P`Rh_MCFyr2bFIse^i-NIaK*nK_^gXfyUJt?U*Nm zW|_fcJD8MYx(`}e#B9jG$f(cs7fgahn3ggyGTJenWng5KVS32G$e78zfq{|HkU5-z zkx>>bYsfqq%m&F$WuC^s$f(Kmgn^N9Dp*_-q>Et{$QFi1kSz?2AYBZrz_LbQ_cVjm zbb?G~=mC+8)l3qg)pTH4F|bG;*hW*3UdBA;$DoxqVAm>v%wc#9GJ!FV=?ViQqXY9k zuwOvrPO#n$O#c`d8Bc&s+X^PPfk=iXX3!crWe}TDnz@I8k<px4m4T6w2TZzwNQNd5 z$!G#n$?%Ek2LmIc7ASle-h<c-O-#2K7#U5#q&`$7$b?of+Yn?X!zvKTcm-_BeK2VX zc9jM53I;~TZm>uPh|R<aW^V+Ojv$hW4@5HRfNW&+0*8q^(>Df2Ms_ee223`BNm-^_ zp!H@TpE5Lp*o;fT;=92lCs_PHST7fIECVCMEv79DjEon-F6jixGF}9`vlFaW8Z3Sc zOx_2}Hh|eqV0IALRd!4*44_jwK`|8u7Lfzn^#(*T6@f&UL_usuHRe#z8bYQS42+DE zK;n$GOy3z887;tUCXks-Dqxk}Ad=x5h-7SJo()=i33js^SmhBg*$0;O2eZY&>}U|1 zNfJadZUTugyaSPpSzs~&EdCx$)`LY>gF>6J9Bi^TSmZQVwhGL)1ItQ+W$nOWA_)$Y zonSSFU|CtPYz$bW2&_g5tY$TsT@Gfef!GXR!R!Wb>U9FA-Ug63qZ3%X9n5ZLt_SBh zP+GDDu^GODWi7zEEI?`){zFAJfaXa-A;uUB5@$39i?0Q<TfuBdDiQ|!MHTGA!(j3d zD8(`!1+#g<vTwocKVb4SSi})brh!E~!0Z$-TNTW<V+OfUk{Psy#E$tQIG5>w$_Ex6 zFgqR02Bil{=3)?=`6F1|2gGI(2D9_PY|tE@By%CSBmtQz3pUdbR7x<)f=UTSL$LX> zpuPHxhG6q$nL*|ovVhE&1)0yV3gjM!MzG#?5SvjS$_BYjAFQ_>tXChbw;ilkAEcMD z1Du{sz#-WI)@uUR+W~e%2iVtnU~$k1VT_DzVD*7u^=)ABK(P8Yu=+r-o7=#;0>NP= z4N}AKAFM_iq=w-?SdA$-7L34T4KpZYWWc$5Dp;=xnB)PI8<^P`7#S~vOk?N*i<p5) zZm@cOkV}}rv%pMJVDaT3m5kwFwlIif*bGw1uoXly%7RH1u=oomP>HPuQqQmg?2-Zy z$<PjxW&Q;6Df3Z~`OHBek_qfKre1Iv+YD04+z3`#2@+v~mc7iNa><k#v@$u5MG{;- zgW}5$EG`Kaw_|<@P6MtCjEp<MX?p`WM{EL_#@G%P(FcpDfZV|F6J$H{Cy*@jQIKny zgFv=3P6f#_YJy}LuYzP5y}_g%SX>e;E(xxK48bC@AQ6UDAT~oInB54LZ3l@k>VrfW z+rc%LK3LowEN%`GVfX+R$ped+f>q{$#2HP&;(}m%i$SssP0aTg7#TN!T^Ils*8;Qc zKs6MjBq*#H+rgos4-SoXu(&={927G8%&y?vy_A8G0UXW@hrluQ3~bIbPzW$Q0GsRz zCJn%(ELc_=#Af&pQo|?&CV9Z5DJb3<_JY(ftOt>do?!9{Sk?wiwu4B9^B{4CwP1E5 zSl3oCdn?!t#$fh;@JhnBAT}dEh-CN)Ca;3@GPW~aWng5K2kB+B2Z=LsgGh#3Ad=Ap zB+hUZL^53msb|^)CPl#JZv%_BfY?m-AU5MvkSt>!h-CN=@*Sf(n6v_!#&DA96=;Pp zQzB@EDwtdbCRc;WE|4svI@p}~U|o<rk_|GAu?{R^3?dmmfld1XVl#??)oX&;tYEe) zR8|7CeiFoHv;oT|gV`HEB*RTG*##!=fk;LM5Xo>CL^9@pNmeikR>^1!X4^9IGB7f7 zfY=N#K_nyC1V&S)KG2F*kO%`L#{YuZzd<CU187YJ!$mOp8cZGolj}evBRhy>$ODs+ zVDc`Qj0Ta6>L8NgJDB_jCU1esb71lmnA{2`-+@R*JrK#T9Tc97k|2`d4%2f6MuyE` zauZl&9hmF|lTjd&(HulF)PTuz5E3+R$Z!M9PGMTbz{s!!%)ShYBZd`V_7Sj|Z@}!$ zU~&n=BL+r>%Z%9!j0`Kl>^ER?Gl*og1Fsl44_3JV6fz7u!R)nQ@+jEk`C#@EFgpXx z4guTJ2VyfCfJlb3VDb%Ed=8i$0#;uJcIQd3$WbtP2uz*;lS{$mOfb0tOfCYGhd_E6 zoxu6p37k$K<y8%+d|;FTmmZm5SwrRt;5IX;#4u!@1!lhh*M^|>vn;r5(E_Pt_yd-m z3N9Np!DVAHSiFh(AZYD6sNQF2V%`N}gKT721uA<P8o~8l2*_TBMo_uL&;v4op^>?j zfsyeT$OOjw;F6~X%r*tH+gU(6U-ZHCayttPs7=Bg#K6ed4tA|R6UepgVE5=Vfm~|~ zGM~{0>@QoeIX+->%)xAPu#F$UZk7e9WcUD9DGM^0;RD!YS&&MG4`5wlVD>ELNCrm6 zJdnQ_O~LJ%JW%b)XbP@9^S~}N1-md0WDcV#*c=^@8iqe$H9DYhV7v%2jj<DK@<p(S z3Rr|4ETRH7pB-$zG)SD`KUiD|?9SI<cPfE&G0Xy+-wEn#F#HFRjFQYkpi>CJ;jkK{ zhOr+^P6nMZ#K;4#wVOa9Orl^?08FxhNXFwJlF1iLg4?uA;C3uiJV-B7B#2~a0-FG7 z&8`QjWLy9y4}xSF4}r-IAQ2`=d1wMs&*T9XDFn;z1GB-k1Ct?`tqT%o@&}QOJWPKW z7#W&CB%?l<Gy#+5AafYanPV6jnZASa6muGw3;>fsU=q^fa09D!1F2-*2NvG}B3b;w zq#u|J2a~=alCc%6z7?$gBuIq$I*4Qem!d3gV74civ;>nbAd=A>oD0ms>Bk)6LU8=r zf$Lv8Q0ii41giv_z~}~6;|5k!0rEBDelU3wL^7v?R5CPy%w%W+naR+^%mogI`ydkJ zHilIolNnZlOlE}iyudNYXads3Xads3Xads3s1Np$3D_<ZkX}Y<kX}Y<u--Kw8yQ<c zHZrz?UDXO!c?~SS988`8lPf?Z^8}DehV7t|jbSI4JPIaPgUL-`5**HqlA!vFVHSvF ztODs}lmn3ruR$g-GJ(lEAQ8q%AU4B45Xs057Rd&)&6%^n{oD?)ud~2p2dEDV7B^vr zh=cn0CZN2)m<iT<6HHD8n=l#72FEy~DVWU(7XJxm&jho#fyq*^hy|FP3uZflU48(} zP6m?>U@{*}>VZgRaGRFl8;H$l3nu$OBom}<EDK^YJ_eKGpjv<toWdDafkYU3KqO-g zh-7#HwpR~qqdJJq@D)rx1d)tVV3G|?GJ(`EEC$v13?YnB42%pHAZ&2Rhk(m=a4(yw z5Tu?7%x1I$u^D|pB*PyN$!G#Hhfx?z-Uo|FfJsd-=>js7u@vlPX0V7Ph-7F4t2YI) z88tv^7(Rg6Tuh+-0vw>yh7oj*G9x1g=v*^K4yL!DmIJdWh-5kmCLt<AL2PjUl!KX> zfsru-Y(gB^1Pi9m42+D*U=x%<;tU@_;tU_bExL~&afXi|lNmlTvx3%2fy`(42r{4H zBUt?#5XtBWAwjwr9YMMn9hpG8DjdP)>wrWUCV@?!1X9B=2_gbEc@o&<Ng$IM*+J$o zOahxf3Bm@snV}4%o>34iQU*4s49va*A{h(7qy<Qv(E_Z}0xAOXuMJq-24pXz4ai1D z8?aqAV3jr?yBO`5Y(YEnm_fZ!8<35R5c9u*&9MQI4F5sqF#HGUV)zdhc?=eL3>J9| z5@FN<kqr02<O8ty0}z{08%%0}-Jk__gBI8gS|BxyT3|P5LDhibOAF)%hJRp@W(Wzg zi?JE3z8P#nGspynpCDO=w-6GfhT$zp4Fl+$Z$^f<U^O4WvLC>*AHcF7z+oQ3bd!OR z=?`cXG{ap`?qE~^laTemc_22^4iL#03nnwbB&5y)kK`~Wfklpi$tW-hE~}X!BL-UF z6f4dQx{Trpm|X)R84iP09t5*}K<S)eC5U9y0g(*v!QxFIl5r83bO4j3U{V=GGCTt3 zzJp-$9>_F?PB3`{B+JOb^c%EG2+Xzt=bgLY{AI@s8fQ=gsbmZRlVDwpG9Z-<O(5GD zbwF%Jb1(@Wabma(5@$FHA{lRjZZcwg!N3G68$oIqLKrhZB`3H{I0+_ifXO*vGKEna zlxsk3W=3PMYdgWM%4!hF*Z_8e9Rq0TaRb<e(jbz-1Y{<YDq{cxBjYc|NCrlxcOaEa zy&#gI5!@y*2eaRRNJf1S$#C=kZw5w&qhPzh`wN)lnIsVF@ifnY*5hgEu^KTjG2CWA zJ#DU?!GxicVIqSS!(@gT49*O*8Rj#1g6}%<1E296!mycP2SX&oZif8~@eBtUE;6Jr zTw!?5P|EO%;T1zC!yAS-3|$QG7~U~-Gkjq9#L&a=mEkKxKf`y19}E*1elapKOk!kV z<YJh`$jd0iu#i!dQH^0aqXwfr!%jvIMo)%|;PdS+GlnxpGhAVeV~l6G$(Y2L&TyMC zlQE0oAtUIPqsQPII-Y=UIeH4do8viS8Dlxa3&uLedWKhwEsQM;Z@}mKzGa-uIGN!c z_`KftjI$YMGkjp2&$x);Bluk2uizUrzA>(2T*vU8aVz6?h98VO8Fw@M2A{wC4}9A0 zf6xiLj0~VNbQu{LZ!+FuWCER=%g6#cF_)1QbPg^f8{=EXcZ}?e9~eI{a)M5}W#nS~ z$;80O4L+Yw7`$Flgvp1=hfxA_)-0nW(`2S8j8dSJQyFELmM|@0lx14Uw31PdX$R9D zMtP?FOa~ZMK<mjF)j;QiGHQTM24&O)oe9dQ1v=N0QJd*6vnrzwvpTaGV<@vDvkPM? zvp;hPV<t1`CZT-Ls#nHB=6>dW#v<lb%xf5nnb$GzWh`Sp#C(#mjrlzD1;#$+%glEf zCotb<zRx(D`62Tg#yQOInLjYDVE)Sdm2nmGcNP}L)ht{re2hC;L|8-^_pykvh%@eI zkzr9_JjkNKqQQ8KMUO>~@i>bSixJ}q7E=~e#*-{IEH;d%Sln3L7*Df=u!Jz4VF_ai zV?4_e$r8<YjwO{PmGL4=HcK|+C6-#2TE@#P^(>8yS6EtDS{bjiEM{5Cc$4KA%Q40~ zEN58GFy3Xk#d4eR9?L_Phl~$cp0PY*e8}>G<u&6YmcK0j7@x6nvhpy#VC7@wV|>FZ z!79P{mQ{*XgYg}!7OMf{UshvQQzjNxOIAxJc2;Xv8zv4`J61a;E><U2cP4IDPgXA` zK~`VZU?ySKFxD_8DbQL_CTZ4W)?_9b)=bt+CRx@T)&eFu))LkdCS}$R)($2W)*jX# zCRNrx)(K2%tczF|F=?_cV_nXq#k!jH29pl!EjAmbD9{=EOnccv*dm#ZvL&%)GM#2C zVryl(3_4Mt={aa^Jkx8?Y57cV*+BO;ePw&j_L}K0+c&mf%uJxu@0r;_cQr9{gVxG3 z3$Qz|J2MM`)|WDiu_v)7GmEpQvZpgkvfpIC$t=TupZz|wENFcxvmE;?_BYJ(p!KE9 zN}%<n%&MUErOaBO^`*?(p!KE9I-vEX%z7LG9D>XS9HJaz%tjp2916@P9EKc*%vKzh z9G1-1ptYvVHXObj{>*luwWiFDptYvV&Y-oX%q|=;95KvppjD>K?x6Lh%-$Rg9Ied3 z9Niq#nIk!7aV%s`<5<kGm^qJQDaTgke2(oL`<NRz4se`i?%+7faglin$7PP&%riOe zaol5G#PNXR0rO&xM;vdMmw?X8WM0qlfs>DU18AKp^Lfw;Rp!f_x}18<S2+DR{g|(D zR&iD_Uk9x|Wxl~VgL4M+Ezs&y=G&mvr_6Ua*K@9Cz6V-y%6uQR;*|LTXvHb>L(p1N z=0}|OIiE2<=6uchni;e=;2QHA(CLZHZ$axznLmQomok6idd2mM`3u*3uJ_DeK`Tp{ zzk$}2GJj|OA+(39gxf)=jXQ{Q5$6i7D}vv6>Udg&ba;w{!h~J8^@Lq`MY!F#gSaDj zr8w7dZsB^yd4PKp=Nz61LNmB`2#at};h84HA;iHwOXwVThfs!a7<Uc#6z&Dw%Y;@5 zWpFofp5ffZd5QCw&>jTjcHj<zK*4Vi2(nAq1p>JvAdu@B_a+47nZUgR0zq~Nhe4oF z1_W|m;=ClZhkFwYb35=%K*mCCLNmC7xObpq&K2BKkTKU4o@o#l34RmefP@A2EFm4C zb0|1WC_@N}**^)p2#3KiuL$=780L24UWS5$gjR6}39S-Z#T_A(femx6<2=LljPnvG zj5&{S9)Mtw8A5y5f3W}KVBtE)(*=&PAkG6^SA<;zzwxxdVv0M6>lx=3!Eap8xYuxS zaR>;9@vIXL;|}6>1Nn%j4x*2z2&9i&4-^NSTevrI?*PRZ&jij(oV&Ppa4!SJCFdoO zOJEq}BF+|`BJK`Q=z>GgfoB5OGe}5*#6TD%4hjWOOmJQjngJ3c1%veC!yrEhae!>V zg<&BIaxV;n!kcpucLc~Kg5N+oVXBa6kSqv;QUXs4_biY)5C-wV@eEB_F!zDn0+I(| zcx*%C6qJHE4}eSqsRpS)#vpeI?E$4sAstYj0;vI+021d=;t=DW!XYEX!J)+SheJas zgXa$j3cGOVahUK#aaeJ7aX4_earkfqaYXP;;E3ayAjHA#!0jOH!aW5PTO27ISsVo% zWgIm;6F857cN=wZJmR>+(Z?}`V;08(j%6HcI5u(Y;Mm7;gyR&)1&(VRcQ_t#yx@4p zsm1Yy;}<6bX9Xu4Cl99(rv#@QXA7qarxvFHrx~XWrxSM^rw7j&PCw2N&M3|Vp$yJ6 z?i$WHLNh=m0QW5J8qOTfBF+lVI-V%b7S1lt37pfoN;v1hFxba!LNh@55E+B~kB&JP z35$S29u$)37@8|vxMzXl34~GdrH;@!P&x%+aJ)hDD2R<53m`VP9(N50gF+t}gK`@N zhUQ#QY64?uTqCC;UMcP-5C+8q7;oX+#kqxZ7bs?7IT=LrOcPqgd4}^6sH_s&!<EN* zgQtb_9@inRL!3`IpK!k7{J{B*^Bd<ME+#GxE<P?1E-8U|T-&%5xYT&1xOBLTxQw_g zcv>K(AB5zZ!4<=0$K}H1#TCF6#udYr#FYV(0hPC0d0Zu2Ra^~RZCpKElelJZ&Es0a zwTf#M*9NX_AbAMp+QW5->jc+1Q0XuDjq4WI1FmOW&$!-jed7AT^^co{n~Ph3TZ~(V zyMud^&?=s3pm66_;tt~0;AsItAstZ3&8^36!fgd&@k;T06AI&Y;As&G<96fr0i|N0 zJ={Tp-?$@$bcDjV<G53}v$zYmXMv#5IqouWoiT;GNoWS777@ze?&F@qJxeG9RFiP8 z0hLoi=Y%qZID|5|_i-QLK7|!t;J$_g?{MGYeuM?S;C=^(U%0;rt6@U!U);ZVKo{V! z@xUMtj}RQn@t{Kq9yuNrDAeLXKm#5KG~>YrZFrpE(1XVh4nue#Fp4LECyghK=MPT~ zPm!<-PX$jM&mW;ZJS{w3JQH}P35)Q|;aSA9f@dAi7M@)^2Y8P0oZ-2|bA#s|&l8?k zJRf+z@%-Us;^pAw6XM_%;g#Z5;8kN_WU2u5>6pNyQp}Kk;vP`niV-}L!^8~kONxNh zFa(3oR{@`p!yxq^bT$hsNQ5y4)U#vw59;eNegczrAd;aOB+e)cVl#S!NT!3J9wn2> z|33_jOrTpX8JX-D#26SEt}yX2Ffuv(2lZ70!M(XzVA2Ilo&l3rK_tU@Fu4RoGPZ(9 zhPNP+3B1Ra@ga!K2${8c4`$bZ$#yUq117<<JWK&#whzcvjQ(JErh~~Out)@m&14T| zmw`#hJkBkqRSb-brHncZj0_6k{kgVa*(~sUhZmR~2_hN(gZjdZwqP;~G<U=31!hNr zNCq2FpO;Y^tnxcpZzh;+#xRqCkuev{<^`KC0b(=ygVZoFgF=t-GbnbLz$-wQA>)CN z*>Lde7?TD_mT?^@zL+3mp0B{{5|B7k1egSmWHNzQJ1~6*i-6ZZFw210%;1$0%;52S z<|SZ}Enspjh-3t_8P|c>OyDt3Ch({N6L{SVGkAW189buPJQJjbc@~Id0*^^DTZ7ol z;BkIt@VGQn4oHNl3`~Mor!av>SD3)-E|}6m;>=(lF@xtIn87Pgn8D*S%wRV#9|Wt} z4kDT2!6bMs3Nv_glo>oPzyx*`<6@93BiJQOVAGg3gG88igGun*D6<EM%?z1w@BzgX zV-lDw1C!n$k^y}301J3Tm&p^Po(b$nX7Kne6L^&flORZ(8M1Oo0>owl&v!7)29K%E z2E{2ecwT^cA~<%yGX+fGk$*<;Xe~2j<Oe)o%%lxgBM6TDP7s@MJBVb`1?5df@Ju(8 z0$8LQG;7SP2_hN)fJVR=!DD5N??7xOBM`~B8ca?AkxbxGJ|<@no8dZ$WPAo98D4`( zrZZqN8bmUJWtmdI>{noNBbZzRBAFaOB;#`s$pjuFWxNYwGadz#r$HpcY{<wP!$Sr} z1`$x0FbIK2=5i3ppaF6}!(R}a3A}QHX)lP)cm^cSBo6XB6L^N5Q3k|j<O7jRkhMKA zps^#y2oTB83?iBAK{3Uc3npv8q%4SJxCI`Y+6l_t4B)vW27b^;6a)Cg6$Z$uO5inY z%-|UcW^k%z0*~@Bxq#hM2`V?3m6#;Jw|s-|G+?{LRL8)`A;iGLAjF`?V8P(UaEaj? zLkvS6Lk+_;hD8ip7!EL8VtB&vjgf=ViLr%&iGd9?F2!&SR0=SG&RBtpFp7ai<o-*- z)G)e$M3_P61whp>Ku(<b$iTqB%pk@f13D3a8FU&6GXn<$AA<-3BSQ;F4<q>G31-kK zFH8(V44@S>pi}5zrc4K`xxv5ywh44U$aW|jw1NqIvIsNi><6fNM)0XE%%Ia#pdt)k zK_)OEnaKz_O9pgK13QBN*lkJ-8Vq_2CJc;BTNyy}Df>VqlR4ug(7G28o6!cuW-|X@ z3mS|5U(3M3AjBZSAjhD>pv7RoV8&p>!1!<Pf6zJ^I}rKLfMGoYBLnll>kN#H=Rxd$ zdztt_E2%&v12a=0*gv3M&sUfv85o&D7#I*S#q|Uf?%Z4q3ZUC4Sku@)a_Dk|a2jyh za^`auf$er;P+<sRFk^6H2w_Nro3$0R6PRfp=mueE+(GsmH$z2)7#NwiF{Z-QGq!{F z1~czP643{naEy_M0ZZ60sxvS$>;sWZ=1icKr#nGxMjH^D$(%t36gCVpNdDLZ@&`{0 zC}bIgSku_=vp;74$PvQP#?j8v!O_Xl#c9B4%xTM+3i20EGS5VK%G|+lharX`i6M!h zhM|LD7Q-@z9So-!?l8P#)L_hlxu0PcxCD94^aCcsC<aRXOmd8m;Uab*5#~guQw&Vt zbcaZPe?a9DQwWG;He~wC084+jz-(~ZXOsrXGTwlSfYKjmB`P#+G0KC@t_7P7Q4d*> z1u7GuY8W8(+H)oexQq0`WyLWj39Mm!6dcA!85o(&na+dKALCI_xPsVB<_w^912zo1 zz-a(I{q11@t+cZRk^l4=n-~}wnEr#>0p~#Me|wl7F)%XPf=C7?W*3-i7%qZJ7ADXP zF8ItgP(Bs51I3&0JO<FIQwj{98NM)OqMVbloOuQFO2`QrtZCpl)kTg~j{UH-3XW3+ za4Jn;I0i0Vau_NYx}fC^L<CgcOkk8^T*RouXvFBi7{ZvqSj5=EIDv5y;}*tuOa?Hw zGTMW}n+dd53lzFG42%r#m>x1PF?xW?4HnRfCukfpgVt1n)PPC}NbUU#q>^D8NF^g^ z{Q^woS48YFJpq}|{0yuT9G^@^ptxd=0E>W2Cl=7kBdEzt;Mo<H4n*8CX@bgo7SJkM zs2WCpP#R@!K%`M7c91PBpq1TFH4LXfx){%Z)mSmeFfcQiFo=O-f_Wa(Lk7@Y?VvJ~ zk?9I3H8NL$)q!2Z<OX&b*sY8;AXz3Quq;G`A5^0;{$jELhoBGxBP*zt0=1P1JpaoI znxTM+fY*RAU&EF%nIpmJFbPC5-3F(|SP+}>0hoOooH8F^PnrMuKxvY(A4L9Z1f@oX z5KziwQUJ04^MTSNV?T&w2ti7jilCIq?9L>?z{ViJz{tP_D#;mm7^W~VGWsyRVPIkq zW6}VfEyg{KdnN-T_Z;p`46NKcxOX$ia3A76!l1x?g8L+cGWR*|iwvsVSGcb-XmVfY zzRsY{eT(}RgAVsy?z;@S+z+`QGU#!?=6=nf&;5b>1A_tgckVw7hTQ+T|1+5L2=E9p zSnwG0STb1g*znjeIP!S%crrMF`aBHIJoP;F;2ZDdXz30f76x-3HXdFETOJ`EH3nB6 z4IWK~C>|XiU4|GQeI7%GIIznS!EQ?83FV1lNaji4Nnpt4N#n_7$l=N7DP}0)Ddj0= zsN|{SX<(?~Y2s;TXkl<=U|^iZz`&>n#UM5aYe2<8Y#0_}U|^JCU|>{YU|@`6U|<BP zLDvW3!_;G=LGmDdAUO~lgh6J3_%I9-1F?M=7#Km=0qPczIuj_{ih+R<Chi7R2hsz> zK@1Fx5m0xgFfcG?LG^*;3m6zc=U9PGAOqtj1_n@@fw7N)0d!Ix<17Zo|I5MY415OZ zKXBWJ0dlq&_`I_JY+zaNId2SL_J8o%mH)w~TKxx~jrkvZV%UH1=~(~&gYq#00|V$> zO@{xVdrukugYH0O_<w<ck%8g=2?oZ0V7&~GQ!&9O?12u^WawfP1Km2x7{M69*vF{E zsKltjsK;o+XvOHj=*H;7xPvi>aSdYx;{wJw#uUaZ#sbDN#u~;Z#tz0l#wm=m7#A=u zV_d^{ig6R;4#s_qM;MPVK4Lt@c#81?<2A-RjE@*!Fur5_!uShx6FU<d6AzORlOK}= zlN{47CKV<vCMPBXCNrijOuLx2Fs%dK)yFh}$p%dC0+SQKa!yQjV4eq<^aGPEU=pM% zgei(CfoTHME~aTrX>idTI18j^7gG^a1ydc<Iwp|5E~Z^z^&pvPV7uoqEn?cmw1R0J z*gnv?FHE2l#Tc0Xn}BOL(5bFW|7E~osRfEX(5bErks$IP_|!%QrvHHqj0`OQWx;Ax zz`E2xt+W4@U^eKiM<&oYb_`75lf9V0XTmZ6&jrh-fmJGjO#q#@%J3he7i1&ze}AwV zkSr6_J*r^!pz@08Kd1y__zz)&Nap`iVD<S7j11!cK`J?*vI-20|Ns66_1768BLBXF zRZ1~1{s*5R`~Tm6aj*zzEt?=y4g({DDwt#fk^fgPX@E*dCLRXH|8t;hB?iX-yFelg z9H8^V7&t&G8LUC%e+F=fDS}RA`+pFu#up^c5C$e?z#=kWwh)+P1B-Bj**qZf|DAuY z7#ROQ1F;z-!6Y-7<OGvkV3L<92VQoARvPet+K3EB3<V5~3~bz+xwmj{<=)1<od<MY zHYX1o4-bzFPcBa(PZ>`YPaRJ)IDbhoFff45!vnSTL8qjF#&tk3#s<2%mw}NH6dMeT zptxmZ1jPfWd}93npW!wGCxZeQiZDolX%LT*A&d!h4>32G<YKxGcOMf2BLfe^1qMdO zHEb#jObiN)!Hgjc3@is(4l*#Yy<vO9z|8iJ?E?b~+i$kN4D9S2>|6|7>=Nu!47}{B z>}m`G>|yL-3_|R!>>UikT=%%{F^F?Fa!+B9;NHW1kU@w0DEDy&Bkt4OXBkYnFL7UD zumFwuF<5fn;J(RV#eJLm4ucK%J?;k#cHED+Uokjxzu|t*;Klus`x}EF_h0UR3?V!W zJp2q{JVHE%3~4-8Jk|_tJa#-D3>`e)JiZK*dHi{j7^d;0@zgP_;%VS%XE@Bj#GnFp zJp<c2ws#DSV0SZt-Ob7_#V*Cb0d_Yh*sa`PxAK79ssMJY8rZFxV7Kak-Kq<As~*^` z24J@ufyOBrOu3(NzhW>0yVx4+VtcTQU3nOISQy-S*m(FEe0YR-G#SFcwN@Uu)+zw| zp&0CkQm`Kyc>H;S7@EN~SUb1|>j&3h6L|7@${A*W>#l|1x@#rFX$A&nJq8A59|i_y z69xumD+UH;2PhvT<_2YFF)%O(F)%PkFfcI3F)%QvFfcHK#0nS~n9CR#m}?jqn41_F zSc*_Fa|Z(hO9DiUxsQQ?c?tsq^DG7imK=x}OB#gDynulL#AaRw6)$37U|xfycM}5x z^9u$B<{b!mkh!29D)SMj7|0$F2I;*6)eGW-FvwjXyFfHZ{uD$H^Bo2T5N0uh@G;zf z0U{1olf%Hkd=27Wkb009^CO76;rc*!fb0Wds9kV5BKcr{zJu6Hs$Qz9Ph((U{=&e( zBE-PJ{EGp+%!Y-Hfq{hwA_fv?kzin8kz-(BQDI<U(SnA#0Rsbz2Ll5rj96?K7+9R3 zd_M*T7Enn*C>%gx2f|U%FaWVZ;Yvs!E_qm5!zE9=I3pu?x8A?opxz7vc&{cy9f-{+ z3nmr8BzW|k5j;Z2s0S7Stx{rS1dSpwGJ;3<7`Z^=44@tl<NyDRpw+0W7!4U1|AAMU z{sXUrWH1A%`3D{mV_;;eVPO0R9v}Swhj9X^mIISVKx!DkJ1hRJV@d#tgGBy;cX#{; zj|elcfJ7J=K<XJ7!6XZqYz6mf6u~4nn3M*S>R?h0OiF@DRWK<BBLDwke8#}|58NC7 z2i|S?54`T}-&2q+|Nk-V0ksa8SQtQchdqb{i8FxLD>H!C=`w(JiL7T#U`%7oVXR=R zV=MxbEsR}^6Bws4&S6}{xPoyV;}*tUj0YHxF`i+(#CU`89^(_nCycKcKQMk{PGS7R z!~{O6P=pEjoWKkwJEm>0(*l`5X9dQ=&-5!{s$z~~YG7((>H(eMhje})==475`F+es zm~OGKG5uiP!NSJE#@qpdpcDN-eC97KY%B~+Z<s!T<u-vxrXS49K%&fjO#fKenEP1R zm|0lZm^U$Vfn-_Okk0wjV>V&70-xlEeu`fia}9G7^Csq5%pD+IAX8Y_n5Tf)Fw8uQ zc>(h>=4H%lm^U%+VBW`kg!vTn1?FqacbFeBzW}LXeg|?N^DmHVSQuE?7#RQE1?|9N zXaKL*RsoaZVA2XqYBR?$Ff#Ii*JxXSNQO3$I8!pCFF4Mwf@AR^I7R+tVEp$1)F);z zWBLbbJAv8Y-Kz|YOrY^y7SR5He`lCLt#U@D<>3CN7g*&FaH<9CV)g-xJOP`03TzAL ztYRi+c91wT=$u_9<^v3j|Br!fu?Le(OuxXgEMRgDn2Z6Fp!NzAGiW@Q8Dav{5>Shg z=>b?4)ShGj?b~2r0NtDX?+w!@u(&eVUXXhjKsz}YSU}{zFA!gV)c<<}TIbHd0NNqJ zzy@{$Gc)K^ekSlvXeMURIq1yHHDJ@6L2VsoCk93a31*Pn_?YK0Ff!<YNd_iR>kP7{ zn-#1^5KM}KNp=wV{~xn61LObWV7=BL5e8;vaGMNdBcmp04J<=DXnirmYtSlJMn};4 zR>mYSTMNwA1jPlTG*mrkm$p39evsQh>+b*m1C5aUdk%8>Kkz!re;=6cGBEyo2J+*- z=OB`Siy3sM0SDN2UogoBCd0s_9Ekk?2kb&_5SxJu>^m0F&Hx5BkjVdCU|BBEZj%3J zplncRD1ucAfYdPX{|EIrBth)||Cmb{7#TQ0Yz8i7CwR+|85EkJu?>bChH0RF0{2wz zS=_U^FEcPQXz(!dF!8YPu<@|-aPn~RaP#o+@bbv;$nnVYDDtR-`tm#xJlQ<CJo!8Y zJcT?(Jf%EkJmox<JXJh3JheP^JoP*cJWV{!JS{w}JZ(Jf;OY!?&kX3?Y0#Y<Dh!PO zXMn<sL5r!2f${%)rc4G#2GGol215`-1VbFd4u&j-YYZt2WehtQu7P<?438KJ7|Iy> z8168XG1M?LF*GrBF!V7@VVK3RfMFTK8iq|^mHQZuFq~qzz;KP>4#Ojc7YvLH8Q^d# z2ZvAwnA`*ok9IJ55R@($ioooPU@{j>R)TdkfZ0`GvH&b%4GMdP1~6M2OdbQvwt~qJ zaM;Iz*(qQ$02~7~V0H<ZtN@cqV3L7>i}4b(76Xfmn@<RXRB~le4ue~IQEE0rLr!8z z9>W@N*fIS7&maiy!!t3kFt9UlFmN&mFbFaTF$gn=Fo-gUF^DrrFi3({69)%5DKHo@ zAnRboqXVRlk%1q>7B)P3lo(i@9YYitynG!!6c|c;{e2V|=J`2>DKMM}^7mB$opq1o zUS>Qdfoun*3q}Se2ADc7tUkl0lACCiJVdMHC0ZpPR+UnTi8&<<^OB8<lNpvJCl;qN ztVvGJEnwILCJ%tgQ(*F1N?v|0!=tpK#AJpSIeDeI44-oHlXDn;fXRO#l92^Wa)C(! zFe#Q-np?yulb=_b%czuJl#<7&Q2=7=6_w=VGMW_UCKoVT6_+LzGddKP78EnOm4IY@ zs#1&c8A10kK}Llb7#JDA=YlhUPGn~VhdvtvGq~@{4CR3up`ch{W8h#wu)$}#Gk`{t zKr>{ZR0lE(e76n*`2GS09&kE^jC+Dl=4XJMEe}b*ka<8*-<Xj>8mtmj9xyUM&Zq~U zj?Mr{5yD_u$jFi^gBpV$LlQ#+!z|FMZN>u}A)G(Bgt%O|T)5J>KsQ-`;}+vK<M!g- z!lS~R6?!ehi!z*E4}!E=G<6E7EU0Ph6eYXSj6=Y;iyL3Ieo)u8)I*jToLYEYJw z4B&Iy!Q)<_Q4bCVX7-irtJqhAWEr`^`2##7DRcrfzXd8WxtJN4c#Obd#>Bt{9sviL z`h$Uy0W|&s3NwhA&ls2(L>NLqbuj}dthtzwM}TK@?`B{HkNv7~pWr^lpa~xP)#1L( zeU-t0`#Se624n6!+;<tw!DFSC3``6HkRCF)_sa<G{fdHnztZ5|uN=7ds|fD>DskWD zzRjQv?y0KqWb<S*sPh!?6ftOk%4-H~o*JGS23?*yo;n6So(7%<27R7po;C*1=oH8& z91KhhY77D#S{ynY+8jz8${aQv#;oZaCLE?5W*p`m795rwRvgw0j0^${J`BDL9~s{< zeqh#Mkz_Gt$zrKzxy|aw+Qd46bqecsMEJ4AF^Do4Fjz6TF!(WKG1M@$F-%~X#juUx z1mi8HH_ZQ71=y6>blA+;9N4_rKw-whaEyV88`REWVYmfneE_pS^I`%FV$3HPn7NlT z`Y^dOFmcajhNuV64={OxL>P_1su>wr7>>hPx8bahU>3}*lTfofKsuQr>LF%%fkYTh zz^Y{!tQedaycmKQq8O4GvKWdOsu-FWx)>%g%wkx?u!><5!!CwH45t__G2CK!#PEvY z6T>e?21YhU9<I*}%q+`UR&ad<(<`~Yfaz6SpTP8LuD=Y-EGt-+bNvU?E4UfK^h$09 zFujWFADCXv&B?&bvXW&vH#eAG!OaV%S90@!=~diZV0tw-GXpcrDwgHktYCTtH#?YK z$;}3)S8=m|>D64{8JJmCvn=QO38q(Y{RY!3xqgA^Ra`&7^lGj@3`{I5xH%Y@SXOc~ zF)*>L;`+wG#Il-!>=5DB2K#(Dw=S4o!L1LbS90rt=~di1V0tyT8QAB`xh=u;N^T1< zy^7l$Ot0p41p9b7w=<Yt!R-pBS8}_6=~diLV0tyTHQ2|?xoyGp3T}Hay^`AwOt0d$ z0n@9w4Z%KM&TR~)S8$tx>6P3jV0sm|5tv@ht;N8^vYgui93obr5aBkUFhr8UK3>k9 z3Z_?Zr-SL0+-YEX6?Y1lUd^2k_W5$|LNL98yBJKb<Sqi!tGElm^lI)Zu+Nus*MR92 z+_hkO6?Zk5Ud>$!_VIG=axlGuyAn*V<gNhItGLU+^lI)*u#cB>XM^b#+__+SC3g;( zUd5dSrdM+(fkPw@oKi}_A(BC1h`57&yqwz;Ot0Yf2Gc9Ky}<M;ZVxcMnmZWm<K^6; zV0s02IGA3^9R{XXafg8E)!eaQpD*W*2h%IK6T$RK?gTKsiaQQWujY;b`+PZf6qsJY z9Sx>eaz}#c)!e>dA1~+j2h%IK1Htr4?f@{oirWuNujY0Ghe!}OL}I`x#fQQW;b#Dq zBg?r3!So7lVKBXtTL?_A;uZkYtGOk?K3>i(4W?Ic%Yx~Z+%jN#6}J?aUd^ov_VIFV zbuhhxTN6yL<kkSwtGLy`^lEN-u+NusD}w12+{$2jCASioUd62drdM-|fPKE4TNF&M z;1&ndE4jtM^eS#XaEM5NLqr7}B66UV0;*X#)ESt#K7v`AaMlzCCLT|)*g81tAe{9Z z$`WNzVbEaEVK8E_U~pmZVDJI;CqU&b%Sx72EUP)xI5aqVIhJzl;P{NFlNcv4Ff;Hl z<S{aU*C@y^sKINf2=+b(7VZx2$=ogMy--#&`vfp+3U>>8Ka|zX-o?Pe-3?aP31v02 z_kdX-b=^=_GXoEU6oU$b9)ksg6N3*!7()U>7DEX`9YY8EG_YA9o2Eip&FnM4ERYG) zp{!>1B@8UwjocmFE$oY-tY-E_U{*JG3;RMStC@Wg*iMjn6QQhT_9<W%$h^r=7Cslv z1KSBQVJ?)_%)S830+}!$%4%j`0k#w5qUBIlGy5_y3*@4uP*yYhEU=v*^JYR>&Fpi) zERcD#p{!=m*aBlMV=LoCaGMF#?gF*2m_Th1P=6cL&Onk8W8mPB=4jxM;b`QL<!IrM z;{dIn<zP6*aGc>5!)=BS3?CVd89_5|4B)mKXiW_ZXrCbHP8Lv#Vw7i80PT50GLw&i zg+rdBi9>+{<Qf*xtuBmgjO^gn9w@CSFqnW_j7$tcpmkIXL14XnP_Z}$4F*PrIItK$ zR4fa;ehf7F$N*j$z{pUENP*yXCm*P-$p9KnVPORIh_K7+gIx?-TZUDh<2Xp3<1_;k zLnYXLQ0Or-u(5+$P>hVH;9^V+Mhs$HeO&!qSGaV!^tkl747d!rjJS-sOt?(B%(%{R z-sgP4`H=Gw=VQ(%oKHEQF)%WSF>o{RFz})EI;9w-8Dtm~7`z$$82lLm7y=oB8NwLC zk!(_7;OCmbHIwTqyDdXCLkUAElNOUUyB(7blP<eG*Lfz;EFnK$vq7_=kl15n*un|g znF`~vfyO@>7#W1%_AxR{;$j8I6e!gwF)%}A!8aQ*Ffd4h!kI}7E)KcjiGe{1v=5hy zk4qff^MITG{~K6bf=iKs0dA@aST|_y6Vh8@V2}Z&Oa>JO7qAS-H8N0hWI*~Egc%@w zP`E=<3n*s5X^|m^p$3dWEmRc-BL){}dIG6nWMG51fb%C8qW1=Bo9i)%aK7jK!1<B$ z6X$2nFPvXFzj1!&{K5H?^B3oD&Oe-gIsb9~=VIVu<N{BZLtMbc!o>?3Cjh$*Y6`aa z<YM7s<znMv=i=bv<l^Gu=HlVv1^I*XJ*F$Lsm1RK&i9-@kX^xO#W0I&C3ij7I<ECx z8#sD7W^v5sSje%IV?D<Pj;$O!I1Y0h<v7l9mg5}96^;iSk2oH4Jm+}F@tNZv$A3;1 zPF7AXuH{@SxR!D)<66z*#kG-R5=S4$1diz(6FH`G%;1>Ev4&$A$4ZV>9Q!zSa_r{V z!?B3tGRIAhs~p!k?s44UxWn;-;|s?(j_;go91l4rbM$je;h4iQpJOh^VvZ#oYdMy4 ztmat9v4Ue0$3~9L9NRgzaU9|}z_E+tAje*g{TxR)j&YpeIK^?2<21(^j`JKBIWBNq z;<(LmjpG)_eU2v_&p4iPyx@4v@rvUm$0v>t9Pc^)a{S`>%JGNeC&zD2MoxB44o+@P zUQQm4X&f^-?sB~0WaebxWa8xHTEn%LYZb>wj<-B^JoY>eJdQk0JkC5WJgz)$JnlRm z;QDYD0}BHuIPWMis4#$f%IXXn44MpD4B8Aj47v<@4EhWP42BFw48{y545kcb4CV|L z43-R54Au-b47Ln*3=Rx&3<(U$422Ah3{4Ep3@r?;3~dbU3>^%e3|$P}3_T3J41Em! z3=<e8GE8EajC2FmEQZ+(a~S3_%ww3(uz=wZ!x4sK3?~>)F`Q$#z;KD-3d1#q8w|G? z?l9bAc);+4;TgjVhF1)47~X;Rbbn^}%J7}x7sDThe~b)_OpGjyY>XU?+>E@8{EUK( z!i=Jf;*64v(u}f<@{Ed%%8aUv>WrF<+Kjr4`izE*#*C(n=8Tq%R*W``c8pGpE{txB z9*jR3e>47N{LduJB*G-hoWOpAyOFzzyP3O%yOq0*yPdm(yOX<%yBpk_gye4~MjM9N zh?ECPMP#KuM9O<hN!sJ&KuUcJu%^E)Xep2y=?`z}!;|)ABc(l1I&xufWpHC~XYgR~ zWbk6}29FBB>VzPMV1^KeP;ku<!4Sz1#SqO9!w`#<_7*ZMVpz<ugkdSeGKS?0D;QQX ztYTQru!dnR!#alb3>z3WGHhbljCAYTE{5F<dl>dI>|@x^aDd?;!(oP_496KxGMr{O z%W$6IBEw~ds|?o}ZZh0vxXW;#;UU9ghNleA8D28HW_Zi+p5Y_I7lv;PKNx;9{AKvh z$jHdd$jZph$jQjV$j2zaD8wkjD8?wkD8(qlD95P4sKlrOzPn9}QHN2F(SXs2(S*^A z(Sp&M(U#Gk(V5Ye(Vfwg@fYJC#(zu<(Dau`IQ20&G00&p!?Bg?Sj50%b>Nx>Tsv@q zOLq~ZnvjhVG)KtD1zJA>N%4#fY@8oJH6Vj90}GQI;{?#!XQnQu2nGfQZwSp8$6y4y z2at)Im5GIwg^7vf0Rz*22L=Xt4h9BI1_1^JcYl9((0aE2e_3?@-DY55(PaeP>k3{1 z#su1x0b2h8x>XNUV}VA&M8LHo1A_<y3zrlF10xqB0|Pq)Xq1qbp^njj(U38bF`2QR zaU$a+#`%m38P_pxV7$Y4m+?L02gaX_|Cz*@q?yc^%$XvYVwrX`?O{5~bdu>h(><n7 zOrM$lGxIR3GOIB=GP^P-F_$yfG1oJ9G50VpWIo4yjrk$-e-;K79u{5}f0h827?yaJ zCYFh;!mP5a>a6-wd!_ctbja?PeJ1-=j#185&R(uwu2pWf+<du@a{uK;<z?kv<$dMD z<s;>z<zwY*<+sQmk-sc|TmHTL7x{k*+zKfQg$nfwoeF&lQxxVXtWnsiuwUVWV!UFD zVy8~7PQC7bJ(p$0%W9X+UoN&>arwICTb6HM{%iUFm3phAR;T`E`^WH4|KI=rf5GeS z7#MgN6c`pT8ZsI&CNZWkHZV?NoXog@aS`Ks#*K`38SgQEVEhPP`zFC8!(`56!4$<5 z$FzrOFKA6K(+#HkOrM#)Ff%aoGOIDGGdnT6F()%uG1oJ<F!wO`F)wC5&wQQv0}JRL zK+r9K0W5(mu`CHJ%`B5xMOfunHKaC3?UQMcWsp4}`&{<79Fv@#oP%70T$|h+xdn2c z<Qe28<Q3#S<O85#5ij2$zfJy_{5AQz@}K0tDKIGTD5NQrC^RT^DNIn9s<1#|t->~i z4~h)nut?C!(|w@Fu*_ju$+EiT49mrrD=pu!eCzV>%YU!bTWzp9`ZvQrhJOnG{{R02 zx|RL^*Z+_IA7cCY{~+VP{|6Z#{a?@ckYPFFeTG?#ciFrd?=bi>-u~|ax^12DBI{Si z3k(d5Xa6^WZmDHF$-uyP=zlQdK?VknhW|_)^_-j>)eH=bUaY_Wp8tF9@7cegyKKKP zy!hwych*0Lzcc^-`#Xby;qM0qhQBWv7?{>DFno0SSpVkm^EV6(?<5%*p09es@_fbP z%IAw17@ov3Fg&+=Zu8vgxy5s{=cdn1o*O?mdT#Js|GD0Co#)!mHJ@ud0^Nwoz`*cw zEd#@|4KKYI7@o~%V0f0s!0`0Oi&?k+GBDf&tp{UBeaOI&Iz1tVfgvFklyMTp5?kUx z_f|6S88I+0TQk{%^D#(@7!0}(6QmBA2Hh135_<(Apcr%?I+V%40KV-U&I2(Rg&?Bf z6}F%g5J7?rpuIAn^`>ABsOdNXvi20l$3-*tFxfB#F)%QtfmASMF)%PSFfcGp0Pz?Y zm^~O6m@}9^K-Q`-FtAKwU|?Or3c7<Bw6$an>j4G^R?yANAR9dxJwg374owy<4mA#S zMlVKhmPw30jJ}M1jQ)%PjDd_nTpz)8eH*xr@8Ry?ZsKlaImq3~-OAn0lg(4aQw}<D z0X%0}##6)7z|+jr%G1VK##zl-&RN59h~+S61!pa1CCf=BdnN~#Q!J-h&M-ML`7?fH z{Kn(Y6TlP56T}nDRLoSuRLWGwRL)evRLNAu_?__w`w{k|?8n%Tv!7r;$?}5bCCe+8 z*PLRU_MGCJ4xAF4j+~O5PTbGApK*WS{>c4?`xW;)?)%&?x$p7Rb3fvK%l(4;J&z6d zYtZU4o)VrMo?M<ho_wAPo?@O-o;2{hYC2B_Pc2U-PZm!jPZLiyPdg7kXq`9r1MY`R zE=;Z*dK~)fH#k%n|1&W#`!feH2QmjS2Q!DTU*phazr|6<ew(A7U7cNnU6WmlYc|&$ zc5Nm`CMG6kb{!@bCRQdkCUzzcCQc?UCT@0JCLShUCO)oKu4t}CCVnn|uB}|#*!9@; z*$vnY*^StZnFP2lGYK*Yv72x$<XXVBn9BxK-*KfeiE=$*H|1*Kvg5MlGUp0l663Ps zvgV5CO5pO~s^ZGvvf#4hisH)Rvgc~xI>S}U70l($RmQc5%a6;8tBK2(%ZaOo-HdAs z*M6?;T)Vh-a_!*S&9#SXFV{YHb9M`MOLi-EYjzuUTTVWd-s4rSOI+tcy-Ox>t}9#@ zxz2(5wCt|zZtU(%5=@fp9_*e>QtV#r-du;7Lz$$x4sadeI?5i(ewFJO*FmmBT*rB) zaNXg$%h|_upX&jW4A(u*>0Gb59&xVbZ0Bs??B`t0xq`EUvyrotNtWv==L9A>_HeEb zoD(@GadvYyaZcuX!S#yk4c9v+d9L@IQ@EZnDR7<OZ02s@oWa@4*~VGVq{z9Fb0+63 z&K}O$oU6D_a-HV7z;%}EG1qObhn&kemvT<y?Bcr4b%X0B*EOzNoKra$axUUr%(;Z? zCD$pg=j;*ekz8-Nw79gnbl9WVqq$VLRJqi+)VVacG?|o`l$lhRRJoMcue0Ce>0-}j z&tcDH&tuPLFJLd^P~|Y<FyK(+Fy!gr>E`L-%Hhi93g;@|3gOD-O5sZ8a^;HPD&$J# z3ggP>a_5TU^5IJ73gmL;a^vdZa$zsx3gU|8n#EPg70Q*zRnAqx70Fe^HHm97*95MK zT+_Iwb4}rz%GJyj!&SoN$(70Zj;olfm#da5i7Sz-p38yDk*kiYnrj}{T&^~*cCHSt zPOkY}U0h3ert(bVl;ZT^l;-s1l;QN_l;!m2l;aHGl;;fORNxHaROAfiRN@TbROSrj zRN)NcROJlkRO5``ROgK3)ZmQb)Z~oj)Z&cc)aH!k)ZvWd)a8ul)Z<Lx)aOj(G~i6) zEaC~_N#;r6N#*M1+RRzZX~>z(X~dbrY0R0*X~LPtY08<-X~vnsY0jC+X~CJrX~~(* zX~mhtY0a6-X~UTZ-mPZGS-@GsS;`a7lfZt5!<PLnhaLMp4tw_d91iRcI2_p@ayYR+ z;&A40;c#Vt%;CoVgu|WvDTfF9GY(Jo=Nw+_FF3r}Uvl`czvA#^f6d{?{)WS!{VhiT z`#X+6_V*k?>>oISK|9LWKXHVzf942d|H2W@{*@zw{ToLl`*)5g_8%P4>_0hT*ne@v za<*``vj66YWB<bu&;FMqf&CvxBKv=iBn}3SWX|W{n{LxM(m66XGC8t1vN;$zayXbc zaygheSUB=HSUK`J*f<I}*f|P0I5>*f>)7kr8`vA!n>aW*iaGf?xHw8UxH(EeC*N?+ z;atZ#mvcSmJkAZA^Eo$iF5uk6!NXC;!OKz3!N*a-!Ov02A;3|^A;=-bA<QAd)5lTG zA;nR{DFC{8k)xKoj`J1h_C?OOJpDWqcqZ~p;=ISx%h3kfF9+T?*Uizx-pby_-p<~^ z{e=4|_hTMo9upo@9y1<u9t$2zo<ttVj!4j+3D6!N&}slJ2ha`W%uEc-sSHevj7*^n zOiYZiER2jyjJ^yE>};$o49pD7f~;(!+Qx#4f~tywigApy|IJ`D{dbz_)L%1WCeZE# zCI*lHpBO-Ux|tdH8RQ*gK$S@>10!RTHv<zBb36kxb2qb(in5>p3$KK>xiaXYWiw+V zF;NjVWhJ%6mXg^eDpHcFs*+MFCz%-k=BUcasj4U_FfcJVGM)gRgbs46ii08(BLf3t zEGsh$Gb3XYgAWS}0|N^?3p*Pt*p+O&qT0gD%FK$)%FGKy%taW*M9f8)PW}7G$OOWm z@jOWe2Jo(JX$E-)cLx_9E+!6s0bXWy1`hT#J~k!>R%RwfCI-e-ZbnYdCT|u-CZ=X4 z9|i__IawJ7X$EO2NeOW=Q4wK5IN+7lW@I-ORc2Q<2V+xXb7fOwb7OWe7G*UyS7v-5 z-#JawU9(@^O|7n5p>2|ehsFdASB?6A_5Jewj9V5sU%YtnqVoc$D_5>uaayndv@_Q3 z|1l;Ortb_&44MoE3<VA%23ji0Qj%h#oUB}oOo}W_42(=(-WzlSA{=B{7@3$EnVA^t z*ce$ESX)3X8dgSz3<hTA7G@u52So;ECgx@qMkYq4W`qhx(7hiF384N;K%@g70|SE+ zgOZ@2n5ZB-ucWrPshXO)shAjuHZ?IbH#HU&6BB1wQ&Sg}V-gi%V;5yMWn&W+5fe5u zGc{3D|7)J1pp<2t9Frd5U>dF>t>CNS6rr0D?_g%ETVriz;AoZ2D99fwAi;P_I>_BC zgf$|ZNrc~vSD5*vu(rLCTR2xf<L!+sT8bLl|1Ps>E2*i0mNGD~G8q2<#>~fbg@K!a zpFxsAl|i3jruPQPfCvX2UPd-PMh;dsjtmA?21ZU+#&jM=78ZthZe}iK28J$g22M_< zcy>qxN;{ZfD(7ZoW^VF^XaaSWx<F~Q8KjRro`Idco82eUL0er-T1rrWhli0tS6fYA zU0+dNN>y4_TvR|(P?CqAho6s^ot1%`k(-}aL|Yh^piNE8SQ(WWS(QK`WNc(=!ipp# z4i`P_>Feq1?(N1T`me;7vFBflnzFK*FJlH&*aysIx>A~zRbHNzRm%0(jOmm~U_e07 zqJ<A&g7yIcfq{!a`@fkPO#gply2W&rL7qXI!IYuOfnQCEjhT_fRFIFIg%zA!Kmn)B z4h|+ZMsOf8GBU+8g96E$ft3}?WCA4`bXBnoOiaxnMX=l)=^(DCz{p^1sGzN=Eh;R) z&&|ak&nVBqE27N^_Aa})nVGpU8yma0vN{_mpMw&TnwqJJ86*hA!AXZ1oQ#Z(%*+`L z0%8O04oWF<M+z9IO)3x9FA2`540cyAPYTvDRa3DxHV87a^|Et_R$#gs=xHCJvP(Wt z-!WISFGR~EEzT!SLnX-EGuT5%UBy;a$wpH}@81apCo^*=Ezr^#21Za>!T{Pe&&(j{ z0N$w{%ftvSM!<W~nFX1l#RsV9fRq}bCNv|1#{VQnKBiL)ybQt)0-#<!XoGqagO8Xn z6R()IunE|gq9S7A%4%vF?moe8?(VKZKJJV{Rga_N9+j8ekBhhu%4c%_lNedx=72Z4 zGcq<YLd{_mVPjVY2Z_3|m>46AyHAj-ySrO3$e_ym5pnlR${)o=KW1QL&}1}Y{KNEv zfseu1L4cQsn~ReJR8TWBG4e9FdvDMTh}g!+$iUFT;3K^S#3+e$;ACK6;A7xp0!0qH zxj4HxyE?nNxw^TyI-`@w0lppOVWGZ}rQ7)Si8B2-U>3taPk;S-{dxQ`W}sD$Mhy8( z98AFs+ze_C$_%UwOst_Sj10_-;DQpAY+@OhSebmmMWO&3uaq{Uv8b}BvZ=DEv8gem z<MHDj$B%n3wz!`==YAd(4x0b#84fU%FmQls3MP;X8ACxa!4M0Q^<@Cf5ORosV#8dV z4IC)uJK6aRBpmr<*-N-h>&+}XKwJJ8G#H*TN--KUFf+(GNHZ`nGBSjM>m87hpxO&u zCxDGHH5S$Q^wiG}5})9@ilLH$8yueu42<!h>w6e|RFpvRX>Nk3nLJb^CDqg<B~{E| zH4?~$Tnr41Sxl!G!08C&@Fs5t28Lz^AEb1|$f(T7nDy^l7$X;`ngs79HvIpMiJR#v z122Ol$ma~q%wU_r<qktU0|P@hgO7@esxqjKWE6pA8IWsOMZ}DaKn1O`5*rh@L1t)W zv3^EqMcKbP=fD70*MLB0#<Y?p5r@~7ED1ljZt|pwQzlKC1PTj=NCpN*(D}?f4AKq~ zT%4?+({;Td6*Jh$QUV}9D=G_`n3=P&v9qh28#5+{F);~93;XCD^kn?3Z6YHeCTM3p z4H9++3=B*hOjj7B8MGYK`FNR_8JQRvn3+IEGQ~46F?D$}Ff)T95)>Zlsv6)5Us2K2 z+>XiAL`_+Vja}Ug<ReiLkZq!hOdS6-cAI*uxmlR{Y3gg`x}=oo1({D}%=FxA77}1+ zZL6YSt!$VUVUd(zIvF(B#lXm*`~MpgGt(6YEd~b%TNOr7V}Oa7pOKM?kCB0q#Y>fu zh0&9NnSqIsnJJxtg@rYqft9t(8<akvfvl>csG_O`PN|@(ObpZx0Toc78V?%I%BD~T z+{KJ<1D!)dtt#U!5_EJk3=%>!<6Ye%qTOt)f;4p03Ox#PnUp<3`B=Cj-0c(01jT~H zCA^)St-ZZ$O)Qn9Y~*xO7#Ns9tNNHUn9eb9F^Di2I_U8;vM{qTGO#dtv9U6-FoE39 zkj4P2mlzlsn;Ct$xw%ESMFfQe1qDFWvMMNBDVj1G3mPkfN>gPvHg;wvjf~KLs~7{K zGxjnwv2aLmUt6?jkvHSRf65O{JQam?`2U@U#GO4j+)gpbF}OH5%7`;DGl+39F)?#8 zGBPoHf$9TLGccWjm6auyfrSO!bOR^QZblzQaMMRbh>wSzl|hbCjvZ8xfJ=F0B{igA z1BI5bqNpOfnHi&SZgX#)MS`MAy1sv6SgeePn2t1K+P|lQf>w;%@>25aMTCRJB)$FJ zyt!Cq7y|>&GlLdEGB7ci|Nq9s%XEc7jzNdP&cT|4k&%Iuk%>`|k%g7ni-C!Om4%5F zbR!Ko&vbdSF|x40DkTMZH5GXs1sxT2RTXw#32k8$J0@czF>z5fHDx6}CU#?3;!{>q zQxk_}DNr>nW-jgCkSb~{AfzYe8e=NK%qAY>5L;B8;gaY0$==V^Ro_ir$%WC-cWR{v z3#&I9n_fVMwX$JhMnQv1Pg`K9OMtqqymlyPWxWmq0~6?^b~Xl82PIa}Nx@#Aya;Iz zgDYE5lahgrflW}5g;z}5m{HMGQIxTRQT1Ov<Nbg4n5qI?{#JqFj2YDaVd4VkHx1Cd zl7q3avM4(XGZUj1D<cyVLp%$l8iy7o-Hbl6GN7i4jE1ZRKQDtcqcj^lrr6lQO*dsF zP!()u4z7vKAXTv#v@V7fGwSMWY>cvT6{>csIv&~$StZq)F6yQp76~>MZpt<)Chl(M zy?i}=gIolhT$!#!1Zz7O3X7Sz8AfHMMjLpV2+4&ynfYkAn;NMaDGP|%nHib>(=c&$ zH8*jUVw3d%<pZPt-@xSvG>!!rSy@2okb{wdk=YAW$1t)orNd(uCHKPOSXEsG9LJ0z zd`ys3Xl!K1WUh={aEhrzTU+3YRgH;5+PyJV#7scl&@I|bf{9H$$T6nSBHh&`&*77u zzq6YGIFe_ABAJ!dn^(_2(@M#(Fx@-H%C);KD8$uY-9|w>!~zsIus)9(12=;>xIAZM z1gFSeP&*QqAXQXUltAUVFjB1|h{T51FtD12@sXOGoSKS)!oLbcox{W+|G%E$5EIBQ zQ3fRkc@{=y1}0|EIZRMH8GU$octm+b#Z;77dBs7E5_tDY7+i_kF`2umNJ^=yN=d3@ zvGW>AIB|*yvLbBT#%<bQsu~drTCB{#$Y8`!!o<mx07|5rnHd-jv{hA2RYh4@nK=Jx zGG71J&RAJ;-srX8rg;oZ3>FMGnV1-#gIAa9JLoVlfVz(ipu=OBnZX@O=2%unW+rA| zY~3|eMNw8$MNtdJQ~%5uPcbfVcR%j#4hmmXH?T1?8fcrVs+zKjvKlc~{%dEv{!jDJ z+|7Qkjn0G86VLxoj5C<7fZM)S4(0-k42=AYObkq*YyzqanCn1U5LD5FYbcg@1{RiX z79R!%Ee#bV26+Z~Rc$t2F>P~G6Eiccbrm0zs3<#9#P#s2DyZoQ*;yO<D9dXk+Qetb znyM%%@x&@iORA_yN-Lj~Rx>x0QP9<rGcb`9bQ6_{3)HnYm6OrZk`bJYh*}0F2CM(e znLU|KG1xQsGE_SVi!pLCxpOcvbLum)G8izjv9fr1Z;%U!a8To5WM*V!U}a`VXJBPu zV`WQbU||9GRhmG(7I6LB%IPER0NSR^$;`x=j#~qZPox8%x2LMQs;ZiXs;UYXs2>Z> zNGLf-oSjWX6kINV+8>}A98_9@+Uug=jHYG^DPqMSZ4`5JP)W<i#_TDo<DjEw%El_> zX6hSc67Q%JD#695Dk-lm?%f<*G&gY0WZQgg?QF-g6_HkXbCWX`#r|VA(y=gPVdK>h zHMEgpOx25U*EUsBHA)L{Ota$WJT1h}Y^rD+ViMEj61OyK$~<WS7a{S8r6sZROC7@& ztar2wajs=yGw=qb2hd?qbxda&*ck*t^(-$V3lpOk8zTz?10xIQU?ip{Z%|hsRL62~ zFfeckatJc8Gq4K^3bONxYb&ZNvMVzhGcv2|F{y(ZDol!D|DJ|MGl~Z?ik%B!=Hq4I z5M&Fydzb0#Ut>ny8ys4?Jo46pH$dr@nIVyZ0eq^Q0D~lh5`(FO5j!I*6QdUc6B{F_ z>Pm&Rkea+1SXdZA)j~6)kCc>@l9Zy7ilUAJsHPW&WM6hjcUxIm7}^|B78HcC63?`D zxjE^2YPA;sj%tZ^4UR6G5bx!i%ycRs(LR`ml|#+VJTZ%LmbI0&@xM#|{(9M1xPsir z$YA^b8&f3H6$U8=a|aV~Mh0dHP9{bME=DFsW-m~E0xrA2MJ_l=bu;-eGKh(Qt9~g) zDOOO00xMO`;fVlLv4RE&7$+CER9EYTXljI7=T7qUpOse_qM{hc)H<uJb+!PHA3tBz zvVxqYv06U-pp%b4VKtZO6ay!NAh-+#jXpt|r-){xqN*ae3}qByQ&tu<HWCwKH&Fwz z6qx27-EjO)_WZE;-p0~IMkU6at=pMS1<Wb!Z~c1#l;J^f!T5pc6azPdrh^&-GXo1N zGfOIXj0<85D=R}Rr16gEz9=dRDvClO<A;BRjQ#&kGb;bP3%Vr5|GwXUP#++XfdOnT zCxfzs0?1qjRC5_X?O%|Q0<64}+Q!N-6L&{}O;h@JkLi^EUw^P0LGjVYbcI2I!P>z> zfRUL=kdc8|j**3xiII_o1=Mz6Wno|iB^z*jbb*r%s3_}Z^buB7Ra1s`x&&bv5)>EU z(HdoNJc0TS=BCPw)4yAldFRjY4_{VlldY$u7H{0pZ(f$5?<75!vGU&{VWG&Sh51XP z#YFrBBxkpVHhXfhUxE6SsTmxGiVkuNpq+~>jH#^P(G$>kTr-0Y$fJT_S12kADhetK zg2oDsnVO^iO^S+Q%!^|5{kNIv)W1vM2`>iFSudbdj<^{V9ArVgS5_8gCJxXQp^!KM zhn*;-W1?tkE~sv*D9SD<&Zzb8Uq}ceQ%H!3Fq5^2iHXSHqrwafjQ=<NcVYmYz9qn* z;h+ktdqB5WfVw0gnjx8iiKz*cgn4;5*cb#D1z31RwAtaURx?vUV?hx%76}zT0TmHR zU74t~ee7&LtgIr2dQ8XuI;MlhOc_Dxh$)-t6ayc~&3qipOe_pcj9#F|T$4Ab2iwfx zBPu8i>Fp>pvx9@c%*@=}n2{+v>#t{2l$@RX!OVY88ABcZy=FS~Z-J7F(v5#7!SN4D zOQ2IRS;0AgfuRZ1S7C|+84ezNWME}rg|-wy0V|pq1-fwcZyV?ou0#d~W>8p)GN?PK z2y-!l`*)B&DJu&zGdL(27#KtuL<NNf#n^Zyv=y0^#l%EG4iq*PHWmc;{FIp)=e%ZN zW(jV+!}6ddl9h?&9aE8frsY3>rc-~nGkN|sW87|%rtr5P=3b`hOs5!x7-Su!m>4kv zLR?S`8W4;ys~C;-m`nwYnWks{Yhqzy3(jDyWnpAy4q*yZ&M^O1$aL!OMga$JMaIdX zvKy2iE-+nX;AfBqhX}NBi`q|CRYUG4gPXLVk^xc+LAshu7rZBD=TG+Vm|T!O$@}k_ zqRPs`g378Q#<cvUF)_>XbC<?MFU@bCJ-fYq=1c}Aa2$ielAA$<!N@@$l+u}47*p98 zK}8WOBRFEf<H5W<j0^&NJR-azT$~(ipy5A6e+X1WDGQ2&$|+EV$tc&;U|O3U6ty+l zBP}J8=~P~db-Kg9S4^jT|2=c^cLkldX8S*k3FKc91_cIf2MuP>IvFoe#%p0<VS#0N zXdrYm`lzU?If{Tv70`&0xU#wusOyR&05a28H+He{vSAH{=ABBL7BXT41gPo+hXv?7 zQa%Q8P^rYu$i&JBYnP{j#|C3TJ;o+)W=3#FRe+z7L0FJqTtFN$AjQDP$cGpTWMdar zW>ywN4i~l7dM!tlBbjUaq7I~GhX;f(ok~r!^wHz_cYsm--%X}de*eC^I=fjjFfthb z|Hk-@=?a4;gPw!7G$S*U3_BAeGaIC<z|0H_A!zfvo54p_M-^OQsDh^#5ZzNXbx5ZN z)FWgEw^Kw##Kgqqm>9oxmD;2!sbpLF2g!Lk#Kc&oxmYD>%BV)@IlIWYSlNf`?vKwB z5(pEJvNKgS(2!6}2(}2)5fkzi5VO=*F;Ev3HwBf`;Iqh>6q!yju!F{1Kw-lK8aRaw z5D5xGW<V5`1(i(|MU@$yqwX__-(#xw2dzks`u~lo0i3TC9ppfLJjnD3xKq&$9$gY* z5K<Oa0X6U$1)&2(pwbIez?%v(HQ3a|wRJ_s#wCU`o%(0wRqi^mobk**!|;UkK*n>B zx*rs|pi^{t7!)1kK)o$SFJ>kt@I(!)tl(kbfs{6k%*xEh!eXG#p}8<q#Q&)OaSH`R zIoQPn7C^?d{+a3cDl7ZxGM)gJ3p@-A%%B@)<w0eUv=BRJ2*wLk3NbOk3rPkBP-9y{ zP*M<77J+Qg1Glh{t%BRhJau1mHzz+gBclj!d-UG8d>%noRuSI1*k(QvRu*BNJdiUO zugF;Ia`J}i{nKYU_0LByOievThjINsKfM?w)o^{r&0x2&FfcHI?&*WnIUKB5%5Nbd zA!xD1%&aWTY%DBn%*^DLw)a5%+j}YNH^kp%H2Zgov4k<~-wQ^Gf8Yfapp(BCm_X+j zb1=v_NU|}5MsU19l_IzdZ)Wrn5)x$Q71w4IHf9!77GySNl-`y2F6vzpV>V;_Kkt99 z83h@4g0i|A0|S#NxE-YFpvKO~$b=YHgC-zQAp~iu2nj+Rs%Q!sIZ$L0{U^v+@ox&_ z&3_$?O)gAk0WN<*YdRPi0{$m4g6<Dw2e}WlN*>faWnu!iI-8h46*t(=tjdDMqRN8C zj0O)Lbal;R&hYrF0S-6NSSP67!#CC`%&5$mz{nl`?;9vSm`;KGBl$mx0W`-5u@^L> z#hl2%$Oy>|jBtC!jRloWjRln@ySg4c2xGe8@n;4kovJZ%Gl?;sXJBJc-^iBY;vmDy z$jHD5E)|=>3AO~hP#ijfvXPC!MOfHaSecnw?TXPWzby+GxfzfAvtdmC2Rd$+f${&p z|7nc-{x4%-W>5f|CkmP+V+7sX1#15>GWZID+Z!N*SQSkb8Tb8jU_3C(0UQPzOmPe! znf`&szrlK?xj@rzj9%bzX3%0HkXyJJxJ5x@%^(wm<(R}pmGzj^O($|Is`6WlTN&~& z{Sz}c72*-Hv=riEU}Dhw|BdkhlOlsOgBnAr1D_-#3xfnBGYcCd8!NLHWQI$gfti7o zjhQu-0W__}&d9*f>&?K%#uyK(-kTYHq#cy8sbFMm1}OuVirq{;kq)Aa3@S=;GGZcv z{M?+ZETBOlSjjA?tPbz&nVUmuP0#?XFgt8k#*|SZDb7KVMcL2UGoh|I+R9YRM^Rci zVXl9Quer8!G?QXj+`q{_I$FL#0pTpn3eF~y0#3rx|DH0lSQzVSdHXRiF@*mA#$>?s zgF%!*kzvv{K^7)f7DlKaWkHo|i#NDJ0S(Uff@YW?KI~@nkp@p@I4EK&g3d+3h9{*R z6p@SoDF-Js@O%|aO=P5lh`1O7gPe?*qPQZcMI@r4&H)-L0nKM34-Bd+vnvY<E3t_} z`n{$mYnho?#RKe9Dyx$11H{>d?B9nuI!1W7GyT}9WG$$q*WK0Cqo?4)^yA-yq;!_# z%&e5tpgdsy{~P0eCM8Hei<^;&QJjZ~nMs0?ff+Q6$pm&-uQ#YS2p-1kX7FKT5ET~S z<78)m_On=(&?+p5i$J|DMjekld&eRV4POaq2?v>ZzCPM6GSZG*R#oxIHCBQ=o}2=w z6Vruw{rLDnZ7R^1st`C1lo+ON6XIlIVTH#50~1pVB-|Mo8GE6T!OX@4o{)gW0h%HP zX69z7N>DqXn*lUu$iT`9^Ar;kb1bHs$VdlqaWO_v94Lt^2@3G@v9mIWGKzxIBP)1Z z5>z!CtEriS3I$NwR5vm+g``VS5iv&Ll#0p}JAX+wCYA_yUKWV}!%$bJNOyO4uI{d` zUOh!#WBzM@IXsjMJY(YoQnCx<6F_GIgZ$3Oq{JZ3AjjbB;K0Mk#K_CY%)|t0&w$!B zkoHVG$R8+Ucajo}3^LLZa*}d_{9GJttPJ9e;vknY8i|RCiYkhMs$Ec2fX0$R<3{32 zZ0w3^YK$r_DW?A>GDQX$`)g?inERGET4%f2d$KbMGTJdI+2nefM#l>a`3eczRYgVA zxp)M6xP*ez3qJz`V>8oV262WM2Yx<A7G{2SCRP?U(1?$h_XgR32nT5f=umfyH>i?f zjb&hEZ3Xofz{P<is2|G8%#w~F7wNz$tg0#q>7p@$8e+<(prI~MXhR!9qQ;Cq?GbTt z(ZTX&!r}s2VmjLGj932YFkaD=lh26eW_M-fvbI--q$L3+AtogTIR<Tp1_ypIW+paP zUPfjX9!4f+SmC9_!N|(W5YNcY1TD58BW|G74lbG6L6gjC42+De-Vl}W@(ojAq=Te_ zJR^geioCXhwv>bbA2%l(cou>aG!$VZCT?sF>cS~2shfhL#1t|!0vYFqjBkU6OiWGG z7==wk<yd*#N~_Df{mWhbnHX8j3NlJdi=DkZ+ylLQn3Oa$-T&S%E>Q~93Um|Y(d7)B z)Z8%LD?2$kGdxi=Hvv*Ng)%TOf$nb=WeC^`ngs=AB+Y;b2XR(L7M2#!=r6d*)(dMJ zOFM`&fX3<>KtTag!x#%{88$QeL^^=Za}Z?^6;={f12u?*MMYq96ri3NsQ)ggEV!1H zO)AnPF*&><$~l7R$9)ZDO|97Ue~THz8&l){y=DS0H)Ub~O>b^xdI(-C(d)f|3*;p5 ztQTldr^Or8V{Zkyu9*o`vhtuvccDvzR+fn4((ND$G7{9;Oh+~~GBVOZ7_?Rbd1VA> z0s?tugt(xxV3UZvyoi{boMQyjLupxAX%Ig77j$y~0|V3llm7)6ApVeMSn9wfz{t$P z&&b3KTJHk#lQh^>3=9k{pn;H9NRk50hJezP_Xd!^;7Y(_B^XLTeuFE)W{QI(sN!c~ zU<Az{qG|{Ek)M}GLR>_MN19h!MF}))j6Ax}3?Ev6j4b%ci9vj8A*II4uOO_T72(0O z65?m+KP~L6?yRiJhD_OiXLy6AuNlCz*i5`kKNy4={2e$2_<2}ZKusS=T_^<VHn)K0 zn_Io%?EndoAR~A+Lo<q0qyy-r5Mc&kVIe6{uR&N)gpJ+Uj>+8Im|a*|on2H}a1Apf z3!8)_=j!yEFS2&ohBN*6S1e#6%poVwwe{)0v%gHiw`hWA*4HxqU|?p@fH;JkfsqmH zj%HBN58{CuQlL?<$Sshzl(Dj)@!E(8Q0fHxi8+i(i9wMecAK086C)ES(}0$vh=JBv zF~qa8aWI3k2Qw46KPl}X#lXha3SNQ55YNs5E=FJ@wvi6vj102Upp{sH{JcDz?5r#d zij0cT;s7+ZVFJxLFxprgT)~4#riIZ_;kka!;dy~}5$?RKlA#85YOK;ROiFQ}EEQQF z75482V`P0w9OzIuPc6+TJssqHuf!nC5U^DMv_cNrh!F<oZWdOs8=*NHl;>GkT0z;3 zAs#e#051(99RwK}`1zpD7G@L%Wf0Jc8Kevkb}nOhLQ;4|qzlNAQZVO*H^SWo>dJxV zO4XT^(AN}z>oIUC1X@#|3h54m#!n#)3XG8w_4Z=-e23N&j{^ID+1^2cK0ZM~UW~l0 zlN@U!TPHYHN5<#p$H(X7fb9(ZFTiBLq{JY~pv;gBYD*xs=OE26aN_~mmIJM=00jdm zcY@ZUF}EVM8!*)%S_sPG%BU>_P#{5i^q^rSP<I6spP*V7(kudxw}d2DR;JhminB4Y zMtJbBNcb5BxiC6L7&yqgGbwd-clPNi2$~4rVdn5uHt>px6HLxFjkAf#L$23E8I%|@ zK<!lIHWH|51Ilo)_7P~ghBv6C*$!D_$Hdf%(S|}+gJ^v!iGzYp6x#Y^h16D{F&tCy z^b)u>V>U8_HpfBDo?T4LY~q0qiIvq!_5l(sylx+Y+!$TLJ>1+rJQXq!R5Adyehid7 z|NLOokB$>c%PfqK&xWU2#y%!cnoWcBD!7>$85smvn3x!uyrdntnHia3yhw-wA#m}^ z%mPl$phaJxnp%v3nHk*BfXq09lUFmSbHNWu%N%SB!i>VK(E1qCq+kPOL`X{Z=U3w6 z=2hU;^w5s*;9`*sW>R8i4rFH04K(}rh)E(z2Xt&Vc${Yw6KKUF?s1-8P-_R4uyK#` z=rKV96XFz65y&vlrjjI!KzW5|eP<gnOH&gsjr=IXP*pi4FLg6ZDO+P>549<N0YU-+ z0@B(lA_@v3A{rJtE?y!6ZhRuja^iAw!onJskZ=|F|BW%2X)=QZXblP<BNGcVBLfp? zOF6R_12YSAGpIfSFQaJn2DK}}&0_F63Q-YZAwdD~ShNJA1Zdn))yNFqiWF2fH8(dF z1@*;6#27h5w0QYUB(&Uhe0-HnX3y5QV`Ft@=altuWVFyyE~<9<cgj#7;vWD1-<UwR z3kWm#Yy~d{g_TX9t!1F3$;`|U4;`qMb`Xb&GB7lQ>Q9*SAng%h24N*(703V$qK60? zXacpP1eruVcv+-kOcIkK%OhQxB>ui|*HVv7V~qc|ydfoy5w^3N0ek}&KWLnZoso%w z(F<gIt2bg)o1cMS8nXU@*%;Jg2GvW##>}Tr#}#o1@iDV73kY!(#hqc2_;*Ci%t%1M z*i?+s=I;xLf4LbLnc0~@^K0r3D$)Wh;Bjy8z(A`vD=6(kmSZU~C`n2QN`jhJs?2I? zpdJM~Y^VuhA835b*v!lvG}yx(!z;qV!Xm_%kTN;ii(7<+g_(zsJw73ZON@nuS(L{+ zYAPe6o~EC;xS!U)%S;mg9%)C&3L2S<G3x!hq#Ph48KK802XY~3r#u7rW+QIU2sS4h zGc!gA2nh)Zf>#DG8;hG8GlQyQ<tsZ=x;m409!{AwC7Dr(k?qu}f4}~{y9PRJo`I2p z@xK5g=mb<L(D<5^Fe@`NgAlk~1PNIN=ul`olaH#hBzRay7(A2)^&WV32s#*QZq682 z!Y{$b!Y0L+8~<E3!cRhlms?&?&q7d!N#fsmO%FxMKut!2zw>;eSef0JSWL7*lk$uV z>I@8w>zO1NI6?DinB!F7wi2u%fH_XZxc*-Sqr$(Bj0OLmFe+Oy&T?`3mj`NUG06N+ zVvJ!r#URU|<De-9u3SMo;aQm&L37;<tPG&JZt%op6N`_ups1iIc)E!d)KxT5Q#LgN zbra2uMcF{Tc6L!QP~TmgF(xL<-rCweFT%t+H`mH^9;08tWMgelMlGW$0e&7#+J+O- zh1rDDCmU)rGB7f{|Ig28f!f9aH!>L++d-o(+@L;MGXt0hYvX_>P~LlbGX3}iO7@^z z)&3_jf^Gtn1<fF^GqNx<dVzXn49qO)3=H7a*U6w^Fwj!DCeTF&46+Qef}(=b&{fx9 zZ<w2^f%?3lr~-Kd>M1q_h$o<4ng??JM6mNG8EP|nF!}{df_QCe0H`AXTEoF8&&0{N zh(Vme20U(M$j->bC=6OT;w8k$=)uOw><-%7$`lS73u9(vNQbV~XJYn;En5MNW-)?C z%Gpgp%l5=!onB=nHAY?)eK8q32?GxqD?Jr`QCT|)Lw8v#MtcEnB}qS19uW}jYX<7! zfY!=*F&tr10{2a193;W^GADwf9yF2J%itp@1YIZtuHhl2H@mU0@(~p&DHRZov69ST zyr(8B3tAkr19US2C_bY9e`9>gbcI2YA<scj0kncnkd=vvQ9_7`nF-VvH4KP=>_%W> zV9Ws7%EH8)&c?{f3Z8s#W&w?&fup6FfrXg`w6GUcR%I|SF*7rTBf<l+LSB(UQBYJx z6&zQL&;{|Jh9-D<1gH#W7gaU|S3PFtri_WIZjw?`PSQcX{ysX6^3qo7&eq`u2I1CB zR|1#>xIMW9($X{H1$ljW1sD@kIBg1}qD$;JK^H!O(h&m#lQ`351_cHW2Uk#)4O+i1 z#>mRT?8VN=#Ky?X!o-{kuBka7E5KM-z@q`ptUinkvNF<Apn8Unmxr5!jX{A?0opVM zP0)iJ460y2qh5-lir}0BTB&Pd#^`4rt}HL-rD17v=8TpUW5YjAZHt72e5T71f^K{g z)=u3{8Mf8}0bX2=PMJ<qB2yTc7_1o@82>XlF(@(^GT1s;@$s;+urM>oi|~USC?_K> z3fi3D#mmaX;2|r<#0W}oj7*Hl44~?Wfq|iy*+)%FUjtkYnwWtWBtzz|&BfV4t1?0B zltIN7XtA=Inz;x#^?{ms;B_cb!U9f)PU4md^5zoG1`hlp%J%xs;ui7_22KW!0>aKp z)+#F2%E};8i7`>mQrtz~K|okoz(L<x+*01&&`IAxKuFm^-$~q3Ud38T$y!Afq#Tqe z8Tc3&m~@y<F^Dl3I~Z^>GID_SSTLorgXW#UYY0F)2AV)EzGhY*lpP`5pp`Vj#>}8K z&>*Y~UI(pgYRqiRD7!i4WX<&H)5E4upI&u5mNAzx_Ftz%kV9jmLy!YwIRg_?8N|+D z1L<jrf}$C;NC7;w03KEYw>iOwH-h%6fRZU_u&tfhCvqEXiV0LQi5d$kzxVV6l~4bg z-~Vd{#n=DejQg4XG8i*BGK4q?^Dr_p*juQ{@G`S8Gpa(zZ$KkWU`s(GvMr$Y0eHv; zG;H7iwv-vvF^1MQ;8q}~mWHyTss?B=BWO81c+e7QY)M2+92A>u;5Y@fbU{TMs4Zcl zrlzjPWG*5m4q1Sxrq0IZY#^_qkrr>^t0t}NY+z$(;o}>oC#$SpoNf^$uMns2Wg%>C zZtA7(Z66>et|{$eC!@pIZD_|YY@uP}D$MW9CoC@`qb?)sZe#2yC~T_c>LV!N%`c@T zD=Z@?Dy(f~rfMw5!K<Srsi7*&t_N!OPh~1+T*q_^ypB&5TvCE&wHX;1!a)ORjPaoC z$B0rSBKP-^*Nab;77><_5f+i&BP|SK2um}qloA)0l9ZH`gwhP)HJ!}-Ojj6$8Ppi; z8B)PEMu8T3*%&ghv)MATurqssj%Q+JWCm4!Z0xLT=?v^#j4Vv-Ea{w#ObiT6;hf;r zpB$hgjQlm!MMW4HtSn57^mWzkHSFbOMbt#qxH&;ha&BG`ZBQZ3sst*RK#O5Pi$M99 z)Qvz3vh|phl|Uo?a!lsn(N{BLBXM?6-hy<fKt&qkf`GPUGqdEj0H4-WOAzf)5N4nk zT<8+j8=x0l6r7x-7v<<^C2OQ@?P%#FZYe2Y#063Y(*~kV^+JnW9gD&Y1N)*uR8)1U zW2&W`tyHL|ZxAn+12-=y9uyes8BLfjF-S6~Fno336K7;$5ChMNFtUM)a?yYY2SxZ? z$SP3Y12+iPf~Gqla|WBia|WPc1=!>XXaI*H9yGYP3SF5hxN3mRv7|GwF)=c-F@jnd zP~|M3K{B;~2nQvQZWd++mUQTJOF9D^BO_ZlY%Ye4(O=p@lYx<qiH(t|4x3^ouwqaq zVq@};1dSkxGBPMB$ViC@@$+(Vu(B{nGD>prLv|2}!gtFc&&Y@)W@I)xI_dL>SgPt< z%(Kvvl`$3*lXA!~u+fs0G}dLhWM+LwOH|s>D4C5(Oi_xT+mKga6BCoXw3L{>1_Kj= z27?9THAc|wCcF$BTX{HG8JP^Ug&{ja%psJ<3j3ZO`xVDl+4c0;tzzUmsj_;t>PcP* z1*&t67#f&37+V-vLF=1A0xh6j0E|qbpte0|W)Zx15V2~75j5Ft%EaORuaL3j-=Dqi z|Nq1GZZNTdPP$-V0j+a}=Lr)ATZT+<u87lTWaD7;;$dfEWn*GvWvT;Z3l>neU}50o zVBt(>;9y{5<zP$YhU5xvaIWA2=L&UjuCTQ>H&r)LH!(IcG|<vO&KbN!<_vYviZf7U zDXy%pEDGBepiC%VxHbg&7|4}`rPvv%>uBg063i3vj9VQY^v!t=tzG+CT|pUid@uO+ zgCC6FnXQPKw*<`vGk*Wa#`ufrhZ872nKLeAEM)@iofBuU1c#>{DEychnbTPz;RWiY zf_wB#4E~@+Ey994;=JOJ9c^sT@DT==43OoBpxGGkE)G!<v1=aTp<Zs0k*)^1`g(?X zdW;K0U0lM#TwFq}O|*1OOmwtN7(nN6F)(p5g@N0Bh7Nkj`-T`mF`CN2#>O7Y!N|_u z%nn+@%+JFw1X)eS$t#VzkqER#9=e(6-$%yljP2kJMSoYhyMxZFXI#K&%pA%f$zb51 z%g4yb#LEaul#r=52GH(EQ0`@54h6M5VnOrKzG9%=DLfL|j97Q4u(KO88vT1#tf|Sb zDko<sr7Y{J?cix`5qOw!fmwmNp_;h7qPU2jq@2CEp`WQQC>sbe&R}$84rS0_@OAJ~ zV`ODeWn^ImHPr+enV1C_8JSqYyDV5)7+BL8SQwa@SeVnnn{Gi3O;8t{iP4{tL0M5& zT1o=6)q+8TQG=ZaQYygrslZmcgIYn#XuDLFx_fBLsq2SEs5;2G*_jwvnOIsH>1)c$ zn@X$5yD*2^8E6`FF>@GcT6yyF+bd}*t0<bQ%gf7&3hIf04vGeyOOHO+4eq<+o9h<k zV`5h}wPP~>$ZKdRVa2DS#Le`N3pCHoBV=kW1{%-)FTf<l1UfrC#(|5Ok%gHHyyFEj z+$6!q$^;%;0!?y*I<n2)3`|Vm!9p3B6nK<^g#{EujNMRaNQ+#OK~hOjTm{l1hmTdL z!^Q^%ML?|#K_)48K2|Az3v~+-7AEG1h>A!TCW*f<JT$Z<MTBfM<}h>oTUHMpx?o^r zF#q4kq{{SzL5Lx6D;sFZwHKrzCcyw&P{_<s2Wl2HF)%WM2Y6aQeM4DPDHcXXmQd*8 zUKU2*$n9#%f`Z_cpse7@H{_L?icG3jX;%E|f_5>+<|&ShLiNn{e-1KEU}e$EiH^?$ z9dz>lKZ6IOEW;7TCCs4p%nXd$44fMo7<VvgZ!p$|jEC_37ht%;06P1}2%OW^h4|T+ zL6e)HeZmZ&t-lP63=GJde#KOjKr2%~jRSE|p9|3@Q#Ute7ZbbU<)t9RDaWUxW~!!b zC8c8AZD7i3&crM%DJ8)gX37CsAEL^*fZ+qP4+9TqOoE$>4LlA5S{T8AzNZhgtcaOM zR9hG{&TR(WZ1%yOnUPC^*G##I+2>yfqllE2D5of=x?v2c`~tNHBAG6M+hum%8$k87 z5a`N1CI(Rd0h}6Efd*eCV5J&Z5|o)h1B6Tr{*l|j{aAhpZOG6!v{wo4u0bZ186(3y zoFhU!-9vwA8yV{87#iv@X$D4y2M2|R1zTHLSzB9z2K<;9)EO)oucFtRjF3H)pj~t7 z=HiT3AvNalm7t1qB_rcW)zzz2PVz!11{MY-1_q`FOrU*(0u0g&Dhw&$n2O}(;b3NE zP-J9g6=7sy1MPlcW@HUzVr1ZEWM*SvPUU1|V+Wnw#*zk_UytSC-~t_^<tr%2!ot8H zD<dc^2;G)0EW{$fBESziAd^{;msb?r@G}N2V@KNEC&*~3Y$|LFTJ9sNZVVcHW@BTo zW8C8X&qtYw2@)5cjM;~edfM8asAXbgRp17#>S2^aikyET{~jfnFiQV>Ym+c1R@6d* z+fWdEn==E`4XFRL7?Qxg3y1g)w3=C#k(ot^k&%rBH1E#B%*v9%1lrgI_9M7O6$)xm z#d5K8Ff+0-Lj5PGC8(vTp`;)!iR3qKTz(VAw$G5A-B>gM>_I`e2k#VXXo1RgBS}cP zZet#J7^^q26!mtXQ|I|XM};$8W&oXoYtG=n@Ezn^?+wzRNqR{}7FN(=9wkO5W?L2} zMov(%VZg}2#pWgLAT0@+Z)0R;!6F+8F~A%&AOQ*>P?g2R3EIWT$;i$b%D~76TBgsC z&dbQf&B(#d#gWFq$;looz{AhX&dKg8?O?~i#>&FV#!|<?%0Pwzkq+9rx|*7d43-wU z=DOx)rl4k%zMiIzrjE9jthAVj03R<mJ1eMO5=68PptJ6vCHb({5ojAAxFZj0H;ID# ze$0%ZZEl!JZxYtJN*`L2Ie_Dhu^l-%GKyhVUPv_?Xl?CZGmPZ<|38Doe+R}TOiGOW z3`&d}m_!aRfJ#xO9ZVviQWSDJ7*ied1|~JoO$m(b49*Ob88$I+Y-D2GunD9DbUy}Y z0t{JA8N)3?Y8bs3@^Pq{2(ybZkRc9-njV-MhAajdh#Dqz_vFFUF#0pBV6X+bnQ4P9 z*v$+~AfGXtGM!@JXAowva4-e!9pYeRO9h>W%g(`=$_d&(2^v3W@@8OXXNU#WZp{on z!jN_tXgmS5IY?2_RGD3w5xOlxR8iGfP?_2EU(c`XSjJ$+$N!!&vj6+ZDD`*ib*sB~ znNETBN!$Z%!v6oC!S=rZXuk=Q8UyIAMs|iOMpp3MDWG-lAHd-a+7SQ>?>4ai7?Hvo zT}>IoSwd<Uy%>^kr~!o~#I7s`eux^Rump{5Yk}RP!@vNF|Ns9XYLMIm(ru2Uri{T2 zLk%+n17j#c4Wrlp+ZbwO85kJNm_hD=*p>Ca1EL1z9tI``IR*wM(B2r(esOyT8&*bU zHby3PW+rfqF~ouf{=iWN>T-cLGV$|)_UVA8m-r<4CBf$curcs5@^V3@<v_cfl|c)S zjRnP(!6Sgi3W6qTjJDbH!jEp;@8xwOZ_}nIMx{Q`4w|B^+ZnC=7@d5-`n_e8>2C$4 zeb8Q=>CB)sYX}M-#z2NS5H}-*4|wf9*zZOlH4M%Scfe|p^ANh4GDc-WY8bs3cHmG0 zau3)p#z2PUIMjf`8LWmOiy;-F1|H6g3=Rw}jK7%d7`PeOHnV{CIx-?1kidAtXw^!i z)yqv*t}<E4WM{l;mGR1z#;aDEtOoD)xBdT+=>pR$25|-j22BPV2TM_5CMHG|Wf^HP zPBvyH4mKuG7es`S(Sx0l!5y^m2sGZ^1sYTXHBvxZ{?&D~ltBZakS+g^p-#|pGSC1T zXdIMPL`<9!G$_MrqRuD=THyrV*ihhUU~8hI<1x9wBvMt+);R9(8F2|ldlSE^BF3x6 z{|-pGYE>43w>s#%Xm}a+gy$}ekq~v#bWh%Bm#oToSb1i9gV#SRA(7djxCO602gjQQ zG~Nz_!wESrqN^!m<RYYo(Tia|4mF@Sf!LMB-~&+uixW_Z#lXO126m4P*ga(o+aYRT zX$@(=1}}pcsPzdNonZklmj!R~1MTvHt-@AOQWO+aW&<5f0a`Y%3|c!NYHTFN3hEw! zDlR51liJ+CsHlXAb^j)MWG03uMKadeWZ2JUI#rYR)7jq@bTb-g9jh19Uj{RVPDtN{ zON5b;Nf>mpu9vg}l*7!(<OQ8c7h_;z0<UIkflOL6Gs0F>f<{=SkYquNDM6#WpaEC# zQc4L1(EcJ8rgZQcN+hYsNC$3HV|_g>4OM+sUNLP(5k6+{>^8WPg>()<NyO9yvf06o z8Pd=NPsW>o>trS_&>mD?HB~daj39jvDM?=qa|2CNdp&7QO=))vWn0w<s}%dha;8ir zV|4|2AwE%ANfmGFP(L97e*q~y4HZLWO=}H#9YqB-X)QHjeXYMcm^_^QmAyde2(qsE zACnq`3wVLHGiZA6|9|LuXP7uULm9(Xa2<fAp3w`mjRLOzKFl1(Ku|LrE`AFp&X5JV zSQ{qJYzP%+XY^-i1?Nw_|KFH(nUolG7>pV07^XRhs4%iIXel$XvI+4pLDqqSw%2L| zL^!B&GO}`kdg+X*yc|qyYz*=2Jm5tTpiw2}c+eWFZcukai-C)gl`E8!k(B||!NR9F z(m`2ImyyB7%FM*jK-XB$SVK)wUPcPE6dSytREJTA4^}v%EGR`Bm;+q~0$P;~DiF*- zJNDU)P1INs1A<J^j&a8SRx<f}8TzVe_!{-vDM$NyCRWr$*&1v3DoQJ-7}^DjN`;tO zIkWz-{P);9&cj&CK9otxCdb1pAzB!;6t&RA7P5j{$<ahY&`DTYQ&&^Z!{5s_<O+Nx zHz<D1{|kWDG&89&xG{iEm#t!01&&9^8e35OdO+g6hyjZ@DBgEs5ocrc0?k?e|IYw1 z2Nb^$bFx5}sQ>>DzD4~w(?2FP4$w*RYz)qzIr0Dh89;Z{^C5|sfzJB*|Ns9j1_nkQ zggB$uCa`<{e_>!?<Yl@AHHV!c>pv*ZLC%~|XZp*az@Wom=3p$w$i&F#r2v{pV`F7u z=4A9>U}OPL0fBNPtmIZw)KF8@QPNS>24zLiN&--M4X$V5>#W4h)zlzmx;kh{Ijrw_ zL%~tDSS{Hlysg9|-@ZP_BtU{iz)7n~tw2;yygJ0&Cpg&0kLfSJim0=hrNiFJ{yytm z?}7#yIVQ^lHE(kVK53qR7bAnc;u2%*BLDvft<PhUWCG=vKv4KI27=ZSLc>!X6b=kQ z;P`T8Xn}`6vUnNj=41@@Y>Zx@HLq}Skoh2U*cbyrTUX)Yp!fodGh~6Ldl{G+j2J4J zIGNnR<9^Z%jt+L9i<uahz?01EjLfV|%&82lEG(?ypyNj3IT%@3S^NdT=WL0K3P=k| zBd;Lk1Z5GVQAp5v0qjV8Mp<!1MR9Qjg@6ATufKt^8PCZoC`m~vDacNAcRvDSgUbZ- z|M!{HnamhO8RQt$Ky|i|0233VlA@HPFb5km6FV!o&K3kukt6DC=t_Oinl1((H62ax z4m0q$0wj9DgA3x|1OTeBg`qVzGpICXQg1Kzw9v59l~-&n@w8I6)|FNIm(9(4N5v$_ zi_uE_j*>~B4`{iaqJ_GhN{VCa1QiQ4d*x(1HAhKCBgve2FT;Q5#Pk3EXMn8p0p&B$ zS<;|3a~C*1(Z$OcE@Ba9WAp+Y5(_s66mKAN*ch@v6MNuOfdv@<fzwM2IK7lH%m#IN z7$9r@elSQfs4>KD6J~?%;Q%drmWON&fUZmjujqqh5KyfLUO6ETI;)}?wssv;MWh3# zs*1Xxgc7ud232Fqa!jJ&Y8td+6<lwDHhn9xu|uY&m<%eD?E@s(7@3(OBA6IiB>Wtb zE2G`Kf<cS@yj&T1K@0sj6qL9gFu!=fr^~Bk(9@Bc8WSU&oSh9S#~^EIK>i2$lZ_$k zF1UOE4W=>GF^9wZQ$7rh;C2Uc`xR1WErr%KY>Yl2BcN@TI_7C`y}k_fIP^Y&>-CL- z+WTLHsgCI^L@xt7V*ukuaQx~0S7H3gqzF|H64wEXgWAxM;P#Okq<zFF0k#Xdy$0ET z0!k~8vKn;HC&=$;dKtYK)?(EQE^oo*JR74I=vXdrU+x=IB=clQUyhNT(GS{o$F%n$ ztd3yxV>pb>&5Yg*tFhX96rBD*Zf0Zj2CZlQ{~x>`buQSypk5j~qc_70uwLYN0o5HF zn0_#+F@V-8u`{VNR)Ot>_M@2C7(i!YLCX3#rXLKl3|b7kw@Gm_ad0w1m&>U`I$4a& zOrTv?EudpHz~hX)-rS5F91QX7TqwI@v~enDU}tZJ>H)1305|H8RdaGe%>^Cd5sRrh zGSWd_UJkVBK~76v3wr9L5Oh7PETb$BuZT9<jv3G*4#?6$@UAY<Tn(h{2U<cZoLXL) zY!BW!bM<P3kB<jv_l$lBX!nep8&_9nPZwzSjDW3EWTeyI#h@KDF|mTF8F>i_ncy&l z^us~<0@MR$XY^qx0f#?YyfZN}f${~o?q>9X)*TSNpnL(*>&sAtLoX;_K=k^?LGlGe zFDSi1^!hQ}z@ZnE-avZU8T}ZJK-~Oa1$0IOlN#v60dSrI-Gd2=e-$Rsejw1vnvD*^ zs*J2GYWz%0tgMWnBRUuvKn+6B9I^%jI|B<VJ4-4DBO4odsu^5#f#z|Ux<Tm@9EIQ# zP8FsUym*8$8JiB!a#=xbEj?W=18oB(5j8bcMNVERZC2161!$%nvSGy>v_1m9n;Wss zh>wXGy1l4XS3rV;Pe#PlNK;Z?9lX299eKx*wm=eevr&mIE29MqtC5b9y*LYGvk`pv zk%ECHlNDs=5vWXngfnRD3lh%W3<)^G8C0Ht!kLZH8+70uv`pv&=S?k8S;XkYa14uH z0VW}Ez6Le$*%-Z`<sPUk>I0XV5WT((*Kp_sr45K)-z-SlfanFK4TxSpMjIS@L1_b| z7nC+GfYXNUe`TgVrYlTp450QTJ5MLWe6YCre-w8zX&OT80*!q%gZ-!t_2UwByZ+w> z?F(YQ$E3#K4N>!dGs6Q0j*X0r8y-N%;=uLG6Q)xP!jOISpdAg|Y)lMXj0~v^TnwNw z-Bi$qh$e3yPA2f2C<6m%n*)O|1LDkCUS3&k@V;47V^Kv@XqFdL6cki6RZL7w1Rc1M zm>BhM5@X)KNle@x<>lq&9)G`r&fs92lMlM78stu<9}IE~6Si_NGJ`i`f+})Fc1F-R zJZMP~CnE<3cw-DWvA2RZ2Q@Q;Rz!dn)FCN^olwx~4blQW=!qGm&_Nzy7y}an3o{dF z=?Vu2Tt#H01L%lXIR-gFL186fbwNQcUKwp+@VFGb$_K3=hi%~i6>n>=Tw!KnlZrA) zOakwP^6_E%5#<yvtS+Fb6_@^RJEJpbd&EDc7^kTJ|NnntU|>uHk5_@m*cb!<pTdYU z&`kywpmsB)U%?o-5E9>_3=E8R;C28+uh0Lt7<%6@FffXO$~&lDpCb^xphHQ#z-bzy z*Z2Qx485-y7#J0qo<RE{Y>d8#AbK_at1xOYonlgB0Bt&9V+??{Eu{aeFdSe4rDIU0 zV`B{X3{}s-z^DbTk0EyXF$AL9#h~%uiHVcx6a&Oeb_QL>U~pRZ`!B$_o#`Qi8u)Ah zb_QS2qJaPZLFcJ3nt;=~E;JqQLN^n%M+@4&g18gfzhX%IuM9dTg-MM;57ZCg=?sUs zGxWbQXipOp=#F6q1~#5f2~bu5?+aq$Ws+bJ0-Y_&%gVwC8u##GVP*pDrvOg}gB>Tt zAS5U(1lq#H2-~=1EDA{`=H`rlPv6em;1nCn!o<WW%DIn8;_bhypUn0!Npx%Yi112t zgRX1%|DPd%fr0Te*kAe}e=(FXXrTKG(w_w9VSlI^S=2lXYK#0=X8a6}Bhcb|Hl9xC z*o5PMWrl;`_6MkQ#KzOv2k|?oY=x_5WM@)m*!%wy1LsCY#vT7JfeHpl|BW#ap_fS= zG#?ML3*=^)U6A(HzdaDW|Mnp1wPO0gpvC}pGov5F>VHu4|AEbCU}WHhn8UyeT3-!1 zFcx&a1P5qe83P06fit`eyrQC@)qKXL?CR!%#)9VJ?4pXIiH6D{QJpGl87;oc*cdT3 z{@W60pK=EjtpC3=Ffej6{b1l`uy^1^F&{E_4%&wX+O!JY+y&x7H>@%GL^^OWFfhP2 z&>IWFtrYY#Rtb-AP)%i&Rj{^T?D)4)$J*uJDrkMhG#wn5;IU|iGA!+1$UaR_eFf?h zgT@{peIigAoemCDP~i?L`#Zt;0hC51nUt8+7(nXTcsfCs*+Jp}*)FW@R#dy#7`;Kq zqJ#QV3=B-5b5ztA0^JxG*qGS9LehQWe<$!6I`RzG4i;jJOw6!zi<rGYJH<U27+FC} z(vv}>PT-R`n?Xky$w-5i^>VO*4q67S&tZk{H8eA41ofCe$NDgW_D_R$Yp^limQ>>v zP!p3hkYoIp%fiIW3_f^=nI!~z#*wgr4pX48TY&1nTBcKfk0=yaFqZtaNddLn;OjO( zr{m>1@QE@qgZ8&DgXS_ptMNb$BpL7!CTK@1c-?<9sKdtq-bdXI+7zh30NnuxK7ke7 ze@0aj=^)I=ASD6X5yJ;MoJpQh9<(6_;VV-?Sm_VmM+91gBq+kh*d?LF%PT7+t5zQA z8Ub3`5owZ?<n{r&m6CCFLvq}|mrN3#TAH!x|AM?jp>324;PM<i55VZd0I3Vm`w!}% z@*F%?!p7(W9m4{(GcJJ3bBJDFh7;g&15@u4CN-#D-vUV9hv)^hs~~!V7#>6PB8_!} z`YlLfF^oYB-QYgA?f-AgDNI)x#2J(r&N^@@GBPtMfKHI}^4<Vi3kf>?0lXBMn}Z3o zy%=-_Aw!opCnGB>TRb}>8(T9QsKN$ClqqNr0_fy3NG}G|BLSbL1fDqpuVRMk0Cjkv zOg0~B2hiEd5G%mFA8h(!8Q9oR4^5ABkO%FYmzR}Ll2iii&jcOu1v#J^w1Xbhb73?R zhfgGmDuPycgO?10#x}v-dvifG#wH^@#-@J{8F~JFVU+*ZB4#9+KiR{5LRoc5NtLCR zCeu}J&>W*b3tP;x{QM=+{xjR#XA3eZ3V`w#GlSXxZ_IT}iVTVj8Vn{3kq%+<jO=Ve z+)PZ2JfNc}y%^XT7@61^Q+YVJnL$Inte}ovuQzB}Eqtg~OH)~ik-<Pu(?rWeO;t%l zSpzZ$4%=@ET0scflZY~M3tGYqJrDpfUaM%L20IKMv~G)OX==&8IZVO6CVm<kex@#& z^73g;Zn^f&MfNFjvhg-HZfuOKHvgRb-8}sLJUp2coAXQ)qQK*{7Ut#_j<u036D-V3 zEj|3aT!R_YQd2Y2QZmxPWf-WP8V@cPO`-MIWk`C1&6_~$nm%w_95hG>Di?bodjBhf z$|@!`22)7g4U+!<pTX|GGH4GWlNxB05ma}Bk|(rWM6!#~n;{LuE_Vh7#+h)t*ciR# zA^8G)rW4qmW>9zT1nWiaPlD8J0_zQfjzvM-2@?N?(97t>;733&8>5#Z%w7S|SyD`D z3}#?6t3YD{|Nk=>{}*7~1TOm_c2zMng2M#eF3^2@pfv%w-HGrc*MDWuSx`)B4CavV zRED@g;J-3x?;w*J1E_Jt#?$#2BF@FYz@!NFmpLd*7`+)>G5iJEcX$olP5|izwIx7j z|0B+w;%Crz&|w8FWoBS!WB~Uiz&i$-yrF9>85kJ&8Ti3VECmHYYb+r>3Gi`LpvJf0 zi>XuZF^S)wGKJCA>vcfDYp;L185kKr_Ja01Dlh~&_zQv7DIxYdva+!@b1*W4R;DvE zfe+JQ1C<J`-k|aV+(!oQd;|@qLk2QH!x-QlkP3_npats4J0PLEC7`<?K`sIfUm$iu zy0}30LQa~5*bQ0ZR0ZA+S>;p(-VgczKLcd05;Qjqo?~PTWaz^POURh%eI_*q@E9n3 z%p9T@G}Zyp>jS<O5!{c1uLFVT1&wt;^!ijl;t--2G}Zyp>&vhnhrOV>0;1Qq3|a4E zCN&0#UVrG?5=NxD0&FjMo(rTGG|#mVoK7M3g6bKF-XLiGhOSouoSz_igBT`)hbyA~ ztANiPQ)7s7;1ghE0v$QR#Lmdb0ITPvL5DmvflgZhcL&kNK0qybMh3=YG(}84pi@Vb zh1FES!@7`z`OwBWz$YYt2FSq-Hg+~P#!C{Sg5n%}vcjfD3Zm+I(DTe9b#!#JvSlT~ z;~6H#^0pG3$Y-1VGqTT8F>(cuYpXEHGD$$=6f|BM01hAU*<|3nWd+V#UW`l_@dDXX z3TiKc1}E4Vy%=_Z^@1v6q`7EDFW7uFQke=FPX_4)b=cS#y$m363egLi>xRr@XZ`;P zu@@;$!DoMg-DV4N8$%hxK8PA5^FgDY>%nmc+6e?Iv)jRLgXjf~fq?Zg`Z1iup%>J5 z1nXt=gO+&^y`VG$(d&(+?}%zI8>6=rsD1_a+ZeN${xa}0xI1w1FfuUlg09o{f*eyL z2%6~zCl&C_H~4TGeg-B`(~*e*baFf7=o3Z;@ZJZ0Mt;zdoQz7)IciX~$*!ix$f~Iy zkr*IvC?YPP#k9r5{_lP!$MjHc4p&xCcY%SCAr`zJ_6mbCgP#NFtQ7_Y(6)AYMrI~4 zMpkA~Miy39@S(eq*(T8Ofb5XHa;&W2Y58^*A4Uc_St$u&LFi67WkzM_0YAt)<pe>? zW8tUVgSKd!nwT+8mp2s_6VMdZ(P(cC4-i)2<yR2U(#Xt=V7kJ`?!wBgZ|myvPb<lf zmBo{VRmYm~nx>p%h979{ASg{VFz;jFVvu3bU@&Bec8FkPWMt42=V9hxV}hJ<#tGU2 z+sw_##?Hac#!<(>#K6wR#GcN;!N9`I!IH)WS~T6v>?0@3&CS4|rKzGMt0AYsEyFDX zS_>*9z`(`8CBnlis?BI>W@c^-TBFU#2pUxcHK9e=*cp}871@Ph=iiHph%p<htAUy> z?2P=P1_D`JdS+t(wlOjp+8XFPN{KNt#RmPm>Gw!dUS3i{K{o1L2)if;hX^~fEvJNw z3<sZ{9{-=iObOEVMiv%^@_M{~=N~x0)C4)>L`v>o-+3VmX=!Ug23E*A0I=W17?c?7 z7(5w{Iq=yqa<N%6a&l=h@^Hh-92-!AVr&Mj18(MHWa0-Mhsy%m4#mvI%A5hZjhTm& zJC%Wpi!EM&k&Ug_n}LUiJsw)gNjo@@tQ|C9&%ndO5zoNE(aqr#>7b*cEFsRr&A{O9 z>S%9iZepaTqoJ;Br(!23Bd#Q&BqYEs#v=v_Xi-5>K!d^<v=7;w-3U4ZYzn*S2C~Wo zBo1GqZfatNyuAncz_oo`77pU}q6PwT`VRI6hBh{a5(=`?lJW|oN%&4;W8TNcqoTsY zA#5tvYi?+4VPRxsZYU=uB?rRy37yi$@c%z(28-DgTn=?W$|1&1a9M)f&w;F`0F`qq z!0o3p=vWeX9TZsaET~=;uwG`QG7K{B3evj^q8B>nZ2VstsZGYl(+Rqb3fv}BMrxC> z@pS%$lsy_uag0?={}_ZAG(oFw9pv~pS-@vaGBYwUFg1fljX)>z2{8zXfd?@_OWZ*R z42UX2k~ny`!e1U;Lt#593u$RHDH|aJ9bWJOeZt%V`qI++0^Gu&tqYL-5SVsB_wq9_ zG=p|LVcG>c`Og?~ZYDVEE#}oR5VDc7kd(HNvJ*Dc<zb2wGcyt96*Q2RHW1_$HZc<e z?H>X8E0Ad^12gQ*L#*rQLD#Xt4jN<>RWxM`{CAycDeTOAkQwnzPZ)R^^uS@G3>xQQ zVgzmdWB_ky22IT}fd+~gco}$=guu52fC7jS+zSI;Jp?-2oiUy@(8J4{#f-&RPu-H0 z>4}Y(hn=RF1gJV-&|oTL=w||*Go=BxLzW42#|3P+Bm*M@Xd4S;6A?3PnJ`kGh=Cl3 zB!@Wq3A8VbDUOka*$}+e-x6#pHTNn_1?3`8ZjzK&kdRQ2Wr_pk4p1&J0_6@62F3M% z6^66mRkAu@7bvoU&zuw#U}a|T0N*bJYIB1cv<!^?s*0eCb3h>{jyi#32D-GUKo{1C zk<}J4P*Q@=#K@TI@bN2v`d5q$ptzdObe}<#!31odCIjfa0Pv<$$aX_UM&@|X9vDVu z(14;SgQ${{kdhMUczBS#!r)nPQ0obF%ND553A$cKgUwQ3&eT9uT$0_0%|c(s)KE-9 zf}JVO+ErFYR@T~8Mpjl98s7cjGcCm!Y{9l03G=cuvVczE24AlSTEhxvFoIVEGcx${ z@Gvm&i1COC34+J!*r1E>86gE9=;jRw%goH2v7cMdOw5Q+L5@2B%n~&egl!5EHZd22 zY!8wNQv$a?|1!lfb}*|la5LzFU7`d!rvP%;C%B=(03Io10Ienl+sw=X+1em%YR3er z+x~J2@v+3QNh=F6#qmivxkz)1IlIe%c6oI%l`|e>c4OcKpFY_RHXpRei;<0yfeCb? z7!T-T1vc=3tDr-Gn3))u>o{20K{Qi1n8C!H0KUE=K-xhSq!3&wf#h+ii*%3@7vtt) zV33st9W^P)&n3z&%D~CMDZ&YLIio1(UMo=545}2s%?t4I5k$qo*ezf#qs1-FUMwsv zEi57>^<GFuMo2_TirI}zAy}D5E<`B@WnZzRlsE&Z1ZQAis$=>9Sx3Og&KUfk=l^L2 z&W%irJN}=Bju(3{&SyBnq{ht7Pzf6RW#HJzz__7lgRwTG4q$R+`oN&Zpb^Rd*3Sgi z4;rh6>Id1vbOWqL8=o4+<zO{BwK&cB|BdM%SdEb$vKl0}g6+D<^npR0!3MMv1)GaN z?co1E7#NuOm_9P7F_x-=&HDHI{~5?Q`TsKzfB%2|{~MzRvm28dBWP_PJ7dWIM37!k zr2<}i!3J9Q4;|MCVLHXc#sIo+9enmX;}@n=46F>+-Wx#kU!aLArdUwfZvh(ev;^${ z69koepz|Z35)3|(4&0y{mKi{2w{wVTGm3%^#%KKU?|2l`ser$2pmTDW7(^Htm<+*Y z^D+21aDy&kU;)))pri@1N{E?}k<kKj3>s)k+!8df$`4Y)z{HRQmIMu;3$U><FtG8l z@qu>T3bAsCYBLIpDw+xlgATo6V`FD#^ndjC@xz<7{E{4;;(YZ?r~c-cnKMoP+sas? z8=|5Tto5%092TItiVtAFYk>LSJ_49;3+98ymzu$R(8e=n@Ldw1v&+F}wS&eUz<XDi zSXn^V6@ZFLMhDP_Jy5N~V9DSkBO@a(BQLC?s;11&Aqm=+g)-d@=_Eo{EwG9znt~TP zV>`RN@!uuz(q{C-%cH?}yn*)@Gl1vO*g*4W&^XNoyBjnw1v$4FG%nA>V6_!g6fk;0 zqLvpDtDrUnIH*C*NG1l*24^M<P>&WAr92Eg5`rwCC}mWJg|9LrV;m!6{5%0^P7W!7 zx$%q);O#_*^g>irLUjMxf?^w#KNBJ6^)s<C7{J35G#A0f0Gf+nW&j<q$qwE_#m>OZ zkP2~>0s|8}<irm)P)7mOi?aar##v)QXJ=Zn`bay-!j&+va4@p6uqGmuf)a=n2M1`o z7zZ~8Hy0<;m8qZ-Nf@-V7K+Uo_x#IY%=s6=_=Kt2-~ZobKfiyQ{Qbdh1&?JjU1efp z0Nt$)&KFFT;Iq!{Anp`mU}9o`xDM3pU<79jArO;^u>~#%3P#ZU59GQPRt|A(&}|W* zdm|E=BqIOK1_c~b_1{*oouKpvnh#}TFb3BZDhv!vN=%@;2SOb9K?gJNFoBLQ2aoAO z93ci;Ee&x5_+Sjs42mUa-L5d`fG%bx@Hx~FSAqft<PsqUA!kPsuuDvZnL!7$YcZ({ zGaH#1D~hVTdct`7Kc9gP_ruq!J{pWnUX0p|T;2hU|9=0w!RQZ)Q}DPQIBl7O-3;pA znSuE>;Pr;a|GzPPV7dajC5l0vAq(P6MHWT|ZcZjPb_TX|4n}s+Iil>0>0FGgtQMdQ zV+lHS4YwNb@y3>*kd#tTU|>*CS5Q|{l$Vo~U=U{z7Z(&17vuqDFYxU#d`#eDX_!HK z3d~JK`ItagRSFB5fkvX$826R5S;)GTMMg%KyU19!6$i#?q!mV%Bx}SoU5Q}wsPHg| z_cdV3%VRS1kJEFj@M4Ns!ekI)9+|<y*z~WCB|FSASpWZj2I%?fOl%C+;CM1+U|@RB zbc#Wm!4KkJ2{zCbJfPcm(mB{!nVFdpMJJLJ10y4IEL0v8JD|~gX$EOQL19rrK~YW) zX>CSP&@Dxx%BG+LEliC;(*=UYf<|VhrcCc;UCN^(qRO3RqS6W?ic*+Py*7^X(!P09 z$1B$8&8yg0#wGt^VxvLR_Mn|eOfQ+PGAJ^HZIfYxo<|8Pa3w&;wSgD=IDkuC##mNH zMo3Bqon^xc>X#=X)PRb4VMg%nctQf8c~8(ml<XWL+MwYK5ixPl0u9LA2I$O1@RT*= z%pDUo#`cN=uh@SNHaSH2Ov=of<P+|&@!x}3??R@w=Ax8E&K~}TOA3-E`1?&rDqLdd z@8Ps0xu_YG-U#j;0@a$}{S)}doj~(W5zMMgYK*m@@oC0j=o(P%|KAu7g2fvl;-E9v zK=TIw1(+nk;-Ev%*%*UC&A0#m8G^v|D##p2y&C*K4xA4_W0m^g`W7_K$i^4~G9P-s zUj&m9gEE5wLyiNt0w)tQn-usKNyxSe(8-^W^E{lrIY0v)3<)gkObnp<L)t-(fr-f) za+C)HBO``_NC!z(6-EXfEfoV*134KnQSb%5%8bgK94HIsK%*j{E4{$$v7w`qpwr>d zR?Q_<RpeOvOR=#EaJzDFvq=bY2(fS|2&n3Fvy1zh1i3jzc)GcAb$515(9#gp;1}}< zP`My4$-?Ns%AumCWZ)T}&X$sym71Cg8pi;wp#|+95ogc?jaacWva-oCvakv=GO{px zF|aYPvaqp&uIyrloIv6PD&oOas3oXGux0WAO{-~XsH-Z<OXx}J2@CP_f+o~JJ_8>~ zjdDf+c$YP3LXAyS5WHy!RI9?y3t)6{&an3LijHk8w(?hqu*-4QaM4uuHV*Sk@H5r+ z^YCN(s~zIt5yHd5l@y(xCnWIi2QzzMs)47BoBh8KA#opfe@`zjTRTws#>l|>Ux0~` z2~_kbImiogF@gFJ;G_7gL5t*U!3#LV8N@|J!F47xACssu=$194Q~#J4kMWD~#Pf>t z-;6Hg787D-VHOnS$YPTC`&BbKTuCM*R+CBS-*YJkYe4}U2Qfy_B7Y{(93PV!(+>tk z27S;eO`zI9h6QvZsTZgUhzA`}Yz5kA1s;jC1kImoYl;eUuz|8DD=3Q^AzzXNIid*E zjRF^x;7ltF-dqD2zG1X?O;T4=4Kdc$lCm<2PV6l7$hS9-x3+LekCu0|P!9C;33g`s zp(NreDyJzUp{^lqSQ=hYXOiOKkl-Ms;A7$H{%;kBjJ~_EQ%Gd6GiYv&fsp~6*O-(T zG#FeRoa7l<m_akVqKpinohS^Tl>n?>pcWMaBP#=FMJl*pat1XzVV+`OV9;PtSJhEf zRs^@GM3t35WulQ8G*N>+V+!^SbYK;tfHB!~dXSBIn4)}`U2&eGnS!o)akN#ihN7aY zer2#5qqRqjp@x)zub@bzvxc!eCo7+|p^KM@kQ={<kB%C+j5q&p%XkvJ?nK@}MjBKw zg2ygfKnL7`F0HU)^bw2~X66vrW`*Bv4BeH)WX{K=44QKS2QcV(D8`fO65$eR0>)<X zNe00=)~q^?N)?PH>9uyE8a`$|jv6`v^73BNd=jFZg6YZLwRst)jEqd4PT`$-Q5u%k zvfKioNi*;|bx9^A1`&put%9IqKcEYHAt!Ky&**gqr3p(=7}|o53j&q;po7(|LAeZa zSTCv)2We2-C7zX$fdMQ5KK8*HY5-^*8zX}NKOf{E9}z|oHb~L}uU!Le0st|<%NM{0 z`dZmVxJJ11vO-Su{kxgT-N6z0NM8nK@E#Z$roRll3?dBDpgY=NJKNYm*Mfld4?01Q z&}9G@iejSte3BBP(qhs=f_x(UBC5(9pvEa^ryF>e1nA&Cb;#mTW+O9mMKLiZ8N=*| zno@)8u$qc5KJKiHMy#GbeqPM~&N8_%R#vW!J-4-LUCim`_O`b6znv2%_D=$hPl3yM zCJ6=s$k~q!OdQ}be^84VoYNs?75G#`0R{n8Wl(k(7DO&#)l3Cfs%nVo^YWQV>A0#h zN&IUwFkoi^ooVXn$XE@kV;C4f>%o}V7=D7%*#BSuzcI-%{bNvPm=CEO1UMNP7?n5} znVA^G!L2@N2NWR|CT7_FJ8_T+kl+Hf1mjsjD_}rPK}d@Pw89GPWG8RX5*BbF3(j94 zB@S||j4Vu`BU<1WM>>Jh2TVaE<fv4226Z)2RTVZ432kLzbv00QvztQ3WyFQSLo=d~ zaW&9Ig5cYF*`7-asA&sHbMq<-89Qi+t`(N&5M<?+6;#z0@Z=B`WMScy6|7?7^VT+G zVRC0?Rq?X=CuhdO=*Y^hs&iJt+EQ3KK>goyP&)urpGYxDFtIU|gM13=$1?t6l3);I zFxtunI>r#%r{MwhX27W%+^XbZU}9iu0gEyCL~a$45@6;K*A|4G!D?y@x|&%zI-65m zl$FKKRVG|DIyjz5;@^D<CwmdQp2dloTbBoe(t{Z^|C@pOeLSGMiy2v%LANTfu(rS! zoPaiygIAeYG5E+RswxWFv2jRgn}f=KNTFnAZotL{E(#z=k%<`_i-L|Q6cGcJ3ZMp) zGNh%duBK+D?x1R9q3NulY%VXy7$s$y?cx;~92T9R<!9z&t0opKt|DM+nwWCV$k&*g zjnC0i-&U2Inc34t$;H^%+&RM0*hGq3z!FlF$nc4aatbE>hwM31XHsHf1Fzj-WZ?P# zjj0%1pRI(XInbmiE8>7(Y49v5RDhWQp57$cSeTfYSYsJjS*^W6Q%&Hb<G^i4NQ#q1 zR=~i_YzbAx0BvA`E)ry9U}mgCRtGT%q9hW0n+s^Y6zBkPZY~ZsPy>L2Lqr=sg>EVc zK4HexTv1e6P(+N$f=`TtLs>lkad@r=lYFL>9UF@)D@Oxk<Ud2k^J>bT|JEu?GcYmu z{}*6V1D_Ku58D4G4!@TgG^-1)Yn(yN5lBBCTJ(vENK1;yi^?mDE3t8igF5rzjXR*r zF+jJ<ff~H(N}{5$)(4YXL$0Qe3@a0JWMiI7ruCaiGCmsquC9zc9ev_rg6_I~Ow65a z4mCx`7D-BEq^75W(io_YIR$PjLT*N50G)%$<OMp>22{^5#Dk_9ok15=i;8ftF(@-C zvp|Yp*aRMCI?@B34Q<9~so^UlBW0%;?jz&v<_k_essbiv=8>jOB}__!Jf2+qd6_oO zYWxD0nmU1U@?M|>!^LHq8l2i>2kPR1%jrNSP<bc|I^`I&ZX2A`tw9wGB%~O8R8<94 zm039?wN;VIV`EWeG3bS<ppCkqTiw+x@`Li*-J2u7H>n%^%kc^h_R`jnPf7XaQR33k zlu~2ishVRKnv>@5P@oMO2x4Gl;QIfS@d%RygDB{ZQ4vN4&<)DaYdk@r!V(KA*1+`? zI07xfw@!;Ph>EBx3xY~4MsNxN4fjI|DK%5j+$Q6Zi>BIQ`T~6BvU+|76FiwDy#8IY z(qm(FV&jtbaAq`CS7u-Y??cmPl3);HP;pQM4MTy;7w}nPpmsVVgP;KTmJTsSF;G(r ze31=kO(LjF1bNvQykD8oI5Jry!p%3pM}R*<K%kz>x!9di_20d)q@oJ9JR9qLui2A9 z#TsbOh5*w%CM5=01`W{3x{Qo03`!hKj4YrFepy(+f$i)KatF8=w`KB?my^?w*ANsG z(*}7JbO$ncn>6I^WzaY)8@N{tN(-Q+S%RSB5Y^_osOswb>4kXNMHqNjdxUwFx>zx0 z$m$pe8Q3z(>KkUed4_ASGHOM~IhXq<);h2}f6ii6krdd@XJG&DDyw0vTU;{8y^R0A z{uf|UWRhl32JL-RWMpMfkP_!(XJKPv<p<YV4B*>QKzHnb0}it0%$C`QkwIQoQbJge zhl`CBl$t?ZNns-~adBZ|X87T|;4w3Gb!KRl1FCVNjP%7_X2xBL6;f5@73buZ6V<g; z6>wh{_aum4Nm7`POP)#E-g*tA^1qHZdU{MuF3hZowpzRX?PHvERYRA}m6;XnZg4rU zhv_?m9OxW1Sw_&z4yXajYUK@TPFte{F#`jG9D|&QprDvIxakQQQUFaMiGr#SQSe!~ z;7At}7i3%&nl2y^F2L_q;}hmn<{WMipvUz6uNQk-mTRe-OSw~etu^cO=gbxrDU4kI zK6{6$u`q3ixXI%GH>PV$5)7IQCJu(2;0+55(7KtOjS18p1Qk*Y37{&?65QL+WYAO= zRuxlL<KU3eW&|fSHf1GsWpKcOre2Lfr(S~7B4h{wJQJ?YG+SOqC)6%SiB%!jE>uTG zK1yEB#?Vkd#7Ni3Moykd!mYtCpvomG%B3p6ufff&!9OwC%VPR;JD21{{{}bE9O_q4 zUl_E%7&6Apko7+S(H91bgZsh^Swak8aZn#z9n_}=*F9{E!Jq*~@H&=nO!^>kMzDIu zV9-d&|Nji&umFosh4jrqXDCC)HyJ;G&l3Uf-(kQw-vnG<d}Er$bc#Wap#xH{ae+pi zKv4|33INJMI=?`Hft`Vgk)0_ObPqeYT2lj+{0#BTpzApFKqJvA*px6ct3%XrFfuUc zfksHg85tx&+gLznlkkJi2xgFDl;dOv^~fQo2Z2uS23_e3I-W#PR9O_XOhHtHjq!=0 zw5+z6uAG(Ij>u(<H*W4v$xGwn@#7LS&~vb|_%{<YMtL+g!Ywrc8U|lLbI^<lkU41d zvtk$^cOR!QU1gAEaC2~$Vq{>IW@KdGVPt0FWn^Jy0Uf&v>OiJ~26(`$mUTg8Ie4{* z9%!|QgqQ#yXy-l)GlMLnEIT`RoQGWzu>us<e}wk67^i17@iNBzTf|yhX&9m9S6DK| zEns$`W3r~IatKpvS&3hLrvQ(iY|PU9yrnS`BEEv4)l}fQZ}6R$Ol+Waide?8i5LR{ z?c)I5i_65upbM_A82^7|Zelvcpv<7d7zVj0hl_;~H1-HOBu?6U17ARd14x7oyi&(Y z+IxdARD>Na0$O>DtOllm1$6F3WMm}7Tu@7fospS6oq?4VJXWdZ4IYn<XMrUhh;7=S zOXJy4)G>gT<3f}{QW1pB09wloat<*@gB(ec(GD6|9Rlv@p(SR}@vY*Z5hgVi8EGjA zVL<_YNW%k^p2d+C<l8ZsD}v4r1ywenb9eZd*!h@LA%h9Z%1(mHyxcMZa!Mi`9OBaa zj3L&Ul_qtaOV)9Ti*fU+*)#63kBvx3G2mur^=4()_f*%IbSVGdC9@dI_#&oiuf<bL zTw)C(9GzV)z;O$jSC|3bS0)1;3*lg7WoKjs-vy=yI@pONj+2dvg+(27={@KO3h<UP zRYgHTK`wSFZDY{Q!h*&~?o||oyEQS2(J0yq<i3uj|IRV?+Q&pBBpX03bcQ+!w7bj~ z>>9{gR8To1%%JO_1wETD71VoXiv=x9R|Ai$s)Ji2;B9Tn!is_%>{8l{(2Osr3?8cj zHDpa0|9w4_k{xB?yeDcY)2V=?u@V0nzFL|8o5fTW0O|vQ<_EICd44lA&%Xh$J3(Hb z%l-cwQvve|CN;)AAT>;C4DzUI7#JB6|GR+aGPuF_c{4IFwt(ssHE^3Z4%CTJhu?C| zE~TxgEUIh@yXCs_Va)9)#?;6?dzeoBZDWG$IR-@vXg@c2P7!)mjS15!2GChGh7NiR zObn2#;29agQxRZ`m}5cr$*42?Fff3QT4Ug4;87G5WM>CYkccXR3Po^QQir9XM8*~W zHf3d(>6P`A=Oy@srN@H~-ZG80PRa+z1*A*_-9-<X%Y^VjbD2zRpfZwyiGl6E3;2vF zeg<)9x?x}pWME^1Of9K-vxDx^0Ow$Ego%p@3c%M7bFxcnGYW#%4}<y|#&*o+;>vu? z?21fI(P95Y!^~A2jTBfuE@F|_w^U&C1qIH(FMIYd^4QH<xynD#YSPR;GjJV<GUo`I zMrB}N4q-aQAP72Nn4gD}jhU610dxc@69a=9=ynfgW_4yCArKH`1Em{AV~{f#jTsr0 z83mOE8I>6o{=H6N6bxe&O!@bkQ7--8%dmeh(i!s^qyH^qjDp~Q6Bx7pO#@+2KSS;R zHzqOg9m5U|w#tmmEX<5d%#d?r85mi-R2W$pJsCiYjF`bY!(nv;Xi*^pxRO&<QB+aY z1Um<19M%-p{Xsvh)!0aki9N<QDsI9At4v+J0>gyll8m&(tjquhmk2Fwt!m%mN+xB` zP#zYZNVm8$L9rll2@fY1J8yRzGb<%&TY2pi21bS?1_q`D;CwIVAT7Yg1YMfMpa#BZ zMV-k<Tu@wqg<V2h7<5G*8@n;1F=S-eT$xchDTIlIk%h4{C4`xUk>y`m3e%~76-t4w z{7n9T%@|u$Lf!cPu7k8w!1jRi&_-w;%EQb<3=B+JOs5#QKzE*Su`_{!%L_C*qz1ks zU7f)Pd?N_Egtj6$o{R+<jTxD;a{ld&iej`*`*#Wy8BC|Z(X$kk4*q{-N(Rp%1v+r? zGctpYKV$|?jDw1IG1&R5YM>gLAs(7Xr5&V@Bp4XfL9*cPj~<gx<aTjYbwL4Ec1dl} z4b0#I8PsJp1;>$@IjF>DN{)KODF!ZrjiE)fvM{KK=3{J!m%HFH+0au(ZSs+PNce!t zU&uTqVqO<MPY&CE1e-gB<U>$-!^Fmz3(Esc5dFqrK4`8rlIaQ)8)&BL|9=LQIYtIX z25_0ibc#U=RK|+(b22kBfp+sTLAFjp+i8%L$-uxM#ULfDs=~@HuFc5I$As{*IV0kN z7^Z?J3XTyjGKL}|dXnZ&GXLHtA7|xbWntlFUBh(hAESG`J_mawC%1tulkmTCZaF?K z1un)OP#FxJ-(+HAECRb7eJ(KZzYEg^rc(^upm9UcqMRU5S6R&)w6uwtF^++eQ5`&J z$j!hF-j~46E~%|5sBEeTt&^B8g#CREDq;QqeT9~>e_I(CLHjwGBEe~2(?Jb1*vrJo z2pWH42Gu!?=@3g87#P$Ue1w&Sm0|G?9*_esI0tnA%ms~^BBQKQ?NaihY+bD5tfLrJ zMI>V*7-j!`u(A{tVFaxO2hVjguLk=;-a!VmYnu^LjWK}w;;3~4%-M>9#>}h#Y>Q%) zjbfCG1{HryRgn4tQr|Ft2A|0Ysv{Yg8G^uLK5E{O$xozELE5dsE{zf{Ad8qkhy6Jc z#V8idC?16rJZ(%>pb2y)1`Y-WrbaCF4g&*tsDfa<1G=3VG>{`I!ln$bch)WYUzk#2 zSk+ux5*`#4o5ob_4{Zj3s~u1jgX(3_{m<MC{0tJH5hVsj1~yhkwp7r_gc|7Vex^9c z>MC_6AJED&2{9o7$e}+B+zecbf}HGP;6@3|a*$_{8YFqiC5DwPjM-6t4;6+5MaF=N zE@<QE)L%0nCudjCo*O3cxgq}GcoSyOcF<s8WME-tWJzTJ)g%ne%uI2hBhbNBo3J1s z55#IVG^^E(jld0(#HhC9a+8MUi5=?`VyZ#SA8>2Tx5X9I24iH9`~Qu}n&}FI9H?&r zy0ej)k(EIheCjO|sBZx|lNH>z0FOI^`xdaW33S!0l%%+*03Qb%sCNYFTL>$$LC^gH z)%&2%EA)_Nb461{HMJK;L5ixHSr)}py?kbt*oA3ng&8z9v;14i7{%4d)GE&JEg}}P zFs*b|3?IKAw_s<3e{MBs9y0O&H|BdxR~bMnu)8693FR4B7#P`D7*iS8*_q>^O&?H0 z98|1=dU}u!qcU6>Gc&kR39AQ@l{%>7QpLoi4w|_IkJf<tg^>>2DyqtYf`Y=z9PBcn z0Ys1=)zm>Fn8t#}pxY{thRKwb*qHCR_ok<Hd$FvHidxO?)t;Q*>-qOdc5!KTR!K<? zctuditjvF#L2(n`>l?i^zkT-X_V$^xK+Q1*F$M-EIi^z#e6Y3-Gb^JP1L%Zy23BU! z>>4ynfc&fu8b=Tp7362&W8f212e-l)nU#gXgNMeTI#ducN^NY+Xt6W%gqpKfYukya zoUo{fm<&dZe>WH{c=Q4s64U>hF={Y|TDv%TfXhb6*+Gg-Y~b_pm>4Yoe`8W)`pY20 zpv_?Dpr_8q#Kg=9Iwl@;#0F@QA-EU=Cl@_NA30eSC0T7bZD~mnAy#$~ZO~;aW@hH% zd`#?Y;EO#${btBGqd0g-12m@2E+WTdnN{XkW5%x>5hm~G!^*~I=&F;EWtZ=f-}1{b zz}8LI-H?+{*`Cp9!x1SyF-~7LJ^?nqoC0ADnYQexa_d!zA!$MJ>PCWwF`l4hUkuEk zoq$ZB`{o1~BtY}84mzN7-63~ff%ch#4!VqGU}V$)<#cchSDnE}QCU${5xt3|4DND( z&UOOz`o%$qF^U=+nK7~0=o@;cmOOuE8EqPAZr54a%J1gV-0I}UIMK+0i-q0N#wC(T zLekn!O?mQsJ&iT$kg=jr1_s7COcD&Npf(67*1^m4G(bH`NF~DxUXRBv2I_5q+KO}D zM}S5+jhH|kZzcxe|87i%OcLO^H)96_(3~<-dsqX#JuD*3&&R;azzeRo(AvYGh*9Qa zVmD@d>=*j4J4D;nmGNjftD>p$S0;&nM*sfo+QrBc|GCE1Wnzl~s2&B41u=r>AwZE2 z+WyVJ^cp;$qvN0{z{|zX!pOz|N*$~$%*@Oh-b{>4;L44GfkBW#5Y!wN0#%)i%)-jd zg35x-%EHXX!h*(v!b~^ren@!{^djZM-GrM#x0odU{rUHXQQ+SPFcx8C`S%BcAz`Ta z{~P08@SL=lgS$E-D}x&J9s|&AbApVZdkmo07o>uRF+qbR`k=`%STcoNI4><JCc@7P zIxHGomVsA*vx8S8fpR&tBr`QZYZpI?$u-wgFjLGgvx<{fiZ!<hp6Oxb8f<T^<E$Yc z!ldNoY-q{L!l_`Y;T$a_=r16pX%yw5s;j0ZDCh=St_j+=&cMK=3l29~2Pqb2CI$vj zSixEuf((LUf?}Yy5a>2sHg<S}m{D191rswPqkK*fBNOAl$GJ=r|90}~8}c$9{QH8@ zM!>|F_n!kenLy_$b(y{~sWDyzjl(gifreP1cC#``K-<8q;5|=XpgIrk1VJGoaD$u? zbmt!^o{R+<CnY@nk@hJff=S}vzkjblu>y)CP``xz|4+uZ;PWw3y*DU<Mq{|aHxh6$ zGPp}SaKkx_o{<oFc)M5w)bhpFF4h38%0O!u3#lq2w~LWlh>DDFBj@qz`C9Tya<K8S zn>h+HIy0VMc|MMr#fgdO*%zpvr!Yw{2!l>x6$0G>z|80co@@nq8lFZ$eSJ|eK{j>? zZBQ@G#LQfoS(#Z`3_L$BEX*{;pP7kyz1J#cX8+QaYnUYdzF-U!)fN92$hclt|KD0B z2@neuCZMwxG?*k9xIy-TR@gByFsHJyGJ%R4P@@lAor6}2gL5S)OMuqG!uqLe8I>a< z{@smWlDL2W?~C{EnIvF&4|xs{WC!TZ3U<)U4tP}>XdNNQKd>wZUA_ovQwxF?FDeT% zNk#m79RYUu*?-0mb3-9_<ub7`K+ar&oXG~7YXqHd#t2&f%Xpkgf`Oeu+Cc(T@ql;h z!pbYq;oB^r@B-C{%BG5p$Jd9iW!%ho?w=9kIq-R_kbQ>|Ol%CGeTU2pX8%F+BtIC0 z8Kf8#L1(JSNK1(badR+ofL7&zHk5#tuQO<YsyEOGkR&s^s5T=cSHdSm%uNNs<KyDc zRf3FD{VSY$Yr;TeeN0G5OmI|4DASJ{9Ij=7RTH>gykK`N3#yvHb>rWC&h+T$3{J*r z|FXC;qN38kb)FCd_%2K)Hil^MJay=QH>Naj{3$yqfEtV7{(uJfkRe#Z7aVm0Z0u6n ztcZ?)F;iODKi3FG(FmViyFg_q<GFvJWwQ*73|<TjOakD1qVJ%?#>l|P4Zi0PnmW>1 zS-`1-fr$x{ID{C4lm$V}D+z63Q4!D-m?<cIK)ME|i_(pPv?C&P!)=43m?RFz$V)x@ z`{KQ<VweZ$xFAs7$E*W(zp8^08!Iz2EaAaA0}SBPOu$|Mr9MVMP~#Oe!e%VUtn*hh z;(5diP%44?z=-i2q}&bt@6KGwB*DNB>eGSxzd?}BfQC04coZfM?tIif0V8A#1~hsH z#?0D&5r0h}w)`{v_irbPMNAAr3=B+7OcD${45HwcIRiT*3o8Q)=)h#i5EQu91~-P( z8GZP885jilc}4j|89-Nfs3>xPl00ZI3e+b64cIe+YHrYKQby4!dD&?tuU9ipnK;GT z-HA!!j<2_OB;z@+f45d^7#M)|zeC#&Tft={s3m6RV2s>10Nah!HvsK#1hvDs`MCLb zc^J4DIN^N*m>WQ$3-20)Ms#PSB;_$`M*RIzZ|UJ|+rT7o$H&Jz5)|U@>V}3OM=*in z5VTL2fs;W9JmSZ|z|6wH3<?4b(3l@A8G?oh6hPwz!p24r?;110nkZ}MUrfvY9Kk5z zYBzPdg(suU43H)N+6|T0K<-A7{r`<|JChQmKOn-$!V2mOz|MJL0o@DA1U+aF+>F)- zHBunQr|2>GFfvGpK@QJA^al{5%a9HLXupp-WVH!s#%;Bpv#gw(j$aJxzaNb3?EXHo zuF{gS0UF-Lj;@tl{Cqw<LLt!}K|TUp?z}=4RVfM8ptZV8459zOG4n#_{^KDHea!xV z2BhT<DxyIB0hC6*255X4<_GjfKB$eaBq%5-qy%l_gDMy33EU93vx1ihfx1{qY|Ok3 zxoLIm9T5?oT(zmLSvLQgTz!3ATz!09LFc13RK91DxL;V|SRI*~nVFiJmd3!uAi%)D zc#BB_+^*Ml&|rej5Q3JVfKHiZ1*c?q(XFT~D5wrDS&Ws<;mvtdWpxoTV`EcgCAPA( znetXD8DSqHn(AHc>iTU>AF`|18TbVKeQ|Y(zRpHNSbf0=n$H963}awp0H0F~I$P~O z=&qw53|b7`4txq|XXb!bnrX2!vT`u8aDsM7Ffnn)GjMW(gBD!wL#G-*=O$=@rq?u( z6mv2#F>^AdGqAB?Q5xwW&B&mtECbs83!P{KpQxk7sKpJQW<zXWhMlMbI!_IJb{uGp zjWIYTL<L3I82iN)czC4*q*clzT_SyaA`Tp2W@MF$GD%8u`M}QV!NR6&z&O1jCGOup zrdY?QD8~q4H9<|S*z|wtKA<&?khT%y9ME2M#xu};o}jr((7j6E7|+7;188j{Xx>el zk(EV;k%1MQAHZkLfcg%gRa^Stz61C;A#i?>6c-f{782m&WQX;S!K(^Pz)puQ_duSC zV`DV)Dt2-y_0;r}m6CCm^$p-)WdHYrHNa2TO-|N@%d#>trN&Z#*MpnSFTf)*Oo+#a zj~^7b#{a*8_nopagn{cX(9zUenI1B+fhx`a|FNGT{r~^}lm7)6AnJTUJr4%<|38^Q zeI!s1=_({&ae<D`VDu7XWOSE?wAVl)>`)O0ZXre%2#3)VG?fNAyGN0Mfs>Jqg@FxJ zI6;QxHNeaNAghbi!D|>nEkkXvLUvSz4D9Ssb>LzRbeAP)v<-A&A;?%PszKd0b&z84 zQa3$jpU6lDF)2yVZZ=6pDMbbe1_>2qK@~+V(C9y`2v!zU28}C18};Uh8sT(JW@>8j z=~`Yr9}5M3Rz7w!Cqc&EoO~-!S9tBP@?0FdBO~+kFYsCdTs|{{8rwn)(x5v_SQ#0( z*qN9(7?@JQvsfD53>+Mcai9es>Wn@j!VC=JqQcT5(x6Shpn6wDksCBI0C%1#w7@YH zhSya;Dza0PO3uEEiu!OgufWRFg-PPBkGFT^dr%2;AMTX@{~0(T=Or?+F}wt)2T<FP z6`Z~=L(}(WusEbG_Kism+!kYFQhNli*O_F%?FCSKhn0b~1>|lGP>+cr4z#QSb^H)I zuOz4}s>~>`JAzR>Vp|xb2LJnFC#d}knlJgw9LvBCnjc|dWM*P+2BkO9l3Vb=FQlW3 z)IJ68JX17f{QGZT6r%@o>|@aGGtj~s@b*f^c}!av*csfsH;4yBIEaDTxoV&;0(jO3 z))JKlOCZ?<lZbQx?Vv%nOc`_tnJMGEj}f1lwmkT!!z3{WGDgnBz`#5eG*`y}K7)h7 znNbaO4&ncQ2DCFc7@QgIfx{MEZy94QLA_;+sz`c4dm$k9X2H&6K{|s2VlU`CXwY~s z8$(t)#Lb|9MLPR~!I_}|!(K?dgZ8z9+Td&q&d@uYH5i^Uo?!%?p(W=a4c<QtDj*qS z!L4vm5dquEZEmV4s=>JADR}c5BZCIRQ|1Fi>tmh))(2iA0M^F@ngwEDVEX^>zY^oz z|Ia`(+YDM8*-~5_<UyCfF@w$;WoBXm--QT@WM(E`a7Tkz0(@f_tD-6BUT8(ex&IOw z=Yw#R!x0At&@zdu42zjgF>o?SI*2jBcA`P9F$e8#W#$#t7FLJstY8;n<1>(O<P;HL zWxUF5(rBs{9tv7F#>0qY2B<dx3Ju04P{|73AqzG`9JD*uj>&uuJFlUHBbTrME7K`% z(*{%3h*0JK{~6@}*E4KmC}Cu0Vq*~gy9#uR6XTA*t3bOvK_)VQ>{tSGCrAXF9db<K zpyL3{i&zDOxf~@8_}H0FDThX=nl_knGcbY7V2oxu#lXQJ2wLF=YW6V3LiR&9G5BzD zGB9uoatiYDFmNz%2!pmlGlJX<@;qpjuQG_i7|kck9?#BeC|SWL!x6{Er!UEL%BtOj z+oZt^N`cA;gk78r!dUF$;$mRn66OL8G=TycY!@tmlwl0U5KvG#af%4CMzix7NH}l_ zAqN^P@E~bg{(n7V9yt8CVByDv9Da@r42%cBXE~ZX@N#p3j&5TFT^7X%y$6w-fswHV zR6;a^+9)6%c!aN+!6$Nys1RsdJfpg>vM{@;xVkaBIpcxVk|`1k7fPf^u4a6~|BsjP zGk-Y$nKS&Lm|*~&igSeN2ZJbsg9GRqZ6WYcETD~4Y|KoIf}l<-<N!&KHMlI55&>DN zYA&iSu51pn7EBnkg9I2QSFe^xl~}PtRCL7(iByTzt3^NZhw|;*$rsAs-_9S(ziStN zD1SSsT=ix6$f(Wul7X8+!U1&tD<k-PF3_MB1Ear+637nZi=TZR^z|Ga_4FMWbDb?M zot><#K=(BM|HO2jp^`z30klb2ok5V14O~YEGI4`x!~fq{GQfAT@-s*>s4^HbSTndX zY=yKAjD$D@nb|~mgqgWm*|;(oSQ!|(SsBv>7(pu>`I-5c85p{}c^SF6nc_LwnV6Ws zH*#BH*Tm1r%-rM+(aHxo_J)b68LXQ<o|BQCy_?-9(!tu+#@I+*O<D?a_ky#djjOGz zrMZ!{v9+$YnxVR(qP&!<w5qtMfTW-#WO@d2u!ATs>|RpHvDK`M%8a0Ol%S@(sR=81 zun!`mh{Q&yP*h?Qg{VF3>Feq1?(N1T`me;7vFBflnzFK*FJlH&m~k1D@$VBvf)`9N zT`A4VDlgB<D&_iX#&pUgFd!gk(ZUBXK^Scx5D*x+XaR%-#j!f$2}UOH{#s!N0Z<<s zv}L=A!ADR49KFWO$}6H4S}~pa_YaacLFzYw)w6^0CZq%apNPQF#OMRsQj4^i7L+%I zg^ih&g^ii7H%2Xd)flx9WZ%Dkj7(qyL1nuIBR}{aNw&?bjEwNRm!X#~GeU1$2ImcR z1`9?$s9I(QkXmt3(2bL+D?v9*GG2#VEeXlf9{)cvt^%L&%K}bkEDX;;X8Z@`We2eP zp=EXxG~<FsMi`g{LFFxI*#x7*KOb+#E#SSkr$B4s8RZ#cnbH~EL1&>d%4^P2OM{fN zjPmeuR+oW+i50v~!`#7yfrWvUk%cvtjggU^k%0qT$1sCx7p5lg(a_Btpo5DA89=Qw zFa{m>Yz#W>O%Qezq_L>7Xj5n?WAnc&jFSJJPoLi8$i(jd+dt2-3FH?BMFs{Y38u>o zpmWN?K_l~^wcwJB>}=pOQ@J2Jq&XQu`=8lZSX059z<3}@A9Tqu1Nb~`Mh0aiMFn{| zSs4j&F;OANQFPoKYz%6QYS056p?wKa@ZodDqRJv{pl*e!nHk8nU~FQ>7+?{uBror& zX=;D!)Tz^Ia*PfCIQ2~v6B85TnJ$Y9xblfuIYl`7IXOBD1bA_IxjFecI;EF_L*3{9 zH>RiHIY|))9fl_kd|HewtO|_mjEam*?6C8X^ch$=8QB;?_w=zaFtW2Srt>f|Gc&|; zGlI_R<z?jJY6bPWnG!e{Aq4^C?nq-|w1El&26lFi1P1U?N74>vyo_ATtjt`jb$GQi zplOVZbWjx)1zj91sw1kSsiCSYCj&a+Pk@g{gja-%lY@<cn~@uI!;vt!5MTo>gA)`7 zP5FR^i&(({3@QcSo7GH}P0h_OwU!x{q{)XjXiCLI2Qhl&<w?o&YjE>uE0{a@`pGk$ z%1g0HxBvHw>6GukXU=}EE)^Nh7gROaSRC27oZW6~sDQ5YVPIqs|No6ipXoA#0YidA zEG)f9GqSPDFtW3;c<C@QGkS6{GBGf-FoAAag{GS{aJm5na~EjHgFT)BTvjqN=;^Ae zC@U$*LHeQ4>-7v64R}D;)4;Y8vKxykvx$g`h=_yN_=83kA&cwPl}(M+OiWF{iO9^1 zvBoGuQ&q-WeTM3n-;9iRuL>pxsr$>zdmB`CiUoKuGJ5z6_b^=+lknh|+V99E#KkGf z?HC#>#OKE+)K%ulBf!fg#^zW(5p<rI<Nx1GUzpA_NPy21GhxVf$lzjRVio0P0-b~g zx_^$Fk(H5&5p;h#3kMqq3mfPjb<jH3bOz8}%<Rkz=?v@)oE+?+3)NZJIKmk?IN0JD z*f`kyB_$adj16_QL7Pq`Wh7;!rGy3fc{$h^Bp4-l*hI7;w}XRrm_c$4WH42fjg65} znNb+&WD|C9JVOR~-gqYI2N*~j2?+{n3umTF>5B*(GuD8M|AS#}j^UwhjuG$G^>o$M zb@kL4>;1!Ry_LAxP1rb#3OPAUIJp?TL1q5mn}Olsfk9zmK}HS^MkaQ4pt)_c|KAvo zF<oI$V$cGuyw{W$7U1V$V`O3U0&P8KVPvQS4GS?cv!t_v4uD|@2dzs4&A~G;`GaoT zkQC=&V_{}cVpL*dgY2p?1`i6WnVPb(ffm}EgEmw`r&&RF(FlXbQ$)=e&6Q19jaj@s zHQltu3?!uV#ANMFtXvJl%+!Nz)Fi5`bghCS6@45FIr!MD+4<SuYq)6mx;f_fi?<tD zGqJ=NYhG|*0B>YqKErg1L6kv}L6^ahA=V*^kCByunURBq$%~PZft8_|ft7)sjg>u} zhmnn&k%fbeC7pqTiHReWfrEo7mY0)@nT3gi$yZNLSxH=sfkDqu&(J_$Q(Z|{Sr>91 z4TC6ysGx)(9~)?0p)sSefgTfRHH<Q&vVk0vsGur%&mhEypxw~0``+126-DDy8C^ju z@BNehZD(O(VPa}?2nld^2n}-4QB%{=QCAORWMn$^cZ-^hgB0V0zh+E+>bB0(|4P~- zf`Y=sgMuQgEX^%UO)bnV54gI5x>gK=j9E;3nNBf?Fvu`CJ2>!jGcz->GJ0`waI!G7 zGO;qXfHtzRvND8%Xa?3;c1BhPR$oz31_n_XQRr|Ng9w9&n4pj#HydbX$yitzG?WjY zUJ?@pb$>yJItVhl#>FK@J1{Y_q?#tMFf#r7n##zP#+b#J@b4od|Gx!iIP`fyECCI+ zi;P-kX8*2%`;VYAP+o%8ZZU$&Zzcw#|L>VBn8X<*8I%}29o!V9nOIrGMERMSnV3Ke z$XQq!S<*r7WMXDzN@ZYXU|<esU}k0jjbt%1_)AGKGDs;&Dap$U3xYO{GDtE?a<GAx z!h<&HLe@NpDnfQmfoArFO(EL~MHx*)i>>v%WAr@BT>j;V`RRIwDJhFvhlB|Gm>9W> z3;NZ0cx1RJIM;-(6IZn{6H&EOWwdJ-QBxA{0JUXU85I8iV0s5`3kWc1GMF+rF?2cb zLGEX^RS{=qX9lgUlM9G&PzGHQ%goA_!3nN%K%Ji^Z*E4=P!bml2Qwq+vQcRVb!@6Q z7#SHs7vHe6v&3^Tvaocs_(VD=nVSiLZ>u(QGIui6mzNdP6w*Yx&lz-3A?7{R;B;sX z3KZ}NA843T473i08N445vibtD%0XQnJYAK?2)e~u6n@DwW1gp<u7bRxn!T!dfR>!P zez2pgs)~YwiiWh7hOQc~qLK!vy@P(W^(_YrO*26eZ8a4`DN}P*0|7xZO$%p6Hf}{3 zDOp)5DWzK~GO}vCtOA-cGAaxVtPFzxe=z-m-UaQ-5Xcb6XaK2<Wsq-zW?^LH0<EHt zbTDS-W&m9U4U%SqT@;Nj4ZRE6l!23hi;<HngMpC;bR#%JIs*#}YdjkxD=YW}Z}1>p zt2aL*H#d7c9|tcpxRE36y#W-DmYAB^*udwwf(PsI8Q@?`yk1^L(AkL~Cve2`F@l>E zk&zDC!9jZ9%cO(ig5!L>tu1w3^<1%CB`pBzN`TkR8$;Htz)mSZOmBeV9&wE{<lZAv zQpOa#mrTck(+y)c!PG+3&C?vDB_9S>2Ic=hm_Tdgm>HB9tQp)HLKqnxB&9@|SlC4v zIaxRunYq{*nV9{}G?}@XSiK-o3r-izpmf2^%gDqHx+9#8jUg6Pn}H)3+-&Iurwhh- zJ`NseriJW71*Z$bnt8x^86{q&9n3*D9dWX=q=V82E;F#`jEr>9^7K$qW@TYu@Cfk? zadtG+SGHEMhO`)k1bDbulvtG*Kto~zyrSCR;sBf|K#MdX%?5ULb7N6uc35e^NOA$u z4UTAY1vfEiS1DanQv)egetCh<J2`n|1)ZZp7>lu_09AR6@<NoC*I7VVT}MregGJ<m zc`g%+i-Vi*zsICSJS&62{~t`>z~wO)gEE6YgAKzh2OdsFCI)jkL1s{W4~c4RE=Cr1 z4t5rfItDfdb{01F3<l6KOQ1z1P2N0=92|`C+^n3?2zJoNr<xNSqaZ!3@!X88tlg|W zkq#<`20YxLo~(h5p^dhtq&T-Sk1`7v3l|4F8!I?McwrGD3_7xbne>291P8q5s=JKp zs~ERn31zIMa)FKEzt(>w7RL;X45>_UjJKG+G4O)cKR`~O!gKy5Xf_+%#8Wp0F9SDc zyu}_KpA^U%#HweiXUfX-&D+<<$4ph-1T=oIk12xD3_Lbww~ZaN#~wB)1{wti5A8Cx zfJViHK!dytjG?e$Qbq>fNR(?%5XUAmnz4w>@f)!5aWOOf;1n{m6yp)T^A+D~}k zzcPcv|HBOIJe~i+S8FmbGVElEW3&RF-H7A{>3|6ENIaQtu;LKpV-9DPP!wYN$0KNJ zAqI8`sNDd%oN57MD6>BU7lSZpy#POaZ#V-p3nOzV8!HnFXcHj|1Nh9hSO!LBMqh4j zZeea=K_Njw0d^iqZAS2h8B<|nL1Sgm{!2DCc6P>4Tkpe1J#9M}nOGIL1DF^R5=<DS z|GkYBwUFR86a=-k7#ZXkr!zV*`!L8cI62tMg03Ku5ny6w;b&xGW(I9cWq_QF0$J9Z z&Hx(L1~s-oEqZ1q(5abn400-}D$0UjS0I%hpjl|hx_@}#!l(@^34+jy2xcExE=S4w z42%pij0+f@nSB`87_=PJL07ggdVx=&Z2^t6GlqitlChw40~+pUV_*{$WZ@Ch7KY>_ ze@K2<zz9z0ps;3UkYt>}=*k?zAi<!*U<jJ|k{4oQW@cjaVqs)pWdv=hNM~SXWCXV; zK_ipQjQ&!RpxtPaDpD%E+@Nk58xL$~jvd@yf(*k!t4nbu(72m8xCzA$ZZ$zFUG)vn zCXy2@cd96;XvoQ`s_H2!X=sAlOUxmN)(}!rXAWu-@qimgJHSmMaO;SHL5xB3zbo@e zrl$<744e$S41x^e4AKnp4B8A<3|<Uj3~>xe3~3Dc48;uP47Ci+4DAfv4E@ZC-W#|A zA{_Xf7!@S-8HE+}7{#QSK|2w-QAGtnqUg#%Q>Gx@eWu(@j7+>tj0KvEs)}lAss)_v ztjsJ7TqYdGY(^}G988Q1OsV{gyn;Nup$vi|Jc8k(j3QDJe9SyDB0T8~lIDyG!jcN< za*Q&vjM8E<(y0t$0>WaU^5RUwW<pE?O2Pu^DvV0XjEbsCimCd#+8Qis>gsBt5SE&H zoQ;9Co|TTJmIbG}n!2B~_Xd#bTS#%0s0foF#6f}>4ib=&P6atd%uI-x47czFL^uq# z5OSCR3mo1$aGWWss?`l>q(w$XI!x~A>F8)_sjI7~NKe<*5fb9#<KhCHwAs_&)8E(I z(cRJA)!EYC(%#lu*Id`!)Ywp8QCm@4Q(aYAURGLCTvS+)o}ZqVm64X3lAM&75FZy4 z86Fz!@9X7ZYi(|3Y^Y<UYo(>3q68X_1TEbV5*Grm-ry7D6BOX*;^pGy;b!Ax<K$om zo$DzmXv-$1&1h;Ys%#3n_Ya0yK_a58%BIF(j5O%Nssx>pHwA5TXJdr)>e(SpX=U(| z7f6#^iH#Lp4k#;wjQ|-1T7?ZN8W}+xWm992z2N%>p|=i#Y&SMF7G*Y_V*2k<>%Tp% z|Ms-}TRSC=Im^`a&onbLMt3_WCp!>kG?L(F7vK_-ur>R4CdAZSTvSZXR4?_lf|8N~ z2s5fHhzn}V{tGcP18M%}q#_|CEcwp}!u^wA7ROW(Z~FHg$cA67OzX|2#F>FX+!V98 z{VgpmkDUSooty&#uCf|2F$qc@Ib@{EsHmVRp}@kzDy^ih)30l6tgCBm%r77yzpu5m z)y!K|NI>M@r<RtMf9s~io0`T?F$Dwg_^jst6y|+QKNy(7rIoXTgCHX#gAg<5G$|%8 zCPrq^oi+^342+;-wV7F%TUZ&HSXh`sK|4u6JH?q;{8?B)vC1OPBCo2;#wMoC$;=9> z^}wYrs8=HnYr}$yU{U0uF~-k~r~jG$Gh=)uqNuGM6QC8Lq@idhEiWgfsHVWHAuFw^ zDJ`qP^y8n|KQqQt)#8$}Qc8A)&R#Mi;eui^;<8Foa^~u?ZOZcU%Bpgp>rVfJ*QGFO zfz~T<K<?`E-T;|10L_yw2AxyM1e&7)?FIeDl)&_t!I;68A=DvAnvsP`ijj?l$%_*- zrq9H}$OJlnpM{N;B^_~(loM!>6x<87WcD#NVPvqjGO;za)zj5blb4kc<KqF{pUz;+ zXv_mWmjyg73R<oP-6{`CWAJ@0q9UN`37izw)WM6hAQhIFxSATHLSB`Sn*$@Gb!Du3 zpaP$u0FM;Au#lmYp$4CxMMNwkW9?Mu;0SGPgWOo&2&TWYT0FU>`7@Wq83*cW`bvrk zaj@EP@S3PA1?p-!O`gIn%f)07XJsGep`)g1t<0F752~j@gHq;97Z{`%)_ZTz0JW*O z7#SHPM7f!n7(u5b@Nh9QGQ+r$kje@)O9?rM27J~n=#VAIE_j3l{7g@Xp$G{i9iY`= zq72Z3F~NIe;F1oakOOZ}BpH1oBO@cX2}!7^v2aLeGuknkgOioGDEJsEK4x~%CIDkb zNl|@W0Z}6j0Wl69K|UE_ZZ#ck!RVJsjH!lsNpfmxEG%x!LW&}uF-dy=zB39k?gWja za{vFvYzaQ!MTfz~!BLcvfrX2ajhzW}aTXf`J6jzqXk9%^EGHuii?uiCx?9EsP+Qj$ zw3AOmO<74^RzjRXj6qCPSyhk=<UG)kH=rey&|^42`9ay#oK+Ft2muvQ(9RySWwn%S za%_$gi*j~MvXV@v8<Y6ICJ7a5BLjm_6CEQfX(kCz>uT%L;;5+NQtKKkHDyoJ8tYhh zFN?@XI~R`_>ng||OJ*(bdJ_ZCo>hi2#w3ij8=(vg%weFs0oqN-z|K&{SPdTYWBB(T zd?vIS=uBt^b|yE5SzvL!fA1L|!0+Q`V{!wZ_rk<r@$WsO=>NksI=_A?`22cD2LsUg z^^)>3|K3{|8CqHx8e162NlDAfN=wNxFoDiuW>#hT0d6}6ZWHGRT`CBjvX^3DVrl^` z>H@VH8N0l}<B^c7?4=!~K#2=<Jv*jk<aQMeQ8i^&UP*06$i5=bB_iPAels&uW6<&g z#5qQwV~oywP0lWu<l!;7AgD%DODvw9+tOb5@7cnts{FjF>O$}qEy$tG=7!upCfwF3 z;-NL5O<HZUW`WWjXb(&qQx=0bs7LIe!^_CRC<>a`1E2T=cO&>NL2wr7X7Ewb6jfD% zx)55XfKK0lyARcY>g~nu`3|imCQ%ByVsY$zmR15n|FS{HE%^imd4blLI@U(EPEb+g z^)upjjTKe!)q|}xWnf?g-7Cdx1im{wa2ppR6R2elS)TwpY_0{gIh~2A2^75Gu<Qn% z3@#4xS2HW<Y%mlV$O&??46@3?nj&nx655QSU^nwIu?s@N8Z;~qo;EQv6=Z5Kl#ONQ zQ1!62sEF_Ei;7Qh^jBdzmB{XE&8;73&i(JASGg<rP9%e{1pQ!B#`EAgQ_vZ#N0_o1 zWEmp2OL4G*yAqJa1`=$HtW2!UpbZnPAO|zVGcqzTfR}X0phz(=G=t<}9*T4TUC$xQ zAS<jStRe=wjDQie{|s@n3FyQhPzf$*4Dt`tUUm)@cN-607O80Cq~u7@m5m0{OxfJ} zA(m|alH9e_W78Pp{;g<8iDMMA=J2%w^@AAybu;<>cVISU5CQEO7GPv#;%8$5ol*jd zgBAuRMn>>u79ck<G5V{hi7@kuYcq?mv9p7g-axAqQ&2iRpr_1g#;&5RD#I(yA*5>K z#B@tdlfyKWO<Y_;fSJ*RO&6T6L2K$hfXfQV`8m!EZ5U+*WDooXCN)Oz9(V?4h6fmG zK<SqeT%LgTaIrBsL+_9Ttr^q>iG%kGu`@V>?we*{WRU#-o4F1=Z?Ep4qAJ0~jOC;Q z&}LNzHDO6v5zyWlaWyq2bz?bZabq(xb73_#C|k(fn2m{DS&vDb`JH*J4QnimqMoq? zE4w&<A}0@1EVF`vr3{OWCsQ0tQgncVovA=OYy2BVrlyz;3p<TveKZ-_O>zuE)-IW7 zQO;<&@9e++i6*U`*8iFr7{U7m{xV52C^Kj{sLG2Av4ijE1#LoOV$y(Z?Pp+MP-ak; z5fKpvIg%0N7Bw|>u!D@{n81!T2RjzRX8Ow>6&56CBU~1s<!8(i&Z=oH!^|ne>&3&% z6v3oqBFkdt$-yK!>EDlflV<Br&Z`e+#INZyk}{Q^YM5mhxM+q`*xN1!Ch*$KeDEG{ z83s!SGiF9ca7URTm4TIkgPoNlm4S%~yi=7ej+2p%O`Xk$fdP8@i4f@Q6WHk|h}F=r z4ae}^&WmQwj6QWLF0<08syjD1E+i&3gh|3DEzPIK40ITakCU?tX#X$7Ev`&041x?& z3=R&qoQ!M?Y|RWzT#W1-Ozf#F;01G_0b20lRpvMb@G%y`LZH(=grtO}7{H4olobU9 zL2FkbH(|qe9e|t%U%GmA<;v+d(@WlzmOksBXzlCH)RN;lWx97H<9W}Ve|f8+8!Z?a zK>K`anXWLXGAw~)c_AT2HfCW)7B(eDPDW)$22K_)X$LexCQcUE`I$=WptTf?oS<#N zY;5pt!JM27@l2rWGQs-*w2%~mHwCk?fhQMqLCag!y%|8NLF?H;`+Y%+)D`4Fvv#0; z&ai7i8B`fnp^MZ}xBfzAl);NH#6S%Lb5S-nrj@x9yqK3nMJ?wFo}6KkqOPLkZ<t-j z#~Ac)4NGmgeu$<<7+2`*^nc(zz;WIFQX)PA(iMe%b=?9ye*Ao(@+0*BH>Sf(N(?F( z;iAaM$*6=LE)YQi;i3WYDXwq<FYyP53wWa>mT-{=Uyq0qE-H*Fh;R{A7Bm)xY>7q= z7w7^5CL_0eXO_;0h%Qc-9A`}*X(=gtSzkYPMuva?IcMrP%E~x!ndF6omNo~a8wm1v zaP#>Fc&&phc?Z=`pms0hd;?L?NEQPdXuSj*V;VanE329}3lnS?ALQ~E@B$tV&;oEq zWoFQNUu9-xa4o<Nx<-t#kx?tY!!5|IGnP?Hn}uJ9LwTV(w-|V?&FkMbMz4R{m`+6q z=otw|B+7t}kOo~4&%nTB4qhWIjA6e9lKp}L@Qr<7`-PR&!9$De%EIExZ0sQW8H1lh zC7b%2Cq_NCVBr&$ZIP7#?frTE`t@rj32QwgFHc)g9RofafO#Rb>@WfioO6H<c3|LO zOy%ZeVrN$aZM$NIZugS}ZEq9?`x`{?u*+&QBK$543Ik(7W6&{!U^l2SRWNEMwYvnm zb|iEki;8+)r_C<Lr#xGQ2NDdv|2Bh8OafuhUUf#j2ss<&s04W{P+Wl8q-@~*l(L|+ z4!Ian-38tb26LB`Bm-z)CCE)640abHOw6In-p$38K_jl9$YD}`9GPP3Z;}#~+8Y+O zHr|4TO@v#zNrqbp6iDyEfJx%P18ZSRX?u4WBL*f0ZUzRXvrMNLWEm6~Y#pp*7@0WO z6&M*fm_Yl~L2IxWn9><IIM`!B%L>)JL4gR`W5B>5FUKIuAS)swC@3N##KjIeyq{f; zNnBi6U5^PAVoD%KDT9t(Q8#5(6ldx=<K&|w=oI6`CvR>PWn?PH=a}FmsO{}|g7MP7 zS(}+oIelQ!3$(a<Ti-<V-&)3CQ4{^!cg+L!Sw1)gUWddf8v_GV1(O8Wtu_vpGK@@Y ztP0Xh%#3VIUd)W35*f4v1a!U;C}kt3EU04z1x3WcDN7XLRM2e$Xil|QWM-qpZy#aL zE3K^-sHr8z>kw|wuViDkh_U(Kn=U2^<F%~n4jM}qDX9tm{w<)cv}lQjy*k@kV~^>e ztOh!lg84GjDF!75Rfe6Aogmzbj7;1ds*DWWppGVt$H~nEDvv=MJQO$?89=9mFoMFH zo0}t+hl`1WL(Lm>odP2$#HGDA=mtbMs4{ReFmZ-55K!!(#sE4^l?`MXCj%QJCtE55 zHd8_SKNuKPlo^y5loaFz1%)B;$qUK?NP#4%EC`KHGjmYn8Vf3dW0iU0X(u0TLFY(k zekC)*Xd^QPUdK2$Nx4f=QH;??7%%;s4T{*0EP4SJcW)b-2>n~f7$jz*d;4LaG^7xJ z;}m!U9A=<=;mst$pv<7gP~pI@#K^?OuExm0#l*<S0b4dF&j8CT=?q+4?6KgSjFe-f z9n_c^897)v7+LEWI6#dAR?sDam<l5uL>L%URX~jzK~VYyr3-NGLh>>qU6`3cvl`UT z+>6X?6a`?(Lrq5-lsq^^xTl7NG4d~jC6RTk>h>B-7AdL={Q4!JrnG2@ga*$CCW-rN zj6J3>Ffz#f*J2W34rK^s$aTo_WoBYz2=d}$Vc}qOV`S$LU}R%gWn^Jy^>SzAVDwaD zWN~NUU}R_HV6Wo@RnDLdzo1oJY^>~TX`nSv%q)qZ!}#JEn3(iHXW{$%xj5O`SX-JJ z>uD&<N{Df=F@!RPf+`$FBQbGN$f6VQ1OjxtkR5z;h_MlDkO4Hx0NTk9>JgelhPKdV z?m-PcQ_w|tc1(;*1f)3FggM1c#Uo-8{i0HurkY!bC>iP4St#ik@o||MDwx>nxcVxj zRwPAMq@*QfW(GLe#%bxOhM7v*i#kZyND6BiF^94;Su(L`De}ZQdxr6_@PxU?<+C#J zO9_a{Ff(&=gmMTnGbvju+qkkYJG!`9!_LZ*RArZQ6yp^zl@iwj4T^!zc(!BQ%QS-_ zgdx)*%?A{=fu3%hEUX-iu8iy){ETeuD&W9X#TTyW*uvG%*V)n5+RDPjNJm{sRzi%O zl_7*N1QD*F@jqy=$}xc!Ho$@v)M<qTyRs5w)eGTJtrU>t;1v-!6ti}<&{r^5%C9mp z7F5zRja5}t<K)&6SI#iEc9K#Ga`TAr^>YKCqoD4gAun&GC~79`AYmdStYyqJgO$mW zRZW)9*#vyFg1m`_b0i}ppE$pmI4d`&7Z*3HvZ<`1xiTZ8hLN5&?63u10aht%VbC3h z;ySY6J{0uM7bZ5w5-{KYzW~!7rteH_j8nkls-QEiAa_NHG00*)*IpOAu?^g@*JJRJ z5Em4XmJ*khkQEUY5EB$rQ|17j+X3ktgHj!+e<!A@#Kx|urUpCN{(|@9Z1{~)|8^7< zaWY=w%r7V^Wc#PfhCKcdy>w$^QBmXHeI1pRpaoKpbNAJml)z_yU_W<XAH{tb=k6;( z-3N_7P)`Ew+<n;SgGYh=PcJWaMhkXd4_`0Vf5%yT;X@CO)kT5+{(=9}qr$?XK<!mf z;Wv}%0)r$&kOQ|EBLkB-H)sOO3o@1{1lmEy6c0IP4RV&2w1XJ9+XIpT56$X=wic^{ zF4W;?WDpSo?dSk4I|Cgd!>Gi@&a4bM2h7aO+#I|B4V3+v(v?-j7N!6DAGcUgf|Em% zKR{gF(m+U&hev{`&B5&-1JkL0=7xT1>Jf&2-6J&EnY~y*!^og{Pw;*@Sq4dlG)RTS z4QfmZf-dI;*KDBqODHcAqCf~VPa4k*+T{-37N-un{YZ=fbjS%<2ILW#M5F^hBLgoF zHy1lA+z;Ra3zV^#m6_ounwi@%F@E3?;p7z+m*K50JswlfFT%vaBEan?sHo2*%fjTs zs-g9-ib>+%TrGP(QFrBACRX6HAi&`b8Vg`b0gW4S_cO&o`uRxv#XxE#LH&6q&{<OK z-2F_N&@?W<vY+WH1L!_9GX_@&Cq+gk7BfZ$CVfVB20cbLcF;aoX3)3=qb~T`0kF3q zDIT<*8?@|}O^eM(RasI9bW0j^&or!@1*drA{nDy%?+P0;vw@UBXMD`fndZ8-r=+(# zIkjh`w7LHMmztZGoRpWB%A^@v&M(f+!Ya*|9s5)!%2!f_ms?&?&r(nZX?PBPcG67k ze`nP_lq3T+7>)kU^NC_*c4J~O(RPQ-A(;OcU~y+sVo(F0U(C)B!{iAH8V1|{N11*w zvoJ_87=hLd=&Ca@Gb(~s+<Gy9Zu((lPG?|ZfZa&S!U#Hno{>RYQ(l&jhe3)_3Y0Qg zm7r4q&|z(GX$iU`9J1vdGKZ}W@iTZ3nQ^v^Dr<DDLw_f$s*JP>dw8w0Q%wZBY9fb< zl!OXrOl)inhl-?>3P*H&ytSk(U(&3kNe4w`B_w3|5@#eO%}nH%m249i78VzoTv9w) zSX@LzOk`ql$z)KQ-2DG(rWht41~CR*20aID1t}&bMr}1F2GDtPjG(KnnbMI~dV&tM z@YmAPQUM>{A;QKEju>#E4)u(f7`qARzGcud1hC`5Q$pfqW=t^!$sFb~a;)*Cg()m@ zGExex@g>pLcI>iJQgUn#R#uK|vQkDo_EwC%CB1?MV$uRVrNuphQlg^Lf;~lnDFPyb zf};E>!NF<#B7!RXp!KJ=|GzOGW#MEHWKd*?V5oDb78YV+XY$fz;$ZjGW8&hlwPNDr z3TI^FWc6ZTWd^NUtz+Qg;N;-q1l@hX%*w!=&cMje!o<YR$dnFRJj5OkTJops&CSTk z$rjHiz{JL;$L6D~#J~_1;^zapF4@M~!pz7(TT>}QIYL$%G_s+jB%~||I?4oc(Iw=X z2T&tJRNNG_830tCL#8L0p|u~VK4b@}fKCaSn;Jt_#X^VoAjtr<A{2DCHydMst*M%4 zkTDyFMTCotiKexLq?DM9qRqnC8e6-P05xwpB{37(ps2J|d2`7qNlS&)wCEsN6EP(@ zZ?%9DJKLI=40m_tetuIkSy?-28O!-9!qU8)yh6gl$};Mfe}2TT%+FmIDIw}CAUd<9 zeZGY7_3I+y^V?fyiV8T3N<=Qq&0iT0T7%BaVD<kSvmbLIgCK(fLnuRsL#w0&6FZZ; z783`%n>G^{hm|=KCl`xXFe4|UrvM{bi1RZtFhGNxg%K^p^<g0{2nlf|MPVUEhCqLB zPf%0N(!$hOUspp-F;pp3NI_VEkC%rFyqH~(QBVkUQnis7QmBKL;fNc7LXRC5{><P7 zb;JcbcqRvwfEnA=JOho{IV>ZbWlS7w(q$BFt*j&@(zC0JQj{zt<s>vkZ0&qqluTqI zWXzOYyzOm;wZ!EmEtOJ=YO*W>rDXz`3uR^OWn?V*O--|vWHl^#l|^KDIeCQC{(R_f z>6j$Q=giHUl^T~LAv<@DtYl7HY8EfIGoRq3j+TB6B_+^N8~^`9#!;Dznbep9KxH=j z6^4zFG8^gsY0$YRf0+(3sWAmIFfg*QUrA<U;MmB>xPcM0rHPTj=Dz?_8q*a9DF!PC zb5NBf0I9MVK&QNd2JXOPTA(Rj7Cq32xEAQRe$Ztc;G-6#7^T=Cp$r|L0q<`!GZ$1g zg(hgmITo3ks!G8|WgTU$k~$($H8b3T=Q3Rp6Y&)gpVihpi<SM~-e>VkvvZclf$Dwp z{{oDsn3NbKak&RPmW0bal8lnL-2>Xhz-X!AFC``AEE^mc6ri9Z5>emgTnfJVf>R(V zGc$pQ^WUy#E&VAqmJEyx#{d5@=`xit2s5y4<^t_SV-#l>XIBSfb#rxdaS&$QZynXE z)Sc3!*b`|J*`wH-+^f{XRH8IH&@ymMkY(U3#W{hNL2Co8f*2SWI2c6!r!b#n+QGof zAkCo3V9wym5X_Lskk4=vyjS_00%*#Wg^7`+PKldSk)4&5jfahur%pv!P??{VmrsO` zSENo&T2fV<Ra8tyOjM>$U7kr+P8PJG57azL=U@a)S+cUQr3*0f2r=^U^6;fgFp5Yq ziiwJdr8CIL$;pH>$jHdWGswxv`6nfXgt)m`SZHa<$nfzoFeK$C<>zK+W~8NrB!(o$ z$3{m*gt-N~1qb^3`gnO*xLUY6JKEdXSZSGSnVT9L8tCcBXv%1+t12rg$ni<@NrQF? z2?>DChEoz!(qI<{Z>?s8^qrK!r5Zc9$QJ``Lk2Zn6j9{ZQFy3wtVGK(HZvI+8JIGw zGpkC<DKLLS;r(5K!mUB!F&#qT{`E%TGV!5s{~bW#GDT{em}<%J^T~GW7(*B^`W=h` zqrboyFuDWA0FCE>(ufQ53Z@(2eb`c<lj|8w8SEI`8N$J7#7B^kfzjMlM_WT(Szb<B zTuhjkho70j#@fgbbk~y?3usCUwBH?cfin|xDCl5I(4ItQCSQAd1_pa~dv_OS$QEvP z$eq&gZQQJ4V&d%TYHI4Nph-@3b2BrLh$y?7n!2hOxPPo}$}SF41QHPkoxiAVW(HQQ zY-VQ8B*G=k>cYyUDERM|xQUnnhln~qQ-_jDfUE(dQs`e%%{UcywFot)4{8x=nsF*d z9Kss>iejc>|FS^x>PjjBjOrlW`dq@SOgEsav!UA6IY3GcID|Dm!fes!QWONKb$P<5 z6bjNVD+9JuQQX84WRYf^3b<XC_}_(@fq6CqFM}$BkAtT?BL^F3#Ugku3lkS30~-@V zIs*qcBPR!EBIK}k&?PeJEIxdEj0}9Le4s6Gic*pi;sX4j>xWpF8F(3ac|hf!k{WCQ ztuY&$usP@kATx7iMrF`+An0&PMq@!^X2$xY0M<ZOJyTsX)?l`XV&7n97ABT|r70oI z%%GE~laoA{nZ12Mt8Kk~|2XbpY?1Zxmi)V(>D0e+MPC<Drhvb#|GqMS&Mb0g>IARx zRbudU@RAi}BH$4XaBCap5hXtGCQ$HZMWQ?c^#|y*Kx1Y`PZVEx*n$rXe3TQ+!o(<_ z6JyU52U#%e?fd8DPDWc1BYpmV_DmB0PAGWGF&_M9^zSb?F2oram_TR33o}SF*g06U zGBSV;hhkt%h0hs*rmWOJN1ecCi$p~j7$n3*q(!A6!@jDDsIx`jfd$YmOH*T0VbDHH zQxmn_OO{0C)R{K*9QE?rla#hKf$3C~Uz=%+RZ>2al3&!n=70ZNT`Zt;X|hZ|7(i#P z*g053=C820ih+Xz<{tEuS5%PQBM52F!JPwLQMPu<lxg|d86|Ige4h19u<>zc`cdxu z?;q%-FeW?a^1r_zGg#p9dGOuX{0y?7J_KlG91AlG8|YM2(0OhQ%%CH*7#NwsHzR_w zHE5;}JP@j3q$sEkI<|{Zgbh?hK{lQm8;OBdxq)gb&~TNqGLxZ^rKPdEfpd7&k?zKS zUH+mff=1?!GIG1(8Gl%&$a`zY@`ARR=KW-1a?%PGu+;7Z^#!13`Y}i|=rU9}h-#>- zsq!+jv9d^sGcmAAf==;+jYi6{GqSKi`sUzs&A@xW81z8BaV^l&07V8SCdgqv;BGqd ziAPX1kq+XrGNAJ`WprhAg#<vmP8p;br8%I7Iw>1KZrcLiF9->4uz#7A*g%^Tjg4TQ zRbvdc3lwK#W{&XSWs&f6NUqe=G&iwVv<Pxxbc_%avNE?77jx&*Q&7_4xx>uiscg{I z9a5^~tr^0@_$Ve$FgcseThm`E$O3egDQIsk0|Vo4@VU~u4qB|BSy#}0QczzQcF6-| zdXs?xR0V>jCIq2(JSd79i-N|7K_^Qy{{DC1+_@+(FQ!ugpZxwEW3=*PbONti;9y{2 zoC`jO6}$Q1(=EYQC7_$H3^HF-8N5%Maqh<zD<XV+m?XRwy1abp@)~S*;(s=#bf!}b z3Jg^aLR{db<BSXvjBJeJjI3-d&`a}_8CcjEL3>8iLB~WR&ej1fcLPu4X@RcYRzRp? zV_;=tO-5A=8gUV2WRQ^(73SmN1ns9_VNhUH0L30?+y!)Qq^P1OxH^Zfh=catO-<Ao zMMcc{qZsG^+bwJ@y<o9RrLUg7th}94RBQvI6)V%fvrMM~elfGHnUXufjfW?Iho`!t zybA2U(Er?wKbRyK6d2qcTtLODEF&w6AR{xY03-MuYDNYY&=y6|xuxI>IlxI%9n_)) zEt_Z30^iJ`z@Q+kqN=J4jWuN)t^~DQM3n^@7kw2}5~^>vO0rS2loYd4ws#JV5Ks~X zovk~UiKTsVVx<K?pC7MaLRw}rGs|Np3DDUK|6Q0%!FydT985(7`M5b4*%&}aGBYwU zws5esF@vTaK_z7z3o{e!<VH~jQP4@Zf`USvpa~^L@Mcf&bpnjajL?f9n7#kKeh?pK z1ikh_9(EZ7=x%|35B`1G1G;DcjFE1H0JS$585sY&GxLD&RKw{e@cF4sc-+J+4%&dK z3_9Bt<qY2SNudU)r|_Qs_ircYv{x`jJ%{)Ie+ISxDxf<lnA8|S3pUxA;}}+h$5j>o ztANhuWm03j06Ob|IgX(j9Pf$$U6}frK<8T<I_U9oFfucMw>>j4wt%*1us{xViUSQ4 zLJq+Moop>6C@2IzqY^0~jRhH*V*Z`_n-gXYxtf9L)W4<w9zw$n6o`!AaY@iQo^s%G z_Y58MxH*`aS(rdaS3?fC0u^iwEG!Ihpe7jjG;PpH+CoBtLV_UsSWUs<V=M@|*UVUu z@s#$bh=`{NPq#<y+64*?(D}EFEdTzU`S%CnH|X6G!l2O?(4KBi4rV3}&}qn^VHZ#x z09weT<_)^6Tb<EISV&k<7<|Z|s<Np%=s+q#(C~q|F{3D>vO1%wt!-44t?j|Ie>WLT zb58cma``t6<S*x?Nmu@DQ~I~)A*lZaTC)Q>%U2k5@0gGv4>t!Z3nK>;E5wta{q(7j zfl1JDUXVk#Ky$IeLc)+B6*V_z7Zq1l7ezRMQ8hQ=?1Qu_2aAXZ3&!`sHP6j{cg8HS z|MvmpVTajZzw$!;Dg?Tbg`bC$nUxuI`w0UFI}>PR0KAd}be|F{t2!&_Pz@mlNRAK` z1Z4?fQ_!kx&{-Oc#-L63g35xtAyIL0kQ+8!K(}o$sriS7`fp>5`nUAoL{L6pQUm!H zbj}$oxc;|wu;PX;7GneLJ7HvEU`*v;WM^lN1sxBj4qDrx;SFXoLtP*UI)EDL0#FGI zide`w)S$I1YqxEC3OVE0$A{@hl;gkcpvZ+DbsXymI&+JWft`VYX$#XS1|HB!{oE{| z16&!sKsUF>f)5i`Lt1JCI*C+JNQjMHLYtEbocqDm3DdHFrx?LrT=I|68k}q){;LWA z-6{fI%ajd1`&8RO1Je%V<xEI+z>d@g9Yrh56!G*&>gTZ4jEv8iB>w&V_ZpO5883K% z4$%h3A1EK*1mEpo;GhdX3!jaHk)4e_5!3}y^9F6HhGYuVqg+`{Ax8-tLywGQYL5Ij zF)E5NKQe639>i*azit1%K+3Do|L#oX;4@=!*abiLl7Rt!aStS#SWQ8@`9RA`6iq>g z(=sUp{JR?w!KfVJzjNpN_n`BUp-olLeH9E0%<8cEo&j`TBO@zlyBFjr95rut_}x;d z^)bj`ML|f7uPB%p#hCYRNz}hdkVOvxf7?KQ0;N4rUb_sd?=j5Rz-PWF=)5w}IkbwR zp%IMAjLfSe{@n$+-s7La`}ZKX|7T<V1D<OycMxJ^WM+_NWMSrKWMTo`?*psvLER(J z5wM^e%h+Q<X&scsSXjVm9XwtSZLvX4iUkc{GcqwIGqAFvs0M9!2VK>t#GoW7C}g6l zYQzburUbFq@u1oh)Cdq%7Gz2gHkX{f$hq84-%d{6PAM|BG)L5uKl0y}D5g{Yb}%!q znVQ}2&dVLZ&0AAeQOV5m?;KO*-*%=`uynx9>;#@0_jGUr`B8?Eg;{`+iG`n$k%`3% zG&jKl8pnk>SHl~0sUM2xAS?I;1%*NL4q#V9>U_``A$a`S6ub({6nr2AyC@`~GO-IN z3c3|KnMPZvn2C#-C|KGA1oJ8LM*RC1!6fmViN&He6}j$bVSNZXy_!h^yk7Y_(*vff z48{!h41NyYvWzUua*S*&wwg?=?3^r2450Q30~aGB6Pp(U8v{El8$0MwK1K${WCj)% zaD!PFbVMk)(W1xXqpGf=s;Z)*2AeWr2RRqCW(+dMj+m4~9-o75i!(L?56D9g6)-bn zI-_i^z^@{%Cda2Ctna5JX|Iqm(QD>H1uG#59wYIR^oA^PF%4aVU=!nDqiB6yJv}`Y z12aZ%$D9BOb`EZTHa017PR^)B+3QbovHP%a&FP%j!)n;&9hPfsm=_n6nB?zXuBK28 ziaXHVrjMConUole80;9PI!J>?9$6Tf87&!^*p+0NSeP^!*;terS=rdUAjb-5GB9&8 zvNM5h%>#{0f^Jy^j|76}j`TpQyul4rJx~Kx4WX8Wft7_d89bPYriINX(m~q9n32KQ z&cqIK){BG~_>>nTMk6jz=N@*v4QMDHyc7>SmjUf?U=3$hq>YA*in5w~!dxmM0rv84 zmVy$@vMN!|j-i(7Typ$!(mcw7sxGpkMymd~7G;cFO3Esd3L5fEN*pZi%xrn7mQlv6 zjPemyF<~KbE{W1C9PDna%%VaZJYF^44YT)Kn;LqHig=qCTZ7w1w*OU_BAKo*se$fI zVqj;EW8?*koBvl~+|Q)Mq{aX`cOBH0+6OMHIsdybDT2>p(gGc6%*M#d!kP%G&td&Z z==v}CsxxTgMG#tc3NkuH-Di@xAGT)?Q)OV_-|OIlnUO){zdPeG@On0oxs0F{_KBdz z0&6Vj=mw<T3-YB$pbL4yO-DgxQ^sTK{KEp)GD&#;s{*wW&wGOX0csALf%fcxPR;|( zwf+}i`~xokWgVpWIhdG1C+2}RVt`wzS`0ptLITX};-FL15i_I0#>|Xb5tm{L_+?mG z*`x&WV=jGo$0YUdmPVwcWP~Q8+TUlOG8t+Yg8&1#eaFho2;PUv$jZpT#>kKcYDlVi zg9eGft7;hp7z7|~01kF3ZScunrp%zjSeQZ00nv9;ro2nqxhwJA<jJf2B^Y=9TgVvy z&s)ZS6(|odGB7~>Aqu)nTmaPO0PT1M-A~HEn8wb=#L5buD24P*KnK`>yObcC7@0wB z9dLgS$%l-8F1EEtbaq^f$rF@fXW@_*$_A}(b6&gFnMvZ`T|GZV#Xx;Vd2kwF`R~G% z0j{t09dvj&*_c^C4Os>jSYiOJAV#!e`5E}Z%`Ip`V1_jDg^ihojRl#6jP@Rge|s-w z{f79vyFgX8*}qeaC5&PJUNB1hTl4SMKhS*%LjT>EB*Afp%Rc002%3HB?4WBs#LbOC zy$r^~8k43ZAKIDH)tS7r-*4BhYu6Zs7}-vp`uFPusNu}W!1>>W*&XaRLkB$$Ms@~v z@Zqyev7p^*kQxr@)Oz&Bh$1wZgHBjC7G(PL_sLl%?k9{XQJ~8X!O0zTr4=~IGl0`P z(;=|GAa=2^2SIWY$Sz2QL%dx%|D0wq&RfeU5)rs_C*yff&wtgR)BeH7=z;G3`tQQD zp6L{WIB1Ww7$YkSJ0mkIlNST%zyelgXg!e#Zk4EkTC0#Ak2r(4vM}hvA#lP0ADgc% z2%bTPZ?!NNWQq(6i$b~(40LlBsPBV$Eg0zDf&Xqy@!)+@77nJOc-;X`zz}zcF^DOl zyTcUX4$v+r(4t;bCISEO0PqzA5uob`KqmnI`?Cvj3jz2_0&v<5U|;~>fhNgd?O-7x z%EZFT#>~XT!sNvOTBOec-mwSDO{wf`OyK3&u<}fjK~hjySWpzwzZV1r1L*z-B{gVB zn1Xh1fC3|0$xY2Rza+}R(^lPG0lbJ;nOBr`+N7vx&>d-(Rx6jX2=g$4j=lwj2Ll5W z2a^PY6oZX}rKA`W3o9pR|2i%QflDb!Ls*JIN>E5x815j@d0V2&rl6Jwc=xI}#6_k| z91$`W3f3%~K@k!0)^ZkdpnUyaScaprh%wy#)R9Q$iQQ~cBB0|BL2W;1UrHFXkA#Vl znNbk5X$P?g0dx--sOPB8gt#M4*cjSe1KpGeTII$rsGJyOm2CmPB97_QzuTZo;{H8m z6aZZk_iq{K+;C7ER+8xl6B`5Qj725}>HpuDMVYQLC^Kj=bU1MFFfuXnGJ+0?g6s~| zU|?luV`DAg0A0Mr$i&8&!NthV&JfSZ$iM)eX#_WM^q74>hjp{Ev$3<X)e%%1=^(4B z!pNYZuA-%?r6?~gB`Pe)54y1!beTAG5gO=3EKr>dJ9SSTdO`sBQfy;mGc$3}k}4B5 z#&=mw)_;GoS5-Ra>1pQ$%wNVOVeZDk=FQA*CMdk9J+YL7aak<W)u_4Y#?>tn0zm?z zn`hgbiYW1L$O#(GUlLGLUf9II#31(n8&evSB01pzZr2bQ4k&6-!a+e!N>YS~Z~!-I z%%Q<x#{>(84!2~}e-oI(0<3(rGy}{_x>+1uI6x=i8*_0vCR^Egu`vocFe%#PdYC3g z3JdxO3AWWUnwbm9bF<3`8v3Q^d-!>~g3p8or3n{snowiVW0>l|4N4QjyiABhq07L= z!OqTBz`(-H(!$Be&dLZ{1dxH)Z;O^P^g!x4*x2ic(-7$(uc6M!psl5@r=h2!Bqu8& z208*0oIunV)xZ-uMxY^OMR)=Ml?rNVxY7t}B2iCt4sY(_M5GddrI1vj7Qu8ia&D>_ zIGOMXGi}+<x4s88srckrgVTyTIIXBM=rFW9aLY5YGAJ-Gv9U6FK{AaF10x3$6Jr4b zI~#ioCnFPRw+|CT1{Wg-2RNC4htMGnVKyIW2VIbI4o0RrqSQw^2&=1UX{za{>j;V} zi72Uv3Ujl|XtS!RsiPzfaAyuB7qN>fgKm>iG*M$rippY!rw@U~NTkH0?5-200!c0` zd`<a?G*X-gPdtKrOdFXdK@!aW{|unrXj<U*o({PE2U;Bx0=|cJJ!qW+lNv)m#yST^ z2GG4>pu4F+djQ#()FL2lEYP@j3;6!;90wtJMrH;nMi$WNQ7k;*J|g67C{U9K+z$pf zy3|0u36x%<w1W)1GYQ&}$C!+y5Y+nxo$IX3pe!h?s;a68u4kdg4uDE>#PBw>TonYB zwdUqbvH#ABE?(qO<Ev*UCvUG2lImFOscaz{6(w#ad6DVVzfDW~^ZH%E<J?sh0qI5@ z?EmgDo%%Ol)=u^%sI40MpPPw~NrFM1!Pdb_l97o`gprwvgOQP$9W;m!>OV3uvoWQE zCNm+8Z_xY-c-fs6gO8vPsMD*=4!U0xvbq%EPEZ#ey!Xc3m|c#EiO)9GO2u4U%uLb7 zFE&ERKqNf;RpJBB0z28n3QK;_6)Oqp>GABW*O?^#{CUG@UJe=OW;()jib0+s$$?9l zk(EJ+kqMljMFS!nWWm)qV<H1HGg~YJ8yn<q%y?*>B<-MxDG$D3g_RYu@B<X&T%c=h zK_~5iJYdYM3|fDW<8s?Xk95B%oEO{%{QI&8*Cn@%4DA2inLL;z7(^K6K=zYy^MM8i zy?7a!7(JyOxIqV1GD3Kf5Ct+I-v`3H2AYCpU|@p#4YGa}JpjP75eP*X0RU-6fja*1 z0El$p5>f^=>jc122oC{e(D4_b#*`xCn;3^k+lcwRdOnu2f;{|Y4uXu%UjP2?WIVs} zTpXJ-^V83WJkrc`ia~-Q#es{Hk&zj4t1c{Wurh#_$AKDCETHjpW@hM(Ees5xE44s* z1F8blHDhD|<qeoZW}iq0P~MPWkO19ysj33b8_=D;u=FOV2p+3e6l7|4DfiR2m6x|u zj!u9K0WzKXTa(x4!o%aw!&6$t$O+jU!KepLAfWWG!6d;T0cr;#+|2-W4!9wVneZ7H zK-YQTb`JQ|OwgepOd8+;9x+i<c}v@W_aY(~m6#;{F(j6m@$>p|3q@pH2agxR!q5eL zzA-;!Cl>=V0~<4FW{{DAF_9gzpNtVaodfQ}2?`2;Mr>3eu?F+MF;jDrXSyG3^b?dY zK|_U*aYN9ZbN}6$TEKk`(6}cfXuld8Xssg)GfN_9a8<*bgPjRBK#tn2F%|^*2(%hO z*&Ni12MroV#5hFRL5B@NgPuFzzlZoG;J*vFeJu{!i3Mukv%&irOrU-SxCl%HjirI7 zSD;r7L-Qi&ns`BDXu}?~4gx%MB52GM86Fml)We9{!^m?L)Sd)2s6p*X$oz`ee>d=* zW@4Z|4#;jq9|y^9Sk%HA_Go<z@D4Dj6Oj8BVZO+Hi@z^+F|sTL-*ATLTY%Pzbc65T z)_2h1W(3`h=mp*J02*Nc4f?Xe_MtIIGf0Edk)SvzSt~Lt%P~Rj^)m*Y`2{YLOw2$x z{xQyZ&BDyg7~Fc7<$g<|M}~hS6EhRbJEkHjS7)(*ZcL~CZfEiYjc@N^JRsrhDEhY_ zn!eqcJ}^lzh%*>C=!)=gFtf2Rda*OIF)*+(BtlAcW+o=^<Ua!ggE)h@kf5j-WXf3; zYCGz6gT{hP9~`3WQ0^Qo1(yh67?%$IGXmGW=yfq@e54Lk7lY1-U}R@fV^9Rw#Y{+R z4k7oweq&Mt-}lPKqz0PK`u`u4xR~mgdzirIOE9uCWHHD<^dhY>hv)^}N#X*Ut7XXg z4qkH&(#>oNZWDBX-KF>c8?!F>-q00bK4dTZ3MMsh>jC605wO{eNbZ8{QwO;VyiXl8 z0R-|6gZ2M!OiP)rGKe$CgU;h+VFaD##>~J3ig;EQX3+WW3=H7maL8T_*x;+A1n2@| z33*9*Q4#PJ#^Q|PuxV~nXnP4#wW^td?k;9FGBZ~c5ffwdaVap+$@VXp>F3p-ncZZ~ z#LZEelvK&_FH|jpsZByKNI)!RX+i#y=;)>SN|kMY_t%zr=R(H%K=(BL1^Jsr6YOuW z+d*N<bP&`wV#s2!0{fc@DNG@HZZWBW^f0h7WPJdKDX6$+4gu+91h=agvKYF+dKr=Q zLfTcgnAE^$E3h$S1w-_z{r|=!2G+X)V(<UI7<v`KcdCN)g63@57_v@)k^m!v^8as4 zf=r-$+#Mb47#Ueu#Tgk`co><OxxsBRP*aNuG;Ytr0vS034`zVFUk`NB3g~8cAr(~> z=!7Huz&BWZ0=lct)LhY&@$=V)$$gWo(slLoj1m(HGo4?9HsQLzVNFhss}K|m5|{9D zcDD0;9KgWH!1rH(@d6X*G;ye#BpI0*_!ya(d9k|*TqA?sqy=`941)}4?*hzCkahc@ zL3qRjf-=}qTW`A*I60OFTE{6UCR+O@<VRcI{&$W^!r=>xX`-iluC0(@fPhq_Z-}?; zXV4VJ|Njh-GZ?~|pl2{J`Y@b>gf&vy2KB>rnU*p^?q+3Y^kL`)rw@qU9++N+EQU;o zUZgmN=mo_S_+D3rEa>`T@ZKd*95Wa};+P>7tQR?Lf%23(_)a*``c^iEEYN|C|Nn!| zWnsDiIzO5z3G5DtIwdAHrerW5Vs<@~8b}^o7NjyPW#HJz%(P)CXk{{JYyqO@7LyuC z4=CM&&YS%Ip8<U5ICDLd8sjmDyZ%1~>t#gJ3%Q37<R{Re2pdDzYDl`}{{M}sfEg5) zdq8>_eHc2yenKuMAa@%rh23ez=mT1w1G=XPtQQoPV7&}k3@Q-4NMQ-l3o5@rgF|c# zS$C1`1)ZY-*2@^gun31<_?=3OL7=Nc|NjS_(!&%9iU-C6AU88)F&JRzh1>-S^6vvk zxycF1Yl;6|z-yK`88jSJ86acw3=9k`v7q`x4Yd9RvY?2QffLj+0ZlG5ih_ndl}(ie zK}(fFL!+2Z1^m4RY9+(x-P{>xGf6ODH51a{0?&}6m<d`F2{v=~JOA(i*bqOH1mw&j zrk`N{9fA4}(!XOy3Rh4X-3m%)j87o`1KoG<|38EHe=CsxnADg+6H9E&@t~=B21W*s z|5o6&R5A=f4*sAehM;4pnY<V{nVFb5nd;a<r#vuovM{GIFmi!zolao@?T==F4!Ns? zHj9E5N`h|RgI<@x#lglP!zcq9PlDe`X=(}{g9kMk!2|xrq9SZ9!tz`kQUV5HK0b_| zA6KmKwLHeb;>pZr;`Y+zwbw$IrLB&js*Qn>f#tsyQzEz=baQYP72@Y%VPk<gmDvll zlbMB$sg413w+JIc3M9fn6A)n6iHnH{3kvY@f>xx0b`OCn9?<R~aCu{Ds*F5FFDk;u z_y+1Mq`~^#esHHTqK(;4gt<}ZzZH`>cx;ncH)?nj?MCEreUKX$LEWf32|mC-$rJ8I z#5n&sP!KYL7QryNf$w6`chCXV+PsXcETAp#(92!ZAT2h~<dZrpsKYBLC<JME3mZdb zX^cgcg~1`EY&-2h%KG&Q2WQT^p0@Wu!u7d~3mG;4J!h2scisQrI&km=f%@Fgdwm%M zL31{^>;#SbgWKVPLZC}PVRot;i<=vRF3S*CR%cf>SGH(g0Gh;D*w(Q&Wzv-7HEoP$ zk4~L><nrm-wNIcmm!QiXK=mXyg9xZ44oWf1jNmJ4L6aEF%nWg$4I1hUKD<1P45;^y zfNmdG1aECIGd3197F0JDgv|3YI`@?umnG*$?Mq3E4-ZX`vrMvK)cb4Z%gE?r=WGKm zn?dES5O_=%wBe13!S4SzW^JZZ3^EMrpdG9Nps6tMGIKTtMz(YgaPNj4)KCC#$kYQZ zrBhLomt~M)kWp1p7FLGb5f47p2|TI|9u$F${F|78+y`-+v5}dXDdTTT69cQrq(oa^ zamfJtyke`mG*`Fy#14IP38qtjUs#%2nZJA+n5Cnps*{oCm|(`J_pjN`yFuO%G(^M1 zVD|qTvoX^T1|<f4&^-mRjEroc_3}(!9H3dwW(MeK2%tsA;I6d3H;T(ulo=SbG?evK z^g%oSRaBLQmBDvD3Zl9mv<V0@fDGC>WUQuUYRU|r`vrBpO-<C8m~<S?O(Ij`jO<i- z<wCuaE6U<+y~Wv>m?yb8IlBcoGTJfy_<Pa8%fWHlyrg&uZ5a)V?#`}0Jw;w4fouOB zWTmF2#>5GxWP$qu%KyJH>oHwn&}NtjnGEOGU}R!rV`O1s^3r5v1C2w#L|CCB(3AA# zSs9r?=N+)5GO)2R#DlyF-WCfUHUy8dtAPd@*_c3=;4rW-f-Y#qsxZ<)6m(OFf}E_h zxTugI9}j~zqc*6>VT5d_5)~5@2ald2B3Mlg?Us8pM$X*QX!nq4Mn+?6OVfyqxaa~# z#_Ytz*u*4n8|yGNUClD4E6KiI;7#scZnoAA_nsvs#AkaudV1QJSt&``$ZLc0AgJwm zgGq@&1GJi7jggH(6%rh*%wA}|0o@!6@izFPVdew|W@bIm4kl$qS!pQ=QBVoW!=S;a z0rCpuz8=uVf3R1;K2cUu$Mnbbh#X@bLt7>$L(9zY{d?J%+}&L*9DS_K)m+tNHG-Lx zyqrOs%DJpebWIzk%{#Qv5Waz2Scn1C{&itWV!Fbh%;4qVt^iu(z{tYN<fRCTN(Lro zrWOWPtZ@+wSzgS@ASWXsCMqnz&&SKd4VvQsxgHS_qN3pWbkLd=w6h5q1q&+@ydn~! z!lKKwl2g+&{2lCKG;}qqz`-8M!@?8cUiI(Go>MM%o}M<Q*2<FL5Ql`hI}<09B7+Kp zn}f3wBO8Mv)ZNUW`9~IT%7L~nU<pVc+PYw5ke8Jd7ZZWhqYNsHDj@g5LR*drw|nnJ z<(cWqn<@l_1$g;-S-S;0SZMgDC}_nqDSEjWn)9-9%A0C>{rk6bik^X|s*akvuz(xr zY$;IB=Kojb2BuRCnhb4_AvZ2LMg~S%MkWT(c5E1j6@1PJ=*UY2(3*N?&^alfF-gz_ zKWJSgY~)T4v^QG|ixN=(5j?i12O6A%jNs`pK}Wqb88lVZMU;h<IoPGN8No#eI8lMh zKQ&X(?Xm2j3uIx}6q|t#g<%RbHOq;}jJAw4zQ`#m#?7m4ZzQP9$0IEurzFC`Auhwm zbn5SC2a9S@)=&#`XFTY&Xo{(GtN}Z#HygXYm%7HJg9Qwram#Pa+~EF<nS-$yBLkx- z*y|`>U|<995Mf|o0$mIPIw3<ySy@;~NC`Zm2rBWw&IJ{8Ajc{rMi!qKS)@kniA|f1 zJho`P$KJMn`n*H&DU4!B1B{R}x#oh~IZ@CdQZ`0V?aj!X3LdZmk0QatPTD~MLmIp! z4HOxWgFGS~K+DZQlc$1$BH#)}8XCT4U>8FI*c3Ld#*`1b$1EZv+A`AU-%`*KEKH~V zesQpblrL)G?vs&*6~W_d-<Vy%<1QHx_bM}hT93>Opsm5IObo0bXEQQ_yMQbSpm8ug z79Y^vFgR4Pv8jWm<5?0ISXlHxW7i<pi!+D|3WN3sLl&@#g4QFV1UaZtDY%wVBEr}r zHGEG@`o9+upap*amO9vi3YCOpv-eCA;Q9g7mpZ_7g+T$dc2<CqnMn||-5k_;WMyFh zuUG_+Sm=W0HNag~Jw_j4RaG@*@M2*`MaaHZ&}L-NR(r%sG0@1JnW-}4az@Gig*h|) zLza|V7wIagrI|E#nC6A}#AxhhEYe=IK5}VM-jWyz5nn;c*{z|?o|dVOV0VGq5xz`H z3^E{h@i8(p@ndzDKC-(&9eb#|K#gfo+A~3Q73i2nWyXNN)y-Xf)2CR)Xv!&s=%=Sg zrbPHIVU$&>YoF3sKSM;=l}{``A*L`0+ScX-_1&0GF^GZ2(ioV)J)t_p;w11L!mwJA z0d$bN7${+Zmu-VqD1l-IIc*6ln=(m1urN2Zh|G?*iZZ>ybSm(l3n)q5f0mR0%9jTM z!C@fs{~MD%c>Vx1W{Y93253qKRxL3wFo-aS2!mEhfEL=I+6xK^L1k0M{i{qYj7-D# zMQ5&LlJNNV*1^`saV9v^iF+_GGMN7V#-z%0g+T*Uw?J0aF)=DJGBZgsvM@`5+CW|m z(A(d@tK!%o6Yrq=br@J#^;mrv89-IMAU}A2uLh$As3i$H90##0-B=XTlmxYPL_t{% zbgZo@c(Rbu)+b-rKr_PD**7&cH6^1wG14|$H>|0nH#OQnx|ZpRy1avwf~C2QtCypT zi<5+Cuv&hcXB-y`cc`adDyYw|{r?-|LD2XXV<R~H82?)_ZDcydpanX&4m5WpB+1Ci zF2Tse3hOC>&+|hPWC7(u@Oge9<!TJ<%&g4ptaS{Gpji!u6xhU!8lu1kpS+=kM<K@K zlQ<)Tx|*trthAU2=u{34HU=$5El%kEBv=m&RAyop@SugkB5X`H(5_A-&Uq<B=M3xY z)ZaFEAC3LL6_Yg+=*IQukW;mUMHyL{Vd2B<B?6wSf>eVrDR3ykq#Qt^>@19o$fBT& z1wbco$)krHX!8~;E2O*z1s%j-WlUuZpl}0Cet=ur;4%_tD1!@Abx@qZ6h}rnh%++C z$;wDeiVF!qgISSL5nC`L2HMOa;mddo8om+pc=dcOc_lg6_}I-H1sR<Y!OD1k<@q>f z7AGdAXJ7v5fVz~RQRe>v$Y&sPFJ{UE_lflW2Oyn+%+9@-$r&sTY5>$RgT{MQKw}q7 z-b@AHu_z`+#5fjsOq<yhIv&o><jv%Ur1v6hJe)a<DGj0*X&g)M|2HOCW*wMb<}fBZ zta`(lk}>oO{r|@J07-8+vR)P*xV;ffi5Pl8_Odaj!|jb=azfb4A_3PMiQUbN4?yP< zfXDyYnIoBOA$mb!%e(=imq8s8wv6nIUJUu*@hoPf@k~f~gT}%@1-Kfcmlp#ADAd8n z7=q%7fq|)x`6I+EMt0^XrYvlJV0^&r1NTD|lOx0(XnLcWG70L9W^zF2Wf6wk8-r7C z9^Bp-CKn{VVsO2&IK!?Gt~VBDFF5R`LG&`HGx{>rGi+i6g-9OgT!D?K^Dm&Z`UGl* z8l!I%B<zepLxQ03w*LW)ADB)-=1Rb!8U}Ws`TqbWM(}!J(EJF<>~OF+WNrnN#zC_| zp!6FF4lhQeG!Clk8Nq2Bte44~31TKh??i}QjO>ho41wUdMjmek>t(vnq{aZ!%f=W8 zie!*G85o!hm_hjiY%g;dQy|1%r2GNWs|ilyAieC&VN70NH-k3!d_dA0&J={9SN{Ju zCPpN^;Y{9Oy@?DAOd{a?0kJoNDF8z+$X-rx{(#sU!Q=|l%lHADKOlM|nf$QoWd!FB zh~7w;UQoP%^9N`E9+W@AKxGP}7X#!BcjP#R#1$xifXq;1^zwtmaX2)NLAGmw%OxF< z8BE@cw;=97iZjqLq#r?X#-Rn;Q^({DI^!9%{^oxGBWV4N8UyI=1a|JljF-WF^ZOsb zu#M><lN$KudXV^9u(<920PtA98fcyXoSrs;#X)XV2d5{{+yEjyf!eDVz-|N2D=>L8 zZ3nvzxy%HGuR6$WkTaH;yqV&_W<vCW(gav9a~RV)h+ecbVFHd<u)WM-OrcoyhGWsI z`TrY}I+EUSWWC@t0kJoNX)RWJ)xl{3Vs8YBUQn3{(HqIM28Z5aCg_<`%#lnXP&WrK zT>z&EQ0@h#iA|vRWb|U#0nSIrWhNxNL1_YHKS(VoHLx*yB|zpNKxZPUg3Mw9-R1#0 z_g@)o25P$c#?%Hr;|r9o*cr+gPD9=CjTu?5Gs7K%dYu_sko1D)alrO6c{A;R_#Y`P zg5tXk6yHo>dy(UtS(SMrlN!X$jDZZxaoBsGNe!%*jWG~(2Nrk^Dgbmh07Nf1U9Jba z2NX_iOj%I%pmZ4l7LWQLz|;UP7eQxRgT$wS#r^*WFo`mO;t#Z_3?v=^7LWS>ji~{g zjx9iO!sN{~3+ylCauIYEy(q|E3}C%X-b}GDz05}7xbOt&Whi6h0{aWOTm<Po0*(t% zUk(%(7qRMfW;jexuQNjzl3q|;fbC`SW?F#N%|}3P29>1@pz=NeN$*4^HPCry;Ih0A zhrOV<0J)isF)$R8_M-j=fbI~0=mp2c9I%=G{{xtgFl95TLG0pQ%;XOiXZRn$1lseV z2Hx`l3Uf#u3YlL6#YGG#+_)Drt^NOnfpa4x<BtDdKof`1wt*QqUTi>Wn7o-hG5iQN z2joWv&^#T;k6I9W85o$%K<N!+FW8UP7=8rn1=m*~y=;tup!I{G`{VzoF~u?cU{Yha z44$KM0$u0E!1T|7DenJ$W*r7j1}RWan3a)*fq{{cMM{{DnTe6v3v``zGXo<F6AL3# z9cb>PiGhWsg~dliOi)A^bjJg;nVGq<C>tBQGU(hKbr8c8BqSy#zFk;aAVSPU%1GT% z(nLziMAA^wN<2o~Qi|!Mq?Q7gtg&dkfR?zpmH>~8lai7Xc#Qn-6{fiV#ZdP+I@mEY zGBI#4GBSw^aWgZ6-NVGt3|fN=a$Ox83llSQ6X+@pCLb;?1_mxEE-4XVem(|H22K%n zUQumEH8pip(1E9-;H#p+EM+y&2s!&dOBrLaZ~<vybxAAnSaB;!BZwoJ_KF(Iaw%v_ za>sMaIw~nS%5p<o397sx;dO*Lok5sEg`v<vP>7L<L6DP)l}S-X9PB{I4Ky+gpku@s z3qU(^n?T)ICRPR}&>h6AEuc+cvLI<zM&>%K@{tbWA|i|oA}S&(3i6T?0(>0o48n}U z9K0gh%#aan#H9-Cre^G*({G@jQU-<n96ciyDP~PpSvhG@aULFLaZ4$r2w+ZEQkIov zQ@3Xk5EA5N)?}_#a+2YJco7s43{3y*nBx9dFc&k3GN^*qoG8gkGP7}jF6?GtW(;Ql z-7Uz$!jR6%%EZjh$i~c;2wLph!r>z(#=sz^DyFKaAT0&D(^^SMNJ)vCS5g~t4kCDg zsWN2giLsHHIn>?oB-6oSpdq2FEhHksuFI;gA)&7=C@jk6B5oyRU~DR7Drq2TEzVr5 zZ!0b?E}>@!BD<9wWVsdf#We-EWgV0t@#D-C_dko-hk=tpoFRJ~8)T6b<WNglHbzEf z#%2ZvW)@}!mO9Xe3>Kyoc2*{4<`&SRekF)JNPvO48Itl@n3!0?8CY1D5*V0Rm;xdl z#K7rHoJ$-!J`YN19K531%-}o#3Vw0$>=Eqjoo!+!Qij4Z{N=1(Ztm_ZrY!o}Y9_4A zK3p=UBHWVN3fVU9Znl~dQtAv$|4`k|!3<vDMF+Pt!cveaD~j9yZQ+*|Hjp$GW8`J^ zba!`Sg}WY<Jw!}pxS+0=1hola?$2WoVNhaN3R+pq#K6f2nh1g{6_;lKO(ifEfM$A_ zSU{&-vobKVGADC@wko%<_&`s~RsbnuVPvhtsm?(Qq=gBz*u0K`k(G&&wFXHoGc#*A z11l?Nz>JmIKQhumQdE?YK~zap33Szgq&PS~i7<+A@``9fCnga2iH+UV3^fA(9ndvY zk!03nm64Mc;TC4&IgT0@c}mK%GHfEcto(w4yiAPhEWMBzg@y?vFBLL~GAJ{Ydv8z+ zh;UHiVg+prWMF1Y2WKXB7SIt-3~U^1$=slG?pxSF3*|vf1`Y;xjykN$+1NP388|rD z;z9cSBORo`xldV4Sy5hAMoI#n|9EibKU8mG&wcW!el66q0p&XgImz11#a2^HLLEF7 zCiY*2VG9ETgCK*80~aqN69Z@sJChe=j9LIRW8BQZ#Kf4uz{m*Rw=D`4f?XVw0J^>{ zAabj+sxWAKq_~M1C<lQ@f7MMvgS|P*igr>a#)k6Jf>J_~CDN7(BDUH(CL9*5;-EPo zp8r-1dl>>41R!(YpnMO$o(6RN2qOdh7#Q&K1n78;0HXltSW}b*6QFTj59sg=S0sFT zKL9eG_5VKu*M9*fMQ}UJ9MmsisA5<SuA2q^3or&VO=ePK0Jm!ysz6)bKxa7p|Hfnh zzMn{wVfQu>W+o0!&<(Yc0TH0<NtxLgnb?_`QbCm}=)wx<EzywOC5)hB!@C(k`9d=w z!a<vr5r=XH$QAD#91QVXj0_AQEhwrvIicn<u&^-3VycdebdZ;q108B4rzx)~DGr&u z;{u<L!ywBj%fl<84O+gT%nsVs4?E35gpJ)8T$+oDu&IM?Ed-6cii(Ia2HOXSvkTe# z_(WX2%FM(n9$=qRSykZSJ~7PEkxNg(g(=o4GSW#-$y!iJue+<O$1^MCbW%D?awY=< zGXoa`1Je?wQw(wp>I?=9Wn0A<*;zmV#uE_XpaxoHz`$6*z{0@J#=@QoT44a*7Tg3n z1c*77gOQoJ8B~(1LllC`czi0sXUZGsX=$jdD#|m+G02*VDsu9QYr_^KfSNR*<58je zszt#o=aiX2qx_(Se1b5>Mk#qYc4mK8Hdl{ltzB+Tx}I9C#S2@aU4x^`Cd7OBCU-K` zN{b81v2!c%IM@Xw+6VKna;UkPCuT9uvbM4|{(Iib#sc0)2c1F2#KyP^G<?SZx*G+Q zen9tcE!oD$%*4tD3Jy^EQG%Uq)B^H8cxbZM8?@qqA)b+)36c&VcVVevQwdH75apoK z6P#*P;N$OXY)}I+m4S*>(DG6_83|=cWnn>RLJ?;a2NkKXgrX=4n!CZDL>QO;+l)1Z z{P4=hmOL1kK=*wyc`$*_)R6?QJ7HpAVP;}UWng4%@@8XXW@d;7rHXC_9|3+w1~CzS zNdZYt(6!lojC|~nWDMR=2|8Z@mTuLQl|jiiG&av5sx76=q@pIkJt3yro692Ek@3gB zOBQjK@fE)A&aO5!evY7GE9n0>CSCBkEOHD<TR9n-!6_7!M`aio8Nt`OfhV<kQC$Su zjQ~E^4|D_>0}~UPbfkl*h%h6Aq`0u0h#VgeD+_}VqY%{1rh=e?2}fW$<uygHFtUmT z+NV_3<#@PH40Q_R>h5BEyAv%8*%BaYHb7%b)=XCzz-Ow1_FoFHFhL4T&>{sUP|eBQ z1)BU}hzHF=bu;)dGJp=u;$Q<Eb;imoq75%IK_>-+cH|(P{rlNER6{dJzqqBQ+8|I- zMKjAWcao>yWG+5_KOTWuZLPB<_<cmgqLvlpER6-V*%-m=F?TRWLDoz_=7m@pRk@g$ zSjD-Sn3*KN2mgaw(TuDNjOh$aOyJ`bz?bHM6KOY#52)}0o$3WXBmp!t1gYFX=cX$w ziGogv1eH$UnKI}J6woO}aZ?jBrW#>+E_PV~eHBGtgW{IzYP}FmjZo{{NuK_*@~o{) znWH#ZJ($@IjQ#i}Kpp^JTm<m|AD@F8xc&o;5hyYJWzb-#bdV5YWM&d(WMr1)W@2Gf zm11ILQDbCaW%csjAR7?jpa9B^plct%DFr;~*$bLnfE-2#&WE7e1DP3_nA1Tec02<k zBdUT(2Vq7AWkop|(Dg)|?4U&=(1Zf@l^DodpyfZ{`wO7{hn{~c%Erd1<B@0YSmYs~ zC}3&_^}Do$gUmc%A8i*IX-6)rs`%s@D;B0`M^{c3PiA(58c$Av(~0RqyncNA;QCIE zfq`i*c+LAHa5)7kx8H*If6FsOL)v?CkW#n+lp$foGz$xJEGV0Ti)nd?0+u=)D!^0e z^0HE(T?S&NqKfR;i)PSyD9Y-_3WA_A8L24#mOVf0=!V=xMy1}yQj`LCPSMuwzKk;c zt)TSB#9++8z{CbVOGgZJXBqso8zv@Z(6W{$$Rz`@pcL55;KR?y$RH%ZC&n)ZI{c4= z4RqipsBZ>e(q^h?s))3x&Az9>v^G2D-zLTt`%{C`QX(?qERt;Q`-9fCG1+?9+kwLm zlzxPmelUoGZo%3n!iiGOLmdJx=b`BZQgE}Nm-ARuGO(~TL#qX(a-Nxii4oNBU}J+C zh^Y)#&MU}Cs7R^^gZ8EJv9mHD%6U-LXe1^MUSbCFv$DD}8@MR|THXU*a>gi}Qc;;= z=P${|#PV-5<5G8C7Ks4EP*<l&cXxNL?yjz0Jw;w){vNNt93Dyrp0RNPDcObb;9~0k ze+IMv3QTHDN{sxB4NNgi5(gL<I5#pd?O>7sjioR!f=5A4gU<@lchG^(n}g0kVu@v7 zVQB*G`G%~~Zw8;r1wYt>S5n&;6h{y&Xv1jw?=GYAztfEU{{Q_z@dBFb1@Bz|uMs~8 z&fjMLzcHyXU188-@OJP3-La&CG;hrUy2^;r6JB|OPJscXmM+lh0dQf}4Vt_L<yYwB zwHBimD97TPyavr)gR-+Zbo$!Lt4vc{BgDbRCm}I0Eu$nc+PqLtH^(Wp(mXE8HK>H? zinhG1w33yXjk~v<i<5_(Sdf^QX{@zR6b}nesHblV$RGc|{ucnvuP}&$PB>*@WMl=+ zNP|x&U}a>1tjCCD0AHC2^F%wS_y<QmFAp~d8-pmLD9GtZRe&I<u2&RQ6cl086_V!W z662LuVC?^Qno;TBJ?{_fY(A{4%KFTb{(t@d)dhow-WVWd{&VIi23>||hX`gy&{3=G zj9OewOzhl@tV|M&%q+5uY|Lz4pp$VJ*+IoVD+3ENXbm6}6Sy@CF8)E?AGU5bA4UdE zbwzm@X(>rD5pWft%cu)#jDW%yxd?<GmtzV#o($aC1qHF0u@R`iWLhmO2ihX8ucQ`l z+|X}cmZ0w>J@>m+nRosS|L|p{9*$<Ps=(Aw0J5Hhi~UN#zeU1AkxL8nmqrT;f~y12 zRSN$Fn5@9%p%SQ_A}hqh#=^`9IyMf}QUM)02B}=z8GJx(DG4P>CD2k_Q0`)bv{OJU z7a#|yfbNwvW(FT6t8QcpzNP@wV39Sm(~y1>*DEN+&Mqa`6aPk0$<9nkKuDNh_=At7 zPKg;){J(A;Uu9)~9me9niyRA8Eqwhf#XXc&UB%=<J3&MLe`5}1`oW;gaAd0>BP%1U zVJXYN%-jO1|5@Te3y7d~4-=xSkq(G(P{dHg#MBI_#$d$^r17Z=QOL&D3Ney_g{2p? z<Oof%gDL}>5@u#_t%0fzbPc>HBZGoG=+a2g8bb~?@G3)Sm_bV((56jM5m<XkR0Pye z2krM`W2(=}F|`P?jfh}nlL#@0j;V9BjmYMTO`q%NkQ(>zHPes#8p@hlvFURgT>}_h z{_U&)-zN;dXO=OD=@f$i=qx<Y23tPp<r$1kAkRRqn+CU(xH;Ka83Y&wSRm~raB~yh z@c69bsu8KGA*RpEXU-+->Byw}_qKrnJBt@PC#WuBWKd#YU^D>VfoJYuA|%Mf$il$N z!_C1CYM~*Wzyn%04z{=%w4xb&_OP(9pfEeHq&A}{J7~SXptz`_sktENus?NEMy-&j zsE~jEKqS*C6Op%m{~3f$OoSO3{N9R~fcnp%dBtp|3k=c>D<Eqo_&}LbgrAR_g_Q|> z(>6$e1t9>vYg-t+Qip|=iGiUDytuxZ3DjW)b=Q!jnvkSGD;klc5V{=1A;mVR-~qJ= z;4+{%7i44r)j+&F9IT*5C@7D>GdCMMJEJoAc5TS!bvq^|O+g7xb{S4yImsoADp}wC zqoQOSWojhURhTZYu(&ZX^2;Ckm(3XF`|mr`sedz+y;Nq%%W{Ik0koHcm+3Eq97CLg zASehxWxbT77#|BW6X+CSPy<dJ>}QY@TR?H&>J1vk1-EEKL4u$?*q~M_Ts+c25WE>r zTvUXEjX{o44&-`a@EtjzK~YgbP*>WH$=uwSU07KibdsCNIbmf`NhB`8#KgiTA<4Nq z{pO3TUAEy&f5GiBY59L&1WbfE<m9=wKK*z0m+4Wa!X8lh&H&oc{F&(o12=;QB>RaW zUBL>va~hO#nn8oms1op+5^|j|N@WR3M1r7Qy2^r~Zf+57Zj4Dzj3NKlIQ^Rkvh)A1 z|KFJ8nEo;7fYJ`AXDTkt!^FU-E-E6#&C0^e#L2`U!w3pKX$NdFEKJOx8}+~%LFR$l zyWoIjjt8GJ+06_}QJ^wM8X*nZancM5eQ<9Dq{KlIw6vCqkpX<D0E%2B<Z5Rf1|2nV zRdvwS&dS2-?CR!_WB(!BA;rzb*@Zy^P0;><y1E_{s6E5Z%=TP7OE{TNNm@vnn^#%L z(orH;IBm1AJcl4Fx2&M5wty#xs2~dqr>tNV6Q6^Ey_|#)3zIuDtB#(cy}~~}GZsci zR(4gLvl7;p!pZ^a|DJ==S=9e;%%E`&Wro;o;LB@Zg|8U+y2d7N(18OC3G8ef%#fbE zgA`PPfsL&hCd&co=7U!w$;*N^1qloC@p5snvVaOjPz}fmKS0RH40@6fgaK}>DJy}z z$S9wh5M^Z_=@Vt;7~>x0&d(~7V%nn3DwoNXUd;IGADf$7N*v=65S^F7xZ$r^ke*(O zu^}ijK<x>p>EQ7iO9wM?M$kkNY^4@>x(L()Y6cbjkd8UHF(D=@A`EUyK(hjJQ^J_h zSdR(hP-RACF)>iqfHx^J7;8ZpEhO__6AKfY3!-81ccXxVw<6=@zh+E<${FVW<Uoy# z|Nj|6{|hilg4gRcgZnJt`FU`gE(zS`2F*F&WV*^A$DqX!vQ3sBv~CYNVkrTt_!#3s zn{>J$l^Qc_WK9M|ikTT&KQVx#Dbj%pv@t_PO_`ln8p{>!pphi#DMsw5_n>cZ?@rI^ zc6IH^@+?r7Pqj!%jIy#%Q#JkjCabV8Gqa#D8|gAAeH}gB^x}W4jKAI7Y-2h=_qDgr zoCzA6F#j*W^oL1_L5e{QG@r-A$igTI-g$&@HMBklIT*AGzMa`eMO8^ySyc(@Wcb01 zkozz|+r~|lmC&5a*O2R+Wm}({WiREU6%Y^};~=N}uf^5d+s)0}#|3_Onun@#T>9V5 zOrG^R4)O8%`SI~NIpDAd^%tv{PBBO_C@~~K`iqL7ju&WnkClO$g_SuK)Pe@L03aQ( zX3#ojC5RgEmJl3@A{_)77?c!bq!=U_BvnmC6*+h%aE$1&fextvwGGgEj@Q9mwjhtR zl*qVf<ep<*igmifzgLXOPX4Z-wO^on4+NMDnEo;-GZ->7Iq<`33~4?lHda`Dp$4um zK&_${a7PR}IK%+D!<m7Zxf_&6+Cjck0jU93AE53X4rP%JlAsf%bhK0qRSgvtB*ldV zA#ET~c1NmJKvx;U2WUZy5JCA#R9VmjbTAHNEC4imb6!{lH1;7T$;!wk;pdoKS(ySl zn4Xa};yw5%dIJY}cX+K6AZ#KCI*GosPftP6MEDMKV$Z+Z;M3?$<7{H`7?>Cm|IcBH z2e*^JC!q0z&N}mAXJlbyX#t%(!OF}Ax(S?tk(D78*3D=JZBhn#19V~`=nimDgt0P% z4@wXPWf&1QHg;h~SUfR)TiX{EmEBse<*0JxUrcs*KuAPd3ZwdArc)`YX_h{EJpT?b z7P~sTS%b=1{r}$>KQmnc-Dl%qqRz<7peD$~$SlMNp4<iv7lKB(z=K`j;O+)(u2fM1 z^&%KF88ty;U5udfmqggu`IsPq2CW}JH};s@F+m!f?CNG_jQq~&R<Y5Je#(IXmf0#w zX*Q)@MltqQE^;o;T7F70YLQG=bb>5`6BH#h43tgn<ORY6#j@fpyiCPK)eThiEyV<U zg~UK^*8TsDaSeD6k-3A38Y44<Di$~Qf(liHo0S#8Zq{Jb0J#~mfd$>o7*2kin4#fi zVqzs`<E$SeFCS=eP0hpD#74@}Ox{^ZPSuY|$;(B@LPJDEK|w@CTUsDMKxm$}rG~Ju zoSe9vvIw7>fC#9stir&+qy!oZV$28S?f*ai3ouS&`pY22pvsWzz{SPL$jr?MYD7ZD zzvMxO0y45Pr-LqIfDC$pdmCWSw1alD$g(j)w@IeM)G{zK!sH_z#AT!z8I%;HRb^B~ zg~9zjDMl&K7!1hY;Jqwn&{zU(Wr1up6bBDT7#o|KsFm8fLYm-aQaY~cx{g-j=9*%H zGNS4tOn=?n|9XHL<j(AzpyqkHy`hY;f`<gZm=LclXpb^<o`*pRw0BpCk(pJVksZFA znZ=8Ng_WflG{D6g%fQOo3c5iM?Cfq(Y%#=xdb8jvP*xgLS&NDY3V`keV^CsL0_9$K zMQCaYE`$Y@P0h`X!L4~v7sgyvgzX-5a!ORyS=+}~*<|+Y5D_h2%MXxkylJu?j*J#s z%0<;K|4t>av2Jm6VPFK$shBdIVi02RgOs$OmJ$mCV*#j6gO;%1_7tcLl7bD&VM;<; zQ9=wtf~q2lpjH%Uo<vjxd}9)5EJ#sQS@3U~Ep#S?ao#<qY6IA$hyP#DU>hTY!2fTI z!Qk?;#z7oZS}K6<^pa;}W)fj!VFn$l0vje(L@G5wAqsYAt2YC5J3u$64J!{XFtMuu zZw-`_MOvh-%%}`aD6p|%&{^2<{uw;jO-;-`h-vY1>WSIRo~^GcqQ%Q+BBAB3<KycI zEe%~lUH+Xi)MsM_B^5}pJ9&XFJA=&;G6*x6Iv5EsvM>rVGJyB~GBSca(FF1YQhNw~ z6@@UPFsN$)ZnJ?-!cj(~WyS&*=le|J_Y~xL#kjbYK6nK)o%8qqYo@Qv%Id?$4r+@r zsQ&-T^n&RWgCfXY88*=ID_)>xBx5Y-6n@bB2m=GGxy;BQEhQ--BmkPcVNhgL1P$q^ z8i6VVb<pM>@L&Uc1PbI9@TG{1?G*)Hv5X3v93p%sWoAwC33u4Ys1WO2=+a!2vdG!P z-*8Dm(gc6M2}y-Z4E;TvmLwN}u0mh{_n(;>n65C$GQ>J?i7+xV3WLvmgv<|%GcYqV z#<MVjhDI2em>@v|9tf8PPwX%-GlK{EyFd+oxGcC^B_RenPLY)bG*1Z+J7Y+=nSw@y zmDoT_e~gVlO-VM!thTPG*to=S1$hxQ0e&N?cAFZmiRFxE{uzcRqz5uOsVi`E`f&41 z__xEW+!a(7g9<b=rmGA>4B6frK$|vr1sItb__^3wSeTeW+x7UMY(_5uMn*=@NQf#S z22kC?2)aNO>}XK0*g*{D8OYENOagp?Dku%GfleY5f|lRn!otSj8!Ob5l|VkQQ7{l` z*qZn<YLTF%s1TPN(^Wa$e-A-t_Wpa#D99M9%;CubN(P`4zWxg^$${?xt%HOwxFahs zDa69U3_fp@*-IMSxn)5SgPsuv>D_{R^u3_=A-Mbk7t7KNEG*zb97q(P$but7S_)JN zaj-F{F{*(g1F44&Spx(;2F2VQGO%R~y5QE#jPa?UEH|qlhoCsuc9}>&3CQ)QR)SJD z;!5}>*jU(P_<Tfkn3ULA9T{1qWc~>uE<I(E`gdN_Ls2qN^QMI+D8AGf7??!C`|iyh zOxPG1nfMt&hZQozDiqL6AuJQJvVu=|Yi9F-Y=svT;NX?f7B)5q9bgaI3(u@5s%R># z?7w6BzbTA2=U1&<#n|*ua8oDa^v3}%@7@111h_DQ&i!CuWKd^dU|i26!5|1a?~aj? zjhzd8vMADRO>AtCgXvpAi5NVw&<s9_LXbfawD(_7P>2)MWe^2f%nq{HT-g-l6vh?# zsne?&mH$;V6)epC_mN4$X|CIP7pt9avq4SJ|Nj}FXVx&WF`WdL1E9GCRi;x6vY`F2 zoQ%v&e2grNp#4?SpnC#9XRU(nn*oiKBSHdF4}%A=Kv@dBM1mcZsXzq-EA+xdb5Pl! zC=S|V1sX{Ot>OaBCV3}TSvu#~UtrwxZ`)ZvqX7McM58=?-7GHKRBP{4W2V#Y0jC@l zoXuSWB*cTn1i@}p`Y*uv1iS~-&A}PwMo>>h3fYbDyM9_BoiI?B09=2Hiwg2X-6+E- zgTsx8_8Oytf03<Ify-^ing7n+wvNtE@U>1<R7m(>li}!}X2$Zx!RxcFZ<Kqult6$W z=okeCng0Te2bm-oG(h#d2qQBKKO+;XDkD3a8Y2Vf&R|vs(0wE642%qH?2K$6cY<df zz%@QnJrCN;EhY*Yxq|IkgVyt)wiv8M3p#s8Q514k5F5%o<@LZUd4I29r-W$h?f*V8 zcI{5j*G~_1P&YL(4wR7z{9tLPXs&4G;9z3A*vnxFOI)~Rgt3&EsH8Y=0551GCnJLa z`263$4Dt*G4&1UbOpNUO;DiZjih*{svVx|5nNk@*N8N(jCoP~%5B3bW$0Y|6V`pSw zPiJFfgsEj_hA99KJxED_eaOoLs!iA!<Qe5bzJxBWG8R>476qkeVP#We&^=$EF)wg~ znI$$yR5E44L&may8ut!-lohix(sx(YS5Ia7n-HqyujBUbEsL8cqllZHx0Z>Sl7h7| zc+3Ho-WlW=93AXnTgjNfXG$`%F{OeA*IA%bK%lWiP#Xc7u%Sn$@Ir>+Kn($SlM7V! zse!LX1I=bY*9WkDgq_f&A7E4y$9VeRTP^Q$SNjGo@DWWxK1L4mjNAbM2aS{5oinW& z7#SevN=Y!t5^x)|9EH109O^W1GLdDJ#c-Q4=rk8aQDsn%2sGo#cEc)8UMbexCfLU} z%7d}+mRv}JrePYFkf6VSl##Wm;a)GVQf(hY!%$ODxv2908{;CT$qdR24i2`$j7-Rf zxiGUZH-nA@2L~F&VF{p|1`agP-GXAGLeM@YD5s$W8R#HZQ+P8K)EERe9nM$;$}2?c zJKN|xYimTufZC~|Qm%d_TtWf?0@B(lGMX|%wsukAmTHWWJg1bitsm&<Z19+kG?Nm8 z0D}}m{5DZuCPwh$3eeyncua;No*6XO4DS7OgGy3x%_PIX%-jmTK?7bjF*3rWBOOGA z1Q{6wrG%uwGq&uY(Rq+ZpglV_(1<Je!ZuJJK@^-s8NF@d%;J`2M|kkCh<j=KI5bXj zXHqgs@r<7s#{LX^ADdT9+yjA*Y!}d>V~h--9iiu$elRdI7(m8dLG?n5H)sH<8FaH8 zh|3rY<wiPifesR5U>0QN71aivfzs&5^y4qb|NkI!7*{d<U{GV83tC^sJeT1%xV&^^ zU|>AV^n*c|Apv5(0tcu{0}U3WvN1BTGBUF;F{g4da&m%K6@arYP9@-oZU*i47Ghuk zPac5IR{~*fURiBMP=^DA1tH75KvM{enzLrjn&k%~n11~ANbvagm66*c!Q(He|L5`l z6T=Zu|Br!%0mM&aU|@O5yn#UtR4X#5GuSd+U;v#I<jt%IUayY4F9f8vlj$E^Z7kC* zkiQwdnZAI{GXMXLMGPztI`2iDA(jcWu#TP4o2d~jpZMR2=@8Q?1~mqKkUj=oCLXA` z0MkLHhj4LUsCejq0mkj1@MZ7^tM_GOf~t37UI#V@RK~C~fY$eb{qkRcc`eu+h`2A) z53u^s{{qbNU~$l1YIX)+rYx{HsJ&PR+B*R`gOJgiAs6gt<b5pQJ(r-p6W~3FY>eKZ zZ6*KzGcYnRFb0G5g7-x+djG!(){C_7;{Oc>21YHAUhuvsHb!sIRb>C6XPSZag7@(- zdNXVT>qWK~)Gkm5=>_jwVq^4<gYAC+?G*v-eFX0nVf1F03)YKdF9T@5hbUMtXs-wx zqc><e`Tu|LdaMR!(7A<Rz3e*}^B{VeH*5k=)Bpbu(aY?@qz2h%!oGvi6dYFIJt{1c zOlk}ez0ElFg7$iX>}6+fM$xMb*Sj63UeJC;h~DiedJ*=v;M9w-w*{&f62Bn-s({io z`wm7suz#75{0oj>uzx`fG<NnKjFMpgLiE0b?vrF^-^~cwFAGuc3f&XQ&b|wx9<*D8 z*%Wjh976}lE=C_l$k}ShaSAzW5_BHi3Q&4x^kMh~E-yf1-RHo2?IRpQL8C7`jO<L3 zjLe{wNX#r=4D1YStn6&59E_}-pygHIlbgURLBR9s@P(v|4B!i9734vCouv@VjkqE6 zt<cGHG1PMz%t5p3APg!*Kn=vXm2<qqmzCON>nW)v88`GmX4WT9p8MUw!6c6>YH@zS zvKTQDKLN?9-H}ahT<o6iegX5`8wABcLB;?Y)AnRiVo+f)WVr0WFT>2l#R<Bnou82f zJjM#D9CX-0C-yV5GBKy|FmiG-#4~a;F);LcGjMTn#4~VkfJf=Uok-9~E99sm1B4z1 zM#ffeh(>Nk-1;2!7`PZXn7BC7@o9w~1>Mf#6B+5CsHV!uprfT~sAi}jCm}8-DlEtc zX(zFQj+^0yE>tr%2T!npmLx#dJA+#Ppd|pxpkBDC3Fr<0NPE^4bQh(tX{a14kDIwY zUr|Pxw|}{XGtcrZj7%(M1sSEK#m-(H?txxDOiCJ>?tf3X+xjR4YAMRQI|{0C2X@z1 z_Iss7$0h|t3#38zdx6qQAGqw$0;e-?h9lrKjhz2MaUcZF|DXjNY>eKZECt;Mn+?{h z2i4n*t`}5hG4V3rV^U-AgQ)qxf#Ct<ruPT1GQ#%13i3Wp#sEeUaGo*$ufl}1Pm?i# zVINo=tR9><z<UoFeHc!G_8c<?Fe+f|Ifj@4$|In?hiZ&IMGOq=5R<@Wf%{J&KQK>$ zxR1dJ-4D<+IR7!JfiL)CWAv7Sl%1gZ>nXV20Ih>(htzeDaAE005(n37;C)!2`s@dT z8Uv_4V~5md(DEB84j9T94Kdt+8V8^~cSpf_J@Nl{<^b?qN)jYtD}cHs%#3WQpp%!u zqfM=#Mm=jh_(&V@$e9WjC7?^znjs1qSXsMSeZULwK+`C~kXu?n9aK<j1#|`@c*qPi zQ6~aUpr+u<<TRr6^$c{PqT(Z?|J{I`4gL3)u92A*WAVRUuax+J<^MK=);WOY2?Utp zn65GiGRQE5Y!~O_WM*WBO@Ru7TJQ|<OwiF2M#gqf3rZY3UjUJU58AhbZgdqE7Gh)& zk`a~x^#~aR83mzZ4`QMsd`!rVJ2p{4Nb9cEKFLBWeo+Nzu2U}F#w}2J#X=vZt0p<Y z&aDl_hR>LHC+gbyS*E-GTj6%OE*R9rgTyJ*bWl2BFa)I&24{wg7;ywzKOhOtCy;gl zY;Pl|AVX>waQ8E%fb}AuR|>8Nz<R;;26sP`Jve<r^g{R7GqQ6}gw;7HXA*p4e82?T zR}WGHsdEAu7#Kf*-3;1w&CcD=6b`l*`5awPyMPgFFQ_2`QsWG^7qUMdWG_VTM67A@ z8xtegUWnd_jItoT|4%V6FdBmG1-E6m`x!5w+xveZ0|O%m$X;+;hMl{g5we$pkAZ>F zl^J9&MDIj~RS>-h|Nei<z`!U2vKOj%BB<pI%}4M($&4VstOe^u4rh>m5$zz58st6L zAbY`WDDH`j?GU{Pdl?{lLE#K4OF-eQ5ArW)*9TKP*uS9e7Rbz4h+d>~LIoHY82do} zWdLnF1*s7O>jka7i3j@^qIV*rIYcj#y&+(|AbTNtCo+5h>jk%=!1jXMP~81YQ^0zW z;}^B<2C_FANiWF15WN#&?I0w3A$mdff(m?)e@($<j@o}8CQk6Ynu3F@l7u)f4<{o7 z2e?p!G$R;%K<lxYcty0uP3@Q=tJc`nktfWceQb8{t_n8w!fD}Zwx-HH8iMg<=5BV@ z3A);rl};Avj`k)>)~d-@w}i>sIQi(>xJmJfa=A(B+3Ffw$;;VlC@K3pSp~}q7<rk* zHYb4kx^n*oKzGYAs4=KID2XwGZeUXo<>mqnVjvvY%itp=AuI@SAh=Wj?L@@tKrwKC zTW-NJT@6`hRl$gO6-y%>UsXB1I772YQ+;h6`;6Tm{FQP;jjcs^L^z$q_05#@3`K<< zB*hdxZS*~*MSWeu%Y49L4vOn$aD0J|3uI^XhMl#G2=o6p85o!(!S$s#sGMQ+{=X5m zz69N)^k0Cfi|HzZC_}_nK}KdKSlJ0GB^lzuqqpFe9C+;oxcmf--h!8mLAuB&vf$BM z(6%4&(h*TcQD_MYp8E%l*MJzt;>LDNjFXF7qWq%r;z32Hm|GCj)!OdA&P;n_V=L4D zMKYa^k=K(1?c*{3KOMZbP>aEw!I{wmIu0$&$inU@!^X_Uslm*|$j0m?4Owi4D!~ep zaDa<(fE0toK&SqI+IpanV`yPuVc=wA;RFr6wZP}udcC<hxR^nUnn6<@-Hf1>L!bp` z=Ad+eUkiAhZZljz10y3uJ7`~rF<d(b78@BkIG~!j7(rG;wK^CxFf)NRk}^UZ3)afc z4jxbM^#<+n!lDbb)=kpVLPy))*23A++1OCqT*q8RRa`|wfQMH~n^oP+9CY~)sGSIE ze1q2bgV$dh3yO%FnTdmwDrmBwjSV!L1DTx`6%hk*Aoqldi7^=mata9wvam`A2c&?e z`@zezBluJjjcgsGG9=Um**N~afiBW!JY=CKEv;@L#HWzS8f48Y!);;=U$=ej?=@3d zJ3U55Yh4pB78Xg%PWTFLHdzTi2_1D776v8;tN-7aQo;AFXoGJdV`pMz0$n7`z{<kJ znhv^>t_iZlJ{~&iq^Q8ipsuQ*t*9+3BFN9f4H{7d4TwR<p+R?qg04;gt=58^sRtc9 zRR>RCK}Jv+ef?@Z{M@a~qdfimJ)<nFU4q?egX1G2<Kx1^xh!*hgOWuhl3gPrT)@aJ zNm4X9&^O1@FWlERB*fPjw2hB}iNWaqHzp;fAK*1Y$=f6$PKS)ZNHZ`Ye9(gG18MNJ zp-ha;Fg1v|?rsL3NC$BRdC-}q@>&X7P%p|c$`Rp36d!81=R3IA85l&^Iy%}$7#i5P zw-*Nb_yh%cd2?A6_=lv635EqU)&;n_2GlhMh6#$N1(!E@#svk&!~_OG`~GVGtw8f7 zOll0ap#CFsJR{`13HAS0p!p0YHr6U|xdmy1OosGb8QB^A7@mUb8MMAA;{)&+Ea3JF zqaVWou--(-nsX-b{Ra%}3{?z!!Q!CyEYg`i3{~*9{Wqoy;4uYoJ<PrXRu3cfvBC8) zxQ`94huL>9Lh4~qUj|w4PMBV#dKg{rP87W$KZ5OL^kdY+@FQ3+*pFa)8T}Zpf&Bup z7u2^0^+!N``*yH6SUoeSZx2?_z6)v>C_K%;{TJ{#5R5(yabUZU`&^K-96<dR$XO0P zptIf?m>AgqKVmEfj|IvxBsd7LF|shqFf%c;2r@D;F@qKzfr>2f96vK73uw5k#T(RY z1{XZtp!F4!pyI3<G|>-IfGij3z$YpqEh!==DyO0(!p1AEEv{~64!RTyvJeMSw3tKl z8M~O6m$QmiguJSwqpO3yqadfyY-wqEDS0_YSvk2xGp5A9k9Zu7O*~X&1$7+c#H6Go zRCFNi|Iq)BnC>$vF(@<WF)W1C4&r=_EDWIio;u7-Z0w4RjBG4kjEs!#(hd^XWx%to zpb9|&x+4_iS0?a5&#m4Z;G!5*3xLO8HQ-8^m|8(wL%<W^;9+FY?ie;Ua9IrQ^9ZV{ zXlttIsp_eys0a$Hazcw;Qxj0Z0$N!v4qa9y3Of7|yhRywq6AW)Fm88N(W;1aiE!s- zm5MP=NP+~Ao`W!_;4E25L;xLVOo{vVib=v#OEWILna9n@!a-S9P#YdpObmSgA2C)j zO=gg0Py?MP%*M#T#K*|aq5=vcNk%4CHWn|?&go{D_u#8GARz$rm8^`iqKulXnu?O3 zps)zYOW=4#4BX@LN}#if7G#}?f{KHai=&>SFsI;bh##0_K#|O73m(P)h3R@oJK!7h zRHh#ciVV6877SI}<%Kz!AzN5MiBu7Eb_X=7K=nYcH#a*MGb<}YJPRjeX)EZ$Eha{$ zW=M2mR}<-=sIRB2#K>S`q-UXTp{cH<tE>w;hnSy_ofWjW0lI-1v_=KCUkP<TrLvMb zWakpNjuaIUQv{`OP<)GsF{%{Q!uBx1_gU5#bXv%!*m`<{b~1S|p7jCky7YkUXtGk; zgV=jn>uBRy7@v{`+Sdf$>71I)zziDGVxG#R#GuHa!(hSS>)-_n7&cZ$FO&cP?dJux zC_w&(O=sxoLcFSLp=Y6?rlg~+gYH$x#2YB9LYDkNhLOPCbQ9247c(>PWzdl6M@7iG zD3E{Em{#EQ>c71ZFEScK{mi5UZ3b8=ojD2LXbSQy)RQnjgYr8w1H=EVOm$2@82A|^ z8Dtnr9k`^$g!s5wA)C8FNkIv8u}upX2NOFJBLg!#LmC4sD|jlS$(s{&RVsLWy%Olk z>}Cv=pxs_DMUf8TQc?^IQZiC9f&vVn%X&fc8iL%sQre2@%FN2b%IwOF;KS~P8I8^L zm_V(5admbk#jwfg&grh9(Tw7Oa$3$_SN{b#`?B!zFmnj9O*GKC`|k#$#$BefewA1L z-eJ_e$D^*!EpIJ&qY*Um1HL<bD^n!X4+aGWO@?X*F?nW2W>#hmbzTk@Rt8ovVLoO? z23X0g2)cZ_1+*R))M$X5Q~}y=3%$n&)arClWMgDuW@!ei1f5a|F0Hyi<rcVi)eRo@ zP*P-IP}Ee?WKdvGP#03w1g)E7WCst%sxyNcN03Eu>g>v(7Ly5Rv%a`FJ2<|@h1Hn! zg%xE~c%=CDsc1tsyc+39IV*;T`_IZ#RppB;ZZR|4Ey47|oRiOom7DeN9WL;`S1#{( zjrG+zOJi9zi)Xb(G$}DjfZBNG{|y-LgZ;0@Q0^ciEXc&lq%12T!otET2RiP81?GFu z*c4+6WKR(2q)zZgXa*J*_yPoJ&<0shyP1)Jv4sJv67c?4H5F+|0nq*wW(EaD1<-sR zs}ibLjnTt`Swvh|S&31{NYmRnRM*6@$b*mH*Ev8&M4C&Iw?kS5y!rKnS`EuQF5b%@ z6pF)=YpfWrKVs+dWZ_``*USUn{>mtlV9Xc?szJFJ7#Kf;_l@d0XrXMgXaX%)V2cAC z)!obny7hyXfft+%1vz-7K#P%0LBnXEd$JWp6T`!!R;^;RVDxckH2-(f{SSB^l<WUi zCPk(n3<3<o45<#BLISKzpbLb(AWcuu)>_6E@Tn0T?4S#VnPWk<IC#%vGlP$`gB$}m z`GA5Dn}SFO0r2Hu!XQTp2?>A(_7s&(*_DMs7feGgf?yUDHD`2=N_AU(pK-CMo2XuJ zw`<=`#sbDLe?2|_e^(i`r%VCmZAJ#;{{oCVnUol;LFJe%BQuj6CllzRJ{Cp`MphO} z@YZM8o@a243m%8>289tM*1=0U%uMw4loX^TdAS*^8Lc7lsiqFP=@YtY$kaqlO<j)( zT8hKZ{1p=i4<LY!69S*|4@&fm8A1LcLRNxeJm5)aF-ubuFOB>t!%$T@B`<X|ODS7p zV-L0LcrF1pUSmx`EnaT@4?clz0<4_u;OS}5f>#j@3mq3P5dk+o5oI}XIXPir4NGnB zKt=&oQ5_8qRu5M2ej)Y$0*t4bBp9R_oE+>ycQWyFGBJX-tTRe7GO)0CF+g|Zf~VD+ z(H8!R!A|IvW|Ri?xIz6J$eI3(pe0D4b9oS6YPRvw<>N85RAyB8_mQ#S-xDi4L2e5} z5qW-Ir4Pz(CfXWSjI&&v{^fD`IO=Gyv3jtwgHDoWU|^iXbcI2bLDxY`n30J=h?5Pp zF$3f<$fh;$;^$^YAJ8=&9PFU&ouHj-pp~>DZ0v%{kP%bp9{>I6WpNo%5t;VR%HeW~ z%Bf6O(jvXP4F7#(bdt$)GqINz^N^AQj}P%MFfdMFQbMwqiyhToa7uvM%gKRiFK9~M z6f`IUw>L{A$Soowsan}rPEk3UNhvK-H!e&eX@X3iTcxy^law3-GidJ<QwY;31`!5X z1})GH8$67l`UTW9Vq{@Y<zQsw1YHlpkP0eQpu1ez*qCFvAm@fKFlcFNsH>?!E|Opn zVGvdn6yyf&IS0*U2|^mc>^Khr0Zn!#1_hnLegMdnDXaY$F9zT^`XkH_w0DE+|2L+K zOs5z`8RS4KI9ZsO7&y7unOQj)SW`hQfF^I~i9et%uM7-wpq=re45BKaObl|Vw6-v~ zTmcQwgUS}j{cfhF;*ha=Q$?<TD8}N*z(AXtIOsaaf4z)JevDH8o`JAmnpe5&#PXDM z&|1he$ovMVpArw6+h@!GFIh<Zzm@R=xbGp(AkDDVdxKCwgo7S<>N=l`k)4;3gOi;D za-I!0BPeho<q~*mEfzE#0V<v#g_te_sCXh;lY=gzOhahGX-Q<HgBWOut2k)45omoM zIFtnVcxAN}l|eV$2r5F#Iq-TrV@6|hWkF+eWyTNBgdK%57-e}Jc??}Gvg;i${X1Q5 zv0lkB+1s1xl%AgdeZT*VzW4uL0o@tM!eIX2fQgam2ZKC=8iO{2KErYcF;+&<k=yKS zdIH?c%uJGEg3K(;EYN~m7u0}h;o)Fn=jCK#VrFMb1D_ZI@&#nh6}+etQa-YPj)4M& zQ8R`n9O@$-)OB>!)j`82I{G^L>e}ksD#{9KifR(#pz}MpI9ZrMLn(aVIY-caKcJhX zmD#a16+m}w8=I?v&S7F_7ZW#UR1p{Rb`CPPy=0@HW$dq|8DMUr<LMl1Xknf0X79;f zV9H%CDXFuSNmHLmiRIQ?nL<C)wY<VYzCwb0S3W3~21V4lcm#UPV4SJtEZpE0ZqN>{ zJN|F_@5IOszTef#!5p!cixqs<5%`1x$Q4t`puM4>b3S0}q<DEa*cc=jB|w8F>`L%^ zDol|!D~hnONT~1$sEA1F$^->P1qP<=18+tbG1Ox;^J8@Sx6kk2#dPpqu>U9j3o!g( zddR@dpv-X9flC0g;*S}0f)!Ulgo7$OBP$1Vq8zlQjDdjxd>R9IUX3Z9laYxDv=9lh zydI0<F3=G@7>ad?H`zfMRIIWwFoI4Igt-K~VVap4Za--7P@I<sI$JL(Aub}sqs*(U zqQu23rY#I=`-4WZm6g<(;Q<B?FH`6q12#W7F%fxr5ivOnDK%bx1z`m(Z|?|iZx5!G zveMGBveMFjTG(0LSy`108NJ<a-gN)B!y7am0dD^aFoWg;lo^Z|8XWi~n3>pEc^R2l zKvye(ntq^ex)Nwt6ZCK*aDYJ4IcOCZxP99WI=cz9S*i)VO$u^34i1ITT~OMZDn_bC zveH5V;BD8+jLOiJhvJ|Kb#S={Y7c-eC_warKm(_U`E)bTgt{7Iwr7zHE5AEreZ91h zvo|v%t4u*ae5<Q#dqPr9PI5%7ib@>Q6$`zXKhL47?!AK3g;fOgEMk`C=Pix)o7LVv z%Pii0mVLY#sMrMc@t8`Pl)(2rH8}7~5(<-EP$Iz<CZPU2sACLTF^EH9q=Tf2G9&bk zC^;Eum_YZIfYxH8hl!dgB2bW*7?^{W7>L*hNU-p_Nk|Gxv2&_O%9|-LF|&yWIwV$B z=Xtofc?G#Kx-cmjD0}{0V6Do|0@?-P>1ZcpAgE*j>KS?##>Zzz#|fong2RFfbVCYw z4~jHsWh6Uj$(k2CBP(coH7ipp=*}yKSkO{a&{lCq#%4wz&|yg8qQcT5(vZt}xVbnv z7=##wxWJ_sC?T`43oA1#LsqE?iYr5p<6=~UYz@m?+ZPocejp9BL5%4Xd}o;YznhHe zK8)dh|GvZah=JPieN0LWk_^?5ktl9qZYE|nMlT^o77u9$ZXre%R<H>8MjlW~mf>J$ zVrBx}#mWG>y^19sw0#EB!~;!LD<DgQ*UUr5mtbuk_{6#@r1A!}zZpf9ML}ykjZML8 z5kVvSkTxzmqjnuA6LPUg23zne@p1Di@LEK0G1|NT_~CvtNymYiIgptpz!@CQAi@m1 z{#^vrhF}A`(u<Rwm6@4?i3xPYP8z7^*#z2;1m1WjBFq3@fi5U0BqYcMUV*L*YWArs zn;NSdgR&7jySXxxPFh`5eX6x<lJgsvM7OKHGnu^no`ZHCy!LBoXlS@U5p@2_e*wmS z;5FT9pmTI21ew@a1Q=P_n7lZcnHV|QnON8uS<*m_fL2gS2aip)v-&7235uwKZVML_ z;Nq3l7KT^~S~d)x<$$*S&CQvWO^t=YTLzTH#l#rnocGzsJ6ncy%0|Gp3|I)tltkO@ zU}2Nu6X_J=mtd0ExN)QVziEj50*p%T|K3RkYFb!odVt4g1OI<#Vg{Wt!{EYXh;haY z6L`K?h)Ib-h(VqqeH%X~6ALSBs!fuCl@+o@xEDJ3&&-B2XayQ(1SwzupWX!8CyYJ^ z07~J~lEU&L@}Pq(*ulF$K-C#&{|~sZ28F&Lc%wFG+#f!f13y)Vh0hJ!i8`)-UwELL zrUTv!4LXNViIJa0ktrREKOyJL{bf*K&}LYRWgjaj)hi+G$O0AR-~nZDS;QO<+L;a7 zg%4R*4l2YU#W(7XSI|*J@NKW4(jNPcS2SgygNT$A85uOx6t$JKLEE{&TV53y6+neO z-Yu`}ko~UEl~X3?gjFG%U72C$5+*|qD|{d3=osOF*yw5jAJGCGSXkKe?{-ppT2@xd zX;8l(w8ncSlM>|oG|*kV5<E<h3xb)w!25nc%TvH-oWKTaKu6ID@Nu$(j;>(k710)k z>?s8e$w8AhByvH^;`g{^+c+1w={QKsIB5m=`}oT^OGrzEGAWst#V0q|^7Hxe3gx7v zB=GTg@__bIFfkbXKhO9Qygp7Jv|E80e3}juqlP>;Gb@V(BQq<Dmy9$MvpWM5JLm*f zmUM7Dg67)5TfxC~Z#T0KXrY?6rmDW0K6Dok=r%M+VGCK`Cn^Hn5f15CfJV;L&CJZf z)hTFGF{m90syQq*eI&rgiE*h$>U#v525K1uDsTyNICDw!t2q`$Dmp7@cxjj^F)0c1 zfX)>&QB~D&F*CB46_*s&mXuepl61&OuCe+zSy5e2MP66|)Hedn6}2$^U{GZ+VrX&T z7v*4LWm95gVN_;hfDbK!jyVLk%Ag4oltv*j0O@yws?K)M=!hC*VwQ~!zrsidNp&?w z20a}$BXuJMIcX_jL0)bKRYp}%vIF(iQL9f-i4B{J1qB7D;lXGGZeBn}l9?=&ER|W9 z*d+b!kmg-wWQFB8xYYlhgU+~qko9!5=Qrk61RahEIUnoVp99b;mQf!*!wPCYL&~R8 zCQ!cB1?5{|@J32TW?9eyV(@ksZ14pfIN%Tg4J?CN6G#V$flf97g&;UgkX15(vLh%g zAvqenFAscBB=~?j(C{>*h{I3@%eR{9in>a=GSZ-pMeMAg(K=`VLWgp|fo1{<KJZyh zY@+zeJT@klN?{eq;V9S&KVD;g{~k`zp>@*oe>*YCLCAgMN(}A{9!w?-3<nq-AmIoT z7iW+Ios1>Q$jl%D-l53A#K6J|I$;vDp%0#Cz=7Be8Z-gz<P{R&<K<)ro!tZ)wnEC> zkh|4EgBYe}X2Oc#!JOZ|C63nF?k*{&jQLEF0pPyWoqz8c?VRmBnUw6Rq9W>CY;rwK zqvOH7r+-^rLP1N({{Lq{y?+W4_u5QK3?dAg4E7E-Y>c3~33NXrGb;;dfhrSZbPe34 zggIDDl#xMI8FV~?sHT{v03U-0qX?+Zfy@~|M>jy_5^{SGR5-z|Yh?6I$uQTGHCHyu z2xx8XYm1MHjj{9g@zs)X4K`;|3Uo9v<z-=!G11iZ(wSD@JjE*`H6umeKu6U>(LhNL z)QR~I>1%;b^|N)b!rJEpx0yiwENGTxWDo)EFalpH$-xE+XpozcHll!feehn47;5L` z17?>6bQh}t6DZ&4GFUN8bpV}(1G?6dQJs;UO^}h9MSzis8MYBw8(dt1+NLeupmr*_ z-O>wMasq3sgSuc0kRG6eCP*Rpph`k&BORpm^%xmUjrFYbtyGoeWkrO*d)ajvb)jus z$QETb(AHJh1&5#_$IKMAC>WGyAh`#A#Ve>c!(;+IK1i~(8nimt)t`wGyfnBZ!z4_O zjfrKBi>Id>XoWEBIHA7{#U)CCT7hn&9P(0(fs>jWrfX;lnh1OJ{JWi<oSYe+D4Lr9 z+7AILhlN0AsxW}o0W*TyM~vT?lpuQznLt-3GO{p&#zBP{S(!ll;Tf2jz&BYl!V@F( z{7&$Zc%Tbg1^9Wm*jZtF4H=DKl?}KIHAOwBjnO&RPC>y<VVkdyim^=bX~TFck34&i zN+u;09|7UhiRo+{limM)5)y%&U<t|F4F81~|1e1~NP=n)2Ym$*q_fys!BgXq4Y{DY zL5h(<N>y4_Scrq2L6T7tG%70&K0v^n*;rgm473Ew+#G%w8)(y*I(TRFUlV&Z>C<s( zd`j#rY$9TuX>n)emF!LU#e{@~g~Z;un;OL!GoJjY5UL<zW+wXapSg96mWhX_q>PA@ zyu71`tRw@||G)pgGyY>zVlZH^0kxmyL2Y+Uac&kC7Dgs7a3X~5eS)4K3qGyF!c19F zNPvTl!GO^K<Xlik4^ob@LzcyWI=?1n=IUx{>T1x<&|>0Xzd*L%GJ`z;nGIyT!Yjhb zD#*bjDORbXU~gh#ucTBjAj!wc%gQOrC#NN2%O}Oj!X?9NE3UIuP(+NMUrd5YiG{_L zkws8$nW2-mv8}C%wu{~xaY4{-L1z{=IkgaBO(6jtp)dudf6K+SB_zZpB&2jfX({l( z0+T3{1S3C#H&Yg@P0ENk-x0Ew7F4$-Iq-q*-DGEEVg!xMfGRdnbp<+ZmmwZ976T2E zUT-$gf&SpxLeLUz&;}{cDXQRF4Iv3R<w}7;K}lExbnuO&wy_{`4TLy64s==%sQMNR zt%9GF!X_1Il9(J`5#`KO2&-%2Am_&YTg({Vm>T!*HTbSh(D_4u8MGOiVI>R`BQGNx zt284En-n863#^1u1xGHZtZM;Hia^~8KIn;og$3L`1CNa;gOosggqRlt9S4P^3Vh^& zrUs}ykq`r?3(#%IkTxf*JVElE2xyuZd@G=tsUU2Hg9+kL7>HLZq2-B0MU-;{^!x*9 zd6<{&dpKA<nc1Zj7!QKI4mpdAiGhoO0Xn88&afA9F@_>1JLr@pCT3P9&`xZ~PFZkc z13WkeiZ;j?8diniu^=Rcpz$-T3Q<jTkO!B^pusa_>!G7(&CEWaaWiQi9!3TpaUSS+ zF=#O)J1YY>BR8llhRlXQGLkT&pDx-287-6R0gaMHFg*m1k;%$R|BD0n&2K`+(1ZSe zWAtE>U}9s0oPhz_IV8g*!NAR+=AaDPGRwlu#K-|!rV8302wt7i%mA7-<YwR&1?>=I z6lE6_7gaVj7gRT8lnDs<5fH#6VIuUeSkS~okg-?D1XRv3GO#i*FqVSPn$K|H5#VKF zVUl5FVq^e~VS;AZ<v<s1GcYnSq%*LvF@mN>AZsVV%l<)k4q#UR*|pxx?gJULkY$in z5>ggY5>f^YS{MsL&QMbZPc91@3xb<C=Ek6&ySm^+PC*U{33g*POMPC!2u>jmaY=R~ zHVb_|LB=8$R#{nVS5`)we=|W$D>v4EI~kb%e`8=^3<1wC$T4JY<zZw8pGpaGKIpVy zc4kKQbkIyc3nK$7GXv<9JxB)=e4-r=6|AwK#%nWZJA;_02m^zZ1Za5^WZR>#sv;LJ zDDy+&7PJaR9D39pvoWaI1D-9PqGe|$s;|x~!xfQ{QLQW_DJ&q#sA;VyWgy4N$tduz z(&OKC#zJm!c@Z8V&;fjqyw7M0p1<`3--o~mIWH12^C1Wx^ar1G0a~vEs&^a&A<K9` zr(ZzDA{}@c8NkDuxK5LNtK+I3uA(WZ#>=Mx>NYSt{yAV^06vif)K3MSf0hrPo9J{9 zl3-+J<7Z@Ihux$Jn~~69U}s=rVP{H*thZoh2A_%03hFU|*A7FnDA<Vzr3h85tdPy5 zpz$QQQpl!oNmy0_?`ei^3I`nz4=rv$hi;jgD}q*3iNd$PGp1R`DJUjc`6lE?Ti^b7 zAR>Zs`R&41$BGX^f&l_jk-j0`wx9nQG5vVp@P$1;*F6`sZ1MkphQR;dn1jG|NdWV5 zEOklXe*us@g9?L*gCQ5_><&gRHWnt(VldDQ6+;3e=zKSCP+n+f2jx8#1{Gl?VI^S| zbx=BIg%6a14$K237SM5`pgI$YX8Og##4Z_XP^ZQ!9cvOD6`t$o9G(|w7xCd0zcH_t zW|W>zTsmXyzvcB&VT>C8me;4mF^c{90csP2_B}I)F)1<VFjP74YbrCbFmo|7v2Zdn zf=`_UjlRf(-5Jlp&dChgpavSnYX%LSgIo6PpkYU426lE>dxitFehPHLJg8R&x_JY1 zsv>x|j3j6vMM)8Kf+}c&fRBfrl|hG52UN^~Ist;%YXoo=s4NH_ngp$YV_Fy;RSByS zVLo-|WrYSn43kn^`aeX~aJW7y?B5N>$a?sSw<taET0qACk0IyuF(@$PI`GLdGJ=i* zViaa%26ya1UY7x96;{yb8e{|&lsXaBq5=c>s3lO=fp*Xs8NpNSFeTviB9Q(kCp#+( zs0Rw_sDZt!46XH`V;a!33GpanctTQmMWl<0t+JRZH-|j0ygYbCAJ}W4iasUo-$F-E zSx$Cm7Isx@rUXwdO-SBn>Sj`6P+&-O;FDxzW?}=aXacp3p{EN<GcYm1$BaQEgP<e; zjUZ_UdB`y<&}K5Y_tp$w`2&tZPSCnURV6mi%0%Qj4mCs-4vi==Q6@=wIX-y~ZZ%P5 z8x`a=i5}1)1zAr=#s$dh5J8Rs?NDJ-2A^jl>mUWn8?D|f%uGy7kn?6iBgSHatf0AZ zL1RYPfsJxZqJp70jG~OpOu@PT-hqz%lK2<EXJEj?X!iF7<9c3WQ~rNfA$1~nT`Z^{ z!2~*B7u=U+)?rd&kYG?@_yQS)=VD@HV&DfK-y#j!*9H<{<Y#2#1RcD?#l*+~<-j%u zC^IlKu&^?-q;hjGfl>n_=mwQuZ%#&5R<?NPVjQSZW@t)57pH(W4=^z?fv-qu1vSLL zMPW1iVwP@DC20)T$jAY`a0N2d2fA1Vhc3_sD^ik-3<`3RDpD$-BRY9Nvl;ActSro+ zIZV*{L`EZVQ}D?XqRQaYGC(yb_}*&Jp#<Pa1`Vwl#Mv<>{QLa(FC*{21#$s~?)eU_ zMXurAL4iI#OiGUCo|8RSd78;9I@U(EPVmZs9=XWC#9;CN8`CxLIJP>2vx5UCbgY0G zbf$J4=;9Q};0~n3U`zltM7kk!Fv^Ocg$BavBI>-{9BiN&7|`eq^y~y>&;g>L;?Tql zF{1`vlMm{>fn3~~J=HfUHb;q7AvZS3ds;zdgN>n~eu$B-kxdPgl3#yPc2iVTQ+8s% zzh_fXP>7dBbF-aGNKjD|B%PT37hsyl^n;0w@h*70o*&YdV&rECWt@wpoQKGR&Piy6 zq#|zk<rbhs1LrZr=W>L=Yf!;0aAp?h_&ubW7K6xuGbm^<0yL}(9{mDIKu++1RC`c~ zNbpHcpg{@_Hqec2ppjnC7=<~wQ3O7I6+D>l$FI!G%`4BR<*ps!!NnpK#08$g(G4_X z{P&k5NymYKk%9le0OKwu2?k}*x*`D%CMITnMn)zDMixdz$hsoXffulH9ejc$WLpn- zDV3azq=bkNFE{8ASWuS`ZLCrq$wA<h1s<u)RRj%AvPcD4AURJ~1~fPcZd}Ch8}mZv znm{g<gHQWG%8UO3jG#F*VTLqlxPykF1we<pfy14dk(mL?gPt=bga~qQ1_I5WJBWb~ z@&L<#0u?5KC163_T*&+wXuJ?wUi(9*$22{_AuAcoqy!7vzn_@FK?^CL!ERMxsDZdu z0OVF#Ay6|MG=K^^9!r3kk%a+S2<mFo)3KN!m!*I^XQ2I6;3+^zM1Y-+sDQvHK!f(r zbFhJ`A5g5I_y8UckQ3;@#Wy38ca${+<$3uOK?fFkfF=SF9{V>7+T;VBSC|M&J)pK< z5Ca3F2lyNnZ3hjI_dpY^uu%la4tH>2&d2~hi5J?!1kI&D0u{93%f!s=lZb&3H?Nws zvU0eF2a^&Pn>P!$j={e+#%f1TS&%(K{{<L1VD|7aGBNNnGBPnCR+oY6>vqsUDRN5| zJVXlWS%dbLfhIjN3_LW#m6fH{c)5iPn3QBa9sf>c$}-U5X7OeNO&x>lBY7qX20jLH z24e>UPSE9VUZ5-d7+IJ=>$w;}cgeJRgXTLylgA7UpcA4P_!#&E#i93xK-O=uv5PCK zD~m$sij|c^KZIqdSSrj+>uRdAb2YK+XOal=F|bo%e|YsOqnwVuD(Kh`(EJ$#1Cu<H z1fx5PF9QRUgac@63-WCgps+ChFTl8oNr}N6lxH;=Sy{A1nV4Bw85x*)7#SHrhsLvd zF+dLo09Whau?z6gkl-$VJCl#9j+&|pxMEiY?W<OYOk9ETCpcX|TPG$s7eX>_DoN5) zQqh1X7JTa;r}zc1xgZkHM$o}LxK=(gFo4@>jPgu>8DtqEATxx*EKJOdLX412C!hft zF?h}epCSeGm9&EhC^s`QgYI!a43>g(H8fAiGRlIAOHcxY3|@f-JwfBpu=z1T6Em}$ zuvQpSgG|Mi=`XbX^*0HrEjG`|Ll()+stn~0LSl@pEaIT~Fi^9ak%1A^2Ld@;fsK(F zG`7SHPD<cWUGRyd@D2@lK`jF-GYe}vl2TBe02*0nX8`T!Vq{QMke8E|6cGZ==5nyX zCW=5c05sk}qtqaOfQD^hz62jX$;PG$^P0CelIK924^ZDRI=C~6J9)@Lx&L0d|Jx7B zgpB_`{TE=A2amy;JD7m(-IL;GVrG<PWMF0n4I6@E0h-=G(EzR@B*eh;k<efl2OaQ+ zd|D#-=xtCH4oZ4Am2Fj|rMaazxRgZ{EfnSDdF45{RY4t2##4qG;H4ijF1G)Sp$$sV z5`_Pgz-|Ji6%Ej8f6$?00*s8{^;Dn`S7c#iWM^b$V`K%5L4aKd8C*vSa(U2wDxf(g zgj&#$I$TAhgEaKkIt_UZ&@ok@Di1P{4C>54hHZ_Fu>?3D6L>xy)Ta><Q*`im@ijsT zbVhYMU1<d!84a-yPA2BgOks#%|GV15$y3%tRfk_hMg(+a?f?G_V*gtiBf)D3!WlEM zv`JuR#!7(B-r{3qVqs=vU}6FH2S9g`HY1(A1?s=RI&_Q-khN~Gm2RLe3#$?G$+n2o zVZ|6Zkd7!-HkmzJe+76PK-R;NNe;Y0=kF6k&=E-tObnoPrU^`-`4>5coUQzfobV+L z@}M=RT-+SYtens_r>&sYFQW16po~ogcnA`D%V0NXphy(7I#pVdL7YJxvcN@9kcU@B z+uRg%d7vU>qDB<l76P>$O~pZ{+nOqJxkfUIf>yflvPi|4Bql|cN4oxd{n!1<l`B`= z|GI0b$ELa1H6%xa%38Vq-<a%~Bp4Jxt6U_wnHZTEy+E72m|{UEo`S~+ArlVZL(F8P zr6i$eox=ADfE(AKQ&vQg#=k+=1&b<!78fz<y5~EX88^K#@Bp>0l`Q1nG-b7O*%tbF z<*0kQij{^1B&P%z$GGsidWN=_w=pn+#vqu)!TGQd(yri=W@KRi4fKMWKp+OAmoy_2 zeBT=A!V89YCg_1?pfgZmTZchCMDQ34yfJ~01#i}d9BIo5KB5uYm=F_%>_r0~$^pu| zps66p;h~HTdM>K@C1tr0&K@4l@@jI@ylPBJG9HdoD=SND84dnjPW1MT?>ATF^k!iL zx3fWwx<BCYlt|Fr$pHoi&W#MPvHAc18My!dXJ%&-XXIyyVirPA^PrQ97#JA;GIKEU zGsJ+_1fl9@U<40X-eQtq;9yX8P+(^PRSk?@%%CG{k;Xqc7&wH4Sa`*>8JR_uO_`0w z%^7bUh&Yte)yX9B@95pTjMkq%fzI9p-^nS#Ai?0_;L5`Yx|W!cMU;`1Q4DgHBw`6Z z{QgS@(BwBLvw;gkP>&4MA!B0&^~S*Y3{)VRDw;yp;VUAlVaD6aR!aX)!`9$4DnonM zpwiIO3bFvd2VM{|F{uAv$t1!Aa+?x^wSxsWBj}hS24*HNMn(pA(8_dX7Ix5j4Dd;u zpd;*<nHge1w}><|_^2qUC<zG)iGWTe6$h=fP=>k(y8lpwO<9@E95e_8-nRD2nT>~S z2Fzu_nh|y;PF~T8LdLGT3Zi1tM&U97vV2e{2Kw1)nY*ZE$&2wx=z!*8`2GtpUI2|z zgU`2N`v2y?024El1cN$*5krzgyf`B>ix49dtCl<y8@s9!69XHI7Z)Qtqo*>+8;HX& z+1VJ`K_xm1=={Z2@N_A>yw=nJt)<W~(lnBk04>TE<mX^xP-j$!7S^C;B%q2BwCrC^ zSs8jLCVX!PJ7|xkx{*0}yjfI4Y^`3TRfL~)z9};cc%<+g<ILMG1x~y?!fL{nDvD}( zE{T@<;kx>2b{}Nzjm%tBRk$U1L4${04qsSI6Fp^3C4@A^%rq2~)I3d;<rReGLBsM4 zJm7r`e;Gs>JRNwz`z4_J79b0o1Q|f%3ZMa6a03CnwUi&k1&y<V;;|XDGm96rmjZK7 z19US5XgPqonc4nyv^@=fL3<iP75^P(%$CV@uapvZl9UJMMJWab#(7MC8QfVCLAQcJ z*DNqH@cjSAIDzR0gD8Wy0}nqB3p3~>PtdKmknStUtzcI&B!FB9?zswrc9b=PT4^vb z@F+7MFXUn`(9RD~dj;G<G&NCE7c>?G$H0EmXk|q?U*+nghzPeJl`JkfDJL=MO1C^2 z#)5zQ6vE<kBS9MmK=Z+Z;IlVm8O$9_K<AE0@h~wnLE9osOyIf=e_I5+`pu3BloTLc z5ztYypyCYF6k*h<sZ@83Hqr0}uP`!lS5<a31aI4VzxR02%xHD+iX!`-;?gc_@NO+o z+6M2<X1dCx#sJ=%%}@y%&w{q;ML}tv@ieH-!l3*A8<QfF5`!><Drh|gFCz;xqZf3z z2X#FKbX{LJqmQTv=p=esX(<U2RZ&%TR#3kmv^D`Wwg_s$gHp8_^a?j|B~UqHEUFBq zjm%6<7)6@8TU#rN6wMU$%!^Z+gI#5`W(M2Egfb~jYObFV?W|#{z{$dEY3S_b<*lpg z5oM&2mH}Ra1{yyLWCG1CP5>V@z`(-D&Zxl!y+2Kik(osre194w*=j&ng`mv2K`&AR z#|G>oHE9PmP>UApjcX_h!9)D&s`9dsh8K9@f;OWzbZ7`N(TIBQB-%{Au@U&nHBso5 zYuG0By-l^upp%UT&Df^*IpZ8%q4B5zj>l`DJu3ef{uhAGJIXMqGu(#EJgT#TwxqGK zGqa_0f(}{)4Yz{#m$rIyGlEX#;6ho$k4-uFIzLS1pjk+4%CVa6pvnN+g~S5Briht? z5$quFfG>(GKr@nxa<aTUpnE=L)#cP7*98a*^2qSYK;|VugNDN3r3sLpEi;4--B^gy z#BCCj1262)v+;KD)Q<4>W>mG-5|>evP!?t?gw0w0nGbI3O8k8RZsDqE3xZp?|Nk>^ z{#O8<h0Ms$;Kw9}Ue|-hQy3T+7cxmOurkOyfSSbMQ4pp$&~`7#a4{<btDqpL9)~zC zG~x@B#6Lq%#Jaw}pp_X6bq@UC-Ghvb%z`XTpc7vpsTb?2G|-$LwEqlRR|`7T&jHJ- zG)!fY4x;L64A51545|#Os#>5q9tmy491kedg32Gr(i+gzrWhnevxy2aBd_RV+=afJ zPuWsQTAhnSPFPmvBWyw6Gt||5CWzj|pWUbn`WWH$k1Ru~1CKN#8-tV(J2N92Xbu<D zZ<1zZWMlyq^Gu+1=a4a5a90~NbM7DsS|7m1$iSA4qzrr~Hh5Klgc#CFdgvL$keO{Z z@Rf1U<>#OZ7*R(l`#a?1L_|ji#>4jBLF=gi&m~Jd>ku^+BLl3S0=peF<|NJo8d8J1 z9dS-Ar~--yIToBpz=zd>-40&cfTWCt1$;`aC?f-?!5{>7J_j3UsSv1)1q~K}s|e7s z!=j)aZ;<u#;60+RVKr8KV03guPL6}Wau(BHc}XX6sY>@;nL3c`0~A9c6&Gkf{x{~C zOg|W;7}OcG7>yw9cOG#ePG%N%4e<31(%u_DIUO#>$^vTD^9wO@u#0mtv2bWGf>JDO zDnbD~b_|+MWQ+&x-Rt${Vq;=qVMt&FP0WGnVn`)zilmMKv{D?T1w6Lg3emwD$H2<k z3}G`QfQl}NW{_J<!L>O^2ee)VF$rsSFaYagU}uMFW8mO`>H^)a0kx2kjg285Y9FXL zk_BD5qNS;<D6KA|4vG#?Y_PL3NHI!5PXjfDE?QSp1I+*^iZUvSDuSj<!JTbz6IE11 zjFnLlzJ8sJi6w%u;olQR<$p%VH^VYoGRpsZ2s=%|nE%=Xr+;}aC~G-c7-xd(Z1evD z%$u2hFc>k|Gd4l)UJ%z(WCG81bBZu>f%@5?{x%~k=&UKwWFlCao1c*hUD^Rd27Eax zs~0FvL03N*GH^05ad9%GGqAI_cylu{Gqc5m&ZX$}=4IsKf=uW^=gfH+85lrw=8$w` zjiQl(n;WK&fhZ$Ds~>DJjbLD716Ro$u?!p>t)MB<X0SuR>l4AFiVX2EcQ_#QgKS6F z%FYgMu;bJZihpGjV@3vROJjQzdmU}iMp=1TNpaAsOz`x+5u*`kTOqdTeNYkrb@S0u z2lU)G)D_aJP-g!hf*1JOBkmB6U~B_5@*OMwsly6alw|=PkiAFXONFmJfHd^ob8S%y zS<s%%mCXN`elTb<m@!x~I5TEKVo6v=n2C*(jgghd9JIOw+(UzAdQ2(Mu{2^bj9i?; zjBH#`JsgnpYCy>al+ZL8*cf<N*?2(xp%!m0Movzqcos&`z3<$-9H2u^;@CllPa`(O z+GEiGJ{|$27aT#Y-UzJ>49!p;V*+&808&EPLsz#$EC=ZYkFWKDoj{B+4wfh;Fn}Bm zb_W9&7fe4RD=R}Bs00V484eC`K>|9J0<`8^Tg%D8#>&#d$Uw_X+YHo)6<1La;p3G7 z9baZ<4j=bHOAw66-CEFrW$^VkpfUsA&1Jd*>gV1Al@}-}qv78ZM4$JcH8g!diV{Y4 z<UTNJDslRk2ki}~!q?WbFwXo}0O=buFfj-)Ffg5Bn#`cWV8L)0a$p^|5IYkivoIqY z_-a%Tj}^*;&J)QqFflVVv$HZWGD0@TKs&?WJ#LUF2c1i&#lXY@RR$h*?)8Rf0o^-} zuERkctQawaz|P3X2rak41EVmrBO@K8)m0f8OiffR)Ga^*?4appHqd#)%An4+F=%i@ zP#HXWs0eA@fU8k(M+<VAg0ea!yrBm!n1gO2`U$@NNZEvuM_5Z7ag>6MiLr-TNz$8l z&Nh&97C70L>x1s0(gO`Uvaq3@py21`p`ZerWe`%}`*+1q9~8#_1(>9m{xaw?m@zDM zkW*u1XH#cnVV7iNW;JBwVCH9J;^1IpWMXGzU}X1#Gz*OxSlC(FSy<~B*xAAT7tjbY zGc)w&EiOh54sg1MmV^wD0@=Y3u8WO<orR4(os*G(o=68_eLZ6%Ju`hXRTV*D5mi-X zZctiAT`^(`ov??7t1;w)4|uzg*~rXX5EP1xD^zS$#MHPr<oM*}`3=RPfjS3Cbb*it z-yD5U#AJpK8wV&r!54ekAzF`rU$U_<_JA&-0u84zf$r8~Hes5~V8-Ccu+%|R4wOXY z895l$8M!$eOhlPkxj_>ikfI5cIvF?^xLG;4(?ORDGcw16uFz`r=H+4njg4{gK&QeT zOc<Ehn3_@4f<wF48=?=ARME6WIw)J1GcwrOm^)fH8X0J7Dl5uJfri<jDbbA43{+h} z<{cm@5j+tB?&pJ=-{6&a;8Y1}+<_CRC^W#?z(*T`+Y{_!utYg~wvMc!uZoyskq2~a zU>*yzN~k$_`;lF;qE;fKkEW@TmZqzs1{XXq!8dqm%9sTt*I0o^4o-`z3QDPhHzTQQ zDj0ZzwjU`;*nq+pJSWc#x*OP(ksVTFNGmdOuq#P1adJp9GI44%GJ{$h%%B_9*}SA3 z<iN6wTpUu2oLuM%*kM=RYBF$efG;#}@dmF)<BSKD*pOvh(8dJlL~=-D0@MXCLDRq$ z&%nji3)LLUz{!bKuY(Z-I|Bz7J4ZU$7NRsoMmoqcG8pJ-X{xEn%Yx1>2kpWDSNEoj zrl9^OQgshqMg`uE3(5n~#vnKf*+fOb6WXATs-OrPQ>}y&FQ1H%jCy&bOGHaVTwHXp zyqU1LfR>n!_Gvy=sR)y#BsciBjnxgwasOU2UiqiPctulAJ|mi&-IbNg+FsdHOEWh8 zUyyews1N%88&f9J4+b5E^^myXmu6&Tk>Oxs1~uZCK~wt3B8<%NJBLAw%fQR7p#?B_ z2OlG7tr?`D4QhQsTJwmKmjS%M47MW(q|O1f2n}WebPW;sEN%EKL}a9cFn9@&I5#I~ z<qv4l9dxK!T~rygbQYz^1@%9nfhQscJ>!P4*g8QwA|fR{%uUS71ahQJh#K@r8*n+? zz$GfG!1Uv9m8mwoki|H}#xDSro|(XN>LyG-Kv|n1&Vh@Sk%bX-6BDSv2J$rMwq<bt z47MPOiHSK5v<MO0*OUg$!Zb5LN7P$ED-q$c;MMiqTnwP`dqF|aDT1KG?G-^C0#!!E zP*|J464c6P`T=g-TSMFPpm~SCOs5!l7$h0|9K5+Xn3)-vBt!+6S=qs3=1lBN4D5B> zoE*&TtW4~zHC!yr%uGz6yX{z6n^}E$c^MdZC3z*q#Xw1wpO1lufk#MCNRWqDLYt9U zS)E-OG>c#?ZZ3?>Vf>ry9T@DH<mMFO7U1TJ%wan9Z^Q53i~)cD{`>c@4Z#MDU4$|) zF#cpZ#lX(M&tTx7%go5g#KOeLQpdo;z{bkLmI@jx1}#fy@&+B@)y(PxK7vFLdd-+3 zsJjhb?4@j~EUFyJxFq6B1ejnt^>X_3A1|j*XJ7=6!-MW}Q(}PL<;JbR$jTru2)cdB zOWFa%V}kOaEe{#++y)aU0fQG`fD>gm=va5~G8Ir#ZUrrFgCtB$CE#Q#D=j9%#|vH> zqQs~KN~Yi?8=~NeIzeMWWm6M#WpIrLnPg&PH#IXeP_|aCh;ojIU}ckxGD%93li`!& z;8J5!lCm+p)tDN`DEjBed&oA4`^vIx%&u%~py&qsv5`rML7!n3B<~9AGO{t~$T2ap z2{SUYihzzn^OAM|i87&yLjA1B0P3uQ(gx_t2S!F%7l;{hZy<PZNR<J!*cYr2)NTcP z98(>5phQbUSrN2Z5$u0`Mt$gD189N`lt)2Je!&%$C^!T_rzqeK45afDa0Ux}DV40J zqX$|5f$j`olxK`(dd}$106Gs^UUQaO8e}$(Q67AK0%(le9IWOQqdN=etYWNc{@-Ef zXDDO3$>`4D%fP@0SHrXe%^YT?bVhej>3~qfh^&T-QIg>*QzD}~iyN{zsA?Gc8Rfxh zJaDQ3xj7N6#t&HyihI}@6&Qbj)G$OLt3k1gk)fZ_2dpLrry3r{s|<@l=NK_T<~Mm5 zuQEo1`CQ;R7KA)2oWBGt&jCuK4025N4BgB^3_J{48`)A^9OOYG%}fl;=?qMaj7;Is zm3T~y{=$MH0xY}|+8fyzTp)vM%BG;9eq}jB8yiCj1q)^&3nL?QBUvf%nber(GBPkR zGcu(!Ff%YPhl494&^el@=0b*gMM0YrjJu)cGTB=g8Ct;1<zT$P$jkJPL4?5q>|R|i zMg~S<Q1Q;d<i*U$#K6?T02&4l2M@)8%5u<sNFod(s;Z!YTCnR)%^*E6&;l(`)h)ut zE*em&swQqKA|_^|=IUYP#CRb@+CxfRkk5oq*u_Z4Ma1O)e+Ci83yhLX{}|j^dKeX9 zdu;#zXOLu)VPs(zV&rF#XJBA_qyU{$W_$!n#VGQMnDPva48lxGjGWB83~UVQU_Z&Q zGBPqSdVw6@44yhJVPIfjV_<`fHG{oiZY-{>&MurQldB#Q!ld;2^`1SDb)~#aN{r0R zyo~%T6Bxx<^<neVtol&5XfTB^R51NuVB_u$0Oc<YrZ|R=O#hhJ7|Ouu1Hp&fm7ww8 zgrVa94MukEUWR}_4<PyT59E3iu>SwKjDi2RFtaoIFfjb(hsgis2iXQO@4pGd$NyIt z*tw@M^nj}8|Nj|4W<tcKL&O-E7(lly{9=*-9V^YC0}chyQW{7oFoN<d1NfFP21Z|I zW@c7qR`3mD;Gj@9W;PdJ7`bUvWF%v6_um)Y-JpQ;VC-dpm?s1>Z94-4Lx~_GuP7w_ zsv9qi+{D=14GA+1hQka~8K*I_vve_V{cC~v;a>~F4{-TztnzXU_ZU7f)-kek&t+(5 zTnEw5xDKu#AwLg?{3(VHjFTAIx#wfbGcYp9G4eAqF?usFGbn)k;vfo6;h~@u9t-lT zub==EuNc^8jLN3Qj7(3SF!F=i_Mot4vS#?g%+A2hy@#O>8vYCn6BxZf<qC@da=C(1 zKAAJhGZcW!W`ATgDCLtPqa>pgxJ(VhsfLG99$JP)<5VNaD9^~t1S;c`u&ZHU1mCa| z!nA>b6_z@X@;XvTFfcH{CuKmXLlJcDqadTu5k@wqJg2{)1|q^Nb_N4*c&aimF)}lO zTH6fFjNtp*nPXWPnVFb<K}Ux(unP);w*<h<Gd48_nRvvB@ubsIu#rgaBiBqpn3--) zj2d7=DRU=yRuXFFawo>)U?Y*-$;zMx_PaD>$Q)E;f`bu!0H~j!pa3(kI5<TqDuT}5 zV+{HC>xh#RQywV2`7tbG3}F&rK$yY6$k5Ed$i&15GJ`1&WG1p1!r*4IpVN_lznBF6 z-EacC17Zd{qTXR-W&p(jsFp|t)k3ih%nZ!Ff`WpGdIx--m#DIz(~%=iOafD!ra;RW zOUA1IH<>}VPB8qr4at9hZo~7R22(iWab{^ob|w}EEoM`YJkt(lQ@A`zoyow+pz&XT zvF!glM0pHKYmA_AQznLH(Ci<yJQf1a{ehB&xH|ac-R=GU5s`j<AMUla-GiI+24N1t za$Ou!u50uef=v2w=S~Z#HUqgwnL!*>1#D(!U^LKXRW~&kWfx~u{{4IL;t$z|*{*i> zQ2Su&SU~E;P0iI!#YHt1FaG_()z02E+Yl07jFJo=8Fw<XGdMFa{M!u*55^t;cEiI% zgHe*PpK&LnJ7W;z_J6y<>oUM=f-%)Fvoi+4%wR$><G(ZG^#4bg*%<>F82&tk*zxBn z+zt<hBMe8FelW8$$TBc6Tw>tZ$iTGW5=fenL4$EV!#SpvNa>4-k*S3NRNjG3Wdn8F z7#Mw#(x@<aj!a`&p()c!Q_w~nWHWTZ>0Akva9fxeL9LolP#l6xVPXX3aFhZAbWp6a z={eIvrj`G`T{Q)_ku(?>7|t<rA<7<*S;*-fWGs^(df5X?^v0qZriF}LAcGhg5atk> z_l!YTR2rXKR%mK^6&$|?jL-gGWngFU1o;WFp%`@8JQEXR9s?5t15+rdYZeFU!}&>r zw`N0bYCw^Q+=iT`SV5~66-|v9pZ#;PVDz=TurxUt<UNi55W83z+z@t&f%7;Pt3;uj zJW-txxfLmnAQnNaX}hpA8SEbc#&-<f44e#xAUhn?K&u@Y7`<4SnHW4c8JHN|G2&bl zR?$JSfTE}(I2W`q`v2S5@}bqR)!N0zmEr&Yf89)e{~ef3nb?@XTg(_ln6wy9GM!@J zWRP+Y2d(P@H7!8rbTTk7STOjA2s3erX$zZ~nH!6;v9T+Qh-vU<i90G=F_|d^C~>KU zN;5Dri2PS!IQjnw11E#tHdfHNV2sdxZ`=%w42+-);cY>u@NmL-C6QYo=8A)iGzA%c zQcRsMOUy~x$^&NX|Njg>{;M#y{6ECR#`YGRKcVL^F|o0zfcfVCzk${sF{v?t`X!({ zDlY#kVBp-y$hhNQ0VvD-|IYx^qXyCgzQ-c`Up`b#K2(kT|9XZ)OlnMQ44|`YnZb8} zNHBr!P}X8FWAJhCRAOXhF#(;x&*a6x%D~LP$_%=BfSrwjJ)MIQdJusVc<~!}Uc{2o zM@L&x!N@?{Ovg-3ML|nZOI1xxm5W0{TbPZF9Xz-RT5<|n?hYIKgbsF^E3tz&51E>% zffgP>2R+4>^6)T9M%db<+PV}tMrP`}R{DiTng(iV`&9<$iMc5n=;?U*`1v?m1WT}c zGU+JCnknfR$2*1Po5rjtuHO{zZlz}<BeU2~NK8>&QuS|Fbbzy$hEjDgxSjX^1p@=q z9;QzW>P!v{t>7Dog8#k#e-;u-|IdO#2^`*_30QOH9ws#=2aqa;tp7hCcUU0ZwSlsK zi-Ga~@Bac!4NOW5rVKYBeSI-mMrIZxH5maGHfAmsCeYdj(87Fa2ap6SrUbOdufo8_ z%*4#bRL217<AaXha|R7TS%NoYC4f5kpfu*a!7w1gK?AOqmDL(F5CR?&!KU6p3$7H@ z)M2b)K-0m<$N)1u5<FC3pr@g(C@&=ez989@(UgNjL>oRTYHA8uWX!0HcJGy_2pc=2 zF&`6XJs4<3w+I^(x3D}Hhm?SUix&sizjskWieje9d_wFJylRqup&VR{q7lN1Vul(# z5*(HvI9NQH*-X+|3ku|2<o_*FO)a+%ab;z8Wo0iYlXq5Nj01^8II=Qta&!Tm&B?&P zw2$cugAjupL&!F64kpM|d!V2Z2dzDaoPOc}3K>vo&u9tSOf15{3_52&5lI1)Po#q| z=+HVT31K-AIWA7nW<WL$5pC#ZK=7%};Kdh6djU<<80$0oJngHaqGGFT-1>7%^YThc zb8?uj__T)yHUw}qHgW_u1ctTw`d20;RaYk^Rf5W8&^a^eOiB#=4AS5o+n~7&&<bzR z@=MSr24}cyZ5e$81sEB`MFpe<r8zkm_!;?;+{7-b42cBPZIm7b_POy9QAMpqL0+Kc z-9Ai8_LY$p-FzQD@b*-+_IPE)$LHk4$7g`bcv}VrrbwnM4B`x74t$_>Eug(rpi8$v z=a7Ix5wY#X0h9>Ab8?oT<L!h&TNs#_6G2sSJjmG&j6UF9F9Q7FVRUguaaKt9K@PnE z&A=HO!<=l!*lC}tqo@{WUS3{ZEg#j_<2{AxikOI>phR&(V&Q{n+|#Q=n?1pGulavt z##2m644R<O0_{1LVqszgPep+CfUqz!Fft^=jsbIK_F-g@lMxr?U}Ml^)MQ0YvY;+M zbkYwo1p{)H802m#MomQrc{yVlQ*BXG1M^5zrxG6xUl|!GJH>Dx8E-dV+wik&94_pf zs`3)jf}C8YsllmDc7i;fT>N>NHqL7N0v?9W-k|%-7#J9zF`Z)IW@v+~&r@JvW?^Mv zE?{6{U||NGx5dZ^-qU5_&Bn;eYRL+^$qN+LiV$_Ib+{FRE)W2j#aai_+JvEy5p*vr z9|HpeHv_jI2(WX2j(|`E?YjjH$_gejw*I@yC>*wz>6HK9^9}zlf;xnZ3}OET7*~VO z?a*=1WB^_4z`{@mD*joRSyMqHK(P#rjMkuf)RqA<)+@lqA*C&@EC{~09c1*n2*%LA zx58RJFmrfbx;YVS?*HHazcJosy27B%;O5{g%*ezn#K^*=!N|&}30c3+!T>ra6=VZ= zKcNF+^wyHW2Xu{;oUFJgKOYA>gEpf!J0vzi=M|VMnuFGI!S>iehj7>x*<l+Vz$<F! zTex#@ss1}<#mXrq!Xd#aE~G4M=g7e&!)WHr$|)r#AjQEY&t+pNXrxeolwVCqLY$4& zgM;19T+m1%;R!^5*^>n{Ovb>-VDMjn@ek8q1|0@l2P+{)MkY-;Ss6i24t5S^MlF;b zNlu^~3@LhSLEcbT6%!HQ1I>y+6C}tB!mOskAU`N8Aq_&YtBNus%1$;m#`)e(0=%jJ z=A`fmYKuuq@M_4|*a{1~Gsczh@Uki>3rex`DtvIYkhM@_l=3lWWLCBp*X9PzA?e9^ z8t(G6`nO9-Q$|2m4qSvn;^Z3x0~0UPRR$Rbe+MC9Mg~S9(B+~W>};U*Tc8;dP+9~X zzX-139lSwJWlPZAN`jzH5U3T-0FeRh4dZ5DV31*uQPpGN5Ytu!`A3~y-CPY!Kv&v9 zBZsk2UXFR6`Yk@Gw;K0MJWRu+wA2&b7cQ5P_v!UeQ7mw7aMtd2X;P6BbCXqgan5yu z7X#z}t>8Nd{xV2|)?W&P_8)U{u(NS8c!1V9+k#J$k!Fx)0woNP-4J_Wq`Dk4xHeK! z(`IFPE%u39R_LktC7ap)GS$bry|h$6_-#v-F_ZFj@>g+|^LBCdNe~VaFI;(}E@_Vk zxIX^|uFtg@)<WuYL2gC{MlA&qE*546MMf6z%o|9I2`<Kpn0u1|m0j_m&F0|poF##c zm5GJLk_DF8L6a5W3<VBLXGl>1N;fPC3=nk=%503RkX`HyOiajXK@9__sz~sJ6oWQ{ zwyK(#sv0=E6R45FBm1Bf$mofuD&~_D@eTsj*Psd)dld|+ltI-rsJR3_6Iu;?R;Mv2 zw{tTxvVpI{1C@E{kj1K?#)~uPfLySrEkWM3g`Cc*ud8aTW(=B&1@E0uVN~IS)E=PL zBWQ!Dy0RQ-;XH`Tt_&{9L86eO{Mbc6ML1~w!bFYH&Lz{jAy?g0TY{Bc$wtrFRg#s} zmxWth(?8XqsnI8fiIGvm%f#Q+l}X8=CaR;4S6a-?ONviHnopFEhntI=)oEeh+QXim za|I-Mm8COM)6+on6wvlJ8>s#L|3CPgzpYFUnb<({4Y0denXWRiF(rZ9kD&JYS<o2} zjBmhv+5g`dw}bi5z<khMnOdMRc!mXFKIl9f1EwELY@p4zQ1c?0t}wANsDaWELm~qM zvljUNgn;b=Jj~3@44{q&D5HuoFoSF2I#7<V@MZ-a`~uFca0##wLo8Sx)Xw2$U|<ks z5ET;?7G&d)&^8t{7B&_(25nh3GgoF-W(M7?B$!zBoaJ?8BnvakJFnL)%q&c&{xvez z|21P=XO^Y>ub#0<F~|HL=-xL*(D^P*jZ6{@LJSex`M8nYCWY)aYf$^a(i_yCwPo>< zc7RKQI;>#VS;HhF9YAgrVh|D)6au?ZT+mn;=0tX7b<h^h(2RAPlS3F87kSKMWc<L) z@$U;G&)*k}K_bS&@7@ZVi2pqdYHP9l7hnRVNht<31}_J96-IUrAx36)CNCDy8Ey=0 zps_yaVj5>}E=G2Ca5ZEJ?%>$6`N&8!FeoWVtI4P_NHItWih<5@<_6V!;ITFEA}>&a z1RXS{3_3wiR9RFQG$W#>tRyNbCg$($-IxbXj+#C)tV~Rd2M<p0cXjohB;)fT#Emht zvkjaA#l-|1G~GfN^)ph_Q;#i@1Qi|s|1-${|HfnuN(0Op;4}i->j6p=YTz`%4&Unm zQ>O+}$H2x=nGNpiFxdVN1K&H&#$W>04{CQp&NmDJ^LZE;n5Tl%pcR<U%>W7+NhUVX zd=vxtj58({CMob7u#ST!4<iex!wkBrhlL5WBc|1xm6-{Ao;d>pCkF#Nc$5@8BQ9(# ztgNogZf>j&+S$a;b=~(`wBr%`=zdEsRwgz!CaJ&A7A|}>MN)=W5`3l<69WeW15+21 z1Oq>VFoT7IDFZ758wV>}Dgy@tBRdCUDkmcg3%Kdo3ObvT0e0JlFyitH(DB-eil(3& zu%ImxQDaqOQ)Q;Ee^*up#4@rm)?7Y%^zuL7cFBbcnIt@>y02OE6jUEFGZ_E>#%u&W zpU9lSj-k;(M2V4=O<j?Rg;j`~iIIVakqNw;S}7pHL79`01vJ~l!jK9o&>)*fK^LAf zGD0rr1K&ZY!N9`Fz!J*92~x_5M`@&kkgc_)g_((pvZ|7ZimI{_53j5?qX-*2JGA>G z4lb<K!6eFwtHwr<1B=<g{bo^7b2BqmWf9QSEwfQYO_Z&%hOeTua*Cl{pr}-cnPZ$W zV>pw)m!YqkhObetopQ9VXJWLmmVKyqoX5Y7KP+vnoEe(~!daM=98DwyorI+|bv5;D zay-luqQOVC7Mj@l2I^{g`x!8^SX8-&_%kqr&cI_bW0GJHV~}G|2kii4=Yk%^&dCfp zJ07xAj)9XC-1h>X$*!iNtSBcVEy*CpAf_lNs4B?KE2+&W3Mz9zd;UQA$`p2cvO4G( zEm315aVTxZWacI)l3McI+xwYiw5h1Dp}AdWWh=j%OLMD}8>5vgzqXu9<X6{wlGetu z+WbCh%9H2oX{=FaU}UiV|C8|rlRSeIXz!LdBLlMpClezB7b6oRvlpoI0?zi}d2^<C z1|}x(>64&)MIej7LEHBkK{Jw|@CCIjA!~kNy$D9Pz}T<|C0Au77rll?yNWRFU}Ys4 zC&uf!adEl4+#bB#Q|kk3T!jQ(c|pCVFwiLr;QgTjpjHj6bq(3r3tCjs%;2M_qNoI# zYGnik3g~_wc2F1y8XGZ5%<NpSp>9e{N{p}Fc}BsGP9}-A=9IX9W#Bqk1!^`Ag9L-U zgAL@a5q4(KEd(qqkXs1ASqK&(e7uYdqM((|{Jau;5}=Ku?5qqtj69&Vl+b-%kc|i8 z%HUlH#zvrnZ`f+5&g`0LVX?rYt<Ca$3X?=zV@KyxkJs)?Jm#H9iDO`70L=zX2lpp5 z9n_%v%s{Ptu)VF|RzB3HpiYXQ02{BAwxS}eGa+isIQ`##M#mSoZoPoyRZw45@&7l* zy-Z3B8laL~f{}$4v~yDlbVLK_Tn<JCMpiFSeZ$Di1UeNHy#4_kqmb1gkj>IkqQU}v zyxi=p3>u6YptT?3O3))?K=Z+%gMdM_5*ujE2c+G~#x4rJdH7L!h`ffgj<tQTtCh#h zU>oyTCHXk3vV8FVwp=b%H$g!)HSj(*O(_9?K_TP~ZlH38i6QL2Im2Ei3Gi)Bnht89 zBMX_Cn3Gu;85v<4gIQS^7`QoE_*wZu6CZ+XyrSB|g35x>$#(G6__hdb=$0oYiN7zH zB>wipb~%B<$mst!MlSGKBH9ibi1UXb>q9^zJkafuj11hMgK7B~`C$7ZO+jfJyuX^Q zL_~p4MMhFRB8ZEf&7E6bm$CO>MF4m*8WgXfIaNN;`Hs9ioS<Wcz|$fOD2HhAG4KhA zf@jP?BjBL3SdH0*mDSlr!y-lGIToegew4mbn@QrUq%z0G*Z(emQ9aMV$RNtVz&Mjh zf`OMo$3YW*b|hpPoS_vo`h~plikE>`R1`FyZ*0o0ZZ2pnYAz1i=@TZW>=>D#((-DJ zpp_b<>??B{uW6uR1W1}>YGRUL5M@wzPyscfm>6JAX9X{{g6!ymHH~;tnnotjrjdxK zU|9KFrUhjYjI1*~rn53KN&HJ=ob~qwqlbW^z`t_FPC+H%e|tf30m|o~{n3I9at_jb ztV{^&Ks~BvCLb|DG4Q;Wu(6<s2)i*OtPRGf92UaF%*dG#!otY>?@I!c#J@|DR^p5^ z{=Q(;mNk|52ddziKxG<}J(B_hAA=OQ9D#152cOOZ**?bLqoSgw3@t~HhhSO3H3cN8 zGuc}ghlCefSQdxZw)~3>2n`MJ4-E@o<PENIb*%{wu6CVP8=sd48Z-i>V@3w$|34Ye zGs!bZg33}sMkZ$XF;vW;!*LKrDWnGs&Uhk1;6WitMoCav3fhNj3LE@|^b(<&?VO&A zl8TE`U|dAFl9P<0TWUk2Z81AHuLn0Ts4x}gbyc2PA6V@MT6ZACAi`wF#KPFl5X2zE zWDQ%50h(uG+QDQEAIp_w@L+OfyujGb;KrcL#Ez_vaR(DSTpcrmFjEv0Gh;i$E(R4Q zD`a)dJD9BC>P-HBXRZOAiNPqsya~2vkQsKiFB601|DTNSm?XgWYFj#(39^8e&UwLa zC;*@111SPQ=lgau_$bITFsP}3F3e_-V~|sp(&XS3*JcEDUBM*}w4Y-R*?R<uIaA18 zm(VWHWo1o$i;5JxBui5RRn<sCQ!}FsM_XG*M>{(v2@gY8Q6Vpjhy?8*YfDdI5f42N z4?P<jJ&&K3rlvMFrlyvl`jL?rnwC@?6hW)~7+XNia`3=jFOv_bxZq%8VP@cC<O4+@ zsA^D#v^<ne%*+_=YFlDKi6+*vm`Pz;Eogi(xY`wD?*E@m_Kds?{0xc?a^M|vpnJoa zV9Aq#0d$S2lCU!9ygf$9B4{;JV~8JN2{RUyBw@)BloA=3!1c=^aQz~}VC10Bz`_7J zH3@Wr4fKow@T$#bCLho?Qvp665nd54P7XHEp|_w?A5x&QDJzRA3xaAkaGU*oUaD47 zh;ig(D{T)~TPBGRUtK@L(@YZX`*ltApy!K7FfcIg1edSkpmr)~StO$uJ0qk~jODN< z0e%JsVL^Uz0deqwO@iv6s0H243R*)9T5G7xE^KV73~pOU%#<~d%gkC35z#&0#ogM@ z<^`9Ejjm_F-xoJ-Fv@M#(A5PU*u=zu>;`KG3wB2IE9YAwceccV4uNQ9@Dbo=gt`GV z&cn$8ibT+|KSgkTVrCAy3dht~P#xwDM#-#9IRn|5Y26VK^W9w>Z0rI&b!}9*Ufj6x z_l5grLtS0aEGDG9-pwSzz|J7;AOYG42tDY5fq|hJJV*#G+!U2T>n}u=8AT(PGcH@k zc)`O1e4fZpCeRrSLa=lJsscd+;0z25-QZyzAqF93VHI$?5QHQQaODK4rI?uYlf1HW zBOM%_ZJ8wgEw_j=$&F?V|F_)M$-|s664L)sW6)>vVEoM3&Jf6;#^iyVpBZ;BdBF3t z5Q8?;H^z^Q?F{>v-u%DAzyLl03%r7hdB^`daCI90dzrkL`WV|80vI%y9;2D}7_JV~ zVZYBL!QjRa$-rRa1)4wtx0UxXflh!_cTkZNWCM5LL5Dyxw1T?q;Ek*d3=Ap^DuR+y zf^49=huK&d)TOjzG8cxh%*@P%jhU61^_bL^`Iy+5`&)yYxrLZnn7Me_!oov1MVMKb zg}Ge<+hapG__!EZ7`b>k!kHxgJ<^Gg5im9vW7PY1Nhv^9GD440?(YjmJsB%KE-rm5 znSYld;ib;Nz_=c?*Bm@J%?O@P1hrSBK(|^kGBUG>GchrN&ii5lje~*i|72!lW?}?S zQ^kV1_24=hDQinHNC~N^s)KyPC<;HY9d_y!s6h)l34?LPinQ?jGOIXwrC4*DU>{$P zmH+-SNjOd9jB;~J5EAqkkkT<X)ODQV!obL&^ZzH~OeWBcgw_rgf{ctz%F<E->}+hz zj4CK2u;AT;NcE4RJg7C#pvI^MD!w4+Cz*q<;Y1rk2A`N?44SxNWBV4H>*MQWsbipI zFDs_xrx6zI>KbU3uNfgP8^rGHX6Yhq%B7+rqa@7h&M)L)W$G+u$)Ty_EXC)~E6l*i zAn^Yi<4Y#ct;yOB8q%VCY%B~cBA_dvnY<WSSbDudO)<zNOWlk<8mg+QO02w++N$7s z5!%TBb)P|l3y{hZR0DvoItEt@Y>XD__JTq(Jlv{6qDD4qX2D8Asyu8;d=fSqCXU(x zW@i4{N@jCSHQ89)*w_UP4cv6t+1!{oG)>L(%=LYAbbR#HeL#5;)TWz-w8xz(7Suig zM<%$-hFDI;C<@vG!8q%6B$I^aKSL(aKm{WxZ8N?Am&J+>avacgiwv#a;B|`-6Tq_( z;KmwgXn<KwO`VOMnd?~a(by_>9#&5NDo|UNF+@aDOi%saI!IfM@h_}wVSw)i16{C% zR<;N#3o0`H4gVg=xSa9AKLe1P{{M&74@_*J7BvGSgDC?8QyBPMC~XG~HbxfE1!pV_ z=^UWT!<do0D$XD-C@3T%C@2Ct8W~gvvnh)zn}T+gnHr0VfHwIXnVK?%X{AJjhbL=A zc8B*cNo+QbwwyQ5GTLa%rbb5Ne`o8rfQkSHzW+ZM--6G_2?U*!&CJNd2s$0ddxKm+ zgac?^4Z7hFybu=ZGtjUYBO^=#v=0(Cv(?Sy6S-YXMNLouluAIQDjyR&Xj}lApUmx; z%oQ2mMowqv=jRZzv5=MLli?DT=4BHU=3=yBykJ(6r55ha<H63M<0Mx&0kl*Fbe0jL zJmY+(vyAQxpd(_iuABb<pHZGkjOjF^J3|NZ+B}rCg7%E^jLl#*s>o`X;cKfIm>GB( z<r(KOon`>tVXMZF<Gn!@G@`=B#KgeO$;HaT%)!8%3fj00nrd1Fx(^l{4C_E+g^CP} z4D1Yy?5Sv~IXGZyA|0gU<QN#_)Z|nZ<z=PCMHxT~eg#Do1$p=-L6^sZMioGp10aSP zV8;t7i;6<pQOdkVtzl8>fsR5VVcv_aLv3`-tbJnb42&EYU+8Yrw>FZ}<x!Whwm+$> zqNFUpb+(R*lIH*a3?RR62KyaUf?^Fruo@?@8V%&|L0L<w&M42Q1yaLYfKv@<UDisb zi;V6JS~%5!+_MN|4udvMHByZ742QsKba1Kpf0kh_Lm60&E-p1-e@z0b(Zj381*}FN zpBg4Uuo?q=Y8cmp)fi$|!@vl3&w8fQ41x@{TlqmpE_gwb86Rl$dllrI=XIdDEU*Am zEcoE(b)Zpk9tH;RZGmEfto-8I!h*)2_BVK395hv;%xrJY!pQvH#f+JW=_jK+<C>4M zZhVYM|3cm?+Kc|11L}`};^qp|B}RA9Sv-jS1t|GMjZu=Z599~t&&Ym2Q3Hy<43HWI zl>H7EYP!K{OmUjS#wgF21XcrDjt@_lC~3}$QIc^1Sd9g;IVfs480DElz-p{;s*z)q zWVB#PV{~V5K~{s}W>ZEfMt{&+VHO3PYE&2{86&`IK<nh;ZbmUjkx`OK1gz#AvN?#d z1~gy8D9M-uUc2mytOms#h+Uw)C!j@U*zE$T@deohTAhv~PC;v+y+LYNG;!J`!zjt9 z0#<`N--<FyGAe@Ad_gt`B`#DL`XS-N02+?L?q&;yWenBewcTHl%|Y=yXn#s5IDAm{ zr=Zwn&M42M4RQ}d0J1r#Y8d(%<3MT{d2p%$g<%><4Fl-pUhHlL`5h9cDD@DEU22R6 z7|WPa8QnpL3L@eHO^q~T8RG#)cUESc?lEWRXUqY+Cm2}`O89UwN;2GGTE*zj5RR+{ z#V%t;NyaEpI5R}xR3ph~%~-?a#puq;iBpX!qa>3C$Q%|MoN5>t<ss|!L467we&=G8 zWV8c^k04HSKz^?Ut+QvWLso<0cV>ouMqiM780(SMp!i*xQIatYlztc+kkz1=14^q~ zK;g_d374AxKN<QNlbDhi-5Dn%t3k2L`2PZiGR7!IHwGVu1+X1rOgsKB0QI;)dHw$a zMrMW=jBX5}2zf??yz&28j8P1a7~L2mu*x(1U%==EmXE|LZ~k9^v6eBL(T%YVA&+D~ z^M3(GUyy#rdW1ZR{Q`_>Aonr$BIJ?utNa&W+ya)LgiZec&;J69Neqt}-54h$<YDGB zFoDkIWX@+&Vo+z$W2kiCS778|;RAIuIKZ<TkfjSsT#TRu$jOk(0BSR_gAVKgZKg(< zw^D;EVq*kfQwQC?-RsTDh@>#mK}bVGLr+6bO<7o3SVdJyfSXrVTNQEzAhhEGnXy9Z zu^Wp**Mh2pPdQ{~&i^+Nc157MQ?jynq<dCwgrlRgO@x%2flG>M4EWYS_TSLE0`*KZ z&5*nJ7P6`~xt@Y9p@AL@3{3y;{|DUx`-4G`!HVIcgP^1sXyq&y6El+r8xuDdXfYe; zYyf=*HV#H+PBv!fjWD3ADnKV}HF+~|adE~oaB}u~GjMY=#DiK3-3*|m8lc_6#>8j? zZ<_|`g^XZGJ0R)8Y7Z+bBdDd@46zZSD>BkS$kN=%Kv!Ey2n3ZyU^9ZCUZ66&GRmDq zrpBV6;SlJRMBw%cIFQ**Km$sU8AK+7D(F41tXwRjqHM;jMw;B*5q#VtqU=VjhFU!Q zu=`@8CqgcYW#sAV0o@E+!Ndf*#)#Q6gB?V(azgHn?L3{7&XSy&1sV$m-)+Iv&IAf~ zYlasNg0fOfY%CglOw3H$oJ?HYuy8j72OuN1aOdU*F9m^|GsF-NKbrw|gcK;k@M~n? z<OChm!o>wS5(pG+4yFhTk-{Es7XvFRC+Ii<G<}hg4$21lj11<c`ql>4TAJ#r%1R2L z$x3li5g`F~Rt7yrJ<!n(;A0%YlYih-)F25Oa!nL!ln}V=lbweR8Y8^?5gf1>;pPG# z4P+SV>J;hj?v6MrDwvrC91+&pV4C^wE|g=VKz+{tKN%Ppo0<MH7%<FqkQ8TRWswkI zVq@iJWM)(5Vd7xYXJlezV1*tsqQ?n3qlXc6X%+_;BO^BlBPd(2#51t4w0N_Fj)00~ z09_=;!^q9u%<UuXpu@nzz{<wLnvSUvQ+cF=7y|=?0fT{_j+Umfps=bcC`I$~%4!=6 zg2!B-0j6wf4jKzJ5`!%h1<x}=20<WqZHeY`azMk0lN;qgh4yxKUUq0g7T{%MWd?;0 zb0^A43NAY!!Nzu#fr0t|M+OGwT}(>gvsfG$W;%!pax<}T+3HDhu<){IswptCFmS+9 zttK~!$H2mo&d<op#>l|R%aG2)$i>AN4<6ZQ_2%PbXJ!R$&6jr2#iEu0G_MEJ09hK) zi%=iwAZKpQz+moR?qF?cYGP!-pv#~uEG#G@rlKMuA^-{_Q_y|^Gc$A8jp?9ki9mBC zqM$7VY~ba{N^0uh<+SRe!ls}c&n_m$3TA+oo`gyZGaIuT=px-(WEveMA;x0FYM>u( z+u#`P&|v#F&&`qDs-AI1uAj4Q!w+_8Aw6r}d!EqioP61&MD=ZW&K>3Dxb=*am+>#7 zu1>wLJ0q{QUwu><J3Ai(6DT~HDw&iRlo+%bS{wxB85!9$)nr74__$d(Kvz3LY9D0= zMmEp|>2(Y&Ol&MnHK3El7~)yknLxKafd-qJL0vL+G*t|stB)W`LF>jq17_fR9U>hh zRg@VSl(khr7iLR{2=nrAurnwzDnU=^6h#UnJtj~Xp@gNl5*xdin7FA4=n5nWAr>PR zL+x<AggDIzX%Qx4R#PqTJxFSP?re^|uAu9X0$63m%&j?39cK|0WBvVyO-9VZiu0zY zmZq1lC%Y<#XCnjC|2zK$m<*Vd81xuy80I(#$nZ09aVzpLv4PhAF~Aa(KKM{9aE4>! zU}WTEV@zk@=7yc2#LLLV1)j9-_U2*a<ZS2kk#;b~q62(83O6@6pF)aFR9%q{QU>}A zphC>Xz=lDOK~G3XLq!FY`S^HcwZ%=5G9Tn>5m2%MpXaI$T7`jBrKqWk3LAl!Rf6W| zL`B3xc{!mOk&oMhheg8AF}bob#V$~sjggfbR(`SZu+21ZkazbAa$$7*P{|6)lPpXg zp2`MY-JN}U3W6rW-fSR2W=2m&ebYFbn7o)c!DP^!CgcCR3=H7=OLQ3KLz0e&ga8v0 zs{$h%lQyXAV)hbeWcHAD5CP5oqe`*Bj-64#5@@WfuwVuqLDLKhTMaDAz+nr&#saD| z(m{xUfkB5sM@dLkRYgQdND0*5F-8hVF>zQng_UA#qDbMWE*i=M3ph3&Ht;1U7KrOy zcwiyN$Ndx>T1-rDk`UL?D1rlvWh=OR2Zayl?h`ErZwC)iMiyo<MkW?nUM5y1O;GT# zc(K9DbXImoMh;d+&{_!Slq@GB2S+mp=mt0~1}%_hRF#C3xp-x?jZIPNFvu7)ygWuJ zi-TAY%?K_H4+9a{B`U}z@iS=C!OziC7J9Er4YU;A&H(nuum9f|A2TU2STLkJq$n`5 zvM4gLvq~_sv74ZrG{nHp%ErphR>#1`#LC80!vMNmlevb0nUR$lynzLp3BY?0K!^K+ z=b8--^mJ8~<zzsWHU}Gn1)~M1U_hC3R)e-em7#aMqnt<sx<A&)4AiP(2QBWqV-YA1 zzG_6=(uCJVR$h|Lm_<!RG(QS{PMD3Ku%VE&8mAGff~;T(mykdJ?79(Fepy)~2QE1s z7cb~pVM?0P?1G#^+Pe0<GHRgHY8d~&{{M|Jm}xSD2`DT?8Clq589A7>K+6RU8M&E^ z7#X-hcdM|mHgkfGl4oLOOlRQWVr1gxU`huyUconcwSrrb37|6(!C|1Us}5ReB@enC zKtfzZn4gb_o0FZvgwceTS410pHWhN5i;0`UPpT3{if=WfTUtQJQL(TyLkj>FP8J_u z&}9r9d>qgkm_vX=Uln{+1Lzd0EJj99CTC>q0G*ZQvJG?-rnM^zvxT8P`1S^HI$!|p z$y^Vf7YlUoV`SvuR0J)P5anlLf}V}S&dA8X$^^PggMp2aiJ5^Zoq>acGZvIJ!3(BX z;y`z}vw#w{3g}uxA!R{fB_S114h7FSfu?f6%?LGhc12M|Q*%V|Cnj#LXv(;vg-e(V z>H`r?kpf2Le-+&lqEK&&X^Z9k`^Y5Ww1)}YxZvTK?_za~1LQM4&bcn&b(5i>z6ba| z057I=*m?ja=z0K9|CCXlF&*5WzJ|Sz%fQ5-^&fOb9B6HdB7>8IJ?Ih_AwkeKXwbbz z?2Ig|j4YrVL78JACz*lI!GRq6CN9RnAS*4VD6R-v)GI8i0h(cE6lI6(X@RXBPzTMl z34^DZA!FT)KVCKX+qM_G=R1^TBpv<t;2LbVkc7ibU;TXl(gv$szw8P&XZbp>f77D; z{bOVO{XqwnFbMqL%G|{CgTb89A98n{q$nd3qXat>1Czd%rjQ^j7lWArBQrY}i<h*6 zq$ndBb~)&7H$4VM7A6)(raE3m9(JA<&^%&`HwQClD{DL(Bluh!E-v<1ZcZk4_GWfa zmrOb!!odhh7dKX2oQ&-3&7giAcRT|(cQ-dkC#W-L%fQIO#=^)3vJX`!^yoK;-LVWH zt1%66K+_LajYTKOAMCLh`a!3Sf@aOk8O%+LbhS0qm4uarL<I$fMZuLbXoe4T!k9UD zm%E^dI3s9blQA>6TL-?k3e>X`R2F0gcl;oS^r*9|L<tB%aw8ifOT=Q|vr?{VNlD?L z1B-48h=Q}Egov7;t#_fYl_n$jtUZ^1rzC_KJs54zo%{D!Oe{A2AL!D@)VP1I8KeHa zW(Q|cHg?e9Ab4g-hDm}!7_{C;NRW@0g_(teorReNbpI~sN@~z#8Z$#0_^59N=z?I- z9kjxN!oq^=koBFS;7fkN%RALgjYZi-8O6N=egt@f2u6GN&7kXkH@i<3GBFXF%)rRN z3b_l9K>}naCnIF3CX*Lv+yZn49SZ|!tp#}A4z^yCfq_ASK|)YaL{(XkgI5Z)rWDcx zhK@+6nSw1h7G;zwRMimE=jAg4-8km!8_sC&9%W#_&f?6@DeLJN?SAtnsBB_p;QBAX zl*XjQAj6={pv5rLflHE+k%NbkiwU$x1~i<Y#mUCR$j!>c#Kp*z$_u_TksWllV6QhH zBNrFA(gj~%2R@@o4_Pq-=r&V`4p5PeMMI>6x~httEF*)4x{8*nmZE~JvYfI6^x9c2 z4)FDgGK@0(yx=X0;>MzoBdZ`yIM9*{V@Q(()Y?^41MRRiR}>Rt42de`wlHI@NPslj zKsVBW+Hr<nu566T9By_l?kxXqFgr6T6&ATQG=m#!cNkx~-Skv8@bd9>5Bis$5fqgG z3Lns2J3pDc!0YMcKq~}5hwpK+Gcj^7F{Xl!QUjeP54%RPo54q1jFCZFN=!~%4s^IO zWF-pttT<6dQRsPluowdEM+a@^7hz)qpRWwMql8f-E7#pUl94gO-CaM)-P!ive+Ty5 zXeYPx=g*&abFqjrarZEHaj|uRx$PTMFt}dPX9#u(5Eo!#VrF6F<Y4k*XXIe?1Rd|l z#mK?Q$dL*vW0+$h4rbuwWQYeHNeHe(^|UqB73Ae)rKKb#Ks6{Y4<`qM3Zn|twQ8m& zpcG|h2EAy9T~Q5s#SSPoL_|f{R3Yn_OiUF;z*p|*nsFPbHoZ}?<zrOivsHf6<RxaN z)Bf)hXqV={W1#zYSeV^(-DNyo1-&gy1NdD%twY_InakV$fbQdAVPb~(E%d(?lL6BY z22}<_h8xgUvLXu;JDUt26EnLQBNMYIXkC(*w1Wg#n2(VKNmPcBh0zmQ_JR(TXJleb z2CZcWoiGYIX^a8XCu3k|hqRZwnPKIo257fCR<+=3ctIK%n3+N99bihqC%1yuxb=F2 zY+wN`2X6)~;D=-l(B<R~V$cKY4b=@n2iA)yt7@o&uB{eE3}=B@kn4XSQ{ASfprwrJ zpwTc;jRwi(rY37)16is{mNw8G$BJt90pjdJ_U|D>TTDN8LI$zAymOU{99<xrjor9F z!(BiAJ%9{srJQB}jcZvk*)jcKP+>4+cmWAxAx=hS4n;-=W=TfST{<kRpy~}O$c`ik z4O>;vy%el0$>2lK8KB1q_j+@&Gl9=mL_I3qfPopbjgY+#yCw$EEmWZ0DezOvr5!M| zz^!0lVgk1bo534e;95XOUaF}wGU#fn8mbv8$b-(o17$^a(BZi%*v>fz&w+vl9>L2` zOih(R$6bSSBxLEIh!~?V(gD^w@L*Q~onVYPfOYL}U>7{lF~+VK`2Smh$F9^ErZ|X$ z@3Z4)Vq@iFWM+dcWQL7gX)|yzGcj{8)qyXZ0B!$;_SsOztr)<g1=0?haMjS^E0`{% zK`V&bNC!zq24&C%(%{SPK!p?s8)(rGXgNH*17T_kDqpdTT7ko>2AcFt(MGCtERR8x z8zbsbpDzDOyTE(dLHl#QfX@oFVc6^-#mvaWsm{p7B*4hRA;-wh!q3ReE(^W*1XTMN zF)%T(axk%`GO#c(v#~IzgGLP);u*QYqbdwsTpaNX930)C{045Hw6pn0JD8zsf(}x_ z3cg-YiwRR>q=TZN0cc><z{b!<TT@Y9MoL@^bSE8X*C>NNqdurt0lM_l*c`Or8#0;z zOEuuUs}5OT4xUQ~WnWVhq>c2TJq5z1p>nJ|Zja!JXmV+FnYVwrt3MMXi&;TNX=$;u zmxp_xmk*PYhNk<!<Q=f2RBl&Xq7<kV=qAde%NaPSxna6jc5-rNc%o=-0%#pJsJs+p z`oW;YP~jjbFUP~e!pH!+MMe~~b-)WU&<t8&!otAF0^0M;#LScox>30WwA~prNdmsA zLD~Vdj|5!}3wYrh_zr8h%18&$rY0o@C1D{|Wg#h0V?<a`gpJ+Uj>+8Im|YySvH&Gl zv5P7Tu3=_mVUv*LT%CS%lNCG+<agPIGyV8iEMOwcAt%qZ_37(Qn6KS_nI2{O0rH>5 ze=CNYOg|We7-Ai`xEPt3L07AT+9;srt~3J!3o{D?GiXmasHg|EOA)tfV3P&!vubAc zfp5YSQdI`8NQA73Kz6y{T11{VW%}_q0O2~2)4*rfS}`{<DKQu@bUE;=$T4v-!}2n0 zP)wD9i<ya;3zU~Z%L*BiK~*t(JSPVesEq__R4{=@2Q|^vf!k0Z#T@aVfsJ0sF~QAD zKH#H$b#*k=l@(=Wq@~0~g@yQexw$yl7z`K<pp`eQCV^d%j-a8Z`NGCq!FigQ7n-R} zuv`Xj8Xbj{w<EFL1s|9G4-|2b@L+NUkC)au@QE?9V+4m113NPlGdn0aIAA9mu*QQn z`?q?7PS^*Bg&Kw;&`>D@=*9)`^#@Re;ERkv_jZbkz=HrfOp0`l2Zq<hM8TeBya4lb zMWjmvcu>?hAqmN=;m9|uLp%uHg9O>js>GnmV9e0#AfhD6#Lgzd#>C9d$H>GCx<eOs zRJSUqNx{Ozm=0+uuyR03E?85-n}LM|+;rB2sRNG)LllEXdwM}-8>B4(RU7Fbt*!>T zicQT}-57Ldsko?+05>OtDx)f>2nQ`&2c7hYQa*u7BUrN;9QmLoGo(=g+Gflcl3a<> zqJXxX!Q-EXpfSz}&}b)<QdhTk9%`dP&_wtSGY6>Y3?ASF4|RgiJhB3haVo*jgasYE zArHDwT9lE6RfLh51=O?<W@cn#Kof<wEfg7;7+D#aSV70}GP5uzgU7$vAj9bl&>0EP ziFPPzKvOwjg^<B?h`LAzQAP$iSs7`_rHdSFpmB82;&4!54mqP4biy^b2v<X78gMuv z-{Fi@4uFR@5qCIWLn;#_l5`wEZCFMI<NsFR`-H7PXAXh9uf@W|%BZO<%FMzFIyFaz zk%<|yor{?X>OIKK&d`d!o5cqd&FZS418O+f7_1nrpzHc!!<Hhjlcm{F9S>SE3H1pm zdZ7n`{DBYVN!c13d#K4u!OLJF4KdgVAmkE&d?qF6V4k>~oUpKlrM8-tNFuCUc41*b z8UPg0u+VYw0{i*@<NpGT6PW%o=rMGIYIjBk&{-=Yj4Z4wjO;AJjLhuH(Aphz6uKIy zqGmy=-N8`@O7$(ERFA09RX}2(m2T-6I-qw4w6j6(@YPULl$Vx*AO5Sys0SJs1>H1+ zxUd%`XDCBYYJ$YOnJMVHS@=E0kKq9{1?hrWq$`X6sqKM<Np&6Kz<(z2?Zu#ai{ZZ& z=>AOxImme$tVm@c10x%_@MB?wj>v<z7Bqu4qJVm1(1w{DqZ}yGk;^h>V_`WaaZpVw zY|IR*Xc-fsrP!X+aYY<Le9SD&0zw=`ahrPJ?J*{ae@Dd3j06OXO~n{({^_+lx`4*0 z8HD~@F@9%~V2}dcZ7V4z%*evP%FW2c%mo^q^I~9NWoAXxtL$t{pfVWb;AUpfXe4Oy zyAY@W0IL5PnX%OR%EF)nyBWXk>__At-bquE5AB590{ZJDqP2YO8lw;++o@Baa8v(p z1zM-iAO><5BO?o|Fe5Vq%weEq`Jj{7k{MW7SYsje2J|FFW{AVY7{tKtf(*<sDxzi& z@V%gnEB-xURE9_JzvG~rH<=`y{^hm8qSOs^+a@SoGcoA>w_?g;Qe@C(Fk|=*=_`pz zGP1BrFfy~SF|u)LFtUS=dtqnwl6F9sVA5n{U}pu*+z5kDvtnl8WMk$`Wnkw5E%;3V zc_N;Hm9^KKn}dms4YFDubTcKy8hr*fP7Y2s4p6HNmp(>NzX&u92hs*wltD-bXavif z8-B$G6X--8d0ibw1|tI<GhH(^6-5Pb*NLB-la&Q@EDf|t0qq|_wg#J<LpImJj&=dn zsIVbB@U=jYgKC)cjO=9vS(N>pJrnAhqpeJ}d=#aX6HJogbflzsq&T>g|E+S4_D}IO zKW6J?@1vvT8wA><t>A1TDc~e59TxZRPCN9taYkmy=4@kKEolFB0l1x^&#)R2SVGK< zOze`3tW5lj%&Y>?gU6wQ93Vk9h#<U<VFtAvQy|?=Mo@nh)Qx9ig0x1OS$#l#P$qT` zb|!H6voN!yfIAZq4WQe#dO`bqn?WnN!NpZKs2q|7P2Fl~DC?`}%gIQH!}}0Qj7p#` zD5%<j_90-w1qx6|*Av7-?>30o`Af3!xxs=<*vKB-`Ls`|s4Q@IclQW&bz)M|Q*`}j z2n#4%FMH@MIi7{_30dHaalq{sQ2(nGymrEtVVZ-uJR=LU0wWWPC<hZ8yDlRuqaGsz zE20O=!UAr2fJ<ZW7-TQ_&<OBqmTr*8;g`dLdZ5e<EKJNSpxd?ZtBrJ!HZo*nurxQc zHL}&#R8f+Z78c~?2DMy44H#DNMg$Wx*qQ9$6DY*Nt58fpb6Bu~96ay@8u$dKH51UB zhp31clfJx}0t*wHq`zGXXx`Rel8uR_QdotXT}Dt`LPAndik(yC-%aSklMk|<j`pb6 z`}y~9vUoDHOUwUtv{nTVn4(-i1x<I};4@&f8NwWbMHrcxlo=VAL6=3#FtW0+crmau zfSR|UPAe-5Yci-Y2M#jmh8<94*3IAp8mG|IP}Nq`R*(a=O!#;?*+D~Z@GyW(QHqI* zDne$fAni4fk3osVl#N-5ja^YqjnUG##L+t2-6h2ow%klwl1G}IOIg^^LC4$PlbunJ z(T>ZmDk`GR#U|I&6tvoG2{cF9df9O@J_+=20i8I?z{sHe-wJ$(swqRPLzFlpGm``( z3o|bxD~mQG8!HPVBbyN;JEJip13SAHbfHWt13L$(9D^TE)(b!Trkl}+k-<PuQ(Z*~ z)SDI+W@lwEWi$oV$e`s#;2|#1Jv-3*RY8#pZjOOGinwOg9K?leR$_c;=%8a!oTq4} zple<nZ56DcsOYL+8SG}^IX%e6JWLVl@naxwMLKI3%X6~wSsS`|i3qvzi}>iMdBhlM zNC_;1dY%Ea|H}%z-yZB=Sb?s{2pULbWYT72V>Du9XM_5e8GL>+!oMsm;6(}G{r9lU z5Av^;hKv;GEG%Ab4mOy7LA$ZQV+CfWCd!~K_@H(fXvKj#XpI$k^bdSdud))-Y~&;( zd+>I#nI2ZI!S>cV&KmL|=`p$HdJ1NW`DIpm(Bku$t=Dn^DNUm&4^>??H9<i)RWD~l zOI{XE1yc>@Xii(0Z$W3p82`6oTE(QqpvIsJieXSY9CTtC3nM#+G9w#kgBcsE7iiZ$ zsK`rYVB=(DU}H!Doy7!NG6lMW40`JzXgilWBZIb<x~_(<qP&bWsLchw>Ryde4OGg3 zVptH|5JfxF1GM2!5IOUL2JM-$jO_Vp<6Kfq8S~*wCcTTCn7yH%{5Qqkll|X&M!RFS zUW_7{Ww3<oD<o)B68di`)RT-Xu(Zs?;P>B((VFQY12=;_!)*sHQATD~F-8_<(5L}d zK!k%D0}~r78>oW;sRY1{Pf)+1#T&FB2fTY3R0BZHpT()V3tctnW=EW=(aZ*2c?xj^ z$YMq|21d}u0ibFI*$JQtHAx;GMg|^v9(g%gDGAU`Opse-L3s(X(HB%En3#zpSHd76 zQ)R&>5qWtLF*!L$9ccCtHgqs$dI&pG;Ur460oq#z%@-@d=Mj22xT`a=GN?&0v9NM8 zGJ>uVXB1{+W@7aMAIZd=44$V2ZNu#abx^?t9XR8wD9OoyE-&L`XV7HS1T|v8caT8# zxgw=<uq(kO9HKd~)jiMNvA|tGnit_@87Hj(A3uK?M+s>OKPDxss`%s@D<&ojXw2Js zE#MW(NJ&iR<MHGHEe`+x_`emSJkwtW4Td}iVNm}|4%Gh=V`OF$2e%9$*O1AAPVQi4 zL3F^tmkEJuFz`V)(jc!fvch8q<X@O9_^uTt1!+kUA$~p%HrRO^$lVPQ&^k7FYDe-b zN=HM<QURLIg^lbv<ay=gkvkb4wjT0Krf`3Du&}FIGwyKm039jKz{ueL-->B5lLUh@ z=qyIis3{+)vCPTH$P79AMcRQ+n30WvlM!^T59lx$XzK@b)-MwyQwj$=xLFVKCuBkd zd_j;J0|P4?D+5~{10(31bC@ayX69y40S{i4(#_%%=^((sz@W^atR$==tg0*s-cpE} z2tlLjAkPaL3qtOoVG>13jjFsXQZXipNs;A|uAr-hk(x2?TI#WBjPd`LH>AWdii7(s zivK}nwgiI)L!?6(s08C@WCGPqOmd8DjH-<6Y-)@Q>};T;eL=VEq$AZ&;Mp1Qj4GnM zR#ude5(6I(13tY$gHZ#Nr;y8QHTZ4z;616J!9hfo1S_L`eC-zf`^8wYI5j4}OvY3k z8lA^%y;ciI>6sX5I`(_I_b>;$d8e|nIzr<TvM1RbypJcH(VYdfQUv?n5zzh;Wu|mS zchK2vIQB-!GcqySfz+^|>`z49uK?cD@QTr$VH5H?4HPw?eJbERIvi@qYEbqoa52g= z`~mH;VDQAH27F)5LeQEJ7M%O<7(n|cAbX)u_ST`e$CP0vWDg395iYwJ*cjy*7Bbyr zbZ5c6SIiWC?~NHwbHo|t8Fqr*jC(&BTn%eFE_41LV(5puCkt5(>i#W;eui_P{Ut28 z_nb*FtYGK`sbMWdHU}jxK>M8d!EVmMt%ji=vd@Xd4yPJZhJNTC9a~&#{=a4DXN(1> zF?(EU7(n}PmV?!Rjs<|HXAC!|fZgnf(;QHm2k)t3aY9yu5{AkQ{ft{c;lqNm2M$Gz zB11pq{tgzLcYJ{S#jqQco>_431LI=ohwPVP?m~7Cioe(xB^kTH{sQedhx;8RJ&Q0( zGM0hW;NEv-$|%j~4^qR*fzvKiMoGpPa5&@Mn+4xf#S)3r97#rbMhTEzpfeG0lr56r zJxriGqd-@&!2N~dcS(lV(0mHIT?4KL#qXR9{fv4byIA6Jx(5{R@u0Y11YL#zHwPt7 zL1#;bFi&PuV*r(PptIs%GHhbt*vQPdVH0S}6lkw1c+DEq4<<DRSI`9~jD8G189?HR z{{xspm`*|TGO%+mW=aK%hyD)$tvP_H=U&W|0~SyGpNmk>$j<1)(E1m20}wOg4#*8a z|Nk?D{?9?^1*_@)%g4aEk%@7~Up|n7{{LsN{V%{2$-IFHa<-v5Llq+{_}uj}MhURn znULHL+K;uL=^x}Qd<J!fDuz`cKQNRr?0~q5fq`i**#DsY*zAmci~?B9_{Jmz_P;ww zFQXsBW{BSZ0Zenj{#OTyb1!CU0E?Ud4?tGWy%==Y!~g#bApgVFgZ;J~?0=Boz&9X) z*8ly_Md$^qDM3}kz{HUFUjSq;gFJ&eXvLE(KN~Y66DuPFBlxTc@RVE=Xixz%4hlL8 z3w+K-JA;p+j-r{05*x3SHY;fG7B*IEqNZ-Hq^t}&Iu5jmm7QHoOc-?HhM=(m<1Q~R z1tCs3J{2`nHBBDg<9D*>hfVL0RxxhrZ7fY>RO&V`Wi@AF7M7HfU=3qB6)>l0-eys2 z4h_b0{jGm5z{g62n0_#5F_<$Pau5{aWMX62R1jxoWsqlNVTH}@sY4b&K)Xed0TPCI zX3#tjc!&htPy$WyKqg_e(UgPRQ=kz7$WRKZ76)z6Spo6ji{%-Zn7~2Q3?72Pq8fB< zu#Pq(gR!BuxsExg^$lJ5pv9;K9aDgALIIDZ7(+JhfC3FXI*J^q=0;}FdjUn!)<3xO zvIrU|N~suod%}ZPjRQKGg4o7$?JtLigc_GAhlUzbIQw{l2ckeDQjmOT0ZI={Y7CHc zxP~zdnhq@xX^DZIdkrJxeuzW{2F4F8+DvMo8%7w}*|##9GwfpE*vQDVVHYTify^}j z|BZ=}xsXW>w3nFyq(%m8Cc55jjHU$jZex^%=>2cO_yL?>KxYDh+@k{)H~(+J#K@!s zvx|ETqb^uH@xL<@=*DTVI~mwmc4R`^dH>xJ>KQ>d#@POO2`MA~yaagwoYw>xKQK>& z_z|4%LC37IGx{<VVaeYDOpHuVp!TaV`o=LZurpLK>;ny1gUkYj7r2Z7?b!yEkr%;c zFd~&R{Gh#5%(Ix(!0kAYnzal&L1D_cVJFB*pfClU$=b&p&ZGuDj{#Kv-M}yhG_EMb zw3JB=v}c=vjnO9u;%87f-3)dE=$r;nIVFXmH;{pWNs{>>lN$JbM35Ua86H5~0J(q- z<d^>eOwHgp(1w;-v%p~uDzhcQWgKWB1E?%d0E<KH?O{>_pAW&#ki`%Pu@`Z-#s9Bh zdw0R?Wyt!U0I`>81KeKK{{l$%vN2SFx*-4mGl>5eU_#i-#!$rx_3wXoB=zjvYZ;5d z?g{<xj-(zWZVD3r|LMO6V<OmJI$(dT2bJ^SvzI*>EtnoMse#Uk0;QGz3;(==rj=Kq zi245?bfXZXEsG?R8Uv_(&CcG;unOWwW_TU=AGFI}ggKo_jYA7$K6^7mBgkIRS<6h> z;JOIZ?q+8wWB35ki<CB8L1(Bl-(yk(-%18jBMS*1Mnw34>e6hm`}IKPb1!Bp0h<qs z7hZ6@fDT~+#S7TK;JO4^{RYtef8hEvl?kpMTz_Q!Wry5Y@)vx19V87feg@kGI;ad} zCZxRZ`5(Zr1#B1S4n%hD#f+;#ZutNGe*oiWaJmJlSLa^L1ZtD9Gy42L5B4ikef$5- z{{Ti&=2j*(29O!*5HmpT_<scKXC@Rs7bDyOQp1q{R}|`2QAphUfAhb9Q55DTkedHT z{t7|W2tm{^B>uNRm;)~7z~##STmNksb&&LW{onNG9z^e-doaDAv$DbY3UrnTC|~7* z{e+yiLm3#D!@y|>bRQf@O&cg&7!v;nfX>-wQe!ZH#@Q>dc<BEC<}h%123F6#7<70O zDBKwsn5Kj60-Z?$GDjJkT}+Z-y8=OGGWs#x0h<X*AJf5c20GUb6lcr8;-K^)3APKY zo_jG<JXk#Oe<~APJt*85PGO{j(Eo`{aJ^tPwSSo*;q#Xn7C!$i5axixwgzl|=zj}@ zUa&YMU4qKE3oOb^YT$EC*x9!*wuAl1geWf<Ky`~cxNZTR2@X=D4>l8`mj$kOGfXcc zA42s8F{y#hhhSi5-^_@t7gVQ#`nI6@ss>yyF`?CI$o6h!)JC!wp?4c&BSF2}7&X9p zLFJ<sIRAsrUjgOqn-KpZ<$uT;7f>5C7!;=rWehKn^n%*nV7-if3{P<A1(jc5y^MYg zpW%Ar!D$K9PY0Ft_b~N>_s4<sf+i(EYNkW<{tsY^2d5>_ePy7uR0J0H{2u^XYr>=k zzCRO`|5t#;L1`}@oc}@U)fs&lsu(sgLiI6lY(&cc3=lIw^%uxaHAWv}22js{aRsa{ z{hyAo8=U5*{pEy|$A3AYX-?pOKEfR!HUD4y6@;csL8uzz|KAwDf&C8}g8=#M2-yF~ z`4*&R6F4u0fx?~9j{)L;<NpDS-<Ym2sWF&=#JLwULDB(8d=oe?fz@*_W|9K?A7suq za2$i}V&A|h3$Y6+O@q{I0{1h(df7KHd_d@B0i|h(-i^5QGK11IMDIqp-T;Ij8Ppm5 z7>+>09aML7Y(({I03*V$Ahpw>euMadi-Cbj5gcBi@fc8e?S=RODV>7OpbKV>WKsj4 zW5UMhXIBAfJydKk*8cyWf$M(&lOj0Xm_yBW0Q*tke*kDt8blu`wwWMxIM@F|gnCds zGDQ9rhQ^~XG#&;1=Q3t9f$~5&*vt(K*T80S{kK5q1(z>kU~z%}#*B3^^^EL{UJNXM zu0qWGa}{c4)c<cx4WRqD7(nL~f!ZuS5WgbDm;e87OrlJ;nAAY$u`sYPWC=su4ADE0 zNe!ZxF_57Tq8BNgAbRh^^fCs5lKTJu3{n3rm>R(0V*&Qd8b(OJ*Z;pMlPHq}L_OHe zX@9Om-FzL{&ERqq>}K{YjCl}y(cKI#HzPpivu|O9l(}FxgVPv9?<SaDq;eDNW^fvV z=-mX>3+kXnFoXPS$-n?=A2Ikt>_ze~Xt4MX6Ue`y!!p?z17#p##qd9XDFW<YOOSiG z7c+%|<A~vZ0BEfalN#v!8E|?~1B-+25CEq^&^R5a{;R;S3v#ajsLYB2naSwKXaLds zKLC9HfEt4pNSu2y(-*Kf_x}K9b|z5U4XmDfG1Eq{I12*<lN;DBYp}ok7*1o@CB(qM z_#a$8M1#y^^kZ0uq!-lY1?y$VVqk*kMT!fEUQqf0>1AWc0^JV)IwOyPfyoSPFX((8 zP(C{Z(TfzGjQ<4~|AFm|f!YhH%hebdm_)(l3~1aCl(vI0^nyky)`QC#(2?kDj9$>V zQ2QUiBnplTTacODi<yGKeo_A)09yaUqy`$30>=fUAE)*|7e)OBMmebZTom;i7+!<L zL;vTZw7WMz(+{M~0F_;!F*tUHtpD{4;8KHW1E|yh>jlRtvmuij_^t?cMt_E{U~zCb zfW<-Kz{cng+SdL5KZD-?Z;TI^g_zVp=Yuh@vve^$0;>;YU|`Gw^|2U1<DsCioq*BD z0<|q7nAw=r7;8b{!1jh=4_GgnIJ+9ddMx5>Y`>)-X&Y5N8#{+GR&lmJpo1&G<2K)z z5caaMb3*$!5OZRn?qOs5D~fCmT%4T?+V277$2xG`q{6_!$j0{O*f~h;`2QTJqyW1a zO%1ym4mFRNt}v)EsH8G5va|jEpYk7U64MTdNzk<V8lonbfsvh^<9{AjHRqVFg3Jj3 zne*p=!2k0g7cuSle;(u_s5$4Et}v*xbN&zbe~yujK_w7;A}+$N|IZm1m@YGGF{rcs z{a*-C6N*cX8iPtG$UR&jl~B9DzW@K9LHqwV#)IJaZG^_}L~xj(iL<LQv|tfuWBdIc z68@;_+1NRLU=?Tk^BSu-JLemSI4CY0!C|No2#&9vpipLHgoZNM4QOiE)iz^Sa|INJ z3>pkiKqVGD#u#Ct2saBH)(jd9_d)95v4*McDAc^GAa!h@m;>93VIGP)NF0J{Clqy{ zHmoE#+(Gx2va`KmI1P3WnmD@}Xw(GU4;5fSsApsQtqBP)RP}7^97b5h+5V_v6=&xJ zU2z0AAC!MU?qOs5tAeZ^F3!#c+CU3Uqvyc!r0tC_o~}dGgfK9&;fg2bSa7&%Gu#4) zD=cSWgg<i_RNZBeI^6NZoCa0*7^Dt&JTb>Z)!hN9!yZqde8!v)%4ZDP3~xZ{Ao&eF zKEdiTq3WK2)Um^I8>&D2KznP!@!rb7z`(}#h8+^l?x^DIYQG@jj40xuatAUez<??a z3Jq}j5kwVd`}02$EG~p9&d&KCd{@^0YhZCu{DR!W&i3~|c%170DO7QGuK$pGi$HCc z`QSL!Da8}-j58r>^6|twlRh~7bs)11c=D$LL><F7aJa%sRn%|=l?nC`b&R09EZA|! zI}?gJ-0{xj2#!x3(Cj`VC}ax3r8$bdpm=9;f~o_Z4bP4v-a+-2Iw;;D{cN^33|qkQ zf+o(c#;_cVI2+q<&@m{`dJ$m`8#{+IB%Pp|!^ZXpbPpvK^_-yXQK0<${~Oa!a6M$C ziHJug)N=O!H)bJ-8Ye_NVyaoebd^D!!HD4oD1PAa$b?efG5r6=ycntuHUDC&D}bt7 z05%U+&SI)7gsNKzQU{MmRCS<sx;`k}87D&Px1HedMH6RNV_1VloQ>@_wB3QKo{gPD z0TS+L;%tAQ{T?)Nc1{sw^`QI)at|BZUue8S)WgNux!54;LFpQF$F3Tv^kigbumPO| z4Z39m7E_?OWME+S2c>;bDe(UsNEM?b14?TE>^IO-^klF)NV|fa!3H!l05T0ZuKxdK zU|{ZH)?!d&=W2zR2I@zHZ=i>_bu9jWW4Z<o*Qt<jW#j_efhNwb#_$)5I2+sV42b_w z)w8j46k-);`;&rIoSicjSsWC8AosAb{Y}Oy&dvqu7DK~K0F<^FOF>6pvAx0G&R|x6 zs4+*Re~h*W^Bzz-WGrO>r)zlnM=2*jqczMspz6+p(<{z$jCm4N-Aa%;+~pYaWT?7T zAa(Hck76&Vd}8hgl~0VN49h_3aMWL*INu0WcLLN>2E{#cEe9=2BAEWb+TQF^pkte{ zh^y*C!XDfv1gi(NE!o(m9%2_)g^q84+cIGF;5G=m6trwZ7gx1`m?HzKqrmFHbr-wT z|8Q_x3qliD{a*nV2bYl`_24p?ja`ZbVh*~vDzvQx&XXYZ;Ie~_T?*Q#Ko?g9O=0~1 z&j3!#VD;cM$SwuyLSqqEt%ljFg4D-RhxDx&*x25}!xcpy(#OInuLkaGfpvr91X-^d zxW9!%4&3L$AqVbvp~`{s7^p9(2JU;|kOTL>U~-_ce=oQ_0BTgKGqy67f>Ic?FUAZj z$-r?0SIe%p=Nzb)1WL0I9iVawT`h|es62z_IcVREv6bl-YUu~c@BhEC=z!Eh%1DsO z`JnNcR;DLd)rx`CLi3&)gGwYs?K!M!B|vJS`A>~OB^sg@G*^#OX8wQv{~L=ED33w& zpc;cpJVY&qdl71(?Flsol>{7W8Nm4iTo!}!4JaL*2A9ci|EGh)6ipt|r(j@b!!EA| z?pr`*vFKL=_c8FugZmnI<iULoOnFec0=Zue-1opE5AK5?%QO7{#?k^#U)tde3~HdV zoROWel^Ik_aBf5^um68zse`BuWMF{Ss*J77ppk1VYFR}=am%0$nqgp2hom#G*=NBi z0i~>EVEF%yRRpU3IRgWOIwY-u)t|wko(rn}E=WBjy@AyqB1SzV&EZlHN<*x&p!CL| z4H^N5j}?Hz<|?N7VD-XK_0K@=fuudK`JfcVxe?XB7XMX{+5qZoZ$NDTQ27L}dr{;e zZ2_F}YTz~j8{6At(A++%*=pc+0S-BE+W?0gJ7*-QmxXL5D4l`IXEnCJaX96`?F5*a zp!C%bX$M#$r!UazB`j%%WiCXmI|G9{V=FUglnvJR#b`UTYC`L9&^16H)ek}C9VDG0 zkJNzkAt-%eRS!vLSk?1D&EE!!PsUc}BVhA!wy9b9q3U-+)gK3`hom!f^Fir_<v%FB zFqSf`gsR^TQV%WPI5(oS#X;&>xuEJnx3qx#dkCZ+lFrc02hUALfYy<K#~#@jeJfz~ z<~ODY(3%dYxK9;KT!jhIK2Za=PhfSB`G1g{60GflTE~LxY;c{%4r;p~^nmQS57WaK z2yHt;%z}xlfyH5ZK<)K9@H!dLcq3?iOg(ta8F@|*q6V~X1)|1>p%J?prbkR_;1j^u z*`@xw{eK1uA;um5pCOGC)*-1;{jZLx=KnY5<4k8k^&O~AU~FZo2X)~Y+?hfcwlcFZ z@H1#_WJ_^zkY`|I0NupE(89pP$jB59x)?Pcw3pRiMM#jDLtJ|!8-t55=+Y)7HOOi$ zQ4uzGB}veAm=e;)Od+aF(t_d=QesMyrZx<W3_t#>Ft+?Z#K6Z83Nn8y=qN!(FYgU} z0TB-3psVZ|nDQ7vJ6k|u%9y~w$iNsN?H~q{VQNN~h;#tmbkE1Yr>exlAqI8|t0-u> zK77v^qq7315F3Z0h>EtInHCG96*HTjq5c2=Fn=<!u|e(vFJy{ie86;{fsHZHlYxPm zp^Pbm@iub|gD8U{gDyiL$gK`;p!<MWm>F2o85p@(nV8ubnbSEL+1c3G!$D`tvBmRn za5J;9v-vA4ferxFR9Dhf)<qlxsH7yMq{Pc133jKj8E79BcsnKJBt+15Kz7h7e(?4| zQ4uy{qyQ~rGtrkdGY}P*;Lv3=)|W9g6qAr(R}hhw77><_Ss^SfEi5b}!}QYBRzgBr z%*0MYLQ1?*LP|<pTuMp;MuW==aGeiM*Wfx8+?GbJGa>Sz`~Z@N%D~0}k@SJu+E7^} zb3thzq>qg;5Of(eTpvta4J?kN57ZA~GG{u)pvIu#4jPM=`mY2TO@X!O{{R2~oq>VL z1fs?Tq(=2W2ZoxD3=B-?!D_U9Kx(A^>tLw)#=yXI6QU*zq(=2WJGvT%#Q)z|bRlY> z`2sZI#KbU%DTHx3IA2II^np?XWdAOoFe4*q%OL~kNJtiU@Xi%RW(m;UgI)}bEbh>q zEAk8sj4X@{EOnrhUYeL0!C47(#xiL45fh`ow1X-GGZP~dGx!Dwgh~d`X_H8KF4BQl zKtMoJKvGf#atAxM+-D9x@=Q!jTyzdBADS$eH4{kSkm5$ok1Wc83S3G-a-e<%0~5mr zrVz#hSo|o)$jBrJ_mVW|j1)#@gusCK(G+y#wkR7L`v$llJ-MYg5(La-(fr6G7o^0c z5D1!AVqjt@WAcLLYZV4>P&_&~h%vIcGqAC<wIF40PF5yn4o2p51`c+1j&KIZoeLc7 z{tOHXa?(-~;-F(a!TFgBe}0A)jF97;v1elskPl46WeidC?|el@Aub^aZ3!7o&{CxT z|Nn!|r1b#Td##``Vn*M?;QH<VTX4U2DU%u_MBL{nMEo8|oS6$M&dx6JKN*x)|KCOv zmqZ@h1<gN0%?VrtG3Pp1J*a&IGM}C819a?In1O-O3tXpx*Yh#@{(lXwuaMVEfW}<y zz-w9{YJC2`MOOnV0~q_jc}^z<lrOQB0nZs27^gziWP{YG{`-NNcNv%%CNYID&cKp> zg&7$cBp6wk(DNu%0G@uC7+DyZ;CU2W34vCWf$}H=G><YcGJx_ZvPuR9W<~~ZZ50oy zt^DD6R8&Yrm5oCJT--CNA!<iu5ixObcphbBuriUB09BWgN_jHo0txKW+)N>CHl~tF zVp0;~g3?UVh+K*{k1_}%`%#P$oJR-JkMKOoD2MQ)C_I;<_z{syapX}BcLol24)i?A z2Fjys?Cfme3~X%d@eJ&2pggLg3_1>i*gOi28qlJ05ixP>d32Ypp^UhRoS38%S|(*R z)Rd9XmJs3+Vg%(a2FMuD6DBpt*bt*{DL4;7#X)%#Jig25Q;sAK&ZA&)b_wXbHP{>^ zaY^`iumF=9xKG~;s-M{2FdT&1iz3dh2AxL$n*+|%VDlLRLy+wS<!P`u+Xv|QG^h<~ z2F}xvbrrr0G3fafG-k<U2F}wEH9ib+=xRWDn&~*xDF$^08-|JCwme3z2D$tH4`{s& zQa2N<PW3<M|FfVGM#dfg&w^UCAa!6n8^HZ@<1oaSD^kCSftjJ2DVgyYGZzCVxYd>d zF5S66=lO6lGJwyARSJl3kOVben^{07vNMH)&g5c<XJuw$U}Er>c2EGzF)%POGchpN zfz&WV)G)`hGBPtU`$sx(s;H=_i3qT9NI~+oGAtvj!`f}iN^0gvY{nohXs*64Eevj` zNxzp85t5M+5|LucQVv$&QVNli2es5BB_$=HG|0Q?{;7uehYfVzI3pu?S2)N&GN9IK zGb<xABO`M-=;SrVcn%hJCN_|WzqErgSegx_ftiu14kXG1QO5*Q$IQgc<R9rEB`(Iz z1v|1@ke^GGTa<y5fm4K&Llo>yPy^rG7*yS|BehDATd41$*}4GYMd>>tQea;)W%0;` zC~+wSE3?CW2lXYmzj2f)jxmVo4+AHI0@#0|oGeTXjEr8Oq7>AUED;f4f;R0L;bDyk zQ>Hj*;Rqia0Jl-W{dn*=E3B^$9yb834Pyk!fknaT3L*{~y9SA?v4h57!Lso2Sy0;* zBnR66uoOuTOkABYkYOpPJ_e0YfaL#w`2USr9@N)oF!Bf0RZ{=8!F3fpwf_GP>hm&v zfT&Rbse#pJ$ZB3NFfi+Z)G(I1g49U;R|cB{AG!MfA9U9TGZ#dSB1nzue<pM_3~K+s zv4la?fXWQUR%Xy7AS1(jrZ~nLaM-JX!(N&VbX@^xfjc8ZGw5`l63}1}1E&ZxMlyg! zH&YzE;AUj-WeQ=~4X%ITeMcsD&|YlNwm6hJQb<G<-gkr+zn~3Kpqg>FwK1$ZM6Cuv zc>;7Ue>H<BQwakzgPemjxIYM56v!CM1iIqZ7c`T_z%0njE2_;dXe=nI)ynkqFFR=Y z+2sG#47p6382CVUTZ4|O;^Y7wbj-}e$jjgXx>*Y3S3U+lCSDP3c0qP^b9HlZb8&WY zc6C8fJE@=`so-D`Y1hg$$4)vZP&znRIxtAu?r#bM<Nr7Rs~N5^ZDQbJFmW(sWdv>J zW@2Jw@?v3TV(<Vp_L(370C6cOWrG~b#lR&d$igcIa;dtxIJ>&JvY^O92kD#~X@|;I zru(+i+1XOIe?1`n*8X43AcC-i0dy_|69f40ZAOqC3`{Kyj0_Bnp`d09Xv-r5njOj@ z8^qa-1w|_zrE_zo9T&AS?XZ=~&X%_Qs|dD(L4(neNrbVBaM%i)DvD|_zF~Cq^aSO* z#{c|`%b0#Js4>J(Vqjonh|dF=$Hc(Hc$G1l=@bJ8gCK*7gCeMT%^1td%)-pb*u>z& z$;rULDaa|v%frCIz#+`WE2_;XCMFKb<mSpS2BRjsET5yKAuoFrhYX*Cq&^=T(<zg7 zE3<l2ZYTw^3l;}a46GoVaE3W61FIk`%te(2MPBT0WxB5p3u7H{7$eNU9;QfUD4QA! zitc~W%Ctir8ixOS{#P@UFl}UDXHaucW?^JzU`CD?(4p+$h+$`77Zel(U8K$~sBCI1 zsw^lP|02GXDe20Uzw<!p6=n`ML#X!#@qh>iDK<t{23C+^pgv(L3nK#qb1VZhb1Q?7 zw1YgVBm*-819K<?Gc!Xh3nK$FgKwk*D93{@d=?Z0pZ*TD7Id!@$m)X!!IrDHtAVU% zV1)Yv!+z+YG9dfGSEZrY50ykpi7cQa<8avzI;tD&^@9h&o>yyE2Ya7^nL(ZL1XB{z zDF$W+b_Q++eFq&5R(57KQ09tdVPaxnXkzr?;9y~4VBp~9;O63FVP|1yV`X4wU>4*A zB_v^EW<_CRW@BMvX2$l$sD=O18lx7LHAXFDJi*BH?;i|<+d}{UGW}ru&TPfR#sHdR zW?}I7|B2xU(^Up;25|;u27QKB*iJ}RE=Cr1R+e<ofk>cU0b`dpCnFOR_{^zR$O(Yl zjBIS(Y(C)Qr8pUxSecp98L(($038DeRU7G`tg0d@!OO$QpslH*uc|LEE1@i@EG)<) z&MOW%H3f8<nJ`k#i(CuiVz)`Ds7T?#Ouh;#s`B!xDhekRRMh0;)W8fh5l|fsPYe7E zF_5$<!@<bTz}~{Z3~F34Go^w~;$Vyg-A4#c4N7RzpjcyI3<b$E#DdQd^o5+l!Oy@i z2mzo|IKW8~k|dzXGCuxAe0+Q>Q<7S{IxJ~2Fu~meN*Uo07fFGdMc}N)%EHK+3My(K zXJ<fj2Q(joB^g*47+69XSXdZhnHU*ZK)FMJfq|QglY;@0E!la+wZV=NRTgA6HdO{? z&7@hgpt+N&qn&~AfA{}thEk@D46LAf2owwqX!Ry51FI0E9#S`E7Zgo+mC(x6ym|9q z&~P$b{}u)|23gR#li)gtiJ=)ZCIqU9*cjM^paqq(xwx{RXhLaeLMv0!_3PmL$pp23 z69XFq7lVw0Bo`+KD+@CdBL~<Z2B;B`$_!Mw2r`?ivx5y0wX?HpWh#!$&W`-s%QV#- zbmtjTe&=O~goLOxJ0lwdTMGj;OS6J1msl1?Mn-THE27G>fND_2P>?i3ENF)`C{Xzs z7#MgNcp(uCI&cvjrr-#M6nOFRov_$l2Pt=$7=#&TFnTeEFmN-7G8j7OF@SDoXJk$X zo$$oK6wb=X#KaH}y5oYuACzAN`FTWnMIm{FjYmWqIgh9tLGE1>5nJc$=N0Jd?-djh zqNAq9IHNcxtGFmTtJHqMeE+}z(Ed3l1`);?j6TdE3^ELw3|<cIpwo9ivC7TJ!o=(a zPTx$R6LpwC*S;{Zq%*KGGqZ*>fNrp2U}k0Z2VDxGsw}H1rwKYpi-V0phEawC<RBw4 zame{^Z0yG1Azx586O@zfn8d+1zkr5-O-<C^@F{b1D+!y~$uP0-nQ2;k1-ZJ!3h9UN z>KKY>$f@aTF^8})TeGlgx@n2Zx;eN7#3kuRd1znPm6Fhx)74YcW?*6vWSqh1$sEQY z&7cnQgAgM#($Sb~j0_;Rg9fiz8JL+^nbXk+^kroj8I%=e)MeGhMfpKzyGb)jL;WBs z!pEen1l@6sbkH5d3y{leR=C6p>4rF|N^vVlnAu7*vGN*gICurQs_3h0X&dV@hs7l8 zM|<k9+px0gxNC^Wc{n%*Tk2}7>FG*oS%ccm408WxF<LM@XLMt5LENc|awqF7MqkjK ztPCDF<<r3OL0IK^{x4wk0o@795RH(B-P!v8KZD}`S&ZHw{VbXYd6@kSjG!48CeZx9 z0z-g<FC>L9gU$kgoFkaZ%E-jY$i~jZmJVuz#d9$-Fm!<`1&&w-@D*R6t2QKIw}lAs z^MMZ^Q(#m89X<v+feCz+92@AQ9#ch8Wl#|)YAmW~3Q8<yX5UrZ6%@oxWvpFX0~p!1 zEMLCm->-@i!+54Ee1Z-<0x1zu;b)z?o#s0~Dy{b}1|8_j%wYWg7?UQ`cLr4kJq8no zY6o!%Q6_dK16_3m8A&!4c11R3Miy2U(76DhBf#W1*q9htLGwHe>?};|>7e8C7+6>{ zm>C%vTNr($9aNba8JQTHF_f{gvV?=q1WjOIWnm47bP!}<(9!_i8zCwwq$nZ62|5MA zTuq%_8FZ13i5cj)bt5rxb7Rnjf9z^%>dcU{@|4-tg~5{`%wp=oY;2+;jAFvt%HsC2 z7UpI7!uEn<T7p9MB7%wn%G~0-i5lK2D!!&dvdO|?T%ugDO5y%ij#klZ{004*T~U=Q zB%_0wn8K4-`Pe;Jxmf=x3GjIF^F^#+e96qj^v_hxld)B%Bq*7I5xh1>lIaSA9>WUn z4WRzCBq(AfK<7S#hSQWK`IuQ*R2bP<K?kMEfaF*hnHeP*nLq>JObBT<&~d3C{qmrx zDi&5y8NtZN5Dz*gt;?H%m6a`l0opQ9V_;%tVP*m!YtO<8I)D<ZLhvcj8fu`CEHM!Q zehxO!O{eImK#Pcp!|w|ehbACVGc)M?7ii4Uj4{qEPF+RT)4)E~*u~DBoms$IjYol> zi(igI+riLXLB+>3x!%sXndyp{hzGxfdrM^QWJ$&h3mIi*W^Wc27mKZo0^DBwd{N5^ za+ZR77NP$qF^4hDVo+n)1DOTkRb^yiP?8bk1C6J6Njre}>~Mah_Xg1Mb&3q227ev{ z3nNPlq#Wm9=VAt3Y{JIO1iqk18e*CPXy~CCpE?H>gc9h9^PqZxgA06CIm|fF`4Wr_ zD$1Y(mL(-bg$4L|c{tfwSwMG3fbtyZ;Bi6tLF=Z>%EFKeLr@tOq@YA<#<VaxDjamg ze23e)yg)n9q3e>N1|?e2ZuaU-N^zh&nj*pH%WwO4hjBMgeM;QFS4<L~TAIE`J3vQ` zu`+=61R61&VvuH#XHaHPXV3<nWGKhT%%Z`_&A{Zv$Ii;kEF{3e%*4pdlqSf}$;>Fs z!v#7$m?0H(=W~;{2rm=(wpRww@r7!tDxljiWMvqn89?VQgRdWgRI-ACf})^%N<m!; zP(2H}ZO9aSYZa(85maUdwP)0og^ksf#f>3!grA?EUq*bHKZwqZFJscuVquGubK2m{ z6d%vRti{Oa5ajUv`}gk-K@R`^Gcx}B&v?1!->0CUpntzWz3|}w-<TztPBHK?h%?wT zEOii*W@KlRVPs`zXJleEVB}=dXJq6A9ncCo=S_!!m4S(ql_`~*5!Ctum5@!K5|S;R zhmnn~*PDTplQ9+)4vgS)fei>K2bE0CAWe|FF*tl89h4;{1o#;lK-YLF$Vu2s+6xQv ziwlTDI{XZLjC`OwF(Bs;vat(;0z_F*Tv-rOgRvs+yA=@=mt%rd)zDhc)C77e`P1Ai zc|)n*_}b{usSZv~7B-BT+72=bGKMnBYN}?+X7WMNYEBYjUJ3>pDyGWj@)1m@QqwHG z^?CjsU{wEilj)Stzpt*&ZniOE0?q=0DzdVga>80x+HT<j0)YZjI?8gIaw3{mI!>VT zs@cJ5XA09P26+b18JJoOdJKjPCJY%4sY;B@ER0?Ppajh<CL+Ye0!}@m!h+l^j1uB} zJS+^nj0~w9pgYBzye0XWczK(7eHa)_j6pXs>S$|eYN&%!lA;2GJcB&wuz4wH-2_ic zQlO;7tZZtm4#LLb#^zwmZY-({!pzFd%FM#X>deOG;M62;Y_7~~uFPt#+^-wq!)Ir# z9iX1A7o(r8>aS^N!|NHM6=hJa8>B0~!G<TKH=fsJhAns4Ur|j)dl3zIDnm(UGyh!; z0)c-wr_P+oz{tSQz`$g~bc#Wk!NS2*h>@Lv(Myn#fzgwdnF(|>IXfdm8mItj@&?~i z(aa7CL16}An1{fZYJ#$cps^sRV`wa@EUe7TE|?Y`9xC-K>EF3cZ&ROGF#0($TKzi) z!cPA-G5Xp4`v5xMTbO}?NsH+egE)hkgRvOs?gl{te%KI_05b!l7pTtx?h!Y6voJD4 z&-E5(5Em4bWaSmtHa2BfHwR;7aP@93&MpeVpGs9`ma5FW&m?{i!denwnwb({nt9#d ze@UQeW@?~m<_*vo2Q!1je*xxYOjj7B8T1)!7&bWw2{1A-^D{CqSurwlYB92K!0vFc zVqjomWny3j-CV@U$jS-6r7)g>nYjyeND)f{8y6GkekdMB4i1)hD2JPooxPpiN7}(0 zzvehDMwnj6nS|a@oskamh6XY+3=HO`pbKea^kwul)D-0zq#2}C)f5GJc_p;Lp$@sc z7F^S-gImO)kv}$NR>+D7*y;AlY;5f8!bY%DXW7NX^s2+MIa9mct#UlI6IA3>@~l#( z2BvQ=VT=qCj13I%(TZ@BGUR1p;oy>=tm~|zq+!C#&8@-Y^p7iQc9LtlrI4Vzptw(0 zT*L0v4~(4w$w78{(Y7Ld;%2&ij5;pX${NNNCZJgsCI+7W0!%DSSHbs8IXgJW2?+}D za<eh9@PMZ1K|?sqUJTHarn|gBmlT0Ql_4I~MQUg8VPw$Jk`(9XV`Bjwj?Bg@qRk3w zIYWvVb#`@jWnpnhO9(P4%nmMSm|<7?ii(JdG3KeLtE<SV%NrL3+XYPs2-Q*bwX^dy zv(PmZ3bNA>m6McE<PrbC<t?D2CD~YhqOFRNbJFDK=|-VJKCZS4Bh%Z$<-7u!ynV{$ zbTqWg#63ahKd^wy5>P!P$Dquh&0xro<Pgup#l*<V$pju!;^Saq=4WSO5nyIXWe{Ls zWfNdc7h>e*W{4GJWMF6l9irLH=A$4FIx<*S2UL0}DatD=D9b|bGX-S|K~Sp}d<~u) zqnt3Wh&HHQYb*-7!WeYd4){JiWl_*gO~&B*NnBafSPevge9x{dYHVcoH>F6#+mVrx znbA2=yfo7yI6OQ&e5TuF71Jk=8JWc|7+d=>o$_)q;}qiLlj1eA4SdO1ZWd|Q=jGy3 z70E5ZCsOUAz`)F4`+oydAJcaRNd`p*b%rhnQIPML<oTIcnAPQ&IM_uQ8Nk^E)biEj zgmiUT7}z;j*i#u88NrwFfDcXW0-cl&iQ8t-Sb`>aiU>^uGcy*okq*KP44}H2L6SjI zSWr|@T#$=bN}JUbJm3wwL|jx1d^54Sps^t6&{amz?HGb=Y^=(l793;gj0K)O$qrT- zx=JdM1~-i}?EXE|P4LYqVw_p8Wg{8j&UtuI+MIZ9HDyLIVLt(Jrhi}lEfN%Ba%0@; zTjk5eWW_&i^HWCfei6`kAOi#FJO~DH1~~>L1{ViM9xf&ZUQQ-PCI-edJ`N@(c2*{4 z7AEFYenxKYCT~!?qZxF8E9l-W8EFP_2GnK-=sI*pVPjEc(6xHv%IeDO%AgzfKv-Cu zjg8${O-)>x-Iy^hVMe1|vQKDy@SmXgQ12w!`e_Mz9MXcBg3?Y?WzI33`uEi#$l>kV zw{IPS92mKiR6-35Lym%yD+40~_y2E9GE7$(EE(b)qNNyF*+A!An=x`TnlmzRvv{#H zvT%SdCT33MWMtxEWaMUIOa(Qx;~Ci4y1-ZO#)Iy01Ya9yVx*_5qYbL?z-RpO^YMbp zZU#$6OHhLVbo8?c$nAE_=8C3@pu~t&K7kIqHWpRpV+P$-3+kAFuCEnkV`Ee*t>e}Y z5q9yk;P`ijv5te?!Nn*{Nm4D>G_{nS-8@{-*~^BL(du6{2iro+Y!#&<uDEzLc?S_i zDPa}|J~?rHQz-#|A&KBnQB45{0Yw=RRtJ7*u@YHOI{<X{H7E^7GJR)|W>8|7<h=ou zRE4Bim>3z9WO!Ivm>79MbCO=t4rqd`Ow6Fp2uQgi=(d0s=)GB>UIqiWPYN2c1Wgr! zF9uWv59Kt2Rf0RN5H+l<&7iUkJhs`*>;t(!OPWDiP*7A*6ndE_Ed4?{9PHqW?;+=- zi-N*QOq_9<QH-jJoV%8Ww~Dfxp2O5Bt}O|1IjN~k-<6p}g?;$MnEoDQ6yWyb<zsYr z=Q_F|Wo{y;S}FguippuA5o<=!=|+rinNBfCfzqrbBNGQ?oQ;E#fujy|!&DOk3utPV zg*hEGdBw;S3c5OyF_s<FRRzs}NHItW3JD4-2?{B3vB_vFGMj>8PubL14RlJbqNuVM zC<U{zu?sWu>=pA5V?T6|E7V7fao%17&Xy+j#DM*bUOIX<4i-iZ4(iShUIE<yjxzlJ z|6h!88N*BF3`TYa-hXcy3K%#xGB9o^08Ll3Fc|*-#>~%jg+Z7>jlqz?iXp-wl$()_ z6?9uR=x}0Y7Di@J@0x?1g(IDToq?5&oi&vUG9k?c9^eAaS2OsltBZ;-GFVxd7^xeo z8ye_oX~@fpsEMj^b211s3iGgmDi%E^QxiKTV<S)<!pEd;WXEJ`qQ|7H1PXpRCUwwB zgP>NdvM9*gpyR5Q85ab!C7YQgw*~mLrdon%hk`Hzz2HKZsNMj*;3B&zK|W!2L2l|g zn%b^hAbFU25N)a#TIA|j6lNIM7Y(A~8MnH+IQz`Kt*WJ=%m5lP`2UA#7t<;5sJ$?Q z6~k)>VSYw7W^qOic5MkJE)Fe57A{aTg)1P!!IG7cnT@#_RHL#pGO*V%uyAp5v2fOL zgU%IaU}H?<VPt3E;9}=UXW(Mt<O*lt;^K^F;N;@;m-gPk4Z3g`%>b+#S-=`u;yFP! z`%6<`E2u*$D#F8~udAUZBPC)bYQ-bW18H6g@Uls1GlI)OVPj!sMq^fWHFZ!E2DMKC zKaUx9w7!~}I=DJu^mA3NRB>swSMX%)@cfse#LUjb%A~}2T-I7tP}o#NMoM1OO4H9p z#zs)sUQ$VmLqXX>!<w-uDTy)SuNl*+L-CvvJc6uoYk0X#Id}ww#YOl;3^a61xHxUO z_yokbg@k!T43srNyBQc6<QNzj<C!EFI2rUDv>BM0n43X&c`<;BPtd4%C<6ln_zFD+ z7Eli2WZ(p~pxM|Yw2e(6)wZ#q+>4txBRy7o-2M9k(l!<Q|AXltc)mt}!IEK_gA6YZ z2Qw#w79$6zCL=S4F(VthC?hMI2qPmao0s<nxqt`<Ee1{o4rWe{3<h=v(1r5p+>D?Z zD^NQce5@v8JP!*OGh}4IK@Xo|E=ESiX3!uDOFR!F3k&#^ZzUl?78V8uJsr?>RB|#B zVuF@JmMj7+0{nd7X(C=;QEg*JV@75{6EkyAOsSh23o<H!ZlQuS)zEG|04>)A)dZs8 zI80;Q;{DG@oQa7`g4ayB$&;}_)j`h9&cwjV#M078UsG1zR9Z#eRnOf+TTWd+gz3~@ zGe$W^5h*QEPEk&E!<c^||8DW}+bd}*t0<bQ%gf7&3hIeT+ZkvYb1`!mX<C8TAWQuJ z!K}-4nL(04mcflt4RWuyJTD^yBM&1tgE=D?w;3Z7Gm`@&2d5GvJBK2u*X<?k08+t% zM@1yWAR`8D1}-LUt_%hy9!6$PCgxO75VLb~q=P1X;z48i;NeTwcs@2>X2=C*kcczG zt&@eN33RR@baIS=ogG=XgB7tFc^Sdg4``B%4>F+^8R?)RFDE6%z+i1@Vx*^|t*NRk z=O*taB`YN>BMoX|iK%Mv^NMQ=o0@|PLA3gt-B^^F(U_5y*!Yzw*3{%zm6J1+QkHeq zcJQ>e2t3>kj&sI7Y%%Sk4~gkeMme(rbwf3Ac|~y%JxMuxb3;E<U%P*gKq-KOK#YUt z(iQ)IV_eCk#Kgt|+7rhJYO{mR++z@Buz{3ZjG%sgDmx=12O|R~BSR_!ILJ9Ux#GAP zxwx9SK%HJu22l}6xdh6&JfMC&xVa6QuLfNO3K?8h6io!Rt)o`0TD6MN;+}h?J0t7A z-|ms_eW2s?7{GQj{9yXQAk2^enE_P*mA6<N(BjR-$jRBv=_BocO9^KzR7s=*XeAp` zw_K1Lhx<aky}i97K*SG_+a&)zcaL=c!NB<cF9QQOOyn4x9PB~sJ_LD~m{>u#NHa39 zGBJWqIcH;JVrF1U2e%Ns8JL+_;uydehB7cP$T7$X34z)JLQ0?!0bxPV42(H=5x%;p zqNt)EIO!;ZyQboT=Xtn9MA?m44Yl|=8CCu@@o<WYvKg})X|nOKF`fFikX2UJ%8lhp z0AmQNtgN*wGb8AnJO(CEyn)9H_!(pvvLS6Z(B;F-EUe6_3~X%RBZHf~!4t`##tLJr zHz%lH&Eg~NpbUvzR#4=!GN9>zs)}?FWncjJyTpV982B0ZRTTvVxj<cP&;W-iq-V*d ztSkr}+ENBbd183@-kt{2+Uy{Yw3NuW=t+|p_xtTF%y!6j{P&O1-!;s~y#RFlCG_m$ zcyPN*nZeJ&o1Kw~O^A`1QJ9g1nc0hhje&`gjVTp$fiy!bXo$NB)CFz^hcxKkm39^% z8EHlad0A;?8D-F&8sOPgDMl&KRRy4NSI{jJ;Ndrvn<fxLag1uM^;(W9M>5y;DaiAR zadArvIeQ;S%MK3+0S~A7=s||ly7ZM<S$){py@Hu#{r-J-b#}7`)kiE0djAa=A29u3 zP+(AF&|@%VxCI$o78B=ZVq{X`V`5`8Hj-iHU<b_rgD!T&A_2M?3A#2|1Jtx>VPIom z=U`(`WngA*0r?l)>FWh`5Lx0`p|J<aC^`(_nG_uALE|S3930@wc)CGXcA+U}WQ3W_ z%nY8z24B|&Qyv-Vz#}XuDk36iswu$9E2}LIpI8B>T=1X@XyjT<6mnv+vapGoI=eYL zyAnIQnVBi8h?uxJ8{150M}4c*3?oiXEg$gpW<r84&K_|Nf-K6uE}I1fG`$%8+1c%! zBL6dp2$`E`UO30+ZRZinJ%<r|%NgU1XUa|gCj01UG3Ki1^ENTrGBX}!^!9a<R^eL5 zV+>kG${_IHfN>_%4+hZKWvhd*00$Ezv!aABGaIA4Boi|`8))VUbRDi10}~6V?^y>r z4!DJZg{8%tlY^C+krA@M1vKygTH4Fr&F%xb@Rx;&r5UtDvl*-$m&!;7K?MZ`B?To_ zB_TmUVNn54W*1i$R#P(-R5mp?Hx@NEH)a=AW(H?}QSik->cXPt8P0(`d_KO)CeiNB zUP9&K+9F!Kd?pg28iJf|7Z@3ZO_dofw3LggAH25w*CEHo>del`&dzw@-aYVI5{AV8 zE}%UoOl(ZuplXyM^uHTZ2Gb7)Nrr^2%#4gIjL^G{<si3|BtrXUEG*!o!+X6!-7@fX zCNKq{78&Hac92r$Sf~O>e+)FTpd=_LtOlB17Zw$P%`poa3o4t!r#1xFva(4<nj|Ls zhx=DVIY%)4xUZqCsTG_4@9n=oyBNb8Q{(=<hTaVfa(@leDFz|Xnj1lGHdYo^W=1d2 z@*)OShD6Z7W|KE)X<#!WsG<>K5E2y>hO8)31zE|=4w^j?Gy~1@F$y!)gsJ}ZjEa)8 zlRudG@9CR>e_!@6hC2Lv&2;MD0wouv8~;xJ+Y8FCjNoumX8OS(&JgdwDaHq~7amrU zFzX>1kA<Zb<^<@<Cy>(^n3=(=06`5wBo&aAPvQ*XQYh|J2VL)MjC=t!lXAG`F5B>M z#Fft*y#D>!1-{VvAL6d(mkf*yYX4oBM43)8a5I=X7;!Lyw(T%5GkLKxvM{i;FfcMg z3wQAPD+UIJX3&wy4BQOdLV`lzJDXWe!52CziZUt+GVcGE&RFqp3ggXx9gIzT_P8*a z1-Se@_3sM<BZK;XH_#bz`0Z&06}k+dL+bF^Bgz=@?>y+jNX7!tEt0!-fo_U)`j__) zGS2XgX)e<h1`!5jhV*Tm%%IC@yddSJBs*xPCZ3Uv2|RGX%E}ZETA~8J@K}+7k+I1e zq5!l)0yY*3Srowx9yAaa6J=zOkrGuFQ|99V54ngiiohl@L3av*udi1I-JoY;hPZqj ze44u&W433J3@g98J3p&TK|p+~t805gQcg~CM68NR9McsGy_mmdF?tp;OY`%VM*Gcb zZ=YorZ$HaE-VC&_A9PkWlPnV(6X+liMh4KCh<lkXFlaIqd2i4Nh;ZNqtr%67;%8<7 zE!C6;^I72hNQfd4(11uRD+?PlXaE%Ma|uvs53ceU;vqhVN`dcJl9vMwg>rGSvB2(; zVl)yL1((gt%FKF9pnf5<GPAL;n3%YknYl2WVP?kMFD=X~EG5o0A-au|pPP|Ugtt9< zZ(Kf)AS<f~Z(VF1p9m|f5Kj=l8Pf%JPgWK6zsDG_$XM%g@`mdD(`P#M&qpszO+7}3 zas59(y%;6caD7HsThKwI4BVjemzh9!euq2o$}loBXvqq)u|O^tlMIM(5CNxF&~P9_ zt2Y}fXnp|H7Lfog>;We+Xq5z$g5)a$1_NPLZ7J}ILeOeE&{b)6Oi(WwgGvENGYYZ< zh8^O4Wj-c$=6RE&y|_hKSeSYE*y9soxWrgkn1#8GxD8YVWw}`eIRvHHGty%?`MH@` zn7H^k6PP6aJ<^Gg5im9vW7PY1Nhv^9GD7dVo-#YDBO{BH%)b~$JsB%KE-rm5nSYlV z!0j)_KTPTjiVQjo9uBS=GE6M2Y>dn-petEH!}ko#Of1al42+De-t3I5tdMx@1&w$$ zGx;bhF)}FWDC<Z|N{ERF3kfnPGAe=+Eo9=5T^w<nt+F~Bo3g2q8Du~ovK&SnG-<KT z)XmOH2z<9K3%?LYdECX+Xc1Eh5fuS$K2Ku_5ngTwNhWn$Q;TpZ1H?VIe_woKVfJKX zlDCqyws%qFmDG`!cM_FhU<93i4ju<%XHW)hQvh!a1f^``$tK9^HSlDUps^sRDVrF@ zX!H*>%6iHF-)2aC#K6F~iAjP1Vh#fXBNGE-DyUd*h58+|LL9z0RT$JD7F8Bp3+fp} zFiG6^dJn#DjS0L5dmfV#gCv6rgRX-XI~x-dqZA(#XrBdii!fuaH)!`1c=%OGL0FJM zl2MWcJR1U9mS8Rp8ln;t6Bh*Ul>pBHslz&MqKwIX^Q?4SRCV?J^g_JsA`JZd42^>f zZ1rVzxY{NMwwvi2X1jTYsk1U_M8`Ro`zJO!db1kDxWy$K*n{d5CI$fpFGeTESK#%d z99!8~m>8H0w9VC3#TnIA#Z6Qg`BeUW0+D}Acbfj2YP!>ufr&wbsgaSFc@_gR13!a~ zgC+}T5~3MYK(;V2GchrTGeE}qnVI|<7{GULftH)HvWaRl3Mvb-gD(02`OMfzjFH#V zL|zoMr%P0xdDg$@jFR25($ccB(x8KDK=v3g+A_N{a5M0OVw0Z{wBdn|mx;lh0kq04 z98~ClZku87S5abO6Vnz(G8(jsdjibtwZ}}3GxI}@Ha%{99O8EkrZ`4NsQF6Z9o!7e zj11{uPlSRz5esTQ`3efDD6z0fpc=1es`vtCd?d)_aP!ZBF3w`mU<zh5V*1Iz%HReW zgA)h4Igf#Xi3xn1HB%gD0SuF$w1XIEr8_A6P$eLnwjryiL7p=;HZ>O2xN6E2Y+ASs zoJQT4JQx=+cQCLq2s;QcF)}bRG&3+VmIw+8GP8+m3yUj@Dw`^QUfb@|&fKxDsR^pb zig5vR6+{o%V$e7eT#q`)5@WC)CM$>@CI$~i4~8Smso?llaZm*70!25db;%6g>JA$H zW@7eNQ5F;chm<n2F*7*5f(BKU)D~MxW|yc)Nvf(!N~ti(GrIj#SCx}fRZ##P0tPZa zh~WrxJ~*D$9F#%V4>B+@*D)|NH-Q5UDWb8(1-r4Z@)4Nn(Uy|g%-T@XxBuG(8Y}Q% zSix|F=_oThdldu2|1i)wI7~bKhk*v6!C|7ocmcexl9PdLGb<ybfwr(ItEjrDx~aOT z24mW6(?lk&1D#ej#iB)O?VvesjsO1{`xreLK<b$o7!9;pRZYc3#X*>{@82xbMAO-f zT?a(kRf<K6Z2tde(D<*%SoQxLGw1|ehCdfT_A~DIa{+2U6N3js7{d`JHSjuW83##_ z|CyK}_ZBiRF!VC|sHmtYvG7W03nPUoq&$FxuZN1Hq?($fqza5?d<0pjtnlv+G$=sv zWyG+Jv6t~EIIkNx=rS;XaxMd7DrjPWi8&P1Vg@zIn3;S*BZ5dv#X)-xgiRG?nG{Wp z7^D9!Wvp{|Z*&JAcM!;MmthZhJX08aVIX8?pTS2^fQeU3+gzF17!>(;8Q(H6G6XVC zgsPQv5Cb)i!OgKIa0?k!M1Yn73o{!tXGvyDGEQW){0Gjb%>Rp-A{iz#r!#Odh%qQJ zWNib@U@(9>2r8iU{-79XW&@W&94zdh0tmDTjk$>lG|GY`3GpR(>laf3SS2%4K%|3| zgg6g31B0B5xRQjDkN~$Bj~D|N1D6OVuc$UNWM?KH6Fc(aabxgGL&(s9nYg7uCbyB5 zc(SmJ3~1Zh3NS4r!*q>D#$Aa^*w9d@7Wr@i&>;g149x#?nIai_;C{*hwI)HOoA(B= zpV&a7HJ~Da0kmU{8M+0HsfpP~+Cd3P65<VJrf@KWi8%q}NoGR60&RI$)?-pP6*mIa zC!p&akrI}viJ6vwrMR`Yl@Yfoc$b=t%sHs9nA4TqWq5=P4TZT@gM5PQGf<hz_^*b^ zn}L-Xv>r#rK@n+x3DU-21_n?7D+#l(iD@(1F&Tqy1ZHFZSEE!iBaD?bYqchmw{wuX zhdJob>Hoi(yct`-=BYcVfaa82m>EGuXgH|O1husonEV+TI6%wQxEQ%u*hI7ijUbz1 zl$A}xW|SzoX|B#<WoB0oa<(;x>=F7`54w|r={^H5gNB1DFC%DBpAmd80Rv+T0}}%S zxJU!_Gnp9tm4uW)g{hz#xLpbz?J`QYw6SD2=85&NNHb!p;}%wwakdra1|>EIrUb@D zrUwwSK_w+GBWU{(hy{vICh!husJmfigYQU%jI61t!_9WLOfzCS2r}EnMwlB^j)Bfu zi(t-zou|USrU25HMi*a;Lwp?$@%1R;9dPpxgO<mG&q4#8C5;e2RE%sdLi`{O^#>s0 z|KEf6$AjDt+8@uxzGgSr91QWbIK<cC5MK`!2k-A^2Dt}f{^9))^WT8&MTj2)U8MB? zKjb_BB=rZO>e0<P01=1mO$LWQcrP&fnq08?7~*Sjh_AyTz8*y!<W7kBhe6wH{{M%X zj}SiujW6(?Ww84p>JQ>je*hx>{~b6SHZVcYKVaX#3+#Rj@qJM7=V<Epf(|wM|Ns9B zH1RzU^-y<$%!jyVKlH9Bh&vJD`*4Wwg`T&Lu6_?lJp&^{(tjtWGNvn_-nRpv1ZYVE zBO^02BLgF7fDF_*lVkv`Z)0RgW?*813^l5Odj0C4VpA3_$HJlpYQuxa33Z|J;0~#r z3~2F&0O-PBWkzLocF@EzXr2o+@?~Z!2)>D)O%yb6BW?_uOcoOr6k%iBBB{zJpe81z zFYgoO5vUmD&d(}r@2y(cma~tY&4-m$*g%Kzc65MQy!}5vrc*KUdXgno{}fUZz+umj z_}_^MbT1AYBj|`8MuzDB-<a~5t}v)F)NGYxWMKwXb0Dv2F)*?)u`n`$T1Bk!Y>cd| zYM@)0;Y`rFUeExu9%%8629jd%;xk>a+E@m#E+nPkwbSylpvCrr{9GKYEDWlQsvHoH zo0=Mf*4V>ujAIiO1uyu8_#CwUj4`RPEh;iHCJ63vAqQ{Of_AHNu8HMbyx|Gyf%m~4 z_hL+f`1_StIq1qp24)5mrZC1B<}3z&@T}cz$S4Y*1S4o?3o|1dBO5cbm$U;&fJK-Q zCIB5}R%8GPFtgQxYCQ%9CPwfK1{>&F<0J+~MhDO$d<_oJK`aa`pa5fJV`OHl1BDJ2 zrI8M@Qc?l}j0}(&GSHzhq9WW}9PAAIjQm_2;H6oh`ApaeC1&E_>Jzk`U0hVrv{6FZ z#0qpUiQG;ODQ+!UGl3cZZZKzoPH|#Wg&yg|1v)wgwEy}rsLcfNdpz9l6QO<=gPtD4 zzzEuFfOL8cL;&h{1$IUj237_Z);du40d#|NIs+>QBO5DQ5(5K+11R>@VMpY^m4a$G z1|~){m5~mjAfF@r4LU4`lS4uqw2K|GodVLxF^4pRK$E|wilY8t--<~{8+&j|vnL3c z%bZ};VA=umEXe09u+7dn?(TTvnvp@6k(r4L5!Z~MxP}Tq{j12p%*4h7k84mjJRP*E zjFpWwiGhj90o2L^$2B7Z3u7HjF(|IFD8(AroE&VdsBsP2UM&h<Zh#us<)EIbq>`11 z^gecJZqRWB^FeV9J$^(Ld`<_pxQ@dX*Wgn~AW@5mYbJ;Q)bF6UW@2Rm$2DXG0uh5y zud6dKgSLJ#*0D3PK$L=dG~g{*uv7t7i4oVJLs!6Y4fZD_o<aT=M~Uk_nCFok2Sqm6 zt5APSBS$u9KI4BaQyjwvrhnl6Oq2r`J0mj#BO@dDWC>}|@ntNGj7*>_U>RDxK^q)E zok!*_P(+G@4`F~vBg;fO2=VeTFbIQpdV)rXML|6hW>Y&Rb7N6HCU$kC7P%z9vLa6w zkCBylDfHMcrZ^rUQ*$vcAxldk_|Xvz3{3ySnc^5$G6ykmGsrQdIdDq}FflNRf{G0< z$jrYO8+4?a6_mIb(m{ilEg*L)fEu=-A)z{$3MK|dNH3KY)D8EKbP(m?VPxQu<B^k; z5E5i(W#DGyX6F^r7DRF>JE#e63>n-6djslTM_wHRAsZ<RNoflyJ7Ggz9;WxOBOxY= znVAUl3K~dD8wm0Wo0x$v`(XZ`!<5S~73>dj25E+P$i74gb|yAv24+Uc4fiZ8tg)b3 z$R^NWr5v&p2O}#B3u`Dy5;TX#%HkX8AT0sjWh)^qAuS~d33Z4UK+}@UI64iW(l8Fx zPY{uoJ`bXWrKP?9U1tswmqI$RLsCk79;g%q^@04DVi`6=-L1>u?%=}A$jHsa#mvA0 z8iiry;bdZGWlv@RFTQ4EVQJ#<fx1gqLRVW;T~%30K~6>r*?pizip)qsjNDaYH3Kb8 z0oCQurZ%`m9|sL|*x7LZ?qNMb4iN>gsF;L&h8(Ex!}LFbDVAXcb0Gs4g92z39<-YZ z>J>DDW<MC48JIcQnOK=wQ$RD@@!&Q1Y(CuF3=G@~+#s(=h=~dd^7Ar)`k!2={ZFip zcNDV_1Sj={tcKds#=0V+LhMGY20D^PdZJ=NY)mhCWbBl<gmrX<dQe@<1Whv_xAHMW zZ{q~5mIO65Ks)Hg!7c{pLP+m3mVpV<^^`%9VPIlrW(s9sVq%U1cRKwd9fZJM;p67x z<pFsCoJoaYiCmQ3R8f>2)TzuAuoS<>sLAvI+>ZoxD2qWU0^Lo};De-QYPm@SQgE1= zK?)9#o8W=i3vv^@*A8|Q^Z#(BNQRZng$zOratvAwdE5CoL8n!Kf(q18mu3X@9-G-2 znOK;bIaxWFnVDJQL2H7+J#|H7SvJs$0G4o&By$2-DGR8hF0CLhBFw;`rXsJUpd}?C zEGHtzAjBXfCd$PtrVW||F-0yRa1BG~p%)ol&<qG4j<_vupfAiTs3t9~CdezSZy?@; z+;<1{<w0qf`F}Q3B*PSD7w}l0G-y2w$eR*upy>@JMh4JO5$b4!0$d8z7z3pV*jNN; z6b5`0kd&YRD+>dIxTt`%pfoop3qLDA18BGhG{Pb*s)%zGV#>ek=IG-OF7ECfAjcv* z9$e=@@*c?Dk_^@k77Pra9LK<z3d?fI$XSjBw6k53MN%A;-S~L8IM~1rf@C>GQS2qf zR7TBzN3iF!zwYh}P%;?P|7@l>hAGUh44^S`EeCb*#&1vnf`*mjL3LXbvkxd#xDnw2 zN}A~5G3DR&DI)UnB4ToK%&zY4<<hb;GBPr<;PLVQ+00A~Q<z^efb1}E(1qK<$_S1J zkS(CPm5JG(IGd)yY<h`o6AObLQxszo^9BY^=s6EF9JoNo2rz;UOY-vGpcW9}pb4(I zL8m4$H*<le@0%GwQ%LMAOc}f!Jj|do$3RDaT7XV`(8sM7`IOKEuts*afJg^5(76ww zgO`xceGnB965!+I66Y2NZE_Uh;}8WmT;azrsT;$`Rd8jSslqb+;bJCIjBcJB=In-A z%4VFF9D(z|c}GTOIW+MxJ90~ED{#q}iWIn7D2htRnY)!^NrRZ-G|PdDgOQn$nGrPW z4GkwQ@IWOuD-$yVb2DhQOfv%u0}~qyQwAt}*y6#SX0rgT;4s9k7OaY$oh=;9U}H}J z1spppq`0^kP)^9;66XS?bOAmdL`cCqF|3dk9nipH$5FX&<(CmQlrj-xWZ?*OL4?*m zXi%L6)6&w+8x*u9xkXH6xRT7>Ab~XzIje$#4OGssFqkk!F~)$?6fc7$gDOKCXjB(6 z0t!k`${f%UP-cc^PDW<X!WX7A&;%q)JU1H`GYg9aXg!cNHdSDG&|YgWgM~GoospG= z)j!ffNm`1Z4-__v@=~hOs-nVtlKhffyj;9I+~9EG;Skkk1fAWb3~B>|nlre@M;W!m zOr#8jW%xV)-7p7xT}B2G1fY}xN-@3e?rB&&kLmZ8ZJ@oJ;1O-G-@&yksQhAVW?<rE zWM*YzPDAnxs|BbLr-@A!$g3=@;Yb0+%0i^ig+V=9P+bG5sBtu+4oR7ah4ae@?`PEb z2=zE3n}FgS6#uF2?oFVWM)o`?&+9SyGbS;2fcyOF3=0wcUT9y4jRoB27lWS2$iN5^ zfcAydI2l=(*qB(@>Ocd(;JzILI~OA>J8KF96O)rS2O}FBxOCBl^@!ja;5{NN>LVQ_ zrKJP}R8^D|<YcAPrPaaxe<2Z7ZcslMci%`!4XJp+(n~T!<Pl4bK&ES0J4_QD%@qZN z<;)!!m>IB#4eUftNKhb7&1HfJ45qL_Bp;Np*@Wmp!cOgM#TPc9VG_`A3E{9ojF*6t z38D`Tx*CIp8MLzpG;Rh;Hw<hH;B><TUQ3n^Pd5w<sObiBurMbh3q%8a)C87pkkn&M zH=ywoaJqqy6+!ydNaH6cVS_o6VvZIxs?ZT6ltC3l(BMlq;M0~N$pn#Z24UFXNH=b< zQ6~72%su$R1~b`!W{&@VWnRa0ib0v7!Fz*fK!gLIl(>i>3o9cVXwaC+OBz{#g^>xA zW<bg$L2boYP;Xxiw0xBzmX(E_nSntaG`J><BnMjEqz+aAKE6Va!3R8^Dg#;$BPuKe zK8r$`Q5iIzDh^&y59)lHncFd$D+&u6GYcy-Gb;--gO>U5F*yk;^YKUv$SH|%aEQzB zF*2{;5P$bw+TH{4Z&!74ii&abs@rq3vwE|!>wBqdOgdQb?**g8zcv557|s5jVk}`~ z^I9~;)H&7wR4cIm|HUlMB*7rT&<I(c#V0Jl%f-yf$Oc*@0P;6KOaQbUn}yL6x{M3q zaSgDyuzOs?8;8e5MT7+T`FOZFIoMbjBp4+i9#=O7dE4Ar+#KX(b#`T8b!9##Q&~YC zelrKbcU_&yI}fK!nv#5|wTM^GhmFmd`RV6Vr~du=_wL#?Mxi|`&&7h~t`iv;n3b4L zF$gk9F<3d6bFwk9vhjebMlS|d@G(80)#41Xpni&)H#-Xx6O%fV4+DdggoqG>AcLT? zkcc7&yM(qeXs4H$DA*~?Y$yxA6Za++8&8gZ@-FR)VvZkl<u}tQqg0>A;BbzRQ~CFb zG1<xA)rElxbY~2+0+SMhG=nBXnFE&?IDpyMK^;R-u_MpG&JH>@i;00j!<&<ljg2`T zw0KC}8#K<M1!}vfgVtSWfKGJ)ZvxQ=Peg!~vVc~G>%mk;I*7^2Ffgbn$!N-If{wCK z77|tw<YJf9Mmo_1>>tn)D<w5`&?aJ0VaV=rWhFLtQ4z6F4;~f?KgY0Qz79}ePv9+% zv<nnxV`QCa;2`hr739L`_<@<jQ`sOh^8_g1FXiUzDF~Vf-(l1@jkAf#i-{9V2F=Yd zFfoWRFfa!&onjDUkO!Te#0bhuUZ52VY)s6l+>9IyY%CmXsho_AjNr+A$RtH97dsOx zt2(QXgg66(w4}Jaggk>7gBWPjg`l8154*Isu`p<do|&<tC>#ocPE8P0h8+HMLd{vL zwT<!DztfD$|L!uH{wwL(c{d{`EGmN0f=4gFAu-+mzTba;MvZ?r7)uyAtzDeJbG^(A z0{_1;+cGIJC^2X<7%}{Yv^j(X7&(~P85vpS8QB;W7#Y|=E8Econb=rh<$)FhI|C~t zJ8LQrBPRnR8z*Bb7b6D;Bt|trtF9U1nYfu47(jC`5DQE&bTA-k;Nrrr*TD>%HgIy# z_h#VY0x$E{0L@*gLu}<{1X~&z>7b~s#mJziqh+LRq@kvwEGsQ3AtJ=j3*KU`#Hhpz znbHAoKZXRfv8Wk%I80Pj5z<W(Wn*Jjgv@dqn?gdJsWiQXx3(*7ro5F(M%Y7XZ+({( z(|;40A_I*5wKN0nFbXo-Ioo?)E@`zjb>%9`z50+{#m>Md$Vx%QCfCz6I$l`FS4fc2 z+a)wGd!wPMz7Ax49#a;0-L$%cijbfHKObnz13MEp0~4bcq{s#3VRZ%{F+m{#7Iq13 zMP<;kF=IjSNu$P~lSbK@vU2|Ijf&bBW)v2Y)*fXXQOB6|ZyM97f6ERBn+7FL4>Jwz zV_*a=vtnXpl3);G&~#7}6666NWy-|K$iV2u$Ot-d6qGqZ>rm7geFTNXgh93mn}fCl zh_kD+3oA1VDhnD5nm^HTwN1$K(((-Yk@hJfqJi<PwySHomySp5zgLU`|2{BD{QENz zRPHkVXJbCgbc(@@;U%QL5!Yp8;!qG^Vq=nLWM%`cwgFW<pc9fXWLP0Gkr0iV3>*wh zY#dDK3@j|{u?+0&YM=-QpRUXdt#LRR85pz}e5AcM7zRW*=wi{p3{uL*2A=2C1DEIV zFij3xaP^F!@L)(rvIs>Vt50O4gCrw^p`MPmiju4}XqhKJ4+k5A8KW5&G*y{`QxIs^ ztP&f$pt2yOMpH(s@&v&N4m5AbbX4C?PTp2IGPX2F)RI4H9hbNmH?Nw#v7j<9w+yrn zl;&p)5jK~cvCz5V7cX}JH*ZZ@MI|%KzjI90UW=!gxWpQ;vwE|#>wBteOgfbRZwE8; znyK0S;5A9?|GAk(nIsr=7<NF;s*+G<Wa5wp#RDu3SiGbdnHfE$9Z;mekpPv7glNTx z32=tT8WWh2paCh=8L&nII9SzHl@#S=CB;F(3SKIy!>EHbSV4zDAe}8|t_aD$;NY}X zvy>FKQnGgri4;&4h^Xb&^RZCiXXRrza}s1!5KtDXZ?{VN%FpM=E0~a$nas@cnDN}o zb8+mBjLgr!JZEBQpPX1}0m_^I*;wSkcL!8E2r)3SGDtD9F!M1ovG6i7GJ!TDgHoD0 z0|x^uGY2bZQ7tnI1Ndeab~W%p2<o7s30#|Lfu>+p&{cvO)J%-Ypn(pk1{R-42R=1b zP(>hQqN-}h#V)JO2u~-76og1yir_q{C}_;o3{4%rsEO&{q^KyyyeP&dXo5gVJB+^n zHZz_2cZpFClwU*tb2ED}Nie8^`l6s?0EA>2nb-x878Zc(1zAQGG{H#7Ml~f)Ms^lP zCT4b~bWryb)Gh+&9nb*+pfj65+0#LtfrW{kC6tqqodK`PNC#;~21R-BUNz7%1YsdT zaDq@{RO7~$&p>NCK@;+#pcR|&AY&?0vy>FGQnq&vjSx^0jQAB1@hd`52{Q$}f6pXw z|2{nOL49QKo*dBKFx(7UAZN3I#!V6#pxcYoyg>~Xb=V#aP?QO>vrB5Tnkox|B1KWq zSdghQ^55(zCW){;dzh;Kwlbai+xG7ZXuJosZ^fM{lSzUBY&LwK3KJ7(&WT0C8+1gK zI(Q)<Hv>1^Z17eYsOe0Z;Q{|%M=&1s`uBGy<Jo`4OcMV<cXfl)tqaqBCeWEf77nI- zjEpRtjI5yZ23bI}si0YJcF_EIA_FrsvM0nD#D$dwg_Q+4*g>a_C_~nFfXXjpNKwVk zZY;=@8ENZc9cLXCWtDA_lF!H(wr3BcfR&}F$iHPwr~cg*k&KNvi|j|p9wsvfV}3?f z(DCf7P`eo!Vf8p{?=~bTK|7Pw1cj9lt^n1&phS+cONmJkydx<Bwn1s<PWW~t#2%%; z42%q6OtFlwm<}@VGDL3UVPs-tg|$efS(rcv#xvxzfgHvf3R*(K7z>&oWb~DGkOIpx zv|y2h>|lT%P%6aECaKLR$`0Pa4{A=Rn=-!A5RizL5RizH5Kw12C=g;~WMmW~z`)2L z^8YuJ9QaHwcLx{fQBaWTo{f*0k(Gss3AB2LiP?(*G@r`MR0rND16tje06I3g8FWUF zw3N6QFAsw}qdY6Gh&HGjCCF}SZVJN2qUNIPAS?)K>>7*kF<p|<;?K^`&JH_w?%cWP zEWI#g|2oj2S8l3~D*h^tDqE(xJG%S3J9zwi;$7$G+K^%enmYjP8DM(Gbc%tMffJPS zK?6)pp!$+2j*W$tnTe^H$%l=Nfq{*ajgy0&0lXrcomWg7l;S~~2aE+7L!uZh{#HkU z5_|w?2QwtiC;oR}hWOvi!B|#QkeP`EG^)qW2wJfO>Yp+)B!l;fG<kzsKFy#G3+R+F zK~Zs4Wp-XkZAL-xigw7!YNntK_@J}IltCL7K__zwGt0$=Now#3DhXw<Ftfb!e#*iY z)NqIS0munSaqO&~tgOY1=QRS<{!V4e@eBWF$#m-P8m16X*%$Ty8`C1DD-0S8(;!V& zVHsv7MpkJ?7DfR^W)^-%CT39Khc3#-3~m)ex;TssEX<6cGhSKY=Qn~@{)0{y=>|=c zD>GnG!NvyO{t8+G$<)mR=`pJ)E69O*YP{U6EDRcq8lXKSj7DPOkRzYiQ0oC@Q*&@L z6|@k`#LSE_Be_JP&pye*Brn`FMpH9UC)6t}%x;dbn^jCmq*Vpem2mIrOomYo_K6mP zVnN~(-YyQ#j!V=u(*yq*F`ff2Nc#Vuf${%erh2ARjQk8LAo>9G_GhM3;8og;47UHj zF)d)az@Q4+#R0m^N{Eqxk;#jZk;wzJlP#WsiK!K|qaQTk!raa5qo%5&!NMz{%_z>t z1Ujk;dRBrG8@nmEum&x>1$hj#6T*zq*V#AMQa`~nJvGi-QkO?SU)d+$)~PKmq08H& zn(2apLUc!xOMz2CL`(uJn;RRaeQAJigHQ0p*rKIbptQ!s!1ezdQw+EaR08eEkmqG* zW@ZHS?m>IcKzo+JSqi+#L`F(jh?9dsoKYN_rNBqgK=xUI_96)zGxIU2gEt(Tne#Dq zSy)-8JAO=DCLqnl!YRky6!%ig%`;M5Tv**e$uz`}%g)f)*NB^O#lKrJ=91FR;*7HY zghEqw3WcR4J>1#kL4`CEgBt?_qZ7FQuFT--;KTshmd_5F=7*kX0h&k#9n%gz(E@x3 z2}?7JkFXFUgPe@Cq?m}1vam7_7biOl==feiF3^!#%BJ8z1)o0w4o=V+d`4!bCJ2!R zQGP4$T%Vw@5cSXqQC<u0OcTpcKb0WH`C5i1k<R|kTCQ6E618;9LY)H~)txm#Vado~ z$jHe!f$1cJ0E4Q75(6{%Xn4?)Lde>7CLcxyeqJsPc2))fMgdR|GC~H+LF<@BMZ}Da zMHzkidn#))lh&2Ri86B5rl*z%ObHG*0_D5J{|-!z;CQlgu!glpnLvXWOw6oIsh}%r z89>DXXuSid_1Mhp!^i+?9fA+S<>p`m#TzJpK#pht4Xv1hYe-{3P<bT6#&}p#lTS!l z*u>)Bl&C1ioT!uo?5sX4Y*y}!_Ww3P8b5zMa#R2RXW;tJ&&&;O?}4_yu`^F$`1M~B zdZUaaG~FBi|HdTEbcI2Y!PCKwmywB4ScnhQk78z$V`O2LXJlYu@dE7;V`65hgKcQ) z0<AWLoCO9=aAG2Y0^D4n?O~8}-oUBeT;0?hl*!f9l-XHDLDe2O&6$IajPmU4x6iV_ z@W8#mP*E>JdpaXqa9T!UyivBHb_Q2|vU8X&YnyY0h?uLeQ1CKm7ds~p3GrYN&>is% zObp8ZzcF59I>R8uAj9D3U?<MV!Ys&$D0^AFK&y6`7+ILoKwBQbMLlS>H$yjrkFYQU zgRqRS3}_Bs7*q(0qZYzurl38k!lowR!=2fg883RfNT~Ai%kn9z{aeN8&%wgP!X_np zjOonZ>)~PStllhantJ+nj7R@@Ot&gk;nSA=_Xd3VhVuV!Oc_jP7{nM97_=ESL&oVu zq#0S5c^R2llvtP;In<e%7#Kl?ForNYBe)a>ZO_!=Vq;=qWn|)DVM=3QW^VH4X5`>t zh-c?yVqoY7RbntUXz)@Un__VPvKgWj)IaP74Pz=QDvFCUGAL>*YOAS=D~KxygZt_{ zpadw!C<Z!bA1MKX!US?&h6o!oJZxAYb7^)==8R6rVHDrp?ac!XC&uSInqo%m{JczD zD1qgz79PeZ2M@9mPSp@4E+KO(anL$=(78Jc5qEMjs4#&ptz!n=AI##zbd^DvL7qW_ zVd*v%Rwi~fSo=qjlaZZ+k%g6=C5?fNjWHh7?*|t)4Dp}}A9QFP<kS{b><Sqez$fRx z%6Dl8O(b>TLY9pUT&Z<|ssR+Wk&zDKpsh{{8VVYq6LuJc8HCl8A?Hw-vnw+ii=$Kt z>gM2l0PXXrt3eJ(+8mg~C>R?dHLopulDGHd?8Z4Venpj)g$0#WMd<--A{^`@Y=L*~ zFr9r}&>X!qKYwXVO;%U??Ah(@GiM&TD{Lbp=^%UuRK78R!io78(^>EsUdmP(@DLuP z5g^UL#=ywJ#t6$8pzZcd?4YCsN<Q*vvP?|Pkem)$ZV65{qKpg@;=)4wyr3e2m4!i! zQ4CgAsVjnfDlEqYDzpVbTgn-Yp?+g}lvks{`R@(bhg-!A+|8roq9*=Lc>?toS4x(| z9j3GYWG%c@lVcf=|1&D@XEcWT3AAB@fq}V}=`46`*w8^wjFA<zvx$ibyd9s3k(DV8 z)SLu0vKT=J<_ZZ3NeM}TIvEn6MwY4^6J&caqcYTuP-n3-$#IAXu&_vQt%?2jKRMvv zE3gBdp{@%2BW7zYBH=5?`1Y?EDB%CaK%I04a*iM~sGR3!5MhvGFn2H!Vq|2HWMpOm zxr&h;w6dEe4b-D*^5$S=f*yk^C(FkRTHXk9n;<8zq_!cWv9PhQF{3i*2w8S$cnL!s zY_7~Gm{@qRAokzy^!&@E`}F4NunTi=h<xS{6=7wU;!&E*bn4%JM#sNqjQ0NyGO^aw zf)l~NCt?l`qLKm1p!LF_v>?D-%XFGSmO%})W=)BajYWc&iJ1wsp$fE?5p;YY8v_$F z8>p}ZAECp{3@t1e7#P|aeB|Wh)a2A81qDS^lt8B|fY%d1TC8T~=Fkv@xLDYj5gxQT z%K35DT4IJ0W;T+dKL1_>fKvAcaCnPxuZ{g@62LCZ!7j=csF|3?AH>CBZf|n=4%6v> zhVVfD7Y`5a|Nj}}|9@k$X1c<p#+(6~<YK4{VPfFe$jG>X2~?3WGVn4mFlB?stxX&Z zg@yPz!RIwFfwm4YF|#r-r-IIL0-fgwKER2A0W>}>EF=nw3DBJz!r<MP#-iXOC(Vr+ z8I{2&IPiu<#l^`%PHkXR%lhjX#iZsR8tT6XdT2u~<P--rP`(52O@_Kb-9bf66kMW$ zX8yTB>mDHG5ws`*?JQv7mC#l-SBG^-&CQJ&!8a`_tFtq*C8r{ei%3t_Oq-cilvESg zfpTO-UyxDA#aV$6yJ7y91D(YnCksBrSb&*{5o|XLBNOQE5hlh|Hbzh#0?N<L3_fCD z?+c1>@XEkkqKp;}s4faY3Jx?^AqNY>VURHKV>-pa3EGPVI%b9iHV_OsAS;#uoM#~y zYzYd3?tu~(H3x6nW*6KY$!PU2Cz9#ZFXeyHevEUK83RCVEHUW0N4%i6I`}XV2Jj(4 zOibVcpDhk_LP#?k=wJ?Lw^k5*P$TFt5YT7}=++HI(L`_WsN7se3np#fpdjCWs-VN3 zz;z5WC(~61Q3e?Xa7&h*iHU)ei<Oy~gMm4fn-NsCFfcN9dGmk|4Q2qJvL+`By60F? zK~`B#SxQn&MqCDT=OTFUftOcOThP=Pyr}|w#3E>rPfbmoQHhORQB4hW=D(ttm>s)M zUuH_LKf9F`i(h|wcE2|ZqgO!@C*x&~!h+&L)_=OJ#f)BVNs|HtCMCP2&kPBjnZ{_- zR8rFPcVBmPHRy<y|NlXK80HnA`^^|YZE|*oA|_+-eG<0+zp=6*i5oG2&c6fg4QBwK z%_Phq!(iuN4H`0L;9yE+W@O+5H98nrQn?t}*&(fB(5Z6GtUjV53=9%tA~K>fph`|q zP*7D-kegRZ+uRg9^9CBOgdDLXs%$C@J5O975PI5DN=nq$XwZ>MrQS?jc`4TE4q@J< zrA!?Eo`GlGK=XjC3=B-w;4|V?7z(_>2j(j?urM+)vJ|j0g3iKWVPynu5MX171sxjI z1R9bApTeO6QN>h;Pg$gcH0X8@1vwcNSrsV>VIf}7>;xNwG@~@A%K<%+Nm&^*$PJ#D z0$sxey3X5J5Pmv3V?N~Qs3-w#b#`Vi7Iv=?ez311m`;KH^zRj;xTb=jGzXWQfK3Qv zhA-TE3{0SMidm5f)ZW%&xa7S-I3U7-i;EF-V+QC74d}`LP!V=U&|EHv!@|i3;zUM5 zbjWcqGP80rF|aW+q;s)@E>Q+AHtqsVA~dss<_tg`cnu^~;65y9L2{QjC{CGB)jO!6 zD`j9}f~W+K-@(p2j*N7W1)T|@rlO>!tfe3iIzv`Oh>wSz71Z<x-zA`=W(vMN0MZQ> z1^1UgbFz?>AqdVBpcaCO8lz57sI7n;FOQmdhnAiaG>JeGNCcyJTyS9k8;d&|$CMHa zBgPDP$TFrugOiED_J0V|1*WSEG7K7^lhDOPm>8I)CB#J;SwUMeWf(!1?t$(uV_^Xg zT6cl^Td<CRimJ4l6DzNzHmkY161<~sY$OKiX|ltLJ!Yhq8e>7485=KK{$vl2$pzVy zyff2vTg7wz8#St5!`f+u8V-yx%kp!V#zZg8Z{De-Z)&9-tZ&F91Z}4=fZS}(e1PdH zg9d{MsPDqe$jmA!Atubi%EZj%B@T8nGvo?8R#5MmjSW1k2);Q3)-+X7RdW>=lw#+V z)@Br8V;5J2oYQLxUfRdbF0QQ3u8!_0RwR!wUC2z=XXMaTR#vldGqwB|-l$S2lkI}+ zx4&m#USdpZ-l=4`O4d?QQPa%L)Y?mBakQ4Fj;lYyqcG2b$Cz~)7?^CCKxflyI;gQT zGBGoH!LCkX0Nr)K06IVhQsyfw3W_O!qCgn3j0Q9#2kP^K8pg`Hr@LDGoKK`}o?Edh zHZq6lR9c#6y!gL^j2hnUUZ7z;21W);1_tncK_yV^3-E*X$1pO28(=K#jG!$Ysi08@ z=y~s~tl$ajW(FTYK|wWD4M71=wWp|Ts)+rdL{UY^jS)=3q5rB^>$qxITd4V{8tNoD zMrXTw^e{4oCMS29&Qy1HQr9w;Q?ORm3h=kjv@2(xFu@x%_V@ogQv}mx1`&n`$Yv8R z5kWpS&}sCHUeXRQ4kIII4jQy+26SZzC}^Mqh0+e7tskI6O~73ba7!HAh>YAWBqS&) z017rnV`gzN=+QaM%IfUO=FG;zj6Rl=cmzZ_*u?}E#Q%@7urLc+9aqV8`JbPnj<2$^ zpDyExzh-lnePg`)Zw06><^M0h+|6`~K?ihaqnfM`FAEbh8zZQ_02;((Wnluf7Z7K= zL)wIr5`r=+N^GE0yg{o=;jKZ?dUiH8(D63#vwXk|@KHES#}umKEHpq(LPt@dCRQFU zW)=bV*0_C91w5i`tP*_1Q4L%otW4ZItQAq*<$0i1p_zjP;}v0JeF1SFsej^3r~U;P z#HlG~nlLW;XQ~n|FKB8e%y<nv#>>ILz@))+ia~@ymZ28X(bHsOWC86>Vgc3L91M(1 z9N=@Yn?N^ZFvNl;aA0S>NIR$_)Pf{9IT$#>s~wOufyap>9puFzCppQA$wK<fkUKTl zSs6qaML_*#NF|~SJKh~~?FjS)e`P^N&BnT}=7gxo$f(?0|JanU=y)cL%#_rk7N%%N zJv~R`e~at`T^;|uVqjuG_LHrH6$2XsCkGp6Dgy@>=saL{(A|fitB63W;8|H=H6a6o zthBf&g9wALBB*gID9Ft#t!)mv_XISf1gfS*A=yn?9a0V}EAP(D1-T~=>@tX(c9=Ul zI5;wS=4B<P7P;F7xi~Q}GU)ynV2TE}u~i%t#rV0oKsSeij>kj{M1s2v(xO7lyyDv8 z;-bo?=7Q>`#-i+?6ULyuuxtK5{QZCUv$3%7s)^r8{a3wI%+yqjSp`J?TWy#m&!`Zr z&A9ciHn=>|`Tvda8+aVs!NC@E*9S8r6EkSOl7|sAc%sb6!sv-qz<?*i!M8iW3VKx) zMHLlIP+A2QmXK3x;a7NpiyFu<BY3wE_{=~t#^?TS0U_OGRsLEjIzdTkNg<&rp*}Xo zAzCW>1upSrOv>(Ie9U~2ZmGGNfnt)bZVrw<PPS%N3JMOY>T#g<I1>Zw|8I=1nXWL% zFsOstRw9fnOv2#aA^6%TMkW>prgR2&c38#4!U8MZ<z!WqWYy)=g;kYRlm$SSMhP2( zS|H%kU0E4&AP6+anVKrAf(ArEZWk4m=no6<2#X1^iVhXl<q=R6G}P~Bl-Jf%lULGY z{AA*l;^*KK^fo<?jn$8Z)x!C?myVi@rjfZGIGj!Xe`AsZw@d6CtT`DO8MqjkKyz%2 z3{0$yOzEK0y}&L6*F@ktshh=zkpXn)fv7O71pwLs#|UmWfesgkoFxbve1=x5paY^z zP1G1wyuDqV<&8u{tuzzzEVI453LV#OZLRZR>WK1o_u=RE;N>q#_sF$#>B_u%$$R1E zqDDxV^8EkCbcX3FgCK((Lm*^bgaoKf1HNjH0o1u;W(EgnH)wiV47{rkeEcb>*8`J? zbPxrNI!lTR$qCB|@N=>=2r>$S9S%A>98{cvR|T6Zn=-<K7IYOwN6rKf&xv`t6FqHg zS20#r<`oxL6dI;8U1f|}l9#tMHg;KF%v629zXfwzJEzZWj%WleP-0|=`ESU0jOhx4 zC_@Eg2!;!E-kK0NaHSo%m>5|ZAROpgUn$7>^Gpn&gCIdyFfhckf)AYoc}Wgc5}fHl zlhL5q>0<N&Z*m7Mxd9bP>?{nTjG|zV8NqMF0`+{9A-6g)Hml0<@~R3%WxRP4=_0@? znZb00HIRuZH9O7gpFZ=<G(&q(d))H>Hzp~j(+u(qIt+Ra+G_kvER3LqJdBK>qhy$x zz-t9zc}-D4K}S(XQBYQmjaNdO5geefGwmQJgPDUbeNh6<m@tEbR~<Zk!WeHIqElb& zmSbxjV`Q!^Cfvlhd43|lHmAF<y`4^gQ3&I0Mb`-1+**?)SN9lG9%VC4Nfll%FB?%g zxqsflzV<$<+*)4N?*8EZj^+RVOj1l&82LGvnSz;4q0aUE|IZ-Fz`(c~JQt+T!~>IO z+yS2piurHN%*AwtL5?BLfm<BZm;`NtVuBt8D9ymk$lL-yfdJBtjb~tF1gAQAh%9&{ zg^3AP9DxoRho}JEoGvJ=s-g%gkyJ$>`2=)Aiy-*;0a0dX^nl7}rV3vXMFB-qA20ua z%ml_rS3Wk`T;J02`LXP5Ui{I%j3#kWm05qMF!#q9nbm>L#6YAsL538h^u~usZ_Er3 z4m7<9F)%TL+MA3F@ysls!wo^{Obj9juKGdg3pBh2PG9_t4A8VC$S4S&8iA)R(3G~g zv6&enU7@C`zxB{G#mE3U&m@TH6oVw_W=oK3_!*g*n7mk7Kv@HHf+M&t0~a^l%%EPp zB!i@?sv`KzNYItbkYoKpQzM|c1ZV;?H)oRWk81U-F4GCs)`&7spWvP8$5i9z=i44$ z-^b7A%g-M=GoxUJ2B<87j7xyV?>HIc9b}+e3ZS<pL5`{fRi5BxmLh2V19<j@sWIxG z6==$Z(T}kPyvT%+A@RRC({(1$dPy}0Wzd`hqZjD(e-_q6P)n}K8?@LB+~yP)6cYf& zxuP;7Xay%IxEPJ~m`p*JFbOI%H3a=@Vqszn&S0zsEhG(b2xkgZ&M^O1$aL!OMga$J zMaId08^Lo6jQ{`t|Hc%_bcI14G}Fex$OKyA#U#PV$|A|g#>(Qw3?B4iVP#+ewSU3o z9=Oy7pA^vz9u|>jkXKa_6jD(Z1Py*ML&hhdr3C0sEAWCZXyB?d+Oq{u$t(;}Q4BQ5 zZsI(5mb0o*FGN!#)OyxpE=Fsg<Y^&VKKv5x<vv9%0z7{FeCww{!kF>@H>UmIaR(O% zM_EQz7By8BIZ<IYCRPz}kC%awkCB;y6|}q*bkG6l(h_jZ0v=(9MZc=LvY@akDCC5} zC*^^1jH$Azq97ZavI1zW0C;Ex=5|%lxr~fW&Dzeg+Zg#x%iR90vT^2%nU-OdrLUkF zW02A&#w5zv!70euJ%gL;xZl66qGF7VymovcO`hVS-XdZd5e2s3`j8nqo+!$o?w}$n zB*@3h!_CUX$iU46SzX8g8g2$R357*Pg+XI^!lveepp_+{fjm`FcIXHqa~$;4*XNAV zKNuN7Lx_yRcA|_a{~!myp7ykL_%|OsjL4`7+NH?A!1NK^f0ANQ0*!AeDT<4U3JXEj zQL?fyG6-UEfv^zR1?Gar!XQVOi?Rzs1~A#pMa@AghQUeAl$|*)<K)JWsHn`VOM~M! zHny@bu`x~prMF&2e*wnqe<$P^rT%^4x8wiU!009Y?;@k3K%J84dF70MTR~~iS^_+` z1qz!?a9dl7L7u_h!A4G2OjJ;SA2cbz&B_A0+W<5Q&dR{Zz{;2kx*`fP^9vddZ)Wh3 zk(QR1k=Icb6chlB&nrT1p98P>0NsZv%Ff2duCA)4rmQS%WX>we6ra9&QdC^r&ax%} zcSk07=ZB13Jkef}X$v_2ePopV_n2`5uPxslKR+%zPM1W{BWfm^|6WzAfo^YLU}Rwa z|BXq3=?a5B=)N*;Mn(pGJtfd_C_Ib|T+ED$pq-Rn44^U&a@z}NeFFm%Q#X^3s;;U! zBv8Ta0nlPvXd)985ffJxWe1NGpe$WbQ&&@GXYNqfuu5~WO45{3jnH#;F>_`VSnJ^2 zRce!_q>^pvA0+4Hz|D1sF+ono*W4mVM@-09K+IC#z+BqePE9V*B|b|?AWT5Y&Q#ez zLxP3HfB`bL{TW<d#z02IK-bx@F|!na=4%+(K$~EhSz|$)!a!#dGk^}-m3B~KU}0us zW?`$tttirgTToC{R8bJt7Y0u>Lndkw17D!Ec%P&GO^Q;7k9ReI7T|%F+SO|+2*_}7 z$q8DAfXc)F{~6T&e*@hO%f!aG0o*UM{V%}O3_jDxn4!jjUzU%F6|_*63A7v*cC3#A z2O}#3XdWk>0k)7H+JpxURJVhsrc@A0z*Q?q9qb-A$l{cC(6pwcstRbCw2HB+v4Xs` zq_7|d8-p^VGU!+X<mpVv>@Kw80LQGcIcUa;8FX(9s80ZH!-_FR*jJic*Vv_|GcmD9 zX9UI9*t*t+`lZUU^7wVmwDi*x$%s!%(G33}A|56sm0ZFnW+bfd6fq+)Z)SkCe!}0( z36mMKG@OF9EJ`c-YP?FF8JPb6Vqjo$2j_1&hO(_ZjO<LH2~5!9L^UoB&`d8Q8w+DP zc&3+uogF;k2s#p<jg0}+u>j3tI;b!(L2jl+*8tjw08<v}AP$-?7m*W@l@y1J)e5OV z#%e(^4r+0jm>C<1gFA%EqRen#8#B58OEIytcQRIyh)Pe7l9iQ`R+01dWi+<eGqn)C z^l!e|Ge#L<BQ-g3Nm&MPdkYlNT;TSU9#b}Yd+Psx25trhCMB@EIg<{$JOk7JrT=Xh znZV_VJVUsHh!7(Sqcl4cGcyZlWd^esD<gxu_XY*f$s(YMH)inhPvBX7aBb1e;v?-K z3SWxE4BCkZTFueK<P*7FSy@O$6Es+2F2WAFWDK&00^FYx7c_<p@0o+TPsi9bq%HVG zM4a?3Tpi7{)S~W7O3P}pD=Nv$bF0W3x{GKkDXQ6+nA!+4?fLUeOh!{(Qjvjy@&D)l z0!%gFJM!8fOS^@Y7+Dz<rNsF;SlO6ZL5od6n;t=;jA)|JwcrvApksGoCrg8_qyiPl z?VvNQWFQOXK=R-wK4`ETvbCU{8PeL9mz9(d7Ubh$X9Hcb2WssLgO0}&2W>wBO~smv zg2y)1)tQwUnZe7dKm)TWO4_pgnOhUy^$JQ#3JFOoXlNLyNTfYaV3ey8l#=3<6yR52 zx+-p<{)aLCpToZm8d?HuPCQB;*1!HGG5%vz)6!#Mb7tcNg>>A10VXf-x*sV9Wd>^p z3wH2yGXpbdT_iIbsPqSqyMbqBz*7m$AYZgI`AADkD@!XWsVE9+D}W{zVWWW1F1oU) zvM_9b0)Bf#+~ux1F9)x{-jaz?QB7e!;bG-HVL@ThOsAqF9Rj&oc>H}c(mpVC*jQUz z{5${ehr6?_BP5O5{{O~&l<5i+8>a#!&Hh(ms$)9Kqz1apnt`1$fZ-%qJn_E@;|Hcw zOll0Eh9XFOBUoJHzY3!kSX_sJfq{)NKp$dm)PEJG2C%pV=)_>g0EUlX^@;xlKzDO6 zsWE^QvU4wEG>3_U&jSP9h{eDF5^n*wH>?;K7^}hSXZ0O)KntnC*APMPJpivfV~qtZ z>1<{NHHf)ki)eWz;g=DC+C)|_Zrysp=;*P=eX7Ub7ofEiplWa}lLQkRhZe~G|0n+o zFhKY^AU=cH|8GocOh1^|7#l#@n8Eb_H>TxG$_%OuIt&*fDVj@`k%f(ek%0v~8v*68 zf_KyL1VlJ!a5Aznv#_ugFmNz1vvDwkCyl@bS1+V<m;h=6cQb&dB}73-34qlzv$50> z)Zk!@Pc3LXIUZ~_XmW}HW({aHhPoO9gO;Y6j=B!${%sW{VO13s&@`1QXmlS`XM_9s z(4h(V78!7>*VF_yH^(%S&)!;ATR_!QzpB$J$0xJsUms&ckfEPGi=vc_3h%$u_Wo>) zl8g>3rId_Z1qB2ICp3lCyS3$;#3YJ}h{-7_NXjsp1qZsv{s-Nu{*7@jlM)jf;{|Yh zD}vj`N(>eZ(GC&jEKKYSW<uP|ER5`8JWNb%N{lS5ij2%GtX`lkt)KxI1~vv(7B<#Y z(7v;H(9BmaXlVwlkqo-&7jzepnu@%v03Rnig9W1nsL}&nJ83Qs_LsRh*w5;q)|Du% zXAT=jf-I>6o!1T8QKoM8$R|x8U65B!R76WyNWxZL(?L{~-9%l%OfkRADo$Q0*4!p| zriYblu)Vd8vxa;Klai5vw2h7uKaZ1un1vgsiVimmr-G@5bF`44zkrmcQIv<Ou9}*l zpquLd{|v_ezcKy=g#`;}K^_x`&n&>C#GuTe1G-V3n~{-8Q&B-uNRW$#gPBoFikTUF z*$OiQ?3Qq7>H@WRAP1IrGx&gNeia>69nhQ<KQE--hptUA1vMt&D>KE>14M)kd|w=^ zm>8o#Mk!+^Ux+h!|C4!Kvse~95Ns4Q97UCiD)p`8xc<FkwdZOrO>%Gr?|_Pnl7aYL zP}JO=qkD;mnysgjmo@mDXlVXpU<RGx3_fNZ+PwsypKGivXuLKef=L3L7p4EJFdSf# zU{V9+RZto88QhP8<yi)P25koo(78RJ#uJklWJxL`sOQcI9(QGA0I%QTXXFQ+FAiEu z4c)l|UXCLsrN+yzAgrJj;qif;)t!}9*^nvw?+kB{3mF+$K$RKzjw3(F)h&{2EKE$C zpnGAMz$XYZw}5Zy0k=Rf<RFu=%?zOJ9>PMPt}_S=aDi?#Qij~b1K!5~8Glk<8xa^7 zu__`UAYv7hhi7_vdb;P|9ZVje`3R6ZvY7rdh%>l22!f7(5El~`5)|NM<NysvdT)>o zh;R^qHP~A~RS9_Z7ko(~69XgYhTmo;pUAD^sw$u{Xkl}3T@R}ILAAW7sJS?3!38@@ zU}Av0p@_JEmWZZ)mO@vA5#uD?ru0y54p&w#6Z;@*3!i^cjAb(5yvobKzzA}aC_|V7 z7ds;pXl*MKXgCPu7%65(1~x{N-gXP9JZc7Q0+j$|Uj{~|bR<RK1t^gYT!MmvLaIsv zplLi|WAFkoSpNbVO1vJ72?$3{niS!|<eU})aiOipKUT)y49pCmu@rSCB?evwWd?l) z0|#9h0VY-!@T40gw=gk*M*w<3Zi0=|si<gbse<Qk7{LqBLCZCbjl{&*ML-whKn9{j z#KcV?VaE;=Fg7w{Qg1JI&v$4o@hGtGVU(2g2@3KO6SpzccQ99wkWi47mXv4YZJp#; z8`(O+vHC41hg67pd`?chNsu%fn~}M>k(8XAl$4wtD82u`^Iw3Wj4_JQjlq{;f#xi= zG|<V}OgsKB04?bO?=Seq=*9GxL5^V}WGqWSf{~d;oQsJWG+D~Y$lxyRfFuMOwT7Py zAO^bZ3bfG{oJJVH^#myGLQ;?vk}P=PA2gJ}LwFJlET9#y%%J<<z>O7f0CqF_L`H5` zRaI4ijtZ$OLkd)LaPbN~K9n6YgCNT2<;ue<?PtNK#LvYm&+ihdq9>vx$j@gX84ws} zXwJ+W%*>J$z!+|5#Kz*n#_1ag%6_1_`3I8(gE)h&gB2p5BQ6_bU}1r5+y?JQ*8=UI zz*suW4%tNk%lYsHJ%S=^@Dc!gofy0nVDxssdDH#h4)0I~rvD573owA(Aiy9EnpI_H zWCSH{&@KQbCJpeOWk`2Ri@`@okdZ-LR8U$-8Z;)z$pKj~%?WV;DCro3#<oP2LHBW* znL_uRYS?%?cxp#@do!w9Yl+LKNhk|{a56D>W|H{(!o$f^)<Z>GP((&VhT;GJ|92Sr z848#Z8QnQ_7#JAkVJU=h2ctYVg@Dw6!VI}RWBz{uLjl7hMmG*EM4Dnmq^Z#VR*cq6 z5)8tibyA#+jLgt^4$#Ot12gDaQYJ>G6jnxXNHa65gU26*8H9yZl?B<@CA5VFp{J%o zN5@P}l?B)8NK5iavvVm68#<UWN&GWxSC(aCc4cF;^|A*Q?VxgvjZvOqAyXm)H)!=f zcwa>*8)(j-k%5sJe0d$HZOp<5x@Z#KxMP>p78V5`@(*5>wb0Pg(9n|cp4QZ<TFuS> z|NlS4&<`?`(VfEtIeeH<!^eZs0#>ImvNHz$U-;)0WDWSASD;Y*|DPe?e*nV{m>LFl z?!}Dj!EHg%ntny55C%a8B?e~)2k10gI_BDbR#t2)`jv#0craJ=gF2d^S$<GUj16N& ze}{@}vZ;Zkt-rsVvzwTJjzN;Lnvah&W2k0;l9H3VrIMw}ztvhw8V*iQR>q)fBD5K1 zGA1yoGYF!u<p+((_cHk~G6?W-b8@hOW_eh7MYL5RSL}cfB?m7~5oOd%C^9Uoa&=st z9m+S;G|D0>*QeRr4KytV+GG4*fJu_+2ZItrp##R5#Gp&N6u|d%F+j)qdqHbVpz9|= zT{iIGg#wZ+3k!IcH>wiw#0_NcEqG6$5~C8RD~B{>A!q^`mH`bKgU+gjR2SgWiMvHL z_ylAH<W<YU-6JBH8Chi_Y$Fq0Kd`ZRu&}A?F)nIPN(5bMby3oaOHVUC^`Eb6C@4J& z{O4z8WtzgE%aHDnBFxLg#G=W_3L2H+039<X$H>ko%gDyg=EcCw!raWj3fk()k<Q5o z-O$(S4VooqOaRSkfQ~o-4=uN|`7knQYiXz{Dac5H&WaG=2e(Ib8FfKRgH(;oV0i|5 z@t7ib5KWAYO&xSGJZL;0k~qv21w|NHB(#KuP37JFeF79rm~7s4RWRC@1?L3n#p*^y zBo*2``)6#=&g#O><sHpvuBBL3ZS$MGJjE@~mQguSOeDe6GtlYFzq5%Tzv}%LU=m<b zW{?NX#Db=Bc(~a?!%d9hjLe{8RG3-37?>DA6U(3-YT!x|9FO4Pg?1Jn6%}PsVbCCg zD$X4Zknt2owflFyvkc|+gUqKea=4Wy#l#wA8-zABceET`>RcwN;3O>(eAp$x$;Dq( z++VXKH8mGB$0qz=fbjs6BzQlAorARmBl>;@&^CrvP<x*#4t*&G1A~Y#bTb1RFV@Wr z%%JIGb7eL*cE$r9K4Mz@f(n94n*UZZ2L1XES*6b;`FEmgC^W?c+A-e#r@t7qnL$eq z)c#~<5dJT~6vre9-OF$fvIb2=2I@>D4kktpb#~}p1_@MQM$lFUc1Cva5hS3+Zdwe? z%&p+v#7uFVtW2PVEug~|AeBlxWS0VL)DO}S)xfTUJ(hu;9jXDcDn;5sjf;_kft`T^ zd^I7OEwDBtXq+(8K|)cH0lND^LYx6~R)vtTsxmjPq_!g347;K!qp_f|s45~95!)UP zxcP#@Q&B)k0~DUoo&S`eLCUBO+xOt*8H*CK9v;xJ{TIur8m_`6VrdP!I>w)Yfw7KB zl7SO+6AlA2s0jj@z5y+e1^55Kvq*x1;MRw+vY?_U_$tfUK8*U0uU=)6bl71JO6wZ` ze=s&MDKV&nW@{xGnVF>6m>8KsE4@M6Fqxq}Cs<&B`c2x9yGK+(EkSsHP)!|jj0AN5 z4rDx3T#kvcAtNl#M#)dx*w)2d#a=DZU(;JvO4(Lk$6Ur#MblBW-@{+pgI`2PLrY7H zPt{u2#aB?kmY-isRaQxoUr^l=G-jmt{~NOflQM%5gDryx!xRTm1AZnZ27NvzMkW?U zPDXhNCN56Uc687pMpbr3Ms7w<E=JB&4o1+)=FGfI3=F;AJd9jiEb-vomCY<Z(hiz9 z)Pb%$1uKS}q~6Wy6X~GH$l&JUU}tS<Y79DO7If@^xR|gY4;MQtgAt<<AFqfuXc3R7 znYlTrKvH6Zwd$bvNGhqRgIDpInt&8Qddz0R?6B!6Q&j|$Q8ppjE;HK76neR2QXJ@F zNk3=v5Fu$}JDq@-pGgI(zUp#1adZ4bVodei!Wbj{Q+&;}ouiqQV-sCvnVA)wO(X@J zgr&pcz}HOb>M3dn1^F#zW0tQK6Lu06|M!HM*~nT)C(zS?nZ?3bSIgTEbZ*rDZ_JfU z$_$DOx(pVe{qLa7MEvrMtPFBYOf0N?jBFgBaY?ucJ46I}P>>P>3j+rm3r8xXi_ORd z4s%XM&=wfbye4@2r!GtpWB?PQ20T82O+9%3yP1iBo{pB9ij0&5IKWw%;R{EN#6bh` zpjH8Bd<N3CMh#%3C5-IIAzY{9ROwM*-(KvRtH3Ce<`xkL57ZytL4iJ?K1vKUbeWX> z{T!<!TPN9BS=ph4;;Z=l{P_5soK#q7g33N722fh{VNzz$U@&Gl3mFgNS7T&nP-SFe z7vpDQgoL6RBRdn42y|puiGhuQgOQB`GHAmD2_VqXIn43kg>|6&Eg>BnHMmOfHdA(X zhImi~+v|;{+CdAKLI%*b4UlTcy$IbbKA>CL85s=qwKbI$<z+$JZ$WdI9BiNsxS;wN zoWvnv3c4l})|~-&YET0nIj|FwEp5ZyBiwjdrJ`*e!bOzgZLlO_P}-g4;hdDfDE9Y- zhn9wsv8e${Xv5PisQv?mu?UkgXugwSA2f`G7@3#_85x<R8JR#Aq)I#R3o$aWAc;W3 zSb>3&fsLJ!4K&rw3_gRY7t|nOi05F1Zfk;sunJrq=u%ABx=?hr4jMR=alkI(2Dc7C zd!fMhH-m29W>8{Kl2TPtRsn73QG^B~N&te^azJ+bn+qE=G9v}&LSYuQ0DIpkc!D)d zNM>f{lH^^S`0r;cG|dL+Ya@qUY~pGQV_9oy#<0IH7}*i2l^L8?LE#A6>to1p6D1^B znB*9lI3cN3h>?j^kP$8d4M`0K76x_>7WPyIMg|T}Mh-}bf|?$^;1!ecT%dJGka1j4 z$*hB+o|Ux~G#~>WltkC#U_d}Q7bAG*I437k2#Yc>=<8~#t0*(bGRO)Fg8~^eii<mt zjm?c2)j@ll&6Pz(Ktr9NCccrGDI>OkE{RY4_tO9r+M1COxWZcG_}>@)vewd}u@<d} zum+V2e9WM*)@QI{SPltkailcM!LG%~#-Pc_$_73S2r2C%%fLgPk%66qksT7^pxGbr zWy+9%0Ilf<FC%IP4Jd(*Sb``;OU9s0p$y<Hq0qx<+CeoPkBYL23N&%bYO@kfoZxy5 zdZHUrjfOS+n3*|*c~>X?+b^hPZy>BBAgZLLDar~BNYPX*saDKDnla;Vsj{Uq8;dum zjuvA$B1oZQ<SW7B!k~-67#TPj7?^mOelSQgq&sj53G%Ul76?J_4VK|x2aR)qPO$-< z3<ti4x)pZJg0zDYsx%Y$v_EjC3$7^AL4bh)bl{qxprEjj6nG^JqbO*BCA+a5lexJu zyRfo4=z3hp5DH`RcEpvqFS2&ohWq%0GtG1SBw!-UAt%qZ_36K}pi6RN9iyT^{YJRk z{Tu{9hg^t?2y=t?V}U1pK|M!721Z8k=oH9F&{=zNP|GY9yh{v}mEbaw+r*><ML_Ej z%+0}$0!>%L+zH#Q@Z8lI<>Fq?4E3z4tU%XHvuM+!Oh5h=!=0KCXc)9G*OUPf#>x!o z4g$(b@^Z2=(!yYOf_K(}+$jy&KE}obUTDw)N|3GIpf);aJk3E7MV0}43wkq(nn(w3 zG4OUw$WAk;2Oyye+HohshSeiJKH=Muf*jQ|pio8%dW3&Kom*C>9}Mga)()I(tW1n7 zpv`xXo&*nQ4_*s+`z~lr0f@`M*bEtuk96Py&EGMw3xjW|6Ep{1WhuBeA|it6$G;<r z|CAYf6d8L#Z30FHeg+1HPfR};xEUNF28%+%06JxdumM#ZJP!&UBj*H-jthd9gBinz z$3>ObM!2~}xVkdMIYdQ)Mq3#Ee`6|PQeqHdkYrE*t@Xmb7Y)=H2Hl|m*^4GEB_hng zASWxOAgv%SCM+oe>Q@RW2?{9*g7%`BnnDH-#EnHEZ7el)bCj)U9$d{?DQ(;i_H1pr zF4;~j-#oq88O_*zJbZju{+(d)`QlVmRaN9v)nZ)~_$1WVH}qe6Vn_(+_(t&D;XWp1 z25AO01|x=9-Wxz08@RX_Sy;uuOP{4dTb<aUoJfeY66iQqW;Pb)bWl?hvTeK98&nxE zfTy`Y^^JoLToD5+D@+Y|^)x6((UeCz$ZM#Bc6sUPs2gb*DJjUP$*O_YD06`Kd4ZZf ztk6LqBhc;%Q0*)NYW1jt8lP;!MvykYsE8P3g(_&^MMR8I%Ol^ep~5^=p2tkn%2CEl zO-zv4D(|GVytIt0?4JN{p8#J!KQ5Qru!d>M^0KP#=8BdoY@%ZRl`f1~PO{1>GP0`w z9u&mJ=Vm6y<wNF<&HsO6-p8cGpvDjcPJ2O&)4}6zO#cO#449M{WEr#>8ny|sGI4T% z7Kwl=U3C^l2GC)PYz(ZR{Rte9z-R?k(BNvf8<g|f*?goOw2@ST=bgA2IXGb5KTb{* z)sYSo@^TCeYASNt^4j3KR#03;MNp83S6UmqLIkw16B16~#<`f7s3<7sDw_&J4xls! zozP>V#uN-Wh%&jdG6iw~<>@??J~;Mt}~YoZ!fm?x}3h)!o^r2ReSz+A$%4DI*4S z_$2rkN>E#n^}hhqWF}<>O$IZD3l0KmjI8W>%1j)r0$fat%%BBBTmcadI-tFNp!H9z z49twI%;{W=pcXS5=u8A~%?TN>2Nj^8bq3xWKq03K(!&V4FN!El4u<IJ8Q9oB!(Jep zK*uOxS_Il12Rf$F*ig$%+e}qONnT1)M35hJ-Iyk$CMey3n%v-|rlt-GLS;eliVV<t zGG*{0Gh-t$=%JsW8<a&s3pmV7O&Is27MW#u8T!gGF-C9+b0{jYvG}mCyZUenaeDHy zN(N~LyYT2+%XxV)Dfe~;*SSgYtLcj^VN_*gRF>zL;^USRvh`+UWSr%tuIm*aw~1YZ zKR5m?0}})1e*tEFCS?X~1`CEZNGJ($GcqvhN{Vr@urX+<GqJFNI*A}bCR9P_>S0+> zHNY6p%*4dV*b7Q};32ba&|DL^xuOW3ql7AA#HJ?Ffm_8?$W%o_RSmQsOI42vegB|1 zEKDE?5VW2}T~ygrO;{8>@d7#zMv0A4)6q*7x|^`w*pY?RlaEC**gCbyu_akVPdq}p zSkge)Gg6~J*hNIjCCM{4fQ`kCm1A;cK)5&~6XRhob=}_9(0X?!rdQwD82PU;Gn>WR zoQMaN_n<qT1(;I6`B96ZVVf`;69*@@{K&w`3Aq)%*Bg}AV2O~84KqK2#=yYJ8JL)` zs7B;REqN_SeiRf@QHSM6=m{K<F-K6E0j*wx<VSTQGw7IwsEF8~eN4=3;(-o{mDNf1 z0TL{{Zb3m2GlJY0UBW%w-1;3{gbW0g47$6zdJU94|ITzsOgtAICzO_17$2Vv%8Taz zd6+&hflgL6W9W5|6k%jx2j4oR!2;TP%E-jZz~aTk$m$MBI;x;CD^Nj>R4{`^44}<e zP!9^6CN$ydpnY9%K!LitY;34%BOS!FwHO$T3_$sbL6bpKP+UYsiwm@A)0AD^9KMPV zG}mM#CJqV(bI4vub?|N(Hg<MF&<1OGfzG(=pxO&2Ce$!VQkT`yV07>mR+nx601KQC zyY{I*=9A`z2hYEt1XWW7RZUYjOBG{%nbv>r8TAo?#mJz*z`%HsNs>VXbQUT0eUGi6 z(amN?9~Ja{kK)SepcxVH@(X2!{Ylw2Mw648OOh=dY^_q5Bm;b{yak`#bTra4fb5A< z|6j^v#-zlc06Hm|54<0W6|^mbg&B0t5CbbiBBFl_x{ro2mYos2%O14zQAHiH+LIN$ z^AQqUO0WSg5jJ*qQRo(V#>>I~mUkGt>8aY-7$^r>`$V|froRYDO78Bq>oy5DQq?xL zl2Z?GwoA0mWbW<t1mzV*28REO8UHZVGl+uL_VaSFvoNxPHjIEa6f}co)tW)gFUDBV zd4R3pvj#;OM5Tm;gg_fcjG=oNg^iiT#6VXtnhP5<pO&>U4VoAiTVXMUTa<-`SwM)R zDDI5k>Tito|Nb*({PUD|6BRHv6=Ssd`vSC9_P+qrZzf3wW6<oSu965d6Ehz>6C)EF zXrc|Y#Q>c3K*P?UmNqDZw=?({8)<5Q8onyZY`kLHte{R1bR^W=oLP@qU73#=zNrz^ zHxLHzY6SH&g^igKrK~)SR1|pS1@ugXxuRHjc(|CDnYnm*SR!I)M)~jxu`;vq@i50m zNAQX=F*6JEdquECr)hF}Fta!~Dl@9_=@@EqacUar@&CKeB>C@|VZ4mIoe?*q&cEwA zQR2c$mW&dhy@230!4C#S20ezdZPIMeHUX%8t_hhSW@lyst+s3NX5ippk7r<Khjzgs zy+TIDcF@iaP0&1NGm-|JY9k%^bhTB~!7Wt@CD2L^$XWq)WjQ9$O_8YWckucJ$U*_o zfz+Ut0tS`I_5l)XjLb|CzP=GVb}%urNccG<S4O*e1-mdhMtHe0@`4%y912QY519Sz zqoeKJ_;h)d40<|JQ)6O;le4qY{9U(Anh(j}T3qZ*%uJwo1y7)YJr3?EgFOzOk^-NQ z1opTV0}CrlGqMg24jhUj9Yh!ybhXt~7!(;4p&<a;M9B)9iv>*qv#~?k(a_lfaG)@P z7fL|=&zQOc<Zqa-;eo-Z0r!8jU3j=1bMOO*uRCFZ;mw!{4*>A`lhFSHOdL#-47?07 z4w4+8#etB6-@wxX?F>E=f`Xv6F5;l$LLnP1&4t0sidb0q<WHrsykX}2cU-|jg3-W` z(UXCZLGZr-<7Fmg1~t&yeO^W;W*$aHCUHgvM)1;AMiy4^vNPD38sL^9c=-spatF<a z>8L0xf;TX+LKcpJ3s`6w0%}CFiy|$KH#Rb3tT^WDv%||W#8*Kl&CWc^%*n|su)W4A zMl&WlG@5IgdzX!axud+IW{9Ipj36t2oKJ40s7Qc5s9DUw^#8+u0mf5I_rU#%T+j*} zNOlITzyaN7ro_O`4t81>^twR~HYRW`2Q7_)O${l41X&rG7@5KQE}`m?%791*L0K7P zMNnr!MOjc-MG3U^QXDiX0=gm=v=SA(jtR7A8stS~WpnWUHBj$B^r3f{umP{4qMl|& zMX0}TKuoZexsI-?f|91EUnCo=JExHa<4<>euOuG_=U{hDHCZ)73((Rx21W+c{{l?n z;Bk8V`z}!;fRO=oj4Y^6137sCG+B(;cL`bO2V2}I!Uo!Q394Hd6+ArM9Od+d8AUDB z6Y?yxyb4=ZZwxQ8@MpZ49uXYE&+X04S5*>N>9lnI`v)Grt9z=N86fR|WM&SgAD}&e zjB*a#oQy17j9xOJ^OYerzb*p{7c&<Na~%Ua13PGETnp$lb7-~B!^z6b%*+tS!N$!D z8RUR;{45D;Vv7SEyW8vyH6nqVkpXmun>3`;ZHmtT(6A+3J0oaN5vJL}6kHdfYUbjC zx)!ItNYEkdiVBPj8fu_Dj?&-*c3@|ova^B?Fa=#s$O<_s5Y!q`Q!_O+7Bn_D25qQf zS2kA$jlQYFuiF(B5n~iisi;h`^Os~}Vu`SDc5$wn>Fnx~z{?^LU>NG^6zT5n&IM|n z=_&FW^I!WLFlUa(+_@e~2A;8T0x8*r@d@CwAwg&FCNnN$`oX}<5DW<#c?Jen(7lkL z`%;-(7+6_byxBlEbjE>p%YxU-$$*YIZ3aykHZw3YF}I*dLl&nAg7@c0YpcRN09ww& zs10>yNrd$ikb9VZ{0#t&cl}Rhv1d|Z&}Qi0rlG{d1ivXki-Cz9w9BE6ft7`|g%jLU z<KgCI22J9DS^+F^TpVo7ETGdMr5*H86f<yhgZ4gvdR#n^SwA!l;Hf-yRYe7PIcZ7I z6dpflih~QZ4~dn9L7Pz<HkF4Q4e+HD@Ff+H-Ytk^S{NOr4U356TtDaVyg<7McV1S> zP=h)(R_PcfrMUEeufY+)7+D_`_U{H`WPM89zgJ8Wo?4nwdZ2|$459y%!RuLN8Jf0A zF(QIO9o2Ure{n)4g&_XoU}J)YgEp#4PR>@yqy}VC2vs$BVog#4!~3#~vamiUR__~w zJj@uLkYow-aA8HH3&^ulDBcWjg!>N^&kPKVZ<uy6NHENRoU*_JDpW;y*qA|EIHetU zSQ%LvVcbY>@On)d1|}x(;8zo9bqphD))w3qgm@NWj1;J(VFqoA2kqeo4cvh`ln@mT zpmhk~job|2DF(0#NN*CXATknkpoXZRC}=~Ov^JwLyO<bgEhVTq$p*X7+sw?IvE9)~ zR7aFk!c5Y^$==aB!i}3%F4&T3=X6FE=3rJ9#zXtL;@tl|WRi?CG+_p{XF>OXBr`o? z0^PNu$l&AP$q7ozUJOi}?3_&OkR;8($-vIY$)3u<#Rc{xXv~(8ktL2BmaG{V6y>EQ z86+4az>O(EaYY_p8OTi~pi^<!K^+%F86hfY45?U@LqCLNs8}jwn8D)5r>m*X&eg=O zpGhLf$G}d7eI_^|UcJgFr=zcG2ns>aeHcu8nI17HGw3l~b>Nd`WaJQJWMKqNK!8S1 zAR{5{TpV2N9CaWU$Aikn7H>9YCPqe%cpgqB4i3mllLXN9f}pYjveDj<fuJUEqnd?< zHGzSZwHq{9p%2povV)7Afh!%&8Z;fCA{MlaTU%2_PgPGr9(0VEm<T`kj3#zg&_*s$ z5epeaft=AK2;D#p8Wb>vt||g8)DVXRp%R;@D3ghucW9_w#LEEW1w}8tjSZFMWaJf@ z9=TiE2mI4zy!`KMBFcIqCHI7ry0YRbx+b6vSB?w}jJKGsf^P}6a4=N`WjHoA(D62) zDuW>&yhR!`;sjd92RemNL7tHTbmu4N#vBGYMmf;IsKVfGDdf~+@FBLKY8iA|4|wzk zH0C1$8j&<LQTr7fX`rfSD_2&qVY$1%wc%{bE?cjJKy7_9Gfg=?rmLYo<^gJQmM(e` zY5qnwhW7H)?Ap|WoZKT_^|W*>6x7XCG(cy7F@eWqm6)zEh%zXGdZq&WOpG23pbHBb znbSeF0i?&x;3F<3D=nrdt|+R?$}6VL2y4HARtB4^shf+5iHo6*haS__Z!Gu7x2vmc z3bm28)7MO@2=wyx_x1B;ysDM%R^4k~>{rsx6rG|XWu>O*_Rl>dG$1W8A}9ltuRwK{ z0An|kGJ_aH9i$P#&CJNiAk4x9TIMb7z|G9a3gbb?nn0VOpoby!f&v=0j*f+;9kc*M z0a7-A+I*mecbH1Ri|mA;$0KmCfzGZ3x0?`4Tp(kb(Blz&_>}lL`9Mo|&z=Pp6f(X{ z%HU<Y$^N%oKQME~8JdIk*BCG`Fexx|F!HmeGI=pcz|R_x0IjVAm6zcCHj)e|>;Kys zd<4Pk|3Qa}t&NEIz|0A%ib3uCY2bBgaSq&)JWMPMQlL}R;pYx8FhItaz!?<Wc|r7V z<iR6tpzXP!^NzrqLr_#iI&iA0s0a!xgLYD@f*b6Jk`XkrCW@4m7!O+82SX<LV@%_c z9R*|r_%y`aow|;AIL9ad{mIPfp{*XDdLDE@7dspHOuo?nkoXj0NJENGex&$hW`Odb z@hJpue1i`i07n*RsMZ0rY#TgI0?AP@iAV>2Mg~yb&cVhY#3%$>$O%3_95Q|iS{4be z%n)&g7Gr-uLL!WjLE-;5##2m^4C0{mzaoq*jH2L;O`s|je4qt5Y?013782kAw<j3H z8O1?a7}CIl9%I1<nO+7hYh=_dZ?rONWn5JlpA{CM>Y^a)#?@9CkT2`uk)0KuDkSJ9 zzz@2U{OA8b#xABG46+Ow3>6N1+>Gpu;*6{e5{zuDpz;~ipI2aD<YZ)LW@Jz2U<4gb z&C1M>&cMpR#>xiT)(F0!Tm#aE#iovpjWwKsl@-+eWo7e^bP$r4Q&pDJkk?RA78Dd# zQRD)R=?fyp4nd7NQDs5ULJ*KYl$F$&!K=NDjZIC|mK)mH+ZzkZ@<gPktLVteaq9~Q zx>`y}D$8lhaxog)=$V-Fa4`z}OE>#>QQwf$jg>u=NnS=wQd&??9hT2+m;#uT7{nPu zxAHK8u1tU=4@roRz}HWJmu<9qL$`-ZJIKQ1puIS7XRQ||4{DtXs|X51woWK2!`pM< z1`Q}FgO;-}{<DF%W{eY(%!3$_+A(qI|6cz42JTxk{Qt&y7Ce^b>fpr5$i&FS$bkPW z1#nLc6ufMZvlJ8<6jYT21yvzuDVUlX+cAO0WZ6M!6I88(N2#GftETSG;gap7;VU66 z;ULp3c=kMtuZOmajI^VkYmNiUcgLV~LqQ%-PJy|O5wSwNeti7qg^{34&A|L$fGM6y z3A``QjG@6n%0ORBQ&kR>C)gPoc-dG*8JSr`z}wj&0jvm`PlN1xKpB~b?r;a^HdXM% z5JVvZs6oyEJ#VfX)KCLY7PT|^L^=qltC<*qcGGDntBWXe@Jeb6n}bJuKus6$4Go}v zGGy6+DP(jSG*841I^<GSO-<aylocEbrpzXcCF!Q2a;!XVzP_c^W#0bfuKrAnEM^5U z1-urFG7g?BjH*0d(f@9+d)NhfF*0-2Pt(wJ-^^#v_wQnHiBh0epqnU<E@xn2Iv1lz zVx*ay-B~tPbHCv5L{O#1z`!KN^n*c)!OuZJN)mJ^IX@pe=*$L2(0Dy4ZwWFmFrcp$ z5C=7!uq_bSCL$^cK3KsVbf|&|8@sug8E9RAxhQyP0K2HNDLZpeI1?j3w>;PC^ouXg z9?9A)p%WhTSCH}5zhYh;A!dFx?yYwW?X~~?{lKbr^gPIVCeS8krZgrc1~CR%hDZk? zX(`ZIv7ne_VPxQCVgb1o)J_uyjh8}V5Y(mwA2uQF0CH_Bcw;5B%L-bL2io%Fz$+mx zE-N7`ET#e;O$9j`R4RgU1o%J*K~|81!Es`0!W`tz%PJLPoRH+}8~*QgL=dBUxGN*0 z=s$i&Zci=E*c4EZ-(wUqxp$7AQ8FRggbj2E6XXAX3=E7DnUol$7_uShOjt@%OjJae z2Q=Nt%*5!$&B)*(?H~-AM?#SS?-vDmOAyo>0Pn|X1*J03A~*+81_lQ3+99Z)K&#o9 zeImDstEzw_K;0ZtE5kDu8yhIuf&9Z1?!m<(8EnC?#K+C6z^mz@{p3kR_+KGL&LkZN zX68U<7F~Z+1ABu<7lc4{Ec5?wjCa8OR5J%-E=JITb<hDDBHZBfAQZqE2wX8i@&h!t zK+c0u1FgRhh8$#sa0zJo&K$gw9h3<`gGJDl?CR{y)hg=wQHG(aa!Ow6W|kK2*NT<Z zN|G!B<rSj!oo$Rg?=iAUh?;A=c!>zO@rfwQDX2?p*^7x<X!`{S2?Pj8Ypcj<%V>kz z8KAa-7t>!RHpV*8-YEvF|KFJXn3NgVID^3aFa`#usZ0`#{ESzbUcuTSj60ZM?GV%d z-<Xt`{xT?o_7I}oZvneEm4N{~*4NGKqk_2If*DfBL0Sx;&Euf-1okPYZD__=CGVYP zEA1EP<KylmrohdoCY4y$ROC}&>ot+-uenB6S-ELKSzMrh0tbs5D|=%>ahq#>SlYf> z3{3yO{TE<jWs+nNW{?H#ijn4KgWqWZP8yIlKs#uglZ2Q6KL<O5FrzT2?iUA-vVe{| z6caZ#1I-e!vB561U}H-%uqjSG5MM3M$;>ZQ9d|=BDpNv0Ohr}FGyH><v2TPR<FkKj zY>aG-8H4|x&dDee6_;_d<u--P$?N@BVSK=($fU;L0-BR&3}BcC4qx;CDol(_N=#}D zpmV)I`@%PY#g+dHFuY{?!KB9E4^q#)jG+}Q4vH^HuzJt|&7ghWHehkc9?yqNYT(Ha zHpT$Z9?$>(8T|jNFo}Zp;4nmh%wY^*SPfPWYBbzt`pclk0GeQ7XYgc<fQd7w!o}4g z;tcEzK1>_n^08Rt{Sop^yl{DT1|NjEOsq)a{vdI1JN6q>H`8ARb<iqUP&O8k<m6yx zWdhx@sKUt3sLIH|&f+EQfFaDx4!+9(q(upQXcl<C3~0QGH5Srj2aSU;bHG<?$_7L@ zs9{$LTH^{{U<}#-4PF_d0=iwDl?8M_9U~*mKy+oG9pQ`&N(!LE>cm9_1$epHSQ*qA z)j>O?!An6vJx5beeGP6Bn?R~IP;UU-ECO#^VKUTm*YWWcuvfP+i!hD0^34*PJzHN@ zM2nZtgiF@Lk<mg+IYC^;*6i<oCP$}WbxXr)mw%@W_1RdR**O^)!F!yInEo&XF$O@& zO-Ty{CMHftb2D)kRwgHH7G_3P9q5G+kjo-uzzWR8nOK+{&6rqOkko+I6rxIVp-M+W z+t{iM(3Ku7-dr3^tgMi8e|y2Bfei8Npi3=5!3Y_GF~CsF0Ggc!YXlzy4BAlv>R%!0 z1Fb68V_;_BWMbw_2df0P8hRntVb|rL4b#BD#RXLknjOZf8Z_=I3tF#lV`XY$pa)tE zs-!3<BPPPZ#t_691UhgNX`{1=8hqn|IJkHM71O8@2|o1&DZ)j-Lq(urd=W7*aq!0Y zJFo&;%+l1vOCvu@O@&X-N6#%%1Qg}M+Pr)w5?UVGKE8aqirRX-!jRHk%G%h(Q>}yx zT5yXfD2Rw?Sm?NTu_?%#dZ<_$ASDQRf{`}S5YZC{m;K^$vce)7mfC&+pfPt)n?!)g zj)9#)05p@z16s$1xYvY%fx*Wcbn_LXFQX3!2Ll6#0EYl*^j%O;keyRp+fdk87<7e~ zIqW?C8_8D_EN|QVHRljuW#i|tV6yvrXz}7V3q%bhB=jWaL&`p|oy<Z^Y8;@2Zfrb` z|B=NxAmWT{jK1C~3>+Jo7&oYFFxLJLQpCU{z^nw9_p-(!&-4}|&%nlG_ZZn+QMkCn zOC)iolMr!6Hbx&`H1qzeFbOc(LF5_O83PzCz-1o9{h<(XMm9$OGO#`-RClg`$TO(% zxP98f$j;-)Ai^+>L2x4z(~kdJHW+JfWMSMe4cvPN)w>WgnIU=@*%$-0z-B`H&cFm} z4>9#I*)Z@k2!m#vL1({lvaqIt)~>Q~GNf`aGBbnwl|G==F_4LPUq&C~J@TBg+N#Rz z%EHhMJ)*{<ih|0_#*ES1T@(K^PP}vO+?{`C)r)2>Ud&|UzS3>KJL8vsKSBP5*bR=a z8K5&scpO1z=P@udcrh?AJ_Nf-oIxIR>jN7jD-)v^J0lYVD+?2AD(JeXSkNGek2eP+ z3k!I}%9qhcQbJGwbRCm~yrjICh=91DI3EuKKO;XUr-(Lm<O({krz{8_U{h8Wg{+oS z7X4M6VPk0FSR8+Jhl6EfWLB+%OEQy<m%E7rCo`9=eNZry%@<vru=W4`rs^0SW?*E{ z`~QRSIg<;6B<Su8F-8VvaZV=4p`*-Rps_S?OC$iaVgg)31cG*QiVE{`v$HZtGD@;? zifAJyyhK66f6(j>8uw*%i%N=#S9MjikBls{cCHPJ@Rn6@V*FK+l2O9P=PT*e5*gOw zt>Vrv1W9jTw}8WOHY6N%k;OsjdN%0J2}bX9P~0;@;{N}C2EG3RAU`mvae(x(GgL7g z1H}u(Z{Yj@(dU(kt`Fq*&oF&F_6(ar$qW>4OyW#73>*vs;8O{in7~ov18OFNhn9UA zd=ym_l~_0>Kqr4IgU;6%V>eL)GnmBZO_;x~XL58}Qn1HmM%9T^m~8sHGcx~$fz9S& zU;vxV!yo|)aW+OqcF+mg44^~zU<nkoHx-m%eL<U^L5HM)t{7(EVc=F26y)R-*ETj) z2F++0f#*Nfjll~g!JE*$?CjR{OrAHv!{c&VQgBAbZ%0Ok{*H-LJa1-XZg&KSi5JLz zaF{HFgk=CIOb}%V)O}2B9E-sHa!?wc#AL(34H~rs-9OF3#0)+T6_mz(Kzkv<wY@JZ z=s0gdK>;>SDQ)B|<i+Um@zJA?|8_t#4Ja>z%>>8uQb;^MgTymL98|t71-s4H2;??I zJcACVm<4t_MBZBgRUV{&4wAf=5~lnlaQO$Z*X|Uuy{t@X93XSq8T}Y$Fd*p!hnoun z1LGuSP#Fo)>u>={FSv{Z>1AW|F+tM#|38D*e-*|_Og0d+L1&3nL&jr3Zk@<v1Knqc zbj&O~Tzy%<K`Ow?DTxSCWiLke4-X%PGugNwaDT_Z$e{oK2a^bsGlMkf%qP%Al)Q|r zOyZ2pETDck3uqk@3o|QZ2P0@Fb^tgHgO=L_GWdWFo>Wx=#h5B+-7O;LLTX`SBXdwf zV-nFxvuvH}(wda&Bj@g$nw61at2^O|w4l(m{?Jw*Wp~A@q`Z8AS?=I)0=tJ96o(ra zK$oofGBja?B}5G<KZDe;F?toDhME3<Wsskk)HpzA*Rk<*hCsp^td9wlUqRyRJoXHG z7#J8B!TFU3oJQ3hKn+n)hDrtP>Sy)=4_5ht+xYP9{G6Z*A3=wSDhnEmDw;C!g#UXJ z9?mGjWb^k3BkRB4Og8V{f%7Wp4vb(X8wOzpaZu=TvNN%Au`n@kvofUeFoG`9=4MI- z&5ZkagN7}A8GS@VM8rkF$3#MAm;?m{csXUY8A110fbMREtkqEj9ca&Pswm17>;|&h z%`Kc!B;0N8zc-9a|3x!0{AXZXY9A315iu`59vr5iJj(-4*IU8)!YdXjycif6R6)T5 z_P?5gGH8^Pg&BM{3ZoaeeF9pW?aS!HzyP}PNR*jVRNEMS9Jsiss-xpAM@J(8#_jwj zCj9?A1&qLUsxmMzYJv0U4oDtt2U+s}|8E8cMk8?i?f|>R_cD@O{{R2~nt_4Q7VK7t zyw_nAdC-^(qXIY&g3M*-vHPD5vyb6FGbj&2^!Zt$===W^WIZ_lLG(HNFNEm(pTu~K z$%a9V11!#Qm{A!d{{Jrn1EU%^Uqa0Dxr$;QgX(`3hX3Gv3DU>L7yug2`Tzg_Ed~Zg zPi9a%1EMc*6Ouj##{awjCowE$vSHu@-J`?I$jAg*_{8MJzz8}E2z(-*52%Xd2JK<x zW8`Du6wzjf@2Ur%|HG&w!7t0Frx_kLkIRLb)!2kd_wViau>b!-W-}^-!|pIRY`s>Z z*bPeOjK9EkD>%sVaC0!Rz>XjVr9dVoUnU=6AyENPwImEZ0TpzY1G}iQR|Kyd-_Dfl zH&Zt|L@?R>dnKSGc=^Y_J&ZiYH$edlDyNh|W;3aA90kXBCn!81d5duYlMMqas3rsr zaruB34#qJsf||Sx450N3f`TlZV&D@w6a^Rl|F??C<{z&o6QrLFD(4n}(-CMd5j&3~ zG~Phsi^1W498^v)sWasMcZQsY@!uKL>I0XZ${@R$)HpzT*?2lZMJGs{fdL`T2r92X z{F?#M`)>wFFX%i#1_s83Og0R>pb-roZZ1wXRu*OsCPqfkDWj0!0w2)`DI0hhctydU zP!&}KEol`r1|3i&%DC{~Dr41%@G`YIo}Lettj!s@@A_ILAA^Jo(^MuK2651N7ov;| z%#4slji3^TiGcxPtT=<Xpt!go8>pQis4Qq=W@fI;tjw$|A_l)&mT77bXff0VpAF1R zO#YQ?m{x;}p>z>LEv|nGj1RfAjl}=WWwQBa06MS?Qr4+3*)Rw)s5mI{Ff%bQF?z8u zGchswfR8wa*el2&C@3b#$_YA$KpE+nV>LBXK_->#fA?4zS^cva6+!wyh290}K!tyM zm~8$TiTWusdO+)FCKYhJodc%_M`&9NR2Hd#)95*H8uczfN~55-`LE2R0*+URzD{RQ zq%ksh{Z9gkGsuAMw-D!JVq)e+EC*#^1Qp}S;LW%`pgBcf@D;r>3^IZeD$0=H0}XY- z7K37VDcn~Vl&LhdSpJ;>`7M)C8RECw@nN7$rm4et8Rkb1QGaDdLxdkec^%@Hz(gd! zFfcI~{Qtq^!Q{%o&mav-{S2V>4h)Qp0U#HG=W7EQd{k7`ltCGe5wf2ET8D~>p<MLh zVO16#Rbg#i5fxo#_0J_FCMF~zB07{&KBCpjt1TkD#ml=TJf)&MHKVxv|9^<R;IO{} z3473z0=PJ+ZoL8yd*3>cdl79nuzSIA1CjU2!y*qZdm-l9frfkG=7QQb5OD`-NST0Y z9y?<Y!%T2p&IIYnfy!BkTfyZl$WC@fABF~q8c6FLJZEC?{}q!5QwW0ugCc_#gN=iw zm?&s#o0_Vu3=1<8CkGod12eOi2qU8hJ0pWT>~_-t<fe+ct`<@-!>8&&Th&3k?!e(K zE(|(ajMYR<of$Op%LEGbP%9+^Wes)fiYRR_Sv7riHPwGELLwhEZKA^&lSG8ys@ldv zqCweE$xyx6GrYx1M9@UuLaoqU-$#ZqRJI~n-$Ux(TA504IK5)>U>0Ul<G2F~e;!9; zMh1?J%#0ftA^mSic!AOrC@k0*1Htt)G=9M8=_k{ECT9i-231CO2QFnsW+o-*#IjOA zgo85ZxCvHfmQ-#ICeR5B;NANH-kgk}SwzrPYQEqrrPKo=96&=opku{gN<r(90=&Wc zpj{PoU3vi#4i;z@;LsJzz{chawidj6Igs5)+QAsE6@2X}L?<YwK*wVEc!MT7A=(%? zIbpg$Lq_sal8g)ra+0c2szS(%!k8H(7$tZ>y+<Q4aiktMxE%`4M37Y&pi{;L)zlcx z1@%N2O`l!A{_NigK^>8>QfuqdsEDwTNO4s@UNt6X7H0Pq?)%+Yn7vvf!dg5%OVct+ zS=kvEu(C5Sf$Pm9Og0Q$48ow3yg{eTGckh?#D?5h0V{GC8H5FSxxoi$aWQhS!Moew zJ7nO8puW$}D#&pU54UslwsZ7mvWW-@O}fcs^Y4kCttn{m8ety~gDB|Kat3AwRu*Q~ zRPfn;EDWg(pu!qbf2t@c3JQW-;Gjj_psQ+(LAS!N!j>K}9syhBm!0+RF2p`YrO>2o zCY!v7BT(zW>8b);P6;u{fo2t$85u#hJuxscv@o!+fV=JByab-p31kEnS&AZ{UIpkP z7SNst$SyokUP3Fjd_z0Ra`+J?ms?15Y;br)ObDZV%2b(24T!R<vLZF3xB?p1Uzltd zKz=uKFlGfEB?3B$A9N%?sE^A49q@p*m>C&Fg`o?J*cf;idDy{$4mw*2<S<cXL3psg zylZAXKe;nKJlx;P+10_F$!4*6fXKfWFPLopeKIgHN7PS@U%+K2XmE>-$MFlKECaPS zzJSZd$Dq8+=nd{$Lh~l1-eUX$uD2liIzdOQGcYn}{{O+ah{=UPok7n*8+?unI};-_ zWETSibXE#HJOZl_R6*ysa7t){&v60GLP6qE9lW#%6vm*D5l9CMG|b7kC@;yvU&%Md z#M#Bc!_OqrLN7#FM#Wvh&|2O~Q`c2vo>vSXUx13PmbRv(l$)!en~Dg(tAL=Ex}1`f zprD4$|Njs-g8lp)QeWJF_!;bWu%Dkp{458m4-oxn&Hn-*zcHzCfb}s{6=2urh1Sp3 z{I86xkEauK)iMJkgX{mFOgc<13@QxGkdbTw6;Tmp1{O|6CT0#sMkdf6HWVRNCh$3d zasd(GrG?B)49w{aEG*zjeQ+(y7|+Vc$QTIPF`)#iO3)OrvigGRVpzhCbl_4JR#8z= z5n$((hOeE1HX1+^XQ)@&gT|y8YvTg*5<|>n9M#O->?7s!c+IrzoFj_T!jps<ZCQie zy`qJDc(@I8jZ7@+6jXe@{>^60$SC#(9mxhdPn&TYlMMqqgQ9~RXw?LBEDIwuvkz#r z4AS9ZXJ8i;gfzrNL7hNlQ^swp!dEfbc>m*P{0O?AjGKW0Yz9ArzJm@cBO?pwsy3!n z(5N7LEC(YyJ9yLyJQBpf&%h7uS8{^<2RV2Ma+{PX*yQ5k@Zw^S>D!!t{BYjp4LS3h zaT_=dyo00xKGZb8{a*lNKa&~<sL#vBP*n&?1Kj_Wk;QpB-$L4PuK#~9@q^o+iVkw1 zekLQh^n|5;1_lN}20>+EWk}-_)M!%!U9ACH)?#KV$i!b!kXstz>E`0jWb<!EMoDo7 zW9Glvp1!{BjOpO^1lW9VS_VzXvGF)6K->cn2eo}ZgZ<%~gX#~6JZMY-BJUN0MIPMt zftYK@f^06R?E?`9Z$JP4p8;f^7&zQO=7HKi?cjC|BU0N3q=p~d_5rD3WAp*Hx1jk8 zoF7!cVWq-g<e<;b2s%}sfeCc(88fJ3&d9)+3|g}Y9z+9|(t%7q!pg#Gs*0c?8CIlq zV4$TOps`h?kTez)VP|7wEYKAc=irkSHZ{_dQq+J3ZG@YyPKhonqXi4Ak&cS9I0tel z|C>=@W$lU-)}V2Eko(yg{TZfX_anGJ3{u0!7zmzoK==_f0P`DM-YYuDu`yzFNEsLy zco=vjz?~~&W@BOaMR{k>Ce-lov#|<s)g+!{viaAgY%C^bDa%;)_XwynAjrVL^qI+q zK^|0tO7OEVgN_dX?{D?-W@Ul*u;dx!B_#wUKwShyX2=cR%*sgCfb6ql0?kY_{!ZfH zWoF^#NQ$2k7RD*W!p6rP9U99i$jZdU%^Vv#lQCP~MqJWT=HEmnn|~XW17&2KH5eoR zEm8827SPe;W6b+|<o|yLu)DzN6Exq##^YE4Nk<TIQ2P51>d!KIF>Hi{C9E9`(+f_6 z5WRLW$a+C(5F+jXx-y!95!@^K03O$ocaY&^V+Mx-Xfy}Ze+Bn3g@l9zLA?)ic4c8^ zV{vn1W?|(YQ<DyEOz7xH+<G|W`Ey2fM$uch{=N8j2a<n5@pThCwyo@-z|O)5HWM1I z3}7=E7#KJhID~{ieR@V_QDswRV_{*&n+GBfB=q(%+5B5{?-payzxRxS;4}m_4-_7p ztdP3r5yVdraU~`-kT@e7qZeA;1C|Gc1xOw=7j+C-pD08h0~?RS8Hl@O85kH3gU3tt z9dtm|FC+M_B9JlACMXjVr1*uDm7ENmLV`k|QpnhpQPEUUlu=PsmQnxT9mdK3E;5>1 zFz)uW{O9Hg_5;{#updBYPq6Vgf(M)aGeE>ae&7O^Io^t>WeP-|l}U{gBo7*gfb@@G zxdYV4G-i}%C}X<G=nfi#WQ3ociZ~k-R8BCmF??X$!@$iT0a}5>$jA^5@>e`43HYlh zG4YCN3&Zz2DXF>YtE=hjtEuZVChF_x=<Dm~{Qu8j#PE&j591HUb_N{=BPIm~h64-^ zppfI-$iTRRNdY`60&<Ty0|VnSrc(^=44O>rFjb(lz!?}A|A57fnPQQ|K?h1`f$xkk z0NqasSyzj6N0$b8oNyrnH-mzMEH@V?2P+FR69*`>f?N;Ux75twBMM$*tEdPbc2pE) z7ZhjI`u8s+gpnyE#6*}`NW{cM<j*@{P`>A9U|<PgI>n&Lpyi;hD#OnP%K2VQj7*?Q zIYDDM;M+GD7(m;QB?ToV1VLBVfG%%`6)cDxugt8+qz<_T6IwFx?@P+(h1_u&*}yFf zzT>hoa(`?qD=#+_vmkqGY$l%sE1M`!KE@T7LZ+s|jMx5}F+LPFHV}~Tk@_djxWp`7 zSuM`sUjPH+|JVObnCh57_fHu)=nFBjF$*%XvVq10!Dq~-f{u-6V@(D%64XHbT6Jb0 zRb_Bx&dx5aEiMSY*GdpHC=ISMA#Ij8&>dG%|E735h$(V&%Lv%mGPD1?$f*C<jM493 zxu*vQizf>k0}}(=e-~EJUCnX~Y7G7kKHMCv%&ZLH!CzL;`4pUt>}>3T3_LuHv3%T2 z%#4g`-n?8)Y;4T29H47O!AI+=sVc}b$T7%)meYfr1u9qs`PpT)83h#ujRhG&H?cE< z+$RdUyju~p!_kh}TpY9^SCPqy(IAS^I_=*nMwgs_d!znchz|QF8fLEIXr#dMaS@BW zzNG@AFVm@i#~CgEEn|%OxAfmc#;kwS7(IXf`?6;bBahvzm8<*%ttQRv1Ko$s%)s{F zfoVR|DFz7!1qO8nUk5K4UM6-9WmYCGb|x<db_Om6cCK`8HYOGZmLLWW4#rqenW*N? z$;`ySz#7NE%Bl{!oIzDZNl{K#3bx@xOk9wMT?!P`W@ezJW1z8E&`p>i?}0AE6E-t5 z7gT0rV^%a}V`pPy%MsHOa`6rgmsMk7R1XOMCwkQ^)Vz&Vp^8zhBwax503)ATlo4-) zH>1?Q&oLtL$0Gi={QGp^023>thzKK}`@(;_ZtE}`M1ayX<9`RHElj5v<QYZ1H}HUN znigVYVG;!2kt^-Jfe$Le1{VPx(8-0Q#sS2EN=Jg$lz<G8Wnf@o2m~Ez3tGRU=FJY; zwZs??>R72Wf-ZRgnJdT6$i~3H2HuGdo~Tm;P1zx<0@+2-DA0Wogp6`f!eSRAqdLe! z@GP<(vri;wOaOFjk356CxT?CKpdbgkl(wp%vZ=D5G9ME=Xva6G&jcF3F*CPgGFKF2 z+7ce}h*M0An^(==SWualTSh=mS(t-ET$+!u-S^+;15DLki>H{l#2T=(db6?{da9^R zK9c{pnSqf(>AyOYD$^+jC5CqI4WJPgArVGq7Jf!1Rz^lP24*h?MmBe82V_A;h+rf{ zxhx|iDD2o0L8p|*GO)0yfd)Fjv$X0=KGF`#3=E)~@(Ms_)iJUqVO16Bz!eI*;Z0E) zoY76qKwUscmrz*|S~G!;e245`R#swj=dv=BceA(FHM9SBim~NiH{;WP)u((S)WU=9 zQe_m}Z+fr`u&c-@DB3dF``P|IsN$q$?Zd_cN@p<tYJtv~1p8Nlk(G^~k%^O$kqhi! zE|7nb1i}90a)<g?ot=?|gOQn&g*g@Eb1nw1MA*QN8t7yjgwJ)MK1XO^04*BeO2Vo> z(m_B|MP61AbRmI|ilQ<%yR5c2T1c2Hn;M%dnktGi8;dHl;|`J4oqLyp!enE|o&{J# z<)6=2Kihx5eBMF>=Kp^N-T&VhKQLWkaAz=MQij!S42%q*J8g@>cR;B-sPKaJy0J1s zZ)Id)U{C{f<Cqc{n3(jKd{kA1nc2m);kW355-4;ndA0u!e>FW}6=6Ozai74sjE}@j zO~w8x8tSvNy0LTmGB7ekF)%Q-Fr8wMVX$;CljdY%1r5)zGJ_^&>zKfo1TwQSFsCtq zN@mbG5$Y_U$vPPZ8DV8nP+`o;F0CyLK6)H<xCr>f8c=T*w5v)P)HN`jx;|>{+QQPP z_}Hj~sHy@cS)as2pG4lC+-++UQWE1gZZGKMNd&b9K=+=5?ruHBAjqHq8Vi$?=4WPM z0aX?(pb<W1kb6KrhYoe?G5Uxpi>V2+vP)_+f{%lMq*IWs%+PC_Oik24=fJSBF}Cka zJX~JBWXY1n<>d#G4GStN^I~J75~CTnFpB+qB2XNfQd5%>S}edQ^N-Itz~9B*i@mLl z9dy(>BZDpEULXcDhG2&P4Q?hTMs*%07A9#4CT12>Mh4K)&@4>MOf1ZGY@j)}c+g22 zy56Av6GJ=)=)fU8(DGChBONVOWqDc9qI2;5D`t#lT<jv+;MIlD^@QLJ0k9n-rpA!d zYaro?v~`|MSxKFZF*vry)~+N#&09`M%tSUQDlJvsTrx`1QXw@hI!M+;Oi9jLEuh5C zwk9US-JL6bWq$6$NC{DA0nwQ)?eissuU{7tpWogxQ&hlNR3dU=ZvM)6J3DYZ{C~l~ zz*GRfk5-Ps*uj9Ek%1A^djj1i0$m&gy{l9gTz<wffX~2JQB+Y@QDS44(iVoCai9(= zPDDXthM<U1Hiwoh%8OME#ngnw^z1@Hv)h^)8&5}NhJ`1F#WP8m*mAJC3x=fDWG1EN z`#5;`n1BXWK=ZQ9+DxYyco+m2Btc{Jpv%qJnAlT6EzwvOMo`)W-3k}W$;!bDb_*{r z1B0ZvupqAhuK+(Eba@IFySO&Eg&+uBo(!s9Rbj4LyNZz|tF@`2i7`6r@14w$@VKx9 zrW(J0S3z!JI`!8K<{l=7L<R<CNpO2g9&`%>GiaR*3o9c_Dg!G67bh!MDzquZ$;lSS z&B4URrVhGLQyz558t4>h6-7|S5#(V9Z}5a2r2-EpL1jUBP$fo9j(YhrtF5u2>Ez_M zP)D6gNJ#K%1UpON?*o{#7{K|5c?;831~CRThHmc-po&o*bmtj6$Z4R1b3pFW1?>`M zjt8Yqb!Jdi3|e)o3|Gd)qy}1r1|Bm(Q|h3OOBFM-I>=P;W->ii(5bTAYHFY+q_8pv zy9}s<07?pC;-JeOz?CUzfu*Vmcr`63wS!75Gh3IgjJOtWj!jWf8(7@iQ!=_-nfUY) zyuA{1b>n@!<MkNRa+byV^~N#kff|`<v%_PT<%TtRcr=AYG<tY6fzvKHZq6{BW#DI! z1kL7&GBPqSdT}s<Zm3{pWJv>sfSNZaJLtRtaN|-?0BPuoi(MMD=T=Zr*q9MK87izO z$Y=~&AIZnWo*2cbRvF7E8dG_{I;Qd8PsZ|<+8k2s%>06EOsD>xV>JD1%;@!R8yL?h z5OI~@*U|ztCm@@IyP3{1FoRRDA!r9X8zT!d6H6Ls1QFck1~1)GXYc_fTu7qj<N)3D zDag()s?Er#$SBUn#?B6M3NyQ+I%655=-*OCNj-K6cDHNJ91{I*j5A%C&i*xKIvXPH zEVgZ%h|9mFJ9aQIgU%sjy2NyfL7YK~K?QU^pa3ru8;c+h6FVD|7pV2k!3Nsp%K=&{ zz`+1ICKJ5GRt>UpRGraBMp{8$T17@#NL(DW+aDA}s^I%3*p)$zAazqkQFb{dadBlv zb46h#Ha2!eJtk!)x3z(54Wr$J^u4T3F*%;L^3)gdi2nC;-M=MM4eT@p8Jh*v?F^PK zUApw1Re%oL9}|;5Y&w1xj~Ex+`S(!Jz);snn1LA{m)s1Z43eO8NCd&L$;QYCy48>! z9-R#A?98#8tW4mnFDAyoASNj$DIw0w16ou9&THK4lJJOCM2b{?CPj5vy#6gkja0Wd z#+flFF$<5?y?_3I+BCfX>zEcXoo0|@NO0g1V`K&G6J!OQI09PnEW^OWz|;b2@v?zt zpTNyC$Yup~(7}=l3`{Jj(hLmhpe7u6Bbz#lPox8vFsKzOA^>WfsVaj;kif&VpoD<j z7Bv?(W?B@RCn(0j8Og~m$)_fyYN02hz|Aejt*j!xK9-Tu!6;bc?*yg-oh027%Lrq3 z7B3c7J2xiq_=4zv7jXUW&bXiHDZKpw?zb^lFoEh~Nzg7x7DgsUra;gkZEUfi1H06` zIarw(8NvH&!TCs1LRg3aG`9~9Z!UHzZAMX0`3ma3C<_|HJ7mli|4v6??SlFKy^O8P z1?sB*|H?d#=@f%3L#P86KO-|EA82#37o>y}2jwAXnguOdjR$3Ma1cu)%YZ`{IwztB z+ONhb2x{aDfa)tnaG8XqfiJ4alpON_djp?o*T1t^oA;15Lm~qMiyJuK={jhMaxpT4 zR$+i<>7gA$&~O0*gF0yBg+ZJ_Tu@M0P>h{jQd^N3cJs5av9Ka&nXe$|3^QiNIj>om zS%O>dusmQ~@b5_^D-+8*rXu-F%YXh%r~Ynd^7Q@N%(&eoP2q1pI9_f4e`C79bd?Eo z$|eIN=mL9IMiU0kjZBO?7)`(<E-avS4M+`m4S_m?F@vXr8#^N_Hyal-3ll3#I>@!4 zb$PnppgTPvM{Vjc_-Ja#%77LD>+5P5YZ@yn%Bah#i;D_K3rcgcGw?I=^PskAKnp?H zKu4N@8wH{wV&>qDIgl#Y7>Ui;o<G^cV{$?EByaD@*_DL_l~qMWVq!8fV&by0E5&7G z#KmP~xMG&&=Pr$jUYei3G{$dsd;83p?d`K)Nz2GcBV)*To$dc`EdQCVGN^OvF@bJa zWa9)~*aA-5OmmrMFbFY7fm*!`tZb~!pq=H6feh^I@bnED$c6PP7#O4^A$MqqA=0-X zxG@18ZZI_#g^f5sMi`XsjTBi!=OTs}{<cAqx9!v=%Y5&jgO4eI_I(I2eq*}Apbc7e z3!cYg0Ucz?$N=gBLDQ@*sKpN{Kfrf7fv&LQU;~|B!V0-e2{J4LIxGOXy#Z9^qR!`u zim<W$vP)LeNH+J3)$`HQ3o*6Jbg)j)mecmrbPUq+&@qg(a47m9B^oB75D{qPZY3x0 zlH}!;Z7Cz}DJ~h}YwBhutLPr<5>#vrD*x2}e`A@>bcMl`q0>Q9pOJx!my4a5l|hP; zomG+%w5P{_k&Dq2vXw=dlaYagk(Hf+HI;#ji!m0|ie^*;wHlaX*;pV&x3q&cLKS4( zgn^5TJD!1?Th|*jdj)P~fM?+J*nA=#giMTdwbfNsR8<5)V?x3_pfMrPNx{gYLdu{7 z2-;~1z3mFL6xtNp=!4(dz{IYldJTD;Xs_#p309f9dIg3F$t4+SiCLKe4lWT|+FI4V z#g$CT25w@E#wg=OetKbXWrAWs;u0QCE_UATHfB~z(zf#2DGZDZ-V6-P7nn{lD1&xs zD2g$$Ftam(=A1!$H9(zo7RGdTQ0=7#TE3>v;3EvW*HlGG0MvF;R2Bryu0Zdk1q}>= z8cXJgi7RtKW9AD{c?m`V(hhZ|N!d~MZbo6|oKg19CP5}qjG6|rGE(x<(TvjnzFOM~ zi^wU1ST;7IqKuKCJtS=ZEt%7qPBG{+m@^!P%!~>tGP1F<LPjH)`4}0QKzp{(1lgHb zydojW4R{$D7(j!0>7YX!nOK<9K?l<?GBGAIaC39UGH`OLdGl~Fad3d^L3K7CX$MnG zE$oaO?4h7z%W&%hpX6h1W@w<NtD~*1rmCW>q#!3PDIo@08Nr~>sL#hPqOA&Ac@95Y z44x^#Cux8?QtYCT5kk=Tjj<UsWR&oOzP*)#va_>|wwR%`idK-inxCAkvc}(i;ikGi zCY+2hero4-u*qtf$T5b;s3{xqF|jL1s~U=!a`B1^Yv`!*3JXc?XXFjK_`K+E3m=n$ z!<1>=mZ07V1NVOcrn%t$wY7tVI3qiw7$X~Kq>z;Xd@MQWcnxqR3hvP((zh0yk20j6 zpae<<s-RRW2s#EDydK2}bgh#zXz3;>Au~B!+wY26#rW~<(UZZU26A%BT84jY4gXDJ zs`2wXy6xZb;8ZRjP77<Od%iJ=Go4}(0<Fg2Wn^aH1GPlGK$RvVXtDy_8U?pO^jLgA z#{q!**XDwddK^4e3b`-%;WZ|nJI1<#3WBnF!Eq-TxA^(}^K`djWAWhu-42lOUxVog z(<ug3h7()m7+Jsvg@XqDKzA%KF*7oOZw&!=HCW;pSXk6S1J95fBDKJ`zzPIJI4FW{ zMg*y4VCG;1wFg1F(2?}8fVwZBUJh}F5@8-_2vD4n0kjEFQbJr*kdF&=W1T9a3et^r zilT~;!w(c82grb0IUo!^4uwtmprL`jKBL{gb0PwQqKt-yE(VtWBBB@*qtrB%1Kn=u zsH*Cj3i9&ssc9?eF`fF`!c_A&SI|LI(*<;wFe3x^e>-seNP>EnY>X_7VvMXT;*1Qe zpmRIf7#Ua@l0j`saK!{3FI8vpVPpVp!T>EK<zNTxd|`*w2%v!wXuN^fbb!_?iL$X> z)wg#yyUE0J)678If=7yzSN@QNiG>R*Q=p&U-xghYOIBtZ7Etm8ts!9g25!TcJD6}Y zGBFA;vNFL(0n*voK!q3hAbOZf7#Ki}8D&9XWyt8Muqi0LLQ)N=x)cPjp)xh)X5zW& z>~0$G5EbQAWRj8tN~wFTZAHWwBmbH)YD!2%N1p}t=NLhK0H$oFD-3d=x)C%#4Z2&C zkCBB*hLM>CbSD=Bs3VmQ+l~zxc2Q^c5mpjbRfUd5fNMfgaBovo6g<c&3R>~1ti;AH zsGOJ*4!ZPISw!E`A=fA+H>%4d+BS;uUv4HFi$AEH91n8Mzo(4c6(VB)mV@fO#Qz%1 zKbTH2s54yIs)&@f)nMrrv>KmP&6|UfjSV?<gI1;?Qa7m24bBM+%v|8qjiC#kzKJ#1 zffzGEX<V9-0d#Z{=!8HCaWN4AUT`{BXH?^cG~Pg`<$}_=sEC*`S~3SGbx=z}nXwR@ z)VKVLR239s++yfrVD(ouicvP2Q8vmCp4R11k~%24=O~A1x@i3W4{Cq1vN2s{Vq^aZ zUaSpmvoi2Ah%iVp$U*K37Z+w?VpNo60$nZ5%*MpT%Fe{Xz{CO?k<<m%mwF67Qc?l} z3i48NQgULV0wMw;YRVk!VxZkmpqdlBV9ywIajBY`x~QVDDH|K;=r2=6Wl=LTrVHMa zv*FFoM2@)Fe;<#;#&fVH#53|AiBDim%U>D;YjQee)N_6O$X&NBuZ{cvf9_ULdHVnA ze*q?W@V#e_4t6YzjI5xw_Do(3%nWR-%xtNk@?8Vety71z-`E)$7{Ki}Vc01{T##di zI3RfzQel~bH-CVemx3Z}lENyyyfT8$5sb1C5&s^$d|+esWMPY9O1*#o@AEJJ4tvKi zFfj=KcVlT_l3<WwP-Y-zo=pRDo=sUvPL@H2K?ZZ44Kzk22)Zs_nHe-4f|zGBGXu@D zF|ivnK7JeVG~wxwv`-Ol{X+kBhiJRHG9E2wRWw!p$|Q0B{=YwrEdT!fd&Ma5@57IE z|NiXS#mEx>xyIFHVv7NIj8Evl8<Rcw%pK57p|69N6b}<ShawB!c{L66c{LSf1$h~1 zNznDEpwS9(QTV)?Iq0NC&@l{VX6B$I464tB&CE?fciw^11RI->uc~C7ud=#`1QVm6 zSKz<W`2pVLEP~O`HNy<KWp*(#o7zfD*|b{UjLV_d_n*PPzq@uZZeg~VW1anIm8>k2 ztOclSVE^yNWWglCAjYr+(mdh@6;_O1yo`*Dp3)8=9vhSgZ9kz-aA|mB%$0#=OE4z5 zG(bbIh`BP%2`=y@uxJxp4xsTUF$OUq@cb^y^cJFp44T)n2n?RbtLJOUE6Kse$8P2* z$ms0$pJ5l{`IYD6m|2{dn4W$42kJ{PgU$|P{Kw45AjhD|V9F5Y5DZ#1EXv5lD#^&k ztjoyG#^MFK3luaw3Ob;OiJ6rtoq?H?k&T_1EuDd#fq^}o0kpZFfq|XDUt3E--cVo5 zRNGWdMP5@uQ$s~fnTrj)UJ;a)O-;bZ=72_%mDJSP*g@x@85@Z)D}iz}c&j0d3F-zh z{?m$ZscF~r$#(MdkMq(FR}p7o;!sG?icVT#>?<h~sF0%Lr4%Y7;%@3>W;sRML;LWa zkO?_9zNQYY0({;f_QpaI!Hh2)P5Ah{6x9D|iVHcp8>(xAI+Ec0CctFKB*DPTAOhOc z3)*eN*uufc3Z6_)WoKamonR6Qq8UJSH3O3`=oUtPJ_cR}UT_zZlMS@h%NR6o4LX|& zDJNm(pMO#R<}phAd%>6#ey`BguCYu9ya&wu|2ObCE4&Pn3`!25p<ZStMo{ycfq^L; zWPd!Uh3~JTs;b1o2H6e@SxyTs4#BlDxJk^$I5FPe*iSn)(AZb!zq+=ThK9D5IwSAY zCbO#aDUD`Tsd)(rd3mw142%q*yQCeNlo+Hz=Zb^c1QI+<%uJGupjGnF>MtEUU>^=1 zj9~%QZ2pW4Vj|!v4{1heRyI6S9-?e)jJ3&=1A-<e*k&k5t3+s37Z>E($7`sBb6Hiz zC)ZdB@_6#_rl%yPgHJvJw-Nq>cAkYWonl}G?RNoX!WL#mCPqf4P|%(rP^*>+d}l5z z1FN7Q3!9iWBeSxwqA6oYLqzevW1yjZrUuXwT!v5v24)>52?lP^`VKZ$W{@c@44{Av z1%-Dk3nLRa9^u1^>}-<S#)9D8bD+k#U?|h|i02V6K=%|gp8ID6!l3iKE;BGNIWzqL zuRFGMFk@q6W?*6foy5(+4!sndm64G(6m)M%ECVAeqc0yX1A`zxuPC1=Xn~rbiXsP_ zIA{+OsBgmtI@QpWQCSq!^fytvHYG1Rt>pD;#wio0Si3th{rKnN>+K!Mw9f1Auhkj` z2Fjp292gjwT$z3{2r@{4?&#%YWMg1!W(Dm;1g(inWnkiBWaj`)r*JScbA&Q*aDaLw z9L&DLLJSOIB0^HaQjn27Wko?jZZ;`xVbEy_qQ*v`j0ozJ7@G>ioO5;M%IP=LOWu^0 zKI@-o?d#6;^P%UI>E4ly=RF_({RwdpC@dKa|9@jrXZpb)$RG=v>*Hr;0?qU>fi9VE z2A@C909q;zN<^R)w9JhDD&V<3P^Q6{>w}!Y0Zqz!v*UKfMpf0-RYk_^i1P^y^7ixd z_h<aT$no!~U}IcfXJ=kqgAk+i-|xOD$$kNG;JHUe2Ic>njHj6-8I%|<LXOrD0v(nm zfI1)Vy+Jo1!U0K!9XxXlo~cJDX9o@2FtWLW7DIqWg5?+)89>Vq*pgwh@Zc5!s90bE z&DBFpRc2skV_**lO>VO>;8N<K0y_AGje$KKGOv%_#K=eoZbcQ)%)TLb{slUp4H`HA z1(GsiY9ADXN}!!7#_Vb;5*oUS+V*<xPZ*W{ePS&C_n;;#Jk;MjKv6{Rx*I1CGqa4c zyowp)9Cyoq=^ie&?rdBPh;Y+l_y!F(Nk&#S0n~YYh!2GjGTh*B1JC#)34+6o3m$G7 zh#7oFMh0$1E(We-*c`qF%A7yMd|iZk25v3}Zg5!Q*5sgvq@Dq+0~D%Uj5utGjC2sv zR990`kb^E3FjNK&IAH`Xe6;}RU^jNiIHxjZAh%~u%L4^-Me3w#tO0$%VUD}yDu?yZ zpoXp$Si_{m;LZ@nc%K2fithh^hM@o77(JLInAjM>ZBho%;UJ(kDd9PN4e%|y>ZH!; zSNBKs^+hE|xOsZHMI=QqwmJp}JNj{^C1j*{I6Hf!WW=X&`GLx2CI+Sd-x!ZF{Q%AA zGnhFTt4j*7u`q*nIx;abHG_7hf-V|hh74@#G59DcGBPOYD(Q-f@NhFIFe<P?n#G{5 ztRAzeG3fXeJ0^2uJ|@TksnCICbv`Ch5wW+SF*bI(RtmfkLPmO8<}!@YjH>RYhGwFg z{#M#%21aVy0%ly{uI7nOnyxOsM&>>)I(m`CAz{shRytlTsyZIp&IX#={yORwI%3+! z42<yevrHI590JuinV1+=xtLg(B*mDRS(v?yK!=+%U`+h$V@&)T=xJ#vE6Pesh>HmE z@vyTpm@t|^C;mbGEX3KO;2PN+>$E>4qpGv9F)CzN7o{j!NXkiQirCuux+s~*M97#a zxp>>#3TuhWOIj+W6xC!|1WL;UaP_xzOcLaC=H|^xjmwdcojXTXGAAxIi<jG(PjFI4 zOTUJak_M<MVqjp(VNzxgWx$;8XJKVx0nf98W&-p<JsD8t0J`&DQCV3T*24xBA<zX1 zpb3AFYn8!cR-jsHgQBj8ilCUNiL8IXq)XX(j~SDk?7Dhw92qP0Oxamo**Sb;t!MZ~ zE;Cf#Y5=<XmxqCYnV(6Lft!J!K?3W1zlJyJd_NBl1A~N^kN^)q4?iC-12+SgqM#sb zz8|!03FIPBvmZX)zj^up=1V!bj0O>Z|I}JLJK0q;UUs`Z!#9#i^6zt3eM3V~Nz1?l zY7;R1XKDh6jhllr@(e#)EM#)un;m>W3TRjcTr43^`pd~kh%tyVhzf%0PC-E|ll~x= zf#&thA@#Yka%jZth~2w;FJ<T5oBg@N+S$dfg{dhsGt+h24Btq`EB|yLuKWKV+!lKe zDi0W+GrPdb1CX2le`ERsJ|k9(;jjarFe59o5F-n#3?m04==@Mo@P0lPPDVx!7Dmv% zC+2uIMrLLW@Qp+avFuD-%;1?RX~@XECIcr6BO_-40}BHo4GxCrYC*<=%ItUsHa2~4 zc19*9b%-_KyKD6rKx+l$K}Y7RsVHbEYDr6piwf{TMzYvgK?mkTXOm1#%pp6_6irP) z<2LHBVI25@`H&k^89(|)X`hIQVEh5SGTAU8*&cL(s=9lqe@Ki8SCF5r+D|6Q+sd_K zpo@`X6aUQ)(ARbg^fZKAGYLw6pazOC6X-l%UIszXxDzL+o#X}D9|0O{N@HMP&;X5B zGRA^t7}Xhl`1lwY_yqX`1^8J(OO=?xv-Y6#l^}};l-bxo6V2CCZv0z2NsdF3lbKzL z)6A4n&jgg%82JN5on<9mBqw)wgUU>1P_KvybeFm)cvq^AgC{=^6B~=T05>ye(w>Wv zoeg!;9yB2fo&nW>&)Q2#iiyd|N-9bzh)IY^h=FFU1h_%V8DUfRW@hH#se3Uo(A2%S zIXigjUQJDz@ky^opJt$~n3MBd#z*sPoMmhS|IO{}SfFVv&%<aVXl_?pT3Wiq$&F)& zuI>&Fdyl1zHx@3u!KWavtH8j_5W>K~4C=>2=Ip_(T?Q@=CT4a9<}^;wl(7bA&W8!q zmIgI`5VQ3{g79WFXtrKh)Y#luSP>lSte{RhJ81C(JG-L#nqRRgH~zkjyBERuh?!lI zOQb=RLo(Tc(b$nm^2Lk4&)>XZl5~)Cku)_Eb-uW26?pzwfJv4~l0k+c(SZ+io-d;p zCnKXUBLkBsq>nDm06iEE+^c4YXJ!OX7c((wftFIrBgulrSy&)zMnU_#w3vJ%9XN$m zGz3MUbIG9PBFe(b!eB?UvB6JR0L|0O#`y6Hv2rp;Fmtf+aVv_O7>P-63UEltaCaxX z(6AT%yM`%5%1kZY$BB`{gN4aRfwA@fe+JOlh%%D|gFEAWrV6BdF8tq(=_->XgCK(h zVvZhk>>XqdQ^T7b6yUJ(nt=gy6$OJJY@-%rj$RowEDIW?6$D*XWNgZ83|j2UboCRw z7kcQ^rxI30Qzl8bf93yR12>HS3>iCJCbodaz!=#7|73aw9s?_YEKcR(10O}k%gE>s z8S-F240(V?GbBLM4Xm+jjI6BS5JwuvkU^0`U!v>4$H2fK#vlS7zW_~_GeWkmp{$26 zHf4JDDFJo-;uFaEy2#@fjG(;62rA#1+ri^bx(-?*JRG3mJJ1d&mRRt;@fzOX{U_?+ zBTB>>L<L2~1O*WmgQw<|nU$eOCI}m=Gq->CXJ%qv@3o4V*}rt<8gWL5&0(Ut;{O5} z*X!#4TgxN?Vu2jM3@*dfnUokneRx#{I|pk9Rt`p#>32x6$q*0PcBjYSBQ3?x$H<^4 zFQqE2Dk{t;$uG&l#=y(S3!0&TE+qtY??pwRZ6ol|Kgy&#qpo|tLu(1>I`l%w&F9`> zVsdg~BJ%QFj<u1k6Tp|BdxCE|kB`rvBrPi|4Z;kdMctq?LY<hDq3$&V_1)MQS=bp_ znOIoiD+csIIRm_eOpn0_wCNEv1Ob}I0_`M53_-Ah8$6&ci4vPQ(k2pfBsP;%XT4vk zQ)hi(sr^5X(Ab#J@aV`0ZD}zvX%Jo|4PGH2Ce6s(Fx>@ov8GFHXk2~)=nl<jkh7(w zrKO=XcwL0~|8LBDnUomRITIMCF)%Q&aVCI@d(ikPlOfY%@Crjq2Q$Q)fFSsq01a;r z@S1=)1}0F^#lRpbAtcBkz#t$39?${jCzRX-UK1b+T03sc_!yF(99&rg%E}m_<D&nJ zAQ>w1LGjzuu8b}dn+-t27ux>?7&n3Mx72gcmS$vTlEK{9s}C7ZW&jT-tLmsKv9L>M zvm$NK01bgbR|0@Gld?mmKR^v=IVQ$U`RV52%4$(sj;;zeng(84MUna;TGDc^n$~u* z)_OW#Ix@+HB0@fbQm$6o)_RgM7QS|I$zl?Y!eUM)8pc|((iQ=b{G<5)8}n5rB?c2l zVMud9!kCep!HAKOTY#5~nT=77k%LW^k%fcROBzx(faIC5$~$06aYD3$deWd}iYi=; zjGT;Y9H6V*xw#o)nVEQ)!F4eQ2TLqFD-#QgI(W_mRL1Ba)PjbAG`tzOxf$Yl7#SEq zEp+gVBlKP~J<uTnh74?+jBKG?jEoGN9E_Z)g!M#5I><9JfExGes!9sdk|M%FpnDuZ zd-T~rO?+N<_>p+Vrp8Fa=irG##CWSI<bEtrd_h_^k79B~MHa(`(`SlF=a*T<$t%U0 z+XT<_uyPHyx7KmikPl%}@^Y5b<-dzOwEj!LNX0o?NYGzEO4BIHLseHzO;FHHm4Oj- zA}w<|lO%&Os23*4&cwjT0~&_%Vgn5WF*7kRXK=8yGBYx2fU>SS_=po_24!VoWzb|E zC%d#ZBWNxNbaNzVS^_kU2VIh2Y7CW7Gc{#mGBME!(2R)CiZ;vE&`+}piiiM<Ff&Q+ zHaC)$ef9VGJ2?e+MYXWt1G~+QWMoCe4}j7U6NAuyJEl)ek_>tbCNx`zpy5s4Is`O* z;B^Ql#s>PjI@($o>k#x9^+;KV0GW<3V+OSr6q)MvY%JuI9UN`dMGd5sH2u}oykunL z<o~G$soOcTG8$W}?wG(~VZ_K3s;Xqj!^9>prJ^Tn%*87rq^_mHBg7-Mi;*$%L+3v| zKE|5jV}T5e45I%9m?nbb-P6I1nURH2j**o`kdc{HfRPEbaGj9>JTwogTp)Y8!DCb4 z>3HzIUoBWt5ENEb1)X0HP70v8GtkI}C`y3?Daj$%p)+3Iq#SM$o9OB(s=+59D<H3G zX=NIq5V3_x(ru@tVodyd*HAV#4;D6cy$6m~@}k!mFN623i~j${co}@&v$lf<FXs9L zaKjt6J^|be0ImN=U!MS)EjYH3ao<)=Jt28PUPGZU@41X-Zf^gsS{SmhxU;ZDg38&@ z{~F+Swlc$stujdSxG2jBz+Fw`SzJ&93o(m}b&Ud&9&mXC>TwZgDE2i9DCU9YZ^aoI zptp+&L+5Ul8I?dS0LZD=#>S$`N}y~Bo)l3Ab$me>T=1|d?*&cUzPhU_D0;O>+xp*{ z2u7I*c{xRY7s%oSIUa#9Wi2MjfBK9U{|O0Ns6v(|fYXv4IBtkpn*eUtk-RoxzrMYT z$ri?aoAi;^CYZUhF|KfP`=_fbk64=^%D})h58Q4ubkO5qWMtq49Z%o|TA|L&$db;= z$iTo93)+qWPB7}sKA<%T!ph*qw2aE2ut6@%)J#p4O%)k0Z#FeGj?#~a&`Y%qj^50; zkMVLTqSy)xu5tsncS9K%m?XjHq#HXJz}6%PGJ*z$K=MosjG&Vuz}ZIwJQ}3V4B9-e z2^%c|uSbAZ$e`myptnSV)+B%iQbYxnL;c)j4FvfGRD_iknHgDS!fm4xBdlz~-6NQi z13fv}U0K<+RQ<$_xb!sRQ~#}Gbn|ddO#Jr|d<M4$a~6{%fwc)5WUWm=)&)=3sB06D zm4Ld)46(394>;B)AZuU&?ZI;(b8P}>ZvhB{miw_OGg=xN=;<>S{+pvJB+8g-Zlz=O zcVWcKh!+tyivF(fgs!6nPwAl4E~w-UPVA7e70|uwOl%yW10GqC+UY_JVhmCY@(fN6 z_M&`DObpVJ;I(}0%uGzI984^XOe|@j(iGf4(_{1z7Z(<0WRRB=mlBr}784c|5=6Au z8I8bM60{q_)Wi(5#NXIhO<j~-OxzT-{ZpCI0Mtk?1~u1%ZSC2b4)GNo<*0VDwPS5y zQUbTq!R>V)jsUlAp}C%Ogx0O&3J0w}W@0e=|BXqF=`VvUgBED#wiqMmN+(8Gn_Nvr zj|sG~KpZ@93c9xmQj&ufOPK31f$oK521`K(rI>iQGN$;;+8HNjbryQ$+owb-S}6K& za@6!S4D|E~_GkL*%Oj#7Cn75^X;2<lRAZX%6ICW9q++OS;-v9!6PHeay+>HMuNUZ; z+5i6;wEtH!yE9#3(C5@+VrS@($pWz$1Yj)2PR2<PF-C5f7(*Xitn+`ZOco<QryfHe zh{a&Dk%4(b2k1~{W+=_Zyn}HPNPrV6zylNDXWsF@79=ACWq|txtC_MHr!lKDu=B(* zDuS9L|Nk@aFv>G7WJ+XoXMD`SfNgI)D2*`6GbVu5JjJet0la>Rv5)B#13QBi<dQVd z#s&sPX7Eu<7NADFCFlehgeW5;cw)$c(I;{nXu|~yhXmx1PGdo1#=gr@QI{G0{%vA9 z_3sj>tYMI2U|@=4I>o@v-~};X3ba(8fsu)!4m3Cg?)+PT*2!3cb{$B<B^ekPnh**Y zL4z3JUW@=6hm<yGLA)qv!?&`jGGlhsDo-W{&s9t{4;c0SU3vgnTb;zfz_ftr6cZcc zMzA{){|hjsF`Z(NVn}lkmk{FRVPRtCW@Q2$u>@MiEXl|OS_y0z5aA%s!pO{Q0cvJi zg1is8N68lCI&lWrISJr^fy+cX2r@E=i-E4?;$&x#Vw7UzfXpF7R?C=~GqZ!H&;`vv z*F1o>`dAr+IS6Vd+lJ+deh-d{5>yrZmig~3qlCc+0Wo%8At~oT#!T0Lub58#n<Jtl z%qaNp%)hJ;V1NDJ^xuhL8^~V_phKI$;{%KdOp*-j3{H^n6#;pdiGeW{<PB@EH$a0# zaACL~tU)6~JfQhH2Jk^U9OBT4Q)R)mn>R-=Nj`A>!Xyc5hlnvSF#crvjW-Uh2*sfl z);I)>?3gMunnqUnFh2IFVA`_e_3I^|vlc*gm@atE=pwlP8~XnnlNZxp22lnb(8@#5 z#55zQbHEO|!kr1UbOW>{6yC!J6>MUli%vm18pU+Pb@+K1L>WavtC*mL8hj0|nkndT zNpU66EsO9DKkP1ZMi=J{Yd^2(*p~9L7P}m04Hr%S&|tp=KT~Z#4?m{A+93`eAv`Qx zNzv(fdFhNkfvE<bGH&+&_PP7`xchs0dD+_8fFgv!_Wuv2DyFLp-VE*zE>et4%<g(j zEKE#ZN|HjnJglI?kC_pCjcGGz<4rT@yfc<?1{M}@B4c6jXJl}8vbK_!l@Md_X7pwQ zFH!&(grH4M;&#mDa?Hj?=HlRiCN;=>6S$^fS2wa_GBp96pk=NEE;2#WtY+ropc8QF zEsEkTr6r|pt;Hk-ZCosPnfQdox%tF61oX7HI29Gx*(F8!_|3!gSy*J1C4~fe`1B1F zgQq34=vqs1EE3Y<&<ZT|4$LtTQkCZt=8=;ZXJJ><lIIrV5av-f5Mtz!mXNWrlh?La zW0l|%Rg=|nG7^*E<I{`rOX~6vk>eH3Wnl)TFUJ2ZOlz3VF{CnVa!~MKWMlOgWMW~` zWMpPhRFGf+rDH}0MpiFJ2McCa5AO|}0TJK<5O&r)1~zuKX4o7T12gFSry9^I4@QO> zP&2rRft`s7ynqL^7nz+YK-$3+JaR&+zDNggMuxBuS7%#mbyZnueqIhXhE&E>PH;4U zuNE{mGE>)M0`-zW*9@|;v+FS_gNCft?U+Hs8|I)(>Ot`ZiYX>zBhYdhP$yLl8du_W zEXGE1OyY7(>}+i8e9Vm3gf&G>_@#uEEtnYPZS~FF6!-+07@3&*S!GrD`4nYX`Pr1T zwfMy}MA_Me)Qr?rEo}5Th0RR(g%zbZ1#E*^g>5bQxn)IU#JMz$43t>ewXE!<xp-L_ z8O8anT$Olg_yk;qMH_qK(li)t&E>2mIThH~vdKycORx)asA|Z_i*j(N%1U{MMQO=9 zSQ{y_@JI^_OK|Wzn2Jhqa;qE5in-}=Dru@oF!P9u$b<w*I9KTyn23XpeP&Sj|AR?} z=>mfcgC|3TL#Utt6C;C_B@+`fBO@!5vJw*uD~p#RBP;kGZ)OHY<~jx@W>#h<);jQ6 ze=IeiecVk9ph_qlwDv9@w9(LCPF7c2)>F<?Sxs4uolQbpSRE2%h_Hl&xUiC%8t9Bm z&;*PeIHVz|-;T*#oQ+LX1bjON8#^D9u`rXcyq2-7l#Pv<u#lz_C$EPeAE%a?nW&15 z<}^WFO-@6B3>GeCW^OT6IU^GxE^ZZL10EhFB@RvwF)K3_J$c4Y9Gr%>mTF?MV&YQl zLgwZIq5`_Mf8U8pb7%|Hu<|JBDH#Xr>&6C3ajR)5a|lYQ3v$}{`^%`gIH^jCv4P7q ziT~f3y_v2u6fv|jR6A4zI54p?X=^btawNvbF|#uYFoLe6N#I~-W^iX<W#VLF<*Z}i zWMkrFt6^Z{U}EE_Vc=k7;$W;{0A1?JUc<o7z{Ji_1FAh4m|2*Z!x>nZn7{=IQ#=<V z6AP1nV|`^sW_nCiXo#N=C_U?`DRZ-lYm0+Jk6j(Sf=x`^%-oLI)C4RB4KqF_kR(V9 z)cP`qssmASOrp^K3aEt$3SUqWV=m6F4odXkaXofE(D@X?2B5pgK;x_6o;V+qxER|B zHW>we2?cQhF%ts;J_Q*LF>x*lF+N2TO9@e3IXN{sX?0a@0WK+F8C4l6MJ`?)TQyBj z6K-J(A46p|K^AUaZY6F`(<mcB9Ysl1eg$^EJ{Kl-IRi;m8#WdJ8DU9V+uKTJvYpa0 zTw*dJdRkJ9jBK17(qa-4{L<#C5^|ipBAkkLX@1`64l)uNlA;<K+7f~q>hc^yY?89P zlBz12G9vmKT)gTE+HM-Mu11ooYJ746lH4p361r-P0wSEvlSDWKORCtdw4H4P_!uR9 z0u&_74H-)WMA=*=l=#JEw54^7#dX2=OLG73XOd)QWC&wuacDGUWaCg#W@2Iy;o@Xw z1|5OT%;IHk#>DBtz{$bEna9A+#>K|YRmZ@^%ErZ7!@$bI#>!H|z{14F!c@b+#K^`3 zigac+M&=p@4hA-M4z>)Wb#2_xb!~n=j`nsoMh1F1YO0Fz5@P(k?5qr7jA1-%BHExk zXTY1@KoJWXEfE1Vw2h5GF%RnJv8#g<0f-42uTV3EWFS!Ff>rY|vqPg_gpcXGxQRHY z7@rhB55JDNtdKM#BeRUSfwQJKN0^(E5jT&%n7NUHniY?M0k4W8hqo{*r<%T+fuf;- zyq<wF3!9V-r-7XcpG90*Av>3qAup#emy9T%7{8p59KV`_x3|2jw*VWjBcqg#m7<Iy zD+{kMXATdmAO|-uyOxo<qp_+8Xh)j7zOiurq!7?5bHV=tOrSg4br`xGq#$=9GBb%X zGB9g1va={Kva!oEva+#3_h_ntH*m0k8oewG>})LT>7e6TK`RPcKoj}kedFz*+kjz% zB<YwM*w|poz?FrThKiD`w73{_Nreuh4(O&PVc32`#Kt#cV{G@XDJz?rKhDTX2~aYX zm6A{v*SB%<efg?(T7QpSy0&4qQBqu1iSrA_IkAz!aopSvoSfz+)>bwzSW?o`%0)zi z#U%plZM~d9M^iE|GKl}@W4zC_he4a6$3dEdk%^I$k(o(^k%3vBk&RuBk(G_rON)^O z)c#cg-&+OR&4Mj3n#c_dO?72O87VPQ&_*aW@TKOEz`$5u0tpK-HgzR6XxrJ;L=6-c z4^PDft60iNiK|KJ+Bm!JzS`Wz*i~&2tELmFA08Q>?RttaZACyF50@<`hq;NBp7{mF zw3yf;CP98bVL=y18#g=9G3cPC!T;~f&P-Pr<}tK7GzBoSa7+#f^iyVKV~J+u=E=)t zVqz3x<YHp=Vqjz8VPWH`W8mRt;o+`f;AUmvW(DOm7B&tRP;--=krlkkjfsnqDV>3f znSm=DDgSZug04vPXJqK=XlW`hO-u3da<sQFH#SsP1ziKj$<8p3aULHy6M|X=X2#%- zHan<+2C1|_%{n_Kb8zViY7l@+SUV<DutIPv5474CdV{4IC}*;RjbLM!V-^(wD*$zt z&CJCOK!$=cEw~K=KFtepb1JxPsLsa>ZgnutG`5lBGE`ELRuJQn6k-$6R<Vop))LdQ z&|;A{Q4%#%wk?d7;WxEZSCLlscF^Q!<&d}ZH!!hMx3Uzrm=mqxEF&ew!6Cq|uWlZs z&ZVj*rQ;E#E~~)9t!v05t12taD`hS%B+eti%BR4_A)?43AkHdcsLUy1XrrMh#>&qj z7hTUOr)MOhVa}+=uOPz=nx$cplo1K+j?fK`G-6ZL72#l$P!Zr%F?G|@)X)pcwHGvy zQ4Mg@HZjrmw9?>K)Z^ylVH0FxV-|7J(DyJAVir-c)Km|2)sj>Z;L@>C5)@H2kd~FO zG*t<(kdp(QGQi5o&(6xoX%%K9YAht>mt5*7s3GW(VaLGq|Ihz#ELKd<7$!0-W~g(h z4rgTJvD08;XSHQyVegEQW@coOV`Sng7Gh#%V)J6)0$seyRL8)<z{AGDlMY&F&CbRO zT0_pl$j$;<x(C`#lg`P=%)r1L&dJEk%n;8FOD6N?v^3S$l$WL^2l~4@TUqGqLX*iv z#)-(u1iZo)IhnArv8x-{F`0v|^)%pP2FENoQX#ER190;b)Dr-&KLHi)=Hh(J>}H?} z9$bpEfllmV=VKN%5Ch8^^Ra*pF*66J31&vHQcyMoHD}q_W?DMRu*1^`ySSmYg_o_W zeSjpNl%caGw}QXDypffOkf@}Xj2H{2sH2Z6pR9qEjg+Ja3!8v|6c?AFv$uyFmx8X6 zf{3b~f@(}klD3knNnW_HzLbovf*`9fzqWynBD)B?vc8G2sG^m&N-iT46TeMlB@;KF ztc<dstByE7m%fLtxE7bXnLek6xjHnh@UuwCiaD42iaW~iNo#2Gu{ihn%4llJNQ>}l zXe+QXvFiC7bE}$}tBQ)VaLI{_D{yeh8QIv&@G7|kBs+5RbGbBUJ18s4L?@|o2y)t$ zCA)A7OKa$;aByiD>dIO>Y1FtXv2w5&XUAGHE@I)~;dk)$loS*Yc6L_*EolU$7iLzb zs|<Dw{-8ZBE{trfx{Qo$ps@vJF9tSNMpn?xmn;mdY@oSlMh0+tKq@rYp_R6YF=+EB z=+<~nb_P2}I}W6B0-OLKbLOBtZ3Z0;0~G|KkZcT!eRXp&P$9t1$7F8DY!2>Gh>D1b z%`~-_2j_2PaT#$zBO@(WTRB}T8SA!u#|Cp_M*{-|Rv~sp2TfKXRvtx1Q`v;(8ad~H zL|aKKaod6jV`()mMI%E&aDdD6^7E+6nZ{aknL5i`<fLedi}N$vWKE3ZSLf%_b~jZJ zWE7MWv$Qhgv&wLKZ{5^Tq|M65A?ll)X`rG8y0eObnSuNNH)b`aD-3=NF$|duSq|wk zj4aHWvP?`Y&Wwyq2|m_bENon$J#;LLEKH1btc=W{r3cL5yu`)E$d%5+$pku~EgVF% zF@Wy^WMlA;i)Ca;Ns7&k%Zv>7^02ox&;xD56%^oLWAJ12;{^vMs6PxI<~B0}<s3a` zP-$vxB+jm;4DKb%F@bwzkWd6=1n}Lz;L;S7$3P1m&CEd|4OY)+1UeQE8Y{g@)~dFu zY9X2e3c@U$EKWh%{3g+*4!XK5x|&wWo*D{9=Hk+}E<Pc;+G_fth0el~?iz|V5{e#< zl7hmjW-c0Pt_s@Wj80BA^7cBC!m2h#2LCE_EJankG^9;bjJbqWrIZyEM5R2mxrDix zwXE$VO%uGeIfXd&{E|#{EEIT|Y-$UmOtj=x(sN=Yjh!Q91trv6blDXR4HYGYB!n5A zWK5;QQw_vqTnc;tb;!tyDTzso$$(a_fcCI5FfgqEj|YNQH<~&aF)*;RGJ&?VrGj>Q zGO~n%dS{HW9L!9NETC-*u#@SbH}`R}fetZ(Y&lRj7F1?57F14Ta$ozl!r7T|ma{W> zJHyn!*``bhe-|););2JL^GzJn6^2=$Qnrebox85O!k2}Uy+wkFk!czuD~l~74=bw| z11CEZJ10{e12+RZCpV~##=ywI#F);&!NA4B!3Emh&B_DHSv+hEJmC!Bl)(TxR*0FG ziGd9?gfgM8tRy=#DKR!W(BIk7+6r{!m6!-WH^VH(S)fuDvOWbIt?EjkHZQb+0%{S% zD@kP~95ptmpd_QlhOQKbRPfB8(wV71L4{vJQG$($Nr0O}N{pRbf}2OrK*<29o(x4P zhB?G^RqO(sG!??_kZWpd2VE6uB_9V(eilwhO|9!_k5W@xTIA<Si84z{a&hx0Dl3RF z39zde+i^)K3rf4X*^2TBu&{9P@v(7pFiYq;>&7V{Rgh|?dYtGLwR3HR^9&zEJ+0&D zhfz-lx*8(Y(~|xg4jED++DaU<UM^yMB2pTf@~oU(rnaChMF0OYK+jxd<Y&-iVrM#q zdWI_W-o`rSJSH{<&?QSu3`YOIF}X2aWsqV}0IgO6?EsRI78eraVPj^JAhZhzbe=wB z1Q&A`5NPd#AgIVS7iD8p7X%#(#aLG`+0%b!zCo;kR6wY<x4d1rW`vf0*oR<EuBc@N zIm=>sge{bW1^=Ft=jFEM;;3SL5<Jfz)Hw&A9R$v2pj;*lIy;Dok%1F*pB+1BcRC9j zBTFg=BO5a_TPSFkE^{mwD-$ytvo8Y!Y-1*3H6nPE4`^x$v{_485T5JSzFmuy?fxBO zwEAnt82xW4BI_}L&kAE&$#jZ=lYy5(%|V%$hntIonGJdrH4{TK_<o!c1_lOB22MdC zK~`|~Hf98^BVrU(HDwe{^kF=1>if@%@!mfrrc?jK7+?K0V|@Kj)HI3lUovR2f(5)s zItDxkz|SDe06r;6QiO?>1$4|R8*GOW10yplV=4nP6BBbN=yHHqc19*<(5^IO534G2 zu!(6K3o3%ELC{tskZ*;J1(k(CV-4zwjLZ!cPC2&870%8T-Q5RO^n;mB<wo1ZoBg|J z%9QZ$Jfq>i2Z9bZ*)pKZmu&xsF*7h-We{MHW>8|#WY7oI+A7LQGN8j$IG9;<_(9vC zycih4=g_8efbT9~WoAfcU}a(g?}uUnxssL1S4fb7L0?Z>OF~RgT1XnS=1NtNlTA#U z6>)U|xD6(*YGf`5YSXg|im8HJtftN=2pW|VV>AXGx6Ak-d-h!K$+_8+yrVs@{A>3$ zmvL0{voL35*VWV2``4?dtIL>D)4{93ziI);;bpl?V`7%(H7`~>azUEOgO^|S?=Bg8 z&F0Y1Ce42gjQ=#7f<v1BeXnBy?doM<1;@i~rc(@{Rl}kTG7O3gcOavw+%jTJY^)rN zOl(Y`Wl&rJ5e_gRPLL3s2T}l9>;xKuRbyaaX9S(AkqTOx#KgkJl+MA(!pO)H3b~Mz z3sOT!dv5@lr^CR+$->E0fTW3mlZlNJyB-H34Udd;kYHd?RFIPetsMnTz<~EJiYbDI zv|z~ubdMJ#Tfh^Fn!2ztGaEZNxj5V2KfGTXo?x^zUA)%I$upfwj&_O_|F??K_TOPp z(z(m1{O_Hhjg7e_@88vo!fZ^Sw9Ukz#=yYj56wU34kqB!wV9YaLEGdQm>3yA8?2d` znL<JPteIok7@3(sc^H(-Kp9F%P>3Crp`aU{6h&2y8I{!-^ZspO;`}$0G4`LVCu5eo zDN}-}>E8vWrr_$5frUYZfr05X)J{<bY0&;oX(7<?suu$TD<f#J6v$f821AgwjInHt zjNl!HqQU}vP^&o<+1W(3jfJ6I0A+P!VP((+g0Px0G%Kl0|Jyhzad-O>=SFAFkZAWp zL+`AO4$i7fr+OyV9Lfh5B1%ls%70%NFNjO90PW;V1g|>)?Q`S=-5kciz`_VRBON(Y zvqCd9CkHzl<oYu<NQM?w1Q%S1j642)tpGI>Ou=mg2GCp(WUlxM6B~08m=Cfi8$1UF z+T+W_AoKqxQ!3L9hD3%OhEj(jc{wI#77j*k))X5iF7BW}CUy?cCSOP<W?*JuVr2$T z7;$s4a;Nh$axt)Ra<Qc|a58YPb8>+CYp^}PJdB`CzsX6A44D~8ImtOu5q>^yE>;%C zM!MQ+Dw5&?d<=<<iJ*pqIA~DQ1adgC31s9Md;|e_xChiZ2iNXqppj@$zf4pFa!E62 zksTlCa(YnL3p7guk^~J6freNit7Q3@z}M5Nt0}RIi9NE7G;l3+=9RThaWJq^;*~H^ zRZ>ybWffMJ5>_%))DzM7)@GA7RhAJHwiH!%G?r5^meKIFS5uLewNYUgVqsFX*HBgF z)^LreR#4^U6lWKZXE%wlw#{(m;xp0G2{r|Fz9lR*HDzUOgt!C^<YgqyjdhI0%o3f& z1sOSo_yxE`M7hoUqV!Eoh2+gVG*s2iqD)wXRD?8~G?aDubp5Rq8GE@nc$k<Ng+UEU za37jEfaxZK1w%VSpF_8ZFcS--p#c*!Qwk#&a~UH8YZxOtcTFS{2fGg=CkMM%1|tKb zCj%EVD>D}>xTVLy&0Ys8fteUt(m{KHxR{vJ8CZE3L03tFB8!8Qog<xrlZ}ltoPm>* zEuNQ=jg!sa%94?xsj;XaD8S3p+0nAys$D}(URFv%ke`Q(!Gh5O6lucXh8(DaEXM>o zdjvF60&3hrdH|pXKd9XYp4|a;rkIsLy#y>HHK6_#xDO7RV&G$92X!bwrizJ*u#53A zv9p8v=SuACd`y=V)dg8)tYR91jUDv#lvI^@1qBrJ<<wl9-89T{Bh4h`IVFsAltq|W z`2_hSjlHt<tQGlLkUHDC>N;+=atanfV*Fw{t_CvZflj=tY7zpntb(jeyrMFKyj<?A zEZp2oegdLGOu`Dx@(Epxrc$aZT#7-#ZrXf;d_sI&GO98XiV}MMsb*@b+{)&THey^7 z;_R|Ein1<t>i-T(YicXAYaoxnNXv_v#aTPD8_M!XD#@@|rN--XsYIokvM{o-vdXJS z33AF=uq&x6vWdxPY4I_0g|>js;03qqS(=!xGE_4-IM{l)Yw@#y?hq`BHj`xmO?Waf zHZz0Hre_KVEoNm%U}a$gZ9EQOWJpW#^>%R*5n^X$sAjBYhxFJWZE;Z%(0B!?Giz*Q z#{?QB6X#=P=VM{FV+MsgXkLwvnVpYC6m$iM8FWI_)WnY2+>XVZ4?MdDnRf$aF;M3i zq?)<O&cj$kQCw4xmqSQX)jU2dT;IMXQ(1sTLP1$xjG0ATUS5Jl!qVPOM#omkB27+E z(7?<{h(}39UW7x)!cLk;(!oJWNkdXiN1caX-^4(fO)#X=-8NEL&R9fDgiXTTO~}AN zg-tOyGC)ovFg%^h%Sy{ySwviejggy^O-ar+way`IN|q!Sm#K%JyAcPMg<oiZj6`T! zin@)zicPSPfJAU|f|{gPNPwdNpPri%m$IjkxreNGfVYi+sHL5S1{;q{LrU0mQ(ap% z6JgP~896d;&PE&(QQ4X5X5|@<pm{U~E(Qjs*-WPx6c{uaj2P;-@`FleFUYa#8k~$Q z%<Rl81+0wV{V*(`>x9_YK)cf!n;=_a7?_xvnS7)jG@(k_>j<fhbdc22VqnlR(lXT5 z1`Pr;C@?4}>L{vm^Gaxg4w5%9Gd6~vcFQgbnmGbB=^*`RarlNaK|#nWA7xQiHdhb9 zGi{x2PP!i2t;N4Z<>lC!7q!H=1V@)mi1YSMe#))D<6y^V5Rhme%)`o|=4PIl#po|1 zAt=Yb)!NG1_}`^}f4yuhTtRg=<NtU6O&H&U&&r3Kjlu-lT*2hU#>fmh#0Rtio{<A| zlL%;6FL?h_6RQs+c$W&Or2(o*IoLpVv4IA&L6a%q6WmM%K^IJePDV5qRTdOs(-&3Z z;*t@xDJo*@`*-^AVed2Gs|Q>dbA1_oeg8A~{+sIQ0dfx$c+Yt~(-j6O27QKR2R=bY zHdb~<b~bTF7Ix6SIM51nMFutob{01FbkJt}c+eSiUEZ9Gpk)Hg983%h-JoSEns7Bt zOiiF2k)R#wj9sARZp~1|pvm!W2A@a=X&Gro1|2O>+(_%o=!=Pp2=nuTmauT~LYA<A zcD9<rM@x*&jRlp}mD#|1Hy~qzpqdT3oRiVgzuYN0(%-v2KdL~Eg~!iRm`x_vE32?L zFTg)MT~q677MDS+lY0~&Gk>6KaH_p_!e6sQEl2ON+M?22J0p81uO<&CL|A~%?h|3q z1oe*C7{T2I76z1k99`fYdyuUs-3&frqKpix%1R0{Qlgq-ntVJAB8(y&5PzU}1Jo1; z`@lp^9dc9_)B|FSPR)HF4>Z&lO!4%bUQ|<7S{WD&cDi9OS6(92=|O4HOY`!U#`;a` z>734JYijH0)ns5T16s@A_5T}FJ@_oWOb0GjMrI}j@cCtsy$8~u3XFw`IUTgJsmU9> zyn~G$7H{%svTSV45GA1IJ2<vPK@0U{WhBK#gar9{xEYigmEry~H`QY@g)DZ5`UaG1 zK>ajOd@))TG;A>o(2mY5mDjo&<&{|+=_$k}lf#u3Gf$40OUvJ-XF`OxSD&q8SuNu< zaIAphfrWwd|97S)rXLKTRfWn7+6>+f9;yP|%q;ATUJOhOtc*;op#Ca53nP0v0~<2~ zTR7;DJq8wL&`G`EBRRnXFADPDtJsA>gGHR|3_^@TprsSw#lWB`L@{w;V`gP@Ha2r( zVP!_>f)!AQn^_n<c`?f&P{}FT!Ni5zY3-u5V(LMQoO_)9&C?IGQ4}`RVc}xwi&U~z zli-Ywaca(WG}mA>`^%APVr9iN>2HQzQofObwHhPiKX1lmVxg5jde)$QLY)7<F@9lE zVi0FgV$fjF2klSO(vT71XJrB%Fwe+<eo_ewBLfp?2uVRsNPv@_L7Y(>G(>>#0jOSL z2M-Uhv#~LQ=DF3BKt2!$_43pig~6S?7kPzR!4-ZU3H|fb<@I#qbXj#GJ!MS9Rav-L z#I;4LRW$YgJ@T=16ywT`b*N3Zv$1nZ;oHY0C1x)y!f3+8$-0q|gQH(SS6*G{Uk+ow zX1j;F4Fd~<0s{kM7&9XS7x)}vS<tN?pc~9VXRUC876&k}Ffo8e$3QcisSIqatZbnS zY;3HtT%f5xUokNrZpe{xkYkAj`ME`TMA=yxxEQ&(*+jHqbC$3jTae<JS=g8v)M@yk zq-&(_V=d1wsURXMe6Da^QJ!;*GgE+?s+NtrvAL0in7p*0fZ*Rc(4ixSjGGu3SpMh# z7l6B0ok5o&+#y7Yk(FJNk%bj}>kBySAueYFxtxuGot2F}m4TIog*BXkm6au)i;;zu z#a|rka$OxIML8KUb#Zm#T+XNjZqk8Te8R@eeBfq-urjJY{#_K&5aH&N6_nQF>R4CF zu4*4^B4^H<>4f32KYi?+rfeL_`b_nI&ntL2Yx#;e+Aw|vukBz3%|SCsFo-fJf=<?y z660cF0VOZcJ#|bijG)mdhEULf8lY8>44{soj5KI7wxlR4o0zsZs6W97zV!>l0=bn* zR2Z}il37_?j`=dLIRC%@+w0f`nK(F^lPpj0i}CQYFbQ%mbjjzGk{0<O6B4V*B=qkG zpBfjFq%=Dt=ijfI(cwyrIy@$FjJ_{~&8-a?n89_<UnU6#Sq4Q06NYGq2q{K3(D4T> zpqp@57}-EOu-O>6*x9(!c^NsG7&ya0OH3HpnNoQfIXM|X8<sd3{8f|~8T52D)RatA zOcWL5<s`*HH6&!8G=nUoEU3B7ssx&lG#6H8Ru)z^H&<j=W(H>pV<XT^lPWmpo0*$~ zC!av7z>-X|Hi29$)*WeU(~4RAnJT$+tXWwk1f|5KM6CaLImb9Ndh^L~v9lP;b6Ppt zu(BI-xmt^uiZSy2lVyA?q-^@{lc+4W5I<K9JBKynrhl$XOsZNk;_8fi|6Yn{i>pD- zG?ZjuV3J_^!5{;=YmN=Hhzxw(PBSYD6B9F23j-rFGh;XdBO_>6EhDo(0|V$3GF35k zK{hrCP#+pJKLA}LFT%#otSk)b=z%gnvt&htGBYO&n@og3L;@3&dAJ#~u|-%gpAOTH z`@$*$8tOjYT;e?c7Bhwm3FsN7#{C0b0nZ@8z`&%&^n*c(p?E7VBO5!T7v!QFbq3I> zL3x}UOl<6IprgB47#Ua@8PXV7+1bGv19W>VE4#n6gBk<q_zHpwBOL@87#NfolvKpj zz^iMy*krVgg_X^X&5hZO*_GMZ*wOt3_LfAY2d9@%gwP4jQ-U1atSWJi9)Zj(&Jhl5 z@!?S-W=!#R(b0CnDjM3_&ThPNg8$Yt+RI9ZCMN#-2F@1}|GzQrWSq#L!C(Ta+c_AS z!Pi`ZPNidEVqs<i_xC`%Bp8_BCq=PB%U?r%RTV{fApr&rMh(y^NO5o{&deONh6OYU z241laZs&s<CZKh8#(YfbppG1<TenxuP==eEQ-_~JQIXBO-C0$UOWZ2WpPh?OP}VO< zSxi1KM%UU$TTn{UNLQ6hT2n_rMn%+=mrFy9-O*19q}a-cpI<{*SX$dhUn|sdzOaph z36Hdqw?An71LUvUj1xiU0)lSh;9z88<z!@GQWs|eZ@pk*1szsV#{gQW$_!ej$jZdX zn$8ZH4`v6?2eW}^0992O8O%)dbX2TWt!1PI_`vl%xDy1Pc`yep%wd8I53sSZ+cB9N zi-3KsZUmZ!0{4@|LDddu<qkWWsK{<r1BkB!<a~nEwe^H$O%w(64Mc>+v>ddgZDfTt zMc6o$gm~E%w59lDea*EIK95&%(v;N^kqe1ZWf9j?V^TL%XO@%~5))?T;S!N%Hq6&n z6^hFW)>CI-VE(`QUo}%8V=sd-gBwFAL%Kr>=qzD26>)B6Ru&&d@UcV8Ol(ZdY;_DQ zY@kWdI?x4NEKF?aoQ$jtjO?t8>0FHLpd;6~7(r*Qae&8PJlsu97#Z9{JwoklOx#S} zG&Pi!<Yfi;7>pT>q4kp*xPxa7U-e)PT6zXa4Wj18%%Bhg_rv*^g+VC-6gJ9Apgy7) zGl*}_$0{l!#;K?!Y#JONE~CVuVl1bk#w*I}$g6BEs~l&gsjgRcPTfh5ON7-p#LQ31 z$UUM$(aB0oKtV~=z))9NRA{M^siCAlyS|f~t(yG5Y9$>3MHfd)ZC-ayc?nGmF==x_ z2VON7B@Jsu4Tpa-#H~zudF(x9CL6kY7&1;U57ANbQqa(L4e+z(<zxTXr0Zuii$zky z*v3IY9<*>9e6E=l<9;S31~mpR2Y1k{hB)Y4GgU^=A|6%-IYt)H1Q{y>3oA=9Z0%An zsKpO&95XV2*5H7K06Ezi)EL#+Aq`_tnGBu?1@HHP<Qa3wW(&v)98*&^Mjekld&eRV z4POaq2?v>ZzCPM6GL|;N@?0EJ0tQlulg~H>PJ<3UTjc1%!Q#oxX5s+4D3p;Q^uHC8 zE7K1K6^2F!J_$y4W){$ew&3H#y*FrrmmIM(GcmJ+GCsV+)dF%o_$=*SZ_qF%xa+CL zfUc048LEbXl@)SoLo;YyyEr3*qJpe6XjB+<MKT8)g9@VxsGr6PTUlgksw@aPssnV? zs<EgDte_J#78PM*ya4r^Nkx=%L<B3FRHR8_vX133h_~Dr!y7?mHPes#8p@hlvFZO_ zcRIR&+RLDQEk(>cV80qNEO!u9VPaxuG!)`vW@DFPWMPtKWMyITf^-Iy7+4rsSy(}H zBrTv0Hn^A83tD2u6b~8@>1F~Q9}Ec|>?)a=n<2^>n3zDS9n@e(va`cXV_*O^E>IPM z&fikiP*D?6RTALfmC<H276l~%P`3y)BB{)-44IQKHUiCcfh%M)b8*<(cr|4uc1Dv3 zUBj$;%i<gxe=#;;d%wsq7i|pzGwJl2_VNh(P*)%I2v0*DrXTm%J!<`1CmAYwFm6_x zUYwH7>&D8_+dS!**2m1O%oOVwV-8TbF@o*^VQgml%OKBC?Z7Y0$i^xHTAafT?fS}s z5(yV46Eo-<5YRF`=xVzbZ_r!=dn^Mxdn;(OMl++2w1Wx*D+3!lD_c5}1`K794xmK{ z@(l8zeWT#IkDFIkn-OwcgQ>BpvZ*<^AQb}*$AX%?qQ;`iqKvi`5wWpxanZr@X2RkE zT4Fld?d^<#4*%XW3OY1v%E@O$bF;g$a#`CeyMXR*WMa_%|Bdk%lQO7n0qWC(d<N>% zOF}({y-(i@?WSYz)3?I=^xzzh*{7G2Wn|FP(biN|mNk+y0`<HE_!wjuWk7v;=t#9W zq)!iyc5yttdeAiI2a_msYiA>K^I&arS4|#f9#;opR?%?1C>QTw3mZo_J}Gw>4=x24 zQ)5qFRz5o&BYRm%4H56Z&wbSmJW^uCvf{MVH8h=!bhM4YdssksiZLlNDKW9Jq=WZH z*nq=Gl0lUr(}9bfk(o&eSD(2R(jmstXKn@M1}uGMP>WPrQdC$-fR~3sl~EPcXGRVO zM6Vg-UF2@_XX7A4LvurmV0&*K5oZfKlL)sEM`0GRFfL_RLt{4qR$eE^oHR#su;)@@ z8KuCU2A$Ev{QnzMB9jt>7K0&!1;b1SJ|0FUPIX3hMny&j_-Kwg7b_DJ4;vFBI}>9X zA0sCxb3ACbL$5bKHxsx5<b{n5Xd|m+U}0(XhA3xXX2wt*>7Z$Bq@&HqU}kD$VQitV zr){WXsH!XrIXG8<ivxVOhZduj0Hg{~S2l&T^29-%3u8VeQE*xZ=XYoU02)GIR$^mU zR8wO%GBZ~c6Jr#PuV6JX<19<I_LpK~72tN|;ARU5kPze$V&PB_P}S#V7xy)FbY*8$ zWpnWjaAW#+gV~j<vB9pmN=rjfgI~-eKt<55QC^aT(SemiMNi3q@lkL<K=8lx$oQBT zP?^BYp!fe9vp@Kp2@?iuP<ujxmx+m4Qiz9{kx8AAgPR#NHOtA($O*b4l$(Q%JC&7@ zi3t{ld|bTD92^Ys>^zV_G&9xKVq~ziFts+bHqg^D(Kb<4R*;vK784QV=i*>vVbEmM z<mUx1i#9beH%B_hNgOnzBPI?xp_^S1T024q!NBY4#8{2YOclk%Zu!Q4OUzUCQJ2+@ zGpx~&PjWF0($e!Y3XEiAEGo=!%92)2wsr~f3yL;n+~(r&?>SolSCHRgHfGgw5n%^W z@mL*0L17OOq2y?j{5CrqTU*4zPfT%cfx)0~VPdfQ|B|tR@h^ikgBpXpgN(AQw3IL_ z=pHFXMn-oA21bTv21dpbEoso@x8mxc6=I;_FLPsY&<as@b`j9jhMBpzx~RFCsfoHe zAJcPb78O@rPVtpu3Ct`!N0fE=Mbs5U&ZV%kxC!zxiSzREs=C_rN+<{v^|NrWvT;t4 zQ4!>o5qnbU#md6Omdhh332xVe(!4Q~GJ_(6I)jIUt0W^UixeXps87!cI^~lol^Jx< zBnvA8ODY#52M4T*Vr2za;oWRL%1Wv#O6tn$LaIuFqC%<y+`KZ{=Ef$Vp?YH@F>ysu zmrztuR1x9<QSd;%x-z2@BwbqN_@orE{F}tY#JJ>NGJlwZp`X51ut|EekR_u^wgMv; zm)#dGuCRKys(e0KK6W;92M0kB4-tX%1V*J?J$p#livRz{bc;!eL65<dVL9YP5MfzH zCI$^gHYQC`CU!P4Miyq!g%coARy5H_hz1Q#P``|cje!ZY3Y49hjXfRNzs$_w^8vb9 ze54(88CaPZSi?C%+rilwm_P{`kNQXlVFP_*BYjf?Qx(vWH6kiX;2;8@M*~TvVxp+Q zqoxj8ZU8CQpqZHwl99!OU8D@8dF$d`lTH6kWQq(h_Se!3F!wHUW|Gj7QqxyfRuSfu zk#uopd}{B>&M3%ecfi)2l_{svCfCz6I$l`FS4hyNB#engK|w~D%ZY{6g)t=1!v%B{ zE$Bi^1_s7ProRm03{ehTe2lCt{EW=tyQe@^xeRy^hk=Eq#T#^-5_n>q8Bu{tftoSQ zEUf96lHgmXKsUDuu=7eo_MIx58l%_Lj4t&N$;lz1a^_;9!s=p1s`ZSQ|LHPbcGFG? z<>YW-Ww$ZWW&oWH&CA5c1RB+}WN>Ae<RGRY&BVrPE6T*o&cVsb1S+T57#Z9l%{2`M zHt?>CbOz9^lZ+goJ_{?Xtbz1b7#JAZK?CqQ=t{u_HYX!1D`*6Pxz`(6d8C7cwUw@p zqrH`@wX3nAj-{@pu&TC-HaD-NwyFr|D0p`8nr+BR5>PfUGX-U5WpL_;WDQUa&aTA9 z&ITHQ1WAKSX;{QF@o91ivD&ckvdQ>bhsTBcnMcZUF)=dBhFPQ*8YX(=TC#9?zwq{A zWc2c|bdq(<HntNK^VT!cF<}pJ6wnqH=aJ<Wkz-`EGPkr;l2K7r6j2k^(Q2#qt#AqU zbWDzjO49W=5e!ZITPYzdr7SHWCeOeKTA9VTgy{!^5ksv5kBlS}E3*-(DGa)O4Ai96 zW?*AsW?=(u{bFZeXJV*hU}j)sXJ!PitY>0n&j2S51_p*^P=FGnnjsdVI?{n#MMGIw zMN=8vwl!7;ueSkZ0C8vo7n)iGjRnEw2<Q$@HB%GFN(fN<_kRShIJcrS2d_8}pNz4G z9=8;41g|)ctTYF>V-Yy)lmzFXKjL7G)7Wc|HjN9sw6i8%t(pMy`Jkn3<JC1mt+d z1!bHpEbN)VSL=b!(PCh%V*0^g&alKmOje4CnN^dIiG^K@mx+PN476$-)Fl9giV*`l zXuyD-C7qj*iGhI&H2BHI!^p_X#hA{(#s=;ZvBq;Sva*8ee_q~ZULR=(yqcJqVd@#! z*mz_47{Qt%9i$i-7|a>WO^po=^mH`Tgp`GpgjAG-l=*pOwT&Sm#;y#i_QXxW$q2@Q zhMBoBDD|m}f&&o7naCx~Eh5cs%wnS}B!tY4;1cE%m1Z|)wbl_9La;>y83oum<Wy{3 zxC+=f<y7rlxIX-Q&dwpP;^@eg&(5i!?BK-xf`OSqo`Hce3w#!{1cN+-xdX4PjF_k( zHwWadbVwJHn}LzB1+)hloM1pac!Jm>Apoigjg=v7UUTpPrl9e9brCUfQ#Lkn&?T&9 zW*;NWTwF~f%$!|JXQ|4{soYkPl~uXN8)|D4!gu!`Z<v)$DDOOFbKbK&=E}-uyk~gK zL1R9l|GzQMWKw3(XRu_L<RGXZ#l*;@rNP9-sH@Gy$pxFX1MM5);$-AX2lZsx;yKuv z*w|XVc|aqmv8>G8%+PeM11dN{${0Y>AhqoA9E|Mjz2H+injsqExf#I|eUT1|h6aob zrX~iKhL)gh&Y*h{ga!HexH;KaLDvoOLYjA=!U8%~Cy3PL1vU1JjUc3$sHm7YyP7)W zOg2;SoEXz-LkG_QQ!`KJh-`1i2v<H<@eqR=bvCI8lgMZz8DUvDYhP(m3uO^5b5mnm zmTEVrh{%687^CXrlmESBlJwBjjMUMMP4DI4HRECP53yC%7f}=!mSupR|CtVMCulRY zItU0cGBU|XF|jks%QCUS+s2@SYuMR9(@IQCEb*+2pf)e)AW4RJ<X#aY14Io-mVt>0 zyafy1D*~<kMa*<6D={*tt0`$KYm1A5MyJ8Sq{yfU>J_m<#-<U$WQ;pt7-xb4#?m&z zEy9hLRVv0NGSNszSYF!3M_R-}NfZ(s6&}t>3E*(h(uhyR2m~gE(EmJ4VNA*lstg7U z6%N9nTh(|O*%@`1nAq4=85!6>MFOaE2-?dA@ggD^7@!@0@M#&~8V7XqDMS^PfB>(7 zhSW`w4&2IGDuTi)Dk`9kKdTz_kStIGLR=8M84x@k0`t9~2)mfLstBlBF$aw%GRgCc z3OgBCxH_3>s$1EBgMdvc+9ooQO+)(MQ*l{YEp|m^dHFAzN{VVWCZ;yRj3sW4NFnjB zT3OD>JyAqaQ&UnNlooXUzhvCP_?JP7L6gDUflr8$fsxTmRz{eKk(JQ{a)Tl_10w?? zs5cGH+MF<6N#s^Vd08f2QEf(XP&El^+=A|&RMulsH#Gy-g6ih%kTM=LAg`{b#^}w@ z$0fxfre@@)DIv#b=&i%Y$;7-|S4W$bO+r|WS3rdEuME4G4zIG4hPHo@o-~J~6ptK> zjOuDpO%WNPf7ir>6s%PByu@Tx7#NrtbpBsr+|MM!pv0ifV8-C)AR{FqF3JM(fPuc6 zs){rRJLq0)9!3u_a4Q0I$`Ve$Y%?(u5@g~PfqKSVoE_X+2YU#zp;-;dSEA->poSf& z<YEVx!Db+@v2e25sCqEMyr-|MqpB(@3h`n*BQv9bNH{M?iKZ6FvmlRh3Ub6q<}txN zE5YL|Y01Wh@bH64Osq_@D(5A2gg1%`Dp)ZvG3fq(&cx58&!E7d0UEm(<mX~$U{q07 zkQL%&X5wIGkdb0yVrKRdU}W@=W@K^)_3uIZD8YFWeBw|ylaG$3swxX;1&ElqFr;=d z1y?oZpm+rLu0R{O)zs8gP1Kn|X|IYy^q!EOtcII{tgBw2xw^5ItU^<{x4F8prjRT< zW1ILLC9?qUI|g!$x_kmcf_?)08YZe1Dk-)N)74B>EksP^6Wt8|U6(F^j6axx_M9{6 zFuF5}FfcGFIWRz0l{4>PQUc#R37Q{v{{N7<n@O8NlfjU|lEHzY$RS@+oQIi-*<4pj zh?|v>$wEh+nVnNbi3zkpTa}TW(Nltv*+ZF;!JUDTfs>t)GZl2Y6Rd&A!@<oA>d~`u zK{}(>R>nq*40g6w4%QAvmd2I_dW!OpJ1AJe9Z^`>ZK{YAK#==H#L<FDosCUcL|hn@ zJ%vFxeyKBqdZXrwB4Ug(sU?glOu@dUz8adorY;!@@@Y=~R*EL-GV;wuF2?F6+Wg$I zaVw;6saX4Y%<y*;x}xxJi;WxGzuz|O&3UE?QQ$_tg}J$fhQ6|ea*|!k1O*FaJ3$ds zOGb%kBSuTPw0~#QQoZ#5T@YdP^Ku3EPgxk8|Nms}W>R5L1kbFSfp+%rFfuU<aWk<q z$wT_>><paT?3|#b1Kb>p+^M{5Oo)y<KNlak<IW20xEmU1X@UxG6JrB2Lo;0+O?@qW zHB}`IWerg09dvI8D+_}nqat)T!xT%Hfy)L^+m4M5+WUbHW3U>T;S4FaT>IuC`xH6Z zI7T~nPgX{4HV-#XH`aew**yQ9#u`eFwUI3oEX+(T86Sm(goOP|4-X3ug9Qu|=q?)O zGH{u12<jh$HVle!Gchx%fM$ZdK!;B=#<MUoGWL3NvN3_S2eLxf^r)*bGU#fn8LAtC z#_&N~iaFRo16k0j3p9og>KK4FFM%4mps8)B7^KOo&Snlu8K5L0Dk8?H>yvNWQYx(@ zEGw((8Q>SBVk@cGP~n?v-B_OP=<q7Q+b6)+&zsA=HmGeP2fI5@R&rdPl(<t=!!(!L z(1z*u_FmxgOOxaBL49UWKk5;48IvW09)mf914EQUxPrVa7Yh@ky`8a<7&jX;ldiUw z1`Fs07CA;n4^2h}cTm=V`;{HVua*{!3>FTS4rV6msxnegzv?mS5%eo&z7Q4x6)?(5 zY~XyMrp}DZ>!v!Q=Aya=jpY`4qUK_3Yz}_H!dqojeEsGGc#Dc|mBkhmg6eV_Dy6;+ z(}mULv{>2f8O8N|r5M9_GXGsDh&A$)`nQ}9G!z5c7zn!SKm>FH4k%hdlk3dP;B|Ga z;NEXDgO9SPs35pN6jcVd){I5P#6&@CP>ijJNQ#JnUS?2MRu!Mdb>RYMT0&KshYNJh zA^g7pQ!JAtgB*i8gNuWs3?ma8Xd;mvw8Fp()E8xDgWP8bUc}Z4npkNDHI=~wFzt*! z3i8T|^6Coeih`=DN*thmCwTQFbhyA2)G7iWZf*ohP3&S~%&^;381Fj?$O!POi@7`7 zdjv)tOv*IZ(=$GsoMLHb=d~b!jm4dvEx=`-kM~U`Nk3n6XJNqrM%Ud&dIs8{dI5B{ zF{3e)JOdAC=LzVHJVq}bMkWsi(Bw4(V;ut%6KqUCP*{MOS6rKsjSb#BF=sTk^N4Wc zW|g!vWIV@`<oWL*lVqHZF)Judg3m=_0-Xaa$50OGzw^mRGcz+Xh;Xui?#=O%b`WG{ zWMPnzW@2Q4h%tjM43!Lsa1a44t7C`<FGpqQ1&0>1kF<jXxEBwV11<lDNkuvcGcrhu zgZ8QLaIu3X<K#e-YmDHF6F~FjpjbpW9F$W*SGzIuDe-g3>57|4DOxF7DTBNs<EbN} zCLra=q|D45%+4z$qvLM^_LiwJJG;J&A_M47>~D<cn3Ne57_=B>L3}34%*e<f3tCyi z%gw~fEXc>i#tIst5(Rk>Lp&0qNuGh3ft8J!6>>8n3uqA<WbP>eHkqUhR{?HQGBPs6 zgBGHpsETwD1s$@aqzJmHPgIzLjX{A?0W`c0@jS@mkgf%&ZvmZ15(KxcnZcb5&{#WT zKc5mmC$9p(bC{8=Fuy#Xm8+qHM}QkQtBmh{3ndY8X%TREFta54`*QG_v2il{hk*MW zjLva}=Km@{-3nEGNZ2s7GAT3YFqko{hIms#OA{39N}MdrEQ~?|OzbRT!b}|Opx}{a zW@Kg1(qv*}MVDoTr36I=76x_>7WQ;Vth2FlGBbcu1P2Fm0s}L1Hz--C!qhN;dgV}s zoJ?ryA{`_d8BC1ybk$Wsvk_7f;FO}nr~@k2Ac2KQDd5f+Mu-_3iHVDvnK8lxj>!#@ zg2XH&6|IykmC-{FoS38?{*@pFA~aE9gd;S8!2=VVKSdcB7?YWl8Tc6N9eDUSm_WP2 zSQ(fYJiIq31VlIpfNq|OXJBA}<x*+z@#jp8pm9$|#%4yJ$gRr4ilB@u3~I%h3xehq zLA9`GSde0veuS8kn0AOJld=>q@87$Or&(BddBNkz-2cBZ#WN{0NHM4}<T?m|suCta z@RX1MHxm=ob~y%S1{PNEW?)8e!?G1LEe4<NmUaMLaL>pL+8+v2$jS<r2IpB&rx{wo zNHI!*@+_;8nyDaYXajWo1gIJn1kaFx_Hvj*dPm^C5aagXWQgOz9?`Tk^wQMy(KOZ2 zG%?jsH{;5PU=#)U#!ZTs_unUN9Zy{YAD!iz=9Ze87Uq!hN%;Ra#x$mX3=#~!4*Wul z%uK?FGqk-oNC!kXh=O*(#WOH5wSZ<e!F|1M&|sJ_XqhM@Xcq)1OEN&l0=B6tt15x3 z5Tp}tO$9-tT9A1Q(U;DiqH6pCG6GIL;%Yp6vI0&$P9bdU?ksEpjJKw6u!0y2j0^$) zzcGn0Niv8qL~UheWM%=aJpvVqvf$Df)D35d2Q67^29=9YCdgIN2zl^897q~mzjTAn zeFMd-2!n{Su!<lXuY@)uWDzl_K!DvCZEDIS0_sjj+eRivSlWiWGrIrV>7k{Okir=M zZxg6D4O+C##K7|Z8&eASTvd67;;np)oUAYxYOpXdF>rA(v2ud$@MdHL*K=&~?2O=b zw49t!CYz76gBn()u?$d^pk-9--RwS*4g&IWGE%}S;Q3)e0niMwu(7GJD66S4c#2FJ zG%p77g{d-RdfZ%<#V3MMBqAUH<`<tOmbQMLZ2#UeD*XJ(sG;F>7wjn&VGn12Kk(2X z6DZ7?-I$aaxEb^qTDNJdGO@rtrNY3<$im3VQU|&~HkO?kboEIq_);XM1WpcaX6VGf z4on$n84)-;GJr2I>Gfvd;An=a=Vk&ck93gd<zZyd(oj(bt(=sS6cZ5?;L+pNV`pXH zX5{7pbwa^aJ;-M!X3U^GVJrwv_}~S`ph6qAu2@+K6a<W?CFSKMCFSMUMMXuJm_vt* z-1u0<gAHob*(D>Gl%?h6rKIHLrT<=zO=pb%w;nWHRJgc4KABPc?{g0gtq2_*@ZPSF z|KFIsn3Ng$IWIHMVv>aP%$RmCNrHQ3j10p6zcB@Z?~aLb;Fe}&VU*$lU%d(`?!_5c zSQz6$tE*c<4IIcq3h>Gi&?On**<;uc5fc-*4Fn#M?`8&_FA2J*U09io7j%If#J31v zs)1WUN^I<=paS73D1k<}@v(x3J`@%BWcd_z?A#eA90es*u#Z3~_llMp8;cXK7sLPm z|G)khU{Yj~W@2NU3@YRPfBnzHRKcXcpva)hFat7eB*e$a#4I7o%g(~e$|T9i#>(s^ z?En&FK^26~GATfpIb?uNbcD_ugRiP&<Y0nMM8H-;fJW0>K}SJ?ecKCKZNd-_QwBb+ zNJmRe1$11IkN^)C8!M<c1zRkm&a5m9o<m{>chbeg#f6QTA#+WlB5Ww7;s+ZyIghPz zuVVS+goPyd6$A}+1pVg3TnH32QL^@MV^)=wQ&y3cRsG@?u>0R;#(A%mWY}C-*$nm0 zFsl6PJ|-sRVP@skEUTg-FR!A^!1({we*q><CItpPMlnbT2@5hZF>6Xo2yn47fDV#l zV`K*HR|Q>q2a;kzmvRsjWMqPiDlxJ$Dl>xGMxZUMJOL373ZSMYBSQgF2!hfMTLO51 zww(>M00(qdzamH-6QoHB>(OH<1i3;Lt`OX20`+OZGxTVR9Sm@&V_;;2Sq`erpd-cY zY~X{31sE6@^cZwiR76xXgakQxrM1~XD;K~A;F)7a5qMk(au>R~Iy)bevY3ScJD;dX zZ6cqXu%HCLypW-ep#Q9xbFqSIid>>R(&|>$QjU=lYI>?4cKOS2Dyx6|28kd8{qv0K z|JomGTQD)XaCy0H*luJ4+R7mG{~J>#lO%%}gAzl&g8(lVJ2MLtsI=k(CtgUFlm<=a zv9YjbfYvmDS7<QAGlH6%;L1!MO_q@nyrc=z)P(JMP?VRJ6cXU!=Hy^wWe{T&12r%~ z>$ud}m4%s&#m#Z0$9K9`qFIxZ_ijz?>`dO`!Dpgs?(E2-BqO5)!dw~(vu`pAGqRmI z^Y2%hw7j#inQN7dl9H^fGWd{P#{c#I1(+DX_k1ZkC~&edGlLpHpvtcml$XFYU^}yq zkdP3#^9FT_u(CR%@|B$_U7g8W52W_}yPC|%$H)z`<KNpW|7<|_ZGy}Noq-JsH)jV2 zb{5c{T~S6>CJu18f%a9fF|lSqZDL~s=h|-YHD2v3J`4<?@L&*Q5K~bR65`;M&}L^u z3k6UcOP!Gssm0RB7z%NcCnOZCbgf0w|6OD90)+$!e_;FvaV0b)G!&-&vtdj?36Dx> zct|j$IB<dvc4uK>0@c1e0TB*z;N89q1<+V#VQB`nT38c6cj$nRPLl^IU}0da!=WM) z+<25=5El{>6B1<Sl|)M2h@fTWV^VIn;AP{H5Wl`BwWmFK)85pcgR<Isil8*hqpHjp z$;f;D{J$Un-e3B6T;E0x+z0<J0B+MLf$nM(WMpAwXJlkz1Ft`1U}Xj^$E{;v2F*XS zuz*{V-5{rf8(i%Spo7shRFy!r0_yE0ppLpS_>2%l6ULZHq@>z9QA<0+($k%pk;S|U z+L(#p$gdO>2oe_ecjpw*5)DPPYQjM0H2?p`Bm`a$r3kJA&Hpc8jAhJVbYt*lSfDve zEscS5BLm}({|i8MAXxnZ#!#@lA1--@0<gS4E_o(xh8K)(3<0?08DqinfjHy^7<0h# z!3cRKg!>f#&tjAU%ZDN4k=)Pqe-^_XMr}qnhH$L%N(}vsF-+-<?i|SsNM~C!?qHM$ zg#b8=7#QUlA2OY0bZ2;htcD3$jWVMolPgmiWSkdqMm96D8gqtz##pB3jP4xv$mSs1 z_5VMkJfk2;4d*UgY8aRq<rzMK)UbfA*_KDd8j_oN7$q4SLH^>rirpLrMuvM#rHqNp zPZ-1**f#SpFdAqxih@?XfcHj%YG6|n@EUN&1Z8;<X%Qy}6?su9QAg${ChW2zf=Vjt zqPn(hMjW!jLdweOqS|(#wg&iYctNJC47?1Ip!Grw%*^1Hxh|*_11EDm&@D)+%AhNH z7)8L{AIQ1_G2|PNm;?<nLo18*GeRrM{?$1L2DrKg1UfUOl`M%kytZUX_`!9PCrz9( zY0@Nc-w||hv@+8v1|9}Q2RTj-7SPs8(7jb^-b{>)jF9`Pco=x3nAt_OjRj52K%1!9 z)y<6s&oVIyNDKSu9rR@UtZgDAASP&MJ?*a<C?BgaFfjgOy22pMVBnz3%LD3<GBPtU zfs93Xh&dLtgif6qv;|q3L0Vl^gOy!e+t?I#S`!;+Z8&7IpN*YeR8drIx2d<9n}w;L zroL9LOG=4ekoi=`OwYY$ApwTgwkitN%7$qX7D)-FlUbm53hDm;#>C8Yg+U9nuUQ3j zuL2_zGe09E6CWc3Ba4?R=qyFhIRlK$OrVPvz%5Q)c$uQd;G?RdsG_RH#xAAJD8dFk zh#FLsKvrCXCaaWT2T+4X1t6CRGQJIT4h^-cjJHV8(akVO2+fRlb&H60v#|=&&`~S& zD9B|}_6X%;;fip#PcRb{3lf*`c5=4%_OdmxRFblh(@9}qU}6B>OQFGZj)99o1axyC zKO++(Ga~~NlNaceCuT;_R<Se&Mn*MopFy3)hnt&$fm?)Ign^5JOHfcqkb_-9ThUa} zl+joav>;X;QVg=OGc#uYTg4a<oskjB#Kgj_z;$|&H{-*9%KnQ!J~Z)>5;o%hcM}wc z_TaEP#UKYBsT5~oW)S0IVq)e5tq2F5=gj~*z5=wn6+Bj{21=sfxYc9yVFceP0_w0s z2ie#~v>9O?6{Mh3Vq;eqRuolaH#1`t&Ta0kvq(@>N!RyJ42zZV5Yv%nO#Am#P|%8T zTV6_jy@+tIn54JAn>QD$3}axxd1ml>WF~N);bpqQAjhBsI!6dJI?2h%#0aWAn87<A zS(u<>XABGsy5P_PSJQgTJ__<`D)KrCIx6a_D(vhM+QN`);UWESJ|@^ob8tspO&m5b z4;r`^GnaO6NEI~}5YiKKjWLyAW)lx`h%KtlaLIH0Wbfzds_&+*<icp^JGIh-h1Hvl zO)ntBTG_BLqoBd1r!6qlB|zO)UOUtrv_y%4f$=%hDF!yso#UXzfsEj65(|!7P!$Zh zLy3)nO;C`9T}<1UQPEUUlre=-^<O>X{eSnEssdd8R)NMUm_hf<G6{q8od$y`Xs4us zC_6JV6KDr06F72o!Rr$k;#n9$EmR*ZO-2SyQ!P_vMSfleX+~+#CApxH70@;|@K$0_ z9||<40y+AM8MGe*JX9zmCI%g<R|ge(VvL%_HJZ*ECY}}vws94zcAz_O>$6PU-K@;r zm2DI~eS=&CoLs%QQlkw#O@!n^oy>eRB7(IY428u^+zg{K8JCIKnHiay8mSs7|C``y zZsID%ChK8t0vbwSfSeV@frw)PMpn?JqfDSJ2+Up#tPD(ytW4>k<Icb_i;{z3ajdGY z0*+%w$dQ}srr?u2%#jyoiHSis85@E9sm8=1?cSIwVkV$&=oW1z!NevW<QP+Ek?!h} z=kUqS-`ULo9LY05k<7~K&8z31X{BUXnC_ip<=WjA6yoBqW}~1TVgZU9(0+q&OrqfX z?!*{$9kgI&yS_JQDJ(oj`1u$aga!G;_{AWXdq86ZX_83Y2(;i8G&`gckY!R`=AUI+ zSw3~z6fZ9Ky5PF$ZnZ)6Gri88KAn;UvX_wobS{?}lQIJjgW+~APF7~ntT*JEYtY&o z4N&h}9W*Wk;(=G<s5AIPZjlmTViyBl-+(Ca8O<V@nK%_hlC`gTG1{qnOL58Yd0Ni~ zl@&S+42<8Hlo_N!_ucdHf{sfBZOrvzV1$hL>4OHDV1}!!Y6yTTFhxZiMZLHp<F|ii zM@;NxtnD;IHS~=09iuapoejGg8SUM>RgCl$bxahLY;{yaJ#}4dlu|*9w-^~@{|7VP zVNzz$0JR-e7+F}A8JSs_7@3%P85x;)z~|D#i+V<oqmvm}SimK|K8ufvs-lXj2Be&a z7W1H{xhc472A)<i1@+!QEKs2Z$`*{rx`X|?%IqW6RpLy7Bh#a8?F{@4JWP!}wKYQP zV@eszI~16?g1l1l#f1HZWxQPMth^*G4NNR#WNcicL2<*xAn`wfNrOolT*lWqaPc#; zFtdS5b}#P@pw*WW42%qnEexQmZ^3s+GQ@$_S%P8<5`ki1d5{zns6Jyz11SX!b;~m_ zvoJTqWf>S)LP4rnzy`1|_(euK@Nsj4Y75W}<N}~;C{>k3l}#bF1$b%;bU;2clSXdX zzs-!EQMreim|56m#dZts+-b#l<Dcmn9bZj81BHK}%Ptrhtp5iyF@pD|Iy%_N;H)c{ z7#Nut;b$~xfX-+DT|Nb^C}bIB*$Gw@jDp#%6KXBul=Wlv1LI?YWL*?Bq#3jRJr%NN zWKGW~ED{w75SR4uad+qB6lV<eyT}8oOD+C?V-jGx#sIp_$j-qUcGD6MBMU2`Izn1X zQC>=2T3tm&RS8l@n2CeN_d&D$%#hXi;Dr!sunIzrjZIucOw3~495G!n5k0AAd~6Dl zCMkIpIYBvQpPaqjoisdj8C6{v^{-uIWM%baWBqqiPro!hw<Vx&N@$RqKckwhvTg{t z9VPTXmhnB41ajQ~I*5e{d|N80hR|RDwVvR0gE*vaC}x!W*T#7F-_ylRdA=5ZYr$uV z82<mp#09MzOh9+{87Yghvw$iGL;<7=%BSFpLXXi$Rt7YeEu$f;fv6lHwKyB3I)IEi zLU%HniG!y*Kr0_iP1Kkn!*V8|WlM~*anKr}A*-ZX(?#9X!y>`P!cEym#l+q1yqB-1 zZ$OxnE7KL^3IVyIa0gcl0^l0rpN5I6tGThOqO1o46NCQ$5GD@r{DTIAwSxsOBP$DX zj}cNYFhFuUyn4`Q@sW{MQjpe=(NI-|M5-#diifsLQ0oNrDq-akX#>!<i;^Y|7P&CT z#9Z?<_rjLXE?(}=>h8KqE-x+}Vq^7WWAC42q*s{kk!>?4D9p#hSJ6g8H^>;Y76}v& z+~77o=$3R12UST4K>=_)z_tT|V*%FOS69Q{+!tpARm7|&>WpHbDH|qk<TgJuBfnBi zpfjT;%fGh*_QnCO$c=v;6-NHlNt4XA|Gl-cnh5TrDgFP(#K@$~z{dIW4d@&%PX-3Y z3^4zf5s0r3zE=h$|C<@aSN|W(_zW!nhYQ4K{T~6Y+t@h&z6J3O{s%LD1EpKee_ug- zjsM@67?`dxuyOwX0OBkBk7WeyWoP4J-~;hh|9=Db7udKMzkv8k|3esmgUsh*`V8U= z|Np`0#khr;o!yp!;a>u%m(8@}Ujn?3smj2>@PTm+Gdn{yOr8;0UV?#v(U@^7Gdn{G zR(ZkyKNuas@}*eixfmE2LmAgIvomSI<WcOG`~RKM0c1auHcTGHev$t_7=6I*w}Z)} z=m#B0;tbZW1CvM5FZurmqbo>1lP*l28QFgz_j@vKV`gW!hsmRuFU%;$=*4si5`O>d zAmR7F4iSEgatt4sPC>#CBG0%3NnV0cj?tLuG9>)4$O|%xF*<_fOBooj$a68uF@`do zg@hkOo(b7}IYv=N2ax@s@Po*s*e}8;#^?ifza7kc6#X)ca*WPk{h+xCu>Vl>OEQWv zx`OnB!Vh9TGqU|4_j@v3frKAK9>sjnXmKXfDF!tz(Eb^ACNV}$aJ~`#|AX0`=@Nq) zmjnX?gF2HKBWRx-JC`8nwB!H(8C3s&XZj7-2a*S!W5CWO%(xq@A9SaPJkw<cH7?LH zZ;(7_lPO64K3HDx|956vu)H+X{2b6VP+Y={f5Gxx|GzV<Fr8&k<C1~O$3f+vfaO*H z|6qELV!tL>UW9QmSYGb`4`vmxyew2d#Qh?SH^B0$3=GVoV0n<gLGFXNUzG6@ME?H| zW=1UX;*2}s^1m?T)w%c?d%^DDW7+^#C;Y#R(TmXtl0N_5gQU;D_Ympxe;vaIMlDGC zgvc}QK$4gEU&m<7Xbef8SmXu&moYkm<x3eDu*h@$uVV~l)P<x^h&&Ur`EvhD8680O zgVHBN9>so<|7DCmVE5a>%tz5L^S_SK8LVFiCXb?D@_!klD@Z>meL~D<Mz$a1eosad zNcx1xqnOYCznI0B=?8;411}>uCK-7DKl^9P$j-pa6!_1UL1-f*<Bor}p!@2WpbYSM zlNo~=lRA?G0|x^SsQ1ah1U@_`5!5#UwJutjeHa-)XM?b_GH@_*u=0v%tAf{G8$-^3 zWaLcGDa>XRU67otR?^&B_K(k*F&EU{ieOM<@`ReJ;-CmJmywAPWG=W9&<Yy!0h!Cd z!N9J_$}6gE4m~JV8FWf)1fytnVNUwP<YYC*Pi3vmC16uQO?LnPNsQV|rx>_F>yV(! z3Q`$ZK}W<Uf@)8Yqnns~z_Y*tY`jw1tjeIl4+v(|zH_Iyx3_m5bB61`EiV5yf!g4V z3=;p77(i*18+;Nb69Xdy6Jsg^0~;eN11reI;NguXkc;65`GUs0#Z5ui7elaAS5HsZ zgLxi|UT%yY9)D(l$JIps3ouqQ1TwIJ#?@FELA(AyUT9`!Vq#=$XGFByc*V5Eg^h)k z)!9WBXw0`MtNg&|_;3H0FAR(f0{;aV(-|i*urnw*$g_d>R6_;_kPKmGU<XZWh-r&6 z8Z(1T5nz<Go6%qspZ0;N>EE({H(tB|yGNYKjme8yf`OYs&Ow@um5~{|1CfydbaNA^ z$;ZIxuc8Fnej%)G20mXM)V^@kO5CwCQB$qa%d>&WO>EB|u>e0m$l6@-{{mq1)VM&c zQ8q5n2qwsbHVh1mN=!c(I2lYFxH#EZS(sTNT~5%x8Biy)1=QsPuMh|EzzL!m)a4Wv z1li6gtSroKDz0wK&d4tuDZF5TaHKHf_kWy>-+BD`&YXe7*+d2g##)#i>};$ojG%!N zFW3eX1_tm-4DcRvZjk3e=>oLMWs9f~$PQssbz^pOQFUSECBhLx%a#d6Fn%{ZbB52K z=N~5nC^4!3f6erb=^g_&gE)gSgFb^b!xirh;sFs3dYp{x0v!CzY>ez|>CB9bEQ}1? zj0~x~jNC#zg3Mg3++3gwX<EGb7+G1HSwXXspo?0F&;`-}zOJzabbF040~0$dQz%iE zvBvT-vNEyyMn*d585*dnNJ{YXFff>#8dw`zYip|LtLn?kN+?Sz3k&jy^NPdMurRNr zHmjhbDd;+1&>47)kc<r;rBg&=;}p;Mx1Z6`htcWZzJI@@6cj*f1{jw?8UNIv492-2 zhNOamC}W5ZWAMMVKL6G*Dak1)%E~G#$ie7;Ci3zi5qWtS&A<%m*f4oAonl~S;AfC# z@Q1{$ENB*z5p;As149$2vjUz50<WV0$2MrP6Lgyv=nySdggVF?CkIXy6%}PcaKXT6 z%&07E0_w*@dT*>qY$k5Ie-5^CGGgK~GU8$~j8QNa=tz9VD^hZDQc|+AN5Hh49H>oi z%An80&a{hxn?Z;{jv>fFNPv-%K}e9FkC&ARbUiu~XnT=dK!k%3Xh{$gb24a=2xvi8 z6X+NOP}_kKeAh1%Gc!{-c#fNanTgpya+`{_3V5*)vQwE&RaH${MUh>6RZ3J$N=i&r zY5`-*zZ%9%|ISH^h{%8hm|7)dWhEqJW&cT9uij<-SnZ3Hl$4aD45+=p#9+!O!FYh_ z8iOH&Ekl5VuM8t-JqrU1D?2L-=qy(@CN@T<I?z@(aC&C|4Y)BefI9Htakeg2AJE!( zOLHSzV_P*91vyD^UTzLH217<e&|*1Z@caj8F&wCa0^YobG>iorUIF!?L8GbS;8ovj z=19qIv!;bCKQEUspM;u>G9L%0fV;Jti4-qCrvN*Tq^O)aA18-^q~&T62?-GqNl8XY zMkys89zk9{Q6&u#JxOT`X;XV~c^(cS4mM7H1$hYrNeOdF1#8tkAkRxmNr9SM42%pd z3?@vSOqL7+3~ZaZ85s?<RoOthHO$4?#KalJ8O6lR8IQY`8yhRiEAjIwGq%Y6tI_n+ z43<|kHZFHn()7~=3n}yQGjKET|9il~%%TB3vs;qEl)-_)o57zUm?4}YjbXRL4h2RI zK1MHQCME`t=qM&}cTi#3%pfi%-on5r0XoZyDV2d$iV<`mMk)h410M%FUpg-j6Ndmd z6DL0hXDS0f1D7B_S2}~BG^3EPpinA<uneP!sIW*XgQzT{n7F7|sw5)|3v(<3GjkJ* zPe@2WfRB%un2-=3Uutqlcu06yXh3j4a8RI+zmLD4ua~E*v%RgQg^96|p{}-?s)~}F z4CGunAyFYw5n(<-K0#qEIbJbsMiX;UP&A2&iYP0oftE6`nktHdF)Y`xgZFwvvXZHZ zxuU6}nz@L$F?fOmJT3rQie#d$%m&s4)@>}xF2ZgKQUOgBj2H9F#Kd(a<z=@0JH&YG z?<S^e|H4(Iq*Pd#7<d13Wnuxb+5VX`o@A5d(c%&2;}Zs99&PS_+nBEX-Nbn8-=S?f zd8T4w5+YLa%=`SM6@+AXIeCQCmD{zoTeP+Nw6(pZR8*wcdD*ntc-bXYRVDd&w0Zah zIXMOSgoSf?L7wL1YzM1s(bn$ulYyEbETRl<r+WPV#595F3Ipi)76wqQ%<uzTUzq&= zz|6>WgMpoapFx~Ko<SXaJ{b!Ws1#@BKw1IV1zP6C8PCAU+0E&ruBrqDid>*0O-zi9 zKq1TurB%^rb|{}Q#?s2l^4|>*$rJ@5|6Kr)OkiS;jg9qx8yjnDDE@6@V*_@h>HiPR z9O!NY6{ny(ZkQQCOB6w)i(TLgz1ibA8QDQA>(JaN40Qv{Z7{boqKTV=-I4$z|D6Pr z*FhvxIG6;v5#+vaHa0f@{@OqQC_Bjh|HCB3_>(~#G<P8?A}qkq$HvUU$pIRtVq;`r z@&cXH30e-okP2Eq2CddbL<B`dz@@sXvN*fCsJbb;y1BBcvAVgqsj;ZJIJ+^E)TTP! zI{P}Ey3L#Gbn5Kub?P?V2Jsj-)$4+|^_w@>>(qmq3JeVYb}+yAzkq=q)W&3CW@2y$ z4Y@Heg@Wc{7-AVg$D4s}#%5<=7ZzmU71L%FRb&O($Nb`N?Z54k-+v{TY|(Eu0qspP z{r{CIlIbnH9pUNV#>&Xd#lp$V#Lf&lg`a@|)bwI(@n&FWXN%`%WMk`Q^MTaij0~8y zH`2O4q_PsU?hlp`k*jWGaYkooMf?^@GtK}pq~ztlgJ?+w1*Sqd1yGf&AouS8tYU`I z|Bk>|p!OFF1A2Pbb<kpAWMXAxW<yQuY;3R<ny`cp+RO+`EU?6bk(e+O_&IpGfu(Io zy8i#4!GmEl!x2U+W_AY95qSq0I5sjcZaBEXSo{Bf1`UR%j8croOl%CGC0UFNDgWge zF8=?-zymrf0JJh%1hm!#GLgvynIUTj)yR@a!i<dIDj5_{OpN}K4xo#ec^G&EMFd%S z#kIvv!7V0bQ_$>SilL2-p{%-@hJ}%lxw?{q6KL#8{{L6T6--wc`MI7j?qNC!StrT7 zgXtuwcMG~V<-Zh@*Z((+?x1$`zdx`&Zj3wr{Q;=}_tUBwMHus$K<D-IGjwlb0o~UC zT3yWtYEgjZ>ls==yOAJmAx2QEQvh^5Hbe$|6d|Zl0p7;L#ON;#*{mr9kw($zAPy14 z&=VOM=^)6?#=yYK&Bo8p&%nyS3hE6C3!00w3&QGcQIYCfQu~`gb+Rs_2%}YvUiQDo ztx{5wQpP5rbi>GC_kSJZHbylDW(Ky+OrSLrtc>Q2jFbMYQDqDcVhmCFw-&07F^F*+ zxa|j3$B0nJ2v^9+(7-6dSON|gAqRd|7G@?E2G9x3B?64RqT0gBAlGd*y(P6D>KbtV zMzneC9IW9j9?+@9bqt_147#%uRMw!ha~K&=+c%&k=p?sqh-=dj-IifsWLWl}pRttb z2jot1Q2$B<)O}@UWJ+ZK^?^X^E80QxK_Z~S6*M0Nnwd+53PX}IJLFDrP*N5IuM`km zW<F!aN9LFRR1E*A{Qu9O`QMW955sR}b_QMshJVbUu^Gl4|Ck|Z^Z$Q_J^w#3S};^H zurUahfZM|VKQR4=*E7lv3b3|r7x;8I=6F^{@P-U<iJ%DTq{GSs7!4~A7$ZQr{@+~? ziBxm^Jq@WaK-C&33>a9LJeXn`PO?6S9FT6C$H>YS8NtND>chy)(q?bR%*1Rc$;8WK zpu)t+yNr>aagB&DvykASJ#5Uvpj;r#<)zHU#LwuN&B*Q{4LQNnh73cp8QDSRFnLOQ zZx9ZMaG=;Bpnb?7hj5bU8)S!oR>dNl!9`?<Ae#YNFbgw-o7IOA*$h5Bp^7lW!9I_X z732*}?TiAvDvXQ**y4rT3vNOr7(gO8oP&{_jlG$Zk&TtDnVXA=g_W6=g}Dy2D4Um= ziMNh{mywy5u||NAk)N57zlMQdkeOewhCxt>Sx~5kK}eWcNVtZFk(oi5fms-|fCan) z9W)>TiTY>;4t9=a23lDGN*Oft0VvJHBYeQX#z}=R;^gcFt#U>RDA2x_RCH??Sy;JP zSwJ@-GqZ9r*N_<@n3jQh&e^yv<6-6EsbSz@X5}H#P6k*Sz_b#SZP2Y`;AG`&=0<pu za(h`>k%API%gWJw3APe+r7bHrOC19XD0FKWxR5PoU}ENDX5y=3;NxZH<E<ek?Zdr| zWW7Tz<u(g2^9s~32rx1WfG)hoo%gWV56<17MuyUf;|KR|+OTx-!UZ#@Po2`;Syxk4 zSyZ5*t*xyqqbDsO!Yiw7uB4`J2E9)cJiH(#Zm!1+JuFC$N!(nI$s9bgBL<RSf=Gyp zh>1flvM>VOo{iw3$bdMYgYH46&VY_O0BxjYV`n#lvOxz(!#SY)O%PIS{7hg~pc`n| z*}>P!fK-EyvlRpB1}~#xQ&PXlqs+oD!N<tY$HoQPy}-*Z!OYFe!N$SC!NkbH%_hjg z!N$nU!@|nQ&Mw5n$-%?M$-%@X$imCV!odt$xhTxS&C9~d#LU6N#LUUY%FM*X#4F6r zE5R!)!NtWQtHvkBEho#)#;q!=&%w{CtjWX0CZZ}Y!yzi9uE5F7CZX*n!mF#p&7){& zC?Lcvr>@GwEyT#EDl4q5$jT>aX28QEt0|zO!@?rWE1)DHY-h#8Cd|tzZYrYBqNu6L z$;Qja!=@m|EX}8>$|)ki&aKZa&8DWsFU&2(&8;LO!)+lY%gx6wVaO=Qr7a}N%g4<r zEg;OH%*Dma1G-v=Lt2EFLso=Yf{TewT$oXnlaqy0fRjUjS%Q~`or#T~gO!6xnTwl~ ziIb0mM}?oChfPS3pIMfXn}?H?olAt7iIbB_l!c3zmqUPu8MHkCG{65p2i#|42CbT9 z0xid93<a%T1r07UGJtw(%nZze%)FwY&YCIni$4+xCMN&?Gw}TX#B9rSg+ZM`iE$|d z0|Og_61bnw^ZyeQ=$=b85TAjafrW7vSX`5VkKq6#Gc%~4&%n?R>1*^u`WhY#jSNQ^ zIiURzBsm5q24zMO#tTfR7}yzv8PpwAKts%+Q^6U*Bfj99Kfnjg^|Jb?fR9WAw~CYn zl}!~zmBnFQJ7py`MiJ9JjBEF}OMnKwL_{PQMHm}RO_za(^k8FJ2)jT#p+SROpw2zS zCPvWIhyZB!AtTgusEH7Rz<muHMt{cb;I=nAgC^*Fa?lyTjESID8z?v#nwWi9SQr>s z*jd=wSQ$X!$_8p|3n~gS3MvZPFjoKD#VE+=&shDhmC+4!+$sYrgVFzw%)(4p;r(E1 zhIoe<VIcv276wLf5kWo{CT1~FUS`mlLRkC9T`2uy$S5}>mN9PZ{bNRTaQ8u+k&&Gd zvbqtnsu;Pij6BTEI8R1WQbtBv`rlSPMx%dc^%zYUP4)hrVKmbFclO^g2{}0lNjW*D zXei^~N~m(CI0YGL1qEptg};mR7|j?>_5Yn_G|~Ha`rk=CMl(KXd3hNbd3k9V{qGb^ zIk;bf7<Z6!kY<ORPQt(#3Ti#af|hqN_zDUNg0|=~s)81PDvL9p`M3RVE%S?C-~a8{ zVq((z|35?A|3)SsrXLLM3>8ex3=9Vt93XQw%Ktwxu4lT!;Le}~nt6tc>-?{0IM1ZU z;Lae&@D8S)fr+7lQG~Gu+^-U3aQEJz77*be1scz2flso5j&}tQ0{4OrN0fj_GBdC+ zfcE(^F@aA_Xkzk-+zv|60<64}pzau2YF=x~$a3BrDJ^d^ohc<LDJ3N-$-s!@21y4o z(4->5a?lJP_?Q7<WkE$zWw1GnB8=Ni!O9p#7%QM|AMn1iAiE%}ugoZ@ZZ0mUjx=t= z=yE{n)^<>L88n0~!YG@qSM%>!E2zUPB`GDvfTh1IuFfc)q{0}i8l=h?tO8CqcIbU& zVVD|5s3PQkvV?;uc=&+915`?at_x*lU<IFM1a=;y!vU#Vj4-Ew%}4Z?EgVciE2<co zSnC)-Q*JCZ3@o7KiVUFX3~*xT0<Hbl(Nb5HmIN*81I+}0ddiG!YM?P*$hG#Mb@IqN z7eF;Fcnz_!5%eH<5jHkPM|}%P0S-<+4LMN>9(DmveqJeKb!&G4P7XdL88r!hVJ=>N zSxZJqMpbJCNplHF0||Kreoi(HAr2mSaeGr~3u#F`5e+3#K3+i{9wks%Zu-y9*ofX& zW?*JyNCofQhIWdj9YjEfT7de>U^%ETdS96pe0P+wAfwle8Rj1u?-(-P`6CV*yI^8S zV_3>~ok^U5pFtk98kUt2GO3;nnp6iJu++-zBPakmhC)DIP@a>WfuE6|4KlF~3L{Xv z1>ELPhb}?}T{H-~M2%72IK;>(#Mn64$SBxY*+NOlLRr~TNy&1lQHZe#NYKPM#K=a; zQW-7>at{jw#<;J83aCP0h=+{!f|kXx#<MfBvUaojfcxZ1N{XOSI`pAl^xiqr5bxgw zXkB#B;4Y$@&dA`;aE*BmV=03;Xj~jL7tYMU$ea!uWnp3nX9FFn8qdPW#K7dw$RHvl zzz>>5Vqped-2+ZNMrM$M3-y>lX$O4Rp&S#_Q*#F%6Rv!3%c{x}V{->?6Ye~3>&o&X zMoD8;Uq2ZY8531se;E}S=$HiK1^Ac*xK?9;OcR2Jy%`u7x<KU_crh?66i`McU?Y_< znlTpSVaO0XqXvl01RB!@jZH$vB|&S}8ReNcnOqsT8I(ciZwWK9Fv~NtGBJ6{F)}lH z3Nf;RkKAHrU`%IVVPa(o2Q5wp-*?FZUX{$k>aPL<;0<la(|_XNSu@D?W^wS^Kgib6 z*OH>b($d1Bl1eK2Vls9T1|Bk2dMf&&vUU=N?y^=)JaW>~ax!u<>jk)#B>hZzL_oB! z884{JG-9Y_;$&O|p6#}GumN4FCd|mpz~sdSaVzK&Kn75L0AK9L0vhCHVFkGvi(46S zxQ`vV9m9*&js7q%FxrD0hvdjod1)CrSy`F?{~3(H;W~jyjUkbNfsvijpP}b}JOk%O zMy4JA<H4g+j0~WASDBb38CV%Wbq6D)odxS^2?~Pi4n<`_MN>s4Cg*>tjQ1F?IfKH% ziQygNUZy_`3JkgoJ`OxQjEoH0yv*QZXuLOodZ9v~SYl=Z6?otUnk}HwV(|PeI3huJ zB8NjygJ5RzkKCrJt)dBPZV8*fmdV1GR)BgM;LT#nN@{B6u=TQ_1+z{@>Y6G>p{9}k zlB#a1=2k8ydj1B{Uakp--p;<-TC%P-3hInqS`NZuW=i_jvPxD0f@-QtY9d1F7TV6f z+U_Pgw)!$sDoUbUdJN1A9{)cv90AWwgVr+mL;N8Nnui9*BQyhm?>K{H0BHx%ax>_Z zG&G|?Vj5IPM1tqhRa7uirYKSjBeOkJBqi0<BqdeQX{K^jIXP7o1%-c5`ZtsYjhp-Y zuV;A7P{PR1z|Y9@|1)IVoN>qh&!9N||DQpdfq`)q(+@^|CLYGuOg~`qOh2IVUjKhG zyk%Oz$j>0h$ipNLk!RY$BoCF>{BObdhv^5CI(S@@iIELNLq|86plUq+e`37AP|2Xq zAjk+B_h$poF)%Th{{PCb0@|LHcaQ<K(Ll5LUEa{Sd(eS1Dk_*$_ku_vWU3$~sh}VU zoqds%Qec`6nSPP`y9cxwLP1Uryl&eReLNMp^oDI=Kq<9wmE4dL8$1Q~@2Zuhr4_i) zf|u0{j11s4J^vpuaD(y<H#-|McsLz2^#NM31X&&gEpx=#l$F#S)Ed1!8r8JockM`$ z3-I#`5Zki{G}P?E@QBfai5+xl%w|T=IKR0ds|zE`BSuy5p2Pnu{tGgM|KHER&A_&q zla<jxTbx~-9dwkSy1BS{n6Zh9iHWkQv5Jv#vWc;Zv5AtYv5K)V0~>?$e<Ozd%o#}i z2zQ1&hinE$9!5y%#LUac1TI8b`50N)Sy|E<*!daRIN90K8Mp-*xwyHK88|sP;sqEv zIJ!A}Y;7Q23D6-M&W<+jw(hu=%|JR9LcEAe)<BgsJ5pngRCXh1CK@yaO(f0qL_tYa zR#sI>VV}G*h@mXMPhMF?PEJKxem_iPCro4?Ofjepz{ue9Z!e=1vmb*uC|(V@nLrD& zK)XXgXLXhs=u3jm<}??PV+M~=fR5xe0gb1C?qWiw&CEatjfsNQfi6P^spn(vkk!$V zHH)=&3<NRIF;)pyVQC3DU1cMC1!ik@9c3|DaakP|H63YTaS?GzVF_(jRc%QjDKQa{ zDkUR(c@~f=aT$mzDPai_5eZ>w9aU8=31QGe4i*Nh|BXxwn0_#*G1xG;G59dta!@lh zQRC)dW#eG<@^p2v7Z%{>;pF7dW@P8oVq{~Nml79YVPRwSf*jzZ$qL#U+QPuez|O|W zp25Y)#=yeN#sWUoyv3Uvb^?AAhmSO58In3w10y#h2PY%wR%2{BLA$E-!Ckjz-0E3a z*uuFO+1Nk>0BkJ&k&zBEcD5So&JMP2c5eE*>NXlSa<Vegk`h9S0z9CT)r>`rjX?9- zVxWV7)zk$cvBC~IvPqd4bcQx)N3glDk(s$E8ylp%VQvb(oKZ|ziCxgh7<92cyNI|T z8ylmOEwhoKt&+X0l#HRcytTBnm4dC2F{5o|zjKAJg=dM5X@OBeRiwLRyrp?rzl0bY zo4&U6*Ia!&rXLQhu0CvhoNnwqEdLI%3i3?g;%EE!hLMN$-%my^o~};+0w>OYYy!M$ zyu6Gt>CsujyqwmF&aRm@j2l`0tz%&fVA@+H!DuBK0xIhb|JO5|U?^d5XW(b}h|~{t zW|U=o!1M#0-yJuyrMNhliSlzYvw)T<39&ITdN46Ef-f9pO=V{U4N8QvgRWSOWoBex zVel1#06`9R8SRa13@(i7%I50E=HkZe;>zsi#_HzE>g>wm?8b~jF5RxK-7e1EZf@Pq zy2(aH$-25JMn)-&vZWQ3rKOb>I(}i{etzL$pt7xsL5r!LNgupsh#g$EsWYmnv8$Vb zMitrB&D7Lq$T7BP`e`a5Rt{;&F}5i4@hc$~4ng|m9*nXKM;Mndu`yJF$CuRqn=>3` z^k-)0n!&*EF92E_1%PTJu)OSlbB5hu`I(sV;4`6;7)=<Z7+4uVt8O9pOE58k2N9U! zm>HQEnLvv-Ss7Rb!7CTU!83jV4ol`S?)cYa1t}{e|0gm01)CuUY6dVdG=pb@LqT2t zIM4<zKWGC=7`*s(ufvlij8gwRtUzHCz$nCM0`7Z*+FcAx4A}eZ#-hp-K-z>DcYrKq zWRPSOV)zTzC+{EwT5f^Z;nW0L2ngy!L!2xO?s)B8@`O={vCirrXtozL&;LJ(@fp)8 z26YB*h8ql^aXfBtcuD?GV!RGof6l=38?;`Bhv71~PkWi+AhQS)GlL{U6=co_bj1)O z19*ipc%-bA8I;vQv*;3_mJ$OKb1DO<mIvLL02<q1VDyDeqk|1Z)#-p!Q)Fc1HbXN* zV^EurQACc(SW#3Fd@r6IgvrOm$f)TWq0cDy?~zGHh_O*<x+#dQAK|LWn53gG%xu6W z>tti&B+F*NEDYL~!*GS+AhRggFD($i2!j_dFfb>Ac3;MVPWyr{36NxfuWx2%2A%52 z0N#Ypzzp*ZR=p0mwSk80K@B5G2600(L(qZ<b5lj|wXk|j%8I6nMxYihACvMGMmdld zKwkUzh*1vawSyo}=%9ED9GvP5&l!#~{b%51kZ=H<Z3jLjk^vg<V!}*3V%ne<wJ~_y zKwMc(O<iBtN#D@Gz)9PX@pEviiCMR|XOFo-Cj%pcEW>k#-Egx&d%+-MYM}J$3pGoG z4RmZiXo;e+nAmPZZ6`y0LwzS*ea5dLZ6@Zup59$%CY}HPGw?G!Wz=AN#iRyWPr}H~ zkoCXnzW}uFAppvyptOj*<^(&R>jR@PgE|uvy8(FD1rsx9#W))i=*&p)nicj4h&;MD zqZAVxgF47=hRckQH7(%PE|)=8gU+sc#(07;1(XlC7BVab<pZvTpz!?vjPV4+LGYL^ zIA1a{w17s(o4||EK_j@Jk#S*RWoCy)tA$Lb{`~{pX#gsh)frDPGl23B6KHLXI+Gy7 zDzJ+M8ACw(H<$z&|AF!u$b2R?h`o%UE!*nI_W%FSVDrD8u^UvrGjTJnf|u{0wfFUm zvP^ai@}RZ%{EVy&;Jxpx%nYpQpw<1%h%54Zn0!P9Wd%hA*f^!ML1*NGjxzuqxB(hI z0w2OEA|@`Xqy{?uOI<?8$TLpcP+dn$(@;Ck(^T`nvRaj$Eu$l&tV*$-5eGB7p?;aN zETe;!Q<=I7_-r>u2I>Fxj0y<1Ft9R$c9t_Ru`+-<z2J?j(EDI~n33F~%El%tD#E4= zYBhn}1iHEal#oE{f<Tw_F)C=9c*klRYH4a}8EQxS8tUw2R8cQ;vT|UQRW8#vWM}5k zGb&b=V|28$t5Q>jl)*Ot>lr>WIWe#^$bd5+GZQ#BgU8=}po93F657I`i_48gm2I|W zXK!V4virNk7NTG5e?7x#xPE2^CT6BYP(lDLnDb$POag%PgDyZ<HZ^X{-nuoLiN)@( zEm%LOfAgJT9+M4t?KQN213D|v2j0I4WCqPt2(W+*F=kdq?%P`?@;eL5N{GwKic82c z+5F3`m64K?k(QGB|DVD1|98eTCL0EIu9XZY!0B@(c+SD>e<{O!#vPzlw4j|1pcx%z zMuv0-P=7iU)Sr$8dBImuNJR;3C3w3gWL}S1S=e~KyqK6A$U4?UerLvJISC0lX(_3{ z*BK`=FoH(m7#=b<Gq5qRZDwO;G|(0X^)*b*AEu>Qx3@DUc6Tc-<6Z#?H(3TPhWp5B z&CS)##YNd=Gcv5(+r7KHl~!;q2buZ5iQzGm69X@Uu!8`oUI2#<qmP&{6Q`KAxe0i{ z3e>?@R#TI=w)V5Ow6yZIw!WXb!_8}FLfmE_mo1>^U=aV`#BdvK4g<J^WAtHwnS)X+ z-L|pzu`)Ne_O-LTpSsoAXLDS_PA|`$;PB)9|D7?4$%R20vhtLd5!54MVqgNDe*ud9 zI*@Ik!N&m5nt4!DlO>SFM@3muMU$0N66|0*Ch+EV#F;Cg>#{^qVzxv^TUn9QMAOPu zUeiY}Aj-&4PSJ%A7S;Q8Y-J==6ou5(m2E}Dyqry46h*YOxnZ#ncBjPuT*ee|JZpef zcuF!du}DD<hGAg<9S#V(PnLlN6!Y+v@Cl%m@Bxyl+A2yQr!pc%J-Y}SJGfyBI{#A~ zHl_?3Wi~Zt<bk=1Us_vPiOWnw-d0&&!&lEA<ZJ~O#ujj@l$2bjYa=7Bq9m-UCMakt zD&py6>Y^yBr3I?g7#TzvPBUI%jAr14t_5XeVr*exU}6GqngK1hV_*VZGR(`st0bhv z$|kN28NmkCNT8ugQJE_Dpeiv_!AK{Q1kuyJ&hDO?`kMNXwqH5ZB*s(BtPJctv5eqj z%orFMME`$d@?o07AjdEX(lg-$9r+@{$i^Vb$j-*>CGCJDz{$o8I{p^45<?v{Ccqxg z#mU6Z-tEo7%EZ6`xni>wbkQDr0z`rxbmbz7BuE=)EEgjuC-^Wo_5=p-qF>0Bi*gKd z!m3K3y;Q=2paV6<1(i+B&5cEkL0D8-Py`h0qL5%0R2EG12~aSZsbD&5mcN9Sh={4Y zyZ=;1#w%Jf)z#J2ZvW0Eva`Cdb9qNIn*Y-U)xFjX3`{SXPBBO`7&{mUgUf!<h%_q; zsPJcD0af;lP2TLF^VOTdyRW1fqy@!91O-Jnc%`&KH%Xa+E{Kt1f}FptrY@)~2)Yr^ z+NL=tBBj+SQa{!$!Y4*+a^(y!_N!OfJ*HJno042+&id~+BP**#S>jYso@Zj<VqjpB zXFA0o#vl(mIf4r`UJu>_#>&XR!N|tWz?RAly6_LYtR6HE+05=EAucT`E-xVu3LF(h zK|ui?(6R($Q&4#dnOjs=hMYTUs?4Y?2wwcI#uXkOzNfjqyESC#(x`Ao?kM-@)R2>r zK8!J0scFTLjvXD0-~N5D@pEwk=ao<f2BvdNrx<t{WI*m>09~Zc$O<}Zn;{l7WDXv& zYXvRKVUA<xU}9zlhZ1PhhmZh29|JD~ud=WrC$G4+u^`Avpc`e>l$8aAL0mIa&{1e? zY|6@^&+{?@y<K`z13P?t1NBk@A26M&N&R=0(a6vLZ#9$1Kf^#@#^?Ve9n-BDSQy0q zZ)94|bcMl_A&4QGA)O)HAw!dqg;|S{fh93A%tu0ii=CU(!`053k(G^`#fz7Notc%5 zwS|e1iGhcYi<y&~ffIDj5@fE(n}M4fcAs2GFatwcN<wUKbVzidKZ7TOr;D?by{(O& zj=HLfsv19Nc_OH01&^OW?mU5zVxpqpEd=U%pmiRg*%R0`pdw;o;-J<i8@s5oDQK`t z6m+eSx~RH{IJl%^Ggo306%!LTH4zsTGd41Z2o`D?Dkw=SaWD($OF4-!2^xy&8Te}X zn;C}~+GaSLBpS-=1!>y(X}B9$gc}9=n<=SDN}4Iy$)xJ@2y$_(R#lX-Q!o=3(^is{ zk<s+86th;7)Df4G6*ZO-H?%QR^wu)b5D_-=v9<}-6%+Lk7O^tb)K?M~GxoM}OArb6 zWMOpkX6E5c{-7ewrK!rtXKBX4!))srX~@WCuOX)o8lx6uU|<pix8=AQydk^Nq+wN1 z6Zm)^@Q%e+P+bi^P*swF1+;9Qg*g?WjDd*>eETjZC<Q}yL<uX3D#BI;2r@DJV_?*c zy3E9Indy|@-xkIPetrzh41E8;GyP<`$e_hw%HYNj>Ja4S>f$Ub&BnnX$Hc_Up`{`N z+JK_U2)a9$frEjWg@YM%9Ts>1vCA8LcV0Z`_JmgC=@th&WffHw4OJx-RnRsFb9Hky zQ&Y&<5}?&Rir|aF!G~_Cv#YZs&3LFY!_Q4LW(A9zs;Ma}ii(Jvi<>V~jpP>cOZ2p` z^<`w_@Q>3nG*B`U6AbkV6N>hcw^y}vOR18PQInNaQq|UDtQAlakrHHd^!xXgIm;~| zPT$+oGtbe-+%-JIG}O?}Us+rzAjr$xo|D^8IM|<YhM~E<jI!okVR=Ip1BU`Ng(!b- zP?-k0Xv%|GpFtCJ5|ywZJ2NYjf~=Sb3kxfg7c*$6f`x&RB^7)DG6NG+lQ%mf0|Q4a z0|!SlhmW9|kfFGsqqqPkxGaIpn3{qw`~?s9h>NPJgOaea5;#GF<^+w6MHS8W`KA@- z+6W4Xi`i(ZYpUA_2uO<Cw0gEiwf=qYr!k|TafM`l8Y5#`E(f14AN%!tjLdh=n(Pg4 z_XQ0F{Qu7&_x~%?L#9)V{7eeW>`bR1<K&Dxm`;H^6^sn3|DQ2AFhw%RF(^35%1I0H zakH?2#t-=!!Lvf(`+iE~#F^N{v|06-)Y-sYDbTGq=3-*vc1)(md`zHAf0(${<Fd>g zOjtabo&D8370etbIjb8=`mv}u=;;M2N|`jYIY#abh`W-k?I~+wyDUsED^1h9rozxB zR}a+3U|{<H6;$>x@-uKU-GRB28R1SP1_s7gOs)(94B8GFuzoIRAc%z_l$nu%fhCre zk%fT;v=~T$K|n+ibi}!Ywy~)q=r$!~Q)5sv6Eqf8Vl;D&YHSQi(ebrq)Qs@5)lQ52 z_XylBW@cdj|CKQpJnj$LlNbhBNG}1(R`G1iOwegWrUcM|D&VZAz{beT+yp;R4m>{q zzV?<ifdM?>8tEXw!y_djBE-Yb!!N9&#Lg=Y>e+${Y;Z$Il~I|I8C>Xr`WQ-T9N>MH zQc?<xssEn)GD@n!`0&Yt;J;=}r~YO_rxF-IyHyw%w=lUv_p>lEGcdO>AbP>z;Ym=K zK-Yn@iEAr@=EX#n1sRq8Jz(7A%fw-8`xms$>HmKQ<^M++^%*jl*}2Zc#-EsW{DY29 zf!8^eGU_u)FfcQ)Gw3_$fCeH!vq-57pynKC1c^BoR1`7$qOTz05!Dt3?+Q~CRc7S* z_l1#%@u{(KfeCcq0LTBAjIK-p3{ni@4kF?_+>D@g{-7l?3=Ab=qKs@J+Tx~m%;3JC zx+!QkA*k&wuB<M?#?E2xqRJ~K8&Yp5!^LLpuAwR=?xAR)ZK^&;QGrXwMN`1tAxlJC z<nk6JI{|PyQ~v*#QJ=w(nVstr%#Vx+KQb~XGp=RSXM6~{l@hWt2HaGP1$C%bgJuH- zkp_xDOVJp8BOSQFGdawH%={34Dl_sht_6FJ6LiNi>n)}$3_J`13{ngl3}y^241Np| z3`q<ZA?Na1h;xZ?h_bRt2}truu=237@nkTtGBEP8GNy}wMmyt$nT41^X-|-!iI<lt zo|}`M8C<+eJ2>FhDhy7U5Ceo5LE1ref;ZR<_IPe^OA>Ujx_4A$fWMoog}IidjI@v- zFE1lQLR@50R8m-oe?&lpkC&^To1eX{xr>F1p}wY>mYK4mw1$j^gqWa|kQA=~uK+(E z2O9$qBabv_@&uI0zzN&b#0+%CGb?m+ps5KfTne-d0#WE=@(_9y;kps5!)7iDzP=uQ zUQAN|O1v3+{?(}|E35gi7@E2$`1qPS%X|NwVCt&i>uc&H@6EUpi3wKs=LeW#6arIB zSFBPTb4$vyvrD)@`O3o2-#=jf+&fmO4!I@Psg60t*jUcK0sj8;<|32eywk_1&#-`* zo$D%&bY;h=&lJD_J%@mi6}00Fw85MevP6Y7mJPhmn}Gqohnt;8Qd=0*=!Bkf-=C9X zl9R(|mv54vZ<7E2KLhA&&(%z)7~C23nRwviF3b#4{{@(Gm_X+!@G}U5ZaCuQ0NvQm z$jHhDuBaG2k+LoW8!HoADg!GsGixXVD=Tv>J0mkIvo8aKun_2WK9FmK1VuR5K%1c$ z8BG;M6@?iUMVZZ+m6;Vy6{Q$$|D9(t`#1UbzpIREKkEMQ=3{*FFZ6>wV-n*dbMt?N z|28dSJZZ?-`DY{OY?uEGuK&L?O=G&s$j_j~beZWiygoV&s*ezUV&n(;304ol>Z||% z!Hs$|P<_T=!(@g<UXwwNc?Hu(#&!l1rhoq*GB7wW8~|zJ+{nPR<NrgDEexRLYzqIs zGc94d#30Ea%b>yF$S}#FU!0MJO^lJ5g^iJs!-$ca%g&gIhufZ!m50rX4>V`Qzy>=0 zpM!}5v}>A`hm(huvyK;3^)NHAfCjYKIhfhg88{f2xHy>78Mqj@dAPXK8F*MZdBPcZ zcsS$v898}4{k1fuq!<}&tjtXf^fVo{9Mx15<fLS!WM!m9g!p;6I9OR2BpD?I*hI92 zjX;+V!EOcw-GmJ~vjNnF2j?wN4<53v0KU2r(l`c<OBsPD^ENs<>GOzKs_I+Jv(S>2 zF%}b(a$x-O&&Qi_%fI~wHd?Zh#=4ANu2HdWQYJzog4%+S+FDZjVj?<Bm&~m1Xo*T2 z8YQzai786)a~tvsaDej2Dkdg*X(=&%jlb`LBVvMhIL+C(i_NWgxoo(&Vc}X14_7~i zUWYE^aCKzl;datz;^NU`WaYvdu3Vg4xWbhi6t3J1JY3v7=?q+~oLu1yTwI*-44hn? z{-8j0bFsHIHUu4^k1a^~NeWWXUTElvVW9CoaC;5ZUS$Wbe*slMa!go*_bMcK@4<q% zu}|4tT-sJvRZUID$lTLX&QeB1%tS_BR$WKdK$?hv{uh$Q&1J#EFDW7}At<D+qp!`) zW5mTPDkv^0z%2pVZKv`77t>d8pFxH}pV7#B16M$VgD@{63$r926X@=5CRPPT22K_) zY3~i(P$@=qDXbbIBO!)aaWgV9GdA;bF>x?)GI4O$u`x1mvU4)9gYFB4-2TGK!^p(J z%9IY8X5|cL;N%4D4drA9?MDRJX@*5FGdB|>0}Cr7OF9Ei-3}C39U1AMA}h<v!oVP_ zFRQPkrJ=5(Brhi}DkQ+o$s)rl176<D$0n-H$f(SSGZV22g02?<^;n>%{F|CGRY4+o z20ZKN2tcxqur8B;Eeng9jf10ygP{iKNC~D>{}y9p6@`DBwGFKtZeDS>G+hfCi#PxO zjrlZq?|Bhu?43c45kxaFfUZVRV>-nk$)LdC>fi(}$>n54_*ht&MVXjbS(v>*lXlIZ zX)N%99~K5y(2j2gHU<W^P|%H|v7q@fUqN9(5kUz7b~b5kMMX$g8#KHEn`AZ@Wn&jr zWE2qt%^NeR{hQ?JALQobq$en@CuL}AWWuQP&q7B}PiH${PIOcjUrq*-m@zju<G)=@ zA||3t<%~fNL41tXyx?=0SwJhdSd*B}g4e^#GN>_JaS%`xVB+Qy=4ImH=3?aK0iBn@ z84%&1%fZUR#|%2$rG=9n)WqiEX5va^;AY_A<>pBRt=QoWW#Hun4UF?LfF`j(3EPl? ziH)flStk=40~a?N9*rbg6d4J+kwQ&X7Id4I1n9bI&|x2-dk+{O?Pz{bJ6c_tU0K*z zSW%go8Fc-Du&^;RBY43w=sY4-HPBKoc6MWCL$kAH30ER6FrG`VtxsGzGo`3Faq%D4 zNJj5Z*RL~vV-a9y=VLQpa^?)v*}uk&3jZE37BNQr`^?DuZ{@#Urc=KE8GLsOJ1NLI zi(dez69xw6V5D@S$(Rgo*MhoxTbUj*v4JO4nHfa>e`TD@bcI2fL6$+2!O6iMv;tFv znGv+j-HVlxk%@(gkp(>51YO$1!onO6>d$mD`^d{NFsLfaY07KL$}k8s2&=J!&TwKz zIk6iw7N>3oIm}xfc`N#4VKogogD8`@Tq#oxF-0L>UTF<gZf8?PDag$;ry2Kgidc$E zL<j3Sn#&3(8>{oo78R4%*OfA{Wd0j3C$AtYs{nEV69fDIZ_F}GKNwUQj2O}#Qe>E! zcz7ATK$kPHH8V3Z@-Xl)GSqRhGqG~9FfnnnGJ#SKFAq0wIzMQ|5KlNiBM%QlJRc(i z4}-rt<myHvbt6T2aFjxtH@u*8syNu$SQ%6qRY8?5tCAWhVg;2!&=hpZ5EzRpgJz=O z2ZE}D_Jf0JV^L8tF(wC#5J`3+yIJ8rKH;+>R<2}bVv!B7%q%LZcK7yj4|Zg9;?h;~ zWQzE^f+@m2F)=aGUP0DLR!6V1y=IDMYEnvKT0B<_Xa<LYkwNM|KjUMj%M6O3@fQU~ zHg-lv7Es~H%ngb&FL6c&Mo$KI1~yi9wp30ICRWf94=kYlz|d{(sQcL&7#I{86a@tZ zg;Z2jg}B&cv>8R&#l%F#Kx;=3)tj=iskx%5G3a0qQFg{tZ`$e@?JI%{{q*8>qa)J_ zobLR)pSk<r9me@*8PD3>WKK_TO0i^A3J?_zc5!reJmbB~#|Cu5wa))<Ol3@084?(Z z80r~X8TuF&Fl=&IZz?Uu&%(qg!^q5JZN|jS-rm|&S6deD$-%=rdukLr3qKF57Xup$ z7YiF#9Rn*DBNr=U9RoKzFFQAH9RnvnA3rBw9Rmjg7b^!B=-?mF2rg*Oj+q^_P?ep5 zmxrA<1GIpTpOc3_U5Js7fq^evh>?$vAzpxyfses|LVsy7Bg3p|{R<{6s3|Y5FRd>u z$jS%|aB{FR*Von3R997y19j3F5*QPN*+jHimB6*VIhZsvHwQ0F1~;nA;nNVHp-9lV zH((l+G}z6Ijf}*>T8zQd;%uOB76FZyfaYF611FGUaD+jpPlJsF9V9C*CdLjvO#qab z*xAL*K?_OM+0DTdAFxBX*_1%X>40a$8KrcL#MoI4JhU7Y1v!;ec=-9b`8l~5S-9Dh zH6#>xq+~?6I9Rxa`FNOxxtWzj*@d_m8I7E^-HkxKI{^uKE)`BiX?~?tTXrrnqbsaz zoZ`AF8me53EX>+T$2kQ#IJks31*Cb{<SR>56r&9`3z!)2@M=zwm1kw<5aJL}6JcVK z=Tfm!6p1wD(9~4Wlwh5}%Eu+h#Uacj#K@>AC#%3ME-oy>C&0|BAlSvsD622v9;)sX zpdn)-&Zi<OrX|nLF0UmnEvjn7Z5|=0Xr;oqPgql2#?eYu(@sIiNS0Y>8RIHOM#kmL z>=N<9A}sS}aVjaWu}jPSdtjo?8)nJK$Yc~Mu5H4=1gdA4;+ak{h%(4BcsaOpFfy_U z@$+!9FtIRsF)*^RuradKaj-HoGqHddoUpSou%|MxF|vRwM$j-S8)&>pR$4-gL6kvM zNJvOrk&{glI-)MZ#x8CST1%wPu57NZEGTGf1R6tDPTbkm;^S&*5t^0}?dTR#>^C`W zReVGw)2XyH*JSb7sA<cxvsc#tyTMr8?gd)@!T>r_iGgVXvjBq-gCv8yg9~WNtC@k3 zm5r5=t&W9}iIb6mgNXsub6{oUU`=OWV`m4ukUf?Qv=iEwfk9G2M3_N{K}b*pJfO=B zs>MO&lOU*U0-sO;x<G*ul(N*68F@3DRyj@T=$HgLXf8i3shFwjpBR&hk561~aw+2z z8^%aR_YiN;NplR$42l2qnc|r<8N?YB7}P-fw%D1NSQ%85<(b)7c^R461Q;2aS-e2! zys<ENurM+*gU%QL)f-Lhpa~RKHqa$+Y|PAH7lRHbVq^A|lwf3#mXc7AR1gyt5eC(r zpvC^2Y@llb#Ld;sS=q(FOA&>^RVS#V6;~ECHZU?4RueZ-2VEDSrmxO-hmVn8s#42Q z<w)kTH1mvvr~_%)Of0r?O$O$sMog#JY)wpD^0j&`ee`(#9blCC7tFZh-%X}de*eBR zGP5;$%Dv=v{0|!c{KjO>bcKnH@fZVWeBFXEnduSJWd>CSE0Ax+8JSs34K*b|W9ZC` zpnI%X8CjT^nOK<XxH#BB$8|HZG1P%tSCE_j*cceY!2^Pvj0}tn{%UHB3~E+tRwl-} zI@($q>M~NI!W`f$fw@7w4JFX^g`i>r)P(>~VZgf(pdJLcKrk0H76z}iGBGn(W>#ia z23<KjU&d5W*j!d!LqkKtP|4j|&RCRRSXa_jQ^UmEw<9htG1`HNktNkMfd#a3fs@0O zolja^Qi_jLTvOS=fSc2hlh;T}oKHww$Jm6OG2!1wM*e>b&T#1SfLH<=Y!^X&;Qycg ze`gV8l4tN^h+)WLs9*?k@Xt>S_Oi3kQIq6k;TGUxVP;@q@&eVcygW?YEUet=TpVo7 zpp|&xU<M0AJTns`XkVCrd1+>Pbflk;tFyYgx`v{Pii!dso2)h~q~t;&L8Gzo{k`CX z03O{p2L%x5j3hQt(FvM;L=`Y*2F>|^3R6&7$%>Q1BFbkTs-PHV1|q}F%)%5DgH8DO zl-$JSmHF)L>iAU^#5`4$+{NUT_-bqURpiCpRg_%C6cl;uYWY+Z#9Wm5esRjl$;ooc ztEwve_2rb6lau38R8^H{i~_M`ITch?6gWkNg+(D)NX(d@ODQ5+y*T%QdPJBiw*Wtv zVnmGkg9qwS;YuK$N_Z5U$0(%|=r1qtAE*)%6cmDk4H~gvW)Nh|VwQvME0tsjaR>z6 zz{$$Q#J~m`Gh$<4=U`(`<!0nyX66V5En{Vl<>%q!<Yi^%VD=Re;ox9k5Rnv-1hsZJ zggKDfJJ43F0GqfrXu+MLs4{q^AY@L{SkxHID@$eMN^843rK4ktlYKv97NeG#*}rRy z31(4dDQ1ib|E`&VRvj=f{Lg2KV9sO^1??sk72;=SVFjIq2~HLs;NxbRp&b;a5+NZ$ zX%;pKZANu-R%S8KS>oox#>}8)n!?P+!i@2^1Q>Z{@CdT8iwP`<{~sl5YaVhauAAwP zm9fv?<H`=Q%6__xC;plRJ!Z6FlK)o<&d)mk`I-5c+8O*AVi}wr96~%SIaolao-;Bs zcrY-rfVKhEff73tWQ>N9jhQi>fsK`wEu4Xk4YVVIjnzLUN=H*uMO~MjO-fr>99;E^ zo0&l-`^7{dH%dU3qkw99&{=85M&Q-c;2leBZ0w+=(x53U&}b&O*<i;cYy$29fah_H z%-#uT8Hw@oXhdoTb*tM4YpS?qxCX~)sY%FbNijQU7&~bQv$2Wksq1B#7(}UxnHtDD zn;H7+sYpvIYT7y|shCTPNvN5Li%B!Ji>do3I?9?znZ+o(**NDpnHR)b1Unm<NsB8; zGjnolYMKNDJ8|=wTWgu=Xr!2_d3t!NI|La7n;B&rXvdh^qz0J(Wz_T!)Yb`7)^}1? zWMKS1fngQHH^xQ=0R~g>DqJnl{W*+Yyr5E_6+8_DEA_zh3I2=>+?)&oi~`KOBH)#` zpdI_{>gMpR18hwij-p9In*@2~L`AfOg(PfNS-45M=-KEf@$)zdh=JzP{1_M*FEDLj z;9$^jP-SIg2CofcW@HEjjkGf(-5tciz#$|k2)a8+ky+W)SXj_lkg;!1%jRAuraY&A zx{R0q1|XZq2}*}-j7+!<<YeF!5)=X(D5$P%Y79E+m9cNtv~`o57>}%Snl$Ne00Scf z%zY%8XNqv)&i2i{PNx|cJN?_r=nZlrxn>H2%!IgcOApA6NsK&BH*SE9WME_fo&96T zw1I&Qv?ds|2AF}-iwTtWLCcLmVF|h7iH(6xgc)?j6SFxe1mE4VpY6;vOYENl;{%XM zpms7WKI9!_I6(bGWP=zOL03fyihynnF=jRgS6G7Y9@s8k;N-+KQygLp;{(th6KK4$ zGpIT!fsVyx^kQIS08b-=*C;bV?z;i?qlLlu-7uSj)+`9VzG8p0*okSD*xyM^c_1e- zFfwpM&EjN`b&%o&WovNR0xEYvOWo8NeFR0}E&?6cEBNlQ-HN$RPE0ez|A{lMw*MQz zxB=9sf}11bAj!$X3>tO^FGU2eLP0Uc9CX#F>ANd-+Zvplm}ZIoJyXTF`)>ef1t%ke z6!GQ=L!5KPZt-M@IsX_9F8>W+bO5DQ&|D@c&cI>B!UVebiP4K0Gt$@@*hRsS2HL!9 zYApEfjLrgQ#v{88Cr$*XQP4eHkUXU9pa41_3vx~_ID8OM&%wYU1~Nra5R^yFLD^@) z3EkNXoR~tV?bDw$4HVdnppy`w`BB9|k(CLQ(XlxRZWyz=xi}~#G4`!ItaB;PiSgJD zqhtTBGJXUZ$H2&-0S_x5@QG&N3kpFy&BegZV_;;|04-sF=XB7{Tt@IFM9_v^xG-dA zE++%0pfIEi5L8w-7dJKq`C`)+g9X!^7*B52U$7J<JUBsVj}4lJSun$ulYvtl93rM5 zUx1d$GxjYwp>Z|ashH7wpULsZjH^)0V`orukOw6{7Esj&c0VF`VUeUL$Y{<8E}Z_& z&||c6Vw7Wy)BAUY(FhbEj0{2y42&ejxhXWK-mzKWT+XB@@vnlh17s8f#4Jd>t2rpM zGBZKaGZv4+V@r@3l4%+H7TmE}u)v9l;a>%l0<xLn(D>p2tpk9@KblYBrl~WV3qwQg zy4}SLrv;2(rT>X#G6kc#j}vqn2IvSANV>%0KzK|*90-oq*$?ejOmkv9`tKAIyVSp0 zMxAi5u?&n1!caGIGUz&JF*7nUF?z8uGI@aJyP+Gs;pv8ffdMJem?}d{8OFYir>yrj zJ1u4WECD)d6l5|YJV|jcJF~eksIXw{TYS@IYqt}l$`U3CiGQALjE3N}1FGamif=(^ zeBZEG;LNDPn5q2l8zUFQeXw$e1GG+&#Q0ux$pjSN`u{#LW~#xAWME`ahK41P^@bum zaZj~kG<0I>SNwa6Ne$#Yl=4;GL50Zp28SOwz876GSu@3n@z@f^Ox1r6Cij92Wn=(_ zA1I9zpO+D-a_woWqm@oAYZ+se{;jTLJO?rnRPL%n{Y-ND5k#b)75gpLH99f6F}f@N zyTPadj%!36Eaf21#t1Gu!FdN-Z3=-aDRodUPcYd2mb0@M)2zP%j1NF=g5^7QP#wnz zPSc=vEh7UHXgwFGZW0t?23?#8(XJe3f90uDG1vg6JO+~LZFON#fvwE!ZTnz>lhXom zrkP0fHY|;Cg7QBn2egiaw<MrGfiwWrg+c8RWkK}_yDJNvoEpTKX3d!KH-K?B_?|lC zdK;7;Km{kb-e$#H5;H@b$JjS}mEGe7PDPCM{{+ODX8bE>?1aT1X>J627Usr&F{W9d zzVF`vM!AomaEG<;I2iOCwAmR!OP&}Q8JS{PKnE_VgU+yrv6(<;`ExLE2trz+#-_&L zh-CI_+2iB{YK8s{V7&ZK7o~lt@1Vm0x}_M@_`z)`sDu&%S8E_c!7T=6zt-JgQ#sQ9 z1~7L0D?@fGCur3Tspf(TDP>c3ziF$SoF+M~Vm$IU0DLtlwcOji)yb*HiLvnS-vCDG ze@{W~MbvfD4ifCp_6>4|5Qb(5u$TR8?l?P3Fa^2&4PXRa+5oxJ4wUyf7^ED;L8ldf zI|q>E^Pn67({64os4U1HYIl8slT(H?<JSd$1DJv{L49XLna%;)W5EHdBas~eOUvMN z!t7^r2b3u!m=yk1FfsfMVC;aHgQ#<yw}S4*1l_X?Ix0YvfteXJFU6n%TK@&!Ri@75 zBkdpzS_{O)zzoX0Fww|upb>b`rFh2b!l1T`vY@h`_0?rgPUR9z0v&$?7@vV025uvO z{0(XEf*cLbHz2uKv<wJ#v?+6d-Lq*<P7|e=g#VoYwNn!rLFo__{zRGss>YQC)%|R4 zE_QP2mSB=t!l?2$fYGoG6px5@D*kwcBr!joGtSP2yFm$TA|&iU`a$j>5Rae^fU+R7 zpU&ZxPEL77I~b4s4PgBE?<&aO3?#O3LA%UBeq!ufFkAP;0;g${^!H6;3I&xQjBv9! z8KfN~V0|2rEoh-@4r#r!`)Qn5;N+BTvX9Zb_-_E?s>dkpS}g~47G_946HCJty#WHg zQy0`~owmSW%O<Dgi}bfL9tSy#0pTuU+nMUncIGiX#tbJ$qkmWQ7~>e_K!!o;O-Q=~ zf1H66kf5K%4QFR%#!PUegRa3sY8T+G%NRjfFV>1N+sR3hssC>PlNwSxfapADa%qv1 z(*iZd%zvMl^#2Ahf)>&-K>PqoH-zFz*c@Ddum@P3UhCvksl*t&w&iaC<GD&Cw-Aw+ zK<P!<RNW8knklM`nM*(^uy-;jWiTMx49X4)kOBZp4oA-4pdO^4a=gX<6;4i#%8aR? zMgpT7C_kw}`vBlOV?ZNhSh^GNjykBfW-Rz_w%$o+rr<u~9iZrCV1&De9n{|kRaT&~ z5p={3BSR`^ZWrFY78V3`uN4KA!6}ciZ`vaLtzVe(78+~@w^{U{Z6V^@l+5hv;IRY7 zzO60lC#O3xnHL)E_@~8q4Qw9BZ;&`scTiy?s?HY#XI5|<aN%s-lM9>}_f79N+A$5> zBZY+*iDsH2T)C@F^CYMpak|2I$G>7mXuFaecOuN((60q@Cm*9_lktv!&lx4beh0Nn zKzWX+c!f6euh>m<W-1f==gxQ+ZU)G&gz^rgAEzw%?uzYn(BMm{#6M@y7!Ig42?{fi zTR`T3#}-H!e|dMs?qseLQ<>P`ZSe6Im|2iK1dmftzJQgO=;JR}Y-fSSUrHtZSyEyA zrA+Mad#vLxM2`nS2Vly?{wcx+U=U+_91PxDAx&=Y4WK%moS_MD!w@=}$gXT^3?5&p zJ-lp|6H`c@6R5|IY9C~%lOp>theMamI#uSx_{{0w3Q$r2#ShZ>rO!6#a47kfA`O`$ z4RNlWyt~zDI-|eSzyF9fI;>sI$v|CuAw#v`@s)LxK>bDColdhEmBD#O9$KyvReu`8 z23F2nO?95kI9=}F9mXC|;fmbuByKznF{pCga>g<zCZ>NijLVe&U1kKAV4%IJurXCd z2RT;I%qgg_Mje>NGN`iXtksEJr|FE7<^EM9Lk3kC89;YPg7P&dsN4q)%rh~vVW~c_ z4X7-*WI1zz6XTJ82N-85{ky^F5CQToXrC*z4&VfxWCzOLpsU1*Xv@F{Q&t_d+T7%{ zoUvK%-$HO}2H|I--3cBD0LSa>D^{zzofwT)F)ot(w`nG$EZCV0j0~VM8&tj$7r&sv zQbA+EcPI5`J2PsZG@Q){8>fKP<s1w|#xH1$6Vzr~a9qD<jT4jpzmKO4`ax|aNc$G# zE>N6sfbW1K5Wh%6jVE<4WjQe#oiMy~l1TyVNr)doW)UB5pu?2FmFI$!`m+`|F`iv; zQh(<BRy6a73NuAh`0&njJw|J%35=PB|Bf;qgqj6w$CH*$AS1Qlm_4z?VA3ilMz?Lc z3qh?RP(1}Q6BMUJ)tQ3KpwW+a6Ku{nGco;JDghp4MvP$*-xdO!!`N4{$NI!mro4Za z5R+i;0fj#a?IHMx#j-A&GYgy;KmXez!T1p}rUEX5L4E|82^m)eWiW7m4&OM4pgJ>T zbcM06d#TOI#ZHWyTK^SDFn(OJ1QZ#tar%u6B$#Q+40q|GK9Ea&88`e}CBgXVUo<1w zRAm2?U@q9Lpne2n-_+S4a~ZWh|LXz;!7oNOkZVEag7O^E@eDdb)mZS|aot(Y+l_l6 zMISW(gTj$e+X#|fl?C6O)UDm`<g~-6n91^Q0OLKFJ3wZD@BIPoSY-r_&ET7u0?jjk z%8}!`JDQxf8?Sⅈ&zyuw4Xl5V(u-?xb$hE|7~V86U>|4PXSH+W{`uKyD(&97rGg z-AUcq3qj`ePiNfsH((lSIYf*(p!foZQ1?cVISq^!jC_9s7(rV}z;z5Lu81l#j6s<a zG$}R1>XI|##edi380YwbVx5t}9$K$}%S9IGJPasDfVWXWCM4nYo*+B3x-hual)J)e z?II_p;N*YX<rqVzL(GEJdqkGmh@`$^qUEIpPK^8iy-;SH^)Hn1JH$Mg+d%CTX!o6> zb`fG;3RJd$%j2TOR$FH|F+TfuP>wMf)B*&hKbSv=E#Hwc?UJb=pF}X`|9b%P$_&OW zAg?fx(Ix;FF5nV*%2JS-jH-wJ9Z+VRc@Z*t0CFd+{l)>BM~5_yam=qEw|qf!)WV>e zGW+V%*-nfP{vCIMwg*tmgEW3|n+I#zf~V!d?gUSHFL!EZ0w*n$F-t86b<kKl-Zl$- zq94>W2aW15_LZJqJlBb_^N|yy0XT_KW+o_GGWJbc*R#cm(P_5Rent*x+<@8!B;+M_ zb&yHm-aez#Y{Qd`{7`d1_XvW@2qN<msE-bchpde{%NIB?DV*G3upBZ4$pGF^37z95 zs{MoL_O8v*TfV@FQNGe}$G;Cupb0KeZf1bFji~ZMQIJuc5u88%J=I}!cVc|>@2CM| zW&xT%iOwJ3!2@s_nO6()>)ff`20NxPZpSc>lyN%fXbC6;d;4@2EO%mbn{TiY)@Ct= z_A`iUv#^8PEUjj{otcd8sxq2^9END;k=$nKS#Gxd3sc^|7b*~=km?~4+AQp_S(deJ zW|yWrG07ZLVKjpd;(+56lx{)kjihz}JFLwzWxg3`d}LqG7ZpY`=s*s_&m@=$8pi=o zS26ajYXzBE#JJ%M$f=Nl9J0(5WQO~GNk7O;Mm|R6+aN<B136&-OOq1E(6OA$=5w4G zQ&j(bXEFfyM?q$Q!jMpVh1pyjJeBnQj`^fjPEL#|s_&RY{{}E#V_;-}nL&Je1==fn zciH@4HOQ=gJ0UF=gjodJ2OtMQ+AEjMCang$=qux@qQ3#43*A9yX#EG5AB4;iXNJs; zE1SN%Y`$WOlM^Fjs_MVTa~YTa4OoHXH$vusR~mtbQ{P=So3jw?o`1g><zX!rP<;hT zucVc;pf(F=RF(1O9HWyJpj-(v2NY+-<ZW<K1}Y=|?NwvUbYhD9_udGSDG}+CgSb8> zqKrLWV6=6M6XS(0-P`|SnBeVaL>~gYjs~=>jY{nm(6}(TJf1t>VB>Bl#%CLJkAhk& z2tN>A79)HC86fS1jgQU)=Lb+6fx?zp^B@Dm;IbV$Fl-4L7@p231Bxw12G9XR#K*ZQ zv{!LZcZ&10gGN(8^JI{AvlhIaN>qI)2<pOvTRC%1=rwI|Vq*I@@t|G}<1&z|KxqhO z9#Lrs-s7I5$7trn7@_y?8dC_!Bt{09IYfsS*kRzfTyR9MZG#iz)_>3T>NPT&mVv_` zVIHI|1TCDw(Fg-gNkdm!nSxhZfn#CA7K25ToR)9WoeOT&f&2<OpPQsO1us4Wo3`Mv z?z9C?jQZ2}8cmuC8Js~LBh_?JBf8xQZq|WvV&VDaGo6?eZaKl~YO>m$pk^#+Hi)rr z#f$?DPK<6&KOh4%2={@<KuBwMf@Y~0`^rwOpXkJRsK#k#KPZ+#VF+_0%uG<`#vL!P zwyY_lb-Z@++R0A++nr`H9s-;B|3AY-#wCm=n4U1GG5TgQFuF7PGGwxJfcL<2Ze(QK z!O{WV0nf~!`Tqw~IFmDj9D^2v2}895zYrS}6N|o{jHECt=o$k^A)~^;!U8_tCjhiq zk0G9!jfsIF&>M801dIbZ23ZkB8E6*>voBN;=q#&12A@a=aUE?&25l1^6EziSDKSxA zZU#9<ISx({ZE^51+u&u>pxsoUCD!8L6ZY7}mDSnUm?67bz-K{#jy+Zf?}K^~ndWG# ztQ_j;8t7;~L0veMS68+u*Iq5$LBmi}QAJZxPSZ(tfx3wuN2sTjkD{WThLx+Mt)ZK2 zud$Cwta84+k}6}Wn7*>SvZ}nS!M`KYQuD<0b@WWYdntwg|7PT5l4ay)Y-NmQ5{92q zAPfq-|Ns9NGnF&+Fx_HcXUO_@4^))=|Ns9iQz3&1(?bR}M!%&D|Ns9JW{UfFhv^>! zJA?Dz*AO-TmNUiuF93^`{R7=b%<%vJ|0bq5hL<2Q#-RUE5Ox0}nc^5$gT=i58$!jx znc^5$g2lZ5gN~R3=}l#dW0=GAgn^yW_doauoB#j+PhpB<C}1{ZU}yCIp99hRPn0R{ ze+$!n26o24zi%O8|8tn)7^X5UWngFY`R@V}V_^Jmz|72Wk=cuZnLz=(4jkibRzU$K zUNP{JZ)QbN#S4rJ|HU(Vxr5qG|8FpbFlaFSU|?oY2kVsq9gf0)>z*#qdCkJ2%BC6t zOh1+^VPIhT-@z2ZPyyD@&R_yIL6eo41$43xV<?!x$Pf!!SjB*GxD2l-#6_aYrp90+ zKY$Gd8Oy-*_ZL&#|3s#L3|tJN47Ol%jYRl3nOQ&!e!%83FrZt&&CS5TEy^t_z|X+N zz$F5@{|e+@(2fOBWj!W!Q)MwRaR}?HfT5_7xS1Z8Ka9cjPbo}>N66ArhzrgD`7ebj zj$t;l59sWD23N2<tk_vWs|OgE89}@085mg@z;}f(v4k_QurS3lFtITC^YAb-@JRAV zii-*h3GhLVspo*Mx)%m-`~vMuH!%|jpVOyq4B1G-C?YQ}A|@xdfi=*>%bUfF#aK_> zl9ky<T2@9zMn+aT!^X?QPE$-moq_Q`*j-Fd7<d_sz^($FHOR!+!omnX2ayFdvmDO= zxx0m%i-V1YnSqy)7j!u=C`g2j#9)UZDw~-xf$U;60@-EG8p!knVuy_vC{O+0$as~( zgXt6l8xt!ifBfIVc$L8$%x7BxO3NU5PcWYYEWeHMDuXYW&$bFAKj*&*L+bx4jO+}~ z|4aT{gPfiH=Nc$Sg3U+Bmto2?F#cchUyUK+{}Tpw1}(5Z<rzSy0D=yD25p>$t=3^= z0$sx;06M=J<Ue-M{yJq-<%m2dr@UCleU6}vg3T<@rnpcBW(EdEX7GhWpoQg3j3{P_ zD}xiLG1#n`aI^fFq8K(YD>1M#sDa%j4caXOIfWABIM5Oz29Tq`mzsdw#H=W)Y^u14 zF~#ZMJ!Yj7Jq(QhXEJFs<S_kU;9!sdo59P$zy#`?Gn5E}Zb}C0GBYzZ7H4B)PdB!S zW#@}aXUb%Eb><F8<6&U@fBL^Xg9Z5BY^1PZW@G{#YQn$_y72^b8wxXnzp$VPJZvDv zwy`LvU^cb@U5zcFVDZqx$k4(_R>~Y)CQSctz>xX>0s}ikFvwky>s=*T7?~LunDaoH z8NA(tfq^j&v_-&A+Cc&&$J~r51z83T+B6^tzLy*1C2`OZjHbq>iXN9d3{q@tQqb%S zMA!*7mw`DSRJk%j&W8rs!Qd<HAP%+?^UN%4HnM{b;}KOB1=)B3Y$N0U>HlRIGXFne z;AVi9S`3T~ETCeKfsK`knFX>C47Asj5wzD7beax$3nx3TB)HUKhiowy1tpG54<`=~ zr+GGRZZ>Xipfun2KZ&8}|2#%^mIeO{{slwQ{J&sGnrC4A@Bbfku(=ikAA<$RuMWDP zyZk_Vu0SWlGBSa0xq@t0OaO^81TZpy@-PD*BOeR25MhUHQ8Wb|ZoyV6EYHOuC1Buh z`Hq9dlbOwA#$-oO?ZC*u@Lz~wBLk9M+>A`1UG_|%t+q^zpaUovz&EKgfb3!d*~Q7u z%7SbcD8+zm0d4IQWn(L~vGg|(kmBHyf9K*jd4>ravnLA&C=UNE{2%b2^Zx+`ZdhFc zjyK4@OK`mTGcrKRLT0EpknjEbcU4qgUQ|?Gegmki1C@E8uq^%`$k6kD3nM$I&i-=? z6qZao{@j9uC8*x~FUwHy{{!g8q5nC5_Cw|O!{z7w7hnLTFgAv&2_W;<{a0ZKX5eRF zV+?2m@o)S$VbJ)0gPEPXmx1BW1CV~k9e*A`^fNI2_xrELunC+OJV9{<$qVA3MeIzB z`QSrmk+QqAgBVB#dKxW~1b8JOJPWdeiUMU(Wl&-8z{y}$ULK@;a{lknu<!q21~CR} zkX;T2tf2c-yx2j@a+sMww^cAOFo%P$e2iygWMF0hopLM2Af_m!D5RtWI)4?Mzd$E> zse`t)nHqx*gN2g&><rALq|6L$%*-X_4J;((ZLKYpm94Ct6qKA4!1rtZkN9uNu<HL! zMs`N;{|0|<L&M@WBrN{_{~!L}f??(V8;tCXUjOwWalwcj7b*YU8D{@K%Lr=M*!+13 z)&CN%Kjpt0!|eZOnAy1}GBEsk0hNCNm-qPZ!La@RNk(?Y!2b$=UP0ww!R2%Q=Q2zM zr3Fyi=Py4*{x3g7o`Lbd!v8de2mhBLwSy2R>VewrzKC{^xT2}zgMSW;2WB~d&;9*x z_+N?P!vALs>`W~GjX}}z|NnnKhVu-283VxXQTta2vF~3Y#J>Ok{~IteF<fNyWM=2? zVPN?CA0q$vKSZ8^@!t%FpNtud4h+ojIs&u>8I&v-K{F~0jGz<#U<bW}qE6LRQS{#o zrVBsaK|{3v^BJ}?Ok(U|U}j+3%*@DWpsj8$&OY&<>i^F(ZD%kr{<r#njNus5HwI<~ zd2o6W0kz%0Ted(q2qGIS%&5$G?B4+&MhB*Ee=abC4!Fl!e=snBYSnb`)e_;Lt0m$= z)f!6u!47G@n1W8yP&S3uAAA-@M&|JP17DuWV*s6k3_5g>Ar7>!+Ygp!n$aat^NhG6 z=rlD`<4ynOI6ZK>1<f-||DFHKFzo&R1bnt3q80=#(o01c7z?rqwN_U&Rb*8(Rowfp zjj`(AK1Qy8-=3V990!Vc#{XFIA*hQ7&4(?ZtjEj{&Inp@5f7RgVaA#d!Kbf_gS$q` zCdx`|q7ZT~dOqBUnhzNm|IcEwW=LaZ2j9cQ4vKeXb8&OnT})|OHrCoUHrm!UTGmW= zU@U7b8;IKvFgY+dFefpH!rM#W#tkFn)OJvt0MtZfX7U%55EO#7mq2G(f*S<jo$bot zxK&fLceRq0m63I^29eAH%KAoPe0(apQpyI#qI?2sI^g!30n;Cb^UMbrLHWjr8CpIw zBg*FlrZ@&oQ2&R)`M(9oiU0rqzrhs8u#o8=0~<rx1_lPk|7uJD47ZqmF|adGuZ)E> zw?vh1F>Z1CcfpD27bwMm^6Y;lhV#&TZUl8t$A1%s3UD3J2de{^kn4cO{{<Lg{~uvs zWpD%KGsw|eVhoH-SgQb0P?o`H2}W*(-p>Nc=j@;kk8<oTrwW@b6(C12{`X+AWZ2Hk z!XVG!53<9-MNF89g&B0V5+jqBs0b6Y2P+Gxamd2RzyhiQ7(i76=+tJ0cqTR`1{MZ? zMh00KDG5P-ULGzE26;w#c4!?dtfU5-a{-@!2D(qf*hmbNnjl>cV>UJ~VHH7DT@_A2 z4hac%V>U~DK}CKgT}5sYE^$eABQ^`Bcs@>BX=@f%Sy^jW9(GG<3s!az6Xb5@{~k<^ z4BMIKFmN*{GUzhIfZZO*1uA!085q;K*_l`wn3-5X=MA$kGI6jmrSmXyaB^~l^DuI7 zfR2FU;Ph8k0(F-()s=LWb$Jwd6y;^5CB?-=;2kGks7C}LB@cMm0n%{-9Vh_x66mxB zb7<KFRv|1SBP=W}eTvOOU&ho>4C*&IQv*?PN%mHdtcbKU^Bi$0Nl8gbDe+uuR~cE5 zw`65xWxHXbAU`twk6?;rSiu~_Aj+T(^C2kPLt}u6hlzocg(01Ri=B-toSPAHT~#^* z7Z+PR2QL#F7n{Gh7$bwGhMJ0!f}E_hq?oq2HmF<3!^OeQ%FH0jD9Q)*p|BEiEP=gb z%*Mu!Rn%S5NKaHuh|QSQP+QtqS432Z-H6pd2dgO4D+viHaZ_6f328ACyB=f?DE|fi zS7liL|1JY3g8?}HR6%!vg7@e#cyO{YF@h>1l)GL;gka+d?B=4zrsC|T%A)IQQ)+8d z>SOHeVq)y<K<&Z*OTqc(IRhJmD%e~p&|X<a(Al@mpe4_sN{WqvO$dDH5jb0zDw~Td ziz-;h#8`i*h>x#ekoY&7fq^j<d<PLX13!Z}gFJ&egFb^fgFS;ggExaeLpVb`Lpnn~ zLpeh|Lpwu1!*qtZ42v0-GhGMS2sx>B9vcf2gBd$BGb1MhV=4ouIfp5$2`dvnCsQgf zBex}w1v3{PH&?nKBfqtP6*HeOKVP~iqp+=r4YQE6uu!@zqqL)p1GAL8v{bqTqnN#< z9kaNcn0Trpqr9_%6SJJMyj;2}qq3`t3$v28vQoMxqq@6>8?&00x>~xvE|azgqn3`g zR=SY^6X+ziP!O%77w2v4W$4MOr=#a54Y^ZbsVS=oGZQxlHxox4x`P=x_&GV!2ZduD z)*!i4pHWv^O<PxOfE>&~Fl-|u9ZoJ;GH>3D851XTb~H9rRumRwW+Wy=Mg#`<_;`3Y zI#^m58fa=LDo9EQ3h?l-u`w_#S-xcXvZeDD&s)4`;ez=y=FXTqXZEa_QzuWDK5=?) zcSnC`e`|9?dt-ZTbwzz;eQ9w)d0}~Oc1C_?erj?;dSZHPbVPh)d}we$cwo4XzmLD4 zuZOpXx0k1@vxB>%yREf_y`{aWv4OdvxvsW`zNWsavVyvzx~#N>yrjISuz<LrIOx=A zK3+C%Hf}CX4tB^bTRzYMJVwx9nW!STN2_XTEXuBAY63cZMI1^iLunXa5z1$U(l9=| zsj(=iNu`P=j;;=!53>*59&vDo7-XWcC}{NM-|RVQO!4V+{`t)FmzI{cmX?-2E-fv6 zLt0w;-)d=TX+}Q~D^OZmdWRWPyy@SAAhCHMF*^{e62z(jvE-$trIVn#L8h!rH~nj7 zmR2>7NpFr>TAJCMG&8dTX=!O`0T2PgdLROX-9Q8gcg~$Vcdjvr1;Sw<0)*l6a2;SX z3e3{y&P_KnGXs^4Ync2P0+_`ZgcuA#C5nTZARjj?3oB?C64ctp7%3HE5RwGl+XO1l znB|znMfsT6l}*jS$Ag)A3Y%F-NLZK&a|`Lo$mobLi*ZRwu)DB{OK}<Vi1YD@^BRHr zq?ee28SI(W7};35w}>!+?~)RMbSju2<9^H@47?1I3{GGdnX@r7F|vY=;{+X;!o<qJ zl+M7)$if=Vz{<)J&knkv!k?dyfk9N5Pm*5}bOVKwkP-*4ICva`*$mV`g$)LRdio|H z0Z|dQInY5!$iQH#n4FxLh`c=0A=nsX3cQyNF6$TmS7eC)e;?6iWk+hW#%mcH>Kht? zNpCG9Lw!SIFv-C9f6adZhJgP!7=&PT4<vjcOQacLwGJq#!M!Eq;1vgr>Dn=w8;gQZ z9ugOIMGM{!n4t@HE5c6F<CL9HoN8dRl<B|6e*uQWV1KGIyamM@WF&!CQAQZ-V-8S? zl7?Irha||v2s->#I3U6SNsy7zOB$Ka#OM_XI`Ne!Ai_b6i4}BT3u7pVW@G^Ei)CO0 zpTWr&5aA%h02+s3VyFY1BncWoXJkZC1F{I03HUWfMn*aaFfgd9$jM5GgU&pYgpI#r zgqS!e&OpJa3_fayU3o29ylvu=l4N&b6O-aL=9T8+mgF_Y4Ah;%4o>3YP7cC6LQXO= z4kD=erVBOS{Qu9;%v8wm3Np_V4a(Qk{tGZ<{lCS)$Dj;~4F?H6_>qz<%uKwHVORm! zFf6+<JG=v?ZZ59u#%m|$W^5rZZ(-~vW~b(+<ius5<=~)Yz~!XG0NQ8v-{HRi!~Xw| z8H5?+8MGO^z;@U(F|so7fR6C=V&njw1_i!Vhn<myiHRi~bVVjpJTpkvpOHaJLq$nW zMna6Amz$H7nL(IQm=oGYWH*BJDMdh+r+`O!Ow7a~=ShR_-Czfk;A0QXf-R&aEkRv$ z3n>|MLmQiU@{-cB3K9|urXWIAT2fwCUESQs$U;K{)Pc{Gl9Q7{!k}<k$P~g5&&<!j z4r%#%ZvZ6`Iq=N^dEg`U^H~^~85x;FSs0m_K?B0fjDFIfq{7V93>tH3!IZ`}L@Ug$ zY_4o>%pR{~EL5#zEW~uC!nwkkf$?Ace<{YM|JN9JVdXD)fDJNO02-lShzCu1fO<cm zAyU+74sj(l*wl(K8ym}{lUi=dbLz8~YPuPpd=?*TW@m1j67m24zj`Kb#wKQVW_IrD z3=GVMkZ~MlLr9U!!1(V9Qz4@c(-LCFl^7LG6&ZCv2Zk~g8iVE&ul#Rj)cL=SnVtJ4 z1H)e-h}nOI;AYn|#WOZBJzx-rk3)ldc%VUO<SriQ=2XxqgE)h@vXYRp5^Nlr5j24W zK9v&E50Ya7jnXnU@x;1Yrl+J^+E}t1^Tc{sq@`ql*h~*xY=k6)6lI)k!4xR1GXAS$ zn#|b9>`&fY5;MwN5^5kb`@=#RRPO$p{9l!E+W)%@Yz%tf{GiMX+UN#8_K1ZMOD{tJ z*2`d31obf#|4n9UtF8T8l?du$fX5Aj8E!G%XJBVw+sqESLk_f_1=P27DpQ)+U8XdV zX^MlrkE4S<=p+CJ#{U^iAq-QP?lG{!`y))CE;S=)DiJg?7Yj<TzQS;8g~59;r}S4V zbuVO^?riT3s;}Vf0cc+dTzZ4|2Y|B!+UOo~eI-n&zGCttTz9+&g&c8p2Qx8s2QyOL zA<n|g$_x$-Fathw3$2!9Kv@|yQwFL%nBlbts73)-FrbnFrx6Z#b(2tgu!0&?ppZ0% zoJ41gUVAWBb4g3EyReGmt3D*rs}F|%|NmZP%K87F=@WxGqtCx}48EXo?7wRn_!tB> zGB9rN-C(S}k&$r&A1LcG{=3Ok%Baq?je!~4U8sTrpnG>16-5>Q-DL9nyNPL=Bj^lh zR;D6GJ*J(EY>Ym4QQCF?|NpzoRK&o>w3CsY(dXY*24q?0|ISS1411ZC8Mqll859|2 zKvIB4K!gLA5F;xiFC#Mplb1A@!vx_(dT#(p%QCPsFtdh(Z)1jB#Lmjf9M8eR&dkip z>@V%0&A`OS%E-i8#|}OVl9{EBft7)UHJkyoMU5GB-yf(2$pLObMmk7~i-E>zWTnLv z#T9u(c|-*TAd@+;nn@Tu?gF_ahaJ@91vkvtkwp7Nq@+ZIWMrOlOS2~kn9Gz3OG|?W zX_yX3NJ)u{OG!yM^T-7&bIFG&vw;R>K*KN$%>P4~${AL}{XYxI|00Ym4E&%AltKO% zVPs*3aG?H|<6vZA1XZofY@jJ#CI-fI4o1)%JuA4Dm3GiUcpMrMARVkM;h@zopeu5~ z>OrRsvatFS69Pt{15zPV`=HyEL_sYaQ{+*pS|J%3ArUF5D0XRXEg5qG9cTzJD}#Iw z3I#UhU^yP;5P2?VkncgE04_UYnBo}cGyP)_X3zxr-$9O#lZBaq33UD#69ZE-XfPTy zo+8X3EGEhV?JEi+H?mCan9Yq;ih8_l;<g5a?})P2O3#RqXZj~%WG2NWqAw$(FT%yA zrl~0at`q*NF(JxU7SMg#ptWk|;_T|46P3!kCn}XO1^d`LIQrOw=1;(7YaGKArWYt> zEA$9L$iyv1*$UdHGi717QguI5oVUF*1LJ?O{|XGR7#JAj88X3s<QCv(0?qcbFfw^T zTE?Iqql^ro^K(GQpl5)aA)r<OGiV&136!SgK=y!UP_ZkBbl?<H)>c*$VB?hncYu_Q z+0BfNz||(`uvc@)2)GioO6|7OQ&5)I*U*rXkdhY@)iAI!P%+ol6jRp~u+J3|l@XN| z6_aMu;j+}yHxri=*H8h)6?l!#3?|gDVDLby9zfIPNc9Y}vAH<AGPIsq3a)4VK4tRz z|DWk010QUC2NNTxSI5Y}lF9&TX@O={K^OKhf+rvN82FTglmyv$CBU9yG*yHT?<y;) z|9#4+%4VpcYRqcM>f@54%Cx{yPgzOd)h`GV*Evif3^UN`Ma=3LQ7<wZi?gdML*woq zIPU(<WRm=E!_37X$e;s`J4IGTP>+V6kA<1R9cdmI6g~bbim;lU(L`AZR8~Ms4RtfK zf8X?_g?VH}^eoJ@b(B<@<`}YDv#^@zX?V)<$wSsB9Qm)qVD$eQgF39uB+SUjBm_Dl zA9S-SBQp~t#tH~|6+QU$D`;p0yf_VX?5CM2$OY<VX2wRKBW*$FenM$+op32BDJf|g z32{*tE=2)jNl9^Wad8oeEArgj>?~|79Nb*ITx=X%(kz^E0s<UtEUcV7++3`zETGjl zptiFIQv$;lrdtex3})ak(Pm&~U}O$wVPpaY4(RA;W@g3&21aJa07eFWJ{~Sk4pz|V zv4U*Sw!W|usClPm3Yo$+Gd31oXB_0IW@_tTBI6Qa!ND|3R@Tgv-%?t}4%F7%$`r>K z#Pp9rozd%GFX$d$Mz0$T3@rb?GsQ7-F`F}RGl(-NGw3sff?WeT-;tS>kvW}{k%@(Y zDV&{=m79%=nT3Is1ti485YNHLz{KFMsv;@D%frZ^t*N4~sxL1qp)9E^EXX6yD-J3C zd7zF(zDxjd&c28kas{A>R2eWD+1VQ!I@lXYD=0}yDJmQgk(3k>m6T*$EGj7}Dk3Gt z6lZN@Xl-q1WNoM*Bdw??Eu+99DJ3HzB_$;ZqrrVG8KxM9C(LdP5)8@=dNAMVNb@tZ zu&{y)NOne67ADqoE;i5tG6t4#FoT659@GnC0r^l$66`-cRXurGNo6TzVL@JQc2))n zMhR}H??AICkjO9r4UmX~5)7!YXHzvY2M^kdiioj-=0w$$mDt6^iZ#r{M9o!<9PLe1 z&BR4aHI3|LjsN}8(-6^+mRC_?WRg==RnXQF)@F*)k(buBH#Kn9RFu(mFp)P^G<H=| z)R2|dVA7D4Rd-Q@lqpk~LKt$GJs1RG<$(Y%4=W2J_|8Aj=m^F@lpuqk1Z*HmSkw%B zuMj)9J_6mYDJiHUreq`_AYh~<p~KJYF@;NlU0K{jTG~WhnO%Zw3OHPgn93OXnQLI_ z2ApcZt^w7gER3Mr<3Nd-30C^5fPfOLWCcws!s<hIaG*gh%QHt}>wzO$L{u^X9QC3i zk_TZT%pTB~ZUxbjQc{vo8dPR6{WtnAz;GJ8)<m3vW2>kjCo7YIHaqAJX?Atc?a=0| zNNjmiQ)Lr#MRQYS6H`Vm6H{eVGet8~WfQYRQ&Z3t3g)KDrlyKWY>*v{{{;ShXZ-Mg z4}&9vGuZDIEKE!cTpUbnj0|k)%#4hztc>BHyLwsUdAK=22Pm_Gx@e9Jj&?Q{W-2O5 z!l3X_;pLTu6v}qY#zu0?pd*M8v>0?D9v`!^k{+|N5{zbJWB(_>#3yg2t)L|@B`Yc+ zEi9p_qM|7wA|)XzD<!X^U}7!JV#=<eCN3u_r=zT<BPlE)Dk>o?rK75>BPS&%F0Cxg z{O`Mzv%RLQmX<6swu#cW3PBbCv9+B*w;eP7KlNXV!R-HY22R+T1<--%;4QZdkQG?* z;1V2B8GyzNL92tr#LY}BT!lrRnP}(5OGz>@F#Rw2FU8OeHcJ>*D+qHkfvN>i$B%(A z6cl(2@!$@Gzp$t<yo3f784xoOrYjg*x(bV|HZgY<7KYhj3A2mw|E&K44517f49pCY z;JD%gIkTC8k+B4^=)>HYSy|4!#a!dx3vfNX<i9vr4=>EGpk)Hh=!+jjRN-s*%#Fb( z;6oaC#&YHn>@p&v(o(`2dw7JUWTa$dq(Nr@{x@byW;ny_49+)*nJ>^_Cb)MM3(BvI zz9M2G!blVF=EiKIBA|g-Rq*}drY4}Fi?fnaMg|5(Qj&}_VJxQ0@>b#o4t7T3R&oj! z;s*BiM&jW63RwQ_W=dvsf!Yfy=k>uMp~B9>%na(@hJqOkjIp4>1x5z23&cRK;NX>k zq)-#k`fW^Cu;LK^w;S%LP8jR&dl-v=ljX5^<NyEv#{Y#F&iwzx%+CFnf#J`3(0B>c zjz8-`oi6ZtgPBYj41LUQjP8uJ{~MTcWX?*?f~aB2fvZ`@l)+HLJcrSp!4;>PMNB*l zEzI*6-5Klt*WfT`5mN?30mv>E&Hvpv)Er^TVaNuV!{GUUFG3CD4kY(%Wy)cQ2f2rH z_y4Up)YLL*FjO(SF{CpD{cnP(VRYyI{eLx62iT87pnLGZW^QC++`$Cd4)Fi~|7A=( z3^gD(G6duF>tQAyhCq-TSpxoFfS3&mGZZ%#GHEd6GdnS)GerEaho}MDKObQ~R6S@r z0>b_{rW}TC%+8GN3{n3hA^I@PUdWWekitBH(Vb!0{~m-I7UVFR&6L4V1y-{I=6{em zC~6inWiaG})$D`05u}D0*_`Q&7Z@^`3Ygis=Q1!bEda?g?qFH~OB??lGoE0SV>-pa z&TjH=52%=DVEnh?zdED;|1%7N3>x4ZBMUB(S{Oj%nxGXkpq&)VjQ&c(D)17DRT)%T zgKmidHw45O{he4%e4}(+%l+6KxmM3kniP6dPE~}1M?*U_K*0lK5!3(J|6&Y_|9@u? zXV7Oz1ltq_Iwet<k(q&wk(F7Vk&RWGk)4IrON)_}(Nl<#(L;`r9o%>ZcgC3*m{~zr z=diJ`vxS3t>g=p6pnIG_7q+pn`-3YR6%{2|Zid`=$8HL4u0Xm2qM-3&T;e>EO8g=k zf=Wih8VV9Bd?Ffx%7!B93J_66V-(RqZgz1&D-{l2E)Fq4D`k!{E)EF+5TBb}T)<L= z9kQlwE>i|W1t{Gyp8DU6h<7IB_*%!5!%)HO#OTg=`hN#P4N9DzXUbtn0;@Ume<eZ< zG(AG>n!u#Q&<s{{_J2D<4T@cfOgRi2!D`O`PeiCeF=sV6t%Ayz3;*ZfP_vUMhoJ^+ z&gK7;aj5BL%4A3btGR;gFBH2vm~t4p!D_DlPr_l&LZ%#sVz8QP|EqDRf#e;Ko3A71 z9TdMWVaj1B0Go5;e;p2U;AIKpO`K)PcBTx5bWnN2c<cW>9OkTG%3;U>+jaZ@d>m?K zGvzQ;g4Nu^8HS6Plo%#})!aueqfx>T6h3)iH4l*8jG`uuDTiS#Sk1%#4mjMC!lcA- z4y@+Ue>)s%;Ni@aj2zC0w93Hv-+?KEVI{LOg9Jk>D2ID*&;^ati88V>i7_&;g2(9~ z9A;J~uSkfrGy`ayij|Qmm4TIkffY1y3)!W`%HS{Upv1t;%D~FZP=}<78K#Pjk%5)L zKhi;%kwI9H4{|9QxZlFgE&{I8p}jI=QP4_tWhKbGkhv%uTabaBgW(T<^=5ZvB@sCu z9$BUgQ%fsjxg9(F)wDQR<v~j!{{R0EDZ4>w>m+j7jh41D7>dAY;vCL;auHJwLlLN+ z;0(Z-{?;>PFyw&i$-w^$5OIKFS3Oe>Ljzci7jk|;QB%T{!LSzWp6CDlaF|oXl)<os z*`3jyGyJ~~4mI6OISd`3G{F@9zY~X=TBaO^X<#+c|EqAQDP+oFI0jY|``;V8nt$d0 znHU)U?_+dlZ~gz9i4(f>kAZOq6DO?h`v3bs6JyK&eT@9<tqcrIobdf^U=^TwtpD;1 z4FBgdv$MA|F#I_Hsr&vMfazyo_^-g&_<sQ-KS-YOKTJO(c*XMn{|sFJeHo4aPXUcV z|9|x7JyidDnEro{|NAoVK;-}J#v*_7zc-`${~l&`?#B!a=zDz_82?){MKc^@wqQ_Y zFb3rf2Mu=6op7KLzI4z^cV>ogR`8lyHqdqG{wjhZDk_2^@cK*`KFMhc>sEp;_5$r= z5i=H50uAOE8;MCO%E-toNEzDM8XMUt%E&0lOB>qS8X4L#otIZpl$KI7v^F%bwKSAd zQIe8UGO#w%x3vO|)l6n$VJKlXXOLsC1iMX-n~@PTSIfxcB_qwm<PO~=ln!3?2^xF@ zEu&>*0@b=ouvWY<V(Jx?!=T*+uwy}ET=vRR(sFVlqTFo4oVu2vu@7?#89An{+G<LY zGIH#OEX-Dh1~!iNc4_<ud>;S*|C|3`=6~$}>x}H&*Z%$ca{?M4Cm`{`!1OPhA)9du zqc;it3{_k$`D|FLommscx-E~rpTWd1gQ=ZyE7M!By|NBcpw<#2LpXTZK|H8u#|Q}( zP6=&cq`p3Kzki052xuxmMCyQ)C};#+RElYrv;?S=FDV7385kJ?nVK1PFnwm=W{`J~ zK^j8@SqPf(g^WKjbBbsqPd&84mZ~&M%gRcFFsLh7!c@u_$1KXg4LYx#3q0=#5^e@v z2mu;6=VstmVdfOoW&}?yfd<YQr6nC~gbI0e^n{p7g)J>aI7H0Ng}E6R8E!EZF)n5n zV&G<wbC6~S%@cs`Zh_vG0yRt&Y#3zqj~$aa<6>SzO9?AJ6(w$FAuiB1LmnYhbI`$+ z3``93nM#=ynMJ{S9St4ycpxXygM10wXcY_D^2q3mzQ>UhbaTC#nYl5@CS%B?3m+5v zd{ImBbRjcK(FPDh(9BYdsgzqXK!-!x!dM8-00lrDQxW4uW+4WC&{=rg?95o^6!;nV zMMPLQ#k3j0`zO`Z+1Qm$L4Jx6a!|IiHnA|b7Shq;V-}JRP~+COven@h26>H<0cN%U z$ZS4N&}Bi4Ud-S-N}3rM7(gK<z#t$Z3N{<$0r2n?cwWz(@uHxv7H@{IgR-@(g`}Ak zDAdd>#1sP5xWr9mY;-_wZ)YlCJkIo&ffsbY0_d1Fl>JQcpx!)aK!%rrS4l{Tl~Y_B zJX;Q56To<!J;cp3kkx|COh?n4o$0TWx0kc7th_cz<5H$b#vbUHsgeVD*CDo@bt)<< zN-Ufb+Kiy(7|<e!9Z?LJG4?nbnc6#;7&@6NOG+szN=qp*oiwqrF*dfbF_u<Pkd{$U z0F6a3<S~^n-e>y3AkLuUpb6@rGcdA%uDoJlU;u9{1rL+3fOq`B*8p%zLVN_BtN`^y zz!MqfjQ82?bVSuvl!S!k*-TjN^hDKFlm&(5*qMGfIf+V%Dk?iVi%N+qf!C@qGPE*P zF>Ynrk8>`QQ%qY}QB<*&(cs?&rv0v9_X_@3Vc5n1x~E>nL6Hrdp9BS1nW57h;UG2f zplJ?&RYfLFF>P_sP9#L3Xa>5GGg4PTf`d;+#MDSuTf{&~sYI8R(Sn85NJqw8hmT*u z6x`qc%k+csJF^uN8$%(O@4*zuu$>9KC;C4q<Us3w4lrpkSTLPpWM@+U&-DKiq@4VJ z2~tk}|NqaEsr-Kfvl|0DW60nApsv{e|Nn3PS7Au~e~5vd?d`vZATb8Uf2K@U|K~HE zVi0180@VSKb-A+O@t`~g(7EyX;HekTd=_&YXfmAHPufA6feEx_kAaz?1w$6H(nW|t zP)S7zba54EQ6MA@g03Yq21OWXO!VI*W>IlTQBkQo%wppDVp2>QViHo4QlerKM$)1T zjQ=c{lK(Gey2~I0pGN>qZh<RHCPvV5KhS1>W=2L9Mt?>I0Y1=RBr6Mp5Tg(qtPu#l zksh2Z*_6T8_?ewEwXv5Mm2nNX;9xTj@?^SeYAT>2CL?1nBMXYVe=C?`{wpwZG4L`# z_oni2gVstgFq9}UvO{)mGlB|t$YhDQsM^03N-_o#5>^#Vr)8AY1$jAnWrS2AX01dw ziy6G`f`Oq#3uYFx2)n77sfn5zXf><YgK{eg2?H5Lrqe;PszNfnoV<eS%AiOB?UVSy zu!Xq@X-)++-vbT{$kruBMy7bs?TSqPj0}9By%3<i&w`ACNMRvnY%Hn_UQ{otY-(cW zrsf%B%*J66;UZ(=V9Q)2D{ChsZOLy6TL1a)50e8U3)3P7UIysCROx^S2MH!dwB!J~ z_>7Smv@aDTg`5<iGLWPIDvFF0VM&3R4ZMn0(MVK8SxJ2>qnd^W<91CAbw;K<J$++i zeZBwx|8HT+V8{ZuW#9atjc7Zf^l#=f<uH_h+Lw$M|5xHrbDAlK!4oug!uTF}3<%M8 z`Tzg_bnsXbs4sr!|8yMYlrrTo^nvYq{680=2BrPo$dtn{8LZ~X|7e676uVY2<uH_k z)ja**f>48EP6AU7!v;{Ffhq8R1VRnM?+lFp!<Z&9tYl_o;DxOzB3KWwLsq^DgJ*L< zgRGzxQ!7~l!@~SnoLKZt42@WrS&bcR&6Jf@Km{b@|1PF%hEisA24My(P`Tis4;mO^ z^kQXUVq#`s0_`7XWMF2@0P&eXcS|rafHw9CGYBgSD+{u*L*`^bE8M_Vf_LnK_jZ_< zn%D_*%8RRN*z@xWEAk35tM74RVb|2x)DRWqWVd5rVE%8$P|a|X=@)|_g9L*-Y`#-U zQbI_8i=7d?XcRP>jD7Y8noosA!IRqTqROxf<VC?}afq9Xf~P^{gTuo@?1Cc0LJch} z4DAff&6$36vd8)O#IaAA!WIvrJNL3WnwvYb{Qk}AWNz;G|Ns9^rVNIKpmfO;`ac;* z+@vvCGt6XK#K6hm=Dk5SAi_Z$ykRyU+=d2~qD--%o9~!>r5(gTb#4oWM5F^Z1NcTL zB_$R%F>Pj00GgT@8;jboh>7Z3{$fg(5HU8fW?=lE&XmqDi|HJ)U7(drd0-nsi?YDC z*fB7H_8WrgrDhBXm|Yx-f?&H$jUjWw$}_LBY3fTTF{NAU7)i?f|Nr;azw1mY%q|T2 z4A%eB{<{i&0<jpL!&rZBGOUM){a^F%I)ueo0TcU|#>5X1V|Wf?G4eB5|6jvYDD;WJ zZ6gEYj{mNZg+@>Y6XOQZ;P*ym#vT8zgJf8s0<4TXm_S=!H?qMP?2J2@3c;1$|NsAd z{@rKX!mPuvoWYJ!>|Z|v1Gq=Yz}ODrGuJRM9AG#ADp7?%cK+)Jnas$zgSiH*pMmS| z<bN$pIm{glpj|h@4B`yZ4Dt-h4C)Np4EhYS!MR`p3n<ltTEC!S3nn&Jrc@3_Hc3ti zW_B(%_Ea85E@@sVW^O(%?o<IrK3PE-W_}?){!}p$CLv*Ap->PlBpfR)$|Ni#?5m(4 zBO@UpA|fEb!=tYUx|CN_LtRZ(ML}6XSxHewUPfL{Rzg}rT1rwxTtr+<R6tljSV$1G zQ9=m3FJC~8T^c;zAq*Yq0BuKLG*uK;G*uL3MW>Agl|dI_2pbD3i?+5Jw6+@jtz)!i zN@leFt&U3nGcqvv*Kc63!@z*)pFwA*LDxTZ0|Nttop7S=-%&<u2nMx9KywD!pnSoi zk3438D6{_m|9_4tham-2_OayrUx6*}{Qv*Imnny#9jxZ(|1=zGAY&>{jP5LsILF5} zfyYZgYJ72y-@wOs7+i3wiDk-Q*aq?!!;1eN2=}0r>E28k497rYDje?r&2Xs6W6EII z16JdSJYRrP?r&$}fs8RStVAATL{kGDhh%U=R)Z4Gpt+(v&{z?JJM!2diaAS|pkr4I z9yrIYAme`X7~L5*A&>hZoAd7(Qyill6Zrh5{S2U!eg5qOw^wH}@i63p!_5n)8<sNV zFcgB_>5V+Ef#R3XOgRjS%##`28GMlIZ)7+82f4G7xsTDEBM0Yr`wpfYhB~lae*Y&S z;t0jAZ%jE1a$q(7$abNqc@9p)p!qY0{|9lH1DYG!0rq>qe+wLHAbxjabY}>}>35L7 zs=(&J=f*&7d=$T*{P&6>?Eeu)cZSgai~qfnfzAsu?)Zl|Kj1P`4nqRioY4PkakytK zc%0ms(VZg-=h*dDrVNHeusLBk)7}B542B@)5=M81@c%n;*aex-a$<Bx%(;R5g%Zv) zm~t3uLFE8L<o_8s%z=-kGeqMYO9zz$;5ihASmd!)WV;v`808t;m`*dgGgyMynzPi> zAnsw5hg1s;j0~IqD>EAZKg__*V7CoA^a1H7@qk8BK&>B!cF@scLYU2xNC(h8LEH@7 zqM&sttl$nmcpSl)RYFn7fL(}>$(B>d+)|WB(9}}&|9^(0|KFGnF<oKgXU}5#&vXhh zUdgnB=@i&Cj10#A6&SxUU14x!$Z?R+1+8MzVPs^HV`O5KXJlq#@e*ZZWb}j_h$hd# zzyMmu$=c-&JM*j?bTk@h2_17gvk!R70s}J>b21i%j6RVLoVq%yYBtKC#Vw4G88pyR zF>yI2(79(yYU*NQ&})=ML2VQ@HFXFw1y8(zIyUN{ThT#1J~76Za{57<cE0NF1{UGQ z^=bSvyu8A!VkRnr%7Xj`VrCASf_zE}T%ugs=~ixGT0Ta`!G<;&&ZY@WD?NlotV}ia zm4wBNy{%%>SQ#0)rFkt?Ik>$!IF#))lyn7HI9S7kCG9NLjZ}n141KI^LUln`GBPOr zS71_PI>jK(Q0ySY23niP$jT(Z$jmCp$imFx1qmf(1||kp1}0X}MlwdwRWVK8Y>cd| z&E5>m%q;N?EG+FTKGF^fa8=9<EX*vR5JOhX>J#a}$H2fK%^;<!A|xmT+Nxk|3fdSU z3K~EH2MBZ|Kpix4!PxSzoAK$tN_#hXWp8B(LlI#c8UJ{B5hYDITPAxy+rN8R?96So zIk>zyIQ=Y?G(Zbf85ux>G!{(C42ldU4u&#pOiYZPphdgj`0Vv&0qxC?Wo2Y!Y-aRf zWRQk5m_eH<6&V#l8{-+l!^YyEqn$u~PH?<{mUDr3=7U?sj79-r4%T<tOzkam{rz$+ z?M>V6SUH6=K1vCWDHnHiRH}@2&a$`9a*nQ4a�gj|olzjY)xy*7(9C$-oV|j}f$g zla+;;3EWO+U}S6s-A~xe;3Ep&VqmOnYA&b_+QTU*{^f|Z^$}}p10KeOJO&0l|KfQV zm>Gf@7??gVNiuLT@G*!nm^m0TFfy>QGP0$DmXWl2GqAEU#er6HGch$Y`G7_S#Y6=8 zx%s&HczGDO7&sLLIeEpj6$On&A*(Bu6$On2&5eyfqvpztP7#wbV$$;dnMb^Dsj#(b zWs<xZ=;<HMB>DHbOT3{5s68J1{~I$ilM;grgEFHyWG^)rXmFC3k(r4Jv@cBwG`9s2 z0i8W4?EsQy;bjDIA|oL>lsOsMLFXH>GlH(X=U|9u<6>f9=!IlH&{;O!%s$X9(CWC9 zf|DQ<6F71q%0V`3Ba}0+v9)@0Gjeb+#B(u%O-I+_V93D9z{tYMn99J;z{14Nl1fky zXj6i`oGc@QqJpfloU)Xpgt(Zfh_E0(7Y7?FgAAh#XyqfLk(ijMD0I0kB=4&$iz<Tx z-ONl}iH%)RO^r#-CB^jLM5f39V}C8p0Q0;)w!Vmni9B`j_MYsFf{b=dN;bKkrqS`j zLcT(RjkRBxB=6@|djxv8go4@-40`{+F>5e^R`j?rzGad;z`)4P;K8U4>KTDr?@W^5 z@{oza|Nl4U6->$uvJ9FG<&e<lVq|1z;ALcC2hTh*GO{y6IMB$EVqj-yh~;2qW@cb$ z^=4xP4J3ie@oq*RX$LtDRwicVR&S7+cm`0Yq9}-T5Mp4^P*YN1kY$in7FJPJ;^dXo zW)uajHvnZNWhFIra9L<7Xe<bsyAedp;V7{&3EL(4=2<mVxaP=<C;6o(M_9T$2S$4b z26+1f`1mtPY8t!NhSblnw=i)|Oks@sx5d*nGLcc?-<P<e;@G&tY|t7-28RCvOhHVi zp#2nA2Pb|`W@ZLPE=E>1CNB<91przI%gVr($^tr_G?syhNez^9m}A))nVGeieHa*o zg#-ooc)>?}2?=tri))LTDl!U#Iu4ACqKu5n%*=}Fii~UjUH$!UGLzZA^NhCt<}-?U z|Cr49#PVP0hh>a@jQ!^3|K$G7vu8ZXxa(i}KP%Ar2h0qK|K~ADFzYiYF=#WGFwAt| z=jCGJWE5uP=8$G&;9~aj-T>OMsSg^hVr0tW0iBh>z?#p%!OO_a#lfA*z{$x7nonVD z@@C-TVu%HmZ_S{(RTrd#sTr(+wS|!SNC!C`9R>y+6CGoHU2RQOWd<b%B}F+|86ibM zK|wxVNo{dcWkJxMZDS*GQ)Ad*0i<RVRW?;pRu*M8hAeGW78HcC_Qu3Ga45+**gM)< zY1pg!yE(9Pm^;M;*?I^0Wdu99L?k6Kok~q*&L|S_ceM}ZVdYSBGxtjt%uY&T{9|op zZT#=jzrS8K7OvpC8J{vAV7$g42pY!+ot^^O-UmJ;D3%$t2-z1juF1~IAjl}l!YiU} z4x8;06=4$<5i?d4y%Qa&Eh(nNDyqTs<Y}n0u8yoSj~J)8q93Rn)A)aqQ3-lRCC64a z7A6KJ18re-b8*m~hG6Z@?&q~PyEDF%d!zN|x7-^o(D)~V#{YSYMhwdt_!+bvG(cw# zGBYxzf+hi(LqS7-v7pW`gD)ckANUjx27X3<RyNp~sNms6Q4wQf(Jd|>9xiot@$q#@ zE{=}QT2awj3``6f|J9*p3p3a_SRzbkV`N|f9Yn~&%E}VTz{0{B3tG9%>MJ0?$N=f_ zBCO-UVjZZXi?H%P10w_6+Hx%|a9N_kxSY|5X#+Dm&veinGNgTnm}6$pU^IZr&w$A@ z!RMesaRt%Oz|WxJpvu4mayw%xcyJsv$O68{n}HcL{Ke0}r>LaJ$|kNYYznG#z~j!~ zazO(W9(67rp3aQRK_LPP8PK{(nBCx61xp7rgz0RIkQ4bZ!-WAFE({RsIIvj9ZmK8> zv(m$*j*$UjD=1L@|A)mjBR|h{#wZ5Y0}PNo_n?6oNSHz5i<zBg4g<sA@1QVa+VS^0 zxYPxuFFytb#t^0r49pDt40;aQpxTbH1(a@?7{WnSHB&q*Bj_kjRu%>ZZcY|{R(=N1 z;aqHNqM+JY5V}MIJWtFh<a7x%e<><2&$Quh0F%8md=8Tdd^a4-9zzE`1_ow^W{71B z%uGz+10TUwF*Es-ZWZGOqz(PFwo8G^cBvy32xvh#0m&)`RDbC@Xo15JX`vr06AS3x z8(iUsJf)9j58N75J4j3q#)8Iz$dlQAP7^?<B8th$fs=y+=vYLMP2l{3obE_Z5BRNO z+<;^iTDVc&E(L1ag<L_P2H^y_RjBbqT3P^woiS3HL$w2L#sB}XJj=+>vYK%b(*{T% zmT?Eu22kmNBEJe#9(u<OD9^Kl?)n3DFq&BynVFc8hsr?{kf0J5ddw=DxHi~%qRN7P zPDhR~ZTNS?>EABU{!?grVdQ67f!8ip1{DWIuw57f@}S-^1FIl-gdAdvpVJYh4Sy#& zf!1e$PTVUmUw0s$-{va=J2PmNJ;P<bD)5=vSD!oY{X6+zHP;6gZBUa8T)Klspcxq$ zSakp0W?<l!_&fRU6s`|olRz?1%(H+g0(4j)1L&+}2<Bz*V4T6=$kfIl$z;P|$867F z$aIInl;I(RBcl$32BQvx9FsbOCX)?=5hD+SCZiLB1|tuH2V)5X7n2QxA(IV5B$Ew; z0h0}bE|U#|D3c9?J(CTCIg<^84pbhb&x4VNK^|lVlMRCfh-Tcxz{A|kV8v9=z`)eS zkjPZQV9RuiA(2UkA(4rlA(80@gDuljhD63-1`S5R|C^Yy84{Uz7!sMg84{U(FeEbb zGT1W3Lg_q)L?%@RV<sI2E~eWIQA`mG49trdc$mBxSeVQh7?^Ar)EGS(0zhtN^aT4; zjd9Qae~gk08cc=^dQ9mIp^Oh0%$d>|%$ZCW%o!sX_`&QfhEPT(20uoo|0kKm!0b@w z<qV-rSqz~}v0(L~Aa#s$8A2KFGZ-^wG6*nbG59n7VPF8QX<-s%5Muntz{q%wL7lON zL54}4;XPvwg96z9EDQ{cybK;pHVn~BHefMpCL0DmkQydN25Tl4hN;XB42F!U3<`{Y z88pCpoES8~VqgCMWn2ReV<W~m1_{PE20^f2@)<&z`WehY@x$<tfsZkcL6xxrtY4k! zC4&+(GlLj2F9Sd0CI$&`xP!tT4Ko-1{|}A}P&^=E#$X0@a9jj4Ff#@-$THnxkb}ho zC@zpOlMRCdh!2hnP<+5JC@x|d5}C>wLc!q<3VSrnoWP(5jtdh=T!7*Ogc+Is|6^og zaAjore~Xdn{}*uh!{PxH7s%L#!3Zkv4~h>M2E_$9uKzJGg8dJ&8{~gvx`M$LY(Fj< zltw}61myor26J$F1-TUzR`_U8dIsskML%UoWXk$~o9QV715*|QCu8vcPoQ+i7|bBb z$n^gWV=#j-Bh&v^;5cAnkOt9ADGVA+EDV02`~gx6&Ld(Bp`f(N#KRB(3NKKeVPs-( zgwmm4nuh^I^D;91{|<^naC-g$vY#Oo&fmbm2xEieGM2#{gI>U3%e;xfj46*H5tIj@ zv>lXo2jxjnzQ9TAFmQqM3_1-;FIf!!;PgWT4a)1_{03fTz`zL4^Vb;E!FeBvW^`i+ zWwK$2Wolqx0Hr}tdIzOBnBQP-Wn9Fd0mhXK8jS4>8VuXPWuXScR|XBn{R|q6+Zi;N z92x#HIWlyC(h?}oF*W}G&usPoKjVe}|Cz1-|7W`R|39<w{~wG||6haDfXg`^hD0V; z1`%+&v0+dHm2n`u!SM+y;}RGcU}YSWHiI%qj_Ec-BB-omvSLsHmvLqc49qGF#-Q?z zS%txrnU6sYoF_r~E1kid@iBuoC{7up7=oBm8T>(I6gbbZF|ablFqnbl8J{qigVZnu zGnj+bfzplK|6fd?GDMkyf$=Vb88{D3X5e9pW$*{9&tx!XywAV|HuEZjIg|STuS`D~ z{F(U}EEuEye+7$!@?k1O4D83J3|ycz$JESV3l3XQc^=Fl3re%hD;OA=_c0_gfz)I% zBr+8+aD)8{%9H5~iSY2+%)kaRi#d#ek;#WajhTTV351zIdX6wKg2U@6v@U>!6{tP| z)dvL(+_10$g*DSIh5!~`hC~)YhD4?<3>?f+42eul42evY400?o42ewj3}T>k!4%G5 z$>hKg%D9msl*yGr7*qx^y<=cxe8r&1)XWeH#)1r?Oim2!Os^P1nQEbRLIDG)P5{>@ zjCUABz-7)=1~X7yz*NBy%9P6B#oWXY%G|{e%Cv()h?$EalqrZIl<^&dEVBzkD3d;e z0N5^28L*Kdl<_?{%#ES-&=*iXXZB)XXD$QRL!3;44545<iWowfL>Lkow=jgl@&h^z z$`>HDj9(Zum|s9J<Lv+c7}hiJfblN|c@WK*&cFl43mD{?7#JLx7#M6AD;Rv4#Th(U zW-=HuykJmgoWY>ZXvUzyXvUz<_?f|jq3ORP<0NpM1ZoE;GIKEaFxfDOGn+CvGI21N zG5=wRXJ%y(1f^A`Yz8A{I|c=2I|e~!I|gNDI|c(LM}}0!FASiWz5|S37<MwoF>o=) zF~~8-F~~5+F-S6gVPF8Yg5Wf$nf8l;fnhngerI6hVPIf5!N34Mp&Z)UVSd4&3BsT- z1Nn<7pMj0ZhJk@Of`J>9X25khD6JVX=rQ^-STGAP*fM1>m^1S*L@_M_EfD<I4Ni9q z3`yWPX=Vszp3Wf2EXp9nw3vaDsfvM<c@{$=(=&!prqy6~urM!VNMr_;uQwUEnHm__ zm~Sv7G6yn*GI=w|F}`Bp0p(X{o&mLA%$ceg7?@ZX7+^HZ5e8cpcLsB2QwCe6$qeQ! zOboWn9Sl}*dz%?-7~e3MGbJ(@Gv8$pVcx?a!VF5wlfmguoGFNblPQ%U5me7H2{DK> zZerkI0=1b$8A6#m7#NvlAbAL!j^{BXGU<ZTQ6eZEF=a9EGKn#8GHqpGXUb;~V*1RG z$TX25lv$r4k?9dbD2oC^B6B=LC^I*MEmISNIjEfgt}AsII2ms<h=9}A9|i_EUCzM5 zq`@G>9LK=PbcI2LX+J{%Q!axSC=W8lf$2n08N?jOAk8$BK@3KN%0h5nf5*Vcw1Xj$ z$$%l0={y4?lQ#o9xO~WE2xa=hkjONRArx#DC{ImgNM!oV5DL-@E^CqMbXXY=ic4@j zK4!3HGGQ=gg3@rid>GWg;o`xd%=n3c4_wB8;v5wJAR5x<G-u`mw>{xBsO$jcUr_l4 z%3m1tE`|V5zGo6*NCcH9pfU%X?_u#%!N9_##vsJx#lQ?MC(;@0KxH;_8-pElGlLm( zCxbGxCW9JNC4(}PB!e3BEd~bWXa;uX?+l5|Q^9pMBtA|va57C`5MlCVFa?$IOeYu^ znY<X-(Zd6cFNDU|BbiUA?W4n>#$>`E4-bDd^`JOoWMZ&^(thAN4_kW!68@Sv<ze}k z0FB<RfaP~WG&o&@+Ky%n4B&W%(U}b93=IDq7#RLufzbc#7#RLJBVjv+vkYPk*BE#} z^*6Z9lg_}&bc=zD2~^LeGlVi#Gej|^Fa$AGFvx@R)prJSP#c?B3#`T%lpa8JH<J#7 z4LIHUFqkp1|Njc^Cs{EtFfU^WWsG5nVhm<bg0%w~nHcz)<o^F+VPlA5`tkoOIIr<B z*s>Ti*fRSvm@};fn;i;juQ91I=ri7D&;_+I7*qfM0K3rv(LQ75V^9T$8>o#T$G`}0 zS9vffGkGwWGk#)FV*JD)!(_!^zy!)auNV{=&oihnc{7AE1~4=-X)`o3u`oD-`aG;W z42dio7!p}*8O)hw84{WK7!sLS7(!V%84{U)F(fkQFoeR=AY(8CBO}xQ8?ZPByMc%{ zAxuAvhL-{8?Qc+<OAKK?+#Zl0J~8kiyA>SP=?vz~s~8fQK;;dr%?zzWV0JO-Fa(0j z8E86Z4E}$Lk?H?J#$X0MMyCHyVRpc1raXpl#<>gvpm<=M%MgO$M|%b}#t#f~;Py+_ z|C=D1IiA6sX+DD$QwW0*JT74FfZ7W)9~TWv&y2MU>`X5iLK#~a_?XWyn1e9bFR(rk z4+9rC-GchKpuX$@1}4TW3_MI-4E#*D8Mv4d7#LuA8`Q1?)wfLl8EnC6HjjaeaV`TF z%q}KFhCr}5D9uCq-HJ@Y3<gj!Q2*N)R5pXluLuTnuvzI0W?*?c26Ir~n(@#7zf4&S zfuQsZ!i-D|T%a~AqXUBqV-*7{W8D95pd$jnb=Pu+KxPOIWy<>h7^EKD4g-}h2@Iez z+=A&UgBjyo27V+Q3hK{*&5U9YV$uh<%OHJxrvHx_AsEy@o5YyOAO_AWSqxlEu?%ud zsSJT2H-h>jjQ<!I7;iB!fcpPTat!LAI)(Am|2K@Q7<d?0F-U>wtI&Rx14AfN1cNS< z9fLWjEeT35pt_iGGq_$i2diDhAjN!u!JPRjgE<QagE`Z81_8#u3<At?V9XD$52G1E z8UHdcF!?crG8O-S1Hzzo83;41_<x6y2RuH&#mK|J#hA@t&iEg6{}}@#sC@)#^MPnE zUdbTGu#!QJQIUazQISD}QI<gxiiH_v8F(2MFld0r96%V%2KAF9p<+%99*j;59t?XK zG(eb<k3kNO6&U0gWf(LVy%-o6Rxp?|nlmUeMlkR&iZTc?E@JS*gEbi6GiZR^$T*Kd z1B|^HG#Eh`WG|?H2Ew4e84rU8!#4&EWX#0JpaI5W3>pj!|GF9OGKhdMlOw|q#s>_F zpmq$H28~nsF&Hr&{Qm;fRs^LDrmp|LnSMj+e5O<eTX0`Uj3JTnG(#BU`~Sb0bQlbn z0{?$w;{3lAtTvXx9Bdxb|C6A$0=NzTjzJdOhXbYi3I<zH`;+M!xX-`>EAv4#IIn`r zm_-acpftq9&%niWl!1defx(!`fq{#Oi@};HgdvP6gh7SzB10Icy}~HW5XKnIV8q10 z5XQKZL6qqRLl{#QLl{#PgEbQugECVbgAh|3gCtWN12gj`1`{TA21~G96@xY7H-<1K zeg+8;X1vHC$`k_5S8B|{3_?s<3>u9085o#OFmQp=Fxaj$3_6TI83Y)2GK4XHV&DR~ z1#Ct)gDI0U10Umj1_mbE|Nj}6GuSgOXW(VL&0x=%3C8M-HyJb-A2HZ7++mPn*!ce} z<0J-q#!v=(CO-yy#&=Nshe3mJ3xgVCCxboX6tF%v#@h^5OtB0cjJXVQjJXV^j1w4C zn2Z<{87DB9gV>Du3@VKI42q0a3^I&%45A=0hRqBXjL{6{ObHC;ptR4}$)Lh$!63>w zhd~XDCoq^Zyk_8HoWx+vIEg`$DS^QhlqMNH7`PZ`F_<$3GB7iCGAJ`%XHa2G`~Q<+ z1%oj-?|{^MF)$#hF@~vOUIZ%J{@(|cRg4k;e=;xs|B)%{|3{|u|92SY{=dr@_5Uv8 z{r|rhGylJ4yvCpeYNIpGV=!m(V$fo~%pd?RzoHmenbN`G3Mx-P?E_GM5<Di!%)?*~ z8rxxHV$cBhT|nbspfYqWIG&6dSNwkrDtka}NKkx%`>~)gClCgWYrbXB2E`#$Cj+EE z2}<`&;4;x4Bn}Qw3kDU&NCtUuc-b?EGCW}50+$;T7*rT1F_<!}U|?f-$Y9EFfk7OM zSNuQ3u$;l1VFiN}qckME!C^V+|66dl&t@<On{}N*8I;!<R{Vbp4R<!iP6iRiW(HHn zK4{n*F-S6kZ~}uQqYDEkV>5#acnkoPXFy}b$TX~OLX5|O`aGaE6LuO}C&KC}oHRQ_ zB6$24)=mJA%P|Ck>RfQ$0p|bz%Jh^$l_`rs943x5UMCA4p9Hrn7+hg(F*wb`kjTiy z;KRi8|2t@04>UG{MBf6H3!u1#(XcT%Tr{}60M%uXwlT&S9lXo|jk|)v4|S~06WZp0 z(E{Kxn)?jK1Zng!J9Iv=V|Wn^4B#{ir7^}VKx6oV;Jy(HC|$$b5uh=Bq;WlX8wfOJ zpUEHqDm%e#bWq<OH0B4&1Nbng?F7P47#Nt|FfcHkXJBBuz`($C<^OXK2DL}9VWwIJ z1`uWzU|?Y8W&oWH3dZ2H0?MB_FtY&z1G6Oq1M_|c2Id_M49q7O7?=+-Ffd>I|D5^s z|L2TR41SDJ4DO6k42+CX3=E7>41$bN3_^@i|F1Dd{XfNcf`NhY5Ca2fu7k;wfq^Ll zinIPdXUhKn96WXh8jC~2%%HJDe+CBTrwk0t4;UDj*D^3LuVY{UkKKXB3UT3m3=GU5 zeaQ?A%su~qgU0;uVp9eNW>*FV=7$Un%y$_Wn72dyx#j<J=4=0dgUUz{hJ`6CycnYx zWI*jMxci~*f!PJpgAX&GXJ7zf783>r7CQz877Ydl7A*z_7L)(aK^SHaE}CT;0|Uzh z1_oAj1_o9&1_o9cDAxb~oK^MzbC^4D(JTuY7+BUbFtA!fu^a;ft0DsftKk3VtTO+f z<8wQ>%?(O}P|SRjfq{{U!5!R20nvdBg-k9CWmw%_{Qo&q!T;~fhW|e@TmS#YV$YDs z<j63G$&q0LQy@bbXbhS$>i=8DsQ>pEqyFCpr=h6-*TM4&pgD%^|DQAN`~RHDkzo={ z4@R1ZW$*`$1;fQbeL)aD{{K1C`TswdHZw3VIWkm3@lmW{6!ZTBv+n=r%)$R(Fzf&S z$dbXJ#^lKGo)Ns$>;G#8hX0cp82-OuVEC`iWW%7rq|VR?YV$$GKsROeFfjaw;1diC zOdbsCjG*~2P@4}X&hWpR0fBoM;~0b);}}H1^JJhl1gO0LY7c<go%sxkOg0QEOg0S0 zpt(s<*~?_Zz{Tvy5X>}>0W`<S&t$_O%zTPLg2{$~2P6mX2ZH)MstnwqzB-c)XsqzR z7-((|boM9XRt7m{I|ec4HU<e$o019C)@EYhV&eJ#mnoKk3smNU>Sl1i0W`)28q4ir zNCfvYVC5R9|HJ~$H=r>?ZpJ?hTuh=2iHsK*LYb~Im@@`32r!y5XfUQSXfS3nXfQ@G zXfQrwa06q|oGuJ+W6)p(VbFXAXx?@|gApSyLm&t<F#IoOVECWQ!0@kzf#Lse1_sET z%uM*oNznX4)c^O4s2G&4-aymWTX_0_=3R6?W7Pk5Q2d-R>i-LLd8UgDN#OeK7(+DU z1O^ji%)s!!mVx1aI0FOdZs-4g3=IDxpzIu|cs5iFL}xQFFz7+C2?GPzEIq~v3~<c6 ziGhJxlYyOCjUkcQh#{1@he3?F06dQi9usB$$iT>K#K6wt%#g^O%@E4;k|7a1_J0#R zZxG7l$PmV4!yv-+pCOUCo*|LxC_@xeJp&`tT?SjG7zQrJDh4;k!wiN@4;d1fofx>7 z{22^E^Eym<49eiLqLYDvC4_;2xt4)}xe-Ex`T<PY47}hr1BlK9&wYdDZW)+YFxav> zgZm-^OzRj}nL`+OL2Ur$eGIltUJSZSEew`SaSRO1vl#f9q8K>9IGjP3Ns~c`@fQOt zQy7B@GbaNN<8y`>reFq3Fy>*9WR_=$0gDwdn1kKQ0vbd9|DWkH10z!!12fZC24<!l z24*H@24?0U23{r~1~sM!47N;(|9>%MgZuy7jEeu4GPV8x%+$aT2O75qmuEVVIehS# z259c<2SXy`MFuNICeVEP|C8V`t$7Tlp!O%zeg;KQ-=A3k+&%@(y-S1p|11nFjBa4e z3#u2u?a}!RA|N?XKN-wt`hODKpJZYP1-DUG{67SdX9!?)WpHDh$e_)X$q>q{!63k- z%b>?3%plC<#~{o&pTVDTDT4-cCxagIdImk_g$#PkA_xr5zo0R3(EOMf11Do7$lVP5 zOeG8qOp6#ynZGiC)(tR$?$u&WW8ehm9nhT3Ed~W9CkA!K?+gsg91Ofn=?olT%)t=K z_@6<L@z(zjOx_Hp%n}UdjN2GOSppbBnH3m98NV@vGJRqQWje?pz{JPk$P~_C$~d1P zl*x<106eC#iXjxlXMDw=z&P>$Po^^P+6B<ob!H|h24<#A24=?j|Nk-GV_*i&`GMvR zm|ii2F$FM~GO_;u1}b+zV^fSw49cK-gpr9s8azL~fq|cS69h9wfzu8@(?W(&W)B8q zCIJQpqVewk|Cm6Sm%)pPi9ru5c4P2ja%13Og3^rp8N86N2ND}3?gHm8Ven!KV9>|F z;S63(;S8)y;S64k$_%Oy{Qozj^8eS2$_&g<{!=DCklg>jQ2s53*Z+5eFyk)<FEHND z;Khi6|9@tBz~IG{j{{dQ7%&lw-!K?3zGm<OVUQlie+*tI_$Y%WBNogQ&fv;;fPotw zGlej?5{nssGk^}i5(Lk|f#%_$nDHY6BO|DtfsXGp$TA{faR1ko!IfE$!H9{SL7XX; z!5Gv>0gc(S#53?S-TD8TwVHvAX)6O8(@6$KCPxM(Fji*JWo&2AVY<f<#mvcI3oaL? z{C~kbgMpdZn<0@!l);wy3_~JQHv<FHLk4~@docqq(^Cdf<_QdJ%<C8!SwbLlyCD6n z77Vsbn;F=clo^a!CNik87%+G<2QjcQJ!ar$Qexm{y2g+IqM5@OxS6&xB(iWbB!bFI z&^QcJ(f_L~Jq*H3!QlP`JCh!RDQIq&@dSf8QxbzYW843&pt)J5%Kw)^b9+n?42Fz1 z7?i>IK7%f}U7F7jz<8BGiMffvifJJOGjlQn53?adD6<QLIkOK#D3dU_EzQns#}L9K z%fQG~!63x+ib0s^Hv>EK9PoILIa4`<Df1TwbFkg_7_^yhGbl3eVenwO&LG6}kU^C3 z1%oJ4DMKij{>&f>F1J8)#-OqW)Si!FFk>!c&}MRCSj~8Zfrqh)!JKh7Ln2cRgB*Cy zDvco#JPzB=5XvOLAO^0lKx=LmFxWEPV_;;`XHZ}cWRPI;V&G;{VGv~e#~{w^#=yj) z^#2dj^Z$RC9T~WpIT;d}GyeYp$2F)uTESoh7UN<_Wa@{+2h%BrM5ZzZHKtn(Doh#- ziA<n52~fW`nn8xy;{P9(=Kp_~E;4X2asGeD^nk&T=?a4(I4?Ofa58>o;A9MEP+$!I zpU))Ez{<?YV91okAjy=@Ai;PJ+-{O!a{0d+G>!%;r<ffX%ox2H_?i3}w87(~{tPxu zsSM1_%?x^spmA_B24-e{2609|1}>%~22;kR|Nk>qF)%Q8GRQN}Vh9C=AqX>`X3zm) zCT9j+(ApK|0}Re!yqdw3c{PJ6Q$9lglM+KXc%4W9Lnz}T1_q`n3=E9h8AO>X7`PeJ z7=)QJ83LFx8CaNSF$6HrVhCYc#vlw{3*r9%E0g~JS4>3=LQF#c>zRuF*E0$IuLP?H zwVNg}n1jZoK=l-STnaRXWzL`o9uui!Py*YR&Y;XVk-?l%=>LC)Zw$<gI~jPG92xF` z=UH|#NHS?NsG+a7WBkv+!Q{(e1zIP@<jr8l*v}x&q{N`ZB*q}iWWgZ8q|ac@WY1v1 z#Kj;4UYBRjpbw^%8I+im89YIIVwjW})R~kSSecX=449M|K>K7An3Ne*nUoonplxVX z_<A$M{5+^#4Vj|{twV#fwF#?R&7jJh!XV5n$)L*Y#UQ~P%^(PBA2BmBs4|-|$T1r* zs4|N(sIq{{Y$DBMiDTers%J1`s%MB`bYbvkbYYNS>}L>REMpL0N(7f#;*6UaY#4Vk zOk|c}P-mLT;KO9iV9NM~!IbG8Lko)#13%L$1`lRa1`}pm22&;*23gRW1ExL(Q)V*; z6VMtT@cKtnh7`s<4Dw8|4C0Jm7^)e+FxWwH1K2EehGn2NlZ;;&_Ar}(&0YpFhdG>q zhiN$j4|p9V4}%Be7Y1c0wqbT<FaoJz>Su^!+|8iO@RmV`@e4x*6t_Ul2iXI&V-u4N zLmJ4P%r6-HnOGT2nXJKcL7@2{BPKTn6($A-C$O7&7<?G7GH5gMFnEF7#U#Pt!El$s z6zsM{264s$1{Vf~|0@_78Jro@7<`zHGFUNuWH4k>W^iVD$4~__gW(Z_I>RFdSw>%m z07hR1NjMD}ul>Uy$^3%hGV=?DD{ysA4E*4*a$?ZnmSE6eZ(z`1v}4d<-0}Yz!;AmV zm_-=WnWFwbV_d~x!)U=E!Dz`K&B)GR!^qAc#&DUzlyNqLDZ^z3Glu^R@(lkOWEp-k z$TR$85N9l8;AJdikYIepAj;&#P|gTyhebfgLC|OhGyone$z>2_)?%<`a%13PmS+fM zy2c>Jq{JY|%*(*X1Zw;KXOLq`WKd<g!@$HO#Gu4j!obdWih+qSh(Q^QD;PMybP$6w z8wZ0fjLpQuAjy=&AjNc<!4=E~jkBy^&}2HrpujYpL4i4zL4)}*gE^Beg92+ZLn3n) zXl{$aj}f$fBZz^WNs>W|sh>fIDTg7EX+1+SQwU^D60;VA1q=KCPs|z&g5Y+&3xf{B zxBnBE<QV*rF=IW02$LKGACnw|IFlR$H<KKL6bLicGbl01F{m-gfoTmWTaB@vL5N8X zj6v!_Y+(?e5w!jZqE{KDpGl5Ej0rS%1u-9_7Gwv=Y?vMB?f{tuQU{{JW<t#cxdVhj zZUJGiTcGwK+XXUPow1%l6=W}y9D^Q{9GDH_t1{L@`~`IzNG%MbyF(rt79d)NNsa+T z%OjZ!HV<mH5;UAZ?f|(Fjv4D2)S+r%G*};FJp;&0dnP#)8YG794v>0xCOHNa%vjH0 z3^f-d566u44AM+;m>BAAm^zUAz--2P23;mO1}!wKjhr^XY!8NsOz{kwjL{6j(0>0} z28Msa3=IF4Gcf#bVqo|m3GF|pGBEs~!ocuP6xy#gU|{%vgMs0H2Lr?3UknWYQ=oVw z1H=C<3=IE4^fm^D|8t;t1*j}xU;y{cXEHGSKh41Ke>xKGV_^6XI!um%f#Kgms9UBm zF#Mm#!0>+^)GkoJ-Wl4D2le$~c6vbFq`<)N-w<kt0RzLo84L{n^BEZaTS4uE=?9rH zi-7@jK<9suKN6tkt1&Qu`5g=l{}(eb{0Er}!l1E)Kn8~YOBonI_a*;d!@%(W64bvS zw}SW}3{rcEfq|i!f#Lr&28RC*3=IDlLdH)(V<`WwFff2|Jp;qPItGS+lNlKPgY3*; zU;vxx!NBnMDg(p6o8Vml4FB#jF#HF(HI#wjUks93F^GTvK84W#K;d}=;@*E-85sV3 zXJGg*1BtKyMGOr8jTjjI2{17HKgGcCzl4F|KgjP(7#RK=Gcf$y4Wa*o%vi?2@P82$ zgUs6s9ajN~A7)_q4>}<(4&tZ(v!P)$oq^%sV+MwQ8yFb=$1*Vdp9_tz^9&6CConMl zPh?>DznX#J|4!)G8z^i+VFuC<as$Zh?a;IV5(C)}l23z%FGvg;j{iaGLGtSv82;Bo z{Q~kIXj~68{!<7k+W(a!k6SS?FmOTLc$0zQzcpkm@!xy~hJV>iehf1hnHU10hb7)( za%Gs$<i}74#=Z>gOr{J=85kJyn5-FE8ICasg2ogf;S5SU|2!EO{@-L^_-D$%@XvyQ z;ok}dhJPy|^8fxo^TB**+5@HaQU-?qjSLL`S1~aB2c@|%28RD#3=IFx7#RL{GBErH z`8l0|;qNU5hJQW`41YoC1LWUx3=IE!q4BZ_8vdZL_GV!CpU1%P9~6Ed42nZg7|mv2 z`1g!~0UW1G85sV5W?%rv*A51T|KAuG{y%46_z#LlkQ^v{Pckt4zs$h!e=P&Ue^8ts zfW|E-|A6E-F}5)<Fn(d!%=Dij3Dm~|_u*0)v>BBd4473Jf|<=2f|;Wk^qB84_%r2z z*E}XNzW~qYL&hLM<B+)UA_hOa5E7{&3=9m&cnt#s!yg6)#w834Oluezm_Zlu{9s^U zHDF+1tzckaJ;1=gX28I}*1*8Pc7lNcbYeQY0|Ntl1p@>78wLgr8wLgr&}N|;1_sU_ z3=CWg7#O${7#O(MFfj16Ffj0XFfj0LVPN1>VPN13U|`@|!N9<Gg@J*80t17<69xvs z1O^5n1_lP99tH-XHw+BIE({F96Brmo3>X+h8W<QvE-)~NnlLbkPGDdVJ;T5t=D@%p zwt#^_T!Mi?d;$Z5gbD+L#0CZi$ruI($r%g`l7AQ&q#_s?q`ojPNc%7_NKav4kbc9! zAfv;;Ad|wtAhU#lLFNksgRB7qgKP@}gIoavgM0=9gZvi;289m{42m-t7?d0s7?eTy z1_Oi20tN=v1q=*oCJYQ}B@7Je77PsPXBZeX92gihB^Veq-!L#}&0t{Ac41)9zQVwu zlfuBDbA*9GH-&*gcLxK5o(%(o-V_D~eF+8z{TK!Y{TB=j1|?8@hJnFw2?K+X4+Dd- z3Il`j90msCKMV|}0t^hM4GausGZ+}m|1dCEI503+v@kGOOkrTKT*JU%`GSGLDu;o= z>Iwscbp!*0jSK^WO#uUgtpWps?G^?G+bawVc0LRYb}JYd>`fRL>?;@;93mJP99<X~ zoPIDcI7=`vINLBVI43YLIJYn`IImz}a6ZGp;QWDs!KHwK!KH(N!DS5tgUba52A3}k z46YIk46Zf|46X?b46ZE<46Z8}7~Cuv7~EnQ7~C2d7~GaHFu0vyU~qfGz~C;xz~Jt~ zz~CXmz~EuQz~B+Xz~Irqz~Hfjfx+Vh1B0gp1A|u#1A|uy1A|u&1B2HR1_rM^3=CdZ z7#O_XFfjPoFfjOpFfjP!FfjPEFfjPcVPNpt!oc8jhJnH72?K-A9|i_r5e5d|D+~<2 zZx|T-SQr@mWEdFyOc)sad>9z~QW!wf1q}Xs7#RGoFfjPPVPFVgVPFW5VPFU_VPFVk zVPFW9VPFV!U|<N0U|<NWVPFWH!oU!?hJhjQ2m?dl3kC+zZDT<y3=Baw3=BaD3=BaP z3=BbY7#M=KFfat&U|<OPzyLb(f+56&fgvP<fgz-TfgxlH14GCf28NIe3=APJ7#Kns z7#PAt7#PAV7#P9=7#PAz7#PBO7#PAfFffFjU|<M)!@v;E!oUzN!@v-3!oUz7!N3q+ z!@v;1z`zjkf`K8Dhk+qdg@GZ`gMlG3fq@~ig@GY*4g*8v76yjMGYkxo9~c;-I2ahB z6c`wyTo@RlVi*{rN*EZTdKeg@elRdZ%P=rRJ1{UrM=&r%7cekHPhnt)Uc<l;eSv`? z`U?X?Ob7!*%n=5Lm=_G-vv6W17#Ly=7#Lzh7#L!67#Lz(7#QL-7#QNdFfhbRFfha$ zFfhc2FfhdDFfhbVU|@(}!N8F4gn=RP4g*6H0|P^n1Or2o0Ruyl2LnS=4g*6{3j;&a z3I>Lx0}KpFPZ$`I{xC2ki!d-G>o71R2QV-sXD~1%H!v_H&tPCk-owC<e1(A_#e{(& z<p~2rDhC5YssaN;stW@{Y77HIY6Am9>I?>k)IAIgsaF^nQhzWoqzN!Eq}^d)Nc+OT zkS@W%kZ!=hkRHOoke<W9kUoKdA$<!2L;4v8hV%~%3>h2@3>i8M3>hvA3>haF7&03e z7_w>@7;+>S7;<bF7;-`w7;-8Y7;+{sFyyRYV8}VZz>urMz>qtGfg$$}14Etz14G^v z28MhI28R3&28IF_28MzO3=9Qt7#IrgFfbG`FfbI!FfbH3FfbIQFfbH#FfbIYVPGh_ z!oX1UgMpz~fPtY{fq|jefPta7hk>C)hJm3(hk>EQhJm5Phk>Ew2?ImP7Y2q>76yjW z8U}{a9tMWeISdSC77Pq!9t;d+YZw^H_AoG%2QV;{ConLS7cekXgfK8vq%bg4vM?}I z9$;Xoe8Rv`#lgT(rNF>YWx>Eu6~MqymBGMJ)xf||UBSRm6TrYwbAo}PwugbC&VzxW z?hXS({Q?Gt1`7s;hB*uj4Qm(}8c#4VG~QrfX!2lSXck~#XjWigXc1vxXj#L+(CWd! z(0YP_q0NPXp=}ETLwgDXLx&6lL&pXNhRzrUhRzZOhRz-ahR!7n44r!z7&@;oFm(Q4 zVCcHRz|i%FfuVZ|14H)~28Qk<3=G{b7#O;LFfjC9VPNP>U|{Gw!@$t@fq|i4gn^+y zg@K{Jgn^;|4Ff~}9|ndAJPZsICNMBeSirzAQG|hE;u!{pNhS;olOh-xCaqv#m>j~u zFgb;RVR8ur!{inQhRIVH7$z@aV3@pxfno9y28JmC3=C5e7#OA$FfdFx!N4%pgn?md z3j@Q{Hw+BZQWzMfy<uRO9>KscgMooz#t#ODnKcXyGkX{qX1Oph%(}zCFk6O!VfG9L zhS@6^80IK2FwA+tz%bW^fnjb81H;@k3=H!E7#QXqU|^Up!oV<Jg@Ivy4g<sd8U}{> zJq!%<&oD5|zr(<=pn!p4K?4KBf-4LR3mq637S3Q`Sj51<u&9B7VKEB>!{Q7Eh9v?F z3`;IBFf4UpU|1T%z_2WVfniw%1H*C!28QJZ3=GR17#NmEFfc67U|?9Wgn?nD0RzKI z2L^_f5ey6~3m6zy9$;Wt#lyg`s)B)G)f@(fRa+PsR^4D=SoMK{VYLVY!)hG{hSdQK z468F37*;P}U|4;FfnoIv28J~j3=C^(7#P+ZU|?ADfPrDH3IoI12@DMD7#JAVDKIds z>tSG6FTudDK8Ar|eGLP{hCd7p8+8~MHr6mOY+S*>u<;55!^SrZ44YIK7&dt@Fl^ev zz_7W2fnm!F28OK{7#OzQVPM!khk;>74+Fza0|thj4h#%Ce=soY4q#x|JAr{=e+L7@ zfd>o>2W=P_4z6KfICy}8;gA6X!=W_{42OLf7!J>2U^tRN9zLnSz;N;d1H&l}28L4- z3=F4b7#Pl|Ffg2X!N72qhk@a&3IoGg8wQ56Aq)&>Z!j>No5R3x-iCqU{2K;_3riRn zE{ZTPT(n?dxERC0aIu7e;bIR1!zBX-hD&D{7%oRJFkF7Yz;Km;f#I461H-i`3=G#f z7#OZEU|_gmz`$_h4g<r@76yh}I~W*luV7%f%fi5LFM@&LUIqihy$S|~`w|Qc_ct&w zJV;<*c&Na@@X&>U;b9B|!y_LChDRw343AA17#@FMV0fCq!0_w}1H-c)3=GdD7#N<f zU|@J*!ocvNgMs1I8U}{fe;63v9ARL1+rhx_PJ)5q-3kVV_YMpUA6yt1J}hBi_{hM( z@bLiy!>0}ghR-q#44+ppFnm71!0`D71H%^&28J(N7#O~4Ffe>wz`*cLf`Q@N3<id8 ze;63PConL4Kf}QA!-Rq1#}o#JA0HSPeqLc<_|?I{@OuIS!=F1041c~bF#P3VVECKD z!0>ku1H<1l3=IE3>pwyLO;A6n0lcn&ks*SCk>LmfBcl%kBjXtcMy41BMy59mjLZ=X zjLaDfj4TBVjI1>bjBIll7}?h_FtYDqU}S&5z{viCfsx}110!bv10$CO10%N#10(kp z21cF)21cGE42--w42--h7#R697#R7sFfj64Ffj6aFfj7xFfj7BFfj73U|{4wz`)3V zfq{|#0Ry7|3j?Eo3<IOU2?j=i8w`vBe;61AMHm<bEf^RD0~i<uOBfghdl(pn6c`wV z_AoFCJz!uI`oX{`EW^MkY{I}O9KpaST)@C6+`zynJb{5xcnbrg@EHb1;SUUqA{-2i zB03C=A}$P!A{h*fA`J|TB1;$;MfNZ-iacOo6#2oxDC)z&C_0CMQS<-<qv#C=M$r!p zjABz57{x6Z7{#wJFiLnZFiLD;V3gEhV3f3BV3d5pz$mqcfl>Ml1EWk21EZ`11EcH* z21dCL42<$M42%jo42%kQ7#I~x7#Nip7#Ni*7#NjaFfb~wU|>|<!N90;hk;Q|gMm@a zfq_vif`L)3hJjIS3In6s4hBZG3k-~EUl<tGc^DYg4Hy{JJs23(a~K%aTNoJCH!v`& zUtnNV|H8ni!Nb6)VZgws;laSDk;A~K(Zax}v4Vk7;{XGr#v2AkO&$hDO%(=4O&bPA z%>)KU%?bua%{dH=np+qcHE%F5YJOl~)DmG})Y4&K)Cyo=)XHFB)aqei)LO#8sC9vX zQR@Q(qqYbGqqYtMqqYkJqjn4fqjm`cqjnDiqxJ>{M(q;}jM{G)7<E_}7<Dul7<C*N z7<Ez@7<FnG7<CpfFzW1JVAOfSz^Kc@z^JRiz^LoMz^I$Tz^Gfpz^J=`fl+q{1EcO8 z21ea442*g_42*gz42*g<42*gq42*ge42*gc7#Q`oFfi(!VPMqzz`&@_!N91m!@#KT z!oaAX!N92Bz`&?KgMm?h0|TS}2?j>}Hw=sh0t}1>8VrmEJ`9WoDGZDTH4Kb~JPeG6 zYZw@fCNMA>`!Fz?a4;~MoM2!yy~Dt0c7%b^+=YSBd<_GmIf#9SfzgtOfzb+tWf&N( zbr=|}H!v{T6fiK_GB7aO9${d#+rq$TcZ7k_zJY<!frWw5QG$Wd(Sm`|aS8*Y;}Ql& zryK@Gr!NeQ&Q};1T`CwDU6(L0y74eDy0tJcy7w?JdiXFfdK_S2^!&oW=(UG|(K~{H z(K~~I(Yu0y(Z`2@(dP>TqwgLDM!z!*jQ%kUi~#}+i~$E27y~XaFb1w+U<^uNU<`W0 zz!-dific8`fidI>17qkM2F9=e2F7q72FCCs42%&D42%&042%(97#Jg`Ffc~NFfc|N zFfc}+VPK3&VPK5qVPK3s!oV2E!@wA)!oV1JfPpdY0s~{*9|p#F83x998wSSs5C+Eh z90tbt76!)nISh>PTNoJQ&oD5?e_&ut;9y`(&|zRqaA9Cf$Y5YhXkcJWSi-=Vu!n&$ z;Q<3<!Vd<<L>UIgL=y(a#0Un)!~zD!#3>AniE9`b6E83@Cca=`Ok!YQOp;(=OtN8M zObTIOOjclEOle?XOj*Lfn6ig~G35aRV=4;+W2y`TW2y-QV`>5eV`>8fW9kwH#?(Cw zjHy=`7*pRcFs89EFs5lRFs3;$Fs6NBU`$`Zz?go9fie9F17ijU17n5)17n5@17k)E z17k)517pSv2F8p%42&697#K5tFfe8cFfeACFfeBNFfe8oFfe9zFfeAWVPMQW!oZmM zf`KuMfq^kgg@G~4hJi6Ffq^lrf`Kt>4g+J>76!)b00zeFHw=t90t}2fCJc-@R~Q)c z9xyQG&tYIJs9|6%n8LtVu!MoJ-~<C>!2<@yf*%Zwg#rwWg(eJ)g+2_7g#`?Zg&hox zg=-iX3y&}`7T#fCEd0X2SR}!~SY*J!SoDQ~u|$S}vE&W|W9b(L#<C|2jO9ld7%Pr2 zFjnqhV5|~hV5~a8z*xP9fw3lrfwATa17ocR17jTr17qDB2FAKI42<=A7#JJ=FfcZ@ zFfcY9VPI^&!NAz^gn_ZOfq}8jhk>!}1OsDx4FhBQ90taY6b8nQ76!)74GfH34h)Rl zDh!N0HVlltISh=wEewo(8Vrnm77UDi9~c<>OBfg@tYKiBu!n(hVgdu>Bn}3~Nk14E zCrdCePQJmwIOPTd<J1QXj8i`_Fi!JeV4Tjwz&QO11LKSc2F95#42&~V7#L@<Ffh($ zU|^hmfq`+(6b8mQUl<tYvM?~tOJQJ~FT=n%Ux$Hlz7GTA0uctr1xFYd7ZxxuE(&2_ zT(pOQaj^;m<KiU@jEhe&FfLiaz_>JqfpM7w1LLwQ42;VUFfcBEz`(eofPrzP2?OKG z6AX;2rZ6zB+QPuN>IwtnsxJ(Ts~s2^SKnb^T+_n9xMm6i<Juku#&rq|jO#2I7}uR) zU|gTTz_`AGfpL8Y1LFo02F8sJ42&BC7#KG#U|`&IfPrz-9|p!PJPeFmPB1WTZDC;C zZo|O1vw(qd_W}mSy(|oj`#cyJ_pe}JJm|u}c&LJb@h}eq<KZ0)j7MY`7>_bAFdkE2 zU_9o+z<4Z!f$>-m1LLs`42;LFFfbnb!N7Q2hJo?80|Vpn6b8oQB@B$mTNoIRPhns@ zzJ!7C_#Xzw6Cn(YCoV8Bo_N8)c#?yG@uUU=<H-^R#*<SR7*8%?U_7~nf$`)K2F8<5 z7#L5nFfg8yU|>9@!@zi|hJo?a3I@hgCm0w{y<lKG&B4HUT7!Y{v<Cy@=@tgY(=!+t zPw!!1JpF)y@eB(C;~5PG#xp()jAv#rFrInCz<Abyf${7V2F9~D7#PpVFfg9WU|>Ag z!N7QK1q0)`9Sn@;85kJPdoVDbFJNFiKZAksJV@*g1LOHW42&0K7#J^DFfd-IVPL#) zf`Rd(00ZO200zd3dl(omDKIczs$pQf)Wg7d=>h}eWeo<#%N7ibmpvF5FXu2YUY@|f zczFQ><CO^vj8}FrFkZRCz<A{i1LL&>2FB|m42;(oFfiV5VPL%Rg@N(r3drW8TW1&; zZ%<)hyyL*YcxMj-<J~t5jQ373Fy6btz<BQk1LM6P42<_V7#QzMFfiWNU|_s&!N7Rm zgMsn>69&cy4GfGAZ5S9I`Y<p)OkrSrSi`{hu!n*1;T#6Whie!ZAMRmbe5Ap^_-F|O z<KsIFj88fk7@vwTFg`6{V0`+6f$^CS1LJcZ2FB+F42;h&FfhK*VPJgG!@&6B4+G=N z7zW0dR~Q&y#V|0wYGGh}wT6N56^Q?Zf${YU2F5oG42*9g7#QDNU|@V3!oc|U4g=#m z2?oY@H4KdJmM}2BJHx>E?h6CsdkzN1_iGp!-|t~y{1Cvv_~8!&<Hscoj31vcFn+RN zVEk0U!1$?yf$`HH2FA||7#KevVPO3Hf`Rc14+G<uCk%{VIT#qf>M$^V4PapWTEf8i zbp`|D*F6l3Umq|qeq&)^{HDRc_|1ob@mm1{<F_{qjNb(q7{8k^Fn*6<VEkUg!1#Ru z1LOB242<7jFfjh$VPO1Wz`*z;gn{u#1q0)cISh<H4lpqOc*4N=lY@crrw#+-&j1F- zpCt^8KW8v7{@laB`11h+<1ZEl#$Or?jK6#s7=INoF#ejt!1!wi1LLnd44{QOjK5VF z7=L>(F#gVAVEjFSf${ei2FBkv7#M&5VPO2Dz`*#&g@N%;3IpSx76!&YOBfjc9ARMm z^Mrx%FAD?XUlj(%zb*`ne^VG3|79>R{(r#0#8|+<#593{iTMEo6Uz$*CN={GCiVaZ zCJqS(CQcOwCN2dACaxz8Ox!FCOxzj_Ox#x(n0SvcF!5P1F!AkSVB){Sz$8$?z$6&L zz$CPTfk{M%fk{+{fk~`|fk`}tfk}dafk{$;fl2ZU1Cz7}1Cxvd1CuNd1CyK#1C!hy z1}6Cs1}6C@3`~j@3`|OE7?_klFfgf{VPI0-!@#7rhJi_a1_P7E6$U2F84OHX4Gc`$ z1q@6&4h&2>DGW?H9Slr5YZ#bxE-*0Zd|_bHm0)1fwP9e=O<-WsZDC;2UBSSldxn8Y z_X7iyo(Kbzo&^JwUJL`1UIPP@-Vz2Ty%P*fdT$t*^aU80^i3F;^dlIU^lKQH^cOHN z=^tTW(tp9gWWd9~WMII+WDvr@WKhAtWH5(;$>0D3lfe@PCPNMeCPN(tCc^**Cc_d2 zCc_yFOokg6m<&%aFd05zU@~H1U^3ERU@{6}U@|IUU^1G)z+|+6fyw9u1C!AM1}0+` z1}0+-1}5Vh3{0jL3{0j03{0jO3{0jy3{0j=7??~?Fff@uU|=%+!N6oDz`$gt!N6qZ z!@y)#!N6oTgMrCx4+E3g0|q8@76vAB83rbE2L>kd6b2^q8U`lwDGW^JI~bVE?=Uc# ze_>#<;9+30P+?%Quwh`b2w`Bds9<2Sn8Uziv4w%j;syhg#UBPHOA!VpOC1I#OBV(v z%M1o4%LWD}%NYzzmPZ(vEI%+XS&1+(Sy?bJSp_gKS(Pv_S<PTzvf9AFWOagp$?5?E zlQjzileG*3leGy0leG^6lXU?Dll2q^ChIi}Ox8yjn5<ub4q#$nvQc4Rvaw-cvPocI zvZ-KTvYErcWV3~V$>s(Flg$SPCR-5(CR-f_Cffi8Cff`KCff!ECfgYdOtwcDm~5Xg zFxhc1FxlxaFxdq#Fxh1=FxfRQFxkyuV6xl8z+`uYfywR%1CzY~1CzZC1CxCW1CxCN z1C#v%1}6I*3{3VH7?|w8FfcjrFfci&FfciIFfcjfFfci^Ffci+U|@1Mz`*2igMrE6 z4+E2<0t1ty1p|{~3<Hy62?LYk3<f604Gc_<Cm5I<A22XEu`n<>$uKZEnJ_Rp`7kg! z6)-S4buchFtzlqtI>Nx@^n!uOnSp`HS%rbg*@l71IfQ}9IfsGCxrKqrc@6`U^A-js z=Nk-6&L0?<TsRn*Tof3XTwEBKTw)lQTuK<2TzVLoT$V5}x$I$Ja=F65<no4r$(4nH z$yI}a$<>E}$+dui$#n_?lj{x!Cf7R*Ol}MeOl~R+Ol~#|Ol~0zOl~<0Ol~a<Om1@+ znB2B7FuC1eU~>Dzz~rvNz~t`3z~o-Sz~nxMfysRf1C#q11}66>3{38S7??an7??bC z7??a<7??a_7??a77??bkFfe(XVPNw3!ocJy!@%U}!ocL2!@%S@g@MU)4Fi+s5e6pD zI}A*oUl^FYco>+xR2Z1NY#5llLKv95Dj1l&<}fgM9bsVddc(lvEyBR$ZNtFiox;H6 z-NV4-y@Y|udk+JX_Z0>v?>7ugJ}eAOJ~9kUJ`M~_J}C@LK0ORfK3f==eC{wX`LZxD z`N}Xb`I;~=`T8(0`KB;1`PMKn`A%VA@?FEg<a>mH$@c{Vlb-+slb;0xlV1!2lV1q~ zlV1-5liv~sCcixlOnz4wnEc)_F!{4EF!{?cF!?($F!`r2F!}c|F!^s`VDi7iz!bp3 zz!advz!VU`z!Z?dz!cEHz!Wfpfhk}E15>~W2Bv@q3`_w(7?=VD7?=Vz7?=Vb7?=Vh z7?=VJ7?=V(7?=VVFfaukU|<S-z`zvvhk+?bf`KW>gn=n2fPpC}hk+@mgMle%3j<To z0|usG9tNgh3kIg(6b7c?2@FiZdl;C4UobF*a4;~1XfQB^crY-9WH2y=bTBZ5tYBaY zIl;gb@`8aWRD^*k)PaF1w19yrbO8fX=miF*Fa`#uFarjrumlFCum%REumucEVS5;u z!fr4yg?(XQ3Kw8t3fEy^3in`O3NK+`3SYp$6n+7+c__kwfhi(^fhl4F15?BS2BwG` z3``Lp7?>h?7?>he7?>g*7?>g>7?>hU7?>hwFfc{#VPJ}Uz`zv6!oU<I!@v|(!@v~H z!oU<Q!oU=*!oU>$hk+?ZhJh)@gn=n0gn=n0hk+@khk+?(0|Qgc6$Yl59}G;fG7L<y zCJan*5)4dne;AnJcQ7!;UtnO0f58CWOr9XYz?5LXz?9&@z?6`~z?3k7fhl1N15?5c z2ByS43`|K27?_e{7?_ev7?_fK7?_fmFfb+WVPHzW!oZaLhJh)Cg@GwWhJh)?fq^L{ zg@Gxhhk+?&3j<Ti4F;yv6%0&iJq%1~HyD`GzA!MQ^Dr=_YcMdSJ1{V%ConLjw=giJ zuV7$GKf}P3{(*rhgM)!7BZ7e`V-EvU#uo;r%m4<a%q<K|SrQCPSpf`8Ss4sWSyvdC zvLzUpvSS#SvX?M0<)|<)<$&lV3{1HK3{1HS3`}_j3`}_k7?|>17?|=~7?|>pFfbK} zFfbL&VPGm0VPGn}!N62BgMq1N2Ln?Pi2Z|ssaS%6sn~*nsrUs0Qz;JvQ<(z;Q+WXc zQ-u!$Q{@^4rm7tbOw}d~Ow~IWm}(Umm}-A8Fx5R_V5<MZz|^pUfvIr?15?u)2Bu~g z2Bzi&2Bwx62BtO!2Bx+U2B!8E3{0JK7??WOFfes#Ffer;U|{M_VPNV}VPNWc!obv* z!NAlX!@$&^!@x8_hJk6q6b7b=4h&2aS1>S55@2AO^n`(F(iaA%$zK?lraWO_n!1I7 zY3d&arfDt=Ow*n)Fin?WV4B{*z%=~<1Jeu}2BsMc7?@^UVPKlc!N4>#gMn%02?nN_ zFBq6+NiZ<Y@?c<^mBGL?>jDGQY!wEk*#QhpvpX1==EN{C%{5_Qn%ly_H1`Gr(>xOf zrg;+>nC7iuV48P;foUE{>;nVSd=3Vt`3ek7^DP*d<_9n^&Cg(9n%}^{G=ByI)BFt# zO!H4LFwK9!z%>5{1JeQl2BrlX3``3g7?>7BFfc7BU|?F%!N9a&0Rz*59SlqhE-)}H zc)`H5kb!||p#%fdLIVb-g&qt{3lkWa7FIAYEu6r>v?zsvX;BFS)8ZHgrX>*!OiMi& zn3lOPFfF%WU|Rlwfoa7G2Bwt>3{0yG7?@VwVPINaz`(SIg@I|!7Y3%aYZ#c;*)TAz zTfo4yo`ZpDg8>86#ux^sO%V)Cn*$h_w&XA{ZS7!S+O~v&Y5M^NrX4#Nn0EFsFzu3I zVA?Ihz_j}a1Jm9R2By6S7?}1MFfi@k!N7Fj0|V2+2MkPyJ}@vH_F-T;yn=!0hyerB zku3~NM;#cLj=o@EI_AK@bnFfT)A2V9Oec64m`<!=U^?l;z;yBl1JkJx2BuRF7?@78 zFfg6o!N7DThJoqq3<jpN8yJ|*-C$rkzk-43f(--Hg(nP57uPT_T|C3UbSZ#=>Czbn zrpqY|OqX{sFkKO0V7hXFf$7Q%2BxbF3`|$2Ffd&!VPLv`fPv{o2?Nv35C*232N;-c z#V|14W?^8ueTISQ&H@Iey9NwQcb70Q-HTyhy3fPFbbkW_(}NTSriUsFOb>4`Fg^Ui z!1PFhf$7l|2Byaq3`~#zFfcuFVPJZ)gMsO30t3@C83v|jQy7?@TQD#^f5O1@Vg&=! z%Mb>pmnjTPuSyu0UVAVwz0P1@dfmam^u~pO=`9GqVPJauhk@yx2m{kQ9R{X%E(}cX zVi=g-l`t^9>tSGe_k@Az-4_O?_bd!d??o7xKIAYkeW+nz`dGoh^s$41=~D^=)29gx zOrKUTFn#7>VER0Tf$56|1Jjoy3`}1e7?{2;U|{+-fr06}2m{mi1q@8zk1#NOzrw)u z{R;!rj~oW39|stiemr4d`pLn-^izR>>E{s!re7)yOuzmxF#UeP!1Sksf$6UX1Jl1A z2Bv>k7?}Q7FfcRRVPIxbVPIzNU|?psz`)FA!@$fwfq|KQ0RuBf3<EPK3j;If6$WN5 z3kGJc1q{sG0SwGM4GhdYGZ>h8r!X+{GcYg<XfQAfDljk$`7kgG?O<RQ4q;#xzQVvP zvW9_KbO{5q*a`+_u^$Y~;wu=KC0ZDmB{dkBrA{y~OZzY|%S13R%bGAS%c(Fh%Uxk$ zR?uN!R(Qg|tXRXqtmMMLtdzpQtTcgvS=onyS@{bCvq}jAvuX+hvl<Hnv)UR4X7vjU z%o-I8%$g<)%$i>qn6=h0Fl+5$VAeXrz^wI#fmyqOfmug{fmug~fmz3efmtVpfmx@7 zfmx@Afmvq>1GCN^24<Z*49q%z7?^cM7?^c+7?|~P7?=&_FfbbmFfbcxFfbc>Ffbct zFfbc7Ffbd=U|=@f!N6>Ifq~iZ0|T>>3Inr|3j?#!0S0EH8w||GH4Mxq91P4R3JlC9 z4h+mD5e&>G6%5QK6Bw9H-Y_tm<}fgu_AoG;&S79S{lLI%#=*dBroq5$=E1;hmchVm z*1*7QwuFJ%Y!3so*&POEvo8$H<~9t>=4Tj~%|9?OTL>^PTWByaTR1Q<Tg+f!wp3tX zwsc@%ww%JiY`KPk+42knv*jBGW-As3W-Ap2W-A*8W~&eeW~&kgW~&|sW~(&}%+?$X z%+?wV%+@Uo%+_-ln62+HFk63NV78H9V74(}V73WiV7A%9z-+6-z-&8(f!THq1GDWJ z24>qQ49s>F49s>j7?|w^7?|xf7?|xn7?|xd7?|xF7?|xr;(HjF?H@2OJFH+}b~wSn z?C^qt*(rg6+35lUv$F#Ov-24SW)~j@W|tHOW|tNQW|uh(%&ra$%&rj(%&rv-%&rp{ zm|Zt8FuR^$V0PQV!0h&if!RHVf!V!=f!Tcu1GD=Y24)W)24)Wx24)Wz24;^G24;^M z24;^b49p%o7??e7Ffe;oFfe=0VPN*$!@%q%!ocjchJo4Z2m`a%3kGIy1_owt2?l2G z90q3ZJq*m=R~VSRzc4WS@Gvm@s4y`5G%zsx%wS;l*}=f<a|e7<I<v0}1G8@q1G8@n z1GDcO24>$q49tE!49tE<7?}MX7?=YD7?=YdFfa#2Ffa#uFffNCFffNyFffNaU|<f- zVPFnpVPFpX!oVEf!oVCM!oVD{hJiV90|RrE3j=f10S4yi8V2SV83yK<2Mo+HKNy%} zTNs$*EEt&Mb}%r<-C<yk-^0Khe}#cLA%%fCQHFsz$%TPA=>Y?CiUR|4$^{1IR0{^? zv;qd^v_A~Y=?x6b86phKnK2B^nK=y1SqcoySt}Trvojc&a|{@ma}^kv^CTFU^X4!x z=L;|}=PzMk&VR$eT;RgMTyTVexiEr(x$p%8bFl&gb4d>abIB40=8`Q8%%u(t%%y)A zn9H6pFqfAwFjp`zFjvfBV6NE0z+Cx-fw`)Lfw|g%fw}q!19MFa19QzB2Ig872Ikra z49s;249xWc49xWx7?|r{FfcciFfcbNFfccrU|?>}U|?=Jz`)#Ez`)#khk?1Bhk?0$ z1_N`42m^D+1_tKN9}LW091P4|I~bU|Ll~I5pD-|Y|6pM5kzru&abRHXS-`;DE5X3r ztHHqB`+<SEkAZ=?FNJ}*?*;>N-wOuj{uK<&6OJ%2PnyEOJox|v^VBsA%+n<pm}jUk zFwZn#V4fYrz&y8yfqC8@2Id6;49p9TFfcEAz`(qifq{9k00Z;l9SqD%92l6FEMZ_? zYQw<1OoxGac>@FU@-Ga`D|#51S3F^0Uh##2c_j-2^Qr|5%xmT_Ft5{LU|w&-z`Xtp z1M`L(49puRFfeaQU|`;C!N9zQg@Jj?76#_6a~PPnIWRD9cVS@OeuaT~#})?WojnZ9 zyLuRycfVj@-m`>(dG7=U=6xp^nD;MWU_P*gf%(7@2Ihk^7?=;;VPHP|g@O4<4+Hbj z00!n`GZ>hU+b}Snn8Cn&atQ<TsV5A~ryCfU&un2}KD&c~`P=~p=JPcS%ohq6m@k?z zFkg&dV7@ekf%)<p2Iea*49r&-Ffd<ZVPL+thk^OJ1OxN+4-CvVc^H^)#V|16y28MG zdj|vaod5>rJ0BRB?;c@bzITCv`Q8Tx=KCucnD6gkV196if%#Dl1M}k;2Ij|G7?_{r zFfcz=VPJlGgn{|#6$a*~Ul^F5i7+rfGhtwU7Q(>%tb~F2*%SumXImJUpIu>Ke)fZb z`MC@O^K%CV=I1F4%+EU*n4hm<V19mqf%%0B1M`a+49qXyFfhL?VPJk`z`*=!0|WEx z2nOai5)905QW%)u+AuJ`V_;x@SHZyi?hXU<`veB&4<ZcAAMP+Pf2?6({$#?y{HcL~ z`Ev*Z^A`>V<}Y&?n7^!HVE(d)f%(fB2Ien!7?{7jVPO99hk^Mk4+Ha883yLBIt<KT zZ5Wup#xO8{tzlsPI){Pz>mCN?uXh-jzy4uh{wBk~{LO}e`CAMF^S2rX=5KQtn7{2| zVE%T8f%)4X2IlWF49wqc7?{7uFff0wVPO6~hk^O~9tP&`R~VSTe_>$$A;Q4?!-RqP zM+gJ+j}ivvA5$2Ze{5l3{&9tY`NtOq=ASYQ%s*`yn19AFF#oJ!VE#FWf%)ei2Iil4 z7?^+lVPO6x!@&H@hJpE43<LA8DGbcN-Y_u#c41)tJ%fSy_Xh^%KPC*!e;OE=|6E{T z{_}!?`L7QH^WQZL%>NA-nE&5lU}2cTz`_W^4;WaOk1((>-(g^3X<%SsRbgOZUBSS@ z`h|go?F<78djtaudkF&zdkX^#`ws>d4haSp4jTp*P8J3hP8|jo&JYF`&JG3^t`G(m zt{n_4TsIh4xLz=@a7Qq(2*)t62v1>P5njW<B7B5_Mfd>&i|`)?7Lg1F7LgSUEFymx zSi}?<Sj18oSj1`=Sj46<u!yZ;U=cT9U=hz?V39CkV3CMmV3DX{V3F9tz#`eez#{pA zfkmo<fko;M1B-MG1B>(r1{Rq)3@ox93@oxa3@oxs7+B;g7+B;D7+B;37+B;B7+B;d zFtEsPVPKIz!@#0o!N8)hgn>oj4FiiJ4+D#$3j>Q%4FijE3<Ha*3<Ha*2?LAj2?iE5 z5e61D6$TbH7X}u!6b2Tx6$~tDPZ(I#Wf)l0V;ES}OBh(xdl*<WA{baSbr@JQD;QWb zk1()kzF=U{{K3GY#lgU$rNO|W<-owAmBPTHRl~rdwS|F2>kb2p)*l8IZ4m|*?F9@h zIyww2Iynq1I%^nMbXgc!bY&P=bSoHGbeAx&=$>I<(Gy`{(TibV(Pv>`(ci+rVj#f4 zVxU4gHWXlBF`U7`Vr0O;VswOo#l(Yw#pDPBi|G>v7PA=)EM_|xSj-(5Sj-a`Sj>+w zuvk<uuvmcTCk!l>HViD5D;QWTPcX1pNieY3Ffg##C@`?tlrXT^^f0j4YA~?adN8oq zW-zeWb}+EmZeU=s=U`xQs9|7na$sO_ieO-I=3!uQ$zWh{X<%S+nZUr}8p6Qh=E1<? z&ceXrS;D~LCBwktwS$4hdj<oG_X-9UpDhe5ejyAjem@vk{3{q(0`@Sl1R5}~1U4|R z1YTfZ2~uHT394XV2|B>Q63oHC5*)(75<G{2CHM&gONb5wOGpU=OUMBRmQVo(me3Xk zme4B<EMW=^EMYkeEMW&2Si*T2Si(~nSi<)(utW$jutdZ#utaQNV2Sv{z!Dk2z!JHH zfhF<}151<z14~o|154Ba29{_Z2A1d)2A1dz3@kA$3@kA*3@kBQ7+7L?7+7L`7+7K_ zFtEhlU|@-JVPJ{tVPJ{7!oU(Q!oU(A!N3x~gn=dg1p`Zh4FgL;2LnsO2?mx#76z6? z9|o4h2@EWWHyBuwR2W#2G8kBrHZXuLZDUCeVPHvK!N8LIhk+%<fq^BZgMlUG3Ij{3 z3<FDQ3Ij{(8U~g$83vZL2@EXh91JY!H4H52M;KT#L>O2y5*S!AwlJ_{axk!D#xSsC zE@5EF{KCMJ<-ov_HGzR8>kb1;wgCf6b_oMZ_5lW#91#YVoD2q*oC6Fjxe^R4xiJhZ zxeFLra^Enp<e4zA<kc{+<Q-vP$>(8U$&X-Q$zQ?1QlP-VQc%LcQgDKSrBH%_r7(km zrEm`eOOXHrOHl*^OVJVrmZC2VEX58CEX5NTSc;!8u#{*pu#}WAu#}u&U@4VhU@0wN zU@1Mpz*5G;z)}{#z*07cfu-yT153FM150@Y155b<29^pA29}Bl29}C53@nv03@nv7 z3@nvf7+9)U7+9)&7+9+2FtAj8U|^|sU|^}9z`#=dfPtmPgn^}|gMp=H0|QI#83vZx zHw-Lw3=AxF0t_s5Dhw=j77Q$PJ`5~%2@EWCB@8Te9SkgWa~N3aHZZW%9bsUpXJBBd zcVJ+tpTWS=puoV=u!Di6QGtP_(SU)a(Sd=bF@S-kF@b@lv4Mf5aRCEM;~NH+CJP3Z zrWyv8racTS%_0me%^eIZ%|94eT0$6DT1psLS{^X4wE8fxv@T#^X+6Ne(hA~#U|?xu zU|?xeU|?zMVPI+JVPI+3VPI+ZVPI*`VPI(oiLGH^X+Oij(!s&N(jmjZ(qY5E(h<YJ z(lLjDrDG2ROUEAumd+3cmd*nVEL|cDEL~F=Sh_ASuyi{xuyiLduymI&uynUDuylW5 zVCi9DVChj|VCm^#VCi*WVChp~VCiRJVCj!xVCi4Lz%oUFfn~}R29_xs7+9uyFtAK* zU|^a0g@I*S1_R6VGYl-#Uofyt|G~gABZ7ftrUC=Y%moZAvsf5dW~nf+%t~Njnbp9+ zGMj~gWp)k&%j`W2EVJJ*u*@-FV41Uofn^>K1Is)M29|j_3@r0H7+B^lVPKiRgn?zj z3I>*i5)3R0Js4OP_Asz43SnSbG=qU<F$)9BVh;wE#akFymc%fyEIGr#vg8Q^%hDqZ zEX!6fuq>BhU|GI{fn|jZ1ItPQ29}jE3@j^8FtDur!@#mCgn?z%83vZs6Bt-lZ(v|q zeT9K#^$!M?H8Kn=YaAF@)}%17tm$B2S#yAaWz7=?mbDxVENdMYSk|U6u&nK1U|G9{ zfo1Il29~uS7+BV^FtDu4VPIJw!@#n>fq`ZH5(bv_Cm2}PzhPk6Ai%(~!GwWjLj(iM zh8hNz4GS1pHXLDK+3<paWg`y*%SHnRmW?3{EE_8rST@dKVA*(pfo0<p29`}63@n>; z7+5w1FtBV^U|`wo!oadQgMnpp4+G2Q4Gb)suQ0G|{=vYqMTUW8ivt78mJ|k-Egew2 zhJj_v83vXuZx~p%@-VP$)nQ=S>chaYHHU#^8wUf+wmA$e+x9T9Y&T(G**=GXW%~;T zmK`PxEIV2lSavcnu<VRsVA;8cfn}Ej1Iw-s2A16{3@p1X7+7{MU|`w3fq`ZB5eAms zPZ(Hs|6pL*!^6O`X9)w#UI_-4y(tVVdp9t!>{DQ1*|&g!W#177mVGZ6SoZTUu<SQr zVA&tSz_P!Bfo1<32A2H?7+4OdFt8k0z`%0Qf`R2=3<Jx-6AUbeOc+=W-C$rjEWyBX zB!GeCNC^YWkr@muNA@tV9C^UNa+HOE<){V&%TXT&mZJp>EJvp>upHgNz;g5s1IsZ6 z29{$g3@pby7+8)aFt8kJVPHA7f`R4O83vYP9~fAUi!iVpw_sp79>c(Lyn%t`_!0(| z<0lwcj=y1GIU&Hna>9gx<wOJn%ZVBWmJ<sYSWX;aU^(%Ef#oC*1ItMR29}d^7+6m3 zVPHA+f`R4q4hEJp0Sqi><}k3Fm0@5xw}gS^+!+Rz^9LAMF2pdfTx?-rx%h;E<&p#g z%cT+qmP;QPSS|}Nuv|7^V7c7Gz;cC!f#r${1IrZ`29_&p7+9`KFtA*0VPLuXfq~^( z2m{NtJq#?@H5gc~PhnuW{)d6(MgjxNjRppm8w(g%ZoFY&xyi%8a?^)_k%56{9m6RG z2}TJ9Q3fW484Rl!x<UKTd2<;!7&sUh82A}>F))KJPGn#J-@yW5GcpJ<#6iWG82A_p zploIaGln`Sn}tD%VGESa$}oZ98kEh(pum_0WwSH5Ft$P291L2Fr=V<31`Wn9P&OBX z6O#;-&COuP1hbci!G>uLRGgP-8q*CZn~%YSHIKoWA)ldup^~A9A(J7UA%mfWL4m=D z!GOV#!IVLP!JQ$WA)g_gA%`KAL4m=OA&()ML61R!!I2?{A%{VMAqcLk7|cs$C}v1y zC}JpMNM%T2&|~mp$Y&^F$Y)Ss2xdrR$YUsG2x3TONM|Tz$YDriC}J>T&|@$FLu&?i z27d;B26qN)xGtC;T{K;orh;68Y;G9X6~zph4EYRsU>{+#ClBg6U4~+Ye1=knB8Fs! zR0b=k|IHZ;7%aizV8vj`V8D>dkj7xiV98+2V9a2_V9t=tV8CF_pukYVP{NSLkjPL9 z_Gtz~CPN-L6g3#i7z`Qo7|a<oN$^o711KaD!R8h*Br>Ehq%!1!!z!CWfgztE4QH(Q zg8d2#?@EROXncWmrh{FSjud~GDqR>rF$YQkpwJ3oNM%T5$Ynql1;wWVLlQ$Jg8~Dl zevm6cp`8v6?GmVdJ#cy|VJKj*V$f&MXDA0lJ%)6oRHes|%#hEJ%b?GY&XCGb!l2Ip zixqtwx^vO|i7=s<p@gB7Aq5=kAq=3H0EML+SUo6R2ZO_}grOW9o}d&B3GEz)OmNJD z(kH~9r3`uCkS_wqLk2iBgBd&-d>9lM{K26M3MYigJ}4&WFeosfr$A6j0AU3NQd|b| z3&>ZX+?fPUVG#F0QZ*<?DKIE8I5Gr-V>g&Vi9vzE3C#Co2xb7eBb>pLA%ww$!Ji?N zA%sDJA)LXHA&4P}!I8m_A%ww`!4<66pCO1rfx(%<pTUp81+2pp%m$h3&)^2m@qP@E z3<?b144z;$AhS~$G8sx3K%oN)r&NXth608na7qG&dp-k5G?O8hp@0Dt!XTG}%8p=$ zRB(7gbb?9-V#8H|A&miIDok%NI4+VIG8xjqF`xi0SMtCmOd>c%f!qno4MhyO44~Ks zrBYDnfm{d*zZ3?L9*`?Reo15~0jC~NN>Bi&Q&34(#E=KiLzU2yLV=+aT-L$zB*;Y| z^A#8nsRBK{q34HUhGcNLTfk7lP|Tpm0CHOngC5wA=?wY|ppf@rV1jI%{6B}m2*N@o zdDbz2t^#FdU}j)pU}a!qU}xZ9;AG%p;AY@q;AP-r;AaqE5M&Ty5M~fz5M>Z!5ND8J zkYtczkY<o!kY$i#kY`X}P-IYIP-akJP-ReKP-oC!&}7hJ&}PtK&}GnL&<EEBMhwOb zCJd$wW(?*G77UgQRt(k*HVn25b`16m4h)VAP7KZrE)1>=ZVc`W9t@rgUJTw0J`BDL zehmH$0Sti*K@7nRAq=4mVGQ965e$(GQ4G-xF$}Q`aSZVc2@HvhEDVboS{Pax_A*Rk zc)`%d(8titFqdH^!xBbThAu`nhGvGzjO>gY484q;3>^%I8SXK1G0bCF#qgEk3&S^t zMGR{hPBI*4SjUjWkjyZFA%)>ILn^}whEojZ8O|`AWjM$1k|B-ZGQ$Oiiwx@-(iuK5 zOk}vmaE0M2Lk7cZhPMoz3|S1B4A~613^@#W3=0_Y84AH^xfq=1${5NSUNKZKR54UC zR5R2v)G+K|SjbS%P{+`~(8%zH;T^*+Ms7wPMqWlfMt(*ChQAE|7zG)H7=;-{82&Rd zFp4sYF^V%XGD<K?GD<N@Gs-Z^GRiT^Gb%7DGAc1DGyGuq$*97p%BaSu&Zxnt$*9Gs z&8Wku%c#ew&uGAC$Y{i9%<zlRgwd4IjM1FYg3*%EiqV?UhS8SMj?tdcfzgrCiQy5$ zV@7927e-e`H%50x4@OT$FGg=hA4XqBKSqDX0LDOu4GbF@gBXJuLl{FD!x+OEBN!tY zqZp$Zelz@Gc*5|MF@`agF^(~wF@Z6WF^MsmF@-UeF^w^uF@rIaF^e&qF^4giF^@5y zv4F9VVK-wDV=-e1V=2QkhUbiB49ghH87mko8LJqp8EY788S5BsFg#?q#c-S94#QoB z2MjkE?laaiHZV3aHZe9cwlKCbwlTIdb})7_b}@D{_AvG`_A&M|PGFqKIEisG;}piJ zjMEsWGtOX~$vBH~Hsc(|xs3A|=QA!~T*$bHaWUf(#-)tQ7?(4yU|h+#ig7jL8pgGZ z>loKFZeZNVxQTHy;}*uPjN2HuGt6e(!MKxg7vpZmJ&b!9_c88gJivI6@et!-#v_bJ z8ILg@XFS1plJOMdX~r{*XBp2io@czkc#-iE<7LJxj8_@2F<xi9!FZGL7UONkJB)W3 z?=jwIe8BjS@e$)=#wUzV8J{seXMDl<lJOPeYsNQ>ZyDb)zGwWv_>u7w<7dV%j9(eQ zF@9(K!T6K$7vpcnKa77F|1th&VqjuqVq#)uVqs!sVq;=w;$Y%r;$q@v;$h-t;$z}x z5?~T!5@Hf&5@8Z$5@Ql)l3<c#l46o(l3|i%l4Fu*0^Loo#H7rm!lcTi#-z@q!KBHg z#iY%!iD5I74wEj!HiqpCN0{^&wlHjEILgq(aEPIuVKu`sCVeIYhJ6hCnG6~BFc~p? zXEJ6oVKQYhV=`y5VCZ48WU^wiX0l<jWwK+kXL4Y2WO8D1W^!S2WpZP3XYye3Wb$J2 zX7XY3W%6V4X9{2nWC~&mW(r{nWeQ^oXNq8oWQt;nW{P2oWr|~pXG&m7WJ+R6W=dg7 zWlCd8XUbs8WXfX7X3Am8Wy)j9XDVPSWGZ4RW-4JSWh!GTXR2VTWU6ASW~yPTWvXMU zXKG+-WNKn+W@=$-Wolz;XX;?;Wa?t-X6j+;W$I(<XPUq?k!cdsWTq)hQ<<hQO=p_H zG?Qr-(`=?WOmms$G0kUMz_gHQ5z}I(B}_}1mN6}7TEVoEX%*9IrZr4!nbt9_XWGED zk!cgtW~MDnTbZ^oZD-oSw3BHU({83cOnaI3G3{qMz;ux55Yu6%BTPq`jxil)I>B_3 z=@ipxrZY@una(ktXS%?2k?9iCWu_}kSDCIcU1z$%bd%{8(`}|ZOm~^?G2Lf+!1R#m z5z}L)CrnS7o-sXVdcpLP=@rv!rZ-G)ncgwIXZpbOk?9lDXQnSqUzxr!eP{Z?^poiq z({H9fOn;gFG5u#|U<O@W$;`~c%*xEh%+Acg%*o8f%+1Wh%*)Kj%+D;qEXXXxEX*vz zEXpj#EY2*!EXgdzEX^##EXyp%EYGaKtjMgytjw&!tjes$tj?^#tjVm!tj(;$tjny& ztj}z~Y{+cHY|L!JY|3oLY|d=KY{_iJY|U)LY|CuNY|re#?8xlI?9A-K?8@xM?9S}L z?8)rK?9J@M?91%O?9Uv)9LOBR9LyZT9LgNV9L^lU9LXHT9L*fV9LpTX9M7D<oXDKS zoXniUoXVWWoX(uVoXMQUoXwoWoXecYoX=dqT*zF+T+Cd;T*_R=T+Up<T*+L;T+Lj= zT+3X?T+iIV+{oO-+|1m<+{)a>+|Jy=+{xU<+|As>+{@g@+|N9Lc_Q;9=E=-cn5QyN zW1h}DgLx+NEautFbC~Bc&tsm?ynuNj^CITO%uAS;GB0CZ&b)$oCG#rg)y!*{*D|kT zUeCONc_Z^C=FQAon71--W8TiZgLx<OF6Q0Ldzkk!?_=K2e1Q2N^C9NL%tx4yG9P0; z&U}LTB=afe)68d>&oZB5KF@rC`6BZr=F7}in6ENlW4_LOgZU=&E#}+IcbM-o-($Yd z{DAo(^CRZR%ukq~GCyN}&isP;CG#uh*UWF2-!i{re$V`Y`6Kfu=FiMun7=ZAWB$(k zgZU@(FXrFOf0+L=|6~5o!ob4F!o<SN!otGJ!p6eR!okAH!o|YP!o$ML!pFkTBETZZ zBE%xhBElldBE}-lBEcfbBE=%jBEurfBF7@nqQIiaqQs)iqQaueqQ;`mqQRocqQ#=k zqQj!gqQ|1oV!&d^V#H$1V!~p|V#Z?5V!>j`V#Q+3V#8v~V#i|7;=tm_;>6<2;=<y} z;>P06;=$s{;>F_4;=|(0;>Y6862KD362ubB62cP762=nF62TJ562%hD62lV962}tH zlE9M4lEjkClERY8lE#wGlEIS6lEsqElEaeAlE;$IQovHkQp8fsQo>ToQpQrwQo&Nm zQpHluQo~ZqQpZxy(!kQl(!|ot(!$cp(#F!x(!tWn(#6uv(!<ir(#O)zGJ$0x%OsY` zEK^vfvP@%{&N72#Cd(|A*(`Hd=CaIVna{F-Wg*KVmc=YfSeCLZV_D9!f@LMkDwfqO zYgpE@tYcZvvVmnI%O;l1EL&K%vTS47&a#7LC(ACD-7I@p_Ok3_+0Sx-<si!;mcuMZ zSdOwBV>!-pg5@O3DVEbLXIRd%oMSo9a)IR{%O#e}ELT{rvRq@i&T@n0Cd)0B+bnlj z?y}rtxzF-|<sr)>md7klSe~*xV|mW<g5@R4E0)(RZ&=>4ykmLK@`2?e%O{r4EMHi@ zvV3Ft&hmrhC(AFE-z<Mv{<8dI`OnJ0%E-#Z%FN2b%F4>d%FfEc%E`*b%FW8d%FD{f z%FimmD#$9tD$FXvD#|LxD$XjwD#<FvD$OdxD$6RzD$lCGs>rIus?4gws>-Uys?Msx zs>!Ows?Dmys>`a!s?Tb`YRGEDYRqcFYRYQHYR+oGYRPKFYRziHYRhWJYR~Gx>d5NE z>dflG>dNZI>dxxH>dETG>dorI>dWfK>dzX$8ps;N8q6BP8p;~R8qONQ8p#^P8qFHR z8p|5T8qb=*n#h{On#`KQn#!8Sn$DWRn#r2Qn$4QSn#-EUn$KFmTF6?&TFhF)TFP3+ zTFzR*TFF|)TFqL+TFY9;TF=_R+Q{0(+RWO*+REC-+Roa++R56*+RfU-+RNI<+Rr+H zbt3B|*2%0>Sf{d1W1Y@AgLNkBEY{hqb6DrH&SRa=x`1^d>mt_0tV>vzvMys?&boqi zCF?5I)vRk+*Rrl-UC+9KbtCI0*3GP2ShuonW8KcWgLNnCF4o<wdsz3f?ql80dVuvH z>mk;|tVdXnvL0hS&U%9NB<m^G)2wG$&$6ClJ<oc9^&;yf*2}C{Sg*2PW4+FLgY_os zE!NwtcUbST-ebMb`hfKz>m%03tWQ{<vOZ&d&iaD&CF?8J*Q{??-?F}Aeb4%V^&{&i z*3Yb8SiiD<WBtzhgY_rtFV^3ze^~#r{$u^m#=yqN#>B?V#=^$R#>U3Z#=*wP#>K|X z#>2+T#>d9bCcq}hCd4MpCc-AlCdMYtCc!4jCdDSrCc`GnCdVevrog7iro^VqroyJm zrpBhuropDkrp2bsro*PorpKnwX2531X2fR9X2NF5X2xdDX2E93X2oXBX2WL7X2)jF z=D_C2=EUaA=ECO6=EmmE=E3I4=EdgC=ELU8=EvsG7QhzB7Q`0J7Qz<F7RDCN7Qq(D z7R46L7Q+_H7RMIPmcW+Cmc*9Kmco|Gmd2LOmcf?Emc^FMmcy3ImdBRQR=`%sR>W4! zR>D@wR>oG&R>4-uR>fA$R>M}yR>xM)*1*=t*2LD#*231x*2dP(*1^`v*2UJ%*2C7z z*2mV*Hi2y-+a$KhY*W~#vQ1-~&NhQ>Cfh8w*=%#z=CaLWo6oj@Z6Vttw#95q*p{*_ zV_VL)f^8++Dz?>ZYuMJZtz%oywt;OU+a|WnY+Km2vTbAA&bEVXC)+Nz-E4c<_Ok6` z+s}4@?I7DBw!>^k*p9LtV>`}vg6$;RDYnyWXV}iNont%Cc7g38+a<QkY**N>vRz}l z&US<CCfhBx+iZ8(?y}uuyU+H3?IGJEw#RHw*q*XIV|&i_g6$>SE4J5cZ`j_ly<>aN z_JQpq+b6cqY+u;EvVCLw&h~@tC)+Q!-)w)_{<8gJ`_In6&dAQh&dkoj&dScl&d$!k z&dJWj&dtul&dbin&d)BuF32v#F3c{%F3K*(F3v8&F3B#%F3m2(F3T>*F3+yOuE?&$ zuFS5&uF9^)uFkH(uF0;&uFbB)uFI~+uFr13Zpd!LZp?1NZpv=PZq9DOZpm)NZq07P zZp&`RZqM$(?#S-M?#%AO?#k}Q?#}MP?#b@O?#=GQ?#u4S?#~{;9>^ZV9?TxX9?BlZ z9?l-Y9?2fX9?c%Z9?Krb9?zb@p2(iWp3I)Yp30uap3a`Zp2?oYp3R=ap39!cp3h#u zUdUd=Ud&#?Udmp^Ud~>@Uddj?Ud>*^Udvv`UeDgZ-pJm>-pt;@-pby_-p<~^-pSs@ z-p$^_-pk&{-p@XPeIolL_Q~v1*r&2jW1r4GgMB9ZEcV&#bJ*vy&tsp@zJPrp`y%$m z>`T~}vM*y_&c1?uCHpG&)$D87*Rro;U(ddQeIxrO_RZ{D*tfE8W8cocgMBCaF81B* zd)W7~?_=N3et`WT`yuwj>_^y-vL9nV&VGXZB>O4$)9h#1&$6FmKhJ)F{UZA%_RH*7 z*sro*W53RRgZ(D^E%w{&ci8W;-($be{($`<`y=+p>`&OAvOi;g&i;b^CHpJ(*X(cD z-?G1Bf6xAb{UiG)_Rs8J*uS!WWB<<ngZ(G_FZSQ;f7t)B|6~8p!N9@D!NkGL!NS4H z!N$SP!NI}F!NtMN!NbAJ!N<YRA;2NXA;clfA;KZbA;uxjA;BTZA;lrhA;TfdA;%%l zp}?WYp~Rugp~9icp~j)kp~0cap~a!ip~Ioep~s=mVZdR?VZ>p~VZvd`Va8$3VZmX^ zVZ~w1VZ&j|VaH+5;lSa@;lyyA!<oZ{!<EC0!=1x}!;`~{!<)m0!<WO4!=EF7BakDA zBbXzEBa|bIBb+0GBa$PEBbp<IBbFnMBc3CHBatJCBbg(GBb6hKBb_6IBa<VGBby_K zBbOtOBcG#yqmZMBqnM+Fqm-kJqnx9HqmrYFqne|Jqn4wNqn@LIqmiSDqnV?Hqm`qL zqn)FJqm!eHqno3LqnD$Pqn~2}$3%`v9FsYwa7^Wx#xb2^2FFZ}Ssb%D=5WmAn8z`n zV*$rPjzt`cIhJrN<ygkCoMQ#YN{&?=t2x$itmRn8v7TcC$3~7#9Gf||aBSt+#<87a z2ggp1T^zeP_HgXw*vGM-;{eA&jzb)WIgW4~<v7N1oZ|$?Nsdz-r#a4WoaH#jah~G> z$3>1y9G5w+a9riM#&MnF2FFc~TO7AJ?r_}YxW{py;{nG*jz=7iIi7Gl<#@*NoZ|(@ zOO96@uQ}duyybYu@t)%Y$48D&9G^M9aD3(X#_^rw2ggs2UmU+V{&4)|_{Z^|lYx_w zlZlg=lZBI&lZ}&|lY^6!lZ%s^lZTU+laG_1Q-D*DQ;1WTQ-o8LQ;bubQ-V{HQ;JiX zQ-)KPQ;t)fQ-M>FQ;AcVQ-xENQ;k!dQ-f2JQ;SoZQ-@QRQ;$=h(}2^E(}>fU(}dHM z(~Q%c(}L5I(~8rY(}vTQ(~i@g(}B~G(}~lW(}mNO(~Z-e(}UBK(~Hxa(}&ZS(~r}i zGk`OYGl(;oGlVmgGmJBwGlDacGm0~sGlnykGmbN!Gl4UaGl?^qGlesiGmSHyGlMge zGmA5uGlw&mGmkT$vw*XZvxu{pvxKvhvy8Kxvx2jdvx>8tvxc*lvyQW#vw^dbvx&2r zvxT#jvyHQzvxBpfvx~Evvxl>nvyZc%a{}i?&Pkk;Ij3+=<($SjopT1~OwL)HvpMH* z&gGoPIiGU@=R(d!oQpY^a4zLs#<`qx1?Ni6Rh+9i*Kn@oT*tYda|7o_&P|+~Ik#|b z<=n=(opT50PR?DNyE*r8?&aLaxu5d@=RwXxoQFA&a31A6#(A9c1m{W4Q=F$c&v2gQ zJjZ#S^8)8Z&P$w^Ij?YD<-Epuo%06gP0m}Kw>j@{-sQZ<d7twE=R?j%oR2x5a6aXH z#`&D{1?Nl7SDddo-*CR=e8>5o^8@Ec&QF}5Ilpjz<^0C^o%09hPtISQzd8SK{^k6~ z`Jan{i;;_oi<ygsi<OIwi=B&ui<66si<^swi<gU!i=Rt?OOQ*5OPEW9OO#8DOPouB zOOi{9OPWiDOO{KHOP))COOZ>7OPNcBOO;EFOPx!DOOs2BOPfoFOP5QJOP|Yt%aF^6 z%b3fA%aqHE%bd%C%aY5A%bLrE%a+TI%bv@D%aO~8%bClC%azNG%bm-E%ahBC%bUxG z%a_ZK%bzQNE08OQE0`;UE0imYE1WBWE0QaUE1D~YE0!ycE1oNXE0HUSE14^WE0rsa zE1fHYE0ZgWE1N5aE0-&eE1#=?tB|XRtC*{VtCXvZtDLKXtCFjVtD38ZtCp*dtDdWY ztC6dTtC_2XtCg#btDUQZtCOpXtDCEbtCy>ftDkEE*F>&KT$8z`a82c!#x<R52G>lk zSzNQZ=5WpBn#VPtYXR3nu0>pnxt4G(<yywIoNEQwO0HF0tGU*2t>s$BwVrDO*G8^Q zT${PJaBbz<#<iVm2iH!nU0l1l_Hgax+Q+q@>j2k5u0vdhxsGrh<vPZ7oa+SFNv=~| zr@78>o#i^mb)M@2*F~;NT$j17a9!oP#&w<R2G>olTU@uf?r`1Zy2o{&>jBq8u18#t zxt?%6<$A{Toa+VGORiU3uesiEz2$nx^`7ek*GH~TT%WnVaDC<a#`T@+2iH%oUtGVr z{&4-}`p5O3n}M5=n~9s5n}wT|n~j^Dn}eH^n~R&9n}?g1n~$5HTYy`TTZmhjTZCJb zTZ~(rTY_7XTZ&tnTZUVfTaH_vTY+1VTZvnlTZLPdTa8<tTZ3DZTZ>zpTZdbhTaR0x z+ko4U+lbqk+l1Sc+l<?s+k)GY+lt$o+lJeg+m73w+kxAW+lkwm+lAYe+l||u+k@Ma z+l$+q+lSki+mG9yJAgZoJBT}&JA^xwJB&M=JAylsJBmA+JBB-!JB~Y^JApfqJBd4) zJB2%yJB>S?JA*ruJBvG;JBK@$JC8e`yMVipyNJ7(yM()xyNtV>yMnutyNbJ-yN0`# zyN<h_yMeoryNSD*yM?=zyN$b@yMw!vyNkP<yNA1%yN|n{djj`F?n&H}xu<YX<(|ep zoqGoNOzv6Sv$^MR&*h%SJ)e64_d@PP+>5!Fa4+Rv#=V?-1@}tsRott&*Kn`pUdO$j zdjt1I?oHgAxwmj{<=)1<oqGrOPVQaYySevp@8#ady`TF4_d)JM+=sc3a3AG9#(kXo z1ouhqQ{1Py&v2jRKF58Y`vUhx?n~U4xvy|v<-W#!o%;s&P3~LVx4G|d-{ro?eV_XQ z_e1VS+>g1Ra6jdK#{Hc81@}wtSKP0;-*CU>e#iZu`vdn!?oZsGxxa9K<^IO~o%;v( zPwrpbzq$W#|K<M2{htSPh%^%qGY<<7D-RnFI}ZmBCl417HxCaFFApCNKaT*9Ade7_ zFpmh2D32JAIFAI6B##u2G>;6AERP(IJdXm8B99V}GLH(6DvuhEI*$gACXW`6HjfUE zE{`6MK92#9A&(J{F^>t4DUTVCIgbU8C65)4HIEICEsq_KJ&yyABaai0Gmi_8D~}tG zJC6sCCyy78H;)gGFOMIOKTiNpAWslaFi!|iC{GwqI8OvmBu^AiG*1jqEKeLyJWm2o zB2N-eGEWLmDo+|uI!^{qCQlYmHct*uE>9j$K2HHpAx{xcF;59kDNh+sIZp*oB~KMk zHBSvsEl(X!Jx>EqBTo}gGfxXoD^D9wJ5L8sCr=koH%|{wFHav&KhFf7i9C~dCi6_; znaVSbXFAUeo|!zecxLm=;hD=bk7qv50-l9Di+C3EEa6$ovy5js&kCNEJgazC^Q_@n z%d?JWJ<kT7jXaxpHuG%Z*~+txXFJaho}E0qcy{yb;n~Zxk7qy60iJ_Ahj<S29N{_2 z;uq@U!{i*qUYeI_VBlx~rCm7l%TkMqlk<yGAtFvjP}&$un?h+zcE{Yr<f8mM_CyHH z=9pBJT9(R|2&UK_^V9S5QnT3;AvCvha%NF-X>M9hY6W*Pg3aQbl3&7-oRVL{=8~LP zl%L0z0-;=zi}Djo*j*upv!_C6HdnCeY^h+1%QYpxBr!QTHLrv#70zULg;>d+3ZdCt zAtt7RDQ<U!<=p8AHj6vRA?YdkC14L48bLg6Xk^Uofl$Srfnc+EBqbKHWF#dPv3Ztc z=A@*uWr8VoPl#LDGa)paC)lxUnP7_D6XGiNObE^7>BW?p#qEVKmpco=hPcJp3`(2x zWTzLUrsm}&=A~pNv-u<@mzJcm<$x)u5+^9_%;p33FIx_nV(|faF9#IPeqiNnd0+~n z+5{4-h9+igeqiNnd0>h=FR>uMxTGk*AS0F8H7}hxH7}jrAL1?cd<f0v5B3*ZKA7V5 z&nV4HPb@0U%}FdR;mt?pu?2yxWGezw5SvY*UNbdk3j$loRs^Af!HU?5!4!8eB1pK4 z5p1v-Muv`1+KDX$qPYZ2v4nsks00*2q2QQdD+N>Rp%9m|mqKW^P_Wb4O2HIsXi;Wf zI%_G2<PAl3KW`~Ak3AF;f$XIanmZifF79$9b|ezJ62WGR0(*_E3QTcD!P75S6`aYM zlb@Gf%;gAj3q)BWoXPI!3Kn8dOa;^2{>3?o#TgKGK7tJm8w)6H$y$=1mtV}Al9^hR zTAW!7=5aaZ6l5fVnVgAv`6a12shNp9t_8)JIr({DVGh?4sJv%Bl*Qwpn+Yla!16qy zNQ$}qb5qkH$^|p?OA=A+Vg=j9;*?sF$m*V$o0|xBn6ae^yDP*9mZ;Q{L}u5LMAndu z)RIINkcF(?i3J6TY(9y(Nhyg;zNJilrA!f->`)gl1!OV@W#qF4XQt;SGKVCVvO`_N z9FUR8?3|Iw98jDIvBuGo2V@@1Mf^~OFg{lzJRo>dA<hANk0TZ8X-<%Tz(OLW5P6tZ zuplc~KT8tGbLk+@v8JTvlq9l4&0?tnc?~340`?lnFxG6a*K)vKgE-R3nJKT7sUnj- z9}>dMMH%^Q#URfavVtk*lEhMWsQt_Z8JWz<8JWxl#hI-6pn&HA84Gh3KU5iv&jU3R z>|7qGB$&em)(mEHCZ=U(8X6cF8N*nnhH#b<oQ04zfs2{KS!QsSIh<tyXIa8nW(IH; z+zvCC9fl@w^9<pp7{X04gqvanH^m5UiV@5d10%TmjNs-O!QE#BH`xeovJu>5W4Ou2 zaFdPUCL6=Uz!+|aG29MgxE;oDJB;CW7{l!_f!kpMx5ET(hY8#c6Sy6Sa4~_~VFI_q z1a5~3+zvCitIXg!%-}lA;5y9UI?Um&GKagx9PSo#xLeHOCY!@eHiw&R4ma5xZn6d3 zWDB@|E#P)o!0oVr+hGB>!vb!H1>6n`xE&U7J1pULSi<eFgxg^Wx5E-{hb7z&OSm1D za68NqroiklG=SM*XaJKnG=SM*XaKXr&;VwKp#jVeLj#x{h6XS@3=LrZFf@SMVF<Sa z;bv2qn1Q7QTX=d=Vp%F%IfM!aR{(6~V2U#wmhCyqVJx;th{8%R1<rd021W)Jyrp?5 z(57EXQVwrnX?{s6s6kg$oSMRxo0$h{X%wd>=jWwxrdA~9B<7|h<#6T|mlmWJW#$(_ z%(1XEF=Q)9Ed~|auBAo!U{NzeBWQXwGc<z6kC~ydDY$`UWN2i@nOa<unVVRWn!=f% zmztWHo>7v)Q<71X3S}2_r)8GG*gVClWvO`(Ma8_yl|`93Iho1enp*%|>nG>u<|aZK zh1^JNK_qq&s0sr&aE%PiO+aO?k%2k531nnoZVu&xD@-E;0|N-(zz|A9oNZtLZV($8 z7(n$KK=m7d8#G1+22gVhVCGmt^@AHLMg|7phMJqJn;S^n&CSgjO1pq)14B2ky#_{3 zU~vOu7qI;X#x7v{4UApD_87VvyMojkx*CJcF?5Bv*U%N>UIQaHV^;r+{GvS8d@vab zCQCsiOGbWvHb}F92}F~Di2=lN6H|!gCZ<rn8I*4ZafFE(#1STD;6N}iF#`vJfr%M7 z5DZMrz>YI8F#`vJfr%M75DZMrz=2?3Vg?Qb0~0fFAQ+gKK|E<<2D1<BDFYKTu%`@6 z%%S$1L+v+*+HVfE9}<ZMCXh%pFfoVP4~a|z6LYBj=1}|1q4t|Y?Kg+oZw|HJ9BRKg z)P4)7{T5LBEsP-HW&t(V0&1=W)LaXwxfW1!EuiLFK+Uy)nrjI)#}eufOK3P+Lc`G# z>JLk3I9fvOvxM4b3AN7>YM&+4K1-;5mQedFq4q)hc_xlfe>g(zcZAyS2({l4YQH1Y zen+VNj!^p@q4qmM?RSLQ?+CTu5o*69)P6^({Z7zubb{Is?OmEULG5>f+V2Fl-wA5J z6V!eusQpe*`<<ZnJ3;M-W)>4CsQpe*`<<ZnJ45YvhT888^}jRJerKrt&QSZEq4qmN z?RSRS?+mry8EU^X)P85E|DB=sJ45YvhT87}wI7<9O`w_C#06@<3)FrWsQr*kZeZd9 zwciD5zYElU7pVO%Q2Sk=_PapscY)gP0=3^2YQHPg|E^H~yF%@Eh1%~5wci!$e^;pe zu2B13q4v8%?RSOR?+Ufw6>7gL)P7f}{m??q#0_e{8`OR`sQqqG``w`SyFu-DgWB%~ zwcibDzZ=wkH>mxPLe#*-4Qjs|)P6`IYhVg3=S-o6qp1PJep5(cZeR*2%neK-g}H$# zq%b!yg%sunrjWwiz|;U@zo`Mlep5(cZeVHv@xLjw95pq7*l%h8@xQ4dB>YVcA^tZt zgxYTi_P?PkB!3#ZLh`4fD<pp!x<c}&p(`YR8oEOAr=cq(e;T?%@~5FIB!3#ZLh`4f zD<pp!x<c}&p(`YR8oEOAr=cq(e;T?%@~5FIB!3#ZLh`4fD<pp!x<c}&p(`YR8oEOA zr=cq(e;T?%@~5FIB!3#ZLh`4fD<pp!x<c}&p(`YR8oEOAr=cq(e;T?%@~5FIB!3#Z zLh`4fD<pp!x<c}&p(`YR8oEOAr=cq(e;T?%@~5FIB!3#ZLh`4ft1~!$3|%4l)6f-? zKMh?W`P0x9l0OYyA^FqL6_P&<T_O3?&=rzD4P7Dm)6f-?KMh?W`P0x9l0OYyA^FqL z6_P&<T_O3?&=rzD4P7Dm)6f-?KMh?W`P0x9l0OYyA^FqL6_P&<T_O3?&=rzD4P7Dm z)6f-?KMh?W`P0x9l0OYyA^FqL6_P&<T_O3?&=rzD4P7Dm)6f-?KMh?W`P0x9l0OYy zA^FqL6_P&<T_O3?&=ry&4P7Dm(a;r=9}Qh0`O(l7k{=CSA^FkBz|lz<F~9+CfhOnY zCLxJ|+ngXVA%r?mGXx}rqzpVv0}|r{H|*dhLAY>3c)_wT{SZmGRsmSs5G0?InpPqR z6G+NT2Z@D3GOHo9F=GgA%osu|dqZetZwRgI4K2W#)WFaJQb-wEKnf{C3rHblXaOmt z455tzLujMG5ZWj(gf<Ecp^XAVXrsUo+9)uDHVO<aA%%pYC8Urrgf<Qgp^XDWXyd>T z+Bh(THVzD-jRQky<G>KwI531Z4h*4<14C%zz!2IvFoZS^3?YS$fgz-@F))M_HU@@} z!p6W5QrH+6LJAuLLr7s`U<fH}3=AQKje#MgurV-%6gCEikiy2m5K`C}7(xmc14BsR zVqgd<Tnr2$g^Ph9q;N4XgcL3YhLFO=zz|Zn7#Knd7Xw2`;bLG2DO?N;A%%;9A*66I zFoYB?28NKr#lR3!xEL5h3Ks)INa12&2q|0)3?YS!fgz-DF))M_E(V5>!o|Q4Qn(lx zLJAiHLrCFbU<fH(3=AQKi-94ea4|516fOpakix~l5K_1p7(xmc149=`;co~jTnr2$ zg^Ph9q;N4XgcL3YhLFO=zz|Zn7#Knd7Xw2`;bLG2DO?N;A%%;9A*4_-FoYB;28NJA z#lR3!s2CVR3KauGNTFh22q{zy3?YSzfgz+&F))M_Dh7s-LdC!kQm7ahLJAcFLr9@w zU<fHx3=AQKih&`dP%$us6e<RWkix{k5L($ALMwYiNa12&2q|0)3?YS!fgz-DF))M_ zE(V5>!o|P{T6r5mD{muc<!uD5yp5ohw-L1RHiA~(M$pRJ2wHg?K`U<~Xyt7Lt-Ot( zmA4VJ@-~82-bT>M+Xz~D8$l~?BWUGq1gX3Yj0_>=f{~#qxN~4+2q_ng3?b!$ks+kK zF*1ZSPK*p8jRPY?NaMiB2$JuOj3D{m2s#5{WCSU9jEtb>8$r!Cf|_pxHQxx*I5IMV zG)|0+z?GkYkrAYEWMl-j-w0~I5!8MosQt!J`;DRY8$;5kkulVMW2pVcQ2U{?5=O>Q zdyS#?8bj?hhT3ZkwbvMGFQmt6U<B#08W@>C?KOegYXY^`1ZuAd)L!T$g^>x=-zHFh zn?UV1f!c2ZwciA4zX{ZS6R7<rP=A|1{SEEx8ks`vhYU;@7@0!tH-*}73iUU1%EHJL zYQHJeep9IZrcirLq4t<U?SXcpji8-qBWS&21g&?Bpq*$VXeZhT+KD!TcA|~UEWm@$ zK8Yond5{za?M53xyU|9_ZnP1!8*O9;bpf;+Z3OK`8$r9#M$m4w5wsg^1nou}LA%jL z=4RaBG2!H#{NmIUh@H@`v=Ou`Z3OK~8$r9$M$oRb5wt691no*2LA%mM(Aw1qTDuxS zYgZ#^?P>(AU5%i%s}ZzzHG<ZzM$p>T2wJ-uL2FkdXzgkQtzC_vwW|@db~S?5u13(> z)d*U<8bQ0@M$lT;2wKY;S(@^u=j4}^B<7Tq7UjWw53OsBpmnVgw5~OR*0n~^y4DC< z*BU|VS|ey(YXq%pjUWwu10zU7-@wSxh&81uCo>%q#*QYOU|w=*Q4VWKF+$v&vm`ku zGaV!jRS8XV(7M+MTK5`3>s}*h-D?D`dyOCseFGy%L*Kv%S{EBZ>tZ8lU2Fuci;bXl zu@ST`HiFj0M$o$02wE2#LF-~8XkBast%HrAb+8e%4mN_;!A8(J*a%t&8$s(}BWN9L z1g(ROpmnYhw5~OR*0n~^y4DC<*BU|VS|ey(YXq%pji7a{5wxx~g4VT0(7M(LTGtvu z>sljdU26obJB^@qrxCR7G=kQhM$o#`2wHa<LF-N<Xx(W9tvijNb*B-u?lgkdokp(E zG6Gt68bRw$BWT@e1g$%bAPsT@BWN9J1g%4jpmnDawC*&5)}2Psy3+_+cN)R!PH0Ej z2-;CLf_9XRpdDo+Xh+$|&5ak-G)_#)FG~frzrm@@7+NkEL(2tYXr4EQ=6Pdio;QZ( zd1GjvH-^T7F*MYTT})UCGBOPzhC+kd7}~5chBj-Aq0Jg&XtTx`+N?2#^qCBdq0Jj( zXcQSkqsSN<MaIw|GlmA4F*L}Gq0J6sXwVr$gU%QlbjHx2GlmA8F*N9mp+RR14LW0J z&>2I6&KMeW#;`F4=xns9AtZ`Tq1C=Aq}n%hfiz<bT_DXELl;Oh#?S@Qj4^b9G-C{1 zAk7#<7f3V4&;`<rF?4}6V+>s&%@{)$NHfOJ1=5T$bb&Nu3|%127(*9GGse&b(u^^5 zfiz<bT_DXELl;Oh#?S@Qj4^b9G-C{1Ak7#<7f3V4&;`<rF?2BmS9gXkhTx*d&;{aO zLl=mD4P7AqHFSab7t+izbb&N;3|%12977jKGsn;c(#$b*fi!arT_DXILl;Oh$Iu1R z%rSI<G;<7HAk7>@7f3V5&;`=WF?4}6a|~S|%^X7)NHfRK1=7qhbb&N;3|%12977jK zGsn;c(#$b*fi!arT_DXILl;Oh$Iu1R%rSH^23PlnE|BJqp$nwBW9R~D?ijj2nmdLr zkmin|3#7SY=mKf(7`i~3JBBWh=8mBYq`7100%`6Tx<HychAxoij-d;rxnt-8Y3>-h zK$<&-E|BJqp$nwBW9R~D?ijj2nmdLrkmin|3#7SY=mKf(7`i~3JBBWh=8mBYq`710 z0%`6Tx<HychAxoij-d;rxnt-8Y3>-hK$<&-E|BJqp$nwBW9VWEZf+U6K$<;<E~en- zmZ6I&xVdHM0%-;rx<HyihAxn1kf95t8D!`JX$Bd(K$<~@E|6xBp$nuLWat8E1{u0Q znn8vxkhugy7sy<Kp$nuDWat8E1R1(O8bO9GkVcT93#1Wb=mKd38M;6kL541nMv$Qk zq!DE30%-&px<Cp$Ll;P4XXpZ%OE7eS%q1AQKpH@XE|3P0p$nuiG<1O!hK4SX!qCtK zQWzS#Kng=c7f1uh&;`-}GIW77fDBzA4Io1oNCU{w1=0XAbb&O03|$}%AVU{O1IW+? z(f~4afi!>&T_6o0Ll;N`$j}AS05WueG=L0UAPpcx7f1uh&;`-}GIW77fDBzA4Io1o zNCU{w1=0XAbb$;r7`i})84O(@O&>!SNYlsA1=92}bb&N|3|$~iA43;N)5p*S()2NO zfi!&#T_8;#Ll;QX$Iu1R^f7dS3_BRQK!zO*T_D2_hAxm{2SXRgu!ErsWZ1#b1v2bl z=mHsbFm!=5eGFY7O&>!SNYlsA1=92}bb&N|3|$~iA43;N)5p*S()2NOfi!&#T_8;# zLl;QX$Iu1R^f7dSG<^(RAWa`b7f92`&;`=;F?4}6eGFY7O&>!S$S{PV3#18T=mKd1 z8M;84K!&c+^4=9%-n&A}dsk?A?+PvNU7_W@E3~|Kg_ifO(DL3DTHd=t%X?R7dG87> z?_Htgy(_f5cZHVsuF&${6<XfALd$zsXnF4nE$>~S<-IGkymy6`_pZ?L-W6KjyF$x* zS7>?f3N7zlq2;|Rw7hqPmiMmE^4=9%-n&A}dsk?A?+PvNU7_W@E3~|Kg_ifO(DL3D zTHd=t%X?R7dG87>?_Htgy(_f5cZHVsuF&${6<XfALd$zsXnF4nE$>~S<-IGkymy6` z_pZ?L-W6KjyF$x*S7>?f3N7DVq2;?Pw0w7kmhZ06^4%3$zPm!pcUNfn?g}m6U7_W> zE3|xfg_iHG(DL0CTE4qN%Xe33`R)oW-(8{QyDPMOcZHVkuF&$`6<WT#Ld$noX!-66 zE#F<C<-04ie0PPG@2=4D-4$BCyF$x%S7`a}3N7DVq2;?Pw0w7kmhZ06^4%3$zPm!p zcUNfn?g}m6U7_W>E3|xfg_iHG(DL0CTE4qN%Xe33`R)oW-(8{QyDPMOcZHVkuF&$` z6<WT#Ld$noX!-66E#F<C<-04ie0PPG@2=4D-4$BCyF$x%S7`a}3N5c)q2;wJw7hnO zme;P(^4b+zUb{leYgcG_?FucgU7_W*E3~|Jg_hT@(DK?9T3)+C%WGF?dF=`<uU(<# zwJWr|c7>MLuF&$@6<S`qLEEEl(DtYsw0v@dmQQZb^2rTaKDj~5CpT#M<OVID+@R%? z8?=0KgO*Qj(DKO*T0Xf!%O^Kz`Q!#IpWLA3lN+>ra)XvnZqV|{4O%|ALCYgIXnEuY zEsxxw<&hh-JaU7UM{dya#|>KkxIxPwH)#3e1}%TwpyiJnwES^{mOpOL^2ZHY{<uNQ zA2(?E;|48%+@R%;8?^j!gO)#T(DKI(TK>2}%O5vr`QrvHf83zuj~lf7af6mWZqV|_ z4O;%VLCYUEX!+v?Eq~mg<&PV*z3B#RZ@NLtBR6Py<OVH|+@R%=8?-!fgO*2b(DKI( zTK>2}%O5vr`QrvHf83zuj~leSaf6mOZqV|^4O-r~LCYIAXnErXEpObQ<&7J(oN<Ge zFK*Cs#SL1XxIxPkH)wg{1}#tApyi1hv^;TxmM3n|^27~Vp148F6E|pi;sz~G+@R%& z8?-!egO(?5(DK9$TAsK;%M&+fdEy2wPu!s8i5s*$af6m8ZqV|?4O*VKLCX_2XnEoW zEl=E_<%t`#JaL1TCvMR8p&PV)=mu>cx<T8AZqW9j8?=4s1}$&gpyiDlw7hYHmN#zD z^2QBX-nc=_8#icq;|48n+@R%+8??M}gO)dL(DKF&THd%p%NsXndE*8xZ``2ejT^MQ zaf6mOZqV|^4OZSj+lOw@_MscJedq>lAG$%?hi=gJp&PV)=mu>cx<T8AZqW9j8?=4s z25ld@LEDFJ(DtDlw0-CXZ6CTp+lOw@_MscJedq>lAG$%?hi=gJp&PV)=mu>cx<T8A zZqRn28?;^M25lF*LED9H&~~94v|Z>1Z5O&h+l6k>cA*=zUFZfG8Z&f*42>DOL59W* z-5^6_hHj9dF+(@Vw3MM6WLnD54KhS#=mwdVGIWCsl^ME0hRO`xAVXz_ZjhleLpR7! znV}nGsLap}GDu_S1{o?dbb}0)8M;9RZ4BKYLt}<+kntKrH^_L6p&Mkp#?TEiUSsG6 z8Lu&PgN)M{x<STi4Ba5(G=^@FaT-H6$T*Fm8)PWW&<!$_X6ObPN;7nW45b;mL59){ z-5^70hHj9dG($JYP@16|WGKzh4KkEw=mr@|GjxLtr5U<GhSCh(AVX<}Zjf;xLpR7c zkf9r79LUfOGX7)e1{wb`bc2ll7`j2me+=Cq<3EOOkntZw=t4b1H^}&pp&MlU$H)Lu z&lwp&>Nz6=NIhp{0IBDU3?TKIkpZNAZDasx9~&7!>JuXaNPS{t0I5%m3?TK1kpZMW zF*1PECq@R4`ohQnQqCJ0K-ynM29R>i$N*BV85uyzH6sH^xn^VlDc6h)Amy5o0i;|r zGJup<Mh1}b$;beb|BVbF`QOL@lK+hiAo<_O0FwWWpnHal3?TW`$N-X0jSL|9(#Qak zFO3W!`O(M#k{^u>Ao<S70Fv*F3?TW=$N-Y>j0_<8&d30g?~Du}`Oe4ylJATRApJ5U z14uqIGJuTt85u(QD@KNpddbKT(k?bKgw#VuhLC#52s(Xl<P51-jGQ6$ijgy<UNLfp z)GJ2Lkb1?)8B(tpIYa6dBWFmxV&n{|SB#t?^@@=*H2j^R;qMF$e`jd;J45OZBWFnc zVdM;{Ka89q^@ou&r2a5+hQ^08r2a61_QM>_A^vkThqQkj%^~d{M{`K~$I%?p{&6&i zw0|7UA?+VWb4Y*8(HxTA9L*u^AxCpad&tooQeQZlL+T4hb4Y#RXb!0_9L+79;d@2E z>oDLv@G=b0SgsqikLL#M<GDfmcy6vn#=@ZeWyVg12F3;^2F8ZQ2F3;kSi}s`#7wZL z1BoH4Gs9vYOblHeNH4OzAax)ym^w==?n4$sR|nDyGY_T?B!;XGWCyZ;LF!;)=;}av zk<A0C1BpS^Ih$g-4@C@J9Y`<KJh(cL7_vH$9Z2p2tAmN5s{`ppHV>o@BnDOI1oE2& z#EtOyMHWL>XNDBNFm)g?s5-D)(9A;-LstjVi|js-UXYj}hihKCUSduOoM8kLG3GAK z%LG-621d@7P_`?A?c##O28(lmw`G-<q;i1QnWyBJ@Im&E!B*Dug4Z6wcwAr}ILmND z)PXY$lnoY#XC<(Kd@!95)!bnH5H@E@ehGxd3uoyiCl>I7bC&@qcY%Cs0p%MQ7#kq- zLGqy3LY4>fA>MXz1*wO!T@Y+%Bynf3I4HLpm_mAF2Bwf6nSm*!Ml&#llu!nykP^zk z6jDMNm_kY*15-!|WMB#@fecI`C6IwBq(^383h9v<m_mAF2Bwf6nSm*!M`mDZWX=y; z!W9n+k0S8ubt404OUu>G5#&B2XGl$F=xXW89s-`b1#dAkbcM{^7`j4gY)5m5y^iJ( z`y9<7_BfhDdVG%Nkeb=i98x1YnnP-0M{`II&e0rF6FZtidTfs7ke-^OIi!c?Xb$O_ zIhsRiYDaTOPt4IA(gSlehxEK0%^@Q|j^>b_m!mnP$K_}a>1jEdLuxWdb4X9i(Hzpl zax{n3XpZKP9+jgxWaP%t95Q0#Xbu^vaWsdt5FE`RHJ+n6q-Jw8htz0}=8&4q(Hv5P zIhsRiE=O}nI69g`S_Y2hkRFSpIi#oJXbu_qa5RVXSRBnEJrzfDNDsx)9MUs!G>7yw z9L*su3rBNEi^9<y($aS{hqN3V%^@v&M{`Ka!O<Mja&R<<wBQ}hAuV`Eb4Ux`(Hzo} za5RUs930IdEeA()NXx;|9MW=dG>5bt9L=4~_@TR!^>Xr)bNn2`_@P^c;e6=kTsR-P z#}mdE@j==}0v7aj^bqmGA_z@+sREFlbcP1TDfuNisl~-`0aK^|7kGzY4s2D2ku#*j zXkY}1J_932huFXn(y%r#GIivG?j44j07~@+M$qvBS2rgR-_RA>&vJ$Ivy7b09l452 zlZumzG7CzwKuV09%`N#r1&EP}CDbGc*U|-r>tuw?HFksf1f&==eS;(mnk_)#I+~zz zEs(jcM#vU{R_Q`zL9TN&hZF~n=8$5*(Ht@$<7f^Uh;cNBG?*RDAq{0mb4UZ((Ht`1 z;%E*TaB(z;4750!Lk3tJ%^?BhXbu@raWsbvq&S*G22dQ$Ap<9l=8ypsM{~$PiK97W zfW*-pGEnPi4jCYEG=~g~IGRHmo{r{_fmla#$bg8WIivyVXbu?waWsbvd^nmz20k3k zAp;+d=8$-HG=~g)IGRHmrjF*22B@Psq~Ymk4ry>YnnN0zj^>aCrlUEeVee=TX=pl{ zLmHZn=8%S_qdBCZ>1YmVXgZoh8k&ygkcOtCIV9aVnnMOC9L*sE6OQJPflWtq$bf{S zIb<Nh(Ht@W;b;yScyKg_3?w+3LplzQ=8z79qdBC5;Ajr%z&n~lItY&DkPf?}IizFY zXbx%EJDNi})Q;wm;@r>`+R<`#bK{2|CIHTPpzI6X;Sb}B<Y38(B6(N@`Jp)orjsAK zi5tdePK!@tO^Z*9&jgb>%xUqN%xUpC?BEUA@g>Z~@g*#Ydd10{iQt+X%mS}Q)+<it zOGGSg)+<itf$x6?s{*$I^oo<YpywulnUF2ydd0~c;0@k-#mT&22EuS~Ye26!nKdyL ztOK&?Tdz2oB?&|%gUn8bD^CWuDD;Yxxs#JqQ!;aMKyKwjI(I>@IGG)E>H<h_ie7Ot zTWU!L$Oy>k3lJ9Q00xje$U;uIeVnN<e{w=jQ~>!n71hV7u%-;iBZ!k3K*pxR{SQ6T z0puH4JQgRjq=9Tq2dPYl*~5o)OoLu=GJiU9gcc{WgAQ!~=>mCx9dsT8$VEs8HGt$Y zK_+Ix!v}H}14vyas>?HxU7nc&J6-~;8|HG>%q)<jp~pLbneh1Igq#5ZvJ#|-59uri zkXSaz{n@DQXUPGXo&$Fq<iG}yLX_lOoXie7z5%Qjyt^M{UM`5p1BvCq^+S$s0O?0b z`Jgz?0|#s#EG@C*gLLM@bwZAC0EJ3EYN+HRg$idrEF1*#k<UW_g#+|R2(YOzH}WB! zMF5t7+0L2|N?0rfpj2N1+K>qHOCg9T0;z+X5&>qx5;K1hTF4cHq#;K{fLSnw+{H+# z9_hRYP@oi}n!%f%T9liZmy(nNGK{4Jlrca@Mu5zN93uhBMI{LH_)Aa?U?~MDErkan z<P-@|AeN#AVkvSUmcj!O<xmMwAVN>205jp~iUWKe1=uE7__36M!m1o32HEWkvJ>gx z2~g1k-}MVt1+$Z-0;IDNBvuJ?Hy_f`6d;|I$gYL#6$WXl0%?LASpjCjLYx<IXay() zOY<^~3}6)zWMtXV95TY@Xbx$iIGRJ+<BsN#0^ZRa)-H#wq=K}=4NM{Ja063FJKVq& z+735^wx`XY?P)V;d)f@zo;HKFr_G@4X)|bh+6>yBHiNdO&7kdRGiZC-4BDPHgSMy5 zpzUchNQ2DL4BDPHgSMy5AR|YPX3%!E8MIw(25ncHLEF`4&~~*Mw7qNwZ7-Wa+skIq z_OcmtM8?bl+@EnYgN)cann5dAGiW>74BC!1gN(>Inn6b59nByk@Q!AdVEqQBkOq^1 zDWt(<U<zq48JI#EOoq-7_ZT`uDtJR@h`S7(Ar-x$GsJy{&X5Y<&>7-RLuW|EZ|Dqj zFSNmA25m5zK^shF&<2wkw83NsZ7`WZ8%$=<29p`I!DI$)FquIcOlHsqlNq$ZWCm?8 znL!&&X3z$cnHhLxp`#gO1kce7+Hf+1Hk{0$4JR{b!^sTVa597V+tCc-Uq>^DKOM~= z{&O^gj*OW>N5ssa{TVZ8x;BG0c+8*;9y7?yh@%-~M#Rw!G85uxX6Ymd=?xf|nSmP` z!9n1*x}zDir)36hYMEI&gPXu+mM$RLz!)-CYhVm%(is>-nr;ThkTHA%V~9QjV@QrO zForbw42;dqLA`ndV;2L^7zl@RT2W$lNof&>2aMqfV+6q%QBVfRVn=gm(l&<#sgWTh z3mO?hCU=btA(OX8hK5Fb0huoOrAaxd!6ikd$&jA8p`jDB9|T?kZ)9lX#OsW#iq`{$ z=ZC@zK;Z?V@PbfyQOG=D&yvKP%w!j2F+uP_Gsq$!?-?0F=CF+nAtj8FA*AbIWC-ax z7#YI44$z!s4$WESkeuac4vi;sOIN6^Dadv}#Zs||p@bDwT^6!BLGbA@$Rd0ND4L)i z0I%>jGBj{whxF`Hp>#f!2Cpc0G=~-u=Fp^R4o#Zo(4=V&nVfSpha@;hbI4?zqZ1@R z9GxHm;^+h&`f!2<j1zPS#0lEBa)J(pI6?bZPS7C{Cum>G2|6_51nqM<L5E13pnWeV z=unB1F*w0EIzfwgCuq^)1TE^Fphb)mw8(dY7Bx=LqTdNx<TydA04HeC;{>e=oS;RJ z6SPWjf)+(i(5k@+S|m9^s|Y7((c}cJDx9E2loPbdaDo<9PSC2u30h=1L8}laXwl^a ztxB9ARfUlOBtDD`APLOK01_`o29ShiWB`dDBLhf+Gcth0laT=|;Xw)pM{~%em7_Ui z(#p{ZT2(ngi%2JEmE{B}DvdykqpDJi^7V4k*z)sIK~zaOh{pjwc0(^GjXf>Dv<OUR zmVxDqGb{9R(m24UZ-5x!6F5K$@-o2&aDdIrFHU0z83>|5CgvBXaYBsDFHYkCn+axs z3<aqHnF>+^F&4yvm<v(_HaNdHjSFltxH-uQW|n|tLAHPyAZtJjE{HuKCMVb;2n%Er zh{XZ23dG=o*ac=nECVq)!M1@}U^`Os@^d*rc7PcmJ3tJm9Uvye4hRcm2Z#l>1H^#Z z0cJw%05KtUfLUNW@=9}yz;=KcAUi+|s2w0C#104xWCw@^wgbd~+5u)l>;N$#c7Rxr z0s<Q0(9NhuhLD76WC%&9Muw1tYGepWs78j6glc36NvKAKkPKjC2+06OhL8+kWB_S1 z7#Tq7P9p<Io59EcQimEDK-vsO29Ubc$N<u2FfxGDsYV8nHiMA?q;54bfMjeV14xE6 zGJs@ABLhgrHZm|VV@*yhN(CRzXJh~=4vY*S#e<On)RoY+dq&W;dqxJ3Y+wXk>u3aB z+i2u!V8Ne~U!GT<Sd>znn3tSi1Rfzag07u3GJq5pM$k2dMh4JOF@T01bWNp^0i-2j zWB?641IQ4SkpZN5GJ>wPG;)QEh#MI|iVGv?nolF>+DRkm8crkV+E63tT2CYByqb}L zi7Q`z9;hFknwOKBn37r~1L1-WYb+_xPsuMSE-1}QE-6hc$;=0D4l{zT*EE8z12r;$ z6p2O#kRs6ty6({kx(?C^y57_Xy8hG%y1vxN08&&Nxf&V@!j1zfNGwWBFG?)P5P^vl zmZlbitj<k@4a!4GP$TF$G)B;KX^dPU%gBtN%SDZ#%T|q`%VCY6%Ug}0Q;9~d#s-qb zg{6r_sVSgLoswUI?ok6sS!`qgP14W>s7BBQs7BC*szwHovfl{0kkiNjQZ^bv7lax? z7kU~&7lIlYm>Tjy!WI_j;2dRO>L>#dE(V1@Bpxu_1gXD_3?O5eM$ko~M$ko~M$l7x zjG(9X7(o|{I+~dq^OhE1Buhx`Yh(avcp4d4xC$o~B_?NQB<7?g<(HJ?=YsaPi=c@W zWu|A82*3qP@(Vz!1d#>6N<=}zDd4tSL1IyAUP%V%TtG3f9ELDB44`Xtji76EjSL_& z0!9Xq837~c8et;?X!FnjvbN6%x@Oi0x`x&Wx>nZ60McwQGJrHAj0~Wqk^!U{VdQFJ z!~=46D#)dvAtf*e>_AYT7sSg>ErCk%L%A?%=xJ4;J}vy*Dv%jaPJTIP_(UMRG&83- zGcP>{YKkCS0A>ykIB=lSykHJYiW`>vLE{TBHmHDsc7+`+VO>^e02x4wWdleT*T?|U zMKdyhbYYAPVC@5FyW0TL4mUD@bS;exAYB?G14tLs$N<u{F*1O3NsSC3i<68DAd8NS z3?Pe+j0_-CDMkj6F;*i3$f6}91IQvJBLm2yBqKv;L1qYz5JO0N$;c2EQP66@5YoOg zGJteZjSL`T#zuzFh%<n6nT!k|Q%6Py@RSVhni?6HI|{*ykl@6;;^5Sx%rqa-;?mq) za7l*T{uO}i!-OkyM;Gux7l`Bt0w4615(rMUhLDx6Muw1;u11ECm8?dFkd>}RhLDx6 zMuyN5&k(Yr)yNRicr`LG2KUB{3?cKMMuw1y2_r)jXP$zhR7m?9R{R=5OB+MTq^FS~ zWSOjyp^<?^ab<2&eok6`QE_5!Vo_#EVqS56X;CudKr%zftf&#_;Mwxj%+#XdlA^@o zVvr9Ej9gsB!4o#Frtzq>B@S^j9O4!@#LdAo$VPDU(ap7l*^8zhCXP!zx;tR%(cJ+P zM|TIhelr~IfQh5K1165k9CUZU)T6rtU7ZCEcfiEa-2oFvcLz)ym-*=KFh>i2a~$q~ ziKDv%CXVh7m^ivSVB#=$z~adi>JB&`%^m3CFn6Gf!`y)`4s!>(IL!YraTty69+)_~ z`7m*G^I_uX{zTUgOCRX=!Nk%12@}U<4!S#F>e1bSt`3%N(A@zOM|THI9Nir-aa`u3 zy8}J^Vd(?i9WZfpcfiEa-2oFvcLz)y<_=i+!0dzb(b6BfILsaB;xKohi^JT3E{^UF zbaP?p2;F@!aa`)r-2qdN?hcqZEFNI)gVE^r!o<<-g^8n^4--fCC%QUVx<R)OCXQ|& zOdQ>xFmYVwqq_s$->~$7?hcqZx;tRv=<a}tqq_qp4s!?0y)gUWe6;k3E)H`Cx;V@o z=;APUpo^os1KnI$`apLdOdOYbba%kiqq_qpj_wY0{jhX|?hcqZx;tRvxXeL!2TVOI zJ;1^VMx)yc6GyifCXQ||OdQ>x==Q<V2fBSQadi7&;^_9l#L@i;6NkA2#)sJl=cA=R zba9wF(8XcyKo^I(16>^59q8u5(g(WxVB)ycqq_s99^D-<addZ}>xZQeba%kS(cJ+P z$7K$>J7DV3-GQzSmX6Tf0TV}e2TUB@9WZfR=EKq@EWThgy1g)QbbDdq==Q?I!Dl}> zI+;50B<2>R78NJvffkQ|IwwYkkUp$|F{GzsU~FK{37&8Uog=~to@NHIKxz$)A@fHD z#*od12F8%h6QHH1P<cmA@H97)4ij$BcuP)ZUTSh~5>yqqLuOzM*=k{64B2X7U<?^{ zFffJ;I~W*4wqAgii$nB5I&cQY&;_i<&;_i<&;_i<kl{K5W9R}_W5^PF17pY%djn(0 z5_<z<$P#-4W9R}`V@O}mz}Uz@0(6Q>L1IoKXfCQMH6<xEC%+uz88MJVQEEw1KIkSC zxG+yjehHidaU^6_s(~@2muX-O>5>~5Lxv0tjA6kInY%JDhR*I98-eEz4UD0)yvC5B z2LofsY_EYaWJ<@t7}6CtFosO&7#KsQbPSA*O~gPqeq^T>XXF=^fWtho66ADIh%jgc z6pAS5)(LdABH-bAG^G%KL3+~$#>U_w00U!4Z`;7w80v0FFWbNvG8JTC3>iu@Foulv z8W=;yehrKvQ#}U8ka0}|W5~FsfiYz4*1#Cj0XHy)3|$x)Lq?Vjj3Fb-2F8%79s^^@ zK&62(WDMEB7&6jr06m}Fz!);TXkZK(yEQO|i~$=MLxvj-j3HxH2F8#vU;|^wSh0aI zWCY#77&1m|U<?_HHZX<^I~o{6req9^Awxk1#*m>K17pY#kb$w85kEN7fb$TT#SJDQ z>%c)_Y3Kr3F=6Q9=Ee<PECrF11jSZnUS?i;a(-S`K9~iO5r@k__@L1&&>*4&nmBl1 z3namvl3!AingX^M$_BefGzC0fh*;nPJ~4<NEC*H$W^sc_h*b~=LpPhbIGaG%!GoO* zk#jcVhAejho5fX}mzbRj&J%parNsrQdBvIed9d+iLr2J>UqeU8qF+Nt$f93EN64aI zLr2J>UqeU8szO6Y$cUJsBV^>u&=E57W#|amMr7y+T}18(83{9Vgp8aSIzmRy3|*kx z&|IL~&|IL~&|IL~&|IL~&|IL~&|F->Ws{+cD|m+1&;_~;%>}Yu$<PIIJdvRbbX%GW zbX%GWbX%GW<ai=O7sz56Ll-x2_AqpTES52Hfo!KUa)E58Gjf4!r!#VaY^O7Ffo!KU za)E58Gjf4!r!#{3!wBjRBd9-&p#Cs|`ojq74<o2QjG+E7g8IV<>JKBRKa8OMFoOES z2<i_bs6UKcAlvMWTp){pj9efymPRg+8A~G<$ZAg`sDF*1{xyR87n0PCTp){s+@SLb zZqOlUH|Q}DZqQ>Q+@QxqxIvGJaDyHb;Rc@4DFUZ3_R?Z7&0Uq5UX_>*PHNzk=;-9i z4_o~N${2dZ$pY||fKUM*aMFfxz)2p;5k_7V2Ne@UWE7|f4|w4ej04UEP!2cfh94-K z2VMz+Myw$j2`a@4$tzGE52!>2U)u#8ayBrA%%~X{L*}9kj3HCy2F8#XH3Jh1$nl0I zkeNCI6Ua=RfeB=$&cFmRQ|D*~T~=%cT|R6ET|R6ES%cze23<aE23<aE2Hh=S23<yM z1{wNwG=mHcJDNe}3LMQK`+gnGAWIG0pyzhDfu^QQ^D-UHpi|pskToriW{|ZnhAz;3 zrY_L^r7kYur2>Y~j9>`O2nNQGp>snQ$Wd>GE|8<%3|*l6SzRFeSq+RKL+A#^kRfyf zW603Ep^J;9a9U1cNl7Yb;;kSxFA<zrzzM_!vgg&n*bG{SK~@?Wx<L2Fx<Jk>GjxG0 z**An{LIY#S$|FN)<~1;e4CfoVK=$k!7(-Tw8A3C$Av6;k7(-Sn85l!`{SAyE>xB%A zA#q~}%iPZ9E<8w!6T#<b8aYD((#RP)_uvd!Ead0}akQhkBe;Zebb?esj!uvY$k7Qh z=iumMW-N(yKwd95vj`L%Mh1{A%tp{7PK=;OoH&|82HYLZAp`D?=8)E&qd8>2-O(H} z;O=M+nG<w0hYZL&nnRZ5IGRIRl8)w(fp|xA$k7sx=8)E-qdBD2=x7eva_eXgX$Lx* zL)w9k=8$%vqdBA<=x7dU2RfQVj+SsVhqMD7%^~eTM{`3n1_lNOMh3?J{~7o}Op0+d zLo|aYgD2A|1_mYx28RCvEV}=0GhO-rjY;YMHwcdbuIB$YrXNfaFma}<|GzQ)MN${T z5X0cj;LT*izyLPI_5TkL%>Wk%$w1|7m|Xt<fXaI?cre&8*fC}>y!gKWVkekA3&LiA z$;*RGV+4~3H!(0Uy+Lw0$W3pM++@vQ&7i}e!>IMYjxmwp5!`&E|7DDc3@`q}?0~9c zI?cF%=>bzBqdY@D$Tp@2j5C-XFr_m}LiigPbQCr)ghseVDkymGVBib%-oO?d6|uoY zdV@w}LYhKXXv794)x@0~3>*x}$;wI6ii#T;A~!HNE4yrBU}SJkaMIntsIx&KAx(D! zla4})!iEC@8(7q$Hfb<&JG&;kZeVkbP~5<*8W|KFp{T4V-4&s*As`?^af3sow891p z5X&MmQeh)Rbz;f}jerP6C{JO70Z85er1C&OghHA^S68CK2CjgJ1Zjm03LrTy5X%h2 zGE0z7h>VPs-oT`~fy+6014B^61_p1CV#N(y&eGl+<Up$Ayc2f_FeHOi>|kX`ii}K2 zjNHJe9T};-fgvCwH8N6n1GA2TtHK5r)x;Eq4Xn-q5gS;Qoi?y3J4q`lMs8qC(A~hI zqpYZ`sF1ReHOWZ<Bm?rJG{nsyasy|AYw`wWEk%V5Y|aW@3SAo*wKp2Ds%~IW3yeqz zkWLJWj8KkLj8xd*5FD|AQCk`m7*P9lH?Zn#V0YHu#J~gzTQ;2y?8;8c3L6-dof0=N zC8cd(Oy0nluz^)ecLTeQ0?4U6&dEDi7?Kn~KG@)p5D8L}-~x6kht4K;9tLMuCoM&I zY;o$K#vT{M6h>|34Ghj3SX2`fT)UJLK`{vqVFqbXENoDa-rxWar47ug%84!zE4XoJ z-=Go@v4H`k3+gpwO+27Pr|h(en~T{sLQz^-F;YuWcLT4^MkXfL4JnB(x*Pa(HZUeA zC~V+$_5%4!VFRzSQ{)Cd5HBb~VFRDCQ>5+&ejSAk0^lG~*ulb(+@+kjf!{enp({aQ z1HZD9vhD@}9q*8cjVviHkt!Q_Q<W=pHwfx@2S#`YLj<K2BULsCgT;k(HZlk}hem7^ z5OChWnCP^DUmKLlH!!I>ZR7<Jd`zlN8yLlu6*e%d21INGCH)O7s!m;93LtCwv=o&$ zFebv-(hzx&7ADoi4SZUPksElO-8b+#yC-a5LX9eg4Ok;^BLjo5vdacW=M4;Yn;01x z!8uJ>hhZZFlWR!C1_5O!1=kHc%1#@&l{auEI4LA-U`*U9B*e(T&*0?Lm9SBWO?yM9 zwzN{D?gkN^jSRxtx*J4wHZp=}F`bP}AX;2!BQuDW(AmfWq9t`UvVv$SosDcDT3Tl# zJBXIi*~kH+Wpy@kf@n=0WmvdxU`y~0iBMM1+rStL${@NMw2&ml;F5(9No^!aHMnFE zL{d(NVFRx=8UB;k*~lQLt-C=%XCotsR@B+Z1frF6HZp@~Wu1*IAX-IdBP)nj)!E1f zqSbUZvV&-KosAqIT0>_eCy3V3QLq7LA6*@VgbhLo3eL(K7!#a9<sc~Q>44Izp3Vkc z?G3tGx*PO$6cpSQaKxf=qJ=W348^NLS}{_0g8?jRH}bH#f>PQBeXWhGjH0d)29e-c zG(-v>TxyJT6imS`H`ZZ*s&U0E95yg&V@-1)aR#w13?SfQr);s&h*1>eR}&ot8wGb9 zKHR|IoM@rD!Bj_2+(vhU86l+`7@d<XbT^pmY-C~(Q&rGYa0iua8<<o*ySm(!-IWs+ zB9f#*1+B8vCNoAxQ4uZO4Hh~Z7{oRRDm!gpQQg3z3Rbp}i@|9Fr?Ylym!7hMf=!o& z?gmR#WeR#=g$f&3l$~Iz6*eRUL?~=<2#nawq`<5oy_rdkSt`;ARK9XJD|9J?btt<f zY+!Ll&!!0q8yK}A6%dniLW=SRX6M9|fQSuD&WX|+n4J?MH!!QB>q%5rP}sntrtFqz zA+5ZD!`Tf~IdM3HZAnnTW{EP$7Uc~r&IzE%U{y`rz=~n&1{SqMPz42cgla-c0Hg#( z*cGX}!3q`@3JMAvSk<6mp=@KJyTKYRwShy~NkKuuP1$_|qqZ_A7Hwd1V9!88dILj9 zgr0(pvLd)@Wr7GQfZPR*iVbY48(396LD>V=On^ipX39%YhQ^jMD9PKxY*X04;S6=6 zLIS8QfgX^sD7Mp4R?q{5qT2>R=ZFC5pvVXXn@GKldW<64x*P0KWP_vwP-GoYWMO)d z%|qAWsI$RB8(9HN6U;&<oeh@ST?z^|pfuKHfm`VY7H7Q;dfK`hoWWiOC1W*6$R}># zQg(u*R8VqOR<KdfQ?`J5$VF!(2aBo`DD{K1sKUYsWF6ro?T#&hfzlVLsdxjEsvD>r zvr)E?RzylKijh!vy6S9Xu+WBuikr?x21{*4P@I7r3iS;<2;6lxFo;63{U!!b4j0zj zV4|hF!2^f5r_M$OMiJo+rdqliymU60Yw2$A28E)lvVxw1TbFVoEVO)dKnZ$-x3=yE zU!6@13@+Nb8~k)OF))G{{yLi&!6E@Vn;5|&fgm-m+PWKpKx#mYV2~ORBLt)d#0b^d z%)r3lsI9vpOlLC#BbXJgvzZYh7NN755h4}|QpX5V7X?xWW<`V4fmtyibzoL3$WCW% z-3@UdJ3)+ikewh#0?1AfBN3#=O<Q+E5=ae*kqlA;Vx)l7fEcMD`xu<GbvLAe>;tpX zLH2=J86f+>tW1zPMv%HJkUB6c8>9}*$^oeZvvPGdGFZVQFb~YzV5hCSAs@oD*Vf%o z019-FvJDQ}x*H00HZodigVhv4m>@O9U^O5KkeU*mjSSXsQ%k`-u#Pea6QrXY!UQR= z(Amgn4KcD3!UQR(f-pe}s&zIp*uc%J0rSA-)k2sc<#iAyNO`@^Mn)Tmc?}RINI@fn z2~yCcvys6TZeBB(2R5$-!UQRAg)l+N+jKTE+Ct20hcH13Iv`Atf=->yoGeVR7Oj)^ z29DGX%qjsDuxeZvRIz&RU^o#Jv5}FnFLDDTq`WNH$iVL8z`b>0FGGGjgR?#-gBDms zWCh0*js}i0<}|i2HZK-44i$Dz4ye>7ws~w_Y}Jf;EO9IWOb%?itY9etCr55A2UQ0J z2iXIX2Sg7D9pF8{>A=9rz^S#7LDI>Qo52ACf+d+5TsEpOb_7OjaOjBG$eiM`Q3J%= z!NCCHGPp!aZ&U{f?BZx(U}SOVNDhhE$jsmp2?7oxt2m}{G;vfgXRt-E`LI}UsIhbM zXzgJ9-@1XNcOw&n%VyRTHU<|L1_lPMl9IH<(vtj)%)Al>(8c$e`FRSq3Wj>-TwIAM zS*67#y2YhQ={c1J8N~{=3I<#$scDI&IVHM~#eNF53OR`-d0Z*wy2&}IiA5!q1*y8A zS(3bT-QtqeT;1}_l#&dv#<awooTS9$Y~AAI#GK5$baX+`sSFCX3VHc?say!PsAi<6 zWD>B)kSo0?u@Z+9K%UIZOV`cG%*`xOuvIWJFyMlT6(#1Sr|RY=Rw&pim|_TLf&#?? ztXMZWKer&iII|=b5+IrBdHF@Dx<#qQB}JLZpe5i?@x0`s)WqUc-3r|d@a_aqu$pic zrKY78rRF84D%dI@IJ%j6DXAc<4Y(j{Bf+5)65{5lo0*rE57Nq2o|%`DUtSEhKd~e; xDKjUtq!KIxvq85wFR`Ei<ipg8<kSL~Tey<*^Gb^Hb96KFia}e`;No0d3;>v1%-R3| literal 0 HcmV?d00001 diff --git a/tests/component_tests/font/__init__.py b/tests/component_tests/font/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/font/test_font.py b/tests/component_tests/font/test_font.py new file mode 100644 index 0000000000..55e27ae84c --- /dev/null +++ b/tests/component_tests/font/test_font.py @@ -0,0 +1,337 @@ +"""Tests for the font component. + +Focuses on verifying that long multi-byte (Chinese/CJK) glyph strings +are correctly processed through the font configuration pipeline. +""" + +import functools +from pathlib import Path +from unittest.mock import MagicMock, patch + +import pytest + +from esphome.components.font import ( + CONF_BPP, + CONF_EXTRAS, + CONF_GLYPHSETS, + CONF_IGNORE_MISSING_GLYPHS, + CONF_RAW_GLYPH_ID, + FONT_CACHE, + flatten, + glyph_comparator, + to_code, + validate_font_config, +) +import esphome.config_validation as cv +from esphome.const import ( + CONF_FILE, + CONF_GLYPHS, + CONF_ID, + CONF_PATH, + CONF_RAW_DATA_ID, + CONF_SIZE, + CONF_TYPE, +) + +FONT_DIR = Path(__file__).parent +FONT_PATH = FONT_DIR / "NotoSans-Regular.ttf" + +# 200 unique CJK Unified Ideograph characters (U+4E00..U+4EC7) +CHINESE_200 = "".join(chr(cp) for cp in range(0x4E00, 0x4EC8)) + + +def _file_conf() -> dict: + return {CONF_PATH: str(FONT_PATH), CONF_TYPE: "local"} + + +def _make_config( + glyphs: list[str], + *, + ignore_missing: bool = False, + size: int = 20, + bpp: int = 1, + extras: list | None = None, + glyphsets: list | None = None, +) -> dict: + """Build a config dict matching what FONT_SCHEMA produces.""" + return { + CONF_FILE: _file_conf(), + CONF_GLYPHS: glyphs, + CONF_GLYPHSETS: glyphsets or [], + CONF_IGNORE_MISSING_GLYPHS: ignore_missing, + CONF_SIZE: size, + CONF_BPP: bpp, + CONF_EXTRAS: extras or [], + } + + +@pytest.fixture(autouse=True) +def _load_font(): + """Load the test font into FONT_CACHE and clean up afterwards.""" + fc = _file_conf() + FONT_CACHE[fc] = FONT_PATH + yield + FONT_CACHE.store.clear() + + +# ---------- flatten / glyph_comparator helpers ---------- + + +def test_flatten_splits_chinese_string_into_chars(): + """A single string of 200 Chinese characters must become 200 individual chars.""" + result = flatten([CHINESE_200]) + assert len(result) == 200 + assert all(len(c) == 1 for c in result) + assert result[0] == "\u4e00" + assert result[-1] == "\u4ec7" + + +def test_flatten_multiple_chinese_strings(): + """Multiple glyph strings are concatenated then split correctly.""" + s1 = CHINESE_200[:100] + s2 = CHINESE_200[100:] + result = flatten([list(s1), list(s2)]) + assert len(result) == 200 + + +def test_glyph_comparator_orders_chinese_by_utf8(): + """glyph_comparator must order CJK characters by their UTF-8 byte sequence.""" + chars = list(CHINESE_200[:10]) + sorted_chars = sorted(chars, key=functools.cmp_to_key(glyph_comparator)) + # CJK block is contiguous and UTF-8 order matches codepoint order here + assert sorted_chars == chars + + +def test_glyph_comparator_mixed_ascii_and_chinese(): + """ASCII characters sort before CJK characters (lower UTF-8 bytes).""" + assert glyph_comparator("A", "\u4e00") == -1 + assert glyph_comparator("\u4e00", "A") == 1 + assert glyph_comparator("\u4e00", "\u4e00") == 0 + + +# ---------- validate_font_config ---------- + + +def test_long_chinese_glyphs_raises_missing_error(): + """200 Chinese chars not present in NotoSans must raise Invalid with the correct count.""" + config = _make_config([CHINESE_200]) + with pytest.raises(cv.Invalid, match=r"missing 200 glyphs"): + validate_font_config(config) + + +def test_long_chinese_glyphs_error_mentions_overflow(): + """When more than 10 glyphs are missing the error should mention the remainder.""" + config = _make_config([CHINESE_200]) + with pytest.raises(cv.Invalid, match=r"and 190 more"): + validate_font_config(config) + + +def test_duplicate_chinese_glyphs_detected(): + """Duplicate CJK characters within a single glyph string must be caught.""" + duped = "\u4e00\u4e01\u4e00" # first char repeated + config = _make_config([duped]) + with pytest.raises(cv.Invalid, match="duplicate"): + validate_font_config(config) + + +def test_duplicate_chinese_across_strings(): + """Duplicates across separate glyph strings are also caught.""" + config = _make_config(["\u4e00\u4e01", "\u4e01\u4e02"]) + with pytest.raises(cv.Invalid, match="duplicate"): + validate_font_config(config) + + +def test_no_false_duplicates_in_200_unique_chinese(): + """200 unique CJK characters must not trigger the duplicate check.""" + config = _make_config([CHINESE_200]) + # Should not raise duplicate error — it should reach the missing-glyph check instead + with pytest.raises(cv.Invalid, match="missing"): + validate_font_config(config) + + +def test_valid_latin_glyphs_pass_validation(): + """Latin characters present in NotoSans-Regular pass validation without error.""" + config = _make_config(["ABCabc123"]) + result = validate_font_config(config) + assert result is not None + assert result[CONF_SIZE] == 20 + + +def test_long_latin_glyphs_pass_validation(): + """A long string of supported Latin glyphs passes validation.""" + # 95 printable ASCII characters that NotoSans supports + latin = "".join(chr(cp) for cp in range(0x21, 0x7F)) + config = _make_config([latin]) + result = validate_font_config(config) + assert result is not None + + +def test_mixed_latin_and_chinese_glyphs_error(): + """Mixing valid Latin and invalid Chinese chars reports missing Chinese glyphs.""" + chinese_10 = CHINESE_200[:10] + config = _make_config(["ABC", chinese_10]) + with pytest.raises(cv.Invalid, match=r"missing 10 glyphs"): + validate_font_config(config) + + +def test_single_chinese_char_glyph(): + """A single Chinese character is correctly handled as one glyph.""" + config = _make_config(["\u4e00"]) + with pytest.raises(cv.Invalid, match=r"missing 1 glyph[^s]"): + validate_font_config(config) + + +def test_chinese_glyphs_as_individual_list_items(): + """Chinese chars provided as separate list items are handled the same as a single string.""" + chars_as_list = list(CHINESE_200[:50]) + config = _make_config(chars_as_list) + with pytest.raises(cv.Invalid, match=r"missing 50 glyphs"): + validate_font_config(config) + + +# ---------- YAML parsing ---------- + + +def test_yaml_long_latin_glyphs_parsed_and_validated(tmp_path): + """200 Latin Extended chars on a single YAML line are parsed intact and pass validation.""" + from esphome.yaml_util import load_yaml + + latin_long = "".join(chr(cp) for cp in range(0x100, 0x1C8)) + yaml_file = tmp_path / "font_test.yaml" + yaml_file.write_text( + f'font:\n - file: "NotoSans-Regular.ttf"\n glyphs: "{latin_long}"\n', + encoding="utf-8", + ) + + parsed = load_yaml(yaml_file) + raw_glyphs = parsed["font"][0]["glyphs"] + + # YAML must preserve every Unicode character on the single line + assert raw_glyphs == latin_long + assert len(raw_glyphs) == 200 + + # Feed through validate_font_config to confirm all glyphs are accepted + config = _make_config([raw_glyphs]) + result = validate_font_config(config) + assert result is not None + + +@pytest.mark.parametrize( + "glyphs_str", + [ + " ABC", # space at start + "AB CD", # space in middle + "ABC ", # space at end + ], + ids=["start", "middle", "end"], +) +def test_yaml_space_in_glyphs_preserved(tmp_path, glyphs_str): + """A space character in a glyphs string must survive YAML round-trip and validation.""" + from esphome.yaml_util import load_yaml + + yaml_file = tmp_path / "font_test.yaml" + yaml_file.write_text( + f'font:\n - file: "NotoSans-Regular.ttf"\n glyphs: "{glyphs_str}"\n', + encoding="utf-8", + ) + + parsed = load_yaml(yaml_file) + raw_glyphs = parsed["font"][0]["glyphs"] + + assert raw_glyphs == glyphs_str + assert " " in raw_glyphs + + # Space and ASCII letters are all in NotoSans — validation must pass + config = _make_config([raw_glyphs]) + result = validate_font_config(config) + assert result is not None + + +# ---------- to_code generation ---------- + + +# 200 unique Latin Extended characters (U+0100..U+01C7), all present in NotoSans +LATIN_LONG = "".join(chr(cp) for cp in range(0x100, 0x1C8)) + + +@pytest.fixture +def mock_cg(): + """Mock all cg codegen functions used by to_code.""" + with ( + patch("esphome.components.font.cg.add_define") as mock_define, + patch("esphome.components.font.cg.progmem_array") as mock_progmem, + patch("esphome.components.font.cg.static_const_array") as mock_static, + patch("esphome.components.font.cg.new_Pvariable") as mock_new_pvar, + ): + mock_progmem.return_value = MagicMock() + mock_static.return_value = MagicMock() + yield { + "add_define": mock_define, + "progmem_array": mock_progmem, + "static_const_array": mock_static, + "new_Pvariable": mock_new_pvar, + } + + +@pytest.mark.asyncio +async def test_to_code_long_latin_generates_all_glyphs(mock_cg): + """to_code must generate glyph data for every character in a long Latin string.""" + glyph_count = len(LATIN_LONG) # 200 + config = _make_config([LATIN_LONG]) + config[CONF_ID] = MagicMock() + config[CONF_RAW_DATA_ID] = MagicMock() + config[CONF_RAW_GLYPH_ID] = MagicMock() + + await to_code(config) + + # USE_FONT define must be emitted + mock_cg["add_define"].assert_any_call("USE_FONT") + + # progmem_array receives the combined bitmap data (non-empty) + mock_cg["progmem_array"].assert_called_once() + bitmap_data = mock_cg["progmem_array"].call_args.args[1] + assert len(bitmap_data) > 0 + + # static_const_array receives one entry per unique glyph + mock_cg["static_const_array"].assert_called_once() + glyph_initializer = mock_cg["static_const_array"].call_args.args[1] + assert len(glyph_initializer) == glyph_count + + # new_Pvariable is called with the correct glyph count + mock_cg["new_Pvariable"].assert_called_once() + pvar_args = mock_cg["new_Pvariable"].call_args.args + assert pvar_args[2] == glyph_count # len(glyph_initializer) + assert pvar_args[8] == 1 # bpp + + +@pytest.mark.asyncio +async def test_to_code_glyph_entries_contain_expected_fields(mock_cg): + """Each glyph initializer entry must have 7 fields: codepoint, data ptr, advance, offset_x, offset_y, w, h.""" + config = _make_config([LATIN_LONG]) + config[CONF_ID] = MagicMock() + config[CONF_RAW_DATA_ID] = MagicMock() + config[CONF_RAW_GLYPH_ID] = MagicMock() + + await to_code(config) + + glyph_initializer = mock_cg["static_const_array"].call_args.args[1] + for entry in glyph_initializer: + assert len(entry) == 7, f"Glyph entry should have 7 fields, got {len(entry)}" + codepoint = entry[0] + assert isinstance(codepoint, int) + assert 0x100 <= codepoint <= 0x1C7 + + +@pytest.mark.asyncio +async def test_to_code_glyphs_sorted_by_utf8(mock_cg): + """Glyphs in the initializer must be sorted by UTF-8 byte order.""" + config = _make_config([LATIN_LONG]) + config[CONF_ID] = MagicMock() + config[CONF_RAW_DATA_ID] = MagicMock() + config[CONF_RAW_GLYPH_ID] = MagicMock() + + await to_code(config) + + glyph_initializer = mock_cg["static_const_array"].call_args.args[1] + codepoints = [entry[0] for entry in glyph_initializer] + assert codepoints == sorted(codepoints) diff --git a/tests/components/font/.gitattributes b/tests/components/font/.gitattributes index 63ab00e9f2..4df6726184 100644 --- a/tests/components/font/.gitattributes +++ b/tests/components/font/.gitattributes @@ -1 +1,2 @@ -*.pcf -text +*.pcf -text +*.ttf -text From a008c27fcfc8e1f4fd1241ce4597eef4ea0be15b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 09:01:08 -1000 Subject: [PATCH 1730/2030] [climate] Avoid duplicate get_traits() in publish_state (#15181) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- esphome/components/climate/climate.cpp | 5 ++--- esphome/components/climate/climate.h | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 5cbe9a5daf..32cac0961c 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -367,7 +367,7 @@ optional<ClimateDeviceRestoreState> Climate::restore_state_() { return recovered; } -void Climate::save_state_() { +void Climate::save_state_(const ClimateTraits &traits) { #if (defined(USE_ESP32) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0))) && \ !defined(CLANG_TIDY) #pragma GCC diagnostic ignored "-Wclass-memaccess" @@ -382,7 +382,6 @@ void Climate::save_state_() { #endif state.mode = this->mode; - auto traits = this->get_traits(); if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { state.target_temperature_low = this->target_temperature_low; @@ -480,7 +479,7 @@ void Climate::publish_state() { ControllerRegistry::notify_climate_update(this); #endif // Save state - this->save_state_(); + this->save_state_(traits); } ClimateTraits Climate::get_traits() { diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index e2cb743c0a..0251365dd8 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -335,7 +335,8 @@ class Climate : public EntityBase { /** Internal method to save the state of the climate device to recover memory. This is automatically * called from publish_state() */ - void save_state_(); + void save_state_(const ClimateTraits &traits); + void save_state_() { this->save_state_(this->traits()); } void dump_traits_(const char *tag); From 1e2c410abfae7a1c1a78cfff62c9507f307b582f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 09:47:18 -1000 Subject: [PATCH 1731/2030] Bump cryptography from 46.0.5 to 46.0.6 (#15193) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ce735f398a..c74dd265c7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -cryptography==46.0.5 +cryptography==46.0.6 voluptuous==0.16.0 PyYAML==6.0.3 paho-mqtt==1.6.1 From 3152642571a32108c87e90390722808c65533b4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 09:48:06 -1000 Subject: [PATCH 1732/2030] Bump codecov/codecov-action from 5.5.3 to 6.0.0 (#15194) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 965e23870d..ab7a750388 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -154,7 +154,7 @@ jobs: . venv/bin/activate pytest -vv --cov-report=xml --tb=native -n auto tests --ignore=tests/integration/ - name: Upload coverage to Codecov - uses: codecov/codecov-action@1af58845a975a7985b0beb0cbe6fbbb71a41dbad # v5.5.3 + uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: token: ${{ secrets.CODECOV_TOKEN }} - name: Save Python virtual environment cache From 81f0aa1168b8b993451b3673f28bd57763148cbe Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 26 Mar 2026 20:54:50 +0100 Subject: [PATCH 1733/2030] [nextion] Replace `or`/`and` operators and missing `this->` (#15191) --- esphome/components/nextion/nextion.cpp | 2 +- .../components/nextion/nextion_upload_arduino.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index ac17e14312..612bfbc968 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -90,7 +90,7 @@ bool Nextion::check_connect_() { #endif // NEXTION_PROTOCOL_LOG ESP_LOGW(TAG, "Not connected"); - comok_sent_ = 0; + this->comok_sent_ = 0; return false; } diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index 6c454ab745..f59b708002 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -22,9 +22,9 @@ static constexpr size_t NEXTION_MAX_RESPONSE_LOG_BYTES = 16; int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { uint32_t range_size = this->tft_size_ - range_start; ESP_LOGV(TAG, "Heap: %" PRIu32, EspClass::getFreeHeap()); - uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; + uint32_t range_end = ((this->upload_first_chunk_sent_ || this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1; ESP_LOGD(TAG, "Range start: %" PRIu32, range_start); - if (range_size <= 0 or range_end <= range_start) { + if (range_size <= 0 || range_end <= range_start) { ESP_LOGE(TAG, "Invalid range end: %" PRIu32 ", size: %" PRIu32, range_end, range_size); return -1; } @@ -34,7 +34,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { ESP_LOGV(TAG, "Range: %s", range_header); http_client.addHeader("Range", range_header); int code = http_client.GET(); - if (code != HTTP_CODE_OK and code != HTTP_CODE_PARTIAL_CONTENT) { + if (code != HTTP_CODE_OK && code != HTTP_CODE_PARTIAL_CONTENT) { ESP_LOGW(TAG, "HTTP failed: %s", HTTPClient::errorToString(code).c_str()); return -1; } @@ -80,12 +80,12 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { recv_string.clear(); this->write_array(buffer, buffer_size); App.feed_wdt(); - this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true); + this->recv_ret_string_(recv_string, this->upload_first_chunk_sent_ ? 500 : 5000, true); this->content_length_ -= read_len; const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_; ESP_LOGD(TAG, "Upload: %0.2f%% (%" PRIu32 " left, heap: %" PRIu32 ")", upload_percentage, this->content_length_, EspClass::getFreeHeap()); - upload_first_chunk_sent_ = true; + this->upload_first_chunk_sent_ = true; if (recv_string.empty()) { ESP_LOGW(TAG, "No response from display during upload"); allocator.deallocate(buffer, 4096); @@ -112,7 +112,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) { allocator.deallocate(buffer, 4096); buffer = nullptr; return range_end + 1; - } else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok" + } else if (recv_string[0] != 0x05 && recv_string[0] != 0x08) { // 0x05 == "ok" char hex_buf[format_hex_pretty_size(NEXTION_MAX_RESPONSE_LOG_BYTES)]; ESP_LOGE( TAG, "Invalid response: [%s]", @@ -214,7 +214,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { ++tries; } - if (code != 200 and code != 206) { + if (code != 200 && code != 206) { ESP_LOGE(TAG, "HTTP request failed with status %d", code); return this->upload_end_(false); } From 6aafb521c15bf9a873f71392a445b1f7983234ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 26 Mar 2026 19:59:21 +0000 Subject: [PATCH 1734/2030] Bump ruff from 0.15.7 to 0.15.8 (#15192) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5e2bfe09ce..f4729f211c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.6 + rev: v0.15.8 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 1440b20333..3b277e214d 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.7 # also change in .pre-commit-config.yaml when updating +ruff==0.15.8 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From fa8a609bcc1939ec4f9d7b54dc89b54bfc8ff23a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 13:50:50 -1000 Subject: [PATCH 1735/2030] [automation] Eliminate trigger trampolines with deduplicated forwarder structs (#15174) --- esphome/automation.py | 44 +++++++++++ esphome/components/binary_sensor/__init__.py | 61 +++++---------- esphome/components/button/__init__.py | 16 +--- esphome/components/event/__init__.py | 14 +--- esphome/components/number/__init__.py | 14 +--- esphome/components/sensor/__init__.py | 34 +++----- esphome/components/switch/__init__.py | 48 +++--------- esphome/components/text_sensor/__init__.py | 38 +++------ esphome/core/automation.h | 42 +++++++++- tests/unit_tests/test_automation.py | 81 +++++++++++++++++++- 10 files changed, 226 insertions(+), 166 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index 17966dc782..7b1d6ceca1 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -137,6 +137,9 @@ UpdateComponentAction = cg.esphome_ns.class_("UpdateComponentAction", Action) SuspendComponentAction = cg.esphome_ns.class_("SuspendComponentAction", Action) ResumeComponentAction = cg.esphome_ns.class_("ResumeComponentAction", Action) Automation = cg.esphome_ns.class_("Automation") +TriggerForwarder = cg.esphome_ns.class_("TriggerForwarder") +TriggerOnTrueForwarder = cg.esphome_ns.class_("TriggerOnTrueForwarder") +TriggerOnFalseForwarder = cg.esphome_ns.class_("TriggerOnFalseForwarder") LambdaCondition = cg.esphome_ns.class_("LambdaCondition", Condition) StatelessLambdaCondition = cg.esphome_ns.class_("StatelessLambdaCondition", Condition) @@ -661,3 +664,44 @@ async def build_automation( actions = await build_action_list(config[CONF_THEN], templ, args) cg.add(obj.add_actions(actions)) return obj + + +async def build_callback_automation( + parent: MockObj, + callback_method: str, + args: TemplateArgsType, + config: ConfigType, + forwarder: MockObj | MockObjClass | None = None, +) -> None: + """Build an Automation and register it as a callback on the parent. + + Eliminates the need for a Trigger wrapper object by registering the + automation's trigger() directly as a callback on the parent component. + + Uses template forwarder structs so the compiler deduplicates the operator() + body across all call sites with the same signature. The forwarder must be + pointer-sized (single Automation* field) to fit inline in Callback::ctx_ + and avoid heap allocation. + + :param parent: The component object (e.g., button, sensor). + :param callback_method: Name of the callback method (e.g., "add_on_press_callback"). + :param args: Automation template args as list of (type, name) tuples. + :param config: The automation config dict. + :param forwarder: Optional forwarder type to use instead of the default + TriggerForwarder<Ts...>. Pass any struct type whose aggregate init takes + a single Automation pointer (e.g., TriggerOnTrueForwarder). + """ + arg_types = [arg[0] for arg in args] + templ = cg.TemplateArguments(*arg_types) + obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ) + actions = await build_action_list(config[CONF_THEN], templ, args) + cg.add(obj.add_actions(actions)) + # Use template forwarder structs for deduplication. The compiler generates + # one operator() per forwarder type; different automation pointers are just + # data in the struct. + if forwarder is None: + forwarder = TriggerForwarder.template(templ) + # RawExpression for aggregate init — both forwarder and obj are codegen + # MockObjs (not user input), and there's no Expression type for positional + # aggregate initialization (StructInitializer uses named fields). + cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}"))) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 37cccc01be..4705f1675d 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -120,10 +120,6 @@ BinarySensorInitiallyOff = binary_sensor_ns.class_( BinarySensorPtr = BinarySensor.operator("ptr") # Triggers -PressTrigger = binary_sensor_ns.class_("PressTrigger", automation.Trigger.template()) -ReleaseTrigger = binary_sensor_ns.class_( - "ReleaseTrigger", automation.Trigger.template() -) ClickTrigger = binary_sensor_ns.class_("ClickTrigger", automation.Trigger.template()) DoubleClickTrigger = binary_sensor_ns.class_( "DoubleClickTrigger", automation.Trigger.template() @@ -132,13 +128,6 @@ MultiClickTrigger = binary_sensor_ns.class_( "MultiClickTrigger", automation.Trigger.template(), cg.Component ) MultiClickTriggerEvent = binary_sensor_ns.struct("MultiClickTriggerEvent") -StateTrigger = binary_sensor_ns.class_( - "StateTrigger", automation.Trigger.template(bool) -) -StateChangeTrigger = binary_sensor_ns.class_( - "StateChangeTrigger", - automation.Trigger.template(cg.optional.template(bool), cg.optional.template(bool)), -) BinarySensorPublishAction = binary_sensor_ns.class_( "BinarySensorPublishAction", automation.Action @@ -458,16 +447,8 @@ _BINARY_SENSOR_SCHEMA = ( ): cv.boolean, cv.Optional(CONF_DEVICE_CLASS): validate_device_class, cv.Optional(CONF_FILTERS): validate_filters, - cv.Optional(CONF_ON_PRESS): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger), - } - ), - cv.Optional(CONF_ON_RELEASE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), - } - ), + cv.Optional(CONF_ON_PRESS): automation.validate_automation({}), + cv.Optional(CONF_ON_RELEASE): automation.validate_automation({}), cv.Optional(CONF_ON_CLICK): cv.All( automation.validate_automation( { @@ -509,16 +490,8 @@ _BINARY_SENSOR_SCHEMA = ( ): cv.positive_time_period_milliseconds, } ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), - } - ), - cv.Optional(CONF_ON_STATE_CHANGE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateChangeTrigger), - } - ), + cv.Optional(CONF_ON_STATE): automation.validate_automation({}), + cv.Optional(CONF_ON_STATE_CHANGE): automation.validate_automation({}), } ) ) @@ -556,13 +529,14 @@ def binary_sensor_schema( @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_binary_sensor_automations(var, config): - for conf in config.get(CONF_ON_PRESS, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - - for conf in config.get(CONF_ON_RELEASE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + for conf_key, forwarder in ( + (CONF_ON_PRESS, automation.TriggerOnTrueForwarder), + (CONF_ON_RELEASE, automation.TriggerOnFalseForwarder), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, "add_on_state_callback", [], conf, forwarder=forwarder + ) for conf in config.get(CONF_ON_CLICK, []): trigger = cg.new_Pvariable( @@ -593,13 +567,14 @@ async def _build_binary_sensor_automations(var, config): await automation.build_automation(trigger, [], conf) for conf in config.get(CONF_ON_STATE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(bool, "x")], conf) + await automation.build_callback_automation( + var, "add_on_state_callback", [(bool, "x")], conf + ) for conf in config.get(CONF_ON_STATE_CHANGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, + await automation.build_callback_automation( + var, + "add_full_state_callback", [ (cg.optional.template(bool), "x_previous"), (cg.optional.template(bool), "x"), diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index 12d9ebaba6..f279b6ffe3 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_ID, CONF_MQTT_ID, CONF_ON_PRESS, - CONF_TRIGGER_ID, CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_IDENTIFY, @@ -41,10 +40,6 @@ ButtonPtr = Button.operator("ptr") PressAction = button_ns.class_("PressAction", automation.Action) -ButtonPressTrigger = button_ns.class_( - "ButtonPressTrigger", automation.Trigger.template() -) - validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") @@ -55,11 +50,7 @@ _BUTTON_SCHEMA = ( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTButtonComponent), cv.Optional(CONF_DEVICE_CLASS): validate_device_class, - cv.Optional(CONF_ON_PRESS): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ButtonPressTrigger), - } - ), + cv.Optional(CONF_ON_PRESS): automation.validate_automation({}), } ) ) @@ -91,8 +82,9 @@ def button_schema( @setup_entity("button") async def setup_button_core_(var, config): for conf in config.get(CONF_ON_PRESS, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_press_callback", [], conf + ) setup_device_class(config) diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 300902b8ca..527bb4ebba 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_ID, CONF_MQTT_ID, CONF_ON_EVENT, - CONF_TRIGGER_ID, CONF_WEB_SERVER, DEVICE_CLASS_BUTTON, DEVICE_CLASS_DOORBELL, @@ -41,8 +40,6 @@ EventPtr = Event.operator("ptr") TriggerEventAction = event_ns.class_("TriggerEventAction", automation.Action) -EventTrigger = event_ns.class_("EventTrigger", automation.Trigger.template()) - validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") _EVENT_SCHEMA = ( @@ -53,11 +50,7 @@ _EVENT_SCHEMA = ( cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTEventComponent), cv.GenerateID(): cv.declare_id(Event), cv.Optional(CONF_DEVICE_CLASS): validate_device_class, - cv.Optional(CONF_ON_EVENT): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(EventTrigger), - } - ), + cv.Optional(CONF_ON_EVENT): automation.validate_automation({}), } ) ) @@ -92,8 +85,9 @@ def event_schema( @setup_entity("event") async def setup_event_core_(var, config, *, event_types: list[str]): for conf in config.get(CONF_ON_EVENT, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.StringRef, "event_type")], conf) + await automation.build_callback_automation( + var, "add_on_event_callback", [(cg.StringRef, "event_type")], conf + ) cg.add(var.set_event_types(event_types)) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 0570ac0b1e..90f9fe1835 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -155,9 +155,6 @@ Number = number_ns.class_("Number", cg.EntityBase) NumberPtr = Number.operator("ptr") # Triggers -NumberStateTrigger = number_ns.class_( - "NumberStateTrigger", automation.Trigger.template(cg.float_) -) ValueRangeTrigger = number_ns.class_( "ValueRangeTrigger", automation.Trigger.template(cg.float_), cg.Component ) @@ -198,11 +195,7 @@ _NUMBER_SCHEMA = ( .extend( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTNumberComponent), - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(NumberStateTrigger), - } - ), + cv.Optional(CONF_ON_VALUE): automation.validate_automation({}), cv.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), @@ -248,8 +241,9 @@ def number_schema( @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_number_automations(var, config): for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) + await automation.build_callback_automation( + var, "add_on_state_callback", [(float, "x")], conf + ) for conf in config.get(CONF_ON_VALUE_RANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await cg.register_component(trigger, conf) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 9f3c1484b0..19d03a0afc 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -238,12 +238,6 @@ Sensor = sensor_ns.class_("Sensor", cg.EntityBase) SensorPtr = Sensor.operator("ptr") # Triggers -SensorStateTrigger = sensor_ns.class_( - "SensorStateTrigger", automation.Trigger.template(cg.float_) -) -SensorRawStateTrigger = sensor_ns.class_( - "SensorRawStateTrigger", automation.Trigger.template(cg.float_) -) ValueRangeTrigger = sensor_ns.class_( "ValueRangeTrigger", automation.Trigger.template(cg.float_), cg.Component ) @@ -316,18 +310,8 @@ _SENSOR_SCHEMA = ( cv.Any(None, cv.positive_time_period_milliseconds), ), cv.Optional(CONF_FILTERS): validate_filters, - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SensorStateTrigger), - } - ), - cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - SensorRawStateTrigger - ), - } - ), + cv.Optional(CONF_ON_VALUE): automation.validate_automation({}), + cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation({}), cv.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), @@ -897,12 +881,14 @@ async def build_filters(config): @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_sensor_automations(var, config): - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(float, "x")], conf) + for conf_key, callback in ( + (CONF_ON_VALUE, "add_on_state_callback"), + (CONF_ON_RAW_VALUE, "add_on_raw_state_callback"), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, callback, [(float, "x")], conf + ) for conf in config.get(CONF_ON_VALUE_RANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await cg.register_component(trigger, conf) diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index bbafc54bd1..c4dd4856e3 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -15,7 +15,6 @@ from esphome.const import ( CONF_ON_TURN_ON, CONF_RESTORE_MODE, CONF_STATE, - CONF_TRIGGER_ID, CONF_WEB_SERVER, DEVICE_CLASS_EMPTY, DEVICE_CLASS_OUTLET, @@ -61,17 +60,6 @@ TurnOnAction = switch_ns.class_("TurnOnAction", automation.Action) SwitchPublishAction = switch_ns.class_("SwitchPublishAction", automation.Action) SwitchCondition = switch_ns.class_("SwitchCondition", Condition) -SwitchStateTrigger = switch_ns.class_( - "SwitchStateTrigger", automation.Trigger.template(bool) -) -SwitchTurnOnTrigger = switch_ns.class_( - "SwitchTurnOnTrigger", automation.Trigger.template() -) -SwitchTurnOffTrigger = switch_ns.class_( - "SwitchTurnOffTrigger", automation.Trigger.template() -) - - validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True) @@ -86,21 +74,9 @@ _SWITCH_SCHEMA = ( cv.Optional(CONF_RESTORE_MODE, default="ALWAYS_OFF"): cv.enum( RESTORE_MODES, upper=True, space="_" ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchStateTrigger), - } - ), - cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOnTrigger), - } - ), - cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOffTrigger), - } - ), + cv.Optional(CONF_ON_STATE): automation.validate_automation({}), + cv.Optional(CONF_ON_TURN_ON): automation.validate_automation({}), + cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation({}), cv.Optional(CONF_DEVICE_CLASS): validate_device_class, } ) @@ -147,15 +123,15 @@ def switch_schema( @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_switch_automations(var, config): - for conf in config.get(CONF_ON_STATE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(bool, "x")], conf) - for conf in config.get(CONF_ON_TURN_ON, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_TURN_OFF, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + for conf_key, args, forwarder in ( + (CONF_ON_STATE, [(bool, "x")], None), + (CONF_ON_TURN_ON, [], automation.TriggerOnTrueForwarder), + (CONF_ON_TURN_OFF, [], automation.TriggerOnFalseForwarder), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, "add_on_state_callback", args, conf, forwarder=forwarder + ) @setup_entity("switch") diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 97f394ecf7..51eedf9a95 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -14,7 +14,6 @@ from esphome.const import ( CONF_ON_VALUE, CONF_STATE, CONF_TO, - CONF_TRIGGER_ID, CONF_WEB_SERVER, DEVICE_CLASS_DATE, DEVICE_CLASS_EMPTY, @@ -42,12 +41,6 @@ text_sensor_ns = cg.esphome_ns.namespace("text_sensor") TextSensor = text_sensor_ns.class_("TextSensor", cg.EntityBase) TextSensorPtr = TextSensor.operator("ptr") -TextSensorStateTrigger = text_sensor_ns.class_( - "TextSensorStateTrigger", automation.Trigger.template(cg.std_string) -) -TextSensorStateRawTrigger = text_sensor_ns.class_( - "TextSensorStateRawTrigger", automation.Trigger.template(cg.std_string) -) TextSensorPublishAction = text_sensor_ns.class_( "TextSensorPublishAction", automation.Action ) @@ -150,20 +143,8 @@ _TEXT_SENSOR_SCHEMA = ( cv.GenerateID(): cv.declare_id(TextSensor), cv.Optional(CONF_DEVICE_CLASS): validate_device_class, cv.Optional(CONF_FILTERS): validate_filters, - cv.Optional(CONF_ON_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - TextSensorStateTrigger - ), - } - ), - cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - TextSensorStateRawTrigger - ), - } - ), + cv.Optional(CONF_ON_VALUE): automation.validate_automation({}), + cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation({}), } ) ) @@ -203,13 +184,14 @@ async def build_filters(config): @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_text_sensor_automations(var, config): - for conf in config.get(CONF_ON_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - - for conf in config.get(CONF_ON_RAW_VALUE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + for conf_key, callback in ( + (CONF_ON_VALUE, "add_on_state_callback"), + (CONF_ON_RAW_VALUE, "add_on_raw_state_callback"), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, callback, [(cg.std_string, "x")], conf + ) @setup_entity("text_sensor") diff --git a/esphome/core/automation.h b/esphome/core/automation.h index ca4a2c8b6b..fc2cad99be 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -470,7 +470,9 @@ template<typename... Ts> class ActionList { template<typename... Ts> class Automation { public: - explicit Automation(Trigger<Ts...> *trigger) : trigger_(trigger) { this->trigger_->set_automation_parent(this); } + /// Default constructor for use with TriggerForwarder (no Trigger object needed). + Automation() = default; + explicit Automation(Trigger<Ts...> *trigger) { trigger->set_automation_parent(this); } void add_action(Action<Ts...> *action) { this->actions_.add_action(action); } void add_actions(const std::initializer_list<Action<Ts...> *> &actions) { this->actions_.add_actions(actions); } @@ -487,8 +489,44 @@ template<typename... Ts> class Automation { int num_running() { return this->actions_.num_running(); } protected: - Trigger<Ts...> *trigger_; ActionList<Ts...> actions_; }; +/// Callback forwarder that triggers an Automation directly. +/// One operator() instantiation per Automation<Ts...> signature, shared across all call sites. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. +template<typename... Ts> struct TriggerForwarder { + Automation<Ts...> *automation; + void operator()(const Ts &...args) const { this->automation->trigger(args...); } +}; + +/// Callback forwarder that triggers an Automation<> only when the bool arg is true. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. +struct TriggerOnTrueForwarder { + Automation<> *automation; + void operator()(bool state) const { + if (state) + this->automation->trigger(); + } +}; + +/// Callback forwarder that triggers an Automation<> only when the bool arg is false. +/// Must stay pointer-sized to fit inline in Callback::ctx_ without heap allocation. +struct TriggerOnFalseForwarder { + Automation<> *automation; + void operator()(bool state) const { + if (!state) + this->automation->trigger(); + } +}; + +// Ensure forwarders fit in Callback::ctx_ (pointer-sized inline storage). +// If these fail, the forwarder would heap-allocate in Callback::create(). +static_assert(sizeof(TriggerForwarder<>) <= sizeof(void *)); +static_assert(sizeof(TriggerOnTrueForwarder) <= sizeof(void *)); +static_assert(sizeof(TriggerOnFalseForwarder) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<TriggerForwarder<>>); +static_assert(std::is_trivially_copyable_v<TriggerOnTrueForwarder>); +static_assert(std::is_trivially_copyable_v<TriggerOnFalseForwarder>); + } // namespace esphome diff --git a/tests/unit_tests/test_automation.py b/tests/unit_tests/test_automation.py index 61fef8201d..37779f23e6 100644 --- a/tests/unit_tests/test_automation.py +++ b/tests/unit_tests/test_automation.py @@ -5,7 +5,13 @@ from unittest.mock import patch import pytest -from esphome.automation import has_non_synchronous_actions +from esphome.automation import ( + TriggerForwarder, + TriggerOnFalseForwarder, + TriggerOnTrueForwarder, + has_non_synchronous_actions, +) +from esphome.cpp_generator import MockObj, RawExpression from esphome.util import RegistryEntry @@ -175,3 +181,76 @@ def test_has_non_synchronous_actions_dict_input( """Direct dict input (single action).""" assert has_non_synchronous_actions({"delay": "1s"}) is True assert has_non_synchronous_actions({"logger.log": "hello"}) is False + + +def _build_forwarder( + automation_name: str, + args: list[tuple[str, str]], + forwarder: MockObj | None = None, +) -> str: + """Build a trigger forwarder expression the same way build_callback_automation does. + + Mirrors the forwarder selection logic in automation.build_callback_automation. + """ + import esphome.codegen as cg + + obj = MockObj(automation_name, "->") + if forwarder is None: + arg_types = [RawExpression(t) for t, _ in args] + templ = ( + cg.TemplateArguments(*arg_types) if arg_types else cg.TemplateArguments() + ) + forwarder = TriggerForwarder.template(templ) + return f"{forwarder}{{{obj}}}" + + +def test_trigger_forwarder_no_args() -> None: + """Button on_press: TriggerForwarder<> with no args.""" + result = _build_forwarder("auto_1", []) + assert result == "TriggerForwarder<>{auto_1}" + + +def test_trigger_forwarder_single_float_arg() -> None: + """Sensor on_value: TriggerForwarder<float>.""" + result = _build_forwarder("auto_1", [("float", "x")]) + assert result == "TriggerForwarder<float>{auto_1}" + + +def test_trigger_forwarder_single_bool_arg() -> None: + """Switch on_state: TriggerForwarder<bool>.""" + result = _build_forwarder("auto_1", [("bool", "x")]) + assert result == "TriggerForwarder<bool>{auto_1}" + + +def test_trigger_forwarder_on_true() -> None: + """Binary_sensor on_press / switch on_turn_on: TriggerOnTrueForwarder.""" + result = _build_forwarder("auto_1", [], forwarder=TriggerOnTrueForwarder) + assert result == "TriggerOnTrueForwarder{auto_1}" + + +def test_trigger_forwarder_on_false() -> None: + """Binary_sensor on_release / switch on_turn_off: TriggerOnFalseForwarder.""" + result = _build_forwarder("auto_1", [], forwarder=TriggerOnFalseForwarder) + assert result == "TriggerOnFalseForwarder{auto_1}" + + +def test_trigger_forwarder_multiple_args() -> None: + """Binary_sensor on_state_change: TriggerForwarder with two args.""" + result = _build_forwarder( + "auto_1", + [("optional<bool>", "x_previous"), ("optional<bool>", "x")], + ) + assert result == "TriggerForwarder<optional<bool>, optional<bool>>{auto_1}" + + +def test_trigger_forwarder_string_arg() -> None: + """Text_sensor on_value: TriggerForwarder<std::string>.""" + result = _build_forwarder("auto_1", [("std::string", "x")]) + assert result == "TriggerForwarder<std::string>{auto_1}" + + +def test_trigger_forwarder_custom_type() -> None: + """Custom forwarder type passed directly.""" + custom = MockObj("MyForwarder", "") + result = _build_forwarder("auto_1", [], forwarder=custom) + assert result == "MyForwarder{auto_1}" From 240e53afce87155d12fe72a4f31117abe7ee4a13 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 14:35:09 -1000 Subject: [PATCH 1736/2030] [fan] Add benchmarks for fan component (#15210) --- tests/benchmarks/components/fan/__init__.py | 5 + tests/benchmarks/components/fan/bench_fan.cpp | 122 ++++++++++++++++++ .../benchmarks/components/fan/benchmark.yaml | 1 + 3 files changed, 128 insertions(+) create mode 100644 tests/benchmarks/components/fan/__init__.py create mode 100644 tests/benchmarks/components/fan/bench_fan.cpp create mode 100644 tests/benchmarks/components/fan/benchmark.yaml diff --git a/tests/benchmarks/components/fan/__init__.py b/tests/benchmarks/components/fan/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/fan/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/fan/bench_fan.cpp b/tests/benchmarks/components/fan/bench_fan.cpp new file mode 100644 index 0000000000..c7966c7886 --- /dev/null +++ b/tests/benchmarks/components/fan/bench_fan.cpp @@ -0,0 +1,122 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/fan/fan.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Fan for benchmarking — control() is a no-op. +class BenchFan : public fan::Fan { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + fan::FanTraits get_traits() override { return this->traits_; } + + fan::FanTraits traits_; + + protected: + void control(const fan::FanCall & /*call*/) override {} +}; + +// Helper to create a typical fan device for benchmarks. +// Note: setup() is not called (no preferences backend), so save_state_() +// is effectively a no-op. This benchmarks the call/validation path, not persistence. +static void setup_fan(BenchFan &fan) { + fan.configure("test_fan"); + fan.traits_.set_oscillation(true); + fan.traits_.set_speed(true); + fan.traits_.set_supported_speed_count(6); + fan.traits_.set_direction(true); + fan.set_restore_mode(fan::FanRestoreMode::NO_RESTORE); + fan.traits_.set_supported_preset_modes({ + "auto", + "sleep", + "nature", + "turbo", + }); +} + +// --- Fan::publish_state() with speed update --- +// Measures the publish path for a fan reporting state — +// the hot path during fan operation. + +static void FanPublish_State(benchmark::State &state) { + BenchFan fan; + setup_fan(fan); + fan.state = true; + fan.direction = fan::FanDirection::FORWARD; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + fan.speed = (i % 6) + 1; + fan.publish_state(); + } + benchmark::DoNotOptimize(fan.speed); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(FanPublish_State); + +// --- Fan::publish_state() with callback --- +// Measures callback dispatch overhead. + +static void FanPublish_WithCallback(benchmark::State &state) { + BenchFan fan; + setup_fan(fan); + fan.state = true; + + uint64_t callback_count = 0; + fan.add_on_state_callback([&callback_count]() { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + fan.speed = (i % 6) + 1; + fan.publish_state(); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(FanPublish_WithCallback); + +// --- FanCall::perform() set speed --- +// The most common fan call — adjusting the speed level. + +static void FanCall_SetSpeed(benchmark::State &state) { + BenchFan fan; + setup_fan(fan); + fan.state = true; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + int speed = (i % 6) + 1; + fan.make_call().set_speed(speed).perform(); + } + benchmark::DoNotOptimize(fan.speed); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(FanCall_SetSpeed); + +// --- FanCall::perform() with multiple fields --- +// Exercises the validation path with state, speed, oscillation, and direction. + +static void FanCall_MultiField(benchmark::State &state) { + BenchFan fan; + setup_fan(fan); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + auto dir = (i % 2 == 0) ? fan::FanDirection::FORWARD : fan::FanDirection::REVERSE; + int speed = (i % 6) + 1; + fan.make_call().set_state(true).set_speed(speed).set_oscillating(i % 2 == 0).set_direction(dir).perform(); + } + benchmark::DoNotOptimize(fan.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(FanCall_MultiField); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/fan/benchmark.yaml b/tests/benchmarks/components/fan/benchmark.yaml new file mode 100644 index 0000000000..e9d59c12b2 --- /dev/null +++ b/tests/benchmarks/components/fan/benchmark.yaml @@ -0,0 +1 @@ +fan: From 90e6c0d7c7b2174309cd5309e0e082b6526b37e5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 15:09:16 -1000 Subject: [PATCH 1737/2030] [core] Remove indirection from ControllerRegistry dispatch (#15173) --- esphome/core/controller_registry.cpp | 22 +++++++++++----------- esphome/core/controller_registry.h | 19 ++----------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/esphome/core/controller_registry.cpp b/esphome/core/controller_registry.cpp index 255efa86ba..dd69de47d4 100644 --- a/esphome/core/controller_registry.cpp +++ b/esphome/core/controller_registry.cpp @@ -10,24 +10,24 @@ StaticVector<Controller *, CONTROLLER_REGISTRY_MAX> ControllerRegistry::controll void ControllerRegistry::register_controller(Controller *controller) { controllers.push_back(controller); } -void ControllerRegistry::notify(void *obj, DispatchFunc dispatch) { - for (auto *controller : controllers) { - dispatch(controller, obj); - } -} - -// Macro for standard registry notification dispatch - calls on_<entity_name>_update() -// Each wrapper passes a small trampoline lambda that calls the correct virtual method. +// Each notify method directly iterates controllers and calls the virtual method. +// This avoids the overhead of a shared noinline dispatch loop with function pointer +// indirection. The loop is tiny (~20 bytes per entity type) so the flash cost of +// duplicating it is negligible compared to eliminating two levels of indirection +// (noinline call + function pointer) from every state publish. // NOLINTBEGIN(bugprone-macro-parentheses) #define CONTROLLER_REGISTRY_NOTIFY(entity_type, entity_name) \ void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { \ - notify(obj, [](Controller *c, void *o) { c->on_##entity_name##_update(static_cast<entity_type *>(o)); }); \ + for (auto *controller : controllers) { \ + controller->on_##entity_name##_update(obj); \ + } \ } -// Macro for entities where controller method has no "_update" suffix (Event, Update) #define CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(entity_type, entity_name) \ void ControllerRegistry::notify_##entity_name(entity_type *obj) { \ - notify(obj, [](Controller *c, void *o) { c->on_##entity_name(static_cast<entity_type *>(o)); }); \ + for (auto *controller : controllers) { \ + controller->on_##entity_name(obj); \ + } \ } // NOLINTEND(bugprone-macro-parentheses) diff --git a/esphome/core/controller_registry.h b/esphome/core/controller_registry.h index 15e3b4ba83..89b3069bcb 100644 --- a/esphome/core/controller_registry.h +++ b/esphome/core/controller_registry.h @@ -146,8 +146,8 @@ class UpdateEntity; * entities call ControllerRegistry::notify_*_update() which iterates the small list * of registered controllers (typically 2: API and WebServer). * - * Controllers read state directly from entities using existing accessors (obj->state, etc.) - * rather than receiving it as callback parameters that were being ignored anyway. + * Each notify method directly iterates controllers and calls the virtual method, + * avoiding function pointer indirection for minimal dispatch overhead. * * Memory savings: 32 bytes per entity (2 controllers × 16 bytes std::function overhead) * Typical config (25 entities): ~780 bytes saved @@ -247,21 +247,6 @@ class ControllerRegistry { #endif protected: - /** Type-erased dispatch function pointer. - * - * Each notify method passes a small trampoline that calls the - * correct virtual method on Controller. The shared notify() loop - * iterates controllers once, calling the trampoline for each. - */ - using DispatchFunc = void (*)(Controller *, void *); - - /** Shared dispatch loop - iterates controllers and calls dispatch for each. - * - * Marked noinline to ensure only one copy of the loop exists in flash, - * rather than being duplicated into each notify_*_update wrapper. - */ - static void __attribute__((noinline)) notify(void *obj, DispatchFunc dispatch); - static StaticVector<Controller *, CONTROLLER_REGISTRY_MAX> controllers; }; From e77cdb59710c5db3a904a6054ebc63035954d40e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 15:13:44 -1000 Subject: [PATCH 1738/2030] [light] Validate effect names during config validation instead of codegen (#15107) --- esphome/components/light/__init__.py | 75 +++++ esphome/components/light/automation.py | 49 ++- tests/component_tests/light/__init__.py | 0 .../light/test_effect_validation.py | 280 ++++++++++++++++++ 4 files changed, 395 insertions(+), 9 deletions(-) create mode 100644 tests/component_tests/light/__init__.py create mode 100644 tests/component_tests/light/test_effect_validation.py diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 4090ca57c2..5925afb472 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -24,6 +24,7 @@ from esphome.const import ( CONF_ID, CONF_INITIAL_STATE, CONF_MQTT_ID, + CONF_NAME, CONF_ON_STATE, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, @@ -41,6 +42,8 @@ from esphome.const import ( from esphome.core import CORE, ID, CoroPriority, HexInt, Lambda, coroutine_with_priority from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity from esphome.cpp_generator import MockObjClass +import esphome.final_validate as fv +from esphome.types import ConfigType from .automation import LIGHT_STATE_SCHEMA from .effects import ( @@ -70,9 +73,19 @@ IS_PLATFORM_COMPONENT = True DOMAIN = "light" +@dataclass +class EffectRef: + """A pending effect name reference from a light action to validate.""" + + light_id: ID + effect_name: str + component_path: list[str | int] # path_context when the action was validated + + @dataclass class LightData: gamma_tables: dict = field(default_factory=dict) # gamma_value -> fwd_arr + effect_refs: list[EffectRef] = field(default_factory=list) def _get_data() -> LightData: @@ -115,6 +128,68 @@ def _get_or_create_gamma_table(gamma_correct): return fwd_arr +def find_effect_index(effects: list, effect_name: str) -> int | None: + """Find the 1-based index of an effect by name (case-insensitive). + + Returns the 1-based index if found, or None if not found. + """ + effect_name_lower = effect_name.lower() + for i, effect_conf in enumerate(effects): + key = next(iter(effect_conf)) + if effect_conf[key][CONF_NAME].lower() == effect_name_lower: + return i + 1 + return None + + +def available_effects_str(effects: list) -> str: + """Return a comma-separated string of available effect names.""" + available = [ + effect_conf[next(iter(effect_conf))][CONF_NAME] for effect_conf in effects + ] + return ", ".join(f"'{name}'" for name in available) if available else "none" + + +def _final_validate(config: ConfigType) -> ConfigType: + """Validate all recorded effect name references against their target lights. + + This runs once per light platform instance. If no light platform is configured, + this never runs — but the ID validator will catch the missing light ID separately. + """ + data = _get_data() + if not data.effect_refs: + return config + + # Drain the list so we only validate once even though + # FINAL_VALIDATE_SCHEMA runs for each light platform instance. + refs = data.effect_refs + data.effect_refs = [] + + fconf = fv.full_config.get() + + for ref in refs: + try: + light_path = fconf.get_path_for_id(ref.light_id)[:-1] + light_config = fconf.get_config_for_path(light_path) + except KeyError: + # Light ID not found — ID validation will have already reported this + continue + + effects = light_config.get(CONF_EFFECTS, []) + + if find_effect_index(effects, ref.effect_name) is None: + raise cv.FinalExternalInvalid( + f"Effect '{ref.effect_name}' not found for light " + f"'{ref.light_id}'. " + f"Available effects: {available_effects_str(effects)}", + path=[cv.ROOT_CONFIG_PATH] + ref.component_path, + ) + + return config + + +FINAL_VALIDATE_SCHEMA = _final_validate + + LightRestoreMode = light_ns.enum("LightRestoreMode") RESTORE_MODES = { "RESTORE_DEFAULT_OFF": LightRestoreMode.LIGHT_RESTORE_DEFAULT_OFF, diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 55273003b9..16e7d72f6b 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -1,5 +1,6 @@ from esphome import automation import esphome.codegen as cg +from esphome.config import path_context import esphome.config_validation as cv from esphome.const import ( CONF_BLUE, @@ -17,7 +18,6 @@ from esphome.const import ( CONF_LIMIT_MODE, CONF_MAX_BRIGHTNESS, CONF_MIN_BRIGHTNESS, - CONF_NAME, CONF_RANGE_FROM, CONF_RANGE_TO, CONF_RED, @@ -26,7 +26,7 @@ from esphome.const import ( CONF_WARM_WHITE, CONF_WHITE, ) -from esphome.core import CORE, Lambda +from esphome.core import CORE, EsphomeError, Lambda from esphome.cpp_generator import LambdaExpression from esphome.types import ConfigType @@ -98,6 +98,31 @@ LIGHT_CONTROL_ACTION_SCHEMA = LIGHT_STATE_SCHEMA.extend( } ) + +def _record_effect_ref(config: ConfigType) -> ConfigType: + """Record a static effect name reference for later cross-component validation.""" + if CONF_EFFECT not in config: + return config + effect = config[CONF_EFFECT] + if isinstance(effect, Lambda): + return config # Lambda effects resolved at runtime + if effect.lower() == "none": + return config # "None" is always valid + + from . import EffectRef, _get_data + + _get_data().effect_refs.append( + EffectRef( + light_id=config[CONF_ID], + effect_name=effect, + component_path=path_context.get(), + ) + ) + return config + + +LIGHT_CONTROL_ACTION_SCHEMA.add_extra(_record_effect_ref) + LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id( { cv.Required(CONF_ID): cv.use_id(LightState), @@ -122,18 +147,24 @@ def _resolve_effect_index(config: ConfigType) -> int: Effect index 0 means "None" (no effect). Effects are 1-indexed matching the C++ convention in LightState. """ + from . import available_effects_str, find_effect_index + original_name = config[CONF_EFFECT] - effect_name = original_name.lower() - if effect_name == "none": + if original_name.lower() == "none": return 0 light_id = config[CONF_ID] light_path = CORE.config.get_path_for_id(light_id)[:-1] light_config = CORE.config.get_config_for_path(light_path) - for i, effect_conf in enumerate(light_config.get(CONF_EFFECTS, [])): - key = next(iter(effect_conf)) - if effect_conf[key][CONF_NAME].lower() == effect_name: - return i + 1 - raise ValueError(f"Effect '{original_name}' not found in light '{light_id}'") + effects = light_config.get(CONF_EFFECTS, []) + index = find_effect_index(effects, original_name) + if index is not None: + return index + # Should never reach here — effect names are validated during config + # validation in FINAL_VALIDATE_SCHEMA. This is a safety net. + raise EsphomeError( + f"Effect '{original_name}' not found for light '{light_id}'. " + f"Available effects: {available_effects_str(effects)}" + ) @automation.register_action( diff --git a/tests/component_tests/light/__init__.py b/tests/component_tests/light/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/light/test_effect_validation.py b/tests/component_tests/light/test_effect_validation.py new file mode 100644 index 0000000000..579e92c62a --- /dev/null +++ b/tests/component_tests/light/test_effect_validation.py @@ -0,0 +1,280 @@ +"""Tests for light effect name validation.""" + +from __future__ import annotations + +from collections.abc import Generator +from contextvars import Token + +import pytest + +from esphome import config_validation as cv +from esphome.components.light import ( + EffectRef, + _final_validate, + _get_data, + available_effects_str, + find_effect_index, +) +from esphome.components.light.automation import _record_effect_ref +from esphome.config import Config, path_context +from esphome.const import CONF_EFFECT, CONF_EFFECTS, CONF_ID, CONF_NAME +from esphome.core import ID, Lambda +import esphome.final_validate as fv +from esphome.types import ConfigType + + +def _make_effects(*names: str) -> list[dict[str, dict[str, str]]]: + """Create a list of effect config dicts from names.""" + return [{f"effect_{i}": {CONF_NAME: name}} for i, name in enumerate(names)] + + +# --- find_effect_index --- + + +def test_find_effect_index_found() -> None: + effects = _make_effects("Fast Pulse", "Slow Pulse") + assert find_effect_index(effects, "Fast Pulse") == 1 + assert find_effect_index(effects, "Slow Pulse") == 2 + + +def test_find_effect_index_case_insensitive() -> None: + effects = _make_effects("Fast Pulse") + assert find_effect_index(effects, "fast pulse") == 1 + assert find_effect_index(effects, "FAST PULSE") == 1 + + +def test_find_effect_index_not_found() -> None: + effects = _make_effects("Fast Pulse", "Slow Pulse") + assert find_effect_index(effects, "Missing") is None + + +def test_find_effect_index_empty() -> None: + assert find_effect_index([], "anything") is None + + +# --- available_effects_str --- + + +def test_available_effects_str_multiple() -> None: + effects = _make_effects("Fast Pulse", "Slow Pulse") + assert available_effects_str(effects) == "'Fast Pulse', 'Slow Pulse'" + + +def test_available_effects_str_single() -> None: + effects = _make_effects("Fast Pulse") + assert available_effects_str(effects) == "'Fast Pulse'" + + +def test_available_effects_str_empty() -> None: + assert available_effects_str([]) == "none" + + +# --- _final_validate --- + + +def _setup_final_validate( + effect_refs: list[EffectRef], + light_configs: list[ConfigType], + declare_ids: list[tuple[ID, list[str | int]]], +) -> Token: + """Set up CORE.data and fv.full_config for _final_validate tests.""" + data = _get_data() + data.effect_refs = effect_refs + + full_conf = Config() + full_conf["light"] = light_configs + for id_, path in declare_ids: + full_conf.declare_ids.append((id_, path)) + + return fv.full_config.set(full_conf) + + +def test_final_validate_valid_effect() -> None: + """Valid effect name should not raise.""" + light_id = ID("led1", is_declaration=True) + token = _setup_final_validate( + effect_refs=[ + EffectRef( + light_id=light_id, effect_name="Fast Pulse", component_path=["esphome"] + ), + ], + light_configs=[ + {CONF_ID: light_id, CONF_EFFECTS: _make_effects("Fast Pulse", "Slow Pulse")} + ], + declare_ids=[(light_id, ["light", 0, CONF_ID])], + ) + try: + _final_validate({}) + finally: + fv.full_config.reset(token) + + +def test_final_validate_invalid_effect_raises() -> None: + """Invalid effect name should raise FinalExternalInvalid.""" + light_id = ID("led1", is_declaration=True) + token = _setup_final_validate( + effect_refs=[ + EffectRef( + light_id=light_id, effect_name="Nonexistent", component_path=["esphome"] + ), + ], + light_configs=[ + {CONF_ID: light_id, CONF_EFFECTS: _make_effects("Fast Pulse", "Slow Pulse")} + ], + declare_ids=[(light_id, ["light", 0, CONF_ID])], + ) + try: + with pytest.raises(cv.FinalExternalInvalid, match="Nonexistent"): + _final_validate({}) + finally: + fv.full_config.reset(token) + + +def test_final_validate_lists_available_effects() -> None: + """Error message should list available effects.""" + light_id = ID("led1", is_declaration=True) + token = _setup_final_validate( + effect_refs=[ + EffectRef( + light_id=light_id, effect_name="Missing", component_path=["esphome"] + ), + ], + light_configs=[ + {CONF_ID: light_id, CONF_EFFECTS: _make_effects("Fast Pulse", "Slow Pulse")} + ], + declare_ids=[(light_id, ["light", 0, CONF_ID])], + ) + try: + with pytest.raises(cv.FinalExternalInvalid, match="'Fast Pulse', 'Slow Pulse'"): + _final_validate({}) + finally: + fv.full_config.reset(token) + + +def test_final_validate_no_effects_on_light() -> None: + """Light with no effects should report 'none' as available.""" + light_id = ID("led1", is_declaration=True) + token = _setup_final_validate( + effect_refs=[ + EffectRef( + light_id=light_id, effect_name="Missing", component_path=["esphome"] + ), + ], + light_configs=[{CONF_ID: light_id}], + declare_ids=[(light_id, ["light", 0, CONF_ID])], + ) + try: + with pytest.raises(cv.FinalExternalInvalid, match="Available effects: none"): + _final_validate({}) + finally: + fv.full_config.reset(token) + + +def test_final_validate_no_refs_is_noop() -> None: + """No stored refs should pass without error.""" + data = _get_data() + data.effect_refs = [] + _final_validate({}) + + +def test_final_validate_unknown_light_id_skipped() -> None: + """Refs to unknown light IDs should be silently skipped.""" + data = _get_data() + data.effect_refs = [ + EffectRef( + light_id=ID("nonexistent", is_declaration=True), + effect_name="Missing", + component_path=["esphome"], + ) + ] + + full_conf = Config() + token = fv.full_config.set(full_conf) + try: + _final_validate({}) + finally: + fv.full_config.reset(token) + + +def test_final_validate_drains_refs() -> None: + """Refs should be drained after validation to avoid redundant runs.""" + light_id = ID("led1", is_declaration=True) + token = _setup_final_validate( + effect_refs=[ + EffectRef( + light_id=light_id, effect_name="Fast Pulse", component_path=["esphome"] + ), + ], + light_configs=[{CONF_ID: light_id, CONF_EFFECTS: _make_effects("Fast Pulse")}], + declare_ids=[(light_id, ["light", 0, CONF_ID])], + ) + try: + _final_validate({}) + assert _get_data().effect_refs == [] + finally: + fv.full_config.reset(token) + + +# --- _record_effect_ref --- + + +@pytest.fixture +def _path_ctx() -> Generator[None]: + """Set path_context for _record_effect_ref tests.""" + token = path_context.set(["esphome"]) + yield + path_context.reset(token) + + +@pytest.mark.usefixtures("_path_ctx") +def test_record_effect_ref_static() -> None: + """Static effect name should be recorded.""" + light_id = ID("led1", is_declaration=True) + config: ConfigType = {CONF_ID: light_id, CONF_EFFECT: "Fast Pulse"} + result = _record_effect_ref(config) + assert result is config + data = _get_data() + assert len(data.effect_refs) == 1 + assert data.effect_refs[0].effect_name == "Fast Pulse" + assert data.effect_refs[0].light_id is light_id + assert data.effect_refs[0].component_path == ["esphome"] + + +@pytest.mark.usefixtures("_path_ctx") +def test_record_effect_ref_skips_lambda() -> None: + """Lambda effect should not be recorded.""" + config: ConfigType = { + CONF_ID: ID("led1", is_declaration=True), + CONF_EFFECT: Lambda("return effect;"), + } + _record_effect_ref(config) + assert _get_data().effect_refs == [] + + +@pytest.mark.usefixtures("_path_ctx") +def test_record_effect_ref_skips_none() -> None: + """Effect 'None' should not be recorded.""" + config: ConfigType = { + CONF_ID: ID("led1", is_declaration=True), + CONF_EFFECT: "None", + } + _record_effect_ref(config) + assert _get_data().effect_refs == [] + + +@pytest.mark.usefixtures("_path_ctx") +def test_record_effect_ref_skips_none_case_insensitive() -> None: + """Effect 'none' (lowercase) should not be recorded.""" + config: ConfigType = { + CONF_ID: ID("led1", is_declaration=True), + CONF_EFFECT: "none", + } + _record_effect_ref(config) + assert _get_data().effect_refs == [] + + +def test_record_effect_ref_skips_no_effect_key() -> None: + """Config without effect key should be a no-op.""" + config: ConfigType = {CONF_ID: ID("led1", is_declaration=True)} + _record_effect_ref(config) + assert _get_data().effect_refs == [] From 90dafa3fa45bc5b279136f069030e1ea4edde780 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 26 Mar 2026 15:59:58 -1000 Subject: [PATCH 1739/2030] [logger] Warn when VERBOSE/VERY_VERBOSE logging is active (#15189) --- esphome/components/logger/logger.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/esphome/components/logger/logger.cpp b/esphome/components/logger/logger.cpp index cd6543bfb8..23b69c36c6 100644 --- a/esphome/components/logger/logger.cpp +++ b/esphome/components/logger/logger.cpp @@ -243,6 +243,16 @@ void Logger::dump_config() { #endif #ifdef USE_ZEPHYR dump_crash_(); +#endif + // Warn users that VERBOSE/VERY_VERBOSE logging impacts performance. + // Only the compiled log level matters — all log calls up to this level + // are in the binary and will be formatted (vsnprintf) and block UART. +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + ESP_LOGW(TAG, "VERY_VERBOSE logging is active — significant performance impact, short-term debugging only\n" + " May cause connection instability. Set log level to DEBUG or lower for long-term use."); +#elif ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + ESP_LOGI(TAG, "VERBOSE logging is active — performance impact, short-term debugging only\n" + " Set log level to DEBUG or lower for long-term use."); #endif } From 6feb2d04dfd61c3fe1d03980fe1516b846eacf6b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Mar 2026 04:36:35 +0100 Subject: [PATCH 1740/2030] [nextion] Replace `static std::string COMMAND_DELIMITER` with `constexpr` (#15195) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 13 +++++++++---- esphome/components/nextion/nextion.h | 2 -- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 612bfbc968..fa1582c209 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -10,6 +10,10 @@ namespace nextion { static const char *const TAG = "nextion"; +// Nextion command terminator: three consecutive 0xFF bytes (per Nextion Instruction Set v1.1). +static constexpr uint8_t COMMAND_DELIMITER[3] = {0xFF, 0xFF, 0xFF}; +static constexpr size_t DELIMITER_SIZE = sizeof(COMMAND_DELIMITER); + void Nextion::setup() { this->is_setup_ = false; this->connection_state_.ignore_is_setup_ = true; @@ -415,7 +419,8 @@ void Nextion::process_nextion_commands_() { #ifdef NEXTION_PROTOCOL_LOG this->print_queue_members_(); #endif - while ((to_process_length = this->command_data_.find(COMMAND_DELIMITER)) != std::string::npos) { + while ((to_process_length = this->command_data_.find(reinterpret_cast<const char *>(COMMAND_DELIMITER), 0, + DELIMITER_SIZE)) != std::string::npos) { #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP if (++commands_processed > this->max_commands_per_loop_) { ESP_LOGW(TAG, "Command processing limit exceeded"); @@ -423,8 +428,8 @@ void Nextion::process_nextion_commands_() { } #endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP ESP_LOGN(TAG, "queue size: %zu", this->nextion_queue_.size()); - while (to_process_length + COMMAND_DELIMITER.length() < this->command_data_.length() && - static_cast<uint8_t>(this->command_data_[to_process_length + COMMAND_DELIMITER.length()]) == 0xFF) { + while (to_process_length + DELIMITER_SIZE < this->command_data_.length() && + static_cast<uint8_t>(this->command_data_[to_process_length + DELIMITER_SIZE]) == 0xFF) { ++to_process_length; ESP_LOGN(TAG, "Add 0xFF"); } @@ -829,7 +834,7 @@ void Nextion::process_nextion_commands_() { break; } - this->command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1); + this->command_data_.erase(0, to_process_length + DELIMITER_SIZE + 1); } const uint32_t ms = App.get_loop_component_start_time(); diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index bb5998cf5d..217d2e605d 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -29,8 +29,6 @@ class NextionComponentBase; using nextion_writer_t = display::DisplayWriter<Nextion>; -static const std::string COMMAND_DELIMITER{static_cast<char>(255), static_cast<char>(255), static_cast<char>(255)}; - #ifdef USE_NEXTION_COMMAND_SPACING class NextionCommandPacer { public: From 2d9922496cd94ed43a0a5eec7193ff9f581c48a8 Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:02:45 +0100 Subject: [PATCH 1741/2030] [git] Add support for subpath to computed destination directory (#15135) --- esphome/git.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/esphome/git.py b/esphome/git.py index a45768b5cd..096ff483a7 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -102,6 +102,7 @@ def clone_or_update( username: str = None, password: str = None, submodules: list[str] | None = None, + subpath: Path | None = None, _recover_broken: bool = True, ) -> tuple[Path, Callable[[], None] | None]: key = f"{url}@{ref}" @@ -112,6 +113,9 @@ def clone_or_update( ) repo_dir = _compute_destination_path(key, domain) + if subpath: + repo_dir = repo_dir / subpath + if not repo_dir.is_dir(): _LOGGER.info("Cloning %s", key) _LOGGER.debug("Location: %s", repo_dir) From 73e939ffb5fa41be407812fa069be76f45d968e6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:13:24 -0400 Subject: [PATCH 1742/2030] [sgp4x] Fix NOx index_offset default (should be 1, not 100) (#15212) --- esphome/components/sgp4x/sensor.py | 39 ++++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/esphome/components/sgp4x/sensor.py b/esphome/components/sgp4x/sensor.py index ab78ab59d9..8d52ffb4f2 100644 --- a/esphome/components/sgp4x/sensor.py +++ b/esphome/components/sgp4x/sensor.py @@ -44,20 +44,27 @@ def validate_sensors(config): return config -GAS_SENSOR = cv.Schema( - { - cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema( - { - cv.Optional(CONF_INDEX_OFFSET, default=100): cv.int_, - cv.Optional(CONF_LEARNING_TIME_OFFSET_HOURS, default=12): cv.int_, - cv.Optional(CONF_LEARNING_TIME_GAIN_HOURS, default=12): cv.int_, - cv.Optional(CONF_GATING_MAX_DURATION_MINUTES, default=720): cv.int_, - cv.Optional(CONF_STD_INITIAL, default=50): cv.int_, - cv.Optional(CONF_GAIN_FACTOR, default=230): cv.int_, - } - ) - } -) +def _gas_sensor_schema(index_offset_default: int): + return cv.Schema( + { + cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema( + { + cv.Optional( + CONF_INDEX_OFFSET, default=index_offset_default + ): cv.int_, + cv.Optional(CONF_LEARNING_TIME_OFFSET_HOURS, default=12): cv.int_, + cv.Optional(CONF_LEARNING_TIME_GAIN_HOURS, default=12): cv.int_, + cv.Optional(CONF_GATING_MAX_DURATION_MINUTES, default=720): cv.int_, + cv.Optional(CONF_STD_INITIAL, default=50): cv.int_, + cv.Optional(CONF_GAIN_FACTOR, default=230): cv.int_, + } + ) + } + ) + + +VOC_SENSOR = _gas_sensor_schema(100) +NOX_SENSOR = _gas_sensor_schema(1) CONFIG_SCHEMA = cv.All( cv.Schema( @@ -68,13 +75,13 @@ CONFIG_SCHEMA = cv.All( accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, - ).extend(GAS_SENSOR), + ).extend(VOC_SENSOR), cv.Optional(CONF_NOX): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, - ).extend(GAS_SENSOR), + ).extend(NOX_SENSOR), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, cv.Optional(CONF_VOC_BASELINE): cv.hex_uint16_t, cv.Optional(CONF_COMPENSATION): cv.Schema( From 1e65165e48274acfd30a8cfd18867608b6dff414 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:19:58 -1000 Subject: [PATCH 1743/2030] [safe_mode] Migrate SafeModeTrigger to callback automation (#15197) --- esphome/components/safe_mode/__init__.py | 13 ++++--------- esphome/components/safe_mode/automation.h | 10 ---------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index e868985054..da36d21eb7 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -7,7 +7,6 @@ from esphome.const import ( CONF_NUM_ATTEMPTS, CONF_REBOOT_TIMEOUT, CONF_SAFE_MODE, - CONF_TRIGGER_ID, KEY_PAST_SAFE_MODE, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority @@ -20,7 +19,6 @@ CONF_ON_SAFE_MODE = "on_safe_mode" safe_mode_ns = cg.esphome_ns.namespace("safe_mode") SafeModeComponent = safe_mode_ns.class_("SafeModeComponent", cg.Component) -SafeModeTrigger = safe_mode_ns.class_("SafeModeTrigger", automation.Trigger.template()) MarkSuccessfulAction = safe_mode_ns.class_("MarkSuccessfulAction", automation.Action) @@ -43,11 +41,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_REBOOT_TIMEOUT, default="5min" ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_ON_SAFE_MODE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SafeModeTrigger), - } - ), + cv.Optional(CONF_ON_SAFE_MODE): automation.validate_automation({}), } ).extend(cv.COMPONENT_SCHEMA), _remove_id_if_disabled, @@ -80,8 +74,9 @@ async def to_code(config): if on_safe_mode_config := config.get(CONF_ON_SAFE_MODE): cg.add_define("USE_SAFE_MODE_CALLBACK") for conf in on_safe_mode_config: - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_safe_mode_callback", [], conf + ) condition = var.should_enter_safe_mode( config[CONF_NUM_ATTEMPTS], diff --git a/esphome/components/safe_mode/automation.h b/esphome/components/safe_mode/automation.h index dee02c64a0..79b53c0881 100644 --- a/esphome/components/safe_mode/automation.h +++ b/esphome/components/safe_mode/automation.h @@ -1,19 +1,9 @@ #pragma once -#include "esphome/core/defines.h" #include "esphome/core/automation.h" #include "safe_mode.h" namespace esphome::safe_mode { -#ifdef USE_SAFE_MODE_CALLBACK -class SafeModeTrigger final : public Trigger<> { - public: - explicit SafeModeTrigger(SafeModeComponent *parent) { - parent->add_on_safe_mode_callback([this]() { trigger(); }); - } -}; -#endif // USE_SAFE_MODE_CALLBACK - template<typename... Ts> class MarkSuccessfulAction : public Action<Ts...>, public Parented<SafeModeComponent> { public: void play(const Ts &...x) override { this->parent_->mark_successful(); } From b0f6a94df51a40c163627aa7e12a1c3947369573 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:20:11 -1000 Subject: [PATCH 1744/2030] [sml] Migrate DataTrigger to callback automation (#15233) --- esphome/components/sml/__init__.py | 23 +++++------------------ esphome/components/sml/automation.h | 19 ------------------- 2 files changed, 5 insertions(+), 37 deletions(-) delete mode 100644 esphome/components/sml/automation.h diff --git a/esphome/components/sml/__init__.py b/esphome/components/sml/__init__.py index eaeddce390..1bf0d97d65 100644 --- a/esphome/components/sml/__init__.py +++ b/esphome/components/sml/__init__.py @@ -4,7 +4,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_ON_DATA, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_ON_DATA CODEOWNERS = ["@alengwenus"] @@ -18,24 +18,11 @@ CONF_SML_ID = "sml_id" CONF_OBIS_CODE = "obis_code" CONF_SERVER_ID = "server_id" -sml_ns = cg.esphome_ns.namespace("sml") - -DataTrigger = sml_ns.class_( - "DataTrigger", - automation.Trigger.template( - cg.std_vector.template(cg.uint8).operator("ref"), cg.bool_ - ), -) - CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(Sml), - cv.Optional(CONF_ON_DATA): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DataTrigger), - } - ), + cv.Optional(CONF_ON_DATA): automation.validate_automation({}), } ).extend(uart.UART_DEVICE_SCHEMA) @@ -45,9 +32,9 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_DATA, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, + await automation.build_callback_automation( + var, + "add_on_data_callback", [ ( cg.std_vector.template(cg.uint8).operator("ref").operator("const"), diff --git a/esphome/components/sml/automation.h b/esphome/components/sml/automation.h deleted file mode 100644 index d51063065d..0000000000 --- a/esphome/components/sml/automation.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "esphome/core/automation.h" -#include "sml.h" - -#include <vector> - -namespace esphome { -namespace sml { - -class DataTrigger : public Trigger<const std::vector<uint8_t> &, bool> { - public: - explicit DataTrigger(Sml *sml) { - sml->add_on_data_callback([this](const std::vector<uint8_t> &data, bool valid) { this->trigger(data, valid); }); - } -}; - -} // namespace sml -} // namespace esphome From b41634e19af272b8c146d3912edf2cba3191b2eb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:20:24 -1000 Subject: [PATCH 1745/2030] [alarm_control_panel] Migrate triggers to callback automation (#15198) --- .../alarm_control_panel/__init__.py | 162 +++++------------- .../alarm_control_panel.cpp | 4 +- .../alarm_control_panel/alarm_control_panel.h | 4 +- .../alarm_control_panel/automation.h | 69 ++------ .../mqtt/mqtt_alarm_control_panel.cpp | 3 +- 5 files changed, 68 insertions(+), 174 deletions(-) diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index aefb18d25c..4ee073a15b 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_ID, CONF_MQTT_ID, CONF_ON_STATE, - CONF_TRIGGER_ID, CONF_WEB_SERVER, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority @@ -34,39 +33,9 @@ CONF_ON_READY = "on_ready" alarm_control_panel_ns = cg.esphome_ns.namespace("alarm_control_panel") AlarmControlPanel = alarm_control_panel_ns.class_("AlarmControlPanel", cg.EntityBase) -StateTrigger = alarm_control_panel_ns.class_( - "StateTrigger", automation.Trigger.template() -) -TriggeredTrigger = alarm_control_panel_ns.class_( - "TriggeredTrigger", automation.Trigger.template() -) -ClearedTrigger = alarm_control_panel_ns.class_( - "ClearedTrigger", automation.Trigger.template() -) -ArmingTrigger = alarm_control_panel_ns.class_( - "ArmingTrigger", automation.Trigger.template() -) -PendingTrigger = alarm_control_panel_ns.class_( - "PendingTrigger", automation.Trigger.template() -) -ArmedHomeTrigger = alarm_control_panel_ns.class_( - "ArmedHomeTrigger", automation.Trigger.template() -) -ArmedNightTrigger = alarm_control_panel_ns.class_( - "ArmedNightTrigger", automation.Trigger.template() -) -ArmedAwayTrigger = alarm_control_panel_ns.class_( - "ArmedAwayTrigger", automation.Trigger.template() -) -DisarmedTrigger = alarm_control_panel_ns.class_( - "DisarmedTrigger", automation.Trigger.template() -) -ChimeTrigger = alarm_control_panel_ns.class_( - "ChimeTrigger", automation.Trigger.template() -) -ReadyTrigger = alarm_control_panel_ns.class_( - "ReadyTrigger", automation.Trigger.template() -) +StateAnyForwarder = alarm_control_panel_ns.class_("StateAnyForwarder") +StateEnterForwarder = alarm_control_panel_ns.class_("StateEnterForwarder") +AlarmControlPanelState = alarm_control_panel_ns.enum("AlarmControlPanelState") ArmAwayAction = alarm_control_panel_ns.class_("ArmAwayAction", automation.Action) ArmHomeAction = alarm_control_panel_ns.class_("ArmHomeAction", automation.Action) @@ -89,61 +58,17 @@ _ALARM_CONTROL_PANEL_SCHEMA = ( cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( mqtt.MQTTAlarmControlPanelComponent ), - cv.Optional(CONF_ON_STATE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), - } - ), - cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger), - } - ), - cv.Optional(CONF_ON_ARMING): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger), - } - ), - cv.Optional(CONF_ON_PENDING): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger), - } - ), - cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger), - } - ), - cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger), - } - ), - cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger), - } - ), - cv.Optional(CONF_ON_DISARMED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger), - } - ), - cv.Optional(CONF_ON_CLEARED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger), - } - ), - cv.Optional(CONF_ON_CHIME): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChimeTrigger), - } - ), - cv.Optional(CONF_ON_READY): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReadyTrigger), - } - ), + cv.Optional(CONF_ON_STATE): automation.validate_automation({}), + cv.Optional(CONF_ON_TRIGGERED): automation.validate_automation({}), + cv.Optional(CONF_ON_ARMING): automation.validate_automation({}), + cv.Optional(CONF_ON_PENDING): automation.validate_automation({}), + cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation({}), + cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation({}), + cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation({}), + cv.Optional(CONF_ON_DISARMED): automation.validate_automation({}), + cv.Optional(CONF_ON_CLEARED): automation.validate_automation({}), + cv.Optional(CONF_ON_CHIME): automation.validate_automation({}), + cv.Optional(CONF_ON_READY): automation.validate_automation({}), } ) ) @@ -189,38 +114,39 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id( @setup_entity("alarm_control_panel") async def setup_alarm_control_panel_core_(var, config): for conf in config.get(CONF_ON_STATE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_TRIGGERED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_ARMING, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_PENDING, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_ARMED_HOME, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_ARMED_NIGHT, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_ARMED_AWAY, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_DISARMED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_state_callback", [], conf, forwarder=StateAnyForwarder + ) + _STATE_ENTER_MAP = { + CONF_ON_TRIGGERED: AlarmControlPanelState.ACP_STATE_TRIGGERED, + CONF_ON_ARMING: AlarmControlPanelState.ACP_STATE_ARMING, + CONF_ON_PENDING: AlarmControlPanelState.ACP_STATE_PENDING, + CONF_ON_ARMED_HOME: AlarmControlPanelState.ACP_STATE_ARMED_HOME, + CONF_ON_ARMED_NIGHT: AlarmControlPanelState.ACP_STATE_ARMED_NIGHT, + CONF_ON_ARMED_AWAY: AlarmControlPanelState.ACP_STATE_ARMED_AWAY, + CONF_ON_DISARMED: AlarmControlPanelState.ACP_STATE_DISARMED, + } + for conf_key, state_enum in _STATE_ENTER_MAP.items(): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, + "add_on_state_callback", + [], + conf, + forwarder=StateEnterForwarder.template(state_enum), + ) for conf in config.get(CONF_ON_CLEARED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_cleared_callback", [], conf + ) for conf in config.get(CONF_ON_CHIME, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_chime_callback", [], conf + ) for conf in config.get(CONF_ON_READY, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_ready_callback", [], conf + ) if web_server_config := config.get(CONF_WEB_SERVER): await web_server.add_entity_config(var, web_server_config) if mqtt_id := config.get(CONF_MQTT_ID): diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 623241851a..fc72c13ce3 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -35,8 +35,8 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { LOG_STR_ARG(alarm_control_panel_state_to_string(state)), LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state))); this->current_state_ = state; - // Single state callback - triggers check get_state() for specific states - this->state_callback_.call(); + // Single state callback - listeners receive the new state as an argument + this->state_callback_.call(state); #if defined(USE_ALARM_CONTROL_PANEL) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_alarm_control_panel_update(this); #endif diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.h b/esphome/components/alarm_control_panel/alarm_control_panel.h index cf99d359e7..e748b8621b 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel.h @@ -145,8 +145,8 @@ class AlarmControlPanel : public EntityBase { uint32_t last_update_; // the call control function virtual void control(const AlarmControlPanelCall &call) = 0; - // state callback - triggers check get_state() for specific state - LazyCallbackManager<void()> state_callback_{}; + // state callback - passes the new state to listeners + LazyCallbackManager<void(AlarmControlPanelState)> state_callback_{}; // clear callback - fires when leaving TRIGGERED state LazyCallbackManager<void()> cleared_callback_{}; // chime callback diff --git a/esphome/components/alarm_control_panel/automation.h b/esphome/components/alarm_control_panel/automation.h index 4ff34de0d5..022d2650d2 100644 --- a/esphome/components/alarm_control_panel/automation.h +++ b/esphome/components/alarm_control_panel/automation.h @@ -5,60 +5,27 @@ namespace esphome::alarm_control_panel { -/// Trigger on any state change -class StateTrigger : public Trigger<> { - public: - explicit StateTrigger(AlarmControlPanel *alarm_control_panel) { - alarm_control_panel->add_on_state_callback([this]() { this->trigger(); }); +/// Callback forwarder that triggers an Automation<> on any state change. +/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_. +struct StateAnyForwarder { + Automation<> *automation; + void operator()(AlarmControlPanelState /*state*/) const { this->automation->trigger(); } +}; + +/// Callback forwarder that triggers an Automation<> only when the alarm enters a specific state. +/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_. +template<AlarmControlPanelState State> struct StateEnterForwarder { + Automation<> *automation; + void operator()(AlarmControlPanelState state) const { + if (state == State) + this->automation->trigger(); } }; -/// Template trigger that fires when entering a specific state -template<AlarmControlPanelState State> class StateEnterTrigger : public Trigger<> { - public: - explicit StateEnterTrigger(AlarmControlPanel *alarm_control_panel) : alarm_control_panel_(alarm_control_panel) { - alarm_control_panel->add_on_state_callback([this]() { - if (this->alarm_control_panel_->get_state() == State) - this->trigger(); - }); - } - - protected: - AlarmControlPanel *alarm_control_panel_; -}; - -// Type aliases for state-specific triggers -using TriggeredTrigger = StateEnterTrigger<ACP_STATE_TRIGGERED>; -using ArmingTrigger = StateEnterTrigger<ACP_STATE_ARMING>; -using PendingTrigger = StateEnterTrigger<ACP_STATE_PENDING>; -using ArmedHomeTrigger = StateEnterTrigger<ACP_STATE_ARMED_HOME>; -using ArmedNightTrigger = StateEnterTrigger<ACP_STATE_ARMED_NIGHT>; -using ArmedAwayTrigger = StateEnterTrigger<ACP_STATE_ARMED_AWAY>; -using DisarmedTrigger = StateEnterTrigger<ACP_STATE_DISARMED>; - -/// Trigger when leaving TRIGGERED state (alarm cleared) -class ClearedTrigger : public Trigger<> { - public: - explicit ClearedTrigger(AlarmControlPanel *alarm_control_panel) { - alarm_control_panel->add_on_cleared_callback([this]() { this->trigger(); }); - } -}; - -/// Trigger on chime event (zone opened while disarmed) -class ChimeTrigger : public Trigger<> { - public: - explicit ChimeTrigger(AlarmControlPanel *alarm_control_panel) { - alarm_control_panel->add_on_chime_callback([this]() { this->trigger(); }); - } -}; - -/// Trigger on ready state change -class ReadyTrigger : public Trigger<> { - public: - explicit ReadyTrigger(AlarmControlPanel *alarm_control_panel) { - alarm_control_panel->add_on_ready_callback([this]() { this->trigger(); }); - } -}; +static_assert(sizeof(StateAnyForwarder) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<StateAnyForwarder>); +static_assert(sizeof(StateEnterForwarder<ACP_STATE_TRIGGERED>) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<StateEnterForwarder<ACP_STATE_TRIGGERED>>); template<typename... Ts> class ArmAwayAction : public Action<Ts...> { public: diff --git a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp index 74a60b3624..f059360e23 100644 --- a/esphome/components/mqtt/mqtt_alarm_control_panel.cpp +++ b/esphome/components/mqtt/mqtt_alarm_control_panel.cpp @@ -48,7 +48,8 @@ static bool apply_command(AlarmControlPanelCall &call, const char *state) { } void MQTTAlarmControlPanelComponent::setup() { - this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); }); + this->alarm_control_panel_->add_on_state_callback( + [this](AlarmControlPanelState /*state*/) { this->publish_state(); }); this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) { auto call = this->alarm_control_panel_->make_call(); if (!payload.empty() && payload[0] == '{') { From dea8fdd906a7fc79648d05dfeb74d6aaadad55e8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:20:35 -1000 Subject: [PATCH 1746/2030] [lock] Migrate LockStateTrigger to callback automation (#15199) --- esphome/components/copy/lock/copy_lock.cpp | 2 +- esphome/components/lock/__init__.py | 34 ++++++++++------------ esphome/components/lock/automation.h | 22 ++++++-------- esphome/components/lock/lock.cpp | 2 +- esphome/components/lock/lock.h | 4 +-- esphome/components/mqtt/mqtt_lock.cpp | 3 +- 6 files changed, 30 insertions(+), 37 deletions(-) diff --git a/esphome/components/copy/lock/copy_lock.cpp b/esphome/components/copy/lock/copy_lock.cpp index 25bd8c33ef..c846954510 100644 --- a/esphome/components/copy/lock/copy_lock.cpp +++ b/esphome/components/copy/lock/copy_lock.cpp @@ -7,7 +7,7 @@ namespace copy { static const char *const TAG = "copy.lock"; void CopyLock::setup() { - source_->add_on_state_callback([this]() { this->publish_state(source_->state); }); + source_->add_on_state_callback([this](lock::LockState state) { this->publish_state(state); }); traits.set_assumed_state(source_->traits.get_assumed_state()); traits.set_requires_code(source_->traits.get_requires_code()); diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index fe4db23ae3..0df4b20cba 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_MQTT_ID, CONF_ON_LOCK, CONF_ON_UNLOCK, - CONF_TRIGGER_ID, CONF_WEB_SERVER, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority @@ -31,8 +30,7 @@ OpenAction = lock_ns.class_("OpenAction", automation.Action) LockPublishAction = lock_ns.class_("LockPublishAction", automation.Action) LockCondition = lock_ns.class_("LockCondition", Condition) -LockLockTrigger = lock_ns.class_("LockLockTrigger", automation.Trigger.template()) -LockUnlockTrigger = lock_ns.class_("LockUnlockTrigger", automation.Trigger.template()) +LockStateForwarder = lock_ns.class_("LockStateForwarder") LockState = lock_ns.enum("LockState") @@ -52,16 +50,8 @@ _LOCK_SCHEMA = ( .extend( { cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTLockComponent), - cv.Optional(CONF_ON_LOCK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LockLockTrigger), - } - ), - cv.Optional(CONF_ON_UNLOCK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LockUnlockTrigger), - } - ), + cv.Optional(CONF_ON_LOCK): automation.validate_automation({}), + cv.Optional(CONF_ON_UNLOCK): automation.validate_automation({}), } ) ) @@ -93,12 +83,18 @@ def lock_schema( @setup_entity("lock") async def _setup_lock_core(var, config): - for conf in config.get(CONF_ON_LOCK, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_UNLOCK, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + for conf_key, state_enum in ( + (CONF_ON_LOCK, LockState.LOCK_STATE_LOCKED), + (CONF_ON_UNLOCK, LockState.LOCK_STATE_UNLOCKED), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, + "add_on_state_callback", + [], + conf, + forwarder=LockStateForwarder.template(state_enum), + ) if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/lock/automation.h b/esphome/components/lock/automation.h index 6f3c422693..c140bc568f 100644 --- a/esphome/components/lock/automation.h +++ b/esphome/components/lock/automation.h @@ -49,21 +49,17 @@ template<typename... Ts> class LockCondition : public Condition<Ts...> { bool state_; }; -template<LockState State> class LockStateTrigger : public Trigger<> { - public: - explicit LockStateTrigger(Lock *a_lock) : lock_(a_lock) { - a_lock->add_on_state_callback([this]() { - if (this->lock_->state == State) { - this->trigger(); - } - }); +/// Callback forwarder that triggers an Automation<> only when a specific lock state is entered. +/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_. +template<LockState State> struct LockStateForwarder { + Automation<> *automation; + void operator()(LockState state) const { + if (state == State) + this->automation->trigger(); } - - protected: - Lock *lock_; }; -using LockLockTrigger = LockStateTrigger<LockState::LOCK_STATE_LOCKED>; -using LockUnlockTrigger = LockStateTrigger<LockState::LOCK_STATE_UNLOCKED>; +static_assert(sizeof(LockStateForwarder<LockState::LOCK_STATE_LOCKED>) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<LockStateForwarder<LockState::LOCK_STATE_LOCKED>>); } // namespace esphome::lock diff --git a/esphome/components/lock/lock.cpp b/esphome/components/lock/lock.cpp index 90937485b9..3ff131af3d 100644 --- a/esphome/components/lock/lock.cpp +++ b/esphome/components/lock/lock.cpp @@ -42,7 +42,7 @@ void Lock::publish_state(LockState state) { this->state = state; this->rtc_.save(&this->state); ESP_LOGV(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state))); - this->state_callback_.call(); + this->state_callback_.call(state); #if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_lock_update(this); #endif diff --git a/esphome/components/lock/lock.h b/esphome/components/lock/lock.h index 707431d543..543a4b51a8 100644 --- a/esphome/components/lock/lock.h +++ b/esphome/components/lock/lock.h @@ -148,7 +148,7 @@ class Lock : public EntityBase { /** Set callback for state changes. * - * @param callback The void(bool) callback. + * @param callback The void(LockState) callback. */ template<typename F> void add_on_state_callback(F &&callback) { this->state_callback_.add(std::forward<F>(callback)); @@ -178,7 +178,7 @@ class Lock : public EntityBase { */ virtual void control(const LockCall &call) = 0; - LazyCallbackManager<void()> state_callback_{}; + LazyCallbackManager<void(LockState)> state_callback_{}; Deduplicator<LockState> publish_dedup_; ESPPreferenceObject rtc_; }; diff --git a/esphome/components/mqtt/mqtt_lock.cpp b/esphome/components/mqtt/mqtt_lock.cpp index 45d8e4698f..7920187f92 100644 --- a/esphome/components/mqtt/mqtt_lock.cpp +++ b/esphome/components/mqtt/mqtt_lock.cpp @@ -28,7 +28,8 @@ void MQTTLockComponent::setup() { this->status_momentary_warning("state", 5000); } }); - this->lock_->add_on_state_callback([this]() { this->defer("send", [this]() { this->publish_state(); }); }); + this->lock_->add_on_state_callback( + [this](LockState /*state*/) { this->defer("send", [this]() { this->publish_state(); }); }); } void MQTTLockComponent::dump_config() { ESP_LOGCONFIG(TAG, "MQTT Lock '%s': ", this->lock_->get_name().c_str()); From 2e42547d32edce07150f925e7bc8fd0c03f7b814 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:20:46 -1000 Subject: [PATCH 1747/2030] [media_player] Migrate triggers to callback automation (#15200) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/media_player/__init__.py | 42 ++++++++++--------- esphome/components/media_player/automation.h | 41 ++++++++---------- .../components/media_player/media_player.cpp | 2 +- .../components/media_player/media_player.h | 2 +- .../voice_assistant/voice_assistant.cpp | 4 +- 5 files changed, 44 insertions(+), 47 deletions(-) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index a5baca2994..767916ad88 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -9,7 +9,6 @@ from esphome.const import ( CONF_ON_STATE, CONF_ON_TURN_OFF, CONF_ON_TURN_ON, - CONF_TRIGGER_ID, CONF_VOLUME, ) from esphome.core import CORE @@ -65,15 +64,19 @@ _COMMAND_ACTIONS = [ "clear_playlist", ] -# State triggers: (config_key, C++ class name) +StateAnyForwarder = media_player_ns.class_("StateAnyForwarder") +StateEnterForwarder = media_player_ns.class_("StateEnterForwarder") +MediaPlayerState = media_player_ns.enum("MediaPlayerState") + +# State triggers: (config_key, state enum or None for any-state) _STATE_TRIGGERS = [ - (CONF_ON_STATE, "StateTrigger"), - (CONF_ON_IDLE, "IdleTrigger"), - (CONF_ON_PLAY, "PlayTrigger"), - (CONF_ON_PAUSE, "PauseTrigger"), - (CONF_ON_ANNOUNCEMENT, "AnnouncementTrigger"), - (CONF_ON_TURN_ON, "OnTrigger"), - (CONF_ON_TURN_OFF, "OffTrigger"), + (CONF_ON_STATE, None), + (CONF_ON_IDLE, MediaPlayerState.MEDIA_PLAYER_STATE_IDLE), + (CONF_ON_PLAY, MediaPlayerState.MEDIA_PLAYER_STATE_PLAYING), + (CONF_ON_PAUSE, MediaPlayerState.MEDIA_PLAYER_STATE_PAUSED), + (CONF_ON_ANNOUNCEMENT, MediaPlayerState.MEDIA_PLAYER_STATE_ANNOUNCING), + (CONF_ON_TURN_ON, MediaPlayerState.MEDIA_PLAYER_STATE_ON), + (CONF_ON_TURN_OFF, MediaPlayerState.MEDIA_PLAYER_STATE_OFF), ] # State conditions that all share the same schema and codegen handler @@ -98,10 +101,15 @@ VolumeSetAction = media_player_ns.class_( @setup_entity("media_player") async def setup_media_player_core_(var, config): - for conf_key, _ in _STATE_TRIGGERS: + for conf_key, state_enum in _STATE_TRIGGERS: for conf in config.get(conf_key, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + if state_enum is None: + forwarder = StateAnyForwarder + else: + forwarder = StateEnterForwarder.template(state_enum) + await automation.build_callback_automation( + var, "add_on_state_callback", [], conf, forwarder=forwarder + ) async def register_media_player(var, config): @@ -120,14 +128,8 @@ async def new_media_player(config, *args): _MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( { - cv.Optional(conf_key): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - media_player_ns.class_(class_name, automation.Trigger.template()) - ), - } - ) - for conf_key, class_name in _STATE_TRIGGERS + cv.Optional(conf_key): automation.validate_automation({}) + for conf_key, _ in _STATE_TRIGGERS } ) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 031f6657f4..658381ef90 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -71,32 +71,27 @@ template<typename... Ts> class VolumeSetAction : public Action<Ts...>, public Pa void play(const Ts &...x) override { this->parent_->make_call().set_volume(this->volume_.value(x...)).perform(); } }; -class StateTrigger : public Trigger<> { - public: - explicit StateTrigger(MediaPlayer *player) { - player->add_on_state_callback([this]() { this->trigger(); }); +/// Callback forwarder that triggers an Automation<> on any state change. +/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_. +struct StateAnyForwarder { + Automation<> *automation; + void operator()(MediaPlayerState /*state*/) const { this->automation->trigger(); } +}; + +/// Callback forwarder that triggers an Automation<> only when a specific media player state is entered. +/// Pointer-sized (single Automation* field) to fit inline in Callback::ctx_. +template<MediaPlayerState State> struct StateEnterForwarder { + Automation<> *automation; + void operator()(MediaPlayerState state) const { + if (state == State) + this->automation->trigger(); } }; -template<MediaPlayerState State> class MediaPlayerStateTrigger : public Trigger<> { - public: - explicit MediaPlayerStateTrigger(MediaPlayer *player) : player_(player) { - player->add_on_state_callback([this]() { - if (this->player_->state == State) - this->trigger(); - }); - } - - protected: - MediaPlayer *player_; -}; - -using IdleTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_IDLE>; -using PlayTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING>; -using PauseTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_PAUSED>; -using AnnouncementTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING>; -using OnTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_ON>; -using OffTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_OFF>; +static_assert(sizeof(StateAnyForwarder) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<StateAnyForwarder>); +static_assert(sizeof(StateEnterForwarder<MediaPlayerState::MEDIA_PLAYER_STATE_IDLE>) <= sizeof(void *)); +static_assert(std::is_trivially_copyable_v<StateEnterForwarder<MediaPlayerState::MEDIA_PLAYER_STATE_IDLE>>); template<typename... Ts> class IsIdleCondition : public Condition<Ts...>, public Parented<MediaPlayer> { public: diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index a0eb7b5500..48d23fa0b1 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -199,7 +199,7 @@ MediaPlayerCall &MediaPlayerCall::set_announcement(bool announce) { } void MediaPlayer::publish_state() { - this->state_callback_.call(); + this->state_callback_.call(this->state); #if defined(USE_MEDIA_PLAYER) && defined(USE_CONTROLLER_REGISTRY) ControllerRegistry::notify_media_player_update(this); #endif diff --git a/esphome/components/media_player/media_player.h b/esphome/components/media_player/media_player.h index 26eca469e7..d5d0020797 100644 --- a/esphome/components/media_player/media_player.h +++ b/esphome/components/media_player/media_player.h @@ -168,7 +168,7 @@ class MediaPlayer : public EntityBase { virtual void control(const MediaPlayerCall &call) = 0; - LazyCallbackManager<void()> state_callback_{}; + LazyCallbackManager<void(MediaPlayerState)> state_callback_{}; }; } // namespace media_player diff --git a/esphome/components/voice_assistant/voice_assistant.cpp b/esphome/components/voice_assistant/voice_assistant.cpp index 15124e422f..ddce606b2c 100644 --- a/esphome/components/voice_assistant/voice_assistant.cpp +++ b/esphome/components/voice_assistant/voice_assistant.cpp @@ -39,8 +39,8 @@ void VoiceAssistant::setup() { #ifdef USE_MEDIA_PLAYER if (this->media_player_ != nullptr) { - this->media_player_->add_on_state_callback([this]() { - switch (this->media_player_->state) { + this->media_player_->add_on_state_callback([this](media_player::MediaPlayerState state) { + switch (state) { case media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING: if (this->media_player_response_state_ == MediaPlayerResponseState::URL_SENT) { // State changed to announcing after receiving the url From a2d452684a0cc6620e0a3e1bce746b0ef6a80ff3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:21:03 -1000 Subject: [PATCH 1748/2030] [ld2450] Migrate LD2450DataTrigger to callback automation (#15201) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/ld2450/__init__.py | 14 +++++--------- esphome/components/ld2450/ld2450.h | 8 -------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/esphome/components/ld2450/__init__.py b/esphome/components/ld2450/__init__.py index 5854a5794c..37bf12bafc 100644 --- a/esphome/components/ld2450/__init__.py +++ b/esphome/components/ld2450/__init__.py @@ -2,7 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_ON_DATA, CONF_THROTTLE, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_ON_DATA, CONF_THROTTLE AUTO_LOAD = ["ld24xx"] DEPENDENCIES = ["uart"] @@ -12,7 +12,6 @@ MULTI_CONF = True ld2450_ns = cg.esphome_ns.namespace("ld2450") LD2450Component = ld2450_ns.class_("LD2450Component", cg.Component, uart.UARTDevice) -LD2450DataTrigger = ld2450_ns.class_("LD2450DataTrigger", automation.Trigger.template()) CONF_LD2450_ID = "ld2450_id" @@ -23,11 +22,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_THROTTLE): cv.invalid( f"{CONF_THROTTLE} has been removed; use per-sensor filters, instead" ), - cv.Optional(CONF_ON_DATA): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LD2450DataTrigger), - } - ), + cv.Optional(CONF_ON_DATA): automation.validate_automation({}), } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -54,5 +49,6 @@ async def to_code(config): await cg.register_component(var, config) await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_DATA, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_data_callback", [], conf + ) diff --git a/esphome/components/ld2450/ld2450.h b/esphome/components/ld2450/ld2450.h index e774dd9c75..cbcdec10b3 100644 --- a/esphome/components/ld2450/ld2450.h +++ b/esphome/components/ld2450/ld2450.h @@ -1,6 +1,5 @@ #pragma once -#include "esphome/core/automation.h" #include "esphome/core/defines.h" #include "esphome/core/component.h" #ifdef USE_SENSOR @@ -201,11 +200,4 @@ class LD2450Component : public Component, public uart::UARTDevice { LazyCallbackManager<void()> data_callback_; }; -class LD2450DataTrigger : public Trigger<> { - public: - explicit LD2450DataTrigger(LD2450Component *parent) { - parent->add_on_data_callback([this]() { this->trigger(); }); - } -}; - } // namespace esphome::ld2450 From 83b3187126be87ac2d7a97db9dd340d8679180e2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:21:16 -1000 Subject: [PATCH 1749/2030] [rtttl] Migrate FinishedPlaybackTrigger to callback automation (#15202) --- esphome/components/rtttl/__init__.py | 25 +++++-------------------- esphome/components/rtttl/rtttl.h | 7 ------- 2 files changed, 5 insertions(+), 27 deletions(-) diff --git a/esphome/components/rtttl/__init__.py b/esphome/components/rtttl/__init__.py index 3566734200..638e950ba6 100644 --- a/esphome/components/rtttl/__init__.py +++ b/esphome/components/rtttl/__init__.py @@ -5,14 +5,7 @@ import esphome.codegen as cg from esphome.components.output import FloatOutput from esphome.components.speaker import Speaker import esphome.config_validation as cv -from esphome.const import ( - CONF_GAIN, - CONF_ID, - CONF_OUTPUT, - CONF_PLATFORM, - CONF_SPEAKER, - CONF_TRIGGER_ID, -) +from esphome.const import CONF_GAIN, CONF_ID, CONF_OUTPUT, CONF_PLATFORM, CONF_SPEAKER import esphome.final_validate as fv _LOGGER = logging.getLogger(__name__) @@ -26,9 +19,6 @@ rtttl_ns = cg.esphome_ns.namespace("rtttl") Rtttl = rtttl_ns.class_("Rtttl", cg.Component) PlayAction = rtttl_ns.class_("PlayAction", automation.Action) StopAction = rtttl_ns.class_("StopAction", automation.Action) -FinishedPlaybackTrigger = rtttl_ns.class_( - "FinishedPlaybackTrigger", automation.Trigger.template() -) IsPlayingCondition = rtttl_ns.class_("IsPlayingCondition", automation.Condition) MULTI_CONF = True @@ -40,13 +30,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_OUTPUT): cv.use_id(FloatOutput), cv.Optional(CONF_SPEAKER): cv.use_id(Speaker), cv.Optional(CONF_GAIN, default="0.6"): cv.percentage, - cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FinishedPlaybackTrigger - ), - } - ), + cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation({}), } ).extend(cv.COMPONENT_SCHEMA), cv.has_exactly_one_key(CONF_OUTPUT, CONF_SPEAKER), @@ -103,8 +87,9 @@ async def to_code(config): cg.add(var.set_gain(config[CONF_GAIN])) for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_finished_playback_callback", [], conf + ) @automation.register_action( diff --git a/esphome/components/rtttl/rtttl.h b/esphome/components/rtttl/rtttl.h index bff43d2edd..98ed9ba1bf 100644 --- a/esphome/components/rtttl/rtttl.h +++ b/esphome/components/rtttl/rtttl.h @@ -131,11 +131,4 @@ template<typename... Ts> class IsPlayingCondition : public Condition<Ts...>, pub bool check(const Ts &...x) override { return this->parent_->is_playing(); } }; -class FinishedPlaybackTrigger : public Trigger<> { - public: - explicit FinishedPlaybackTrigger(Rtttl *parent) { - parent->add_on_finished_playback_callback([this]() { this->trigger(); }); - } -}; - } // namespace esphome::rtttl From 4493d2efb6582f020b6ed73879ab56566c088779 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:21:27 -1000 Subject: [PATCH 1750/2030] [online_image] Migrate triggers to callback automation (#15216) --- esphome/components/online_image/__init__.py | 41 ++++--------------- .../components/online_image/online_image.h | 14 ------- 2 files changed, 9 insertions(+), 46 deletions(-) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 292e2bb3bb..5b8294c70e 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -7,14 +7,7 @@ from esphome.components.const import CONF_REQUEST_HEADERS from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent from esphome.components.image import CONF_TRANSPARENCY, add_metadata import esphome.config_validation as cv -from esphome.const import ( - CONF_BUFFER_SIZE, - CONF_ID, - CONF_ON_ERROR, - CONF_TRIGGER_ID, - CONF_TYPE, - CONF_URL, -) +from esphome.const import CONF_BUFFER_SIZE, CONF_ID, CONF_ON_ERROR, CONF_TYPE, CONF_URL from esphome.core import Lambda AUTO_LOAD = ["image", "runtime_image"] @@ -41,14 +34,6 @@ ReleaseImageAction = online_image_ns.class_( "OnlineImageReleaseAction", automation.Action, cg.Parented.template(OnlineImage) ) -# Triggers -DownloadFinishedTrigger = online_image_ns.class_( - "DownloadFinishedTrigger", automation.Trigger.template() -) -DownloadErrorTrigger = online_image_ns.class_( - "DownloadErrorTrigger", automation.Trigger.template() -) - ONLINE_IMAGE_SCHEMA = ( runtime_image.runtime_image_schema(OnlineImage) @@ -61,18 +46,8 @@ ONLINE_IMAGE_SCHEMA = ( cv.Optional(CONF_REQUEST_HEADERS): cv.All( cv.Schema({cv.string: cv.templatable(cv.string)}) ), - cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - DownloadFinishedTrigger - ), - } - ), - cv.Optional(CONF_ON_ERROR): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DownloadErrorTrigger), - } - ), + cv.Optional(CONF_ON_DOWNLOAD_FINISHED): automation.validate_automation({}), + cv.Optional(CONF_ON_ERROR): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("never")) @@ -165,9 +140,11 @@ async def to_code(config): cg.add(var.add_request_header(key, value)) for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(bool, "cached")], conf) + await automation.build_callback_automation( + var, "add_on_finished_callback", [(bool, "cached")], conf + ) for conf in config.get(CONF_ON_ERROR, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_error_callback", [], conf + ) diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 3a348cbb07..816d6525ea 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -129,18 +129,4 @@ template<typename... Ts> class OnlineImageReleaseAction : public Action<Ts...> { OnlineImage *parent_; }; -class DownloadFinishedTrigger : public Trigger<bool> { - public: - explicit DownloadFinishedTrigger(OnlineImage *parent) { - parent->add_on_finished_callback([this](bool cached) { this->trigger(cached); }); - } -}; - -class DownloadErrorTrigger : public Trigger<> { - public: - explicit DownloadErrorTrigger(OnlineImage *parent) { - parent->add_on_error_callback([this]() { this->trigger(); }); - } -}; - } // namespace esphome::online_image From 54283a2599cf5f6958bbb329745afd0dbb800f2a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:21:41 -1000 Subject: [PATCH 1751/2030] [rotary_encoder] Migrate triggers to callback automation (#15217) --- .../rotary_encoder/rotary_encoder.h | 14 -------- esphome/components/rotary_encoder/sensor.py | 34 +++++-------------- 2 files changed, 8 insertions(+), 40 deletions(-) diff --git a/esphome/components/rotary_encoder/rotary_encoder.h b/esphome/components/rotary_encoder/rotary_encoder.h index 4b776fe55e..6f4a4fd83c 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.h +++ b/esphome/components/rotary_encoder/rotary_encoder.h @@ -118,19 +118,5 @@ template<typename... Ts> class RotaryEncoderSetValueAction : public Action<Ts... RotaryEncoderSensor *encoder_; }; -class RotaryEncoderClockwiseTrigger : public Trigger<> { - public: - explicit RotaryEncoderClockwiseTrigger(RotaryEncoderSensor *parent) { - parent->add_on_clockwise_callback([this]() { this->trigger(); }); - } -}; - -class RotaryEncoderAnticlockwiseTrigger : public Trigger<> { - public: - explicit RotaryEncoderAnticlockwiseTrigger(RotaryEncoderSensor *parent) { - parent->add_on_anticlockwise_callback([this]() { this->trigger(); }); - } -}; - } // namespace rotary_encoder } // namespace esphome diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index be315db55d..e64e44f7c1 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -10,7 +10,6 @@ from esphome.const import ( CONF_PIN_B, CONF_RESOLUTION, CONF_RESTORE_MODE, - CONF_TRIGGER_ID, CONF_VALUE, ICON_ROTATE_RIGHT, UNIT_STEPS, @@ -43,13 +42,6 @@ RotaryEncoderSetValueAction = rotary_encoder_ns.class_( "RotaryEncoderSetValueAction", automation.Action ) -RotaryEncoderClockwiseTrigger = rotary_encoder_ns.class_( - "RotaryEncoderClockwiseTrigger", automation.Trigger -) -RotaryEncoderAnticlockwiseTrigger = rotary_encoder_ns.class_( - "RotaryEncoderAnticlockwiseTrigger", automation.Trigger -) - def validate_min_max_value(config): if CONF_MIN_VALUE in config and CONF_MAX_VALUE in config: @@ -81,20 +73,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_RESTORE_MODE, default="RESTORE_DEFAULT_ZERO"): cv.enum( RESTORE_MODES, upper=True, space="_" ), - cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - RotaryEncoderClockwiseTrigger - ), - } - ), - cv.Optional(CONF_ON_ANTICLOCKWISE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - RotaryEncoderAnticlockwiseTrigger - ), - } - ), + cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation({}), + cv.Optional(CONF_ON_ANTICLOCKWISE): automation.validate_automation({}), } ) .extend(cv.COMPONENT_SCHEMA), @@ -123,11 +103,13 @@ async def to_code(config): cg.add(var.set_max_value(config[CONF_MAX_VALUE])) for conf in config.get(CONF_ON_CLOCKWISE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_clockwise_callback", [], conf + ) for conf in config.get(CONF_ON_ANTICLOCKWISE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_anticlockwise_callback", [], conf + ) @automation.register_action( From 514df6c99af94915523d26e45ad489d4a5ff60d7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:21:52 -1000 Subject: [PATCH 1752/2030] [dfplayer] Migrate FinishedPlaybackTrigger to callback automation (#15218) --- esphome/components/dfplayer/__init__.py | 18 +++++------------- esphome/components/dfplayer/dfplayer.h | 7 ------- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index 9df108c9c0..c49420f060 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -2,16 +2,13 @@ from esphome import automation import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv -from esphome.const import CONF_DEVICE, CONF_FILE, CONF_ID, CONF_TRIGGER_ID, CONF_VOLUME +from esphome.const import CONF_DEVICE, CONF_FILE, CONF_ID, CONF_VOLUME DEPENDENCIES = ["uart"] CODEOWNERS = ["@glmnet"] dfplayer_ns = cg.esphome_ns.namespace("dfplayer") DFPlayer = dfplayer_ns.class_("DFPlayer", cg.Component) -DFPlayerFinishedPlaybackTrigger = dfplayer_ns.class_( - "DFPlayerFinishedPlaybackTrigger", automation.Trigger.template() -) DFPlayerIsPlayingCondition = dfplayer_ns.class_( "DFPlayerIsPlayingCondition", automation.Condition ) @@ -58,13 +55,7 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(DFPlayer), - cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - DFPlayerFinishedPlaybackTrigger - ), - } - ), + cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation({}), } ).extend(uart.UART_DEVICE_SCHEMA) ) @@ -79,8 +70,9 @@ async def to_code(config): await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_finished_playback_callback", [], conf + ) @automation.register_action( diff --git a/esphome/components/dfplayer/dfplayer.h b/esphome/components/dfplayer/dfplayer.h index 2c4ee03470..0d240566c3 100644 --- a/esphome/components/dfplayer/dfplayer.h +++ b/esphome/components/dfplayer/dfplayer.h @@ -171,12 +171,5 @@ template<typename... Ts> class DFPlayerIsPlayingCondition : public Condition<Ts. bool check(const Ts &...x) override { return this->parent_->is_playing(); } }; -class DFPlayerFinishedPlaybackTrigger : public Trigger<> { - public: - explicit DFPlayerFinishedPlaybackTrigger(DFPlayer *parent) { - parent->add_on_finished_playback_callback([this]() { this->trigger(); }); - } -}; - } // namespace dfplayer } // namespace esphome From 623408bbfe2bff8c41964b73afa2a23fbd208e10 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:02 -1000 Subject: [PATCH 1753/2030] [hlk_fm22x] Migrate triggers to callback automation (#15219) --- esphome/components/hlk_fm22x/__init__.py | 109 ++++++----------------- esphome/components/hlk_fm22x/hlk_fm22x.h | 46 ---------- 2 files changed, 28 insertions(+), 127 deletions(-) diff --git a/esphome/components/hlk_fm22x/__init__.py b/esphome/components/hlk_fm22x/__init__.py index cb6d5cdfd6..c0349319d1 100644 --- a/esphome/components/hlk_fm22x/__init__.py +++ b/esphome/components/hlk_fm22x/__init__.py @@ -8,7 +8,6 @@ from esphome.const import ( CONF_NAME, CONF_ON_ENROLLMENT_DONE, CONF_ON_ENROLLMENT_FAILED, - CONF_TRIGGER_ID, ) CODEOWNERS = ["@OnFreund"] @@ -28,33 +27,6 @@ HlkFm22xComponent = hlk_fm22x_ns.class_( "HlkFm22xComponent", cg.PollingComponent, uart.UARTDevice ) -FaceScanMatchedTrigger = hlk_fm22x_ns.class_( - "FaceScanMatchedTrigger", automation.Trigger.template(cg.int16, cg.std_string) -) - -FaceScanUnmatchedTrigger = hlk_fm22x_ns.class_( - "FaceScanUnmatchedTrigger", automation.Trigger.template() -) - -FaceScanInvalidTrigger = hlk_fm22x_ns.class_( - "FaceScanInvalidTrigger", automation.Trigger.template(cg.uint8) -) - -FaceInfoTrigger = hlk_fm22x_ns.class_( - "FaceInfoTrigger", - automation.Trigger.template( - cg.int16, cg.int16, cg.int16, cg.int16, cg.int16, cg.int16, cg.int16, cg.int16 - ), -) - -EnrollmentDoneTrigger = hlk_fm22x_ns.class_( - "EnrollmentDoneTrigger", automation.Trigger.template(cg.int16, cg.uint8) -) - -EnrollmentFailedTrigger = hlk_fm22x_ns.class_( - "EnrollmentFailedTrigger", automation.Trigger.template(cg.uint8) -) - EnrollmentAction = hlk_fm22x_ns.class_("EnrollmentAction", automation.Action) DeleteAction = hlk_fm22x_ns.class_("DeleteAction", automation.Action) DeleteAllAction = hlk_fm22x_ns.class_("DeleteAllAction", automation.Action) @@ -65,46 +37,14 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(HlkFm22xComponent), - cv.Optional(CONF_ON_FACE_SCAN_MATCHED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FaceScanMatchedTrigger - ), - } - ), + cv.Optional(CONF_ON_FACE_SCAN_MATCHED): automation.validate_automation({}), cv.Optional(CONF_ON_FACE_SCAN_UNMATCHED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FaceScanUnmatchedTrigger - ), - } - ), - cv.Optional(CONF_ON_FACE_SCAN_INVALID): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FaceScanInvalidTrigger - ), - } - ), - cv.Optional(CONF_ON_FACE_INFO): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FaceInfoTrigger), - } - ), - cv.Optional(CONF_ON_ENROLLMENT_DONE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - EnrollmentDoneTrigger - ), - } - ), - cv.Optional(CONF_ON_ENROLLMENT_FAILED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - EnrollmentFailedTrigger - ), - } + {} ), + cv.Optional(CONF_ON_FACE_SCAN_INVALID): automation.validate_automation({}), + cv.Optional(CONF_ON_FACE_INFO): automation.validate_automation({}), + cv.Optional(CONF_ON_ENROLLMENT_DONE): automation.validate_automation({}), + cv.Optional(CONF_ON_ENROLLMENT_FAILED): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("50ms")) @@ -118,23 +58,27 @@ async def to_code(config): await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_FACE_SCAN_MATCHED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.int16, "face_id"), (cg.std_string, "name")], conf + await automation.build_callback_automation( + var, + "add_on_face_scan_matched_callback", + [(cg.int16, "face_id"), (cg.std_string, "name")], + conf, ) for conf in config.get(CONF_ON_FACE_SCAN_UNMATCHED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_face_scan_unmatched_callback", [], conf + ) for conf in config.get(CONF_ON_FACE_SCAN_INVALID, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.uint8, "error")], conf) + await automation.build_callback_automation( + var, "add_on_face_scan_invalid_callback", [(cg.uint8, "error")], conf + ) for conf in config.get(CONF_ON_FACE_INFO, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, + await automation.build_callback_automation( + var, + "add_on_face_info_callback", [ (cg.int16, "status"), (cg.int16, "left"), @@ -149,14 +93,17 @@ async def to_code(config): ) for conf in config.get(CONF_ON_ENROLLMENT_DONE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.int16, "face_id"), (cg.uint8, "direction")], conf + await automation.build_callback_automation( + var, + "add_on_enrollment_done_callback", + [(cg.int16, "face_id"), (cg.uint8, "direction")], + conf, ) for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.uint8, "error")], conf) + await automation.build_callback_automation( + var, "add_on_enrollment_failed_callback", [(cg.uint8, "error")], conf + ) @automation.register_action( diff --git a/esphome/components/hlk_fm22x/hlk_fm22x.h b/esphome/components/hlk_fm22x/hlk_fm22x.h index d897d51881..fd8257b435 100644 --- a/esphome/components/hlk_fm22x/hlk_fm22x.h +++ b/esphome/components/hlk_fm22x/hlk_fm22x.h @@ -141,52 +141,6 @@ class HlkFm22xComponent : public PollingComponent, public uart::UARTDevice { CallbackManager<void(uint8_t)> enrollment_failed_callback_; }; -class FaceScanMatchedTrigger : public Trigger<int16_t, std::string> { - public: - explicit FaceScanMatchedTrigger(HlkFm22xComponent *parent) { - parent->add_on_face_scan_matched_callback( - [this](int16_t face_id, const std::string &name) { this->trigger(face_id, name); }); - } -}; - -class FaceScanUnmatchedTrigger : public Trigger<> { - public: - explicit FaceScanUnmatchedTrigger(HlkFm22xComponent *parent) { - parent->add_on_face_scan_unmatched_callback([this]() { this->trigger(); }); - } -}; - -class FaceScanInvalidTrigger : public Trigger<uint8_t> { - public: - explicit FaceScanInvalidTrigger(HlkFm22xComponent *parent) { - parent->add_on_face_scan_invalid_callback([this](uint8_t error) { this->trigger(error); }); - } -}; - -class FaceInfoTrigger : public Trigger<int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t, int16_t> { - public: - explicit FaceInfoTrigger(HlkFm22xComponent *parent) { - parent->add_on_face_info_callback( - [this](int16_t status, int16_t left, int16_t top, int16_t right, int16_t bottom, int16_t yaw, int16_t pitch, - int16_t roll) { this->trigger(status, left, top, right, bottom, yaw, pitch, roll); }); - } -}; - -class EnrollmentDoneTrigger : public Trigger<int16_t, uint8_t> { - public: - explicit EnrollmentDoneTrigger(HlkFm22xComponent *parent) { - parent->add_on_enrollment_done_callback( - [this](int16_t face_id, uint8_t direction) { this->trigger(face_id, direction); }); - } -}; - -class EnrollmentFailedTrigger : public Trigger<uint8_t> { - public: - explicit EnrollmentFailedTrigger(HlkFm22xComponent *parent) { - parent->add_on_enrollment_failed_callback([this](uint8_t error) { this->trigger(error); }); - } -}; - template<typename... Ts> class EnrollmentAction : public Action<Ts...>, public Parented<HlkFm22xComponent> { public: TEMPLATABLE_VALUE(std::string, name) From a4a8fa3027088c2a9c3ef8cc96c004cfabfe36b5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:14 -1000 Subject: [PATCH 1754/2030] [pn532] Migrate PN532OnFinishedWriteTrigger to callback automation (#15220) --- esphome/components/pn532/__init__.py | 17 ++++------------- esphome/components/pn532/pn532.h | 7 ------- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/esphome/components/pn532/__init__.py b/esphome/components/pn532/__init__.py index 6f679ed10a..4ccda49a72 100644 --- a/esphome/components/pn532/__init__.py +++ b/esphome/components/pn532/__init__.py @@ -19,10 +19,6 @@ CONF_PN532_ID = "pn532_id" pn532_ns = cg.esphome_ns.namespace("pn532") PN532 = pn532_ns.class_("PN532", cg.PollingComponent) -PN532OnFinishedWriteTrigger = pn532_ns.class_( - "PN532OnFinishedWriteTrigger", automation.Trigger.template() -) - PN532IsWritingCondition = pn532_ns.class_( "PN532IsWritingCondition", automation.Condition ) @@ -35,13 +31,7 @@ PN532_SCHEMA = cv.Schema( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(nfc.NfcOnTagTrigger), } ), - cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - PN532OnFinishedWriteTrigger - ), - } - ), + cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation({}), cv.Optional(CONF_ON_TAG_REMOVED): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(nfc.NfcOnTagTrigger), @@ -77,8 +67,9 @@ async def setup_pn532(var, config): ) for conf in config.get(CONF_ON_FINISHED_WRITE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_finished_write_callback", [], conf + ) @automation.register_condition( diff --git a/esphome/components/pn532/pn532.h b/esphome/components/pn532/pn532.h index 1f6a6b3bc3..b76cbb1946 100644 --- a/esphome/components/pn532/pn532.h +++ b/esphome/components/pn532/pn532.h @@ -133,13 +133,6 @@ class PN532BinarySensor : public binary_sensor::BinarySensor { bool found_{false}; }; -class PN532OnFinishedWriteTrigger : public Trigger<> { - public: - explicit PN532OnFinishedWriteTrigger(PN532 *parent) { - parent->add_on_finished_write_callback([this]() { this->trigger(); }); - } -}; - template<typename... Ts> class PN532IsWritingCondition : public Condition<Ts...>, public Parented<PN532> { public: bool check(const Ts &...x) override { return this->parent_->is_writing(); } From 985477f2cfa40cc31a97f3169364b73db4d34a91 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:25 -1000 Subject: [PATCH 1755/2030] [pn7150][pn7160] Migrate triggers to callback automation (#15221) --- esphome/components/pn7150/__init__.py | 34 ++++++-------------------- esphome/components/pn7150/automation.h | 14 ----------- esphome/components/pn7160/__init__.py | 34 ++++++-------------------- esphome/components/pn7160/automation.h | 14 ----------- 4 files changed, 16 insertions(+), 80 deletions(-) diff --git a/esphome/components/pn7150/__init__.py b/esphome/components/pn7150/__init__.py index 6af1412881..c8723dc31c 100644 --- a/esphome/components/pn7150/__init__.py +++ b/esphome/components/pn7150/__init__.py @@ -50,14 +50,6 @@ SetWriteMessageAction = pn7150_ns.class_("SetWriteMessageAction", automation.Act SetWriteModeAction = pn7150_ns.class_("SetWriteModeAction", automation.Action) -PN7150OnEmulatedTagScanTrigger = pn7150_ns.class_( - "PN7150OnEmulatedTagScanTrigger", automation.Trigger.template() -) - -PN7150OnFinishedWriteTrigger = pn7150_ns.class_( - "PN7150OnFinishedWriteTrigger", automation.Trigger.template() -) - PN7150IsWritingCondition = pn7150_ns.class_( "PN7150IsWritingCondition", automation.Condition ) @@ -83,20 +75,8 @@ SET_MESSAGE_ACTION_SCHEMA = cv.Schema( PN7150_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(PN7150), - cv.Optional(CONF_ON_EMULATED_TAG_SCAN): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - PN7150OnEmulatedTagScanTrigger - ), - } - ), - cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - PN7150OnFinishedWriteTrigger - ), - } - ), + cv.Optional(CONF_ON_EMULATED_TAG_SCAN): automation.validate_automation({}), + cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation({}), cv.Optional(CONF_ON_TAG): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(nfc.NfcOnTagTrigger), @@ -215,12 +195,14 @@ async def setup_pn7150(var, config): ) for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_emulated_tag_scan_callback", [], conf + ) for conf in config.get(CONF_ON_FINISHED_WRITE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_finished_write_callback", [], conf + ) @automation.register_condition( diff --git a/esphome/components/pn7150/automation.h b/esphome/components/pn7150/automation.h index 21329a998a..a8c65ae633 100644 --- a/esphome/components/pn7150/automation.h +++ b/esphome/components/pn7150/automation.h @@ -7,20 +7,6 @@ namespace esphome { namespace pn7150 { -class PN7150OnEmulatedTagScanTrigger : public Trigger<> { - public: - explicit PN7150OnEmulatedTagScanTrigger(PN7150 *parent) { - parent->add_on_emulated_tag_scan_callback([this]() { this->trigger(); }); - } -}; - -class PN7150OnFinishedWriteTrigger : public Trigger<> { - public: - explicit PN7150OnFinishedWriteTrigger(PN7150 *parent) { - parent->add_on_finished_write_callback([this]() { this->trigger(); }); - } -}; - template<typename... Ts> class PN7150IsWritingCondition : public Condition<Ts...>, public Parented<PN7150> { public: bool check(const Ts &...x) override { return this->parent_->is_writing(); } diff --git a/esphome/components/pn7160/__init__.py b/esphome/components/pn7160/__init__.py index 54e4b74796..e382594b93 100644 --- a/esphome/components/pn7160/__init__.py +++ b/esphome/components/pn7160/__init__.py @@ -52,14 +52,6 @@ SetWriteMessageAction = pn7160_ns.class_("SetWriteMessageAction", automation.Act SetWriteModeAction = pn7160_ns.class_("SetWriteModeAction", automation.Action) -PN7160OnEmulatedTagScanTrigger = pn7160_ns.class_( - "PN7160OnEmulatedTagScanTrigger", automation.Trigger.template() -) - -PN7160OnFinishedWriteTrigger = pn7160_ns.class_( - "PN7160OnFinishedWriteTrigger", automation.Trigger.template() -) - PN7160IsWritingCondition = pn7160_ns.class_( "PN7160IsWritingCondition", automation.Condition ) @@ -85,20 +77,8 @@ SET_MESSAGE_ACTION_SCHEMA = cv.Schema( PN7160_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(PN7160), - cv.Optional(CONF_ON_EMULATED_TAG_SCAN): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - PN7160OnEmulatedTagScanTrigger - ), - } - ), - cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - PN7160OnFinishedWriteTrigger - ), - } - ), + cv.Optional(CONF_ON_EMULATED_TAG_SCAN): automation.validate_automation({}), + cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation({}), cv.Optional(CONF_ON_TAG): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(nfc.NfcOnTagTrigger), @@ -227,12 +207,14 @@ async def setup_pn7160(var, config): ) for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_emulated_tag_scan_callback", [], conf + ) for conf in config.get(CONF_ON_FINISHED_WRITE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_finished_write_callback", [], conf + ) @automation.register_condition( diff --git a/esphome/components/pn7160/automation.h b/esphome/components/pn7160/automation.h index 08148c2311..7759da8f53 100644 --- a/esphome/components/pn7160/automation.h +++ b/esphome/components/pn7160/automation.h @@ -7,20 +7,6 @@ namespace esphome { namespace pn7160 { -class PN7160OnEmulatedTagScanTrigger : public Trigger<> { - public: - explicit PN7160OnEmulatedTagScanTrigger(PN7160 *parent) { - parent->add_on_emulated_tag_scan_callback([this]() { this->trigger(); }); - } -}; - -class PN7160OnFinishedWriteTrigger : public Trigger<> { - public: - explicit PN7160OnFinishedWriteTrigger(PN7160 *parent) { - parent->add_on_finished_write_callback([this]() { this->trigger(); }); - } -}; - template<typename... Ts> class PN7160IsWritingCondition : public Condition<Ts...>, public Parented<PN7160> { public: bool check(const Ts &...x) override { return this->parent_->is_writing(); } From a5416df6155172ff80869caa8e183cd58e552e18 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:36 -1000 Subject: [PATCH 1756/2030] [sim800l] Migrate triggers to callback automation (#15222) --- esphome/components/sim800l/__init__.py | 93 +++++++------------------- esphome/components/sim800l/sim800l.h | 35 ---------- 2 files changed, 23 insertions(+), 105 deletions(-) diff --git a/esphome/components/sim800l/__init__.py b/esphome/components/sim800l/__init__.py index ebb74302a9..91771047e1 100644 --- a/esphome/components/sim800l/__init__.py +++ b/esphome/components/sim800l/__init__.py @@ -2,7 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import uart import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_MESSAGE, CONF_TRIGGER_ID +from esphome.const import CONF_ID, CONF_MESSAGE DEPENDENCIES = ["uart"] CODEOWNERS = ["@glmnet"] @@ -11,28 +11,6 @@ MULTI_CONF = True sim800l_ns = cg.esphome_ns.namespace("sim800l") Sim800LComponent = sim800l_ns.class_("Sim800LComponent", cg.Component) -Sim800LReceivedMessageTrigger = sim800l_ns.class_( - "Sim800LReceivedMessageTrigger", - automation.Trigger.template(cg.std_string, cg.std_string), -) -Sim800LIncomingCallTrigger = sim800l_ns.class_( - "Sim800LIncomingCallTrigger", - automation.Trigger.template(cg.std_string), -) -Sim800LCallConnectedTrigger = sim800l_ns.class_( - "Sim800LCallConnectedTrigger", - automation.Trigger.template(), -) -Sim800LCallDisconnectedTrigger = sim800l_ns.class_( - "Sim800LCallDisconnectedTrigger", - automation.Trigger.template(), -) - -Sim800LReceivedUssdTrigger = sim800l_ns.class_( - "Sim800LReceivedUssdTrigger", - automation.Trigger.template(cg.std_string), -) - # Actions Sim800LSendSmsAction = sim800l_ns.class_("Sim800LSendSmsAction", automation.Action) Sim800LSendUssdAction = sim800l_ns.class_("Sim800LSendUssdAction", automation.Action) @@ -55,41 +33,11 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(Sim800LComponent), - cv.Optional(CONF_ON_SMS_RECEIVED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Sim800LReceivedMessageTrigger - ), - } - ), - cv.Optional(CONF_ON_INCOMING_CALL): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Sim800LIncomingCallTrigger - ), - } - ), - cv.Optional(CONF_ON_CALL_CONNECTED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Sim800LCallConnectedTrigger - ), - } - ), - cv.Optional(CONF_ON_CALL_DISCONNECTED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Sim800LCallDisconnectedTrigger - ), - } - ), - cv.Optional(CONF_ON_USSD_RECEIVED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - Sim800LReceivedUssdTrigger - ), - } - ), + cv.Optional(CONF_ON_SMS_RECEIVED): automation.validate_automation({}), + cv.Optional(CONF_ON_INCOMING_CALL): automation.validate_automation({}), + cv.Optional(CONF_ON_CALL_CONNECTED): automation.validate_automation({}), + cv.Optional(CONF_ON_CALL_DISCONNECTED): automation.validate_automation({}), + cv.Optional(CONF_ON_USSD_RECEIVED): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("5s")) @@ -106,23 +54,28 @@ async def to_code(config): await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_SMS_RECEIVED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.std_string, "message"), (cg.std_string, "sender")], conf + await automation.build_callback_automation( + var, + "add_on_sms_received_callback", + [(cg.std_string, "message"), (cg.std_string, "sender")], + conf, ) for conf in config.get(CONF_ON_INCOMING_CALL, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "caller_id")], conf) + await automation.build_callback_automation( + var, "add_on_incoming_call_callback", [(cg.std_string, "caller_id")], conf + ) for conf in config.get(CONF_ON_CALL_CONNECTED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_on_call_connected_callback", [], conf + ) for conf in config.get(CONF_ON_CALL_DISCONNECTED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_on_call_disconnected_callback", [], conf + ) for conf in config.get(CONF_ON_USSD_RECEIVED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "ussd")], conf) + await automation.build_callback_automation( + var, "add_on_ussd_received_callback", [(cg.std_string, "ussd")], conf + ) SIM800L_SEND_SMS_SCHEMA = cv.Schema( diff --git a/esphome/components/sim800l/sim800l.h b/esphome/components/sim800l/sim800l.h index d79279ea72..d0da123039 100644 --- a/esphome/components/sim800l/sim800l.h +++ b/esphome/components/sim800l/sim800l.h @@ -121,41 +121,6 @@ class Sim800LComponent : public uart::UARTDevice, public PollingComponent { CallbackManager<void(std::string)> ussd_received_callback_; }; -class Sim800LReceivedMessageTrigger : public Trigger<std::string, std::string> { - public: - explicit Sim800LReceivedMessageTrigger(Sim800LComponent *parent) { - parent->add_on_sms_received_callback( - [this](const std::string &message, const std::string &sender) { this->trigger(message, sender); }); - } -}; - -class Sim800LIncomingCallTrigger : public Trigger<std::string> { - public: - explicit Sim800LIncomingCallTrigger(Sim800LComponent *parent) { - parent->add_on_incoming_call_callback([this](const std::string &caller_id) { this->trigger(caller_id); }); - } -}; - -class Sim800LCallConnectedTrigger : public Trigger<> { - public: - explicit Sim800LCallConnectedTrigger(Sim800LComponent *parent) { - parent->add_on_call_connected_callback([this]() { this->trigger(); }); - } -}; - -class Sim800LCallDisconnectedTrigger : public Trigger<> { - public: - explicit Sim800LCallDisconnectedTrigger(Sim800LComponent *parent) { - parent->add_on_call_disconnected_callback([this]() { this->trigger(); }); - } -}; -class Sim800LReceivedUssdTrigger : public Trigger<std::string> { - public: - explicit Sim800LReceivedUssdTrigger(Sim800LComponent *parent) { - parent->add_on_ussd_received_callback([this](const std::string &ussd) { this->trigger(ussd); }); - } -}; - template<typename... Ts> class Sim800LSendSmsAction : public Action<Ts...> { public: Sim800LSendSmsAction(Sim800LComponent *parent) : parent_(parent) {} From 6ffb5af60ced80ff47720fc572c4476475954f97 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:47 -1000 Subject: [PATCH 1757/2030] [fingerprint_grow] Migrate triggers to callback automation (#15223) --- .../components/fingerprint_grow/__init__.py | 142 +++++------------- .../fingerprint_grow/fingerprint_grow.h | 58 ------- 2 files changed, 36 insertions(+), 164 deletions(-) diff --git a/esphome/components/fingerprint_grow/__init__.py b/esphome/components/fingerprint_grow/__init__.py index 2637097be8..0b01ba7cab 100644 --- a/esphome/components/fingerprint_grow/__init__.py +++ b/esphome/components/fingerprint_grow/__init__.py @@ -21,7 +21,6 @@ from esphome.const import ( CONF_SENSING_PIN, CONF_SPEED, CONF_STATE, - CONF_TRIGGER_ID, ) CODEOWNERS = ["@OnFreund", "@loongyh", "@alexborro"] @@ -38,38 +37,6 @@ FingerprintGrowComponent = fingerprint_grow_ns.class_( "FingerprintGrowComponent", cg.PollingComponent, uart.UARTDevice ) -FingerScanStartTrigger = fingerprint_grow_ns.class_( - "FingerScanStartTrigger", automation.Trigger.template() -) - -FingerScanMatchedTrigger = fingerprint_grow_ns.class_( - "FingerScanMatchedTrigger", automation.Trigger.template(cg.uint16, cg.uint16) -) - -FingerScanUnmatchedTrigger = fingerprint_grow_ns.class_( - "FingerScanUnmatchedTrigger", automation.Trigger.template() -) - -FingerScanMisplacedTrigger = fingerprint_grow_ns.class_( - "FingerScanMisplacedTrigger", automation.Trigger.template() -) - -FingerScanInvalidTrigger = fingerprint_grow_ns.class_( - "FingerScanInvalidTrigger", automation.Trigger.template() -) - -EnrollmentScanTrigger = fingerprint_grow_ns.class_( - "EnrollmentScanTrigger", automation.Trigger.template(cg.uint8, cg.uint16) -) - -EnrollmentDoneTrigger = fingerprint_grow_ns.class_( - "EnrollmentDoneTrigger", automation.Trigger.template(cg.uint16) -) - -EnrollmentFailedTrigger = fingerprint_grow_ns.class_( - "EnrollmentFailedTrigger", automation.Trigger.template(cg.uint16) -) - EnrollmentAction = fingerprint_grow_ns.class_("EnrollmentAction", automation.Action) CancelEnrollmentAction = fingerprint_grow_ns.class_( "CancelEnrollmentAction", automation.Action @@ -125,62 +92,22 @@ CONFIG_SCHEMA = cv.All( ): cv.positive_time_period_milliseconds, cv.Optional(CONF_PASSWORD): cv.uint32_t, cv.Optional(CONF_NEW_PASSWORD): cv.uint32_t, - cv.Optional(CONF_ON_FINGER_SCAN_START): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FingerScanStartTrigger - ), - } - ), + cv.Optional(CONF_ON_FINGER_SCAN_START): automation.validate_automation({}), cv.Optional(CONF_ON_FINGER_SCAN_MATCHED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FingerScanMatchedTrigger - ), - } + {} ), cv.Optional(CONF_ON_FINGER_SCAN_UNMATCHED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FingerScanUnmatchedTrigger - ), - } + {} ), cv.Optional(CONF_ON_FINGER_SCAN_MISPLACED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FingerScanMisplacedTrigger - ), - } + {} ), cv.Optional(CONF_ON_FINGER_SCAN_INVALID): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - FingerScanInvalidTrigger - ), - } - ), - cv.Optional(CONF_ON_ENROLLMENT_SCAN): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - EnrollmentScanTrigger - ), - } - ), - cv.Optional(CONF_ON_ENROLLMENT_DONE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - EnrollmentDoneTrigger - ), - } - ), - cv.Optional(CONF_ON_ENROLLMENT_FAILED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - EnrollmentFailedTrigger - ), - } + {} ), + cv.Optional(CONF_ON_ENROLLMENT_SCAN): automation.validate_automation({}), + cv.Optional(CONF_ON_ENROLLMENT_DONE): automation.validate_automation({}), + cv.Optional(CONF_ON_ENROLLMENT_FAILED): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("500ms")) @@ -214,40 +141,43 @@ async def to_code(config): cg.add(var.set_idle_period_to_sleep_ms(idle_period_to_sleep_ms)) for conf in config.get(CONF_ON_FINGER_SCAN_START, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_on_finger_scan_start_callback", [], conf + ) for conf in config.get(CONF_ON_FINGER_SCAN_MATCHED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.uint16, "finger_id"), (cg.uint16, "confidence")], conf + await automation.build_callback_automation( + var, + "add_on_finger_scan_matched_callback", + [(cg.uint16, "finger_id"), (cg.uint16, "confidence")], + conf, ) - for conf in config.get(CONF_ON_FINGER_SCAN_UNMATCHED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_on_finger_scan_unmatched_callback", [], conf + ) for conf in config.get(CONF_ON_FINGER_SCAN_MISPLACED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_on_finger_scan_misplaced_callback", [], conf + ) for conf in config.get(CONF_ON_FINGER_SCAN_INVALID, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_on_finger_scan_invalid_callback", [], conf + ) for conf in config.get(CONF_ON_ENROLLMENT_SCAN, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.uint8, "scan_num"), (cg.uint16, "finger_id")], conf + await automation.build_callback_automation( + var, + "add_on_enrollment_scan_callback", + [(cg.uint8, "scan_num"), (cg.uint16, "finger_id")], + conf, ) - for conf in config.get(CONF_ON_ENROLLMENT_DONE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.uint16, "finger_id")], conf) - + await automation.build_callback_automation( + var, "add_on_enrollment_done_callback", [(cg.uint16, "finger_id")], conf + ) for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.uint16, "finger_id")], conf) + await automation.build_callback_automation( + var, "add_on_enrollment_failed_callback", [(cg.uint16, "finger_id")], conf + ) @automation.register_action( diff --git a/esphome/components/fingerprint_grow/fingerprint_grow.h b/esphome/components/fingerprint_grow/fingerprint_grow.h index 63839534f6..947c701c98 100644 --- a/esphome/components/fingerprint_grow/fingerprint_grow.h +++ b/esphome/components/fingerprint_grow/fingerprint_grow.h @@ -210,64 +210,6 @@ class FingerprintGrowComponent : public PollingComponent, public uart::UARTDevic CallbackManager<void(uint16_t)> enrollment_failed_callback_; }; -class FingerScanStartTrigger : public Trigger<> { - public: - explicit FingerScanStartTrigger(FingerprintGrowComponent *parent) { - parent->add_on_finger_scan_start_callback([this]() { this->trigger(); }); - } -}; - -class FingerScanMatchedTrigger : public Trigger<uint16_t, uint16_t> { - public: - explicit FingerScanMatchedTrigger(FingerprintGrowComponent *parent) { - parent->add_on_finger_scan_matched_callback( - [this](uint16_t finger_id, uint16_t confidence) { this->trigger(finger_id, confidence); }); - } -}; - -class FingerScanUnmatchedTrigger : public Trigger<> { - public: - explicit FingerScanUnmatchedTrigger(FingerprintGrowComponent *parent) { - parent->add_on_finger_scan_unmatched_callback([this]() { this->trigger(); }); - } -}; - -class FingerScanMisplacedTrigger : public Trigger<> { - public: - explicit FingerScanMisplacedTrigger(FingerprintGrowComponent *parent) { - parent->add_on_finger_scan_misplaced_callback([this]() { this->trigger(); }); - } -}; - -class FingerScanInvalidTrigger : public Trigger<> { - public: - explicit FingerScanInvalidTrigger(FingerprintGrowComponent *parent) { - parent->add_on_finger_scan_invalid_callback([this]() { this->trigger(); }); - } -}; - -class EnrollmentScanTrigger : public Trigger<uint8_t, uint16_t> { - public: - explicit EnrollmentScanTrigger(FingerprintGrowComponent *parent) { - parent->add_on_enrollment_scan_callback( - [this](uint8_t scan_num, uint16_t finger_id) { this->trigger(scan_num, finger_id); }); - } -}; - -class EnrollmentDoneTrigger : public Trigger<uint16_t> { - public: - explicit EnrollmentDoneTrigger(FingerprintGrowComponent *parent) { - parent->add_on_enrollment_done_callback([this](uint16_t finger_id) { this->trigger(finger_id); }); - } -}; - -class EnrollmentFailedTrigger : public Trigger<uint16_t> { - public: - explicit EnrollmentFailedTrigger(FingerprintGrowComponent *parent) { - parent->add_on_enrollment_failed_callback([this](uint16_t finger_id) { this->trigger(finger_id); }); - } -}; - template<typename... Ts> class EnrollmentAction : public Action<Ts...>, public Parented<FingerprintGrowComponent> { public: TEMPLATABLE_VALUE(uint16_t, finger_id) From a95f9f41fb418a66d9d3d550b69aa29d1fc303ed Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:22:58 -1000 Subject: [PATCH 1758/2030] [ltr_als_ps] Migrate triggers to callback automation (#15224) --- esphome/components/ltr_als_ps/ltr_als_ps.h | 36 +++++----------------- esphome/components/ltr_als_ps/sensor.py | 33 ++++++-------------- 2 files changed, 18 insertions(+), 51 deletions(-) diff --git a/esphome/components/ltr_als_ps/ltr_als_ps.h b/esphome/components/ltr_als_ps/ltr_als_ps.h index 2e24a14283..8aa5c9f24b 100644 --- a/esphome/components/ltr_als_ps/ltr_als_ps.h +++ b/esphome/components/ltr_als_ps/ltr_als_ps.h @@ -58,6 +58,14 @@ class LTRAlsPsComponent : public PollingComponent, public i2c::I2CDevice { void set_actual_integration_time_sensor(sensor::Sensor *sensor) { this->actual_integration_time_sensor_ = sensor; } void set_proximity_counts_sensor(sensor::Sensor *sensor) { this->proximity_counts_sensor_ = sensor; } + template<typename F> void add_on_ps_high_trigger_callback(F &&callback) { + this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); + } + + template<typename F> void add_on_ps_low_trigger_callback(F &&callback) { + this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); + } + protected: // // Internal state machine, used to split all the actions into @@ -151,36 +159,8 @@ class LTRAlsPsComponent : public PollingComponent, public i2c::I2CDevice { } bool is_any_ps_sensor_enabled_() const { return this->proximity_counts_sensor_ != nullptr; } - // - // Trigger section for the automations - // - friend class LTRPsHighTrigger; - friend class LTRPsLowTrigger; - CallbackManager<void()> on_ps_high_trigger_callback_; CallbackManager<void()> on_ps_low_trigger_callback_; - - template<typename F> void add_on_ps_high_trigger_callback_(F &&callback) { - this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); - } - - template<typename F> void add_on_ps_low_trigger_callback_(F &&callback) { - this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); - } -}; - -class LTRPsHighTrigger : public Trigger<> { - public: - explicit LTRPsHighTrigger(LTRAlsPsComponent *parent) { - parent->add_on_ps_high_trigger_callback_([this]() { this->trigger(); }); - } -}; - -class LTRPsLowTrigger : public Trigger<> { - public: - explicit LTRPsLowTrigger(LTRAlsPsComponent *parent) { - parent->add_on_ps_low_trigger_callback_([this]() { this->trigger(); }); - } }; } // namespace ltr_als_ps } // namespace esphome diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py index 0dbcff1bfb..57503772a1 100644 --- a/esphome/components/ltr_als_ps/sensor.py +++ b/esphome/components/ltr_als_ps/sensor.py @@ -14,7 +14,6 @@ from esphome.const import ( CONF_INTEGRATION_TIME, CONF_NAME, CONF_REPEAT, - CONF_TRIGGER_ID, CONF_TYPE, DEVICE_CLASS_ILLUMINANCE, ICON_BRIGHTNESS_5, @@ -93,11 +92,6 @@ PS_GAINS = { "64X": PsGain.PS_GAIN_64, } -LTRPsHighTrigger = ltr_als_ps_ns.class_( - "LTRPsHighTrigger", automation.Trigger.template() -) -LTRPsLowTrigger = ltr_als_ps_ns.class_("LTRPsLowTrigger", automation.Trigger.template()) - def validate_integration_time(value): value = cv.positive_time_period_milliseconds(value).total_milliseconds @@ -143,16 +137,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PS_LOW_THRESHOLD, default=0): cv.int_range( min=0, max=65535 ), - cv.Optional(CONF_ON_PS_HIGH_THRESHOLD): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LTRPsHighTrigger), - } - ), - cv.Optional(CONF_ON_PS_LOW_THRESHOLD): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LTRPsLowTrigger), - } - ), + cv.Optional(CONF_ON_PS_HIGH_THRESHOLD): automation.validate_automation({}), + cv.Optional(CONF_ON_PS_LOW_THRESHOLD): automation.validate_automation({}), cv.Optional(CONF_AMBIENT_LIGHT): cv.maybe_simple_value( sensor.sensor_schema( unit_of_measurement=UNIT_LUX, @@ -244,13 +230,14 @@ async def to_code(config): sens = await sensor.new_sensor(prox_cnt_config) cg.add(var.set_proximity_counts_sensor(sens)) - for prox_high_tr in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): - trigger = cg.new_Pvariable(prox_high_tr[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], prox_high_tr) - - for prox_low_tr in config.get(CONF_ON_PS_LOW_THRESHOLD, []): - trigger = cg.new_Pvariable(prox_low_tr[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], prox_low_tr) + for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): + await automation.build_callback_automation( + var, "add_on_ps_high_trigger_callback", [], conf + ) + for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []): + await automation.build_callback_automation( + var, "add_on_ps_low_trigger_callback", [], conf + ) cg.add(var.set_ltr_type(config[CONF_TYPE])) From a73c67e4763c971573e89c0d5b4f7e6971ef2341 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:23:17 -1000 Subject: [PATCH 1759/2030] [ltr501] Migrate triggers to callback automation (#15225) --- esphome/components/ltr501/ltr501.h | 36 +++++++---------------------- esphome/components/ltr501/sensor.py | 31 ++++++++----------------- 2 files changed, 18 insertions(+), 49 deletions(-) diff --git a/esphome/components/ltr501/ltr501.h b/esphome/components/ltr501/ltr501.h index 2bd838a0fe..2b91463108 100644 --- a/esphome/components/ltr501/ltr501.h +++ b/esphome/components/ltr501/ltr501.h @@ -58,6 +58,14 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { void set_actual_integration_time_sensor(sensor::Sensor *sensor) { this->actual_integration_time_sensor_ = sensor; } void set_proximity_counts_sensor(sensor::Sensor *sensor) { this->proximity_counts_sensor_ = sensor; } + template<typename F> void add_on_ps_high_trigger_callback(F &&callback) { + this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); + } + + template<typename F> void add_on_ps_low_trigger_callback(F &&callback) { + this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); + } + protected: // // Internal state machine, used to split all the actions into @@ -151,36 +159,8 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice { } bool is_any_ps_sensor_enabled_() const { return this->proximity_counts_sensor_ != nullptr; } - // - // Trigger section for the automations - // - friend class LTRPsHighTrigger; - friend class LTRPsLowTrigger; - CallbackManager<void()> on_ps_high_trigger_callback_; CallbackManager<void()> on_ps_low_trigger_callback_; - - template<typename F> void add_on_ps_high_trigger_callback_(F &&callback) { - this->on_ps_high_trigger_callback_.add(std::forward<F>(callback)); - } - - template<typename F> void add_on_ps_low_trigger_callback_(F &&callback) { - this->on_ps_low_trigger_callback_.add(std::forward<F>(callback)); - } -}; - -class LTRPsHighTrigger : public Trigger<> { - public: - explicit LTRPsHighTrigger(LTRAlsPs501Component *parent) { - parent->add_on_ps_high_trigger_callback_([this]() { this->trigger(); }); - } -}; - -class LTRPsLowTrigger : public Trigger<> { - public: - explicit LTRPsLowTrigger(LTRAlsPs501Component *parent) { - parent->add_on_ps_low_trigger_callback_([this]() { this->trigger(); }); - } }; } // namespace ltr501 } // namespace esphome diff --git a/esphome/components/ltr501/sensor.py b/esphome/components/ltr501/sensor.py index adaf669a72..712810222c 100644 --- a/esphome/components/ltr501/sensor.py +++ b/esphome/components/ltr501/sensor.py @@ -14,7 +14,6 @@ from esphome.const import ( CONF_INTEGRATION_TIME, CONF_NAME, CONF_REPEAT, - CONF_TRIGGER_ID, CONF_TYPE, DEVICE_CLASS_DISTANCE, DEVICE_CLASS_ILLUMINANCE, @@ -87,9 +86,6 @@ PS_GAINS = { "16X": PsGain.PS_GAIN_16, } -LTRPsHighTrigger = ltr501_ns.class_("LTRPsHighTrigger", automation.Trigger.template()) -LTRPsLowTrigger = ltr501_ns.class_("LTRPsLowTrigger", automation.Trigger.template()) - def validate_integration_time(value): value = cv.positive_time_period_milliseconds(value).total_milliseconds @@ -146,16 +142,8 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PS_LOW_THRESHOLD, default=0): cv.int_range( min=0, max=65535 ), - cv.Optional(CONF_ON_PS_HIGH_THRESHOLD): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LTRPsHighTrigger), - } - ), - cv.Optional(CONF_ON_PS_LOW_THRESHOLD): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LTRPsLowTrigger), - } - ), + cv.Optional(CONF_ON_PS_HIGH_THRESHOLD): automation.validate_automation({}), + cv.Optional(CONF_ON_PS_LOW_THRESHOLD): automation.validate_automation({}), cv.Optional(CONF_AMBIENT_LIGHT): cv.maybe_simple_value( sensor.sensor_schema( unit_of_measurement=UNIT_LUX, @@ -252,13 +240,14 @@ async def to_code(config): sens = await sensor.new_sensor(prox_cnt_config) cg.add(var.set_proximity_counts_sensor(sens)) - for prox_high_tr in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): - trigger = cg.new_Pvariable(prox_high_tr[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], prox_high_tr) - - for prox_low_tr in config.get(CONF_ON_PS_LOW_THRESHOLD, []): - trigger = cg.new_Pvariable(prox_low_tr[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], prox_low_tr) + for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): + await automation.build_callback_automation( + var, "add_on_ps_high_trigger_callback", [], conf + ) + for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []): + await automation.build_callback_automation( + var, "add_on_ps_low_trigger_callback", [], conf + ) cg.add(var.set_ltr_type(config[CONF_TYPE])) From f5cd1e5e76831637ecf987439e205243a32c1fb6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:23:26 -1000 Subject: [PATCH 1760/2030] [ld2450] Fix flaky integration test race condition (#15226) --- tests/integration/test_uart_mock_ld2450.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_uart_mock_ld2450.py b/tests/integration/test_uart_mock_ld2450.py index b1aa2f6952..2469273e0a 100644 --- a/tests/integration/test_uart_mock_ld2450.py +++ b/tests/integration/test_uart_mock_ld2450.py @@ -83,11 +83,18 @@ async def test_uart_mock_ld2450( ], ) - # Signal when we see recovery frame values (target 1 distance ≈ 500mm) + # Signal when we see all recovery frame values + # Must wait for ALL values to avoid race where some arrive after the waiter fires recovery_received = collector.add_waiter( lambda: ( pytest.approx(500.0, abs=1.0) in collector.sensor_states["target_1_distance"] + and pytest.approx(300.0) in collector.sensor_states["target_1_x"] + and pytest.approx(400.0) in collector.sensor_states["target_1_y"] + and pytest.approx(30.0) in collector.sensor_states["target_1_speed"] + and pytest.approx(1.0) in collector.sensor_states["target_count"] + and pytest.approx(1.0) in collector.sensor_states["moving_target_count"] + and pytest.approx(0.0) in collector.sensor_states["still_target_count"] ) ) From d77bf23c76b7257d20cd0c9541eabcf2613adf69 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:23:37 -1000 Subject: [PATCH 1761/2030] [nextion] Migrate triggers to callback automation (#15227) --- esphome/components/nextion/automation.h | 44 ------------ esphome/components/nextion/display.py | 90 +++++++------------------ 2 files changed, 25 insertions(+), 109 deletions(-) diff --git a/esphome/components/nextion/automation.h b/esphome/components/nextion/automation.h index 8e85e15823..9f52507d67 100644 --- a/esphome/components/nextion/automation.h +++ b/esphome/components/nextion/automation.h @@ -5,50 +5,6 @@ namespace esphome { namespace nextion { -class BufferOverflowTrigger : public Trigger<> { - public: - explicit BufferOverflowTrigger(Nextion *nextion) { - nextion->add_buffer_overflow_event_callback([this]() { this->trigger(); }); - } -}; - -class SetupTrigger : public Trigger<> { - public: - explicit SetupTrigger(Nextion *nextion) { - nextion->add_setup_state_callback([this]() { this->trigger(); }); - } -}; - -class SleepTrigger : public Trigger<> { - public: - explicit SleepTrigger(Nextion *nextion) { - nextion->add_sleep_state_callback([this]() { this->trigger(); }); - } -}; - -class WakeTrigger : public Trigger<> { - public: - explicit WakeTrigger(Nextion *nextion) { - nextion->add_wake_state_callback([this]() { this->trigger(); }); - } -}; - -class PageTrigger : public Trigger<uint8_t> { - public: - explicit PageTrigger(Nextion *nextion) { - nextion->add_new_page_callback([this](const uint8_t page_id) { this->trigger(page_id); }); - } -}; - -class TouchTrigger : public Trigger<uint8_t, uint8_t, bool> { - public: - explicit TouchTrigger(Nextion *nextion) { - nextion->add_touch_event_callback([this](uint8_t page_id, uint8_t component_id, bool touch_event) { - this->trigger(page_id, component_id, touch_event); - }); - } -}; - template<typename... Ts> class NextionSetBrightnessAction : public Action<Ts...> { public: explicit NextionSetBrightnessAction(Nextion *component) : component_(component) {} diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 5b2dfc488d..506eb1202b 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -2,13 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import display, esp32, uart import esphome.config_validation as cv -from esphome.const import ( - CONF_BRIGHTNESS, - CONF_ID, - CONF_LAMBDA, - CONF_ON_TOUCH, - CONF_TRIGGER_ID, -) +from esphome.const import CONF_BRIGHTNESS, CONF_ID, CONF_LAMBDA, CONF_ON_TOUCH from esphome.core import CORE, TimePeriod from . import ( # noqa: F401 pylint: disable=unused-import @@ -55,14 +49,6 @@ def AUTO_LOAD() -> list[str]: NextionSetBrightnessAction = nextion_ns.class_( "NextionSetBrightnessAction", automation.Action ) -SetupTrigger = nextion_ns.class_("SetupTrigger", automation.Trigger.template()) -SleepTrigger = nextion_ns.class_("SleepTrigger", automation.Trigger.template()) -WakeTrigger = nextion_ns.class_("WakeTrigger", automation.Trigger.template()) -PageTrigger = nextion_ns.class_("PageTrigger", automation.Trigger.template()) -TouchTrigger = nextion_ns.class_("TouchTrigger", automation.Trigger.template()) -BufferOverflowTrigger = nextion_ns.class_( - "BufferOverflowTrigger", automation.Trigger.template() -) def _validate_tft_upload(config): @@ -101,38 +87,12 @@ CONFIG_SCHEMA = cv.All( ), cv.Optional(CONF_MAX_COMMANDS_PER_LOOP): cv.uint16_t, cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int, - cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - BufferOverflowTrigger - ), - } - ), - cv.Optional(CONF_ON_PAGE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PageTrigger), - } - ), - cv.Optional(CONF_ON_SETUP): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SetupTrigger), - } - ), - cv.Optional(CONF_ON_SLEEP): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SleepTrigger), - } - ), - cv.Optional(CONF_ON_TOUCH): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TouchTrigger), - } - ), - cv.Optional(CONF_ON_WAKE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(WakeTrigger), - } - ), + cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation({}), + cv.Optional(CONF_ON_PAGE): automation.validate_automation({}), + cv.Optional(CONF_ON_SETUP): automation.validate_automation({}), + cv.Optional(CONF_ON_SLEEP): automation.validate_automation({}), + cv.Optional(CONF_ON_TOUCH): automation.validate_automation({}), + cv.Optional(CONF_ON_WAKE): automation.validate_automation({}), cv.Optional(CONF_SKIP_CONNECTION_HANDSHAKE, default=False): cv.boolean, cv.Optional(CONF_STARTUP_OVERRIDE_MS, default="8000ms"): cv.All( cv.positive_time_period_milliseconds, @@ -273,25 +233,25 @@ async def to_code(config): await display.register_display(var, config) for conf in config.get(CONF_ON_SETUP, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_setup_state_callback", [], conf + ) for conf in config.get(CONF_ON_SLEEP, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_sleep_state_callback", [], conf + ) for conf in config.get(CONF_ON_WAKE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) - + await automation.build_callback_automation( + var, "add_wake_state_callback", [], conf + ) for conf in config.get(CONF_ON_PAGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.uint8, "x")], conf) - + await automation.build_callback_automation( + var, "add_new_page_callback", [(cg.uint8, "x")], conf + ) for conf in config.get(CONF_ON_TOUCH, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, + await automation.build_callback_automation( + var, + "add_touch_event_callback", [ (cg.uint8, "page_id"), (cg.uint8, "component_id"), @@ -299,7 +259,7 @@ async def to_code(config): ], conf, ) - for conf in config.get(CONF_ON_BUFFER_OVERFLOW, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [], conf) + await automation.build_callback_automation( + var, "add_buffer_overflow_event_callback", [], conf + ) From 2f3c21c7c16b37d2ad1f57e4d90883129a50c86c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:23:50 -1000 Subject: [PATCH 1762/2030] [ezo] Migrate triggers to callback automation (#15228) --- esphome/components/ezo/automation.h | 53 ---------------- esphome/components/ezo/sensor.py | 94 ++++++++--------------------- 2 files changed, 25 insertions(+), 122 deletions(-) delete mode 100644 esphome/components/ezo/automation.h diff --git a/esphome/components/ezo/automation.h b/esphome/components/ezo/automation.h deleted file mode 100644 index a4a6fa3014..0000000000 --- a/esphome/components/ezo/automation.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include <utility> - -#include "esphome/core/automation.h" -#include "ezo.h" - -namespace esphome { -namespace ezo { - -class LedTrigger : public Trigger<bool> { - public: - explicit LedTrigger(EZOSensor *ezo) { - ezo->add_led_state_callback([this](bool value) { this->trigger(value); }); - } -}; - -class CustomTrigger : public Trigger<std::string> { - public: - explicit CustomTrigger(EZOSensor *ezo) { - ezo->add_custom_callback([this](const std::string &value) { this->trigger(value); }); - } -}; - -class TTrigger : public Trigger<std::string> { - public: - explicit TTrigger(EZOSensor *ezo) { - ezo->add_t_callback([this](const std::string &value) { this->trigger(value); }); - } -}; - -class CalibrationTrigger : public Trigger<std::string> { - public: - explicit CalibrationTrigger(EZOSensor *ezo) { - ezo->add_calibration_callback([this](const std::string &value) { this->trigger(value); }); - } -}; - -class SlopeTrigger : public Trigger<std::string> { - public: - explicit SlopeTrigger(EZOSensor *ezo) { - ezo->add_slope_callback([this](const std::string &value) { this->trigger(value); }); - } -}; - -class DeviceInformationTrigger : public Trigger<std::string> { - public: - explicit DeviceInformationTrigger(EZOSensor *ezo) { - ezo->add_device_infomation_callback([this](const std::string &value) { this->trigger(value); }); - } -}; - -} // namespace ezo -} // namespace esphome diff --git a/esphome/components/ezo/sensor.py b/esphome/components/ezo/sensor.py index cf240faec3..7c81f9c848 100644 --- a/esphome/components/ezo/sensor.py +++ b/esphome/components/ezo/sensor.py @@ -2,7 +2,7 @@ from esphome import automation import esphome.codegen as cg from esphome.components import i2c, sensor import esphome.config_validation as cv -from esphome.const import CONF_ID, CONF_TRIGGER_ID +from esphome.const import CONF_ID CODEOWNERS = ["@ssieb"] @@ -21,61 +21,16 @@ EZOSensor = ezo_ns.class_( "EZOSensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice ) -CustomTrigger = ezo_ns.class_( - "CustomTrigger", automation.Trigger.template(cg.std_string) -) - - -TTrigger = ezo_ns.class_("TTrigger", automation.Trigger.template(cg.std_string)) - -SlopeTrigger = ezo_ns.class_("SlopeTrigger", automation.Trigger.template(cg.std_string)) - -CalibrationTrigger = ezo_ns.class_( - "CalibrationTrigger", automation.Trigger.template(cg.std_string) -) - -DeviceInformationTrigger = ezo_ns.class_( - "DeviceInformationTrigger", automation.Trigger.template(cg.std_string) -) - -LedTrigger = ezo_ns.class_("LedTrigger", automation.Trigger.template(cg.bool_)) - CONFIG_SCHEMA = ( sensor.sensor_schema(EZOSensor) .extend( { - cv.Optional(CONF_ON_CUSTOM): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CustomTrigger), - } - ), - cv.Optional(CONF_ON_CALIBRATION): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CalibrationTrigger), - } - ), - cv.Optional(CONF_ON_SLOPE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SlopeTrigger), - } - ), - cv.Optional(CONF_ON_T): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TTrigger), - } - ), - cv.Optional(CONF_ON_DEVICE_INFORMATION): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - DeviceInformationTrigger - ), - } - ), - cv.Optional(CONF_ON_LED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LedTrigger), - } - ), + cv.Optional(CONF_ON_CUSTOM): automation.validate_automation({}), + cv.Optional(CONF_ON_CALIBRATION): automation.validate_automation({}), + cv.Optional(CONF_ON_SLOPE): automation.validate_automation({}), + cv.Optional(CONF_ON_T): automation.validate_automation({}), + cv.Optional(CONF_ON_DEVICE_INFORMATION): automation.validate_automation({}), + cv.Optional(CONF_ON_LED): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("60s")) @@ -90,25 +45,26 @@ async def to_code(config): await i2c.register_i2c_device(var, config) for conf in config.get(CONF_ON_CUSTOM, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - + await automation.build_callback_automation( + var, "add_custom_callback", [(cg.std_string, "x")], conf + ) for conf in config.get(CONF_ON_LED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(bool, "x")], conf) - + await automation.build_callback_automation( + var, "add_led_state_callback", [(bool, "x")], conf + ) for conf in config.get(CONF_ON_DEVICE_INFORMATION, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - + await automation.build_callback_automation( + var, "add_device_infomation_callback", [(cg.std_string, "x")], conf + ) for conf in config.get(CONF_ON_SLOPE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - + await automation.build_callback_automation( + var, "add_slope_callback", [(cg.std_string, "x")], conf + ) for conf in config.get(CONF_ON_CALIBRATION, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) - + await automation.build_callback_automation( + var, "add_calibration_callback", [(cg.std_string, "x")], conf + ) for conf in config.get(CONF_ON_T, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(cg.std_string, "x")], conf) + await automation.build_callback_automation( + var, "add_t_callback", [(cg.std_string, "x")], conf + ) From 39509265bc76a0eadce17c9e28a4b032fc3597fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:24:03 -1000 Subject: [PATCH 1763/2030] [haier] Migrate triggers to callback automation (#15229) --- esphome/components/haier/climate.py | 62 ++++++++------------------ esphome/components/haier/haier_base.h | 7 --- esphome/components/haier/hon_climate.h | 16 ------- 3 files changed, 18 insertions(+), 67 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index caaaa18dd6..9c2c999f25 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -22,7 +22,6 @@ from esphome.const import ( CONF_SUPPORTED_SWING_MODES, CONF_TARGET_TEMPERATURE, CONF_TEMPERATURE_STEP, - CONF_TRIGGER_ID, CONF_VISUAL, CONF_WIFI, ) @@ -122,21 +121,6 @@ SUPPORTED_HON_CONTROL_METHODS = { "SET_SINGLE_PARAMETER": HonControlMethod.SET_SINGLE_PARAMETER, } -HaierAlarmStartTrigger = haier_ns.class_( - "HaierAlarmStartTrigger", - automation.Trigger.template(cg.uint8, cg.const_char_ptr), -) - -HaierAlarmEndTrigger = haier_ns.class_( - "HaierAlarmEndTrigger", - automation.Trigger.template(cg.uint8, cg.const_char_ptr), -) - -StatusMessageTrigger = haier_ns.class_( - "StatusMessageTrigger", - automation.Trigger.template(cg.const_char_ptr, cg.size_t), -) - def validate_visual(config): if CONF_VISUAL in config: @@ -203,13 +187,7 @@ def _base_config_schema(class_: MockObjClass) -> cv.Schema: cv.Optional( CONF_ANSWER_TIMEOUT, ): cv.positive_time_period_milliseconds, - cv.Optional(CONF_ON_STATUS_MESSAGE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - StatusMessageTrigger - ), - } - ), + cv.Optional(CONF_ON_STATUS_MESSAGE): automation.validate_automation({}), } ) .extend(uart.UART_DEVICE_SCHEMA) @@ -264,19 +242,9 @@ CONFIG_SCHEMA = cv.All( f"The {CONF_OUTDOOR_TEMPERATURE} option is deprecated, use a sensor for a haier platform instead" ), cv.Optional(CONF_ON_ALARM_START): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - HaierAlarmStartTrigger - ), - } - ), - cv.Optional(CONF_ON_ALARM_END): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - HaierAlarmEndTrigger - ), - } + {} ), + cv.Optional(CONF_ON_ALARM_END): automation.validate_automation({}), } ), }, @@ -530,19 +498,25 @@ async def to_code(config): var.set_status_message_header_size(config[CONF_STATUS_MESSAGE_HEADER_SIZE]) ) for conf in config.get(CONF_ON_ALARM_START, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.uint8, "code"), (cg.const_char_ptr, "message")], conf + await automation.build_callback_automation( + var, + "add_alarm_start_callback", + [(cg.uint8, "code"), (cg.const_char_ptr, "message")], + conf, ) for conf in config.get(CONF_ON_ALARM_END, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.uint8, "code"), (cg.const_char_ptr, "message")], conf + await automation.build_callback_automation( + var, + "add_alarm_end_callback", + [(cg.uint8, "code"), (cg.const_char_ptr, "message")], + conf, ) for conf in config.get(CONF_ON_STATUS_MESSAGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.const_char_ptr, "data"), (cg.size_t, "data_size")], conf + await automation.build_callback_automation( + var, + "add_status_message_callback", + [(cg.const_char_ptr, "data"), (cg.size_t, "data_size")], + conf, ) # https://github.com/paveldn/HaierProtocol cg.add_library("pavlodn/HaierProtocol", "0.9.31") diff --git a/esphome/components/haier/haier_base.h b/esphome/components/haier/haier_base.h index 87aa1d65ef..0c416623c0 100644 --- a/esphome/components/haier/haier_base.h +++ b/esphome/components/haier/haier_base.h @@ -177,12 +177,5 @@ class HaierClimateBase : public esphome::Component, ESPPreferenceObject base_rtc_; }; -class StatusMessageTrigger : public Trigger<const char *, size_t> { - public: - explicit StatusMessageTrigger(HaierClimateBase *parent) { - parent->add_status_message_callback([this](const char *data, size_t data_size) { this->trigger(data, data_size); }); - } -}; - } // namespace haier } // namespace esphome diff --git a/esphome/components/haier/hon_climate.h b/esphome/components/haier/hon_climate.h index 7c48a3748b..7a87f27b66 100644 --- a/esphome/components/haier/hon_climate.h +++ b/esphome/components/haier/hon_climate.h @@ -200,21 +200,5 @@ class HonClimate : public HaierClimateBase { SwitchState quiet_mode_state_{SwitchState::OFF}; }; -class HaierAlarmStartTrigger : public Trigger<uint8_t, const char *> { - public: - explicit HaierAlarmStartTrigger(HonClimate *parent) { - parent->add_alarm_start_callback( - [this](uint8_t alarm_code, const char *alarm_message) { this->trigger(alarm_code, alarm_message); }); - } -}; - -class HaierAlarmEndTrigger : public Trigger<uint8_t, const char *> { - public: - explicit HaierAlarmEndTrigger(HonClimate *parent) { - parent->add_alarm_end_callback( - [this](uint8_t alarm_code, const char *alarm_message) { this->trigger(alarm_code, alarm_message); }); - } -}; - } // namespace haier } // namespace esphome From f9d41bd36adf4923f0509db82da47c321ffafcac Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:24:15 -1000 Subject: [PATCH 1764/2030] [modbus_controller] Migrate triggers to callback automation (#15230) --- .../components/modbus_controller/__init__.py | 64 ++++++------------- .../components/modbus_controller/automation.h | 35 ---------- 2 files changed, 19 insertions(+), 80 deletions(-) delete mode 100644 esphome/components/modbus_controller/automation.h diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index aea79b2053..dfc43bf23b 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -5,14 +5,7 @@ import esphome.codegen as cg from esphome.components import modbus from esphome.components.const import CONF_ENABLED import esphome.config_validation as cv -from esphome.const import ( - CONF_ADDRESS, - CONF_ID, - CONF_LAMBDA, - CONF_NAME, - CONF_OFFSET, - CONF_TRIGGER_ID, -) +from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_OFFSET from esphome.cpp_helpers import logging from .const import ( @@ -135,17 +128,6 @@ CPP_TYPE_REGISTER_MAP = { "FP32_R": cg.float_, } -ModbusCommandSentTrigger = modbus_controller_ns.class_( - "ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_) -) - -ModbusOnlineTrigger = modbus_controller_ns.class_( - "ModbusOnlineTrigger", automation.Trigger.template(cg.int_, cg.int_) -) - -ModbusOfflineTrigger = modbus_controller_ns.class_( - "ModbusOfflineTrigger", automation.Trigger.template(cg.int_, cg.int_) -) _LOGGER = logging.getLogger(__name__) @@ -182,23 +164,9 @@ CONFIG_SCHEMA = cv.All( cv.Optional( CONF_SERVER_REGISTERS, ): cv.ensure_list(ModbusServerRegisterSchema), - cv.Optional(CONF_ON_COMMAND_SENT): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - ModbusCommandSentTrigger - ), - } - ), - cv.Optional(CONF_ON_ONLINE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOnlineTrigger), - } - ), - cv.Optional(CONF_ON_OFFLINE): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ModbusOfflineTrigger), - } - ), + cv.Optional(CONF_ON_COMMAND_SENT): automation.validate_automation({}), + cv.Optional(CONF_ON_ONLINE): automation.validate_automation({}), + cv.Optional(CONF_ON_OFFLINE): automation.validate_automation({}), } ) .extend(cv.polling_component_schema("60s")) @@ -363,19 +331,25 @@ async def to_code(config): cg.add(var.add_server_register(server_register_var)) await register_modbus_device(var, config) for conf in config.get(CONF_ON_COMMAND_SENT, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf + await automation.build_callback_automation( + var, + "add_on_command_sent_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + conf, ) for conf in config.get(CONF_ON_ONLINE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf + await automation.build_callback_automation( + var, + "add_on_online_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + conf, ) for conf in config.get(CONF_ON_OFFLINE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(cg.int_, "function_code"), (cg.int_, "address")], conf + await automation.build_callback_automation( + var, + "add_on_offline_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + conf, ) diff --git a/esphome/components/modbus_controller/automation.h b/esphome/components/modbus_controller/automation.h deleted file mode 100644 index b3338192cc..0000000000 --- a/esphome/components/modbus_controller/automation.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/core/automation.h" -#include "esphome/components/modbus_controller/modbus_controller.h" - -namespace esphome { -namespace modbus_controller { - -class ModbusCommandSentTrigger : public Trigger<int, int> { - public: - ModbusCommandSentTrigger(ModbusController *a_modbuscontroller) { - a_modbuscontroller->add_on_command_sent_callback( - [this](int function_code, int address) { this->trigger(function_code, address); }); - } -}; - -class ModbusOnlineTrigger : public Trigger<int, int> { - public: - ModbusOnlineTrigger(ModbusController *a_modbuscontroller) { - a_modbuscontroller->add_on_online_callback( - [this](int function_code, int address) { this->trigger(function_code, address); }); - } -}; - -class ModbusOfflineTrigger : public Trigger<int, int> { - public: - ModbusOfflineTrigger(ModbusController *a_modbuscontroller) { - a_modbuscontroller->add_on_offline_callback( - [this](int function_code, int address) { this->trigger(function_code, address); }); - } -}; - -} // namespace modbus_controller -} // namespace esphome From 0d67f91facbe654bbb634d95aa16c791ff52a3f2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:24:25 -1000 Subject: [PATCH 1765/2030] [rf_bridge] Migrate triggers to callback automation (#15231) --- esphome/components/rf_bridge/__init__.py | 37 +++++++----------------- esphome/components/rf_bridge/rf_bridge.h | 14 --------- 2 files changed, 10 insertions(+), 41 deletions(-) diff --git a/esphome/components/rf_bridge/__init__.py b/esphome/components/rf_bridge/__init__.py index 934f24b789..c6eb1749c3 100644 --- a/esphome/components/rf_bridge/__init__.py +++ b/esphome/components/rf_bridge/__init__.py @@ -12,7 +12,6 @@ from esphome.const import ( CONF_PROTOCOL, CONF_RAW, CONF_SYNC, - CONF_TRIGGER_ID, ) DEPENDENCIES = ["uart"] @@ -26,14 +25,6 @@ RFBridgeComponent = rf_bridge_ns.class_( RFBridgeData = rf_bridge_ns.struct("RFBridgeData") RFBridgeAdvancedData = rf_bridge_ns.struct("RFBridgeAdvancedData") -RFBridgeReceivedCodeTrigger = rf_bridge_ns.class_( - "RFBridgeReceivedCodeTrigger", automation.Trigger.template(RFBridgeData) -) -RFBridgeReceivedAdvancedCodeTrigger = rf_bridge_ns.class_( - "RFBridgeReceivedAdvancedCodeTrigger", - automation.Trigger.template(RFBridgeAdvancedData), -) - RFBridgeSendCodeAction = rf_bridge_ns.class_( "RFBridgeSendCodeAction", automation.Action ) @@ -65,19 +56,9 @@ CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(RFBridgeComponent), - cv.Optional(CONF_ON_CODE_RECEIVED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - RFBridgeReceivedCodeTrigger - ), - } - ), + cv.Optional(CONF_ON_CODE_RECEIVED): automation.validate_automation({}), cv.Optional(CONF_ON_ADVANCED_CODE_RECEIVED): automation.validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( - RFBridgeReceivedAdvancedCodeTrigger - ), - } + {} ), } ) @@ -92,13 +73,15 @@ async def to_code(config): await uart.register_uart_device(var, config) for conf in config.get(CONF_ON_CODE_RECEIVED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation(trigger, [(RFBridgeData, "data")], conf) - + await automation.build_callback_automation( + var, "add_on_code_received_callback", [(RFBridgeData, "data")], conf + ) for conf in config.get(CONF_ON_ADVANCED_CODE_RECEIVED, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await automation.build_automation( - trigger, [(RFBridgeAdvancedData, "data")], conf + await automation.build_callback_automation( + var, + "add_on_advanced_code_received_callback", + [(RFBridgeAdvancedData, "data")], + conf, ) diff --git a/esphome/components/rf_bridge/rf_bridge.h b/esphome/components/rf_bridge/rf_bridge.h index e5780c9ebe..571ac6c385 100644 --- a/esphome/components/rf_bridge/rf_bridge.h +++ b/esphome/components/rf_bridge/rf_bridge.h @@ -77,20 +77,6 @@ class RFBridgeComponent : public uart::UARTDevice, public Component { CallbackManager<void(RFBridgeAdvancedData)> advanced_data_callback_; }; -class RFBridgeReceivedCodeTrigger : public Trigger<RFBridgeData> { - public: - explicit RFBridgeReceivedCodeTrigger(RFBridgeComponent *parent) { - parent->add_on_code_received_callback([this](RFBridgeData data) { this->trigger(data); }); - } -}; - -class RFBridgeReceivedAdvancedCodeTrigger : public Trigger<RFBridgeAdvancedData> { - public: - explicit RFBridgeReceivedAdvancedCodeTrigger(RFBridgeComponent *parent) { - parent->add_on_advanced_code_received_callback([this](const RFBridgeAdvancedData &data) { this->trigger(data); }); - } -}; - template<typename... Ts> class RFBridgeSendCodeAction : public Action<Ts...> { public: RFBridgeSendCodeAction(RFBridgeComponent *parent) : parent_(parent) {} From 5a8d6931a8d8a0f1fe05727e2e5d00098aa2dbb4 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 27 Mar 2026 08:24:35 -1000 Subject: [PATCH 1766/2030] [factory_reset] Migrate FastBootTrigger to callback automation (#15232) --- esphome/components/factory_reset/__init__.py | 21 ++++++------------- .../components/factory_reset/factory_reset.h | 6 ------ 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/esphome/components/factory_reset/__init__.py b/esphome/components/factory_reset/__init__.py index 5784d09ce6..20b191a2b7 100644 --- a/esphome/components/factory_reset/__init__.py +++ b/esphome/components/factory_reset/__init__.py @@ -1,10 +1,9 @@ -from esphome.automation import Trigger, build_automation, validate_automation +from esphome import automation import esphome.codegen as cg from esphome.components.esp8266 import CONF_RESTORE_FROM_FLASH, KEY_ESP8266 import esphome.config_validation as cv from esphome.const import ( CONF_ID, - CONF_TRIGGER_ID, PLATFORM_BK72XX, PLATFORM_ESP32, PLATFORM_ESP8266, @@ -18,7 +17,6 @@ CODEOWNERS = ["@anatoly-savchenkov"] factory_reset_ns = cg.esphome_ns.namespace("factory_reset") FactoryResetComponent = factory_reset_ns.class_("FactoryResetComponent", cg.Component) -FastBootTrigger = factory_reset_ns.class_("FastBootTrigger", Trigger, cg.Component) CONF_MAX_DELAY = "max_delay" CONF_RESETS_REQUIRED = "resets_required" @@ -55,11 +53,7 @@ CONFIG_SCHEMA = cv.All( ), ), cv.Optional(CONF_RESETS_REQUIRED): cv.positive_not_null_int, - cv.Optional(CONF_ON_INCREMENT): validate_automation( - { - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FastBootTrigger), - } - ), + cv.Optional(CONF_ON_INCREMENT): automation.validate_automation({}), } ).extend(cv.COMPONENT_SCHEMA), _validate, @@ -88,12 +82,9 @@ async def to_code(config): ) await cg.register_component(var, config) for conf in config.get(CONF_ON_INCREMENT, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - await build_automation( - trigger, - [ - (cg.uint8, "x"), - (cg.uint8, "target"), - ], + await automation.build_callback_automation( + var, + "add_increment_callback", + [(cg.uint8, "x"), (cg.uint8, "target")], conf, ) diff --git a/esphome/components/factory_reset/factory_reset.h b/esphome/components/factory_reset/factory_reset.h index 34f89d73b6..41ee627c4b 100644 --- a/esphome/components/factory_reset/factory_reset.h +++ b/esphome/components/factory_reset/factory_reset.h @@ -30,12 +30,6 @@ class FactoryResetComponent : public Component { uint8_t required_count_; // The number of boot attempts before fast boot is enabled }; -class FastBootTrigger : public Trigger<uint8_t, uint8_t> { - public: - explicit FastBootTrigger(FactoryResetComponent *parent) { - parent->add_increment_callback([this](uint8_t current, uint8_t target) { this->trigger(current, target); }); - } -}; } // namespace esphome::factory_reset #endif // !defined(USE_RP2040) && !defined(USE_HOST) From 810c046cc68dba48b3748f4a60de2049146beee7 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:25:38 -0400 Subject: [PATCH 1767/2030] [multiple] Fix misc hardware register bugs (#15208) --- esphome/components/mcp23008/mcp23008.cpp | 4 +++- esphome/components/mcp23017/mcp23017.cpp | 6 ++++-- esphome/components/mcp23s08/mcp23s08.cpp | 15 ++++++++++----- esphome/components/mcp23s17/mcp23s17.cpp | 22 +++++++++++++--------- esphome/components/mmc5603/mmc5603.cpp | 6 +++--- esphome/components/sx1509/sx1509.cpp | 4 ++-- 6 files changed, 35 insertions(+), 22 deletions(-) diff --git a/esphome/components/mcp23008/mcp23008.cpp b/esphome/components/mcp23008/mcp23008.cpp index 0c34e4971a..64b120daa4 100644 --- a/esphome/components/mcp23008/mcp23008.cpp +++ b/esphome/components/mcp23008/mcp23008.cpp @@ -6,6 +6,8 @@ namespace mcp23008 { static const char *const TAG = "mcp23008"; +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin + void MCP23008::setup() { uint8_t iocon; if (!this->read_reg(mcp23x08_base::MCP23X08_IOCON, &iocon)) { @@ -18,7 +20,7 @@ void MCP23008::setup() { if (this->open_drain_ints_) { // enable open-drain interrupt pins, 3.3V-safe - this->write_reg(mcp23x08_base::MCP23X08_IOCON, 0x04); + this->write_reg(mcp23x08_base::MCP23X08_IOCON, iocon | IOCON_ODR); } } diff --git a/esphome/components/mcp23017/mcp23017.cpp b/esphome/components/mcp23017/mcp23017.cpp index 1ad2036939..e14e317d44 100644 --- a/esphome/components/mcp23017/mcp23017.cpp +++ b/esphome/components/mcp23017/mcp23017.cpp @@ -6,6 +6,8 @@ namespace mcp23017 { static const char *const TAG = "mcp23017"; +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin + void MCP23017::setup() { uint8_t iocon; if (!this->read_reg(mcp23x17_base::MCP23X17_IOCONA, &iocon)) { @@ -19,8 +21,8 @@ void MCP23017::setup() { if (this->open_drain_ints_) { // enable open-drain interrupt pins, 3.3V-safe - this->write_reg(mcp23x17_base::MCP23X17_IOCONA, 0x04); - this->write_reg(mcp23x17_base::MCP23X17_IOCONB, 0x04); + this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon | IOCON_ODR); + this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | IOCON_ODR); } } diff --git a/esphome/components/mcp23s08/mcp23s08.cpp b/esphome/components/mcp23s08/mcp23s08.cpp index 3d944b45d5..1c17b66637 100644 --- a/esphome/components/mcp23s08/mcp23s08.cpp +++ b/esphome/components/mcp23s08/mcp23s08.cpp @@ -6,6 +6,11 @@ namespace mcp23s08 { static const char *const TAG = "mcp23s08"; +// IOCON register bits +static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode +static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin + void MCP23S08::set_device_address(uint8_t device_addr) { if (device_addr != 0) { this->device_opcode_ |= ((device_addr & 0x03) << 1); @@ -15,19 +20,19 @@ void MCP23S08::set_device_address(uint8_t device_addr) { void MCP23S08::setup() { this->spi_setup(); + // Enable HAEN (broadcast to all chips since HAEN isn't active yet) this->enable(); - uint8_t cmd = 0b01000000; - this->transfer_byte(cmd); + this->transfer_byte(0b01000000); this->transfer_byte(mcp23x08_base::MCP23X08_IOCON); - this->transfer_byte(0b00011000); // Enable HAEN pins for addressing + this->transfer_byte(IOCON_SEQOP | IOCON_HAEN); this->disable(); // Read current output register state this->read_reg(mcp23x08_base::MCP23X08_OLAT, &this->olat_); if (this->open_drain_ints_) { - // enable open-drain interrupt pins, 3.3V-safe - this->write_reg(mcp23x08_base::MCP23X08_IOCON, 0x04); + // enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip) + this->write_reg(mcp23x08_base::MCP23X08_IOCON, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); } } diff --git a/esphome/components/mcp23s17/mcp23s17.cpp b/esphome/components/mcp23s17/mcp23s17.cpp index 1624eda9e4..c6abd7ad59 100644 --- a/esphome/components/mcp23s17/mcp23s17.cpp +++ b/esphome/components/mcp23s17/mcp23s17.cpp @@ -6,6 +6,11 @@ namespace mcp23s17 { static const char *const TAG = "mcp23s17"; +// IOCON register bits +static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode +static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin + void MCP23S17::set_device_address(uint8_t device_addr) { if (device_addr != 0) { this->device_opcode_ |= ((device_addr & 0b111) << 1); @@ -15,18 +20,17 @@ void MCP23S17::set_device_address(uint8_t device_addr) { void MCP23S17::setup() { this->spi_setup(); + // Enable HAEN (broadcast to addresses 0 and 4 since HAEN isn't active yet) this->enable(); - uint8_t cmd = 0b01000000; - this->transfer_byte(cmd); + this->transfer_byte(0b01000000); this->transfer_byte(mcp23x17_base::MCP23X17_IOCONA); - this->transfer_byte(0b00011000); // Enable HAEN pins for addressing + this->transfer_byte(IOCON_SEQOP | IOCON_HAEN); this->disable(); this->enable(); - cmd = 0b01001000; - this->transfer_byte(cmd); + this->transfer_byte(0b01001000); this->transfer_byte(mcp23x17_base::MCP23X17_IOCONA); - this->transfer_byte(0b00011000); // Enable HAEN pins for addressing + this->transfer_byte(IOCON_SEQOP | IOCON_HAEN); this->disable(); // Read current output register state @@ -34,9 +38,9 @@ void MCP23S17::setup() { this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_); if (this->open_drain_ints_) { - // enable open-drain interrupt pins, 3.3V-safe - this->write_reg(mcp23x17_base::MCP23X17_IOCONA, 0x04); - this->write_reg(mcp23x17_base::MCP23X17_IOCONB, 0x04); + // enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip) + this->write_reg(mcp23x17_base::MCP23X17_IOCONA, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); + this->write_reg(mcp23x17_base::MCP23X17_IOCONB, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); } } diff --git a/esphome/components/mmc5603/mmc5603.cpp b/esphome/components/mmc5603/mmc5603.cpp index 1cbc84191f..51b94eb767 100644 --- a/esphome/components/mmc5603/mmc5603.cpp +++ b/esphome/components/mmc5603/mmc5603.cpp @@ -126,21 +126,21 @@ void MMC5603Component::update() { int32_t raw_x = 0; raw_x |= buffer[0] << 12; raw_x |= buffer[1] << 4; - raw_x |= buffer[2] << 0; + raw_x |= buffer[2] & 0x0F; const float x = 0.00625 * (raw_x - 524288); int32_t raw_y = 0; raw_y |= buffer[3] << 12; raw_y |= buffer[4] << 4; - raw_y |= buffer[5] << 0; + raw_y |= buffer[5] & 0x0F; const float y = 0.00625 * (raw_y - 524288); int32_t raw_z = 0; raw_z |= buffer[6] << 12; raw_z |= buffer[7] << 4; - raw_z |= buffer[8] << 0; + raw_z |= buffer[8] & 0x0F; const float z = 0.00625 * (raw_z - 524288); diff --git a/esphome/components/sx1509/sx1509.cpp b/esphome/components/sx1509/sx1509.cpp index dfe1277297..1cdae76eaf 100644 --- a/esphome/components/sx1509/sx1509.cpp +++ b/esphome/components/sx1509/sx1509.cpp @@ -309,8 +309,8 @@ void SX1509Component::set_debounce_keypad_(uint8_t time, uint8_t num_rows, uint8 set_debounce_time_(time); for (uint16_t i = 0; i < num_rows; i++) set_debounce_pin_(i); - for (uint16_t i = 0; i < (8 + num_cols); i++) - set_debounce_pin_(i); + for (uint16_t i = 0; i < num_cols; i++) + set_debounce_pin_(i + 8); } } // namespace sx1509 From 0a607b9c93c0a1c8504a73de09b564c723a258b2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:36:16 -0400 Subject: [PATCH 1768/2030] [esp32_ble_server] Fix wrong union member in STOP_EVT handler (#15239) --- esphome/components/esp32_ble_server/ble_service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32_ble_server/ble_service.cpp b/esphome/components/esp32_ble_server/ble_service.cpp index 96fedf2346..8956c87b3e 100644 --- a/esphome/components/esp32_ble_server/ble_service.cpp +++ b/esphome/components/esp32_ble_server/ble_service.cpp @@ -159,7 +159,7 @@ void BLEService::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t g break; } case ESP_GATTS_STOP_EVT: { - if (param->start.service_handle == this->handle_) { + if (param->stop.service_handle == this->handle_) { this->state_ = STOPPED; } break; From 4b9467cd0cd03bf33aa24ec8be48bc9395976a6a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:37:33 -0400 Subject: [PATCH 1769/2030] [esp32_ble_client] Fix wrong union member in OPEN_EVT handler (#15236) --- esphome/components/esp32_ble_client/ble_client_base.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/esp32_ble_client/ble_client_base.cpp b/esphome/components/esp32_ble_client/ble_client_base.cpp index 9d6e079d92..7f0f2c624d 100644 --- a/esphome/components/esp32_ble_client/ble_client_base.cpp +++ b/esphome/components/esp32_ble_client/ble_client_base.cpp @@ -350,7 +350,7 @@ bool BLEClientBase::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_ // For V3_WITHOUT_CACHE, we already set fast params before connecting // No need to update them again here this->log_event_("Searching for services"); - esp_ble_gattc_search_service(esp_gattc_if, param->cfg_mtu.conn_id, nullptr); + esp_ble_gattc_search_service(esp_gattc_if, param->open.conn_id, nullptr); break; } case ESP_GATTC_CONNECT_EVT: { From 53bd57f3c2557d75fade7864b7371a2de27cabc5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:37:54 -0400 Subject: [PATCH 1770/2030] [pid] Fix inverted debug log conditions and broken smoothing formula (#15240) --- esphome/components/pid/pid_autotuner.cpp | 4 ++-- esphome/components/pid/pid_simulator.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/pid/pid_autotuner.cpp b/esphome/components/pid/pid_autotuner.cpp index e1ddd1d7c6..3b971e6559 100644 --- a/esphome/components/pid/pid_autotuner.cpp +++ b/esphome/components/pid/pid_autotuner.cpp @@ -101,10 +101,10 @@ PIDAutotuner::PIDAutotuneResult PIDAutotuner::update(float setpoint, float proce if (!zc_symmetrical || !amplitude_convergent) { // The frequency/amplitude is not fully accurate yet, try to wait // until the fault clears, or terminate after a while anyway - if (zc_symmetrical) { + if (!zc_symmetrical) { ESP_LOGVV(TAG, "%s: ZC is not symmetrical", this->id_.c_str()); } - if (amplitude_convergent) { + if (!amplitude_convergent) { ESP_LOGVV(TAG, "%s: Amplitude is not convergent", this->id_.c_str()); } uint32_t phase = this->relay_function_.phase_count; diff --git a/esphome/components/pid/pid_simulator.h b/esphome/components/pid/pid_simulator.h index 30222f2f7a..629784cea5 100644 --- a/esphome/components/pid/pid_simulator.h +++ b/esphome/components/pid/pid_simulator.h @@ -59,7 +59,7 @@ class PIDSimulator : public PollingComponent, public output::FloatOutput { delayed_temps.erase(delayed_temps.begin()); float prev_temp = this->delayed_temps[0]; float alpha = 0.1f; - float ret = (1 - alpha) * prev_temp + alpha * prev_temp; + float ret = (1 - alpha) * prev_temp + alpha * temperature; return ret; } From 951ad91cb259262675dbfbf7f71d1d6fb27d596a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:39:30 -0400 Subject: [PATCH 1771/2030] [atm90e32] Fix phase angle precision loss and remove unused member (#15238) --- esphome/components/atm90e32/atm90e32.cpp | 4 ++-- esphome/components/atm90e32/atm90e32.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/esphome/components/atm90e32/atm90e32.cpp b/esphome/components/atm90e32/atm90e32.cpp index ee7fe5ce75..db29702c54 100644 --- a/esphome/components/atm90e32/atm90e32.cpp +++ b/esphome/components/atm90e32/atm90e32.cpp @@ -550,8 +550,8 @@ float ATM90E32Component::get_phase_harmonic_active_power_(uint8_t phase) { } float ATM90E32Component::get_phase_angle_(uint8_t phase) { - uint16_t val = this->read16_(ATM90E32_REGISTER_PANGLE + phase) / 10.0; - return (val > 180) ? (float) (val - 360.0f) : (float) val; + float val = this->read16_(ATM90E32_REGISTER_PANGLE + phase) / 10.0f; + return (val > 180.0f) ? val - 360.0f : val; } float ATM90E32Component::get_phase_peak_current_(uint8_t phase) { diff --git a/esphome/components/atm90e32/atm90e32.h b/esphome/components/atm90e32/atm90e32.h index 2524616470..c44a11e3ed 100644 --- a/esphome/components/atm90e32/atm90e32.h +++ b/esphome/components/atm90e32/atm90e32.h @@ -134,7 +134,6 @@ class ATM90E32Component : public PollingComponent, void set_freq_status_text_sensor(text_sensor::TextSensor *sensor) { this->freq_status_text_sensor_ = sensor; } #endif uint16_t calculate_voltage_threshold(int line_freq, uint16_t ugain, float multiplier); - int32_t last_periodic_millis = millis(); protected: #ifdef USE_NUMBER From 05c15f4241d20c78d3f8eb40a19d3046723aeaf7 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:44:40 -0400 Subject: [PATCH 1772/2030] [remote_base] Fix gobox uint64_t format specifier (#15237) --- esphome/components/remote_base/gobox_protocol.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/remote_base/gobox_protocol.cpp b/esphome/components/remote_base/gobox_protocol.cpp index 4f6de5e59e..0e1617659d 100644 --- a/esphome/components/remote_base/gobox_protocol.cpp +++ b/esphome/components/remote_base/gobox_protocol.cpp @@ -1,5 +1,6 @@ #include "gobox_protocol.h" #include "esphome/core/log.h" +#include <cinttypes> namespace esphome { namespace remote_base { @@ -25,7 +26,7 @@ void GoboxProtocol::encode(RemoteTransmitData *dst, const GoboxData &data) { dst->set_carrier_frequency(38000); dst->reserve((HEADER_SIZE + CODE_SIZE + 1) * 2); uint64_t code = (HEADER << CODE_SIZE) | (data.code & ((1UL << CODE_SIZE) - 1)); - ESP_LOGI(TAG, "Send Gobox: code=0x%Lx", code); + ESP_LOGI(TAG, "Send Gobox: code=0x%016" PRIx64, code); for (int16_t i = (HEADER_SIZE + CODE_SIZE - 1); i >= 0; i--) { if (code & ((uint64_t) 1 << i)) { dst->item(BIT_MARK_US, BIT_ONE_SPACE_US); From f0db0c105424e31022e9521b44eb577cfa18d2d5 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:48:08 -0400 Subject: [PATCH 1773/2030] [esp32] Add ESP-IDF 5.5.4 and 6.0.0 version mappings (#15241) --- esphome/components/esp32/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 91eb913e3d..0ce1117262 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -690,9 +690,15 @@ ARDUINO_IDF_VERSION_LOOKUP = { ESP_IDF_FRAMEWORK_VERSION_LOOKUP = { "recommended": cv.Version(5, 5, 3, "1"), "latest": cv.Version(5, 5, 3, "1"), - "dev": cv.Version(5, 5, 3, "1"), + "dev": cv.Version(5, 5, 4), } ESP_IDF_PLATFORM_VERSION_LOOKUP = { + cv.Version( + 6, 0, 0 + ): "https://github.com/pioarduino/platform-espressif32.git#prep_IDF6", + cv.Version( + 5, 5, 4 + ): "https://github.com/pioarduino/platform-espressif32.git#develop", cv.Version(5, 5, 3, "1"): cv.Version(55, 3, 37), cv.Version(5, 5, 3): cv.Version(55, 3, 37), cv.Version(5, 5, 2): cv.Version(55, 3, 37), From 7532e1f957499ca880c71c0e8c1f693c585b4cf3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:58:41 -0400 Subject: [PATCH 1774/2030] [multiple] Fix uninitialized members and error constant types (#15235) --- esphome/components/max44009/max44009.cpp | 18 +++++++++--------- esphome/components/max44009/max44009.h | 4 ++-- .../modbus_controller/output/modbus_output.h | 4 ++-- esphome/components/tuya/climate/tuya_climate.h | 10 +++++----- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/esphome/components/max44009/max44009.cpp b/esphome/components/max44009/max44009.cpp index 8b8e38c1ea..cbce053519 100644 --- a/esphome/components/max44009/max44009.cpp +++ b/esphome/components/max44009/max44009.cpp @@ -8,17 +8,17 @@ namespace max44009 { static const char *const TAG = "max44009.sensor"; // REGISTERS -static const uint8_t MAX44009_REGISTER_CONFIGURATION = 0x02; -static const uint8_t MAX44009_LUX_READING_HIGH = 0x03; -static const uint8_t MAX44009_LUX_READING_LOW = 0x04; +static constexpr uint8_t MAX44009_REGISTER_CONFIGURATION = 0x02; +static constexpr uint8_t MAX44009_LUX_READING_HIGH = 0x03; +static constexpr uint8_t MAX44009_LUX_READING_LOW = 0x04; // CONFIGURATION MASKS -static const uint8_t MAX44009_CFG_CONTINUOUS = 0x80; +static constexpr uint8_t MAX44009_CFG_CONTINUOUS = 0x80; // ERROR CODES -static const uint8_t MAX44009_OK = 0; -static const uint8_t MAX44009_ERROR_WIRE_REQUEST = -10; -static const uint8_t MAX44009_ERROR_OVERFLOW = -20; -static const uint8_t MAX44009_ERROR_HIGH_BYTE = -30; -static const uint8_t MAX44009_ERROR_LOW_BYTE = -31; +static constexpr int8_t MAX44009_OK = 0; +static constexpr int8_t MAX44009_ERROR_WIRE_REQUEST = -10; +static constexpr int8_t MAX44009_ERROR_OVERFLOW = -20; +static constexpr int8_t MAX44009_ERROR_HIGH_BYTE = -30; +static constexpr int8_t MAX44009_ERROR_LOW_BYTE = -31; void MAX44009Sensor::setup() { bool state_ok = false; diff --git a/esphome/components/max44009/max44009.h b/esphome/components/max44009/max44009.h index 59eea66ed9..d0ffd7bc70 100644 --- a/esphome/components/max44009/max44009.h +++ b/esphome/components/max44009/max44009.h @@ -28,8 +28,8 @@ class MAX44009Sensor : public sensor::Sensor, public PollingComponent, public i2 uint8_t read_(uint8_t reg); void write_(uint8_t reg, uint8_t value); - int error_; - MAX44009Mode mode_; + int8_t error_{0}; + MAX44009Mode mode_{MAX44009_MODE_AUTO}; }; } // namespace max44009 diff --git a/esphome/components/modbus_controller/output/modbus_output.h b/esphome/components/modbus_controller/output/modbus_output.h index 0fb4bb89ea..3f3cadfe2f 100644 --- a/esphome/components/modbus_controller/output/modbus_output.h +++ b/esphome/components/modbus_controller/output/modbus_output.h @@ -15,7 +15,7 @@ class ModbusFloatOutput : public output::FloatOutput, public Component, public S this->register_type = ModbusRegisterType::HOLDING; this->start_address = start_address; this->offset = offset; - this->bitmask = bitmask; + this->bitmask = 0xFFFFFFFF; this->register_count = register_count; this->sensor_value_type = value_type; this->skip_updates = 0; @@ -47,7 +47,7 @@ class ModbusBinaryOutput : public output::BinaryOutput, public Component, public ModbusBinaryOutput(uint16_t start_address, uint8_t offset) { this->register_type = ModbusRegisterType::COIL; this->start_address = start_address; - this->bitmask = bitmask; + this->bitmask = 0xFFFFFFFF; this->sensor_value_type = SensorValueType::BIT; this->skip_updates = 0; this->register_count = 1; diff --git a/esphome/components/tuya/climate/tuya_climate.h b/esphome/components/tuya/climate/tuya_climate.h index 31bef57639..09f3fd30c3 100644 --- a/esphome/components/tuya/climate/tuya_climate.h +++ b/esphome/components/tuya/climate/tuya_climate.h @@ -105,8 +105,8 @@ class TuyaClimate : public climate::Climate, public Component { optional<uint8_t> sleep_id_{}; optional<float> eco_temperature_{}; TuyaDatapointType eco_type_{}; - uint8_t active_state_; - uint8_t fan_state_; + uint8_t active_state_{0}; + uint8_t fan_state_{0}; optional<uint8_t> swing_vertical_id_{}; optional<uint8_t> swing_horizontal_id_{}; optional<uint8_t> fan_speed_id_{}; @@ -119,9 +119,9 @@ class TuyaClimate : public climate::Climate, public Component { bool swing_horizontal_{false}; bool heating_state_{false}; bool cooling_state_{false}; - float manual_temperature_; - bool eco_; - bool sleep_; + float manual_temperature_{NAN}; + bool eco_{false}; + bool sleep_{false}; bool reports_fahrenheit_{false}; }; From 3016cd363617d080e7eb6ed6532e5668cb07bdbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 27 Mar 2026 09:29:08 -1000 Subject: [PATCH 1775/2030] Bump github/codeql-action from 4.34.1 to 4.35.1 (#15245) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6baab70b42..67f4690ac9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -58,7 +58,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/init@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} @@ -86,6 +86,6 @@ jobs: exit 1 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@38697555549f1db7851b81482ff19f1fa5c4fedc # v4.34.1 + uses: github/codeql-action/analyze@c10b8064de6f491fea524254123dbe5e09572f13 # v4.35.1 with: category: "/language:${{matrix.language}}" From a2dee21e8e8f43c9ba68ab5a7b99908d7cd22eaf Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Fri, 27 Mar 2026 21:24:19 +0100 Subject: [PATCH 1776/2030] [nextion] Replace `std::deque` queues with `std::list` (#15211) --- esphome/components/nextion/nextion.cpp | 14 ++++++-------- esphome/components/nextion/nextion.h | 12 ++++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index fa1582c209..964dbfb660 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -841,10 +841,10 @@ void Nextion::process_nextion_commands_() { if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() && ms - this->nextion_queue_.front()->queue_time > this->max_q_age_ms_) { - for (size_t i = 0; i < this->nextion_queue_.size(); i++) { - NextionComponentBase *component = this->nextion_queue_[i]->component; - if (ms - this->nextion_queue_[i]->queue_time > this->max_q_age_ms_) { - if (this->nextion_queue_[i]->queue_time == 0) { + for (auto it = this->nextion_queue_.begin(); it != this->nextion_queue_.end();) { + NextionComponentBase *component = (*it)->component; + if (ms - (*it)->queue_time > this->max_q_age_ms_) { + if ((*it)->queue_time == 0) { ESP_LOGD(TAG, "Remove old queue '%s':'%s' (t=0)", component->get_queue_type_string().c_str(), component->get_variable_name().c_str()); } @@ -863,10 +863,8 @@ void Nextion::process_nextion_commands_() { delete component; // NOLINT(cppcoreguidelines-owning-memory) } - delete this->nextion_queue_[i]; // NOLINT(cppcoreguidelines-owning-memory) - - this->nextion_queue_.erase(this->nextion_queue_.begin() + i); - i--; + delete *it; // NOLINT(cppcoreguidelines-owning-memory) + it = this->nextion_queue_.erase(it); } else { break; diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index 217d2e605d..b5aaecd667 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -1,16 +1,16 @@ #pragma once -#include <deque> +#include <list> #include <vector> +#include "esphome/components/display/display.h" +#include "esphome/components/display/display_color_utils.h" +#include "esphome/components/uart/uart.h" #include "esphome/core/defines.h" #include "esphome/core/time.h" -#include "esphome/components/uart/uart.h" #include "nextion_base.h" #include "nextion_component.h" -#include "esphome/components/display/display.h" -#include "esphome/components/display/display_color_utils.h" #ifdef USE_NEXTION_TFT_UPLOAD #ifdef USE_ESP32 @@ -1391,8 +1391,8 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void process_pending_in_queue_(); #endif // USE_NEXTION_COMMAND_SPACING - std::deque<NextionQueue *> nextion_queue_; - std::deque<NextionQueue *> waveform_queue_; + std::list<NextionQueue *> nextion_queue_; + std::list<NextionQueue *> waveform_queue_; uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag); void all_components_send_state_(bool force_update = false); uint32_t comok_sent_ = 0; From d245b9f123e37618e51f027412f9cc860309478a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:24:03 -0400 Subject: [PATCH 1777/2030] [sm2135] Fix copy-paste error in setup pin mode (#15248) --- esphome/components/sm2135/sm2135.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/sm2135/sm2135.cpp b/esphome/components/sm2135/sm2135.cpp index 1293c3f321..c3d10e70c2 100644 --- a/esphome/components/sm2135/sm2135.cpp +++ b/esphome/components/sm2135/sm2135.cpp @@ -25,7 +25,7 @@ void SM2135::setup() { this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); this->clock_pin_->setup(); this->clock_pin_->digital_write(false); - this->data_pin_->pin_mode(gpio::FLAG_OUTPUT); + this->clock_pin_->pin_mode(gpio::FLAG_OUTPUT); this->data_pin_->pin_mode(gpio::FLAG_PULLUP); this->clock_pin_->pin_mode(gpio::FLAG_PULLUP); From 24b8a95340d79ad00157c261e0e3c9f92998439e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:24:15 -0400 Subject: [PATCH 1778/2030] [pid] Remove unused PIDSimulator class (#15247) --- esphome/components/pid/pid_autotuner.h | 1 - esphome/components/pid/pid_simulator.h | 77 -------------------------- 2 files changed, 78 deletions(-) delete mode 100644 esphome/components/pid/pid_simulator.h diff --git a/esphome/components/pid/pid_autotuner.h b/esphome/components/pid/pid_autotuner.h index 98dc02bcc4..1db9ca7138 100644 --- a/esphome/components/pid/pid_autotuner.h +++ b/esphome/components/pid/pid_autotuner.h @@ -3,7 +3,6 @@ #include "esphome/core/component.h" #include "esphome/core/optional.h" #include "pid_controller.h" -#include "pid_simulator.h" #include <vector> diff --git a/esphome/components/pid/pid_simulator.h b/esphome/components/pid/pid_simulator.h deleted file mode 100644 index 629784cea5..0000000000 --- a/esphome/components/pid/pid_simulator.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include "esphome/core/component.h" -#include "esphome/core/helpers.h" -#include "esphome/components/sensor/sensor.h" -#include "esphome/components/output/float_output.h" - -#include <vector> - -namespace esphome { -namespace pid { - -class PIDSimulator : public PollingComponent, public output::FloatOutput { - public: - PIDSimulator() : PollingComponent(1000) {} - - float surface = 1; /// surface area in m² - float mass = 3; /// mass of simulated object in kg - float temperature = 21; /// current temperature of object in °C - float efficiency = 0.98; /// heating efficiency, 1 is 100% efficient - float thermal_conductivity = 15; /// thermal conductivity of surface are in W/(m*K), here: steel - float specific_heat_capacity = 4.182; /// specific heat capacity of mass in kJ/(kg*K), here: water - float heat_power = 500; /// Heating power in W - float ambient_temperature = 20; /// Ambient temperature in °C - float update_interval = 1; /// The simulated updated interval in seconds - std::vector<float> delayed_temps; /// storage of past temperatures for delaying temperature reading - size_t delay_cycles = 15; /// how many update cycles to delay the output - float output_value = 0.0; /// Current output value of heating element - sensor::Sensor *sensor = new sensor::Sensor(); - - float delta_t(float power) { - // P = Q / t - // Q = c * m * 𝚫t - // 𝚫t = (P*t) / (c*m) - float c = this->specific_heat_capacity; - float t = this->update_interval; - float p = power / 1000; // in kW - float m = this->mass; - return (p * t) / (c * m); - } - - float update_temp() { - float value = clamp(output_value, 0.0f, 1.0f); - - // Heat - float power = value * heat_power * efficiency; - temperature += this->delta_t(power); - - // Cool - // Q = k_w * A * (T_mass - T_ambient) - // P = Q / t - float dt = temperature - ambient_temperature; - float cool_power = (thermal_conductivity * surface * dt) / update_interval; - temperature -= this->delta_t(cool_power); - - // Delay temperature readings - delayed_temps.push_back(temperature); - if (delayed_temps.size() > delay_cycles) - delayed_temps.erase(delayed_temps.begin()); - float prev_temp = this->delayed_temps[0]; - float alpha = 0.1f; - float ret = (1 - alpha) * prev_temp + alpha * temperature; - return ret; - } - - void setup() override { sensor->publish_state(this->temperature); } - void update() override { - float new_temp = this->update_temp(); - sensor->publish_state(new_temp); - } - - protected: - void write_state(float state) override { this->output_value = state; } -}; - -} // namespace pid -} // namespace esphome From 68d9f657adf9d2a65621486627596b5f6275a317 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:32:37 -0400 Subject: [PATCH 1779/2030] [bl0940] Fix energy reference default using wrong constant in legacy mode (#15249) --- esphome/components/bl0940/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/bl0940/sensor.py b/esphome/components/bl0940/sensor.py index d2e0ea435d..f36250ecdf 100644 --- a/esphome/components/bl0940/sensor.py +++ b/esphome/components/bl0940/sensor.py @@ -124,7 +124,7 @@ def set_reference_values(config): config.setdefault(CONF_VOLTAGE_REFERENCE, DEFAULT_BL0940_LEGACY_UREF) config.setdefault(CONF_CURRENT_REFERENCE, DEFAULT_BL0940_LEGACY_IREF) config.setdefault(CONF_POWER_REFERENCE, DEFAULT_BL0940_LEGACY_PREF) - config.setdefault(CONF_ENERGY_REFERENCE, DEFAULT_BL0940_LEGACY_PREF) + config.setdefault(CONF_ENERGY_REFERENCE, DEFAULT_BL0940_LEGACY_EREF) else: vref = config.get(CONF_VOLTAGE_REFERENCE, DEFAULT_BL0940_VREF) r_one = config.get(CONF_RESISTOR_ONE, DEFAULT_BL0940_R1) From 76d75850a3bd100fb056d5a82c8792abb3f23154 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:35:12 -0400 Subject: [PATCH 1780/2030] [sgp4x] Remove dead voc_baseline config option (#15250) --- esphome/components/sgp4x/sensor.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/esphome/components/sgp4x/sensor.py b/esphome/components/sgp4x/sensor.py index 8d52ffb4f2..1e58a0f26a 100644 --- a/esphome/components/sgp4x/sensor.py +++ b/esphome/components/sgp4x/sensor.py @@ -15,7 +15,6 @@ from esphome.const import ( CONF_STORE_BASELINE, CONF_TEMPERATURE_SOURCE, CONF_VOC, - CONF_VOC_BASELINE, DEVICE_CLASS_AQI, ICON_RADIATOR, STATE_CLASS_MEASUREMENT, @@ -83,7 +82,6 @@ CONFIG_SCHEMA = cv.All( state_class=STATE_CLASS_MEASUREMENT, ).extend(NOX_SENSOR), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, - cv.Optional(CONF_VOC_BASELINE): cv.hex_uint16_t, cv.Optional(CONF_COMPENSATION): cv.Schema( { cv.Required(CONF_HUMIDITY_SOURCE): cv.use_id(sensor.Sensor), @@ -112,9 +110,6 @@ async def to_code(config): cg.add(var.set_store_baseline(config[CONF_STORE_BASELINE])) - if CONF_VOC_BASELINE in config: - cg.add(var.set_voc_baseline(CONF_VOC_BASELINE)) - if CONF_VOC in config: sens = await sensor.new_sensor(config[CONF_VOC]) cg.add(var.set_voc_sensor(sens)) From f6c63c62e43b88b8933a3f02f866c7e0936dd290 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Fri, 27 Mar 2026 17:59:26 -0500 Subject: [PATCH 1781/2030] [tmp117] Code clean-up (#15260) --- esphome/components/tmp117/tmp117.cpp | 17 +++++++---------- esphome/components/tmp117/tmp117.h | 6 ++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/esphome/components/tmp117/tmp117.cpp b/esphome/components/tmp117/tmp117.cpp index f8f52266e0..b3e900f5b6 100644 --- a/esphome/components/tmp117/tmp117.cpp +++ b/esphome/components/tmp117/tmp117.cpp @@ -4,8 +4,7 @@ #include "tmp117.h" #include "esphome/core/log.h" -namespace esphome { -namespace tmp117 { +namespace esphome::tmp117 { static const char *const TAG = "tmp117"; @@ -18,11 +17,10 @@ void TMP117Component::update() { if ((uint16_t) data != 0x8000) { float temperature = data * 0.0078125f; - ESP_LOGD(TAG, "Got temperature=%.2f°C", temperature); this->publish_state(temperature); this->status_clear_warning(); } else { - ESP_LOGD(TAG, "TMP117 not ready"); + ESP_LOGD(TAG, "Not ready"); } } void TMP117Component::setup() { @@ -38,7 +36,7 @@ void TMP117Component::setup() { } } void TMP117Component::dump_config() { - ESP_LOGD(TAG, "TMP117:"); + ESP_LOGCONFIG(TAG, "TMP117:"); LOG_I2C_DEVICE(this); if (this->is_failed()) { ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); @@ -48,7 +46,7 @@ void TMP117Component::dump_config() { bool TMP117Component::read_data_(int16_t *data) { if (!this->read_byte_16(0, (uint16_t *) data)) { - ESP_LOGW(TAG, "Updating TMP117 failed!"); + ESP_LOGW(TAG, "Updating failed"); return false; } return true; @@ -56,7 +54,7 @@ bool TMP117Component::read_data_(int16_t *data) { bool TMP117Component::read_config_(uint16_t *config) { if (!this->read_byte_16(1, (uint16_t *) config)) { - ESP_LOGW(TAG, "Reading TMP117 config failed!"); + ESP_LOGW(TAG, "Reading config failed"); return false; } return true; @@ -64,11 +62,10 @@ bool TMP117Component::read_config_(uint16_t *config) { bool TMP117Component::write_config_(uint16_t config) { if (!this->write_byte_16(1, config)) { - ESP_LOGE(TAG, "Writing TMP117 config failed!"); + ESP_LOGE(TAG, "Writing config failed"); return false; } return true; } -} // namespace tmp117 -} // namespace esphome +} // namespace esphome::tmp117 diff --git a/esphome/components/tmp117/tmp117.h b/esphome/components/tmp117/tmp117.h index f501ee270c..a8fe7ac7ce 100644 --- a/esphome/components/tmp117/tmp117.h +++ b/esphome/components/tmp117/tmp117.h @@ -4,8 +4,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/i2c/i2c.h" -namespace esphome { -namespace tmp117 { +namespace esphome::tmp117 { class TMP117Component : public PollingComponent, public i2c::I2CDevice, public sensor::Sensor { public: @@ -22,5 +21,4 @@ class TMP117Component : public PollingComponent, public i2c::I2CDevice, public s uint16_t config_; }; -} // namespace tmp117 -} // namespace esphome +} // namespace esphome::tmp117 From a99f051e19759c70e2007deb4b873327c9127699 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Sat, 28 Mar 2026 00:49:00 +0100 Subject: [PATCH 1782/2030] [nextion] Replace queue name string literals with short Nextion-native identifiers (#15215) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 13 +- .../components/nextion/nextion_commands.cpp | 115 ++++++++---------- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 964dbfb660..97d9b36e4c 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -241,7 +241,7 @@ bool Nextion::send_command(const char *command) { return false; if (this->send_command_(command)) { - this->add_no_result_to_queue_("send_command"); + this->add_no_result_to_queue_("command"); return true; } return false; @@ -262,7 +262,7 @@ bool Nextion::send_command_printf(const char *format, ...) { } if (this->send_command_(buffer)) { - this->add_no_result_to_queue_("send_command_printf"); + this->add_no_result_to_queue_("command_printf"); return true; } return false; @@ -853,8 +853,13 @@ void Nextion::process_nextion_commands_() { this->is_sleeping_ = false; } - ESP_LOGD(TAG, "Remove old queue '%s':'%s'", component->get_queue_type_string().c_str(), - component->get_variable_name().c_str()); + if ((*it)->pending_command.empty()) { + ESP_LOGD(TAG, "Remove old queue '%s':'%s'", component->get_queue_type_string().c_str(), + component->get_variable_name().c_str()); + } else { + ESP_LOGD(TAG, "Remove old queue '%s':'%s' cmd:'%s'", component->get_queue_type_string().c_str(), + component->get_variable_name().c_str(), (*it)->pending_command.c_str()); + } if (component->get_queue_type() == NextionQueueType::NO_RESULT) { if (component->get_variable_name() == "sleep_wake") { diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 4ddbfbee6a..6718646efa 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -12,7 +12,7 @@ void Nextion::soft_reset() { this->send_command_("rest"); } void Nextion::set_wake_up_page(uint8_t wake_up_page) { this->wake_up_page_ = wake_up_page; - this->add_no_result_to_queue_with_set_internal_("wake_up_page", "wup", wake_up_page, true); + this->add_no_result_to_queue_with_set_internal_("wup", "wup", wake_up_page, true); } void Nextion::set_touch_sleep_timeout(const uint16_t touch_sleep_timeout) { @@ -23,7 +23,7 @@ void Nextion::set_touch_sleep_timeout(const uint16_t touch_sleep_timeout) { this->touch_sleep_timeout_ = touch_sleep_timeout; } - this->add_no_result_to_queue_with_set_internal_("touch_sleep_timeout", "thsp", this->touch_sleep_timeout_, true); + this->add_no_result_to_queue_with_set_internal_("thsp", "thsp", this->touch_sleep_timeout_, true); } void Nextion::sleep(bool sleep) { @@ -58,115 +58,107 @@ bool Nextion::set_protocol_reparse_mode(bool active_mode) { // Set Colors - Background void Nextion::set_component_background_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%" PRIu16, component, color); + this->add_no_result_to_queue_with_printf_(".bco", "%s.bco=%" PRIu16, component, color); } void Nextion::set_component_background_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%s", component, color); + this->add_no_result_to_queue_with_printf_(".bco", "%s.bco=%s", component, color); } void Nextion::set_component_background_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_background_color", "%s.bco=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".bco", "%s.bco=%d", component, display::ColorUtil::color_to_565(color)); } // Set Colors - Background (pressed) void Nextion::set_component_pressed_background_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%" PRIu16, component, - color); + this->add_no_result_to_queue_with_printf_(".bco2", "%s.bco2=%" PRIu16, component, color); } void Nextion::set_component_pressed_background_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%s", component, color); + this->add_no_result_to_queue_with_printf_(".bco2", "%s.bco2=%s", component, color); } void Nextion::set_component_pressed_background_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_background_color", "%s.bco2=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".bco2", "%s.bco2=%d", component, display::ColorUtil::color_to_565(color)); } // Set Colors - Foreground void Nextion::set_component_foreground_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_foreground_color", "%s.pco=%" PRIu16, component, color); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%" PRIu16, component, color); } void Nextion::set_component_foreground_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_foreground_color", "%s.pco=%s", component, color); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%s", component, color); } void Nextion::set_component_foreground_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_foreground_color", "%s.pco=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%d", component, display::ColorUtil::color_to_565(color)); } // Set Colors - Foreground (pressed) void Nextion::set_component_pressed_foreground_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_foreground_color", "%s.pco2=%" PRIu16, component, - color); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%" PRIu16, component, color); } void Nextion::set_component_pressed_foreground_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_foreground_color", "%s.pco2=%s", component, color); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%s", component, color); } void Nextion::set_component_pressed_foreground_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_foreground_color", "%s.pco2=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%d", component, display::ColorUtil::color_to_565(color)); } // Set Colors - Font void Nextion::set_component_font_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%" PRIu16, component, color); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%" PRIu16, component, color); } void Nextion::set_component_font_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%s", component, color); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%s", component, color); } void Nextion::set_component_font_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_font_color", "%s.pco=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".pco", "%s.pco=%d", component, display::ColorUtil::color_to_565(color)); } // Set Colors - Font (pressed) void Nextion::set_component_pressed_font_color(const char *component, uint16_t color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%" PRIu16, component, color); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%" PRIu16, component, color); } void Nextion::set_component_pressed_font_color(const char *component, const char *color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%s", component, color); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%s", component, color); } void Nextion::set_component_pressed_font_color(const char *component, Color color) { - this->add_no_result_to_queue_with_printf_("set_component_pressed_font_color", "%s.pco2=%d", component, - display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_(".pco2", "%s.pco2=%d", component, display::ColorUtil::color_to_565(color)); } // Set picture void Nextion::set_component_pic(const char *component, uint16_t pic_id) { - this->add_no_result_to_queue_with_printf_("set_component_pic", "%s.pic=%" PRIu16, component, pic_id); + this->add_no_result_to_queue_with_printf_(".pic", "%s.pic=%" PRIu16, component, pic_id); } void Nextion::set_component_picc(const char *component, uint16_t pic_id) { - this->add_no_result_to_queue_with_printf_("set_component_picc", "%s.picc=%" PRIu16, component, pic_id); + this->add_no_result_to_queue_with_printf_(".picc", "%s.picc=%" PRIu16, component, pic_id); } // Set video void Nextion::set_component_vid(const char *component, uint8_t vid_id) { - this->add_no_result_to_queue_with_printf_("set_component_vid", "%s.vid=%" PRIu8, component, vid_id); + this->add_no_result_to_queue_with_printf_(".vid", "%s.vid=%" PRIu8, component, vid_id); } void Nextion::set_component_drag(const char *component, bool drag) { - this->add_no_result_to_queue_with_printf_("set_component_drag", "%s.drag=%i", component, drag ? 1 : 0); + this->add_no_result_to_queue_with_printf_(".drag", "%s.drag=%i", component, drag ? 1 : 0); } void Nextion::set_component_aph(const char *component, uint8_t aph) { - this->add_no_result_to_queue_with_printf_("set_component_aph", "%s.aph=%" PRIu8, component, aph); + this->add_no_result_to_queue_with_printf_(".aph", "%s.aph=%" PRIu8, component, aph); } void Nextion::set_component_position(const char *component, uint32_t x, uint32_t y) { - this->add_no_result_to_queue_with_printf_("set_component_position_x", "%s.x=%" PRIu32, component, x); - this->add_no_result_to_queue_with_printf_("set_component_position_y", "%s.y=%" PRIu32, component, y); + this->add_no_result_to_queue_with_printf_(".x", "%s.x=%" PRIu32, component, x); + this->add_no_result_to_queue_with_printf_(".y", "%s.y=%" PRIu32, component, y); } void Nextion::set_component_text_printf(const char *component, const char *format, ...) { @@ -180,29 +172,29 @@ void Nextion::set_component_text_printf(const char *component, const char *forma } // General Nextion -void Nextion::goto_page(const char *page) { this->add_no_result_to_queue_with_printf_("goto_page", "page %s", page); } -void Nextion::goto_page(uint8_t page) { this->add_no_result_to_queue_with_printf_("goto_page", "page %i", page); } +void Nextion::goto_page(const char *page) { this->add_no_result_to_queue_with_printf_("page", "page %s", page); } +void Nextion::goto_page(uint8_t page) { this->add_no_result_to_queue_with_printf_("page", "page %i", page); } void Nextion::set_backlight_brightness(float brightness) { if (brightness < 0 || brightness > 1.0) { ESP_LOGD(TAG, "Brightness out of bounds (0-1.0)"); return; } - this->add_no_result_to_queue_with_printf_("backlight_brightness", "dim=%d", static_cast<int>(brightness * 100)); + this->add_no_result_to_queue_with_printf_("dim", "dim=%d", static_cast<int>(brightness * 100)); } void Nextion::set_auto_wake_on_touch(bool auto_wake_on_touch) { this->connection_state_.auto_wake_on_touch_ = auto_wake_on_touch; - this->add_no_result_to_queue_with_set("auto_wake_on_touch", "thup", auto_wake_on_touch ? 1 : 0); + this->add_no_result_to_queue_with_set("thup", "thup", auto_wake_on_touch ? 1 : 0); } // General Component void Nextion::set_component_font(const char *component, uint8_t font_id) { - this->add_no_result_to_queue_with_printf_("set_component_font", "%s.font=%" PRIu8, component, font_id); + this->add_no_result_to_queue_with_printf_(".font", "%s.font=%" PRIu8, component, font_id); } void Nextion::set_component_visibility(const char *component, bool show) { - this->add_no_result_to_queue_with_printf_("set_component_visibility", "vis %s,%d", component, show ? 1 : 0); + this->add_no_result_to_queue_with_printf_("vis", "vis %s,%d", component, show ? 1 : 0); } void Nextion::hide_component(const char *component) { this->set_component_visibility(component, false); } @@ -210,56 +202,55 @@ void Nextion::hide_component(const char *component) { this->set_component_visibi void Nextion::show_component(const char *component) { this->set_component_visibility(component, true); } void Nextion::enable_component_touch(const char *component) { - this->add_no_result_to_queue_with_printf_("enable_component_touch", "tsw %s,1", component); + this->add_no_result_to_queue_with_printf_("tsw", "tsw %s,1", component); } void Nextion::disable_component_touch(const char *component) { - this->add_no_result_to_queue_with_printf_("disable_component_touch", "tsw %s,0", component); + this->add_no_result_to_queue_with_printf_("tsw", "tsw %s,0", component); } void Nextion::set_component_text(const char *component, const char *text) { - this->add_no_result_to_queue_with_printf_("set_component_text", "%s.txt=\"%s\"", component, text); + this->add_no_result_to_queue_with_printf_(".txt", "%s.txt=\"%s\"", component, text); } void Nextion::set_component_value(const char *component, int32_t value) { - this->add_no_result_to_queue_with_printf_("set_component_value", "%s.val=%" PRId32, component, value); + this->add_no_result_to_queue_with_printf_(".val", "%s.val=%" PRId32, component, value); } void Nextion::add_waveform_data(uint8_t component_id, uint8_t channel_number, uint8_t value) { - this->add_no_result_to_queue_with_printf_("add_waveform_data", "add %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, - channel_number, value); + this->add_no_result_to_queue_with_printf_("add", "add %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, channel_number, + value); } void Nextion::open_waveform_channel(uint8_t component_id, uint8_t channel_number, uint8_t value) { - this->add_no_result_to_queue_with_printf_("open_waveform_channel", "addt %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, - channel_number, value); + this->add_no_result_to_queue_with_printf_("addt", "addt %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, channel_number, + value); } void Nextion::set_component_coordinates(const char *component, uint16_t x, uint16_t y) { - this->add_no_result_to_queue_with_printf_("set_component_coordinates command 1", "%s.xcen=%" PRIu16, component, x); - this->add_no_result_to_queue_with_printf_("set_component_coordinates command 2", "%s.ycen=%" PRIu16, component, y); + this->add_no_result_to_queue_with_printf_(".xcen", "%s.xcen=%" PRIu16, component, x); + this->add_no_result_to_queue_with_printf_(".ycen", "%s.ycen=%" PRIu16, component, y); } // Drawing void Nextion::display_picture(uint16_t picture_id, uint16_t x_start, uint16_t y_start) { - this->add_no_result_to_queue_with_printf_("display_picture", "pic %" PRIu16 ", %" PRIu16 ", %" PRIu16, x_start, - y_start, picture_id); + this->add_no_result_to_queue_with_printf_("pic", "pic %" PRIu16 ", %" PRIu16 ", %" PRIu16, x_start, y_start, + picture_id); } void Nextion::fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint16_t color) { - this->add_no_result_to_queue_with_printf_( - "fill_area", "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, y1, width, height, color); -} - -void Nextion::fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, const char *color) { - this->add_no_result_to_queue_with_printf_("fill_area", "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", x1, + this->add_no_result_to_queue_with_printf_("fill", "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, y1, width, height, color); } +void Nextion::fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, const char *color) { + this->add_no_result_to_queue_with_printf_("fill", "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%s", x1, y1, + width, height, color); +} + void Nextion::fill_area(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, Color color) { - this->add_no_result_to_queue_with_printf_("fill_area", - "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, y1, - width, height, display::ColorUtil::color_to_565(color)); + this->add_no_result_to_queue_with_printf_("fill", "fill %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16, x1, + y1, width, height, display::ColorUtil::color_to_565(color)); } void Nextion::line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { From 34410e92b7e1f9ddd15629ecb5903932554e9077 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 19:55:40 -0400 Subject: [PATCH 1783/2030] [as5600] Remove dead angle/position sensor code (#15254) --- esphome/components/as5600/sensor/__init__.py | 15 ----------- .../as5600/sensor/as5600_sensor.cpp | 25 +++---------------- .../components/as5600/sensor/as5600_sensor.h | 6 ----- 3 files changed, 4 insertions(+), 42 deletions(-) diff --git a/esphome/components/as5600/sensor/__init__.py b/esphome/components/as5600/sensor/__init__.py index e84733a484..cf67a3f203 100644 --- a/esphome/components/as5600/sensor/__init__.py +++ b/esphome/components/as5600/sensor/__init__.py @@ -2,11 +2,9 @@ import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv from esphome.const import ( - CONF_ANGLE, CONF_GAIN, CONF_ID, CONF_MAGNITUDE, - CONF_POSITION, CONF_STATUS, ENTITY_CATEGORY_DIAGNOSTIC, ICON_MAGNET, @@ -21,7 +19,6 @@ DEPENDENCIES = ["as5600"] AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingComponent) -CONF_RAW_ANGLE = "raw_angle" CONF_RAW_POSITION = "raw_position" CONF_SLOW_FILTER = "slow_filter" CONF_FAST_FILTER = "fast_filter" @@ -89,18 +86,6 @@ async def to_code(config): if out_of_range_mode_config := config.get(CONF_OUT_OF_RANGE_MODE): cg.add(var.set_out_of_range_mode(out_of_range_mode_config)) - if angle_config := config.get(CONF_ANGLE): - sens = await sensor.new_sensor(angle_config) - cg.add(var.set_angle_sensor(sens)) - - if raw_angle_config := config.get(CONF_RAW_ANGLE): - sens = await sensor.new_sensor(raw_angle_config) - cg.add(var.set_raw_angle_sensor(sens)) - - if position_config := config.get(CONF_POSITION): - sens = await sensor.new_sensor(position_config) - cg.add(var.set_position_sensor(sens)) - if raw_position_config := config.get(CONF_RAW_POSITION): sens = await sensor.new_sensor(raw_position_config) cg.add(var.set_raw_position_sensor(sens)) diff --git a/esphome/components/as5600/sensor/as5600_sensor.cpp b/esphome/components/as5600/sensor/as5600_sensor.cpp index 1c0f4bad2c..4e549d24d5 100644 --- a/esphome/components/as5600/sensor/as5600_sensor.cpp +++ b/esphome/components/as5600/sensor/as5600_sensor.cpp @@ -25,27 +25,10 @@ static const uint8_t REGISTER_MAGNITUDE = 0x1B; // 16 bytes / R void AS5600Sensor::dump_config() { LOG_SENSOR("", "AS5600 Sensor", this); ESP_LOGCONFIG(TAG, " Out of Range Mode: %u", this->out_of_range_mode_); - if (this->angle_sensor_ != nullptr) { - LOG_SENSOR(" ", "Angle Sensor", this->angle_sensor_); - } - if (this->raw_angle_sensor_ != nullptr) { - LOG_SENSOR(" ", "Raw Angle Sensor", this->raw_angle_sensor_); - } - if (this->position_sensor_ != nullptr) { - LOG_SENSOR(" ", "Position Sensor", this->position_sensor_); - } - if (this->raw_position_sensor_ != nullptr) { - LOG_SENSOR(" ", "Raw Position Sensor", this->raw_position_sensor_); - } - if (this->gain_sensor_ != nullptr) { - LOG_SENSOR(" ", "Gain Sensor", this->gain_sensor_); - } - if (this->magnitude_sensor_ != nullptr) { - LOG_SENSOR(" ", "Magnitude Sensor", this->magnitude_sensor_); - } - if (this->status_sensor_ != nullptr) { - LOG_SENSOR(" ", "Status Sensor", this->status_sensor_); - } + LOG_SENSOR(" ", "Raw Position Sensor", this->raw_position_sensor_); + LOG_SENSOR(" ", "Gain Sensor", this->gain_sensor_); + LOG_SENSOR(" ", "Magnitude Sensor", this->magnitude_sensor_); + LOG_SENSOR(" ", "Status Sensor", this->status_sensor_); LOG_UPDATE_INTERVAL(this); } diff --git a/esphome/components/as5600/sensor/as5600_sensor.h b/esphome/components/as5600/sensor/as5600_sensor.h index d471be49b5..77593f4b12 100644 --- a/esphome/components/as5600/sensor/as5600_sensor.h +++ b/esphome/components/as5600/sensor/as5600_sensor.h @@ -15,9 +15,6 @@ class AS5600Sensor : public PollingComponent, public Parented<AS5600Component>, void update() override; void dump_config() override; - void set_angle_sensor(sensor::Sensor *angle_sensor) { this->angle_sensor_ = angle_sensor; } - void set_raw_angle_sensor(sensor::Sensor *raw_angle_sensor) { this->raw_angle_sensor_ = raw_angle_sensor; } - void set_position_sensor(sensor::Sensor *position_sensor) { this->position_sensor_ = position_sensor; } void set_raw_position_sensor(sensor::Sensor *raw_position_sensor) { this->raw_position_sensor_ = raw_position_sensor; } @@ -28,9 +25,6 @@ class AS5600Sensor : public PollingComponent, public Parented<AS5600Component>, OutRangeMode get_out_of_range_mode() { return this->out_of_range_mode_; } protected: - sensor::Sensor *angle_sensor_{nullptr}; - sensor::Sensor *raw_angle_sensor_{nullptr}; - sensor::Sensor *position_sensor_{nullptr}; sensor::Sensor *raw_position_sensor_{nullptr}; sensor::Sensor *gain_sensor_{nullptr}; sensor::Sensor *magnitude_sensor_{nullptr}; From 47774fb644a162c5e38941a1b392ab7374aecb2e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 19:55:57 -0400 Subject: [PATCH 1784/2030] [modbus_controller] Fix wrong enum in function_code_to_register (#15253) --- esphome/components/modbus_controller/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index dfc43bf23b..cb0969913a 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -362,7 +362,7 @@ async def register_modbus_device(var, config): def function_code_to_register(function_code): FUNCTION_CODE_TYPE_MAP = { "read_coils": ModbusRegisterType.COIL, - "read_discrete_inputs": ModbusRegisterType.DISCRETE, + "read_discrete_inputs": ModbusRegisterType.DISCRETE_INPUT, "read_holding_registers": ModbusRegisterType.HOLDING, "read_input_registers": ModbusRegisterType.READ, "write_single_coil": ModbusRegisterType.COIL, From b6abfec82e4e51bac2f0a927ca3180b174d70c02 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 22:22:24 -0400 Subject: [PATCH 1785/2030] [core] Fix area/device hash collision validation not running (#15259) --- esphome/config.py | 18 ++++++++++++++++++ esphome/core/config.py | 15 ++++++--------- script/ci-custom.py | 12 ++++++++++++ tests/unit_tests/core/test_config.py | 18 ++++++++++++++++++ .../config/area_singular_hash_collision.yaml | 10 ++++++++++ 5 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 tests/unit_tests/fixtures/core/config/area_singular_hash_collision.yaml diff --git a/esphome/config.py b/esphome/config.py index 7a6feea3d3..641b6ec1b4 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -958,6 +958,23 @@ class FinalValidateValidationStep(ConfigValidationStep): fv.full_config.reset(token) +class CoreFinalValidateStep(ConfigValidationStep): + """Run final validation on core esphome config (area/device hash collisions).""" + + # Same priority as component final validate steps + priority = -20.0 + + def run(self, result: Config) -> None: + if result.errors: + return + + token = fv.full_config.set(result) + with result.catch_error([CONF_ESPHOME]): + if CONF_ESPHOME in result: + core_config.validate_ids_and_references(result[CONF_ESPHOME]) + fv.full_config.reset(token) + + class PinUseValidationCheck(ConfigValidationStep): """Check for pin reuse""" @@ -1085,6 +1102,7 @@ def validate_config( for domain, conf in config.items(): result.add_validation_step(LoadValidationStep(domain, conf)) result.add_validation_step(IDPassValidationStep()) + result.add_validation_step(CoreFinalValidateStep()) result.add_validation_step(PinUseValidationCheck()) result.add_validation_step(RemoveReferenceValidationStep()) diff --git a/esphome/core/config.py b/esphome/core/config.py index e02c6ec75f..c47693c783 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -156,22 +156,22 @@ def validate_ids_and_references(config: ConfigType) -> ConfigType: hash_dict[hash_val] = id_obj.id # Collect all areas - all_areas: list[dict[str, str | core.ID]] = [] + all_areas: list[tuple[dict[str, str | core.ID], str]] = [] if CONF_AREA in config: - all_areas.append(config[CONF_AREA]) - all_areas.extend(config[CONF_AREAS]) + all_areas.append((config[CONF_AREA], CONF_AREA)) + all_areas.extend((area, CONF_AREAS) for area in config.get(CONF_AREAS, [])) # Validate area hash collisions and collect IDs area_hashes: dict[int, str] = {} area_ids: set[str] = set() - for area in all_areas: + for area, key in all_areas: area_id: core.ID = area[CONF_ID] - check_hash_collision(area_id, area_hashes, "Area", [CONF_AREAS, area_id.id]) + check_hash_collision(area_id, area_hashes, "Area", [key, area_id.id]) area_ids.add(area_id.id) # Validate device hash collisions and area references device_hashes: dict[int, str] = {} - for device in config[CONF_DEVICES]: + for device in config.get(CONF_DEVICES, []): device_id: core.ID = device[CONF_ID] check_hash_collision( device_id, device_hashes, "Device", [CONF_DEVICES, device_id.id] @@ -329,9 +329,6 @@ CONFIG_SCHEMA = cv.All( ) -FINAL_VALIDATE_SCHEMA = cv.All(validate_ids_and_references) - - PRELOAD_CONFIG_SCHEMA = cv.Schema( { cv.Required(CONF_NAME): cv.valid_name, diff --git a/script/ci-custom.py b/script/ci-custom.py index 7d0680a491..ad39f92005 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -1006,6 +1006,18 @@ def lint_log_in_header(fname, line, col, content): ) +@lint_content_find_check( + "FINAL_VALIDATE_SCHEMA", + include=["esphome/core/*.py"], + exclude=["esphome/core/entity_helpers.py"], +) +def lint_final_validate_in_core(fname, line, col, content): + return ( + "FINAL_VALIDATE_SCHEMA in esphome/core/ is not picked up by the component loader. " + "Use CoreFinalValidateStep in esphome/config.py instead." + ) + + def main(): colorama.init() diff --git a/tests/unit_tests/core/test_config.py b/tests/unit_tests/core/test_config.py index 474d31a90a..6fa8f7ed43 100644 --- a/tests/unit_tests/core/test_config.py +++ b/tests/unit_tests/core/test_config.py @@ -248,6 +248,24 @@ def test_area_id_hash_collision( ) +def test_area_singular_hash_collision( + yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] +) -> None: + """Test that area hash collisions between singular area: and areas: list are detected.""" + result = load_config_from_fixture( + yaml_file, "area_singular_hash_collision.yaml", FIXTURES_DIR + ) + assert result is None + + captured = capsys.readouterr() + assert ( + "Area ID 'd6ka' with hash 3082558663 collides with existing area ID 'test_2258'" + in captured.out + ) + # Error path should point to 'areas' (where the colliding entry is), not 'area' + assert "areas" in captured.out + + def test_device_duplicate_id( yaml_file: Callable[[str], str], capsys: pytest.CaptureFixture[str] ) -> None: diff --git a/tests/unit_tests/fixtures/core/config/area_singular_hash_collision.yaml b/tests/unit_tests/fixtures/core/config/area_singular_hash_collision.yaml new file mode 100644 index 0000000000..6e137f5f6e --- /dev/null +++ b/tests/unit_tests/fixtures/core/config/area_singular_hash_collision.yaml @@ -0,0 +1,10 @@ +esphome: + name: test + area: + id: test_2258 + name: "Area 1" + areas: + - id: d6ka + name: "Area 2" + +host: From 7a7c33fdb16f2b32d95d194ed5130471e6bb99e3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Mar 2026 15:38:06 -1000 Subject: [PATCH 1786/2030] [esp32_ble_server] Fix set_value action with static data lists (#15285) --- .../components/esp32_ble_server/ble_server_automations.h | 2 ++ tests/components/esp32_ble_server/common.yaml | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/esphome/components/esp32_ble_server/ble_server_automations.h b/esphome/components/esp32_ble_server/ble_server_automations.h index fe18600280..0bbfdffd5b 100644 --- a/esphome/components/esp32_ble_server/ble_server_automations.h +++ b/esphome/components/esp32_ble_server/ble_server_automations.h @@ -70,6 +70,7 @@ template<typename... Ts> class BLECharacteristicSetValueAction : public Action<T public: BLECharacteristicSetValueAction(BLECharacteristic *characteristic) : parent_(characteristic) {} TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer) + void set_buffer(std::initializer_list<uint8_t> buffer) { this->buffer_ = std::vector<uint8_t>(buffer); } void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } void play(const Ts &...x) override { // If the listener is already set, do nothing @@ -115,6 +116,7 @@ template<typename... Ts> class BLEDescriptorSetValueAction : public Action<Ts... public: BLEDescriptorSetValueAction(BLEDescriptor *descriptor) : parent_(descriptor) {} TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer) + void set_buffer(std::initializer_list<uint8_t> buffer) { this->buffer_ = std::vector<uint8_t>(buffer); } void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } void play(const Ts &...x) override { this->parent_->set_value(this->buffer_.value(x...)); } diff --git a/tests/components/esp32_ble_server/common.yaml b/tests/components/esp32_ble_server/common.yaml index 7fe0b2eb5f..4e34049038 100644 --- a/tests/components/esp32_ble_server/common.yaml +++ b/tests/components/esp32_ble_server/common.yaml @@ -69,3 +69,11 @@ esp32_ble_server: - ble_server.descriptor.set_value: id: test_change_descriptor value: !lambda return bytebuffer::ByteBuffer::wrap({0x03, 0x04, 0x05}).get_data(); + - ble_server.characteristic.set_value: + id: test_change_characteristic + value: + data: [0xfc, 0xef, 0xfe, 0x86] + - ble_server.descriptor.set_value: + id: test_change_descriptor + value: + data: [0x01, 0x02, 0x03] From d9adb078aa2fa4ba1db4912672d7904ea1038818 Mon Sep 17 00:00:00 2001 From: Tobias Stanzel <tobi.stanzel@gmail.com> Date: Sun, 29 Mar 2026 19:41:00 +0200 Subject: [PATCH 1787/2030] [tm1637] Add buffer manipulation methods (#13686) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/tm1637/tm1637.cpp | 6 ++++++ esphome/components/tm1637/tm1637.h | 3 +++ tests/components/tm1637/common.yaml | 2 ++ 3 files changed, 11 insertions(+) diff --git a/esphome/components/tm1637/tm1637.cpp b/esphome/components/tm1637/tm1637.cpp index f9c876f40c..da9adb59a4 100644 --- a/esphome/components/tm1637/tm1637.cpp +++ b/esphome/components/tm1637/tm1637.cpp @@ -348,6 +348,12 @@ uint8_t TM1637Display::print(uint8_t start_pos, const char *str) { return pos - start_pos; } uint8_t TM1637Display::print(const char *str) { return this->print(0, str); } + +void TM1637Display::set_buffer(const uint8_t *data, uint8_t length) { + uint8_t len = std::min(length, (uint8_t) sizeof(this->buffer_)); + memcpy(this->buffer_, data, len); +} + uint8_t TM1637Display::printf(uint8_t pos, const char *format, ...) { va_list arg; va_start(arg, format); diff --git a/esphome/components/tm1637/tm1637.h b/esphome/components/tm1637/tm1637.h index b9e96119e9..c1fbabb21b 100644 --- a/esphome/components/tm1637/tm1637.h +++ b/esphome/components/tm1637/tm1637.h @@ -47,6 +47,9 @@ class TM1637Display : public PollingComponent { /// Print `str` at position 0. uint8_t print(const char *str); + /// Set raw buffer bytes from data array up to length bytes. + void set_buffer(const uint8_t *data, uint8_t length); + void set_intensity(uint8_t intensity) { this->intensity_ = intensity; } void set_inverted(bool inverted) { this->inverted_ = inverted; } void set_length(uint8_t length) { this->length_ = length; } diff --git a/tests/components/tm1637/common.yaml b/tests/components/tm1637/common.yaml index 8d01e29877..b6debc055d 100644 --- a/tests/components/tm1637/common.yaml +++ b/tests/components/tm1637/common.yaml @@ -5,3 +5,5 @@ display: intensity: 3 lambda: |- it.print("1234"); + static const uint8_t buf[] = {0x3f, 0x06, 0x5b, 0x4f | 0x80}; + it.set_buffer(buf, sizeof(buf)); From a91e6d92f6e922d37283c6b9679e7ce458785716 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:32:43 -1000 Subject: [PATCH 1788/2030] [core] Remove dead get_loop_priority code (#15242) --- esphome/components/ch422g/ch422g.cpp | 6 ------ esphome/components/ch422g/ch422g.h | 3 --- esphome/components/ch423/ch423.cpp | 6 ------ esphome/components/ch423/ch423.h | 3 --- esphome/components/deep_sleep/deep_sleep_component.cpp | 6 ------ esphome/components/deep_sleep/deep_sleep_component.h | 3 --- esphome/components/pca9554/pca9554.cpp | 5 ----- esphome/components/pca9554/pca9554.h | 4 ---- esphome/components/pcf8574/pcf8574.cpp | 5 ----- esphome/components/pcf8574/pcf8574.h | 3 --- esphome/components/status_led/light/status_led_light.h | 3 --- esphome/components/status_led/status_led.cpp | 3 --- esphome/components/status_led/status_led.h | 3 --- esphome/components/wifi/wifi_component.cpp | 6 ------ esphome/components/wifi/wifi_component.h | 4 ---- esphome/core/application.cpp | 6 ------ esphome/core/component.cpp | 4 ---- esphome/core/component.h | 10 ---------- esphome/core/defines.h | 1 - 19 files changed, 84 deletions(-) diff --git a/esphome/components/ch422g/ch422g.cpp b/esphome/components/ch422g/ch422g.cpp index 5f5e848c76..fc856cd563 100644 --- a/esphome/components/ch422g/ch422g.cpp +++ b/esphome/components/ch422g/ch422g.cpp @@ -124,12 +124,6 @@ bool CH422GComponent::write_outputs_() { float CH422GComponent::get_setup_priority() const { return setup_priority::IO; } -#ifdef USE_LOOP_PRIORITY -// Run our loop() method very early in the loop, so that we cache read values -// before other components call our digital_read() method. -float CH422GComponent::get_loop_priority() const { return 9.0f; } // Just after WIFI -#endif - void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } diff --git a/esphome/components/ch422g/ch422g.h b/esphome/components/ch422g/ch422g.h index 1b96568209..6e6bdad64a 100644 --- a/esphome/components/ch422g/ch422g.h +++ b/esphome/components/ch422g/ch422g.h @@ -23,9 +23,6 @@ class CH422GComponent : public Component, public i2c::I2CDevice { void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif void dump_config() override; protected: diff --git a/esphome/components/ch423/ch423.cpp b/esphome/components/ch423/ch423.cpp index 805d8df877..8424d130b4 100644 --- a/esphome/components/ch423/ch423.cpp +++ b/esphome/components/ch423/ch423.cpp @@ -129,12 +129,6 @@ bool CH423Component::write_outputs_() { float CH423Component::get_setup_priority() const { return setup_priority::IO; } -#ifdef USE_LOOP_PRIORITY -// Run our loop() method very early in the loop, so that we cache read values -// before other components call our digital_read() method. -float CH423Component::get_loop_priority() const { return 9.0f; } // Just after WIFI -#endif - void CH423GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; } diff --git a/esphome/components/ch423/ch423.h b/esphome/components/ch423/ch423.h index d85648a8f9..d384971a72 100644 --- a/esphome/components/ch423/ch423.h +++ b/esphome/components/ch423/ch423.h @@ -22,9 +22,6 @@ class CH423Component : public Component, public i2c::I2CDevice { void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif void dump_config() override; protected: diff --git a/esphome/components/deep_sleep/deep_sleep_component.cpp b/esphome/components/deep_sleep/deep_sleep_component.cpp index 0511518419..3dd1b70930 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.cpp +++ b/esphome/components/deep_sleep/deep_sleep_component.cpp @@ -40,12 +40,6 @@ void DeepSleepComponent::loop() { this->begin_sleep(); } -#ifdef USE_LOOP_PRIORITY -float DeepSleepComponent::get_loop_priority() const { - return -100.0f; // run after everything else is ready -} -#endif - void DeepSleepComponent::set_sleep_duration(uint32_t time_ms) { this->sleep_duration_ = uint64_t(time_ms) * 1000; } void DeepSleepComponent::set_run_duration(uint32_t time_ms) { this->run_duration_ = time_ms; } diff --git a/esphome/components/deep_sleep/deep_sleep_component.h b/esphome/components/deep_sleep/deep_sleep_component.h index 14713d51a1..9090f91876 100644 --- a/esphome/components/deep_sleep/deep_sleep_component.h +++ b/esphome/components/deep_sleep/deep_sleep_component.h @@ -113,9 +113,6 @@ class DeepSleepComponent : public Component { void setup() override; void dump_config() override; void loop() override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif float get_setup_priority() const override; /// Helper to enter deep sleep mode diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index d94767ef07..adc7bc0fb5 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -122,11 +122,6 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) { float PCA9554Component::get_setup_priority() const { return setup_priority::IO; } -#ifdef USE_LOOP_PRIORITY -// Run our loop() method early to invalidate cache before any other components access the pins -float PCA9554Component::get_loop_priority() const { return 9.0f; } // Just after WIFI -#endif - void PCA9554GPIOPin::setup() { pin_mode(flags_); } void PCA9554GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool PCA9554GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } diff --git a/esphome/components/pca9554/pca9554.h b/esphome/components/pca9554/pca9554.h index 6dd15ccb4b..1d877f9ce2 100644 --- a/esphome/components/pca9554/pca9554.h +++ b/esphome/components/pca9554/pca9554.h @@ -23,10 +23,6 @@ class PCA9554Component : public Component, float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif - void dump_config() override; void set_pin_count(size_t pin_count) { this->pin_count_ = pin_count; } diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index fa9496e7e4..d3ec31436d 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -99,11 +99,6 @@ bool PCF8574Component::write_gpio_() { } float PCF8574Component::get_setup_priority() const { return setup_priority::IO; } -#ifdef USE_LOOP_PRIORITY -// Run our loop() method early to invalidate cache before any other components access the pins -float PCF8574Component::get_loop_priority() const { return 9.0f; } // Just after WIFI -#endif - void PCF8574GPIOPin::setup() { pin_mode(flags_); } void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } bool PCF8574GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } diff --git a/esphome/components/pcf8574/pcf8574.h b/esphome/components/pcf8574/pcf8574.h index 23bccc26c9..b039173789 100644 --- a/esphome/components/pcf8574/pcf8574.h +++ b/esphome/components/pcf8574/pcf8574.h @@ -26,9 +26,6 @@ class PCF8574Component : public Component, void pin_mode(uint8_t pin, gpio::Flags flags); float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif void dump_config() override; diff --git a/esphome/components/status_led/light/status_led_light.h b/esphome/components/status_led/light/status_led_light.h index a5c98d90d4..3a745e0017 100644 --- a/esphome/components/status_led/light/status_led_light.h +++ b/esphome/components/status_led/light/status_led_light.h @@ -30,9 +30,6 @@ class StatusLEDLightOutput : public light::LightOutput, public Component { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override { return 50.0f; } -#endif protected: GPIOPin *pin_{nullptr}; diff --git a/esphome/components/status_led/status_led.cpp b/esphome/components/status_led/status_led.cpp index 93a8d4b38e..a792110eeb 100644 --- a/esphome/components/status_led/status_led.cpp +++ b/esphome/components/status_led/status_led.cpp @@ -28,9 +28,6 @@ void StatusLED::loop() { } } float StatusLED::get_setup_priority() const { return setup_priority::HARDWARE; } -#ifdef USE_LOOP_PRIORITY -float StatusLED::get_loop_priority() const { return 50.0f; } -#endif } // namespace status_led } // namespace esphome diff --git a/esphome/components/status_led/status_led.h b/esphome/components/status_led/status_led.h index f262eb260c..a4b5db93d7 100644 --- a/esphome/components/status_led/status_led.h +++ b/esphome/components/status_led/status_led.h @@ -14,9 +14,6 @@ class StatusLED : public Component { void dump_config() override; void loop() override; float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif protected: GPIOPin *pin_; diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 620d1a083d..db20332667 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -970,12 +970,6 @@ void WiFiComponent::set_ap(const WiFiAP &ap) { } #endif // USE_WIFI_AP -#ifdef USE_LOOP_PRIORITY -float WiFiComponent::get_loop_priority() const { - return 10.0f; // before other loop components -} -#endif - void WiFiComponent::init_sta(size_t count) { this->sta_.init(count); } void WiFiComponent::add_sta(const WiFiAP &ap) { this->sta_.push_back(ap); } void WiFiComponent::clear_sta() { diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 55e532c37d..8dfe5fa7af 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -463,10 +463,6 @@ class WiFiComponent final : public Component { void restart_adapter(); /// WIFI setup_priority. float get_setup_priority() const override; -#ifdef USE_LOOP_PRIORITY - float get_loop_priority() const override; -#endif - /// Reconnect WiFi if required. void loop() override; diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index ce15aed1e2..5cb8a5bb24 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -99,12 +99,6 @@ void Application::setup() { if (component->can_proceed()) continue; -#ifdef USE_LOOP_PRIORITY - // Sort components 0 through i by loop priority - insertion_sort_by_priority<decltype(this->components_.begin()), &Component::get_loop_priority>( - this->components_.begin(), this->components_.begin() + i + 1); -#endif - do { uint8_t new_app_state = STATUS_LED_WARNING; uint32_t now = millis(); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index caaea89143..2ad82e1172 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -85,10 +85,6 @@ void store_component_error_message(const Component *component, const char *messa static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again -#ifdef USE_LOOP_PRIORITY -float Component::get_loop_priority() const { return 0.0f; } -#endif - float Component::get_setup_priority() const { return setup_priority::DATA; } void Component::setup() {} diff --git a/esphome/core/component.h b/esphome/core/component.h index 46cd77b034..d08b1abfcd 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -115,16 +115,6 @@ class Component { void set_setup_priority(float priority); - /** priority of loop(). higher -> executed earlier - * - * Defaults to 0. - * - * @return The loop priority of this component - */ -#ifdef USE_LOOP_PRIORITY - virtual float get_loop_priority() const; -#endif - void call(); virtual void on_shutdown() {} diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 8cf331c4d6..7259167a52 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -357,7 +357,6 @@ #ifdef USE_RP2040 #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 3, 0) -#define USE_LOOP_PRIORITY #define USE_RP2040_CRASH_HANDLER #define USE_HTTP_REQUEST_RESPONSE #define USE_I2C From 8a802ca666b608426644bfa2fc4caf7e0ab72577 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:54:07 -1000 Subject: [PATCH 1789/2030] [benchmark] Add BLE raw advertisement proto encode benchmarks (#15289) --- script/cpp_benchmark.py | 5 ++ tests/benchmarks/components/api/__init__.py | 14 +++ .../components/api/bench_proto_encode.cpp | 89 +++++++++++++++++++ .../bluetooth_proxy/bluetooth_proxy.h | 38 ++++++++ 4 files changed, 146 insertions(+) create mode 100644 tests/benchmarks/stubs/esphome/components/bluetooth_proxy/bluetooth_proxy.h diff --git a/script/cpp_benchmark.py b/script/cpp_benchmark.py index a54d3752df..92faa05819 100755 --- a/script/cpp_benchmark.py +++ b/script/cpp_benchmark.py @@ -21,6 +21,10 @@ BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "components" # Path to /tests/benchmarks/core (always included, not a component) CORE_BENCHMARKS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "core" +# Stub headers for ESP32-only components (e.g. bluetooth_proxy) that +# allow benchmarks to compile on the host platform. +STUBS_DIR: Path = Path(root_path) / "tests" / "benchmarks" / "stubs" + PLATFORMIO_OPTIONS = { "build_unflags": [ "-Os", # remove default size-opt @@ -29,6 +33,7 @@ PLATFORMIO_OPTIONS = { "-O2", # optimize for speed (CodSpeed recommends RelWithDebInfo) "-g", # debug symbols for profiling "-DUSE_BENCHMARK", # disable WarnIfComponentBlockingGuard in finish() + f"-I{STUBS_DIR}", # stub headers for ESP32-only components ], # Use deep+ LDF mode to ensure PlatformIO detects the benchmark # library dependency from nested includes. diff --git a/tests/benchmarks/components/api/__init__.py b/tests/benchmarks/components/api/__init__.py index 0687c3f87f..eb86492964 100644 --- a/tests/benchmarks/components/api/__init__.py +++ b/tests/benchmarks/components/api/__init__.py @@ -1,3 +1,4 @@ +import esphome.codegen as cg from tests.testing_helpers import ComponentManifestOverride @@ -5,3 +6,16 @@ def override_manifest(manifest: ComponentManifestOverride) -> None: # api must run its to_code to define USE_API, USE_API_PLAINTEXT, # and add the noise-c library dependency. manifest.enable_codegen() + + original_to_code = manifest.to_code + + async def to_code(config): + await original_to_code(config) + # Enable BLE proto message types for benchmarks. The real + # bluetooth_proxy component is ESP32-only; a lightweight stub + # header in tests/benchmarks/stubs/ satisfies the include. + cg.add_define("USE_BLUETOOTH_PROXY") + cg.add_define("BLUETOOTH_PROXY_MAX_CONNECTIONS", 3) + cg.add_define("BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE", 16) + + manifest.to_code = to_code diff --git a/tests/benchmarks/components/api/bench_proto_encode.cpp b/tests/benchmarks/components/api/bench_proto_encode.cpp index 656c1e17db..1e2efcd281 100644 --- a/tests/benchmarks/components/api/bench_proto_encode.cpp +++ b/tests/benchmarks/components/api/bench_proto_encode.cpp @@ -295,4 +295,93 @@ static void CalcAndEncode_DeviceInfoResponse_Fresh(benchmark::State &state) { } BENCHMARK(CalcAndEncode_DeviceInfoResponse_Fresh); +// --- BluetoothLERawAdvertisementsResponse (12 adverts, highest-volume BLE message) --- + +#ifdef USE_BLUETOOTH_PROXY + +static BluetoothLERawAdvertisementsResponse make_ble_raw_advs_12() { + static const uint8_t fake_adv_data[] = { + 0x02, 0x01, 0x06, 0x03, 0x03, 0x9F, 0xFE, 0x17, 0x16, 0x9F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + BluetoothLERawAdvertisementsResponse msg; + msg.advertisements_len = 12; + for (int i = 0; i < 12; i++) { + auto &adv = msg.advertisements[i]; + adv.address = 0xAABBCCDD0000ULL + i; + adv.rssi = -60 - i; + adv.address_type = 1; + memcpy(adv.data, fake_adv_data, sizeof(fake_adv_data)); + adv.data_len = sizeof(fake_adv_data); + } + return msg; +} + +static void CalculateSize_BLERawAdvs12(benchmark::State &state) { + auto msg = make_ble_raw_advs_12(); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_BLERawAdvs12); + +static void Encode_BLERawAdvs12(benchmark::State &state) { + auto msg = make_ble_raw_advs_12(); + APIBuffer buffer; + uint32_t total_size = msg.calculate_size(); + buffer.resize(total_size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_BLERawAdvs12); + +static void CalcAndEncode_BLERawAdvs12(benchmark::State &state) { + auto msg = make_ble_raw_advs_12(); + APIBuffer buffer; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_BLERawAdvs12); + +static void CalcAndEncode_BLERawAdvs12_Fresh(benchmark::State &state) { + auto msg = make_ble_raw_advs_12(); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + benchmark::DoNotOptimize(buffer.data()); + } + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_BLERawAdvs12_Fresh); + +#endif // USE_BLUETOOTH_PROXY + } // namespace esphome::api::benchmarks diff --git a/tests/benchmarks/stubs/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/tests/benchmarks/stubs/esphome/components/bluetooth_proxy/bluetooth_proxy.h new file mode 100644 index 0000000000..0934e0d4ed --- /dev/null +++ b/tests/benchmarks/stubs/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -0,0 +1,38 @@ +// Stub for benchmark builds — provides the minimal interface that +// api_connection.cpp needs when USE_BLUETOOTH_PROXY is defined, +// without pulling in ESP32 BLE dependencies. +#pragma once + +#include "esphome/components/api/api_pb2.h" + +namespace esphome { +namespace api { +class APIConnection; +} // namespace api + +namespace bluetooth_proxy { + +class BluetoothProxy { + public: + api::APIConnection *get_api_connection() const { return nullptr; } + void subscribe_api_connection(api::APIConnection *conn, uint32_t flags) {} + void unsubscribe_api_connection(api::APIConnection *conn) {} + void bluetooth_device_request(const api::BluetoothDeviceRequest &msg) {} + void bluetooth_gatt_read(const api::BluetoothGATTReadRequest &msg) {} + void bluetooth_gatt_write(const api::BluetoothGATTWriteRequest &msg) {} + void bluetooth_gatt_read_descriptor(const api::BluetoothGATTReadDescriptorRequest &msg) {} + void bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg) {} + void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg) {} + void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg) {} + void send_connections_free(api::APIConnection *conn) {} + void bluetooth_scanner_set_mode(bool active) {} + void bluetooth_set_connection_params(const api::BluetoothSetConnectionParamsRequest &msg) {} + uint32_t get_feature_flags() const { return 0; } + void get_bluetooth_mac_address_pretty(char *buf) const { buf[0] = '\0'; } +}; + +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +extern BluetoothProxy *global_bluetooth_proxy; + +} // namespace bluetooth_proxy +} // namespace esphome From 1f3fd60d294eed3162328520077119541666101f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:55:39 -1000 Subject: [PATCH 1790/2030] [version] Remove duplicate build_info_data.h include (#15288) --- esphome/components/version/version_text_sensor.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 8aec98d2da..34c7aae6bc 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -1,6 +1,5 @@ #include "version_text_sensor.h" #include "esphome/core/application.h" -#include "esphome/core/build_info_data.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" #include "esphome/core/progmem.h" @@ -36,7 +35,9 @@ void VersionTextSensor::setup() { if (!this->hide_timestamp_) { size_t len = strlen(version_str); ESPHOME_strncat_P(version_str, BUILT_STR, sizeof(version_str) - len - 1); - ESPHOME_strncat_P(version_str, ESPHOME_BUILD_TIME_STR, sizeof(version_str) - strlen(version_str) - 1); + char build_time_buf[Application::BUILD_TIME_STR_SIZE]; + App.get_build_time_string(build_time_buf); + strncat(version_str, build_time_buf, sizeof(version_str) - strlen(version_str) - 1); } // The closing parenthesis is part of the config-hash suffix and must From 2a97eca00b82e8ef10c5203f9b1865ac6c5cc6de Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:55:52 -1000 Subject: [PATCH 1791/2030] [sensor] Use std::array in ValueList/FilterOut/ThrottleWithPriority filters (#15265) --- esphome/components/sensor/__init__.py | 6 ++-- esphome/components/sensor/filter.cpp | 38 ++++++-------------- esphome/components/sensor/filter.h | 51 +++++++++++++++++++-------- esphome/core/helpers.h | 18 ++++++++++ 4 files changed, 70 insertions(+), 43 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 19d03a0afc..5569567de1 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -381,7 +381,7 @@ async def filter_out_filter_to_code(config, filter_id): if not isinstance(config, list): config = [config] template_ = [await cg.templatable(x, [], float) for x in config] - return cg.new_Pvariable(filter_id, template_) + return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(template_)), template_) QUANTILE_SCHEMA = cv.All( @@ -650,7 +650,9 @@ async def throttle_with_priority_filter_to_code(config, filter_id): if not isinstance(config[CONF_VALUE], list): config[CONF_VALUE] = [config[CONF_VALUE]] template_ = [await cg.templatable(x, [], float) for x in config[CONF_VALUE]] - return cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], template_) + return cg.new_Pvariable( + filter_id, cg.TemplateArguments(len(template_)), config[CONF_TIMEOUT], template_ + ) HEARTBEAT_SCHEMA = cv.Schema( diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index d995ee4111..66a9e9555b 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -222,16 +222,14 @@ MultiplyFilter::MultiplyFilter(TemplatableValue<float> multiplier) : multiplier_ optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); } -// ValueListFilter (base class) -ValueListFilter::ValueListFilter(std::initializer_list<TemplatableValue<float>> values) : values_(values) {} - -bool ValueListFilter::value_matches_any_(float sensor_value) { - int8_t accuracy = this->parent_->get_accuracy_decimals(); +// ValueListFilter helper (non-template, shared by all ValueListFilter<N> instantiations) +bool value_list_matches_any(Sensor *parent, float sensor_value, const TemplatableValue<float> *values, size_t count) { + int8_t accuracy = parent->get_accuracy_decimals(); float accuracy_mult = pow10_int(accuracy); float rounded_sensor = roundf(accuracy_mult * sensor_value); - for (auto &filter_value : this->values_) { - float fv = filter_value.value(); + for (size_t i = 0; i < count; i++) { + float fv = values[i].value(); // Handle NaN comparison if (std::isnan(fv)) { @@ -248,16 +246,6 @@ bool ValueListFilter::value_matches_any_(float sensor_value) { return false; } -// FilterOutValueFilter -FilterOutValueFilter::FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out) - : ValueListFilter(values_to_filter_out) {} - -optional<float> FilterOutValueFilter::new_value(float value) { - if (this->value_matches_any_(value)) - return {}; // Filter out - return value; // Pass through -} - // ThrottleFilter ThrottleFilter::ThrottleFilter(uint32_t min_time_between_inputs) : min_time_between_inputs_(min_time_between_inputs) {} optional<float> ThrottleFilter::new_value(float value) { @@ -269,17 +257,13 @@ optional<float> ThrottleFilter::new_value(float value) { return {}; } -// ThrottleWithPriorityFilter -ThrottleWithPriorityFilter::ThrottleWithPriorityFilter( - uint32_t min_time_between_inputs, std::initializer_list<TemplatableValue<float>> prioritized_values) - : ValueListFilter(prioritized_values), min_time_between_inputs_(min_time_between_inputs) {} - -optional<float> ThrottleWithPriorityFilter::new_value(float value) { +// ThrottleWithPriorityFilter helper (non-template, keeps App access in .cpp) +optional<float> throttle_with_priority_new_value(Sensor *parent, float value, const TemplatableValue<float> *values, + size_t count, uint32_t &last_input, uint32_t min_time_between_inputs) { const uint32_t now = App.get_loop_component_start_time(); - // Allow value through if: no previous input, time expired, or is prioritized - if (this->last_input_ == 0 || now - this->last_input_ >= min_time_between_inputs_ || - this->value_matches_any_(value)) { - this->last_input_ = now; + if (last_input == 0 || now - last_input >= min_time_between_inputs || + value_list_matches_any(parent, value, values, count)) { + last_input = now; return value; } return {}; diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 6a76bd373e..80fa14742c 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -3,6 +3,7 @@ #include "esphome/core/defines.h" #ifdef USE_SENSOR_FILTER +#include <array> #include <utility> #include <vector> #include "esphome/core/automation.h" @@ -328,28 +329,42 @@ class MultiplyFilter : public Filter { TemplatableValue<float> multiplier_; }; -/** Base class for filters that compare sensor values against a list of configured values. +/// Non-template helper for value matching (implementation in filter.cpp) +bool value_list_matches_any(Sensor *parent, float sensor_value, const TemplatableValue<float> *values, size_t count); + +/** Base class for filters that compare sensor values against a fixed list of configured values. * - * This base class provides common functionality for filters that need to check if a sensor - * value matches any value in a configured list, with proper handling of NaN values and - * accuracy-based rounding for comparisons. + * Templated on N (the number of values) so the list is stored inline in a std::array, + * avoiding heap allocation and the overhead of FixedVector. + * + * @tparam N Number of values in the filter list, set by code generation to match + * the exact number of values configured in YAML. */ -class ValueListFilter : public Filter { +template<size_t N> class ValueListFilter : public Filter { protected: - explicit ValueListFilter(std::initializer_list<TemplatableValue<float>> values); + explicit ValueListFilter(std::initializer_list<TemplatableValue<float>> values) { + init_array_from(this->values_, values); + } /// Check if sensor value matches any configured value (with accuracy rounding) - bool value_matches_any_(float sensor_value); + bool value_matches_any_(float sensor_value) { + return value_list_matches_any(this->parent_, sensor_value, this->values_.data(), N); + } - FixedVector<TemplatableValue<float>> values_; + std::array<TemplatableValue<float>, N> values_{}; }; /// A simple filter that only forwards the filter chain if it doesn't receive `value_to_filter_out`. -class FilterOutValueFilter : public ValueListFilter { +template<size_t N> class FilterOutValueFilter : public ValueListFilter<N> { public: - explicit FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out); + explicit FilterOutValueFilter(std::initializer_list<TemplatableValue<float>> values_to_filter_out) + : ValueListFilter<N>(values_to_filter_out) {} - optional<float> new_value(float value) override; + optional<float> new_value(float value) override { + if (this->value_matches_any_(value)) + return {}; // Filter out + return value; // Pass through + } }; class ThrottleFilter : public Filter { @@ -363,13 +378,21 @@ class ThrottleFilter : public Filter { uint32_t min_time_between_inputs_; }; +/// Non-template helper for ThrottleWithPriorityFilter (implementation in filter.cpp) +optional<float> throttle_with_priority_new_value(Sensor *parent, float value, const TemplatableValue<float> *values, + size_t count, uint32_t &last_input, uint32_t min_time_between_inputs); + /// Same as 'throttle' but will immediately publish values contained in `value_to_prioritize`. -class ThrottleWithPriorityFilter : public ValueListFilter { +template<size_t N> class ThrottleWithPriorityFilter : public ValueListFilter<N> { public: explicit ThrottleWithPriorityFilter(uint32_t min_time_between_inputs, - std::initializer_list<TemplatableValue<float>> prioritized_values); + std::initializer_list<TemplatableValue<float>> prioritized_values) + : ValueListFilter<N>(prioritized_values), min_time_between_inputs_(min_time_between_inputs) {} - optional<float> new_value(float value) override; + optional<float> new_value(float value) override { + return throttle_with_priority_new_value(this->parent_, value, this->values_.data(), N, this->last_input_, + this->min_time_between_inputs_); + } protected: uint32_t last_input_{0}; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 82c6b3833c..913614f564 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -2,6 +2,7 @@ #include <algorithm> #include <array> +#include <cassert> #include <cmath> #include <cstdarg> #include <cstdint> @@ -497,6 +498,23 @@ template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()> index_type capacity_{0}; }; +/// Initialize a std::array from an initializer_list. Uses memcpy for trivially copyable types (optimal codegen), +/// falls back to element-wise copy for non-trivially copyable types (e.g. TemplatableValue). +/// N is set by code generation; assert catches mismatches in debug/integration tests. +template<typename T, size_t N> inline void init_array_from(std::array<T, N> &dest, std::initializer_list<T> src) { +#ifdef ESPHOME_DEBUG + assert(src.size() == N); +#endif + if constexpr (std::is_trivially_copyable_v<T>) { + __builtin_memcpy(dest.data(), src.begin(), N * sizeof(T)); + } else { + size_t i = 0; + for (const auto &v : src) { + dest[i++] = v; + } + } +} + /// Fixed-capacity vector - allocates once at runtime, never reallocates /// This avoids std::vector template overhead (_M_realloc_insert, _M_default_append) /// when size is known at initialization but not at compile time From 5da3253f4b67128b991c7631b9730488072f9a6a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:57:52 -1000 Subject: [PATCH 1792/2030] [esp8266] Add enable_scanf_float option (#15284) --- esphome/components/esp8266/__init__.py | 62 +++++++++++++++---- .../components/esp8266/test.esp8266-ard.yaml | 3 + tests/unit_tests/components/test_esp8266.py | 62 +++++++++++++++++++ 3 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 tests/unit_tests/components/test_esp8266.py diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 16043b6d69..2081145096 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -1,5 +1,6 @@ import logging from pathlib import Path +import re import esphome.codegen as cg import esphome.config_validation as cv @@ -18,8 +19,9 @@ from esphome.const import ( PLATFORM_ESP8266, ThreadModel, ) -from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority from esphome.helpers import copy_file_if_changed +from esphome.types import ConfigType from .boards import BOARDS, ESP8266_LD_SCRIPTS from .const import ( @@ -40,12 +42,42 @@ from .const import ( ) from .gpio import PinInitialState, add_pin_initial_states_array +CONF_ENABLE_SCANF_FLOAT = "enable_scanf_float" +# Heuristically matches scanf/sscanf calls with float format specifiers. +# Standard scanf float conversions: %f %F %e %E %g %G %a %A +# With optional modifiers: %*f (suppression), %8f (width), %lf %Lf (length) +# Also matches non-standard patterns like %.2f as a heuristic — these are +# invalid in scanf but users may write them by analogy with printf. +# Uses [^;]*? to stay within a single statement, preventing false positives +# from e.g. sscanf(buf, "%d", &x); printf("%f", val); +_SCANF_FLOAT_RE = re.compile(r"scanf\s*\([^;]*?%[*\d.]*[hlL]*[feEgGaAF]") + CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) AUTO_LOAD = ["preferences"] IS_TARGET_PLATFORM = True +def lambdas_use_scanf_float(config: ConfigType) -> bool: + """Check if any lambda in the config uses scanf with a float format specifier. + + Comments are stripped before matching to avoid false positives from + commented-out code. The cost of a false positive is only ~8KB flash. + """ + stack: list = [config] + while stack: + obj = stack.pop() + if isinstance(obj, Lambda): + src = obj.comment_remover(obj.value) + if _SCANF_FLOAT_RE.search(src): + return True + elif isinstance(obj, dict): + stack.extend(obj.values()) + elif isinstance(obj, list): + stack.extend(obj) + return False + + def set_core_data(config): CORE.data[KEY_ESP8266] = {} CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP8266 @@ -181,6 +213,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_ENABLE_SERIAL): cv.boolean, cv.Optional(CONF_ENABLE_SERIAL1): cv.boolean, cv.Optional(CONF_ENABLE_FULL_PRINTF, default=False): cv.boolean, + cv.Optional(CONF_ENABLE_SCANF_FLOAT): cv.boolean, } ), set_core_data, @@ -201,16 +234,23 @@ async def to_code(config): cg.add_define("ESPHOME_VARIANT", "ESP8266") cg.add_define(ThreadModel.SINGLE) - cg.add_platformio_option( - "extra_scripts", - [ - "pre:testing_mode.py", - "pre:exclude_updater.py", - "pre:exclude_waveform.py", - "pre:remove_float_scanf.py", - "post:post_build.py", - ], - ) + enable_scanf_float = config.get(CONF_ENABLE_SCANF_FLOAT) + if enable_scanf_float is None and lambdas_use_scanf_float(CORE.config): + enable_scanf_float = True + _LOGGER.warning( + "Lambda uses scanf with a float format specifier; " + "enabling scanf float support (~8KB flash)" + ) + + extra_scripts = [ + "pre:testing_mode.py", + "pre:exclude_updater.py", + "pre:exclude_waveform.py", + ] + if not enable_scanf_float: + extra_scripts.append("pre:remove_float_scanf.py") + extra_scripts.append("post:post_build.py") + cg.add_platformio_option("extra_scripts", extra_scripts) conf = config[CONF_FRAMEWORK] cg.add_platformio_option("framework", "arduino") diff --git a/tests/components/esp8266/test.esp8266-ard.yaml b/tests/components/esp8266/test.esp8266-ard.yaml index c77218f7a3..ba70c1a6a4 100644 --- a/tests/components/esp8266/test.esp8266-ard.yaml +++ b/tests/components/esp8266/test.esp8266-ard.yaml @@ -14,3 +14,6 @@ esphome: assert(x == 95); x = clamp_at_most(x, 40); assert(x == 40); + - lambda: |- + float value = 0.0f; + sscanf("3.14", "%f", &value); diff --git a/tests/unit_tests/components/test_esp8266.py b/tests/unit_tests/components/test_esp8266.py new file mode 100644 index 0000000000..318fd2d889 --- /dev/null +++ b/tests/unit_tests/components/test_esp8266.py @@ -0,0 +1,62 @@ +"""Tests for ESP8266 component.""" + +import pytest + +from esphome.components.esp8266 import lambdas_use_scanf_float +from esphome.core import Lambda +from esphome.types import ConfigType + + +@pytest.mark.parametrize( + ("src", "expected"), + [ + # Basic float formats + ('sscanf(buf, "%f", &v)', True), + ('sscanf(buf, "%F", &v)', True), + ('sscanf(buf, "%e", &v)', True), + ('sscanf(buf, "%E", &v)', True), + ('sscanf(buf, "%g", &v)', True), + ('sscanf(buf, "%G", &v)', True), + ('sscanf(buf, "%a", &v)', True), + ('sscanf(buf, "%A", &v)', True), + # With modifiers + ('sscanf(buf, "%lf", &v)', True), + ('sscanf(buf, "%Lf", &v)', True), + ('sscanf(buf, "%8lf", &v)', True), + ('sscanf(buf, "%*f")', True), + ('sscanf(buf, "%.2f", &v)', True), + # Mixed formats + ('sscanf(buf, "%d,%f", &a, &b)', True), + # fscanf and std::sscanf + ('fscanf(fp, "%f", &v)', True), + ('std::sscanf(buf, "%f", &v)', True), + # Multi-line + ('sscanf(buf,\n"%f", &v)', True), + # No float format + ('sscanf(buf, "%d", &v)', False), + ('sscanf(buf, "%s", s)', False), + # printf not scanf + ('printf("%f", val)', False), + # %f in a different statement after scanf + ('sscanf(buf, "%d", &x); printf("%f", val);', False), + # scanf %f in comment only + ('// sscanf(buf, "%f", &v)\nsscanf(buf, "%d", &x)', False), + ('/* sscanf(buf, "%f") */\nsscanf(buf, "%d", &x)', False), + ], +) +def test_lambdas_use_scanf_float(src: str, expected: bool) -> None: + """Test scanf float detection in lambda source.""" + config: ConfigType = {"test": [Lambda(src)]} + assert lambdas_use_scanf_float(config) is expected + + +def test_lambdas_use_scanf_float_no_lambdas() -> None: + """Test with config containing no lambdas.""" + config: ConfigType = {"key": "value", "list": [1, 2]} + assert lambdas_use_scanf_float(config) is False + + +def test_lambdas_use_scanf_float_nested() -> None: + """Test detection in deeply nested config.""" + config: ConfigType = {"a": {"b": {"c": [Lambda('sscanf(buf, "%f", &v)')]}}} + assert lambdas_use_scanf_float(config) is True From 584807b03900ea488f46fde1cd3a1cd13234bed6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:58:03 -1000 Subject: [PATCH 1793/2030] [ld2410] Fix flaky integration test race condition (#15299) --- tests/integration/test_uart_mock_ld2410.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_uart_mock_ld2410.py b/tests/integration/test_uart_mock_ld2410.py index ce0e1bb7ec..88d6f2cbac 100644 --- a/tests/integration/test_uart_mock_ld2410.py +++ b/tests/integration/test_uart_mock_ld2410.py @@ -73,9 +73,16 @@ async def test_uart_mock_ld2410( ], ) - # Signal when we see recovery frame values + # Signal when we see ALL recovery frame values to avoid race where some + # arrive after the waiter fires but before we index into the lists recovery_received = collector.add_waiter( - lambda: pytest.approx(50.0) in collector.sensor_states["moving_distance"] + lambda: ( + pytest.approx(50.0) in collector.sensor_states["moving_distance"] + and pytest.approx(75.0) in collector.sensor_states["still_distance"] + and pytest.approx(100.0) in collector.sensor_states["moving_energy"] + and pytest.approx(80.0) in collector.sensor_states["still_energy"] + and pytest.approx(127.0) in collector.sensor_states["detection_distance"] + ) ) async with ( From c2b8ea33610be67f2ea7cf043e2276552d1c558a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 12:02:29 -1000 Subject: [PATCH 1794/2030] [web_server_base] Reduce sizeof(WebServerBase) by 4 bytes (#15251) --- esphome/components/web_server_base/web_server_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/web_server_base/web_server_base.h b/esphome/components/web_server_base/web_server_base.h index 48e13ad71e..2aa3ae215c 100644 --- a/esphome/components/web_server_base/web_server_base.h +++ b/esphome/components/web_server_base/web_server_base.h @@ -135,7 +135,7 @@ class WebServerBase { uint16_t get_port() const { return port_; } protected: - int initialized_{0}; + uint8_t initialized_{0}; uint16_t port_{80}; AsyncWebServer *server_{nullptr}; std::vector<AsyncWebHandler *> handlers_; From 38fa8925da52981021c334e6f88ba4e521208fc1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 12:02:47 -1000 Subject: [PATCH 1795/2030] [ai] Add automation, callback manager, and test grouping docs (#15243) --- .ai/instructions.md | 174 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) diff --git a/.ai/instructions.md b/.ai/instructions.md index a7e08f9c4d..86f554e9ce 100644 --- a/.ai/instructions.md +++ b/.ai/instructions.md @@ -239,6 +239,123 @@ This document provides essential context for AI models interacting with this pro var = await switch.new_switch(config) ``` +* **Automations (Triggers, Actions, Conditions):** + + Automations have three building blocks: **Triggers** (fire when something happens), **Actions** (do something), and **Conditions** (check if something is true). + + * **Triggers -- Callback method (preferred):** + + Use `build_callback_automation()` for simple triggers. This eliminates the need for a C++ Trigger class by using a lightweight pointer-sized forwarder struct registered directly as a callback. No `CONF_TRIGGER_ID` in the schema. + + **Python:** + ```python + from esphome import automation + + CONFIG_SCHEMA = cv.Schema({ + cv.GenerateID(): cv.declare_id(MyComponent), + cv.Optional(CONF_ON_STATE): automation.validate_automation({}), + }).extend(cv.COMPONENT_SCHEMA) + + async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + for conf in config.get(CONF_ON_STATE, []): + await automation.build_callback_automation( + var, "add_on_state_callback", [(bool, "x")], conf + ) + ``` + + `build_callback_automation` arguments: `parent`, `callback_method` (C++ method name), `args` (template args as `[(type, name)]` tuples), `config`, and optional `forwarder` (defaults to `TriggerForwarder<Ts...>`). + + For boolean filtering (e.g. `on_press`/`on_release`), use built-in forwarders with `args=[]`: + ```python + for conf_key, forwarder in ( + (CONF_ON_PRESS, automation.TriggerOnTrueForwarder), + (CONF_ON_RELEASE, automation.TriggerOnFalseForwarder), + ): + for conf in config.get(conf_key, []): + await automation.build_callback_automation( + var, "add_on_state_callback", [], conf, forwarder=forwarder + ) + ``` + + **C++ -- no trigger class needed.** The callback registration method must be templatized to accept both `std::function` and lightweight forwarder structs (which avoid heap allocation): + ```cpp + class MyComponent : public Component { + public: + // Must be a template -- accepts both std::function and pointer-sized forwarder structs + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } + protected: + // Use CallbackManager when callbacks are always registered (e.g. core components) + CallbackManager<void(bool)> state_callback_; + // Use LazyCallbackManager when callbacks are often not registered -- saves 8 bytes + // (nullptr vs empty std::vector) per instance when no callbacks are added + // LazyCallbackManager<void(bool)> state_callback_; + }; + ``` + + * **Triggers -- Trigger class method:** + + Use `build_automation()` with a `Trigger<Ts...>` subclass only when the forwarder needs **mutable state beyond a single `Automation*` pointer** (e.g. edge detection tracking previous state, timing logic). + + **Python:** + ```python + TurnOnTrigger = my_ns.class_("TurnOnTrigger", automation.Trigger.template()) + + CONFIG_SCHEMA = cv.Schema({ + cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( + {cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TurnOnTrigger)} + ), + }) + + async def to_code(config): + for conf in config.get(CONF_ON_TURN_ON, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + ``` + + **C++:** + ```cpp + class TurnOnTrigger : public Trigger<> { + public: + explicit TurnOnTrigger(MyComponent *parent) : last_on_{false} { + parent->add_on_state_callback([this](bool state) { + if (state && !this->last_on_) + this->trigger(); + this->last_on_ = state; + }); + } + protected: + bool last_on_; + }; + ``` + + * **Actions:** + ```cpp + template<typename... Ts> class MyAction : public Action<Ts...> { + public: + explicit MyAction(MyComponent *parent) : parent_(parent) {} + void play(const Ts &...) override { this->parent_->do_something(); } + protected: + MyComponent *parent_; + }; + ``` + Register with `@automation.register_action("my_component.do_something", MyAction, schema, synchronous=True)`. Use `synchronous=True` for actions that run to completion inside `play()` without deferring. Use `synchronous=False` if the action may suspend/defer execution (e.g. `delay`, `wait_until`, `script.wait`) or store trigger arguments for later use. + + * **Conditions:** + ```cpp + template<typename... Ts> class MyCondition : public Condition<Ts...> { + public: + explicit MyCondition(MyComponent *parent) : parent_(parent) {} + bool check(const Ts &...) override { return this->parent_->is_active(); } + protected: + MyComponent *parent_; + }; + ``` + Register with `@automation.register_condition("my_component.is_active", MyCondition, schema)`. + * **Configuration Validation:** * **Common Validators:** `cv.int_`, `cv.float_`, `cv.string`, `cv.boolean`, `cv.int_range(min=0, max=100)`, `cv.positive_int`, `cv.percentage`. * **Complex Validation:** `cv.All(cv.string, cv.Length(min=1, max=50))`, `cv.Any(cv.int_, cv.string)`. @@ -274,10 +391,39 @@ This document provides essential context for AI models interacting with this pro * **Component Tests:** YAML-based compilation tests are located in `tests/`. The structure is as follows: ``` tests/ - ├── test_build_components/ # Base test configurations - └── components/[component]/ # Component-specific tests + ├── test_build_components/ + │ └── common/ # Shared bus packages (uart, i2c, spi, etc.) + │ ├── uart/ # UART at default baud rate + │ ├── uart_115200/ # UART at 115200 baud + │ ├── i2c/ # I2C bus + │ └── spi/ # SPI bus + └── components/[component]/ + ├── common.yaml # Component-only config (no bus definitions) + ├── test.esp32-idf.yaml + ├── test.esp8266-ard.yaml + └── test.rp2040-ard.yaml ``` Run them using `script/test_build_components`. Use `-c <component>` to test specific components and `-t <target>` for specific platforms. + + * **Test Grouping with Packages:** Components that use shared bus packages can be grouped together in CI to reduce build count. **Never define buses (uart, i2c, spi, modbus) directly in test YAML files** — always use packages from `test_build_components/common/`: + ```yaml + # test.esp32-idf.yaml — use packages for buses + packages: + uart: !include ../../test_build_components/common/uart_115200/esp32-idf.yaml + + <<: !include common.yaml + ``` + ```yaml + # common.yaml — component config only, NO bus definitions + my_component: + id: my_instance + + sensor: + - platform: my_component + name: My Sensor + ``` + Components that define buses directly are flagged as "NEEDS MIGRATION" and cannot be grouped, increasing CI build time. + * **Testing All Components Together:** To verify that all components can be tested together without ID conflicts or configuration issues, use: ```bash ./script/test_component_grouping.py -e config --all @@ -417,6 +563,30 @@ This document provides essential context for AI models interacting with this pro Note: Avoiding heap allocation after `setup()` is always required regardless of component type. The prioritization above is about the effort spent on container optimization (e.g., migrating from `std::vector` to `StaticVector`). + **Callback Managers:** + + ESPHome provides two callback manager types in `esphome/core/helpers.h` for the observer pattern. Both support `std::function`, lambdas, and lightweight forwarder structs via their templatized `add()` method. + + | Type | Idle overhead (32-bit) | When to use | + |------|----------------------|-------------| + | `CallbackManager<void(Ts...)>` | 12 bytes (empty `std::vector`) | Callbacks are always or almost always registered | + | `LazyCallbackManager<void(Ts...)>` | 4 bytes (`nullptr`) | Callbacks are often not registered (common case) | + + `LazyCallbackManager` is a drop-in replacement for `CallbackManager` that defers allocation until the first callback is added. Prefer it for entity-level callbacks where most instances have no subscribers. + + **Important:** Registration methods that add to a callback manager **must always be templatized** to accept both `std::function` and pointer-sized forwarder structs (used by `build_callback_automation`). Never use `std::function` in the method signature: + ```cpp + // Bad -- forces heap allocation for forwarder structs + void add_on_state_callback(std::function<void(bool)> &&callback) { + this->state_callback_.add(std::move(callback)); + } + + // Good -- accepts any callable without forcing std::function wrapping + template<typename F> void add_on_state_callback(F &&callback) { + this->state_callback_.add(std::forward<F>(callback)); + } + ``` + * **State Management:** Use `CORE.data` for component state that needs to persist during configuration generation. Avoid module-level mutable globals. **Bad Pattern (Module-Level Globals):** From a9aaf29d837b9228437f3954c1b2fb2396035ce6 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 12:09:21 -1000 Subject: [PATCH 1796/2030] [core] Shrink Component from 12 to 8 bytes per instance (#15103) --- esphome/core/component.cpp | 24 ++++-- esphome/core/component.h | 37 +++++--- esphome/cpp_helpers.py | 123 ++++++++++++++++++++++++++- tests/unit_tests/test_cpp_helpers.py | 72 +++++++++++++++- 4 files changed, 230 insertions(+), 26 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 2ad82e1172..00a36fce3d 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -84,6 +84,8 @@ void store_component_error_message(const Component *component, const char *messa static constexpr uint16_t WARN_IF_BLOCKING_INCREMENT_MS = 10U; ///< How long the blocking time must be larger to warn again +// Threshold in ms (computed from centiseconds constant in component.h) +static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast<uint32_t>(WARN_IF_BLOCKING_OVER_CS) * 10U; float Component::get_setup_priority() const { return setup_priority::DATA; } @@ -268,15 +270,18 @@ void Component::call() { break; } } +const LogString *Component::get_component_log_str() const { + return component_source_lookup(this->component_source_index_); +} bool Component::should_warn_of_blocking(uint32_t blocking_time) { - if (blocking_time > this->warn_if_blocking_over_) { - // Prevent overflow when adding increment - if we're about to overflow, just max out - if (blocking_time + WARN_IF_BLOCKING_INCREMENT_MS < blocking_time || - blocking_time + WARN_IF_BLOCKING_INCREMENT_MS > std::numeric_limits<uint16_t>::max()) { - this->warn_if_blocking_over_ = std::numeric_limits<uint16_t>::max(); - } else { - this->warn_if_blocking_over_ = static_cast<uint16_t>(blocking_time + WARN_IF_BLOCKING_INCREMENT_MS); - } + // Convert centisecond threshold to milliseconds for comparison + uint32_t threshold_ms = static_cast<uint32_t>(this->warn_if_blocking_over_) * 10U; + if (blocking_time > threshold_ms) { + // Set new threshold: blocking_time + increment, converted back to centiseconds + uint32_t new_threshold_ms = blocking_time + WARN_IF_BLOCKING_INCREMENT_MS; + uint32_t new_cs = new_threshold_ms / 10U; + // Saturate at uint8_t max (255 = 2550ms) + this->warn_if_blocking_over_ = static_cast<uint8_t>(new_cs > 255U ? 255U : new_cs); return true; } return false; @@ -537,4 +542,7 @@ void clear_setup_priority_overrides() { } #endif +// Weak default for component_source_lookup - overridden by generated code +__attribute__((weak)) const LogString *component_source_lookup(uint8_t) { return LOG_STR("<unknown>"); } + } // namespace esphome diff --git a/esphome/core/component.h b/esphome/core/component.h index d08b1abfcd..c390a205f0 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -11,6 +11,10 @@ #include "esphome/core/log.h" #include "esphome/core/optional.h" +// Forward declarations for friend access from codegen-generated setup() +void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h +void original_setup(); // NOLINT(readability-redundant-declaration) + namespace esphome { // Forward declaration for LogString @@ -79,11 +83,14 @@ inline constexpr uint8_t STATUS_LED_WARNING = 0x08; inline constexpr uint8_t STATUS_LED_ERROR = 0x10; // Component loop override flag uses bit 5 (set at registration time) inline constexpr uint8_t COMPONENT_HAS_LOOP = 0x20; - // Remove before 2026.8.0 enum class RetryResult { DONE, RETRY }; -inline constexpr uint16_t WARN_IF_BLOCKING_OVER_MS = 50U; +inline constexpr uint8_t WARN_IF_BLOCKING_OVER_CS = 5U; // 50ms in centiseconds (1cs = 10ms) + +/// Lookup component source name by index (1-based). Generated by Python codegen. +/// Weak default returns "<unknown>" so builds without codegen still link. +const LogString *component_source_lookup(uint8_t index); class Component { public: @@ -275,23 +282,25 @@ class Component { bool has_overridden_loop() const { return (this->component_state_ & COMPONENT_HAS_LOOP) != 0; } - /** Set where this component was loaded from for some debug messages. - * - * This is set by the ESPHome core, and should not be called manually. - */ - void set_component_source(const LogString *source) { component_source_ = source; } /** Get the integration where this component was declared as a LogString for logging. * * Returns LOG_STR("<unknown>") if source not set */ - const LogString *get_component_log_str() const { - return this->component_source_ == nullptr ? LOG_STR("<unknown>") : this->component_source_; - } + const LogString *get_component_log_str() const; bool should_warn_of_blocking(uint32_t blocking_time); protected: friend class Application; + friend void ::setup(); + friend void ::original_setup(); + + /** Set where this component was loaded from for some debug messages. + * + * This is set by the ESPHome core during setup, and should not be called manually. + * @param index 1-based index into the component source lookup table (0 = not set) + */ + void set_component_source_(uint8_t index) { this->component_source_index_ = index; } virtual void call_setup(); void call_dump_config_(); @@ -509,9 +518,9 @@ class Component { void status_clear_warning_slow_path_(); void status_clear_error_slow_path_(); - // Ordered for optimal packing on 32-bit systems - const LogString *component_source_{nullptr}; - uint16_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS}; ///< Warn if blocked for this many ms (max 65.5s) + // Ordered for optimal packing on 32-bit systems (8 bytes total with vtable) + uint8_t component_source_index_{0}; ///< Index into component source PROGMEM lookup table (0 = not set) + uint8_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_CS}; ///< Warn threshold in centiseconds (max 2550ms) /// State of this component - each bit has a purpose: /// Bits 0-2: Component state (0x00=CONSTRUCTION, 0x01=SETUP, 0x02=LOOP, 0x03=FAILED, 0x04=LOOP_DONE) /// Bit 3: STATUS_LED_WARNING @@ -588,6 +597,8 @@ class WarnIfComponentBlockingGuard { this->record_runtime_stats_(); #endif #ifndef USE_BENCHMARK + // Fast path: compare against constant threshold in ms (computed at compile time from centiseconds) + static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast<uint32_t>(WARN_IF_BLOCKING_OVER_CS) * 10U; if (blocking_time > WARN_IF_BLOCKING_OVER_MS) [[unlikely]] { warn_blocking(this->component_, blocking_time); } diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index 8f8c693140..e7ff2965c8 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass, field import logging from esphome.const import ( @@ -7,15 +8,130 @@ from esphome.const import ( CONF_UPDATE_INTERVAL, KEY_PAST_SAFE_MODE, ) -from esphome.core import CORE, ID, coroutine +from esphome.core import CORE, ID, CoroPriority, coroutine, coroutine_with_priority from esphome.coroutine import FakeAwaitable -from esphome.cpp_generator import LogStringLiteral, add, add_define, get_variable +from esphome.cpp_generator import ( + RawStatement, + add, + add_define, + add_global, + get_variable, +) from esphome.cpp_types import App +from esphome.helpers import cpp_string_escape from esphome.types import ConfigFragmentType, ConfigType from esphome.util import Registry, RegistryEntry _LOGGER = logging.getLogger(__name__) +_COMPONENT_SOURCE_DOMAIN = "component_source_pool" + +# Maximum unique component source names (8-bit index, 0 = not set) +_MAX_COMPONENT_SOURCES = 0xFF # 255 + + +@dataclass +class ComponentSourcePool: + """Pool of component source names for PROGMEM lookup table. + + Source names are registered during to_code() and assigned 1-based indices. + Index 0 means "not set" (returns LOG_STR("<unknown>")). At render time, + the pool generates a C++ PROGMEM table + lookup function. + """ + + sources: dict[str, int] = field(default_factory=dict) + table_registered: bool = False + + +def _get_source_pool() -> ComponentSourcePool: + """Get or create the component source pool from CORE.data.""" + if _COMPONENT_SOURCE_DOMAIN not in CORE.data: + CORE.data[_COMPONENT_SOURCE_DOMAIN] = ComponentSourcePool() + return CORE.data[_COMPONENT_SOURCE_DOMAIN] + + +def _ensure_source_table_registered() -> None: + """Schedule the table generation job (once).""" + pool = _get_source_pool() + if pool.table_registered: + return + pool.table_registered = True + CORE.add_job(_generate_component_source_table) + + +def register_component_source(name: str) -> int: + """Register a component source name and return its 1-based index. + + Deduplicates: multiple components from the same source share one index. + """ + if not name: + return 0 + pool = _get_source_pool() + if name in pool.sources: + return pool.sources[name] + idx = len(pool.sources) + 1 + if idx > _MAX_COMPONENT_SOURCES: + _LOGGER.warning( + "Too many unique component source names (max %d), '%s' will show as '<unknown>'", + _MAX_COMPONENT_SOURCES, + name, + ) + return 0 + pool.sources[name] = idx + _ensure_source_table_registered() + return idx + + +def _generate_source_table_code( + table_var: str, + lookup_fn: str, + strings: dict[str, int], +) -> str: + """Generate C++ PROGMEM table + LogString* lookup for component sources. + + Same pattern as entity_helpers._generate_category_code but returns + const LogString* instead of const char* (needed for LOG_STR_ARG). + """ + if not strings: + return "" + + sorted_strings = sorted(strings.items(), key=lambda x: x[1]) + count = len(sorted_strings) + + # Emit individual PROGMEM char arrays so string data lives in flash on ESP8266 + lines: list[str] = [] + var_names: list[str] = [] + for i, (s, _) in enumerate(sorted_strings): + var_name = f"{table_var}_STR_{i}" + var_names.append(var_name) + lines.append( + f"static const char {var_name}[] PROGMEM = {cpp_string_escape(s)};" + ) + + entries = ", ".join(var_names) + lines.append(f"static const char *const {table_var}[] PROGMEM = {{{entries}}};") + lines.append(f"const LogString *{lookup_fn}(uint8_t index) {{") + lines.append(f' if (index == 0 || index > {count}) return LOG_STR("<unknown>");') + lines.append(" return reinterpret_cast<const LogString *>(") + lines.append(f" progmem_read_ptr(&{table_var}[index - 1]));") + lines.append("}") + return "\n".join(lines) + "\n" + + +@coroutine_with_priority(CoroPriority.FINAL) +async def _generate_component_source_table() -> None: + """Generate the component source lookup table as a FINAL-priority job. + + Runs after all component to_code() calls have registered their sources. + """ + pool = _get_source_pool() + if code := _generate_source_table_code( + "COMP_SRC_TABLE", "component_source_lookup", pool.sources + ): + add_global( + RawStatement(f"namespace esphome {{\n{code}}} // namespace esphome") + ) + async def gpio_pin_expression(conf): """Generate an expression for the given pin option. @@ -77,7 +193,8 @@ async def register_component(var, config): "Error while finding name of component, please report this", exc_info=e ) if name is not None: - add(var.set_component_source(LogStringLiteral(name))) + idx = register_component_source(name) + add(var.set_component_source_(idx)) add(App.register_component_(var)) diff --git a/tests/unit_tests/test_cpp_helpers.py b/tests/unit_tests/test_cpp_helpers.py index 5b6eed156f..52424a7cb2 100644 --- a/tests/unit_tests/test_cpp_helpers.py +++ b/tests/unit_tests/test_cpp_helpers.py @@ -1,8 +1,10 @@ +import logging from unittest.mock import Mock import pytest from esphome import const, cpp_helpers as ch +from esphome.cpp_helpers import ComponentSourcePool, register_component_source @pytest.mark.asyncio @@ -23,7 +25,7 @@ async def test_register_component(monkeypatch): app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) - core_mock = Mock(component_ids=["foo.bar"]) + core_mock = Mock(component_ids=["foo.bar"], data={}) monkeypatch.setattr(ch, "CORE", core_mock) add_mock = Mock() @@ -59,7 +61,7 @@ async def test_register_component__with_setup_priority(monkeypatch): app_mock = Mock(register_component_=Mock(return_value=var)) monkeypatch.setattr(ch, "App", app_mock) - core_mock = Mock(component_ids=["foo.bar"]) + core_mock = Mock(component_ids=["foo.bar"], data={}) monkeypatch.setattr(ch, "CORE", core_mock) add_mock = Mock() @@ -78,3 +80,69 @@ async def test_register_component__with_setup_priority(monkeypatch): assert add_mock.call_count == 4 app_mock.register_component_.assert_called_with(var) assert core_mock.component_ids == [] + + +def test_register_component_source_empty_name(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr(ch, "CORE", Mock(data={})) + assert register_component_source("") == 0 + + +def test_register_component_source_deduplicates( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setattr(ch, "CORE", Mock(data={})) + idx1 = register_component_source("wifi") + idx2 = register_component_source("api") + idx3 = register_component_source("wifi") + assert idx1 == 1 + assert idx2 == 2 + assert idx3 == 1 # deduplicated + + +def test_generate_source_table_code_empty() -> None: + from esphome.cpp_helpers import _generate_source_table_code + + assert _generate_source_table_code("TBL", "lookup", {}) == "" + + +def test_generate_source_table_code_non_empty() -> None: + from esphome.cpp_helpers import _generate_source_table_code + + code = _generate_source_table_code("TBL", "lookup", {"wifi": 1, "api": 2}) + assert "PROGMEM" in code + assert "wifi" in code + assert "api" in code + assert "lookup" in code + assert "index == 0" in code + assert "progmem_read_ptr" in code + assert "index > 2" in code + + +@pytest.mark.asyncio +async def test_generate_component_source_table_empty_pool( + monkeypatch: pytest.MonkeyPatch, +) -> None: + """Test that _generate_component_source_table does nothing with an empty pool.""" + from esphome.cpp_helpers import _generate_component_source_table + + monkeypatch.setattr(ch, "CORE", Mock(data={})) + add_global_mock = Mock() + monkeypatch.setattr(ch, "add_global", add_global_mock) + await _generate_component_source_table() + add_global_mock.assert_not_called() + + +def test_register_component_source_overflow_warns( + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture +) -> None: + # Pre-fill pool to max + pool = ComponentSourcePool( + sources={f"comp_{i}": i + 1 for i in range(0xFF)}, + table_registered=True, + ) + monkeypatch.setattr(ch, "CORE", Mock(data={ch._COMPONENT_SOURCE_DOMAIN: pool})) + with caplog.at_level(logging.WARNING): + idx = register_component_source("overflow_component") + assert idx == 0 + assert "Too many unique component source names" in caplog.text + assert "overflow_component" in caplog.text From d6475eaeed764bb30589323f832cf305d94bd69f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 12:15:18 -1000 Subject: [PATCH 1797/2030] [binary_sensor] Remove redundant `optional<bool>` state_, save 8 bytes per instance (#15095) --- .../binary_sensor/binary_sensor.cpp | 7 -- .../components/binary_sensor/binary_sensor.h | 21 +++-- esphome/core/entity_base.h | 88 +++++++++++++------ 3 files changed, 77 insertions(+), 39 deletions(-) diff --git a/esphome/components/binary_sensor/binary_sensor.cpp b/esphome/components/binary_sensor/binary_sensor.cpp index 8ace7eafd1..7596975a68 100644 --- a/esphome/components/binary_sensor/binary_sensor.cpp +++ b/esphome/components/binary_sensor/binary_sensor.cpp @@ -32,13 +32,6 @@ void BinarySensor::publish_initial_state(bool new_state) { this->invalidate_state(); this->publish_state(new_state); } -void BinarySensor::send_state_internal(bool new_state) { - // copy the new state to the visible property for backwards compatibility, before any callbacks - this->state = new_state; - // Note that set_new_state_ de-dups and will only trigger callbacks if the state has actually changed - this->set_new_state(new_state); -} - bool BinarySensor::set_new_state(const optional<bool> &new_state) { if (StatefulEntityBase::set_new_state(new_state)) { // weirdly, this file could be compiled even without USE_BINARY_SENSOR defined diff --git a/esphome/components/binary_sensor/binary_sensor.h b/esphome/components/binary_sensor/binary_sensor.h index 6ae5d04bcb..28c156763a 100644 --- a/esphome/components/binary_sensor/binary_sensor.h +++ b/esphome/components/binary_sensor/binary_sensor.h @@ -32,7 +32,10 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi */ class BinarySensor : public StatefulEntityBase<bool> { public: - explicit BinarySensor(){}; + explicit BinarySensor() = default; + + const bool &get_state() const override { return this->state; } + void set_trigger_on_initial_state(bool value) { this->trigger_on_initial_state_ = value; } /** Publish a new state to the front-end. * @@ -54,16 +57,24 @@ class BinarySensor : public StatefulEntityBase<bool> { // ========== INTERNAL METHODS ========== // (In most use cases you won't need these) - void send_state_internal(bool new_state); + void send_state_internal(bool new_state) { + // Fast path: skip virtual dispatch when state hasn't changed + if (this->flags_.has_state && this->state == new_state) + return; + this->set_new_state(new_state); + } /// Return whether this binary sensor has outputted a state. virtual bool is_status_binary_sensor() const; - // For backward compatibility, provide an accessible property - + /// The current state of this binary sensor. Also used as the backing storage for StatefulEntityBase. bool state{}; protected: + bool get_trigger_on_initial_state() const override { return this->trigger_on_initial_state_; } + void set_state_value(const bool &value) override { this->state = value; } + + bool trigger_on_initial_state_{true}; #ifdef USE_BINARY_SENSOR_FILTER Filter *filter_list_{nullptr}; #endif @@ -73,7 +84,7 @@ class BinarySensor : public StatefulEntityBase<bool> { class BinarySensorInitiallyOff : public BinarySensor { public: - bool has_state() const override { return true; } + BinarySensorInitiallyOff() { this->set_has_state(true); } }; } // namespace esphome::binary_sensor diff --git a/esphome/core/entity_base.h b/esphome/core/entity_base.h index 8c1f1a213e..5a69c9dd09 100644 --- a/esphome/core/entity_base.h +++ b/esphome/core/entity_base.h @@ -296,15 +296,36 @@ void log_entity_device_class(const char *tag, const char *prefix, const EntityBa #define LOG_ENTITY_UNIT_OF_MEASUREMENT(tag, prefix, obj) log_entity_unit_of_measurement(tag, prefix, obj) void log_entity_unit_of_measurement(const char *tag, const char *prefix, const EntityBase &obj); -/** - * An entity that has a state. - * @tparam T The type of the state +/** Base class for entities that track a typed state value with change-detection and callbacks. + * + * This class does not store the state value — subclasses own their storage. Whether a state + * has been set is tracked by EntityBase::has_state(). + * + * Subclasses must implement: + * - get_state(): return a const reference to the current value + * - set_state_value(): store a new value (called only when the state actually changes) + * - get_trigger_on_initial_state(): return whether callbacks should fire on the first state + * + * Subclasses may override set_new_state() to add behavior (logging, notifications) after calling + * the base implementation. Since set_new_state() is virtual, callers like invalidate_state() + * dispatch through the vtable to the subclass override in the .cpp, avoiding template code + * bloat at inline call sites. Subclasses may also add a fast-path dedup check before calling + * set_new_state() to skip virtual dispatch entirely when the state hasn't changed. + * + * Callback behavior: + * - full_state_callbacks_: fired on every change, receives optional<T> previous and current + * - state_callbacks_: fired only when the new state has a value, and either this is not the + * first state (had_state) or trigger_on_initial_state is set + * + * @tparam T The type of the state value */ template<typename T> class StatefulEntityBase : public EntityBase { public: - virtual bool has_state() const { return this->state_.has_value(); } - virtual const T &get_state() const { return this->state_.value(); } // NOLINT(bugprone-unchecked-optional-access) - virtual T get_state_default(T default_value) const { return this->state_.value_or(default_value); } + /// Return the current state value. Only valid when has_state() is true. + virtual const T &get_state() const = 0; + /// Return the current state if available, otherwise return the provided default. + T get_state_default(T default_value) const { return this->has_state() ? this->get_state() : default_value; } + /// Clear the state — sets has_state() to false and fires callbacks with nullopt. void invalidate_state() { this->set_new_state({}); } template<typename F> void add_full_state_callback(F &&callback) { @@ -314,33 +335,46 @@ template<typename T> class StatefulEntityBase : public EntityBase { this->state_callbacks_.add(std::forward<F>(callback)); } - void set_trigger_on_initial_state(bool trigger_on_initial_state) { - this->trigger_on_initial_state_ = trigger_on_initial_state; - } - protected: - optional<T> state_{}; - /** - * Set a new state for this entity. This will trigger callbacks only if the new state is different from the previous. + /// Subclasses return whether callbacks should fire on the very first state. + virtual bool get_trigger_on_initial_state() const = 0; + + /** Apply a new state, de-duplicating and firing callbacks as needed. * - * @param new_state The new state. - * @return True if the state was changed, false if it was the same as before. + * Pass nullopt to invalidate (clear) the state. Pass a value to set it. + * Returns true if the state actually changed, false if it was the same. + * Subclasses may override to add logging/notifications after calling the base. */ virtual bool set_new_state(const optional<T> &new_state) { - if (this->state_ != new_state) { - // call the full state callbacks with the previous and new state - this->full_state_callbacks_.call(this->state_, new_state); - // trigger legacy callbacks only if the new state is valid and either the trigger on initial state is enabled or - // the previous state was valid - auto had_state = this->has_state(); - this->state_ = new_state; - if (new_state.has_value() && (this->trigger_on_initial_state_ || had_state)) - this->state_callbacks_.call(new_state.value()); - return true; + // Access flags_ directly to avoid function call overhead in this hot path + bool had_state = this->flags_.has_state; + // Use pointer to avoid requiring T to be default-constructible + const T *current = had_state ? &this->get_state() : nullptr; + if (new_state.has_value()) { + if (current != nullptr && *current == new_state.value()) + return false; // same value, no change + } else if (!had_state) { + return false; // already invalidated, no change } - return false; + // Capture old_state before set_state_value — current pointer aliases subclass storage + bool has_full_cbs = !this->full_state_callbacks_.empty(); + optional<T> old_state; + if (has_full_cbs) + old_state = current != nullptr ? optional<T>(*current) : nullopt; + // Update storage before firing callbacks so callback code can inspect current state + this->flags_.has_state = new_state.has_value(); + if (new_state.has_value()) { + this->set_state_value(new_state.value()); + } + if (has_full_cbs) + this->full_state_callbacks_.call(old_state, new_state); + // had_state first: on every change except the first, skips the virtual call + if (new_state.has_value() && (had_state || this->get_trigger_on_initial_state())) + this->state_callbacks_.call(new_state.value()); + return true; } - bool trigger_on_initial_state_{true}; + /// Subclasses implement this to store the actual value into their own storage. + virtual void set_state_value(const T &value) = 0; LazyCallbackManager<void(optional<T> previous, optional<T> current)> full_state_callbacks_; LazyCallbackManager<void(T)> state_callbacks_; }; From 3520ef74809b0d6f1c6e9d3abd067c36536ce9a9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 12:38:04 -1000 Subject: [PATCH 1798/2030] [text_sensor] Use std::array in MapFilter (#15269) --- esphome/components/text_sensor/__init__.py | 2 +- esphome/components/text_sensor/filter.cpp | 14 ++++++-------- esphome/components/text_sensor/filter.h | 17 +++++++++++++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 51eedf9a95..78a7a3a41b 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -129,7 +129,7 @@ async def map_filter_to_code(config, filter_id): ) for conf in config ] - return cg.new_Pvariable(filter_id, mappings) + return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(mappings)), mappings) validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") diff --git a/esphome/components/text_sensor/filter.cpp b/esphome/components/text_sensor/filter.cpp index f7c6a695fb..bc044f3a73 100644 --- a/esphome/components/text_sensor/filter.cpp +++ b/esphome/components/text_sensor/filter.cpp @@ -93,17 +93,15 @@ bool SubstituteFilter::new_value(std::string &value) { return true; } -// Map -MapFilter::MapFilter(const std::initializer_list<Substitution> &mappings) : mappings_(mappings) {} - -bool MapFilter::new_value(std::string &value) { - for (const auto &mapping : this->mappings_) { - if (value == mapping.from) { - value.assign(mapping.to); +// Map — non-template helper +bool map_filter_apply(const Substitution *mappings, size_t count, std::string &value) { + for (size_t i = 0; i < count; i++) { + if (value == mappings[i].from) { + value.assign(mappings[i].to); return true; } } - return true; // Pass through if no match + return true; } } // namespace esphome::text_sensor diff --git a/esphome/components/text_sensor/filter.h b/esphome/components/text_sensor/filter.h index 8a8bc55c8e..07832af9e2 100644 --- a/esphome/components/text_sensor/filter.h +++ b/esphome/components/text_sensor/filter.h @@ -3,6 +3,8 @@ #include "esphome/core/defines.h" #ifdef USE_TEXT_SENSOR_FILTER +#include <array> + #include "esphome/core/component.h" #include "esphome/core/helpers.h" @@ -131,6 +133,9 @@ class SubstituteFilter : public Filter { FixedVector<Substitution> substitutions_; }; +/// Non-template helper (implementation in filter.cpp) +bool map_filter_apply(const Substitution *mappings, size_t count, std::string &value); + /** A filter that maps values from one set to another * * Uses linear search instead of std::map for typical small datasets (2-20 mappings). @@ -154,14 +159,18 @@ class SubstituteFilter : public Filter { * - Faster for typical ESPHome usage (2-10 mappings common, 20+ rare) * * Break-even point: ~35-40 mappings, but ESPHome configs rarely exceed 20 + * + * N is set by code generation to match the exact number of mappings configured in YAML. */ -class MapFilter : public Filter { +template<size_t N> class MapFilter : public Filter { public: - explicit MapFilter(const std::initializer_list<Substitution> &mappings); - bool new_value(std::string &value) override; + explicit MapFilter(const std::initializer_list<Substitution> &mappings) { + init_array_from(this->mappings_, mappings); + } + bool new_value(std::string &value) override { return map_filter_apply(this->mappings_.data(), N, value); } protected: - FixedVector<Substitution> mappings_; + std::array<Substitution, N> mappings_{}; }; } // namespace esphome::text_sensor From 29419d9d97557af72cc75d351b80797e9cefe83d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 13:36:08 -1000 Subject: [PATCH 1799/2030] [automation] Use std::array in And/Or/Xor conditions (#15282) --- esphome/automation.py | 20 +++++++++++++++----- esphome/core/base_automation.h | 25 ++++++++++++++++--------- esphome/core/helpers.h | 3 ++- 3 files changed, 33 insertions(+), 15 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index 7b1d6ceca1..94d64086ec 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -250,7 +250,9 @@ async def and_condition_to_code( args: TemplateArgsType, ) -> MockObj: conditions = await build_condition_list(config, template_arg, args) - return cg.new_Pvariable(condition_id, template_arg, conditions) + return cg.new_Pvariable( + condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions + ) @register_condition("or", OrCondition, validate_condition_list) @@ -261,7 +263,9 @@ async def or_condition_to_code( args: TemplateArgsType, ) -> MockObj: conditions = await build_condition_list(config, template_arg, args) - return cg.new_Pvariable(condition_id, template_arg, conditions) + return cg.new_Pvariable( + condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions + ) @register_condition("all", AndCondition, validate_condition_list) @@ -272,7 +276,9 @@ async def all_condition_to_code( args: TemplateArgsType, ) -> MockObj: conditions = await build_condition_list(config, template_arg, args) - return cg.new_Pvariable(condition_id, template_arg, conditions) + return cg.new_Pvariable( + condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions + ) @register_condition("any", OrCondition, validate_condition_list) @@ -283,7 +289,9 @@ async def any_condition_to_code( args: TemplateArgsType, ) -> MockObj: conditions = await build_condition_list(config, template_arg, args) - return cg.new_Pvariable(condition_id, template_arg, conditions) + return cg.new_Pvariable( + condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions + ) @register_condition("not", NotCondition, validate_potentially_and_condition) @@ -305,7 +313,9 @@ async def xor_condition_to_code( args: TemplateArgsType, ) -> MockObj: conditions = await build_condition_list(config, template_arg, args) - return cg.new_Pvariable(condition_id, template_arg, conditions) + return cg.new_Pvariable( + condition_id, cg.TemplateArguments(len(conditions), *template_arg), conditions + ) @register_condition("lambda", LambdaCondition, cv.returning_lambda) diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index efcffa8824..11133d3973 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -9,14 +9,17 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" +#include <array> #include <list> #include <vector> namespace esphome { -template<typename... Ts> class AndCondition : public Condition<Ts...> { +template<size_t N, typename... Ts> class AndCondition : public Condition<Ts...> { public: - explicit AndCondition(std::initializer_list<Condition<Ts...> *> conditions) : conditions_(conditions) {} + explicit AndCondition(std::initializer_list<Condition<Ts...> *> conditions) { + init_array_from(this->conditions_, conditions); + } bool check(const Ts &...x) override { for (auto *condition : this->conditions_) { if (!condition->check(x...)) @@ -27,12 +30,14 @@ template<typename... Ts> class AndCondition : public Condition<Ts...> { } protected: - FixedVector<Condition<Ts...> *> conditions_; + std::array<Condition<Ts...> *, N> conditions_{}; }; -template<typename... Ts> class OrCondition : public Condition<Ts...> { +template<size_t N, typename... Ts> class OrCondition : public Condition<Ts...> { public: - explicit OrCondition(std::initializer_list<Condition<Ts...> *> conditions) : conditions_(conditions) {} + explicit OrCondition(std::initializer_list<Condition<Ts...> *> conditions) { + init_array_from(this->conditions_, conditions); + } bool check(const Ts &...x) override { for (auto *condition : this->conditions_) { if (condition->check(x...)) @@ -43,7 +48,7 @@ template<typename... Ts> class OrCondition : public Condition<Ts...> { } protected: - FixedVector<Condition<Ts...> *> conditions_; + std::array<Condition<Ts...> *, N> conditions_{}; }; template<typename... Ts> class NotCondition : public Condition<Ts...> { @@ -55,9 +60,11 @@ template<typename... Ts> class NotCondition : public Condition<Ts...> { Condition<Ts...> *condition_; }; -template<typename... Ts> class XorCondition : public Condition<Ts...> { +template<size_t N, typename... Ts> class XorCondition : public Condition<Ts...> { public: - explicit XorCondition(std::initializer_list<Condition<Ts...> *> conditions) : conditions_(conditions) {} + explicit XorCondition(std::initializer_list<Condition<Ts...> *> conditions) { + init_array_from(this->conditions_, conditions); + } bool check(const Ts &...x) override { size_t result = 0; for (auto *condition : this->conditions_) { @@ -68,7 +75,7 @@ template<typename... Ts> class XorCondition : public Condition<Ts...> { } protected: - FixedVector<Condition<Ts...> *> conditions_; + std::array<Condition<Ts...> *, N> conditions_{}; }; template<typename... Ts> class LambdaCondition : public Condition<Ts...> { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 913614f564..66ba166445 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -500,7 +500,8 @@ template<typename T, size_t MAX_CAPACITY = std::numeric_limits<uint16_t>::max()> /// Initialize a std::array from an initializer_list. Uses memcpy for trivially copyable types (optimal codegen), /// falls back to element-wise copy for non-trivially copyable types (e.g. TemplatableValue). -/// N is set by code generation; assert catches mismatches in debug/integration tests. +/// N is always set by code generation — the caller is responsible for ensuring src.size() == N. +/// The debug assert is a safety net for development, not a runtime check. template<typename T, size_t N> inline void init_array_from(std::array<T, N> &dest, std::initializer_list<T> src) { #ifdef ESPHOME_DEBUG assert(src.size() == N); From 4da7f5ecc2e82e185c0dea21bf7f40caa1a88148 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 13:50:46 -1000 Subject: [PATCH 1800/2030] [binary_sensor] Use std::array in AutorepeatFilter (#15268) --- esphome/components/binary_sensor/__init__.py | 3 +- esphome/components/binary_sensor/filter.cpp | 27 ++++++------------ esphome/components/binary_sensor/filter.h | 29 ++++++++++++++++---- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 4705f1675d..8d072904b0 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -255,6 +255,7 @@ async def delayed_off_filter_to_code(config, filter_id): ): cv.positive_time_period_milliseconds, } ), + cv.Length(max=254), ), ) async def autorepeat_filter_to_code(config, filter_id): @@ -283,7 +284,7 @@ async def autorepeat_filter_to_code(config, filter_id): ), ) ] - var = cg.new_Pvariable(filter_id, timings) + var = cg.new_Pvariable(filter_id, cg.TemplateArguments(len(timings)), timings) await cg.register_component(var, {}) return var diff --git a/esphome/components/binary_sensor/filter.cpp b/esphome/components/binary_sensor/filter.cpp index 5d525e967d..914060ce13 100644 --- a/esphome/components/binary_sensor/filter.cpp +++ b/esphome/components/binary_sensor/filter.cpp @@ -76,14 +76,11 @@ float DelayedOffFilter::get_setup_priority() const { return setup_priority::HARD optional<bool> InvertFilter::new_value(bool value) { return !value; } -AutorepeatFilter::AutorepeatFilter(std::initializer_list<AutorepeatFilterTiming> timings) : timings_(timings) {} - -optional<bool> AutorepeatFilter::new_value(bool value) { +// AutorepeatFilterBase +optional<bool> AutorepeatFilterBase::new_value(bool value) { if (value) { - // Ignore if already running if (this->active_timing_ != 0) return {}; - this->next_timing_(); return true; } else { @@ -94,34 +91,26 @@ optional<bool> AutorepeatFilter::new_value(bool value) { } } -void AutorepeatFilter::next_timing_() { - // Entering this method - // 1st time: starts waiting the first delay - // 2nd time: starts waiting the second delay and starts toggling with the first time_off / _on - // last time: no delay to start but have to bump the index to reflect the last - if (this->active_timing_ < this->timings_.size()) { +void AutorepeatFilterBase::next_timing_() { + if (this->active_timing_ < this->timings_count_) { this->set_timeout(AUTOREPEAT_TIMING_ID, this->timings_[this->active_timing_].delay, [this]() { this->next_timing_(); }); } - - if (this->active_timing_ <= this->timings_.size()) { + if (this->active_timing_ <= this->timings_count_) { this->active_timing_++; } - if (this->active_timing_ == 2) this->next_value_(false); - - // Leaving this method: if the toggling is started, it has to use [active_timing_ - 2] for the intervals } -void AutorepeatFilter::next_value_(bool val) { +void AutorepeatFilterBase::next_value_(bool val) { const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2]; - this->output(val); // This is at least the second one so not initial + this->output(val); this->set_timeout(AUTOREPEAT_ON_OFF_ID, val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); }); } -float AutorepeatFilter::get_setup_priority() const { return setup_priority::HARDWARE; } +float AutorepeatFilterBase::get_setup_priority() const { return setup_priority::HARDWARE; } LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {} diff --git a/esphome/components/binary_sensor/filter.h b/esphome/components/binary_sensor/filter.h index 0813847ca2..37c6bf0092 100644 --- a/esphome/components/binary_sensor/filter.h +++ b/esphome/components/binary_sensor/filter.h @@ -3,6 +3,8 @@ #include "esphome/core/defines.h" #ifdef USE_BINARY_SENSOR_FILTER +#include <array> + #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" @@ -86,22 +88,39 @@ struct AutorepeatFilterTiming { uint32_t time_on; }; -class AutorepeatFilter : public Filter, public Component { +/// Non-template base for AutorepeatFilter — all methods in filter.cpp. +/// Lambdas capture this base pointer, so set_timeout/cancel_timeout are instantiated once. +class AutorepeatFilterBase : public Filter, public Component { public: - explicit AutorepeatFilter(std::initializer_list<AutorepeatFilterTiming> timings); - optional<bool> new_value(bool value) override; - float get_setup_priority() const override; + AutorepeatFilterBase(const AutorepeatFilterBase &) = delete; + AutorepeatFilterBase &operator=(const AutorepeatFilterBase &) = delete; protected: + AutorepeatFilterBase() = default; void next_timing_(); void next_value_(bool val); - FixedVector<AutorepeatFilterTiming> timings_; + const AutorepeatFilterTiming *timings_{nullptr}; + uint8_t timings_count_{0}; uint8_t active_timing_{0}; }; +/// Template wrapper that provides inline std::array storage for timings. +/// N is set by code generation to match the exact number of timings configured in YAML. +template<size_t N> class AutorepeatFilter : public AutorepeatFilterBase { + public: + explicit AutorepeatFilter(std::initializer_list<AutorepeatFilterTiming> timings) { + init_array_from(this->timings_storage_, timings); + this->timings_ = this->timings_storage_.data(); + this->timings_count_ = N; + } + + protected: + std::array<AutorepeatFilterTiming, N> timings_storage_{}; +}; + class LambdaFilter : public Filter { public: explicit LambdaFilter(std::function<optional<bool>(bool)> f); From 66754fa376b8495885c7718acacaf66b0872f7f0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 14:24:32 -1000 Subject: [PATCH 1801/2030] [text_sensor] Use std::array in SubstituteFilter (#15266) --- esphome/components/text_sensor/__init__.py | 4 +++- esphome/components/text_sensor/filter.cpp | 20 +++++++------------- esphome/components/text_sensor/filter.h | 16 +++++++++++----- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 78a7a3a41b..5b07dd2915 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -116,7 +116,9 @@ async def substitute_filter_to_code(config, filter_id): ) for conf in config ] - return cg.new_Pvariable(filter_id, substitutions) + return cg.new_Pvariable( + filter_id, cg.TemplateArguments(len(substitutions)), substitutions + ) @FILTER_REGISTRY.register("map", MapFilter, cv.ensure_list(validate_mapping)) diff --git a/esphome/components/text_sensor/filter.cpp b/esphome/components/text_sensor/filter.cpp index bc044f3a73..d4e6b5b9bb 100644 --- a/esphome/components/text_sensor/filter.cpp +++ b/esphome/components/text_sensor/filter.cpp @@ -73,20 +73,14 @@ bool PrependFilter::new_value(std::string &value) { return true; } -// Substitute -SubstituteFilter::SubstituteFilter(const std::initializer_list<Substitution> &substitutions) - : substitutions_(substitutions) {} - -bool SubstituteFilter::new_value(std::string &value) { - for (const auto &sub : this->substitutions_) { - // Compute lengths once per substitution (strlen is fast, called infrequently) - const size_t from_len = strlen(sub.from); - const size_t to_len = strlen(sub.to); +// Substitute — non-template helper +bool substitute_filter_apply(const Substitution *substitutions, size_t count, std::string &value) { + for (size_t i = 0; i < count; i++) { + const size_t from_len = strlen(substitutions[i].from); + const size_t to_len = strlen(substitutions[i].to); std::size_t pos = 0; - while ((pos = value.find(sub.from, pos, from_len)) != std::string::npos) { - value.replace(pos, from_len, sub.to, to_len); - // Advance past the replacement to avoid infinite loop when - // the replacement contains the search pattern (e.g., f -> foo) + while ((pos = value.find(substitutions[i].from, pos, from_len)) != std::string::npos) { + value.replace(pos, from_len, substitutions[i].to, to_len); pos += to_len; } } diff --git a/esphome/components/text_sensor/filter.h b/esphome/components/text_sensor/filter.h index 07832af9e2..6db76dcb64 100644 --- a/esphome/components/text_sensor/filter.h +++ b/esphome/components/text_sensor/filter.h @@ -123,14 +123,20 @@ struct Substitution { const char *to; }; -/// A simple filter that replaces a substring with another substring -class SubstituteFilter : public Filter { +/// Non-template helper (implementation in filter.cpp) +bool substitute_filter_apply(const Substitution *substitutions, size_t count, std::string &value); + +/// A simple filter that replaces a substring with another substring. +/// N is set by code generation to match the exact number of substitutions configured in YAML. +template<size_t N> class SubstituteFilter : public Filter { public: - explicit SubstituteFilter(const std::initializer_list<Substitution> &substitutions); - bool new_value(std::string &value) override; + explicit SubstituteFilter(const std::initializer_list<Substitution> &substitutions) { + init_array_from(this->substitutions_, substitutions); + } + bool new_value(std::string &value) override { return substitute_filter_apply(this->substitutions_.data(), N, value); } protected: - FixedVector<Substitution> substitutions_; + std::array<Substitution, N> substitutions_{}; }; /// Non-template helper (implementation in filter.cpp) From 508ec295a4d9b8b920b27ce4d3cee6818997c39d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 14:55:46 -1000 Subject: [PATCH 1802/2030] [sensor] Use std::array in OrFilter (#15262) --- esphome/components/sensor/__init__.py | 2 +- esphome/components/sensor/filter.cpp | 30 ++++++++----------------- esphome/components/sensor/filter.h | 32 ++++++++++++++++++++------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 5569567de1..8bbaa73e2e 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -620,7 +620,7 @@ async def delta_filter_to_code(config, filter_id): @FILTER_REGISTRY.register("or", OrFilter, validate_filters) async def or_filter_to_code(config, filter_id): filters = await build_filters(config) - return cg.new_Pvariable(filter_id, filters) + return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(filters)), filters) @FILTER_REGISTRY.register( diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 66a9e9555b..dad09ff021 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -295,32 +295,20 @@ optional<float> DeltaFilter::new_value(float value) { return {}; } -// OrFilter -OrFilter::OrFilter(std::initializer_list<Filter *> filters) : filters_(filters), phi_(this) {} -OrFilter::PhiNode::PhiNode(OrFilter *or_parent) : or_parent_(or_parent) {} - -optional<float> OrFilter::PhiNode::new_value(float value) { - if (!this->or_parent_->has_value_) { - this->or_parent_->output(value); - this->or_parent_->has_value_ = true; +// OrFilter helpers +void or_filter_initialize(Filter **filters, size_t count, Sensor *parent, Filter *phi) { + for (size_t i = 0; i < count; i++) { + filters[i]->initialize(parent, phi); } - - return {}; + phi->initialize(parent, nullptr); } -optional<float> OrFilter::new_value(float value) { - this->has_value_ = false; - for (auto *filter : this->filters_) - filter->input(value); +optional<float> or_filter_new_value(Filter **filters, size_t count, float value, bool &has_value) { + has_value = false; + for (size_t i = 0; i < count; i++) + filters[i]->input(value); return {}; } -void OrFilter::initialize(Sensor *parent, Filter *next) { - Filter::initialize(parent, next); - for (auto *filter : this->filters_) { - filter->initialize(parent, &this->phi_); - } - this->phi_.initialize(parent, nullptr); -} // TimeoutFilterBase - shared loop logic void TimeoutFilterBase::loop() { diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 80fa14742c..deaaa27f19 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -489,26 +489,42 @@ class DeltaFilter : public Filter { float last_value_{NAN}; }; -class OrFilter : public Filter { +/// Non-template helpers for OrFilter (implementation in filter.cpp) +void or_filter_initialize(Filter **filters, size_t count, Sensor *parent, Filter *phi); +optional<float> or_filter_new_value(Filter **filters, size_t count, float value, bool &has_value); + +/// N is set by code generation to match the exact number of filters configured in YAML. +template<size_t N> class OrFilter : public Filter { public: - explicit OrFilter(std::initializer_list<Filter *> filters); + explicit OrFilter(std::initializer_list<Filter *> filters) { init_array_from(this->filters_, filters); } - void initialize(Sensor *parent, Filter *next) override; + void initialize(Sensor *parent, Filter *next) override { + Filter::initialize(parent, next); + or_filter_initialize(this->filters_.data(), N, parent, &this->phi_); + } - optional<float> new_value(float value) override; + optional<float> new_value(float value) override { + return or_filter_new_value(this->filters_.data(), N, value, this->has_value_); + } protected: class PhiNode : public Filter { public: - PhiNode(OrFilter *or_parent); - optional<float> new_value(float value) override; + PhiNode(OrFilter *or_parent) : or_parent_(or_parent) {} + optional<float> new_value(float value) override { + if (!this->or_parent_->has_value_) { + this->or_parent_->output(value); + this->or_parent_->has_value_ = true; + } + return {}; + } protected: OrFilter *or_parent_; }; - FixedVector<Filter *> filters_; - PhiNode phi_; + std::array<Filter *, N> filters_{}; + PhiNode phi_{this}; bool has_value_{false}; }; From d51b047f6381c407cb8c879a96d73c4b5c36f528 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 14:56:04 -1000 Subject: [PATCH 1803/2030] [sensor] Use std::array in CalibratePolynomialFilter (#15264) --- esphome/components/sensor/__init__.py | 2 +- esphome/components/sensor/filter.cpp | 9 +++------ esphome/components/sensor/filter.h | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 8bbaa73e2e..8abba17ff9 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -808,7 +808,7 @@ async def calibrate_polynomial_filter_to_code(config, filter_id): # Column vector b = [[v] for v in y] res = [v[0] for v in _lstsq(a, b)] - return cg.new_Pvariable(filter_id, res) + return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(res)), res) def validate_clamp(config): diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index dad09ff021..7b7a968f48 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -396,14 +396,11 @@ optional<float> CalibrateLinearFilter::new_value(float value) { return NAN; } -CalibratePolynomialFilter::CalibratePolynomialFilter(std::initializer_list<float> coefficients) - : coefficients_(coefficients) {} - -optional<float> CalibratePolynomialFilter::new_value(float value) { +optional<float> calibrate_polynomial_compute(const float *coefficients, size_t count, float value) { float res = 0.0f; float x = 1.0f; - for (const auto &coefficient : this->coefficients_) { - res += x * coefficient; + for (size_t i = 0; i < count; i++) { + res += x * coefficients[i]; x *= value; } return res; diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index deaaa27f19..26a03acde5 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -537,13 +537,21 @@ class CalibrateLinearFilter : public Filter { FixedVector<std::array<float, 3>> linear_functions_; }; -class CalibratePolynomialFilter : public Filter { +/// Non-template helper for polynomial calibration (implementation in filter.cpp) +optional<float> calibrate_polynomial_compute(const float *coefficients, size_t count, float value); + +/// N is set by code generation to match the exact number of polynomial coefficients. +template<size_t N> class CalibratePolynomialFilter : public Filter { public: - explicit CalibratePolynomialFilter(std::initializer_list<float> coefficients); - optional<float> new_value(float value) override; + explicit CalibratePolynomialFilter(std::initializer_list<float> coefficients) { + init_array_from(this->coefficients_, coefficients); + } + optional<float> new_value(float value) override { + return calibrate_polynomial_compute(this->coefficients_.data(), N, value); + } protected: - FixedVector<float> coefficients_; + std::array<float, N> coefficients_{}; }; class ClampFilter : public Filter { From 17afbeb87b32c8b30a983c5926060d09ed78846d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 14:57:15 -1000 Subject: [PATCH 1804/2030] [binary_sensor] Use std::array in MultiClickTrigger (#15267) --- esphome/components/binary_sensor/__init__.py | 13 ++++++--- .../components/binary_sensor/automation.cpp | 18 ++++++------- esphome/components/binary_sensor/automation.h | 27 ++++++++++++++++--- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 8d072904b0..660f75ccd9 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -124,9 +124,10 @@ ClickTrigger = binary_sensor_ns.class_("ClickTrigger", automation.Trigger.templa DoubleClickTrigger = binary_sensor_ns.class_( "DoubleClickTrigger", automation.Trigger.template() ) -MultiClickTrigger = binary_sensor_ns.class_( - "MultiClickTrigger", automation.Trigger.template(), cg.Component +MultiClickTriggerBase = binary_sensor_ns.class_( + "MultiClickTriggerBase", automation.Trigger.template(), cg.Component ) +MultiClickTrigger = binary_sensor_ns.class_("MultiClickTrigger", MultiClickTriggerBase) MultiClickTriggerEvent = binary_sensor_ns.struct("MultiClickTriggerEvent") BinarySensorPublishAction = binary_sensor_ns.class_( @@ -484,7 +485,9 @@ _BINARY_SENSOR_SCHEMA = ( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), cv.Required(CONF_TIMING): cv.All( - [parse_multi_click_timing_str], validate_multi_click_timing + [parse_multi_click_timing_str], + validate_multi_click_timing, + cv.Length(min=1, max=255), ), cv.Optional( CONF_INVALID_COOLDOWN, default="1s" @@ -561,7 +564,9 @@ async def _build_binary_sensor_automations(var, config): ) for tim in conf[CONF_TIMING] ] - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var, timings) + trigger = cg.new_Pvariable( + conf[CONF_TRIGGER_ID], cg.TemplateArguments(len(timings)), var, timings + ) if CONF_INVALID_COOLDOWN in conf: cg.add(trigger.set_invalid_cooldown(conf[CONF_INVALID_COOLDOWN])) await cg.register_component(trigger, conf) diff --git a/esphome/components/binary_sensor/automation.cpp b/esphome/components/binary_sensor/automation.cpp index 7e43d42357..eb68abce3b 100644 --- a/esphome/components/binary_sensor/automation.cpp +++ b/esphome/components/binary_sensor/automation.cpp @@ -13,7 +13,7 @@ constexpr uint32_t MULTICLICK_COOLDOWN_ID = 1; constexpr uint32_t MULTICLICK_IS_VALID_ID = 2; constexpr uint32_t MULTICLICK_IS_NOT_VALID_ID = 3; -void MultiClickTrigger::on_state_(bool state) { +void MultiClickTriggerBase::on_state_(bool state) { // Handle duplicate events if (state == this->last_state_) { return; @@ -32,7 +32,7 @@ void MultiClickTrigger::on_state_(bool state) { ESP_LOGV(TAG, "START min=%" PRIu32 " max=%" PRIu32, evt.min_length, evt.max_length); ESP_LOGV(TAG, "Multi Click: Starting multi click action!"); this->at_index_ = 1; - if (this->timing_.size() == 1 && evt.max_length == 4294967294UL) { + if (this->timing_count_ == 1 && evt.max_length == 4294967294UL) { this->set_timeout(MULTICLICK_TRIGGER_ID, evt.min_length, [this]() { this->trigger_(); }); } else { this->schedule_is_valid_(evt.min_length); @@ -50,7 +50,7 @@ void MultiClickTrigger::on_state_(bool state) { return; } - if (*this->at_index_ == this->timing_.size()) { + if (*this->at_index_ == this->timing_count_) { this->trigger_(); return; } @@ -61,7 +61,7 @@ void MultiClickTrigger::on_state_(bool state) { ESP_LOGV(TAG, "A i=%zu min=%" PRIu32 " max=%" PRIu32, *this->at_index_, evt.min_length, evt.max_length); // NOLINT this->schedule_is_valid_(evt.min_length); this->schedule_is_not_valid_(evt.max_length); - } else if (*this->at_index_ + 1 != this->timing_.size()) { + } else if (*this->at_index_ + 1 != this->timing_count_) { ESP_LOGV(TAG, "B i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); this->schedule_is_valid_(evt.min_length); @@ -74,7 +74,7 @@ void MultiClickTrigger::on_state_(bool state) { *this->at_index_ = *this->at_index_ + 1; } -void MultiClickTrigger::schedule_cooldown_() { +void MultiClickTriggerBase::schedule_cooldown_() { ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %" PRIu32 " ms", this->invalid_cooldown_); this->is_in_cooldown_ = true; this->set_timeout(MULTICLICK_COOLDOWN_ID, this->invalid_cooldown_, [this]() { @@ -86,7 +86,7 @@ void MultiClickTrigger::schedule_cooldown_() { this->cancel_timeout(MULTICLICK_IS_VALID_ID); this->cancel_timeout(MULTICLICK_IS_NOT_VALID_ID); } -void MultiClickTrigger::schedule_is_valid_(uint32_t min_length) { +void MultiClickTriggerBase::schedule_is_valid_(uint32_t min_length) { if (min_length == 0) { this->is_valid_ = true; return; @@ -97,19 +97,19 @@ void MultiClickTrigger::schedule_is_valid_(uint32_t min_length) { this->is_valid_ = true; }); } -void MultiClickTrigger::schedule_is_not_valid_(uint32_t max_length) { +void MultiClickTriggerBase::schedule_is_not_valid_(uint32_t max_length) { this->set_timeout(MULTICLICK_IS_NOT_VALID_ID, max_length, [this]() { ESP_LOGV(TAG, "Multi Click: You waited too long to %s.", this->parent_->state ? "RELEASE" : "PRESS"); this->is_valid_ = false; this->schedule_cooldown_(); }); } -void MultiClickTrigger::cancel() { +void MultiClickTriggerBase::cancel() { ESP_LOGV(TAG, "Multi Click: Sequence explicitly cancelled."); this->is_valid_ = false; this->schedule_cooldown_(); } -void MultiClickTrigger::trigger_() { +void MultiClickTriggerBase::trigger_() { ESP_LOGV(TAG, "Multi Click: Hooray, multi click is valid. Triggering!"); this->at_index_.reset(); this->cancel_timeout(MULTICLICK_TRIGGER_ID); diff --git a/esphome/components/binary_sensor/automation.h b/esphome/components/binary_sensor/automation.h index f30f9d3279..1875910aff 100644 --- a/esphome/components/binary_sensor/automation.h +++ b/esphome/components/binary_sensor/automation.h @@ -1,5 +1,6 @@ #pragma once +#include <array> #include <cinttypes> #include <utility> @@ -89,10 +90,10 @@ class DoubleClickTrigger : public Trigger<> { uint32_t max_length_; /// Maximum length of click. 0 means no maximum. }; -class MultiClickTrigger : public Trigger<>, public Component { +/// Non-template base for MultiClickTrigger (keeps large method bodies out of the header). +class MultiClickTriggerBase : public Trigger<>, public Component { public: - explicit MultiClickTrigger(BinarySensor *parent, std::initializer_list<MultiClickTriggerEvent> timing) - : parent_(parent), timing_(timing) {} + explicit MultiClickTriggerBase(BinarySensor *parent) : parent_(parent) {} void setup() override { this->last_state_ = this->parent_->get_state_default(false); @@ -104,6 +105,8 @@ class MultiClickTrigger : public Trigger<>, public Component { void set_invalid_cooldown(uint32_t invalid_cooldown) { this->invalid_cooldown_ = invalid_cooldown; } void cancel(); + MultiClickTriggerBase(const MultiClickTriggerBase &) = delete; + MultiClickTriggerBase &operator=(const MultiClickTriggerBase &) = delete; protected: void on_state_(bool state); @@ -113,14 +116,30 @@ class MultiClickTrigger : public Trigger<>, public Component { void trigger_(); BinarySensor *parent_; - FixedVector<MultiClickTriggerEvent> timing_; + const MultiClickTriggerEvent *timing_{nullptr}; uint32_t invalid_cooldown_{1000}; optional<size_t> at_index_{}; + uint8_t timing_count_{0}; bool last_state_{false}; bool is_in_cooldown_{false}; bool is_valid_{false}; }; +/// Template wrapper that provides inline std::array storage for timing events. +/// N is set by code generation to match the exact number of timing events configured in YAML. +template<size_t N> class MultiClickTrigger : public MultiClickTriggerBase { + public: + MultiClickTrigger(BinarySensor *parent, std::initializer_list<MultiClickTriggerEvent> timing) + : MultiClickTriggerBase(parent) { + init_array_from(this->timing_storage_, timing); + this->timing_ = this->timing_storage_.data(); + this->timing_count_ = N; + } + + protected: + std::array<MultiClickTriggerEvent, N> timing_storage_{}; +}; + class StateTrigger : public Trigger<bool> { public: explicit StateTrigger(BinarySensor *parent) { From 18168ad7fda9cb7f93a6d5b5c183038954318076 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 15:07:15 -1000 Subject: [PATCH 1805/2030] [sensor] Use std::array in CalibrateLinearFilter (#15263) --- esphome/components/sensor/__init__.py | 4 +++- esphome/components/sensor/filter.cpp | 11 ++++------- esphome/components/sensor/filter.h | 16 ++++++++++++---- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 8abba17ff9..650f5ed826 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -770,7 +770,9 @@ async def calibrate_linear_filter_to_code(config, filter_id): linear_functions = [[k, b, float("NaN")]] elif config[CONF_METHOD] == "exact": linear_functions = map_linear(x, y) - return cg.new_Pvariable(filter_id, linear_functions) + return cg.new_Pvariable( + filter_id, cg.TemplateArguments(len(linear_functions)), linear_functions + ) CONF_DEGREE = "degree" diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 7b7a968f48..6a90a5af66 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -385,13 +385,10 @@ void HeartbeatFilter::setup() { float HeartbeatFilter::get_setup_priority() const { return setup_priority::HARDWARE; } -CalibrateLinearFilter::CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions) - : linear_functions_(linear_functions) {} - -optional<float> CalibrateLinearFilter::new_value(float value) { - for (const auto &f : this->linear_functions_) { - if (!std::isfinite(f[2]) || value < f[2]) - return (value * f[0]) + f[1]; +optional<float> calibrate_linear_compute(const std::array<float, 3> *functions, size_t count, float value) { + for (size_t i = 0; i < count; i++) { + if (!std::isfinite(functions[i][2]) || value < functions[i][2]) + return (value * functions[i][0]) + functions[i][1]; } return NAN; } diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 26a03acde5..cb4abd154a 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -528,13 +528,21 @@ template<size_t N> class OrFilter : public Filter { bool has_value_{false}; }; -class CalibrateLinearFilter : public Filter { +/// Non-template helper for linear calibration (implementation in filter.cpp) +optional<float> calibrate_linear_compute(const std::array<float, 3> *functions, size_t count, float value); + +/// N is set by code generation to match the exact number of calibration segments. +template<size_t N> class CalibrateLinearFilter : public Filter { public: - explicit CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions); - optional<float> new_value(float value) override; + explicit CalibrateLinearFilter(std::initializer_list<std::array<float, 3>> linear_functions) { + init_array_from(this->linear_functions_, linear_functions); + } + optional<float> new_value(float value) override { + return calibrate_linear_compute(this->linear_functions_.data(), N, value); + } protected: - FixedVector<std::array<float, 3>> linear_functions_; + std::array<std::array<float, 3>, N> linear_functions_{}; }; /// Non-template helper for polynomial calibration (implementation in filter.cpp) From ffbbe5eab33e9d18e8e209fa55b3d24de21f765f Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 30 Mar 2026 08:55:40 +0200 Subject: [PATCH 1806/2030] [nextion] Fix log level for command processing limit message (#15302) --- esphome/components/nextion/nextion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 97d9b36e4c..b0d8ba92f7 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -423,7 +423,7 @@ void Nextion::process_nextion_commands_() { DELIMITER_SIZE)) != std::string::npos) { #ifdef USE_NEXTION_MAX_COMMANDS_PER_LOOP if (++commands_processed > this->max_commands_per_loop_) { - ESP_LOGW(TAG, "Command processing limit exceeded"); + ESP_LOGV(TAG, "Command limit reached, deferring"); break; } #endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP From 95b0e6061795f6e4ba2d7474674cbbd1a07a7347 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:20:04 +0200 Subject: [PATCH 1807/2030] [nextion] Add accessor const qualifiers, return by ref, and deprecate `get_wave_chan_id()` (#15204) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../binary_sensor/nextion_binarysensor.h | 6 ++-- esphome/components/nextion/nextion.cpp | 30 +++++----------- .../nextion/nextion_component_base.h | 34 +++++++++---------- .../nextion/sensor/nextion_sensor.h | 5 ++- .../nextion/switch/nextion_switch.h | 2 +- .../nextion/text_sensor/nextion_textsensor.h | 2 +- 6 files changed, 32 insertions(+), 47 deletions(-) diff --git a/esphome/components/nextion/binary_sensor/nextion_binarysensor.h b/esphome/components/nextion/binary_sensor/nextion_binarysensor.h index b6b23ada85..baab47851c 100644 --- a/esphome/components/nextion/binary_sensor/nextion_binarysensor.h +++ b/esphome/components/nextion/binary_sensor/nextion_binarysensor.h @@ -21,15 +21,15 @@ class NextionBinarySensor : public NextionComponent, void process_touch(uint8_t page_id, uint8_t component_id, bool state) override; // Set the components page id for Nextion Touch Component - void set_page_id(uint8_t page_id) { page_id_ = page_id; } + void set_page_id(uint8_t page_id) { this->page_id_ = page_id; } // Set the components component id for Nextion Touch Component - void set_component_id(uint8_t component_id) { component_id_ = component_id; } + void set_component_id(uint8_t component_id) { this->component_id_ = component_id; } void set_state(bool state) override { this->set_state(state, true, true); } void set_state(bool state, bool publish) override { this->set_state(state, publish, true); } void set_state(bool state, bool publish, bool send_to_nextion) override; - NextionQueueType get_queue_type() override { return NextionQueueType::BINARY_SENSOR; } + NextionQueueType get_queue_type() const override { return NextionQueueType::BINARY_SENSOR; } void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {} void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override { this->set_state(state_value != 0, publish, send_to_nextion); diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index b0d8ba92f7..22fb3ce937 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -281,7 +281,7 @@ void Nextion::print_queue_members_() { ESP_LOGN(TAG, "Queue null"); } else { ESP_LOGN(TAG, "Queue type: %d:%s, name: %s", i->component->get_queue_type(), - i->component->get_queue_type_string().c_str(), i->component->get_variable_name().c_str()); + i->component->get_queue_type_string(), i->component->get_variable_name().c_str()); } } ESP_LOGN(TAG, "*******************************************"); @@ -607,7 +607,7 @@ void Nextion::process_nextion_commands_() { ESP_LOGE(TAG, "String return but '%s' not text sensor", component->get_variable_name().c_str()); } else { ESP_LOGN(TAG, "String resp: '%s' id: %s type: %s", to_process.c_str(), component->get_variable_name().c_str(), - component->get_queue_type_string().c_str()); + component->get_queue_type_string()); } delete nb; // NOLINT(cppcoreguidelines-owning-memory) @@ -649,7 +649,7 @@ void Nextion::process_nextion_commands_() { component->get_queue_type()); } else { ESP_LOGN(TAG, "Numeric: %s type %d:%s val %d", component->get_variable_name().c_str(), - component->get_queue_type(), component->get_queue_type_string().c_str(), value); + component->get_queue_type(), component->get_queue_type_string(), value); component->set_state_from_int(value, true, false); } @@ -842,24 +842,10 @@ void Nextion::process_nextion_commands_() { if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() && ms - this->nextion_queue_.front()->queue_time > this->max_q_age_ms_) { for (auto it = this->nextion_queue_.begin(); it != this->nextion_queue_.end();) { - NextionComponentBase *component = (*it)->component; if (ms - (*it)->queue_time > this->max_q_age_ms_) { - if ((*it)->queue_time == 0) { - ESP_LOGD(TAG, "Remove old queue '%s':'%s' (t=0)", component->get_queue_type_string().c_str(), - component->get_variable_name().c_str()); - } - - if (component->get_variable_name() == "sleep_wake") { - this->is_sleeping_ = false; - } - - if ((*it)->pending_command.empty()) { - ESP_LOGD(TAG, "Remove old queue '%s':'%s'", component->get_queue_type_string().c_str(), - component->get_variable_name().c_str()); - } else { - ESP_LOGD(TAG, "Remove old queue '%s':'%s' cmd:'%s'", component->get_queue_type_string().c_str(), - component->get_variable_name().c_str(), (*it)->pending_command.c_str()); - } + NextionComponentBase *component = (*it)->component; + ESP_LOGV(TAG, "Remove old queue '%s':'%s'", component->get_queue_type_string(), + component->get_variable_name().c_str()); if (component->get_queue_type() == NextionQueueType::NO_RESULT) { if (component->get_variable_name() == "sleep_wake") { @@ -940,7 +926,7 @@ void Nextion::all_components_send_state_(bool force_update) { binarysensortype->send_state_to_nextion(); } for (auto *sensortype : this->sensortype_) { - if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_chan_id() == 0) + if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_channel_id() == 0) sensortype->send_state_to_nextion(); } for (auto *switchtype : this->switchtype_) { @@ -1236,7 +1222,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) { nextion_queue->component = component; nextion_queue->queue_time = App.get_loop_component_start_time(); - ESP_LOGN(TAG, "Queue %s: %s", component->get_queue_type_string().c_str(), component->get_variable_name().c_str()); + ESP_LOGN(TAG, "Queue %s: %s", component->get_queue_type_string(), component->get_variable_name().c_str()); std::string command = "get " + component->get_variable_name_to_send(); diff --git a/esphome/components/nextion/nextion_component_base.h b/esphome/components/nextion/nextion_component_base.h index fe0692b875..4d5550d406 100644 --- a/esphome/components/nextion/nextion_component_base.h +++ b/esphome/components/nextion/nextion_component_base.h @@ -1,4 +1,6 @@ #pragma once + +#include <string> #include <utility> #include <vector> #include "esphome/core/defines.h" @@ -35,12 +37,8 @@ class NextionComponentBase { virtual ~NextionComponentBase() = default; void set_variable_name(const std::string &variable_name, const std::string &variable_name_to_send = "") { - variable_name_ = variable_name; - if (variable_name_to_send.empty()) { - variable_name_to_send_ = variable_name; - } else { - variable_name_to_send_ = variable_name_to_send; - } + this->variable_name_ = variable_name; + this->variable_name_to_send_ = variable_name_to_send.empty() ? variable_name : variable_name_to_send; } virtual void update_component_settings(){}; @@ -64,14 +62,14 @@ class NextionComponentBase { virtual void set_state(const std::string &state, bool publish) {} virtual void set_state(const std::string &state, bool publish, bool send_to_nextion){}; - uint8_t get_component_id() { return this->component_id_; } - void set_component_id(uint8_t component_id) { component_id_ = component_id; } + uint8_t get_component_id() const { return this->component_id_; } + void set_component_id(uint8_t component_id) { this->component_id_ = component_id; } - uint8_t get_wave_channel_id() { return this->wave_chan_id_; } + uint8_t get_wave_channel_id() const { return this->wave_chan_id_; } void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; } - std::vector<uint8_t> get_wave_buffer() { return this->wave_buffer_; } - size_t get_wave_buffer_size() { return this->wave_buffer_.size(); } + const std::vector<uint8_t> &get_wave_buffer() const { return this->wave_buffer_; } + size_t get_wave_buffer_size() const { return this->wave_buffer_.size(); } void clear_wave_buffer(size_t buffer_sent) { if (this->wave_buffer_.size() <= buffer_sent) { this->wave_buffer_.clear(); @@ -80,15 +78,17 @@ class NextionComponentBase { } } - std::string get_variable_name() { return this->variable_name_; } - std::string get_variable_name_to_send() { return this->variable_name_to_send_; } - virtual NextionQueueType get_queue_type() { return NextionQueueType::NO_RESULT; } - virtual std::string get_queue_type_string() { return NEXTION_QUEUE_TYPE_STRINGS[this->get_queue_type()]; } + const std::string &get_variable_name() const { return this->variable_name_; } + const std::string &get_variable_name_to_send() const { return this->variable_name_to_send_; } + virtual NextionQueueType get_queue_type() const { return NextionQueueType::NO_RESULT; } + virtual const char *get_queue_type_string() const { return NEXTION_QUEUE_TYPE_STRINGS[this->get_queue_type()]; } virtual void set_state_from_int(int state_value, bool publish, bool send_to_nextion){}; virtual void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion){}; virtual void send_state_to_nextion(){}; - bool get_needs_to_send_update() { return this->needs_to_send_update_; } - uint8_t get_wave_chan_id() { return this->wave_chan_id_; } + bool get_needs_to_send_update() const { return this->needs_to_send_update_; } + // Remove before 2026.10.0 + ESPDEPRECATED("Use get_wave_channel_id() instead. Will be removed in 2026.10.0", "2026.4.0") + uint8_t get_wave_chan_id() const { return this->get_wave_channel_id(); } void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; } protected: diff --git a/esphome/components/nextion/sensor/nextion_sensor.h b/esphome/components/nextion/sensor/nextion_sensor.h index e4dde9a513..b1902f9b1b 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.h +++ b/esphome/components/nextion/sensor/nextion_sensor.h @@ -17,7 +17,7 @@ class NextionSensor : public NextionComponent, public sensor::Sensor, public Pol void update() override; void add_to_wave_buffer(float state); void set_precision(uint8_t precision) { this->precision_ = precision; } - void set_component_id(uint8_t component_id) { component_id_ = component_id; } + void set_component_id(uint8_t component_id) { this->component_id_ = component_id; } void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; } void set_wave_max_value(uint32_t wave_maxvalue) { this->wave_maxvalue_ = wave_maxvalue; } void process_sensor(const std::string &variable_name, int state) override; @@ -27,9 +27,8 @@ class NextionSensor : public NextionComponent, public sensor::Sensor, public Pol void set_state(float state, bool publish, bool send_to_nextion) override; void set_waveform_send_last_value(bool send_last_value) { this->send_last_value_ = send_last_value; } - uint8_t get_wave_chan_id() { return this->wave_chan_id_; } void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; } - NextionQueueType get_queue_type() override { + NextionQueueType get_queue_type() const override { return this->wave_chan_id_ == UINT8_MAX ? NextionQueueType::SENSOR : NextionQueueType::WAVEFORM_SENSOR; } void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {} diff --git a/esphome/components/nextion/switch/nextion_switch.h b/esphome/components/nextion/switch/nextion_switch.h index 1548287473..c371ea3fc6 100644 --- a/esphome/components/nextion/switch/nextion_switch.h +++ b/esphome/components/nextion/switch/nextion_switch.h @@ -21,7 +21,7 @@ class NextionSwitch : public NextionComponent, public switch_::Switch, public Po void set_state(bool state, bool publish, bool send_to_nextion) override; void send_state_to_nextion() override { this->set_state(this->state, false, true); }; - NextionQueueType get_queue_type() override { return NextionQueueType::SWITCH; } + NextionQueueType get_queue_type() const override { return NextionQueueType::SWITCH; } void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {} void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override { this->set_state(state_value != 0, publish, send_to_nextion); diff --git a/esphome/components/nextion/text_sensor/nextion_textsensor.h b/esphome/components/nextion/text_sensor/nextion_textsensor.h index 5716d0a008..7c08e47189 100644 --- a/esphome/components/nextion/text_sensor/nextion_textsensor.h +++ b/esphome/components/nextion/text_sensor/nextion_textsensor.h @@ -22,7 +22,7 @@ class NextionTextSensor : public NextionComponent, public text_sensor::TextSenso void set_state(const std::string &state, bool publish, bool send_to_nextion) override; void send_state_to_nextion() override { this->set_state(this->state, false, true); }; - NextionQueueType get_queue_type() override { return NextionQueueType::TEXT_SENSOR; } + NextionQueueType get_queue_type() const override { return NextionQueueType::TEXT_SENSOR; } void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override {} void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override { this->set_state(state_value, publish, send_to_nextion); From cd3c2ae77e0e88291d28372eb9a1a54d39e52b16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 29 Mar 2026 22:45:46 -1000 Subject: [PATCH 1808/2030] Bump aioesphomeapi from 44.8.0 to 44.8.1 (#15309) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c74dd265c7..0df5caf181 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.1 esphome-dashboard==20260210.0 -aioesphomeapi==44.8.0 +aioesphomeapi==44.8.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From d420e7bc236984f9e711e8f7669025f5f5eb090c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 02:57:27 -1000 Subject: [PATCH 1809/2030] [modbus_controller] Fix off-by-one bounds check in byte_from_hex_str (#15301) --- esphome/components/modbus_controller/modbus_controller.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index 78c3b95965..693908dca4 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -81,15 +81,15 @@ inline ModbusFunctionCode modbus_register_write_function(ModbusRegisterType reg_ inline uint8_t c_to_hex(char c) { return (c >= 'A') ? (c >= 'a') ? (c - 'a' + 10) : (c - 'A' + 10) : (c - '0'); } /** Get a byte from a hex string - * hex_byte_from_str("1122",1) returns uint_8 value 0x22 == 34 - * hex_byte_from_str("1122",0) returns 0x11 + * byte_from_hex_str("1122", 1) returns uint_8 value 0x22 == 34 + * byte_from_hex_str("1122", 0) returns 0x11 * @param value string containing hex encoding * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in * the hex string is byte_pos * 2 * @return byte value */ inline uint8_t byte_from_hex_str(const std::string &value, uint8_t pos) { - if (value.length() < pos * 2 + 1) + if (value.length() < pos * 2 + 2) return 0; return (c_to_hex(value[pos * 2]) << 4) | c_to_hex(value[pos * 2 + 1]); } From 1bc6a8d95698f2913f202c11b1af13986f6c453a Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:54:09 +0200 Subject: [PATCH 1810/2030] [nextion] Fix queue age check using inconsistent time sources (#15317) --- esphome/components/nextion/nextion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 22fb3ce937..bb3e12be50 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -1034,7 +1034,7 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) { nextion_queue->component = new nextion::NextionComponentBase; nextion_queue->component->set_variable_name(variable_name); - nextion_queue->queue_time = millis(); + nextion_queue->queue_time = App.get_loop_component_start_time(); this->nextion_queue_.push_back(nextion_queue); From 31574a427bf721f429d6fad82f25b360ce255aad Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Mon, 30 Mar 2026 09:56:47 -0700 Subject: [PATCH 1811/2030] [modbus] Share helper functions across modbus components - part A (#15291) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/modbus/helpers.py | 83 +++++++++++++ esphome/components/modbus/modbus_helpers.h | 106 +++++++++++++++++ .../components/modbus_controller/__init__.py | 87 ++------------ .../binary_sensor/__init__.py | 2 +- .../modbus_controller/modbus_controller.cpp | 4 +- .../modbus_controller/modbus_controller.h | 109 ++++-------------- .../modbus_controller/number/__init__.py | 6 +- .../modbus_controller/output/__init__.py | 2 +- .../modbus_controller/select/__init__.py | 9 +- .../modbus_controller/sensor/__init__.py | 3 +- .../modbus_controller/switch/__init__.py | 2 +- .../modbus_controller/text_sensor/__init__.py | 2 +- 12 files changed, 231 insertions(+), 184 deletions(-) create mode 100644 esphome/components/modbus/helpers.py create mode 100644 esphome/components/modbus/modbus_helpers.h diff --git a/esphome/components/modbus/helpers.py b/esphome/components/modbus/helpers.py new file mode 100644 index 0000000000..6f97f1e605 --- /dev/null +++ b/esphome/components/modbus/helpers.py @@ -0,0 +1,83 @@ +import esphome.codegen as cg + +modbus_ns = cg.esphome_ns.namespace("modbus") +modbus_helpers_ns = modbus_ns.namespace("helpers") + +ModbusFunctionCode_ns = modbus_ns.namespace("ModbusFunctionCode") +ModbusFunctionCode = ModbusFunctionCode_ns.enum("ModbusFunctionCode") + +MODBUS_FUNCTION_CODE = { + "read_coils": ModbusFunctionCode.READ_COILS, + "read_discrete_inputs": ModbusFunctionCode.READ_DISCRETE_INPUTS, + "read_holding_registers": ModbusFunctionCode.READ_HOLDING_REGISTERS, + "read_input_registers": ModbusFunctionCode.READ_INPUT_REGISTERS, + "write_single_coil": ModbusFunctionCode.WRITE_SINGLE_COIL, + "write_single_register": ModbusFunctionCode.WRITE_SINGLE_REGISTER, + "write_multiple_coils": ModbusFunctionCode.WRITE_MULTIPLE_COILS, + "write_multiple_registers": ModbusFunctionCode.WRITE_MULTIPLE_REGISTERS, +} + +ModbusRegisterType_ns = modbus_ns.namespace("ModbusRegisterType") +ModbusRegisterType = ModbusRegisterType_ns.enum("ModbusRegisterType") + +MODBUS_WRITE_REGISTER_TYPE = { + "custom": ModbusRegisterType.CUSTOM, + "coil": ModbusRegisterType.COIL, + "holding": ModbusRegisterType.HOLDING, +} + +MODBUS_REGISTER_TYPE = { + **MODBUS_WRITE_REGISTER_TYPE, + "discrete_input": ModbusRegisterType.DISCRETE_INPUT, + "read": ModbusRegisterType.READ, +} + +SensorValueType_ns = modbus_helpers_ns.namespace("SensorValueType") +SensorValueType = SensorValueType_ns.enum("SensorValueType") +SENSOR_VALUE_TYPE = { + "RAW": SensorValueType.RAW, + "U_WORD": SensorValueType.U_WORD, + "S_WORD": SensorValueType.S_WORD, + "U_DWORD": SensorValueType.U_DWORD, + "U_DWORD_R": SensorValueType.U_DWORD_R, + "S_DWORD": SensorValueType.S_DWORD, + "S_DWORD_R": SensorValueType.S_DWORD_R, + "U_QWORD": SensorValueType.U_QWORD, + "U_QWORD_R": SensorValueType.U_QWORD_R, + "S_QWORD": SensorValueType.S_QWORD, + "S_QWORD_R": SensorValueType.S_QWORD_R, + "FP32": SensorValueType.FP32, + "FP32_R": SensorValueType.FP32_R, +} + +TYPE_REGISTER_MAP = { + "RAW": 1, + "U_WORD": 1, + "S_WORD": 1, + "U_DWORD": 2, + "U_DWORD_R": 2, + "S_DWORD": 2, + "S_DWORD_R": 2, + "U_QWORD": 4, + "U_QWORD_R": 4, + "S_QWORD": 4, + "S_QWORD_R": 4, + "FP32": 2, + "FP32_R": 2, +} + +CPP_TYPE_REGISTER_MAP = { + "RAW": cg.uint16, + "U_WORD": cg.uint16, + "S_WORD": cg.int16, + "U_DWORD": cg.uint32, + "U_DWORD_R": cg.uint32, + "S_DWORD": cg.int32, + "S_DWORD_R": cg.int32, + "U_QWORD": cg.uint64, + "U_QWORD_R": cg.uint64, + "S_QWORD": cg.int64, + "S_QWORD_R": cg.int64, + "FP32": cg.float_, + "FP32_R": cg.float_, +} diff --git a/esphome/components/modbus/modbus_helpers.h b/esphome/components/modbus/modbus_helpers.h new file mode 100644 index 0000000000..9f78de1c21 --- /dev/null +++ b/esphome/components/modbus/modbus_helpers.h @@ -0,0 +1,106 @@ +#pragma once + +#include <string> + +#include "esphome/core/helpers.h" +#include "esphome/components/modbus/modbus_definitions.h" + +namespace esphome::modbus::helpers { + +enum class SensorValueType : uint8_t { + RAW = 0x00, // variable length + U_WORD = 0x1, // 1 Register unsigned + U_DWORD = 0x2, // 2 Registers unsigned + S_WORD = 0x3, // 1 Register signed + S_DWORD = 0x4, // 2 Registers signed + BIT = 0x5, + U_DWORD_R = 0x6, // 2 Registers unsigned + S_DWORD_R = 0x7, // 2 Registers unsigned + U_QWORD = 0x8, + S_QWORD = 0x9, + U_QWORD_R = 0xA, + S_QWORD_R = 0xB, + FP32 = 0xC, + FP32_R = 0xD +}; + +inline bool value_type_is_float(SensorValueType v) { + return v == SensorValueType::FP32 || v == SensorValueType::FP32_R; +} + +inline ModbusFunctionCode modbus_register_read_function(ModbusRegisterType reg_type) { + switch (reg_type) { + case ModbusRegisterType::COIL: + return ModbusFunctionCode::READ_COILS; + case ModbusRegisterType::DISCRETE_INPUT: + return ModbusFunctionCode::READ_DISCRETE_INPUTS; + case ModbusRegisterType::HOLDING: + return ModbusFunctionCode::READ_HOLDING_REGISTERS; + case ModbusRegisterType::READ: + return ModbusFunctionCode::READ_INPUT_REGISTERS; + default: + return ModbusFunctionCode::CUSTOM; + } +} + +inline ModbusFunctionCode modbus_register_write_function(ModbusRegisterType reg_type) { + switch (reg_type) { + case ModbusRegisterType::COIL: + return ModbusFunctionCode::WRITE_SINGLE_COIL; + case ModbusRegisterType::DISCRETE_INPUT: + return ModbusFunctionCode::CUSTOM; + case ModbusRegisterType::HOLDING: + return ModbusFunctionCode::READ_WRITE_MULTIPLE_REGISTERS; + case ModbusRegisterType::READ: + default: + return ModbusFunctionCode::CUSTOM; + } +} + +inline uint8_t c_to_hex(char c) { return (c >= 'A') ? (c >= 'a') ? (c - 'a' + 10) : (c - 'A' + 10) : (c - '0'); } + +/** Get a byte from a hex string + * byte_from_hex_str("1122", 1) returns uint_8 value 0x22 == 34 + * byte_from_hex_str("1122", 0) returns 0x11 + * @param value string containing hex encoding + * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in + * the hex string is byte_pos * 2 + * @return byte value + */ +inline uint8_t byte_from_hex_str(const std::string &value, uint8_t pos) { + if (value.length() < pos * 2 + 2) + return 0; + return (c_to_hex(value[pos * 2]) << 4) | c_to_hex(value[pos * 2 + 1]); +} + +/** Get a word from a hex string + * @param value string containing hex encoding + * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in + * the hex string is byte_pos * 2 + * @return word value + */ +inline uint16_t word_from_hex_str(const std::string &value, uint8_t pos) { + return byte_from_hex_str(value, pos) << 8 | byte_from_hex_str(value, pos + 1); +} + +/** Get a dword from a hex string + * @param value string containing hex encoding + * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in + * the hex string is byte_pos * 2 + * @return dword value + */ +inline uint32_t dword_from_hex_str(const std::string &value, uint8_t pos) { + return word_from_hex_str(value, pos) << 16 | word_from_hex_str(value, pos + 2); +} + +/** Get a qword from a hex string + * @param value string containing hex encoding + * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in + * the hex string is byte_pos * 2 + * @return qword value + */ +inline uint64_t qword_from_hex_str(const std::string &value, uint8_t pos) { + return static_cast<uint64_t>(dword_from_hex_str(value, pos)) << 32 | dword_from_hex_str(value, pos + 4); +} + +} // namespace esphome::modbus::helpers diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index cb0969913a..9e332425a6 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -4,6 +4,13 @@ from esphome import automation import esphome.codegen as cg from esphome.components import modbus from esphome.components.const import CONF_ENABLED +from esphome.components.modbus.helpers import ( + CPP_TYPE_REGISTER_MAP, + MODBUS_REGISTER_TYPE, + SENSOR_VALUE_TYPE, + TYPE_REGISTER_MAP, + ModbusRegisterType, +) import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_OFFSET from esphome.cpp_helpers import logging @@ -41,7 +48,6 @@ CONF_SERVER_REGISTERS = "server_registers" MULTI_CONF = True modbus_controller_ns = cg.esphome_ns.namespace("modbus_controller") -modbus_ns = cg.esphome_ns.namespace("modbus") ModbusController = modbus_controller_ns.class_( "ModbusController", cg.PollingComponent, modbus.ModbusDevice ) @@ -50,85 +56,6 @@ SensorItem = modbus_controller_ns.struct("SensorItem") ServerCourtesyResponse = modbus_controller_ns.struct("ServerCourtesyResponse") ServerRegister = modbus_controller_ns.struct("ServerRegister") -ModbusFunctionCode_ns = modbus_ns.namespace("ModbusFunctionCode") -ModbusFunctionCode = ModbusFunctionCode_ns.enum("ModbusFunctionCode") -MODBUS_FUNCTION_CODE = { - "read_coils": ModbusFunctionCode.READ_COILS, - "read_discrete_inputs": ModbusFunctionCode.READ_DISCRETE_INPUTS, - "read_holding_registers": ModbusFunctionCode.READ_HOLDING_REGISTERS, - "read_input_registers": ModbusFunctionCode.READ_INPUT_REGISTERS, - "write_single_coil": ModbusFunctionCode.WRITE_SINGLE_COIL, - "write_single_register": ModbusFunctionCode.WRITE_SINGLE_REGISTER, - "write_multiple_coils": ModbusFunctionCode.WRITE_MULTIPLE_COILS, - "write_multiple_registers": ModbusFunctionCode.WRITE_MULTIPLE_REGISTERS, -} - -ModbusRegisterType_ns = modbus_controller_ns.namespace("ModbusRegisterType") -ModbusRegisterType = ModbusRegisterType_ns.enum("ModbusRegisterType") - -MODBUS_WRITE_REGISTER_TYPE = { - "custom": ModbusRegisterType.CUSTOM, - "coil": ModbusRegisterType.COIL, - "holding": ModbusRegisterType.HOLDING, -} - -MODBUS_REGISTER_TYPE = { - **MODBUS_WRITE_REGISTER_TYPE, - "discrete_input": ModbusRegisterType.DISCRETE_INPUT, - "read": ModbusRegisterType.READ, -} - -SensorValueType_ns = modbus_controller_ns.namespace("SensorValueType") -SensorValueType = SensorValueType_ns.enum("SensorValueType") -SENSOR_VALUE_TYPE = { - "RAW": SensorValueType.RAW, - "U_WORD": SensorValueType.U_WORD, - "S_WORD": SensorValueType.S_WORD, - "U_DWORD": SensorValueType.U_DWORD, - "U_DWORD_R": SensorValueType.U_DWORD_R, - "S_DWORD": SensorValueType.S_DWORD, - "S_DWORD_R": SensorValueType.S_DWORD_R, - "U_QWORD": SensorValueType.U_QWORD, - "U_QWORD_R": SensorValueType.U_QWORD_R, - "S_QWORD": SensorValueType.S_QWORD, - "S_QWORD_R": SensorValueType.S_QWORD_R, - "FP32": SensorValueType.FP32, - "FP32_R": SensorValueType.FP32_R, -} - -TYPE_REGISTER_MAP = { - "RAW": 1, - "U_WORD": 1, - "S_WORD": 1, - "U_DWORD": 2, - "U_DWORD_R": 2, - "S_DWORD": 2, - "S_DWORD_R": 2, - "U_QWORD": 4, - "U_QWORD_R": 4, - "S_QWORD": 4, - "S_QWORD_R": 4, - "FP32": 2, - "FP32_R": 2, -} - -CPP_TYPE_REGISTER_MAP = { - "RAW": cg.uint16, - "U_WORD": cg.uint16, - "S_WORD": cg.int16, - "U_DWORD": cg.uint32, - "U_DWORD_R": cg.uint32, - "S_DWORD": cg.int32, - "S_DWORD_R": cg.int32, - "U_QWORD": cg.uint64, - "U_QWORD_R": cg.uint64, - "S_QWORD": cg.int64, - "S_QWORD_R": cg.int64, - "FP32": cg.float_, - "FP32_R": cg.float_, -} - - _LOGGER = logging.getLogger(__name__) SERVER_COURTESY_RESPONSE_SCHEMA = cv.Schema( diff --git a/esphome/components/modbus_controller/binary_sensor/__init__.py b/esphome/components/modbus_controller/binary_sensor/__init__.py index 2ae008f630..18d017e13f 100644 --- a/esphome/components/modbus_controller/binary_sensor/__init__.py +++ b/esphome/components/modbus_controller/binary_sensor/__init__.py @@ -1,10 +1,10 @@ import esphome.codegen as cg from esphome.components import binary_sensor +from esphome.components.modbus.helpers import MODBUS_REGISTER_TYPE import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID from .. import ( - MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, add_modbus_base_properties, diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index ea6ba9d085..38eaea2d1c 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -535,7 +535,7 @@ ModbusCommandItem ModbusCommandItem::create_read_command( ModbusCommandItem cmd; cmd.modbusdevice = modbusdevice; cmd.register_type = register_type; - cmd.function_code = modbus_register_read_function(register_type); + cmd.function_code = modbus::helpers::modbus_register_read_function(register_type); cmd.register_address = start_address; cmd.register_count = register_count; cmd.on_data_func = std::move(handler); @@ -548,7 +548,7 @@ ModbusCommandItem ModbusCommandItem::create_read_command(ModbusController *modbu ModbusCommandItem cmd; cmd.modbusdevice = modbusdevice; cmd.register_type = register_type; - cmd.function_code = modbus_register_read_function(register_type); + cmd.function_code = modbus::helpers::modbus_register_read_function(register_type); cmd.register_address = start_address; cmd.register_count = register_count; cmd.on_data_func = [modbusdevice](ModbusRegisterType register_type, uint16_t start_address, diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index 693908dca4..438eb12c2a 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -3,6 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/modbus/modbus.h" +#include "esphome/components/modbus/modbus_helpers.h" #include "esphome/core/automation.h" #include <list> @@ -19,109 +20,43 @@ class ModbusController; using modbus::ModbusFunctionCode; using modbus::ModbusRegisterType; using modbus::ModbusExceptionCode; +using modbus::helpers::SensorValueType; -enum class SensorValueType : uint8_t { - RAW = 0x00, // variable length - U_WORD = 0x1, // 1 Register unsigned - U_DWORD = 0x2, // 2 Registers unsigned - S_WORD = 0x3, // 1 Register signed - S_DWORD = 0x4, // 2 Registers signed - BIT = 0x5, - U_DWORD_R = 0x6, // 2 Registers unsigned - S_DWORD_R = 0x7, // 2 Registers unsigned - U_QWORD = 0x8, - S_QWORD = 0x9, - U_QWORD_R = 0xA, - S_QWORD_R = 0xB, - FP32 = 0xC, - FP32_R = 0xD -}; - -inline bool value_type_is_float(SensorValueType v) { - return v == SensorValueType::FP32 || v == SensorValueType::FP32_R; -} +// Remove before 2026.10.0 — these helpers have moved to modbus::helpers +ESPDEPRECATED("Use modbus::helpers::value_type_is_float() instead. Removed in 2026.10.0", "2026.4.0") +inline bool value_type_is_float(SensorValueType v) { return modbus::helpers::value_type_is_float(v); } +ESPDEPRECATED("Use modbus::helpers::modbus_register_read_function() instead. Removed in 2026.10.0", "2026.4.0") inline ModbusFunctionCode modbus_register_read_function(ModbusRegisterType reg_type) { - switch (reg_type) { - case ModbusRegisterType::COIL: - return ModbusFunctionCode::READ_COILS; - break; - case ModbusRegisterType::DISCRETE_INPUT: - return ModbusFunctionCode::READ_DISCRETE_INPUTS; - break; - case ModbusRegisterType::HOLDING: - return ModbusFunctionCode::READ_HOLDING_REGISTERS; - break; - case ModbusRegisterType::READ: - return ModbusFunctionCode::READ_INPUT_REGISTERS; - break; - default: - return ModbusFunctionCode::CUSTOM; - break; - } + return modbus::helpers::modbus_register_read_function(reg_type); } + +ESPDEPRECATED("Use modbus::helpers::modbus_register_write_function() instead. Removed in 2026.10.0", "2026.4.0") inline ModbusFunctionCode modbus_register_write_function(ModbusRegisterType reg_type) { - switch (reg_type) { - case ModbusRegisterType::COIL: - return ModbusFunctionCode::WRITE_SINGLE_COIL; - break; - case ModbusRegisterType::DISCRETE_INPUT: - return ModbusFunctionCode::CUSTOM; - break; - case ModbusRegisterType::HOLDING: - return ModbusFunctionCode::READ_WRITE_MULTIPLE_REGISTERS; - break; - case ModbusRegisterType::READ: - default: - return ModbusFunctionCode::CUSTOM; - break; - } + return modbus::helpers::modbus_register_write_function(reg_type); } -inline uint8_t c_to_hex(char c) { return (c >= 'A') ? (c >= 'a') ? (c - 'a' + 10) : (c - 'A' + 10) : (c - '0'); } +ESPDEPRECATED("Use modbus::helpers::c_to_hex() instead. Removed in 2026.10.0", "2026.4.0") +inline uint8_t c_to_hex(char c) { return modbus::helpers::c_to_hex(c); } -/** Get a byte from a hex string - * byte_from_hex_str("1122", 1) returns uint_8 value 0x22 == 34 - * byte_from_hex_str("1122", 0) returns 0x11 - * @param value string containing hex encoding - * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in - * the hex string is byte_pos * 2 - * @return byte value - */ +ESPDEPRECATED("Use modbus::helpers::byte_from_hex_str() instead. Removed in 2026.10.0", "2026.4.0") inline uint8_t byte_from_hex_str(const std::string &value, uint8_t pos) { - if (value.length() < pos * 2 + 2) - return 0; - return (c_to_hex(value[pos * 2]) << 4) | c_to_hex(value[pos * 2 + 1]); + return modbus::helpers::byte_from_hex_str(value, pos); } -/** Get a word from a hex string - * @param value string containing hex encoding - * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in - * the hex string is byte_pos * 2 - * @return word value - */ +ESPDEPRECATED("Use modbus::helpers::word_from_hex_str() instead. Removed in 2026.10.0", "2026.4.0") inline uint16_t word_from_hex_str(const std::string &value, uint8_t pos) { - return byte_from_hex_str(value, pos) << 8 | byte_from_hex_str(value, pos + 1); + return modbus::helpers::word_from_hex_str(value, pos); } -/** Get a dword from a hex string - * @param value string containing hex encoding - * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in - * the hex string is byte_pos * 2 - * @return dword value - */ +ESPDEPRECATED("Use modbus::helpers::dword_from_hex_str() instead. Removed in 2026.10.0", "2026.4.0") inline uint32_t dword_from_hex_str(const std::string &value, uint8_t pos) { - return word_from_hex_str(value, pos) << 16 | word_from_hex_str(value, pos + 2); + return modbus::helpers::dword_from_hex_str(value, pos); } -/** Get a qword from a hex string - * @param value string containing hex encoding - * @param position offset in bytes. Because each byte is encoded in 2 hex digits the position of the original byte in - * the hex string is byte_pos * 2 - * @return qword value - */ +ESPDEPRECATED("Use modbus::helpers::qword_from_hex_str() instead. Removed in 2026.10.0", "2026.4.0") inline uint64_t qword_from_hex_str(const std::string &value, uint8_t pos) { - return static_cast<uint64_t>(dword_from_hex_str(value, pos)) << 32 | dword_from_hex_str(value, pos + 4); + return modbus::helpers::qword_from_hex_str(value, pos); } // Extract data from modbus response buffer @@ -585,7 +520,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem int64_t number = payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask); float float_value; - if (value_type_is_float(item.sensor_value_type)) { + if (modbus::helpers::value_type_is_float(item.sensor_value_type)) { float_value = bit_cast<float>(static_cast<uint32_t>(number)); } else { float_value = static_cast<float>(number); @@ -597,7 +532,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) { int64_t val; - if (value_type_is_float(value_type)) { + if (modbus::helpers::value_type_is_float(value_type)) { val = bit_cast<uint32_t>(value); } else { val = llroundf(value); diff --git a/esphome/components/modbus_controller/number/__init__.py b/esphome/components/modbus_controller/number/__init__.py index b5efd7abf0..7563adfad9 100644 --- a/esphome/components/modbus_controller/number/__init__.py +++ b/esphome/components/modbus_controller/number/__init__.py @@ -1,5 +1,9 @@ import esphome.codegen as cg from esphome.components import number +from esphome.components.modbus.helpers import ( + MODBUS_WRITE_REGISTER_TYPE, + SENSOR_VALUE_TYPE, +) import esphome.config_validation as cv from esphome.const import ( CONF_ADDRESS, @@ -11,8 +15,6 @@ from esphome.const import ( ) from .. import ( - MODBUS_WRITE_REGISTER_TYPE, - SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, add_modbus_base_properties, diff --git a/esphome/components/modbus_controller/output/__init__.py b/esphome/components/modbus_controller/output/__init__.py index 1800a90d57..1ec4afd997 100644 --- a/esphome/components/modbus_controller/output/__init__.py +++ b/esphome/components/modbus_controller/output/__init__.py @@ -1,10 +1,10 @@ import esphome.codegen as cg from esphome.components import output +from esphome.components.modbus.helpers import SENSOR_VALUE_TYPE import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID, CONF_MULTIPLY from .. import ( - SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, modbus_calc_properties, diff --git a/esphome/components/modbus_controller/select/__init__.py b/esphome/components/modbus_controller/select/__init__.py index c94532da51..334a4dfd76 100644 --- a/esphome/components/modbus_controller/select/__init__.py +++ b/esphome/components/modbus_controller/select/__init__.py @@ -1,15 +1,10 @@ import esphome.codegen as cg from esphome.components import select +from esphome.components.modbus.helpers import SENSOR_VALUE_TYPE, TYPE_REGISTER_MAP import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC -from .. import ( - SENSOR_VALUE_TYPE, - TYPE_REGISTER_MAP, - ModbusController, - SensorItem, - modbus_controller_ns, -) +from .. import ModbusController, SensorItem, modbus_controller_ns from ..const import ( CONF_FORCE_NEW_RANGE, CONF_MODBUS_CONTROLLER_ID, diff --git a/esphome/components/modbus_controller/sensor/__init__.py b/esphome/components/modbus_controller/sensor/__init__.py index d8fce54ece..5b72586c66 100644 --- a/esphome/components/modbus_controller/sensor/__init__.py +++ b/esphome/components/modbus_controller/sensor/__init__.py @@ -1,11 +1,10 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.modbus.helpers import MODBUS_REGISTER_TYPE, SENSOR_VALUE_TYPE import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID from .. import ( - MODBUS_REGISTER_TYPE, - SENSOR_VALUE_TYPE, ModbusItemBaseSchema, SensorItem, add_modbus_base_properties, diff --git a/esphome/components/modbus_controller/switch/__init__.py b/esphome/components/modbus_controller/switch/__init__.py index e325e6198e..a40c15ab92 100644 --- a/esphome/components/modbus_controller/switch/__init__.py +++ b/esphome/components/modbus_controller/switch/__init__.py @@ -1,10 +1,10 @@ import esphome.codegen as cg from esphome.components import switch +from esphome.components.modbus.helpers import MODBUS_REGISTER_TYPE import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ASSUMED_STATE, CONF_ID from .. import ( - MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, add_modbus_base_properties, diff --git a/esphome/components/modbus_controller/text_sensor/__init__.py b/esphome/components/modbus_controller/text_sensor/__init__.py index 35cae645e1..995357143e 100644 --- a/esphome/components/modbus_controller/text_sensor/__init__.py +++ b/esphome/components/modbus_controller/text_sensor/__init__.py @@ -1,10 +1,10 @@ import esphome.codegen as cg from esphome.components import text_sensor +from esphome.components.modbus.helpers import MODBUS_REGISTER_TYPE import esphome.config_validation as cv from esphome.const import CONF_ADDRESS, CONF_ID from .. import ( - MODBUS_REGISTER_TYPE, ModbusItemBaseSchema, SensorItem, add_modbus_base_properties, From 1a86e88373996828d5927c08ad53318e6340cb04 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 30 Mar 2026 13:15:02 -0500 Subject: [PATCH 1812/2030] [thermostat] Fix stale `max_runtime_exceeded` causing spurious supplemental heating/cooling (#15274) --- .../components/thermostat/thermostat_climate.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index d52a22f880..eb3e756bc2 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -606,6 +606,16 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } void ThermostatClimate::switch_to_supplemental_action_(climate::ClimateAction action) { + // Always cancel max-runtime timers and clear exceeded flags when transitioning to idle/off, + // even if supplemental_action_ is already idle (early-return path). This prevents a stale + // heating_max_runtime_exceeded_ flag from triggering supplemental on the next heating cycle + // when HEATING_MAX_RUN_TIME fires while the main action is already IDLE. + if (action == climate::CLIMATE_ACTION_OFF || action == climate::CLIMATE_ACTION_IDLE) { + this->cancel_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); + this->cancel_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); + this->cooling_max_runtime_exceeded_ = false; + this->heating_max_runtime_exceeded_ = false; + } // setup_complete_ helps us ensure an action is called immediately after boot if ((action == this->supplemental_action_) && this->setup_complete_) { // already in target mode @@ -975,8 +985,10 @@ void ThermostatClimate::cooling_on_timer_callback_() { void ThermostatClimate::fan_mode_timer_callback_() { ESP_LOGVV(TAG, "fan_mode timer expired"); this->switch_to_fan_mode_(this->fan_mode.value_or(climate::CLIMATE_FAN_ON)); - if (this->supports_fan_only_action_uses_fan_mode_timer_) + if (this->supports_fan_only_action_uses_fan_mode_timer_) { this->switch_to_action_(this->compute_action_()); + this->switch_to_supplemental_action_(this->compute_supplemental_action_()); + } } void ThermostatClimate::fanning_off_timer_callback_() { From ddb188e8f03d7c113c690154d9f386af188d0f4f Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 30 Mar 2026 13:15:13 -0500 Subject: [PATCH 1813/2030] [bme68x_bsec2] Fix warning spam, code clean-up (#15258) --- .../components/bme68x_bsec2/bme68x_bsec2.cpp | 67 +++++++++---------- .../components/bme68x_bsec2/bme68x_bsec2.h | 62 ++++++++--------- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index cf516f6ca6..d9e00e65b2 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -6,10 +6,7 @@ #ifdef USE_BSEC2 #include "bme68x_bsec2.h" -#include <string> - -namespace esphome { -namespace bme68x_bsec2 { +namespace esphome::bme68x_bsec2 { #define BME68X_BSEC2_ALGORITHM_OUTPUT_LOG(a) (a == ALGORITHM_OUTPUT_CLASSIFICATION ? "Classification" : "Regression") #define BME68X_BSEC2_OPERATING_AGE_LOG(o) (o == OPERATING_AGE_4D ? "4 days" : "28 days") @@ -18,9 +15,19 @@ namespace bme68x_bsec2 { static const char *const TAG = "bme68x_bsec2.sensor"; -static const std::string IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"}; +static constexpr const char *const IAQ_ACCURACY_STATES[4] = {"Stabilizing", "Uncertain", "Calibrating", "Calibrated"}; + +static bool is_no_new_data_warning(int8_t status) { +#ifdef BME68X_W_NO_NEW_DATA + return status == BME68X_W_NO_NEW_DATA; +#else + return status == 2; +#endif +} void BME68xBSEC2Component::setup() { + this->warn_if_blocking_over_ = 60; // initial reads may block for up to 60ms + this->bsec_status_ = bsec_init_m(&this->bsec_instance_); if (this->bsec_status_ != BSEC_OK) { this->mark_failed(); @@ -114,7 +121,8 @@ void BME68xBSEC2Component::loop() { } else { this->status_clear_error(); } - if (this->bsec_status_ > BSEC_OK || this->bme68x_status_ > BME68X_OK) { + const bool has_bme68x_warning = this->bme68x_status_ > BME68X_OK && !is_no_new_data_warning(this->bme68x_status_); + if (this->bsec_status_ > BSEC_OK || has_bme68x_warning) { this->status_set_warning(); } else { this->status_clear_warning(); @@ -130,7 +138,7 @@ void BME68xBSEC2Component::loop() { void BME68xBSEC2Component::set_config_(const uint8_t *config, uint32_t len) { if (len > BSEC_MAX_PROPERTY_BLOB_SIZE) { - ESP_LOGE(TAG, "Configuration is larger than BSEC_MAX_PROPERTY_BLOB_SIZE"); + ESP_LOGE(TAG, "Configuration blob too large"); this->mark_failed(); return; } @@ -212,14 +220,12 @@ void BME68xBSEC2Component::run_() { if (curr_time_ns < this->bsec_settings_.next_call) { return; } - uint8_t status; - ESP_LOGV(TAG, "Performing sensor run"); struct bme68x_conf bme68x_conf; this->bsec_status_ = bsec_sensor_control_m(&this->bsec_instance_, curr_time_ns, &this->bsec_settings_); if (this->bsec_status_ < BSEC_OK) { - ESP_LOGW(TAG, "Failed to fetch sensor control settings (BSEC2 error code %d)", this->bsec_status_); + ESP_LOGW(TAG, "Fetching control settings failed (BSEC2 error code %d)", this->bsec_status_); return; } @@ -235,9 +241,9 @@ void BME68xBSEC2Component::run_() { this->bme68x_heatr_conf_.heatr_temp = this->bsec_settings_.heater_temperature; this->bme68x_heatr_conf_.heatr_dur = this->bsec_settings_.heater_duration; - // status = bme68x_set_op_mode(this->bsec_settings_.op_mode, &this->bme68x_); - status = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &this->bme68x_heatr_conf_, &this->bme68x_); - status = bme68x_set_op_mode(BME68X_FORCED_MODE, &this->bme68x_); + // this->bme68x_status_ = bme68x_set_op_mode(this->bsec_settings_.op_mode, &this->bme68x_); + this->bme68x_status_ = bme68x_set_heatr_conf(BME68X_FORCED_MODE, &this->bme68x_heatr_conf_, &this->bme68x_); + this->bme68x_status_ = bme68x_set_op_mode(BME68X_FORCED_MODE, &this->bme68x_); this->op_mode_ = BME68X_FORCED_MODE; ESP_LOGV(TAG, "Using forced mode"); @@ -259,9 +265,8 @@ void BME68xBSEC2Component::run_() { BSEC_TOTAL_HEAT_DUR - (bme68x_get_meas_dur(BME68X_PARALLEL_MODE, &bme68x_conf, &this->bme68x_) / INT64_C(1000)); - status = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &this->bme68x_heatr_conf_, &this->bme68x_); - - status = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &this->bme68x_); + this->bme68x_status_ = bme68x_set_heatr_conf(BME68X_PARALLEL_MODE, &this->bme68x_heatr_conf_, &this->bme68x_); + this->bme68x_status_ = bme68x_set_op_mode(BME68X_PARALLEL_MODE, &this->bme68x_); this->op_mode_ = BME68X_PARALLEL_MODE; ESP_LOGV(TAG, "Using parallel mode"); } @@ -282,24 +287,15 @@ void BME68xBSEC2Component::run_() { this->trigger_time_ns_ = curr_time_ns; this->set_timeout("read", meas_dur / 1000, [this]() { this->read_(this->trigger_time_ns_); }); } else { - ESP_LOGV(TAG, "Measurement not required"); - this->read_(curr_time_ns); + ESP_LOGV(TAG, "Measurement not required, queueing immediate read"); + this->trigger_time_ns_ = curr_time_ns; + this->set_timeout("read", 0, [this]() { this->read_(this->trigger_time_ns_); }); } } void BME68xBSEC2Component::read_(int64_t trigger_time_ns) { ESP_LOGV(TAG, "Reading data"); - if (this->bsec_settings_.trigger_measurement) { - uint8_t current_op_mode; - this->bme68x_status_ = bme68x_get_op_mode(¤t_op_mode, &this->bme68x_); - - if (current_op_mode == BME68X_SLEEP_MODE) { - ESP_LOGV(TAG, "Still in sleep mode, doing nothing"); - return; - } - } - if (!this->bsec_settings_.process_data) { ESP_LOGV(TAG, "Data processing not required"); return; @@ -309,12 +305,16 @@ void BME68xBSEC2Component::read_(int64_t trigger_time_ns) { uint8_t nFields = 0; this->bme68x_status_ = bme68x_get_data(this->op_mode_, &data[0], &nFields, &this->bme68x_); + if (is_no_new_data_warning(this->bme68x_status_)) { + ESP_LOGV(TAG, "BME68X did not provide new data"); + return; + } if (this->bme68x_status_ != BME68X_OK) { - ESP_LOGW(TAG, "Failed to get sensor data (BME68X error code %d)", this->bme68x_status_); + ESP_LOGW(TAG, "Fetching data failed (BME68X error code %d)", this->bme68x_status_); return; } if (nFields < 1) { - ESP_LOGD(TAG, "BME68X did not provide new data"); + ESP_LOGV(TAG, "BME68X did not provide new fields"); return; } @@ -373,7 +373,7 @@ void BME68xBSEC2Component::read_(int64_t trigger_time_ns) { uint8_t num_outputs = BSEC_NUMBER_OUTPUTS; this->bsec_status_ = bsec_do_steps_m(&this->bsec_instance_, inputs, num_inputs, outputs, &num_outputs); if (this->bsec_status_ != BSEC_OK) { - ESP_LOGW(TAG, "BSEC2 failed to process signals (BSEC2 error code %d)", this->bsec_status_); + ESP_LOGW(TAG, "Signal processing failed (BSEC2 error code %d)", this->bsec_status_); return; } if (num_outputs < 1) { @@ -474,7 +474,7 @@ void BME68xBSEC2Component::publish_sensor_(sensor::Sensor *sensor, float value, #endif #ifdef USE_TEXT_SENSOR -void BME68xBSEC2Component::publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value) { +void BME68xBSEC2Component::publish_sensor_(text_sensor::TextSensor *sensor, const char *value) { if (!sensor || (sensor->has_state() && sensor->state == value)) { return; } @@ -526,6 +526,5 @@ void BME68xBSEC2Component::save_state_(uint8_t accuracy) { ESP_LOGI(TAG, "Saved state"); } -} // namespace bme68x_bsec2 -} // namespace esphome +} // namespace esphome::bme68x_bsec2 #endif diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.h b/esphome/components/bme68x_bsec2/bme68x_bsec2.h index 1ed72eee03..9317229a1f 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.h +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.h @@ -19,8 +19,7 @@ #include <bsec2.h> -namespace esphome { -namespace bme68x_bsec2 { +namespace esphome::bme68x_bsec2 { enum AlgorithmOutput { ALGORITHM_OUTPUT_IAQ, @@ -97,7 +96,7 @@ class BME68xBSEC2Component : public Component { void publish_sensor_(sensor::Sensor *sensor, float value, bool change_only = false); #endif #ifdef USE_TEXT_SENSOR - void publish_sensor_(text_sensor::TextSensor *sensor, const std::string &value); + void publish_sensor_(text_sensor::TextSensor *sensor, const char *value); #endif void load_state_(); @@ -108,39 +107,12 @@ class BME68xBSEC2Component : public Component { struct bme68x_dev bme68x_; bsec_bme_settings_t bsec_settings_; bsec_version_t version_; - uint8_t bsec_instance_[BSEC_INSTANCE_SIZE]; - struct bme68x_heatr_conf bme68x_heatr_conf_; - uint8_t op_mode_; // operating mode of sensor - bsec_library_return_t bsec_status_{BSEC_OK}; - int8_t bme68x_status_{BME68X_OK}; - - int64_t last_time_ms_{0}; - int64_t trigger_time_ns_{0}; // Stored for set_timeout lambda to help avoid heap allocation on supported 32-bit - // toolchains with small std::function SBO - uint32_t millis_overflow_counter_{0}; std::queue<std::function<void()>> queue_; + ESPPreferenceObject bsec_state_; uint8_t const *bsec2_configuration_{nullptr}; - uint32_t bsec2_configuration_length_{0}; - bool bsec2_blob_configured_{false}; - - ESPPreferenceObject bsec_state_; - uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day - uint32_t last_state_save_ms_ = 0; - - float temperature_offset_{0}; - - AlgorithmOutput algorithm_output_{ALGORITHM_OUTPUT_IAQ}; - OperatingAge operating_age_{OPERATING_AGE_28D}; - Voltage voltage_{VOLTAGE_3_3V}; - - SampleRate sample_rate_{SAMPLE_RATE_LP}; // Core/gas sample rate - SampleRate temperature_sample_rate_{SAMPLE_RATE_DEFAULT}; - SampleRate pressure_sample_rate_{SAMPLE_RATE_DEFAULT}; - SampleRate humidity_sample_rate_{SAMPLE_RATE_DEFAULT}; - #ifdef USE_SENSOR sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *pressure_sensor_{nullptr}; @@ -155,8 +127,32 @@ class BME68xBSEC2Component : public Component { #ifdef USE_TEXT_SENSOR text_sensor::TextSensor *iaq_accuracy_text_sensor_{nullptr}; #endif + + int64_t last_time_ms_{0}; + int64_t trigger_time_ns_{0}; // Stored for set_timeout lambda to help avoid heap allocation on supported 32-bit + // toolchains with small std::function SBO + + uint32_t state_save_interval_ms_{21600000}; // 6 hours - 4 times a day + uint32_t last_state_save_ms_{0}; + uint32_t millis_overflow_counter_{0}; + uint32_t bsec2_configuration_length_{0}; + bsec_library_return_t bsec_status_{BSEC_OK}; + + float temperature_offset_{0}; + + AlgorithmOutput algorithm_output_{ALGORITHM_OUTPUT_IAQ}; + OperatingAge operating_age_{OPERATING_AGE_28D}; + Voltage voltage_{VOLTAGE_3_3V}; + SampleRate sample_rate_{SAMPLE_RATE_LP}; // Core/gas sample rate + SampleRate temperature_sample_rate_{SAMPLE_RATE_DEFAULT}; + SampleRate pressure_sample_rate_{SAMPLE_RATE_DEFAULT}; + SampleRate humidity_sample_rate_{SAMPLE_RATE_DEFAULT}; + + uint8_t bsec_instance_[BSEC_INSTANCE_SIZE]; + uint8_t op_mode_; // operating mode of sensor + int8_t bme68x_status_{BME68X_OK}; + bool bsec2_blob_configured_{false}; }; -} // namespace bme68x_bsec2 -} // namespace esphome +} // namespace esphome::bme68x_bsec2 #endif From 45e6d49d36ebbb1d2d3a19d4cd6704ac2112e01a Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 30 Mar 2026 13:15:27 -0500 Subject: [PATCH 1814/2030] [shtcx] Code clean-up (#15261) --- esphome/components/shtcx/shtcx.cpp | 18 +++++++----------- esphome/components/shtcx/shtcx.h | 16 +++++++++------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/esphome/components/shtcx/shtcx.cpp b/esphome/components/shtcx/shtcx.cpp index ec12a5babd..9ec0a2cdb7 100644 --- a/esphome/components/shtcx/shtcx.cpp +++ b/esphome/components/shtcx/shtcx.cpp @@ -2,16 +2,15 @@ #include "esphome/core/log.h" #include "esphome/core/hal.h" -namespace esphome { -namespace shtcx { +namespace esphome::shtcx { static const char *const TAG = "shtcx"; -static const uint16_t SHTCX_COMMAND_SLEEP = 0xB098; -static const uint16_t SHTCX_COMMAND_WAKEUP = 0x3517; -static const uint16_t SHTCX_COMMAND_READ_ID_REGISTER = 0xEFC8; -static const uint16_t SHTCX_COMMAND_SOFT_RESET = 0x805D; -static const uint16_t SHTCX_COMMAND_POLLING_H = 0x7866; +static constexpr uint16_t SHTCX_COMMAND_SLEEP = 0xB098; +static constexpr uint16_t SHTCX_COMMAND_WAKEUP = 0x3517; +static constexpr uint16_t SHTCX_COMMAND_READ_ID_REGISTER = 0xEFC8; +static constexpr uint16_t SHTCX_COMMAND_SOFT_RESET = 0x805D; +static constexpr uint16_t SHTCX_COMMAND_POLLING_H = 0x7866; static const LogString *shtcx_type_to_string(SHTCXType type) { switch (type) { @@ -91,8 +90,6 @@ void SHTCXComponent::update() { } else { temperature = 175.0f * float(raw_data[0]) / 65536.0f - 45.0f; humidity = 100.0f * float(raw_data[1]) / 65536.0f; - - ESP_LOGD(TAG, "Temperature=%.2f°C Humidity=%.2f%%", temperature, humidity); } if (this->temperature_sensor_ != nullptr) this->temperature_sensor_->publish_state(temperature); @@ -117,5 +114,4 @@ void SHTCXComponent::wake_up() { delayMicroseconds(200); } -} // namespace shtcx -} // namespace esphome +} // namespace esphome::shtcx diff --git a/esphome/components/shtcx/shtcx.h b/esphome/components/shtcx/shtcx.h index f9778dce8d..a86b204e2b 100644 --- a/esphome/components/shtcx/shtcx.h +++ b/esphome/components/shtcx/shtcx.h @@ -4,10 +4,13 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/sensirion_common/i2c_sensirion.h" -namespace esphome { -namespace shtcx { +namespace esphome::shtcx { -enum SHTCXType { SHTCX_TYPE_SHTC3 = 0, SHTCX_TYPE_SHTC1, SHTCX_TYPE_UNKNOWN }; +enum SHTCXType : uint8_t { + SHTCX_TYPE_SHTC3 = 0, + SHTCX_TYPE_SHTC1, + SHTCX_TYPE_UNKNOWN, +}; /// This class implements support for the SHT3x-DIS family of temperature+humidity i2c sensors. class SHTCXComponent : public PollingComponent, public sensirion_common::SensirionI2CDevice { @@ -23,11 +26,10 @@ class SHTCXComponent : public PollingComponent, public sensirion_common::Sensiri void wake_up(); protected: - SHTCXType type_; - uint16_t sensor_id_; sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; + uint16_t sensor_id_; + SHTCXType type_; }; -} // namespace shtcx -} // namespace esphome +} // namespace esphome::shtcx From b579758c469eebbcb23fecefa3043530f493e913 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 30 Mar 2026 13:15:37 -0500 Subject: [PATCH 1815/2030] [dht] Code clean-up (#15271) --- esphome/components/dht/dht.cpp | 28 +++++++++++----------------- esphome/components/dht/dht.h | 13 +++++-------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/esphome/components/dht/dht.cpp b/esphome/components/dht/dht.cpp index fef247f168..5b7b6a268f 100644 --- a/esphome/components/dht/dht.cpp +++ b/esphome/components/dht/dht.cpp @@ -2,8 +2,7 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" -namespace esphome { -namespace dht { +namespace esphome::dht { static const char *const TAG = "dht"; @@ -45,16 +44,13 @@ void DHT::update() { } if (success) { - ESP_LOGD(TAG, "Temperature %.1f°C Humidity %.1f%%", temperature, humidity); - if (this->temperature_sensor_ != nullptr) this->temperature_sensor_->publish_state(temperature); if (this->humidity_sensor_ != nullptr) this->humidity_sensor_->publish_state(humidity); this->status_clear_warning(); } else { - ESP_LOGW(TAG, "Invalid readings! Check pin number and pull-up resistor%s.", - this->is_auto_detect_ ? " and try manually specifying the model" : ""); + ESP_LOGW(TAG, "Invalid readings"); if (this->temperature_sensor_ != nullptr) this->temperature_sensor_->publish_state(NAN); if (this->humidity_sensor_ != nullptr) @@ -73,8 +69,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r *temperature = NAN; int error_code = 0; - int8_t i = 0; - uint8_t data[5] = {0, 0, 0, 0, 0}; + uint8_t data[5] = {}; #ifndef USE_ESP32 this->pin_.pin_mode(gpio::FLAG_OUTPUT); @@ -107,7 +102,9 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r uint8_t bit = 7; uint8_t byte = 0; - for (i = -1; i < 40; i++) { + // On 32-bit Xtensa/RISC-V cores, int8_t would require masking/sign-extension for comparisons + // vs. native int. Using int i is native word size — small win in the timing-critical section. + for (int i = -1; i < 40; i++) { uint32_t start_time = micros(); // Wait for rising edge @@ -156,11 +153,9 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r } } } - if (!report_errors && error_code != 0) - return false; - - if (error_code) { - ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); + if (error_code != 0) { + if (report_errors) + ESP_LOGW(TAG, ESP_LOG_MSG_COMM_FAIL); return false; } @@ -177,7 +172,7 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r if (checksum_a != data[4] && checksum_b != data[4]) { if (report_errors) { - ESP_LOGW(TAG, "Checksum invalid: %u!=%u", checksum_a, data[4]); + ESP_LOGW(TAG, "Invalid checksum"); } return false; } @@ -234,5 +229,4 @@ bool HOT IRAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool r return true; } -} // namespace dht -} // namespace esphome +} // namespace esphome::dht diff --git a/esphome/components/dht/dht.h b/esphome/components/dht/dht.h index 4671ee6f27..0c535f7cf6 100644 --- a/esphome/components/dht/dht.h +++ b/esphome/components/dht/dht.h @@ -4,10 +4,9 @@ #include "esphome/core/hal.h" #include "esphome/components/sensor/sensor.h" -namespace esphome { -namespace dht { +namespace esphome::dht { -enum DHTModel { +enum DHTModel : uint8_t { DHT_MODEL_AUTO_DETECT = 0, DHT_MODEL_DHT11, DHT_MODEL_DHT22, @@ -42,7 +41,6 @@ class DHT : public PollingComponent { this->t_pin_ = pin; this->pin_ = pin->to_isr(); } - void set_model(DHTModel model) { model_ = model; } void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } @@ -55,13 +53,12 @@ class DHT : public PollingComponent { protected: bool read_sensor_(float *temperature, float *humidity, bool report_errors); + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; InternalGPIOPin *t_pin_; ISRInternalGPIOPin pin_; DHTModel model_{DHT_MODEL_AUTO_DETECT}; bool is_auto_detect_{false}; - sensor::Sensor *temperature_sensor_{nullptr}; - sensor::Sensor *humidity_sensor_{nullptr}; }; -} // namespace dht -} // namespace esphome +} // namespace esphome::dht From ad3f6ae3139b1ad8cb60bc27bb9c4ddc45336f2b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:20:52 -1000 Subject: [PATCH 1816/2030] [automation] Remove actions_end_ pointer from ActionList to save RAM (#15283) --- esphome/core/automation.h | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/esphome/core/automation.h b/esphome/core/automation.h index fc2cad99be..05c7f19588 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -419,44 +419,48 @@ template<typename... Ts> class Action { template<typename... Ts> class ActionList { public: void add_action(Action<Ts...> *action) { - if (this->actions_end_ == nullptr) { - this->actions_begin_ = action; - } else { - this->actions_end_->next_ = action; - } - this->actions_end_ = action; + // Walk to end of chain - action lists are short and only built during setup() + Action<Ts...> **tail = &this->actions_; + while (*tail != nullptr) + tail = &(*tail)->next_; + *tail = action; } void add_actions(const std::initializer_list<Action<Ts...> *> &actions) { + // Find tail once, then append all actions in a single pass + Action<Ts...> **tail = &this->actions_; + while (*tail != nullptr) + tail = &(*tail)->next_; for (auto *action : actions) { - this->add_action(action); + *tail = action; + tail = &action->next_; } } // Force-inline: part of the Trigger→Automation→ActionList forwarding // chain collapsed to reduce automation call stack depth. inline void play(const Ts &...x) ESPHOME_ALWAYS_INLINE { - if (this->actions_begin_ != nullptr) - this->actions_begin_->play_complex(x...); + if (this->actions_ != nullptr) + this->actions_->play_complex(x...); } void play_tuple(const std::tuple<Ts...> &tuple) { this->play_tuple_(tuple, std::make_index_sequence<sizeof...(Ts)>{}); } void stop() { - if (this->actions_begin_ != nullptr) - this->actions_begin_->stop_complex(); + if (this->actions_ != nullptr) + this->actions_->stop_complex(); } - bool empty() const { return this->actions_begin_ == nullptr; } + bool empty() const { return this->actions_ == nullptr; } /// Check if any action in this action list is currently running. bool is_running() { - if (this->actions_begin_ == nullptr) + if (this->actions_ == nullptr) return false; - return this->actions_begin_->is_running(); + return this->actions_->is_running(); } /// Return the number of actions in this action list that are currently running. int num_running() { - if (this->actions_begin_ == nullptr) + if (this->actions_ == nullptr) return 0; - return this->actions_begin_->num_running_total(); + return this->actions_->num_running_total(); } protected: @@ -464,8 +468,7 @@ template<typename... Ts> class ActionList { this->play(std::get<S>(tuple)...); } - Action<Ts...> *actions_begin_{nullptr}; - Action<Ts...> *actions_end_{nullptr}; + Action<Ts...> *actions_{nullptr}; }; template<typename... Ts> class Automation { From ffee4c22b3416d774f7cf398ffbe1b03523b168e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:21:58 -1000 Subject: [PATCH 1817/2030] [esp32_ble] Devirtualize BLE event handler dispatch (#15310) --- esphome/components/esp32_ble/__init__.py | 66 +++++++++++++++--- esphome/components/esp32_ble/ble.cpp | 21 ++---- esphome/components/esp32_ble/ble.h | 69 +++++++------------ .../components/esp32_ble_beacon/__init__.py | 1 - .../esp32_ble_beacon/esp32_ble_beacon.h | 4 +- .../components/esp32_ble_server/__init__.py | 1 - .../components/esp32_ble_server/ble_server.h | 7 +- .../components/esp32_ble_tracker/__init__.py | 2 - .../esp32_ble_tracker/esp32_ble_tracker.h | 13 ++-- esphome/core/helpers.h | 32 +++++++++ 10 files changed, 128 insertions(+), 88 deletions(-) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 43208eb87e..2e5e358753 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -134,10 +134,38 @@ class HandlerCounts: _handler_counts = HandlerCounts() +def _add_callback( + parent_var: cg.MockObj, + method: str, + handler_var: cg.MockObj, + params: str, + call_args: str, +) -> None: + """Generate a lambda callback that forwards to a handler method. + + Uses a braced scope with a local pointer variable so the generated C++ + lambda captures only that pointer, avoiding GCC warnings about capturing + variables with static storage duration. + """ + cg.add( + cg.RawStatement( + f"{{ auto *h = {handler_var}; " + f"{parent_var}->{method}(" + f"[h]({params}) {{ h->{call_args}; }}); }}" + ) + ) + + def register_gap_event_handler(parent_var: cg.MockObj, handler_var: cg.MockObj) -> None: """Register a GAP event handler and track the count.""" _handler_counts.gap_event += 1 - cg.add(parent_var.register_gap_event_handler(handler_var)) + _add_callback( + parent_var, + "add_gap_event_callback", + handler_var, + "esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param", + "gap_event_handler(event, param)", + ) def register_gap_scan_event_handler( @@ -145,7 +173,13 @@ def register_gap_scan_event_handler( ) -> None: """Register a GAP scan event handler and track the count.""" _handler_counts.gap_scan_event += 1 - cg.add(parent_var.register_gap_scan_event_handler(handler_var)) + _add_callback( + parent_var, + "add_gap_scan_event_callback", + handler_var, + "const esphome::esp32_ble::BLEScanResult &scan_result", + "gap_scan_event_handler(scan_result)", + ) def register_gattc_event_handler( @@ -153,7 +187,13 @@ def register_gattc_event_handler( ) -> None: """Register a GATTc event handler and track the count.""" _handler_counts.gattc_event += 1 - cg.add(parent_var.register_gattc_event_handler(handler_var)) + _add_callback( + parent_var, + "add_gattc_event_callback", + handler_var, + "esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param", + "gattc_event_handler(event, gattc_if, param)", + ) def register_gatts_event_handler( @@ -161,7 +201,13 @@ def register_gatts_event_handler( ) -> None: """Register a GATTs event handler and track the count.""" _handler_counts.gatts_event += 1 - cg.add(parent_var.register_gatts_event_handler(handler_var)) + _add_callback( + parent_var, + "add_gatts_event_callback", + handler_var, + "esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param", + "gatts_event_handler(event, gatts_if, param)", + ) def register_ble_status_event_handler( @@ -169,7 +215,13 @@ def register_ble_status_event_handler( ) -> None: """Register a BLE status event handler and track the count.""" _handler_counts.ble_status_event += 1 - cg.add(parent_var.register_ble_status_event_handler(handler_var)) + _add_callback( + parent_var, + "add_ble_status_event_callback", + handler_var, + "", + "ble_before_disabled_event_handler()", + ) def register_bt_logger(*loggers: BTLoggers) -> None: @@ -225,10 +277,6 @@ NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2] esp32_ble_ns = cg.esphome_ns.namespace("esp32_ble") ESP32BLE = esp32_ble_ns.class_("ESP32BLE", cg.Component) -GAPEventHandler = esp32_ble_ns.class_("GAPEventHandler") -GATTcEventHandler = esp32_ble_ns.class_("GATTcEventHandler") -GATTsEventHandler = esp32_ble_ns.class_("GATTsEventHandler") - BLEEnabledCondition = esp32_ble_ns.class_("BLEEnabledCondition", automation.Condition) BLEEnableAction = esp32_ble_ns.class_("BLEEnableAction", automation.Action) BLEDisableAction = esp32_ble_ns.class_("BLEDisableAction", automation.Action) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 317f8fd11b..2cd2ec67f7 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -408,9 +408,7 @@ void ESP32BLE::loop() { esp_gatt_if_t gatts_if = ble_event->event_.gatts.gatts_if; esp_ble_gatts_cb_param_t *param = &ble_event->event_.gatts.gatts_param; ESP_LOGV(TAG, "gatts_event [esp_gatt_if: %d] - %d", gatts_if, event); - for (auto *gatts_handler : this->gatts_event_handlers_) { - gatts_handler->gatts_event_handler(event, gatts_if, param); - } + this->gatts_event_callbacks_.call(event, gatts_if, param); break; } #endif @@ -420,9 +418,7 @@ void ESP32BLE::loop() { esp_gatt_if_t gattc_if = ble_event->event_.gattc.gattc_if; esp_ble_gattc_cb_param_t *param = &ble_event->event_.gattc.gattc_param; ESP_LOGV(TAG, "gattc_event [esp_gatt_if: %d] - %d", gattc_if, event); - for (auto *gattc_handler : this->gattc_event_handlers_) { - gattc_handler->gattc_event_handler(event, gattc_if, param); - } + this->gattc_event_callbacks_.call(event, gattc_if, param); break; } #endif @@ -431,10 +427,7 @@ void ESP32BLE::loop() { switch (gap_event) { case ESP_GAP_BLE_SCAN_RESULT_EVT: #ifdef ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT - // Use the new scan event handler - no memcpy! - for (auto *scan_handler : this->gap_scan_event_handlers_) { - scan_handler->gap_scan_event_handler(ble_event->scan_result()); - } + this->gap_scan_event_callbacks_.call(ble_event->scan_result()); #endif break; @@ -478,9 +471,7 @@ void ESP32BLE::loop() { } // clang-format on // Dispatch to all registered handlers - for (auto *gap_handler : this->gap_event_handlers_) { - gap_handler->gap_event_handler(gap_event, param); - } + this->gap_event_callbacks_.call(gap_event, param); } #endif break; @@ -518,9 +509,7 @@ void ESP32BLE::loop_handle_state_transition_not_active_() { ESP_LOGD(TAG, "Disabling"); #ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT - for (auto *ble_event_handler : this->ble_status_event_handlers_) { - ble_event_handler->ble_before_disabled_event_handler(); - } + this->ble_status_event_callbacks_.call(); #endif if (!ble_dismantle_()) { diff --git a/esphome/components/esp32_ble/ble.h b/esphome/components/esp32_ble/ble.h index 82b2789461..de8c8c2343 100644 --- a/esphome/components/esp32_ble/ble.h +++ b/esphome/components/esp32_ble/ble.h @@ -87,37 +87,6 @@ enum BLEComponentState : uint8_t { BLE_COMPONENT_STATE_ACTIVE, }; -class GAPEventHandler { - public: - virtual void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) = 0; -}; - -class GAPScanEventHandler { - public: - virtual void gap_scan_event_handler(const BLEScanResult &scan_result) = 0; -}; - -#ifdef USE_ESP32_BLE_CLIENT -class GATTcEventHandler { - public: - virtual void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t *param) = 0; -}; -#endif - -#ifdef USE_ESP32_BLE_SERVER -class GATTsEventHandler { - public: - virtual void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) = 0; -}; -#endif - -class BLEStatusEventHandler { - public: - virtual void ble_before_disabled_event_handler() = 0; -}; - class ESP32BLE : public Component { public: void set_io_capability(IoCapability io_capability) { this->io_cap_ = (esp_ble_io_cap_t) io_capability; } @@ -154,22 +123,28 @@ class ESP32BLE : public Component { #endif #ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT - void register_gap_event_handler(GAPEventHandler *handler) { this->gap_event_handlers_.push_back(handler); } + template<typename F> void add_gap_event_callback(F &&callback) { + this->gap_event_callbacks_.add(std::forward<F>(callback)); + } #endif #ifdef ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT - void register_gap_scan_event_handler(GAPScanEventHandler *handler) { - this->gap_scan_event_handlers_.push_back(handler); + template<typename F> void add_gap_scan_event_callback(F &&callback) { + this->gap_scan_event_callbacks_.add(std::forward<F>(callback)); } #endif #if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT) - void register_gattc_event_handler(GATTcEventHandler *handler) { this->gattc_event_handlers_.push_back(handler); } + template<typename F> void add_gattc_event_callback(F &&callback) { + this->gattc_event_callbacks_.add(std::forward<F>(callback)); + } #endif #if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT) - void register_gatts_event_handler(GATTsEventHandler *handler) { this->gatts_event_handlers_.push_back(handler); } + template<typename F> void add_gatts_event_callback(F &&callback) { + this->gatts_event_callbacks_.add(std::forward<F>(callback)); + } #endif #ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT - void register_ble_status_event_handler(BLEStatusEventHandler *handler) { - this->ble_status_event_handlers_.push_back(handler); + template<typename F> void add_ble_status_event_callback(F &&callback) { + this->ble_status_event_callbacks_.add(std::forward<F>(callback)); } #endif void set_enable_on_boot(bool enable_on_boot) { this->enable_on_boot_ = enable_on_boot; } @@ -202,21 +177,27 @@ class ESP32BLE : public Component { private: template<typename... Args> friend void enqueue_ble_event(Args... args); - // Handler vectors - use StaticVector when counts are known at compile time #ifdef ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT - StaticVector<GAPEventHandler *, ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT> gap_event_handlers_; + StaticCallbackManager<ESPHOME_ESP32_BLE_GAP_EVENT_HANDLER_COUNT, + void(esp_gap_ble_cb_event_t, esp_ble_gap_cb_param_t *)> + gap_event_callbacks_; #endif #ifdef ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT - StaticVector<GAPScanEventHandler *, ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT> gap_scan_event_handlers_; + StaticCallbackManager<ESPHOME_ESP32_BLE_GAP_SCAN_EVENT_HANDLER_COUNT, void(const BLEScanResult &)> + gap_scan_event_callbacks_; #endif #if defined(USE_ESP32_BLE_CLIENT) && defined(ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT) - StaticVector<GATTcEventHandler *, ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT> gattc_event_handlers_; + StaticCallbackManager<ESPHOME_ESP32_BLE_GATTC_EVENT_HANDLER_COUNT, + void(esp_gattc_cb_event_t, esp_gatt_if_t, esp_ble_gattc_cb_param_t *)> + gattc_event_callbacks_; #endif #if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT) - StaticVector<GATTsEventHandler *, ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT> gatts_event_handlers_; + StaticCallbackManager<ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT, + void(esp_gatts_cb_event_t, esp_gatt_if_t, esp_ble_gatts_cb_param_t *)> + gatts_event_callbacks_; #endif #ifdef ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT - StaticVector<BLEStatusEventHandler *, ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT> ble_status_event_handlers_; + StaticCallbackManager<ESPHOME_ESP32_BLE_BLE_STATUS_EVENT_HANDLER_COUNT, void()> ble_status_event_callbacks_; #endif // Large objects (size depends on template parameters, but typically aligned to 4 bytes) diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index 04c783980d..e2e790164e 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -13,7 +13,6 @@ esp32_ble_beacon_ns = cg.esphome_ns.namespace("esp32_ble_beacon") ESP32BLEBeacon = esp32_ble_beacon_ns.class_( "ESP32BLEBeacon", cg.Component, - esp32_ble.GAPEventHandler, cg.Parented.template(esp32_ble.ESP32BLE), ) CONF_MAJOR = "major" diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h index 7a0424f3aa..e16c413179 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h @@ -35,7 +35,7 @@ using esp_ble_ibeacon_t = struct { using namespace esp32_ble; -class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented<ESP32BLE> { +class ESP32BLEBeacon : public Component, public Parented<ESP32BLE> { public: explicit ESP32BLEBeacon(const std::array<uint8_t, 16> &uuid) : uuid_(uuid) {} @@ -51,7 +51,7 @@ class ESP32BLEBeacon : public Component, public GAPEventHandler, public Parented #ifndef CONFIG_ESP_HOSTED_ENABLE_BT_BLUEDROID void set_tx_power(esp_power_level_t val) { this->tx_power_ = val; } #endif - void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; + void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); protected: void on_advertise_(); diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index 827ddba955..57106cd93b 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -72,7 +72,6 @@ BLECharacteristic_ns = esp32_ble_server_ns.namespace("BLECharacteristic") BLEServer = esp32_ble_server_ns.class_( "BLEServer", cg.Component, - esp32_ble.GATTsEventHandler, cg.Parented.template(esp32_ble.ESP32BLE), ) esp32_ble_server_automations_ns = esp32_ble_server_ns.namespace( diff --git a/esphome/components/esp32_ble_server/ble_server.h b/esphome/components/esp32_ble_server/ble_server.h index 1b419d2ee4..9708ed40c8 100644 --- a/esphome/components/esp32_ble_server/ble_server.h +++ b/esphome/components/esp32_ble_server/ble_server.h @@ -24,7 +24,7 @@ namespace esp32_ble_server { using namespace esp32_ble; using namespace bytebuffer; -class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEventHandler, public Parented<ESP32BLE> { +class BLEServer : public Component, public Parented<ESP32BLE> { public: void setup() override; void loop() override; @@ -53,10 +53,9 @@ class BLEServer : public Component, public GATTsEventHandler, public BLEStatusEv const uint16_t *get_clients() const { return this->clients_; } uint8_t get_client_count() const { return this->client_count_; } - void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, - esp_ble_gatts_cb_param_t *param) override; + void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); - void ble_before_disabled_event_handler() override; + void ble_before_disabled_event_handler(); // Direct callback registration - supports multiple callbacks void on_connect(std::function<void(uint16_t)> &&callback) { diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index c5e8f3178d..b9c4c28ccf 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -90,8 +90,6 @@ esp32_ble_tracker_ns = cg.esphome_ns.namespace("esp32_ble_tracker") ESP32BLETracker = esp32_ble_tracker_ns.class_( "ESP32BLETracker", cg.Component, - esp32_ble.GAPEventHandler, - esp32_ble.GATTcEventHandler, cg.Parented.template(esp32_ble.ESP32BLE), ) ESPBTClient = esp32_ble_tracker_ns.class_("ESPBTClient") diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index f50ed107b6..ff69a4dcd2 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -291,10 +291,6 @@ class ESPBTClient : public ESPBTDeviceListener { }; class ESP32BLETracker : public Component, - public GAPEventHandler, - public GAPScanEventHandler, - public GATTcEventHandler, - public BLEStatusEventHandler, #ifdef USE_OTA_STATE_LISTENER public ota::OTAGlobalStateListener, #endif @@ -325,11 +321,10 @@ class ESP32BLETracker : public Component, void start_scan(); void stop_scan(); - void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, - esp_ble_gattc_cb_param_t *param) override; - void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) override; - void gap_scan_event_handler(const BLEScanResult &scan_result) override; - void ble_before_disabled_event_handler() override; + void gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param); + void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); + void gap_scan_event_handler(const BLEScanResult &scan_result); + void ble_before_disabled_event_handler(); #ifdef USE_OTA_STATE_LISTENER void on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) override; diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 66ba166445..f96b888e28 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1830,6 +1830,38 @@ template<typename... Ts> class CallbackManager<void(Ts...)> { std::vector<Callback<void(Ts...)>> callbacks_; }; +/** CallbackManager backed by StaticVector for compile-time-known callback counts. + * + * Drop-in replacement for CallbackManager that avoids std::vector template bloat + * (_M_realloc_insert, etc.) when the maximum number of callbacks is known at compile time. + * + * @tparam N Maximum number of callbacks (compile-time constant, typically from cg.add_define()) + * @tparam Ts The arguments for the callbacks, wrapped in void(). + */ +template<size_t N, typename... X> class StaticCallbackManager; + +template<size_t N, typename... Ts> class StaticCallbackManager<N, void(Ts...)> { + public: + /// Add any callable. Small trivially-copyable callables (like [this] lambdas) + /// are stored inline without heap allocation. + template<typename F> void add(F &&callback) { this->add_(Callback<void(Ts...)>::create(std::forward<F>(callback))); } + + /// Call all callbacks in this manager. + void call(Ts... args) { + for (auto &cb : this->callbacks_) + cb.call(args...); + } + size_t size() const { return this->callbacks_.size(); } + + /// Call all callbacks in this manager. + void operator()(Ts... args) { call(args...); } + + protected: + /// Non-template core to avoid code duplication per lambda type. + void add_(Callback<void(Ts...)> cb) { this->callbacks_.push_back(cb); } + StaticVector<Callback<void(Ts...)>, N> callbacks_; +}; + template<typename... X> class LazyCallbackManager; /** Lazy-allocating callback manager that only allocates memory when callbacks are registered. From 8969eb76e9bdd12734f96af0200c89a18b70bc75 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:24:17 -1000 Subject: [PATCH 1818/2030] [wifi] Avoid redundant SDK calls in WiFi loop on ESP8266 (#15303) --- esphome/components/wifi/wifi_component.cpp | 8 +--- esphome/components/wifi/wifi_component.h | 13 +++++- .../wifi/wifi_component_esp8266.cpp | 44 ++++++++++--------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index db20332667..7b31a22ed5 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -784,7 +784,8 @@ void WiFiComponent::loop() { } case WIFI_COMPONENT_STATE_STA_CONNECTED: { - if (!this->is_connected_()) { + // Use cached connected_ set unconditionally at the top of loop() + if (!this->connected_) { ESP_LOGW(TAG, "Connection lost; reconnecting"); this->state_ = WIFI_COMPONENT_STATE_STA_CONNECTING; this->retry_connect(); @@ -2129,11 +2130,6 @@ void WiFiComponent::retry_connect() { } void WiFiComponent::set_reboot_timeout(uint32_t reboot_timeout) { this->reboot_timeout_ = reboot_timeout; } -bool WiFiComponent::is_connected_() const { - return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && - this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_; -} -void WiFiComponent::update_connected_state_() { this->connected_ = this->is_connected_(); } void WiFiComponent::set_power_save_mode(WiFiPowerSaveMode power_save) { this->power_save_ = power_save; #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 8dfe5fa7af..073341fe79 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -670,8 +670,11 @@ class WiFiComponent final : public Component { bool wifi_sta_connect_(const WiFiAP &ap); void wifi_pre_setup_(); WiFiSTAConnectStatus wifi_sta_connect_status_() const; - bool is_connected_() const; - void update_connected_state_(); + bool is_connected_() const { + return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED && + this->wifi_sta_connect_status_() == WiFiSTAConnectStatus::CONNECTED && !this->error_from_callback_; + } + void update_connected_state_() { this->connected_ = this->is_connected_(); } bool wifi_scan_start_(bool passive); #ifdef USE_WIFI_AP @@ -811,6 +814,12 @@ class WiFiComponent final : public Component { uint8_t num_ipv6_addresses_{0}; #endif /* USE_NETWORK_IPV6 */ bool error_from_callback_{false}; +#ifdef USE_ESP8266 + // ESP8266WiFiSTAState enum, defined in wifi_component_esp8266.cpp. + // Written from SDK system context (wifi_event_callback) — uint8_t writes + // are atomic on Xtensa LX106 so no synchronization is needed. + uint8_t sta_state_{0}; +#endif RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; RoamingState roaming_state_{RoamingState::IDLE}; bssid_t roaming_target_bssid_{}; // BSSID of the AP we're trying to roam to diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 03800cc3a9..cb53d3ac1b 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -44,11 +44,14 @@ namespace esphome::wifi { static const char *const TAG = "wifi_esp8266"; -static bool s_sta_connected = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_sta_got_ip = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_sta_connect_not_found = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_sta_connect_error = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static bool s_sta_connecting = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +enum class ESP8266WiFiSTAState : uint8_t { + IDLE, // Not connecting + CONNECTING, // Connection in progress + ASSOCIATED, // Associated to AP, waiting for IP + CONNECTED, // Successfully connected with IP + ERROR_NOT_FOUND, // AP not found (probe failed) + ERROR_FAILED, // Connection failed (auth, timeout, etc.) +}; bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) { uint8_t current_mode = wifi_get_opmode(); @@ -359,11 +362,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { // Reset flags, do this _before_ wifi_station_connect as the callback method // may be called from wifi_station_connect - s_sta_connecting = true; - s_sta_connected = false; - s_sta_got_ip = false; - s_sta_connect_error = false; - s_sta_connect_not_found = false; + this->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::CONNECTING); ETS_UART_INTR_DISABLE(); ret = wifi_station_connect(); @@ -493,7 +492,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { ESP_LOGV(TAG, "Connected ssid='%.*s' bssid=%s channel=%u", it.ssid_len, (const char *) it.ssid, bssid_buf, it.channel); #endif - s_sta_connected = true; + global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ASSOCIATED); #ifdef USE_WIFI_CONNECT_STATE_LISTENERS // Defer listener notification until state machine reaches STA_CONNECTED // This ensures wifi.connected condition returns true in listener automations @@ -506,16 +505,14 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { if (it.reason == REASON_NO_AP_FOUND) { ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len, (const char *) it.ssid); - s_sta_connect_not_found = true; + global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_NOT_FOUND); } else { char bssid_s[18]; format_mac_addr_upper(it.bssid, bssid_s); ESP_LOGW(TAG, "Disconnected ssid='%.*s' bssid=" LOG_SECRET("%s") " reason='%s'", it.ssid_len, (const char *) it.ssid, bssid_s, LOG_STR_ARG(get_disconnect_reason_str(it.reason))); - s_sta_connect_error = true; + global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::ERROR_FAILED); } - s_sta_connected = false; - s_sta_connecting = false; global_wifi_component->error_from_callback_ = true; #ifdef USE_WIFI_CONNECT_STATE_LISTENERS global_wifi_component->pending_.disconnect = true; @@ -541,7 +538,7 @@ void WiFiComponent::wifi_event_callback(System_Event_t *event) { mask_buf[network::IP_ADDRESS_BUFFER_SIZE]; ESP_LOGV(TAG, "static_ip=%s gateway=%s netmask=%s", network::IPAddress(&it.ip).str_to(ip_buf), network::IPAddress(&it.gw).str_to(gw_buf), network::IPAddress(&it.mask).str_to(mask_buf)); - s_sta_got_ip = true; + global_wifi_component->sta_state_ = static_cast<uint8_t>(ESP8266WiFiSTAState::CONNECTED); #ifdef USE_WIFI_IP_STATE_LISTENERS // Defer listener callbacks to main loop - system context has limited stack global_wifi_component->pending_.got_ip = true; @@ -636,17 +633,22 @@ void WiFiComponent::wifi_pre_setup_() { } WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { - station_status_t status = wifi_station_get_connect_status(); - if (status == STATION_GOT_IP) + // Use cached state from wifi_event_callback() instead of calling + // wifi_station_get_connect_status() which queries the SDK every time. + // Use if statements with early returns instead of switch to avoid GCC + // generating a CSWTCH lookup table in .rodata (flash) on ESP8266. + auto state = static_cast<ESP8266WiFiSTAState>(this->sta_state_); + if (state == ESP8266WiFiSTAState::CONNECTED) return WiFiSTAConnectStatus::CONNECTED; - if (status == STATION_NO_AP_FOUND) + if (state == ESP8266WiFiSTAState::ERROR_NOT_FOUND) return WiFiSTAConnectStatus::ERROR_NETWORK_NOT_FOUND; - if (status == STATION_CONNECT_FAIL || status == STATION_WRONG_PASSWORD) + if (state == ESP8266WiFiSTAState::ERROR_FAILED) return WiFiSTAConnectStatus::ERROR_CONNECT_FAILED; - if (status == STATION_CONNECTING) + if (state == ESP8266WiFiSTAState::CONNECTING || state == ESP8266WiFiSTAState::ASSOCIATED) return WiFiSTAConnectStatus::CONNECTING; return WiFiSTAConnectStatus::IDLE; } + bool WiFiComponent::wifi_scan_start_(bool passive) { // enable STA if (!this->wifi_mode_(true, {})) From 46ea61666e97061d32a115b29a38328553067e33 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:24:34 -1000 Subject: [PATCH 1819/2030] [wifi] Replace FreeRTOS queue with LockFreeQueue on ESP-IDF (#15306) --- esphome/components/wifi/wifi_component.h | 11 ++++++++ .../wifi/wifi_component_esp_idf.cpp | 26 ++++++------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 073341fe79..9a08902d47 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -6,6 +6,9 @@ #include "esphome/core/automation.h" #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#ifdef USE_ESP32 +#include "esphome/core/lock_free_queue.h" +#endif #include "esphome/core/string_ref.h" #include <span> @@ -727,6 +730,7 @@ class WiFiComponent final : public Component { #ifdef USE_ESP32 void wifi_process_event_(IDFWiFiEvent *data); + friend void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); #endif #ifdef USE_RP2040 @@ -871,6 +875,13 @@ class WiFiComponent final : public Component { bool is_high_performance_mode_{false}; #endif +#ifdef USE_ESP32 + // Lock-free SPSC queue for WiFi events from ESP-IDF event handler. + // 17 slots = 16 usable (ring buffer reserves one slot). WiFi events are rare. + // Placed at end of class to avoid padding between smaller fields. + LockFreeQueue<IDFWiFiEvent, 17> event_queue_; +#endif + private: // Stores a pointer to a string literal (static storage duration). // ONLY set from Python-generated code with string literals - never dynamic strings. diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index d8b3db9667..4097df80af 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -47,7 +47,6 @@ namespace esphome::wifi { static const char *const TAG = "wifi_esp32"; static EventGroupHandle_t s_wifi_event_group; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -static QueueHandle_t s_event_queue; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static esp_netif_t *s_sta_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) #ifdef USE_WIFI_AP static esp_netif_t *s_ap_netif = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -132,11 +131,10 @@ void event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, voi return; } - // copy to heap to keep queue object small + // copy to heap — WiFi events are rare so heap alloc is fine auto *to_send = new IDFWiFiEvent; // NOLINT(cppcoreguidelines-owning-memory) memcpy(to_send, &event, sizeof(IDFWiFiEvent)); - // don't block, we may miss events but the core can handle that - if (xQueueSend(s_event_queue, &to_send, 0L) != pdPASS) { + if (!global_wifi_component->event_queue_.push(to_send)) { delete to_send; // NOLINT(cppcoreguidelines-owning-memory) } } @@ -157,12 +155,6 @@ void WiFiComponent::wifi_pre_setup_() { ESP_LOGE(TAG, "xEventGroupCreate failed"); return; } - // NOLINTNEXTLINE(bugprone-sizeof-expression) - s_event_queue = xQueueCreate(64, sizeof(IDFWiFiEvent *)); - if (s_event_queue == nullptr) { - ESP_LOGE(TAG, "xQueueCreate failed"); - return; - } err = esp_event_loop_create_default(); if (err != ERR_OK) { ESP_LOGE(TAG, "esp_event_loop_create_default failed: %s", esp_err_to_name(err)); @@ -724,16 +716,14 @@ const char *get_disconnect_reason_str(uint8_t reason) { } void WiFiComponent::wifi_loop_() { - while (true) { - IDFWiFiEvent *data; - if (xQueueReceive(s_event_queue, &data, 0L) != pdTRUE) { - // no event ready - break; - } + uint16_t dropped = this->event_queue_.get_and_reset_dropped_count(); + if (dropped > 0) { + ESP_LOGW(TAG, "Dropped %u WiFi events due to buffer overflow", dropped); + } - // process event + IDFWiFiEvent *data; + while ((data = this->event_queue_.pop()) != nullptr) { wifi_process_event_(data); - delete data; // NOLINT(cppcoreguidelines-owning-memory) } } From 8688ef7125cd7eac012ec26e90b0e4c63e67ebb1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:24:48 -1000 Subject: [PATCH 1820/2030] [benchmark] Fix decode benchmarks being optimized away by compiler (#15293) --- .../components/api/bench_proto_decode.cpp | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/tests/benchmarks/components/api/bench_proto_decode.cpp b/tests/benchmarks/components/api/bench_proto_decode.cpp index 113201dd8a..961c629f2a 100644 --- a/tests/benchmarks/components/api/bench_proto_decode.cpp +++ b/tests/benchmarks/components/api/bench_proto_decode.cpp @@ -10,10 +10,9 @@ namespace esphome::api::benchmarks { // sub-microsecond benchmarks. static constexpr int kInnerIterations = 2000; -// Helper: encode a message into a buffer and return it. -// Benchmarks encode once in setup, then decode the resulting bytes in a loop. -// This keeps decode benchmarks in sync with the actual protobuf schema — -// hand-encoded byte arrays would silently break when fields change. +// Helper: encode a message into an APIBuffer for reuse in decode benchmarks. +// Optimization barriers are applied to the decode target objects via +// DoNotOptimize/ClobberMemory, not to this buffer. template<typename T> static APIBuffer encode_message(const T &msg) { APIBuffer buffer; uint32_t size = msg.calculate_size(); @@ -23,6 +22,12 @@ template<typename T> static APIBuffer encode_message(const T &msg) { return buffer; } +/// Force a pointer through an asm barrier so the compiler cannot +/// prove its contents are unchanged across iterations. +/// benchmark::DoNotOptimize/ClobberMemory are insufficient under +/// CodSpeed's valgrind-based instrumentation. +static void escape(void *p) { asm volatile("" : : "g"(p) : "memory"); } + // --- HelloRequest decode (string + varint fields) --- static void Decode_HelloRequest(benchmark::State &state) { @@ -31,13 +36,18 @@ static void Decode_HelloRequest(benchmark::State &state) { source.api_version_major = 1; source.api_version_minor = 10; auto encoded = encode_message(source); + auto *data = encoded.data(); + auto size = encoded.size(); + benchmark::DoNotOptimize(data); + benchmark::DoNotOptimize(size); for (auto _ : state) { - HelloRequest msg; for (int i = 0; i < kInnerIterations; i++) { - msg.decode(encoded.data(), encoded.size()); + HelloRequest msg; + escape(&msg); + msg.decode(data, size); + escape(&msg); } - benchmark::DoNotOptimize(msg.api_version_major); } state.SetItemsProcessed(state.iterations() * kInnerIterations); } @@ -50,13 +60,18 @@ static void Decode_SwitchCommandRequest(benchmark::State &state) { source.key = 0x12345678; source.state = true; auto encoded = encode_message(source); + auto *data = encoded.data(); + auto size = encoded.size(); + benchmark::DoNotOptimize(data); + benchmark::DoNotOptimize(size); for (auto _ : state) { - SwitchCommandRequest msg; for (int i = 0; i < kInnerIterations; i++) { - msg.decode(encoded.data(), encoded.size()); + SwitchCommandRequest msg; + escape(&msg); + msg.decode(data, size); + escape(&msg); } - benchmark::DoNotOptimize(msg.state); } state.SetItemsProcessed(state.iterations() * kInnerIterations); } @@ -78,13 +93,18 @@ static void Decode_LightCommandRequest(benchmark::State &state) { source.has_effect = true; source.effect = StringRef::from_lit("rainbow"); auto encoded = encode_message(source); + auto *data = encoded.data(); + auto size = encoded.size(); + benchmark::DoNotOptimize(data); + benchmark::DoNotOptimize(size); for (auto _ : state) { - LightCommandRequest msg; for (int i = 0; i < kInnerIterations; i++) { - msg.decode(encoded.data(), encoded.size()); + LightCommandRequest msg; + escape(&msg); + msg.decode(data, size); + escape(&msg); } - benchmark::DoNotOptimize(msg.brightness); } state.SetItemsProcessed(state.iterations() * kInnerIterations); } From 8561a8c495afdf7caaffb3e043c644dbed7474e0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 08:48:04 -1000 Subject: [PATCH 1821/2030] [core] Suppress component source overflow warnings in testing mode (#15320) --- esphome/cpp_helpers.py | 12 +++++++----- tests/unit_tests/test_cpp_helpers.py | 21 ++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index e7ff2965c8..479090016f 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -71,11 +71,13 @@ def register_component_source(name: str) -> int: return pool.sources[name] idx = len(pool.sources) + 1 if idx > _MAX_COMPONENT_SOURCES: - _LOGGER.warning( - "Too many unique component source names (max %d), '%s' will show as '<unknown>'", - _MAX_COMPONENT_SOURCES, - name, - ) + if not CORE.testing_mode: + _LOGGER.warning( + "Too many unique component source names (max %d), " + "'%s' will show as '<unknown>'", + _MAX_COMPONENT_SOURCES, + name, + ) return 0 pool.sources[name] = idx _ensure_source_table_registered() diff --git a/tests/unit_tests/test_cpp_helpers.py b/tests/unit_tests/test_cpp_helpers.py index 52424a7cb2..a76ea21c23 100644 --- a/tests/unit_tests/test_cpp_helpers.py +++ b/tests/unit_tests/test_cpp_helpers.py @@ -140,9 +140,28 @@ def test_register_component_source_overflow_warns( sources={f"comp_{i}": i + 1 for i in range(0xFF)}, table_registered=True, ) - monkeypatch.setattr(ch, "CORE", Mock(data={ch._COMPONENT_SOURCE_DOMAIN: pool})) + monkeypatch.setattr( + ch, "CORE", Mock(data={ch._COMPONENT_SOURCE_DOMAIN: pool}, testing_mode=False) + ) with caplog.at_level(logging.WARNING): idx = register_component_source("overflow_component") assert idx == 0 assert "Too many unique component source names" in caplog.text assert "overflow_component" in caplog.text + + +def test_register_component_source_overflow_suppressed_in_testing_mode( + monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture +) -> None: + # Pre-fill pool to max + pool = ComponentSourcePool( + sources={f"comp_{i}": i + 1 for i in range(0xFF)}, + table_registered=True, + ) + monkeypatch.setattr( + ch, "CORE", Mock(data={ch._COMPONENT_SOURCE_DOMAIN: pool}, testing_mode=True) + ) + with caplog.at_level(logging.WARNING): + idx = register_component_source("overflow_component") + assert idx == 0 + assert "Too many unique component source names" not in caplog.text From f25fa7123599fe3a33fff4c652486b6fe6c23e47 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 31 Mar 2026 06:25:15 +1000 Subject: [PATCH 1822/2030] [lvgl] Fix align_to directives (#15311) --- esphome/components/lvgl/__init__.py | 15 +++++++++++++-- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/lvgl_esphome.h | 15 ++++++++++++--- esphome/components/lvgl/trigger.py | 25 +++++++++++++++++++++++-- esphome/components/lvgl/types.py | 4 ++-- tests/components/lvgl/lvgl-package.yaml | 4 +++- 6 files changed, 54 insertions(+), 10 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index a6afa12afa..6377183ef4 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -48,6 +48,7 @@ from esphome.yaml_util import load_yaml from . import defines as df, helpers, lv_validation as lvalid, widgets from .automation import focused_widgets, layers_to_code, lvgl_update, refreshed_widgets +from .defines import CONF_ALIGN_TO_LAMBDA_ID from .encoders import ( ENCODERS_CONFIG, encoders_to_code, @@ -69,8 +70,16 @@ from .schemas import ( ) from .styles import styles_to_code, theme_to_code from .touchscreens import touchscreen_schema, touchscreens_to_code -from .trigger import add_on_boot_triggers, generate_triggers -from .types import IdleTrigger, PlainTrigger, lv_font_t, lv_group_t, lv_style_t, lvgl_ns +from .trigger import add_on_boot_triggers, generate_align_tos, generate_triggers +from .types import ( + IdleTrigger, + PlainTrigger, + lv_font_t, + lv_group_t, + lv_lambda_t, + lv_style_t, + lvgl_ns, +) from .widgets import ( LvScrActType, Widget, @@ -345,6 +354,7 @@ async def to_code(configs): Widget.widgets_completed = True async with LvContext(): await generate_triggers() + await generate_align_tos(configs[0]) for config in configs: lv_component = await cg.get_variable(config[CONF_ID]) await generate_page_triggers(config) @@ -458,6 +468,7 @@ LVGL_SCHEMA = cv.All( .extend( { cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), + cv.GenerateID(CONF_ALIGN_TO_LAMBDA_ID): cv.declare_id(lv_lambda_t), cv.GenerateID(df.CONF_DISPLAYS): display_schema, cv.Optional(CONF_COLOR_DEPTH, default=16): cv.one_of(16), cv.Optional( diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 0a53d88669..72345ca98e 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -504,6 +504,7 @@ CONF_ACCEPTED_CHARS = "accepted_chars" CONF_ADJUSTABLE = "adjustable" CONF_ALIGN = "align" CONF_ALIGN_TO = "align_to" +CONF_ALIGN_TO_LAMBDA_ID = "align_to_lambda_id" CONF_ANGLE_RANGE = "angle_range" CONF_ANIMATED = "animated" CONF_ANIMATION = "animation" diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 8de82d50c0..21d1e0d417 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -128,10 +128,19 @@ class LvPageType : public Parented<LvglComponent> { bool skip; }; -using LvLambdaType = std::function<void(lv_obj_t *)>; -using set_value_lambda_t = std::function<void(float)>; using event_callback_t = void(lv_event_t *); -using text_lambda_t = std::function<const char *()>; + +class LvLambdaComponent : public Component { + public: + LvLambdaComponent(void (*callback)()) : callback_(callback) {} + + void setup() override { this->callback_(); } + // execute after the LvglComponent is setup + float get_setup_priority() const override { return setup_priority::PROCESSOR - 5; } + + protected: + void (*callback_)(); +}; template<typename... Ts> class ObjUpdateAction : public Action<Ts...> { public: diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 077ff06bb7..54309cdf89 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -8,10 +8,13 @@ from esphome.const import ( CONF_X, CONF_Y, ) +from esphome.cpp_generator import new_Pvariable +from esphome.cpp_helpers import register_component from .defines import ( CONF_ALIGN, CONF_ALIGN_TO, + CONF_ALIGN_TO_LAMBDA_ID, DIRECTIONS, LV_EVENT_MAP, LV_EVENT_TRIGGERS, @@ -89,14 +92,32 @@ async def generate_triggers(): await add_on_boot_triggers(w.config.get(CONF_ON_BOOT, ())) - # Generate align to directives while we're here - if align_to := w.config.get(CONF_ALIGN_TO): + +async def generate_align_tos(config: dict): + """ + Called once, with a full lvgl configuration to emit deferred align_to actions as a component + that executes after the LVGL setup. This is required since align_to actions are not recalculated on layout changes + and so must be applied after the display is properly laid out. + :param config: + :return: + """ + align_tos = tuple( + w for w in widget_map.values() if w.config and CONF_ALIGN_TO in w.config + ) + if align_tos: + async with LambdaContext(where="align_to") as context: + for w in align_tos: + align_to = w.config[CONF_ALIGN_TO] target = widget_map[align_to[CONF_ID]].obj align = literal(align_to[CONF_ALIGN]) x = align_to[CONF_X] y = align_to[CONF_Y] lv.obj_align_to(w.obj, target, align, x, y) + action_id = config[CONF_ALIGN_TO_LAMBDA_ID] + var = new_Pvariable(action_id, await context.get_lambda()) + await register_component(var, {}) + async def add_trigger(conf, w, *events, is_selected=None): is_selected = is_selected or w.is_selected() diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 8343a542a9..686e429267 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -1,7 +1,7 @@ from esphome import automation, codegen as cg from esphome.const import CONF_TEXT, CONF_VALUE from esphome.cpp_generator import MockObj -from esphome.cpp_types import esphome_ns +from esphome.cpp_types import Component, esphome_ns from .defines import lvgl_ns @@ -51,7 +51,7 @@ IdleTrigger = lvgl_ns.class_("IdleTrigger", automation.Trigger.template()) ObjUpdateAction = lvgl_ns.class_("ObjUpdateAction", automation.Action) LvglCondition = lvgl_ns.class_("LvglCondition", automation.Condition) LvglAction = lvgl_ns.class_("LvglAction", automation.Action) -lv_lambda_t = lvgl_ns.class_("LvLambdaType") +lv_lambda_t = lvgl_ns.class_("LvLambdaComponent", Component) LvCompound = lvgl_ns.class_("LvCompound") lv_font_t = cg.global_ns.class_("lv_font_t") lv_style_t = cg.global_ns.struct("lv_style_t") diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index b168578a98..821476a72b 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -288,7 +288,9 @@ lvgl: - label: text: "Hello shiny day" text_color: 0xFFFFFF - align: bottom_mid + align_to: + id: hello_label + align: OUT_LEFT_TOP - label: id: setup_lambda_label # Test lambda in widget property during setup (LvContext) From c5eb0eb984deae5f95edeb9b9f873feeb6aec785 Mon Sep 17 00:00:00 2001 From: Ardumine <61353807+Ardumine@users.noreply.github.com> Date: Mon, 30 Mar 2026 22:50:11 +0100 Subject: [PATCH 1823/2030] [internal_temperature] Add nRF52 Zephyr support (#15297) --- .../internal_temperature.cpp | 46 +++++++++++++++++++ .../components/internal_temperature/sensor.py | 9 +++- .../test.nrf52-adafruit.yaml | 1 + 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/components/internal_temperature/test.nrf52-adafruit.yaml diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature.cpp index 34d7baf880..567ae6170e 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature.cpp @@ -22,11 +22,18 @@ extern "C" { uint32_t temp_single_get_current_temperature(uint32_t *temp_value); } #endif // USE_BK72XX +#if defined(USE_ZEPHYR) && defined(USE_NRF52) +#include <zephyr/device.h> +#include <zephyr/drivers/sensor.h> +#endif // USE_ZEPHYR && USE_NRF52 namespace esphome { namespace internal_temperature { static const char *const TAG = "internal_temperature"; +#if defined(USE_ZEPHYR) && defined(USE_NRF52) +static const struct device *const DIE_TEMPERATURE_SENSOR = DEVICE_DT_GET_ONE(nordic_nrf_temp); +#endif // USE_ZEPHYR && USE_NRF52 #ifdef USE_ESP32 #if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \ defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \ @@ -36,6 +43,37 @@ static temperature_sensor_handle_t tsensNew = NULL; #endif // USE_ESP32 void InternalTemperatureSensor::update() { +#if defined(USE_ZEPHYR) && defined(USE_NRF52) + struct sensor_value value; + int result = sensor_sample_fetch(DIE_TEMPERATURE_SENSOR); + if (result != 0) { + ESP_LOGE(TAG, "Failed to fetch nRF52 die temperature sample (%d)", result); + if (!this->has_state()) { + this->publish_state(NAN); + } + return; + } + + result = sensor_channel_get(DIE_TEMPERATURE_SENSOR, SENSOR_CHAN_DIE_TEMP, &value); + if (result != 0) { + ESP_LOGE(TAG, "Failed to get nRF52 die temperature (%d)", result); + if (!this->has_state()) { + this->publish_state(NAN); + } + return; + } + + const float temperature = value.val1 + (value.val2 / 1000000.0f); + if (std::isfinite(temperature)) { + this->publish_state(temperature); + } else { + ESP_LOGD(TAG, "Ignoring invalid nRF52 temperature (value=%.1f)", temperature); + if (!this->has_state()) { + this->publish_state(NAN); + } + } +#else + float temperature = NAN; bool success = false; #ifdef USE_ESP32 @@ -79,9 +117,17 @@ void InternalTemperatureSensor::update() { this->publish_state(NAN); } } +#endif // USE_ZEPHYR && USE_NRF52 } void InternalTemperatureSensor::setup() { +#if defined(USE_ZEPHYR) && defined(USE_NRF52) + if (!device_is_ready(DIE_TEMPERATURE_SENSOR)) { + ESP_LOGE(TAG, "nRF52 die temperature sensor device %s not ready", DIE_TEMPERATURE_SENSOR->name); + this->mark_failed(); + return; + } +#endif // USE_ZEPHYR && USE_NRF52 #ifdef USE_ESP32 #if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \ defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \ diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py index 93b98a30f4..965e7f0520 100644 --- a/esphome/components/internal_temperature/sensor.py +++ b/esphome/components/internal_temperature/sensor.py @@ -1,15 +1,18 @@ import esphome.codegen as cg from esphome.components import sensor +from esphome.components.zephyr import zephyr_add_prj_conf import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_TEMPERATURE, ENTITY_CATEGORY_DIAGNOSTIC, PLATFORM_BK72XX, PLATFORM_ESP32, + PLATFORM_NRF52, PLATFORM_RP2040, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, ) +from esphome.core import CORE internal_temperature_ns = cg.esphome_ns.namespace("internal_temperature") InternalTemperatureSensor = internal_temperature_ns.class_( @@ -25,10 +28,14 @@ CONFIG_SCHEMA = cv.All( state_class=STATE_CLASS_MEASUREMENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ).extend(cv.polling_component_schema("60s")), - cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX]), + cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX, PLATFORM_NRF52]), ) async def to_code(config): var = await sensor.new_sensor(config) await cg.register_component(var, config) + + if CORE.using_zephyr and CORE.is_nrf52: + zephyr_add_prj_conf("SENSOR", True) + zephyr_add_prj_conf("TEMP_NRF5", True) diff --git a/tests/components/internal_temperature/test.nrf52-adafruit.yaml b/tests/components/internal_temperature/test.nrf52-adafruit.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/internal_temperature/test.nrf52-adafruit.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From 58df755d8bfe43123d59033b82c4dc3f82b0197e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 12:27:30 -1000 Subject: [PATCH 1824/2030] Bump requests from 2.33.0 to 2.33.1 (#15324) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0df5caf181..8ad5528c95 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,7 @@ freetype-py==2.5.1 jinja2==3.1.6 bleak==2.1.1 smpclient==6.0.0 -requests==2.33.0 +requests==2.33.1 # esp-idf >= 5.0 requires this pyparsing >= 3.0 From 53b2a03c80d22a99fb13aa5f09d665773e414402 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:56:05 -0400 Subject: [PATCH 1825/2030] [multiple] Fix -Wformat and -Wextra warnings across 33 component files (#15321) --- esphome/components/adc/adc_sensor_esp32.cpp | 10 ++++-- esphome/components/api/api_connection.cpp | 12 +++---- .../media_source/audio_file_media_source.cpp | 3 +- esphome/components/bm8563/bm8563.cpp | 7 ++-- .../components/bme68x_bsec2/bme68x_bsec2.cpp | 4 +-- esphome/components/dlms_meter/dlms_meter.cpp | 4 ++- .../components/esp32_touch/esp32_touch.cpp | 2 +- .../components/espnow/espnow_component.cpp | 4 ++- .../components/http_request/http_request.cpp | 2 +- esphome/components/hub75/hub75.cpp | 4 ++- esphome/components/infrared/infrared.cpp | 11 +++--- esphome/components/inkplate/inkplate.cpp | 34 ++++++++++--------- esphome/components/ld2450/ld2450.cpp | 3 +- .../components/max7219digit/max7219digit.cpp | 5 ++- esphome/components/modbus/modbus.cpp | 2 +- .../components/nextion/nextion_commands.cpp | 4 +-- esphome/components/qmp6988/qmp6988.cpp | 6 ++-- esphome/components/rd03d/rd03d.cpp | 4 ++- .../remote_base/symphony_protocol.cpp | 10 +++--- .../components/runtime_image/bmp_decoder.cpp | 4 ++- .../components/serial_proxy/serial_proxy.cpp | 24 +++++++------ esphome/components/spa06_base/spa06_base.cpp | 4 ++- esphome/components/sps30/sps30.cpp | 8 +++-- .../thermostat/thermostat_climate.cpp | 8 +++-- .../components/tormatic/tormatic_cover.cpp | 11 +++--- .../components/tormatic/tormatic_protocol.h | 4 ++- .../uart/uart_component_esp_idf.cpp | 2 +- .../climate/uponor_smatrix_climate.cpp | 4 ++- .../sensor/uponor_smatrix_sensor.cpp | 4 ++- .../uponor_smatrix/uponor_smatrix.cpp | 14 ++++---- esphome/components/vl53l0x/vl53l0x_sensor.cpp | 6 ++-- .../components/water_heater/water_heater.cpp | 5 ++- .../components/zwave_proxy/zwave_proxy.cpp | 4 ++- 33 files changed, 145 insertions(+), 88 deletions(-) diff --git a/esphome/components/adc/adc_sensor_esp32.cpp b/esphome/components/adc/adc_sensor_esp32.cpp index 1d3138623e..fc707013a8 100644 --- a/esphome/components/adc/adc_sensor_esp32.cpp +++ b/esphome/components/adc/adc_sensor_esp32.cpp @@ -2,6 +2,7 @@ #include "adc_sensor.h" #include "esphome/core/log.h" +#include <cinttypes> namespace esphome { namespace adc { @@ -346,7 +347,8 @@ float ADCSensor::sample_autorange_() { ESP_LOGVV(TAG, "Autorange summary:"); ESP_LOGVV(TAG, " Raw readings: 12db=%d, 6db=%d, 2.5db=%d, 0db=%d", raw12, raw6, raw2, raw0); ESP_LOGVV(TAG, " Voltages: 12db=%.6f, 6db=%.6f, 2.5db=%.6f, 0db=%.6f", mv12, mv6, mv2, mv0); - ESP_LOGVV(TAG, " Coefficients: c12=%u, c6=%u, c2=%u, c0=%u, sum=%u", c12, c6, c2, c0, csum); + ESP_LOGVV(TAG, " Coefficients: c12=%" PRIu32 ", c6=%" PRIu32 ", c2=%" PRIu32 ", c0=%" PRIu32 ", sum=%" PRIu32, c12, + c6, c2, c0, csum); if (csum == 0) { ESP_LOGE(TAG, "Invalid weight sum in autorange calculation"); @@ -354,8 +356,10 @@ float ADCSensor::sample_autorange_() { } const float final_result = (mv12 * c12 + mv6 * c6 + mv2 * c2 + mv0 * c0) / csum; - ESP_LOGV(TAG, "Autorange final: (%.6f*%u + %.6f*%u + %.6f*%u + %.6f*%u)/%u = %.6fV", mv12, c12, mv6, c6, mv2, c2, mv0, - c0, csum, final_result); + ESP_LOGV(TAG, + "Autorange final: (%.6f*%" PRIu32 " + %.6f*%" PRIu32 " + %.6f*%" PRIu32 " + %.6f*%" PRIu32 ")/%" PRIu32 + " = %.6fV", + mv12, c12, mv6, c6, mv2, c2, mv0, c0, csum, final_result); return final_result; } diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 0a99adcacf..79df85ada3 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1465,7 +1465,7 @@ void APIConnection::send_infrared_rf_receive_event(const InfraredRFReceiveEvent void APIConnection::on_serial_proxy_configure_request(const SerialProxyConfigureRequest &msg) { auto &proxies = App.get_serial_proxies(); if (msg.instance >= proxies.size()) { - ESP_LOGW(TAG, "Serial proxy instance %u out of range (max %u)", msg.instance, + ESP_LOGW(TAG, "Serial proxy instance %" PRIu32 " out of range (max %" PRIu32 ")", msg.instance, static_cast<uint32_t>(proxies.size())); return; } @@ -1476,7 +1476,7 @@ void APIConnection::on_serial_proxy_configure_request(const SerialProxyConfigure void APIConnection::on_serial_proxy_write_request(const SerialProxyWriteRequest &msg) { auto &proxies = App.get_serial_proxies(); if (msg.instance >= proxies.size()) { - ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + ESP_LOGW(TAG, "Serial proxy instance %" PRIu32 " out of range", msg.instance); return; } proxies[msg.instance]->write_from_client(msg.data, msg.data_len); @@ -1485,7 +1485,7 @@ void APIConnection::on_serial_proxy_write_request(const SerialProxyWriteRequest void APIConnection::on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &msg) { auto &proxies = App.get_serial_proxies(); if (msg.instance >= proxies.size()) { - ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + ESP_LOGW(TAG, "Serial proxy instance %" PRIu32 " out of range", msg.instance); return; } proxies[msg.instance]->set_modem_pins(msg.line_states); @@ -1494,7 +1494,7 @@ void APIConnection::on_serial_proxy_set_modem_pins_request(const SerialProxySetM void APIConnection::on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &msg) { auto &proxies = App.get_serial_proxies(); if (msg.instance >= proxies.size()) { - ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + ESP_LOGW(TAG, "Serial proxy instance %" PRIu32 " out of range", msg.instance); return; } SerialProxyGetModemPinsResponse resp{}; @@ -1506,7 +1506,7 @@ void APIConnection::on_serial_proxy_get_modem_pins_request(const SerialProxyGetM void APIConnection::on_serial_proxy_request(const SerialProxyRequest &msg) { auto &proxies = App.get_serial_proxies(); if (msg.instance >= proxies.size()) { - ESP_LOGW(TAG, "Serial proxy instance %u out of range", msg.instance); + ESP_LOGW(TAG, "Serial proxy instance %" PRIu32 " out of range", msg.instance); return; } switch (msg.type) { @@ -1536,7 +1536,7 @@ void APIConnection::on_serial_proxy_request(const SerialProxyRequest &msg) { break; } default: - ESP_LOGW(TAG, "Unknown serial proxy request type: %u", static_cast<uint32_t>(msg.type)); + ESP_LOGW(TAG, "Unknown serial proxy request type: %" PRIu32, static_cast<uint32_t>(msg.type)); break; } } diff --git a/esphome/components/audio_file/media_source/audio_file_media_source.cpp b/esphome/components/audio_file/media_source/audio_file_media_source.cpp index 120f871d2f..fbb5ecd88d 100644 --- a/esphome/components/audio_file/media_source/audio_file_media_source.cpp +++ b/esphome/components/audio_file/media_source/audio_file_media_source.cpp @@ -4,6 +4,7 @@ #include "esphome/components/audio/audio_decoder.h" +#include <cinttypes> #include <cstring> namespace esphome::audio_file { @@ -249,7 +250,7 @@ void AudioFileMediaSource::decode_task(void *params) { audio::AudioStreamInfo stream_info = decoder->get_audio_stream_info().value(); - ESP_LOGD(TAG, "Bits per sample: %d, Channels: %d, Sample rate: %d", stream_info.get_bits_per_sample(), + ESP_LOGD(TAG, "Bits per sample: %d, Channels: %d, Sample rate: %" PRIu32, stream_info.get_bits_per_sample(), stream_info.get_channels(), stream_info.get_sample_rate()); if (stream_info.get_bits_per_sample() != 16 || stream_info.get_channels() > 2) { diff --git a/esphome/components/bm8563/bm8563.cpp b/esphome/components/bm8563/bm8563.cpp index 269acfea44..062094c036 100644 --- a/esphome/components/bm8563/bm8563.cpp +++ b/esphome/components/bm8563/bm8563.cpp @@ -1,4 +1,7 @@ #include "bm8563.h" + +#include <cinttypes> + #include "esphome/core/log.h" namespace esphome::bm8563 { @@ -146,10 +149,10 @@ optional<uint8_t> BM8563::read_register_(uint8_t reg) { } void BM8563::set_timer_irq_(uint32_t duration_s) { - ESP_LOGI(TAG, "Timer Duration: %u s", duration_s); + ESP_LOGI(TAG, "Timer Duration: %" PRIu32 " s", duration_s); if (duration_s > MAX_TIMER_DURATION_S) { - ESP_LOGW(TAG, "Timer duration %u s exceeds maximum %u s", duration_s, MAX_TIMER_DURATION_S); + ESP_LOGW(TAG, "Timer duration %" PRIu32 " s exceeds maximum %" PRIu32 " s", duration_s, MAX_TIMER_DURATION_S); return; } diff --git a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp index d9e00e65b2..d4ac57d750 100644 --- a/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp +++ b/esphome/components/bme68x_bsec2/bme68x_bsec2.cpp @@ -89,7 +89,7 @@ void BME68xBSEC2Component::dump_config() { " Operating age: %s\n" " Sample rate: %s\n" " Voltage: %s\n" - " State save interval: %ims\n" + " State save interval: %" PRIu32 "ms\n" " Temperature offset: %.2f", BME68X_BSEC2_OPERATING_AGE_LOG(this->operating_age_), BME68X_BSEC2_SAMPLE_RATE_LOG(this->sample_rate_), BME68X_BSEC2_VOLTAGE_LOG(this->voltage_), this->state_save_interval_ms_, this->temperature_offset_); @@ -283,7 +283,7 @@ void BME68xBSEC2Component::run_() { if (this->bsec_settings_.trigger_measurement && this->bsec_settings_.op_mode != BME68X_SLEEP_MODE) { bme68x_get_conf(&bme68x_conf, &this->bme68x_); uint32_t meas_dur = bme68x_get_meas_dur(this->op_mode_, &bme68x_conf, &this->bme68x_); - ESP_LOGV(TAG, "Queueing read in %uus", meas_dur); + ESP_LOGV(TAG, "Queueing read in %" PRIu32 "us", meas_dur); this->trigger_time_ns_ = curr_time_ns; this->set_timeout("read", meas_dur / 1000, [this]() { this->read_(this->trigger_time_ns_); }); } else { diff --git a/esphome/components/dlms_meter/dlms_meter.cpp b/esphome/components/dlms_meter/dlms_meter.cpp index 052a0f4d01..b732e71d24 100644 --- a/esphome/components/dlms_meter/dlms_meter.cpp +++ b/esphome/components/dlms_meter/dlms_meter.cpp @@ -1,5 +1,7 @@ #include "dlms_meter.h" +#include <cinttypes> + #if defined(USE_ESP8266_FRAMEWORK_ARDUINO) #include <bearssl/bearssl.h> #elif defined(USE_ESP32) @@ -21,7 +23,7 @@ void DlmsMeterComponent::dump_config() { ESP_LOGCONFIG(TAG, "DLMS Meter:\n" " Provider: %s\n" - " Read Timeout: %u ms", + " Read Timeout: %" PRIu32 " ms", provider_name, this->read_timeout_); #define DLMS_METER_LOG_SENSOR(s) LOG_SENSOR(" ", #s, this->s##_sensor_); DLMS_METER_SENSOR_LIST(DLMS_METER_LOG_SENSOR, ) diff --git a/esphome/components/esp32_touch/esp32_touch.cpp b/esphome/components/esp32_touch/esp32_touch.cpp index 0d331b29d6..e44bc807e9 100644 --- a/esphome/components/esp32_touch/esp32_touch.cpp +++ b/esphome/components/esp32_touch/esp32_touch.cpp @@ -217,7 +217,7 @@ void ESP32TouchComponent::setup() { for (uint32_t i = 0; i < ONESHOT_SCAN_COUNT; i++) { err = touch_sensor_trigger_oneshot_scanning(this->sens_handle_, ONESHOT_SCAN_TIMEOUT_MS); if (err != ESP_OK) { - ESP_LOGW(TAG, "Oneshot scan %d failed: %s", i, esp_err_to_name(err)); + ESP_LOGW(TAG, "Oneshot scan %" PRIu32 " failed: %s", i, esp_err_to_name(err)); } } diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index 78916891f4..0dc0f12e7e 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -4,6 +4,8 @@ #include "espnow_err.h" +#include <cinttypes> + #include "esphome/core/application.h" #include "esphome/core/defines.h" #include "esphome/core/helpers.h" @@ -266,7 +268,7 @@ void ESPNowComponent::loop() { if (wifi::global_wifi_component != nullptr && wifi::global_wifi_component->is_connected()) { int32_t new_channel = wifi::global_wifi_component->get_wifi_channel(); if (new_channel != this->wifi_channel_) { - ESP_LOGI(TAG, "Wifi Channel is changed from %d to %d.", this->wifi_channel_, new_channel); + ESP_LOGI(TAG, "Wifi Channel is changed from %d to %" PRId32 ".", this->wifi_channel_, new_channel); this->wifi_channel_ = new_channel; } } diff --git a/esphome/components/http_request/http_request.cpp b/esphome/components/http_request/http_request.cpp index 6590d2018e..2c74638f12 100644 --- a/esphome/components/http_request/http_request.cpp +++ b/esphome/components/http_request/http_request.cpp @@ -11,7 +11,7 @@ static const char *const TAG = "http_request"; void HttpRequestComponent::dump_config() { ESP_LOGCONFIG(TAG, "HTTP Request:\n" - " Timeout: %ums\n" + " Timeout: %" PRIu32 "ms\n" " User-Agent: %s\n" " Follow redirects: %s\n" " Redirect limit: %d", diff --git a/esphome/components/hub75/hub75.cpp b/esphome/components/hub75/hub75.cpp index cf8661b2b3..ba652d427d 100644 --- a/esphome/components/hub75/hub75.cpp +++ b/esphome/components/hub75/hub75.cpp @@ -1,6 +1,8 @@ #include "hub75_component.h" #include "esphome/core/application.h" +#include <cinttypes> + #ifdef USE_ESP32 namespace esphome::hub75 { @@ -58,7 +60,7 @@ void HUB75Display::dump_config() { config_.pins.oe, config_.pins.clk); ESP_LOGCONFIG(TAG, - " Clock Speed: %u MHz\n" + " Clock Speed: %" PRIu32 " MHz\n" " Latch Blanking: %i\n" " Clock Phase: %s\n" " Min Refresh Rate: %i Hz\n" diff --git a/esphome/components/infrared/infrared.cpp b/esphome/components/infrared/infrared.cpp index 658c9fd0df..9b97995a96 100644 --- a/esphome/components/infrared/infrared.cpp +++ b/esphome/components/infrared/infrared.cpp @@ -1,4 +1,7 @@ #include "infrared.h" + +#include <cinttypes> + #include "esphome/core/log.h" #ifdef USE_API @@ -100,7 +103,7 @@ void Infrared::control(const InfraredCall &call) { // Zero-copy from packed protobuf data transmit_data->set_data_from_packed_sint32(call.get_packed_data(), call.get_packed_length(), call.get_packed_count()); - ESP_LOGD(TAG, "Transmitting packed raw timings: count=%u, repeat=%u", call.get_packed_count(), + ESP_LOGD(TAG, "Transmitting packed raw timings: count=%" PRIu16 ", repeat=%" PRIu32, call.get_packed_count(), call.get_repeat_count()); } else if (call.is_base64url()) { // Decode base64url (URL-safe) into transmit buffer @@ -113,16 +116,16 @@ void Infrared::control(const InfraredCall &call) { for (int32_t timing : transmit_data->get_data()) { int32_t abs_timing = timing < 0 ? -timing : timing; if (abs_timing > max_timing_us) { - ESP_LOGE(TAG, "Invalid timing value: %d µs (max %d)", timing, max_timing_us); + ESP_LOGE(TAG, "Invalid timing value: %" PRId32 " µs (max %" PRId32 ")", timing, max_timing_us); return; } } - ESP_LOGD(TAG, "Transmitting base64url raw timings: count=%zu, repeat=%u", transmit_data->get_data().size(), + ESP_LOGD(TAG, "Transmitting base64url raw timings: count=%zu, repeat=%" PRIu32, transmit_data->get_data().size(), call.get_repeat_count()); } else { // From vector (lambdas/automations) transmit_data->set_data(call.get_raw_timings()); - ESP_LOGD(TAG, "Transmitting raw timings: count=%zu, repeat=%u", call.get_raw_timings().size(), + ESP_LOGD(TAG, "Transmitting raw timings: count=%zu, repeat=%" PRIu32, call.get_raw_timings().size(), call.get_repeat_count()); } diff --git a/esphome/components/inkplate/inkplate.cpp b/esphome/components/inkplate/inkplate.cpp index 3b4b1a63d5..0511b451a8 100644 --- a/esphome/components/inkplate/inkplate.cpp +++ b/esphome/components/inkplate/inkplate.cpp @@ -3,6 +3,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cinttypes> + #include <hal/gpio_hal.h> namespace esphome { @@ -193,7 +195,7 @@ void Inkplate::dump_config() { ESP_LOGCONFIG(TAG, " Greyscale: %s\n" " Partial Updating: %s\n" - " Full Update Every: %d", + " Full Update Every: %" PRIu32, YESNO(this->greyscale_), YESNO(this->partial_updating_), this->full_update_every_); // Log pins LOG_PIN(" CKV Pin: ", this->ckv_pin_); @@ -306,7 +308,7 @@ void Inkplate::fill(Color color) { // If clipping is active, fall back to base implementation if (this->get_clipping().is_set()) { Display::fill(color); - ESP_LOGV(TAG, "Fill finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Fill finished (%" PRIu32 "ms)", millis() - start_time); return; } @@ -329,12 +331,12 @@ void Inkplate::display() { this->display3b_(); } else { if (this->partial_updating_ && this->partial_update_()) { - ESP_LOGV(TAG, "Display finished (partial) (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display finished (partial) (%" PRIu32 "ms)", millis() - start_time); return; } this->display1b_(); } - ESP_LOGV(TAG, "Display finished (full) (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display finished (full) (%" PRIu32 "ms)", millis() - start_time); } void Inkplate::display1b_() { @@ -409,7 +411,7 @@ void Inkplate::display1b_() { uint32_t clock = (1UL << this->cl_pin_->get_pin()); uint32_t data_mask = this->get_data_pin_mask_(); - ESP_LOGV(TAG, "Display1b start loops (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display1b start loops (%" PRIu32 "ms)", millis() - start_time); for (uint8_t k = 0; k < rep; k++) { buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1]; @@ -440,7 +442,7 @@ void Inkplate::display1b_() { } delayMicroseconds(230); } - ESP_LOGV(TAG, "Display1b first loop x %d (%ums)", 4, millis() - start_time); + ESP_LOGV(TAG, "Display1b first loop x %d (%" PRIu32 "ms)", 4, millis() - start_time); buffer_ptr = &this->buffer_[this->get_buffer_length_() - 1]; vscan_start_(); @@ -469,7 +471,7 @@ void Inkplate::display1b_() { vscan_end_(); } delayMicroseconds(230); - ESP_LOGV(TAG, "Display1b second loop (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display1b second loop (%" PRIu32 "ms)", millis() - start_time); if (this->model_ == INKPLATE_6_PLUS) { clean_fast_(2, 2); @@ -495,13 +497,13 @@ void Inkplate::display1b_() { vscan_end_(); } delayMicroseconds(230); - ESP_LOGV(TAG, "Display1b third loop (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display1b third loop (%" PRIu32 "ms)", millis() - start_time); } vscan_start_(); eink_off_(); this->block_partial_ = false; this->partial_updates_ = 0; - ESP_LOGV(TAG, "Display1b finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display1b finished (%" PRIu32 "ms)", millis() - start_time); } void Inkplate::display3b_() { @@ -614,7 +616,7 @@ void Inkplate::display3b_() { clean_fast_(3, 1); vscan_start_(); eink_off_(); - ESP_LOGV(TAG, "Display3b finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Display3b finished (%" PRIu32 "ms)", millis() - start_time); } bool Inkplate::partial_update_() { @@ -641,7 +643,7 @@ bool Inkplate::partial_update_() { this->partial_buffer_2_[n--] = LUTW[diffw & 0x0F] & LUTB[diffb & 0x0F]; } } - ESP_LOGV(TAG, "Partial update buffer built after (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Partial update buffer built after (%" PRIu32 "ms)", millis() - start_time); int rep = (this->model_ == INKPLATE_6_V2) ? 6 : 5; @@ -667,7 +669,7 @@ bool Inkplate::partial_update_() { vscan_end_(); } delayMicroseconds(230); - ESP_LOGV(TAG, "Partial update loop k=%d (%ums)", k, millis() - start_time); + ESP_LOGV(TAG, "Partial update loop k=%d (%" PRIu32 "ms)", k, millis() - start_time); } clean_fast_(2, 2); clean_fast_(3, 1); @@ -675,7 +677,7 @@ bool Inkplate::partial_update_() { eink_off_(); memcpy(this->buffer_, this->partial_buffer_, this->get_buffer_length_()); - ESP_LOGV(TAG, "Partial update finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Partial update finished (%" PRIu32 "ms)", millis() - start_time); return true; } @@ -730,7 +732,7 @@ void Inkplate::clean() { clean_fast_(0, 8); // Black to Black clean_fast_(2, 1); // Black to White clean_fast_(1, 10); // White to White - ESP_LOGV(TAG, "Clean finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Clean finished (%" PRIu32 "ms)", millis() - start_time); } void Inkplate::clean_fast_(uint8_t c, uint8_t rep) { @@ -773,9 +775,9 @@ void Inkplate::clean_fast_(uint8_t c, uint8_t rep) { vscan_end_(); } delayMicroseconds(230); - ESP_LOGV(TAG, "Clean fast rep loop %d finished (%ums)", k, millis() - start_time); + ESP_LOGV(TAG, "Clean fast rep loop %d finished (%" PRIu32 "ms)", k, millis() - start_time); } - ESP_LOGV(TAG, "Clean fast finished (%ums)", millis() - start_time); + ESP_LOGV(TAG, "Clean fast finished (%" PRIu32 "ms)", millis() - start_time); } void Inkplate::pins_z_state_() { diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 6230a8c30b..58c3cac42d 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -10,6 +10,7 @@ #include "esphome/core/component.h" #include "esphome/core/helpers.h" +#include <cinttypes> #include <cmath> #include <numbers> @@ -575,7 +576,7 @@ void LD2450Component::handle_periodic_data_() { if (this->get_timeout_status_(this->presence_millis_)) { this->target_binary_sensor_->publish_state(false); } else { - ESP_LOGV(TAG, "Clear presence waiting timeout: %d", this->timeout_); + ESP_LOGV(TAG, "Clear presence waiting timeout: %" PRIu32, this->timeout_); } } } diff --git a/esphome/components/max7219digit/max7219digit.cpp b/esphome/components/max7219digit/max7219digit.cpp index cdceafad50..f9b46cf797 100644 --- a/esphome/components/max7219digit/max7219digit.cpp +++ b/esphome/components/max7219digit/max7219digit.cpp @@ -6,6 +6,7 @@ #include "max7219font.h" #include <algorithm> +#include <cinttypes> namespace esphome { namespace max7219digit { @@ -92,7 +93,9 @@ void MAX7219Component::loop() { if (this->scroll_mode_ == ScrollMode::STOP) { if (static_cast<size_t>(this->stepsleft_ + get_width_internal()) == first_line_size + 1) { if (millis_since_last_scroll < this->scroll_dwell_) { - ESP_LOGVV(TAG, "Dwell time at end of string in case of stop at end. Step %d, since last scroll %d, dwell %d.", + ESP_LOGVV(TAG, + "Dwell time at end of string in case of stop at end. Step %d, since last scroll %" PRIu32 + ", dwell %d.", this->stepsleft_, millis_since_last_scroll, this->scroll_dwell_); return; } diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 4146a54c87..3b1a038be3 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -313,7 +313,7 @@ void Modbus::send_next_frame_() { this->last_send_ = millis(); this->tx_buffer_.pop_front(); if (!this->tx_buffer_.empty()) { - ESP_LOGV(TAG, "Write queue contains %" PRIu32 " items.", this->tx_buffer_.size()); + ESP_LOGV(TAG, "Write queue contains %zu items.", this->tx_buffer_.size()); } } diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 6718646efa..6c8e0f18bc 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -319,14 +319,14 @@ void Nextion::filled_circle(uint16_t center_x, uint16_t center_y, uint16_t radiu void Nextion::qrcode(uint16_t x1, uint16_t y1, const char *content, uint16_t size, uint16_t background_color, uint16_t foreground_color, int32_t logo_pic, uint8_t border_width) { this->add_no_result_to_queue_with_printf_( - "qrcode", "qrcode %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu8 ",%" PRIu8 ",\"%s\"", x1, + "qrcode", "qrcode %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRId32 ",%" PRIu8 ",\"%s\"", x1, y1, size, background_color, foreground_color, logo_pic, border_width, content); } void Nextion::qrcode(uint16_t x1, uint16_t y1, const char *content, uint16_t size, Color background_color, Color foreground_color, int32_t logo_pic, uint8_t border_width) { this->add_no_result_to_queue_with_printf_( - "qrcode", "qrcode %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu8 ",%" PRIu8 ",\"%s\"", x1, + "qrcode", "qrcode %" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRIu16 ",%" PRId32 ",%" PRIu8 ",\"%s\"", x1, y1, size, display::ColorUtil::color_to_565(background_color), display::ColorUtil::color_to_565(foreground_color), logo_pic, border_width, content); } diff --git a/esphome/components/qmp6988/qmp6988.cpp b/esphome/components/qmp6988/qmp6988.cpp index 17d91c3633..976efe7910 100644 --- a/esphome/components/qmp6988/qmp6988.cpp +++ b/esphome/components/qmp6988/qmp6988.cpp @@ -1,4 +1,6 @@ #include "qmp6988.h" + +#include <cinttypes> #include <cmath> namespace esphome { @@ -129,7 +131,7 @@ bool QMP6988Component::get_calibration_data_() { ESP_LOGV(TAG, "Calibration data:\n" - " COE_a0[%d] COE_a1[%d] COE_a2[%d] COE_b00[%d]\n" + " COE_a0[%" PRId32 "] COE_a1[%d] COE_a2[%d] COE_b00[%" PRId32 "]\n" " COE_bt1[%d] COE_bt2[%d] COE_bp1[%d] COE_b11[%d]\n" " COE_bp2[%d] COE_b12[%d] COE_b21[%d] COE_bp3[%d]", qmp6988_data_.qmp6988_cali.COE_a0, qmp6988_data_.qmp6988_cali.COE_a1, qmp6988_data_.qmp6988_cali.COE_a2, @@ -153,7 +155,7 @@ bool QMP6988Component::get_calibration_data_() { qmp6988_data_.ik.bp3 = 2915L * (int64_t) qmp6988_data_.qmp6988_cali.COE_bp3 + 157155561L; // 28Q65 ESP_LOGV(TAG, "Int calibration data:\n" - " a0[%d] a1[%d] a2[%d] b00[%d]\n" + " a0[%" PRId32 "] a1[%" PRId32 "] a2[%" PRId32 "] b00[%" PRId32 "]\n" " bt1[%lld] bt2[%lld] bp1[%lld] b11[%lld]\n" " bp2[%lld] b12[%lld] b21[%lld] bp3[%lld]", qmp6988_data_.ik.a0, qmp6988_data_.ik.a1, qmp6988_data_.ik.a2, qmp6988_data_.ik.b00, qmp6988_data_.ik.bt1, diff --git a/esphome/components/rd03d/rd03d.cpp b/esphome/components/rd03d/rd03d.cpp index d47347fcfa..c9c6a546ab 100644 --- a/esphome/components/rd03d/rd03d.cpp +++ b/esphome/components/rd03d/rd03d.cpp @@ -1,6 +1,8 @@ #include "rd03d.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" + +#include <cinttypes> #include <cmath> namespace esphome::rd03d { @@ -56,7 +58,7 @@ void RD03DComponent::dump_config() { *this->tracking_mode_ == TrackingMode::SINGLE_TARGET ? "single" : "multi"); } if (this->throttle_ > 0) { - ESP_LOGCONFIG(TAG, " Throttle: %ums", this->throttle_); + ESP_LOGCONFIG(TAG, " Throttle: %" PRIu32 "ms", this->throttle_); } #ifdef USE_SENSOR LOG_SENSOR(" ", "Target Count", this->target_count_sensor_); diff --git a/esphome/components/remote_base/symphony_protocol.cpp b/esphome/components/remote_base/symphony_protocol.cpp index f30a980d91..6844e449ed 100644 --- a/esphome/components/remote_base/symphony_protocol.cpp +++ b/esphome/components/remote_base/symphony_protocol.cpp @@ -1,6 +1,8 @@ #include "symphony_protocol.h" #include "esphome/core/log.h" +#include <cinttypes> + namespace esphome { namespace remote_base { @@ -26,8 +28,8 @@ static constexpr uint32_t INTER_FRAME_GAP_US = 34760; void SymphonyProtocol::encode(RemoteTransmitData *dst, const SymphonyData &data) { dst->set_carrier_frequency(CARRIER_FREQUENCY); - ESP_LOGD(TAG, "Sending Symphony: data=0x%0*X nbits=%u repeats=%u", (data.nbits + 3) / 4, (uint32_t) data.data, - data.nbits, data.repeats); + ESP_LOGD(TAG, "Sending Symphony: data=0x%0*" PRIX32 " nbits=%" PRIu8 " repeats=%" PRIu8, (data.nbits + 3) / 4, + (uint32_t) data.data, data.nbits, data.repeats); // Each bit produces a mark+space (2 entries). We fold the inter-frame/footer gap // into the last bit's space of each frame to avoid over-length gaps. dst->reserve(data.nbits * 2u * data.repeats); @@ -112,8 +114,8 @@ optional<SymphonyData> SymphonyProtocol::decode(RemoteReceiveData src) { } void SymphonyProtocol::dump(const SymphonyData &data) { - const int32_t hex_width = (data.nbits + 3) / 4; // pad to nibble width - ESP_LOGI(TAG, "Received Symphony: data=0x%0*X, nbits=%d", hex_width, (uint32_t) data.data, data.nbits); + const int hex_width = (data.nbits + 3) / 4; // pad to nibble width + ESP_LOGI(TAG, "Received Symphony: data=0x%0*" PRIX32 ", nbits=%" PRIu8, hex_width, (uint32_t) data.data, data.nbits); } } // namespace remote_base diff --git a/esphome/components/runtime_image/bmp_decoder.cpp b/esphome/components/runtime_image/bmp_decoder.cpp index 174f924b28..6a1bd61d86 100644 --- a/esphome/components/runtime_image/bmp_decoder.cpp +++ b/esphome/components/runtime_image/bmp_decoder.cpp @@ -6,6 +6,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cinttypes> + namespace esphome::runtime_image { static const char *const TAG = "image_decoder.bmp"; @@ -107,7 +109,7 @@ int HOT BmpDecoder::decode(uint8_t *buffer, size_t size) { } if (this->compression_method_ != 0) { - ESP_LOGE(TAG, "Unsupported compression method: %d", this->compression_method_); + ESP_LOGE(TAG, "Unsupported compression method: %" PRIu32, this->compression_method_); return DECODE_ERROR_UNSUPPORTED_FORMAT; } diff --git a/esphome/components/serial_proxy/serial_proxy.cpp b/esphome/components/serial_proxy/serial_proxy.cpp index f3c256c62a..04c94e9292 100644 --- a/esphome/components/serial_proxy/serial_proxy.cpp +++ b/esphome/components/serial_proxy/serial_proxy.cpp @@ -3,6 +3,8 @@ #ifdef USE_SERIAL_PROXY #include "esphome/core/log.h" + +#include <cinttypes> #include "esphome/core/util.h" #ifdef USE_API @@ -74,7 +76,7 @@ void __attribute__((noinline)) SerialProxy::read_and_send_(size_t available) { void SerialProxy::dump_config() { ESP_LOGCONFIG(TAG, - "Serial Proxy [%u]:\n" + "Serial Proxy [%" PRIu32 "]:\n" " Name: %s\n" " Port Type: %s\n" " RTS Pin: %s\n" @@ -89,7 +91,9 @@ void SerialProxy::dump_config() { void SerialProxy::configure(uint32_t baudrate, bool flow_control, uint8_t parity, uint8_t stop_bits, uint8_t data_size) { - ESP_LOGD(TAG, "Configuring serial proxy [%u]: baud=%u, flow_ctrl=%s, parity=%u, stop=%u, data=%u", + ESP_LOGD(TAG, + "Configuring serial proxy [%" PRIu32 "]: baud=%" PRIu32 ", flow_ctrl=%s, parity=%" PRIu8 ", stop=%" PRIu8 + ", data=%" PRIu8, this->instance_index_, baudrate, YESNO(flow_control), parity, stop_bits, data_size); auto *uart_comp = this->parent_; @@ -148,7 +152,7 @@ void SerialProxy::write_from_client(const uint8_t *data, size_t len) { void SerialProxy::set_modem_pins(uint32_t line_states) { const bool rts = (line_states & SERIAL_PROXY_LINE_STATE_FLAG_RTS) != 0; const bool dtr = (line_states & SERIAL_PROXY_LINE_STATE_FLAG_DTR) != 0; - ESP_LOGV(TAG, "Setting modem pins [%u]: RTS=%s, DTR=%s", this->instance_index_, ONOFF(rts), ONOFF(dtr)); + ESP_LOGV(TAG, "Setting modem pins [%" PRIu32 "]: RTS=%s, DTR=%s", this->instance_index_, ONOFF(rts), ONOFF(dtr)); if (this->rts_pin_ != nullptr) { this->rts_state_ = rts; @@ -161,12 +165,12 @@ void SerialProxy::set_modem_pins(uint32_t line_states) { } uint32_t SerialProxy::get_modem_pins() const { - return (this->rts_state_ ? SERIAL_PROXY_LINE_STATE_FLAG_RTS : 0u) | - (this->dtr_state_ ? SERIAL_PROXY_LINE_STATE_FLAG_DTR : 0u); + return (this->rts_state_ ? static_cast<uint32_t>(SERIAL_PROXY_LINE_STATE_FLAG_RTS) : 0u) | + (this->dtr_state_ ? static_cast<uint32_t>(SERIAL_PROXY_LINE_STATE_FLAG_DTR) : 0u); } uart::UARTFlushResult SerialProxy::flush_port() { - ESP_LOGV(TAG, "Flushing serial proxy [%u]", this->instance_index_); + ESP_LOGV(TAG, "Flushing serial proxy [%" PRIu32 "]", this->instance_index_); return this->flush(); } @@ -180,19 +184,19 @@ void SerialProxy::serial_proxy_request(api::APIConnection *api_connection, api:: } this->api_connection_ = api_connection; this->enable_loop(); - ESP_LOGV(TAG, "API connection subscribed to serial proxy [%u]", this->instance_index_); + ESP_LOGV(TAG, "API connection subscribed to serial proxy [%" PRIu32 "]", this->instance_index_); break; case api::enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE: if (this->api_connection_ != api_connection) { - ESP_LOGV(TAG, "API connection is not subscribed to serial proxy [%u]", this->instance_index_); + ESP_LOGV(TAG, "API connection is not subscribed to serial proxy [%" PRIu32 "]", this->instance_index_); return; } this->api_connection_ = nullptr; this->disable_loop(); - ESP_LOGV(TAG, "API connection unsubscribed from serial proxy [%u]", this->instance_index_); + ESP_LOGV(TAG, "API connection unsubscribed from serial proxy [%" PRIu32 "]", this->instance_index_); break; default: - ESP_LOGW(TAG, "Unknown serial proxy request type: %u", static_cast<uint32_t>(type)); + ESP_LOGW(TAG, "Unknown serial proxy request type: %" PRIu32, static_cast<uint32_t>(type)); break; } } diff --git a/esphome/components/spa06_base/spa06_base.cpp b/esphome/components/spa06_base/spa06_base.cpp index 36268aa9a2..b0490628cb 100644 --- a/esphome/components/spa06_base/spa06_base.cpp +++ b/esphome/components/spa06_base/spa06_base.cpp @@ -1,5 +1,7 @@ #include "spa06_base.h" +#include <cinttypes> + #include "esphome/core/helpers.h" namespace esphome::spa06_base { @@ -195,7 +197,7 @@ bool SPA06Component::read_coefficients_() { ESP_LOGV(TAG, "Coefficients:\n" " c0: %i, c1: %i,\n" - " c00: %i, c10: %i, c20: %i, c30: %i, c40: %i,\n" + " c00: %" PRIi32 ", c10: %" PRIi32 ", c20: %i, c30: %i, c40: %i,\n" " c01: %i, c11: %i, c21: %i, c31: %i", this->c0_, this->c1_, this->c00_, this->c10_, this->c20_, this->c30_, this->c40_, this->c01_, this->c11_, this->c21_, this->c31_); diff --git a/esphome/components/sps30/sps30.cpp b/esphome/components/sps30/sps30.cpp index dbb44743d2..e4fc4ffd31 100644 --- a/esphome/components/sps30/sps30.cpp +++ b/esphome/components/sps30/sps30.cpp @@ -2,6 +2,8 @@ #include "esphome/core/log.h" #include "sps30.h" +#include <cinttypes> + namespace esphome { namespace sps30 { @@ -105,7 +107,7 @@ void SPS30Component::dump_config() { " Firmware version v%0d.%0d", this->serial_number_, this->raw_firmware_version_ >> 8, this->raw_firmware_version_ & 0xFF); if (this->idle_interval_.has_value()) { - ESP_LOGCONFIG(TAG, " Idle interval: %us", this->idle_interval_.value() / 1000); + ESP_LOGCONFIG(TAG, " Idle interval: %" PRIu32 "s", this->idle_interval_.value() / 1000); } LOG_SENSOR(" ", "PM1.0 Weight Concentration", this->pm_1_0_sensor_); LOG_SENSOR(" ", "PM2.5 Weight Concentration", this->pm_2_5_sensor_); @@ -142,8 +144,8 @@ void SPS30Component::update() { // If its not time to take an action, do nothing. const uint32_t update_start_ms = millis(); if (this->next_state_ != NONE && (int32_t) (this->next_state_ms_ - update_start_ms) > 0) { - ESP_LOGD(TAG, "Sensor waiting for %ums before transitioning to state %d.", (this->next_state_ms_ - update_start_ms), - this->next_state_); + ESP_LOGD(TAG, "Sensor waiting for %" PRIu32 "ms before transitioning to state %d.", + (this->next_state_ms_ - update_start_ms), this->next_state_); return; } diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index eb3e756bc2..d979359c1f 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -2,6 +2,7 @@ #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cinttypes> namespace esphome::thermostat { @@ -1346,15 +1347,16 @@ void ThermostatClimate::set_timer_duration_in_sec_(ThermostatClimateTimerIndex t if (elapsed >= new_duration_ms) { // Timer should complete immediately (including when new_duration_ms is 0) - ESP_LOGVV(TAG, "timer %d completing immediately (elapsed %d >= new %d)", timer_index, elapsed, new_duration_ms); + ESP_LOGVV(TAG, "timer %d completing immediately (elapsed %" PRIu32 " >= new %" PRIu32 ")", timer_index, elapsed, + new_duration_ms); this->timer_[timer_index].active = false; // Trigger the timer callback immediately this->call_timer_callback_(timer_index); return; } else { // Adjust timer to run for remaining time - keep original start time - ESP_LOGVV(TAG, "timer %d adjusted: elapsed %d, new total %d, remaining %d", timer_index, elapsed, new_duration_ms, - new_duration_ms - elapsed); + ESP_LOGVV(TAG, "timer %d adjusted: elapsed %" PRIu32 ", new total %" PRIu32 ", remaining %" PRIu32, timer_index, + elapsed, new_duration_ms, new_duration_ms - elapsed); this->timer_[timer_index].time = new_duration_ms; return; } diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index 37a269088e..77c2e87717 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -1,3 +1,4 @@ +#include <cinttypes> #include <vector> #include "tormatic_cover.h" @@ -120,11 +121,11 @@ void Tormatic::recalibrate_duration_(GateStatus s) { if (s == OPENED) { this->open_duration_ = now - this->direction_start_time_; - ESP_LOGI(TAG, "Recalibrated the gate's open duration to %dms", this->open_duration_); + ESP_LOGI(TAG, "Recalibrated the gate's open duration to %" PRIu32 "ms", this->open_duration_); } if (s == CLOSED) { this->close_duration_ = now - this->direction_start_time_; - ESP_LOGI(TAG, "Recalibrated the gate's close duration to %dms", this->close_duration_); + ESP_LOGI(TAG, "Recalibrated the gate's close duration to %" PRIu32 "ms", this->close_duration_); } this->direction_start_time_ = 0; @@ -269,7 +270,7 @@ optional<GateStatus> Tormatic::read_gate_status_() { switch (hdr.type) { case STATUS: { if (hdr.payload_size() != sizeof(StatusReply)) { - ESP_LOGE(TAG, "Header specifies payload size %d but size of StatusReply is %d", hdr.payload_size(), + ESP_LOGE(TAG, "Header specifies payload size %" PRIu32 " but size of StatusReply is %zu", hdr.payload_size(), sizeof(StatusReply)); } @@ -294,7 +295,7 @@ optional<GateStatus> Tormatic::read_gate_status_() { default: // Unknown message type, drain the remaining amount of bytes specified in // the header. - ESP_LOGE(TAG, "Reading remaining %d payload bytes of unknown type 0x%x", hdr.payload_size(), hdr.type); + ESP_LOGE(TAG, "Reading remaining %" PRIu32 " payload bytes of unknown type 0x%x", hdr.payload_size(), hdr.type); break; } @@ -339,7 +340,7 @@ template<typename T> optional<T> Tormatic::read_data_() { } obj.byteswap(); - ESP_LOGV(TAG, "Read %s in %d ms", obj.print().c_str(), millis() - start); + ESP_LOGV(TAG, "Read %s in %" PRIu32 " ms", obj.print().c_str(), millis() - start); return obj; } diff --git a/esphome/components/tormatic/tormatic_protocol.h b/esphome/components/tormatic/tormatic_protocol.h index 26a634b630..269b63ff78 100644 --- a/esphome/components/tormatic/tormatic_protocol.h +++ b/esphome/components/tormatic/tormatic_protocol.h @@ -1,5 +1,7 @@ #pragma once +#include <cinttypes> + #include "esphome/components/cover/cover.h" /** @@ -86,7 +88,7 @@ struct MessageHeader { std::string print() { // 64 bytes: "MessageHeader: seq " + uint16 + ", len " + uint32 + ", type " + type + safety margin char buf[64]; - buf_append_printf(buf, sizeof(buf), 0, "MessageHeader: seq %d, len %d, type %s", this->seq, this->len, + buf_append_printf(buf, sizeof(buf), 0, "MessageHeader: seq %d, len %" PRIu32 ", type %s", this->seq, this->len, message_type_to_str(this->type)); return buf; } diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index cd77cd1189..6d9d44e97f 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -296,7 +296,7 @@ void IDFUARTComponent::set_rx_timeout(size_t rx_timeout) { void IDFUARTComponent::write_array(const uint8_t *data, size_t len) { int32_t write_len = uart_write_bytes(this->uart_num_, data, len); if (write_len != (int32_t) len) { - ESP_LOGW(TAG, "uart_write_bytes failed: %d != %zu", write_len, len); + ESP_LOGW(TAG, "uart_write_bytes failed: %" PRId32 " != %zu", write_len, len); this->mark_failed(); } #ifdef USE_UART_DEBUGGER diff --git a/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp b/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp index 3eae4d2d96..512a258122 100644 --- a/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp +++ b/esphome/components/uponor_smatrix/climate/uponor_smatrix_climate.cpp @@ -3,6 +3,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cinttypes> + namespace esphome { namespace uponor_smatrix { @@ -10,7 +12,7 @@ static const char *const TAG = "uponor_smatrix.climate"; void UponorSmatrixClimate::dump_config() { LOG_CLIMATE("", "Uponor Smatrix Climate", this); - ESP_LOGCONFIG(TAG, " Device address: 0x%08X", this->address_); + ESP_LOGCONFIG(TAG, " Device address: 0x%08" PRIX32, this->address_); } void UponorSmatrixClimate::loop() { diff --git a/esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp b/esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp index 7ee12edcdb..5f690a6879 100644 --- a/esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp +++ b/esphome/components/uponor_smatrix/sensor/uponor_smatrix_sensor.cpp @@ -1,6 +1,8 @@ #include "uponor_smatrix_sensor.h" #include "esphome/core/log.h" +#include <cinttypes> + namespace esphome { namespace uponor_smatrix { @@ -9,7 +11,7 @@ static const char *const TAG = "uponor_smatrix.sensor"; void UponorSmatrixSensor::dump_config() { ESP_LOGCONFIG(TAG, "Uponor Smatrix Sensor\n" - " Device address: 0x%08X", + " Device address: 0x%08" PRIX32, this->address_); LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); LOG_SENSOR(" ", "External Temperature", this->external_temperature_sensor_); diff --git a/esphome/components/uponor_smatrix/uponor_smatrix.cpp b/esphome/components/uponor_smatrix/uponor_smatrix.cpp index 4c3a4b05df..1fd53955a0 100644 --- a/esphome/components/uponor_smatrix/uponor_smatrix.cpp +++ b/esphome/components/uponor_smatrix/uponor_smatrix.cpp @@ -3,6 +3,8 @@ #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include <cinttypes> + namespace esphome { namespace uponor_smatrix { @@ -24,7 +26,7 @@ void UponorSmatrixComponent::dump_config() { #ifdef USE_TIME if (this->time_id_ != nullptr) { ESP_LOGCONFIG(TAG, " Time synchronization: YES"); - ESP_LOGCONFIG(TAG, " Time master device address: 0x%08X", this->time_device_address_); + ESP_LOGCONFIG(TAG, " Time master device address: 0x%08" PRIX32 "", this->time_device_address_); } #endif @@ -33,7 +35,7 @@ void UponorSmatrixComponent::dump_config() { if (!this->unknown_devices_.empty()) { ESP_LOGCONFIG(TAG, " Detected unknown device addresses:"); for (auto device_address : this->unknown_devices_) { - ESP_LOGCONFIG(TAG, " 0x%08X", device_address); + ESP_LOGCONFIG(TAG, " 0x%08" PRIX32 "", device_address); } } } @@ -103,14 +105,14 @@ bool UponorSmatrixComponent::parse_byte_(uint8_t byte) { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_size(UPONOR_MAX_LOG_BYTES)]; #endif - ESP_LOGV(TAG, "Received packet: addr=%08X, data=%s, crc=%04X", device_address, + ESP_LOGV(TAG, "Received packet: addr=%08" PRIX32 ", data=%s, crc=%04X", device_address, format_hex_to(hex_buf, &packet[4], packet_len - 6), crc); // Handle packet size_t data_len = (packet_len - 6) / 3; if (data_len == 0) { if (packet[4] == UPONOR_ID_REQUEST) - ESP_LOGVV(TAG, "Ignoring request packet for device 0x%08X", device_address); + ESP_LOGVV(TAG, "Ignoring request packet for device 0x%08" PRIX32 "", device_address); return true; } @@ -135,7 +137,7 @@ bool UponorSmatrixComponent::parse_byte_(uint8_t byte) { if (data[i].id == UPONOR_ID_DATETIME1) found_time = true; if (found_temperature && found_time) { - ESP_LOGI(TAG, "Using detected time device address 0x%08X", device_address); + ESP_LOGI(TAG, "Using detected time device address 0x%08" PRIX32 "", device_address); this->time_device_address_ = device_address; break; } @@ -154,7 +156,7 @@ bool UponorSmatrixComponent::parse_byte_(uint8_t byte) { // Log unknown device addresses if (!found && !this->unknown_devices_.count(device_address)) { - ESP_LOGI(TAG, "Received packet for unknown device address 0x%08X ", device_address); + ESP_LOGI(TAG, "Received packet for unknown device address 0x%08" PRIX32 " ", device_address); this->unknown_devices_.insert(device_address); } diff --git a/esphome/components/vl53l0x/vl53l0x_sensor.cpp b/esphome/components/vl53l0x/vl53l0x_sensor.cpp index 8a76ed7760..58b5a42675 100644 --- a/esphome/components/vl53l0x/vl53l0x_sensor.cpp +++ b/esphome/components/vl53l0x/vl53l0x_sensor.cpp @@ -1,6 +1,8 @@ #include "vl53l0x_sensor.h" #include "esphome/core/log.h" +#include <cinttypes> + /* * Most of the code in this integration is based on the VL53L0x library * by Pololu (Pololu Corporation), which in turn is based on the VL53L0X @@ -28,8 +30,8 @@ void VL53L0XSensor::dump_config() { LOG_PIN(" Enable Pin: ", this->enable_pin_); } ESP_LOGCONFIG(TAG, - " Timeout: %u%s\n" - " Timing Budget %uus ", + " Timeout: %" PRIu32 "%s\n" + " Timing Budget %" PRIu32 "us ", this->timeout_us_, this->timeout_us_ > 0 ? "us" : " (no timeout)", this->measurement_timing_budget_us_); } diff --git a/esphome/components/water_heater/water_heater.cpp b/esphome/components/water_heater/water_heater.cpp index 9a74877f0a..9ee8faadee 100644 --- a/esphome/components/water_heater/water_heater.cpp +++ b/esphome/components/water_heater/water_heater.cpp @@ -1,5 +1,7 @@ #include "water_heater.h" #include "esphome/core/log.h" + +#include <cinttypes> #include "esphome/core/application.h" #include "esphome/core/controller_registry.h" #include "esphome/core/progmem.h" @@ -110,7 +112,8 @@ void WaterHeaterCall::validate_() { auto traits = this->parent_->get_traits(); if (this->mode_.has_value()) { if (!traits.supports_mode(*this->mode_)) { - ESP_LOGW(TAG, "'%s' - Mode %d not supported", this->parent_->get_name().c_str(), *this->mode_); + ESP_LOGW(TAG, "'%s' - Mode %" PRIu32 " not supported", this->parent_->get_name().c_str(), + static_cast<uint32_t>(*this->mode_)); this->mode_.reset(); } } diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index ad4357663f..7653d2b678 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -3,6 +3,8 @@ #ifdef USE_API #include "esphome/components/api/api_server.h" + +#include <cinttypes> #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" @@ -160,7 +162,7 @@ void ZWaveProxy::zwave_proxy_request(api::APIConnection *api_connection, api::en break; default: - ESP_LOGW(TAG, "Unknown request type: %d", type); + ESP_LOGW(TAG, "Unknown request type: %" PRIu32, static_cast<uint32_t>(type)); break; } } From ef65e47bc58ef6df76506be39060ce9114d9e3ca Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino <glm.net@gmail.com> Date: Mon, 30 Mar 2026 21:08:50 -0300 Subject: [PATCH 1826/2030] [schema] generator fixes (#15276) --- esphome/components/sensor/__init__.py | 4 + esphome/config_validation.py | 4 + script/build_language_schema.py | 206 ++++++++++++++++++-------- 3 files changed, 151 insertions(+), 63 deletions(-) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 650f5ed826..626466eefa 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -113,6 +113,7 @@ from esphome.core.entity_helpers import ( setup_unit_of_measurement, ) from esphome.cpp_generator import MockObj, MockObjClass +from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor from esphome.util import Registry CODEOWNERS = ["@esphome/core"] @@ -229,7 +230,10 @@ _SENSOR_ENTITY_CATEGORIES = { } +@schema_extractor("enum") def sensor_entity_category(value): + if value == SCHEMA_EXTRACT: + return _SENSOR_ENTITY_CATEGORIES return cv.enum(_SENSOR_ENTITY_CATEGORIES, lower=True)(value) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 56f255a076..45d2cd8117 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -417,10 +417,14 @@ def icon(value): return value +@schema_extractor("use_id") def sub_device_id(value: str | None) -> core.ID | None: # Lazy import to avoid circular imports from esphome.core.config import Device + if value == SCHEMA_EXTRACT: + return Device + if not value: return None diff --git a/script/build_language_schema.py b/script/build_language_schema.py index bea540dc63..09ff999901 100755 --- a/script/build_language_schema.py +++ b/script/build_language_schema.py @@ -67,19 +67,16 @@ def get_component_names(): # pylint: disable-next=redefined-outer-name,reimported from esphome.loader import CORE_COMPONENTS_PATH - component_names = ["esphome", "sensor", "esp32", "esp8266"] - skip_components = [] - - for d in CORE_COMPONENTS_PATH.iterdir(): - if ( - not d.name.startswith("__") - and d.is_dir() - and d.name not in component_names - and d.name not in skip_components - ): - component_names.append(d.name) - - return sorted(component_names) + # return sorted( + # ["esphome", "sensor", "esp32", "esp8266", "adc", "touchscreen", "xpt2046"] + # ) + return sorted( + [ + d.name + for d in CORE_COMPONENTS_PATH.iterdir() + if not d.name.startswith("__") and d.is_dir() + ] + ) def load_components(): @@ -120,39 +117,57 @@ from esphome.util import Registry # noqa: E402 # pylint: enable=wrong-import-position +def sort_obj(obj): + if isinstance(obj, dict): + return {k: sort_obj(v) for k, v in sorted(obj.items(), key=lambda x: str(x[0]))} + if isinstance(obj, list): + return [sort_obj(item) for item in obj] + return obj + + def write_file(name, obj): full_path = Path(args.output_path) / f"{name}.json" + sorted_obj = sort_obj(obj) if JSON_DUMP_PRETTY: - json_str = json.dumps(obj, indent=2) + json_str = json.dumps(sorted_obj, indent=2) else: - json_str = json.dumps(obj, separators=(",", ":")) + json_str = json.dumps(sorted_obj, separators=(",", ":")) write_file_if_changed(full_path, json_str) - print(f"Wrote {full_path}") def delete_extra_files(keep_names): output_path = Path(args.output_path) + count = 0 for d in output_path.iterdir(): if d.suffix == ".json" and d.stem not in keep_names: + count += 1 d.unlink() - print(f"Deleted {d}") + return count def register_module_schemas(key, module, manifest=None): + count = 0 for name, schema in module_schemas(module): + count += 1 register_known_schema(key, name, schema) - if manifest and manifest.multi_conf and S_CONFIG_SCHEMA in output[key][S_SCHEMAS]: + if ( + manifest + and manifest.multi_conf + and key in output + and S_CONFIG_SCHEMA in output[key][S_SCHEMAS] + ): # Multi conf should allow list of components # not sure about 2nd part of the if, might be useless config (e.g. as3935) output[key][S_SCHEMAS][S_CONFIG_SCHEMA]["is_list"] = True + return count def register_known_schema(module, name, schema): if module not in output: output[module] = {S_SCHEMAS: {}} config = convert_config(schema, f"{module}/{name}") - if S_TYPE not in config: + if S_TYPE not in config and name != "FINAL_VALIDATE_SCHEMA" and module != "core": print(f"Config var without type: {module}.{name}") output[module][S_SCHEMAS][name] = config @@ -175,14 +190,23 @@ def module_schemas(module): except OSError: # some empty __init__ files module_str = "" - schemas = {} + schemas = [] for m_attr_name in dir(module): m_attr_obj = getattr(module, m_attr_name) if is_convertible_schema(m_attr_obj): - schemas[module_str.find(m_attr_name)] = [m_attr_name, m_attr_obj] + # Find where the name is assigned in the module source to preserve + # definition order. Using ^NAME\s*= (multiline) targets assignments + # at column 0, so "CONFIG_SCHEMA" won't collide with "CONFIG_SCHEMA_BASE". + match = re.search( + r"^" + re.escape(m_attr_name) + r"\s*=", + module_str, + re.MULTILINE, + ) + pos = match.start() if match else -1 + schemas.append((pos, m_attr_name, m_attr_obj)) - for pos in sorted(schemas.keys()): - yield schemas[pos] + for _, name, obj in sorted(schemas, key=lambda x: x[0]): + yield name, obj found_registries = {} @@ -240,9 +264,16 @@ def add_module_registries(domain, module): if len(parts) == 2: reg_domain = parts[0] reg_entry_name = parts[1] - else: - reg_domain = ".".join([parts[1], parts[0]]) - reg_entry_name = parts[2] + elif len(parts) == 3: + # is a platform or a component? + if parts[0] in schema_core[S_PLATFORMS]: + reg_domain = ".".join([parts[1], parts[0]]) + reg_entry_name = parts[2] + elif parts[0] in schema_core[S_COMPONENTS]: + reg_domain = parts[0] + reg_entry_name = ".".join([parts[1], parts[2]]) + else: + print(f"registry {name} is unknown") if reg_domain not in output: output[reg_domain] = {} @@ -252,8 +283,6 @@ def add_module_registries(domain, module): attr_obj[name].schema, f"{reg_domain}/{reg_type}/{reg_entry_name}" ) - # print(f"{domain} - {attr_name} - {name}") - def do_pins(): # do pin registries @@ -330,6 +359,35 @@ def fix_font(): ) +def fix_globals(): + if "globals" not in output: + return + from esphome.components.globals import _NON_RESTORING_SCHEMA + + config = convert_config(_NON_RESTORING_SCHEMA, "globals/CONFIG_SCHEMA") + config["is_list"] = True + output["globals"][S_SCHEMAS][S_CONFIG_SCHEMA] = config + + +def fix_mapping(): + if "mapping" not in output: + return + from esphome.components.mapping import BASE_SCHEMA + + config = convert_config(BASE_SCHEMA, "mapping/CONFIG_SCHEMA") + output["mapping"][S_SCHEMAS][S_CONFIG_SCHEMA] = config + + +def fix_image(): + if "image" not in output: + return + from esphome.components.image import IMAGE_SCHEMA + + config = convert_config(IMAGE_SCHEMA, "image/CONFIG_SCHEMA") + config["is_list"] = True + output["image"][S_SCHEMAS][S_CONFIG_SCHEMA] = config + + def fix_menu(): if "display_menu_base" not in output: return @@ -355,7 +413,7 @@ def fix_menu(): # 4. Configure menu items inside as recursive menu = schemas["MENU_TYPES"][S_SCHEMA][S_CONFIG_VARS]["items"]["types"]["menu"] menu[S_CONFIG_VARS].pop("items") - menu[S_EXTENDS] = ["display_menu_base.MENU_TYPES"] + menu[S_EXTENDS].append("display_menu_base.MENU_TYPES") def get_logger_tags(): @@ -531,7 +589,6 @@ def shrink(): else: arr_s.pop(S_EXTENDS) arr_s |= key_s[S_SCHEMA] - print(x) # simple types should be spread on each component, # for enums so far these are logger.is_log_level, cover.validate_cover_state and pulse_counter.sensor.COUNT_MODE_SCHEMA @@ -580,6 +637,10 @@ def shrink(): domain_schemas[S_SCHEMAS].pop(schema_name) +def is_cv_invalid(schema): + return repr(schema).startswith("<function invalid.<locals>.validator") + + def build_schema(): print("Building schema") @@ -610,7 +671,8 @@ def build_schema(): output[domain] = {S_COMPONENTS: {}, S_SCHEMAS: {}} platforms[domain] = {} elif manifest.config_schema is not None: - # e.g. dallas + if is_cv_invalid(manifest.config_schema): + continue output[domain] = {S_SCHEMAS: {S_CONFIG_SCHEMA: {}}} # Generate platforms (e.g. sensor, binary_sensor, climate ) @@ -621,7 +683,9 @@ def build_schema(): # Generate components for domain, manifest in components.items(): if domain not in platforms: - if manifest.config_schema is not None: + if manifest.config_schema is not None and not is_cv_invalid( + manifest.config_schema + ): core_components[domain] = {} if len(manifest.dependencies) > 0: core_components[domain]["dependencies"] = manifest.dependencies @@ -630,14 +694,15 @@ def build_schema(): for platform in platforms: platform_manifest = get_platform(domain=platform, platform=domain) if platform_manifest is not None: - output[platform][S_COMPONENTS][domain] = {} - if len(platform_manifest.dependencies) > 0: - output[platform][S_COMPONENTS][domain]["dependencies"] = ( - platform_manifest.dependencies - ) - register_module_schemas( + count = register_module_schemas( f"{domain}.{platform}", platform_manifest.module, platform_manifest ) + if count > 0: + output[platform][S_COMPONENTS].setdefault(domain, {}) + if len(platform_manifest.dependencies) > 0: + output[platform][S_COMPONENTS][domain]["dependencies"] = ( + platform_manifest.dependencies + ) # Do registries add_module_registries("core", automation) @@ -657,6 +722,9 @@ def build_schema(): fix_remote_receiver() fix_script() fix_font() + fix_globals() + fix_mapping() + fix_image() add_logger_tags() shrink() fix_menu() @@ -677,12 +745,19 @@ def build_schema(): # bundle core inside esphome data["esphome"]["core"] = data.pop("core")["core"] + if GENERATED_ID_TYPES: + print( + "Unconsumed id_type matchers:", + [id_type for _, id_type in GENERATED_ID_TYPES], + ) + if args.check: # do not gen files return for c, s in data.items(): write_file(c, s) - delete_extra_files(data.keys()) + deleted = delete_extra_files(data.keys()) + print(f"Written {len(data.items())} deleted {deleted} files.") def is_convertible_schema(schema): @@ -711,6 +786,30 @@ def convert_config(schema, path): return converted +GENERATED_ID_TYPES = [ + ( + lambda p: p.startswith("i2c/CONFIG_SCHEMA/") and p.endswith("/id"), + {"class": "i2c::I2CBus", "parents": ["Component"]}, + ), + ( + lambda p: p == "uart/CONFIG_SCHEMA/val 1/ext0/all/id", + {"class": "uart::UARTComponent", "parents": ["Component"]}, + ), + ( + lambda p: p == "http_request/CONFIG_SCHEMA/val 1/ext0/all/id", + {"class": "http_request::HttpRequestComponent", "parents": ["Component"]}, + ), + ( + lambda p: ( + p + == "uptime.sensor/CONFIG_SCHEMA/type_timestamp/ext0/ext1/all/time_id/val 1" + ), + {}, + ), + (lambda p: p == "esp_ldo/action/voltage.adjust/all/all/id", {}), +] + + def convert(schema, config_var, path): """config_var can be a config_var or a schema: both are dicts config_var has a S_TYPE property, if this is S_SCHEMA, then it has a S_SCHEMA property @@ -718,9 +817,6 @@ def convert(schema, config_var, path): """ repr_schema = repr(schema) - if path.startswith("ads1115.sensor") and path.endswith("gain"): - print(path) - if repr_schema in known_schemas: schema_info = known_schemas[(repr_schema)] for schema_instance, name in schema_info: @@ -841,8 +937,6 @@ def convert(schema, config_var, path): schema({"delay": "1s"}) except cv.Invalid: config_var["has_required_var"] = True - else: - print("figure out " + path) elif schema_type == "effects": config_var[S_TYPE] = "registry" config_var["registry"] = "light.effects" @@ -879,8 +973,6 @@ def convert(schema, config_var, path): "id" ]["id_type"]["class"] config_var[S_TYPE] = "use_id" - else: - print("TODO deferred?") elif isinstance(data, str): # TODO: Figure out why pipsolar does this config_var["use_id_type"] = data @@ -890,23 +982,11 @@ def convert(schema, config_var, path): else: raise TypeError("Unknown extracted schema type") elif config_var.get("key") == "GeneratedID": - if path.startswith("i2c/CONFIG_SCHEMA/") and path.endswith("/id"): - config_var["id_type"] = { - "class": "i2c::I2CBus", - "parents": ["Component"], - } - elif path == "uart/CONFIG_SCHEMA/val 1/ext0/all/id": - config_var["id_type"] = { - "class": "uart::UARTComponent", - "parents": ["Component"], - } - elif path == "http_request/CONFIG_SCHEMA/val 1/ext0/all/id": - config_var["id_type"] = { - "class": "http_request::HttpRequestComponent", - "parents": ["Component"], - } - elif path == "pins/esp32/val 1/id": - config_var["id_type"] = "pin" + for i, (matcher, id_type) in enumerate(GENERATED_ID_TYPES): + if matcher(path): + config_var["id_type"] = id_type + GENERATED_ID_TYPES.pop(i) + break else: print("Cannot determine id_type for " + path) From a3913b98ba4d41263d9022a09fb91d21b4747384 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 30 Mar 2026 17:05:48 -1000 Subject: [PATCH 1827/2030] [wifi] Move LibreTiny WiFi STA state to member variable (#15305) --- esphome/components/wifi/wifi_component.h | 8 +++--- .../wifi/wifi_component_libretiny.cpp | 25 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 9a08902d47..665dec37d5 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -818,10 +818,10 @@ class WiFiComponent final : public Component { uint8_t num_ipv6_addresses_{0}; #endif /* USE_NETWORK_IPV6 */ bool error_from_callback_{false}; -#ifdef USE_ESP8266 - // ESP8266WiFiSTAState enum, defined in wifi_component_esp8266.cpp. - // Written from SDK system context (wifi_event_callback) — uint8_t writes - // are atomic on Xtensa LX106 so no synchronization is needed. +#if defined(USE_ESP8266) || defined(USE_LIBRETINY) + // Platform-specific STA state enum, defined in platform cpp file. + // On ESP8266, written from SDK system context (wifi_event_callback) — + // uint8_t writes are atomic on Xtensa LX106 so no synchronization is needed. uint8_t sta_state_{0}; #endif RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; diff --git a/esphome/components/wifi/wifi_component_libretiny.cpp b/esphome/components/wifi/wifi_component_libretiny.cpp index b049a0413c..9565ffa747 100644 --- a/esphome/components/wifi/wifi_component_libretiny.cpp +++ b/esphome/components/wifi/wifi_component_libretiny.cpp @@ -97,8 +97,6 @@ enum class LTWiFiSTAState : uint8_t { ERROR_FAILED, // Connection failed (auth, timeout, etc.) }; -static LTWiFiSTAState s_sta_state = LTWiFiSTAState::IDLE; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - // Count of ignored disconnect events during connection - too many indicates real failure static uint8_t s_ignored_disconnect_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) // Threshold for ignored disconnect events before treating as connection failure @@ -223,7 +221,7 @@ bool WiFiComponent::wifi_sta_connect_(const WiFiAP &ap) { this->wifi_apply_hostname_(); // Reset state machine and disconnect counter before connecting - s_sta_state = LTWiFiSTAState::CONNECTING; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::CONNECTING); s_ignored_disconnect_count = 0; WiFiStatus status = WiFi.begin(ap.ssid_.c_str(), ap.password_.empty() ? NULL : ap.password_.c_str(), @@ -459,7 +457,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { } case ESPHOME_EVENT_ID_WIFI_STA_STOP: { ESP_LOGV(TAG, "STA stop"); - s_sta_state = LTWiFiSTAState::IDLE; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::IDLE); break; } case ESPHOME_EVENT_ID_WIFI_STA_CONNECTED: { @@ -479,7 +477,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // For static IP configurations, GOT_IP event may not fire, so set connected state here #ifdef USE_WIFI_MANUAL_IP if (const WiFiAP *config = this->get_selected_sta_(); config && config->get_manual_ip().has_value()) { - s_sta_state = LTWiFiSTAState::CONNECTED; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::CONNECTED); #ifdef USE_WIFI_IP_STATE_LISTENERS this->notify_ip_state_listeners_(); #endif @@ -501,12 +499,13 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { // Only ignore benign reasons - real failures like NO_AP_FOUND should still be processed. // However, if we get too many of these events (IGNORED_DISCONNECT_THRESHOLD), treat it // as a real connection failure to avoid waiting the full timeout for a failing connection. - if (it.ssid_len == 0 && s_sta_state == LTWiFiSTAState::CONNECTING && it.reason != WIFI_REASON_NO_AP_FOUND) { + if (it.ssid_len == 0 && this->sta_state_ == static_cast<uint8_t>(LTWiFiSTAState::CONNECTING) && + it.reason != WIFI_REASON_NO_AP_FOUND) { s_ignored_disconnect_count++; if (s_ignored_disconnect_count >= IGNORED_DISCONNECT_THRESHOLD) { ESP_LOGW(TAG, "Too many disconnect events (%u) while connecting, treating as failure (reason=%s)", s_ignored_disconnect_count, get_disconnect_reason_str(it.reason)); - s_sta_state = LTWiFiSTAState::ERROR_FAILED; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::ERROR_FAILED); WiFi.disconnect(); this->error_from_callback_ = true; // Don't break - fall through to notify listeners @@ -520,13 +519,13 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { if (it.reason == WIFI_REASON_NO_AP_FOUND) { ESP_LOGW(TAG, "Disconnected ssid='%.*s' reason='Probe Request Unsuccessful'", it.ssid_len, (const char *) it.ssid); - s_sta_state = LTWiFiSTAState::ERROR_NOT_FOUND; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::ERROR_NOT_FOUND); } else { char bssid_s[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; format_mac_addr_upper(it.bssid, bssid_s); ESP_LOGW(TAG, "Disconnected ssid='%.*s' bssid=" LOG_SECRET("%s") " reason='%s'", it.ssid_len, (const char *) it.ssid, bssid_s, get_disconnect_reason_str(it.reason)); - s_sta_state = LTWiFiSTAState::ERROR_FAILED; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::ERROR_FAILED); } uint8_t reason = it.reason; @@ -551,7 +550,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { ESP_LOGW(TAG, "Potential Authmode downgrade detected, disconnecting"); WiFi.disconnect(); this->error_from_callback_ = true; - s_sta_state = LTWiFiSTAState::ERROR_FAILED; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::ERROR_FAILED); } break; } @@ -559,7 +558,7 @@ void WiFiComponent::wifi_process_event_(LTWiFiEvent *event) { char ip_buf[network::IP_ADDRESS_BUFFER_SIZE], gw_buf[network::IP_ADDRESS_BUFFER_SIZE]; ESP_LOGV(TAG, "static_ip=%s gateway=%s", network::IPAddress(WiFi.localIP()).str_to(ip_buf), network::IPAddress(WiFi.gatewayIP()).str_to(gw_buf)); - s_sta_state = LTWiFiSTAState::CONNECTED; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::CONNECTED); #ifdef USE_WIFI_IP_STATE_LISTENERS this->notify_ip_state_listeners_(); #endif @@ -637,7 +636,7 @@ void WiFiComponent::wifi_pre_setup_() { WiFiSTAConnectStatus WiFiComponent::wifi_sta_connect_status_() const { // Use state machine instead of querying WiFi.status() directly // State is updated in main loop from queued events, ensuring thread safety - switch (s_sta_state) { + switch (static_cast<LTWiFiSTAState>(this->sta_state_)) { case LTWiFiSTAState::CONNECTED: return WiFiSTAConnectStatus::CONNECTED; case LTWiFiSTAState::ERROR_NOT_FOUND: @@ -758,7 +757,7 @@ network::IPAddress WiFiComponent::wifi_soft_ap_ip() { return {WiFi.softAPIP()}; bool WiFiComponent::wifi_disconnect_() { // Reset state first so disconnect events aren't ignored // and wifi_sta_connect_status_() returns IDLE instead of CONNECTING - s_sta_state = LTWiFiSTAState::IDLE; + this->sta_state_ = static_cast<uint8_t>(LTWiFiSTAState::IDLE); return WiFi.disconnect(); } From ceb3cb2ae797611e73f14f3887df812778600ed6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:22:29 -0400 Subject: [PATCH 1828/2030] [haier] Fix hOn half-degree temperature setting (#15312) --- esphome/components/haier/hon_climate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index 1cee95bf16..1e9cb42f38 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -675,7 +675,6 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { this->quiet_mode_state_ = (SwitchState) ((uint8_t) this->quiet_mode_state_ & 0b01); } out_data->beeper_status = ((!this->get_beeper_state()) || (!has_hvac_settings)) ? 1 : 0; - control_out_buffer[4] = 0; // This byte should be cleared before setting values out_data->display_status = this->get_display_state() ? 1 : 0; this->display_status_ = (SwitchState) ((uint8_t) this->display_status_ & 0b01); out_data->health_mode = this->get_health_mode() ? 1 : 0; From c64bc2496093dfd0f107e15473adff8437574cc9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 07:34:54 -1000 Subject: [PATCH 1829/2030] [preferences] Reduce log verbosity for unchanged NVS/FDB writes (#15332) --- esphome/components/esp32/preferences.cpp | 12 ++++++++---- esphome/components/libretiny/preferences.cpp | 13 +++++++++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/esphome/components/esp32/preferences.cpp b/esphome/components/esp32/preferences.cpp index e88ace3e6b..bc0a34ebe8 100644 --- a/esphome/components/esp32/preferences.cpp +++ b/esphome/components/esp32/preferences.cpp @@ -129,11 +129,15 @@ bool ESP32Preferences::sync() { } s_pending_save.clear(); - ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, - failed); if (failed > 0) { - ESP_LOGE(TAG, "Writing %d items failed. Last error=%s for key=%" PRIu32, failed, esp_err_to_name(last_err), - last_key); + ESP_LOGE(TAG, "Writing %d items: %d cached, %d written, %d failed. Last error=%s for key=%" PRIu32, + cached + written + failed, cached, written, failed, esp_err_to_name(last_err), last_key); + } else if (written > 0) { + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); + } else { + ESP_LOGV(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); } // note: commit on esp-idf currently is a no-op, nvs_set_blob always writes diff --git a/esphome/components/libretiny/preferences.cpp b/esphome/components/libretiny/preferences.cpp index 344ca4a8b3..fba6717294 100644 --- a/esphome/components/libretiny/preferences.cpp +++ b/esphome/components/libretiny/preferences.cpp @@ -108,16 +108,21 @@ bool LibreTinyPreferences::sync() { } written++; } else { - ESP_LOGD(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.data.size()); + ESP_LOGV(TAG, "FDB data not changed; skipping %" PRIu32 " len=%zu", save.key, save.data.size()); cached++; } } s_pending_save.clear(); - ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, - failed); if (failed > 0) { - ESP_LOGE(TAG, "Writing %d items failed. Last error=%d for key=%" PRIu32, failed, last_err, last_key); + ESP_LOGE(TAG, "Writing %d items: %d cached, %d written, %d failed. Last error=%d for key=%" PRIu32, + cached + written + failed, cached, written, failed, last_err, last_key); + } else if (written > 0) { + ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); + } else { + ESP_LOGV(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written, + failed); } return failed == 0; From 9b97e95cf3620dc3aad8715e011ec1b89cdbf112 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 07:42:12 -1000 Subject: [PATCH 1830/2030] [binary_sensor] Add on_multi_click integration test (#15329) --- .../fixtures/multi_click_trigger.yaml | 105 ++++++++++++++++++ tests/integration/test_multi_click_trigger.py | 82 ++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 tests/integration/fixtures/multi_click_trigger.yaml create mode 100644 tests/integration/test_multi_click_trigger.py diff --git a/tests/integration/fixtures/multi_click_trigger.yaml b/tests/integration/fixtures/multi_click_trigger.yaml new file mode 100644 index 0000000000..3bd53d594c --- /dev/null +++ b/tests/integration/fixtures/multi_click_trigger.yaml @@ -0,0 +1,105 @@ +esphome: + name: test-multi-click + +host: +api: + batch_delay: 0ms + services: + - service: run_all_tests + then: + # Prime the binary sensor with an initial OFF state. + # trigger_on_initial_state defaults to false, so the first + # state change from unknown won't fire callbacks. + - binary_sensor.template.publish: + id: test_button + state: false + - delay: 50ms + + # Test 1: Single click (ON < 50ms, OFF >= 30ms) + - binary_sensor.template.publish: + id: test_button + state: true + - delay: 20ms + - binary_sensor.template.publish: + id: test_button + state: false + # Wait for single click trigger (30ms) + cooldown (100ms) + margin + - delay: 200ms + + # Test 2: Double click (ON < 50ms, OFF < 25ms, ON < 50ms, OFF >= 25ms) + - binary_sensor.template.publish: + id: test_button + state: true + - delay: 20ms + - binary_sensor.template.publish: + id: test_button + state: false + - delay: 15ms + - binary_sensor.template.publish: + id: test_button + state: true + - delay: 20ms + - binary_sensor.template.publish: + id: test_button + state: false + # Wait for double click trigger (25ms) + cooldown (100ms) + margin + - delay: 200ms + + # Test 3: Long press (ON >= 80ms) + - binary_sensor.template.publish: + id: test_button + state: true + - delay: 100ms + - binary_sensor.template.publish: + id: test_button + state: false + +logger: + level: VERBOSE + +globals: + - id: single_click_count + type: int + initial_value: "0" + - id: double_click_count + type: int + initial_value: "0" + - id: long_press_count + type: int + initial_value: "0" + +binary_sensor: + - platform: template + name: "Test Button" + id: test_button + on_multi_click: + # Single press + - timing: + - ON for at most 50ms + - OFF for at least 30ms + invalid_cooldown: 100ms + then: + - lambda: |- + id(single_click_count) += 1; + ESP_LOGI("multi_click_test", "SINGLE_CLICK count=%d", id(single_click_count)); + + # Double press + - timing: + - ON for at most 50ms + - OFF for at most 25ms + - ON for at most 50ms + - OFF for at least 25ms + invalid_cooldown: 100ms + then: + - lambda: |- + id(double_click_count) += 1; + ESP_LOGI("multi_click_test", "DOUBLE_CLICK count=%d", id(double_click_count)); + + # Long press + - timing: + - ON for at least 80ms + invalid_cooldown: 100ms + then: + - lambda: |- + id(long_press_count) += 1; + ESP_LOGI("multi_click_test", "LONG_PRESS count=%d", id(long_press_count)); diff --git a/tests/integration/test_multi_click_trigger.py b/tests/integration/test_multi_click_trigger.py new file mode 100644 index 0000000000..8a020dd18b --- /dev/null +++ b/tests/integration/test_multi_click_trigger.py @@ -0,0 +1,82 @@ +"""Integration test for on_multi_click binary sensor automation. + +Tests that on_multi_click correctly triggers for single click, double click, +and long press patterns using a template binary sensor with timing +orchestrated entirely in YAML. + +""" + +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_multi_click_trigger( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that on_multi_click triggers for single, double, and long press patterns.""" + loop = asyncio.get_running_loop() + + single_click_pattern = re.compile(r"SINGLE_CLICK count=(\d+)") + double_click_pattern = re.compile(r"DOUBLE_CLICK count=(\d+)") + long_press_pattern = re.compile(r"LONG_PRESS count=(\d+)") + + single_click_future: asyncio.Future[int] = loop.create_future() + double_click_future: asyncio.Future[int] = loop.create_future() + long_press_future: asyncio.Future[int] = loop.create_future() + + def check_output(line: str) -> None: + """Check log output for multi-click trigger messages.""" + if m := single_click_pattern.search(line): + if not single_click_future.done(): + single_click_future.set_result(int(m.group(1))) + elif m := double_click_pattern.search(line): + if not double_click_future.done(): + double_click_future.set_result(int(m.group(1))) + elif (m := long_press_pattern.search(line)) and not long_press_future.done(): + long_press_future.set_result(int(m.group(1))) + + async with ( + run_compiled(yaml_config, line_callback=check_output), + api_client_connected() as client, + ): + _entities, services = await client.list_entities_services() + + test_service = next((s for s in services if s.name == "run_all_tests"), None) + assert test_service is not None, "run_all_tests service not found" + + # Kick off the entire test sequence (runs in YAML with delays) + await client.execute_service(test_service, {}) + + # Wait for all three triggers + try: + count = await asyncio.wait_for(single_click_future, timeout=5.0) + except TimeoutError: + pytest.fail( + "Timeout waiting for SINGLE_CLICK - on_multi_click did not trigger." + ) + assert count == 1, f"Expected single click count=1, got {count}" + + try: + count = await asyncio.wait_for(double_click_future, timeout=5.0) + except TimeoutError: + pytest.fail( + "Timeout waiting for DOUBLE_CLICK - on_multi_click did not trigger." + ) + assert count == 1, f"Expected double click count=1, got {count}" + + try: + count = await asyncio.wait_for(long_press_future, timeout=5.0) + except TimeoutError: + pytest.fail( + "Timeout waiting for LONG_PRESS - on_multi_click did not trigger." + ) + assert count == 1, f"Expected long press count=1, got {count}" From 2c9a3051d6e90e6a89da2a08d52d93160288c300 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 07:43:18 -1000 Subject: [PATCH 1831/2030] [api] Use memcpy for fixed32 decode on little-endian platforms (#15292) --- esphome/components/api/proto.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 4f5b3f0918..d9fe0fe461 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -257,7 +257,13 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); return; } - uint32_t val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); + uint32_t val; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + // Protobuf fixed32 is little-endian — direct load on LE platforms + memcpy(&val, ptr, 4); +#else + val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); +#endif if (!this->decode_32bit(field_id, Proto32Bit(val))) { ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val); } From 2449aa75af91ba01b3b812d5fde43d73eb918d5a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 07:45:23 -1000 Subject: [PATCH 1832/2030] [http_request] Fix crash when esp_http_client_init fails (#15328) --- .../http_request/http_request_idf.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/esphome/components/http_request/http_request_idf.cpp b/esphome/components/http_request/http_request_idf.cpp index dda61e2400..30f53eecdc 100644 --- a/esphome/components/http_request/http_request_idf.cpp +++ b/esphome/components/http_request/http_request_idf.cpp @@ -17,6 +17,7 @@ namespace esphome::http_request { static const char *const TAG = "http_request.idf"; +static constexpr uint32_t ERROR_DURATION_MS = 1000; struct UserData { const std::vector<std::string> &lower_case_collect_headers; @@ -57,7 +58,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c const std::vector<Header> &request_headers, const std::vector<std::string> &lower_case_collect_headers) { if (!network::is_connected()) { - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); ESP_LOGE(TAG, "HTTP Request failed; Not connected to network"); return nullptr; } @@ -74,7 +75,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c } else if (method == "PATCH") { method_idf = HTTP_METHOD_PATCH; } else { - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); ESP_LOGE(TAG, "HTTP Request failed; Unsupported method"); return nullptr; } @@ -112,6 +113,11 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c config.event_handler = http_event_handler; esp_http_client_handle_t client = esp_http_client_init(&config); + if (client == nullptr) { + this->status_momentary_error("failed", ERROR_DURATION_MS); + ESP_LOGE(TAG, "HTTP Request failed; client could not be initialized"); + return nullptr; + } std::shared_ptr<HttpContainerIDF> container = std::make_shared<HttpContainerIDF>(client); container->set_parent(this); @@ -129,7 +135,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c esp_err_t err = esp_http_client_open(client, body_len); if (err != ESP_OK) { - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); esp_http_client_cleanup(client); return nullptr; @@ -151,7 +157,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c } if (err != ESP_OK) { - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); ESP_LOGE(TAG, "HTTP Request failed: %s", esp_err_to_name(err)); esp_http_client_cleanup(client); return nullptr; @@ -176,7 +182,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c err = esp_http_client_set_redirection(client); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_http_client_set_redirection failed: %s", esp_err_to_name(err)); - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); esp_http_client_cleanup(client); return nullptr; } @@ -189,7 +195,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c err = esp_http_client_open(client, 0); if (err != ESP_OK) { ESP_LOGE(TAG, "esp_http_client_open failed: %s", esp_err_to_name(err)); - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); esp_http_client_cleanup(client); return nullptr; } @@ -214,7 +220,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::perform(const std::string &url, c } ESP_LOGE(TAG, "HTTP Request failed; URL: %s; Code: %d", url.c_str(), container->status_code); - this->status_momentary_error("failed", 1000); + this->status_momentary_error("failed", ERROR_DURATION_MS); return container; } From 26b426bbffd28611d0ff4880b4196c8a0bde4d13 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Tue, 31 Mar 2026 14:34:16 -0500 Subject: [PATCH 1833/2030] [zwave_proxy] Clear Home ID on USB modem disconnect (#15327) --- esphome/components/uart/uart_component.h | 4 + esphome/components/usb_uart/usb_uart.h | 1 + .../components/zwave_proxy/zwave_proxy.cpp | 76 +++++++++++++++++-- esphome/components/zwave_proxy/zwave_proxy.h | 6 ++ 4 files changed, 80 insertions(+), 7 deletions(-) diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index abc77fbae8..afd3ad5777 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -85,6 +85,10 @@ class UARTComponent { // @return UARTFlushResult indicating whether the flush was confirmed, timed out, failed, or assumed successful. virtual UARTFlushResult flush() = 0; + // Returns true if the underlying transport is connected and operational. + // Hardware UARTs always return true. USB-backed UARTs override to reflect actual connection state. + virtual bool is_connected() { return true; } + // Sets the maximum time to wait for TX to drain during flush(). // Only meaningful on ESP32 (IDF). Other platforms ignore this value. // @param flush_timeout_ms Timeout in milliseconds; 0 means wait indefinitely. diff --git a/esphome/components/usb_uart/usb_uart.h b/esphome/components/usb_uart/usb_uart.h index 8a47f0cf4b..8e8e65032d 100644 --- a/esphome/components/usb_uart/usb_uart.h +++ b/esphome/components/usb_uart/usb_uart.h @@ -140,6 +140,7 @@ class USBUartChannel : public uart::UARTComponent, public Parented<USBUartCompon bool peek_byte(uint8_t *data) override; bool read_array(uint8_t *data, size_t len) override; size_t available() override { return this->input_buffer_.get_available(); } + bool is_connected() override { return this->initialised_.load(); } uart::UARTFlushResult flush() override; void check_logger_conflict() override {} void set_parity(UARTParityOptions parity) { this->parity_ = parity; } diff --git a/esphome/components/zwave_proxy/zwave_proxy.cpp b/esphome/components/zwave_proxy/zwave_proxy.cpp index 7653d2b678..ecb38b25e7 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.cpp +++ b/esphome/components/zwave_proxy/zwave_proxy.cpp @@ -22,6 +22,8 @@ static constexpr uint8_t ZWAVE_COMMAND_GET_NETWORK_IDS = 0x20; static constexpr uint8_t ZWAVE_COMMAND_TYPE_RESPONSE = 0x01; // Response type field value static constexpr uint8_t ZWAVE_MIN_GET_NETWORK_IDS_LENGTH = 9; // TYPE + CMD + HOME_ID(4) + NODE_ID + checksum static constexpr uint32_t HOME_ID_TIMEOUT_MS = 100; // Timeout for waiting for home ID during setup +static constexpr uint32_t RECONNECT_DELAY_MS = 500; // Delay between home ID query attempts after reconnect +static constexpr uint8_t MAX_QUERY_RETRIES = 5; // Max attempts to query home ID after reconnect static uint8_t calculate_frame_checksum(const uint8_t *data, uint8_t length) { // Calculate Z-Wave frame checksum @@ -38,7 +40,10 @@ ZWaveProxy::ZWaveProxy() { global_zwave_proxy = this; } void ZWaveProxy::setup() { this->setup_time_ = App.get_loop_component_start_time(); - this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS); + this->was_connected_ = this->parent_->is_connected(); + if (this->was_connected_) { + this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS); + } } float ZWaveProxy::get_setup_priority() const { @@ -84,6 +89,14 @@ void ZWaveProxy::loop() { this->api_connection_ = nullptr; // Unsubscribe if disconnected } + const bool connected = this->parent_->is_connected(); + if (this->was_connected_ != connected) { + this->on_connection_changed_(connected); + } + if (this->reconnect_time_ != 0) { + this->retry_home_id_query_(); + } + this->process_uart_(); this->status_clear_warning(); } @@ -167,6 +180,55 @@ void ZWaveProxy::zwave_proxy_request(api::APIConnection *api_connection, api::en } } +void ZWaveProxy::on_connection_changed_(bool connected) { + this->was_connected_ = connected; + if (connected) { + ESP_LOGD(TAG, "Modem reconnected"); + this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START; + this->buffer_index_ = 0; + this->last_response_ = 0; + this->in_bootloader_ = false; + // Defer the query — the modem needs time to initialize after power is applied + this->reconnect_time_ = App.get_loop_component_start_time(); + this->query_retries_ = 0; + } else { + ESP_LOGW(TAG, "Modem disconnected"); + this->clear_home_id_(); + } +} + +void ZWaveProxy::retry_home_id_query_() { + if (this->home_id_ready_) { + // Got the home ID, cancel remaining retries + this->reconnect_time_ = 0; + return; + } + if (App.get_loop_component_start_time() - this->reconnect_time_ <= RECONNECT_DELAY_MS) { + return; // Not yet time for next attempt + } + this->reconnect_time_ = App.get_loop_component_start_time(); // Reset timer for next retry + this->query_retries_++; + if (this->query_retries_ <= MAX_QUERY_RETRIES) { + ESP_LOGD(TAG, "Querying Home ID (attempt %u)", this->query_retries_); + this->send_simple_command_(ZWAVE_COMMAND_GET_NETWORK_IDS); + } else { + ESP_LOGW(TAG, "Failed to read Home ID after %u attempts", MAX_QUERY_RETRIES); + this->reconnect_time_ = 0; + } +} + +void ZWaveProxy::clear_home_id_() { + static constexpr uint8_t ZERO_HOME_ID[ZWAVE_HOME_ID_SIZE] = {}; + if (this->set_home_id_(ZERO_HOME_ID)) { + this->send_homeid_changed_msg_(); + } + this->home_id_ready_ = false; + this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START; + this->buffer_index_ = 0; + this->last_response_ = 0; + this->in_bootloader_ = false; +} + bool ZWaveProxy::set_home_id_(const uint8_t *new_home_id) { if (std::memcmp(this->home_id_.data(), new_home_id, this->home_id_.size()) == 0) { ESP_LOGV(TAG, "Home ID unchanged"); @@ -309,7 +371,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) { this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_START; switch (byte) { case ZWAVE_FRAME_TYPE_START: - ESP_LOGVV(TAG, "Received START"); + ESP_LOGV(TAG, "Received START"); if (this->in_bootloader_) { ESP_LOGD(TAG, "Exited bootloader mode"); this->in_bootloader_ = false; @@ -318,7 +380,7 @@ void ZWaveProxy::parse_start_(uint8_t byte) { this->parsing_state_ = ZWAVE_PARSING_STATE_WAIT_LENGTH; return; case ZWAVE_FRAME_TYPE_BL_MENU: - ESP_LOGVV(TAG, "Received BL_MENU"); + ESP_LOGV(TAG, "Received BL_MENU"); if (!this->in_bootloader_) { ESP_LOGD(TAG, "Entered bootloader mode"); this->in_bootloader_ = true; @@ -327,16 +389,16 @@ void ZWaveProxy::parse_start_(uint8_t byte) { this->parsing_state_ = ZWAVE_PARSING_STATE_READ_BL_MENU; return; case ZWAVE_FRAME_TYPE_BL_BEGIN_UPLOAD: - ESP_LOGVV(TAG, "Received BL_BEGIN_UPLOAD"); + ESP_LOGV(TAG, "Received BL_BEGIN_UPLOAD"); break; case ZWAVE_FRAME_TYPE_ACK: - ESP_LOGVV(TAG, "Received ACK"); + ESP_LOGV(TAG, "Received ACK"); break; case ZWAVE_FRAME_TYPE_NAK: - ESP_LOGW(TAG, "Received NAK"); + ESP_LOGV(TAG, "Received NAK"); break; case ZWAVE_FRAME_TYPE_CAN: - ESP_LOGW(TAG, "Received CAN"); + ESP_LOGV(TAG, "Received CAN"); break; default: ESP_LOGW(TAG, "Unrecognized START: 0x%02X", byte); diff --git a/esphome/components/zwave_proxy/zwave_proxy.h b/esphome/components/zwave_proxy/zwave_proxy.h index 12cb9a90a1..0b810de29f 100644 --- a/esphome/components/zwave_proxy/zwave_proxy.h +++ b/esphome/components/zwave_proxy/zwave_proxy.h @@ -65,6 +65,9 @@ class ZWaveProxy : public uart::UARTDevice, public Component { protected: bool set_home_id_(const uint8_t *new_home_id); // Store a new home ID. Returns true if it changed. + void clear_home_id_(); // Clear home ID and notify API clients + void on_connection_changed_(bool connected); // Handle modem connect/disconnect transitions + void retry_home_id_query_(); // Retry home ID query after reconnect void send_homeid_changed_msg_(api::APIConnection *conn = nullptr); void send_simple_command_(uint8_t command_id); bool parse_byte_(uint8_t byte); // Returns true if frame parsing was completed (a frame is ready in the buffer) @@ -80,14 +83,17 @@ class ZWaveProxy : public uart::UARTDevice, public Component { // Pointers and 32-bit values (aligned together) api::APIConnection *api_connection_{nullptr}; // Current subscribed client uint32_t setup_time_{0}; // Time when setup() was called + uint32_t reconnect_time_{0}; // Timestamp of reconnect detection (0 = no pending query) // Small values (grouped by size to minimize padding) uint16_t buffer_index_{0}; // Index for populating the data buffer uint16_t end_frame_after_{0}; // Payload reception ends after this index uint8_t last_response_{0}; // Last response type sent + uint8_t query_retries_{0}; // Number of home ID query attempts after reconnect ZWaveParsingState parsing_state_{ZWAVE_PARSING_STATE_WAIT_START}; bool in_bootloader_{false}; // True if the device is detected to be in bootloader mode bool home_id_ready_{false}; // True when home ID has been received from Z-Wave module + bool was_connected_{false}; // Previous UART connection state for edge detection }; extern ZWaveProxy *global_zwave_proxy; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) From da6c4e20fef3f92dfc25ecd5f34df76d2c8baf1a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 1 Apr 2026 06:29:57 +1000 Subject: [PATCH 1834/2030] [lvgl] Fixes #2 (#15161) --- esphome/components/lvgl/automation.py | 4 +- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/lvcode.py | 5 -- esphome/components/lvgl/lvgl_esphome.cpp | 26 ++++---- esphome/components/lvgl/number/__init__.py | 4 +- esphome/components/lvgl/schemas.py | 67 ++++++++++++++++----- esphome/components/lvgl/switch/__init__.py | 4 +- esphome/components/lvgl/text/__init__.py | 4 +- esphome/components/lvgl/trigger.py | 3 + esphome/components/lvgl/widgets/meter.py | 63 ++++++++++--------- esphome/components/lvgl/widgets/tileview.py | 2 +- tests/components/lvgl/lvgl-package.yaml | 34 ++++++++++- 12 files changed, 145 insertions(+), 72 deletions(-) diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 24579e5be8..50e6db74b8 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -136,7 +136,7 @@ async def update_to_code(config, action_id, template_arg, args): widget.type.w_type.value_property is not None and widget.type.w_type.value_property in config ): - lv.event_send(widget.obj, UPDATE_EVENT, nullptr) + lv_obj.send_event(widget.obj, UPDATE_EVENT, nullptr) widgets = await get_widgets(config[CONF_ID]) return await action_to_code( @@ -455,6 +455,6 @@ async def obj_refresh_to_code(config, action_id, template_arg, args): widget.type.w_type.value_property is not None and widget.type.w_type.value_property in config ): - lv.event_send(widget.obj, UPDATE_EVENT, nullptr) + lv_obj.send_event(widget.obj, UPDATE_EVENT, nullptr) return await action_to_code(widget, do_refresh, action_id, template_arg, args) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 72345ca98e..de5835d7a6 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -541,6 +541,7 @@ CONF_END_ANGLE = "end_angle" CONF_END_VALUE = "end_value" CONF_ENTER_BUTTON = "enter_button" CONF_ENTRIES = "entries" +CONF_EXT_CLICK_AREA = "ext_click_area" CONF_FLAGS = "flags" CONF_FLEX_FLOW = "flex_flow" CONF_FLEX_ALIGN_MAIN = "flex_align_main" diff --git a/esphome/components/lvgl/lvcode.py b/esphome/components/lvgl/lvcode.py index 146b261f26..eb8f7d4437 100644 --- a/esphome/components/lvgl/lvcode.py +++ b/esphome/components/lvgl/lvcode.py @@ -253,14 +253,10 @@ class MockLv: A mock object that can be used to generate LVGL calls. """ - # Mapping for LVGL 9 - ATTR_MAP = {"event_send": "obj_send_event", "dither": "bg_dither_mode"} - def __init__(self, base): self.base = base def __getattr__(self, attr: str) -> "MockLv": - attr = MockLv.ATTR_MAP.get(attr, attr) return MockLv(f"{self.base}{attr}") def append(self, expression): @@ -314,7 +310,6 @@ class ReturnStatement(ExpressionStatement): class LvExpr(MockLv): def __getattr__(self, attr: str) -> "MockLv": - attr = MockLv.ATTR_MAP.get(attr, attr) return LvExpr(f"{self.base}{attr}") def append(self, expression): diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index bf86a4e9ee..a5075cb614 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -343,26 +343,26 @@ void IndicatorLine::set_value(int value) { } void IndicatorLine::update_length_() { - uint32_t actual_needle_length; - auto radius = lv_obj_get_width(lv_obj_get_parent(this->obj)) / 2; + auto cx = lv_obj_get_width(lv_obj_get_parent(this->obj)) / 2; + auto cy = lv_obj_get_height(lv_obj_get_parent(this->obj)) / 2; + auto radius = clamp_at_most(cx, cy); auto length = lv_obj_get_style_length(this->obj, LV_PART_MAIN); auto radial_offset = lv_obj_get_style_radial_offset(this->obj, LV_PART_MAIN); if (LV_COORD_IS_PCT(radial_offset)) { radial_offset = radius * LV_COORD_GET_PCT(radial_offset) / 100; } if (LV_COORD_IS_PCT(length)) { - actual_needle_length = radius * LV_COORD_GET_PCT(length) / 100; + length = radius * LV_COORD_GET_PCT(length) / 100; } else if (length < 0) { - actual_needle_length = radius + length; - } else { - actual_needle_length = length; + length += radius; } auto x = lv_trigo_cos(this->angle_) / 32768.0f; auto y = lv_trigo_sin(this->angle_) / 32768.0f; + // radius here also represents the offset of the scale center from top left this->points_[0].x = radius + radial_offset * x; this->points_[0].y = radius + radial_offset * y; - this->points_[1].x = x * actual_needle_length + radius; - this->points_[1].y = y * actual_needle_length + radius; + this->points_[1].x = radius + x * (radial_offset + length); + this->points_[1].y = radius + y * (radial_offset + length); lv_obj_refresh_self_size(this->obj); lv_obj_invalidate(this->obj); } @@ -682,15 +682,15 @@ void lv_scale_draw_event_cb(lv_event_t *e, int16_t range_start, int16_t range_en auto *line_dsc = static_cast<lv_draw_line_dsc_t *>(lv_draw_task_get_draw_dsc(task)); int tick = line_dsc->base.id2; if (tick >= range_start && tick <= range_end) { - unsigned range = range_end - range_start; + int ratio; if (local) { + int range = range_end - range_start; tick -= range_start; + ratio = range == 0 ? 0 : (tick * 255) / range; } else { - range = lv_scale_get_total_tick_count(scale) - 1; + // total tick count is guaranteed to be at least 2. + ratio = (line_dsc->base.id1 * 255) / (lv_scale_get_total_tick_count(scale) - 1); } - if (range == 0) - range = 1; - auto ratio = (tick * 255) / range; line_dsc->color = lv_color_mix(color_end, color_start, ratio); line_dsc->width += width; } diff --git a/esphome/components/lvgl/number/__init__.py b/esphome/components/lvgl/number/__init__.py index c48e051eac..d80e93708b 100644 --- a/esphome/components/lvgl/number/__init__.py +++ b/esphome/components/lvgl/number/__init__.py @@ -12,7 +12,7 @@ from ..lvcode import ( UPDATE_EVENT, LambdaContext, ReturnStatement, - lv, + lv_obj, lvgl_static, ) from ..types import LV_EVENT, LvNumber, lvgl_ns @@ -40,7 +40,7 @@ async def to_code(config): await widget.set_property( "value", MockObj("v") * MockObj(widget.get_scale()), config[CONF_ANIMATED] ) - lv.event_send(widget.obj, API_EVENT, cg.nullptr) + lv_obj.send_event(widget.obj, API_EVENT, cg.nullptr) event_code = ( LV_EVENT.VALUE_CHANGED if not config[CONF_UPDATE_ON_RELEASE] diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index bcbb193ce3..9c9504f05f 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -146,26 +146,41 @@ def point_schema(value): # All LVGL styles and their validators -STYLE_PROPS = { +BASE_PROPS = { "align": df.CHILD_ALIGNMENTS.one_of, - "arc_opa": lvalid.opacity, + "anim_duration": lvalid.lv_milliseconds, "arc_color": lvalid.lv_color, + "arc_opa": lvalid.opacity, "arc_rounded": lvalid.lv_bool, "arc_width": lvalid.pixels, - "anim_time": lvalid.lv_milliseconds, + "base_dir": df.LvConstant("LV_BASE_DIR_", "LTR", "RTL", "AUTO").one_of, "bg_color": lvalid.lv_color, "bg_grad": lv_gradient, "bg_grad_color": lvalid.lv_color, - "bg_dither_mode": df.LvConstant("LV_DITHER_", "NONE", "ORDERED", "ERR_DIFF").one_of, "bg_grad_dir": LV_GRAD_DIR.one_of, + "bg_grad_opa": lvalid.opacity, "bg_grad_stop": lvalid.stop_value, "bg_image_opa": lvalid.opacity, "bg_image_recolor": lvalid.lv_color, "bg_image_recolor_opa": lvalid.opacity, "bg_image_src": lvalid.lv_image, "bg_image_tiled": lvalid.lv_bool, + "bg_main_opa": lvalid.opacity, "bg_main_stop": lvalid.stop_value, "bg_opa": lvalid.opacity, + "blend_mode": df.LvConstant( + "LV_BLEND_MODE_", + "NORMAL", + "ADDITIVE", + "SUBTRACTIVE", + "MULTIPLY", + "DIFFERENCE", + ).one_of, + "blur_backdrop": lvalid.lv_bool, + "blur_quality": df.LvConstant( + "LV_BLUR_QUALITY_", "AUTO", "SPEED", "PRECISION" + ).one_of, + "blur_radius": lvalid.lv_positive_int, "border_color": lvalid.lv_color, "border_opa": lvalid.opacity, "border_post": lvalid.lv_bool, @@ -175,33 +190,53 @@ STYLE_PROPS = { "border_width": lvalid.lv_positive_int, "clip_corner": lvalid.lv_bool, "color_filter_opa": lvalid.opacity, + "drop_shadow_color": lvalid.lv_color, + "drop_shadow_offset_x": lvalid.lv_int, + "drop_shadow_offset_y": lvalid.lv_int, + "drop_shadow_opa": lvalid.opacity, + "drop_shadow_quality": df.LvConstant( + "LV_BLUR_QUALITY_", "AUTO", "SPEED", "PRECISION" + ).one_of, + "drop_shadow_radius": lvalid.lv_positive_int, "height": lvalid.size, + "image_opa": lvalid.opacity, "image_recolor": lvalid.lv_color, "image_recolor_opa": lvalid.opacity, + "length": lvalid.pixels_or_percent, "line_color": lvalid.lv_color, "line_dash_gap": lvalid.lv_positive_int, "line_dash_width": lvalid.lv_positive_int, "line_opa": lvalid.opacity, "line_rounded": lvalid.lv_bool, "line_width": lvalid.lv_positive_int, + "margin_bottom": lvalid.padding, + "margin_left": lvalid.padding, + "margin_right": lvalid.padding, + "margin_top": lvalid.padding, + "max_height": lvalid.pixels_or_percent, + "max_width": lvalid.pixels_or_percent, + "min_height": lvalid.pixels_or_percent, + "min_width": lvalid.pixels_or_percent, "opa": lvalid.opacity, "opa_layered": lvalid.opacity, "outline_color": lvalid.lv_color, "outline_opa": lvalid.opacity, "outline_pad": lvalid.padding, "outline_width": lvalid.pixels, - "length": lvalid.pixels_or_percent, "pad_all": lvalid.padding, "pad_bottom": lvalid.padding, "pad_left": lvalid.padding, + "pad_radial": lvalid.padding, "pad_right": lvalid.padding, "pad_top": lvalid.padding, "radial_offset": lvalid.size, + "radius": lvalid.lv_fraction, + "recolor": lvalid.lv_color, + "recolor_opa": lvalid.opacity, + "rotary_sensitivity": lvalid.lv_positive_int, "shadow_color": lvalid.lv_color, "shadow_offset_x": lvalid.lv_int, "shadow_offset_y": lvalid.lv_int, - "shadow_ofs_x": lvalid.lv_int, - "shadow_ofs_y": lvalid.lv_int, "shadow_opa": lvalid.opacity, "shadow_spread": lvalid.lv_int, "shadow_width": lvalid.lv_positive_int, @@ -216,7 +251,9 @@ STYLE_PROPS = { "text_letter_space": lvalid.lv_positive_int, "text_line_space": lvalid.lv_positive_int, "text_opa": lvalid.opacity, - "transform_angle": lvalid.lv_angle, + "text_outline_stroke_color": lvalid.lv_color, + "text_outline_stroke_opa": lvalid.opacity, + "text_outline_stroke_width": lvalid.lv_positive_int, "transform_height": lvalid.pixels_or_percent, "transform_pivot_x": lvalid.pixels_or_percent, "transform_pivot_y": lvalid.pixels_or_percent, @@ -226,20 +263,17 @@ STYLE_PROPS = { "transform_scale_y": lvalid.scale, "transform_skew_x": lvalid.lv_angle, "transform_skew_y": lvalid.lv_angle, - "transform_zoom": lvalid.scale, + "transform_width": lvalid.pixels_or_percent, + "translate_radial": lvalid.lv_int, "translate_x": lvalid.pixels_or_percent, "translate_y": lvalid.pixels_or_percent, - "max_height": lvalid.pixels_or_percent, - "max_width": lvalid.pixels_or_percent, - "min_height": lvalid.pixels_or_percent, - "min_width": lvalid.pixels_or_percent, - "radius": lvalid.lv_fraction, "width": lvalid.size, "x": lvalid.pixels_or_percent, "y": lvalid.pixels_or_percent, } STYLE_REMAP = { + "anim_time": "anim_duration", "transform_angle": "transform_rotation", "transform_zoom": "transform_scale", "zoom": "scale", @@ -249,6 +283,10 @@ STYLE_REMAP = { "r_mod": "length", } +STYLE_PROPS = BASE_PROPS | { + p: BASE_PROPS[v] for p, v in STYLE_REMAP.items() if v in BASE_PROPS +} + def remap_property(prop, record=True): """ @@ -394,6 +432,7 @@ def obj_schema(widget_type: WidgetType): return ( part_schema(widget_type.parts) .extend(ALIGN_TO_SCHEMA) + .extend({cv.Optional(df.CONF_EXT_CLICK_AREA): lvalid.pixels}) .extend(automation_schema(widget_type.w_type)) .extend( { diff --git a/esphome/components/lvgl/switch/__init__.py b/esphome/components/lvgl/switch/__init__.py index 6d10a70d85..a43851b4a3 100644 --- a/esphome/components/lvgl/switch/__init__.py +++ b/esphome/components/lvgl/switch/__init__.py @@ -13,8 +13,8 @@ from ..lvcode import ( LambdaContext, LvConditional, LvContext, - lv, lv_add, + lv_obj, lvgl_static, ) from ..types import LV_EVENT, LV_STATE, lv_pseudo_button_t, lvgl_ns @@ -39,7 +39,7 @@ async def to_code(config): widget.add_state(LV_STATE.CHECKED) cond.else_() widget.clear_state(LV_STATE.CHECKED) - lv.event_send(widget.obj, API_EVENT, cg.nullptr) + lv_obj.send_event(widget.obj, API_EVENT, cg.nullptr) control.add(switch_id.publish_state(v)) switch = cg.new_Pvariable(config[CONF_ID], await control.get_lambda()) await cg.register_component(switch, config) diff --git a/esphome/components/lvgl/text/__init__.py b/esphome/components/lvgl/text/__init__.py index eb56cdb7a7..190ecacda5 100644 --- a/esphome/components/lvgl/text/__init__.py +++ b/esphome/components/lvgl/text/__init__.py @@ -10,8 +10,8 @@ from ..lvcode import ( UPDATE_EVENT, LambdaContext, LvContext, - lv, lv_add, + lv_obj, lvgl_static, ) from ..types import LV_EVENT, LvText, lvgl_ns @@ -33,7 +33,7 @@ async def to_code(config): await wait_for_widgets() async with LambdaContext([(cg.std_string, "text_value")]) as control: await widget.set_property("text", "text_value.c_str()") - lv.event_send(widget.obj, API_EVENT, cg.nullptr) + lv_obj.send_event(widget.obj, API_EVENT, cg.nullptr) control.add(textvar.publish_state(widget.get_value())) async with LambdaContext(EVENT_ARG) as lamb: lv_add(textvar.publish_state(widget.get_value())) diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 54309cdf89..c52d213e15 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -15,6 +15,7 @@ from .defines import ( CONF_ALIGN, CONF_ALIGN_TO, CONF_ALIGN_TO_LAMBDA_ID, + CONF_EXT_CLICK_AREA, DIRECTIONS, LV_EVENT_MAP, LV_EVENT_TRIGGERS, @@ -113,6 +114,8 @@ async def generate_align_tos(config: dict): x = align_to[CONF_X] y = align_to[CONF_Y] lv.obj_align_to(w.obj, target, align, x, y) + if ext_click_area := w.config.get(CONF_EXT_CLICK_AREA): + lv.obj_set_ext_click_area(w.obj, ext_click_area) action_id = config[CONF_ALIGN_TO_LAMBDA_ID] var = new_Pvariable(action_id, await context.get_lambda()) diff --git a/esphome/components/lvgl/widgets/meter.py b/esphome/components/lvgl/widgets/meter.py index 494f811a8e..ab65a7c47d 100644 --- a/esphome/components/lvgl/widgets/meter.py +++ b/esphome/components/lvgl/widgets/meter.py @@ -56,11 +56,11 @@ from ..lv_validation import ( lv_float, lv_image, lv_int, + lv_positive_int, opacity, padding, pixels, pixels_or_percent, - pixels_or_percent_validator, requires_component, size, ) @@ -88,7 +88,10 @@ CONF_COLOR_START = "color_start" CONF_DRAW_TICKS_ON_TOP = "draw_ticks_on_top" CONF_IMAGE_ID = "image_id" CONF_INDICATORS = "indicators" +CONF_DASH_GAP = "dash_gap" +CONF_DASH_WIDTH = "dash_width" CONF_LINE_ID = "line_id" +CONF_ROUNDED = "rounded" CONF_LABEL_GAP = "label_gap" CONF_MAJOR = "major" CONF_METER = "meter" @@ -135,9 +138,12 @@ INDICATOR_LINE_SCHEMA = cv.Schema( { cv.Optional(CONF_WIDTH, default=4): cv.int_, cv.Optional(CONF_COLOR, default=0): lv_color, + cv.Optional(CONF_ROUNDED, default=True): lv_bool, + cv.Optional(CONF_DASH_GAP): lv_positive_int, + cv.Optional(CONF_DASH_WIDTH): lv_positive_int, cv.Optional(CONF_R_MOD): padding, - cv.Optional(CONF_LENGTH): pixels_or_percent_validator, - cv.Optional(CONF_RADIAL_OFFSET, 0): pixels_or_percent_validator, + cv.Optional(CONF_LENGTH): pixels_or_percent, + cv.Optional(CONF_RADIAL_OFFSET): pixels_or_percent, cv.Optional(CONF_VALUE, default=0.0): lv_float, cv.Optional(CONF_OPA, default=1.0): opacity, } @@ -249,17 +255,17 @@ SCALE_SCHEMA = cv.Schema( { cv.Optional(CONF_COUNT, default=12): cv.int_range(min=2), cv.Optional(CONF_WIDTH, default=2): cv.positive_int, - cv.Optional(CONF_LENGTH, default=10): size, - cv.Optional(CONF_RADIAL_OFFSET, default=0): size, + cv.Optional(CONF_LENGTH, default=10): cv.positive_int, + cv.Optional(CONF_RADIAL_OFFSET): cv.positive_int, cv.Optional(CONF_COLOR, default=0x808080): lv_color, cv.Optional(CONF_MAJOR): cv.Schema( { cv.Optional(CONF_STRIDE, default=3): cv.positive_int, cv.Optional(CONF_WIDTH, default=5): size, - cv.Optional(CONF_LENGTH, default="15%"): size, - cv.Optional(CONF_RADIAL_OFFSET, default=0): size, + cv.Optional(CONF_LENGTH, default=12): cv.positive_int, + cv.Optional(CONF_RADIAL_OFFSET): cv.positive_int, cv.Optional(CONF_COLOR, default=0): lv_color, - cv.Optional(CONF_LABEL_GAP, default=4): size, + cv.Optional(CONF_LABEL_GAP, default=4): cv.int_, } ), } @@ -466,11 +472,15 @@ class MeterType(WidgetType): CONF_OPA: v[CONF_OPA], CONF_LINE_WIDTH: v[CONF_WIDTH], "line_color": v[CONF_COLOR], - "line_rounded": True, + "line_rounded": v[CONF_ROUNDED], CONF_ALIGN: CHILD_ALIGNMENTS.TOP_LEFT, CONF_LENGTH: length, - CONF_RADIAL_OFFSET: v[CONF_RADIAL_OFFSET], } + if radial_offset := v.get(CONF_RADIAL_OFFSET): + props[CONF_RADIAL_OFFSET] = radial_offset + for option in (CONF_DASH_WIDTH, CONF_DASH_GAP): + if option in v: + props["line_" + option] = v[option] lw = await widget_to_code(props, line_indicator_type, scale_var) await set_indicator_values(lw, v) @@ -478,10 +488,8 @@ class MeterType(WidgetType): add_lv_use(CONF_IMAGE) src = v[CONF_SRC] src_data = get_image_metadata(src.id) - pivot_x = await pixels.process(v[CONF_PIVOT_X]) - pivot_y = await pixels.process( - v.get(CONF_PIVOT_Y, src_data.height // 2) - ) + pivot_x = v[CONF_PIVOT_X] + pivot_y = v.get(CONF_PIVOT_Y, src_data.height // 2) props = { CONF_X: src_data.width // 2 - pivot_x, "transform_pivot_x": pivot_x, @@ -511,11 +519,12 @@ class MeterType(WidgetType): lv_obj.set_style_line_width( scale_var, await size.process(ticks[CONF_WIDTH]), LV_PART.ITEMS ) - lv_obj.set_style_radial_offset( - scale_var, - await size.process(ticks[CONF_RADIAL_OFFSET]), - LV_PART.ITEMS, - ) + if radial_offset := ticks.get(CONF_RADIAL_OFFSET): + lv_obj.set_style_radial_offset( + scale_var, + -radial_offset, + LV_PART.ITEMS, + ) lv_obj.set_style_line_color( scale_var, await lv_color.process(ticks[CONF_COLOR]), @@ -536,11 +545,12 @@ class MeterType(WidgetType): await size.process(major[CONF_LENGTH]), LV_PART.INDICATOR, ) - lv_obj.set_style_radial_offset( - scale_var, - await size.process(ticks[CONF_RADIAL_OFFSET]), - LV_PART.INDICATOR, - ) + if radial_offset := major.get(CONF_RADIAL_OFFSET): + lv_obj.set_style_radial_offset( + scale_var, + -radial_offset, + LV_PART.INDICATOR, + ) lv_obj.set_style_line_width( scale_var, await size.process(major[CONF_WIDTH]), @@ -553,12 +563,9 @@ class MeterType(WidgetType): ) # Set label gap (padding) - label_gap = await size.process(major[CONF_LABEL_GAP]) - if isinstance(label_gap, int): - label_gap -= DEFAULT_LABEL_GAP lv_obj.set_style_pad_radial( scale_var, - label_gap, + major[CONF_LABEL_GAP] - DEFAULT_LABEL_GAP, LV_PART.INDICATOR, ) else: diff --git a/esphome/components/lvgl/widgets/tileview.py b/esphome/components/lvgl/widgets/tileview.py index 8e9d95f349..4657d628de 100644 --- a/esphome/components/lvgl/widgets/tileview.py +++ b/esphome/components/lvgl/widgets/tileview.py @@ -129,6 +129,6 @@ async def tileview_select(config, action_id, template_arg, args): lv.tileview_set_tile_by_index( widgets[0].obj, column, row, literal(config[CONF_ANIMATED]) ) - lv.event_send(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) + lv_obj.send_event(w.obj, LV_EVENT.VALUE_CHANGED, cg.nullptr) return await action_to_code(widgets, do_select, action_id, template_arg, args) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 821476a72b..b8c9a1809e 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -232,7 +232,7 @@ lvgl: - roller: id: lv_roller visible_row_count: 2 - anim_time: 500ms + anim_duration: 500ms options: - Nov - Dec @@ -317,20 +317,27 @@ lvgl: align: top_left - container: align: center + anim_duration: 1s arc_opa: COVER arc_color: 0xFF0000 arc_rounded: false arc_width: 3 - anim_time: 1s + base_dir: auto bg_color: light_blue bg_grad_color: light_blue bg_grad_dir: hor + bg_grad_opa: cover bg_grad_stop: 128 bg_image_opa: transp bg_image_recolor: light_blue bg_image_recolor_opa: 50% + bg_main_opa: cover bg_main_stop: 0 bg_opa: 20% + blend_mode: normal + blur_backdrop: false + blur_quality: auto + blur_radius: 0 border_color: 0x00FF00 border_opa: cover border_post: true @@ -338,7 +345,15 @@ lvgl: border_width: 4 clip_corner: false color_filter_opa: transp + drop_shadow_color: 0x000000 + drop_shadow_offset_x: 5 + drop_shadow_offset_y: 5 + drop_shadow_opa: cover + drop_shadow_quality: precision + drop_shadow_radius: 10 + ext_click_area: 100px height: 50% + image_opa: cover image_recolor: light_blue image_recolor_opa: cover line_width: 10 @@ -346,6 +361,10 @@ lvgl: line_dash_gap: 10 line_rounded: false line_color: light_blue + margin_bottom: 4 + margin_left: 4 + margin_right: 4 + margin_top: 4 opa: cover opa_layered: cover outline_color: light_blue @@ -355,8 +374,12 @@ lvgl: pad_all: 10px pad_bottom: 10px pad_left: 10px + pad_radial: 0 pad_right: 10px pad_top: 10px + recolor: 0xFF0000 + recolor_opa: transp + rotary_sensitivity: 256 shadow_color: light_blue shadow_opa: cover shadow_spread: 5 @@ -368,6 +391,9 @@ lvgl: text_letter_space: 4 text_line_space: 4 text_opa: cover + text_outline_stroke_color: 0x000000 + text_outline_stroke_opa: cover + text_outline_stroke_width: 2 transform_rotation: 90 transform_height: 100 transform_pivot_x: 50% @@ -377,8 +403,10 @@ lvgl: transform_scale_y: 0.8 transform_skew_x: 10 transform_skew_y: 20 + transform_width: 100 shadow_offset_x: 3 shadow_offset_y: 3 + translate_radial: 0 translate_x: 10 translate_y: 10 max_height: 100 @@ -1053,7 +1081,7 @@ lvgl: - ticks: width: 1 count: 61 - length: 20% + length: 20 radial_offset: 5 color: 0xFFFFFF major: From 2cb987095da9ca82aaa6f4412184f8cda9fc8090 Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Tue, 31 Mar 2026 13:48:16 -0700 Subject: [PATCH 1835/2030] [modbus] Share helper functions across modbus components - part B (#14172) Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/modbus/modbus_helpers.cpp | 139 ++++++++++++++++++ esphome/components/modbus/modbus_helpers.h | 101 +++++++++++++ .../binary_sensor/modbus_binarysensor.cpp | 4 +- .../modbus_controller/modbus_controller.cpp | 134 +---------------- .../modbus_controller/modbus_controller.h | 109 ++++---------- .../number/modbus_number.cpp | 2 +- .../output/modbus_output.cpp | 2 +- .../select/modbus_select.cpp | 4 +- .../switch/modbus_switch.cpp | 4 +- 9 files changed, 277 insertions(+), 222 deletions(-) create mode 100644 esphome/components/modbus/modbus_helpers.cpp diff --git a/esphome/components/modbus/modbus_helpers.cpp b/esphome/components/modbus/modbus_helpers.cpp new file mode 100644 index 0000000000..77190b2846 --- /dev/null +++ b/esphome/components/modbus/modbus_helpers.cpp @@ -0,0 +1,139 @@ +#include "modbus_helpers.h" +#include "esphome/core/log.h" + +namespace esphome::modbus::helpers { + +static const char *const TAG = "modbus_helpers"; + +void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type) { + switch (value_type) { + case SensorValueType::U_WORD: + case SensorValueType::S_WORD: + data.push_back(value & 0xFFFF); + break; + case SensorValueType::U_DWORD: + case SensorValueType::S_DWORD: + case SensorValueType::FP32: + data.push_back((value & 0xFFFF0000) >> 16); + data.push_back(value & 0xFFFF); + break; + case SensorValueType::U_DWORD_R: + case SensorValueType::S_DWORD_R: + case SensorValueType::FP32_R: + data.push_back(value & 0xFFFF); + data.push_back((value & 0xFFFF0000) >> 16); + break; + case SensorValueType::U_QWORD: + case SensorValueType::S_QWORD: + data.push_back((value & 0xFFFF000000000000) >> 48); + data.push_back((value & 0xFFFF00000000) >> 32); + data.push_back((value & 0xFFFF0000) >> 16); + data.push_back(value & 0xFFFF); + break; + case SensorValueType::U_QWORD_R: + case SensorValueType::S_QWORD_R: + data.push_back(value & 0xFFFF); + data.push_back((value & 0xFFFF0000) >> 16); + data.push_back((value & 0xFFFF00000000) >> 32); + data.push_back((value & 0xFFFF000000000000) >> 48); + break; + default: + ESP_LOGE(TAG, "Invalid data type for modbus number to payload conversion: %d", static_cast<uint16_t>(value_type)); + break; + } +} + +int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sensor_value_type, uint8_t offset, + uint32_t bitmask) { + int64_t value = 0; // int64_t because it can hold signed and unsigned 32 bits + + if (offset > data.size()) { + ESP_LOGE(TAG, "not enough data for value"); + return value; + } + + size_t size = data.size() - offset; + bool error = false; + switch (sensor_value_type) { + case SensorValueType::U_WORD: + if (size >= 2) { + value = mask_and_shift_by_rightbit(get_data<uint16_t>(data, offset), + bitmask); // default is 0xFFFF ; + } else { + error = true; + } + break; + case SensorValueType::U_DWORD: + case SensorValueType::FP32: + if (size >= 4) { + value = get_data<uint32_t>(data, offset); + value = mask_and_shift_by_rightbit((uint32_t) value, bitmask); + } else { + error = true; + } + break; + case SensorValueType::U_DWORD_R: + case SensorValueType::FP32_R: + if (size >= 4) { + value = get_data<uint32_t>(data, offset); + value = static_cast<uint32_t>(value & 0xFFFF) << 16 | (value & 0xFFFF0000) >> 16; + value = mask_and_shift_by_rightbit((uint32_t) value, bitmask); + } else { + error = true; + } + break; + case SensorValueType::S_WORD: + if (size >= 2) { + value = mask_and_shift_by_rightbit(get_data<int16_t>(data, offset), + bitmask); // default is 0xFFFF ; + } else { + error = true; + } + break; + case SensorValueType::S_DWORD: + if (size >= 4) { + value = mask_and_shift_by_rightbit(get_data<int32_t>(data, offset), bitmask); + } else { + error = true; + } + break; + case SensorValueType::S_DWORD_R: { + if (size >= 4) { + value = get_data<uint32_t>(data, offset); + // Currently the high word is at the low position + // the sign bit is therefore at low before the switch + uint32_t sign_bit = (value & 0x8000) << 16; + value = mask_and_shift_by_rightbit( + static_cast<int32_t>(((value & 0x7FFF) << 16 | (value & 0xFFFF0000) >> 16) | sign_bit), bitmask); + } else { + error = true; + } + } break; + case SensorValueType::U_QWORD: + case SensorValueType::S_QWORD: + // Ignore bitmask for QWORD + if (size >= 8) { + value = get_data<uint64_t>(data, offset); + } else { + error = true; + } + break; + case SensorValueType::U_QWORD_R: + case SensorValueType::S_QWORD_R: { + // Ignore bitmask for QWORD + if (size >= 8) { + uint64_t tmp = get_data<uint64_t>(data, offset); + value = (tmp << 48) | (tmp >> 48) | ((tmp & 0xFFFF0000) << 16) | ((tmp >> 16) & 0xFFFF0000); + } else { + error = true; + } + } break; + case SensorValueType::RAW: + default: + break; + } + if (error) + ESP_LOGE(TAG, "not enough data for value"); + return value; +} +} // namespace esphome::modbus::helpers diff --git a/esphome/components/modbus/modbus_helpers.h b/esphome/components/modbus/modbus_helpers.h index 9f78de1c21..84897bcad3 100644 --- a/esphome/components/modbus/modbus_helpers.h +++ b/esphome/components/modbus/modbus_helpers.h @@ -1,6 +1,8 @@ #pragma once #include <string> +#include <vector> +#include <cmath> #include "esphome/core/helpers.h" #include "esphome/components/modbus/modbus_definitions.h" @@ -103,4 +105,103 @@ inline uint64_t qword_from_hex_str(const std::string &value, uint8_t pos) { return static_cast<uint64_t>(dword_from_hex_str(value, pos)) << 32 | dword_from_hex_str(value, pos + 4); } +// Extract data from modbus response buffer +/** Extract data from modbus response buffer + * @param T one of supported integer data types int_8,int_16,int_32,int_64 + * @param data modbus response buffer (uint8_t) + * @param buffer_offset offset in bytes. + * @return value of type T extracted from buffer + */ +template<typename T> T get_data(const std::vector<uint8_t> &data, size_t buffer_offset) { + if (sizeof(T) == sizeof(uint8_t)) { + return T(data[buffer_offset]); + } + if (sizeof(T) == sizeof(uint16_t)) { + return T((uint16_t(data[buffer_offset + 0]) << 8) | (uint16_t(data[buffer_offset + 1]) << 0)); + } + + if (sizeof(T) == sizeof(uint32_t)) { + return static_cast<uint32_t>(get_data<uint16_t>(data, buffer_offset)) << 16 | + static_cast<uint32_t>(get_data<uint16_t>(data, buffer_offset + 2)); + } + + if (sizeof(T) == sizeof(uint64_t)) { + return static_cast<uint64_t>(get_data<uint32_t>(data, buffer_offset)) << 32 | + (static_cast<uint64_t>(get_data<uint32_t>(data, buffer_offset + 4))); + } + + static_assert(sizeof(T) == sizeof(uint8_t) || sizeof(T) == sizeof(uint16_t) || sizeof(T) == sizeof(uint32_t) || + sizeof(T) == sizeof(uint64_t), + "Unsupported type size in get_data; only 1, 2, 4, or 8-byte integer types are supported."); + + return T{}; +} + +/** Extract coil data from modbus response buffer + * Responses for coil are packed into bytes . + * coil 3 is bit 3 of the first response byte + * coil 9 is bit 2 of the second response byte + * @param coil number of the cil + * @param data modbus response buffer (uint8_t) + * @return content of coil register + */ +inline bool coil_from_vector(int coil, const std::vector<uint8_t> &data) { + auto data_byte = coil / 8; + return (data[data_byte] & (1 << (coil % 8))) > 0; +} + +/** Extract bits from value and shift right according to the bitmask + * if the bitmask is 0x00F0 we want the values frrom bit 5 - 8. + * the result is then shifted right by the position if the first right set bit in the mask + * Useful for modbus data where more than one value is packed in a 16 bit register + * Example: on Epever the "Length of night" register 0x9065 encodes values of the whole night length of time as + * D15 - D8 = hour, D7 - D0 = minute + * To get the hours use mask 0xFF00 and 0x00FF for the minute + * @param data an integral value between 16 aand 32 bits, + * @param bitmask the bitmask to apply + */ +template<typename N> N mask_and_shift_by_rightbit(N data, uint32_t mask) { + auto result = (mask & data); + if (result == 0 || mask == 0xFFFFFFFF) { + return result; + } + for (size_t pos = 0; pos < sizeof(N) << 3; pos++) { + if (pos < 32 && (mask & (1UL << pos)) != 0) + return result >> pos; + } + return 0; +} + +/** Convert float value to vector<uint16_t> suitable for sending + * @param data target for payload + * @param value float value to convert + * @param value_type defines if 16/32 or FP32 is used + * @return vector containing the modbus register words in correct order + */ +void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type); + +/** Convert vector<uint8_t> response payload to number. + * @param data payload with the data to convert + * @param sensor_value_type defines if 16/32/64 bits or FP32 is used + * @param offset offset to the data in data + * @param bitmask bitmask used for masking and shifting + * @return 64-bit number of the payload + */ +int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sensor_value_type, uint8_t offset, + uint32_t bitmask); + +inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) { + int64_t val; + + if (value_type_is_float(value_type)) { + val = bit_cast<uint32_t>(value); + } else { + val = llroundf(value); + } + + std::vector<uint16_t> data; + number_to_payload(data, val, value_type); + return data; +} + } // namespace esphome::modbus::helpers diff --git a/esphome/components/modbus_controller/binary_sensor/modbus_binarysensor.cpp b/esphome/components/modbus_controller/binary_sensor/modbus_binarysensor.cpp index c3eb3d4411..1ea3041b4d 100644 --- a/esphome/components/modbus_controller/binary_sensor/modbus_binarysensor.cpp +++ b/esphome/components/modbus_controller/binary_sensor/modbus_binarysensor.cpp @@ -15,10 +15,10 @@ void ModbusBinarySensor::parse_and_publish(const std::vector<uint8_t> &data) { case ModbusRegisterType::DISCRETE_INPUT: case ModbusRegisterType::COIL: // offset for coil is the actual number of the coil not the byte offset - value = coil_from_vector(this->offset, data); + value = modbus::helpers::coil_from_vector(this->offset, data); break; default: - value = get_data<uint16_t>(data, this->offset) & this->bitmask; + value = modbus::helpers::get_data<uint16_t>(data, this->offset) & this->bitmask; break; } // Is there a lambda registered diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 38eaea2d1c..3c4ceaf62d 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -140,7 +140,7 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t std::vector<uint16_t> payload; payload.reserve(server_register->register_count * 2); - number_to_payload(payload, value, server_register->value_type); + modbus::helpers::number_to_payload(payload, value, server_register->value_type); sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend()); current_address += server_register->register_count; found = true; @@ -258,7 +258,7 @@ void ModbusController::on_modbus_write_registers(uint8_t function_code, const st // Actually write to the registers: if (!for_each_register([&data](ServerRegister *server_register, uint16_t offset) { - int64_t number = payload_to_number(data, server_register->value_type, offset, 0xFFFFFFFF); + int64_t number = modbus::helpers::payload_to_number(data, server_register->value_type, offset, 0xFFFFFFFF); return server_register->write_lambda(number); })) { this->send_error(function_code, ModbusExceptionCode::SERVICE_DEVICE_FAILURE); @@ -517,7 +517,8 @@ void ModbusController::loop() { void ModbusController::on_write_register_response(ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data) { - ESP_LOGV(TAG, "Command ACK 0x%X %d ", get_data<uint16_t>(data, 0), get_data<int16_t>(data, 1)); + ESP_LOGV(TAG, "Command ACK 0x%X %d ", modbus::helpers::get_data<uint16_t>(data, 0), + modbus::helpers::get_data<int16_t>(data, 1)); } void ModbusController::dump_sensors_() { @@ -710,132 +711,5 @@ bool ModbusCommandItem::is_equal(const ModbusCommandItem &other) { other.register_type == this->register_type && other.function_code == this->function_code; } -void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type) { - switch (value_type) { - case SensorValueType::U_WORD: - case SensorValueType::S_WORD: - data.push_back(value & 0xFFFF); - break; - case SensorValueType::U_DWORD: - case SensorValueType::S_DWORD: - case SensorValueType::FP32: - data.push_back((value & 0xFFFF0000) >> 16); - data.push_back(value & 0xFFFF); - break; - case SensorValueType::U_DWORD_R: - case SensorValueType::S_DWORD_R: - case SensorValueType::FP32_R: - data.push_back(value & 0xFFFF); - data.push_back((value & 0xFFFF0000) >> 16); - break; - case SensorValueType::U_QWORD: - case SensorValueType::S_QWORD: - data.push_back((value & 0xFFFF000000000000) >> 48); - data.push_back((value & 0xFFFF00000000) >> 32); - data.push_back((value & 0xFFFF0000) >> 16); - data.push_back(value & 0xFFFF); - break; - case SensorValueType::U_QWORD_R: - case SensorValueType::S_QWORD_R: - data.push_back(value & 0xFFFF); - data.push_back((value & 0xFFFF0000) >> 16); - data.push_back((value & 0xFFFF00000000) >> 32); - data.push_back((value & 0xFFFF000000000000) >> 48); - break; - default: - ESP_LOGE(TAG, "Invalid data type for modbus number to payload conversation: %d", - static_cast<uint16_t>(value_type)); - break; - } -} - -int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sensor_value_type, uint8_t offset, - uint32_t bitmask) { - int64_t value = 0; // int64_t because it can hold signed and unsigned 32 bits - - size_t size = data.size() - offset; - bool error = false; - switch (sensor_value_type) { - case SensorValueType::U_WORD: - if (size >= 2) { - value = mask_and_shift_by_rightbit(get_data<uint16_t>(data, offset), bitmask); // default is 0xFFFF ; - } else { - error = true; - } - break; - case SensorValueType::U_DWORD: - case SensorValueType::FP32: - if (size >= 4) { - value = get_data<uint32_t>(data, offset); - value = mask_and_shift_by_rightbit((uint32_t) value, bitmask); - } else { - error = true; - } - break; - case SensorValueType::U_DWORD_R: - case SensorValueType::FP32_R: - if (size >= 4) { - value = get_data<uint32_t>(data, offset); - value = static_cast<uint32_t>(value & 0xFFFF) << 16 | (value & 0xFFFF0000) >> 16; - value = mask_and_shift_by_rightbit((uint32_t) value, bitmask); - } else { - error = true; - } - break; - case SensorValueType::S_WORD: - if (size >= 2) { - value = mask_and_shift_by_rightbit(get_data<int16_t>(data, offset), - bitmask); // default is 0xFFFF ; - } else { - error = true; - } - break; - case SensorValueType::S_DWORD: - if (size >= 4) { - value = mask_and_shift_by_rightbit(get_data<int32_t>(data, offset), bitmask); - } else { - error = true; - } - break; - case SensorValueType::S_DWORD_R: { - if (size >= 4) { - value = get_data<uint32_t>(data, offset); - // Currently the high word is at the low position - // the sign bit is therefore at low before the switch - uint32_t sign_bit = (value & 0x8000) << 16; - value = mask_and_shift_by_rightbit( - static_cast<int32_t>(((value & 0x7FFF) << 16 | (value & 0xFFFF0000) >> 16) | sign_bit), bitmask); - } else { - error = true; - } - } break; - case SensorValueType::U_QWORD: - case SensorValueType::S_QWORD: - // Ignore bitmask for QWORD - if (size >= 8) { - value = get_data<uint64_t>(data, offset); - } else { - error = true; - } - break; - case SensorValueType::U_QWORD_R: - case SensorValueType::S_QWORD_R: { - // Ignore bitmask for QWORD - if (size >= 8) { - uint64_t tmp = get_data<uint64_t>(data, offset); - value = (tmp << 48) | (tmp >> 48) | ((tmp & 0xFFFF0000) << 16) | ((tmp >> 16) & 0xFFFF0000); - } else { - error = true; - } - } break; - case SensorValueType::RAW: - default: - break; - } - if (error) - ESP_LOGE(TAG, "not enough data for value"); - return value; -} - } // namespace modbus_controller } // namespace esphome diff --git a/esphome/components/modbus_controller/modbus_controller.h b/esphome/components/modbus_controller/modbus_controller.h index 438eb12c2a..6c6c748b73 100644 --- a/esphome/components/modbus_controller/modbus_controller.h +++ b/esphome/components/modbus_controller/modbus_controller.h @@ -59,83 +59,38 @@ inline uint64_t qword_from_hex_str(const std::string &value, uint8_t pos) { return modbus::helpers::qword_from_hex_str(value, pos); } -// Extract data from modbus response buffer -/** Extract data from modbus response buffer - * @param T one of supported integer data types int_8,int_16,int_32,int_64 - * @param data modbus response buffer (uint8_t) - * @param buffer_offset offset in bytes. - * @return value of type T extracted from buffer - */ -template<typename T> T get_data(const std::vector<uint8_t> &data, size_t buffer_offset) { - if (sizeof(T) == sizeof(uint8_t)) { - return T(data[buffer_offset]); - } - if (sizeof(T) == sizeof(uint16_t)) { - return T((uint16_t(data[buffer_offset + 0]) << 8) | (uint16_t(data[buffer_offset + 1]) << 0)); - } - - if (sizeof(T) == sizeof(uint32_t)) { - return get_data<uint16_t>(data, buffer_offset) << 16 | get_data<uint16_t>(data, (buffer_offset + 2)); - } - - if (sizeof(T) == sizeof(uint64_t)) { - return static_cast<uint64_t>(get_data<uint32_t>(data, buffer_offset)) << 32 | - (static_cast<uint64_t>(get_data<uint32_t>(data, buffer_offset + 4))); - } +template<typename T> +ESPDEPRECATED("Use modbus::helpers::get_data() instead. Removed in 2026.10.0", "2026.4.0") +T get_data(const std::vector<uint8_t> &data, size_t buffer_offset) { + return modbus::helpers::get_data<T>(data, buffer_offset); } -/** Extract coil data from modbus response buffer - * Responses for coil are packed into bytes . - * coil 3 is bit 3 of the first response byte - * coil 9 is bit 2 of the second response byte - * @param coil number of the cil - * @param data modbus response buffer (uint8_t) - * @return content of coil register - */ +ESPDEPRECATED("Use modbus::helpers::coil_from_vector() instead. Removed in 2026.10.0", "2026.4.0") inline bool coil_from_vector(int coil, const std::vector<uint8_t> &data) { - auto data_byte = coil / 8; - return (data[data_byte] & (1 << (coil % 8))) > 0; + return modbus::helpers::coil_from_vector(coil, data); } -/** Extract bits from value and shift right according to the bitmask - * if the bitmask is 0x00F0 we want the values frrom bit 5 - 8. - * the result is then shifted right by the position if the first right set bit in the mask - * Useful for modbus data where more than one value is packed in a 16 bit register - * Example: on Epever the "Length of night" register 0x9065 encodes values of the whole night length of time as - * D15 - D8 = hour, D7 - D0 = minute - * To get the hours use mask 0xFF00 and 0x00FF for the minute - * @param data an integral value between 16 aand 32 bits, - * @param bitmask the bitmask to apply - */ -template<typename N> N mask_and_shift_by_rightbit(N data, uint32_t mask) { - auto result = (mask & data); - if (result == 0 || mask == 0xFFFFFFFF) { - return result; - } - for (size_t pos = 0; pos < sizeof(N) << 3; pos++) { - if ((mask & (1UL << pos)) != 0) - return result >> pos; - } - return 0; +template<typename N> +ESPDEPRECATED("Use modbus::helpers::mask_and_shift_by_rightbit() instead. Removed in 2026.10.0", "2026.4.0") +N mask_and_shift_by_rightbit(N data, uint32_t mask) { + return modbus::helpers::mask_and_shift_by_rightbit(data, mask); } -/** Convert float value to vector<uint16_t> suitable for sending - * @param data target for payload - * @param value float value to convert - * @param value_type defines if 16/32 or FP32 is used - * @return vector containing the modbus register words in correct order - */ -void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type); +ESPDEPRECATED("Use modbus::helpers::number_to_payload() instead. Removed in 2026.10.0", "2026.4.0") +inline void number_to_payload(std::vector<uint16_t> &data, int64_t value, SensorValueType value_type) { + modbus::helpers::number_to_payload(data, value, value_type); +} -/** Convert vector<uint8_t> response payload to number. - * @param data payload with the data to convert - * @param sensor_value_type defines if 16/32/64 bits or FP32 is used - * @param offset offset to the data in data - * @param bitmask bitmask used for masking and shifting - * @return 64-bit number of the payload - */ -int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sensor_value_type, uint8_t offset, - uint32_t bitmask); +ESPDEPRECATED("Use modbus::helpers::payload_to_number() instead. Removed in 2026.10.0", "2026.4.0") +inline int64_t payload_to_number(const std::vector<uint8_t> &data, SensorValueType sensor_value_type, uint8_t offset, + uint32_t bitmask) { + return modbus::helpers::payload_to_number(data, sensor_value_type, offset, bitmask); +} + +ESPDEPRECATED("Use modbus::helpers::float_to_payload() instead. Removed in 2026.10.0", "2026.4.0") +inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) { + return modbus::helpers::float_to_payload(value, value_type); +} class ModbusController; @@ -517,7 +472,7 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice { * @return float value of data */ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem &item) { - int64_t number = payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask); + int64_t number = modbus::helpers::payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask); float float_value; if (modbus::helpers::value_type_is_float(item.sensor_value_type)) { @@ -529,19 +484,5 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem return float_value; } -inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) { - int64_t val; - - if (modbus::helpers::value_type_is_float(value_type)) { - val = bit_cast<uint32_t>(value); - } else { - val = llroundf(value); - } - - std::vector<uint16_t> data; - number_to_payload(data, val, value_type); - return data; -} - } // namespace modbus_controller } // namespace esphome diff --git a/esphome/components/modbus_controller/number/modbus_number.cpp b/esphome/components/modbus_controller/number/modbus_number.cpp index 4a3ec1fc41..ed5d91ec5b 100644 --- a/esphome/components/modbus_controller/number/modbus_number.cpp +++ b/esphome/components/modbus_controller/number/modbus_number.cpp @@ -62,7 +62,7 @@ void ModbusNumber::control(float value) { this->parent_->on_write_register_response(write_cmd.register_type, this->start_address, data); }); } else { - data = float_to_payload(write_value, this->sensor_value_type); + data = modbus::helpers::float_to_payload(write_value, this->sensor_value_type); ESP_LOGD(TAG, "Updating register: connected Sensor=%s start address=0x%X register count=%d new value=%.02f (val=%.02f)", diff --git a/esphome/components/modbus_controller/output/modbus_output.cpp b/esphome/components/modbus_controller/output/modbus_output.cpp index f02d9397ca..e7f1a39716 100644 --- a/esphome/components/modbus_controller/output/modbus_output.cpp +++ b/esphome/components/modbus_controller/output/modbus_output.cpp @@ -34,7 +34,7 @@ void ModbusFloatOutput::write_state(float value) { } // lambda didn't set payload if (data.empty()) { - data = float_to_payload(value, this->sensor_value_type); + data = modbus::helpers::float_to_payload(value, this->sensor_value_type); } ESP_LOGD(TAG, "Updating register: start address=0x%X register count=%d new value=%.02f (val=%.02f)", diff --git a/esphome/components/modbus_controller/select/modbus_select.cpp b/esphome/components/modbus_controller/select/modbus_select.cpp index e2a54d3f60..2cff7e89ee 100644 --- a/esphome/components/modbus_controller/select/modbus_select.cpp +++ b/esphome/components/modbus_controller/select/modbus_select.cpp @@ -9,7 +9,7 @@ static const char *const TAG = "modbus_controller.select"; void ModbusSelect::dump_config() { LOG_SELECT(TAG, "Modbus Controller Select", this); } void ModbusSelect::parse_and_publish(const std::vector<uint8_t> &data) { - int64_t value = payload_to_number(data, this->sensor_value_type, this->offset, this->bitmask); + int64_t value = modbus::helpers::payload_to_number(data, this->sensor_value_type, this->offset, this->bitmask); ESP_LOGD(TAG, "New select value %lld from payload", value); @@ -61,7 +61,7 @@ void ModbusSelect::control(size_t index) { } if (data.empty()) { - number_to_payload(data, *mapval, this->sensor_value_type); + modbus::helpers::number_to_payload(data, *mapval, this->sensor_value_type); } else { ESP_LOGV(TAG, "Using payload from write lambda"); } diff --git a/esphome/components/modbus_controller/switch/modbus_switch.cpp b/esphome/components/modbus_controller/switch/modbus_switch.cpp index 68aa37c9ed..dbaff04cc6 100644 --- a/esphome/components/modbus_controller/switch/modbus_switch.cpp +++ b/esphome/components/modbus_controller/switch/modbus_switch.cpp @@ -33,10 +33,10 @@ void ModbusSwitch::parse_and_publish(const std::vector<uint8_t> &data) { case ModbusRegisterType::DISCRETE_INPUT: case ModbusRegisterType::COIL: // offset for coil is the actual number of the coil not the byte offset - value = coil_from_vector(this->offset, data); + value = modbus::helpers::coil_from_vector(this->offset, data); break; default: - value = get_data<uint16_t>(data, this->offset) & this->bitmask; + value = modbus::helpers::get_data<uint16_t>(data, this->offset) & this->bitmask; break; } From 64e836f9c8da7cb68ade3cb430f9dbb7b4cecc9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Mar 2026 10:49:17 -1000 Subject: [PATCH 1836/2030] Bump CodSpeedHQ/action from 4.12.1 to 4.13.0 (#15340) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab7a750388..71703652e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -339,7 +339,7 @@ jobs: echo "binary=$BINARY" >> $GITHUB_OUTPUT - name: Run CodSpeed benchmarks - uses: CodSpeedHQ/action@1c8ae4843586d3ba879736b7f6b7b0c990757fab # v4 + uses: CodSpeedHQ/action@d872884a306dd4853acf0f584f4b706cf0cc72a2 # v4 with: run: ${{ steps.build.outputs.binary }} mode: simulation From 2064eef273c878191cd29799329c049693fa60d4 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 31 Mar 2026 16:53:12 -0400 Subject: [PATCH 1837/2030] [esp32_hosted] Guard against empty firmware URL in perform() (#15338) --- .../components/esp32_hosted/update/esp32_hosted_update.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp index dcd6e643c2..af35d32888 100644 --- a/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp +++ b/esphome/components/esp32_hosted/update/esp32_hosted_update.cpp @@ -448,6 +448,13 @@ void Esp32HostedUpdate::perform(bool force) { return; } +#ifdef USE_ESP32_HOSTED_HTTP_UPDATE + if (this->firmware_url_.empty()) { + ESP_LOGW(TAG, "No firmware URL available, run check first"); + return; + } +#endif + update::UpdateState prev_state = this->state_; this->state_ = update::UPDATE_STATE_INSTALLING; this->update_info_.has_progress = false; From 66b6d36a260dd1900c1786f9edc98c47157c8255 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 1 Apr 2026 07:04:10 +1000 Subject: [PATCH 1838/2030] [lvgl] Fixes #3 (#15304) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/lvgl/__init__.py | 10 ++----- esphome/components/lvgl/defines.py | 4 --- esphome/components/lvgl/styles.py | 31 +++------------------ esphome/components/lvgl/widgets/__init__.py | 7 +++-- esphome/components/lvgl/widgets/canvas.py | 2 -- esphome/components/lvgl/widgets/keyboard.py | 26 +++++++++++++---- esphome/components/lvgl/widgets/label.py | 2 +- esphome/components/lvgl/widgets/line.py | 19 ++++++------- esphome/components/lvgl/widgets/msgbox.py | 8 ++++-- esphome/components/lvgl/widgets/qrcode.py | 3 +- esphome/components/lvgl/widgets/tabview.py | 4 +-- 11 files changed, 48 insertions(+), 68 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 6377183ef4..736fba759f 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -380,7 +380,8 @@ async def to_code(configs): # This must be done after all widgets are created for comp in helpers.lvgl_components_required: cg.add_define(f"USE_LVGL_{comp.upper()}") - lv_image_formats = df.get_color_formats().copy() + # Currently always need RGB565 for the display buffer, and ARGB8888 is used for layer blending + lv_image_formats = {"RGB565", "ARGB8888"} if { "transform_rotation", "transform_scale", @@ -388,10 +389,6 @@ async def to_code(configs): "transform_scale_y", } & styles_used: df.add_define("LV_COLOR_SCREEN_TRANSP", "1") - lv_image_formats.add("ARGB8888") - lv_image_formats.add( - "RGB565" - ) # Currently always need RGB565 for the display buffer for use in helpers.lv_uses: df.add_define(f"LV_USE_{use.upper()}") cg.add_define(f"USE_LVGL_{use.upper()}") @@ -401,9 +398,6 @@ async def to_code(configs): metadata = get_image_metadata(image_id.id) image_type = IMAGE_TYPE[metadata.image_type] transparent = metadata.transparency != CONF_OPAQUE - if transparent: - # Internal draw layer will use ARGB8888 - lv_image_formats.add("ARGB8888") if image_type == ImageBinary: lv_image_formats.add("I1") if image_type == ImageGrayscale: diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index de5835d7a6..dd51a2f519 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -52,10 +52,6 @@ def get_remapped_uses(): return get_data(KEY_REMAPPED_USES, set()) -def get_color_formats(): - return get_data(KEY_COLOR_FORMATS, set()) - - def add_warning(msg: str): get_warnings().add(msg) diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 6f43e78f90..793290de73 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -4,26 +4,12 @@ import esphome.config_validation as cv from esphome.const import CONF_ID from esphome.core import ID -from .defines import ( - CONF_STYLE_DEFINITIONS, - CONF_THEME, - CONF_TOP_LAYER, - LValidator, - literal, -) +from .defines import CONF_STYLE_DEFINITIONS, CONF_THEME, LValidator, literal from .helpers import add_lv_use -from .lvcode import LambdaContext, LocalVariable, lv +from .lvcode import LambdaContext, lv from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, remap_property -from .types import ObjUpdateAction, lv_obj_t, lv_style_t -from .widgets import ( - Widget, - add_widgets, - collect_parts, - set_obj_properties, - theme_widget_map, - wait_for_widgets, -) -from .widgets.obj import obj_spec +from .types import ObjUpdateAction, lv_style_t +from .widgets import collect_parts, theme_widget_map, wait_for_widgets def has_style_props(config) -> bool: @@ -112,12 +98,3 @@ async def theme_to_code(config): for state, props in states.items() } theme_widget_map[w_name] = styles - - -async def add_top_layer(lv_component, config): - top_layer = lv.disp_get_layer_top(lv_component.var.get_disp()) - if top_conf := config.get(CONF_TOP_LAYER): - with LocalVariable("top_layer", lv_obj_t, top_layer) as top_layer_obj: - top_w = Widget(top_layer_obj, obj_spec, top_conf) - await set_obj_properties(top_w, top_conf) - await add_widgets(top_w, top_conf) diff --git a/esphome/components/lvgl/widgets/__init__.py b/esphome/components/lvgl/widgets/__init__.py index b383196963..0ac4062106 100644 --- a/esphome/components/lvgl/widgets/__init__.py +++ b/esphome/components/lvgl/widgets/__init__.py @@ -1,5 +1,4 @@ import sys -from typing import Any from esphome import codegen as cg, config_validation as cv from esphome.automation import register_action @@ -405,7 +404,11 @@ class Widget: # Map of widgets to their config, used for trigger generation -widget_map: dict[Any, Widget] = {} +widget_map: dict[ID, Widget] = {} + + +def is_widget_completed(name: ID) -> bool: + return name in widget_map class LvScrActType(WidgetType): diff --git a/esphome/components/lvgl/widgets/canvas.py b/esphome/components/lvgl/widgets/canvas.py index 0e40d0dfbe..f12766bae1 100644 --- a/esphome/components/lvgl/widgets/canvas.py +++ b/esphome/components/lvgl/widgets/canvas.py @@ -42,7 +42,6 @@ from ..defines import ( CONF_SRC, CONF_START_ANGLE, addr, - get_color_formats, literal, ) from ..lv_validation import ( @@ -99,7 +98,6 @@ class CanvasType(WidgetType): # RGB565 is 16-bit (2 bytes per pixel), ARGB8888 is 32-bit (4 bytes per pixel) if config[CONF_TRANSPARENT]: color_format = "LV_COLOR_FORMAT_ARGB8888" - get_color_formats().add("ARGB8888") else: color_format = "LV_COLOR_FORMAT_NATIVE" diff --git a/esphome/components/lvgl/widgets/keyboard.py b/esphome/components/lvgl/widgets/keyboard.py index d4a71078d0..029ca5f684 100644 --- a/esphome/components/lvgl/widgets/keyboard.py +++ b/esphome/components/lvgl/widgets/keyboard.py @@ -1,12 +1,15 @@ from esphome.components.key_provider import KeyProvider import esphome.config_validation as cv from esphome.const import CONF_ITEMS, CONF_MODE +from esphome.core import CORE from esphome.cpp_types import std_string +from .. import LvContext from ..defines import CONF_MAIN, KEYBOARD_MODES, literal -from ..helpers import add_lv_use, lvgl_components_required +from ..helpers import lvgl_components_required from ..types import LvCompound, LvType -from . import Widget, WidgetType, get_widgets +from . import Widget, WidgetType, get_widgets, is_widget_completed +from .buttonmatrix import CONF_BUTTONMATRIX from .textarea import CONF_TEXTAREA, lv_textarea_t CONF_KEYBOARD = "keyboard" @@ -41,16 +44,27 @@ class KeyboardType(WidgetType): ) def get_uses(self): - return CONF_KEYBOARD, CONF_TEXTAREA + return CONF_KEYBOARD, CONF_TEXTAREA, CONF_BUTTONMATRIX async def to_code(self, w: Widget, config: dict): lvgl_components_required.add("KEY_LISTENER") lvgl_components_required.add(CONF_KEYBOARD) - add_lv_use("btnmatrix") if mode := config.get(CONF_MODE): await w.set_property(CONF_MODE, await KEYBOARD_MODES.process(mode)) - if ta := await get_widgets(config, CONF_TEXTAREA): - await w.set_property(CONF_TEXTAREA, ta[0].obj) + if textarea := config.get(CONF_TEXTAREA): + # If a textarea is configured, it must be generated before the keyboard can attach it. + # If not yet configured, defer the attachment code. + + async def add_textarea(): + async with LvContext(): + await w.set_property( + CONF_TEXTAREA, (await get_widgets(config, CONF_TEXTAREA))[0].obj + ) + + if is_widget_completed(textarea): + await add_textarea() + else: + CORE.add_job(add_textarea) keyboard_spec = KeyboardType() diff --git a/esphome/components/lvgl/widgets/label.py b/esphome/components/lvgl/widgets/label.py index bb5900b8c9..5ac92f2717 100644 --- a/esphome/components/lvgl/widgets/label.py +++ b/esphome/components/lvgl/widgets/label.py @@ -35,7 +35,7 @@ class LabelType(WidgetType): if (value := config.get(CONF_TEXT)) is not None: await w.set_property(CONF_TEXT, await lv_text.process(value)) await w.set_property(CONF_LONG_MODE, config) - await w.set_property(CONF_RECOLOR, config) + await w.set_property(CONF_RECOLOR, config, processor=lv_bool) label_spec = LabelType() diff --git a/esphome/components/lvgl/widgets/line.py b/esphome/components/lvgl/widgets/line.py index a9b202163f..3112cc28d0 100644 --- a/esphome/components/lvgl/widgets/line.py +++ b/esphome/components/lvgl/widgets/line.py @@ -17,11 +17,6 @@ lv_point_t = cg.global_ns.struct("lv_point_t") lv_point_precise_t = cg.global_ns.struct("lv_point_precise_t") -LINE_SCHEMA = { - cv.Required(CONF_POINTS): cv.ensure_list(point_schema), -} - - async def process_coord(coord): if isinstance(coord, Lambda): return call_lambda(await cg.process_lambda(coord, [], return_type=lv_coord_t)) @@ -34,15 +29,17 @@ class LineType(WidgetType): CONF_LINE, LvType("LvLineType", parents=(LvCompound,)), (CONF_MAIN,), - LINE_SCHEMA, + schema={cv.Required(CONF_POINTS): cv.ensure_list(point_schema)}, + modify_schema={cv.Optional(CONF_POINTS): cv.ensure_list(point_schema)}, ) async def to_code(self, w: Widget, config): - points = [ - [await process_coord(p[CONF_X]), await process_coord(p[CONF_Y])] - for p in config[CONF_POINTS] - ] - lv_add(w.var.set_points(points)) + if CONF_POINTS in config: + points = [ + [await process_coord(p[CONF_X]), await process_coord(p[CONF_Y])] + for p in config[CONF_POINTS] + ] + lv_add(w.var.set_points(points)) line_spec = LineType() diff --git a/esphome/components/lvgl/widgets/msgbox.py b/esphome/components/lvgl/widgets/msgbox.py index af27ee7553..d0e6bfa3a2 100644 --- a/esphome/components/lvgl/widgets/msgbox.py +++ b/esphome/components/lvgl/widgets/msgbox.py @@ -33,6 +33,7 @@ from ..styles import LVStyle from ..types import LV_EVENT, lv_obj_t from . import Widget, WidgetType, add_widgets, set_obj_properties, widget_to_code from .button import button_spec, lv_button_t +from .img import CONF_IMAGE from .label import CONF_LABEL from .obj import obj_spec @@ -41,7 +42,7 @@ CONF_MSGBOX = "msgbox" OUTER_STYLE = LVStyle( "msgbox_outer", { - "bg_opa": 128, + "bg_opa": 0.5, "bg_color": "black", "border_width": 0, "pad_all": 0, @@ -119,6 +120,7 @@ async def msgbox_to_code(top_layer, conf): CONF_BUTTON, CONF_LABEL, CONF_MSGBOX, + CONF_IMAGE, *button_spec.get_uses(), ) if CONF_BUTTON_STYLE in conf: @@ -156,7 +158,7 @@ async def msgbox_to_code(top_layer, conf): with LocalVariable( "close_btn_", lv_obj_t, lv_expr.msgbox_add_close_button(msgbox) ) as close_btn: - lv_obj.remove_event_cb(close_btn, nullptr) + lv_obj.remove_event(close_btn, 0) lv_obj.add_event_cb( close_btn, await close_action.get_lambda(), @@ -170,6 +172,6 @@ async def msgbox_to_code(top_layer, conf): async def msgboxes_to_code(lv_component, config): - top_layer = lv.disp_get_layer_top(lv_component.get_disp()) + top_layer = lv_expr.disp_get_layer_top(lv_component.get_disp()) for conf in config.get(CONF_MSGBOXES, ()): await msgbox_to_code(top_layer, conf) diff --git a/esphome/components/lvgl/widgets/qrcode.py b/esphome/components/lvgl/widgets/qrcode.py index 82c4370543..df76ab6bb0 100644 --- a/esphome/components/lvgl/widgets/qrcode.py +++ b/esphome/components/lvgl/widgets/qrcode.py @@ -2,7 +2,7 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import CONF_SIZE, CONF_TEXT -from ..defines import CONF_MAIN, get_color_formats +from ..defines import CONF_MAIN from ..lv_validation import color, lv_color, lv_int, lv_text from ..lvcode import LocalVariable, lv from ..schemas import TEXT_SCHEMA @@ -44,7 +44,6 @@ class QrCodeType(WidgetType): return CONF_CANVAS, CONF_IMAGE async def to_code(self, w: Widget, config): - get_color_formats().add("ARGB8888") await w.set_property( CONF_LIGHT_COLOR, await lv_color.process(config.get(CONF_LIGHT_COLOR)) ) diff --git a/esphome/components/lvgl/widgets/tabview.py b/esphome/components/lvgl/widgets/tabview.py index 60ba664f04..7629b03e9d 100644 --- a/esphome/components/lvgl/widgets/tabview.py +++ b/esphome/components/lvgl/widgets/tabview.py @@ -26,7 +26,7 @@ from ..schemas import container_schema, part_schema from ..types import LV_EVENT, LvType, ObjUpdateAction, lv_obj_t, lv_obj_t_ptr from . import Widget, WidgetType, add_widgets, get_widgets, set_obj_properties from .button import button_spec -from .buttonmatrix import buttonmatrix_spec +from .buttonmatrix import CONF_BUTTONMATRIX, buttonmatrix_spec from .obj import obj_spec CONF_TABVIEW = "tabview" @@ -73,7 +73,7 @@ class TabviewType(WidgetType): ) def get_uses(self): - return "btnmatrix", TYPE_FLEX + return CONF_BUTTONMATRIX, TYPE_FLEX async def to_code(self, w: Widget, config: dict): await w.set_property( From 9dca7e0daf015db9a2dbe1cad391a000df335ae6 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:01:33 -0400 Subject: [PATCH 1839/2030] [tormatic] Fix UART stream desync on ESP32 (#15337) --- .../components/tormatic/tormatic_cover.cpp | 67 ++++++++++++++----- esphome/components/tormatic/tormatic_cover.h | 1 + 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index 77c2e87717..a58228a219 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -10,6 +10,10 @@ namespace tormatic { static const char *const TAG = "tormatic.cover"; +// Time to poll the UART when flushing after desync. At 9600 baud, a full +// 12-byte message takes ~12.5ms, so 15ms guarantees all bytes have arrived. +static constexpr uint32_t DRAIN_TIMEOUT_MS = 15; + using namespace esphome::cover; void Tormatic::setup() { @@ -256,32 +260,51 @@ void Tormatic::stop_at_target_() { // Read a GateStatus from the unit. The unit only sends messages in response to // status requests or commands, so a message needs to be sent first. optional<GateStatus> Tormatic::read_gate_status_() { - if (this->available() < sizeof(MessageHeader)) { + if (!this->pending_hdr_) { + if (this->available() < sizeof(MessageHeader)) { + return {}; + } + + this->pending_hdr_ = this->read_data_<MessageHeader>(); + if (!this->pending_hdr_) { + return {}; + } + + // Sanity check: valid messages have small payloads (3-4 bytes). A large + // or impossible payload_size means the stream is out of sync (corrupted + // byte, dropped data, etc.). Flush the buffer so we can resync on the + // next request/response cycle. + if (this->pending_hdr_->payload_size() > sizeof(CommandRequestReply)) { + ESP_LOGW(TAG, "Unexpected payload size %" PRIu32 ", flushing rx buffer", this->pending_hdr_->payload_size()); + this->pending_hdr_.reset(); + this->drain_rx_(); + return {}; + } + } + + // Wait for all payload bytes to arrive before processing. + if (this->available() < this->pending_hdr_->payload_size()) { return {}; } - auto o_hdr = this->read_data_<MessageHeader>(); - if (!o_hdr) { - ESP_LOGE(TAG, "Timeout reading message header"); - return {}; - } - auto hdr = o_hdr.value(); + auto hdr = *this->pending_hdr_; + this->pending_hdr_.reset(); switch (hdr.type) { case STATUS: { if (hdr.payload_size() != sizeof(StatusReply)) { ESP_LOGE(TAG, "Header specifies payload size %" PRIu32 " but size of StatusReply is %zu", hdr.payload_size(), sizeof(StatusReply)); + this->drain_rx_(hdr.payload_size()); + return {}; } - // Read a StatusReply requested by update(). auto o_status = this->read_data_<StatusReply>(); if (!o_status) { return {}; } - auto status = o_status.value(); - return status.state; + return o_status->state; } case COMMAND: @@ -344,16 +367,24 @@ template<typename T> optional<T> Tormatic::read_data_() { return obj; } -// Drain up to n amount of bytes from the uart rx buffer. +// Drain bytes from the uart rx buffer. When n > 0, drain exactly n bytes +// (caller must ensure they are available). When n == 0, poll for 15ms to +// guarantee a full packet time at 9600 baud has elapsed, consuming any +// bytes still in transit. void Tormatic::drain_rx_(uint16_t n) { uint8_t data; - uint16_t count = 0; - while (this->available()) { - this->read_byte(&data); - count++; - - if (n > 0 && count >= n) { - return; + if (n > 0) { + for (uint16_t i = 0; i < n; i++) { + if (!this->read_byte(&data)) { + return; + } + } + } else { + uint32_t start = millis(); + while (millis() - start < DRAIN_TIMEOUT_MS) { + if (this->available()) { + this->read_byte(&data); + } } } } diff --git a/esphome/components/tormatic/tormatic_cover.h b/esphome/components/tormatic/tormatic_cover.h index 534d4bef14..34483ed6a3 100644 --- a/esphome/components/tormatic/tormatic_cover.h +++ b/esphome/components/tormatic/tormatic_cover.h @@ -43,6 +43,7 @@ class Tormatic : public cover::Cover, public uart::UARTDevice, public PollingCom void handle_gate_status_(GateStatus s); uint32_t seq_tx_{0}; + optional<MessageHeader> pending_hdr_{}; GateStatus current_status_{PAUSED}; From 23dcc5389d12cf4bbfccc0238c959ba84aa77f13 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 12:59:45 -1000 Subject: [PATCH 1840/2030] [time] Fix strftime %Z and %z returning wrong timezone (#15330) --- esphome/components/time/posix_tz.cpp | 13 +++++++ esphome/components/time/posix_tz.h | 3 ++ esphome/core/time.cpp | 54 ++++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/esphome/components/time/posix_tz.cpp b/esphome/components/time/posix_tz.cpp index 4d1f0c74c2..f388267abd 100644 --- a/esphome/components/time/posix_tz.cpp +++ b/esphome/components/time/posix_tz.cpp @@ -4,6 +4,7 @@ #include "posix_tz.h" #include <cctype> +#include <cstdio> namespace esphome::time { @@ -442,6 +443,18 @@ bool parse_posix_tz(const char *tz_string, ParsedTimezone &result) { return internal::parse_dst_rule(p, result.dst_end); } +// Format a POSIX offset (positive = west) as "+HHMM" / "-HHMM" for display. +// Convention: negate POSIX sign so east-of-UTC is positive (ISO 8601 / RFC 2822). +void format_designation(int32_t posix_offset, char *buf, size_t buf_size) { + int32_t display = -posix_offset; + char sign = display >= 0 ? '+' : '-'; + if (display < 0) + display = -display; + int h = display / 3600; + int m = (display % 3600) / 60; + snprintf(buf, buf_size, "%c%02d%02d", sign, h, m); +} + bool epoch_to_local_tm(time_t utc_epoch, const ParsedTimezone &tz, struct tm *out_tm) { if (!out_tm) { return false; diff --git a/esphome/components/time/posix_tz.h b/esphome/components/time/posix_tz.h index c71ba15cd1..be1ddfd689 100644 --- a/esphome/components/time/posix_tz.h +++ b/esphome/components/time/posix_tz.h @@ -36,6 +36,9 @@ struct ParsedTimezone { bool has_dst() const { return this->dst_start.type != DSTRuleType::NONE; } }; +/// Format a POSIX offset as "+HHMM"/"-HHMM" into buf (must be >= 6 bytes). +void format_designation(int32_t posix_offset, char *buf, size_t buf_size); + /// Parse a POSIX TZ string into a ParsedTimezone struct. /// /// @deprecated Remove before 2026.9.0 (bridge code for backward compatibility). diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 650c61d37b..b6fc9b90ad 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -2,6 +2,9 @@ #include "helpers.h" #include <algorithm> +#ifdef USE_TIME_TIMEZONE +#include "esphome/components/time/posix_tz.h" +#endif namespace esphome { @@ -14,12 +17,59 @@ uint8_t days_in_month(uint8_t month, uint16_t year) { size_t ESPTime::strftime(char *buffer, size_t buffer_len, const char *format) { struct tm c_tm = this->to_c_tm(); +#ifdef USE_TIME_TIMEZONE + // ::strftime uses libc's internal timezone state for %Z and %z, but we + // eliminated setenv("TZ")/tzset() on embedded platforms to save flash. + // Substitute %Z and %z with correct values from our parsed timezone. + // Quick scan: does format contain %Z or %z (but not %%Z/%%z)? + bool needs_subst = false; + for (const char *p = format; *p; p++) { + if (*p == '%' && *(p + 1)) { + p++; + if (*p == '%') + continue; // %% is a literal %, skip + if (*p == 'Z' || *p == 'z') { + needs_subst = true; + break; + } + } + } + if (needs_subst) { + const auto &tz = time::get_global_tz(); + char designation[6]; // "+HHMM" + null + int32_t offset = c_tm.tm_isdst > 0 ? tz.dst_offset_seconds : tz.std_offset_seconds; + time::format_designation(offset, designation, sizeof(designation)); + + char modified[STRFTIME_BUFFER_SIZE]; + char *out = modified; + char *out_end = modified + sizeof(modified) - 1; + for (const char *p = format; *p && out < out_end; p++) { + if (*p == '%') { + if (*(p + 1) == '%') { + // %% → copy both percent signs (literal %) + *out++ = *p++; + if (out < out_end) + *out++ = *p; + } else if (*(p + 1) == 'Z' || *(p + 1) == 'z') { + p++; // skip the Z/z + for (const char *d = designation; *d && out < out_end; d++) + *out++ = *d; + } else { + *out++ = *p; + } + } else { + *out++ = *p; + } + } + *out = '\0'; + return ::strftime(buffer, buffer_len, modified, &c_tm); + } +#endif return ::strftime(buffer, buffer_len, format, &c_tm); } size_t ESPTime::strftime_to(std::span<char, STRFTIME_BUFFER_SIZE> buffer, const char *format) { - struct tm c_tm = this->to_c_tm(); - size_t len = ::strftime(buffer.data(), buffer.size(), format, &c_tm); + size_t len = this->strftime(buffer.data(), buffer.size(), format); if (len > 0) { return len; } From 15bcd62f222ce4e24be1ea3f6e37b0d1c0b04cab Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 1 Apr 2026 11:59:53 +1300 Subject: [PATCH 1841/2030] [internal_temperature] Move code into platform specific files (#15339) --- .../internal_temperature.h | 10 +- .../internal_temperature_bk72xx.cpp | 41 ++++++++ .../internal_temperature_common.cpp | 10 ++ ...ure.cpp => internal_temperature_esp32.cpp} | 96 ++----------------- .../internal_temperature_rp2040.cpp | 31 ++++++ .../internal_temperature_zephyr.cpp | 56 +++++++++++ .../components/internal_temperature/sensor.py | 17 ++++ 7 files changed, 170 insertions(+), 91 deletions(-) create mode 100644 esphome/components/internal_temperature/internal_temperature_bk72xx.cpp create mode 100644 esphome/components/internal_temperature/internal_temperature_common.cpp rename esphome/components/internal_temperature/{internal_temperature.cpp => internal_temperature_esp32.cpp} (54%) create mode 100644 esphome/components/internal_temperature/internal_temperature_rp2040.cpp create mode 100644 esphome/components/internal_temperature/internal_temperature_zephyr.cpp diff --git a/esphome/components/internal_temperature/internal_temperature.h b/esphome/components/internal_temperature/internal_temperature.h index 78e3bcef7d..4810e8478d 100644 --- a/esphome/components/internal_temperature/internal_temperature.h +++ b/esphome/components/internal_temperature/internal_temperature.h @@ -1,18 +1,18 @@ #pragma once -#include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" -namespace esphome { -namespace internal_temperature { +namespace esphome::internal_temperature { class InternalTemperatureSensor : public sensor::Sensor, public PollingComponent { public: +#if defined(USE_ESP32) || (defined(USE_ZEPHYR) && defined(USE_NRF52)) void setup() override; +#endif // USE_ESP32 || (USE_ZEPHYR && USE_NRF52) void dump_config() override; void update() override; }; -} // namespace internal_temperature -} // namespace esphome +} // namespace esphome::internal_temperature diff --git a/esphome/components/internal_temperature/internal_temperature_bk72xx.cpp b/esphome/components/internal_temperature/internal_temperature_bk72xx.cpp new file mode 100644 index 0000000000..31a92f90a5 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature_bk72xx.cpp @@ -0,0 +1,41 @@ +#ifdef USE_BK72XX + +#include "esphome/core/log.h" +#include "internal_temperature.h" + +extern "C" { +uint32_t temp_single_get_current_temperature(uint32_t *temp_value); +} + +namespace esphome::internal_temperature { + +static const char *const TAG = "internal_temperature.bk72xx"; + +void InternalTemperatureSensor::update() { + float temperature = NAN; + bool success = false; + + uint32_t raw, result; + result = temp_single_get_current_temperature(&raw); + success = (result == 0); +#if defined(USE_LIBRETINY_VARIANT_BK7231N) + temperature = raw * -0.38f + 156.0f; +#elif defined(USE_LIBRETINY_VARIANT_BK7231T) + temperature = raw * 0.04f; +#else // USE_LIBRETINY_VARIANT + temperature = raw * 0.128f; +#endif // USE_LIBRETINY_VARIANT + + if (success && std::isfinite(temperature)) { + this->publish_state(temperature); + } else { + ESP_LOGD(TAG, "Ignoring invalid temperature (success=%d, value=%.1f)", success, temperature); + if (!this->has_state()) { + this->publish_state(NAN); + } + } +} + +} // namespace esphome::internal_temperature + +#endif // USE_BK72XX diff --git a/esphome/components/internal_temperature/internal_temperature_common.cpp b/esphome/components/internal_temperature/internal_temperature_common.cpp new file mode 100644 index 0000000000..89a7d34333 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature_common.cpp @@ -0,0 +1,10 @@ +#include "esphome/core/log.h" +#include "internal_temperature.h" + +namespace esphome::internal_temperature { + +static const char *const TAG = "internal_temperature"; + +void InternalTemperatureSensor::dump_config() { LOG_SENSOR("", "Internal Temperature Sensor", this); } + +} // namespace esphome::internal_temperature diff --git a/esphome/components/internal_temperature/internal_temperature.cpp b/esphome/components/internal_temperature/internal_temperature_esp32.cpp similarity index 54% rename from esphome/components/internal_temperature/internal_temperature.cpp rename to esphome/components/internal_temperature/internal_temperature_esp32.cpp index 567ae6170e..09121fa9c9 100644 --- a/esphome/components/internal_temperature/internal_temperature.cpp +++ b/esphome/components/internal_temperature/internal_temperature_esp32.cpp @@ -1,7 +1,8 @@ -#include "internal_temperature.h" -#include "esphome/core/log.h" - #ifdef USE_ESP32 + +#include "esphome/core/log.h" +#include "internal_temperature.h" + #if defined(USE_ESP32_VARIANT_ESP32) // there is no official API available on the original ESP32 extern "C" { @@ -13,70 +14,20 @@ uint8_t temprature_sens_read(); defined(USE_ESP32_VARIANT_ESP32S3) #include "driver/temperature_sensor.h" #endif // USE_ESP32_VARIANT -#endif // USE_ESP32 -#ifdef USE_RP2040 -#include "Arduino.h" -#endif // USE_RP2040 -#ifdef USE_BK72XX -extern "C" { -uint32_t temp_single_get_current_temperature(uint32_t *temp_value); -} -#endif // USE_BK72XX -#if defined(USE_ZEPHYR) && defined(USE_NRF52) -#include <zephyr/device.h> -#include <zephyr/drivers/sensor.h> -#endif // USE_ZEPHYR && USE_NRF52 -namespace esphome { -namespace internal_temperature { +namespace esphome::internal_temperature { + +static const char *const TAG = "internal_temperature.esp32"; -static const char *const TAG = "internal_temperature"; -#if defined(USE_ZEPHYR) && defined(USE_NRF52) -static const struct device *const DIE_TEMPERATURE_SENSOR = DEVICE_DT_GET_ONE(nordic_nrf_temp); -#endif // USE_ZEPHYR && USE_NRF52 -#ifdef USE_ESP32 #if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \ defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \ defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) static temperature_sensor_handle_t tsensNew = NULL; #endif // USE_ESP32_VARIANT -#endif // USE_ESP32 void InternalTemperatureSensor::update() { -#if defined(USE_ZEPHYR) && defined(USE_NRF52) - struct sensor_value value; - int result = sensor_sample_fetch(DIE_TEMPERATURE_SENSOR); - if (result != 0) { - ESP_LOGE(TAG, "Failed to fetch nRF52 die temperature sample (%d)", result); - if (!this->has_state()) { - this->publish_state(NAN); - } - return; - } - - result = sensor_channel_get(DIE_TEMPERATURE_SENSOR, SENSOR_CHAN_DIE_TEMP, &value); - if (result != 0) { - ESP_LOGE(TAG, "Failed to get nRF52 die temperature (%d)", result); - if (!this->has_state()) { - this->publish_state(NAN); - } - return; - } - - const float temperature = value.val1 + (value.val2 / 1000000.0f); - if (std::isfinite(temperature)) { - this->publish_state(temperature); - } else { - ESP_LOGD(TAG, "Ignoring invalid nRF52 temperature (value=%.1f)", temperature); - if (!this->has_state()) { - this->publish_state(NAN); - } - } -#else - float temperature = NAN; bool success = false; -#ifdef USE_ESP32 #if defined(USE_ESP32_VARIANT_ESP32) uint8_t raw = temprature_sens_read(); ESP_LOGV(TAG, "Raw temperature value: %d", raw); @@ -92,23 +43,7 @@ void InternalTemperatureSensor::update() { ESP_LOGE(TAG, "Reading failed (%d)", result); } #endif // USE_ESP32_VARIANT -#endif // USE_ESP32 -#ifdef USE_RP2040 - temperature = analogReadTemp(); - success = (temperature != 0.0f); -#endif // USE_RP2040 -#ifdef USE_BK72XX - uint32_t raw, result; - result = temp_single_get_current_temperature(&raw); - success = (result == 0); -#if defined(USE_LIBRETINY_VARIANT_BK7231N) - temperature = raw * -0.38f + 156.0f; -#elif defined(USE_LIBRETINY_VARIANT_BK7231T) - temperature = raw * 0.04f; -#else // USE_LIBRETINY_VARIANT - temperature = raw * 0.128f; -#endif // USE_LIBRETINY_VARIANT -#endif // USE_BK72XX + if (success && std::isfinite(temperature)) { this->publish_state(temperature); } else { @@ -117,18 +52,9 @@ void InternalTemperatureSensor::update() { this->publish_state(NAN); } } -#endif // USE_ZEPHYR && USE_NRF52 } void InternalTemperatureSensor::setup() { -#if defined(USE_ZEPHYR) && defined(USE_NRF52) - if (!device_is_ready(DIE_TEMPERATURE_SENSOR)) { - ESP_LOGE(TAG, "nRF52 die temperature sensor device %s not ready", DIE_TEMPERATURE_SENSOR->name); - this->mark_failed(); - return; - } -#endif // USE_ZEPHYR && USE_NRF52 -#ifdef USE_ESP32 #if defined(USE_ESP32_VARIANT_ESP32C2) || defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || \ defined(USE_ESP32_VARIANT_ESP32C6) || defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32H2) || \ defined(USE_ESP32_VARIANT_ESP32P4) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) @@ -148,10 +74,8 @@ void InternalTemperatureSensor::setup() { return; } #endif // USE_ESP32_VARIANT -#endif // USE_ESP32 } -void InternalTemperatureSensor::dump_config() { LOG_SENSOR("", "Internal Temperature Sensor", this); } +} // namespace esphome::internal_temperature -} // namespace internal_temperature -} // namespace esphome +#endif // USE_ESP32 diff --git a/esphome/components/internal_temperature/internal_temperature_rp2040.cpp b/esphome/components/internal_temperature/internal_temperature_rp2040.cpp new file mode 100644 index 0000000000..66dee9faf7 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature_rp2040.cpp @@ -0,0 +1,31 @@ +#ifdef USE_RP2040 + +#include "esphome/core/log.h" +#include "internal_temperature.h" + +#include "Arduino.h" + +namespace esphome::internal_temperature { + +static const char *const TAG = "internal_temperature.rp2040"; + +void InternalTemperatureSensor::update() { + float temperature = NAN; + bool success = false; + + temperature = analogReadTemp(); + success = (temperature != 0.0f); + + if (success && std::isfinite(temperature)) { + this->publish_state(temperature); + } else { + ESP_LOGD(TAG, "Ignoring invalid temperature (success=%d, value=%.1f)", success, temperature); + if (!this->has_state()) { + this->publish_state(NAN); + } + } +} + +} // namespace esphome::internal_temperature + +#endif // USE_RP2040 diff --git a/esphome/components/internal_temperature/internal_temperature_zephyr.cpp b/esphome/components/internal_temperature/internal_temperature_zephyr.cpp new file mode 100644 index 0000000000..be72ab6f51 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature_zephyr.cpp @@ -0,0 +1,56 @@ +#if defined(USE_ZEPHYR) && defined(USE_NRF52) + +#include "esphome/core/log.h" +#include "internal_temperature.h" + +#include <zephyr/device.h> +#include <zephyr/drivers/sensor.h> + +namespace esphome::internal_temperature { + +static const char *const TAG = "internal_temperature.zephyr"; + +static const struct device *const DIE_TEMPERATURE_SENSOR = DEVICE_DT_GET_ONE(nordic_nrf_temp); + +void InternalTemperatureSensor::update() { + struct sensor_value value; + int result = sensor_sample_fetch(DIE_TEMPERATURE_SENSOR); + if (result != 0) { + ESP_LOGE(TAG, "Failed to fetch nRF52 die temperature sample (%d)", result); + if (!this->has_state()) { + this->publish_state(NAN); + } + return; + } + + result = sensor_channel_get(DIE_TEMPERATURE_SENSOR, SENSOR_CHAN_DIE_TEMP, &value); + if (result != 0) { + ESP_LOGE(TAG, "Failed to get nRF52 die temperature (%d)", result); + if (!this->has_state()) { + this->publish_state(NAN); + } + return; + } + + const float temperature = value.val1 + (value.val2 / 1000000.0f); + if (std::isfinite(temperature)) { + this->publish_state(temperature); + } else { + ESP_LOGD(TAG, "Ignoring invalid nRF52 temperature (value=%.1f)", temperature); + if (!this->has_state()) { + this->publish_state(NAN); + } + } +} + +void InternalTemperatureSensor::setup() { + if (!device_is_ready(DIE_TEMPERATURE_SENSOR)) { + ESP_LOGE(TAG, "nRF52 die temperature sensor device %s not ready", DIE_TEMPERATURE_SENSOR->name); + this->mark_failed(); + return; + } +} + +} // namespace esphome::internal_temperature + +#endif // USE_ZEPHYR && USE_NRF52 diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py index 965e7f0520..6d79e08675 100644 --- a/esphome/components/internal_temperature/sensor.py +++ b/esphome/components/internal_temperature/sensor.py @@ -1,6 +1,7 @@ import esphome.codegen as cg from esphome.components import sensor from esphome.components.zephyr import zephyr_add_prj_conf +from esphome.config_helpers import filter_source_files_from_platform import esphome.config_validation as cv from esphome.const import ( DEVICE_CLASS_TEMPERATURE, @@ -11,6 +12,7 @@ from esphome.const import ( PLATFORM_RP2040, STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, + PlatformFramework, ) from esphome.core import CORE @@ -39,3 +41,18 @@ async def to_code(config): if CORE.using_zephyr and CORE.is_nrf52: zephyr_add_prj_conf("SENSOR", True) zephyr_add_prj_conf("TEMP_NRF5", True) + + +FILTER_SOURCE_FILES = filter_source_files_from_platform( + { + "internal_temperature_esp32.cpp": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, + }, + "internal_temperature_rp2040.cpp": {PlatformFramework.RP2040_ARDUINO}, + "internal_temperature_bk72xx.cpp": { + PlatformFramework.BK72XX_ARDUINO, + }, + "internal_temperature_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR}, + } +) From b71c406e704f1d751484404737a91c2b8035ddbb Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 1 Apr 2026 01:04:07 +0200 Subject: [PATCH 1842/2030] [uart] fix baud rate not applied on `load_settings()` for ESP32 (IDF) (#15341) --- .../uart/uart_component_esp_idf.cpp | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 6d9d44e97f..93e43e0372 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -147,6 +147,20 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + // uart_param_config must be called after uart_driver_install and before any + // other uart_set_*() calls. The driver installation resets the UART peripheral + // registers to their default state, overwriting any previously configured baud + // rate or framing settings. Calling uart_param_config here ensures the requested + // settings are applied after the reset and before pin routing, inversion, and + // threshold configuration. + uart_config_t uart_config = this->get_config_(); + err = uart_param_config(this->uart_num_, &uart_config); + if (err != ESP_OK) { + ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); + this->mark_failed(); + return; + } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; @@ -214,22 +228,15 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + // Per ESP-IDF docs, uart_set_mode() must be called only after uart_driver_install(). auto mode = this->flow_control_pin_ != nullptr ? UART_MODE_RS485_HALF_DUPLEX : UART_MODE_UART; - err = uart_set_mode(this->uart_num_, mode); // per docs, must be called only after uart_driver_install() + err = uart_set_mode(this->uart_num_, mode); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_set_mode failed: %s", esp_err_to_name(err)); this->mark_failed(); return; } - uart_config_t uart_config = this->get_config_(); - err = uart_param_config(this->uart_num_, &uart_config); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - #ifdef USE_UART_WAKE_LOOP_ON_RX // Register ISR callback to wake the main loop when UART data arrives. // The callback runs in ISR context and uses vTaskNotifyGiveFromISR() to From 4a23ba7d8a2b28f5245674fc8337227e6f50ed08 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 31 Mar 2026 19:06:48 -0400 Subject: [PATCH 1843/2030] [mixer] Fix memory leak in mixer task on stop/start cycles (#15185) --- .../mixer/speaker/mixer_speaker.cpp | 274 +++++++++--------- 1 file changed, 137 insertions(+), 137 deletions(-) diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 9d11abb327..0fabc68c70 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -597,173 +597,173 @@ void MixerSpeaker::audio_mixer_task(void *params) { xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STARTING); - std::unique_ptr<audio::AudioSinkTransferBuffer> output_transfer_buffer = audio::AudioSinkTransferBuffer::create( - this_mixer->audio_stream_info_.value().ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); + { // Ensure C++ objects fall out of scope to ensure proper cleanup before stopping the task + std::unique_ptr<audio::AudioSinkTransferBuffer> output_transfer_buffer = audio::AudioSinkTransferBuffer::create( + this_mixer->audio_stream_info_.value().ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); - if (output_transfer_buffer == nullptr) { - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED | MIXER_TASK_ERR_ESP_NO_MEM); + if (output_transfer_buffer == nullptr) { + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED | MIXER_TASK_ERR_ESP_NO_MEM); - vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it - } - - output_transfer_buffer->set_sink(this_mixer->output_speaker_); - - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_RUNNING); - - bool sent_finished = false; - - // Pre-allocate vectors to avoid heap allocation in the loop (max 8 source speakers per schema) - FixedVector<SourceSpeaker *> speakers_with_data; - FixedVector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; - speakers_with_data.init(this_mixer->source_speakers_.size()); - transfer_buffers_with_data.init(this_mixer->source_speakers_.size()); - - while (true) { - uint32_t event_group_bits = xEventGroupGetBits(this_mixer->event_group_); - if (event_group_bits & MIXER_TASK_COMMAND_STOP) { - break; + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } - // Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves - output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false); + output_transfer_buffer->set_sink(this_mixer->output_speaker_); - const uint32_t output_frames_free = - this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free()); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_RUNNING); - speakers_with_data.clear(); - transfer_buffers_with_data.clear(); + bool sent_finished = false; - for (auto &speaker : this_mixer->source_speakers_) { - if (speaker->is_running() && !speaker->get_pause_state()) { - // Speaker is running and not paused, so it possibly can provide audio data - std::shared_ptr<audio::AudioSourceTransferBuffer> transfer_buffer = speaker->get_transfer_buffer().lock(); - if (transfer_buffer.use_count() == 0) { - // No transfer buffer allocated, so skip processing this speaker - continue; - } - speaker->process_data_from_source(transfer_buffer, 0); // Transfers and ducks audio from source ring buffers + // Pre-allocate vectors to avoid heap allocation in the loop (max 8 source speakers per schema) + FixedVector<SourceSpeaker *> speakers_with_data; + FixedVector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; + speakers_with_data.init(this_mixer->source_speakers_.size()); + transfer_buffers_with_data.init(this_mixer->source_speakers_.size()); - if (transfer_buffer->available() > 0) { - // Store the locked transfer buffers in their own vector to avoid releasing ownership until after the loop - transfer_buffers_with_data.push_back(transfer_buffer); - speakers_with_data.push_back(speaker); + while (true) { + uint32_t event_group_bits = xEventGroupGetBits(this_mixer->event_group_); + if (event_group_bits & MIXER_TASK_COMMAND_STOP) { + break; + } + + // Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves + output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false); + + const uint32_t output_frames_free = + this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free()); + + speakers_with_data.clear(); + transfer_buffers_with_data.clear(); + + for (auto &speaker : this_mixer->source_speakers_) { + if (speaker->is_running() && !speaker->get_pause_state()) { + // Speaker is running and not paused, so it possibly can provide audio data + std::shared_ptr<audio::AudioSourceTransferBuffer> transfer_buffer = speaker->get_transfer_buffer().lock(); + if (transfer_buffer.use_count() == 0) { + // No transfer buffer allocated, so skip processing this speaker + continue; + } + speaker->process_data_from_source(transfer_buffer, 0); // Transfers and ducks audio from source ring buffers + + if (transfer_buffer->available() > 0) { + // Store the locked transfer buffers in their own vector to avoid releasing ownership until after the loop + transfer_buffers_with_data.push_back(transfer_buffer); + speakers_with_data.push_back(speaker); + } } } - } - if (transfer_buffers_with_data.empty()) { - // No audio available for transferring, block task temporarily - delay(TASK_DELAY_MS); - continue; - } + if (transfer_buffers_with_data.empty()) { + // No audio available for transferring, block task temporarily + delay(TASK_DELAY_MS); + continue; + } - uint32_t frames_to_mix = output_frames_free; + uint32_t frames_to_mix = output_frames_free; - if ((transfer_buffers_with_data.size() == 1) || this_mixer->queue_mode_) { - // Only one speaker has audio data, just copy samples over + if ((transfer_buffers_with_data.size() == 1) || this_mixer->queue_mode_) { + // Only one speaker has audio data, just copy samples over - audio::AudioStreamInfo active_stream_info = speakers_with_data[0]->get_audio_stream_info(); + audio::AudioStreamInfo active_stream_info = speakers_with_data[0]->get_audio_stream_info(); - if (active_stream_info.get_sample_rate() == - this_mixer->output_speaker_->get_audio_stream_info().get_sample_rate()) { - // Speaker's sample rate matches the output speaker's, copy directly + if (active_stream_info.get_sample_rate() == + this_mixer->output_speaker_->get_audio_stream_info().get_sample_rate()) { + // Speaker's sample rate matches the output speaker's, copy directly - const uint32_t frames_available_in_buffer = - active_stream_info.bytes_to_frames(transfer_buffers_with_data[0]->available()); - frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); - copy_frames(reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()), active_stream_info, - reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), - this_mixer->audio_stream_info_.value(), frames_to_mix); + const uint32_t frames_available_in_buffer = + active_stream_info.bytes_to_frames(transfer_buffers_with_data[0]->available()); + frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); + copy_frames(reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()), + active_stream_info, reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), + this_mixer->audio_stream_info_.value(), frames_to_mix); - // Set playback delay for newly contributing source - if (!speakers_with_data[0]->has_contributed_.load(std::memory_order_acquire)) { - speakers_with_data[0]->playback_delay_frames_.store( - this_mixer->frames_in_pipeline_.load(std::memory_order_acquire), std::memory_order_release); - speakers_with_data[0]->has_contributed_.store(true, std::memory_order_release); + // Set playback delay for newly contributing source + if (!speakers_with_data[0]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[0]->playback_delay_frames_.store( + this_mixer->frames_in_pipeline_.load(std::memory_order_acquire), std::memory_order_release); + speakers_with_data[0]->has_contributed_.store(true, std::memory_order_release); + } + + // Update source speaker pending frames + speakers_with_data[0]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); + transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); + + // Update output transfer buffer length and pipeline frame count + output_transfer_buffer->increase_buffer_length( + this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); + this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); + } else { + // Speaker's stream info doesn't match the output speaker's, so it's a new source speaker + if (!this_mixer->output_speaker_->is_stopped()) { + if (!sent_finished) { + this_mixer->output_speaker_->finish(); + sent_finished = true; // Avoid repeatedly sending the finish command + } + } else { + // Speaker has finished writing the current audio, update the stream information and restart the speaker + this_mixer->audio_stream_info_ = + audio::AudioStreamInfo(active_stream_info.get_bits_per_sample(), this_mixer->output_channels_, + active_stream_info.get_sample_rate()); + this_mixer->output_speaker_->set_audio_stream_info(this_mixer->audio_stream_info_.value()); + this_mixer->output_speaker_->start(); + // Reset pipeline frame count since we're starting fresh with a new sample rate + this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); + sent_finished = false; + } + } + } else { + // Determine how many frames to mix + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { + const uint32_t frames_available_in_buffer = speakers_with_data[i]->get_audio_stream_info().bytes_to_frames( + transfer_buffers_with_data[i]->available()); + frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); + } + int16_t *primary_buffer = reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()); + audio::AudioStreamInfo primary_stream_info = speakers_with_data[0]->get_audio_stream_info(); + + // Mix two streams together + for (size_t i = 1; i < transfer_buffers_with_data.size(); ++i) { + mix_audio_samples(primary_buffer, primary_stream_info, + reinterpret_cast<int16_t *>(transfer_buffers_with_data[i]->get_buffer_start()), + speakers_with_data[i]->get_audio_stream_info(), + reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), + this_mixer->audio_stream_info_.value(), frames_to_mix); + + if (i != transfer_buffers_with_data.size() - 1) { + // Need to mix more streams together, point primary buffer and stream info to the already mixed output + primary_buffer = reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()); + primary_stream_info = this_mixer->audio_stream_info_.value(); + } } - // Update source speaker pending frames - speakers_with_data[0]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); - transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); + // Get current pipeline depth for delay calculation (before incrementing) + uint32_t current_pipeline_frames = this_mixer->frames_in_pipeline_.load(std::memory_order_acquire); - // Update output transfer buffer length and pipeline frame count + // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { + // Set playback delay for newly contributing sources + if (!speakers_with_data[i]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[i]->playback_delay_frames_.store(current_pipeline_frames, std::memory_order_release); + speakers_with_data[i]->has_contributed_.store(true, std::memory_order_release); + } + + speakers_with_data[i]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); + transfer_buffers_with_data[i]->decrease_buffer_length( + speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); + } + + // Update output transfer buffer length and pipeline frame count (once, not per source) output_transfer_buffer->increase_buffer_length( this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); - } else { - // Speaker's stream info doesn't match the output speaker's, so it's a new source speaker - if (!this_mixer->output_speaker_->is_stopped()) { - if (!sent_finished) { - this_mixer->output_speaker_->finish(); - sent_finished = true; // Avoid repeatedly sending the finish command - } - } else { - // Speaker has finished writing the current audio, update the stream information and restart the speaker - this_mixer->audio_stream_info_ = - audio::AudioStreamInfo(active_stream_info.get_bits_per_sample(), this_mixer->output_channels_, - active_stream_info.get_sample_rate()); - this_mixer->output_speaker_->set_audio_stream_info(this_mixer->audio_stream_info_.value()); - this_mixer->output_speaker_->start(); - // Reset pipeline frame count since we're starting fresh with a new sample rate - this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); - sent_finished = false; - } } - } else { - // Determine how many frames to mix - for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { - const uint32_t frames_available_in_buffer = - speakers_with_data[i]->get_audio_stream_info().bytes_to_frames(transfer_buffers_with_data[i]->available()); - frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); - } - int16_t *primary_buffer = reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()); - audio::AudioStreamInfo primary_stream_info = speakers_with_data[0]->get_audio_stream_info(); - - // Mix two streams together - for (size_t i = 1; i < transfer_buffers_with_data.size(); ++i) { - mix_audio_samples(primary_buffer, primary_stream_info, - reinterpret_cast<int16_t *>(transfer_buffers_with_data[i]->get_buffer_start()), - speakers_with_data[i]->get_audio_stream_info(), - reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), - this_mixer->audio_stream_info_.value(), frames_to_mix); - - if (i != transfer_buffers_with_data.size() - 1) { - // Need to mix more streams together, point primary buffer and stream info to the already mixed output - primary_buffer = reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()); - primary_stream_info = this_mixer->audio_stream_info_.value(); - } - } - - // Get current pipeline depth for delay calculation (before incrementing) - uint32_t current_pipeline_frames = this_mixer->frames_in_pipeline_.load(std::memory_order_acquire); - - // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks - for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { - // Set playback delay for newly contributing sources - if (!speakers_with_data[i]->has_contributed_.load(std::memory_order_acquire)) { - speakers_with_data[i]->playback_delay_frames_.store(current_pipeline_frames, std::memory_order_release); - speakers_with_data[i]->has_contributed_.store(true, std::memory_order_release); - } - - speakers_with_data[i]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); - transfer_buffers_with_data[i]->decrease_buffer_length( - speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); - } - - // Update output transfer buffer length and pipeline frame count (once, not per source) - output_transfer_buffer->increase_buffer_length( - this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); - this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); } - } - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPING); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPING); + } // Reset pipeline frame count since the task is stopping this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); - output_transfer_buffer.reset(); - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED); vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it From 954227b2031962cf074615981b471613206be47b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 13:26:26 -1000 Subject: [PATCH 1844/2030] [esp32_ble_tracker] Restart BLE scan after OTA failure (#15308) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp | 6 ++++++ esphome/components/esp32_ble_tracker/esp32_ble_tracker.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 6dce70f839..f2d60be641 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -88,12 +88,18 @@ void ESP32BLETracker::setup() { #ifdef USE_OTA_STATE_LISTENER void ESP32BLETracker::on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { if (state == ota::OTA_STARTED) { + this->scan_continuous_before_ota_ = this->scan_continuous_; this->stop_scan(); #ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT for (auto *client : this->clients_) { client->disconnect(); } #endif + } else if ((state == ota::OTA_ERROR || state == ota::OTA_ABORT) && this->scan_continuous_before_ota_) { + this->scan_continuous_before_ota_ = false; + this->scan_continuous_ = true; + // Do not restart scanning immediately here; allow loop() to + // safely restart scanning once the scanner and all clients are idle. } } #endif diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index ff69a4dcd2..43405b02b7 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -431,6 +431,9 @@ class ESP32BLETracker : public Component, ScannerState scanner_state_{ScannerState::IDLE}; bool scan_continuous_; bool scan_active_; +#ifdef USE_OTA_STATE_LISTENER + bool scan_continuous_before_ota_{false}; +#endif bool ble_was_disabled_{true}; bool raw_advertisements_{false}; bool parse_advertisements_{false}; From e261b5de655dbcda6a1fbda83aec1fbdfd8c5c1c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:22:25 -1000 Subject: [PATCH 1845/2030] [time] Point to valid IANA timezone list on validation failure (#15110) --- esphome/components/time/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 9821046a73..c31ccbc7ea 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -284,13 +284,23 @@ def validate_tz(value: str) -> str: tzfile = _load_tzdata(value) if tzfile is not None: value = _extract_tz_string(tzfile) + is_iana = True + else: + is_iana = False # Validate that the POSIX TZ string is parseable (skip empty strings) if value: try: parse_posix_tz_python(value) except ValueError as e: - raise cv.Invalid(f"Invalid POSIX timezone string '{value}': {e}") from e + if is_iana: + raise cv.Invalid(f"Invalid POSIX timezone string '{value}': {e}") from e + raise cv.Invalid( + f"Invalid POSIX timezone string '{value}': {e}. " + f"If you meant to use an IANA timezone, check the list of valid " + f"timezones at " + f"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones" + ) from e return value From f7b410fd0c14e0bf00bddab3f03227087957d7f3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 08:47:15 -1000 Subject: [PATCH 1846/2030] [wifi] Fix roaming attempt counter reset on disconnect during scan (#15099) --- esphome/components/wifi/wifi_component.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 09f883ed61..aa4e691cd0 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -269,11 +269,11 @@ bool CompactString::operator==(const StringRef &other) const { /// │ │ │ /// │ ┌──────────────┼──────────────┐ │ /// │ ↓ ↓ ↓ │ -/// │ scan error no better AP +10 dB better AP │ +/// │ disconnect no better AP +10 dB better AP │ /// │ │ │ │ │ /// │ ↓ ↓ ↓ │ /// │ ┌──────────────────────────────┐ ┌──────────────────────────┐ │ -/// │ │ → IDLE │ │ CONNECTING │ │ +/// │ │ → RECONNECTING │ │ CONNECTING │ │ /// │ │ (counter preserved) │ │ (process_roaming_scan_) │ │ /// │ └──────────────────────────────┘ └────────────┬─────────────┘ │ /// │ │ │ @@ -296,7 +296,7 @@ bool CompactString::operator==(const StringRef &other) const { /// │ Key behaviors: │ /// │ - After 3 checks: attempts >= 3, stop checking │ /// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │ -/// │ - Scan error (SCANNING→IDLE): counter preserved │ +/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ /// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │ /// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ /// └──────────────────────────────────────────────────────────────────────┘ @@ -2075,9 +2075,10 @@ void WiFiComponent::retry_connect() { ESP_LOGD(TAG, "Roam failed, reconnecting (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::SCANNING) { - // Roam scan failed (e.g., scan error on ESP8266) - go back to idle, keep counter - ESP_LOGD(TAG, "Roam scan failed (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); - this->roaming_state_ = RoamingState::IDLE; + // Disconnected during roam scan - transition to RECONNECTING so the attempts + // counter is preserved when reconnection succeeds (IDLE would reset it) + ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::IDLE) { // Not a roaming-triggered reconnect, reset state this->clear_roaming_state_(); From d9788aaefc337faaa20e4cde5681368ae3e18a4f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 23 Mar 2026 13:58:36 -1000 Subject: [PATCH 1847/2030] [wifi] Reduce ESP8266 roaming scan dwell time to match ESP32 (#15127) --- .../components/wifi/wifi_component_esp8266.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/esphome/components/wifi/wifi_component_esp8266.cpp b/esphome/components/wifi/wifi_component_esp8266.cpp index 5514f1c6be..517b59da37 100644 --- a/esphome/components/wifi/wifi_component_esp8266.cpp +++ b/esphome/components/wifi/wifi_component_esp8266.cpp @@ -664,11 +664,22 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { config.show_hidden = 1; #if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 4, 0) config.scan_type = passive ? WIFI_SCAN_TYPE_PASSIVE : WIFI_SCAN_TYPE_ACTIVE; + // Use shorter dwell times for roaming scans - we only need to detect strong + // nearby APs, not do a thorough survey. This also reduces off-channel time + // which can cause Beacon Timeout disconnects on some APs. + // Roaming times match the ESP32 IDF scan defaults. + static constexpr uint32_t SCAN_PASSIVE_DEFAULT_MS = 500; + static constexpr uint32_t SCAN_PASSIVE_ROAMING_MS = 300; + static constexpr uint32_t SCAN_ACTIVE_MIN_DEFAULT_MS = 400; + static constexpr uint32_t SCAN_ACTIVE_MAX_DEFAULT_MS = 500; + static constexpr uint32_t SCAN_ACTIVE_MIN_ROAMING_MS = 100; + static constexpr uint32_t SCAN_ACTIVE_MAX_ROAMING_MS = 300; + bool roaming = this->roaming_state_ == RoamingState::SCANNING; if (passive) { - config.scan_time.passive = 500; + config.scan_time.passive = roaming ? SCAN_PASSIVE_ROAMING_MS : SCAN_PASSIVE_DEFAULT_MS; } else { - config.scan_time.active.min = 400; - config.scan_time.active.max = 500; + config.scan_time.active.min = roaming ? SCAN_ACTIVE_MIN_ROAMING_MS : SCAN_ACTIVE_MIN_DEFAULT_MS; + config.scan_time.active.max = roaming ? SCAN_ACTIVE_MAX_ROAMING_MS : SCAN_ACTIVE_MAX_DEFAULT_MS; } #endif bool ret = wifi_station_scan(&config, &WiFiComponent::s_wifi_scan_done_callback); From 2f2c7ac393b23f52e660b928ace0fcd0becf9176 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:04:27 -0400 Subject: [PATCH 1848/2030] [sx127x] Fix FIFO read corruption (#15114) --- esphome/components/sx127x/sx127x.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index 66957a7342..0fddfdccdb 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -38,14 +38,18 @@ void SX127x::write_register_(uint8_t reg, uint8_t value) { void SX127x::read_fifo_(std::vector<uint8_t> &packet) { this->enable(); this->write_byte(REG_FIFO & 0x7F); - this->read_array(packet.data(), packet.size()); + for (auto &byte : packet) { + byte = this->transfer_byte(0x00); + } this->disable(); } void SX127x::write_fifo_(const std::vector<uint8_t> &packet) { this->enable(); this->write_byte(REG_FIFO | 0x80); - this->write_array(packet.data(), packet.size()); + for (const auto &byte : packet) { + this->transfer_byte(byte); + } this->disable(); } From cb15e98765e69377bf7369cf95fb21386dd21d57 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:03:56 -1000 Subject: [PATCH 1849/2030] [datetime] Fix state_as_esptime() returning invalid timestamp (#15128) --- .../components/datetime/datetime_entity.cpp | 3 + esphome/core/time.cpp | 2 +- esphome/core/time.h | 18 ++++-- tests/components/time/posix_tz_parser.cpp | 56 ++++++++++++++++++- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/esphome/components/datetime/datetime_entity.cpp b/esphome/components/datetime/datetime_entity.cpp index 730abb3ca8..fa50271f04 100644 --- a/esphome/components/datetime/datetime_entity.cpp +++ b/esphome/components/datetime/datetime_entity.cpp @@ -60,6 +60,9 @@ ESPTime DateTimeEntity::state_as_esptime() const { obj.year = this->year_; obj.month = this->month_; obj.day_of_month = this->day_; + obj.day_of_week = 0; + obj.day_of_year = 0; + obj.is_dst = false; obj.hour = this->hour_; obj.minute = this->minute_; obj.second = this->second_; diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 6add82e7d1..650c61d37b 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -231,7 +231,7 @@ void ESPTime::increment_day() { void ESPTime::recalc_timestamp_utc(bool use_day_of_year) { time_t res = 0; - if (!this->fields_in_range()) { + if (!this->fields_in_range(false, use_day_of_year)) { this->timestamp = -1; return; } diff --git a/esphome/core/time.h b/esphome/core/time.h index 1716c51ffd..ed47432038 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -79,11 +79,19 @@ struct ESPTime { /// Check if this ESPTime is valid (all fields in range and year is greater than or equal to 2019) bool is_valid() const { return this->year >= 2019 && this->fields_in_range(); } - /// Check if all time fields of this ESPTime are in range. - bool fields_in_range() const { - return this->second < 61 && this->minute < 60 && this->hour < 24 && this->day_of_week > 0 && - this->day_of_week < 8 && this->day_of_year > 0 && this->day_of_year < 367 && this->month > 0 && - this->month < 13 && this->day_of_month > 0 && this->day_of_month <= days_in_month(this->month, this->year); + /// Check if time fields are in range. + /// @param check_day_of_week validate day_of_week (not always available when constructing from date/time fields) + /// @param check_day_of_year validate day_of_year (not always available when constructing from date/time fields) + bool fields_in_range(bool check_day_of_week = true, bool check_day_of_year = true) const { + bool valid = this->second < 61 && this->minute < 60 && this->hour < 24 && this->month > 0 && this->month < 13 && + this->day_of_month > 0 && this->day_of_month <= days_in_month(this->month, this->year); + if (check_day_of_week) { + valid = valid && this->day_of_week > 0 && this->day_of_week < 8; + } + if (check_day_of_year) { + valid = valid && this->day_of_year > 0 && this->day_of_year < 367; + } + return valid; } /** Convert a string to ESPTime struct as specified by the format argument. diff --git a/tests/components/time/posix_tz_parser.cpp b/tests/components/time/posix_tz_parser.cpp index d1747ef5b1..b7cf2a4afa 100644 --- a/tests/components/time/posix_tz_parser.cpp +++ b/tests/components/time/posix_tz_parser.cpp @@ -1036,8 +1036,6 @@ static time_t esptime_recalc_local(int year, int month, int day, int hour, int m t.hour = hour; t.minute = min; t.second = sec; - t.day_of_week = 1; // Placeholder for fields_in_range() - t.day_of_year = 1; t.recalc_timestamp_local(); return t.timestamp; } @@ -1187,6 +1185,60 @@ TEST(RecalcTimestampLocal, NonDefaultTransitionTime) { EXPECT_EQ(esp_result, libc_result); } +TEST(RecalcTimestampLocal, MinimalFieldsWithoutDayOfWeekOrYear) { + // Regression test for issue #15115: DateTimeEntity::state_as_esptime() constructs + // an ESPTime with only year/month/day/hour/minute/second set (no day_of_week or + // day_of_year). recalc_timestamp_local() must work without those fields. + const char *tz_str = "CET-1CEST,M3.5.0,M10.5.0"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + // Construct ESPTime with only date/time fields (like state_as_esptime does) + ESPTime t{}; + t.year = 2026; + t.month = 3; + t.day_of_month = 20; + t.hour = 23; + t.minute = 14; + t.second = 55; + // day_of_week and day_of_year are deliberately left as 0 + t.recalc_timestamp_local(); + + // Must NOT return -1 (the bug: fields_in_range() rejected valid times) + EXPECT_NE(t.timestamp, -1); + + // Verify against libc + time_t libc_result = libc_mktime(2026, 3, 20, 23, 14, 55); + EXPECT_EQ(t.timestamp, libc_result); +} + +TEST(RecalcTimestampLocal, MinimalFieldsNoDST) { + // Same test but with a timezone that has no DST + const char *tz_str = "IST-5:30"; + setenv("TZ", tz_str, 1); + tzset(); + time::ParsedTimezone tz{}; + ASSERT_TRUE(parse_posix_tz(tz_str, tz)); + set_global_tz(tz); + + ESPTime t{}; + t.year = 2026; + t.month = 3; + t.day_of_month = 23; + t.hour = 10; + t.minute = 0; + t.second = 0; + t.recalc_timestamp_local(); + + EXPECT_NE(t.timestamp, -1); + + time_t libc_result = libc_mktime(2026, 3, 23, 10, 0, 0); + EXPECT_EQ(t.timestamp, libc_result); +} + TEST(RecalcTimestampLocal, YearBoundaryDST) { // Test southern hemisphere DST across year boundary // Australia/Sydney: DST active from October to April (spans Jan 1) From f5f99071fb51f9cd61ed3bcf2e2f63e3a1555c77 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 24 Mar 2026 14:04:17 -1000 Subject: [PATCH 1850/2030] [wifi] Fix roaming counter reset from delayed disconnect and successful retry (#15126) --- esphome/components/wifi/wifi_component.cpp | 66 +++++++++++++++++----- esphome/components/wifi/wifi_component.h | 6 ++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index aa4e691cd0..8656df7f4d 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -287,18 +287,25 @@ bool CompactString::operator==(const StringRef &other) const { /// │ │ (counter reset to 0) │ │ (retry_connect called) │ /// │ └──────────────────────────────────┘ └───────────┬─────────────┘ /// │ │ │ -/// │ ↓ │ -/// │ ┌───────────────────────┐ │ -/// │ │ → IDLE │ │ -/// │ │ (counter preserved!) │ │ -/// │ └───────────────────────┘ │ +/// │ ┌─────────┴─────────┐ │ +/// │ ↓ ↓ │ +/// │ on target BSSID on other AP │ +/// │ │ │ │ +/// │ ↓ ↓ │ +/// │ ┌──────────────────┐ ┌────────────┐│ +/// │ │ → IDLE │ │ → IDLE ││ +/// │ │ (counter reset) │ │ (counter ││ +/// │ │ (roam worked!) │ │ preserved)││ +/// │ └──────────────────┘ └────────────┘│ /// │ │ /// │ Key behaviors: │ /// │ - After 3 checks: attempts >= 3, stop checking │ /// │ - Non-roaming disconnect: clear_roaming_state_() resets counter │ -/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ +/// │ - Disconnect during scan (SCANNING→RECONNECTING): counter preserved │ +/// │ - Disconnect after scan (within grace period): counter preserved │ /// │ - Roaming success (CONNECTING→IDLE): counter reset (can roam again) │ -/// │ - Roaming fail (RECONNECTING→IDLE): counter preserved (ping-pong) │ +/// │ - Roaming success via retry (on target BSSID): counter reset │ +/// │ - Roaming fail (RECONNECTING on other AP): counter preserved │ /// └──────────────────────────────────────────────────────────────────────┘ // Use if-chain instead of switch to avoid jump table in RODATA (wastes RAM on ESP8266) @@ -1583,17 +1590,33 @@ void WiFiComponent::check_connecting_finished(uint32_t now) { // Only preserve attempts if reconnecting after a failed roam attempt // This prevents ping-pong between APs when a roam target is unreachable if (this->roaming_state_ == RoamingState::CONNECTING) { - // Successful roam to better AP - reset attempts so we can roam again later + // Successful roam to better AP on first try - reset attempts so we can roam again later ESP_LOGD(TAG, "Roam successful"); this->roaming_attempts_ = 0; } else if (this->roaming_state_ == RoamingState::RECONNECTING) { - // Failed roam, reconnected via normal recovery - keep attempts to prevent ping-pong - ESP_LOGD(TAG, "Reconnected after failed roam (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + // Check if we ended up on the roam target despite needing a retry + // (e.g., first connect failed but scan-based retry found and connected to the same better AP) + bssid_t current_bssid = this->wifi_bssid(); + if (this->roaming_target_bssid_ != bssid_t{} && current_bssid == this->roaming_target_bssid_) { + char bssid_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE]; + format_mac_addr_upper(current_bssid.data(), bssid_buf); + ESP_LOGD(TAG, "Roam successful (via retry, attempt %u/%u) to %s", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS, + bssid_buf); + this->roaming_attempts_ = 0; + } else if (this->roaming_target_bssid_ != bssid_t{}) { + // Failed roam to specific target, reconnected to different AP - keep attempts to prevent ping-pong + ESP_LOGD(TAG, "Reconnected after failed roam (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + } else { + // Reconnected after scan-induced disconnect (no roam target) - keep attempts + ESP_LOGD(TAG, "Reconnected after roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + } } else { // Normal connection (boot, credentials changed, etc.) this->roaming_attempts_ = 0; } this->roaming_state_ = RoamingState::IDLE; + this->roaming_target_bssid_ = {}; + this->roaming_scan_end_ = 0; // Clear all priority penalties - the next reconnect will happen when an AP disconnects, // which means the landscape has likely changed and previous tracked failures are stale @@ -2080,8 +2103,16 @@ void WiFiComponent::retry_connect() { ESP_LOGD(TAG, "Disconnected during roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); this->roaming_state_ = RoamingState::RECONNECTING; } else if (this->roaming_state_ == RoamingState::IDLE) { - // Not a roaming-triggered reconnect, reset state - this->clear_roaming_state_(); + // Check if a roaming scan recently completed - on ESP8266, going off-channel + // during scan can cause a delayed Beacon Timeout 8-20 seconds after scan finishes. + // Transition to RECONNECTING so the attempts counter is preserved on reconnect. + if (this->roaming_scan_end_ != 0 && millis() - this->roaming_scan_end_ < ROAMING_SCAN_GRACE_PERIOD) { + ESP_LOGD(TAG, "Disconnect after roam scan (attempt %u/%u)", this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); + this->roaming_state_ = RoamingState::RECONNECTING; + } else { + // Not a roaming-triggered reconnect, reset state + this->clear_roaming_state_(); + } } // RECONNECTING: keep state and counter, still trying to reconnect @@ -2316,6 +2347,8 @@ bool WiFiScanResult::operator==(const WiFiScanResult &rhs) const { return this-> void WiFiComponent::clear_roaming_state_() { this->roaming_attempts_ = 0; this->roaming_last_check_ = 0; + this->roaming_scan_end_ = 0; + this->roaming_target_bssid_ = {}; this->roaming_state_ = RoamingState::IDLE; } @@ -2383,7 +2416,7 @@ void WiFiComponent::check_roaming_(uint32_t now) { // Guard: skip scan if signal is already good (no meaningful improvement possible) int8_t rssi = this->wifi_rssi(); if (rssi > ROAMING_GOOD_RSSI) { - ESP_LOGV(TAG, "Roam check skipped, signal good (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, + ESP_LOGD(TAG, "Roam check skipped, signal good (%d dBm, attempt %u/%u)", rssi, this->roaming_attempts_, ROAMING_MAX_ATTEMPTS); return; } @@ -2397,6 +2430,9 @@ void WiFiComponent::process_roaming_scan_() { this->scan_done_ = false; // Default to IDLE - will be set to CONNECTING if we find a better AP this->roaming_state_ = RoamingState::IDLE; + // Record when scan completed so delayed disconnects (e.g., ESP8266 Beacon Timeout) + // can be attributed to the scan and avoid resetting the attempts counter + this->roaming_scan_end_ = millis(); // Get current connection info int8_t current_rssi = this->wifi_rssi(); @@ -2445,10 +2481,12 @@ void WiFiComponent::process_roaming_scan_() { WiFiAP roam_params = *selected; apply_scan_result_to_params(roam_params, *best); - this->release_scan_results_(); // Mark as roaming attempt - affects retry behavior if connection fails this->roaming_state_ = RoamingState::CONNECTING; + this->roaming_target_bssid_ = best->get_bssid(); // Must read before releasing scan results + + this->release_scan_results_(); // Connect directly - wifi_sta_connect_ handles disconnect internally this->start_connecting(roam_params); diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 883cc1344b..27a46a8e03 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -779,6 +779,10 @@ class WiFiComponent : public Component { static constexpr int8_t ROAMING_MIN_IMPROVEMENT = 10; // dB static constexpr int8_t ROAMING_GOOD_RSSI = -49; // Skip scan if signal is excellent static constexpr uint8_t ROAMING_MAX_ATTEMPTS = 3; + // Grace period after roaming scan completes. If WiFi disconnects within this + // window (e.g., ESP8266 Beacon Timeout caused by going off-channel during scan), + // the disconnect is treated as roaming-related and the attempts counter is preserved. + static constexpr uint32_t ROAMING_SCAN_GRACE_PERIOD = 30 * 1000; // 30 seconds // 4-byte members float output_power_{NAN}; @@ -786,6 +790,7 @@ class WiFiComponent : public Component { uint32_t last_connected_{0}; uint32_t reboot_timeout_{}; uint32_t roaming_last_check_{0}; + uint32_t roaming_scan_end_{0}; // Timestamp when last roaming scan completed #ifdef USE_WIFI_AP uint32_t ap_timeout_{}; #endif @@ -810,6 +815,7 @@ class WiFiComponent : public Component { bool error_from_callback_{false}; RetryHiddenMode retry_hidden_mode_{RetryHiddenMode::BLIND_RETRY}; RoamingState roaming_state_{RoamingState::IDLE}; + bssid_t roaming_target_bssid_{}; // BSSID of the AP we're trying to roam to #if defined(USE_ESP32) && defined(USE_WIFI_RUNTIME_POWER_SAVE) WiFiPowerSaveMode configured_power_save_{WIFI_POWER_SAVE_NONE}; #endif From 92642df419ad4ca8a7dae98ddb85cef050e8e5c2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 24 Mar 2026 20:21:04 -0400 Subject: [PATCH 1851/2030] [wifi] Filter fast_connect by band_mode and use background scan for roaming (#15152) --- esphome/components/wifi/wifi_component.cpp | 8 ++++++++ esphome/components/wifi/wifi_component.h | 2 ++ esphome/components/wifi/wifi_component_esp_idf.cpp | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 8656df7f4d..6163571bc9 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -2229,6 +2229,14 @@ bool WiFiComponent::load_fast_connect_settings_(WiFiAP ¶ms) { params.set_hidden(false); ESP_LOGD(TAG, "Loaded fast_connect settings"); +#if defined(USE_ESP32) && defined(SOC_WIFI_SUPPORT_5G) + if ((this->band_mode_ == WIFI_BAND_MODE_5G_ONLY && fast_connect_save.channel < FIRST_5GHZ_CHANNEL) || + (this->band_mode_ == WIFI_BAND_MODE_2G_ONLY && fast_connect_save.channel >= FIRST_5GHZ_CHANNEL)) { + ESP_LOGW(TAG, "Saved channel %u not allowed by band mode, ignoring fast_connect", fast_connect_save.channel); + this->selected_sta_index_ = -1; + return false; + } +#endif return true; } diff --git a/esphome/components/wifi/wifi_component.h b/esphome/components/wifi/wifi_component.h index 27a46a8e03..c88fffc512 100644 --- a/esphome/components/wifi/wifi_component.h +++ b/esphome/components/wifi/wifi_component.h @@ -774,6 +774,8 @@ class WiFiComponent : public Component { SemaphoreHandle_t high_performance_semaphore_{nullptr}; #endif + static constexpr uint8_t FIRST_5GHZ_CHANNEL = 36; + // Post-connect roaming constants static constexpr uint32_t ROAMING_CHECK_INTERVAL = 5 * 60 * 1000; // 5 minutes static constexpr int8_t ROAMING_MIN_IMPROVEMENT = 10; // dB diff --git a/esphome/components/wifi/wifi_component_esp_idf.cpp b/esphome/components/wifi/wifi_component_esp_idf.cpp index eca3f19249..0280becc7e 100644 --- a/esphome/components/wifi/wifi_component_esp_idf.cpp +++ b/esphome/components/wifi/wifi_component_esp_idf.cpp @@ -961,6 +961,11 @@ bool WiFiComponent::wifi_scan_start_(bool passive) { config.scan_time.active.min = 100; config.scan_time.active.max = 300; } + // When scanning while connected (roaming), return to home channel between + // each scanned channel to maintain the connection (helps with BLE/WiFi coexistence) + if (this->roaming_state_ == RoamingState::SCANNING) { + config.coex_background_scan = true; + } esp_err_t err = esp_wifi_scan_start(&config, false); if (err != ESP_OK) { From 7b5a4b466a135ab658317e928830a65c05f9d19a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:50:37 -0400 Subject: [PATCH 1852/2030] [uart] Fix debug callback missing peeked byte and reading past end (#15169) --- esphome/components/uart/uart_component_esp_idf.cpp | 6 ++++-- esphome/components/uart/uart_component_host.cpp | 6 ++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 8168e49805..82120b1a5f 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -324,6 +324,9 @@ bool IDFUARTComponent::peek_byte(uint8_t *data) { } bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { + if (len == 0) { + return false; + } size_t length_to_read = len; int32_t read_len = 0; if (!this->check_read_timeout_(len)) @@ -331,11 +334,10 @@ bool IDFUARTComponent::read_array(uint8_t *data, size_t len) { if (this->has_peek_) { length_to_read--; *data = this->peek_byte_; - data++; this->has_peek_ = false; } if (length_to_read > 0) - read_len = uart_read_bytes(this->uart_num_, data, length_to_read, 20 / portTICK_PERIOD_MS); + read_len = uart_read_bytes(this->uart_num_, data + (len - length_to_read), length_to_read, 20 / portTICK_PERIOD_MS); #ifdef USE_UART_DEBUGGER for (size_t i = 0; i < len; i++) { this->debug_callback_.call(UART_DIRECTION_RX, data[i]); diff --git a/esphome/components/uart/uart_component_host.cpp b/esphome/components/uart/uart_component_host.cpp index 66026f3ccd..e9c101816e 100644 --- a/esphome/components/uart/uart_component_host.cpp +++ b/esphome/components/uart/uart_component_host.cpp @@ -235,16 +235,14 @@ bool HostUartComponent::read_array(uint8_t *data, size_t len) { } if (!this->check_read_timeout_(len)) return false; - uint8_t *data_ptr = data; size_t length_to_read = len; if (this->has_peek_) { length_to_read--; - *data_ptr = this->peek_byte_; - data_ptr++; + *data = this->peek_byte_; this->has_peek_ = false; } if (length_to_read > 0) { - int sz = ::read(this->file_descriptor_, data_ptr, length_to_read); + int sz = ::read(this->file_descriptor_, data + (len - length_to_read), length_to_read); if (sz == -1) { this->update_error_(strerror(errno)); return false; From 3fd3dcc7e575e52f0924ebdd4fa2fa0356762c0c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 27 Mar 2026 14:13:24 -0400 Subject: [PATCH 1853/2030] [sgp4x] Fix NOx index_offset default (should be 1, not 100) (#15212) --- esphome/components/sgp4x/sensor.py | 39 ++++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/esphome/components/sgp4x/sensor.py b/esphome/components/sgp4x/sensor.py index ab78ab59d9..8d52ffb4f2 100644 --- a/esphome/components/sgp4x/sensor.py +++ b/esphome/components/sgp4x/sensor.py @@ -44,20 +44,27 @@ def validate_sensors(config): return config -GAS_SENSOR = cv.Schema( - { - cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema( - { - cv.Optional(CONF_INDEX_OFFSET, default=100): cv.int_, - cv.Optional(CONF_LEARNING_TIME_OFFSET_HOURS, default=12): cv.int_, - cv.Optional(CONF_LEARNING_TIME_GAIN_HOURS, default=12): cv.int_, - cv.Optional(CONF_GATING_MAX_DURATION_MINUTES, default=720): cv.int_, - cv.Optional(CONF_STD_INITIAL, default=50): cv.int_, - cv.Optional(CONF_GAIN_FACTOR, default=230): cv.int_, - } - ) - } -) +def _gas_sensor_schema(index_offset_default: int): + return cv.Schema( + { + cv.Optional(CONF_ALGORITHM_TUNING): cv.Schema( + { + cv.Optional( + CONF_INDEX_OFFSET, default=index_offset_default + ): cv.int_, + cv.Optional(CONF_LEARNING_TIME_OFFSET_HOURS, default=12): cv.int_, + cv.Optional(CONF_LEARNING_TIME_GAIN_HOURS, default=12): cv.int_, + cv.Optional(CONF_GATING_MAX_DURATION_MINUTES, default=720): cv.int_, + cv.Optional(CONF_STD_INITIAL, default=50): cv.int_, + cv.Optional(CONF_GAIN_FACTOR, default=230): cv.int_, + } + ) + } + ) + + +VOC_SENSOR = _gas_sensor_schema(100) +NOX_SENSOR = _gas_sensor_schema(1) CONFIG_SCHEMA = cv.All( cv.Schema( @@ -68,13 +75,13 @@ CONFIG_SCHEMA = cv.All( accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, - ).extend(GAS_SENSOR), + ).extend(VOC_SENSOR), cv.Optional(CONF_NOX): sensor.sensor_schema( icon=ICON_RADIATOR, accuracy_decimals=0, device_class=DEVICE_CLASS_AQI, state_class=STATE_CLASS_MEASUREMENT, - ).extend(GAS_SENSOR), + ).extend(NOX_SENSOR), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, cv.Optional(CONF_VOC_BASELINE): cv.hex_uint16_t, cv.Optional(CONF_COMPENSATION): cv.Schema( From 3d8a3a91f25cc2e620c4d04e3b5aa9fd1773921b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 28 Mar 2026 15:38:06 -1000 Subject: [PATCH 1854/2030] [esp32_ble_server] Fix set_value action with static data lists (#15285) --- .../components/esp32_ble_server/ble_server_automations.h | 2 ++ tests/components/esp32_ble_server/common.yaml | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/esphome/components/esp32_ble_server/ble_server_automations.h b/esphome/components/esp32_ble_server/ble_server_automations.h index fe18600280..0bbfdffd5b 100644 --- a/esphome/components/esp32_ble_server/ble_server_automations.h +++ b/esphome/components/esp32_ble_server/ble_server_automations.h @@ -70,6 +70,7 @@ template<typename... Ts> class BLECharacteristicSetValueAction : public Action<T public: BLECharacteristicSetValueAction(BLECharacteristic *characteristic) : parent_(characteristic) {} TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer) + void set_buffer(std::initializer_list<uint8_t> buffer) { this->buffer_ = std::vector<uint8_t>(buffer); } void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } void play(const Ts &...x) override { // If the listener is already set, do nothing @@ -115,6 +116,7 @@ template<typename... Ts> class BLEDescriptorSetValueAction : public Action<Ts... public: BLEDescriptorSetValueAction(BLEDescriptor *descriptor) : parent_(descriptor) {} TEMPLATABLE_VALUE(std::vector<uint8_t>, buffer) + void set_buffer(std::initializer_list<uint8_t> buffer) { this->buffer_ = std::vector<uint8_t>(buffer); } void set_buffer(ByteBuffer buffer) { this->set_buffer(buffer.get_data()); } void play(const Ts &...x) override { this->parent_->set_value(this->buffer_.value(x...)); } diff --git a/tests/components/esp32_ble_server/common.yaml b/tests/components/esp32_ble_server/common.yaml index 7fe0b2eb5f..4e34049038 100644 --- a/tests/components/esp32_ble_server/common.yaml +++ b/tests/components/esp32_ble_server/common.yaml @@ -69,3 +69,11 @@ esp32_ble_server: - ble_server.descriptor.set_value: id: test_change_descriptor value: !lambda return bytebuffer::ByteBuffer::wrap({0x03, 0x04, 0x05}).get_data(); + - ble_server.characteristic.set_value: + id: test_change_characteristic + value: + data: [0xfc, 0xef, 0xfe, 0x86] + - ble_server.descriptor.set_value: + id: test_change_descriptor + value: + data: [0x01, 0x02, 0x03] From d79cf1d7183ed1b72a825a116be798120bbd775e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 29 Mar 2026 11:57:52 -1000 Subject: [PATCH 1855/2030] [esp8266] Add enable_scanf_float option (#15284) --- esphome/components/esp8266/__init__.py | 62 +++++++++++++++---- .../components/esp8266/test.esp8266-ard.yaml | 3 + tests/unit_tests/components/test_esp8266.py | 62 +++++++++++++++++++ 3 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 tests/unit_tests/components/test_esp8266.py diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 16043b6d69..2081145096 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -1,5 +1,6 @@ import logging from pathlib import Path +import re import esphome.codegen as cg import esphome.config_validation as cv @@ -18,8 +19,9 @@ from esphome.const import ( PLATFORM_ESP8266, ThreadModel, ) -from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority from esphome.helpers import copy_file_if_changed +from esphome.types import ConfigType from .boards import BOARDS, ESP8266_LD_SCRIPTS from .const import ( @@ -40,12 +42,42 @@ from .const import ( ) from .gpio import PinInitialState, add_pin_initial_states_array +CONF_ENABLE_SCANF_FLOAT = "enable_scanf_float" +# Heuristically matches scanf/sscanf calls with float format specifiers. +# Standard scanf float conversions: %f %F %e %E %g %G %a %A +# With optional modifiers: %*f (suppression), %8f (width), %lf %Lf (length) +# Also matches non-standard patterns like %.2f as a heuristic — these are +# invalid in scanf but users may write them by analogy with printf. +# Uses [^;]*? to stay within a single statement, preventing false positives +# from e.g. sscanf(buf, "%d", &x); printf("%f", val); +_SCANF_FLOAT_RE = re.compile(r"scanf\s*\([^;]*?%[*\d.]*[hlL]*[feEgGaAF]") + CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) AUTO_LOAD = ["preferences"] IS_TARGET_PLATFORM = True +def lambdas_use_scanf_float(config: ConfigType) -> bool: + """Check if any lambda in the config uses scanf with a float format specifier. + + Comments are stripped before matching to avoid false positives from + commented-out code. The cost of a false positive is only ~8KB flash. + """ + stack: list = [config] + while stack: + obj = stack.pop() + if isinstance(obj, Lambda): + src = obj.comment_remover(obj.value) + if _SCANF_FLOAT_RE.search(src): + return True + elif isinstance(obj, dict): + stack.extend(obj.values()) + elif isinstance(obj, list): + stack.extend(obj) + return False + + def set_core_data(config): CORE.data[KEY_ESP8266] = {} CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_ESP8266 @@ -181,6 +213,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_ENABLE_SERIAL): cv.boolean, cv.Optional(CONF_ENABLE_SERIAL1): cv.boolean, cv.Optional(CONF_ENABLE_FULL_PRINTF, default=False): cv.boolean, + cv.Optional(CONF_ENABLE_SCANF_FLOAT): cv.boolean, } ), set_core_data, @@ -201,16 +234,23 @@ async def to_code(config): cg.add_define("ESPHOME_VARIANT", "ESP8266") cg.add_define(ThreadModel.SINGLE) - cg.add_platformio_option( - "extra_scripts", - [ - "pre:testing_mode.py", - "pre:exclude_updater.py", - "pre:exclude_waveform.py", - "pre:remove_float_scanf.py", - "post:post_build.py", - ], - ) + enable_scanf_float = config.get(CONF_ENABLE_SCANF_FLOAT) + if enable_scanf_float is None and lambdas_use_scanf_float(CORE.config): + enable_scanf_float = True + _LOGGER.warning( + "Lambda uses scanf with a float format specifier; " + "enabling scanf float support (~8KB flash)" + ) + + extra_scripts = [ + "pre:testing_mode.py", + "pre:exclude_updater.py", + "pre:exclude_waveform.py", + ] + if not enable_scanf_float: + extra_scripts.append("pre:remove_float_scanf.py") + extra_scripts.append("post:post_build.py") + cg.add_platformio_option("extra_scripts", extra_scripts) conf = config[CONF_FRAMEWORK] cg.add_platformio_option("framework", "arduino") diff --git a/tests/components/esp8266/test.esp8266-ard.yaml b/tests/components/esp8266/test.esp8266-ard.yaml index c77218f7a3..ba70c1a6a4 100644 --- a/tests/components/esp8266/test.esp8266-ard.yaml +++ b/tests/components/esp8266/test.esp8266-ard.yaml @@ -14,3 +14,6 @@ esphome: assert(x == 95); x = clamp_at_most(x, 40); assert(x == 40); + - lambda: |- + float value = 0.0f; + sscanf("3.14", "%f", &value); diff --git a/tests/unit_tests/components/test_esp8266.py b/tests/unit_tests/components/test_esp8266.py new file mode 100644 index 0000000000..318fd2d889 --- /dev/null +++ b/tests/unit_tests/components/test_esp8266.py @@ -0,0 +1,62 @@ +"""Tests for ESP8266 component.""" + +import pytest + +from esphome.components.esp8266 import lambdas_use_scanf_float +from esphome.core import Lambda +from esphome.types import ConfigType + + +@pytest.mark.parametrize( + ("src", "expected"), + [ + # Basic float formats + ('sscanf(buf, "%f", &v)', True), + ('sscanf(buf, "%F", &v)', True), + ('sscanf(buf, "%e", &v)', True), + ('sscanf(buf, "%E", &v)', True), + ('sscanf(buf, "%g", &v)', True), + ('sscanf(buf, "%G", &v)', True), + ('sscanf(buf, "%a", &v)', True), + ('sscanf(buf, "%A", &v)', True), + # With modifiers + ('sscanf(buf, "%lf", &v)', True), + ('sscanf(buf, "%Lf", &v)', True), + ('sscanf(buf, "%8lf", &v)', True), + ('sscanf(buf, "%*f")', True), + ('sscanf(buf, "%.2f", &v)', True), + # Mixed formats + ('sscanf(buf, "%d,%f", &a, &b)', True), + # fscanf and std::sscanf + ('fscanf(fp, "%f", &v)', True), + ('std::sscanf(buf, "%f", &v)', True), + # Multi-line + ('sscanf(buf,\n"%f", &v)', True), + # No float format + ('sscanf(buf, "%d", &v)', False), + ('sscanf(buf, "%s", s)', False), + # printf not scanf + ('printf("%f", val)', False), + # %f in a different statement after scanf + ('sscanf(buf, "%d", &x); printf("%f", val);', False), + # scanf %f in comment only + ('// sscanf(buf, "%f", &v)\nsscanf(buf, "%d", &x)', False), + ('/* sscanf(buf, "%f") */\nsscanf(buf, "%d", &x)', False), + ], +) +def test_lambdas_use_scanf_float(src: str, expected: bool) -> None: + """Test scanf float detection in lambda source.""" + config: ConfigType = {"test": [Lambda(src)]} + assert lambdas_use_scanf_float(config) is expected + + +def test_lambdas_use_scanf_float_no_lambdas() -> None: + """Test with config containing no lambdas.""" + config: ConfigType = {"key": "value", "list": [1, 2]} + assert lambdas_use_scanf_float(config) is False + + +def test_lambdas_use_scanf_float_nested() -> None: + """Test detection in deeply nested config.""" + config: ConfigType = {"a": {"b": {"c": [Lambda('sscanf(buf, "%f", &v)')]}}} + assert lambdas_use_scanf_float(config) is True From 9cd7c5e700f954272742250467b2ad703d6f5e60 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Mon, 30 Mar 2026 13:15:02 -0500 Subject: [PATCH 1856/2030] [thermostat] Fix stale `max_runtime_exceeded` causing spurious supplemental heating/cooling (#15274) --- .../components/thermostat/thermostat_climate.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index d52a22f880..eb3e756bc2 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -606,6 +606,16 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } void ThermostatClimate::switch_to_supplemental_action_(climate::ClimateAction action) { + // Always cancel max-runtime timers and clear exceeded flags when transitioning to idle/off, + // even if supplemental_action_ is already idle (early-return path). This prevents a stale + // heating_max_runtime_exceeded_ flag from triggering supplemental on the next heating cycle + // when HEATING_MAX_RUN_TIME fires while the main action is already IDLE. + if (action == climate::CLIMATE_ACTION_OFF || action == climate::CLIMATE_ACTION_IDLE) { + this->cancel_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); + this->cancel_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); + this->cooling_max_runtime_exceeded_ = false; + this->heating_max_runtime_exceeded_ = false; + } // setup_complete_ helps us ensure an action is called immediately after boot if ((action == this->supplemental_action_) && this->setup_complete_) { // already in target mode @@ -975,8 +985,10 @@ void ThermostatClimate::cooling_on_timer_callback_() { void ThermostatClimate::fan_mode_timer_callback_() { ESP_LOGVV(TAG, "fan_mode timer expired"); this->switch_to_fan_mode_(this->fan_mode.value_or(climate::CLIMATE_FAN_ON)); - if (this->supports_fan_only_action_uses_fan_mode_timer_) + if (this->supports_fan_only_action_uses_fan_mode_timer_) { this->switch_to_action_(this->compute_action_()); + this->switch_to_supplemental_action_(this->compute_supplemental_action_()); + } } void ThermostatClimate::fanning_off_timer_callback_() { From 3bf45d8fe026309f8a8e60f49bdb15c564788529 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 31 Mar 2026 11:22:29 -0400 Subject: [PATCH 1857/2030] [haier] Fix hOn half-degree temperature setting (#15312) --- esphome/components/haier/hon_climate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/haier/hon_climate.cpp b/esphome/components/haier/hon_climate.cpp index b8889ef2bd..b027b0f295 100644 --- a/esphome/components/haier/hon_climate.cpp +++ b/esphome/components/haier/hon_climate.cpp @@ -677,7 +677,6 @@ haier_protocol::HaierMessage HonClimate::get_control_message() { this->quiet_mode_state_ = (SwitchState) ((uint8_t) this->quiet_mode_state_ & 0b01); } out_data->beeper_status = ((!this->get_beeper_state()) || (!has_hvac_settings)) ? 1 : 0; - control_out_buffer[4] = 0; // This byte should be cleared before setting values out_data->display_status = this->get_display_state() ? 1 : 0; this->display_status_ = (SwitchState) ((uint8_t) this->display_status_ & 0b01); out_data->health_mode = this->get_health_mode() ? 1 : 0; From 66a4acafd061b37f71f49cd7c6348df9a7c9eb9e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 31 Mar 2026 18:01:33 -0400 Subject: [PATCH 1858/2030] [tormatic] Fix UART stream desync on ESP32 (#15337) --- .../components/tormatic/tormatic_cover.cpp | 67 ++++++++++++++----- esphome/components/tormatic/tormatic_cover.h | 1 + 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/esphome/components/tormatic/tormatic_cover.cpp b/esphome/components/tormatic/tormatic_cover.cpp index 37a269088e..a48dece840 100644 --- a/esphome/components/tormatic/tormatic_cover.cpp +++ b/esphome/components/tormatic/tormatic_cover.cpp @@ -9,6 +9,10 @@ namespace tormatic { static const char *const TAG = "tormatic.cover"; +// Time to poll the UART when flushing after desync. At 9600 baud, a full +// 12-byte message takes ~12.5ms, so 15ms guarantees all bytes have arrived. +static constexpr uint32_t DRAIN_TIMEOUT_MS = 15; + using namespace esphome::cover; void Tormatic::setup() { @@ -255,32 +259,51 @@ void Tormatic::stop_at_target_() { // Read a GateStatus from the unit. The unit only sends messages in response to // status requests or commands, so a message needs to be sent first. optional<GateStatus> Tormatic::read_gate_status_() { - if (this->available() < sizeof(MessageHeader)) { + if (!this->pending_hdr_) { + if (this->available() < sizeof(MessageHeader)) { + return {}; + } + + this->pending_hdr_ = this->read_data_<MessageHeader>(); + if (!this->pending_hdr_) { + return {}; + } + + // Sanity check: valid messages have small payloads (3-4 bytes). A large + // or impossible payload_size means the stream is out of sync (corrupted + // byte, dropped data, etc.). Flush the buffer so we can resync on the + // next request/response cycle. + if (this->pending_hdr_->payload_size() > sizeof(CommandRequestReply)) { + ESP_LOGW(TAG, "Unexpected payload size %" PRIu32 ", flushing rx buffer", this->pending_hdr_->payload_size()); + this->pending_hdr_.reset(); + this->drain_rx_(); + return {}; + } + } + + // Wait for all payload bytes to arrive before processing. + if (this->available() < this->pending_hdr_->payload_size()) { return {}; } - auto o_hdr = this->read_data_<MessageHeader>(); - if (!o_hdr) { - ESP_LOGE(TAG, "Timeout reading message header"); - return {}; - } - auto hdr = o_hdr.value(); + auto hdr = *this->pending_hdr_; + this->pending_hdr_.reset(); switch (hdr.type) { case STATUS: { if (hdr.payload_size() != sizeof(StatusReply)) { ESP_LOGE(TAG, "Header specifies payload size %d but size of StatusReply is %d", hdr.payload_size(), sizeof(StatusReply)); + this->drain_rx_(hdr.payload_size()); + return {}; } - // Read a StatusReply requested by update(). auto o_status = this->read_data_<StatusReply>(); if (!o_status) { return {}; } - auto status = o_status.value(); - return status.state; + return o_status->state; } case COMMAND: @@ -343,16 +366,24 @@ template<typename T> optional<T> Tormatic::read_data_() { return obj; } -// Drain up to n amount of bytes from the uart rx buffer. +// Drain bytes from the uart rx buffer. When n > 0, drain exactly n bytes +// (caller must ensure they are available). When n == 0, poll for 15ms to +// guarantee a full packet time at 9600 baud has elapsed, consuming any +// bytes still in transit. void Tormatic::drain_rx_(uint16_t n) { uint8_t data; - uint16_t count = 0; - while (this->available()) { - this->read_byte(&data); - count++; - - if (n > 0 && count >= n) { - return; + if (n > 0) { + for (uint16_t i = 0; i < n; i++) { + if (!this->read_byte(&data)) { + return; + } + } + } else { + uint32_t start = millis(); + while (millis() - start < DRAIN_TIMEOUT_MS) { + if (this->available()) { + this->read_byte(&data); + } } } } diff --git a/esphome/components/tormatic/tormatic_cover.h b/esphome/components/tormatic/tormatic_cover.h index 534d4bef14..34483ed6a3 100644 --- a/esphome/components/tormatic/tormatic_cover.h +++ b/esphome/components/tormatic/tormatic_cover.h @@ -43,6 +43,7 @@ class Tormatic : public cover::Cover, public uart::UARTDevice, public PollingCom void handle_gate_status_(GateStatus s); uint32_t seq_tx_{0}; + optional<MessageHeader> pending_hdr_{}; GateStatus current_status_{PAUSED}; From dc634b8c7b5218b9b5b0a9c561ffa4a80254bb57 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 1 Apr 2026 01:04:07 +0200 Subject: [PATCH 1859/2030] [uart] fix baud rate not applied on `load_settings()` for ESP32 (IDF) (#15341) --- .../uart/uart_component_esp_idf.cpp | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/esphome/components/uart/uart_component_esp_idf.cpp b/esphome/components/uart/uart_component_esp_idf.cpp index 82120b1a5f..7d02f54b47 100644 --- a/esphome/components/uart/uart_component_esp_idf.cpp +++ b/esphome/components/uart/uart_component_esp_idf.cpp @@ -147,6 +147,20 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + // uart_param_config must be called after uart_driver_install and before any + // other uart_set_*() calls. The driver installation resets the UART peripheral + // registers to their default state, overwriting any previously configured baud + // rate or framing settings. Calling uart_param_config here ensures the requested + // settings are applied after the reset and before pin routing, inversion, and + // threshold configuration. + uart_config_t uart_config = this->get_config_(); + err = uart_param_config(this->uart_num_, &uart_config); + if (err != ESP_OK) { + ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); + this->mark_failed(); + return; + } + int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1; @@ -214,22 +228,15 @@ void IDFUARTComponent::load_settings(bool dump_config) { return; } + // Per ESP-IDF docs, uart_set_mode() must be called only after uart_driver_install(). auto mode = this->flow_control_pin_ != nullptr ? UART_MODE_RS485_HALF_DUPLEX : UART_MODE_UART; - err = uart_set_mode(this->uart_num_, mode); // per docs, must be called only after uart_driver_install() + err = uart_set_mode(this->uart_num_, mode); if (err != ESP_OK) { ESP_LOGW(TAG, "uart_set_mode failed: %s", esp_err_to_name(err)); this->mark_failed(); return; } - uart_config_t uart_config = this->get_config_(); - err = uart_param_config(this->uart_num_, &uart_config); - if (err != ESP_OK) { - ESP_LOGW(TAG, "uart_param_config failed: %s", esp_err_to_name(err)); - this->mark_failed(); - return; - } - #ifdef USE_UART_WAKE_LOOP_ON_RX // Register ISR callback to wake the main loop when UART data arrives. // The callback runs in ISR context and uses vTaskNotifyGiveFromISR() to From 514c0c8331c6eebc7e116b85c7d8abe2ecc6526b Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 31 Mar 2026 19:06:48 -0400 Subject: [PATCH 1860/2030] [mixer] Fix memory leak in mixer task on stop/start cycles (#15185) --- .../mixer/speaker/mixer_speaker.cpp | 274 +++++++++--------- 1 file changed, 137 insertions(+), 137 deletions(-) diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 9d11abb327..0fabc68c70 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -597,173 +597,173 @@ void MixerSpeaker::audio_mixer_task(void *params) { xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STARTING); - std::unique_ptr<audio::AudioSinkTransferBuffer> output_transfer_buffer = audio::AudioSinkTransferBuffer::create( - this_mixer->audio_stream_info_.value().ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); + { // Ensure C++ objects fall out of scope to ensure proper cleanup before stopping the task + std::unique_ptr<audio::AudioSinkTransferBuffer> output_transfer_buffer = audio::AudioSinkTransferBuffer::create( + this_mixer->audio_stream_info_.value().ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); - if (output_transfer_buffer == nullptr) { - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED | MIXER_TASK_ERR_ESP_NO_MEM); + if (output_transfer_buffer == nullptr) { + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED | MIXER_TASK_ERR_ESP_NO_MEM); - vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it - } - - output_transfer_buffer->set_sink(this_mixer->output_speaker_); - - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_RUNNING); - - bool sent_finished = false; - - // Pre-allocate vectors to avoid heap allocation in the loop (max 8 source speakers per schema) - FixedVector<SourceSpeaker *> speakers_with_data; - FixedVector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; - speakers_with_data.init(this_mixer->source_speakers_.size()); - transfer_buffers_with_data.init(this_mixer->source_speakers_.size()); - - while (true) { - uint32_t event_group_bits = xEventGroupGetBits(this_mixer->event_group_); - if (event_group_bits & MIXER_TASK_COMMAND_STOP) { - break; + vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it } - // Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves - output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false); + output_transfer_buffer->set_sink(this_mixer->output_speaker_); - const uint32_t output_frames_free = - this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free()); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_RUNNING); - speakers_with_data.clear(); - transfer_buffers_with_data.clear(); + bool sent_finished = false; - for (auto &speaker : this_mixer->source_speakers_) { - if (speaker->is_running() && !speaker->get_pause_state()) { - // Speaker is running and not paused, so it possibly can provide audio data - std::shared_ptr<audio::AudioSourceTransferBuffer> transfer_buffer = speaker->get_transfer_buffer().lock(); - if (transfer_buffer.use_count() == 0) { - // No transfer buffer allocated, so skip processing this speaker - continue; - } - speaker->process_data_from_source(transfer_buffer, 0); // Transfers and ducks audio from source ring buffers + // Pre-allocate vectors to avoid heap allocation in the loop (max 8 source speakers per schema) + FixedVector<SourceSpeaker *> speakers_with_data; + FixedVector<std::shared_ptr<audio::AudioSourceTransferBuffer>> transfer_buffers_with_data; + speakers_with_data.init(this_mixer->source_speakers_.size()); + transfer_buffers_with_data.init(this_mixer->source_speakers_.size()); - if (transfer_buffer->available() > 0) { - // Store the locked transfer buffers in their own vector to avoid releasing ownership until after the loop - transfer_buffers_with_data.push_back(transfer_buffer); - speakers_with_data.push_back(speaker); + while (true) { + uint32_t event_group_bits = xEventGroupGetBits(this_mixer->event_group_); + if (event_group_bits & MIXER_TASK_COMMAND_STOP) { + break; + } + + // Never shift the data in the output transfer buffer to avoid unnecessary, slow data moves + output_transfer_buffer->transfer_data_to_sink(pdMS_TO_TICKS(TASK_DELAY_MS), false); + + const uint32_t output_frames_free = + this_mixer->audio_stream_info_.value().bytes_to_frames(output_transfer_buffer->free()); + + speakers_with_data.clear(); + transfer_buffers_with_data.clear(); + + for (auto &speaker : this_mixer->source_speakers_) { + if (speaker->is_running() && !speaker->get_pause_state()) { + // Speaker is running and not paused, so it possibly can provide audio data + std::shared_ptr<audio::AudioSourceTransferBuffer> transfer_buffer = speaker->get_transfer_buffer().lock(); + if (transfer_buffer.use_count() == 0) { + // No transfer buffer allocated, so skip processing this speaker + continue; + } + speaker->process_data_from_source(transfer_buffer, 0); // Transfers and ducks audio from source ring buffers + + if (transfer_buffer->available() > 0) { + // Store the locked transfer buffers in their own vector to avoid releasing ownership until after the loop + transfer_buffers_with_data.push_back(transfer_buffer); + speakers_with_data.push_back(speaker); + } } } - } - if (transfer_buffers_with_data.empty()) { - // No audio available for transferring, block task temporarily - delay(TASK_DELAY_MS); - continue; - } + if (transfer_buffers_with_data.empty()) { + // No audio available for transferring, block task temporarily + delay(TASK_DELAY_MS); + continue; + } - uint32_t frames_to_mix = output_frames_free; + uint32_t frames_to_mix = output_frames_free; - if ((transfer_buffers_with_data.size() == 1) || this_mixer->queue_mode_) { - // Only one speaker has audio data, just copy samples over + if ((transfer_buffers_with_data.size() == 1) || this_mixer->queue_mode_) { + // Only one speaker has audio data, just copy samples over - audio::AudioStreamInfo active_stream_info = speakers_with_data[0]->get_audio_stream_info(); + audio::AudioStreamInfo active_stream_info = speakers_with_data[0]->get_audio_stream_info(); - if (active_stream_info.get_sample_rate() == - this_mixer->output_speaker_->get_audio_stream_info().get_sample_rate()) { - // Speaker's sample rate matches the output speaker's, copy directly + if (active_stream_info.get_sample_rate() == + this_mixer->output_speaker_->get_audio_stream_info().get_sample_rate()) { + // Speaker's sample rate matches the output speaker's, copy directly - const uint32_t frames_available_in_buffer = - active_stream_info.bytes_to_frames(transfer_buffers_with_data[0]->available()); - frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); - copy_frames(reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()), active_stream_info, - reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), - this_mixer->audio_stream_info_.value(), frames_to_mix); + const uint32_t frames_available_in_buffer = + active_stream_info.bytes_to_frames(transfer_buffers_with_data[0]->available()); + frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); + copy_frames(reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()), + active_stream_info, reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), + this_mixer->audio_stream_info_.value(), frames_to_mix); - // Set playback delay for newly contributing source - if (!speakers_with_data[0]->has_contributed_.load(std::memory_order_acquire)) { - speakers_with_data[0]->playback_delay_frames_.store( - this_mixer->frames_in_pipeline_.load(std::memory_order_acquire), std::memory_order_release); - speakers_with_data[0]->has_contributed_.store(true, std::memory_order_release); + // Set playback delay for newly contributing source + if (!speakers_with_data[0]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[0]->playback_delay_frames_.store( + this_mixer->frames_in_pipeline_.load(std::memory_order_acquire), std::memory_order_release); + speakers_with_data[0]->has_contributed_.store(true, std::memory_order_release); + } + + // Update source speaker pending frames + speakers_with_data[0]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); + transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); + + // Update output transfer buffer length and pipeline frame count + output_transfer_buffer->increase_buffer_length( + this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); + this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); + } else { + // Speaker's stream info doesn't match the output speaker's, so it's a new source speaker + if (!this_mixer->output_speaker_->is_stopped()) { + if (!sent_finished) { + this_mixer->output_speaker_->finish(); + sent_finished = true; // Avoid repeatedly sending the finish command + } + } else { + // Speaker has finished writing the current audio, update the stream information and restart the speaker + this_mixer->audio_stream_info_ = + audio::AudioStreamInfo(active_stream_info.get_bits_per_sample(), this_mixer->output_channels_, + active_stream_info.get_sample_rate()); + this_mixer->output_speaker_->set_audio_stream_info(this_mixer->audio_stream_info_.value()); + this_mixer->output_speaker_->start(); + // Reset pipeline frame count since we're starting fresh with a new sample rate + this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); + sent_finished = false; + } + } + } else { + // Determine how many frames to mix + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { + const uint32_t frames_available_in_buffer = speakers_with_data[i]->get_audio_stream_info().bytes_to_frames( + transfer_buffers_with_data[i]->available()); + frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); + } + int16_t *primary_buffer = reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()); + audio::AudioStreamInfo primary_stream_info = speakers_with_data[0]->get_audio_stream_info(); + + // Mix two streams together + for (size_t i = 1; i < transfer_buffers_with_data.size(); ++i) { + mix_audio_samples(primary_buffer, primary_stream_info, + reinterpret_cast<int16_t *>(transfer_buffers_with_data[i]->get_buffer_start()), + speakers_with_data[i]->get_audio_stream_info(), + reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), + this_mixer->audio_stream_info_.value(), frames_to_mix); + + if (i != transfer_buffers_with_data.size() - 1) { + // Need to mix more streams together, point primary buffer and stream info to the already mixed output + primary_buffer = reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()); + primary_stream_info = this_mixer->audio_stream_info_.value(); + } } - // Update source speaker pending frames - speakers_with_data[0]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); - transfer_buffers_with_data[0]->decrease_buffer_length(active_stream_info.frames_to_bytes(frames_to_mix)); + // Get current pipeline depth for delay calculation (before incrementing) + uint32_t current_pipeline_frames = this_mixer->frames_in_pipeline_.load(std::memory_order_acquire); - // Update output transfer buffer length and pipeline frame count + // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks + for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { + // Set playback delay for newly contributing sources + if (!speakers_with_data[i]->has_contributed_.load(std::memory_order_acquire)) { + speakers_with_data[i]->playback_delay_frames_.store(current_pipeline_frames, std::memory_order_release); + speakers_with_data[i]->has_contributed_.store(true, std::memory_order_release); + } + + speakers_with_data[i]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); + transfer_buffers_with_data[i]->decrease_buffer_length( + speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); + } + + // Update output transfer buffer length and pipeline frame count (once, not per source) output_transfer_buffer->increase_buffer_length( this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); - } else { - // Speaker's stream info doesn't match the output speaker's, so it's a new source speaker - if (!this_mixer->output_speaker_->is_stopped()) { - if (!sent_finished) { - this_mixer->output_speaker_->finish(); - sent_finished = true; // Avoid repeatedly sending the finish command - } - } else { - // Speaker has finished writing the current audio, update the stream information and restart the speaker - this_mixer->audio_stream_info_ = - audio::AudioStreamInfo(active_stream_info.get_bits_per_sample(), this_mixer->output_channels_, - active_stream_info.get_sample_rate()); - this_mixer->output_speaker_->set_audio_stream_info(this_mixer->audio_stream_info_.value()); - this_mixer->output_speaker_->start(); - // Reset pipeline frame count since we're starting fresh with a new sample rate - this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); - sent_finished = false; - } } - } else { - // Determine how many frames to mix - for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { - const uint32_t frames_available_in_buffer = - speakers_with_data[i]->get_audio_stream_info().bytes_to_frames(transfer_buffers_with_data[i]->available()); - frames_to_mix = std::min(frames_to_mix, frames_available_in_buffer); - } - int16_t *primary_buffer = reinterpret_cast<int16_t *>(transfer_buffers_with_data[0]->get_buffer_start()); - audio::AudioStreamInfo primary_stream_info = speakers_with_data[0]->get_audio_stream_info(); - - // Mix two streams together - for (size_t i = 1; i < transfer_buffers_with_data.size(); ++i) { - mix_audio_samples(primary_buffer, primary_stream_info, - reinterpret_cast<int16_t *>(transfer_buffers_with_data[i]->get_buffer_start()), - speakers_with_data[i]->get_audio_stream_info(), - reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()), - this_mixer->audio_stream_info_.value(), frames_to_mix); - - if (i != transfer_buffers_with_data.size() - 1) { - // Need to mix more streams together, point primary buffer and stream info to the already mixed output - primary_buffer = reinterpret_cast<int16_t *>(output_transfer_buffer->get_buffer_end()); - primary_stream_info = this_mixer->audio_stream_info_.value(); - } - } - - // Get current pipeline depth for delay calculation (before incrementing) - uint32_t current_pipeline_frames = this_mixer->frames_in_pipeline_.load(std::memory_order_acquire); - - // Update source transfer buffer lengths and add new audio durations to the source speaker pending playbacks - for (size_t i = 0; i < transfer_buffers_with_data.size(); ++i) { - // Set playback delay for newly contributing sources - if (!speakers_with_data[i]->has_contributed_.load(std::memory_order_acquire)) { - speakers_with_data[i]->playback_delay_frames_.store(current_pipeline_frames, std::memory_order_release); - speakers_with_data[i]->has_contributed_.store(true, std::memory_order_release); - } - - speakers_with_data[i]->pending_playback_frames_.fetch_add(frames_to_mix, std::memory_order_release); - transfer_buffers_with_data[i]->decrease_buffer_length( - speakers_with_data[i]->get_audio_stream_info().frames_to_bytes(frames_to_mix)); - } - - // Update output transfer buffer length and pipeline frame count (once, not per source) - output_transfer_buffer->increase_buffer_length( - this_mixer->audio_stream_info_.value().frames_to_bytes(frames_to_mix)); - this_mixer->frames_in_pipeline_.fetch_add(frames_to_mix, std::memory_order_release); } - } - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPING); + xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPING); + } // Reset pipeline frame count since the task is stopping this_mixer->frames_in_pipeline_.store(0, std::memory_order_release); - output_transfer_buffer.reset(); - xEventGroupSetBits(this_mixer->event_group_, MIXER_TASK_STATE_STOPPED); vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it From 65051153ac0f7559bd8e271d82fb9685b611164e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 31 Mar 2026 13:26:26 -1000 Subject: [PATCH 1861/2030] [esp32_ble_tracker] Restart BLE scan after OTA failure (#15308) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp | 6 ++++++ esphome/components/esp32_ble_tracker/esp32_ble_tracker.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index 5a43cf7e49..6a2834a869 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -82,12 +82,18 @@ void ESP32BLETracker::setup() { #ifdef USE_OTA_STATE_LISTENER void ESP32BLETracker::on_ota_global_state(ota::OTAState state, float progress, uint8_t error, ota::OTAComponent *comp) { if (state == ota::OTA_STARTED) { + this->scan_continuous_before_ota_ = this->scan_continuous_; this->stop_scan(); #ifdef ESPHOME_ESP32_BLE_TRACKER_CLIENT_COUNT for (auto *client : this->clients_) { client->disconnect(); } #endif + } else if ((state == ota::OTA_ERROR || state == ota::OTA_ABORT) && this->scan_continuous_before_ota_) { + this->scan_continuous_before_ota_ = false; + this->scan_continuous_ = true; + // Do not restart scanning immediately here; allow loop() to + // safely restart scanning once the scanner and all clients are idle. } } #endif diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h index 7f1c2b0f7c..e0e25aca20 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.h @@ -429,6 +429,9 @@ class ESP32BLETracker : public Component, ScannerState scanner_state_{ScannerState::IDLE}; bool scan_continuous_; bool scan_active_; +#ifdef USE_OTA_STATE_LISTENER + bool scan_continuous_before_ota_{false}; +#endif bool ble_was_disabled_{true}; bool raw_advertisements_{false}; bool parse_advertisements_{false}; From 600ca01fd3904fffd3d6092a45c8a3f6a1899c1b Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 1 Apr 2026 13:18:24 +1300 Subject: [PATCH 1862/2030] Bump version to 2026.3.2 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index d86894435f..97201d1c44 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.1 +PROJECT_NUMBER = 2026.3.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index 52ac7acd22..ebab56193c 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.1" +__version__ = "2026.3.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 8f2cf8b8a75ed710559eff51a37097bc2100959a Mon Sep 17 00:00:00 2001 From: Christian H <28529536+nytaros@users.noreply.github.com> Date: Wed, 1 Apr 2026 03:39:41 +0200 Subject: [PATCH 1863/2030] [bmp581_base] Add support for BMP585 (#15277) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/bmp581_base/bmp581_base.cpp | 2 +- esphome/components/bmp581_base/bmp581_base.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/bmp581_base/bmp581_base.cpp b/esphome/components/bmp581_base/bmp581_base.cpp index c9d250545b..7a627eee03 100644 --- a/esphome/components/bmp581_base/bmp581_base.cpp +++ b/esphome/components/bmp581_base/bmp581_base.cpp @@ -126,7 +126,7 @@ void BMP581Component::setup() { } // verify id - if (chip_id != BMP581_ASIC_ID) { + if (chip_id != BMP581_ASIC_ID && chip_id != BMP585_ASIC_ID) { ESP_LOGE(TAG, "Unknown chip ID"); this->error_code_ = ERROR_WRONG_CHIP_ID; diff --git a/esphome/components/bmp581_base/bmp581_base.h b/esphome/components/bmp581_base/bmp581_base.h index c3920512e0..1a73a91558 100644 --- a/esphome/components/bmp581_base/bmp581_base.h +++ b/esphome/components/bmp581_base/bmp581_base.h @@ -8,7 +8,8 @@ namespace esphome::bmp581_base { static const uint8_t BMP581_ASIC_ID = 0x50; // BMP581's ASIC chip ID (page 51 of datasheet) -static const uint8_t RESET_COMMAND = 0xB6; // Soft reset command +static const uint8_t BMP585_ASIC_ID = 0x51; +static const uint8_t RESET_COMMAND = 0xB6; // Soft reset command // BMP581 Register Addresses enum { From 31a70ab29911d646dc602a0df012d73ba6c85f9b Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Tue, 31 Mar 2026 21:44:54 -0400 Subject: [PATCH 1864/2030] [resampler] Future-proof resampler task to avoid potential memory leaks (#15186) --- .../resampler/speaker/resampler_speaker.cpp | 86 ++++++++++--------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/esphome/components/resampler/speaker/resampler_speaker.cpp b/esphome/components/resampler/speaker/resampler_speaker.cpp index 1303bc459e..b737a2d39a 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.cpp +++ b/esphome/components/resampler/speaker/resampler_speaker.cpp @@ -317,57 +317,59 @@ void ResamplerSpeaker::resample_task(void *params) { xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STARTING); - std::unique_ptr<audio::AudioResampler> resampler = - make_unique<audio::AudioResampler>(this_resampler->audio_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS), - this_resampler->target_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); + { // Ensure C++ objects fall out of scope for proper cleanup before stopping the task + std::unique_ptr<audio::AudioResampler> resampler = make_unique<audio::AudioResampler>( + this_resampler->audio_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS), + this_resampler->target_stream_info_.ms_to_bytes(TRANSFER_BUFFER_DURATION_MS)); - esp_err_t err = resampler->start(this_resampler->audio_stream_info_, this_resampler->target_stream_info_, - this_resampler->taps_, this_resampler->filters_); + esp_err_t err = resampler->start(this_resampler->audio_stream_info_, this_resampler->target_stream_info_, + this_resampler->taps_, this_resampler->filters_); - if (err == ESP_OK) { - std::shared_ptr<RingBuffer> temp_ring_buffer = - RingBuffer::create(this_resampler->audio_stream_info_.ms_to_bytes(this_resampler->buffer_duration_ms_)); + if (err == ESP_OK) { + std::shared_ptr<RingBuffer> temp_ring_buffer = + RingBuffer::create(this_resampler->audio_stream_info_.ms_to_bytes(this_resampler->buffer_duration_ms_)); - if (!temp_ring_buffer) { - err = ESP_ERR_NO_MEM; - } else { - this_resampler->ring_buffer_ = temp_ring_buffer; - resampler->add_source(this_resampler->ring_buffer_); + if (!temp_ring_buffer) { + err = ESP_ERR_NO_MEM; + } else { + this_resampler->ring_buffer_ = temp_ring_buffer; + resampler->add_source(this_resampler->ring_buffer_); - this_resampler->output_speaker_->set_audio_stream_info(this_resampler->target_stream_info_); - resampler->add_sink(this_resampler->output_speaker_); - } - } - - if (err == ESP_OK) { - xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_RUNNING); - } else if (err == ESP_ERR_NO_MEM) { - xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM); - } else if (err == ESP_ERR_NOT_SUPPORTED) { - xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED); - } - - while (err == ESP_OK) { - uint32_t event_bits = xEventGroupGetBits(this_resampler->event_group_); - - if (event_bits & ResamplingEventGroupBits::TASK_COMMAND_STOP) { - break; + this_resampler->output_speaker_->set_audio_stream_info(this_resampler->target_stream_info_); + resampler->add_sink(this_resampler->output_speaker_); + } } - // Stop gracefully if the decoder is done - int32_t ms_differential = 0; - audio::AudioResamplerState resampler_state = resampler->resample(false, &ms_differential); - - if (resampler_state == audio::AudioResamplerState::FINISHED) { - break; - } else if (resampler_state == audio::AudioResamplerState::FAILED) { - xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL); - break; + if (err == ESP_OK) { + xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_RUNNING); + } else if (err == ESP_ERR_NO_MEM) { + xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NO_MEM); + } else if (err == ESP_ERR_NOT_SUPPORTED) { + xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_NOT_SUPPORTED); } + + while (err == ESP_OK) { + uint32_t event_bits = xEventGroupGetBits(this_resampler->event_group_); + + if (event_bits & ResamplingEventGroupBits::TASK_COMMAND_STOP) { + break; + } + + // Stop gracefully if the decoder is done + int32_t ms_differential = 0; + audio::AudioResamplerState resampler_state = resampler->resample(false, &ms_differential); + + if (resampler_state == audio::AudioResamplerState::FINISHED) { + break; + } else if (resampler_state == audio::AudioResamplerState::FAILED) { + xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::ERR_ESP_FAIL); + break; + } + } + + xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPING); } - xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPING); - resampler.reset(); xEventGroupSetBits(this_resampler->event_group_, ResamplingEventGroupBits::STATE_STOPPED); vTaskSuspend(nullptr); // Suspend this task indefinitely until the loop method deletes it From 212b3e16880808ab7e3af1b6a5f513a9f622b2fb Mon Sep 17 00:00:00 2001 From: Rene Guca <45061891+rguca@users.noreply.github.com> Date: Wed, 1 Apr 2026 03:59:24 +0200 Subject: [PATCH 1865/2030] [cover] move time_based_cover to its own subdirectory (#15313) Co-authored-by: Rene <rene@guca.at> --- esphome/components/time_based/__init__.py | 3 +++ esphome/components/time_based/{cover.py => cover/__init__.py} | 3 ++- esphome/components/time_based/{ => cover}/time_based_cover.cpp | 0 esphome/components/time_based/{ => cover}/time_based_cover.h | 0 4 files changed, 5 insertions(+), 1 deletion(-) rename esphome/components/time_based/{cover.py => cover/__init__.py} (97%) rename esphome/components/time_based/{ => cover}/time_based_cover.cpp (100%) rename esphome/components/time_based/{ => cover}/time_based_cover.h (100%) diff --git a/esphome/components/time_based/__init__.py b/esphome/components/time_based/__init__.py index e69de29bb2..ce2f453bda 100644 --- a/esphome/components/time_based/__init__.py +++ b/esphome/components/time_based/__init__.py @@ -0,0 +1,3 @@ +import esphome.codegen as cg + +time_based_ns = cg.esphome_ns.namespace("time_based") diff --git a/esphome/components/time_based/cover.py b/esphome/components/time_based/cover/__init__.py similarity index 97% rename from esphome/components/time_based/cover.py rename to esphome/components/time_based/cover/__init__.py index d14332d453..022b48d249 100644 --- a/esphome/components/time_based/cover.py +++ b/esphome/components/time_based/cover/__init__.py @@ -11,7 +11,8 @@ from esphome.const import ( CONF_STOP_ACTION, ) -time_based_ns = cg.esphome_ns.namespace("time_based") +from .. import time_based_ns + TimeBasedCover = time_based_ns.class_("TimeBasedCover", cover.Cover, cg.Component) CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop" diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/cover/time_based_cover.cpp similarity index 100% rename from esphome/components/time_based/time_based_cover.cpp rename to esphome/components/time_based/cover/time_based_cover.cpp diff --git a/esphome/components/time_based/time_based_cover.h b/esphome/components/time_based/cover/time_based_cover.h similarity index 100% rename from esphome/components/time_based/time_based_cover.h rename to esphome/components/time_based/cover/time_based_cover.h From fbfb5d401f99cf40d60bdced6db36ba00262f27e Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 1 Apr 2026 10:34:29 +0200 Subject: [PATCH 1866/2030] [nextion] Fix memory leak in `reset_()` (#15344) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/nextion/nextion.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index bb3e12be50..d141ef7906 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -143,8 +143,17 @@ void Nextion::reset_(bool reset_nextion) { while (this->available()) { // Clear receive buffer this->read_byte(&d); - }; + } + for (auto *entry : this->nextion_queue_) { + if (entry->component != nullptr && entry->component->get_queue_type() == NextionQueueType::NO_RESULT) { + delete entry->component; // NOLINT(cppcoreguidelines-owning-memory) + } + delete entry; // NOLINT(cppcoreguidelines-owning-memory) + } this->nextion_queue_.clear(); + for (auto *entry : this->waveform_queue_) { + delete entry; // NOLINT(cppcoreguidelines-owning-memory) + } this->waveform_queue_.clear(); } From cc8889628010840dcbc9167e07adf6ec342e00b9 Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Wed, 1 Apr 2026 17:04:22 +0200 Subject: [PATCH 1867/2030] [debug] add peripherals status (#12053) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/debug/debug_zephyr.cpp | 47 ++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/esphome/components/debug/debug_zephyr.cpp b/esphome/components/debug/debug_zephyr.cpp index bf87b7ae3d..d1580dae80 100644 --- a/esphome/components/debug/debug_zephyr.cpp +++ b/esphome/components/debug/debug_zephyr.cpp @@ -91,6 +91,49 @@ void DebugComponent::log_partition_info_() { flash_area_foreach(fa_cb, nullptr); } +#ifdef ESPHOME_LOG_HAS_VERBOSE +// Check if an nRF peripheral's ENABLE register indicates it is enabled. +// periph: peripheral register prefix (e.g. USBD, UARTE, SPI) +// reg: register block pointer (e.g. NRF_USBD, NRF_UARTE0) +#define NRF_PERIPH_ENABLED(periph, reg) \ + YESNO(((reg)->ENABLE & periph##_ENABLE_ENABLE_Msk) == (periph##_ENABLE_ENABLE_Enabled << periph##_ENABLE_ENABLE_Pos)) + +static void log_peripherals_info() { + // most peripherals are enabled only when in use so ESP_LOGV is enough + ESP_LOGV(TAG, "Peripherals status:"); + ESP_LOGV(TAG, " USBD: %-3s| UARTE0: %-3s| UARTE1: %-3s| UART0: %-3s", // + NRF_PERIPH_ENABLED(USBD, NRF_USBD), NRF_PERIPH_ENABLED(UARTE, NRF_UARTE0), + NRF_PERIPH_ENABLED(UARTE, NRF_UARTE1), NRF_PERIPH_ENABLED(UART, NRF_UART0)); + ESP_LOGV(TAG, " TWIS0: %-3s| TWIS1: %-3s| TWIM0: %-3s| TWIM1: %-3s", // + NRF_PERIPH_ENABLED(TWIS, NRF_TWIS0), NRF_PERIPH_ENABLED(TWIS, NRF_TWIS1), + NRF_PERIPH_ENABLED(TWIM, NRF_TWIM0), NRF_PERIPH_ENABLED(TWIM, NRF_TWIM1)); + ESP_LOGV(TAG, " TWI0: %-3s| TWI1: %-3s| COMP: %-3s| CCM: %-3s", // + NRF_PERIPH_ENABLED(TWI, NRF_TWI0), NRF_PERIPH_ENABLED(TWI, NRF_TWI1), NRF_PERIPH_ENABLED(COMP, NRF_COMP), + NRF_PERIPH_ENABLED(CCM, NRF_CCM)); + ESP_LOGV(TAG, " PDM: %-3s| SPIS0: %-3s| SPIS1: %-3s| SPIS2: %-3s", // + NRF_PERIPH_ENABLED(PDM, NRF_PDM), NRF_PERIPH_ENABLED(SPIS, NRF_SPIS0), NRF_PERIPH_ENABLED(SPIS, NRF_SPIS1), + NRF_PERIPH_ENABLED(SPIS, NRF_SPIS2)); + ESP_LOGV(TAG, " SPIM0: %-3s| SPIM1: %-3s| SPIM2: %-3s| SPIM3: %-3s", // + NRF_PERIPH_ENABLED(SPIM, NRF_SPIM0), NRF_PERIPH_ENABLED(SPIM, NRF_SPIM1), + NRF_PERIPH_ENABLED(SPIM, NRF_SPIM2), NRF_PERIPH_ENABLED(SPIM, NRF_SPIM3)); + ESP_LOGV(TAG, " SPI0: %-3s| SPI1: %-3s| SPI2: %-3s| SAADC: %-3s", // + NRF_PERIPH_ENABLED(SPI, NRF_SPI0), NRF_PERIPH_ENABLED(SPI, NRF_SPI1), NRF_PERIPH_ENABLED(SPI, NRF_SPI2), + NRF_PERIPH_ENABLED(SAADC, NRF_SAADC)); + ESP_LOGV(TAG, " QSPI: %-3s| QDEC: %-3s| LPCOMP: %-3s| I2S: %-3s", // + NRF_PERIPH_ENABLED(QSPI, NRF_QSPI), NRF_PERIPH_ENABLED(QDEC, NRF_QDEC), + NRF_PERIPH_ENABLED(LPCOMP, NRF_LPCOMP), NRF_PERIPH_ENABLED(I2S, NRF_I2S)); + ESP_LOGV(TAG, " PWM0: %-3s| PWM1: %-3s| PWM2: %-3s| PWM3: %-3s", // + NRF_PERIPH_ENABLED(PWM, NRF_PWM0), NRF_PERIPH_ENABLED(PWM, NRF_PWM1), NRF_PERIPH_ENABLED(PWM, NRF_PWM2), + NRF_PERIPH_ENABLED(PWM, NRF_PWM3)); + ESP_LOGV(TAG, " AAR: %-3s| QSPI deep power-down:%-3s| CRYPTOCELL: %-3s", NRF_PERIPH_ENABLED(AAR, NRF_AAR), + YESNO((NRF_QSPI->IFCONFIG0 & QSPI_IFCONFIG0_DPMENABLE_Msk) == + (QSPI_IFCONFIG0_DPMENABLE_Enable << QSPI_IFCONFIG0_DPMENABLE_Pos)), + YESNO((NRF_CRYPTOCELL->ENABLE & CRYPTOCELL_ENABLE_ENABLE_Msk) == + (CRYPTOCELL_ENABLE_ENABLE_Enabled << CRYPTOCELL_ENABLE_ENABLE_Pos))); +} +#undef NRF_PERIPH_ENABLED +#endif + static const char *regout0_to_str(uint32_t value) { switch (value) { case (UICR_REGOUT0_VOUT_DEFAULT): @@ -354,7 +397,9 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE> }; ESP_LOGD(TAG, " NRFFW %s", uicr(NRF_UICR->NRFFW, 13).c_str()); ESP_LOGD(TAG, " NRFHW %s", uicr(NRF_UICR->NRFHW, 12).c_str()); - +#ifdef ESPHOME_LOG_HAS_VERBOSE + log_peripherals_info(); +#endif return pos; } From f33fd047ee5589fa7d21445ed42bb541fe06e92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7alo=20Pereira?= <goncalo_pereira@outlook.pt> Date: Wed, 1 Apr 2026 17:09:22 +0100 Subject: [PATCH 1868/2030] [hdc2080] Add support for HDC2080 sensor (#9331) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: Big Mike <mikelawrence@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- CODEOWNERS | 1 + esphome/components/hdc2080/__init__.py | 1 + esphome/components/hdc2080/hdc2080.cpp | 71 +++++++++++++++++++ esphome/components/hdc2080/hdc2080.h | 24 +++++++ esphome/components/hdc2080/sensor.py | 57 +++++++++++++++ tests/components/hdc2080/common.yaml | 7 ++ tests/components/hdc2080/test.esp32-idf.yaml | 4 ++ .../components/hdc2080/test.esp8266-ard.yaml | 4 ++ tests/components/hdc2080/test.rp2040-ard.yaml | 4 ++ 9 files changed, 173 insertions(+) create mode 100644 esphome/components/hdc2080/__init__.py create mode 100644 esphome/components/hdc2080/hdc2080.cpp create mode 100644 esphome/components/hdc2080/hdc2080.h create mode 100644 esphome/components/hdc2080/sensor.py create mode 100644 tests/components/hdc2080/common.yaml create mode 100644 tests/components/hdc2080/test.esp32-idf.yaml create mode 100644 tests/components/hdc2080/test.esp8266-ard.yaml create mode 100644 tests/components/hdc2080/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 8d297d7b07..03f41618af 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -217,6 +217,7 @@ esphome/components/hbridge/light/* @DotNetDann esphome/components/hbridge/switch/* @dwmw2 esphome/components/hc8/* @omartijn esphome/components/hdc2010/* @optimusprimespace @ssieb +esphome/components/hdc2080/* @G-Pereira @jesserockz esphome/components/hdc302x/* @joshuasing esphome/components/he60r/* @clydebarrow esphome/components/heatpumpir/* @rob-deutsch diff --git a/esphome/components/hdc2080/__init__.py b/esphome/components/hdc2080/__init__.py new file mode 100644 index 0000000000..341ea61048 --- /dev/null +++ b/esphome/components/hdc2080/__init__.py @@ -0,0 +1 @@ +CODEOWNERS = ["@G-Pereira", "@jesserockz"] diff --git a/esphome/components/hdc2080/hdc2080.cpp b/esphome/components/hdc2080/hdc2080.cpp new file mode 100644 index 0000000000..dcb207e099 --- /dev/null +++ b/esphome/components/hdc2080/hdc2080.cpp @@ -0,0 +1,71 @@ +#include "hdc2080.h" +#include "esphome/core/hal.h" +#include "esphome/core/log.h" + +namespace esphome::hdc2080 { + +static const char *const TAG = "hdc2080"; + +// Register map (Table 8-6) +static constexpr uint8_t REG_TEMPERATURE_LOW = 0x00; // Temperature [7:0] +static constexpr uint8_t REG_TEMPERATURE_HIGH = 0x01; // Temperature [15:8] +static constexpr uint8_t REG_HUMIDITY_LOW = 0x02; // Humidity [7:0] +static constexpr uint8_t REG_HUMIDITY_HIGH = 0x03; // Humidity [15:8] +static constexpr uint8_t REG_RESET_DRDY_INT_CONF = 0x0E; // Soft Reset and Interrupt Configuration +static constexpr uint8_t REG_MEASUREMENT_CONFIGURATION = 0x0F; + +// Measurement register (0x0F) bit fields +static constexpr uint8_t MEAS_TRIG = 0x01; // Bit 0: start measurement +static constexpr uint8_t MEAS_CONF_TEMP = 0x02; // Bits 2:1 = 01: temperature only +static constexpr uint8_t MEAS_CONF_HUM = 0x04; // Bits 2:1 = 10: humidity only + +void HDC2080Component::setup() { + const uint8_t data = 0x00; // automatic measurement mode disabled, heater off + if (this->write_register(REG_RESET_DRDY_INT_CONF, &data, 1) != i2c::ERROR_OK) { + this->mark_failed(ESP_LOG_MSG_COMM_FAIL); + return; + } +} + +void HDC2080Component::dump_config() { + ESP_LOGCONFIG(TAG, "HDC2080:"); + LOG_I2C_DEVICE(this); + LOG_UPDATE_INTERVAL(this); + LOG_SENSOR(" ", "Temperature", this->temperature_sensor_); + LOG_SENSOR(" ", "Humidity", this->humidity_sensor_); + if (this->is_failed()) { + ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); + } +} + +void HDC2080Component::update() { + uint8_t data = MEAS_TRIG; // 14-bit resolution, measure both, start + if (this->temperature_sensor_ != nullptr && this->humidity_sensor_ == nullptr) { + data = MEAS_TRIG | MEAS_CONF_TEMP; + } else if (this->temperature_sensor_ == nullptr && this->humidity_sensor_ != nullptr) { + data = MEAS_TRIG | MEAS_CONF_HUM; + } + if (this->write_register(REG_MEASUREMENT_CONFIGURATION, &data, 1) != i2c::ERROR_OK) { + this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); + return; + } + // wait for conversion to complete 2ms should be enough, more is fine + this->set_timeout(5, [this]() { + uint8_t raw_data[4]; + if (this->read_register(REG_TEMPERATURE_LOW, raw_data, 4) != i2c::ERROR_OK) { + this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); + return; + } + this->status_clear_warning(); + if (this->temperature_sensor_ != nullptr) { + float temp = encode_uint16(raw_data[1], raw_data[0]) * (165.0f / 65536.0f) - 40.5f; + this->temperature_sensor_->publish_state(temp); + } + if (this->humidity_sensor_ != nullptr) { + float humidity = encode_uint16(raw_data[3], raw_data[2]) * (100.0f / 65536.0f); + this->humidity_sensor_->publish_state(humidity); + } + }); +} + +} // namespace esphome::hdc2080 diff --git a/esphome/components/hdc2080/hdc2080.h b/esphome/components/hdc2080/hdc2080.h new file mode 100644 index 0000000000..daa10d371d --- /dev/null +++ b/esphome/components/hdc2080/hdc2080.h @@ -0,0 +1,24 @@ +#pragma once + +#include "esphome/components/i2c/i2c.h" +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" + +namespace esphome::hdc2080 { + +class HDC2080Component : public PollingComponent, public i2c::I2CDevice { + public: + void set_temperature(sensor::Sensor *temperature) { this->temperature_sensor_ = temperature; } + void set_humidity(sensor::Sensor *humidity) { this->humidity_sensor_ = humidity; } + + /// Setup the sensor and check for connection. + void setup() override; + void dump_config() override; + void update() override; + + protected: + sensor::Sensor *temperature_sensor_{nullptr}; + sensor::Sensor *humidity_sensor_{nullptr}; +}; + +} // namespace esphome::hdc2080 diff --git a/esphome/components/hdc2080/sensor.py b/esphome/components/hdc2080/sensor.py new file mode 100644 index 0000000000..777fc51cba --- /dev/null +++ b/esphome/components/hdc2080/sensor.py @@ -0,0 +1,57 @@ +import esphome.codegen as cg +from esphome.components import i2c, sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_HUMIDITY, + CONF_ID, + CONF_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + STATE_CLASS_MEASUREMENT, + UNIT_CELSIUS, + UNIT_PERCENT, +) + +DEPENDENCIES = ["i2c"] + +hdc2080_ns = cg.esphome_ns.namespace("hdc2080") +HDC2080Component = hdc2080_ns.class_( + "HDC2080Component", cg.PollingComponent, i2c.I2CDevice +) + +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HDC2080Component), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + unit_of_measurement=UNIT_CELSIUS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + unit_of_measurement=UNIT_PERCENT, + accuracy_decimals=0, + device_class=DEVICE_CLASS_HUMIDITY, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) + .add_extra(cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_HUMIDITY)) +) + + +async def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await i2c.register_i2c_device(var, config) + + if temperature_config := config.get(CONF_TEMPERATURE): + sens = await sensor.new_sensor(temperature_config) + cg.add(var.set_temperature(sens)) + + if humidity_config := config.get(CONF_HUMIDITY): + sens = await sensor.new_sensor(humidity_config) + cg.add(var.set_humidity(sens)) diff --git a/tests/components/hdc2080/common.yaml b/tests/components/hdc2080/common.yaml new file mode 100644 index 0000000000..cb14cb183b --- /dev/null +++ b/tests/components/hdc2080/common.yaml @@ -0,0 +1,7 @@ +sensor: + - platform: hdc2080 + temperature: + name: Temperature + humidity: + name: Humidity + update_interval: 15s diff --git a/tests/components/hdc2080/test.esp32-idf.yaml b/tests/components/hdc2080/test.esp32-idf.yaml new file mode 100644 index 0000000000..b47e39c389 --- /dev/null +++ b/tests/components/hdc2080/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/hdc2080/test.esp8266-ard.yaml b/tests/components/hdc2080/test.esp8266-ard.yaml new file mode 100644 index 0000000000..4a98b9388a --- /dev/null +++ b/tests/components/hdc2080/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/hdc2080/test.rp2040-ard.yaml b/tests/components/hdc2080/test.rp2040-ard.yaml new file mode 100644 index 0000000000..319a7c71a6 --- /dev/null +++ b/tests/components/hdc2080/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml + +<<: !include common.yaml From ea609d3552fe0685a68a97362abc5658f203837b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 07:09:04 -1000 Subject: [PATCH 1869/2030] [runtime_stats] Store stats inline on Component to eliminate std::map lookup (#15345) --- .../runtime_stats/runtime_stats.cpp | 76 +++++++++---------- .../components/runtime_stats/runtime_stats.h | 75 +----------------- esphome/core/application.h | 9 +++ esphome/core/component.cpp | 12 +-- esphome/core/component.h | 42 ++++++++++ esphome/core/defines.h | 1 + 6 files changed, 92 insertions(+), 123 deletions(-) diff --git a/esphome/components/runtime_stats/runtime_stats.cpp b/esphome/components/runtime_stats/runtime_stats.cpp index cb28acc96c..06714b5a44 100644 --- a/esphome/components/runtime_stats/runtime_stats.cpp +++ b/esphome/components/runtime_stats/runtime_stats.cpp @@ -2,6 +2,7 @@ #ifdef USE_RUNTIME_STATS +#include "esphome/core/application.h" #include "esphome/core/component.h" #include <algorithm> @@ -13,20 +14,16 @@ RuntimeStatsCollector::RuntimeStatsCollector() : log_interval_(60000), next_log_ global_runtime_stats = this; } -void RuntimeStatsCollector::record_component_time(Component *component, uint32_t duration_us) { - if (component == nullptr) - return; - - // Record stats using component pointer as key - this->component_stats_[component].record_time(duration_us); -} - void RuntimeStatsCollector::log_stats_() { - // First pass: count active components + auto &components = App.components_; + + // Single pass: collect active components into stack buffer + SmallBufferWithHeapFallback<256, Component *> buffer(components.size()); + Component **sorted = buffer.get(); size_t count = 0; - for (const auto &it : this->component_stats_) { - if (it.second.get_period_count() > 0) { - count++; + for (auto *component : components) { + if (component->runtime_stats_.period_count > 0) { + sorted[count++] = component; } } @@ -39,61 +36,58 @@ void RuntimeStatsCollector::log_stats_() { return; } - // Stack buffer sized to actual active count (up to 256 components), heap fallback for larger - SmallBufferWithHeapFallback<256, Component *> buffer(count); - Component **sorted = buffer.get(); - - // Second pass: fill buffer with active components - size_t idx = 0; - for (const auto &it : this->component_stats_) { - if (it.second.get_period_count() > 0) { - sorted[idx++] = it.first; - } - } - // Sort by period runtime (descending) - std::sort(sorted, sorted + count, [this](Component *a, Component *b) { - return this->component_stats_[a].get_period_time_us() > this->component_stats_[b].get_period_time_us(); - }); + std::sort(sorted, sorted + count, compare_period_time); // Log top components by period runtime for (size_t i = 0; i < count; i++) { - const auto &stats = this->component_stats_[sorted[i]]; + const auto &stats = sorted[i]->runtime_stats_; ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.3fms, max=%.2fms, total=%.1fms", - LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_period_count(), - stats.get_period_avg_time_us() / 1000.0f, stats.get_period_max_time_us() / 1000.0f, - stats.get_period_time_us() / 1000.0f); + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.period_count, + stats.period_count > 0 ? stats.period_time_us / (float) stats.period_count / 1000.0f : 0.0f, + stats.period_max_time_us / 1000.0f, stats.period_time_us / 1000.0f); } // Log total stats since boot (only for active components - idle ones haven't changed) ESP_LOGI(TAG, " Total stats (since boot): %zu active components", count); // Re-sort by total runtime for all-time stats - std::sort(sorted, sorted + count, [this](Component *a, Component *b) { - return this->component_stats_[a].get_total_time_us() > this->component_stats_[b].get_total_time_us(); - }); + std::sort(sorted, sorted + count, compare_total_time); for (size_t i = 0; i < count; i++) { - const auto &stats = this->component_stats_[sorted[i]]; + const auto &stats = sorted[i]->runtime_stats_; ESP_LOGI(TAG, " %s: count=%" PRIu32 ", avg=%.3fms, max=%.2fms, total=%.1fms", - LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.get_total_count(), - stats.get_total_avg_time_us() / 1000.0f, stats.get_total_max_time_us() / 1000.0f, - stats.get_total_time_us() / 1000.0); + LOG_STR_ARG(sorted[i]->get_component_log_str()), stats.total_count, + stats.total_count > 0 ? stats.total_time_us / (float) stats.total_count / 1000.0f : 0.0f, + stats.total_max_time_us / 1000.0f, stats.total_time_us / 1000.0); } + + // Reset period stats + for (auto *component : components) { + component->runtime_stats_.reset_period(); + } +} + +bool RuntimeStatsCollector::compare_period_time(Component *a, Component *b) { + return a->runtime_stats_.period_time_us > b->runtime_stats_.period_time_us; +} + +bool RuntimeStatsCollector::compare_total_time(Component *a, Component *b) { + return a->runtime_stats_.total_time_us > b->runtime_stats_.total_time_us; } void RuntimeStatsCollector::process_pending_stats(uint32_t current_time) { if ((int32_t) (current_time - this->next_log_time_) >= 0) { this->log_stats_(); - this->reset_stats_(); this->next_log_time_ = current_time + this->log_interval_; } } } // namespace runtime_stats -runtime_stats::RuntimeStatsCollector *global_runtime_stats = - nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +runtime_stats::RuntimeStatsCollector + *global_runtime_stats = // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + nullptr; } // namespace esphome diff --git a/esphome/components/runtime_stats/runtime_stats.h b/esphome/components/runtime_stats/runtime_stats.h index 303d895985..3c2c9f78ad 100644 --- a/esphome/components/runtime_stats/runtime_stats.h +++ b/esphome/components/runtime_stats/runtime_stats.h @@ -4,11 +4,8 @@ #ifdef USE_RUNTIME_STATS -#include <map> #include <cstdint> -#include <cstring> #include "esphome/core/hal.h" -#include "esphome/core/helpers.h" #include "esphome/core/log.h" namespace esphome { @@ -19,64 +16,6 @@ namespace runtime_stats { static const char *const TAG = "runtime_stats"; -class ComponentRuntimeStats { - public: - ComponentRuntimeStats() - : period_count_(0), - period_time_us_(0), - period_max_time_us_(0), - total_count_(0), - total_time_us_(0), - total_max_time_us_(0) {} - - void record_time(uint32_t duration_us) { - // Update period counters - this->period_count_++; - this->period_time_us_ += duration_us; - if (duration_us > this->period_max_time_us_) - this->period_max_time_us_ = duration_us; - - // Update total counters (uint64_t to avoid overflow — uint32_t would overflow after ~10 hours) - this->total_count_++; - this->total_time_us_ += duration_us; - if (duration_us > this->total_max_time_us_) - this->total_max_time_us_ = duration_us; - } - - void reset_period_stats() { - this->period_count_ = 0; - this->period_time_us_ = 0; - this->period_max_time_us_ = 0; - } - - // Period stats (reset each logging interval) - uint32_t get_period_count() const { return this->period_count_; } - uint32_t get_period_time_us() const { return this->period_time_us_; } - uint32_t get_period_max_time_us() const { return this->period_max_time_us_; } - float get_period_avg_time_us() const { - return this->period_count_ > 0 ? this->period_time_us_ / static_cast<float>(this->period_count_) : 0.0f; - } - - // Total stats (persistent until reboot, uint64_t to avoid overflow) - uint32_t get_total_count() const { return this->total_count_; } - uint64_t get_total_time_us() const { return this->total_time_us_; } - uint32_t get_total_max_time_us() const { return this->total_max_time_us_; } - float get_total_avg_time_us() const { - return this->total_count_ > 0 ? this->total_time_us_ / static_cast<float>(this->total_count_) : 0.0f; - } - - protected: - // Period stats (reset each logging interval) - uint32_t period_count_; - uint32_t period_time_us_; - uint32_t period_max_time_us_; - - // Total stats (persistent until reboot) - uint32_t total_count_; - uint64_t total_time_us_; - uint32_t total_max_time_us_; -}; - class RuntimeStatsCollector { public: RuntimeStatsCollector(); @@ -87,23 +26,15 @@ class RuntimeStatsCollector { } uint32_t get_log_interval() const { return this->log_interval_; } - void record_component_time(Component *component, uint32_t duration_us); - // Process any pending stats printing (should be called after component loop) void process_pending_stats(uint32_t current_time); protected: void log_stats_(); + // Static comparators — member functions have friend access, lambdas do not + static bool compare_period_time(Component *a, Component *b); + static bool compare_total_time(Component *a, Component *b); - void reset_stats_() { - for (auto &it : this->component_stats_) { - it.second.reset_period_stats(); - } - } - - // Map from component to its stats - // We use Component* as the key since each component is unique - std::map<Component *, ComponentRuntimeStats> component_stats_; uint32_t log_interval_; uint32_t next_log_time_{0}; }; diff --git a/esphome/core/application.h b/esphome/core/application.h index 06ff30e81f..6cc61bc954 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -130,6 +130,12 @@ bool socket_ready_fd(int fd, bool loop_monitored); // NOLINT(readability-redund #endif } // namespace esphome::socket +#ifdef USE_RUNTIME_STATS +namespace esphome::runtime_stats { +class RuntimeStatsCollector; +} // namespace esphome::runtime_stats +#endif + // Forward declarations for friend access from codegen-generated setup() void setup(); // NOLINT(readability-redundant-declaration) - may be declared in Arduino.h void original_setup(); // NOLINT(readability-redundant-declaration) - used by cpp unit tests @@ -590,6 +596,9 @@ class Application { friend Component; #if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) friend bool socket::socket_ready_fd(int fd, bool loop_monitored); +#endif +#ifdef USE_RUNTIME_STATS + friend class runtime_stats::RuntimeStatsCollector; #endif friend void ::setup(); friend void ::original_setup(); diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 00a36fce3d..955596ce95 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -9,9 +9,6 @@ #include "esphome/core/hal.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" -#ifdef USE_RUNTIME_STATS -#include "esphome/components/runtime_stats/runtime_stats.h" -#endif namespace esphome { @@ -524,13 +521,8 @@ WarnIfComponentBlockingGuard::warn_blocking(Component *component, uint32_t block #ifdef USE_RUNTIME_STATS void WarnIfComponentBlockingGuard::record_runtime_stats_() { - // Use micros() for accurate sub-millisecond timing. millis() has insufficient - // resolution — most components complete in microseconds but millis() only has - // 1ms granularity, so results were essentially random noise. - if (global_runtime_stats != nullptr) { - uint32_t duration_us = micros() - this->started_us_; - global_runtime_stats->record_component_time(this->component_, duration_us); - } + uint32_t duration_us = micros() - this->started_us_; + this->component_->runtime_stats_.record_time(duration_us); } #endif diff --git a/esphome/core/component.h b/esphome/core/component.h index c390a205f0..c5a331ee29 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -20,6 +20,12 @@ namespace esphome { // Forward declaration for LogString struct LogString; +#ifdef USE_RUNTIME_STATS +namespace runtime_stats { +class RuntimeStatsCollector; +} // namespace runtime_stats +#endif + /** Default setup priorities for components of different types. * * Components should return one of these setup priorities in get_setup_priority. @@ -92,6 +98,37 @@ inline constexpr uint8_t WARN_IF_BLOCKING_OVER_CS = 5U; // 50ms in centiseconds /// Weak default returns "<unknown>" so builds without codegen still link. const LogString *component_source_lookup(uint8_t index); +#ifdef USE_RUNTIME_STATS +/// Inline runtime statistics — eliminates std::map lookup on every loop iteration. +/// Only present when USE_RUNTIME_STATS is defined (profiling builds). +struct ComponentRuntimeStats { + // Period stats (reset each logging interval) + uint32_t period_count{0}; + uint32_t period_time_us{0}; + uint32_t period_max_time_us{0}; + // Total stats (persistent until reboot, uint64_t to avoid overflow) + uint32_t total_count{0}; + uint64_t total_time_us{0}; + uint32_t total_max_time_us{0}; + + void record_time(uint32_t duration_us) { + this->period_count++; + this->period_time_us += duration_us; + if (duration_us > this->period_max_time_us) + this->period_max_time_us = duration_us; + this->total_count++; + this->total_time_us += duration_us; + if (duration_us > this->total_max_time_us) + this->total_max_time_us = duration_us; + } + void reset_period() { + this->period_count = 0; + this->period_time_us = 0; + this->period_max_time_us = 0; + } +}; +#endif + class Component { public: /** Where the component's initialization should happen. @@ -529,6 +566,11 @@ class Component { /// Bits 6-7: Unused - reserved for future expansion uint8_t component_state_{0x00}; volatile bool pending_enable_loop_{false}; ///< ISR-safe flag for enable_loop_soon_any_context +#ifdef USE_RUNTIME_STATS + friend class runtime_stats::RuntimeStatsCollector; + friend class WarnIfComponentBlockingGuard; + ComponentRuntimeStats runtime_stats_; +#endif }; /** This class simplifies creating components that periodically check a state. diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 7259167a52..23e65f55bc 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -180,6 +180,7 @@ #define USE_RUNTIME_IMAGE_BMP #define USE_RUNTIME_IMAGE_PNG #define USE_RUNTIME_IMAGE_JPEG +#define USE_RUNTIME_STATS #define USE_OTA #define USE_OTA_PASSWORD #define USE_OTA_STATE_LISTENER From 2e3ea2152d103a21b0cfbe5018bd3a47aabe285a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Wed, 1 Apr 2026 13:13:23 -0400 Subject: [PATCH 1870/2030] [esp32_camera] Bump esp32-camera to v2.1.6 (#15349) --- esphome/components/camera_encoder/__init__.py | 2 +- esphome/components/esp32_camera/__init__.py | 2 +- esphome/idf_component.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/camera_encoder/__init__.py b/esphome/components/camera_encoder/__init__.py index a0c59a517a..3bbeae7835 100644 --- a/esphome/components/camera_encoder/__init__.py +++ b/esphome/components/camera_encoder/__init__.py @@ -50,7 +50,7 @@ async def to_code(config: ConfigType) -> None: buffer = cg.new_Pvariable(config[CONF_ENCODER_BUFFER_ID]) cg.add(buffer.set_buffer_size(config[CONF_BUFFER_SIZE])) if config[CONF_TYPE] == ESP32_CAMERA_ENCODER: - add_idf_component(name="espressif/esp32-camera", ref="2.1.5") + add_idf_component(name="espressif/esp32-camera", ref="2.1.6") cg.add_define("USE_ESP32_CAMERA_JPEG_ENCODER") var = cg.new_Pvariable( config[CONF_ID], diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index afab849a7c..66af321e4e 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -400,7 +400,7 @@ async def to_code(config): if config[CONF_JPEG_QUALITY] != 0 and config[CONF_PIXEL_FORMAT] != "JPEG": cg.add_define("USE_ESP32_CAMERA_JPEG_CONVERSION") - add_idf_component(name="espressif/esp32-camera", ref="2.1.5") + add_idf_component(name="espressif/esp32-camera", ref="2.1.6") add_idf_sdkconfig_option("CONFIG_SCCB_HARDWARE_I2C_DRIVER_NEW", True) add_idf_sdkconfig_option("CONFIG_SCCB_HARDWARE_I2C_DRIVER_LEGACY", False) diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index c44853969e..462af5d1e7 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -10,7 +10,7 @@ dependencies: espressif/esp-tflite-micro: version: 1.3.3~1 espressif/esp32-camera: - version: 2.1.5 + version: 2.1.6 espressif/mdns: version: 1.10.0 espressif/esp_wifi_remote: From bdce47e764497cd75051f885ffd2916fdf980459 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 2 Apr 2026 07:39:51 +1000 Subject: [PATCH 1871/2030] [lvgl] Fixes #4 (#15334) --- esphome/components/lvgl/__init__.py | 22 +++++++++++++++++----- esphome/components/lvgl/lvgl_esphome.h | 8 +++++--- esphome/components/lvgl/schemas.py | 1 + tests/components/lvgl/lvgl-package.yaml | 8 ++++++++ 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 736fba759f..3b4f150699 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -380,8 +380,10 @@ async def to_code(configs): # This must be done after all widgets are created for comp in helpers.lvgl_components_required: cg.add_define(f"USE_LVGL_{comp.upper()}") - # Currently always need RGB565 for the display buffer, and ARGB8888 is used for layer blending - lv_image_formats = {"RGB565", "ARGB8888"} + for use in helpers.lv_uses: + df.add_define(f"LV_USE_{use.upper()}") + cg.add_define(f"USE_LVGL_{use.upper()}") + if { "transform_rotation", "transform_scale", @@ -389,9 +391,18 @@ async def to_code(configs): "transform_scale_y", } & styles_used: df.add_define("LV_COLOR_SCREEN_TRANSP", "1") - for use in helpers.lv_uses: - df.add_define(f"LV_USE_{use.upper()}") - cg.add_define(f"USE_LVGL_{use.upper()}") + + # Currently always need RGB565 for the display buffer, and ARGB8888 is used for layer blending + lv_image_formats = {"RGB565", "ARGB8888"} + if { + "drop_shadow_color", + "drop_shadow_offset_x", + "drop_shadow_offset_y", + "drop_shadow_opa", + "drop_shadow_quality", + "drop_shadow_radius", + } & styles_used: + lv_image_formats.add("A8") for image_id in lv_images_used: await cg.get_variable(image_id) @@ -410,6 +421,7 @@ async def to_code(configs): lv_image_formats.add("RGB888") for fmt in lv_image_formats: df.add_define(f"LV_DRAW_SW_SUPPORT_{fmt}", "1") + lv_conf_h_file = CORE.relative_src_path(LV_CONF_FILENAME) write_file_if_changed(lv_conf_h_file, generate_lv_conf_h()) cg.add_build_flag("-DLV_CONF_H=1") diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 21d1e0d417..8d139b23cb 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -74,11 +74,13 @@ inline void lv_style_set_text_font(lv_style_t *style, const font::Font *font) { #if defined(USE_LVGL_IMAGE) && defined(USE_IMAGE) // Shortcut / overload, so that the source of an image can easily be updated // from within a lambda. -inline void lv_image_set_src(lv_obj_t *obj, esphome::image::Image *image) { - lv_image_set_src(obj, image->get_lv_image_dsc()); +inline void lv_image_set_src(lv_obj_t *obj, image::Image *image) { lv_image_set_src(obj, image->get_lv_image_dsc()); } + +inline void lv_obj_set_style_bitmap_mask_src(lv_obj_t *obj, image::Image *image, lv_style_selector_t selector) { + lv_obj_set_style_bitmap_mask_src(obj, image->get_lv_image_dsc(), selector); } -inline void lv_obj_set_style_bg_image_src(lv_obj_t *obj, esphome::image::Image *image, lv_style_selector_t selector) { +inline void lv_obj_set_style_bg_image_src(lv_obj_t *obj, image::Image *image, lv_style_selector_t selector) { lv_obj_set_style_bg_image_src(obj, image->get_lv_image_dsc(), selector); } #endif // USE_LVGL_IMAGE diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 9c9504f05f..4f1473b652 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -168,6 +168,7 @@ BASE_PROPS = { "bg_main_opa": lvalid.opacity, "bg_main_stop": lvalid.stop_value, "bg_opa": lvalid.opacity, + "bitmap_mask_src": lvalid.lv_image, "blend_mode": df.LvConstant( "LV_BLEND_MODE_", "NORMAL", diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index b8c9a1809e..abc66ef587 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -511,6 +511,7 @@ lvgl: image: src: cat_image align: top_left + bitmap_mask_src: alert on_click: - lvgl.widget.focus: spin_up - lvgl.widget.focus: next @@ -1189,6 +1190,13 @@ image: type: BINARY transparency: chroma_key + - id: alert + file: $component_dir/logo-text.svg + type: grayscale + resize: 100x100 + invert_alpha: true + transparency: alpha_channel + color: - id: light_blue hex: "3340FF" From 5cdbbd48873b0cfed261b2c19081fd42e99967a0 Mon Sep 17 00:00:00 2001 From: Boris Krivonog <boris.krivonog@inova.si> Date: Wed, 1 Apr 2026 23:48:47 +0200 Subject: [PATCH 1872/2030] [mitsubishi_cn105] Add climate component for Mitsubishi A/C units with CN105 connector (Part 1) (#15315) Co-authored-by: J. Nick Koston <nick+github@koston.org> --- CODEOWNERS | 1 + .../components/mitsubishi_cn105/__init__.py | 0 .../components/mitsubishi_cn105/climate.py | 41 +++++++++++++++++++ .../mitsubishi_cn105/mitsubishi_cn105.cpp | 7 ++++ .../mitsubishi_cn105/mitsubishi_cn105.h | 19 +++++++++ .../mitsubishi_cn105_climate.cpp | 28 +++++++++++++ .../mitsubishi_cn105_climate.h | 27 ++++++++++++ tests/components/mitsubishi_cn105/common.yaml | 4 ++ .../mitsubishi_cn105/test.esp32-idf.yaml | 4 ++ .../mitsubishi_cn105/test.esp8266-ard.yaml | 4 ++ .../mitsubishi_cn105/test.rp2040-ard.yaml | 4 ++ 11 files changed, 139 insertions(+) create mode 100644 esphome/components/mitsubishi_cn105/__init__.py create mode 100644 esphome/components/mitsubishi_cn105/climate.py create mode 100644 esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp create mode 100644 esphome/components/mitsubishi_cn105/mitsubishi_cn105.h create mode 100644 esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp create mode 100644 esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h create mode 100644 tests/components/mitsubishi_cn105/common.yaml create mode 100644 tests/components/mitsubishi_cn105/test.esp32-idf.yaml create mode 100644 tests/components/mitsubishi_cn105/test.esp8266-ard.yaml create mode 100644 tests/components/mitsubishi_cn105/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index 03f41618af..fffe5ce91c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -331,6 +331,7 @@ esphome/components/mipi_dsi/* @clydebarrow esphome/components/mipi_rgb/* @clydebarrow esphome/components/mipi_spi/* @clydebarrow esphome/components/mitsubishi/* @RubyBailey +esphome/components/mitsubishi_cn105/* @crnjan esphome/components/mixer/speaker/* @kahrendt esphome/components/mlx90393/* @functionpointer esphome/components/mlx90614/* @jesserockz diff --git a/esphome/components/mitsubishi_cn105/__init__.py b/esphome/components/mitsubishi_cn105/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/mitsubishi_cn105/climate.py b/esphome/components/mitsubishi_cn105/climate.py new file mode 100644 index 0000000000..5ea72d4cd2 --- /dev/null +++ b/esphome/components/mitsubishi_cn105/climate.py @@ -0,0 +1,41 @@ +import esphome.codegen as cg +from esphome.components import climate, uart +import esphome.config_validation as cv +from esphome.const import CONF_UPDATE_INTERVAL +from esphome.types import ConfigType + +DEPENDENCIES = ["uart"] +AUTO_LOAD = ["climate"] +CODEOWNERS = ["@crnjan"] + +mitsubishi_ns = cg.esphome_ns.namespace("mitsubishi_cn105") + +MitsubishiCN105Climate = mitsubishi_ns.class_( + "MitsubishiCN105Climate", + climate.Climate, + cg.Component, + uart.UARTDevice, +) + +CONFIG_SCHEMA = ( + climate.climate_schema(MitsubishiCN105Climate) + .extend(uart.UART_DEVICE_SCHEMA) + .extend({cv.Optional(CONF_UPDATE_INTERVAL, default="1s"): cv.update_interval}) +) + +FINAL_VALIDATE_SCHEMA = cv.All( + uart.final_validate_device_schema( + "mitsubishi_cn105", + require_rx=True, + require_tx=True, + data_bits=8, + parity="EVEN", + stop_bits=1, + ) +) + + +async def to_code(config: ConfigType) -> None: + var = await climate.new_climate(config) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp new file mode 100644 index 0000000000..35ab405b2d --- /dev/null +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp @@ -0,0 +1,7 @@ +#include "mitsubishi_cn105.h" + +namespace esphome::mitsubishi_cn105 { + +static const char *const TAG = "mitsubishi_cn105.driver"; + +} // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h new file mode 100644 index 0000000000..6018dddbff --- /dev/null +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h @@ -0,0 +1,19 @@ +#pragma once + +#include "esphome/components/uart/uart.h" + +namespace esphome::mitsubishi_cn105 { + +class MitsubishiCN105 { + public: + explicit MitsubishiCN105(uart::UARTDevice &device) : device_(device) {} + + uint32_t get_update_interval() const { return this->update_interval_ms_; } + void set_update_interval(uint32_t interval_ms) { this->update_interval_ms_ = interval_ms; } + + protected: + uart::UARTDevice &device_; + uint32_t update_interval_ms_{1000}; +}; + +} // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp new file mode 100644 index 0000000000..6d50296c8f --- /dev/null +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp @@ -0,0 +1,28 @@ +#include "mitsubishi_cn105_climate.h" +#include "esphome/core/log.h" + +namespace esphome::mitsubishi_cn105 { + +static const char *const TAG = "mitsubishi_cn105.climate"; + +void MitsubishiCN105Climate::dump_config() { + LOG_CLIMATE("", "Mitsubishi CN105 Climate", this); + ESP_LOGCONFIG(TAG, + " Update interval: %" PRIu32 " ms\n" + " UART: baud_rate=%" PRIu32 " data_bits=%u parity=%s stop_bits=%u", + this->hp_.get_update_interval(), this->parent_->get_baud_rate(), this->parent_->get_data_bits(), + LOG_STR_ARG(parity_to_str(this->parent_->get_parity())), this->parent_->get_stop_bits()); +} + +void MitsubishiCN105Climate::setup() {} + +void MitsubishiCN105Climate::loop() {} + +climate::ClimateTraits MitsubishiCN105Climate::traits() { + climate::ClimateTraits traits; + return traits; +} + +void MitsubishiCN105Climate::control(const climate::ClimateCall &call) {} + +} // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h new file mode 100644 index 0000000000..08b482025f --- /dev/null +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h @@ -0,0 +1,27 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/components/climate/climate.h" +#include "esphome/components/uart/uart.h" +#include "mitsubishi_cn105.h" + +namespace esphome::mitsubishi_cn105 { + +class MitsubishiCN105Climate : public climate::Climate, public Component, public uart::UARTDevice { + public: + explicit MitsubishiCN105Climate() : hp_(*this) {} + + void setup() override; + void loop() override; + void dump_config() override; + + climate::ClimateTraits traits() override; + void control(const climate::ClimateCall &call) override; + + void set_update_interval(uint32_t ms) { hp_.set_update_interval(ms); } + + protected: + MitsubishiCN105 hp_; +}; + +} // namespace esphome::mitsubishi_cn105 diff --git a/tests/components/mitsubishi_cn105/common.yaml b/tests/components/mitsubishi_cn105/common.yaml new file mode 100644 index 0000000000..e885ceef81 --- /dev/null +++ b/tests/components/mitsubishi_cn105/common.yaml @@ -0,0 +1,4 @@ +climate: + - platform: mitsubishi_cn105 + name: "AC Test" + uart_id: uart_bus diff --git a/tests/components/mitsubishi_cn105/test.esp32-idf.yaml b/tests/components/mitsubishi_cn105/test.esp32-idf.yaml new file mode 100644 index 0000000000..ac63cf987f --- /dev/null +++ b/tests/components/mitsubishi_cn105/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml b/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml new file mode 100644 index 0000000000..9f2f350b46 --- /dev/null +++ b/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_9600_even/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml b/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml new file mode 100644 index 0000000000..4363d6eee8 --- /dev/null +++ b/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_9600_even/rp2040-ard.yaml + +<<: !include common.yaml From b5c4449a161c2fc83b4e7b5150b50dcc6ef1ea71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Apr 2026 14:11:44 -1000 Subject: [PATCH 1873/2030] Bump pillow from 12.1.1 to 12.2.0 (#15361) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8ad5528c95..dd20600097 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import ruamel.yaml.clib==0.2.15 # dashboard_import esphome-glyphsets==0.2.0 -pillow==12.1.1 +pillow==12.2.0 resvg-py==0.2.6 freetype-py==2.5.1 jinja2==3.1.6 From eefbb42be477d1ed2e80c251859a4588df61c47b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Thu, 2 Apr 2026 11:16:56 +1000 Subject: [PATCH 1874/2030] [lvgl] Add missing event names (#15362) --- esphome/components/lvgl/defines.py | 75 +++++++++++++--- tests/components/lvgl/lvgl-package.yaml | 108 ++++++++++++++++++++++++ 2 files changed, 172 insertions(+), 11 deletions(-) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index dd51a2f519..500ccb608a 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -251,22 +251,75 @@ LV_FONTS = list(f"montserrat_{s}" for s in range(8, 50, 2)) + [ ] LV_EVENT_MAP = { - "PRESS": "PRESSED", - "SHORT_CLICK": "SHORT_CLICKED", + "ALL_EVENTS": "ALL", + "CANCEL": "CANCEL", + "CHANGE": "VALUE_CHANGED", + "CHILD_CHANGE": "CHILD_CHANGED", + "CHILD_CREATE": "CHILD_CREATED", + "CHILD_DELETE": "CHILD_DELETED", + "CLICK": "CLICKED", + "COLOR_FORMAT_CHANGE": "COLOR_FORMAT_CHANGED", + "COVER_CHECK": "COVER_CHECK", + "CREATE": "CREATE", + "DEFOCUS": "DEFOCUSED", + "DELETE": "DELETE", + "DOUBLE_CLICK": "DOUBLE_CLICKED", + "DRAW_MAIN": "DRAW_MAIN", + "DRAW_MAIN_BEGIN": "DRAW_MAIN_BEGIN", + "DRAW_MAIN_END": "DRAW_MAIN_END", + "DRAW_POST": "DRAW_POST", + "DRAW_POST_BEGIN": "DRAW_POST_BEGIN", + "DRAW_POST_END": "DRAW_POST_END", + "DRAW_TASK_ADD": "DRAW_TASK_ADDED", + "FLUSH_FINISH": "FLUSH_FINISH", + "FLUSH_START": "FLUSH_START", + "FLUSH_WAIT_FINISH": "FLUSH_WAIT_FINISH", + "FLUSH_WAIT_START": "FLUSH_WAIT_START", + "FOCUS": "FOCUSED", + "GESTURE": "GESTURE", + "GET_SELF_SIZE": "GET_SELF_SIZE", + "HIT_TEST": "HIT_TEST", + "HOVER_LEAVE": "HOVER_LEAVE", + "HOVER_OVER": "HOVER_OVER", + "INDEV_RESET": "INDEV_RESET", + "INSERT": "INSERT", + "INVALIDATE_AREA": "INVALIDATE_AREA", + "KEY": "KEY", + "LAYOUT_CHANGE": "LAYOUT_CHANGED", + "LEAVE": "LEAVE", "LONG_PRESS": "LONG_PRESSED", "LONG_PRESS_REPEAT": "LONG_PRESSED_REPEAT", - "CLICK": "CLICKED", + "PRESS": "PRESSED", + "PRESS_LOST": "PRESS_LOST", + "PRESSING": "PRESSING", + "READY": "READY", + "REFRESH": "REFRESH", + "REFR_EXT_DRAW_SIZE": "REFR_EXT_DRAW_SIZE", + "REFR_READY": "REFR_READY", + "REFR_REQUEST": "REFR_REQUEST", + "REFR_START": "REFR_START", "RELEASE": "RELEASED", + "RENDER_READY": "RENDER_READY", + "RENDER_START": "RENDER_START", + "RESOLUTION_CHANGE": "RESOLUTION_CHANGED", + "ROTARY": "ROTARY", + "SCREEN_LOAD": "SCREEN_LOADED", + "SCREEN_LOAD_START": "SCREEN_LOAD_START", + "SCREEN_UNLOAD": "SCREEN_UNLOADED", + "SCREEN_UNLOAD_START": "SCREEN_UNLOAD_START", + "SCROLL": "SCROLL", "SCROLL_BEGIN": "SCROLL_BEGIN", "SCROLL_END": "SCROLL_END", - "SCROLL": "SCROLL", - "FOCUS": "FOCUSED", - "DEFOCUS": "DEFOCUSED", - "READY": "READY", - "CANCEL": "CANCEL", - "ALL_EVENTS": "ALL", - "CHANGE": "VALUE_CHANGED", - "GESTURE": "GESTURE", + "SCROLL_THROW_BEGIN": "SCROLL_THROW_BEGIN", + "SHORT_CLICK": "SHORT_CLICKED", + "SINGLE_CLICK": "SINGLE_CLICKED", + "SIZE_CHANGE": "SIZE_CHANGED", + "STATE_CHANGE": "STATE_CHANGED", + "STYLE_CHANGE": "STYLE_CHANGED", + "TRIPLE_CLICK": "TRIPLE_CLICKED", + "UPDATE_LAYOUT_COMPLETE": "UPDATE_LAYOUT_COMPLETED", + "VSYNC": "VSYNC", + "VSYNC_REQUEST": "VSYNC_REQUEST", } LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index abc66ef587..3a6af93b64 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -590,6 +590,114 @@ lvgl: logger.log: Button clicked on_long_press_repeat: logger.log: Button clicked + on_pressing: + logger.log: Button pressing + on_press_lost: + logger.log: Button press lost + on_single_click: + logger.log: Button single clicked + on_double_click: + logger.log: Button double clicked + on_triple_click: + logger.log: Button triple clicked + on_scroll_throw_begin: + logger.log: Scroll throw begin + on_gesture: + logger.log: Gesture detected + on_key: + logger.log: Key event + on_rotary: + logger.log: Rotary event + on_leave: + logger.log: Leave event + on_hit_test: + logger.log: Hit test + on_indev_reset: + logger.log: Indev reset + on_hover_over: + logger.log: Hover over + on_hover_leave: + logger.log: Hover leave + on_cover_check: + logger.log: Cover check + on_refr_ext_draw_size: + logger.log: Refr ext draw size + on_draw_main_begin: + logger.log: Draw main begin + on_draw_main: + logger.log: Draw main + on_draw_main_end: + logger.log: Draw main end + on_draw_post_begin: + logger.log: Draw post begin + on_draw_post: + logger.log: Draw post + on_draw_post_end: + logger.log: Draw post end + on_draw_task_add: + logger.log: Draw task add + on_insert: + logger.log: Insert event + on_refresh: + logger.log: Refresh event + on_state_change: + logger.log: State changed + on_create: + logger.log: Create event + on_delete: + logger.log: Delete event + on_child_change: + logger.log: Child changed + on_child_create: + logger.log: Child created + on_child_delete: + logger.log: Child deleted + on_screen_unload_start: + logger.log: Screen unload start + on_screen_load_start: + logger.log: Screen load start + on_screen_load: + logger.log: Screen loaded + on_screen_unload: + logger.log: Screen unloaded + on_size_change: + logger.log: Size changed + on_style_change: + logger.log: Style changed + on_layout_change: + logger.log: Layout changed + on_get_self_size: + logger.log: Get self size + on_invalidate_area: + logger.log: Invalidate area + on_resolution_change: + logger.log: Resolution changed + on_color_format_change: + logger.log: Color format changed + on_refr_request: + logger.log: Refresh request + on_refr_start: + logger.log: Refresh start + on_refr_ready: + logger.log: Refresh ready + on_render_start: + logger.log: Render start + on_render_ready: + logger.log: Render ready + on_flush_start: + logger.log: Flush start + on_flush_finish: + logger.log: Flush finish + on_flush_wait_start: + logger.log: Flush wait start + on_flush_wait_finish: + logger.log: Flush wait finish + on_update_layout_complete: + logger.log: Update layout complete + on_vsync: + logger.log: Vsync + on_vsync_request: + logger.log: Vsync request - led: id: lv_led color: 0x00FF00 From 27c662e73faf6583179084d6a179816751d8d170 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 16:11:50 -1000 Subject: [PATCH 1875/2030] [bluetooth_proxy] Replace loop() with set_interval for advertisement flushing (#15347) --- .../bluetooth_proxy/bluetooth_proxy.cpp | 48 ++++++------------- .../bluetooth_proxy/bluetooth_proxy.h | 17 +++++-- 2 files changed, 27 insertions(+), 38 deletions(-) diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp index 87206996b2..c69163b1f7 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.cpp @@ -30,6 +30,19 @@ void BluetoothProxy::setup() { this->configured_scan_active_ = this->parent_->get_scan_active(); this->parent_->add_scanner_state_listener(this); + + this->set_interval(100, [this]() { + if (api::global_api_server->is_connected() && this->api_connection_ != nullptr) { + this->flush_pending_advertisements_(); + return; + } + for (uint8_t i = 0; i < this->connection_count_; i++) { + auto *connection = this->connections_[i]; + if (connection->get_address() != 0 && !connection->disconnect_pending()) { + connection->disconnect(); + } + } + }); } void BluetoothProxy::on_scanner_state(esp32_ble_tracker::ScannerState state) { @@ -101,25 +114,15 @@ bool BluetoothProxy::parse_devices(const esp32_ble::BLEScanResult *scan_results, // Flush if we have reached BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE if (this->response_.advertisements_len >= BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE) { - this->flush_pending_advertisements(); + this->flush_pending_advertisements_(); } } return true; } -void BluetoothProxy::flush_pending_advertisements() { - if (this->response_.advertisements_len == 0 || !api::global_api_server->is_connected() || - this->api_connection_ == nullptr) - return; - - // Send the message - this->api_connection_->send_message(this->response_); - +void BluetoothProxy::log_advertisement_flush_() { ESP_LOGV(TAG, "Sent batch of %u BLE advertisements", this->response_.advertisements_len); - - // Reset the length for the next batch - this->response_.advertisements_len = 0; } void BluetoothProxy::dump_config() { @@ -130,27 +133,6 @@ void BluetoothProxy::dump_config() { YESNO(this->active_), this->connection_count_); } -void BluetoothProxy::loop() { - if (!api::global_api_server->is_connected() || this->api_connection_ == nullptr) { - for (uint8_t i = 0; i < this->connection_count_; i++) { - auto *connection = this->connections_[i]; - if (connection->get_address() != 0 && !connection->disconnect_pending()) { - connection->disconnect(); - } - } - return; - } - - // Flush any pending BLE advertisements that have been accumulated but not yet sent - uint32_t now = App.get_loop_component_start_time(); - - // Flush accumulated advertisements every 100ms - if (now - this->last_advertisement_flush_time_ >= 100) { - this->flush_pending_advertisements(); - this->last_advertisement_flush_time_ = now; - } -} - esp32_ble_tracker::AdvertisementParserType BluetoothProxy::get_advertisement_parser_type() { return esp32_ble_tracker::AdvertisementParserType::RAW_ADVERTISEMENTS; } diff --git a/esphome/components/bluetooth_proxy/bluetooth_proxy.h b/esphome/components/bluetooth_proxy/bluetooth_proxy.h index f1b723e719..6680ab0e84 100644 --- a/esphome/components/bluetooth_proxy/bluetooth_proxy.h +++ b/esphome/components/bluetooth_proxy/bluetooth_proxy.h @@ -65,8 +65,6 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, bool parse_devices(const esp32_ble::BLEScanResult *scan_results, size_t count) override; void dump_config() override; void setup() override; - void loop() override; - void flush_pending_advertisements(); esp32_ble_tracker::AdvertisementParserType get_advertisement_parser_type() override; void register_connection(BluetoothConnection *connection) { @@ -150,6 +148,18 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, protected: void send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerState state); + /// Caller must ensure api_connection_ is non-null and API server is connected. + void flush_pending_advertisements_() { + if (this->response_.advertisements_len == 0) + return; + this->api_connection_->send_message(this->response_); +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE + this->log_advertisement_flush_(); +#endif + this->response_.advertisements_len = 0; + } + void log_advertisement_flush_(); + BluetoothConnection *get_connection_(uint64_t address, bool reserve); void log_connection_request_ignored_(BluetoothConnection *connection, espbt::ClientState state); void log_connection_info_(BluetoothConnection *connection, const char *message); @@ -166,9 +176,6 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener, // BLE advertisement batching api::BluetoothLERawAdvertisementsResponse response_; - // Group 3: 4-byte types - uint32_t last_advertisement_flush_time_{0}; - // Pre-allocated response message - always ready to send api::BluetoothConnectionsFreeResponse connections_free_response_; From bcc7b8f490cae830be31bb3e891c5a39a43fac37 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 16:12:02 -1000 Subject: [PATCH 1876/2030] [api] Add send_sensor_state benchmarks (#15352) --- esphome/components/api/api_connection.h | 12 ++ .../benchmarks/components/api/bench_helpers.h | 67 ++++++ .../components/api/bench_plaintext_frame.cpp | 58 +----- .../api/bench_send_sensor_state.cpp | 191 ++++++++++++++++++ 4 files changed, 272 insertions(+), 56 deletions(-) create mode 100644 tests/benchmarks/components/api/bench_helpers.h create mode 100644 tests/benchmarks/components/api/bench_send_sensor_state.cpp diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 3d8563b1ae..4ce1335650 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -44,10 +44,22 @@ static constexpr size_t MAX_INITIAL_PER_BATCH = 34; // For clients >= AP static_assert(MAX_MESSAGES_PER_BATCH >= MAX_INITIAL_PER_BATCH, "MAX_MESSAGES_PER_BATCH must be >= MAX_INITIAL_PER_BATCH"); +#ifdef USE_BENCHMARK +class APIConnection; +void bench_enable_immediate_send(APIConnection *conn); +void bench_clear_batch(APIConnection *conn); +void bench_process_batch(APIConnection *conn); +#endif + class APIConnection final : public APIServerConnectionBase { public: friend class APIServer; friend class ListEntitiesIterator; +#ifdef USE_BENCHMARK + friend void bench_enable_immediate_send(APIConnection *conn); + friend void bench_clear_batch(APIConnection *conn); + friend void bench_process_batch(APIConnection *conn); +#endif APIConnection(std::unique_ptr<socket::Socket> socket, APIServer *parent); ~APIConnection(); diff --git a/tests/benchmarks/components/api/bench_helpers.h b/tests/benchmarks/components/api/bench_helpers.h new file mode 100644 index 0000000000..73e51bce3d --- /dev/null +++ b/tests/benchmarks/components/api/bench_helpers.h @@ -0,0 +1,67 @@ +#pragma once + +#include <fcntl.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <sys/socket.h> +#include <unistd.h> + +#include <memory> +#include <utility> + +#include "esphome/components/socket/socket.h" + +namespace esphome::api::benchmarks { + +// Helper to drain accumulated data from the read side of a socket +// to prevent the write side from blocking. +inline void drain_socket(int fd) { + char buf[65536]; + while (::read(fd, buf, sizeof(buf)) > 0) { + } +} + +// Create a TCP loopback socket pair. Returns the write-side Socket +// (wrapped for ESPHome) and the raw read-side fd for draining. +// Both ends are non-blocking with 16MB buffers. +inline std::pair<std::unique_ptr<socket::Socket>, int> create_tcp_loopback() { + // Create a TCP listener on loopback + int listen_fd = ::socket(AF_INET, SOCK_STREAM, 0); + int opt = 1; + ::setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + struct sockaddr_in addr {}; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + addr.sin_port = 0; // OS-assigned port + ::bind(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); + ::listen(listen_fd, 1); + + // Get the assigned port + socklen_t addr_len = sizeof(addr); + ::getsockname(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), &addr_len); + + // Connect from client side + int write_fd = ::socket(AF_INET, SOCK_STREAM, 0); + ::connect(write_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); + + // Accept on server side (this is our read fd) + int read_fd = ::accept(listen_fd, nullptr, nullptr); + ::close(listen_fd); + + // Make both ends non-blocking + int flags = ::fcntl(write_fd, F_GETFL, 0); + ::fcntl(write_fd, F_SETFL, flags | O_NONBLOCK); + flags = ::fcntl(read_fd, F_GETFL, 0); + ::fcntl(read_fd, F_SETFL, flags | O_NONBLOCK); + + // Use large socket buffers so benchmarks never hit WOULD_BLOCK + // during a single outer iteration (2000 × ~15B messages = ~30KB). + int bufsize = 16 * 1024 * 1024; + ::setsockopt(write_fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); + ::setsockopt(read_fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); + + return {std::make_unique<socket::Socket>(write_fd), read_fd}; +} + +} // namespace esphome::api::benchmarks diff --git a/tests/benchmarks/components/api/bench_plaintext_frame.cpp b/tests/benchmarks/components/api/bench_plaintext_frame.cpp index 79bffaf953..0caa50c748 100644 --- a/tests/benchmarks/components/api/bench_plaintext_frame.cpp +++ b/tests/benchmarks/components/api/bench_plaintext_frame.cpp @@ -2,12 +2,9 @@ #ifdef USE_API_PLAINTEXT #include <benchmark/benchmark.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <sys/socket.h> #include <unistd.h> +#include "bench_helpers.h" #include "esphome/components/api/api_frame_helper_plaintext.h" #include "esphome/components/api/api_pb2.h" #include "esphome/components/api/api_buffer.h" @@ -16,57 +13,12 @@ namespace esphome::api::benchmarks { static constexpr int kInnerIterations = 2000; -// Helper to drain accumulated data from the read side of a socket -// to prevent the write side from blocking. -static void drain_socket(int fd) { - char buf[65536]; - while (::read(fd, buf, sizeof(buf)) > 0) { - } -} - // Helper to create a TCP loopback connection with an APIPlaintextFrameHelper // on the write end. Returns the helper and the read-side fd. -// Uses real TCP sockets so TCP_NODELAY succeeds during init(). static std::pair<std::unique_ptr<APIPlaintextFrameHelper>, int> create_plaintext_helper() { - // Create a TCP listener on loopback - int listen_fd = ::socket(AF_INET, SOCK_STREAM, 0); - int opt = 1; - ::setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - - struct sockaddr_in addr {}; - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = 0; // OS-assigned port - ::bind(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); - ::listen(listen_fd, 1); - - // Get the assigned port - socklen_t addr_len = sizeof(addr); - ::getsockname(listen_fd, reinterpret_cast<struct sockaddr *>(&addr), &addr_len); - - // Connect from client side - int write_fd = ::socket(AF_INET, SOCK_STREAM, 0); - ::connect(write_fd, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)); - - // Accept on server side (this is our read fd) - int read_fd = ::accept(listen_fd, nullptr, nullptr); - ::close(listen_fd); - - // Make both ends non-blocking - int flags = ::fcntl(write_fd, F_GETFL, 0); - ::fcntl(write_fd, F_SETFL, flags | O_NONBLOCK); - flags = ::fcntl(read_fd, F_GETFL, 0); - ::fcntl(read_fd, F_SETFL, flags | O_NONBLOCK); - - // Increase socket buffer sizes to reduce drain frequency - int bufsize = 1024 * 1024; - ::setsockopt(write_fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)); - ::setsockopt(read_fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)); - - auto sock = std::make_unique<socket::Socket>(write_fd); + auto [sock, read_fd] = create_tcp_loopback(); auto helper = std::make_unique<APIPlaintextFrameHelper>(std::move(sock)); helper->init(); - return {std::move(helper), read_fd}; } @@ -97,9 +49,6 @@ static void PlaintextFrame_WriteSensorState(benchmark::State &state) { msg.encode(writer); helper->write_protobuf_packet(SensorStateResponse::MESSAGE_TYPE, writer); - - if ((i & 0xFF) == 0) - drain_socket(read_fd); } drain_socket(read_fd); benchmark::DoNotOptimize(helper.get()); @@ -144,9 +93,6 @@ static void PlaintextFrame_WriteBatch5(benchmark::State &state) { } helper->write_protobuf_messages(ProtoWriteBuffer(&buffer, 0), std::span<const MessageInfo>(messages, 5)); - - if ((i & 0xFF) == 0) - drain_socket(read_fd); } drain_socket(read_fd); benchmark::DoNotOptimize(helper.get()); diff --git a/tests/benchmarks/components/api/bench_send_sensor_state.cpp b/tests/benchmarks/components/api/bench_send_sensor_state.cpp new file mode 100644 index 0000000000..815081374a --- /dev/null +++ b/tests/benchmarks/components/api/bench_send_sensor_state.cpp @@ -0,0 +1,191 @@ +#include "esphome/core/defines.h" +#if defined(USE_API_PLAINTEXT) && defined(USE_SENSOR) + +#include <benchmark/benchmark.h> +#include <unistd.h> + +#include "bench_helpers.h" +#include "esphome/components/api/api_connection.h" +#include "esphome/components/api/api_server.h" +#include "esphome/components/sensor/sensor.h" + +namespace esphome::api { + +// Friend functions declared in APIConnection for benchmark access. +void bench_enable_immediate_send(APIConnection *conn) { conn->flags_.should_try_send_immediately = true; } +void bench_clear_batch(APIConnection *conn) { conn->clear_batch_(); } +void bench_process_batch(APIConnection *conn) { conn->process_batch_(); } + +} // namespace esphome::api + +namespace esphome::api::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Helper to create a TCP loopback connection with an APIConnection. +// Returns the connection and the read-side fd for draining. +static std::pair<std::unique_ptr<APIConnection>, int> create_api_connection() { + auto [sock, read_fd] = create_tcp_loopback(); + auto conn = std::make_unique<APIConnection>(std::move(sock), global_api_server); + conn->start(); + return {std::move(conn), read_fd}; +} + +// Test subclass to access protected configure_entity_() for benchmark setup. +class TestSensor : public sensor::Sensor { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } +}; + +// --- send_sensor_state: immediate send path --- +// Measures: send_message_smart_ → prepare buffer → dispatch_message_ → +// try_send_sensor_state → fill key/device_id + proto encode → frame write → +// TCP send. This is the per-client cost when batch_delay=0 and initial states +// have been sent. + +static void SendSensorState_Immediate(benchmark::State &state) { + auto [conn, read_fd] = create_api_connection(); + bench_enable_immediate_send(conn.get()); + // batch_delay must be 0 for should_send_immediately_ to return true + uint16_t saved_delay = global_api_server->get_batch_delay(); + global_api_server->set_batch_delay(0); + + TestSensor sensor; + sensor.configure("test_sensor"); + sensor.publish_state(23.5f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + conn->send_sensor_state(&sensor); + } + drain_socket(read_fd); + benchmark::DoNotOptimize(conn.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + global_api_server->set_batch_delay(saved_delay); + ::close(read_fd); +} +BENCHMARK(SendSensorState_Immediate); + +// --- send_sensor_state: batch path (cold — first call allocates) --- +// Measures: send_message_smart_ → schedule_message_ → deferred batch add. +// Includes one-time vector allocation cost. + +static void SendSensorState_Batch_Cold(benchmark::State &state) { + auto [conn, read_fd] = create_api_connection(); + + TestSensor sensor; + sensor.configure("test_sensor"); + sensor.publish_state(23.5f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + conn->send_sensor_state(&sensor); + } + benchmark::DoNotOptimize(conn.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(SendSensorState_Batch_Cold); + +// --- send_sensor_state: batch path (warm — buffer already allocated) --- +// Measures steady-state batch cost after the vector has been allocated +// and cleared at least once. This is the typical path during normal +// operation after the first batch has been processed. + +static void SendSensorState_Batch_Warm(benchmark::State &state) { + auto [conn, read_fd] = create_api_connection(); + + TestSensor sensor; + sensor.configure("test_sensor"); + sensor.publish_state(23.5f); + + // Warm up: send once to allocate, then clear to keep capacity + conn->send_sensor_state(&sensor); + bench_clear_batch(conn.get()); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + conn->send_sensor_state(&sensor); + } + benchmark::DoNotOptimize(conn.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(SendSensorState_Batch_Warm); + +// --- process_batch_: single sensor state (encode + frame + write) --- +// Measures the deferred batch processing path: dispatch_message_ → +// try_send_sensor_state → fill + proto encode → send_buffer → frame write. +// This is the cost paid on the next loop() after batching. + +static void ProcessBatch_SingleSensor(benchmark::State &state) { + auto [conn, read_fd] = create_api_connection(); + + TestSensor sensor; + sensor.configure("test_sensor"); + sensor.publish_state(23.5f); + + // Warm up batch vector + conn->send_sensor_state(&sensor); + bench_process_batch(conn.get()); + drain_socket(read_fd); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + conn->send_sensor_state(&sensor); + bench_process_batch(conn.get()); + } + drain_socket(read_fd); + benchmark::DoNotOptimize(conn.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(ProcessBatch_SingleSensor); + +// --- process_batch_: 5 different sensors --- +// Measures batch processing with multiple items queued. +// This exercises the multi-message path in process_batch_. + +static void ProcessBatch_5Sensors(benchmark::State &state) { + auto [conn, read_fd] = create_api_connection(); + + TestSensor sensors[5]; + for (int i = 0; i < 5; i++) { + char name[20]; + snprintf(name, sizeof(name), "sensor_%d", i); + sensors[i].configure(name); + sensors[i].publish_state(23.5f + static_cast<float>(i)); + } + + // Warm up batch vector + for (auto &s : sensors) + conn->send_sensor_state(&s); + bench_process_batch(conn.get()); + drain_socket(read_fd); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + for (auto &s : sensors) + conn->send_sensor_state(&s); + bench_process_batch(conn.get()); + } + drain_socket(read_fd); + benchmark::DoNotOptimize(conn.get()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); + + ::close(read_fd); +} +BENCHMARK(ProcessBatch_5Sensors); + +} // namespace esphome::api::benchmarks + +#endif // USE_API_PLAINTEXT && USE_SENSOR From be56be5201f23d41e060f3cee458607f0bf97729 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 16:14:45 -1000 Subject: [PATCH 1877/2030] [core] Reduce runtime_stats measurement overhead (#15359) --- esphome/core/component.cpp | 7 ------- esphome/core/component.h | 9 ++++----- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 955596ce95..288c3f01a3 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -519,13 +519,6 @@ WarnIfComponentBlockingGuard::warn_blocking(Component *component, uint32_t block } } -#ifdef USE_RUNTIME_STATS -void WarnIfComponentBlockingGuard::record_runtime_stats_() { - uint32_t duration_us = micros() - this->started_us_; - this->component_->runtime_stats_.record_time(duration_us); -} -#endif - #ifdef USE_SETUP_PRIORITY_OVERRIDE void clear_setup_priority_overrides() { // Free the setup priority map completely diff --git a/esphome/core/component.h b/esphome/core/component.h index c5a331ee29..d09b42b936 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -630,17 +630,17 @@ class WarnIfComponentBlockingGuard { { } - // Finish the timing operation and return the current time + // Finish the timing operation and return the current time (millis) // Inlined: the fast path is just millis() + subtract + compare inline uint32_t HOT finish() { - uint32_t curr_time = millis(); - uint32_t blocking_time = curr_time - this->started_; #ifdef USE_RUNTIME_STATS - this->record_runtime_stats_(); + this->component_->runtime_stats_.record_time(micros() - this->started_us_); #endif + uint32_t curr_time = millis(); #ifndef USE_BENCHMARK // Fast path: compare against constant threshold in ms (computed at compile time from centiseconds) static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast<uint32_t>(WARN_IF_BLOCKING_OVER_CS) * 10U; + uint32_t blocking_time = curr_time - this->started_; if (blocking_time > WARN_IF_BLOCKING_OVER_MS) [[unlikely]] { warn_blocking(this->component_, blocking_time); } @@ -655,7 +655,6 @@ class WarnIfComponentBlockingGuard { Component *component_; #ifdef USE_RUNTIME_STATS uint32_t started_us_; - void record_runtime_stats_(); #endif private: From f36d78e09c866136111c260d03c99820ff71fcee Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 16:15:00 -1000 Subject: [PATCH 1878/2030] [core] Force inline Component::get_component_log_str() (#15363) --- esphome/core/component.cpp | 3 --- esphome/core/component.h | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 288c3f01a3..2b5aba2a7b 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -267,9 +267,6 @@ void Component::call() { break; } } -const LogString *Component::get_component_log_str() const { - return component_source_lookup(this->component_source_index_); -} bool Component::should_warn_of_blocking(uint32_t blocking_time) { // Convert centisecond threshold to milliseconds for comparison uint32_t threshold_ms = static_cast<uint32_t>(this->warn_if_blocking_over_) * 10U; diff --git a/esphome/core/component.h b/esphome/core/component.h index d09b42b936..f091f9434c 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -323,7 +323,9 @@ class Component { * * Returns LOG_STR("<unknown>") if source not set */ - const LogString *get_component_log_str() const; + inline const LogString *get_component_log_str() const ESPHOME_ALWAYS_INLINE { + return component_source_lookup(this->component_source_index_); + } bool should_warn_of_blocking(uint32_t blocking_time); From 08c7b3afbdf332ff65e1648047ba3ff90f7e2d2b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 16:53:53 -1000 Subject: [PATCH 1879/2030] [esp32_ble_tracker] Reduce scan cycle log spam (#15365) --- esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp index f2d60be641..c7f2319d69 100644 --- a/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp +++ b/esphome/components/esp32_ble_tracker/esp32_ble_tracker.cpp @@ -249,7 +249,7 @@ void ESP32BLETracker::start_scan_(bool first) { return; } this->set_scanner_state_(ScannerState::STARTING); - ESP_LOGD(TAG, "Starting scan, set scanner state to STARTING."); + ESP_LOGV(TAG, "Starting scan, set scanner state to STARTING."); if (!first) { #ifdef ESPHOME_ESP32_BLE_TRACKER_LISTENER_COUNT for (auto *listener : this->listeners_) @@ -855,7 +855,7 @@ void ESP32BLETracker::process_scan_result_(const BLEScanResult &scan_result) { } void ESP32BLETracker::cleanup_scan_state_(bool is_stop_complete) { - ESP_LOGD(TAG, "Scan %scomplete, set scanner state to IDLE.", is_stop_complete ? "stop " : ""); + ESP_LOGV(TAG, "Scan %scomplete, set scanner state to IDLE.", is_stop_complete ? "stop " : ""); #ifdef USE_ESP32_BLE_DEVICE this->already_discovered_.clear(); #endif From 1436d034bf699531d81b2545804ebb996288d15f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 17:11:47 -1000 Subject: [PATCH 1880/2030] [api] Inline DeferredBatch::add_item to eliminate push_back call barrier (#15353) --- esphome/components/api/api_connection.cpp | 36 ++--------------------- esphome/components/api/api_connection.h | 33 +++++++++++++++------ 2 files changed, 27 insertions(+), 42 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 79df85ada3..aa64ced64c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -132,8 +132,6 @@ APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *pa #endif } -uint32_t APIConnection::get_batch_delay_ms_() const { return this->parent_->get_batch_delay(); } - void APIConnection::start() { this->last_traffic_ = App.get_loop_component_start_time(); @@ -2072,37 +2070,9 @@ void APIConnection::on_fatal_error() { this->flags_.remove = true; } -void __attribute__((flatten)) APIConnection::DeferredBatch::push_item(const BatchItem &item) { items.push_back(item); } - -void APIConnection::DeferredBatch::add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, - uint8_t aux_data_index) { - // Check if we already have a message of this type for this entity - // This provides deduplication per entity/message_type combination - // O(n) but optimized for RAM and not performance. - // Skip deduplication for events - they are edge-triggered, every occurrence matters -#ifdef USE_EVENT - if (message_type != EventResponse::MESSAGE_TYPE) -#endif - { - for (const auto &item : items) { - if (item.entity == entity && item.message_type == message_type) - return; // Already queued - } - } - // No existing item found (or event), add new one - this->push_item({entity, message_type, estimated_size, aux_data_index}); -} - -void APIConnection::DeferredBatch::add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { - // Add high priority message and swap to front - // This avoids expensive vector::insert which shifts all elements - // Note: We only ever have one high-priority message at a time (ping OR disconnect) - // If we're disconnecting, pings are blocked, so this simple swap is sufficient - this->push_item({entity, message_type, estimated_size, AUX_DATA_UNUSED}); - if (items.size() > 1) { - // Swap the new high-priority item to the front - std::swap(items.front(), items.back()); - } +bool APIConnection::schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { + this->deferred_batch_.add_item_front(entity, message_type, estimated_size); + return this->schedule_batch_(); } bool APIConnection::send_message_smart_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 4ce1335650..13d5273ecb 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -644,11 +644,28 @@ class APIConnection final : public APIServerConnectionBase { // Add item to the batch (with deduplication) void add_item(EntityBase *entity, uint8_t message_type, uint8_t estimated_size, - uint8_t aux_data_index = AUX_DATA_UNUSED); + uint8_t aux_data_index = AUX_DATA_UNUSED) { + // Dedup: O(n) scan but optimized for RAM over performance + // Skip deduplication for events - they are edge-triggered, every occurrence matters +#ifdef USE_EVENT + if (message_type != EventResponse::MESSAGE_TYPE) +#endif + { + for (const auto &item : this->items) { + if (item.entity == entity && item.message_type == message_type) + return; // Already queued + } + } + this->items.push_back({entity, message_type, estimated_size, aux_data_index}); + } // Add item to the front of the batch (for high priority messages like ping) - void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size); - // Single push_back site to avoid duplicate _M_realloc_insert instantiation - void push_item(const BatchItem &item); + void add_item_front(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { + // Swap to front avoids expensive vector::insert which shifts all elements + this->items.push_back({entity, message_type, estimated_size, AUX_DATA_UNUSED}); + if (this->items.size() > 1) { + std::swap(this->items.front(), this->items.back()); + } + } // Clear all items void clear() { @@ -713,7 +730,7 @@ class APIConnection final : public APIServerConnectionBase { ActiveIterator active_iterator_{ActiveIterator::NONE}; // Total: 2 (flags) + 2 + 2 + 1 = 7 bytes, then 1 byte padding to next 4-byte boundary - uint32_t get_batch_delay_ms_() const; + uint32_t get_batch_delay_ms_() const { return this->parent_->get_batch_delay(); } // Message will use 8 more bytes than the minimum size, and typical // MTU is 1500. Sometimes users will see as low as 1460 MTU. // If its IPv6 the header is 40 bytes, and if its IPv4 @@ -780,10 +797,8 @@ class APIConnection final : public APIServerConnectionBase { } // Helper function to schedule a high priority message at the front of the batch - bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size) { - this->deferred_batch_.add_item_front(entity, message_type, estimated_size); - return this->schedule_batch_(); - } + // Out-of-line: callers (on_shutdown, check_keepalive_) are cold paths + bool schedule_message_front_(EntityBase *entity, uint8_t message_type, uint8_t estimated_size); // Helper function to log client messages with name and peername void log_client_(int level, const LogString *message); From 3fbf0f0c019da645c9e68cb217789711e58aa6c9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Wed, 1 Apr 2026 17:13:09 -1000 Subject: [PATCH 1881/2030] [api] Simplify encode_to_buffer to single resize call (#15355) --- esphome/components/api/api_connection.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index aa64ced64c..0f456ecd0c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -2021,24 +2021,23 @@ uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncode auto &shared_buf = conn->parent_->get_shared_buffer_ref(); + size_t to_add; if (conn->flags_.batch_first_message) { // First message - buffer already prepared by caller, just clear flag conn->flags_.batch_first_message = false; + to_add = calculated_size; } else { // Batch message second or later - // Add padding for previous message footer + this message header - size_t current_size = shared_buf.size(); - shared_buf.reserve_and_resize(current_size + total_calculated_size, current_size + footer_size + header_padding); + // Reserve for full message, resize to include footer gap + header padding + payload + to_add = total_calculated_size; } - // Pre-resize buffer to include payload, then encode through raw pointer - size_t write_start = shared_buf.size(); - shared_buf.resize(write_start + calculated_size); - ProtoWriteBuffer buffer{&shared_buf, write_start}; + shared_buf.resize(shared_buf.size() + to_add); + ProtoWriteBuffer buffer{&shared_buf, shared_buf.size() - calculated_size}; encode_fn(msg, buffer); // Return total size (header + payload + footer) - return static_cast<uint16_t>(header_padding + calculated_size + footer_size); + return static_cast<uint16_t>(total_calculated_size); } bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) { const bool is_log_message = (message_type == SubscribeLogsResponse::MESSAGE_TYPE); From 34295fbd6985cdea1017ee188439c3fa66e59a59 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 2 Apr 2026 12:25:54 +0200 Subject: [PATCH 1882/2030] [nextion] Collapse nested namespace to esphome::nextion (#15367) --- esphome/components/nextion/automation.h | 6 ++---- .../nextion/binary_sensor/nextion_binarysensor.cpp | 6 ++---- .../nextion/binary_sensor/nextion_binarysensor.h | 7 +++---- esphome/components/nextion/nextion.cpp | 6 ++---- esphome/components/nextion/nextion.h | 6 ++---- esphome/components/nextion/nextion_base.h | 7 +++---- esphome/components/nextion/nextion_commands.cpp | 7 +++---- esphome/components/nextion/nextion_component.cpp | 6 ++---- esphome/components/nextion/nextion_component.h | 7 +++---- esphome/components/nextion/nextion_component_base.h | 6 ++---- esphome/components/nextion/nextion_upload.cpp | 7 +++---- esphome/components/nextion/nextion_upload_arduino.cpp | 7 +++---- esphome/components/nextion/nextion_upload_esp32.cpp | 7 +++---- esphome/components/nextion/sensor/nextion_sensor.cpp | 6 ++---- esphome/components/nextion/sensor/nextion_sensor.h | 7 +++---- esphome/components/nextion/switch/nextion_switch.cpp | 6 ++---- esphome/components/nextion/switch/nextion_switch.h | 7 +++---- .../components/nextion/text_sensor/nextion_textsensor.cpp | 7 +++---- .../components/nextion/text_sensor/nextion_textsensor.h | 7 +++---- 19 files changed, 49 insertions(+), 76 deletions(-) diff --git a/esphome/components/nextion/automation.h b/esphome/components/nextion/automation.h index 9f52507d67..17f6c77e17 100644 --- a/esphome/components/nextion/automation.h +++ b/esphome/components/nextion/automation.h @@ -2,8 +2,7 @@ #include "esphome/core/automation.h" #include "nextion.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { template<typename... Ts> class NextionSetBrightnessAction : public Action<Ts...> { public: @@ -91,5 +90,4 @@ template<typename... Ts> class NextionPublishBoolAction : public Action<Ts...> { NextionComponent *component_; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp b/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp index 3628ac2f63..08e7c58ef1 100644 --- a/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp +++ b/esphome/components/nextion/binary_sensor/nextion_binarysensor.cpp @@ -2,8 +2,7 @@ #include "esphome/core/util.h" #include "esphome/core/log.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { static const char *const TAG = "nextion_binarysensor"; @@ -64,5 +63,4 @@ void NextionBinarySensor::set_state(bool state, bool publish, bool send_to_nexti ESP_LOGN(TAG, "Write: %s=%s", this->variable_name_.c_str(), ONOFF(this->state)); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/binary_sensor/nextion_binarysensor.h b/esphome/components/nextion/binary_sensor/nextion_binarysensor.h index baab47851c..7637957222 100644 --- a/esphome/components/nextion/binary_sensor/nextion_binarysensor.h +++ b/esphome/components/nextion/binary_sensor/nextion_binarysensor.h @@ -4,8 +4,8 @@ #include "../nextion_component.h" #include "../nextion_base.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + class NextionBinarySensor; class NextionBinarySensor : public NextionComponent, @@ -38,5 +38,4 @@ class NextionBinarySensor : public NextionComponent, protected: uint8_t page_id_; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index d141ef7906..ab268fed7f 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -5,8 +5,7 @@ #include "esphome/core/log.h" #include "esphome/core/util.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { static const char *const TAG = "nextion"; @@ -1290,5 +1289,4 @@ void Nextion::set_writer(const nextion_writer_t &writer) { this->writer_ = write bool Nextion::is_updating() { return this->connection_state_.is_updating_; } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index b5aaecd667..b3ecbf46b1 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -21,8 +21,7 @@ #endif // USE_ESP32 vs USE_ESP8266 #endif // USE_NEXTION_TFT_UPLOAD -namespace esphome { -namespace nextion { +namespace esphome::nextion { class Nextion; class NextionComponentBase; @@ -1547,5 +1546,4 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe uint16_t max_q_age_ms_ = 8000; ///< Maximum age for queue items in ms }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_base.h b/esphome/components/nextion/nextion_base.h index d46cd9a185..2c516fc80f 100644 --- a/esphome/components/nextion/nextion_base.h +++ b/esphome/components/nextion/nextion_base.h @@ -2,8 +2,8 @@ #include "esphome/core/defines.h" #include "esphome/core/color.h" #include "nextion_component_base.h" -namespace esphome { -namespace nextion { + +namespace esphome::nextion { #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE #define NEXTION_PROTOCOL_LOG @@ -61,5 +61,4 @@ class NextionBase { bool is_detected_ = false; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index 6c8e0f18bc..a7e65b5ddf 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -3,8 +3,8 @@ #include "esphome/core/log.h" #include <cinttypes> -namespace esphome { -namespace nextion { +namespace esphome::nextion { + static const char *const TAG = "nextion"; // Sleep safe commands @@ -340,5 +340,4 @@ void Nextion::set_nextion_rtc_time(ESPTime time) { this->add_no_result_to_queue_with_printf_("rtc5", "rtc5=%u", time.second); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_component.cpp b/esphome/components/nextion/nextion_component.cpp index 30c8b80524..f457125616 100644 --- a/esphome/components/nextion/nextion_component.cpp +++ b/esphome/components/nextion/nextion_component.cpp @@ -1,7 +1,6 @@ #include "nextion_component.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { void NextionComponent::set_background_color(Color bco) { if (this->variable_name_ == this->variable_name_to_send_) { @@ -110,5 +109,4 @@ void NextionComponent::update_component_settings(bool force_update) { this->component_flags_.font_id_needs_update = false; } } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_component.h b/esphome/components/nextion/nextion_component.h index add9e11cf1..068cf51361 100644 --- a/esphome/components/nextion/nextion_component.h +++ b/esphome/components/nextion/nextion_component.h @@ -3,8 +3,8 @@ #include "esphome/core/color.h" #include "nextion_base.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + class NextionComponent; class NextionComponent : public NextionComponentBase { @@ -80,5 +80,4 @@ class NextionComponent : public NextionComponentBase { uint16_t reserved : 3; } component_flags_; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_component_base.h b/esphome/components/nextion/nextion_component_base.h index 4d5550d406..c1d0ae8ed1 100644 --- a/esphome/components/nextion/nextion_component_base.h +++ b/esphome/components/nextion/nextion_component_base.h @@ -5,8 +5,7 @@ #include <vector> #include "esphome/core/defines.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { enum NextionQueueType { NO_RESULT = 0, @@ -102,5 +101,4 @@ class NextionComponentBase { bool needs_to_send_update_; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/nextion_upload.cpp b/esphome/components/nextion/nextion_upload.cpp index 7ddd7a2f08..a49e7f18d6 100644 --- a/esphome/components/nextion/nextion_upload.cpp +++ b/esphome/components/nextion/nextion_upload.cpp @@ -4,8 +4,8 @@ #include "esphome/core/application.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + static const char *const TAG = "nextion.upload"; bool Nextion::upload_end_(bool successful) { @@ -33,7 +33,6 @@ bool Nextion::upload_end_(bool successful) { return successful; } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion #endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/nextion/nextion_upload_arduino.cpp b/esphome/components/nextion/nextion_upload_arduino.cpp index f59b708002..c79c68552e 100644 --- a/esphome/components/nextion/nextion_upload_arduino.cpp +++ b/esphome/components/nextion/nextion_upload_arduino.cpp @@ -11,8 +11,8 @@ #include "esphome/core/log.h" #include "esphome/core/util.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + static const char *const TAG = "nextion.upload.arduino"; static constexpr size_t NEXTION_MAX_RESPONSE_LOG_BYTES = 16; @@ -342,8 +342,7 @@ WiFiClient *Nextion::get_wifi_client_() { } #endif // USE_ESP8266 -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion #endif // NOT USE_ESP32 #endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/nextion/nextion_upload_esp32.cpp b/esphome/components/nextion/nextion_upload_esp32.cpp index 166bbcc86a..40a284dc46 100644 --- a/esphome/components/nextion/nextion_upload_esp32.cpp +++ b/esphome/components/nextion/nextion_upload_esp32.cpp @@ -14,8 +14,8 @@ #include "esphome/core/log.h" #include "esphome/core/util.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + static const char *const TAG = "nextion.upload.esp32"; static constexpr size_t NEXTION_MAX_RESPONSE_LOG_BYTES = 16; @@ -344,8 +344,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) { return this->upload_end_(true); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion #endif // USE_ESP32 #endif // USE_NEXTION_TFT_UPLOAD diff --git a/esphome/components/nextion/sensor/nextion_sensor.cpp b/esphome/components/nextion/sensor/nextion_sensor.cpp index 9ea12cf808..d4fad86286 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.cpp +++ b/esphome/components/nextion/sensor/nextion_sensor.cpp @@ -2,8 +2,7 @@ #include "esphome/core/util.h" #include "esphome/core/log.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { static const char *const TAG = "nextion_sensor"; @@ -108,5 +107,4 @@ void NextionSensor::wave_update_() { this->nextion_->add_addt_command_to_queue(this); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/sensor/nextion_sensor.h b/esphome/components/nextion/sensor/nextion_sensor.h index b1902f9b1b..f1a3ff72ec 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.h +++ b/esphome/components/nextion/sensor/nextion_sensor.h @@ -4,8 +4,8 @@ #include "../nextion_component.h" #include "../nextion_base.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + class NextionSensor; class NextionSensor : public NextionComponent, public sensor::Sensor, public PollingComponent { @@ -44,5 +44,4 @@ class NextionSensor : public NextionComponent, public sensor::Sensor, public Pol bool send_last_value_ = true; void wave_update_(); }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/switch/nextion_switch.cpp b/esphome/components/nextion/switch/nextion_switch.cpp index 21636f2bfa..0018cff005 100644 --- a/esphome/components/nextion/switch/nextion_switch.cpp +++ b/esphome/components/nextion/switch/nextion_switch.cpp @@ -2,8 +2,7 @@ #include "esphome/core/util.h" #include "esphome/core/log.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { static const char *const TAG = "nextion_switch"; @@ -48,5 +47,4 @@ void NextionSwitch::set_state(bool state, bool publish, bool send_to_nextion) { void NextionSwitch::write_state(bool state) { this->set_state(state); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/switch/nextion_switch.h b/esphome/components/nextion/switch/nextion_switch.h index c371ea3fc6..7e0593d217 100644 --- a/esphome/components/nextion/switch/nextion_switch.h +++ b/esphome/components/nextion/switch/nextion_switch.h @@ -4,8 +4,8 @@ #include "../nextion_component.h" #include "../nextion_base.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + class NextionSwitch; class NextionSwitch : public NextionComponent, public switch_::Switch, public PollingComponent { @@ -30,5 +30,4 @@ class NextionSwitch : public NextionComponent, public switch_::Switch, public Po protected: void write_state(bool state) override; }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/text_sensor/nextion_textsensor.cpp b/esphome/components/nextion/text_sensor/nextion_textsensor.cpp index 9b6deeda87..45e4691423 100644 --- a/esphome/components/nextion/text_sensor/nextion_textsensor.cpp +++ b/esphome/components/nextion/text_sensor/nextion_textsensor.cpp @@ -2,8 +2,8 @@ #include "esphome/core/util.h" #include "esphome/core/log.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + static const char *const TAG = "nextion_textsensor"; void NextionTextSensor::process_text(const std::string &variable_name, const std::string &text_value) { @@ -45,5 +45,4 @@ void NextionTextSensor::set_state(const std::string &state, bool publish, bool s ESP_LOGN(TAG, "Write: %s='%s'", this->variable_name_.c_str(), state.c_str()); } -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion diff --git a/esphome/components/nextion/text_sensor/nextion_textsensor.h b/esphome/components/nextion/text_sensor/nextion_textsensor.h index 7c08e47189..42cd5dcef4 100644 --- a/esphome/components/nextion/text_sensor/nextion_textsensor.h +++ b/esphome/components/nextion/text_sensor/nextion_textsensor.h @@ -4,8 +4,8 @@ #include "../nextion_component.h" #include "../nextion_base.h" -namespace esphome { -namespace nextion { +namespace esphome::nextion { + class NextionTextSensor; class NextionTextSensor : public NextionComponent, public text_sensor::TextSensor, public PollingComponent { @@ -28,5 +28,4 @@ class NextionTextSensor : public NextionComponent, public text_sensor::TextSenso this->set_state(state_value, publish, send_to_nextion); } }; -} // namespace nextion -} // namespace esphome +} // namespace esphome::nextion From c21c7dd29289f2553a16fa63da60f66e715c8fe5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 2 Apr 2026 03:12:38 -1000 Subject: [PATCH 1883/2030] [mitsubishi_cn105] Fix test grouping conflict with uart package (#15366) --- tests/components/mitsubishi_cn105/test.esp32-idf.yaml | 2 +- tests/components/mitsubishi_cn105/test.esp8266-ard.yaml | 2 +- tests/components/mitsubishi_cn105/test.rp2040-ard.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/components/mitsubishi_cn105/test.esp32-idf.yaml b/tests/components/mitsubishi_cn105/test.esp32-idf.yaml index ac63cf987f..5ce1861902 100644 --- a/tests/components/mitsubishi_cn105/test.esp32-idf.yaml +++ b/tests/components/mitsubishi_cn105/test.esp32-idf.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml + uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp32-idf.yaml <<: !include common.yaml diff --git a/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml b/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml index 9f2f350b46..a3f8cf43d4 100644 --- a/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml +++ b/tests/components/mitsubishi_cn105/test.esp8266-ard.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_9600_even/esp8266-ard.yaml + uart_9600_even: !include ../../test_build_components/common/uart_9600_even/esp8266-ard.yaml <<: !include common.yaml diff --git a/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml b/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml index 4363d6eee8..7c1f4f41e2 100644 --- a/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml +++ b/tests/components/mitsubishi_cn105/test.rp2040-ard.yaml @@ -1,4 +1,4 @@ packages: - uart: !include ../../test_build_components/common/uart_9600_even/rp2040-ard.yaml + uart_9600_even: !include ../../test_build_components/common/uart_9600_even/rp2040-ard.yaml <<: !include common.yaml From a359ecaaf40384c8f31934e9662fdad84b4db3bc Mon Sep 17 00:00:00 2001 From: tomaszduda23 <tomaszduda23@gmail.com> Date: Thu, 2 Apr 2026 16:12:20 +0200 Subject: [PATCH 1884/2030] [zigbee] print logs after reporting info update (#13916) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/zigbee/zigbee_zephyr.cpp | 60 +++++++++++++++------ esphome/components/zigbee/zigbee_zephyr.h | 1 + esphome/components/zigbee/zigbee_zephyr.py | 2 + 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/esphome/components/zigbee/zigbee_zephyr.cpp b/esphome/components/zigbee/zigbee_zephyr.cpp index c103363b4a..047c30300e 100644 --- a/esphome/components/zigbee/zigbee_zephyr.cpp +++ b/esphome/components/zigbee/zigbee_zephyr.cpp @@ -255,26 +255,25 @@ void ZigbeeComponent::factory_reset() { ZB_SCHEDULE_APP_CALLBACK(zb_bdb_reset_via_local_action, 0); } +static void log_reporting_info(zb_zcl_reporting_info_t *rep_info) { + auto now = millis(); + ESP_LOGD(TAG, "Reporting: endpoint %d, cluster_id 0x%04X, attr_id 0x%04X, flags 0x%02X, report in %ums", rep_info->ep, + rep_info->cluster_id, rep_info->attr_id, rep_info->flags, + ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED) + ? ZB_TIME_BEACON_INTERVAL_TO_MSEC(rep_info->run_time) - now + : 0); + ESP_LOGD(TAG, " min_interval %ds, max_interval %ds, def_min_interval %ds, def_max_interval %ds", + rep_info->u.send_info.min_interval, rep_info->u.send_info.max_interval, + rep_info->u.send_info.def_min_interval, rep_info->u.send_info.def_max_interval); +} + void ZigbeeComponent::dump_reporting_() { #ifdef ESPHOME_LOG_HAS_VERBOSE - auto now = millis(); - bool first = true; for (zb_uint8_t j = 0; j < ZCL_CTX().device_ctx->ep_count; j++) { if (ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info) { zb_zcl_reporting_info_t *rep_info = ZCL_CTX().device_ctx->ep_desc_list[j]->reporting_info; for (zb_uint8_t i = 0; i < ZCL_CTX().device_ctx->ep_desc_list[j]->rep_info_count; i++) { - if (!first) { - ESP_LOGV(TAG, ""); - } - first = false; - ESP_LOGV(TAG, "Endpoint: %d, cluster_id %d, attr_id %d, flags %d, report in %ums", rep_info->ep, - rep_info->cluster_id, rep_info->attr_id, rep_info->flags, - ZB_ZCL_GET_REPORTING_FLAG(rep_info, ZB_ZCL_REPORT_TIMER_STARTED) - ? ZB_TIME_BEACON_INTERVAL_TO_MSEC(rep_info->run_time) - now - : 0); - ESP_LOGV(TAG, "Min_interval %ds, max_interval %ds, def_min_interval %ds, def_max_interval %ds", - rep_info->u.send_info.min_interval, rep_info->u.send_info.max_interval, - rep_info->u.send_info.def_min_interval, rep_info->u.send_info.def_max_interval); + log_reporting_info(rep_info); rep_info++; } } @@ -282,9 +281,38 @@ void ZigbeeComponent::dump_reporting_() { #endif } +void ZigbeeComponent::after_reporting_info(zb_zcl_configure_reporting_req_t *config_rep_req, + zb_zcl_attr_addr_info_t *attr_addr_info) { +#ifdef ESPHOME_LOG_HAS_DEBUG + auto *rep_info = + zb_zcl_find_reporting_info_manuf(attr_addr_info->src_ep, attr_addr_info->cluster_id, attr_addr_info->cluster_role, + config_rep_req->attr_id, attr_addr_info->manuf_code); + if (rep_info == nullptr) { + ESP_LOGE(TAG, + "Failed to resolve reporting info (src_ep=%u cluster_id=0x%04x role=%u attr_id=0x%04x manuf_code=0x%04x)", + attr_addr_info->src_ep, attr_addr_info->cluster_id, attr_addr_info->cluster_role, config_rep_req->attr_id, + attr_addr_info->manuf_code); + return; + } + log_reporting_info(rep_info); +#endif +} + } // namespace esphome::zigbee -extern "C" void zboss_signal_handler(zb_uint8_t param) { - esphome::zigbee::global_zigbee->zboss_signal_handler_esphome(param); +extern "C" { +void zboss_signal_handler(zb_uint8_t param) { esphome::zigbee::global_zigbee->zboss_signal_handler_esphome(param); } + +// NOLINTBEGIN(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) +extern zb_ret_t __real_zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, + zb_zcl_attr_addr_info_t *attr_addr_info); + +zb_ret_t __wrap_zb_zcl_put_reporting_info_from_req(zb_zcl_configure_reporting_req_t *config_rep_req, + zb_zcl_attr_addr_info_t *attr_addr_info) { + zb_ret_t ret = __real_zb_zcl_put_reporting_info_from_req(config_rep_req, attr_addr_info); + esphome::zigbee::global_zigbee->after_reporting_info(config_rep_req, attr_addr_info); + return ret; +} +// NOLINTEND(readability-identifier-naming,bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) } #endif diff --git a/esphome/components/zigbee/zigbee_zephyr.h b/esphome/components/zigbee/zigbee_zephyr.h index 3fa5818ec5..eeb142eff1 100644 --- a/esphome/components/zigbee/zigbee_zephyr.h +++ b/esphome/components/zigbee/zigbee_zephyr.h @@ -76,6 +76,7 @@ class ZigbeeComponent : public Component { } template<typename F> void add_join_callback(F &&cb) { this->join_cb_.add(std::forward<F>(cb)); } void zboss_signal_handler_esphome(zb_bufid_t bufid); + void after_reporting_info(zb_zcl_configure_reporting_req_t *config_rep_req, zb_zcl_attr_addr_info_t *attr_addr_info); void factory_reset(); Trigger<> *get_join_trigger() { return &this->join_trigger_; }; void force_report(); diff --git a/esphome/components/zigbee/zigbee_zephyr.py b/esphome/components/zigbee/zigbee_zephyr.py index a1e6ad3097..3288d92483 100644 --- a/esphome/components/zigbee/zigbee_zephyr.py +++ b/esphome/components/zigbee/zigbee_zephyr.py @@ -166,6 +166,8 @@ async def zephyr_to_code(config: ConfigType) -> None: zephyr_add_prj_conf("NET_IP_ADDR_CHECK", False) zephyr_add_prj_conf("NET_UDP", False) + cg.add_build_flag("-Wl,--wrap=zb_zcl_put_reporting_info_from_req") + if CONF_IEEE802154_VENDOR_OUI in config: zephyr_add_prj_conf("IEEE802154_VENDOR_OUI_ENABLE", True) random_number = config[CONF_IEEE802154_VENDOR_OUI] From b8a9d327f05700a6df463202cdc5cfaefbfdc8dd Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 2 Apr 2026 09:40:19 -0500 Subject: [PATCH 1885/2030] [media_player] Add enqueue action (#14775) --- esphome/components/media_player/__init__.py | 41 +++++++++++++------- esphome/components/media_player/automation.h | 16 +++++--- tests/components/media_player/common.yaml | 5 +++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 767916ad88..842f620dae 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -94,6 +94,9 @@ _STATE_CONDITIONS = [ PlayMediaAction = media_player_ns.class_( "PlayMediaAction", automation.Action, cg.Parented.template(MediaPlayer) ) +EnqueueMediaAction = media_player_ns.class_( + "EnqueueMediaAction", automation.Action, cg.Parented.template(MediaPlayer) +) VolumeSetAction = media_player_ns.class_( "VolumeSetAction", automation.Action, cg.Parented.template(MediaPlayer) ) @@ -168,20 +171,17 @@ MEDIA_PLAYER_CONDITION_SCHEMA = automation.maybe_simple_id( ) -@automation.register_action( - "media_player.play_media", - PlayMediaAction, - cv.maybe_simple_value( - { - cv.GenerateID(): cv.use_id(MediaPlayer), - cv.Required(CONF_MEDIA_URL): cv.templatable(cv.url), - cv.Optional(CONF_ANNOUNCEMENT, default=False): cv.templatable(cv.boolean), - }, - key=CONF_MEDIA_URL, - ), - synchronous=True, +_MEDIA_URL_ACTION_SCHEMA = cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(MediaPlayer), + cv.Required(CONF_MEDIA_URL): cv.templatable(cv.url), + cv.Optional(CONF_ANNOUNCEMENT, default=False): cv.templatable(cv.boolean), + }, + key=CONF_MEDIA_URL, ) -async def media_player_play_media_action(config, action_id, template_arg, args): + + +async def _media_action_handler(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) media_url = await cg.templatable(config[CONF_MEDIA_URL], args, cg.std_string) @@ -191,6 +191,21 @@ async def media_player_play_media_action(config, action_id, template_arg, args): return var +automation.register_action( + "media_player.play_media", + PlayMediaAction, + _MEDIA_URL_ACTION_SCHEMA, + synchronous=True, +)(_media_action_handler) + +automation.register_action( + "media_player.enqueue", + EnqueueMediaAction, + _MEDIA_URL_ACTION_SCHEMA, + synchronous=True, +)(_media_action_handler) + + def _snake_to_camel(name): return "".join(word.capitalize() for word in name.split("_")) diff --git a/esphome/components/media_player/automation.h b/esphome/components/media_player/automation.h index 658381ef90..14ce3c6aed 100644 --- a/esphome/components/media_player/automation.h +++ b/esphome/components/media_player/automation.h @@ -55,17 +55,23 @@ using GroupJoinAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYE template<typename... Ts> using ClearPlaylistAction = MediaPlayerCommandAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_CLEAR_PLAYLIST, Ts...>; -template<typename... Ts> class PlayMediaAction : public Action<Ts...>, public Parented<MediaPlayer> { +template<MediaPlayerCommand Command, typename... Ts> +class MediaPlayerMediaAction : public Action<Ts...>, public Parented<MediaPlayer> { TEMPLATABLE_VALUE(std::string, media_url) TEMPLATABLE_VALUE(bool, announcement) void play(const Ts &...x) override { - this->parent_->make_call() - .set_media_url(this->media_url_.value(x...)) - .set_announcement(this->announcement_.value(x...)) - .perform(); + auto call = this->parent_->make_call(); + if constexpr (Command != MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PLAY) + call.set_command(Command); + call.set_media_url(this->media_url_.value(x...)).set_announcement(this->announcement_.value(x...)).perform(); } }; +template<typename... Ts> +using PlayMediaAction = MediaPlayerMediaAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_PLAY, Ts...>; +template<typename... Ts> +using EnqueueMediaAction = MediaPlayerMediaAction<MediaPlayerCommand::MEDIA_PLAYER_COMMAND_ENQUEUE, Ts...>; + template<typename... Ts> class VolumeSetAction : public Action<Ts...>, public Parented<MediaPlayer> { TEMPLATABLE_VALUE(float, volume) void play(const Ts &...x) override { this->parent_->make_call().set_volume(this->volume_.value(x...)).perform(); } diff --git a/tests/components/media_player/common.yaml b/tests/components/media_player/common.yaml index 89600f70f6..88d04d0ff0 100644 --- a/tests/components/media_player/common.yaml +++ b/tests/components/media_player/common.yaml @@ -61,3 +61,8 @@ media_player: - media_player.volume_up: - media_player.volume_down: - media_player.volume_set: 50% + - media_player.enqueue: http://localhost/media.mp3 + - media_player.enqueue: !lambda 'return "http://localhost/media.mp3";' + - media_player.enqueue: + media_url: http://localhost/media.mp3 + announcement: true From da8d9d9c2d1f1ba41837beea471ebcfd50116618 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt <kevin.ahrendt@openhomefoundation.org> Date: Thu, 2 Apr 2026 10:37:14 -0500 Subject: [PATCH 1886/2030] [audio] use microFLAC library for decoding (#15372) --- esphome/components/audio/__init__.py | 1 + esphome/components/audio/audio_decoder.cpp | 83 +++++++++------------- esphome/components/audio/audio_decoder.h | 10 +-- esphome/idf_component.yml | 2 + 4 files changed, 42 insertions(+), 54 deletions(-) diff --git a/esphome/components/audio/__init__.py b/esphome/components/audio/__init__.py index acc3b5d351..8f2102de6a 100644 --- a/esphome/components/audio/__init__.py +++ b/esphome/components/audio/__init__.py @@ -210,6 +210,7 @@ async def to_code(config): data = _get_data() if data.flac_support: cg.add_define("USE_AUDIO_FLAC_SUPPORT") + add_idf_component(name="esphome/micro-flac", ref="0.1.1") if data.mp3_support: cg.add_define("USE_AUDIO_MP3_SUPPORT") if data.opus_support: diff --git a/esphome/components/audio/audio_decoder.cpp b/esphome/components/audio/audio_decoder.cpp index bc05bc0006..baa4c41c06 100644 --- a/esphome/components/audio/audio_decoder.cpp +++ b/esphome/components/audio/audio_decoder.cpp @@ -84,13 +84,10 @@ esp_err_t AudioDecoder::start(AudioFileType audio_file_type) { switch (this->audio_file_type_) { #ifdef USE_AUDIO_FLAC_SUPPORT case AudioFileType::FLAC: - this->flac_decoder_ = make_unique<esp_audio_libs::flac::FLACDecoder>(); - // CRC check slows down decoding by 15-20% on an ESP32-S3. FLAC sources in ESPHome are either from an http source - // or built into the firmware, so the data integrity is already verified by the time it gets to the decoder, - // making the CRC check unnecessary. - this->flac_decoder_->set_crc_check_enabled(false); + this->flac_decoder_ = make_unique<micro_flac::FLACDecoder>(); this->free_buffer_required_ = this->output_transfer_buffer_->capacity(); // Adjusted and reallocated after reading the header + this->decoder_buffers_internally_ = true; break; #endif #ifdef USE_AUDIO_MP3_SUPPORT @@ -268,59 +265,45 @@ AudioDecoderState AudioDecoder::decode(bool stop_gracefully) { #ifdef USE_AUDIO_FLAC_SUPPORT FileDecoderState AudioDecoder::decode_flac_() { - if (!this->audio_stream_info_.has_value()) { - // Header hasn't been read - auto result = this->flac_decoder_->read_header(this->input_buffer_->data(), this->input_buffer_->available()); + size_t bytes_consumed, samples_decoded; - if (result > esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) { - // Serrious error reading FLAC header, there is no recovery - return FileDecoderState::FAILED; + micro_flac::FLACDecoderResult result = this->flac_decoder_->decode( + this->input_buffer_->data(), this->input_buffer_->available(), this->output_transfer_buffer_->get_buffer_end(), + this->output_transfer_buffer_->free(), bytes_consumed, samples_decoded); + + if (result == micro_flac::FLAC_DECODER_SUCCESS) { + if (samples_decoded > 0 && this->audio_stream_info_.has_value()) { + this->output_transfer_buffer_->increase_buffer_length( + this->audio_stream_info_.value().samples_to_bytes(samples_decoded)); } - - size_t bytes_consumed = this->flac_decoder_->get_bytes_index(); this->input_buffer_->consume(bytes_consumed); + } else if (result == micro_flac::FLAC_DECODER_HEADER_READY) { + // Header just parsed, stream info now available + const auto &info = this->flac_decoder_->get_stream_info(); + this->audio_stream_info_ = audio::AudioStreamInfo(info.bits_per_sample(), info.num_channels(), info.sample_rate()); - if (result == esp_audio_libs::flac::FLAC_DECODER_HEADER_OUT_OF_DATA) { - return FileDecoderState::MORE_TO_PROCESS; - } - - // Reallocate the output transfer buffer to the smallest necessary size - this->free_buffer_required_ = flac_decoder_->get_output_buffer_size_bytes(); + // Reallocate the output transfer buffer to the required size + this->free_buffer_required_ = this->flac_decoder_->get_output_buffer_size_samples() * info.bytes_per_sample(); if (!this->output_transfer_buffer_->reallocate(this->free_buffer_required_)) { - // Couldn't reallocate output buffer return FileDecoderState::FAILED; } - - this->audio_stream_info_ = - audio::AudioStreamInfo(this->flac_decoder_->get_sample_depth(), this->flac_decoder_->get_num_channels(), - this->flac_decoder_->get_sample_rate()); - - return FileDecoderState::MORE_TO_PROCESS; - } - - uint32_t output_samples = 0; - auto result = this->flac_decoder_->decode_frame(this->input_buffer_->data(), this->input_buffer_->available(), - this->output_transfer_buffer_->get_buffer_end(), &output_samples); - - if (result == esp_audio_libs::flac::FLAC_DECODER_ERROR_OUT_OF_DATA) { - // Not an issue, just needs more data that we'll get next time. - return FileDecoderState::POTENTIALLY_FAILED; - } - - size_t bytes_consumed = this->flac_decoder_->get_bytes_index(); - this->input_buffer_->consume(bytes_consumed); - - if (result > esp_audio_libs::flac::FLAC_DECODER_ERROR_OUT_OF_DATA) { - // Corrupted frame, don't retry with current buffer content, wait for new sync - return FileDecoderState::POTENTIALLY_FAILED; - } - - // We have successfully decoded some input data and have new output data - this->output_transfer_buffer_->increase_buffer_length( - this->audio_stream_info_.value().samples_to_bytes(output_samples)); - - if (result == esp_audio_libs::flac::FLAC_DECODER_NO_MORE_FRAMES) { + this->input_buffer_->consume(bytes_consumed); + } else if (result == micro_flac::FLAC_DECODER_END_OF_STREAM) { + this->input_buffer_->consume(bytes_consumed); return FileDecoderState::END_OF_FILE; + } else if (result == micro_flac::FLAC_DECODER_NEED_MORE_DATA) { + this->input_buffer_->consume(bytes_consumed); + return FileDecoderState::MORE_TO_PROCESS; + } else if (result == micro_flac::FLAC_DECODER_ERROR_OUTPUT_TOO_SMALL) { + // Reallocate to decode the frame on the next call + const auto &info = this->flac_decoder_->get_stream_info(); + this->free_buffer_required_ = this->flac_decoder_->get_output_buffer_size_samples() * info.bytes_per_sample(); + if (!this->output_transfer_buffer_->reallocate(this->free_buffer_required_)) { + return FileDecoderState::FAILED; + } + } else { + ESP_LOGE(TAG, "FLAC decoder failed: %d", static_cast<int>(result)); + return FileDecoderState::POTENTIALLY_FAILED; } return FileDecoderState::MORE_TO_PROCESS; diff --git a/esphome/components/audio/audio_decoder.h b/esphome/components/audio/audio_decoder.h index 726baa289e..6e3a228a68 100644 --- a/esphome/components/audio/audio_decoder.h +++ b/esphome/components/audio/audio_decoder.h @@ -16,14 +16,16 @@ #include "esp_err.h" // esp-audio-libs -#ifdef USE_AUDIO_FLAC_SUPPORT -#include <flac_decoder.h> -#endif #ifdef USE_AUDIO_MP3_SUPPORT #include <mp3_decoder.h> #endif #include <wav_decoder.h> +// micro-flac +#ifdef USE_AUDIO_FLAC_SUPPORT +#include <micro_flac/flac_decoder.h> +#endif + // micro-opus #ifdef USE_AUDIO_OPUS_SUPPORT #include <micro_opus/ogg_opus_decoder.h> @@ -119,7 +121,7 @@ class AudioDecoder { std::unique_ptr<esp_audio_libs::wav_decoder::WAVDecoder> wav_decoder_; #ifdef USE_AUDIO_FLAC_SUPPORT FileDecoderState decode_flac_(); - std::unique_ptr<esp_audio_libs::flac::FLACDecoder> flac_decoder_; + std::unique_ptr<micro_flac::FLACDecoder> flac_decoder_; #endif #ifdef USE_AUDIO_MP3_SUPPORT FileDecoderState decode_mp3_(); diff --git a/esphome/idf_component.yml b/esphome/idf_component.yml index 462af5d1e7..1e40fef2dc 100644 --- a/esphome/idf_component.yml +++ b/esphome/idf_component.yml @@ -3,6 +3,8 @@ dependencies: version: "7.4.2" esphome/esp-audio-libs: version: 2.0.4 + esphome/micro-flac: + version: 0.1.1 esphome/micro-opus: version: 0.3.6 espressif/esp-dsp: From e7e590b36f97deea2b9dac5af69be9505c335970 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:08:43 -0400 Subject: [PATCH 1887/2030] [thermostat] Fix on_boot_restore_from DEFAULT_PRESET validation bypass (#15383) --- esphome/components/thermostat/climate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index f7c1298d68..ec115296d7 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -503,7 +503,7 @@ def validate_thermostat(config): # If restoring default preset on boot is true then ensure we have a default preset if ( CONF_ON_BOOT_RESTORE_FROM in config - and config[CONF_ON_BOOT_RESTORE_FROM] is OnBootRestoreFrom.DEFAULT_PRESET + and config[CONF_ON_BOOT_RESTORE_FROM] == "DEFAULT_PRESET" and CONF_DEFAULT_PRESET not in config ): raise cv.Invalid( From da09e1e1ce336ff7f7d2c3bede9c4bdad7bbedf0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 2 Apr 2026 09:19:47 -1000 Subject: [PATCH 1888/2030] [time] Use O(1) closed-form leap year math for epoch-to-year conversion (#15368) --- esphome/components/time/posix_tz.cpp | 63 +++++++------ tests/components/time/posix_tz_parser.cpp | 109 ++++++++++++++++++++++ 2 files changed, 144 insertions(+), 28 deletions(-) diff --git a/esphome/components/time/posix_tz.cpp b/esphome/components/time/posix_tz.cpp index f388267abd..c25248e457 100644 --- a/esphome/components/time/posix_tz.cpp +++ b/esphome/components/time/posix_tz.cpp @@ -34,25 +34,43 @@ bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year // Get days in year (avoids duplicate is_leap_year calls) static inline int days_in_year(int year) { return is_leap_year(year) ? 366 : 365; } -// Convert days since epoch to year, updating days to remainder -static int __attribute__((noinline)) days_to_year(int64_t &days) { - int year = 1970; - int diy; - while (days >= (diy = days_in_year(year)) && year < 2200) { - days -= diy; +// Count leap years in [1, year] (i.e. up to and including year) +static constexpr int count_leap_years_up_to(int year) { return year / 4 - year / 100 + year / 400; } + +constexpr int EPOCH_YEAR = 1970; +constexpr int LEAP_YEARS_BEFORE_EPOCH = count_leap_years_up_to(EPOCH_YEAR - 1); +constexpr int DAYS_PER_YEAR = 365; +constexpr int SECONDS_PER_DAY = 86400; + +// Days from epoch (Jan 1 1970) to Jan 1 of given year — O(1) +static inline int64_t days_to_year_start(int year) { + return static_cast<int64_t>(DAYS_PER_YEAR) * (year - EPOCH_YEAR) + + (count_leap_years_up_to(year - 1) - LEAP_YEARS_BEFORE_EPOCH); +} + +// Convert days since epoch to year, updating days to day-of-year remainder. +// The initial estimate from days/365 can overshoot by multiple years for +// far-future dates (e.g., year 5000+) due to accumulated leap days, +// so we use loops rather than single-step correction. +static int days_to_year(int64_t &days) { + int year = static_cast<int>(EPOCH_YEAR + days / DAYS_PER_YEAR); + int64_t year_start = days_to_year_start(year); + while (days < year_start) { + year--; + year_start = days_to_year_start(year); + } + while (days >= year_start + days_in_year(year)) { + year_start += days_in_year(year); year++; } - while (days < 0 && year > 1900) { - year--; - days += days_in_year(year); - } + days -= year_start; return year; } -// Extract just the year from a UTC epoch +// Extract just the year from a UTC epoch — O(1) static int epoch_to_year(time_t epoch) { - int64_t days = epoch / 86400; - if (epoch < 0 && epoch % 86400 != 0) + int64_t days = epoch / SECONDS_PER_DAY; + if (epoch < 0 && epoch % SECONDS_PER_DAY != 0) days--; return days_to_year(days); } @@ -87,11 +105,11 @@ int __attribute__((noinline)) day_of_week(int year, int month, int day) { void __attribute__((noinline)) epoch_to_tm_utc(time_t epoch, struct tm *out_tm) { // Days since epoch - int64_t days = epoch / 86400; - int32_t remaining_secs = epoch % 86400; + int64_t days = epoch / SECONDS_PER_DAY; + int32_t remaining_secs = epoch % SECONDS_PER_DAY; if (remaining_secs < 0) { days--; - remaining_secs += 86400; + remaining_secs += SECONDS_PER_DAY; } out_tm->tm_sec = remaining_secs % 60; @@ -280,17 +298,6 @@ static int __attribute__((noinline)) days_from_year_start(int year, int month, i return days; } -// Calculate days from epoch to Jan 1 of given year (for DST transition calculations) -// Only supports years >= 1970. Timezone is either compiled in from YAML or set by -// Home Assistant, so pre-1970 dates are not a concern. -static int64_t __attribute__((noinline)) days_to_year_start(int year) { - int64_t days = 0; - for (int y = 1970; y < year; y++) { - days += days_in_year(y); - } - return days; -} - time_t __attribute__((noinline)) calculate_dst_transition(int year, const DSTRule &rule, int32_t base_offset_seconds) { int month, day; @@ -339,7 +346,7 @@ time_t __attribute__((noinline)) calculate_dst_transition(int year, const DSTRul int64_t days = days_to_year_start(year) + days_from_year_start(year, month, day); // Convert to epoch and add transition time and base offset - return days * 86400 + rule.time_seconds + base_offset_seconds; + return days * SECONDS_PER_DAY + rule.time_seconds + base_offset_seconds; } } // namespace internal diff --git a/tests/components/time/posix_tz_parser.cpp b/tests/components/time/posix_tz_parser.cpp index b7cf2a4afa..440eea608d 100644 --- a/tests/components/time/posix_tz_parser.cpp +++ b/tests/components/time/posix_tz_parser.cpp @@ -758,6 +758,115 @@ TEST(PosixTzParser, EpochToLocalDstTransition) { EXPECT_EQ(local.tm_isdst, 1); } +// ============================================================================ +// Leap year edge cases for closed-form year arithmetic +// ============================================================================ + +TEST(PosixTzParser, EpochToLocalLeapYear2000) { + // 2000 is a leap year (divisible by 400) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + + // Feb 29, 2000 12:00:00 UTC + time_t epoch = make_utc(2000, 2, 29, 12); + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 100); // 2000 + EXPECT_EQ(local.tm_mon, 1); // February + EXPECT_EQ(local.tm_mday, 29); + EXPECT_EQ(local.tm_hour, 12); +} + +TEST(PosixTzParser, EpochToLocalNonLeapYear2100) { + // 2100 is NOT a leap year (divisible by 100 but not 400) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + + // Mar 1, 2100 00:00:00 UTC — the day after what would be Feb 29 + time_t epoch = make_utc(2100, 3, 1); + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 200); // 2100 + EXPECT_EQ(local.tm_mon, 2); // March + EXPECT_EQ(local.tm_mday, 1); + + // Feb 28, 2100 23:59:59 UTC — last second of February (no Feb 29) + epoch = make_utc(2100, 2, 28, 23, 59, 59); + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 200); + EXPECT_EQ(local.tm_mon, 1); // February + EXPECT_EQ(local.tm_mday, 28); +} + +TEST(PosixTzParser, EpochToLocalLeapYear2400) { + // 2400 is a leap year (divisible by 400) + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + + time_t epoch = make_utc(2400, 2, 29, 6); + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 500); // 2400 + EXPECT_EQ(local.tm_mon, 1); // February + EXPECT_EQ(local.tm_mday, 29); + EXPECT_EQ(local.tm_hour, 6); +} + +TEST(PosixTzParser, EpochToLocalNewYearBoundaries) { + // Test year boundary — last second of 2099 and first second of 2100 + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + struct tm local; + + // Dec 31, 2099 23:59:59 UTC + time_t epoch = make_utc(2099, 12, 31, 23, 59, 59); + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 199); // 2099 + EXPECT_EQ(local.tm_mon, 11); // December + EXPECT_EQ(local.tm_mday, 31); + + // Jan 1, 2100 00:00:00 UTC + epoch = make_utc(2100, 1, 1); + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 200); // 2100 + EXPECT_EQ(local.tm_mon, 0); // January + EXPECT_EQ(local.tm_mday, 1); +} + +TEST(PosixTzParser, EpochToLocalDstAcrossCenturyBoundary) { + // DST transition in year 2100 (non-leap) with US Eastern rules + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("EST5EDT,M3.2.0/2,M11.1.0/2", tz)); + + // July 4, 2100 16:00 UTC = 12:00 EDT + time_t epoch = make_utc(2100, 7, 4, 16); + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_hour, 12); + EXPECT_EQ(local.tm_isdst, 1); + + // Jan 15, 2100 10:00 UTC = 05:00 EST + epoch = make_utc(2100, 1, 15, 10); + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_hour, 5); + EXPECT_EQ(local.tm_isdst, 0); +} + +TEST(PosixTzParser, EpochToLocalFarFutureYear5000) { + // Year 5000 — days/365 estimate overshoots by ~2 years due to leap days, + // requiring multiple correction steps in days_to_year. + ParsedTimezone tz; + ASSERT_TRUE(parse_posix_tz("UTC0", tz)); + + time_t epoch = make_utc(5000, 6, 15, 12); + struct tm local; + ASSERT_TRUE(epoch_to_local_tm(epoch, tz, &local)); + EXPECT_EQ(local.tm_year, 3100); // 5000 + EXPECT_EQ(local.tm_mon, 5); // June + EXPECT_EQ(local.tm_mday, 15); + EXPECT_EQ(local.tm_hour, 12); +} + // ============================================================================ // Verification against libc // ============================================================================ From 0343121e9b81ba09d1951831b396df32a3ff2850 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:21:18 -0400 Subject: [PATCH 1889/2030] [ble_client] Fix descriptor_uuid ignored for text sensors (#15374) --- esphome/components/ble_client/text_sensor/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ble_client/text_sensor/__init__.py b/esphome/components/ble_client/text_sensor/__init__.py index a6b8956f93..0f53cccdad 100644 --- a/esphome/components/ble_client/text_sensor/__init__.py +++ b/esphome/components/ble_client/text_sensor/__init__.py @@ -88,7 +88,7 @@ async def to_code(config): ) cg.add(var.set_char_uuid128(uuid128)) - if descriptor_uuid := config: + if descriptor_uuid := config.get(CONF_DESCRIPTOR_UUID): if len(descriptor_uuid) == len(esp32_ble_tracker.bt_uuid16_format): cg.add(var.set_descr_uuid16(esp32_ble_tracker.as_hex(descriptor_uuid))) elif len(descriptor_uuid) == len(esp32_ble_tracker.bt_uuid32_format): From 5dcae1a133762ad49b4fb57b408d7651bc6bd470 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:22:07 -0400 Subject: [PATCH 1890/2030] [climate] Fix MQTT target_temperature_low_state_topic calling wrong setter (#15376) --- esphome/components/climate/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index 8cf5fa9b0c..13dd7aa007 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -400,7 +400,7 @@ async def setup_climate_core_(var, config): ) ) is not None: cg.add( - mqtt_.set_custom_target_temperature_state_topic( + mqtt_.set_custom_target_temperature_low_state_topic( target_temperature_low_state_topic ) ) From 12a0f5959f0a63a63356aabb05419056db97861f Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:23:04 -0400 Subject: [PATCH 1891/2030] [bl0940] Fix reference_voltage config ignored in non-legacy mode (#15375) --- esphome/components/bl0940/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/bl0940/sensor.py b/esphome/components/bl0940/sensor.py index f36250ecdf..992064943b 100644 --- a/esphome/components/bl0940/sensor.py +++ b/esphome/components/bl0940/sensor.py @@ -126,7 +126,7 @@ def set_reference_values(config): config.setdefault(CONF_POWER_REFERENCE, DEFAULT_BL0940_LEGACY_PREF) config.setdefault(CONF_ENERGY_REFERENCE, DEFAULT_BL0940_LEGACY_EREF) else: - vref = config.get(CONF_VOLTAGE_REFERENCE, DEFAULT_BL0940_VREF) + vref = config.get(CONF_REFERENCE_VOLTAGE, DEFAULT_BL0940_VREF) r_one = config.get(CONF_RESISTOR_ONE, DEFAULT_BL0940_R1) r_two = config.get(CONF_RESISTOR_TWO, DEFAULT_BL0940_R2) r_shunt = config.get(CONF_RESISTOR_SHUNT, DEFAULT_BL0940_RL) From 67ee727e382c0c13ad8d2918a33e491cac0d037a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:24:26 -1000 Subject: [PATCH 1892/2030] Bump docker/login-action from 4.0.0 to 4.1.0 in the docker-actions group (#15386) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4aa63f6a16..ba6db99b84 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,12 +102,12 @@ jobs: uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 - name: Log in to docker hub - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -182,13 +182,13 @@ jobs: - name: Log in to docker hub if: matrix.registry == 'dockerhub' - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Log in to the GitHub container registry if: matrix.registry == 'ghcr' - uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ghcr.io username: ${{ github.actor }} From 2f405fd96f39819dfcfa4f1f069cbf5ffee501c3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:25:15 -0400 Subject: [PATCH 1893/2030] [espnow] Fix enable_on_boot config option not passed to C++ (#15377) --- esphome/components/espnow/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index d1a85ae8fd..00703bc228 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -132,6 +132,7 @@ async def to_code(config): if wifi_channel := config.get(CONF_CHANNEL): cg.add(var.set_wifi_channel(wifi_channel)) + cg.add(var.set_enable_on_boot(config[CONF_ENABLE_ON_BOOT])) cg.add(var.set_auto_add_peer(config[CONF_AUTO_ADD_PEER])) for peer in config.get(CONF_PEERS, []): From 37b33f62de49c667c88b5a60b38ef46365bbd9ff Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:25:54 -0400 Subject: [PATCH 1894/2030] [htu21d] Fix set_heater action reading wrong config key (#15378) --- esphome/components/htu21d/sensor.py | 2 +- tests/components/htu21d/common.yaml | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 92c088a22f..ed4fb5968a 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -118,6 +118,6 @@ async def set_heater_level_to_code(config, action_id, template_arg, args): async def set_heater_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - status_ = await cg.templatable(config[CONF_LEVEL], args, bool) + status_ = await cg.templatable(config[CONF_STATUS], args, bool) cg.add(var.set_status(status_)) return var diff --git a/tests/components/htu21d/common.yaml b/tests/components/htu21d/common.yaml index ad4b23d460..126360b775 100644 --- a/tests/components/htu21d/common.yaml +++ b/tests/components/htu21d/common.yaml @@ -1,5 +1,6 @@ sensor: - platform: htu21d + id: htu21d_sensor i2c_id: i2c_bus model: htu21d temperature: @@ -9,3 +10,14 @@ sensor: heater: name: Heater update_interval: 15s + +button: + - platform: template + name: "Test HTU21D Actions" + on_press: + - htu21d.set_heater: + id: htu21d_sensor + status: true + - htu21d.set_heater_level: + id: htu21d_sensor + level: 5 From 0262d20bbe4bdbac88666e90e231d25f94ff72ea Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:26:47 -0400 Subject: [PATCH 1895/2030] [mlx90393] Remove call to non-existent set_drdy_pin method (#15381) --- esphome/components/mlx90393/sensor.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/esphome/components/mlx90393/sensor.py b/esphome/components/mlx90393/sensor.py index d93c379506..293a133c3d 100644 --- a/esphome/components/mlx90393/sensor.py +++ b/esphome/components/mlx90393/sensor.py @@ -130,9 +130,6 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) - if CONF_DRDY_PIN in config: - pin = await cg.gpio_pin_expression(config[CONF_DRDY_PIN]) - cg.add(var.set_drdy_pin(pin)) cg.add(var.set_gain(GAIN[config[CONF_GAIN]])) cg.add(var.set_oversampling(config[CONF_OVERSAMPLING])) cg.add(var.set_filter(config[CONF_FILTER])) From f7222a0e6cc53b5b5d92959c97b73b99e7c18ef3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Apr 2026 19:28:30 +0000 Subject: [PATCH 1896/2030] Bump ruff from 0.15.8 to 0.15.9 (#15385) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .pre-commit-config.yaml | 2 +- requirements_test.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4729f211c..4ff1685ea7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,7 +11,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit # Ruff version. - rev: v0.15.8 + rev: v0.15.9 hooks: # Run the linter. - id: ruff diff --git a/requirements_test.txt b/requirements_test.txt index 3b277e214d..a191378dd7 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,6 +1,6 @@ pylint==4.0.5 flake8==7.3.0 # also change in .pre-commit-config.yaml when updating -ruff==0.15.8 # also change in .pre-commit-config.yaml when updating +ruff==0.15.9 # also change in .pre-commit-config.yaml when updating pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit From dde472b0cf24d2f8f8964b6e816516a9e4d31b33 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:28:44 -0400 Subject: [PATCH 1897/2030] [pipsolar] Fix set_level action passing string to cv.use_id (#15380) --- esphome/components/pipsolar/output/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/pipsolar/output/__init__.py b/esphome/components/pipsolar/output/__init__.py index 81e99e15a2..4ae8d9d487 100644 --- a/esphome/components/pipsolar/output/__init__.py +++ b/esphome/components/pipsolar/output/__init__.py @@ -94,7 +94,7 @@ async def to_code(config): SetOutputAction, cv.Schema( { - cv.Required(CONF_ID): cv.use_id(CONF_ID), + cv.Required(CONF_ID): cv.use_id(PipsolarOutput), cv.Required(CONF_VALUE): cv.templatable(cv.positive_float), } ), From 6b89998b6058b444c9de20ab7d8ac023538f77dc Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:29:33 -0400 Subject: [PATCH 1898/2030] [template] Fix cover position_action overridden by has_position default (#15379) --- esphome/components/template/cover/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/esphome/components/template/cover/__init__.py b/esphome/components/template/cover/__init__.py index cfc19c00cd..ea4da4e73c 100644 --- a/esphome/components/template/cover/__init__.py +++ b/esphome/components/template/cover/__init__.py @@ -108,7 +108,6 @@ async def to_code(config): cg.add(var.set_optimistic(config[CONF_OPTIMISTIC])) cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE])) cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) - cg.add(var.set_has_position(config[CONF_HAS_POSITION])) @automation.register_action( From 90624e6eca424a7b98afdbdbf924aa862c35702a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:34:27 -0400 Subject: [PATCH 1899/2030] [deep_sleep] Fix wakeup_pin_mode rejecting lowercase on ESP32/BK72XX (#15384) --- esphome/components/deep_sleep/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index 4098fd3fb8..16329bb0fa 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -266,8 +266,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_WAKEUP_PIN): validate_wakeup_pin, cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All( cv.only_on([PLATFORM_ESP32, PLATFORM_BK72XX]), - cv.enum(WAKEUP_PIN_MODES), - upper=True, + cv.enum(WAKEUP_PIN_MODES, upper=True), ), cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All( cv.only_on_esp32, From c82166e5f35acfad339c7a16f952efc8ee0de151 Mon Sep 17 00:00:00 2001 From: Thom Wiggers <thom@thomwiggers.nl> Date: Thu, 2 Apr 2026 22:06:49 +0200 Subject: [PATCH 1900/2030] [dsmr] Allow setting MBUS id for thermal sensors in DSMR component (#7519) Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- CODEOWNERS | 2 +- esphome/components/dsmr/__init__.py | 5 ++++- tests/components/dsmr/common.yaml | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index fffe5ce91c..c466204b66 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -142,7 +142,7 @@ esphome/components/dlms_meter/* @SimonFischer04 esphome/components/dps310/* @kbx81 esphome/components/ds1307/* @badbadc0ffee esphome/components/ds2484/* @mrk-its -esphome/components/dsmr/* @glmnet @PolarGoose @zuidwijk +esphome/components/dsmr/* @glmnet @PolarGoose esphome/components/duty_time/* @dudanov esphome/components/ee895/* @Stock-M esphome/components/ektf2232/touchscreen/* @jesserockz diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index 7d76856f28..b1ff9794a3 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -4,7 +4,7 @@ from esphome.components import uart import esphome.config_validation as cv from esphome.const import CONF_ID, CONF_RECEIVE_TIMEOUT, CONF_UART_ID -CODEOWNERS = ["@glmnet", "@zuidwijk", "@PolarGoose"] +CODEOWNERS = ["@glmnet", "@PolarGoose"] MULTI_CONF = True @@ -16,6 +16,7 @@ CONF_DECRYPTION_KEY = "decryption_key" CONF_DSMR_ID = "dsmr_id" CONF_GAS_MBUS_ID = "gas_mbus_id" CONF_WATER_MBUS_ID = "water_mbus_id" +CONF_THERMAL_MBUS_ID = "thermal_mbus_id" CONF_MAX_TELEGRAM_LENGTH = "max_telegram_length" CONF_REQUEST_INTERVAL = "request_interval" CONF_REQUEST_PIN = "request_pin" @@ -35,6 +36,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_CRC_CHECK, default=True): cv.boolean, cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, cv.Optional(CONF_WATER_MBUS_ID, default=2): cv.int_, + cv.Optional(CONF_THERMAL_MBUS_ID, default=3): cv.int_, cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_, cv.Optional(CONF_REQUEST_PIN): pins.gpio_output_pin_schema, cv.Optional( @@ -64,6 +66,7 @@ async def to_code(config): cg.add_build_flag("-DDSMR_GAS_MBUS_ID=" + str(config[CONF_GAS_MBUS_ID])) cg.add_build_flag("-DDSMR_WATER_MBUS_ID=" + str(config[CONF_WATER_MBUS_ID])) + cg.add_build_flag("-DDSMR_THERMAL_MBUS_ID=" + str(config[CONF_THERMAL_MBUS_ID])) # DSMR Parser cg.add_library("esphome/dsmr_parser", "1.1.0") diff --git a/tests/components/dsmr/common.yaml b/tests/components/dsmr/common.yaml index d11ce37d59..962800d7b0 100644 --- a/tests/components/dsmr/common.yaml +++ b/tests/components/dsmr/common.yaml @@ -13,3 +13,4 @@ dsmr: request_pin: ${request_pin} request_interval: 20s receive_timeout: 100ms + thermal_mbus_id: 3 From 63710a4cb70c3071e5664eeed57e374b91b5c1da Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 2 Apr 2026 10:10:16 -1000 Subject: [PATCH 1901/2030] [spi] Add spi0 and spi1 to reserved IDs for RP2040 compatibility (#15388) --- esphome/config_validation.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 45d2cd8117..09f460f46b 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -244,6 +244,8 @@ RESERVED_IDS = [ "open", "setup", "loop", + "spi0", + "spi1", "uart0", "uart1", "uart2", From 1e72f0ee5aa347214d6e5476d26864758e912d83 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:17:20 +0200 Subject: [PATCH 1902/2030] [nextion] Gate waveform code behind `USE_NEXTION_WAVEFORM`, use `StaticRingBuffer` (#15273) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/nextion/nextion.cpp | 53 ++++++++----- esphome/components/nextion/nextion.h | 16 +++- esphome/components/nextion/nextion_base.h | 2 + .../components/nextion/nextion_commands.cpp | 2 + .../nextion/nextion_component_base.h | 6 ++ esphome/components/nextion/sensor/__init__.py | 18 ++--- .../nextion/sensor/nextion_sensor.cpp | 78 ++++++++++--------- .../nextion/sensor/nextion_sensor.h | 23 ++++-- esphome/core/defines.h | 1 + 9 files changed, 125 insertions(+), 74 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index ab268fed7f..4a15cbe64f 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -150,10 +150,12 @@ void Nextion::reset_(bool reset_nextion) { delete entry; // NOLINT(cppcoreguidelines-owning-memory) } this->nextion_queue_.clear(); +#ifdef USE_NEXTION_WAVEFORM for (auto *entry : this->waveform_queue_) { delete entry; // NOLINT(cppcoreguidelines-owning-memory) } this->waveform_queue_.clear(); +#endif // USE_NEXTION_WAVEFORM } void Nextion::dump_config() { @@ -496,20 +498,21 @@ void Nextion::process_nextion_commands_() { ESP_LOGW(TAG, "Invalid baud rate"); break; case 0x12: // invalid Waveform ID or Channel # was used +#ifdef USE_NEXTION_WAVEFORM if (this->waveform_queue_.empty()) { ESP_LOGW(TAG, "Waveform ID/ch used but no sensor queued"); } else { auto &nb = this->waveform_queue_.front(); NextionComponentBase *component = nb->component; - ESP_LOGW(TAG, "Invalid waveform ID %d/ch %d", component->get_component_id(), component->get_wave_channel_id()); - ESP_LOGN(TAG, "Remove waveform ID %d/ch %d", component->get_component_id(), component->get_wave_channel_id()); - delete nb; // NOLINT(cppcoreguidelines-owning-memory) - this->waveform_queue_.pop_front(); + this->waveform_queue_.pop(); } +#else // USE_NEXTION_WAVEFORM + ESP_LOGW(TAG, "Waveform ID/ch error but waveform not enabled"); +#endif // USE_NEXTION_WAVEFORM break; case 0x1A: // variable name invalid ESP_LOGW(TAG, "Invalid variable name"); @@ -812,29 +815,30 @@ void Nextion::process_nextion_commands_() { } case 0xFD: { // data transparent transmit finished ESP_LOGVV(TAG, "Data transmit done"); +#ifdef USE_NEXTION_WAVEFORM this->check_pending_waveform_(); +#endif // USE_NEXTION_WAVEFORM break; } case 0xFE: { // data transparent transmit ready ESP_LOGVV(TAG, "Ready for transmit"); +#ifdef USE_NEXTION_WAVEFORM if (this->waveform_queue_.empty()) { ESP_LOGE(TAG, "No waveforms queued"); break; } - auto &nb = this->waveform_queue_.front(); auto *component = nb->component; - size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size() - : 255; // ADDT command can only send 255 - + size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size() : 255; this->write_array(component->get_wave_buffer().data(), static_cast<int>(buffer_to_send)); - ESP_LOGN(TAG, "Send waveform: component id %d, waveform id %d, size %zu", component->get_component_id(), component->get_wave_channel_id(), buffer_to_send); - component->clear_wave_buffer(buffer_to_send); delete nb; // NOLINT(cppcoreguidelines-owning-memory) - this->waveform_queue_.pop_front(); + this->waveform_queue_.pop(); +#else // USE_NEXTION_WAVEFORM + ESP_LOGW(TAG, "Waveform transmit ready but waveform not enabled"); +#endif // USE_NEXTION_WAVEFORM break; } default: @@ -934,8 +938,13 @@ void Nextion::all_components_send_state_(bool force_update) { binarysensortype->send_state_to_nextion(); } for (auto *sensortype : this->sensortype_) { - if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_channel_id() == 0) +#ifdef USE_NEXTION_WAVEFORM + if ((force_update || sensortype->get_needs_to_send_update()) && sensortype->get_wave_channel_id() == UINT8_MAX) { +#else // USE_NEXTION_WAVEFORM + if (force_update || sensortype->get_needs_to_send_update()) { +#endif // USE_NEXTION_WAVEFORM sensortype->send_state_to_nextion(); + } } for (auto *switchtype : this->switchtype_) { if (force_update || switchtype->get_needs_to_send_update()) @@ -1239,13 +1248,11 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) { } } +#ifdef USE_NEXTION_WAVEFORM /** - * @brief Add addt command to the queue + * @brief Add addt command to the waveform queue. * - * @param component_id The waveform component id - * @param wave_chan_id The waveform channel to send it to - * @param buffer_to_send The buffer size - * @param buffer_size The buffer data + * @param component Pointer to the Nextion component with waveform data to send. */ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) { if ((!this->is_setup() && !this->connection_state_.ignore_is_setup_) || this->is_sleeping()) @@ -1262,7 +1269,11 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) { nextion_queue->component = component; nextion_queue->queue_time = App.get_loop_component_start_time(); - this->waveform_queue_.push_back(nextion_queue); + if (!this->waveform_queue_.push(nextion_queue)) { + ESP_LOGW(TAG, "Waveform queue full, drop"); + delete nextion_queue; // NOLINT(cppcoreguidelines-owning-memory) + return; + } if (this->waveform_queue_.size() == 1) this->check_pending_waveform_(); } @@ -1273,17 +1284,17 @@ void Nextion::check_pending_waveform_() { auto *nb = this->waveform_queue_.front(); auto *component = nb->component; - size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size() - : 255; // ADDT command can only send 255 + size_t buffer_to_send = component->get_wave_buffer_size() < 255 ? component->get_wave_buffer_size() : 255; char command[24]; // "addt " + uint8 + "," + uint8 + "," + uint8 + null = max 17 chars buf_append_printf(command, sizeof(command), 0, "addt %u,%u,%zu", component->get_component_id(), component->get_wave_channel_id(), buffer_to_send); if (!this->send_command_(command)) { delete nb; // NOLINT(cppcoreguidelines-owning-memory) - this->waveform_queue_.pop_front(); + this->waveform_queue_.pop(); } } +#endif // USE_NEXTION_WAVEFORM void Nextion::set_writer(const nextion_writer_t &writer) { this->writer_ = writer; } diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index b3ecbf46b1..d910389289 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -9,6 +9,10 @@ #include "esphome/core/defines.h" #include "esphome/core/time.h" +#ifdef USE_NEXTION_WAVEFORM +#include "esphome/core/helpers.h" +#endif // USE_NEXTION_WAVEFORM + #include "nextion_base.h" #include "nextion_component.h" @@ -602,6 +606,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe */ void disable_component_touch(const char *component); +#ifdef USE_NEXTION_WAVEFORM /** * Add waveform data to a waveform component * @param component_id The integer component id. @@ -611,6 +616,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void add_waveform_data(uint8_t component_id, uint8_t channel_number, uint8_t value); void open_waveform_channel(uint8_t component_id, uint8_t channel_number, uint8_t value); +#endif // USE_NEXTION_WAVEFORM /** * Display a picture at coordinates. @@ -1205,7 +1211,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe void add_to_get_queue(NextionComponentBase *component) override; +#ifdef USE_NEXTION_WAVEFORM void add_addt_command_to_queue(NextionComponentBase *component) override; +#endif // USE_NEXTION_WAVEFORM void update_components_by_prefix(const std::string &prefix); @@ -1391,7 +1399,11 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe #endif // USE_NEXTION_COMMAND_SPACING std::list<NextionQueue *> nextion_queue_; - std::list<NextionQueue *> waveform_queue_; +#ifdef USE_NEXTION_WAVEFORM + /// Fixed-size ring buffer for waveform queue. Nextion supports at most 4 waveform + /// channels (IDs 0-3), so 4 entries is both the correct maximum and a safe default. + StaticRingBuffer<NextionQueue *, 4> waveform_queue_; +#endif // USE_NEXTION_WAVEFORM uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag); void all_components_send_state_(bool force_update = false); uint32_t comok_sent_ = 0; @@ -1460,7 +1472,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe const std::string &variable_name_to_send, const std::string &state_value, bool is_sleep_safe = false); +#ifdef USE_NEXTION_WAVEFORM void check_pending_waveform_(); +#endif // USE_NEXTION_WAVEFORM #ifdef USE_NEXTION_TFT_UPLOAD #ifdef USE_ESP8266 diff --git a/esphome/components/nextion/nextion_base.h b/esphome/components/nextion/nextion_base.h index 2c516fc80f..4a2dc90d40 100644 --- a/esphome/components/nextion/nextion_base.h +++ b/esphome/components/nextion/nextion_base.h @@ -33,7 +33,9 @@ class NextionBase { const std::string &variable_name_to_send, const std::string &state_value) = 0; +#ifdef USE_NEXTION_WAVEFORM virtual void add_addt_command_to_queue(NextionComponentBase *component) = 0; +#endif // USE_NEXTION_WAVEFORM virtual void add_to_get_queue(NextionComponentBase *component) = 0; diff --git a/esphome/components/nextion/nextion_commands.cpp b/esphome/components/nextion/nextion_commands.cpp index a7e65b5ddf..a332d342ee 100644 --- a/esphome/components/nextion/nextion_commands.cpp +++ b/esphome/components/nextion/nextion_commands.cpp @@ -217,6 +217,7 @@ void Nextion::set_component_value(const char *component, int32_t value) { this->add_no_result_to_queue_with_printf_(".val", "%s.val=%" PRId32, component, value); } +#ifdef USE_NEXTION_WAVEFORM void Nextion::add_waveform_data(uint8_t component_id, uint8_t channel_number, uint8_t value) { this->add_no_result_to_queue_with_printf_("add", "add %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, channel_number, value); @@ -226,6 +227,7 @@ void Nextion::open_waveform_channel(uint8_t component_id, uint8_t channel_number this->add_no_result_to_queue_with_printf_("addt", "addt %" PRIu8 ",%" PRIu8 ",%" PRIu8, component_id, channel_number, value); } +#endif // USE_NEXTION_WAVEFORM void Nextion::set_component_coordinates(const char *component, uint16_t x, uint16_t y) { this->add_no_result_to_queue_with_printf_(".xcen", "%s.xcen=%" PRIu16, component, x); diff --git a/esphome/components/nextion/nextion_component_base.h b/esphome/components/nextion/nextion_component_base.h index c1d0ae8ed1..6676d01920 100644 --- a/esphome/components/nextion/nextion_component_base.h +++ b/esphome/components/nextion/nextion_component_base.h @@ -64,6 +64,7 @@ class NextionComponentBase { uint8_t get_component_id() const { return this->component_id_; } void set_component_id(uint8_t component_id) { this->component_id_ = component_id; } +#ifdef USE_NEXTION_WAVEFORM uint8_t get_wave_channel_id() const { return this->wave_chan_id_; } void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; } @@ -76,6 +77,7 @@ class NextionComponentBase { this->wave_buffer_.erase(this->wave_buffer_.begin(), this->wave_buffer_.begin() + buffer_sent); } } +#endif // USE_NEXTION_WAVEFORM const std::string &get_variable_name() const { return this->variable_name_; } const std::string &get_variable_name_to_send() const { return this->variable_name_to_send_; } @@ -85,19 +87,23 @@ class NextionComponentBase { virtual void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion){}; virtual void send_state_to_nextion(){}; bool get_needs_to_send_update() const { return this->needs_to_send_update_; } +#ifdef USE_NEXTION_WAVEFORM // Remove before 2026.10.0 ESPDEPRECATED("Use get_wave_channel_id() instead. Will be removed in 2026.10.0", "2026.4.0") uint8_t get_wave_chan_id() const { return this->get_wave_channel_id(); } void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; } +#endif // USE_NEXTION_WAVEFORM protected: std::string variable_name_; std::string variable_name_to_send_; uint8_t component_id_ = 0; +#ifdef USE_NEXTION_WAVEFORM uint8_t wave_chan_id_ = UINT8_MAX; std::vector<uint8_t> wave_buffer_; int wave_max_length_ = 255; +#endif // USE_NEXTION_WAVEFORM bool needs_to_send_update_; }; diff --git a/esphome/components/nextion/sensor/__init__.py b/esphome/components/nextion/sensor/__init__.py index cab531f1db..7351d8f1d5 100644 --- a/esphome/components/nextion/sensor/__init__.py +++ b/esphome/components/nextion/sensor/__init__.py @@ -85,16 +85,16 @@ async def to_code(config): cg.add(var.set_component_id(config[CONF_COMPONENT_ID])) if CONF_WAVE_CHANNEL_ID in config: + cg.add_define("USE_NEXTION_WAVEFORM") cg.add(var.set_wave_channel_id(config[CONF_WAVE_CHANNEL_ID])) - - if CONF_WAVEFORM_SEND_LAST_VALUE in config: - cg.add(var.set_waveform_send_last_value(config[CONF_WAVEFORM_SEND_LAST_VALUE])) - - if CONF_WAVE_MAX_VALUE in config: - cg.add(var.set_wave_max_value(config[CONF_WAVE_MAX_VALUE])) - - if CONF_WAVE_MAX_LENGTH in config: - cg.add(var.set_wave_max_length(config[CONF_WAVE_MAX_LENGTH])) + if CONF_WAVEFORM_SEND_LAST_VALUE in config: + cg.add( + var.set_waveform_send_last_value(config[CONF_WAVEFORM_SEND_LAST_VALUE]) + ) + if CONF_WAVE_MAX_VALUE in config: + cg.add(var.set_wave_max_value(config[CONF_WAVE_MAX_VALUE])) + if CONF_WAVE_MAX_LENGTH in config: + cg.add(var.set_wave_max_length(config[CONF_WAVE_MAX_LENGTH])) @automation.register_action( diff --git a/esphome/components/nextion/sensor/nextion_sensor.cpp b/esphome/components/nextion/sensor/nextion_sensor.cpp index d4fad86286..ca657522f9 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.cpp +++ b/esphome/components/nextion/sensor/nextion_sensor.cpp @@ -10,37 +10,44 @@ void NextionSensor::process_sensor(const std::string &variable_name, int state) if (!this->nextion_->is_setup()) return; - if (this->wave_chan_id_ == UINT8_MAX && this->variable_name_ == variable_name) { +#ifdef USE_NEXTION_WAVEFORM + if (this->wave_chan_id_ == UINT8_MAX && this->variable_name_ == variable_name) +#else // USE_NEXTION_WAVEFORM + if (this->variable_name_ == variable_name) +#endif // USE_NEXTION_WAVEFORM + { this->publish_state(state); ESP_LOGD(TAG, "Sensor: %s=%d", variable_name.c_str(), state); } } +#ifdef USE_NEXTION_WAVEFORM void NextionSensor::add_to_wave_buffer(float state) { this->needs_to_send_update_ = true; - int wave_state = (int) ((state / (float) this->wave_maxvalue_) * 100); - - wave_buffer_.push_back(wave_state); - + this->wave_buffer_.push_back(wave_state); if (this->wave_buffer_.size() > (size_t) this->wave_max_length_) { this->wave_buffer_.erase(this->wave_buffer_.begin()); } } +#endif // USE_NEXTION_WAVEFORM void NextionSensor::update() { if (!this->nextion_->is_setup() || this->nextion_->is_updating()) return; +#ifdef USE_NEXTION_WAVEFORM if (this->wave_chan_id_ == UINT8_MAX) { this->nextion_->add_to_get_queue(this); } else { if (this->send_last_value_) { this->add_to_wave_buffer(this->last_value_); } - this->wave_update_(); } +#else // USE_NEXTION_WAVEFORM + this->nextion_->add_to_get_queue(this); +#endif // USE_NEXTION_WAVEFORM } void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { @@ -50,61 +57,60 @@ void NextionSensor::set_state(float state, bool publish, bool send_to_nextion) { if (std::isnan(state)) return; - if (this->wave_chan_id_ == UINT8_MAX) { - if (send_to_nextion) { - if (this->nextion_->is_sleeping() || !this->component_flags_.visible) { - this->needs_to_send_update_ = true; - } else { - this->needs_to_send_update_ = false; - - if (this->precision_ > 0) { - double to_multiply = pow(10, this->precision_); - int state_value = (int) (state * to_multiply); - - this->nextion_->add_no_result_to_queue_with_set(this, (int) state_value); - } else { - this->nextion_->add_no_result_to_queue_with_set(this, (int) state); - } - } - } - } else { +#ifdef USE_NEXTION_WAVEFORM + if (this->wave_chan_id_ != UINT8_MAX) { + // Waveform sensor — buffer the value, don't send directly. if (this->send_last_value_) { this->last_value_ = state; // Update will handle setting the buffer } else { this->add_to_wave_buffer(state); } + this->update_component_settings(); + return; + } +#endif // USE_NEXTION_WAVEFORM + + if (send_to_nextion) { + if (this->nextion_->is_sleeping() || !this->component_flags_.visible) { + this->needs_to_send_update_ = true; + } else { + this->needs_to_send_update_ = false; + if (this->precision_ > 0) { + double to_multiply = pow(10, this->precision_); + int state_value = (int) (state * to_multiply); + this->nextion_->add_no_result_to_queue_with_set(this, (int) state_value); + } else { + this->nextion_->add_no_result_to_queue_with_set(this, (int) state); + } + } } float published_state = state; - if (this->wave_chan_id_ == UINT8_MAX) { - if (publish) { - if (this->precision_ > 0) { - double to_multiply = pow(10, -this->precision_); - published_state = (float) (state * to_multiply); - } - - this->publish_state(published_state); + if (publish) { + if (this->precision_ > 0) { + double to_multiply = pow(10, -this->precision_); + published_state = (float) (state * to_multiply); } + this->publish_state(published_state); } this->update_component_settings(); ESP_LOGN(TAG, "Write: %s=%lf", this->variable_name_.c_str(), published_state); } +#ifdef USE_NEXTION_WAVEFORM void NextionSensor::wave_update_() { if (this->nextion_->is_sleeping() || this->wave_buffer_.empty()) { return; } - #ifdef NEXTION_PROTOCOL_LOG size_t buffer_to_send = this->wave_buffer_.size() < 255 ? this->wave_buffer_.size() : 255; // ADDT command can only send 255 - ESP_LOGN(TAG, "Wave update: %zu/%zu vals to comp %d ch %d", buffer_to_send, this->wave_buffer_.size(), this->component_id_, this->wave_chan_id_); -#endif - +#endif // NEXTION_PROTOCOL_LOG this->nextion_->add_addt_command_to_queue(this); } +#endif // USE_NEXTION_WAVEFORM } // namespace esphome::nextion diff --git a/esphome/components/nextion/sensor/nextion_sensor.h b/esphome/components/nextion/sensor/nextion_sensor.h index f1a3ff72ec..72e3982b3a 100644 --- a/esphome/components/nextion/sensor/nextion_sensor.h +++ b/esphome/components/nextion/sensor/nextion_sensor.h @@ -15,22 +15,30 @@ class NextionSensor : public NextionComponent, public sensor::Sensor, public Pol void update_component() override { this->update(); } void update() override; - void add_to_wave_buffer(float state); void set_precision(uint8_t precision) { this->precision_ = precision; } void set_component_id(uint8_t component_id) { this->component_id_ = component_id; } - void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; } - void set_wave_max_value(uint32_t wave_maxvalue) { this->wave_maxvalue_ = wave_maxvalue; } void process_sensor(const std::string &variable_name, int state) override; void set_state(float state) override { this->set_state(state, true, true); } void set_state(float state, bool publish) override { this->set_state(state, publish, true); } void set_state(float state, bool publish, bool send_to_nextion) override; + NextionQueueType get_queue_type() const override { +#ifdef USE_NEXTION_WAVEFORM + return this->wave_chan_id_ == UINT8_MAX ? NextionQueueType::SENSOR : NextionQueueType::WAVEFORM_SENSOR; +#else // USE_NEXTION_WAVEFORM + return NextionQueueType::SENSOR; +#endif // USE_NEXTION_WAVEFORM + } + +#ifdef USE_NEXTION_WAVEFORM + void add_to_wave_buffer(float state); + void set_wave_channel_id(uint8_t wave_chan_id) { this->wave_chan_id_ = wave_chan_id; } + void set_wave_max_value(uint32_t wave_maxvalue) { this->wave_maxvalue_ = wave_maxvalue; } void set_waveform_send_last_value(bool send_last_value) { this->send_last_value_ = send_last_value; } void set_wave_max_length(int wave_max_length) { this->wave_max_length_ = wave_max_length; } - NextionQueueType get_queue_type() const override { - return this->wave_chan_id_ == UINT8_MAX ? NextionQueueType::SENSOR : NextionQueueType::WAVEFORM_SENSOR; - } +#endif // USE_NEXTION_WAVEFORM + void set_state_from_string(const std::string &state_value, bool publish, bool send_to_nextion) override {} void set_state_from_int(int state_value, bool publish, bool send_to_nextion) override { this->set_state(state_value, publish, send_to_nextion); @@ -38,10 +46,11 @@ class NextionSensor : public NextionComponent, public sensor::Sensor, public Pol protected: uint8_t precision_ = 0; +#ifdef USE_NEXTION_WAVEFORM uint32_t wave_maxvalue_ = 255; - float last_value_ = 0; bool send_last_value_ = true; void wave_update_(); +#endif // USE_NEXTION_WAVEFORM }; } // namespace esphome::nextion diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 23e65f55bc..faa8c6d4b0 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -123,6 +123,7 @@ #define USE_NEXTION_MAX_COMMANDS_PER_LOOP #define USE_NEXTION_MAX_QUEUE_SIZE #define USE_NEXTION_TFT_UPLOAD +#define USE_NEXTION_WAVEFORM #define USE_NUMBER #define USE_OUTPUT #define USE_POWER_SUPPLY From 4134763f3455929a837465c037fca0ab55faa817 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:32:10 -0400 Subject: [PATCH 1903/2030] [at581x][canbus] Fix walrus operator skipping falsy config values (#15390) --- esphome/components/at581x/__init__.py | 4 ++-- esphome/components/canbus/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/at581x/__init__.py b/esphome/components/at581x/__init__.py index 0780814ea6..34e6570628 100644 --- a/esphome/components/at581x/__init__.py +++ b/esphome/components/at581x/__init__.py @@ -177,7 +177,7 @@ async def at581x_settings_to_code(config, action_id, template_arg, args): template_ = int(template_ / 1000000) cg.add(var.set_frequency(template_)) - if sens_dist := config.get(CONF_SENSING_DISTANCE): + if (sens_dist := config.get(CONF_SENSING_DISTANCE)) is not None: template_ = await cg.templatable(sens_dist, args, int) cg.add(var.set_sensing_distance(template_)) @@ -209,7 +209,7 @@ async def at581x_settings_to_code(config, action_id, template_arg, args): template_ = int(template_) cg.add(var.set_trigger_keep(template_)) - if stage_gain := config.get(CONF_STAGE_GAIN): + if (stage_gain := config.get(CONF_STAGE_GAIN)) is not None: template_ = await cg.templatable(stage_gain, args, int) cg.add(var.set_stage_gain(template_)) diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index c94c8647a9..7d3bf78f49 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -161,7 +161,7 @@ async def canbus_action_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_CANBUS_ID]) - if can_id := config.get(CONF_CAN_ID): + if (can_id := config.get(CONF_CAN_ID)) is not None: can_id = await cg.templatable(can_id, args, cg.uint32) cg.add(var.set_can_id(can_id)) cg.add(var.set_use_extended_id(config[CONF_USE_EXTENDED_ID])) From 4d0d3cc271754930b6c33cf0e02b439173af6e3a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:53:53 -0400 Subject: [PATCH 1904/2030] [sen5x] Remove dead voc_baseline config option (#15391) --- esphome/components/sen5x/sensor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/esphome/components/sen5x/sensor.py b/esphome/components/sen5x/sensor.py index 9fe51121f1..ce35cf5bf1 100644 --- a/esphome/components/sen5x/sensor.py +++ b/esphome/components/sen5x/sensor.py @@ -25,7 +25,6 @@ from esphome.const import ( CONF_TEMPERATURE_COMPENSATION, CONF_TIME_CONSTANT, CONF_VOC, - CONF_VOC_BASELINE, DEVICE_CLASS_AQI, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_PM1, @@ -165,7 +164,6 @@ CONFIG_SCHEMA = ( gain_factor=230, ), cv.Optional(CONF_STORE_BASELINE, default=True): cv.boolean, - cv.Optional(CONF_VOC_BASELINE): cv.hex_uint16_t, cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, icon=ICON_THERMOMETER, From be3e0c27bfc0910f1581ab9fb837ecff113cbb50 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Thu, 2 Apr 2026 11:28:12 -1000 Subject: [PATCH 1905/2030] [core] Inline fast path for enable_loop (#15392) --- esphome/core/component.cpp | 10 ++++------ esphome/core/component.h | 7 ++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 2b5aba2a7b..0f68f0c8e0 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -294,12 +294,10 @@ void Component::disable_loop() { App.disable_component_loop_(this); } } -void Component::enable_loop() { - if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE) { - ESP_LOGVV(TAG, "%s loop enabled", LOG_STR_ARG(this->get_component_log_str())); - this->set_component_state_(COMPONENT_STATE_LOOP); - App.enable_component_loop_(this); - } +void Component::enable_loop_slow_path_() { + ESP_LOGVV(TAG, "%s loop enabled", LOG_STR_ARG(this->get_component_log_str())); + this->set_component_state_(COMPONENT_STATE_LOOP); + App.enable_component_loop_(this); } void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // This method is thread and ISR-safe because: diff --git a/esphome/core/component.h b/esphome/core/component.h index f091f9434c..e2b7aa85d3 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -242,7 +242,10 @@ class Component { * @note Components should call this->enable_loop() on themselves, not on other components. * This ensures the component's state is properly updated along with the loop partition. */ - void enable_loop(); + void enable_loop() { + if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_LOOP_DONE) + this->enable_loop_slow_path_(); + } /** Thread and ISR-safe version of enable_loop() that can be called from any context. * @@ -344,6 +347,8 @@ class Component { virtual void call_setup(); void call_dump_config_(); + void enable_loop_slow_path_(); + /// Helper to set component state (clears state bits and sets new state) inline void set_component_state_(uint8_t state) { this->component_state_ &= ~COMPONENT_STATE_MASK; From 710186998baa241b360f30ad08e90218eaea8a3a Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Thu, 2 Apr 2026 18:12:05 -0500 Subject: [PATCH 1906/2030] [ota] Use modernized namespace syntax (#15398) --- esphome/components/ota/automation.h | 6 ++---- esphome/components/ota/ota_backend.cpp | 6 ++---- esphome/components/ota/ota_backend.h | 6 ++---- esphome/components/ota/ota_backend_arduino_libretiny.cpp | 7 ++----- esphome/components/ota/ota_backend_arduino_libretiny.h | 7 ++----- esphome/components/ota/ota_backend_arduino_rp2040.cpp | 7 ++----- esphome/components/ota/ota_backend_arduino_rp2040.h | 7 ++----- esphome/components/ota/ota_backend_esp_idf.cpp | 6 ++---- esphome/components/ota/ota_backend_esp_idf.h | 6 ++---- 9 files changed, 18 insertions(+), 40 deletions(-) diff --git a/esphome/components/ota/automation.h b/esphome/components/ota/automation.h index 92c0050ba0..29a8878136 100644 --- a/esphome/components/ota/automation.h +++ b/esphome/components/ota/automation.h @@ -4,8 +4,7 @@ #include "esphome/core/automation.h" -namespace esphome { -namespace ota { +namespace esphome::ota { class OTAStateChangeTrigger final : public Trigger<OTAState>, public OTAStateListener { public: @@ -67,6 +66,5 @@ class OTAErrorTrigger final : public Trigger<uint8_t>, public OTAStateListener { OTAComponent *parent_; }; -} // namespace ota -} // namespace esphome +} // namespace esphome::ota #endif diff --git a/esphome/components/ota/ota_backend.cpp b/esphome/components/ota/ota_backend.cpp index 01a18a58ef..17949de642 100644 --- a/esphome/components/ota/ota_backend.cpp +++ b/esphome/components/ota/ota_backend.cpp @@ -1,7 +1,6 @@ #include "ota_backend.h" -namespace esphome { -namespace ota { +namespace esphome::ota { #ifdef USE_OTA_STATE_LISTENER OTAGlobalCallback *global_ota_callback{nullptr}; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) @@ -34,5 +33,4 @@ void OTAComponent::notify_state_(OTAState state, float progress, uint8_t error) } #endif -} // namespace ota -} // namespace esphome +} // namespace esphome::ota diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index ab0ec58e8a..db79370bb3 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -8,8 +8,7 @@ #include <vector> #endif -namespace esphome { -namespace ota { +namespace esphome::ota { enum OTAResponseTypes { OTA_RESPONSE_OK = 0x00, @@ -117,5 +116,4 @@ OTAGlobalCallback *get_global_ota_callback(); // - notify_state_deferred_() when in separate task (e.g., web_server OTA) // This ensures proper listener execution in all contexts. #endif -} // namespace ota -} // namespace esphome +} // namespace esphome::ota diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.cpp b/esphome/components/ota/ota_backend_arduino_libretiny.cpp index d364f75007..dcd71e92dd 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.cpp +++ b/esphome/components/ota/ota_backend_arduino_libretiny.cpp @@ -7,8 +7,7 @@ #include <Update.h> -namespace esphome { -namespace ota { +namespace esphome::ota { static const char *const TAG = "ota.arduino_libretiny"; @@ -66,7 +65,5 @@ OTAResponseTypes ArduinoLibreTinyOTABackend::end() { void ArduinoLibreTinyOTABackend::abort() { Update.abort(); } -} // namespace ota -} // namespace esphome - +} // namespace esphome::ota #endif // USE_LIBRETINY diff --git a/esphome/components/ota/ota_backend_arduino_libretiny.h b/esphome/components/ota/ota_backend_arduino_libretiny.h index 4514bf84bd..3d426e6759 100644 --- a/esphome/components/ota/ota_backend_arduino_libretiny.h +++ b/esphome/components/ota/ota_backend_arduino_libretiny.h @@ -4,8 +4,7 @@ #include "esphome/core/defines.h" -namespace esphome { -namespace ota { +namespace esphome::ota { class ArduinoLibreTinyOTABackend final { public: @@ -22,7 +21,5 @@ class ArduinoLibreTinyOTABackend final { std::unique_ptr<ArduinoLibreTinyOTABackend> make_ota_backend(); -} // namespace ota -} // namespace esphome - +} // namespace esphome::ota #endif // USE_LIBRETINY diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.cpp b/esphome/components/ota/ota_backend_arduino_rp2040.cpp index e2a57ec665..bc8ef812e6 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.cpp +++ b/esphome/components/ota/ota_backend_arduino_rp2040.cpp @@ -9,8 +9,7 @@ #include <Updater.h> -namespace esphome { -namespace ota { +namespace esphome::ota { static const char *const TAG = "ota.arduino_rp2040"; @@ -75,8 +74,6 @@ void ArduinoRP2040OTABackend::abort() { rp2040::preferences_prevent_write(false); } -} // namespace ota -} // namespace esphome - +} // namespace esphome::ota #endif // USE_RP2040 #endif // USE_ARDUINO diff --git a/esphome/components/ota/ota_backend_arduino_rp2040.h b/esphome/components/ota/ota_backend_arduino_rp2040.h index 0956cb4b4b..05bd2f5cc4 100644 --- a/esphome/components/ota/ota_backend_arduino_rp2040.h +++ b/esphome/components/ota/ota_backend_arduino_rp2040.h @@ -6,8 +6,7 @@ #include "esphome/core/defines.h" #include "esphome/core/macros.h" -namespace esphome { -namespace ota { +namespace esphome::ota { class ArduinoRP2040OTABackend final { public: @@ -24,8 +23,6 @@ class ArduinoRP2040OTABackend final { std::unique_ptr<ArduinoRP2040OTABackend> make_ota_backend(); -} // namespace ota -} // namespace esphome - +} // namespace esphome::ota #endif // USE_RP2040 #endif // USE_ARDUINO diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index 925bb39645..efaf810ca3 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -8,8 +8,7 @@ #include <esp_task_wdt.h> #include <spi_flash_mmap.h> -namespace esphome { -namespace ota { +namespace esphome::ota { std::unique_ptr<IDFOTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); } @@ -112,6 +111,5 @@ void IDFOTABackend::abort() { this->update_handle_ = 0; } -} // namespace ota -} // namespace esphome +} // namespace esphome::ota #endif // USE_ESP32 diff --git a/esphome/components/ota/ota_backend_esp_idf.h b/esphome/components/ota/ota_backend_esp_idf.h index a0f538afc0..d007bcd128 100644 --- a/esphome/components/ota/ota_backend_esp_idf.h +++ b/esphome/components/ota/ota_backend_esp_idf.h @@ -7,8 +7,7 @@ #include <esp_ota_ops.h> -namespace esphome { -namespace ota { +namespace esphome::ota { class IDFOTABackend final { public: @@ -29,6 +28,5 @@ class IDFOTABackend final { std::unique_ptr<IDFOTABackend> make_ota_backend(); -} // namespace ota -} // namespace esphome +} // namespace esphome::ota #endif // USE_ESP32 From af662da90d92f4e802cb6ae25372701b6cc22cd0 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 3 Apr 2026 11:28:45 +1000 Subject: [PATCH 1907/2030] [mipi_spi] Rotation and buffer size changes (#15047) --- esphome/components/const/__init__.py | 2 + esphome/components/display/__init__.py | 38 ++++ esphome/components/display/display.h | 2 +- esphome/components/image/__init__.py | 3 +- esphome/components/mipi/__init__.py | 70 ++++-- esphome/components/mipi_dsi/display.py | 3 +- esphome/components/mipi_dsi/mipi_dsi.cpp | 12 +- esphome/components/mipi_dsi/mipi_dsi.h | 2 - esphome/components/mipi_rgb/display.py | 3 +- esphome/components/mipi_rgb/mipi_rgb.cpp | 10 +- esphome/components/mipi_rgb/mipi_rgb.h | 2 - esphome/components/mipi_spi/display.py | 122 +++------- esphome/components/mipi_spi/mipi_spi.cpp | 10 +- esphome/components/mipi_spi/mipi_spi.h | 212 ++++++++++++------ tests/component_tests/display/__init__.py | 0 .../display/test_display_metadata.py | 81 +++++++ .../mipi_spi/test_display_metadata.py | 200 +++++++++++++++++ tests/component_tests/mipi_spi/test_init.py | 9 +- 18 files changed, 557 insertions(+), 224 deletions(-) create mode 100644 tests/component_tests/display/__init__.py create mode 100644 tests/component_tests/display/test_display_metadata.py create mode 100644 tests/component_tests/mipi_spi/test_display_metadata.py diff --git a/esphome/components/const/__init__.py b/esphome/components/const/__init__.py index 0eb37e3029..846d3fd883 100644 --- a/esphome/components/const/__init__.py +++ b/esphome/components/const/__init__.py @@ -32,4 +32,6 @@ ICON_CURRENT_DC = "mdi:current-dc" ICON_SOLAR_PANEL = "mdi:solar-panel" ICON_SOLAR_POWER = "mdi:solar-power" +KEY_METADATA = "metadata" + UNIT_AMPERE_HOUR = "Ah" diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 6367f88acc..4d79a0a31b 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -1,6 +1,9 @@ +from dataclasses import dataclass + from esphome import automation, core from esphome.automation import maybe_simple_id import esphome.codegen as cg +from esphome.components.const import KEY_METADATA import esphome.config_validation as cv from esphome.const import ( CONF_AUTO_CLEAR_ENABLED, @@ -16,7 +19,9 @@ from esphome.const import ( SCHEDULER_DONT_RUN, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.cpp_generator import MockObj +DOMAIN = "display" IS_PLATFORM_COMPONENT = True display_ns = cg.esphome_ns.namespace("display") @@ -146,6 +151,39 @@ async def setup_display_core_(var, config): cg.add(var.show_test_card()) +# Storage of display metadata in a central location, accessible via the id + + +@dataclass(frozen=True) +class DisplayMetaData: + width: int = 0 + height: int = 0 + has_writer: bool = False + has_hardware_rotation: bool = False + + +def get_all_display_metadata() -> dict[str, DisplayMetaData]: + """Get all display metadata.""" + return CORE.data.setdefault(DOMAIN, {}).setdefault(KEY_METADATA, {}) + + +def get_display_metadata(display_id: str) -> DisplayMetaData | None: + """Get display metadata by ID for use by other components.""" + return get_all_display_metadata().get(display_id, DisplayMetaData()) + + +def add_metadata( + id: str | MockObj, + width: int, + height: int, + has_writer: bool, + has_hardware_rotation: bool = False, +): + get_all_display_metadata()[str(id)] = DisplayMetaData( + width, height, has_writer, has_hardware_rotation + ) + + async def register_display(var, config): await cg.register_component(var, config) await setup_display_core_(var, config) diff --git a/esphome/components/display/display.h b/esphome/components/display/display.h index e40f6ec963..6e38300d0e 100644 --- a/esphome/components/display/display.h +++ b/esphome/components/display/display.h @@ -704,7 +704,7 @@ class Display : public PollingComponent { void add_on_page_change_trigger(DisplayOnPageChangeTrigger *t) { this->on_page_change_triggers_.push_back(t); } /// Internal method to set the display rotation with. - void set_rotation(DisplayRotation rotation); + virtual void set_rotation(DisplayRotation rotation); // Internal method to set display auto clearing. void set_auto_clear(bool auto_clear_enabled) { this->auto_clear_enabled_ = auto_clear_enabled; } diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 6fb0e46d93..4a5fcc385e 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -12,7 +12,7 @@ from PIL import Image, UnidentifiedImageError from esphome import core, external_files import esphome.codegen as cg -from esphome.components.const import CONF_BYTE_ORDER +from esphome.components.const import CONF_BYTE_ORDER, KEY_METADATA import esphome.config_validation as cv from esphome.const import ( CONF_DEFAULTS, @@ -53,7 +53,6 @@ CONF_CHROMA_KEY = "chroma_key" CONF_ALPHA_CHANNEL = "alpha_channel" CONF_INVERT_ALPHA = "invert_alpha" CONF_IMAGES = "images" -KEY_METADATA = "metadata" TRANSPARENCY_TYPES = ( CONF_OPAQUE, diff --git a/esphome/components/mipi/__init__.py b/esphome/components/mipi/__init__.py index 4dbc81caa2..ccd43c72cf 100644 --- a/esphome/components/mipi/__init__.py +++ b/esphome/components/mipi/__init__.py @@ -128,6 +128,8 @@ MADCTL_MH = 0x04 # Bit 2 LCD refresh right to left MADCTL_XFLIP = 0x02 # Mirror the display horizontally MADCTL_YFLIP = 0x01 # Mirror the display vertically +MADCTL_FLIP_FLAG = 0x100 # meta-flag to indicate use of axis flips + # Special constant for delays in command sequences DELAY_FLAG = 0xFFF # Special flag to indicate a delay @@ -329,7 +331,13 @@ class DriverChip: return CONF_SWAP_XY in transforms and CONF_MIRROR_X in transforms return CONF_SWAP_XY in transforms and CONF_MIRROR_Y in transforms - def get_dimensions(self, config) -> tuple[int, int, int, int]: + def get_dimensions(self, config, swap: bool = True) -> tuple[int, int, int, int]: + """ + Return the dimensions of the current model. + :param config: The current configuration + :param swap: If width/height should be swapped when axes are swapped. + :return: + """ if CONF_DIMENSIONS in config: # Explicit dimensions, just use as is dimensions = config[CONF_DIMENSIONS] @@ -361,13 +369,12 @@ class DriverChip: ) offset_height = native_height - height - offset_height # Swap default dimensions if swap_xy is set, or if rotation is 90/270 and we are not using a buffer - if transform.get(CONF_SWAP_XY) is True: + if swap and transform.get(CONF_SWAP_XY) is True: width, height = height, width offset_height, offset_width = offset_width, offset_height return width, height, offset_width, offset_height - def get_transform(self, config) -> dict[str, bool]: - can_transform = self.rotation_as_transform(config) + def get_base_transform(self, config): transform = config.get( CONF_TRANSFORM, { @@ -376,14 +383,20 @@ class DriverChip: CONF_SWAP_XY: self.get_default(CONF_SWAP_XY), }, ) - if not isinstance(transform, dict): - # Presumably disabled - return { - CONF_MIRROR_X: False, - CONF_MIRROR_Y: False, - CONF_SWAP_XY: False, - CONF_TRANSFORM: False, - } + if isinstance(transform, dict): + return transform + + # Transform is disabled + return { + CONF_MIRROR_X: False, + CONF_MIRROR_Y: False, + CONF_SWAP_XY: False, + CONF_TRANSFORM: False, + } + + def get_transform(self, config) -> dict[str, bool]: + transform = self.get_base_transform(config) + can_transform = self.rotation_as_transform(config) # Can we use the MADCTL register to set the rotation? if can_transform and CONF_TRANSFORM not in config: rotation = config[CONF_ROTATION] @@ -411,11 +424,15 @@ class DriverChip: return {cv.Required(CONF_SWAP_XY): cv.boolean} return {cv.Optional(CONF_SWAP_XY, default=False): validator} - def add_madctl(self, sequence: list, config: dict): - # Add the MADCTL command to the sequence based on the configuration. - use_flip = config.get(CONF_USE_AXIS_FLIPS) - madctl = 0 - transform = self.get_transform(config) + def get_madctl(self, transform: dict, config: dict) -> int: + """ + Convert a transform to MADCTL bits + :param transform: The transform dict + :param use_flip: Whether to use axis flips + :return: MADCTL value + """ + use_flip = config.get(CONF_USE_AXIS_FLIPS, False) + madctl = MADCTL_FLIP_FLAG if use_flip else 0 if transform[CONF_MIRROR_X]: madctl |= MADCTL_XFLIP if use_flip else MADCTL_MX if transform[CONF_MIRROR_Y]: @@ -424,22 +441,28 @@ class DriverChip: madctl |= MADCTL_MV if config[CONF_COLOR_ORDER] == MODE_BGR: madctl |= MADCTL_BGR - sequence.append((MADCTL, madctl)) return madctl + def add_madctl(self, sequence: list, config: dict): + # Add the MADCTL command to the sequence based on the configuration. + # This takes into account rotation if it can be implemented in the transform + transform = self.get_transform(config) + madctl = self.get_madctl(transform, config) + sequence.append((MADCTL, madctl & 0xFF)) + def skip_command(self, command: str): """ Allow suppressing a standard command in the init sequence. """ return self.get_default(f"no_{command.lower()}", False) - def get_sequence(self, config) -> tuple[tuple[int, ...], int]: + def get_sequence(self, config, add_madctl=True) -> tuple[int, ...]: """ Create the init sequence for the display. Use the default sequence from the model, if any, and append any custom sequence provided in the config. Append SLPOUT (if not already in the sequence) and DISPON to the end of the sequence - Pixel format, color order, and orientation will be set. - Returns a tuple of the init sequence and the computed MADCTL value. + MADCTL will be set if add_madctl is True + Returns the init sequence """ sequence = list(self.initsequence or ()) custom_sequence = config.get(CONF_INIT_SEQUENCE, []) @@ -457,7 +480,8 @@ class DriverChip: if self.rotation_as_transform(config): LOGGER.info("Using hardware transform to implement rotation") - madctl = self.add_madctl(sequence, config) + if add_madctl: + self.add_madctl(sequence, config) if config[CONF_INVERT_COLORS]: sequence.append((INVON,)) else: @@ -471,7 +495,7 @@ class DriverChip: # Flatten the sequence into a list of bytes, with the length of each command # or the delay flag inserted where needed - return flatten_sequence(sequence), madctl + return flatten_sequence(sequence) def requires_buffer(config) -> bool: diff --git a/esphome/components/mipi_dsi/display.py b/esphome/components/mipi_dsi/display.py index 85bfad7f1a..026c214569 100644 --- a/esphome/components/mipi_dsi/display.py +++ b/esphome/components/mipi_dsi/display.py @@ -192,10 +192,9 @@ async def to_code(config): width, height, _offset_width, _offset_height = model.get_dimensions(config) var = cg.new_Pvariable(config[CONF_ID], width, height, color_depth, pixel_mode) - sequence, madctl = model.get_sequence(config) + sequence = model.get_sequence(config) cg.add(var.set_model(config[CONF_MODEL])) cg.add(var.set_init_sequence(sequence)) - cg.add(var.set_madctl(madctl)) cg.add(var.set_invert_colors(config[CONF_INVERT_COLORS])) cg.add(var.set_hsync_pulse_width(config[CONF_HSYNC_PULSE_WIDTH])) cg.add(var.set_hsync_back_porch(config[CONF_HSYNC_BACK_PORCH])) diff --git a/esphome/components/mipi_dsi/mipi_dsi.cpp b/esphome/components/mipi_dsi/mipi_dsi.cpp index e8e9ca2bfb..fc59aeffe8 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.cpp +++ b/esphome/components/mipi_dsi/mipi_dsi.cpp @@ -392,9 +392,6 @@ void MIPI_DSI::dump_config() { "\n Model: %s" "\n Width: %u" "\n Height: %u" - "\n Mirror X: %s" - "\n Mirror Y: %s" - "\n Swap X/Y: %s" "\n Rotation: %d degrees" "\n DSI Lanes: %u" "\n Lane Bit Rate: %.0fMbps" @@ -406,14 +403,11 @@ void MIPI_DSI::dump_config() { "\n VSync Front Porch: %u" "\n Buffer Color Depth: %d bit" "\n Display Pixel Mode: %d bit" - "\n Color Order: %s" "\n Invert Colors: %s" "\n Pixel Clock: %.1fMHz", - this->model_, this->width_, this->height_, YESNO(this->madctl_ & (MADCTL_XFLIP | MADCTL_MX)), - YESNO(this->madctl_ & (MADCTL_YFLIP | MADCTL_MY)), YESNO(this->madctl_ & MADCTL_MV), this->rotation_, - this->lanes_, this->lane_bit_rate_, this->hsync_pulse_width_, this->hsync_back_porch_, - this->hsync_front_porch_, this->vsync_pulse_width_, this->vsync_back_porch_, this->vsync_front_porch_, - (3 - this->color_depth_) * 8, this->pixel_mode_, this->madctl_ & MADCTL_BGR ? "BGR" : "RGB", + this->model_, this->width_, this->height_, this->rotation_, this->lanes_, this->lane_bit_rate_, + this->hsync_pulse_width_, this->hsync_back_porch_, this->hsync_front_porch_, this->vsync_pulse_width_, + this->vsync_back_porch_, this->vsync_front_porch_, (3 - this->color_depth_) * 8, this->pixel_mode_, YESNO(this->invert_colors_), this->pclk_frequency_); LOG_PIN(" Reset Pin ", this->reset_pin_); } diff --git a/esphome/components/mipi_dsi/mipi_dsi.h b/esphome/components/mipi_dsi/mipi_dsi.h index 6e27912aa5..c27c9ccc6e 100644 --- a/esphome/components/mipi_dsi/mipi_dsi.h +++ b/esphome/components/mipi_dsi/mipi_dsi.h @@ -60,7 +60,6 @@ class MIPI_DSI : public display::Display { void set_model(const char *model) { this->model_ = model; } void set_lane_bit_rate(float lane_bit_rate) { this->lane_bit_rate_ = lane_bit_rate; } void set_lanes(uint8_t lanes) { this->lanes_ = lanes; } - void set_madctl(uint8_t madctl) { this->madctl_ = madctl; } void smark_failed(const LogString *message, esp_err_t err); @@ -86,7 +85,6 @@ class MIPI_DSI : public display::Display { std::vector<GPIOPin *> enable_pins_{}; size_t width_{}; size_t height_{}; - uint8_t madctl_{}; uint16_t hsync_pulse_width_ = 10; uint16_t hsync_back_porch_ = 10; uint16_t hsync_front_porch_ = 20; diff --git a/esphome/components/mipi_rgb/display.py b/esphome/components/mipi_rgb/display.py index 0aa8c56719..4952bda95f 100644 --- a/esphome/components/mipi_rgb/display.py +++ b/esphome/components/mipi_rgb/display.py @@ -265,9 +265,8 @@ async def to_code(config): if CONF_SPI_ID in config: await spi.register_spi_device(var, config, write_only=True) - sequence, madctl = model.get_sequence(config) + sequence = model.get_sequence(config) cg.add(var.set_init_sequence(sequence)) - cg.add(var.set_madctl(madctl)) cg.add(var.set_color_mode(COLOR_ORDERS[config[CONF_COLOR_ORDER]])) cg.add(var.set_invert_colors(config[CONF_INVERT_COLORS])) diff --git a/esphome/components/mipi_rgb/mipi_rgb.cpp b/esphome/components/mipi_rgb/mipi_rgb.cpp index 0b0a5344e4..6f5e2f2490 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.cpp +++ b/esphome/components/mipi_rgb/mipi_rgb.cpp @@ -118,15 +118,7 @@ void MipiRgbSpi::dump_config() { MipiRgb::dump_config(); LOG_PIN(" CS Pin: ", this->cs_); LOG_PIN(" DC Pin: ", this->dc_pin_); - ESP_LOGCONFIG(TAG, - " SPI Data rate: %uMHz" - "\n Mirror X: %s" - "\n Mirror Y: %s" - "\n Swap X/Y: %s" - "\n Color Order: %s", - (unsigned) (this->data_rate_ / 1000000), YESNO(this->madctl_ & (MADCTL_XFLIP | MADCTL_MX)), - YESNO(this->madctl_ & (MADCTL_YFLIP | MADCTL_MY | MADCTL_ML)), YESNO(this->madctl_ & MADCTL_MV), - this->madctl_ & MADCTL_BGR ? "BGR" : "RGB"); + ESP_LOGCONFIG(TAG, " SPI Data rate: %uMHz", (unsigned) (this->data_rate_ / 1000000)); } #endif // USE_SPI diff --git a/esphome/components/mipi_rgb/mipi_rgb.h b/esphome/components/mipi_rgb/mipi_rgb.h index 76b48bb249..accc251a18 100644 --- a/esphome/components/mipi_rgb/mipi_rgb.h +++ b/esphome/components/mipi_rgb/mipi_rgb.h @@ -38,7 +38,6 @@ class MipiRgb : public display::Display { display::ColorOrder get_color_mode() { return this->color_mode_; } void set_color_mode(display::ColorOrder color_mode) { this->color_mode_ = color_mode; } void set_invert_colors(bool invert_colors) { this->invert_colors_ = invert_colors; } - void set_madctl(uint8_t madctl) { this->madctl_ = madctl; } void add_data_pin(InternalGPIOPin *data_pin, size_t index) { this->data_pins_[index] = data_pin; }; void set_de_pin(InternalGPIOPin *de_pin) { this->de_pin_ = de_pin; } @@ -84,7 +83,6 @@ class MipiRgb : public display::Display { uint16_t vsync_front_porch_ = 10; uint32_t pclk_frequency_ = 16 * 1000 * 1000; bool pclk_inverted_{true}; - uint8_t madctl_{}; const char *model_{"Unknown"}; bool invert_colors_{}; display::ColorOrder color_mode_{display::COLOR_ORDER_BGR}; diff --git a/esphome/components/mipi_spi/display.py b/esphome/components/mipi_spi/display.py index 8dccfa3a92..6aa98e3f66 100644 --- a/esphome/components/mipi_spi/display.py +++ b/esphome/components/mipi_spi/display.py @@ -10,7 +10,7 @@ from esphome.components.const import ( CONF_COLOR_DEPTH, CONF_DRAW_ROUNDING, ) -from esphome.components.display import CONF_SHOW_TEST_CARD, DISPLAY_ROTATIONS +from esphome.components.display import CONF_SHOW_TEST_CARD from esphome.components.mipi import ( CONF_PIXEL_MODE, CONF_USE_AXIS_FLIPS, @@ -47,12 +47,10 @@ from esphome.const import ( CONF_MIRROR_Y, CONF_MODEL, CONF_RESET_PIN, - CONF_ROTATION, CONF_SWAP_XY, CONF_TRANSFORM, CONF_WIDTH, ) -from esphome.core import CORE from esphome.cpp_generator import TemplateArguments from esphome.final_validate import full_config @@ -113,22 +111,21 @@ DISPLAY_PIXEL_MODES = { def denominator(config): """ Calculate the best denominator for a buffer size fraction. - The denominator must be a number between 2 and 16 that divides the display height evenly, + The denominator should be a number between 2 and 16 that divides the display height evenly, and the fraction represented by the denominator must be less than or equal to the given fraction. :config: The configuration dictionary containing the buffer size fraction and display dimensions :return: The denominator to use for the buffer size fraction """ model = MODELS[config[CONF_MODEL]] frac = config.get(CONF_BUFFER_SIZE) - if frac is None or frac > 0.75: + _width, height, _offset_width, _offset_height = model.get_dimensions(config) + if frac is None or frac > 0.75 or height < 32: return 1 - height, _width, _offset_width, _offset_height = model.get_dimensions(config) try: return next(x for x in range(2, 17) if frac >= 1 / x and height % x == 0) except StopIteration: - raise cv.Invalid( - f"Buffer size fraction {frac} is not compatible with display height {height}" - ) from StopIteration + # No exact divisor, just use the closest. + return next(x for x in range(2, 17) if frac >= 1 / x) def model_schema(config): @@ -287,30 +284,19 @@ def _final_validate(config): config[CONF_SHOW_TEST_CARD] = True if PSRAM_DOMAIN not in global_config and CONF_BUFFER_SIZE not in config: - if not requires_buffer(config): - return config # No buffer needed, so no need to set a buffer size # If PSRAM is not enabled, choose a small buffer size by default if not requires_buffer(config): - # not our problem. - return config + return config # No buffer needed, so no need to set a buffer size color_depth = get_color_depth(config) frac = denominator(config) - height, width, _offset_width, _offset_height = model.get_dimensions(config) + width, height, _offset_width, _offset_height = model.get_dimensions(config) buffer_size = color_depth // 8 * width * height // frac - # Target a buffer size of 20kB - fraction = 20000.0 / buffer_size - try: - config[CONF_BUFFER_SIZE] = 1.0 / next( - x for x in range(2, 17) if fraction >= 1 / x and height % x == 0 - ) - except StopIteration: - # Either the screen is too big, or the height is not divisible by any of the fractions, so use 1.0 - # PSRAM will be needed. - if CORE.is_esp32: - raise cv.Invalid( - "PSRAM is required for this display" - ) from StopIteration + # Target a buffer size of 20kB, except for large displays, which shouldn't end up here + fraction = min(20000.0, buffer_size // 16) / buffer_size + config[CONF_BUFFER_SIZE] = 1.0 / next( + x for x in range(2, 17) if fraction >= 1 / x + ) return config @@ -318,39 +304,6 @@ def _final_validate(config): FINAL_VALIDATE_SCHEMA = _final_validate -def get_transform(config): - """ - Get the transformation configuration for the display. - :param config: - :return: - """ - model = MODELS[config[CONF_MODEL]] - can_transform = model.rotation_as_transform(config) - transform = config.get( - CONF_TRANSFORM, - { - CONF_MIRROR_X: model.get_default(CONF_MIRROR_X, False), - CONF_MIRROR_Y: model.get_default(CONF_MIRROR_Y, False), - CONF_SWAP_XY: model.get_default(CONF_SWAP_XY, False), - }, - ) - - # Can we use the MADCTL register to set the rotation? - if can_transform and CONF_TRANSFORM not in config: - rotation = config[CONF_ROTATION] - if rotation == 180: - transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X] - transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y] - elif rotation == 90: - transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY] - transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X] - else: - transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY] - transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y] - transform[CONF_TRANSFORM] = True - return transform - - def get_instance(config): """ Get the type of MipiSpi instance to create based on the configuration, @@ -359,7 +312,16 @@ def get_instance(config): :return: type, template arguments """ model = MODELS[config[CONF_MODEL]] - width, height, offset_width, offset_height = model.get_dimensions(config) + has_hardware_transform = config.get( + CONF_TRANSFORM + ) != CONF_DISABLED and model.transforms == { + CONF_MIRROR_X, + CONF_MIRROR_Y, + CONF_SWAP_XY, + } + width, height, offset_width, offset_height = model.get_dimensions( + config, not has_hardware_transform + ) color_depth = int(config[CONF_COLOR_DEPTH].removesuffix("bit")) bufferpixels = COLOR_DEPTHS[color_depth] @@ -373,57 +335,43 @@ def get_instance(config): bus_type = BusTypes[bus_type] buffer_type = cg.uint8 if color_depth == 8 else cg.uint16 frac = denominator(config) - rotation = ( - 0 if model.rotation_as_transform(config) else config.get(CONF_ROTATION, 0) - ) + madctl = model.get_madctl(model.get_base_transform(config), config) + has_writer = requires_buffer(config) templateargs = [ buffer_type, bufferpixels, config[CONF_BYTE_ORDER] == "big_endian", display_pixel_mode, bus_type, + width, + height, + offset_width, + offset_height, + madctl, + has_hardware_transform, ] + display.add_metadata( + config[CONF_ID], width, height, has_writer, has_hardware_transform + ) # If a buffer is required, use MipiSpiBuffer, otherwise use MipiSpi if requires_buffer(config): templateargs.extend( [ - width, - height, - offset_width, - offset_height, - DISPLAY_ROTATIONS[rotation], frac, config[CONF_DRAW_ROUNDING], ] ) return MipiSpiBuffer, templateargs - # Swap height and width if the display is rotated 90 or 270 degrees in software - if rotation in (90, 270): - width, height = height, width - offset_width, offset_height = offset_height, offset_width - templateargs.extend( - [ - width, - height, - offset_width, - offset_height, - ] - ) return MipiSpi, templateargs async def to_code(config): model = MODELS[config[CONF_MODEL]] var_id = config[CONF_ID] + init_sequence = model.get_sequence(config, False) var_id.type, templateargs = get_instance(config) var = cg.new_Pvariable(var_id, TemplateArguments(*templateargs)) - init_sequence, _madctl = model.get_sequence(config) cg.add(var.set_init_sequence(init_sequence)) - if model.rotation_as_transform(config): - if CONF_TRANSFORM in config: - LOGGER.warning("Use of 'transform' with 'rotation' is not recommended") - else: - config[CONF_ROTATION] = 0 cg.add(var.set_model(config[CONF_MODEL])) if enable_pin := config.get(CONF_ENABLE_PIN): enable = [await cg.gpio_pin_expression(pin) for pin in enable_pin] diff --git a/esphome/components/mipi_spi/mipi_spi.cpp b/esphome/components/mipi_spi/mipi_spi.cpp index 90f6324511..2eec3b12d1 100644 --- a/esphome/components/mipi_spi/mipi_spi.cpp +++ b/esphome/components/mipi_spi/mipi_spi.cpp @@ -5,7 +5,8 @@ namespace esphome::mipi_spi { void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, bool invert_colors, int display_bits, bool is_big_endian, const optional<uint8_t> &brightness, - GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width) { + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width, + bool has_hardware_rotation) { ESP_LOGCONFIG(TAG, "MIPI_SPI Display\n" " Model: %s\n" @@ -14,6 +15,7 @@ void internal_dump_config(const char *model, int width, int height, int offset_w " Swap X/Y: %s\n" " Mirror X: %s\n" " Mirror Y: %s\n" + " Hardware rotation: %s\n" " Invert colors: %s\n" " Color order: %s\n" " Display pixels: %d bits\n" @@ -22,9 +24,9 @@ void internal_dump_config(const char *model, int width, int height, int offset_w " SPI Data rate: %uMHz\n" " SPI Bus width: %d", model, width, height, YESNO(madctl & MADCTL_MV), YESNO(madctl & (MADCTL_MX | MADCTL_XFLIP)), - YESNO(madctl & (MADCTL_MY | MADCTL_YFLIP)), YESNO(invert_colors), (madctl & MADCTL_BGR) ? "BGR" : "RGB", - display_bits, is_big_endian ? "Big" : "Little", spi_mode, static_cast<unsigned>(data_rate / 1000000), - bus_width); + YESNO(madctl & (MADCTL_MY | MADCTL_YFLIP)), YESNO(has_hardware_rotation), YESNO(invert_colors), + (madctl & MADCTL_BGR) ? "BGR" : "RGB", display_bits, is_big_endian ? "Big" : "Little", spi_mode, + static_cast<unsigned>(data_rate / 1000000), bus_width); LOG_PIN(" CS Pin: ", cs); LOG_PIN(" Reset Pin: ", reset); LOG_PIN(" DC Pin: ", dc); diff --git a/esphome/components/mipi_spi/mipi_spi.h b/esphome/components/mipi_spi/mipi_spi.h index 083ff9507f..423226b1d7 100644 --- a/esphome/components/mipi_spi/mipi_spi.h +++ b/esphome/components/mipi_spi/mipi_spi.h @@ -34,13 +34,14 @@ static constexpr uint8_t SWIRE1 = 0x5A; static constexpr uint8_t SWIRE2 = 0x5B; static constexpr uint8_t PAGESEL = 0xFE; -static constexpr uint8_t MADCTL_MY = 0x80; // Bit 7 Bottom to top -static constexpr uint8_t MADCTL_MX = 0x40; // Bit 6 Right to left -static constexpr uint8_t MADCTL_MV = 0x20; // Bit 5 Swap axes -static constexpr uint8_t MADCTL_RGB = 0x00; // Bit 3 Red-Green-Blue pixel order -static constexpr uint8_t MADCTL_BGR = 0x08; // Bit 3 Blue-Green-Red pixel order -static constexpr uint8_t MADCTL_XFLIP = 0x02; // Mirror the display horizontally -static constexpr uint8_t MADCTL_YFLIP = 0x01; // Mirror the display vertically +static constexpr uint8_t MADCTL_MY = 0x80; // Bit 7 Bottom to top +static constexpr uint8_t MADCTL_MX = 0x40; // Bit 6 Right to left +static constexpr uint8_t MADCTL_MV = 0x20; // Bit 5 Swap axes +static constexpr uint8_t MADCTL_RGB = 0x00; // Bit 3 Red-Green-Blue pixel order +static constexpr uint8_t MADCTL_BGR = 0x08; // Bit 3 Blue-Green-Red pixel order +static constexpr uint8_t MADCTL_XFLIP = 0x02; // Mirror the display horizontally +static constexpr uint8_t MADCTL_YFLIP = 0x01; // Mirror the display vertically +static constexpr uint16_t MADCTL_FLIP_FLAG = 0x100; // controller uses axis flip bits static constexpr uint8_t DELAY_FLAG = 0xFF; // store a 16 bit value in a buffer, big endian. @@ -66,7 +67,8 @@ enum BusType { // Helper function for dump_config - defined in mipi_spi.cpp to allow use of LOG_PIN macro void internal_dump_config(const char *model, int width, int height, int offset_width, int offset_height, uint8_t madctl, bool invert_colors, int display_bits, bool is_big_endian, const optional<uint8_t> &brightness, - GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width); + GPIOPin *cs, GPIOPin *reset, GPIOPin *dc, int spi_mode, uint32_t data_rate, int bus_width, + bool has_hardware_rotation); /** * Base class for MIPI SPI displays. @@ -83,7 +85,7 @@ void internal_dump_config(const char *model, int width, int height, int offset_w * buffer */ template<typename BUFFERTYPE, PixelMode BUFFERPIXEL, bool IS_BIG_ENDIAN, PixelMode DISPLAYPIXEL, BusType BUS_TYPE, - int WIDTH, int HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT> + int WIDTH, int HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT, uint16_t MADCTL, bool HAS_HARDWARE_ROTATION> class MipiSpi : public display::Display, public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_1MHZ> { @@ -103,10 +105,39 @@ class MipiSpi : public display::Display, this->brightness_ = brightness; this->reset_params_(); } + void set_rotation(display::DisplayRotation rotation) override { + this->rotation_ = rotation; + if constexpr (HAS_HARDWARE_ROTATION) { + this->reset_params_(); + } + } display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; } - int get_width_internal() override { return WIDTH; } - int get_height_internal() override { return HEIGHT; } + int get_width() override { + if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES || + this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) + return HEIGHT; + return WIDTH; + } + + int get_height() override { + if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES || + this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) + return WIDTH; + return HEIGHT; + } + + // If hardware rotation is in use, the actual display width/height changes with rotation + int get_width_internal() override { + if constexpr (HAS_HARDWARE_ROTATION) + return get_width(); + return WIDTH; + } + int get_height_internal() override { + if constexpr (HAS_HARDWARE_ROTATION) + return get_height(); + return HEIGHT; + } void set_init_sequence(const std::vector<uint8_t> &sequence) { this->init_sequence_ = sequence; } // reset the display, and write the init sequence @@ -166,9 +197,6 @@ class MipiSpi : public display::Display, case INVERT_ON: this->invert_colors_ = true; break; - case MADCTL_CMD: - this->madctl_ = arg_byte; - break; case BRIGHTNESS: this->brightness_ = arg_byte; break; @@ -177,13 +205,13 @@ class MipiSpi : public display::Display, break; } const auto *ptr = vec.data() + index; - esph_log_d(TAG, "Command %02X, length %d, byte %02X", cmd, num_args, arg_byte); this->write_command_(cmd, ptr, num_args); index += num_args; if (cmd == SLEEP_OUT) delay(10); } } + this->reset_params_(); // init sequence no longer needed this->init_sequence_.clear(); } @@ -206,9 +234,10 @@ class MipiSpi : public display::Display, } void dump_config() override { - internal_dump_config(this->model_, WIDTH, HEIGHT, OFFSET_WIDTH, OFFSET_HEIGHT, this->madctl_, this->invert_colors_, - DISPLAYPIXEL * 8, IS_BIG_ENDIAN, this->brightness_, this->cs_, this->reset_pin_, this->dc_pin_, - this->mode_, this->data_rate_, BUS_TYPE); + internal_dump_config(this->model_, this->get_width(), this->get_height(), OFFSET_WIDTH, OFFSET_HEIGHT, MADCTL, + this->invert_colors_, DISPLAYPIXEL * 8, IS_BIG_ENDIAN, this->brightness_, this->cs_, + this->reset_pin_, this->dc_pin_, this->mode_, this->data_rate_, BUS_TYPE, + HAS_HARDWARE_ROTATION); } protected: @@ -219,10 +248,13 @@ class MipiSpi : public display::Display, // Writes a command to the display, with the given bytes. void write_command_(uint8_t cmd, const uint8_t *bytes, size_t len) { -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE char hex_buf[format_hex_pretty_size(MIPI_SPI_MAX_CMD_LOG_BYTES)]; - esph_log_v(TAG, "Command %02X, length %d, bytes %s", cmd, len, format_hex_pretty_to(hex_buf, bytes, len)); -#endif + // Don't spam the log after setup + if (this->init_sequence_.empty()) { + esph_log_v(TAG, "Command %02X, length %d, bytes %s", cmd, len, format_hex_pretty_to(hex_buf, bytes, len)); + } else { + esph_log_d(TAG, "Command %02X, length %d, bytes %s", cmd, len, format_hex_pretty_to(hex_buf, bytes, len)); + } if constexpr (BUS_TYPE == BUS_TYPE_QUAD) { this->enable(); this->write_cmd_addr_data(8, 0x02, 24, cmd << 8, bytes, len); @@ -271,16 +303,60 @@ class MipiSpi : public display::Display, this->write_command_(this->invert_colors_ ? INVERT_ON : INVERT_OFF); if (this->brightness_.has_value()) this->write_command_(BRIGHTNESS, this->brightness_.value()); + + // calculate new madctl value from base value adjusted for rotation + uint8_t madctl = MADCTL; // lower 8 bits only + constexpr bool use_flips = (MADCTL & MADCTL_FLIP_FLAG) != 0; + constexpr uint8_t x_mask = use_flips ? MADCTL_XFLIP : MADCTL_MX; + constexpr uint8_t y_mask = use_flips ? MADCTL_YFLIP : MADCTL_MY; + if constexpr (HAS_HARDWARE_ROTATION) { + switch (this->rotation_) { + default: + break; + case display::DISPLAY_ROTATION_90_DEGREES: + madctl ^= x_mask; // flip X axis + madctl ^= MADCTL_MV; // swap X and Y axes + break; + case display::DISPLAY_ROTATION_180_DEGREES: + madctl ^= x_mask; // flip X axis + madctl ^= y_mask; // flip Y axis + break; + case display::DISPLAY_ROTATION_270_DEGREES: + madctl ^= y_mask; // flip Y axis + madctl ^= MADCTL_MV; // swap X and Y axes + break; + } + } + esph_log_d(TAG, "Setting MADCTL for rotation %d, value %X", this->rotation_, madctl); + this->write_command_(MADCTL_CMD, madctl); + } + + uint16_t get_offset_width_() { + if constexpr (HAS_HARDWARE_ROTATION) { + if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES || + this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) + return OFFSET_HEIGHT; + } + return OFFSET_WIDTH; + } + + uint16_t get_offset_height_() { + if constexpr (HAS_HARDWARE_ROTATION) { + if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES || + this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) + return OFFSET_WIDTH; + } + return OFFSET_HEIGHT; } // set the address window for the next data write void set_addr_window_(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { esph_log_v(TAG, "Set addr %d/%d, %d/%d", x1, y1, x2, y2); uint8_t buf[4]; - x1 += OFFSET_WIDTH; - x2 += OFFSET_WIDTH; - y1 += OFFSET_HEIGHT; - y2 += OFFSET_HEIGHT; + x1 += get_offset_width_(); + x2 += get_offset_width_(); + y1 += get_offset_height_(); + y2 += get_offset_height_(); put16_be(buf, y1); put16_be(buf + 2, y2); this->write_command_(RASET, buf, sizeof buf); @@ -408,7 +484,6 @@ class MipiSpi : public display::Display, optional<uint8_t> brightness_{}; const char *model_{"Unknown"}; std::vector<uint8_t> init_sequence_{}; - uint8_t madctl_{}; }; /** @@ -427,22 +502,21 @@ class MipiSpi : public display::Display, * @tparam ROUNDING The alignment requirement for drawing operations (e.g. 2 means that x coordinates must be even) */ template<typename BUFFERTYPE, PixelMode BUFFERPIXEL, bool IS_BIG_ENDIAN, PixelMode DISPLAYPIXEL, BusType BUS_TYPE, - uint16_t WIDTH, uint16_t HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT, display::DisplayRotation ROTATION, - int FRACTION, unsigned ROUNDING> + uint16_t WIDTH, uint16_t HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT, uint16_t MADCTL, + bool HAS_HARDWARE_ROTATION, int FRACTION, unsigned ROUNDING> class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, - OFFSET_WIDTH, OFFSET_HEIGHT> { + OFFSET_WIDTH, OFFSET_HEIGHT, MADCTL, HAS_HARDWARE_ROTATION> { public: // these values define the buffer size needed to write in accordance with the chip pixel alignment // requirements. If the required rounding does not divide the width and height, we round up to the next multiple and // ignore the extra columns and rows when drawing, but use them to write to the display. - static constexpr unsigned BUFFER_WIDTH = (WIDTH + ROUNDING - 1) / ROUNDING * ROUNDING; - static constexpr unsigned BUFFER_HEIGHT = (HEIGHT + ROUNDING - 1) / ROUNDING * ROUNDING; + static constexpr size_t round_buffer(size_t size) { return (size + ROUNDING - 1) / ROUNDING * ROUNDING; } - MipiSpiBuffer() { this->rotation_ = ROTATION; } + MipiSpiBuffer() = default; void dump_config() override { - MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH, - OFFSET_HEIGHT>::dump_config(); + MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH, OFFSET_HEIGHT, + MADCTL, HAS_HARDWARE_ROTATION>::dump_config(); esph_log_config(TAG, " Rotation: %d°\n" " Buffer pixels: %d bits\n" @@ -450,14 +524,14 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS " Buffer bytes: %zu\n" " Draw rounding: %u", this->rotation_, BUFFERPIXEL * 8, FRACTION, - sizeof(BUFFERTYPE) * BUFFER_WIDTH * BUFFER_HEIGHT / FRACTION, ROUNDING); + sizeof(BUFFERTYPE) * round_buffer(WIDTH) * round_buffer(HEIGHT) / FRACTION, ROUNDING); } void setup() override { - MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH, - OFFSET_HEIGHT>::setup(); + MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH, OFFSET_HEIGHT, + MADCTL, HAS_HARDWARE_ROTATION>::setup(); RAMAllocator<BUFFERTYPE> allocator{}; - this->buffer_ = allocator.allocate(BUFFER_WIDTH * BUFFER_HEIGHT / FRACTION); + this->buffer_ = allocator.allocate(round_buffer(WIDTH) * round_buffer(HEIGHT) / FRACTION); if (this->buffer_ == nullptr) { this->mark_failed(LOG_STR("Buffer allocation failed")); } @@ -472,11 +546,13 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS } // for updates with a small buffer, we repeatedly call the writer_ function, clipping the height to a fraction of // the display height, - for (this->start_line_ = 0; this->start_line_ < HEIGHT; this->start_line_ += HEIGHT / FRACTION) { + for (this->start_line_ = 0; this->start_line_ < this->get_height_internal(); + this->start_line_ += this->get_height_internal() / FRACTION) { #if ESPHOME_LOG_LEVEL == ESPHOME_LOG_LEVEL_VERBOSE auto lap = millis(); #endif - this->end_line_ = this->start_line_ + HEIGHT / FRACTION; + this->end_line_ = + clamp_at_most(this->start_line_ + this->get_height_internal() / FRACTION, this->get_height_internal()); if (this->auto_clear_enabled_) { this->clear(); } @@ -503,10 +579,10 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS int w = this->x_high_ - this->x_low_ + 1; int h = this->y_high_ - this->y_low_ + 1; this->write_to_display_(this->x_low_, this->y_low_, w, h, this->buffer_, this->x_low_, - this->y_low_ - this->start_line_, BUFFER_WIDTH - w); + this->y_low_ - this->start_line_, round_buffer(this->get_width_internal()) - w); // invalidate watermarks - this->x_low_ = WIDTH; - this->y_low_ = HEIGHT; + this->x_low_ = this->get_width_internal(); + this->y_low_ = this->get_height_internal(); this->x_high_ = 0; this->y_high_ = 0; #if ESPHOME_LOG_LEVEL == ESPHOME_LOG_LEVEL_VERBOSE @@ -523,10 +599,23 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS void draw_pixel_at(int x, int y, Color color) override { if (!this->get_clipping().inside(x, y)) return; - rotate_coordinates(x, y); - if (x < 0 || x >= WIDTH || y < this->start_line_ || y >= this->end_line_) + if constexpr (not HAS_HARDWARE_ROTATION) { + if (this->rotation_ == display::DISPLAY_ROTATION_180_DEGREES) { + x = WIDTH - x - 1; + y = HEIGHT - y - 1; + } else if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES) { + auto tmp = x; + x = WIDTH - y - 1; + y = tmp; + } else if (this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) { + auto tmp = y; + y = HEIGHT - x - 1; + x = tmp; + } + } + if (x < 0 || x >= this->get_width_internal() || y < this->start_line_ || y >= this->end_line_) return; - this->buffer_[(y - this->start_line_) * BUFFER_WIDTH + x] = convert_color(color); + this->buffer_[(y - this->start_line_) * round_buffer(this->get_width_internal()) + x] = convert_color(color); if (x < this->x_low_) { this->x_low_ = x; } @@ -551,39 +640,14 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS this->x_low_ = 0; this->y_low_ = this->start_line_; - this->x_high_ = WIDTH - 1; + this->x_high_ = this->get_width_internal() - 1; this->y_high_ = this->end_line_ - 1; - std::fill_n(this->buffer_, HEIGHT * BUFFER_WIDTH / FRACTION, convert_color(color)); - } - - int get_width() override { - if constexpr (ROTATION == display::DISPLAY_ROTATION_90_DEGREES || ROTATION == display::DISPLAY_ROTATION_270_DEGREES) - return HEIGHT; - return WIDTH; - } - - int get_height() override { - if constexpr (ROTATION == display::DISPLAY_ROTATION_90_DEGREES || ROTATION == display::DISPLAY_ROTATION_270_DEGREES) - return WIDTH; - return HEIGHT; + std::fill_n(this->buffer_, (this->end_line_ - this->start_line_) * round_buffer(this->get_width_internal()), + convert_color(color)); } protected: // Rotate the coordinates to match the display orientation. - static void rotate_coordinates(int &x, int &y) { - if constexpr (ROTATION == display::DISPLAY_ROTATION_180_DEGREES) { - x = WIDTH - x - 1; - y = HEIGHT - y - 1; - } else if constexpr (ROTATION == display::DISPLAY_ROTATION_90_DEGREES) { - auto tmp = x; - x = WIDTH - y - 1; - y = tmp; - } else if constexpr (ROTATION == display::DISPLAY_ROTATION_270_DEGREES) { - auto tmp = y; - y = HEIGHT - x - 1; - x = tmp; - } - } // Convert a color to the buffer pixel format. static BUFFERTYPE convert_color(const Color &color) { diff --git a/tests/component_tests/display/__init__.py b/tests/component_tests/display/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/component_tests/display/test_display_metadata.py b/tests/component_tests/display/test_display_metadata.py new file mode 100644 index 0000000000..e569754494 --- /dev/null +++ b/tests/component_tests/display/test_display_metadata.py @@ -0,0 +1,81 @@ +"""Tests for display component metadata functions.""" + +from unittest.mock import patch + +from esphome.components.display import ( + DisplayMetaData, + add_metadata, + get_all_display_metadata, + get_display_metadata, +) +from esphome.cpp_generator import MockObj + + +def test_add_metadata_with_string_id(): + """Test adding metadata with a plain string ID.""" + with patch("esphome.components.display.CORE.data", {}): + add_metadata("my_display", 320, 240, True) + meta = get_display_metadata("my_display") + assert meta == DisplayMetaData( + width=320, height=240, has_writer=True, has_hardware_rotation=False + ) + + +def test_add_metadata_with_mockobj_id(): + """Test adding metadata with a MockObj ID (converted via str()).""" + with patch("esphome.components.display.CORE.data", {}): + mock_id = MockObj("my_display_obj") + add_metadata(mock_id, 480, 320, False, has_hardware_rotation=True) + meta = get_display_metadata("my_display_obj") + assert meta == DisplayMetaData( + width=480, height=320, has_writer=False, has_hardware_rotation=True + ) + + +def test_add_metadata_hardware_rotation_default(): + """Test that has_hardware_rotation defaults to False.""" + with patch("esphome.components.display.CORE.data", {}): + add_metadata("disp", 128, 64, False) + meta = get_display_metadata("disp") + assert meta.has_hardware_rotation is False + + +def test_get_display_metadata_missing_returns_none(): + """Test that querying a non-existent ID returns None.""" + with patch("esphome.components.display.CORE.data", {}): + data = get_display_metadata("no_such_display") + assert data.width == 0 + assert data.height == 0 + assert data.has_writer is False + assert data.has_hardware_rotation is False + + +def test_add_multiple_displays(): + """Test adding metadata for multiple displays.""" + with patch("esphome.components.display.CORE.data", {}): + add_metadata("disp_a", 320, 240, True) + add_metadata("disp_b", 128, 64, False, has_hardware_rotation=True) + + all_meta = get_all_display_metadata() + assert len(all_meta) == 2 + assert all_meta["disp_a"] == DisplayMetaData(320, 240, True, False) + assert all_meta["disp_b"] == DisplayMetaData(128, 64, False, True) + + +def test_add_metadata_overwrites_existing(): + """Test that adding metadata for the same ID overwrites the previous entry.""" + with patch("esphome.components.display.CORE.data", {}): + add_metadata("disp", 320, 240, True) + add_metadata("disp", 640, 480, False, has_hardware_rotation=True) + meta = get_display_metadata("disp") + assert meta == DisplayMetaData(640, 480, False, True) + + +def test_metadata_is_frozen(): + """Test that DisplayMetaData instances are immutable (frozen dataclass).""" + meta = DisplayMetaData(320, 240, True, False) + try: + meta.width = 640 + assert False, "Expected FrozenInstanceError" + except AttributeError: + pass diff --git a/tests/component_tests/mipi_spi/test_display_metadata.py b/tests/component_tests/mipi_spi/test_display_metadata.py new file mode 100644 index 0000000000..ab42a75694 --- /dev/null +++ b/tests/component_tests/mipi_spi/test_display_metadata.py @@ -0,0 +1,200 @@ +"""Tests for display metadata created by mipi_spi component.""" + +from collections.abc import Callable +from pathlib import Path + +from esphome.components.display import ( + DisplayMetaData, + get_all_display_metadata, + get_display_metadata, +) +from esphome.components.esp32 import ( + KEY_BOARD, + KEY_VARIANT, + VARIANT_ESP32, + VARIANT_ESP32S3, +) +from esphome.components.mipi_spi.display import ( + CONFIG_SCHEMA, + FINAL_VALIDATE_SCHEMA, + get_instance, +) +from esphome.const import PlatformFramework +from tests.component_tests.types import SetCoreConfigCallable + + +def validated_config(config): + """Run schema + final validation and return the validated config.""" + return FINAL_VALIDATE_SCHEMA(CONFIG_SCHEMA(config)) + + +def test_metadata_native_quad_default_test_card( + set_core_config: SetCoreConfigCallable, +) -> None: + """A quad-mode display with no explicit drawing gets a test card from final validation.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3}, + ) + config = validated_config({"model": "JC3636W518"}) + get_instance(config) + meta = get_display_metadata(str(config["id"])) + assert meta is not None + assert meta.width == 360 + assert meta.height == 360 + # final validation auto-enables show_test_card when no drawing methods are configured + assert meta.has_writer is True + assert meta.has_hardware_rotation is True + + +def test_metadata_single_mode_with_dc_pin( + set_core_config: SetCoreConfigCallable, +) -> None: + """A single-mode display with no explicit drawing gets a test card from final validation.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + config = validated_config( + { + "model": "ST7735", + "dc_pin": 18, + } + ) + get_instance(config) + meta = get_display_metadata(str(config["id"])) + assert meta is not None + assert meta.width == 128 + assert meta.height == 160 + assert meta.has_writer is True + assert meta.has_hardware_rotation is True + + +def test_metadata_custom_dimensions( + set_core_config: SetCoreConfigCallable, +) -> None: + """A custom model picks up explicit dimensions.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + config = validated_config( + { + "model": "custom", + "dc_pin": 18, + "dimensions": {"width": 480, "height": 320}, + "init_sequence": [[0xA0, 0x01]], + } + ) + get_instance(config) + meta = get_display_metadata(str(config["id"])) + assert meta is not None + assert meta.width == 480 + assert meta.height == 320 + # final validation auto-enables show_test_card + assert meta.has_writer is True + assert meta.has_hardware_rotation is True + + +def test_metadata_with_test_card_has_writer( + set_core_config: SetCoreConfigCallable, +) -> None: + """When show_test_card is enabled, has_writer should be True.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + config = validated_config( + { + "model": "custom", + "dc_pin": 18, + "dimensions": {"width": 240, "height": 240}, + "init_sequence": [[0xA0, 0x01]], + "show_test_card": True, + } + ) + get_instance(config) + meta = get_display_metadata(str(config["id"])) + assert meta is not None + assert meta.has_writer is True + + +def test_metadata_no_swap_xy_not_full_hardware_rotation( + set_core_config: SetCoreConfigCallable, +) -> None: + """A model that disables swap_xy should report has_hardware_rotation=False.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32-s3-devkitc-1", KEY_VARIANT: VARIANT_ESP32S3}, + ) + # JC3248W535 has swap_xy=cv.UNDEFINED -> transforms={mirror_x, mirror_y} only + config = validated_config({"model": "JC3248W535"}) + get_instance(config) + meta = get_display_metadata(str(config["id"])) + assert meta is not None + assert meta.has_hardware_rotation is False + + +def test_metadata_multiple_displays_independent( + set_core_config: SetCoreConfigCallable, +) -> None: + """Multiple displays each get their own metadata entry.""" + set_core_config( + PlatformFramework.ESP32_IDF, + platform_data={KEY_BOARD: "esp32dev", KEY_VARIANT: VARIANT_ESP32}, + ) + config_a = validated_config( + { + "id": "disp_a", + "model": "custom", + "dc_pin": 18, + "dimensions": {"width": 320, "height": 240}, + "init_sequence": [[0xA0, 0x01]], + } + ) + config_b = validated_config( + { + "id": "disp_b", + "model": "custom", + "dc_pin": 19, + "dimensions": {"width": 128, "height": 64}, + "init_sequence": [[0xA0, 0x01]], + } + ) + get_instance(config_a) + get_instance(config_b) + + all_meta = get_all_display_metadata() + # final validation auto-enables show_test_card for both + assert all_meta["disp_a"] == DisplayMetaData(320, 240, True, True) + assert all_meta["disp_b"] == DisplayMetaData(128, 64, True, True) + + +def test_metadata_via_code_generation_native( + generate_main: Callable[[str | Path], str], + component_fixture_path: Callable[[str], Path], +) -> None: + """Full code generation for native.yaml should produce correct metadata.""" + generate_main(component_fixture_path("native.yaml")) + all_meta = get_all_display_metadata() + # native.yaml: model JC3636W518 -> 360x360, no writer, full hardware rotation + assert len(all_meta) == 1 + meta = next(iter(all_meta.values())) + assert meta == DisplayMetaData( + width=360, height=360, has_writer=True, has_hardware_rotation=True + ) + + +def test_metadata_via_code_generation_lvgl( + generate_main: Callable[[str | Path], str], + component_fixture_path: Callable[[str], Path], +) -> None: + """Full code generation for lvgl.yaml should produce correct metadata.""" + generate_main(component_fixture_path("lvgl.yaml")) + all_meta = get_all_display_metadata() + # lvgl.yaml: model ST7735 -> 128x160, no writer (lvgl draws directly), full hw rotation + assert len(all_meta) == 1 + meta = next(iter(all_meta.values())) + assert meta == DisplayMetaData( + width=128, height=160, has_writer=False, has_hardware_rotation=True + ) diff --git a/tests/component_tests/mipi_spi/test_init.py b/tests/component_tests/mipi_spi/test_init.py index bae39d3879..4873892a8d 100644 --- a/tests/component_tests/mipi_spi/test_init.py +++ b/tests/component_tests/mipi_spi/test_init.py @@ -204,11 +204,6 @@ def test_transform_and_init_sequence_errors( r"extra keys not allowed @ data\['brightness'\]", id="brightness_not_supported", ), - pytest.param( - {"model": "T-DISPLAY-S3-PRO"}, - "PSRAM is required for this display", - id="psram_required", - ), ], ) def test_esp32s3_specific_errors( @@ -319,7 +314,7 @@ def test_native_generation( main_cpp = generate_main(component_fixture_path("native.yaml")) assert ( - "mipi_spi::MipiSpiBuffer<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_QUAD, 360, 360, 0, 1, display::DISPLAY_ROTATION_0_DEGREES, 1, 1>()" + "mipi_spi::MipiSpiBuffer<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_QUAD, 360, 360, 0, 1, 0, true, 1, 1>()" in main_cpp ) assert "set_init_sequence({240, 1, 8, 242" in main_cpp @@ -335,7 +330,7 @@ def test_lvgl_generation( main_cpp = generate_main(component_fixture_path("lvgl.yaml")) assert ( - "mipi_spi::MipiSpi<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_SINGLE, 128, 160, 0, 0>();" + "mipi_spi::MipiSpi<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_SINGLE, 128, 160, 0, 0, 0, true>();" in main_cpp ) assert "set_init_sequence({1, 0, 10, 255, 177" in main_cpp From bcd8ddeabe46f4ed2509554b3ed51066b891d572 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Thu, 2 Apr 2026 21:44:54 -0400 Subject: [PATCH 1908/2030] [lvgl] Fix ext_click_area property application (#15394) Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/lvgl/schemas.py | 4 +++- esphome/components/lvgl/trigger.py | 3 --- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/esphome/components/lvgl/schemas.py b/esphome/components/lvgl/schemas.py index 4f1473b652..2c57452a55 100644 --- a/esphome/components/lvgl/schemas.py +++ b/esphome/components/lvgl/schemas.py @@ -23,6 +23,7 @@ from esphome.core.config import StartupTrigger from . import defines as df, lv_validation as lvalid from .defines import ( + CONF_EXT_CLICK_AREA, CONF_SCROLL_DIR, CONF_SCROLL_SNAP_X, CONF_SCROLL_SNAP_Y, @@ -311,6 +312,7 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex cv.Optional(df.CONF_SCROLLBAR_MODE): df.LvConstant( "LV_SCROLLBAR_MODE_", "OFF", "ON", "ACTIVE", "AUTO" ).one_of, + cv.Optional(CONF_EXT_CLICK_AREA): lvalid.pixels, cv.Optional(CONF_SCROLL_DIR): df.SCROLL_DIRECTIONS.one_of, cv.Optional(CONF_SCROLL_SNAP_X): df.SNAP_DIRECTIONS.one_of, cv.Optional(CONF_SCROLL_SNAP_Y): df.SNAP_DIRECTIONS.one_of, @@ -318,6 +320,7 @@ STYLE_SCHEMA = cv.Schema({cv.Optional(k): v for k, v in STYLE_PROPS.items()}).ex ) OBJ_PROPERTIES = { + CONF_EXT_CLICK_AREA, CONF_SCROLL_SNAP_X, CONF_SCROLL_SNAP_Y, CONF_SCROLL_DIR, @@ -433,7 +436,6 @@ def obj_schema(widget_type: WidgetType): return ( part_schema(widget_type.parts) .extend(ALIGN_TO_SCHEMA) - .extend({cv.Optional(df.CONF_EXT_CLICK_AREA): lvalid.pixels}) .extend(automation_schema(widget_type.w_type)) .extend( { diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index c52d213e15..54309cdf89 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -15,7 +15,6 @@ from .defines import ( CONF_ALIGN, CONF_ALIGN_TO, CONF_ALIGN_TO_LAMBDA_ID, - CONF_EXT_CLICK_AREA, DIRECTIONS, LV_EVENT_MAP, LV_EVENT_TRIGGERS, @@ -114,8 +113,6 @@ async def generate_align_tos(config: dict): x = align_to[CONF_X] y = align_to[CONF_Y] lv.obj_align_to(w.obj, target, align, x, y) - if ext_click_area := w.config.get(CONF_EXT_CLICK_AREA): - lv.obj_set_ext_click_area(w.obj, ext_click_area) action_id = config[CONF_ALIGN_TO_LAMBDA_ID] var = new_Pvariable(action_id, await context.get_lambda()) From 6f05e3d20494d6cf5c9f7cd1a0b362e1491cdf7b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 3 Apr 2026 11:54:44 +1000 Subject: [PATCH 1909/2030] [ci] Run ci-custom.py as a pre-commit check (#15411) --- .github/workflows/ci.yml | 2 +- .pre-commit-config.yaml | 4 ++++ script/run-in-env.py | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 71703652e8..06e8189f54 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -723,7 +723,7 @@ jobs: cache-key: ${{ needs.common.outputs.cache-key }} - uses: esphome/pre-commit-action@43cd1109c09c544d97196f7730ee5b2e0cc6d81e # v3.0.1 fork with pinned actions/cache env: - SKIP: pylint,clang-tidy-hash + SKIP: pylint,clang-tidy-hash,ci-custom - uses: pre-commit-ci/lite-action@5d6cc0eb514c891a40562a58a8e71576c5c7fb43 # v1.1.0 if: always() diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ff1685ea7..f8c21aad36 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -65,3 +65,7 @@ repos: files: ^(\.clang-tidy|platformio\.ini|requirements_dev\.txt)$ pass_filenames: false additional_dependencies: [] + - id: ci-custom + name: ci-custom + entry: python3 script/run-in-env.py script/ci-custom.py + language: system diff --git a/script/run-in-env.py b/script/run-in-env.py index 886e65db27..9283ba9940 100755 --- a/script/run-in-env.py +++ b/script/run-in-env.py @@ -44,7 +44,8 @@ def find_and_activate_virtualenv(): def run_command(): # Execute the remaining arguments in the new environment if len(sys.argv) > 1: - subprocess.run(sys.argv[1:], check=False, close_fds=False) + result = subprocess.run(sys.argv[1:], check=False, close_fds=False) + sys.exit(result.returncode) else: print( "No command provided to run in the virtual environment.", From 5548a3277118c7c051592a25061c0f29bab63061 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 3 Apr 2026 06:15:51 -0400 Subject: [PATCH 1910/2030] [ili9xxx] Fix SPI MOSI pin validation never executing (#15399) --- esphome/components/ili9xxx/display.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index bfb2300f4f..185a74fa41 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -210,8 +210,8 @@ def final_validate(config): ): LOGGER.info("Consider enabling PSRAM if available for the display buffer") - return spi.final_validate_device_schema( - "ili9xxx", require_miso=False, require_mosi=True + spi.final_validate_device_schema("ili9xxx", require_miso=False, require_mosi=True)( + config ) From 8360502a94ea7ee3787a6f38d5e44ed4a7074fed Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Fri, 3 Apr 2026 22:01:04 +1000 Subject: [PATCH 1911/2030] [ci] Fix deprecated-component matcher (#15417) --- .github/scripts/auto-label-pr/detectors.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/scripts/auto-label-pr/detectors.js b/.github/scripts/auto-label-pr/detectors.js index fc63198019..fb9dadc6a0 100644 --- a/.github/scripts/auto-label-pr/detectors.js +++ b/.github/scripts/auto-label-pr/detectors.js @@ -235,19 +235,20 @@ async function detectDeprecatedComponents(github, context, changedFiles) { } } - // Get PR head to fetch files from the PR branch - const prNumber = context.payload.pull_request.number; + // Get base branch ref to check if deprecation already exists for the component + // This prevents flagging a PR that simply adds deprecation + const baseRef = context.payload.pull_request.base.ref; // Check each component's __init__.py for DEPRECATED_COMPONENT constant for (const component of components) { const initFile = `esphome/components/${component}/__init__.py`; try { - // Fetch file content from PR head using GitHub API + // Fetch file content from base branch using GitHub API const { data: fileData } = await github.rest.repos.getContent({ owner, repo, path: initFile, - ref: `refs/pull/${prNumber}/head` + ref: baseRef }); // Decode base64 content From 6fecd720490ddffff1305b86340639ee95b62a61 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Fri, 3 Apr 2026 08:35:16 -0400 Subject: [PATCH 1912/2030] [ezo_pmp] Fix change_i2c_address action using wrong template type (#15393) --- esphome/components/ezo_pmp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ezo_pmp/__init__.py b/esphome/components/ezo_pmp/__init__.py index 1538e303f1..3de796dd25 100644 --- a/esphome/components/ezo_pmp/__init__.py +++ b/esphome/components/ezo_pmp/__init__.py @@ -286,7 +286,7 @@ async def ezo_pmp_change_i2c_address_to_code(config, action_id, template_arg, ar paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, paren) - template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.double) + template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.int_) cg.add(var.set_address(template_)) return var From 2a5933e4f728580b4b95de13c4783c4d8c9396a5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:27:13 -1000 Subject: [PATCH 1913/2030] [host] Add graceful shutdown on SIGINT/SIGTERM (#15387) --- esphome/components/host/core.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/esphome/components/host/core.cpp b/esphome/components/host/core.cpp index a662e842ee..0ade4274fe 100644 --- a/esphome/components/host/core.cpp +++ b/esphome/components/host/core.cpp @@ -5,11 +5,17 @@ #include "esphome/core/helpers.h" #include "preferences.h" +#include <csignal> #include <sched.h> #include <time.h> #include <cmath> #include <cstdlib> +namespace { +volatile sig_atomic_t s_signal_received = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) +void signal_handler(int signal) { s_signal_received = signal; } +} // namespace + namespace esphome { void HOT yield() { ::sched_yield(); } @@ -72,11 +78,17 @@ uint32_t arch_get_cpu_freq_hz() { return 1000000000U; } void setup(); void loop(); int main() { + // Install signal handlers for graceful shutdown (flushes preferences to disk) + std::signal(SIGINT, signal_handler); + std::signal(SIGTERM, signal_handler); + esphome::host::setup_preferences(); setup(); - while (true) { + while (s_signal_received == 0) { loop(); } + esphome::App.run_safe_shutdown_hooks(); + return 0; } #endif // USE_HOST From 5a236697473e554d7b27b29d25f7b188163d3b49 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:27:29 -1000 Subject: [PATCH 1914/2030] [scheduler] Fix unrealistic scheduler benchmarks missing periodic drain (#15396) --- tests/benchmarks/core/bench_scheduler.cpp | 124 +++++++++++++++++++--- 1 file changed, 107 insertions(+), 17 deletions(-) diff --git a/tests/benchmarks/core/bench_scheduler.cpp b/tests/benchmarks/core/bench_scheduler.cpp index 9357734cc8..214fe0e4b8 100644 --- a/tests/benchmarks/core/bench_scheduler.cpp +++ b/tests/benchmarks/core/bench_scheduler.cpp @@ -8,7 +8,24 @@ namespace esphome::benchmarks { // Inner iteration count to amortize CodSpeed instrumentation overhead. // Without this, the ~60ns per-iteration valgrind start/stop cost dominates // sub-microsecond benchmarks. -static constexpr int kInnerIterations = 2000; +// Must be divisible by all batch sizes used below (3, 10) to avoid +// pool imbalance at iteration boundaries that causes spurious malloc. +static constexpr int kInnerIterations = 2100; + +// Warm the scheduler pool by registering and replacing items twice. +// The first batch allocates fresh items; the second batch cancels them and +// populates the recycling pool with the cancelled items from the first batch. +static void warm_pool(Scheduler &scheduler, Component *component, int batch_size, uint32_t delay) { + uint32_t now = millis(); + for (int i = 0; i < batch_size; i++) { + scheduler.set_timeout(component, static_cast<uint32_t>(i), delay, []() {}); + } + scheduler.call(++now); + for (int i = 0; i < batch_size; i++) { + scheduler.set_timeout(component, static_cast<uint32_t>(i), delay, []() {}); + } + scheduler.call(++now); +} // --- Scheduler fast path: no work to do --- @@ -83,11 +100,21 @@ static void Scheduler_SetTimeout(benchmark::State &state) { Scheduler scheduler; Component dummy_component; + // Register 3 timeouts then call() — realistic worst case where multiple + // components schedule in the same loop iteration. Keeps item count within + // the recycling pool (MAX_POOL_SIZE=5) to avoid spurious malloc/free. + static constexpr int kBatchSize = 3; + static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize"); + warm_pool(scheduler, &dummy_component, kBatchSize, 1000); for (auto _ : state) { + uint32_t now = millis(); for (int i = 0; i < kInnerIterations; i++) { - scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % 5), 1000, []() {}); + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % kBatchSize), 1000, []() {}); + if ((i + 1) % kBatchSize == 0) { + scheduler.call(++now); + } } - scheduler.process_to_add(); + scheduler.call(++now); benchmark::DoNotOptimize(scheduler); } state.SetItemsProcessed(state.iterations() * kInnerIterations); @@ -99,22 +126,22 @@ BENCHMARK(Scheduler_SetTimeout); static void Scheduler_SetInterval(benchmark::State &state) { Scheduler scheduler; Component dummy_component; - // Number of distinct interval keys; controls how many unique timers exist - // simultaneously and the drain cadence for process_to_add(). - static constexpr int kKeyCount = 5; + // Register 3 intervals then call() — realistic worst case where multiple + // components schedule in the same loop iteration. Keeps item count within + // the recycling pool (MAX_POOL_SIZE=5) to avoid spurious malloc/free. + static constexpr int kBatchSize = 3; + static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize"); + warm_pool(scheduler, &dummy_component, kBatchSize, 1000); for (auto _ : state) { + uint32_t now = millis(); for (int i = 0; i < kInnerIterations; i++) { - scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i % kKeyCount), 1000, []() {}); - // Drain to_add_ periodically to reflect production behavior where - // process_to_add() runs each main loop iteration. Without this, - // cancelled items accumulate in to_add_ causing O(n²) scan cost. - if ((i + 1) % kKeyCount == 0) { - scheduler.process_to_add(); + scheduler.set_interval(&dummy_component, static_cast<uint32_t>(i % kBatchSize), 1000, []() {}); + if ((i + 1) % kBatchSize == 0) { + scheduler.call(++now); } } - // Final drain in case kInnerIterations is not a multiple of 5 - scheduler.process_to_add(); + scheduler.call(++now); benchmark::DoNotOptimize(scheduler); } state.SetItemsProcessed(state.iterations() * kInnerIterations); @@ -128,16 +155,79 @@ static void Scheduler_Defer(benchmark::State &state) { Component dummy_component; // defer() is Component::defer which calls set_timeout(delay=0). - // Call set_timeout directly since defer() is protected. + // Component::defer(func) passes nullptr as the name, which skips + // cancel_item_locked_ entirely — matching production behavior where + // defers are anonymous fire-and-forget callbacks. + static constexpr int kBatchSize = 3; + static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize"); + warm_pool(scheduler, &dummy_component, kBatchSize, 0); for (auto _ : state) { + uint32_t now = millis(); for (int i = 0; i < kInnerIterations; i++) { - scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % 5), 0, []() {}); + scheduler.set_timeout(&dummy_component, static_cast<const char *>(nullptr), 0, []() {}); + if ((i + 1) % kBatchSize == 0) { + scheduler.call(++now); + } } - scheduler.process_to_add(); + scheduler.call(++now); benchmark::DoNotOptimize(scheduler); } state.SetItemsProcessed(state.iterations() * kInnerIterations); } BENCHMARK(Scheduler_Defer); +// --- Scheduler: defer with same ID (cancel-and-replace pattern) --- + +static void Scheduler_Defer_SameID(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + // Measures defer with a fixed numeric ID — each call cancels the previous + // pending defer before adding the new one. This is the pattern used by + // components that defer work but want to coalesce rapid updates. + static constexpr int kBatchSize = 3; + static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize"); + warm_pool(scheduler, &dummy_component, kBatchSize, 0); + for (auto _ : state) { + uint32_t now = millis(); + for (int i = 0; i < kInnerIterations; i++) { + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(0), 0, []() {}); + if ((i + 1) % kBatchSize == 0) { + scheduler.call(++now); + } + } + scheduler.call(++now); + benchmark::DoNotOptimize(scheduler); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_Defer_SameID); + +// --- Scheduler: set_timeout with batch size exceeding pool (cliff test) --- + +static void Scheduler_SetTimeout_ExceedPool(benchmark::State &state) { + Scheduler scheduler; + Component dummy_component; + + // Register 10 timeouts then call() — exceeds MAX_POOL_SIZE=5 to measure + // the performance cliff when the recycling pool is exhausted and items + // must be malloc'd/freed. + static constexpr int kBatchSize = 10; + static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize"); + warm_pool(scheduler, &dummy_component, kBatchSize, 1000); + for (auto _ : state) { + uint32_t now = millis(); + for (int i = 0; i < kInnerIterations; i++) { + scheduler.set_timeout(&dummy_component, static_cast<uint32_t>(i % kBatchSize), 1000, []() {}); + if ((i + 1) % kBatchSize == 0) { + scheduler.call(++now); + } + } + scheduler.call(++now); + benchmark::DoNotOptimize(scheduler); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Scheduler_SetTimeout_ExceedPool); + } // namespace esphome::benchmarks From ea0227a20668de45b993cc745c5b2f86316d8732 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:27:44 -1000 Subject: [PATCH 1915/2030] [benchmarks] Add host platform benchmarks for number, select, and switch (#15405) --- .../benchmarks/components/number/__init__.py | 5 + .../components/number/bench_number.cpp | 121 ++++++++++++++ .../components/number/benchmark.yaml | 1 + .../benchmarks/components/select/__init__.py | 5 + .../components/select/bench_select.cpp | 157 ++++++++++++++++++ .../components/select/benchmark.yaml | 1 + .../benchmarks/components/switch/__init__.py | 5 + .../components/switch/bench_switch.cpp | 137 +++++++++++++++ .../components/switch/benchmark.yaml | 1 + 9 files changed, 433 insertions(+) create mode 100644 tests/benchmarks/components/number/__init__.py create mode 100644 tests/benchmarks/components/number/bench_number.cpp create mode 100644 tests/benchmarks/components/number/benchmark.yaml create mode 100644 tests/benchmarks/components/select/__init__.py create mode 100644 tests/benchmarks/components/select/bench_select.cpp create mode 100644 tests/benchmarks/components/select/benchmark.yaml create mode 100644 tests/benchmarks/components/switch/__init__.py create mode 100644 tests/benchmarks/components/switch/bench_switch.cpp create mode 100644 tests/benchmarks/components/switch/benchmark.yaml diff --git a/tests/benchmarks/components/number/__init__.py b/tests/benchmarks/components/number/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/number/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/number/bench_number.cpp b/tests/benchmarks/components/number/bench_number.cpp new file mode 100644 index 0000000000..57a73930b2 --- /dev/null +++ b/tests/benchmarks/components/number/bench_number.cpp @@ -0,0 +1,121 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/number/number.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Number for benchmarking — control() publishes the value back. +class BenchNumber : public number::Number { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + protected: + void control(float value) override { this->publish_state(value); } +}; + +// Helper to create a typical number entity for benchmarks. +static void setup_number(BenchNumber &number) { + number.configure("test_number"); + number.traits.set_min_value(0.0f); + number.traits.set_max_value(100.0f); + number.traits.set_step(1.0f); + number.traits.set_mode(number::NUMBER_MODE_SLIDER); +} + +// --- Number::publish_state() --- +// Measures the publish path: set_has_state, store value, callback dispatch. + +static void NumberPublish_State(benchmark::State &state) { + BenchNumber number; + setup_number(number); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + number.publish_state(static_cast<float>(i % 100)); + } + benchmark::DoNotOptimize(number.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(NumberPublish_State); + +// --- Number::publish_state() with callback --- +// Measures callback dispatch overhead. + +static void NumberPublish_WithCallback(benchmark::State &state) { + BenchNumber number; + setup_number(number); + + uint64_t callback_count = 0; + number.add_on_state_callback([&callback_count](float) { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + number.publish_state(static_cast<float>(i % 100)); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(NumberPublish_WithCallback); + +// --- NumberCall::perform() set value --- +// The most common number call — setting an absolute value. +// Exercises: validation against min/max, control() dispatch. + +static void NumberCall_SetValue(benchmark::State &state) { + BenchNumber number; + setup_number(number); + number.publish_state(50.0f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + float val = static_cast<float>(i % 100); + number.make_call().set_value(val).perform(); + } + benchmark::DoNotOptimize(number.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(NumberCall_SetValue); + +// --- NumberCall::perform() increment --- +// Exercises: state read, step arithmetic, max clamping. + +static void NumberCall_Increment(benchmark::State &state) { + BenchNumber number; + setup_number(number); + number.publish_state(0.0f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + number.make_call().number_increment(true).perform(); + } + benchmark::DoNotOptimize(number.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(NumberCall_Increment); + +// --- NumberCall::perform() decrement --- +// Exercises: state read, step arithmetic, min clamping. + +static void NumberCall_Decrement(benchmark::State &state) { + BenchNumber number; + setup_number(number); + number.publish_state(100.0f); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + number.make_call().number_decrement(true).perform(); + } + benchmark::DoNotOptimize(number.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(NumberCall_Decrement); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/number/benchmark.yaml b/tests/benchmarks/components/number/benchmark.yaml new file mode 100644 index 0000000000..f435661270 --- /dev/null +++ b/tests/benchmarks/components/number/benchmark.yaml @@ -0,0 +1 @@ +number: diff --git a/tests/benchmarks/components/select/__init__.py b/tests/benchmarks/components/select/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/select/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/select/bench_select.cpp b/tests/benchmarks/components/select/bench_select.cpp new file mode 100644 index 0000000000..8e047d9151 --- /dev/null +++ b/tests/benchmarks/components/select/bench_select.cpp @@ -0,0 +1,157 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/select/select.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Select for benchmarking — control() publishes directly by index. +class BenchSelect : public select::Select { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + protected: + void control(size_t index) override { this->publish_state(index); } +}; + +// Helper to create a select with the given options. +static void setup_select(BenchSelect &select, const char *name, std::initializer_list<const char *> options) { + select.configure(name); + select.traits.set_options(options); + select.publish_state(size_t(0)); +} + +// --- Select::publish_state(size_t) --- +// The fast path: publish by index, no string lookup. + +static void SelectPublish_ByIndex(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.publish_state(static_cast<size_t>(i % 4)); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectPublish_ByIndex); + +// --- Select::publish_state(const char *) --- +// The string path: requires index_of() lookup via strncmp. + +static void SelectPublish_ByString(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + const char *options[] = {"off", "still", "move", "still+move"}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.publish_state(options[i % 4]); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectPublish_ByString); + +// --- Select::publish_state() with callback --- +// Measures callback dispatch overhead on the index path. + +static void SelectPublish_WithCallback(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + uint64_t callback_count = 0; + select.add_on_state_callback([&callback_count](size_t) { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.publish_state(static_cast<size_t>(i % 4)); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectPublish_WithCallback); + +// --- SelectCall::perform() set by index --- +// The fast call path — no string matching needed. + +static void SelectCall_SetByIndex(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.make_call().set_index(i % 4).perform(); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectCall_SetByIndex); + +// --- SelectCall::perform() set by option string --- +// Exercises the string lookup path through index_of(). + +static void SelectCall_SetByOption(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + const char *options[] = {"off", "still", "move", "still+move"}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.make_call().set_option(options[i % 4]).perform(); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectCall_SetByOption); + +// --- SelectCall::perform() next with cycling --- +// Exercises the navigation path through active_index_. + +static void SelectCall_NextCycle(benchmark::State &state) { + BenchSelect select; + setup_select(select, "test_select", {"off", "still", "move", "still+move"}); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.make_call().select_next(true).perform(); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectCall_NextCycle); + +// --- SelectCall with 10 options (string lookup) --- +// Worst-case string matching with more options. + +static void SelectCall_SetByOption_10Options(benchmark::State &state) { + BenchSelect select; + setup_select( + select, "test_select", + {"off", "still", "move", "still+move", "custom1", "custom2", "custom3", "custom4", "custom5", "custom6"}); + + // Pick options spread across the list to exercise different search depths + const char *picks[] = {"off", "custom3", "custom6", "move"}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + select.make_call().set_option(picks[i % 4]).perform(); + } + benchmark::DoNotOptimize(select.active_index()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SelectCall_SetByOption_10Options); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/select/benchmark.yaml b/tests/benchmarks/components/select/benchmark.yaml new file mode 100644 index 0000000000..d336a348a0 --- /dev/null +++ b/tests/benchmarks/components/select/benchmark.yaml @@ -0,0 +1 @@ +select: diff --git a/tests/benchmarks/components/switch/__init__.py b/tests/benchmarks/components/switch/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/switch/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/switch/bench_switch.cpp b/tests/benchmarks/components/switch/bench_switch.cpp new file mode 100644 index 0000000000..d948f080ad --- /dev/null +++ b/tests/benchmarks/components/switch/bench_switch.cpp @@ -0,0 +1,137 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/switch/switch.h" + +namespace esphome::benchmarks { + +// Inner iteration count to amortize CodSpeed instrumentation overhead. +static constexpr int kInnerIterations = 2000; + +// Minimal Switch for benchmarking — write_state() publishes directly. +class BenchSwitch : public switch_::Switch { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + protected: + void write_state(bool state) override { this->publish_state(state); } +}; + +// --- Switch::publish_state() alternating --- +// Forces state change every call, exercising the full publish path. + +static void SwitchPublish_Alternating(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + sw.publish_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.publish_state(i % 2 == 0); + } + benchmark::DoNotOptimize(sw.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchPublish_Alternating); + +// --- Switch::publish_state() no change --- +// Tests the deduplication fast path in publish_dedup_. + +static void SwitchPublish_NoChange(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + sw.publish_state(true); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.publish_state(true); + } + benchmark::DoNotOptimize(sw.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchPublish_NoChange); + +// --- Switch::publish_state() with callback --- +// Measures callback dispatch overhead on state changes. + +static void SwitchPublish_WithCallback(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + + uint64_t callback_count = 0; + sw.add_on_state_callback([&callback_count](bool) { callback_count++; }); + sw.publish_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.publish_state(i % 2 == 0); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchPublish_WithCallback); + +// --- Switch::turn_on() / turn_off() --- +// The front-end call path: turn_on → write_state → publish_state. + +static void SwitchTurnOn(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + sw.publish_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.turn_on(); + } + benchmark::DoNotOptimize(sw.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchTurnOn); + +// --- Switch::toggle() alternating --- +// Exercises the toggle path which reads current state to determine target. + +static void SwitchToggle(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + sw.publish_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.toggle(); + } + benchmark::DoNotOptimize(sw.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchToggle); + +// --- Switch::publish_state() inverted --- +// Verifies the inversion path doesn't add significant overhead. + +static void SwitchPublish_Inverted(benchmark::State &state) { + BenchSwitch sw; + sw.configure("test_switch"); + sw.set_restore_mode(switch_::SWITCH_ALWAYS_OFF); + sw.set_inverted(true); + sw.publish_state(false); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sw.publish_state(i % 2 == 0); + } + benchmark::DoNotOptimize(sw.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(SwitchPublish_Inverted); + +} // namespace esphome::benchmarks diff --git a/tests/benchmarks/components/switch/benchmark.yaml b/tests/benchmarks/components/switch/benchmark.yaml new file mode 100644 index 0000000000..c637b3dc89 --- /dev/null +++ b/tests/benchmarks/components/switch/benchmark.yaml @@ -0,0 +1 @@ +switch: From f2a0d9943d5a207e7f3b099509e2f04df5d651e9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:27:55 -1000 Subject: [PATCH 1916/2030] [benchmarks] Add host platform benchmarks for text_sensor and button (#15407) --- .../benchmarks/components/button/__init__.py | 5 + .../components/button/bench_button.cpp | 55 +++++++++ .../components/button/benchmark.yaml | 1 + .../components/text_sensor/__init__.py | 5 + .../text_sensor/bench_text_sensor.cpp | 108 ++++++++++++++++++ .../components/text_sensor/benchmark.yaml | 1 + 6 files changed, 175 insertions(+) create mode 100644 tests/benchmarks/components/button/__init__.py create mode 100644 tests/benchmarks/components/button/bench_button.cpp create mode 100644 tests/benchmarks/components/button/benchmark.yaml create mode 100644 tests/benchmarks/components/text_sensor/__init__.py create mode 100644 tests/benchmarks/components/text_sensor/bench_text_sensor.cpp create mode 100644 tests/benchmarks/components/text_sensor/benchmark.yaml diff --git a/tests/benchmarks/components/button/__init__.py b/tests/benchmarks/components/button/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/button/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/button/bench_button.cpp b/tests/benchmarks/components/button/bench_button.cpp new file mode 100644 index 0000000000..82f76961c9 --- /dev/null +++ b/tests/benchmarks/components/button/bench_button.cpp @@ -0,0 +1,55 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/button/button.h" + +namespace esphome::button::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// Minimal Button for benchmarking — press_action() is a no-op. +class BenchButton : public Button { + public: + void configure(const char *name) { this->configure_entity_(name, 0x12345678, 0); } + + protected: + void press_action() override {} +}; + +// --- Button::press() --- +// Measures: ESP_LOGD + press_action() + callback dispatch. + +static void ButtonPress(benchmark::State &state) { + BenchButton button; + button.configure("test_button"); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + button.press(); + } + benchmark::DoNotOptimize(&button); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ButtonPress); + +// --- Button::press() with callback --- +// Measures callback dispatch overhead. + +static void ButtonPress_WithCallback(benchmark::State &state) { + BenchButton button; + button.configure("test_button"); + + uint64_t callback_count = 0; + button.add_on_press_callback([&callback_count]() { callback_count++; }); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + button.press(); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(ButtonPress_WithCallback); + +} // namespace esphome::button::benchmarks diff --git a/tests/benchmarks/components/button/benchmark.yaml b/tests/benchmarks/components/button/benchmark.yaml new file mode 100644 index 0000000000..75f089f793 --- /dev/null +++ b/tests/benchmarks/components/button/benchmark.yaml @@ -0,0 +1 @@ +button: diff --git a/tests/benchmarks/components/text_sensor/__init__.py b/tests/benchmarks/components/text_sensor/__init__.py new file mode 100644 index 0000000000..b08f67a095 --- /dev/null +++ b/tests/benchmarks/components/text_sensor/__init__.py @@ -0,0 +1,5 @@ +from tests.testing_helpers import ComponentManifestOverride + + +def override_manifest(manifest: ComponentManifestOverride) -> None: + manifest.enable_codegen() diff --git a/tests/benchmarks/components/text_sensor/bench_text_sensor.cpp b/tests/benchmarks/components/text_sensor/bench_text_sensor.cpp new file mode 100644 index 0000000000..0ac88f79c1 --- /dev/null +++ b/tests/benchmarks/components/text_sensor/bench_text_sensor.cpp @@ -0,0 +1,108 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/text_sensor/text_sensor.h" + +namespace esphome::text_sensor::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// --- publish_state(const char *) with short string, value changes each time --- +// Exercises: memcmp check (mismatch), string assign, callback dispatch. + +static void TextSensorPublish_Short_Changing(benchmark::State &state) { + TextSensor sensor; + + // Pre-populate with different short strings + const char *values[] = {"192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4"}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(values[i % 4]); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(TextSensorPublish_Short_Changing); + +// --- publish_state(const char *) with short string, same value (dedup path) --- +// Exercises: memcmp check (match), skips string assign. + +static void TextSensorPublish_Short_NoChange(benchmark::State &state) { + TextSensor sensor; + sensor.publish_state("192.168.1.100"); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state("192.168.1.100"); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(TextSensorPublish_Short_NoChange); + +// --- publish_state with longer string (firmware version, MAC address) --- +// Exercises: memcmp on longer strings, string assign with potential realloc. + +static void TextSensorPublish_Long_Changing(benchmark::State &state) { + TextSensor sensor; + + const char *values[] = { + "2025.12.0-dev (Jan 15 2025, 10:30:00)", + "2025.12.1-dev (Feb 20 2025, 14:45:00)", + "2025.12.2-dev (Mar 10 2025, 08:15:00)", + "2025.12.3-dev (Apr 5 2025, 16:00:00)", + }; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(values[i % 4]); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(TextSensorPublish_Long_Changing); + +// --- publish_state with callback --- +// Measures callback dispatch overhead for text sensors. + +static void TextSensorPublish_WithCallback(benchmark::State &state) { + TextSensor sensor; + + uint64_t callback_count = 0; + sensor.add_on_state_callback([&callback_count](const std::string &) { callback_count++; }); + + const char *values[] = {"192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4"}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(values[i % 4]); + } + benchmark::DoNotOptimize(callback_count); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(TextSensorPublish_WithCallback); + +// --- publish_state(const char *, size_t) direct --- +// The lowest-level overload, avoids strlen. + +static void TextSensorPublish_WithLen(benchmark::State &state) { + TextSensor sensor; + + static constexpr const char *values[] = {"192.168.1.1", "192.168.1.2", "192.168.1.3", "192.168.1.4"}; + static constexpr size_t lens[] = {11, 11, 11, 11}; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + sensor.publish_state(values[i % 4], lens[i % 4]); + } + benchmark::DoNotOptimize(sensor.state); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(TextSensorPublish_WithLen); + +} // namespace esphome::text_sensor::benchmarks diff --git a/tests/benchmarks/components/text_sensor/benchmark.yaml b/tests/benchmarks/components/text_sensor/benchmark.yaml new file mode 100644 index 0000000000..7bcb7de1c8 --- /dev/null +++ b/tests/benchmarks/components/text_sensor/benchmark.yaml @@ -0,0 +1 @@ +text_sensor: From 38f4dc32170f1882bf8eb07de61cf2198d53278e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:28:07 -1000 Subject: [PATCH 1917/2030] [uptime] Pass known length to publish_state to avoid redundant strlen (#15410) --- esphome/components/uptime/text_sensor/uptime_text_sensor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp index c89d23672e..7a56654804 100644 --- a/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp +++ b/esphome/components/uptime/text_sensor/uptime_text_sensor.cpp @@ -70,7 +70,7 @@ void UptimeTextSensor::update() { if (show_seconds) append_unit(buf, sizeof(buf), pos, this->separator_, seconds, this->seconds_text_); - this->publish_state(buf); + this->publish_state(buf, pos); } float UptimeTextSensor::get_setup_priority() const { return setup_priority::HARDWARE; } From 95683b7416a4973733cdc5a695d82cafe55fc691 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:28:29 -1000 Subject: [PATCH 1918/2030] [light] Pass LightTraits to avoid redundant virtual get_traits() calls (#15403) --- esphome/components/light/light_call.cpp | 12 +++++------- esphome/components/light/light_call.h | 5 +++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/esphome/components/light/light_call.cpp b/esphome/components/light/light_call.cpp index 7c936b51b7..a749cd7305 100644 --- a/esphome/components/light/light_call.cpp +++ b/esphome/components/light/light_call.cpp @@ -198,13 +198,13 @@ LightColorValues LightCall::validate_() { // Ensure there is always a color mode set if (!this->has_color_mode()) { - this->color_mode_ = this->compute_color_mode_(); + this->color_mode_ = this->compute_color_mode_(traits); this->set_flag_(FLAG_HAS_COLOR_MODE); } auto color_mode = this->color_mode_; // Transform calls that use non-native parameters for the current mode. - this->transform_parameters_(); + this->transform_parameters_(traits); // Business logic adjustments before validation // Flag whether an explicit turn off was requested, in which case we'll also stop the effect. @@ -366,9 +366,7 @@ LightColorValues LightCall::validate_() { return v; } -void LightCall::transform_parameters_() { - auto traits = this->parent_->get_traits(); - +void LightCall::transform_parameters_(const LightTraits &traits) { // Allow CWWW modes to be set with a white value and/or color temperature. // This is used in three cases in HA: // - CW/WW lights, which set the "brightness" and "color_temperature" @@ -407,8 +405,8 @@ void LightCall::transform_parameters_() { } } } -ColorMode LightCall::compute_color_mode_() { - auto supported_modes = this->parent_->get_traits().get_supported_color_modes(); +ColorMode LightCall::compute_color_mode_(const LightTraits &traits) { + auto supported_modes = traits.get_supported_color_modes(); int supported_count = supported_modes.size(); // Some lights don't support any color modes (e.g. monochromatic light), leave it at unknown. diff --git a/esphome/components/light/light_call.h b/esphome/components/light/light_call.h index 0eb1785239..88d29bd349 100644 --- a/esphome/components/light/light_call.h +++ b/esphome/components/light/light_call.h @@ -10,6 +10,7 @@ struct LogString; namespace light { class LightState; +class LightTraits; /** This class represents a requested change in a light state. * @@ -188,11 +189,11 @@ class LightCall { LightColorValues validate_(); //// Compute the color mode that should be used for this call. - ColorMode compute_color_mode_(); + ColorMode compute_color_mode_(const LightTraits &traits); /// Get potential color modes bitmask for this light call. color_mode_bitmask_t get_suitable_color_modes_mask_(); /// Some color modes also can be set using non-native parameters, transform those calls. - void transform_parameters_(); + void transform_parameters_(const LightTraits &traits); // Bitfield flags - each flag indicates whether a corresponding value has been set. enum FieldFlags : uint16_t { From 4969fd6e99c40209cebe9d1d385aacee3d950abe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:28:41 -1000 Subject: [PATCH 1919/2030] [light] Use reciprocal multiply in normalize_color (#15401) --- esphome/components/light/light_color_values.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/light/light_color_values.h b/esphome/components/light/light_color_values.h index a2c2dbca46..fa286a3941 100644 --- a/esphome/components/light/light_color_values.h +++ b/esphome/components/light/light_color_values.h @@ -104,9 +104,10 @@ class LightColorValues { this->green_ = 1.0f; this->blue_ = 1.0f; } else { - this->red_ /= max_value; - this->green_ /= max_value; - this->blue_ /= max_value; + float inv = 1.0f / max_value; + this->red_ *= inv; + this->green_ *= inv; + this->blue_ *= inv; } } } From d90e2a6a9aa9241478366f110a5ab2eddaba2b65 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 08:28:54 -1000 Subject: [PATCH 1920/2030] [core] Use __builtin_ctz for FiniteSetMask bit scanning (#15400) --- esphome/core/finite_set_mask.h | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/esphome/core/finite_set_mask.h b/esphome/core/finite_set_mask.h index f9cd0377c7..616c69353d 100644 --- a/esphome/core/finite_set_mask.h +++ b/esphome/core/finite_set_mask.h @@ -119,7 +119,7 @@ template<typename ValueType, typename BitPolicy = DefaultBitPolicy<ValueType, 16 constexpr ValueType operator*() const { // Return value for the first set bit - return BitPolicy::from_bit(find_next_set_bit(mask_, 0)); + return BitPolicy::from_bit(find_lowest_set_bit(mask_)); } constexpr Iterator &operator++() { @@ -151,17 +151,32 @@ template<typename ValueType, typename BitPolicy = DefaultBitPolicy<ValueType, 16 /// Get the first value from a raw bitmask /// Used for optimizing intersection logic (e.g., "pick first suitable mode") static constexpr ValueType first_value_from_mask(bitmask_t mask) { - return BitPolicy::from_bit(find_next_set_bit(mask, 0)); + return BitPolicy::from_bit(find_lowest_set_bit(mask)); } - /// Find the next set bit in a bitmask starting from a given position - /// Returns the bit position, or MAX_BITS if no more bits are set - static constexpr int find_next_set_bit(bitmask_t mask, int start_bit) { - int bit = start_bit; + /// Find the lowest set bit in a bitmask + /// Returns the bit position, or MAX_BITS if no bits are set + static constexpr int find_lowest_set_bit(bitmask_t mask) { + if (mask == 0) { + return BitPolicy::MAX_BITS; + } +#if defined(__GNUC__) || defined(__clang__) + int bit; + if constexpr (sizeof(bitmask_t) <= sizeof(unsigned int)) { + bit = __builtin_ctz(static_cast<unsigned int>(mask)); + } else if constexpr (sizeof(bitmask_t) <= sizeof(uint32_t)) { + bit = __builtin_ctzl(static_cast<uint32_t>(mask)); + } else { + bit = __builtin_ctzll(static_cast<uint64_t>(mask)); + } + return bit < BitPolicy::MAX_BITS ? bit : BitPolicy::MAX_BITS; +#else + int bit = 0; while (bit < BitPolicy::MAX_BITS && !(mask & (static_cast<bitmask_t>(1) << bit))) { ++bit; } return bit; +#endif } protected: From f8f65c1a7b8a96c7dca602294cd7a9aa919a6bfc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 09:42:37 -1000 Subject: [PATCH 1921/2030] Bump click from 8.3.1 to 8.3.2 (#15421) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index dd20600097..a8ec413b23 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ tzdata>=2021.1 # from time pyserial==3.5 platformio==6.1.19 esptool==5.2.0 -click==8.3.1 +click==8.3.2 esphome-dashboard==20260210.0 aioesphomeapi==44.8.1 zeroconf==0.148.0 From c6bb1fe1415bcb1cbd9120265307a377bb1b0be3 Mon Sep 17 00:00:00 2001 From: Bonne Eggleston <bonne@exciton.com.au> Date: Fri, 3 Apr 2026 13:24:02 -0700 Subject: [PATCH 1922/2030] [modbus] Add integration tests for server and server via controller (#14845) Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- tests/integration/conftest.py | 7 + .../fixtures/uart_mock_modbus.yaml | 6 +- .../uart_mock_modbus_no_threshold.yaml | 7 +- .../fixtures/uart_mock_modbus_server.yaml | 124 +++++ .../uart_mock_modbus_server_controller.yaml | 180 +++++++ ...ock_modbus_server_controller_multiple.yaml | 118 +++++ ...t_mock_modbus_server_controller_write.yaml | 330 ++++++++++++ .../fixtures/uart_mock_modbus_timing.yaml | 4 +- tests/integration/state_utils.py | 106 ++++ tests/integration/test_uart_mock_modbus.py | 483 ++++++++++-------- 10 files changed, 1136 insertions(+), 229 deletions(-) create mode 100644 tests/integration/fixtures/uart_mock_modbus_server.yaml create mode 100644 tests/integration/fixtures/uart_mock_modbus_server_controller.yaml create mode 100644 tests/integration/fixtures/uart_mock_modbus_server_controller_multiple.yaml create mode 100644 tests/integration/fixtures/uart_mock_modbus_server_controller_write.yaml diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index b652b4174c..7c85bf753c 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -198,6 +198,13 @@ async def yaml_config(request: pytest.FixtureRequest, unused_tcp_port: int) -> s ' - "-g" # Add debug symbols', ) + # Replace external component path placeholder if present + if "EXTERNAL_COMPONENT_PATH" in content: + external_components_path = str( + Path(__file__).parent / "fixtures" / "external_components" + ) + content = content.replace("EXTERNAL_COMPONENT_PATH", external_components_path) + return content diff --git a/tests/integration/fixtures/uart_mock_modbus.yaml b/tests/integration/fixtures/uart_mock_modbus.yaml index 3ff7ab01bd..da36da4de1 100644 --- a/tests/integration/fixtures/uart_mock_modbus.yaml +++ b/tests/integration/fixtures/uart_mock_modbus.yaml @@ -22,6 +22,8 @@ uart_mock: baud_rate: 9600 rx_full_threshold: 120 rx_timeout: 2 + # auto_start must be false to avoid races: the test presses the + # "Start Scenario" button only after subscribing to states. auto_start: false debug: responses: @@ -46,7 +48,7 @@ modbus: modbus_controller: - address: 1 id: modbus_controller_ok - max_cmd_retries: 0 + max_cmd_retries: 2 update_interval: 1s - address: 2 id: modbus_controller_slow @@ -89,4 +91,4 @@ button: name: "Start Scenario" id: start_scenario_btn on_press: - - lambda: 'id(virtual_uart_dev).start_scenario();' + - lambda: "id(virtual_uart_dev).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml b/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml index e3e8c8c8da..9bc4dc50e9 100644 --- a/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml +++ b/tests/integration/fixtures/uart_mock_modbus_no_threshold.yaml @@ -22,6 +22,8 @@ uart: uart_mock: - id: virtual_uart_dev baud_rate: 9600 + # auto_start must be false to avoid races: the test presses the + # "Start Scenario" button only after subscribing to states. auto_start: false debug: on_tx: @@ -40,7 +42,8 @@ uart_mock: 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uart_mock.inject_rx: # Second USB packet: rest of response (staged with 40ms latency) delay: 40ms - data: !lambda return{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + data: + !lambda return{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x6F,0xCC,0xCD,0x43,0x7C,0xB8,0x10,0x3D,0x38,0x51,0xEC, 0x43,0x81,0x1B,0xE7,0x3B,0x03,0x12,0x6F,0x50,0x1B}; @@ -61,4 +64,4 @@ button: name: "Start Scenario" id: start_scenario_btn on_press: - - lambda: 'id(virtual_uart_dev).start_scenario();' + - lambda: "id(virtual_uart_dev).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_server.yaml b/tests/integration/fixtures/uart_mock_modbus_server.yaml new file mode 100644 index 0000000000..b657a6fd21 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_server.yaml @@ -0,0 +1,124 @@ +esphome: + name: uart-mock-modbus-server-test + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_dev + baud_rate: 9600 + rx_full_threshold: 120 + rx_timeout: 2 + auto_start: false + debug: + injections: + - delay: 100ms + inject_rx: [0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x74, 0x0A] # Read holding register 3 on device 1 (basic_read) + - delay: 100ms + # Read holding register 7 on device 2 + # Reply from device 2 + # Read holding register 5 on device 1 (read_after_peer_response) + inject_rx: + [ + 0x02, + 0x03, + 0x00, + 0x07, + 0x00, + 0x01, + 0x35, + 0xF8, + 0x02, + 0x03, + 0x02, + 0x00, + 0xF0, + 0xFC, + 0x00, + 0x01, + 0x03, + 0x00, + 0x05, + 0x00, + 0x01, + 0x94, + 0x0B, + ] + - delay: 100ms + inject_rx: [0x02, 0x03, 0x00, 0x07, 0x00, 0x01, 0x35, 0xF8] # Read holding register 7 on device 2, with no response + - delay: 100ms + # Read holding register 7 on device 2, with no response + # Read holding register A on device 1 (read_after_peer_timeout) + inject_rx: + [ + 0x02, + 0x03, + 0x00, + 0x07, + 0x00, + 0x01, + 0x35, + 0xF8, + 0x01, + 0x03, + 0x00, + 0x0A, + 0x00, + 0x01, + 0xA4, + 0x08, + ] + +modbus: + uart_id: virtual_uart_dev + role: server + +modbus_controller: + - address: 1 + server_registers: + - address: 0x03 + value_type: U_WORD + read_lambda: |- + id(basic_read).publish_state(1); + return 1; + - address: 0x05 + value_type: U_WORD + read_lambda: |- + id(read_after_peer_response).publish_state(1); + return 1; + - address: 0x0A + value_type: U_WORD + read_lambda: |- + id(read_after_peer_timeout).publish_state(1); + return 1; + +sensor: + - platform: template + name: "basic_read" + id: basic_read + - platform: template + name: "read_after_peer_response" + id: read_after_peer_response + - platform: template + name: "read_after_peer_timeout" + id: read_after_peer_timeout + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: "id(virtual_uart_dev).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_server_controller.yaml b/tests/integration/fixtures/uart_mock_modbus_server_controller.yaml new file mode 100644 index 0000000000..f0f2c56a36 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_server_controller.yaml @@ -0,0 +1,180 @@ +esphome: + name: uart-mock-modbus-server-contro + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_server + baud_rate: 9600 + # auto_start must be true for loopback fixtures: the modbus controller + # polls on its update_interval immediately at boot, so the uart_mock + # forwarding must already be active or early requests are lost and + # generate modbus warnings. + auto_start: true + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_controller + data: !lambda return data; + - id: virtual_uart_controller + baud_rate: 9600 + auto_start: true # See comment on virtual_uart_server above + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_server + data: !lambda return data; + +modbus: + - uart_id: virtual_uart_server + id: virtual_modbus_server + role: server + - uart_id: virtual_uart_controller + id: virtual_modbus_controller + role: client + turnaround_time: 10ms + +modbus_controller: + - address: 1 + modbus_id: virtual_modbus_controller + update_interval: 1s + id: modbus_controller_1 + + - address: 1 + modbus_id: virtual_modbus_server + id: modbus_server_1 + server_registers: + - address: 0x01 + value_type: U_WORD + read_lambda: return 99; + - address: 0x03 + value_type: S_WORD + read_lambda: return -99; + - address: 0x05 + value_type: U_DWORD + read_lambda: return 16909060; + - address: 0x08 + value_type: S_DWORD + read_lambda: return -16909060; + - address: 0x0B + value_type: U_DWORD_R + read_lambda: return 67305985; + - address: 0x0E + value_type: S_DWORD_R + read_lambda: return -67305985; + - address: 0x11 + value_type: U_QWORD + read_lambda: return 72623859790382856; + - address: 0x16 + value_type: S_QWORD + read_lambda: return -72623859790382856; + - address: 0x1B + value_type: U_QWORD_R + read_lambda: return 578437695752307201; + - address: 0x20 + value_type: S_QWORD_R + read_lambda: return -578437695752307201; + - address: 0x25 + value_type: FP32 + read_lambda: return 3.14; + - address: 0x28 + value_type: FP32_R + read_lambda: return 3.14; + +sensor: + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_word" + address: 0x01 + register_type: holding + value_type: U_WORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_word" + address: 0x03 + register_type: holding + value_type: S_WORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_dword" + address: 0x05 + register_type: holding + value_type: U_DWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_dword" + address: 0x08 + register_type: holding + value_type: S_DWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_dword_r" + address: 0x0B + register_type: holding + value_type: U_DWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_dword_r" + address: 0x0E + register_type: holding + value_type: S_DWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_qword" + address: 0x11 + register_type: holding + value_type: U_QWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_qword" + address: 0x16 + register_type: holding + value_type: S_QWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_qword_r" + address: 0x1B + register_type: holding + value_type: U_QWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_qword_r" + address: 0x20 + register_type: holding + value_type: S_QWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_fp32" + address: 0x25 + register_type: holding + value_type: FP32 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_fp32_r" + address: 0x28 + register_type: holding + value_type: FP32_R + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: "id(virtual_uart_server).start_scenario();" + - lambda: "id(virtual_uart_controller).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_server_controller_multiple.yaml b/tests/integration/fixtures/uart_mock_modbus_server_controller_multiple.yaml new file mode 100644 index 0000000000..7ec67b03db --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_server_controller_multiple.yaml @@ -0,0 +1,118 @@ +esphome: + name: uart-mock-modbus-server-mult + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_server + baud_rate: 9600 + # auto_start must be true for loopback fixtures: the modbus controller + # polls on its update_interval immediately at boot, so the uart_mock + # forwarding must already be active or early requests are lost and + # generate modbus warnings. + auto_start: true + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_controller + data: !lambda return data; + - uart_mock.inject_rx: + id: virtual_uart_server_2 + data: !lambda return data; + - id: virtual_uart_server_2 + baud_rate: 9600 + auto_start: true # See comment on virtual_uart_server above + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_server + data: !lambda return data; + - uart_mock.inject_rx: + id: virtual_uart_controller + data: !lambda return data; + - id: virtual_uart_controller + baud_rate: 9600 + auto_start: true # See comment on virtual_uart_server above + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_server + data: !lambda return data; + - uart_mock.inject_rx: + id: virtual_uart_server_2 + data: !lambda return data; + +modbus: + - uart_id: virtual_uart_server + id: virtual_modbus_server + role: server + - uart_id: virtual_uart_server_2 + id: virtual_modbus_server_2 + role: server + - uart_id: virtual_uart_controller + id: virtual_modbus_client + role: client + turnaround_time: 10ms + +modbus_controller: + - address: 1 + modbus_id: virtual_modbus_client + update_interval: 1s + id: modbus_controller_1 + - address: 2 + modbus_id: virtual_modbus_client + update_interval: 1s + id: modbus_controller_2 + + - address: 1 + modbus_id: virtual_modbus_server + server_registers: + - address: 0x01 + value_type: U_WORD + read_lambda: return 919; + - address: 2 + modbus_id: virtual_modbus_server_2 + server_registers: + - address: 0x01 + value_type: U_WORD + read_lambda: return 929; + +sensor: + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_word" + address: 0x01 + register_type: holding + value_type: U_WORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_2 + name: "reg_u_word_2" + address: 0x01 + register_type: holding + value_type: U_WORD + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: "id(virtual_uart_server).start_scenario();" + - lambda: "id(virtual_uart_server_2).start_scenario();" + - lambda: "id(virtual_uart_controller).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_server_controller_write.yaml b/tests/integration/fixtures/uart_mock_modbus_server_controller_write.yaml new file mode 100644 index 0000000000..3edcc73f07 --- /dev/null +++ b/tests/integration/fixtures/uart_mock_modbus_server_controller_write.yaml @@ -0,0 +1,330 @@ +esphome: + name: uart-mock-modbus-srv-write + +host: +api: +logger: + level: VERBOSE + +external_components: + - source: + type: local + path: EXTERNAL_COMPONENT_PATH + +# Dummy uart entry to satisfy modbus's DEPENDENCIES = ["uart"] +# The actual UART bus used is the uart_mock component below +uart: + baud_rate: 115200 + port: /dev/null + +uart_mock: + - id: virtual_uart_server + baud_rate: 9600 + # auto_start must be true for loopback fixtures: the modbus controller + # polls on its update_interval immediately at boot, so the uart_mock + # forwarding must already be active or early requests are lost and + # generate modbus warnings. + auto_start: true + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_controller + data: !lambda return data; + - id: virtual_uart_controller + baud_rate: 9600 + auto_start: true # See comment on virtual_uart_server above + debug: + on_tx: + - then: + - uart_mock.inject_rx: + id: virtual_uart_server + data: !lambda return data; + +globals: + - id: stored_u_word + type: uint16_t + initial_value: "11" + - id: stored_s_word + type: int16_t + initial_value: "-11" + - id: stored_u_dword + type: uint32_t + initial_value: "1001" + - id: stored_s_dword + type: int32_t + initial_value: "-1001" + - id: stored_u_dword_r + type: uint32_t + initial_value: "3003" + - id: stored_s_dword_r + type: int32_t + initial_value: "-3003" + - id: stored_u_qword + type: uint64_t + initial_value: "5005" + - id: stored_s_qword + type: int64_t + initial_value: "-5005" + - id: stored_u_qword_r + type: uint64_t + initial_value: "7007" + - id: stored_s_qword_r + type: int64_t + initial_value: "-7007" + - id: stored_fp32 + type: float + initial_value: "1.5" + - id: stored_fp32_r + type: float + initial_value: "2.5" + +modbus: + - uart_id: virtual_uart_server + id: virtual_modbus_server + role: server + - uart_id: virtual_uart_controller + id: virtual_modbus_controller + role: client + turnaround_time: 10ms + +modbus_controller: + - address: 1 + modbus_id: virtual_modbus_controller + update_interval: 2s + id: modbus_controller_1 + + - address: 1 + modbus_id: virtual_modbus_server + id: modbus_server_1 + server_registers: + - address: 0x01 + value_type: U_WORD + read_lambda: return id(stored_u_word); + write_lambda: id(stored_u_word) = x; return true; + - address: 0x03 + value_type: S_WORD + read_lambda: return id(stored_s_word); + write_lambda: id(stored_s_word) = x; return true; + - address: 0x05 + value_type: U_DWORD + read_lambda: return id(stored_u_dword); + write_lambda: id(stored_u_dword) = x; return true; + - address: 0x08 + value_type: S_DWORD + read_lambda: return id(stored_s_dword); + write_lambda: id(stored_s_dword) = x; return true; + - address: 0x0B + value_type: U_DWORD_R + read_lambda: return id(stored_u_dword_r); + write_lambda: id(stored_u_dword_r) = x; return true; + - address: 0x0E + value_type: S_DWORD_R + read_lambda: return id(stored_s_dword_r); + write_lambda: id(stored_s_dword_r) = x; return true; + - address: 0x11 + value_type: U_QWORD + read_lambda: return id(stored_u_qword); + write_lambda: id(stored_u_qword) = x; return true; + - address: 0x16 + value_type: S_QWORD + read_lambda: return id(stored_s_qword); + write_lambda: id(stored_s_qword) = x; return true; + - address: 0x1B + value_type: U_QWORD_R + read_lambda: return id(stored_u_qword_r); + write_lambda: id(stored_u_qword_r) = x; return true; + - address: 0x20 + value_type: S_QWORD_R + read_lambda: return id(stored_s_qword_r); + write_lambda: id(stored_s_qword_r) = x; return true; + - address: 0x25 + value_type: FP32 + read_lambda: return id(stored_fp32); + write_lambda: id(stored_fp32) = x; return true; + - address: 0x28 + value_type: FP32_R + read_lambda: return id(stored_fp32_r); + write_lambda: id(stored_fp32_r) = x; return true; + +sensor: + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_word" + address: 0x01 + register_type: holding + value_type: U_WORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_word" + address: 0x03 + register_type: holding + value_type: S_WORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_dword" + address: 0x05 + register_type: holding + value_type: U_DWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_dword" + address: 0x08 + register_type: holding + value_type: S_DWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_dword_r" + address: 0x0B + register_type: holding + value_type: U_DWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_dword_r" + address: 0x0E + register_type: holding + value_type: S_DWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_qword" + address: 0x11 + register_type: holding + value_type: U_QWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_qword" + address: 0x16 + register_type: holding + value_type: S_QWORD + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_u_qword_r" + address: 0x1B + register_type: holding + value_type: U_QWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_s_qword_r" + address: 0x20 + register_type: holding + value_type: S_QWORD_R + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_fp32" + address: 0x25 + register_type: holding + value_type: FP32 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "reg_fp32_r" + address: 0x28 + register_type: holding + value_type: FP32_R + +number: + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_u_word" + address: 0x01 + register_type: holding + value_type: U_WORD + min_value: 0 + max_value: 65535 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_s_word" + address: 0x03 + register_type: holding + value_type: S_WORD + min_value: -16777215 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_u_dword" + address: 0x05 + register_type: holding + value_type: U_DWORD + min_value: 0 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_s_dword" + address: 0x08 + register_type: holding + value_type: S_DWORD + min_value: -16777215 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_u_dword_r" + address: 0x0B + register_type: holding + value_type: U_DWORD_R + min_value: 0 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_s_dword_r" + address: 0x0E + register_type: holding + value_type: S_DWORD_R + min_value: -16777215 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_u_qword" + address: 0x11 + register_type: holding + value_type: U_QWORD + min_value: 0 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_s_qword" + address: 0x16 + register_type: holding + value_type: S_QWORD + min_value: -16777215 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_u_qword_r" + address: 0x1B + register_type: holding + value_type: U_QWORD_R + min_value: 0 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_s_qword_r" + address: 0x20 + register_type: holding + value_type: S_QWORD_R + min_value: -16777215 + max_value: 16777215 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_fp32" + address: 0x25 + register_type: holding + value_type: FP32 + min_value: -16777215 + max_value: 16777215 + step: 0.01 + - platform: modbus_controller + modbus_controller_id: modbus_controller_1 + name: "write_fp32_r" + address: 0x28 + register_type: holding + value_type: FP32_R + min_value: -16777215 + max_value: 16777215 + step: 0.01 + +button: + - platform: template + name: "Start Scenario" + id: start_scenario_btn + on_press: + - lambda: "id(virtual_uart_server).start_scenario();" + - lambda: "id(virtual_uart_controller).start_scenario();" diff --git a/tests/integration/fixtures/uart_mock_modbus_timing.yaml b/tests/integration/fixtures/uart_mock_modbus_timing.yaml index f4cf0bde37..c670864085 100644 --- a/tests/integration/fixtures/uart_mock_modbus_timing.yaml +++ b/tests/integration/fixtures/uart_mock_modbus_timing.yaml @@ -22,6 +22,8 @@ uart_mock: baud_rate: 9600 rx_full_threshold: 120 rx_timeout: 2 + # auto_start must be false to avoid races: the test presses the + # "Start Scenario" button only after subscribing to states. auto_start: false debug: on_tx: @@ -61,4 +63,4 @@ button: name: "Start Scenario" id: start_scenario_btn on_press: - - lambda: 'id(virtual_uart_dev).start_scenario();' + - lambda: "id(virtual_uart_dev).start_scenario();" diff --git a/tests/integration/state_utils.py b/tests/integration/state_utils.py index 5792a8e804..d42b50ecdb 100644 --- a/tests/integration/state_utils.py +++ b/tests/integration/state_utils.py @@ -346,3 +346,109 @@ class SensorStateCollector: else: self._waiters.append((condition, future)) return future + + +class SensorTracker: + """Data-driven sensor state tracker with expected-value futures. + + Tracks sensor state updates and resolves futures when sensors report + specific expected values. Eliminates per-sensor future boilerplate. + + Usage:: + + tracker = SensorTracker(["reg_u_word", "reg_s_word"]) + futures = tracker.expect_all({"reg_u_word": 99, "reg_s_word": -99}) + # ... subscribe_states with tracker.on_state, start scenario ... + await tracker.await_all(futures) + """ + + def __init__(self, sensor_names: list[str]) -> None: + self.sensor_states: dict[str, list[float]] = {name: [] for name in sensor_names} + self.key_to_sensor: dict[int, str] = {} + self._expectations: dict[str, list[tuple[object, asyncio.Future]]] = {} + + _ANY = object() # Sentinel: match any value + + def expect(self, name: str, value: object) -> asyncio.Future: + """Register an expected value for *name* and return a future for it.""" + future: asyncio.Future = asyncio.get_running_loop().create_future() + self._expectations.setdefault(name, []).append((value, future)) + return future + + def expect_any(self, name: str) -> asyncio.Future: + """Register a future that resolves on *any* state update for *name*.""" + return self.expect(name, self._ANY) + + def expect_all(self, expected: dict[str, object]) -> dict[str, asyncio.Future]: + """Call ``expect`` for every entry and return a dict of futures.""" + return {name: self.expect(name, value) for name, value in expected.items()} + + def on_state(self, state: EntityState) -> None: + """State callback suitable for ``subscribe_states``.""" + if not isinstance(state, SensorState) or state.missing_state: + return + sensor_name = self.key_to_sensor.get(state.key) + if not sensor_name or sensor_name not in self.sensor_states: + return + self.sensor_states[sensor_name].append(state.state) + for expected_value, future in self._expectations.get(sensor_name, []): + if not future.done() and ( + expected_value is self._ANY or state.state == expected_value + ): + future.set_result(True) + break + + async def await_change( + self, future: asyncio.Future, name: str, timeout: float = 2.0 + ) -> None: + """Wait for a sensor future to resolve; fail the test on timeout.""" + try: + await asyncio.wait_for(future, timeout=timeout) + except TimeoutError: + import pytest + + pytest.fail( + f"Timeout waiting for {name} change. Received sensor states:\n" + f" {name}: {self.sensor_states[name]}\n" + ) + + async def await_must_not_change( + self, future: asyncio.Future, name: str, timeout: float = 2.0 + ) -> None: + """Assert a sensor future does NOT resolve within the timeout.""" + try: + await asyncio.wait_for(future, timeout=timeout) + except TimeoutError: + return # Expected + import pytest + + pytest.fail( + f"{name} change should not have been triggered, but was. " + f"Received sensor states:\n {name}: {self.sensor_states[name]}\n" + ) + + async def await_all( + self, futures: dict[str, asyncio.Future], timeout: float = 2.0 + ) -> None: + """Await every future in *futures*, failing with per-sensor diagnostics.""" + for name, future in futures.items(): + await self.await_change(future, name, timeout=timeout) + + async def setup_and_start_scenario(self, client) -> list: + """Wire up subscriptions, wait for initial states, press Start Scenario.""" + entities, _ = await client.list_entities_services() + self.key_to_sensor.update( + build_key_to_entity_mapping(entities, list(self.sensor_states.keys())) + ) + initial_state_helper = InitialStateHelper(entities) + client.subscribe_states(initial_state_helper.on_state_wrapper(self.on_state)) + try: + await initial_state_helper.wait_for_initial_states() + except TimeoutError: + import pytest + + pytest.fail("Timeout waiting for initial states") + start_btn = find_entity(entities, "start_scenario", ButtonInfo) + assert start_btn is not None, "Start Scenario button not found" + client.button_command(start_btn.key) + return entities diff --git a/tests/integration/test_uart_mock_modbus.py b/tests/integration/test_uart_mock_modbus.py index e341d86f53..e8dfa1b822 100644 --- a/tests/integration/test_uart_mock_modbus.py +++ b/tests/integration/test_uart_mock_modbus.py @@ -14,15 +14,67 @@ test_uart_mock_modbus_no_threshold : from __future__ import annotations import asyncio -from pathlib import Path +from collections.abc import Callable +from dataclasses import dataclass -from aioesphomeapi import ButtonInfo, EntityState, SensorState +from aioesphomeapi import NumberInfo import pytest -from .state_utils import InitialStateHelper, build_key_to_entity_mapping, find_entity +from .state_utils import SensorTracker, find_entity from .types import APIClientConnectedFactory, RunCompiledFunction +@dataclass +class RegisterTestCase: + """Test parameters for a single modbus register write/read round-trip.""" + + initial_value: object + write_number_name: str + write_value: float + post_write_value: object + + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_modbus_line_callback() -> tuple[Callable[[str], None], list[str], list[str]]: + """Return a (callback, error_lines, warning_lines) tuple for tracking modbus log output. + + Only captures bus-level modbus messages ([modbus:]), not modbus_controller + scheduling noise (e.g. "Duplicate modbus command found"). + """ + error_log_lines: list[str] = [] + warning_log_lines: list[str] = [] + + def line_callback(line: str) -> None: + if "[E][modbus:" in line: + error_log_lines.append(line) + if "[W][modbus:" in line: + warning_log_lines.append(line) + + return line_callback, error_log_lines, warning_log_lines + + +def _assert_no_modbus_errors( + error_log_lines: list[str], warning_log_lines: list[str] +) -> None: + assert len(error_log_lines) == 0, ( + "Expect no errors logged by the modbus mock, but got:\n" + + "\n".join(error_log_lines) + ) + assert len(warning_log_lines) == 0, ( + "Expect no warnings logged by the modbus mock, but got:\n" + + "\n".join(warning_log_lines) + ) + + +# --------------------------------------------------------------------------- +# Tests +# --------------------------------------------------------------------------- + + @pytest.mark.asyncio async def test_uart_mock_modbus( yaml_config: str, @@ -30,127 +82,41 @@ async def test_uart_mock_modbus( api_client_connected: APIClientConnectedFactory, ) -> None: """Test basic modbus data parsing.""" - # Replace external component path placeholder - external_components_path = str( - Path(__file__).parent / "fixtures" / "external_components" + + tracker = SensorTracker( + [ + "basic_register", + "delayed_response", + "late_response", + "no_response", + "exception_response", + ] ) - yaml_config = yaml_config.replace( - "EXTERNAL_COMPONENT_PATH", external_components_path - ) - - loop = asyncio.get_running_loop() - - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "basic_register": [], - "delayed_response": [], - "late_response": [], - "no_response": [], - "exception_response": [], - } - - basic_register_changed = loop.create_future() - delayed_response_changed = loop.create_future() - late_response_changed = loop.create_future() - no_response_changed = loop.create_future() - exception_response_changed = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - if ( - sensor_name == "basic_register" - and state.state == 259.0 - and not basic_register_changed.done() - ): - basic_register_changed.set_result(True) - elif ( - sensor_name == "delayed_response" - and state.state == 255.0 - and not delayed_response_changed.done() - ): - delayed_response_changed.set_result(True) - elif ( - sensor_name == "late_response" and not late_response_changed.done() - ): - late_response_changed.set_result(True) - elif sensor_name == "no_response" and not no_response_changed.done(): - no_response_changed.set_result(True) - elif ( - sensor_name == "exception_response" - and not exception_response_changed.done() - ): - exception_response_changed.set_result(True) + basic_register_changed = tracker.expect("basic_register", 259.0) + delayed_response_changed = tracker.expect("delayed_response", 255.0) + # late_response / no_response / exception_response: expect *any* value + # (these should never fire, so we use a permissive match via expect_any) + late_response_changed = tracker.expect_any("late_response") + no_response_changed = tracker.expect_any("no_response") + exception_response_changed = tracker.expect_any("exception_response") async with ( run_compiled(yaml_config), api_client_connected() as client, ): - entities, _ = await client.list_entities_services() + await tracker.setup_and_start_scenario(client) - # Build key mappings for all sensor types - all_names = list(sensor_states.keys()) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) - - # Set up initial state helper - initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) - - try: - await initial_state_helper.wait_for_initial_states() - except TimeoutError: - pytest.fail("Timeout waiting for initial states") - - # Start the UART mock scenario now that we're subscribed - start_btn = find_entity(entities, "start_scenario", ButtonInfo) - assert start_btn is not None, "Start Scenario button not found" - client.button_command(start_btn.key) - - try: - await asyncio.wait_for(delayed_response_changed, timeout=2.0) - except TimeoutError: - pytest.fail( - f"Timeout waiting for delayed_response change. Received sensor states:\n" - f" delayed_response: {sensor_states['delayed_response']}\n" - ) - - try: - await asyncio.wait_for(late_response_changed, timeout=2.0) - pytest.fail( - f"late_response change should not have been triggered, but was. Received sensor states:\n" - f" late_response: {sensor_states['late_response']}\n" - ) - except TimeoutError: - pass # Expected timeout since we never inject a response for late_response - - try: - await asyncio.wait_for(no_response_changed, timeout=2.0) - pytest.fail( - f"no_response change should not have been triggered, but was. Received sensor states:\n" - f" no_response: {sensor_states['no_response']}\n" - ) - except TimeoutError: - pass # Expected timeout since we never inject a response for no_response - - # Wait for basic register to be updated with successful parse - try: - await asyncio.wait_for(basic_register_changed, timeout=2.0) - except TimeoutError: - pytest.fail( - f"Timeout waiting for Basic Register change. Received sensor states:\n" - f" basic_register: {sensor_states['basic_register']}\n" - ) - - try: - await asyncio.wait_for(exception_response_changed, timeout=2.0) - pytest.fail( - f"exception_response change should not have been triggered, but was. Received sensor states:\n" - f" exception_response: {sensor_states['exception_response']}\n" - ) - except TimeoutError: - pass + await tracker.await_change(delayed_response_changed, "delayed_response") + await tracker.await_change(basic_register_changed, "basic_register") + # Run all "must not change" checks concurrently — each waits the full + # timeout, so sequential execution would multiply the wall time. + await asyncio.gather( + tracker.await_must_not_change(late_response_changed, "late_response"), + tracker.await_must_not_change(no_response_changed, "no_response"), + tracker.await_must_not_change( + exception_response_changed, "exception_response" + ), + ) @pytest.mark.asyncio @@ -159,69 +125,17 @@ async def test_uart_mock_modbus_timing( run_compiled: RunCompiledFunction, api_client_connected: APIClientConnectedFactory, ) -> None: - """Test basic modbus data parsing.""" - # Replace external component path placeholder - external_components_path = str( - Path(__file__).parent / "fixtures" / "external_components" - ) - yaml_config = yaml_config.replace( - "EXTERNAL_COMPONENT_PATH", external_components_path - ) + """Test modbus timing with multi-register SDM meter response.""" - loop = asyncio.get_running_loop() - - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "sdm_voltage": [], - } - - voltage_changed = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - # Check if this is a good voltage reading (243V) - if ( - sensor_name == "sdm_voltage" - and state.state > 200.0 - and not voltage_changed.done() - ): - voltage_changed.set_result(True) + tracker = SensorTracker(["sdm_voltage"]) + voltage_changed = tracker.expect_any("sdm_voltage") async with ( run_compiled(yaml_config), api_client_connected() as client, ): - entities, _ = await client.list_entities_services() - - # Build key mappings for all sensor types - all_names = list(sensor_states.keys()) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) - - # Set up initial state helper - initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) - - try: - await initial_state_helper.wait_for_initial_states() - except TimeoutError: - pytest.fail("Timeout waiting for initial states") - - # Start the UART mock scenario now that we're subscribed - start_btn = find_entity(entities, "start_scenario", ButtonInfo) - assert start_btn is not None, "Start Scenario button not found" - client.button_command(start_btn.key) - - # Wait for voltage to be updated with successful parse - try: - await asyncio.wait_for(voltage_changed, timeout=2.0) - except TimeoutError: - pytest.fail( - f"Timeout waiting for SDM voltage change. Received sensor states:\n" - f" sdm_voltage: {sensor_states['sdm_voltage']}\n" - ) + await tracker.setup_and_start_scenario(client) + await tracker.await_change(voltage_changed, "sdm_voltage") @pytest.mark.asyncio @@ -234,66 +148,187 @@ async def test_uart_mock_modbus_no_threshold( Without the 50ms fallback timeout, the chunked response with a 40ms gap between USB packets would cause a false timeout and CRC failure cascade. + Bus-level warnings (CRC failures, buffer clears) are expected during + chunked reassembly — the test only verifies the final value arrives. """ - # Replace external component path placeholder - external_components_path = str( - Path(__file__).parent / "fixtures" / "external_components" - ) - yaml_config = yaml_config.replace( - "EXTERNAL_COMPONENT_PATH", external_components_path - ) - loop = asyncio.get_running_loop() - - # Track sensor state updates (after initial state is swallowed) - sensor_states: dict[str, list[float]] = { - "sdm_voltage": [], - } - - voltage_changed = loop.create_future() - - def on_state(state: EntityState) -> None: - if isinstance(state, SensorState) and not state.missing_state: - sensor_name = key_to_sensor.get(state.key) - if sensor_name and sensor_name in sensor_states: - sensor_states[sensor_name].append(state.state) - # Check if this is a good voltage reading (243V) - if ( - sensor_name == "sdm_voltage" - and state.state > 200.0 - and not voltage_changed.done() - ): - voltage_changed.set_result(True) + tracker = SensorTracker(["sdm_voltage"]) + voltage_changed = tracker.expect_any("sdm_voltage") async with ( run_compiled(yaml_config), api_client_connected() as client, ): - entities, _ = await client.list_entities_services() + await tracker.setup_and_start_scenario(client) + await tracker.await_change(voltage_changed, "sdm_voltage") - # Build key mappings for all sensor types - all_names = list(sensor_states.keys()) - key_to_sensor = build_key_to_entity_mapping(entities, all_names) - # Set up initial state helper - initial_state_helper = InitialStateHelper(entities) - client.subscribe_states(initial_state_helper.on_state_wrapper(on_state)) +@pytest.mark.asyncio +@pytest.mark.xfail( + reason="Modbus parser cannot handle server responses from other devices on the bus. Fix tracked in PR #11969.", + strict=True, +) +async def test_uart_mock_modbus_server( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test modbus server parsing with peer traffic on a shared bus.""" - try: - await initial_state_helper.wait_for_initial_states() - except TimeoutError: - pytest.fail("Timeout waiting for initial states") + line_callback, error_log_lines, warning_log_lines = _make_modbus_line_callback() - # Start the UART mock scenario now that we're subscribed - start_btn = find_entity(entities, "start_scenario", ButtonInfo) - assert start_btn is not None, "Start Scenario button not found" - client.button_command(start_btn.key) + tracker = SensorTracker( + ["basic_read", "read_after_peer_response", "read_after_peer_timeout"] + ) + futures = tracker.expect_all( + { + "basic_read": 1, + "read_after_peer_response": 1, + "read_after_peer_timeout": 1, + } + ) - # Wait for voltage to be updated with successful parse - try: - await asyncio.wait_for(voltage_changed, timeout=2.0) - except TimeoutError: - pytest.fail( - f"Timeout waiting for SDM voltage change. Received sensor states:\n" - f" sdm_voltage: {sensor_states['sdm_voltage']}\n" + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + await tracker.setup_and_start_scenario(client) + await tracker.await_all(futures) + _assert_no_modbus_errors(error_log_lines, warning_log_lines) + + +@pytest.mark.asyncio +async def test_uart_mock_modbus_server_controller( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test server/controller functionality for all read register types.""" + + line_callback, error_log_lines, warning_log_lines = _make_modbus_line_callback() + + expected_values = { + "reg_u_word": 99, + "reg_s_word": -99, + "reg_u_dword": 16909060, + "reg_s_dword": -16909060, + "reg_u_dword_r": pytest.approx(67305985), + "reg_s_dword_r": pytest.approx(-67305985), + "reg_u_qword": pytest.approx(72623859790382856), + "reg_s_qword": pytest.approx(-72623859790382856), + "reg_u_qword_r": pytest.approx(578437695752307201), + "reg_s_qword_r": pytest.approx(-578437695752307201), + "reg_fp32": pytest.approx(3.14), + "reg_fp32_r": pytest.approx(3.14), + } + tracker = SensorTracker(list(expected_values.keys())) + futures = tracker.expect_all(expected_values) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + await tracker.setup_and_start_scenario(client) + await tracker.await_all(futures) + _assert_no_modbus_errors(error_log_lines, warning_log_lines) + + +@pytest.mark.asyncio +async def test_uart_mock_modbus_server_controller_write( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test server/controller write functionality for all register value types. + + Verifies that writing to modbus server registers via the controller updates + the server's stored values, which are then read back correctly on the next poll. + All 12 value types are tested: U/S_WORD, U/S_DWORD(_R), U/S_QWORD(_R), FP32(_R). + """ + + line_callback, error_log_lines, warning_log_lines = _make_modbus_line_callback() + + register_test_cases: dict[str, RegisterTestCase] = { + "reg_u_word": RegisterTestCase(11, "write_u_word", 42, 42), + "reg_s_word": RegisterTestCase(-11, "write_s_word", -42, -42), + "reg_u_dword": RegisterTestCase(1001, "write_u_dword", 2002, 2002), + "reg_s_dword": RegisterTestCase(-1001, "write_s_dword", -2002, -2002), + "reg_u_dword_r": RegisterTestCase(3003, "write_u_dword_r", 4004, 4004), + "reg_s_dword_r": RegisterTestCase(-3003, "write_s_dword_r", -4004, -4004), + "reg_u_qword": RegisterTestCase(5005, "write_u_qword", 6006, 6006), + "reg_s_qword": RegisterTestCase(-5005, "write_s_qword", -6006, -6006), + "reg_u_qword_r": RegisterTestCase(7007, "write_u_qword_r", 8008, 8008), + "reg_s_qword_r": RegisterTestCase(-7007, "write_s_qword_r", -8008, -8008), + "reg_fp32": RegisterTestCase( + pytest.approx(1.5, abs=0.01), + "write_fp32", + 3.14, + pytest.approx(3.14, abs=0.01), + ), + "reg_fp32_r": RegisterTestCase( + pytest.approx(2.5, abs=0.01), + "write_fp32_r", + 6.28, + pytest.approx(6.28, abs=0.01), + ), + } + + tracker = SensorTracker(list(register_test_cases.keys())) + + # Phase 1: expect initial baseline values + initial_futures = tracker.expect_all( + {name: case.initial_value for name, case in register_test_cases.items()} + ) + # Phase 2: expect post-write values (registered now so on_state can match them) + written_futures = tracker.expect_all( + {name: case.post_write_value for name, case in register_test_cases.items()} + ) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + entities = await tracker.setup_and_start_scenario(client) + + # Wait for initial baseline values to confirm the controller <-> server + # connection is working before issuing writes + await tracker.await_all(initial_futures, timeout=4.0) + + # Issue write commands for all register types + for case in register_test_cases.values(): + entity = find_entity(entities, case.write_number_name, NumberInfo) + assert entity is not None, ( + f"{case.write_number_name} number entity not found" ) + client.number_command(entity.key, case.write_value) + + # Wait for sensors to reflect the written values (round-trip write+read) + await tracker.await_all(written_futures, timeout=4.0) + _assert_no_modbus_errors(error_log_lines, warning_log_lines) + + +@pytest.mark.asyncio +@pytest.mark.xfail( + reason="Modbus parser cannot handle server responses from other devices on the bus. Fix tracked in PR #11969.", + strict=True, +) +async def test_uart_mock_modbus_server_controller_multiple( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test server/controller functionality with multiple servers.""" + + line_callback, error_log_lines, warning_log_lines = _make_modbus_line_callback() + + expected_values = {"reg_u_word": 919, "reg_u_word_2": 929} + tracker = SensorTracker(list(expected_values.keys())) + futures = tracker.expect_all(expected_values) + + async with ( + run_compiled(yaml_config, line_callback=line_callback), + api_client_connected() as client, + ): + await tracker.setup_and_start_scenario(client) + await tracker.await_all(futures) + _assert_no_modbus_errors(error_log_lines, warning_log_lines) From 533eeabf1d349bfb5912d6bcae012c5db8ff46c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 23:17:49 +0000 Subject: [PATCH 1923/2030] Bump aioesphomeapi from 44.8.1 to 44.9.0 (#15425) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a8ec413b23..9c63cdee27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.2 esphome-dashboard==20260210.0 -aioesphomeapi==44.8.1 +aioesphomeapi==44.9.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 7ab26a4fe0b5ef4770e76e65a39409be02557375 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 4 Apr 2026 12:21:58 +1000 Subject: [PATCH 1924/2030] [ili9xxx][st7735] Add deprecation warnings (#15416) --- esphome/components/ili9xxx/__init__.py | 4 ++++ esphome/components/ili9xxx/display.py | 3 +++ esphome/components/st7735/__init__.py | 5 +++++ esphome/components/st7735/display.py | 6 ++++++ 4 files changed, 18 insertions(+) diff --git a/esphome/components/ili9xxx/__init__.py b/esphome/components/ili9xxx/__init__.py index e69de29bb2..84888bbabc 100644 --- a/esphome/components/ili9xxx/__init__.py +++ b/esphome/components/ili9xxx/__init__.py @@ -0,0 +1,4 @@ +DEPRECATED_COMPONENT = """ +The 'ili9xxx' component is deprecated and no new models will be added to it. +New model PRs should target the newer and more performant 'mipi_spi' component. +""" diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 185a74fa41..1f20b21a0e 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -219,6 +219,9 @@ FINAL_VALIDATE_SCHEMA = final_validate async def to_code(config): + LOGGER.warning( + "The 'ili9xxx' component is deprecated, it is recommended to use 'mipi_spi' instead." + ) rhs = MODELS[config[CONF_MODEL]].new() var = cg.Pvariable(config[CONF_ID], rhs) diff --git a/esphome/components/st7735/__init__.py b/esphome/components/st7735/__init__.py index ba854bb0ae..62dfa6f413 100644 --- a/esphome/components/st7735/__init__.py +++ b/esphome/components/st7735/__init__.py @@ -1,3 +1,8 @@ import esphome.codegen as cg st7735_ns = cg.esphome_ns.namespace("st7735") + +DEPRECATED_COMPONENT = """ +The 'st7735' component is deprecated and no new models will be added to it. +New model PRs should target the newer and more performant 'mipi_spi' component. +""" diff --git a/esphome/components/st7735/display.py b/esphome/components/st7735/display.py index 9dc69f27ff..766370c21f 100644 --- a/esphome/components/st7735/display.py +++ b/esphome/components/st7735/display.py @@ -1,3 +1,5 @@ +import logging + from esphome import pins import esphome.codegen as cg from esphome.components import display, spi @@ -15,6 +17,7 @@ from esphome.const import ( from . import st7735_ns CODEOWNERS = ["@SenexCrenshaw"] +LOGGER = logging.getLogger(__name__) DEPENDENCIES = ["spi"] @@ -87,6 +90,9 @@ async def setup_st7735(var, config): async def to_code(config): + LOGGER.warning( + "The 'st7735' component is deprecated, it is recommended to use 'mipi_spi' instead." + ) var = cg.new_Pvariable( config[CONF_ID], config[CONF_MODEL], From 4f2290d5480afc7e97494ececb7334060e247030 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 16:37:20 -1000 Subject: [PATCH 1925/2030] [web_server] Disable loop when no SSE clients are connected (#15428) --- esphome/components/web_server/web_server.cpp | 17 +++++++++++++++-- esphome/components/web_server/web_server.h | 3 ++- .../web_server_idf/web_server_idf.cpp | 6 +++++- .../components/web_server_idf/web_server_idf.h | 3 ++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index 1dda6204fe..a57a8d26ff 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -286,10 +286,11 @@ void DeferredUpdateEventSource::try_send_nodefer(const char *message, const char this->send(message, event, id, reconnect); } -void DeferredUpdateEventSourceList::loop() { +bool DeferredUpdateEventSourceList::loop() { for (DeferredUpdateEventSource *dues : *this) { dues->loop(); } + return !this->empty(); } void DeferredUpdateEventSourceList::deferrable_send_state(void *source, const char *event_type, @@ -318,6 +319,7 @@ void DeferredUpdateEventSourceList::add_new_client(WebServer *ws, AsyncWebServer es->onDisconnect([this, es](AsyncEventSourceClient *client) { this->on_client_disconnect_(es); }); es->handleRequest(request); + ws->enable_loop_soon_any_context(); } void DeferredUpdateEventSourceList::on_client_connect_(DeferredUpdateEventSource *source) { @@ -413,13 +415,24 @@ void WebServer::setup() { // doesn't need defer functionality - if the queue is full, the client JS knows it's alive because it's clearly // getting a lot of events this->set_interval(10000, [this]() { + if (this->events_.empty()) + return; char buf[32]; auto uptime = static_cast<uint32_t>(millis_64() / 1000); buf_append_printf(buf, sizeof(buf), 0, "{\"uptime\":%" PRIu32 "}", uptime); this->events_.try_send_nodefer(buf, "ping", millis(), 30000); }); } -void WebServer::loop() { this->events_.loop(); } +void WebServer::loop() { + // No SSE clients connected; stop looping until a new client connects via + // enable_loop_soon_any_context(). This is safe because: + // - set_interval/set_timeout/defer run via the Scheduler, independent of loop() + // - deferrable_send_state early-outs when no clients are connected + // - try_send_nodefer (log, ping) iterates sessions which are empty + // - REST API handlers use defer() which runs via the Scheduler + if (!this->events_.loop()) + this->disable_loop(); +} #ifdef USE_LOGGER void WebServer::on_log(uint8_t level, const char *tag, const char *message, size_t message_len) { diff --git a/esphome/components/web_server/web_server.h b/esphome/components/web_server/web_server.h index 6152dfbfd3..8e8b1de8c4 100644 --- a/esphome/components/web_server/web_server.h +++ b/esphome/components/web_server/web_server.h @@ -169,7 +169,8 @@ class DeferredUpdateEventSourceList final : public std::list<DeferredUpdateEvent void on_client_disconnect_(DeferredUpdateEventSource *source); public: - void loop(); + /// Returns true if there are event sources remaining (including pending cleanup). + bool loop(); void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator); void try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0); diff --git a/esphome/components/web_server_idf/web_server_idf.cpp b/esphome/components/web_server_idf/web_server_idf.cpp index 38ccfccb76..8f464ae912 100644 --- a/esphome/components/web_server_idf/web_server_idf.cpp +++ b/esphome/components/web_server_idf/web_server_idf.cpp @@ -484,9 +484,12 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request) { this->on_connect_(rsp); } this->sessions_.push_back(rsp); + // Wake up WebServer::loop() to drain deferred event queues for this client. + // Safe from httpd task context via the pending_enable_loop_ flag. + this->web_server_->enable_loop_soon_any_context(); } -void AsyncEventSource::loop() { +bool AsyncEventSource::loop() { // Clean up dead sessions safely // This follows the ESP-IDF pattern where free_ctx marks resources as dead // and the main loop handles the actual cleanup to avoid race conditions @@ -504,6 +507,7 @@ void AsyncEventSource::loop() { ++i; } } + return !this->sessions_.empty(); } void AsyncEventSource::try_send_nodefer(const char *message, const char *event, uint32_t id, uint32_t reconnect) { diff --git a/esphome/components/web_server_idf/web_server_idf.h b/esphome/components/web_server_idf/web_server_idf.h index 81683e8d85..f2931fb507 100644 --- a/esphome/components/web_server_idf/web_server_idf.h +++ b/esphome/components/web_server_idf/web_server_idf.h @@ -340,7 +340,8 @@ class AsyncEventSource : public AsyncWebHandler { void try_send_nodefer(const char *message, const char *event = nullptr, uint32_t id = 0, uint32_t reconnect = 0); void deferrable_send_state(void *source, const char *event_type, message_generator_t *message_generator); - void loop(); + /// Returns true if there are sessions remaining (including pending cleanup). + bool loop(); bool empty() { return this->count() == 0; } size_t count() const { return this->sessions_.size(); } From 2337767c38e09c7e98e0289f2f3cb93a0234c3f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Fri, 3 Apr 2026 16:37:31 -1000 Subject: [PATCH 1926/2030] [modbus_controller] Fix format specifier warnings (#15429) --- .../components/modbus_controller/modbus_controller.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/modbus_controller/modbus_controller.cpp b/esphome/components/modbus_controller/modbus_controller.cpp index 3c4ceaf62d..5c3b39c954 100644 --- a/esphome/components/modbus_controller/modbus_controller.cpp +++ b/esphome/components/modbus_controller/modbus_controller.cpp @@ -376,7 +376,7 @@ size_t ModbusController::create_register_ranges_() { while (ix != this->sensorset_.end()) { SensorItem *curr = *ix; - ESP_LOGV(TAG, "Register: 0x%X %d %d %d offset=%u skip=%u addr=%p", curr->start_address, curr->register_count, + ESP_LOGV(TAG, "Register: 0x%X %d %d %zu offset=%u skip=%u addr=%p", curr->start_address, curr->register_count, curr->offset, curr->get_register_size(), curr->offset, curr->skip_updates, curr); if (r.register_count == 0) { @@ -484,18 +484,18 @@ void ModbusController::dump_config() { #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE ESP_LOGCONFIG(TAG, "sensormap"); for (auto &it : this->sensorset_) { - ESP_LOGCONFIG(TAG, " Sensor type=%zu start=0x%X offset=0x%X count=%d size=%d", + ESP_LOGCONFIG(TAG, " Sensor type=%u start=0x%X offset=0x%X count=%d size=%zu", static_cast<uint8_t>(it->register_type), it->start_address, it->offset, it->register_count, it->get_register_size()); } ESP_LOGCONFIG(TAG, "ranges"); for (auto &it : this->register_ranges_) { - ESP_LOGCONFIG(TAG, " Range type=%zu start=0x%X count=%d skip_updates=%d", static_cast<uint8_t>(it.register_type), + ESP_LOGCONFIG(TAG, " Range type=%u start=0x%X count=%d skip_updates=%d", static_cast<uint8_t>(it.register_type), it.start_address, it.register_count, it.skip_updates); } ESP_LOGCONFIG(TAG, "server registers"); for (auto &r : this->server_registers_) { - ESP_LOGCONFIG(TAG, " Address=0x%02X value_type=%zu register_count=%u", r->address, + ESP_LOGCONFIG(TAG, " Address=0x%02X value_type=%u register_count=%u", r->address, static_cast<uint8_t>(r->value_type), r->register_count); } #endif @@ -524,7 +524,7 @@ void ModbusController::on_write_register_response(ModbusRegisterType register_ty void ModbusController::dump_sensors_() { ESP_LOGV(TAG, "sensors"); for (auto &it : this->sensorset_) { - ESP_LOGV(TAG, " Sensor start=0x%X count=%d size=%d offset=%d", it->start_address, it->register_count, + ESP_LOGV(TAG, " Sensor start=0x%X count=%d size=%zu offset=%d", it->start_address, it->register_count, it->get_register_size(), it->offset); } } From 16ae753317b68022ce2763c72622280df8160a8d Mon Sep 17 00:00:00 2001 From: Boris Krivonog <boris.krivonog@inova.si> Date: Sat, 4 Apr 2026 07:44:04 +0200 Subject: [PATCH 1927/2030] [mitsubishi_cn105] Add climate component for Mitsubishi A/C units with CN105 connector (Part 2) (#15358) --- .../mitsubishi_cn105/mitsubishi_cn105.cpp | 188 ++++++++++++++++++ .../mitsubishi_cn105/mitsubishi_cn105.h | 26 +++ .../mitsubishi_cn105_climate.cpp | 5 +- .../mitsubishi_cn105_time.cpp | 7 + .../climate/mitsubishi_cn105_tests.cpp | 173 ++++++++++++++++ tests/components/mitsubishi_cn105/common.cpp | 7 + tests/components/mitsubishi_cn105/common.h | 53 +++++ 7 files changed, 457 insertions(+), 2 deletions(-) create mode 100644 esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp create mode 100644 tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp create mode 100644 tests/components/mitsubishi_cn105/common.cpp create mode 100644 tests/components/mitsubishi_cn105/common.h diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp index 35ab405b2d..e3923bb0b8 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp @@ -1,7 +1,195 @@ +#include <array> +#include <numeric> #include "mitsubishi_cn105.h" namespace esphome::mitsubishi_cn105 { static const char *const TAG = "mitsubishi_cn105.driver"; +static constexpr uint32_t WRITE_TIMEOUT_MS = 2000; + +static constexpr size_t HEADER_LEN = 5; +static constexpr uint8_t PREAMBLE = 0xFC; +static constexpr uint8_t HEADER_BYTE_1 = 0x01; +static constexpr uint8_t HEADER_BYTE_2 = 0x30; + +static constexpr uint8_t PACKET_TYPE_CONNECT_REQUEST = 0x5A; +static constexpr uint8_t PACKET_TYPE_CONNECT_RESPONSE = 0x7A; +static constexpr std::array<uint8_t, 2> CONNECT_REQUEST_PAYLOAD = {{0xCA, 0x01}}; + +static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) { + return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0})); +} + +template<std::size_t PayloadSize> +static constexpr auto make_packet(uint8_t type, const std::array<uint8_t, PayloadSize> &payload) { + const size_t full_len = PayloadSize + HEADER_LEN + 1; + std::array<uint8_t, full_len> packet{PREAMBLE, type, HEADER_BYTE_1, HEADER_BYTE_2, static_cast<uint8_t>(PayloadSize)}; + std::copy_n(payload.begin(), PayloadSize, packet.begin() + HEADER_LEN); + packet.back() = checksum(packet.data(), packet.size() - 1); + return packet; +} + +static constexpr auto CONNECT_PACKET = make_packet(PACKET_TYPE_CONNECT_REQUEST, CONNECT_REQUEST_PAYLOAD); + +void MitsubishiCN105::initialize() { this->set_state_(State::CONNECTING); } + +void MitsubishiCN105::update() { + if (const auto start = this->write_timeout_start_ms_; start && (get_loop_time_ms() - *start) >= WRITE_TIMEOUT_MS) { + this->write_timeout_start_ms_.reset(); + this->read_pos_ = 0; + this->set_state_(State::READ_TIMEOUT); + return; + } + + this->read_incoming_bytes_(); +} + +void MitsubishiCN105::set_state_(State new_state) { + if (should_transition(this->state_, new_state)) { + ESP_LOGV(TAG, "Did transition: %s -> %s", LOG_STR_ARG(state_to_string(this->state_)), + LOG_STR_ARG(state_to_string(new_state))); + this->state_ = new_state; + this->did_transition_(new_state); + } else { + ESP_LOGV(TAG, "Ignoring unexpected transition %s -> %s", LOG_STR_ARG(state_to_string(this->state_)), + LOG_STR_ARG(state_to_string(new_state))); + } +} + +bool MitsubishiCN105::should_transition(State from, State to) { + switch (to) { + case State::CONNECTING: + return from == State::NOT_CONNECTED || from == State::READ_TIMEOUT; + + case State::CONNECTED: + case State::READ_TIMEOUT: + return from == State::CONNECTING; + + default: + return false; + } +} + +void MitsubishiCN105::did_transition_(State to) { + switch (to) { + case State::CONNECTING: + this->send_packet_(CONNECT_PACKET); + break; + + case State::CONNECTED: + this->write_timeout_start_ms_.reset(); + // TODO: read AC status after connected, next PR + break; + + case State::READ_TIMEOUT: + this->set_state_(State::CONNECTING); + break; + + default: + break; + } +} + +void MitsubishiCN105::send_packet_(const uint8_t *packet, size_t len) { + dump_buffer_vv("TX", packet, len); + this->device_.write_array(packet, len); + this->write_timeout_start_ms_ = get_loop_time_ms(); +} + +void MitsubishiCN105::read_incoming_bytes_() { + uint8_t watchdog = 64; + while (this->device_.available() > 0 && watchdog-- > 0) { + uint8_t &value = this->read_buffer_[this->read_pos_]; + if (!this->device_.read_byte(&value)) { + ESP_LOGW(TAG, "UART read failed while data available"); + return; + } + + switch (++this->read_pos_) { + case 1: + if (value != PREAMBLE) { + this->reset_read_position_and_dump_buffer_("RX ignoring preamble"); + } + continue; + + case 2: + continue; + + case 3: + if (value != HEADER_BYTE_1) { + this->reset_read_position_and_dump_buffer_("RX invalid: header 1 mismatch"); + } + continue; + + case 4: + if (value != HEADER_BYTE_2) { + this->reset_read_position_and_dump_buffer_("RX invalid: header 2 mismatch"); + } + continue; + + case HEADER_LEN: + static_assert(READ_BUFFER_SIZE > HEADER_LEN); + if (this->read_buffer_[HEADER_LEN - 1] >= READ_BUFFER_SIZE - HEADER_LEN) { + this->reset_read_position_and_dump_buffer_("RX invalid: payload too large"); + } + continue; + + default: + break; + } + + const size_t len_without_checksum = HEADER_LEN + static_cast<size_t>(this->read_buffer_[HEADER_LEN - 1]); + if (this->read_pos_ <= len_without_checksum) { + continue; + } + + if (checksum(this->read_buffer_, len_without_checksum) != value) { + this->reset_read_position_and_dump_buffer_("RX invalid: checksum mismatch"); + continue; + } + + this->process_rx_packet_(this->read_buffer_[1], this->read_buffer_ + HEADER_LEN, len_without_checksum - HEADER_LEN); + this->reset_read_position_and_dump_buffer_("RX"); + } +} + +void MitsubishiCN105::process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len) { + switch (type) { + case PACKET_TYPE_CONNECT_RESPONSE: + this->set_state_(State::CONNECTED); + break; + + default: + ESP_LOGVV(TAG, "RX unknown packet type 0x%02X", type); + break; + } +} + +void MitsubishiCN105::reset_read_position_and_dump_buffer_(const char *prefix) { + dump_buffer_vv(prefix, this->read_buffer_, this->read_pos_); + this->read_pos_ = 0; +} + +void MitsubishiCN105::dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char buf[format_hex_pretty_size(READ_BUFFER_SIZE)]; + ESP_LOGVV(TAG, "%s (%zu): %s", prefix, len, format_hex_pretty_to(buf, data, len)); +#endif +} + +const LogString *MitsubishiCN105::state_to_string(State state) { + switch (state) { + case State::NOT_CONNECTED: + return LOG_STR("Not connected"); + case State::CONNECTING: + return LOG_STR("Connecting"); + case State::CONNECTED: + return LOG_STR("Connected"); + case State::READ_TIMEOUT: + return LOG_STR("ReadTimeout"); + } + return LOG_STR("Unknown"); +} + } // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h index 6018dddbff..fc09b3bed2 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h @@ -1,19 +1,45 @@ #pragma once +#include <optional> #include "esphome/components/uart/uart.h" namespace esphome::mitsubishi_cn105 { +uint32_t get_loop_time_ms(); + class MitsubishiCN105 { public: explicit MitsubishiCN105(uart::UARTDevice &device) : device_(device) {} + void initialize(); + void update(); + uint32_t get_update_interval() const { return this->update_interval_ms_; } void set_update_interval(uint32_t interval_ms) { this->update_interval_ms_ = interval_ms; } protected: + enum class State : uint8_t { NOT_CONNECTED, CONNECTING, CONNECTED, READ_TIMEOUT }; + + void set_state_(State new_state); + void did_transition_(State to); + void read_incoming_bytes_(); + void process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len); + void reset_read_position_and_dump_buffer_(const char *prefix); + void send_packet_(const uint8_t *packet, size_t len); + template<typename T> void send_packet_(const T &packet) { this->send_packet_(packet.data(), packet.size()); } + static bool should_transition(State from, State to); + static const LogString *state_to_string(State state); + static void dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len); + uart::UARTDevice &device_; uint32_t update_interval_ms_{1000}; + std::optional<uint32_t> write_timeout_start_ms_; + State state_{State::NOT_CONNECTED}; + + private: + static constexpr size_t READ_BUFFER_SIZE = 32; + uint8_t read_buffer_[READ_BUFFER_SIZE]; + uint8_t read_pos_{0}; }; } // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp index 6d50296c8f..cce6bef5e4 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp @@ -1,3 +1,4 @@ +#include <cinttypes> #include "mitsubishi_cn105_climate.h" #include "esphome/core/log.h" @@ -14,9 +15,9 @@ void MitsubishiCN105Climate::dump_config() { LOG_STR_ARG(parity_to_str(this->parent_->get_parity())), this->parent_->get_stop_bits()); } -void MitsubishiCN105Climate::setup() {} +void MitsubishiCN105Climate::setup() { this->hp_.initialize(); } -void MitsubishiCN105Climate::loop() {} +void MitsubishiCN105Climate::loop() { this->hp_.update(); } climate::ClimateTraits MitsubishiCN105Climate::traits() { climate::ClimateTraits traits; diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp new file mode 100644 index 0000000000..55a0a2328f --- /dev/null +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp @@ -0,0 +1,7 @@ +#include "esphome/core/application.h" + +namespace esphome::mitsubishi_cn105 { + +uint32_t __attribute__((weak)) get_loop_time_ms() { return App.get_loop_component_start_time(); }; + +} // namespace esphome::mitsubishi_cn105 diff --git a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp new file mode 100644 index 0000000000..e01d9e69ff --- /dev/null +++ b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp @@ -0,0 +1,173 @@ +#include "../common.h" + +namespace esphome::mitsubishi_cn105::testing { + +struct TestContext { + MockUARTComponent uart; + uart::UARTDevice device{&uart}; + TestableMitsubishiCN105 sut{device}; + + TestContext() { this->sut.set_current_time(0); } +}; + +TEST(MitsubishiCN105Tests, InitSendsConnectPacket) { + auto ctx = TestContext{}; + + ctx.sut.set_current_time(123); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::NOT_CONNECTED); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_FALSE(ctx.sut.write_timeout_start_ms_.has_value()); + + ctx.sut.initialize(); + + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x5A, 0x01, 0x30, 0x02, 0xCA, 0x01, 0xA8)); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{123}); +} + +TEST(MitsubishiCN105Tests, SuccessfullyConnects) { + auto ctx = TestContext{}; + + ctx.sut.initialize(); + ctx.uart.tx.clear(); // Remove first connect packet bytes + + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.sut.write_timeout_start_ms_.has_value()); + + // Connect response + ctx.uart.push_rx({0xFC, 0x7A, 0x01, 0x30, 0x00, 0x55}); + + ctx.sut.update(); + + // All bytes from UART should be consumed and state = CONNECTED + EXPECT_TRUE(ctx.uart.rx.empty()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTED); + EXPECT_FALSE(ctx.sut.write_timeout_start_ms_.has_value()); + + // Nothing should be send to UART + EXPECT_TRUE(ctx.uart.tx.empty()); +} + +TEST(MitsubishiCN105Tests, NoResponseTriggersReconnect) { + auto ctx = TestContext{}; + + ctx.sut.initialize(); + ctx.uart.tx.clear(); // Remove first connect packet bytes + + // No response (no RX data), no retry yet + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{0}); + + // Still no response after 1999ms, no retry yet + ctx.sut.set_current_time(1999); + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{0}); + + // Stop waiting after 2s and retry connect + ctx.sut.set_current_time(2000); + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x5A, 0x01, 0x30, 0x02, 0xCA, 0x01, 0xA8)); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{2000}); +} + +TEST(MitsubishiCN105Tests, RxWatchdogLimitsProcessingPerUpdate) { + auto ctx = TestContext{}; + + ctx.sut.initialize(); + ctx.uart.tx.clear(); // Remove first connect packet bytes + + // RX noise/unexpected traffic + ctx.uart.push_rx({0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, + 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, + 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}); + + // Make sure we have enough bytes in buffer. + ASSERT_GT(ctx.uart.rx.size(), 64); + + // No valid response, no state change expected + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.uart.tx.empty()); + + // Watchdog interrupts reading (max. 64 bytes at once) so we do not spend the whole loop draining UART + EXPECT_FALSE(ctx.uart.rx.empty()); + + // Next update will read remaining bytes, no state change expected + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_TRUE(ctx.uart.rx.empty()); +} + +TEST(MitsubishiCN105Tests, ParserHandlesMixedRxStream) { + auto ctx = TestContext{}; + + ctx.sut.initialize(); + ctx.uart.tx.clear(); // Remove first connect packet bytes + + // Mixed RX stream with partial, malformed, and oversized frames to test parser robustness + ctx.uart.push_rx({// ───────────────────────────── + // Noise (no 0xFC) -> should be ignored via preamble reset + // ──────────────────────────── + 0x01, 0x02, 0x03, 0x04, 0x05, + + // ───────────────────────────── + // Partial frame (declares payload len=5, but we cut it short) + // Later bytes will eventually force checksum mismatch and reset + // ───────────────────────────── + 0xFC, 0x62, 0x01, 0x30, 0x05, 0xAA, 0xBB, + + // ───────────────────────────── + // Invalid header (header byte 3 should be 0x01, header byte 4 should be 0x30) + // Should reset quickly on header mismatch + // ───────────────────────────── + 0xFC, 0x62, 0xFF, 0xFF, 0x02, 0x01, 0x02, 0x00, + + // ───────────────────────────── + // Oversized length field (rejected by payload-too-large check at HEADER_LEN) + // ───────────────────────────── + 0xFC, 0x62, 0x01, 0x30, 0xFE, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, + 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + + // ───────────────────────────── + // Valid unknown-type frame (type=0x62), should be parsed successfully then ignored + // Frame: FC 62 01 30 02 AA BB 30 + // ───────────────────────────── + 0xFC, 0x62, 0x01, 0x30, 0x02, 0xAA, 0xBB, 0x30, + + // ───────────────────────────── + // Invalid checksum (should be rejected at checksum check) + // ───────────────────────────── + 0xFC, 0x62, 0x01, 0x30, 0x02, 0x10, 0x20, 0xFF, + + // ───────────────────────────── + // Back-to-back VALID frames (unknown type=0x62) to stress boundary handling. + // Frame A: FC 62 01 30 01 02 6C + // Frame B: FC 62 01 30 01 03 6B + // ───────────────────────────── + 0xFC, 0x62, 0x01, 0x30, 0x01, 0x02, 0x6C, 0xFC, 0x62, 0x01, 0x30, 0x01, 0x03, 0x6B, + + // ───────────────────────────── + // Trailing noise + // ───────────────────────────── + 0x55, 0x66, 0x77, 0x88}); + + // Drain RX - no valid response, no state change expected + int iterations = 0; + while (!ctx.uart.rx.empty() && iterations++ < 10) { + ctx.sut.update(); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); + EXPECT_TRUE(ctx.uart.tx.empty()); + } + + EXPECT_TRUE(ctx.uart.rx.empty()); +} + +} // namespace esphome::mitsubishi_cn105::testing diff --git a/tests/components/mitsubishi_cn105/common.cpp b/tests/components/mitsubishi_cn105/common.cpp new file mode 100644 index 0000000000..ea13d7676c --- /dev/null +++ b/tests/components/mitsubishi_cn105/common.cpp @@ -0,0 +1,7 @@ +#include "common.h" + +namespace esphome::mitsubishi_cn105 { + +uint32_t get_loop_time_ms() { return testing::TestableMitsubishiCN105::test_loop_time_ms; }; + +} // namespace esphome::mitsubishi_cn105 diff --git a/tests/components/mitsubishi_cn105/common.h b/tests/components/mitsubishi_cn105/common.h new file mode 100644 index 0000000000..c41268d723 --- /dev/null +++ b/tests/components/mitsubishi_cn105/common.h @@ -0,0 +1,53 @@ +#pragma once + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <algorithm> +#include <cstdint> +#include <initializer_list> +#include <vector> +#include "esphome/components/uart/uart_component.h" +#include "esphome/components/mitsubishi_cn105/mitsubishi_cn105.h" + +namespace esphome::mitsubishi_cn105::testing { + +class MockUARTComponent : public uart::UARTComponent { + public: + std::vector<uint8_t> tx; + std::vector<uint8_t> rx; + + void push_rx(std::initializer_list<uint8_t> data) { this->rx.insert(this->rx.end(), data.begin(), data.end()); } + + // UARTComponent + void write_array(const uint8_t *data, size_t len) override { this->tx.insert(this->tx.end(), data, data + len); } + + bool read_array(uint8_t *data, size_t len) override { + if (this->rx.size() < len) { + return false; + } + + std::copy(this->rx.begin(), this->rx.begin() + len, data); + this->rx.erase(this->rx.begin(), this->rx.begin() + len); + return true; + } + + size_t available() override { return this->rx.size(); } + + MOCK_METHOD(bool, peek_byte, (uint8_t * data), (override)); + MOCK_METHOD(uart::UARTFlushResult, flush, (), (override)); + MOCK_METHOD(void, check_logger_conflict, (), (override)); +}; + +class TestableMitsubishiCN105 : public MitsubishiCN105 { + public: + using MitsubishiCN105::MitsubishiCN105; + using MitsubishiCN105::State; + using MitsubishiCN105::state_; + using MitsubishiCN105::write_timeout_start_ms_; + + static inline uint32_t test_loop_time_ms = 0; + + void set_current_time(uint32_t ms) { test_loop_time_ms = ms; } +}; + +} // namespace esphome::mitsubishi_cn105::testing From 53b6528cc5dd88161c364b53518b557c38e2f31a Mon Sep 17 00:00:00 2001 From: alorente <gitmaster@passific.fr> Date: Sat, 4 Apr 2026 08:02:15 +0200 Subject: [PATCH 1928/2030] [epaper_spi] Allow runtime rotation change (#15419) Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com> --- esphome/components/display/__init__.py | 5 ++-- esphome/components/epaper_spi/display.py | 14 +---------- esphome/components/epaper_spi/epaper_spi.cpp | 23 ++++++++++++++++--- esphome/components/epaper_spi/epaper_spi.h | 17 ++++++++++---- .../mipi_dsi/test_mipi_dsi_config.py | 2 +- 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 4d79a0a31b..67d76a59d9 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -117,8 +117,9 @@ FULL_DISPLAY_SCHEMA.add_extra(_validate_test_card) async def setup_display_core_(var, config): - if CONF_ROTATION in config: - cg.add(var.set_rotation(DISPLAY_ROTATIONS[config[CONF_ROTATION]])) + if rotation := config.get(CONF_ROTATION, 0): + # Default initialised value for rotation is 0 + cg.add(var.set_rotation(DISPLAY_ROTATIONS[rotation])) if (auto_clear := config.get(CONF_AUTO_CLEAR_ENABLED)) is not None: # Default to true if pages or lambda is specified. Ideally this would be done during validation, but diff --git a/esphome/components/epaper_spi/display.py b/esphome/components/epaper_spi/display.py index 2657071f45..658f9e2c4a 100644 --- a/esphome/components/epaper_spi/display.py +++ b/esphome/components/epaper_spi/display.py @@ -175,9 +175,7 @@ async def to_code(config): *model.get_constructor_args(config), ) - # Rotation is handled by setting the transform - display_config = {k: v for k, v in config.items() if k != CONF_ROTATION} - await display.register_display(var, display_config) + await display.register_display(var, config) await spi.register_spi_device(var, config, write_only=True) dc = await cg.gpio_pin_expression(config[CONF_DC_PIN]) @@ -201,16 +199,6 @@ async def to_code(config): transform[CONF_SWAP_XY] = False else: transform = {x: model.get_default(x, False) for x in TRANSFORM_OPTIONS} - rotation = config[CONF_ROTATION] - if rotation == 180: - transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X] - transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y] - elif rotation == 90: - transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY] - transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X] - elif rotation == 270: - transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY] - transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y] transform_str = "|".join( { str(getattr(Transform, x.upper())) diff --git a/esphome/components/epaper_spi/epaper_spi.cpp b/esphome/components/epaper_spi/epaper_spi.cpp index ae1923a916..a2ca311b30 100644 --- a/esphome/components/epaper_spi/epaper_spi.cpp +++ b/esphome/components/epaper_spi/epaper_spi.cpp @@ -97,6 +97,23 @@ bool EPaperBase::reset() { return true; } +void EPaperBase::update_effective_transform_() { + switch (this->rotation_) { + case DISPLAY_ROTATION_90_DEGREES: + this->effective_transform_ = this->transform_ ^ (SWAP_XY | MIRROR_X); + break; + case DISPLAY_ROTATION_180_DEGREES: + this->effective_transform_ = this->transform_ ^ (MIRROR_Y | MIRROR_X); + break; + case DISPLAY_ROTATION_270_DEGREES: + this->effective_transform_ = this->transform_ ^ (SWAP_XY | MIRROR_Y); + break; + default: + this->effective_transform_ = this->transform_; + break; + } +} + void EPaperBase::update() { if (this->state_ != EPaperState::IDLE) { ESP_LOGE(TAG, "Display already in state %s", epaper_state_to_string_()); @@ -280,11 +297,11 @@ bool EPaperBase::initialise(bool partial) { bool EPaperBase::rotate_coordinates_(int &x, int &y) { if (!this->get_clipping().inside(x, y)) return false; - if (this->transform_ & SWAP_XY) + if (this->effective_transform_ & SWAP_XY) std::swap(x, y); - if (this->transform_ & MIRROR_X) + if (this->effective_transform_ & MIRROR_X) x = this->width_ - x - 1; - if (this->transform_ & MIRROR_Y) + if (this->effective_transform_ & MIRROR_Y) y = this->height_ - y - 1; if (x >= this->width_ || y >= this->height_ || x < 0 || y < 0) return false; diff --git a/esphome/components/epaper_spi/epaper_spi.h b/esphome/components/epaper_spi/epaper_spi.h index a743985518..47b4f9f72d 100644 --- a/esphome/components/epaper_spi/epaper_spi.h +++ b/esphome/components/epaper_spi/epaper_spi.h @@ -1,6 +1,6 @@ #pragma once -#include "esphome/components/display/display_buffer.h" +#include "esphome/components/display/display.h" #include "esphome/components/spi/spi.h" #include "esphome/components/split_buffer/split_buffer.h" #include "esphome/core/component.h" @@ -51,7 +51,14 @@ class EPaperBase : public Display, void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; } void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; } void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; } - void set_transform(uint8_t transform) { this->transform_ = transform; } + void set_transform(uint8_t transform) { + this->transform_ = transform; + this->update_effective_transform_(); + } + void set_rotation(DisplayRotation rotation) override { + Display::set_rotation(rotation); + this->update_effective_transform_(); + } void set_full_update_every(uint8_t full_update_every) { this->full_update_every_ = full_update_every; } void dump_config() override; @@ -106,8 +113,8 @@ class EPaperBase : public Display, protected: int get_height_internal() override { return this->height_; }; int get_width_internal() override { return this->width_; }; - int get_width() override { return this->transform_ & SWAP_XY ? this->height_ : this->width_; } - int get_height() override { return this->transform_ & SWAP_XY ? this->width_ : this->height_; } + int get_width() override { return this->effective_transform_ & SWAP_XY ? this->height_ : this->width_; } + int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; } void draw_pixel_at(int x, int y, Color color) override; void process_state_(); @@ -119,6 +126,7 @@ class EPaperBase : public Display, void send_init_sequence_(const uint8_t *sequence, size_t length); void wait_for_idle_(bool should_wait); bool init_buffer_(size_t buffer_length); + void update_effective_transform_(); bool rotate_coordinates_(int &x, int &y); /** @@ -171,6 +179,7 @@ class EPaperBase : public Display, uint32_t delay_until_{}; // timestamp until which to delay processing uint16_t next_delay_{}; // milliseconds to delay before next state uint8_t transform_{}; + uint8_t effective_transform_{}; uint8_t update_count_{}; // these values represent the bounds of the updated buffer. Note that x_high and y_high // point to the pixel past the last one updated, i.e. may range up to width/height. diff --git a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py index 1ae8cc644e..119bbf7fea 100644 --- a/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py +++ b/tests/component_tests/mipi_dsi/test_mipi_dsi_config.py @@ -133,6 +133,6 @@ def test_code_generation( assert "set_init_sequence({224, 1, 0, 225, 1, 147, 226, 1," in main_cpp assert "p4_nano->set_lane_bit_rate(1500.0f);" in main_cpp assert "p4_nano->set_rotation(display::DISPLAY_ROTATION_90_DEGREES);" in main_cpp - assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" in main_cpp + assert "p4_86->set_rotation(display::DISPLAY_ROTATION_0_DEGREES);" not in main_cpp assert "custom_id->set_rotation(display::DISPLAY_ROTATION_180_DEGREES);" in main_cpp # assert "backlight_id = new light::LightState(mipi_dsi_dsibacklight_id);" in main_cpp From 89de00e7ce485c982a454e9fc26ece9a144d9a6a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:04:01 +1000 Subject: [PATCH 1929/2030] [online_image] Clear LVGL dsc when image size changes. (#15360) --- esphome/components/runtime_image/runtime_image.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 2ebe67c3a5..fa42b53496 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -248,6 +248,9 @@ void RuntimeImage::release_buffer_() { this->height_ = 0; this->buffer_width_ = 0; this->buffer_height_ = 0; +#ifdef USE_LVGL + memset(&this->dsc_, 0, sizeof(this->dsc_)); +#endif } } From b0d39aedd33be6f8380d90728d220e0e4fdf0bad Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 00:30:29 -1000 Subject: [PATCH 1930/2030] [hlw8012] Change periodic sensor reading logs to LOGV (#15431) --- esphome/components/hlw8012/hlw8012.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/hlw8012/hlw8012.cpp b/esphome/components/hlw8012/hlw8012.cpp index d0fd697d8f..22f292e47e 100644 --- a/esphome/components/hlw8012/hlw8012.cpp +++ b/esphome/components/hlw8012/hlw8012.cpp @@ -73,13 +73,13 @@ void HLW8012Component::update() { // Only read cf1 after one cycle. Apparently it's quite unstable after being changed. if (this->current_mode_) { float current = cf1_hz * this->current_multiplier_; - ESP_LOGD(TAG, "Got power=%.1fW, current=%.1fA", power, current); + ESP_LOGV(TAG, "Got power=%.1fW, current=%.1fA", power, current); if (this->current_sensor_ != nullptr) { this->current_sensor_->publish_state(current); } } else { float voltage = cf1_hz * this->voltage_multiplier_; - ESP_LOGD(TAG, "Got power=%.1fW, voltage=%.1fV", power, voltage); + ESP_LOGV(TAG, "Got power=%.1fW, voltage=%.1fV", power, voltage); if (this->voltage_sensor_ != nullptr) { this->voltage_sensor_->publish_state(voltage); } From 9ee5089891f54ef3e986db448b52b1dfaf9bafbe Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 00:30:41 -1000 Subject: [PATCH 1931/2030] [time] Support */N syntax in cron expressions (#15434) --- esphome/components/time/__init__.py | 4 +- tests/unit_tests/components/test_time.py | 80 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 tests/unit_tests/components/test_time.py diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index c31ccbc7ea..7ac0abeee0 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -123,8 +123,8 @@ def _parse_cron_part(part, min_value, max_value, special_mapping): f"Can't have more than two '/' in one time expression, got {part}" ) offset, repeat = data - offset_n = 0 - if offset: + offset_n = min_value + if offset and offset not in ("*", "?"): offset_n = _parse_cron_int( offset, special_mapping, diff --git a/tests/unit_tests/components/test_time.py b/tests/unit_tests/components/test_time.py new file mode 100644 index 0000000000..48988fb03f --- /dev/null +++ b/tests/unit_tests/components/test_time.py @@ -0,0 +1,80 @@ +"""Tests for time component cron expression parsing.""" + +from esphome.components.time import _parse_cron_part + + +def test_star_slash_seconds() -> None: + assert _parse_cron_part("*/10", 0, 60, {}) == {0, 10, 20, 30, 40, 50, 60} + + +def test_star_slash_minutes() -> None: + assert _parse_cron_part("*/5", 0, 59, {}) == { + 0, + 5, + 10, + 15, + 20, + 25, + 30, + 35, + 40, + 45, + 50, + 55, + } + + +def test_star_slash_hours() -> None: + assert _parse_cron_part("*/2", 0, 23, {}) == { + 0, + 2, + 4, + 6, + 8, + 10, + 12, + 14, + 16, + 18, + 20, + 22, + } + + +def test_star_slash_days_of_month() -> None: + """days_of_month starts at 1, not 0.""" + assert _parse_cron_part("*/5", 1, 31, {}) == {1, 6, 11, 16, 21, 26, 31} + + +def test_question_slash() -> None: + assert _parse_cron_part("?/10", 0, 60, {}) == {0, 10, 20, 30, 40, 50, 60} + + +def test_empty_offset_slash() -> None: + """Empty offset defaults to min_value.""" + assert _parse_cron_part("/10", 0, 60, {}) == {0, 10, 20, 30, 40, 50, 60} + + +def test_empty_offset_slash_nonzero_min() -> None: + """Empty offset defaults to min_value, not 0.""" + assert _parse_cron_part("/5", 1, 31, {}) == {1, 6, 11, 16, 21, 26, 31} + + +def test_numeric_offset_slash() -> None: + assert _parse_cron_part("5/10", 0, 60, {}) == {5, 15, 25, 35, 45, 55} + + +def test_star() -> None: + assert _parse_cron_part("*", 0, 59, {}) == set(range(0, 60)) + + +def test_question() -> None: + assert _parse_cron_part("?", 0, 59, {}) == set(range(0, 60)) + + +def test_range() -> None: + assert _parse_cron_part("1-5", 0, 59, {}) == {1, 2, 3, 4, 5} + + +def test_single_value() -> None: + assert _parse_cron_part("30", 0, 59, {}) == {30} From f51871fa6b577216d80d9a2699c757a0d109becd Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 00:37:50 -1000 Subject: [PATCH 1932/2030] [total_daily_energy] Replace loop() with timeout-based midnight reset (#15432) --- .../total_daily_energy/total_daily_energy.cpp | 67 ++++++++++++++----- .../total_daily_energy/total_daily_energy.h | 8 +-- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/esphome/components/total_daily_energy/total_daily_energy.cpp b/esphome/components/total_daily_energy/total_daily_energy.cpp index e7a45a5edf..161c712cc1 100644 --- a/esphome/components/total_daily_energy/total_daily_energy.cpp +++ b/esphome/components/total_daily_energy/total_daily_energy.cpp @@ -1,10 +1,21 @@ #include "total_daily_energy.h" +#include "esphome/core/application.h" #include "esphome/core/log.h" -namespace esphome { -namespace total_daily_energy { +namespace esphome::total_daily_energy { static const char *const TAG = "total_daily_energy"; +static constexpr uint32_t TIMEOUT_ID_MIDNIGHT = 1; +static constexpr uint8_t SECONDS_PER_MINUTE = 60; +static constexpr uint8_t MINUTES_PER_HOUR = 60; +static constexpr uint8_t HOURS_PER_DAY = 24; +static constexpr uint32_t SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR; +static constexpr uint16_t MILLIS_PER_SECOND = 1000; +// Wake up 90 minutes before midnight to recalculate, ensuring DST transitions +// (which shift wall clock by 1 hour but don't change millis()) don't cause +// the midnight reset to fire late. DST transitions don't trigger the time sync +// callback since they change local time interpretation, not the epoch. +static constexpr uint32_t PRE_MIDNIGHT_SECONDS = 90 * SECONDS_PER_MINUTE; void TotalDailyEnergy::setup() { float initial_value = 0; @@ -15,28 +26,55 @@ void TotalDailyEnergy::setup() { } this->publish_state_and_save(initial_value); - this->last_update_ = millis(); + this->last_update_ = App.get_loop_component_start_time(); this->parent_->add_on_state_callback([this](float state) { this->process_new_state_(state); }); + + // Schedule initial midnight reset if time is already valid, otherwise + // the time sync callback will handle it once time becomes available. + this->schedule_midnight_reset_(); + // Re-schedule on every NTP sync in case the clock jumped across midnight. + this->time_->add_on_time_sync_callback([this]() { this->schedule_midnight_reset_(); }); } void TotalDailyEnergy::dump_config() { LOG_SENSOR("", "Total Daily Energy", this); } -void TotalDailyEnergy::loop() { +void TotalDailyEnergy::schedule_midnight_reset_() { auto t = this->time_->now(); if (!t.is_valid()) return; - if (this->last_day_of_year_ == 0) { + // Check if the day changed (time sync moved us past midnight, or first call) + if (this->last_day_of_year_ != t.day_of_year) { + if (this->last_day_of_year_ != 0) { + // Day actually changed — reset energy + this->total_energy_ = 0; + this->publish_state_and_save(0); + } this->last_day_of_year_ = t.day_of_year; - return; } - if (t.day_of_year != this->last_day_of_year_) { - this->last_day_of_year_ = t.day_of_year; - this->total_energy_ = 0; - this->publish_state_and_save(0); + // Calculate seconds until next midnight. + // Uses the same TIMEOUT_ID_MIDNIGHT ID so re-scheduling (e.g. from time sync) cancels + // any previously pending timeout. + uint32_t seconds_until_midnight = + ((HOURS_PER_DAY - 1 - t.hour) * MINUTES_PER_HOUR + (MINUTES_PER_HOUR - 1 - t.minute)) * SECONDS_PER_MINUTE + + (SECONDS_PER_MINUTE - t.second); + + // set_timeout counts real elapsed millis, but DST shifts wall clock by up to 1 hour + // without changing millis. To avoid firing up to 1 hour late/early, we use two stages: + // 1) Wake up 90 minutes before midnight to recalculate with current wall clock + // 2) From there, schedule the precise midnight reset + uint32_t timeout_seconds; + if (seconds_until_midnight > PRE_MIDNIGHT_SECONDS) { + timeout_seconds = seconds_until_midnight - PRE_MIDNIGHT_SECONDS; + } else { + timeout_seconds = seconds_until_midnight + 1; } + + ESP_LOGD(TAG, "Scheduling midnight check in %us", timeout_seconds); + this->set_timeout(TIMEOUT_ID_MIDNIGHT, timeout_seconds * MILLIS_PER_SECOND, + [this]() { this->schedule_midnight_reset_(); }); } void TotalDailyEnergy::publish_state_and_save(float state) { @@ -50,14 +88,14 @@ void TotalDailyEnergy::publish_state_and_save(float state) { void TotalDailyEnergy::process_new_state_(float state) { if (std::isnan(state)) return; - const uint32_t now = millis(); + const uint32_t now = App.get_loop_component_start_time(); const float old_state = this->last_power_state_; const float new_state = state; - float delta_hours = (now - this->last_update_) / 1000.0f / 60.0f / 60.0f; + float delta_hours = (now - this->last_update_) / static_cast<float>(MILLIS_PER_SECOND) / SECONDS_PER_HOUR; float delta_energy = 0.0f; switch (this->method_) { case TOTAL_DAILY_ENERGY_METHOD_TRAPEZOID: - delta_energy = delta_hours * (old_state + new_state) / 2.0; + delta_energy = delta_hours * (old_state + new_state) / 2.0f; break; case TOTAL_DAILY_ENERGY_METHOD_LEFT: delta_energy = delta_hours * old_state; @@ -71,5 +109,4 @@ void TotalDailyEnergy::process_new_state_(float state) { this->publish_state_and_save(this->total_energy_ + delta_energy); } -} // namespace total_daily_energy -} // namespace esphome +} // namespace esphome::total_daily_energy diff --git a/esphome/components/total_daily_energy/total_daily_energy.h b/esphome/components/total_daily_energy/total_daily_energy.h index 1145f54f95..9a20ecea01 100644 --- a/esphome/components/total_daily_energy/total_daily_energy.h +++ b/esphome/components/total_daily_energy/total_daily_energy.h @@ -6,8 +6,7 @@ #include "esphome/components/sensor/sensor.h" #include "esphome/components/time/real_time_clock.h" -namespace esphome { -namespace total_daily_energy { +namespace esphome::total_daily_energy { enum TotalDailyEnergyMethod { TOTAL_DAILY_ENERGY_METHOD_TRAPEZOID = 0, @@ -23,12 +22,12 @@ class TotalDailyEnergy : public sensor::Sensor, public Component { void set_method(TotalDailyEnergyMethod method) { method_ = method; } void setup() override; void dump_config() override; - void loop() override; void publish_state_and_save(float state); protected: void process_new_state_(float state); + void schedule_midnight_reset_(); ESPPreferenceObject pref_; time::RealTimeClock *time_; @@ -41,5 +40,4 @@ class TotalDailyEnergy : public sensor::Sensor, public Component { float last_power_state_{0.0f}; }; -} // namespace total_daily_energy -} // namespace esphome +} // namespace esphome::total_daily_energy From 297f9c134f3b1000d8dddefcac5acf5240c50d45 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 01:07:16 -1000 Subject: [PATCH 1933/2030] [time] Use set_interval for CronTrigger instead of loop() (#15433) --- esphome/components/time/automation.cpp | 7 ++++++- esphome/components/time/automation.h | 3 ++- tests/components/time/common.yaml | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/esphome/components/time/automation.cpp b/esphome/components/time/automation.cpp index 8bc87878d1..7eb99cfe74 100644 --- a/esphome/components/time/automation.cpp +++ b/esphome/components/time/automation.cpp @@ -20,7 +20,12 @@ bool CronTrigger::matches(const ESPTime &time) { return time.is_valid() && this->seconds_[time.second] && this->minutes_[time.minute] && this->hours_[time.hour] && this->days_of_month_[time.day_of_month] && this->months_[time.month] && this->days_of_week_[time.day_of_week]; } -void CronTrigger::loop() { +void CronTrigger::setup() { + // Cron resolution is 1 second — check once per second instead of every loop iteration + this->set_interval(1000, [this]() { this->check_time_(); }); +} + +void CronTrigger::check_time_() { ESPTime time = this->rtc_->now(); if (!time.is_valid()) return; diff --git a/esphome/components/time/automation.h b/esphome/components/time/automation.h index 4ccfc641d6..546c4a10de 100644 --- a/esphome/components/time/automation.h +++ b/esphome/components/time/automation.h @@ -26,10 +26,11 @@ class CronTrigger : public Trigger<>, public Component { void add_day_of_week(uint8_t day_of_week); void add_days_of_week(const std::vector<uint8_t> &days_of_week); bool matches(const ESPTime &time); - void loop() override; + void setup() override; float get_setup_priority() const override; protected: + void check_time_(); std::bitset<61> seconds_; std::bitset<60> minutes_; std::bitset<24> hours_; diff --git a/tests/components/time/common.yaml b/tests/components/time/common.yaml index 465be045db..cd258c7aa6 100644 --- a/tests/components/time/common.yaml +++ b/tests/components/time/common.yaml @@ -6,5 +6,9 @@ api: time: - platform: homeassistant + on_time: + - seconds: "0,10,20,30,40,50" + then: + - logger.log: "CronTrigger fired (every 10 seconds)" - platform: sntp id: sntp_time From 1a1725f958a285f7018c48d89c8f509c58ddad0b Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 4 Apr 2026 23:11:29 +1000 Subject: [PATCH 1934/2030] [esp32] Clean build when sdkconfig options change (#15439) --- esphome/components/esp32/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0ce1117262..5cae67db13 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -48,7 +48,7 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache +from esphome.writer import clean_build, clean_cmake_cache from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa @@ -2195,6 +2195,7 @@ def _write_sdkconfig(): if write_file_if_changed(internal_path, contents): # internal changed, update real one write_file_if_changed(sdk_path, contents) + clean_build(clear_pio_cache=False) def _write_idf_component_yml(): From 830517a98f4db08749bcb5e36182d3d6ebb958ab Mon Sep 17 00:00:00 2001 From: Boris Krivonog <boris.krivonog@inova.si> Date: Sun, 5 Apr 2026 00:40:05 +0200 Subject: [PATCH 1935/2030] [mitsubishi_cn105] Add climate component for Mitsubishi A/C units with CN105 connector (Part 3) (#15437) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick+github@koston.org> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- .../mitsubishi_cn105/mitsubishi_cn105.cpp | 160 ++++++++++++++++-- .../mitsubishi_cn105/mitsubishi_cn105.h | 37 +++- .../mitsubishi_cn105_climate.cpp | 23 ++- .../mitsubishi_cn105_climate.h | 2 + .../mitsubishi_cn105_time.cpp | 2 +- .../climate/mitsubishi_cn105_tests.cpp | 156 +++++++++++++++-- tests/components/mitsubishi_cn105/common.cpp | 2 +- tests/components/mitsubishi_cn105/common.h | 3 + 8 files changed, 353 insertions(+), 32 deletions(-) diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp index e3923bb0b8..0bce8da1ad 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp @@ -8,6 +8,7 @@ static const char *const TAG = "mitsubishi_cn105.driver"; static constexpr uint32_t WRITE_TIMEOUT_MS = 2000; +static constexpr size_t REQUEST_PAYLOAD_LEN = 0x10; static constexpr size_t HEADER_LEN = 5; static constexpr uint8_t PREAMBLE = 0xFC; static constexpr uint8_t HEADER_BYTE_1 = 0x01; @@ -15,7 +16,13 @@ static constexpr uint8_t HEADER_BYTE_2 = 0x30; static constexpr uint8_t PACKET_TYPE_CONNECT_REQUEST = 0x5A; static constexpr uint8_t PACKET_TYPE_CONNECT_RESPONSE = 0x7A; -static constexpr std::array<uint8_t, 2> CONNECT_REQUEST_PAYLOAD = {{0xCA, 0x01}}; +static constexpr std::array<uint8_t, 2> CONNECT_REQUEST_PAYLOAD = {0xCA, 0x01}; + +static constexpr uint8_t PACKET_TYPE_STATUS_REQUEST = 0x42; +static constexpr uint8_t PACKET_TYPE_STATUS_RESPONSE = 0x62; +static constexpr uint8_t STATUS_MSG_SETTINGS = 0x02; +static constexpr uint8_t STATUS_MSG_ROOM_TEMP = 0x03; +static constexpr std::array<uint8_t, 2> STATUS_MSG_TYPES = {STATUS_MSG_SETTINGS, STATUS_MSG_ROOM_TEMP}; static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) { return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0})); @@ -30,19 +37,29 @@ static constexpr auto make_packet(uint8_t type, const std::array<uint8_t, Payloa return packet; } +static float decode_temperature(int temp_a, int temp_b, int delta) { + return temp_b != 0 ? (temp_b - 128) / 2.0f : delta + temp_a; +} + static constexpr auto CONNECT_PACKET = make_packet(PACKET_TYPE_CONNECT_REQUEST, CONNECT_REQUEST_PAYLOAD); void MitsubishiCN105::initialize() { this->set_state_(State::CONNECTING); } -void MitsubishiCN105::update() { +bool MitsubishiCN105::update() { + if (const auto start = this->status_update_start_ms_; + start && (get_loop_time_ms() - *start) >= this->update_interval_ms_) { + this->cancel_waiting_and_transition_to_(State::UPDATING_STATUS); + return false; + } + if (const auto start = this->write_timeout_start_ms_; start && (get_loop_time_ms() - *start) >= WRITE_TIMEOUT_MS) { this->write_timeout_start_ms_.reset(); this->read_pos_ = 0; this->set_state_(State::READ_TIMEOUT); - return; + return false; } - this->read_incoming_bytes_(); + return this->read_incoming_bytes_(); } void MitsubishiCN105::set_state_(State new_state) { @@ -63,9 +80,24 @@ bool MitsubishiCN105::should_transition(State from, State to) { return from == State::NOT_CONNECTED || from == State::READ_TIMEOUT; case State::CONNECTED: - case State::READ_TIMEOUT: return from == State::CONNECTING; + case State::UPDATING_STATUS: + return from == State::CONNECTED || from == State::STATUS_UPDATED || + from == State::WAITING_FOR_SCHEDULED_STATUS_UPDATE; + + case State::STATUS_UPDATED: + return from == State::UPDATING_STATUS; + + case State::SCHEDULE_NEXT_STATUS_UPDATE: + return from == State::STATUS_UPDATED; + + case State::WAITING_FOR_SCHEDULED_STATUS_UPDATE: + return from == State::SCHEDULE_NEXT_STATUS_UPDATE; + + case State::READ_TIMEOUT: + return from == State::UPDATING_STATUS || from == State::CONNECTING; + default: return false; } @@ -79,7 +111,30 @@ void MitsubishiCN105::did_transition_(State to) { case State::CONNECTED: this->write_timeout_start_ms_.reset(); - // TODO: read AC status after connected, next PR + this->status_msg_index_ = 0; + this->set_state_(State::UPDATING_STATUS); + break; + + case State::UPDATING_STATUS: + this->update_status_(); + break; + + case State::STATUS_UPDATED: { + this->write_timeout_start_ms_.reset(); + if (++this->status_msg_index_ >= STATUS_MSG_TYPES.size()) { + this->status_msg_index_ = 0; + } + if (this->status_msg_index_ != 0) { + this->set_state_(State::UPDATING_STATUS); + } else { + this->set_state_(State::SCHEDULE_NEXT_STATUS_UPDATE); + } + break; + } + + case State::SCHEDULE_NEXT_STATUS_UPDATE: + this->status_update_start_ms_ = get_loop_time_ms(); + this->set_state_(State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); break; case State::READ_TIMEOUT: @@ -97,13 +152,24 @@ void MitsubishiCN105::send_packet_(const uint8_t *packet, size_t len) { this->write_timeout_start_ms_ = get_loop_time_ms(); } -void MitsubishiCN105::read_incoming_bytes_() { +void MitsubishiCN105::update_status_() { + ESP_LOGV(TAG, "Requesting status update, index=%u", this->status_msg_index_); + std::array<uint8_t, REQUEST_PAYLOAD_LEN> payload = {STATUS_MSG_TYPES[this->status_msg_index_]}; + this->send_packet_(make_packet(PACKET_TYPE_STATUS_REQUEST, payload)); +} + +void MitsubishiCN105::cancel_waiting_and_transition_to_(State state) { + this->status_update_start_ms_.reset(); + this->set_state_(state); +} + +bool MitsubishiCN105::read_incoming_bytes_() { uint8_t watchdog = 64; while (this->device_.available() > 0 && watchdog-- > 0) { uint8_t &value = this->read_buffer_[this->read_pos_]; if (!this->device_.read_byte(&value)) { ESP_LOGW(TAG, "UART read failed while data available"); - return; + return false; } switch (++this->read_pos_) { @@ -149,23 +215,85 @@ void MitsubishiCN105::read_incoming_bytes_() { continue; } - this->process_rx_packet_(this->read_buffer_[1], this->read_buffer_ + HEADER_LEN, len_without_checksum - HEADER_LEN); + bool processed = this->process_rx_packet_(this->read_buffer_[1], this->read_buffer_ + HEADER_LEN, + len_without_checksum - HEADER_LEN); this->reset_read_position_and_dump_buffer_("RX"); + return processed; } + + return false; } -void MitsubishiCN105::process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len) { +bool MitsubishiCN105::process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len) { switch (type) { case PACKET_TYPE_CONNECT_RESPONSE: this->set_state_(State::CONNECTED); - break; + return false; + + case PACKET_TYPE_STATUS_RESPONSE: + return this->process_status_packet_(payload, len); default: ESP_LOGVV(TAG, "RX unknown packet type 0x%02X", type); - break; + return false; } } +bool MitsubishiCN105::process_status_packet_(const uint8_t *payload, size_t len) { + if (len == 0) { + ESP_LOGVV(TAG, "RX status packet too short"); + return false; + } + + const auto previous = this->status_; + const auto msg_type = payload[0]; + if (!this->parse_status_payload_(msg_type, payload + 1, len - 1)) { + return false; + } + + if (msg_type == STATUS_MSG_TYPES[this->status_msg_index_]) { + this->set_state_(State::STATUS_UPDATED); + } + + return previous != this->status_ && this->is_status_initialized(); +} + +bool MitsubishiCN105::parse_status_payload_(uint8_t msg_type, const uint8_t *payload, size_t len) { + switch (msg_type) { + case STATUS_MSG_SETTINGS: + return this->parse_status_settings_(payload, len); + + case STATUS_MSG_ROOM_TEMP: + return this->parse_status_room_temperature_(payload, len); + + default: + ESP_LOGVV(TAG, "RX unsupported status msg type 0x%02X", msg_type); + return false; + } +} + +bool MitsubishiCN105::parse_status_settings_(const uint8_t *payload, size_t len) { + if (len <= 10) { + ESP_LOGVV(TAG, "RX settings payload too short"); + return false; + } + + this->status_.power_on = payload[2] != 0; + this->status_.target_temperature = decode_temperature(-payload[4], payload[10], 31); + + return true; +} + +bool MitsubishiCN105::parse_status_room_temperature_(const uint8_t *payload, size_t len) { + if (len <= 5) { + ESP_LOGVV(TAG, "RX room temperature payload too short"); + return false; + } + + this->status_.room_temperature = decode_temperature(payload[2], payload[5], 10); + return true; +} + void MitsubishiCN105::reset_read_position_and_dump_buffer_(const char *prefix) { dump_buffer_vv(prefix, this->read_buffer_, this->read_pos_); this->read_pos_ = 0; @@ -186,6 +314,14 @@ const LogString *MitsubishiCN105::state_to_string(State state) { return LOG_STR("Connecting"); case State::CONNECTED: return LOG_STR("Connected"); + case State::UPDATING_STATUS: + return LOG_STR("UpdatingStatus"); + case State::STATUS_UPDATED: + return LOG_STR("StatusUpdated"); + case State::SCHEDULE_NEXT_STATUS_UPDATE: + return LOG_STR("ScheduleNextStatusUpdate"); + case State::WAITING_FOR_SCHEDULED_STATUS_UPDATE: + return LOG_STR("WaitingForScheduledStatusUpdate"); case State::READ_TIMEOUT: return LOG_STR("ReadTimeout"); } diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h index fc09b3bed2..d43904b313 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h @@ -9,23 +9,49 @@ uint32_t get_loop_time_ms(); class MitsubishiCN105 { public: + struct Status { + bool operator==(const Status &) const = default; + + bool power_on{false}; + float target_temperature{NAN}; + float room_temperature{NAN}; + }; + explicit MitsubishiCN105(uart::UARTDevice &device) : device_(device) {} void initialize(); - void update(); + bool update(); uint32_t get_update_interval() const { return this->update_interval_ms_; } void set_update_interval(uint32_t interval_ms) { this->update_interval_ms_ = interval_ms; } + const Status &status() const { return this->status_; } + bool is_status_initialized() const { return !std::isnan(status_.room_temperature); } + protected: - enum class State : uint8_t { NOT_CONNECTED, CONNECTING, CONNECTED, READ_TIMEOUT }; + enum class State : uint8_t { + NOT_CONNECTED, + CONNECTING, + CONNECTED, + UPDATING_STATUS, + STATUS_UPDATED, + SCHEDULE_NEXT_STATUS_UPDATE, + WAITING_FOR_SCHEDULED_STATUS_UPDATE, + READ_TIMEOUT + }; void set_state_(State new_state); void did_transition_(State to); - void read_incoming_bytes_(); - void process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len); + bool read_incoming_bytes_(); + bool process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len); + bool process_status_packet_(const uint8_t *payload, size_t len); + bool parse_status_payload_(uint8_t msg_type, const uint8_t *payload, size_t len); + bool parse_status_settings_(const uint8_t *payload, size_t len); + bool parse_status_room_temperature_(const uint8_t *payload, size_t len); void reset_read_position_and_dump_buffer_(const char *prefix); void send_packet_(const uint8_t *packet, size_t len); + void update_status_(); + void cancel_waiting_and_transition_to_(State state); template<typename T> void send_packet_(const T &packet) { this->send_packet_(packet.data(), packet.size()); } static bool should_transition(State from, State to); static const LogString *state_to_string(State state); @@ -34,7 +60,10 @@ class MitsubishiCN105 { uart::UARTDevice &device_; uint32_t update_interval_ms_{1000}; std::optional<uint32_t> write_timeout_start_ms_; + std::optional<uint32_t> status_update_start_ms_; + Status status_{}; State state_{State::NOT_CONNECTED}; + uint8_t status_msg_index_{0}; private: static constexpr size_t READ_BUFFER_SIZE = 32; diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp index cce6bef5e4..55fc23c449 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp @@ -17,13 +17,34 @@ void MitsubishiCN105Climate::dump_config() { void MitsubishiCN105Climate::setup() { this->hp_.initialize(); } -void MitsubishiCN105Climate::loop() { this->hp_.update(); } +void MitsubishiCN105Climate::loop() { + if (this->hp_.update()) { + this->apply_values_(); + } +} climate::ClimateTraits MitsubishiCN105Climate::traits() { climate::ClimateTraits traits; + + traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE); + + traits.set_visual_min_temperature(16.0f); + traits.set_visual_max_temperature(31.0f); + traits.set_visual_temperature_step(1.0f); + traits.set_visual_current_temperature_step(0.5f); + return traits; } void MitsubishiCN105Climate::control(const climate::ClimateCall &call) {} +void MitsubishiCN105Climate::apply_values_() { + const auto &status = this->hp_.status(); + + this->target_temperature = status.target_temperature; + this->current_temperature = status.room_temperature; + + this->publish_state(); +} + } // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h index 08b482025f..da8f8d8d0a 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h @@ -21,6 +21,8 @@ class MitsubishiCN105Climate : public climate::Climate, public Component, public void set_update_interval(uint32_t ms) { hp_.set_update_interval(ms); } protected: + void apply_values_(); + MitsubishiCN105 hp_; }; diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp index 55a0a2328f..0f3fcb5648 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_time.cpp @@ -2,6 +2,6 @@ namespace esphome::mitsubishi_cn105 { -uint32_t __attribute__((weak)) get_loop_time_ms() { return App.get_loop_component_start_time(); }; +uint32_t __attribute__((weak)) get_loop_time_ms() { return App.get_loop_component_start_time(); } } // namespace esphome::mitsubishi_cn105 diff --git a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp index e01d9e69ff..5b4f84623e 100644 --- a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp +++ b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp @@ -25,27 +25,80 @@ TEST(MitsubishiCN105Tests, InitSendsConnectPacket) { EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{123}); } -TEST(MitsubishiCN105Tests, SuccessfullyConnects) { +TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) { auto ctx = TestContext{}; ctx.sut.initialize(); ctx.uart.tx.clear(); // Remove first connect packet bytes EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); - EXPECT_TRUE(ctx.sut.write_timeout_start_ms_.has_value()); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{0}); + EXPECT_FALSE(ctx.sut.status_update_start_ms_.has_value()); // Connect response ctx.uart.push_rx({0xFC, 0x7A, 0x01, 0x30, 0x00, 0x55}); - ctx.sut.update(); + ctx.sut.set_current_time(200); + ASSERT_FALSE(ctx.sut.update()); - // All bytes from UART should be consumed and state = CONNECTED + // All bytes from UART should be consumed EXPECT_TRUE(ctx.uart.rx.empty()); - EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTED); - EXPECT_FALSE(ctx.sut.write_timeout_start_ms_.has_value()); + // After successful connect we request status, first settings (0x02) + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS); + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x42, 0x01, 0x30, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B)); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{200}); + EXPECT_FALSE(ctx.sut.status_update_start_ms_.has_value()); + + // Clear TX bytes. + ctx.uart.tx.clear(); + + // Settings response + ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x10, 0x02, 0x00, 0x00, 0x00, 0x08, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x99}); + + // Settings should still have initial values + EXPECT_FALSE(ctx.sut.status().power_on); + EXPECT_THAT(ctx.sut.status().target_temperature, ::testing::IsNan()); + + ctx.sut.set_current_time(300); + ASSERT_FALSE(ctx.sut.update()); + EXPECT_TRUE(ctx.uart.rx.empty()); + + // Check settings that we just read from received package + EXPECT_FALSE(ctx.sut.status().power_on); + EXPECT_EQ(ctx.sut.status().target_temperature, 24.0f); + + // Now fetch room temperature (0x03) + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS); + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x42, 0x01, 0x30, 0x10, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A)); + EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{300}); + EXPECT_FALSE(ctx.sut.status_update_start_ms_.has_value()); + + // Clear TX bytes. + ctx.uart.tx.clear(); + + // Room temperature response + ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x10, 0x03, 0x00, 0x00, 0x0B, 0x00, 0x00, + 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5}); + + // Room temperature should still have initial value + EXPECT_THAT(ctx.sut.status().room_temperature, ::testing::IsNan()); + + ctx.sut.set_current_time(400); + EXPECT_FALSE(ctx.sut.is_status_initialized()); + ASSERT_TRUE(ctx.sut.update()); + EXPECT_TRUE(ctx.uart.rx.empty()); + EXPECT_TRUE(ctx.sut.is_status_initialized()); + + // Check room temperature we just read from received package + EXPECT_EQ(ctx.sut.status().room_temperature, 21.0f); - // Nothing should be send to UART EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); + EXPECT_FALSE(ctx.sut.write_timeout_start_ms_.has_value()); + EXPECT_EQ(ctx.sut.status_update_start_ms_, std::optional<uint32_t>{400}); } TEST(MitsubishiCN105Tests, NoResponseTriggersReconnect) { @@ -55,21 +108,21 @@ TEST(MitsubishiCN105Tests, NoResponseTriggersReconnect) { ctx.uart.tx.clear(); // Remove first connect packet bytes // No response (no RX data), no retry yet - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_TRUE(ctx.uart.tx.empty()); EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{0}); // Still no response after 1999ms, no retry yet ctx.sut.set_current_time(1999); - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_TRUE(ctx.uart.tx.empty()); EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{0}); // Stop waiting after 2s and retry connect ctx.sut.set_current_time(2000); - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x5A, 0x01, 0x30, 0x02, 0xCA, 0x01, 0xA8)); EXPECT_EQ(ctx.sut.write_timeout_start_ms_, std::optional<uint32_t>{2000}); @@ -92,7 +145,7 @@ TEST(MitsubishiCN105Tests, RxWatchdogLimitsProcessingPerUpdate) { ASSERT_GT(ctx.uart.rx.size(), 64); // No valid response, no state change expected - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_TRUE(ctx.uart.tx.empty()); @@ -100,7 +153,7 @@ TEST(MitsubishiCN105Tests, RxWatchdogLimitsProcessingPerUpdate) { EXPECT_FALSE(ctx.uart.rx.empty()); // Next update will read remaining bytes, no state change expected - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_TRUE(ctx.uart.tx.empty()); EXPECT_TRUE(ctx.uart.rx.empty()); @@ -162,7 +215,7 @@ TEST(MitsubishiCN105Tests, ParserHandlesMixedRxStream) { // Drain RX - no valid response, no state change expected int iterations = 0; while (!ctx.uart.rx.empty() && iterations++ < 10) { - ctx.sut.update(); + ASSERT_FALSE(ctx.sut.update()); EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::CONNECTING); EXPECT_TRUE(ctx.uart.tx.empty()); } @@ -170,4 +223,81 @@ TEST(MitsubishiCN105Tests, ParserHandlesMixedRxStream) { EXPECT_TRUE(ctx.uart.rx.empty()); } +TEST(MitsubishiCN105Tests, NextStatusUpdateAfterUpdateIntervalMilliseconds) { + auto ctx = TestContext{}; + + ctx.sut.set_update_interval(2000); + ctx.sut.set_current_time(80000); + + // No scheduled status update + EXPECT_FALSE(ctx.sut.status_update_start_ms_.has_value()); + + // Status update completed, schedule next status update + ctx.sut.state_ = TestableMitsubishiCN105::State::STATUS_UPDATED; + ctx.sut.set_state(TestableMitsubishiCN105::State::SCHEDULE_NEXT_STATUS_UPDATE); + + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); + EXPECT_EQ(ctx.sut.status_update_start_ms_, std::optional<uint32_t>{80000}); + + // Wait for update_interval (ms) before doing another status update + ASSERT_FALSE(ctx.sut.update()); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); + + ctx.sut.set_current_time(81999); + ASSERT_FALSE(ctx.sut.update()); + EXPECT_TRUE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); + + ctx.sut.set_current_time(82000); + ASSERT_FALSE(ctx.sut.update()); + EXPECT_FALSE(ctx.uart.tx.empty()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS); + EXPECT_FALSE(ctx.sut.status_update_start_ms_.has_value()); +} + +TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedA) { + auto ctx = TestContext{}; + + ctx.uart.push_rx( + {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56}); + + ctx.sut.update(); + + EXPECT_TRUE(ctx.sut.status().power_on); + EXPECT_EQ(ctx.sut.status().target_temperature, 26.0f); +} + +TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) { + auto ctx = TestContext{}; + + ctx.uart.push_rx( + {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xB7}); + + ctx.sut.update(); + + EXPECT_FALSE(ctx.sut.status().power_on); + EXPECT_EQ(ctx.sut.status().target_temperature, 18.5f); +} + +TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedA) { + auto ctx = TestContext{}; + + ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x07, 0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x5D}); + + ctx.sut.update(); + + EXPECT_EQ(ctx.sut.status().room_temperature, 16.0f); +} + +TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedB) { + auto ctx = TestContext{}; + + ctx.uart.push_rx({0xFC, 0x62, 0x01, 0x30, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBC, 0xA7}); + + ctx.sut.update(); + + EXPECT_EQ(ctx.sut.status().room_temperature, 30.0f); +} + } // namespace esphome::mitsubishi_cn105::testing diff --git a/tests/components/mitsubishi_cn105/common.cpp b/tests/components/mitsubishi_cn105/common.cpp index ea13d7676c..50993c5c2c 100644 --- a/tests/components/mitsubishi_cn105/common.cpp +++ b/tests/components/mitsubishi_cn105/common.cpp @@ -2,6 +2,6 @@ namespace esphome::mitsubishi_cn105 { -uint32_t get_loop_time_ms() { return testing::TestableMitsubishiCN105::test_loop_time_ms; }; +uint32_t get_loop_time_ms() { return testing::TestableMitsubishiCN105::test_loop_time_ms; } } // namespace esphome::mitsubishi_cn105 diff --git a/tests/components/mitsubishi_cn105/common.h b/tests/components/mitsubishi_cn105/common.h index c41268d723..ed55c3dc0c 100644 --- a/tests/components/mitsubishi_cn105/common.h +++ b/tests/components/mitsubishi_cn105/common.h @@ -44,6 +44,9 @@ class TestableMitsubishiCN105 : public MitsubishiCN105 { using MitsubishiCN105::State; using MitsubishiCN105::state_; using MitsubishiCN105::write_timeout_start_ms_; + using MitsubishiCN105::status_update_start_ms_; + + void set_state(State s) { this->set_state_(s); } static inline uint32_t test_loop_time_ms = 0; From 2d9a42e4bad94c4c608cb18c40d83d2939391a0d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 13:56:21 -1000 Subject: [PATCH 1936/2030] [pcf8574][pca9554] Add optional interrupt pin to eliminate polling (#15444) --- .../components/gpio_expander/cached_gpio.h | 20 +++++++++++++++---- esphome/components/pca9554/__init__.py | 4 ++++ esphome/components/pca9554/pca9554.cpp | 19 +++++++++++++++--- esphome/components/pca9554/pca9554.h | 5 ++++- esphome/components/pcf8574/__init__.py | 4 ++++ esphome/components/pcf8574/pcf8574.cpp | 17 +++++++++++++++- esphome/components/pcf8574/pcf8574.h | 5 ++++- tests/components/pca9554/common.yaml | 5 +++++ tests/components/pca9554/test.esp32-idf.yaml | 3 +++ .../components/pca9554/test.esp8266-ard.yaml | 3 +++ tests/components/pca9554/test.rp2040-ard.yaml | 3 +++ tests/components/pcf8574/common.yaml | 5 +++++ tests/components/pcf8574/test.esp32-idf.yaml | 3 +++ .../components/pcf8574/test.esp8266-ard.yaml | 3 +++ tests/components/pcf8574/test.rp2040-ard.yaml | 3 +++ 15 files changed, 92 insertions(+), 10 deletions(-) diff --git a/esphome/components/gpio_expander/cached_gpio.h b/esphome/components/gpio_expander/cached_gpio.h index eeff98cb6e..ddb9e63686 100644 --- a/esphome/components/gpio_expander/cached_gpio.h +++ b/esphome/components/gpio_expander/cached_gpio.h @@ -28,7 +28,10 @@ namespace esphome::gpio_expander { template<typename T, uint16_t N, typename P = typename std::conditional<(N > 256), uint16_t, uint8_t>::type> class CachedGpioExpander { public: - /// @brief Read the state of the given pin. This will invalidate the cache for the given pin number. + /// @brief Read the state of the given pin. + /// By default, each read invalidates the pin's cache entry so the next read + /// of the same pin triggers a fresh hardware read. When invalidate_on_read + /// is disabled, the cache stays valid until explicitly cleared via reset_pin_cache_(). /// @param pin Pin number to read /// @return Pin state bool digital_read(P pin) { @@ -36,14 +39,17 @@ class CachedGpioExpander { const T pin_mask = (1 << (pin % BANK_SIZE)); // Check if specific pin cache is valid if (this->read_cache_valid_[bank] & pin_mask) { - // Invalidate pin - this->read_cache_valid_[bank] &= ~pin_mask; + if (this->invalidate_on_read_) { + // Invalidate pin so next read triggers hardware read + this->read_cache_valid_[bank] &= ~pin_mask; + } } else { // Read whole bank from hardware if (!this->digital_read_hw(pin)) return false; // Mark bank cache as valid except the pin that is being returned now - this->read_cache_valid_[bank] = std::numeric_limits<T>::max() & ~pin_mask; + // (when not invalidating on read, mark all pins including this one as valid) + this->read_cache_valid_[bank] = std::numeric_limits<T>::max() & ~(this->invalidate_on_read_ ? pin_mask : 0); } return this->digital_read_cache(pin); } @@ -71,12 +77,18 @@ class CachedGpioExpander { /// @brief Invalidate cache. This function should be called in component loop(). void reset_pin_cache_() { memset(this->read_cache_valid_, 0x00, CACHE_SIZE_BYTES); } + /// @brief Control whether digital_read() invalidates the pin's cache entry after reading. + /// When enabled (default), each read self-invalidates so the next read triggers a hardware read. + /// When disabled, cache stays valid until reset_pin_cache_() is explicitly called. + void set_invalidate_on_read_(bool invalidate) { this->invalidate_on_read_ = invalidate; } + static constexpr uint16_t BITS_PER_BYTE = 8; static constexpr uint16_t BANK_SIZE = sizeof(T) * BITS_PER_BYTE; static constexpr size_t BANKS = N / BANK_SIZE; static constexpr size_t CACHE_SIZE_BYTES = BANKS * sizeof(T); T read_cache_valid_[BANKS]{0}; + bool invalidate_on_read_{true}; }; } // namespace esphome::gpio_expander diff --git a/esphome/components/pca9554/__init__.py b/esphome/components/pca9554/__init__.py index 626b08a378..99b812b33b 100644 --- a/esphome/components/pca9554/__init__.py +++ b/esphome/components/pca9554/__init__.py @@ -5,6 +5,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_INPUT, + CONF_INTERRUPT_PIN, CONF_INVERTED, CONF_MODE, CONF_NUMBER, @@ -29,6 +30,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_ID): cv.declare_id(PCA9554Component), cv.Optional(CONF_PIN_COUNT, default=8): cv.one_of(4, 8, 16), + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ) .extend(cv.COMPONENT_SCHEMA) @@ -43,6 +45,8 @@ async def to_code(config): cg.add(var.set_pin_count(config[CONF_PIN_COUNT])) await cg.register_component(var, config) await i2c.register_i2c_device(var, config) + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) def validate_mode(value): diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index adc7bc0fb5..9b300eaac2 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -34,12 +34,24 @@ void PCA9554Component::setup() { this->read_inputs_(); ESP_LOGD(TAG, "Initialization complete. Warning: %d, Error: %d", this->status_has_warning(), this->status_has_error()); -} + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->attach_interrupt(&PCA9554Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); + // Don't invalidate cache on read — only invalidate when interrupt fires + this->set_invalidate_on_read_(false); + // With interrupt pin, only run loop when interrupt fires + this->disable_loop(); + } +} +void IRAM_ATTR PCA9554Component::gpio_intr(PCA9554Component *arg) { arg->enable_loop_soon_any_context(); } void PCA9554Component::loop() { - // Invalidate the cache at the start of each loop. - // The actual read will happen on demand when digital_read() is called + // Invalidate the cache so the next digital_read() triggers a fresh I2C read this->reset_pin_cache_(); + if (this->interrupt_pin_ != nullptr) { + // Interrupt-driven: disable loop until next interrupt fires + this->disable_loop(); + } } void PCA9554Component::dump_config() { @@ -47,6 +59,7 @@ void PCA9554Component::dump_config() { "PCA9554:\n" " I/O Pins: %d", this->pin_count_); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); LOG_I2C_DEVICE(this) if (this->is_failed()) { ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); diff --git a/esphome/components/pca9554/pca9554.h b/esphome/components/pca9554/pca9554.h index 1d877f9ce2..f33f9d4592 100644 --- a/esphome/components/pca9554/pca9554.h +++ b/esphome/components/pca9554/pca9554.h @@ -16,7 +16,6 @@ class PCA9554Component : public Component, /// Check i2c availability and setup masks void setup() override; - /// Invalidate cache at start of each loop void loop() override; /// Helper function to set the pin mode of a pin. void pin_mode(uint8_t pin, gpio::Flags flags); @@ -26,8 +25,11 @@ class PCA9554Component : public Component, void dump_config() override; void set_pin_count(size_t pin_count) { this->pin_count_ = pin_count; } + void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } protected: + static void IRAM_ATTR gpio_intr(PCA9554Component *arg); + bool read_inputs_(); bool write_register_(uint8_t reg, uint16_t value); @@ -48,6 +50,7 @@ class PCA9554Component : public Component, uint16_t input_mask_{0x00}; /// Storage for last I2C error seen esphome::i2c::ErrorCode last_error_; + InternalGPIOPin *interrupt_pin_{nullptr}; }; /// Helper class to expose a PCA9554 pin as an internal input GPIO pin. diff --git a/esphome/components/pcf8574/__init__.py b/esphome/components/pcf8574/__init__.py index f387d0a610..902efd2279 100644 --- a/esphome/components/pcf8574/__init__.py +++ b/esphome/components/pcf8574/__init__.py @@ -5,6 +5,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_INPUT, + CONF_INTERRUPT_PIN, CONF_INVERTED, CONF_MODE, CONF_NUMBER, @@ -27,6 +28,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_ID): cv.declare_id(PCF8574Component), cv.Optional(CONF_PCF8575, default=False): cv.boolean, + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ) .extend(cv.COMPONENT_SCHEMA) @@ -39,6 +41,8 @@ async def to_code(config): await cg.register_component(var, config) await i2c.register_i2c_device(var, config) cg.add(var.set_pcf8575(config[CONF_PCF8575])) + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) def validate_mode(value): diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index d3ec31436d..1eeef663b0 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -15,16 +15,31 @@ void PCF8574Component::setup() { this->write_gpio_(); this->read_gpio_(); + + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->attach_interrupt(&PCF8574Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); + // Don't invalidate cache on read — only invalidate when interrupt fires + this->set_invalidate_on_read_(false); + // With interrupt pin, only run loop when interrupt fires + this->disable_loop(); + } } +void IRAM_ATTR PCF8574Component::gpio_intr(PCF8574Component *arg) { arg->enable_loop_soon_any_context(); } void PCF8574Component::loop() { - // Invalidate the cache at the start of each loop + // Invalidate the cache so the next digital_read() triggers a fresh I2C read this->reset_pin_cache_(); + if (this->interrupt_pin_ != nullptr) { + // Interrupt-driven: disable loop until next interrupt fires + this->disable_loop(); + } } void PCF8574Component::dump_config() { ESP_LOGCONFIG(TAG, "PCF8574:\n" " Is PCF8575: %s", YESNO(this->pcf8575_)); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); LOG_I2C_DEVICE(this) if (this->is_failed()) { ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); diff --git a/esphome/components/pcf8574/pcf8574.h b/esphome/components/pcf8574/pcf8574.h index b039173789..cae2e930b7 100644 --- a/esphome/components/pcf8574/pcf8574.h +++ b/esphome/components/pcf8574/pcf8574.h @@ -17,10 +17,10 @@ class PCF8574Component : public Component, PCF8574Component() = default; void set_pcf8575(bool pcf8575) { pcf8575_ = pcf8575; } + void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } /// Check i2c availability and setup masks void setup() override; - /// Invalidate cache at start of each loop void loop() override; /// Helper function to set the pin mode of a pin. void pin_mode(uint8_t pin, gpio::Flags flags); @@ -30,6 +30,8 @@ class PCF8574Component : public Component, void dump_config() override; protected: + static void IRAM_ATTR gpio_intr(PCF8574Component *arg); + bool digital_read_hw(uint8_t pin) override; bool digital_read_cache(uint8_t pin) override; void digital_write_hw(uint8_t pin, bool value) override; @@ -44,6 +46,7 @@ class PCF8574Component : public Component, /// The state read in read_gpio_ - 1 means HIGH, 0 means LOW uint16_t input_mask_{0x00}; bool pcf8575_; ///< TRUE->16-channel PCF8575, FALSE->8-channel PCF8574 + InternalGPIOPin *interrupt_pin_{nullptr}; }; /// Helper class to expose a PCF8574 pin as an internal input GPIO pin. diff --git a/tests/components/pca9554/common.yaml b/tests/components/pca9554/common.yaml index 9e5e7f3342..82a88b90aa 100644 --- a/tests/components/pca9554/common.yaml +++ b/tests/components/pca9554/common.yaml @@ -3,6 +3,11 @@ pca9554: i2c_id: i2c_bus pin_count: 8 address: 0x3F + - id: pca9554_hub_int + i2c_id: i2c_bus + pin_count: 8 + address: 0x3E + interrupt_pin: ${interrupt_pin} binary_sensor: - platform: gpio diff --git a/tests/components/pca9554/test.esp32-idf.yaml b/tests/components/pca9554/test.esp32-idf.yaml index b47e39c389..8c3b341dce 100644 --- a/tests/components/pca9554/test.esp32-idf.yaml +++ b/tests/components/pca9554/test.esp32-idf.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml diff --git a/tests/components/pca9554/test.esp8266-ard.yaml b/tests/components/pca9554/test.esp8266-ard.yaml index 4a98b9388a..69b243bfd8 100644 --- a/tests/components/pca9554/test.esp8266-ard.yaml +++ b/tests/components/pca9554/test.esp8266-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml diff --git a/tests/components/pca9554/test.rp2040-ard.yaml b/tests/components/pca9554/test.rp2040-ard.yaml index 319a7c71a6..b8ad1e4792 100644 --- a/tests/components/pca9554/test.rp2040-ard.yaml +++ b/tests/components/pca9554/test.rp2040-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO2 + packages: i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml diff --git a/tests/components/pcf8574/common.yaml b/tests/components/pcf8574/common.yaml index 09fa33164e..8a26b93015 100644 --- a/tests/components/pcf8574/common.yaml +++ b/tests/components/pcf8574/common.yaml @@ -3,6 +3,11 @@ pcf8574: i2c_id: i2c_bus address: 0x21 pcf8575: false + - id: pcf8574_hub_int + i2c_id: i2c_bus + address: 0x22 + pcf8575: false + interrupt_pin: ${interrupt_pin} binary_sensor: - platform: gpio diff --git a/tests/components/pcf8574/test.esp32-idf.yaml b/tests/components/pcf8574/test.esp32-idf.yaml index b47e39c389..8c3b341dce 100644 --- a/tests/components/pcf8574/test.esp32-idf.yaml +++ b/tests/components/pcf8574/test.esp32-idf.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml diff --git a/tests/components/pcf8574/test.esp8266-ard.yaml b/tests/components/pcf8574/test.esp8266-ard.yaml index 4a98b9388a..69b243bfd8 100644 --- a/tests/components/pcf8574/test.esp8266-ard.yaml +++ b/tests/components/pcf8574/test.esp8266-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml diff --git a/tests/components/pcf8574/test.rp2040-ard.yaml b/tests/components/pcf8574/test.rp2040-ard.yaml index 319a7c71a6..b8ad1e4792 100644 --- a/tests/components/pcf8574/test.rp2040-ard.yaml +++ b/tests/components/pcf8574/test.rp2040-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO2 + packages: i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml From 4d2062282ed68f7f6ca793b4ffb22c73bd130d5c Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sun, 5 Apr 2026 11:11:49 +1000 Subject: [PATCH 1937/2030] [mipi_spi] Run spi final validation (#15418) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/mipi_spi/display.py | 8 +++++--- tests/component_tests/mipi_spi/conftest.py | 11 +++++++++++ .../component_tests/mipi_spi/test_display_metadata.py | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/components/mipi_spi/display.py b/esphome/components/mipi_spi/display.py index 6aa98e3f66..42c7ec2224 100644 --- a/esphome/components/mipi_spi/display.py +++ b/esphome/components/mipi_spi/display.py @@ -279,6 +279,10 @@ def _final_validate(config): from esphome.components.lvgl import DOMAIN as LVGL_DOMAIN + if config[CONF_BUS_MODE] == TYPE_SINGLE: + spi.final_validate_device_schema(DOMAIN, require_miso=False, require_mosi=True)( + config + ) if not requires_buffer(config) and LVGL_DOMAIN not in global_config: # If no drawing methods are configured, and LVGL is not enabled, show a test card config[CONF_SHOW_TEST_CARD] = True @@ -286,7 +290,7 @@ def _final_validate(config): if PSRAM_DOMAIN not in global_config and CONF_BUFFER_SIZE not in config: # If PSRAM is not enabled, choose a small buffer size by default if not requires_buffer(config): - return config # No buffer needed, so no need to set a buffer size + return # No need to pick a size color_depth = get_color_depth(config) frac = denominator(config) width, height, _offset_width, _offset_height = model.get_dimensions(config) @@ -298,8 +302,6 @@ def _final_validate(config): x for x in range(2, 17) if fraction >= 1 / x ) - return config - FINAL_VALIDATE_SCHEMA = _final_validate diff --git a/tests/component_tests/mipi_spi/conftest.py b/tests/component_tests/mipi_spi/conftest.py index eddf0987d0..082a9e55f2 100644 --- a/tests/component_tests/mipi_spi/conftest.py +++ b/tests/component_tests/mipi_spi/conftest.py @@ -1,6 +1,7 @@ """Tests for mpip_spi configuration validation.""" from collections.abc import Callable, Generator +from unittest import mock import pytest @@ -12,6 +13,16 @@ from esphome.core import CORE from esphome.pins import gpio_pin_schema +@pytest.fixture(autouse=True) +def mock_spi_final_validate(): + """Mock spi.final_validate_device_schema since unit tests have no real SPI bus config.""" + with mock.patch( + "esphome.components.spi.final_validate_device_schema", + return_value=lambda config: None, + ): + yield + + @pytest.fixture def choose_variant_with_pins() -> Generator[Callable[[list], None]]: """ diff --git a/tests/component_tests/mipi_spi/test_display_metadata.py b/tests/component_tests/mipi_spi/test_display_metadata.py index ab42a75694..c11c7816e4 100644 --- a/tests/component_tests/mipi_spi/test_display_metadata.py +++ b/tests/component_tests/mipi_spi/test_display_metadata.py @@ -25,7 +25,9 @@ from tests.component_tests.types import SetCoreConfigCallable def validated_config(config): """Run schema + final validation and return the validated config.""" - return FINAL_VALIDATE_SCHEMA(CONFIG_SCHEMA(config)) + config = CONFIG_SCHEMA(config) + FINAL_VALIDATE_SCHEMA(config) + return config def test_metadata_native_quad_default_test_card( From 9ea27e68ee0ed94b6b693c14fab1ac10db31aba2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sat, 4 Apr 2026 22:52:40 -1000 Subject: [PATCH 1938/2030] [pcf8574][pca9554] Disable loop when all pins are outputs (#15455) --- esphome/components/pca9554/pca9554.cpp | 11 +++++++++-- esphome/components/pcf8574/pcf8574.cpp | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index 9b300eaac2..ac4f119dfe 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -40,9 +40,11 @@ void PCA9554Component::setup() { this->interrupt_pin_->attach_interrupt(&PCA9554Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); // Don't invalidate cache on read — only invalidate when interrupt fires this->set_invalidate_on_read_(false); - // With interrupt pin, only run loop when interrupt fires - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } void IRAM_ATTR PCA9554Component::gpio_intr(PCA9554Component *arg) { arg->enable_loop_soon_any_context(); } void PCA9554Component::loop() { @@ -89,6 +91,11 @@ void PCA9554Component::pin_mode(uint8_t pin, gpio::Flags flags) { if (flags == gpio::FLAG_INPUT) { // Clear mode mask bit this->config_mask_ &= ~(1 << pin); + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr) { + this->enable_loop(); + } } else if (flags == gpio::FLAG_OUTPUT) { // Set mode mask bit this->config_mask_ |= 1 << pin; diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index 1eeef663b0..bf4a9442a2 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -21,9 +21,11 @@ void PCF8574Component::setup() { this->interrupt_pin_->attach_interrupt(&PCF8574Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); // Don't invalidate cache on read — only invalidate when interrupt fires this->set_invalidate_on_read_(false); - // With interrupt pin, only run loop when interrupt fires - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } void IRAM_ATTR PCF8574Component::gpio_intr(PCF8574Component *arg) { arg->enable_loop_soon_any_context(); } void PCF8574Component::loop() { @@ -66,6 +68,11 @@ void PCF8574Component::pin_mode(uint8_t pin, gpio::Flags flags) { this->mode_mask_ &= ~(1 << pin); // Write GPIO to enable input mode this->write_gpio_(); + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr) { + this->enable_loop(); + } } else if (flags == gpio::FLAG_OUTPUT) { // Set mode mask bit this->mode_mask_ |= 1 << pin; From 2d7eb116f20064cdd5774441627294e36669c98e Mon Sep 17 00:00:00 2001 From: Javier Peletier <jpeletier@users.noreply.github.com> Date: Sun, 5 Apr 2026 12:11:49 +0200 Subject: [PATCH 1939/2030] [spi] Enable host-platform builds for unit testing (#15188) --- esphome/components/spi/spi.cpp | 10 +++++++++- esphome/components/spi/spi.h | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/spi/spi.cpp b/esphome/components/spi/spi.cpp index 36344a6d38..20359135ba 100644 --- a/esphome/components/spi/spi.cpp +++ b/esphome/components/spi/spi.cpp @@ -68,7 +68,7 @@ void SPIComponent::dump_config() { LOG_PIN(" SDI Pin: ", this->sdi_pin_); LOG_PIN(" SDO Pin: ", this->sdo_pin_); for (size_t i = 0; i != this->data_pins_.size(); i++) { - ESP_LOGCONFIG(TAG, " Data pin %u: GPIO%d", i, this->data_pins_[i]); + ESP_LOGCONFIG(TAG, " Data pin %zu: GPIO%d", i, this->data_pins_[i]); } if (this->spi_bus_->is_hw()) { ESP_LOGCONFIG(TAG, " Using HW SPI: %s", this->interface_name_); @@ -118,4 +118,12 @@ uint16_t SPIDelegateBitBash::transfer_(uint16_t data, size_t num_bits) { return out_data; } +#if !defined(USE_ESP32) && !defined(USE_ARDUINO) +// Stub for unsupported platforms (host, Zephyr, etc.) - hardware SPI is unavailable +SPIBus *SPIComponent::get_bus(SPIInterface interface, GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi, + const std::vector<uint8_t> &data_pins) { + return nullptr; +} +#endif + } // namespace esphome::spi diff --git a/esphome/components/spi/spi.h b/esphome/components/spi/spi.h index 84c8bca267..dc538f4c41 100644 --- a/esphome/components/spi/spi.h +++ b/esphome/components/spi/spi.h @@ -23,9 +23,9 @@ using SPIInterface = SPIClassRP2040 *; using SPIInterface = SPIClass *; #endif -#elif defined(CLANG_TIDY) +#elif defined(USE_HOST) || defined(CLANG_TIDY) -using SPIInterface = void *; // Stub for platforms without SPI (e.g., Zephyr) +using SPIInterface = void *; // Stub for platforms without SPI (e.g., host, Zephyr) #endif // USE_ESP32 / USE_ARDUINO From dae8ea1b043bacb0a26def16b3ce4929324e6064 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 08:26:39 -1000 Subject: [PATCH 1940/2030] [mcp23xxx][pi4ioe5v6408] Add optional interrupt pin to eliminate polling (#15445) --- esphome/components/mcp23008/mcp23008.cpp | 7 ++++- esphome/components/mcp23017/mcp23017.cpp | 23 ++++++++++++---- esphome/components/mcp23s08/mcp23s08.cpp | 3 +++ esphome/components/mcp23s17/mcp23s17.cpp | 23 +++++++++++----- .../mcp23x08_base/mcp23x08_base.cpp | 5 ++++ .../mcp23x17_base/mcp23x17_base.cpp | 5 ++++ esphome/components/mcp23xxx_base/__init__.py | 4 +++ .../mcp23xxx_base/mcp23xxx_base.cpp | 7 ++++- .../components/mcp23xxx_base/mcp23xxx_base.h | 23 +++++++++++++++- esphome/components/pi4ioe5v6408/__init__.py | 4 +++ .../components/pi4ioe5v6408/pi4ioe5v6408.cpp | 26 ++++++++++++++++++- .../components/pi4ioe5v6408/pi4ioe5v6408.h | 4 +++ tests/components/mcp23008/common.yaml | 14 ++++++++-- tests/components/mcp23008/test.esp32-idf.yaml | 3 +++ .../components/mcp23008/test.esp8266-ard.yaml | 3 +++ .../components/mcp23008/test.rp2040-ard.yaml | 3 +++ tests/components/mcp23017/common.yaml | 14 ++++++++-- tests/components/mcp23017/test.esp32-idf.yaml | 3 +++ .../components/mcp23017/test.esp8266-ard.yaml | 3 +++ .../components/mcp23017/test.rp2040-ard.yaml | 3 +++ tests/components/mcp23s08/common.yaml | 1 + tests/components/mcp23s08/test.esp32-idf.yaml | 1 + .../components/mcp23s08/test.esp8266-ard.yaml | 1 + .../components/mcp23s08/test.rp2040-ard.yaml | 1 + tests/components/mcp23s17/common.yaml | 1 + tests/components/mcp23s17/test.esp32-idf.yaml | 1 + .../components/mcp23s17/test.esp8266-ard.yaml | 1 + .../components/mcp23s17/test.rp2040-ard.yaml | 1 + tests/components/pi4ioe5v6408/common.yaml | 15 ++++++++--- .../pi4ioe5v6408/test.esp32-idf.yaml | 1 + .../pi4ioe5v6408/test.rp2040-ard.yaml | 1 + 31 files changed, 183 insertions(+), 22 deletions(-) diff --git a/esphome/components/mcp23008/mcp23008.cpp b/esphome/components/mcp23008/mcp23008.cpp index 64b120daa4..5f73e03f6f 100644 --- a/esphome/components/mcp23008/mcp23008.cpp +++ b/esphome/components/mcp23008/mcp23008.cpp @@ -22,9 +22,14 @@ void MCP23008::setup() { // enable open-drain interrupt pins, 3.3V-safe this->write_reg(mcp23x08_base::MCP23X08_IOCON, iocon | IOCON_ODR); } + + this->setup_interrupt_pin_(); } -void MCP23008::dump_config() { ESP_LOGCONFIG(TAG, "MCP23008:"); } +void MCP23008::dump_config() { + ESP_LOGCONFIG(TAG, "MCP23008:"); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); +} bool MCP23008::read_reg(uint8_t reg, uint8_t *value) { if (this->is_failed()) diff --git a/esphome/components/mcp23017/mcp23017.cpp b/esphome/components/mcp23017/mcp23017.cpp index e14e317d44..212c15ccf2 100644 --- a/esphome/components/mcp23017/mcp23017.cpp +++ b/esphome/components/mcp23017/mcp23017.cpp @@ -6,7 +6,8 @@ namespace mcp23017 { static const char *const TAG = "mcp23017"; -static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin +static constexpr uint8_t IOCON_MIRROR = 0x40; // Mirror INTA/INTB pins +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin void MCP23017::setup() { uint8_t iocon; @@ -19,14 +20,26 @@ void MCP23017::setup() { this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_); this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_); + uint8_t iocon_flags = 0; if (this->open_drain_ints_) { - // enable open-drain interrupt pins, 3.3V-safe - this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon | IOCON_ODR); - this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | IOCON_ODR); + iocon_flags |= IOCON_ODR; } + if (this->interrupt_pin_ != nullptr) { + // Mirror INTA/INTB so either pin fires for changes on any port + iocon_flags |= IOCON_MIRROR; + } + if (iocon_flags != 0) { + this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon | iocon_flags); + this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | iocon_flags); + } + + this->setup_interrupt_pin_(); } -void MCP23017::dump_config() { ESP_LOGCONFIG(TAG, "MCP23017:"); } +void MCP23017::dump_config() { + ESP_LOGCONFIG(TAG, "MCP23017:"); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); +} bool MCP23017::read_reg(uint8_t reg, uint8_t *value) { if (this->is_failed()) diff --git a/esphome/components/mcp23s08/mcp23s08.cpp b/esphome/components/mcp23s08/mcp23s08.cpp index 1c17b66637..983c1aa600 100644 --- a/esphome/components/mcp23s08/mcp23s08.cpp +++ b/esphome/components/mcp23s08/mcp23s08.cpp @@ -34,11 +34,14 @@ void MCP23S08::setup() { // enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip) this->write_reg(mcp23x08_base::MCP23X08_IOCON, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); } + + this->setup_interrupt_pin_(); } void MCP23S08::dump_config() { ESP_LOGCONFIG(TAG, "MCP23S08:"); LOG_PIN(" CS Pin: ", this->cs_); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); } bool MCP23S08::read_reg(uint8_t reg, uint8_t *value) { diff --git a/esphome/components/mcp23s17/mcp23s17.cpp b/esphome/components/mcp23s17/mcp23s17.cpp index c6abd7ad59..db9a34e230 100644 --- a/esphome/components/mcp23s17/mcp23s17.cpp +++ b/esphome/components/mcp23s17/mcp23s17.cpp @@ -7,9 +7,10 @@ namespace mcp23s17 { static const char *const TAG = "mcp23s17"; // IOCON register bits -static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode -static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable -static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin +static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode +static constexpr uint8_t IOCON_MIRROR = 0x40; // Mirror INTA/INTB pins +static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable +static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin void MCP23S17::set_device_address(uint8_t device_addr) { if (device_addr != 0) { @@ -37,16 +38,26 @@ void MCP23S17::setup() { this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_); this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_); + uint8_t iocon_flags = IOCON_SEQOP | IOCON_HAEN; if (this->open_drain_ints_) { - // enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip) - this->write_reg(mcp23x17_base::MCP23X17_IOCONA, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); - this->write_reg(mcp23x17_base::MCP23X17_IOCONB, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR); + iocon_flags |= IOCON_ODR; } + if (this->interrupt_pin_ != nullptr) { + // Mirror INTA/INTB so either pin fires for changes on any port + iocon_flags |= IOCON_MIRROR; + } + if (this->open_drain_ints_ || this->interrupt_pin_ != nullptr) { + this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon_flags); + this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon_flags); + } + + this->setup_interrupt_pin_(); } void MCP23S17::dump_config() { ESP_LOGCONFIG(TAG, "MCP23S17:"); LOG_PIN(" CS Pin: ", this->cs_); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); } bool MCP23S17::read_reg(uint8_t reg, uint8_t *value) { diff --git a/esphome/components/mcp23x08_base/mcp23x08_base.cpp b/esphome/components/mcp23x08_base/mcp23x08_base.cpp index 92228be62c..e4f4d50aae 100644 --- a/esphome/components/mcp23x08_base/mcp23x08_base.cpp +++ b/esphome/components/mcp23x08_base/mcp23x08_base.cpp @@ -32,6 +32,11 @@ void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) { } else if (flags == gpio::FLAG_OUTPUT) { this->update_reg(pin, false, iodir); } + // When interrupt_pin is configured, auto-enable CHANGE interrupt for input pins + // so the chip's INT output fires on any input state change + if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { + this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); + } } void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23x17_base/mcp23x17_base.cpp b/esphome/components/mcp23x17_base/mcp23x17_base.cpp index 6f95ee98fd..42613053de 100644 --- a/esphome/components/mcp23x17_base/mcp23x17_base.cpp +++ b/esphome/components/mcp23x17_base/mcp23x17_base.cpp @@ -44,6 +44,11 @@ void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) { } else if (flags == gpio::FLAG_OUTPUT) { this->update_reg(pin, false, iodir); } + // When interrupt_pin is configured, auto-enable CHANGE interrupt for input pins + // so the chip's INT output fires on any input state change + if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { + this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); + } } void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23xxx_base/__init__.py b/esphome/components/mcp23xxx_base/__init__.py index d6e82101ad..cd952099c0 100644 --- a/esphome/components/mcp23xxx_base/__init__.py +++ b/esphome/components/mcp23xxx_base/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_ID, CONF_INPUT, CONF_INTERRUPT, + CONF_INTERRUPT_PIN, CONF_INVERTED, CONF_MODE, CONF_NUMBER, @@ -32,6 +33,7 @@ MCP23XXX_INTERRUPT_MODES = { MCP23XXX_CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean, + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ).extend(cv.COMPONENT_SCHEMA) @@ -43,6 +45,8 @@ async def register_mcp23xxx(config, num_pins): await cg.register_component(var, config) CORE.data.setdefault(CONF_MCP23XXX, {})[id.id] = num_pins cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT])) + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) return var diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp b/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp index 535119fc5c..4c1daac562 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.cpp @@ -7,7 +7,12 @@ namespace mcp23xxx_base { template<uint8_t N> void MCP23XXXGPIOPin<N>::setup() { this->pin_mode(flags_); - this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_); + // When interrupt_pin is configured, pin_mode() already auto-enables CHANGE + // interrupt for input pins, so skip the explicit call if the user didn't + // override the default (NO_INTERRUPT) + if (this->interrupt_mode_ != MCP23XXX_NO_INTERRUPT || this->parent_->get_interrupt_pin() == nullptr) { + this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_); + } } template<uint8_t N> void MCP23XXXGPIOPin<N>::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); } template<uint8_t N> bool MCP23XXXGPIOPin<N>::digital_read() { diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.h b/esphome/components/mcp23xxx_base/mcp23xxx_base.h index fb992466d5..e77eac87e7 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.h +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.h @@ -15,11 +15,31 @@ template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander: virtual void pin_interrupt_mode(uint8_t pin, MCP23XXXInterruptMode interrupt_mode); void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; } + void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } + InternalGPIOPin *get_interrupt_pin() const { return this->interrupt_pin_; } float get_setup_priority() const override { return setup_priority::IO; } - void loop() override { this->reset_pin_cache_(); } + void loop() override { + this->reset_pin_cache_(); + if (this->interrupt_pin_ != nullptr) { + this->disable_loop(); + } + } protected: + // No need to clear latched interrupts before attaching the ISR — if INT is + // already low the ISR fires immediately, loop runs, cache invalidates, and + // the GPIO read clears the latch. One harmless extra read at most. + void setup_interrupt_pin_() { + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->attach_interrupt(&MCP23XXXBase::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); + this->set_invalidate_on_read_(false); + this->disable_loop(); + } + } + static void IRAM_ATTR gpio_intr(MCP23XXXBase *arg) { arg->enable_loop_soon_any_context(); } + // read a given register virtual bool read_reg(uint8_t reg, uint8_t *value) = 0; // write a value to a given register @@ -28,6 +48,7 @@ template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander: virtual void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a) = 0; bool open_drain_ints_; + InternalGPIOPin *interrupt_pin_{nullptr}; }; template<uint8_t N> class MCP23XXXGPIOPin : public GPIOPin { diff --git a/esphome/components/pi4ioe5v6408/__init__.py b/esphome/components/pi4ioe5v6408/__init__.py index c64f923823..d5b19dab1c 100644 --- a/esphome/components/pi4ioe5v6408/__init__.py +++ b/esphome/components/pi4ioe5v6408/__init__.py @@ -5,6 +5,7 @@ import esphome.config_validation as cv from esphome.const import ( CONF_ID, CONF_INPUT, + CONF_INTERRUPT_PIN, CONF_INVERTED, CONF_MODE, CONF_NUMBER, @@ -33,6 +34,7 @@ CONFIG_SCHEMA = ( { cv.Required(CONF_ID): cv.declare_id(PI4IOE5V6408Component), cv.Optional(CONF_RESET, default=True): cv.boolean, + cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema, } ) .extend(cv.COMPONENT_SCHEMA) @@ -46,6 +48,8 @@ async def to_code(config): await i2c.register_i2c_device(var, config) cg.add(var.set_reset(config[CONF_RESET])) + if interrupt_pin := config.get(CONF_INTERRUPT_PIN): + cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin))) def validate_mode(value): diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index 9247e114f0..8e38e7fa1d 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -33,9 +33,21 @@ void PI4IOE5V6408Component::setup() { return; } } + + // No need to clear latched interrupts before attaching the ISR — if INT is + // already low the ISR fires immediately, loop runs, cache invalidates, and + // the read clears the latch. One harmless extra read at most. + if (this->interrupt_pin_ != nullptr) { + this->interrupt_pin_->setup(); + this->interrupt_pin_->attach_interrupt(&PI4IOE5V6408Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); + this->set_invalidate_on_read_(false); + this->disable_loop(); + } } +void IRAM_ATTR PI4IOE5V6408Component::gpio_intr(PI4IOE5V6408Component *arg) { arg->enable_loop_soon_any_context(); } void PI4IOE5V6408Component::dump_config() { ESP_LOGCONFIG(TAG, "PI4IOE5V6408:"); + LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_); LOG_I2C_DEVICE(this) if (this->is_failed()) { ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL); @@ -60,7 +72,12 @@ void PI4IOE5V6408Component::pin_mode(uint8_t pin, gpio::Flags flags) { this->write_gpio_modes_(); } -void PI4IOE5V6408Component::loop() { this->reset_pin_cache_(); } +void PI4IOE5V6408Component::loop() { + this->reset_pin_cache_(); + if (this->interrupt_pin_ != nullptr) { + this->disable_loop(); + } +} bool PI4IOE5V6408Component::read_gpio_outputs_() { if (this->is_failed()) @@ -142,6 +159,13 @@ bool PI4IOE5V6408Component::write_gpio_modes_() { this->status_set_warning(LOG_STR("Failed to write GPIO pull enable")); return false; } + // Enable interrupts for input pins when interrupt pin is configured + // (input pins have mode_mask_ bit cleared) + if (this->interrupt_pin_ != nullptr && + !this->write_byte(PI4IOE5V6408_REGISTER_INTERRUPT_ENABLE_MASK, static_cast<uint8_t>(~this->mode_mask_))) { + this->status_set_warning(LOG_STR("Failed to write interrupt enable mask")); + return false; + } #if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE ESP_LOGV(TAG, "Wrote GPIO config:\n" diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h index 4dc31201ce..ff2474fe99 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.h @@ -22,8 +22,11 @@ class PI4IOE5V6408Component : public Component, /// Indicate if the component should reset the state during setup void set_reset(bool reset) { this->reset_ = reset; } + void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; } protected: + static void IRAM_ATTR gpio_intr(PI4IOE5V6408Component *arg); + bool digital_read_hw(uint8_t pin) override; bool digital_read_cache(uint8_t pin) override; void digital_write_hw(uint8_t pin, bool value) override; @@ -40,6 +43,7 @@ class PI4IOE5V6408Component : public Component, uint8_t pull_up_down_mask_{0x00}; bool reset_{true}; + InternalGPIOPin *interrupt_pin_{nullptr}; bool read_gpio_modes_(); bool write_gpio_modes_(); diff --git a/tests/components/mcp23008/common.yaml b/tests/components/mcp23008/common.yaml index 4a407adfd8..7eeee409ff 100644 --- a/tests/components/mcp23008/common.yaml +++ b/tests/components/mcp23008/common.yaml @@ -1,6 +1,10 @@ mcp23008: - i2c_id: i2c_bus - id: mcp23008_hub + - i2c_id: i2c_bus + id: mcp23008_hub + - i2c_id: i2c_bus + id: mcp23008_hub_int + address: 0x21 + interrupt_pin: ${interrupt_pin} binary_sensor: - platform: gpio @@ -9,6 +13,12 @@ binary_sensor: mcp23xxx: mcp23008_hub number: 0 mode: INPUT + - platform: gpio + id: mcp23008_binary_sensor_int + pin: + mcp23xxx: mcp23008_hub_int + number: 0 + mode: INPUT switch: - platform: gpio diff --git a/tests/components/mcp23008/test.esp32-idf.yaml b/tests/components/mcp23008/test.esp32-idf.yaml index b47e39c389..8c3b341dce 100644 --- a/tests/components/mcp23008/test.esp32-idf.yaml +++ b/tests/components/mcp23008/test.esp32-idf.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml diff --git a/tests/components/mcp23008/test.esp8266-ard.yaml b/tests/components/mcp23008/test.esp8266-ard.yaml index 4a98b9388a..69b243bfd8 100644 --- a/tests/components/mcp23008/test.esp8266-ard.yaml +++ b/tests/components/mcp23008/test.esp8266-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml diff --git a/tests/components/mcp23008/test.rp2040-ard.yaml b/tests/components/mcp23008/test.rp2040-ard.yaml index 319a7c71a6..b8ad1e4792 100644 --- a/tests/components/mcp23008/test.rp2040-ard.yaml +++ b/tests/components/mcp23008/test.rp2040-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO2 + packages: i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml diff --git a/tests/components/mcp23017/common.yaml b/tests/components/mcp23017/common.yaml index 54a97e911f..8b1e32600e 100644 --- a/tests/components/mcp23017/common.yaml +++ b/tests/components/mcp23017/common.yaml @@ -1,6 +1,10 @@ mcp23017: - i2c_id: i2c_bus - id: mcp23017_hub + - i2c_id: i2c_bus + id: mcp23017_hub + - i2c_id: i2c_bus + id: mcp23017_hub_int + address: 0x21 + interrupt_pin: ${interrupt_pin} binary_sensor: - platform: gpio @@ -9,6 +13,12 @@ binary_sensor: mcp23xxx: mcp23017_hub number: 0 mode: INPUT + - platform: gpio + id: mcp23017_binary_sensor_int + pin: + mcp23xxx: mcp23017_hub_int + number: 0 + mode: INPUT switch: - platform: gpio diff --git a/tests/components/mcp23017/test.esp32-idf.yaml b/tests/components/mcp23017/test.esp32-idf.yaml index b47e39c389..8c3b341dce 100644 --- a/tests/components/mcp23017/test.esp32-idf.yaml +++ b/tests/components/mcp23017/test.esp32-idf.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml diff --git a/tests/components/mcp23017/test.esp8266-ard.yaml b/tests/components/mcp23017/test.esp8266-ard.yaml index 4a98b9388a..69b243bfd8 100644 --- a/tests/components/mcp23017/test.esp8266-ard.yaml +++ b/tests/components/mcp23017/test.esp8266-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO15 + packages: i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml diff --git a/tests/components/mcp23017/test.rp2040-ard.yaml b/tests/components/mcp23017/test.rp2040-ard.yaml index 319a7c71a6..b8ad1e4792 100644 --- a/tests/components/mcp23017/test.rp2040-ard.yaml +++ b/tests/components/mcp23017/test.rp2040-ard.yaml @@ -1,3 +1,6 @@ +substitutions: + interrupt_pin: GPIO2 + packages: i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml diff --git a/tests/components/mcp23s08/common.yaml b/tests/components/mcp23s08/common.yaml index 2170ae0459..327bf02ca9 100644 --- a/tests/components/mcp23s08/common.yaml +++ b/tests/components/mcp23s08/common.yaml @@ -2,3 +2,4 @@ mcp23s08: - id: mcp23s08_hub cs_pin: ${cs_pin} deviceaddress: 0 + interrupt_pin: ${interrupt_pin} diff --git a/tests/components/mcp23s08/test.esp32-idf.yaml b/tests/components/mcp23s08/test.esp32-idf.yaml index a3352cf880..eeb6941645 100644 --- a/tests/components/mcp23s08/test.esp32-idf.yaml +++ b/tests/components/mcp23s08/test.esp32-idf.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO5 + interrupt_pin: GPIO15 packages: spi: !include ../../test_build_components/common/spi/esp32-idf.yaml diff --git a/tests/components/mcp23s08/test.esp8266-ard.yaml b/tests/components/mcp23s08/test.esp8266-ard.yaml index 595f31046a..ffc40b3595 100644 --- a/tests/components/mcp23s08/test.esp8266-ard.yaml +++ b/tests/components/mcp23s08/test.esp8266-ard.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO15 + interrupt_pin: GPIO0 packages: spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml diff --git a/tests/components/mcp23s08/test.rp2040-ard.yaml b/tests/components/mcp23s08/test.rp2040-ard.yaml index 79ea6ce90b..09b87ca3f8 100644 --- a/tests/components/mcp23s08/test.rp2040-ard.yaml +++ b/tests/components/mcp23s08/test.rp2040-ard.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO5 + interrupt_pin: GPIO2 packages: spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml diff --git a/tests/components/mcp23s17/common.yaml b/tests/components/mcp23s17/common.yaml index a89beeb16b..150ecca325 100644 --- a/tests/components/mcp23s17/common.yaml +++ b/tests/components/mcp23s17/common.yaml @@ -2,3 +2,4 @@ mcp23s17: - id: mcp23s17_hub cs_pin: ${cs_pin} deviceaddress: 0 + interrupt_pin: ${interrupt_pin} diff --git a/tests/components/mcp23s17/test.esp32-idf.yaml b/tests/components/mcp23s17/test.esp32-idf.yaml index a3352cf880..eeb6941645 100644 --- a/tests/components/mcp23s17/test.esp32-idf.yaml +++ b/tests/components/mcp23s17/test.esp32-idf.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO5 + interrupt_pin: GPIO15 packages: spi: !include ../../test_build_components/common/spi/esp32-idf.yaml diff --git a/tests/components/mcp23s17/test.esp8266-ard.yaml b/tests/components/mcp23s17/test.esp8266-ard.yaml index 595f31046a..ffc40b3595 100644 --- a/tests/components/mcp23s17/test.esp8266-ard.yaml +++ b/tests/components/mcp23s17/test.esp8266-ard.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO15 + interrupt_pin: GPIO0 packages: spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml diff --git a/tests/components/mcp23s17/test.rp2040-ard.yaml b/tests/components/mcp23s17/test.rp2040-ard.yaml index 79ea6ce90b..09b87ca3f8 100644 --- a/tests/components/mcp23s17/test.rp2040-ard.yaml +++ b/tests/components/mcp23s17/test.rp2040-ard.yaml @@ -1,5 +1,6 @@ substitutions: cs_pin: GPIO5 + interrupt_pin: GPIO2 packages: spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml diff --git a/tests/components/pi4ioe5v6408/common.yaml b/tests/components/pi4ioe5v6408/common.yaml index 2344622081..77a77fa3e4 100644 --- a/tests/components/pi4ioe5v6408/common.yaml +++ b/tests/components/pi4ioe5v6408/common.yaml @@ -1,7 +1,11 @@ pi4ioe5v6408: - i2c_id: i2c_bus - id: pi4ioe1 - address: 0x44 + - i2c_id: i2c_bus + id: pi4ioe1 + address: 0x44 + - i2c_id: i2c_bus + id: pi4ioe1_int + address: 0x45 + interrupt_pin: ${interrupt_pin} switch: - platform: gpio @@ -16,3 +20,8 @@ binary_sensor: pin: pi4ioe5v6408: pi4ioe1 number: 1 + - platform: gpio + id: sensor1_int + pin: + pi4ioe5v6408: pi4ioe1_int + number: 1 diff --git a/tests/components/pi4ioe5v6408/test.esp32-idf.yaml b/tests/components/pi4ioe5v6408/test.esp32-idf.yaml index 9a4779d822..a6eb3c1cb1 100644 --- a/tests/components/pi4ioe5v6408/test.esp32-idf.yaml +++ b/tests/components/pi4ioe5v6408/test.esp32-idf.yaml @@ -1,6 +1,7 @@ substitutions: i2c_sda: GPIO21 i2c_scl: GPIO22 + interrupt_pin: GPIO15 packages: i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml diff --git a/tests/components/pi4ioe5v6408/test.rp2040-ard.yaml b/tests/components/pi4ioe5v6408/test.rp2040-ard.yaml index 3429a2952a..cd6fef3042 100644 --- a/tests/components/pi4ioe5v6408/test.rp2040-ard.yaml +++ b/tests/components/pi4ioe5v6408/test.rp2040-ard.yaml @@ -1,6 +1,7 @@ substitutions: i2c_sda: GPIO4 i2c_scl: GPIO5 + interrupt_pin: GPIO2 packages: i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml From ae9068a4c43e6db15daa45092bb47613382ea6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Filistovi=C4=8D?= <efilistovic@gmail.com> Date: Sun, 5 Apr 2026 22:17:12 +0300 Subject: [PATCH 1941/2030] [internal_temperature] Add support for LN882X (Lightning LN882H) (#15370) Co-authored-by: Bl00d-B0b <Bl00d-B0b@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- .../internal_temperature_ln882x.cpp | 24 +++++++++++++++++++ .../components/internal_temperature/sensor.py | 14 ++++++++++- .../internal_temperature/test.ln882x-ard.yaml | 1 + 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 esphome/components/internal_temperature/internal_temperature_ln882x.cpp create mode 100644 tests/components/internal_temperature/test.ln882x-ard.yaml diff --git a/esphome/components/internal_temperature/internal_temperature_ln882x.cpp b/esphome/components/internal_temperature/internal_temperature_ln882x.cpp new file mode 100644 index 0000000000..621fbed030 --- /dev/null +++ b/esphome/components/internal_temperature/internal_temperature_ln882x.cpp @@ -0,0 +1,24 @@ +#ifdef USE_LN882X + +#include "internal_temperature.h" + +extern "C" { +uint16_t hal_adc_get_data(uint32_t adc_base, uint32_t ch); +} + +namespace esphome::internal_temperature { + +void InternalTemperatureSensor::update() { + static constexpr uint32_t ADC_BASE = 0x40000800U; + static constexpr uint32_t ADC_CH0 = 1U; + static constexpr uint16_t ADC_MASK = 0xFFF; + static constexpr float ADC_TEMP_SCALE = 2.54f; + static constexpr float ADC_TEMP_OFFSET = 278.15f; + uint16_t raw = hal_adc_get_data(ADC_BASE, ADC_CH0); + float temperature = (raw & ADC_MASK) / ADC_TEMP_SCALE - ADC_TEMP_OFFSET; + this->publish_state(temperature); +} + +} // namespace esphome::internal_temperature + +#endif // USE_LN882X diff --git a/esphome/components/internal_temperature/sensor.py b/esphome/components/internal_temperature/sensor.py index 6d79e08675..02730b6862 100644 --- a/esphome/components/internal_temperature/sensor.py +++ b/esphome/components/internal_temperature/sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( ENTITY_CATEGORY_DIAGNOSTIC, PLATFORM_BK72XX, PLATFORM_ESP32, + PLATFORM_LN882X, PLATFORM_NRF52, PLATFORM_RP2040, STATE_CLASS_MEASUREMENT, @@ -30,7 +31,15 @@ CONFIG_SCHEMA = cv.All( state_class=STATE_CLASS_MEASUREMENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ).extend(cv.polling_component_schema("60s")), - cv.only_on([PLATFORM_ESP32, PLATFORM_RP2040, PLATFORM_BK72XX, PLATFORM_NRF52]), + cv.only_on( + [ + PLATFORM_ESP32, + PLATFORM_RP2040, + PLATFORM_BK72XX, + PLATFORM_NRF52, + PLATFORM_LN882X, + ] + ), ) @@ -53,6 +62,9 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( "internal_temperature_bk72xx.cpp": { PlatformFramework.BK72XX_ARDUINO, }, + "internal_temperature_ln882x.cpp": { + PlatformFramework.LN882X_ARDUINO, + }, "internal_temperature_zephyr.cpp": {PlatformFramework.NRF52_ZEPHYR}, } ) diff --git a/tests/components/internal_temperature/test.ln882x-ard.yaml b/tests/components/internal_temperature/test.ln882x-ard.yaml new file mode 100644 index 0000000000..dade44d145 --- /dev/null +++ b/tests/components/internal_temperature/test.ln882x-ard.yaml @@ -0,0 +1 @@ +<<: !include common.yaml From c7a163441e2297c37b91c693c4a86713625a6296 Mon Sep 17 00:00:00 2001 From: Ross Tyler <rossetyler@gmail.com> Date: Sun, 5 Apr 2026 13:57:41 -0700 Subject: [PATCH 1942/2030] [ethernet] Add `interface` configuration variable for esp-idf (#10285) Co-authored-by: J. Nick Koston <nick@home-assistant.io> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/ethernet/__init__.py | 61 ++++++++++++------- .../components/ethernet/ethernet_component.h | 5 ++ .../ethernet/ethernet_component_esp32.cpp | 13 ++-- .../ethernet/test-w5500.esp32-idf.yaml | 21 ++++++- 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index 17459cabb6..d9f51c677e 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -104,6 +104,8 @@ CONF_CLK_MODE = "clk_mode" CONF_POWER_PIN = "power_pin" CONF_PHY_REGISTERS = "phy_registers" +CONF_INTERFACE = "interface" + CONF_CLOCK_SPEED = "clock_speed" EthernetType = ethernet_ns.enum("EthernetType") @@ -191,6 +193,13 @@ CLK_MODES_DEPRECATED = { "GPIO17_OUT": ("CLK_OUT", 17), } +spi_host_device_t = cg.global_ns.enum("spi_host_device_t") + +SPI_INTERFACE_MAP = { + "spi2": spi_host_device_t.SPI2_HOST, + "spi3": spi_host_device_t.SPI3_HOST, +} + MANUAL_IP_SCHEMA = cv.Schema( { cv.Required(CONF_STATIC_IP): cv.ipv4address, @@ -225,6 +234,24 @@ def _is_framework_spi_polling_mode_supported() -> bool: return False +def _validate_spi_interface(config: ConfigType) -> ConfigType: + """Set default SPI interface or validate user choice against the variant.""" + if not CORE.is_esp32: + return config + from esphome.components.esp32 import VARIANT_ESP32, get_esp32_variant + from esphome.components.spi import get_hw_interface_list + + has_spi3 = "spi3" in sum(get_hw_interface_list(), []) + if CONF_INTERFACE not in config: + # Only classic ESP32 defaults to spi3; all others default to spi2 + config[CONF_INTERFACE] = ( + "spi3" if get_esp32_variant() == VARIANT_ESP32 else "spi2" + ) + elif config[CONF_INTERFACE] == "spi3" and not has_spi3: + raise cv.Invalid("Interface 'spi3' is not available on this variant.") + return config + + def _validate(config): if CONF_USE_ADDRESS not in config: if CONF_MANUAL_IP in config: @@ -368,6 +395,10 @@ SPI_SCHEMA = cv.All( cv.frequency, cv.int_range(int(8e6), int(80e6)), ), + cv.Optional(CONF_INTERFACE): cv.All( + cv.only_on_esp32, + cv.one_of(*SPI_INTERFACE_MAP.keys(), lower=True), + ), # Set default value (SPI_ETHERNET_DEFAULT_POLLING_INTERVAL) at _validate() cv.Optional(CONF_POLLING_INTERVAL): cv.All( cv.only_on_esp32, @@ -378,6 +409,7 @@ SPI_SCHEMA = cv.All( ), ), cv.only_on([Platform.ESP32, Platform.RP2040]), + _validate_spi_interface, ) CONFIG_SCHEMA = cv.All( @@ -408,37 +440,18 @@ def _final_validate_spi(config): return # SPI interface validation is ESP32-only if config[CONF_TYPE] not in SPI_ETHERNET_TYPES: return - from esphome.components.esp32 import ( - VARIANT_ESP32C3, - VARIANT_ESP32C5, - VARIANT_ESP32C6, - VARIANT_ESP32C61, - VARIANT_ESP32S2, - VARIANT_ESP32S3, - get_esp32_variant, - ) from esphome.components.spi import CONF_INTERFACE_INDEX, get_spi_interface if spi_configs := fv.full_config.get().get(CONF_SPI): - variant = get_esp32_variant() - if variant in ( - VARIANT_ESP32C3, - VARIANT_ESP32C5, - VARIANT_ESP32C6, - VARIANT_ESP32C61, - VARIANT_ESP32S2, - VARIANT_ESP32S3, - ): - spi_host = "SPI2_HOST" - else: - spi_host = "SPI3_HOST" + # get_spi_interface() returns strings like "SPI2_HOST" + spi_host = f"{config[CONF_INTERFACE].upper()}_HOST" for spi_conf in spi_configs: if (index := spi_conf.get(CONF_INTERFACE_INDEX)) is not None: interface = get_spi_interface(index) if interface == spi_host: raise cv.Invalid( - f"`spi` component is using interface '{interface}'. " - f"To use {config[CONF_TYPE]}, you must change the `interface` on the `spi` component.", + f"The `ethernet` and `spi` components are both using interface '{interface}'. " + f"To use {config[CONF_TYPE]}, change the `interface` on either `ethernet:` or `spi:`." ) @@ -528,6 +541,8 @@ async def _to_code_esp32(var: cg.Pvariable, config: ConfigType) -> None: cg.add(var.set_clock_speed(config[CONF_CLOCK_SPEED])) cg.add_define("USE_ETHERNET_SPI") + + cg.add(var.set_interface(SPI_INTERFACE_MAP[config[CONF_INTERFACE]])) add_idf_sdkconfig_option("CONFIG_ETH_USE_SPI_ETHERNET", True) # CONFIG_ETH_SPI_ETHERNET_{TYPE} Kconfig options were removed in IDF 6.0 # ENC28J60 was never built-in to IDF, so it has no Kconfig option diff --git a/esphome/components/ethernet/ethernet_component.h b/esphome/components/ethernet/ethernet_component.h index c6e37d01ea..b760ba2af7 100644 --- a/esphome/components/ethernet/ethernet_component.h +++ b/esphome/components/ethernet/ethernet_component.h @@ -11,6 +11,9 @@ #ifdef USE_ESP32 #include "esp_eth.h" +#ifdef USE_ETHERNET_SPI +#include "hal/spi_types.h" +#endif #include "esp_eth_mac.h" #include "esp_eth_mac_esp.h" #include "esp_netif.h" @@ -135,6 +138,7 @@ class EthernetComponent final : public Component { void set_interrupt_pin(uint8_t interrupt_pin); void set_reset_pin(uint8_t reset_pin); void set_clock_speed(int clock_speed); + void set_interface(spi_host_device_t interface); #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT void set_polling_interval(uint32_t polling_interval); #endif @@ -201,6 +205,7 @@ class EthernetComponent final : public Component { int reset_pin_{-1}; int phy_addr_spi_{-1}; int clock_speed_; + spi_host_device_t interface_{SPI3_HOST}; #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT uint32_t polling_interval_{0}; #endif diff --git a/esphome/components/ethernet/ethernet_component_esp32.cpp b/esphome/components/ethernet/ethernet_component_esp32.cpp index a170239e03..d4585bf100 100644 --- a/esphome/components/ethernet/ethernet_component_esp32.cpp +++ b/esphome/components/ethernet/ethernet_component_esp32.cpp @@ -158,12 +158,7 @@ void EthernetComponent::setup() { .intr_flags = 0, }; -#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32C5) || defined(USE_ESP32_VARIANT_ESP32C6) || \ - defined(USE_ESP32_VARIANT_ESP32C61) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3) - auto host = SPI2_HOST; -#else - auto host = SPI3_HOST; -#endif + auto host = this->interface_; err = spi_bus_initialize(host, &buscfg, SPI_DMA_CH_AUTO); ESPHL_ERROR_CHECK(err, "SPI bus initialize error"); @@ -458,6 +453,11 @@ void EthernetComponent::dump_config() { " MOSI Pin: %u\n" " CS Pin: %u", this->clk_pin_, this->miso_pin_, this->mosi_pin_, this->cs_pin_); + const char *spi_interface = "spi3"; + if (this->interface_ == SPI2_HOST) { + spi_interface = "spi2"; + } + ESP_LOGCONFIG(TAG, " Interface: %s", spi_interface); #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT if (this->polling_interval_ != 0) { ESP_LOGCONFIG(TAG, " Polling Interval: %" PRIu32 " ms", this->polling_interval_); @@ -760,6 +760,7 @@ void EthernetComponent::set_cs_pin(uint8_t cs_pin) { this->cs_pin_ = cs_pin; } void EthernetComponent::set_interrupt_pin(uint8_t interrupt_pin) { this->interrupt_pin_ = interrupt_pin; } void EthernetComponent::set_reset_pin(uint8_t reset_pin) { this->reset_pin_ = reset_pin; } void EthernetComponent::set_clock_speed(int clock_speed) { this->clock_speed_ = clock_speed; } +void EthernetComponent::set_interface(spi_host_device_t interface) { this->interface_ = interface; } #ifdef USE_ETHERNET_SPI_POLLING_SUPPORT void EthernetComponent::set_polling_interval(uint32_t polling_interval) { this->polling_interval_ = polling_interval; } #endif diff --git a/tests/components/ethernet/test-w5500.esp32-idf.yaml b/tests/components/ethernet/test-w5500.esp32-idf.yaml index 36f1b5365f..f1551fef60 100644 --- a/tests/components/ethernet/test-w5500.esp32-idf.yaml +++ b/tests/components/ethernet/test-w5500.esp32-idf.yaml @@ -1 +1,20 @@ -<<: !include common-w5500.yaml +ethernet: + type: W5500 + clk_pin: 19 + mosi_pin: 21 + miso_pin: 23 + cs_pin: 18 + interrupt_pin: 36 + reset_pin: 22 + clock_speed: 10Mhz + manual_ip: + static_ip: 192.168.178.56 + gateway: 192.168.178.1 + subnet: 255.255.255.0 + domain: .local + mac_address: "02:AA:BB:CC:DD:01" + interface: spi2 + on_connect: + - logger.log: "Ethernet connected!" + on_disconnect: + - logger.log: "Ethernet disconnected!" From f23843130e79f0d4149c3fbf8c9d994211a34705 Mon Sep 17 00:00:00 2001 From: Andrew Rankin <andrew@eiknet.com> Date: Sun, 5 Apr 2026 19:07:42 -0400 Subject: [PATCH 1943/2030] [lvgl] option to enable LVGL's built-in dark theme (#15389) --- esphome/components/lvgl/__init__.py | 10 ++++++++-- esphome/components/lvgl/defines.py | 1 + esphome/components/lvgl/hello_world.yaml | 2 +- esphome/components/lvgl/styles.py | 4 ++-- tests/components/lvgl/lvgl-package.yaml | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index 3b4f150699..a9d31d42d8 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -392,6 +392,9 @@ async def to_code(configs): } & styles_used: df.add_define("LV_COLOR_SCREEN_TRANSP", "1") + if configs[0].get(df.CONF_THEME, {}).get(df.CONF_DARK_MODE): + df.add_define("LV_THEME_DEFAULT_DARK", "1") + # Currently always need RGB565 for the display buffer, and ARGB8888 is used for layer blending lv_image_formats = {"RGB565", "ARGB8888"} if { @@ -459,8 +462,11 @@ def add_hello_world(config): def _theme_schema(value): return cv.Schema( { - cv.Optional(name): obj_schema(w).extend(FULL_STYLE_SCHEMA) - for name, w in WIDGET_TYPES.items() + cv.Optional(df.CONF_DARK_MODE, default=False): cv.boolean, + **{ + cv.Optional(name): obj_schema(w).extend(FULL_STYLE_SCHEMA) + for name, w in WIDGET_TYPES.items() + }, } )(value) diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 500ccb608a..668bb46515 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -598,6 +598,7 @@ CONF_FLEX_ALIGN_CROSS = "flex_align_cross" CONF_FLEX_ALIGN_TRACK = "flex_align_track" CONF_FLEX_GROW = "flex_grow" CONF_FREEZE = "freeze" +CONF_DARK_MODE = "dark_mode" CONF_FULL_REFRESH = "full_refresh" CONF_GRADIENTS = "gradients" CONF_GRID_CELL_ROW_POS = "grid_cell_row_pos" diff --git a/esphome/components/lvgl/hello_world.yaml b/esphome/components/lvgl/hello_world.yaml index 4af179a589..bbbd34e30a 100644 --- a/esphome/components/lvgl/hello_world.yaml +++ b/esphome/components/lvgl/hello_world.yaml @@ -3,7 +3,7 @@ - obj: id: hello_world_card_ pad_all: 12 - bg_color: white + bg_opa: cover height: 100% width: 100% scrollable: false diff --git a/esphome/components/lvgl/styles.py b/esphome/components/lvgl/styles.py index 793290de73..c17f30383b 100644 --- a/esphome/components/lvgl/styles.py +++ b/esphome/components/lvgl/styles.py @@ -7,7 +7,7 @@ from esphome.core import ID from .defines import CONF_STYLE_DEFINITIONS, CONF_THEME, LValidator, literal from .helpers import add_lv_use from .lvcode import LambdaContext, lv -from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, remap_property +from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, WIDGET_TYPES, remap_property from .types import ObjUpdateAction, lv_style_t from .widgets import collect_parts, theme_widget_map, wait_for_widgets @@ -85,7 +85,7 @@ async def style_update_to_code(config, action_id, template_arg, args): async def theme_to_code(config): if theme := config.get(CONF_THEME): add_lv_use(CONF_THEME) - for w_name, style in theme.items(): + for w_name, style in ((k, v) for k, v in theme.items() if k in WIDGET_TYPES): # Work around Python 3.10 bug with nested async comprehensions # With Python 3.11 this could be simplified # TODO: Now that we require Python 3.11+, this can be updated to use nested comprehensions diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 3a6af93b64..3c5c730e6c 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -49,6 +49,7 @@ lvgl: bg_color: 0x000000 bg_opa: cover theme: + dark_mode: true obj: border_width: 1 From f01762ea44a8b57488e080d2a52bdc05b4af484f Mon Sep 17 00:00:00 2001 From: Tomer27cz <85194189+Tomer27cz@users.noreply.github.com> Date: Mon, 6 Apr 2026 01:17:52 +0200 Subject: [PATCH 1944/2030] [ci] move import to function (#15440) --- script/helpers.py | 4 +--- tests/script/test_helpers.py | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/script/helpers.py b/script/helpers.py index 290dcadf0b..c9c550d889 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -15,8 +15,6 @@ from typing import Any import colorama -from esphome.loader import get_platform - root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, "..", ".."))) basepath = os.path.join(root_path, "esphome") temp_folder = os.path.join(root_path, ".temp") @@ -644,7 +642,7 @@ def get_all_dependencies( PLATFORM_HOST, ) from esphome.core import CORE - from esphome.loader import get_component + from esphome.loader import get_component, get_platform all_components: set[str] = set(component_names) diff --git a/tests/script/test_helpers.py b/tests/script/test_helpers.py index 28f111d758..948aabaa66 100644 --- a/tests/script/test_helpers.py +++ b/tests/script/test_helpers.py @@ -1037,7 +1037,7 @@ def test_get_all_dependencies_platform_component() -> None: with ( patch("esphome.loader.get_component") as mock_get_component, - patch("helpers.get_platform") as mock_get_platform, + patch("esphome.loader.get_platform") as mock_get_platform, ): mock_get_platform.return_value = platform_comp mock_get_component.return_value = None @@ -1061,7 +1061,7 @@ def test_get_all_dependencies_platform_component_with_dependencies() -> None: with ( patch("esphome.loader.get_component") as mock_get_component, - patch("helpers.get_platform") as mock_get_platform, + patch("esphome.loader.get_platform") as mock_get_platform, ): mock_get_platform.return_value = platform_comp mock_get_component.side_effect = lambda name: ( From f193bab60b17a981f1e2648c9768daa4fe806a34 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:25:50 -1000 Subject: [PATCH 1945/2030] [api] Add ListEntities benchmarks for sensor, binary_sensor, and light (#15427) --- .../components/api/bench_list_entities.cpp | 235 ++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 tests/benchmarks/components/api/bench_list_entities.cpp diff --git a/tests/benchmarks/components/api/bench_list_entities.cpp b/tests/benchmarks/components/api/bench_list_entities.cpp new file mode 100644 index 0000000000..02cef50d70 --- /dev/null +++ b/tests/benchmarks/components/api/bench_list_entities.cpp @@ -0,0 +1,235 @@ +#include <benchmark/benchmark.h> + +#include "esphome/components/api/api_pb2.h" +#include "esphome/components/api/api_buffer.h" +#include "esphome/components/light/color_mode.h" + +namespace esphome::api::benchmarks { + +static constexpr int kInnerIterations = 2000; + +// --- ListEntitiesSensorResponse --- + +static ListEntitiesSensorResponse make_sensor_response() { + ListEntitiesSensorResponse msg; + msg.object_id = StringRef::from_lit("living_room_temperature"); + msg.key = 0x12345678; + msg.name = StringRef::from_lit("Living Room Temperature"); +#ifdef USE_ENTITY_ICON + msg.icon = StringRef::from_lit("mdi:thermometer"); +#endif + msg.entity_category = enums::ENTITY_CATEGORY_NONE; + msg.disabled_by_default = false; + msg.unit_of_measurement = StringRef::from_lit("°C"); + msg.accuracy_decimals = 1; + msg.force_update = false; + msg.device_class = StringRef::from_lit("temperature"); + msg.state_class = enums::STATE_CLASS_MEASUREMENT; +#ifdef USE_DEVICES + msg.device_id = 1; +#endif + return msg; +} + +static void CalculateSize_ListEntitiesSensorResponse(benchmark::State &state) { + auto msg = make_sensor_response(); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_ListEntitiesSensorResponse); + +static void Encode_ListEntitiesSensorResponse(benchmark::State &state) { + auto msg = make_sensor_response(); + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_ListEntitiesSensorResponse); + +static void CalcAndEncode_ListEntitiesSensorResponse(benchmark::State &state) { + auto msg = make_sensor_response(); + APIBuffer buffer; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_ListEntitiesSensorResponse); + +// --- ListEntitiesBinarySensorResponse --- + +static ListEntitiesBinarySensorResponse make_binary_sensor_response() { + ListEntitiesBinarySensorResponse msg; + msg.object_id = StringRef::from_lit("front_door_contact"); + msg.key = 0xAABBCCDD; + msg.name = StringRef::from_lit("Front Door Contact"); +#ifdef USE_ENTITY_ICON + msg.icon = StringRef::from_lit("mdi:door"); +#endif + msg.entity_category = enums::ENTITY_CATEGORY_NONE; + msg.disabled_by_default = false; + msg.device_class = StringRef::from_lit("door"); + msg.is_status_binary_sensor = false; +#ifdef USE_DEVICES + msg.device_id = 2; +#endif + return msg; +} + +static void CalculateSize_ListEntitiesBinarySensorResponse(benchmark::State &state) { + auto msg = make_binary_sensor_response(); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_ListEntitiesBinarySensorResponse); + +static void Encode_ListEntitiesBinarySensorResponse(benchmark::State &state) { + auto msg = make_binary_sensor_response(); + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_ListEntitiesBinarySensorResponse); + +static void CalcAndEncode_ListEntitiesBinarySensorResponse(benchmark::State &state) { + auto msg = make_binary_sensor_response(); + APIBuffer buffer; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_ListEntitiesBinarySensorResponse); + +// --- ListEntitiesLightResponse --- + +static light::ColorModeMask light_color_modes; +static FixedVector<const char *> light_effects; + +static ListEntitiesLightResponse make_light_response() { + // Initialize static data on first call + static bool initialized = false; + if (!initialized) { + light_color_modes.insert(light::ColorMode::RGB_WHITE); + light_color_modes.insert(light::ColorMode::COLOR_TEMPERATURE); + light_effects.init(3); + light_effects.push_back("None"); + light_effects.push_back("Rainbow"); + light_effects.push_back("Strobe"); + initialized = true; + } + + ListEntitiesLightResponse msg; + msg.object_id = StringRef::from_lit("kitchen_ceiling_light"); + msg.key = 0x55667788; + msg.name = StringRef::from_lit("Kitchen Ceiling Light"); +#ifdef USE_ENTITY_ICON + msg.icon = StringRef::from_lit("mdi:ceiling-light"); +#endif + msg.entity_category = enums::ENTITY_CATEGORY_NONE; + msg.disabled_by_default = false; + msg.supported_color_modes = &light_color_modes; + msg.min_mireds = 153.0f; + msg.max_mireds = 500.0f; + msg.effects = &light_effects; +#ifdef USE_DEVICES + msg.device_id = 3; +#endif + return msg; +} + +static void CalculateSize_ListEntitiesLightResponse(benchmark::State &state) { + auto msg = make_light_response(); + + for (auto _ : state) { + uint32_t result = 0; + for (int i = 0; i < kInnerIterations; i++) { + result += msg.calculate_size(); + } + benchmark::DoNotOptimize(result); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalculateSize_ListEntitiesLightResponse); + +static void Encode_ListEntitiesLightResponse(benchmark::State &state) { + auto msg = make_light_response(); + APIBuffer buffer; + uint32_t size = msg.calculate_size(); + buffer.resize(size); + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(Encode_ListEntitiesLightResponse); + +static void CalcAndEncode_ListEntitiesLightResponse(benchmark::State &state) { + auto msg = make_light_response(); + APIBuffer buffer; + + for (auto _ : state) { + for (int i = 0; i < kInnerIterations; i++) { + uint32_t size = msg.calculate_size(); + buffer.resize(size); + ProtoWriteBuffer writer(&buffer, 0); + msg.encode(writer); + } + benchmark::DoNotOptimize(buffer.data()); + } + state.SetItemsProcessed(state.iterations() * kInnerIterations); +} +BENCHMARK(CalcAndEncode_ListEntitiesLightResponse); + +} // namespace esphome::api::benchmarks From 83a4edbea14c4f854d3d30ab3423ae6975f8747f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:26:08 -1000 Subject: [PATCH 1946/2030] [select] [switch] Downgrade control path logging from DEBUG to VERBOSE (#15406) --- esphome/components/select/select_call.cpp | 2 +- esphome/components/switch/switch.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/select/select_call.cpp b/esphome/components/select/select_call.cpp index 0e14371d00..9d2fb725f3 100644 --- a/esphome/components/select/select_call.cpp +++ b/esphome/components/select/select_call.cpp @@ -116,7 +116,7 @@ void SelectCall::perform() { auto idx = target_index.value(); // All operations use indices, call control() by index to avoid string conversion - ESP_LOGD(TAG, "'%s' - Set selected option to: %s", name, parent->option_at(idx)); + ESP_LOGV(TAG, "'%s' - Set selected option to: %s", name, parent->option_at(idx)); parent->control(idx); } diff --git a/esphome/components/switch/switch.cpp b/esphome/components/switch/switch.cpp index 11840db3a3..abc7338a62 100644 --- a/esphome/components/switch/switch.cpp +++ b/esphome/components/switch/switch.cpp @@ -18,15 +18,15 @@ void Switch::control(bool target_state) { } } void Switch::turn_on() { - ESP_LOGD(TAG, "'%s' Turning ON.", this->get_name().c_str()); + ESP_LOGV(TAG, "'%s' Turning ON.", this->get_name().c_str()); this->write_state(!this->inverted_); } void Switch::turn_off() { - ESP_LOGD(TAG, "'%s' Turning OFF.", this->get_name().c_str()); + ESP_LOGV(TAG, "'%s' Turning OFF.", this->get_name().c_str()); this->write_state(this->inverted_); } void Switch::toggle() { - ESP_LOGD(TAG, "'%s' Toggling %s.", this->get_name().c_str(), this->state ? "OFF" : "ON"); + ESP_LOGV(TAG, "'%s' Toggling %s.", this->get_name().c_str(), this->state ? "OFF" : "ON"); this->write_state(this->inverted_ == this->state); } optional<bool> Switch::get_initial_state() { From 30d1230a174df2d4220ddce7b5dc47185202bced Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:26:21 -1000 Subject: [PATCH 1947/2030] [button] Downgrade press logging from DEBUG to VERBOSE (#15408) --- esphome/components/button/button.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/button/button.cpp b/esphome/components/button/button.cpp index b1c491805e..2a2a645132 100644 --- a/esphome/components/button/button.cpp +++ b/esphome/components/button/button.cpp @@ -16,7 +16,7 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o } void Button::press() { - ESP_LOGD(TAG, "'%s' Pressed.", this->get_name().c_str()); + ESP_LOGV(TAG, "'%s' Pressed.", this->get_name().c_str()); this->press_action(); this->press_callback_.call(); } From 0f2d8656adc64ece1e0f2e3ebcc85a66320e322d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:26:40 -1000 Subject: [PATCH 1948/2030] [esp32_ble] Skip dropped count memw when queue is empty (#15422) --- esphome/components/esp32_ble/ble.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 2cd2ec67f7..68e5fffe2b 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -399,8 +399,17 @@ void ESP32BLE::loop() { return; } +#ifdef USE_ESP32_BLE_ADVERTISING + if (this->advertising_ != nullptr) { + this->advertising_->loop(); + } +#endif + BLEEvent *ble_event = this->ble_events_.pop(); - while (ble_event != nullptr) { + if (ble_event == nullptr) + return; + + do { switch (ble_event->type_) { #if defined(USE_ESP32_BLE_SERVER) && defined(ESPHOME_ESP32_BLE_GATTS_EVENT_HANDLER_COUNT) case BLEEvent::GATTS: { @@ -488,15 +497,11 @@ void ESP32BLE::loop() { } // Return the event to the pool this->ble_event_pool_.release(ble_event); - ble_event = this->ble_events_.pop(); - } -#ifdef USE_ESP32_BLE_ADVERTISING - if (this->advertising_ != nullptr) { - this->advertising_->loop(); - } -#endif + } while ((ble_event = this->ble_events_.pop()) != nullptr); - // Log dropped events periodically + // Log dropped events - only reachable when events were processed. + // Drops only occur when the queue is full, and only this loop drains it, + // so if pop() returned nullptr above we can skip this check (saves a memw). uint16_t dropped = this->ble_events_.get_and_reset_dropped_count(); if (dropped > 0) { ESP_LOGW(TAG, "Dropped %u BLE events due to buffer overflow", dropped); From 155657f1ccda9d6529ce07a4ffb41996e3641f7a Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:26:55 -1000 Subject: [PATCH 1949/2030] [mcp23xxx][pi4ioe5v6408] Disable loop when all pins are outputs (#15460) --- esphome/components/mcp23x08_base/mcp23x08_base.cpp | 5 +++++ esphome/components/mcp23x17_base/mcp23x17_base.cpp | 5 +++++ esphome/components/mcp23xxx_base/mcp23xxx_base.h | 5 ++++- esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp | 10 +++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/esphome/components/mcp23x08_base/mcp23x08_base.cpp b/esphome/components/mcp23x08_base/mcp23x08_base.cpp index e4f4d50aae..197b739204 100644 --- a/esphome/components/mcp23x08_base/mcp23x08_base.cpp +++ b/esphome/components/mcp23x08_base/mcp23x08_base.cpp @@ -37,6 +37,11 @@ void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) { if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr && (flags & gpio::FLAG_INPUT)) { + this->enable_loop(); + } } void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23x17_base/mcp23x17_base.cpp b/esphome/components/mcp23x17_base/mcp23x17_base.cpp index 42613053de..efed7f5f17 100644 --- a/esphome/components/mcp23x17_base/mcp23x17_base.cpp +++ b/esphome/components/mcp23x17_base/mcp23x17_base.cpp @@ -49,6 +49,11 @@ void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) { if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) { this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE); } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr && (flags & gpio::FLAG_INPUT)) { + this->enable_loop(); + } } void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) { diff --git a/esphome/components/mcp23xxx_base/mcp23xxx_base.h b/esphome/components/mcp23xxx_base/mcp23xxx_base.h index e77eac87e7..6efd04e246 100644 --- a/esphome/components/mcp23xxx_base/mcp23xxx_base.h +++ b/esphome/components/mcp23xxx_base/mcp23xxx_base.h @@ -35,8 +35,11 @@ template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander: this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&MCP23XXXBase::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); this->set_invalidate_on_read_(false); - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } static void IRAM_ATTR gpio_intr(MCP23XXXBase *arg) { arg->enable_loop_soon_any_context(); } diff --git a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp index 8e38e7fa1d..6e8631022a 100644 --- a/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp +++ b/esphome/components/pi4ioe5v6408/pi4ioe5v6408.cpp @@ -41,8 +41,11 @@ void PI4IOE5V6408Component::setup() { this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&PI4IOE5V6408Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); this->set_invalidate_on_read_(false); - this->disable_loop(); } + // Disable loop until an input pin is configured via pin_mode() + // For interrupt-driven mode, loop is re-enabled by the ISR + // For polling mode, loop is re-enabled when pin_mode() registers an input pin + this->disable_loop(); } void IRAM_ATTR PI4IOE5V6408Component::gpio_intr(PI4IOE5V6408Component *arg) { arg->enable_loop_soon_any_context(); } void PI4IOE5V6408Component::dump_config() { @@ -67,6 +70,11 @@ void PI4IOE5V6408Component::pin_mode(uint8_t pin, gpio::Flags flags) { this->pull_up_down_mask_ &= ~(1 << pin); this->pull_enable_mask_ |= 1 << pin; } + // Enable polling loop for input pins (not needed for interrupt-driven mode + // where the ISR handles re-enabling loop) + if (this->interrupt_pin_ == nullptr) { + this->enable_loop(); + } } // Write GPIO to enable input mode this->write_gpio_modes_(); From ea0ce710a8cf5d93a364826f6581f10e7e8c5d5e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 13:55:06 -1000 Subject: [PATCH 1950/2030] [api] Split Noise handshake state_action_ to reduce stack pressure (#15464) --- .../components/api/api_frame_helper_noise.cpp | 250 +++++++++--------- .../components/api/api_frame_helper_noise.h | 5 + 2 files changed, 136 insertions(+), 119 deletions(-) diff --git a/esphome/components/api/api_frame_helper_noise.cpp b/esphome/components/api/api_frame_helper_noise.cpp index 78e87793fc..162f4ef605 100644 --- a/esphome/components/api/api_frame_helper_noise.cpp +++ b/esphome/components/api/api_frame_helper_noise.cpp @@ -244,132 +244,144 @@ APIError APINoiseFrameHelper::try_read_frame_() { * If an error occurred, returns that error. Only returns OK if the transport is ready for data * traffic. */ +// Split into per-state methods so the compiler doesn't allocate stack space +// for all branches simultaneously. On RP2040 the core0 stack lives in a 4KB +// scratch RAM bank; the Noise crypto path (curve25519) needs ~2KB+ of stack, +// so every byte saved in the caller matters. APIError APINoiseFrameHelper::state_action_() { - int err; - APIError aerr; - if (state_ == State::INITIALIZE) { - HELPER_LOG("Bad state for method: %d", (int) state_); - return APIError::BAD_STATE; + switch (this->state_) { + case State::INITIALIZE: + HELPER_LOG("Bad state for method: %d", (int) this->state_); + return APIError::BAD_STATE; + case State::CLIENT_HELLO: + return this->state_action_client_hello_(); + case State::SERVER_HELLO: + return this->state_action_server_hello_(); + case State::HANDSHAKE: + return this->state_action_handshake_(); + case State::CLOSED: + case State::FAILED: + return APIError::BAD_STATE; + default: + return APIError::OK; } - if (state_ == State::CLIENT_HELLO) { - // waiting for client hello - aerr = this->try_read_frame_(); - if (aerr != APIError::OK) { - return handle_handshake_frame_error_(aerr); - } - // ignore contents, may be used in future for flags - // Resize for: existing prologue + 2 size bytes + frame data - size_t old_size = this->prologue_.size(); - size_t rx_size = this->rx_buf_.size(); - this->prologue_.resize(old_size + 2 + rx_size); - this->prologue_[old_size] = (uint8_t) (rx_size >> 8); - this->prologue_[old_size + 1] = (uint8_t) rx_size; - if (rx_size > 0) { - std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), rx_size); - } - - state_ = State::SERVER_HELLO; +} +APIError APINoiseFrameHelper::state_action_client_hello_() { + // waiting for client hello + APIError aerr = this->try_read_frame_(); + if (aerr != APIError::OK) { + return handle_handshake_frame_error_(aerr); } - if (state_ == State::SERVER_HELLO) { - // send server hello - const auto &name = App.get_name(); - char mac[MAC_ADDRESS_BUFFER_SIZE]; - get_mac_address_into_buffer(mac); - - // Calculate positions and sizes - size_t name_len = name.size() + 1; // including null terminator - size_t name_offset = 1; - size_t mac_offset = name_offset + name_len; - size_t total_size = 1 + name_len + MAC_ADDRESS_BUFFER_SIZE; - - // 1 (proto) + name (max ESPHOME_DEVICE_NAME_MAX_LEN) + 1 (name null) - // + mac (MAC_ADDRESS_BUFFER_SIZE - 1) + 1 (mac null) - constexpr size_t max_msg_size = 1 + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + MAC_ADDRESS_BUFFER_SIZE; - uint8_t msg[max_msg_size]; - - // chosen proto - msg[0] = 0x01; - - // node name, terminated by null byte - std::memcpy(msg + name_offset, name.c_str(), name_len); - // node mac, terminated by null byte - std::memcpy(msg + mac_offset, mac, MAC_ADDRESS_BUFFER_SIZE); - - aerr = write_frame_(msg, total_size); - if (aerr != APIError::OK) - return aerr; - - // start handshake - aerr = init_handshake_(); - if (aerr != APIError::OK) - return aerr; - - state_ = State::HANDSHAKE; + // ignore contents, may be used in future for flags + // Resize for: existing prologue + 2 size bytes + frame data + size_t old_size = this->prologue_.size(); + size_t rx_size = this->rx_buf_.size(); + this->prologue_.resize(old_size + 2 + rx_size); + this->prologue_[old_size] = (uint8_t) (rx_size >> 8); + this->prologue_[old_size + 1] = (uint8_t) rx_size; + if (rx_size > 0) { + std::memcpy(this->prologue_.data() + old_size + 2, this->rx_buf_.data(), rx_size); } - if (state_ == State::HANDSHAKE) { - int action = noise_handshakestate_get_action(handshake_); - if (action == NOISE_ACTION_READ_MESSAGE) { - // waiting for handshake msg - aerr = this->try_read_frame_(); - if (aerr != APIError::OK) { - return handle_handshake_frame_error_(aerr); - } - if (this->rx_buf_.empty()) { - send_explicit_handshake_reject_(LOG_STR("Empty handshake message")); - return APIError::BAD_HANDSHAKE_ERROR_BYTE; - } else if (this->rx_buf_[0] != 0x00) { - HELPER_LOG("Bad handshake error byte: %u", this->rx_buf_[0]); - send_explicit_handshake_reject_(LOG_STR("Bad handshake error byte")); - return APIError::BAD_HANDSHAKE_ERROR_BYTE; - } - - NoiseBuffer mbuf; - noise_buffer_init(mbuf); - noise_buffer_set_input(mbuf, this->rx_buf_.data() + 1, this->rx_buf_.size() - 1); - err = noise_handshakestate_read_message(handshake_, &mbuf, nullptr); - if (err != 0) { - // Special handling for MAC failure - send_explicit_handshake_reject_(err == NOISE_ERROR_MAC_FAILURE ? LOG_STR("Handshake MAC failure") - : LOG_STR("Handshake error")); - return handle_noise_error_(err, LOG_STR("noise_handshakestate_read_message"), - APIError::HANDSHAKESTATE_READ_FAILED); - } - - aerr = check_handshake_finished_(); - if (aerr != APIError::OK) - return aerr; - } else if (action == NOISE_ACTION_WRITE_MESSAGE) { - uint8_t buffer[65]; - NoiseBuffer mbuf; - noise_buffer_init(mbuf); - noise_buffer_set_output(mbuf, buffer + 1, sizeof(buffer) - 1); - - err = noise_handshakestate_write_message(handshake_, &mbuf, nullptr); - APIError aerr_write = handle_noise_error_(err, LOG_STR("noise_handshakestate_write_message"), - APIError::HANDSHAKESTATE_WRITE_FAILED); - if (aerr_write != APIError::OK) - return aerr_write; - buffer[0] = 0x00; // success - - aerr = write_frame_(buffer, mbuf.size + 1); - if (aerr != APIError::OK) - return aerr; - aerr = check_handshake_finished_(); - if (aerr != APIError::OK) - return aerr; - } else { - // bad state for action - state_ = State::FAILED; - HELPER_LOG("Bad action for handshake: %d", action); - return APIError::HANDSHAKESTATE_BAD_STATE; - } - } - if (state_ == State::CLOSED || state_ == State::FAILED) { - return APIError::BAD_STATE; - } + state_ = State::SERVER_HELLO; return APIError::OK; } +APIError APINoiseFrameHelper::state_action_server_hello_() { + // send server hello + const auto &name = App.get_name(); + char mac[MAC_ADDRESS_BUFFER_SIZE]; + get_mac_address_into_buffer(mac); + + // Calculate positions and sizes + size_t name_len = name.size() + 1; // including null terminator + size_t name_offset = 1; + size_t mac_offset = name_offset + name_len; + size_t total_size = 1 + name_len + MAC_ADDRESS_BUFFER_SIZE; + + // 1 (proto) + name (max ESPHOME_DEVICE_NAME_MAX_LEN) + 1 (name null) + // + mac (MAC_ADDRESS_BUFFER_SIZE - 1) + 1 (mac null) + constexpr size_t max_msg_size = 1 + ESPHOME_DEVICE_NAME_MAX_LEN + 1 + MAC_ADDRESS_BUFFER_SIZE; + uint8_t msg[max_msg_size]; + + // chosen proto + msg[0] = 0x01; + + // node name, terminated by null byte + std::memcpy(msg + name_offset, name.c_str(), name_len); + // node mac, terminated by null byte + std::memcpy(msg + mac_offset, mac, MAC_ADDRESS_BUFFER_SIZE); + + APIError aerr = write_frame_(msg, total_size); + if (aerr != APIError::OK) + return aerr; + + // start handshake + aerr = init_handshake_(); + if (aerr != APIError::OK) + return aerr; + + state_ = State::HANDSHAKE; + return APIError::OK; +} +APIError APINoiseFrameHelper::state_action_handshake_() { + int action = noise_handshakestate_get_action(this->handshake_); + if (action == NOISE_ACTION_READ_MESSAGE) { + return this->state_action_handshake_read_(); + } else if (action == NOISE_ACTION_WRITE_MESSAGE) { + return this->state_action_handshake_write_(); + } + // bad state for action + this->state_ = State::FAILED; + HELPER_LOG("Bad action for handshake: %d", action); + return APIError::HANDSHAKESTATE_BAD_STATE; +} +APIError APINoiseFrameHelper::state_action_handshake_read_() { + APIError aerr = this->try_read_frame_(); + if (aerr != APIError::OK) { + return this->handle_handshake_frame_error_(aerr); + } + + if (this->rx_buf_.empty()) { + this->send_explicit_handshake_reject_(LOG_STR("Empty handshake message")); + return APIError::BAD_HANDSHAKE_ERROR_BYTE; + } else if (this->rx_buf_[0] != 0x00) { + HELPER_LOG("Bad handshake error byte: %u", this->rx_buf_[0]); + this->send_explicit_handshake_reject_(LOG_STR("Bad handshake error byte")); + return APIError::BAD_HANDSHAKE_ERROR_BYTE; + } + + NoiseBuffer mbuf; + noise_buffer_init(mbuf); + noise_buffer_set_input(mbuf, this->rx_buf_.data() + 1, this->rx_buf_.size() - 1); + int err = noise_handshakestate_read_message(this->handshake_, &mbuf, nullptr); + if (err != 0) { + // Special handling for MAC failure + this->send_explicit_handshake_reject_(err == NOISE_ERROR_MAC_FAILURE ? LOG_STR("Handshake MAC failure") + : LOG_STR("Handshake error")); + return this->handle_noise_error_(err, LOG_STR("noise_handshakestate_read_message"), + APIError::HANDSHAKESTATE_READ_FAILED); + } + + return this->check_handshake_finished_(); +} +APIError APINoiseFrameHelper::state_action_handshake_write_() { + uint8_t buffer[65]; + NoiseBuffer mbuf; + noise_buffer_init(mbuf); + noise_buffer_set_output(mbuf, buffer + 1, sizeof(buffer) - 1); + + int err = noise_handshakestate_write_message(this->handshake_, &mbuf, nullptr); + APIError aerr = this->handle_noise_error_(err, LOG_STR("noise_handshakestate_write_message"), + APIError::HANDSHAKESTATE_WRITE_FAILED); + if (aerr != APIError::OK) + return aerr; + buffer[0] = 0x00; // success + + aerr = this->write_frame_(buffer, mbuf.size + 1); + if (aerr != APIError::OK) + return aerr; + return this->check_handshake_finished_(); +} void APINoiseFrameHelper::send_explicit_handshake_reject_(const LogString *reason) { // Max reject message: "Bad handshake packet len" (24) + 1 (failure byte) = 25 bytes uint8_t data[32]; diff --git a/esphome/components/api/api_frame_helper_noise.h b/esphome/components/api/api_frame_helper_noise.h index a6b17ff3b9..f44bde0755 100644 --- a/esphome/components/api/api_frame_helper_noise.h +++ b/esphome/components/api/api_frame_helper_noise.h @@ -26,6 +26,11 @@ class APINoiseFrameHelper final : public APIFrameHelper { protected: APIError state_action_(); + APIError state_action_client_hello_(); + APIError state_action_server_hello_(); + APIError state_action_handshake_(); + APIError state_action_handshake_read_(); + APIError state_action_handshake_write_(); APIError try_read_frame_(); APIError write_frame_(const uint8_t *data, uint16_t len); APIError init_handshake_(); From 07f6be679fcfe4edf700b496de86803cce219227 Mon Sep 17 00:00:00 2001 From: Keith Burzinski <kbx81x@gmail.com> Date: Sun, 5 Apr 2026 21:20:48 -0500 Subject: [PATCH 1951/2030] [esp32] Add signed app verification without hardware secure boot (#15357) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --- esphome/components/esp32/__init__.py | 104 ++++++++++++++++++ esphome/components/esp32/post_build.py.script | 96 +++++++++++++++- esphome/components/ota/ota_backend.h | 1 + .../components/ota/ota_backend_esp_idf.cpp | 8 ++ esphome/core/defines.h | 1 + esphome/espota2.py | 8 ++ tests/components/esp32/dummy_signing_key.pem | 41 +++++++ .../esp32/test-signed_ota.esp32-s3-idf.yaml | 10 ++ 8 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 tests/components/esp32/dummy_signing_key.pem create mode 100644 tests/components/esp32/test-signed_ota.esp32-s3-idf.yaml diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 5cae67db13..0d8a221524 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -97,8 +97,12 @@ CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_EXECUTE_FROM_PSRAM = "execute_from_psram" CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision" CONF_RELEASE = "release" +CONF_SIGNED_OTA_VERIFICATION = "signed_ota_verification" +CONF_SIGNING_KEY = "signing_key" +CONF_SIGNING_SCHEME = "signing_scheme" CONF_SRAM1_AS_IRAM = "sram1_as_iram" CONF_SUBTYPE = "subtype" +CONF_VERIFICATION_KEY = "verification_key" ARDUINO_FRAMEWORK_NAME = "framework-arduinoespressif32" ARDUINO_FRAMEWORK_PKG = f"pioarduino/{ARDUINO_FRAMEWORK_NAME}" @@ -120,6 +124,27 @@ ASSERTION_LEVELS = { "SILENT": "CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT", } +SIGNING_SCHEMES = { + "rsa3072": "CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME", + "ecdsa256": "CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME", +} + +# Chip variants that only support one signing scheme for Secure Boot V2. +# Based on SOC_SECURE_BOOT_V2_RSA / SOC_SECURE_BOOT_V2_ECC in soc_caps.h. +# Variants not listed in either set support both RSA and ECDSA +# (e.g. C5, C6, H2, P4). New variants should be added to the +# appropriate set if they only support one scheme. +SIGNED_OTA_RSA_ONLY_VARIANTS = { + VARIANT_ESP32, + VARIANT_ESP32S2, + VARIANT_ESP32S3, + VARIANT_ESP32C3, +} +SIGNED_OTA_ECC_ONLY_VARIANTS = { + VARIANT_ESP32C2, + VARIANT_ESP32C61, +} + COMPILER_OPTIMIZATIONS = { "DEBUG": "CONFIG_COMPILER_OPTIMIZATION_DEBUG", "NONE": "CONFIG_COMPILER_OPTIMIZATION_NONE", @@ -962,6 +987,47 @@ def final_validate(config): ) # disable the rollback feature anyway since it can't be used. advanced[CONF_ENABLE_OTA_ROLLBACK] = False + if signed_ota := advanced.get(CONF_SIGNED_OTA_VERIFICATION): + scheme = signed_ota[CONF_SIGNING_SCHEME] + variant = config[CONF_VARIANT] + scheme_variant_conflicts = { + "ecdsa256": (SIGNED_OTA_RSA_ONLY_VARIANTS, "rsa3072"), + "rsa3072": (SIGNED_OTA_ECC_ONLY_VARIANTS, "ecdsa256"), + } + if (conflict := scheme_variant_conflicts.get(scheme)) and variant in conflict[ + 0 + ]: + errs.append( + cv.Invalid( + f"Signing scheme '{scheme}' is not supported on " + f"{VARIANT_FRIENDLY[variant]}. Use '{conflict[1]}' instead.", + path=[ + CONF_FRAMEWORK, + CONF_ADVANCED, + CONF_SIGNED_OTA_VERIFICATION, + CONF_SIGNING_SCHEME, + ], + ) + ) + if CONF_OTA not in full_config: + _LOGGER.warning( + "Signed OTA verification is enabled but no OTA component is configured. " + "The initial firmware will be signed but OTA updates won't be possible " + "until an OTA component is added." + ) + if CONF_SIGNING_KEY in signed_ota: + _LOGGER.info( + "Signed OTA verification is enabled. Keep your signing key safe! " + "If you lose the signing key, you will NOT be able to OTA update " + "devices running firmware signed with this key. " + "Without the key, you'll need to reflash via serial." + ) + else: + _LOGGER.info( + "Signed OTA verification is configured with a public verification key. " + "Binaries will NOT be signed automatically during build. " + "You must sign them externally before flashing." + ) if errs: raise cv.MultipleInvalid(errs) @@ -1173,6 +1239,18 @@ FRAMEWORK_SCHEMA = cv.Schema( min=8192, max=32768 ), cv.Optional(CONF_ENABLE_OTA_ROLLBACK, default=True): cv.boolean, + cv.Optional(CONF_SIGNED_OTA_VERIFICATION): cv.All( + cv.Schema( + { + cv.Optional(CONF_SIGNING_KEY): cv.file_, + cv.Optional(CONF_VERIFICATION_KEY): cv.file_, + cv.Optional( + CONF_SIGNING_SCHEME, default="rsa3072" + ): cv.one_of(*SIGNING_SCHEMES, lower=True), + } + ), + cv.has_exactly_one_key(CONF_SIGNING_KEY, CONF_VERIFICATION_KEY), + ), cv.Optional( CONF_USE_FULL_CERTIFICATE_BUNDLE, default=False ): cv.boolean, @@ -1878,6 +1956,32 @@ async def to_code(config): add_idf_sdkconfig_option("CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE", True) cg.add_define("USE_OTA_ROLLBACK") + # Enable signed app verification without hardware secure boot + if signed_ota := advanced.get(CONF_SIGNED_OTA_VERIFICATION): + add_idf_sdkconfig_option("CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT", True) + add_idf_sdkconfig_option("CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT", True) + + scheme = signed_ota[CONF_SIGNING_SCHEME] + for key, flag in SIGNING_SCHEMES.items(): + add_idf_sdkconfig_option(flag, scheme == key) + + if CONF_SIGNING_KEY in signed_ota: + # Private key mode — auto-sign binaries during build + add_idf_sdkconfig_option("CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES", True) + add_idf_sdkconfig_option( + "CONFIG_SECURE_BOOT_SIGNING_KEY", + str(signed_ota[CONF_SIGNING_KEY].resolve()), + ) + else: + # Public key mode — verification only, external signing required + add_idf_sdkconfig_option("CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES", False) + add_idf_sdkconfig_option( + "CONFIG_SECURE_BOOT_VERIFICATION_KEY", + str(signed_ota[CONF_VERIFICATION_KEY].resolve()), + ) + + cg.add_define("USE_OTA_SIGNED_VERIFICATION") + cg.add_define("ESPHOME_LOOP_TASK_STACK_SIZE", advanced[CONF_LOOP_TASK_STACK_SIZE]) cg.add_define( diff --git a/esphome/components/esp32/post_build.py.script b/esphome/components/esp32/post_build.py.script index 5ef5860687..8d13214259 100644 --- a/esphome/components/esp32/post_build.py.script +++ b/esphome/components/esp32/post_build.py.script @@ -8,6 +8,99 @@ import shutil # noqa: E402 from glob import glob # noqa: E402 +def _parse_sdkconfig(sdkconfig_path): + """Parse sdkconfig file and return a dict of CONFIG_ options.""" + options = {} + try: + for line in sdkconfig_path.read_text().splitlines(): + line = line.strip() + if line and not line.startswith("#") and "=" in line: + key, _, value = line.partition("=") + # Strip surrounding quotes from string values + if value.startswith('"') and value.endswith('"'): + value = value[1:-1] + options[key] = value + except FileNotFoundError: + pass + return options + + +def sign_firmware(source, target, env): + """ + Sign the firmware binary using espsecure.py if signed OTA verification is enabled. + Reads signing configuration from sdkconfig. + """ + build_dir = pathlib.Path(env.subst("$BUILD_DIR")) + project_dir = pathlib.Path(env.subst("$PROJECT_DIR")) + pioenv = env.subst("$PIOENV") + sdkconfig = _parse_sdkconfig(project_dir / f"sdkconfig.{pioenv}") + + if sdkconfig.get("CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT") != "y": + return + + if sdkconfig.get("CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES") != "y": + print("Signed OTA verification enabled but build-time signing disabled.") + print("You must sign the firmware externally before flashing.") + return + + signing_key = sdkconfig.get("CONFIG_SECURE_BOOT_SIGNING_KEY") + if not signing_key: + print("Error: CONFIG_SECURE_BOOT_SIGNING_KEY not set in sdkconfig") + env.Exit(1) + return + + signing_key_path = pathlib.Path(signing_key) + if not signing_key_path.exists(): + print(f"Error: Signing key not found: {signing_key_path}") + env.Exit(1) + return + + # ESPHome only exposes RSA3072 and ECDSA256 (both Secure Boot V2 schemes), + # so the espsecure signature version is always 2. + sign_version = "2" + + firmware_name = os.path.basename(env.subst("$PROGNAME")) + ".bin" + firmware_path = build_dir / firmware_name + + if not firmware_path.exists(): + print(f"Error: Firmware binary not found: {firmware_path}") + env.Exit(1) + return + + python_exe = f'"{env.subst("$PYTHONEXE")}"' + unsigned_path = firmware_path.with_suffix(".unsigned.bin") + + # Keep a copy of the unsigned binary + shutil.copyfile(str(firmware_path), str(unsigned_path)) + + cmd = [ + python_exe, + "-m", + "espsecure", + "sign-data", + "--version", + sign_version, + "--keyfile", + str(signing_key_path), + "--output", + str(firmware_path), + str(unsigned_path), + ] + + print(f"Signing firmware with key: {signing_key_path.name}") + result = env.Execute( + env.VerboseAction(" ".join(cmd), "Signing firmware with espsecure") + ) + + if result == 0: + print("Successfully signed firmware") + else: + print(f"Error: espsecure sign_data failed with code {result}") + # Restore unsigned binary on failure + shutil.copyfile(str(unsigned_path), str(firmware_path)) + env.Exit(1) + + def merge_factory_bin(source, target, env): """ Merges all flash sections into a single .factory.bin using esptool. @@ -124,7 +217,8 @@ def esp32_copy_ota_bin(source, target, env): print(f"Copied firmware to {new_file_name}") -# Run merge first, then ota copy second +# Run signing first, then merge, then ota copy +env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", sign_firmware) # noqa: F821 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", merge_factory_bin) # noqa: F821 env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_copy_ota_bin) # noqa: F821 diff --git a/esphome/components/ota/ota_backend.h b/esphome/components/ota/ota_backend.h index db79370bb3..bd9c481901 100644 --- a/esphome/components/ota/ota_backend.h +++ b/esphome/components/ota/ota_backend.h @@ -37,6 +37,7 @@ enum OTAResponseTypes { OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION = 0x8A, OTA_RESPONSE_ERROR_MD5_MISMATCH = 0x8B, OTA_RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE = 0x8C, + OTA_RESPONSE_ERROR_SIGNATURE_INVALID = 0x8D, OTA_RESPONSE_ERROR_UNKNOWN = 0xFF, }; diff --git a/esphome/components/ota/ota_backend_esp_idf.cpp b/esphome/components/ota/ota_backend_esp_idf.cpp index efaf810ca3..598fce1562 100644 --- a/esphome/components/ota/ota_backend_esp_idf.cpp +++ b/esphome/components/ota/ota_backend_esp_idf.cpp @@ -3,6 +3,7 @@ #include "esphome/components/md5/md5.h" #include "esphome/core/defines.h" +#include "esphome/core/log.h" #include <esp_ota_ops.h> #include <esp_task_wdt.h> @@ -10,6 +11,8 @@ namespace esphome::ota { +static const char *const TAG = "ota.idf"; + std::unique_ptr<IDFOTABackend> make_ota_backend() { return make_unique<IDFOTABackend>(); } OTAResponseTypes IDFOTABackend::begin(size_t image_size) { @@ -98,7 +101,12 @@ OTAResponseTypes IDFOTABackend::end() { } } if (err == ESP_ERR_OTA_VALIDATE_FAILED) { +#ifdef USE_OTA_SIGNED_VERIFICATION + ESP_LOGE(TAG, "OTA validation failed (err=0x%X) - possible signature verification failure", err); + return OTA_RESPONSE_ERROR_SIGNATURE_INVALID; +#else return OTA_RESPONSE_ERROR_UPDATE_END; +#endif } if (err == ESP_ERR_FLASH_OP_TIMEOUT || err == ESP_ERR_FLASH_OP_FAIL) { return OTA_RESPONSE_ERROR_WRITING_FLASH; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index faa8c6d4b0..141f6d2be4 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -211,6 +211,7 @@ #define USE_ESPHOME_TASK_LOG_BUFFER #define ESPHOME_TASK_LOG_BUFFER_SIZE 768 #define USE_OTA_ROLLBACK +#define USE_OTA_SIGNED_VERIFICATION #define USE_ESP32_MIN_CHIP_REVISION_SET #define USE_ESP32_SRAM1_AS_IRAM diff --git a/esphome/espota2.py b/esphome/espota2.py index c412bb51ff..4b813e4060 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -40,6 +40,8 @@ RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE = 0x88 RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE = 0x89 RESPONSE_ERROR_NO_UPDATE_PARTITION = 0x8A RESPONSE_ERROR_MD5_MISMATCH = 0x8B +RESPONSE_ERROR_RP2040_NOT_ENOUGH_SPACE = 0x8C +RESPONSE_ERROR_SIGNATURE_INVALID = 0x8D RESPONSE_ERROR_UNKNOWN = 0xFF OTA_VERSION_1_0 = 1 @@ -192,6 +194,12 @@ def check_error(data: list[int] | bytes, expect: int | list[int] | None) -> None "Error: Application MD5 code mismatch. Please try again " "or flash over USB with a good quality cable." ) + if dat == RESPONSE_ERROR_SIGNATURE_INVALID: + raise OTAError( + "Error: Firmware signature verification failed. The firmware was not signed " + "with the correct key. Ensure the signing key matches the one used to build " + "the firmware currently running on the device." + ) if dat == RESPONSE_ERROR_UNKNOWN: raise OTAError("Unknown error from ESP") if not isinstance(expect, (list, tuple)): diff --git a/tests/components/esp32/dummy_signing_key.pem b/tests/components/esp32/dummy_signing_key.pem new file mode 100644 index 0000000000..a74231d590 --- /dev/null +++ b/tests/components/esp32/dummy_signing_key.pem @@ -0,0 +1,41 @@ +*** DO NOT USE THIS KEY...EVER *** +-----BEGIN RSA PRIVATE KEY----- +MIIG5AIBAAKCAYEA0J665DlxzUzzouzH96fxqXybEfFU7H1oSf2fUHwoNMgUG7Vc +SHxuFJkpsUnxg9br09/v5THOXfUj5t/Arog6FGiL7i0HXCYDMnSn2EzQWR+DY2Qj +C3YzTLvcOQ40gFjDWfzAheAMCQmc5xQeB3YmaXQf+fUWH/PfFs9Pm+L92YTv2XC1 +B2q5s8K8hUWghO472A+UMrreuDcltNJ+TbuSRHK0NQzKpKo0Vkl4HycczGDgpa8D +h68JL/BKVeJAjKxWd/xcj/FCk661ODXi0esB/mGQP3hAthWpwi+gdkWczWs1Ocr6 +VxKje1zFm9SEq+SmCViPY/Pu8Xs7steqz3b3JtRGtKQE0r3B+hBKI7aRudOZyz0s +kqoL1zYrAWmoTWBqa2tj1ACPqtr2LyHGt2aVrHRQGJf21mPYIy9GIOv+3v3GzIAK +az2B8Z93Bw1biwNZDr1SLNYfQVaJT1hQavmdlvwW8vqLUGDcQlk42yOF6nAmvAPu +Wzxf+QFEtJT6Am65AgMBAAECggGAB0d+mG+LscDtYGI4MQNGaqZLJ+NelfjjPm+v +0yhd48eWcggQPgQ/eA8HFiVRHMtPQ7+U2I+2Fm+zDr+AcuaUdjlWppsiHlxCMMzC +vYiinXV8yWdJVMFNVXBZpRECknbmbBmmYxV3/gm8lJCOYq7D9NqFMhzT5o4FGv/l +VHhlaKVblB/7ZRSbgbL6DoFpMjI42tdiUanVEyLzeR1+JDq3BhXlhVNar8ezl04t +d5LPDa+UrxtN+XpJTQeqpFgGbhImSxjzCjo0kbGiEx/DwWuFJxguIcDU25sM4g2+ +ivtn7N11U0oaqNwsz7p4cKAm8toJYxxXWZvKdj1kZvCZ+BtyH0/MtOa2Q6v91HOh +zY4KEl5wxQYnxJrgqevSm8rrC51tLOCidZ16cHba8sjrK69xysEazk43roHLFXDp +JpH7Zd8LETjFWGVfUz6vppzkt6mrJk0DNuMLk/UwpPHzW2pu1qDiHPCb9+ra1S9U +t55hT2TBFDcG/NmZZnyHQoh8METhAoHBAPIG0G8Cd4fmkvbgCRLzCIWsH6zGHS9o +80Rj9Gu93B+m/F9GtgyYuX+DKSdMdw3IJamUsBwofT2wynmkuJFhLtD1FmYtlsXf +TWp8g8CfFGrIXDvin5E3heyhvtFiOjXlw0Q8yMmQXr5LF0i3WyFCPQM20ugClB7N +CQBOVAfpVoRU1fA6UjjHibFRwi1b4bLV69QiERPCJfcny/DPkZpu7I1fiINmwzEb +O5mIFo5F4TQADEreWplXEmhEXIzDMFIwEQKBwQDcqimCcO3RSysZMQhhUfk8G19I +yRNwvi2fK5LiGCZMYjeYKqg1rBN4yCf9PTwaqBNRqXTg13Fc7zrOkSI+0oDa4FWI +/kMEztaUK+Kwd2NKc96aXHMBGF+1Sx7Ygnr9e2dyqDqRij2/qlQYY1EDz7cYldaX +YNrXcQQeNJbqydjRDYi+9bI+wDkrK/5PxE1sGmqS1RMKxoJCZmxNiQT3PmXM/oNR +Ev6N9CDklFtClWNcD0Uum+mxNJ53ldZDx4UI/CkCgcEA6R6BI3vX0FHaGureMp9f +BQoulEdbEzBeqPAyHJkKbn50Nf0xGt78RYL7X7v6LI8tH7N1Eho5z/L6g8KSeI2H +/4MiqRaeVEdrFPeMHDvd+aC1noUBt2komS2OU7XuZb3CoHZ/3A4wA9DmQ4dAwr8/ +b1oeOZVKQISzd9T6gYhSajIgwzwZuFESInaitvf6ZDxC49hQZJyr3u05NeFo2Lyh +Iuby4cZYmnMlrBN1zmImseSd8ntL/sjslPvLvVXAtFlRAoHBAIDuG5rPiOTE2sW5 +VIAoeUuZYq8QbX9uXxGlUAkyuw3eRUVvhyD1DduAd30Ljla05bTNIjFNMDtwvBd9 +zViPfiJk+RU2GspwYAfrLGSXHTifQu1GHxwAtcsjvT4b3ujEdckUakQnVbTrPH+T +Z/6mGwEOa3e/a559tj4/0/4TOc/L7J5GyILJpZ2H8uuAcww60xI/1QRywCEz3wve +hzw/BRQlkWyJgJpIjf+Af2IEDy327iExj/WuHPkaXzrzFNQPIQKBwAM6qeNOxrO3 +V91wg4+44FAsOda62fZ0GlCM7ETnEjLbFamtCKEcDNfijwTa54LcZ6yObyutD1RN +dhj4Z6QKuYnsE02agv9CtXdFEVEXaqj4pshdgVOwGK34OidT4yIJQGLrRAQ/JiGH +x6CoGUCNIAq5J08VdosLTD9qdn1zv8USCAP0ReKnRMndTzENLYz9G3nQyHgt5GzI +YoSRtrWnXrQp2Yn3epk74gFAJtKozWNV4Du35FJBjmSeMuRivonNMQ== +-----END RSA PRIVATE KEY----- +*** DO NOT USE THIS KEY...EVER *** diff --git a/tests/components/esp32/test-signed_ota.esp32-s3-idf.yaml b/tests/components/esp32/test-signed_ota.esp32-s3-idf.yaml new file mode 100644 index 0000000000..cf1a54cfa1 --- /dev/null +++ b/tests/components/esp32/test-signed_ota.esp32-s3-idf.yaml @@ -0,0 +1,10 @@ +esp32: + variant: esp32s3 + framework: + type: esp-idf + advanced: + signed_ota_verification: + signing_key: ../../components/esp32/dummy_signing_key.pem + signing_scheme: rsa3072 + +<<: !include common.yaml From aac74f4c947d55726129f1914e78a85f84bee375 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 5 Apr 2026 22:48:00 -0400 Subject: [PATCH 1952/2030] [ags10] Fix wrong type passed to cg.templatable for set_zero_point mode (#15467) --- esphome/components/ags10/sensor.py | 10 +++++++--- tests/components/ags10/common.yaml | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/esphome/components/ags10/sensor.py b/esphome/components/ags10/sensor.py index 4cfa9e67ec..90fe067b32 100644 --- a/esphome/components/ags10/sensor.py +++ b/esphome/components/ags10/sensor.py @@ -112,7 +112,9 @@ AGS10_SET_ZERO_POINT_ACTION_MODE = { AGS10_SET_ZERO_POINT_SCHEMA = cv.Schema( { cv.GenerateID(): cv.use_id(AGS10Component), - cv.Required(CONF_MODE): cv.enum(AGS10_SET_ZERO_POINT_ACTION_MODE, upper=True), + cv.Required(CONF_MODE): cv.templatable( + cv.enum(AGS10_SET_ZERO_POINT_ACTION_MODE, upper=True) + ), cv.Optional(CONF_VALUE, default=0xFFFF): cv.templatable(cv.uint16_t), }, ) @@ -127,8 +129,10 @@ AGS10_SET_ZERO_POINT_SCHEMA = cv.Schema( async def ags10setzeropoint_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - mode = await cg.templatable(config.get(CONF_MODE), args, enumerate) + mode = await cg.templatable( + config.get(CONF_MODE), args, AGS10SetZeroPointActionMode + ) cg.add(var.set_mode(mode)) - value = await cg.templatable(config[CONF_VALUE], args, int) + value = await cg.templatable(config[CONF_VALUE], args, cg.uint16) cg.add(var.set_value(value)) return var diff --git a/tests/components/ags10/common.yaml b/tests/components/ags10/common.yaml index 0551871e59..8009c56295 100644 --- a/tests/components/ags10/common.yaml +++ b/tests/components/ags10/common.yaml @@ -4,3 +4,14 @@ sensor: tvoc: name: AGS10 TVOC update_interval: 60s + +button: + - platform: template + name: "Test AGS10 Actions" + on_press: + - ags10.set_zero_point: + id: ags10_1 + mode: CURRENT_VALUE + - ags10.new_i2c_address: + id: ags10_1 + address: 0x1A From 10f08e080299296db5afb8ca8a25f9d423401bca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 17:30:56 -1000 Subject: [PATCH 1953/2030] [esp8266] Add crash handler for post-mortem diagnostics (#15465) --- esphome/components/api/api_connection.h | 6 + esphome/components/esp8266/__init__.py | 1 + esphome/components/esp8266/crash_handler.cpp | 235 +++++++++++++++++++ esphome/components/esp8266/crash_handler.h | 20 ++ esphome/components/esp8266/preferences.cpp | 11 +- esphome/components/logger/logger_esp8266.cpp | 7 + esphome/core/defines.h | 1 + 7 files changed, 276 insertions(+), 5 deletions(-) create mode 100644 esphome/components/esp8266/crash_handler.cpp create mode 100644 esphome/components/esp8266/crash_handler.h diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 13d5273ecb..5a86240ab5 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -20,6 +20,9 @@ #ifdef USE_RP2040_CRASH_HANDLER #include "esphome/components/rp2040/crash_handler.h" #endif +#ifdef USE_ESP8266_CRASH_HANDLER +#include "esphome/components/esp8266/crash_handler.h" +#endif #include "esphome/core/entity_base.h" #include "esphome/core/string_ref.h" @@ -276,6 +279,9 @@ class APIConnection final : public APIServerConnectionBase { #endif #ifdef USE_RP2040_CRASH_HANDLER rp2040::crash_handler_log(); +#endif +#ifdef USE_ESP8266_CRASH_HANDLER + esp8266::crash_handler_log(); #endif } #ifdef USE_API_HOMEASSISTANT_SERVICES diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index 2081145096..fcd3499b15 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -233,6 +233,7 @@ async def to_code(config): cg.add_define("ESPHOME_BOARD", config[CONF_BOARD]) cg.add_define("ESPHOME_VARIANT", "ESP8266") cg.add_define(ThreadModel.SINGLE) + cg.add_define("USE_ESP8266_CRASH_HANDLER") enable_scanf_float = config.get(CONF_ENABLE_SCANF_FLOAT) if enable_scanf_float is None and lambdas_use_scanf_float(CORE.config): diff --git a/esphome/components/esp8266/crash_handler.cpp b/esphome/components/esp8266/crash_handler.cpp new file mode 100644 index 0000000000..91b0cf9082 --- /dev/null +++ b/esphome/components/esp8266/crash_handler.cpp @@ -0,0 +1,235 @@ +#ifdef USE_ESP8266 + +#include "esphome/core/defines.h" +#ifdef USE_ESP8266_CRASH_HANDLER + +#include "crash_handler.h" +#include "esphome/core/log.h" + +#include <cinttypes> + +extern "C" { +#include <user_interface.h> + +// Global reset info struct populated by SDK/Arduino core at boot +extern struct rst_info resetInfo; +} + +// Xtensa windowed-ABI: bits[31:30] encode call type (CALL0=00, CALL4=01, +// CALL8=10, CALL12=11). Mask and force bit 30 to recover the real address. +static constexpr uint32_t XTENSA_ADDR_MASK = 0x3FFFFFFF; +static constexpr uint32_t XTENSA_CODE_BASE = 0x40000000; + +// ESP8266 memory map boundaries for code regions +static constexpr uint32_t IRAM_START = 0x40100000; +static constexpr uint32_t IRAM_END = 0x40108000; // 32KB + +// Linker symbols for the actual firmware IROM section. +// Using these instead of a conservative upper bound (0x40400000) prevents +// false positives from stale stack values beyond the actual flash mapping. +extern "C" { +// NOLINTBEGIN(bugprone-reserved-identifier,readability-identifier-naming,readability-redundant-declaration) +extern void _irom0_text_start(void); +extern void _irom0_text_end(void); +// NOLINTEND(bugprone-reserved-identifier,readability-identifier-naming,readability-redundant-declaration) +} + +// Check if a value looks like a code address in IRAM or flash-mapped IROM. +// IRAM_ATTR as safety net — normally inlined into custom_crash_callback, but +// ensures correctness if the compiler ever chooses not to inline. +static inline bool IRAM_ATTR is_code_addr(uint32_t val) { + uint32_t addr = (val & XTENSA_ADDR_MASK) | XTENSA_CODE_BASE; + return (addr >= IRAM_START && addr < IRAM_END) || + (addr >= (uint32_t) _irom0_text_start && addr < (uint32_t) _irom0_text_end); +} + +// Recover the actual code address from a windowed-ABI return address on the stack. +static inline uint32_t IRAM_ATTR recover_code_addr(uint32_t val) { return (val & XTENSA_ADDR_MASK) | XTENSA_CODE_BASE; } + +// RTC user memory layout for crash backtrace data. +// User-accessible RTC memory: blocks 64-191 (each block = 4 bytes). +// We use blocks 174-191 (last 18 blocks, 72 bytes) to minimize conflicts. +// Store 16 raw candidates, filter to real return addresses at log time. +static constexpr uint8_t RTC_CRASH_BASE = 174; +static constexpr size_t MAX_BACKTRACE = 16; + +// Magic word packs sentinel, version, and count into one uint32_t: +// bits[31:16] = sentinel +// bits[15:8] = version +// bits[7:0] = backtrace count +static constexpr uint8_t CRASH_SENTINEL_BITS = 16; +static constexpr uint8_t CRASH_VERSION_BITS = 8; + +static constexpr uint16_t CRASH_SENTINEL_VALUE = 0xDEAD; +static constexpr uint8_t CRASH_VERSION_VALUE = 1; + +static constexpr uint32_t CRASH_SENTINEL = static_cast<uint32_t>(CRASH_SENTINEL_VALUE) << CRASH_SENTINEL_BITS; +static constexpr uint32_t CRASH_VERSION = static_cast<uint32_t>(CRASH_VERSION_VALUE) << CRASH_VERSION_BITS; +static constexpr uint32_t CRASH_SENTINEL_MASK = static_cast<uint32_t>(0xFFFF) << CRASH_SENTINEL_BITS; +static constexpr uint32_t CRASH_VERSION_MASK = static_cast<uint32_t>(0xFF) << CRASH_VERSION_BITS; +static constexpr uint32_t CRASH_COUNT_MASK = 0xFF; + +// Struct layout: 18 RTC blocks (72 bytes): +// [0] = magic (sentinel | version | count) +// [1..16] = up to 16 code addresses from stack scanning +// [17] = epc1 at crash time (to skip duplicates at log time) +struct RtcCrashData { + uint32_t magic; + uint32_t backtrace[MAX_BACKTRACE]; + uint32_t epc1; // Fault PC, used to filter duplicates +}; +static_assert(sizeof(RtcCrashData) == 72, "RtcCrashData must fit in 18 RTC blocks"); + +namespace esphome::esp8266 { + +static const char *const TAG = "esp8266"; + +static inline bool is_crash_reason(uint32_t reason) { + return reason == REASON_WDT_RST || reason == REASON_EXCEPTION_RST || reason == REASON_SOFT_WDT_RST; +} + +bool crash_handler_has_data() { return is_crash_reason(resetInfo.reason); } + +// Xtensa exception cause names for the LX106 core (ESP8266). +// Only includes causes that can actually occur on the LX106 — it has no MMU, +// no TLB, no PIF, and no privilege levels, so causes 12-18 and 24-26 are +// impossible and omitted. The numeric cause is always logged as fallback. +// Uses if-else with LOG_STR to avoid CSWTCH jump tables (RAM on ESP8266). +static const LogString *get_exception_cause(uint32_t cause) { + if (cause == 0) + return LOG_STR("IllegalInst"); + if (cause == 2) + return LOG_STR("InstFetchErr"); + if (cause == 3) + return LOG_STR("LoadStoreErr"); + if (cause == 4) + return LOG_STR("Level1Int"); + if (cause == 6) + return LOG_STR("DivByZero"); + if (cause == 9) + return LOG_STR("Alignment"); + if (cause == 20) + return LOG_STR("InstFetchProhibit"); + if (cause == 28) + return LOG_STR("LoadProhibit"); + if (cause == 29) + return LOG_STR("StoreProhibit"); + return nullptr; +} + +static const LogString *get_reset_reason(uint32_t reason) { + if (reason == REASON_WDT_RST) + return LOG_STR("Hardware WDT"); + if (reason == REASON_EXCEPTION_RST) + return LOG_STR("Exception"); + if (reason == REASON_SOFT_WDT_RST) + return LOG_STR("Soft WDT"); + return LOG_STR("Unknown"); +} + +// Read backtrace from RTC user memory into caller-provided buffer. +// Returns the number of valid backtrace entries (0 if no data found). +static uint8_t read_rtc_backtrace(uint32_t *backtrace, size_t max_entries) { + RtcCrashData rtc_data; + if (!system_rtc_mem_read(RTC_CRASH_BASE, &rtc_data, sizeof(rtc_data))) + return 0; + uint32_t magic = rtc_data.magic; + if ((magic & CRASH_SENTINEL_MASK) != CRASH_SENTINEL || (magic & CRASH_VERSION_MASK) != CRASH_VERSION) + return 0; + uint8_t raw_count = magic & CRASH_COUNT_MASK; + if (raw_count > MAX_BACKTRACE) + raw_count = MAX_BACKTRACE; + // Skip any that match epc1 (already reported as the fault PC). + // Note: we cannot verify CALL instructions at addr-3 on ESP8266 because + // reading from IROM causes LoadStoreError due to flash cache conflicts + // (the reading code and target can share a direct-mapped cache line). + // The linker-symbol IROM bounds already eliminate most false positives. + uint8_t out = 0; + for (uint8_t i = 0; i < raw_count && out < max_entries; i++) { + uint32_t addr = rtc_data.backtrace[i]; + if (addr != rtc_data.epc1) + backtrace[out++] = addr; + } + return out; +} + +// Intentionally uses separate ESP_LOGE calls per line instead of combining into +// one multi-line log message. This ensures each address appears as its own line +// on the serial console, making it possible to see partial output if the device +// crashes again during boot, and allowing the CLI's process_stacktrace to match +// and decode each address individually. +void crash_handler_log() { + if (!is_crash_reason(resetInfo.reason)) + return; + + // Read and filter backtrace from RTC into stack-local buffer (no persistent RAM cost). + // Both resetInfo and RTC data survive until the next reset, so this can be + // called multiple times (logger init + API subscribe) with the same result. + uint32_t backtrace[MAX_BACKTRACE]; + uint8_t bt_count = read_rtc_backtrace(backtrace, MAX_BACKTRACE); + + ESP_LOGE(TAG, "*** CRASH DETECTED ON PREVIOUS BOOT ***"); + // GCC's ROM divide routine triggers IllegalInstruction (exccause=0) at specific + // ROM addresses instead of IntegerDivideByZero (exccause=6). Patch to match + // the Arduino core's postmortem handler behavior. + static constexpr uint32_t EXCCAUSE_ILLEGAL_INSTRUCTION = 0; + static constexpr uint32_t EXCCAUSE_INTEGER_DIVIDE_BY_ZERO = 6; + static constexpr uint32_t ROM_DIV_ZERO_ADDR_1 = 0x4000dce5; + static constexpr uint32_t ROM_DIV_ZERO_ADDR_2 = 0x4000dd3d; + uint32_t exccause = resetInfo.exccause; + if (exccause == EXCCAUSE_ILLEGAL_INSTRUCTION && + (resetInfo.epc1 == ROM_DIV_ZERO_ADDR_1 || resetInfo.epc1 == ROM_DIV_ZERO_ADDR_2)) { + exccause = EXCCAUSE_INTEGER_DIVIDE_BY_ZERO; + } + const LogString *cause = get_exception_cause(exccause); + if (cause != nullptr) { + ESP_LOGE(TAG, " Reason: %s - %s (exccause=%" PRIu32 ")", LOG_STR_ARG(get_reset_reason(resetInfo.reason)), + LOG_STR_ARG(cause), exccause); + } else { + ESP_LOGE(TAG, " Reason: %s (exccause=%" PRIu32 ")", LOG_STR_ARG(get_reset_reason(resetInfo.reason)), exccause); + } + ESP_LOGE(TAG, " PC: 0x%08" PRIX32, resetInfo.epc1); + if (resetInfo.reason == REASON_EXCEPTION_RST) { + ESP_LOGE(TAG, " EXCVADDR: 0x%08" PRIX32, resetInfo.excvaddr); + } + for (uint8_t i = 0; i < bt_count; i++) { + ESP_LOGE(TAG, " BT%d: 0x%08" PRIX32, i, backtrace[i]); + } +} + +} // namespace esphome::esp8266 + +// --- Custom crash callback --- +// Overrides the weak custom_crash_callback() from Arduino core's +// core_esp8266_postmortem.cpp. Called during exception handling before +// the device restarts. We scan the full stack for code addresses and store +// them in RTC user memory (which survives software reset). +extern "C" void IRAM_ATTR custom_crash_callback(struct rst_info *rst_info, uint32_t stack, uint32_t stack_end) { + // No zero-init — only magic, epc1, and backtrace[0..count-1] are read. + // Saves the IRAM cost of a 72-byte zero-init loop. + RtcCrashData data; // NOLINT(cppcoreguidelines-pro-type-member-init) + uint8_t count = 0; + + // Stack pointer from the Xtensa exception frame is always 4-byte aligned. + auto *scan = (uint32_t *) stack; // NOLINT(performance-no-int-to-ptr) + auto *end = (uint32_t *) stack_end; // NOLINT(performance-no-int-to-ptr) + uint32_t epc1 = rst_info->epc1; + + for (; scan < end && count < MAX_BACKTRACE; scan++) { + uint32_t val = *scan; + if (is_code_addr(val)) { + uint32_t addr = recover_code_addr(val); + // Skip epc1 — already reported as the fault PC + if (addr != epc1) + data.backtrace[count++] = addr; + } + } + + data.epc1 = epc1; + data.magic = CRASH_SENTINEL | CRASH_VERSION | count; + + system_rtc_mem_write(RTC_CRASH_BASE, &data, sizeof(data)); +} + +#endif // USE_ESP8266_CRASH_HANDLER +#endif // USE_ESP8266 diff --git a/esphome/components/esp8266/crash_handler.h b/esphome/components/esp8266/crash_handler.h new file mode 100644 index 0000000000..ea3683b834 --- /dev/null +++ b/esphome/components/esp8266/crash_handler.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef USE_ESP8266 + +#include "esphome/core/defines.h" + +#ifdef USE_ESP8266_CRASH_HANDLER + +namespace esphome::esp8266 { + +/// Log crash data if a crash was detected on previous boot. +void crash_handler_log(); + +/// Returns true if the previous boot was a crash (exception, WDT, or soft WDT). +bool crash_handler_has_data(); + +} // namespace esphome::esp8266 + +#endif // USE_ESP8266_CRASH_HANDLER +#endif // USE_ESP8266 diff --git a/esphome/components/esp8266/preferences.cpp b/esphome/components/esp8266/preferences.cpp index 906fed2b29..f444f03555 100644 --- a/esphome/components/esp8266/preferences.cpp +++ b/esphome/components/esp8266/preferences.cpp @@ -19,12 +19,13 @@ static constexpr uint32_t ESP_RTC_USER_MEM_START = 0x60001200; static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_WORDS = 128; static constexpr uint32_t ESP_RTC_USER_MEM_SIZE_BYTES = ESP_RTC_USER_MEM_SIZE_WORDS * 4; -// RTC memory layout for preferences: -// - Eboot region: RTC words 0-31 (reserved, mapped from preference offset 96-127) -// - Normal region: RTC words 32-127 (mapped from preference offset 0-95) +// RTC memory layout: +// - Eboot region: RTC words 0-31 (reserved, mapped from preference offset 78-109) +// - Normal region: RTC words 32-109 (mapped from preference offset 0-77) +// - Crash handler: RTC words 110-127 (reserved for crash_handler.cpp backtrace data) static constexpr uint32_t RTC_EBOOT_REGION_WORDS = 32; // Words 0-31 reserved for eboot -static constexpr uint32_t RTC_NORMAL_REGION_WORDS = 96; // Words 32-127 for normal prefs -static constexpr uint32_t PREF_TOTAL_WORDS = RTC_EBOOT_REGION_WORDS + RTC_NORMAL_REGION_WORDS; // 128 +static constexpr uint32_t RTC_NORMAL_REGION_WORDS = 78; // Words 32-109 for normal prefs +static constexpr uint32_t PREF_TOTAL_WORDS = RTC_EBOOT_REGION_WORDS + RTC_NORMAL_REGION_WORDS; // 110 // Maximum preference size in words (limited by uint8_t length_words field) static constexpr uint32_t MAX_PREFERENCE_WORDS = 255; diff --git a/esphome/components/logger/logger_esp8266.cpp b/esphome/components/logger/logger_esp8266.cpp index b9507e707a..5797b03ba7 100644 --- a/esphome/components/logger/logger_esp8266.cpp +++ b/esphome/components/logger/logger_esp8266.cpp @@ -1,5 +1,9 @@ #ifdef USE_ESP8266 #include "logger.h" +#include "esphome/core/defines.h" +#ifdef USE_ESP8266_CRASH_HANDLER +#include "esphome/components/esp8266/crash_handler.h" +#endif #include "esphome/core/log.h" namespace esphome::logger { @@ -26,6 +30,9 @@ void Logger::pre_setup() { global_logger = this; ESP_LOGI(TAG, "Log initialized"); +#ifdef USE_ESP8266_CRASH_HANDLER + esp8266::crash_handler_log(); +#endif } const LogString *Logger::get_uart_selection_() { diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 141f6d2be4..d92fb6e98a 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -331,6 +331,7 @@ // ESP8266-specific feature flags #ifdef USE_ESP8266 #define USE_ADC_SENSOR_VCC +#define USE_ESP8266_CRASH_HANDLER #define USE_ARDUINO_VERSION_CODE VERSION_CODE(3, 1, 2) #define USE_CAPTIVE_PORTAL #define USE_ESP8266_LOGGER_SERIAL From 1de94c1a8489ca1ed5cf229e6f0e41bbbb6e065d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Sun, 5 Apr 2026 18:02:06 -1000 Subject: [PATCH 1954/2030] [api] Add max_value proto option for constant-size varint codegen (#15424) --- esphome/components/api/api.proto | 2 +- esphome/components/api/api_options.proto | 6 +++ esphome/components/api/api_pb2.cpp | 6 +-- script/api_protobuf/api_protobuf.py | 68 ++++++++++++++++++++---- 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 96ee2fb920..1e03675999 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -1606,7 +1606,7 @@ message BluetoothLEAdvertisementResponse { message BluetoothLERawAdvertisement { uint64 address = 1 [(force) = true]; sint32 rssi = 2 [(force) = true]; - uint32 address_type = 3; + uint32 address_type = 3 [(max_value) = 4]; bytes data = 4 [(fixed_array_size) = 62, (force) = true]; } diff --git a/esphome/components/api/api_options.proto b/esphome/components/api/api_options.proto index 02600f0977..0aa9e814cf 100644 --- a/esphome/components/api/api_options.proto +++ b/esphome/components/api/api_options.proto @@ -96,4 +96,10 @@ extend google.protobuf.FieldOptions { // variant of the calc_ method. Use on fields that are almost always non-default // to eliminate dead branches on hot paths. optional bool force = 50016 [default=false]; + + // max_value: Maximum value a field can have. + // When max_value < 128, the code generator emits constant-size calculations + // and direct byte writes instead of varint branching, since the encoded varint + // is guaranteed to be 1 byte. + optional uint32 max_value = 50017; } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index ae2cd2bae8..f25d269e8f 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -2255,15 +2255,15 @@ void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { buffer.encode_varint_raw(encode_zigzag32(this->rssi)); buffer.encode_uint32(3, this->address_type); buffer.write_raw_byte(34); - buffer.encode_varint_raw(this->data_len); + buffer.write_raw_byte(static_cast<uint8_t>(this->data_len)); buffer.encode_raw(this->data, this->data_len); } uint32_t BluetoothLERawAdvertisement::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_uint64_force(1, this->address); size += ProtoSize::calc_sint32_force(1, this->rssi); - size += ProtoSize::calc_uint32(1, this->address_type); - size += ProtoSize::calc_length_force(1, this->data_len); + size += this->address_type ? 2 : 0; + size += 2 + this->data_len; return size; } void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index f2a11141af..c17f16412c 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -156,6 +156,11 @@ class TypeInfo(ABC): """Check if this field should always be encoded (skip zero/empty check).""" return get_field_opt(self._field, pb.force, False) + @property + def max_value(self) -> int | None: + """Get the max_value option for this field, or None if not set.""" + return get_field_opt(self._field, pb.max_value, None) + @property def wire_type(self) -> WireType: """Get the wire type for the field.""" @@ -235,37 +240,56 @@ class TypeInfo(ABC): "encode_bool": "buffer.write_raw_byte({value} ? 0x01 : 0x00);", } + # When max_value < 128, the varint is always 1 byte — use a direct byte write + RAW_ENCODE_SMALL_MAP: dict[str, str] = { + "encode_uint32": "buffer.write_raw_byte(static_cast<uint8_t>({value}));", + "encode_uint64": "buffer.write_raw_byte(static_cast<uint8_t>({value}));", + } + def _encode_with_precomputed_tag(self, value_expr: str) -> str | None: """Try to emit a precomputed-tag encode for a forced field. Returns the raw encode string if the tag is a single byte and the encode_func has a known raw equivalent, or None otherwise. + When max_value < 128, uses direct byte write instead of varint encoding. """ if not self.force: return None tag = self.calculate_tag() if tag >= 128: return None - raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) + max_val = self.max_value + raw_expr = None + if max_val is not None and max_val < 128: + raw_expr = self.RAW_ENCODE_SMALL_MAP.get(self.encode_func) + if raw_expr is None: + raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) if raw_expr is None: return None return f"buffer.write_raw_byte({tag});\n{raw_expr.format(value=value_expr)}" def _encode_bytes_with_precomputed_tag( - self, data_expr: str, len_expr: str + self, data_expr: str, len_expr: str, max_len: int | None = None ) -> str | None: """Try to emit a precomputed-tag encode for a forced bytes/string field. Returns the raw encode string if the tag is a single byte, or None. + When max_len < 128, uses direct byte write for the length varint. """ if not self.force: return None tag = self.calculate_tag() if tag >= 128: return None + # When max_len < 128, length varint is always 1 byte + len_encode = ( + f"buffer.write_raw_byte(static_cast<uint8_t>({len_expr}));" + if max_len is not None and max_len < 128 + else f"buffer.encode_varint_raw({len_expr});" + ) return ( f"buffer.write_raw_byte({tag});\n" - f"buffer.encode_varint_raw({len_expr});\n" + f"{len_encode}\n" f"buffer.encode_raw({data_expr}, {len_expr});" ) @@ -346,6 +370,25 @@ class TypeInfo(ABC): value = value_expr or name return f"size += ProtoSize::{method}({field_id_size}, {value});" + def _get_single_byte_varint_size( + self, name: str, force: bool, extra_expr: str | None = None + ) -> str: + """Size calculation when the varint is guaranteed to be 1 byte. + + Used when max_value < 128 or fixed_array_size < 128. + The fixed part is field_id_size + 1 (tag + 1-byte varint). + + Args: + name: Expression to check for zero (non-force only) + force: Whether to skip the zero check + extra_expr: Additional variable expression to add (e.g., data length) + """ + fixed = self.calculate_field_id_size() + 1 + size_expr = f"{fixed} + {extra_expr}" if extra_expr else str(fixed) + if force: + return f"size += {size_expr};" + return f"size += {name} ? {size_expr} : 0;" + @abstractmethod def get_size_calculation(self, name: str, force: bool = False) -> str: """Calculate the size needed for encoding this field. @@ -1191,8 +1234,9 @@ class FixedArrayBytesType(TypeInfo): @property def encode_content(self) -> str: + max_len = self.array_size if isinstance(self.array_size, int) else None if result := self._encode_bytes_with_precomputed_tag( - f"this->{self.field_name}", f"this->{self.field_name}_len" + f"this->{self.field_name}", f"this->{self.field_name}_len", max_len=max_len ): return result if self.force: @@ -1212,13 +1256,14 @@ class FixedArrayBytesType(TypeInfo): def get_size_calculation(self, name: str, force: bool = False) -> str: # Use the actual length stored in the _len field length_field = f"this->{self.field_name}_len" - field_id_size = self.calculate_field_id_size() - if force: - # For repeated fields, always calculate size (no zero check) - return f"size += ProtoSize::calc_length_force({field_id_size}, {length_field});" - # For non-repeated fields, length already checks for zero - return f"size += ProtoSize::calc_length({field_id_size}, {length_field});" + # When array_size < 128, length varint is always 1 byte + if isinstance(self.array_size, int) and self.array_size < 128: + return self._get_single_byte_varint_size( + length_field, force, extra_expr=length_field + ) + + return self._get_simple_size_calculation(length_field, force, "length") def get_estimated_size(self) -> int: # Estimate based on typical BLE advertisement size @@ -1245,6 +1290,9 @@ class UInt32Type(TypeInfo): return o def get_size_calculation(self, name: str, force: bool = False) -> str: + max_val = self.max_value + if max_val is not None and max_val < 128: + return self._get_single_byte_varint_size(name, force) return self._get_simple_size_calculation(name, force, "uint32") def get_estimated_size(self) -> int: From 7644f17cf61f08a36304be3309dd26e229c1312d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 00:05:04 -0400 Subject: [PATCH 1955/2030] [at581x] Fix codegen crash when using lambdas for frequency/time/power (#15468) --- esphome/components/at581x/__init__.py | 32 ++++++++++----------------- tests/components/at581x/common.yaml | 5 +++++ 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/esphome/components/at581x/__init__.py b/esphome/components/at581x/__init__.py index 34e6570628..4923491f0c 100644 --- a/esphome/components/at581x/__init__.py +++ b/esphome/components/at581x/__init__.py @@ -173,8 +173,10 @@ async def at581x_settings_to_code(config, action_id, template_arg, args): cg.add(var.set_hw_frontend_reset(template_)) if freq := config.get(CONF_FREQUENCY): - template_ = await cg.templatable(freq, args, float) - template_ = int(template_ / 1000000) + if cg.is_template(freq): + template_ = await cg.templatable(freq, args, cg.int32) + else: + template_ = int(freq / 1000000) cg.add(var.set_frequency(template_)) if (sens_dist := config.get(CONF_SENSING_DISTANCE)) is not None: @@ -182,31 +184,19 @@ async def at581x_settings_to_code(config, action_id, template_arg, args): cg.add(var.set_sensing_distance(template_)) if selfcheck := config.get(CONF_POWERON_SELFCHECK_TIME): - template_ = await cg.templatable(selfcheck, args, float) - if isinstance(template_, cv.TimePeriod): - template_ = template_.total_milliseconds - template_ = int(template_) + template_ = await cg.templatable(selfcheck, args, cg.int32) cg.add(var.set_poweron_selfcheck_time(template_)) if protect := config.get(CONF_PROTECT_TIME): - template_ = await cg.templatable(protect, args, float) - if isinstance(template_, cv.TimePeriod): - template_ = template_.total_milliseconds - template_ = int(template_) + template_ = await cg.templatable(protect, args, cg.int32) cg.add(var.set_protect_time(template_)) if trig_base := config.get(CONF_TRIGGER_BASE): - template_ = await cg.templatable(trig_base, args, float) - if isinstance(template_, cv.TimePeriod): - template_ = template_.total_milliseconds - template_ = int(template_) + template_ = await cg.templatable(trig_base, args, cg.int32) cg.add(var.set_trigger_base(template_)) if trig_keep := config.get(CONF_TRIGGER_KEEP): - template_ = await cg.templatable(trig_keep, args, float) - if isinstance(template_, cv.TimePeriod): - template_ = template_.total_milliseconds - template_ = int(template_) + template_ = await cg.templatable(trig_keep, args, cg.int32) cg.add(var.set_trigger_keep(template_)) if (stage_gain := config.get(CONF_STAGE_GAIN)) is not None: @@ -214,8 +204,10 @@ async def at581x_settings_to_code(config, action_id, template_arg, args): cg.add(var.set_stage_gain(template_)) if power := config.get(CONF_POWER_CONSUMPTION): - template_ = await cg.templatable(power, args, float) - template_ = int(template_ * 1000000) + if cg.is_template(power): + template_ = await cg.templatable(power, args, cg.int32) + else: + template_ = int(power * 1000000) cg.add(var.set_power_consumption(template_)) return var diff --git a/tests/components/at581x/common.yaml b/tests/components/at581x/common.yaml index 425be47c42..dfb3a9a05e 100644 --- a/tests/components/at581x/common.yaml +++ b/tests/components/at581x/common.yaml @@ -12,6 +12,11 @@ esphome: trigger_keep: 10s stage_gain: 3 power_consumption: 70uA + - at581x.settings: + id: waveradar + frequency: !lambda "return 5800;" + poweron_selfcheck_time: !lambda "return 2000;" + power_consumption: !lambda "return 70;" - at581x.reset: id: waveradar From 859ea23bdefdb8dd209c071394d32f12f4779fae Mon Sep 17 00:00:00 2001 From: Boris Krivonog <boris.krivonog@inova.si> Date: Mon, 6 Apr 2026 06:33:02 +0200 Subject: [PATCH 1956/2030] [mitsubishi_cn105] Add climate component for Mitsubishi A/C units with CN105 connector (Part 4) (#15462) --- .../components/mitsubishi_cn105/climate.py | 16 +- .../mitsubishi_cn105/mitsubishi_cn105.cpp | 225 +++++++++++------- .../mitsubishi_cn105/mitsubishi_cn105.h | 63 ++++- .../mitsubishi_cn105_climate.cpp | 78 +++++- .../mitsubishi_cn105_climate.h | 1 + .../climate/mitsubishi_cn105_tests.cpp | 12 +- 6 files changed, 291 insertions(+), 104 deletions(-) diff --git a/esphome/components/mitsubishi_cn105/climate.py b/esphome/components/mitsubishi_cn105/climate.py index 5ea72d4cd2..7fa6825ea6 100644 --- a/esphome/components/mitsubishi_cn105/climate.py +++ b/esphome/components/mitsubishi_cn105/climate.py @@ -8,6 +8,8 @@ DEPENDENCIES = ["uart"] AUTO_LOAD = ["climate"] CODEOWNERS = ["@crnjan"] +CONF_CURRENT_TEMPERATURE_MIN_INTERVAL = "current_temperature_min_interval" + mitsubishi_ns = cg.esphome_ns.namespace("mitsubishi_cn105") MitsubishiCN105Climate = mitsubishi_ns.class_( @@ -20,7 +22,14 @@ MitsubishiCN105Climate = mitsubishi_ns.class_( CONFIG_SCHEMA = ( climate.climate_schema(MitsubishiCN105Climate) .extend(uart.UART_DEVICE_SCHEMA) - .extend({cv.Optional(CONF_UPDATE_INTERVAL, default="1s"): cv.update_interval}) + .extend( + { + cv.Optional(CONF_UPDATE_INTERVAL, default="1s"): cv.update_interval, + cv.Optional( + CONF_CURRENT_TEMPERATURE_MIN_INTERVAL, default="60s" + ): cv.update_interval, + } + ) ) FINAL_VALIDATE_SCHEMA = cv.All( @@ -39,3 +48,8 @@ async def to_code(config: ConfigType) -> None: var = await climate.new_climate(config) await cg.register_component(var, config) await uart.register_uart_device(var, config) + cg.add( + var.set_current_temperature_min_interval( + config[CONF_CURRENT_TEMPERATURE_MIN_INTERVAL] + ) + ) diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp index 0bce8da1ad..3b29f66bf1 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp @@ -22,7 +22,33 @@ static constexpr uint8_t PACKET_TYPE_STATUS_REQUEST = 0x42; static constexpr uint8_t PACKET_TYPE_STATUS_RESPONSE = 0x62; static constexpr uint8_t STATUS_MSG_SETTINGS = 0x02; static constexpr uint8_t STATUS_MSG_ROOM_TEMP = 0x03; -static constexpr std::array<uint8_t, 2> STATUS_MSG_TYPES = {STATUS_MSG_SETTINGS, STATUS_MSG_ROOM_TEMP}; + +static constexpr std::array<std::optional<MitsubishiCN105::Mode>, 9> PROTOCOL_MODE_MAP = { + std::nullopt, // 0x00 + MitsubishiCN105::Mode::HEAT, // 0x01 + MitsubishiCN105::Mode::DRY, // 0x02 + MitsubishiCN105::Mode::COOL, // 0x03 + std::nullopt, // 0x04 + std::nullopt, // 0x05 + std::nullopt, // 0x06 + MitsubishiCN105::Mode::FAN_ONLY, // 0x07 + MitsubishiCN105::Mode::AUTO // 0x08 +}; + +static constexpr std::array<std::optional<MitsubishiCN105::FanMode>, 7> PROTOCOL_FAN_MODE_MAP = { + MitsubishiCN105::FanMode::AUTO, // 0x00 + MitsubishiCN105::FanMode::QUIET, // 0x01 + MitsubishiCN105::FanMode::SPEED_1, // 0x02 + MitsubishiCN105::FanMode::SPEED_2, // 0x03 + std::nullopt, // 0x04 + MitsubishiCN105::FanMode::SPEED_3, // 0x05 + MitsubishiCN105::FanMode::SPEED_4 // 0x06 +}; + +template<typename T, size_t N> +static constexpr std::optional<T> lookup(const std::array<std::optional<T>, N> &table, uint8_t value) { + return (value < N) ? table[value] : std::nullopt; +} static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) { return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0})); @@ -54,12 +80,14 @@ bool MitsubishiCN105::update() { if (const auto start = this->write_timeout_start_ms_; start && (get_loop_time_ms() - *start) >= WRITE_TIMEOUT_MS) { this->write_timeout_start_ms_.reset(); - this->read_pos_ = 0; + this->frame_parser_.reset(); this->set_state_(State::READ_TIMEOUT); return false; } - return this->read_incoming_bytes_(); + return this->frame_parser_.read_and_parse(this->device_, [this](uint8_t type, const uint8_t *payload, size_t len) { + return this->process_rx_packet_(type, payload, len); + }); } void MitsubishiCN105::set_state_(State new_state) { @@ -111,7 +139,7 @@ void MitsubishiCN105::did_transition_(State to) { case State::CONNECTED: this->write_timeout_start_ms_.reset(); - this->status_msg_index_ = 0; + this->current_status_msg_type_ = STATUS_MSG_SETTINGS; this->set_state_(State::UPDATING_STATUS); break; @@ -121,10 +149,8 @@ void MitsubishiCN105::did_transition_(State to) { case State::STATUS_UPDATED: { this->write_timeout_start_ms_.reset(); - if (++this->status_msg_index_ >= STATUS_MSG_TYPES.size()) { - this->status_msg_index_ = 0; - } - if (this->status_msg_index_ != 0) { + if (this->current_status_msg_type_ == STATUS_MSG_SETTINGS && this->should_request_room_temperature_()) { + this->current_status_msg_type_ = STATUS_MSG_ROOM_TEMP; this->set_state_(State::UPDATING_STATUS); } else { this->set_state_(State::SCHEDULE_NEXT_STATUS_UPDATE); @@ -134,6 +160,7 @@ void MitsubishiCN105::did_transition_(State to) { case State::SCHEDULE_NEXT_STATUS_UPDATE: this->status_update_start_ms_ = get_loop_time_ms(); + this->current_status_msg_type_ = STATUS_MSG_SETTINGS; this->set_state_(State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); break; @@ -146,15 +173,26 @@ void MitsubishiCN105::did_transition_(State to) { } } +bool MitsubishiCN105::should_request_room_temperature_() const { + if (!this->is_room_temperature_enabled()) { + return false; + } + + if (!this->last_room_temperature_update_ms_.has_value()) { + return true; + } + + return (get_loop_time_ms() - *this->last_room_temperature_update_ms_) >= this->room_temperature_min_interval_ms_; +} + void MitsubishiCN105::send_packet_(const uint8_t *packet, size_t len) { - dump_buffer_vv("TX", packet, len); + FrameParser::dump_buffer_vv("TX", packet, len); this->device_.write_array(packet, len); this->write_timeout_start_ms_ = get_loop_time_ms(); } void MitsubishiCN105::update_status_() { - ESP_LOGV(TAG, "Requesting status update, index=%u", this->status_msg_index_); - std::array<uint8_t, REQUEST_PAYLOAD_LEN> payload = {STATUS_MSG_TYPES[this->status_msg_index_]}; + std::array<uint8_t, REQUEST_PAYLOAD_LEN> payload = {this->current_status_msg_type_}; this->send_packet_(make_packet(PACKET_TYPE_STATUS_REQUEST, payload)); } @@ -163,67 +201,6 @@ void MitsubishiCN105::cancel_waiting_and_transition_to_(State state) { this->set_state_(state); } -bool MitsubishiCN105::read_incoming_bytes_() { - uint8_t watchdog = 64; - while (this->device_.available() > 0 && watchdog-- > 0) { - uint8_t &value = this->read_buffer_[this->read_pos_]; - if (!this->device_.read_byte(&value)) { - ESP_LOGW(TAG, "UART read failed while data available"); - return false; - } - - switch (++this->read_pos_) { - case 1: - if (value != PREAMBLE) { - this->reset_read_position_and_dump_buffer_("RX ignoring preamble"); - } - continue; - - case 2: - continue; - - case 3: - if (value != HEADER_BYTE_1) { - this->reset_read_position_and_dump_buffer_("RX invalid: header 1 mismatch"); - } - continue; - - case 4: - if (value != HEADER_BYTE_2) { - this->reset_read_position_and_dump_buffer_("RX invalid: header 2 mismatch"); - } - continue; - - case HEADER_LEN: - static_assert(READ_BUFFER_SIZE > HEADER_LEN); - if (this->read_buffer_[HEADER_LEN - 1] >= READ_BUFFER_SIZE - HEADER_LEN) { - this->reset_read_position_and_dump_buffer_("RX invalid: payload too large"); - } - continue; - - default: - break; - } - - const size_t len_without_checksum = HEADER_LEN + static_cast<size_t>(this->read_buffer_[HEADER_LEN - 1]); - if (this->read_pos_ <= len_without_checksum) { - continue; - } - - if (checksum(this->read_buffer_, len_without_checksum) != value) { - this->reset_read_position_and_dump_buffer_("RX invalid: checksum mismatch"); - continue; - } - - bool processed = this->process_rx_packet_(this->read_buffer_[1], this->read_buffer_ + HEADER_LEN, - len_without_checksum - HEADER_LEN); - this->reset_read_position_and_dump_buffer_("RX"); - return processed; - } - - return false; -} - bool MitsubishiCN105::process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len) { switch (type) { case PACKET_TYPE_CONNECT_RESPONSE: @@ -251,11 +228,19 @@ bool MitsubishiCN105::process_status_packet_(const uint8_t *payload, size_t len) return false; } - if (msg_type == STATUS_MSG_TYPES[this->status_msg_index_]) { + if (msg_type == this->current_status_msg_type_) { this->set_state_(State::STATUS_UPDATED); } - return previous != this->status_ && this->is_status_initialized(); + bool changed = previous.power_on != this->status_.power_on || previous.mode != this->status_.mode || + previous.fan_mode != this->status_.fan_mode || + previous.target_temperature != this->status_.target_temperature; + + if (this->is_room_temperature_enabled()) { + changed |= previous.room_temperature != this->status_.room_temperature; + } + + return changed && this->is_status_initialized(); } bool MitsubishiCN105::parse_status_payload_(uint8_t msg_type, const uint8_t *payload, size_t len) { @@ -278,6 +263,9 @@ bool MitsubishiCN105::parse_status_settings_(const uint8_t *payload, size_t len) return false; } + const bool i_see = payload[3] > 0x08; + this->status_.mode = lookup(PROTOCOL_MODE_MAP, payload[3] - (i_see ? 0x08 : 0)).value_or(Mode::UNKNOWN); + this->status_.fan_mode = lookup(PROTOCOL_FAN_MODE_MAP, payload[5]).value_or(FanMode::UNKNOWN); this->status_.power_on = payload[2] != 0; this->status_.target_temperature = decode_temperature(-payload[4], payload[10], 31); @@ -291,21 +279,11 @@ bool MitsubishiCN105::parse_status_room_temperature_(const uint8_t *payload, siz } this->status_.room_temperature = decode_temperature(payload[2], payload[5], 10); + this->last_room_temperature_update_ms_ = get_loop_time_ms(); + return true; } -void MitsubishiCN105::reset_read_position_and_dump_buffer_(const char *prefix) { - dump_buffer_vv(prefix, this->read_buffer_, this->read_pos_); - this->read_pos_ = 0; -} - -void MitsubishiCN105::dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len) { -#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE - char buf[format_hex_pretty_size(READ_BUFFER_SIZE)]; - ESP_LOGVV(TAG, "%s (%zu): %s", prefix, len, format_hex_pretty_to(buf, data, len)); -#endif -} - const LogString *MitsubishiCN105::state_to_string(State state) { switch (state) { case State::NOT_CONNECTED: @@ -328,4 +306,79 @@ const LogString *MitsubishiCN105::state_to_string(State state) { return LOG_STR("Unknown"); } +template<typename Callback> +bool MitsubishiCN105::FrameParser::read_and_parse(uart::UARTDevice &device, Callback &&callback) { + uint8_t watchdog = 64; + while (device.available() > 0 && watchdog-- > 0) { + uint8_t &value = this->read_buffer_[this->read_pos_]; + if (!device.read_byte(&value)) { + ESP_LOGW(TAG, "UART read failed while data available"); + return false; + } + + switch (++this->read_pos_) { + case 1: + if (value != PREAMBLE) { + this->reset_and_dump_buffer_("RX ignoring preamble"); + } + continue; + + case 2: + continue; + + case 3: + if (value != HEADER_BYTE_1) { + this->reset_and_dump_buffer_("RX invalid: header 1 mismatch"); + } + continue; + + case 4: + if (value != HEADER_BYTE_2) { + this->reset_and_dump_buffer_("RX invalid: header 2 mismatch"); + } + continue; + + case HEADER_LEN: + static_assert(READ_BUFFER_SIZE > HEADER_LEN); + if (this->read_buffer_[HEADER_LEN - 1] >= READ_BUFFER_SIZE - HEADER_LEN) { + this->reset_and_dump_buffer_("RX invalid: payload too large"); + } + continue; + + default: + break; + } + + const size_t len_without_checksum = HEADER_LEN + static_cast<size_t>(this->read_buffer_[HEADER_LEN - 1]); + if (this->read_pos_ <= len_without_checksum) { + continue; + } + + if (checksum(this->read_buffer_, len_without_checksum) != value) { + this->reset_and_dump_buffer_("RX invalid: checksum mismatch"); + continue; + } + + dump_buffer_vv("RX", this->read_buffer_, this->read_pos_); + const bool processed = + callback(this->read_buffer_[1], this->read_buffer_ + HEADER_LEN, len_without_checksum - HEADER_LEN); + this->read_pos_ = 0; + return processed; + } + + return false; +} + +void MitsubishiCN105::FrameParser::reset_and_dump_buffer_(const char *prefix) { + dump_buffer_vv(prefix, this->read_buffer_, this->read_pos_); + this->read_pos_ = 0; +} + +void MitsubishiCN105::FrameParser::dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len) { +#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE + char buf[format_hex_pretty_size(READ_BUFFER_SIZE)]; + ESP_LOGVV(TAG, "%s (%zu): %s", prefix, len, format_hex_pretty_to(buf, data, len)); +#endif +} + } // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h index d43904b313..6a29763696 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h @@ -9,11 +9,30 @@ uint32_t get_loop_time_ms(); class MitsubishiCN105 { public: - struct Status { - bool operator==(const Status &) const = default; + enum class Mode : uint8_t { + HEAT, + DRY, + COOL, + FAN_ONLY, + AUTO, + UNKNOWN, + }; + enum class FanMode : uint8_t { + AUTO, + QUIET, + SPEED_1, + SPEED_2, + SPEED_3, + SPEED_4, + UNKNOWN, + }; + + struct Status { bool power_on{false}; float target_temperature{NAN}; + Mode mode{Mode::UNKNOWN}; + FanMode fan_mode{FanMode::UNKNOWN}; float room_temperature{NAN}; }; @@ -25,8 +44,17 @@ class MitsubishiCN105 { uint32_t get_update_interval() const { return this->update_interval_ms_; } void set_update_interval(uint32_t interval_ms) { this->update_interval_ms_ = interval_ms; } + uint32_t get_room_temperature_min_interval() const { return this->room_temperature_min_interval_ms_; } + bool is_room_temperature_enabled() const { return this->room_temperature_min_interval_ms_ != SCHEDULER_DONT_RUN; } + void set_room_temperature_min_interval(uint32_t interval_ms) { + this->room_temperature_min_interval_ms_ = interval_ms; + } + const Status &status() const { return this->status_; } - bool is_status_initialized() const { return !std::isnan(status_.room_temperature); } + bool is_status_initialized() const { + return this->is_room_temperature_enabled() ? !std::isnan(this->status_.room_temperature) + : !std::isnan(this->status_.target_temperature); + } protected: enum class State : uint8_t { @@ -40,35 +68,46 @@ class MitsubishiCN105 { READ_TIMEOUT }; + class FrameParser { + public: + template<typename Callback> bool read_and_parse(uart::UARTDevice &device, Callback &&callback); + void reset() { read_pos_ = 0; } + static void dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len); + + protected: + void reset_and_dump_buffer_(const char *prefix); + + private: + static constexpr size_t READ_BUFFER_SIZE = 32; + uint8_t read_buffer_[READ_BUFFER_SIZE]; + uint8_t read_pos_{0}; + }; + void set_state_(State new_state); void did_transition_(State to); - bool read_incoming_bytes_(); bool process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len); bool process_status_packet_(const uint8_t *payload, size_t len); bool parse_status_payload_(uint8_t msg_type, const uint8_t *payload, size_t len); bool parse_status_settings_(const uint8_t *payload, size_t len); bool parse_status_room_temperature_(const uint8_t *payload, size_t len); - void reset_read_position_and_dump_buffer_(const char *prefix); void send_packet_(const uint8_t *packet, size_t len); void update_status_(); void cancel_waiting_and_transition_to_(State state); + bool should_request_room_temperature_() const; template<typename T> void send_packet_(const T &packet) { this->send_packet_(packet.data(), packet.size()); } static bool should_transition(State from, State to); static const LogString *state_to_string(State state); - static void dump_buffer_vv(const char *prefix, const uint8_t *data, size_t len); uart::UARTDevice &device_; uint32_t update_interval_ms_{1000}; + uint32_t room_temperature_min_interval_ms_{60000}; std::optional<uint32_t> write_timeout_start_ms_; std::optional<uint32_t> status_update_start_ms_; + std::optional<uint32_t> last_room_temperature_update_ms_; Status status_{}; State state_{State::NOT_CONNECTED}; - uint8_t status_msg_index_{0}; - - private: - static constexpr size_t READ_BUFFER_SIZE = 32; - uint8_t read_buffer_[READ_BUFFER_SIZE]; - uint8_t read_pos_{0}; + uint8_t current_status_msg_type_{0}; + FrameParser frame_parser_; }; } // namespace esphome::mitsubishi_cn105 diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp index 55fc23c449..21ce272993 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp @@ -6,8 +6,42 @@ namespace esphome::mitsubishi_cn105 { static const char *const TAG = "mitsubishi_cn105.climate"; +static constexpr std::array MODE_MAP{ + std::pair{MitsubishiCN105::Mode::AUTO, climate::CLIMATE_MODE_AUTO}, + std::pair{MitsubishiCN105::Mode::HEAT, climate::CLIMATE_MODE_HEAT}, + std::pair{MitsubishiCN105::Mode::DRY, climate::CLIMATE_MODE_DRY}, + std::pair{MitsubishiCN105::Mode::COOL, climate::CLIMATE_MODE_COOL}, + std::pair{MitsubishiCN105::Mode::FAN_ONLY, climate::CLIMATE_MODE_FAN_ONLY}, +}; + +static constexpr std::array FAN_MODE_MAP{ + std::pair{MitsubishiCN105::FanMode::AUTO, climate::CLIMATE_FAN_AUTO}, + std::pair{MitsubishiCN105::FanMode::QUIET, climate::CLIMATE_FAN_QUIET}, + std::pair{MitsubishiCN105::FanMode::SPEED_1, climate::CLIMATE_FAN_LOW}, + std::pair{MitsubishiCN105::FanMode::SPEED_2, climate::CLIMATE_FAN_MEDIUM}, + std::pair{MitsubishiCN105::FanMode::SPEED_3, climate::CLIMATE_FAN_MIDDLE}, + std::pair{MitsubishiCN105::FanMode::SPEED_4, climate::CLIMATE_FAN_HIGH}, +}; + +template<typename A, typename B, std::size_t N> +static bool map_lookup(const std::array<std::pair<A, B>, N> &map, A key, B &out) { + for (const auto &[from, to] : map) { + if (from == key) { + out = to; + return true; + } + } + return false; +} + void MitsubishiCN105Climate::dump_config() { LOG_CLIMATE("", "Mitsubishi CN105 Climate", this); + if (this->hp_.is_room_temperature_enabled()) { + ESP_LOGCONFIG(TAG, " Current temperature min interval: %" PRIu32 " ms", + this->hp_.get_room_temperature_min_interval()); + } else { + ESP_LOGCONFIG(TAG, " Current temperature: disabled"); + } ESP_LOGCONFIG(TAG, " Update interval: %" PRIu32 " ms\n" " UART: baud_rate=%" PRIu32 " data_bits=%u parity=%s stop_bits=%u", @@ -26,12 +60,32 @@ void MitsubishiCN105Climate::loop() { climate::ClimateTraits MitsubishiCN105Climate::traits() { climate::ClimateTraits traits; - traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE); + traits.set_supported_modes({ + climate::CLIMATE_MODE_OFF, + climate::CLIMATE_MODE_COOL, + climate::CLIMATE_MODE_HEAT, + climate::CLIMATE_MODE_DRY, + climate::CLIMATE_MODE_FAN_ONLY, + climate::CLIMATE_MODE_AUTO, + }); + + traits.set_supported_fan_modes({ + climate::CLIMATE_FAN_AUTO, + climate::CLIMATE_FAN_QUIET, + climate::CLIMATE_FAN_LOW, + climate::CLIMATE_FAN_MEDIUM, + climate::CLIMATE_FAN_MIDDLE, + climate::CLIMATE_FAN_HIGH, + }); traits.set_visual_min_temperature(16.0f); traits.set_visual_max_temperature(31.0f); traits.set_visual_temperature_step(1.0f); - traits.set_visual_current_temperature_step(0.5f); + + if (this->hp_.is_room_temperature_enabled()) { + traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE); + traits.set_visual_current_temperature_step(0.5f); + } return traits; } @@ -42,7 +96,25 @@ void MitsubishiCN105Climate::apply_values_() { const auto &status = this->hp_.status(); this->target_temperature = status.target_temperature; - this->current_temperature = status.room_temperature; + + if (this->hp_.is_room_temperature_enabled()) { + this->current_temperature = status.room_temperature; + } + + if (status.power_on) { + if (!map_lookup(MODE_MAP, status.mode, this->mode)) { + ESP_LOGD(TAG, "Unable to map mode"); + } + } else { + this->mode = climate::CLIMATE_MODE_OFF; + } + + climate::ClimateFanMode fan_mode; + if (map_lookup(FAN_MODE_MAP, status.fan_mode, fan_mode)) { + this->fan_mode = fan_mode; + } else { + ESP_LOGD(TAG, "Unable to map fan mode"); + } this->publish_state(); } diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h index da8f8d8d0a..eee4c20966 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.h @@ -19,6 +19,7 @@ class MitsubishiCN105Climate : public climate::Climate, public Component, public void control(const climate::ClimateCall &call) override; void set_update_interval(uint32_t ms) { hp_.set_update_interval(ms); } + void set_current_temperature_min_interval(uint32_t ms) { hp_.set_room_temperature_min_interval(ms); } protected: void apply_values_(); diff --git a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp index 5b4f84623e..f26b0d82b6 100644 --- a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp +++ b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp @@ -60,6 +60,8 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) { // Settings should still have initial values EXPECT_FALSE(ctx.sut.status().power_on); EXPECT_THAT(ctx.sut.status().target_temperature, ::testing::IsNan()); + EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::UNKNOWN); + EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::UNKNOWN); ctx.sut.set_current_time(300); ASSERT_FALSE(ctx.sut.update()); @@ -68,6 +70,8 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) { // Check settings that we just read from received package EXPECT_FALSE(ctx.sut.status().power_on); EXPECT_EQ(ctx.sut.status().target_temperature, 24.0f); + EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::AUTO); + EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::AUTO); // Now fetch room temperature (0x03) EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS); @@ -260,24 +264,28 @@ TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedA) { auto ctx = TestContext{}; ctx.uart.push_rx( - {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56}); + {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x01, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55}); ctx.sut.update(); EXPECT_TRUE(ctx.sut.status().power_on); EXPECT_EQ(ctx.sut.status().target_temperature, 26.0f); + EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::COOL); + EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::QUIET); } TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) { auto ctx = TestContext{}; ctx.uart.push_rx( - {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xB7}); + {0xFC, 0x62, 0x01, 0x30, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xAD}); ctx.sut.update(); EXPECT_FALSE(ctx.sut.status().power_on); EXPECT_EQ(ctx.sut.status().target_temperature, 18.5f); + EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::FAN_ONLY); + EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::SPEED_4); } TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedA) { From 1c97954b4734781097ca1aced2dbf3c1e1ec6887 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Apr 2026 18:42:17 -1000 Subject: [PATCH 1957/2030] Bump aioesphomeapi from 44.9.0 to 44.9.1 (#15470) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9c63cdee27..7e6a2fe4b5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.2 esphome-dashboard==20260210.0 -aioesphomeapi==44.9.0 +aioesphomeapi==44.9.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 2f2b7e42ba1dca11bde1f07fa9e52b175d07b85f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 5 Apr 2026 21:15:02 -1000 Subject: [PATCH 1958/2030] Bump aioesphomeapi from 44.9.1 to 44.11.1 (#15471) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7e6a2fe4b5..db4a2b19e0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.2 esphome-dashboard==20260210.0 -aioesphomeapi==44.9.1 +aioesphomeapi==44.11.1 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 02185fb4f4b227319c5408a981f0f68f1a5f8d57 Mon Sep 17 00:00:00 2001 From: Boris Krivonog <boris.krivonog@inova.si> Date: Mon, 6 Apr 2026 21:59:18 +0200 Subject: [PATCH 1959/2030] [mitsubishi_cn105] Add climate component for Mitsubishi A/C units with CN105 connector (Part 5) (#15483) --- .../mitsubishi_cn105/mitsubishi_cn105.cpp | 150 ++++++++++++++++-- .../mitsubishi_cn105/mitsubishi_cn105.h | 27 ++++ .../mitsubishi_cn105_climate.cpp | 39 ++++- .../climate/mitsubishi_cn105_tests.cpp | 101 +++++++++++- tests/components/mitsubishi_cn105/common.h | 2 + 5 files changed, 298 insertions(+), 21 deletions(-) diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp index 3b29f66bf1..1a35495618 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.cpp @@ -1,4 +1,5 @@ #include <array> +#include <cmath> #include <numeric> #include "mitsubishi_cn105.h" @@ -8,6 +9,8 @@ static const char *const TAG = "mitsubishi_cn105.driver"; static constexpr uint32_t WRITE_TIMEOUT_MS = 2000; +static constexpr uint8_t TARGET_TEMPERATURE_ENC_A_OFFSET = 31; + static constexpr size_t REQUEST_PAYLOAD_LEN = 0x10; static constexpr size_t HEADER_LEN = 5; static constexpr uint8_t PREAMBLE = 0xFC; @@ -23,6 +26,9 @@ static constexpr uint8_t PACKET_TYPE_STATUS_RESPONSE = 0x62; static constexpr uint8_t STATUS_MSG_SETTINGS = 0x02; static constexpr uint8_t STATUS_MSG_ROOM_TEMP = 0x03; +static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_REQUEST = 0x41; +static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_RESPONSE = 0x61; + static constexpr std::array<std::optional<MitsubishiCN105::Mode>, 9> PROTOCOL_MODE_MAP = { std::nullopt, // 0x00 MitsubishiCN105::Mode::HEAT, // 0x01 @@ -50,6 +56,18 @@ static constexpr std::optional<T> lookup(const std::array<std::optional<T>, N> & return (value < N) ? table[value] : std::nullopt; } +template<typename T, size_t N> +static constexpr bool reverse_lookup(const std::array<std::optional<T>, N> &table, T value, uint8_t &placeholder) { + for (size_t i = 0; i < N; ++i) { + const auto &table_value = table[i]; + if (table_value.has_value() && table_value == value) { + placeholder = i; + return true; + } + } + return false; +} + static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) { return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0})); } @@ -72,10 +90,16 @@ static constexpr auto CONNECT_PACKET = make_packet(PACKET_TYPE_CONNECT_REQUEST, void MitsubishiCN105::initialize() { this->set_state_(State::CONNECTING); } bool MitsubishiCN105::update() { - if (const auto start = this->status_update_start_ms_; - start && (get_loop_time_ms() - *start) >= this->update_interval_ms_) { - this->cancel_waiting_and_transition_to_(State::UPDATING_STATUS); - return false; + if (const auto start = this->status_update_start_ms_) { + if (this->pending_updates_.any()) { + this->cancel_waiting_and_transition_to_(State::APPLYING_SETTINGS); + return false; + } + + if ((get_loop_time_ms() - *start) >= this->update_interval_ms_) { + this->cancel_waiting_and_transition_to_(State::UPDATING_STATUS); + return false; + } } if (const auto start = this->write_timeout_start_ms_; start && (get_loop_time_ms() - *start) >= WRITE_TIMEOUT_MS) { @@ -118,13 +142,19 @@ bool MitsubishiCN105::should_transition(State from, State to) { return from == State::UPDATING_STATUS; case State::SCHEDULE_NEXT_STATUS_UPDATE: - return from == State::STATUS_UPDATED; + return from == State::STATUS_UPDATED || from == State::SETTINGS_APPLIED; case State::WAITING_FOR_SCHEDULED_STATUS_UPDATE: return from == State::SCHEDULE_NEXT_STATUS_UPDATE; + case State::APPLYING_SETTINGS: + return from == State::WAITING_FOR_SCHEDULED_STATUS_UPDATE || from == State::STATUS_UPDATED; + + case State::SETTINGS_APPLIED: + return from == State::APPLYING_SETTINGS; + case State::READ_TIMEOUT: - return from == State::UPDATING_STATUS || from == State::CONNECTING; + return from == State::UPDATING_STATUS || from == State::APPLYING_SETTINGS || from == State::CONNECTING; default: return false; @@ -149,7 +179,9 @@ void MitsubishiCN105::did_transition_(State to) { case State::STATUS_UPDATED: { this->write_timeout_start_ms_.reset(); - if (this->current_status_msg_type_ == STATUS_MSG_SETTINGS && this->should_request_room_temperature_()) { + if (this->pending_updates_.any() && this->is_status_initialized()) { + this->set_state_(State::APPLYING_SETTINGS); + } else if (this->current_status_msg_type_ == STATUS_MSG_SETTINGS && this->should_request_room_temperature_()) { this->current_status_msg_type_ = STATUS_MSG_ROOM_TEMP; this->set_state_(State::UPDATING_STATUS); } else { @@ -164,6 +196,16 @@ void MitsubishiCN105::did_transition_(State to) { this->set_state_(State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); break; + case State::APPLYING_SETTINGS: + this->apply_settings_(); + this->pending_updates_.clear(); + break; + + case State::SETTINGS_APPLIED: + this->write_timeout_start_ms_.reset(); + this->set_state_(State::SCHEDULE_NEXT_STATUS_UPDATE); + break; + case State::READ_TIMEOUT: this->set_state_(State::CONNECTING); break; @@ -210,6 +252,10 @@ bool MitsubishiCN105::process_rx_packet_(uint8_t type, const uint8_t *payload, s case PACKET_TYPE_STATUS_RESPONSE: return this->process_status_packet_(payload, len); + case PACKET_TYPE_WRITE_SETTINGS_RESPONSE: + this->set_state_(State::SETTINGS_APPLIED); + return false; + default: ESP_LOGVV(TAG, "RX unknown packet type 0x%02X", type); return false; @@ -263,11 +309,23 @@ bool MitsubishiCN105::parse_status_settings_(const uint8_t *payload, size_t len) return false; } - const bool i_see = payload[3] > 0x08; - this->status_.mode = lookup(PROTOCOL_MODE_MAP, payload[3] - (i_see ? 0x08 : 0)).value_or(Mode::UNKNOWN); - this->status_.fan_mode = lookup(PROTOCOL_FAN_MODE_MAP, payload[5]).value_or(FanMode::UNKNOWN); - this->status_.power_on = payload[2] != 0; - this->status_.target_temperature = decode_temperature(-payload[4], payload[10], 31); + if (!this->pending_updates_.has(UpdateFlag::POWER)) { + this->status_.power_on = payload[2] != 0; + } + + this->use_temperature_encoding_b_ = payload[10] != 0; + if (!this->pending_updates_.has(UpdateFlag::TEMPERATURE)) { + this->status_.target_temperature = decode_temperature(-payload[4], payload[10], TARGET_TEMPERATURE_ENC_A_OFFSET); + } + + if (!this->pending_updates_.has(UpdateFlag::MODE)) { + const bool i_see = payload[3] > 0x08; + this->status_.mode = lookup(PROTOCOL_MODE_MAP, payload[3] - (i_see ? 0x08 : 0)).value_or(Mode::UNKNOWN); + } + + if (!this->pending_updates_.has(UpdateFlag::FAN)) { + this->status_.fan_mode = lookup(PROTOCOL_FAN_MODE_MAP, payload[5]).value_or(FanMode::UNKNOWN); + } return true; } @@ -284,6 +342,70 @@ bool MitsubishiCN105::parse_status_room_temperature_(const uint8_t *payload, siz return true; } +void MitsubishiCN105::set_power(bool power_on) { + this->status_.power_on = power_on; + this->pending_updates_.set(UpdateFlag::POWER); +} + +void MitsubishiCN105::set_target_temperature(float target_temperature) { + if (target_temperature < 16 || target_temperature > 31) { + ESP_LOGD(TAG, "Setting temperature out-of-range: %.1f", target_temperature); + return; + } + this->status_.target_temperature = std::round(target_temperature); + this->pending_updates_.set(UpdateFlag::TEMPERATURE); +} + +void MitsubishiCN105::set_mode(Mode mode) { + uint8_t placeholder; + if (!reverse_lookup(PROTOCOL_MODE_MAP, mode, placeholder)) { + ESP_LOGD(TAG, "Setting invalid mode: %u", static_cast<uint8_t>(mode)); + return; + } + this->status_.mode = mode; + this->pending_updates_.set(UpdateFlag::MODE); +} + +void MitsubishiCN105::set_fan_mode(FanMode fan_mode) { + uint8_t placeholder; + if (!reverse_lookup(PROTOCOL_FAN_MODE_MAP, fan_mode, placeholder)) { + ESP_LOGD(TAG, "Setting invalid fan mode: %u", static_cast<uint8_t>(fan_mode)); + return; + } + this->status_.fan_mode = fan_mode; + this->pending_updates_.set(UpdateFlag::FAN); +} + +void MitsubishiCN105::apply_settings_() { + std::array<uint8_t, REQUEST_PAYLOAD_LEN> payload = {0x01}; + + if (this->pending_updates_.has(UpdateFlag::POWER)) { + payload[1] |= 0x01; + payload[3] = this->status_.power_on ? 0x01 : 0x00; + } + + if (this->pending_updates_.has(UpdateFlag::TEMPERATURE)) { + payload[1] |= 0x04; + if (this->use_temperature_encoding_b_) { + payload[14] = static_cast<uint8_t>(this->status_.target_temperature * 2.0f + 128.0f); + } else { + payload[5] = static_cast<uint8_t>(TARGET_TEMPERATURE_ENC_A_OFFSET - this->status_.target_temperature); + } + } + + if (this->pending_updates_.has(UpdateFlag::MODE) && + reverse_lookup(PROTOCOL_MODE_MAP, this->status_.mode, payload[4])) { + payload[1] |= 0x02; + } + + if (this->pending_updates_.has(UpdateFlag::FAN) && + reverse_lookup(PROTOCOL_FAN_MODE_MAP, this->status_.fan_mode, payload[6])) { + payload[1] |= 0x08; + } + + this->send_packet_(make_packet(PACKET_TYPE_WRITE_SETTINGS_REQUEST, payload)); +} + const LogString *MitsubishiCN105::state_to_string(State state) { switch (state) { case State::NOT_CONNECTED: @@ -300,6 +422,10 @@ const LogString *MitsubishiCN105::state_to_string(State state) { return LOG_STR("ScheduleNextStatusUpdate"); case State::WAITING_FOR_SCHEDULED_STATUS_UPDATE: return LOG_STR("WaitingForScheduledStatusUpdate"); + case State::APPLYING_SETTINGS: + return LOG_STR("ApplyingSettings"); + case State::SETTINGS_APPLIED: + return LOG_STR("SettingsApplied"); case State::READ_TIMEOUT: return LOG_STR("ReadTimeout"); } diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h index 6a29763696..68d98bf6d9 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105.h @@ -56,6 +56,11 @@ class MitsubishiCN105 { : !std::isnan(this->status_.target_temperature); } + void set_power(bool power_on); + void set_target_temperature(float target_temperature); + void set_mode(Mode mode); + void set_fan_mode(FanMode fan_mode); + protected: enum class State : uint8_t { NOT_CONNECTED, @@ -65,6 +70,8 @@ class MitsubishiCN105 { STATUS_UPDATED, SCHEDULE_NEXT_STATUS_UPDATE, WAITING_FOR_SCHEDULED_STATUS_UPDATE, + APPLYING_SETTINGS, + SETTINGS_APPLIED, READ_TIMEOUT }; @@ -83,6 +90,23 @@ class MitsubishiCN105 { uint8_t read_pos_{0}; }; + enum class UpdateFlag : uint8_t { + TEMPERATURE = 1 << 0, + POWER = 1 << 1, + MODE = 1 << 2, + FAN = 1 << 3, + }; + + struct UpdateFlags { + void set(UpdateFlag f) { flags_ |= static_cast<uint8_t>(f); } + void clear() { flags_ = 0; } + bool any() const { return flags_ != 0; } + bool has(UpdateFlag f) const { return (flags_ & static_cast<uint8_t>(f)) != 0; } + + protected: + uint8_t flags_{0}; + }; + void set_state_(State new_state); void did_transition_(State to); bool process_rx_packet_(uint8_t type, const uint8_t *payload, size_t len); @@ -94,6 +118,7 @@ class MitsubishiCN105 { void update_status_(); void cancel_waiting_and_transition_to_(State state); bool should_request_room_temperature_() const; + void apply_settings_(); template<typename T> void send_packet_(const T &packet) { this->send_packet_(packet.data(), packet.size()); } static bool should_transition(State from, State to); static const LogString *state_to_string(State state); @@ -106,6 +131,8 @@ class MitsubishiCN105 { std::optional<uint32_t> last_room_temperature_update_ms_; Status status_{}; State state_{State::NOT_CONNECTED}; + UpdateFlags pending_updates_; + bool use_temperature_encoding_b_{false}; uint8_t current_status_msg_type_{0}; FrameParser frame_parser_; }; diff --git a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp index 21ce272993..40ddb88a79 100644 --- a/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp +++ b/esphome/components/mitsubishi_cn105/mitsubishi_cn105_climate.cpp @@ -34,6 +34,22 @@ static bool map_lookup(const std::array<std::pair<A, B>, N> &map, A key, B &out) return false; } +template<typename Left, typename Right, std::size_t N> +static constexpr std::optional<Left> reverse_map_lookup(const std::array<std::pair<Left, Right>, N> &map, Right key) { + for (const auto &entry : map) { + if (entry.second == key) { + return entry.first; + } + } + return std::nullopt; +} + +template<typename Left, typename Right, std::size_t N> +static constexpr std::optional<Left> reverse_map_lookup(const std::array<std::pair<Left, Right>, N> &map, + const std::optional<Right> &key) { + return key.has_value() ? reverse_map_lookup(map, *key) : std::nullopt; +} + void MitsubishiCN105Climate::dump_config() { LOG_CLIMATE("", "Mitsubishi CN105 Climate", this); if (this->hp_.is_room_temperature_enabled()) { @@ -90,7 +106,28 @@ climate::ClimateTraits MitsubishiCN105Climate::traits() { return traits; } -void MitsubishiCN105Climate::control(const climate::ClimateCall &call) {} +void MitsubishiCN105Climate::control(const climate::ClimateCall &call) { + if (const auto target_temperature = call.get_target_temperature()) { + this->hp_.set_target_temperature(*target_temperature); + } + + if (const auto mode = call.get_mode()) { + if (*mode == climate::CLIMATE_MODE_OFF) { + this->hp_.set_power(false); + } else if (const auto mapped = reverse_map_lookup(MODE_MAP, *mode)) { + this->hp_.set_power(true); + this->hp_.set_mode(*mapped); + } + } + + if (const auto fan_mode = reverse_map_lookup(FAN_MODE_MAP, call.get_fan_mode())) { + this->hp_.set_fan_mode(*fan_mode); + } + + if (this->hp_.is_status_initialized()) { + this->apply_values_(); + } +} void MitsubishiCN105Climate::apply_values_() { const auto &status = this->hp_.status(); diff --git a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp index f26b0d82b6..7846a31193 100644 --- a/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp +++ b/tests/components/mitsubishi_cn105/climate/mitsubishi_cn105_tests.cpp @@ -60,8 +60,8 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) { // Settings should still have initial values EXPECT_FALSE(ctx.sut.status().power_on); EXPECT_THAT(ctx.sut.status().target_temperature, ::testing::IsNan()); - EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::UNKNOWN); - EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::UNKNOWN); + EXPECT_EQ(ctx.sut.status().mode, MitsubishiCN105::Mode::UNKNOWN); + EXPECT_EQ(ctx.sut.status().fan_mode, MitsubishiCN105::FanMode::UNKNOWN); ctx.sut.set_current_time(300); ASSERT_FALSE(ctx.sut.update()); @@ -70,8 +70,8 @@ TEST(MitsubishiCN105Tests, ConnectAndUpdateStatus) { // Check settings that we just read from received package EXPECT_FALSE(ctx.sut.status().power_on); EXPECT_EQ(ctx.sut.status().target_temperature, 24.0f); - EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::AUTO); - EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::AUTO); + EXPECT_EQ(ctx.sut.status().mode, MitsubishiCN105::Mode::AUTO); + EXPECT_EQ(ctx.sut.status().fan_mode, MitsubishiCN105::FanMode::AUTO); // Now fetch room temperature (0x03) EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::UPDATING_STATUS); @@ -269,9 +269,10 @@ TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedA) { ctx.sut.update(); EXPECT_TRUE(ctx.sut.status().power_on); + EXPECT_FALSE(ctx.sut.use_temperature_encoding_b_); EXPECT_EQ(ctx.sut.status().target_temperature, 26.0f); - EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::COOL); - EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::QUIET); + EXPECT_EQ(ctx.sut.status().mode, MitsubishiCN105::Mode::COOL); + EXPECT_EQ(ctx.sut.status().fan_mode, MitsubishiCN105::FanMode::QUIET); } TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) { @@ -283,9 +284,10 @@ TEST(MitsubishiCN105Tests, DecodeStatusSettingsPackageTempEncodedB) { ctx.sut.update(); EXPECT_FALSE(ctx.sut.status().power_on); + EXPECT_TRUE(ctx.sut.use_temperature_encoding_b_); EXPECT_EQ(ctx.sut.status().target_temperature, 18.5f); - EXPECT_EQ(ctx.sut.status().mode, TestableMitsubishiCN105::Mode::FAN_ONLY); - EXPECT_EQ(ctx.sut.status().fan_mode, TestableMitsubishiCN105::FanMode::SPEED_4); + EXPECT_EQ(ctx.sut.status().mode, MitsubishiCN105::Mode::FAN_ONLY); + EXPECT_EQ(ctx.sut.status().fan_mode, MitsubishiCN105::FanMode::SPEED_4); } TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedA) { @@ -308,4 +310,87 @@ TEST(MitsubishiCN105Tests, DecodeStatusRoomTempPackageTempEncodedB) { EXPECT_EQ(ctx.sut.status().room_temperature, 30.0f); } +TEST(MitsubishiCN105Tests, ApplySettingsPowerOn) { + auto ctx = TestContext{}; + + ctx.sut.set_power(true); + ctx.sut.apply_settings(); + + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B)); +} + +TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedA) { + auto ctx = TestContext{}; + + ctx.sut.set_target_temperature(23.0f); + ctx.sut.apply_settings(); + + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71)); +} + +TEST(MitsubishiCN105Tests, ApplySettingsTemperatureEncodedB) { + auto ctx = TestContext{}; + + ctx.sut.use_temperature_encoding_b_ = true; + ctx.sut.set_target_temperature(26.0f); + ctx.sut.apply_settings(); + + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x00, 0xC5)); +} + +TEST(MitsubishiCN105Tests, ApplyModeCool) { + auto ctx = TestContext{}; + + ctx.sut.set_mode(MitsubishiCN105::Mode::COOL); + ctx.sut.apply_settings(); + + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x02, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78)); +} + +TEST(MitsubishiCN105Tests, ApplyFanModeSpeed1) { + auto ctx = TestContext{}; + + ctx.sut.set_fan_mode(MitsubishiCN105::FanMode::SPEED_1); + ctx.sut.apply_settings(); + + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73)); +} + +TEST(MitsubishiCN105Tests, WriteInterruptsWaitingForNextStatusUpdate) { + auto ctx = TestContext{}; + + // Waiting for next scheduled status update + ctx.sut.state_ = TestableMitsubishiCN105::State::STATUS_UPDATED; + ctx.sut.set_state(TestableMitsubishiCN105::State::SCHEDULE_NEXT_STATUS_UPDATE); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); + + // Nothing to do in update (rx empty, no timeout) + ASSERT_FALSE(ctx.sut.update()); + EXPECT_TRUE(ctx.uart.tx.empty()); + + // Write new values + ctx.sut.use_temperature_encoding_b_ = true; + ctx.sut.set_power(false); + ctx.sut.set_target_temperature(25.0f); + ctx.sut.set_mode(MitsubishiCN105::Mode::HEAT); + ctx.sut.set_fan_mode(MitsubishiCN105::FanMode::AUTO); + + // Waiting for next status update must be interrupted and new values send to AC + ASSERT_FALSE(ctx.sut.update()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::APPLYING_SETTINGS); + EXPECT_THAT(ctx.uart.tx, ::testing::ElementsAre(0xFC, 0x41, 0x01, 0x30, 0x10, 0x01, 0x0F, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x00, 0xBB)); + + // Write ACK response + ctx.uart.push_rx({0xFC, 0x61, 0x01, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E}); + ASSERT_FALSE(ctx.sut.update()); + EXPECT_EQ(ctx.sut.state_, TestableMitsubishiCN105::State::WAITING_FOR_SCHEDULED_STATUS_UPDATE); +} + } // namespace esphome::mitsubishi_cn105::testing diff --git a/tests/components/mitsubishi_cn105/common.h b/tests/components/mitsubishi_cn105/common.h index ed55c3dc0c..0862d64fa7 100644 --- a/tests/components/mitsubishi_cn105/common.h +++ b/tests/components/mitsubishi_cn105/common.h @@ -45,8 +45,10 @@ class TestableMitsubishiCN105 : public MitsubishiCN105 { using MitsubishiCN105::state_; using MitsubishiCN105::write_timeout_start_ms_; using MitsubishiCN105::status_update_start_ms_; + using MitsubishiCN105::use_temperature_encoding_b_; void set_state(State s) { this->set_state_(s); } + void apply_settings() { this->apply_settings_(); } static inline uint32_t test_loop_time_ms = 0; From dbd4e77d611cf259d21d04e830499902d7c3e22a Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:23:10 -0400 Subject: [PATCH 1960/2030] [pylontech] Remove unnecessary Component inheritance from sensor/text_sensor (#15482) --- esphome/components/pylontech/sensor/__init__.py | 2 +- esphome/components/pylontech/sensor/pylontech_sensor.h | 2 +- esphome/components/pylontech/text_sensor/__init__.py | 2 +- .../components/pylontech/text_sensor/pylontech_text_sensor.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/pylontech/sensor/__init__.py b/esphome/components/pylontech/sensor/__init__.py index 716cc1001a..52f2679b70 100644 --- a/esphome/components/pylontech/sensor/__init__.py +++ b/esphome/components/pylontech/sensor/__init__.py @@ -18,7 +18,7 @@ from esphome.const import ( from .. import CONF_BATTERY, CONF_PYLONTECH_ID, PYLONTECH_COMPONENT_SCHEMA, pylontech_ns -PylontechSensor = pylontech_ns.class_("PylontechSensor", cg.Component) +PylontechSensor = pylontech_ns.class_("PylontechSensor") CONF_COULOMB = "coulomb" CONF_TEMPERATURE_LOW = "temperature_low" diff --git a/esphome/components/pylontech/sensor/pylontech_sensor.h b/esphome/components/pylontech/sensor/pylontech_sensor.h index 8986adc26c..25e71606a4 100644 --- a/esphome/components/pylontech/sensor/pylontech_sensor.h +++ b/esphome/components/pylontech/sensor/pylontech_sensor.h @@ -6,7 +6,7 @@ namespace esphome { namespace pylontech { -class PylontechSensor : public PylontechListener, public Component { +class PylontechSensor : public PylontechListener { public: PylontechSensor(int8_t bat_num); void dump_config() override; diff --git a/esphome/components/pylontech/text_sensor/__init__.py b/esphome/components/pylontech/text_sensor/__init__.py index 15741ea9d1..f68ca10374 100644 --- a/esphome/components/pylontech/text_sensor/__init__.py +++ b/esphome/components/pylontech/text_sensor/__init__.py @@ -5,7 +5,7 @@ from esphome.const import CONF_ID from .. import CONF_BATTERY, CONF_PYLONTECH_ID, PYLONTECH_COMPONENT_SCHEMA, pylontech_ns -PylontechTextSensor = pylontech_ns.class_("PylontechTextSensor", cg.Component) +PylontechTextSensor = pylontech_ns.class_("PylontechTextSensor") CONF_BASE_STATE = "base_state" CONF_VOLTAGE_STATE = "voltage_state" diff --git a/esphome/components/pylontech/text_sensor/pylontech_text_sensor.h b/esphome/components/pylontech/text_sensor/pylontech_text_sensor.h index a685512ed5..27a3993b3e 100644 --- a/esphome/components/pylontech/text_sensor/pylontech_text_sensor.h +++ b/esphome/components/pylontech/text_sensor/pylontech_text_sensor.h @@ -6,7 +6,7 @@ namespace esphome { namespace pylontech { -class PylontechTextSensor : public PylontechListener, public Component { +class PylontechTextSensor : public PylontechListener { public: PylontechTextSensor(int8_t bat_num); void dump_config() override; From a64f09a43f18af2627e7c9b6313e4869278b03d9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:29:59 -0400 Subject: [PATCH 1961/2030] [sprinkler][dfplayer][max6956][rf_bridge] Fix cg.templatable type mismatches (#15480) --- esphome/components/dfplayer/__init__.py | 14 +++++++------- esphome/components/max6956/__init__.py | 6 ++++-- esphome/components/rf_bridge/__init__.py | 4 ++-- esphome/components/sprinkler/__init__.py | 4 ++-- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index c49420f060..adc1913791 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -122,7 +122,7 @@ async def dfplayer_previous_to_code(config, action_id, template_arg, args): async def dfplayer_play_mp3_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - template_ = await cg.templatable(config[CONF_FILE], args, float) + template_ = await cg.templatable(config[CONF_FILE], args, cg.uint16) cg.add(var.set_file(template_)) return var @@ -143,10 +143,10 @@ async def dfplayer_play_mp3_to_code(config, action_id, template_arg, args): async def dfplayer_play_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - template_ = await cg.templatable(config[CONF_FILE], args, float) + template_ = await cg.templatable(config[CONF_FILE], args, cg.uint16) cg.add(var.set_file(template_)) if CONF_LOOP in config: - template_ = await cg.templatable(config[CONF_LOOP], args, float) + template_ = await cg.templatable(config[CONF_LOOP], args, cg.bool_) cg.add(var.set_loop(template_)) return var @@ -167,13 +167,13 @@ async def dfplayer_play_to_code(config, action_id, template_arg, args): async def dfplayer_play_folder_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - template_ = await cg.templatable(config[CONF_FOLDER], args, float) + template_ = await cg.templatable(config[CONF_FOLDER], args, cg.uint16) cg.add(var.set_folder(template_)) if CONF_FILE in config: - template_ = await cg.templatable(config[CONF_FILE], args, float) + template_ = await cg.templatable(config[CONF_FILE], args, cg.uint16) cg.add(var.set_file(template_)) if CONF_LOOP in config: - template_ = await cg.templatable(config[CONF_LOOP], args, float) + template_ = await cg.templatable(config[CONF_LOOP], args, cg.bool_) cg.add(var.set_loop(template_)) return var @@ -213,7 +213,7 @@ async def dfplayer_set_device_to_code(config, action_id, template_arg, args): async def dfplayer_set_volume_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) await cg.register_parented(var, config[CONF_ID]) - template_ = await cg.templatable(config[CONF_VOLUME], args, float) + template_ = await cg.templatable(config[CONF_VOLUME], args, cg.uint8) cg.add(var.set_volume(template_)) return var diff --git a/esphome/components/max6956/__init__.py b/esphome/components/max6956/__init__.py index be6390fc17..e9fae4cceb 100644 --- a/esphome/components/max6956/__init__.py +++ b/esphome/components/max6956/__init__.py @@ -117,7 +117,7 @@ async def max6956_pin_to_code(config): async def max6956_set_brightness_global_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) - template_ = await cg.templatable(config[CONF_BRIGHTNESS_GLOBAL], args, float) + template_ = await cg.templatable(config[CONF_BRIGHTNESS_GLOBAL], args, cg.uint8) cg.add(var.set_brightness_global(template_)) return var @@ -139,6 +139,8 @@ async def max6956_set_brightness_global_to_code(config, action_id, template_arg, async def max6956_set_brightness_mode_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) - template_ = await cg.templatable(config[CONF_BRIGHTNESS_MODE], args, float) + template_ = await cg.templatable( + config[CONF_BRIGHTNESS_MODE], args, MAX6956_CURRENTMODE + ) cg.add(var.set_brightness_mode(template_)) return var diff --git a/esphome/components/rf_bridge/__init__.py b/esphome/components/rf_bridge/__init__.py index c6eb1749c3..4ee1e7891f 100644 --- a/esphome/components/rf_bridge/__init__.py +++ b/esphome/components/rf_bridge/__init__.py @@ -185,9 +185,9 @@ RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA = cv.Schema( async def rf_bridge_send_advanced_code_to_code(config, action_id, template_args, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_args, paren) - template_ = await cg.templatable(config[CONF_LENGTH], args, cg.uint16) + template_ = await cg.templatable(config[CONF_LENGTH], args, cg.uint8) cg.add(var.set_length(template_)) - template_ = await cg.templatable(config[CONF_PROTOCOL], args, cg.uint16) + template_ = await cg.templatable(config[CONF_PROTOCOL], args, cg.uint8) cg.add(var.set_protocol(template_)) template_ = await cg.templatable(config[CONF_CODE], args, cg.std_string) cg.add(var.set_code(template_)) diff --git a/esphome/components/sprinkler/__init__.py b/esphome/components/sprinkler/__init__.py index 6e2ff4ee2e..9dc695cafc 100644 --- a/esphome/components/sprinkler/__init__.py +++ b/esphome/components/sprinkler/__init__.py @@ -427,7 +427,7 @@ CONFIG_SCHEMA = cv.All( async def sprinkler_set_divider_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) - template_ = await cg.templatable(config[CONF_DIVIDER], args, cg.float_) + template_ = await cg.templatable(config[CONF_DIVIDER], args, cg.uint32) cg.add(var.set_divider(template_)) return var @@ -471,7 +471,7 @@ async def sprinkler_set_queued_valve_to_code(config, action_id, template_arg, ar async def sprinkler_set_repeat_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) - template_ = await cg.templatable(config[CONF_REPEAT], args, cg.float_) + template_ = await cg.templatable(config[CONF_REPEAT], args, cg.uint32) cg.add(var.set_repeat(template_)) return var From 6044f41db55e61c4178d88366880cf9c0869615e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:30:15 -0400 Subject: [PATCH 1962/2030] [multiple] Add missing cv.COMPONENT_SCHEMA to CONFIG_SCHEMA (#15475) --- esphome/components/ads1118/__init__.py | 14 +- esphome/components/as3935/sensor.py | 2 +- esphome/components/cse7766/sensor.py | 96 ++++++------- .../cst226/binary_sensor/__init__.py | 12 +- esphome/components/dsmr/__init__.py | 4 +- esphome/components/e131/__init__.py | 2 +- esphome/components/gcja5/sensor.py | 128 +++++++++--------- esphome/components/hlw8032/sensor.py | 76 ++++++----- esphome/components/sml/__init__.py | 16 ++- esphome/components/sml/sensor/__init__.py | 18 ++- .../components/sml/text_sensor/__init__.py | 18 ++- esphome/components/sun_gtil2/__init__.py | 14 +- esphome/components/tm1651/__init__.py | 2 +- .../tt21100/binary_sensor/__init__.py | 14 +- esphome/components/wiegand/__init__.py | 2 +- 15 files changed, 230 insertions(+), 188 deletions(-) diff --git a/esphome/components/ads1118/__init__.py b/esphome/components/ads1118/__init__.py index 128e0d0701..45d47a329e 100644 --- a/esphome/components/ads1118/__init__.py +++ b/esphome/components/ads1118/__init__.py @@ -12,11 +12,15 @@ CONF_ADS1118_ID = "ads1118_id" ads1118_ns = cg.esphome_ns.namespace("ads1118") ADS1118 = ads1118_ns.class_("ADS1118", cg.Component, spi.SPIDevice) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(ADS1118), - } -).extend(spi.spi_device_schema(cs_pin_required=True)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(ADS1118), + } + ) + .extend(spi.spi_device_schema(cs_pin_required=True)) + .extend(cv.COMPONENT_SCHEMA) +) async def to_code(config): diff --git a/esphome/components/as3935/sensor.py b/esphome/components/as3935/sensor.py index 79bc7af4a9..1e549c5d82 100644 --- a/esphome/components/as3935/sensor.py +++ b/esphome/components/as3935/sensor.py @@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.Schema( accuracy_decimals=1, ), } -).extend(cv.COMPONENT_SCHEMA) +) async def to_code(config): diff --git a/esphome/components/cse7766/sensor.py b/esphome/components/cse7766/sensor.py index 6572a914aa..94ed66d7cc 100644 --- a/esphome/components/cse7766/sensor.py +++ b/esphome/components/cse7766/sensor.py @@ -32,52 +32,56 @@ DEPENDENCIES = ["uart"] cse7766_ns = cg.esphome_ns.namespace("cse7766") CSE7766Component = cse7766_ns.class_("CSE7766Component", cg.Component, uart.UARTDevice) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(CSE7766Component), - cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( - unit_of_measurement=UNIT_VOLT, - accuracy_decimals=1, - device_class=DEVICE_CLASS_VOLTAGE, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_CURRENT): sensor.sensor_schema( - unit_of_measurement=UNIT_AMPERE, - accuracy_decimals=2, - device_class=DEVICE_CLASS_CURRENT, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_POWER): sensor.sensor_schema( - unit_of_measurement=UNIT_WATT, - accuracy_decimals=1, - device_class=DEVICE_CLASS_POWER, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_ENERGY): sensor.sensor_schema( - unit_of_measurement=UNIT_WATT_HOURS, - accuracy_decimals=3, - device_class=DEVICE_CLASS_ENERGY, - state_class=STATE_CLASS_TOTAL_INCREASING, - ), - cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema( - unit_of_measurement=UNIT_VOLT_AMPS, - accuracy_decimals=1, - device_class=DEVICE_CLASS_APPARENT_POWER, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema( - unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, - accuracy_decimals=1, - device_class=DEVICE_CLASS_REACTIVE_POWER, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( - accuracy_decimals=2, - device_class=DEVICE_CLASS_POWER_FACTOR, - state_class=STATE_CLASS_MEASUREMENT, - ), - } -).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(CSE7766Component), + cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CURRENT): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_ENERGY): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT_HOURS, + accuracy_decimals=3, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, + ), + cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT_AMPS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_APPARENT_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, + accuracy_decimals=1, + device_class=DEVICE_CLASS_REACTIVE_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( + accuracy_decimals=2, + device_class=DEVICE_CLASS_POWER_FACTOR, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( "cse7766", baud_rate=4800, parity="EVEN", require_rx=True ) diff --git a/esphome/components/cst226/binary_sensor/__init__.py b/esphome/components/cst226/binary_sensor/__init__.py index d95f0d2b4d..324d794772 100644 --- a/esphome/components/cst226/binary_sensor/__init__.py +++ b/esphome/components/cst226/binary_sensor/__init__.py @@ -15,10 +15,14 @@ CST226Button = cst226_ns.class_( cg.Parented.template(CST226Touchscreen), ) -CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(CST226Button).extend( - { - cv.GenerateID(CONF_CST226_ID): cv.use_id(CST226Touchscreen), - } +CONFIG_SCHEMA = ( + binary_sensor.binary_sensor_schema(CST226Button) + .extend( + { + cv.GenerateID(CONF_CST226_ID): cv.use_id(CST226Touchscreen), + } + ) + .extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index b1ff9794a3..dd7f2b9f56 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -46,7 +46,9 @@ CONFIG_SCHEMA = cv.All( CONF_RECEIVE_TIMEOUT, default="200ms" ): cv.positive_time_period_milliseconds, } - ).extend(uart.UART_DEVICE_SCHEMA), + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA), ) diff --git a/esphome/components/e131/__init__.py b/esphome/components/e131/__init__.py index 301812e314..a1a8e0aec5 100644 --- a/esphome/components/e131/__init__.py +++ b/esphome/components/e131/__init__.py @@ -29,7 +29,7 @@ CONFIG_SCHEMA = cv.Schema( cv.GenerateID(): cv.declare_id(E131Component), cv.Optional(CONF_METHOD, default="MULTICAST"): cv.one_of(*METHODS, upper=True), } -) +).extend(cv.COMPONENT_SCHEMA) async def to_code(config): diff --git a/esphome/components/gcja5/sensor.py b/esphome/components/gcja5/sensor.py index ec26447ccb..a522b1f50f 100644 --- a/esphome/components/gcja5/sensor.py +++ b/esphome/components/gcja5/sensor.py @@ -29,68 +29,72 @@ GCJA5Component = gcja5_ns.class_("GCJA5Component", cg.PollingComponent, uart.UAR CONF_PMC_0_3 = "pmc_0_3" CONF_PMC_5_0 = "pmc_5_0" -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(GCJA5Component), - cv.Optional(CONF_PM_1_0): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_CHEMICAL_WEAPON, - accuracy_decimals=2, - device_class=DEVICE_CLASS_PM1, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PM_2_5): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_CHEMICAL_WEAPON, - accuracy_decimals=2, - device_class=DEVICE_CLASS_PM25, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PM_10_0): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_CHEMICAL_WEAPON, - accuracy_decimals=2, - device_class=DEVICE_CLASS_PM10, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_0_3): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_0_5): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_1_0): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_2_5): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_5_0): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_PMC_10_0): sensor.sensor_schema( - unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, - icon=ICON_COUNTER, - accuracy_decimals=0, - state_class=STATE_CLASS_MEASUREMENT, - ), - } -).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(GCJA5Component), + cv.Optional(CONF_PM_1_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM1, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM25, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_CHEMICAL_WEAPON, + accuracy_decimals=2, + device_class=DEVICE_CLASS_PM10, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_0_3): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_0_5): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_1_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_2_5): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_5_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_PMC_10_0): sensor.sensor_schema( + unit_of_measurement=UNIT_MICROGRAMS_PER_CUBIC_METER, + icon=ICON_COUNTER, + accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, + ), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( "gcja5", baud_rate=9600, require_rx=True, parity="EVEN" ) diff --git a/esphome/components/hlw8032/sensor.py b/esphome/components/hlw8032/sensor.py index 96800e46f4..846c9a398b 100644 --- a/esphome/components/hlw8032/sensor.py +++ b/esphome/components/hlw8032/sensor.py @@ -27,42 +27,46 @@ DEPENDENCIES = ["uart"] hlw8032_ns = cg.esphome_ns.namespace("hlw8032") HLW8032Component = hlw8032_ns.class_("HLW8032Component", cg.Component, uart.UARTDevice) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(HLW8032Component), - cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( - unit_of_measurement=UNIT_VOLT, - accuracy_decimals=1, - device_class=DEVICE_CLASS_VOLTAGE, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_CURRENT): sensor.sensor_schema( - unit_of_measurement=UNIT_AMPERE, - accuracy_decimals=2, - device_class=DEVICE_CLASS_CURRENT, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_POWER): sensor.sensor_schema( - unit_of_measurement=UNIT_WATT, - accuracy_decimals=1, - device_class=DEVICE_CLASS_POWER, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema( - unit_of_measurement=UNIT_VOLT_AMPS, - accuracy_decimals=1, - device_class=DEVICE_CLASS_APPARENT_POWER, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( - accuracy_decimals=2, - device_class=DEVICE_CLASS_POWER_FACTOR, - state_class=STATE_CLASS_MEASUREMENT, - ), - cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance, - cv.Optional(CONF_VOLTAGE_DIVIDER, default=1.720): cv.positive_float, - } -).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HLW8032Component), + cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CURRENT): sensor.sensor_schema( + unit_of_measurement=UNIT_AMPERE, + accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_WATT, + accuracy_decimals=1, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_APPARENT_POWER): sensor.sensor_schema( + unit_of_measurement=UNIT_VOLT_AMPS, + accuracy_decimals=1, + device_class=DEVICE_CLASS_APPARENT_POWER, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( + accuracy_decimals=2, + device_class=DEVICE_CLASS_POWER_FACTOR, + state_class=STATE_CLASS_MEASUREMENT, + ), + cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance, + cv.Optional(CONF_VOLTAGE_DIVIDER, default=1.720): cv.positive_float, + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( "hlw8032", baud_rate=4800, require_rx=True, data_bits=8, parity="EVEN" diff --git a/esphome/components/sml/__init__.py b/esphome/components/sml/__init__.py index 1bf0d97d65..1b7f9da4fb 100644 --- a/esphome/components/sml/__init__.py +++ b/esphome/components/sml/__init__.py @@ -19,12 +19,16 @@ CONF_OBIS_CODE = "obis_code" CONF_SERVER_ID = "server_id" -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(Sml), - cv.Optional(CONF_ON_DATA): automation.validate_automation({}), - } -).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Sml), + cv.Optional(CONF_ON_DATA): automation.validate_automation({}), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) async def to_code(config): diff --git a/esphome/components/sml/sensor/__init__.py b/esphome/components/sml/sensor/__init__.py index 164a31f8a7..e6d7180f17 100644 --- a/esphome/components/sml/sensor/__init__.py +++ b/esphome/components/sml/sensor/__init__.py @@ -10,13 +10,17 @@ AUTO_LOAD = ["sml"] SmlSensor = sml_ns.class_("SmlSensor", sensor.Sensor, cg.Component) -CONFIG_SCHEMA = sensor.sensor_schema().extend( - { - cv.GenerateID(): cv.declare_id(SmlSensor), - cv.GenerateID(CONF_SML_ID): cv.use_id(Sml), - cv.Required(CONF_OBIS_CODE): obis_code, - cv.Optional(CONF_SERVER_ID, default=""): cv.string, - } +CONFIG_SCHEMA = ( + sensor.sensor_schema() + .extend( + { + cv.GenerateID(): cv.declare_id(SmlSensor), + cv.GenerateID(CONF_SML_ID): cv.use_id(Sml), + cv.Required(CONF_OBIS_CODE): obis_code, + cv.Optional(CONF_SERVER_ID, default=""): cv.string, + } + ) + .extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/sml/text_sensor/__init__.py b/esphome/components/sml/text_sensor/__init__.py index 9c9da26c3a..5a5ab658c4 100644 --- a/esphome/components/sml/text_sensor/__init__.py +++ b/esphome/components/sml/text_sensor/__init__.py @@ -19,13 +19,17 @@ SML_TYPES = { SmlTextSensor = sml_ns.class_("SmlTextSensor", text_sensor.TextSensor, cg.Component) -CONFIG_SCHEMA = text_sensor.text_sensor_schema(SmlTextSensor).extend( - { - cv.GenerateID(CONF_SML_ID): cv.use_id(Sml), - cv.Required(CONF_OBIS_CODE): obis_code, - cv.Optional(CONF_SERVER_ID, default=""): cv.string, - cv.Optional(CONF_FORMAT, default=""): cv.enum(SML_TYPES, lower=True), - } +CONFIG_SCHEMA = ( + text_sensor.text_sensor_schema(SmlTextSensor) + .extend( + { + cv.GenerateID(CONF_SML_ID): cv.use_id(Sml), + cv.Required(CONF_OBIS_CODE): obis_code, + cv.Optional(CONF_SERVER_ID, default=""): cv.string, + cv.Optional(CONF_FORMAT, default=""): cv.enum(SML_TYPES, lower=True), + } + ) + .extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/sun_gtil2/__init__.py b/esphome/components/sun_gtil2/__init__.py index d073c16e4e..c7082794db 100644 --- a/esphome/components/sun_gtil2/__init__.py +++ b/esphome/components/sun_gtil2/__init__.py @@ -13,11 +13,15 @@ sun_gtil2_ns = cg.esphome_ns.namespace("sun_gtil2") SunGTIL2Component = sun_gtil2_ns.class_("SunGTIL2", cg.Component, uart.UARTDevice) -CONFIG_SCHEMA = cv.Schema( - { - cv.GenerateID(): cv.declare_id(SunGTIL2Component), - } -).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SunGTIL2Component), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) async def to_code(config): diff --git a/esphome/components/tm1651/__init__.py b/esphome/components/tm1651/__init__.py index fb35eb21b5..7d957df3be 100644 --- a/esphome/components/tm1651/__init__.py +++ b/esphome/components/tm1651/__init__.py @@ -39,7 +39,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_schema, cv.Required(CONF_DIO_PIN): pins.internal_gpio_output_pin_schema, } - ), + ).extend(cv.COMPONENT_SCHEMA), ) diff --git a/esphome/components/tt21100/binary_sensor/__init__.py b/esphome/components/tt21100/binary_sensor/__init__.py index f79eff0e01..081bd17c20 100644 --- a/esphome/components/tt21100/binary_sensor/__init__.py +++ b/esphome/components/tt21100/binary_sensor/__init__.py @@ -16,11 +16,15 @@ TT21100Button = tt21100_ns.class_( cg.Parented.template(TT21100Touchscreen), ) -CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(TT21100Button).extend( - { - cv.GenerateID(CONF_TT21100_ID): cv.use_id(TT21100Touchscreen), - cv.Required(CONF_INDEX): cv.int_range(min=0, max=3), - } +CONFIG_SCHEMA = ( + binary_sensor.binary_sensor_schema(TT21100Button) + .extend( + { + cv.GenerateID(CONF_TT21100_ID): cv.use_id(TT21100Touchscreen), + cv.Required(CONF_INDEX): cv.int_range(min=0, max=3), + } + ) + .extend(cv.COMPONENT_SCHEMA) ) diff --git a/esphome/components/wiegand/__init__.py b/esphome/components/wiegand/__init__.py index 962ac4c373..36ec7bd43f 100644 --- a/esphome/components/wiegand/__init__.py +++ b/esphome/components/wiegand/__init__.py @@ -48,7 +48,7 @@ CONFIG_SCHEMA = cv.Schema( } ), } -) +).extend(cv.COMPONENT_SCHEMA) async def to_code(config): From e86978f0dad99790effc0e5abebdece6baeb99a3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:30:46 -0400 Subject: [PATCH 1963/2030] [rpi_dpi_rgb][st7701s][ags10] Fix Optional config keys accessed unconditionally (#15474) --- esphome/components/ags10/sensor.py | 2 +- esphome/components/rpi_dpi_rgb/display.py | 2 +- esphome/components/st7701s/display.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/ags10/sensor.py b/esphome/components/ags10/sensor.py index 90fe067b32..e94504ff1a 100644 --- a/esphome/components/ags10/sensor.py +++ b/esphome/components/ags10/sensor.py @@ -35,7 +35,7 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(AGS10Component), - cv.Optional(CONF_TVOC): sensor.sensor_schema( + cv.Required(CONF_TVOC): sensor.sensor_schema( unit_of_measurement=UNIT_PARTS_PER_BILLION, icon=ICON_RADIATOR, accuracy_decimals=0, diff --git a/esphome/components/rpi_dpi_rgb/display.py b/esphome/components/rpi_dpi_rgb/display.py index e92eee7c0c..ee462686e4 100644 --- a/esphome/components/rpi_dpi_rgb/display.py +++ b/esphome/components/rpi_dpi_rgb/display.py @@ -102,7 +102,7 @@ CONFIG_SCHEMA = cv.All( } ), ), - cv.Optional(CONF_COLOR_ORDER): cv.one_of( + cv.Optional(CONF_COLOR_ORDER, default="BGR"): cv.one_of( *COLOR_ORDERS.keys(), upper=True ), cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean, diff --git a/esphome/components/st7701s/display.py b/esphome/components/st7701s/display.py index a8b12dfa28..7f6492812f 100644 --- a/esphome/components/st7701s/display.py +++ b/esphome/components/st7701s/display.py @@ -138,7 +138,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_INIT_SEQUENCE, default=1): cv.ensure_list( map_sequence ), - cv.Optional(CONF_COLOR_ORDER): cv.one_of( + cv.Optional(CONF_COLOR_ORDER, default="BGR"): cv.one_of( *COLOR_ORDERS.keys(), upper=True ), cv.Optional(CONF_PCLK_FREQUENCY, default="16MHz"): cv.All( From a7963bee98e0c468f8e75436567bb5be70023014 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:31:40 -0400 Subject: [PATCH 1964/2030] [gcja5][cd74hc4067][openthread_info] Fix PollingComponent mismatches (#15476) --- esphome/components/cd74hc4067/__init__.py | 4 +--- esphome/components/gcja5/sensor.py | 2 +- esphome/components/openthread_info/text_sensor.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/esphome/components/cd74hc4067/__init__.py b/esphome/components/cd74hc4067/__init__.py index 9b69576b43..af6866df78 100644 --- a/esphome/components/cd74hc4067/__init__.py +++ b/esphome/components/cd74hc4067/__init__.py @@ -9,9 +9,7 @@ MULTI_CONF = True cd74hc4067_ns = cg.esphome_ns.namespace("cd74hc4067") -CD74HC4067Component = cd74hc4067_ns.class_( - "CD74HC4067Component", cg.Component, cg.PollingComponent -) +CD74HC4067Component = cd74hc4067_ns.class_("CD74HC4067Component", cg.Component) CONF_PIN_S0 = "pin_s0" CONF_PIN_S1 = "pin_s1" diff --git a/esphome/components/gcja5/sensor.py b/esphome/components/gcja5/sensor.py index a522b1f50f..e4de7721c6 100644 --- a/esphome/components/gcja5/sensor.py +++ b/esphome/components/gcja5/sensor.py @@ -24,7 +24,7 @@ DEPENDENCIES = ["uart"] gcja5_ns = cg.esphome_ns.namespace("gcja5") -GCJA5Component = gcja5_ns.class_("GCJA5Component", cg.PollingComponent, uart.UARTDevice) +GCJA5Component = gcja5_ns.class_("GCJA5Component", cg.Component, uart.UARTDevice) CONF_PMC_0_3 = "pmc_0_3" CONF_PMC_5_0 = "pmc_5_0" diff --git a/esphome/components/openthread_info/text_sensor.py b/esphome/components/openthread_info/text_sensor.py index ddec8f264c..b672831bf0 100644 --- a/esphome/components/openthread_info/text_sensor.py +++ b/esphome/components/openthread_info/text_sensor.py @@ -54,7 +54,7 @@ CONFIG_SCHEMA = cv.Schema( { cv.Optional(CONF_IP_ADDRESS): text_sensor.text_sensor_schema( IPAddressOpenThreadInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC - ), + ).extend(cv.polling_component_schema("1s")), cv.Optional(CONF_ROLE): text_sensor.text_sensor_schema( RoleOpenThreadInfo, entity_category=ENTITY_CATEGORY_DIAGNOSTIC ).extend(cv.polling_component_schema("1s")), From 62b4b250c7fd085b356b8eff34f9a9d493007ee9 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 16:35:50 -0400 Subject: [PATCH 1965/2030] [opentherm] Fix step=0 default overriding entity step (#15484) --- esphome/components/opentherm/input.py | 33 +++++++++---------- .../components/opentherm/number/__init__.py | 14 +++++--- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/esphome/components/opentherm/input.py b/esphome/components/opentherm/input.py index c5814f74e2..e711e4df8e 100644 --- a/esphome/components/opentherm/input.py +++ b/esphome/components/opentherm/input.py @@ -2,51 +2,48 @@ from typing import Any import esphome.codegen as cg import esphome.config_validation as cv +from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE from . import generate, schema -CONF_min_value = "min_value" -CONF_max_value = "max_value" -CONF_auto_min_value = "auto_min_value" -CONF_auto_max_value = "auto_max_value" -CONF_step = "step" +CONF_AUTO_MIN_VALUE = "auto_min_value" +CONF_AUTO_MAX_VALUE = "auto_max_value" OpenthermInput = generate.opentherm_ns.class_("OpenthermInput") def validate_min_value_less_than_max_value(conf): if ( - CONF_min_value in conf - and CONF_max_value in conf - and conf[CONF_min_value] > conf[CONF_max_value] + CONF_MIN_VALUE in conf + and CONF_MAX_VALUE in conf + and conf[CONF_MIN_VALUE] > conf[CONF_MAX_VALUE] ): - raise cv.Invalid(f"{CONF_min_value} must be less than {CONF_max_value}") + raise cv.Invalid(f"{CONF_MIN_VALUE} must be less than {CONF_MAX_VALUE}") return conf def input_schema(entity: schema.InputSchema) -> cv.Schema: result = cv.Schema( { - cv.Optional(CONF_min_value, entity.range[0]): cv.float_range( + cv.Optional(CONF_MIN_VALUE, entity.range[0]): cv.float_range( entity.range[0], entity.range[1] ), - cv.Optional(CONF_max_value, entity.range[1]): cv.float_range( + cv.Optional(CONF_MAX_VALUE, entity.range[1]): cv.float_range( entity.range[0], entity.range[1] ), } ) result = result.add_extra(validate_min_value_less_than_max_value) - result = result.extend({cv.Optional(CONF_step, False): cv.float_}) if entity.auto_min_value is not None: - result = result.extend({cv.Optional(CONF_auto_min_value, False): cv.boolean}) + result = result.extend({cv.Optional(CONF_AUTO_MIN_VALUE, False): cv.boolean}) if entity.auto_max_value is not None: - result = result.extend({cv.Optional(CONF_auto_max_value, False): cv.boolean}) + result = result.extend({cv.Optional(CONF_AUTO_MAX_VALUE, False): cv.boolean}) return result def generate_setters(entity: cg.MockObj, conf: dict[str, Any]) -> None: - generate.add_property_set(entity, CONF_min_value, conf) - generate.add_property_set(entity, CONF_max_value, conf) - generate.add_property_set(entity, CONF_auto_min_value, conf) - generate.add_property_set(entity, CONF_auto_max_value, conf) + generate.add_property_set(entity, CONF_MIN_VALUE, conf) + generate.add_property_set(entity, CONF_MAX_VALUE, conf) + generate.add_property_set(entity, CONF_AUTO_MIN_VALUE, conf) + generate.add_property_set(entity, CONF_AUTO_MAX_VALUE, conf) diff --git a/esphome/components/opentherm/number/__init__.py b/esphome/components/opentherm/number/__init__.py index 6dbc45f49b..17ec12a61a 100644 --- a/esphome/components/opentherm/number/__init__.py +++ b/esphome/components/opentherm/number/__init__.py @@ -3,7 +3,13 @@ from typing import Any import esphome.codegen as cg from esphome.components import number import esphome.config_validation as cv -from esphome.const import CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_STEP +from esphome.const import ( + CONF_INITIAL_VALUE, + CONF_MAX_VALUE, + CONF_MIN_VALUE, + CONF_RESTORE_VALUE, + CONF_STEP, +) from .. import const, generate, input, schema, validate @@ -18,9 +24,9 @@ OpenthermNumber = generate.opentherm_ns.class_( async def new_openthermnumber(config: dict[str, Any]) -> cg.Pvariable: var = await number.new_number( config, - min_value=config[input.CONF_min_value], - max_value=config[input.CONF_max_value], - step=config[input.CONF_step], + min_value=config[CONF_MIN_VALUE], + max_value=config[CONF_MAX_VALUE], + step=config[CONF_STEP], ) await cg.register_component(var, config) input.generate_setters(var, config) From ab455915079d9a51fda55e59bc7dafe7f864997c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 11:01:03 -1000 Subject: [PATCH 1966/2030] [core] Move wake_loop out of socket component into core (#15446) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> --- esphome/components/esp32_ble/__init__.py | 6 - esphome/components/esp32_ble/ble.cpp | 6 - esphome/components/esp32_camera/__init__.py | 5 +- .../components/esp32_camera/esp32_camera.cpp | 2 - .../components/esphome/ota/ota_esphome.cpp | 2 +- esphome/components/espnow/__init__.py | 8 +- .../components/espnow/espnow_component.cpp | 8 +- .../components/micro_wake_word/__init__.py | 8 +- .../micro_wake_word/micro_wake_word.cpp | 2 - esphome/components/mixer/speaker/__init__.py | 5 +- .../mixer/speaker/mixer_speaker.cpp | 4 - esphome/components/mqtt/__init__.py | 6 - .../components/mqtt/mqtt_backend_esp32.cpp | 4 +- .../components/resampler/speaker/__init__.py | 5 +- .../resampler/speaker/resampler_speaker.cpp | 2 - esphome/components/socket/__init__.py | 48 ++----- .../components/socket/lwip_raw_tcp_impl.cpp | 111 +-------------- esphome/components/socket/lwip_raw_tcp_impl.h | 2 +- esphome/components/socket/socket.cpp | 2 +- esphome/components/socket/socket.h | 16 +-- esphome/components/uart/__init__.py | 14 -- .../components/usb_cdc_acm/usb_cdc_acm.cpp | 6 - esphome/components/usb_host/__init__.py | 8 +- .../components/usb_host/usb_host_client.cpp | 4 +- esphome/components/usb_uart/__init__.py | 7 +- esphome/components/usb_uart/usb_uart.cpp | 4 +- esphome/core/application.cpp | 91 ++++--------- esphome/core/application.h | 128 ++++++------------ esphome/core/component.cpp | 10 +- esphome/core/config.py | 14 ++ esphome/core/defines.h | 5 +- esphome/core/lwip_fast_select.c | 57 ++------ esphome/core/lwip_fast_select.h | 20 --- esphome/core/main_task.c | 5 + esphome/core/main_task.h | 55 ++++++++ esphome/core/wake.cpp | 82 +++++++++++ esphome/core/wake.h | 126 +++++++++++++++++ .../socket/test_wake_loop_threadsafe.py | 127 ----------------- 38 files changed, 397 insertions(+), 618 deletions(-) create mode 100644 esphome/core/main_task.c create mode 100644 esphome/core/main_task.h create mode 100644 esphome/core/wake.cpp create mode 100644 esphome/core/wake.h delete mode 100644 tests/components/socket/test_wake_loop_threadsafe.py diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 2e5e358753..974611c9b1 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -7,7 +7,6 @@ from typing import Any from esphome import automation import esphome.codegen as cg -from esphome.components import socket from esphome.components.esp32 import add_idf_sdkconfig_option, const, get_esp32_variant from esphome.components.esp32.const import VARIANT_ESP32C2 import esphome.config_validation as cv @@ -592,11 +591,6 @@ async def to_code(config): cg.add(var.set_name(name)) await cg.register_component(var, config) - # BLE uses the socket wake_loop_threadsafe() mechanism to wake the main loop from BLE tasks - # This enables low-latency (~12μs) BLE event processing instead of waiting for - # select() timeout (0-16ms). The wake socket is shared across all components. - socket.require_wake_loop_threadsafe() - # Define max connections for use in C++ code (e.g., ble_server.h) max_connections = config.get(CONF_MAX_CONNECTIONS, DEFAULT_MAX_CONNECTIONS) cg.add_define("USE_ESP32_BLE_MAX_CONNECTIONS", max_connections) diff --git a/esphome/components/esp32_ble/ble.cpp b/esphome/components/esp32_ble/ble.cpp index 68e5fffe2b..0280439731 100644 --- a/esphome/components/esp32_ble/ble.cpp +++ b/esphome/components/esp32_ble/ble.cpp @@ -599,9 +599,7 @@ void ESP32BLE::gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_pa GAP_SECURITY_EVENTS: enqueue_ble_event(event, param); // Wake up main loop to process security event immediately -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif return; // Ignore these GAP events as they are not relevant for our use case @@ -622,9 +620,7 @@ void ESP32BLE::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gat esp_ble_gatts_cb_param_t *param) { enqueue_ble_event(event, gatts_if, param); // Wake up main loop to process GATT event immediately -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif } #endif @@ -633,9 +629,7 @@ void ESP32BLE::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gat esp_ble_gattc_cb_param_t *param) { enqueue_ble_event(event, gattc_if, param); // Wake up main loop to process GATT event immediately -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif } #endif diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index 66af321e4e..5165956806 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -2,7 +2,7 @@ import logging from esphome import automation, pins import esphome.codegen as cg -from esphome.components import i2c, socket +from esphome.components import i2c from esphome.components.esp32 import add_idf_component, add_idf_sdkconfig_option from esphome.components.psram import DOMAIN as psram_domain import esphome.config_validation as cv @@ -29,7 +29,7 @@ from esphome.types import ConfigType _LOGGER = logging.getLogger(__name__) -AUTO_LOAD = ["camera", "socket"] +AUTO_LOAD = ["camera"] DEPENDENCIES = ["esp32"] esp32_camera_ns = cg.esphome_ns.namespace("esp32_camera") @@ -370,7 +370,6 @@ SETTERS = { async def to_code(config): cg.add_define("USE_CAMERA") - socket.require_wake_loop_threadsafe() var = cg.new_Pvariable(config[CONF_ID]) await setup_entity(var, config, "camera") await cg.register_component(var, config) diff --git a/esphome/components/esp32_camera/esp32_camera.cpp b/esphome/components/esp32_camera/esp32_camera.cpp index 085feb8c8a..a7546476d8 100644 --- a/esphome/components/esp32_camera/esp32_camera.cpp +++ b/esphome/components/esp32_camera/esp32_camera.cpp @@ -521,11 +521,9 @@ void ESP32Camera::framebuffer_task(void *pv) { camera_fb_t *framebuffer = esp_camera_fb_get(); xQueueSend(that->framebuffer_get_queue_, &framebuffer, portMAX_DELAY); // Only wake the main loop if there's a pending request to consume the frame -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) if (that->has_requested_image_()) { App.wake_loop_threadsafe(); } -#endif // return is no-op for config with 1 fb xQueueReceive(that->framebuffer_return_queue_, &framebuffer, portMAX_DELAY); esp_camera_fb_return(framebuffer); diff --git a/esphome/components/esphome/ota/ota_esphome.cpp b/esphome/components/esphome/ota/ota_esphome.cpp index 972d2b2b8d..af9b8ee19a 100644 --- a/esphome/components/esphome/ota/ota_esphome.cpp +++ b/esphome/components/esphome/ota/ota_esphome.cpp @@ -262,7 +262,7 @@ void ESPHomeOTAComponent::handle_data_() { /// BSD sockets (ESP32): setblocking(true) makes read/write block /// lwip sockets (LT): setblocking(true) makes read/write block /// Raw TCP (8266, RP2040): setblocking is no-op; SO_RCVTIMEO uses - /// socket_delay()/socket_wake() in read(); + /// wakeable_delay() in read(); /// write() always returns immediately ota::OTAResponseTypes error_code = ota::OTA_RESPONSE_ERROR_UNKNOWN; bool update_started = false; diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 00703bc228..1c8d262810 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -1,6 +1,6 @@ from esphome import automation, core import esphome.codegen as cg -from esphome.components import socket, wifi +from esphome.components import wifi from esphome.components.udp import CONF_ON_RECEIVE import esphome.config_validation as cv from esphome.const import ( @@ -17,7 +17,7 @@ from esphome.core import HexInt from esphome.types import ConfigType CODEOWNERS = ["@jesserockz"] -AUTO_LOAD = ["socket"] + byte_vector = cg.std_vector.template(cg.uint8) peer_address_t = cg.std_ns.class_("array").template(cg.uint8, 6) @@ -124,10 +124,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - # ESP-NOW uses wake_loop_threadsafe() to wake the main loop from ESP-NOW callbacks - # This enables low-latency event processing instead of waiting for select() timeout - socket.require_wake_loop_threadsafe() - cg.add_define("USE_ESPNOW") if wifi_channel := config.get(CONF_CHANNEL): cg.add(var.set_wifi_channel(wifi_channel)) diff --git a/esphome/components/espnow/espnow_component.cpp b/esphome/components/espnow/espnow_component.cpp index 0dc0f12e7e..282287ca83 100644 --- a/esphome/components/espnow/espnow_component.cpp +++ b/esphome/components/espnow/espnow_component.cpp @@ -92,10 +92,8 @@ void on_send_report(const uint8_t *mac_addr, esp_now_send_status_t status) // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if // allocate() returned non-null, the queue cannot be full. - // Wake main loop immediately to process ESP-NOW send event instead of waiting for select() timeout -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + // Wake main loop immediately to process ESP-NOW send event App.wake_loop_threadsafe(); -#endif } void on_data_received(const esp_now_recv_info_t *info, const uint8_t *data, int size) { @@ -115,10 +113,8 @@ void on_data_received(const esp_now_recv_info_t *info, const uint8_t *data, int // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if // allocate() returned non-null, the queue cannot be full. - // Wake main loop immediately to process ESP-NOW receive event instead of waiting for select() timeout -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + // Wake main loop immediately to process ESP-NOW receive event App.wake_loop_threadsafe(); -#endif } ESPNowComponent::ESPNowComponent() { global_esp_now = this; } diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index 372eb4c3b0..fae48630b5 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -7,7 +7,7 @@ from urllib.parse import urljoin from esphome import automation, external_files, git from esphome.automation import register_action, register_condition import esphome.codegen as cg -from esphome.components import esp32, microphone, ota, socket +from esphome.components import esp32, microphone, ota import esphome.config_validation as cv from esphome.const import ( CONF_FILE, @@ -32,7 +32,7 @@ _LOGGER = logging.getLogger(__name__) CODEOWNERS = ["@kahrendt", "@jesserockz"] DEPENDENCIES = ["microphone"] -AUTO_LOAD = ["socket"] + DOMAIN = "micro_wake_word" @@ -444,10 +444,6 @@ async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - # Enable wake_loop_threadsafe() for low-latency wake word detection - # The inference task queues detection events that need immediate processing - socket.require_wake_loop_threadsafe() - mic_source = await microphone.microphone_source_to_code(config[CONF_MICROPHONE]) cg.add(var.set_microphone_source(mic_source)) diff --git a/esphome/components/micro_wake_word/micro_wake_word.cpp b/esphome/components/micro_wake_word/micro_wake_word.cpp index b93bf1b556..f1aac875f1 100644 --- a/esphome/components/micro_wake_word/micro_wake_word.cpp +++ b/esphome/components/micro_wake_word/micro_wake_word.cpp @@ -431,9 +431,7 @@ void MicroWakeWord::process_probabilities_() { xQueueSend(this->detection_queue_, &wake_word_state, portMAX_DELAY); // Wake main loop immediately to process wake word detection -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif model->reset_probabilities(); #ifdef USE_MICRO_WAKE_WORD_VAD diff --git a/esphome/components/mixer/speaker/__init__.py b/esphome/components/mixer/speaker/__init__.py index 63b419cc98..59a80d9297 100644 --- a/esphome/components/mixer/speaker/__init__.py +++ b/esphome/components/mixer/speaker/__init__.py @@ -1,6 +1,6 @@ from esphome import automation import esphome.codegen as cg -from esphome.components import audio, esp32, socket, speaker +from esphome.components import audio, esp32, speaker import esphome.config_validation as cv from esphome.const import ( CONF_BITS_PER_SAMPLE, @@ -111,9 +111,6 @@ FINAL_VALIDATE_SCHEMA = cv.All( async def to_code(config): - # Enable wake_loop_threadsafe for immediate command processing from other tasks - socket.require_wake_loop_threadsafe() - var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) diff --git a/esphome/components/mixer/speaker/mixer_speaker.cpp b/esphome/components/mixer/speaker/mixer_speaker.cpp index 0fabc68c70..741239a2dd 100644 --- a/esphome/components/mixer/speaker/mixer_speaker.cpp +++ b/esphome/components/mixer/speaker/mixer_speaker.cpp @@ -245,11 +245,9 @@ void SourceSpeaker::send_command_(uint32_t command_bit, bool wake_loop) { uint32_t event_bits = xEventGroupGetBits(this->event_group_); if (!(event_bits & command_bit)) { xEventGroupSetBits(this->event_group_, command_bit); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) if (wake_loop) { App.wake_loop_threadsafe(); } -#endif } } @@ -533,9 +531,7 @@ esp_err_t MixerSpeaker::start(audio::AudioStreamInfo &stream_info) { if (!(event_bits & MIXER_TASK_COMMAND_START)) { // Set MIXER_TASK_COMMAND_START bit if not already set, and then immediately wake for low latency xEventGroupSetBits(this->event_group_, MIXER_TASK_COMMAND_START); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif } return ESP_OK; diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index 817f99375e..33a88c49cc 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -69,9 +69,6 @@ DEPENDENCIES = ["network"] def AUTO_LOAD(): if CORE.is_esp8266 or CORE.is_libretiny: return ["async_tcp", "json"] - # ESP32 needs socket for wake_loop_threadsafe() - if CORE.is_esp32: - return ["json", "socket"] return ["json"] @@ -348,10 +345,7 @@ async def to_code(config): # https://github.com/heman/async-mqtt-client/blob/master/library.json cg.add_library("heman/AsyncMqttClient-esphome", "2.0.0") - # MQTT on ESP32 uses wake_loop_threadsafe() to wake the main loop from the MQTT event handler - # This enables low-latency MQTT event processing instead of waiting for select() timeout if CORE.is_esp32: - socket.require_wake_loop_threadsafe() # Re-enable ESP-IDF's mqtt component (excluded by default to save compile time) # IDF 6.0 moved esp-mqtt to an external component if idf_version() >= cv.Version(6, 0, 0): diff --git a/esphome/components/mqtt/mqtt_backend_esp32.cpp b/esphome/components/mqtt/mqtt_backend_esp32.cpp index ab067c4418..499a330730 100644 --- a/esphome/components/mqtt/mqtt_backend_esp32.cpp +++ b/esphome/components/mqtt/mqtt_backend_esp32.cpp @@ -202,10 +202,8 @@ void MQTTBackendESP32::mqtt_event_handler(void *handler_args, esp_event_base_t b // allocate() returned non-null, the queue cannot be full. instance->mqtt_event_queue_.push(event); - // Wake main loop immediately to process MQTT event instead of waiting for select() timeout -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + // Wake main loop immediately to process MQTT event App.wake_loop_threadsafe(); -#endif } } diff --git a/esphome/components/resampler/speaker/__init__.py b/esphome/components/resampler/speaker/__init__.py index 4e4705a889..3134cf7646 100644 --- a/esphome/components/resampler/speaker/__init__.py +++ b/esphome/components/resampler/speaker/__init__.py @@ -1,5 +1,5 @@ import esphome.codegen as cg -from esphome.components import audio, esp32, socket, speaker +from esphome.components import audio, esp32, speaker import esphome.config_validation as cv from esphome.const import ( CONF_BITS_PER_SAMPLE, @@ -77,9 +77,6 @@ FINAL_VALIDATE_SCHEMA = _validate_audio_compatibility async def to_code(config): - # Enable wake_loop_threadsafe for immediate command processing from other tasks - socket.require_wake_loop_threadsafe() - var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await speaker.register_speaker(var, config) diff --git a/esphome/components/resampler/speaker/resampler_speaker.cpp b/esphome/components/resampler/speaker/resampler_speaker.cpp index b737a2d39a..3b50353ddc 100644 --- a/esphome/components/resampler/speaker/resampler_speaker.cpp +++ b/esphome/components/resampler/speaker/resampler_speaker.cpp @@ -245,11 +245,9 @@ void ResamplerSpeaker::send_command_(uint32_t command_bit, bool wake_loop) { uint32_t event_bits = xEventGroupGetBits(this->event_group_); if (!(event_bits & command_bit)) { xEventGroupSetBits(this->event_group_, command_bit); -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) if (wake_loop) { App.wake_loop_threadsafe(); } -#endif } } diff --git a/esphome/components/socket/__init__.py b/esphome/components/socket/__init__.py index 08cf3ea33c..abbbb0f056 100644 --- a/esphome/components/socket/__init__.py +++ b/esphome/components/socket/__init__.py @@ -31,9 +31,6 @@ MIN_UDP_SOCKETS = 6 # Minimum listening sockets — at least api + ota baseline. MIN_TCP_LISTEN_SOCKETS = 2 -# Wake loop threadsafe support tracking -KEY_WAKE_LOOP_THREADSAFE_REQUIRED = "wake_loop_threadsafe_required" - class SocketType(StrEnum): TCP = "tcp" @@ -123,37 +120,22 @@ def get_socket_counts() -> SocketCounts: def require_wake_loop_threadsafe() -> None: - """Mark that wake_loop_threadsafe support is required by a component. + """Deprecated: wake loop support is now always available on all platforms. - Call this from components that need to wake the main event loop from background threads. - This enables the shared UDP loopback socket mechanism (~208 bytes RAM). - The socket is shared across all components that use this feature. - - This call is a no-op if networking is not enabled in the configuration. - - IMPORTANT: This is for background thread context only, NOT ISR context. - Socket operations are not safe to call from ISR handlers. - - On ESP32, FreeRTOS task notifications are used instead (no socket needed). - - Example: - from esphome.components import socket - - async def to_code(config): - socket.require_wake_loop_threadsafe() + This function adds backward-compatible defines so external components + that check #ifdef USE_WAKE_LOOP_THREADSAFE / USE_SOCKET_SELECT_SUPPORT + continue to compile. Remove before 2026.12.0. """ - - # Only set up once (idempotent - multiple components can call this) - if CORE.has_networking and not CORE.data.get( - KEY_WAKE_LOOP_THREADSAFE_REQUIRED, False - ): - CORE.data[KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True - cg.add_define("USE_WAKE_LOOP_THREADSAFE") - if not CORE.is_esp32 and not CORE.is_libretiny: - # Only platforms without fast select need a UDP socket for wake - # notifications. ESP32 and LibreTiny use FreeRTOS task notifications - # instead (no socket needed). - consume_sockets(1, "socket.wake_loop_threadsafe", SocketType.UDP)({}) + # Remove before 2026.12.0 + _LOGGER.warning( + "require_wake_loop_threadsafe() is deprecated and no longer needed. " + "Wake loop support is now always available. Remove this call and any " + "#ifdef USE_SOCKET_SELECT_SUPPORT / USE_WAKE_LOOP_THREADSAFE guards. " + "This will be removed in 2026.12.0." + ) + # Add deprecated defines for backward compat with external component C++ code + cg.add_define("USE_WAKE_LOOP_THREADSAFE") + cg.add_define("USE_SOCKET_SELECT_SUPPORT") CONFIG_SCHEMA = cv.Schema( @@ -184,10 +166,8 @@ async def to_code(config): cg.add_define("USE_SOCKET_IMPL_LWIP_TCP") elif impl == IMPLEMENTATION_LWIP_SOCKETS: cg.add_define("USE_SOCKET_IMPL_LWIP_SOCKETS") - cg.add_define("USE_SOCKET_SELECT_SUPPORT") elif impl == IMPLEMENTATION_BSD_SOCKETS: cg.add_define("USE_SOCKET_IMPL_BSD_SOCKETS") - cg.add_define("USE_SOCKET_SELECT_SUPPORT") # ESP32 and LibreTiny both have LwIP >= 2.1.3 with lwip_socket_dbg_get_socket() # and FreeRTOS task notifications — enable fast select to bypass lwip_select(). # Only when not using lwip_tcp, which does not provide select() support. diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 3bcbd88085..86131d3ddb 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -8,6 +8,7 @@ #include <sys/time.h> #include "esphome/core/helpers.h" +#include "esphome/core/wake.h" #include "esphome/core/log.h" #ifdef USE_ESP8266 @@ -19,102 +20,6 @@ namespace esphome::socket { -#ifdef USE_ESP8266 -// Flag to signal socket activity - checked by socket_delay() to exit early -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -static volatile bool s_socket_woke = false; - -void socket_delay(uint32_t ms) { - // Use esp_delay with a callback that checks if socket data arrived. - // This allows the delay to exit early when socket_wake() is called by - // lwip recv_fn/accept_fn callbacks, reducing socket latency. - // - // When ms is 0, we must use delay(0) because esp_delay(0, callback) - // exits immediately without yielding, which can cause watchdog timeouts - // when the main loop runs in high-frequency mode (e.g., during light effects). - if (ms == 0) { - delay(0); - return; - } - s_socket_woke = false; - esp_delay(ms, []() { return !s_socket_woke; }); -} - -void IRAM_ATTR socket_wake() { - s_socket_woke = true; - esp_schedule(); -} -#elif defined(USE_RP2040) -// RP2040 (non-FreeRTOS) socket wake using hardware WFE/SEV instructions. -// -// Same pattern as ESP8266's esp_delay()/esp_schedule(): set a one-shot timer, -// then sleep with __wfe(). Wake on either: -// - Timer alarm fires → callback calls __sev() → __wfe() returns → timeout -// - Socket data arrives → LWIP callback calls socket_wake() → __sev() → __wfe() returns → early wake -// -// CYW43 WiFi chip communicates via SPI interrupts on core 0. When data arrives, -// the GPIO interrupt fires → async_context pendsv processes CYW43/LWIP → recv/accept -// callbacks call socket_wake() → __sev() wakes the main loop from __wfe() sleep. -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -static volatile bool s_socket_woke = false; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -static volatile bool s_delay_expired = false; - -static int64_t alarm_callback(alarm_id_t id, void *user_data) { - (void) id; - (void) user_data; - s_delay_expired = true; - // Wake the main loop from __wfe() sleep — timeout expired. - __sev(); - // Return 0 = don't reschedule (one-shot) - return 0; -} - -void socket_delay(uint32_t ms) { - if (ms == 0) { - yield(); - return; - } - // If a wake was already signalled, consume it and return immediately - // instead of going to sleep. This avoids losing a wake that arrived - // between loop iterations. - if (s_socket_woke) { - s_socket_woke = false; - return; - } - // Don't clear s_socket_woke here — if an IRQ fires between the check above - // and the while loop below, the while condition sees it immediately. Clearing - // here would lose that wake and sleep until the timer fires. - s_delay_expired = false; - // Set a one-shot timer to wake us after the timeout. - // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. - alarm_id_t alarm = add_alarm_in_ms(ms, alarm_callback, nullptr, true); - if (alarm <= 0) { - delay(ms); - return; - } - // Sleep until woken by either the timer alarm or socket_wake(). - // __wfe() may return spuriously (stale event register, other interrupts), - // so we loop checking both flags. - while (!s_socket_woke && !s_delay_expired) { - __wfe(); - } - // Cancel timer if we woke early (socket data arrived before timeout) - if (!s_delay_expired) - cancel_alarm(alarm); - s_socket_woke = false; // consume the wake for next call -} - -// No IRAM_ATTR equivalent needed: on RP2040, CYW43 async_context runs LWIP -// callbacks via pendsv (not hard IRQ), so they execute from flash safely. -void socket_wake() { - s_socket_woke = true; - // Wake the main loop from __wfe() sleep. __sev() is a global event that - // wakes any core sleeping in __wfe(). This is ISR-safe. - __sev(); -} -#endif - // ---- LWIP thread safety ---- // // On RP2040 (Pico W), arduino-pico sets PICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1. @@ -543,10 +448,8 @@ err_t LWIPRawImpl::recv_fn(struct pbuf *pb, err_t err) { } else { pbuf_cat(this->rx_buf_, pb); } -#if (defined(USE_ESP8266) || defined(USE_RP2040)) // Wake the main loop immediately so it can process the received data. - socket_wake(); -#endif + esphome::wake_loop_any_context(); return ERR_OK; } @@ -555,15 +458,15 @@ void LWIPRawImpl::wait_for_data_() { // (needs async_context lock). // // Loop until data arrives, connection closes, or the full timeout elapses. - // socket_delay() may return early due to other sockets waking the global - // socket_wake() flag, so we re-enter for the remaining time. + // wakeable_delay() may return early due to any wake source, + // so we re-enter for the remaining time. uint32_t timeout_ms = this->recv_timeout_cs_ * 10; uint32_t start = millis(); while (this->waiting_for_data_()) { uint32_t elapsed = millis() - start; if (elapsed >= timeout_ms) break; - socket_delay(timeout_ms - elapsed); + esphome::internal::wakeable_delay(timeout_ms - elapsed); } } @@ -951,10 +854,8 @@ err_t LWIPRawListenImpl::accept_fn_(struct tcp_pcb *newpcb, err_t err) { tcp_err(newpcb, LWIPRawListenImpl::s_queued_err_fn); tcp_recv(newpcb, LWIPRawListenImpl::s_queued_recv_fn); LWIP_LOG("Accepted connection, queue size: %d", this->accepted_socket_count_); -#if (defined(USE_ESP8266) || defined(USE_RP2040)) // Wake the main loop immediately so it can accept the new connection. - socket_wake(); -#endif + esphome::wake_loop_any_context(); return ERR_OK; } diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index 3c27d71062..e2dcb80d32 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -109,7 +109,7 @@ class LWIPRawImpl : public LWIPRawCommon { return -1; } // Raw TCP doesn't use a blocking flag directly. Blocking behavior - // is provided by SO_RCVTIMEO which makes read() wait via socket_delay(). + // is provided by SO_RCVTIMEO which makes read() wait via wakeable_delay(). return 0; } int loop() { return 0; } diff --git a/esphome/components/socket/socket.cpp b/esphome/components/socket/socket.cpp index bfb6ae8e13..bc43b2746e 100644 --- a/esphome/components/socket/socket.cpp +++ b/esphome/components/socket/socket.cpp @@ -8,7 +8,7 @@ namespace esphome::socket { -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // Shared ready() implementation for fd-based socket implementations (BSD and LWIP sockets). // Checks if the Application's select() loop has marked this fd as ready. bool socket_ready_fd(int fd, bool loop_monitored) { return !loop_monitored || App.is_socket_ready_(fd); } diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 226a669e31..9ea71321e0 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -45,7 +45,7 @@ using ListenSocket = LWIPRawListenImpl; inline bool socket_ready(struct lwip_sock *cached_sock, bool loop_monitored) { return !loop_monitored || (cached_sock != nullptr && esphome_lwip_socket_has_data(cached_sock)); } -#elif defined(USE_SOCKET_SELECT_SUPPORT) +#elif defined(USE_HOST) /// Shared ready() helper for fd-based socket implementations. /// Checks if the Application's select() loop has marked this fd as ready. bool socket_ready_fd(int fd, bool loop_monitored); @@ -120,19 +120,5 @@ socklen_t set_sockaddr_any(struct sockaddr *addr, socklen_t addrlen, uint16_t po /// Format sockaddr into caller-provided buffer, returns length written (excluding null) size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::span<char, SOCKADDR_STR_LEN> buf); -#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) -/// Delay that can be woken early by socket activity. -/// On ESP8266, uses esp_delay() with a callback that checks socket activity. -/// On RP2040, uses __wfe() (Wait For Event) to truly sleep until an interrupt -/// (for example, CYW43 GPIO or a timer alarm) fires and wakes the CPU. -void socket_delay(uint32_t ms); // NOLINT(readability-redundant-declaration) - -/// Signal socket/IO activity and wake the main loop early. -/// On ESP8266: sets flag + esp_schedule(). -/// On RP2040: sets flag + __sev() (Send Event) to wake from __wfe(). -/// ISR-safe on both platforms. -void socket_wake(); // NOLINT(readability-redundant-declaration) -#endif - } // namespace esphome::socket #endif diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index 83649cc209..7075228743 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -42,16 +42,6 @@ CODEOWNERS = ["@esphome/core"] DOMAIN = "uart" -def AUTO_LOAD() -> list[str]: - """Ideally, we would only auto-load socket only when wake_loop_on_rx is requested; - however, AUTO_LOAD is examined before wake_loop_on_rx is set, so instead, since ESP32 - always uses socket select support in the main app, we'll just ensure it's loaded here. - """ - if CORE.is_esp32: - return ["socket"] - return [] - - uart_ns = cg.esphome_ns.namespace("uart") UARTComponent = uart_ns.class_("UARTComponent") @@ -527,10 +517,6 @@ async def final_step(): # Wake-on-RX is essentially free on ESP32 (just an ISR function pointer # registration) — enable by default to reduce RX buffer overflow risk # by waking the main loop immediately when data arrives. - # Requires networking for the wake_loop_isrsafe() infrastructure. - from esphome.components import socket - - socket.require_wake_loop_threadsafe() cg.add_define("USE_UART_WAKE_LOOP_ON_RX") diff --git a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp index 253626f0a3..40f7f2e28b 100644 --- a/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp +++ b/esphome/components/usb_cdc_acm/usb_cdc_acm.cpp @@ -29,10 +29,7 @@ void USBCDCACMInstance::queue_line_state_event(bool dtr, bool rts) { // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if // allocate() returned non-null, the queue cannot be full. this->event_queue_.push(event); - -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif } void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity, @@ -53,10 +50,7 @@ void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_ // Push always succeeds: pool is sized to queue capacity (SIZE-1), so if // allocate() returned non-null, the queue cannot be full. this->event_queue_.push(event); - -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) App.wake_loop_threadsafe(); -#endif } void USBCDCACMInstance::process_events_() { diff --git a/esphome/components/usb_host/__init__.py b/esphome/components/usb_host/__init__.py index 5eb0371e5c..338bd8d572 100644 --- a/esphome/components/usb_host/__init__.py +++ b/esphome/components/usb_host/__init__.py @@ -1,5 +1,4 @@ import esphome.codegen as cg -from esphome.components import socket from esphome.components.esp32 import ( VARIANT_ESP32P4, VARIANT_ESP32S2, @@ -14,7 +13,7 @@ from esphome.const import CONF_DEVICES, CONF_ID from esphome.cpp_types import Component from esphome.types import ConfigType -AUTO_LOAD = ["bytebuffer", "socket"] +AUTO_LOAD = ["bytebuffer"] CODEOWNERS = ["@clydebarrow"] DEPENDENCIES = ["esp32"] usb_host_ns = cg.esphome_ns.namespace("usb_host") @@ -76,11 +75,6 @@ async def to_code(config: ConfigType) -> None: max_requests = config[CONF_MAX_TRANSFER_REQUESTS] cg.add_define("USB_HOST_MAX_REQUESTS", max_requests) - # USB uses the socket wake_loop_threadsafe() mechanism to wake the main loop from USB task - # This enables low-latency (~12μs) USB event processing instead of waiting for - # select() timeout (0-16ms). The wake socket is shared across all components. - socket.require_wake_loop_threadsafe() - var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) for device in config.get(CONF_DEVICES) or (): diff --git a/esphome/components/usb_host/usb_host_client.cpp b/esphome/components/usb_host/usb_host_client.cpp index 18d938344c..c34c7ef67d 100644 --- a/esphome/components/usb_host/usb_host_client.cpp +++ b/esphome/components/usb_host/usb_host_client.cpp @@ -200,10 +200,8 @@ static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void * // Re-enable component loop to process the queued event client->enable_loop_soon_any_context(); - // Wake main loop immediately to process USB event instead of waiting for select() timeout -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + // Wake main loop immediately to process USB event App.wake_loop_threadsafe(); -#endif } void USBClient::setup() { usb_host_client_config_t config{.is_synchronous = false, diff --git a/esphome/components/usb_uart/__init__.py b/esphome/components/usb_uart/__init__.py index 2d85723d72..0e8994a3ed 100644 --- a/esphome/components/usb_uart/__init__.py +++ b/esphome/components/usb_uart/__init__.py @@ -1,5 +1,4 @@ import esphome.codegen as cg -from esphome.components import socket from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS from esphome.components.uart import CONF_DEBUG_PREFIX, CONF_FLUSH_TIMEOUT, UARTComponent from esphome.components.usb_host import register_usb_client, usb_device_schema @@ -14,7 +13,7 @@ from esphome.const import ( ) from esphome.cpp_types import Component -AUTO_LOAD = ["uart", "usb_host", "bytebuffer", "socket"] +AUTO_LOAD = ["uart", "usb_host", "bytebuffer"] CODEOWNERS = ["@clydebarrow"] usb_uart_ns = cg.esphome_ns.namespace("usb_uart") @@ -117,10 +116,6 @@ CONFIG_SCHEMA = cv.ensure_list( async def to_code(config): - # Enable wake_loop_threadsafe for low-latency USB data processing - # The USB task queues data events that need immediate processing - socket.require_wake_loop_threadsafe() - for device in config: var = await register_usb_client(device) for index, channel in enumerate(device[CONF_CHANNELS]): diff --git a/esphome/components/usb_uart/usb_uart.cpp b/esphome/components/usb_uart/usb_uart.cpp index 0b8589f671..30ec61fdc4 100644 --- a/esphome/components/usb_uart/usb_uart.cpp +++ b/esphome/components/usb_uart/usb_uart.cpp @@ -325,10 +325,8 @@ void USBUartComponent::start_input(USBUartChannel *channel) { // Re-enable component loop to process the queued data this->enable_loop_soon_any_context(); - // Wake main loop immediately to process USB data instead of waiting for select() timeout -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) + // Wake main loop immediately to process USB data App.wake_loop_threadsafe(); -#endif } // On success, restart input immediately from USB task for performance diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 5cb8a5bb24..cd75859880 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -28,22 +28,8 @@ #include "esphome/components/socket/socket.h" #endif -#ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_HOST #include <cerrno> - -#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS -// LWIP sockets implementation -#include <lwip/sockets.h> -#elif defined(USE_SOCKET_IMPL_BSD_SOCKETS) -// BSD sockets implementation -#ifdef USE_ESP32 -// ESP32 "BSD sockets" are actually LWIP under the hood -#include <lwip/sockets.h> -#else -// True BSD sockets (e.g., host platform) -#include <sys/select.h> -#endif -#endif #endif namespace esphome { @@ -128,13 +114,11 @@ void Application::setup() { clear_setup_priority_overrides(); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) - // Initialize fast select: saves main loop task handle for xTaskNotifyGive wake. - // The fast path (rcvevent reads + ulTaskNotifyTake) is used unconditionally - // when USE_LWIP_FAST_SELECT is enabled (ESP32 and LibreTiny). - esphome_lwip_fast_select_init(); +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Save main loop task handle for wake_loop_*() / fast select FreeRTOS notifications. + esphome_main_task_handle = xTaskGetCurrentTaskHandle(); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // Set up wake socket for waking main loop from tasks (platforms without fast select only) this->setup_wake_loop_threadsafe_(); #endif @@ -490,23 +474,17 @@ void Application::unregister_socket(struct lwip_sock *sock) { return; } } -#elif defined(USE_SOCKET_SELECT_SUPPORT) +#elif defined(USE_HOST) bool Application::register_socket_fd(int fd) { // WARNING: This function is NOT thread-safe and must only be called from the main loop // It modifies socket_fds_ and related variables without locking if (fd < 0) return false; -#ifndef USE_ESP32 - // Only check on non-ESP32 platforms - // On ESP32 (both Arduino and ESP-IDF), CONFIG_LWIP_MAX_SOCKETS is always <= FD_SETSIZE by design - // (LWIP_SOCKET_OFFSET = FD_SETSIZE - CONFIG_LWIP_MAX_SOCKETS per lwipopts.h) - // Other platforms may not have this guarantee if (fd >= FD_SETSIZE) { ESP_LOGE(TAG, "fd %d exceeds FD_SETSIZE %d", fd, FD_SETSIZE); return false; } -#endif this->socket_fds_.push_back(fd); this->socket_fds_changed_ = true; @@ -547,7 +525,7 @@ void Application::unregister_socket_fd(int fd) { #endif // Only the select() fallback path remains in the .cpp — all other paths are inlined in application.h -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST void Application::yield_with_select_(uint32_t delay_ms) { // Fallback select() path (host platform and any future platforms without fast select). if (!this->socket_fds_.empty()) [[likely]] { @@ -570,11 +548,7 @@ void Application::yield_with_select_(uint32_t delay_ms) { tv.tv_usec = (delay_ms - tv.tv_sec * 1000) * 1000; // Call select with timeout -#ifdef USE_SOCKET_IMPL_LWIP_SOCKETS - int ret = lwip_select(this->max_fd_ + 1, &this->read_fds_, nullptr, nullptr, &tv); -#else int ret = ::select(this->max_fd_ + 1, &this->read_fds_, nullptr, nullptr, &tv); -#endif // Process select() result: // ret > 0: socket(s) have data ready - normal and expected @@ -597,7 +571,7 @@ void Application::yield_with_select_(uint32_t delay_ms) { // No sockets registered or select() failed - use regular delay delay(delay_ms); } -#endif // defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#endif // USE_HOST // App storage — asm label shares the linker symbol with "extern Application App". // char[] is trivially destructible, so no __cxa_atexit or destructor chain is emitted. @@ -618,18 +592,13 @@ alignas(Application) char app_storage[sizeof(Application)] asm( #undef ESPHOME_STRINGIFY_ #undef ESPHOME_STRINGIFY_IMPL_ -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) - -#ifdef USE_LWIP_FAST_SELECT -void Application::wake_loop_threadsafe() { - // Direct FreeRTOS task notification — <1 us, task context only (NOT ISR-safe) - esphome_lwip_wake_main_loop(); -} -#else // !USE_LWIP_FAST_SELECT +// Host platform wake_loop_threadsafe() and setup — needs wake_socket_fd_ +// ESP32/LibreTiny/ESP8266/RP2040 implementations are in wake.cpp +#ifdef USE_HOST void Application::setup_wake_loop_threadsafe_() { // Create UDP socket for wake notifications - this->wake_socket_fd_ = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + this->wake_socket_fd_ = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (this->wake_socket_fd_ < 0) { ESP_LOGW(TAG, "Wake socket create failed: %d", errno); return; @@ -638,12 +607,12 @@ void Application::setup_wake_loop_threadsafe_() { // Bind to loopback with auto-assigned port struct sockaddr_in addr = {}; addr.sin_family = AF_INET; - addr.sin_addr.s_addr = lwip_htonl(INADDR_LOOPBACK); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = 0; // Auto-assign port - if (lwip_bind(this->wake_socket_fd_, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + if (::bind(this->wake_socket_fd_, (struct sockaddr *) &addr, sizeof(addr)) < 0) { ESP_LOGW(TAG, "Wake socket bind failed: %d", errno); - lwip_close(this->wake_socket_fd_); + ::close(this->wake_socket_fd_); this->wake_socket_fd_ = -1; return; } @@ -652,50 +621,36 @@ void Application::setup_wake_loop_threadsafe_() { // Connecting a UDP socket allows using send() instead of sendto() for better performance struct sockaddr_in wake_addr; socklen_t len = sizeof(wake_addr); - if (lwip_getsockname(this->wake_socket_fd_, (struct sockaddr *) &wake_addr, &len) < 0) { + if (::getsockname(this->wake_socket_fd_, (struct sockaddr *) &wake_addr, &len) < 0) { ESP_LOGW(TAG, "Wake socket address failed: %d", errno); - lwip_close(this->wake_socket_fd_); + ::close(this->wake_socket_fd_); this->wake_socket_fd_ = -1; return; } // Connect to self (loopback) - allows using send() instead of sendto() // After connect(), no need to store wake_addr - the socket remembers it - if (lwip_connect(this->wake_socket_fd_, (struct sockaddr *) &wake_addr, sizeof(wake_addr)) < 0) { + if (::connect(this->wake_socket_fd_, (struct sockaddr *) &wake_addr, sizeof(wake_addr)) < 0) { ESP_LOGW(TAG, "Wake socket connect failed: %d", errno); - lwip_close(this->wake_socket_fd_); + ::close(this->wake_socket_fd_); this->wake_socket_fd_ = -1; return; } // Set non-blocking mode - int flags = lwip_fcntl(this->wake_socket_fd_, F_GETFL, 0); - lwip_fcntl(this->wake_socket_fd_, F_SETFL, flags | O_NONBLOCK); + int flags = ::fcntl(this->wake_socket_fd_, F_GETFL, 0); + ::fcntl(this->wake_socket_fd_, F_SETFL, flags | O_NONBLOCK); // Register with application's select() loop if (!this->register_socket_fd(this->wake_socket_fd_)) { ESP_LOGW(TAG, "Wake socket register failed"); - lwip_close(this->wake_socket_fd_); + ::close(this->wake_socket_fd_); this->wake_socket_fd_ = -1; return; } } -void Application::wake_loop_threadsafe() { - // Called from FreeRTOS task context when events need immediate processing - // Wakes up lwip_select() in main loop by writing to connected loopback socket - if (this->wake_socket_fd_ >= 0) { - const char dummy = 1; - // Non-blocking send - if it fails (unlikely), select() will wake on timeout anyway - // No error checking needed: we control both ends of this loopback socket. - // This is safe to call from FreeRTOS tasks - send() is thread-safe in lwip - // Socket is already connected to loopback address, so send() is faster than sendto() - lwip_send(this->wake_socket_fd_, &dummy, 1, 0); - } -} -#endif // USE_LWIP_FAST_SELECT - -#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) +#endif // USE_HOST void Application::get_build_time_string(std::span<char, BUILD_TIME_STR_SIZE> buffer) { ESPHOME_strncpy_P(buffer.data(), ESPHOME_BUILD_TIME_STR, buffer.size()); diff --git a/esphome/core/application.h b/esphome/core/application.h index 6cc61bc954..6b2969b490 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -24,32 +24,21 @@ #include "esphome/core/area.h" #endif -#ifdef USE_SOCKET_SELECT_SUPPORT #ifdef USE_LWIP_FAST_SELECT #include "esphome/core/lwip_fast_select.h" -#ifdef USE_ESP32 -#include <freertos/FreeRTOS.h> -#include <freertos/task.h> -#else -#include <FreeRTOS.h> -#include <task.h> #endif -#else +#ifdef USE_HOST #include <sys/select.h> -#ifdef USE_WAKE_LOOP_THREADSAFE -#include <lwip/sockets.h> +#include <sys/socket.h> +#include <unistd.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <arpa/inet.h> #endif -#endif -#endif // USE_SOCKET_SELECT_SUPPORT #ifdef USE_RUNTIME_STATS #include "esphome/components/runtime_stats/runtime_stats.h" #endif -#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) -namespace esphome::socket { -void socket_wake(); // NOLINT(readability-redundant-declaration) -void socket_delay(uint32_t ms); // NOLINT(readability-redundant-declaration) -} // namespace esphome::socket -#endif +#include "esphome/core/wake.h" #ifdef USE_BINARY_SENSOR #include "esphome/components/binary_sensor/binary_sensor.h" #endif @@ -124,7 +113,7 @@ void socket_delay(uint32_t ms); // NOLINT(readability-redundant-declaration) #endif namespace esphome::socket { -#ifdef USE_SOCKET_SELECT_SUPPORT +#ifdef USE_HOST /// Shared ready() helper for fd-based socket implementations. bool socket_ready_fd(int fd, bool loop_monitored); // NOLINT(readability-redundant-declaration) #endif @@ -550,7 +539,7 @@ class Application { /// @return true if registration was successful, false if sock is null bool register_socket(struct lwip_sock *sock); void unregister_socket(struct lwip_sock *sock); -#elif defined(USE_SOCKET_SELECT_SUPPORT) +#elif defined(USE_HOST) /// Fallback select() path: monitors file descriptors. /// NOTE: File descriptors >= FD_SETSIZE (typically 10 on ESP) will be rejected with an error. /// @return true if registration was successful, false if fd exceeds limits @@ -558,43 +547,21 @@ class Application { void unregister_socket_fd(int fd); #endif -#ifdef USE_WAKE_LOOP_THREADSAFE - /// Wake the main event loop from another FreeRTOS task. - /// Thread-safe, but must only be called from task context (NOT ISR-safe). - /// On ESP32: uses xTaskNotifyGive (<1 us) - /// On other platforms: uses UDP loopback socket - void wake_loop_threadsafe(); -#endif - -#ifdef USE_LWIP_FAST_SELECT - /// Wake the main event loop from an ISR. - /// Uses vTaskNotifyGiveFromISR() — <1 us, ISR-safe. - /// Only available on platforms with fast select (ESP32, LibreTiny). - /// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. - static void IRAM_ATTR wake_loop_isrsafe(int *px_higher_priority_task_woken) { - esphome_lwip_wake_main_loop_from_isr(px_higher_priority_task_woken); - } + /// Wake the main event loop from another thread or callback. + /// @see esphome::wake_loop_threadsafe() in wake.h for platform details. + void wake_loop_threadsafe() { esphome::wake_loop_threadsafe(); } #ifdef USE_ESP32 - /// Wake the main event loop from any context (ISR, thread, or main loop). - /// Detects the calling context and uses the appropriate FreeRTOS API. - static void IRAM_ATTR wake_loop_any_context() { esphome_lwip_wake_main_loop_any_context(); } -#endif + /// Wake from ISR (ESP32 only). + static void IRAM_ATTR wake_loop_isrsafe(BaseType_t *px) { esphome::wake_loop_isrsafe(px); } #endif -#if defined(USE_ESP8266) && defined(USE_SOCKET_IMPL_LWIP_TCP) - /// Wake the main event loop from any context (ISR, thread, or main loop). - /// Sets the socket wake flag and calls esp_schedule() to exit esp_delay() early. - static void IRAM_ATTR wake_loop_any_context() { socket::socket_wake(); } -#elif defined(USE_RP2040) && defined(USE_SOCKET_IMPL_LWIP_TCP) - /// Wake the main event loop from any context. - /// Sets the socket wake flag and calls __sev() to exit __wfe() early. - static void wake_loop_any_context() { socket::socket_wake(); } -#endif + /// Wake from any context (ISR, thread, callback). + static void IRAM_ATTR wake_loop_any_context() { esphome::wake_loop_any_context(); } protected: friend Component; -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST friend bool socket::socket_ready_fd(int fd, bool loop_monitored); #endif #ifdef USE_RUNTIME_STATS @@ -602,8 +569,11 @@ class Application { #endif friend void ::setup(); friend void ::original_setup(); +#ifdef USE_HOST + friend void wake_loop_threadsafe(); // Host platform accesses wake_socket_fd_ +#endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST bool is_socket_ready_(int fd) const { return FD_ISSET(fd, &this->read_fds_); } #endif @@ -648,14 +618,14 @@ class Application { void feed_wdt_arch_(); /// Perform a delay while also monitoring socket file descriptors for readiness -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // select() fallback path is too complex to inline (host platform) void yield_with_select_(uint32_t delay_ms); #else inline void ESPHOME_ALWAYS_INLINE yield_with_select_(uint32_t delay_ms); #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST void setup_wake_loop_threadsafe_(); // Create wake notification socket inline void drain_wake_notifications_(); // Read pending wake notifications in main loop (hot path - inlined) #endif @@ -685,13 +655,11 @@ class Application { FixedVector<Component *> looping_components_{}; #ifdef USE_LWIP_FAST_SELECT std::vector<struct lwip_sock *> monitored_sockets_; // Cached lwip_sock pointers for direct rcvevent read -#elif defined(USE_SOCKET_SELECT_SUPPORT) +#elif defined(USE_HOST) std::vector<int> socket_fds_; // Vector of all monitored socket file descriptors #endif -#ifdef USE_SOCKET_SELECT_SUPPORT -#if defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST int wake_socket_fd_{-1}; // Shared wake notification socket for waking main loop from tasks -#endif #endif // StringRef members (8 bytes each: pointer + size) @@ -702,7 +670,7 @@ class Application { uint32_t last_loop_{0}; uint32_t loop_component_start_time_{0}; -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST int max_fd_{-1}; // Highest file descriptor number for select() #endif @@ -718,11 +686,11 @@ class Application { bool in_loop_{false}; volatile bool has_pending_enable_loop_requests_{false}; -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST bool socket_fds_changed_{false}; // Flag to rebuild base_read_fds_ when socket_fds_ changes #endif -#if defined(USE_SOCKET_SELECT_SUPPORT) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // Variable-sized members (not needed with fast select — is_socket_ready_ reads rcvevent directly) fd_set read_fds_{}; // Working fd_set: populated by select() fd_set base_read_fds_{}; // Cached fd_set rebuilt only when socket_fds_ changes @@ -815,7 +783,7 @@ class Application { /// Global storage of Application pointer - only one Application can exist. extern Application App; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // Inline implementations for hot-path functions // drain_wake_notifications_() is called on every loop iteration @@ -832,15 +800,15 @@ inline void Application::drain_wake_notifications_() { // Multiple wake events may have triggered multiple writes, so drain until EWOULDBLOCK // We control both ends of this loopback socket (always write 1 byte per wake), // so no error checking needed - any errors indicate catastrophic system failure - while (lwip_recvfrom(this->wake_socket_fd_, buffer, sizeof(buffer), 0, nullptr, nullptr) > 0) { + while (::recvfrom(this->wake_socket_fd_, buffer, sizeof(buffer), 0, nullptr, nullptr) > 0) { // Just draining, no action needed - wake has already occurred } } } -#endif // defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#endif // USE_HOST inline void ESPHOME_ALWAYS_INLINE Application::before_loop_tasks_(uint32_t loop_start_time) { -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE) && !defined(USE_LWIP_FAST_SELECT) +#ifdef USE_HOST // Drain wake notifications first to clear socket for next wake this->drain_wake_notifications_(); #endif @@ -908,21 +876,17 @@ inline void ESPHOME_ALWAYS_INLINE Application::loop() { #endif // Use the last component's end time instead of calling millis() again + uint32_t delay_time = 0; auto elapsed = last_op_end_time - this->last_loop_; - if (elapsed >= this->loop_interval_ || HighFrequencyLoopRequester::is_high_frequency()) { - // Even if we overran the loop interval, we still need to select() - // to know if any sockets have data ready - this->yield_with_select_(0); - } else { - uint32_t delay_time = this->loop_interval_ - elapsed; + if (elapsed < this->loop_interval_ && !HighFrequencyLoopRequester::is_high_frequency()) { + delay_time = this->loop_interval_ - elapsed; uint32_t next_schedule = this->scheduler.next_schedule_in(last_op_end_time).value_or(delay_time); // next_schedule is max 0.5*delay_time // otherwise interval=0 schedules result in constant looping with almost no sleep next_schedule = std::max(next_schedule, delay_time / 2); delay_time = std::min(next_schedule, delay_time); - - this->yield_with_select_(delay_time); } + this->yield_with_select_(delay_time); this->last_loop_ = last_op_end_time; if (this->dump_config_at_ < this->components_.size()) { @@ -931,9 +895,9 @@ inline void ESPHOME_ALWAYS_INLINE Application::loop() { } // Inline yield_with_select_ for all paths except the select() fallback -#if !defined(USE_SOCKET_SELECT_SUPPORT) || defined(USE_LWIP_FAST_SELECT) +#ifndef USE_HOST inline void ESPHOME_ALWAYS_INLINE Application::yield_with_select_(uint32_t delay_ms) { -#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_LWIP_FAST_SELECT) +#ifdef USE_LWIP_FAST_SELECT // Fast path (ESP32/LibreTiny): reads rcvevent directly from cached lwip_sock pointers. // Safe because this runs on the main loop which owns socket lifetime (create, read, close). if (delay_ms == 0) [[unlikely]] { @@ -953,20 +917,10 @@ inline void ESPHOME_ALWAYS_INLINE Application::yield_with_select_(uint32_t delay } // Sleep with instant wake via FreeRTOS task notification. - // Woken by: callback wrapper (socket data arrives), wake_loop_threadsafe() (other tasks), or timeout. - // Without USE_WAKE_LOOP_THREADSAFE, only hooked socket callbacks wake the task — - // background tasks won't call wake, so this degrades to a pure timeout (same as old select path). - ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(delay_ms)); -#elif (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP) - // No select support but can wake on socket activity - // ESP8266: via esp_schedule() - // RP2040: via __sev()/__wfe() hardware sleep/wake - socket::socket_delay(delay_ms); -#else - // No select support, use regular delay - delay(delay_ms); + // Woken by: callback wrapper (socket data), wake_loop_threadsafe() (background tasks), or timeout. #endif + esphome::internal::wakeable_delay(delay_ms); } -#endif // !defined(USE_SOCKET_SELECT_SUPPORT) || defined(USE_LWIP_FAST_SELECT) +#endif // !USE_HOST } // namespace esphome diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 0f68f0c8e0..deda42b0a7 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -299,7 +299,7 @@ void Component::enable_loop_slow_path_() { this->set_component_state_(COMPONENT_STATE_LOOP); App.enable_component_loop_(this); } -void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { +void IRAM_ATTR Component::enable_loop_soon_any_context() { // This method is thread and ISR-safe because: // 1. Only performs simple assignments to volatile variables (atomic on all platforms) // 2. No read-modify-write operations that could be interrupted @@ -311,15 +311,9 @@ void IRAM_ATTR HOT Component::enable_loop_soon_any_context() { // 8. Race condition with main loop is handled by clearing flag before processing this->pending_enable_loop_ = true; App.has_pending_enable_loop_requests_ = true; -#if (defined(USE_LWIP_FAST_SELECT) && defined(USE_ESP32)) || \ - ((defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_SOCKET_IMPL_LWIP_TCP)) // Wake the main loop from sleep. Without this, the main loop would not // wake until the select/delay timeout expires (~16ms). - // ESP32: uses xPortInIsrContext() to choose the correct FreeRTOS notify API. - // ESP8266: sets socket wake flag and calls esp_schedule() to exit esp_delay() early. - // RP2040: sets socket wake flag and calls __sev() to exit __wfe() early. - Application::wake_loop_any_context(); -#endif + wake_loop_any_context(); } void Component::reset_to_construction_state() { if ((this->component_state_ & COMPONENT_STATE_MASK) == COMPONENT_STATE_FAILED) { diff --git a/esphome/core/config.py b/esphome/core/config.py index c47693c783..62c41b254c 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -753,6 +753,20 @@ FILTER_SOURCE_FILES = filter_source_files_from_platform( PlatformFramework.ESP32_ARDUINO, PlatformFramework.ESP32_IDF, }, + "main_task.c": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, + PlatformFramework.BK72XX_ARDUINO, + PlatformFramework.RTL87XX_ARDUINO, + PlatformFramework.LN882X_ARDUINO, + }, + "lwip_fast_select.c": { + PlatformFramework.ESP32_ARDUINO, + PlatformFramework.ESP32_IDF, + PlatformFramework.BK72XX_ARDUINO, + PlatformFramework.RTL87XX_ARDUINO, + PlatformFramework.LN882X_ARDUINO, + }, "time_64.cpp": { PlatformFramework.ESP8266_ARDUINO, PlatformFramework.BK72XX_ARDUINO, diff --git a/esphome/core/defines.h b/esphome/core/defines.h index d92fb6e98a..9c90790f3a 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -252,9 +252,8 @@ #define USE_SENDSPIN #define USE_SENDSPIN_PORT 8928 // NOLINT #define USE_SOCKET_IMPL_BSD_SOCKETS -#define USE_SOCKET_SELECT_SUPPORT #define USE_LWIP_FAST_SELECT -#define USE_WAKE_LOOP_THREADSAFE + #define USE_SPEAKER #define USE_SPEAKER_MEDIA_PLAYER_ON_OFF #define USE_SPI @@ -379,7 +378,6 @@ #ifdef USE_LIBRETINY #define USE_CAPTIVE_PORTAL #define USE_SOCKET_IMPL_LWIP_SOCKETS -#define USE_SOCKET_SELECT_SUPPORT #define USE_LWIP_FAST_SELECT #define USE_WEBSERVER #define USE_WEBSERVER_AUTH @@ -391,7 +389,6 @@ #ifdef USE_HOST #define USE_HTTP_REQUEST_RESPONSE #define USE_SOCKET_IMPL_BSD_SOCKETS -#define USE_SOCKET_SELECT_SUPPORT #define USE_ESPHOME_TASK_LOG_BUFFER #define ESPHOME_TASK_LOG_BUFFER_SIZE 64 #endif diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index a695fa396b..bb3acbafcb 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -63,12 +63,12 @@ // // Shared state and safety rationale: // -// s_main_loop_task (TaskHandle_t, 4 bytes): -// Written once by main loop in init(). Read by TCP/IP thread (in callback) -// and background tasks (in wake). -// Safe: write-once-then-read pattern. Socket hooks may run before init(), -// but the NULL check on s_main_loop_task in the callback provides correct -// degraded behavior — notifications are simply skipped until init() completes. +// esphome_main_task_handle (TaskHandle_t, 4 bytes, defined in main_task.c): +// Written once by main loop in Application::setup(). Read by TCP/IP thread +// (in callback) and background tasks (in wake). +// Safe: write-once-then-read pattern. Socket hooks may run before setup(), +// but the NULL check on esphome_main_task_handle in the callback provides correct +// degraded behavior — notifications are simply skipped until setup() completes. // // s_original_callback (netconn_callback, 4-byte function pointer): // Written by main loop in hook_socket() (only when NULL — set once). @@ -123,15 +123,10 @@ #endif #include "esphome/core/lwip_fast_select.h" +#include "esphome/core/main_task.h" #include <stddef.h> -// IRAM_ATTR is defined by esp_attr.h (included via FreeRTOS headers) on ESP32. -// On LibreTiny it's not defined — provide a no-op fallback. -#ifndef IRAM_ATTR -#define IRAM_ATTR -#endif - // Compile-time verification of thread safety assumptions. // On ESP32 (Xtensa/RISC-V) and LibreTiny (ARM Cortex-M), naturally-aligned // reads/writes up to 32 bits are atomic. @@ -157,8 +152,7 @@ _Static_assert(offsetof(struct lwip_sock, rcvevent) % sizeof(((struct lwip_sock _Static_assert(offsetof(struct lwip_sock, rcvevent) == ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET, "lwip_sock.rcvevent offset changed — update ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET in lwip_fast_select.h"); -// Task handle for the main loop — written once in init(), read from TCP/IP and background tasks. -static TaskHandle_t s_main_loop_task = NULL; +// Task handle is in main_task.c (esphome_main_task_handle) — shared with wake.h. // Saved original event_callback pointer — written once in first hook_socket(), read from TCP/IP task. static netconn_callback s_original_callback = NULL; @@ -177,15 +171,13 @@ static void esphome_socket_event_callback(struct netconn *conn, enum netconn_evt // (rcvevent++ with a NULL pbuf or error in recvmbox), so error conditions // already wake the main loop through the RCVPLUS path. if (evt == NETCONN_EVT_RCVPLUS) { - TaskHandle_t task = s_main_loop_task; + TaskHandle_t task = esphome_main_task_handle; if (task != NULL) { xTaskNotifyGive(task); } } } -void esphome_lwip_fast_select_init(void) { s_main_loop_task = xTaskGetCurrentTaskHandle(); } - // lwip_socket_dbg_get_socket() is a thin wrapper around the static // tryget_socket_unconn_nouse() — a direct array lookup without the refcount // that get_socket()/done_socket() uses. This is safe because: @@ -232,35 +224,4 @@ bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable) { return true; } -// Wake the main loop from another FreeRTOS task. NOT ISR-safe. -void esphome_lwip_wake_main_loop(void) { - TaskHandle_t task = s_main_loop_task; - if (task != NULL) { - xTaskNotifyGive(task); - } -} - -// Wake the main loop from an ISR. ISR-safe variant. -void IRAM_ATTR esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken) { - TaskHandle_t task = s_main_loop_task; - if (task != NULL) { - vTaskNotifyGiveFromISR(task, (BaseType_t *) px_higher_priority_task_woken); - } -} - -// Wake the main loop from any context (ISR, thread, or main loop). -// ESP32-only: uses xPortInIsrContext() to detect ISR context. -// LibreTiny is excluded because it lacks IRAM_ATTR support needed for ISR-safe paths. -#ifdef USE_ESP32 -void IRAM_ATTR esphome_lwip_wake_main_loop_any_context(void) { - if (xPortInIsrContext()) { - int px_higher_priority_task_woken = 0; - esphome_lwip_wake_main_loop_from_isr(&px_higher_priority_task_woken); - portYIELD_FROM_ISR(px_higher_priority_task_woken); - } else { - esphome_lwip_wake_main_loop(); - } -} -#endif - #endif // USE_LWIP_FAST_SELECT diff --git a/esphome/core/lwip_fast_select.h b/esphome/core/lwip_fast_select.h index 50706ba9f6..20ac191673 100644 --- a/esphome/core/lwip_fast_select.h +++ b/esphome/core/lwip_fast_select.h @@ -20,10 +20,6 @@ enum { ESPHOME_LWIP_SOCK_RCVEVENT_OFFSET = 8 }; extern "C" { #endif -/// Initialize fast select — must be called from the main loop task during setup(). -/// Saves the current task handle for xTaskNotifyGive() wake notifications. -void esphome_lwip_fast_select_init(void); - /// Look up a LwIP socket struct from a file descriptor. /// Returns NULL if fd is invalid or the socket/netconn is not initialized. /// Use this at registration time to cache the pointer for esphome_lwip_socket_has_data(). @@ -57,15 +53,6 @@ static inline bool esphome_lwip_socket_has_data(struct lwip_sock *sock) { /// The sock pointer must have been obtained from esphome_lwip_get_sock(). void esphome_lwip_hook_socket(struct lwip_sock *sock); -/// Wake the main loop task from another FreeRTOS task — costs <1 us. -/// NOT ISR-safe — must only be called from task context. -void esphome_lwip_wake_main_loop(void); - -/// Wake the main loop task from an ISR — costs <1 us. -/// ISR-safe variant using vTaskNotifyGiveFromISR(). -/// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed. -void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); - /// Set or clear TCP_NODELAY on a socket's tcp_pcb directly. /// Must be called with the TCPIP core lock held (LwIPLock in C++). /// This bypasses lwip_setsockopt() overhead (socket lookups, switch cascade, @@ -73,13 +60,6 @@ void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken); /// Returns true if successful, false if sock/conn/pcb is NULL or the socket is not TCP. bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable); -/// Wake the main loop task from any context (ISR, thread, or main loop). -/// ESP32-only: uses xPortInIsrContext() to detect ISR context. -/// LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths. -#ifdef USE_ESP32 -void esphome_lwip_wake_main_loop_any_context(void); -#endif - #ifdef __cplusplus } #endif diff --git a/esphome/core/main_task.c b/esphome/core/main_task.c new file mode 100644 index 0000000000..52d9c2951a --- /dev/null +++ b/esphome/core/main_task.c @@ -0,0 +1,5 @@ +#include "esphome/core/main_task.h" + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) +TaskHandle_t esphome_main_task_handle = NULL; +#endif diff --git a/esphome/core/main_task.h b/esphome/core/main_task.h new file mode 100644 index 0000000000..ed2885d2e2 --- /dev/null +++ b/esphome/core/main_task.h @@ -0,0 +1,55 @@ +#pragma once + +/// Main loop task handle and wake helpers — shared between wake.h (C++) and lwip_fast_select.c (C). +/// esphome_main_task_handle is set once during Application::setup() via xTaskGetCurrentTaskHandle(). + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + +#ifdef USE_ESP32 +#include <freertos/FreeRTOS.h> +#include <freertos/task.h> +#else +#include <FreeRTOS.h> +#include <task.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +extern TaskHandle_t esphome_main_task_handle; + +/// Wake the main loop task from another FreeRTOS task. NOT ISR-safe. +static inline void esphome_main_task_notify() { + TaskHandle_t task = esphome_main_task_handle; + if (task != NULL) { + xTaskNotifyGive(task); + } +} + +/// Wake the main loop task from an ISR. ISR-safe. +static inline void esphome_main_task_notify_from_isr(BaseType_t *px_higher_priority_task_woken) { + TaskHandle_t task = esphome_main_task_handle; + if (task != NULL) { + vTaskNotifyGiveFromISR(task, px_higher_priority_task_woken); + } +} + +#ifdef USE_ESP32 +/// Wake the main loop from any context (ISR or task). ESP32-only (needs xPortInIsrContext). +static inline void esphome_main_task_notify_any_context() { + if (xPortInIsrContext()) { + int px_higher_priority_task_woken = 0; + esphome_main_task_notify_from_isr(&px_higher_priority_task_woken); + portYIELD_FROM_ISR(px_higher_priority_task_woken); + } else { + esphome_main_task_notify(); + } +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif // USE_ESP32 || USE_LIBRETINY diff --git a/esphome/core/wake.cpp b/esphome/core/wake.cpp new file mode 100644 index 0000000000..b6b59b5990 --- /dev/null +++ b/esphome/core/wake.cpp @@ -0,0 +1,82 @@ +#include "esphome/core/wake.h" +#include "esphome/core/hal.h" + +#ifdef USE_ESP8266 +#include <coredecls.h> +#endif + +#ifdef USE_HOST +#include "esphome/core/application.h" +#include <sys/socket.h> +#endif + +namespace esphome { + +// === ESP32 — IRAM_ATTR entry points === +#ifdef USE_ESP32 +void IRAM_ATTR wake_loop_isrsafe(BaseType_t *px_higher_priority_task_woken) { + esphome_main_task_notify_from_isr(px_higher_priority_task_woken); +} +void IRAM_ATTR wake_loop_any_context() { esphome_main_task_notify_any_context(); } +#endif + +// === ESP8266 / RP2040 === +#if defined(USE_ESP8266) || defined(USE_RP2040) +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +volatile bool g_main_loop_woke = false; +#endif + +#ifdef USE_ESP8266 +void IRAM_ATTR wake_loop_any_context() { wake_loop_impl(); } +#endif + +// === RP2040 — wakeable_delay (needs file-scope state for alarm callback) === +#ifdef USE_RP2040 +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +static volatile bool s_delay_expired = false; + +static int64_t alarm_callback_(alarm_id_t id, void *user_data) { + (void) id; + (void) user_data; + s_delay_expired = true; + __sev(); + return 0; +} + +namespace internal { +void wakeable_delay(uint32_t ms) { + if (ms == 0) { + yield(); + return; + } + if (g_main_loop_woke) { + g_main_loop_woke = false; + return; + } + s_delay_expired = false; + alarm_id_t alarm = add_alarm_in_ms(ms, alarm_callback_, nullptr, true); + if (alarm <= 0) { + delay(ms); + return; + } + while (!g_main_loop_woke && !s_delay_expired) { + __wfe(); + } + if (!s_delay_expired) + cancel_alarm(alarm); + g_main_loop_woke = false; +} +} // namespace internal +#endif // USE_RP2040 + +// === Host (UDP loopback socket) === +#ifdef USE_HOST +void wake_loop_threadsafe() { + if (App.wake_socket_fd_ >= 0) { + const char dummy = 1; + ::send(App.wake_socket_fd_, &dummy, 1, 0); + } +} +#endif + +} // namespace esphome diff --git a/esphome/core/wake.h b/esphome/core/wake.h new file mode 100644 index 0000000000..a8c9b7ad08 --- /dev/null +++ b/esphome/core/wake.h @@ -0,0 +1,126 @@ +#pragma once + +/// @file wake.h +/// Platform-specific main loop wake primitives. +/// Always available on all platforms — no opt-in needed. + +#include "esphome/core/defines.h" +#include "esphome/core/hal.h" + +#if defined(USE_ESP32) || defined(USE_LIBRETINY) +#include "esphome/core/main_task.h" +#endif +#ifdef USE_ESP8266 +#include <coredecls.h> +#elif defined(USE_RP2040) +#include <hardware/sync.h> +#include <pico/time.h> +#endif + +namespace esphome { + +// === Wake flag for ESP8266/RP2040 === +#if defined(USE_ESP8266) || defined(USE_RP2040) +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +extern volatile bool g_main_loop_woke; +#endif + +// === ESP32 / LibreTiny (FreeRTOS) === +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + +#ifdef USE_ESP32 +/// IRAM_ATTR entry point — defined in wake.cpp. +void wake_loop_isrsafe(BaseType_t *px_higher_priority_task_woken); +/// IRAM_ATTR entry point — defined in wake.cpp. +void wake_loop_any_context(); +#else +/// LibreTiny: IRAM_ATTR is not functional and the FreeRTOS port does not +/// provide vTaskNotifyGiveFromISR/portYIELD_FROM_ISR, so ISR-safe wake +/// is not possible. xTaskNotifyGive is used as the best available option. +inline void wake_loop_any_context() { esphome_main_task_notify(); } +#endif + +inline void wake_loop_threadsafe() { esphome_main_task_notify(); } + +namespace internal { +inline void wakeable_delay(uint32_t ms) { + if (ms == 0) { + yield(); + return; + } + ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(ms)); +} +} // namespace internal + +// === ESP8266 === +#elif defined(USE_ESP8266) + +/// Inline implementation — IRAM callers inline this directly. +inline void ESPHOME_ALWAYS_INLINE wake_loop_impl() { + g_main_loop_woke = true; + esp_schedule(); +} + +/// IRAM_ATTR entry point for ISR callers — defined in wake.cpp. +void wake_loop_any_context(); + +/// Non-ISR: always inline. +inline void wake_loop_threadsafe() { wake_loop_impl(); } + +namespace internal { +inline void wakeable_delay(uint32_t ms) { + if (ms == 0) { + delay(0); + return; + } + if (g_main_loop_woke) { + g_main_loop_woke = false; + return; + } + esp_delay(ms, []() { return !g_main_loop_woke; }); +} +} // namespace internal + +// === RP2040 === +#elif defined(USE_RP2040) + +inline void wake_loop_any_context() { + g_main_loop_woke = true; + __sev(); +} + +inline void wake_loop_threadsafe() { wake_loop_any_context(); } + +/// RP2040 wakeable delay uses file-scope state (alarm callback + flag) — defined in wake.cpp. +namespace internal { +void wakeable_delay(uint32_t ms); +} // namespace internal + +// === Host / Zephyr / other === +#else + +#ifdef USE_HOST +/// Host: wakes select() via UDP loopback socket. Defined in wake.cpp. +void wake_loop_threadsafe(); +#else +/// Zephyr is currently the only platform without a wake mechanism. +/// wake_loop_threadsafe() is a no-op and wakeable_delay() falls back to delay(). +/// TODO: implement proper Zephyr wake using k_poll / k_sem or similar. +inline void wake_loop_threadsafe() {} +#endif + +inline void wake_loop_any_context() { wake_loop_threadsafe(); } + +namespace internal { +inline void wakeable_delay(uint32_t ms) { + if (ms == 0) { + yield(); + return; + } + delay(ms); +} +} // namespace internal + +#endif + +} // namespace esphome diff --git a/tests/components/socket/test_wake_loop_threadsafe.py b/tests/components/socket/test_wake_loop_threadsafe.py deleted file mode 100644 index 0434b3e1b5..0000000000 --- a/tests/components/socket/test_wake_loop_threadsafe.py +++ /dev/null @@ -1,127 +0,0 @@ -import pytest - -from esphome.components import socket -from esphome.const import ( - KEY_CORE, - KEY_TARGET_PLATFORM, - PLATFORM_BK72XX, - PLATFORM_ESP32, - PLATFORM_ESP8266, - PLATFORM_LN882X, - PLATFORM_RTL87XX, -) -from esphome.core import CORE - - -def _setup_platform(platform=PLATFORM_ESP8266) -> None: - """Set up CORE.data with a platform for testing.""" - CORE.data[KEY_CORE] = {KEY_TARGET_PLATFORM: platform} - - -def test_require_wake_loop_threadsafe__first_call() -> None: - """Test that first call sets up define and consumes socket.""" - _setup_platform() - CORE.config = {"wifi": True} - socket.require_wake_loop_threadsafe() - - # Verify CORE.data was updated - assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True - - # Verify the define was added - assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - - -def test_require_wake_loop_threadsafe__idempotent() -> None: - """Test that subsequent calls are idempotent.""" - # Set up initial state as if already called - CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] = True - CORE.config = {"ethernet": True} - - # Call again - should not raise or fail - socket.require_wake_loop_threadsafe() - - # Verify state is still True - assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True - - # Define should not be added since flag was already True - assert not any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - - -def test_require_wake_loop_threadsafe__multiple_calls() -> None: - """Test that multiple calls only set up once.""" - _setup_platform() - # Call three times - CORE.config = {"openthread": True} - socket.require_wake_loop_threadsafe() - socket.require_wake_loop_threadsafe() - socket.require_wake_loop_threadsafe() - - # Verify CORE.data was set - assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True - - # Verify the define was added (only once, but we can just check it exists) - assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - - -def test_require_wake_loop_threadsafe__no_networking() -> None: - """Test that wake loop is NOT configured when no networking is configured.""" - # Set up config without any networking components - CORE.config = {"esphome": {"name": "test"}, "logger": {}} - - # Call require_wake_loop_threadsafe - socket.require_wake_loop_threadsafe() - - # Verify CORE.data flag was NOT set (since has_networking returns False) - assert socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED not in CORE.data - - # Verify the define was NOT added - assert not any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - - -def test_require_wake_loop_threadsafe__no_networking_does_not_consume_socket() -> None: - """Test that no socket is consumed when no networking is configured.""" - # Set up config without any networking components - CORE.config = {"logger": {}} - - # Track initial socket consumer state - initial_udp = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) - - # Call require_wake_loop_threadsafe - socket.require_wake_loop_threadsafe() - - # Verify no socket was consumed - udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) - assert "socket.wake_loop_threadsafe" not in udp_consumers - assert udp_consumers == initial_udp - - -@pytest.mark.parametrize( - "platform", - [PLATFORM_ESP32, PLATFORM_BK72XX, PLATFORM_RTL87XX, PLATFORM_LN882X], -) -def test_require_wake_loop_threadsafe__fast_select_no_udp_socket( - platform: str, -) -> None: - """Test that fast select platforms use task notifications instead of UDP socket.""" - _setup_platform(platform) - CORE.config = {"wifi": True} - socket.require_wake_loop_threadsafe() - - # Verify the define was added - assert CORE.data[socket.KEY_WAKE_LOOP_THREADSAFE_REQUIRED] is True - assert any(d.name == "USE_WAKE_LOOP_THREADSAFE" for d in CORE.defines) - - # Verify no UDP socket was consumed (fast select platforms use FreeRTOS task notifications) - udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) - assert "socket.wake_loop_threadsafe" not in udp_consumers - - -def test_require_wake_loop_threadsafe__non_fast_select_consumes_udp_socket() -> None: - """Test that platforms without fast select consume a UDP socket for wake notifications.""" - _setup_platform(PLATFORM_ESP8266) - CORE.config = {"wifi": True} - socket.require_wake_loop_threadsafe() - - # Verify UDP socket was consumed - udp_consumers = CORE.data.get(socket.KEY_SOCKET_CONSUMERS_UDP, {}) - assert udp_consumers.get("socket.wake_loop_threadsafe") == 1 From 95e2b0a8b051e989e7d01e26dffbff2a65411354 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:02:20 -0400 Subject: [PATCH 1967/2030] [multiple] Add missing device_class to sensor schemas (#15479) --- esphome/components/alpha3/sensor.py | 13 +++++++++++++ esphome/components/atm90e26/sensor.py | 2 ++ esphome/components/atm90e32/sensor.py | 2 ++ esphome/components/growatt_solar/sensor.py | 6 ++++++ esphome/components/havells_solar/sensor.py | 5 +++++ esphome/components/hydreon_rgxx/sensor.py | 2 ++ esphome/components/mlx90393/sensor.py | 2 ++ esphome/components/pipsolar/sensor/__init__.py | 13 +++++++++++++ esphome/components/pzemac/sensor.py | 2 ++ esphome/components/sdm_meter/sensor.py | 9 ++++++++- esphome/components/selec_meter/sensor.py | 5 +++++ esphome/components/teleinfo/sensor/__init__.py | 10 +++++++++- 12 files changed, 69 insertions(+), 2 deletions(-) diff --git a/esphome/components/alpha3/sensor.py b/esphome/components/alpha3/sensor.py index 361e1d101f..279ab214cf 100644 --- a/esphome/components/alpha3/sensor.py +++ b/esphome/components/alpha3/sensor.py @@ -9,6 +9,10 @@ from esphome.const import ( CONF_POWER, CONF_SPEED, CONF_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_POWER, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, UNIT_AMPERE, UNIT_CUBIC_METER_PER_HOUR, UNIT_METER, @@ -27,26 +31,35 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_FLOW): sensor.sensor_schema( unit_of_measurement=UNIT_CUBIC_METER_PER_HOUR, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_HEAD): sensor.sensor_schema( unit_of_measurement=UNIT_METER, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, accuracy_decimals=2, + device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CURRENT): sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, accuracy_decimals=2, + device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_SPEED): sensor.sensor_schema( unit_of_measurement=UNIT_REVOLUTIONS_PER_MINUTE, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=2, + device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), } ) diff --git a/esphome/components/atm90e26/sensor.py b/esphome/components/atm90e26/sensor.py index 4522e94846..5941cb35b4 100644 --- a/esphome/components/atm90e26/sensor.py +++ b/esphome/components/atm90e26/sensor.py @@ -14,6 +14,7 @@ from esphome.const import ( CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_REACTIVE_POWER, @@ -103,6 +104,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=1, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True), diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index a510095217..0944950432 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -20,6 +20,7 @@ from esphome.const import ( DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_REACTIVE_POWER, @@ -166,6 +167,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=1, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CHIP_TEMPERATURE): sensor.sensor_schema( diff --git a/esphome/components/growatt_solar/sensor.py b/esphome/components/growatt_solar/sensor.py index 19f3adfd0e..7458b88b72 100644 --- a/esphome/components/growatt_solar/sensor.py +++ b/esphome/components/growatt_solar/sensor.py @@ -12,7 +12,9 @@ from esphome.const import ( CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, ICON_CURRENT_AC, STATE_CLASS_MEASUREMENT, @@ -53,6 +55,7 @@ PHASE_SENSORS = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, @@ -72,6 +75,7 @@ PV_SENSORS = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, @@ -118,6 +122,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=2, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ACTIVE_POWER): sensor.sensor_schema( @@ -147,6 +152,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_INVERTER_MODULE_TEMP): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, + device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), } diff --git a/esphome/components/havells_solar/sensor.py b/esphome/components/havells_solar/sensor.py index 532315a1d1..a876acd79b 100644 --- a/esphome/components/havells_solar/sensor.py +++ b/esphome/components/havells_solar/sensor.py @@ -13,6 +13,7 @@ from esphome.const import ( CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, ICON_CURRENT_AC, @@ -64,6 +65,7 @@ PHASE_SENSORS = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=2, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, @@ -77,6 +79,7 @@ PV_SENSORS = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=2, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, @@ -123,6 +126,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=2, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ACTIVE_POWER): sensor.sensor_schema( @@ -171,6 +175,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_INVERTER_BUS_VOLTAGE): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=0, + device_class=DEVICE_CLASS_VOLTAGE, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_INSULATION_OF_PV_N_TO_GROUND): sensor.sensor_schema( diff --git a/esphome/components/hydreon_rgxx/sensor.py b/esphome/components/hydreon_rgxx/sensor.py index f270b72e24..fdb606182f 100644 --- a/esphome/components/hydreon_rgxx/sensor.py +++ b/esphome/components/hydreon_rgxx/sensor.py @@ -9,6 +9,7 @@ from esphome.const import ( CONF_TEMPERATURE, DEVICE_CLASS_PRECIPITATION, DEVICE_CLASS_PRECIPITATION_INTENSITY, + DEVICE_CLASS_TEMPERATURE, ICON_THERMOMETER, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, @@ -117,6 +118,7 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=0, icon=ICON_THERMOMETER, + device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DISABLE_LED): cv.boolean, diff --git a/esphome/components/mlx90393/sensor.py b/esphome/components/mlx90393/sensor.py index 293a133c3d..a6330b1cc0 100644 --- a/esphome/components/mlx90393/sensor.py +++ b/esphome/components/mlx90393/sensor.py @@ -10,6 +10,7 @@ from esphome.const import ( CONF_RESOLUTION, CONF_TEMPERATURE, CONF_TEMPERATURE_COMPENSATION, + DEVICE_CLASS_TEMPERATURE, ICON_MAGNET, ICON_THERMOMETER, STATE_CLASS_MEASUREMENT, @@ -107,6 +108,7 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, icon=ICON_THERMOMETER, + device_class=DEVICE_CLASS_TEMPERATURE, state_class=STATE_CLASS_MEASUREMENT, ).extend( cv.Schema( diff --git a/esphome/components/pipsolar/sensor/__init__.py b/esphome/components/pipsolar/sensor/__init__.py index 8d3ba10d62..88c6566d63 100644 --- a/esphome/components/pipsolar/sensor/__init__.py +++ b/esphome/components/pipsolar/sensor/__init__.py @@ -102,46 +102,56 @@ TYPES = { unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=1, + device_class=DEVICE_CLASS_FREQUENCY, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_AC_OUTPUT_RATING_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, accuracy_decimals=1, device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_AC_OUTPUT_RATING_APPARENT_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS, accuracy_decimals=0, device_class=DEVICE_CLASS_APPARENT_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_AC_OUTPUT_RATING_ACTIVE_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_WATT, accuracy_decimals=0, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_RATING_VOLTAGE: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_RECHARGE_VOLTAGE: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_UNDER_VOLTAGE: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_BULK_VOLTAGE: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_FLOAT_VOLTAGE: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_BATTERY_TYPE: sensor.sensor_schema( accuracy_decimals=0, @@ -150,11 +160,13 @@ TYPES = { unit_of_measurement=UNIT_AMPERE, accuracy_decimals=0, device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT_MAX_CHARGING_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, accuracy_decimals=0, device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_INPUT_VOLTAGE_RANGE: sensor.sensor_schema( accuracy_decimals=0, @@ -294,6 +306,7 @@ TYPES = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_EEPROM_VERSION: sensor.sensor_schema( accuracy_decimals=0, diff --git a/esphome/components/pzemac/sensor.py b/esphome/components/pzemac/sensor.py index fa1c3961d0..c134bc19c1 100644 --- a/esphome/components/pzemac/sensor.py +++ b/esphome/components/pzemac/sensor.py @@ -13,6 +13,7 @@ from esphome.const import ( CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_VOLTAGE, @@ -66,6 +67,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=1, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( diff --git a/esphome/components/sdm_meter/sensor.py b/esphome/components/sdm_meter/sensor.py index affbc0409e..9687357f5e 100644 --- a/esphome/components/sdm_meter/sensor.py +++ b/esphome/components/sdm_meter/sensor.py @@ -19,8 +19,10 @@ from esphome.const import ( CONF_REACTIVE_POWER, CONF_TOTAL_POWER, CONF_VOLTAGE, + DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_VOLTAGE, @@ -67,6 +69,7 @@ PHASE_SENSORS = { CONF_APPARENT_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS, accuracy_decimals=2, + device_class=DEVICE_CLASS_APPARENT_POWER, state_class=STATE_CLASS_MEASUREMENT, ), CONF_REACTIVE_POWER: sensor.sensor_schema( @@ -80,7 +83,10 @@ PHASE_SENSORS = { state_class=STATE_CLASS_MEASUREMENT, ), CONF_PHASE_ANGLE: sensor.sensor_schema( - unit_of_measurement=UNIT_DEGREES, icon=ICON_FLASH, accuracy_decimals=3 + unit_of_measurement=UNIT_DEGREES, + icon=ICON_FLASH, + accuracy_decimals=3, + state_class=STATE_CLASS_MEASUREMENT, ), } @@ -99,6 +105,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=3, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_TOTAL_POWER): sensor.sensor_schema( diff --git a/esphome/components/selec_meter/sensor.py b/esphome/components/selec_meter/sensor.py index 069b61af5a..eda65bf9f5 100644 --- a/esphome/components/selec_meter/sensor.py +++ b/esphome/components/selec_meter/sensor.py @@ -14,8 +14,10 @@ from esphome.const import ( CONF_POWER_FACTOR, CONF_REACTIVE_POWER, CONF_VOLTAGE, + DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, + DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_VOLTAGE, @@ -102,6 +104,7 @@ SENSORS = { CONF_APPARENT_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS, accuracy_decimals=3, + device_class=DEVICE_CLASS_APPARENT_POWER, state_class=STATE_CLASS_MEASUREMENT, ), CONF_VOLTAGE: sensor.sensor_schema( @@ -125,6 +128,7 @@ SENSORS = { unit_of_measurement=UNIT_HERTZ, icon=ICON_CURRENT_AC, accuracy_decimals=2, + device_class=DEVICE_CLASS_FREQUENCY, state_class=STATE_CLASS_MEASUREMENT, ), CONF_MAXIMUM_DEMAND_ACTIVE_POWER: sensor.sensor_schema( @@ -141,6 +145,7 @@ SENSORS = { CONF_MAXIMUM_DEMAND_APPARENT_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS, accuracy_decimals=3, + device_class=DEVICE_CLASS_APPARENT_POWER, state_class=STATE_CLASS_MEASUREMENT, ), } diff --git a/esphome/components/teleinfo/sensor/__init__.py b/esphome/components/teleinfo/sensor/__init__.py index b436c70120..150484d97a 100644 --- a/esphome/components/teleinfo/sensor/__init__.py +++ b/esphome/components/teleinfo/sensor/__init__.py @@ -1,6 +1,12 @@ import esphome.codegen as cg from esphome.components import sensor -from esphome.const import CONF_ID, ICON_FLASH, UNIT_WATT_HOURS +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_ENERGY, + ICON_FLASH, + STATE_CLASS_TOTAL_INCREASING, + UNIT_WATT_HOURS, +) from .. import CONF_TAG_NAME, CONF_TELEINFO_ID, TELEINFO_LISTENER_SCHEMA, teleinfo_ns @@ -11,6 +17,8 @@ CONFIG_SCHEMA = sensor.sensor_schema( unit_of_measurement=UNIT_WATT_HOURS, icon=ICON_FLASH, accuracy_decimals=0, + device_class=DEVICE_CLASS_ENERGY, + state_class=STATE_CLASS_TOTAL_INCREASING, ).extend(TELEINFO_LISTENER_SCHEMA) From 50518918130b4a58e0860e0732bbb81fc415a826 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:02:28 -0400 Subject: [PATCH 1968/2030] [esp32] Fix ESP32-C6 pin validator rejecting GPIO 24-30 with wrong error (#15477) --- esphome/components/esp32/gpio_esp32_c6.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/esp32/gpio_esp32_c6.py b/esphome/components/esp32/gpio_esp32_c6.py index 993606d9de..bd7bb9e220 100644 --- a/esphome/components/esp32/gpio_esp32_c6.py +++ b/esphome/components/esp32/gpio_esp32_c6.py @@ -26,8 +26,8 @@ _LOGGER = logging.getLogger(__name__) def esp32_c6_validate_gpio_pin(value: int) -> int: - if value < 0 or value > 23: - raise cv.Invalid(f"Invalid pin number: {value} (must be 0-23)") + if value < 0 or value > 30: + raise cv.Invalid(f"Invalid pin number: {value} (must be 0-30)") if value in _ESP32C6_SPI_PSRAM_PINS: raise cv.Invalid( f"This pin cannot be used on ESP32-C6s and is already used by the SPI/PSRAM interface (function: {_ESP32C6_SPI_PSRAM_PINS[value]})" @@ -47,8 +47,8 @@ def esp32_c6_validate_supports(value: dict[str, Any]) -> dict[str, Any]: mode = value[CONF_MODE] is_input = mode[CONF_INPUT] - if num < 0 or num > 23: - raise cv.Invalid(f"Invalid pin number: {num} (must be 0-23)") + if num < 0 or num > 30: + raise cv.Invalid(f"Invalid pin number: {num} (must be 0-30)") if is_input: # All ESP32 pins support input mode pass From 8650c5b013a8a4c0d07fb021c8ba95ded0150194 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 17:19:20 -0400 Subject: [PATCH 1969/2030] [multiple] Add missing state_class to sensor schemas (#15478) --- esphome/components/dsmr/sensor.py | 10 ++++++++++ esphome/components/ltr390/sensor.py | 5 +++++ esphome/components/mopeka_pro_check/sensor.py | 1 + esphome/components/rotary_encoder/sensor.py | 2 ++ esphome/components/seeed_mr24hpc1/sensor.py | 4 ++++ esphome/components/xiaomi_cgpr1/binary_sensor.py | 4 ++++ esphome/components/xiaomi_mjyd02yla/binary_sensor.py | 1 + 7 files changed, 27 insertions(+) diff --git a/esphome/components/dsmr/sensor.py b/esphome/components/dsmr/sensor.py index 863af42d1b..c49614eaa9 100644 --- a/esphome/components/dsmr/sensor.py +++ b/esphome/components/dsmr/sensor.py @@ -122,42 +122,52 @@ CONFIG_SCHEMA = cv.Schema( cv.Optional("total_imported_energy"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_delivered_tariff1"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_delivered_tariff2"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_delivered_tariff3"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_delivered_tariff4"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("total_exported_energy"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_returned_tariff1"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_returned_tariff2"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_returned_tariff3"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("reactive_energy_returned_tariff4"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOVOLT_AMPS_REACTIVE_HOURS, accuracy_decimals=3, + state_class=STATE_CLASS_TOTAL_INCREASING, ), cv.Optional("power_delivered"): sensor.sensor_schema( unit_of_measurement=UNIT_KILOWATT, diff --git a/esphome/components/ltr390/sensor.py b/esphome/components/ltr390/sensor.py index 579adb9051..37fceaf984 100644 --- a/esphome/components/ltr390/sensor.py +++ b/esphome/components/ltr390/sensor.py @@ -10,6 +10,7 @@ from esphome.const import ( DEVICE_CLASS_EMPTY, DEVICE_CLASS_ILLUMINANCE, ICON_BRIGHTNESS_5, + STATE_CLASS_MEASUREMENT, UNIT_LUX, ) @@ -57,24 +58,28 @@ CONFIG_SCHEMA = cv.All( icon=ICON_BRIGHTNESS_5, accuracy_decimals=1, device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_AMBIENT_LIGHT): sensor.sensor_schema( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_5, accuracy_decimals=1, device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_UV_INDEX): sensor.sensor_schema( unit_of_measurement=UNIT_UVI, icon=ICON_BRIGHTNESS_5, accuracy_decimals=5, device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_UV): sensor.sensor_schema( unit_of_measurement=UNIT_COUNTS, icon=ICON_BRIGHTNESS_5, accuracy_decimals=1, device_class=DEVICE_CLASS_EMPTY, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_GAIN, default="X18"): cv.Any( cv.enum(GAIN_OPTIONS), diff --git a/esphome/components/mopeka_pro_check/sensor.py b/esphome/components/mopeka_pro_check/sensor.py index 4e84fb708c..323175917d 100644 --- a/esphome/components/mopeka_pro_check/sensor.py +++ b/esphome/components/mopeka_pro_check/sensor.py @@ -115,6 +115,7 @@ CONFIG_SCHEMA = ( icon=ICON_COUNTER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_MINIMUM_SIGNAL_QUALITY, default="MEDIUM"): cv.enum( SIGNAL_QUALITIES, upper=True diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index e64e44f7c1..fc4202556d 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -12,6 +12,7 @@ from esphome.const import ( CONF_RESTORE_MODE, CONF_VALUE, ICON_ROTATE_RIGHT, + STATE_CLASS_MEASUREMENT, UNIT_STEPS, ) @@ -60,6 +61,7 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_STEPS, icon=ICON_ROTATE_RIGHT, accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, ) .extend( { diff --git a/esphome/components/seeed_mr24hpc1/sensor.py b/esphome/components/seeed_mr24hpc1/sensor.py index 7b20941aa4..ca15fd5be6 100644 --- a/esphome/components/seeed_mr24hpc1/sensor.py +++ b/esphome/components/seeed_mr24hpc1/sensor.py @@ -5,6 +5,7 @@ from esphome.const import ( DEVICE_CLASS_DISTANCE, DEVICE_CLASS_ENERGY, DEVICE_CLASS_SPEED, + STATE_CLASS_MEASUREMENT, UNIT_METER, ) @@ -26,6 +27,7 @@ CONFIG_SCHEMA = cv.Schema( unit_of_measurement=UNIT_METER, accuracy_decimals=2, # Specify the number of decimal places icon="mdi:signal-distance-variant", + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_MOVEMENT_SIGNS): sensor.sensor_schema( icon="mdi:human-greeting-variant", @@ -34,6 +36,7 @@ CONFIG_SCHEMA = cv.Schema( unit_of_measurement=UNIT_METER, accuracy_decimals=2, icon="mdi:signal-distance-variant", + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CUSTOM_SPATIAL_STATIC_VALUE): sensor.sensor_schema( device_class=DEVICE_CLASS_ENERGY, @@ -48,6 +51,7 @@ CONFIG_SCHEMA = cv.Schema( device_class=DEVICE_CLASS_SPEED, accuracy_decimals=2, icon="mdi:run-fast", + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CUSTOM_MODE_NUM): sensor.sensor_schema( icon="mdi:counter", diff --git a/esphome/components/xiaomi_cgpr1/binary_sensor.py b/esphome/components/xiaomi_cgpr1/binary_sensor.py index 2f71a11b28..0606c93dbe 100644 --- a/esphome/components/xiaomi_cgpr1/binary_sensor.py +++ b/esphome/components/xiaomi_cgpr1/binary_sensor.py @@ -12,6 +12,7 @@ from esphome.const import ( DEVICE_CLASS_MOTION, ENTITY_CATEGORY_DIAGNOSTIC, ICON_TIMELAPSE, + STATE_CLASS_MEASUREMENT, UNIT_LUX, UNIT_MINUTE, UNIT_PERCENT, @@ -38,6 +39,7 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_PERCENT, accuracy_decimals=0, device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, ), cv.Optional(CONF_IDLE_TIME): sensor.sensor_schema( @@ -45,11 +47,13 @@ CONFIG_SCHEMA = cv.All( icon=ICON_TIMELAPSE, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( unit_of_measurement=UNIT_LUX, accuracy_decimals=0, device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, ), } ) diff --git a/esphome/components/xiaomi_mjyd02yla/binary_sensor.py b/esphome/components/xiaomi_mjyd02yla/binary_sensor.py index 312f8b43b1..312abc82cb 100644 --- a/esphome/components/xiaomi_mjyd02yla/binary_sensor.py +++ b/esphome/components/xiaomi_mjyd02yla/binary_sensor.py @@ -43,6 +43,7 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_MINUTE, icon=ICON_TIMELAPSE, accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, From c78fb964a2ba058c1909df95a6e0cd6a1885ce4b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:15:42 -0400 Subject: [PATCH 1970/2030] [multiple] Add missing state_class to remaining sensor schemas (#15486) --- esphome/components/am43/sensor/__init__.py | 3 +++ esphome/components/as3935/sensor.py | 2 ++ esphome/components/cs5460a/sensor.py | 4 ++++ esphome/components/debug/sensor.py | 8 ++++++++ esphome/components/hmc5883l/sensor.py | 1 + esphome/components/ld2420/sensor/__init__.py | 5 ++++- esphome/components/max31855/sensor.py | 1 + esphome/components/mmc5603/sensor.py | 1 + esphome/components/pylontech/sensor/__init__.py | 10 ++++++++++ esphome/components/qmc5883l/sensor.py | 1 + esphome/components/shelly_dimmer/light.py | 4 ++++ esphome/components/sun/sensor/__init__.py | 8 +++++++- esphome/components/sun_gtil2/sensor.py | 7 +++++++ esphome/components/tx20/sensor.py | 1 + 14 files changed, 54 insertions(+), 2 deletions(-) diff --git a/esphome/components/am43/sensor/__init__.py b/esphome/components/am43/sensor/__init__.py index 4b3e1716a4..2697d364ad 100644 --- a/esphome/components/am43/sensor/__init__.py +++ b/esphome/components/am43/sensor/__init__.py @@ -8,6 +8,7 @@ from esphome.const import ( DEVICE_CLASS_BATTERY, ENTITY_CATEGORY_DIAGNOSTIC, ICON_BRIGHTNESS_5, + STATE_CLASS_MEASUREMENT, UNIT_PERCENT, ) @@ -26,11 +27,13 @@ CONFIG_SCHEMA = ( device_class=DEVICE_CLASS_BATTERY, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, icon=ICON_BRIGHTNESS_5, accuracy_decimals=0, + state_class=STATE_CLASS_MEASUREMENT, ), } ) diff --git a/esphome/components/as3935/sensor.py b/esphome/components/as3935/sensor.py index 1e549c5d82..9b43155563 100644 --- a/esphome/components/as3935/sensor.py +++ b/esphome/components/as3935/sensor.py @@ -6,6 +6,7 @@ from esphome.const import ( CONF_LIGHTNING_ENERGY, ICON_FLASH, ICON_SIGNAL_DISTANCE_VARIANT, + STATE_CLASS_MEASUREMENT, UNIT_KILOMETER, ) @@ -20,6 +21,7 @@ CONFIG_SCHEMA = cv.Schema( unit_of_measurement=UNIT_KILOMETER, icon=ICON_SIGNAL_DISTANCE_VARIANT, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_LIGHTNING_ENERGY): sensor.sensor_schema( icon=ICON_FLASH, diff --git a/esphome/components/cs5460a/sensor.py b/esphome/components/cs5460a/sensor.py index d2383bd01b..0c6ae0d821 100644 --- a/esphome/components/cs5460a/sensor.py +++ b/esphome/components/cs5460a/sensor.py @@ -12,6 +12,7 @@ from esphome.const import ( DEVICE_CLASS_CURRENT, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, UNIT_AMPERE, UNIT_VOLT, UNIT_WATT, @@ -82,16 +83,19 @@ CONFIG_SCHEMA = cv.All( unit_of_measurement=UNIT_VOLT, accuracy_decimals=0, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CURRENT): sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, accuracy_decimals=1, device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, accuracy_decimals=0, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), } ) diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index 0a716d666e..af1b83190d 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -14,6 +14,7 @@ from esphome.const import ( PLATFORM_BK72XX, PLATFORM_LN882X, PLATFORM_RTL87XX, + STATE_CLASS_MEASUREMENT, UNIT_BYTES, UNIT_HERTZ, UNIT_MILLISECOND, @@ -38,12 +39,14 @@ CONFIG_SCHEMA = { icon=ICON_COUNTER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_BLOCK): sensor.sensor_schema( unit_of_measurement=UNIT_BYTES, icon=ICON_COUNTER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_FRAGMENTATION): cv.All( cv.Any( @@ -59,6 +62,7 @@ CONFIG_SCHEMA = { icon=ICON_COUNTER, accuracy_decimals=1, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), ), cv.Optional(CONF_MIN_FREE): cv.All( @@ -72,6 +76,7 @@ CONFIG_SCHEMA = { icon=ICON_COUNTER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), ), cv.Optional(CONF_LOOP_TIME): sensor.sensor_schema( @@ -79,6 +84,7 @@ CONFIG_SCHEMA = { icon=ICON_TIMER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_PSRAM): cv.All( cv.only_on_esp32, @@ -88,6 +94,7 @@ CONFIG_SCHEMA = { icon=ICON_COUNTER, accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), ), cv.Optional(CONF_CPU_FREQUENCY): cv.All( @@ -96,6 +103,7 @@ CONFIG_SCHEMA = { icon="mdi:speedometer", accuracy_decimals=0, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, + state_class=STATE_CLASS_MEASUREMENT, ), ), } diff --git a/esphome/components/hmc5883l/sensor.py b/esphome/components/hmc5883l/sensor.py index 96d0313008..cf3c594f36 100644 --- a/esphome/components/hmc5883l/sensor.py +++ b/esphome/components/hmc5883l/sensor.py @@ -87,6 +87,7 @@ heading_schema = sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, icon=ICON_SCREEN_ROTATION, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ) CONFIG_SCHEMA = ( diff --git a/esphome/components/ld2420/sensor/__init__.py b/esphome/components/ld2420/sensor/__init__.py index 6dde35753a..97acdabd7b 100644 --- a/esphome/components/ld2420/sensor/__init__.py +++ b/esphome/components/ld2420/sensor/__init__.py @@ -5,6 +5,7 @@ from esphome.const import ( CONF_ID, CONF_MOVING_DISTANCE, DEVICE_CLASS_DISTANCE, + STATE_CLASS_MEASUREMENT, UNIT_CENTIMETER, ) @@ -20,7 +21,9 @@ CONFIG_SCHEMA = cv.All( cv.GenerateID(): cv.declare_id(LD2420Sensor), cv.GenerateID(CONF_LD2420_ID): cv.use_id(LD2420Component), cv.Optional(CONF_MOVING_DISTANCE): sensor.sensor_schema( - device_class=DEVICE_CLASS_DISTANCE, unit_of_measurement=UNIT_CENTIMETER + device_class=DEVICE_CLASS_DISTANCE, + unit_of_measurement=UNIT_CENTIMETER, + state_class=STATE_CLASS_MEASUREMENT, ), } ), diff --git a/esphome/components/max31855/sensor.py b/esphome/components/max31855/sensor.py index 93e48beee0..35ae28d04c 100644 --- a/esphome/components/max31855/sensor.py +++ b/esphome/components/max31855/sensor.py @@ -19,6 +19,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ) .extend( { diff --git a/esphome/components/mmc5603/sensor.py b/esphome/components/mmc5603/sensor.py index 5b3982cee6..6d2bafdd0e 100644 --- a/esphome/components/mmc5603/sensor.py +++ b/esphome/components/mmc5603/sensor.py @@ -45,6 +45,7 @@ heading_schema = sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, icon=ICON_SCREEN_ROTATION, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ) CONFIG_SCHEMA = ( diff --git a/esphome/components/pylontech/sensor/__init__.py b/esphome/components/pylontech/sensor/__init__.py index 52f2679b70..450f663274 100644 --- a/esphome/components/pylontech/sensor/__init__.py +++ b/esphome/components/pylontech/sensor/__init__.py @@ -10,6 +10,7 @@ from esphome.const import ( DEVICE_CLASS_CURRENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, UNIT_AMPERE, UNIT_CELSIUS, UNIT_PERCENT, @@ -32,46 +33,55 @@ TYPES: dict[str, cv.Schema] = { unit_of_measurement=UNIT_VOLT, accuracy_decimals=3, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_CURRENT: sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, accuracy_decimals=3, device_class=DEVICE_CLASS_CURRENT, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_TEMPERATURE: sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_TEMPERATURE_LOW: sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_TEMPERATURE_HIGH: sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_VOLTAGE_LOW: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=3, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_VOLTAGE_HIGH: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=3, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_COULOMB: sensor.sensor_schema( unit_of_measurement=UNIT_PERCENT, accuracy_decimals=0, device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, ), CONF_MOS_TEMPERATURE: sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), } diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index b79e370a05..fe34381ad8 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -100,6 +100,7 @@ heading_schema = sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, icon=ICON_SCREEN_ROTATION, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ) temperature_schema = sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, diff --git a/esphome/components/shelly_dimmer/light.py b/esphome/components/shelly_dimmer/light.py index c96bc380d7..c1e9cad358 100644 --- a/esphome/components/shelly_dimmer/light.py +++ b/esphome/components/shelly_dimmer/light.py @@ -22,6 +22,7 @@ from esphome.const import ( DEVICE_CLASS_CURRENT, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, UNIT_AMPERE, UNIT_VOLT, UNIT_WATT, @@ -163,16 +164,19 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_WATT, accuracy_decimals=1, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_CURRENT): sensor.sensor_schema( unit_of_measurement=UNIT_AMPERE, device_class=DEVICE_CLASS_CURRENT, accuracy_decimals=2, + state_class=STATE_CLASS_MEASUREMENT, ), # Change the default gamma_correct setting. cv.Optional(CONF_GAMMA_CORRECT, default=1.0): cv.positive_float, diff --git a/esphome/components/sun/sensor/__init__.py b/esphome/components/sun/sensor/__init__.py index a356d9cca8..a1ced8ff5b 100644 --- a/esphome/components/sun/sensor/__init__.py +++ b/esphome/components/sun/sensor/__init__.py @@ -1,7 +1,12 @@ import esphome.codegen as cg from esphome.components import sensor import esphome.config_validation as cv -from esphome.const import CONF_TYPE, ICON_WEATHER_SUNSET, UNIT_DEGREES +from esphome.const import ( + CONF_TYPE, + ICON_WEATHER_SUNSET, + STATE_CLASS_MEASUREMENT, + UNIT_DEGREES, +) from .. import CONF_SUN_ID, Sun, sun_ns @@ -20,6 +25,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_DEGREES, icon=ICON_WEATHER_SUNSET, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ) .extend( { diff --git a/esphome/components/sun_gtil2/sensor.py b/esphome/components/sun_gtil2/sensor.py index d8c59bf1de..55c8195391 100644 --- a/esphome/components/sun_gtil2/sensor.py +++ b/esphome/components/sun_gtil2/sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( DEVICE_CLASS_VOLTAGE, ICON_FLASH, ICON_THERMOMETER, + STATE_CLASS_MEASUREMENT, UNIT_CELSIUS, UNIT_VOLT, UNIT_WATT, @@ -30,36 +31,42 @@ CONFIG_SCHEMA = cv.All( icon=ICON_FLASH, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DC_VOLTAGE): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT, icon=ICON_FLASH, accuracy_decimals=1, device_class=DEVICE_CLASS_VOLTAGE, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_AC_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, icon=ICON_FLASH, accuracy_decimals=1, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DC_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, icon=ICON_FLASH, accuracy_decimals=1, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_LIMITER_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_WATT, icon=ICON_FLASH, accuracy_decimals=1, device_class=DEVICE_CLASS_POWER, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( unit_of_measurement=UNIT_CELSIUS, icon=ICON_THERMOMETER, accuracy_decimals=1, device_class=DEVICE_CLASS_TEMPERATURE, + state_class=STATE_CLASS_MEASUREMENT, ), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/tx20/sensor.py b/esphome/components/tx20/sensor.py index 4f1582072e..87bc4283b7 100644 --- a/esphome/components/tx20/sensor.py +++ b/esphome/components/tx20/sensor.py @@ -30,6 +30,7 @@ CONFIG_SCHEMA = cv.Schema( unit_of_measurement=UNIT_DEGREES, icon=ICON_SIGN_DIRECTION, accuracy_decimals=1, + state_class=STATE_CLASS_MEASUREMENT, ), cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema), } From 6f62b2f18c702a9a8752ffaa9f0161d5b782a85d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:20:38 -0400 Subject: [PATCH 1971/2030] [thermostat] Remove non-functional cv.templatable from preset fields (#15481) --- esphome/components/thermostat/climate.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index ec115296d7..d609e22ac2 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -118,10 +118,8 @@ PRESET_CONFIG_SCHEMA = cv.Schema( cv.Optional(CONF_MODE): validate_climate_mode, cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, - cv.Optional(CONF_FAN_MODE): cv.templatable(climate.validate_climate_fan_mode), - cv.Optional(CONF_SWING_MODE): cv.templatable( - climate.validate_climate_swing_mode - ), + cv.Optional(CONF_FAN_MODE): climate.validate_climate_fan_mode, + cv.Optional(CONF_SWING_MODE): climate.validate_climate_swing_mode, } ) @@ -631,7 +629,7 @@ CONFIG_SCHEMA = cv.All( ): automation.validate_automation(single=True), cv.Optional(CONF_HUMIDITY_HYSTERESIS, default=1.0): cv.percentage, cv.Optional(CONF_DEFAULT_MODE, default=None): cv.valid, - cv.Optional(CONF_DEFAULT_PRESET): cv.templatable(cv.string), + cv.Optional(CONF_DEFAULT_PRESET): cv.string, cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, cv.Optional( From 5a14d6a4add88e80facb2890a7cf58fab22ea453 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 18:38:47 -0400 Subject: [PATCH 1972/2030] [multiple] Add missing device_class to sensor schemas (batch 2) (#15487) Co-authored-by: J. Nick Koston <nick@koston.org> --- esphome/components/debug/sensor.py | 2 ++ esphome/components/havells_solar/sensor.py | 6 ++++++ esphome/components/sdm_meter/sensor.py | 2 ++ esphome/components/selec_meter/sensor.py | 3 +++ esphome/components/tx20/sensor.py | 2 ++ esphome/components/xiaomi_miscale/sensor.py | 2 ++ 6 files changed, 17 insertions(+) diff --git a/esphome/components/debug/sensor.py b/esphome/components/debug/sensor.py index af1b83190d..a018ce5c3b 100644 --- a/esphome/components/debug/sensor.py +++ b/esphome/components/debug/sensor.py @@ -8,6 +8,7 @@ from esphome.const import ( CONF_FRAGMENTATION, CONF_FREE, CONF_LOOP_TIME, + DEVICE_CLASS_FREQUENCY, ENTITY_CATEGORY_DIAGNOSTIC, ICON_COUNTER, ICON_TIMER, @@ -102,6 +103,7 @@ CONFIG_SCHEMA = { unit_of_measurement=UNIT_HERTZ, icon="mdi:speedometer", accuracy_decimals=0, + device_class=DEVICE_CLASS_FREQUENCY, entity_category=ENTITY_CATEGORY_DIAGNOSTIC, state_class=STATE_CLASS_MEASUREMENT, ), diff --git a/esphome/components/havells_solar/sensor.py b/esphome/components/havells_solar/sensor.py index a876acd79b..f0683e1d9c 100644 --- a/esphome/components/havells_solar/sensor.py +++ b/esphome/components/havells_solar/sensor.py @@ -15,6 +15,7 @@ from esphome.const import ( DEVICE_CLASS_ENERGY, DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, + DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_VOLTAGE, ICON_CURRENT_AC, STATE_CLASS_MEASUREMENT, @@ -138,6 +139,7 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, accuracy_decimals=2, + device_class=DEVICE_CLASS_REACTIVE_POWER, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_ENERGY_PRODUCTION_DAY): sensor.sensor_schema( @@ -186,21 +188,25 @@ CONFIG_SCHEMA = ( cv.Optional(CONF_GFCI_VALUE): sensor.sensor_schema( unit_of_measurement=UNIT_MILLIAMPERE, accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DCI_OF_R): sensor.sensor_schema( unit_of_measurement=UNIT_MILLIAMPERE, accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DCI_OF_S): sensor.sensor_schema( unit_of_measurement=UNIT_MILLIAMPERE, accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_DCI_OF_T): sensor.sensor_schema( unit_of_measurement=UNIT_MILLIAMPERE, accuracy_decimals=0, + device_class=DEVICE_CLASS_CURRENT, state_class=STATE_CLASS_MEASUREMENT, ), } diff --git a/esphome/components/sdm_meter/sensor.py b/esphome/components/sdm_meter/sensor.py index 9687357f5e..8006d0b4ba 100644 --- a/esphome/components/sdm_meter/sensor.py +++ b/esphome/components/sdm_meter/sensor.py @@ -25,6 +25,7 @@ from esphome.const import ( DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_VOLTAGE, ICON_CURRENT_AC, ICON_FLASH, @@ -75,6 +76,7 @@ PHASE_SENSORS = { CONF_REACTIVE_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, accuracy_decimals=2, + device_class=DEVICE_CLASS_REACTIVE_POWER, state_class=STATE_CLASS_MEASUREMENT, ), CONF_POWER_FACTOR: sensor.sensor_schema( diff --git a/esphome/components/selec_meter/sensor.py b/esphome/components/selec_meter/sensor.py index eda65bf9f5..1a53eb5c37 100644 --- a/esphome/components/selec_meter/sensor.py +++ b/esphome/components/selec_meter/sensor.py @@ -20,6 +20,7 @@ from esphome.const import ( DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_VOLTAGE, ICON_CURRENT_AC, STATE_CLASS_MEASUREMENT, @@ -99,6 +100,7 @@ SENSORS = { CONF_REACTIVE_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, accuracy_decimals=3, + device_class=DEVICE_CLASS_REACTIVE_POWER, state_class=STATE_CLASS_MEASUREMENT, ), CONF_APPARENT_POWER: sensor.sensor_schema( @@ -140,6 +142,7 @@ SENSORS = { CONF_MAXIMUM_DEMAND_REACTIVE_POWER: sensor.sensor_schema( unit_of_measurement=UNIT_VOLT_AMPS_REACTIVE, accuracy_decimals=3, + device_class=DEVICE_CLASS_REACTIVE_POWER, state_class=STATE_CLASS_MEASUREMENT, ), CONF_MAXIMUM_DEMAND_APPARENT_POWER: sensor.sensor_schema( diff --git a/esphome/components/tx20/sensor.py b/esphome/components/tx20/sensor.py index 87bc4283b7..1bb5ab0706 100644 --- a/esphome/components/tx20/sensor.py +++ b/esphome/components/tx20/sensor.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_PIN, CONF_WIND_DIRECTION_DEGREES, CONF_WIND_SPEED, + DEVICE_CLASS_WIND_SPEED, ICON_SIGN_DIRECTION, ICON_WEATHER_WINDY, STATE_CLASS_MEASUREMENT, @@ -24,6 +25,7 @@ CONFIG_SCHEMA = cv.Schema( unit_of_measurement=UNIT_KILOMETER_PER_HOUR, icon=ICON_WEATHER_WINDY, accuracy_decimals=1, + device_class=DEVICE_CLASS_WIND_SPEED, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_WIND_DIRECTION_DEGREES): sensor.sensor_schema( diff --git a/esphome/components/xiaomi_miscale/sensor.py b/esphome/components/xiaomi_miscale/sensor.py index 4aa8d029f8..14e5c1d376 100644 --- a/esphome/components/xiaomi_miscale/sensor.py +++ b/esphome/components/xiaomi_miscale/sensor.py @@ -7,6 +7,7 @@ from esphome.const import ( CONF_IMPEDANCE, CONF_MAC_ADDRESS, CONF_WEIGHT, + DEVICE_CLASS_WEIGHT, ICON_OMEGA, ICON_SCALE_BATHROOM, STATE_CLASS_MEASUREMENT, @@ -31,6 +32,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_KILOGRAM, icon=ICON_SCALE_BATHROOM, accuracy_decimals=2, + device_class=DEVICE_CLASS_WEIGHT, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_IMPEDANCE): sensor.sensor_schema( From 2b5ee69eb27a2f1aa0d6d473caaab7dc71d6e626 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 12:42:18 -1000 Subject: [PATCH 1973/2030] [api] Speed up protobuf encode 17-20% with register-optimized write path (#15290) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> --- esphome/components/api/api_connection.cpp | 4 +- esphome/components/api/api_connection.h | 6 +- esphome/components/api/api_pb2.cpp | 1455 ++++++++++++--------- esphome/components/api/api_pb2.h | 186 +-- esphome/components/api/proto.cpp | 17 +- esphome/components/api/proto.h | 407 +++--- script/api_protobuf/api_protobuf.py | 121 +- 7 files changed, 1257 insertions(+), 939 deletions(-) diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 0f456ecd0c..feb16e4f4c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -1993,7 +1993,7 @@ bool APIConnection::send_message_(uint32_t payload_size, uint8_t message_type, M size_t write_start = shared_buf.size(); shared_buf.resize(write_start + payload_size); ProtoWriteBuffer buffer{&shared_buf, write_start}; - encode_fn(msg, buffer); + encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type); } // Encodes a message to the buffer and returns the total number of bytes used, @@ -2034,7 +2034,7 @@ uint16_t APIConnection::encode_to_buffer(uint32_t calculated_size, MessageEncode shared_buf.resize(shared_buf.size() + to_add); ProtoWriteBuffer buffer{&shared_buf, shared_buf.size() - calculated_size}; - encode_fn(msg, buffer); + encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); // Return total size (header + payload + footer) return static_cast<uint16_t>(total_calculated_size); diff --git a/esphome/components/api/api_connection.h b/esphome/components/api/api_connection.h index 5a86240ab5..2f685b0b8a 100644 --- a/esphome/components/api/api_connection.h +++ b/esphome/components/api/api_connection.h @@ -324,7 +324,7 @@ class APIConnection final : public APIServerConnectionBase { void on_no_setup_connection(); // Function pointer type for type-erased message encoding - using MessageEncodeFn = void (*)(const void *, ProtoWriteBuffer &); + using MessageEncodeFn = uint8_t *(*) (const void *, ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM); // Function pointer type for type-erased size calculation using CalculateSizeFn = uint32_t (*)(const void *); @@ -403,7 +403,9 @@ class APIConnection final : public APIServerConnectionBase { } // Shared no-op encode thunk for empty messages (ESTIMATED_SIZE == 0) - static void encode_msg_noop(const void *, ProtoWriteBuffer &) {} + static uint8_t *encode_msg_noop(const void *, ProtoWriteBuffer &buf PROTO_ENCODE_DEBUG_PARAM) { + return buf.get_pos(); + } // Non-template buffer management for send_message bool send_message_(uint32_t payload_size, uint8_t message_type, MessageEncodeFn encode_fn, const void *msg); diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f25d269e8f..ed4711bfaa 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -31,11 +31,13 @@ bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) } return true; } -void HelloResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->api_version_major); - buffer.encode_uint32(2, this->api_version_minor); - buffer.encode_string(3, this->server_info); - buffer.encode_string(4, this->name); +uint8_t *HelloResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->api_version_major); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->api_version_minor); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->server_info); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->name); + return pos; } uint32_t HelloResponse::calculate_size() const { uint32_t size = 0; @@ -46,9 +48,11 @@ uint32_t HelloResponse::calculate_size() const { return size; } #ifdef USE_AREAS -void AreaInfo::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->area_id); - buffer.encode_string(2, this->name); +uint8_t *AreaInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->area_id); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); + return pos; } uint32_t AreaInfo::calculate_size() const { uint32_t size = 0; @@ -58,10 +62,12 @@ uint32_t AreaInfo::calculate_size() const { } #endif #ifdef USE_DEVICES -void DeviceInfo::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->device_id); - buffer.encode_string(2, this->name); - buffer.encode_uint32(3, this->area_id); +uint8_t *DeviceInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->area_id); + return pos; } uint32_t DeviceInfo::calculate_size() const { uint32_t size = 0; @@ -72,9 +78,11 @@ uint32_t DeviceInfo::calculate_size() const { } #endif #ifdef USE_SERIAL_PROXY -void SerialProxyInfo::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->name); - buffer.encode_uint32(2, static_cast<uint32_t>(this->port_type)); +uint8_t *SerialProxyInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->port_type)); + return pos; } uint32_t SerialProxyInfo::calculate_size() const { uint32_t size = 0; @@ -83,65 +91,67 @@ uint32_t SerialProxyInfo::calculate_size() const { return size; } #endif -void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(2, this->name); - buffer.encode_string(3, this->mac_address); - buffer.encode_string(4, this->esphome_version); - buffer.encode_string(5, this->compilation_time); - buffer.encode_string(6, this->model); +uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->mac_address); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->esphome_version); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->compilation_time); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->model); #ifdef USE_DEEP_SLEEP - buffer.encode_bool(7, this->has_deep_sleep); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - buffer.encode_string(8, this->project_name); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->project_name); #endif #ifdef ESPHOME_PROJECT_NAME - buffer.encode_string(9, this->project_version); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->project_version); #endif #ifdef USE_WEBSERVER - buffer.encode_uint32(10, this->webserver_port); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->webserver_port); #endif #ifdef USE_BLUETOOTH_PROXY - buffer.encode_uint32(15, this->bluetooth_proxy_feature_flags); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, this->bluetooth_proxy_feature_flags); #endif - buffer.encode_string(12, this->manufacturer); - buffer.encode_string(13, this->friendly_name); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 12, this->manufacturer); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->friendly_name); #ifdef USE_VOICE_ASSISTANT - buffer.encode_uint32(17, this->voice_assistant_feature_flags); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 17, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - buffer.encode_string(16, this->suggested_area); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 16, this->suggested_area); #endif #ifdef USE_BLUETOOTH_PROXY - buffer.encode_string(18, this->bluetooth_mac_address); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 18, this->bluetooth_mac_address); #endif #ifdef USE_API_NOISE - buffer.encode_bool(19, this->api_encryption_supported); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 19, this->api_encryption_supported); #endif #ifdef USE_DEVICES for (const auto &it : this->devices) { - buffer.encode_sub_message(20, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 20, it); } #endif #ifdef USE_AREAS for (const auto &it : this->areas) { - buffer.encode_sub_message(21, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 21, it); } #endif #ifdef USE_AREAS - buffer.encode_optional_sub_message(22, this->area); + ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 22, this->area); #endif #ifdef USE_ZWAVE_PROXY - buffer.encode_uint32(23, this->zwave_proxy_feature_flags); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 23, this->zwave_proxy_feature_flags); #endif #ifdef USE_ZWAVE_PROXY - buffer.encode_uint32(24, this->zwave_home_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 24, this->zwave_home_id); #endif #ifdef USE_SERIAL_PROXY for (const auto &it : this->serial_proxies) { - buffer.encode_sub_message(25, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 25, it); } #endif + return pos; } uint32_t DeviceInfoResponse::calculate_size() const { uint32_t size = 0; @@ -206,20 +216,22 @@ uint32_t DeviceInfoResponse::calculate_size() const { return size; } #ifdef USE_BINARY_SENSOR -void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); - buffer.encode_string(5, this->device_class); - buffer.encode_bool(6, this->is_status_binary_sensor); - buffer.encode_bool(7, this->disabled_by_default); +uint8_t *ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->is_status_binary_sensor); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(8, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->icon); #endif - buffer.encode_uint32(9, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(10, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif + return pos; } uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { uint32_t size = 0; @@ -238,13 +250,15 @@ uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { #endif return size; } -void BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t BinarySensorStateResponse::calculate_size() const { uint32_t size = 0; @@ -258,23 +272,25 @@ uint32_t BinarySensorStateResponse::calculate_size() const { } #endif #ifdef USE_COVER -void ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); - buffer.encode_bool(5, this->assumed_state); - buffer.encode_bool(6, this->supports_position); - buffer.encode_bool(7, this->supports_tilt); - buffer.encode_string(8, this->device_class); - buffer.encode_bool(9, this->disabled_by_default); +uint8_t *ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->assumed_state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_position); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_tilt); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(10, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); #endif - buffer.encode_uint32(11, static_cast<uint32_t>(this->entity_category)); - buffer.encode_bool(12, this->supports_stop); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_stop); #ifdef USE_DEVICES - buffer.encode_uint32(13, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); #endif + return pos; } uint32_t ListEntitiesCoverResponse::calculate_size() const { uint32_t size = 0; @@ -296,14 +312,16 @@ uint32_t ListEntitiesCoverResponse::calculate_size() const { #endif return size; } -void CoverStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_float(3, this->position); - buffer.encode_float(4, this->tilt); - buffer.encode_uint32(5, static_cast<uint32_t>(this->current_operation)); +uint8_t *CoverStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->position); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->tilt); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES - buffer.encode_uint32(6, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif + return pos; } uint32_t CoverStateResponse::calculate_size() const { uint32_t size = 0; @@ -355,25 +373,27 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_FAN -void ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); - buffer.encode_bool(5, this->supports_oscillation); - buffer.encode_bool(6, this->supports_speed); - buffer.encode_bool(7, this->supports_direction); - buffer.encode_int32(8, this->supported_speed_count); - buffer.encode_bool(9, this->disabled_by_default); +uint8_t *ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_oscillation); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_speed); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_direction); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_speed_count); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(10, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); #endif - buffer.encode_uint32(11, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(this->entity_category)); for (const char *it : *this->supported_preset_modes) { - buffer.encode_string(12, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 12, it, strlen(it), true); } #ifdef USE_DEVICES - buffer.encode_uint32(13, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); #endif + return pos; } uint32_t ListEntitiesFanResponse::calculate_size() const { uint32_t size = 0; @@ -399,16 +419,18 @@ uint32_t ListEntitiesFanResponse::calculate_size() const { #endif return size; } -void FanStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->state); - buffer.encode_bool(3, this->oscillating); - buffer.encode_uint32(5, static_cast<uint32_t>(this->direction)); - buffer.encode_int32(6, this->speed_level); - buffer.encode_string(7, this->preset_mode); +uint8_t *FanStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->oscillating); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast<uint32_t>(this->direction)); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->speed_level); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->preset_mode); #ifdef USE_DEVICES - buffer.encode_uint32(8, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif + return pos; } uint32_t FanStateResponse::calculate_size() const { uint32_t size = 0; @@ -485,26 +507,28 @@ bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_LIGHT -void ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); for (const auto &it : *this->supported_color_modes) { - buffer.encode_uint32(12, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it), true); } - buffer.encode_float(9, this->min_mireds); - buffer.encode_float(10, this->max_mireds); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->min_mireds); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->max_mireds); for (const char *it : *this->effects) { - buffer.encode_string(11, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, it, strlen(it), true); } - buffer.encode_bool(13, this->disabled_by_default); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(14, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 14, this->icon); #endif - buffer.encode_uint32(15, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(16, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); #endif + return pos; } uint32_t ListEntitiesLightResponse::calculate_size() const { uint32_t size = 0; @@ -533,23 +557,25 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { #endif return size; } -void LightStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->state); - buffer.encode_float(3, this->brightness); - buffer.encode_uint32(11, static_cast<uint32_t>(this->color_mode)); - buffer.encode_float(10, this->color_brightness); - buffer.encode_float(4, this->red); - buffer.encode_float(5, this->green); - buffer.encode_float(6, this->blue); - buffer.encode_float(7, this->white); - buffer.encode_float(8, this->color_temperature); - buffer.encode_float(12, this->cold_white); - buffer.encode_float(13, this->warm_white); - buffer.encode_string(9, this->effect); +uint8_t *LightStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->brightness); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(this->color_mode)); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->color_brightness); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->red); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->green); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->blue); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->white); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->color_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 12, this->cold_white); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 13, this->warm_white); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->effect); #ifdef USE_DEVICES - buffer.encode_uint32(14, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif + return pos; } uint32_t LightStateResponse::calculate_size() const { uint32_t size = 0; @@ -681,23 +707,25 @@ bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SENSOR -void ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_string(6, this->unit_of_measurement); - buffer.encode_int32(7, this->accuracy_decimals); - buffer.encode_bool(8, this->force_update); - buffer.encode_string(9, this->device_class); - buffer.encode_uint32(10, static_cast<uint32_t>(this->state_class)); - buffer.encode_bool(12, this->disabled_by_default); - buffer.encode_uint32(13, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->unit_of_measurement); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->accuracy_decimals); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->force_update); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(this->state_class)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(14, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif + return pos; } uint32_t ListEntitiesSensorResponse::calculate_size() const { uint32_t size = 0; @@ -719,13 +747,15 @@ uint32_t ListEntitiesSensorResponse::calculate_size() const { #endif return size; } -void SensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_float(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *SensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t SensorStateResponse::calculate_size() const { uint32_t size = 0; @@ -739,20 +769,22 @@ uint32_t SensorStateResponse::calculate_size() const { } #endif #ifdef USE_SWITCH -void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->assumed_state); - buffer.encode_bool(7, this->disabled_by_default); - buffer.encode_uint32(8, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(9, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->assumed_state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); #ifdef USE_DEVICES - buffer.encode_uint32(10, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif + return pos; } uint32_t ListEntitiesSwitchResponse::calculate_size() const { uint32_t size = 0; @@ -771,12 +803,14 @@ uint32_t ListEntitiesSwitchResponse::calculate_size() const { #endif return size; } -void SwitchStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->state); +uint8_t *SwitchStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); #ifdef USE_DEVICES - buffer.encode_uint32(3, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif + return pos; } uint32_t SwitchStateResponse::calculate_size() const { uint32_t size = 0; @@ -814,19 +848,21 @@ bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_TEXT_SENSOR -void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - buffer.encode_uint32(9, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif + return pos; } uint32_t ListEntitiesTextSensorResponse::calculate_size() const { uint32_t size = 0; @@ -844,13 +880,15 @@ uint32_t ListEntitiesTextSensorResponse::calculate_size() const { #endif return size; } -void TextSensorStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_string(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *TextSensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t TextSensorStateResponse::calculate_size() const { uint32_t size = 0; @@ -876,9 +914,11 @@ bool SubscribeLogsRequest::decode_varint(uint32_t field_id, proto_varint_value_t } return true; } -void SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, static_cast<uint32_t>(this->level)); - buffer.encode_bytes(3, this->message_ptr_, this->message_len_); +uint8_t *SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast<uint32_t>(this->level)); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->message_ptr_, this->message_len_); + return pos; } uint32_t SubscribeLogsResponse::calculate_size() const { uint32_t size = 0; @@ -899,7 +939,11 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD } return true; } -void NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } +uint8_t *NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); + return pos; +} uint32_t NoiseEncryptionSetKeyResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_bool(1, this->success); @@ -907,9 +951,11 @@ uint32_t NoiseEncryptionSetKeyResponse::calculate_size() const { } #endif #ifdef USE_API_HOMEASSISTANT_SERVICES -void HomeassistantServiceMap::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->key); - buffer.encode_string(2, this->value); +uint8_t *HomeassistantServiceMap::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->value); + return pos; } uint32_t HomeassistantServiceMap::calculate_size() const { uint32_t size = 0; @@ -917,27 +963,29 @@ uint32_t HomeassistantServiceMap::calculate_size() const { size += ProtoSize::calc_length(1, this->value.size()); return size; } -void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->service); +uint8_t *HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->service); for (auto &it : this->data) { - buffer.encode_sub_message(2, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); } for (auto &it : this->data_template) { - buffer.encode_sub_message(3, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } for (auto &it : this->variables) { - buffer.encode_sub_message(4, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); } - buffer.encode_bool(5, this->is_event); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->is_event); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - buffer.encode_uint32(6, this->call_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->call_id); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - buffer.encode_bool(7, this->wants_response); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->wants_response); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - buffer.encode_string(8, this->response_template); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->response_template); #endif + return pos; } uint32_t HomeassistantActionRequest::calculate_size() const { uint32_t size = 0; @@ -1004,10 +1052,12 @@ bool HomeassistantActionResponse::decode_length(uint32_t field_id, ProtoLengthDe } #endif #ifdef USE_API_HOMEASSISTANT_STATES -void SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->entity_id); - buffer.encode_string(2, this->attribute); - buffer.encode_bool(3, this->once); +uint8_t *SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->entity_id); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->attribute); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->once); + return pos; } uint32_t SubscribeHomeAssistantStateResponse::calculate_size() const { uint32_t size = 0; @@ -1112,9 +1162,11 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { return true; } #ifdef USE_API_USER_DEFINED_ACTIONS -void ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->name); - buffer.encode_uint32(2, static_cast<uint32_t>(this->type)); +uint8_t *ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->type)); + return pos; } uint32_t ListEntitiesServicesArgument::calculate_size() const { uint32_t size = 0; @@ -1122,13 +1174,15 @@ uint32_t ListEntitiesServicesArgument::calculate_size() const { size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); return size; } -void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->name); - buffer.write_tag_and_fixed32(21, this->key); +uint8_t *ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); for (auto &it : this->args) { - buffer.encode_sub_message(3, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } - buffer.encode_uint32(4, static_cast<uint32_t>(this->supports_response)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(this->supports_response)); + return pos; } uint32_t ListEntitiesServicesResponse::calculate_size() const { uint32_t size = 0; @@ -1247,13 +1301,15 @@ void ExecuteServiceRequest::decode(const uint8_t *buffer, size_t length) { } #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES -void ExecuteServiceResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->call_id); - buffer.encode_bool(2, this->success); - buffer.encode_string(3, this->error_message); +uint8_t *ExecuteServiceResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->call_id); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - buffer.encode_bytes(4, this->response_data, this->response_data_len); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 4, this->response_data, this->response_data_len); #endif + return pos; } uint32_t ExecuteServiceResponse::calculate_size() const { uint32_t size = 0; @@ -1267,18 +1323,20 @@ uint32_t ExecuteServiceResponse::calculate_size() const { } #endif #ifdef USE_CAMERA -void ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); - buffer.encode_bool(5, this->disabled_by_default); +uint8_t *ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(6, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->icon); #endif - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(8, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif + return pos; } uint32_t ListEntitiesCameraResponse::calculate_size() const { uint32_t size = 0; @@ -1295,13 +1353,15 @@ uint32_t ListEntitiesCameraResponse::calculate_size() const { #endif return size; } -void CameraImageResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bytes(2, this->data_ptr_, this->data_len_); - buffer.encode_bool(3, this->done); +uint8_t *CameraImageResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->done); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t CameraImageResponse::calculate_size() const { uint32_t size = 0; @@ -1328,48 +1388,50 @@ bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t v } #endif #ifdef USE_CLIMATE -void ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); - buffer.encode_bool(5, this->supports_current_temperature); - buffer.encode_bool(6, this->supports_two_point_target_temperature); +uint8_t *ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_current_temperature); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_two_point_target_temperature); for (const auto &it : *this->supported_modes) { - buffer.encode_uint32(7, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(it), true); } - buffer.encode_float(8, this->visual_min_temperature); - buffer.encode_float(9, this->visual_max_temperature); - buffer.encode_float(10, this->visual_target_temperature_step); - buffer.encode_bool(12, this->supports_action); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->visual_min_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->visual_max_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->visual_target_temperature_step); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_action); for (const auto &it : *this->supported_fan_modes) { - buffer.encode_uint32(13, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast<uint32_t>(it), true); } for (const auto &it : *this->supported_swing_modes) { - buffer.encode_uint32(14, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, static_cast<uint32_t>(it), true); } for (const char *it : *this->supported_custom_fan_modes) { - buffer.encode_string(15, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 15, it, strlen(it), true); } for (const auto &it : *this->supported_presets) { - buffer.encode_uint32(16, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, static_cast<uint32_t>(it), true); } for (const char *it : *this->supported_custom_presets) { - buffer.encode_string(17, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 17, it, strlen(it), true); } - buffer.encode_bool(18, this->disabled_by_default); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 18, this->disabled_by_default); #ifdef USE_ENTITY_ICON - buffer.encode_string(19, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 19, this->icon); #endif - buffer.encode_uint32(20, static_cast<uint32_t>(this->entity_category)); - buffer.encode_float(21, this->visual_current_temperature_step); - buffer.encode_bool(22, this->supports_current_humidity); - buffer.encode_bool(23, this->supports_target_humidity); - buffer.encode_float(24, this->visual_min_humidity); - buffer.encode_float(25, this->visual_max_humidity); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 20, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 21, this->visual_current_temperature_step); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 22, this->supports_current_humidity); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 23, this->supports_target_humidity); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 24, this->visual_min_humidity); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 25, this->visual_max_humidity); #ifdef USE_DEVICES - buffer.encode_uint32(26, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 26, this->device_id); #endif - buffer.encode_uint32(27, this->feature_flags); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 27, this->feature_flags); + return pos; } uint32_t ListEntitiesClimateResponse::calculate_size() const { uint32_t size = 0; @@ -1428,24 +1490,26 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { size += ProtoSize::calc_uint32(2, this->feature_flags); return size; } -void ClimateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); - buffer.encode_float(3, this->current_temperature); - buffer.encode_float(4, this->target_temperature); - buffer.encode_float(5, this->target_temperature_low); - buffer.encode_float(6, this->target_temperature_high); - buffer.encode_uint32(8, static_cast<uint32_t>(this->action)); - buffer.encode_uint32(9, static_cast<uint32_t>(this->fan_mode)); - buffer.encode_uint32(10, static_cast<uint32_t>(this->swing_mode)); - buffer.encode_string(11, this->custom_fan_mode); - buffer.encode_uint32(12, static_cast<uint32_t>(this->preset)); - buffer.encode_string(13, this->custom_preset); - buffer.encode_float(14, this->current_humidity); - buffer.encode_float(15, this->target_humidity); +uint8_t *ClimateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->mode)); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->current_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->target_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->target_temperature_low); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->target_temperature_high); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast<uint32_t>(this->action)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast<uint32_t>(this->fan_mode)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(this->swing_mode)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->custom_fan_mode); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(this->preset)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->custom_preset); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 14, this->current_humidity); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 15, this->target_humidity); #ifdef USE_DEVICES - buffer.encode_uint32(16, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); #endif + return pos; } uint32_t ClimateStateResponse::calculate_size() const { uint32_t size = 0; @@ -1561,25 +1625,27 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_WATER_HEATER -void ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(4, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif - buffer.encode_bool(5, this->disabled_by_default); - buffer.encode_uint32(6, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(7, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); #endif - buffer.encode_float(8, this->min_temperature); - buffer.encode_float(9, this->max_temperature); - buffer.encode_float(10, this->target_temperature_step); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->min_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->max_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->target_temperature_step); for (const auto &it : *this->supported_modes) { - buffer.encode_uint32(11, static_cast<uint32_t>(it), true); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(it), true); } - buffer.encode_uint32(12, this->supported_features); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supported_features); + return pos; } uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { uint32_t size = 0; @@ -1605,17 +1671,19 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->supported_features); return size; } -void WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_float(2, this->current_temperature); - buffer.encode_float(3, this->target_temperature); - buffer.encode_uint32(4, static_cast<uint32_t>(this->mode)); +uint8_t *WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->current_temperature); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->target_temperature); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(this->mode)); #ifdef USE_DEVICES - buffer.encode_uint32(5, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); #endif - buffer.encode_uint32(6, this->state); - buffer.encode_float(7, this->target_temperature_low); - buffer.encode_float(8, this->target_temperature_high); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->state); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->target_temperature_low); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->target_temperature_high); + return pos; } uint32_t WaterHeaterStateResponse::calculate_size() const { uint32_t size = 0; @@ -1673,24 +1741,26 @@ bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value } #endif #ifdef USE_NUMBER -void ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_float(6, this->min_value); - buffer.encode_float(7, this->max_value); - buffer.encode_float(8, this->step); - buffer.encode_bool(9, this->disabled_by_default); - buffer.encode_uint32(10, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(11, this->unit_of_measurement); - buffer.encode_uint32(12, static_cast<uint32_t>(this->mode)); - buffer.encode_string(13, this->device_class); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->min_value); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->max_value); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->step); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->unit_of_measurement); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(this->mode)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_class); #ifdef USE_DEVICES - buffer.encode_uint32(14, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif + return pos; } uint32_t ListEntitiesNumberResponse::calculate_size() const { uint32_t size = 0; @@ -1713,13 +1783,15 @@ uint32_t ListEntitiesNumberResponse::calculate_size() const { #endif return size; } -void NumberStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_float(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *NumberStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t NumberStateResponse::calculate_size() const { uint32_t size = 0; @@ -1758,21 +1830,23 @@ bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SELECT -void ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif for (const char *it : *this->options) { - buffer.encode_string(6, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, it, strlen(it), true); } - buffer.encode_bool(7, this->disabled_by_default); - buffer.encode_uint32(8, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(9, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif + return pos; } uint32_t ListEntitiesSelectResponse::calculate_size() const { uint32_t size = 0; @@ -1794,13 +1868,15 @@ uint32_t ListEntitiesSelectResponse::calculate_size() const { #endif return size; } -void SelectStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_string(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *SelectStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t SelectStateResponse::calculate_size() const { uint32_t size = 0; @@ -1847,23 +1923,25 @@ bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_SIREN -void ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); for (const char *it : *this->tones) { - buffer.encode_string(7, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, it, strlen(it), true); } - buffer.encode_bool(8, this->supports_duration); - buffer.encode_bool(9, this->supports_volume); - buffer.encode_uint32(10, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supports_duration); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_volume); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(11, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif + return pos; } uint32_t ListEntitiesSirenResponse::calculate_size() const { uint32_t size = 0; @@ -1887,12 +1965,14 @@ uint32_t ListEntitiesSirenResponse::calculate_size() const { #endif return size; } -void SirenStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->state); +uint8_t *SirenStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); #ifdef USE_DEVICES - buffer.encode_uint32(3, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif + return pos; } uint32_t SirenStateResponse::calculate_size() const { uint32_t size = 0; @@ -1959,22 +2039,24 @@ bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_LOCK -void ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_bool(8, this->assumed_state); - buffer.encode_bool(9, this->supports_open); - buffer.encode_bool(10, this->requires_code); - buffer.encode_string(11, this->code_format); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->assumed_state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_open); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->code_format); #ifdef USE_DEVICES - buffer.encode_uint32(12, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif + return pos; } uint32_t ListEntitiesLockResponse::calculate_size() const { uint32_t size = 0; @@ -1995,12 +2077,14 @@ uint32_t ListEntitiesLockResponse::calculate_size() const { #endif return size; } -void LockStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); +uint8_t *LockStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES - buffer.encode_uint32(3, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif + return pos; } uint32_t LockStateResponse::calculate_size() const { uint32_t size = 0; @@ -2052,19 +2136,21 @@ bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_BUTTON -void ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - buffer.encode_uint32(9, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif + return pos; } uint32_t ListEntitiesButtonResponse::calculate_size() const { uint32_t size = 0; @@ -2106,12 +2192,14 @@ bool ButtonCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_MEDIA_PLAYER -void MediaPlayerSupportedFormat::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->format); - buffer.encode_uint32(2, this->sample_rate); - buffer.encode_uint32(3, this->num_channels); - buffer.encode_uint32(4, static_cast<uint32_t>(this->purpose)); - buffer.encode_uint32(5, this->sample_bytes); +uint8_t *MediaPlayerSupportedFormat::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->format); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->sample_rate); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->num_channels); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(this->purpose)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->sample_bytes); + return pos; } uint32_t MediaPlayerSupportedFormat::calculate_size() const { uint32_t size = 0; @@ -2122,23 +2210,25 @@ uint32_t MediaPlayerSupportedFormat::calculate_size() const { size += ProtoSize::calc_uint32(1, this->sample_bytes); return size; } -void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_bool(8, this->supports_pause); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supports_pause); for (auto &it : this->supported_formats) { - buffer.encode_sub_message(9, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 9, it); } #ifdef USE_DEVICES - buffer.encode_uint32(10, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif - buffer.encode_uint32(11, this->feature_flags); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->feature_flags); + return pos; } uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { uint32_t size = 0; @@ -2162,14 +2252,16 @@ uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->feature_flags); return size; } -void MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); - buffer.encode_float(3, this->volume); - buffer.encode_bool(4, this->muted); +uint8_t *MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->state)); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->volume); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->muted); #ifdef USE_DEVICES - buffer.encode_uint32(5, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); #endif + return pos; } uint32_t MediaPlayerStateResponse::calculate_size() const { uint32_t size = 0; @@ -2248,15 +2340,20 @@ bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, } return true; } -void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const { - buffer.write_raw_byte(8); - buffer.encode_varint_raw_64(this->address); - buffer.write_raw_byte(16); - buffer.encode_varint_raw(encode_zigzag32(this->rssi)); - buffer.encode_uint32(3, this->address_type); - buffer.write_raw_byte(34); - buffer.write_raw_byte(static_cast<uint8_t>(this->data_len)); - buffer.encode_raw(this->data, this->data_len); +uint8_t *BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 8); + ProtoEncode::encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, this->address); + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 16); + ProtoEncode::encode_varint_raw_short(pos PROTO_ENCODE_DEBUG_ARG, encode_zigzag32(this->rssi)); + if (this->address_type) { + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 24); + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast<uint8_t>(this->address_type)); + } + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 34); + ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast<uint8_t>(this->data_len)); + ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, this->data, this->data_len); + return pos; } uint32_t BluetoothLERawAdvertisement::calculate_size() const { uint32_t size = 0; @@ -2266,10 +2363,12 @@ uint32_t BluetoothLERawAdvertisement::calculate_size() const { size += 2 + this->data_len; return size; } -void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const { +uint8_t *BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); for (uint16_t i = 0; i < this->advertisements_len; i++) { - buffer.encode_sub_message(1, this->advertisements[i]); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, this->advertisements[i]); } + return pos; } uint32_t BluetoothLERawAdvertisementsResponse::calculate_size() const { uint32_t size = 0; @@ -2297,11 +2396,13 @@ bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, proto_varint_value } return true; } -void BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_bool(2, this->connected); - buffer.encode_uint32(3, this->mtu); - buffer.encode_int32(4, this->error); +uint8_t *BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->connected); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->mtu); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error); + return pos; } uint32_t BluetoothDeviceConnectionResponse::calculate_size() const { uint32_t size = 0; @@ -2321,13 +2422,15 @@ bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, proto_var } return true; } -void BluetoothGATTDescriptor::encode(ProtoWriteBuffer &buffer) const { +uint8_t *BluetoothGATTDescriptor::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - buffer.encode_uint64(1, this->uuid[0], true); - buffer.encode_uint64(1, this->uuid[1], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); } - buffer.encode_uint32(2, this->handle); - buffer.encode_uint32(3, this->short_uuid); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->short_uuid); + return pos; } uint32_t BluetoothGATTDescriptor::calculate_size() const { uint32_t size = 0; @@ -2339,17 +2442,19 @@ uint32_t BluetoothGATTDescriptor::calculate_size() const { size += ProtoSize::calc_uint32(1, this->short_uuid); return size; } -void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const { +uint8_t *BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - buffer.encode_uint64(1, this->uuid[0], true); - buffer.encode_uint64(1, this->uuid[1], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); } - buffer.encode_uint32(2, this->handle); - buffer.encode_uint32(3, this->properties); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->properties); for (auto &it : this->descriptors) { - buffer.encode_sub_message(4, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); } - buffer.encode_uint32(5, this->short_uuid); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->short_uuid); + return pos; } uint32_t BluetoothGATTCharacteristic::calculate_size() const { uint32_t size = 0; @@ -2367,16 +2472,18 @@ uint32_t BluetoothGATTCharacteristic::calculate_size() const { size += ProtoSize::calc_uint32(1, this->short_uuid); return size; } -void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const { +uint8_t *BluetoothGATTService::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - buffer.encode_uint64(1, this->uuid[0], true); - buffer.encode_uint64(1, this->uuid[1], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); } - buffer.encode_uint32(2, this->handle); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); for (auto &it : this->characteristics) { - buffer.encode_sub_message(3, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } - buffer.encode_uint32(4, this->short_uuid); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->short_uuid); + return pos; } uint32_t BluetoothGATTService::calculate_size() const { uint32_t size = 0; @@ -2393,11 +2500,13 @@ uint32_t BluetoothGATTService::calculate_size() const { size += ProtoSize::calc_uint32(1, this->short_uuid); return size; } -void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); +uint8_t *BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); for (auto &it : this->services) { - buffer.encode_sub_message(2, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); } + return pos; } uint32_t BluetoothGATTGetServicesResponse::calculate_size() const { uint32_t size = 0; @@ -2409,8 +2518,10 @@ uint32_t BluetoothGATTGetServicesResponse::calculate_size() const { } return size; } -void BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); +uint8_t *BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + return pos; } uint32_t BluetoothGATTGetServicesDoneResponse::calculate_size() const { uint32_t size = 0; @@ -2430,10 +2541,12 @@ bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, proto_varint_val } return true; } -void BluetoothGATTReadResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_uint32(2, this->handle); - buffer.encode_bytes(3, this->data_ptr_, this->data_len_); +uint8_t *BluetoothGATTReadResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); + return pos; } uint32_t BluetoothGATTReadResponse::calculate_size() const { uint32_t size = 0; @@ -2524,10 +2637,12 @@ bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, proto_varint_v } return true; } -void BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_uint32(2, this->handle); - buffer.encode_bytes(3, this->data_ptr_, this->data_len_); +uint8_t *BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); + return pos; } uint32_t BluetoothGATTNotifyDataResponse::calculate_size() const { uint32_t size = 0; @@ -2536,14 +2651,16 @@ uint32_t BluetoothGATTNotifyDataResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->data_len_); return size; } -void BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->free); - buffer.encode_uint32(2, this->limit); +uint8_t *BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->free); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->limit); for (const auto &it : this->allocated) { if (it != 0) { - buffer.encode_uint64(3, it, true); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); } } + return pos; } uint32_t BluetoothConnectionsFreeResponse::calculate_size() const { uint32_t size = 0; @@ -2556,10 +2673,12 @@ uint32_t BluetoothConnectionsFreeResponse::calculate_size() const { } return size; } -void BluetoothGATTErrorResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_uint32(2, this->handle); - buffer.encode_int32(3, this->error); +uint8_t *BluetoothGATTErrorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + return pos; } uint32_t BluetoothGATTErrorResponse::calculate_size() const { uint32_t size = 0; @@ -2568,9 +2687,11 @@ uint32_t BluetoothGATTErrorResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->error); return size; } -void BluetoothGATTWriteResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_uint32(2, this->handle); +uint8_t *BluetoothGATTWriteResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + return pos; } uint32_t BluetoothGATTWriteResponse::calculate_size() const { uint32_t size = 0; @@ -2578,9 +2699,11 @@ uint32_t BluetoothGATTWriteResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->handle); return size; } -void BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_uint32(2, this->handle); +uint8_t *BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + return pos; } uint32_t BluetoothGATTNotifyResponse::calculate_size() const { uint32_t size = 0; @@ -2588,10 +2711,12 @@ uint32_t BluetoothGATTNotifyResponse::calculate_size() const { size += ProtoSize::calc_uint32(1, this->handle); return size; } -void BluetoothDevicePairingResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_bool(2, this->paired); - buffer.encode_int32(3, this->error); +uint8_t *BluetoothDevicePairingResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->paired); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + return pos; } uint32_t BluetoothDevicePairingResponse::calculate_size() const { uint32_t size = 0; @@ -2600,10 +2725,12 @@ uint32_t BluetoothDevicePairingResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->error); return size; } -void BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_bool(2, this->success); - buffer.encode_int32(3, this->error); +uint8_t *BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + return pos; } uint32_t BluetoothDeviceUnpairingResponse::calculate_size() const { uint32_t size = 0; @@ -2612,10 +2739,12 @@ uint32_t BluetoothDeviceUnpairingResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->error); return size; } -void BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_bool(2, this->success); - buffer.encode_int32(3, this->error); +uint8_t *BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + return pos; } uint32_t BluetoothDeviceClearCacheResponse::calculate_size() const { uint32_t size = 0; @@ -2624,10 +2753,12 @@ uint32_t BluetoothDeviceClearCacheResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->error); return size; } -void BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, static_cast<uint32_t>(this->state)); - buffer.encode_uint32(2, static_cast<uint32_t>(this->mode)); - buffer.encode_uint32(3, static_cast<uint32_t>(this->configured_mode)); +uint8_t *BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast<uint32_t>(this->state)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->mode)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast<uint32_t>(this->configured_mode)); + return pos; } uint32_t BluetoothScannerStateResponse::calculate_size() const { uint32_t size = 0; @@ -2661,10 +2792,12 @@ bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, proto_vari } return true; } -void VoiceAssistantAudioSettings::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->noise_suppression_level); - buffer.encode_uint32(2, this->auto_gain); - buffer.encode_float(3, this->volume_multiplier); +uint8_t *VoiceAssistantAudioSettings::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->noise_suppression_level); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->auto_gain); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->volume_multiplier); + return pos; } uint32_t VoiceAssistantAudioSettings::calculate_size() const { uint32_t size = 0; @@ -2673,12 +2806,14 @@ uint32_t VoiceAssistantAudioSettings::calculate_size() const { size += ProtoSize::calc_float(1, this->volume_multiplier); return size; } -void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_bool(1, this->start); - buffer.encode_string(2, this->conversation_id); - buffer.encode_uint32(3, this->flags); - buffer.encode_optional_sub_message(4, this->audio_settings); - buffer.encode_string(5, this->wake_word_phrase); +uint8_t *VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->start); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->conversation_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->flags); + ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, this->audio_settings); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->wake_word_phrase); + return pos; } uint32_t VoiceAssistantRequest::calculate_size() const { uint32_t size = 0; @@ -2760,9 +2895,11 @@ bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited } return true; } -void VoiceAssistantAudio::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_bytes(1, this->data, this->data_len); - buffer.encode_bool(2, this->end); +uint8_t *VoiceAssistantAudio::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->end); + return pos; } uint32_t VoiceAssistantAudio::calculate_size() const { uint32_t size = 0; @@ -2833,18 +2970,24 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength } return true; } -void VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bool(1, this->success); } +uint8_t *VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); + return pos; +} uint32_t VoiceAssistantAnnounceFinished::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_bool(1, this->success); return size; } -void VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->id); - buffer.encode_string(2, this->wake_word); +uint8_t *VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->id); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->wake_word); for (auto &it : this->trained_languages) { - buffer.encode_string(3, it, true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); } + return pos; } uint32_t VoiceAssistantWakeWord::calculate_size() const { uint32_t size = 0; @@ -2908,14 +3051,16 @@ bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoL } return true; } -void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer) const { +uint8_t *VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); for (auto &it : this->available_wake_words) { - buffer.encode_sub_message(1, it); + ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, it); } for (const auto &it : *this->active_wake_words) { - buffer.encode_string(2, it, true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, it, true); } - buffer.encode_uint32(3, this->max_active_wake_words); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->max_active_wake_words); + return pos; } uint32_t VoiceAssistantConfigurationResponse::calculate_size() const { uint32_t size = 0; @@ -2944,21 +3089,23 @@ bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengt } #endif #ifdef USE_ALARM_CONTROL_PANEL -void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_uint32(8, this->supported_features); - buffer.encode_bool(9, this->requires_code); - buffer.encode_bool(10, this->requires_code_to_arm); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_features); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->requires_code); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code_to_arm); #ifdef USE_DEVICES - buffer.encode_uint32(11, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif + return pos; } uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { uint32_t size = 0; @@ -2978,12 +3125,14 @@ uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { #endif return size; } -void AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_uint32(2, static_cast<uint32_t>(this->state)); +uint8_t *AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->state)); #ifdef USE_DEVICES - buffer.encode_uint32(3, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif + return pos; } uint32_t AlarmControlPanelStateResponse::calculate_size() const { uint32_t size = 0; @@ -3032,22 +3181,24 @@ bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit } #endif #ifdef USE_TEXT -void ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_uint32(8, this->min_length); - buffer.encode_uint32(9, this->max_length); - buffer.encode_string(10, this->pattern); - buffer.encode_uint32(11, static_cast<uint32_t>(this->mode)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->min_length); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->max_length); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->pattern); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast<uint32_t>(this->mode)); #ifdef USE_DEVICES - buffer.encode_uint32(12, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif + return pos; } uint32_t ListEntitiesTextResponse::calculate_size() const { uint32_t size = 0; @@ -3068,13 +3219,15 @@ uint32_t ListEntitiesTextResponse::calculate_size() const { #endif return size; } -void TextStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_string(2, this->state); - buffer.encode_bool(3, this->missing_state); +uint8_t *TextStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t TextStateResponse::calculate_size() const { uint32_t size = 0; @@ -3121,18 +3274,20 @@ bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_DATE -void ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(8, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif + return pos; } uint32_t ListEntitiesDateResponse::calculate_size() const { uint32_t size = 0; @@ -3149,15 +3304,17 @@ uint32_t ListEntitiesDateResponse::calculate_size() const { #endif return size; } -void DateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->missing_state); - buffer.encode_uint32(3, this->year); - buffer.encode_uint32(4, this->month); - buffer.encode_uint32(5, this->day); +uint8_t *DateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->year); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->month); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->day); #ifdef USE_DEVICES - buffer.encode_uint32(6, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif + return pos; } uint32_t DateStateResponse::calculate_size() const { uint32_t size = 0; @@ -3204,18 +3361,20 @@ bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_TIME -void ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(8, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif + return pos; } uint32_t ListEntitiesTimeResponse::calculate_size() const { uint32_t size = 0; @@ -3232,15 +3391,17 @@ uint32_t ListEntitiesTimeResponse::calculate_size() const { #endif return size; } -void TimeStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->missing_state); - buffer.encode_uint32(3, this->hour); - buffer.encode_uint32(4, this->minute); - buffer.encode_uint32(5, this->second); +uint8_t *TimeStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->hour); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->minute); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->second); #ifdef USE_DEVICES - buffer.encode_uint32(6, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif + return pos; } uint32_t TimeStateResponse::calculate_size() const { uint32_t size = 0; @@ -3287,22 +3448,24 @@ bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_EVENT -void ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); for (const char *it : *this->event_types) { - buffer.encode_string(9, it, strlen(it), true); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, it, strlen(it), true); } #ifdef USE_DEVICES - buffer.encode_uint32(10, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif + return pos; } uint32_t ListEntitiesEventResponse::calculate_size() const { uint32_t size = 0; @@ -3325,12 +3488,14 @@ uint32_t ListEntitiesEventResponse::calculate_size() const { #endif return size; } -void EventResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_string(2, this->event_type); +uint8_t *EventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->event_type); #ifdef USE_DEVICES - buffer.encode_uint32(3, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif + return pos; } uint32_t EventResponse::calculate_size() const { uint32_t size = 0; @@ -3343,22 +3508,24 @@ uint32_t EventResponse::calculate_size() const { } #endif #ifdef USE_VALVE -void ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(8, this->device_class); - buffer.encode_bool(9, this->assumed_state); - buffer.encode_bool(10, this->supports_position); - buffer.encode_bool(11, this->supports_stop); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->assumed_state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->supports_position); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 11, this->supports_stop); #ifdef USE_DEVICES - buffer.encode_uint32(12, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif + return pos; } uint32_t ListEntitiesValveResponse::calculate_size() const { uint32_t size = 0; @@ -3379,13 +3546,15 @@ uint32_t ListEntitiesValveResponse::calculate_size() const { #endif return size; } -void ValveStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_float(2, this->position); - buffer.encode_uint32(3, static_cast<uint32_t>(this->current_operation)); +uint8_t *ValveStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->position); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast<uint32_t>(this->current_operation)); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t ValveStateResponse::calculate_size() const { uint32_t size = 0; @@ -3430,18 +3599,20 @@ bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_DATETIME_DATETIME -void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(8, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif + return pos; } uint32_t ListEntitiesDateTimeResponse::calculate_size() const { uint32_t size = 0; @@ -3458,13 +3629,15 @@ uint32_t ListEntitiesDateTimeResponse::calculate_size() const { #endif return size; } -void DateTimeStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->missing_state); - buffer.encode_fixed32(3, this->epoch_seconds); +uint8_t *DateTimeStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + ProtoEncode::encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->epoch_seconds); #ifdef USE_DEVICES - buffer.encode_uint32(4, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif + return pos; } uint32_t DateTimeStateResponse::calculate_size() const { uint32_t size = 0; @@ -3503,19 +3676,21 @@ bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_UPDATE -void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(5, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - buffer.encode_bool(6, this->disabled_by_default); - buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category)); - buffer.encode_string(8, this->device_class); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - buffer.encode_uint32(9, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif + return pos; } uint32_t ListEntitiesUpdateResponse::calculate_size() const { uint32_t size = 0; @@ -3533,20 +3708,22 @@ uint32_t ListEntitiesUpdateResponse::calculate_size() const { #endif return size; } -void UpdateStateResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.write_tag_and_fixed32(13, this->key); - buffer.encode_bool(2, this->missing_state); - buffer.encode_bool(3, this->in_progress); - buffer.encode_bool(4, this->has_progress); - buffer.encode_float(5, this->progress); - buffer.encode_string(6, this->current_version); - buffer.encode_string(7, this->latest_version); - buffer.encode_string(8, this->title); - buffer.encode_string(9, this->release_summary); - buffer.encode_string(10, this->release_url); +uint8_t *UpdateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->in_progress); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->has_progress); + ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->progress); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->current_version); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->latest_version); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->title); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->release_summary); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->release_url); #ifdef USE_DEVICES - buffer.encode_uint32(11, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif + return pos; } uint32_t UpdateStateResponse::calculate_size() const { uint32_t size = 0; @@ -3604,7 +3781,11 @@ bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited valu } return true; } -void ZWaveProxyFrame::encode(ProtoWriteBuffer &buffer) const { buffer.encode_bytes(1, this->data, this->data_len); } +uint8_t *ZWaveProxyFrame::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); + return pos; +} uint32_t ZWaveProxyFrame::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->data_len); @@ -3632,9 +3813,11 @@ bool ZWaveProxyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited va } return true; } -void ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, static_cast<uint32_t>(this->type)); - buffer.encode_bytes(2, this->data, this->data_len); +uint8_t *ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast<uint32_t>(this->type)); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data, this->data_len); + return pos; } uint32_t ZWaveProxyRequest::calculate_size() const { uint32_t size = 0; @@ -3644,20 +3827,22 @@ uint32_t ZWaveProxyRequest::calculate_size() const { } #endif #ifdef USE_INFRARED -void ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_string(1, this->object_id); - buffer.write_tag_and_fixed32(21, this->key); - buffer.encode_string(3, this->name); +uint8_t *ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); #ifdef USE_ENTITY_ICON - buffer.encode_string(4, this->icon); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif - buffer.encode_bool(5, this->disabled_by_default); - buffer.encode_uint32(6, static_cast<uint32_t>(this->entity_category)); + ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast<uint32_t>(this->entity_category)); #ifdef USE_DEVICES - buffer.encode_uint32(7, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); #endif - buffer.encode_uint32(8, this->capabilities); - buffer.encode_uint32(9, this->receiver_frequency); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->capabilities); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->receiver_frequency); + return pos; } uint32_t ListEntitiesInfraredResponse::calculate_size() const { uint32_t size = 0; @@ -3719,14 +3904,16 @@ bool InfraredRFTransmitRawTimingsRequest::decode_32bit(uint32_t field_id, Proto3 } return true; } -void InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer) const { +uint8_t *InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); #ifdef USE_DEVICES - buffer.encode_uint32(1, this->device_id); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); #endif - buffer.write_tag_and_fixed32(21, this->key); + ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); for (const auto &it : *this->timings) { - buffer.encode_sint32(3, it, true); + ProtoEncode::encode_sint32(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); } + return pos; } uint32_t InfraredRFReceiveEvent::calculate_size() const { uint32_t size = 0; @@ -3768,9 +3955,11 @@ bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, proto_varint_ } return true; } -void SerialProxyDataReceived::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->instance); - buffer.encode_bytes(2, this->data_ptr_, this->data_len_); +uint8_t *SerialProxyDataReceived::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); + return pos; } uint32_t SerialProxyDataReceived::calculate_size() const { uint32_t size = 0; @@ -3823,9 +4012,11 @@ bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, proto_vari } return true; } -void SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->instance); - buffer.encode_uint32(2, this->line_states); +uint8_t *SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->line_states); + return pos; } uint32_t SerialProxyGetModemPinsResponse::calculate_size() const { uint32_t size = 0; @@ -3846,11 +4037,13 @@ bool SerialProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t v } return true; } -void SerialProxyRequestResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint32(1, this->instance); - buffer.encode_uint32(2, static_cast<uint32_t>(this->type)); - buffer.encode_uint32(3, static_cast<uint32_t>(this->status)); - buffer.encode_string(4, this->error_message); +uint8_t *SerialProxyRequestResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(this->type)); + ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast<uint32_t>(this->status)); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error_message); + return pos; } uint32_t SerialProxyRequestResponse::calculate_size() const { uint32_t size = 0; @@ -3884,9 +4077,11 @@ bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, proto } return true; } -void BluetoothSetConnectionParamsResponse::encode(ProtoWriteBuffer &buffer) const { - buffer.encode_uint64(1, this->address); - buffer.encode_int32(2, this->error); +uint8_t *BluetoothSetConnectionParamsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { + uint8_t *__restrict__ pos = buffer.get_pos(); + ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->error); + return pos; } uint32_t BluetoothSetConnectionParamsResponse::calculate_size() const { uint32_t size = 0; diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 14f6c704ae..3b239db36c 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -412,7 +412,7 @@ class HelloResponse final : public ProtoMessage { uint32_t api_version_minor{0}; StringRef server_info{}; StringRef name{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -477,7 +477,7 @@ class AreaInfo final : public ProtoMessage { public: uint32_t area_id{0}; StringRef name{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -492,7 +492,7 @@ class DeviceInfo final : public ProtoMessage { uint32_t device_id{0}; StringRef name{}; uint32_t area_id{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -506,7 +506,7 @@ class SerialProxyInfo final : public ProtoMessage { public: StringRef name{}; enums::SerialProxyPortType port_type{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -574,7 +574,7 @@ class DeviceInfoResponse final : public ProtoMessage { #ifdef USE_SERIAL_PROXY std::array<SerialProxyInfo, SERIAL_PROXY_COUNT> serial_proxies{}; #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -605,7 +605,7 @@ class ListEntitiesBinarySensorResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; bool is_status_binary_sensor{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -622,7 +622,7 @@ class BinarySensorStateResponse final : public StateResponseProtoMessage { #endif bool state{false}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -644,7 +644,7 @@ class ListEntitiesCoverResponse final : public InfoResponseProtoMessage { bool supports_tilt{false}; StringRef device_class{}; bool supports_stop{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -662,7 +662,7 @@ class CoverStateResponse final : public StateResponseProtoMessage { float position{0.0f}; float tilt{0.0f}; enums::CoverOperation current_operation{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -704,7 +704,7 @@ class ListEntitiesFanResponse final : public InfoResponseProtoMessage { bool supports_direction{false}; int32_t supported_speed_count{0}; const std::vector<const char *> *supported_preset_modes{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -724,7 +724,7 @@ class FanStateResponse final : public StateResponseProtoMessage { enums::FanDirection direction{}; int32_t speed_level{0}; StringRef preset_mode{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -771,7 +771,7 @@ class ListEntitiesLightResponse final : public InfoResponseProtoMessage { float min_mireds{0.0f}; float max_mireds{0.0f}; const FixedVector<const char *> *effects{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -798,7 +798,7 @@ class LightStateResponse final : public StateResponseProtoMessage { float cold_white{0.0f}; float warm_white{0.0f}; StringRef effect{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -862,7 +862,7 @@ class ListEntitiesSensorResponse final : public InfoResponseProtoMessage { bool force_update{false}; StringRef device_class{}; enums::SensorStateClass state_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -879,7 +879,7 @@ class SensorStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -898,7 +898,7 @@ class ListEntitiesSwitchResponse final : public InfoResponseProtoMessage { #endif bool assumed_state{false}; StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -914,7 +914,7 @@ class SwitchStateResponse final : public StateResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("switch_state_response"); } #endif bool state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -948,7 +948,7 @@ class ListEntitiesTextSensorResponse final : public InfoResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("list_entities_text_sensor_response"); } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -965,7 +965,7 @@ class TextSensorStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1004,7 +1004,7 @@ class SubscribeLogsResponse final : public ProtoMessage { this->message_ptr_ = data; this->message_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1037,7 +1037,7 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage { const LogString *message_name() const override { return LOG_STR("noise_encryption_set_key_response"); } #endif bool success{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1051,7 +1051,7 @@ class HomeassistantServiceMap final : public ProtoMessage { public: StringRef key{}; StringRef value{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1080,7 +1080,7 @@ class HomeassistantActionRequest final : public ProtoMessage { #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON StringRef response_template{}; #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1124,7 +1124,7 @@ class SubscribeHomeAssistantStateResponse final : public ProtoMessage { StringRef entity_id{}; StringRef attribute{}; bool once{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1215,7 +1215,7 @@ class ListEntitiesServicesArgument final : public ProtoMessage { public: StringRef name{}; enums::ServiceArgType type{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1234,7 +1234,7 @@ class ListEntitiesServicesResponse final : public ProtoMessage { uint32_t key{0}; FixedVector<ListEntitiesServicesArgument> args{}; enums::SupportsResponseType supports_response{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1304,7 +1304,7 @@ class ExecuteServiceResponse final : public ProtoMessage { const uint8_t *response_data{nullptr}; uint16_t response_data_len{0}; #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1321,7 +1321,7 @@ class ListEntitiesCameraResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const LogString *message_name() const override { return LOG_STR("list_entities_camera_response"); } #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1343,7 +1343,7 @@ class CameraImageResponse final : public StateResponseProtoMessage { this->data_len_ = len; } bool done{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1394,7 +1394,7 @@ class ListEntitiesClimateResponse final : public InfoResponseProtoMessage { float visual_min_humidity{0.0f}; float visual_max_humidity{0.0f}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1422,7 +1422,7 @@ class ClimateStateResponse final : public StateResponseProtoMessage { StringRef custom_preset{}; float current_humidity{0.0f}; float target_humidity{0.0f}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1480,7 +1480,7 @@ class ListEntitiesWaterHeaterResponse final : public InfoResponseProtoMessage { float target_temperature_step{0.0f}; const water_heater::WaterHeaterModeMask *supported_modes{}; uint32_t supported_features{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1501,7 +1501,7 @@ class WaterHeaterStateResponse final : public StateResponseProtoMessage { uint32_t state{0}; float target_temperature_low{0.0f}; float target_temperature_high{0.0f}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1545,7 +1545,7 @@ class ListEntitiesNumberResponse final : public InfoResponseProtoMessage { StringRef unit_of_measurement{}; enums::NumberMode mode{}; StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1562,7 +1562,7 @@ class NumberStateResponse final : public StateResponseProtoMessage { #endif float state{0.0f}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1596,7 +1596,7 @@ class ListEntitiesSelectResponse final : public InfoResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("list_entities_select_response"); } #endif const FixedVector<const char *> *options{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1613,7 +1613,7 @@ class SelectStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1650,7 +1650,7 @@ class ListEntitiesSirenResponse final : public InfoResponseProtoMessage { const FixedVector<const char *> *tones{}; bool supports_duration{false}; bool supports_volume{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1666,7 +1666,7 @@ class SirenStateResponse final : public StateResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("siren_state_response"); } #endif bool state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1711,7 +1711,7 @@ class ListEntitiesLockResponse final : public InfoResponseProtoMessage { bool supports_open{false}; bool requires_code{false}; StringRef code_format{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1727,7 +1727,7 @@ class LockStateResponse final : public StateResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("lock_state_response"); } #endif enums::LockState state{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1764,7 +1764,7 @@ class ListEntitiesButtonResponse final : public InfoResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("list_entities_button_response"); } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1796,7 +1796,7 @@ class MediaPlayerSupportedFormat final : public ProtoMessage { uint32_t num_channels{0}; enums::MediaPlayerFormatPurpose purpose{}; uint32_t sample_bytes{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1814,7 +1814,7 @@ class ListEntitiesMediaPlayerResponse final : public InfoResponseProtoMessage { bool supports_pause{false}; std::vector<MediaPlayerSupportedFormat> supported_formats{}; uint32_t feature_flags{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1832,7 +1832,7 @@ class MediaPlayerStateResponse final : public StateResponseProtoMessage { enums::MediaPlayerState state{}; float volume{0.0f}; bool muted{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1888,7 +1888,7 @@ class BluetoothLERawAdvertisement final : public ProtoMessage { uint32_t address_type{0}; uint8_t data[62]{}; uint8_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1905,7 +1905,7 @@ class BluetoothLERawAdvertisementsResponse final : public ProtoMessage { #endif std::array<BluetoothLERawAdvertisement, BLUETOOTH_PROXY_ADVERTISEMENT_BATCH_SIZE> advertisements{}; uint16_t advertisements_len{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1942,7 +1942,7 @@ class BluetoothDeviceConnectionResponse final : public ProtoMessage { bool connected{false}; uint32_t mtu{0}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1970,7 +1970,7 @@ class BluetoothGATTDescriptor final : public ProtoMessage { std::array<uint64_t, 2> uuid{}; uint32_t handle{0}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1985,7 +1985,7 @@ class BluetoothGATTCharacteristic final : public ProtoMessage { uint32_t properties{0}; FixedVector<BluetoothGATTDescriptor> descriptors{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -1999,7 +1999,7 @@ class BluetoothGATTService final : public ProtoMessage { uint32_t handle{0}; FixedVector<BluetoothGATTCharacteristic> characteristics{}; uint32_t short_uuid{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2016,7 +2016,7 @@ class BluetoothGATTGetServicesResponse final : public ProtoMessage { #endif uint64_t address{0}; std::vector<BluetoothGATTService> services{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2032,7 +2032,7 @@ class BluetoothGATTGetServicesDoneResponse final : public ProtoMessage { const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_done_response"); } #endif uint64_t address{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2071,7 +2071,7 @@ class BluetoothGATTReadResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2166,7 +2166,7 @@ class BluetoothGATTNotifyDataResponse final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2184,7 +2184,7 @@ class BluetoothConnectionsFreeResponse final : public ProtoMessage { uint32_t free{0}; uint32_t limit{0}; std::array<uint64_t, BLUETOOTH_PROXY_MAX_CONNECTIONS> allocated{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2202,7 +2202,7 @@ class BluetoothGATTErrorResponse final : public ProtoMessage { uint64_t address{0}; uint32_t handle{0}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2219,7 +2219,7 @@ class BluetoothGATTWriteResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2236,7 +2236,7 @@ class BluetoothGATTNotifyResponse final : public ProtoMessage { #endif uint64_t address{0}; uint32_t handle{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2254,7 +2254,7 @@ class BluetoothDevicePairingResponse final : public ProtoMessage { uint64_t address{0}; bool paired{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2272,7 +2272,7 @@ class BluetoothDeviceUnpairingResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2290,7 +2290,7 @@ class BluetoothDeviceClearCacheResponse final : public ProtoMessage { uint64_t address{0}; bool success{false}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2308,7 +2308,7 @@ class BluetoothScannerStateResponse final : public ProtoMessage { enums::BluetoothScannerState state{}; enums::BluetoothScannerMode mode{}; enums::BluetoothScannerMode configured_mode{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2354,7 +2354,7 @@ class VoiceAssistantAudioSettings final : public ProtoMessage { uint32_t noise_suppression_level{0}; uint32_t auto_gain{0}; float volume_multiplier{0.0f}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2374,7 +2374,7 @@ class VoiceAssistantRequest final : public ProtoMessage { uint32_t flags{0}; VoiceAssistantAudioSettings audio_settings{}; StringRef wake_word_phrase{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2436,7 +2436,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { const uint8_t *data{nullptr}; uint16_t data_len{0}; bool end{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2494,7 +2494,7 @@ class VoiceAssistantAnnounceFinished final : public ProtoMessage { const LogString *message_name() const override { return LOG_STR("voice_assistant_announce_finished"); } #endif bool success{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2507,7 +2507,7 @@ class VoiceAssistantWakeWord final : public ProtoMessage { StringRef id{}; StringRef wake_word{}; std::vector<std::string> trained_languages{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2557,7 +2557,7 @@ class VoiceAssistantConfigurationResponse final : public ProtoMessage { std::vector<VoiceAssistantWakeWord> available_wake_words{}; const std::vector<std::string> *active_wake_words{}; uint32_t max_active_wake_words{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2592,7 +2592,7 @@ class ListEntitiesAlarmControlPanelResponse final : public InfoResponseProtoMess uint32_t supported_features{0}; bool requires_code{false}; bool requires_code_to_arm{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2608,7 +2608,7 @@ class AlarmControlPanelStateResponse final : public StateResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("alarm_control_panel_state_response"); } #endif enums::AlarmControlPanelState state{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2647,7 +2647,7 @@ class ListEntitiesTextResponse final : public InfoResponseProtoMessage { uint32_t max_length{0}; StringRef pattern{}; enums::TextMode mode{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2664,7 +2664,7 @@ class TextStateResponse final : public StateResponseProtoMessage { #endif StringRef state{}; bool missing_state{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2698,7 +2698,7 @@ class ListEntitiesDateResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const LogString *message_name() const override { return LOG_STR("list_entities_date_response"); } #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2717,7 +2717,7 @@ class DateStateResponse final : public StateResponseProtoMessage { uint32_t year{0}; uint32_t month{0}; uint32_t day{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2752,7 +2752,7 @@ class ListEntitiesTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const LogString *message_name() const override { return LOG_STR("list_entities_time_response"); } #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2771,7 +2771,7 @@ class TimeStateResponse final : public StateResponseProtoMessage { uint32_t hour{0}; uint32_t minute{0}; uint32_t second{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2808,7 +2808,7 @@ class ListEntitiesEventResponse final : public InfoResponseProtoMessage { #endif StringRef device_class{}; const FixedVector<const char *> *event_types{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2824,7 +2824,7 @@ class EventResponse final : public StateResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("event_response"); } #endif StringRef event_type{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2845,7 +2845,7 @@ class ListEntitiesValveResponse final : public InfoResponseProtoMessage { bool assumed_state{false}; bool supports_position{false}; bool supports_stop{false}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2862,7 +2862,7 @@ class ValveStateResponse final : public StateResponseProtoMessage { #endif float position{0.0f}; enums::ValveOperation current_operation{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2897,7 +2897,7 @@ class ListEntitiesDateTimeResponse final : public InfoResponseProtoMessage { #ifdef HAS_PROTO_MESSAGE_DUMP const LogString *message_name() const override { return LOG_STR("list_entities_date_time_response"); } #endif - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2914,7 +2914,7 @@ class DateTimeStateResponse final : public StateResponseProtoMessage { #endif bool missing_state{false}; uint32_t epoch_seconds{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2948,7 +2948,7 @@ class ListEntitiesUpdateResponse final : public InfoResponseProtoMessage { const LogString *message_name() const override { return LOG_STR("list_entities_update_response"); } #endif StringRef device_class{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -2972,7 +2972,7 @@ class UpdateStateResponse final : public StateResponseProtoMessage { StringRef title{}; StringRef release_summary{}; StringRef release_url{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3007,7 +3007,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { #endif const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3026,7 +3026,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { enums::ZWaveProxyRequestType type{}; const uint8_t *data{nullptr}; uint16_t data_len{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3047,7 +3047,7 @@ class ListEntitiesInfraredResponse final : public InfoResponseProtoMessage { #endif uint32_t capabilities{0}; uint32_t receiver_frequency{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3094,7 +3094,7 @@ class InfraredRFReceiveEvent final : public ProtoMessage { #endif uint32_t key{0}; const std::vector<int32_t> *timings{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3138,7 +3138,7 @@ class SerialProxyDataReceived final : public ProtoMessage { this->data_ptr_ = data; this->data_len_ = len; } - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3204,7 +3204,7 @@ class SerialProxyGetModemPinsResponse final : public ProtoMessage { #endif uint32_t instance{0}; uint32_t line_states{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3239,7 +3239,7 @@ class SerialProxyRequestResponse final : public ProtoMessage { enums::SerialProxyRequestType type{}; enums::SerialProxyStatus status{}; StringRef error_message{}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; @@ -3277,7 +3277,7 @@ class BluetoothSetConnectionParamsResponse final : public ProtoMessage { #endif uint64_t address{0}; int32_t error{0}; - void encode(ProtoWriteBuffer &buffer) const; + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const; uint32_t calculate_size() const; #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index d9fe0fe461..236e4a474a 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -145,14 +145,15 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size // [tag][v1][v2][body ..... body] // ^-- pos_ = element end, within buffer void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const void *value, - void (*encode_fn)(const void *, ProtoWriteBuffer &)) { + uint8_t *(*encode_fn)(const void *, + ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM)) { this->encode_field_raw(field_id, 2); // Reserve 1 byte for length varint (optimistic: submessage < 128 bytes) uint8_t *len_pos = this->pos_; this->debug_check_bounds_(1); this->pos_++; uint8_t *body_start = this->pos_; - encode_fn(value, *this); + this->pos_ = encode_fn(value, *this PROTO_ENCODE_DEBUG_INIT(this->buffer_)); uint32_t body_size = static_cast<uint32_t>(this->pos_ - body_start); if (body_size < 128) [[likely]] { // Common case: 1-byte varint, just backpatch @@ -173,22 +174,27 @@ void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const void *value, // Non-template core for encode_optional_sub_message. void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value, - void (*encode_fn)(const void *, ProtoWriteBuffer &)) { + uint8_t *(*encode_fn)(const void *, + ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM)) { if (nested_size == 0) return; this->encode_field_raw(field_id, 2); this->encode_varint_raw(nested_size); #ifdef ESPHOME_DEBUG_API uint8_t *start = this->pos_; - encode_fn(value, *this); + this->pos_ = encode_fn(value, *this PROTO_ENCODE_DEBUG_INIT(this->buffer_)); if (static_cast<uint32_t>(this->pos_ - start) != nested_size) this->debug_check_encode_size_(field_id, nested_size, this->pos_ - start); #else - encode_fn(value, *this); + this->pos_ = encode_fn(value, *this PROTO_ENCODE_DEBUG_INIT(this->buffer_)); #endif } #ifdef ESPHOME_DEBUG_API +void proto_check_bounds_failed(const uint8_t *pos, size_t bytes, const uint8_t *end, const char *caller) { + ESP_LOGE(TAG, "Proto encode bounds check failed in %s: need %zu bytes, %td available", caller, bytes, end - pos); + abort(); +} void ProtoWriteBuffer::debug_check_bounds_(size_t bytes, const char *caller) { if (this->pos_ + bytes > this->buffer_->data() + this->buffer_->size()) { ESP_LOGE(TAG, "ProtoWriteBuffer bounds check failed in %s: bytes=%zu offset=%td buf_size=%zu", caller, bytes, @@ -201,6 +207,7 @@ void ProtoWriteBuffer::debug_check_encode_size_(uint32_t field_id, uint32_t expe expected, actual); abort(); } + #endif void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index b629018a91..902d4c0f5c 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -195,6 +195,26 @@ class Proto32Bit { // NOTE: Proto64Bit class removed - wire type 1 (64-bit fixed) not supported +// Debug bounds checking for proto encode functions. +// In debug mode (ESPHOME_DEBUG_API), an extra end-of-buffer pointer is threaded +// through the entire encode chain. In production, these expand to nothing. +#ifdef ESPHOME_DEBUG_API +#define PROTO_ENCODE_DEBUG_PARAM , uint8_t *proto_debug_end_ +#define PROTO_ENCODE_DEBUG_ARG , proto_debug_end_ +#define PROTO_ENCODE_DEBUG_INIT(buf) , (buf)->data() + (buf)->size() +#define PROTO_ENCODE_CHECK_BOUNDS(pos, n) \ + do { \ + if ((pos) + (n) > proto_debug_end_) \ + proto_check_bounds_failed(pos, n, proto_debug_end_, __builtin_FUNCTION()); \ + } while (0) +void proto_check_bounds_failed(const uint8_t *pos, size_t bytes, const uint8_t *end, const char *caller); +#else +#define PROTO_ENCODE_DEBUG_PARAM +#define PROTO_ENCODE_DEBUG_ARG +#define PROTO_ENCODE_DEBUG_INIT(buf) +#define PROTO_ENCODE_CHECK_BOUNDS(pos, n) +#endif + class ProtoWriteBuffer { public: ProtoWriteBuffer(APIBuffer *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} @@ -207,15 +227,6 @@ class ProtoWriteBuffer { } this->encode_varint_raw_slow_(value); } - void encode_varint_raw_64(uint64_t value) { - while (value > 0x7F) { - this->debug_check_bounds_(1); - *this->pos_++ = static_cast<uint8_t>(value | 0x80); - value >>= 7; - } - this->debug_check_bounds_(1); - *this->pos_++ = static_cast<uint8_t>(value); - } /** * Encode a field key (tag/wire type combination). * @@ -229,123 +240,6 @@ class ProtoWriteBuffer { * Following https://protobuf.dev/programming-guides/encoding/#structure */ void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); } - /// Write a single precomputed tag byte. Tag must be < 128. - inline void write_raw_byte(uint8_t b) ESPHOME_ALWAYS_INLINE { - this->debug_check_bounds_(1); - *this->pos_++ = b; - } - /// Write raw bytes to the buffer (no tag, no length prefix). - inline void encode_raw(const void *data, size_t len) ESPHOME_ALWAYS_INLINE { - this->debug_check_bounds_(len); - std::memcpy(this->pos_, data, len); - this->pos_ += len; - } - /// Write a precomputed tag byte + 32-bit value in one operation. - /// Tag must be a single-byte varint (< 128). No zero check. - inline void write_tag_and_fixed32(uint8_t tag, uint32_t value) ESPHOME_ALWAYS_INLINE { - this->debug_check_bounds_(5); - this->pos_[0] = tag; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::memcpy(this->pos_ + 1, &value, 4); -#else - this->pos_[1] = static_cast<uint8_t>(value & 0xFF); - this->pos_[2] = static_cast<uint8_t>((value >> 8) & 0xFF); - this->pos_[3] = static_cast<uint8_t>((value >> 16) & 0xFF); - this->pos_[4] = static_cast<uint8_t>((value >> 24) & 0xFF); -#endif - this->pos_ += 5; - } - void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { - if (len == 0 && !force) - return; - - this->encode_field_raw(field_id, 2); // type 2: Length-delimited string - this->encode_varint_raw(len); - // Direct memcpy into pre-sized buffer — avoids push_back() per-byte capacity checks - // and vector::insert() iterator overhead. ~10-11x faster for 16-32 byte strings. - this->debug_check_bounds_(len); - std::memcpy(this->pos_, string, len); - this->pos_ += len; - } - void encode_string(uint32_t field_id, const std::string &value, bool force = false) { - this->encode_string(field_id, value.data(), value.size(), force); - } - void encode_string(uint32_t field_id, const StringRef &ref, bool force = false) { - this->encode_string(field_id, ref.c_str(), ref.size(), force); - } - void encode_bytes(uint32_t field_id, const uint8_t *data, size_t len, bool force = false) { - this->encode_string(field_id, reinterpret_cast<const char *>(data), len, force); - } - void encode_uint32(uint32_t field_id, uint32_t value, bool force = false) { - if (value == 0 && !force) - return; - this->encode_field_raw(field_id, 0); // type 0: Varint - uint32 - this->encode_varint_raw(value); - } - void encode_uint64(uint32_t field_id, uint64_t value, bool force = false) { - if (value == 0 && !force) - return; - this->encode_field_raw(field_id, 0); // type 0: Varint - uint64 - this->encode_varint_raw_64(value); - } - void encode_bool(uint32_t field_id, bool value, bool force = false) { - if (!value && !force) - return; - this->encode_field_raw(field_id, 0); // type 0: Varint - bool - this->debug_check_bounds_(1); - *this->pos_++ = value ? 0x01 : 0x00; - } - void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) { - if (value == 0 && !force) - return; - - this->encode_field_raw(field_id, 5); // type 5: 32-bit fixed32 - this->debug_check_bounds_(4); -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - // Protobuf fixed32 is little-endian, so direct copy works - std::memcpy(this->pos_, &value, 4); - this->pos_ += 4; -#else - *this->pos_++ = (value >> 0) & 0xFF; - *this->pos_++ = (value >> 8) & 0xFF; - *this->pos_++ = (value >> 16) & 0xFF; - *this->pos_++ = (value >> 24) & 0xFF; -#endif - } - // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally - // not supported to reduce overhead on embedded systems. All ESPHome devices are - // 32-bit microcontrollers where 64-bit operations are expensive. If 64-bit support - // is needed in the future, the necessary encoding/decoding functions must be added. - void encode_float(uint32_t field_id, float value, bool force = false) { - if (value == 0.0f && !force) - return; - - union { - float value; - uint32_t raw; - } val{}; - val.value = value; - this->encode_fixed32(field_id, val.raw); - } - void encode_int32(uint32_t field_id, int32_t value, bool force = false) { - if (value < 0) { - // negative int32 is always 10 byte long - this->encode_int64(field_id, value, force); - return; - } - this->encode_uint32(field_id, static_cast<uint32_t>(value), force); - } - void encode_int64(uint32_t field_id, int64_t value, bool force = false) { - this->encode_uint64(field_id, static_cast<uint64_t>(value), force); - } - void encode_sint32(uint32_t field_id, int32_t value, bool force = false) { - this->encode_uint32(field_id, encode_zigzag32(value), force); - } - void encode_sint64(uint32_t field_id, int64_t value, bool force = false) { - this->encode_uint64(field_id, encode_zigzag64(value), force); - } - /// Encode a packed repeated sint32 field (zero-copy from vector) - void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values); /// Single-pass encode for repeated submessage elements. /// Thin template wrapper; all buffer work is in the non-template core. template<typename T> void encode_sub_message(uint32_t field_id, const T &value); @@ -353,12 +247,17 @@ class ProtoWriteBuffer { /// Thin template wrapper; all buffer work is in the non-template core. template<typename T> void encode_optional_sub_message(uint32_t field_id, const T &value); + // NOLINTBEGIN(readability-identifier-naming) // Non-template core for encode_sub_message — backpatch approach. - void encode_sub_message(uint32_t field_id, const void *value, void (*encode_fn)(const void *, ProtoWriteBuffer &)); + void encode_sub_message(uint32_t field_id, const void *value, + uint8_t *(*encode_fn)(const void *, ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM)); // Non-template core for encode_optional_sub_message. void encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value, - void (*encode_fn)(const void *, ProtoWriteBuffer &)); + uint8_t *(*encode_fn)(const void *, ProtoWriteBuffer &PROTO_ENCODE_DEBUG_PARAM)); + // NOLINTEND(readability-identifier-naming) APIBuffer *get_buffer() const { return buffer_; } + uint8_t *get_pos() const { return pos_; } + void set_pos(uint8_t *pos) { pos_ = pos; } protected: // Slow path for encode_varint_raw values >= 128, outlined to keep fast path small @@ -375,6 +274,211 @@ class ProtoWriteBuffer { uint8_t *pos_; }; +// Varint encoding thresholds — used by both proto_encode_* free functions and ProtoSize. +constexpr uint32_t VARINT_MAX_1_BYTE = 1 << 7; // 128 +constexpr uint32_t VARINT_MAX_2_BYTE = 1 << 14; // 16384 + +/// Static encode helpers for generated encode() functions. +/// Generated code hoists buffer.pos_ into a local uint8_t *__restrict__ pos, +/// then calls these methods which take pos by reference. No struct, no overhead. +/// For sub-messages, pos is synced back to buffer before the call and reloaded after. +class ProtoEncode { + public: + /// Write a multi-byte varint directly through a pos pointer. + template<typename T> + static inline void encode_varint_raw_loop(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, T value) { + do { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = static_cast<uint8_t>(value | 0x80); + value >>= 7; + } while (value > 0x7F); + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = static_cast<uint8_t>(value); + } + static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t value) { + if (value < VARINT_MAX_1_BYTE) [[likely]] { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = static_cast<uint8_t>(value); + return; + } + encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + } + /// Encode a varint that is expected to be 1-2 bytes (e.g. zigzag RSSI, small lengths). + static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_short(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t value) { + if (value < VARINT_MAX_1_BYTE) [[likely]] { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = static_cast<uint8_t>(value); + return; + } + if (value < VARINT_MAX_2_BYTE) [[likely]] { + PROTO_ENCODE_CHECK_BOUNDS(pos, 2); + *pos++ = static_cast<uint8_t>(value | 0x80); + *pos++ = static_cast<uint8_t>(value >> 7); + return; + } + encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + } + static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint64_t value) { + if (value < VARINT_MAX_1_BYTE) [[likely]] { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = static_cast<uint8_t>(value); + return; + } + encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + } + static inline void ESPHOME_ALWAYS_INLINE encode_field_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint32_t type) { + encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, (field_id << 3) | type); + } + /// Write a single precomputed tag byte. Tag must be < 128. + static inline void ESPHOME_ALWAYS_INLINE write_raw_byte(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint8_t b) { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = b; + } + /// Write raw bytes to the buffer (no tag, no length prefix). + static inline void ESPHOME_ALWAYS_INLINE encode_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + const void *data, size_t len) { + PROTO_ENCODE_CHECK_BOUNDS(pos, len); + std::memcpy(pos, data, len); + pos += len; + } + /// Write a precomputed tag byte + 32-bit value in one operation. + static inline void ESPHOME_ALWAYS_INLINE write_tag_and_fixed32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + uint8_t tag, uint32_t value) { + PROTO_ENCODE_CHECK_BOUNDS(pos, 5); + pos[0] = tag; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::memcpy(pos + 1, &value, 4); +#else + pos[1] = static_cast<uint8_t>(value & 0xFF); + pos[2] = static_cast<uint8_t>((value >> 8) & 0xFF); + pos[3] = static_cast<uint8_t>((value >> 16) & 0xFF); + pos[4] = static_cast<uint8_t>((value >> 24) & 0xFF); +#endif + pos += 5; + } + static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + const char *string, size_t len, bool force = false) { + if (len == 0 && !force) + return; + encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 2); // type 2: Length-delimited string + if (len < VARINT_MAX_1_BYTE) [[likely]] { + PROTO_ENCODE_CHECK_BOUNDS(pos, 1 + len); + *pos++ = static_cast<uint8_t>(len); + } else { + encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, len); + PROTO_ENCODE_CHECK_BOUNDS(pos, len); + } + std::memcpy(pos, string, len); + pos += len; + } + static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + const std::string &value, bool force = false) { + encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, value.data(), value.size(), force); + } + static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + const StringRef &ref, bool force = false) { + encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.c_str(), ref.size(), force); + } + static inline void encode_bytes(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + const uint8_t *data, size_t len, bool force = false) { + encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, reinterpret_cast<const char *>(data), len, force); + } + static inline void encode_uint32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + uint32_t value, bool force = false) { + if (value == 0 && !force) + return; + encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, value); + } + static inline void encode_uint64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + uint64_t value, bool force = false) { + if (value == 0 && !force) + return; + encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, value); + } + static inline void encode_bool(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, bool value, + bool force = false) { + if (!value && !force) + return; + encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + PROTO_ENCODE_CHECK_BOUNDS(pos, 1); + *pos++ = value ? 0x01 : 0x00; + } + static inline void encode_fixed32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + uint32_t value, bool force = false) { + if (value == 0 && !force) + return; + encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 5); + PROTO_ENCODE_CHECK_BOUNDS(pos, 4); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + std::memcpy(pos, &value, 4); + pos += 4; +#else + *pos++ = (value >> 0) & 0xFF; + *pos++ = (value >> 8) & 0xFF; + *pos++ = (value >> 16) & 0xFF; + *pos++ = (value >> 24) & 0xFF; +#endif + } + // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally + // not supported to reduce overhead on embedded systems. All ESPHome devices are + // 32-bit microcontrollers where 64-bit operations are expensive. If 64-bit support + // is needed in the future, the necessary encoding/decoding functions must be added. + static inline void encode_float(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, float value, + bool force = false) { + if (value == 0.0f && !force) + return; + union { + float value; + uint32_t raw; + } val{}; + val.value = value; + encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, field_id, val.raw); + } + static inline void encode_int32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, int32_t value, + bool force = false) { + if (value < 0) { + // negative int32 is always 10 byte long + encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast<uint64_t>(value), force); + return; + } + encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast<uint32_t>(value), force); + } + static inline void encode_int64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, int64_t value, + bool force = false) { + encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast<uint64_t>(value), force); + } + static inline void encode_sint32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + int32_t value, bool force = false) { + encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag32(value), force); + } + static inline void encode_sint64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, + int64_t value, bool force = false) { + encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag64(value), force); + } + /// Sub-message encoding: sync pos to buffer, delegate, get pos from return value. + template<typename T> + static inline void encode_sub_message(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, ProtoWriteBuffer &buffer, + uint32_t field_id, const T &value) { + buffer.set_pos(pos); + buffer.encode_sub_message(field_id, value); + pos = buffer.get_pos(); + } + template<typename T> + static inline void encode_optional_sub_message(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, + ProtoWriteBuffer &buffer, uint32_t field_id, const T &value) { + buffer.set_pos(pos); + buffer.encode_optional_sub_message(field_id, value); + pos = buffer.get_pos(); + } +}; + #ifdef HAS_PROTO_MESSAGE_DUMP /** * Fixed-size buffer for message dumps - avoids heap allocation. @@ -470,7 +574,7 @@ class ProtoMessage { // All call sites use templates to preserve the concrete type, so virtual // dispatch is not needed. This eliminates per-message vtable entries for // encode/calculate_size, saving ~1.3 KB of flash across all message types. - void encode(ProtoWriteBuffer &buffer) const {} + uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { return buffer.get_pos(); } uint32_t calculate_size() const { return 0; } #ifdef HAS_PROTO_MESSAGE_DUMP virtual const char *dump_to(DumpBuffer &out) const = 0; @@ -512,9 +616,10 @@ class ProtoDecodableMessage : public ProtoMessage { class ProtoSize { public: - // Varint encoding thresholds: values below each threshold fit in N bytes - static constexpr uint32_t VARINT_THRESHOLD_1_BYTE = 1 << 7; // 128 - static constexpr uint32_t VARINT_THRESHOLD_2_BYTE = 1 << 14; // 16384 + // Varint encoding thresholds — use namespace-level constants for 1/2 byte, + // class-level for 3/4 byte (only used within ProtoSize). + static constexpr uint32_t VARINT_THRESHOLD_1_BYTE = VARINT_MAX_1_BYTE; + static constexpr uint32_t VARINT_THRESHOLD_2_BYTE = VARINT_MAX_2_BYTE; static constexpr uint32_t VARINT_THRESHOLD_3_BYTE = 1 << 21; // 2097152 static constexpr uint32_t VARINT_THRESHOLD_4_BYTE = 1 << 28; // 268435456 @@ -531,6 +636,17 @@ class ProtoSize { return varint_wide(value); return varint_slow(value); } + /// Size of a varint expected to be 1-2 bytes (e.g. zigzag RSSI, small lengths). + /// Inlines both checks; falls back to slow path for 3+ bytes. + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint_short(uint32_t value) { + if (value < VARINT_THRESHOLD_1_BYTE) [[likely]] + return 1; + if (value < VARINT_THRESHOLD_2_BYTE) [[likely]] + return 2; + if (__builtin_is_constant_evaluated()) + return varint_wide(value); + return varint_slow(value); + } private: // Slow path for varint >= 128, outlined to keep fast path small @@ -645,10 +761,10 @@ class ProtoSize { return value ? field_id_size + 4 : 0; } static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value) { - return value ? field_id_size + varint(encode_zigzag32(value)) : 0; + return value ? field_id_size + varint_short(encode_zigzag32(value)) : 0; } static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE calc_sint32_force(uint32_t field_id_size, int32_t value) { - return field_id_size + varint(encode_zigzag32(value)); + return field_id_size + varint_short(encode_zigzag32(value)); } static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value) { return value ? field_id_size + varint(value) : 0; @@ -691,28 +807,9 @@ class ProtoSize { // Implementation of methods that depend on ProtoSize being fully defined -// Implementation of encode_packed_sint32 - must be after ProtoSize is defined -inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) { - if (values.empty()) - return; - - // Calculate packed size - size_t packed_size = 0; - for (int value : values) { - packed_size += ProtoSize::varint(encode_zigzag32(value)); - } - - // Write tag (LENGTH_DELIMITED) + length + all zigzag-encoded values - this->encode_field_raw(field_id, WIRE_TYPE_LENGTH_DELIMITED); - this->encode_varint_raw(packed_size); - for (int value : values) { - this->encode_varint_raw(encode_zigzag32(value)); - } -} - // Encode thunk — converts void* back to concrete type for direct encode() call -template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &buf) { - static_cast<const T *>(msg)->encode(buf); +template<typename T> uint8_t *proto_encode_msg(const void *msg, ProtoWriteBuffer &buf PROTO_ENCODE_DEBUG_PARAM) { + return static_cast<const T *>(msg)->encode(buf PROTO_ENCODE_DEBUG_ARG); } // Thin template wrapper; delegates to non-template core in proto.cpp. diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index c17f16412c..3833f279ce 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -232,29 +232,31 @@ class TypeInfo(ABC): # eliminating the zero-check branch and encode_field_raw indirection. # {value} is replaced with the actual field expression. RAW_ENCODE_MAP: dict[str, str] = { - "encode_uint32": "buffer.encode_varint_raw({value});", - "encode_uint64": "buffer.encode_varint_raw_64({value});", - "encode_sint32": "buffer.encode_varint_raw(encode_zigzag32({value}));", - "encode_sint64": "buffer.encode_varint_raw_64(encode_zigzag64({value}));", - "encode_int64": "buffer.encode_varint_raw_64(static_cast<uint64_t>({value}));", - "encode_bool": "buffer.write_raw_byte({value} ? 0x01 : 0x00);", + "encode_uint32": "ProtoEncode::encode_varint_raw(pos, {value});", + "encode_uint64": "ProtoEncode::encode_varint_raw_64(pos, {value});", + "encode_sint32": "ProtoEncode::encode_varint_raw_short(pos, encode_zigzag32({value}));", + "encode_sint64": "ProtoEncode::encode_varint_raw_64(pos, encode_zigzag64({value}));", + "encode_int64": "ProtoEncode::encode_varint_raw_64(pos, static_cast<uint64_t>({value}));", + "encode_bool": "ProtoEncode::write_raw_byte(pos, {value} ? 0x01 : 0x00);", } # When max_value < 128, the varint is always 1 byte — use a direct byte write RAW_ENCODE_SMALL_MAP: dict[str, str] = { - "encode_uint32": "buffer.write_raw_byte(static_cast<uint8_t>({value}));", - "encode_uint64": "buffer.write_raw_byte(static_cast<uint8_t>({value}));", + "encode_uint32": "ProtoEncode::write_raw_byte(pos, static_cast<uint8_t>({value}));", + "encode_uint64": "ProtoEncode::write_raw_byte(pos, static_cast<uint8_t>({value}));", } def _encode_with_precomputed_tag(self, value_expr: str) -> str | None: - """Try to emit a precomputed-tag encode for a forced field. + """Try to emit a precomputed-tag encode for a field. + + For forced fields: emits raw tag + value unconditionally. + For non-forced fields with single-byte tag: emits inline zero-check + + raw tag + value, avoiding an outlined function call. Returns the raw encode string if the tag is a single byte and the encode_func has a known raw equivalent, or None otherwise. When max_value < 128, uses direct byte write instead of varint encoding. """ - if not self.force: - return None tag = self.calculate_tag() if tag >= 128: return None @@ -263,10 +265,17 @@ class TypeInfo(ABC): if max_val is not None and max_val < 128: raw_expr = self.RAW_ENCODE_SMALL_MAP.get(self.encode_func) if raw_expr is None: + # Only use RAW_ENCODE_MAP for forced fields or fields with max_value + if not self.force and max_val is None: + return None raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) if raw_expr is None: return None - return f"buffer.write_raw_byte({tag});\n{raw_expr.format(value=value_expr)}" + body = f"ProtoEncode::write_raw_byte(pos, {tag});\n{raw_expr.format(value=value_expr)}" + if self.force: + return body + # Non-forced with max_value: inline zero-check + raw encode + return f"if ({value_expr}) {{\n {body}\n}}" def _encode_bytes_with_precomputed_tag( self, data_expr: str, len_expr: str, max_len: int | None = None @@ -283,14 +292,14 @@ class TypeInfo(ABC): return None # When max_len < 128, length varint is always 1 byte len_encode = ( - f"buffer.write_raw_byte(static_cast<uint8_t>({len_expr}));" + f"ProtoEncode::write_raw_byte(pos, static_cast<uint8_t>({len_expr}));" if max_len is not None and max_len < 128 - else f"buffer.encode_varint_raw({len_expr});" + else f"ProtoEncode::encode_varint_raw(pos, {len_expr});" ) return ( - f"buffer.write_raw_byte({tag});\n" + f"ProtoEncode::write_raw_byte(pos, {tag});\n" f"{len_encode}\n" - f"buffer.encode_raw({data_expr}, {len_expr});" + f"ProtoEncode::encode_raw(pos, {data_expr}, {len_expr});" ) @property @@ -298,8 +307,8 @@ class TypeInfo(ABC): if result := self._encode_with_precomputed_tag(f"this->{self.field_name}"): return result if self.force: - return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);" - return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name}, true);" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name});" encode_func = None @@ -657,10 +666,10 @@ class Fixed32Type(TypeInfo): tag = self.calculate_tag() if self.force and tag < 128: # Emit combined tag+value write: precomputed tag + direct memcpy - return f"buffer.write_tag_and_fixed32({tag}, this->{self.field_name});" + return f"ProtoEncode::write_tag_and_fixed32(pos, {tag}, this->{self.field_name});" if self.force: - return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);" - return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name}, true);" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name});" def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() @@ -734,8 +743,8 @@ class StringType(TypeInfo): ): return result if self.force: - return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_, true);" - return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);" + return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}_ref_, true);" + return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}_ref_);" def dump(self, name): # If name is 'it', this is a repeated field element - always use string @@ -822,8 +831,8 @@ class MessageType(TypeInfo): @property def encode_content(self) -> str: - # encode_sub_message always encodes (uses backpatch), no force needed - return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" + # Sub-message encoding needs buffer for backpatch/sync + return f"ProtoEncode::{self.encode_func}(pos, buffer, {self.number}, this->{self.field_name});" @property def decode_length(self) -> str: @@ -904,8 +913,8 @@ class BytesType(TypeInfo): ): return result if self.force: - return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);" - return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" def dump(self, name: str) -> str: ptr_dump = f"format_hex_pretty(this->{self.field_name}_ptr_, this->{self.field_name}_len_)" @@ -1015,8 +1024,8 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): ): return result if self.force: - return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" - return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len);" @property def decode_length_content(self) -> str | None: @@ -1068,10 +1077,10 @@ class PointerToStringBufferType(PointerToBufferTypeBase): ): return result if self.force: - return ( - f"buffer.encode_string({self.number}, this->{self.field_name}, true);" - ) - return f"buffer.encode_string({self.number}, this->{self.field_name});" + return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}, true);" + return ( + f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name});" + ) @property def decode_length_content(self) -> str | None: @@ -1240,8 +1249,8 @@ class FixedArrayBytesType(TypeInfo): ): return result if self.force: - return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" - return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" + return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len);" def dump(self, name: str) -> str: return f"out.append(format_hex_pretty({name}, {name}_len));" @@ -1323,8 +1332,8 @@ class EnumType(TypeInfo): ): return result if self.force: - return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}), true);" - return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}));" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, static_cast<uint32_t>(this->{self.field_name}), true);" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, static_cast<uint32_t>(this->{self.field_name}));" def dump(self, name: str) -> str: return f"out.append_p(proto_enum_to_string<{self.cpp_type}>({name}));" @@ -1487,11 +1496,13 @@ class FixedArrayRepeatedType(TypeInfo): def _encode_element(self, element: str) -> str: """Helper to generate encode statement for a single element.""" if isinstance(self._ti, EnumType): - return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);" + return f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, static_cast<uint32_t>({element}), true);" # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): - return f"buffer.encode_sub_message({self.number}, {element});" - return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);" + return f"ProtoEncode::encode_sub_message(pos, buffer, {self.number}, {element});" + return ( + f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, {element}, true);" + ) @property def cpp_type(self) -> str: @@ -1815,11 +1826,13 @@ class RepeatedTypeInfo(TypeInfo): def _encode_element_call(self, element: str) -> str: """Helper to generate encode call for a single element.""" if isinstance(self._ti, EnumType): - return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);" + return f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, static_cast<uint32_t>({element}), true);" # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): - return f"buffer.encode_sub_message({self.number}, {element});" - return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);" + return f"ProtoEncode::encode_sub_message(pos, buffer, {self.number}, {element});" + return ( + f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, {element}, true);" + ) @property def encode_content(self) -> str: @@ -1828,7 +1841,7 @@ class RepeatedTypeInfo(TypeInfo): # Special handling for const char* elements (when container_no_template contains "const char") if "const char" in self._container_no_template: o = f"for (const char *it : *this->{self.field_name}) {{\n" - o += f" buffer.{self._ti.encode_func}({self.number}, it, strlen(it), true);\n" + o += f" ProtoEncode::{self._ti.encode_func}(pos, {self.number}, it, strlen(it), true);\n" else: o = f"for (const auto &it : *this->{self.field_name}) {{\n" o += f" {self._encode_element_call('it')}\n" @@ -2403,15 +2416,19 @@ def build_message_type( # Only generate encode method if this message needs encoding and has fields if needs_encode and encode: - o = f"void {desc.name}::encode(ProtoWriteBuffer &buffer) const {{" - if len(encode) == 1 and len(encode[0]) + len(o) + 3 < 120: - o += f" {encode[0]} }}\n" - else: - o += "\n" - o += indent("\n".join(encode)) + "\n" - o += "}\n" + # Add PROTO_ENCODE_DEBUG_ARG after pos in all proto_* calls + encode_debug = [ + line.replace("(pos,", "(pos PROTO_ENCODE_DEBUG_ARG,") for line in encode + ] + o = f"uint8_t *{desc.name}::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {{\n" + o += " uint8_t *__restrict__ pos = buffer.get_pos();\n" + o += indent("\n".join(encode_debug)) + "\n" + o += " return pos;\n" + o += "}\n" cpp += o - prot = "void encode(ProtoWriteBuffer &buffer) const;" + prot = ( + "uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const;" + ) public_content.append(prot) # If no fields to encode or message doesn't need encoding, the default implementation in ProtoMessage will be used From ce0d36079064fe6d228d29fb01e4693e62c1e9f1 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 7 Apr 2026 08:46:42 +1000 Subject: [PATCH 1974/2030] [lvgl] Implement rotation directly (#14955) --- esphome/components/lvgl/__init__.py | 26 +++- esphome/components/lvgl/automation.py | 31 ++++- esphome/components/lvgl/defines.py | 5 + esphome/components/lvgl/lvgl_esphome.cpp | 154 ++++++++++++++++------- esphome/components/lvgl/lvgl_esphome.h | 14 ++- esphome/components/lvgl/types.py | 1 + tests/components/lvgl/lvgl-package.yaml | 11 +- 7 files changed, 189 insertions(+), 53 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index a9d31d42d8..b429e1e322 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -9,7 +9,7 @@ from esphome.components.const import ( CONF_COLOR_DEPTH, CONF_DRAW_ROUNDING, ) -from esphome.components.display import Display +from esphome.components.display import Display, get_display_metadata, validate_rotation from esphome.components.esp32 import ( VARIANT_ESP32P4, add_idf_component, @@ -37,6 +37,7 @@ from esphome.const import ( CONF_ON_BOOT, CONF_ON_IDLE, CONF_PAGES, + CONF_ROTATION, CONF_TIMEOUT, CONF_TRIGGER_ID, ) @@ -74,6 +75,7 @@ from .trigger import add_on_boot_triggers, generate_align_tos, generate_triggers from .types import ( IdleTrigger, PlainTrigger, + RotationType, lv_font_t, lv_group_t, lv_lambda_t, @@ -185,6 +187,7 @@ def final_validation(config_list): for config in config_list: if (pages := config.get(CONF_PAGES)) and all(p[df.CONF_SKIP] for p in pages): raise cv.Invalid("At least one page must not be skipped") + uses_rotation = CONF_ROTATION in config for display_id in config[df.CONF_DISPLAYS]: path = global_config.get_path_for_id(display_id)[:-1] display = global_config.get_config_for_path(path) @@ -192,6 +195,11 @@ def final_validation(config_list): raise cv.Invalid( "Using lambda: or pages: in display config is not compatible with LVGL" ) + # treating 0 as false is intended here. + if uses_rotation and display.get(CONF_ROTATION): + df.LOGGER.warning( + "use of 'rotation' in both LVGL and the display config is not recommended" + ) if display.get(CONF_AUTO_CLEAR_ENABLED) is True: raise cv.Invalid( "Using auto_clear_enabled: true in display config not compatible with LVGL" @@ -322,6 +330,18 @@ async def to_code(configs): displays = [ await cg.get_variable(display) for display in config[df.CONF_DISPLAYS] ] + rotation_type = RotationType.ROTATION_UNUSED + # options will have CONF_ROTATION true if rotation is changed in an automation. + if CONF_ROTATION in config or df.get_options().get(CONF_ROTATION) is True: + if all( + get_display_metadata(str(disp)).has_hardware_rotation + for disp in displays + ): + rotation_type = RotationType.ROTATION_HARDWARE + df.LOGGER.info("LVGL will use hardware rotation via display driver") + else: + rotation_type = RotationType.ROTATION_SOFTWARE + df.LOGGER.info("LVGL will use software rotation") lv_component = cg.new_Pvariable( config[CONF_ID], displays, @@ -330,8 +350,11 @@ async def to_code(configs): config[CONF_DRAW_ROUNDING], config[df.CONF_RESUME_ON_INPUT], config[df.CONF_UPDATE_WHEN_DISPLAY_IDLE], + rotation_type, ) await cg.register_component(lv_component, config) + if rotation := config.get(CONF_ROTATION): + cg.add(lv_component.set_rotation(rotation)) Widget.create(config[CONF_ID], lv_component, LvScrActType(), config) lv_scr_act = get_screen_active(lv_component) @@ -492,6 +515,7 @@ LVGL_SCHEMA = cv.All( ): cv.boolean, cv.Optional(CONF_DRAW_ROUNDING, default=2): cv.positive_int, cv.Optional(CONF_BUFFER_SIZE, default=0): cv.percentage, + cv.Optional(CONF_ROTATION): validate_rotation, cv.Optional(CONF_LOG_LEVEL, default="WARN"): cv.one_of( *df.LV_LOG_LEVELS, upper=True ), diff --git a/esphome/components/lvgl/automation.py b/esphome/components/lvgl/automation.py index 50e6db74b8..b825320a40 100644 --- a/esphome/components/lvgl/automation.py +++ b/esphome/components/lvgl/automation.py @@ -3,8 +3,9 @@ from typing import Any from esphome import automation import esphome.codegen as cg +from esphome.components.display import validate_rotation import esphome.config_validation as cv -from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_TIMEOUT +from esphome.const import CONF_ACTION, CONF_GROUP, CONF_ID, CONF_ROTATION, CONF_TIMEOUT from esphome.core import Lambda from esphome.cpp_generator import TemplateArguments, get_variable from esphome.cpp_types import nullptr @@ -23,6 +24,7 @@ from .defines import ( PARTS, StaticCastExpression, add_warning, + get_options, ) from .lv_validation import lv_bool, lv_milliseconds from .lvcode import ( @@ -191,6 +193,33 @@ async def lvgl_is_idle(config, condition_id, template_arg, args): return var +def _validate_rotation(value): + # Note that we need rotation + get_options()[CONF_ROTATION] = True + return validate_rotation(value) + + +@automation.register_action( + "lvgl.display.set_rotation", + ObjUpdateAction, + cv.maybe_simple_value( + LVGL_SCHEMA.extend( + { + cv.Required(CONF_ROTATION): _validate_rotation, + } + ), + key=CONF_ROTATION, + ), + synchronous=True, +) +async def lvgl_set_rotation(config, action_id, template_arg, args): + lv_comp = await cg.get_variable(config[CONF_LVGL_ID]) + async with LambdaContext() as context: + add_line_marks(where=action_id) + lv_add(lv_comp.set_rotation(config[CONF_ROTATION])) + return cg.new_Pvariable(action_id, template_arg, await context.get_lambda()) + + @automation.register_action( "lvgl.widget.redraw", ObjUpdateAction, diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index 668bb46515..ae8387bcca 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -29,6 +29,7 @@ KEY_COLOR_FORMATS = "color_formats" KEY_LV_DEFINES = "lv_defines" KEY_REMAPPED_USES = "remapped_uses" KEY_UPDATED_WIDGETS = "updated_widgets" +KEY_OPTIONS = "options" KEY_WARNINGS = "warnings" @@ -56,6 +57,10 @@ def add_warning(msg: str): get_warnings().add(msg) +def get_options(): + return get_data(KEY_OPTIONS) + + class StaticCastExpression(Expression): __slots__ = ("type", "exp") diff --git a/esphome/components/lvgl/lvgl_esphome.cpp b/esphome/components/lvgl/lvgl_esphome.cpp index a5075cb614..0ab49d0a10 100644 --- a/esphome/components/lvgl/lvgl_esphome.cpp +++ b/esphome/components/lvgl/lvgl_esphome.cpp @@ -83,6 +83,44 @@ std::string lv_event_code_name_for(lv_event_t *event) { return buf; } +void LvglComponent::set_rotation(display::DisplayRotation rotation) { + if (this->rotation_type_ == RotationType::ROTATION_UNUSED) { + ESP_LOGW(TAG, "Display rotation cannot be changed unless rotation was enabled during setup."); + return; + } + this->rotation_ = rotation; + if (this->is_ready()) { + this->set_resolution_(); + lv_obj_update_layout(this->get_screen_active()); + lv_obj_invalidate(this->get_screen_active()); + } +} + +void LvglComponent::rotate_coordinates(int32_t &x, int32_t &y) const { + switch (this->rotation_) { + default: + break; + + case display::DISPLAY_ROTATION_180_DEGREES: { + x = this->width_ - x - 1; + y = this->height_ - y - 1; + break; + } + case display::DISPLAY_ROTATION_270_DEGREES: { + auto tmp = x; + x = this->height_ - y - 1; + y = tmp; + break; + } + case display::DISPLAY_ROTATION_90_DEGREES: { + auto tmp = y; + y = this->width_ - x - 1; + x = tmp; + break; + } + } +} + static void rounder_cb(lv_event_t *event) { auto *comp = static_cast<LvglComponent *>(lv_event_get_user_data(event)); auto *area = static_cast<lv_area_t *>(lv_event_get_param(event)); @@ -118,7 +156,11 @@ void LvglComponent::dump_config() { " Buffer size: %zu%%\n" " Rotation: %d\n" " Draw rounding: %d", - this->width_, this->height_, 100 / this->buffer_frac_, this->rotation, (int) this->draw_rounding); + this->width_, this->height_, 100 / this->buffer_frac_, this->rotation_, (int) this->draw_rounding); + if (this->rotation_type_ != ROTATION_UNUSED) { + ESP_LOGCONFIG(TAG, " Rotation type: %s", + this->rotation_type_ == RotationType::ROTATION_SOFTWARE ? "software" : "hardware via display driver"); + } } void LvglComponent::set_paused(bool paused, bool show_snow) { @@ -216,48 +258,51 @@ void LvglComponent::draw_buffer_(const lv_area_t *area, lv_color_data *ptr) { auto height_rounded = (height + this->draw_rounding - 1) / this->draw_rounding * this->draw_rounding; auto x1 = area->x1; auto y1 = area->y1; - lv_color_data *dst = reinterpret_cast<lv_color_data *>(this->rotate_buf_); - switch (this->rotation) { - case display::DISPLAY_ROTATION_90_DEGREES: - for (lv_coord_t x = height; x-- != 0;) { - for (lv_coord_t y = 0; y != width; y++) { - dst[y * height_rounded + x] = *ptr++; + if (this->rotation_type_ == RotationType::ROTATION_SOFTWARE) { + lv_color_data *dst = reinterpret_cast<lv_color_data *>(this->rotate_buf_); + switch (this->rotation_) { + case display::DISPLAY_ROTATION_90_DEGREES: + for (lv_coord_t x = height; x-- != 0;) { + for (lv_coord_t y = 0; y != width; y++) { + dst[y * height_rounded + x] = *ptr++; + } } - } - y1 = x1; - x1 = this->height_ - area->y1 - height; - height = width; - width = height_rounded; - break; + y1 = x1; + x1 = this->width_ - area->y1 - height; + height = width; + width = height_rounded; + break; - case display::DISPLAY_ROTATION_180_DEGREES: - for (lv_coord_t y = height; y-- != 0;) { - for (lv_coord_t x = width; x-- != 0;) { - dst[y * width + x] = *ptr++; + case display::DISPLAY_ROTATION_180_DEGREES: + for (lv_coord_t y = height; y-- != 0;) { + for (lv_coord_t x = width; x-- != 0;) { + dst[y * width + x] = *ptr++; + } } - } - x1 = this->width_ - x1 - width; - y1 = this->height_ - y1 - height; - break; + x1 = this->width_ - x1 - width; + y1 = this->height_ - y1 - height; + break; - case display::DISPLAY_ROTATION_270_DEGREES: - for (lv_coord_t x = 0; x != height; x++) { - for (lv_coord_t y = width; y-- != 0;) { - dst[y * height_rounded + x] = *ptr++; + case display::DISPLAY_ROTATION_270_DEGREES: + for (lv_coord_t x = 0; x != height; x++) { + for (lv_coord_t y = width; y-- != 0;) { + dst[y * height_rounded + x] = *ptr++; + } } - } - x1 = y1; - y1 = this->width_ - area->x1 - width; - height = width; - width = height_rounded; - break; + x1 = y1; + y1 = this->height_ - area->x1 - width; + height = width; + width = height_rounded; + break; - default: - dst = ptr; - break; + default: + dst = ptr; + break; + } + ptr = dst; } for (auto *display : this->displays_) { - display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) dst, display::COLOR_ORDER_RGB, LV_BITNESS, + display->draw_pixels_at(x1, y1, width, height, (const uint8_t *) ptr, display::COLOR_ORDER_RGB, LV_BITNESS, this->big_endian_); } } @@ -297,6 +342,7 @@ LVTouchListener::LVTouchListener(uint16_t long_press_time, uint16_t long_press_r if (l->touch_pressed_) { data->point.x = l->touch_point_.x; data->point.y = l->touch_point_.y; + l->parent_->rotate_coordinates(data->point.x, data->point.y); data->state = LV_INDEV_STATE_PRESSED; } else { data->state = LV_INDEV_STATE_RELEASED; @@ -543,26 +589,44 @@ void LvglComponent::write_random_() { * multiple of 2, and so on. * @param resume_on_input if true, this component will resume rendering when the user * presses a key or clicks on the screen. + * @param rotation_type What rotation type to use, if any */ LvglComponent::LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh, - int draw_rounding, bool resume_on_input, bool update_when_display_idle) + int draw_rounding, bool resume_on_input, bool update_when_display_idle, + RotationType rotation_type) : draw_rounding(draw_rounding), displays_(std::move(displays)), buffer_frac_(buffer_frac), full_refresh_(full_refresh), resume_on_input_(resume_on_input), - update_when_display_idle_(update_when_display_idle) { + update_when_display_idle_(update_when_display_idle), + rotation_type_(rotation_type) { this->disp_ = lv_display_create(240, 240); } +void LvglComponent::set_resolution_() const { + int32_t width = this->width_; + int32_t height = this->height_; + if (this->rotation_ == display::DISPLAY_ROTATION_90_DEGREES || + this->rotation_ == display::DISPLAY_ROTATION_270_DEGREES) { + std::swap(width, height); + } + ESP_LOGD(TAG, "Setting resolution to %u x %u (rotation %d)", (unsigned) width, (unsigned) height, + (int) this->rotation_); + if (this->rotation_type_ == RotationType::ROTATION_HARDWARE) { + for (auto *display : this->displays_) + display->set_rotation(this->rotation_); + } + lv_display_set_resolution(this->disp_, width, height); +} void LvglComponent::setup() { auto *display = this->displays_[0]; auto rounding = this->draw_rounding; + this->width_ = display->get_native_width(); + this->height_ = display->get_native_height(); // cater for displays with dimensions that don't divide by the required rounding - this->width_ = display->get_width(); - this->height_ = display->get_height(); - auto width = (display->get_width() + rounding - 1) / rounding * rounding; - auto height = (display->get_height() + rounding - 1) / rounding * rounding; + auto width = (this->width_ + rounding - 1) / rounding * rounding; + auto height = (this->height_ + rounding - 1) / rounding * rounding; auto frac = this->buffer_frac_; if (frac == 0) frac = 1; @@ -586,15 +650,14 @@ void LvglComponent::setup() { return; } this->draw_buf_ = static_cast<uint8_t *>(buffer); - lv_display_set_resolution(this->disp_, this->width_, this->height_); + this->set_resolution_(); lv_display_set_color_format(this->disp_, LV_COLOR_FORMAT_RGB565); lv_display_set_flush_cb(this->disp_, static_flush_cb); lv_display_set_user_data(this->disp_, this); lv_display_add_event_cb(this->disp_, rounder_cb, LV_EVENT_INVALIDATE_AREA, this); lv_display_set_buffers(this->disp_, this->draw_buf_, nullptr, buf_bytes, this->full_refresh_ ? LV_DISPLAY_RENDER_MODE_FULL : LV_DISPLAY_RENDER_MODE_PARTIAL); - this->rotation = display->get_rotation(); - if (this->rotation != display::DISPLAY_ROTATION_0_DEGREES) { + if (this->rotation_type_ == RotationType::ROTATION_SOFTWARE) { this->rotate_buf_ = static_cast<lv_color_t *>(lv_alloc_draw_buf(buf_bytes, false)); // NOLINT if (this->rotate_buf_ == nullptr) { this->status_set_error(LOG_STR("Memory allocation failure")); @@ -620,9 +683,6 @@ void LvglComponent::setup() { esp_log_printf_(LOG_LEVEL_MAP[level], TAG, 0, "%.*s", (int) strlen(buf) - 1, buf); }); #endif - // Rotation will be handled by our drawing function, so reset the display rotation. - for (auto *disp : this->displays_) - disp->set_rotation(display::DISPLAY_ROTATION_0_DEGREES); this->show_page(0, LV_SCREEN_LOAD_ANIM_NONE, 0); lv_display_trigger_activity(this->disp_); } diff --git a/esphome/components/lvgl/lvgl_esphome.h b/esphome/components/lvgl/lvgl_esphome.h index 8d139b23cb..4a4c11d383 100644 --- a/esphome/components/lvgl/lvgl_esphome.h +++ b/esphome/components/lvgl/lvgl_esphome.h @@ -156,13 +156,18 @@ template<typename... Ts> class ObjUpdateAction : public Action<Ts...> { #ifdef USE_LVGL_ANIMIMG void lv_animimg_stop(lv_obj_t *obj); #endif // USE_LVGL_ANIMIMG +enum RotationType : uint8_t { + ROTATION_UNUSED, + ROTATION_SOFTWARE, + ROTATION_HARDWARE, +}; class LvglComponent : public PollingComponent { constexpr static const char *const TAG = "lvgl"; public: LvglComponent(std::vector<display::Display *> displays, float buffer_frac, bool full_refresh, int draw_rounding, - bool resume_on_input, bool update_when_display_idle); + bool resume_on_input, bool update_when_display_idle, RotationType rotation_type); static void static_flush_cb(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *color_p); float get_setup_priority() const override { return setup_priority::PROCESSOR; } @@ -216,13 +221,16 @@ class LvglComponent : public PollingComponent { // rounding factor to align bounds of update area when drawing size_t draw_rounding{2}; - display::DisplayRotation rotation{display::DISPLAY_ROTATION_0_DEGREES}; void set_pause_trigger(Trigger<> *trigger) { this->pause_callback_ = trigger; } void set_resume_trigger(Trigger<> *trigger) { this->resume_callback_ = trigger; } void set_draw_start_trigger(Trigger<> *trigger) { this->draw_start_callback_ = trigger; } void set_draw_end_trigger(Trigger<> *trigger) { this->draw_end_callback_ = trigger; } + void set_rotation(display::DisplayRotation rotation); + display::DisplayRotation get_rotation() const { return this->rotation_; } + void rotate_coordinates(int32_t &x, int32_t &y) const; protected: + void set_resolution_() const; void draw_end_(); // Not checking for non-null callback since the // LVGL callback that calls it is not set in that case @@ -256,6 +264,8 @@ class LvglComponent : public PollingComponent { Trigger<> *draw_start_callback_{}; Trigger<> *draw_end_callback_{}; void *rotate_buf_{}; + display::DisplayRotation rotation_{display::DISPLAY_ROTATION_0_DEGREES}; + RotationType rotation_type_; }; class IdleTrigger : public Trigger<> { diff --git a/esphome/components/lvgl/types.py b/esphome/components/lvgl/types.py index 686e429267..0c8ddfbfbd 100644 --- a/esphome/components/lvgl/types.py +++ b/esphome/components/lvgl/types.py @@ -69,6 +69,7 @@ lv_page_t = LvType("LvPageType", parents=(LvCompound,)) lv_image_t = LvType("lv_image_t") lv_gradient_t = LvType("lv_grad_dsc_t") lv_event_t = LvType("lv_event_t") +RotationType = lvgl_ns.enum("RotationType") LV_EVENT = MockObj(base="LV_EVENT_", op="") LV_STATE = MockObj(base="LV_STATE_", op="") diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 3c5c730e6c..4d44c62000 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -30,12 +30,19 @@ binary_sensor: return y; lvgl: + id: lvgl_id + rotation: 90 log_level: debug resume_on_input: true on_pause: - logger.log: LVGL is Paused + - logger.log: LVGL is Paused + - lvgl.display.set_rotation: 90 on_resume: - logger.log: LVGL has resumed + - logger.log: LVGL has resumed + - lvgl.display.set_rotation: + rotation: 0 + lvgl_id: lvgl_id + on_boot: - logger.log: LVGL has started - lvgl.indicator.update: From c98bb9060f7d45e9ef57103fd3add9578caa2e59 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 7 Apr 2026 08:48:14 +1000 Subject: [PATCH 1975/2030] [lvgl] Fix setting triggers on display (#15364) --- esphome/components/lvgl/__init__.py | 20 +++++-- esphome/components/lvgl/defines.py | 36 +++++++----- esphome/components/lvgl/trigger.py | 54 +++++++++++++----- tests/components/lvgl/lvgl-package.yaml | 76 ++++++++++++------------- 4 files changed, 114 insertions(+), 72 deletions(-) diff --git a/esphome/components/lvgl/__init__.py b/esphome/components/lvgl/__init__.py index b429e1e322..b69f8ef57b 100644 --- a/esphome/components/lvgl/__init__.py +++ b/esphome/components/lvgl/__init__.py @@ -2,7 +2,7 @@ import importlib from pathlib import Path import pkgutil -from esphome.automation import build_automation, validate_automation +from esphome.automation import Trigger, build_automation, validate_automation import esphome.codegen as cg from esphome.components.const import ( CONF_BYTE_ORDER, @@ -34,7 +34,6 @@ from esphome.const import ( CONF_ID, CONF_LAMBDA, CONF_LOG_LEVEL, - CONF_ON_BOOT, CONF_ON_IDLE, CONF_PAGES, CONF_ROTATION, @@ -59,7 +58,7 @@ from .encoders import ( from .gradient import GRADIENT_SCHEMA, gradients_to_code from .keypads import KEYPADS_CONFIG, keypads_to_code from .lv_validation import lv_bool, lv_images_used -from .lvcode import LvContext, LvglComponent, lvgl_static +from .lvcode import LvContext, LvglComponent, lv_event_t_ptr, lvgl_static from .schemas import ( DISP_BG_SCHEMA, FULL_STYLE_SCHEMA, @@ -71,7 +70,7 @@ from .schemas import ( ) from .styles import styles_to_code, theme_to_code from .touchscreens import touchscreen_schema, touchscreens_to_code -from .trigger import add_on_boot_triggers, generate_align_tos, generate_triggers +from .trigger import generate_align_tos, generate_triggers from .types import ( IdleTrigger, PlainTrigger, @@ -79,6 +78,7 @@ from .types import ( lv_font_t, lv_group_t, lv_lambda_t, + lv_obj_t_ptr, lv_style_t, lvgl_ns, ) @@ -398,7 +398,6 @@ async def to_code(configs): f"set_{trigger_name.removeprefix('on_')}_trigger", )(trigger_var) ) - await add_on_boot_triggers(config.get(CONF_ON_BOOT, ())) # This must be done after all widgets are created for comp in helpers.lvgl_components_required: @@ -502,6 +501,17 @@ LVGL_SCHEMA = cv.All( cv.polling_component_schema("1s") .extend( { + **{ + cv.Optional(event): validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + Trigger.template(lv_obj_t_ptr, lv_event_t_ptr) + ), + } + ) + for event in df.LV_SCREEN_EVENT_TRIGGERS + + df.LV_DISPLAY_EVENT_TRIGGERS + }, cv.GenerateID(CONF_ID): cv.declare_id(LvglComponent), cv.GenerateID(CONF_ALIGN_TO_LAMBDA_ID): cv.declare_id(lv_lambda_t), cv.GenerateID(df.CONF_DISPLAYS): display_schema, diff --git a/esphome/components/lvgl/defines.py b/esphome/components/lvgl/defines.py index ae8387bcca..ef29a99ddd 100644 --- a/esphome/components/lvgl/defines.py +++ b/esphome/components/lvgl/defines.py @@ -276,10 +276,6 @@ LV_EVENT_MAP = { "DRAW_POST_BEGIN": "DRAW_POST_BEGIN", "DRAW_POST_END": "DRAW_POST_END", "DRAW_TASK_ADD": "DRAW_TASK_ADDED", - "FLUSH_FINISH": "FLUSH_FINISH", - "FLUSH_START": "FLUSH_START", - "FLUSH_WAIT_FINISH": "FLUSH_WAIT_FINISH", - "FLUSH_WAIT_START": "FLUSH_WAIT_START", "FOCUS": "FOCUSED", "GESTURE": "GESTURE", "GET_SELF_SIZE": "GET_SELF_SIZE", @@ -300,18 +296,8 @@ LV_EVENT_MAP = { "READY": "READY", "REFRESH": "REFRESH", "REFR_EXT_DRAW_SIZE": "REFR_EXT_DRAW_SIZE", - "REFR_READY": "REFR_READY", - "REFR_REQUEST": "REFR_REQUEST", - "REFR_START": "REFR_START", "RELEASE": "RELEASED", - "RENDER_READY": "RENDER_READY", - "RENDER_START": "RENDER_START", - "RESOLUTION_CHANGE": "RESOLUTION_CHANGED", "ROTARY": "ROTARY", - "SCREEN_LOAD": "SCREEN_LOADED", - "SCREEN_LOAD_START": "SCREEN_LOAD_START", - "SCREEN_UNLOAD": "SCREEN_UNLOADED", - "SCREEN_UNLOAD_START": "SCREEN_UNLOAD_START", "SCROLL": "SCROLL", "SCROLL_BEGIN": "SCROLL_BEGIN", "SCROLL_END": "SCROLL_END", @@ -322,12 +308,34 @@ LV_EVENT_MAP = { "STATE_CHANGE": "STATE_CHANGED", "STYLE_CHANGE": "STYLE_CHANGED", "TRIPLE_CLICK": "TRIPLE_CLICKED", +} +LV_SCREEN_EVENT_MAP = { + "SCREEN_LOAD": "SCREEN_LOADED", + "SCREEN_LOAD_START": "SCREEN_LOAD_START", + "SCREEN_UNLOAD": "SCREEN_UNLOADED", + "SCREEN_UNLOAD_START": "SCREEN_UNLOAD_START", +} + +LV_DISPLAY_EVENT_MAP = { + "FLUSH_FINISH": "FLUSH_FINISH", + "FLUSH_START": "FLUSH_START", + "FLUSH_WAIT_FINISH": "FLUSH_WAIT_FINISH", + "FLUSH_WAIT_START": "FLUSH_WAIT_START", + "REFR_READY": "REFR_READY", + "REFR_REQUEST": "REFR_REQUEST", + "REFR_START": "REFR_START", + "RENDER_READY": "RENDER_READY", + "RENDER_START": "RENDER_START", + "RESOLUTION_CHANGE": "RESOLUTION_CHANGED", "UPDATE_LAYOUT_COMPLETE": "UPDATE_LAYOUT_COMPLETED", "VSYNC": "VSYNC", "VSYNC_REQUEST": "VSYNC_REQUEST", } LV_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_EVENT_MAP) +LV_DISPLAY_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_DISPLAY_EVENT_MAP) +LV_SCREEN_EVENT_TRIGGERS = tuple(f"on_{x.lower()}" for x in LV_SCREEN_EVENT_MAP) + SWIPE_TRIGGERS = tuple( f"on_swipe_{x.lower()}" for x in DIRECTIONS.choices + ("up", "down") ) diff --git a/esphome/components/lvgl/trigger.py b/esphome/components/lvgl/trigger.py index 54309cdf89..f825999e8a 100644 --- a/esphome/components/lvgl/trigger.py +++ b/esphome/components/lvgl/trigger.py @@ -8,16 +8,21 @@ from esphome.const import ( CONF_X, CONF_Y, ) -from esphome.cpp_generator import new_Pvariable +from esphome.cpp_generator import MockObj, new_Pvariable from esphome.cpp_helpers import register_component +from esphome.cpp_types import nullptr from .defines import ( CONF_ALIGN, CONF_ALIGN_TO, CONF_ALIGN_TO_LAMBDA_ID, DIRECTIONS, + LV_DISPLAY_EVENT_MAP, + LV_DISPLAY_EVENT_TRIGGERS, LV_EVENT_MAP, LV_EVENT_TRIGGERS, + LV_SCREEN_EVENT_MAP, + LV_SCREEN_EVENT_TRIGGERS, SWIPE_TRIGGERS, literal, ) @@ -30,6 +35,7 @@ from .lvcode import ( lv, lv_add, lv_event_t_ptr, + lv_expr, lvgl_static, ) from .types import LV_EVENT @@ -49,25 +55,24 @@ async def generate_triggers(): Must be done after all widgets completed """ + all_triggers = ( + LV_EVENT_TRIGGERS + LV_DISPLAY_EVENT_TRIGGERS + LV_SCREEN_EVENT_TRIGGERS + ) for w in widget_map.values(): + config = w.config if isinstance(w.type, LvScrActType): w = get_screen_active(w.var) - if w.config: + if config: for event, conf in { - event: conf - for event, conf in w.config.items() - if event in LV_EVENT_TRIGGERS + event: conf for event, conf in config.items() if event in all_triggers }.items(): conf = conf[0] w.add_flag("LV_OBJ_FLAG_CLICKABLE") - event = literal("LV_EVENT_" + LV_EVENT_MAP[event[3:].upper()]) await add_trigger(conf, w, event) for event, conf in { - event: conf - for event, conf in w.config.items() - if event in SWIPE_TRIGGERS + event: conf for event, conf in config.items() if event in SWIPE_TRIGGERS }.items(): conf = conf[0] dir = event[9:].upper() @@ -77,11 +82,9 @@ async def generate_triggers(): selected = literal( f"lv_indev_get_gesture_dir(lv_indev_active()) == {dir}" ) - await add_trigger( - conf, w, literal("LV_EVENT_GESTURE"), is_selected=selected - ) + await add_trigger(conf, w, "GESTURE", is_selected=selected) - for conf in w.config.get(CONF_ON_VALUE, ()): + for conf in config.get(CONF_ON_VALUE, ()): await add_trigger( conf, w, @@ -90,7 +93,7 @@ async def generate_triggers(): UPDATE_EVENT, ) - await add_on_boot_triggers(w.config.get(CONF_ON_BOOT, ())) + await add_on_boot_triggers(config.get(CONF_ON_BOOT, ())) async def generate_align_tos(config: dict): @@ -119,6 +122,17 @@ async def generate_align_tos(config: dict): await register_component(var, {}) +TRIGGER_MAP = LV_EVENT_MAP | LV_DISPLAY_EVENT_MAP | LV_SCREEN_EVENT_MAP +DISPLAY_TRIGGERS = set(LV_DISPLAY_EVENT_TRIGGERS) + + +def _get_event_literal(trigger: str | MockObj) -> MockObj: + if isinstance(trigger, MockObj): + return trigger + trigger = trigger.removeprefix("on_") + return literal("LV_EVENT_" + TRIGGER_MAP[trigger.upper()]) + + async def add_trigger(conf, w, *events, is_selected=None): is_selected = is_selected or w.is_selected() tid = conf[CONF_TRIGGER_ID] @@ -129,4 +143,14 @@ async def add_trigger(conf, w, *events, is_selected=None): async with LambdaContext(EVENT_ARG, where=tid) as context: with LvConditional(is_selected): lv_add(trigger.trigger(*value, literal("event"))) - lv_add(lvgl_static.add_event_cb(w.obj, await context.get_lambda(), *events)) + callback = await context.get_lambda() + event_literals = [_get_event_literal(event) for event in events] + if isinstance(events[0], str) and events[0] in DISPLAY_TRIGGERS: + assert len(events) == 1 + lv.display_add_event_cb( + lv_expr.obj_get_display(w.obj), callback, event_literals[0], nullptr + ) + else: + lv_add( + lvgl_static.add_event_cb(w.obj, await context.get_lambda(), *event_literals) + ) diff --git a/tests/components/lvgl/lvgl-package.yaml b/tests/components/lvgl/lvgl-package.yaml index 4d44c62000..967fe51592 100644 --- a/tests/components/lvgl/lvgl-package.yaml +++ b/tests/components/lvgl/lvgl-package.yaml @@ -49,6 +49,44 @@ lvgl: id: meter_arc_indicator start_value: 0 end_value: 180 + on_invalidate_area: + logger.log: Invalidate area + on_resolution_change: + logger.log: Resolution changed + on_color_format_change: + logger.log: Color format changed + on_refr_request: + logger.log: Refresh request + on_refr_start: + logger.log: Refresh start + on_refr_ready: + logger.log: Refresh ready + on_render_start: + logger.log: Render start + on_render_ready: + logger.log: Render ready + on_flush_start: + logger.log: Flush start + on_flush_finish: + logger.log: Flush finish + on_flush_wait_start: + logger.log: Flush wait start + on_flush_wait_finish: + logger.log: Flush wait finish + on_update_layout_complete: + logger.log: Update layout complete + on_vsync: + logger.log: Vsync + on_vsync_request: + logger.log: Vsync request + on_screen_load_start: + logger.log: Screen load start + on_screen_load: + logger.log: Screen loaded + on_screen_unload: + logger.log: Screen unloaded + on_screen_unload_start: + logger.log: Screen unload start bg_color: light_blue bottom_layer: widgets: @@ -660,14 +698,6 @@ lvgl: logger.log: Child created on_child_delete: logger.log: Child deleted - on_screen_unload_start: - logger.log: Screen unload start - on_screen_load_start: - logger.log: Screen load start - on_screen_load: - logger.log: Screen loaded - on_screen_unload: - logger.log: Screen unloaded on_size_change: logger.log: Size changed on_style_change: @@ -676,36 +706,6 @@ lvgl: logger.log: Layout changed on_get_self_size: logger.log: Get self size - on_invalidate_area: - logger.log: Invalidate area - on_resolution_change: - logger.log: Resolution changed - on_color_format_change: - logger.log: Color format changed - on_refr_request: - logger.log: Refresh request - on_refr_start: - logger.log: Refresh start - on_refr_ready: - logger.log: Refresh ready - on_render_start: - logger.log: Render start - on_render_ready: - logger.log: Render ready - on_flush_start: - logger.log: Flush start - on_flush_finish: - logger.log: Flush finish - on_flush_wait_start: - logger.log: Flush wait start - on_flush_wait_finish: - logger.log: Flush wait finish - on_update_layout_complete: - logger.log: Update layout complete - on_vsync: - logger.log: Vsync - on_vsync_request: - logger.log: Vsync request - led: id: lv_led color: 0x00FF00 From 9bd936112d6947555d3864ef39b3f33e85bff49b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:54:09 +0200 Subject: [PATCH 1976/2030] [nextion] Fix queue age check using inconsistent time sources (#15317) --- esphome/components/nextion/nextion.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 01ceb3d765..d0e87d4fdf 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -1064,7 +1064,7 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) { nextion_queue->component = new nextion::NextionComponentBase; nextion_queue->component->set_variable_name(variable_name); - nextion_queue->queue_time = millis(); + nextion_queue->queue_time = App.get_loop_component_start_time(); this->nextion_queue_.push_back(nextion_queue); From 9036c29c8a1122faac1ff145de79dd303d741044 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:04:01 +1000 Subject: [PATCH 1977/2030] [online_image] Clear LVGL dsc when image size changes. (#15360) --- esphome/components/runtime_image/runtime_image.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/esphome/components/runtime_image/runtime_image.cpp b/esphome/components/runtime_image/runtime_image.cpp index 5a4a2ea7d6..25cf7c8ab4 100644 --- a/esphome/components/runtime_image/runtime_image.cpp +++ b/esphome/components/runtime_image/runtime_image.cpp @@ -247,6 +247,9 @@ void RuntimeImage::release_buffer_() { this->height_ = 0; this->buffer_width_ = 0; this->buffer_height_ = 0; +#ifdef USE_LVGL + memset(&this->dsc_, 0, sizeof(this->dsc_)); +#endif } } From 162c8810db89d3dc09e2f5f1c84bb890d476ca18 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Sat, 4 Apr 2026 23:11:29 +1000 Subject: [PATCH 1978/2030] [esp32] Clean build when sdkconfig options change (#15439) --- esphome/components/esp32/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 475de6aa3e..72d0e42971 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -47,7 +47,7 @@ from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed from esphome.types import ConfigType -from esphome.writer import clean_cmake_cache +from esphome.writer import clean_build, clean_cmake_cache from .boards import BOARDS, STANDARD_BOARDS from .const import ( # noqa @@ -1911,6 +1911,7 @@ def _write_sdkconfig(): if write_file_if_changed(internal_path, contents): # internal changed, update real one write_file_if_changed(sdk_path, contents) + clean_build(clear_pio_cache=False) def _write_idf_component_yml(): From 1c67e4ce4c5d50419d0d610a4c50e99554e92337 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:50:41 +1200 Subject: [PATCH 1979/2030] Bump version to 2026.3.3 --- Doxyfile | 2 +- esphome/const.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 97201d1c44..7d0fcb9a27 100644 --- a/Doxyfile +++ b/Doxyfile @@ -48,7 +48,7 @@ PROJECT_NAME = ESPHome # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 2026.3.2 +PROJECT_NUMBER = 2026.3.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/esphome/const.py b/esphome/const.py index ebab56193c..6037065a21 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -4,7 +4,7 @@ from enum import Enum from esphome.enum import StrEnum -__version__ = "2026.3.2" +__version__ = "2026.3.3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = ( From 62d0c25a2bfd3da6afcfdd3c9f869c18432cbe18 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 7 Apr 2026 11:14:59 +1200 Subject: [PATCH 1980/2030] [CI] Add branches-ignore for release and beta in PR title check (#15491) --- .github/workflows/pr-title-check.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml index 2ad023ed1b..0021654def 100644 --- a/.github/workflows/pr-title-check.yml +++ b/.github/workflows/pr-title-check.yml @@ -3,6 +3,9 @@ name: PR Title Check on: pull_request: types: [opened, edited, synchronize, reopened] + branches-ignore: + - release + - beta permissions: contents: read From 29ca7bc8f930335201d3827b95c1efbbfe131fe0 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 19:57:16 -0400 Subject: [PATCH 1981/2030] [espnow] Fix string data generating invalid C++ char literals (#15493) --- esphome/components/espnow/__init__.py | 2 +- tests/components/espnow/common.yaml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 1c8d262810..49b96eeb6f 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -245,7 +245,7 @@ async def send_action( data = config.get(CONF_DATA, []) if isinstance(data, str): - data = [cg.RawExpression(f"'{c}'") for c in data] + data = list(data.encode()) templ = await cg.templatable(data, args, byte_vector, byte_vector) cg.add(var.set_data(templ)) diff --git a/tests/components/espnow/common.yaml b/tests/components/espnow/common.yaml index b724af54e0..bdc478ea03 100644 --- a/tests/components/espnow/common.yaml +++ b/tests/components/espnow/common.yaml @@ -29,6 +29,8 @@ espnow: data: !lambda 'return {0x01, 0x02, 0x03, 0x04, 0x05};' - espnow.broadcast: data: "Hello, World!" + - espnow.broadcast: + data: "it's a test" - espnow.broadcast: data: [0x01, 0x02, 0x03, 0x04, 0x05] - espnow.broadcast: From d9da91efbe2de7c967efa2fce6e6462c9afd9862 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:14:17 -0400 Subject: [PATCH 1982/2030] [bl0940] Fix restore_value reading from wrong config dict (#15492) --- esphome/components/bl0940/number/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/bl0940/number/__init__.py b/esphome/components/bl0940/number/__init__.py index a640c2ae08..92ab2837b3 100644 --- a/esphome/components/bl0940/number/__init__.py +++ b/esphome/components/bl0940/number/__init__.py @@ -89,6 +89,6 @@ async def to_code(config): ) await cg.register_component(var, conf) - if restore_value := config.get(CONF_RESTORE_VALUE): + if restore_value := conf.get(CONF_RESTORE_VALUE): cg.add(var.set_restore_value(restore_value)) cg.add(getattr(bl0940, setter_method)(var)) From 14bcd9db59411348a22d8da887ca2fcd6380d87e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:18:59 -0400 Subject: [PATCH 1983/2030] [neopixelbus] Fix SPI pin validation accepting one wrong pin on ESP8266 (#15494) --- esphome/components/neopixelbus/_methods.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/neopixelbus/_methods.py b/esphome/components/neopixelbus/_methods.py index 9072f78035..e1c327a2e0 100644 --- a/esphome/components/neopixelbus/_methods.py +++ b/esphome/components/neopixelbus/_methods.py @@ -344,7 +344,7 @@ def _spi_extra_validate(config): if CORE.is_esp32: return - if config[CONF_DATA_PIN] != 13 and config[CONF_CLOCK_PIN] != 14: + if config[CONF_DATA_PIN] != 13 or config[CONF_CLOCK_PIN] != 14: raise cv.Invalid( "SPI only supports pins GPIO13 for data and GPIO14 for clock on ESP8266" ) From c6e683cc33c35e789c40bf93645e52876391680d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:19:53 -0400 Subject: [PATCH 1984/2030] [pmsx003] Connect model-specific sensor validation to schema (#15495) --- esphome/components/pmsx003/sensor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index cdcedc85ac..0a11120bf0 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -185,7 +185,7 @@ def validate_update_interval(value): return value -CONFIG_SCHEMA = ( +CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(PMSX003Component), @@ -290,7 +290,8 @@ CONFIG_SCHEMA = ( } ) .extend(cv.COMPONENT_SCHEMA) - .extend(uart.UART_DEVICE_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA), + validate_pmsx003_sensors, ) From 0816579fa93b5573ac6b4ed68c0628dfa84b4b0b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:20:46 -0400 Subject: [PATCH 1985/2030] [prometheus] Fix relabel validation not checking for required keys (#15496) --- esphome/components/prometheus/__init__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/esphome/components/prometheus/__init__.py b/esphome/components/prometheus/__init__.py index 26a9e70f7c..cc1541ce80 100644 --- a/esphome/components/prometheus/__init__.py +++ b/esphome/components/prometheus/__init__.py @@ -10,12 +10,14 @@ AUTO_LOAD = ["web_server_base"] prometheus_ns = cg.esphome_ns.namespace("prometheus") PrometheusHandler = prometheus_ns.class_("PrometheusHandler", cg.Component) -CUSTOMIZED_ENTITY = cv.Schema( - { - cv.Optional(CONF_ID): cv.string_strict, - cv.Optional(CONF_NAME): cv.string_strict, - }, - cv.has_at_least_one_key, +CUSTOMIZED_ENTITY = cv.All( + cv.Schema( + { + cv.Optional(CONF_ID): cv.string_strict, + cv.Optional(CONF_NAME): cv.string_strict, + }, + ), + cv.has_at_least_one_key(CONF_ID, CONF_NAME), ) CONFIG_SCHEMA = cv.Schema( From b155c13117b63a50ddacf70c34bc99f59309aaf7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 14:25:53 -1000 Subject: [PATCH 1986/2030] [api] Use integer comparison for float zero checks in protobuf encoding (#15490) --- esphome/components/api/proto.h | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 902d4c0f5c..48da1f2226 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -25,6 +25,19 @@ constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2; // string, bytes, embedded me constexpr uint8_t WIRE_TYPE_FIXED32 = 5; // fixed32, sfixed32, float constexpr uint8_t WIRE_TYPE_MASK = 0b111; // Mask to extract wire type from tag +// Reinterpret float bits as uint32_t without floating-point comparison. +// Used by both encode_float() and calc_float() to ensure identical zero checks. +// Uses union type-punning which is a GCC/Clang extension (not standard C++), +// but bit_cast/memcpy don't optimize to a no-op on xtensa-gcc (ESP8266). +inline uint32_t float_to_raw(float value) { + union { + float f; + uint32_t u; + } v; + v.f = value; + return v.u; +} + // Helper functions for ZigZag encoding/decoding inline constexpr uint32_t encode_zigzag32(int32_t value) { return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31)); @@ -432,14 +445,10 @@ class ProtoEncode { // is needed in the future, the necessary encoding/decoding functions must be added. static inline void encode_float(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, float value, bool force = false) { - if (value == 0.0f && !force) + uint32_t raw = float_to_raw(value); + if (raw == 0 && !force) return; - union { - float value; - uint32_t raw; - } val{}; - val.value = value; - encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, field_id, val.raw); + encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, field_id, raw); } static inline void encode_int32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, int32_t value, bool force = false) { @@ -751,8 +760,8 @@ class ProtoSize { } static constexpr uint32_t calc_bool(uint32_t field_id_size, bool value) { return value ? field_id_size + 1 : 0; } static constexpr uint32_t calc_bool_force(uint32_t field_id_size) { return field_id_size + 1; } - static constexpr uint32_t calc_float(uint32_t field_id_size, float value) { - return value != 0.0f ? field_id_size + 4 : 0; + static uint32_t calc_float(uint32_t field_id_size, float value) { + return float_to_raw(value) != 0 ? field_id_size + 4 : 0; } static constexpr uint32_t calc_fixed32(uint32_t field_id_size, uint32_t value) { return value ? field_id_size + 4 : 0; From 094e0440c68e52c0eb74664e4174bfc85fb89dfb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:30:36 -0400 Subject: [PATCH 1987/2030] [config] Fix unfilled placeholder in dimensions() error message (#15498) --- esphome/config_validation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 09f460f46b..c6b67e9f35 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1667,7 +1667,7 @@ def dimensions(value): match = re.match(r"\s*([0-9]+)\s*[xX]\s*([0-9]+)\s*", value) if not match: raise Invalid( - "Invalid value '{}' for dimensions. Only WIDTHxHEIGHT is allowed." + f"Invalid value '{value}' for dimensions. Only WIDTHxHEIGHT is allowed." ) return dimensions([match.group(1), match.group(2)]) From 4fa3e48d3353b1cb50fd68a978b35d2dd8f6b517 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 20:34:07 -0400 Subject: [PATCH 1988/2030] [remote_base] Fix misc protocol schema and codegen bugs (#15497) --- esphome/components/remote_base/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index a0594d7f67..99eda76f81 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -470,7 +470,7 @@ CANALSATLD_SCHEMA = cv.Schema( ) -@register_binary_sensor("canalsatld", CanalSatLDBinarySensor, CANALSAT_SCHEMA) +@register_binary_sensor("canalsatld", CanalSatLDBinarySensor, CANALSATLD_SCHEMA) def canalsatld_binary_sensor(var, config): cg.add( var.set_data( @@ -1130,7 +1130,7 @@ def sony_dumper(var, config): async def sony_action(var, config, args): template_ = await cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) - template_ = await cg.templatable(config[CONF_NBITS], args, cg.uint32) + template_ = await cg.templatable(config[CONF_NBITS], args, cg.uint8) cg.add(var.set_nbits(template_)) @@ -1174,7 +1174,7 @@ def symphony_dumper(var, config): async def symphony_action(var, config, args): template_ = await cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) - template_ = await cg.templatable(config[CONF_NBITS], args, cg.uint32) + template_ = await cg.templatable(config[CONF_NBITS], args, cg.uint8) cg.add(var.set_nbits(template_)) template_ = await cg.templatable(config[CONF_COMMAND_REPEATS], args, cg.uint8) cg.add(var.set_repeats(template_)) @@ -1188,7 +1188,7 @@ def validate_raw_alternating(value): this_negative = val < 0 if i != 0 and this_negative == last_negative: raise cv.Invalid( - f"Values must alternate between being positive and negative, please see index {i} and {i + 1}", + f"Values must alternate between being positive and negative, please see index {i - 1} and {i}", [i], ) last_negative = this_negative @@ -2105,12 +2105,12 @@ async def abbwelcome_action(var, config, args): ) cg.add( var.set_source_address( - await cg.templatable(config[CONF_SOURCE_ADDRESS], args, cg.uint16) + await cg.templatable(config[CONF_SOURCE_ADDRESS], args, cg.uint32) ) ) cg.add( var.set_destination_address( - await cg.templatable(config[CONF_DESTINATION_ADDRESS], args, cg.uint16) + await cg.templatable(config[CONF_DESTINATION_ADDRESS], args, cg.uint32) ) ) cg.add( From d15fa84f4f5a33e9fd48597a278e3f8bb3645193 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 14:39:55 -1000 Subject: [PATCH 1989/2030] [api] Auto-derive max_value for enum fields in protobuf codegen (#15469) --- esphome/components/api/api_pb2.cpp | 130 +++++++++++++--------------- script/api_protobuf/api_protobuf.py | 62 ++++++++----- 2 files changed, 98 insertions(+), 94 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index ed4711bfaa..ba9ebd1f40 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -87,7 +87,7 @@ uint8_t *SerialProxyInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PAR uint32_t SerialProxyInfo::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->name.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->port_type)); + size += this->port_type ? 2 : 0; return size; } #endif @@ -244,7 +244,7 @@ uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); #endif - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -305,7 +305,7 @@ uint32_t ListEntitiesCoverResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); #endif - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_bool(1, this->supports_stop); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -328,7 +328,7 @@ uint32_t CoverStateResponse::calculate_size() const { size += 5; size += ProtoSize::calc_float(1, this->position); size += ProtoSize::calc_float(1, this->tilt); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); + size += this->current_operation ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -408,7 +408,7 @@ uint32_t ListEntitiesFanResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); #endif - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; if (!this->supported_preset_modes->empty()) { for (const char *it : *this->supported_preset_modes) { size += ProtoSize::calc_length_force(1, strlen(it)); @@ -437,7 +437,7 @@ uint32_t FanStateResponse::calculate_size() const { size += 5; size += ProtoSize::calc_bool(1, this->state); size += ProtoSize::calc_bool(1, this->oscillating); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->direction)); + size += this->direction ? 2 : 0; size += ProtoSize::calc_int32(1, this->speed_level); size += ProtoSize::calc_length(1, this->preset_mode.size()); #ifdef USE_DEVICES @@ -536,9 +536,7 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { size += 5; size += ProtoSize::calc_length(1, this->name.size()); if (!this->supported_color_modes->empty()) { - for (const auto &it : *this->supported_color_modes) { - size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); - } + size += this->supported_color_modes->size() * 2; } size += ProtoSize::calc_float(1, this->min_mireds); size += ProtoSize::calc_float(1, this->max_mireds); @@ -551,7 +549,7 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); #endif - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(2, this->device_id); #endif @@ -582,7 +580,7 @@ uint32_t LightStateResponse::calculate_size() const { size += 5; size += ProtoSize::calc_bool(1, this->state); size += ProtoSize::calc_float(1, this->brightness); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->color_mode)); + size += this->color_mode ? 2 : 0; size += ProtoSize::calc_float(1, this->color_brightness); size += ProtoSize::calc_float(1, this->red); size += ProtoSize::calc_float(1, this->green); @@ -739,9 +737,9 @@ uint32_t ListEntitiesSensorResponse::calculate_size() const { size += ProtoSize::calc_int32(1, this->accuracy_decimals); size += ProtoSize::calc_bool(1, this->force_update); size += ProtoSize::calc_length(1, this->device_class.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state_class)); + size += this->state_class ? 2 : 0; size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -796,7 +794,7 @@ uint32_t ListEntitiesSwitchResponse::calculate_size() const { #endif size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -873,7 +871,7 @@ uint32_t ListEntitiesTextSensorResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -922,7 +920,7 @@ uint8_t *SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEB } uint32_t SubscribeLogsResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->level)); + size += this->level ? 2 : 0; size += ProtoSize::calc_length(1, this->message_len_); return size; } @@ -1171,7 +1169,7 @@ uint8_t *ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer PROTO_ENC uint32_t ListEntitiesServicesArgument::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_length(1, this->name.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); + size += this->type ? 2 : 0; return size; } uint8_t *ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { @@ -1193,7 +1191,7 @@ uint32_t ListEntitiesServicesResponse::calculate_size() const { size += ProtoSize::calc_message_force(1, it.calculate_size()); } } - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->supports_response)); + size += this->supports_response ? 2 : 0; return size; } bool ExecuteServiceArgument::decode_varint(uint32_t field_id, proto_varint_value_t value) { @@ -1347,7 +1345,7 @@ uint32_t ListEntitiesCameraResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(1, this->icon.size()); #endif - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1441,23 +1439,17 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { size += ProtoSize::calc_bool(1, this->supports_current_temperature); size += ProtoSize::calc_bool(1, this->supports_two_point_target_temperature); if (!this->supported_modes->empty()) { - for (const auto &it : *this->supported_modes) { - size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); - } + size += this->supported_modes->size() * 2; } size += ProtoSize::calc_float(1, this->visual_min_temperature); size += ProtoSize::calc_float(1, this->visual_max_temperature); size += ProtoSize::calc_float(1, this->visual_target_temperature_step); size += ProtoSize::calc_bool(1, this->supports_action); if (!this->supported_fan_modes->empty()) { - for (const auto &it : *this->supported_fan_modes) { - size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); - } + size += this->supported_fan_modes->size() * 2; } if (!this->supported_swing_modes->empty()) { - for (const auto &it : *this->supported_swing_modes) { - size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); - } + size += this->supported_swing_modes->size() * 2; } if (!this->supported_custom_fan_modes->empty()) { for (const char *it : *this->supported_custom_fan_modes) { @@ -1465,9 +1457,7 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { } } if (!this->supported_presets->empty()) { - for (const auto &it : *this->supported_presets) { - size += ProtoSize::calc_uint32_force(2, static_cast<uint32_t>(it)); - } + size += this->supported_presets->size() * 3; } if (!this->supported_custom_presets->empty()) { for (const char *it : *this->supported_custom_presets) { @@ -1478,7 +1468,7 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { #ifdef USE_ENTITY_ICON size += ProtoSize::calc_length(2, this->icon.size()); #endif - size += ProtoSize::calc_uint32(2, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 3 : 0; size += ProtoSize::calc_float(2, this->visual_current_temperature_step); size += ProtoSize::calc_bool(2, this->supports_current_humidity); size += ProtoSize::calc_bool(2, this->supports_target_humidity); @@ -1514,16 +1504,16 @@ uint8_t *ClimateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBU uint32_t ClimateStateResponse::calculate_size() const { uint32_t size = 0; size += 5; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += this->mode ? 2 : 0; size += ProtoSize::calc_float(1, this->current_temperature); size += ProtoSize::calc_float(1, this->target_temperature); size += ProtoSize::calc_float(1, this->target_temperature_low); size += ProtoSize::calc_float(1, this->target_temperature_high); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->action)); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->fan_mode)); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->swing_mode)); + size += this->action ? 2 : 0; + size += this->fan_mode ? 2 : 0; + size += this->swing_mode ? 2 : 0; size += ProtoSize::calc_length(1, this->custom_fan_mode.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->preset)); + size += this->preset ? 2 : 0; size += ProtoSize::calc_length(1, this->custom_preset.size()); size += ProtoSize::calc_float(1, this->current_humidity); size += ProtoSize::calc_float(1, this->target_humidity); @@ -1656,7 +1646,7 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1664,9 +1654,7 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { size += ProtoSize::calc_float(1, this->max_temperature); size += ProtoSize::calc_float(1, this->target_temperature_step); if (!this->supported_modes->empty()) { - for (const auto &it : *this->supported_modes) { - size += ProtoSize::calc_uint32_force(1, static_cast<uint32_t>(it)); - } + size += this->supported_modes->size() * 2; } size += ProtoSize::calc_uint32(1, this->supported_features); return size; @@ -1690,7 +1678,7 @@ uint32_t WaterHeaterStateResponse::calculate_size() const { size += 5; size += ProtoSize::calc_float(1, this->current_temperature); size += ProtoSize::calc_float(1, this->target_temperature); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += this->mode ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1774,9 +1762,9 @@ uint32_t ListEntitiesNumberResponse::calculate_size() const { size += ProtoSize::calc_float(1, this->max_value); size += ProtoSize::calc_float(1, this->step); size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->unit_of_measurement.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += this->mode ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -1862,7 +1850,7 @@ uint32_t ListEntitiesSelectResponse::calculate_size() const { } } size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1959,7 +1947,7 @@ uint32_t ListEntitiesSirenResponse::calculate_size() const { } size += ProtoSize::calc_bool(1, this->supports_duration); size += ProtoSize::calc_bool(1, this->supports_volume); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -2067,7 +2055,7 @@ uint32_t ListEntitiesLockResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->supports_open); size += ProtoSize::calc_bool(1, this->requires_code); @@ -2089,7 +2077,7 @@ uint8_t *LockStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_P uint32_t LockStateResponse::calculate_size() const { uint32_t size = 0; size += 5; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); + size += this->state ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -2161,7 +2149,7 @@ uint32_t ListEntitiesButtonResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -2206,7 +2194,7 @@ uint32_t MediaPlayerSupportedFormat::calculate_size() const { size += ProtoSize::calc_length(1, this->format.size()); size += ProtoSize::calc_uint32(1, this->sample_rate); size += ProtoSize::calc_uint32(1, this->num_channels); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->purpose)); + size += this->purpose ? 2 : 0; size += ProtoSize::calc_uint32(1, this->sample_bytes); return size; } @@ -2239,7 +2227,7 @@ uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_bool(1, this->supports_pause); if (!this->supported_formats.empty()) { for (const auto &it : this->supported_formats) { @@ -2266,7 +2254,7 @@ uint8_t *MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_ uint32_t MediaPlayerStateResponse::calculate_size() const { uint32_t size = 0; size += 5; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); + size += this->state ? 2 : 0; size += ProtoSize::calc_float(1, this->volume); size += ProtoSize::calc_bool(1, this->muted); #ifdef USE_DEVICES @@ -2348,7 +2336,7 @@ uint8_t *BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer PROTO_ENCO ProtoEncode::encode_varint_raw_short(pos PROTO_ENCODE_DEBUG_ARG, encode_zigzag32(this->rssi)); if (this->address_type) { ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 24); - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast<uint8_t>(this->address_type)); + ProtoEncode::encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, this->address_type); } ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 34); ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast<uint8_t>(this->data_len)); @@ -2762,9 +2750,9 @@ uint8_t *BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_EN } uint32_t BluetoothScannerStateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->configured_mode)); + size += this->state ? 2 : 0; + size += this->mode ? 2 : 0; + size += this->configured_mode ? 2 : 0; return size; } bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { @@ -3116,7 +3104,7 @@ uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_uint32(1, this->supported_features); size += ProtoSize::calc_bool(1, this->requires_code); size += ProtoSize::calc_bool(1, this->requires_code_to_arm); @@ -3137,7 +3125,7 @@ uint8_t *AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer PROTO_E uint32_t AlarmControlPanelStateResponse::calculate_size() const { uint32_t size = 0; size += 5; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->state)); + size += this->state ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3209,11 +3197,11 @@ uint32_t ListEntitiesTextResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_uint32(1, this->min_length); size += ProtoSize::calc_uint32(1, this->max_length); size += ProtoSize::calc_length(1, this->pattern.size()); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->mode)); + size += this->mode ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3298,7 +3286,7 @@ uint32_t ListEntitiesDateResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3385,7 +3373,7 @@ uint32_t ListEntitiesTimeResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3476,7 +3464,7 @@ uint32_t ListEntitiesEventResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); if (!this->event_types->empty()) { for (const char *it : *this->event_types) { @@ -3536,7 +3524,7 @@ uint32_t ListEntitiesValveResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->supports_position); @@ -3560,7 +3548,7 @@ uint32_t ValveStateResponse::calculate_size() const { uint32_t size = 0; size += 5; size += ProtoSize::calc_float(1, this->position); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->current_operation)); + size += this->current_operation ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3623,7 +3611,7 @@ uint32_t ListEntitiesDateTimeResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3701,7 +3689,7 @@ uint32_t ListEntitiesUpdateResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; size += ProtoSize::calc_length(1, this->device_class.size()); #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); @@ -3821,7 +3809,7 @@ uint8_t *ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_P } uint32_t ZWaveProxyRequest::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); + size += this->type ? 2 : 0; size += ProtoSize::calc_length(1, this->data_len); return size; } @@ -3853,7 +3841,7 @@ uint32_t ListEntitiesInfraredResponse::calculate_size() const { size += ProtoSize::calc_length(1, this->icon.size()); #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->entity_category)); + size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -4048,8 +4036,8 @@ uint8_t *SerialProxyRequestResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD uint32_t SerialProxyRequestResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_uint32(1, this->instance); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->type)); - size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->status)); + size += this->type ? 2 : 0; + size += this->status ? 2 : 0; size += ProtoSize::calc_length(1, this->error_message.size()); return size; } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 3833f279ce..6de5c2b1c7 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -56,6 +56,10 @@ FILE_HEADER = """// This file was automatically generated with a tool. // See script/api_protobuf/api_protobuf.py """ +# Populated by main() before any TypeInfo creation. +# Maps enum type name (e.g. ".BluetoothDeviceRequestType") to max enum value. +_enum_max_values: dict[str, int] = {} + def indent_list(text: str, padding: str = " ") -> list[str]: """Indent each line of the given text with the specified padding.""" @@ -240,12 +244,6 @@ class TypeInfo(ABC): "encode_bool": "ProtoEncode::write_raw_byte(pos, {value} ? 0x01 : 0x00);", } - # When max_value < 128, the varint is always 1 byte — use a direct byte write - RAW_ENCODE_SMALL_MAP: dict[str, str] = { - "encode_uint32": "ProtoEncode::write_raw_byte(pos, static_cast<uint8_t>({value}));", - "encode_uint64": "ProtoEncode::write_raw_byte(pos, static_cast<uint8_t>({value}));", - } - def _encode_with_precomputed_tag(self, value_expr: str) -> str | None: """Try to emit a precomputed-tag encode for a field. @@ -255,19 +253,14 @@ class TypeInfo(ABC): Returns the raw encode string if the tag is a single byte and the encode_func has a known raw equivalent, or None otherwise. - When max_value < 128, uses direct byte write instead of varint encoding. """ tag = self.calculate_tag() if tag >= 128: return None max_val = self.max_value + # Only use RAW_ENCODE_MAP for forced fields or fields with max_value raw_expr = None - if max_val is not None and max_val < 128: - raw_expr = self.RAW_ENCODE_SMALL_MAP.get(self.encode_func) - if raw_expr is None: - # Only use RAW_ENCODE_MAP for forced fields or fields with max_value - if not self.force and max_val is None: - return None + if self.force or max_val is not None: raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) if raw_expr is None: return None @@ -1321,19 +1314,24 @@ class EnumType(TypeInfo): default_value = "" wire_type = WireType.VARINT # Uses wire type 0 + @property + def max_value(self) -> int | None: + """Get max_value from explicit annotation or auto-derive from enum definition.""" + explicit = super().max_value + if explicit is not None: + return explicit + return _enum_max_values.get(self._field.type_name) + @property def encode_func(self) -> str: return "encode_uint32" @property def encode_content(self) -> str: - if result := self._encode_with_precomputed_tag( - f"static_cast<uint32_t>(this->{self.field_name})" - ): - return result + value_expr = f"static_cast<uint32_t>(this->{self.field_name})" if self.force: - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, static_cast<uint32_t>(this->{self.field_name}), true);" - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, static_cast<uint32_t>(this->{self.field_name}));" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, {value_expr}, true);" + return f"ProtoEncode::{self.encode_func}(pos, {self.number}, {value_expr});" def dump(self, name: str) -> str: return f"out.append_p(proto_enum_to_string<{self.cpp_type}>({name}));" @@ -1343,6 +1341,9 @@ class EnumType(TypeInfo): return f"static_cast<{self.cpp_type}>({value})" def get_size_calculation(self, name: str, force: bool = False) -> str: + max_val = self.max_value + if max_val is not None and max_val < 128: + return self._get_single_byte_varint_size(name, force) return self._get_simple_size_calculation( name, force, "uint32", f"static_cast<uint32_t>({name})" ) @@ -1905,17 +1906,27 @@ class RepeatedTypeInfo(TypeInfo): size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()" o += f" size += {size_expr} * {bytes_per_element};\n" else: - # Other types need the actual value + # Check if inner type produces a constant size (doesn't depend on value) + inner_size = self._ti.get_size_calculation("it", True) + if "it" not in inner_size: + # Constant size per element — use multiply instead of loop + # Extract the constant from "size += N;" + const_val = ( + inner_size.strip().removeprefix("size += ").removesuffix(";") + ) + size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()" + o += f" size += {size_expr} * {const_val};\n" # Special handling for const char* elements - if self._use_pointer and "const char" in self._container_no_template: + elif self._use_pointer and "const char" in self._container_no_template: field_id_size = self.calculate_field_id_size() o += f" for (const char *it : {container_ref}) {{\n" o += f" size += ProtoSize::calc_length_force({field_id_size}, strlen(it));\n" + o += " }\n" else: auto_ref = "" if self._ti_is_bool else "&" o += f" for (const auto {auto_ref}it : {container_ref}) {{\n" - o += f" {self._ti.get_size_calculation('it', True)}\n" - o += " }\n" + o += f" {inner_size}\n" + o += " }\n" o += "}" return o @@ -2788,6 +2799,11 @@ def main() -> None: file = d.file[0] + # Build enum max value map so EnumType can auto-derive max_value + for enum in file.enum_type: + if not enum.options.deprecated and enum.value: + _enum_max_values[f".{enum.name}"] = max(v.number for v in enum.value) + # Build dynamic ifdef mappings early so we can emit USE_API_VARINT64 before includes enum_ifdef_map, message_ifdef_map, message_source_map, used_messages = ( build_type_usage_map(file) From 82dc80a4138df4005ca6469e27d1bc71753b3abc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 15:26:40 -1000 Subject: [PATCH 1990/2030] [scheduler] Skip cancel for anonymous items, add empty-container fast path (#15397) --- esphome/core/scheduler.cpp | 24 +++++++++++++++++++++--- esphome/core/scheduler.h | 30 +++++++++++++++--------------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 9ee3b2fdd2..71b29390d6 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -214,8 +214,9 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type #endif /* ESPHOME_DEBUG_SCHEDULER */ } - // Common epilogue: atomic cancel-and-add (unless skip_cancel is true) - if (!skip_cancel) { + // Common epilogue: atomic cancel-and-add (unless skip_cancel is true or anonymous) + // Anonymous items (STATIC_STRING with nullptr) can never match anything, so skip the scan. + if (!skip_cancel && (name_type != NameType::STATIC_STRING || static_name != nullptr)) { this->cancel_item_locked_(component, name_type, static_name, hash_or_id, type, /* match_retry= */ false, /* find_first= */ true); } @@ -742,6 +743,23 @@ bool HOT Scheduler::cancel_item_(Component *component, NameType name_type, const // When find_first=false, cancels ALL matches across all containers (needed for // public cancel path where DelayAction parallel mode can create duplicates). // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id +size_t Scheduler::mark_matching_items_removed_slow_locked_(std::vector<SchedulerItem *> &container, + Component *component, NameType name_type, + const char *static_name, uint32_t hash_or_id, + SchedulerItem::Type type, bool match_retry, + bool find_first) { + size_t count = 0; + for (auto *item : container) { + if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { + this->set_item_removed_(item, true); + if (find_first) + return 1; + count++; + } + } + return count; +} + bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry, bool find_first) { @@ -767,7 +785,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type // The main loop may be executing an item's callback right now, and recycling // would destroy the callback while it's running (use-after-free). // Only the main loop in call() should recycle items after execution completes. - if (!this->items_.empty()) { + { size_t heap_cancelled = this->mark_matching_items_removed_locked_(this->items_, component, name_type, static_name, hash_or_id, type, match_retry, find_first); total_cancelled += heap_cancelled; diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 1e44f41da8..43a3ec7049 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -495,23 +495,23 @@ class Scheduler { // name_type determines matching: STATIC_STRING uses static_name, others use hash_or_id // Returns the number of items marked for removal. // IMPORTANT: Must be called with scheduler lock held - __attribute__((noinline)) size_t mark_matching_items_removed_locked_(std::vector<SchedulerItem *> &container, - Component *component, NameType name_type, - const char *static_name, uint32_t hash_or_id, - SchedulerItem::Type type, bool match_retry, - bool find_first = false) { - size_t count = 0; - for (auto *item : container) { - if (this->matches_item_locked_(item, component, name_type, static_name, hash_or_id, type, match_retry)) { - this->set_item_removed_(item, true); - if (find_first) - return 1; - count++; - } - } - return count; + // Inlined: the fast path (empty container) avoids calling the out-of-line scan. + inline size_t HOT mark_matching_items_removed_locked_(std::vector<SchedulerItem *> &container, Component *component, + NameType name_type, const char *static_name, + uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry, + bool find_first = false) { + if (container.empty()) + return 0; + return this->mark_matching_items_removed_slow_locked_(container, component, name_type, static_name, hash_or_id, + type, match_retry, find_first); } + // Out-of-line slow path for mark_matching_items_removed_locked_ when container is non-empty. + // IMPORTANT: Must be called with scheduler lock held + __attribute__((noinline)) size_t mark_matching_items_removed_slow_locked_( + std::vector<SchedulerItem *> &container, Component *component, NameType name_type, const char *static_name, + uint32_t hash_or_id, SchedulerItem::Type type, bool match_retry, bool find_first); + Mutex lock_; std::vector<SchedulerItem *> items_; std::vector<SchedulerItem *> to_add_; From b8b8d1bb15eceaf389cf0e06b4da13ae35b655d3 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 21:31:57 -0400 Subject: [PATCH 1991/2030] [core] Replace deprecated datetime.utcfromtimestamp() (#15503) --- esphome/external_files.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/external_files.py b/esphome/external_files.py index 72a3f33fdc..18b68fba08 100644 --- a/esphome/external_files.py +++ b/esphome/external_files.py @@ -1,6 +1,6 @@ from __future__ import annotations -from datetime import datetime +from datetime import UTC, datetime import logging from pathlib import Path @@ -27,8 +27,8 @@ def has_remote_file_changed(url: str, local_file_path: Path) -> bool: _LOGGER.debug("has_remote_file_changed: File exists at %s", local_file_path) try: local_modification_time = local_file_path.stat().st_mtime - local_modification_time_str = datetime.utcfromtimestamp( - local_modification_time + local_modification_time_str = datetime.fromtimestamp( + local_modification_time, tz=UTC ).strftime("%a, %d %b %Y %H:%M:%S GMT") headers = { From e428cb5092afcd78e8565bb992fc75da20b7f11c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 21:33:22 -0400 Subject: [PATCH 1992/2030] [multiple] Fix misc cosmetic bugs (batch 2) (#15502) --- esphome/components/atm90e32/sensor.py | 1 - esphome/components/esp8266/gpio.py | 2 +- esphome/components/espnow/__init__.py | 6 +++--- esphome/components/kamstrup_kmp/sensor.py | 3 ++- esphome/components/stepper/__init__.py | 2 +- esphome/zeroconf.py | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index 0944950432..7e5d85c57a 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -132,7 +132,6 @@ ATM90E32_PHASE_SCHEMA = cv.Schema( cv.Optional(CONF_PHASE_ANGLE): sensor.sensor_schema( unit_of_measurement=UNIT_DEGREES, accuracy_decimals=2, - device_class=DEVICE_CLASS_POWER, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_HARMONIC_POWER): sensor.sensor_schema( diff --git a/esphome/components/esp8266/gpio.py b/esphome/components/esp8266/gpio.py index 43508afaf9..64be4a6495 100644 --- a/esphome/components/esp8266/gpio.py +++ b/esphome/components/esp8266/gpio.py @@ -155,7 +155,7 @@ ESP8266_PIN_SCHEMA = cv.All( @dataclass class PinInitialState: - mode = 255 + mode: int = 255 level: int = 255 diff --git a/esphome/components/espnow/__init__.py b/esphome/components/espnow/__init__.py index 49b96eeb6f..a9624734d0 100644 --- a/esphome/components/espnow/__init__.py +++ b/esphome/components/espnow/__init__.py @@ -158,15 +158,15 @@ def validate_peer(value): def _validate_raw_data(value): if isinstance(value, str): - if len(value) >= MAX_ESPNOW_PACKET_SIZE: + if len(value) > MAX_ESPNOW_PACKET_SIZE: raise cv.Invalid( - f"'{CONF_DATA}' must be less than {MAX_ESPNOW_PACKET_SIZE} characters long, got {len(value)}" + f"'{CONF_DATA}' must be at most {MAX_ESPNOW_PACKET_SIZE} characters long, got {len(value)}" ) return value if isinstance(value, list): if len(value) > MAX_ESPNOW_PACKET_SIZE: raise cv.Invalid( - f"'{CONF_DATA}' must be less than {MAX_ESPNOW_PACKET_SIZE} bytes long, got {len(value)}" + f"'{CONF_DATA}' must be at most {MAX_ESPNOW_PACKET_SIZE} bytes long, got {len(value)}" ) return cv.Schema([cv.hex_uint8_t])(value) raise cv.Invalid( diff --git a/esphome/components/kamstrup_kmp/sensor.py b/esphome/components/kamstrup_kmp/sensor.py index fb37ac2c8d..134ac245bf 100644 --- a/esphome/components/kamstrup_kmp/sensor.py +++ b/esphome/components/kamstrup_kmp/sensor.py @@ -13,6 +13,7 @@ from esphome.const import ( DEVICE_CLASS_POWER, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLUME, + DEVICE_CLASS_VOLUME_FLOW_RATE, STATE_CLASS_MEASUREMENT, STATE_CLASS_TOTAL_INCREASING, UNIT_CELSIUS, @@ -75,7 +76,7 @@ CONFIG_SCHEMA = ( ), cv.Optional(CONF_FLOW): sensor.sensor_schema( accuracy_decimals=1, - device_class=DEVICE_CLASS_VOLUME, + device_class=DEVICE_CLASS_VOLUME_FLOW_RATE, state_class=STATE_CLASS_MEASUREMENT, unit_of_measurement=UNIT_LITRE_PER_HOUR, ), diff --git a/esphome/components/stepper/__init__.py b/esphome/components/stepper/__init__.py index 27d4fc276d..8acacc3b49 100644 --- a/esphome/components/stepper/__init__.py +++ b/esphome/components/stepper/__init__.py @@ -46,7 +46,7 @@ def validate_acceleration(value): def validate_speed(value): value = cv.string(value) - for suffix in ("steps/s", "steps/s"): + for suffix in ("steps/s",): value = value.removesuffix(suffix) if value == "inf": diff --git a/esphome/zeroconf.py b/esphome/zeroconf.py index dc4ca77eb4..dd45b58a6c 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -25,7 +25,7 @@ _BACKGROUND_TASKS: set[asyncio.Task] = set() class DashboardStatus: - def __init__(self, on_update: Callable[[dict[str, bool | None], []]]) -> None: + def __init__(self, on_update: Callable[[dict[str, bool | None]], None]) -> None: """Initialize the dashboard status.""" self.on_update = on_update From e62c78ad46dc41f231fbe258147387d2c5262ebb Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 21:41:57 -0400 Subject: [PATCH 1993/2030] [multiple] Fix misc cosmetic bugs (error messages, types, defaults) (#15499) --- esphome/components/binary_sensor/__init__.py | 2 +- esphome/components/lc709203f/sensor.py | 2 +- esphome/components/micro_wake_word/__init__.py | 2 +- esphome/components/rotary_encoder/sensor.py | 2 +- esphome/components/sprinkler/__init__.py | 2 +- esphome/components/st7789v/display.py | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 660f75ccd9..d8cdaa5d58 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -390,7 +390,7 @@ def validate_multi_click_timing(value): new_state = v_.get(CONF_STATE, not state) if new_state == state: raise cv.Invalid( - f"Timings must have alternating state. Indices {i} and {i + 1} have the same state {state}" + f"Timings must have alternating state. Indices {i - 1} and {i} have the same state {state}" ) if max_length is not None and max_length < min_length: raise cv.Invalid( diff --git a/esphome/components/lc709203f/sensor.py b/esphome/components/lc709203f/sensor.py index eb08a522e5..75ae703638 100644 --- a/esphome/components/lc709203f/sensor.py +++ b/esphome/components/lc709203f/sensor.py @@ -36,7 +36,7 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.GenerateID(): cv.declare_id(lc709203f), - cv.Optional(CONF_SIZE, default="500"): cv.int_range(100, 3000), + cv.Optional(CONF_SIZE, default=500): cv.int_range(100, 3000), cv.Optional(CONF_VOLTAGE, default="3.7"): cv.enum( BATTERY_VOLTAGE_OPTIONS, upper=True ), diff --git a/esphome/components/micro_wake_word/__init__.py b/esphome/components/micro_wake_word/__init__.py index fae48630b5..ff27dec6df 100644 --- a/esphome/components/micro_wake_word/__init__.py +++ b/esphome/components/micro_wake_word/__init__.py @@ -405,7 +405,7 @@ def _model_config_to_manifest_data(model_config): file = _compute_local_file_path(model_config) / "manifest.json" else: - raise ValueError("Unsupported config type: {model_config[CONF_TYPE]}") + raise ValueError(f"Unsupported config type: {model_config[CONF_TYPE]}") return _load_model_data(file) diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index fc4202556d..d88657e715 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -50,7 +50,7 @@ def validate_min_max_value(config): max_val = config[CONF_MAX_VALUE] if min_val >= max_val: raise cv.Invalid( - f"Max value {max_val} must be smaller than min value {min_val}" + f"Max value {max_val} must be greater than min value {min_val}" ) return config diff --git a/esphome/components/sprinkler/__init__.py b/esphome/components/sprinkler/__init__.py index 9dc695cafc..fb2beb5b16 100644 --- a/esphome/components/sprinkler/__init__.py +++ b/esphome/components/sprinkler/__init__.py @@ -272,7 +272,7 @@ SPRINKLER_VALVE_SCHEMA = cv.Schema( ), cv.Optional( CONF_UNIT_OF_MEASUREMENT, default=UNIT_SECOND - ): cv.one_of(UNIT_MINUTE, UNIT_SECOND, lower="True"), + ): cv.one_of(UNIT_MINUTE, UNIT_SECOND, lower=True), } ) .extend(cv.COMPONENT_SCHEMA), diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index c9f4199616..85414237cf 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -127,7 +127,7 @@ def validate_st7789v(config): if model_data[REQUIRE_PS] and CONF_POWER_SUPPLY not in config: raise cv.Invalid( - f'{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is {config[CONF_MODEL]}"' + f"{CONF_POWER_SUPPLY} must be specified when {CONF_MODEL} is {config[CONF_MODEL]}" ) if ( From 96c398648178086ceaf9f28c99e37acfaed227c8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 15:58:17 -1000 Subject: [PATCH 1994/2030] [core] Replace std::vector in CallbackManager with trivial-copy container (#15272) --- esphome/core/helpers.cpp | 13 ++++++++ esphome/core/helpers.h | 68 +++++++++++++++++++++++++++++++++------- 2 files changed, 69 insertions(+), 12 deletions(-) diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index 1732fc72e8..5940f6ec98 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -22,6 +22,19 @@ namespace esphome { static const char *const TAG = "helpers"; +__attribute__((noinline, cold)) void *callback_manager_grow(void *data, uint16_t size, uint16_t &capacity, + size_t elem_size) { + ESPHOME_DEBUG_ASSERT(size < UINT16_MAX); + uint16_t new_cap = size + 1; + auto *new_data = ::operator new(new_cap *elem_size); + if (data) { + __builtin_memcpy(new_data, data, size * elem_size); + ::operator delete(data); + } + capacity = new_cap; + return new_data; +} + static const uint16_t CRC16_A001_LE_LUT_L[] = {0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440}; static const uint16_t CRC16_A001_LE_LUT_H[] = {0x0000, 0xcc01, 0xd801, 0x1400, 0xf001, 0x3c00, 0x2800, 0xe401, diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index f96b888e28..c26bbe17b7 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -1801,33 +1801,77 @@ template<typename... Ts> struct Callback<void(Ts...)> { } }; +/// Grow a CallbackManager's backing array to exactly size+1. Defined in helpers.cpp. +void *callback_manager_grow(void *data, uint16_t size, uint16_t &capacity, size_t elem_size); + template<typename... X> class CallbackManager; /** Helper class to allow having multiple subscribers to a callback. + * + * Uses a trivial-copyable-specialized container instead of std::vector to avoid + * template bloat (_M_realloc_insert, exception-safe copies). Since Callback is + * trivially copyable (just {fn_ptr, ctx_ptr}), reallocation is a plain memcpy. + * Uses uint16_t for size/capacity (8 bytes on 32-bit vs 12 for std::vector). + * Grows to exact size on each add — callbacks are registered during setup() + * and most instances have only 1-2 callbacks, so slack capacity is wasteful. * * @tparam Ts The arguments for the callbacks, wrapped in void(). */ template<typename... Ts> class CallbackManager<void(Ts...)> { + using CbType = Callback<void(Ts...)>; + static_assert(std::is_trivially_copyable_v<CbType>, "Callback must be trivially copyable"); + public: + CallbackManager() = default; + ~CallbackManager() { ::operator delete(this->data_); } + + // Non-copyable (would alias data_), movable (for std::map support) + CallbackManager(const CallbackManager &) = delete; + CallbackManager &operator=(const CallbackManager &) = delete; + CallbackManager(CallbackManager &&other) noexcept + : data_(other.data_), size_(other.size_), capacity_(other.capacity_) { + other.data_ = nullptr; + other.size_ = 0; + other.capacity_ = 0; + } + CallbackManager &operator=(CallbackManager &&other) noexcept { + std::swap(this->data_, other.data_); + std::swap(this->size_, other.size_); + std::swap(this->capacity_, other.capacity_); + return *this; + } + /// Add any callable. Small trivially-copyable callables (like [this] lambdas) /// are stored inline without heap allocation or std::function. - template<typename F> void add(F &&callback) { this->add_(Callback<void(Ts...)>::create(std::forward<F>(callback))); } - - /// Call all callbacks in this manager. No null check on invoke. - void call(Ts... args) { - for (auto &cb : this->callbacks_) - cb.call(args...); - } - size_t size() const { return this->callbacks_.size(); } + template<typename F> void add(F &&callback) { this->add_(CbType::create(std::forward<F>(callback))); } /// Call all callbacks in this manager. - void operator()(Ts... args) { call(args...); } + inline void ESPHOME_ALWAYS_INLINE call(Ts... args) { + if (this->size_ != 0) { + for (auto *it = this->data_, *end = it + this->size_; it != end; ++it) { + it->call(args...); + } + } + } + uint16_t size() const { return this->size_; } + + /// Call all callbacks in this manager. + void operator()(Ts... args) { this->call(args...); } protected: template<typename...> friend class LazyCallbackManager; /// Non-template core to avoid code duplication per lambda type. - void add_(Callback<void(Ts...)> cb) { this->callbacks_.push_back(cb); } - std::vector<Callback<void(Ts...)>> callbacks_; + /// Inline fast path; cold growth path is in helpers.cpp via callback_manager_grow(). + void add_(CbType cb) { + if (this->size_ == this->capacity_) { + this->data_ = + static_cast<CbType *>(callback_manager_grow(this->data_, this->size_, this->capacity_, sizeof(CbType))); + } + this->data_[this->size_++] = cb; + } + CbType *data_{nullptr}; + uint16_t size_{0}; + uint16_t capacity_{0}; }; /** CallbackManager backed by StaticVector for compile-time-known callback counts. @@ -1871,7 +1915,7 @@ template<typename... X> class LazyCallbackManager; * from API and web_server components). * * Memory overhead comparison (32-bit systems): - * - CallbackManager: 12 bytes (empty std::vector) + * - CallbackManager: 8 bytes (pointer + uint16 size + uint16 capacity) * - LazyCallbackManager: 4 bytes (nullptr pointer) * * Uses plain pointer instead of unique_ptr to avoid template instantiation overhead. From 517d0390d0affbac28159910df9013f139d39347 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:17:25 -0400 Subject: [PATCH 1995/2030] [ota] Fix check_error skipping validation for RESPONSE_OK (#15501) --- esphome/espota2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/espota2.py b/esphome/espota2.py index 4b813e4060..39f51e02e9 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -130,7 +130,7 @@ def check_error(data: list[int] | bytes, expect: int | list[int] | None) -> None :param expect: Expected response code(s), None to skip validation. :raises OTAError: If an error code is detected or response doesn't match expected. """ - if not expect: + if expect is None: return if not data: raise OTAError( @@ -278,7 +278,7 @@ def perform_ota( raise OTAError("ESP requests password, but no password given!") nonce_bytes = receive_exactly( - sock, nonce_size, f"{hash_name} authentication nonce", [], decode=False + sock, nonce_size, f"{hash_name} authentication nonce", None, decode=False ) assert isinstance(nonce_bytes, bytes) nonce = nonce_bytes.decode() From 99ee405f4e427a639ed813bae611a9d42c12fe7d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 22:17:34 -0400 Subject: [PATCH 1996/2030] [esp32_ble][esp32_ble_server][esp32_ble_beacon] Fix UUID regex, IndexError, and unused inheritance (#15504) --- esphome/components/esp32_ble/__init__.py | 6 +++--- esphome/components/esp32_ble_beacon/__init__.py | 6 +----- .../components/esp32_ble_beacon/esp32_ble_beacon.h | 2 +- esphome/components/esp32_ble_server/__init__.py | 14 ++++++++++---- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/esphome/components/esp32_ble/__init__.py b/esphome/components/esp32_ble/__init__.py index 974611c9b1..79d05049bf 100644 --- a/esphome/components/esp32_ble/__init__.py +++ b/esphome/components/esp32_ble/__init__.py @@ -373,14 +373,14 @@ def bt_uuid(value): value = in_value.upper() if len(value) == len(bt_uuid16_format): - pattern = re.compile("^[A-F|0-9]{4,}$") + pattern = re.compile("^[A-F0-9]{4,}$") if not pattern.match(value): raise cv.Invalid( f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'" ) return value if len(value) == len(bt_uuid32_format): - pattern = re.compile("^[A-F|0-9]{8,}$") + pattern = re.compile("^[A-F0-9]{8,}$") if not pattern.match(value): raise cv.Invalid( f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'" @@ -388,7 +388,7 @@ def bt_uuid(value): return value if len(value) == len(bt_uuid128_format): pattern = re.compile( - "^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$" + "^[A-F0-9]{8,}-[A-F0-9]{4,}-[A-F0-9]{4,}-[A-F0-9]{4,}-[A-F0-9]{12,}$" ) if not pattern.match(value): raise cv.Invalid( diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index e2e790164e..8052c13596 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -10,11 +10,7 @@ AUTO_LOAD = ["esp32_ble"] DEPENDENCIES = ["esp32"] esp32_ble_beacon_ns = cg.esphome_ns.namespace("esp32_ble_beacon") -ESP32BLEBeacon = esp32_ble_beacon_ns.class_( - "ESP32BLEBeacon", - cg.Component, - cg.Parented.template(esp32_ble.ESP32BLE), -) +ESP32BLEBeacon = esp32_ble_beacon_ns.class_("ESP32BLEBeacon", cg.Component) CONF_MAJOR = "major" CONF_MINOR = "minor" CONF_MIN_INTERVAL = "min_interval" diff --git a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h index e16c413179..44a7133454 100644 --- a/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h +++ b/esphome/components/esp32_ble_beacon/esp32_ble_beacon.h @@ -35,7 +35,7 @@ using esp_ble_ibeacon_t = struct { using namespace esp32_ble; -class ESP32BLEBeacon : public Component, public Parented<ESP32BLE> { +class ESP32BLEBeacon : public Component { public: explicit ESP32BLEBeacon(const std::array<uint8_t, 16> &uuid) : uuid_(uuid) {} diff --git a/esphome/components/esp32_ble_server/__init__.py b/esphome/components/esp32_ble_server/__init__.py index 57106cd93b..7bf3092a4e 100644 --- a/esphome/components/esp32_ble_server/__init__.py +++ b/esphome/components/esp32_ble_server/__init__.py @@ -307,24 +307,30 @@ def final_validate_config(config): # Check if all characteristics that require notifications have the notify property set for char_id in CORE.data.get(DOMAIN, {}).get(KEY_NOTIFY_REQUIRED, set()): # Look for the characteristic in the configuration - char_config = [ + matches = [ char_conf for service_conf in config[CONF_SERVICES] for char_conf in service_conf[CONF_CHARACTERISTICS] if char_conf[CONF_ID] == char_id - ][0] + ] + if not matches: + continue + char_config = matches[0] if not char_config[CONF_NOTIFY]: raise cv.Invalid( f"Characteristic {char_config[CONF_UUID]} has notify actions and the {CONF_NOTIFY} property is not set" ) for char_id in CORE.data.get(DOMAIN, {}).get(KEY_SET_VALUE, set()): # Look for the characteristic in the configuration - char_config = [ + matches = [ char_conf for service_conf in config[CONF_SERVICES] for char_conf in service_conf[CONF_CHARACTERISTICS] if char_conf[CONF_ID] == char_id - ][0] + ] + if not matches: + continue + char_config = matches[0] if isinstance(char_config.get(CONF_VALUE, {}).get(CONF_DATA), cv.Lambda): raise cv.Invalid( f"Characteristic {char_config[CONF_UUID]} has both a set_value action and a templated value" From 9894bdc0f1ee40f33537d31e10ed63a1f2cc4a0d Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 23:03:57 -0400 Subject: [PATCH 1997/2030] [multiple] Fix misc low-priority bugs (batch 3) (#15506) --- esphome/components/display_menu_base/__init__.py | 2 +- esphome/components/ens160_base/__init__.py | 1 - esphome/components/font/__init__.py | 2 +- esphome/components/shelly_dimmer/light.py | 4 ++-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/esphome/components/display_menu_base/__init__.py b/esphome/components/display_menu_base/__init__.py index c9a0c7ee93..9125c43f0c 100644 --- a/esphome/components/display_menu_base/__init__.py +++ b/esphome/components/display_menu_base/__init__.py @@ -119,7 +119,7 @@ DisplayMenuOnPrevTrigger = display_menu_base_ns.class_( def validate_format(format): - if re.search(r"^%([+-])*(\d+)*(\.\d+)*[fg]$", format) is None: + if re.search(r"^%[+-]*(\d+)?(\.\d+)?[fg]$", format) is None: raise cv.Invalid( f"{CONF_FORMAT}: has to specify a printf-like format string specifying exactly one f or g type conversion, '{format}' provided" ) diff --git a/esphome/components/ens160_base/__init__.py b/esphome/components/ens160_base/__init__.py index 3b6ad8a4ee..46c53c3b10 100644 --- a/esphome/components/ens160_base/__init__.py +++ b/esphome/components/ens160_base/__init__.py @@ -24,7 +24,6 @@ CODEOWNERS = ["@vincentscode", "@latonita"] ens160_ns = cg.esphome_ns.namespace("ens160_base") CONF_AQI = "aqi" -UNIT_INDEX = "index" CONFIG_SCHEMA_BASE = cv.Schema( { diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index c8813bf1bc..a1339a4bc1 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -238,7 +238,7 @@ def validate_font_config(config): return config -FONT_EXTENSIONS = (".ttf", ".woff", ".otf", "bdf", ".pcf") +FONT_EXTENSIONS = (".ttf", ".woff", ".otf", ".bdf", ".pcf") def validate_truetype_file(value): diff --git a/esphome/components/shelly_dimmer/light.py b/esphome/components/shelly_dimmer/light.py index c1e9cad358..1688f9d6a6 100644 --- a/esphome/components/shelly_dimmer/light.py +++ b/esphome/components/shelly_dimmer/light.py @@ -67,7 +67,7 @@ KNOWN_FIRMWARE = { def parse_firmware_version(value): - match = re.match(r"(\d+).(\d+)", value) + match = re.fullmatch(r"(\d+)\.(\d+)", value) if match is None: raise ValueError(f"Not a valid version number {value}") major = int(match[1]) @@ -129,7 +129,7 @@ def validate_firmware(value): def validate_sha256(value): value = cv.string(value) - if not value.isalnum() or not len(value) == 64: + if not re.fullmatch(r"[0-9a-fA-F]{64}", value): raise ValueError(f"Not a valid SHA256 hex string: {value}") return value From b6ef1a58fb0c92dcc93388ab816cc6cd76b879af Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 23:17:35 -0400 Subject: [PATCH 1998/2030] [multiple] Fix validation ranges and error messages (#15508) --- esphome/components/bmp581_spi/sensor.py | 2 +- esphome/components/mcp23s08/__init__.py | 2 +- esphome/components/mcp23s17/__init__.py | 2 +- esphome/components/pcd8544/display.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esphome/components/bmp581_spi/sensor.py b/esphome/components/bmp581_spi/sensor.py index 75f60b2460..db0d0cd529 100644 --- a/esphome/components/bmp581_spi/sensor.py +++ b/esphome/components/bmp581_spi/sensor.py @@ -31,7 +31,7 @@ BMP581SPIComponent = bmp581_ns.class_( def check_spi_mode(config): spi_mode = config.get(CONF_SPI_MODE) if spi_mode not in VALID_SPI_MODES: - raise cv.Invalid("BMP581 only supports SPI mode 3") + raise cv.Invalid("BMP581 only supports SPI mode 0 or mode 3") return config diff --git a/esphome/components/mcp23s08/__init__.py b/esphome/components/mcp23s08/__init__.py index 3d4e304f9b..312da79b75 100644 --- a/esphome/components/mcp23s08/__init__.py +++ b/esphome/components/mcp23s08/__init__.py @@ -18,7 +18,7 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.Required(CONF_ID): cv.declare_id(mcp23S08), - cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, + cv.Optional(CONF_DEVICEADDRESS, default=0): cv.int_range(min=0, max=3), } ) .extend(mcp23xxx_base.MCP23XXX_CONFIG_SCHEMA) diff --git a/esphome/components/mcp23s17/__init__.py b/esphome/components/mcp23s17/__init__.py index ea8433af2e..599bfa0851 100644 --- a/esphome/components/mcp23s17/__init__.py +++ b/esphome/components/mcp23s17/__init__.py @@ -18,7 +18,7 @@ CONFIG_SCHEMA = ( cv.Schema( { cv.Required(CONF_ID): cv.declare_id(mcp23S17), - cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, + cv.Optional(CONF_DEVICEADDRESS, default=0): cv.int_range(min=0, max=7), } ) .extend(mcp23xxx_base.MCP23XXX_CONFIG_SCHEMA) diff --git a/esphome/components/pcd8544/display.py b/esphome/components/pcd8544/display.py index 9d993c2105..2f6dcc56ed 100644 --- a/esphome/components/pcd8544/display.py +++ b/esphome/components/pcd8544/display.py @@ -27,7 +27,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, # CE - cv.Optional(CONF_CONTRAST, default=0x7F): cv.int_, + cv.Optional(CONF_CONTRAST, default=0x7F): cv.int_range(min=0, max=127), } ) .extend(cv.polling_component_schema("1s")) From 10b38e158844120956b7eba6caff8c980eafe43d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 17:31:01 -1000 Subject: [PATCH 1999/2030] [api] Add max_data_length proto option and optimize entity name/object_id (#15426) --- esphome/components/api/api.proto | 180 ++++++------ esphome/components/api/api_options.proto | 6 + esphome/components/api/api_pb2.cpp | 274 +++++++++---------- esphome/components/api/proto.h | 13 + esphome/components/number/__init__.py | 7 +- esphome/components/sensor/__init__.py | 7 +- esphome/core/config.py | 3 + esphome/core/entity_helpers.py | 11 +- script/api_protobuf/api_protobuf.py | 34 ++- tests/unit_tests/core/test_entity_helpers.py | 17 ++ 10 files changed, 321 insertions(+), 231 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 1e03675999..07705baff6 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -308,6 +308,12 @@ enum EntityCategory { ENTITY_CATEGORY_DIAGNOSTIC = 2; } +// Entity field max_data_length values match Python validation constants: +// name/object_id = 120 (config_validation.NAME_MAX_LENGTH) +// icon = 63 (core/config.ICON_MAX_LENGTH) +// device_class = 47 (core/config.DEVICE_CLASS_MAX_LENGTH) +// unit_of_measurement = 63 (core/config.UNIT_OF_MEASUREMENT_MAX_LENGTH) + // ==================== BINARY SENSOR ==================== message ListEntitiesBinarySensorResponse { option (id) = 12; @@ -315,15 +321,15 @@ message ListEntitiesBinarySensorResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_BINARY_SENSOR"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string device_class = 5; + string device_class = 5 [(max_data_length) = 47]; bool is_status_binary_sensor = 6; bool disabled_by_default = 7; - string icon = 8 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 8 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 9; uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"]; } @@ -349,17 +355,17 @@ message ListEntitiesCoverResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_COVER"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id bool assumed_state = 5; bool supports_position = 6; bool supports_tilt = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; bool disabled_by_default = 9; - string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 11; bool supports_stop = 12; uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"]; @@ -433,9 +439,9 @@ message ListEntitiesFanResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_FAN"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id bool supports_oscillation = 5; @@ -443,7 +449,7 @@ message ListEntitiesFanResponse { bool supports_direction = 7; int32 supported_speed_count = 8; bool disabled_by_default = 9; - string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 10 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 11; repeated string supported_preset_modes = 12 [(container_pointer_no_template) = "std::vector<const char *>"]; uint32 device_id = 13 [(field_ifdef) = "USE_DEVICES"]; @@ -521,9 +527,9 @@ message ListEntitiesLightResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_LIGHT"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"]; @@ -540,7 +546,7 @@ message ListEntitiesLightResponse { float max_mireds = 10; repeated string effects = 11 [(container_pointer_no_template) = "FixedVector<const char *>"]; bool disabled_by_default = 13; - string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 14 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 15; uint32 device_id = 16 [(field_ifdef) = "USE_DEVICES"]; } @@ -626,16 +632,16 @@ message ListEntitiesSensorResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_SENSOR"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; - string unit_of_measurement = 6; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; + string unit_of_measurement = 6 [(max_data_length) = 63]; int32 accuracy_decimals = 7; bool force_update = 8; - string device_class = 9; + string device_class = 9 [(max_data_length) = 47]; SensorStateClass state_class = 10; // Last reset type removed in 2021.9.0 // Deprecated in API version 1.5 @@ -666,16 +672,16 @@ message ListEntitiesSwitchResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_SWITCH"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool assumed_state = 6; bool disabled_by_default = 7; EntityCategory entity_category = 8; - string device_class = 9; + string device_class = 9 [(max_data_length) = 47]; uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"]; } message SwitchStateResponse { @@ -708,15 +714,15 @@ message ListEntitiesTextSensorResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_TEXT_SENSOR"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"]; } message TextSensorStateResponse { @@ -971,12 +977,12 @@ message ListEntitiesCameraResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_CAMERA"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id bool disabled_by_default = 5; - string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 7; uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"]; } @@ -1056,9 +1062,9 @@ message ListEntitiesClimateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_CLIMATE"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id bool supports_current_temperature = 5; // Deprecated: use feature_flags @@ -1078,7 +1084,7 @@ message ListEntitiesClimateResponse { repeated ClimatePreset supported_presets = 16 [(container_pointer_no_template) = "climate::ClimatePresetMask"]; repeated string supported_custom_presets = 17 [(container_pointer_no_template) = "std::vector<const char *>"]; bool disabled_by_default = 18; - string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 19 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; EntityCategory entity_category = 20; float visual_current_temperature_step = 21; bool supports_current_humidity = 22; // Deprecated: use feature_flags @@ -1167,10 +1173,10 @@ message ListEntitiesWaterHeaterResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_WATER_HEATER"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; - string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"]; + string name = 3 [(max_data_length) = 120, (force) = true]; + string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 5; EntityCategory entity_category = 6; uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"]; @@ -1243,20 +1249,20 @@ message ListEntitiesNumberResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_NUMBER"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; float min_value = 6; float max_value = 7; float step = 8; bool disabled_by_default = 9; EntityCategory entity_category = 10; - string unit_of_measurement = 11; + string unit_of_measurement = 11 [(max_data_length) = 63]; NumberMode mode = 12; - string device_class = 13; + string device_class = 13 [(max_data_length) = 47]; uint32 device_id = 14 [(field_ifdef) = "USE_DEVICES"]; } message NumberStateResponse { @@ -1292,12 +1298,12 @@ message ListEntitiesSelectResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_SELECT"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; repeated string options = 6 [(container_pointer_no_template) = "FixedVector<const char *>"]; bool disabled_by_default = 7; EntityCategory entity_category = 8; @@ -1336,12 +1342,12 @@ message ListEntitiesSirenResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_SIREN"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; repeated string tones = 7 [(container_pointer_no_template) = "FixedVector<const char *>"]; bool supports_duration = 8; @@ -1399,12 +1405,12 @@ message ListEntitiesLockResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_LOCK"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; bool assumed_state = 8; @@ -1448,15 +1454,15 @@ message ListEntitiesButtonResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_BUTTON"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"]; } message ButtonCommandRequest { @@ -1515,12 +1521,12 @@ message ListEntitiesMediaPlayerResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_MEDIA_PLAYER"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; @@ -2103,11 +2109,11 @@ message ListEntitiesAlarmControlPanelResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_ALARM_CONTROL_PANEL"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; uint32 supported_features = 8; @@ -2150,11 +2156,11 @@ message ListEntitiesTextResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_TEXT"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; @@ -2198,12 +2204,12 @@ message ListEntitiesDateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_DATETIME_DATE"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"]; @@ -2245,12 +2251,12 @@ message ListEntitiesTimeResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_DATETIME_TIME"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"]; @@ -2292,15 +2298,15 @@ message ListEntitiesEventResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_EVENT"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; repeated string event_types = 9 [(container_pointer_no_template) = "FixedVector<const char *>"]; uint32 device_id = 10 [(field_ifdef) = "USE_DEVICES"]; @@ -2323,15 +2329,15 @@ message ListEntitiesValveResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_VALVE"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; bool assumed_state = 9; bool supports_position = 10; @@ -2378,12 +2384,12 @@ message ListEntitiesDateTimeResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_DATETIME_DATETIME"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; uint32 device_id = 8 [(field_ifdef) = "USE_DEVICES"]; @@ -2421,15 +2427,15 @@ message ListEntitiesUpdateResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_UPDATE"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; + string name = 3 [(max_data_length) = 120, (force) = true]; reserved 4; // Deprecated: was string unique_id - string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON"]; + string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 6; EntityCategory entity_category = 7; - string device_class = 8; + string device_class = 8 [(max_data_length) = 47]; uint32 device_id = 9 [(field_ifdef) = "USE_DEVICES"]; } message UpdateStateResponse { @@ -2504,10 +2510,10 @@ message ListEntitiesInfraredResponse { option (source) = SOURCE_SERVER; option (ifdef) = "USE_INFRARED"; - string object_id = 1; + string object_id = 1 [(max_data_length) = 120, (force) = true]; fixed32 key = 2 [(force) = true]; - string name = 3; - string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON"]; + string name = 3 [(max_data_length) = 120, (force) = true]; + string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63]; bool disabled_by_default = 5; EntityCategory entity_category = 6; uint32 device_id = 7 [(field_ifdef) = "USE_DEVICES"]; diff --git a/esphome/components/api/api_options.proto b/esphome/components/api/api_options.proto index 0aa9e814cf..0f71268d70 100644 --- a/esphome/components/api/api_options.proto +++ b/esphome/components/api/api_options.proto @@ -102,4 +102,10 @@ extend google.protobuf.FieldOptions { // and direct byte writes instead of varint branching, since the encoded varint // is guaranteed to be 1 byte. optional uint32 max_value = 50017; + + // max_data_length: Maximum length of a string or bytes field. + // When max_data_length < 128, the code generator emits constant-size + // length varint calculations and direct byte writes, since the length + // varint is guaranteed to be 1 byte. + optional uint32 max_data_length = 50018; } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index ba9ebd1f40..f7c68b95a7 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -218,9 +218,9 @@ uint32_t DeviceInfoResponse::calculate_size() const { #ifdef USE_BINARY_SENSOR uint8_t *ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_class); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->is_status_binary_sensor); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); @@ -235,14 +235,14 @@ uint8_t *ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer PROTO } uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); - size += ProtoSize::calc_length(1, this->device_class.size()); + size += 2 + this->name.size(); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; size += ProtoSize::calc_bool(1, this->is_status_binary_sensor); size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES @@ -274,9 +274,9 @@ uint32_t BinarySensorStateResponse::calculate_size() const { #ifdef USE_COVER uint8_t *ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->assumed_state); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_position); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_tilt); @@ -294,16 +294,16 @@ uint8_t *ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE } uint32_t ListEntitiesCoverResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->supports_position); size += ProtoSize::calc_bool(1, this->supports_tilt); - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += this->entity_category ? 2 : 0; size += ProtoSize::calc_bool(1, this->supports_stop); @@ -375,9 +375,9 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_FAN uint8_t *ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_oscillation); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_speed); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_direction); @@ -397,16 +397,16 @@ uint8_t *ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_D } uint32_t ListEntitiesFanResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); size += ProtoSize::calc_bool(1, this->supports_oscillation); size += ProtoSize::calc_bool(1, this->supports_speed); size += ProtoSize::calc_bool(1, this->supports_direction); size += ProtoSize::calc_int32(1, this->supported_speed_count); size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += this->entity_category ? 2 : 0; if (!this->supported_preset_modes->empty()) { @@ -509,9 +509,9 @@ bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LIGHT uint8_t *ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); for (const auto &it : *this->supported_color_modes) { ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it), true); } @@ -532,9 +532,9 @@ uint8_t *ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE } uint32_t ListEntitiesLightResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); if (!this->supported_color_modes->empty()) { size += this->supported_color_modes->size() * 2; } @@ -547,7 +547,7 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { } size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES @@ -707,9 +707,9 @@ bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SENSOR uint8_t *ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -727,16 +727,16 @@ uint8_t *ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesSensorResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif - size += ProtoSize::calc_length(1, this->unit_of_measurement.size()); + size += !this->unit_of_measurement.empty() ? 2 + this->unit_of_measurement.size() : 0; size += ProtoSize::calc_int32(1, this->accuracy_decimals); size += ProtoSize::calc_bool(1, this->force_update); - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; size += this->state_class ? 2 : 0; size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -769,9 +769,9 @@ uint32_t SensorStateResponse::calculate_size() const { #ifdef USE_SWITCH uint8_t *ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -786,16 +786,16 @@ uint8_t *ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesSwitchResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -848,9 +848,9 @@ bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_TEXT_SENSOR uint8_t *ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -864,15 +864,15 @@ uint8_t *ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_E } uint32_t ListEntitiesTextSensorResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1323,9 +1323,9 @@ uint32_t ExecuteServiceResponse::calculate_size() const { #ifdef USE_CAMERA uint8_t *ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->icon); @@ -1338,12 +1338,12 @@ uint8_t *ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesCameraResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); size += ProtoSize::calc_bool(1, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += this->entity_category ? 2 : 0; #ifdef USE_DEVICES @@ -1388,9 +1388,9 @@ bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t v #ifdef USE_CLIMATE uint8_t *ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_current_temperature); ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_two_point_target_temperature); for (const auto &it : *this->supported_modes) { @@ -1433,9 +1433,9 @@ uint8_t *ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCO } uint32_t ListEntitiesClimateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); size += ProtoSize::calc_bool(1, this->supports_current_temperature); size += ProtoSize::calc_bool(1, this->supports_two_point_target_temperature); if (!this->supported_modes->empty()) { @@ -1466,7 +1466,7 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { } size += ProtoSize::calc_bool(2, this->disabled_by_default); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(2, this->icon.size()); + size += !this->icon.empty() ? 3 + this->icon.size() : 0; #endif size += this->entity_category ? 3 : 0; size += ProtoSize::calc_float(2, this->visual_current_temperature_step); @@ -1617,9 +1617,9 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_WATER_HEATER uint8_t *ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif @@ -1639,11 +1639,11 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer PROTO_ } uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -1731,9 +1731,9 @@ bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value #ifdef USE_NUMBER uint8_t *ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -1752,20 +1752,20 @@ uint8_t *ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesNumberResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_float(1, this->min_value); size += ProtoSize::calc_float(1, this->max_value); size += ProtoSize::calc_float(1, this->step); size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->unit_of_measurement.size()); + size += !this->unit_of_measurement.empty() ? 2 + this->unit_of_measurement.size() : 0; size += this->mode ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -1820,9 +1820,9 @@ bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SELECT uint8_t *ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -1838,11 +1838,11 @@ uint8_t *ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesSelectResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif if (!this->options->empty()) { for (const char *it : *this->options) { @@ -1913,9 +1913,9 @@ bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SIREN uint8_t *ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -1933,11 +1933,11 @@ uint8_t *ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE } uint32_t ListEntitiesSirenResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); if (!this->tones->empty()) { @@ -2029,9 +2029,9 @@ bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LOCK uint8_t *ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -2048,11 +2048,11 @@ uint8_t *ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_ } uint32_t ListEntitiesLockResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -2126,9 +2126,9 @@ bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_BUTTON uint8_t *ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -2142,15 +2142,15 @@ uint8_t *ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesButtonResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -2200,9 +2200,9 @@ uint32_t MediaPlayerSupportedFormat::calculate_size() const { } uint8_t *ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -2220,11 +2220,11 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer PROTO_ } uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3079,9 +3079,9 @@ bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengt #ifdef USE_ALARM_CONTROL_PANEL uint8_t *ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3097,11 +3097,11 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer } uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3171,9 +3171,9 @@ bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit #ifdef USE_TEXT uint8_t *ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3190,11 +3190,11 @@ uint8_t *ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_ } uint32_t ListEntitiesTextResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3264,9 +3264,9 @@ bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATE uint8_t *ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3279,11 +3279,11 @@ uint8_t *ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_ } uint32_t ListEntitiesDateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3351,9 +3351,9 @@ bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_TIME uint8_t *ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3366,11 +3366,11 @@ uint8_t *ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_ } uint32_t ListEntitiesTimeResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3438,9 +3438,9 @@ bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_EVENT uint8_t *ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3457,15 +3457,15 @@ uint8_t *ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE } uint32_t ListEntitiesEventResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; if (!this->event_types->empty()) { for (const char *it : *this->event_types) { size += ProtoSize::calc_length_force(1, strlen(it)); @@ -3498,9 +3498,9 @@ uint32_t EventResponse::calculate_size() const { #ifdef USE_VALVE uint8_t *ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3517,15 +3517,15 @@ uint8_t *ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE } uint32_t ListEntitiesValveResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; size += ProtoSize::calc_bool(1, this->assumed_state); size += ProtoSize::calc_bool(1, this->supports_position); size += ProtoSize::calc_bool(1, this->supports_stop); @@ -3589,9 +3589,9 @@ bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATETIME uint8_t *ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3604,11 +3604,11 @@ uint8_t *ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENC } uint32_t ListEntitiesDateTimeResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; @@ -3666,9 +3666,9 @@ bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_UPDATE uint8_t *ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif @@ -3682,15 +3682,15 @@ uint8_t *ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCOD } uint32_t ListEntitiesUpdateResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; - size += ProtoSize::calc_length(1, this->device_class.size()); + size += !this->device_class.empty() ? 2 + this->device_class.size() : 0; #ifdef USE_DEVICES size += ProtoSize::calc_uint32(1, this->device_id); #endif @@ -3817,9 +3817,9 @@ uint32_t ZWaveProxyRequest::calculate_size() const { #ifdef USE_INFRARED uint8_t *ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->object_id); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif @@ -3834,11 +3834,11 @@ uint8_t *ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer PROTO_ENC } uint32_t ListEntitiesInfraredResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->object_id.size()); + size += 2 + this->object_id.size(); size += 5; - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); #ifdef USE_ENTITY_ICON - size += ProtoSize::calc_length(1, this->icon.size()); + size += !this->icon.empty() ? 2 + this->icon.size() : 0; #endif size += ProtoSize::calc_bool(1, this->disabled_by_default); size += this->entity_category ? 2 : 0; diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 48da1f2226..ff7c5232b6 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -359,6 +359,19 @@ class ProtoEncode { std::memcpy(pos, data, len); pos += len; } + /// Encode tag + 1-byte length + raw string data. For strings with max_data_length < 128. + /// Tag must be a single-byte varint (< 128). Always encodes (no zero check). + static inline void encode_short_string_force(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, + const StringRef &ref) { +#ifdef ESPHOME_DEBUG_API + assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128"); +#endif + PROTO_ENCODE_CHECK_BOUNDS(pos, 2 + ref.size()); + pos[0] = tag; + pos[1] = static_cast<uint8_t>(ref.size()); + std::memcpy(pos + 2, ref.c_str(), ref.size()); + pos += 2 + ref.size(); + } /// Write a precomputed tag byte + 32-bit value in one operation. static inline void ESPHOME_ALWAYS_INLINE write_tag_and_fixed32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, uint32_t value) { diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 90f9fe1835..26d2602ba4 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -79,6 +79,7 @@ from esphome.const import ( DEVICE_CLASS_WIND_SPEED, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH from esphome.core.entity_helpers import ( entity_duplicate_validator, setup_device_class, @@ -186,7 +187,11 @@ NUMBER_OPERATION_OPTIONS = { } validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") -validate_unit_of_measurement = cv.string_strict +validate_unit_of_measurement = cv.All( + cv.string_strict, + # Keep in sync with max_data_length in api.proto + cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), +) _NUMBER_SCHEMA = ( cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 626466eefa..275c4542fb 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -106,6 +106,7 @@ from esphome.const import ( ENTITY_CATEGORY_CONFIG, ) from esphome.core import CORE, CoroPriority, coroutine_with_priority +from esphome.core.config import UNIT_OF_MEASUREMENT_MAX_LENGTH from esphome.core.entity_helpers import ( entity_duplicate_validator, setup_device_class, @@ -290,7 +291,11 @@ ClampFilter = sensor_ns.class_("ClampFilter", Filter) RoundFilter = sensor_ns.class_("RoundFilter", Filter) RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter) -validate_unit_of_measurement = cv.string_strict +validate_unit_of_measurement = cv.All( + cv.string_strict, + # Keep in sync with max_data_length in api.proto + cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), +) validate_accuracy_decimals = cv.int_ validate_icon = cv.icon validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") diff --git a/esphome/core/config.py b/esphome/core/config.py index 62c41b254c..31cfd00ef7 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -233,6 +233,9 @@ DEVICE_CLASS_MAX_LENGTH = 47 # Keep in sync with MAX_ICON_LENGTH in esphome/core/entity_base.h ICON_MAX_LENGTH = 63 +# Max unit of measurement string length +UNIT_OF_MEASUREMENT_MAX_LENGTH = 63 + AREA_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Area), diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index 0589b92364..fc931c2baa 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -17,7 +17,11 @@ from esphome.const import ( CONF_UNIT_OF_MEASUREMENT, ) from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority -from esphome.core.config import DEVICE_CLASS_MAX_LENGTH, ICON_MAX_LENGTH +from esphome.core.config import ( + DEVICE_CLASS_MAX_LENGTH, + ICON_MAX_LENGTH, + UNIT_OF_MEASUREMENT_MAX_LENGTH, +) from esphome.cpp_generator import MockObj, RawStatement, add, get_variable import esphome.final_validate as fv from esphome.helpers import cpp_string_escape, fnv1_hash_object_id, sanitize, snake_case @@ -200,6 +204,11 @@ def register_device_class(value: str) -> int: def register_unit_of_measurement(value: str) -> int: """Register a unit_of_measurement string and return its 1-based index.""" + if value and len(value) > UNIT_OF_MEASUREMENT_MAX_LENGTH: + raise ValueError( + f"Unit of measurement string too long ({len(value)} chars, " + f"max {UNIT_OF_MEASUREMENT_MAX_LENGTH}): '{value}'" + ) return _register_string(value, _get_pool().units, _MAX_UNITS, "unit_of_measurement") diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 6de5c2b1c7..526644842d 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -165,6 +165,11 @@ class TypeInfo(ABC): """Get the max_value option for this field, or None if not set.""" return get_field_opt(self._field, pb.max_value, None) + @property + def max_data_length(self) -> int | None: + """Get the max_data_length option for this field, or None if not set.""" + return get_field_opt(self._field, pb.max_data_length, None) + @property def wire_type(self) -> WireType: """Get the wire type for the field.""" @@ -373,7 +378,11 @@ class TypeInfo(ABC): return f"size += ProtoSize::{method}({field_id_size}, {value});" def _get_single_byte_varint_size( - self, name: str, force: bool, extra_expr: str | None = None + self, + name: str, + force: bool, + extra_expr: str | None = None, + zero_check: str | None = None, ) -> str: """Size calculation when the varint is guaranteed to be 1 byte. @@ -384,12 +393,14 @@ class TypeInfo(ABC): name: Expression to check for zero (non-force only) force: Whether to skip the zero check extra_expr: Additional variable expression to add (e.g., data length) + zero_check: Override expression for the zero check (e.g., "!x.empty()") """ fixed = self.calculate_field_id_size() + 1 size_expr = f"{fixed} + {extra_expr}" if extra_expr else str(fixed) if force: return f"size += {size_expr};" - return f"size += {name} ? {size_expr} : 0;" + check = zero_check or name + return f"size += {check} ? {size_expr} : 0;" @abstractmethod def get_size_calculation(self, name: str, force: bool = False) -> str: @@ -1065,8 +1076,14 @@ class PointerToStringBufferType(PointerToBufferTypeBase): @property def encode_content(self) -> str: + max_len = self.max_data_length + if max_len is not None and max_len < 128 and self.force: + tag = self.calculate_tag() + if tag < 128: + return f"ProtoEncode::encode_short_string_force(pos, {tag}, this->{self.field_name});" if result := self._encode_bytes_with_precomputed_tag( - f"this->{self.field_name}.c_str()", f"this->{self.field_name}.size()" + f"this->{self.field_name}.c_str()", + f"this->{self.field_name}.size()", ): return result if self.force: @@ -1091,7 +1108,16 @@ class PointerToStringBufferType(PointerToBufferTypeBase): return f'dump_field(out, ESPHOME_PSTR("{self.name}"), this->{self.field_name});' def get_size_calculation(self, name: str, force: bool = False) -> str: - return f"size += ProtoSize::calc_length({self.calculate_field_id_size()}, this->{self.field_name}.size());" + size_field = f"this->{self.field_name}.size()" + max_len = self.max_data_length + if max_len is not None and max_len < 128: + return self._get_single_byte_varint_size( + size_field, + force, + extra_expr=size_field, + zero_check=f"!this->{self.field_name}.empty()", + ) + return self._get_simple_size_calculation(size_field, force, "length") def get_estimated_size(self) -> int: return self.calculate_field_id_size() + 8 # field ID + 8 bytes typical string diff --git a/tests/unit_tests/core/test_entity_helpers.py b/tests/unit_tests/core/test_entity_helpers.py index d6cbb8c6be..e79ff850f9 100644 --- a/tests/unit_tests/core/test_entity_helpers.py +++ b/tests/unit_tests/core/test_entity_helpers.py @@ -28,6 +28,7 @@ from esphome.core.entity_helpers import ( get_base_entity_object_id, register_device_class, register_icon, + register_unit_of_measurement, setup_device_class, setup_entity, setup_unit_of_measurement, @@ -925,6 +926,22 @@ def test_register_device_class_max_length() -> None: assert register_device_class("") == 0 +def test_register_unit_of_measurement_max_length() -> None: + """Test register_unit_of_measurement rejects units exceeding 63 characters.""" + # 63 chars should succeed + max_uom = "a" * 63 + idx = register_unit_of_measurement(max_uom) + assert idx > 0 + + # 64 chars should fail + too_long = "a" * 64 + with pytest.raises(ValueError, match="Unit of measurement string too long"): + register_unit_of_measurement(too_long) + + # Empty string returns 0 + assert register_unit_of_measurement("") == 0 + + @pytest.mark.asyncio async def test_setup_entity_with_entity_category( setup_test_environment: list[str], From e49384cd573b5ddf29947d18433eafbd05d388c8 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Mon, 6 Apr 2026 23:42:39 -0400 Subject: [PATCH 2000/2030] [dfrobot_sen0395] Fix list.index() on mutated list in range validator (#15511) --- esphome/components/dfrobot_sen0395/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/dfrobot_sen0395/__init__.py b/esphome/components/dfrobot_sen0395/__init__.py index ba77e56abb..0becaf3543 100644 --- a/esphome/components/dfrobot_sen0395/__init__.py +++ b/esphome/components/dfrobot_sen0395/__init__.py @@ -97,7 +97,7 @@ def range_segment_list(input): ) largest_distance = -1 - for distance in input: + for i, distance in enumerate(input): if isinstance(distance, cv.Lambda): continue m = cv.distance(distance) @@ -112,7 +112,7 @@ def range_segment_list(input): ) largest_distance = m # Replace distance object with meters float - input[input.index(distance)] = m + input[i] = m return input From f94e1dfab6c6a4890aedf6c203dd8f26591ac919 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Mon, 6 Apr 2026 18:12:01 -1000 Subject: [PATCH 2001/2030] [core] Move ControllerRegistry notify methods inline into header (#15505) --- esphome/core/controller_registry.cpp | 110 ------------------------- esphome/core/controller_registry.h | 117 +++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 110 deletions(-) diff --git a/esphome/core/controller_registry.cpp b/esphome/core/controller_registry.cpp index dd69de47d4..92f23f5642 100644 --- a/esphome/core/controller_registry.cpp +++ b/esphome/core/controller_registry.cpp @@ -2,122 +2,12 @@ #ifdef USE_CONTROLLER_REGISTRY -#include "esphome/core/controller.h" - namespace esphome { StaticVector<Controller *, CONTROLLER_REGISTRY_MAX> ControllerRegistry::controllers; void ControllerRegistry::register_controller(Controller *controller) { controllers.push_back(controller); } -// Each notify method directly iterates controllers and calls the virtual method. -// This avoids the overhead of a shared noinline dispatch loop with function pointer -// indirection. The loop is tiny (~20 bytes per entity type) so the flash cost of -// duplicating it is negligible compared to eliminating two levels of indirection -// (noinline call + function pointer) from every state publish. -// NOLINTBEGIN(bugprone-macro-parentheses) -#define CONTROLLER_REGISTRY_NOTIFY(entity_type, entity_name) \ - void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { \ - for (auto *controller : controllers) { \ - controller->on_##entity_name##_update(obj); \ - } \ - } - -#define CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(entity_type, entity_name) \ - void ControllerRegistry::notify_##entity_name(entity_type *obj) { \ - for (auto *controller : controllers) { \ - controller->on_##entity_name(obj); \ - } \ - } -// NOLINTEND(bugprone-macro-parentheses) - -#ifdef USE_BINARY_SENSOR -CONTROLLER_REGISTRY_NOTIFY(binary_sensor::BinarySensor, binary_sensor) -#endif - -#ifdef USE_FAN -CONTROLLER_REGISTRY_NOTIFY(fan::Fan, fan) -#endif - -#ifdef USE_LIGHT -CONTROLLER_REGISTRY_NOTIFY(light::LightState, light) -#endif - -#ifdef USE_SENSOR -CONTROLLER_REGISTRY_NOTIFY(sensor::Sensor, sensor) -#endif - -#ifdef USE_SWITCH -CONTROLLER_REGISTRY_NOTIFY(switch_::Switch, switch) -#endif - -#ifdef USE_COVER -CONTROLLER_REGISTRY_NOTIFY(cover::Cover, cover) -#endif - -#ifdef USE_TEXT_SENSOR -CONTROLLER_REGISTRY_NOTIFY(text_sensor::TextSensor, text_sensor) -#endif - -#ifdef USE_CLIMATE -CONTROLLER_REGISTRY_NOTIFY(climate::Climate, climate) -#endif - -#ifdef USE_NUMBER -CONTROLLER_REGISTRY_NOTIFY(number::Number, number) -#endif - -#ifdef USE_DATETIME_DATE -CONTROLLER_REGISTRY_NOTIFY(datetime::DateEntity, date) -#endif - -#ifdef USE_DATETIME_TIME -CONTROLLER_REGISTRY_NOTIFY(datetime::TimeEntity, time) -#endif - -#ifdef USE_DATETIME_DATETIME -CONTROLLER_REGISTRY_NOTIFY(datetime::DateTimeEntity, datetime) -#endif - -#ifdef USE_TEXT -CONTROLLER_REGISTRY_NOTIFY(text::Text, text) -#endif - -#ifdef USE_SELECT -CONTROLLER_REGISTRY_NOTIFY(select::Select, select) -#endif - -#ifdef USE_LOCK -CONTROLLER_REGISTRY_NOTIFY(lock::Lock, lock) -#endif - -#ifdef USE_VALVE -CONTROLLER_REGISTRY_NOTIFY(valve::Valve, valve) -#endif - -#ifdef USE_MEDIA_PLAYER -CONTROLLER_REGISTRY_NOTIFY(media_player::MediaPlayer, media_player) -#endif - -#ifdef USE_ALARM_CONTROL_PANEL -CONTROLLER_REGISTRY_NOTIFY(alarm_control_panel::AlarmControlPanel, alarm_control_panel) -#endif - -#ifdef USE_WATER_HEATER -CONTROLLER_REGISTRY_NOTIFY(water_heater::WaterHeater, water_heater) -#endif - -#ifdef USE_EVENT -CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(event::Event, event) -#endif - -#ifdef USE_UPDATE -CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(update::UpdateEntity, update) -#endif - -#undef CONTROLLER_REGISTRY_NOTIFY -#undef CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX - } // namespace esphome #endif // USE_CONTROLLER_REGISTRY diff --git a/esphome/core/controller_registry.h b/esphome/core/controller_registry.h index 89b3069bcb..846642da29 100644 --- a/esphome/core/controller_registry.h +++ b/esphome/core/controller_registry.h @@ -252,4 +252,121 @@ class ControllerRegistry { } // namespace esphome +// Include controller.h AFTER the class definition so notify methods can be +// defined inline. This is safe because controller_registry.h is only ever +// included from .cpp files, never from other headers. +#include "esphome/core/controller.h" + +namespace esphome { + +// Inline notify methods — each is a tiny loop over 1-2 controllers. +// Defining them here (rather than in controller_registry.cpp) allows the +// compiler to inline them into the single call site in each entity's +// notify_frontend_(), eliminating an unnecessary function-call frame. + +// NOLINTBEGIN(bugprone-macro-parentheses) +#define CONTROLLER_REGISTRY_NOTIFY(entity_type, entity_name) \ + inline void ControllerRegistry::notify_##entity_name##_update(entity_type *obj) { \ + for (auto *controller : controllers) { \ + controller->on_##entity_name##_update(obj); \ + } \ + } + +#define CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(entity_type, entity_name) \ + inline void ControllerRegistry::notify_##entity_name(entity_type *obj) { \ + for (auto *controller : controllers) { \ + controller->on_##entity_name(obj); \ + } \ + } +// NOLINTEND(bugprone-macro-parentheses) + +#ifdef USE_BINARY_SENSOR +CONTROLLER_REGISTRY_NOTIFY(binary_sensor::BinarySensor, binary_sensor) +#endif + +#ifdef USE_FAN +CONTROLLER_REGISTRY_NOTIFY(fan::Fan, fan) +#endif + +#ifdef USE_LIGHT +CONTROLLER_REGISTRY_NOTIFY(light::LightState, light) +#endif + +#ifdef USE_SENSOR +CONTROLLER_REGISTRY_NOTIFY(sensor::Sensor, sensor) +#endif + +#ifdef USE_SWITCH +CONTROLLER_REGISTRY_NOTIFY(switch_::Switch, switch) +#endif + +#ifdef USE_COVER +CONTROLLER_REGISTRY_NOTIFY(cover::Cover, cover) +#endif + +#ifdef USE_TEXT_SENSOR +CONTROLLER_REGISTRY_NOTIFY(text_sensor::TextSensor, text_sensor) +#endif + +#ifdef USE_CLIMATE +CONTROLLER_REGISTRY_NOTIFY(climate::Climate, climate) +#endif + +#ifdef USE_NUMBER +CONTROLLER_REGISTRY_NOTIFY(number::Number, number) +#endif + +#ifdef USE_DATETIME_DATE +CONTROLLER_REGISTRY_NOTIFY(datetime::DateEntity, date) +#endif + +#ifdef USE_DATETIME_TIME +CONTROLLER_REGISTRY_NOTIFY(datetime::TimeEntity, time) +#endif + +#ifdef USE_DATETIME_DATETIME +CONTROLLER_REGISTRY_NOTIFY(datetime::DateTimeEntity, datetime) +#endif + +#ifdef USE_TEXT +CONTROLLER_REGISTRY_NOTIFY(text::Text, text) +#endif + +#ifdef USE_SELECT +CONTROLLER_REGISTRY_NOTIFY(select::Select, select) +#endif + +#ifdef USE_LOCK +CONTROLLER_REGISTRY_NOTIFY(lock::Lock, lock) +#endif + +#ifdef USE_VALVE +CONTROLLER_REGISTRY_NOTIFY(valve::Valve, valve) +#endif + +#ifdef USE_MEDIA_PLAYER +CONTROLLER_REGISTRY_NOTIFY(media_player::MediaPlayer, media_player) +#endif + +#ifdef USE_ALARM_CONTROL_PANEL +CONTROLLER_REGISTRY_NOTIFY(alarm_control_panel::AlarmControlPanel, alarm_control_panel) +#endif + +#ifdef USE_WATER_HEATER +CONTROLLER_REGISTRY_NOTIFY(water_heater::WaterHeater, water_heater) +#endif + +#ifdef USE_EVENT +CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(event::Event, event) +#endif + +#ifdef USE_UPDATE +CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX(update::UpdateEntity, update) +#endif + +#undef CONTROLLER_REGISTRY_NOTIFY +#undef CONTROLLER_REGISTRY_NOTIFY_NO_UPDATE_SUFFIX + +} // namespace esphome + #endif // USE_CONTROLLER_REGISTRY From 488a6a1c4090209a726cef53b2042d588b203126 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 05:15:03 +0000 Subject: [PATCH 2002/2030] Bump aioesphomeapi from 44.11.1 to 44.12.0 (#15515) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index db4a2b19e0..5c798819a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ platformio==6.1.19 esptool==5.2.0 click==8.3.2 esphome-dashboard==20260210.0 -aioesphomeapi==44.11.1 +aioesphomeapi==44.12.0 zeroconf==0.148.0 puremagic==1.30 ruamel.yaml==0.19.1 # dashboard_import From 7ab7538220372b85deb233dc40f198b9940d744c Mon Sep 17 00:00:00 2001 From: Diorcet Yann <diorcety@users.noreply.github.com> Date: Tue, 7 Apr 2026 09:59:05 +0200 Subject: [PATCH 2003/2030] [hdc2080] Fix tests (#15518) --- tests/components/hdc2080/common.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/components/hdc2080/common.yaml b/tests/components/hdc2080/common.yaml index cb14cb183b..48c6de2cd5 100644 --- a/tests/components/hdc2080/common.yaml +++ b/tests/components/hdc2080/common.yaml @@ -1,5 +1,6 @@ sensor: - platform: hdc2080 + i2c_id: i2c_bus temperature: name: Temperature humidity: From 674d030cbb47507a83c57b63a816088591a5e8a5 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 7 Apr 2026 07:36:55 -1000 Subject: [PATCH 2004/2030] [core] Reschedule fired intervals directly into heap (#15516) --- esphome/core/scheduler.cpp | 24 ++- .../scheduler_interval_reschedule.yaml | 113 ++++++++++++ .../test_scheduler_interval_reschedule.py | 165 ++++++++++++++++++ 3 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 tests/integration/fixtures/scheduler_interval_reschedule.yaml create mode 100644 tests/integration/test_scheduler_interval_reschedule.py diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 71b29390d6..dff50b03ef 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -529,7 +529,7 @@ void HOT Scheduler::call(uint32_t now) { const auto now_64 = this->millis_64_from_(now); this->process_to_add(); - // Track if any items were added to to_add_ during this call (intervals or from callbacks) + // Track if any items were added to to_add_ during callbacks bool has_added_items = false; #ifdef ESPHOME_DEBUG_SCHEDULER @@ -578,6 +578,12 @@ void HOT Scheduler::call(uint32_t now) { if (this->to_remove_count_() >= MAX_LOGICALLY_DELETED_ITEMS) { this->full_cleanup_removed_items_(); } + // IMPORTANT: This loop uses index-based access (items_[0]), NOT iterators. + // This is intentional — fired intervals are pushed back into items_ via + // push_back() + push_heap() below, which may reallocate the vector's storage. + // Index-based access is safe across reallocations because we re-read items_[0] + // at the top of each iteration. Do NOT convert this to a range-based for loop + // or iterator-based loop, as that would break when items are added. while (!this->items_.empty()) { // Don't copy-by value yet SchedulerItem *item = this->items_[0]; @@ -646,10 +652,18 @@ void HOT Scheduler::call(uint32_t now) { if (executed_item->type == SchedulerItem::INTERVAL) { executed_item->set_next_execution(now_64 + executed_item->interval); - // Add new item directly to to_add_ - // since we have the lock held - this->to_add_.push_back(executed_item); - this->to_add_count_increment_(); + // Push directly back into the heap instead of routing through to_add_. + // This is safe because: + // 1. We're on the main loop and already hold the lock + // 2. The item was already popped from items_ via pop_raw_locked_() above + // 3. The while loop uses index-based access (items_[0]), not iterators, + // so push_back() reallocation cannot invalidate our iteration + // 4. push_heap() restores the heap invariant before the next iteration + // peeks at items_[0] + // This avoids the to_add_ detour and the overhead of + // process_to_add_slow_path_() (lock acquisition, vector iteration, clear). + this->items_.push_back(executed_item); + std::push_heap(this->items_.begin(), this->items_.end(), SchedulerItem::cmp); } else { // Timeout completed - recycle it this->recycle_item_main_loop_(executed_item); diff --git a/tests/integration/fixtures/scheduler_interval_reschedule.yaml b/tests/integration/fixtures/scheduler_interval_reschedule.yaml new file mode 100644 index 0000000000..a0f882deee --- /dev/null +++ b/tests/integration/fixtures/scheduler_interval_reschedule.yaml @@ -0,0 +1,113 @@ +esphome: + name: sched-interval-resched + +host: +api: +logger: + level: DEBUG + +globals: + # Counters for each interval + - id: fast_count + type: int + initial_value: "0" + - id: medium_count + type: int + initial_value: "0" + - id: slow_count + type: int + initial_value: "0" + # Track interval that cancels itself + - id: self_cancel_count + type: int + initial_value: "0" + # Track interval that schedules a timeout from its callback + - id: callback_timeout_fired + type: bool + initial_value: "false" + # Track set_interval replacing itself from within callback + - id: replace_count + type: int + initial_value: "0" + - id: replaced_count + type: int + initial_value: "0" + +interval: + # Fast interval: 50ms + - interval: 50ms + then: + - lambda: |- + id(fast_count) += 1; + if (id(fast_count) == 10) { + ESP_LOGI("test", "FAST_10_REACHED"); + } + + # Medium interval: 100ms + - interval: 100ms + then: + - lambda: |- + id(medium_count) += 1; + if (id(medium_count) == 5) { + ESP_LOGI("test", "MEDIUM_5_REACHED fast_count=%d", id(fast_count)); + } + + # Slow interval: 200ms + - interval: 200ms + then: + - lambda: |- + id(slow_count) += 1; + if (id(slow_count) == 3) { + ESP_LOGI("test", "SLOW_3_REACHED fast_count=%d medium_count=%d", id(fast_count), id(medium_count)); + } + + # Interval that cancels itself after 3 fires + - interval: 75ms + id: self_cancelling + then: + - lambda: |- + id(self_cancel_count) += 1; + ESP_LOGI("test", "SELF_CANCEL_FIRE count=%d", id(self_cancel_count)); + if (id(self_cancel_count) >= 3) { + id(self_cancelling)->stop_poller(); + ESP_LOGI("test", "SELF_CANCEL_STOPPED"); + } + + # Interval that schedules a timeout from its callback (tests to_add_ path) + - interval: 150ms + id: timeout_creator + then: + - lambda: |- + if (!id(callback_timeout_fired)) { + // Schedule a one-shot timeout from within an interval callback + // This goes through to_add_ (not the direct push_heap path) + id(timeout_creator)->set_timeout("test_timeout", 10, []() { + id(callback_timeout_fired) = true; + ESP_LOGI("test", "CALLBACK_TIMEOUT_FIRED"); + }); + // Stop this interval after scheduling the timeout + id(timeout_creator)->stop_poller(); + } + + # Interval that calls set_interval with the same name from within its callback, + # replacing itself. Tests that the old item (marked removed) is not rescheduled + # via push_heap, and the new item goes through to_add_ correctly. + - interval: 60ms + id: replace_test + then: + - lambda: |- + id(replace_count) += 1; + if (id(replace_count) == 1) { + ESP_LOGI("test", "REPLACE_ORIGINAL_FIRE"); + // Replace the polling interval with a named interval on the same component + id(replace_test)->set_interval("replaced_interval", 80, []() { + id(replaced_count) += 1; + ESP_LOGI("test", "REPLACED_FIRE count=%d", id(replaced_count)); + if (id(replaced_count) >= 3) { + id(replace_test)->cancel_interval("replaced_interval"); + ESP_LOGI("test", "REPLACED_STOPPED"); + } + }); + // Stop the original polling interval + id(replace_test)->stop_poller(); + } diff --git a/tests/integration/test_scheduler_interval_reschedule.py b/tests/integration/test_scheduler_interval_reschedule.py new file mode 100644 index 0000000000..d141bd9f15 --- /dev/null +++ b/tests/integration/test_scheduler_interval_reschedule.py @@ -0,0 +1,165 @@ +"""Test that intervals are correctly rescheduled after firing. + +This test verifies the optimization where fired intervals are pushed directly +back into the scheduler's heap (items_) via push_back() + push_heap(), instead +of routing through the to_add_ staging vector and process_to_add_slow_path_(). + +Key scenarios tested: +1. Multiple intervals at different periods all fire at correct rates +2. Heap ordering is preserved — faster intervals fire proportionally more often +3. An interval that cancels itself mid-callback is not rescheduled +4. A timeout scheduled from within an interval callback (to_add_ path) still works +5. An interval that replaces itself via set_interval from within its callback +""" + +from __future__ import annotations + +import asyncio +import re + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_scheduler_interval_reschedule( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test that intervals are correctly rescheduled via direct heap insertion.""" + loop = asyncio.get_running_loop() + + # Futures for each milestone + fast_10_future: asyncio.Future[None] = loop.create_future() + medium_5_future: asyncio.Future[tuple[int]] = loop.create_future() + slow_3_future: asyncio.Future[tuple[int, int]] = loop.create_future() + self_cancel_stopped_future: asyncio.Future[None] = loop.create_future() + callback_timeout_future: asyncio.Future[None] = loop.create_future() + replace_original_future: asyncio.Future[None] = loop.create_future() + replaced_stopped_future: asyncio.Future[None] = loop.create_future() + + self_cancel_fire_count = 0 + replaced_fire_count = 0 + + def on_log_line(line: str) -> None: + nonlocal self_cancel_fire_count, replaced_fire_count + + if "FAST_10_REACHED" in line and not fast_10_future.done(): + fast_10_future.set_result(None) + + match = re.search(r"MEDIUM_5_REACHED fast_count=(\d+)", line) + if match and not medium_5_future.done(): + medium_5_future.set_result((int(match.group(1)),)) + + match = re.search(r"SLOW_3_REACHED fast_count=(\d+) medium_count=(\d+)", line) + if match and not slow_3_future.done(): + slow_3_future.set_result((int(match.group(1)), int(match.group(2)))) + + match = re.search(r"SELF_CANCEL_FIRE count=(\d+)", line) + if match: + self_cancel_fire_count = int(match.group(1)) + + if "SELF_CANCEL_STOPPED" in line and not self_cancel_stopped_future.done(): + self_cancel_stopped_future.set_result(None) + + if "CALLBACK_TIMEOUT_FIRED" in line and not callback_timeout_future.done(): + callback_timeout_future.set_result(None) + + if "REPLACE_ORIGINAL_FIRE" in line and not replace_original_future.done(): + replace_original_future.set_result(None) + + match = re.search(r"REPLACED_FIRE count=(\d+)", line) + if match: + replaced_fire_count = int(match.group(1)) + + if "REPLACED_STOPPED" in line and not replaced_stopped_future.done(): + replaced_stopped_future.set_result(None) + + async with ( + run_compiled(yaml_config, line_callback=on_log_line), + api_client_connected() as client, + ): + device_info = await client.device_info() + assert device_info is not None + assert device_info.name == "sched-interval-resched" + + # 1. Fast interval (50ms) should reach 10 fires within ~600ms + try: + await asyncio.wait_for(fast_10_future, timeout=5.0) + except TimeoutError: + pytest.fail("Fast interval (50ms) did not fire 10 times") + + # 2. Medium interval (100ms) should reach 5 fires + # At that point, fast_count should be roughly 2x medium_count + try: + result = await asyncio.wait_for(medium_5_future, timeout=5.0) + except TimeoutError: + pytest.fail("Medium interval (100ms) did not fire 5 times") + + fast_at_medium_5 = result[0] + # Fast runs at 50ms, medium at 100ms, so fast should be ~2x medium + # Allow some slack for scheduling jitter + assert fast_at_medium_5 >= 7, ( + f"Fast interval should have fired at least 7 times when medium hit 5, " + f"but only fired {fast_at_medium_5} times" + ) + + # 3. Slow interval (200ms) should reach 3 fires + # At that point, both fast and medium should have proportionally more fires + try: + result = await asyncio.wait_for(slow_3_future, timeout=5.0) + except TimeoutError: + pytest.fail("Slow interval (200ms) did not fire 3 times") + + fast_at_slow_3, medium_at_slow_3 = result + # At 600ms: fast ~12, medium ~6, slow 3 + assert fast_at_slow_3 >= 8, ( + f"Fast should have fired at least 8 times when slow hit 3, " + f"but only fired {fast_at_slow_3}" + ) + assert medium_at_slow_3 >= 4, ( + f"Medium should have fired at least 4 times when slow hit 3, " + f"but only fired {medium_at_slow_3}" + ) + + # 4. Self-cancelling interval should have stopped after exactly 3 fires + try: + await asyncio.wait_for(self_cancel_stopped_future, timeout=5.0) + except TimeoutError: + pytest.fail("Self-cancelling interval did not stop") + + # Wait a bit to ensure it doesn't fire again + await asyncio.sleep(0.3) + assert self_cancel_fire_count == 3, ( + f"Self-cancelling interval fired {self_cancel_fire_count} times, " + f"expected exactly 3" + ) + + # 5. Timeout scheduled from interval callback should have fired + try: + await asyncio.wait_for(callback_timeout_future, timeout=5.0) + except TimeoutError: + pytest.fail("Timeout scheduled from interval callback did not fire") + + # 6. Interval that replaces itself via set_interval from within callback + # The original fires once, sets up a new named interval, then stops itself. + # The replacement interval should fire 3 times then cancel itself. + try: + await asyncio.wait_for(replace_original_future, timeout=5.0) + except TimeoutError: + pytest.fail("Replace-test original interval did not fire") + + try: + await asyncio.wait_for(replaced_stopped_future, timeout=5.0) + except TimeoutError: + pytest.fail( + f"Replaced interval did not stop. Fired {replaced_fire_count} times" + ) + + # Wait to ensure replacement doesn't fire again after cancellation + await asyncio.sleep(0.3) + assert replaced_fire_count == 3, ( + f"Replaced interval fired {replaced_fire_count} times, expected exactly 3" + ) From 0d809a748102808a2e03fe69a9206d5162f6326e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 7 Apr 2026 10:09:27 -1000 Subject: [PATCH 2005/2030] [automation] Add CallbackAutomation dataclass and build_callback_automations helper (#15246) --- esphome/automation.py | 33 +++ .../alarm_control_panel/__init__.py | 92 +++++--- esphome/components/binary_sensor/__init__.py | 47 ++-- esphome/components/button/__init__.py | 10 +- esphome/components/dfplayer/__init__.py | 12 +- esphome/components/event/__init__.py | 12 +- esphome/components/ezo/sensor.py | 45 ++-- esphome/components/factory_reset/__init__.py | 17 +- .../components/fingerprint_grow/__init__.py | 77 +++--- esphome/components/haier/climate.py | 41 ++-- esphome/components/hlk_fm22x/__init__.py | 89 ++++--- esphome/components/ld2450/__init__.py | 10 +- esphome/components/lock/__init__.py | 27 ++- esphome/components/ltr501/sensor.py | 19 +- esphome/components/ltr_als_ps/sensor.py | 19 +- esphome/components/media_player/__init__.py | 59 ++++- .../components/modbus_controller/__init__.py | 41 ++-- esphome/components/nextion/display.py | 54 ++--- esphome/components/number/__init__.py | 12 +- esphome/components/online_image/__init__.py | 18 +- esphome/components/pn532/__init__.py | 12 +- esphome/components/pn7150/__init__.py | 20 +- esphome/components/pn7160/__init__.py | 20 +- esphome/components/rf_bridge/__init__.py | 26 +- esphome/components/rotary_encoder/sensor.py | 17 +- esphome/components/rtttl/__init__.py | 12 +- esphome/components/safe_mode/__init__.py | 14 +- esphome/components/sensor/__init__.py | 19 +- esphome/components/sim800l/__init__.py | 49 ++-- esphome/components/sml/__init__.py | 29 ++- esphome/components/switch/__init__.py | 27 ++- esphome/components/text_sensor/__init__.py | 19 +- tests/unit_tests/test_automation.py | 223 +++++++++++++++++- 33 files changed, 794 insertions(+), 427 deletions(-) diff --git a/esphome/automation.py b/esphome/automation.py index 94d64086ec..b4dcc41995 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -1,3 +1,4 @@ +from dataclasses import dataclass, field import logging import esphome.codegen as cg @@ -715,3 +716,35 @@ async def build_callback_automation( # MockObjs (not user input), and there's no Expression type for positional # aggregate initialization (StructInitializer uses named fields). cg.add(getattr(parent, callback_method)(cg.RawExpression(f"{forwarder}{{{obj}}}"))) + + +@dataclass(frozen=True, slots=True) +class CallbackAutomation: + """A single callback automation entry for build_callback_automations.""" + + conf_key: str + callback_method: str + args: TemplateArgsType = field(default_factory=list) + forwarder: MockObj | MockObjClass | None = None + + +async def build_callback_automations( + parent: MockObj, + config: ConfigType, + entries: tuple[CallbackAutomation, ...], +) -> None: + """Build multiple callback automations from a tuple of entries. + + :param parent: The component object (e.g., button, sensor). + :param config: The full component config dict. + :param entries: Tuple of CallbackAutomation entries to process. + """ + for entry in entries: + for conf in config.get(entry.conf_key, []): + await build_callback_automation( + parent, + entry.callback_method, + entry.args, + conf, + forwarder=entry.forwarder, + ) diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index 4ee073a15b..9fcdf42ecb 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -111,42 +111,66 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_STATE, "add_on_state_callback", forwarder=StateAnyForwarder + ), + automation.CallbackAutomation( + CONF_ON_TRIGGERED, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_TRIGGERED + ), + ), + automation.CallbackAutomation( + CONF_ON_ARMING, + "add_on_state_callback", + forwarder=StateEnterForwarder.template(AlarmControlPanelState.ACP_STATE_ARMING), + ), + automation.CallbackAutomation( + CONF_ON_PENDING, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_PENDING + ), + ), + automation.CallbackAutomation( + CONF_ON_ARMED_HOME, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_ARMED_HOME + ), + ), + automation.CallbackAutomation( + CONF_ON_ARMED_NIGHT, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_ARMED_NIGHT + ), + ), + automation.CallbackAutomation( + CONF_ON_ARMED_AWAY, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_ARMED_AWAY + ), + ), + automation.CallbackAutomation( + CONF_ON_DISARMED, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + AlarmControlPanelState.ACP_STATE_DISARMED + ), + ), + automation.CallbackAutomation(CONF_ON_CLEARED, "add_on_cleared_callback"), + automation.CallbackAutomation(CONF_ON_CHIME, "add_on_chime_callback"), + automation.CallbackAutomation(CONF_ON_READY, "add_on_ready_callback"), +) + + @setup_entity("alarm_control_panel") async def setup_alarm_control_panel_core_(var, config): - for conf in config.get(CONF_ON_STATE, []): - await automation.build_callback_automation( - var, "add_on_state_callback", [], conf, forwarder=StateAnyForwarder - ) - _STATE_ENTER_MAP = { - CONF_ON_TRIGGERED: AlarmControlPanelState.ACP_STATE_TRIGGERED, - CONF_ON_ARMING: AlarmControlPanelState.ACP_STATE_ARMING, - CONF_ON_PENDING: AlarmControlPanelState.ACP_STATE_PENDING, - CONF_ON_ARMED_HOME: AlarmControlPanelState.ACP_STATE_ARMED_HOME, - CONF_ON_ARMED_NIGHT: AlarmControlPanelState.ACP_STATE_ARMED_NIGHT, - CONF_ON_ARMED_AWAY: AlarmControlPanelState.ACP_STATE_ARMED_AWAY, - CONF_ON_DISARMED: AlarmControlPanelState.ACP_STATE_DISARMED, - } - for conf_key, state_enum in _STATE_ENTER_MAP.items(): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, - "add_on_state_callback", - [], - conf, - forwarder=StateEnterForwarder.template(state_enum), - ) - for conf in config.get(CONF_ON_CLEARED, []): - await automation.build_callback_automation( - var, "add_on_cleared_callback", [], conf - ) - for conf in config.get(CONF_ON_CHIME, []): - await automation.build_callback_automation( - var, "add_on_chime_callback", [], conf - ) - for conf in config.get(CONF_ON_READY, []): - await automation.build_callback_automation( - var, "add_on_ready_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) if web_server_config := config.get(CONF_WEB_SERVER): await web_server.add_entity_config(var, web_server_config) if mqtt_id := config.get(CONF_MQTT_ID): diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index d8cdaa5d58..0b36c299f6 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -531,16 +531,31 @@ def binary_sensor_schema( return _BINARY_SENSOR_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_PRESS, + "add_on_state_callback", + forwarder=automation.TriggerOnTrueForwarder, + ), + automation.CallbackAutomation( + CONF_ON_RELEASE, + "add_on_state_callback", + forwarder=automation.TriggerOnFalseForwarder, + ), + automation.CallbackAutomation( + CONF_ON_STATE, "add_on_state_callback", [(bool, "x")] + ), + automation.CallbackAutomation( + CONF_ON_STATE_CHANGE, + "add_full_state_callback", + [(cg.optional.template(bool), "x_previous"), (cg.optional.template(bool), "x")], + ), +) + + @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_binary_sensor_automations(var, config): - for conf_key, forwarder in ( - (CONF_ON_PRESS, automation.TriggerOnTrueForwarder), - (CONF_ON_RELEASE, automation.TriggerOnFalseForwarder), - ): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, "add_on_state_callback", [], conf, forwarder=forwarder - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) for conf in config.get(CONF_ON_CLICK, []): trigger = cg.new_Pvariable( @@ -572,22 +587,6 @@ async def _build_binary_sensor_automations(var, config): await cg.register_component(trigger, conf) await automation.build_automation(trigger, [], conf) - for conf in config.get(CONF_ON_STATE, []): - await automation.build_callback_automation( - var, "add_on_state_callback", [(bool, "x")], conf - ) - - for conf in config.get(CONF_ON_STATE_CHANGE, []): - await automation.build_callback_automation( - var, - "add_full_state_callback", - [ - (cg.optional.template(bool), "x_previous"), - (cg.optional.template(bool), "x"), - ], - conf, - ) - @setup_entity("binary_sensor") async def setup_binary_sensor_core_(var, config): diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index f279b6ffe3..2c19ea69b1 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -79,12 +79,14 @@ def button_schema( return _BUTTON_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation(CONF_ON_PRESS, "add_on_press_callback"), +) + + @setup_entity("button") async def setup_button_core_(var, config): - for conf in config.get(CONF_ON_PRESS, []): - await automation.build_callback_automation( - var, "add_on_press_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) setup_device_class(config) diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index adc1913791..7796f5d891 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -64,15 +64,19 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_FINISHED_PLAYBACK, "add_on_finished_playback_callback" + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []): - await automation.build_callback_automation( - var, "add_on_finished_playback_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_action( diff --git a/esphome/components/event/__init__.py b/esphome/components/event/__init__.py index 527bb4ebba..9c9dd025b1 100644 --- a/esphome/components/event/__init__.py +++ b/esphome/components/event/__init__.py @@ -82,12 +82,16 @@ def event_schema( return _EVENT_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_EVENT, "add_on_event_callback", [(cg.StringRef, "event_type")] + ), +) + + @setup_entity("event") async def setup_event_core_(var, config, *, event_types: list[str]): - for conf in config.get(CONF_ON_EVENT, []): - await automation.build_callback_automation( - var, "add_on_event_callback", [(cg.StringRef, "event_type")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) cg.add(var.set_event_types(event_types)) diff --git a/esphome/components/ezo/sensor.py b/esphome/components/ezo/sensor.py index 7c81f9c848..b931885149 100644 --- a/esphome/components/ezo/sensor.py +++ b/esphome/components/ezo/sensor.py @@ -38,33 +38,30 @@ CONFIG_SCHEMA = ( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_CUSTOM, "add_custom_callback", [(cg.std_string, "x")] + ), + automation.CallbackAutomation(CONF_ON_LED, "add_led_state_callback", [(bool, "x")]), + automation.CallbackAutomation( + CONF_ON_DEVICE_INFORMATION, + "add_device_infomation_callback", + [(cg.std_string, "x")], + ), + automation.CallbackAutomation( + CONF_ON_SLOPE, "add_slope_callback", [(cg.std_string, "x")] + ), + automation.CallbackAutomation( + CONF_ON_CALIBRATION, "add_calibration_callback", [(cg.std_string, "x")] + ), + automation.CallbackAutomation(CONF_ON_T, "add_t_callback", [(cg.std_string, "x")]), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await sensor.register_sensor(var, config) await i2c.register_i2c_device(var, config) - for conf in config.get(CONF_ON_CUSTOM, []): - await automation.build_callback_automation( - var, "add_custom_callback", [(cg.std_string, "x")], conf - ) - for conf in config.get(CONF_ON_LED, []): - await automation.build_callback_automation( - var, "add_led_state_callback", [(bool, "x")], conf - ) - for conf in config.get(CONF_ON_DEVICE_INFORMATION, []): - await automation.build_callback_automation( - var, "add_device_infomation_callback", [(cg.std_string, "x")], conf - ) - for conf in config.get(CONF_ON_SLOPE, []): - await automation.build_callback_automation( - var, "add_slope_callback", [(cg.std_string, "x")], conf - ) - for conf in config.get(CONF_ON_CALIBRATION, []): - await automation.build_callback_automation( - var, "add_calibration_callback", [(cg.std_string, "x")], conf - ) - for conf in config.get(CONF_ON_T, []): - await automation.build_callback_automation( - var, "add_t_callback", [(cg.std_string, "x")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/factory_reset/__init__.py b/esphome/components/factory_reset/__init__.py index 20b191a2b7..818a53c0ed 100644 --- a/esphome/components/factory_reset/__init__.py +++ b/esphome/components/factory_reset/__init__.py @@ -73,6 +73,15 @@ def _final_validate(config): FINAL_VALIDATE_SCHEMA = _final_validate +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_INCREMENT, + "add_increment_callback", + [(cg.uint8, "x"), (cg.uint8, "target")], + ), +) + + async def to_code(config): if reset_count := config.get(CONF_RESETS_REQUIRED): var = cg.new_Pvariable( @@ -81,10 +90,4 @@ async def to_code(config): config[CONF_MAX_DELAY].total_seconds, ) await cg.register_component(var, config) - for conf in config.get(CONF_ON_INCREMENT, []): - await automation.build_callback_automation( - var, - "add_increment_callback", - [(cg.uint8, "x"), (cg.uint8, "target")], - conf, - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/fingerprint_grow/__init__.py b/esphome/components/fingerprint_grow/__init__.py index 0b01ba7cab..8d935a3c9e 100644 --- a/esphome/components/fingerprint_grow/__init__.py +++ b/esphome/components/fingerprint_grow/__init__.py @@ -116,6 +116,44 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_FINGER_SCAN_START, "add_on_finger_scan_start_callback" + ), + automation.CallbackAutomation( + CONF_ON_FINGER_SCAN_MATCHED, + "add_on_finger_scan_matched_callback", + [(cg.uint16, "finger_id"), (cg.uint16, "confidence")], + ), + automation.CallbackAutomation( + CONF_ON_FINGER_SCAN_UNMATCHED, + "add_on_finger_scan_unmatched_callback", + ), + automation.CallbackAutomation( + CONF_ON_FINGER_SCAN_MISPLACED, + "add_on_finger_scan_misplaced_callback", + ), + automation.CallbackAutomation( + CONF_ON_FINGER_SCAN_INVALID, "add_on_finger_scan_invalid_callback" + ), + automation.CallbackAutomation( + CONF_ON_ENROLLMENT_SCAN, + "add_on_enrollment_scan_callback", + [(cg.uint8, "scan_num"), (cg.uint16, "finger_id")], + ), + automation.CallbackAutomation( + CONF_ON_ENROLLMENT_DONE, + "add_on_enrollment_done_callback", + [(cg.uint16, "finger_id")], + ), + automation.CallbackAutomation( + CONF_ON_ENROLLMENT_FAILED, + "add_on_enrollment_failed_callback", + [(cg.uint16, "finger_id")], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) @@ -140,44 +178,7 @@ async def to_code(config): idle_period_to_sleep_ms = config[CONF_IDLE_PERIOD_TO_SLEEP] cg.add(var.set_idle_period_to_sleep_ms(idle_period_to_sleep_ms)) - for conf in config.get(CONF_ON_FINGER_SCAN_START, []): - await automation.build_callback_automation( - var, "add_on_finger_scan_start_callback", [], conf - ) - for conf in config.get(CONF_ON_FINGER_SCAN_MATCHED, []): - await automation.build_callback_automation( - var, - "add_on_finger_scan_matched_callback", - [(cg.uint16, "finger_id"), (cg.uint16, "confidence")], - conf, - ) - for conf in config.get(CONF_ON_FINGER_SCAN_UNMATCHED, []): - await automation.build_callback_automation( - var, "add_on_finger_scan_unmatched_callback", [], conf - ) - for conf in config.get(CONF_ON_FINGER_SCAN_MISPLACED, []): - await automation.build_callback_automation( - var, "add_on_finger_scan_misplaced_callback", [], conf - ) - for conf in config.get(CONF_ON_FINGER_SCAN_INVALID, []): - await automation.build_callback_automation( - var, "add_on_finger_scan_invalid_callback", [], conf - ) - for conf in config.get(CONF_ON_ENROLLMENT_SCAN, []): - await automation.build_callback_automation( - var, - "add_on_enrollment_scan_callback", - [(cg.uint8, "scan_num"), (cg.uint16, "finger_id")], - conf, - ) - for conf in config.get(CONF_ON_ENROLLMENT_DONE, []): - await automation.build_callback_automation( - var, "add_on_enrollment_done_callback", [(cg.uint16, "finger_id")], conf - ) - for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []): - await automation.build_callback_automation( - var, "add_on_enrollment_failed_callback", [(cg.uint16, "finger_id")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_action( diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index 9c2c999f25..d485c1d5d4 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -456,6 +456,25 @@ def _final_validate(config): FINAL_VALIDATE_SCHEMA = _final_validate +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_ALARM_START, + "add_alarm_start_callback", + [(cg.uint8, "code"), (cg.const_char_ptr, "message")], + ), + automation.CallbackAutomation( + CONF_ON_ALARM_END, + "add_alarm_end_callback", + [(cg.uint8, "code"), (cg.const_char_ptr, "message")], + ), + automation.CallbackAutomation( + CONF_ON_STATUS_MESSAGE, + "add_status_message_callback", + [(cg.const_char_ptr, "data"), (cg.size_t, "data_size")], + ), +) + + async def to_code(config): cg.add(haier_ns.init_haier_protocol_logging()) var = await climate.new_climate(config) @@ -497,26 +516,6 @@ async def to_code(config): cg.add( var.set_status_message_header_size(config[CONF_STATUS_MESSAGE_HEADER_SIZE]) ) - for conf in config.get(CONF_ON_ALARM_START, []): - await automation.build_callback_automation( - var, - "add_alarm_start_callback", - [(cg.uint8, "code"), (cg.const_char_ptr, "message")], - conf, - ) - for conf in config.get(CONF_ON_ALARM_END, []): - await automation.build_callback_automation( - var, - "add_alarm_end_callback", - [(cg.uint8, "code"), (cg.const_char_ptr, "message")], - conf, - ) - for conf in config.get(CONF_ON_STATUS_MESSAGE, []): - await automation.build_callback_automation( - var, - "add_status_message_callback", - [(cg.const_char_ptr, "data"), (cg.size_t, "data_size")], - conf, - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) # https://github.com/paveldn/HaierProtocol cg.add_library("pavlodn/HaierProtocol", "0.9.31") diff --git a/esphome/components/hlk_fm22x/__init__.py b/esphome/components/hlk_fm22x/__init__.py index c0349319d1..8f55d5dc08 100644 --- a/esphome/components/hlk_fm22x/__init__.py +++ b/esphome/components/hlk_fm22x/__init__.py @@ -52,58 +52,53 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_FACE_SCAN_MATCHED, + "add_on_face_scan_matched_callback", + [(cg.int16, "face_id"), (cg.std_string, "name")], + ), + automation.CallbackAutomation( + CONF_ON_FACE_SCAN_UNMATCHED, "add_on_face_scan_unmatched_callback" + ), + automation.CallbackAutomation( + CONF_ON_FACE_SCAN_INVALID, + "add_on_face_scan_invalid_callback", + [(cg.uint8, "error")], + ), + automation.CallbackAutomation( + CONF_ON_FACE_INFO, + "add_on_face_info_callback", + [ + (cg.int16, "status"), + (cg.int16, "left"), + (cg.int16, "top"), + (cg.int16, "right"), + (cg.int16, "bottom"), + (cg.int16, "yaw"), + (cg.int16, "pitch"), + (cg.int16, "roll"), + ], + ), + automation.CallbackAutomation( + CONF_ON_ENROLLMENT_DONE, + "add_on_enrollment_done_callback", + [(cg.int16, "face_id"), (cg.uint8, "direction")], + ), + automation.CallbackAutomation( + CONF_ON_ENROLLMENT_FAILED, + "add_on_enrollment_failed_callback", + [(cg.uint8, "error")], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_FACE_SCAN_MATCHED, []): - await automation.build_callback_automation( - var, - "add_on_face_scan_matched_callback", - [(cg.int16, "face_id"), (cg.std_string, "name")], - conf, - ) - - for conf in config.get(CONF_ON_FACE_SCAN_UNMATCHED, []): - await automation.build_callback_automation( - var, "add_on_face_scan_unmatched_callback", [], conf - ) - - for conf in config.get(CONF_ON_FACE_SCAN_INVALID, []): - await automation.build_callback_automation( - var, "add_on_face_scan_invalid_callback", [(cg.uint8, "error")], conf - ) - - for conf in config.get(CONF_ON_FACE_INFO, []): - await automation.build_callback_automation( - var, - "add_on_face_info_callback", - [ - (cg.int16, "status"), - (cg.int16, "left"), - (cg.int16, "top"), - (cg.int16, "right"), - (cg.int16, "bottom"), - (cg.int16, "yaw"), - (cg.int16, "pitch"), - (cg.int16, "roll"), - ], - conf, - ) - - for conf in config.get(CONF_ON_ENROLLMENT_DONE, []): - await automation.build_callback_automation( - var, - "add_on_enrollment_done_callback", - [(cg.int16, "face_id"), (cg.uint8, "direction")], - conf, - ) - - for conf in config.get(CONF_ON_ENROLLMENT_FAILED, []): - await automation.build_callback_automation( - var, "add_on_enrollment_failed_callback", [(cg.uint8, "error")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_action( diff --git a/esphome/components/ld2450/__init__.py b/esphome/components/ld2450/__init__.py index 37bf12bafc..585c9f7bf5 100644 --- a/esphome/components/ld2450/__init__.py +++ b/esphome/components/ld2450/__init__.py @@ -44,11 +44,13 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation(CONF_ON_DATA, "add_on_data_callback"), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_DATA, []): - await automation.build_callback_automation( - var, "add_on_data_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/lock/__init__.py b/esphome/components/lock/__init__.py index 0df4b20cba..1a45896ac1 100644 --- a/esphome/components/lock/__init__.py +++ b/esphome/components/lock/__init__.py @@ -81,20 +81,23 @@ def lock_schema( return _LOCK_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_LOCK, + "add_on_state_callback", + forwarder=LockStateForwarder.template(LockState.LOCK_STATE_LOCKED), + ), + automation.CallbackAutomation( + CONF_ON_UNLOCK, + "add_on_state_callback", + forwarder=LockStateForwarder.template(LockState.LOCK_STATE_UNLOCKED), + ), +) + + @setup_entity("lock") async def _setup_lock_core(var, config): - for conf_key, state_enum in ( - (CONF_ON_LOCK, LockState.LOCK_STATE_LOCKED), - (CONF_ON_UNLOCK, LockState.LOCK_STATE_UNLOCKED), - ): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, - "add_on_state_callback", - [], - conf, - forwarder=LockStateForwarder.template(state_enum), - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) if mqtt_id := config.get(CONF_MQTT_ID): mqtt_ = cg.new_Pvariable(mqtt_id, var) diff --git a/esphome/components/ltr501/sensor.py b/esphome/components/ltr501/sensor.py index 712810222c..cca9330e76 100644 --- a/esphome/components/ltr501/sensor.py +++ b/esphome/components/ltr501/sensor.py @@ -211,6 +211,16 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_PS_HIGH_THRESHOLD, "add_on_ps_high_trigger_callback" + ), + automation.CallbackAutomation( + CONF_ON_PS_LOW_THRESHOLD, "add_on_ps_low_trigger_callback" + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) @@ -240,14 +250,7 @@ async def to_code(config): sens = await sensor.new_sensor(prox_cnt_config) cg.add(var.set_proximity_counts_sensor(sens)) - for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): - await automation.build_callback_automation( - var, "add_on_ps_high_trigger_callback", [], conf - ) - for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []): - await automation.build_callback_automation( - var, "add_on_ps_low_trigger_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) cg.add(var.set_ltr_type(config[CONF_TYPE])) diff --git a/esphome/components/ltr_als_ps/sensor.py b/esphome/components/ltr_als_ps/sensor.py index 57503772a1..893415f028 100644 --- a/esphome/components/ltr_als_ps/sensor.py +++ b/esphome/components/ltr_als_ps/sensor.py @@ -201,6 +201,16 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_PS_HIGH_THRESHOLD, "add_on_ps_high_trigger_callback" + ), + automation.CallbackAutomation( + CONF_ON_PS_LOW_THRESHOLD, "add_on_ps_low_trigger_callback" + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) @@ -230,14 +240,7 @@ async def to_code(config): sens = await sensor.new_sensor(prox_cnt_config) cg.add(var.set_proximity_counts_sensor(sens)) - for conf in config.get(CONF_ON_PS_HIGH_THRESHOLD, []): - await automation.build_callback_automation( - var, "add_on_ps_high_trigger_callback", [], conf - ) - for conf in config.get(CONF_ON_PS_LOW_THRESHOLD, []): - await automation.build_callback_automation( - var, "add_on_ps_low_trigger_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) cg.add(var.set_ltr_type(config[CONF_TYPE])) diff --git a/esphome/components/media_player/__init__.py b/esphome/components/media_player/__init__.py index 842f620dae..3c2e9029d6 100644 --- a/esphome/components/media_player/__init__.py +++ b/esphome/components/media_player/__init__.py @@ -69,7 +69,7 @@ StateEnterForwarder = media_player_ns.class_("StateEnterForwarder") MediaPlayerState = media_player_ns.enum("MediaPlayerState") # State triggers: (config_key, state enum or None for any-state) -_STATE_TRIGGERS = [ +_STATE_TRIGGERS = ( (CONF_ON_STATE, None), (CONF_ON_IDLE, MediaPlayerState.MEDIA_PLAYER_STATE_IDLE), (CONF_ON_PLAY, MediaPlayerState.MEDIA_PLAYER_STATE_PLAYING), @@ -77,7 +77,7 @@ _STATE_TRIGGERS = [ (CONF_ON_ANNOUNCEMENT, MediaPlayerState.MEDIA_PLAYER_STATE_ANNOUNCING), (CONF_ON_TURN_ON, MediaPlayerState.MEDIA_PLAYER_STATE_ON), (CONF_ON_TURN_OFF, MediaPlayerState.MEDIA_PLAYER_STATE_OFF), -] +) # State conditions that all share the same schema and codegen handler _STATE_CONDITIONS = [ @@ -102,17 +102,54 @@ VolumeSetAction = media_player_ns.class_( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_STATE, "add_on_state_callback", forwarder=StateAnyForwarder + ), + automation.CallbackAutomation( + CONF_ON_IDLE, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + MediaPlayerState.MEDIA_PLAYER_STATE_IDLE + ), + ), + automation.CallbackAutomation( + CONF_ON_PLAY, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + MediaPlayerState.MEDIA_PLAYER_STATE_PLAYING + ), + ), + automation.CallbackAutomation( + CONF_ON_PAUSE, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + MediaPlayerState.MEDIA_PLAYER_STATE_PAUSED + ), + ), + automation.CallbackAutomation( + CONF_ON_ANNOUNCEMENT, + "add_on_state_callback", + forwarder=StateEnterForwarder.template( + MediaPlayerState.MEDIA_PLAYER_STATE_ANNOUNCING + ), + ), + automation.CallbackAutomation( + CONF_ON_TURN_ON, + "add_on_state_callback", + forwarder=StateEnterForwarder.template(MediaPlayerState.MEDIA_PLAYER_STATE_ON), + ), + automation.CallbackAutomation( + CONF_ON_TURN_OFF, + "add_on_state_callback", + forwarder=StateEnterForwarder.template(MediaPlayerState.MEDIA_PLAYER_STATE_OFF), + ), +) + + @setup_entity("media_player") async def setup_media_player_core_(var, config): - for conf_key, state_enum in _STATE_TRIGGERS: - for conf in config.get(conf_key, []): - if state_enum is None: - forwarder = StateAnyForwarder - else: - forwarder = StateEnterForwarder.template(state_enum) - await automation.build_callback_automation( - var, "add_on_state_callback", [], conf, forwarder=forwarder - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) async def register_media_player(var, config): diff --git a/esphome/components/modbus_controller/__init__.py b/esphome/components/modbus_controller/__init__.py index 9e332425a6..2af58a96be 100644 --- a/esphome/components/modbus_controller/__init__.py +++ b/esphome/components/modbus_controller/__init__.py @@ -205,6 +205,25 @@ async def add_modbus_base_properties( cg.add(var.set_template(template_)) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_COMMAND_SENT, + "add_on_command_sent_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + ), + automation.CallbackAutomation( + CONF_ON_ONLINE, + "add_on_online_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + ), + automation.CallbackAutomation( + CONF_ON_OFFLINE, + "add_on_offline_callback", + [(cg.int_, "function_code"), (cg.int_, "address")], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) cg.add(var.set_allow_duplicate_commands(config[CONF_ALLOW_DUPLICATE_COMMANDS])) @@ -257,27 +276,7 @@ async def to_code(config): ) cg.add(var.add_server_register(server_register_var)) await register_modbus_device(var, config) - for conf in config.get(CONF_ON_COMMAND_SENT, []): - await automation.build_callback_automation( - var, - "add_on_command_sent_callback", - [(cg.int_, "function_code"), (cg.int_, "address")], - conf, - ) - for conf in config.get(CONF_ON_ONLINE, []): - await automation.build_callback_automation( - var, - "add_on_online_callback", - [(cg.int_, "function_code"), (cg.int_, "address")], - conf, - ) - for conf in config.get(CONF_ON_OFFLINE, []): - await automation.build_callback_automation( - var, - "add_on_offline_callback", - [(cg.int_, "function_code"), (cg.int_, "address")], - conf, - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) async def register_modbus_device(var, config): diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 506eb1202b..e477ab7182 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -144,6 +144,28 @@ async def nextion_set_brightness_to_code(config, action_id, template_arg, args): return var +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation(CONF_ON_SETUP, "add_setup_state_callback"), + automation.CallbackAutomation(CONF_ON_SLEEP, "add_sleep_state_callback"), + automation.CallbackAutomation(CONF_ON_WAKE, "add_wake_state_callback"), + automation.CallbackAutomation( + CONF_ON_PAGE, "add_new_page_callback", [(cg.uint8, "x")] + ), + automation.CallbackAutomation( + CONF_ON_TOUCH, + "add_touch_event_callback", + [ + (cg.uint8, "page_id"), + (cg.uint8, "component_id"), + (cg.bool_, "touch_event"), + ], + ), + automation.CallbackAutomation( + CONF_ON_BUFFER_OVERFLOW, "add_buffer_overflow_event_callback" + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await uart.register_uart_device(var, config) @@ -232,34 +254,4 @@ async def to_code(config): await display.register_display(var, config) - for conf in config.get(CONF_ON_SETUP, []): - await automation.build_callback_automation( - var, "add_setup_state_callback", [], conf - ) - for conf in config.get(CONF_ON_SLEEP, []): - await automation.build_callback_automation( - var, "add_sleep_state_callback", [], conf - ) - for conf in config.get(CONF_ON_WAKE, []): - await automation.build_callback_automation( - var, "add_wake_state_callback", [], conf - ) - for conf in config.get(CONF_ON_PAGE, []): - await automation.build_callback_automation( - var, "add_new_page_callback", [(cg.uint8, "x")], conf - ) - for conf in config.get(CONF_ON_TOUCH, []): - await automation.build_callback_automation( - var, - "add_touch_event_callback", - [ - (cg.uint8, "page_id"), - (cg.uint8, "component_id"), - (cg.bool_, "touch_event"), - ], - conf, - ) - for conf in config.get(CONF_ON_BUFFER_OVERFLOW, []): - await automation.build_callback_automation( - var, "add_buffer_overflow_event_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 26d2602ba4..a223b346f2 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -243,12 +243,16 @@ def number_schema( return _NUMBER_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_VALUE, "add_on_state_callback", [(float, "x")] + ), +) + + @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_number_automations(var, config): - for conf in config.get(CONF_ON_VALUE, []): - await automation.build_callback_automation( - var, "add_on_state_callback", [(float, "x")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) for conf in config.get(CONF_ON_VALUE_RANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await cg.register_component(trigger, conf) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 5b8294c70e..518d787d8a 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -105,6 +105,14 @@ async def online_image_action_to_code(config, action_id, template_arg, args): return var +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_DOWNLOAD_FINISHED, "add_on_finished_callback", [(bool, "cached")] + ), + automation.CallbackAutomation(CONF_ON_ERROR, "add_on_error_callback"), +) + + async def to_code(config): # Use the enhanced helper function to get all runtime image parameters settings = await runtime_image.process_runtime_image_config(config) @@ -139,12 +147,4 @@ async def to_code(config): else: cg.add(var.add_request_header(key, value)) - for conf in config.get(CONF_ON_DOWNLOAD_FINISHED, []): - await automation.build_callback_automation( - var, "add_on_finished_callback", [(bool, "cached")], conf - ) - - for conf in config.get(CONF_ON_ERROR, []): - await automation.build_callback_automation( - var, "add_on_error_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/pn532/__init__.py b/esphome/components/pn532/__init__.py index 4ccda49a72..f34df21647 100644 --- a/esphome/components/pn532/__init__.py +++ b/esphome/components/pn532/__init__.py @@ -49,6 +49,13 @@ def CONFIG_SCHEMA(conf): ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback" + ), +) + + async def setup_pn532(var, config): await cg.register_component(var, config) @@ -66,10 +73,7 @@ async def setup_pn532(var, config): trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf ) - for conf in config.get(CONF_ON_FINISHED_WRITE, []): - await automation.build_callback_automation( - var, "add_on_finished_write_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_condition( diff --git a/esphome/components/pn7150/__init__.py b/esphome/components/pn7150/__init__.py index c8723dc31c..9dd3e8c5b0 100644 --- a/esphome/components/pn7150/__init__.py +++ b/esphome/components/pn7150/__init__.py @@ -164,6 +164,16 @@ async def pn7150_simple_action_to_code(config, action_id, template_arg, args): return var +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_EMULATED_TAG_SCAN, "add_on_emulated_tag_scan_callback" + ), + automation.CallbackAutomation( + CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback" + ), +) + + async def setup_pn7150(var, config): await cg.register_component(var, config) @@ -194,15 +204,7 @@ async def setup_pn7150(var, config): trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf ) - for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []): - await automation.build_callback_automation( - var, "add_on_emulated_tag_scan_callback", [], conf - ) - - for conf in config.get(CONF_ON_FINISHED_WRITE, []): - await automation.build_callback_automation( - var, "add_on_finished_write_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_condition( diff --git a/esphome/components/pn7160/__init__.py b/esphome/components/pn7160/__init__.py index e382594b93..ef14a29099 100644 --- a/esphome/components/pn7160/__init__.py +++ b/esphome/components/pn7160/__init__.py @@ -168,6 +168,16 @@ async def pn7160_simple_action_to_code(config, action_id, template_arg, args): return var +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_EMULATED_TAG_SCAN, "add_on_emulated_tag_scan_callback" + ), + automation.CallbackAutomation( + CONF_ON_FINISHED_WRITE, "add_on_finished_write_callback" + ), +) + + async def setup_pn7160(var, config): await cg.register_component(var, config) @@ -206,15 +216,7 @@ async def setup_pn7160(var, config): trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf ) - for conf in config.get(CONF_ON_EMULATED_TAG_SCAN, []): - await automation.build_callback_automation( - var, "add_on_emulated_tag_scan_callback", [], conf - ) - - for conf in config.get(CONF_ON_FINISHED_WRITE, []): - await automation.build_callback_automation( - var, "add_on_finished_write_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_condition( diff --git a/esphome/components/rf_bridge/__init__.py b/esphome/components/rf_bridge/__init__.py index 4ee1e7891f..9ca47fe862 100644 --- a/esphome/components/rf_bridge/__init__.py +++ b/esphome/components/rf_bridge/__init__.py @@ -67,22 +67,26 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_CODE_RECEIVED, + "add_on_code_received_callback", + [(RFBridgeData, "data")], + ), + automation.CallbackAutomation( + CONF_ON_ADVANCED_CODE_RECEIVED, + "add_on_advanced_code_received_callback", + [(RFBridgeAdvancedData, "data")], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_CODE_RECEIVED, []): - await automation.build_callback_automation( - var, "add_on_code_received_callback", [(RFBridgeData, "data")], conf - ) - for conf in config.get(CONF_ON_ADVANCED_CODE_RECEIVED, []): - await automation.build_callback_automation( - var, - "add_on_advanced_code_received_callback", - [(RFBridgeAdvancedData, "data")], - conf, - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) RFBRIDGE_SEND_CODE_SCHEMA = cv.Schema( diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index d88657e715..20c757f093 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -84,6 +84,14 @@ CONFIG_SCHEMA = cv.All( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation(CONF_ON_CLOCKWISE, "add_on_clockwise_callback"), + automation.CallbackAutomation( + CONF_ON_ANTICLOCKWISE, "add_on_anticlockwise_callback" + ), +) + + async def to_code(config): var = await sensor.new_sensor(config) await cg.register_component(var, config) @@ -104,14 +112,7 @@ async def to_code(config): if CONF_MAX_VALUE in config: cg.add(var.set_max_value(config[CONF_MAX_VALUE])) - for conf in config.get(CONF_ON_CLOCKWISE, []): - await automation.build_callback_automation( - var, "add_on_clockwise_callback", [], conf - ) - for conf in config.get(CONF_ON_ANTICLOCKWISE, []): - await automation.build_callback_automation( - var, "add_on_anticlockwise_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_action( diff --git a/esphome/components/rtttl/__init__.py b/esphome/components/rtttl/__init__.py index 638e950ba6..c661aad972 100644 --- a/esphome/components/rtttl/__init__.py +++ b/esphome/components/rtttl/__init__.py @@ -71,6 +71,13 @@ FINAL_VALIDATE_SCHEMA = cv.Schema( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_FINISHED_PLAYBACK, "add_on_finished_playback_callback" + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) @@ -86,10 +93,7 @@ async def to_code(config): cg.add(var.set_gain(config[CONF_GAIN])) - for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []): - await automation.build_callback_automation( - var, "add_on_finished_playback_callback", [], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @automation.register_action( diff --git a/esphome/components/safe_mode/__init__.py b/esphome/components/safe_mode/__init__.py index da36d21eb7..6df0ba78b1 100644 --- a/esphome/components/safe_mode/__init__.py +++ b/esphome/components/safe_mode/__init__.py @@ -65,18 +65,22 @@ async def safe_mode_mark_successful_to_code(config, action_id, template_arg, arg return var +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation(CONF_ON_SAFE_MODE, "add_on_safe_mode_callback"), +) + + @coroutine_with_priority(CoroPriority.APPLICATION) async def to_code(config): if not config[CONF_DISABLED]: var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) - if on_safe_mode_config := config.get(CONF_ON_SAFE_MODE): + if config.get(CONF_ON_SAFE_MODE): cg.add_define("USE_SAFE_MODE_CALLBACK") - for conf in on_safe_mode_config: - await automation.build_callback_automation( - var, "add_on_safe_mode_callback", [], conf - ) + await automation.build_callback_automations( + var, config, _CALLBACK_AUTOMATIONS + ) condition = var.should_enter_safe_mode( config[CONF_NUM_ATTEMPTS], diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 275c4542fb..3a54e97f68 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -892,16 +892,19 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_VALUE, "add_on_state_callback", [(float, "x")] + ), + automation.CallbackAutomation( + CONF_ON_RAW_VALUE, "add_on_raw_state_callback", [(float, "x")] + ), +) + + @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_sensor_automations(var, config): - for conf_key, callback in ( - (CONF_ON_VALUE, "add_on_state_callback"), - (CONF_ON_RAW_VALUE, "add_on_raw_state_callback"), - ): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, callback, [(float, "x")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) for conf in config.get(CONF_ON_VALUE_RANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await cg.register_component(trigger, conf) diff --git a/esphome/components/sim800l/__init__.py b/esphome/components/sim800l/__init__.py index 91771047e1..ae7ee6fa59 100644 --- a/esphome/components/sim800l/__init__.py +++ b/esphome/components/sim800l/__init__.py @@ -48,34 +48,37 @@ FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_SMS_RECEIVED, + "add_on_sms_received_callback", + [(cg.std_string, "message"), (cg.std_string, "sender")], + ), + automation.CallbackAutomation( + CONF_ON_INCOMING_CALL, + "add_on_incoming_call_callback", + [(cg.std_string, "caller_id")], + ), + automation.CallbackAutomation( + CONF_ON_CALL_CONNECTED, "add_on_call_connected_callback" + ), + automation.CallbackAutomation( + CONF_ON_CALL_DISCONNECTED, "add_on_call_disconnected_callback" + ), + automation.CallbackAutomation( + CONF_ON_USSD_RECEIVED, + "add_on_ussd_received_callback", + [(cg.std_string, "ussd")], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_SMS_RECEIVED, []): - await automation.build_callback_automation( - var, - "add_on_sms_received_callback", - [(cg.std_string, "message"), (cg.std_string, "sender")], - conf, - ) - for conf in config.get(CONF_ON_INCOMING_CALL, []): - await automation.build_callback_automation( - var, "add_on_incoming_call_callback", [(cg.std_string, "caller_id")], conf - ) - for conf in config.get(CONF_ON_CALL_CONNECTED, []): - await automation.build_callback_automation( - var, "add_on_call_connected_callback", [], conf - ) - for conf in config.get(CONF_ON_CALL_DISCONNECTED, []): - await automation.build_callback_automation( - var, "add_on_call_disconnected_callback", [], conf - ) - for conf in config.get(CONF_ON_USSD_RECEIVED, []): - await automation.build_callback_automation( - var, "add_on_ussd_received_callback", [(cg.std_string, "ussd")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) SIM800L_SEND_SMS_SCHEMA = cv.Schema( diff --git a/esphome/components/sml/__init__.py b/esphome/components/sml/__init__.py index 1b7f9da4fb..d25e883fa1 100644 --- a/esphome/components/sml/__init__.py +++ b/esphome/components/sml/__init__.py @@ -31,23 +31,26 @@ CONFIG_SCHEMA = ( ) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_DATA, + "add_on_data_callback", + [ + ( + cg.std_vector.template(cg.uint8).operator("ref").operator("const"), + "bytes", + ), + (cg.bool_, "valid"), + ], + ), +) + + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) await uart.register_uart_device(var, config) - for conf in config.get(CONF_ON_DATA, []): - await automation.build_callback_automation( - var, - "add_on_data_callback", - [ - ( - cg.std_vector.template(cg.uint8).operator("ref").operator("const"), - "bytes", - ), - (cg.bool_, "valid"), - ], - conf, - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) def obis_code(value): diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index c4dd4856e3..5a63cbfb9f 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -121,17 +121,26 @@ def switch_schema( return _SWITCH_SCHEMA.extend(schema) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_STATE, "add_on_state_callback", [(bool, "x")] + ), + automation.CallbackAutomation( + CONF_ON_TURN_ON, + "add_on_state_callback", + forwarder=automation.TriggerOnTrueForwarder, + ), + automation.CallbackAutomation( + CONF_ON_TURN_OFF, + "add_on_state_callback", + forwarder=automation.TriggerOnFalseForwarder, + ), +) + + @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_switch_automations(var, config): - for conf_key, args, forwarder in ( - (CONF_ON_STATE, [(bool, "x")], None), - (CONF_ON_TURN_ON, [], automation.TriggerOnTrueForwarder), - (CONF_ON_TURN_OFF, [], automation.TriggerOnFalseForwarder), - ): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, "add_on_state_callback", args, conf, forwarder=forwarder - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @setup_entity("switch") diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index 5b07dd2915..94014e8d20 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -184,16 +184,19 @@ async def build_filters(config): return await cg.build_registry_list(FILTER_REGISTRY, config) +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_VALUE, "add_on_state_callback", [(cg.std_string, "x")] + ), + automation.CallbackAutomation( + CONF_ON_RAW_VALUE, "add_on_raw_state_callback", [(cg.std_string, "x")] + ), +) + + @coroutine_with_priority(CoroPriority.AUTOMATION) async def _build_text_sensor_automations(var, config): - for conf_key, callback in ( - (CONF_ON_VALUE, "add_on_state_callback"), - (CONF_ON_RAW_VALUE, "add_on_raw_state_callback"), - ): - for conf in config.get(conf_key, []): - await automation.build_callback_automation( - var, callback, [(cg.std_string, "x")], conf - ) + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) @setup_entity("text_sensor") diff --git a/tests/unit_tests/test_automation.py b/tests/unit_tests/test_automation.py index 37779f23e6..a377cf185a 100644 --- a/tests/unit_tests/test_automation.py +++ b/tests/unit_tests/test_automation.py @@ -1,14 +1,16 @@ """Tests for esphome.automation module.""" from collections.abc import Generator -from unittest.mock import patch +from unittest.mock import AsyncMock, call, patch import pytest from esphome.automation import ( + CallbackAutomation, TriggerForwarder, TriggerOnFalseForwarder, TriggerOnTrueForwarder, + build_callback_automations, has_non_synchronous_actions, ) from esphome.cpp_generator import MockObj, RawExpression @@ -254,3 +256,222 @@ def test_trigger_forwarder_custom_type() -> None: custom = MockObj("MyForwarder", "") result = _build_forwarder("auto_1", [], forwarder=custom) assert result == "MyForwarder{auto_1}" + + +@pytest.fixture +def mock_build_callback() -> Generator[AsyncMock]: + """Patch build_callback_automation to capture calls.""" + with patch( + "esphome.automation.build_callback_automation", new_callable=AsyncMock + ) as mock: + yield mock + + +@pytest.mark.asyncio +async def test_build_callback_automations_empty_entries( + mock_build_callback: AsyncMock, +) -> None: + """No entries means no calls.""" + parent = MockObj("var", "->") + await build_callback_automations(parent, {}, ()) + mock_build_callback.assert_not_called() + + +@pytest.mark.asyncio +async def test_build_callback_automations_missing_config_key( + mock_build_callback: AsyncMock, +) -> None: + """Entry present but config key missing -- no calls.""" + parent = MockObj("var", "->") + await build_callback_automations( + parent, + {}, + (CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),), + ) + mock_build_callback.assert_not_called() + + +@pytest.mark.asyncio +async def test_build_callback_automations_single_entry( + mock_build_callback: AsyncMock, +) -> None: + """Single entry with one config triggers one call.""" + parent = MockObj("var", "->") + conf: dict[str, object] = {"automation_id": "auto_1", "then": []} + config: dict[str, list[dict[str, object]]] = {"on_state": [conf]} + await build_callback_automations( + parent, + config, + (CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),), + ) + mock_build_callback.assert_called_once_with( + parent, "add_on_state_callback", [(bool, "x")], conf, forwarder=None + ) + + +@pytest.mark.asyncio +async def test_build_callback_automations_multiple_configs( + mock_build_callback: AsyncMock, +) -> None: + """Single entry with multiple configs triggers multiple calls.""" + parent = MockObj("var", "->") + conf1: dict[str, object] = {"automation_id": "auto_1", "then": []} + conf2: dict[str, object] = {"automation_id": "auto_2", "then": []} + config: dict[str, list[dict[str, object]]] = {"on_state": [conf1, conf2]} + await build_callback_automations( + parent, + config, + (CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]),), + ) + assert mock_build_callback.call_count == 2 + mock_build_callback.assert_any_call( + parent, "add_on_state_callback", [(bool, "x")], conf1, forwarder=None + ) + mock_build_callback.assert_any_call( + parent, "add_on_state_callback", [(bool, "x")], conf2, forwarder=None + ) + + +@pytest.mark.asyncio +async def test_build_callback_automations_multiple_entries( + mock_build_callback: AsyncMock, +) -> None: + """Multiple entries each with one config.""" + parent = MockObj("var", "->") + conf_a: dict[str, object] = {"automation_id": "auto_a", "then": []} + conf_b: dict[str, object] = {"automation_id": "auto_b", "then": []} + config: dict[str, list[dict[str, object]]] = { + "on_value": [conf_a], + "on_raw_value": [conf_b], + } + await build_callback_automations( + parent, + config, + ( + CallbackAutomation("on_value", "add_on_value_callback", [(float, "x")]), + CallbackAutomation( + "on_raw_value", "add_on_raw_value_callback", [(float, "x")] + ), + ), + ) + assert mock_build_callback.call_count == 2 + assert mock_build_callback.call_args_list == [ + call(parent, "add_on_value_callback", [(float, "x")], conf_a, forwarder=None), + call( + parent, "add_on_raw_value_callback", [(float, "x")], conf_b, forwarder=None + ), + ] + + +@pytest.mark.asyncio +async def test_build_callback_automations_with_forwarder( + mock_build_callback: AsyncMock, +) -> None: + """Entry with forwarder passes it through.""" + parent = MockObj("var", "->") + conf: dict[str, object] = {"automation_id": "auto_1", "then": []} + config: dict[str, list[dict[str, object]]] = {"on_press": [conf]} + await build_callback_automations( + parent, + config, + ( + CallbackAutomation( + "on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder + ), + ), + ) + mock_build_callback.assert_called_once_with( + parent, "add_on_state_callback", [], conf, forwarder=TriggerOnTrueForwarder + ) + + +@pytest.mark.asyncio +async def test_build_callback_automations_mixed_entries( + mock_build_callback: AsyncMock, +) -> None: + """Mix of entries with args, forwarders, and defaults.""" + parent = MockObj("var", "->") + conf_state: dict[str, object] = {"automation_id": "auto_1", "then": []} + conf_press: dict[str, object] = {"automation_id": "auto_2", "then": []} + conf_release: dict[str, object] = {"automation_id": "auto_3", "then": []} + config: dict[str, list[dict[str, object]]] = { + "on_state": [conf_state], + "on_press": [conf_press], + "on_release": [conf_release], + } + await build_callback_automations( + parent, + config, + ( + CallbackAutomation("on_state", "add_on_state_callback", [(bool, "x")]), + CallbackAutomation( + "on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder + ), + CallbackAutomation( + "on_release", "add_on_state_callback", forwarder=TriggerOnFalseForwarder + ), + ), + ) + assert mock_build_callback.call_count == 3 + assert mock_build_callback.call_args_list == [ + call( + parent, "add_on_state_callback", [(bool, "x")], conf_state, forwarder=None + ), + call( + parent, + "add_on_state_callback", + [], + conf_press, + forwarder=TriggerOnTrueForwarder, + ), + call( + parent, + "add_on_state_callback", + [], + conf_release, + forwarder=TriggerOnFalseForwarder, + ), + ] + + +@pytest.mark.asyncio +async def test_build_callback_automations_skips_missing_keys( + mock_build_callback: AsyncMock, +) -> None: + """Entries whose config keys are absent are silently skipped.""" + parent = MockObj("var", "->") + conf: dict[str, object] = {"automation_id": "auto_1", "then": []} + config: dict[str, list[dict[str, object]]] = {"on_press": [conf]} + await build_callback_automations( + parent, + config, + ( + CallbackAutomation( + "on_press", "add_on_state_callback", forwarder=TriggerOnTrueForwarder + ), + CallbackAutomation( + "on_release", "add_on_state_callback", forwarder=TriggerOnFalseForwarder + ), + ), + ) + mock_build_callback.assert_called_once_with( + parent, "add_on_state_callback", [], conf, forwarder=TriggerOnTrueForwarder + ) + + +@pytest.mark.asyncio +async def test_build_callback_automations_defaults( + mock_build_callback: AsyncMock, +) -> None: + """Verify CallbackAutomation with only required fields defaults args=[] and forwarder=None.""" + parent = MockObj("var", "->") + conf: dict[str, object] = {"automation_id": "auto_1", "then": []} + config: dict[str, list[dict[str, object]]] = {"on_press": [conf]} + await build_callback_automations( + parent, + config, + (CallbackAutomation("on_press", "add_on_press_callback"),), + ) + mock_build_callback.assert_called_once_with( + parent, "add_on_press_callback", [], conf, forwarder=None + ) From 6460f3a757777f805af3a94d8521db2af837dba1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 7 Apr 2026 10:24:36 -1000 Subject: [PATCH 2006/2030] [api] Add max_data_length and force to DeviceInfoResponse/HelloResponse proto fields (#15514) --- esphome/components/api/api.proto | 51 +++++++++++------- esphome/components/api/api_connection.cpp | 9 ++++ esphome/components/api/api_pb2.cpp | 60 +++++++++++----------- esphome/components/esp32/__init__.py | 5 +- esphome/components/esp8266/__init__.py | 5 +- esphome/components/libretiny/__init__.py | 5 +- esphome/components/nrf52/__init__.py | 5 +- esphome/components/number/__init__.py | 2 +- esphome/components/rp2040/__init__.py | 5 +- esphome/components/sensor/__init__.py | 2 +- esphome/config_validation.py | 34 +++++++++--- esphome/core/config.py | 20 ++++++-- esphome/core/entity_helpers.py | 15 +++--- tests/unit_tests/test_config_validation.py | 44 +++++++++++++--- 14 files changed, 182 insertions(+), 80 deletions(-) diff --git a/esphome/components/api/api.proto b/esphome/components/api/api.proto index 07705baff6..33d16f0339 100644 --- a/esphome/components/api/api.proto +++ b/esphome/components/api/api.proto @@ -129,11 +129,12 @@ message HelloResponse { // A string identifying the server (ESP); like client info this may be empty // and only exists for debugging/logging purposes. - // For example "ESPHome v1.10.0 on ESP8266" - string server_info = 3; + // Currently set to ESPHOME_VERSION string literal. + string server_info = 3 [(max_data_length) = 32, (force) = true]; - // The name of the server (App.get_name()) - string name = 4; + // The name of the server (App.get_name() - device hostname) + // max_data_length matches ESPHOME_DEVICE_NAME_MAX_LEN (validated by validate_hostname) + string name = 4 [(max_data_length) = 31, (force) = true]; } // DEPRECATED in ESPHome 2026.1.0 - Password authentication is no longer supported. @@ -196,12 +197,14 @@ message DeviceInfoRequest { message AreaInfo { uint32 area_id = 1; - string name = 2; + // max_data_length matches core/config.FRIENDLY_NAME_MAX_LEN via AREA_SCHEMA + string name = 2 [(max_data_length) = 120, (force) = true]; } message DeviceInfo { uint32 device_id = 1; - string name = 2; + // max_data_length matches core/config.FRIENDLY_NAME_MAX_LEN via DEVICE_SCHEMA + string name = 2 [(max_data_length) = 120, (force) = true]; uint32 area_id = 3; } @@ -216,6 +219,16 @@ message SerialProxyInfo { SerialProxyPortType port_type = 2; // Port type (RS232, RS485) } +// DeviceInfoResponse max_data_length values: +// name = 31 (ESPHOME_DEVICE_NAME_MAX_LEN, validated by validate_hostname) +// friendly_name = 120 (core/config.FRIENDLY_NAME_MAX_LEN) +// mac_address/bluetooth_mac_address = 17 (MAC_ADDRESS_PRETTY_BUFFER_SIZE - 1, constexpr) +// esphome_version = 32 (ESPHOME_VERSION string literal) +// compilation_time = 25 (Application::BUILD_TIME_STR_SIZE - 1, constexpr) +// manufacturer = 20 (longest hardcoded literal: "Nordic Semiconductor") +// model = 127 (core/config.BOARD_MAX_LENGTH, validated in platform schemas) +// project_name/project_version = 127 (core/config.PROJECT_MAX_LENGTH) +// suggested_area = 120 (core/config.FRIENDLY_NAME_MAX_LEN via AREA_SCHEMA) message DeviceInfoResponse { option (id) = 10; option (source) = SOURCE_SERVER; @@ -224,28 +237,30 @@ message DeviceInfoResponse { // with older ESPHome versions that still send this field. bool uses_password = 1 [deprecated = true]; - // The name of the node, given by "App.set_name()" - string name = 2; + // The name of the node, given by "App.set_name()" - device hostname + string name = 2 [(max_data_length) = 31, (force) = true]; // The mac address of the device. For example "AC:BC:32:89:0E:A9" - string mac_address = 3; + string mac_address = 3 [(max_data_length) = 17, (force) = true]; // A string describing the ESPHome version. For example "1.10.0" - string esphome_version = 4; + string esphome_version = 4 [(max_data_length) = 32, (force) = true]; // A string describing the date of compilation, this is generated by the compiler // and therefore may not be in the same format all the time. // If the user isn't using ESPHome, this will also not be set. - string compilation_time = 5; + string compilation_time = 5 [(max_data_length) = 25, (force) = true]; // The model of the board. For example NodeMCU - string model = 6; + // max_data_length matches core/config.BOARD_MAX_LENGTH (validated in platform schemas) + string model = 6 [(max_data_length) = 127, (force) = true]; bool has_deep_sleep = 7 [(field_ifdef) = "USE_DEEP_SLEEP"]; // The esphome project details if set - string project_name = 8 [(field_ifdef) = "ESPHOME_PROJECT_NAME"]; - string project_version = 9 [(field_ifdef) = "ESPHOME_PROJECT_NAME"]; + // max_data_length matches core/config.PROJECT_MAX_LENGTH + string project_name = 8 [(max_data_length) = 127, (force) = true, (field_ifdef) = "ESPHOME_PROJECT_NAME"]; + string project_version = 9 [(max_data_length) = 127, (force) = true, (field_ifdef) = "ESPHOME_PROJECT_NAME"]; uint32 webserver_port = 10 [(field_ifdef) = "USE_WEBSERVER"]; @@ -253,18 +268,18 @@ message DeviceInfoResponse { uint32 legacy_bluetooth_proxy_version = 11 [deprecated=true, (field_ifdef) = "USE_BLUETOOTH_PROXY"]; uint32 bluetooth_proxy_feature_flags = 15 [(field_ifdef) = "USE_BLUETOOTH_PROXY"]; - string manufacturer = 12; + string manufacturer = 12 [(max_data_length) = 20, (force) = true]; - string friendly_name = 13; + string friendly_name = 13 [(max_data_length) = 120, (force) = true]; // Deprecated in API version 1.10 uint32 legacy_voice_assistant_version = 14 [deprecated=true, (field_ifdef) = "USE_VOICE_ASSISTANT"]; uint32 voice_assistant_feature_flags = 17 [(field_ifdef) = "USE_VOICE_ASSISTANT"]; - string suggested_area = 16 [(field_ifdef) = "USE_AREAS"]; + string suggested_area = 16 [(max_data_length) = 120, (force) = true, (field_ifdef) = "USE_AREAS"]; // The Bluetooth mac address of the device. For example "AC:BC:32:89:0E:AA" - string bluetooth_mac_address = 18 [(field_ifdef) = "USE_BLUETOOTH_PROXY"]; + string bluetooth_mac_address = 18 [(max_data_length) = 17, (force) = true, (field_ifdef) = "USE_BLUETOOTH_PROXY"]; // Supports receiving and saving api encryption key bool api_encryption_supported = 19 [(field_ifdef) = "USE_API_NOISE"]; diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index feb16e4f4c..bfb3ec291c 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -72,6 +72,14 @@ static constexpr uint32_t HANDSHAKE_TIMEOUT_MS = 60000; static constexpr auto ESPHOME_VERSION_REF = StringRef::from_lit(ESPHOME_VERSION); +// Cross-validate C++ constants against proto max_data_length annotations in api.proto +static_assert(MAC_ADDRESS_PRETTY_BUFFER_SIZE - 1 == 17, + "Update max_data_length for mac_address/bluetooth_mac_address in api.proto"); +static_assert(Application::BUILD_TIME_STR_SIZE - 1 == 25, "Update max_data_length for compilation_time in api.proto"); +static_assert(sizeof(ESPHOME_VERSION) - 1 <= 32, "Update max_data_length for esphome_version in api.proto"); +static_assert(ESPHOME_DEVICE_NAME_MAX_LEN <= 31, "Update max_data_length for name in api.proto"); +static_assert(ESPHOME_FRIENDLY_NAME_MAX_LEN <= 120, "Update max_data_length for friendly_name in api.proto"); + static const char *const TAG = "api.connection"; #ifdef USE_CAMERA static const int CAMERA_STOP_STREAM = 5000; @@ -1716,6 +1724,7 @@ bool APIConnection::send_device_info_response_() { static constexpr auto MANUFACTURER = StringRef::from_lit(ESPHOME_MANUFACTURER); resp.manufacturer = MANUFACTURER; #endif + static_assert(sizeof(ESPHOME_MANUFACTURER) - 1 <= 20, "Update max_data_length for manufacturer in api.proto"); #undef ESPHOME_MANUFACTURER #ifdef USE_ESP8266 diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f7c68b95a7..d27cfa57cf 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -35,29 +35,29 @@ uint8_t *HelloResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM uint8_t *__restrict__ pos = buffer.get_pos(); ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->api_version_major); ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->api_version_minor); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->server_info); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->server_info); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->name); return pos; } uint32_t HelloResponse::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_uint32(1, this->api_version_major); size += ProtoSize::calc_uint32(1, this->api_version_minor); - size += ProtoSize::calc_length(1, this->server_info.size()); - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->server_info.size(); + size += 2 + this->name.size(); return size; } #ifdef USE_AREAS uint8_t *AreaInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->area_id); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); return pos; } uint32_t AreaInfo::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_uint32(1, this->area_id); - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); return size; } #endif @@ -65,14 +65,14 @@ uint32_t AreaInfo::calculate_size() const { uint8_t *DeviceInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->area_id); return pos; } uint32_t DeviceInfo::calculate_size() const { uint32_t size = 0; size += ProtoSize::calc_uint32(1, this->device_id); - size += ProtoSize::calc_length(1, this->name.size()); + size += 2 + this->name.size(); size += ProtoSize::calc_uint32(1, this->area_id); return size; } @@ -93,19 +93,19 @@ uint32_t SerialProxyInfo::calculate_size() const { #endif uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->name); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->mac_address); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->esphome_version); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->compilation_time); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->model); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->mac_address); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->esphome_version); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 42, this->compilation_time); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 50, this->model); #ifdef USE_DEEP_SLEEP ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->project_name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 66, this->project_name); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->project_version); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 74, this->project_version); #endif #ifdef USE_WEBSERVER ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->webserver_port); @@ -113,16 +113,16 @@ uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_ #ifdef USE_BLUETOOTH_PROXY ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, this->bluetooth_proxy_feature_flags); #endif - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 12, this->manufacturer); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->friendly_name); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 98, this->manufacturer); + ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 106, this->friendly_name); #ifdef USE_VOICE_ASSISTANT ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 17, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 16, this->suggested_area); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 16, this->suggested_area, true); #endif #ifdef USE_BLUETOOTH_PROXY - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 18, this->bluetooth_mac_address); + ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 18, this->bluetooth_mac_address, true); #endif #ifdef USE_API_NOISE ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 19, this->api_encryption_supported); @@ -155,19 +155,19 @@ uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_ } uint32_t DeviceInfoResponse::calculate_size() const { uint32_t size = 0; - size += ProtoSize::calc_length(1, this->name.size()); - size += ProtoSize::calc_length(1, this->mac_address.size()); - size += ProtoSize::calc_length(1, this->esphome_version.size()); - size += ProtoSize::calc_length(1, this->compilation_time.size()); - size += ProtoSize::calc_length(1, this->model.size()); + size += 2 + this->name.size(); + size += 2 + this->mac_address.size(); + size += 2 + this->esphome_version.size(); + size += 2 + this->compilation_time.size(); + size += 2 + this->model.size(); #ifdef USE_DEEP_SLEEP size += ProtoSize::calc_bool(1, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - size += ProtoSize::calc_length(1, this->project_name.size()); + size += 2 + this->project_name.size(); #endif #ifdef ESPHOME_PROJECT_NAME - size += ProtoSize::calc_length(1, this->project_version.size()); + size += 2 + this->project_version.size(); #endif #ifdef USE_WEBSERVER size += ProtoSize::calc_uint32(1, this->webserver_port); @@ -175,16 +175,16 @@ uint32_t DeviceInfoResponse::calculate_size() const { #ifdef USE_BLUETOOTH_PROXY size += ProtoSize::calc_uint32(1, this->bluetooth_proxy_feature_flags); #endif - size += ProtoSize::calc_length(1, this->manufacturer.size()); - size += ProtoSize::calc_length(1, this->friendly_name.size()); + size += 2 + this->manufacturer.size(); + size += 2 + this->friendly_name.size(); #ifdef USE_VOICE_ASSISTANT size += ProtoSize::calc_uint32(2, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - size += ProtoSize::calc_length(2, this->suggested_area.size()); + size += 3 + this->suggested_area.size(); #endif #ifdef USE_BLUETOOTH_PROXY - size += ProtoSize::calc_length(2, this->bluetooth_mac_address.size()); + size += 3 + this->bluetooth_mac_address.size(); #endif #ifdef USE_API_NOISE size += ProtoSize::calc_bool(2, this->api_encryption_supported); diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index 0d8a221524..f27690c97b 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -44,6 +44,7 @@ from esphome.const import ( __version__, ) from esphome.core import CORE, HexInt +from esphome.core.config import BOARD_MAX_LENGTH from esphome.coroutine import CoroPriority, coroutine_with_priority import esphome.final_validate as fv from esphome.helpers import copy_file_if_changed, rmtree, write_file_if_changed @@ -1403,7 +1404,9 @@ CONF_PARTITIONS = "partitions" CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Optional(CONF_BOARD): cv.string_strict, + cv.Optional(CONF_BOARD): cv.All( + cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_CPU_FREQUENCY): cv.one_of( *FULL_CPU_FREQUENCIES, upper=True ), diff --git a/esphome/components/esp8266/__init__.py b/esphome/components/esp8266/__init__.py index fcd3499b15..bef7e36470 100644 --- a/esphome/components/esp8266/__init__.py +++ b/esphome/components/esp8266/__init__.py @@ -20,6 +20,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, Lambda, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH from esphome.helpers import copy_file_if_changed from esphome.types import ConfigType @@ -203,7 +204,9 @@ BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"] CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FRAMEWORK, default={}): ARDUINO_FRAMEWORK_SCHEMA, cv.Optional(CONF_RESTORE_FROM_FLASH, default=False): cv.boolean, cv.Optional(CONF_EARLY_PIN_INIT, default=True): cv.boolean, diff --git a/esphome/components/libretiny/__init__.py b/esphome/components/libretiny/__init__.py index 8f99124604..656eee6d7b 100644 --- a/esphome/components/libretiny/__init__.py +++ b/esphome/components/libretiny/__init__.py @@ -23,6 +23,7 @@ from esphome.const import ( __version__, ) from esphome.core import CORE +from esphome.core.config import BOARD_MAX_LENGTH from esphome.storage_json import StorageJSON from . import gpio # noqa @@ -266,7 +267,9 @@ CONFIG_SCHEMA = cv.All(_notify_old_style) BASE_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(LTComponent), - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FAMILY): cv.one_of(*FAMILIES, upper=True), cv.Optional(CONF_FRAMEWORK, default={}): FRAMEWORK_SCHEMA, }, diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 5054e5e0df..5d92a4fa80 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -46,6 +46,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH import esphome.final_validate as fv from esphome.storage_json import StorageJSON from esphome.types import ConfigType @@ -145,7 +146,9 @@ CONFIG_SCHEMA = cv.All( set_core_data, cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) + ), cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True), cv.Optional(CONF_DFU): cv.Schema( { diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index a223b346f2..9fbaff6860 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -190,7 +190,7 @@ validate_device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") validate_unit_of_measurement = cv.All( cv.string_strict, # Keep in sync with max_data_length in api.proto - cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), + cv.ByteLength(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), ) _NUMBER_SCHEMA = ( diff --git a/esphome/components/rp2040/__init__.py b/esphome/components/rp2040/__init__.py index 0bb1811069..e452780d41 100644 --- a/esphome/components/rp2040/__init__.py +++ b/esphome/components/rp2040/__init__.py @@ -22,6 +22,7 @@ from esphome.const import ( ThreadModel, ) from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority +from esphome.core.config import BOARD_MAX_LENGTH from esphome.helpers import copy_file_if_changed, read_file, write_file_if_changed from . import boards @@ -168,7 +169,9 @@ ARDUINO_FRAMEWORK_SCHEMA = cv.All( CONFIG_SCHEMA = cv.All( cv.Schema( { - cv.Required(CONF_BOARD): cv.string_strict, + cv.Required(CONF_BOARD): cv.All( + cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) + ), cv.Optional(CONF_FRAMEWORK, default={}): ARDUINO_FRAMEWORK_SCHEMA, cv.Optional(CONF_WATCHDOG_TIMEOUT, default="8388ms"): cv.All( cv.positive_time_period_milliseconds, diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 3a54e97f68..ecf51d5488 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -294,7 +294,7 @@ RoundMultipleFilter = sensor_ns.class_("RoundMultipleFilter", Filter) validate_unit_of_measurement = cv.All( cv.string_strict, # Keep in sync with max_data_length in api.proto - cv.Length(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), + cv.ByteLength(max=UNIT_OF_MEASUREMENT_MAX_LENGTH), ) validate_accuracy_decimals = cv.int_ validate_icon = cv.icon diff --git a/esphome/config_validation.py b/esphome/config_validation.py index c6b67e9f35..7805de98db 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -130,6 +130,26 @@ RequiredFieldInvalid = vol.RequiredFieldInvalid # the rest of the error path is relative to the root config path ROOT_CONFIG_PATH = object() + +def ByteLength(*, max: int) -> Callable[[str], str]: + """Validate that the UTF-8 byte length of a string does not exceed max. + + Use instead of Length() when the limit must apply to encoded bytes, + not characters (e.g. for protobuf length-varint constraints). + """ + + def validator(value: str) -> str: + byte_len = len(str(value).encode("utf-8")) + if byte_len > max: + raise Invalid( + f"String is too long ({byte_len} bytes, max {max}). " + f"Multibyte characters count as multiple bytes." + ) + return value + + return validator + + RESERVED_IDS = [ # C++ keywords https://en.cppreference.com/w/cpp/keyword "alarm", @@ -411,9 +431,10 @@ def icon(value): raise Invalid( 'Icons must match the format "[icon pack]:[icon]", e.g. "mdi:home-assistant"' ) - if len(value) > ICON_MAX_LENGTH: + byte_len = len(value.encode("utf-8")) + if byte_len > ICON_MAX_LENGTH: raise Invalid( - f"Icon string is too long ({len(value)} chars, max {ICON_MAX_LENGTH}). " + f"Icon string is too long ({byte_len} bytes, max {ICON_MAX_LENGTH}). " "Icons are stored in PROGMEM with a 64-byte buffer limit." ) return value @@ -2067,11 +2088,12 @@ def _validate_entity_name(value): "Name cannot be None when esphome->friendly_name is not set!" )(value) if value is not None: - # Validate length for web server URL compatibility - if len(value) > NAME_MAX_LENGTH: + # Validate byte length for web server URL and proto encoding compatibility + byte_len = len(value.encode("utf-8")) + if byte_len > NAME_MAX_LENGTH: raise Invalid( - f"Name is too long ({len(value)} chars). " - f"Maximum length is {NAME_MAX_LENGTH} characters." + f"Name is too long ({byte_len} bytes). " + f"Maximum length is {NAME_MAX_LENGTH} bytes." ) # Validate no '/' in name for web server URL compatibility value = _validate_no_slash(value) diff --git a/esphome/core/config.py b/esphome/core/config.py index 31cfd00ef7..bf210876df 100644 --- a/esphome/core/config.py +++ b/esphome/core/config.py @@ -236,11 +236,17 @@ ICON_MAX_LENGTH = 63 # Max unit of measurement string length UNIT_OF_MEASUREMENT_MAX_LENGTH = 63 +# Max project name/version string length (must fit in single-byte varint for proto encoding) +PROJECT_MAX_LENGTH = 127 + +# Max board/model string length (must fit in single-byte varint for proto encoding) +BOARD_MAX_LENGTH = 127 + AREA_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Area), cv.Required(CONF_NAME): cv.All( - cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) + cv.string_no_slash, cv.ByteLength(max=FRIENDLY_NAME_MAX_LEN) ), } ) @@ -249,7 +255,7 @@ DEVICE_SCHEMA = cv.Schema( { cv.GenerateID(CONF_ID): cv.declare_id(Device), cv.Required(CONF_NAME): cv.All( - cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) + cv.string_no_slash, cv.ByteLength(max=FRIENDLY_NAME_MAX_LEN) ), cv.Optional(CONF_AREA_ID): cv.use_id(Area), } @@ -266,7 +272,7 @@ CONFIG_SCHEMA = cv.All( cv.Required(CONF_NAME): cv.valid_name, # Keep max=120 in sync with OBJECT_ID_MAX_LEN in esphome/core/entity_base.h cv.Optional(CONF_FRIENDLY_NAME, ""): cv.All( - cv.string_no_slash, cv.Length(max=FRIENDLY_NAME_MAX_LEN) + cv.string_no_slash, cv.ByteLength(max=FRIENDLY_NAME_MAX_LEN) ), cv.Optional(CONF_AREA): validate_area_config, cv.Optional(CONF_COMMENT): cv.All(cv.string, cv.Length(max=255)), @@ -306,9 +312,13 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_PROJECT): cv.Schema( { cv.Required(CONF_NAME): cv.All( - cv.string_strict, valid_project_name + cv.string_strict, + valid_project_name, + cv.ByteLength(max=PROJECT_MAX_LENGTH), + ), + cv.Required(CONF_VERSION): cv.All( + cv.string_strict, cv.ByteLength(max=PROJECT_MAX_LENGTH) ), - cv.Required(CONF_VERSION): cv.string_strict, cv.Optional(CONF_ON_UPDATE): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index fc931c2baa..f09dd013fe 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -193,9 +193,10 @@ def _register_string( def register_device_class(value: str) -> int: """Register a device_class string and return its 1-based index.""" - if value and len(value) > DEVICE_CLASS_MAX_LENGTH: + byte_len = len(value.encode("utf-8")) if value else 0 + if byte_len > DEVICE_CLASS_MAX_LENGTH: raise ValueError( - f"Device class string too long ({len(value)} chars, max {DEVICE_CLASS_MAX_LENGTH}): '{value}'" + f"Device class string too long ({byte_len} bytes, max {DEVICE_CLASS_MAX_LENGTH}): '{value}'" ) return _register_string( value, _get_pool().device_classes, _MAX_DEVICE_CLASSES, "device_class" @@ -204,9 +205,10 @@ def register_device_class(value: str) -> int: def register_unit_of_measurement(value: str) -> int: """Register a unit_of_measurement string and return its 1-based index.""" - if value and len(value) > UNIT_OF_MEASUREMENT_MAX_LENGTH: + byte_len = len(value.encode("utf-8")) if value else 0 + if byte_len > UNIT_OF_MEASUREMENT_MAX_LENGTH: raise ValueError( - f"Unit of measurement string too long ({len(value)} chars, " + f"Unit of measurement string too long ({byte_len} bytes, " f"max {UNIT_OF_MEASUREMENT_MAX_LENGTH}): '{value}'" ) return _register_string(value, _get_pool().units, _MAX_UNITS, "unit_of_measurement") @@ -214,9 +216,10 @@ def register_unit_of_measurement(value: str) -> int: def register_icon(value: str) -> int: """Register an icon string and return its 1-based index.""" - if value and len(value) > ICON_MAX_LENGTH: + byte_len = len(value.encode("utf-8")) if value else 0 + if byte_len > ICON_MAX_LENGTH: raise ValueError( - f"Icon string too long ({len(value)} chars, max {ICON_MAX_LENGTH}): '{value}'" + f"Icon string too long ({byte_len} bytes, max {ICON_MAX_LENGTH}): '{value}'" ) return _register_string(value, _get_pool().icons, _MAX_ICONS, "icon") diff --git a/tests/unit_tests/test_config_validation.py b/tests/unit_tests/test_config_validation.py index c1849daf4b..ce941b40dc 100644 --- a/tests/unit_tests/test_config_validation.py +++ b/tests/unit_tests/test_config_validation.py @@ -149,17 +149,36 @@ def test_icon__invalid(): def test_icon__max_length(): - """Test that icons exceeding 63 characters are rejected.""" - # Exactly 63 chars should pass - max_icon = "mdi:" + "a" * 59 # 63 chars total + """Test that icons exceeding 63 bytes are rejected.""" + # Exactly 63 bytes should pass + max_icon = "mdi:" + "a" * 59 # 63 bytes total assert config_validation.icon(max_icon) == max_icon - # 64 chars should fail - too_long = "mdi:" + "a" * 60 # 64 chars total + # 64 bytes should fail + too_long = "mdi:" + "a" * 60 # 64 bytes total with pytest.raises(Invalid, match="Icon string is too long"): config_validation.icon(too_long) +def test_byte_length() -> None: + """Test ByteLength validator checks UTF-8 byte length, not char count.""" + validator = config_validation.ByteLength(max=10) # pylint: disable=no-member + + # ASCII: 10 chars = 10 bytes, should pass + assert validator("a" * 10) == "a" * 10 + + # ASCII: 11 chars = 11 bytes, should fail + with pytest.raises(Invalid, match="too long.*11 bytes.*max 10"): + validator("a" * 11) + + # Multibyte: 3 chars × 3 bytes = 9 bytes, should pass + assert validator("温度传") == "温度传" + + # Multibyte: 4 chars × 3 bytes = 12 bytes, should fail + with pytest.raises(Invalid, match="too long.*12 bytes.*max 10"): + validator("温度传感") + + @pytest.mark.parametrize("value", ("True", "YES", "on", "enAblE", True)) def test_boolean__valid_true(value): assert config_validation.boolean(value) is True @@ -567,14 +586,23 @@ def test_validate_entity_name__slash_replaced_with_warning( def test_validate_entity_name__max_length() -> None: - # 120 chars should pass + # 120 bytes should pass assert config_validation._validate_entity_name("x" * 120) == "x" * 120 - # 121 chars should fail - with pytest.raises(Invalid, match="too long.*121 chars.*Maximum.*120"): + # 121 bytes should fail + with pytest.raises(Invalid, match="too long.*121 bytes.*Maximum.*120"): config_validation._validate_entity_name("x" * 121) +def test_validate_entity_name__multibyte_byte_length() -> None: + # 40 chars of 3-byte UTF-8 = 120 bytes, should pass + assert config_validation._validate_entity_name("温" * 40) == "温" * 40 + + # 41 chars of 3-byte UTF-8 = 123 bytes, should fail (over 120 byte limit) + with pytest.raises(Invalid, match="too long.*123 bytes.*Maximum.*120"): + config_validation._validate_entity_name("温" * 41) + + def test_validate_entity_name__none_without_friendly_name() -> None: # When name is "None" and friendly_name is not set, it should fail CORE.friendly_name = None From c6c743e2bb0b7b686bd2d727480d004b879d3948 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:26:11 -1000 Subject: [PATCH 2007/2030] Bump pytest from 9.0.2 to 9.0.3 (#15540) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- requirements_test.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_test.txt b/requirements_test.txt index a191378dd7..eeee3434ce 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -5,7 +5,7 @@ pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating pre-commit # Unit tests -pytest==9.0.2 +pytest==9.0.3 pytest-cov==7.1.0 pytest-mock==3.15.1 pytest-asyncio==1.3.0 From ef6c65c7ecb5cfeefab06035f68e9b1c6ae80f22 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 7 Apr 2026 10:37:19 -1000 Subject: [PATCH 2008/2030] [cli] Add config bundle CLI command for remote compilation (#13791) --- esphome/__main__.py | 61 + esphome/bundle.py | 699 ++++++++++ esphome/components/wifi/wpa2_eap.py | 6 +- esphome/yaml_util.py | 33 +- .../fixtures/bundle/assets/certs/ca_cert.pem | 18 + .../bundle/assets/certs/client_cert.pem | 18 + .../bundle/assets/certs/client_key.pem | 27 + .../bundle/assets/fonts/test_font.ttf | Bin 0 -> 202764 bytes .../bundle/assets/images/animation.gif | Bin 0 -> 9735 bytes .../fixtures/bundle/assets/images/logo.png | Bin 0 -> 685 bytes .../fixtures/bundle/assets/web/custom.css | 2 + .../fixtures/bundle/assets/web/custom.js | 2 + .../fixtures/bundle/bundle_test.yaml | 60 + .../fixtures/bundle/common/base.yaml | 1 + .../fixtures/bundle/includes/custom_sensor.h | 3 + .../local_components/my_component/__init__.py | 1 + .../my_component/my_component.h | 2 + tests/unit_tests/fixtures/bundle/secrets.yaml | 4 + tests/unit_tests/test_bundle.py | 1210 +++++++++++++++++ tests/unit_tests/test_main.py | 196 +++ tests/unit_tests/test_yaml_util.py | 54 + 21 files changed, 2390 insertions(+), 7 deletions(-) create mode 100644 esphome/bundle.py create mode 100644 tests/unit_tests/fixtures/bundle/assets/certs/ca_cert.pem create mode 100644 tests/unit_tests/fixtures/bundle/assets/certs/client_cert.pem create mode 100644 tests/unit_tests/fixtures/bundle/assets/certs/client_key.pem create mode 100644 tests/unit_tests/fixtures/bundle/assets/fonts/test_font.ttf create mode 100644 tests/unit_tests/fixtures/bundle/assets/images/animation.gif create mode 100644 tests/unit_tests/fixtures/bundle/assets/images/logo.png create mode 100644 tests/unit_tests/fixtures/bundle/assets/web/custom.css create mode 100644 tests/unit_tests/fixtures/bundle/assets/web/custom.js create mode 100644 tests/unit_tests/fixtures/bundle/bundle_test.yaml create mode 100644 tests/unit_tests/fixtures/bundle/common/base.yaml create mode 100644 tests/unit_tests/fixtures/bundle/includes/custom_sensor.h create mode 100644 tests/unit_tests/fixtures/bundle/local_components/my_component/__init__.py create mode 100644 tests/unit_tests/fixtures/bundle/local_components/my_component/my_component.h create mode 100644 tests/unit_tests/fixtures/bundle/secrets.yaml create mode 100644 tests/unit_tests/test_bundle.py diff --git a/esphome/__main__.py b/esphome/__main__.py index 87abd7f796..a696cceffb 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1242,6 +1242,38 @@ def command_clean(args: ArgsProtocol, config: ConfigType) -> int | None: return 0 +def command_bundle(args: ArgsProtocol, config: ConfigType) -> int | None: + from esphome.bundle import BUNDLE_EXTENSION, ConfigBundleCreator + + creator = ConfigBundleCreator(config) + + if args.list_only: + files = creator.discover_files() + for bf in sorted(files, key=lambda f: f.path): + safe_print(f" {bf.path}") + _LOGGER.info("Found %d files", len(files)) + return 0 + + result = creator.create_bundle() + + if args.output: + output_path = Path(args.output) + else: + stem = CORE.config_path.stem + output_path = CORE.config_dir / f"{stem}{BUNDLE_EXTENSION}" + + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_bytes(result.data) + + _LOGGER.info( + "Bundle created: %s (%d files, %.1f KB)", + output_path, + len(result.files), + len(result.data) / 1024, + ) + return 0 + + def command_dashboard(args: ArgsProtocol) -> int | None: from esphome.dashboard import dashboard @@ -1517,6 +1549,7 @@ POST_CONFIG_ACTIONS = { "rename": command_rename, "discover": command_discover, "analyze-memory": command_analyze_memory, + "bundle": command_bundle, } SIMPLE_CONFIG_ACTIONS = [ @@ -1818,6 +1851,24 @@ def parse_args(argv): "configuration", help="Your YAML configuration file(s).", nargs="+" ) + parser_bundle = subparsers.add_parser( + "bundle", + help="Create a self-contained config bundle for remote compilation.", + ) + parser_bundle.add_argument( + "configuration", help="Your YAML configuration file(s).", nargs="+" + ) + parser_bundle.add_argument( + "-o", + "--output", + help="Output path for the bundle archive.", + ) + parser_bundle.add_argument( + "--list-only", + help="List discovered files without creating the archive.", + action="store_true", + ) + # Keep backward compatibility with the old command line format of # esphome <config> <command>. # @@ -1896,6 +1947,16 @@ def run_esphome(argv): _LOGGER.warning("Skipping secrets file %s", conf_path) return 0 + # Bundle support: if the configuration is a .esphomebundle, extract it + # and rewrite conf_path to the extracted YAML config. + from esphome.bundle import is_bundle_path, prepare_bundle_for_compile + + if is_bundle_path(conf_path): + _LOGGER.info("Extracting config bundle %s...", conf_path) + conf_path = prepare_bundle_for_compile(conf_path) + # Update the argument so downstream code sees the extracted path + args.configuration[0] = str(conf_path) + CORE.config_path = conf_path CORE.dashboard = args.dashboard diff --git a/esphome/bundle.py b/esphome/bundle.py new file mode 100644 index 0000000000..b6816c7c95 --- /dev/null +++ b/esphome/bundle.py @@ -0,0 +1,699 @@ +"""Config bundle creator and extractor for ESPHome. + +A bundle is a self-contained .tar.gz archive containing a YAML config +and every local file it depends on. Bundles can be created from a config +and compiled directly: ``esphome compile my_device.esphomebundle.tar.gz`` +""" + +from __future__ import annotations + +from dataclasses import dataclass +from enum import StrEnum +import io +import json +import logging +from pathlib import Path +import re +import shutil +import tarfile +from typing import Any + +from esphome import const, yaml_util +from esphome.const import ( + CONF_ESPHOME, + CONF_EXTERNAL_COMPONENTS, + CONF_INCLUDES, + CONF_INCLUDES_C, + CONF_PATH, + CONF_SOURCE, + CONF_TYPE, +) +from esphome.core import CORE, EsphomeError + +_LOGGER = logging.getLogger(__name__) + +BUNDLE_EXTENSION = ".esphomebundle.tar.gz" +MANIFEST_FILENAME = "manifest.json" +CURRENT_MANIFEST_VERSION = 1 +MAX_DECOMPRESSED_SIZE = 500 * 1024 * 1024 # 500 MB +MAX_MANIFEST_SIZE = 1024 * 1024 # 1 MB + +# Directories preserved across bundle extractions (build caches) +_PRESERVE_DIRS = (".esphome", ".pioenvs", ".pio") +_BUNDLE_STAGING_DIR = ".bundle_staging" + + +class ManifestKey(StrEnum): + """Keys used in bundle manifest.json.""" + + MANIFEST_VERSION = "manifest_version" + ESPHOME_VERSION = "esphome_version" + CONFIG_FILENAME = "config_filename" + FILES = "files" + HAS_SECRETS = "has_secrets" + + +# String prefixes that are never local file paths +_NON_PATH_PREFIXES = ("http://", "https://", "ftp://", "mdi:", "<") + +# File extensions recognized when resolving relative path strings. +# A relative string with one of these extensions is resolved against the +# config directory and included if the file exists. +_KNOWN_FILE_EXTENSIONS = frozenset( + { + # Fonts + ".ttf", + ".otf", + ".woff", + ".woff2", + ".pcf", + ".bdf", + # Images + ".png", + ".jpg", + ".jpeg", + ".bmp", + ".gif", + ".svg", + ".ico", + ".webp", + # Certificates + ".pem", + ".crt", + ".key", + ".der", + ".p12", + ".pfx", + # C/C++ includes + ".h", + ".hpp", + ".c", + ".cpp", + ".ino", + # Web assets + ".css", + ".js", + ".html", + } +) + + +# Matches !secret references in YAML text. This is intentionally a simple +# regex scan rather than a YAML parse — it may match inside comments or +# multi-line strings, which is the conservative direction (include more +# secrets rather than fewer). +_SECRET_RE = re.compile(r"!secret\s+(\S+)") + + +def _find_used_secret_keys(yaml_files: list[Path]) -> set[str]: + """Scan YAML files for ``!secret <key>`` references.""" + keys: set[str] = set() + for fpath in yaml_files: + try: + text = fpath.read_text(encoding="utf-8") + except (OSError, UnicodeDecodeError): + continue + for match in _SECRET_RE.finditer(text): + keys.add(match.group(1)) + return keys + + +@dataclass +class BundleFile: + """A file to include in the bundle.""" + + path: str # Relative path inside the archive + source: Path # Absolute path on disk + + +@dataclass +class BundleResult: + """Result of creating a bundle.""" + + data: bytes + manifest: dict[str, Any] + files: list[BundleFile] + + +@dataclass +class BundleManifest: + """Parsed and validated bundle manifest.""" + + manifest_version: int + esphome_version: str + config_filename: str + files: list[str] + has_secrets: bool + + +class ConfigBundleCreator: + """Creates a self-contained bundle from an ESPHome config.""" + + def __init__(self, config: dict[str, Any]) -> None: + self._config = config + self._config_dir = CORE.config_dir + self._config_path = CORE.config_path + self._files: list[BundleFile] = [] + self._seen_paths: set[Path] = set() + self._secrets_paths: set[Path] = set() + + def discover_files(self) -> list[BundleFile]: + """Discover all files needed for the bundle.""" + self._files = [] + self._seen_paths = set() + self._secrets_paths = set() + + # The main config file + self._add_file(self._config_path) + + # Phase 1: YAML includes (tracked during config loading) + self._discover_yaml_includes() + + # Phase 2: Component-referenced files from validated config + self._discover_component_files() + + return list(self._files) + + def create_bundle(self) -> BundleResult: + """Create the bundle archive.""" + files = self.discover_files() + + # Determine which secret keys are actually referenced by the + # bundled YAML files so we only ship those, not the entire + # secrets.yaml which may contain secrets for other devices. + yaml_sources = [ + bf.source for bf in files if bf.source.suffix in (".yaml", ".yml") + ] + used_secret_keys = _find_used_secret_keys(yaml_sources) + filtered_secrets = self._build_filtered_secrets(used_secret_keys) + + has_secrets = bool(filtered_secrets) + if has_secrets: + _LOGGER.warning( + "Bundle contains secrets (e.g. Wi-Fi passwords). " + "Do not share it with untrusted parties." + ) + + manifest = self._build_manifest(files, has_secrets=has_secrets) + + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + # Add manifest first + manifest_data = json.dumps(manifest, indent=2).encode("utf-8") + _add_bytes_to_tar(tar, MANIFEST_FILENAME, manifest_data) + + # Add filtered secrets files + for rel_path, data in sorted(filtered_secrets.items()): + _add_bytes_to_tar(tar, rel_path, data) + + # Add files in sorted order for determinism, skipping secrets + # files which were already added above with filtered content + for bf in sorted(files, key=lambda f: f.path): + if bf.source in self._secrets_paths: + continue + self._add_to_tar(tar, bf) + + return BundleResult(data=buf.getvalue(), manifest=manifest, files=files) + + def _add_file(self, abs_path: Path) -> bool: + """Add a file to the bundle. Returns False if already added.""" + abs_path = abs_path.resolve() + if abs_path in self._seen_paths: + return False + if not abs_path.is_file(): + _LOGGER.warning("Bundle: skipping missing file %s", abs_path) + return False + + rel_path = self._relative_to_config_dir(abs_path) + if rel_path is None: + _LOGGER.warning( + "Bundle: skipping file outside config directory: %s", abs_path + ) + return False + + self._seen_paths.add(abs_path) + self._files.append(BundleFile(path=rel_path, source=abs_path)) + return True + + def _add_directory(self, abs_path: Path) -> None: + """Recursively add all files in a directory.""" + abs_path = abs_path.resolve() + if not abs_path.is_dir(): + _LOGGER.warning("Bundle: skipping missing directory %s", abs_path) + return + for child in sorted(abs_path.rglob("*")): + if child.is_file() and "__pycache__" not in child.parts: + self._add_file(child) + + def _relative_to_config_dir(self, abs_path: Path) -> str | None: + """Get a path relative to the config directory. Returns None if outside. + + Always uses forward slashes for consistency in tar archives. + """ + try: + return abs_path.relative_to(self._config_dir).as_posix() + except ValueError: + return None + + def _discover_yaml_includes(self) -> None: + """Discover YAML files loaded during config parsing. + + We track files by wrapping _load_yaml_internal. The config has already + been loaded at this point (bundle is a POST_CONFIG_ACTION), so we + re-load just to discover the file list. + + Secrets files are tracked separately so we can filter them to + only include the keys this config actually references. + """ + with yaml_util.track_yaml_loads() as loaded_files: + try: + yaml_util.load_yaml(self._config_path) + except EsphomeError: + _LOGGER.debug( + "Bundle: re-loading YAML for include discovery failed, " + "proceeding with partial file list" + ) + + for fpath in loaded_files: + if fpath == self._config_path.resolve(): + continue # Already added as config + if fpath.name in const.SECRETS_FILES: + self._secrets_paths.add(fpath) + self._add_file(fpath) + + def _discover_component_files(self) -> None: + """Walk the validated config for file references. + + Uses a generic recursive walk to find file paths instead of + hardcoding per-component knowledge about config dict formats. + After validation, components typically resolve paths to absolute + using CORE.relative_config_path() or cv.file_(). Relative paths + with known file extensions are also resolved and checked. + + Core ESPHome concepts that use relative paths or directories + are handled explicitly. + """ + config = self._config + + # Generic walk: find all file paths in the validated config + self._walk_config_for_files(config) + + # --- Core ESPHome concepts needing explicit handling --- + + # esphome.includes / includes_c - can be relative paths and directories + esphome_conf = config.get(CONF_ESPHOME, {}) + for include_path in esphome_conf.get(CONF_INCLUDES, []): + resolved = _resolve_include_path(include_path) + if resolved is None: + continue + if resolved.is_dir(): + self._add_directory(resolved) + else: + self._add_file(resolved) + for include_path in esphome_conf.get(CONF_INCLUDES_C, []): + resolved = _resolve_include_path(include_path) + if resolved is not None: + self._add_file(resolved) + + # external_components with source: local - directories + for ext_conf in config.get(CONF_EXTERNAL_COMPONENTS, []): + source = ext_conf.get(CONF_SOURCE, {}) + if not isinstance(source, dict): + continue + if source.get(CONF_TYPE) != "local": + continue + path = source.get(CONF_PATH) + if not path: + continue + p = Path(path) + if not p.is_absolute(): + p = CORE.relative_config_path(p) + self._add_directory(p) + + def _walk_config_for_files(self, obj: Any) -> None: + """Recursively walk the config dict looking for file path references.""" + if isinstance(obj, dict): + for value in obj.values(): + self._walk_config_for_files(value) + elif isinstance(obj, (list, tuple)): + for item in obj: + self._walk_config_for_files(item) + elif isinstance(obj, Path): + if obj.is_absolute() and obj.is_file(): + self._add_file(obj) + elif isinstance(obj, str): + self._check_string_path(obj) + + def _check_string_path(self, value: str) -> None: + """Check if a string value is a local file reference.""" + # Fast exits for strings that cannot be file paths + if len(value) < 2 or "\n" in value: + return + if value.startswith(_NON_PATH_PREFIXES): + return + # File paths must contain a path separator or a dot (for extension) + if "/" not in value and "\\" not in value and "." not in value: + return + + p = Path(value) + + # Absolute path - check if it points to an existing file + if p.is_absolute(): + if p.is_file(): + self._add_file(p) + return + + # Relative path with a known file extension - likely a component + # validator that forgot to resolve to absolute via cv.file_() or + # CORE.relative_config_path(). Warn and try to resolve. + if p.suffix.lower() in _KNOWN_FILE_EXTENSIONS: + _LOGGER.warning( + "Bundle: non-absolute path in validated config: %s " + "(component validator should return absolute paths)", + value, + ) + resolved = CORE.relative_config_path(p) + if resolved.is_file(): + self._add_file(resolved) + + def _build_filtered_secrets(self, used_keys: set[str]) -> dict[str, bytes]: + """Build filtered secrets files containing only the referenced keys. + + Returns a dict mapping relative archive path to YAML bytes. + """ + if not used_keys or not self._secrets_paths: + return {} + + result: dict[str, bytes] = {} + for secrets_path in self._secrets_paths: + rel_path = self._relative_to_config_dir(secrets_path) + if rel_path is None: + continue + try: + all_secrets = yaml_util.load_yaml(secrets_path, clear_secrets=False) + except EsphomeError: + _LOGGER.warning("Bundle: failed to load secrets file %s", secrets_path) + continue + if not isinstance(all_secrets, dict): + continue + filtered = {k: v for k, v in all_secrets.items() if k in used_keys} + if filtered: + data = yaml_util.dump(filtered, show_secrets=True).encode("utf-8") + result[rel_path] = data + return result + + def _build_manifest( + self, files: list[BundleFile], *, has_secrets: bool + ) -> dict[str, Any]: + """Build the manifest.json content.""" + return { + ManifestKey.MANIFEST_VERSION: CURRENT_MANIFEST_VERSION, + ManifestKey.ESPHOME_VERSION: const.__version__, + ManifestKey.CONFIG_FILENAME: self._config_path.name, + ManifestKey.FILES: [f.path for f in files], + ManifestKey.HAS_SECRETS: has_secrets, + } + + @staticmethod + def _add_to_tar(tar: tarfile.TarFile, bf: BundleFile) -> None: + """Add a BundleFile to the tar archive with deterministic metadata.""" + with open(bf.source, "rb") as f: + _add_bytes_to_tar(tar, bf.path, f.read()) + + +def extract_bundle( + bundle_path: Path, + target_dir: Path | None = None, +) -> Path: + """Extract a bundle archive and return the path to the config YAML. + + Sanity checks reject path traversal, symlinks, absolute paths, and + oversized archives to prevent accidental file overwrites or extraction + outside the target directory. These are **not** a security boundary — + bundles are assumed to come from the user's own machine or a trusted + build pipeline. + + Args: + bundle_path: Path to the .tar.gz bundle file. + target_dir: Directory to extract into. If None, extracts next to + the bundle file in a directory named after it. + + Returns: + Absolute path to the extracted config YAML file. + + Raises: + EsphomeError: If the bundle is invalid or extraction fails. + """ + + bundle_path = bundle_path.resolve() + if not bundle_path.is_file(): + raise EsphomeError(f"Bundle file not found: {bundle_path}") + + if target_dir is None: + target_dir = _default_target_dir(bundle_path) + + target_dir = target_dir.resolve() + target_dir.mkdir(parents=True, exist_ok=True) + + # Read and validate the archive + try: + with tarfile.open(bundle_path, "r:gz") as tar: + manifest = _read_manifest_from_tar(tar) + _validate_tar_members(tar, target_dir) + tar.extractall(path=target_dir, filter="data") + except tarfile.TarError as err: + raise EsphomeError(f"Failed to extract bundle: {err}") from err + + config_filename = manifest[ManifestKey.CONFIG_FILENAME] + config_path = target_dir / config_filename + if not config_path.is_file(): + raise EsphomeError( + f"Bundle manifest references config '{config_filename}' " + f"but it was not found in the archive" + ) + + return config_path + + +def read_bundle_manifest(bundle_path: Path) -> BundleManifest: + """Read and validate the manifest from a bundle without full extraction. + + Args: + bundle_path: Path to the .tar.gz bundle file. + + Returns: + Parsed BundleManifest. + + Raises: + EsphomeError: If the manifest is missing, invalid, or version unsupported. + """ + + try: + with tarfile.open(bundle_path, "r:gz") as tar: + manifest = _read_manifest_from_tar(tar) + except tarfile.TarError as err: + raise EsphomeError(f"Failed to read bundle: {err}") from err + + return BundleManifest( + manifest_version=manifest[ManifestKey.MANIFEST_VERSION], + esphome_version=manifest.get(ManifestKey.ESPHOME_VERSION, "unknown"), + config_filename=manifest[ManifestKey.CONFIG_FILENAME], + files=manifest.get(ManifestKey.FILES, []), + has_secrets=manifest.get(ManifestKey.HAS_SECRETS, False), + ) + + +def _read_manifest_from_tar(tar: tarfile.TarFile) -> dict[str, Any]: + """Read and validate manifest.json from an open tar archive.""" + + try: + member = tar.getmember(MANIFEST_FILENAME) + except KeyError: + raise EsphomeError("Invalid bundle: missing manifest.json") from None + + f = tar.extractfile(member) + if f is None: + raise EsphomeError("Invalid bundle: manifest.json is not a regular file") + + if member.size > MAX_MANIFEST_SIZE: + raise EsphomeError( + f"Invalid bundle: manifest.json too large " + f"({member.size} bytes, max {MAX_MANIFEST_SIZE})" + ) + + try: + manifest = json.loads(f.read()) + except (json.JSONDecodeError, UnicodeDecodeError) as err: + raise EsphomeError(f"Invalid bundle: malformed manifest.json: {err}") from err + + # Version check + version = manifest.get(ManifestKey.MANIFEST_VERSION) + if version is None: + raise EsphomeError("Invalid bundle: manifest.json missing 'manifest_version'") + if not isinstance(version, int) or version < 1: + raise EsphomeError( + f"Invalid bundle: manifest_version must be a positive integer, got {version!r}" + ) + if version > CURRENT_MANIFEST_VERSION: + raise EsphomeError( + f"Bundle manifest version {version} is newer than this ESPHome " + f"version supports (max {CURRENT_MANIFEST_VERSION}). " + f"Please upgrade ESPHome to compile this bundle." + ) + + # Required fields + if ManifestKey.CONFIG_FILENAME not in manifest: + raise EsphomeError("Invalid bundle: manifest.json missing 'config_filename'") + + return manifest + + +def _validate_tar_members(tar: tarfile.TarFile, target_dir: Path) -> None: + """Sanity-check tar members to prevent mistakes and accidental overwrites. + + This is not a security boundary — bundles are created locally or come + from a trusted build pipeline. The checks catch malformed archives + and common mistakes (stray absolute paths, ``..`` components) that + could silently overwrite unrelated files. + """ + + total_size = 0 + for member in tar.getmembers(): + # Reject absolute paths (Unix and Windows) + if member.name.startswith(("/", "\\")): + raise EsphomeError( + f"Invalid bundle: absolute path in archive: {member.name}" + ) + + # Reject path traversal (split on both / and \ for cross-platform) + parts = re.split(r"[/\\]", member.name) + if ".." in parts: + raise EsphomeError( + f"Invalid bundle: path traversal in archive: {member.name}" + ) + + # Reject symlinks + if member.issym() or member.islnk(): + raise EsphomeError(f"Invalid bundle: symlink in archive: {member.name}") + + # Ensure extraction stays within target_dir + target_path = (target_dir / member.name).resolve() + if not target_path.is_relative_to(target_dir): + raise EsphomeError( + f"Invalid bundle: file would extract outside target: {member.name}" + ) + + # Track total decompressed size + total_size += member.size + if total_size > MAX_DECOMPRESSED_SIZE: + raise EsphomeError( + f"Invalid bundle: decompressed size exceeds " + f"{MAX_DECOMPRESSED_SIZE // (1024 * 1024)}MB limit" + ) + + +def is_bundle_path(path: Path) -> bool: + """Check if a path looks like a bundle file.""" + return path.name.lower().endswith(BUNDLE_EXTENSION) + + +def _add_bytes_to_tar(tar: tarfile.TarFile, name: str, data: bytes) -> None: + """Add in-memory bytes to a tar archive with deterministic metadata.""" + info = tarfile.TarInfo(name=name) + info.size = len(data) + info.mtime = 0 + info.uid = 0 + info.gid = 0 + info.mode = 0o644 + tar.addfile(info, io.BytesIO(data)) + + +def _resolve_include_path(include_path: Any) -> Path | None: + """Resolve an include path to absolute, skipping system includes.""" + if isinstance(include_path, str) and include_path.startswith("<"): + return None # System include, not a local file + p = Path(include_path) + if not p.is_absolute(): + p = CORE.relative_config_path(p) + return p + + +def _default_target_dir(bundle_path: Path) -> Path: + """Compute the default extraction directory for a bundle.""" + name = bundle_path.name + if name.lower().endswith(BUNDLE_EXTENSION): + name = name[: -len(BUNDLE_EXTENSION)] + return bundle_path.parent / name + + +def _restore_preserved_dirs(preserved: dict[str, Path], target_dir: Path) -> None: + """Move preserved build cache directories back into target_dir. + + If the bundle contained entries under a preserved directory name, + the extracted copy is removed so the original cache always wins. + """ + for dirname, src in preserved.items(): + dst = target_dir / dirname + if dst.exists(): + shutil.rmtree(dst) + shutil.move(str(src), str(dst)) + + +def prepare_bundle_for_compile( + bundle_path: Path, + target_dir: Path | None = None, +) -> Path: + """Extract a bundle for compilation, preserving build caches. + + Unlike extract_bundle(), this preserves .esphome/ and .pioenvs/ + directories in the target if they already exist (for incremental builds). + + Args: + bundle_path: Path to the .tar.gz bundle file. + target_dir: Directory to extract into. Must be specified for + build server use. + + Returns: + Absolute path to the extracted config YAML file. + """ + + bundle_path = bundle_path.resolve() + if not bundle_path.is_file(): + raise EsphomeError(f"Bundle file not found: {bundle_path}") + + if target_dir is None: + target_dir = _default_target_dir(bundle_path) + + target_dir = target_dir.resolve() + target_dir.mkdir(parents=True, exist_ok=True) + + preserved: dict[str, Path] = {} + + # Temporarily move preserved dirs out of the way + staging = target_dir / _BUNDLE_STAGING_DIR + for dirname in _PRESERVE_DIRS: + src = target_dir / dirname + if src.is_dir(): + dst = staging / dirname + dst.parent.mkdir(parents=True, exist_ok=True) + shutil.move(str(src), str(dst)) + preserved[dirname] = dst + + try: + # Clean non-preserved content and extract fresh + for item in target_dir.iterdir(): + if item.name == _BUNDLE_STAGING_DIR: + continue + if item.is_dir(): + shutil.rmtree(item) + else: + item.unlink() + + config_path = extract_bundle(bundle_path, target_dir) + finally: + # Restore preserved dirs (idempotent) and clean staging + _restore_preserved_dirs(preserved, target_dir) + if staging.is_dir(): + shutil.rmtree(staging) + + return config_path diff --git a/esphome/components/wifi/wpa2_eap.py b/esphome/components/wifi/wpa2_eap.py index 5d5bd8dca3..9da3494329 100644 --- a/esphome/components/wifi/wpa2_eap.py +++ b/esphome/components/wifi/wpa2_eap.py @@ -71,9 +71,11 @@ def _validate_load_certificate(value): def validate_certificate(value): + # _validate_load_certificate already calls cv.file_() internally, + # but returns the parsed certificate object. We re-call cv.file_() + # to get the resolved path string that the bundle walker can discover. _validate_load_certificate(value) - # Validation result should be the path, not the loaded certificate - return value + return str(cv.file_(value)) def _validate_load_private_key(key, cert_pw): diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index e001316a22..a24c1ebccb 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -1,7 +1,7 @@ from __future__ import annotations -from collections.abc import Callable -from contextlib import suppress +from collections.abc import Callable, Generator +from contextlib import contextmanager, suppress import functools import inspect from io import BytesIO, TextIOBase, TextIOWrapper @@ -44,6 +44,27 @@ _LOGGER = logging.getLogger(__name__) SECRET_YAML = "secrets.yaml" _SECRET_CACHE = {} _SECRET_VALUES = {} +# Not thread-safe — config processing is single-threaded today. +_load_listeners: list[Callable[[Path], None]] = [] + + +@contextmanager +def track_yaml_loads() -> Generator[list[Path]]: + """Context manager that records every file loaded by the YAML loader. + + Yields a list that is populated with resolved Path objects for every + file loaded through ``_load_yaml_internal`` while the context is active. + """ + loaded: list[Path] = [] + + def _on_load(fname: Path) -> None: + loaded.append(Path(fname).resolve()) + + _load_listeners.append(_on_load) + try: + yield loaded + finally: + _load_listeners.remove(_on_load) class ESPHomeDataBase: @@ -466,6 +487,8 @@ def load_yaml(fname: Path, clear_secrets: bool = True) -> Any: def _load_yaml_internal(fname: Path) -> Any: """Load a YAML file.""" + for listener in _load_listeners: + listener(fname) try: with fname.open(encoding="utf-8") as f_handle: return parse_yaml(fname, f_handle) @@ -473,10 +496,10 @@ def _load_yaml_internal(fname: Path) -> Any: raise EsphomeError(f"Error reading file {fname}: {err}") from err -def parse_yaml( - file_name: Path, file_handle: TextIOWrapper, yaml_loader=_load_yaml_internal -) -> Any: +def parse_yaml(file_name: Path, file_handle: TextIOWrapper, yaml_loader=None) -> Any: """Parse a YAML file.""" + if yaml_loader is None: + yaml_loader = _load_yaml_internal try: return _load_yaml_internal_with_type( ESPHomeLoader, file_name, file_handle, yaml_loader diff --git a/tests/unit_tests/fixtures/bundle/assets/certs/ca_cert.pem b/tests/unit_tests/fixtures/bundle/assets/certs/ca_cert.pem new file mode 100644 index 0000000000..6d200b15ef --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/assets/certs/ca_cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICzjCCAbagAwIBAgIUW3BzjtekVgMj12/oeXawSswGyXMwDQYJKoZIhvcNAQEL +BQAwITEfMB0GA1UEAwwWRVNQSG9tZSBCdW5kbGUgVGVzdCBDQTAeFw0yNjAyMDYx +MzMxMTZaFw0yNzAyMDYxMzMxMTZaMCExHzAdBgNVBAMMFkVTUEhvbWUgQnVuZGxl +IFRlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDG62vBFkGn +hEu54gh2A7b1ZwesVadZ6u0iaVO7GSWiI0o4nb6xv7ULZbGrgsKNIO6qCV4VSR3p +BfMhF5dFy8kkMzA8dKZMk16tygzocdNum2QQ8BHyIsATL7SGZ33si9Alp30gXv6h +XSlEKYDKHFavkDhWPFNa5+oeHbMS/MxjpOUXIpq32VaFpJr427d9Y9wGjuK8B7Gp +CI5Ub1g2dpC9xSHqQKD3JZokmtc70+mD74AcNWbyxWp0bkW9wOfNJJnAoiwhJxQ8 +yfE37UsUIVc8014NhdhU1K/S0iQuOKfGX1L/GAshv8syQIcDfzJuJdX+5E/leAYD +UEKqRkcLT+D5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAF1HpJ6d+W5WrzOQrGej +41pxCDeJ9tSiSj/KtvJfjEVIpg0hMRTY7nSL7OAg9KGESfx4u1jMwVnyOv34br5B +DTlRl+wF2k7Ip8CNnyZfCC+1SVQZpUt1mVNz8BhIZZ9/a830wCILNQQrVKkSeNBk +SEc1qTt4mIhQZ+M422qAswluv4fz/FW1f4oB9KhCpzUCANjmyERnqTnImjnJu8h0 +jbPNnNsN+G+Roju8UD/7atWYfAUmDjHx72Ci/5G9SzoM5fhgxxu43XYd5RW5wBzt +j4KdKdYlDtOL62mRPKWd40uGnJcieUjisU7noRn0ErMgbUlhLdbXT9X7aNborZcu +x6I= +-----END CERTIFICATE----- diff --git a/tests/unit_tests/fixtures/bundle/assets/certs/client_cert.pem b/tests/unit_tests/fixtures/bundle/assets/certs/client_cert.pem new file mode 100644 index 0000000000..6d200b15ef --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/assets/certs/client_cert.pem @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE----- +MIICzjCCAbagAwIBAgIUW3BzjtekVgMj12/oeXawSswGyXMwDQYJKoZIhvcNAQEL +BQAwITEfMB0GA1UEAwwWRVNQSG9tZSBCdW5kbGUgVGVzdCBDQTAeFw0yNjAyMDYx +MzMxMTZaFw0yNzAyMDYxMzMxMTZaMCExHzAdBgNVBAMMFkVTUEhvbWUgQnVuZGxl +IFRlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDG62vBFkGn +hEu54gh2A7b1ZwesVadZ6u0iaVO7GSWiI0o4nb6xv7ULZbGrgsKNIO6qCV4VSR3p +BfMhF5dFy8kkMzA8dKZMk16tygzocdNum2QQ8BHyIsATL7SGZ33si9Alp30gXv6h +XSlEKYDKHFavkDhWPFNa5+oeHbMS/MxjpOUXIpq32VaFpJr427d9Y9wGjuK8B7Gp +CI5Ub1g2dpC9xSHqQKD3JZokmtc70+mD74AcNWbyxWp0bkW9wOfNJJnAoiwhJxQ8 +yfE37UsUIVc8014NhdhU1K/S0iQuOKfGX1L/GAshv8syQIcDfzJuJdX+5E/leAYD +UEKqRkcLT+D5AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAF1HpJ6d+W5WrzOQrGej +41pxCDeJ9tSiSj/KtvJfjEVIpg0hMRTY7nSL7OAg9KGESfx4u1jMwVnyOv34br5B +DTlRl+wF2k7Ip8CNnyZfCC+1SVQZpUt1mVNz8BhIZZ9/a830wCILNQQrVKkSeNBk +SEc1qTt4mIhQZ+M422qAswluv4fz/FW1f4oB9KhCpzUCANjmyERnqTnImjnJu8h0 +jbPNnNsN+G+Roju8UD/7atWYfAUmDjHx72Ci/5G9SzoM5fhgxxu43XYd5RW5wBzt +j4KdKdYlDtOL62mRPKWd40uGnJcieUjisU7noRn0ErMgbUlhLdbXT9X7aNborZcu +x6I= +-----END CERTIFICATE----- diff --git a/tests/unit_tests/fixtures/bundle/assets/certs/client_key.pem b/tests/unit_tests/fixtures/bundle/assets/certs/client_key.pem new file mode 100644 index 0000000000..6182f45d8b --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/assets/certs/client_key.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAxutrwRZBp4RLueIIdgO29WcHrFWnWertImlTuxkloiNKOJ2+ +sb+1C2Wxq4LCjSDuqgleFUkd6QXzIReXRcvJJDMwPHSmTJNercoM6HHTbptkEPAR +8iLAEy+0hmd97IvQJad9IF7+oV0pRCmAyhxWr5A4VjxTWufqHh2zEvzMY6TlFyKa +t9lWhaSa+Nu3fWPcBo7ivAexqQiOVG9YNnaQvcUh6kCg9yWaJJrXO9Ppg++AHDVm +8sVqdG5FvcDnzSSZwKIsIScUPMnxN+1LFCFXPNNeDYXYVNSv0tIkLjinxl9S/xgL +Ib/LMkCHA38ybiXV/uRP5XgGA1BCqkZHC0/g+QIDAQABAoIBAEpsFwcJNCwf95MG +qcK5lhCPaRQFgdTG68ylmoGUIXvddy3ies+W2X33oLb5958ElLaCRbRyBCJEKxgU +8vBWk50bF69uty9MLa6YuyaWO5QUyCX8I8KzVKh4/zIP81F2Z7xGwy5CzEKED+Xk +Hz6+xoHt094TuN34iaOV2gM/GJsok4Wp/lzsuT3X6i3Nad9YGrV2yL/wv5c542bw +vrFDtYQ/+ADZZPW4+xK0ShiarSqV3iXB2cEjc4JX7yLX1hB4LY8VHRzl+Byjdl0/ +lheiIesl5htl82SFxquZDimDsbilTm7TLW2bbm3b3/oC7DchTx6COBjp90VJqk3R +QrO5dicCgYEA80pyA7tCB0bGnJ7KWkteKddyOdakeYeM7Bpfv17qbCm9ciMw9nqt +KJVZPtAuqZGTpfSJseOCIyz9zloB79hVJ3mdWpGJVvmNM5H+BJyCciXpwfqp64QG +1gMqGlSy/MwsZHqNCsOIvrzH09GFN0LSPNKeXN7GNAtU1vI5s7Xf158CgYEA0U+Y +Qe1qJY4m597spHNFfkGznoFXAjHOoWYHv95902cH6JD4GnYPfwFXxgFsrJhFaFMC +jXlT0fRFAIe4NuUJhGD6TYSJqsFkH3xJkAepvKpfjM5qJ7+PQHRnED/E5OS2Nj0R ++cxBhTEWTw9YiOFBRbj6hlphkj8izVGJZ2pL4GcCgYEApsjiYKx/F33tqnExR7Vj +WEvagswi9S137mQmP4tSKdRzi0uUxWRUUP4RsH4HfzfNgHej7c+J55Nwa4ZIzaQA +vI8i0HP1MyrhIflzqrWgt6BGIDU3R7268fw5YNOv4J4X0Moy5q4lkJzaYNvB96BX +gFrjNceDGSqrfq+P3yNP0QECgYBNQfHTM8ygPA4EO/Zg5ONbrOidsuPovXWlgUGP +ApKy+y6iGxBYxAcIO/in71KrijDkRu+ERKo5rs3hWjcWnAedQyZggnFGA8fvDzMf +5JQ0PTazhGUOcthvVAfOqZsFWZ4f+v6tk0UD4pB3chSdwXcUQyjFeorVLlSsMFJl +R4jmNQKBgG38YFR2bqIc7jJItr+34POXdJ4te8Dm1jJHbo8xXsnjVSaxjc5PGs3p +OuJpwuMwzEuFEnE7XLkQxTJw54OBLMmDgK0XUOPDq6eLzrKkW5NlpejqaQV9Piyo +q1kqbJan20jfJQUGTcX7FXHMUThzqJltHILR1GTW6I9z4k8xdsDY +-----END RSA PRIVATE KEY----- diff --git a/tests/unit_tests/fixtures/bundle/assets/fonts/test_font.ttf b/tests/unit_tests/fixtures/bundle/assets/fonts/test_font.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4066b0a9889c2505d31b953487ac1d48fafaf9e9 GIT binary patch literal 202764 zcmZQzWME(rU}RumVPJ4`3-O)5@W3htX7LXU3=A^vF0O8DJGes`n7+3#FfgdN2lxly zl)ov*z$|`%fq}umJvh|q{=9uB7?{4VU|>)X^AFZH(h2;i!oa}T!N9<fker)X5N+$Q zkAXq@2Ll5)PjXp_0)q<E8U_Y+76t|emh{Bpg8%;+m>HP9*Dx?JaHQu{rZuez?`B|d zlwn|ERLMw9OsOi<5M^Ls<Y8c7Fw4kDO^g?bTgt$|=mK(2Ms7((^OndL3=E7f7#O4k za`KZCSxW+^FfgcdFfd4o<R(@Wu$^a8Wnf^;U|?WS$V<#k4e~y{kb%j`fq{W3q9DJx zM0`S~7Xy>a3<icx55Zx<%)sDsGEXF)-{va=H;V-W0|Uc@RfT;}dLjeEe}O0lmJJ~H zGBAO4Fn~yw4gUog5~CO(@*okA4j5)@0g14+Fn(d+1dA~-fOLVv-hn|6EW*NcfpG!@ zD+2@5KBg}W3=GpDG!q+xDWf<80}}%)GguwN69&Ki9vlyTGcYVL0Eq;oxu!5QFev>0 z%Y5K}2SXyu28Is_42<R=Ii?6^50K9p6c~FLR6ru2kYKvNz`%5Y;RDkJh6*Sf#D`&+ zI7kkJLE<nPBnRRXi$UsPdO>=S*&seXOp01!%t1B}nT@R11}QvXY!D5?$m-D9gyhk~ z0mMf)1DhDS8gxFgKgiLKZXP-xWIi%Rm!~x!6t2ja*7nicd{Eee{D+Ok<`$4zm^h4$ zi-xJAH4U?$+V+6Lgcvi4Rfo?kP~L%=17ahq1&Nd5M^e-x+e5BCkQpF1g6N@!LGA`& zn7fhLFfnS-Aag;O8fFn=1}F`oV?z39?LK;#Pis2}g(0c(1MOa9`$731gh}-SrRtI0 zK&e?HNk1suuwin-0Avn1`lzJ`R94|~1G*fDkIi0?I4(1=sRyY=#@N)1ib48n<c0$* ze96%d(u=MSBnHCB;^=&2Ib=3W9gN17USM)CeK0<{T9`OU9WoolhhdO72*da=8k-nQ z4n%|O0?{xGQjabMlS8IK>X7;9Y+}qn*Mo~ssGcAskIP(`IHmew=74Bqvj~L|NIfA8 zG6RHR>d@IBJ_y6)k!f^sWIj3@#)r|!=D^q>IZ(WUXb^^pgT!ELbQ+`%9fQ<>#6UDY z3{r!R@u?q`!(D!Y!jT@~LykQlJs=EoA2J&zhA)l5)Zn5)=7BISc}m5JH5*+Wh!4V) z+CQovGu^||3ydZ=jEIdNkUhw1k=Y=-(fJIl3m6zU3K)=RMjh4#APf<M$%E8zJ1{Wt z2{14SJYZlD-oU^h*1*6Z8Nk3Gqrku*_kn>y@c;vZ$^-@m^#le6EdvGyT?PgQ{R<2X zMhh4iObZwoEF2gZtOXbtY#%T%IBZ~GaBg5=a0_5y@Kj)6@czKS;CFz5A#ef%Lr4Mx zL%0D0188J_)ZXD6&akva?{qa#_A)Rqfaa4xSOzpV#lXPH#J~(@$uO{RJY!&BT*1h| zz|OFOp^jk<BR``mqb{QXqaC9MV<=-HV=7}IV?ARh<3z^!jH?(oG45nM%y^RV3gcbI zmyCaz6q(eS^qI_<?3j|6GMGx4YM2_C`k59ntzp{DbcX3Ba~*R#^Frp8%qN*|v&6F` zvy`&TW?9U#k!3f_A(qQ5_gTKO{A6Wd4P)(K?PBd`-N$;2^%d(E_7eg}1&#}x75Fdu zQ1q9Wh}Z(LEn+`p`DK-4%Vj6ZG0SnwDa)zL8OpiJMam`0Wy{sdwaZPEn<+P6Zm-;D zx&QJT<#)<ol)oweQ2wQYnu584t%8$6kV3dZp+cQPpTaVQbqf0x#TAtljTBuJy%hr$ z!xiHdI~AuW9#Ooa_*IETiAPCTNlr;m$y_N!DM_haX@$~WrDMuW%F@c`mESA>Rb8mM zUG<>qdDR=L&(zq|IMhVc6x7VsoYd0Q^3__^rmHPgJE3-7?S(p%I;T3Hx`eumx{rE_ z`VGxk%@bM%T0vSzv;(vwv|sC_=@ja!>PhM8=~?JG>UkRo8LBSVTyD7BdU^En%H@sA zS1#Z1oAtN+Z|&cvzpa0}{Pz3L{r~U(|KNGP1q|yLg%~v$4H%6W9T|NXBN$T{GZ;%4 z8yWi;XE82k+{Cz@aW~^h#<Prf86PpeW0GJ}VbWtVVzOd#WJ+PmVk&2<V`^cVh!Rs1 znHMu}WWLS9z>>sL#4?Fx5z9K3T`UJ!F0fo<dBpOAm4VfeH4++AhgmPMeqcW#umBuW z7vM3qNNk%dgRBHNrkLco<mBYk<P7BO<U-^U<g(;y<Qn9<<fhBbmfIuuN$v+qObIF& zC|D{uDR?M^D-<Y{C^RT6P*|z30UA?|ir$I=iouGJik*rR6ptvLSNy8Ppv0*ps3fhV zs$`-RqLiT2q_jwBx6)x{24xB5^U5!kKdUZO-K4rl^%yv&7@#p_pk}F-pq8oDpf*8m zq1q9om=XcUR5CoK0<{i<W9pSos!pyhgPw$*o}MW@rqq@jEVo=9wY+k9!}1l&*Z*et zE&E&hw;?#DydW|4|MCAr{}2A(|9|iQ-T!y}-|>Iz|IPn5{$KxpEd#^<B@7JzC;#vH z-|@fwf7Ac^|K*@r+yB1*z5l!ZcmD72-|oNdf1Cf-|E>O8{5Suv_g~?^z<-v13I8Jg z`Tz6#=l;*^pU^*ne@qMvfA9Rg^!L=?V}E!4-Trs$-_3v5{;mC6{kQ6G*<TL^hQF47 zO@1eS>iX3AspV7C+l6mC-xj=i`sT@-#~}Njl|GAk`sV4gr&pd{dU}e1;pw`kE1oWR zI^k*G)1Ig8PuremJvC!scvAnQ;z{C@s3*Zsd>9y>2tN^e!pFeygz53C$1ff~e|+un zmB*JK*E}wIoXo)R*!QvLV~@w~kL4aqJbL-){-gbmwlXk0TJvZr$i7FF3=EI_7#JSO zgLn)K4@DUm9(=za0^!})zAty5^*+nJpZDI~yU)OIZ|}W5_trq<?&aJIxo3UP^qwID z!`**(zu$d$H}CeV+YPrRZ~eU0dGp`R?>EzKyk%gx5zfGHJ&=Lny5n_=t3_85Ai5bC z;>2Mr1_rKT1_rJ)t~dq;wmIPWd4v=ii?NS^ff1wzNt|&8<1!>Jkxa%(_!NTIQQ%O( zSc0yXaRxS}sHzyJK-4hqfY7KU4$)O0Rg7yG_c1Uq9%5i%Ji@@hc#iQ3;|&G|#yeoS zCyehHe}GsB%=ibwX5wHHW0HfgK_rt5h{TSWxEL6i1Q-~YgkbVa0!(5|5+FTHGE8zz z3QS5&It&a<;58FWMhpy077PrGpvD~oqaLF^BX~swqamXiWc>r91*0WnC}SANG{$ho z2*yapD8^{U7{*wT2m=FS9Ai8K17iYXB4ZLrgfW>hg{gw662xYzVyXtyHB7b4>>w61 z2Q%2W3=GV7neQ<$FyCijV1B^-koge<1M_1B2IeQsPZ=1PpD{mYegRU?z`*>H`4#hP z=0D7Tng20^N@xZa1{OvZEf#H%Jc|yCE{h(EK8qOx1B*FitqB7IizSN{i!}oSiw%n{ ziyZ?4i#>}2iz7%q0|Sc_OCU=SOE3#KXRw5_gfTF%gtJ7jOasZYOlR4}z`(MbWe>{{ z1_qX+EXP=mGcd560Lz_ZImL3Cfq~@=%Q*%Hmh&vv7#LWtv)lm7-DJ57rth)bXJBA? z!19oRf#ng)W0t2Z&%ol(SzfTbWckMO9nAZ|@{{Ek%Wp9I56fSce=K01F@P4YFfcH% zGO{wUinB_vN-{98N`X|dN;5F9%CH)-8Z$7kny{LJ#mrd2D^wU5SS?sBK_UzctX8ZJ zP?jTW2m=FaC<CY!P|Lu;TF2S|l3{IRZDVa`?O^R>?PBd_?O|YG?Pcv_?Ps0HI*D~M z>lD_htkYPhv(8|h$vTUHfps?P90mr~xvcX+dO>{%*2Sz#SeG&|ur6a=!N3MeZJ=d1 z;8qVr34~;10Ikmfv0*fbjSYiV@PJxUEDWp+Yz*uS91NTcTnyX{JPf=Hd<^^y0t|u- zLJYzTA`GGoVhrL85)6_IQVh}zG7Pc|at!he3Ji)2N({;jDh#R&Y7FWO8Vs5YS`69@ zIt;oDdJOsu1`LJ_MhwObCJd$wW(?*G77UgQRt(k*HVn25b`16m4h)VAP7KZrE)1>= zZVc`W9t@rgUJTw0J`BDLehmH$0Sti*K@7nRAq=4mVGQ965e$(GQ4G-xF$}Q`aSZVc z2@Hu03=FLdZ44a@T?~^LrZdcCSj4c9VKKu}h9wNk7*;T>Vpz$rnqdvYI)=3j>lrpM zY+~5Lu$f^i!*+&k47(Y2G3;U3%VN(^$dJO2%8<$8$WYF(fFYkDn`H_^DMJ>^IfizI znJkAHiok)F&QQj(on<cr0~0&T35FboYR2yj%NceuG%zGH<bhRyh+Kvm7AJ-zhDL@K zhG~rKj2xi60nQDUELIGla_a!2Dgy&c1B*9{4=Ao#92hECtXb?>oEe%Kx*3`ndKfwx z`WX5dCNT6eOktSHz`!t>VK&1YhFKuv85kG}7#J8qDIT29K`Y5XYtq1SpnQdlLF>{M zFfcHDVPIf%U|?XJz`(%xfq{XEhk=2~gMopmfq{W(2Ll7s15hGhU|^PEU|=?3U|`N+ zU|`<EzyK--SWG}}Wnf_0!@$7uhk*f<##u`k7+4Q5FtD*OFtF(`Ft9~1Ft9CPU|>7J zz`!oRz`!2Cz`#C-fr0%B0|SQ$0|Q3@0|Q3`0|Unz1_q8R3=EtC3=Et$3=EtZ3=Eu8 z7#KKjFfefbU|`@fVPN1YU|`@{!N9<EgMootfq{WLhJk^52?GQ72?hr4FANMk1`G^5 zISdRuCm0xbSr{02Js22xa~K$SmoPB!o?u|$V_;z5lVM=s1NE?L7#R4rFfj0aU|`_a zU|`@+VPN2&!N9<Og@HkUgMmT7hJit#gn>a|3j>3|9R>zL5e5c98wLi!5(Wmr4Gau| zZx|SaWEdEPA{ZEidKeglwlFXVePCb^R$yQdu7LF1h2JnRh^R0yh&V7Xh*U5zh-`r3 z8w?DhDhv#wDGUsvI~W+m1Q-~^Y#12CrZ6yw?O<RKXJKFvw_#uqU%<csT8}8<z`!68 z!@wXhfq_Bd1OtO42V_J*vVeg>asdN_<P8P}$uA5HQZft-QXUKpQXLEoQg0X-q(c}O zq_;3I$mlRI$doWJ$Q)r{kQHHIkj-FVkUhe{ASc4WAeY0yAh(8rLGA|wgS-s`gM0%6 zgZvo=1_coY289p?28AgM3<`G`7!(y47!(sAqYp|v3=B#U3=B$Z7#Nf}7#Nfz7#Nf{ zFfb^8VPH_PU|>+GVPH@>!N8y@z`&rIz`&q7g@Hl!4g-Ul4g-T)4FiMP6$S=%69xwL z4h9DG7Yqy<CJYQ34Gat#7Z?~c6&M&aD;O9w&oD4(aWF7wxiBzjbuch!onT<lmSJGf z&S7BC-oe12!@|Iz6T!fsvxR{{mxX~r*MfmTw}yd1cMk)D?jHsQJr@QBy$%Kjy(<h1 z`Wy@l`VkBa`U@Bs^xrTr7`QMn7|dZ{FnGeiU}(U=VA#UIV0eRp!N`Px!Ds>lgV7xZ z24f8d2ICe62IB_|3?@1Z3??}Y3??fW7)-t}Fqk?pFqqC@U@*PHz+fiBz+e``z+kq5 zfx+wx1B1B_1B3Yz1_tv#3=9?_3=9@)7#J+RFfdr!FfdqlFfdr&U|_IPVPLQ-VPLR2 z0vV~X_F-VKZed`sKEuFZBf!95<H5jS)55@DbB2MzR)m4UHim)0b_)Z89R~x0od*Mh zT>}Gy-5v%8yEhCB_6iIP_6ZCO_DdKT?C&rzILI(CI21reejFJX7#wXF7#wFXFgQM7 zU~tl4U~np6U~oFZz~C&wz~EfLz~Fp?fx$(Efx)GOfx+bj1B0so1A}W01B2@x1_n0? z1_rkr1_rka3=Hl%3=HlK3=HmP7#KVZ7#KWy7#KXxFfe%XFfe!~Ffe#-U|{fk!@%IB z!oc8Fz`)?OgMq=Dhk?O6hJnF*3j>1>2Lppo0t1831_lOS4h9C_7zPI44Gau^JPZte z2@DK=TNoJp85kJ+Qy3Wh4=^zJKVV=8&|zQ*NMT?ISi-;%@PL6KP=SFV&<8Sl6?lh% zA&7^8A;^J&A!q^vL(m=uhM+$T48bl848aWy48cbj7{JAy1p`A!4Ff~S0S1Op1_p-E z5C(?O84L`e7Z@1A1Q-~?0vH&=au^uGrZ6ysonc@I`@+Bw?!v$jK8JxJ{0jp^gbf2j zL<0ju#1#gHNDT&t$PxyI$UO`Ukv|w1qC6NFqLwf)MEzl4hz?<3h~B}#5F^3B5L3ax z5OalrAy$TgAvTABA$AV~LmUSKLtG34L);t&hPW>b4Dk^R4DlNn7~=mhFeGR&FeKzK zFeL0@U`XU(U`PyMU`SlSz>s)_fgwqQfg!1Yfgx!F14Gge28Lt@28QGo28QGl3=Am( z3=Am|3=Anf3=An37#LCo7#LDR7#LDlFfgQkU|>j7U|>i~U|>j_!N8Dqfq@}ifq@}C zgMlG^2?Im=69$G16$XZk1O|qT6$}g+Zx|Rd4Hy_QOBfh3w=ghd{$OCp@?c=dYGGi= z+QYz*^@V{U+k$~1yM%!u`v3z&4hsWAjtc`rP6Go&&K?GaTm}Y)TpI?4+zJMU+&v87 zN-xiZfg!Jkfgx`P14G^i28MhC28R3$28R443=H{i7#Ipv7#Ioy7#IqsFfbHcVPGiu z!N5>x!N5>hz`#(rhJm5*4Ff}w0s}))2m?dW1O|qp3k(d!5)2H*84L`?a~K$kFEB8a z@GvlxI504j<S;Ol%wS+Bxxm0s%E7=;>chZLTEW0jx`%<G^aBG!nF<3#SqcL~*%AhZ zvKtHx<su9W<t_{i<uwcp<vSP{Dg+o9Dgqc7Di$y>RNP=-s1#sesPtf9sO(^1s64~K zP{qT*P!+(yP&I{tq3QqwLp28jL$wbBLv;=VL-hs*hUy;-3^fi63^fxN7;4rqFw`7j zV5oV(z);J<z)-8gz)%~*z)(AffuVK}14Hc(28KEn28Ox}28OyR3=DNQ7#QkV7#Qk3 z7#QkX7#QjgFfi2rVPI%5VPI&;VPI&Oz`)ROfPtZrg@K__gMpzjg@K`Q3j;%w00Tpl z4+BHf1O|qtD+~<H3JeU*1q=+$2N)Qd|1dDL1TZkP)G#o#>|tPNdBDKXs=&a|n!v!& zI)Q<q^#lV$n*swvTLc3`TMGk2+YSbXwm%FE?IsKi?FkGF?Nb;S+V3zhbeJ$Obd)eK zbR1w{=wx7E=yYLV=<H!&=sd!}(D{dfq051Rp{s*|p=%2RL)Q-mhHe!GhVBdohVB&% z4Bc-S7<xPy7<%R~F!X$2VCYp~VCaotVCbE|z|ebvfuZ*U14Ew<14CZ~14G{u28O;5 z3=I7`3=I7p3=I8e7#RA0FfdFoVPKe$z`!tJ1_Q%{Jq!#J-Y_ss)L>wk=)=G;v4w$Q z;uQvlNd^oIlM)yhCQV>qm~?=FVbTu<hRHe%43je$7$(nPV3>S|fnkaQ1H+UU28Jm! z7#OD9U|^Uk!N4%pf`MUb0RzL-H4F?>zc4UNb6{YYR>QzB?FIwGbO{EA=`IWm(;FBV zrmtaOnEr%;VFm{S!weS&h8YbE3^SH6FwD5az%WyVfnjD11H;TU3=A`GFfh#GU|^W# zz`!u8fPrDw3I>K*Hy9XZ%P=s^PGDe|J%fQ^_6r7vIW`Oob2=Cp=Imi$n9IPxFxQ5G zVQv8f!`uxF40B&FFwE0nV3?P}z%XwG0|TgmKR<+lVLpg`gMndz1Ovl@2nL1)GZ+{a z++bi>D8s<8FoA(#;RFVTg?ktn7MU<GENWq3SagAbVX*`Q!{Pu2hQ%!m42usiFf9JV zz_7%Ffnmu628Jbj7#Nm(U|?7(!@#h#gMne`2L^^^9t;f27BDa@`@q1k+=YQ*`2+@r z<u4c*R_HJ=tjJ(sSaF1bVWk8E!^#>4hLv|17*@G3Fsxd^z_98I1H)<u28PvB7#LQ+ zU|?8d!N9PlgMneq2?mC>91IL=6BroQ?qFb8C&Iw6u7H7I-3|tZ^$ZLQ>jM}V)-PaS z0Bt$gkifvOVFd%jhBpih8yy%JHcnw+*m#72VG{!b!zL33hD{|544c+4Fl>6jz_3|? zfnl=;1H<MD28PXh7#KGHVPM#z!N9P^gMnd70|UdB3k(cf85kJ0S}-td?O|Zpx`%;b z>lX%wZ7K{5+X@&Mwk=>_*!F~hVY>hW!}bUUhV4BJ4BM|TFzn!9VAx^8z_25MfnmoQ z28JCs7#Mb{Ffi=&U|`regMne^4F-l?0t^hh5*QeEwJ<R3TEf7v>j(qGt|tr(yEzyb zb{jA-><(aH*xkXvu=@Z5!|p!}40{|H81|GfFzngDz_8~71H)bg28O*c3=Df$Ffi<W z!oaXkf`MV51p~vr8U}`a7Z@1!b1*RMw_#w|-^0MLe-8u00Tu>^0|pEX2Vxi)4s<Xu z95}<kaFBt4;h+Np!@(K`hJyzf7!H16U^pbhz;Gylf#FaG1H+*$3=D@pFfbezU|={L zz`$^L1_Q(43k(cLG#D6;Brq@>nZv+v<NyQ1Q4R)%qbdvxM|~I=j+QVm9NogeaP$EK z!!Zd4hGRAi497AU7>>0tFdSRKz;NsW1H*9^28QDb3=GE|7#NP{Ffbfnz`$_)3<JXn z9tMUJ8Vn340vH%hbTBZSIKjYh;s*o6NdpFklQ|3wCs!~qoP5H-aEgP0;gkad!>IxW zhEp>b7)~8vU^w-Jf#Ea@1H)+(28PoG3=F5&Ffg2c!oYBbhk@Zt2m`~J3I>KVD;OBg zykTHCtHHo<)`NlJYy$(s*%J&5=Xe+x&N(nJoSVSFaP9~L!?_;}4Cf6P7|zEqFr1&l zz;ONs1H%Oc28IhE3=9_<7#J>WU|_iLfq~(o3<JZ(7zT!ma~K#d-e6$3q`<&%DTIOH z(gp^GOHUXWE(<U)T=rmKxLm`)aCr*@!xaVwhASQn3|D#>7_J;(V7SV_z;M-pf#K>L z28OG57#OZ;Ffd#zU|_hmg@NJP2L^`gCJYSM=P)o_f5O0ULxX|gMhOGMjROn}H(3}M zZYD4=+?>L|aPtWR!z}{_hFcRD7;c?mV7RToz;HW(f#LQB28P>T7#Qw2FfiPyVPLrP zfPvwz3j@R53I>L|I~W-5aWF94D`8-`cY=Z8J_iHC{TK#@`&$?o9`G<QJP2W6crb;5 z;lT|ChKDi?3=e%67#=n-Fg!fL!0<?hf#FdI1H+>h28KsR7#JQ4FfcrhU|@LM!@%(P z1Ovkp76yhV9t;dmDi|1^Y++z{@`8cksSX3f(+mcNr)wA(p0O}6JhNe7cvix|@azl& z!*dY^hUW<k49{mUFg!oO!0`MB1H%gg28I_M3=A(mFfhE-VPJTfz`*cw2?N8+KMV}7 zG#D6Or7$qOn!v#D>I?(Js}~FmuSFObURN+MygtCd@cIt}!y63-hBq+`3~%NzFub|J z!0=Xqf#Gck1H;<_28Op&7#QAOU|@L1!@%&)f`Q>(0RzLkJq!%*zA!Mnw_sp+-@w4| zeh&k~2Mz{?4=xN0A2JviK1^U>_;7-O;iCit!^aK=hL0B*7(O{LFnnrZVEA;0f#I_Z z1H<PK28Pdj7#P0DFfe=xVPN=Dz`*e33<JYg9tMW5F$@e}OBfiw&S7BqdW3=D>mLS& zZy^i}-<B{ie0#va@Lhy~;d=!G!}lc&4By`{F#IrKVEB>3!0=-Z1H+FC3=BVc7#M!q zFfjbgU|{$;fq~)Y9tMV=e;62kSuimCDqvvvwSa-)*Bu51(16o#9R`Nq84L`+moPB= ze!#%+M}~pnPX+_SpB)Sge;F7U{@O4w{B2=i_`8RJ;qM;?hJPLm4F9GuF#Nl~!0=y$ zf#H7yc!V7^YQxA7!NAC{hJlgc4+A5k2LmJH1O`UNI}D6WA`Fa7F$|1MYZw@r-Y_sS zn=mjkH!v_VA7Ef)5n*6tNnl`PnZUrva)E)7)qsJKbpit;>k|e>HXQ~=wgv`9wi67D z>@p0D>?sV4>>C&u**`Eaa>Ot&avWh`<g{R5<XpkP$oYYRk;{aEk!uPABi9=SMs5oR zM(zm=jNES+7<ptE7<pnC7<r~JF!EesVB}R{VC1b}VC22Qz{sb;z{pp^z{q!nfsx;U zfswz2fsua$1ET-~1EYWs1EatK21bDw42*&j42*&y42*&^7#IZ~Ffa=KVPF)JU|<w7 zVPF&rVPF(0VPF)R!oVnWgn?1$3j?FD3In5X00X0N2Lq$<0tQCmGYpI(8VrmgJq(N@ zYZw?s?l3Tl$}ljBIxsMb7BDc1ZeU;(eZjyerog}`c7lOXoP~i=+=qct`~d@_gaZSk z!~zCJi8Bn0k_-%tk`@e%k_ilql1CUAr8pQEr6L#@rFs|`rM56IO1)rUlvZG1l#XFw zl<r|*l)l2iC?mkYC}YFGC=<cJDAT~eD6@uvQRW5%qbv^tqpSr3qih8OqwE0&M%gb6 zjB+{*jB*(ajB+y=808)?Fv`m?Fv`0yFv=$|Fv@o@Fv@RXV3dErz^Gurz^IUe1)pGG zRJ37WRIFiORJ_2zsHDNbs8qthsI-NFQJIH<Q8|WzQF#pmqly3nqe=n;qskTrMwK57 zjH)3FjH(?BjH*`{7}XRQ7}a_h7}ZWNFsgGfFsjEeFsg50VARlHVALpKVAPnyz^HM9 zfl*U{fl;%7fl>1e1EZD>1Ebay21acb21e}+21e~G42(J+42(J}7#MX$7#MY17#Q_f z7#Q^$7#Q`wFfi)dFfi(GVPMq%z`$sr!@y{e!N6#+gn`lE4FjX01p}jD4+Ep&2?j<Z z76wKm2L?u?8U{wA3k;0L5)6#SF$|2xGZ+|+pD-|*h%hjk#4s?L>|tOuWno}6O<`a( zUBSR;dW3<|^bZ50SpWm0*&GH&vpWoo<|+(~<~|IJ<}D12=6e_z&0jDuT8J<(TI4V= zS}b5-w79~+Xeq$JXz9biXxYNRXnBEw(TazG(aM8?(P{w$qty=vMr#uWM(Y9wM(ZgI zjMh6C7_ILxFxqf1Fxmt#Fxt#uV6=I_z-Y_Ez-a5jz-W7ffzeKYfzfUS1Ebv=21a`a z21fe|21ffG42<@F7#JNq7#JO<Ffck?VPJGrU|@9gVPJGDVPJHe!@%fxf`QTT0|TQI z4+Eo<1p}kg6b4489}JAnA`FbqHVll;DGZFx3m6!kPcSgLurM&X7%(up<S;P0%wS-2 zxx&Ec%EQ3u8pFWoI)#DJjfH{HO^1QeErfy5t%ZTnU5A0uy@G+!{Q?7{hXVtn#})=g zj}Huto*@j3o=X@Qy+jxoy)qaWz2-15dfj1Q^p;^@^iE-5^j^Zi=>3L)(Z_^=(Wixh z(dP&Qqb~;oqi+TSqwf|5M&B<CjD9){jD9H$jD9;982vdI82v3682vjK82yhhF#7*t zU<`0!U<^oMU<{bRz!-3XfiaMSficj8fiW<Lfids^17qMD2F4%-2F9Qm2F9Qj42(g4 z7#M>S7#M@sFfax`VPFgiU|<Y+0l}dL42+=-42+={7#PD$7#PDk7#PF8FffKkFffKM zU|@_8U|@_0U|@`x!N3@)!N3^Vz`z)Jgn==NgMl$hhk-FFf`Kt=4g+H}3j<@c4+CTL z6b8oVI}D65Dh!M<ISh<3M;I7m1sE7(V;C4?=P)qFK44&slVD(s3t(W3o58>scZ2~v z*%EKVz!=}cz!<-QfieCK17m^;17ku017ku517pGg2F8Rx42+3342+2-42+3u7#I_8 zFfb<ZFfb;0Ffb++Ffb-<VPH)9!oZm9!oZkZz`&S1gMl&m1OsCV0|R4<0Rv-73Ik)x z3I@iMCk%|KDh!ONF$|2U8yFZ<pD-|{2{16GxiB!Ml`t@-tzlqH`@+DOZo|Nsp2NVH zzJ-A?{SE_T1_uLUh5`d)Mg{|8#vBI5j0+5mnH&s^nH~&`nNt`TGw(1kX0b3ZW;rl0 zW=&vV%zDDWn61OWn4QAFn7x95G5Z7qWA+;c#vB(0#+(iY#+)+@jJW~~jJYukjJY!y z7;|qhFy`qnFy`ejFy>8QV9Yzfz?jd$z?kpAz?h%Gz?i>)fieF917m>%17m>$17krA z17pDv2F8Ln42*>#42*>}42*>v7#IsbFfbOmFfbN%FfbNfU|=kkVPGuIU|=lX!oXOf z!N6Ej!oXN^fPt};hk>y)f`PGg2?Jy42L{G68wSR*4hF`uD-4X~3Ji?pISh>DI~W)% zSQr>90vH%8<}ff;ykKCgG+|(@Y+zulJj1|PCBeX0mBPSSwSj@L>JI~BwFd)Z^%Mri z>IV#rH98E8H5CkuHAfg2YXuk>YhxG~YgaHZ)_!4NtaD&stm|Q5th>R$Sg*psSYN=v zSigsXv4Mkuu_1(kv0(uNW5XK;#zqSU#>N%~#>NW_j7>5Oj7=E~j7?h@7@HXw7@K_< z7@KD>Fg8D7U~Dm9U~H*jU~D<Tz}PCnz}T9=z}UKmfwA=m17n*D17q6+2FA8K42<m> z42<n142<mu7#KTv7#KSu7#KU2Ffev}U|{UDVPNd+U|{UL!ob+2z`)p*!@$_JgMqP| zg@Lg<fPt}l4g+KN3kJp>69&ef1_s8SGYpKq5)6#JDGZFg8yFaS|1dE2c`z{cO<`c{ zd%(chufxFDU%|lGe}sW?f&c^Kgct_K2`d;FCwyUGoan&7II)L;apDaI#z`s+jFSo& z7$@yvV4Tdsz&JUCfpPKz2FA&67#OEmFfdMOVPKqcfq`+V3<KlT3<k!jTNoIpF)%Pr z^I>3|HiLn2+7kxG=>`mp(`y(Qr=MV8oc@FXG~vrQLxzEIh6MxTj1UIK83hcCGkO>p zXRKggoN<JKamE7%#u<MY7-vc_FwQh#V4NAiz&JC9fpKOB1LMpk42&}mFfh)%!@xN6 z2Lt0Q5eCLt1`Ld|d>9yKWiT+#YGGiUwSa+f)*c4NSvMFMXMJH{obAKFIQs|#<D3`< z#<?O4jC0>GFwT3zz&QU81LHyy2F67_42(-y7#Nq%VPISy!oavvhk<dm3IpR>8wSSp zB@B!k&oD4<abaNGc87s+=M)CUJvj`F`%@Sg57jU*9^Jygc#?;K@k|Q?;{_Q8#>-b2 z7_YBkV7$GAf${bO2F5!&42*Yr7#Q#TVPL%5z`%G<gn{wi9tOtyB@B!Y92giM$}liK z;$dKX%)`L=M1g_vsS5++vl<4*=SLVAUn(##zUpCMe8a=Q_;wBh<9i1N#t&Z@7(eY{ zVEi(Lf$>`d1LKbx2F71K42*x)Ffjgm06KqwfeEx{p3#Nr0s}JxJA>XvMh1PGP3$ZT zZ;dvxvEH%S#LUF-)`(#vGf0>fB)o~8jq#7oCPt9Bv7n-$y0M_L3ZufG8#kCP{54Qv z>Huxz{{T9VfY}3VCWES=vY@!BvM6IlMMcF2rii~QK2%hIrlOb_DwrY|AHdWxnktJb zgVa5!sHk9y`0(KaXc`Kv5VXginL(a`LD<w-l-bl+)Y#P6R2hsRdXz<tMM3yO1u6j9 z`ESOD4<K=nfgl$^=0d^e21qk7D4IgdQZ!XG1=+3)Hb+rZQPddX;(s$3AAq!1FlPKy z05cF)K&HePz-EEMPa5PxWl@k%Am)P276q9J!XR%|{F?#S5Ax*S6(2rSfFPJaa+^BX zZK6<rio$&h@;lT-V^BzlLPHjADue-Y>4%C65Cs+h2LWg*_ybb}V+J_P89?r2%m9Zq zD3}=;Di|2R@gWSdTiH}u5bl0KV^Da2Vg_tlMMVWDXe+?J!O#oRWh|%+4o_oIV?mJL z;SNF7%E(Z`_yA@nD0UJ41;wYbC_*12lI`Gds$hy>y1>BAz@Q3C2_QFSfWi|Lpdgw7 z;-?IT4-D)K3?O$Qy9KfWhA{(_3PEcH8BG;MLFp6ZHLx5w9Wzvb<P<?E6O@8MVaNbF zTZ7qyK^S5t$XsJk>V?J&EQmm<4HN?)*MQA~>4T&@L1j}=Is>^#Sr8J|#-_%CilQK& z{+j`E1;nI(Gb)%Oz)Z%Bzbh)hp^jo6H#ok);S36GrU+1|eW+l%P*L$u0i4%B{Xs}N z1>3DG3QM0LHz<o5n<_%x&J+QP(+^-fDi||hNeE;h*efXZg3W@)7}x}eImV)(&@u-5 z18&d<aKZ-#1uR%V4nw#Ll;*%b0J#Pn4yMYYp!fh=4RRDHnSev#-;4@S*?_9o6qMpX zxmZz9Q4nE2DEt0h!T11dJ2*)H%>c8J<53(GejtB9LIn~dAiu!kq5_<K7&AaNgPl<E zPvOG{P<8<&esKQhXJAkS<rhIkSZE4@toyqHoKqMxz=8Rp;@=E#+C_>Bki8%biUEk7 zpb!A13{X0Ng&)YxQ2Rk~0!rK<2Oz=#>IZNrfXXm%+5(vgEgxV8FlK<_5o9!^Sgc@R zVgRRerU*!R4Js9cVW}OY?w<m@y#C(-$}J4cpj-!1CkV=U@Dd257@R&UAbtcz7y~$s zfXf1KNsGuQpb`a^Mj&B|L4xWM22d@5aGRniESG|F>H|plK=L^_9;6X@5@IW;90Az{ zj#Z@c1j9B^dIYbA0h=StAPy;6kmCkq2D~nVgeb@uP>djGP?BI|VEEqwE}w)M7+6g~ zX%bYPDuVO8vY@djQ^Y?7Q2JoZ03~g3jrVWH2T*FQsQ9}A<P=C4g5AQ;zyPXiA#tk+ z%3XrsR0S#|{>`XheDF^Jl-DaN{(@GAA<_gWPl56UI7fg&9+E#m@dVNe3Oi7(2CCX% z#m%1`NcKYXgYqFbRfEe4K}ejz^n<(&EuBElM%WE5lZ*wG!FDSO!tDH~PyvcKricpA zh!&DvVD+FJq-?5aswfBwpAR1xA3*aDNHxN2PEdG&<Hb}_umYkCWC2JOa=sP>=W9V_ zQBde9f=Vce>p|HN6lkEj=t0H58KBY?<a%Vi+#ov?1wrMhqNy@0yuo43?D63PIGjKQ z0I2-}b~~s9R|MB~Ag6#52RK}?n5zhh6H`#iM5w*+*PsHN(GdO=2e|=MgMwmS8JvGW zDG-#BK$#dE_7xv07(spjB_@yn$Ysd>U<HMNqM$N3L@O$oE}(@ws15_w?xx0Izk=IS zApe5Q0%J(vFnfSFIP{8w^+IZV488wmFnfSQ1Ed+@H&A&A3I|B6fKmy#z5uBNmvazn zL1_h)84&t-L16+ar$KcXD5W5Bf&wToD=I*#0HGdIE<)N-u-qr82(D?MK?boB5}+Ux z{;mKeK5$eZrB6Yyy`V4xmwAw!1hyNNjX)_1q#xn}<T!x10c1NUZG%c@QS>?rRLFw; z4Qp9}Ohr!*?2tMJl*$-0KKxzr0hH^}@;o>#Lh>D`oB=rq<iQG1^BjbsWiz;3f#z?J zYH+-RS|Q*z6ezAC_yfpSpd1Ej{381alx{#NQWTUvl|gYY3Tnkbbiqhw4^Vx;6ak8Q zq_9*5g(bN43Jy<{lnu@mpw_&yAj}j54T>>H$%7F42U-)1h;NXeK=m-BJqB-sf^<Ul zfKnEO`F91htcJGd!0`l1TaXqVs163_H&JD9c@5G8YD<7<ForZuKqtvT+L@rT02D{y zmNTf#`v7Y7V3u_tH-cOS!JrTXV}!#%4R>&*0%>Ew${CQ^ppsZnSrpWw`S5|+16o-y zf?DpdI2DG)3)Fm&AHePf6QC3UW`I%`w4Q?Om0^Xpe?b!9b{?pI2I?!YGl2RE;Ftl2 zBgCOdVaF7~04i%iDO?m1YLJ!;xHSn$)*upLHIiOt53pWvSpY7nLHSEi8C+w4!w*zS zXMnQ9hYH3FaJdU^M>9o$+TWnqQU>KFa1K`#MWlI<OTj50mZSd7Ku-G*_d?UHF{lIt zw>Ci`UjeEgAcYn<v3-E+gZdMci%mhbA*3#b*5;5>7-A(jWq>RMhocPx1CtE12Lq_g z69m;;pt=|oE5?G1I?#S8ENuQMK*I*yegKCnE4WtxYZZdR7gXXafcyn=AE@YHil~4z z=fL)X!v|uYF(@xUav3y#g3}eK;Q9wHFTp{|z{CJ^BQpapIJQB(Sa8j0EXt?@YP@~` zRUV)w2Bf|LwHv{09B^NfAEHMP6pPT-H#m`iLIYGt{n-Jo_CZZn21dADp!yBmhXsWR zQYj#)EVu=hM8UlU7>DrzIR0U7<pkAj%1~D_$$%T_Oc$V80#@EY;tU+akU9=jG9cAb z9~d8e_y7ru3UGk{ElZdpKqnc3S`MJvR}tC*Pym&Oj1NF65$Ztk3i3Iwx(t#OK{)_g zmqFuJn1Mmu6r6&=c?-&d*aS=Z;2skwIl;<#gkDxqEe7%pcuc?;oby1T4vt|^$^iEO zA$=E66CaeYm?D@WK<N;iF2H#PQu0I7Jt$p(1N-j^r0@fmSD-io*LslpOBB{O0tE;- zDJp<9f(fKJ28Ru(Z3G!z0mTE849Gtqg`my|D6@fr1<5{8yn<Vfpxg{DLqJ0(pg00` zXA$8Jbr-(+3*5E^J8uT4Mn~x71=Xd9dJB|?K`w$=1gY>q#V$O|Ky?;MxeBTyKzSJ4 z%K(?(ARfdF{3IlgLgSGi)IR|E0Mtf<#386C0A(C-+q{A)0u+@XK8kz5eg~x(kUKzS z0?2l7Jp~$I`nv*@=8&8Lu@h8FK*lY=qg^2XfYT4CB?@WRgS3G15j5FB>K{<z0o4P{ zkT7G+s9^R0SLsOoE?9d2TIaxeTpu9G4{R)`i3Ktj>Xr}Sv?$ELU=A$<z@;Kczo@b( zNCO0eTmvx#JRbM~+y{k>SAuFKQDIPB0UDVBCH=n!pcW&zodOQu3!wfdE7YHgpt=)e zKE%)9G9MgFpa6zg1|`9wkbxF>+0X0&>Jfr+04OJb#vman8WeVra0i#bkfaUrCb;B+ z*Buv_B0wXUppgwwp90+a0k;#t`42qu2@<b>mg8W}AlHCP4QLez;zKGGXgX&0U{D5? zfnXPbM?}G42r>;^qJY{_5X_hXt!F@HfGvSI6vBm)p#C-@u0gfFpt2x5d>J2r+yd&h zf}32h{L1VB@)sy2f=Y03?+sKALPlhvqY#j?0#t`XN()Gagrsk%-B1ctb%D-qg^p2z z+yII#*mwk}E&=6ZCUCyI!0f@m4vH03u-}yhK{X|)URD+amD><oKY$_=R7ZlW26_75 zj1SPB87QrQ>oL$MB(nztH>hM}1h)x5Inh`Y)FNVhPysHBL9S)Y02u~}8}JUA3Z@H8 z7Z`*Y)InnfpppQT8zDInoCCnA4OI-{1+aHPt^qT!6VQADYK1)jZ9P&I1m$y(qZuE7 z3TjYPfx>~=gV}?@7?KV^brmQ@f!bdn7l6_m$X#FzY8`>v0-*W=oaaE}YY@A^<qL!f zBSAt???STzm;xmNh!TkVm@a_Zoy?#X0LZ+*D?mPk$T4Ps$AG}C15g?Tg$yX=L&l^) z^%N*}z%;0&0i{1s0sxKogX02uWEUJ4kkMVn49KuKq;LTR0VqFw0NVu~wE?9>RQo_S zLk99ewn1VL;tLQ7PRkJe(x8|G=>=hsE{J=LL3s+^H-eY}Awl|K7*rlY$Jg0Ga{-Xt z2#RJ<;Zy-GOTgt)1ZV^eT=zrkIZ%8;M}k1<l<@($x(B<9feDn(!R=L0KN}RYV0Vcc zgGU%aL%g8zqYHlxKmiYqBL+r>51_Ql_y9C^4H~Hf4?u!)4zz4!1dWMvgW4Yue}YO0 zkUK$TG}t#_bs$r~`GP^!6x7awly%TV0Umg$K*U=GIQ;oRt#U?C8y=KzK`BjC8Iq4O zAZ?5fkc<Sf2vlG~CWAov86_`)^9(5Wz-v}`oWe^sP%jAVRuBPpJcxlEgOU{}p@8!W zGbF!)@;AsHkl(?*SdgnB<KUo{71U->`vcsxftKkI^TBZsCcvo*8W!Nd0Hs9+us!PV zu}ElX2=W6MW7q<5KG;Br1t1b62oeHeP^%kM4MOt>*nDONeQ;_Oh175u{s5PXpqVVN zj46l&)l|?F1NRRoqeE(0Pz*sW15+SJfH2r!Oz<&HW>A?6N>!kqCTJW66pElU2}&QJ zHXW#>2k8T~rodeWkip<g2a5-$2$l_yvYQba%gln{(KbkpVX6#C+t6$QE_0X<fQ<a( z0LmYbln%)wptQq)Y#t=nQNcWJQ0oCUD+ThOBqORDK@kM1%Rv4`a$`jWx+@WG<OkK3 z5HrE<1m_a$=3+G&(`?WQ7a;#zfXDB}LFF*022d77Hx<;bBqBh;=@%TH@}O}Vh>yXk z7VK6?c?g=Dfsc!V;suPsVStDquvi5s0f4d|)Ldo{22qf?#-M&8v^NY&qu^0ZP)D<( z;sdC<1`oA@oeMJNuK}nm{4W5mYe4&M(b{y7o<AssgG(n!iw>Ny!4s?C3LiYO4k-f> z@xcx$uRv`%W6<0J*hQdmMX))bvI^80_`3p@`XDX>wSF<o0LLe}W^jY@6eL}M+ya_K zMvR6-)7b;itP^NV9O4*IQb0HdRMLaSu~;DKKp2q@7)=o-LDB%4L4O>OjA3A60ChAT zfb%EB6mW?v3~sH0#vUQHH>dyy1u(=de;mL;3>xjm&<_b0GW25!6HreQ;s$7#fJcTZ zDj==^hX|;u1-XM6>JKd8fiMLU9w>$&c?Fc_K&??&p9#`W1J#(|*#uEzL6BvjPyi(q zP%Rt*?RkBu01xCK(g;7Or4ET-aCm_8k|ZOzjRtCyfm)rQl28!hFHo9?Vwl%Jo`YBi z8Jhx)b0f?Lw}WA2sWAFz1gL)mpVa*~17alHqo5`wq#X<@N8sf$*qx#jnuSq@GNQQ+ z;$Kj1gN7s2bs+CT(-gY<u$H0N&4rbrAR6XxP`IM`9cLMeZYoN80Tp*xgA$x>AnOy9 z!TnosYa5hql%eGoxP%7hD^Qt*+}{Pc4hM#`$slvb;IV2@Yad*8g4$W26a*f@2e}c{ z$$?h7pfm%H`wyUYGip4e<Znpo293FZVgoaOgIkz?4M2l6$mtGj22xr9&8~pv*^ts4 zB9O3}fhC_K+=7}uASOZ529jB*@dtJhID|#P@dtAeXaxz#YoLS%F$k0lkc<KM>0o(4 z8dQQp{RJ9D1?N~uKMK@Z1Q~=BPcZX9p$!oR4JIP$JkT62WUNmVG=>1LJ3%!Sd|3f_ z@(wyC4;gO|7X;1WgGL4*JvmSs0@Zb(iW1a(1~>OBDnQe7AYVZo1*)B(?L?*s<^v4u z44`G|pwb1@gTWZ32WtXPM1vAEB&Wa{SfI27@eV9(5avO`2Gm~$^-IC-1h?KuHjkS@ z7TjBcjYo=Nnh8w>h%t7MQz4E7wJ(sIiR4ax21S^;V7G!}5SQ5%pcXbXHo&8XFw@b^ zho&{~xHl|h!M#IFlfljc4c5;9ITvTh!sCj?f&uJi^!^hTlR>!)6fs!i4J7f`0Bk#m z3GR1-+6GJ!ppXWQ{ejXEsI?AD&!E;Vq-6(Ml?K)XCm>-D<$}u~P&<q%0+gyCJrDF5 z7*Lr8P6eRw1T~I9MG?5a0TzXHbU|%GXgPvNQ=qmFxE%&wj|WaypmqmjEgq<nMG8$w z1c9c_!7c=ijA57uj(1R-j8gM3(<sI)5ZD#qW-EpxL1_pS29WHEzHShbJ0WQZ!&GoA zg4)y=hNAc!l!hSlBB1;(2r9c^VF~KFgT~z%b-?3@pspS~=)i`8>I5{suy7+uFE^-V z4{76o>;|=AVfrESIiRT)$TSitHT^Y!WVs4ZctGrjtQm#49vU7n6Bw6(T>k)@>%nOf zl)m9(k%FLl7E%L%(jq8jBb85}dH^&A3W*JHW(T<h<R)+@6~q9AC#bUuDnI!_DIMZ3 zaJYcW5qR$k-eLo#ZP-d2kP)C92%5A2O%{QS0w;Koc_g*f5K#qgrGg6*q%sa_7T8?` z+iC>NBBQMaF%g`+!QO`ybV%+ayR8N@8N+PU@)xPU3$E)yW6wyVzu=Ayq-Oj#17aj7 z*&zibxZeb6tAW<=a)WaYc*KeoGU^O!H8Fyg$$~R5WV{MmuQNq}dTrqKJf`q=7%1IB z$}I5eG*GDk!eEzxlNV@F09ty0q<C<9kP$i}2wi^+F5h8!1~k0^N>QL`Fr+YM2hE^^ z>kQCZJks@J=3BTKV3&h32Ph07;RlKk&<Yt)nFMMJqQ(crC!jC@)#4~EFHq%;)hFP* z1{xOy*8|`fMM}?5GeC6#D2c(^rJ%|H;vn$kGN`5jxe;8~fz1NXw}Z!6K`YoG<tk)u z6{Z$6e*B^0!ygAw8i48nr2()DAf*R5O(DAgRCa)z0kR9H6JT)z?u&z4ql#EYV?fRT zRgT~+4QfB4j~ao)1zN5#gUVLW+D9yHfd}AqgCOIet^%iYQ1JsQhCmox^neM_xEna1 zL(>a5&0&m{JpiY5aFT@@3vwUGB;0O1zyPizk<G>CR<Oz7R1Nkwxb%g@BPd~kYderV zka&cQ_lSe$NR^@eM(COgP@ITDXKkTQ1UnbHOaWpRXdDUD7ej8ZAejT2$p*JrLA`Kr z!yRD~r~~x@+$IFO21Fq8EO=}Lxqkp2Ifl(Ig4*ZM+zak^!IBFk2>&>M#|c0Nf<`G2 zaSW=rNj4J_a-fy~*!Q611j>`pb`Z-325!W7Bdksa<t<dVLUTE^R0JD>JfZ>_#sv?b zA;N$e6yMN28IaZ_sJ<u8Y>2BtaRjQ<!A)6E>kS?j;Cutkh0rl(=-e$lY%xL>XSjme z6eO4havP!WL{8&4+y{zZ3^#%Vak>*4p5&Mfax=(myzT~v0VsYz>A)D$RsgNLG*yI- zwL?l)P@x7%sgPcF1ZX`ZVyp=?7sU*zZ<Ixu!Sf`b*;Y^w73>Poyuk-hAL8!{W)INX z4sb397d>Di0vxyC8A0$`Zp3&ixD-Pk;Y1pigr;Y3p9^$bswr46dYc|<0=P{Jwidhq z1{5gZ1P)1J@Uj_{H_*ZaeWVmr0D!jrfEOYo1qvufgMtKR7C0}+f?5uU@MVP5IN<UH z)Z2%wuYj6}=0sTB!JP^9FCwf!c?)S27qp!KM^M4t1WNbdumbBv4=acXXzoA>D$qCt zr2GZ1VF$IS5iS6=c0eU2%n^`TA4nPWX9swY9jYJJPXy~na|Nv21+{4^U}Z13p9roc zAO#V6d4?~}z(onDN>M-_wFf6;GUE(kB3fACj5AQWLLbin)m<p7(7`bc3NCOKc>t=Y zkkc2asRRmMPz?c{cY~!dNIwLWhe7cQ+AoB>G7xSq$V5;c0A*)z#sn`*1`Vh}hK&$q zE!4ee<qmjN9cYy@w8Vw92taWIYHWZ^C(^y><|6uG;1(UsT#$*xxfe8^4^7wLv1ycW z1*b#QFa;GO*uoPje}K$Ea~Eiv47!`Z4Nd3*9dMr$)UIIm0QC;V!Q;B1QV_iI1kwuu z&-#L51mPe^x&|jDX#9fn3L=i7BTC?M1YAaAxC>+iy30U|-f_jPIBX0Il4hX&R`4zo zklR3`Qs9h+h)+<<9=gc^QQw2x65t(<h_z3WjG$3T&?vMrcy%enJWxII0eMOW)Y?NV zHU-ZQf#(<b5%a5H|APC~jG(>~s5d2u*!>5}yP&2m%!%L(4Gll|+SLOLSo`T9^FZs0 zjYT125TG_4Vh{nEi@_060m>7Qxi3%}gV#~Wvqhjn3LIMC_7Q0KI0DfwLX2U6*U*CM zD8%RmDBHm71$99|NfK1FLFU`Q;Q<~8N6jzDc7q}w6t>7Af#d=v=(<`^I|7_PU||Xx zPeZr^Yzk;O7_2J>ZiYbv030`r50L8}w0S#ln+6iOD0YJq3TWL9GiVJJc+D87%mdBw ziW-Z8!W<H6pcO&?6hJ!~;rm@!K<f&?YeztRFK+03EVu^=G6%e-3$iN`l)NBG0aBuY z7UP5VC7{m_fx{8KoK%Lo1!M?3&4XhRlm<Y4fw~Bh7fCP&;vi@?1g}m4)x*&8K^)Wu z2aUji*6)BuT;b~_OhJ32!SN&tidm3LK=A`|BREDtz6A+>__G5f22L-G3^xA-!0XB7 zLH#1IS>Tl(5OYAgFhJv7pm8r{(AsT~egp;^1LlGjQ-gVswOXLHp^)(mh;DG39$cz{ z#)cuY^I&~o0<00j0?l*4+AE;BLvY%MxCPXng0AEM)kDzG28T6ljsl!#!2K!k$N@|r zJiQ{uEFqa6tQow-8`{2L_5iI|hm1pm*3g2=OHi==Q-D;jpkxkiks!hivgQ`lX9L%A zppXKMje>F~I2OQb$YE<<K>crU*@ti+xX+B_H&Al=rvUXGq-=t0vx1dPVEwrBB*>2- zGe8c2_!4Re%%31P!1hUiR$78XNe~=Hpq(k86~B<U0C%VUDO5oAq=3T~vfctR<`2~e z-lYa^dqGxWLn0GIf=X(TY2c<hm;j9zu!G8JXt^ZH3|==2PRXDdN6@Sitp5OZLj|O8 z0Qmq^LZfW|0_6#?UqF3bM0kqA#~+|3LE;aRr$ECP;PxRjok8=IFvv~dJSB?i7EnzL zO0h7<fbtWh1B>JokY7QW36$3b!0V7XL46uf-3_YE6b0d?K%4?n52_WxEB`?pa9sf| z^T2T{kJ|PpB8*_6L@1oVV{_232d6vqumU9<&^~WSXn_iIxI;np8N`jC`V2Y_1s>6Y zv`;|2Kk!Z>uqS7LOoGgjgEASoUW1gZaC5-@FCxtWxd&9wK?fBeoi9W=fiVUJYJ*{{ z-33P;sJ;U=4Uw}3lIx&mg4@T4@e^=Z5jGR#N>EBcb18I86I?EVN3fwW06B*NG|CF9 z-B3aiJhY2k(LsU|WH=~}L9Me2P*)n%qz8>R!t(+7=EEEhigZw62kSzC+ooXiJ;1pH zwE6(tssi=FAmf^_K09a#6gm|GaVaP%fLL&+g2vB4W<ll-!F2<;wgI&!!K-3Htu{e$ z9ux(c2F@KI6CfDM1+|+XNdQ&`fWsC%^93%I;AH@a2c98EDhohu2T%n9Ndb@{Na#o* ztR4ZUbM*0JX3)GnY*rb*rVv!dBM%cox_IDO8faPq=V`S5JS^X#yAPCWKwbs=PyymX zP=rHsAxH|{jTmVkhdaTkAMR36EF)qEo+rWKh$w%+eFo%J_@F)<Xr>pe72J9QxeVlL zP`-k=7t}?9h5|?sG#`ivPeh&qnGM?a1{&D_jh%{udvG9)sOG|Vqk}vT!64({^$9m( zEfgpfLHe=S+zd%PAeVz$&#+Dpa?uG+_8=?J-Hm<R6XbGGt`!BX?^lGL27qQh)b*g? z1{n;&kTw#u?vaJIyFe=`Kqf-M0@}U=w<bVgg6d>Y&l$AX9c&!fv7nA0v<(9rBZ0K# zz^NZ%COCwl>+O)t105XzG7xMSn7|BQXo-bf4q~_!<a0>5g=F{);=>os4(w?IoQjdm z#}&TFc@JF2fN~lreHe=h3xZa?L)W{59Q=312S~~V<up(+_}2i|)?z-uzzpj{K>98q zGax-cCK<3}Kq1C-;ll?=q5lEYJ4dO{ar8^k*Cc`R5U6BAgcry)NIR|Jd6XGf-xO`0 z4P1SI5(mgjAXkDCA@W=sEQ~<)IlO<0a2IG-FepwzMu5TxRFA`#H$nA+>u_)zT@hu5 z4irP+g&82bktZ6V`oLu(+SnVoeg)0MfYy7#MsmQ0fNTeO0L2B!;epYvL7Ml3m;`N$ zf}8^~3E4?VbqF}F!08ZF4}sRfi7JE2DR{_&!ULoqRO*An1$>eLNCY&T0}maz+rVpZ zVD%D`nMm#f<!+DxXf8yHEYvmxQYi|pg)!Hrfr>j&wFY)3c(pso7PKHlYdgSP3ffTs z>d}DOCJ4WSW-CFaf;KVC0QH1G27)k3Xd?U$8Vf|5(*d3F0_rP(QW-cW2`a-^Jb+As zxA(z`AH+l2^bbut;I^40>NpfAJYnV;!%AY1dqLA<7a%4>TnQS=1<!cnbtkBd0GAk` zkppn4XAE^GC;%YlAyOr%YXT7ibt^#W2|WJ`8aqK7;{vyrp=lgc-$6_Rr7BP~fm$W7 z6bedDNSifb@ej(Y&>j?|?S;*yplAoBP>7qLUCBQVXwC$=6Vw(%uk%534WPOMgh6fu z^?yJZ<Vx^pILKJgXbFgh1Oj*(3RW6|x{ENg!EGp{)QT`0VKU5IP*)MU;29DKpa}$! z9Uu&@?!g3P&IfEJsIG_fV6nIr6qq2L$S%e0PSE%*xI98O6UB|7P6KHB0c0~Q$c4Dv z2TJ$KsC_tuzd>~mXjB0dqR_e+RP=+IBcQQAaMVF#43-C=QHd6=;5G@ktOBJ`&{|CJ zicr*$0EaEue2mZq6)>RifnZS3qMSPc+S3ghhXoDrLp%#<yMy-%NrLwWf=dQa_=9%s zK-aLF8ViC{gW9j4+6=VZ1!Msz@Stu1g&}zV1#~SuXfGPLtO2)Fz;l4GmGB^4Al)E0 zfONz6k%Q(9MWJp0<xWAcE0FYpH(7$Tf}3=p>30<Ups_{po@a3X9Mn1jovH*f3H96< zNLL>eFQ8*AAnSBMcEj|7b{Rq1DIhZlt>1^}2iXleR|T~H5;S52J}Cl}NI?e&FnfS2 zJn(u2P~L=%w;;Jw6f|!JN|~Uf0xLB@`4V=p+Xv7gg`n{Wgni(1vq0q;IGjM^;UHIo z+ziGLlRki3lpqtq0S9dof+%QvwFA6&kQcnq4?fchT5S$0Q$c65fR^@vM=e2pM)24- z<lG3zcoAqU5!82p%w2-*0G&4kIR_1r{y+^+Q22oM3V}uoLA&NaV?v<x0iwZkAfPre z$X196u>K}^su(6z0UfgfpD6)3dw~_yz6P)50##q&;XI~@3Q)L%%WOng!QvJ%*9vAq z!U&Qg!6c|O{Qx>Q2Ryci&<|Nl4_YMzNtIyTh<Pt)&Hx?#0Lqe}ya{nNq(cie2X-C_ zC{KXKPC@YvDm6fBR6v`iL1Q$a_8CMggoNZz@SY~H8$fXl(hKejfkF~gtAj@Pz#9-5 zL8oCsG=fM_MFc8fKz)b~uo;kfTF|H*D2;&k`+-KtAm;&sv>;WjkO~#*cG%b=Xf_8_ zCxhm(KyeSsfgpV#tH7bD06jnoVW%j#F9cq13Gy+hosBqs4;)#rj1AgI4O(#t@(VQW zfa_fFelXDZEoc=n$oHUf$r!X(8Je@<X%*xYkTXCBw7}0b1ew7U0a_geH3OXTpk{!| zSjZ|o@Dx7C08sY<j6sP2;eUBh*#s&Tjlpx&V0VB+5fq1@*>1?r$r<3%37q4htv^uM zK+OeFACTe{QQm=jUdEtvYTzXnWH$ylUBXfnXkj3zR|v|B;Cux+y9AUfK(huAKY>CS z6bNwrpzs8H2$X$60SitG;PeFY1-P{dX~%+76m(ZS$gQxQcCZWyF2kVVDGn|(Ksg$o zi=ie7f-5)B34{<cKwMCf13G<<5ptFwxR1dA8jVLfD*`&V1eODzWCTiKkaK>(=Sd*W zlmPo3zUK-)+5{?zKo~T61+pG`q5){s98`Ef&oP9VkMrDFX3%^SxK0F}V+e0SfLsIK z5eynv2geeqWCsN<xY&R+p8pzvyLX^`1UkqTl!RdICUE}<+{OWw+TdISAJYQG8E6d% zEI)y0P^t2722#5LG%N$Eh(WbHI2yqOXuU8o>*^qV5^$P?q$v;yF%D!PD8)dc3o_rx z2-@EVp5H=lk3jm%ko|QaH$svXsD6Po8o|vQP;h_-F^QXRM4sC~I0sbifJ#qj{{UOq zf%}%Au^Mm<pa|Ik0B*2?+yn9*hMORx)lf6ReGatvAZ#YG6Ol%)p=N^J2~IJHI0l;u z?H}L{Gt7P_*nQ}8Lg4lpd<Pb|TmbnN;VPuT0BG3-FC##;C3w6D(q09{IB4DkJP!ss zB@&cEK!p`JS%C>iyByqu1g%fSwj&o@V?oY=1-ExWVGbF8g%pI4rXeg3fb*Urs2vTS z`v#Z9pd1S-y}&fML<O}5K;}Yr13*$Ghy?i()IbM062u2%)IJ~Dm@GK#(bs=~w1LVa z(0~TW%^)X(#6W|bph<T``UST&!0~{^Tu`|W2}w}yg~u$&L{Q=b^;JL)2Ad2z-3q=g z1Uaps^(nyfLZIEA;4%%IhCn?5=tws>af8eQF%Ygsp9ls=9b~Q_oF38b0FCxT#=Ie= zH>eE(IwNNZ#AqZEVFx0}L9@c(FbCBGVDrK833e;ER0M~)DI{c&YI{)X0=XO1@&-jL zDA~fy|9t|K-$8bOLJ!o=1<kvG+AN^{Hm3RD&;f-yD9u1y6WGj03V%?9L#zj-MUdOU z@rpgKg8c!HQE+9BWE7|r0UcC^h)0YyIbeSag6d;<UIjS-HO1jhZy4rbNo$}D#Gw2S zt|p*Err-evcsfJ0!K4v&HMqtHx4A(*K`;+`jv~041Vuh59zacRkm;ZT9g?2FbuM^Z z0bFLn>MzL14|MDY)DnQFRgh7j(H`(P6=b9WX@V7G9N1t`{RQ2h05cPEq5y2wDJULb zyJpbmdO`guu$vJ16Eyz}8fgdjW<aSBJO>4H6<SFJ@*b#K#adQ@=AczUWfeGWgU-9d zS6+eAAE@C0^){G-BpNJ57N`vfohy)s#|@}_2DbyjsT$-5aC;28$_bWsKxGTaa8N9P zf(FC}<t0#W7ThibnadObn%4u(QG><~z`X@fO$nXV0F|#G?V#yE@XA6^Sp`a;AhX~Y z$&HY6V4!2{Aoqa!NEIKzyGsA;0OeQ2+6j2O5VSH06r-TL0J2e8bPMQw5~%qg`$22* zz+>z1HZ3?`dVuyIg4*h!)Ct0{)DIe80ht7^>p}hog#pwMcnSu!I3ZyHI%63e7TC?h zVj5($AL>dd1upNPX$_-I1fBN-ua^Tk2BZf>W3=61E9Ma82KISANcj(5F9$LQWFE*v zcvj58{mSeCI+GAfznIyh;?EAm*}nff!0lV;JQZl|4(y~mP=63S_XX}9LJ}~<c2EKY zy9IpW9AqR2Bm<5-L|Fqqdjr%X0i`@p{sYAxDCR&Xf`D2lATvOHbPx^g@<EIN9TfyM z2i9MMnFA^7L8gFCkOD<JsOJdIau1-ILB_%7CBf^{z;i^PHR#at1l0C{&hdi66<lya z+SiZ<3&gW1XU2frE8sSmGH5OY*6#<O;0{iOSlZK|G79V%P>zJfHE4_%>K;h_2p&Cv ztgisABn8(opsWq55<vs{Sk^Cq#xsdB1LP6N)D<X)g9c+jbsjkVg4_YF^Ay2zW{{E% z*7`CQ1hu+AITPZ3h+9C-AqfBP3XnO_JPMsd1GVEor9Y@I2TnKW>qWp-6S!i61~@dm zRQ&G%ujzxXwSuHU(CPvB2r9%<(BZ(Kkc6gjW)E1}0F?|NmxE##G=2uk%OIbF#!=wq zdBq1%LID?YpkfMCrh(S6LH5prQWwYsut}hnCwMggn*Cr`zzPM3epvq*l){xkttsfa zq2N&fq?1FzgLdHLiKxFI<8Gk1fbT^GjVpm$Vi5D-X&vdT2CySQ;Rj}*5a8ihn7bhJ z#9)7cSE7J?26h#=6$u%o0~Pe3(Nh#tKqCvF>KM{z0F8%&&c6hYK7;zbpfa540=RJo z?(%_BD(I>Ln7z<3O-P*!&K=+pBJgY*D6fGUec*Hj>U4lcXF%g*(6K3KSU|^&kw!&9 zZBkGc2W59~%?dFIbUy>kUU=UITr-188c>M?jX|hBNUINgBLp}NLC2^e<ENnh6htqG zgq*wp9>E2rdQkj<>;wfo*zaI(L&FWShz=ZH;Ib4lo&pX5&?ph8tOBih0qvs#nFT5@ zK{~-kfGa+5ngVlC(gf(7OmI2`=?0}vkV(jAU4t9X3XoI9z-P#S-2hIL;PE7I>_bu| zxHVx6JuM$(JGeXmEgA%KKvDSzcAh`z{7KNcOQxXPIY48SptV+zwi9S%7F05T3p-dP z3yw}u7abZGpfm#=X9cA?kgLJ{Md%0{$U;zrfO00-=a4)NY3GCV!p{r?oe_*~0we@M zgM-jX%0D|m27v`YO>vML{zJyH!Q+j}pi?ox;{srJfI>r*=>qs%GjQ00TmwEE8&)BK z3I|Bt0}2PoenQaP17utbtRIvwjX|b>6BMY)0ZJR-Wm~Xz4RZPdg(YY%0X*^vN)h1R zfT*z`ct{?U96+ru(1bpy6Ap3^C|`gMcZS3#)E$sA0aPwR!vuWJ9%Mcg(ntqug%F?s zhPnZsCP8Tl)Gi0LPe5fHI8TB{)xc|Vz@7p1z91%mLKNx-P#Xc#js&f+hS(13Yk^v) zpj-wD4^V9k(g?B`)Lnq(6mZCZB)}MvzG3+ll)gZ94~SL-uMGg{L<9<08z{OEWfJII zVo(_Yixtp{GH`nqls3R20lB9ElEgs+Z;)_=>Vt%%A}DV|R_1|vJ>XIWWK9LA`~#&Z z(8K{$AGAyZs|J;SkbDJ>MWnOG!5J8&vjSA6egF-np}HBGCqTIgyblN3t_Kx_piqP8 z2O9wLJ}6f}(jmy*(%`XkP{{=Dk%C*(@LnZ!2PrtHpr(M?AOaNrAk#7P1x7m$HAO!F z9Tfx8362lsz3iYo3MyYfB^+qP0F*OO;sBhIK-mIR34_xXD61jHoMCYfDdEApbU`gL z=omiO2S{Bph}9tXgX#wiz2G_qGExo7K3K=F!0`xfFF?v>P%Z}L1ZXP`l7>O?03POs z+6_Ny2V8F>*$<9Kq%;8TLqq0nK=Tja`T-R5P>ho1!FoYC2!uiT29$>&t_QVNASF6f zBPa#H^Dtz+J;YY%t{SlG5&A(X9~1(hnMQ;O&^8vRlMPBoQ2#^5=b<f6a9IF%19)vO zY$67f5J4#jb{;9?1Eve0T^o@8B(yys3hD=fY7j_;01iH|wV*JAmc`(56gulH3agz# z{ztVJl-5Au2TC}gsRmHh0tr7*TN4uZpfU)<1dt|B!hw{eSkAbI=mm!#sH}kJ9dN$` z)S&^H0E%glcR`gIIL(09dn1P#sPzPiZ*Z>&q!>KE01j}FYoXx)jyJHI!QsUUnkfMH z<3Mo-nE?mI7c`GSf(-qvWLW(V>ji@Aa8UgZ)(O@Fs)xbbr69!(w7h_{X+hxxE+?S+ zK%oz6i-FQP=nztfhe5kcA&aQ~8h}j$)qlwIFW|Lf;B``<90N`(AYX$$42q_|2B4+9 zpjj1=pFx@Y0TcMlTF@*8C}+X!1eGP=(hU^4AhqB$32`fA4jEJrfOaZCYie+90JaB8 zfWj9%Yy;{e!OK=~-vJy);8YE&6+o^8#}8;s3glm?0bmN;UIMc~XYhi~2nU}H&A<w( zPeFEqTAHAUfsJQC#(oiVkDw7v&>Cq_%L1Ghz&3z_6I6?UBL{Tr4@eY#rZ*_>34+gf z1?{MS%)5eH^`JI5*fF5h2#_tZ@cCA7`T^fv0Zu>Qauzg-2yO$2f@(Xc&I(YA98vZ_ z^Bu@ea2p6z&VttyK}u;*Jq9jo!R0jA2#{OB-6L?}0o4y`cR<$zfO=NSrl2|#RJVgl zD$w?k2cY5x)P{t{1t_mGML_o0fNB?zE>N8gN+#fP8LSCx58RK?G98lE!J}NDJ|wuc zi`0LD*a{tP0587=xe=ikcCHGzE&-2DLCO_yc>*rcVAC3)qysLT!1)`gP5`xrK;v$p z*<{ch4JfohGfAMFwE`45keC9ceTb>x)+RU|gX0Ntemp3zgX%`G39!}k$aOS0$U$L| z0Wt~11JR)T0V(UC{sP~J06ISooF~BbKFD@xtT9D^G=RMV3k%qK44ir(m+ZjxK;sLx z766oUz_vis7ieW2I5mUkFd??V>m;zB!S_RmgW8plSp-n&C<t~RIIBXJ=t0I&z~K!p zPa*eZfpvgtAXu3IPJ@uMFrnobq#OZ{VS#fr=&mnt{4qk#*a7t=VSa~{@8I$VJSPBc zXG2bLfmCCl+y!zMSR1N7NWB1RgM!K+P{{>y4JcMXT0t=cu8sb#fW<ec4FsvvKy5Nm zY=cU7P|X4kL6B~UE?BUEL_kFZIMtx~4^-}ebb;@B0~e;Cz5qCrLDB;#o*?BUbnFst zAE+G(8tnk53s6M_awf=Pn02uD0*|pk>TZx3pxg;+$%0xBV7(wc;PpCS|3doXU_FpD z1u7dsEf#Re3@Rg`Q431MphNFLEoX>Z85qEM3e-LXg$#H^1FQ?$P6L$%;5Y<jX>das zwEhcZJxo71jeyH@kd2`D0QEy5G}yf$yFsl>P;CuKY+xf$%34U?0hhC&om!w$6BHz1 z-+^ofF~Bt_QaXT?L7=uFq{fBjUy$1%7!*>FGy&3%;$HAwW01NXRN5+n`V`<E6r@E5 z-V6p#JK($xZWDmq1y&2KpP~5x>?%l824pKJ$)UOtJi-NW8@NUW<#v$EK&nCU0ja(~ zmV>Ul0_lb3RYjye1gH*!l(wKe3rc+;8q`CFXb0_;g&GLSGEfeP0`;iCeu0_`sbj#o z4%DIp#Sy4?2pMAnm-evcB%}xh8HlVOKK2aCz2KG|$Sq(Wf=VLj+3lc#Vn_oM<Oax5 z&5#rTOXINi1gLLl3R#~7HVss7L1ukGnGsY+gM%6rhbVV!g7kq#f#4+*xb=_$?xllt zR)EgQ2U!m48GynS6qoSzP@uF1X%&D&6O!7%ok@^wA3$SOV22{|KDgWkrEAd05GbvK zN<&DfK~fpmQc#qFQam(^fyP~-_Cm*9!EH07nhQJ{4eoV;5<1)@P;&vcQwvcR!}=ql zh_VlSqBVFW6ev}J^n=PRkiS7Q_{jI5!TTf-+re!iSnnEE|AO>^)*iy^UyuN(1qg8i zv>b($zmQc=pb!Dg5J2-RD5rx16C4_#<|^o_Sy1GG*C2ty0#Z+aQV*!D2`aroK@KWq zK0wcx0VNI4S|0G&81ncMsEh*D*WmgET#|yr8kDd;fbYx$?FWXezXUlPlIKC=)l3&a z=ea@eRRYI2NH@4VHU*8IgH*#X=yV$x8+n|LDFSp?2PnK@cP=tMfaQ0jG9OafgYpE_ zm5|YOP=rE?Kgd7_=wMe+bq&g1u=_s1{)MdP1?Nv_Dg&3rkWv|(9l)UpIVTq6PLK)U zfh=gd4iv_avn#;y1YTVVHwhB!q9Ah+IR%taK^W{lNPB|`WEj{zyr3CL#9AWIct08s z5(n_HC{P~_<g<S>Ktrt%7U<pz==~Ys`$WJay`aN{K-Mrafbaf++{X+(n-4VX%g6w} z(;9q-Irv5(Mo2>fq=yNj2Ye3(^e!31-L|0hJqn<kghA!j2hjC4;Cp6aW`NQs$P7rD z2CZ=go#6`|^8=NMNNEyOw1ZFn1lNS1m2e<4K?xM350W22r4VF&DL7w(?gs=#5mJ5x znF8X1k7_|Gi&#PD<%3dG1>*zo^(x>Eg$Q?n&4<+fkd`T^ZUwJb1Vuc^l8O(Ys03&G z8K9N62)&?n%}D3Ng9c1NeGaVmu7c}tP-+2{2cVn@Dv3cU4rCXkJOLHx5KBRQW-trV z?tp~_q@4(=i$Nonkd_>%7<uqd0Xl(-NK=%Qh2TCb<n9tsJb_#bDn~$(3NCX%84a|G z4LP1b_tAlNw}V^<%UO`IFvyxmh<89K7!;CVUIqBbW~8_RwKu@?MWA*AEKWcp>=5M@ zpqPM6Jb>y?)UW~R1=$bQ4-QvQTL9YX0O^M~8dN5L)@(z{EoeT5=@kXfD?sWkl)e^7 zFUkT9=>8P&94I^JJ{s`pf{>H7Aorky&(i`YI8d<*#wd2e+hgE5P7qY%!NM1ml)+=? zu-XYZoI!W7gYyyORy~jne+|IPKN0B?-1Y*cHIz0#DBQvQQ&4EY=Qcoj3@L4b`kA0{ zTu@C93Pn(w2B`;S9uN)1paKy!{K2bIAt?pt{i>k62I?DuTQVS<KrJK0&O~sp3TgqQ zON*2?Aahcno;qlh02H^N)CKClgT}2v{Zg1t2n`BENO=JEH~0oS<ZuMtNe6NZB+gM& zETZ;8N<R=|K`jVSp#U)&CI%j;LWDoEKS6$lm<MTbL9~DiaPS&jaP^1ePf$KG1>O7% zsySijErM!((3m24)EHzvsDJ>qi$S$NsAU4WW*lliybS_swLxl1kQ<;O1#>s3&HzOs zgbxiOaQJ}Qu*~4S@6hu<!C?a$Hv`q@pmYJ6&jz<AK&}880xlFlEd+??K7i(>;buYZ zZUgtRKy6TvTR=58But?7H@L2XXhx7Alc79NcLphp!0XLH^(`n3L0U&3w}C<o)IJ8a z20(cU*7XA!0&1axXb=X~!zg_tP<%n=b0IwsXblcZ`=Ih1QaXclLNFvBL&FJrjts;l zpt2n_n*l4^L7@d{t%E%S%Y9%D#4H$zFq2OEH$Y{422%tBDBptm+n_!yxTgb3R-hqI zNO&`X#xB8W666<1n1g)@%6%whB(!A%_Rt4VqYauKA^mia9)t<7)PyM8!Epl05Ksn6 zc!1Yffk(7J<52K=58M#|g(>=Y3OGJNHiAkpP|SeK8I&>tVioe(17ytsB%OlV{tyh( z3B#aR1*I!UZUGfAV9&y`0)zu4A?^p&FOWM!!LA3bGXu}OBKiVgQ$U#zVkju!q2UH? z!-MlJq+A6h8&KN<GRg=Z7((=&_(5ysz-2yo76eppgB=Dn7t%chZQudLD=6(k$_coC zL8S%AeV`E=&^}mDsRF*(9+bI34g_U(kmo?I0GR<=D}eAD$c3Qx6RaKs?T;elH;@}a z`atWdKn3F86`<k_)Uup`8V>Nf5;Q^sDt#b*LTEt<avXHN0^}}Kzk$XRK)S#)GoYFS z(W3`>28^KwWWa(75_eE@ltJMNDOE61KfDY>q+_sw5CT@jLU^FyLoO4ceO>U_E~vkS z#ciNFn;~ujha|kd1&=2|>O<%lE!c;kk`+?kL-H~xq9D-@b^*kfpq?i<+`w)DrBCQy z5pW9x<U??K1U&l)D*qt5K(!ud9~OuQ)(z^xK--$&HKvfYSK#mfo$UlR2X;0pXa)*Y zjAFY73fhhWuStX5CIzY;K(`Kn`~oVE!86L>4gxMyko_VEYVU(;1JHN}C_jL9WPl14 z&?Gc?%pIJ_K!ex@$ZHqbL8J80UKeQZ3C#82ZUbnw7ic{!(*^L!rO5Vy+fJZ52xJ$i z><9ZDG-eK-QGhg8p<xCpBEhi&ZahQtIi!4qmJcBRg6c$+-A>TN4eNA6A^~b7IIV)p za?t(h;Qk0`Z7Imlka`D{d!cPfP@baRy-uKZBiKGr3Py}>LF|K`1_ui#(3l2j%?G$` z4vH60ZUl#uAUNlM!vx$!W{LnW&I6_T3eXV~sC`I~8KCkIwG{}ig&;;iYXopef!a!- zStn4L08QtRdJOCePz?lG`wOZgV7uMH8bLV~GJpVS()?Y4nof|;i^0Dq0q&*`(49)4 zwUkhkL0J;g{eg{Nf%6gS`f*cGSb=(8AUA@-3>Nhu-AL=lLBgOTgF)U0-SUp?UW|3L z;5C-udKA=7g49Hyq6(6rK$#Vi+Ck|ZG>rzil>pLS0+or7ej#`+6>17-1`^V~V)g)C zqzRcOL<)Cu`~I+UA5=Dhat0_*LhB_^o&eQ_8Q`P>?$IIg6Qus9!I%Nm|AL@80hGtU zBhQf1TNG5=f>J*u)|n6doACj(z5m|~c)1N8>jCE(kUntg69kp9kYWv_AI%@q;Ia&q z;=#RYP$>gRx8N2DTHgfJZi8UZE(cJH`JVz(96;&|$cigSJr5y~*4)5S0H|{fPD;>Z z2F{uAu|-II0iHXD<Rnl_5H#0=<Q|L!iKr_u_VI(yZ$dK()XIW{Bh(3qB#B`(k{?0& z8#D$04lU5!H#o#V^$GD~5TG#@uxmiG5unluvY7-_Fo9AxsHg=MO5nJJjT?Z~gYzh; zUy2kCpm76e#)MQHh%^ea2i%Vb_0g5#ZCX$aLdS9tYGL^R6l2)hj}U7>dv8ExJVGBW z#tI;L3p9&`da67$UqaFlyeAK;=uq4PO8KCigL8}k=2vLh0vam>r3O&W0+mfDB@(!P zf#ylrdN6Qq1l29z_yFe}P;LPw8)#aBQlO9qnGBj%1hGL)8l<#DlkowlTe(5=PN4D} zgdyt$LF-Q{J}`l|I%1TcpfUqont{dvkmh_rcNv14hG^ptQ1u|wK^T-gK(z(9aE27n zpd<|GJAmqD@H%slN*GpztbBt+Bh*z8jVS3K5?7#hCuG(DbgMFG=?tjw0Tn`^A`Q|v zgXVwmco}q736wuUYcPz#y-&~rB}l}8#<HNA!9%r3aROd<4a(Etz8Po@G&I$LQU}OV zMo{gCNN<p~8Eh^FlzTwE8%Qe^tP|9(g_d@ZK!VK2fzuUIn*mm)z+2m({b8VWM-Uf- zNXCp0;QR+}Ykfd-hajjN2e17Awe7(DGf0jHjVyp85R?ERLzCcc9n8;=IebO14?sBq zG{OO*L1#KZ>Sb_?1(J+G&Va@%)a{VG3epX#Jwa_!P)!PLmx8PW`5!cZ4DR?tYAbj- z4?B|q7Tz!#%h)@}W)S`hoeKjU2nJef10Q>b+*|zsGN=bhcOZF0J&F{vphN?XPmqZf zOcy}YT^~R*4bXUnh6%_=;CUD53K#H6576zNAnl;GHh9VxR3svWC#X&Z&1i!$EDeIv zA*hr9mG@w4p#*r80F)R(i3_P7hphdDwD>_~4QONl)RP67foKau%0kHG0n|V^1#Y*4 z$MqrM3>vLKZ|%VqgBZ{iyr3-&AZ?(C2H#JJS)ZDM%>vbd@R}KvKv3#a$W#kxMJ_mu zz=<DfG*VcB>QhiSfyV|wVFgM9;IKlePZ1^~kNZH!FTiypYF!E{$3g8LL|Fn215iE# zs|T0eXmu&51cwF!JRO13Im{kVt%6#YBF%Lo(hj7|0_6#`{D71fKy6CUj4ZqyfQ*xY zd;!9s6bhQF`KJKN@}TenmFo~cz{gC%B@HNTKyrEow3vZ($Uz|nE*KH+g5*`g^(rVB zzzGXvFVz2_F+A`ZFVI*zX#XK7zQF^_h`a_a<H3D3@JIuw6alM(tOZj5t>=Pz8&nY@ z^ugBjK<icT=m0ov!Pjp=avLa(f{HSb`(Oqkhaadu1*J^T8VgX&g4m#%1JpVLm&l+# zJ9_>D8H$M^c?TNiIO|eS`39b~0A&?KI78}2(EJ%FhCpiuLGEYF0L_$s0594^R}1zz zsAdG`5^z9)j<Zn!84fiYG&c<y3j?hS0;z>y)Or-+BJhCa3Y4@DNt2+^0M(<Q&;XBl zfJz^T??G))SU(Xw&x%=xnu2D`Astqb6G7u|ppGp33@K1~i&}qz_WOZrK~S_o?E#hG z2>+8(e}dv2VhA+-K+`6y41uH>P|qFYPf)BQwUa@GHN+KQW5C4-Qu-DItrG?1Z&*1C zqCvS3UVnnJI@tCP@V+njEH?1@44^&}=p27gs{u4Z1FJE>c7X~bq-q0FFv7PbgGvGD z7!|nf0^NNME(1YhRN(V&KzRu~mI<y|!6Q}pO@!wQ<^!Oaf5_Mm$V_l~0cs<FW~M-4 z1u+r4^Z@KVkf$M$3>qv2xenxCaD5B*FZgUqNGUDJ2%7bV`w`|b$igf1I0ltF;IyX* zF6+U$9Ben*_!YzvpbjD250G*XQWt_k7!)^%kp)mc9U4oZ<6xlr;pdHl_HBaQ3_6Dn zw5k(47OVqac>zB)1{|0b49t*o8=&z3J^>vRW+*zBfcmXC?zx2Qrvi;zf$v#hG*uP_ z?Wcm>Z2->Qpt1lIQs7OQkgEuw=@7K`7c~9^uAe|PEXZz9d?})jVS!Q<*q<NJ*Yra4 zgW5WvJOB=FkSU;+B&bG!Xo9dlfQRa#c7xmu$wy$@LFpM(8-r=kt|_oaNFo8XmOyb1 zHsvq4J;nqoq`++jcF<i4@G(vtH9JT*C_h3Bt@r@G2MW|u02>Jwh2&3UbCJibz$H6) zCLPiK05>qfdO-vzgh3`^wmo2R1UlOSY$iA@gGxk{b4fut4pe)gj$1*D1&yJA*F{4L z6mWYMxvoIefrxP{P-_HKoFlarLH#1wnoY=>6Igt~Z?1=004ip|1I*CXV353Zf$0M1 zTrF_EAgCV{C}0e#v?2OIaSmw{fZHn2G7H>y0QnqN#e&@cO1hx*0-nx-r5Sj>B&;72 z<)E|=3IK@xApb+ke^8nOrB}#mXmINRUiX6?4PKW4YLkElvOw!3VPyj-&%n$8g&rh5 zfctx(xj=}uP$R%e4m>muatA2MBHRI9&j8MAkUkvfY*KJ^ftHhiG=hQ+$=@LLAp1al z1W;)TIw2L3D?w=(RLg_gH_Qi^Js9-CeR1>_38;Por#f(}1T=~O3I$O6RM1!yHW&qW zIh+AY1~3{FOBJ9BA5vn1!v)$_0M8qP<|bh&9F&_uwt?rGz<Cpvp5exWN`6qI0JN?d zM8ncHD6YWcA0YEUB?H(@kRL!U7X_86aI+v;22xmnQtqD}(Bc&oe$adZKBoX=7POp$ zm;`ncXjc~~5aDiuazL$4@M=!D9}(-MA+2&y%Nepq6coXrxc>k;M;c^5yqtuF4Y;ie zstv%kD(L)1@OT7VA7}|Nq;Q6$5m;UU*P8IY1E{5myygOwOCZjMl#Adr0A5=Snv27) z7gX<pA{D$n7t;O&wQnHnBtT<YD4`BdIiU79#7Za$@-~zSF8rYB92)N6I0U70q;N-= zg))B)GX&}=P|zd70x`A-YM-EtErRA*QP%!|$L66uPe?9@?^gitegYLX;Nc9=-XQ4t z0H8KBXk{-bW(2X$GePSH@EJ(z@N;6oeqjcsNiYV58Myufr7zH$3rMRM<~0}%%Wk0A z6Hs0PVOXCWl<}c<fzK>Lw+obJ!5G6XaO(z|cwsg{S{xwWUjtD70&P72(co?Yto;r4 z6I$H_J?8{mI)l<ID9}J=gQ6Q$24I|b0?CfxE+EWYu=^2b^?<{QqB~%r?N;dAD)?jz zNN7WEF+*`JD1n2grr=J61UHgHq2@u`UyznHIOeds5>z%r{SF?af|&#g8&D8~x(P79 zgToZ;LU73i@jKGWN{}8%-9WXw2|?qO;4VLCw;;@&5H~`aCZPBO7u$$@1!)g}>r?1R z9JtpFnL~q=PT(14&=p+~AU~p?O$!^l0<B5_wP8T5Z4eFeA1GPFbc50jsIUiB$FMWY zq45Y#A&__kpRNt55kYZ@<Q8abLi`5~eMlyPo}L2Q)H?&*Sil{ppxy__R8eF%Ld*sC ze!-?f!V5fQ3#v;%r4Z;ode8tB<a|7K&}|i<mNuw%lVk+73PBhnH-d9MD8vvL=3+#z z87b4Fx*L3o8zf8w!MPp0eiYOK0H;ro-JqHk6v_zmK`fa2L75ySvqQ~?hB=b?kT3_8 z(cpd#B=nKz(7;g#N;lv>3@A~+JOU0pkgcGm5+tZ#aSP2;sP;hD-67cn9kl@a1JfRu zXCPL<NKpR}5g*_@20pJ4)Jg~U$-(s{cq|>{Sg1CToBud~?0`;RL8<^)eg(T1Y8Lp6 zdvNOrY!Y}T5Og92)Feom3hGc-Ku7Oj<BX_b3@%Y2aR|N{5yM2dd7!Bb=)q|i4uqNs zb|1>Q@z`C7Y$j6hp*j?5CNwR8eGPFZBrSmZ%J6Y@a3q5Q64WpUg(74c9qGs-v^Xcl zJh&4<{)U!W;Pw`@Eiy3u1=R3Cibq)Zp!Z#%VFU^xa0xX7C7j?L8K}9KaY?kfDB%Uq zbx?Dm@d;kdffk?8-5`*i0MNB&kRS)S7c!EI;$~1E1XN$3#VxsJqq!TBN?~~q>~8RS zE5heXfgA}c^DjUX3wWa%td9*Edm+*skb}TOB2aU{bvJ4_qNiiD`CDk5gTn70^r9zp zhk?%)2G6U5?y@AsJdpD+y8W=Y0I#dTeNPy=J3-M1Dqx{`80uC~6yS0%=qyC?&4;)h zY(D5DRHOh#4PS6fLDMPHTrkL~kd_uGXhHD}DsWIHhN0#_^AV~!&>98Of<c%AaTMqV z5$MDh3#g;Q1gq1zLAUn8YIVq6B#?F+WG)xxCQwi!71rnzyHGQs?!sp#bfg;OKB$=p z2O<r0qx8!_W8I)|0`>pF?HKT!DJYP@8#y3@k)S>=O4$h>{RE8=L1uUn;~X%1BmS;{ zoMMe!?t=PIps@y|6%mk8V8~il&^k^~KkYB_JrIzx8Z;IHYC}L*bwJhvKwA%>qyW+i zD!9O9C43JXsJ{=JGk~;4!TP}+Tu8b_=!5hz5N%kPKJW@dP+tX7zQM+6LF1<xkfnDB zJ>YgPd@lm1bcBorfo4xYt^<WCxVZ|BdC<O0P>%_rpA&RGJm@YpkbRJ`HprMTcn1(d z9VpH~H&cLP0aUMo)j|RhJh2XHnM30Y6b7I%QSg})pw>93g$L@#f=2j3b8ZhnBORb% z{|7pFAKbbFO^kqzKr#ao58$<?&^?xjx*Q%6pwbK6^#{iTN;<>c*9NVg1}*Ue`wx63 z2P-5TKqpLrq6u;4Bxo%)WZx{Pbqs2~g3};qClY9u1nd(~iULj6fmeUS%>|d2vLJIo zeF{Xo8hi%;XiNii!ZWz93u--siW%^@1IR;Q&IeE`1IHmWOh98Pp#Hre=tcpw^(IUg zKoj{hz^B`xrGL;G1xTwH)Sm&bQGqS2VSE5d79c*T7y*X|*xlfL93VG?+zxH$LQ@tj zMj`hvfI<sY0fU_kNuuxxRd7ohVkRg}fYT6Y?-<NHP*DNZ56U2*o69iW4vKS74hH8% za7h7*X%GenJH&33{0p`Rv<eQqR|mA>8q}i%Sp-U{pv5wO4Z!1b(DDVc{tm584-P9x zZx_776Qmt9Pzh~6Lsp|eri_uzg4hiitpShjfdUwm)Ike&E+Cyh0<{}D1`CQ&(8v;K zr2;6ofMOS<6J#rN{0<tnpl}9HE<wT-nkK*_c+m0&oPa?6T=0q|aHc}21@Er~$18Y+ z1}H8;u>tBIfJ!(}Sqicf6sn*dvT$#LqY^0{g32n0eV{oL@R$)eZa~fhPfLKBVvHH^ zcmcT+W;aY9xGaI3)B>^_lKMd|0F7>e^Al*B5NLNeVh<H49f8Vp(E2=3FA`!FWE>5g zS3v8uAV*T5*bT}zpnfy7O#usAaD@TZg5)=lT2TE2j(xDpAVI?H0Xmffwfuyq9q`UP zSeSy==!11b>;Z))#0U@xO*Bvn)m~$idJ0m!f^rEs7LoG?++Ik|hQuQ%CP66(+GaqM zk>C*lh=rh51E@_5u@_wSLDnL|#v?(CjvjzZe=PPv%07^tpcDhzRRUTAji`&k(GMa( z`4i-AP@I6+;ASbrPH_1GTAvBY)u31ew*o*l5GYH7Zh?f2cY%xo7qQsuN@(nZQa{Ac zpzsA-2P#jn?a_pl$Dp|q(98n34Fbw>pmGkhMhFyR&;b*W<)Hc#Tn>ZMCCD@2jKIiH z0oqp$Ig5!AYz{OGK!dp8raWj&7NJHM<V)z;V^AfG3>DBl;q2fW<UnNxXf^~?Mu9AW z*a6x*fGq!^;sZ#31?WB&B>gCE0Qnsj-XM2^%-{yw0m*StcYtyU*jFI47(k=#%pRaU z{-7JepgW&ICZVpa5(KT6gVchM5CiRqhXfR8uIT~jOeSy;{sm2NLdzY<*cy2D1hirU z<Wo@igYMOZX$3VWAahipfi;xzf6%%e&|DqJR?v76*hbLM6R2GS@&E{f%>gG8h+gRY z7I+U8O1%Y{{|0#slnX$ISArV@;6f8J^#W<jLFYSoL32>xwliqVQxINzLew*6fR7A8 z_A6u!wjyY(3uG^7B@-xpfNCM|Oe-Y+fwhCSL4ax^a6W_D2R@%f8Ke^wN}#e8ycPz! zS_PC9z*z&*Ttam(I4^_O+`!s%pgaLeyr3+d0otJr%GRjiD+ux*XqE)jx`Bl*C^BGy z3vwyQ4A2a!0kn;Pm=l4VrvxesK(Pxdg^*JPJYql$aH;@D6S!P}#TBA`1#$(*1)$a? zBu9f|36`Zn$sRI=4zB({WeLa~khv_dJ3wP*pimQp&e}t51&!W<vhg1WP@V*xp$0k2 z0<s<m?3fDB8gfY65fl%QGc=)QLe4+~wfDf|XCNPd3<lAV={ZnnflOh{_~QUE16sF( z+fd-L5|aBNBzQIjH17vWiQqtiCJ9h_gzVJ-nGLQDK`8_&z94=DpRWdX3n)imoX-bZ z_y#Jdpm7Ct3%Je%wZWnBgA_)f+7>j@UI7_Mgyvah@Ok#obPPIy2V9?lT1B8(2GumM zoxza)0wkJ1sRrz5kQczs9%wv)@*_BHg4=(PKG6kGvlEoQK)pxMsy(!P1Zf+A!XHvo zfbtTwPXP*VP(}bBkqxmB9F(B!2s&~F9uJ`Q0=Pa0<zdMFM9_L>kZYMPRDcdW2hDIo z$_&stEU+6vwH#utC`c_Rzk$26;JgY=vtV<<ZA@@W4|G!Rj1M4{;B&K~>+3;j6n6GE zXblc1J%B<FQcpw5S&(l)wt#CcaL7RjP|*ttKTsS(*06zEwa7UYlxCn|4oT+l^_Nh4 zLG!2J&;#H91uaY9wj!bqUgg2;MADB^W`puMXr>wDLI}oxo*yZG24w`8{m6cXgcqpQ z3TiEaQVb{uf;<dLVxY6q;qeWMLr|X<)P4ikG0;{iIFo`>3n)CHc^q7}gH{7V(gmc9 zg~S8sNJVJkfaX8wSz+LIFC+#)x*+XzP!kmt^PoxzR3<=XVIXdTh9f5fgE*+o3Tm-H zTC1SGZv@B>kYiP#?gF_VTqc8Bf{>gB%5$KS9Nc*aB@s|J1eDC6-A0H#p!r`&xdvKW z2J6RymSRBULFXbv>LyljYaO(P0OWU&4?yD#;Hm{oK!OT1&;arexFG?_AD}!e3Ep1? zO;MoI8hq9^XskrkSo8x(11K?rA`+4~U?eD|!SW8skDzb_wa3A|I!I{`%D|A&htyY~ z{Ebo8!_EZ*rAg?>04S7@TX4{p7(7Kood5|rP-X!atsqfQm_zfjAZQ&UcvKlw_d-io z&`=F1rGeCf=8V9-1!#Hzr6I^V9#9(tl&itDAav9Y<QGuq1>_%49tAB60X6C%aRFM= z3R$-dX={P<6DWW{K?e(OQ2K|iVF1+|U<?XxxNku%SIFoA$O2GW0A&U+8%lt~8+1wl zcwH(3=o}PK<p6RUXxa&KryW=h;|w9t;!{wk3+!Idf>_X51E72bURwYffdeh{0MGk^ z3UQ>m2C{b@Qc8eA1v2^wayclDpurCgR1g74D4;C_(6|7l4N$oXN>QL*fgrg51xpH` z00Pzi;5rKAGtiCb;C?ftWecvOK=A;MF-Y?W6f)od0s95yagZJGb=lxO6QKPSpkP5- zvjEOZARmKoM+N0|NZ5fo))AnELmA-n*g%a%&{+-446u6vLCPTE0Sh;{UEnn*pu`Oh zUKICmg4)%feJHRJ4rB#*JPA~ygZ&F?p@YsdhOJ2j<r+}#1vwnl+lCGhK!*!KXHJ36 zfCI-b{OqR;a8QH78d@%~GBB`$eF$<k;{#CF9c5iII4(eK21U@QBsjf+$}I3~IH;8Y zANzou*9dN>gXdg9Wj3UR08$GcLIKs&kOQ(2{sD(Ds15~{THvx8RJwr%S-@>;lrRFV z(FBc~flifyw8tRv4PF%k9jO2{W@doe6QC3T-FpQ-Ukefrptchz5rMk=V6$Oy1aSw* zJjkk<51`Hn#DidUuyjLKxrJ0tfXXdU+6Jvx69u1s2XZK^L;{tckiI&&7(j|AP`d<N zcYyK~xEBIi&Bq8n5)4$x`~`KlK<Yu|2BfV3NhhGb04Pm?YY<SP0-X^EijoZQ@Bk<` zfy)VKdH}T-Kw%7OM}ubQK_LR#I|lB%K%5GRMo?7&4PRK;z{a9MdO>|2&?+x*iv!$_ z2W9t)4<J`V$|+EB2%YZ&pTi4UHxHWm2IYG2YD9L>%y$Op08~&42W4T95un|8plpid zS8)CUjV(jN1v07$QiMonAk#r@0<aC>xf<{Zrr<CDc?(qOfeLKM!eE3x(0WB^eF<9S zt}F_2Jh-feWKNI)pm}^)Is(m)flC5V-3oR$C}V*zs7!#KRSiyy;9foWejY(kJp-y= zK7eMoK{3h106M=BROW)sgU{!HvJq(05-1mg?#TWCs!2fS#F&HX2WY<@G@cG}4g&+j z2XGn5&%j^~>W@OyfMQ1!<Yf>BhbX8J2B!f~+JUqYz-1~}CFo8HaN7~IvJ+CofV>aV z3{D8(jeyYbg6IX60g&-b@R%5=)eb2)K$pyd8_^(RKwbg0Xdv+jzV`tXN8r2xF#$9h zqbLYEj}Vl=K|MI|4pUIV0}XS7?F8!s<z3LZOyJoMW{(fx&FA3lX`oIfSRHuG3DTbc zl^me{45%LlavNxT8SK6a=s+u|p#W-Qg1iW;co1a(WXuP2mI~yC60l_;N5bs_y9qQ7 z49er+5kZK`3Xlchcm-EUsOrIa2UO02>Q+!n1IGZU_PYQ|`JlsR!M8nt3NLWU2<i%h znj&c72e%V6HV1MgDDQz1HMm%T^r5khi-G1pkm>=@Eh7fVX#!O4fyy6H{SOW?aJ>wQ z7*KG5k|8*wg4%1)w8sDr2Sk{QLQ)dA2V)9q-Gat7!M*^s)Ihaj1}Kg}t$DC0D8E4B z4%CN(h7Y*(1C6et#vG{g2y+W4>OjdFG-v@T-5_Rw#-G7?8Cu7JTCmV|_zcDeVEy1e zFw$Odu=^q7te|liP;NkJv4Ywepez82A5bv>vlyDXL7@!FDR6&)%>$(ikSX9W1dRfK zLIHH%DyZWK8L$U+9O3B=<adxBP}v2l_dw+-=w5qpf?&*m%qD|Ju~6*+=OvK&pb&%Y zqX3sj;J^iibOmU>1-#S@l7_%}1XACF_MCuwPaqwjfUN)>FbW^5f|e7YGy$3u1eYtI zejcd&1)W6$sy9K^I4DFwxd>54fWrV1myi}4C`}>7B`D&cVF|VtT$6)B5)vqgxP+uD za7aQ<RRN`Ul(A@te(*WbprinG(+tq?J(7Pxet_l~aIFBX>p<=R543_B?x30kIWHj3 zD~f{VGhyTOps6MBNIk-xpzwsmognDMSa1sm6!?&c`v;w{L#T(&d4gI*ptc=&eGcec zBv6YHG$jJgVBm5Pl<&aJX?R)zrEz4pflglml^3AA1*xr|bCaOD9#U3=&V&V(5};H9 z9(NOk=4+@vPz*AH8yTSSzZIZX3D~XRcm%l>9(G{e;8YDRao~{%E^<I=4(whOw}R&Y zKx0^-^EN>J1V|bJ6$cROL1_rut^=(hL5>4R{DV>tC?|vaLg1DTJgmS?DR7|&%8$_I z3ph=nxB-;6Kqi1w5~P(6OTnOg4RSPOSPYbApy7t~+$qp~WzbLrw_cF;OM>e>kdHul z0hF@94GmC30^~W=d<#mCko*Lm2?FI{SP22v4O*BFnMDN011!&i%2TlIC~*!7NkrZQ ztA&;epb!Vu(I}%_pjJ01u)wpWpj8+kKO^OJP&x*?4N@~h(=seIqtwe_yFh*cwIxCN zz@-Ve{{za1AX_rPkpl`~P;Cy4TX4F9l)2#fSWv0}jr%Bqd*z^BC1_1MsKElBWCqy@ z3P(`TfEp7Z8XlftH$c(}xI6>5D!{Eva9Rb|`OuO9G++a|+YRIwkQrb%qNEeBIUp0j z^)lELQ27tSkftNJ`U5v=zy?608DR!w4g_QZc;p3Cj)U9Qpb{3m=ob`Opo9Tx7bD^p zQdWXm)1dSKPFawVL$E$@EdUNja5)E>;R6@wkntK&KNmco07@C)_A#b@&_*kW0Z6@N zP`rcEI#UE_jW8?7c2I19YC%v=1Em3QZ3yx`s8<i^TY&uyCm`t^5)5EL5EB|VP_sdO z4N$%VjRAq%ZYZe{>MGDI6-Ym*DuuOop!$*aWPp4J8W{ogI>Dnj&~gAAk<g|!$P|zx zKs2=AM1(Uu%|T)ZWERM0pwbCMgF_pv5ki16F1Qs3N{Z053+|tT*1dq&$3ok3pm2ip zAHZ{a5Z&P959&sPxS%A6)J}o)6``Zmpb!U@aiAJf6x>UI_Y}bu0Vt56dZA$g-4hPV zGq5oi)bM~<2_m6k0ixjX0zSV^8#E^b4hKlD0ptouZ4K%XLNK`X49bt-eM9g(2r?Ip zAtE5Nq3H@#nu26NX$xAWfb$e6oIoR-AlHKHa8S-b<V{cx2h}BzN(I~;2VJ;|$XAfL z8c1IkRD*-Y5x{v=5RxiE{Y6j#3_9H&6kH!FK$if40u5mX<je?An1kaR)XoB@OOSb> z_BiC;I*{w37}N&?)g>SU!AT5a7AOuNV|Ji1K}Z}x(lp_82?;7hx&)a88A}75=cNb^ zb+GF|ZD&}?0dfP#Ne~*cAO|!ahgyb!_xD3@{6x*akdswGcU%dg`Vr(Yu%Y1a2fGSn z52%cVrWI%$g35SkSRs!`fdd6nn*N&s8f*cN6M_8%yL$%Q4+EDVklT+y{sPw$$axLy z22lP5+m76f0Hq_ad9ZtuLFR!&36gg~b6t?I$6_A5oQ9Svi1Jb$l=ea8B?v>~ADsTd zrb1i_wgoh14t5k00ggjhLI;aOL||@(wz)vz1*^}%V`UJtKtT=hFQ{<{%jht@u(Ntm z^CdXffXWzfeuSiWu*FaU6pvsBA@U<M{-9w8D}$jYxPxnU(6|(|y$Om!P#7^qfU6pi zccA*A@ei5f#0-0AO@m%`g8cXay21hEM9^3T<or6QdEoLBw66u!LILGtkPpFg46xoB z*a(O|kO`o6DdxO1BL9JW1j69iWpFu)NDq+E28R#GC{TkRlEM-70;r7(i7!wngGzFE z`2@-ppcDyije`<AxHAZgFJ=!0Xj%fLB=9^cxHJX%2aKUDXHdxi87Bo5b0B9xF(T@q z0u|uZN8r*AnqCohK*}1BO`w_(VkW3`2KgML{0G%IP%~j60OcYmc%25BbB45AK<#5h z>jR`0+<XI7OrTwP&^!)ahk#ZOLEHiIH)3`M8t$MT7AQJV%PdH`0<}7z7-RwrqvmVy z4k1wSj&MDc1&Ryk{Ejww9VXN)a5#Z;3@Ckq!Ur{_f#zeNMt~_$4gfPy31}k#(lrIy z1<h0PpgA&7Sq+L6kX@kofbc;qP?-nHNU$6Z>SMtS1|@D-BM?!iz~+xZW<kOq6cR|G z0Ghu54-bJFkzlhy1UL>sZbCjk8Ds`HHbFH3sN@HwXIOm#b`q$lfK_nNID$A2-ArXj zSqU-`gh8<jE+xSxgM0}|fslj@HVG6}5buG^f|v?+GNcTEx)p3LH0;3lL4(UYaC{-m z2gMQ05Ri*e3<GmOO*7bCkg&EHxLgng^)o>(2DLjtF#;)nA=v`dECZ!%kP%SxVe7fT zck4mgXRMGuBdBEz3O{hY1?mSt{EDRi187SXTDujTH=zE5wS7T*`9xuU0_g|mERZ9> z#SGYo@c4wa3&7z5+UW}(Wdx-O&^l?*`UY^C0vQ7yKmmt6gaGXUtN^cGd%yr1TL!NS zQx*l?JHl=XJ;xqY=!0zrWl7MQ8PGT~q#RHMwf&)S0vgqX_!pG)pkW1?t-^38IIKY- z22L5MV;U&^bdX;`HiHa<)-#|q0jv8!=77QtQZIw@E;v1a%2jBc1!`=9!wQ^|AzlU< z2oeXEoM5+s>Kc?e5>UMW9=ib54WM8Hhd#)2phN*_EF$Uz@R$y`4++)-ig!?ufi^Ex zU>mCf)ghpDE8tZx;PeLWKO*$Obwh0fxfoQQfZPdbPeO7mhy;~Xp!yMH4mgiN+sdF* zlUIPE9Taw8k3+%%oOr=*2bar`Gu9xpAdt9(<SP&xG<E>88jc}GLAaoyBP2Hog61nh zCq+QYHE>D<t%nCI1`Sexvib+mXe!ula9<oUe+RY?R5Czf6TF%atP4cIb$%dIFQ{}u z*DDF0+lRE>KxqY(YeBU+$j@*$gKY;p8bW}a4)HHI+(7H6AfX0L{mS5T)<9(pB$N>0 z16B_i+k&<nKt2Uws2-3TAzeVom;-o-2At0rz<Oa}3#qLj_CaS~z-uf)PDQ#)2doF= zN6=UcD2IXk1;U^<7>GvoBPfYOO#lz7f#U~k1}uKS_JT)VpmxKRgBPE|c(Ahyz<QDG z2lo}h{>9Lb?0%3rFf+jELm6C0!*oOSBJw&Y&49`{P__i=#e%`38DMeHnpV(61ZeFm zBred+g@-6uJ(vKG^nvEpAn^dx2b!~mgexdSQTp-FmO7}Q1cxKcA0W4aaw<3!;pqmv zt`pjuKpGze+YKQgX$dwS1Tq$q2Epb+@-Aqt87Njky%1P00_-k`2?!D#(eQQ=#2j#3 z$%69(Xm%Ey6F}|+)!pFo6tt!WCA~lsE6iBN3{b`Zg;53geq~_>233S9V0VB@1+d*P zJ#ZSy4Uqf<cLQj)6s8Ok28<72X#?zLka|%1hWH%pcbIypU7!qzhyzgEp{fVPAX1z| zlgbCs$_a?Oz+nvTD}!SXoL)e+4LA-#HiBD8;823kpTgV#Zp45}T~GrKgdvp;!adsH zFbAaskUPL;gK`L}+2Gm?9EM2dA~V4zgGTuvu>uMywDKL4he5W0!U^nN@c0Ev$quO( zzy%N_F2VEnkop}o-VC~<5wuDZ948<vpks@m?GG4hM8W+vP<VlICTQIxD8GVy1}W=6 zj)#|#(98mgC`j8DTE8LXdw6(*%V)5e;P3$1fF<99T?Y+&kX4|`9Z=eY<X><-4R#AC z%wgxvfSR`8NJnu4xQ>R_WuROI4m;?0HP~cO)e5SoK~{n%gi!1OhZ`s#2r5I<7}&Mo z0tKf%2tUHy2C@mH5fo&gMirzD1YTnV-irxdS-_Z40otz#k%N_Sg#F3{(!d0oPZS3A zOtIx!=uPP$e}Hl(IOIXj0XYj4%1|1V&apA!Z7W2Z1)RR2X%XC7fz-n2=jDI`6_TVu z)*zb$i5HLwpd1K_8BqC&5?-Le97r(-U5|niCh#&Bc8&!!6++b_rG3!t&*0Po9?gLE zQ$a2RO~6!uk4XRpAvjNi%OptJ2j^vQE(5s?5~t8K01hOO3E<V5AReqt1D7?ZegpXr z6zZscgXjjWn}OI3^BZ`)8r13nxfoo6gJTO+I>E|ccs>VNjEs@P7c_nc4pmTY2blv} zPY$vaG#?!S8hi&0o`MoQBd8YunsEm0-UjU~X3PL>E&(lr1GQZkGr(a2SxE>A1#r6* zG;{|(AsAxk2bjM>{RnW{0M)IKyoQ`6Kn{S9|KrU+pqvf5!xB2d2ij!^KHdf7-@ni` zQLr!r=MhjU1eddj^nk1uWEr&00BUVRQV&=?$R-pwg7(LOw0;1!HDLO{@dAnyP}v13 z&A|Qyw`LTfaSQeyqLPPj!3|!JF$^&Gg6c4ESq>>v!RDC4$``QBAOe(QKrKj=bP0Al zC`G~bD}&a&AlnbhGT<ZvCO{@Y;s{c9!rB^;)D3MBf?WVI6}^Q3bq9z7m+oM<z~UNG zHiFkogVHFdbV1S&8rX*(WCE&<pl$%`1-SuIhl9c%w7UbO9~_dXy#|oIka7y#2Lo}@ z%_1hRfhKf7B`+wogWLg&2k`nb(6|e@J^(KO{Qx;<5qli~k0X%Z(AwB&aSHMWD5XG> z0LbCs*Z_?tLe_XOfOd&7T>za93C%O0@B@bfq_zUpjG$Z(9YX{effFOObM(RO5pe8+ zay_&p0mUu2e+F_BC>0}22aOHjG#IM{I4#4<S5RDn(;~>N;1&kh51>>D3Ij9)!0jAn z572M`I9q_j8C-Wk+zsl*f!z+$4{|4{{R+z2=wSj9Lxe4wEjYL^cZ27mL332#ky>!t z2aVQ1N-I#A1FCpHF$FdUTuFdg;1wXC^aJxdwc9rgpuGsp9-upY!SRFSK5)BD6x6qX z_!>e&-3F<`Q1d1zB*7RI3y{(d>IoPHUepg6pM$p7AZ=MtZ3m76NXURw5jg#T;sPAY z;JO~<7MM{OG{|`%3@XFG7#8;6{I3p9qo7m+%KxB!KwuhXJ}B-X7_{FD!)&Mk^yq#l z554{chaXP=gGU0uTT;RMEy3+D#tcyX2O0?n)qmjH4>PVI?G<pmfN~Zn6@u#!Xv+fH zwt%_`iGmbjAOX-I6lk>#)NF9w3R(*QsjETl1W1_-nyVCL1RbaV(gixw!vo3yZ6$-W z8DQxJKBf+K56F$+dK#2xK;Zz&^PrRhjSx`g1GV(Pc@f&@0J#X17e9b%dr&y2nu5w5 zP&hF#F?;~6T7|7`1+7^{+(`_bPJ+3of+>RO0_bj5P?-jbPmtZ9hB;`Q4m=qEty972 z0JLTW7M5WDgXZ?YK?Qay$jy+s6SOuRq%Q|gr=YX~Nvojx6l5bPm10YuApd}j2Gd{$ zO1gyB@!;MLsJ{#jMey7;BsLIj5lB>k1{1-~1y5gtVipz-3}F9(>I6_d2aQ#5c!2lk zL9~N<9pI`7#6YU2!FnP6VvtTqOA6A{1G^d2FNTaUf*V5Md=D<u)WPE{pnL_cOTeK3 zKA{ejE<mXP98wU!K*~6fLqP5Z(cpXvVL&_uVnY)f*bZ=7g|)RnBjb>=5|oaZA}YY+ z;h=~Dr6UG#dlDR;AUok0lFz|45zf2<vKEpaVdX5`9B3?qOKPy6Ksg-J9);)vk)SZb z-seDsDJXnE7(CVo$_(ILFCReLXp!ntQ2c>H6BG+z)x?yeknv|os{%4-2igA)UP}l{ zF%^&<2%zbFm|c*$2T0ovb=4jyu0eyx@ahN>HK37eaGZeWKR|H;9+3pClmqX3fh0%; za8nz+su+>ZA$K>xXG%;VYdb-10(A&Lv##K~*C2Z<E`a9}7*qw71;xQ70w{n%i{2sI zJ&@dwa057YAnpc@MS%9^fua*hEv$b9u4O=J101iQItCgaAX~tba3BUKU4jxi!oQ$+ z0hb%N+Mb|50xh`*X$NUVvK!Pd0)-W*#)ppE!`upv9Eesh6D7<*Ym8y5DnK(Huvu%! zQbw3XP&Y!(l>yZyAPmZfp!5J;feBIzG9NVT0+}QM4+kQ-5v5%UTD%T+p#q9~5aA8V ziQqf{&d4AWK^Qz|3#!)<X$xGgfkPRz0u?R)fm{SChd_ov>n3p80);g!4?s#H@E$sl zClHt^0;CO80-(4N)HVl)8K?~bnv(<NS@0fJ(D*obZWCb!N*cMq0IC~6HJK<VrGl|2 zXzwE^AAp<+_9Ce81Q`I1Vo>;j_U<uzfKJK+?E#0UD)1~2sP_zV1GrWJWqI)8YEa06 zM8G>e!Snp!IX%dj3gql9=&5M1JN%%z6r2Vi8esVoloUXxf&FoS<vWn$zy&+9d7_}R zd6gk&tAp|iWQ7J~PYkFm1@+%5z_%BI4FdTXG!c(s4nLAPp!q7$O??@l${pk$$boO5 z<I^HQGgqKq6Bajsdi#)C3EY<h&9#A6Z^A<d;v2}o3dmIO;3u*<(0c?x_sN0QbwK*T zkg^1#7ZkoA%Rxms<SqfkS$fK%!r)pK8c(1V+B%?u8{AVu(hi#PQvmJ70T}{`6L1(p z&*B4}wj>DJkpfE9prx+hSb^@AgNNe-=uw!ENqy-4B=Fc9l3Ad+H%Lwer4*=HphW`U zB$ol+{#^k+ln<KpK=nOxctGO>dNwg=&nUQO4k=WiZUH4-=yh|L=L;%}g2ED9u7O$~ zkW>MU519T8&~C2>pv($R6VS8fz~PE=pDXmtVTdb0^*xd^KquBAIRw=VXo?4=4Dh+2 zpdLERH6U|9iR=R;iGs~Rbr38(HZY*xeE=%4Atr&!6Oeh}vIyiTum?ez1;hZwJlI%J zltE-Gz!ftn`k`qE-E43>0McIsl{MgU1{8KnAcn$8nAwmv0!SD<9RZIAkh$Q~G$Cmc zeAg&=)hF0Qa2o*TB9LZKvmAOXDriUmWw--oCispJ@X5^>W`e>1bj}`fyYd65Gy?TB zK`j!{ngwW$jGF$TF+|XPApibx!0k5Bd6eMv4^DTW7BwV>kYWbxPq3>%`{q%Pfr0rE zoc562BnnQ!pk5JXm?7K*8q@(*9FPJ6nr^^(5?-!Acl980kpd`uKrR7?4XEUY>I0uS z3HA#toY6{ZP-6tv2!kFm2|8~Z>_1ROf|UuNvn7$!0JsJN<ps!kB2a%Ck_JE|Xu<(B zHhBSL%%2_LMhhr${WU-d8|cj`%#gAkQl}yO1iDrZ>>{l00mTt4Y;m{+%_X?q0S+Hf zTtmVY6jI>2748;LZG))CKqUmY1P2dxf%6}T0PRO%2JO%W^##G@6{IDHNHw5(40Z}J z$Z??1L5?d624>JLJRtqxdKFZgf?8zYH8;@pPq4ZS+<*iXz>pFLS}B4|1g9NXID^v- zG@QVvG9jA@so5ZvJj^_3N&*=K!62`J3v@^w!ws!p!96JO2q9>n-v?;&y#UIiuse0Y z=^uK^CnIPl9Vpd<`Z}P~fxtKGKx}~M1<g2tPd2Q8xt(PL13zd*zA&g91GjoW=?&aQ z0JT*?ePi(cNl+UGl)6Bs!DvXRfJ8urCTJobw44wWb06U5GasPDd{B;qm=79gg2V)b zL~=ju<Y!QeMwA&;!h?EENG(QKGJu!_uFJp<29=>6psoi~1Sl86%Q<kl2}!SDGZAeS za6JzyGhs$T90)o(73OtNBM!M-K*`UbF%j@cC8&G?w`O4mk?uB74ub6U1;-eqEl${N zsP!$_b&#<O@R`}@AqTE=p>D$+a8NVB`G6gC4-P1Ifn0?aav;;7nHqE|0H}U301YRA znr)ynb70{H%A?TyL@+*~2^(izg32&x8HnZ@NP83HIZ!O(ibIfF!1qjm$}VvHLFy?` zIs?_BpppliN<e)rWpHT*G7<$t+z5(la8njZ4m4_kNOvH&!t4T>4~h*?eg?5I?LwY8 zLKq403xW@0fr=MsJb}v$b_Q)oDFccpa9ayfb3(=dF>Qm*ZNbcg(jc#aG80bELG6U5 z4J13^=?$L`K`91m6M_PH5mW{uL|`nmauk||Ky7_UZh?%Pf^s0py)a$igbit{K!l+6 z1!$ch*xk_b6<l9HPkRKn(xLSPs6C9-KnKM!O8o%7??M^%v^>x$Eui)y2!qT5xALI7 z?Lkwdpr$`!{}&{bLE#K`Afy2P04oE*cZta3G9O_&L>s7Y0m^wRz(D{BOVrSW-Mt1) zC(uv?r4x)AW(lZi0~;!axDrxJLTed#+Gep};Aa5eW&v(1gK8-7SUyIc1bYxvPk|XQ z=YbrETvC9|1;r28T=2>3sODmcE3ko}4g@H2KrIb~;oy!Ha=d}(>A?Pn*2SP40-BKr z_3%Ex5)7m!hK^Z)$0#A=OOSdL)WZbNNP$WQ=w29b2NTrQ0Hqm_gTSL%;ISL9e$bc) zNFT%mP$+>hc+?oA9J=-v!~{(pfHF0B%oemp2ecj(Jfi^`%La{Yf!32kXUoAIS#X&P z@q7hn&k|_d0yItoS<4M>vqJMCC^dpy4W3~DwG2S57;s*MdH`hJ3{Y5tTmtGjgZu<b zkKi_iG%P)Wa~`-nVFaCb2wGQcst8}r0B$XOV0`d*1tj%=%!8yLXu}U$CxF`#idfAA zoiYku{R$fGgoZOXS%TZ?uvkSzHmE59&I+KROe8m>v?B<X8L-9=u5ts^mWSjVaP5FK zJ%U?>pp*b9JwQH2xyugfcW`*Z%MV0&Vsj(dW1w+MP(Xq)a=3!JV_-qZnrcM91AL-A zdK(aY^8!+N2QwQ~a6pm~%-tX}(ee;DO@q@WXucEFmIQ?Z=)5vm+6J{y!D$L)7RUr} zt_O{tfH<J`0N4yzzJTq=1C1qu!vLfo)ZT$6Lx`(DJ_HZ6fc1jymj}=Jfo4O%sSsWV zK=LNI6oUB-WHA`SS}CAp4H5w7anKkaWM3a>{~Y+9Gf=Mq+5!OQ6;aR_Bd8|>idDF& z(A#D~27w1$q45f?Tfi+aMbMZWs3!x;`ylfm<A&gKgTT9_Kw3dP8)$DBl)S-Sho)|{ zdJkM*f$n{Q^tC`W04Q&ON`6Qvf!olagaPXI!6FfKdI+do1($tbw}Hz(klVm3c|<|_ zL4E>dCD1KEpzaI<^!yocSqUD40*#G9&QAcHodD7Uu@jPEz~h3TiVdlq47LmEW^kH= zrW9~%`vJ&{An$`x3Cw0lXBuih$n%hX6F9#qg2(p2DFhUfAhST@dk^5@2x=-G0M(_S zv;s02<Q&*~BSz332JpFNFqcEdl^HXbE+FJU+Ydp$g2^!-K*%v4fLx^mmIE(mf}HOH z?ioUBc<}5hXg(6BJZRPu<R;MBq6{BE=kb76(t*llPz-=eTyUBM9ZUpSXNjJBAwC1O zB|r;MKt%$myeCFING(VYNd5l~#s>@^Kxc%BgX#fD-Ua6)nE4<YR6l`|4ZJ=A%@Kgo zGFT<32MgYk1wOa|a^*e9Y-rsB9;*k{-XIL}A*kj7%@Kf21rZ=GgDW0zomattZLS#H z&Sdsr0NotR4w?rB_2ofr77zxn`v92&ax4P_3&@?|c}vKC6>!@Le6uVl#fXAxLQuO5 znufsT1nBfeNTmld0)#=C8gwlo$Y-D;2s8l0zyLb!n1KO&*CfPjXzv<fI><es+8K)t z-~m05Ss?R4V>=O`MM2;Y0GSRd0KntmgwJ_qV2S{joBWtHCe&=C9h0EA0L`95)_*|L z5okmX6nij?vOXD+b3mqn(kbHHX`JUqW4H+t5};XgSkxfQ#pNcL9uSSF>p`wS=mqgW zZUXH|V!8ktEyA`k6;Z^4)Wa~UKF}Fh;8Y1IMZhTm=2n;vFb#`$4{%uqN`L$e&XE2U zs4omkiy#^r@1TAisI-T+wm>NXl<vX(aF7^89&8)vYzk1L4|FEf1Eiz@wiSs0m5iVg z5>oddNuV(qSQtPV6|^1^mOjCAte_Gev||etuHcXX6>k+EKohPY4E8jvtpwh4EDl<w z4|O?c9U!QkYHEx$R|{D`0j@wng$XG0D1ckLp#5U7^&_Bl!`7g1f~^q%hXHt&o)KK$ zD8ow}P^kdf^NK14b|}P`NK8mrfQ7-{0kc38-%th$1u71Z%LH)-Y4GYe&?zI3zBgoq z5KKaLwt-@l*#qK7kX<0FA*Yvs!wl?gFaZfU<T6K?0cJiHvq7`Apm+e84^GiA!@+9= zLH2=50Z<VQS^*5Y7aZKA0Oc3xd9C32Vo=P0>U~hU0yQ(iC*XrB6;J^JX&ZsoZ9~>2 zfc7AR!Wp#h585(^UVH-yJ5b92w6+3r_M0&5>^IbS0DBZ1tOyq9s&WR%e0~IEJ|C0| zP}cB(icnDaL)#JHw51L!wNPz<luW2%NOpnk1`!ZPgIK5$&cMuooc4u5w!q3|&>3Q& z{vBvdA}B7wx<Q!=+*<&xBl<T3c8)OUc5O(X3F0D9+67}+SqY<2%1n@n;1~rl;20cl zA7Ev*Dzu#pTloWW2`IilfTm$VSsUDN1Fwtv0AA+;%ERE3IE6uTPM{_s$jzYRhCm}r zpm;`@4I0Y@mFkc>4!Xh%Wbg;Dvp_WrxXl7S;}6oNfUczijc0>Sas!Vzfi8tn0J#Ga z^q}+!ia&&1;Qc$0QWIQ*f?D39pfz2fRtwZOVE==(f|`M-VE`#}LHiLwIUW=rpbhk3 zec<#9UN;AGqco%xQU<49P+A9#&>?70_(5_ZSU<$YV7oyClD!Z&Lq=sGVFW3IGN8Ia zB^bmoutsn=fzRE8tT_YUvJQ%M&>1nHSO7KuK`OyZ3qW-WsNDr#$A)NIJ^)L?&SiwI zcLANK%W4Wbbph1wg{&k2mzt3Lm%;1-YTKwnM*2a$1aO>yivy7Rz+GC9eV{fHM6EeA zO@UhDkN^P1IVdr~!XDJdV|)N=<AM7%Ab)^L1W@k-=6{HPAWj0U@2G(40i7WVnjZj_ z{-8Jp_vb*p6VQQAXy&8rQAWfOhy`vBgK9U310f*?CP8rowF~8J9*{0bT!T+?fQLIM zp22Yj){P*L%mLjujWaJmnnj4b0JR&W2a?9H=LLvGpac!g3s8NKvoJt)I!HGtzQFxW zP*j1E6eK}|G=sFFg%>|~&p)_sh4>UHFMt+Lg2D>ahhTu(g(G}m{Zf#f;E(~eq(K;D zEgU0-55&#*@&Y6^K=eZV3ocg~GeBt*)OrTBB0%jrh@B9HASDdoec}usAnQCKsT@*$ z!TOQlwXp1<T&*aIoDU%J3dwh%J`v*skX`V#Ht?|kP}&3c4ncv*$N);G84$JN82JF= z4M>&&`5)RJ0k3I=_ySalfl79We?UHhU?%XYBS>gMeTPPY%ma;2LeA(yIv*XB1_VJp zBCrNf9Kt%9ptThl;Ee*{@d0T61Ulx$462(!X$XwLtt3!B1(#CBqM)ONA;k_T6M;+y zh5Wx6;4}tKWFU*c^%t_)+MpT`)L)1B6I9}YM#sT?P^ty3;DF|BV?j{K4_ZD2G9QA$ zsTS15M6PH-Rzsvgg$yWtK<#9TVBiF`#zAcyQ2PdSYZ<7V2c0DhZA*bS!2DBy4E0uk z79xN~svzT3p!SL+Xbf2u(X#~CWsnpOy88l@V!)LdxIlz1vw}38Aua-^duVwI9yeh2 z0L^}aV;i~)1nhT6>m1wyhlUAwof{|=K_LvLAts`d;66F@d=Sw71o+Amu&Lk}gQO*6 zL9kQ6x<RIa&iDu28Uqpd0O=%y>Qu;jUdR|4cy0z%*MUw3grr1JKN+M4v{nyHg9vcK zM4VFr@gw-03Rvoa)^Sj`fLq!ie<HV>;0A#c5vUUi6M^&tpy^W*mWIG#2sR(QmI;(< zASnjCEf#!UEG(sfJPa`m)JlPc8E9@Fa+eawpWqk(g&L@&hqZ^`zC{EcB&I>V3(#7I z8PGZv*1uo|#jY@@K1Izxu<>G$E5R6?wqYq3TF-%;2oi$jBM={qK^X}gH{dV;uMq~X zWdM&vLs#B{Pm~4CnuG4L0F@VDlN3NB-Jr%3*c>DRR9+yLKcMzIs67fTeIO|ZS}Vgs z0ZBWE39<l0!(5LXuAq4dkZw?@!g3GTOk-$!AEXf!J)j&7p5p*b;K0{?g8hlI_8sg# zP+bV_6M^y`I4wceih~UU4djAmu^`b8Nk7nt2T`Dy2bT-rF<NF&X%1@pFhbWnfI6Lw z8K6`RYS4mK-GGW1aQP3*x8QIGjpjn!0$V)?O2?pZ2d8E55f-5E23ZMq7My^a1u9pd z=?>gpMJfkCX%Au^*fh}6JLHrHHWWmF$E9Ft4ty>UBsW0LSc8^Nkh}p2b#N;Hl!HO% zvw*`K)^Y+hc42OWRC*vD$P#Euhr1he79(W72o$r>S!s}qk@v2E{0_k&W5D+dfWi;t zXV9Dx)J-6NgHtegg+8=40jDDcXjuZvU<#1E&@lbbdJ;5B3u>Q0VgXz;fyzxmP`H88 zKFD5V4C+h40ukhMgnuA?D!5sqAQ!=01~nIUrX0v^pxOnN=0Sxr*b-1cfye*BX$zcg znHh8;BMhJsSkT#kAhSTJ1=4bamo4DlIH;A3afUwFWRMl0G!06Jkd^~P7~~X?KR}zS zA!ROO26+4rR5F5M23op;Oa|EuDj!gC9r)yYP#l4x8<Nf-$Co0N383@HK`UCo^9`WW zcs~470IlMNG@ig^5jY<~)-J=&cLbea4n4CFw3`C7Hdq1Nzy(_g4kjc!KxqjS2B6U= zP~8u<4|6XIC}%?a2`#Undp|(+5~REahbzbgNb3Zg)<Llf=>vk2F({TGp$8>FUI#H@ zG_>pjhodTZ{s!tYa9)C}MFXWW&>9+W`3*{KAX7mY92+3hKo}$dD||qK3p&gc99}rg zhOU!?<RcIXDoemEZ%_gN4Zwg*g<w!O0hAQLu7(*7OV42QA^X~(ZU?y$l1o6R--A*% z$b4l;Uj!UhAjg7w$)MbZ+|q)GgDgd{3gHjf9!5}F1Dk}!9#E|c9>)ZgI}jhC+XXfq z>`#zg;H(d_8YB!l6arzNCT5&~;vZb<VUHJZmPd;jklCQ*0I~=cd<Z*q3EF|hN8rW^ zB9=fd2bqp+6NnFL6C<ZFLjrbzZ34Brpm7NHBgjxx`#}B!dlb|^LkU6{2a?~w<q}f5 z2A`%5E{k!d3UD<FF$GM52K7J}M1g$>3p{w*1C2u?r9BMu;r;>VC%A7ws|CQOgA*Xc zZ=mD=o;w5E1P(k9foRts0FQZVgZga7qM%l$F*FZB$^mdn1lxd|(m`XT3ZT3LG9DC= zFl)i|2T+p>!~)w1_Z_56huCLK&_1{yk>d=jy@+T7+lgX1NCbpI=^xpCL*ng6gfR}= zp#crH2F-GC(4gC`OVDm`8wQkKA$c8_y&xMw7&W{>DHv2tLeeUDk2I(+11iP97+h*$ zl)NBwpcq^(f=<Z=moLcq%osVJLE{AyPoUHfN+sZW0~TVCS_6Ao1+@#5exOWHVgX}N zpn<{+RF**Yg@VWT!23jC_JC?R(AXKM;)Uu*P|$pY&<pCvfm{Y|y@6eaveFOU41rYK zX!e4007y5u_6GHiVCq3_2ZXKQz6&<Jps)sy$AIc0m|mDZm<M2PW<J0KJ`YzFR2M+v z3v4&IeGaWF;e`n(q(CJwga$=Cs6_!v=M~^GiW{^e95%WMnoj_&TLbmoLFo$AG6$bd z2O6dXt)m4^RDqoZ%1|H%iksv?^9G>)J~%wUtvj%rKqsj~>MT)k_aD^20%dtn`wr?N zkXdjHNl%El0gaGBdS0OP1C7@Ypv6BBU%@qEhOarKeFh32Sj-}y#RXoR1kn!a@`3XM zioM|W4p=8BY~cMe=>B$yP7nzT2hc1lXaoc_t`61<ZDV1HSGWgYdcpB356StU5CrQ7 z*$u*=cm?-qL2iJ08%%*#Du7&oia||yZ~+eL2Y}-ke3mWPBv1<(bZ#}Mv<CG~z&gQZ zft!w?#S)O2Cvb3r!vtlF0@Th0tu}%5TtTTF+U|oS3UKoM02<i=t(b<?B%m}8IU@wN z763F#2I{MVTm&8410@ACXMnr_)(dX?g8PGzwQryj3RHH0YzMXUL41hC&?8bnU0hIi z7vwqc=5VlQ5N3hbFM#3{f<bLwP+|aK=vo4h-OLQ&^E<)yA9UTbF=z!kXyg)lwmztg z16lR~)O7&Ob%AUJZQTHs`4FSPW4O?^G^9-c&KsaO2DhoeaSJjBwEqL-E0AwMRVTPj z4{qy#3tW(2AQ%!%U>P)jLC29maSZB*fNBVk4?$;qg2M;Adlxhi3EBY#vIAlus8E2W zLr7e!Lic+Mf?Npd)qqR^*Y_aTB8@IVOa*0SFbh;XgG+2M4{kW92tqL*>`qW?5|YY6 zd+b1Y1mttj*dRzFXe0$hLovwDpiIihzyP{B2(caq9CsPuZ~&ES5ce~KW;?*+4WRk} zl*+&-rGhqwg4T0Dmsx>R#s|=vC|KW~AGCJ_)Q<%D8x(q=cma=DK+9*4Ge8Ob15*TK zHzmTOpi|2cXFh@5f>g$Wd)}b(&{!1NJV;6XfiVMS8n|Qxoe>SbYZekQpmbZo1iDKT zGAj?xIpCHg#Ao0h7&sMzJO{3nK_LzbIZ!eL=iv(QIsMT2G?1?#=?@gQpiqaTJBS&e zObd!g7>1jJn8O9nOM=FELF)>@P6nMX2Ew3x1930tyavczGN`5kyBXwvkZm9np%~P6 z1805c7z=v&3o7$L<u|n4hw1`R5S^fg49Gr6yd&RbgY%vp(6~Kh?hG_%01ih%P#Xji zc%WJja%~YP+@NY<_qTvj6S(aKN*^GffG{NNKw%0>9T2C1NJt#O#NZ;3^$`$%g2EBJ z3J)?*4XSy;XM}+AHfW$5G{6Q<+MpQ~=(#>fdcf*U!D|vhH}=48-2v$W#RCh70M|(n zJ>d0wkadlqd3um;P|I-!sNjdJKL9Tr2e}lyhUx=2%^>N8jCX-X;XyIU4BlJ=A;D<? zob$o+K%fc;8vmfaFgUbO+X0|Bhqi^mAp{z<hr}bO&H}ebLE}S;;MOC^Hc$x!%8{U! z38(^|0UBrmw<R*5=78J{!=Si>mbu_M2V7%;#xp_b3DnvXWdhIfz*<+ZvJjNF(e*;> z97z2uh*p+@VhX&l6;uYIjGHKe+rpwCUx4x&q@IGL6>zQtkD!6<1=$HU1{@GzAAqtR zm;oJig0zVsX<QLo*$hpG;F16oTCidX(E<e-4iyD4L2(5tPr>CBxPIjZm6@vG+qpn1 z%RzlT(76Jjh88G6fy!g}%rYpppyejAUQoRQx%Cs2MnGu-q8n63qv-|3H6#zPgWHXu z7M>vF;2cor8ni_N91n0cpjjc%Eq9PnV{lUxG?|8C4rtz7SrC*Tz%?eQI)}^?!p_9v zhS>#*70^9g;7hJR-UEmB-xc7w4~U(hbvz89wlTPb0L?^!M^_->0u4!!F3{lwNL*0B zf|5T2%uZ%V8ymFF78LuCb`vO$Kyd~N8IU0mjL7m3K6Z1kxd~(rk|Qt;0)-PK{eap& zpt(}$%5QKifd->MO-T?2&;Nr??t`4~0J#SeoP$AO0B*^H6A;*m2o@~ggX=s*KM>SI z0p}TTZI9HR0MCAaX9Gat0Ks4*K^Y0=6>!#oW-o{&st6)^!{Qlohajk}2&%EcH3!IS za1I33Az)vlobZG^e+V8I0qq?Drvr#t%nbIB@nz^<HE<pSnTMF00F_DL7=_vgif6DG zsI>%E52{%q9>76@d<^j$4h4{=060%T+yy$@2^5c@85&SO2R!csy44F@gRKBJ13(vB zg3<!$qy|uP5@}2r98cgeewaT%r7I+Lg4@;5xnW3H{n-I>7Tl5G>;)>MKusu6R~#H( zkbDC!N5HE@!L1X}dOA=!0@7cBoJ=8Q2q;~G+BO$Jxdgm62ohJIkOb)m(MV_iflYxV zI`G^NI6UC`!F^)z9vN^63o7eDaSj>>0BeL0A3*&ZP$LJ#1yzw?H!yoZ`qfBofS3ew z0Vw4o&3%D1f-xuvz<20C90P6Rg4$Z(J~}w>fcyh;1$Z17oJv5ZVeu2fU67*!p<#M~ z3AA<yG{ON}uZVCL_+CfQy=!3CfI_zdw5Sv68j!yrc^;G>5N#JwxPbaEpuIZao*1YM z01cUfa~d=iLc9ht7o2E7>yseoH*+(9R+NIw0Qm|$Zw^ugN@nmh3SI{SSvv&|Pf!?| zBA-JE>SluD?gRKN7?7C|HDGh0W<lZ^R30%fAgKf8JxE#wrAN@f1WX~gyoA{eYPWz~ z3hIMHcQ=9p2!vtr1Z^8Js0xD4Dgv#Ei~v<Upm2kwWd_KaJxGlR3MWYLfNTb@ECJV_ z;Jm~PT2l(z?*{5WfNDZza6Ca;9^ldrw2BG7$QNP`sJjSigMg|asG0Cc0LMQhuY>2g zA!j8aS|d<1!E41pH6yrX0yQ6QI(V@Rc=j85^*X3{1+_XLH0aK6P>%}S$3;IY800rd zIDo^_Tu@O^Tu>2wKGEM5U^BrP8XS)m&~^ayY;RDR3#x}fDFajzfg0;b>OiR(9^atS z5_AFrLOrB41kwX)CW4wNP`#kM0ItJ9X#iAiDGS0>foy`_Lk=kqV0{meJ>Xgkv}*;X z9+bL4IzSk9j1|-l&^iThdIZ^ln$92-#7OP|sRjE5t`?G~Kx^f|_fSLED?v4aLIR%l zpng$>lndaz#B>4d8&G>3<S=;I!~{|cvIn6S+%5)<#X$9d0t%)N9JO$JpzUz@m=vf~ z1=UNS)CgTv1hNc)Vc|g4GejZjh#x$@1)IMV1f56*%Tu6S085u(Hne>S&0FAo)5f5E zRNy)fI=TTa5yANYG(Qfy5fHSK5$Y>Q;{cHp5PVQh0|gR@28lw{K>Q89{~8+qkkT47 z<_4`Uz{v)@mJPC28k{dctAs)M0z72{G7>ZqI|Cg4puH@hJGmkL2B$>u=rS~YfWsVG zcvVy|aDv90!1Icr^%9`=r!<2)gFb^X19%NRs3wK9MM1qHQ2PS3k{p7;<0#-*1>e00 zO7Ecl7NpDvmC>MJhO9jRU(^gvD$oiCyp9UA9R+;U2-r<f@4|Ypa3@0gqTuoo>`v%- z0yrmvOK!05Ky5zoSU9-t0BtLPcBF#RKgfJgVg+^F!C}PkzXKe{^5DCHK)0Jg^AM=V z1SuC3L2WrmdIg0qD7wIz7F<+<vl!fkkZ}}ne+g<X_-;Z_c?=38aQK1S@entI#6jgW z_>?NpeR86p))UB$pezffK?Hbt6Ub^12V7Hv+yF{Cps_ws+mi*9S;77Qos=XE*?kYT z4Kim2&2_L{UhJTl0gHi3Kj;W5)B=!SzzGd>g);nTYDipwA_gP}4n0sjK<Wo@9~ZW= z50Yv@z5=&8p~k`H{yu<K=77TodL}GneqR*4LLQnzkz)}wt^qa?a-I-4HbH$Ha7aK1 z$RHL>5ac{`J3#kGfcGzhQZ2|tMNmlwDZ@bH`=Fj5*eqxeRQ%ZiiwA@VD1SoZR2Q69 zKz&ANID*F}LE#CGTcnf&YHJ}<4#*Brcz_EUP{SWmRDjYWNDAf!a12A*9gy&a>@fwo z7u=cy)o!48gVe>4wgIRm4ABQ0L;;uOAlsm~#DVJ#&^|UuSqLgSz+*p<m9U^5GpKEX zz@WGWxd=QKgRBQSjsuDnkS-7gHA2BVQy|(wo&m)JB)@{vCWd~Ht&mnSL_esD@B!3# z1Tnx?g9%WwW<~1DvNM3%_u$=}Fx@a3)XE2&045;DfXx6C43IrCSlxke3&i;#y<kJY zIzd4Q%3|QXcc}VN+<|NgST~X}C<fv14?;hvOa+B5#5G{Ezy#P7D8azMz=kDUz<X3- zA%aRn;|OdLn1IF-+(6W{f#f$q@ajfTod@1822Q=8HWFx>1zZ4uOakqUM2tCrN+Iyh z5s*JXBL<LhKghjh;BpgGf}t4zjUz~!2c=J8aGTZ?R0@M;K0r5ug7#=Bi-JZ@!R`Ug z-asZ3Ag+QYepG`Y9WH1;0#x3E=J=uO*})|+B-et*3BV-~Xf6Pf|3PsNawyn?;5rQC zZ*Yi#+6SOPhX=6!5vU#pojRfnD#yX2YtS8pU;{v!L9J|X<qYYlFd@YsKWJpgSX3M| zHVEn)i7G;RXyE(SL9T#|%Yr9>!R0Qv?*J}$!DAy}cZ16XP~8q~g@bZ07=s9CnG4nj z?sr2<4@eq;tg?fUpjI8UMgV&oPC$x6kZ(XN5RJ`DkV`-%A-FXFsq;YL333}q8{9Mq z1LQT3>tLk?!f)X7Od)=Qj0b?z9%yO;q#jf~f_m@>^<Y0i)PvF-$Uaotq547gf^7vc zz(zp`5Et1$;IPFABh<b;#6ysfz@`^9EKv1=-2n0es9ph$6+`;}ptcpr-C#e1N__C_ z1;{s0_k+e!KyC$NP#F(qfKn8wj|`dTWMu&Nr64*$Bjn(+9~xGWxd)`XLm=+@0NSVZ zq2lifgj#TW0u&FRJyxLH0jfhG`*uEn`(I!^|7L*Zv;HZ7^?}kfEdPS*2}MyxkS<Y0 z(8!l4V+N>g&6okcWDsOw#ora6yo%&TaGrv?5#)bRFBZ1@43tVhyR$RE2WlbD2SIlt z3q$I4kbB`X?Vv~kPmX=~YXDke3hCE^`-|W{GbrCOgF+cxmxIC{nkPW5SW##mh6OUX zwFhduLmDEWv0{)E#7uB_fyyn=xGl)vpj8~88+9N~fXz>V%2`+#f$B2`kPATjQ9-SE zNHO+j2WSieTwXwQf$C6XJy8FGcFlt^s9y|n2<VUxkXBGgfleau__G6CZ=vc1m+g>J z6=W}{Ol1X+K~z8*CE%e5h#Npt9AJYX?f}&}=w^ZI9EfRPw?NBlgoz;iC`LkE2io=i zX9wu?0ccwg6n2pM9khoP9ExDK!AykFXl{ix#zDudfxHebouLHMy+fdKAGB^wl7T@S zG*$^JX+eECP&oymO%(;9#R@1}fm-tLLKoCMi2xny0BVmw@)2mBNDw^70!pQzK7*+u zc$O99Iq;D)FgN@IuWSaF5771_q)z}!Z=hZa$Tc7~xYPu->p;03sa_I=_zDz?=oq?l z6DABQ8^A>hq)Y*)M`y4b!SkOWvq7z2Fb#1vsC^3RFM;d_xdqGzm7kz88>AM(#$2Zh zvyv1V(%%A=b&&g(K%*8Q3?7>Y`yS+TP{{|H4+Z5ii0Pp017X2PP=15Xje^fx1mz%D z-3#i6fW}QgB^;=|57h&%NnzO+G-in$xuEa@oxcKc7kHl{w9f}x6#-tu4QhD{g4&p% zo)EOf4(*qL+y`n0A$7>W_Z@@#sPH?L!6ggammq(G;{g=nqM+GD`1ljJXaNzR$_~_S z0NV)i2FO|v29@@(^aN_lK<@8_#v}NIQc!vX-<1mrQ4j`c2Um2U-Me58ga9oZ0htfx zf!Z{%e8LU6a|`ThP#%GdeL&kbka2otaG4G=9qLMuA&{YZa0ef3A9zj!oPR(=rJw;v zaIpqS3;#P1VFbPj1XN>!%3UxG?gxT+;L#~iNuVqWI#veOkB7J$6#5m=rCp#(6&gU0 zFk%8_Sn$|7Xgq_#9GvUHEk}@_Kp_ShQ-mfAs0YACg4m$e9%xbuls=$kls>p_1-TD| zL9PSGDJU*MsSO%3Ad|ta289lI90F_{8iB9}O#)&ccx@zjtqLTyfXo8dO_25~q~3<> z1g*6I`5jyUAj&B4TsFvcpqK=i12zS00*D1Gq+oFcqQRk90j?{-=77r)d+@w3q#ObH z4CH%|FTuVCx4Xb88P*d9l^-DUK{kSH2eEN_7w!kRYamgJ%muN*X&$=&4YFSdRBwab z1abjnyaPJ20*V==du3n-Lac)N5M(CApWt)?ZWDmh34F8?>?cUPBJK%*m;nnZC=GQR zIIIwH1};TFWhl694H^jm@5BM+Zip$6Fab3o!F^0{c!S*mIx8Qv_ZdE)3`&P+Y9Mo| z@DX^BS)e^lpiBlj(hj3P#SNNc2i5qXmIga?JRPJ9vi#!D4iFpCLjm<Yp|vL{Y(V4d z2N;+^WddmJ26QeGZ^(nqf_M@^g0ceW%mai7gayi`$o7ES6w090Zb&f<N<(Np6Nq`> z`WjsC;xGq1Cjw2Wpx6MVP89b+%mG*bAj81n3~r|}LC${S2d%3F`5bi09B925C_X_W z7vNe1vdjP!?2v=zK*v{sXFfn_1H5*I0o@$%iEW@Y9fF{KKX^|NXaH9Mv}gbn_MmbO z)fh;b08U?sJPnQkP#y!VrUBJ@pgJ3rx<SDTtMWi>kQk_RfSzvvX~Tj0Owc|KXdV|l z8wXmQ2_C@$wfLcJ4{-W~mXRPfB<x@;5Dh8Mp=Bgwz7JH^g4+~mV|$=hF~mt=M}dM3 zlo4UWc;LZ1a6W+f6;$%0nE@(!KzR#f79=x)%mSGTGX~Ufg$y==(iH=E{Tegq^jOfW zD7XbE3aSS{;RVXy;IOGcEagGeXpnFR=Sk3=!JzaA&T-(<2ArlKW`N=v<Nz23hY@5^ z7qn~un*rKG1?i=LLK_rD&{hQ~{Z@cZ4hN56fL2B+K*s>V`au0KP&*Y==YrQQfcCdT z+DM>2RRw4>9ODCU-a^C$Qv~SF2uS-1S~EfH2A}5(nOQ(C89{*vicPSIpiBUc2iP2` zB4~9EIK_eHD<KUD@Ln&li$UQ8YC}Qyq=Q<Np!pH7O`!G-xD^XF9CWf8DAqykC6EB9 z%Lkf!0LPIaWNa1G8UURy2WrJZTU`*Vz^w;H@X7ocAkD~O3n_O&=>jyW3#kE+?m~ft z7N~~>S*`|-DX1eLVFqebg7=X#u!3fZz<MDu!3bX62I{T;1zpkzZr_2!1>|1v`Ug<C z0%|RS+F#(f2PJCI&=aV10EZCc1DIZD9flOA;1xllpt~$Vt^|cYc)}FqI>>37aDPJ9 z#ei}x$R@C@pfE<B-v%vqg4hby51p4}0J|5m*AIMFCMXs`lQN*Yu|P@xp8_-vLGy~B zGbun}07~nEpqVmoEPz5B<T%C*@Nu7@6|JC72S^{NT@Q5|I6Oe(NZ?)!s1AjUW`U9y zbnzT020&FI!foKQc^Dw)FoMzxcw8H7Gbk^DyaTfw(zpaKCI(G{L(?eaOc`U)8IWLi zLrQ7rSR<%d1uyRcnFXyIq52@{71Txno&5+}Q3}GKem}^$;4}hS6bv!}gkgCSv>p~z z|3cC@X#N5;cLUza1W^uZJA%RmlqZ-y7<d^#X$q8kL9HiIMYw9v?YIX(0SOvR0M%bm zcfs!3fyOeVEdUztgiIQMN@MWyv5F6%{mY;OEg@+b6c5ZEpxHdo3Rw^aud@dQ9>`&k zW&|Srg3nC>r9M#m5L6O^N(*p02CY#9AM6C`+knFXQdEF~1vHonH3JfFtl)JHppXOA zjNs6O)*TR?%m*N@1P39cZ4T8BKl2h)x`EoIAd^7lDmWE^Tm;Qc5QD%ZNCcd;VTk}* zR)O*_WbB9)+^Yt)7(l0CfQsP{pk(s_G{S`lCrDn0ry20t0`U5DP;vvE4S{eY=qwsY zTnmEsqk~F?8K9yBTJVC3C5X8oH$d*ng7hOHF#t-@ptJ{y2G9yGaKQjQQvhE6f$|+U zXnX=x@`3gffz}8@8WNzBTNOYj9R6{DrV*$;pmYT)mq9bopj-`)HIR!yNgj0W11P#c zX%U(>Kx?-kp$lrogX(Aq52Z%|iYbtV;9e-Gs719`5ado!+5};6DTK5_2^7|#AOvAh z(Px0r3(7Z;Ghje{RM^Y{`1~hO4FRiFKuHx8)u6-%@(E_xg3~NKMnLKzsRE=66fvOm z0rNLBtYH0Qa2*D2HG%RX$Q__C0Ao-R2d`fO<u7<ngNj0ohWZ5*mXLS`g#c*O0i60F zp#X9=xTJ%`TLw~Ef}~Gz&?rC1W{`TA!$AR1@c|UW&@upGKD<l>%}zu65TK9+r6p+j z2AYtCrd5dfp!^6+d5E+M%Z1>HIjDMw9gv-s;2u4wO#(>?U<<&Pse=L&T+l<}0pxdP z@O_@3lnO58!8I;oEd<C*(A_ZLkOUb3D&Sxl7Q9vpyuSrJe*$gqgWBmJGeG$k()$Ou z_d%fv342fof!jEsyaej;g0@b8RuF;bH6Y`M@OdY2`y5osFg^gy#eqx!b&etJK~P?U z_VqwLM$pbNP<s$m-WZF*`g$N=Kmq~Ox&u1{+)M)%H{f&9D$veJgWV+uI=&N{Y?1OE zsJ?)<i$L~(mym-z0m^FN?lx#W6zKdR@HwLlpm{)$3t;y(gWG|Swl!q*4rCUnqy)Eg zK&?<viw@L(0hf0m2FT9{3?APB#T_`zp|ii>{UG3$2dEMP^&i233_ide(G~~W4Q{W1 zX7WI-4`onGQV^Q9Kp6y@P+)UZpgaeulfmU6Xgw#mJq4bX09B5VB>|8dqrf2mNn22T zkTL?)mILok1hxM`EedeFgM0*Pu!A_z@pVM~2OVRTgtj9==@NuNH8gl80u)Z**}Z=X zAkTta0Wu5HivU$ppmrNHk3;Kj6th5S6O`jY<CI{tKx-sGaSbYTK(Pr*=HT;9K+Z$l zLkq2Iz;Om@NmqdGrGT8U2yPa_(g~yu1*wHWWgNsFMEwB{Do`gKG>8cb2~cecE-#o5 zK<ZMEUT|9m6mp<GCU_(e)TaZtI>35B`4N<|L5(?(!$IvacyR}9Yl6)KpIri)c?HKg zs4a)xM0hm;avEqsHz;7iR)Gj;c!JU%<Q_ZFJQpb6fl6Uez61FW)GG(KRX{NSsfNJ@ zfeZj)Q2v9Y5$IWzpuQ9|CxG;W@)UH28RR{Xau5b-MYSK%PXPG`lzTw+A82e7v{ng} z)j@hdGXS8h02;vrRlT6f1RT!bya1kK1MM~d_0~ZrELK3zu>|E`rVF514NxBfx()_3 z0E%*+KX_~pvX=tXQUUcvq5DHXp#UlSKz(|se?Y}1xZ4Es5GdZj<vz%jU<?vPN<Wg| zu{u!60O}`$d-k9f87O=pxex3m@GvS!C(Of${Ub~fp!Lw;em6XPL8IWHv<NPdLAHXN z0bb$*&io)3W`K%Um^&c#11Nr>btAY13-KLjJ^@mYf()vt_y9g_1d<kEbrWJN0hHT7 z`5!dK2Oj?f#TdwUqTq9`z~vk`<AItxpqPRf3ic!{y@2CPkbwbW7A#+ZVh5B}VGS`* z-hxLtBF%v2dO+vdfKmyl?EtE~!6^r-AJk<7l_4PeXF#rpf?5tvFW@n5@ERnD?VuA3 zz`YYtYZuuZcpgIb4d}cw6c2&T1p5c#CeTPWsLlrU)Ico?(9Sb(w1V6)1Kdx8M-?cI zV!8JiR^Ng0EXX6^vrIwjts&>Cf@=y$$Rq013~(L;2R`CHCeR%-qM$RoAa@6WOCnHA zf!rnvYV(2%evo%SMKI)698fw0&7^?B8(KGm&$0xsi2$uS1dj!PW{^c8yZ%8IgF9NF zel95NLH2_h(V(@Cpf&)5xv8=!s09R807__}ObRz2yv7o|M-!wDww46c#|2jcSd0hF zH-XA7u)737t4QH%P(Wibpi^)lx3z$8rUe~D47T~-3{V*YvKJa>@V+J}S3z3rp!sdk zTs3&~4_@#=d<CknLH+`r%L(=uXarJ{5poX@ECBz4#v`EN23|)En|BB0H&9s(b{%LF zJ;+c{9)suvmmr}2GqPUr%rN-OK2RST)ZPU3Ex>2<gIXe>);VbAA9lqUXdGq+$XHN= z2;oOqI|mf=p!RA8q&)&!p9b0Q3az7=88ks*X)Fqwy91RJpc(<(mjKmR(7p+%#DJ7u zAQym=4!A)HFSI}b2dX9@NghOka0Mt$FfdfGYJlU69khoA<S#{0R*hdbKp0dzgYpG< ze71u92e?hd4m&9fl+Hnz{l^au7zULLpu_|zC;xY_YC!wGppqMmL2KYaH4$j6gy{mP z(fLoI0+h-@14p2C0XPUCW3c}_*ncn|0PXl?1?vTuNuV`_q7V}xB=Z3li$4yaQ~#L{ z{Mk|Q`vjEf0N&jV3Jp+x1(m=IOpH4JJDC4~&m;%$)CGkmI8?zs8&Eikn<|Pj{{iJ$ z2nIK$L56@ZsPM)x1FRn$6CnMdwht&&m}DUOKYaKA9!~&ihhUH)ure1MKH&B$$R!~E zflULu22>Y;Oa#ROi^cB~5ZxFgJntaP0+|6GtAM)-6jC6UfyT_CCj36ZVgY5sDI&}Q znFPYHc}9@lKMpJ#eg`0#4H5)ZQsDH?{)5?r0W>EFDS1J&#HJt@f_w~0$>4Pn;Cujb zA*2lk^*5^q#3T^;>jsFds9@*#@dLubMnc<V90ibhYDnpd92OwAgRrtFI|s~wA3wn9 z7tV)@L(SrLAZ!*V)NvIR-!!;Re6>LEQO)8LAZ!-T3aFln&k?*cK4l>IP;scc1VCrV zgVPQuG_m`UAF8FI;zNf(#`_rvK2!o~mhc9`?h^8V>Zy3UL)hZY2?QT14mC@xfv{Pk z5>P!AuU?38y!?USL&c$HNd^!$OZ){?PsIxfi5t%~5PYaO)GQeV!e&W<chQ0LJ@t@Y z@gxGl2Z@2Y5s<c<+y}yD$#y{XR6MGXt9aOf;6ufs?otG;PaqJF3ZNboSlj&-iXQiN zAoyTGcwSSPK-gW%@Jw~*hKj`P7YIJ8S?URd%~FMD#akR|FK$X8_^4)S84xy0175;i zx6s^i%>%(lHA|O)uvyxm>JF^!N`_9y<q8BJEC>%TeNelVK-lZSJAD^t=to>wf#9Q> zWwd~>yA0t)?zt028fR}H_^4)?5>bAcz{{)CKTLj{=0NaK&9We({4#@=Une!pPn@to z@KMdOCZhbZgqL5(BCKW{%|P%`&9Wt;{IY>+si-*IVViMi27(WjfaW0wBFZm&c=>f; zhl9ob69_)4S<Xb1UrzAyYwrtZjy*pRd{ndCh$z2Y;N{nD3D+CDG!T4Lvpk6?zue*F z*A5Sl726{ad{nc%i73Ck;N{oW3h#<79SA<ES$;&6U%v42YtsrpkBvJJd{nani73AU z;N{o)8-Wt*ULg3WW`z(@eg(nHueBV(FV;vP_^4)u6H$JJ!ppB!7GXP9dLa0yW<?QE zenr5`ujLt$9m^^Zd{na#?Htft2&nxCYVm;DQ6LOzMS(|0*g3#Wbhu}shCnH39zwKp z@S4SW<EsVNiEr>ofEog&pk^W3Ie5+DS@9`@cgAOU;(!_grJ!aZ+Bta5;;(o=Lm=Y= zJkdf8fl^Sj5bYeiW(j$`IU#KE7M_`)hCnH(S%`KHUb93cUj7i{cm>boP(z>;)GS0h z2d`P;FP>{i+;{;me4vIvDX3Y9b`D;%q;@=skY4c=UMNBhfl^Sj5bYeiX32Iu?2xN? z1l5a9LCr$6bMTs_5OHsZqQ`xBC4y=i)GS0h2d`Pm8n<7lNZf%}ZdlDiv~%#9rTXKh zgxZT+@Jbh}S%`KHUb8e#T=US}aUI?mz-ktvorBjb?HQLVbULoU8!1@LLbP-6nx&U< zVTFFgMR?(Z)ht9i2d`O%7H4l5X`F)>idfA;v~%#9Wx{cq!{o<l{N)#-orBjbvl}NY z%uk%eUw$FlIe5*oTyZqRYQ{1A<rkuzgV!vZibFGOGY;b~zYy&lyk^;Z>_6dPaR7h$ zg=pvCHOon2&ktvgz4*&7L^}tsSuQVjX}I3ljlcXtv~%#9<-TKkgvW{<_{%RuI|r{> zUL9LHyeqb%CQ&#KTIL|yIe5+Tjo7%u&tnt*@(a<<!E084#<~}Q66^7oUx;=NUbBLJ ztdR(Qu@-;%g=pvCH7oSQN{_G|tMHd!h;|NMvm$0JtBCAaj=%guv~$qMIzTH;AagE= z@tleu4eSl@=z}ugV_S%J4sNrM#&5oE;0k~m0jJ<*A=){(%|aT#`SgGnX-X1e9Na8K zI|sK}NaHsj1o$DNxDaE&B-|`SI|sK}NaHte9fTlPUxH165OA{)?Ht@@A&uX>DiECj zF#$os%|f(uaGQlRe)D{RL;}JT2n%i&qMd`=ETr+9Cl{m*ASNJ4xLJsH4sNrM#%~@m z$T1*Hfw16aA=){(%|aT#xo@C=e5?c5Ft}NWb`EZ{kj8KBBq%Qc8-PT>%|f(uaGQlR zesgnzS^<(VU?$uwL^}t!SxDnI*A8epfDJ$*;ASD(Ik?S28o#;xK}P_|7%&rV7NVVl z+bpE<n~Ms1pv5m>GhhVVEJQm8w^>NzH|GKjH^9t*(Qva6?Ht@@A&uXhZZN@Jej(a9 zxXnTuzd5nN9C!JJXy@QI3u*l3=mRU<<rkuzgWD{m@teZ}Hn__#L^}t!SxDnI2OR8i zmtTl>4sNrM#&7l(IN>h85bYe?W+9E=>{{T8yZl15b8wr5G=8)Ff(P#M3(?NOZ5Gn_ z%~l3)+~pUdorBvfr16_g2EMq<FGM>Bw^>NzH|rAuaF<_*b`EZ{kj8J;ObEtZej(a9 zxXnTuzgc-840rj3Xy@QI3u*jj*@sBn<rkuz1DYKJjpu;O1dZi@Fnm0xg1zAfMgajW zbl_zUqMd`^EUtjB7zG!)S%`KHezSNLK4BE7=w>0>Irz=u|L_4LpwP`iv~%#AC3N5| zMg*dpg=pvCH%oNFD~yDNZWf}QgWoKPgy$Fu9^EWNI|sj6(gsg3G9tQJh;|Nsv*Z{a zVH6PPW+B=+_{~zda37=KLN^Q1&cSb%@`5`U1uD8(h;|Nsv(yT1Vife~W+B=+_|4LE zxQ0;yp__$h=ioO>N8mC>#fWYeqMd`^EWHO8F)D0yvk>hZ{AL+$IET@YKsO7~&cSb% zNyBM^<rkuzgWoLkfD;7EFGM>BzgboaM+uf+h;|Nsvur*bCRlzU+Bx{mvOjQuVEKh; z=ioQXX~JHD<rkuzgWoLIgk1#7FGM>BzgZpz+X<Fmh;|Nsv%DF$5-h(E?Hv4O`CiyW zu>3-_bMTuLuwXsG@(a<<!EaV@!5V_)7owem->fi)l?2N#L^}t+S&;(E2$Wxp85{+O z`yn_AzE1$HTZ62LV$9%nK*(`Bd^vzD$0vZ0;}iG@KGOiEPv8MUPT;|N@V+dVobU#O zobZM>0mx>GH6Y}~8eTRa%Si?x<Rk;0Z9tZjQ9#JaC_H|EEGPE?At(3Yp#ZX+;sJ!5 z;(>b($Z{$Z5OOLLZWkcSsV5-h)DvzjK$g=oK*(tsT)luSr^|ql(`C5KfGnqf0U@V< z;er9OoY4Y=oY8`_3CMD$NbzS{a0(^<ERf>Q!r?ed{8=N#pS8ddl=!nnia*;2hfw0r z0V)0*Hta`<KWC))b8gs!5`S(;@#hw>6D9sUk>bx&VH-;Pc_YQ2_lGSg@#lvWe|`rx zqQqYyQv3x@ScejSAxQBTlCT;j{=$*sFWg`Sa{N7D1+6Pl2CWzdt?>lyQHIf=d<g0n zz-dv?>R9j!T{r`@dJtMm!zs`jCdLQgzJ@V2b8(svUQY<J5oSD!U0@D2`(PGB>;?Br zoblO9(0;7$09%jjFt7kV_n^89+{Xzf#$80a52ri9PD6JqSdbX^qPiR0pGqdh-6Xpo zuRp-f#^x8W1S$SO^%uBrS4@t-$o3yWe}cV)%dcQba{P<xZ*V`fnG%0f?0=%d0qk9T zVF6Y^NqC@!3%E}`nHu3jweTT2oWMarD6GJWs1aVM;RYT*SWL}uqk8y}6pr9vA|@=s z3aJ^MsNo78OW90|aHU!Jk{r(9AS5=d!HQ`S-l*XY9(OuS%W$W8_>&b6;NT@CF2EXS z86T+e0v^M=Opkb>Tl|n6PvD>@HLk##=n-G2@dh3*eN4}IqkH^O6p!F&Atx@u8tECI zsPPIOyZ$^7@j77fOL07dqm10R25TOO_(qL)&^!Yp^FYS?fX6>o(g8R+DM<@p0|qiZ zpr#AZoDrk&U`Q8(CVfyXoq(g7(zF6LWH6)`)N})yA7sQj{s@c5fuiB#p0IcvXc|8L z3W`cfFle_rWHUU4B={OuSbPo^8Zr(Hnk#0+JN`US=?Z4=pi5t{^i8#N21=t;OKV`m z22=Tkp57tp4z#X-k*N6xSUMOedeEjnnxsQ;@}Wi@3Ni?W2W9z(Jzav<s4$W=|1?nP z5@zq9PoFePr=a9T)p8SLAP5hM^a@MAkn$9?9*U8y`A1kf8Yp_mq+gn*V{o#gcDV~O z6oiLVdPYsxptX676wN;mRJw-QJLJ+g&C@wJNzy8<gAE_d?O#~>#zjNQbI>|cMyjko zfThEMqT%TYmac{xP1SxLD0!k|nzUh%Eg6#KKYIRv<O|T6Xhy28KN+Ze0ke0==MPwZ zrg=UAC25-H6|f~kx&FYOZ$Rt+8ELZq2$qfqiXJxkhpzbuoXlz21_N0D!^5Kf!Je-` zdtn%9y8djS@)gY9VVA$?p3gwpfG+hG$RZFPmiY~q{~+x^(7rK7x~xBh<%5Buhi(2F zkbDTv9`vgBK$d~<u+ERD`4Y4Tlaa3LPX{Vr!t5RP`E$VXDLCuUJFkK*9Zvl}SpLLC zL+Vq|erLu3S$_=6M*~HVnEX4S`52t71|lzmEgnhv8J5o>`5JWg0ONqJKOd-k4YPN| z<?jK{=in?iP<b6}`AE#~$oU?8pVS2gVbHBrpc_NM_tJoFwglb5Cd!z>6al*6>F){< z3A)1#bW0NWVo%UrL6AG9q+xnd^@HyE1Ko)PHUn-9+$6{aT3{nV<qtyz*9oQz49du6 zVVZ|-CbF?eCd17JF(7A(FjVl)V7kDdjcz`6JFwV;W)+HUAZtJY1ICcMuox-?GMFwf z7-O>!x1HGS#k3mDb`<+T9GIVlEtoDaSmSa7es|z>3s&b~xCrD7aCpE7Sh$FBFkN79 z#^)x&?!xCbT+YMdLJT*81Ylt&af9gsgEt{}66aO|?#1I|tgZ$*6Bev+8Wz6NE0``Y z1QX+K;@wWz{rJ6r!xvcn0TP78fm{XC1%_y1{X&|5i1HIbZ{hSA$Q$suL1w_>NzsGp z0z)z>ek0v~#QKpKZ{qPOPQQXAU~#D;!E}Kkn^gaj=Vuc9O{CZH`X1y><S0gA!{S@* z1=9tFVsiXXei)Dz4#WoqfzZGk9w13rn$X<Abb+Co+%TamTu2TZl7fd|2!VnDC7qyi zVChDugXsc8GbLd}c{q_1R-^_O5g|q}%s>iYX-hwX=>kJHrQt@Mup=}4$OuBBLJ<^9 z=*bO(4@-YW8cY`$CQ~CEsTY>yhbMVKN@S=K6|Nvfurz7{x}$eCwZfLV;Y(2%lO4=N zhcqY{G14qH0a!XV2lX!(Q!}ioAKsLPIVHhPLdX*x_8^6@v~C6Jf3K!?_|qm1s1Oen zMg>W+0SabpNgt~iEI-(S#wRw@B0gvrC)9}-%A<zF*dZx?K#E~`#sM^bvzu0NMB8|x zT3k^jx=4;OP&8o8Kez;8`N|nIzIB+EaYp-iqh{PuEBeTYL6YMTqyd)qTtVZ1r)eFJ z^odI<$0rq|l&n|<MH8-Uh*KPvKRrO>qnGIsuk?#s>c=m2qnONCCM%vnnqYa@8#I1= zn_h8E-}t6UoKrp8$&PtYG~&$5_#|NY+z&Lq{+OO|PyhI*RT`j0GN2$OkewDl8ewHY zAZY&KHNDfrz@!NprVAP+4T@3+D4OvV33%mT<wY=Pe&+K)q>q71BeYE?v`Z=!rWT6Q z3rI7pObG+cU;Q4aG&8X2hURI9rpbrm6a-2Jc*_++lHgTTd<^TrtDiu(K$<e-K-r88 zoDAEbY$gVFh6_+OGlMFl3Y5*lz{wZ~WwSDHGd4ikYz&-?3mBLg7+E+O7#Ok`7@%xM z1|fz;P&N|-AHxACo0-9j;Rck=!XU)x1!c1`h%shB*=!6#j6DpV3@Hpn45<vM48;rz z3?2-L48;t^42cYR3_1)73>ge13?&Q&48;sq4EhZE4CxG+3?&R145bW740;U74EYSX z4EiW$crxTMBs1tU_%h@(<T2zkBr_B-Br>EilrS)OrWB>77Atrp78fVx=_q8BloS+O z>FcLwmSmJB=_Tjq>O)j`<|XU<=I7-n7bT{ZFkmwYNj8Wfl_8y>lp%*9k)eozAt*Jy zG$*l$fx!)Ie+if_Vn}C5Wl&%+V$fqSU{GMNVo<<hDn#6n!GJ-R!Hhwd!HB_t!3eb0 z%Pl{z#4W!lJypR-&p^RS0dBj3m4cyxu9>cpfsrvGcZM;fG88csGh~9@rNCeeb_+vT zYEf}!ex8D{o&g~fm_W&if#Lr`1|tXym1JuHmtRZ_%#2Ko%#19Itc;*k!_LUT$jQLV z$i=|VAiyBVAjBZdAi^NZAjTlhAi*HXAjKffAj2TbAjcrjpunKWpv0ie$j!*Z$jivb z$j>OiD99+pD9k9rD9R|tD9$LsD9I?rD9tFtD9b3vD9@<CsK}_qsLZIssLEi^sK%(y z;KZoGsL80ssLiOusLQCwsLyD?Xvk>9Xv}EBXv%2DXwGQCXvt{BXw7KDXv=8FXwT@t z=*Z~A=*;NC=*sBE=+5ZD=*j5C=*{TE=*#HG=+79y7|0mJ7|a;LaEmdNF^n;sF@iCY zF^VyoF^1tDV=QAFV?1L5V<KY`V=`k3V=7}BV>)97V<ux3V>V+BV=iMJV?JX6V<BS^ zV=-e1V<}@9V>x35V<lr1V>M$9V=ZGHV?AR7V<Te|V>4q5V=H4DV>@F9V<%%5V>e?D zV=rSLV?W~r#)*uR7$-AMVVuf1jd42T491y^vlwSH&S9L(IFE5Y;{wKojEfi-GcI9V z%D9YiIpYe(m5i$xS2M0*T+6tQaXsS(#*K`d7&kL+Vcg2Njd45U4#u5~yBK#f?qS@^ zxQ}r^;{nEljE5KxGag|)%6N?NIO7S%lZ>YrPcxojJj-~F@jT-N#*2)X7%wwkVZ6$C zjqy6;4aS>{w-|3T-eJ7Uc#rWu;{(QrjE@)}Gd^K_%J_`&IpYh)myE9%Uo*a8e9QQb z@jc@Q#*d7j7(X+9Vf@PYjqy9<55}L2zZicr{$c#f_>b{F69W??6B83N6AKe76B`pd z69*F~6BiRV6Au$F6CV>llK_(-lMs_IlL(V2lNggYlLV6_lN6IQlMItAlN^&glLC_> zlM<6MlM0h6lNysclLnI}lNOUUlMa(ElOB^klL3<<lM$0KlL?b4lNpmalLeC{lNFOS zlMRzClO2;ilLM0@lM|COlM9n8lN*yelLwP0lNXaWlMj<GlOK~mQvg#SQxH=yQwUQi zQy5b?Qv_2aQxsD)Qw&oqQyfz~Qvy>WQxa1$QwmcmQyNn`QwCEeQx;P;Qw~!uQyx=3 zQvp*UQxQ`!QwdWkQyEh^Qw38cQx#J+Qw>usQyo)1Qv*{YQxj7&QwvioQyWt|QwLKg zQx{V=Qx8)wQy)`5(*&l8Op}-<GfiQd$~28>I@1iMnM|{oW;4xUn#(kgX+F~eriDz4 zm=-fFVOq+xjA=R33Z|7ztC&_ZtzlZrw2o;#(*~xEOq-ZCGi_no%CwDXJJSxPolLu! zb~Ei^+RL<$X+P5erh`m}m<}@?VLHlmjOjSj38s@wr<hJNonbo5bdKpf(*>rBOqZB0 zGhJc2%5;tCI@1lNn@qQuZZq9sy32Hr=|0l~riV<Am>x4dVS38+jOjVk3#OM$ub5sl zy<vLG^p5F0(+8%HOrMxOGkszD%JhxtJJS!QpG?1)elz`H`pfi>=|3|AGb1w-Gcz*_ zGb=M2GdnW}Gbb|_GdD92GcPkAGe5Hcvmmn&voNy=vnaC|vpBN^vm~<=vox~|vn;b5 zvpll`vm&z+vof;^vnsP1vpTZ|vnI0^vo^C1vo5n9vp%x{vmvt)voW&?vnjI~vpKT` zvn8_?vo*5~vn{h7vpur|vm>(;voo^`vn#V3vpcf~vnR6`vp2I3voEtBvp;hHb0BjN zb1-uVb0~8db2xJZb0l*Vb2M`db1ZWlb3Ahbb0TvRb24)Zb1HKhb2@Vdb0%{Zb2f7h zb1ripb3Stcb0KpPb1`!Xb18Efb2)Pbb0u>Xb2W1fb1icnb3Jndb0c#Tb2D=bb1QQj zb31bfb0>2bb2oDjb1!orb3gM0=84Rcm?tw&VV=r7jd?or4Ca~4vzTWy&taa+Jdb%k z^8)6D%!`;8GcRFY%DjwuIr9qUmCUP{S2M3+Udz0Wc|G$6=8epom^U+TVcyETjd?rs z4(6TAyO?(~?_u7{ypMT5^8x0A%!il{Gaq3-%6yFZIP(eSlgy`>PcxrkKFfTL`8@Ll z=8Mdim@hM5VZO?IjrltB4d$E7x0r7;-(kMXe2@7)^8@CG%#WBKGe2Q|%KVJ^Ir9tV zm&~u2Uo*d9e#`uh`91Ro=8w#um_IXrVgAbejrlwC59XiDznFhB|6%^i{EzuR3j+%y z3lj@73kwS?3mXeN3kM4)3l|GF3l9q~3m*$VivWutix7)2iwKJ-ix`VIiv)`#ixi7A ziwuh_iyVtQivo)xixP`6iwcV>iyDhMiw27(ix!JEiw=t}iyn(Uivf!vixG=4iwTP< ziy4bKiv^1%ixrDCiw%n{iyezSivx=zixZ18iwlb@iyMnOiwBD*ix-PGiw}!0iyw<W zO8`qCOAt#iO9)FSOBhQyO9V?KOB72qOAJdaOB_o)O9D$GOA<>mOA1RWOBzc$O9o3O zOBPEuOAbpeOCC!;O94wEOA$*kO9@LUOBqW!O9e|MOBG8sOASjcOC3u+O9M+IOA|{o zOAAXYOB+i&O9x9QOBYKwOAkvgOCL)=%LJB*ER$F!vrJ)`$}){*I?D`}nJlwdX0yy; znaeVdWj@OSmW3>fSQfJ^VOh$ujAc2?3YL{Dt5{aEtYKNpvW{gv%LbN>ESp$1vut76 z%Ce1RJIfB1oh-XpcC+kZ*~_wzWk1USmV+#ZSPrusVL8fjjO94X36_&Ar&vz2oMAc3 za*pLZ%LSH;ESFd=vs_`h%5sh6I?D}~n=H3jZnNBBxyy2o<vz;;mWM2lSRS)HVR_2( zjO97Y3znBGuUKBQykU9E@{Z*_%LkT^ET33DvwUIs%JPlnJIfE2pDe#vezW{x`OET; z<v%L}D<dltD>Ew#D=RA-D?2L(D<>-#D>o|-D=#Y_D?h6Mt01cot1znwt0=1&t2nC! zt0b!wt2C<&t1PP=t30a$t0F@as}e&yt1_z!t17D+t2(O&t0t=!t2V0+t1hb^t3Im% zt0Aiqt1+tyt0}7)t2wI$t0k)yt2L_)t1YV?t39g&t0Suut23($t1GJ;t2?U)t0$`$ zt2e6;t1qh`t3PW1YanY7YcOjFYba|NYdC8JYb0wFYcy*NYb<LVYdmWLYa(kBYcgvJ zYbt9RYdUKNYbI+JYc^{RYc6XZYd&iMYawe9YcXpHYbk3PYdLELYb9$HYc*>PYb|RX zYdvcNYa?qDYcp#LYb$FTYddQPYbR?LYd32TYcFdbYd`A*)`_f>SSPbiVV%l4jdeQf z4Az;fvsh=d&S9O)I*)Ze>jKt=tczF|GfZM#!n%}o8S8R}Ijk#KSF)~RUCp|NbuH^U z*7d9#SU0k6V%^NTg>@_IHrDN|J6LzJ?qc1|x`%Zy>ps@~tOr;RvL0eR%zA|NDC;rS z<E$rGPqLn3J<WQC^(^Z-*7K|vSTC|(V!h0Ih4m`yHP-8_H&}17-eSGYdWZEc>pj-{ ztPfZpvOZ#c%=(1&DeE)V=d3SSU$VYpea-rY^)2f=*7vL*SU<9UV*Skeh4m}zH`ed0 zKUjaV{$l;j`iJ!|>p#~2Yz%CSY)ov-Y%FZ7Y;0`oY#eNyY+P*IY&>kdY<z6|Yyxb8 zY(i|pY$9x;Y+`KUY!YmeY*K8}Y%*-JY;tV!Yzl0OY)Wj(Y$|N3Y-()kY#MBuY+7vE zY&vYZY<g_^YzAzGY({LxY$j}`Y-VicY!+;mY*uX6Y&LARY<6t+Yz}OWY))*>Y%XlB zY;J7sY#wZ$Y+h{MY(8whY<_J1YyoV6Y(Z?nY$0r+Y+-ESY!PgcY*B2{Y%y%HY;kPy zYzb_MY)Nd%Y$<H1Y-w!iY#D5sY*}pCY&mSXY<X<?Yz1tEY(;FvY$a@^Y-McaY!z&k zY*lR4Y&C4PY;|n)Yz=IUY)x#<Y%Of9Y;A1qY#nT!Y+Y>KY&~qfY<+C~Y!lcfvQ1)} z%r=E>D%&)+>1;FDX0pv<o6R<dZ7$n9w)t!e*cP%aVq46%gl#F?GPdPxE7(@Dtzuiv zwuWsj+d8)OY#Z1%vTb79%(jJXE88}<?QA>PcCzha+s(FzZ7<tCw*71e*bcHCVmr)s zgzYHXF}CAuC)iH1onkx9c82XN+c~!LY!}!rvRz`k%yxzCD%&-->ufjJZnE8CyUlio z?JnCrw)<=k*dDSyVtdT?gzYKYGq&e!FW6qPy<&UK_J-{(+dH=RY#-P@vVCIv%=U%t zE891=?`%KVezN^y`_1-;?JwIuw*Tx5?2PP8?9A*e?5yl;?Ck6u?40ae?A+`;?7ZxJ z?ELHk?1Jn<?859K?4s;q?BeVa?2_zK?9%Kq?6T}~?DFgi?27D4?8@va?5gZ)?CR_q z?3(Oa?Aq))?7HlF?E35m?1t<{?8fXS?56By?B?ti?3V0S?AGiy?6&N7?Dp&q?2hbC z?9S{i?5^x??C$Iy?4Imi?B47??7r-N?EdTl?1Ah-?7{3I?4j&o?BVPY?2+tI?9uEo z?6K@|?D6ag?1}720;v_rIf=Q6C7Jno@wtgb*?fhi`6UQ0cV203Qfg6rab|iRcS?Rv zP9lWOQ;=GeoSIhxmf$JQ%uCNnjR$E>705|VD~T^iEK1EQ$w)2EEEX)vOwT|O;Vj50 zEe7ip%SkNB%!^M>EXXWL%!$uQEh$MYiciEYoP=FC8M|-_cHva)!fDur)3FO@U>DBB zE}Vs3I2*fg4tC*O?8152h4Zls7ho4I#4cQfUAP##a0zzdQtZNI*oDin3s+zluEZ`} zB@9l2#f7DbMXB*gMTyDTsU;$iRER3bomiZlnHis)Sd?1AlU|fqmKvX!3`*7_kaSs` zo0x-0mDmK6un8t(6HLJ-n2Jp>4Vz#(Ho**Rf|=L^v#<$fV-w85CYXy&Fb|txJ~qJu zY=VW@1dFf<7Go1E!6sOWO|T4`U^zCy3T%Rv*aWK}#awb}QBEZ|iKX(Cr52TBCMV{^ zCnXj^%RD4$Xi_W5%t=Y*%gfhIDoRbvjxR1qOiq=|%me97O^HV@j5$GR5nNDm737!Z zrGS~d$)!a_sd>qjU>-+hY95%ul~k0Uotg)-ou@c88C;-)N^Q=R%*50pP(jR>oL^80 z%?6q2c~WVqxtV#Hd8zUFMJbtii8=9^c`2F6i6!|(n&1pnke``Xl9`ttpORmil#?2t z2ruLj^#ey<KBNxdFG@|%EG|hcN`<(RJ0&%}C^Z%AG=6Y-pPQKnE%o_}OAAtqij#{n z3rgZk%JT(L_!&j1sXU3vr6sV;$d#L!T$B$siKielC%GuU9L(X$%}hzjNsUj*FF`Re zKQC1}H?cUmGzY8av>-u1jPIn&N^{Z^i{jIY5+MPap9iYt5{pVwizKkgWhCaL$)QV> zfP54WDve4~i;BhIv0Yf2S`3aRP`#@NDRIzi!uaycl8kt8(S%n8IK0&GnUS1Xlw6vd zmXlh6*C22LRmEozJU!vHt_YNH5|i@FQpK?wma2?ZJQ?ES<kXbRoSa1LPECcV!4oP_ z6?j4gssa%z*!>Ju2KO^|2W1j;5L5*o2SHU3au8G*+(8mpLou}^1G`J}AT9;RGIkaD z5EXa=7pek}U!W=we!*)M*fH3HA8HWXx5BxlIVG6|IiO++)M5n{a7tK10IIXN1XL<w zx4x91PoXOC_!O!F;ZyAXfGUIg1G|GNAr1mtCxz8lB^miec~B{o#z}ETVo^bSu{=Z< zic})RRB(jikq6tVf?Geri+BtHM<q04V{-&N0Pt9ZC^<y2xh54Fb|}W9mKxX`2+hbi zLjfv}GZdimh)}@hOQ<5aFR?iUnt^dT1S*fyAy9ez4uL9yI|SNLMhUajk_>F_LoOk( z$wM<1PWMCQak?KWk8nR8OK>J9s3CCw@up;!Wr8LL!3_fiEa?WS15zGfvl5y`arz4? zkJDdJd4#{PB@n10xVy1A1i2J|mhLF=1}+1z84lG5HynGx2rUkB6O)Vb^RR^!iUMe6 z!`>`ODoQO&#pVU55ny?|uE<Z%&r8k5;|hoZ?5==jdT@+ja|N<I_O=RC1tQL{6-yY3 zuov-AWhwb3@!)0;wirTJgV$fliADK&c>D#H$8JIjq{s)Wz-9unJofm3mSnh735o*j zu7D~5rvhxQK$gcIrcf1l!xUW&UjIOn6SnjQH3p&puYYicD%1$DJofaK4viOhQyg1* z!%&3XHBe<ZLl;>dd+0({;0;|IYS799s4CP(J4&I2sselHWDpZN7>clm4zvOUS0LEZ z9<n_46a!U(I|raB!0QT}aRfC2ERQ{opeo>TBnhe7;NhQ{o>)>^lp3Fz1?^@*LmeTG zJ*=~c32O{R&@v5fJ7l;v8)_CxmksI;Y$~udMzV`=^!0KehT|;ck>#;F52^xB;>4-~ z&66-SxC&)tdF%-asshpi!BzyJD8Qbepp7$}p@A%qJv5*y@Pr0d6=<OWQ-doskma$5 z2DCkfJA0uhz#bY<CE)CXEt4b5YoKKuNWz4wfDLeg2A!b!1ttArQHCoc=EKH2pa#G) zVm_?jf)<iR1kyLMJoZq4ssL9z*g^qW9=i#}1l)iu4-FnPUqDshZ%AP%!k$85%5WDa zSXJO~5v~*pGXo@#Jyc2{p@K79k>#<Q0B!B#tb~x|vF8$~3f#E_MFCz{;LIgZBf#?5 zV;8Cd(J{x?Y{5{3J;y<n5z2A6m7&FRIW(5=HmNWaVfQDr1BE{oV<^I2aYL2CJ7d`6 zrV8SEoaH&PJa&7aD&P$SXr6+WK9EulT@7Bh;7spOQ^4}j(htR!ocz4>_+n_qh89an z5PxRm=V!}eEr?4%BkRSP719t{6ob*^(2UM6NX?7SmxJg-lS@o1%1lnoi%)@;i)hlI z?rTvoXx;@nq=qJ6oSadf2z3#f6xh~O?4C`-@GOdVpw)a*Vi7b(QDqZzlTx7lXGl{4 znvYOaLF-p=kVB?3a#GWw3ejB(aSe2?1Y8#3iGq^ye5i*}>;p$ZNqIhWJOa&%)Zz?i z_(Lb~5dmAA5ucNvUw}QJ${<byr3xGdSK%1OPOZv_hgkxRTNL*q%gaEL2GnUK<<QC; z61Y%zqj?DI-L%ZIRH$AQv*D6@C<eo)b<%V4OF)Ymic9hfARdHRC5WQDyfQBjnv0+= zOG(WGX-m$@OwNX;N2p9rVo7RIVop3*3K~67sl=SJ)O^sQ46q#3xlp;H)RLln(1Z^} zBev1hoGk2R0W<-E^E$ThMV7~I0<`0T(*$IB>?T0t38x9j^4Lv)Rw6h}K$eFFD{4%a z7Uh9T2WXj!mPitz{e4K~40QpDeyl3cOo4TbLG2K1A&o2#wFAurSoaH;3CQx;eFDlY z;CV)HNI`8u@d>I5Z0>~h6+y0mnt<j`s84X#b;$D2oPlNnD9>Ow8(JRX9K1!A$KKL{ z#TD3j(BcXu2v8KLL-I13`(SO#{M_8c_@vaF{Bmq1Jf<q_roq~m_)Wu9g+1&l^V2g> zhX^2T1CTiOFolh@fMOI|j3diyVGR#xsH4_W&=MCVY+>V(rA0Z=phpW?Xxjr+Q()7N zBn=I5H2u)>3U4b3T@7}VprsC8lhD;*PjS!|BBc0$dK)EFP!wSEHnb%HT4jPw8XEk# zq+uziv?vF=1EB!|slBi(fevUxlwk7%iUMdVLW>)yFOm|Aw6Ufls5?_K6VvlSt5hJC zVNbKjbuZL5lpsZx$L=F&OBG@Xv>HZpa4Bew4URSxq{b-2ZZ@>SfS8Rfv``daHv?ME z;x+?C0rn7u1W6&JaRSOy@g<3wIncTRA_;9mpsT^|Cg=zQZa1MQz-|UKvEw!aMFF1L zIuY8GMDa&rPC-T@wggcEi7>D{wmbw)4xm7Sma8b{g1Z5*&IgJNG~wgQe9#gP6z<rp zg-V00g(fr<!(mO|_*8731$SGZp^TypEP;r1oE}QWrWtN0*w3jtki3dwKAIAQO`2E~ zC+FmYx?X5{pnVt=V^i`=a#D+n<55yJworq%AV8spErCE6oTa0-k|9>XvN%i<A_~m~ zMTxn^@t~C#*i40{AXpCwMI*F|1UU#=UZF~-<{>#5TY&&=B|~xrK6htAM>J5(hnB3! zT|aEW233}nnp1);_@UB>-UP@y*qRbKsZ|+xLMRtoDu9MwE+nmhTM9X;>DXKeRRXdc zTS*12?7#~bL29u11gZwrC-_1&51V(A5{p2K9P_aiC(uNlpPQNvTf~kMBLx|m*o=gR zLJ^)2f)=5$5P~*NPz;Be0trh{AYjeM5NVh}c$B1N7H5D=fmR|YcEPhP)Lk&O_(Bsl z-T}>35c6Oe58iz)GQ?6?U@ZdT6Z2ByK@P+g7@&pTCGatV_|)PIZ22p-7@9>v<usm{ z!J09k4HMMlgsngZHyEI835c(uK~P#yoSBoKhb_4yjg8=OR~a6;ay)XC_~NM&n|q*5 zY*091o4-q~!XCa=NZ|{uZ=ilhZi+!OD^#W+BeAG5FFiFeC%!B{GdVRS9z2X!l350; zn4k*bX$ILWXaqo&6qgjGmLzASro<;hg99p&l$n#5lnEPD!517!*b)vbqk{$?Q=w%q z)MQ8u!_qZU0gum;45%3p%}|q|6<%^tele)31T_|*o<LCs&G*^(%+J9Vr%0_kXcmH6 zj2xbj;sR0w=|Qq4R294oz@;1-a8Tv&5C?4?DlIMs4X@?qr(~vOrWV0={y@Ew4C?bL zqD$uFm&bz^%7Yi#gVuI)!h2!Dpta`N@hB^*1t4OHdHL}rsX3{ciBb>&Sj<431#bFD zVwFltEy1BFJux>Ihg3>xPD!E+R`XIJ*&VxORjDP364<rjaz#l-YDpq?(=zjMY06G4 zD8S+LoW$IeL~*Qc$SuV#o`*xcA`^QM<b&7p=V3RjAQO846lLUNkGtZ`^jsW)R+3nX z-38Dx7rRXb891Dfj7y@RI1{_uz-<7iEhyO)oZz4VfFc1(ZrC({6B{-Oa8iTXj$#rt zp<%NGl+45+QH-hup88OP!AT68IiLiF%}wCsg-rsSxJ0qooLh=bG!Lt21uU>p90^TS z*o-O2#OB$ejC?sPE=dFLf<aDHDAs@_uo+j9Sc)wcpeYTTj)DxV?n=fkTu=;4l_>53 zr!Z*tN0BHl0p$zT<jSJVoSe*L^zD_I&|wDfXsHxVRr%7mq*Ag{amuA<rK;f4SDIav zn3<QEm=~Xk+klj+R0CWFBvq#7<QIYJj>NopB-3zuqB0Yw6dph1;E~JAN|nLoyprM! z-2TeO6EM(j9ymheahYD6kzZ62Uy9TAl&XwWNnDx}afU-uDo&{~+`dWAz^yF>w-lau zufk(u6>g7Z5(qEc2_PGHn55?543pGc+){ZsgFhdqrUKl7m0E;TS86d%sS?~_Rf<zn zY8p<dj6|Gyy`&g-0!hY`6^b(wWpO3c;*8{sL`7V(8Hq)Z?S(jVL1k)DDNgOh`Du{d ziZ~+*cWhMR4!z1makzs~3gScw?BYqOI3&uDA`iu+^bA~DQgBIR;xelWr&(30I6RVx zh%XdpLCT~|9KOlM<^R+i96C~SaY^Lia9KVM4F$M@CAA2Lj?`it5+%4or4)yT)HECt z8HtF5hZ2q@#ke9X8M#nL(Nm0^Gtp#{GZGQyB8nV52O%;%iaaR);Lr-sJvgEQSBO{Q z3a83MW$gI_rG<hcEHm?Qgk?$=uCPqcN>##cAyQicsRTd?7*O@9hg~<WW(f|LSK`Vq zI31pYQzkD9mwQ2t5gZ|ujWZmO8zOkKd?^m2Q>t)R36+T@ICNDemf$SV(=tntDr%G{ z0ZAd!Dq6ojvnnIAq!_89LD348Rfk6?n(p)rXd@Xi@PTMcqnLuGN(+~1RWQ?1Qj3#Q z^HNfaG~h~648&BZ30H{b!ffdDEZj(hUr>z1P>0jRROt9PArmpwAu<)38;eVd62XVR zlq$fzf#NuX0z}rrX$JC0lnx>DkQL)hTg4d}xY8C#3Xy-IV?_mtIr+&M*@<d!+tC~g zk3aBgT0}<(#nZSHp_v7ZU$9At5JoWxSqUOVVK)c95*6WiY-YigA(A|rd9cD6>@Wfa zI9Ls$AVD(;JRgZ@U7|P#EQg3?Y&s!P40kXh_hA}@Qz@Fc@Th^CiU?K|Q!y3d%vM#< zk_2ufj*N<-4tESdyaQP|f-44))gU~9=3i)e4|f`lw1KV+r+KiIFR&v=aF~a#3{g6u zxeqqiCI`=OD6s&O)`v^u&<_a=xHom->aiM!rW&Vj(IXazZ_$<Ej92J-M7;5eq6VkS zpsL^=#^Ew_W!ms?K?_HiLg+y-pnWok^o|mSSX3f1CYq_q@M;m3UJxEaF%(lFPM3n( zuW0dy!=+eM;%rQ0=jUd|r=&_J7Uiab2e8n5l31C9Q!Xhr52svuX08-2GgA_AYD-Pd zz^Sb&5vNotZe6J*ICYie<8((=2JRrq%*&L)<+Ys5a@=83fybH2xWgnnH4mp3GV*as zWhLTtWqL+p3Qo!7jMNOA;gXBTEtQ!#wdLiP<CH7Tz#Xq;xML_e19ylOq-NmsURDO4 zSSZ46W-*>nDN8NKX<rGx6j6l7Ey?*f&8*BU&%-HMkXc@YGqAJqSeTDH+S5`q)Zs}U zWA+ksEF$Q9sCdvmDq*;~#DaWKAEO{6RSYhcnp=>OSe#i5K9NxpA&h=jBU}bNVT#a? zG7pMK`iV)P_E;w3^ezRs0Vu^SbQU(TG6`WfiUQm+NvU}_^rUCzN?^AxB@u^~)Z`2t zTB;IpNTlM@ky?U7M@c>o+d;$W*d3gimx%~elz;&hY&eXo!0EJPT>j5a&BNj7jC>pt zSxBV>ipxNS84gE-iZUFI&c*41%1j(u^76}Z$P{PbinTIaagdyWD{KmovnYyBK}8pi z&?&-YT5)Oy4o8=zmg5LEP?3d0QxWdCMyiQWTn#F$a99K?s&H78jnkrhTpmhG&A`a^ zuuaOT$r<q=hp1pr_m$9o0I0mmPUVLy%BU>JNX-+1^HYivbHNAkNMxiY6{VKP7nJ5D zmz2WFox;R487vaT`DyV5iN&Rba#$quO7r3~64OevGZKZM($GG6VoqwBAgWMOYKbta zNP1>&Y7UxMN@7lGi2$m)j8rtE$`Z@av{fZmX6B)(%1A9i6Dh$EsmxCiN3{$x-JG3> z?)>b;G&DPN5_40r>&{KhMYB0KH5aQrd8O#C&MVCmL3L4aVs2`726_NjX6A{Zs)M+^ zAQdh23Q{GpsVgZ?Ovyy^5m*e(<%RiaXjT`c7NfhSI0GZ}OA^bJVD`dNa%E;pN@j5e z?C8p}#4>qYO3D(;;w$r02pLhCp91q8a&k@wovoRHEj_2F78PeCR%Yh%=Vj-|r(~vQ zmc*xmM#H4iQ}c_`LDS&qy@)(%TvADixaHFE$fe}x;j}Ilw~=L;xaF$w=qpLYZ5<vX zv+?*KC$Si3sN~|&mzP+C)93lPeOHiJB!epwsxlIbaJr=^F%_p=F&=l8;BjYZ9!|G_ z7D?ii%+A2$i}VaUt|`Q$5tQ|CTA7@ICw`Oh*qD`>gEQQcGjs4*h$k{C5^;xI7C!%H zB&Om_H5s@gI3p9cwsJh$@OU93AGeW}xYKW9YMu~0{lcoqJYjU9q(n@ybSz>i`IyF~ zVrnhR#1yN-qOK$n(>N?zv$41&C$SjA7r9u}<s}wj1VBEf>k1N!M9>2Tl)o|TC`wGl z5G%%FZwVHAOY<=70OeZ@K~R3h5Cr8@44VtFI2)8NF?56SBZlr|Ebh+A%)wNbnS;f^ z#3BrZ6^WQW1m!Obg&B#d7_pLp8L%0dn99nrD8u5EjC@S3X_*+7R_2MKM|)~cW?Cj9 z*F!T6v=fXiQzT|0l`aK|MTzM}i3J()#i<~6Nq&(Gdfy*zV;&ZVC#L2}!WBR*htJX@ zibkjmbk#cO;9I%m#Jt25P&=ZyG6y7{TnswOz6i9Qx+EhJpL8~81rBcAS*6lNrFogj zuw~h4sTrm5X{q@c@oA~?X<{gHrA4Jx@ufxarTi$ul|_80d{l0^B8qHDMrl!Iabi_G zh*2C5KH^dUMMY{!h6sv4VqS4+ReYi#ieP?md_Jm3Vluj##MI(sITT&sy)a2diFwHx z@%hEY@%geS(vU?iCFPmv5Lr~8<fHmKKNXFihiX_+VrEKyd{JUbd{Js<N_>$JidET( zrFn^{9#2lq6UI;zpN*<0H7{KPMNxWcQht1TWm;)`I;zU_#3D%)mF1;*S^4pxt@ZKc zq9`&MiRn3sRq<%yo{^ZEo)e#e8h^+kn30$cx-}s~0mU$+K!hnkjfA|!(v-}q_`J%L zcn~u_4^<jTKSUbUttt5>C8;U#c~U5rf|FEcaeQWRaeO9fw56h^rmWPW#Ju<{w6IDo zLUjbPHxrBE6H{eStV41mNEX$FndOO9@u~S4s9FkAi%K%`;|o&ri%K%$3s565F(*9} zq$ek%0@bYI{PN74{P<!ORO>U-Q*+{x-B_HT6JLy){*c@VmPHMfWK?bys$)yQekjQ- ziZ7`wiZ8)wFjyAVq!d*YrzWKqWhdq(=EWza<`*T$CuJpq`0+`osS3%ha22Ql0gd(o z)Eoldp;{o0Vq<CsIQ%o>Q&E$DZem_uVpV)@VqSc%Jc<tFfXq!yDT>cUO$<n`gGi%k zPb|$&tcuS`OfQYk$xkne&%x^S98{-g=B1Y>R-q=t%)E3|H>V_~CsxI$B&Mdvr=Z4A zeo01RPGVksYDq?FPJBM9IjM<7r~;Y!MX0$Txg4AhQA^O|#GGW*QYtw$F((;SQE^FP z9%`L|9DJ2UsQD5p=qk~Qqs-*goJ7z)6!GXaNFi#9s(|Jd=-op|eR8N>(4*p0kw>4P zX#%{X3RxT)35i8HiKXfB#g(~9`LO6JDa*`FOerlw6-`RbNe9(ZP*GH;WusOB#Tlsl ze6;!{ttc@s8&q`{XQ!6L=c8p<RM||tvZ)!Uc@kA`Vlrw9MUzb}PR6%`ED@h1UY#lU zbf)6j(Uyr%V-`M1ynEqt@#)ORCs_d9c?@lfK?ZPPgE-IzV-Y?BO7KaR;*%`HCs~e9 zvI<WKr$djPf%pXKEu_N-z*}rV`wpS|17UuJs)U}70N;iO4IUKJ(A8i!32G-^lhD;* zHwk+B8eWso)j&5vqxlZHbrZ521G<+H#cL=Eu)7Aj{S~ik(AD5K3AR)MTUf(Pf~kQX zI)LV{Y{>cu@JUD5HnAhiV>bc17ayky$nw~I166@HT+r2EHwm_AF(1#l>*#8*`wDtm z8%|##%VT#7R0UpNp{v1e5_DTVUX#$(U^fYR+!S7u(A8i!3A*1MuSw`?u!l5sb36Dj zLTo7zSsuFy&=Wl&JEkDJl2NiIvOHcBaK<*&1h72z@PMj-FS5dxBhl61Hwj-FhM5FY zgWaSGNZ!U9N9bzsn*=LMu=x&V5=;$tlb|Q};B^za8Z}6qqLo~*LkRF5_KKkho6BM8 z6y|blC)z?o9JE{ma-{<{MNo$$6hY52KuL|@wlI1ogKnnBtq}FVE9enxIF)B)rf0-M zW@e$S0kpt_UJ(R69|6T2@J3?n*#x?H5ocCKmd9=aG=y+wRb+X*Cg5}f)C90RG_ukB z4m|>=JT<2{Bfbo33rY~6s({w^Xr@5z0Uc<H?KlM_X%#HHi^2Q8A=wksq)>w>LbC)z znKDEfifci;uaS*Xg{VO@3SAY{LKKsro0O3a)4*yN7KOrj`FZi+iwr@Ry=8z`0kEg$ z#it||XRxQ{f@vx6i9FCw8t8&p*eZacY-z~Jwb<pLqM$P$EWsDcBJ@Fwgq|Rc)ky4e zP*H3~@<QcO64TRDi-a@si!!V7!N;+t=Hz4+6lWIm6{Hr$=Vs>Qq=HvAh=RB!sd=EG z%F<%cK{TKdS=NH0%-mESs9_LJNl|7&PHH@u!v{Yy1I!hLbCGo*M3J>>!U6=ej0}Ev zA+{?SwV)~?p^H~3Ur}mWD(EiBRPahOai}xUuc745%qvMPD#}kv%uDA;1YPo&S)3~g zUu1@^ToPFTt_pO?p+HGyQ9gM6EGV?%Q%ewjMZVaP2NXq6d$NV#fmEEDo0*)Slb@#m zI>Z+yUmTy9lbH@WrxkWKNKU0FXgyqNQ8MU!7o=+^3riDIib~<JA%J}CWL0WWz5=oU zqyj?8E14)d((+4-Pz5r}Qc*6VEY7SDL^iTGwJbFcMFhMa0L2i{g`A?un!tBwf`SW0 zBiL8s$m&uHOA~X7!HH7_Ssa}Ikgj8vMV5r75yWN9e8r_n&~ws2A;OE`=I5m%@k+|` z`4Mv98!nNwf`SH_n^}gew>Yx`NiR51koe#rLDCEg5MhK>@Zdnw0uBsOgc_uvkV1%} z2ZS_23L_YVQcH{S<54bJ<pL)?aQN~j7nN3}W<u{I6-)!=pbXF@p?S$*dCr{7qC^M_ zRAPWxTzQEwL5}i#$d#@9d8y^`#TluEsX1UZoGIWV)HBobIKlRVVx1#9vj8l~T~eA} zl$i}?3#O+QfkrF~QuFd4*T8ZXq!vT3NKG$IEK1DF1S{l8ECp?`f*8+}QB+x$mkD(l z=mrq58sVJGvZB=ZlKj%5y!=c^3gRs;NG;9<k1=Pa=W&&!=A}c*JwebNv59%{MWqGM z%UuOaN{g~VOKsqu7RUo#D4Pr}QouHF<tFAOLN;D=6@jmk1^J9KC$R|X%B0Ma<orxX zphy;jZ@Mi?O$M2gmmZ%CyS0|Tq$n{3Qc{796@ZSoz-qlTX{bPPVqS54acWU!8vN*s zbUbpEFoP0vLD$kI=A~f0_Z6H_OEM(UuXhEVT%VVjheM_$BeN()3SAGV00YYuV>K=< zGp!^8t0u5au?&WJ;45Y!l2}bF&a5cO!0;C6i1T=`R56BaAa8;5Vumbs+aQvdZUGw# zmBi2r4n)W@sElGU_`SM$rMam^pqq!|L6`TU+XpI%;vvDs56Z>miA5>J@rgx6`Q^N& z1xP#ra7IQF;7`df&qLxvZfypug6LNTvyoK9=a+$xqe?455>!S~1+62&wnJJ?kVdx{ z!ez)xL|_g?78J)}o*2TpD9S-b$Ak627PNt_*Fq=<^W#D4AkNNDi-%bZmSRuKFN#mh z$>B=Q&n?JF%}vcK5h+M4Dgo7yDVb^DRse{@Q<9Ndlp3E}ky%_)ECS)A<fj(LgYJ0- ziwc5RpeY83De?JfLdl?}Qf6Lpd}48YZfb5)YLOIN4^$2z#h(|SSX3EbT$-B;Zqjjq zOK)(77J@MIi{jy>JZExgQfhoretrozs8T7(0JHfEit-Eci$IqrC+5VL<a2{2-g9zN z!R(y;bnppbiFqkpFm`?s54a5jy%<{n<f{DAqIi&CdQoByC)lTH`9-PhNvX++rNyaS z2rGCXB|oHA;Q@Ic%#1I|7XWcGK?nDPZ7j*>1l1{^LHsmsNHq&)^MjNn#>3?xK^Tvu z0$h24)yC%+#lwt;*6$eNT#%$tl9-&$2}%O-AQpRR0hnefDJo56uE;N9$xF;jVb04h z;)aBHX<lZ29&d3;Vo`j40VKEarer4Ork11@frFnlBfqpbRjeQ<F*!9pKMfo>MXAM* zf}6EGu_QTzGb6vWC_N{!xR@t3D>b<UI{l%Nl#`g84Nal&7AG_bmlS1!o2kkWMW8eq zk4udiL=D7$xD-Kh9jvtnI*i#Aq7ARnn7XiA26HY%J=71#mPy0I0HP!<C%+uj{{i&^ zpnl9vP01|H1!qTuS78Q20}HAK&8sj)iVz<`6_plX8iQ&TI2phL3}%Wj7UzpXOa`5g zS(F+NDi%N&Rft1GL08}8Ktv%GFi$~#IVgF6XT*ddocz4_{IoP^)bqo|AhTvX<r$eJ zsqqlwr68tabG{Tr9X2Uhh%Ou<BMZ@pLskZ&7khBXK(ykJgy=*~L$H8^>clR|3(*P6 zOZj;zyiiLr6La(PQlP;B30ID!(wv;))XG#Ihz^J-ANUx{;?#JMY-$Nq2ZSRGQCM6G z9l<V2tSn|t&dD!L;V8{bDoV}CNn|h1%P-GO%wtW?&rL1if@&y9EaHMV1eD=<N-|18 zrw$aC<QL^iz;r^AFX%|F_>`jjf?|>4?9!YZ@RSdDf;1^VFSS^xq$o2Tw4NW7QZiB# z%Tn_MkcDy*vr|z7(lU!ug^^W2?M6{lo|%^-h^(j_bj67XvPf=zX<kWUW*&;N)Wo8a z3}J}J(u(rS^FSFdEipM&2qFe*v%-a-L6Mu80~bomEGjOEFDy+g0u_3>`T2R=X{ou1 z&`v!koFxF&TL5Zs7MEt02tdrw068EYBmlJ#8tGsmeu$>zoYEvPAF8JqVF*M4k|7WQ z6hj~u!42VoIW{l9B$XS|tO8ZWslrLApj`pbwiH;XSPUu#YSN{q=9OeXg!ywzi!+ns z({iAVa3Kgk4|H{8BBXC101<+Y5rW$MDVeG9ppcC><bpGe5KLnP(*(gZMKH~v=`SrO zF&&yJK}<H#Dy#e=K5z<4O^Giq&o4?TW>3sX%}vTo76gxCmgVP^BtknJBH%ay4X_|Z zln6A<gHv#RX-PbYF9uC$@!<RcPR5|L%~Ft=oDD7Xz?Q~?dS4ltsW~Zpkl-&)&MYp@ zFDm9p%_~dI$uCG1$^jR8&>|)^FF7+u0F?AA<C8N|le57c8$O6YQesX{eo1@<C&&e9 zpv=Gpu>>^Sp$bt0iErdV5s+kjeo<Z`s2wH<Q3Y`eSS@c(Vo`c(JhVbbYUP10dC$*> zmIX<PMM=;qH?1f?7gP`OL5kfJXz{BAT>_DroCs<v#e;fX;2?{KkHt&DT1cP}F3&6h z?U;a0q)Ec0^3f-nRNyTc<kkwB$!bW=8$8McA?Y1j(SZvqNO(XBM@f(f#AI;c3*JBp z4k{^x3?!luQqa*`l(8G=Q5lf7I@WWxA-14hGa&^T27+}lq4VD0F<R)s{Ag0pE@&dQ zxq>o?6;S8q=Vwd6*L|Y86=^{zibPT(E}3+kGAa3aIIKZlcZy<7Stc%Ps&MKlNyKFh zPQ$Wsx;ZDY7_lT4#c8=X_2eZM;qYfZF5eU&Z@oaV2DB0!hYN}lQ*p=?<8)gIPPdgJ z?UzAu0cf2#VofrN6lk?L4k^%@aU8BI#OYbk`f(iQfmV^@FfSRWZ?iIUaOug+!D&%q z5e`ii$a{)V0s^$s9EYZi#8e!qAp=+RWn|*gQjSv#PDf|tr;32vb)Z$Lpk5|)_*@h+ zO9Ckf;4{Z!MX6<};F}21hRaLA7m&dRzImag3uKxCF`EDy?oQ-|P8UEVxk1~?6LY|I zm2gsiL4Iz2T0U$&cWPcb^e}d`(kml1FCE*}4oKo?I!dZUAw?ug%#>6?=OCd4CPWgZ zH4UF+F*frO%di#MiO>QSX}TsUu?RXf2eS<7f};4M{F2hV6xcF0h>OrAvFpvuD=r1y zv6q6k$j`yE&MF5wdyD2M=#+4NQch-JX)1K~7TW|eR)zRNu@J9Qvr*$1wrMgg4TpFp z4)Gk+$z+5%nNaJYp$wCN&V!f0wo5{TzcL@Xv@0XCD6>!%*G5f{G7v6EEJ@6OZ|8(u zV+Jb2AepK-GY{0fk%gH8kxxp6&G;v#rxs_R$%3|kLK;8VWU~{~AV#NvWzig80G$Dc zNTL~B0!yM0Sv0M1Ycuk55_6?-xVR`WEmaCt4rV7vN;s`FC#O6!r6dC}Y9?Bg3LeD) zH810nGZKpulS@*Ipp%>m;NhiWXmJ7Mfrg|MAfpAyB9I~lDk2KHg-4+zBQZ}QzX&3x zP?8Ti>l@U0!;s(tHP{ruqmSI+CJ%%y2w|6GWF}`rL^z8J5|dMlGcpV0G2|fD6f1z5 zt_p?(<c$c(8xxQ>As}x`K;Ddiyg31R3j*?%3IxK(fRF-1LJEusDKI9az=V(jQ$h;N z2q`cpq`-oZ0zx5aL?|SU2!*5(p^!8p6p}`SLehv(NE#6eNh3lbX+$U_jR=LLv4I@8 z96-wNsCgQ{v=M%3WBk%4_@zzpOPk@BHpee*fnVBE9)GYH5Rf+{Aa6uK-k5;A2?2Ri z0`g`A<jo1lTM&>Z5Pn7k!q136_!$uhKO+L+XG9?Uj0l9E5rObCA`pH?1j5gVK=>IO z2t(=`aQ&?So|scG#3E*dMa&qBm<bj!Q!HX;Sj5b+h*@9}vlPMNW&>=3hS&s+un8Jt z6EwjlXo^kH44a@iHbDz)g4ldygw01r*nDJ!%|}Mqd}M^pM@HCuWQ5H}M%a90gw01r z*nDJcAOtQ9QPLWwkP)VkF{Y3SrjRM7kQt_sIi`>WrjVsDrc({Dh#6uLGr}Tfj77`@ zi<l`EF*7V;=2*lmu!v#thY=Qk7-8{;5f*<KVey9%7JnFF@rMx>e;8r$hY=Qk7-8{; zu>minyn>KMC_G~no(T%i6oqGo!ZSzVS)lMN`5-nyNJ9fut|2Pd2$gG$$~8gdnxb;e zP`T!)Tnkh#s;i7pU1fyoDkD@^8KJt$2-Q_asID?Xb(ImStBg=xWrXS~V*}pg#G=#^ z1qf+~!ZSkQ8Kdw_P<W;&JTnxYISS7Lg=fhJu@^!b8lZ9wQMpE_Tw_$O2`bkVm1~B| zHAm%IpmI@NWrXS~BUD!zp}NWl)m28Qt};S(l@Y3|j8I)=gz73IR96`raD&$9D1Zq= zB(@O}+Zc&$g2XmOVw)kc&5_s^NNh_Uur*-9&;XfZh|DoU<`^S$OprOI$Q(0djyW>N z0-1yC0wZJ>7$LjB2-yWj$SyEKc7YMH3yhFmV1(=fBV-pCA-llXfB_5`|Nm!TVqj!o zVBle3V31*8U|?ckVqj)n!NAD6lC7D6iGc+y#sF5s#bCf-$H0`5mQ%vOmy=kM#~=lk zXZZggEDur(V>9MtrYACRFhF!NGO&PEGBR*5Fv{;@U}q3v&|qoc%@SKB9U+~>z{J4D zz{k3Vftf*pL4kEO0~3P+gB*h$Lmk5&h98VZj9H8e7_Ts~F_|%?Fil|E#q@}ogIR~! zk2#OIhj|6_A?91mA6Qse#8}i=OjsOPyjX(Rni=F7_{fKBO$>4r=x$_?C093F1A`2C zdfDn3q{-3AR>vSkx<0mA21!zNvDGk0kfw*Nnn9ct9c)z$V#KRwt7H%*RyA7%g9veI z*~%G&iBZW`#vnvk9a|}bAR$$3B@6=i)vy&a@Z(d#R)kl!kbxJMJX-++4|X}Wd<Jf8 zGHiJaT$ti)xeT1>qHH+~9H?S!*$nK+B5YZpk^?5fmdU^hXJ;_5K-g^Q49p-FTN(os z10RD8LlwgwhChrpj8%*~7{4$XFl8|<VY<UC!tBM|z`TX|1&b7m4@(Wp8kSqE9IPg+ z39MbLTUhU~v9M{e1+bN{&0yQbc8Bc`y9~P(djxw4`vmq?>_^z|uz%s;;!xl);qc&y z;>h8s;ppL*#j%283&#PDQyf<~?r=O|<6%%>5TF1mvbi(JQ=ngfjhiC<ifnESa^&03 z#zlc{MK)IkS#s@W<0M<JBAW|?40-mlageD~k<FPwnjAaX*vZnT$mYZ#MY?@#Y-H$C zWOHPYB-Ji9R+9B7vN<qFkY*1X3yC@u+3Xp_NwI^CnI!d!Y<3J{#GB8?M1pEXHd_W! zV$Eh_BwDQ^n+<~qaptly5UEm;&6+`&7&BS_6Qxd(&5A*Yuz9Tih)|`-X2~E($Sl^s z1l1_ASr9bk4*?a5Y~~F7_|&le#w)MLX2!sWTR-bBJhF;xrVPBe^s@fMDW}M0!oY)F zAL|bsGKy@*4BXiCuztrXuE=J@z=f%v^&1vZMK(hQPIR@bUopfK*$fysP}Q-1K@(AA z(`R5uR>S%kg|En_$H0b=XZ?i4Q)JU+V1>!CeuT3X*>o6KAmXeape#i;Z3bqL80&j5 zt;o88fr&wp!JeUk;SeJWqYGmT;~^#nCL5*-rcF$5m{pi#m?trxVE)5mz>>r=h2;p# z7gi<K0M;7T6|9$7|FEgB`LGqS&0yQZ_JEy<U4`9+J%zoAeF6I(_8aV<ICwZzIBYnA zI5IeDI3{o`;@HA*gyRawBaROoe>gcfg*at6RXBAxO*pOCv?y%v2(Z2b^#>`zY?>6c zcm!DAGRRY8zXk<u9s$-j407b#&ZbUwt4DzKHG?d<HnXXb+3pcweZ?R{o~>-EWVL(* zSYI+olVc;B3K?x50oE4`Ql#6)rc83{M}YM?gCwaou_=+*{t;k(#vnnOEo_P;wSWXz zpE8J(Vgs8332h(&)+Y>N#GB40Pjo9tfb}thD6uB9$r0HO5@3DAAVQp}Y_dePgalY0 zG6)l6BAW~mZ6N{H2Mj`lO=FWL*cuXGz0V*>$Rsv`eHPYx3<CH~VUxt$A`)P|%fOG% z1UArk7S29B>m3F@+`8Gsakh#CSZ_1%;?l_`hNE31z<P@TG{&HSsgq3<Ys*N0^(F&1 zrfLQSHW4gsBLUVM3|yG1*@Q7#M*^(Z8932ZvI(KJj|5n+F>s)&ViQDZAqlWvWnf2E z!6tyzMiOAX!oY@*W#fmpk_1>UGqA#B*!ZCBBmve-3@i{)HePT`Nr3etbj*1Zm{w$6 z&%neWz`7PZ0<Fm4!qCQWjFE-Wfw78l6XOde874obI;J&DH<+22wU`5#OPHrIZ)3i~ z{DFmwMTy0N#fK%1C6A?srGsS>%Pf{fEGt+qK<p!%RAfC*Q42(o^&ACl2u0SjWVZtp zS<jGJn=7)OCaYFfWIaVj{i?`%lH|Hlk@W<LHJ>8uagu5>Mb={^)J=-4M~SX)6j_fD zS&JyL9ww@GP-HzsM7giXdXQk5uE=_TK#8r$x*u<etjM|#PnoO8x)*1;s>r$rN9n1^ zx*KaLsmQtuOL?fsx)Y=9Q)JzNR?;c5ZbvEE6j`?+m1T;oTjAxGBI_1tsinxe8CpuM z0@Dht8$ta%)|KGWijjeZbsd;R+00oggFJ&H`H(GzL5>35$qcgO>Sjw~kReYmTOxxr zIXc-A7^Fzo#}>~ZNvbZkI0gyQ^svP;h?Am&Ervmic=c@245GxUW{YAFAx<q@B!e(9 zD%m0!gb1r+3uh1{q>3$!K>)uRwonFsd@9&N82E6@vjsEo;*w<xV&K6p#}>%IjZKCv zfPo8BoXwws6J3<ekAVYKjLnyU9a)6Uhk*^jXY*!Yh4I+D7+4@|Hctj-5R1)&fr-J9 zfsuh7Jf|iAZjmT5I6`Olxfpa9^ib9XNPuViL2CgRkXYa)2jG<g4EKEQc7eDLRu%R^ G>4^Y6@-El_ literal 0 HcmV?d00001 diff --git a/tests/unit_tests/fixtures/bundle/assets/images/animation.gif b/tests/unit_tests/fixtures/bundle/assets/images/animation.gif new file mode 100644 index 0000000000000000000000000000000000000000..9932e774483eb3516bec26187591b997e6d41859 GIT binary patch literal 9735 zcmZ?wbhEHbOkqf2_|5<VTnvn2jLcF@%xX+bT1-qP%q&(cEUql9zAUVPEUeM2tN|<> z$!u&{Y;0K^?Ah#`rR=QLZ0r>r?Dgy%bsQYc?CgE)>`ff(ogD0~>>Mo|9G#pTv)S3F zaj?(kV4us*Ih~VZ4hP3V4z|^t>`OVhmT+(`;^bJ(!MTouV?8J5I!?}Q9PHb;*fw)= zZs+9K#>KIXi)$+v*G^8(9bBBdxVZLkaqZ&bJj}&$gq!mSH|Gg%&ePl+r?@yzb90^J z<~+;IeU6L!BoEhlZl2TJTo<{yE^%>P<>tJ^!+nj1>moPLC2sD!++6p$x$g0B-{t1H z%gyzWoAVJj=R<Dp$2^=5xgPLvKjPtf%)|ABm-`tH_hTNeH{6`Bc(~v4aJ}Q@e$C7C zl8@&tFYh}Z-nYDbZ+Lk=aB+R)=KjFL`GJS~D=+sq9`294JRf*?Kk@K<=H>m)%kzns z=MN9}4<4SMyu818d4KWq{N?5O&&%_NkLN!h&p$ri|9rgv`Fa2H^8MlC`^C!xih@x* zKp~*`pWDwhB-q(8z|~04fSHkjfkE*n3j>(`&+Y5(ZQ<nUYhYktAOm8ssDhm-a7DJ~ zW<SFwmX{5jGv54gs$)?6&+X~#9OUlgZfIa=^q+x&DI_O3x0uC%fgv}qq$tSUNg*OK zN`d_a0}lfu12Y2)gHd8~ae-q%fDhP2ti-o#V0SQF)&-e`RS9lE?v&KxWCjLC4h9AW zyX1nR5(WlF4+aJXpYoCd5PJ#(1A|C%Mq&yB1LFz?1_qs?h{z}g2F5EO@gxZQ1&Eyv zVgCWKi$a2&85o!Z7#J87(vjFnNbKZ{qW`%J3`_<L3=Ar{Ii<-^H-dtcCp9lLn1O*o ziGhJZhM|}th{2t~i9vzElfjk2nZb;~kin9{jKPdSm%)fZkHL_E0f&B&*)j}%4EYQS z49N`n3<V683`Go?4CxFR3?&RY3<?aT48;to3<?Zs3`Gp745<t`43(e=fVc$_u*GS{ zMqn{U9w!C{)_ec|e^zB+V4uvu@OQ%h|GyXh|NnOp0|WCN28IK92>tmB7#J+RGB7Yt zK!~Z#XJFuOVPM#HI3hAEN&##rL(+5xhVAVP3=%gB5{nYSV$2K-3`}Wh3=E%^GcfQ* zGB5~VU|`^iPR=OGh08N6zRti9Qq92NbC!W&<}3yVwKN6>{ul-wkP1+_&A{=WfssST zW5a@j%^bp7F()=GJlrmz>@~+@<D#S862@6~PFzfA=vQ#=lJVTM<m6-x-!LA{1xrs) zH%LA;$8+<tv$K?>n{q4@7#ioZaB;|TZCP<~vBzYs*k8pOfeUP-n^JxRI-Fm?wn^^B zsjaK8uTMDKCF?yc`x=uyyGLxq)pSN?b^(<cs~4=h%To6F)!ozE*Wce?`&`K)fnn{f zelF$+UMcf~O{{!M-t&BRZhCrphH>`1KNbfQ4l^;SY>QG@*K|TyBjUmWMdoa7F@qEH ze0OhqdwWOm{kF4FhqJgvHC)0z%yf8h#Ew_N!uH@HR(>Uy88hVe?)v)r#^&t%=l1^k z^8TWJ#Qzx&8g?);WeID^1z0sUKa=xW(s3}Ut@gL!r`Pw-@8AFbKLb<6{aV8%2~8Z5 z6Q&<vWR+=~ki??FK9f~$f&nw1^_zktZIWd#9=0pAX*}vsDckX|)B1sdGnZ1tg9A() zbIR{H3P?S;!6H7xpt;S*=i%di9~R9g6I{eHpG@?S`}ug1kIcryJZdou7W6E-sNvA^ zF7SaPmxYX>t3=`kMYS0z(=wmU%viSa*{qZ<%QT5#nMP+WMUL$Y3PY<(o-!_vRB+<4 zHV}L!(<1ch*}@LBRWBCxm{nygEbcjZgwJqG#689eI}L}-<(VIz^Tlss%v_k{6s5It zsa@8qm5bJCy;|9J=)YCg!UDTYCbsE|rl&i06~1a<v#PrJYRwU`>^B=vsCj422}mo* zY~C$&MSDJ9iohF@!&<A~Zo4CNnr*XM3PU3k51+tWhs#<Fj2nzOZol3AA?x>BLF1l+ zgPWgay;{B8x^Cv1MMqa@z24s;$F06sEn~v#o~mE3()Tx?d-dXoNVv_0g<H=(XzYF> zcEDhL^*7B!eNA1n+E<G$U$bepP`hE~Qt2nN)=y;#=svhywSU*AMTzgutT?9^ti`nM zNt)N@vli|>tIqob^L#n&tY5RvK|qN&<D7>1+O3QHxqVHR$$Lw0Vm6OoTe8Ob`ySH+ z%h+OHUUz#P`8hL{z3SVo3iVrGZwF=nw=%!!nLhjb1Ln;S%dWV#_rAMPn!MNKVfJ=j z(>q<kXDc2=I<GTb)gEkT$`ESIu;b>YEV-Re;_N5<cpiFLcE^Kd`R9H<sg-|g_0sD2 zy)XAVn$P}vx+8sE^{GA8@3vnpJ8ZY-{OYo}-FHq{%f0;MbN=1e&kFzVR-Eq-Ucc#U z&HB1OZ%^{Sw*9=(N`K$m#nbQq{pq(@j+sN|w_V-uONamO{qrSRf7`bi!t?&!m}a-) zs(#+h?t3?vnIGshJ>T#zT85$d`#v_IfFLL92WJ+z+r2cr(A3K`f9bmr%L|P9l}s!P zS9z4~V4k+2^vCYmT+SL!;{WoRG<+WN$XD$BT4>OAYPRC_|1KFe-*WXkoOC1vl`|}5 zrk$zTm3{eCg@oO2$&aO0DN*OoY_S)+bgrHAjly@W6{ZGzSNg>EO!>9u$6@7Xc?G## zlO>l&9FW^&*pu>^f%W1vbIo__`f8F7$o^k`Ag8t<H!JzDG|%(nKPoR~KbBg;!rggf zt?H+q%#g=VlsX-px;B;+)LfRAkJOaD_r7E5k=rsC-MzdUFHUwivq<dX4&!?>KXq02 z#3~zST5#+unlyikD#ywfUY=$fC*=D);#z*)Np04J&g3VHjkvF$iI@94d8N-H-MO63 z=3JMXK53_^H*y}y$r7IMsOBN(XLDcGZJ(y)@+>g9z0)__Zt|r2SMDnv=KSw(Q#HBA zIOfSo9#htMsn7FnoO%8sL(^h=>4J`rDswHrrXMrV5$ej8d2X7#GT^TxmruM+hWS&= z^O>I}&rbe)S<YMQNL5!!@Rcfw6=EkYB{Jo5`FlNo|E+Ybfkt=gim1>fSzIA@=Qc;M zH%~fbwajncHty(;U8_P$+14$cmc86??=;2br$Y12a(jLKED`p5$<=kUu7><iy2i1F zOSkssn&ol2cmBndZd`j#YbEF5>%2d|Fid?mVMS_8s_uQw&3kt(XHt4FX}ZwKWyh?( zZH%{?Jo|via?7hH8M%d4-_O~?z!j10?*8K9B(7OYF3tM3#qF11>g*J4&BSS5vt19g z2vsZc{$IGlWyjgId5$GYd@DOxrZoxX2s+JT-jU8EIl+&Mtwdgo<;Bhmz3b{{SU3NX z>0sv43g={Wka}uxoJo?Sv1FMsld!{b>+6h+RoA;^zec6AJZ;UdI2Jrl;$@aePb6Pf z$mGU<|I(Ou9puen^LfB@c$pcS+J+pqH?yz)Xk$9GQoq?`m&JAyHlxXn2hz;WJmkwy zW1Kg0L-Uo*a%)W3^cy@2yPh9P5?wvxXtO3ymD6X-lBp8f1)AM`<!6%R=Bw(OtTVj2 zDoJ#{NUKIhV%MbUG9qf`M>SnLxq9U{3D5ZAaw=<Q=d|r-Qs<@IR8?H);dRXCnbGV@ z6<N>Cv#y_cX14n$$Jv6u&2t{h2;gY0{RcJInBRgbOa=i4P{W6jfeA)~<vxMsxEL7z zg8>5rNR)*QEXvLRYBn)5Lc~C91_n^0hmnDS$pM0)>UqKHSr`}?D!}?h;Cx0fUlPuj z1M?NZd|w6z21ZbWh@ZicA%!8IAqm`A31G-z$Y&^F$Y&@9vkDj(7znF?x)QZ%st9kJ zg00m6TMO!HFxh_qvl&L)tcbSkXqz>X=55w?P-ljRfk~8+QHGIGfss*%k<pZq(UOtD zoteRviNTqH!GnRxgMrb5iNTkF!H1C{fRQ1Xks*+YDUgXFn3*AjfgzNEF_eKJgpnbP zfiawcF^rKZoQWZjg&~5GDT0wPnvo%nfgzreA(n|LhKV78fgzEBF_D2GiGeYRks+Cp zDT$FWfr%lJi7|<pA%&44oq-{Ri6MiLA)ApQmw_RVfgzuPF`t1kkC7ptkuisfA(x3M zmzgn-nK6fjp@4y*kb$9qk+G1Gsepl@h=HMqk+GPGp_GB4gpsL~fuWp{p_GZKgo&Yy ziLru#p^|~2nt`E;k+Fh_p^}NIl9{1~fuWXxp^kyEj)9?`fuW9(v7V8khKaG3nW2G! zp^<^1fsvt+k)er!p_zfPiIJh1k)eT!p^=H9k(sH1iK&5^xsjQniHV_^nW>qHp@o65 zg@K`!fuV(wp^br|oq@5PfuW6&p`DSjg^8h+iK&&Dv7L#bjhUgHnW2e=v4w@9gMp!w zfuVzuv6GRpi-DnoiJ_B;v6GppiwRmHj8e1=0m6N@jf;=>^D}oq`)t9hVon+zaGAuE z1nINQwkUpe#M5Yr$4urXAqg*7pY2ph#)Soj?pA*^9WokMM{Lfz3+c0Mw~|$Gcy(xg z7`KE$!Gg87w--D<HP?Ily1U!5c|{Z$LRAhk7_tilR68_2Wbcrdh&!`m<KyEKl)dA6 zetdYuTs3!E=}dvQ3EMgpJLG(KZFzZlMeyo4-zdXpdsF_F_5J*LfSE&~X!VV=)#Z5t zdrLq6<E^pyaDQ*Jdi**j%g=WNMD{$34pU4x$jbFNOmXq<9;F9+yZ_7k@7we9^NXX+ z{P*`(eqr9Q`n(vA)Q|5<{-0jQL;7rN8VVJ^-iEjEoVEQBm2)k0=`^MtwbSFJM8YB- zv`VC{c-SVB6rtGqQ<lT2q{`6ZcEYW~_WSKR+g?2CHaMp7xZ7W5#i8ozlkEZt8uyOf z6&7VvdeQ^xv$Z?1F+CFIc;wO0$Nq7~+<qg5nQoJu<yJnO=8?piH2Kog6F2*q7H~Z5 z7fG6_Iz2~d<+4ecS1J}aC7In&X3<(xv2=RwH%sODg<^*4HU52)sWXEgMW#;3{`GQ2 zcf+ZdDpS}zXC_SzGyC;oS?r;i@-te3q9!a&_d4-%rOP#rthwrG;j8AYIQIY5qE+T? zkt^n|)8bmaW=~Vb<0WljT`!jI{-&k9_P`^rHB*m$>RPjQk&sJP%TcrHRjZVpq~EMK zyzkVStt;%LUv0Zow)*w<2Sr+Xt5arG=Iz?Jt~z`5=|j@**5A^4y>{>QN7n21z5ld( z<(`XtCTqK1aNSWm_(Up4?+}-LSMH`S@1!@*=V9jgc(gVxrtpBw=9h)Lcjn0$O&5Ot z+mK_~yq-<_-^jhvJAHN69IZ2-C#{h^%X!=8@d=~pcQ&1OW71u-TTQt3^D0aB*!7oO zrOxVJa(32TeC6r6n5|b0lHP8(W?Fo9(RC)-JzH<+PU3C2nYj4vYMz__eivTK>+dZ- zm}*~Bb~pd}f35B31U{YlzNXxKj`<DS&uhPJY2wc_zg)3CH}7#@bi|Hh)!KDG@65cu zcgMZl-E%+P_lu6Hyf4D+m-}d5{yM9t%j^A0Uu5*leZIK!P~6TpJInQUy<WP$Zr9TZ z(t1DNtoa{j^K47^+25BB+viukIq;az_G`g%Ih(tE-uy=23h&!(y>PZTxBBum|NYfp zAIDoI&MHm+x$^#_^tl?dGSyCQofUtnzwWo)CE@=IzNy9k)GuN`%s+u^g$dg!PL`5i z^Zy2^I5-HNZER|CU=g&?(em}E&zmeinJ>d;o9g;9r9%@tPna~YuYDIS+qIA<eT5=- zt41}Kh9G-%1_P_j0Xvpm7wV5YnJiF}GIVg-BFJLsJXa_zHSNwzzY4x7^R%Kqc0Gyg zFTaz#T2zk9dci^8!fD2C&t`12OjlW4aH+!Wg@%T4+?p$;S&yBs-T2s7ab|J$gB>$B zhp_hKTKc4_IiGNn`eZm&QY9`ySo-nW+`i^O?&x<;C%vL3P0HTM6)*Ku{J@`y8i|}s zHQYVD7EM^%&nxMfFz?couw9>~uB++tNqH>n|L)1O9cPy6rC*xdvE|A113b$NyqP8? zNqwGi!e^P$^pj`OtUk}Y(Bk1RIzr08ATl~aI=Dwj+rd37ZblX{MrKJSb~Pq8EhY{f zW)4$kP8$|(R~8;07TzFMzDQR76gK`WR)J(T!E6qpTsGliHj!#}(Pj?O7Iv{tPO%OS z$$oap=^PRh*`;Q4NYCSxTEr={hD&ZMxBPA%g}vPJ2l(XAaw{I?QaZ~6Lg#pu&+#ao z<yN}Dt#pY;`7)QvWgg|Le5%)ZlrHfq-{4lg$E9|kSM@Hx>Rn#d`#fs*c~tN7sy^gV zeZ;Hwm`n8ux7t%~wdY*w&v{gz@TfoIQGLv#{)%7yHILdGUiG)U>hE~f-|%X@=Fxb| zr}>6g^F4^I{)tchGmrWg9<{H$>fiX(Kl5sQ<k9@dtMQpf^D~deS6+>;e41Z)wZ8CZ zeB;&p#;f_AU*j8}<~Kf#@BA9yc{RRpYyRZc{LQ2BgIDt>zvd4<jh{T)KlrqM@M`?# z*Zjq!^@~sI7r*vzKFvS;ntyn-{_t!4<<tDfqy3*(`#-<de?Fc6e44)n)IWoe#xDV_ z-vZkI1hxJPX#W?``bWzq)u`DxLx6B=6Lp3l*o#MVLF#EngXB|FUT#`;7S!5YV`-e` zJAvPRpNzwTjEhVjleK)k8dhFh9<bPJu2yMg<1+t5E{0tJ8a_;Hd@>FW+t%FNoN;+o z?CEK_O)RNLl~fHDq%yQIvIyuJm^C)BHZXI``Rv&6@NkDPcNoL>16Oy+i`J=RF*r7{ z^2j+f2qb<^W1r{T4QXvIQFo~L(7>3?(!bs7TJ(WWP3*!&;R_NLZfE5>(9A9Gw`a%4 z$H&V*zmv5oZ)Po6f68yh^aG8jcW7sv*s!qq`+Hfl4p?jRa{qHXxjp3{rL=r182&Qc zJ;A>E`aau(PUZaaEecE=EMh+nHY&)hc+kXS_ToXafL6qV7WS$QjjW$_8KhG<o|+yg z<?#tP$R^j|(8Q^~WW^#*cx$uAc-0OiPK5}MgDgBM3HM9nI1}bF?Z~{q$f0&bfSKRN z?B<e5HaaVxO!4>IsWLe%C^B_gcvR=pseW#f&72A)3l7$B{iz7Ab5dHsz#^RTfss@H zLxPJ~McT#|K{uU;&*wL=X}ws`BK9kNe%-gu<sub&2M=?r)J$m1lDc<2aW=Pufzl+y zJC(<lFL<VzCDzlI^=jpcWwW$aEYvf6#x5Q5pTTjdgII_x6Ss?lBfH|2nXIc1uxab8 zuK#2BX5$IAXq^p_9~{!yMb2<VuVrC1I8Y}LaiNi8pH_9-#*<aj?{+*f`|UJS%)^^u zD|2M`+HDFyxb!w0)#F~Z_luCV{?0#}vh;Rc5<9TY;oT#ygRJglx8EP)`L2C*ajM(u zg$J^$O4c6yaBXMHhTnC+vJWfBTfg5gyTtnA0S1vh4a~cbWj|kjtS{%4q<nwWs}=vw z&H21?Ay;<G=G0SO*+;j<&B;8icH^hv=2d33t3=GL_h!uNF?zj<a|2iJfn6@)*(NL^ zISnfO-a2m$&ju}DyY2EnsgGG~LixR$P9@}jaJ-aiy!YF^n(qI%zTGY?zWeZc;(b}? zn}*eQzCWt|-)nm3)j8iCcRiK%89$z3{&vTbM(@7dhf`;-t$4QN^_m^G`^)c@?w%|? zZ~MJW_t;;nmNU!!e8s~3!SZR!?A$kR%ub*C{%it&?aO!NlXYD;90=wueYP;I(dzkj z`Fw*H?cMkOED9*s-*Y9*ntS!DYx2I8-!@EtxA%K(d;eFqC!0HM?%guqZ}+?RclFmF zS2uee_`0V$_De(g{&&3o_3NAB|2KWH|E%iYuy}SX<No7jEc^89cvv1VzfRx(d+Yh8 zKgRR^n@H^X;`yOcWKF{ABg-8G(=Ifs?wQUq`?!sJY(e9;Lm_u#o?CC}d{ue-bo}c7 zLLCQX%nI5KTW0b%cUZ0#6l}kGN%5P4gri!WK#T4a>32bDM?VJ^c81v~h;>UGRc=~W z?!}TUarA|ubX!38bfd-M_H64+%>wInRFZd>SSZQWt?nyJxg)V~$8qIvhMx0&g^4on z+~&CJLI<05%5s<GZlOyJIxgOh7h^R)<l|{HaeDHSTShb8ot~YWkmRhwzCGQ+QOj>~ zl})P3dG=GTZ2TP?58oG+{(8iH+Q+J*prxGkJNCuAn$%nMN>#?1b6bL6(TqEv6E3Um zuyEJ=+<Mj|MpxTYE6eZlY^NoXI=&}ejjf7jub9Ln&-G#pXWXQ++z>VOjh>CgK|vJ{ zwxrm(@BDx0duHyu313un-)FA+x>k7l%A)7im1ZvWlRk$%dn{rltaY~RU2y9op9l8O zj~x%OGoIofo#CjzN=xToF++6Aie*77O)`WgEU~y9v*t?cC5v-KIl{4vt!Ho3f0_AZ zq3qRXT8CEzR8+l5Pnoq+pWD)V;jSrD4X(-sIWD-8%_h?Mf_bGVcSS&mVfLy})))GT zGp;h;+BoC*m+0FKVqtx!F82GsRp5$Vxw-1+m4)6@RU`LnoXQisyt@9+;n<bCE>0;E zTo-jW%k_0t$TqQS%c_^A#Q*(uZoQS*iu|SWpVguR+S<5ETaM~*UX%zw_snymyKHdA z=P17ftF2p>on_j$#9;5t|5^uDCA%tR3QI=^p53;sKlPc2>h0T;+PbzGN;qC~k&dh{ z+`OaWlX%g`uG_YCddxzq8YQ;3BVKh)EuHTzakC}VvCU{=rG53mBL8VYhdRqEpFGvu z^rKSeKG*BS=c}}ivVGV47-W>fz!(0=iFG4ij6%Y^!#Ap#&pfdIw7SpDLVSzBoqJ3% zYSI5(bDO2x)+aV<r#0yo+~Eqi{6~N_TsULqp+lmVQ(UjFd2;v7-n2jMU)*{Q{b5Zg ztIUr2b8ve^`O<qwymB_O*)1qgi3qysa&)<x_050)wJDRA?^&+-`DI#7l?bPe!AkZ! z-*zvzVVJ14pixLw(<lCu(9|7Mp6TVT{O=ukXwr-ucb3d|eaU+M5W}o1BJKj69WH84 z6MHjUUN}ihxhW@1><vm`k|~U|vz^qJIQ!8uwlB}^8D|AFDIIy~XWZd5%TJ(Dz(tY2 zM1fi2lMxfo0Y$Ue*H(WP9w^)Ocph)cgKInXZLKOh`#SFOE$i*a8fsoVR`xDE5tXo! zH?QQe^n(xw%M+btMe}^$W<~$Lb$;K0f+FWPq0N>3)f;`&%q~k_neqG13qSL024UG< z3wjddvb^H|Et*kv`}e(uh2IlJKFng4IB@sJLccvvZKrLM`163ne@En>zxn0+cgH$i z<PPlHB(f^v&m)QRJ3`k5iOerx)mOOLdBWZA)1>z<+GcW`7A`@DK26*G=c&rejx*_g WpJ(0v^UUJ>&U5AKJ~uEhSOWldK6Y9F literal 0 HcmV?d00001 diff --git a/tests/unit_tests/fixtures/bundle/assets/images/logo.png b/tests/unit_tests/fixtures/bundle/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bd2fd547833635ab465a796c9a936dcfdf4b3086 GIT binary patch literal 685 zcmeAS@N?(olHy`uVBq!ia0y~yU{GLSV36QoW?*1g)637sz`*c4z$e5tBjbR_9FGGv z1|4%&yeKd*FzIM$5D>`Wn31BfV2MXV%Z!ME28jTL1v3O94kRpCap1!ohXw<Mgr1Cu zn2rToDil;2Dms32%s8OYqcCAkKtW1_L4$%vM#KaWfrN~Lf{Km<2^kVwBo?fwn4zQ4 zF=fS!1shhZvB;<>Sdn8;&?68Kv!P?kf*ErpDk3B@as&?KR3xO#*r1~@qh-Q@mW~4< z5-TJmG!AG~)KpC9$>`{j2#}G;@G$5o5r{}QP?1tl(ehx!o(U@^EO=q#kTIvBpkhVD zoP>gw2@xw24(MnEgaj;DBGD0{prE3_<}P)Qfq}8n)5S4F<NVr5vBAQQ0<Pw60qUza zxvBQe&J<mwl)@^Qyi9ceqe<P*|NobhH**R~ovQ!s^qpB&rTL-Xb$=We`Ohk#@qUi8 z*opYXSJhvfdU*X@@5{2Ed;UCmpC49i*Hcq%e5iKSGMTBp;Zx;5d<m<pR%YVq^l&oW zczJ=S!a|QpK0+I-eSSR_(9!Ypf4gpf_3e8X?`{4N@c8|=(o1a#bDev3+~z)i@YkuS zX_ocb>3z2@FlsK$s7;x*#cS2xIVzl27!7YGlpAJTWL~5zX7qB=y4|@V4$`mB_usE@ zUhls6(dk0vySo<zO6!O?bX0BGYC3oNV!7#3a<?Zpe|p~E@4ilCt%K$)h9$eE9yZ_- z$x&mwCU)XX6l;*zcYfz?owIR*!LQ!SMRlzX)mEJ7vTIu5U$Mtr<=>2gKXL9{DD`+3 z+ozL}c3Gb`eezyEZD-}ln?~oKXCFT$IrT}8!ehU46+6WYTU`7UEZ7~JSSndHJRIM2 u*M?6J3sPw9wJQkST)Ot_rLO&F^NY`J=VxKsf0u!Qfx*+&&t;ucLK6VvyDrWE literal 0 HcmV?d00001 diff --git a/tests/unit_tests/fixtures/bundle/assets/web/custom.css b/tests/unit_tests/fixtures/bundle/assets/web/custom.css new file mode 100644 index 0000000000..992b81c80e --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/assets/web/custom.css @@ -0,0 +1,2 @@ +/* Dummy CSS for bundle testing */ +body { color: red; } diff --git a/tests/unit_tests/fixtures/bundle/assets/web/custom.js b/tests/unit_tests/fixtures/bundle/assets/web/custom.js new file mode 100644 index 0000000000..9be8a6b2dc --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/assets/web/custom.js @@ -0,0 +1,2 @@ +// Dummy JS for bundle testing +console.log("test"); diff --git a/tests/unit_tests/fixtures/bundle/bundle_test.yaml b/tests/unit_tests/fixtures/bundle/bundle_test.yaml new file mode 100644 index 0000000000..f834a8d867 --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/bundle_test.yaml @@ -0,0 +1,60 @@ +esphome: + name: bundle-test + includes: + - includes/custom_sensor.h + +esp32: + board: esp32dev + framework: + type: esp-idf + +logger: + <<: !include common/base.yaml + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + +api: + +ota: + - platform: esphome + password: !secret ota_password + +web_server: + port: 80 + css_include: assets/web/custom.css + js_include: assets/web/custom.js + +i2c: + sda: GPIO21 + scl: GPIO22 + +font: + - id: test_font + file: assets/fonts/test_font.ttf + size: 16 + +image: + - id: test_image + file: assets/images/logo.png + type: BINARY + resize: 16x16 + +animation: + - id: test_animation + file: assets/images/animation.gif + type: BINARY + resize: 16x16 + +display: + - platform: ssd1306_i2c + model: SSD1306_128X64 + address: 0x3C + lambda: |- + it.image(0, 0, id(test_image)); + +external_components: + - source: + type: local + path: local_components diff --git a/tests/unit_tests/fixtures/bundle/common/base.yaml b/tests/unit_tests/fixtures/bundle/common/base.yaml new file mode 100644 index 0000000000..58e1083e82 --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/common/base.yaml @@ -0,0 +1 @@ +level: DEBUG diff --git a/tests/unit_tests/fixtures/bundle/includes/custom_sensor.h b/tests/unit_tests/fixtures/bundle/includes/custom_sensor.h new file mode 100644 index 0000000000..7f0ff474ee --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/includes/custom_sensor.h @@ -0,0 +1,3 @@ +// Dummy custom sensor header for bundle testing +#pragma once +#include "esphome/core/component.h" diff --git a/tests/unit_tests/fixtures/bundle/local_components/my_component/__init__.py b/tests/unit_tests/fixtures/bundle/local_components/my_component/__init__.py new file mode 100644 index 0000000000..aa9fc1474b --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/local_components/my_component/__init__.py @@ -0,0 +1 @@ +# Dummy local external component for bundle testing diff --git a/tests/unit_tests/fixtures/bundle/local_components/my_component/my_component.h b/tests/unit_tests/fixtures/bundle/local_components/my_component/my_component.h new file mode 100644 index 0000000000..19b89ecc82 --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/local_components/my_component/my_component.h @@ -0,0 +1,2 @@ +// Dummy component header for bundle testing +#pragma once diff --git a/tests/unit_tests/fixtures/bundle/secrets.yaml b/tests/unit_tests/fixtures/bundle/secrets.yaml new file mode 100644 index 0000000000..47acddb4d9 --- /dev/null +++ b/tests/unit_tests/fixtures/bundle/secrets.yaml @@ -0,0 +1,4 @@ +wifi_ssid: "TestNetwork" +wifi_password: "TestPassword123" +api_key: "unused_secret_should_not_appear" +ota_password: "ota_test_password" diff --git a/tests/unit_tests/test_bundle.py b/tests/unit_tests/test_bundle.py new file mode 100644 index 0000000000..b8b2d0ffd1 --- /dev/null +++ b/tests/unit_tests/test_bundle.py @@ -0,0 +1,1210 @@ +"""Tests for esphome.bundle module.""" + +from __future__ import annotations + +import io +import json +from pathlib import Path +import tarfile +from typing import Any + +import pytest + +from esphome.bundle import ( + BUNDLE_EXTENSION, + CURRENT_MANIFEST_VERSION, + MANIFEST_FILENAME, + BundleManifest, + ConfigBundleCreator, + ManifestKey, + _add_bytes_to_tar, + _default_target_dir, + _find_used_secret_keys, + extract_bundle, + is_bundle_path, + prepare_bundle_for_compile, + read_bundle_manifest, +) +from esphome.core import CORE, EsphomeError + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_bundle( + tmp_path: Path, + config_filename: str = "test.yaml", + config_content: str = "esphome:\n name: test\n", + manifest_overrides: dict[str, Any] | None = None, + extra_files: dict[str, bytes] | None = None, + *, + include_manifest: bool = True, + raw_members: list[tarfile.TarInfo] | None = None, +) -> Path: + """Create a minimal bundle tar.gz for testing.""" + bundle_path = tmp_path / f"device{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + if include_manifest: + manifest: dict[str, Any] = { + ManifestKey.MANIFEST_VERSION: CURRENT_MANIFEST_VERSION, + ManifestKey.ESPHOME_VERSION: "2026.2.0-test", + ManifestKey.CONFIG_FILENAME: config_filename, + ManifestKey.FILES: [config_filename], + ManifestKey.HAS_SECRETS: False, + } + if manifest_overrides: + manifest.update(manifest_overrides) + _add_bytes_to_tar(tar, MANIFEST_FILENAME, json.dumps(manifest).encode()) + + _add_bytes_to_tar(tar, config_filename, config_content.encode()) + + if extra_files: + for name, data in extra_files.items(): + _add_bytes_to_tar(tar, name, data) + + if raw_members: + for info in raw_members: + tar.addfile(info, io.BytesIO(b"")) + + bundle_path.write_bytes(buf.getvalue()) + return bundle_path + + +def _setup_config_dir( + tmp_path: Path, + files: dict[str, str] | None = None, +) -> Path: + """Set up a fake config directory with files and configure CORE.""" + config_dir = tmp_path / "config" + config_dir.mkdir() + + config_yaml = "esphome:\n name: test\n" + (config_dir / "test.yaml").write_text(config_yaml) + + if files: + for rel_path, content in files.items(): + p = config_dir / rel_path + p.parent.mkdir(parents=True, exist_ok=True) + p.write_text(content) + + CORE.config_path = config_dir / "test.yaml" + return config_dir + + +# --------------------------------------------------------------------------- +# is_bundle_path +# --------------------------------------------------------------------------- + + +@pytest.mark.parametrize( + ("filename", "expected"), + [ + (f"my_device{BUNDLE_EXTENSION}", True), + (f"MY_DEVICE{BUNDLE_EXTENSION.upper()}", True), + ("my_device.yaml", False), + ("my_device.tar.gz", False), + ("my_device.zip", False), + ("", False), + ], +) +def test_is_bundle_path(filename: str, expected: bool) -> None: + assert is_bundle_path(Path(filename)) is expected + + +# --------------------------------------------------------------------------- +# _default_target_dir +# --------------------------------------------------------------------------- + + +def test_default_target_dir_strips_extension() -> None: + p = Path(f"/builds/device{BUNDLE_EXTENSION}") + result = _default_target_dir(p) + assert result == Path("/builds/device") + + +def test_default_target_dir_no_extension() -> None: + p = Path("/builds/device.other") + result = _default_target_dir(p) + assert result == Path("/builds/device.other") + + +# --------------------------------------------------------------------------- +# _find_used_secret_keys +# --------------------------------------------------------------------------- + + +def test_find_used_secret_keys(tmp_path: Path) -> None: + yaml1 = tmp_path / "a.yaml" + yaml1.write_text("wifi:\n ssid: !secret wifi_ssid\n password: !secret wifi_pw\n") + yaml2 = tmp_path / "b.yaml" + yaml2.write_text("api:\n key: !secret api_key\n") + + keys = _find_used_secret_keys([yaml1, yaml2]) + assert keys == {"wifi_ssid", "wifi_pw", "api_key"} + + +def test_find_used_secret_keys_no_secrets(tmp_path: Path) -> None: + yaml1 = tmp_path / "a.yaml" + yaml1.write_text("esphome:\n name: test\n") + + keys = _find_used_secret_keys([yaml1]) + assert keys == set() + + +def test_find_used_secret_keys_missing_file(tmp_path: Path) -> None: + missing = tmp_path / "does_not_exist.yaml" + keys = _find_used_secret_keys([missing]) + assert keys == set() + + +def test_find_used_secret_keys_deduplicates(tmp_path: Path) -> None: + yaml1 = tmp_path / "a.yaml" + yaml1.write_text("a: !secret key1\nb: !secret key1\n") + + keys = _find_used_secret_keys([yaml1]) + assert keys == {"key1"} + + +# --------------------------------------------------------------------------- +# _add_bytes_to_tar +# --------------------------------------------------------------------------- + + +def test_add_bytes_to_tar_deterministic_metadata() -> None: + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + _add_bytes_to_tar(tar, "hello.txt", b"world") + + buf.seek(0) + with tarfile.open(fileobj=buf, mode="r:gz") as tar: + member = tar.getmember("hello.txt") + assert member.size == 5 + assert member.mtime == 0 + assert member.uid == 0 + assert member.gid == 0 + assert member.mode == 0o644 + assert tar.extractfile(member).read() == b"world" + + +# --------------------------------------------------------------------------- +# ManifestKey +# --------------------------------------------------------------------------- + + +def test_manifest_key_values() -> None: + assert ManifestKey.MANIFEST_VERSION == "manifest_version" + assert ManifestKey.ESPHOME_VERSION == "esphome_version" + assert ManifestKey.CONFIG_FILENAME == "config_filename" + assert ManifestKey.FILES == "files" + assert ManifestKey.HAS_SECRETS == "has_secrets" + + +def test_manifest_key_is_str() -> None: + """Verify ManifestKey values work as dict keys and JSON keys.""" + d: dict[str, int] = {ManifestKey.MANIFEST_VERSION: 1} + assert d["manifest_version"] == 1 + + +# --------------------------------------------------------------------------- +# extract_bundle +# --------------------------------------------------------------------------- + + +def test_extract_bundle_basic(tmp_path: Path) -> None: + bundle_path = _make_bundle(tmp_path) + target = tmp_path / "output" + + config_path = extract_bundle(bundle_path, target) + + assert config_path.is_file() + assert config_path.name == "test.yaml" + assert config_path.read_text().startswith("esphome:") + assert (target / MANIFEST_FILENAME).is_file() + + +def test_extract_bundle_default_target_dir(tmp_path: Path) -> None: + bundle_path = _make_bundle(tmp_path) + + config_path = extract_bundle(bundle_path) + + expected_dir = tmp_path / "device" + assert config_path.parent == expected_dir + + +def test_extract_bundle_missing_file(tmp_path: Path) -> None: + missing = tmp_path / f"missing{BUNDLE_EXTENSION}" + with pytest.raises(EsphomeError, match="Bundle file not found"): + extract_bundle(missing) + + +def test_extract_bundle_missing_manifest(tmp_path: Path) -> None: + bundle_path = _make_bundle(tmp_path, include_manifest=False) + with pytest.raises(EsphomeError, match="missing manifest.json"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_future_manifest_version(tmp_path: Path) -> None: + bundle_path = _make_bundle( + tmp_path, + manifest_overrides={ManifestKey.MANIFEST_VERSION: 999}, + ) + with pytest.raises(EsphomeError, match="newer than this ESPHome"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_missing_config_filename_in_manifest(tmp_path: Path) -> None: + """Manifest exists but is missing config_filename key.""" + bundle_path = tmp_path / f"bad{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + manifest = {ManifestKey.MANIFEST_VERSION: 1} + _add_bytes_to_tar(tar, MANIFEST_FILENAME, json.dumps(manifest).encode()) + _add_bytes_to_tar(tar, "test.yaml", b"esphome:\n name: test\n") + bundle_path.write_bytes(buf.getvalue()) + + with pytest.raises(EsphomeError, match="missing 'config_filename'"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_config_not_in_archive(tmp_path: Path) -> None: + """Manifest references a config file that isn't in the archive.""" + bundle_path = _make_bundle( + tmp_path, + config_filename="test.yaml", + manifest_overrides={ManifestKey.CONFIG_FILENAME: "missing.yaml"}, + ) + with pytest.raises(EsphomeError, match="was not found in the archive"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_with_extra_files(tmp_path: Path) -> None: + bundle_path = _make_bundle( + tmp_path, + extra_files={ + "common/base.yaml": b"level: DEBUG\n", + "includes/sensor.h": b"#pragma once\n", + }, + ) + target = tmp_path / "out" + extract_bundle(bundle_path, target) + + assert (target / "common" / "base.yaml").read_text() == "level: DEBUG\n" + assert (target / "includes" / "sensor.h").read_text() == "#pragma once\n" + + +# --------------------------------------------------------------------------- +# extract_bundle - security validation +# --------------------------------------------------------------------------- + + +def test_extract_bundle_rejects_absolute_path(tmp_path: Path) -> None: + info = tarfile.TarInfo(name="/etc/passwd") + info.size = 0 + bundle_path = _make_bundle(tmp_path, raw_members=[info]) + + with pytest.raises(EsphomeError, match="absolute path"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_rejects_path_traversal(tmp_path: Path) -> None: + info = tarfile.TarInfo(name="../../../etc/passwd") + info.size = 0 + bundle_path = _make_bundle(tmp_path, raw_members=[info]) + + with pytest.raises(EsphomeError, match="path traversal"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_rejects_backslash_path_traversal(tmp_path: Path) -> None: + info = tarfile.TarInfo(name="foo\\..\\..\\etc\\passwd") + info.size = 0 + bundle_path = _make_bundle(tmp_path, raw_members=[info]) + + with pytest.raises(EsphomeError, match="path traversal"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_rejects_symlink(tmp_path: Path) -> None: + info = tarfile.TarInfo(name="evil_link") + info.type = tarfile.SYMTYPE + info.linkname = "/etc/passwd" + info.size = 0 + bundle_path = _make_bundle(tmp_path, raw_members=[info]) + + with pytest.raises(EsphomeError, match="symlink"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_rejects_oversized( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """Archive whose total decompressed size exceeds the limit is rejected.""" + # Lower the limit so we don't need huge test data + monkeypatch.setattr("esphome.bundle.MAX_DECOMPRESSED_SIZE", 100) + + bundle_path = _make_bundle( + tmp_path, + extra_files={"big.bin": b"\x00" * 200}, + ) + + with pytest.raises(EsphomeError, match="decompressed size exceeds"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_corrupted_tar(tmp_path: Path) -> None: + """Corrupted tar file raises EsphomeError.""" + bundle_path = tmp_path / f"bad{BUNDLE_EXTENSION}" + bundle_path.write_bytes(b"not a tar file at all") + + with pytest.raises(EsphomeError, match="Failed to extract bundle"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_malformed_manifest_json(tmp_path: Path) -> None: + """Invalid JSON in manifest.json raises EsphomeError.""" + bundle_path = tmp_path / f"badjson{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + _add_bytes_to_tar(tar, MANIFEST_FILENAME, b"{invalid json") + _add_bytes_to_tar(tar, "test.yaml", b"esphome:\n name: test\n") + bundle_path.write_bytes(buf.getvalue()) + + with pytest.raises(EsphomeError, match="malformed manifest.json"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_missing_manifest_version(tmp_path: Path) -> None: + """Manifest without manifest_version raises EsphomeError.""" + bundle_path = tmp_path / f"nover{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + manifest = {ManifestKey.CONFIG_FILENAME: "test.yaml"} + _add_bytes_to_tar(tar, MANIFEST_FILENAME, json.dumps(manifest).encode()) + _add_bytes_to_tar(tar, "test.yaml", b"esphome:\n name: test\n") + bundle_path.write_bytes(buf.getvalue()) + + with pytest.raises(EsphomeError, match="missing 'manifest_version'"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_invalid_manifest_version_type(tmp_path: Path) -> None: + """Non-integer manifest_version raises EsphomeError.""" + bundle_path = _make_bundle( + tmp_path, + manifest_overrides={ManifestKey.MANIFEST_VERSION: "not_an_int"}, + ) + + with pytest.raises(EsphomeError, match="must be a positive integer"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_manifest_version_zero(tmp_path: Path) -> None: + """manifest_version of 0 is rejected.""" + bundle_path = _make_bundle( + tmp_path, + manifest_overrides={ManifestKey.MANIFEST_VERSION: 0}, + ) + + with pytest.raises(EsphomeError, match="must be a positive integer"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_manifest_too_large( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """Oversized manifest.json is rejected.""" + monkeypatch.setattr("esphome.bundle.MAX_MANIFEST_SIZE", 50) + + bundle_path = _make_bundle(tmp_path) + + with pytest.raises(EsphomeError, match="manifest.json too large"): + extract_bundle(bundle_path, tmp_path / "out") + + +def test_extract_bundle_manifest_not_regular_file(tmp_path: Path) -> None: + """manifest.json that is a directory entry raises EsphomeError.""" + bundle_path = tmp_path / f"dirmanifest{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + # Add manifest.json as a directory instead of a file + dir_info = tarfile.TarInfo(name=MANIFEST_FILENAME) + dir_info.type = tarfile.DIRTYPE + dir_info.size = 0 + tar.addfile(dir_info) + _add_bytes_to_tar(tar, "test.yaml", b"esphome:\n name: test\n") + bundle_path.write_bytes(buf.getvalue()) + + with pytest.raises(EsphomeError, match="not a regular file"): + extract_bundle(bundle_path, tmp_path / "out") + + +# --------------------------------------------------------------------------- +# read_bundle_manifest +# --------------------------------------------------------------------------- + + +def test_read_bundle_manifest_corrupted_tar(tmp_path: Path) -> None: + """Corrupted tar file raises EsphomeError via read_bundle_manifest.""" + bundle_path = tmp_path / f"bad{BUNDLE_EXTENSION}" + bundle_path.write_bytes(b"not a tar file") + + with pytest.raises(EsphomeError, match="Failed to read bundle"): + read_bundle_manifest(bundle_path) + + +def test_read_bundle_manifest(tmp_path: Path) -> None: + bundle_path = _make_bundle( + tmp_path, + manifest_overrides={ManifestKey.HAS_SECRETS: True}, + extra_files={"secrets.yaml": b"wifi: test\n"}, + ) + + manifest = read_bundle_manifest(bundle_path) + + assert isinstance(manifest, BundleManifest) + assert manifest.manifest_version == CURRENT_MANIFEST_VERSION + assert manifest.esphome_version == "2026.2.0-test" + assert manifest.config_filename == "test.yaml" + assert manifest.has_secrets is True + + +def test_read_bundle_manifest_minimal(tmp_path: Path) -> None: + """Manifest with only required fields.""" + bundle_path = tmp_path / f"min{BUNDLE_EXTENSION}" + buf = io.BytesIO() + with tarfile.open(fileobj=buf, mode="w:gz") as tar: + manifest = { + ManifestKey.MANIFEST_VERSION: 1, + ManifestKey.CONFIG_FILENAME: "cfg.yaml", + } + _add_bytes_to_tar(tar, MANIFEST_FILENAME, json.dumps(manifest).encode()) + _add_bytes_to_tar(tar, "cfg.yaml", b"") + bundle_path.write_bytes(buf.getvalue()) + + result = read_bundle_manifest(bundle_path) + assert result.esphome_version == "unknown" + assert result.files == [] + assert result.has_secrets is False + + +# --------------------------------------------------------------------------- +# prepare_bundle_for_compile +# --------------------------------------------------------------------------- + + +def test_prepare_bundle_preserves_build_cache(tmp_path: Path) -> None: + bundle_path = _make_bundle(tmp_path) + target = tmp_path / "work" + target.mkdir() + + # Pre-existing build cache + esphome_dir = target / ".esphome" + esphome_dir.mkdir() + (esphome_dir / "build_state.json").write_text('{"cached": true}') + + pio_dir = target / ".pioenvs" + pio_dir.mkdir() + (pio_dir / "firmware.bin").write_bytes(b"\x00" * 100) + + config_path = prepare_bundle_for_compile(bundle_path, target) + + assert config_path.is_file() + # Build caches should be preserved + assert (target / ".esphome" / "build_state.json").read_text() == '{"cached": true}' + assert (target / ".pioenvs" / "firmware.bin").read_bytes() == b"\x00" * 100 + + +def test_prepare_bundle_cleans_old_config(tmp_path: Path) -> None: + bundle_path = _make_bundle(tmp_path) + target = tmp_path / "work" + target.mkdir() + + # Old config from previous extraction + (target / "old_config.yaml").write_text("old: true") + old_dir = target / "old_includes" + old_dir.mkdir() + (old_dir / "old.h").write_text("// old") + + prepare_bundle_for_compile(bundle_path, target) + + # Old files should be cleaned + assert not (target / "old_config.yaml").exists() + assert not (target / "old_includes").exists() + # New config should exist + assert (target / "test.yaml").is_file() + + +def test_prepare_bundle_missing_file(tmp_path: Path) -> None: + missing = tmp_path / f"missing{BUNDLE_EXTENSION}" + with pytest.raises(EsphomeError, match="Bundle file not found"): + prepare_bundle_for_compile(missing) + + +def test_prepare_bundle_cache_wins_over_bundle_content(tmp_path: Path) -> None: + """Pre-existing build cache is restored even if the bundle contains those dirs.""" + bundle_path = _make_bundle( + tmp_path, + extra_files={ + ".esphome/from_bundle.json": b'{"from": "bundle"}', + }, + ) + target = tmp_path / "work" + target.mkdir() + + # Pre-existing build cache + esphome_dir = target / ".esphome" + esphome_dir.mkdir() + (esphome_dir / "local_cache.json").write_text('{"from": "local"}') + + prepare_bundle_for_compile(bundle_path, target) + + # Local cache should win over bundle content + assert (target / ".esphome" / "local_cache.json").read_text() == '{"from": "local"}' + assert not (target / ".esphome" / "from_bundle.json").exists() + + +def test_prepare_bundle_default_target_dir(tmp_path: Path) -> None: + """prepare_bundle_for_compile uses default dir when target_dir is None.""" + bundle_path = _make_bundle(tmp_path) + + config_path = prepare_bundle_for_compile(bundle_path) + + expected_dir = tmp_path / "device" + assert config_path.parent == expected_dir + assert config_path.is_file() + + +# --------------------------------------------------------------------------- +# ConfigBundleCreator - file discovery +# --------------------------------------------------------------------------- + + +def test_discover_files_includes_config(tmp_path: Path) -> None: + _setup_config_dir(tmp_path) + + creator = ConfigBundleCreator({}) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "test.yaml" in paths + + +def test_discover_files_finds_path_objects(tmp_path: Path) -> None: + """Path objects in validated config are discovered.""" + config_dir = _setup_config_dir( + tmp_path, + files={"assets/font.ttf": "fake font data"}, + ) + + config: dict[str, Any] = {"font": [{"file": config_dir / "assets" / "font.ttf"}]} + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "assets/font.ttf" in paths + + +def test_discover_files_finds_absolute_string_paths(tmp_path: Path) -> None: + """Absolute string paths in validated config are discovered.""" + config_dir = _setup_config_dir( + tmp_path, + files={"assets/logo.png": "fake png data"}, + ) + + abs_path = str(config_dir / "assets" / "logo.png") + config: dict[str, Any] = {"image": [{"file": abs_path}]} + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "assets/logo.png" in paths + + +def test_discover_files_skips_non_path_prefixes(tmp_path: Path) -> None: + """Remote URLs and special prefixes are not treated as file paths.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "font": [ + {"file": "https://example.com/font.ttf"}, + {"file": "mdi:home"}, + {"file": "http://example.com/icon.png"}, + ] + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + # Only the config file itself + assert len(files) == 1 + assert files[0].path == "test.yaml" + + +def test_discover_files_skips_multiline_strings(tmp_path: Path) -> None: + """Lambda/template strings are not treated as file paths.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "sensor": [{"lambda": "auto val = id(sensor1);\nreturn val;"}] + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + assert len(files) == 1 + + +def test_discover_files_deduplicates(tmp_path: Path) -> None: + """Same file referenced twice is only included once.""" + config_dir = _setup_config_dir( + tmp_path, + files={"cert.pem": "fake cert"}, + ) + + abs_path = str(config_dir / "cert.pem") + config: dict[str, Any] = { + "a": {"cert": abs_path}, + "b": {"cert": abs_path}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + cert_files = [f for f in files if f.path == "cert.pem"] + assert len(cert_files) == 1 + + +def test_discover_files_skips_outside_config_dir(tmp_path: Path) -> None: + """Files outside the config directory are skipped.""" + _setup_config_dir(tmp_path) + + outside_file = tmp_path / "outside.pem" + outside_file.write_text("outside cert") + + config: dict[str, Any] = {"cert": str(outside_file)} + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "outside.pem" not in paths + + +def test_discover_files_esphome_includes(tmp_path: Path) -> None: + """Paths listed in esphome.includes are discovered.""" + _setup_config_dir( + tmp_path, + files={"my_sensor.h": "#pragma once\n"}, + ) + + config: dict[str, Any] = { + "esphome": {"includes": ["my_sensor.h"]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "my_sensor.h" in paths + + +def test_discover_files_esphome_includes_directory(tmp_path: Path) -> None: + """esphome.includes pointing to a directory adds all files.""" + _setup_config_dir( + tmp_path, + files={ + "my_lib/a.h": "// a", + "my_lib/b.cpp": "// b", + }, + ) + + config: dict[str, Any] = { + "esphome": {"includes": ["my_lib"]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "my_lib/a.h" in paths + assert "my_lib/b.cpp" in paths + + +def test_discover_files_esphome_includes_skips_system(tmp_path: Path) -> None: + """System includes like <Arduino.h> are not added.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "esphome": {"includes": ["<Arduino.h>"]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert len(paths) == 1 # Just test.yaml + + +def test_discover_files_external_components_local(tmp_path: Path) -> None: + """external_components with type: local adds the directory.""" + _setup_config_dir( + tmp_path, + files={ + "components/my_comp/__init__.py": "# comp", + "components/my_comp/sensor.py": "# sensor", + }, + ) + + config: dict[str, Any] = { + "external_components": [{"source": {"type": "local", "path": "components"}}], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "components/my_comp/__init__.py" in paths + assert "components/my_comp/sensor.py" in paths + + +def test_discover_files_external_components_skips_pycache(tmp_path: Path) -> None: + """__pycache__ directories inside local external_components are excluded.""" + _setup_config_dir( + tmp_path, + files={ + "components/my_comp/__init__.py": "# comp", + "components/my_comp/__pycache__/module.cpython-313.pyc": "bytecode", + }, + ) + + config: dict[str, Any] = { + "external_components": [{"source": {"type": "local", "path": "components"}}], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "components/my_comp/__init__.py" in paths + assert not any("__pycache__" in p for p in paths) + + +def test_discover_files_external_components_non_dict_source(tmp_path: Path) -> None: + """external_components with string source (e.g. github shorthand) is skipped.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "external_components": [{"source": "github://user/repo@main"}], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + # Only the config file itself - no crash from non-dict source + assert len(files) == 1 + assert files[0].path == "test.yaml" + + +def test_discover_files_nested_config_values(tmp_path: Path) -> None: + """Deeply nested Path objects in lists/dicts are found.""" + config_dir = _setup_config_dir( + tmp_path, + files={"deep/file.pem": "cert data"}, + ) + + config: dict[str, Any] = { + "level1": {"level2": [{"level3": config_dir / "deep" / "file.pem"}]} + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "deep/file.pem" in paths + + +def test_discover_files_idempotent_secrets(tmp_path: Path) -> None: + """Calling discover_files twice does not accumulate secrets paths.""" + config_dir = _setup_config_dir(tmp_path) + (config_dir / "secrets.yaml").write_text("k: v\n") + (config_dir / "test.yaml").write_text("a: !secret k\n") + + creator = ConfigBundleCreator({}) + files1 = creator.discover_files() + files2 = creator.discover_files() + + # Both calls should return the same result (secrets not accumulated) + paths1 = [f.path for f in files1] + paths2 = [f.path for f in files2] + assert "secrets.yaml" in paths1 + assert paths1 == paths2 + + +def test_discover_files_skips_missing_file(tmp_path: Path) -> None: + """_add_file logs warning for non-existent files via includes.""" + _setup_config_dir(tmp_path) + + # Include references a file that doesn't exist on disk + config: dict[str, Any] = { + "esphome": {"includes": ["nonexistent.h"]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "nonexistent.h" not in paths + + +def test_discover_files_skips_missing_directory(tmp_path: Path) -> None: + """_add_directory logs warning for non-existent directories.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "external_components": [ + {"source": {"type": "local", "path": "nonexistent_dir"}} + ], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + # Only the config file + assert len(files) == 1 + + +def test_discover_files_yaml_reload_failure( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """YAML reload failure during include discovery is handled gracefully.""" + _setup_config_dir(tmp_path) + + def _raise_error(*args, **kwargs): + raise EsphomeError("parse error") + + monkeypatch.setattr("esphome.yaml_util.load_yaml", _raise_error) + + creator = ConfigBundleCreator({}) + files = creator.discover_files() + + # Should still have the config file at minimum + paths = [f.path for f in files] + assert "test.yaml" in paths + + +def test_discover_files_esphome_includes_c(tmp_path: Path) -> None: + """Paths listed in esphome.includes_c are discovered.""" + _setup_config_dir( + tmp_path, + files={"my_code.c": "// c code"}, + ) + + config: dict[str, Any] = { + "esphome": {"includes_c": ["my_code.c"]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "my_code.c" in paths + + +def test_discover_files_external_components_non_local_type(tmp_path: Path) -> None: + """external_components with type != 'local' are skipped.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "external_components": [ + {"source": {"type": "git", "url": "https://github.com/user/repo"}} + ], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + assert len(files) == 1 + + +def test_discover_files_external_components_no_path(tmp_path: Path) -> None: + """external_components with local type but missing path are skipped.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "external_components": [{"source": {"type": "local"}}], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + assert len(files) == 1 + + +def test_discover_files_external_components_absolute_path(tmp_path: Path) -> None: + """external_components with absolute path are resolved correctly.""" + config_dir = _setup_config_dir( + tmp_path, + files={"ext/comp/__init__.py": "# comp"}, + ) + + abs_path = str(config_dir / "ext") + config: dict[str, Any] = { + "external_components": [{"source": {"type": "local", "path": abs_path}}], + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "ext/comp/__init__.py" in paths + + +def test_discover_files_relative_string_with_known_extension(tmp_path: Path) -> None: + """Relative strings with known extensions are resolved and warned.""" + _setup_config_dir( + tmp_path, + files={"my_cert.pem": "cert data"}, + ) + + config: dict[str, Any] = { + "component": {"cert": "my_cert.pem"}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "my_cert.pem" in paths + + +def test_discover_files_relative_string_missing_file(tmp_path: Path) -> None: + """Relative strings with known extensions that don't exist are skipped.""" + _setup_config_dir(tmp_path) + + config: dict[str, Any] = { + "component": {"cert": "nonexistent.pem"}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + assert len(files) == 1 + + +def test_discover_files_esphome_includes_absolute_path(tmp_path: Path) -> None: + """esphome.includes with absolute path is handled.""" + config_dir = _setup_config_dir( + tmp_path, + files={"my_code.h": "#pragma once"}, + ) + + config: dict[str, Any] = { + "esphome": {"includes": [str(config_dir / "my_code.h")]}, + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "my_code.h" in paths + + +def test_discover_files_walk_tuple_values(tmp_path: Path) -> None: + """Tuples in config are walked like lists.""" + config_dir = _setup_config_dir( + tmp_path, + files={"a.pem": "cert"}, + ) + + config: dict[str, Any] = { + "items": (config_dir / "a.pem",), + } + creator = ConfigBundleCreator(config) + files = creator.discover_files() + + paths = [f.path for f in files] + assert "a.pem" in paths + + +# --------------------------------------------------------------------------- +# ConfigBundleCreator - create_bundle +# --------------------------------------------------------------------------- + + +def test_create_bundle_produces_valid_archive(tmp_path: Path) -> None: + _setup_config_dir(tmp_path) + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + assert isinstance(result.data, bytes) + assert len(result.data) > 0 + + # Verify it's a valid tar.gz + buf = io.BytesIO(result.data) + with tarfile.open(fileobj=buf, mode="r:gz") as tar: + names = tar.getnames() + assert MANIFEST_FILENAME in names + assert "test.yaml" in names + + +def test_create_bundle_manifest_content(tmp_path: Path) -> None: + _setup_config_dir(tmp_path) + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + manifest = result.manifest + assert manifest[ManifestKey.MANIFEST_VERSION] == CURRENT_MANIFEST_VERSION + assert manifest[ManifestKey.CONFIG_FILENAME] == "test.yaml" + assert "test.yaml" in manifest[ManifestKey.FILES] + + +def test_create_bundle_filters_secrets(tmp_path: Path) -> None: + config_dir = _setup_config_dir(tmp_path) + + # Create secrets.yaml with multiple secrets + secrets = config_dir / "secrets.yaml" + secrets.write_text( + "wifi_ssid: MyNetwork\nwifi_pw: secret123\nunused: should_not_appear\n" + ) + + # Config that references only some secrets + config_yaml = "wifi:\n ssid: !secret wifi_ssid\n password: !secret wifi_pw\n" + (config_dir / "test.yaml").write_text(config_yaml) + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + # Extract and check secrets + buf = io.BytesIO(result.data) + with tarfile.open(fileobj=buf, mode="r:gz") as tar: + secrets_data = tar.extractfile("secrets.yaml").read().decode() + + assert "wifi_ssid" in secrets_data + assert "wifi_pw" in secrets_data + assert "unused" not in secrets_data + assert "should_not_appear" not in secrets_data + + +def test_create_bundle_no_secrets(tmp_path: Path) -> None: + _setup_config_dir(tmp_path) + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + assert result.manifest[ManifestKey.HAS_SECRETS] is False + + +def test_create_bundle_secrets_load_failure( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + """Secrets file that fails to load during filtering is skipped gracefully.""" + config_dir = _setup_config_dir(tmp_path) + (config_dir / "secrets.yaml").write_text("k: v\n") + (config_dir / "test.yaml").write_text("a: !secret k\n") + + from esphome import yaml_util as yu + + original_load = yu.load_yaml + + def _failing_on_filter(fname, *args, clear_secrets=True, **kwargs): + # Fail only when _build_filtered_secrets calls with clear_secrets=False + if not clear_secrets and "secrets" in str(fname): + raise EsphomeError("corrupt secrets") + return original_load(fname, *args, clear_secrets=clear_secrets, **kwargs) + + monkeypatch.setattr(yu, "load_yaml", _failing_on_filter) + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + # Should succeed without secrets since the filtered load failed + assert result.manifest[ManifestKey.HAS_SECRETS] is False + + +def test_create_bundle_secrets_non_dict(tmp_path: Path) -> None: + """Secrets file that parses to non-dict is skipped.""" + config_dir = _setup_config_dir(tmp_path) + (config_dir / "secrets.yaml").write_text("- item1\n- item2\n") + (config_dir / "test.yaml").write_text("a: !secret k\n") + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + assert result.manifest[ManifestKey.HAS_SECRETS] is False + + +def test_create_bundle_secrets_no_matching_keys(tmp_path: Path) -> None: + """Secrets with no matching keys produces empty filtered result.""" + config_dir = _setup_config_dir(tmp_path) + (config_dir / "secrets.yaml").write_text("other_key: value\n") + (config_dir / "test.yaml").write_text("a: !secret nonexistent\n") + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + assert result.manifest[ManifestKey.HAS_SECRETS] is False + + +def test_create_bundle_deterministic_order(tmp_path: Path) -> None: + """Files are added in sorted order for reproducibility.""" + _setup_config_dir( + tmp_path, + files={ + "z_last.h": "// z", + "a_first.h": "// a", + "m_middle.h": "// m", + }, + ) + + config: dict[str, Any] = { + "esphome": {"includes": ["z_last.h", "a_first.h", "m_middle.h"]}, + } + creator = ConfigBundleCreator(config) + result = creator.create_bundle() + + buf = io.BytesIO(result.data) + with tarfile.open(fileobj=buf, mode="r:gz") as tar: + names = tar.getnames() + + # manifest.json is always first, then files in sorted order + assert names[0] == MANIFEST_FILENAME + file_names = [n for n in names if n != MANIFEST_FILENAME] + assert file_names == sorted(file_names) + + +# --------------------------------------------------------------------------- +# Round-trip: create then extract +# --------------------------------------------------------------------------- + + +def test_bundle_round_trip(tmp_path: Path) -> None: + """A bundle created by ConfigBundleCreator can be extracted.""" + _setup_config_dir( + tmp_path, + files={"include.h": "#pragma once\n"}, + ) + config: dict[str, Any] = {"esphome": {"includes": ["include.h"]}} + + creator = ConfigBundleCreator(config) + result = creator.create_bundle() + + bundle_path = tmp_path / f"roundtrip{BUNDLE_EXTENSION}" + bundle_path.write_bytes(result.data) + + target = tmp_path / "extracted" + config_path = extract_bundle(bundle_path, target) + + assert config_path.is_file() + assert (target / "include.h").read_text() == "#pragma once\n" + + manifest = read_bundle_manifest(bundle_path) + assert manifest.config_filename == "test.yaml" + assert "include.h" in manifest.files + + +def test_bundle_round_trip_with_secrets(tmp_path: Path) -> None: + """Secrets survive round-trip with correct filtering.""" + config_dir = _setup_config_dir(tmp_path) + (config_dir / "secrets.yaml").write_text("key1: val1\nkey2: val2\nunused: nope\n") + (config_dir / "test.yaml").write_text("a: !secret key1\nb: !secret key2\n") + + creator = ConfigBundleCreator({}) + result = creator.create_bundle() + + bundle_path = tmp_path / f"secrets{BUNDLE_EXTENSION}" + bundle_path.write_bytes(result.data) + + target = tmp_path / "extracted" + extract_bundle(bundle_path, target) + + secrets_content = (target / "secrets.yaml").read_text() + assert "key1" in secrets_content + assert "key2" in secrets_content + assert "unused" not in secrets_content + + manifest = read_bundle_manifest(bundle_path) + assert manifest.has_secrets is True diff --git a/tests/unit_tests/test_main.py b/tests/unit_tests/test_main.py index 115ce38c93..85536d2f1c 100644 --- a/tests/unit_tests/test_main.py +++ b/tests/unit_tests/test_main.py @@ -24,6 +24,7 @@ from esphome.__main__ import ( _make_crystal_freq_callback, choose_upload_log_host, command_analyze_memory, + command_bundle, command_clean_all, command_rename, command_update_all, @@ -47,6 +48,7 @@ from esphome.__main__ import ( upload_using_picotool, upload_using_platformio, ) +from esphome.bundle import BUNDLE_EXTENSION, BundleFile, BundleResult from esphome.components.esp32 import KEY_ESP32, KEY_VARIANT, VARIANT_ESP32 from esphome.const import ( CONF_API, @@ -1101,6 +1103,8 @@ class MockArgs: name: str | None = None dashboard: bool = False reset: bool = False + list_only: bool = False + output: str | None = None def test_upload_program_serial_esp32( @@ -3765,6 +3769,198 @@ esp32: assert "secrets.yaml" not in summary_section +# --- command_bundle tests --- + + +def test_command_bundle_list_only( + tmp_path: Path, + capsys: CaptureFixture[str], +) -> None: + """Test command_bundle with --list-only prints files and returns 0.""" + mock_files = [ + BundleFile(path="device.yaml", source=tmp_path / "device.yaml"), + BundleFile(path="secrets.yaml", source=tmp_path / "secrets.yaml"), + BundleFile(path="common/base.yaml", source=tmp_path / "common" / "base.yaml"), + ] + + args = MockArgs(list_only=True) + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.discover_files.return_value = mock_files + + with patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator): + result = command_bundle(args, config) + + assert result == 0 + captured = capsys.readouterr() + # Files should be printed in sorted order + assert "common/base.yaml" in captured.out + assert "device.yaml" in captured.out + assert "secrets.yaml" in captured.out + + +def test_command_bundle_list_only_empty( + tmp_path: Path, + capsys: CaptureFixture[str], +) -> None: + """Test command_bundle --list-only with no files discovered.""" + args = MockArgs(list_only=True) + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.discover_files.return_value = [] + + with patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator): + result = command_bundle(args, config) + + assert result == 0 + + +def test_command_bundle_creates_archive(tmp_path: Path) -> None: + """Test command_bundle creates archive at default output path.""" + CORE.config_path = tmp_path / "mydevice.yaml" + + mock_result = BundleResult( + data=b"fake-tar-gz-data", + manifest={"manifest_version": 1}, + files=[BundleFile(path="mydevice.yaml", source=tmp_path / "mydevice.yaml")], + ) + + args = MockArgs() + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.create_bundle.return_value = mock_result + + with patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator): + result = command_bundle(args, config) + + assert result == 0 + output_path = tmp_path / f"mydevice{BUNDLE_EXTENSION}" + assert output_path.exists() + assert output_path.read_bytes() == b"fake-tar-gz-data" + + +def test_command_bundle_custom_output(tmp_path: Path) -> None: + """Test command_bundle with -o custom output path.""" + custom_output = tmp_path / "output" / "custom.esphomebundle.tar.gz" + mock_result = BundleResult( + data=b"custom-output-data", + manifest={"manifest_version": 1}, + files=[BundleFile(path="mydevice.yaml", source=tmp_path / "mydevice.yaml")], + ) + + args = MockArgs(output=str(custom_output)) + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.create_bundle.return_value = mock_result + + with patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator): + result = command_bundle(args, config) + + assert result == 0 + assert custom_output.exists() + assert custom_output.read_bytes() == b"custom-output-data" + + +def test_command_bundle_creates_parent_dirs(tmp_path: Path) -> None: + """Test command_bundle creates parent directories for output path.""" + nested_output = tmp_path / "deep" / "nested" / "dir" / "out.tar.gz" + mock_result = BundleResult( + data=b"data", + manifest={"manifest_version": 1}, + files=[BundleFile(path="mydevice.yaml", source=tmp_path / "mydevice.yaml")], + ) + + args = MockArgs(output=str(nested_output)) + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.create_bundle.return_value = mock_result + + with patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator): + result = command_bundle(args, config) + + assert result == 0 + assert nested_output.exists() + + +def test_command_bundle_logs_info( + tmp_path: Path, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test command_bundle logs bundle creation info.""" + CORE.config_path = tmp_path / "mydevice.yaml" + + mock_result = BundleResult( + data=b"x" * 2048, + manifest={"manifest_version": 1}, + files=[ + BundleFile(path="mydevice.yaml", source=tmp_path / "mydevice.yaml"), + BundleFile(path="secrets.yaml", source=tmp_path / "secrets.yaml"), + ], + ) + + args = MockArgs() + config: dict[str, Any] = {} + + mock_creator = MagicMock() + mock_creator.create_bundle.return_value = mock_result + + with ( + patch("esphome.bundle.ConfigBundleCreator", return_value=mock_creator), + caplog.at_level(logging.INFO), + ): + result = command_bundle(args, config) + + assert result == 0 + assert "Bundle created" in caplog.text + assert "2 files" in caplog.text + assert "2.0 KB" in caplog.text + + +def test_run_esphome_bundle_detection(tmp_path: Path) -> None: + """Test run_esphome detects .esphomebundle.tar.gz and extracts it.""" + bundle_path = tmp_path / f"device{BUNDLE_EXTENSION}" + bundle_path.write_bytes(b"fake-bundle") + + extracted_yaml = tmp_path / "extracted" / "device.yaml" + + with ( + patch("esphome.bundle.is_bundle_path", return_value=True) as mock_is_bundle, + patch( + "esphome.bundle.prepare_bundle_for_compile", + return_value=extracted_yaml, + ) as mock_prepare, + patch("esphome.__main__.read_config", return_value=None), + ): + result = run_esphome(["esphome", "compile", str(bundle_path)]) + + mock_is_bundle.assert_called_once() + mock_prepare.assert_called_once_with(bundle_path) + # read_config returns None → exit code 2 + assert result == 2 + + +def test_run_esphome_non_bundle_skips_extraction(tmp_path: Path) -> None: + """Test run_esphome does not extract for regular .yaml files.""" + yaml_file = tmp_path / "device.yaml" + yaml_file.write_text("esphome:\n name: test\n") + + with ( + patch("esphome.bundle.is_bundle_path", return_value=False) as mock_is_bundle, + patch("esphome.bundle.prepare_bundle_for_compile") as mock_prepare, + patch("esphome.__main__.read_config", return_value=None), + ): + result = run_esphome(["esphome", "compile", str(yaml_file)]) + + mock_is_bundle.assert_called_once() + mock_prepare.assert_not_called() + assert result == 2 + + def test_get_configured_xtal_freq_reads_sdkconfig(tmp_path: Path) -> None: """Test reading XTAL_FREQ from sdkconfig.""" CORE.name = "test-device" diff --git a/tests/unit_tests/test_yaml_util.py b/tests/unit_tests/test_yaml_util.py index 667b593819..0342d12540 100644 --- a/tests/unit_tests/test_yaml_util.py +++ b/tests/unit_tests/test_yaml_util.py @@ -323,6 +323,60 @@ def test_dump_sort_keys() -> None: assert sorted_dump.index("a_key:") < sorted_dump.index("z_key:") +# --------------------------------------------------------------------------- +# track_yaml_loads +# --------------------------------------------------------------------------- + + +def test_track_yaml_loads_records_files(tmp_path: Path) -> None: + """track_yaml_loads records every file loaded inside the context.""" + yaml_file = tmp_path / "test.yaml" + yaml_file.write_text("key: value\n") + + with yaml_util.track_yaml_loads() as loaded: + yaml_util.load_yaml(yaml_file) + + assert len(loaded) == 1 + assert loaded[0] == yaml_file.resolve() + + +def test_track_yaml_loads_records_includes(tmp_path: Path) -> None: + """track_yaml_loads records nested !include files.""" + inc = tmp_path / "included.yaml" + inc.write_text("included_key: 42\n") + main = tmp_path / "main.yaml" + main.write_text("child: !include included.yaml\n") + + with yaml_util.track_yaml_loads() as loaded: + yaml_util.load_yaml(main) + + resolved = [p.name for p in loaded] + assert "main.yaml" in resolved + assert "included.yaml" in resolved + + +def test_track_yaml_loads_empty_outside_context(tmp_path: Path) -> None: + """Files loaded outside the context are not recorded.""" + yaml_file = tmp_path / "test.yaml" + yaml_file.write_text("key: value\n") + + with yaml_util.track_yaml_loads() as loaded: + pass # load nothing inside + + yaml_util.load_yaml(yaml_file) + assert loaded == [] + + +def test_track_yaml_loads_cleanup_on_exception(tmp_path: Path) -> None: + """Listener is removed even if the body raises.""" + before = len(yaml_util._load_listeners) + + with pytest.raises(RuntimeError), yaml_util.track_yaml_loads(): + raise RuntimeError("boom") + + assert len(yaml_util._load_listeners) == before + + @pytest.mark.parametrize( "data", [ From ac14b9e5584d8c2bea962529522aaa46df8a41e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:40:21 -1000 Subject: [PATCH 2009/2030] Bump pypa/gh-action-pypi-publish from 1.13.0 to 1.14.0 (#15541) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba6db99b84..9e8a040888 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -70,7 +70,7 @@ jobs: pip3 install build python3 -m build - name: Publish - uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 with: skip-existing: true From 9d396cea5a3d5ad5d1ae50f29c81825b9d5c3120 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:56:25 -0400 Subject: [PATCH 2010/2030] [grove_tb6612fng] Move direction logic from Python to C++ to fix lambda crash (#15513) --- esphome/components/grove_tb6612fng/__init__.py | 4 +--- esphome/components/grove_tb6612fng/grove_tb6612fng.h | 10 +++++++++- tests/components/grove_tb6612fng/common.yaml | 5 +++++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/esphome/components/grove_tb6612fng/__init__.py b/esphome/components/grove_tb6612fng/__init__.py index 210e2f7bab..27a47953b3 100644 --- a/esphome/components/grove_tb6612fng/__init__.py +++ b/esphome/components/grove_tb6612fng/__init__.py @@ -80,11 +80,9 @@ async def grove_tb6612fng_run_to_code(config, action_id, template_arg, args): template_channel = await cg.templatable(config[CONF_CHANNEL], args, int) template_speed = await cg.templatable(config[CONF_SPEED], args, cg.uint16) - template_speed = ( - template_speed if config[CONF_DIRECTION] == "FORWARD" else -template_speed - ) cg.add(var.set_channel(template_channel)) cg.add(var.set_speed(template_speed)) + cg.add(var.set_direction(config[CONF_DIRECTION] == "FORWARD")) return var diff --git a/esphome/components/grove_tb6612fng/grove_tb6612fng.h b/esphome/components/grove_tb6612fng/grove_tb6612fng.h index a36cb85cff..bf47163226 100644 --- a/esphome/components/grove_tb6612fng/grove_tb6612fng.h +++ b/esphome/components/grove_tb6612fng/grove_tb6612fng.h @@ -168,11 +168,19 @@ class GROVETB6612FNGMotorRunAction : public Action<Ts...>, public Parented<Grove TEMPLATABLE_VALUE(uint8_t, channel) TEMPLATABLE_VALUE(uint16_t, speed) + void set_direction(bool forward) { this->forward_ = forward; } + void play(const Ts &...x) override { auto channel = this->channel_.value(x...); - auto speed = this->speed_.value(x...); + int16_t speed = this->speed_.value(x...); + if (!this->forward_) { + speed = -speed; + } this->parent_->dc_motor_run(channel, speed); } + + protected: + bool forward_{true}; }; template<typename... Ts> diff --git a/tests/components/grove_tb6612fng/common.yaml b/tests/components/grove_tb6612fng/common.yaml index 52d5ead96e..7c6d65e9a6 100644 --- a/tests/components/grove_tb6612fng/common.yaml +++ b/tests/components/grove_tb6612fng/common.yaml @@ -6,6 +6,11 @@ esphome: speed: 255 direction: BACKWARD id: test_motor + - grove_tb6612fng.run: + channel: 0 + speed: !lambda "return 200;" + direction: BACKWARD + id: test_motor - grove_tb6612fng.stop: channel: 1 id: test_motor From 186525e77d127234887b6a9c05aa3a4b4136134c Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 16:57:26 -0400 Subject: [PATCH 2011/2030] [ld2420] Fix select options wrapped in extra list (#15524) --- esphome/components/ld2420/select/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/ld2420/select/__init__.py b/esphome/components/ld2420/select/__init__.py index 6ccc00b41c..3d078eba68 100644 --- a/esphome/components/ld2420/select/__init__.py +++ b/esphome/components/ld2420/select/__init__.py @@ -28,7 +28,7 @@ async def to_code(config): if operating_mode_config := config.get(CONF_OPERATING_MODE): sel = await select.new_select( operating_mode_config, - options=[CONF_SELECTS], + options=CONF_SELECTS, ) await cg.register_parented(sel, config[CONF_LD2420_ID]) cg.add(LD2420_component.set_operating_mode_select(sel)) From 687753b0bebe95b0510f32f932042d7571f7a080 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:03:55 -0400 Subject: [PATCH 2012/2030] [lightwaverf] Fix write pin using input schema instead of output (#15525) --- esphome/components/lightwaverf/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/lightwaverf/__init__.py b/esphome/components/lightwaverf/__init__.py index acbbbb4de9..46c400cb0e 100644 --- a/esphome/components/lightwaverf/__init__.py +++ b/esphome/components/lightwaverf/__init__.py @@ -28,7 +28,7 @@ CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(LIGHTWAVERFComponent), cv.Optional(CONF_READ_PIN, default=13): pins.internal_gpio_input_pin_schema, - cv.Optional(CONF_WRITE_PIN, default=14): pins.internal_gpio_input_pin_schema, + cv.Optional(CONF_WRITE_PIN, default=14): pins.internal_gpio_output_pin_schema, } ).extend(cv.polling_component_schema("1s")) From 17ec5389d88e9562eee2fcc80acdbe44b8e73cf7 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:07:28 -0400 Subject: [PATCH 2013/2030] [mcp4461] Fix terminal disable passing string where C++ expects char (#15528) --- esphome/components/mcp4461/output/__init__.py | 6 +++--- tests/components/mcp4461/common.yaml | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/esphome/components/mcp4461/output/__init__.py b/esphome/components/mcp4461/output/__init__.py index 02bdbefed5..0d145d81d3 100644 --- a/esphome/components/mcp4461/output/__init__.py +++ b/esphome/components/mcp4461/output/__init__.py @@ -48,11 +48,11 @@ async def to_code(config): config[CONF_CHANNEL], ) if not config[CONF_TERMINAL_A]: - cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], "a")) + cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], ord("a"))) if not config[CONF_TERMINAL_B]: - cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], "b")) + cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], ord("b"))) if not config[CONF_TERMINAL_W]: - cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], "w")) + cg.add(parent.initialize_terminal_disabled(config[CONF_CHANNEL], ord("w"))) if CONF_INITIAL_VALUE in config: cg.add( parent.set_initial_value(config[CONF_CHANNEL], config[CONF_INITIAL_VALUE]) diff --git a/tests/components/mcp4461/common.yaml b/tests/components/mcp4461/common.yaml index 92fd789dcb..71e2528aa4 100644 --- a/tests/components/mcp4461/common.yaml +++ b/tests/components/mcp4461/common.yaml @@ -22,3 +22,11 @@ output: id: digipot_wiper_4 mcp4461_id: mcp4461_digipot_01 channel: D + + - platform: mcp4461 + id: digipot_wiper_5 + mcp4461_id: mcp4461_digipot_01 + channel: A + terminal_a: false + terminal_b: false + terminal_w: false From d354747da041f4189c6fd17416429d9735d119c7 Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Tue, 7 Apr 2026 23:10:56 +0200 Subject: [PATCH 2014/2030] [nextion] Fix format specifiers and error message typos in command handlers (#15542) --- esphome/components/nextion/nextion.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 4a15cbe64f..6b806e0988 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -706,7 +706,7 @@ void Nextion::process_nextion_commands_() { auto index = to_process.find('\0'); if (index == std::string::npos || (to_process_length - index - 1) < 1) { ESP_LOGE(TAG, "Bad switch data (0x90)"); - ESP_LOGN(TAG, "proc: %s %zu %d", to_process.c_str(), to_process_length, index); + ESP_LOGN(TAG, "proc: %s %zu %zu", to_process.c_str(), to_process_length, index); break; } @@ -732,7 +732,7 @@ void Nextion::process_nextion_commands_() { auto index = to_process.find('\0'); if (index == std::string::npos || (to_process_length - index - 1) != 4) { ESP_LOGE(TAG, "Bad sensor data (0x91)"); - ESP_LOGN(TAG, "proc: %s %zu %d", to_process.c_str(), to_process_length, index); + ESP_LOGN(TAG, "proc: %s %zu %zu", to_process.c_str(), to_process_length, index); break; } @@ -765,7 +765,7 @@ void Nextion::process_nextion_commands_() { auto index = to_process.find('\0'); if (index == std::string::npos || (to_process_length - index - 1) < 1) { ESP_LOGE(TAG, "Bad text data (0x92)"); - ESP_LOGN(TAG, "proc: %s %zu %d", to_process.c_str(), to_process_length, index); + ESP_LOGN(TAG, "proc: %s %zu %zu", to_process.c_str(), to_process_length, index); break; } @@ -798,8 +798,8 @@ void Nextion::process_nextion_commands_() { // Get variable name auto index = to_process.find('\0'); if (index == std::string::npos || (to_process_length - index - 1) < 1) { - ESP_LOGE(TAG, "Bad binary data (0x92)"); - ESP_LOGN(TAG, "proc: %s %zu %d", to_process.c_str(), to_process_length, index); + ESP_LOGE(TAG, "Bad binary data (0x93)"); + ESP_LOGN(TAG, "proc: %s %zu %zu", to_process.c_str(), to_process_length, index); break; } From 2fe6cb392bd687c21f9967f042d7927391ba8217 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:40:43 -0400 Subject: [PATCH 2015/2030] [rotary_encoder] Fix set_value action accepting any sensor ID (#15535) --- esphome/components/rotary_encoder/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index 20c757f093..246db023f4 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -120,7 +120,7 @@ async def to_code(config): RotaryEncoderSetValueAction, cv.Schema( { - cv.Required(CONF_ID): cv.use_id(sensor.Sensor), + cv.Required(CONF_ID): cv.use_id(RotaryEncoderSensor), cv.Required(CONF_VALUE): cv.templatable(cv.int_), } ), From 4ebfe71b8fa5cc9eb8c2ce2a1db31a86182dbc3b Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:42:33 -0400 Subject: [PATCH 2016/2030] [seeed_mr24hpc1] Move baud rate validation to FINAL_VALIDATE_SCHEMA (#15536) --- esphome/components/seeed_mr24hpc1/__init__.py | 1 + esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/esphome/components/seeed_mr24hpc1/__init__.py b/esphome/components/seeed_mr24hpc1/__init__.py index e80470bde1..f71239d18c 100644 --- a/esphome/components/seeed_mr24hpc1/__init__.py +++ b/esphome/components/seeed_mr24hpc1/__init__.py @@ -33,6 +33,7 @@ CONFIG_SCHEMA = ( # This authentication mode requires that the device must have transmit and receive functionality, a parity mode of "NONE", and a stop bit of one. FINAL_VALIDATE_SCHEMA = uart.final_validate_device_schema( "seeed_mr24hpc1", + baud_rate=115200, require_tx=True, require_rx=True, parity="NONE", diff --git a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp index c9fe3a2e6e..b44c5ce83d 100644 --- a/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp +++ b/esphome/components/seeed_mr24hpc1/seeed_mr24hpc1.cpp @@ -62,8 +62,6 @@ void MR24HPC1Component::dump_config() { // Initialisation functions void MR24HPC1Component::setup() { - this->check_uart_settings(115200); - #ifdef USE_NUMBER if (this->custom_mode_number_ != nullptr) { this->custom_mode_number_->publish_state(0); // Zero out the custom mode From 3ca3cdc5e20b17b1506eff4b8dda26a453ee80cd Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:44:28 -0400 Subject: [PATCH 2017/2030] [multiple] Fix missing entity base classes in Python class declarations (#15534) --- esphome/components/bh1900nux/sensor.py | 2 +- esphome/components/gl_r01_i2c/sensor.py | 2 +- esphome/components/ld2420/select/__init__.py | 2 +- esphome/components/sdp3x/sensor.py | 5 ++++- esphome/components/sen0321/sensor.py | 2 +- esphome/components/sen21231/sensor.py | 2 +- esphome/components/tc74/sensor.py | 4 +++- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/esphome/components/bh1900nux/sensor.py b/esphome/components/bh1900nux/sensor.py index 5e1c0395af..a70db3555a 100644 --- a/esphome/components/bh1900nux/sensor.py +++ b/esphome/components/bh1900nux/sensor.py @@ -12,7 +12,7 @@ CODEOWNERS = ["@B48D81EFCC"] sensor_ns = cg.esphome_ns.namespace("bh1900nux") BH1900NUXSensor = sensor_ns.class_( - "BH1900NUXSensor", cg.PollingComponent, i2c.I2CDevice + "BH1900NUXSensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice ) CONFIG_SCHEMA = ( diff --git a/esphome/components/gl_r01_i2c/sensor.py b/esphome/components/gl_r01_i2c/sensor.py index 58db72540e..6a8d47213c 100644 --- a/esphome/components/gl_r01_i2c/sensor.py +++ b/esphome/components/gl_r01_i2c/sensor.py @@ -13,7 +13,7 @@ DEPENDENCIES = ["i2c"] gl_r01_i2c_ns = cg.esphome_ns.namespace("gl_r01_i2c") GLR01I2CComponent = gl_r01_i2c_ns.class_( - "GLR01I2CComponent", i2c.I2CDevice, cg.PollingComponent + "GLR01I2CComponent", sensor.Sensor, i2c.I2CDevice, cg.PollingComponent ) CONFIG_SCHEMA = ( diff --git a/esphome/components/ld2420/select/__init__.py b/esphome/components/ld2420/select/__init__.py index 3d078eba68..b9059c120f 100644 --- a/esphome/components/ld2420/select/__init__.py +++ b/esphome/components/ld2420/select/__init__.py @@ -12,7 +12,7 @@ CONF_SELECTS = [ "Simple", ] -LD2420Select = ld2420_ns.class_("LD2420Select", cg.Component) +LD2420Select = ld2420_ns.class_("LD2420Select", select.Select, cg.Component) CONFIG_SCHEMA = { cv.GenerateID(CONF_LD2420_ID): cv.use_id(LD2420Component), diff --git a/esphome/components/sdp3x/sensor.py b/esphome/components/sdp3x/sensor.py index 169ed374ed..be2eec7baf 100644 --- a/esphome/components/sdp3x/sensor.py +++ b/esphome/components/sdp3x/sensor.py @@ -14,7 +14,10 @@ CODEOWNERS = ["@Azimath"] sdp3x_ns = cg.esphome_ns.namespace("sdp3x") SDP3XComponent = sdp3x_ns.class_( - "SDP3XComponent", cg.PollingComponent, sensirion_common.SensirionI2CDevice + "SDP3XComponent", + sensor.Sensor, + cg.PollingComponent, + sensirion_common.SensirionI2CDevice, ) diff --git a/esphome/components/sen0321/sensor.py b/esphome/components/sen0321/sensor.py index e1c1d4e94b..3910e6e4c9 100644 --- a/esphome/components/sen0321/sensor.py +++ b/esphome/components/sen0321/sensor.py @@ -12,7 +12,7 @@ DEPENDENCIES = ["i2c"] sen0321_sensor_ns = cg.esphome_ns.namespace("sen0321_sensor") Sen0321Sensor = sen0321_sensor_ns.class_( - "Sen0321Sensor", cg.PollingComponent, i2c.I2CDevice + "Sen0321Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice ) CONFIG_SCHEMA = ( diff --git a/esphome/components/sen21231/sensor.py b/esphome/components/sen21231/sensor.py index 52cecbfb69..781a1213ac 100644 --- a/esphome/components/sen21231/sensor.py +++ b/esphome/components/sen21231/sensor.py @@ -8,7 +8,7 @@ DEPENDENCIES = ["i2c"] sen21231_sensor_ns = cg.esphome_ns.namespace("sen21231_sensor") Sen21231Sensor = sen21231_sensor_ns.class_( - "Sen21231Sensor", cg.PollingComponent, i2c.I2CDevice + "Sen21231Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice ) CONFIG_SCHEMA = ( diff --git a/esphome/components/tc74/sensor.py b/esphome/components/tc74/sensor.py index 18fc2d9a42..18a94016fb 100644 --- a/esphome/components/tc74/sensor.py +++ b/esphome/components/tc74/sensor.py @@ -11,7 +11,9 @@ CODEOWNERS = ["@sethgirvan"] DEPENDENCIES = ["i2c"] tc74_ns = cg.esphome_ns.namespace("tc74") -TC74Component = tc74_ns.class_("TC74Component", cg.PollingComponent, i2c.I2CDevice) +TC74Component = tc74_ns.class_( + "TC74Component", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) CONFIG_SCHEMA = ( sensor.sensor_schema( From 5a52936f7281a1e044c8f43833b648f8d4c826f7 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:52:33 -0400 Subject: [PATCH 2018/2030] [graph] Fix legend config incorrectly accepting a list (#15522) --- esphome/components/graph/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esphome/components/graph/__init__.py b/esphome/components/graph/__init__.py index d72fe40dd2..0749d7e2a3 100644 --- a/esphome/components/graph/__init__.py +++ b/esphome/components/graph/__init__.py @@ -110,7 +110,7 @@ GRAPH_SCHEMA = cv.Schema( cv.Optional(CONF_MIN_RANGE): cv.float_range(min=0, min_included=False), cv.Optional(CONF_MAX_RANGE): cv.float_range(min=0, min_included=False), cv.Optional(CONF_TRACES): cv.ensure_list(GRAPH_TRACE_SCHEMA), - cv.Optional(CONF_LEGEND): cv.ensure_list(GRAPH_LEGEND_SCHEMA), + cv.Optional(CONF_LEGEND): GRAPH_LEGEND_SCHEMA, } ) @@ -192,7 +192,7 @@ async def to_code(config): cg.add(var.add_trace(tr)) # Add legend if CONF_LEGEND in config: - lgd = config[CONF_LEGEND][0] + lgd = config[CONF_LEGEND] legend = cg.new_Pvariable(lgd[CONF_ID], GraphLegend()) if CONF_NAME_FONT in lgd: font = await cg.get_variable(lgd[CONF_NAME_FONT]) From 3073f3ec5c09cfff14867d140faa590000aae270 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:53:16 -0400 Subject: [PATCH 2019/2030] [haier] Fix control_method schema incorrectly using ensure_list (#15523) --- esphome/components/haier/climate.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/components/haier/climate.py b/esphome/components/haier/climate.py index d485c1d5d4..424ef46392 100644 --- a/esphome/components/haier/climate.py +++ b/esphome/components/haier/climate.py @@ -215,9 +215,7 @@ CONFIG_SCHEMA = cv.All( { cv.Optional( CONF_CONTROL_METHOD, default="SET_GROUP_PARAMETERS" - ): cv.ensure_list( - cv.enum(SUPPORTED_HON_CONTROL_METHODS, upper=True) - ), + ): cv.enum(SUPPORTED_HON_CONTROL_METHODS, upper=True), cv.Optional(CONF_BEEPER): cv.invalid( f"The {CONF_BEEPER} option is deprecated, use beeper_on/beeper_off actions or beeper switch for a haier platform instead" ), From cbcf80081b9cf5c5adf6cbcf06e930c363cecb9e Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:54:12 -0400 Subject: [PATCH 2020/2030] [pcf8563] Fix default I2C address from 8-bit (0xA3) to 7-bit (0x51) (#15526) --- esphome/components/pcf8563/time.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/pcf8563/time.py b/esphome/components/pcf8563/time.py index 0d4de3cb73..1502158c29 100644 --- a/esphome/components/pcf8563/time.py +++ b/esphome/components/pcf8563/time.py @@ -21,7 +21,7 @@ CONFIG_SCHEMA = time.TIME_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(pcf8563Component), } -).extend(i2c.i2c_device_schema(0xA3)) +).extend(i2c.i2c_device_schema(0x51)) @automation.register_action( From e7ddc6f6d39c720d5ea667f7cd76bba2858ddc34 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:54:57 -0400 Subject: [PATCH 2021/2030] [multiple] Fix validation ranges (batch 2) (#15533) --- esphome/components/dsmr/__init__.py | 2 +- esphome/components/hlk_fm22x/__init__.py | 2 +- esphome/components/micronova/button/__init__.py | 2 +- esphome/components/micronova/switch/__init__.py | 8 ++++++-- esphome/components/pca6416a/__init__.py | 2 +- esphome/components/pcf8574/__init__.py | 2 +- esphome/components/xiaomi_mue4094rt/binary_sensor.py | 8 +++++--- 7 files changed, 16 insertions(+), 10 deletions(-) diff --git a/esphome/components/dsmr/__init__.py b/esphome/components/dsmr/__init__.py index dd7f2b9f56..9c493bfcff 100644 --- a/esphome/components/dsmr/__init__.py +++ b/esphome/components/dsmr/__init__.py @@ -37,7 +37,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_GAS_MBUS_ID, default=1): cv.int_, cv.Optional(CONF_WATER_MBUS_ID, default=2): cv.int_, cv.Optional(CONF_THERMAL_MBUS_ID, default=3): cv.int_, - cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_, + cv.Optional(CONF_MAX_TELEGRAM_LENGTH, default=1500): cv.int_range(min=1), cv.Optional(CONF_REQUEST_PIN): pins.gpio_output_pin_schema, cv.Optional( CONF_REQUEST_INTERVAL, default="0ms" diff --git a/esphome/components/hlk_fm22x/__init__.py b/esphome/components/hlk_fm22x/__init__.py index 8f55d5dc08..c1aa81f6d4 100644 --- a/esphome/components/hlk_fm22x/__init__.py +++ b/esphome/components/hlk_fm22x/__init__.py @@ -131,7 +131,7 @@ async def hlk_fm22x_enroll_to_code(config, action_id, template_arg, args): cv.maybe_simple_value( { cv.GenerateID(): cv.use_id(HlkFm22xComponent), - cv.Required(CONF_FACE_ID): cv.templatable(cv.uint16_t), + cv.Required(CONF_FACE_ID): cv.templatable(cv.int_range(min=0, max=32767)), }, key=CONF_FACE_ID, ), diff --git a/esphome/components/micronova/button/__init__.py b/esphome/components/micronova/button/__init__.py index 1ef359ea6c..63b127e63d 100644 --- a/esphome/components/micronova/button/__init__.py +++ b/esphome/components/micronova/button/__init__.py @@ -28,7 +28,7 @@ CONFIG_SCHEMA = cv.Schema( is_polling_component=False, ) ) - .extend({cv.Required(CONF_MEMORY_DATA): cv.hex_int_range()}), + .extend({cv.Required(CONF_MEMORY_DATA): cv.hex_int_range(min=0x00, max=0xFF)}), } ) diff --git a/esphome/components/micronova/switch/__init__.py b/esphome/components/micronova/switch/__init__.py index d9722b5d48..e149ee3ce3 100644 --- a/esphome/components/micronova/switch/__init__.py +++ b/esphome/components/micronova/switch/__init__.py @@ -37,8 +37,12 @@ CONFIG_SCHEMA = cv.Schema( ) .extend( { - cv.Optional(CONF_MEMORY_DATA_OFF, default=0x06): cv.hex_int_range(), - cv.Optional(CONF_MEMORY_DATA_ON, default=0x01): cv.hex_int_range(), + cv.Optional(CONF_MEMORY_DATA_OFF, default=0x06): cv.hex_int_range( + min=0x00, max=0xFF + ), + cv.Optional(CONF_MEMORY_DATA_ON, default=0x01): cv.hex_int_range( + min=0x00, max=0xFF + ), } ), } diff --git a/esphome/components/pca6416a/__init__.py b/esphome/components/pca6416a/__init__.py index e540edb91f..b6e156e7ff 100644 --- a/esphome/components/pca6416a/__init__.py +++ b/esphome/components/pca6416a/__init__.py @@ -51,7 +51,7 @@ PCA6416A_PIN_SCHEMA = cv.All( { cv.GenerateID(): cv.declare_id(PCA6416AGPIOPin), cv.Required(CONF_PCA6416A): cv.use_id(PCA6416AComponent), - cv.Required(CONF_NUMBER): cv.int_range(min=0, max=16), + cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15), cv.Optional(CONF_MODE, default={}): cv.All( { cv.Optional(CONF_INPUT, default=False): cv.boolean, diff --git a/esphome/components/pcf8574/__init__.py b/esphome/components/pcf8574/__init__.py index 902efd2279..d8a1e20db6 100644 --- a/esphome/components/pcf8574/__init__.py +++ b/esphome/components/pcf8574/__init__.py @@ -55,7 +55,7 @@ def validate_mode(value): PCF8574_PIN_SCHEMA = pins.gpio_base_schema( PCF8574GPIOPin, - cv.int_range(min=0, max=17), + cv.int_range(min=0, max=15), modes=[CONF_INPUT, CONF_OUTPUT], mode_validator=validate_mode, invertible=True, diff --git a/esphome/components/xiaomi_mue4094rt/binary_sensor.py b/esphome/components/xiaomi_mue4094rt/binary_sensor.py index 911d179d8b..c5d93384c9 100644 --- a/esphome/components/xiaomi_mue4094rt/binary_sensor.py +++ b/esphome/components/xiaomi_mue4094rt/binary_sensor.py @@ -1,3 +1,4 @@ +from esphome import core import esphome.codegen as cg from esphome.components import binary_sensor, esp32_ble_tracker import esphome.config_validation as cv @@ -21,9 +22,10 @@ CONFIG_SCHEMA = cv.All( .extend( { cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional( - CONF_TIMEOUT, default="5s" - ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_TIMEOUT, default="5s"): cv.All( + cv.positive_time_period_milliseconds, + cv.Range(max=core.TimePeriod(milliseconds=65535)), + ), } ) .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) From 97ad5ab35fd0432851fdcdb0ebfa474f176fbc12 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:56:01 -0400 Subject: [PATCH 2022/2030] [udp] Fix on_receive only processing first automation (#15538) --- esphome/components/udp/__init__.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/esphome/components/udp/__init__.py b/esphome/components/udp/__init__.py index 17bbf19c9e..5dfd188f0f 100644 --- a/esphome/components/udp/__init__.py +++ b/esphome/components/udp/__init__.py @@ -130,12 +130,9 @@ async def to_code(config): if (listen_address := str(config[CONF_LISTEN_ADDRESS])) != "255.255.255.255": cg.add(var.set_listen_address(listen_address)) cg.add(var.set_addresses([str(addr) for addr in config[CONF_ADDRESSES]])) - if on_receive := config.get(CONF_ON_RECEIVE): - on_receive = on_receive[0] - trigger_id = cg.new_Pvariable(on_receive[CONF_TRIGGER_ID]) - trigger = await automation.build_automation( - trigger_id, trigger_argtype, on_receive - ) + for conf in config.get(CONF_ON_RECEIVE, []): + trigger_id = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) + trigger = await automation.build_automation(trigger_id, trigger_argtype, conf) trigger_lambda = await cg.process_lambda( trigger.trigger( cg.std_vector.template(cg.uint8)( @@ -146,6 +143,7 @@ async def to_code(config): listener_argtype, ) cg.add(var.add_listener(trigger_lambda)) + if config.get(CONF_ON_RECEIVE): cg.add(var.set_should_listen()) From 9fe4d5c63db19b0166de6be7eb1dabea4761ccef Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 17:56:50 -0400 Subject: [PATCH 2023/2030] [rp2040_pio_led_strip][rp2040_pio] Fix CUSTOM chipset crash and improve error message (#15537) --- esphome/components/rp2040_pio/__init__.py | 9 ++++++++- esphome/components/rp2040_pio_led_strip/light.py | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/rp2040_pio/__init__.py b/esphome/components/rp2040_pio/__init__.py index 4bd46731df..eecfedaa75 100644 --- a/esphome/components/rp2040_pio/__init__.py +++ b/esphome/components/rp2040_pio/__init__.py @@ -1,6 +1,7 @@ import platform import esphome.codegen as cg +import esphome.config_validation as cv DEPENDENCIES = ["rp2040"] @@ -31,7 +32,13 @@ async def to_code(config): # "earlephilhower/tool-pioasm-rp2040-earlephilhower", # ], # ) - file = PIOASM_DOWNLOADS[platform.system().lower()][platform.machine().lower()] + os_name = platform.system().lower() + arch = platform.machine().lower() + if os_name not in PIOASM_DOWNLOADS or arch not in PIOASM_DOWNLOADS[os_name]: + raise cv.Invalid( + f"pioasm is not available for {platform.system()} {platform.machine()}" + ) + file = PIOASM_DOWNLOADS[os_name][arch] cg.add_platformio_option( "platform_packages", [f"earlephilhower/tool-pioasm-rp2040-earlephilhower@{PIOASM_REPO_BASE}/{file}"], diff --git a/esphome/components/rp2040_pio_led_strip/light.py b/esphome/components/rp2040_pio_led_strip/light.py index 62f7fffdc9..274f059bd5 100644 --- a/esphome/components/rp2040_pio_led_strip/light.py +++ b/esphome/components/rp2040_pio_led_strip/light.py @@ -148,7 +148,6 @@ CHIPSETS = { "WS2812B": Chipset.CHIPSET_WS2812B, "SK6812": Chipset.CHIPSET_SK6812, "SM16703": Chipset.CHIPSET_SM16703, - "CUSTOM": Chipset.CHIPSET_CUSTOM, } From 5d31f4aeba5376e09ae7ad42025030b28404e0f8 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" <nick@koston.org> Date: Tue, 7 Apr 2026 12:00:17 -1000 Subject: [PATCH 2024/2030] [light] Use function-pointer fields in LightControlAction (#15132) --- esphome/components/light/automation.h | 61 ++++---- esphome/components/light/automation.py | 97 ++++++------ .../fixtures/light_control_action.yaml | 139 ++++++++++++++++++ .../integration/test_light_control_action.py | 95 ++++++++++++ 4 files changed, 320 insertions(+), 72 deletions(-) create mode 100644 tests/integration/fixtures/light_control_action.yaml create mode 100644 tests/integration/test_light_control_action.py diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index 2854bc62d9..a5c9220a23 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -24,46 +24,51 @@ template<typename... Ts> class ToggleAction : public Action<Ts...> { LightState *state_; }; +/// Compact light control action — each field is a function pointer (nullptr = unset). +/// Codegen wraps constants in stateless lambdas. 72 bytes vs 128 with TemplatableValue. template<typename... Ts> class LightControlAction : public Action<Ts...> { public: explicit LightControlAction(LightState *parent) : parent_(parent) {} - TEMPLATABLE_VALUE(ColorMode, color_mode) - TEMPLATABLE_VALUE(bool, state) - TEMPLATABLE_VALUE(uint32_t, transition_length) - TEMPLATABLE_VALUE(uint32_t, flash_length) - TEMPLATABLE_VALUE(float, brightness) - TEMPLATABLE_VALUE(float, color_brightness) - TEMPLATABLE_VALUE(float, red) - TEMPLATABLE_VALUE(float, green) - TEMPLATABLE_VALUE(float, blue) - TEMPLATABLE_VALUE(float, white) - TEMPLATABLE_VALUE(float, color_temperature) - TEMPLATABLE_VALUE(float, cold_white) - TEMPLATABLE_VALUE(float, warm_white) - TEMPLATABLE_VALUE(uint32_t, effect) +#define LIGHT_CONTROL_FIELDS(X) \ + X(ColorMode, color_mode) \ + X(bool, state) \ + X(uint32_t, transition_length) \ + X(uint32_t, flash_length) \ + X(float, brightness) \ + X(float, color_brightness) \ + X(float, red) \ + X(float, green) \ + X(float, blue) \ + X(float, white) \ + X(float, color_temperature) \ + X(float, cold_white) \ + X(float, warm_white) \ + X(uint32_t, effect) + +#define LIGHT_FIELD_SETTER_(type, name) \ + void set_##name(type (*f)(Ts...)) { this->name##_ = f; } +#define LIGHT_FIELD_APPLY_(type, name) \ + if (this->name##_) \ + call.set_##name(this->name##_(x...)); +#define LIGHT_FIELD_DECL_(type, name) type (*name##_)(Ts...){nullptr}; + + LIGHT_CONTROL_FIELDS(LIGHT_FIELD_SETTER_) void play(const Ts &...x) override { auto call = this->parent_->make_call(); - call.set_color_mode(this->color_mode_.optional_value(x...)); - call.set_state(this->state_.optional_value(x...)); - call.set_brightness(this->brightness_.optional_value(x...)); - call.set_color_brightness(this->color_brightness_.optional_value(x...)); - call.set_red(this->red_.optional_value(x...)); - call.set_green(this->green_.optional_value(x...)); - call.set_blue(this->blue_.optional_value(x...)); - call.set_white(this->white_.optional_value(x...)); - call.set_color_temperature(this->color_temperature_.optional_value(x...)); - call.set_cold_white(this->cold_white_.optional_value(x...)); - call.set_warm_white(this->warm_white_.optional_value(x...)); - call.set_effect(this->effect_.optional_value(x...)); - call.set_flash_length(this->flash_length_.optional_value(x...)); - call.set_transition_length(this->transition_length_.optional_value(x...)); + LIGHT_CONTROL_FIELDS(LIGHT_FIELD_APPLY_) call.perform(); } protected: LightState *parent_; + LIGHT_CONTROL_FIELDS(LIGHT_FIELD_DECL_) + +#undef LIGHT_FIELD_DECL_ +#undef LIGHT_FIELD_APPLY_ +#undef LIGHT_FIELD_SETTER_ +#undef LIGHT_CONTROL_FIELDS }; template<typename... Ts> class DimRelativeAction : public Action<Ts...> { diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 16e7d72f6b..365a64584c 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -1,3 +1,5 @@ +from typing import Any + from esphome import automation import esphome.codegen as cg from esphome.config import path_context @@ -28,7 +30,7 @@ from esphome.const import ( ) from esphome.core import CORE, EsphomeError, Lambda from esphome.cpp_generator import LambdaExpression -from esphome.types import ConfigType +from esphome.types import ConfigType, SafeExpType from .types import ( COLOR_MODES, @@ -141,6 +143,28 @@ LIGHT_TURN_ON_ACTION_SCHEMA = automation.maybe_simple_id( ) +async def _as_lambda( + value: Any, + args: list[tuple[SafeExpType, str]], + output_type: SafeExpType, +) -> LambdaExpression: + """Return a stateless lambda expression for a templatable value. + + If value is already a lambda, process it normally. Otherwise wrap + the constant in a ``[](...) -> T { return <value>; }`` expression + so that LightControlAction can store every field as a plain + function pointer. + """ + if cg.is_template(value): + return await cg.process_lambda(value, args, return_type=output_type) + return LambdaExpression( + f"return {cg.safe_exp(value)};", + args, + capture="", + return_type=output_type, + ) + + def _resolve_effect_index(config: ConfigType) -> int: """Resolve a static effect name to its 1-based index at codegen time. @@ -179,47 +203,29 @@ def _resolve_effect_index(config: ConfigType) -> int: async def light_control_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 CONF_COLOR_MODE in config: - template_ = await cg.templatable(config[CONF_COLOR_MODE], args, ColorMode) - cg.add(var.set_color_mode(template_)) - if CONF_STATE in config: - template_ = await cg.templatable(config[CONF_STATE], args, bool) - cg.add(var.set_state(template_)) - if CONF_TRANSITION_LENGTH in config: - template_ = await cg.templatable( - config[CONF_TRANSITION_LENGTH], args, cg.uint32 - ) - cg.add(var.set_transition_length(template_)) - if CONF_FLASH_LENGTH in config: - template_ = await cg.templatable(config[CONF_FLASH_LENGTH], args, cg.uint32) - cg.add(var.set_flash_length(template_)) - if CONF_BRIGHTNESS in config: - template_ = await cg.templatable(config[CONF_BRIGHTNESS], args, float) - cg.add(var.set_brightness(template_)) - if CONF_COLOR_BRIGHTNESS in config: - template_ = await cg.templatable(config[CONF_COLOR_BRIGHTNESS], args, float) - cg.add(var.set_color_brightness(template_)) - if CONF_RED in config: - template_ = await cg.templatable(config[CONF_RED], args, float) - cg.add(var.set_red(template_)) - if CONF_GREEN in config: - template_ = await cg.templatable(config[CONF_GREEN], args, float) - cg.add(var.set_green(template_)) - if CONF_BLUE in config: - template_ = await cg.templatable(config[CONF_BLUE], args, float) - cg.add(var.set_blue(template_)) - if CONF_WHITE in config: - template_ = await cg.templatable(config[CONF_WHITE], args, float) - cg.add(var.set_white(template_)) - if CONF_COLOR_TEMPERATURE in config: - template_ = await cg.templatable(config[CONF_COLOR_TEMPERATURE], args, float) - cg.add(var.set_color_temperature(template_)) - if CONF_COLD_WHITE in config: - template_ = await cg.templatable(config[CONF_COLD_WHITE], args, float) - cg.add(var.set_cold_white(template_)) - if CONF_WARM_WHITE in config: - template_ = await cg.templatable(config[CONF_WARM_WHITE], args, float) - cg.add(var.set_warm_white(template_)) + + # (config_key, setter_name, c++ type) + FIELDS = ( + (CONF_COLOR_MODE, "set_color_mode", ColorMode), + (CONF_STATE, "set_state", bool), + (CONF_TRANSITION_LENGTH, "set_transition_length", cg.uint32), + (CONF_FLASH_LENGTH, "set_flash_length", cg.uint32), + (CONF_BRIGHTNESS, "set_brightness", float), + (CONF_COLOR_BRIGHTNESS, "set_color_brightness", float), + (CONF_RED, "set_red", float), + (CONF_GREEN, "set_green", float), + (CONF_BLUE, "set_blue", float), + (CONF_WHITE, "set_white", float), + (CONF_COLOR_TEMPERATURE, "set_color_temperature", float), + (CONF_COLD_WHITE, "set_cold_white", float), + (CONF_WARM_WHITE, "set_warm_white", float), + ) + for conf_key, setter, type_ in FIELDS: + if conf_key in config: + cg.add( + getattr(var, setter)(await _as_lambda(config[conf_key], args, type_)) + ) + if CONF_EFFECT in config: if isinstance(config[CONF_EFFECT], Lambda): # Lambda returns a string — wrap in a C++ lambda that resolves @@ -242,8 +248,11 @@ async def light_control_to_code(config, action_id, template_arg, args): cg.add(var.set_effect(wrapper)) else: # Static string — resolve effect name to index at codegen time - effect_index = _resolve_effect_index(config) - cg.add(var.set_effect(effect_index)) + cg.add( + var.set_effect( + await _as_lambda(_resolve_effect_index(config), args, cg.uint32) + ) + ) return var diff --git a/tests/integration/fixtures/light_control_action.yaml b/tests/integration/fixtures/light_control_action.yaml new file mode 100644 index 0000000000..66f0cf1873 --- /dev/null +++ b/tests/integration/fixtures/light_control_action.yaml @@ -0,0 +1,139 @@ +esphome: + name: light-control-action-test +host: +api: # Port will be automatically injected +logger: + level: DEBUG + +globals: + - id: test_brightness + type: float + initial_value: "0.75" + +output: + - platform: template + id: test_red + type: float + write_action: + - lambda: "" + - platform: template + id: test_green + type: float + write_action: + - lambda: "" + - platform: template + id: test_blue + type: float + write_action: + - lambda: "" + - platform: template + id: test_cold_white + type: float + write_action: + - lambda: "" + - platform: template + id: test_warm_white + type: float + write_action: + - lambda: "" + +light: + - platform: rgbww + name: "Test Light" + id: test_light + red: test_red + green: test_green + blue: test_blue + cold_white: test_cold_white + warm_white: test_warm_white + cold_white_color_temperature: 6536 K + warm_white_color_temperature: 2000 K + effects: + - random: + name: "Test Effect" + transition_length: 10ms + update_interval: 10ms + +button: + # Test 1: light.turn_on with RGB constants + - platform: template + id: btn_turn_on_rgb + name: "Turn On RGB" + on_press: + - light.turn_on: + id: test_light + brightness: 1.0 + red: 0.0 + green: 0.0 + blue: 1.0 + + # Test 2: light.turn_off + - platform: template + id: btn_turn_off + name: "Turn Off" + on_press: + - light.turn_off: + id: test_light + + # Test 3: light.turn_on with color_temperature + - platform: template + id: btn_turn_on_ct + name: "Turn On CT" + on_press: + - light.turn_on: + id: test_light + color_temperature: 4000 K + brightness: 0.8 + + # Test 4: light.turn_on with effect + - platform: template + id: btn_turn_on_effect + name: "Turn On Effect" + on_press: + - light.turn_on: + id: test_light + effect: "Test Effect" + + # Test 5: light.turn_on with effect none to clear it + - platform: template + id: btn_clear_effect + name: "Clear Effect" + on_press: + - light.turn_on: + id: test_light + effect: "None" + + # Test 6: light.control with cold/warm white + - platform: template + id: btn_control_cw + name: "Control CW" + on_press: + - light.control: + id: test_light + cold_white: 0.9 + warm_white: 0.1 + + # Test 7: light.turn_on with lambda brightness (tests lambda path) + - platform: template + id: btn_lambda_brightness + name: "Lambda Brightness" + on_press: + - light.turn_on: + id: test_light + brightness: !lambda "return id(test_brightness);" + red: 1.0 + green: 0.0 + blue: 0.0 + + # Test 8: light.turn_on with transition_length + - platform: template + id: btn_turn_on_transition + name: "Turn On Transition" + on_press: + - light.turn_on: + id: test_light + brightness: 0.5 + transition_length: 0s + red: 0.5 + green: 0.5 + blue: 0.0 diff --git a/tests/integration/test_light_control_action.py b/tests/integration/test_light_control_action.py new file mode 100644 index 0000000000..9a5c16a04d --- /dev/null +++ b/tests/integration/test_light_control_action.py @@ -0,0 +1,95 @@ +"""Integration test for LightControlAction. + +Tests that light.turn_on, light.turn_off, and light.control automation actions +work correctly with the compact per-field union storage. Exercises both constant +value and lambda paths. +""" + +import asyncio +from typing import Any + +import pytest + +from .types import APIClientConnectedFactory, RunCompiledFunction + + +@pytest.mark.asyncio +async def test_light_control_action( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + """Test LightControlAction with constants and lambdas.""" + async with run_compiled(yaml_config), api_client_connected() as client: + state_futures: dict[int, asyncio.Future[Any]] = {} + + def on_state(state: Any) -> None: + if state.key in state_futures and not state_futures[state.key].done(): + state_futures[state.key].set_result(state) + + client.subscribe_states(on_state) + + # Get entities + entities = await client.list_entities_services() + light = next(e for e in entities[0] if e.object_id == "test_light") + buttons = {e.name: e for e in entities[0] if hasattr(e, "name")} + + async def wait_for_state(key: int, timeout: float = 5.0) -> Any: + """Wait for a state change for the given entity key.""" + loop = asyncio.get_running_loop() + state_futures[key] = loop.create_future() + try: + return await asyncio.wait_for(state_futures[key], timeout) + finally: + state_futures.pop(key, None) + + async def press_and_wait(button_name: str) -> Any: + """Press a button and wait for light state change.""" + btn = buttons[button_name] + client.button_command(btn.key) + return await wait_for_state(light.key) + + # Test 1: light.turn_on with RGB constants + state = await press_and_wait("Turn On RGB") + assert state.state is True + assert state.brightness == pytest.approx(1.0) + assert state.red == pytest.approx(0.0, abs=0.01) + assert state.green == pytest.approx(0.0, abs=0.01) + assert state.blue == pytest.approx(1.0, abs=0.01) + + # Test 2: light.turn_off + state = await press_and_wait("Turn Off") + assert state.state is False + + # Test 3: light.turn_on with color_temperature + state = await press_and_wait("Turn On CT") + assert state.state is True + assert state.brightness == pytest.approx(0.8) + assert state.color_temperature == pytest.approx(250.0) # 4000K = 250 mireds + + # Test 4: light.turn_on with effect + state = await press_and_wait("Turn On Effect") + assert state.effect == "Test Effect" + + # Test 5: Clear effect + state = await press_and_wait("Clear Effect") + assert state.effect == "None" + + # Test 6: light.control with cold/warm white + state = await press_and_wait("Control CW") + assert state.cold_white == pytest.approx(0.9, abs=0.1) + assert state.warm_white == pytest.approx(0.1, abs=0.1) + + # Test 7: light.turn_on with lambda brightness + # The global test_brightness is 0.75 + state = await press_and_wait("Lambda Brightness") + assert state.state is True + assert state.brightness == pytest.approx(0.75, abs=0.05) + assert state.red == pytest.approx(1.0, abs=0.01) + assert state.green == pytest.approx(0.0, abs=0.01) + assert state.blue == pytest.approx(0.0, abs=0.01) + + # Test 8: light.turn_on with transition_length and brightness + state = await press_and_wait("Turn On Transition") + assert state.state is True + assert state.brightness == pytest.approx(0.5) From ee7b38504b936b5bae5a9666c25a50e3329fb92b Mon Sep 17 00:00:00 2001 From: Edward Firmo <94725493+edwardtfn@users.noreply.github.com> Date: Wed, 8 Apr 2026 00:13:58 +0200 Subject: [PATCH 2025/2030] [nextion] Expose custom protocol frames as automation triggers (#13248) Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- esphome/components/nextion/automation.h | 3 + esphome/components/nextion/base_component.py | 4 ++ esphome/components/nextion/display.py | 41 ++++++++++++ esphome/components/nextion/nextion.cpp | 20 ++++++ esphome/components/nextion/nextion.h | 66 ++++++++++++++++++++ esphome/core/defines.h | 4 ++ tests/components/nextion/common.yaml | 27 +++++++- 7 files changed, 164 insertions(+), 1 deletion(-) diff --git a/esphome/components/nextion/automation.h b/esphome/components/nextion/automation.h index 17f6c77e17..e039dae615 100644 --- a/esphome/components/nextion/automation.h +++ b/esphome/components/nextion/automation.h @@ -1,5 +1,8 @@ #pragma once + #include "esphome/core/automation.h" +#include "esphome/core/string_ref.h" + #include "nextion.h" namespace esphome::nextion { diff --git a/esphome/components/nextion/base_component.py b/esphome/components/nextion/base_component.py index 7705b21b0b..74a50a95d4 100644 --- a/esphome/components/nextion/base_component.py +++ b/esphome/components/nextion/base_component.py @@ -19,6 +19,10 @@ CONF_MAX_COMMANDS_PER_LOOP = "max_commands_per_loop" CONF_MAX_QUEUE_AGE = "max_queue_age" CONF_MAX_QUEUE_SIZE = "max_queue_size" CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow" +CONF_ON_CUSTOM_BINARY_SENSOR = "on_custom_binary_sensor" +CONF_ON_CUSTOM_SENSOR = "on_custom_sensor" +CONF_ON_CUSTOM_SWITCH = "on_custom_switch" +CONF_ON_CUSTOM_TEXT_SENSOR = "on_custom_text_sensor" CONF_ON_PAGE = "on_page" CONF_ON_SETUP = "on_setup" CONF_ON_SLEEP = "on_sleep" diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index e477ab7182..4d42898a10 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -20,6 +20,10 @@ from .base_component import ( CONF_MAX_QUEUE_AGE, CONF_MAX_QUEUE_SIZE, CONF_ON_BUFFER_OVERFLOW, + CONF_ON_CUSTOM_BINARY_SENSOR, + CONF_ON_CUSTOM_SENSOR, + CONF_ON_CUSTOM_SWITCH, + CONF_ON_CUSTOM_TEXT_SENSOR, CONF_ON_PAGE, CONF_ON_SETUP, CONF_ON_SLEEP, @@ -88,6 +92,12 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_MAX_COMMANDS_PER_LOOP): cv.uint16_t, cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int, cv.Optional(CONF_ON_BUFFER_OVERFLOW): automation.validate_automation({}), + cv.Optional(CONF_ON_CUSTOM_BINARY_SENSOR): automation.validate_automation( + {} + ), + cv.Optional(CONF_ON_CUSTOM_SENSOR): automation.validate_automation({}), + cv.Optional(CONF_ON_CUSTOM_SWITCH): automation.validate_automation({}), + cv.Optional(CONF_ON_CUSTOM_TEXT_SENSOR): automation.validate_automation({}), cv.Optional(CONF_ON_PAGE): automation.validate_automation({}), cv.Optional(CONF_ON_SETUP): automation.validate_automation({}), cv.Optional(CONF_ON_SLEEP): automation.validate_automation({}), @@ -163,8 +173,36 @@ _CALLBACK_AUTOMATIONS = ( automation.CallbackAutomation( CONF_ON_BUFFER_OVERFLOW, "add_buffer_overflow_event_callback" ), + automation.CallbackAutomation( + CONF_ON_CUSTOM_BINARY_SENSOR, + "add_custom_binary_sensor_callback", + [(cg.StringRef, "key"), (cg.bool_, "value")], + ), + automation.CallbackAutomation( + CONF_ON_CUSTOM_SENSOR, + "add_custom_sensor_callback", + [(cg.StringRef, "key"), (cg.int32, "value")], + ), + automation.CallbackAutomation( + CONF_ON_CUSTOM_SWITCH, + "add_custom_switch_callback", + [(cg.StringRef, "key"), (cg.bool_, "value")], + ), + automation.CallbackAutomation( + CONF_ON_CUSTOM_TEXT_SENSOR, + "add_custom_text_sensor_callback", + [(cg.StringRef, "key"), (cg.StringRef, "value")], + ), ) +# Map custom trigger config keys to their conditional defines +_CUSTOM_TRIGGER_DEFINES = { + CONF_ON_CUSTOM_BINARY_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR", + CONF_ON_CUSTOM_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_SENSOR", + CONF_ON_CUSTOM_SWITCH: "USE_NEXTION_TRIGGER_CUSTOM_SWITCH", + CONF_ON_CUSTOM_TEXT_SENSOR: "USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR", +} + async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) @@ -253,5 +291,8 @@ async def to_code(config): cg.add(var.set_max_commands_per_loop(max_commands_per_loop)) await display.register_display(var, config) + for conf_key, define_name in _CUSTOM_TRIGGER_DEFINES.items(): + if config.get(conf_key): + cg.add_define(define_name) await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) diff --git a/esphome/components/nextion/nextion.cpp b/esphome/components/nextion/nextion.cpp index 6b806e0988..b0e14b5ea3 100644 --- a/esphome/components/nextion/nextion.cpp +++ b/esphome/components/nextion/nextion.cpp @@ -1,8 +1,11 @@ #include "nextion.h" + #include <cinttypes> + #include "esphome/core/application.h" #include "esphome/core/helpers.h" #include "esphome/core/log.h" +#include "esphome/core/string_ref.h" #include "esphome/core/util.h" namespace esphome::nextion { @@ -715,6 +718,10 @@ void Nextion::process_nextion_commands_() { ESP_LOGN(TAG, "Switch %s: %s", ONOFF(to_process[index] != 0), variable_name.c_str()); +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH + this->custom_switch_callback_.call(StringRef(variable_name), to_process[index] != 0); +#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH + for (auto *switchtype : this->switchtype_) { switchtype->process_bool(variable_name, to_process[index] != 0); } @@ -744,6 +751,10 @@ void Nextion::process_nextion_commands_() { ESP_LOGN(TAG, "Sensor: %s=%d", variable_name.c_str(), value); +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR + this->custom_sensor_callback_.call(StringRef(variable_name), value); +#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR + for (auto *sensor : this->sensortype_) { sensor->process_sensor(variable_name, value); } @@ -781,6 +792,11 @@ void Nextion::process_nextion_commands_() { // nq->variable_name = variable_name; // nq->state = text_value; // this->textsensorq_.push_back(nq); + +#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR + this->custom_text_sensor_callback_.call(StringRef(variable_name), StringRef(text_value)); +#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR + for (auto *textsensortype : this->textsensortype_) { textsensortype->process_text(variable_name, text_value); } @@ -808,6 +824,10 @@ void Nextion::process_nextion_commands_() { ESP_LOGN(TAG, "Binary sensor: %s=%s", variable_name.c_str(), ONOFF(to_process[index] != 0)); +#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR + this->custom_binary_sensor_callback_.call(StringRef(variable_name), to_process[index] != 0); +#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR + for (auto *binarysensortype : this->binarysensortype_) { binarysensortype->process_bool(&variable_name[0], to_process[index] != 0); } diff --git a/esphome/components/nextion/nextion.h b/esphome/components/nextion/nextion.h index d910389289..c84a5cd49c 100644 --- a/esphome/components/nextion/nextion.h +++ b/esphome/components/nextion/nextion.h @@ -7,6 +7,7 @@ #include "esphome/components/display/display_color_utils.h" #include "esphome/components/uart/uart.h" #include "esphome/core/defines.h" +#include "esphome/core/string_ref.h" #include "esphome/core/time.h" #ifdef USE_NEXTION_WAVEFORM @@ -1183,6 +1184,59 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe this->buffer_overflow_callback_.add(std::forward<F>(callback)); } + // Callbacks for Nextion "custom protocol" frames (0x90..0x93) +#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR + /** Add a callback to be notified when Nextion sends a custom binary sensor protocol frame (0x93). + * + * This callback is invoked when a Nextion custom binary sensor frame is received, + * providing the component name as the key and the decoded boolean value. + * + * @param callback The void(const StringRef &key, bool value) callback. + */ + template<typename F> void add_custom_binary_sensor_callback(F &&callback) { + this->custom_binary_sensor_callback_.add(std::forward<F>(callback)); + } +#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR + +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR + /** Add a callback to be notified when Nextion sends a custom sensor protocol frame (0x91). + * + * This callback is invoked when a Nextion custom sensor frame is received, + * providing the component name as the key and the decoded integer value. + * + * @param callback The void(StringRef key, int32_t value) callback. + */ + template<typename F> void add_custom_sensor_callback(F &&callback) { + this->custom_sensor_callback_.add(std::forward<F>(callback)); + } +#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR + +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH + /** Add a callback to be notified when Nextion sends a custom switch protocol frame (0x90). + * + * This callback is invoked when a Nextion custom switch frame is received, + * providing the component name as the key and the decoded boolean value. + * + * @param callback The void(const StringRef &key, bool value) callback. + */ + template<typename F> void add_custom_switch_callback(F &&callback) { + this->custom_switch_callback_.add(std::forward<F>(callback)); + } +#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH + +#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR + /** Add a callback to be notified when Nextion sends a custom text sensor protocol frame (0x92). + * + * This callback is invoked when a Nextion custom text sensor frame is received, + * providing the component name as the key and the decoded text value. + * + * @param callback The void(const StringRef &key, const StringRef &value) callback. + */ + template<typename F> void add_custom_text_sensor_callback(F &&callback) { + this->custom_text_sensor_callback_.add(std::forward<F>(callback)); + } +#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR + void update_all_components(); /** @@ -1535,6 +1589,18 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe CallbackManager<void(uint8_t)> page_callback_{}; CallbackManager<void(uint8_t, uint8_t, bool)> touch_callback_{}; CallbackManager<void()> buffer_overflow_callback_{}; +#ifdef USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR + CallbackManager<void(StringRef, bool)> custom_binary_sensor_callback_{}; +#endif // USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SENSOR + CallbackManager<void(StringRef, int32_t)> custom_sensor_callback_{}; +#endif // USE_NEXTION_TRIGGER_CUSTOM_SENSOR +#ifdef USE_NEXTION_TRIGGER_CUSTOM_SWITCH + CallbackManager<void(StringRef, bool)> custom_switch_callback_{}; +#endif // USE_NEXTION_TRIGGER_CUSTOM_SWITCH +#ifdef USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR + CallbackManager<void(StringRef, StringRef)> custom_text_sensor_callback_{}; +#endif // USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR nextion_writer_t writer_; optional<float> brightness_; diff --git a/esphome/core/defines.h b/esphome/core/defines.h index 9c90790f3a..4939c194e3 100644 --- a/esphome/core/defines.h +++ b/esphome/core/defines.h @@ -123,6 +123,10 @@ #define USE_NEXTION_MAX_COMMANDS_PER_LOOP #define USE_NEXTION_MAX_QUEUE_SIZE #define USE_NEXTION_TFT_UPLOAD +#define USE_NEXTION_TRIGGER_CUSTOM_BINARY_SENSOR +#define USE_NEXTION_TRIGGER_CUSTOM_SENSOR +#define USE_NEXTION_TRIGGER_CUSTOM_SWITCH +#define USE_NEXTION_TRIGGER_CUSTOM_TEXT_SENSOR #define USE_NEXTION_WAVEFORM #define USE_NUMBER #define USE_OUTPUT diff --git a/tests/components/nextion/common.yaml b/tests/components/nextion/common.yaml index d9493db50c..0616b9a41a 100644 --- a/tests/components/nextion/common.yaml +++ b/tests/components/nextion/common.yaml @@ -286,6 +286,31 @@ display: on_buffer_overflow: then: logger.log: "Nextion reported a buffer overflow!" + on_custom_text_sensor: + then: + - lambda: |- + // key: StringRef, value: StringRef + if (key == "csv") { + // parse value here, or forward to your own component + ESP_LOGD("nextion.csv", "Got CSV: %s", value.c_str()); + } + on_custom_sensor: + then: + - lambda: |- + // key: StringRef, value: int32_t + if (key == "temperature_raw") { + ESP_LOGD("nextion.custom", "%s=%d", key.c_str(), value); + } + on_custom_binary_sensor: + then: + - lambda: |- + if (key == "btn1") { + ESP_LOGD("nextion.btn", "btn1=%s", ONOFF(value)); + } + on_custom_switch: + then: + - lambda: |- + ESP_LOGD("nextion.sw", "%s=%s", key.c_str(), ONOFF(value)); on_page: then: lambda: 'ESP_LOGD("display","Display shows new page %u", x);' @@ -304,8 +329,8 @@ display: on_wake: then: lambda: 'ESP_LOGD("display","Display woke up");' - update_interval: 5s start_up_page: 1 startup_override_ms: 10000ms # Wait 10s for display ready touch_sleep_timeout: 3 + update_interval: 5s wake_up_page: 2 From 0d7f2f05b914bd7b1e3fc066af49386371a10227 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:16:37 -0400 Subject: [PATCH 2026/2030] [libretiny] Fix board pin alias resolution TypeError (#15527) --- esphome/components/libretiny/gpio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/components/libretiny/gpio.py b/esphome/components/libretiny/gpio.py index 9bad400eb7..9f8d96de24 100644 --- a/esphome/components/libretiny/gpio.py +++ b/esphome/components/libretiny/gpio.py @@ -41,7 +41,7 @@ def _lookup_board_pins(board): board_pins = component.board_pins.get(board, {}) # Resolve aliased board pins (shorthand when two boards have the same pin configuration) while isinstance(board_pins, str): - board_pins = board_pins[board_pins] + board_pins = component.board_pins[board_pins] return board_pins From 14bcdfe7004a6ea77425c0f4e5ab77af21e70827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Metrich?= <45318189+FredM67@users.noreply.github.com> Date: Wed, 8 Apr 2026 00:29:55 +0200 Subject: [PATCH 2027/2030] [emontx] emonTx component (#9027) Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: J. Nick Koston <nick@home-assistant.io> --- CODEOWNERS | 1 + esphome/components/emontx/__init__.py | 152 ++++++++++++++++++ esphome/components/emontx/emontx.cpp | 116 +++++++++++++ esphome/components/emontx/emontx.h | 69 ++++++++ esphome/components/emontx/sensor/__init__.py | 133 +++++++++++++++ .../emontx/sensor/emontx_sensor.cpp | 10 ++ .../components/emontx/sensor/emontx_sensor.h | 13 ++ tests/components/emontx/common.yaml | 25 +++ tests/components/emontx/test.esp32-idf.yaml | 4 + tests/components/emontx/test.esp8266-ard.yaml | 4 + tests/components/emontx/test.rp2040-ard.yaml | 4 + .../common/uart_115200/esp32-ard.yaml | 1 + .../common/uart_115200/esp32-c3-ard.yaml | 1 + .../common/uart_115200/esp32-c3-idf.yaml | 1 + .../common/uart_115200/esp32-idf.yaml | 1 + .../common/uart_115200/esp8266-ard.yaml | 1 + .../common/uart_115200/rp2040-ard.yaml | 1 + 17 files changed, 537 insertions(+) create mode 100644 esphome/components/emontx/__init__.py create mode 100644 esphome/components/emontx/emontx.cpp create mode 100644 esphome/components/emontx/emontx.h create mode 100644 esphome/components/emontx/sensor/__init__.py create mode 100644 esphome/components/emontx/sensor/emontx_sensor.cpp create mode 100644 esphome/components/emontx/sensor/emontx_sensor.h create mode 100644 tests/components/emontx/common.yaml create mode 100644 tests/components/emontx/test.esp32-idf.yaml create mode 100644 tests/components/emontx/test.esp8266-ard.yaml create mode 100644 tests/components/emontx/test.rp2040-ard.yaml diff --git a/CODEOWNERS b/CODEOWNERS index c466204b66..5b1ae65f1b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -148,6 +148,7 @@ esphome/components/ee895/* @Stock-M esphome/components/ektf2232/touchscreen/* @jesserockz esphome/components/emc2101/* @ellull esphome/components/emmeti/* @E440QF +esphome/components/emontx/* @FredM67 @glynhudson @TrystanLea esphome/components/ens160/* @latonita esphome/components/ens160_base/* @latonita @vincentscode esphome/components/ens160_i2c/* @latonita diff --git a/esphome/components/emontx/__init__.py b/esphome/components/emontx/__init__.py new file mode 100644 index 0000000000..a2d4349698 --- /dev/null +++ b/esphome/components/emontx/__init__.py @@ -0,0 +1,152 @@ +from dataclasses import dataclass, field + +from esphome import automation +import esphome.codegen as cg +from esphome.components import uart +import esphome.config_validation as cv +from esphome.const import ( + CONF_COMMAND, + CONF_ID, + CONF_ON_DATA, + CONF_RX_BUFFER_SIZE, + CONF_UART_ID, +) +from esphome.core import CORE +import esphome.final_validate as fv +from esphome.types import ConfigType + +AUTO_LOAD = ["json"] +CODEOWNERS = ["@FredM67", "@TrystanLea", "@glynhudson"] +DEPENDENCIES = ["uart"] + +emontx_ns = cg.esphome_ns.namespace("emontx") +EmonTx = emontx_ns.class_("EmonTx", cg.Component, uart.UARTDevice) + +# Action to send command to emonTx +EmonTxSendCommandAction = emontx_ns.class_("EmonTxSendCommandAction", automation.Action) + +CONF_EMONTX_ID = "emontx_id" +CONF_TAG_NAME = "tag_name" +CONF_ON_JSON = "on_json" + +DOMAIN = "emontx" + +MINIMUM_RX_BUFFER_SIZE = 2048 + + +@dataclass +class EmonTxData: + sensor_counts: dict[str, int] = field(default_factory=dict) + + +def _get_data() -> EmonTxData: + if DOMAIN not in CORE.data: + CORE.data[DOMAIN] = EmonTxData() + return CORE.data[DOMAIN] + + +# Main configuration schema +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(EmonTx), + cv.Optional(CONF_ON_JSON): automation.validate_automation({}), + cv.Optional(CONF_ON_DATA): automation.validate_automation({}), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) + + +def final_validate(config: ConfigType) -> ConfigType: + full_config = fv.full_config.get() + + # Count sensors registered to this hub (IDs are resolved at final_validate stage) + hub_id = str(config[CONF_ID]) + sensor_count = sum( + 1 + for s in full_config.get("sensor", []) + if s.get("platform") == "emontx" and str(s.get(CONF_EMONTX_ID)) == hub_id + ) + _get_data().sensor_counts[hub_id] = sensor_count + + # Ensure UART RX buffer size is large enough to handle data bursts from firmware + for uart_conf in full_config["uart"]: + if uart_conf[CONF_ID] == config[CONF_UART_ID]: + current_buffer_size = uart_conf[CONF_RX_BUFFER_SIZE] + if current_buffer_size < MINIMUM_RX_BUFFER_SIZE: + raise cv.Invalid( + f"Component emontx requires UART '{config[CONF_UART_ID]}' to have " + f"rx_buffer_size of at least {MINIMUM_RX_BUFFER_SIZE} bytes " + f"(currently set to {current_buffer_size} bytes). " + f"Please add 'rx_buffer_size: {MINIMUM_RX_BUFFER_SIZE}' to your uart configuration.", + path=[CONF_UART_ID], + ) + break + + # Validate UART settings + schema = uart.final_validate_device_schema( + "emontx", + baud_rate=115200, + require_tx=False, + require_rx=True, + data_bits=8, + parity="NONE", + stop_bits=1, + ) + return schema(config) + + +FINAL_VALIDATE_SCHEMA = final_validate + + +_CALLBACK_AUTOMATIONS = ( + automation.CallbackAutomation( + CONF_ON_JSON, + "add_on_json_callback", + [(cg.JsonObject, "json"), (cg.std_string, "raw_json")], + ), + automation.CallbackAutomation( + CONF_ON_DATA, "add_on_data_callback", [(cg.std_string, "data")] + ), +) + + +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await uart.register_uart_device(var, config) + + # Initialize sensor storage with count from final_validate + sensor_count = _get_data().sensor_counts.get(str(config[CONF_ID]), 0) + if sensor_count > 0: + cg.add(var.init_sensors(sensor_count)) + + await automation.build_callback_automations(var, config, _CALLBACK_AUTOMATIONS) + + +# Action: emontx.send_command + +EMONTX_SEND_COMMAND_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(EmonTx), + cv.Required(CONF_COMMAND): cv.templatable(cv.string), + } +) + + +@automation.register_action( + "emontx.send_command", + EmonTxSendCommandAction, + EMONTX_SEND_COMMAND_ACTION_SCHEMA, + synchronous=True, +) +async def emontx_send_command_action_to_code( + config: ConfigType, action_id, template_arg, args +) -> None: + var = cg.new_Pvariable(action_id, template_arg) + await cg.register_parented(var, config[CONF_ID]) + template_ = await cg.templatable(config[CONF_COMMAND], args, cg.std_string) + cg.add(var.set_command(template_)) + return var diff --git a/esphome/components/emontx/emontx.cpp b/esphome/components/emontx/emontx.cpp new file mode 100644 index 0000000000..7a1b084fe0 --- /dev/null +++ b/esphome/components/emontx/emontx.cpp @@ -0,0 +1,116 @@ +#include "emontx.h" +#include "esphome/core/log.h" +#include "esphome/components/json/json_util.h" + +namespace esphome::emontx { + +static const char *const TAG = "emontx"; + +void EmonTx::setup() { this->buffer_pos_ = 0; } + +/** + * @brief Implements the main loop for parsing data from the serial port. + * + * @details Continuously processes incoming UART data line-by-line: + * 1. Fire on_data callbacks for all received lines + * 2. If line starts with '{', parse as JSON and update sensors/callbacks + */ +void EmonTx::loop() { + // Read all available data to prevent UART buffer overflow + while (this->available() > 0) { + uint8_t received = this->read(); + + if (received == '\r') { + continue; // Ignore CR + } else if (received == '\n') { + // End of line - process the buffer + if (this->buffer_pos_ > 0) { + // Null-terminate for safe logging and c_str() use + size_t len = this->buffer_pos_; + this->buffer_[len] = '\0'; + this->buffer_pos_ = 0; + + StringRef line(this->buffer_.data(), len); + ESP_LOGD(TAG, "Received line: %s", line.c_str()); + + // Fire data callbacks for all received lines + this->data_callbacks_.call(line); + + // Check if this line is JSON (starts with '{') + if (this->buffer_[0] == '{') { + ESP_LOGV(TAG, "Line is JSON, parsing..."); + this->parse_json_(this->buffer_.data(), len); + } + } + } else if (this->buffer_pos_ >= MAX_LINE_LENGTH) { + ESP_LOGW(TAG, "Buffer overflow (>%zu bytes), discarding buffer", MAX_LINE_LENGTH); + this->buffer_pos_ = 0; + } else { + this->buffer_[this->buffer_pos_++] = static_cast<char>(received); + } + } +} + +void EmonTx::parse_json_(const char *data, size_t len) { + bool success = json::parse_json(reinterpret_cast<const uint8_t *>(data), len, [this, data, len](JsonObject root) { +#ifdef USE_SENSOR + for (auto &sensor_pair : this->sensors_) { + auto val = root[sensor_pair.first]; + if (val.is<JsonVariant>()) { + float value = val; + ESP_LOGV(TAG, "Updating sensor '%s' with value: %.2f", sensor_pair.first, value); + sensor_pair.second->publish_state(value); + } + } +#endif + + this->json_callbacks_.call(root, StringRef(data, len)); + return true; + }); + + if (!success) { + ESP_LOGW(TAG, "Failed to parse JSON"); + } +} + +/** + * @brief Logs the EmonTx component configuration details. + */ +void EmonTx::dump_config() { + ESP_LOGCONFIG(TAG, "EmonTx:"); + +#ifdef USE_SENSOR + ESP_LOGCONFIG(TAG, " Registered sensors: %zu", this->sensors_.size()); + for (const auto &sensor_pair : this->sensors_) { + ESP_LOGCONFIG(TAG, " Sensor: %s", sensor_pair.first); + } +#else + ESP_LOGCONFIG(TAG, " Sensor support: DISABLED"); +#endif +} + +/** + * @brief Sends a command string to the emonTx device via UART. + * + * @param command The command string to send (LF will be appended automatically). + */ +void EmonTx::send_command(const std::string &command) { + ESP_LOGD(TAG, "Sending command to emonTx: %s", command.c_str()); + this->write_str(command.c_str()); + this->write_byte('\n'); +} + +#ifdef USE_SENSOR +/** + * @brief Registers a sensor to receive updates for a specific JSON tag. + * + * @param tag_name The JSON key to monitor for this sensor (must be a string literal). + * @param sensor Pointer to the sensor that will receive value updates. + */ +void EmonTx::register_sensor(const char *tag_name, sensor::Sensor *sensor) { + ESP_LOGCONFIG(TAG, "Registering sensor for tag: %s", tag_name); + this->sensors_.emplace_back(tag_name, sensor); +} +#endif + +} // namespace esphome::emontx diff --git a/esphome/components/emontx/emontx.h b/esphome/components/emontx/emontx.h new file mode 100644 index 0000000000..67e7f5bffc --- /dev/null +++ b/esphome/components/emontx/emontx.h @@ -0,0 +1,69 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/core/automation.h" +#include "esphome/core/helpers.h" +#include "esphome/core/string_ref.h" +#include "esphome/components/uart/uart.h" +#include "esphome/components/json/json_util.h" + +#include <array> + +#ifdef USE_SENSOR +#include "esphome/components/sensor/sensor.h" +#endif + +namespace esphome::emontx { + +/// Maximum line length in bytes (plus one byte reserved for null terminator) +static constexpr size_t MAX_LINE_LENGTH = 1024; + +/** + * @class EmonTx + * @brief Main class for the EmonTx component. + * + * The EmonTx processes incoming data frames via UART, + * extracts tags and values, and publishes them to registered sensors. + */ +class EmonTx : public Component, public uart::UARTDevice { + public: + EmonTx() = default; + + void loop() override; + void setup() override; + void dump_config() override; + + template<typename F> void add_on_json_callback(F &&callback) { this->json_callbacks_.add(std::forward<F>(callback)); } + + template<typename F> void add_on_data_callback(F &&callback) { this->data_callbacks_.add(std::forward<F>(callback)); } + + // Send command to emonTx via UART + void send_command(const std::string &command); + +#ifdef USE_SENSOR + void init_sensors(size_t count) { this->sensors_.init(count); } + void register_sensor(const char *tag_name, sensor::Sensor *sensor); +#endif + + protected: + void parse_json_(const char *data, size_t len); + +#ifdef USE_SENSOR + FixedVector<std::pair<const char *, sensor::Sensor *>> sensors_{}; +#endif + LazyCallbackManager<void(JsonObject, StringRef)> json_callbacks_; + LazyCallbackManager<void(StringRef)> data_callbacks_; + uint16_t buffer_pos_{0}; + std::array<char, MAX_LINE_LENGTH + 1> buffer_{}; +}; + +// Action to send command to emonTx +template<typename... Ts> class EmonTxSendCommandAction : public Action<Ts...>, public Parented<EmonTx> { + public: + TEMPLATABLE_VALUE(std::string, command) + + void play(const Ts &...x) override { this->parent_->send_command(this->command_.value(x...)); } +}; + +} // namespace esphome::emontx diff --git a/esphome/components/emontx/sensor/__init__.py b/esphome/components/emontx/sensor/__init__.py new file mode 100644 index 0000000000..83a972c5e0 --- /dev/null +++ b/esphome/components/emontx/sensor/__init__.py @@ -0,0 +1,133 @@ +import esphome.codegen as cg +from esphome.components import sensor +import esphome.config_validation as cv +from esphome.const import ( + CONF_ACCURACY_DECIMALS, + CONF_DEVICE_CLASS, + CONF_ID, + CONF_STATE_CLASS, + CONF_UNIT_OF_MEASUREMENT, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, + STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, + UNIT_AMPERE, + UNIT_CELSIUS, + UNIT_EMPTY, + UNIT_PULSES, + UNIT_VOLT, + UNIT_WATT, + UNIT_WATT_HOURS, +) +from esphome.types import ConfigType + +from .. import CONF_EMONTX_ID, CONF_TAG_NAME, EmonTx, emontx_ns + +EmonTxSensor = emontx_ns.class_("EmonTxSensor", sensor.Sensor, cg.Component) + +# Define sensor type configurations by prefix +SENSOR_CONFIGS = { + "P": { + CONF_UNIT_OF_MEASUREMENT: UNIT_WATT, + CONF_DEVICE_CLASS: DEVICE_CLASS_POWER, + CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT, + CONF_ACCURACY_DECIMALS: 0, + }, + "E": { + CONF_UNIT_OF_MEASUREMENT: UNIT_WATT_HOURS, + CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY, + CONF_STATE_CLASS: STATE_CLASS_TOTAL_INCREASING, + CONF_ACCURACY_DECIMALS: 0, + }, + "V": { + CONF_UNIT_OF_MEASUREMENT: UNIT_VOLT, + CONF_DEVICE_CLASS: DEVICE_CLASS_VOLTAGE, + CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT, + CONF_ACCURACY_DECIMALS: 2, + }, + "I": { + CONF_UNIT_OF_MEASUREMENT: UNIT_AMPERE, + CONF_DEVICE_CLASS: DEVICE_CLASS_CURRENT, + CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT, + CONF_ACCURACY_DECIMALS: 2, + }, + "T": { + CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS, + CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, + CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT, + CONF_ACCURACY_DECIMALS: 2, + }, +} + +# Pattern-based configurations +PATTERN_CONFIGS = { + "PULSE": { + CONF_UNIT_OF_MEASUREMENT: UNIT_PULSES, + CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY, + CONF_ACCURACY_DECIMALS: 0, + }, + "PF": { + CONF_UNIT_OF_MEASUREMENT: UNIT_EMPTY, + CONF_DEVICE_CLASS: DEVICE_CLASS_POWER_FACTOR, + CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT, + CONF_ACCURACY_DECIMALS: 2, + }, +} + +# Create a base schema that's flexible for any tag +BASE_SCHEMA = sensor.sensor_schema( + EmonTxSensor, + state_class=STATE_CLASS_MEASUREMENT, + accuracy_decimals=0, +).extend( + { + cv.GenerateID(CONF_EMONTX_ID): cv.use_id(EmonTx), + cv.Required(CONF_TAG_NAME): cv.string, + } +) + + +def apply_tag_defaults(config: ConfigType) -> ConfigType: + """Apply defaults based on tag prefix if applicable, but don't restrict any tags.""" + tag = config[CONF_TAG_NAME] + + # Skip if tag is too short + if len(tag) < 2: + return config + + # Check if this tag starts with a known prefix + tag_upper = tag.upper() + + for pattern, pattern_config in PATTERN_CONFIGS.items(): + if tag_upper.startswith(pattern): + # Apply pattern defaults if not overridden by user + for key, value in pattern_config.items(): + if key not in config: + config[key] = value + return config + + # Only apply defaults for known prefixes with numeric indices + prefix = tag_upper[0] + if prefix in SENSOR_CONFIGS and len(tag) > 1 and tag[1:].isdigit(): + # Apply defaults for known tag types, but only if not overridden by user + defaults = SENSOR_CONFIGS[prefix] + for key, value in defaults.items(): + if key not in config: + config[key] = value + + return config + + +CONFIG_SCHEMA = cv.All(BASE_SCHEMA, apply_tag_defaults) + + +async def to_code(config: ConfigType) -> None: + var = cg.new_Pvariable(config[CONF_ID]) + await cg.register_component(var, config) + await sensor.register_sensor(var, config) + hub = await cg.get_variable(config[CONF_EMONTX_ID]) + cg.add(hub.register_sensor(config[CONF_TAG_NAME], var)) diff --git a/esphome/components/emontx/sensor/emontx_sensor.cpp b/esphome/components/emontx/sensor/emontx_sensor.cpp new file mode 100644 index 0000000000..142df0150e --- /dev/null +++ b/esphome/components/emontx/sensor/emontx_sensor.cpp @@ -0,0 +1,10 @@ +#include "emontx_sensor.h" +#include "esphome/core/log.h" + +namespace esphome::emontx { + +static const char *const TAG = "emontx_sensor"; + +void EmonTxSensor::dump_config() { LOG_SENSOR(" ", "EmonTx Sensor", this); } + +} // namespace esphome::emontx diff --git a/esphome/components/emontx/sensor/emontx_sensor.h b/esphome/components/emontx/sensor/emontx_sensor.h new file mode 100644 index 0000000000..9714acdf0d --- /dev/null +++ b/esphome/components/emontx/sensor/emontx_sensor.h @@ -0,0 +1,13 @@ +#pragma once + +#include "esphome/components/sensor/sensor.h" +#include "esphome/core/component.h" + +namespace esphome::emontx { + +class EmonTxSensor : public sensor::Sensor, public Component { + public: + void dump_config() override; +}; + +} // namespace esphome::emontx diff --git a/tests/components/emontx/common.yaml b/tests/components/emontx/common.yaml new file mode 100644 index 0000000000..5c25e37abb --- /dev/null +++ b/tests/components/emontx/common.yaml @@ -0,0 +1,25 @@ +button: + - platform: template + name: Send command test + on_press: + - emontx.send_command: + id: test_emontx + command: "v" + +emontx: + id: test_emontx + on_json: + - then: + - logger.log: "Got JSON" + on_data: + - then: + - logger.log: + format: "Got data: %s" + args: [data.c_str()] + +sensor: + - platform: emontx + name: Power + tag_name: P1 + emontx_id: test_emontx + unit_of_measurement: W diff --git a/tests/components/emontx/test.esp32-idf.yaml b/tests/components/emontx/test.esp32-idf.yaml new file mode 100644 index 0000000000..3a3747f3a5 --- /dev/null +++ b/tests/components/emontx/test.esp32-idf.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_115200/esp32-idf.yaml + +<<: !include common.yaml diff --git a/tests/components/emontx/test.esp8266-ard.yaml b/tests/components/emontx/test.esp8266-ard.yaml new file mode 100644 index 0000000000..31c5731589 --- /dev/null +++ b/tests/components/emontx/test.esp8266-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_115200/esp8266-ard.yaml + +<<: !include common.yaml diff --git a/tests/components/emontx/test.rp2040-ard.yaml b/tests/components/emontx/test.rp2040-ard.yaml new file mode 100644 index 0000000000..ff55e8263d --- /dev/null +++ b/tests/components/emontx/test.rp2040-ard.yaml @@ -0,0 +1,4 @@ +packages: + uart: !include ../../test_build_components/common/uart_115200/rp2040-ard.yaml + +<<: !include common.yaml diff --git a/tests/test_build_components/common/uart_115200/esp32-ard.yaml b/tests/test_build_components/common/uart_115200/esp32-ard.yaml index 9102910f31..108f12110d 100644 --- a/tests/test_build_components/common/uart_115200/esp32-ard.yaml +++ b/tests/test_build_components/common/uart_115200/esp32-ard.yaml @@ -9,3 +9,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 diff --git a/tests/test_build_components/common/uart_115200/esp32-c3-ard.yaml b/tests/test_build_components/common/uart_115200/esp32-c3-ard.yaml index 87a969c6a3..5176a4e8e2 100644 --- a/tests/test_build_components/common/uart_115200/esp32-c3-ard.yaml +++ b/tests/test_build_components/common/uart_115200/esp32-c3-ard.yaml @@ -9,3 +9,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 diff --git a/tests/test_build_components/common/uart_115200/esp32-c3-idf.yaml b/tests/test_build_components/common/uart_115200/esp32-c3-idf.yaml index f3768592e5..f61d01d206 100644 --- a/tests/test_build_components/common/uart_115200/esp32-c3-idf.yaml +++ b/tests/test_build_components/common/uart_115200/esp32-c3-idf.yaml @@ -10,3 +10,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 diff --git a/tests/test_build_components/common/uart_115200/esp32-idf.yaml b/tests/test_build_components/common/uart_115200/esp32-idf.yaml index e405f74fe7..b432d31a7e 100644 --- a/tests/test_build_components/common/uart_115200/esp32-idf.yaml +++ b/tests/test_build_components/common/uart_115200/esp32-idf.yaml @@ -10,3 +10,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 diff --git a/tests/test_build_components/common/uart_115200/esp8266-ard.yaml b/tests/test_build_components/common/uart_115200/esp8266-ard.yaml index 2dcf1c4a5d..c4b9170c2f 100644 --- a/tests/test_build_components/common/uart_115200/esp8266-ard.yaml +++ b/tests/test_build_components/common/uart_115200/esp8266-ard.yaml @@ -9,3 +9,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 diff --git a/tests/test_build_components/common/uart_115200/rp2040-ard.yaml b/tests/test_build_components/common/uart_115200/rp2040-ard.yaml index 62a7b5aed2..874b09217b 100644 --- a/tests/test_build_components/common/uart_115200/rp2040-ard.yaml +++ b/tests/test_build_components/common/uart_115200/rp2040-ard.yaml @@ -9,3 +9,4 @@ uart: tx_pin: ${tx_pin} rx_pin: ${rx_pin} baud_rate: 115200 + rx_buffer_size: 2048 From aad898503d8200600f1ec285b0444f7d38906ba2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Tue, 7 Apr 2026 18:37:17 -0400 Subject: [PATCH 2028/2030] [multiple] Fix channel/pin range validation and widen channel types (#15529) --- esphome/components/bp1658cj/output.py | 2 +- esphome/components/mcp3008/sensor/__init__.py | 2 +- esphome/components/my9231/my9231.cpp | 4 ++-- esphome/components/my9231/my9231.h | 6 +++--- esphome/components/sm16716/output.py | 2 +- esphome/components/sm2135/output.py | 2 +- esphome/components/sm2235/output.py | 2 +- esphome/components/sm2335/output.py | 2 +- esphome/components/tlc5947/output/__init__.py | 2 +- esphome/components/tlc5947/output/tlc5947_output.h | 4 ++-- esphome/components/tlc5971/output/__init__.py | 2 +- esphome/components/tlc5971/output/tlc5971_output.h | 4 ++-- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/esphome/components/bp1658cj/output.py b/esphome/components/bp1658cj/output.py index 023b6ecd1e..78cf717aba 100644 --- a/esphome/components/bp1658cj/output.py +++ b/esphome/components/bp1658cj/output.py @@ -14,7 +14,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_BP1658CJ_ID): cv.use_id(BP1658CJ), cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=4), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/mcp3008/sensor/__init__.py b/esphome/components/mcp3008/sensor/__init__.py index e85ce2955d..2576ef50e5 100644 --- a/esphome/components/mcp3008/sensor/__init__.py +++ b/esphome/components/mcp3008/sensor/__init__.py @@ -35,7 +35,7 @@ CONFIG_SCHEMA = ( .extend( { cv.GenerateID(CONF_MCP3008_ID): cv.use_id(MCP3008), - cv.Required(CONF_NUMBER): cv.int_, + cv.Required(CONF_NUMBER): cv.int_range(min=0, max=7), cv.Optional(CONF_REFERENCE_VOLTAGE, default="3.3V"): cv.voltage, } ) diff --git a/esphome/components/my9231/my9231.cpp b/esphome/components/my9231/my9231.cpp index 5b77a49e72..25f7e6925d 100644 --- a/esphome/components/my9231/my9231.cpp +++ b/esphome/components/my9231/my9231.cpp @@ -81,9 +81,9 @@ void MY9231OutputComponent::loop() { } this->update_ = false; } -void MY9231OutputComponent::set_channel_value_(uint8_t channel, uint16_t value) { +void MY9231OutputComponent::set_channel_value_(uint16_t channel, uint16_t value) { ESP_LOGV(TAG, "set channels %u to %u", channel, value); - uint8_t index = this->num_channels_ - channel - 1; + uint16_t index = this->num_channels_ - channel - 1; if (this->pwm_amounts_[index] != value) { this->update_ = true; } diff --git a/esphome/components/my9231/my9231.h b/esphome/components/my9231/my9231.h index 77c1259853..dff68d247c 100644 --- a/esphome/components/my9231/my9231.h +++ b/esphome/components/my9231/my9231.h @@ -30,7 +30,7 @@ class MY9231OutputComponent : public Component { class Channel : public output::FloatOutput { public: void set_parent(MY9231OutputComponent *parent) { parent_ = parent; } - void set_channel(uint8_t channel) { channel_ = channel; } + void set_channel(uint16_t channel) { channel_ = channel; } protected: void write_state(float state) override { @@ -39,13 +39,13 @@ class MY9231OutputComponent : public Component { } MY9231OutputComponent *parent_; - uint8_t channel_; + uint16_t channel_; }; protected: uint16_t get_max_amount_() const { return (uint32_t(1) << this->bit_depth_) - 1; } - void set_channel_value_(uint8_t channel, uint16_t value); + void set_channel_value_(uint16_t channel, uint16_t value); void init_chips_(uint8_t command); void write_word_(uint16_t value, uint8_t bits); void send_di_pulses_(uint8_t count); diff --git a/esphome/components/sm16716/output.py b/esphome/components/sm16716/output.py index 50f6ec759f..2cfc38f5cc 100644 --- a/esphome/components/sm16716/output.py +++ b/esphome/components/sm16716/output.py @@ -14,7 +14,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_SM16716_ID): cv.use_id(SM16716), cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=254), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/sm2135/output.py b/esphome/components/sm2135/output.py index 71c4af2253..a4ac7fc7da 100644 --- a/esphome/components/sm2135/output.py +++ b/esphome/components/sm2135/output.py @@ -15,7 +15,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_SM2135_ID): cv.use_id(SM2135), cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=4), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/sm2235/output.py b/esphome/components/sm2235/output.py index 2a9698d645..b17af2b1e0 100644 --- a/esphome/components/sm2235/output.py +++ b/esphome/components/sm2235/output.py @@ -15,7 +15,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_SM2235_ID): cv.use_id(SM2235), cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=4), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/sm2335/output.py b/esphome/components/sm2335/output.py index ef7fec7307..7fd00917bd 100644 --- a/esphome/components/sm2335/output.py +++ b/esphome/components/sm2335/output.py @@ -15,7 +15,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_SM2335_ID): cv.use_id(SM2335), cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=4), } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/tlc5947/output/__init__.py b/esphome/components/tlc5947/output/__init__.py index a1290add81..6bea1546d3 100644 --- a/esphome/components/tlc5947/output/__init__.py +++ b/esphome/components/tlc5947/output/__init__.py @@ -16,7 +16,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_TLC5947_ID): cv.use_id(TLC5947), cv.Required(CONF_ID): cv.declare_id(TLC5947Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.uint16_t, } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/tlc5947/output/tlc5947_output.h b/esphome/components/tlc5947/output/tlc5947_output.h index 5b2c51020c..0faec96acb 100644 --- a/esphome/components/tlc5947/output/tlc5947_output.h +++ b/esphome/components/tlc5947/output/tlc5947_output.h @@ -11,11 +11,11 @@ namespace tlc5947 { class TLC5947Channel : public output::FloatOutput, public Parented<TLC5947> { public: - void set_channel(uint8_t channel) { this->channel_ = channel; } + void set_channel(uint16_t channel) { this->channel_ = channel; } protected: void write_state(float state) override; - uint8_t channel_; + uint16_t channel_; }; } // namespace tlc5947 diff --git a/esphome/components/tlc5971/output/__init__.py b/esphome/components/tlc5971/output/__init__.py index ae000ae0a9..854fbbd810 100644 --- a/esphome/components/tlc5971/output/__init__.py +++ b/esphome/components/tlc5971/output/__init__.py @@ -16,7 +16,7 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( { cv.GenerateID(CONF_TLC5971_ID): cv.use_id(TLC5971), cv.Required(CONF_ID): cv.declare_id(TLC5971Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + cv.Required(CONF_CHANNEL): cv.uint16_t, } ).extend(cv.COMPONENT_SCHEMA) diff --git a/esphome/components/tlc5971/output/tlc5971_output.h b/esphome/components/tlc5971/output/tlc5971_output.h index 944ee19b2d..ca3099e7b2 100644 --- a/esphome/components/tlc5971/output/tlc5971_output.h +++ b/esphome/components/tlc5971/output/tlc5971_output.h @@ -11,11 +11,11 @@ namespace tlc5971 { class TLC5971Channel : public output::FloatOutput, public Parented<TLC5971> { public: - void set_channel(uint8_t channel) { this->channel_ = channel; } + void set_channel(uint16_t channel) { this->channel_ = channel; } protected: void write_state(float state) override; - uint8_t channel_; + uint16_t channel_; }; } // namespace tlc5971 From b307c7c74ca18922b4580e7344f5b6a4a354a371 Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:44:52 +1200 Subject: [PATCH 2029/2030] [config_validation] Add unbounded percentage validators (#15500) --- esphome/config_validation.py | 65 ++++++--- tests/unit_tests/test_config_validation.py | 149 +++++++++++++++++++++ 2 files changed, 197 insertions(+), 17 deletions(-) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 7805de98db..b0bd9e6231 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -1468,17 +1468,53 @@ hex_uint64_t = hex_int_range(min=0, max=18446744073709551615) i2c_address = hex_uint8_t -def percentage(value): +def percentage(value: object) -> float: """Validate that the value is a percentage. - The resulting value is an integer in the range 0.0 to 1.0. + The resulting value is a float in the range 0.0 to 1.0. """ - value = possibly_negative_percentage(value) + value = _parse_percentage(value) return zero_to_one_float(value) -def possibly_negative_percentage(value): - has_percent_sign = False +def possibly_negative_percentage(value: object) -> float: + """Validate that the value is a possibly negative percentage. + + The resulting value is a float in the range -1.0 to 1.0. + """ + value = _parse_percentage(value) + return negative_one_to_one_float(value) + + +def unbounded_percentage(value: object) -> float: + """Validate that the value is a percentage, allowing values above 100%. + + The resulting value is a non-negative float with no upper bound. + For example, "150%" returns 1.5 and "50%" returns 0.5. + """ + value = _parse_percentage(value) + if value < 0: + raise Invalid("Percentage must not be negative") + return value + + +def unbounded_possibly_negative_percentage(value: object) -> float: + """Validate that the value is a possibly negative percentage without bounds. + + The resulting value is an unbounded float. + For example, "200%" returns 2.0 and "-150%" returns -1.5. + """ + return _parse_percentage(value) + + +def _parse_percentage(value: object) -> float: + """Parse a percentage string or number into a float. + + Handles both "50%" style strings and raw float values. + Values without a percent sign above 1.0 or below -1.0 are rejected + to prevent user mistakes (e.g. writing 50 instead of 50%). + """ + has_percent_sign: bool = False if isinstance(value, str): try: if value.endswith("%"): @@ -1490,21 +1526,16 @@ def possibly_negative_percentage(value): # pylint: disable=raise-missing-from raise Invalid("invalid number") try: - if value > 1: - msg = "Percentage must not be higher than 100%." - if not has_percent_sign: - msg += " Please put a percent sign after the number!" - raise Invalid(msg) - if value < -1: - msg = "Percentage must not be smaller than -100%." - if not has_percent_sign: - msg += " Please put a percent sign after the number!" - raise Invalid(msg) + if not has_percent_sign and (value > 1 or value < -1): + raise Invalid( + "Percentage value must use a percent sign for values " + "outside -1.0 to 1.0. Please put a percent sign after the number!" + ) except TypeError: raise Invalid( # pylint: disable=raise-missing-from - "Expected percentage or float between -1.0 and 1.0" + "Expected percentage or float" ) - return negative_one_to_one_float(value) + return float(value) def percentage_int(value): diff --git a/tests/unit_tests/test_config_validation.py b/tests/unit_tests/test_config_validation.py index ce941b40dc..ac84ce7cc8 100644 --- a/tests/unit_tests/test_config_validation.py +++ b/tests/unit_tests/test_config_validation.py @@ -616,3 +616,152 @@ def test_validate_entity_name__none_with_friendly_name() -> None: result = config_validation._validate_entity_name("None") assert result is None CORE.friendly_name = None # Reset + + +# --- percentage validators --- + + +@pytest.mark.parametrize( + ("value", "expected"), + ( + ("0%", 0.0), + ("50%", 0.5), + ("100%", 1.0), + (0.0, 0.0), + (0.5, 0.5), + (1.0, 1.0), + ("0.0", 0.0), + ("0.5", 0.5), + ("1.0", 1.0), + ), +) +def test_percentage__valid(value: object, expected: float) -> None: + assert config_validation.percentage(value) == expected + + +@pytest.mark.parametrize( + "value", + ( + "150%", + "-10%", + "-0.1", + "1.1", + 2, + -1, + "foo", + None, + ), +) +def test_percentage__invalid(value: object) -> None: + with pytest.raises(Invalid): + config_validation.percentage(value) + + +@pytest.mark.parametrize( + ("value", "expected"), + ( + ("0%", 0.0), + ("50%", 0.5), + ("100%", 1.0), + ("-50%", -0.5), + ("-100%", -1.0), + (0.0, 0.0), + (0.5, 0.5), + (-0.5, -0.5), + (1.0, 1.0), + (-1.0, -1.0), + ), +) +def test_possibly_negative_percentage__valid(value: object, expected: float) -> None: + assert config_validation.possibly_negative_percentage(value) == expected + + +@pytest.mark.parametrize( + "value", + ( + "150%", + "-150%", + 2, + -2, + "foo", + None, + ), +) +def test_possibly_negative_percentage__invalid(value: object) -> None: + with pytest.raises(Invalid): + config_validation.possibly_negative_percentage(value) + + +@pytest.mark.parametrize( + ("value", "expected"), + ( + ("0%", 0.0), + ("50%", 0.5), + ("100%", 1.0), + ("150%", 1.5), + ("200%", 2.0), + (0.0, 0.0), + (0.5, 0.5), + (1.0, 1.0), + ), +) +def test_unbounded_percentage__valid(value: object, expected: float) -> None: + assert config_validation.unbounded_percentage(value) == expected + + +@pytest.mark.parametrize( + "value", + ( + "-10%", + "-0.5", + -1, + "foo", + None, + ), +) +def test_unbounded_percentage__invalid(value: object) -> None: + with pytest.raises(Invalid): + config_validation.unbounded_percentage(value) + + +@pytest.mark.parametrize( + ("value", "expected"), + ( + ("0%", 0.0), + ("50%", 0.5), + ("150%", 1.5), + ("-50%", -0.5), + ("-150%", -1.5), + ("200%", 2.0), + ("-200%", -2.0), + (0.0, 0.0), + (0.5, 0.5), + (-0.5, -0.5), + (1.0, 1.0), + (-1.0, -1.0), + ), +) +def test_unbounded_possibly_negative_percentage__valid( + value: object, expected: float +) -> None: + assert config_validation.unbounded_possibly_negative_percentage(value) == expected + + +@pytest.mark.parametrize("value", ("foo", None)) +def test_unbounded_possibly_negative_percentage__invalid(value: object) -> None: + with pytest.raises(Invalid): + config_validation.unbounded_possibly_negative_percentage(value) + + +@pytest.mark.parametrize( + "value", + (50, -50, 2, -2), +) +def test_percentage_validators__raw_number_above_one_without_percent_sign( + value: object, +) -> None: + """Raw numeric values outside [-1, 1] must use a percent sign.""" + with pytest.raises(Invalid, match="percent sign"): + config_validation.unbounded_percentage(value) + with pytest.raises(Invalid, match="percent sign"): + config_validation.unbounded_possibly_negative_percentage(value) From 801f3fadaa266acac82e29dcc3060d576431f947 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Wed, 8 Apr 2026 11:00:39 +1000 Subject: [PATCH 2030/2030] [epaper_spi] Fix deep sleep command (#15544) --- esphome/components/epaper_spi/epaper_spi.h | 8 +++++--- esphome/components/epaper_spi/epaper_spi_mono.cpp | 14 +++++++++++++- tests/components/epaper_spi/test.esp32-s3-idf.yaml | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/esphome/components/epaper_spi/epaper_spi.h b/esphome/components/epaper_spi/epaper_spi.h index 47b4f9f72d..2992ca5afd 100644 --- a/esphome/components/epaper_spi/epaper_spi.h +++ b/esphome/components/epaper_spi/epaper_spi.h @@ -110,12 +110,14 @@ class EPaperBase : public Display, this->fill(COLOR_ON); } - protected: - int get_height_internal() override { return this->height_; }; - int get_width_internal() override { return this->width_; }; int get_width() override { return this->effective_transform_ & SWAP_XY ? this->height_ : this->width_; } int get_height() override { return this->effective_transform_ & SWAP_XY ? this->width_ : this->height_; } void draw_pixel_at(int x, int y, Color color) override; + + protected: + int get_height_internal() override { return this->height_; }; + int get_width_internal() override { return this->width_; }; + bool is_using_partial_update_() const { return this->full_update_every_ > 1; } void process_state_(); const char *epaper_state_to_string_(); diff --git a/esphome/components/epaper_spi/epaper_spi_mono.cpp b/esphome/components/epaper_spi/epaper_spi_mono.cpp index d10022c4ac..ee117304c4 100644 --- a/esphome/components/epaper_spi/epaper_spi_mono.cpp +++ b/esphome/components/epaper_spi/epaper_spi_mono.cpp @@ -15,7 +15,11 @@ void EPaperMono::refresh_screen(bool partial) { void EPaperMono::deep_sleep() { ESP_LOGV(TAG, "Deep sleep"); - this->command(0x10); + if (this->is_using_partial_update_()) { + this->cmd_data(0x10, {0x00}); // sleep in power on mode + } else { + this->cmd_data(0x10, {0x03}); // deep sleep + } } bool EPaperMono::reset() { @@ -27,6 +31,14 @@ bool EPaperMono::reset() { } void EPaperMono::set_window() { + // if not using partial update, the display will go into deep sleep, so must rewrite entire + // buffer since the display RAM will not retain contents + if (!this->is_using_partial_update_()) { + this->x_low_ = 0; + this->x_high_ = this->width_; + this->y_low_ = 0; + this->y_high_ = this->height_; + } // round x-coordinates to byte boundaries this->x_low_ &= ~7; this->x_high_ += 7; diff --git a/tests/components/epaper_spi/test.esp32-s3-idf.yaml b/tests/components/epaper_spi/test.esp32-s3-idf.yaml index 9593d0f6f0..bf6053c78b 100644 --- a/tests/components/epaper_spi/test.esp32-s3-idf.yaml +++ b/tests/components/epaper_spi/test.esp32-s3-idf.yaml @@ -78,6 +78,7 @@ display: model: seeed-reterminal-e1002 - platform: epaper_spi model: seeed-ee04-mono-4.26 + full_update_every: 10 # Override pins to avoid conflict with other display configs busy_pin: 43 dc_pin: 42